diff --git a/.ci/generate-buildkite-pipeline-premerge b/.ci/generate-buildkite-pipeline-premerge index 4ebf304e23d5875c23d626984d17fb1ed5004a0f..2e503c867403bcf6fc56f6eed024229b82a0cc1d 100755 --- a/.ci/generate-buildkite-pipeline-premerge +++ b/.ci/generate-buildkite-pipeline-premerge @@ -68,7 +68,7 @@ function compute-projects-to-test() { done ;; clang) - for p in clang-tools-extra compiler-rt flang libc lldb openmp cross-project-tests; do + for p in clang-tools-extra compiler-rt flang lldb cross-project-tests; do echo $p done ;; @@ -224,7 +224,7 @@ fi # needs while letting them run on the infrastructure provided by LLVM. # Figure out which projects need to be built on each platform -all_projects="bolt clang-tools-extra compiler-rt cross-project-tests flang libc libclc lld lldb llvm mlir openmp polly pstl" +all_projects="bolt clang clang-tools-extra compiler-rt cross-project-tests flang libc libclc lld lldb llvm mlir openmp polly pstl" modified_projects="$(keep-modified-projects ${all_projects})" linux_projects_to_test=$(exclude-linux $(compute-projects-to-test ${modified_projects})) diff --git a/.ci/monolithic-linux.sh b/.ci/monolithic-linux.sh index 9e670c447fbaddc82106905b60927fc2c5c883db..b347c443da677fd530afb91936a9605ec1218b2b 100755 --- a/.ci/monolithic-linux.sh +++ b/.ci/monolithic-linux.sh @@ -18,7 +18,7 @@ set -o pipefail MONOREPO_ROOT="${MONOREPO_ROOT:="$(git rev-parse --show-toplevel)"}" BUILD_DIR="${BUILD_DIR:=${MONOREPO_ROOT}/build}" -rm -rf ${BUILD_DIR} +rm -rf "${BUILD_DIR}" ccache --zero-stats @@ -37,8 +37,8 @@ projects="${1}" targets="${2}" echo "--- cmake" -pip install -q -r ${MONOREPO_ROOT}/mlir/python/requirements.txt -cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \ +pip install -q -r "${MONOREPO_ROOT}"/mlir/python/requirements.txt +cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \ -D LLVM_ENABLE_PROJECTS="${projects}" \ -G Ninja \ -D CMAKE_BUILD_TYPE=Release \ diff --git a/.ci/monolithic-windows.sh b/.ci/monolithic-windows.sh index 52ba13036f915983e97ad1149ffc40ee51a4c24e..4fd88ea81c84a8e2c2e1201b5593e4305ed28b09 100755 --- a/.ci/monolithic-windows.sh +++ b/.ci/monolithic-windows.sh @@ -19,7 +19,7 @@ set -o pipefail MONOREPO_ROOT="${MONOREPO_ROOT:="$(git rev-parse --show-toplevel)"}" BUILD_DIR="${BUILD_DIR:=${MONOREPO_ROOT}/build}" -rm -rf ${BUILD_DIR} +rm -rf "${BUILD_DIR}" if [[ -n "${CLEAR_CACHE:-}" ]]; then echo "clearing sccache" @@ -37,14 +37,14 @@ projects="${1}" targets="${2}" echo "--- cmake" -pip install -q -r ${MONOREPO_ROOT}/mlir/python/requirements.txt +pip install -q -r "${MONOREPO_ROOT}"/mlir/python/requirements.txt # The CMAKE_*_LINKER_FLAGS to disable the manifest come from research # on fixing a build reliability issue on the build server, please # see https://github.com/llvm/llvm-project/pull/82393 and # https://discourse.llvm.org/t/rfc-future-of-windows-pre-commit-ci/76840/40 # for further information. -cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \ +cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \ -D LLVM_ENABLE_PROJECTS="${projects}" \ -G Ninja \ -D CMAKE_BUILD_TYPE=Release \ diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 85850848b220c4e61b447dc022657065bb914ab1..76b8266cae87c4b0b3fbf90e4bf72626aad7c9f3 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -32,6 +32,9 @@ /clang/www/cxx_dr_status.html @Endilll /clang/www/make_cxx_dr_status @Endilll +clang/lib/AST/Interp/ @tbaederr +clang/test/AST/Interp/ @tbaederr + /lldb/ @JDevlieghere # MLIR Interfaces. @@ -56,8 +59,8 @@ /mlir/Dialect/*/Transforms/Bufferize.cpp @matthias-springer # Linalg Dialect in MLIR. -/mlir/include/mlir/Dialect/Linalg @dcaballe @nicolasvasilache -/mlir/lib/Dialect/Linalg @dcaballe @nicolasvasilache +/mlir/include/mlir/Dialect/Linalg/* @dcaballe @nicolasvasilache +/mlir/lib/Dialect/Linalg/* @dcaballe @nicolasvasilache /mlir/lib/Dialect/Linalg/Transforms/DecomposeLinalgOps.cpp @MaheshRavishankar @nicolasvasilache /mlir/lib/Dialect/Linalg/Transforms/DropUnitDims.cpp @MaheshRavishankar @nicolasvasilache /mlir/lib/Dialect/Linalg/Transforms/ElementwiseOpFusion.cpp @MaheshRavishankar @nicolasvasilache @@ -74,14 +77,14 @@ /mlir/**/*SME* @banach-space @dcaballe @nicolasvasilache /mlir/**/*SVE* @banach-space @dcaballe @nicolasvasilache /mlir/**/*VectorInterfaces* @dcaballe @nicolasvasilache -/mlir/**/*VectorToSCF* @banach-space @dcaballe @nicolasvasilache @matthias-springer +/mlir/**/*VectorToSCF* @banach-space @dcaballe @matthias-springer @nicolasvasilache /mlir/**/*VectorToLLVM* @banach-space @dcaballe @nicolasvasilache /mlir/**/*X86Vector* @aartbik @dcaballe @nicolasvasilache -/mlir/include/mlir/Dialect/Vector @dcaballe @nicolasvasilache -/mlir/lib/Dialect/Vector @dcaballe @nicolasvasilache -/mlir/lib/Dialect/Vector/Transforms/VectorEmulateNarrowType.cpp @MaheshRavishankar @nicolasvasilache -/mlir/**/*EmulateNarrowType* @hanhanW +/mlir/include/mlir/Dialect/Vector/* @dcaballe @nicolasvasilache +/mlir/lib/Dialect/Vector/* @dcaballe @nicolasvasilache /mlir/lib/Dialect/Vector/Transforms/* @hanhanW @nicolasvasilache +/mlir/lib/Dialect/Vector/Transforms/VectorEmulateNarrowType.cpp @MaheshRavishankar @nicolasvasilache +/mlir/**/*EmulateNarrowType* @dcaballe @hanhanW # Presburger library in MLIR /mlir/**/*Presburger* @Groverkss @Superty @@ -93,6 +96,7 @@ # Transform Dialect in MLIR. /mlir/include/mlir/Dialect/Transform/* @ftynse @nicolasvasilache /mlir/lib/Dialect/Transform/* @ftynse @nicolasvasilache +/mlir/**/*TransformOps* @ftynse @nicolasvasilache # SPIR-V Dialect in MLIR. /mlir/**/SPIRV/ @antiagainst @kuhar @@ -103,5 +107,24 @@ # MLIR Sparsifier. /mlir/**/*SparseTensor*/ @aartbik @PeimingLiu @yinying-lisa-li @matthias-springer +# MLIR NVGPU Dialect +/mlir/**/NVGPU*/ @grypp +/mlir/test/**/CUDA/ @grypp + +# MLIR NVVM Dialect in MLIR +/mlir/**/LLVMIR/**/BasicPtxBuilderInterface* @grypp +/mlir/**/NVVM*/ @grypp + # BOLT /bolt/ @aaupov @maksfb @rafaelauler @ayermolo @dcci + +# Bazel build system. +/utils/bazel/ @rupprecht + +# InstallAPI and TextAPI +/llvm/**/TextAPI/ @cyndyishida +/clang/**/InstallAPI/ @cyndyishida +/clang/tools/clang-installapi/ @cyndyishida + +# ExtractAPI +/clang/**/ExtractAPI @daniel-grumberg diff --git a/.github/new-prs-labeler.yml b/.github/new-prs-labeler.yml index 9a580c6d6984e105fbc9b3516d99c72896fa888f..a0428336d300f9ac3d4eaff2f2daf4100e4ccdfc 100644 --- a/.github/new-prs-labeler.yml +++ b/.github/new-prs-labeler.yml @@ -629,6 +629,8 @@ backend:DirectX: - '**/*DirectX*/**' - '**/*DXIL*/**' - '**/*dxil*/**' + - '**/*DXContainer*' + - '**/*DXContainer*/**' backend:SPIR-V: - clang/lib/Driver/ToolChains/SPIRV.* @@ -933,3 +935,6 @@ openmp:libomp: openmp:libomptarget: - any: ['openmp/**', '!openmp/runtime/**'] + +bazel: + - utils/bazel/** diff --git a/.github/workflows/email-check.yaml b/.github/workflows/email-check.yaml index ac53b5e527b0949020e0e73d90def5d2b6295cd0..8f32d020975f5d70e7eead9c34a0ea86fb836e81 100644 --- a/.github/workflows/email-check.yaml +++ b/.github/workflows/email-check.yaml @@ -1,7 +1,7 @@ name: "Check for private emails used in PRs" on: - pull_request_target: + pull_request: types: - opened @@ -10,8 +10,6 @@ permissions: jobs: validate_email: - permissions: - pull-requests: write runs-on: ubuntu-latest if: github.repository == 'llvm/llvm-project' steps: @@ -25,20 +23,24 @@ jobs: run: | git log -1 echo "EMAIL=$(git show -s --format='%ae' HEAD~0)" >> $GITHUB_OUTPUT + # Create empty comment file + echo "[]" > comments - name: Validate author email if: ${{ endsWith(steps.author.outputs.EMAIL, 'noreply.github.com') }} - uses: actions/github-script@v6 env: - EMAIL: ${{ steps.author.outputs.EMAIL }} + COMMENT: >- + ⚠️ We detected that you are using a GitHub private e-mail address to contribute to the repo.
+ Please turn off [Keep my email addresses private](https://github.com/settings/emails) setting in your account.
+ See [LLVM Discourse](https://discourse.llvm.org/t/hidden-emails-on-github-should-we-do-something-about-it) for more information. + run: | + cat << EOF > comments + [{"body" : "$COMMENT"}] + EOF + + - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0 + if: always() with: - script: | - const { EMAIL } = process.env - await github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: `⚠️ We detected that you are using a GitHub private e-mail address to contribute to the repo. - Please turn off [Keep my email addresses private](https://github.com/settings/emails) setting in your account. - See [LLVM Discourse](https://discourse.llvm.org/t/hidden-emails-on-github-should-we-do-something-about-it) for more information. - `}) + name: workflow-args + path: | + comments diff --git a/.github/workflows/issue-write.yml b/.github/workflows/issue-write.yml new file mode 100644 index 0000000000000000000000000000000000000000..e003be006c4e15405bd977e277b0f9a64e69d2af --- /dev/null +++ b/.github/workflows/issue-write.yml @@ -0,0 +1,139 @@ +name: Comment on an issue + +on: + workflow_run: + workflows: + - "Check code formatting" + - "Check for private emails used in PRs" + types: + - completed + +permissions: + contents: read + +jobs: + pr-comment: + runs-on: ubuntu-latest + permissions: + pull-requests: write + if: > + github.event.workflow_run.event == 'pull_request' + steps: + - name: 'Download artifact' + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + with: + github-token: ${{ secrets.ISSUE_WRITE_DOWNLOAD_ARTIFACT }} + run-id: ${{ github.event.workflow_run.id }} + name: workflow-args + + - name: 'Comment on PR' + uses: actions/github-script@v3 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + var fs = require('fs'); + const comments = JSON.parse(fs.readFileSync('./comments')); + if (!comments || comments.length == 0) { + return; + } + + let runInfo = await github.actions.getWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id + }); + + console.log(runInfo); + + + // Query to find the number of the pull request that triggered this job. + // The associated pull requests are based off of the branch name, so if + // you create a pull request for a branch, close it, and then create + // another pull request with the same branch, then this query will return + // two associated pull requests. This is why we have to fetch all the + // associated pull requests and then iterate through them to find the + // one that is open. + const gql_query = ` + query($repo_owner : String!, $repo_name : String!, $branch: String!) { + repository(owner: $repo_owner, name: $repo_name) { + ref (qualifiedName: $branch) { + associatedPullRequests(first: 100) { + nodes { + baseRepository { + owner { + login + } + } + number + state + } + } + } + } + } + ` + const gql_variables = { + repo_owner: runInfo.data.head_repository.owner.login, + repo_name: runInfo.data.head_repository.name, + branch: runInfo.data.head_branch + } + const gql_result = await github.graphql(gql_query, gql_variables); + console.log(gql_result); + // If the branch for the PR was deleted before this job has a chance + // to run, then the ref will be null. This can happen if someone: + // 1. Rebase the PR, which triggers some workflow. + // 2. Immediately merges the PR and deletes the branch. + // 3. The workflow finishes and triggers this job. + if (!gql_result.repository.ref) { + console.log("Ref has been deleted"); + return; + } + console.log(gql_result.repository.ref.associatedPullRequests.nodes); + + var pr_number = 0; + gql_result.repository.ref.associatedPullRequests.nodes.forEach((pr) => { + if (pr.baseRepository.owner.login = context.repo.owner && pr.state == 'OPEN') { + pr_number = pr.number; + } + }); + if (pr_number == 0) { + console.log("Error retrieving pull request number"); + return; + } + + await comments.forEach(function (comment) { + if (comment.id) { + // Security check: Ensure that this comment was created by + // the github-actions bot, so a malicious input won't overwrite + // a user's comment. + github.issues.getComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: comment.id + }).then((old_comment) => { + console.log(old_comment); + if (old_comment.data.user.login != "github-actions[bot]") { + console.log("Invalid comment id: " + comment.id); + return; + } + github.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr_number, + comment_id: comment.id, + body: comment.body + }); + }); + } else { + github.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr_number, + body: comment.body + }); + } + }); + + - name: Dump comments file + if: always() + run: cat comments diff --git a/.github/workflows/llvm-project-tests.yml b/.github/workflows/llvm-project-tests.yml index 43b90193406fc96983e9a73675fc322f1280c70e..a52dd2db8035ddce07a606268f6472f552841f5c 100644 --- a/.github/workflows/llvm-project-tests.yml +++ b/.github/workflows/llvm-project-tests.yml @@ -118,6 +118,11 @@ jobs: else builddir="$(pwd)"/build fi + if [ "${{ runner.os }}" == "macOS" ]; then + # Workaround test failure on some lld tests on MacOS + # https://github.com/llvm/llvm-project/issues/81967 + extra_cmake_args="-DLLVM_DISABLE_ASSEMBLY_FILES=ON" + fi echo "llvm-builddir=$builddir" >> "$GITHUB_OUTPUT" cmake -G Ninja \ -B "$builddir" \ diff --git a/.github/workflows/llvm-tests.yml b/.github/workflows/llvm-tests.yml index 127628d76f1913ff91bf5f37bec347d75cfed084..64d60bc3da45e1ec42c158f5d316e48cfd7d6229 100644 --- a/.github/workflows/llvm-tests.yml +++ b/.github/workflows/llvm-tests.yml @@ -42,6 +42,7 @@ jobs: BASELINE_REF: ${{ steps.vars.outputs.BASELINE_REF }} ABI_HEADERS: ${{ steps.vars.outputs.ABI_HEADERS }} BASELINE_VERSION_MAJOR: ${{ steps.vars.outputs.BASELINE_VERSION_MAJOR }} + BASELINE_VERSION_MINOR: ${{ steps.vars.outputs.BASELINE_VERSION_MINOR }} LLVM_VERSION_MAJOR: ${{ steps.version.outputs.LLVM_VERSION_MAJOR }} LLVM_VERSION_MINOR: ${{ steps.version.outputs.LLVM_VERSION_MINOR }} LLVM_VERSION_PATCH: ${{ steps.version.outputs.LLVM_VERSION_PATCH }} @@ -58,7 +59,14 @@ jobs: - name: Setup Variables id: vars run: | - if [ ${{ steps.version.outputs.LLVM_VERSION_MINOR }} -ne 0 ] || [ ${{ steps.version.outputs.LLVM_VERSION_PATCH }} -eq 0 ]; then + # C++ ABI: + # 18.1.0 we aren't doing ABI checks. + # 18.1.1 We want to check 18.1.0. + # C ABI: + # 18.1.0 We want to check 17.0.x + # 18.1.1 We want to check 18.1.0 + echo "BASELINE_VERSION_MINOR=1" >> "$GITHUB_OUTPUT" + if [ ${{ steps.version.outputs.LLVM_VERSION_PATCH }} -eq 0 ]; then { echo "BASELINE_VERSION_MAJOR=$(( ${{ steps.version.outputs.LLVM_VERSION_MAJOR }} - 1))" echo "ABI_HEADERS=llvm-c" @@ -82,7 +90,7 @@ jobs: include: - name: build-baseline llvm_version_major: ${{ needs.abi-dump-setup.outputs.BASELINE_VERSION_MAJOR }} - ref: llvmorg-${{ needs.abi-dump-setup.outputs.BASELINE_VERSION_MAJOR }}.0.0 + ref: llvmorg-${{ needs.abi-dump-setup.outputs.BASELINE_VERSION_MAJOR }}.${{ needs.abi-dump-setup.outputs.BASELINE_VERSION_MINOR }}.0 repo: llvm/llvm-project - name: build-latest llvm_version_major: ${{ needs.abi-dump-setup.outputs.LLVM_VERSION_MAJOR }} diff --git a/.github/workflows/pr-code-format.yml b/.github/workflows/pr-code-format.yml index 3d0c23917bd403007ccd102787546793b8bfa36a..10b18f245d8965a69251038f44f1505fc40c0cf0 100644 --- a/.github/workflows/pr-code-format.yml +++ b/.github/workflows/pr-code-format.yml @@ -1,12 +1,9 @@ name: "Check code formatting" on: - pull_request_target: + pull_request: branches: - main -permissions: - pull-requests: write - jobs: code_formatter: runs-on: ubuntu-latest @@ -31,12 +28,13 @@ jobs: separator: "," skip_initial_fetch: true - # We need to make sure that we aren't executing/using any code from the - # PR for security reasons as we're using pull_request_target. Checkout - # the target branch with the necessary files. + # We need to pull the script from the main branch, so that we ensure + # we get the latest version of this script. - name: Fetch code formatting utils uses: actions/checkout@v4 with: + repository: ${{ github.repository }} + ref: ${{ github.base_ref }} sparse-checkout: | llvm/utils/git/requirements_formatting.txt llvm/utils/git/code-format-helper.py @@ -53,7 +51,7 @@ jobs: - name: Install clang-format uses: aminya/setup-cpp@v1 with: - clangformat: 17.0.1 + clangformat: 18.1.1 - name: Setup Python env uses: actions/setup-python@v4 @@ -75,10 +73,20 @@ jobs: # to take advantage of the new --diff_from_common_commit option # explicitly in code-format-helper.py and not have to diff starting at # the merge base. + # Create an empty comments file so the pr-write job doesn't fail. run: | + echo "[]" > comments && python ./code-format-tools/llvm/utils/git/code-format-helper.py \ + --write-comment-to-file \ --token ${{ secrets.GITHUB_TOKEN }} \ --issue-number $GITHUB_PR_NUMBER \ --start-rev $(git merge-base $START_REV $END_REV) \ --end-rev $END_REV \ --changed-files "$CHANGED_FILES" + + - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0 + if: always() + with: + name: workflow-args + path: | + comments diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index b8e8ab26c3ffa61a1f3a76883034564086d1d237..ff61cf83a6af3c816e7fa4b0a55fa26f3d1471e4 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -36,7 +36,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86 # v2.1.2 + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 with: results_file: results.sarif results_format: sarif diff --git a/bolt/CMakeLists.txt b/bolt/CMakeLists.txt index f163d45342874d0e8dd2a64a292e735ddf3cd626..cc3a70fa35e0ab1c5a5029bea080a363eebdbd0c 100644 --- a/bolt/CMakeLists.txt +++ b/bolt/CMakeLists.txt @@ -45,9 +45,9 @@ if (BOLT_ENABLE_RUNTIME) execute_process(COMMAND ls /proc/self/map_files RESULT_VARIABLE LS OUTPUT_QUIET ERROR_QUIET) if (LS) - set(BOLT_ENABLE_RUNTIME OFF) message(WARNING - "BOLT runtime is disabled as /proc/self/map_files is unreadable.") + "BOLT runtime may not be able to read /proc/self/map_files. Please use + `--instrumentation-binpath ` option.") endif() endif() diff --git a/bolt/docs/BAT.md b/bolt/docs/BAT.md index d1cab984d14834242836622ed4f5b448e887723c..f23ef1abf8761cc58fc2249ef0da43ae0034e114 100644 --- a/bolt/docs/BAT.md +++ b/bolt/docs/BAT.md @@ -14,9 +14,8 @@ binary onto the original binary. # Usage `--enable-bat` flag controls the generation of BAT section. Sampled profile needs to be passed along with the optimized binary containing BAT section to -`perf2bolt` which reads BAT section and produces fdata profile for the original -binary. Note that YAML profile generation is not supported since BAT doesn't -contain the metadata for input functions. +`perf2bolt` which reads BAT section and produces profile for the original +binary. # Internals ## Section contents @@ -43,21 +42,21 @@ and [BoltAddressTranslation.cpp](/bolt/lib/Profile/BoltAddressTranslation.cpp). ### Layout The general layout is as follows: ``` -Hot functions table header -|------------------| -| Function entry | -| |--------------| | -| | OutOff InOff | | -| |--------------| | -~~~~~~~~~~~~~~~~~~~~ +Hot functions table +Cold functions table -Cold functions table header +Functions table: |------------------| | Function entry | -| |--------------| | -| | OutOff InOff | | -| |--------------| | -~~~~~~~~~~~~~~~~~~~~ +| | +| Address | +| translation | +| table | +| | +| Secondary entry | +| points | +|------------------| + ``` ### Functions table @@ -75,28 +74,43 @@ internal offsets, and between hot and cold fragments, to better spread deltas and save space. Hot indices are delta encoded, implicitly starting at zero. -| Entry | Encoding | Description | -| ------ | ------| ----------- | -| `Address` | Continuous, Delta, ULEB128 | Function address in the output binary | -| `HotIndex` | Delta, ULEB128 | Cold functions only: index of corresponding hot function in hot functions table | -| `NumEntries` | ULEB128 | Number of address translation entries for a function | -| `EqualElems` | ULEB128 | Hot functions only: number of equal offsets in the beginning of a function | -| `BranchEntries` | Bitmask, `alignTo(EqualElems, 8)` bits | Hot functions only: if `EqualElems` is non-zero, bitmask denoting entries with `BRANCHENTRY` bit | +| Entry | Encoding | Description | Hot/Cold | +| ------ | ------| ----------- | ------ | +| `Address` | Continuous, Delta, ULEB128 | Function address in the output binary | Both | +| `HotIndex` | Delta, ULEB128 | Index of corresponding hot function in hot functions table | Cold | +| `FuncHash` | 8b | Function hash for input function | Hot | +| `NumBlocks` | ULEB128 | Number of basic blocks in the original function | Hot | +| `NumSecEntryPoints` | ULEB128 | Number of secondary entry points in the original function | Hot | +| `NumEntries` | ULEB128 | Number of address translation entries for a function | Both | +| `EqualElems` | ULEB128 | Number of equal offsets in the beginning of a function | Hot | +| `BranchEntries` | Bitmask, `alignTo(EqualElems, 8)` bits | If `EqualElems` is non-zero, bitmask denoting entries with `BRANCHENTRY` bit | Hot | -Function header is followed by `EqualElems` offsets (hot functions only) and -`NumEntries-EqualElems` (`NumEntries` for cold functions) pairs of offsets for -current function. +Function header is followed by *Address Translation Table* with `NumEntries` +total entries, and *Secondary Entry Points* table with `NumSecEntryPoints` +entries (hot functions only). ### Address translation table Delta encoding means that only the difference with the previous corresponding entry is encoded. Input offsets implicitly start at zero. -| Entry | Encoding | Description | -| ------ | ------| ----------- | -| `OutputOffset` | Continuous, Delta, ULEB128 | Function offset in output binary | -| `InputOffset` | Optional, Delta, SLEB128 | Function offset in input binary with `BRANCHENTRY` LSB bit | +| Entry | Encoding | Description | Branch/BB | +| ------ | ------| ----------- | ------ | +| `OutputOffset` | Continuous, Delta, ULEB128 | Function offset in output binary | Both | +| `InputOffset` | Optional, Delta, SLEB128 | Function offset in input binary with `BRANCHENTRY` LSB bit | Both | +| `BBHash` | Optional, 8b | Basic block hash in input binary | BB | +| `BBIdx` | Optional, Delta, ULEB128 | Basic block index in input binary | BB | + +For hot fragments, the table omits the first `EqualElems` input offsets +where the input offset equals output offset. `BRANCHENTRY` bit denotes whether a given offset pair is a control flow source (branch or call instruction). If not set, it signifies a control flow target (basic block offset). `InputAddr` is omitted for equal offsets in input and output function. In this case, `BRANCHENTRY` bits are encoded separately in a `BranchEntries` bitvector. + +### Secondary Entry Points table +The table is emitted for hot fragments only. It contains `NumSecEntryPoints` +offsets denoting secondary entry points, delta encoded, implicitly starting at zero. +| Entry | Encoding | Description | +| ----- | -------- | ----------- | +| `SecEntryPoint` | Delta, ULEB128 | Secondary entry point offset | diff --git a/bolt/include/bolt/Core/AddressMap.h b/bolt/include/bolt/Core/AddressMap.h index 85a9ab4473aafedd192145acaa334208e22ac6e6..31ed7d40ee7f215586e53a6b285f492c898ab765 100644 --- a/bolt/include/bolt/Core/AddressMap.h +++ b/bolt/include/bolt/Core/AddressMap.h @@ -14,7 +14,6 @@ #ifndef BOLT_CORE_ADDRESS_MAP_H #define BOLT_CORE_ADDRESS_MAP_H -#include "llvm/ADT/StringRef.h" #include "llvm/MC/MCSymbol.h" #include diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h index 741b1a36af86f871bb51430686ff229ce2e1d1b8..8b1af9e8153925760985efcb954e87a046b2c1f2 100644 --- a/bolt/include/bolt/Core/BinaryContext.h +++ b/bolt/include/bolt/Core/BinaryContext.h @@ -265,7 +265,8 @@ class BinaryContext { public: static Expected> - createBinaryContext(const ObjectFile *File, bool IsPIC, + createBinaryContext(Triple TheTriple, StringRef InputFileName, + SubtargetFeatures *Features, bool IsPIC, std::unique_ptr DwCtx, JournalingStreams Logger); diff --git a/bolt/include/bolt/Core/BinaryData.h b/bolt/include/bolt/Core/BinaryData.h index 5f1efda781905db66ec18e16a3263a88c5f0816f..495163f1b61aafd2360b9699fcda4f95844f1dd3 100644 --- a/bolt/include/bolt/Core/BinaryData.h +++ b/bolt/include/bolt/Core/BinaryData.h @@ -18,7 +18,6 @@ #include "llvm/ADT/Twine.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/raw_ostream.h" -#include #include #include diff --git a/bolt/include/bolt/Core/BinaryDomTree.h b/bolt/include/bolt/Core/BinaryDomTree.h index a9565795f94631b25c6674eb699b78e9f9d5bffd..de27aa78769d23398eaf97177ad316abf3e09798 100644 --- a/bolt/include/bolt/Core/BinaryDomTree.h +++ b/bolt/include/bolt/Core/BinaryDomTree.h @@ -16,7 +16,6 @@ #include "bolt/Core/BinaryBasicBlock.h" #include "llvm/IR/Dominators.h" -#include "llvm/Support/GenericDomTreeConstruction.h" namespace llvm { namespace bolt { diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h index c170fa6397cc927293f539391ea5a29b7389a7be..bc047fefa3151c9d32050e71ed3d182005665923 100644 --- a/bolt/include/bolt/Core/BinaryFunction.h +++ b/bolt/include/bolt/Core/BinaryFunction.h @@ -27,6 +27,7 @@ #include "bolt/Core/BinaryBasicBlock.h" #include "bolt/Core/BinaryContext.h" +#include "bolt/Core/BinaryDomTree.h" #include "bolt/Core/BinaryLoop.h" #include "bolt/Core/BinarySection.h" #include "bolt/Core/DebugData.h" @@ -51,7 +52,6 @@ #include #include #include -#include #include #include @@ -266,6 +266,7 @@ private: BinaryContext &BC; std::unique_ptr BLI; + std::unique_ptr BDT; /// All labels in the function that are referenced via relocations from /// data objects. Typically these are jump table destinations and computed @@ -838,6 +839,14 @@ public: /// stats. void calculateMacroOpFusionStats(); + /// Returns if BinaryDominatorTree has been constructed for this function. + bool hasDomTree() const { return BDT != nullptr; } + + BinaryDominatorTree &getDomTree() { return *BDT.get(); } + + /// Constructs DomTree for this function. + void constructDomTree(); + /// Returns if loop detection has been run for this function. bool hasLoopInfo() const { return BLI != nullptr; } @@ -1159,7 +1168,7 @@ public: /// Pass an offset of the entry point in the input binary and a corresponding /// global symbol to the callback function. /// - /// Return true of all callbacks returned true, false otherwise. + /// Return true if all callbacks returned true, false otherwise. bool forEachEntryPoint(EntryPointCallbackTy Callback) const; /// Return MC symbol associated with the end of the function. diff --git a/bolt/include/bolt/Core/BinaryLoop.h b/bolt/include/bolt/Core/BinaryLoop.h index 72dce77df8c14b970023a59b82180f6bc2bb1633..b425c75715d8b1d02e66655d8ff7e4d9115fffdd 100644 --- a/bolt/include/bolt/Core/BinaryLoop.h +++ b/bolt/include/bolt/Core/BinaryLoop.h @@ -15,7 +15,7 @@ #ifndef BOLT_CORE_BINARY_LOOP_H #define BOLT_CORE_BINARY_LOOP_H -#include "llvm/Support/GenericLoopInfoImpl.h" +#include "llvm/Support/GenericLoopInfo.h" namespace llvm { namespace bolt { diff --git a/bolt/include/bolt/Core/BinarySection.h b/bolt/include/bolt/Core/BinarySection.h index 0f179877bd3df3b4bf7e736d1fc00e4806c9f7d2..5b7a5b08820e6e5190559ce2ad59992c7a998e2a 100644 --- a/bolt/include/bolt/Core/BinarySection.h +++ b/bolt/include/bolt/Core/BinarySection.h @@ -18,7 +18,6 @@ #include "bolt/Core/DebugData.h" #include "bolt/Core/Relocation.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/MachO.h" diff --git a/bolt/include/bolt/Core/DIEBuilder.h b/bolt/include/bolt/Core/DIEBuilder.h index 4debf9363354725d612d6fae03a0f2d0e0cce1e5..06084819ec0b3ab96daa83f071a5594e8d7efcd0 100644 --- a/bolt/include/bolt/Core/DIEBuilder.h +++ b/bolt/include/bolt/Core/DIEBuilder.h @@ -209,7 +209,13 @@ private: void updateReferences(); /// Update the Offset and Size of DIE, populate DebugNames table. - uint32_t finalizeDIEs(DWARFUnit &CU, DIE &Die, uint32_t &CurOffset); + /// Along with current CU, and DIE being processed and the new DIE offset to + /// be updated, it takes in Parents vector that can be empty if this DIE has + /// no parents. + uint32_t + finalizeDIEs(DWARFUnit &CU, DIE &Die, + std::vector> &Parents, + uint32_t &CurOffset); void registerUnit(DWARFUnit &DU, bool NeedSort); diff --git a/bolt/include/bolt/Core/DebugData.h b/bolt/include/bolt/Core/DebugData.h index 7d10b208dc83a22c9eee5d0f5acd538258401e42..166bb3617e57f68448eb662348e2e414ed885b32 100644 --- a/bolt/include/bolt/Core/DebugData.h +++ b/bolt/include/bolt/Core/DebugData.h @@ -27,7 +27,6 @@ #include #include #include -#include #include #include diff --git a/bolt/include/bolt/Core/DebugNames.h b/bolt/include/bolt/Core/DebugNames.h index 84c448aa1354cc866a8c484e11c808724ad4d550..a4fdde7c396ad886e3d8c96bb92d25a657a4a0e1 100644 --- a/bolt/include/bolt/Core/DebugNames.h +++ b/bolt/include/bolt/Core/DebugNames.h @@ -14,7 +14,7 @@ #ifndef BOLT_CORE_DEBUG_NAMES_H #define BOLT_CORE_DEBUG_NAMES_H -#include "DebugData.h" +#include "bolt/Core/DebugData.h" #include "llvm/CodeGen/AccelTable.h" namespace llvm { @@ -36,6 +36,9 @@ public: bool isTU() const { return DWARF5AccelTableData::isTU(); } std::optional getSecondUnitID() const { return SecondUnitID; } + void setPatchOffset(uint64_t PatchOffset) { OffsetVal = PatchOffset; } + uint64_t getPatchOffset() const { return std::get(OffsetVal); } + private: std::optional SecondUnitID; }; @@ -49,10 +52,12 @@ public: Abbrev->~DebugNamesAbbrev(); } /// Add DWARF5 Accelerator table entry. - /// Input is DWARFUnit being processed, DIE that belongs to it, and potential - /// SkeletonCU if the Unit comes from a DWO section. - void addAccelTableEntry(DWARFUnit &Unit, const DIE &Die, - const std::optional &DWOID); + /// Input is DWARFUnit being processed, DIE that belongs to it, potential + /// DWOID if the Unit comes from a DWO section, and potential parent entry. + std::optional + addAccelTableEntry(DWARFUnit &Unit, const DIE &Die, + const std::optional &DWOID, + std::optional &Parent); /// Set current unit being processed. void setCurrentUnit(DWARFUnit &Unit, const uint64_t UnitStartOffset); /// Emit Accelerator table. @@ -63,6 +68,16 @@ public: std::unique_ptr releaseBuffer() { return std::move(FullTableBuffer); } + /// Adds a DIE that is referenced across CUs. + void addCrossCUDie(const DIE *Die) { + CrossCUDies.insert({Die->getOffset(), Die}); + } + /// Returns true if the DIE can generate an entry for a cross cu reference. + /// This only checks TAGs of a DIE because when this is invoked DIE might not + /// be fully constructed. + bool canGenerateEntryWithCrossCUReference( + const DWARFUnit &Unit, const DIE &Die, + const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec); private: BinaryContext &BC; @@ -121,6 +136,9 @@ private: llvm::DenseMap StrCacheToOffsetMap; // Contains DWO ID to CUList Index. llvm::DenseMap CUOffsetsToPatch; + // Contains a map of Entry ID to Entry relative offset. + llvm::DenseMap EntryRelativeOffsets; + llvm::DenseMap CrossCUDies; /// Adds Unit to either CUList, LocalTUList or ForeignTUList. /// Input Unit being processed, and DWO ID if Unit is being processed comes /// from a DWO section. @@ -143,7 +161,7 @@ private: /// Write Entries. void writeEntries(); /// Write an Entry. - void writeEntry(const BOLTDWARF5AccelTableData &Entry); + void writeEntry(BOLTDWARF5AccelTableData &Entry); /// Write augmentation_string for BOLT. void writeAugmentationString(); /// Emit out Header for DWARF5 Accelerator table. diff --git a/bolt/include/bolt/Core/FunctionLayout.h b/bolt/include/bolt/Core/FunctionLayout.h index 2e4c184ba4511ca6836ca9d031014c1f784385f0..b685a99c79c14cccd0e7661ed8a48991c9a53b98 100644 --- a/bolt/include/bolt/Core/FunctionLayout.h +++ b/bolt/include/bolt/Core/FunctionLayout.h @@ -25,7 +25,6 @@ #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" #include -#include namespace llvm { namespace bolt { diff --git a/bolt/include/bolt/Core/MCPlus.h b/bolt/include/bolt/Core/MCPlus.h index b6a9e73f2347e71faa09beb4ae2aad9ff7fc5747..601d709712864ebefce1a4156378b023f564be96 100644 --- a/bolt/include/bolt/Core/MCPlus.h +++ b/bolt/include/bolt/Core/MCPlus.h @@ -14,10 +14,8 @@ #ifndef BOLT_CORE_MCPLUS_H #define BOLT_CORE_MCPLUS_H -#include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" -#include "llvm/Support/Casting.h" #include namespace llvm { @@ -73,6 +71,7 @@ public: kOffset, /// Offset in the function. kLabel, /// MCSymbol pointing to this instruction. kSize, /// Size of the instruction. + kDynamicBranch, /// Jit instruction patched at runtime. kGeneric /// First generic annotation. }; diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h index 6bb76d1b917db3159bfca8cbd3904110486a056b..f7614cf9ac9777be6812e228190cc20c810b4c3d 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -19,6 +19,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCDisassembler/MCSymbolizer.h" #include "llvm/MC/MCExpr.h" @@ -27,6 +28,7 @@ #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/RWMutex.h" @@ -487,10 +489,9 @@ public: llvm_unreachable("not implemented"); } - virtual bool createDirectCall(MCInst &Inst, const MCSymbol *Target, + virtual void createDirectCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx, bool IsTailCall) { llvm_unreachable("not implemented"); - return false; } virtual MCPhysReg getX86R11() const { llvm_unreachable("not implemented"); } @@ -534,9 +535,7 @@ public: return Analysis->isReturn(Inst); } - virtual bool isTerminator(const MCInst &Inst) const { - return Analysis->isTerminator(Inst); - } + virtual bool isTerminator(const MCInst &Inst) const; virtual bool isNoop(const MCInst &Inst) const { llvm_unreachable("not implemented"); @@ -1200,6 +1199,16 @@ public: /// Set instruction size. void setSize(MCInst &Inst, uint32_t Size) const; + /// Check if the branch instruction could be modified at runtime. + bool isDynamicBranch(const MCInst &Inst) const; + + /// Return ID for runtime-modifiable instruction. + std::optional getDynamicBranchID(const MCInst &Inst) const; + + /// Mark instruction as a dynamic branch, i.e. a branch that can be + /// overwritten at runtime. + void setDynamicBranch(MCInst &Inst, uint32_t ID) const; + /// Return MCSymbol that represents a target of this instruction at a given /// operand number \p OpNum. If there's no symbol associated with /// the operand - return nullptr. @@ -1534,15 +1543,13 @@ public: } /// Create a no-op instruction. - virtual bool createNoop(MCInst &Inst) const { + virtual void createNoop(MCInst &Inst) const { llvm_unreachable("not implemented"); - return false; } /// Create a return instruction. - virtual bool createReturn(MCInst &Inst) const { + virtual void createReturn(MCInst &Inst) const { llvm_unreachable("not implemented"); - return false; } /// Store \p Target absolute address to \p RegName @@ -1556,32 +1563,30 @@ public: /// Creates a new unconditional branch instruction in Inst and set its operand /// to TBB. - /// - /// Returns true on success. - virtual bool createUncondBranch(MCInst &Inst, const MCSymbol *TBB, + virtual void createUncondBranch(MCInst &Inst, const MCSymbol *TBB, MCContext *Ctx) const { llvm_unreachable("not implemented"); - return false; + } + + /// Create a version of unconditional jump that has the largest span for a + /// single instruction with direct target. + virtual void createLongUncondBranch(MCInst &Inst, const MCSymbol *Target, + MCContext *Ctx) const { + llvm_unreachable("not implemented"); } /// Creates a new call instruction in Inst and sets its operand to /// Target. - /// - /// Returns true on success. - virtual bool createCall(MCInst &Inst, const MCSymbol *Target, + virtual void createCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx) { llvm_unreachable("not implemented"); - return false; } /// Creates a new tail call instruction in Inst and sets its operand to /// Target. - /// - /// Returns true on success. - virtual bool createTailCall(MCInst &Inst, const MCSymbol *Target, + virtual void createTailCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx) { llvm_unreachable("not implemented"); - return false; } virtual void createLongTailCall(InstructionListType &Seq, @@ -1590,43 +1595,36 @@ public: } /// Creates a trap instruction in Inst. - /// - /// Returns true on success. - virtual bool createTrap(MCInst &Inst) const { + virtual void createTrap(MCInst &Inst) const { llvm_unreachable("not implemented"); - return false; } /// Creates an instruction to bump the stack pointer just like a call. - virtual bool createStackPointerIncrement(MCInst &Inst, int Size = 8, + virtual void createStackPointerIncrement(MCInst &Inst, int Size = 8, bool NoFlagsClobber = false) const { llvm_unreachable("not implemented"); - return false; } /// Creates an instruction to move the stack pointer just like a ret. - virtual bool createStackPointerDecrement(MCInst &Inst, int Size = 8, + virtual void createStackPointerDecrement(MCInst &Inst, int Size = 8, bool NoFlagsClobber = false) const { llvm_unreachable("not implemented"); - return false; } /// Create a store instruction using \p StackReg as the base register /// and \p Offset as the displacement. - virtual bool createSaveToStack(MCInst &Inst, const MCPhysReg &StackReg, + virtual void createSaveToStack(MCInst &Inst, const MCPhysReg &StackReg, int Offset, const MCPhysReg &SrcReg, int Size) const { llvm_unreachable("not implemented"); - return false; } - virtual bool createLoad(MCInst &Inst, const MCPhysReg &BaseReg, int64_t Scale, + virtual void createLoad(MCInst &Inst, const MCPhysReg &BaseReg, int64_t Scale, const MCPhysReg &IndexReg, int64_t Offset, const MCExpr *OffsetExpr, const MCPhysReg &AddrSegmentReg, const MCPhysReg &DstReg, int Size) const { llvm_unreachable("not implemented"); - return false; } virtual InstructionListType createLoadImmediate(const MCPhysReg Dest, @@ -1636,32 +1634,27 @@ public: /// Create a fragment of code (sequence of instructions) that load a 32-bit /// address from memory, zero-extends it to 64 and jump to it (indirect jump). - virtual bool + virtual void createIJmp32Frag(SmallVectorImpl &Insts, const MCOperand &BaseReg, const MCOperand &Scale, const MCOperand &IndexReg, const MCOperand &Offset, const MCOperand &TmpReg) const { llvm_unreachable("not implemented"); - return false; } /// Create a load instruction using \p StackReg as the base register /// and \p Offset as the displacement. - virtual bool createRestoreFromStack(MCInst &Inst, const MCPhysReg &StackReg, + virtual void createRestoreFromStack(MCInst &Inst, const MCPhysReg &StackReg, int Offset, const MCPhysReg &DstReg, int Size) const { llvm_unreachable("not implemented"); - return false; } /// Creates a call frame pseudo instruction. A single operand identifies which /// MCCFIInstruction this MCInst is referring to. - /// - /// Returns true on success. - virtual bool createCFI(MCInst &Inst, int64_t Offset) const { + virtual void createCFI(MCInst &Inst, int64_t Offset) const { Inst.clear(); Inst.setOpcode(TargetOpcode::CFI_INSTRUCTION); Inst.addOperand(MCOperand::createImm(Offset)); - return true; } /// Create an inline version of memcpy(dest, src, 1). @@ -1699,6 +1692,19 @@ public: return Inst.getOpcode() == TargetOpcode::CFI_INSTRUCTION; } + /// Create a conditional branch with a target-specific conditional code \p CC. + virtual void createCondBranch(MCInst &Inst, const MCSymbol *Target, + unsigned CC, MCContext *Ctx) const { + llvm_unreachable("not implemented"); + } + + /// Create long conditional branch with a target-specific conditional code + /// \p CC. + virtual void createLongCondBranch(MCInst &Inst, const MCSymbol *Target, + unsigned CC, MCContext *Ctx) const { + llvm_unreachable("not implemented"); + } + /// Reverses the branch condition in Inst and update its taken target to TBB. /// /// Returns true on success. diff --git a/bolt/include/bolt/Passes/BinaryPasses.h b/bolt/include/bolt/Passes/BinaryPasses.h index 046765b16f19d21b8562440f51c1b0c3c666995e..8d89ef8b5484f8e18d7ea034c3d38df57746760a 100644 --- a/bolt/include/bolt/Passes/BinaryPasses.h +++ b/bolt/include/bolt/Passes/BinaryPasses.h @@ -18,7 +18,6 @@ #include "bolt/Core/DynoStats.h" #include "llvm/Support/CommandLine.h" #include -#include #include #include #include diff --git a/bolt/include/bolt/Passes/CacheMetrics.h b/bolt/include/bolt/Passes/CacheMetrics.h index 5c88d98c76c1d5aa20b386a5398e3ee010867243..ea56d330446b9932bd021ee71be5fc0ad7107829 100644 --- a/bolt/include/bolt/Passes/CacheMetrics.h +++ b/bolt/include/bolt/Passes/CacheMetrics.h @@ -13,7 +13,6 @@ #ifndef BOLT_PASSES_CACHEMETRICS_H #define BOLT_PASSES_CACHEMETRICS_H -#include #include namespace llvm { diff --git a/bolt/include/bolt/Passes/DominatorAnalysis.h b/bolt/include/bolt/Passes/DominatorAnalysis.h index c2b5c3af01472213ef56b994b04866c2a2b7ec1e..3f3afa943c06cefe853113de6e9b29703742f7f7 100644 --- a/bolt/include/bolt/Passes/DominatorAnalysis.h +++ b/bolt/include/bolt/Passes/DominatorAnalysis.h @@ -11,7 +11,6 @@ #include "bolt/Passes/DataflowAnalysis.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/Timer.h" namespace opts { extern llvm::cl::opt TimeOpts; diff --git a/bolt/include/bolt/Passes/ReachingDefOrUse.h b/bolt/include/bolt/Passes/ReachingDefOrUse.h index f38d1a373e18b8de4618bdb2d95362b05d4bea00..585d673e3b84e58431ff074a01b2283315abb7a4 100644 --- a/bolt/include/bolt/Passes/ReachingDefOrUse.h +++ b/bolt/include/bolt/Passes/ReachingDefOrUse.h @@ -11,9 +11,7 @@ #include "bolt/Passes/DataflowAnalysis.h" #include "bolt/Passes/RegAnalysis.h" -#include "llvm/MC/MCRegisterInfo.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/Timer.h" #include namespace opts { diff --git a/bolt/include/bolt/Passes/ReachingInsns.h b/bolt/include/bolt/Passes/ReachingInsns.h index 65782b12064b85848d59b1d7e7d2a06cf03cdba4..ef878f5e452db30f6b4f8e3d5617e4fc285dcf19 100644 --- a/bolt/include/bolt/Passes/ReachingInsns.h +++ b/bolt/include/bolt/Passes/ReachingInsns.h @@ -11,7 +11,6 @@ #include "bolt/Passes/DataflowAnalysis.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/Timer.h" namespace opts { extern llvm::cl::opt TimeOpts; diff --git a/bolt/include/bolt/Passes/ReorderUtils.h b/bolt/include/bolt/Passes/ReorderUtils.h index bc82b4f436fa7553f9ae7762ad2098147080250e..8ceb8ba62690a55b87fe0933633c7ebe0239b318 100644 --- a/bolt/include/bolt/Passes/ReorderUtils.h +++ b/bolt/include/bolt/Passes/ReorderUtils.h @@ -14,7 +14,6 @@ #ifndef BOLT_PASSES_REORDER_UTILS_H #define BOLT_PASSES_REORDER_UTILS_H -#include #include #include "llvm/ADT/BitVector.h" diff --git a/bolt/include/bolt/Profile/BoltAddressTranslation.h b/bolt/include/bolt/Profile/BoltAddressTranslation.h index 844f0c54e68fb2fccfb3e804ea2b66fcc633c305..caf907cc43da3e8d4af24c6b5be5b5c41293e65c 100644 --- a/bolt/include/bolt/Profile/BoltAddressTranslation.h +++ b/bolt/include/bolt/Profile/BoltAddressTranslation.h @@ -115,13 +115,21 @@ public: /// Save function and basic block hashes used for metadata dump. void saveMetadata(BinaryContext &BC); + /// True if a given \p Address is a function with translation table entry. + bool isBATFunction(uint64_t Address) const { return Maps.count(Address); } + + /// Returns branch offsets grouped by containing basic block in a given + /// function. + std::unordered_map> + getBFBranches(uint64_t FuncOutputAddress) const; + private: /// Helper to update \p Map by inserting one or more BAT entries reflecting /// \p BB for function located at \p FuncAddress. At least one entry will be /// emitted for the start of the BB. More entries may be emitted to cover /// the location of calls or any instruction that may change control flow. void writeEntriesForBB(MapTy &Map, const BinaryBasicBlock &BB, - uint64_t FuncAddress); + uint64_t FuncInputAddress, uint64_t FuncOutputAddress); /// Write the serialized address translation table for a function. template @@ -144,15 +152,126 @@ private: std::map Maps; - using BBHashMap = std::unordered_map; - std::unordered_map> FuncHashes; + /// Map a function to its basic blocks count + std::unordered_map NumBasicBlocksMap; + + /// Map a function to its secondary entry points vector + std::unordered_map> SecondaryEntryPointsMap; /// Links outlined cold bocks to their original function std::map ColdPartSource; + /// Links output address of a main fragment back to input address. + std::unordered_map ReverseMap; + /// Identifies the address of a control-flow changing instructions in a /// translation map entry const static uint32_t BRANCHENTRY = 0x1; + +public: + /// Map basic block input offset to a basic block index and hash pair. + class BBHashMapTy { + class EntryTy { + unsigned Index; + size_t Hash; + + public: + unsigned getBBIndex() const { return Index; } + size_t getBBHash() const { return Hash; } + EntryTy(unsigned Index, size_t Hash) : Index(Index), Hash(Hash) {} + }; + + std::unordered_map Map; + const EntryTy &getEntry(uint32_t BBInputOffset) const { + auto It = Map.find(BBInputOffset); + assert(It != Map.end()); + return It->second; + } + + public: + bool isInputBlock(uint32_t InputOffset) const { + return Map.count(InputOffset); + } + + unsigned getBBIndex(uint32_t BBInputOffset) const { + return getEntry(BBInputOffset).getBBIndex(); + } + + size_t getBBHash(uint32_t BBInputOffset) const { + return getEntry(BBInputOffset).getBBHash(); + } + + void addEntry(uint32_t BBInputOffset, unsigned BBIndex, size_t BBHash) { + Map.emplace(BBInputOffset, EntryTy(BBIndex, BBHash)); + } + + size_t getNumBasicBlocks() const { return Map.size(); } + }; + + /// Map function output address to its hash and basic blocks hash map. + class FuncHashesTy { + class EntryTy { + size_t Hash; + BBHashMapTy BBHashMap; + + public: + size_t getBFHash() const { return Hash; } + const BBHashMapTy &getBBHashMap() const { return BBHashMap; } + EntryTy(size_t Hash) : Hash(Hash) {} + }; + + std::unordered_map Map; + const EntryTy &getEntry(uint64_t FuncOutputAddress) const { + auto It = Map.find(FuncOutputAddress); + assert(It != Map.end()); + return It->second; + } + + public: + size_t getBFHash(uint64_t FuncOutputAddress) const { + return getEntry(FuncOutputAddress).getBFHash(); + } + + const BBHashMapTy &getBBHashMap(uint64_t FuncOutputAddress) const { + return getEntry(FuncOutputAddress).getBBHashMap(); + } + + void addEntry(uint64_t FuncOutputAddress, size_t BFHash) { + Map.emplace(FuncOutputAddress, EntryTy(BFHash)); + } + + size_t getNumFunctions() const { return Map.size(); }; + + size_t getNumBasicBlocks() const { + size_t NumBasicBlocks{0}; + for (auto &I : Map) + NumBasicBlocks += I.second.getBBHashMap().getNumBasicBlocks(); + return NumBasicBlocks; + } + }; + + /// Returns BF hash by function output address (after BOLT). + size_t getBFHash(uint64_t FuncOutputAddress) const { + return FuncHashes.getBFHash(FuncOutputAddress); + } + + /// Returns BBHashMap by function output address (after BOLT). + const BBHashMapTy &getBBHashMap(uint64_t FuncOutputAddress) const { + return FuncHashes.getBBHashMap(FuncOutputAddress); + } + + BBHashMapTy &getBBHashMap(uint64_t FuncOutputAddress) { + return const_cast( + std::as_const(*this).getBBHashMap(FuncOutputAddress)); + } + + /// Returns the number of basic blocks in a function. + size_t getNumBasicBlocks(uint64_t OutputAddress) const { + return NumBasicBlocksMap.at(OutputAddress); + } + +private: + FuncHashesTy FuncHashes; }; } // namespace bolt diff --git a/bolt/include/bolt/Profile/DataAggregator.h b/bolt/include/bolt/Profile/DataAggregator.h index 5bb4d00024c503b81705ee2aeade3648c8b517a3..4fbe524b1c385d24d10cd3a0ea33ca53580f0fc9 100644 --- a/bolt/include/bolt/Profile/DataAggregator.h +++ b/bolt/include/bolt/Profile/DataAggregator.h @@ -463,6 +463,13 @@ private: /// Dump data structures into a file readable by llvm-bolt std::error_code writeAggregatedFile(StringRef OutputFilename) const; + /// Dump translated data structures into YAML + std::error_code writeBATYAML(BinaryContext &BC, + StringRef OutputFilename) const; + + /// Fixup profile collected on BOLTed binary, namely handle split functions. + void fixupBATProfile(BinaryContext &BC); + /// Filter out binaries based on PID void filterBinaryMMapInfo(); diff --git a/bolt/include/bolt/Profile/ProfileReaderBase.h b/bolt/include/bolt/Profile/ProfileReaderBase.h index 511718f3c0ec7431310d5c722e90bbb061c9057f..3e5cf2612893907677014e01dbe08922fe8cae24 100644 --- a/bolt/include/bolt/Profile/ProfileReaderBase.h +++ b/bolt/include/bolt/Profile/ProfileReaderBase.h @@ -65,7 +65,7 @@ public: /// Return true if the function \p BF may have a profile available. /// The result is based on the name(s) of the function alone and the profile /// match is not guaranteed. - virtual bool mayHaveProfileData(const BinaryFunction &BF); + virtual bool mayHaveProfileData(const BinaryFunction &BF) { return true; } /// Return true if the profile contains an entry for a local object /// that has an associated file name. diff --git a/bolt/include/bolt/Profile/ProfileYAMLMapping.h b/bolt/include/bolt/Profile/ProfileYAMLMapping.h index 548b528ae2d6534d96cbcea298f9b283c79385f6..9dd3920dbf0943fbb1f6aac2721b170a01d34900 100644 --- a/bolt/include/bolt/Profile/ProfileYAMLMapping.h +++ b/bolt/include/bolt/Profile/ProfileYAMLMapping.h @@ -14,7 +14,6 @@ #define BOLT_PROFILE_PROFILEYAMLMAPPING_H #include "bolt/Core/BinaryFunction.h" -#include "llvm/ADT/StringRef.h" #include "llvm/Support/YAMLTraits.h" #include diff --git a/bolt/include/bolt/Profile/YAMLProfileWriter.h b/bolt/include/bolt/Profile/YAMLProfileWriter.h index 2d3009ca91759b61786c37a7c3b2760c4f10eb5e..882748627e7f54aec2a5d0b85d738ce93cf292ee 100644 --- a/bolt/include/bolt/Profile/YAMLProfileWriter.h +++ b/bolt/include/bolt/Profile/YAMLProfileWriter.h @@ -9,6 +9,7 @@ #ifndef BOLT_PROFILE_YAML_PROFILE_WRITER_H #define BOLT_PROFILE_YAML_PROFILE_WRITER_H +#include "bolt/Profile/ProfileYAMLMapping.h" #include "llvm/Support/raw_ostream.h" #include @@ -29,6 +30,9 @@ public: /// Save execution profile for that instance. std::error_code writeProfile(const RewriteInstance &RI); + + static yaml::bolt::BinaryFunctionProfile convert(const BinaryFunction &BF, + bool UseDFS); }; } // namespace bolt diff --git a/bolt/include/bolt/Rewrite/DWARFRewriter.h b/bolt/include/bolt/Rewrite/DWARFRewriter.h index 20972f3d0b85ae2ac553d1a8ddf85746a6bfaf24..2c482bd2b9ea965ff1bc289ead744bfe3f19737d 100644 --- a/bolt/include/bolt/Rewrite/DWARFRewriter.h +++ b/bolt/include/bolt/Rewrite/DWARFRewriter.h @@ -22,9 +22,7 @@ #include #include #include -#include #include -#include #include namespace llvm { diff --git a/bolt/include/bolt/Rewrite/MetadataManager.h b/bolt/include/bolt/Rewrite/MetadataManager.h index efbc74b4daba9de588581719534d0a4e02f787f7..2ff70dbaab3de74d6af6ec14cf89cc84d29c69b4 100644 --- a/bolt/include/bolt/Rewrite/MetadataManager.h +++ b/bolt/include/bolt/Rewrite/MetadataManager.h @@ -11,7 +11,6 @@ #include "bolt/Rewrite/MetadataRewriter.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Error.h" namespace llvm { namespace bolt { diff --git a/bolt/include/bolt/Rewrite/RewriteInstance.h b/bolt/include/bolt/Rewrite/RewriteInstance.h index 97ab65cd5a4a1ffd26df3e575b8ce2853437405d..826677cd63b22b1a0abef55837f4c254a7b7ee84 100644 --- a/bolt/include/bolt/Rewrite/RewriteInstance.h +++ b/bolt/include/bolt/Rewrite/RewriteInstance.h @@ -17,7 +17,6 @@ #include "bolt/Core/Linker.h" #include "bolt/Rewrite/MetadataManager.h" #include "bolt/Utils/NameResolver.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/MC/StringTableBuilder.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ObjectFile.h" diff --git a/bolt/include/bolt/RuntimeLibs/RuntimeLibrary.h b/bolt/include/bolt/RuntimeLibs/RuntimeLibrary.h index c845cb7f7b214d825929d7019ba1c3e7652e612a..e392029156bcea81c2fbfda93f8584a6109dd480 100644 --- a/bolt/include/bolt/RuntimeLibs/RuntimeLibrary.h +++ b/bolt/include/bolt/RuntimeLibs/RuntimeLibrary.h @@ -17,7 +17,6 @@ #include "bolt/Core/Linker.h" #include "llvm/ADT/StringRef.h" -#include #include namespace llvm { diff --git a/bolt/include/bolt/Utils/NameShortener.h b/bolt/include/bolt/Utils/NameShortener.h index 9c7b7ec9ba655c452e9dffa7d17e1177d1628228..fd61235f93c86bcfedd7df514658e588fd142d36 100644 --- a/bolt/include/bolt/Utils/NameShortener.h +++ b/bolt/include/bolt/Utils/NameShortener.h @@ -14,7 +14,6 @@ #define BOLT_UTILS_NAME_SHORTENER_H #include "llvm/ADT/StringMap.h" -#include "llvm/ADT/Twine.h" namespace llvm { namespace bolt { diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp index b29ebbbfa18c4bc3eff2c0aa54de6d6bb7c0b940..47eae964e816c5565697bdc2ef974bdfecdff4dc 100644 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -14,7 +14,6 @@ #include "bolt/Core/BinaryEmitter.h" #include "bolt/Core/BinaryFunction.h" #include "bolt/Utils/CommandLineOpts.h" -#include "bolt/Utils/NameResolver.h" #include "bolt/Utils/Utils.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Twine.h" @@ -39,7 +38,6 @@ #include #include #include -#include #include using namespace llvm; @@ -162,28 +160,30 @@ BinaryContext::~BinaryContext() { /// Create BinaryContext for a given architecture \p ArchName and /// triple \p TripleName. -Expected> -BinaryContext::createBinaryContext(const ObjectFile *File, bool IsPIC, - std::unique_ptr DwCtx, - JournalingStreams Logger) { +Expected> BinaryContext::createBinaryContext( + Triple TheTriple, StringRef InputFileName, SubtargetFeatures *Features, + bool IsPIC, std::unique_ptr DwCtx, JournalingStreams Logger) { StringRef ArchName = ""; std::string FeaturesStr = ""; - switch (File->getArch()) { + switch (TheTriple.getArch()) { case llvm::Triple::x86_64: + if (Features) + return createFatalBOLTError( + "x86_64 target does not use SubtargetFeatures"); ArchName = "x86-64"; FeaturesStr = "+nopl"; break; case llvm::Triple::aarch64: + if (Features) + return createFatalBOLTError( + "AArch64 target does not use SubtargetFeatures"); ArchName = "aarch64"; FeaturesStr = "+all"; break; case llvm::Triple::riscv64: { ArchName = "riscv64"; - Expected Features = File->getFeatures(); - - if (auto E = Features.takeError()) - return std::move(E); - + if (!Features) + return createFatalBOLTError("RISCV target needs SubtargetFeatures"); // We rely on relaxation for some transformations (e.g., promoting all calls // to PseudoCALL and then making JITLink relax them). Since the relax // feature is not stored in the object file, we manually enable it. @@ -196,12 +196,11 @@ BinaryContext::createBinaryContext(const ObjectFile *File, bool IsPIC, "BOLT-ERROR: Unrecognized machine in ELF file"); } - auto TheTriple = std::make_unique(File->makeTriple()); - const std::string TripleName = TheTriple->str(); + const std::string TripleName = TheTriple.str(); std::string Error; const Target *TheTarget = - TargetRegistry::lookupTarget(std::string(ArchName), *TheTriple, Error); + TargetRegistry::lookupTarget(std::string(ArchName), TheTriple, Error); if (!TheTarget) return createStringError(make_error_code(std::errc::not_supported), Twine("BOLT-ERROR: ", Error)); @@ -240,13 +239,13 @@ BinaryContext::createBinaryContext(const ObjectFile *File, bool IsPIC, Twine("BOLT-ERROR: no instruction info for target ", TripleName)); std::unique_ptr Ctx( - new MCContext(*TheTriple, AsmInfo.get(), MRI.get(), STI.get())); + new MCContext(TheTriple, AsmInfo.get(), MRI.get(), STI.get())); std::unique_ptr MOFI( TheTarget->createMCObjectFileInfo(*Ctx, IsPIC)); Ctx->setObjectFileInfo(MOFI.get()); // We do not support X86 Large code model. Change this in the future. bool Large = false; - if (TheTriple->getArch() == llvm::Triple::aarch64) + if (TheTriple.getArch() == llvm::Triple::aarch64) Large = true; unsigned LSDAEncoding = Large ? dwarf::DW_EH_PE_absptr : dwarf::DW_EH_PE_udata4; @@ -273,7 +272,7 @@ BinaryContext::createBinaryContext(const ObjectFile *File, bool IsPIC, int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); std::unique_ptr InstructionPrinter( - TheTarget->createMCInstPrinter(*TheTriple, AsmPrinterVariant, *AsmInfo, + TheTarget->createMCInstPrinter(TheTriple, AsmPrinterVariant, *AsmInfo, *MII, *MRI)); if (!InstructionPrinter) return createStringError( @@ -285,8 +284,8 @@ BinaryContext::createBinaryContext(const ObjectFile *File, bool IsPIC, TheTarget->createMCCodeEmitter(*MII, *Ctx)); auto BC = std::make_unique( - std::move(Ctx), std::move(DwCtx), std::move(TheTriple), TheTarget, - std::string(TripleName), std::move(MCE), std::move(MOFI), + std::move(Ctx), std::move(DwCtx), std::make_unique(TheTriple), + TheTarget, std::string(TripleName), std::move(MCE), std::move(MOFI), std::move(AsmInfo), std::move(MII), std::move(STI), std::move(InstructionPrinter), std::move(MIA), nullptr, std::move(MRI), std::move(DisAsm), Logger); @@ -296,7 +295,7 @@ BinaryContext::createBinaryContext(const ObjectFile *File, bool IsPIC, BC->MAB = std::unique_ptr( BC->TheTarget->createMCAsmBackend(*BC->STI, *BC->MRI, MCTargetOptions())); - BC->setFilename(File->getFileName()); + BC->setFilename(InputFileName); BC->HasFixedLoadAddress = !IsPIC; @@ -1939,7 +1938,13 @@ void BinaryContext::printInstruction(raw_ostream &OS, const MCInst &Instruction, OS << Endl; return; } - InstPrinter->printInst(&Instruction, 0, "", *STI, OS); + if (std::optional DynamicID = + MIB->getDynamicBranchID(Instruction)) { + OS << "\tjit\t" << MIB->getTargetSymbol(Instruction)->getName() + << " # ID: " << DynamicID; + } else { + InstPrinter->printInst(&Instruction, 0, "", *STI, OS); + } if (MIB->isCall(Instruction)) { if (MIB->isTailCall(Instruction)) OS << " # TAILCALL "; diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp index ce4dd29f542b0d9400e8e8d3fdcec755ae8bcc6f..1fa96dfaabde819eeb3ff70e5340cc46af5ed49a 100644 --- a/bolt/lib/Core/BinaryFunction.cpp +++ b/bolt/lib/Core/BinaryFunction.cpp @@ -12,7 +12,6 @@ #include "bolt/Core/BinaryFunction.h" #include "bolt/Core/BinaryBasicBlock.h" -#include "bolt/Core/BinaryDomTree.h" #include "bolt/Core/DynoStats.h" #include "bolt/Core/HashUtilities.h" #include "bolt/Core/MCPlusBuilder.h" @@ -35,6 +34,8 @@ #include "llvm/Object/ObjectFile.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/GenericDomTreeConstruction.h" +#include "llvm/Support/GenericLoopInfoImpl.h" #include "llvm/Support/GraphWriter.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/Regex.h" @@ -3350,6 +3351,16 @@ void BinaryFunction::fixBranches() { // Eliminate unnecessary conditional branch. if (TSuccessor == FSuccessor) { + // FIXME: at the moment, we cannot safely remove static key branches. + if (MIB->isDynamicBranch(*CondBranch)) { + if (opts::Verbosity) { + BC.outs() + << "BOLT-INFO: unable to remove redundant dynamic branch in " + << *this << '\n'; + } + continue; + } + BB->removeDuplicateConditionalSuccessor(CondBranch); if (TSuccessor != NextBB) BB->addBranchInstruction(TSuccessor); @@ -3358,8 +3369,13 @@ void BinaryFunction::fixBranches() { // Reverse branch condition and swap successors. auto swapSuccessors = [&]() { - if (MIB->isUnsupportedBranch(*CondBranch)) + if (MIB->isUnsupportedBranch(*CondBranch)) { + if (opts::Verbosity) { + BC.outs() << "BOLT-INFO: unable to swap successors in " << *this + << '\n'; + } return false; + } std::swap(TSuccessor, FSuccessor); BB->swapConditionalSuccessors(); auto L = BC.scopeLock(); @@ -3532,7 +3548,7 @@ MCSymbol *BinaryFunction::getSymbolForEntryID(uint64_t EntryID) { if (!isMultiEntry()) return nullptr; - uint64_t NumEntries = 0; + uint64_t NumEntries = 1; if (hasCFG()) { for (BinaryBasicBlock *BB : BasicBlocks) { MCSymbol *EntrySymbol = getSecondaryEntryPointSymbol(*BB); @@ -3565,7 +3581,7 @@ uint64_t BinaryFunction::getEntryIDForSymbol(const MCSymbol *Symbol) const { return 0; // Check all secondary entries available as either basic blocks or lables. - uint64_t NumEntries = 0; + uint64_t NumEntries = 1; for (const BinaryBasicBlock *BB : BasicBlocks) { MCSymbol *EntrySymbol = getSecondaryEntryPointSymbol(*BB); if (!EntrySymbol) @@ -3574,7 +3590,7 @@ uint64_t BinaryFunction::getEntryIDForSymbol(const MCSymbol *Symbol) const { return NumEntries; ++NumEntries; } - NumEntries = 0; + NumEntries = 1; for (const std::pair &KV : Labels) { MCSymbol *EntrySymbol = getSecondaryEntryPointSymbol(KV.second); if (!EntrySymbol) @@ -4061,12 +4077,17 @@ BinaryFunction::~BinaryFunction() { delete BB; } +void BinaryFunction::constructDomTree() { + BDT.reset(new BinaryDominatorTree); + BDT->recalculate(*this); +} + void BinaryFunction::calculateLoopInfo() { + if (!hasDomTree()) + constructDomTree(); // Discover loops. - BinaryDominatorTree DomTree; - DomTree.recalculate(*this); BLI.reset(new BinaryLoopInfo()); - BLI->analyze(DomTree); + BLI->analyze(getDomTree()); // Traverse discovered loops and add depth and profile information. std::stack St; diff --git a/bolt/lib/Core/DIEBuilder.cpp b/bolt/lib/Core/DIEBuilder.cpp index 42287978a8576feb868f82cd38496adb41504658..c4b0b251c1201fcf9f27454b3b26fc861d5235bb 100644 --- a/bolt/lib/Core/DIEBuilder.cpp +++ b/bolt/lib/Core/DIEBuilder.cpp @@ -22,7 +22,6 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Format.h" #include "llvm/Support/LEB128.h" #include @@ -377,20 +376,32 @@ getUnitForOffset(DIEBuilder &Builder, DWARFContext &DWCtx, return nullptr; } -uint32_t DIEBuilder::finalizeDIEs(DWARFUnit &CU, DIE &Die, - uint32_t &CurOffset) { +uint32_t DIEBuilder::finalizeDIEs( + DWARFUnit &CU, DIE &Die, + std::vector> &Parents, + uint32_t &CurOffset) { getState().DWARFDieAddressesParsed.erase(Die.getOffset()); uint32_t CurSize = 0; Die.setOffset(CurOffset); - DebugNamesTable.addAccelTableEntry( - CU, Die, SkeletonCU ? SkeletonCU->getDWOId() : std::nullopt); + std::optional NameEntry = + DebugNamesTable.addAccelTableEntry( + CU, Die, SkeletonCU ? SkeletonCU->getDWOId() : std::nullopt, + Parents.back()); + // It is possible that an indexed debugging information entry has a parent + // that is not indexed (for example, if its parent does not have a name + // attribute). In such a case, a parent attribute may point to a nameless + // index entry (that is, one that cannot be reached from any entry in the name + // table), or it may point to the nearest ancestor that does have an index + // entry. + if (NameEntry) + Parents.push_back(std::move(NameEntry)); for (DIEValue &Val : Die.values()) CurSize += Val.sizeOf(CU.getFormParams()); CurSize += getULEB128Size(Die.getAbbrevNumber()); CurOffset += CurSize; for (DIE &Child : Die.children()) { - uint32_t ChildSize = finalizeDIEs(CU, Child, CurOffset); + uint32_t ChildSize = finalizeDIEs(CU, Child, Parents, CurOffset); CurSize += ChildSize; } // for children end mark. @@ -400,6 +411,8 @@ uint32_t DIEBuilder::finalizeDIEs(DWARFUnit &CU, DIE &Die, } Die.setSize(CurSize); + if (NameEntry) + Parents.pop_back(); return CurSize; } @@ -410,7 +423,9 @@ void DIEBuilder::finish() { uint32_t HeaderSize = CU.getHeaderSize(); uint32_t CurOffset = HeaderSize; DebugNamesTable.setCurrentUnit(CU, UnitStartOffset); - finalizeDIEs(CU, *UnitDIE, CurOffset); + std::vector> Parents; + Parents.push_back(std::nullopt); + finalizeDIEs(CU, *UnitDIE, Parents, CurOffset); DWARFUnitInfo &CurUnitInfo = getUnitInfoByDwarfUnit(CU); CurUnitInfo.UnitOffset = UnitStartOffset; @@ -529,6 +544,10 @@ void DIEBuilder::cloneDieReferenceAttribute( NewRefDie = DieInfo.Die; if (AttrSpec.Form == dwarf::DW_FORM_ref_addr) { + // Adding referenced DIE to DebugNames to be used when entries are created + // that contain cross cu references. + if (DebugNamesTable.canGenerateEntryWithCrossCUReference(U, Die, AttrSpec)) + DebugNamesTable.addCrossCUDie(DieInfo.Die); // no matter forward reference or backward reference, we are supposed // to calculate them in `finish` due to the possible modification of // the DIE. @@ -538,7 +557,7 @@ void DIEBuilder::cloneDieReferenceAttribute( std::make_pair(CurDieInfo, AddrReferenceInfo(&DieInfo, AttrSpec))); Die.addValue(getState().DIEAlloc, AttrSpec.Attr, dwarf::DW_FORM_ref_addr, - DIEInteger(0xDEADBEEF)); + DIEInteger(DieInfo.Die->getOffset())); return; } diff --git a/bolt/lib/Core/DebugData.cpp b/bolt/lib/Core/DebugData.cpp index a75016ede3090d5b6f77897bab9120d38e8c6057..a987a103a08b93ad7311fc81efb752ca15bac303 100644 --- a/bolt/lib/Core/DebugData.cpp +++ b/bolt/lib/Core/DebugData.cpp @@ -13,7 +13,6 @@ #include "bolt/Core/DebugData.h" #include "bolt/Core/BinaryContext.h" #include "bolt/Core/DIEBuilder.h" -#include "bolt/Rewrite/RewriteInstance.h" #include "bolt/Utils/Utils.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/CodeGen/DIE.h" @@ -23,7 +22,6 @@ #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCObjectStreamer.h" -#include "llvm/Support/Allocator.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/LEB128.h" @@ -32,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/bolt/lib/Core/DebugNames.cpp b/bolt/lib/Core/DebugNames.cpp index 384e63695dfdc563ceda2a97eb2f48692615ec7a..049244c4b51518a88cd9d8af1b5d64c24010d705 100644 --- a/bolt/lib/Core/DebugNames.cpp +++ b/bolt/lib/Core/DebugNames.cpp @@ -13,6 +13,7 @@ #include "llvm/Support/EndianStream.h" #include "llvm/Support/LEB128.h" #include +#include namespace llvm { namespace bolt { @@ -145,6 +146,55 @@ static bool shouldIncludeVariable(const DWARFUnit &Unit, const DIE &Die) { return false; } +bool static canProcess(const DWARFUnit &Unit, const DIE &Die, + std::string &NameToUse, const bool TagsOnly) { + switch (Die.getTag()) { + case dwarf::DW_TAG_base_type: + case dwarf::DW_TAG_class_type: + case dwarf::DW_TAG_enumeration_type: + case dwarf::DW_TAG_imported_declaration: + case dwarf::DW_TAG_pointer_type: + case dwarf::DW_TAG_structure_type: + case dwarf::DW_TAG_typedef: + case dwarf::DW_TAG_unspecified_type: + if (TagsOnly || Die.findAttribute(dwarf::Attribute::DW_AT_name)) + return true; + return false; + case dwarf::DW_TAG_namespace: + // According to DWARF5 spec namespaces without DW_AT_name needs to have + // "(anonymous namespace)" + if (!Die.findAttribute(dwarf::Attribute::DW_AT_name)) + NameToUse = "(anonymous namespace)"; + return true; + case dwarf::DW_TAG_inlined_subroutine: + case dwarf::DW_TAG_label: + case dwarf::DW_TAG_subprogram: + if (TagsOnly || Die.findAttribute(dwarf::Attribute::DW_AT_low_pc) || + Die.findAttribute(dwarf::Attribute::DW_AT_high_pc) || + Die.findAttribute(dwarf::Attribute::DW_AT_ranges) || + Die.findAttribute(dwarf::Attribute::DW_AT_entry_pc)) + return true; + return false; + case dwarf::DW_TAG_variable: + return TagsOnly || shouldIncludeVariable(Unit, Die); + default: + break; + } + return false; +} + +bool DWARF5AcceleratorTable::canGenerateEntryWithCrossCUReference( + const DWARFUnit &Unit, const DIE &Die, + const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec) { + if (!isCreated()) + return false; + std::string NameToUse = ""; + if (!canProcess(Unit, Die, NameToUse, true)) + return false; + return (AttrSpec.Attr == dwarf::Attribute::DW_AT_abstract_origin || + AttrSpec.Attr == dwarf::Attribute::DW_AT_specification) && + AttrSpec.Form == dwarf::DW_FORM_ref_addr; +} /// Returns name offset in String Offset section. static uint64_t getNameOffset(BinaryContext &BC, DWARFUnit &Unit, const uint64_t Index) { @@ -163,46 +213,17 @@ static uint64_t getNameOffset(BinaryContext &BC, DWARFUnit &Unit, Index * DwarfOffsetByteSize); } -void DWARF5AcceleratorTable::addAccelTableEntry( - DWARFUnit &Unit, const DIE &Die, const std::optional &DWOID) { +static uint64_t getEntryID(const BOLTDWARF5AccelTableData &Entry) { + return reinterpret_cast(&Entry); +} + +std::optional +DWARF5AcceleratorTable::addAccelTableEntry( + DWARFUnit &Unit, const DIE &Die, const std::optional &DWOID, + std::optional &Parent) { if (Unit.getVersion() < 5 || !NeedToCreate) - return; + return std::nullopt; std::string NameToUse = ""; - auto canProcess = [&](const DIE &Die) -> bool { - switch (Die.getTag()) { - case dwarf::DW_TAG_base_type: - case dwarf::DW_TAG_class_type: - case dwarf::DW_TAG_enumeration_type: - case dwarf::DW_TAG_imported_declaration: - case dwarf::DW_TAG_pointer_type: - case dwarf::DW_TAG_structure_type: - case dwarf::DW_TAG_typedef: - case dwarf::DW_TAG_unspecified_type: - if (Die.findAttribute(dwarf::Attribute::DW_AT_name)) - return true; - return false; - case dwarf::DW_TAG_namespace: - // According to DWARF5 spec namespaces without DW_AT_name needs to have - // "(anonymous namespace)" - if (!Die.findAttribute(dwarf::Attribute::DW_AT_name)) - NameToUse = "(anonymous namespace)"; - return true; - case dwarf::DW_TAG_inlined_subroutine: - case dwarf::DW_TAG_label: - case dwarf::DW_TAG_subprogram: - if (Die.findAttribute(dwarf::Attribute::DW_AT_low_pc) || - Die.findAttribute(dwarf::Attribute::DW_AT_high_pc) || - Die.findAttribute(dwarf::Attribute::DW_AT_ranges) || - Die.findAttribute(dwarf::Attribute::DW_AT_entry_pc)) - return true; - return false; - case dwarf::DW_TAG_variable: - return shouldIncludeVariable(Unit, Die); - default: - break; - } - return false; - }; auto getUnitID = [&](const DWARFUnit &Unit, bool &IsTU, uint32_t &DieTag) -> uint32_t { @@ -216,8 +237,8 @@ void DWARF5AcceleratorTable::addAccelTableEntry( return CUList.size() - 1; }; - if (!canProcess(Die)) - return; + if (!canProcess(Unit, Die, NameToUse, false)) + return std::nullopt; // Addes a Unit to either CU, LocalTU or ForeignTU list the first time we // encounter it. @@ -227,10 +248,10 @@ void DWARF5AcceleratorTable::addAccelTableEntry( addUnit(Unit, DWOID); } - auto addEntry = [&](DIEValue ValName) -> void { + auto getName = [&](DIEValue ValName) -> std::optional { if ((!ValName || ValName.getForm() == dwarf::DW_FORM_string) && NameToUse.empty()) - return; + return std::nullopt; std::string Name = ""; uint64_t NameIndexOffset = 0; if (NameToUse.empty()) { @@ -260,7 +281,16 @@ void DWARF5AcceleratorTable::addAccelTableEntry( // This the same hash function used in DWARF5AccelTableData. It.HashValue = caseFoldingDjbHash(Name); } + return Name; + }; + auto addEntry = + [&](DIEValue ValName) -> std::optional { + std::optional Name = getName(ValName); + if (!Name) + return std::nullopt; + + auto &It = Entries[*Name]; bool IsTU = false; uint32_t DieTag = 0; uint32_t UnitID = getUnitID(Unit, IsTU, DieTag); @@ -270,18 +300,66 @@ void DWARF5AcceleratorTable::addAccelTableEntry( if (Iter == CUOffsetsToPatch.end()) BC.errs() << "BOLT-WARNING: [internal-dwarf-warning]: Could not find " "DWO ID in CU offsets for second Unit Index " - << Name << ". For DIE at offset: " + << *Name << ". For DIE at offset: " << Twine::utohexstr(CurrentUnitOffset + Die.getOffset()) << ".\n"; SecondIndex = Iter->second; } + std::optional ParentOffset = + (Parent ? std::optional(getEntryID(**Parent)) : std::nullopt); + // This will be populated later in writeEntry. + // This way only parent entries get tracked. + // Keeping memory footprint down. + if (ParentOffset) + EntryRelativeOffsets.insert({*ParentOffset, 0}); It.Values.push_back(new (Allocator) BOLTDWARF5AccelTableData( - Die.getOffset(), std::nullopt, DieTag, UnitID, IsTU, SecondIndex)); + Die.getOffset(), ParentOffset, DieTag, UnitID, IsTU, SecondIndex)); + return It.Values.back(); + }; + + // Minor optimization not to add entry twice for DW_TAG_namespace if it has no + // DW_AT_name. + if (!(Die.getTag() == dwarf::DW_TAG_namespace && + !Die.findAttribute(dwarf::Attribute::DW_AT_name))) + addEntry(Die.findAttribute(dwarf::Attribute::DW_AT_linkage_name)); + // For the purposes of determining whether a debugging information entry has a + // particular attribute (such as DW_AT_name), if debugging information entry A + // has a DW_AT_specification or DW_AT_abstract_origin attribute pointing to + // another debugging information entry B, any attributes of B are considered + // to be part of A. + auto processReferencedDie = [&](const dwarf::Attribute &Attr) + -> std::optional { + const DIEValue Value = Die.findAttribute(Attr); + if (!Value) + return std::nullopt; + const DIE *EntryDie = nullptr; + if (Value.getForm() == dwarf::DW_FORM_ref_addr) { + auto Iter = CrossCUDies.find(Value.getDIEInteger().getValue()); + if (Iter == CrossCUDies.end()) { + BC.errs() << "BOLT-WARNING: [internal-dwarf-warning]: Could not find " + "referenced DIE in CrossCUDies for " + << Twine::utohexstr(Value.getDIEInteger().getValue()) + << ".\n"; + return std::nullopt; + } + EntryDie = Iter->second; + } else { + const DIEEntry &DIEENtry = Value.getDIEEntry(); + EntryDie = &DIEENtry.getEntry(); + } + + addEntry(EntryDie->findAttribute(dwarf::Attribute::DW_AT_linkage_name)); + return addEntry(EntryDie->findAttribute(dwarf::Attribute::DW_AT_name)); }; - addEntry(Die.findAttribute(dwarf::Attribute::DW_AT_name)); - addEntry(Die.findAttribute(dwarf::Attribute::DW_AT_linkage_name)); - return; + if (std::optional Entry = + processReferencedDie(dwarf::Attribute::DW_AT_abstract_origin)) + return *Entry; + if (std::optional Entry = + processReferencedDie(dwarf::Attribute::DW_AT_specification)) + return *Entry; + + return addEntry(Die.findAttribute(dwarf::Attribute::DW_AT_name)); } /// Algorithm from llvm implementation. @@ -382,6 +460,11 @@ void DWARF5AcceleratorTable::populateAbbrevsMap() { if (SecondEntryRet) Abbrev.addAttribute(SecondEntryRet->Encoding); Abbrev.addAttribute({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4}); + if (std::optional Offset = Value->getParentDieOffset()) + Abbrev.addAttribute({dwarf::DW_IDX_parent, dwarf::DW_FORM_ref4}); + else + Abbrev.addAttribute( + {dwarf::DW_IDX_parent, dwarf::DW_FORM_flag_present}); FoldingSetNodeID ID; Abbrev.Profile(ID); void *InsertPos; @@ -401,7 +484,11 @@ void DWARF5AcceleratorTable::populateAbbrevsMap() { } } -void DWARF5AcceleratorTable::writeEntry(const BOLTDWARF5AccelTableData &Entry) { +void DWARF5AcceleratorTable::writeEntry(BOLTDWARF5AccelTableData &Entry) { + const uint64_t EntryID = getEntryID(Entry); + if (EntryRelativeOffsets.find(EntryID) != EntryRelativeOffsets.end()) + EntryRelativeOffsets[EntryID] = EntriesBuffer->size(); + const std::optional EntryRet = getIndexForEntry(Entry); // For forgeign type (FTU) units that need to refer to the FTU and to the CU. @@ -456,6 +543,17 @@ void DWARF5AcceleratorTable::writeEntry(const BOLTDWARF5AccelTableData &Entry) { llvm::endianness::little); break; } + case dwarf::DW_IDX_parent: { + assert( + (AttrEnc.Form == dwarf::DW_FORM_ref4 && Entry.getParentDieOffset()) || + AttrEnc.Form == dwarf::DW_FORM_flag_present); + if (std::optional ParentOffset = Entry.getParentDieOffset()) { + Entry.setPatchOffset(EntriesBuffer->size()); + support::endian::write(*Entriestream, static_cast(UINT32_MAX), + llvm::endianness::little); + } + break; + } } } } @@ -464,13 +562,34 @@ void DWARF5AcceleratorTable::writeEntries() { for (auto &Bucket : getBuckets()) { for (DWARF5AcceleratorTable::HashData *Hash : Bucket) { Hash->EntryOffset = EntriesBuffer->size(); - for (const BOLTDWARF5AccelTableData *Value : Hash->Values) { + for (BOLTDWARF5AccelTableData *Value : Hash->Values) { writeEntry(*Value); } support::endian::write(*Entriestream, static_cast(0), llvm::endianness::little); } } + // Patching parent offsets. + for (auto &Bucket : getBuckets()) { + for (DWARF5AcceleratorTable::HashData *Hash : Bucket) { + for (BOLTDWARF5AccelTableData *Entry : Hash->Values) { + std::optional ParentOffset = Entry->getParentDieOffset(); + if (!ParentOffset) + continue; + if (const auto Iter = EntryRelativeOffsets.find(*ParentOffset); + Iter != EntryRelativeOffsets.end()) { + const uint64_t PatchOffset = Entry->getPatchOffset(); + uint32_t *Ptr = reinterpret_cast( + &EntriesBuffer.get()->data()[PatchOffset]); + *Ptr = Iter->second; + } else { + BC.errs() << "BOLT-WARNING: [internal-dwarf-warning]: Could not find " + "entry with offset " + << *ParentOffset << "\n"; + } + } + } + } } void DWARF5AcceleratorTable::writeAugmentationString() { diff --git a/bolt/lib/Core/FunctionLayout.cpp b/bolt/lib/Core/FunctionLayout.cpp index 27e40de94be660f0ffbe9b5f6ddacb5b0393b0ac..73f4d5247d9ac06092601f1e931055223b83c00d 100644 --- a/bolt/lib/Core/FunctionLayout.cpp +++ b/bolt/lib/Core/FunctionLayout.cpp @@ -1,12 +1,17 @@ +//===- bolt/Core/FunctionLayout.cpp - Fragmented Function Layout -*- 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 "bolt/Core/FunctionLayout.h" -#include "bolt/Core/BinaryFunction.h" +#include "bolt/Core/BinaryBasicBlock.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/edit_distance.h" #include -#include -#include #include -#include using namespace llvm; using namespace bolt; diff --git a/bolt/lib/Core/HashUtilities.cpp b/bolt/lib/Core/HashUtilities.cpp index d40159b2e216d90f97b510886b7d79e468f895be..c4c67bd68198b6681b4dc95b7d3f0cb43caae5df 100644 --- a/bolt/lib/Core/HashUtilities.cpp +++ b/bolt/lib/Core/HashUtilities.cpp @@ -12,7 +12,6 @@ #include "bolt/Core/HashUtilities.h" #include "bolt/Core/BinaryContext.h" -#include "bolt/Core/BinaryFunction.h" #include "llvm/MC/MCInstPrinter.h" namespace llvm { diff --git a/bolt/lib/Core/MCPlusBuilder.cpp b/bolt/lib/Core/MCPlusBuilder.cpp index bd9bd0c45922a5d4a92fe280fc97d34cf7decb64..7ff7a2288451c844f360f9b24878d6d335be85ee 100644 --- a/bolt/lib/Core/MCPlusBuilder.cpp +++ b/bolt/lib/Core/MCPlusBuilder.cpp @@ -12,15 +12,16 @@ #include "bolt/Core/MCPlusBuilder.h" #include "bolt/Core/MCPlus.h" +#include "bolt/Utils/CommandLineOpts.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include -#include #define DEBUG_TYPE "mcplus" @@ -28,6 +29,13 @@ using namespace llvm; using namespace bolt; using namespace MCPlus; +namespace opts { +cl::opt + TerminalTrap("terminal-trap", + cl::desc("Assume that execution stops at trap instruction"), + cl::init(true), cl::Hidden, cl::cat(BoltCategory)); +} + bool MCPlusBuilder::equals(const MCInst &A, const MCInst &B, CompFuncTy Comp) const { if (A.getOpcode() != B.getOpcode()) @@ -121,6 +129,11 @@ bool MCPlusBuilder::equals(const MCTargetExpr &A, const MCTargetExpr &B, llvm_unreachable("target-specific expressions are unsupported"); } +bool MCPlusBuilder::isTerminator(const MCInst &Inst) const { + return Analysis->isTerminator(Inst) || + (opts::TerminalTrap && Info->get(Inst.getOpcode()).isTrap()); +} + void MCPlusBuilder::setTailCall(MCInst &Inst) const { assert(!hasAnnotation(Inst, MCAnnotation::kTailCall)); setAnnotationOpValue(Inst, MCAnnotation::kTailCall, true); @@ -303,6 +316,28 @@ void MCPlusBuilder::setSize(MCInst &Inst, uint32_t Size) const { setAnnotationOpValue(Inst, MCAnnotation::kSize, Size); } +bool MCPlusBuilder::isDynamicBranch(const MCInst &Inst) const { + if (!hasAnnotation(Inst, MCAnnotation::kDynamicBranch)) + return false; + assert(isBranch(Inst) && "Branch expected."); + return true; +} + +std::optional +MCPlusBuilder::getDynamicBranchID(const MCInst &Inst) const { + if (std::optional Value = + getAnnotationOpValue(Inst, MCAnnotation::kDynamicBranch)) { + assert(isBranch(Inst) && "Branch expected."); + return static_cast(*Value); + } + return std::nullopt; +} + +void MCPlusBuilder::setDynamicBranch(MCInst &Inst, uint32_t ID) const { + assert(isBranch(Inst) && "Branch expected."); + setAnnotationOpValue(Inst, MCAnnotation::kDynamicBranch, ID); +} + bool MCPlusBuilder::hasAnnotation(const MCInst &Inst, unsigned Index) const { return (bool)getAnnotationOpValue(Inst, Index); } diff --git a/bolt/lib/Passes/BinaryPasses.cpp b/bolt/lib/Passes/BinaryPasses.cpp index d2850b03e2e13f0aab563815743a412cc31cb18f..c0ba73108f5778b4e385560c2129e6ef3bb056c8 100644 --- a/bolt/lib/Passes/BinaryPasses.cpp +++ b/bolt/lib/Passes/BinaryPasses.cpp @@ -107,6 +107,12 @@ static cl::opt cl::desc("print statistics about basic block ordering"), cl::init(0), cl::cat(BoltOptCategory)); +static cl::opt PrintLargeFunctions( + "print-large-functions", + cl::desc("print functions that could not be overwritten due to excessive " + "size"), + cl::init(false), cl::cat(BoltOptCategory)); + static cl::list PrintSortedBy("print-sorted-by", cl::CommaSeparated, cl::desc("print functions sorted by order of dyno stats"), @@ -570,8 +576,12 @@ Error CheckLargeFunctions::runOnFunctions(BinaryContext &BC) { uint64_t HotSize, ColdSize; std::tie(HotSize, ColdSize) = BC.calculateEmittedSize(BF, /*FixBranches=*/false); - if (HotSize > BF.getMaxSize()) + if (HotSize > BF.getMaxSize()) { + if (opts::PrintLargeFunctions) + BC.outs() << "BOLT-INFO: " << BF << " size exceeds allocated space by " + << (HotSize - BF.getMaxSize()) << " bytes\n"; BF.setSimple(false); + } }; ParallelUtilities::PredicateTy SkipFunc = [&](const BinaryFunction &BF) { @@ -852,6 +862,10 @@ uint64_t SimplifyConditionalTailCalls::fixTailCalls(BinaryFunction &BF) { assert(Result && "internal error analyzing conditional branch"); assert(CondBranch && "conditional branch expected"); + // Skip dynamic branches for now. + if (BF.getBinaryContext().MIB->isDynamicBranch(*CondBranch)) + continue; + // It's possible that PredBB is also a successor to BB that may have // been processed by a previous iteration of the SCTC loop, in which // case it may have been marked invalid. We should skip rewriting in @@ -1012,6 +1026,10 @@ uint64_t ShortenInstructions::shortenInstructions(BinaryFunction &Function) { const BinaryContext &BC = Function.getBinaryContext(); for (BinaryBasicBlock &BB : Function) { for (MCInst &Inst : BB) { + // Skip shortening instructions with Size annotation. + if (BC.MIB->getSize(Inst)) + continue; + MCInst OriginalInst; if (opts::Verbosity > 2) OriginalInst = Inst; @@ -1056,10 +1074,9 @@ void Peepholes::addTailcallTraps(BinaryFunction &Function) { MCInst *Inst = BB.getLastNonPseudoInstr(); if (Inst && MIB->isTailCall(*Inst) && MIB->isIndirectBranch(*Inst)) { MCInst Trap; - if (MIB->createTrap(Trap)) { - BB.addInstruction(Trap); - ++TailCallTraps; - } + MIB->createTrap(Trap); + BB.addInstruction(Trap); + ++TailCallTraps; } } } diff --git a/bolt/lib/Passes/CMOVConversion.cpp b/bolt/lib/Passes/CMOVConversion.cpp index 2492ff21794634bd35bc4f7f03c9970bccf69739..cdd99b55207e0b6e92a1f0eab59f5082f57bd614 100644 --- a/bolt/lib/Passes/CMOVConversion.cpp +++ b/bolt/lib/Passes/CMOVConversion.cpp @@ -17,7 +17,6 @@ #include "llvm/ADT/PostOrderIterator.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" -#include #define DEBUG_TYPE "cmov" diff --git a/bolt/lib/Passes/FixRISCVCallsPass.cpp b/bolt/lib/Passes/FixRISCVCallsPass.cpp index 83c745facb290b70209a3243fdf4a553ca49f3e4..9011ef303a80ef1922f4f772d5e43f6a4f9f1b05 100644 --- a/bolt/lib/Passes/FixRISCVCallsPass.cpp +++ b/bolt/lib/Passes/FixRISCVCallsPass.cpp @@ -1,3 +1,11 @@ +//===- bolt/Passes/FixRISCVCallsPass.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 "bolt/Passes/FixRISCVCallsPass.h" #include "bolt/Core/ParallelUtilities.h" diff --git a/bolt/lib/Passes/FixRelaxationPass.cpp b/bolt/lib/Passes/FixRelaxationPass.cpp index a49fb9894e808cccdf0f222a51e6f354db2c0f8d..7c970e464a94e361626dac979546e0564f25a012 100644 --- a/bolt/lib/Passes/FixRelaxationPass.cpp +++ b/bolt/lib/Passes/FixRelaxationPass.cpp @@ -1,3 +1,11 @@ +//===- bolt/Passes/FixRelaxationPass.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 "bolt/Passes/FixRelaxationPass.h" #include "bolt/Core/ParallelUtilities.h" diff --git a/bolt/lib/Passes/FrameOptimizer.cpp b/bolt/lib/Passes/FrameOptimizer.cpp index fb5f8eafa5cf846e576bbfff6b4f7b1ddbec5b06..8461225e1819c169023ab1f31fb34e6ab619d08e 100644 --- a/bolt/lib/Passes/FrameOptimizer.cpp +++ b/bolt/lib/Passes/FrameOptimizer.cpp @@ -20,7 +20,6 @@ #include "bolt/Utils/CommandLineOpts.h" #include "llvm/Support/Timer.h" #include -#include #define DEBUG_TYPE "fop" diff --git a/bolt/lib/Passes/Hugify.cpp b/bolt/lib/Passes/Hugify.cpp index b77356153bfd8caf5f1e01b27c29547c3b45a704..1ac1b08573b86954f01ef3de3a5c4db2f732b984 100644 --- a/bolt/lib/Passes/Hugify.cpp +++ b/bolt/lib/Passes/Hugify.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "bolt/Passes/Hugify.h" -#include "llvm/Support/CommandLine.h" #define DEBUG_TYPE "bolt-hugify" diff --git a/bolt/lib/Passes/Inliner.cpp b/bolt/lib/Passes/Inliner.cpp index a3b2017aa32aa82dfc3dec7043bf2f9385d892d5..84e7d97067b0cf7bde944c7a139e4c5246a0ddf7 100644 --- a/bolt/lib/Passes/Inliner.cpp +++ b/bolt/lib/Passes/Inliner.cpp @@ -27,7 +27,6 @@ #include "bolt/Passes/Inliner.h" #include "bolt/Core/MCPlus.h" #include "llvm/Support/CommandLine.h" -#include #define DEBUG_TYPE "bolt-inliner" diff --git a/bolt/lib/Passes/ShrinkWrapping.cpp b/bolt/lib/Passes/ShrinkWrapping.cpp index 9a1f9d72623a388a275f204a72a0a092cf962123..176321c58dc903fdb62e76a237f31a15c7ffba12 100644 --- a/bolt/lib/Passes/ShrinkWrapping.cpp +++ b/bolt/lib/Passes/ShrinkWrapping.cpp @@ -11,7 +11,6 @@ //===----------------------------------------------------------------------===// #include "bolt/Passes/ShrinkWrapping.h" -#include "bolt/Core/MCPlus.h" #include "bolt/Passes/DataflowInfoManager.h" #include "bolt/Passes/MCF.h" #include "bolt/Utils/CommandLineOpts.h" @@ -680,16 +679,15 @@ void StackLayoutModifier::performChanges() { if (StackPtrReg != BC.MIB->getFramePointer()) Adjustment = -Adjustment; if (IsLoad) - Success = BC.MIB->createRestoreFromStack( - Inst, StackPtrReg, StackOffset + Adjustment, Reg, Size); + BC.MIB->createRestoreFromStack(Inst, StackPtrReg, + StackOffset + Adjustment, Reg, Size); else if (IsStore) - Success = BC.MIB->createSaveToStack( - Inst, StackPtrReg, StackOffset + Adjustment, Reg, Size); + BC.MIB->createSaveToStack(Inst, StackPtrReg, StackOffset + Adjustment, + Reg, Size); LLVM_DEBUG({ dbgs() << "Adjusted instruction: "; Inst.dump(); }); - assert(Success); } } } @@ -1653,19 +1651,13 @@ Expected ShrinkWrapping::createStackAccess(int SPVal, int FPVal, if (SPVal != StackPointerTracking::SUPERPOSITION && SPVal != StackPointerTracking::EMPTY) { if (FIE.IsLoad) { - if (!BC.MIB->createRestoreFromStack(NewInst, BC.MIB->getStackPointer(), - FIE.StackOffset - SPVal, FIE.RegOrImm, - FIE.Size)) { - return createFatalBOLTError( - "createRestoreFromStack: not supported on this platform\n"); - } - } else { - if (!BC.MIB->createSaveToStack(NewInst, BC.MIB->getStackPointer(), + BC.MIB->createRestoreFromStack(NewInst, BC.MIB->getStackPointer(), FIE.StackOffset - SPVal, FIE.RegOrImm, - FIE.Size)) { - return createFatalBOLTError( - "createSaveToStack: not supported on this platform\n"); - } + FIE.Size); + } else { + BC.MIB->createSaveToStack(NewInst, BC.MIB->getStackPointer(), + FIE.StackOffset - SPVal, FIE.RegOrImm, + FIE.Size); } if (CreatePushOrPop) BC.MIB->changeToPushOrPop(NewInst); @@ -1675,19 +1667,12 @@ Expected ShrinkWrapping::createStackAccess(int SPVal, int FPVal, FPVal != StackPointerTracking::EMPTY); if (FIE.IsLoad) { - if (!BC.MIB->createRestoreFromStack(NewInst, BC.MIB->getFramePointer(), - FIE.StackOffset - FPVal, FIE.RegOrImm, - FIE.Size)) { - return createFatalBOLTError( - "createRestoreFromStack: not supported on this platform\n"); - } - } else { - if (!BC.MIB->createSaveToStack(NewInst, BC.MIB->getFramePointer(), + BC.MIB->createRestoreFromStack(NewInst, BC.MIB->getFramePointer(), FIE.StackOffset - FPVal, FIE.RegOrImm, - FIE.Size)) { - return createFatalBOLTError( - "createSaveToStack: not supported on this platform\n"); - } + FIE.Size); + } else { + BC.MIB->createSaveToStack(NewInst, BC.MIB->getFramePointer(), + FIE.StackOffset - FPVal, FIE.RegOrImm, FIE.Size); } return NewInst; } diff --git a/bolt/lib/Passes/SplitFunctions.cpp b/bolt/lib/Passes/SplitFunctions.cpp index cdbb2a15f667c6b7dc2a06674028e583bbb27aaf..f9e634d15a97244c58adf185c0ea4ec80017079c 100644 --- a/bolt/lib/Passes/SplitFunctions.cpp +++ b/bolt/lib/Passes/SplitFunctions.cpp @@ -17,7 +17,6 @@ #include "bolt/Core/ParallelUtilities.h" #include "bolt/Utils/CommandLineOpts.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/Sequence.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/CommandLine.h" diff --git a/bolt/lib/Passes/TailDuplication.cpp b/bolt/lib/Passes/TailDuplication.cpp index 2163e3a6a008362586fc484efb97cfad71a43b52..463ea49527fa6cd5696ea1fde973f6e5e8c7e10e 100644 --- a/bolt/lib/Passes/TailDuplication.cpp +++ b/bolt/lib/Passes/TailDuplication.cpp @@ -13,9 +13,9 @@ #include "bolt/Passes/TailDuplication.h" #include "llvm/ADT/DenseMap.h" #include "llvm/MC/MCRegisterInfo.h" -#include #include +#include #define DEBUG_TYPE "taildup" diff --git a/bolt/lib/Passes/ValidateInternalCalls.cpp b/bolt/lib/Passes/ValidateInternalCalls.cpp index 54ae621159cfa3bcd1587d4a4a680eb53089c006..88df2e5b59f3895497312e1f8536ed8358694f1c 100644 --- a/bolt/lib/Passes/ValidateInternalCalls.cpp +++ b/bolt/lib/Passes/ValidateInternalCalls.cpp @@ -14,7 +14,6 @@ #include "bolt/Core/BinaryBasicBlock.h" #include "bolt/Passes/DataflowInfoManager.h" #include "bolt/Passes/FrameAnalysis.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCInstPrinter.h" #include #include diff --git a/bolt/lib/Profile/BoltAddressTranslation.cpp b/bolt/lib/Profile/BoltAddressTranslation.cpp index 5477d3b7d1c366f02a05fa7810144844702c97d0..bcd4a457ce3b491908b0a1617e66bee322cdd7c6 100644 --- a/bolt/lib/Profile/BoltAddressTranslation.cpp +++ b/bolt/lib/Profile/BoltAddressTranslation.cpp @@ -22,9 +22,10 @@ const char *BoltAddressTranslation::SECTION_NAME = ".note.bolt_bat"; void BoltAddressTranslation::writeEntriesForBB(MapTy &Map, const BinaryBasicBlock &BB, - uint64_t FuncAddress) { + uint64_t FuncInputAddress, + uint64_t FuncOutputAddress) { const uint64_t BBOutputOffset = - BB.getOutputAddressRange().first - FuncAddress; + BB.getOutputAddressRange().first - FuncOutputAddress; const uint32_t BBInputOffset = BB.getInputOffset(); // Every output BB must track back to an input BB for profile collection @@ -39,6 +40,14 @@ void BoltAddressTranslation::writeEntriesForBB(MapTy &Map, LLVM_DEBUG(dbgs() << "BB " << BB.getName() << "\n"); LLVM_DEBUG(dbgs() << " Key: " << Twine::utohexstr(BBOutputOffset) << " Val: " << Twine::utohexstr(BBInputOffset) << "\n"); + // NB: in `writeEntriesForBB` we use the input address because hashes are + // saved early in `saveMetadata` before output addresses are assigned. + const BBHashMapTy &BBHashMap = getBBHashMap(FuncInputAddress); + (void)BBHashMap; + LLVM_DEBUG( + dbgs() << formatv(" Hash: {0:x}\n", BBHashMap.getBBHash(BBInputOffset))); + LLVM_DEBUG( + dbgs() << formatv(" Index: {0}\n", BBHashMap.getBBIndex(BBInputOffset))); // In case of conflicts (same Key mapping to different Vals), the last // update takes precedence. Of course it is not ideal to have conflicts and // those happen when we have an empty BB that either contained only @@ -55,7 +64,7 @@ void BoltAddressTranslation::writeEntriesForBB(MapTy &Map, const auto InputAddress = BB.getFunction()->getAddress() + InputOffset; const auto OutputAddress = IOAddressMap.lookup(InputAddress); assert(OutputAddress && "Unknown instruction address"); - const auto OutputOffset = *OutputAddress - FuncAddress; + const auto OutputOffset = *OutputAddress - FuncOutputAddress; // Is this the first instruction in the BB? No need to duplicate the entry. if (OutputOffset == BBOutputOffset) @@ -72,20 +81,35 @@ void BoltAddressTranslation::write(const BinaryContext &BC, raw_ostream &OS) { LLVM_DEBUG(dbgs() << "BOLT-DEBUG: Writing BOLT Address Translation Tables\n"); for (auto &BFI : BC.getBinaryFunctions()) { const BinaryFunction &Function = BFI.second; + const uint64_t InputAddress = Function.getAddress(); + const uint64_t OutputAddress = Function.getOutputAddress(); // We don't need a translation table if the body of the function hasn't // changed if (Function.isIgnored() || (!BC.HasRelocations && !Function.isSimple())) continue; + uint32_t NumSecondaryEntryPoints = 0; + Function.forEachEntryPoint([&](uint64_t Offset, const MCSymbol *) { + if (!Offset) + return true; + ++NumSecondaryEntryPoints; + SecondaryEntryPointsMap[OutputAddress].push_back(Offset); + return true; + }); + LLVM_DEBUG(dbgs() << "Function name: " << Function.getPrintName() << "\n"); LLVM_DEBUG(dbgs() << " Address reference: 0x" << Twine::utohexstr(Function.getOutputAddress()) << "\n"); + LLVM_DEBUG(dbgs() << formatv(" Hash: {0:x}\n", getBFHash(OutputAddress))); + LLVM_DEBUG(dbgs() << " Secondary Entry Points: " << NumSecondaryEntryPoints + << '\n'); MapTy Map; for (const BinaryBasicBlock *const BB : Function.getLayout().getMainFragment()) - writeEntriesForBB(Map, *BB, Function.getOutputAddress()); + writeEntriesForBB(Map, *BB, InputAddress, OutputAddress); Maps.emplace(Function.getOutputAddress(), std::move(Map)); + ReverseMap.emplace(OutputAddress, InputAddress); if (!Function.isSplit()) continue; @@ -94,12 +118,12 @@ void BoltAddressTranslation::write(const BinaryContext &BC, raw_ostream &OS) { LLVM_DEBUG(dbgs() << " Cold part\n"); for (const FunctionFragment &FF : Function.getLayout().getSplitFragments()) { + ColdPartSource.emplace(FF.getAddress(), Function.getOutputAddress()); Map.clear(); for (const BinaryBasicBlock *const BB : FF) - writeEntriesForBB(Map, *BB, FF.getAddress()); + writeEntriesForBB(Map, *BB, InputAddress, FF.getAddress()); Maps.emplace(FF.getAddress(), std::move(Map)); - ColdPartSource.emplace(FF.getAddress(), Function.getOutputAddress()); } } @@ -109,6 +133,9 @@ void BoltAddressTranslation::write(const BinaryContext &BC, raw_ostream &OS) { writeMaps(Maps, PrevAddress, OS); BC.outs() << "BOLT-INFO: Wrote " << Maps.size() << " BAT maps\n"; + BC.outs() << "BOLT-INFO: Wrote " << FuncHashes.getNumFunctions() + << " function and " << FuncHashes.getNumBasicBlocks() + << " basic block hashes\n"; } APInt BoltAddressTranslation::calculateBranchEntriesBitMask(MapTy &Map, @@ -155,17 +182,38 @@ void BoltAddressTranslation::writeMaps(std::map &Maps, // Only process cold fragments in cold mode, and vice versa. if (Cold != ColdPartSource.count(Address)) continue; + // NB: in `writeMaps` we use the input address because hashes are saved + // early in `saveMetadata` before output addresses are assigned. + const uint64_t HotInputAddress = + ReverseMap[Cold ? ColdPartSource[Address] : Address]; MapTy &Map = MapEntry.second; const uint32_t NumEntries = Map.size(); LLVM_DEBUG(dbgs() << "Writing " << NumEntries << " entries for 0x" << Twine::utohexstr(Address) << ".\n"); encodeULEB128(Address - PrevAddress, OS); PrevAddress = Address; + const uint32_t NumSecondaryEntryPoints = + SecondaryEntryPointsMap.count(Address) + ? SecondaryEntryPointsMap[Address].size() + : 0; if (Cold) { size_t HotIndex = std::distance(ColdPartSource.begin(), ColdPartSource.find(Address)); encodeULEB128(HotIndex - PrevIndex, OS); PrevIndex = HotIndex; + } else { + // Function hash + size_t BFHash = getBFHash(HotInputAddress); + LLVM_DEBUG(dbgs() << "Hash: " << formatv("{0:x}\n", BFHash)); + OS.write(reinterpret_cast(&BFHash), 8); + // Number of basic blocks + size_t NumBasicBlocks = getBBHashMap(HotInputAddress).getNumBasicBlocks(); + LLVM_DEBUG(dbgs() << "Basic blocks: " << NumBasicBlocks << '\n'); + encodeULEB128(NumBasicBlocks, OS); + // Secondary entry points + encodeULEB128(NumSecondaryEntryPoints, OS); + LLVM_DEBUG(dbgs() << "Secondary Entry Points: " << NumSecondaryEntryPoints + << '\n'); } encodeULEB128(NumEntries, OS); // For hot fragments only: encode the number of equal offsets @@ -187,8 +235,10 @@ void BoltAddressTranslation::writeMaps(std::map &Maps, }); } } + const BBHashMapTy &BBHashMap = getBBHashMap(HotInputAddress); size_t Index = 0; uint64_t InOffset = 0; + size_t PrevBBIndex = 0; // Output and Input addresses and delta-encoded for (std::pair &KeyVal : Map) { const uint64_t OutputAddress = KeyVal.first + Address; @@ -197,6 +247,28 @@ void BoltAddressTranslation::writeMaps(std::map &Maps, if (Index++ >= EqualElems) encodeSLEB128(KeyVal.second - InOffset, OS); InOffset = KeyVal.second; // Keeping InOffset as if BRANCHENTRY is encoded + if ((InOffset & BRANCHENTRY) == 0) { + const bool IsBlock = BBHashMap.isInputBlock(InOffset >> 1); + unsigned BBIndex = IsBlock ? BBHashMap.getBBIndex(InOffset >> 1) : 0; + size_t BBHash = IsBlock ? BBHashMap.getBBHash(InOffset >> 1) : 0; + OS.write(reinterpret_cast(&BBHash), 8); + // Basic block index in the input binary + encodeULEB128(BBIndex - PrevBBIndex, OS); + PrevBBIndex = BBIndex; + LLVM_DEBUG(dbgs() << formatv("{0:x} -> {1:x} {2:x} {3}\n", KeyVal.first, + InOffset >> 1, BBHash, BBIndex)); + } + } + uint32_t PrevOffset = 0; + if (!Cold && NumSecondaryEntryPoints) { + LLVM_DEBUG(dbgs() << "Secondary entry points: "); + // Secondary entry point offsets, delta-encoded + for (uint32_t Offset : SecondaryEntryPointsMap[Address]) { + encodeULEB128(Offset - PrevOffset, OS); + LLVM_DEBUG(dbgs() << formatv("{0:x} ", Offset)); + PrevOffset = Offset; + } + LLVM_DEBUG(dbgs() << '\n'); } } } @@ -239,12 +311,31 @@ void BoltAddressTranslation::parseMaps(std::vector &HotFuncs, size_t HotIndex = 0; for (uint32_t I = 0; I < NumFunctions; ++I) { const uint64_t Address = PrevAddress + DE.getULEB128(&Offset, &Err); + uint64_t HotAddress = Cold ? 0 : Address; PrevAddress = Address; + uint32_t SecondaryEntryPoints = 0; if (Cold) { HotIndex += DE.getULEB128(&Offset, &Err); - ColdPartSource.emplace(Address, HotFuncs[HotIndex]); + HotAddress = HotFuncs[HotIndex]; + ColdPartSource.emplace(Address, HotAddress); } else { HotFuncs.push_back(Address); + // Function hash + const size_t FuncHash = DE.getU64(&Offset, &Err); + FuncHashes.addEntry(Address, FuncHash); + LLVM_DEBUG(dbgs() << formatv("{0:x}: hash {1:x}\n", Address, FuncHash)); + // Number of basic blocks + const size_t NumBasicBlocks = DE.getULEB128(&Offset, &Err); + NumBasicBlocksMap.emplace(Address, NumBasicBlocks); + LLVM_DEBUG(dbgs() << formatv("{0:x}: #bbs {1}, {2} bytes\n", Address, + NumBasicBlocks, + getULEB128Size(NumBasicBlocks))); + // Secondary entry points + SecondaryEntryPoints = DE.getULEB128(&Offset, &Err); + LLVM_DEBUG( + dbgs() << formatv("{0:x}: secondary entry points {1}, {2} bytes\n", + Address, SecondaryEntryPoints, + getULEB128Size(SecondaryEntryPoints))); } const uint32_t NumEntries = DE.getULEB128(&Offset, &Err); // Equal offsets, hot fragments only. @@ -275,6 +366,7 @@ void BoltAddressTranslation::parseMaps(std::vector &HotFuncs, LLVM_DEBUG(dbgs() << "Parsing " << NumEntries << " entries for 0x" << Twine::utohexstr(Address) << "\n"); uint64_t InputOffset = 0; + size_t BBIndex = 0; for (uint32_t J = 0; J < NumEntries; ++J) { const uint64_t OutputDelta = DE.getULEB128(&Offset, &Err); const uint64_t OutputAddress = PrevAddress + OutputDelta; @@ -288,14 +380,42 @@ void BoltAddressTranslation::parseMaps(std::vector &HotFuncs, InputOffset += InputDelta; } Map.insert(std::pair(OutputOffset, InputOffset)); - LLVM_DEBUG( - dbgs() << formatv("{0:x} -> {1:x} ({2}/{3}b -> {4}/{5}b), {6:x}\n", - OutputOffset, InputOffset, OutputDelta, - getULEB128Size(OutputDelta), InputDelta, - (J < EqualElems) ? 0 : getSLEB128Size(InputDelta), - OutputAddress)); + size_t BBHash = 0; + size_t BBIndexDelta = 0; + const bool IsBranchEntry = InputOffset & BRANCHENTRY; + if (!IsBranchEntry) { + BBHash = DE.getU64(&Offset, &Err); + BBIndexDelta = DE.getULEB128(&Offset, &Err); + BBIndex += BBIndexDelta; + // Map basic block hash to hot fragment by input offset + getBBHashMap(HotAddress).addEntry(InputOffset >> 1, BBIndex, BBHash); + } + LLVM_DEBUG({ + dbgs() << formatv( + "{0:x} -> {1:x} ({2}/{3}b -> {4}/{5}b), {6:x}", OutputOffset, + InputOffset, OutputDelta, getULEB128Size(OutputDelta), InputDelta, + (J < EqualElems) ? 0 : getSLEB128Size(InputDelta), OutputAddress); + if (!IsBranchEntry) { + dbgs() << formatv(" {0:x} {1}/{2}b", BBHash, BBIndex, + getULEB128Size(BBIndexDelta)); + } + dbgs() << '\n'; + }); } Maps.insert(std::pair(Address, Map)); + if (!Cold && SecondaryEntryPoints) { + uint32_t EntryPointOffset = 0; + LLVM_DEBUG(dbgs() << "Secondary entry points: "); + for (uint32_t EntryPointId = 0; EntryPointId != SecondaryEntryPoints; + ++EntryPointId) { + uint32_t OffsetDelta = DE.getULEB128(&Offset, &Err); + EntryPointOffset += OffsetDelta; + SecondaryEntryPointsMap[Address].push_back(EntryPointOffset); + LLVM_DEBUG(dbgs() << formatv("{0:x}/{1}b ", EntryPointOffset, + getULEB128Size(OffsetDelta))); + } + LLVM_DEBUG(dbgs() << '\n'); + } } } @@ -303,8 +423,15 @@ void BoltAddressTranslation::dump(raw_ostream &OS) { const size_t NumTables = Maps.size(); OS << "BAT tables for " << NumTables << " functions:\n"; for (const auto &MapEntry : Maps) { - OS << "Function Address: 0x" << Twine::utohexstr(MapEntry.first) << "\n"; + const uint64_t Address = MapEntry.first; + const uint64_t HotAddress = fetchParentAddress(Address); + OS << "Function Address: 0x" << Twine::utohexstr(Address); + if (HotAddress == 0) + OS << formatv(", hash: {0:x}", getBFHash(Address)); + OS << "\n"; OS << "BB mappings:\n"; + const BBHashMapTy &BBHashMap = + getBBHashMap(HotAddress ? HotAddress : Address); for (const auto &Entry : MapEntry.second) { const bool IsBranch = Entry.second & BRANCHENTRY; const uint32_t Val = Entry.second >> 1; // dropping BRANCHENTRY bit @@ -312,8 +439,17 @@ void BoltAddressTranslation::dump(raw_ostream &OS) { << "0x" << Twine::utohexstr(Val); if (IsBranch) OS << " (branch)"; + else + OS << formatv(" hash: {0:x}", BBHashMap.getBBHash(Val)); OS << "\n"; } + if (SecondaryEntryPointsMap.count(Address)) { + const std::vector &SecondaryEntryPoints = + SecondaryEntryPointsMap[Address]; + OS << SecondaryEntryPoints.size() << " secondary entry points:\n"; + for (uint32_t EntryPointOffset : SecondaryEntryPoints) + OS << formatv("{0:x}\n", EntryPointOffset); + } OS << "\n"; } const size_t NumColdParts = ColdPartSource.size(); @@ -432,12 +568,34 @@ void BoltAddressTranslation::saveMetadata(BinaryContext &BC) { if (BF.isIgnored() || (!BC.HasRelocations && !BF.isSimple())) continue; // Prepare function and block hashes - FuncHashes[BF.getAddress()].first = BF.computeHash(); + FuncHashes.addEntry(BF.getAddress(), BF.computeHash()); BF.computeBlockHashes(); + BBHashMapTy &BBHashMap = getBBHashMap(BF.getAddress()); + // Set BF/BB metadata for (const BinaryBasicBlock &BB : BF) - FuncHashes[BF.getAddress()].second.emplace(BB.getInputOffset(), - BB.getHash()); + BBHashMap.addEntry(BB.getInputOffset(), BB.getIndex(), BB.getHash()); } } + +std::unordered_map> +BoltAddressTranslation::getBFBranches(uint64_t OutputAddress) const { + std::unordered_map> Branches; + auto FuncIt = Maps.find(OutputAddress); + assert(FuncIt != Maps.end()); + std::vector InputOffsets; + for (const auto &KV : FuncIt->second) + InputOffsets.emplace_back(KV.second); + // Sort with LSB BRANCHENTRY bit. + llvm::sort(InputOffsets); + uint32_t BBOffset{0}; + for (uint32_t InOffset : InputOffsets) { + if (InOffset & BRANCHENTRY) + Branches[BBOffset].push_back(InOffset >> 1); + else + BBOffset = InOffset >> 1; + } + return Branches; +} + } // namespace bolt } // namespace llvm diff --git a/bolt/lib/Profile/CMakeLists.txt b/bolt/lib/Profile/CMakeLists.txt index 3a31a9cc191971dc487e1d54ade64c5b08f7565e..045ac47edb950bb1ebc99fd4dc56fb38cc652667 100644 --- a/bolt/lib/Profile/CMakeLists.txt +++ b/bolt/lib/Profile/CMakeLists.txt @@ -3,7 +3,6 @@ add_llvm_library(LLVMBOLTProfile DataAggregator.cpp DataReader.cpp Heatmap.cpp - ProfileReaderBase.cpp StaleProfileMatching.cpp YAMLProfileReader.cpp YAMLProfileWriter.cpp diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp index 6a64bcde911e668eca8ff2693501e0dabb744006..05099aa25ce22738687c0e3106e63302fadc0540 100644 --- a/bolt/lib/Profile/DataAggregator.cpp +++ b/bolt/lib/Profile/DataAggregator.cpp @@ -16,6 +16,7 @@ #include "bolt/Core/BinaryFunction.h" #include "bolt/Profile/BoltAddressTranslation.h" #include "bolt/Profile/Heatmap.h" +#include "bolt/Profile/YAMLProfileWriter.h" #include "bolt/Utils/CommandLineOpts.h" #include "bolt/Utils/Utils.h" #include "llvm/ADT/STLExtras.h" @@ -85,6 +86,7 @@ MaxSamples("max-samples", cl::cat(AggregatorCategory)); extern cl::opt ProfileFormat; +extern cl::opt SaveProfile; cl::opt ReadPreAggregated( "pa", cl::desc("skip perf and read data from a pre-aggregated file format"), @@ -594,10 +596,23 @@ Error DataAggregator::readProfile(BinaryContext &BC) { convertBranchData(Function); } - if (opts::AggregateOnly && - opts::ProfileFormat == opts::ProfileFormatKind::PF_Fdata) { - if (std::error_code EC = writeAggregatedFile(opts::OutputFilename)) - report_error("cannot create output data file", EC); + if (opts::AggregateOnly) { + if (opts::ProfileFormat == opts::ProfileFormatKind::PF_Fdata) + if (std::error_code EC = writeAggregatedFile(opts::OutputFilename)) + report_error("cannot create output data file", EC); + + // BAT YAML is handled by DataAggregator since normal YAML output requires + // CFG which is not available in BAT mode. + if (usesBAT()) { + // Postprocess split function profile for BAT + fixupBATProfile(BC); + if (opts::ProfileFormat == opts::ProfileFormatKind::PF_YAML) + if (std::error_code EC = writeBATYAML(BC, opts::OutputFilename)) + report_error("cannot create output data file", EC); + if (!opts::SaveProfile.empty()) + if (std::error_code EC = writeBATYAML(BC, opts::SaveProfile)) + report_error("cannot create output data file", EC); + } } return Error::success(); @@ -2258,6 +2273,181 @@ DataAggregator::writeAggregatedFile(StringRef OutputFilename) const { return std::error_code(); } +void DataAggregator::fixupBATProfile(BinaryContext &BC) { + for (auto &[FuncName, Branches] : NamesToBranches) { + BinaryData *BD = BC.getBinaryDataByName(FuncName); + assert(BD); + uint64_t FuncAddress = BD->getAddress(); + if (!BAT->isBATFunction(FuncAddress)) + continue; + // Filter out cold fragments + if (!BD->getSectionName().equals(BC.getMainCodeSectionName())) + continue; + // Convert inter-branches between hot and cold fragments into + // intra-branches. + for (auto &[OffsetFrom, CallToMap] : Branches.InterIndex) { + for (auto &[CallToLoc, CallToIdx] : CallToMap) { + if (CallToLoc.Name != FuncName) + continue; + Branches.IntraIndex[OffsetFrom][CallToLoc.Offset] = CallToIdx; + Branches.InterIndex[OffsetFrom].erase(CallToLoc); + } + } + } +} + +std::error_code DataAggregator::writeBATYAML(BinaryContext &BC, + StringRef OutputFilename) const { + std::error_code EC; + raw_fd_ostream OutFile(OutputFilename, EC, sys::fs::OpenFlags::OF_None); + if (EC) + return EC; + + yaml::bolt::BinaryProfile BP; + + // Fill out the header info. + BP.Header.Version = 1; + BP.Header.FileName = std::string(BC.getFilename()); + std::optional BuildID = BC.getFileBuildID(); + BP.Header.Id = BuildID ? std::string(*BuildID) : ""; + BP.Header.Origin = std::string(getReaderName()); + // Only the input binary layout order is supported. + BP.Header.IsDFSOrder = false; + // FIXME: Need to match hash function used to produce BAT hashes. + BP.Header.HashFunction = HashFunction::Default; + + ListSeparator LS(","); + raw_string_ostream EventNamesOS(BP.Header.EventNames); + for (const StringMapEntry &EventEntry : EventNames) + EventNamesOS << LS << EventEntry.first().str(); + + BP.Header.Flags = opts::BasicAggregation ? BinaryFunction::PF_SAMPLE + : BinaryFunction::PF_LBR; + + if (!opts::BasicAggregation) { + // Convert profile for functions not covered by BAT + for (auto &BFI : BC.getBinaryFunctions()) { + BinaryFunction &Function = BFI.second; + if (!Function.hasProfile()) + continue; + if (BAT->isBATFunction(Function.getAddress())) + continue; + BP.Functions.emplace_back( + YAMLProfileWriter::convert(Function, /*UseDFS=*/false)); + } + + for (const auto &KV : NamesToBranches) { + const StringRef FuncName = KV.first; + const FuncBranchData &Branches = KV.second; + yaml::bolt::BinaryFunctionProfile YamlBF; + BinaryData *BD = BC.getBinaryDataByName(FuncName); + assert(BD); + uint64_t FuncAddress = BD->getAddress(); + if (!BAT->isBATFunction(FuncAddress)) + continue; + // Filter out cold fragments + if (!BD->getSectionName().equals(BC.getMainCodeSectionName())) + continue; + BinaryFunction *BF = BC.getBinaryFunctionAtAddress(FuncAddress); + assert(BF); + YamlBF.Name = FuncName.str(); + YamlBF.Id = BF->getFunctionNumber(); + YamlBF.Hash = BAT->getBFHash(FuncAddress); + YamlBF.ExecCount = BF->getKnownExecutionCount(); + YamlBF.NumBasicBlocks = BAT->getNumBasicBlocks(FuncAddress); + const BoltAddressTranslation::BBHashMapTy &BlockMap = + BAT->getBBHashMap(FuncAddress); + + auto addSuccProfile = [&](yaml::bolt::BinaryBasicBlockProfile &YamlBB, + uint64_t SuccOffset, unsigned SuccDataIdx) { + const llvm::bolt::BranchInfo &BI = Branches.Data.at(SuccDataIdx); + yaml::bolt::SuccessorInfo SI; + SI.Index = BlockMap.getBBIndex(SuccOffset); + SI.Count = BI.Branches; + SI.Mispreds = BI.Mispreds; + YamlBB.Successors.emplace_back(SI); + }; + + std::unordered_map> BFBranches = + BAT->getBFBranches(FuncAddress); + + auto addCallsProfile = [&](yaml::bolt::BinaryBasicBlockProfile &YamlBB, + uint64_t Offset) { + // Iterate over BRANCHENTRY records in the current block + for (uint32_t BranchOffset : BFBranches[Offset]) { + if (!Branches.InterIndex.contains(BranchOffset)) + continue; + for (const auto &[CallToLoc, CallToIdx] : + Branches.InterIndex.at(BranchOffset)) { + const llvm::bolt::BranchInfo &BI = Branches.Data.at(CallToIdx); + yaml::bolt::CallSiteInfo YamlCSI; + YamlCSI.DestId = 0; // designated for unknown functions + YamlCSI.EntryDiscriminator = 0; + YamlCSI.Count = BI.Branches; + YamlCSI.Mispreds = BI.Mispreds; + YamlCSI.Offset = BranchOffset - Offset; + BinaryData *CallTargetBD = BC.getBinaryDataByName(CallToLoc.Name); + if (!CallTargetBD) { + YamlBB.CallSites.emplace_back(YamlCSI); + continue; + } + uint64_t CallTargetAddress = CallTargetBD->getAddress(); + BinaryFunction *CallTargetBF = + BC.getBinaryFunctionAtAddress(CallTargetAddress); + if (!CallTargetBF) { + YamlBB.CallSites.emplace_back(YamlCSI); + continue; + } + // Calls between hot and cold fragments must be handled in + // fixupBATProfile. + assert(CallTargetBF != BF && "invalid CallTargetBF"); + YamlCSI.DestId = CallTargetBF->getFunctionNumber(); + if (CallToLoc.Offset) { + if (BAT->isBATFunction(CallTargetAddress)) { + LLVM_DEBUG(dbgs() << "BOLT-DEBUG: Unsupported secondary " + "entry point in BAT function " + << CallToLoc.Name << '\n'); + } else if (const BinaryBasicBlock *CallTargetBB = + CallTargetBF->getBasicBlockAtOffset( + CallToLoc.Offset)) { + // Only record true call information, ignoring returns (normally + // won't have a target basic block) and jumps to the landing + // pads (not an entry point). + if (CallTargetBB->isEntryPoint()) { + YamlCSI.EntryDiscriminator = + CallTargetBF->getEntryIDForSymbol( + CallTargetBB->getLabel()); + } + } + } + YamlBB.CallSites.emplace_back(YamlCSI); + } + } + }; + + for (const auto &[FromOffset, SuccKV] : Branches.IntraIndex) { + yaml::bolt::BinaryBasicBlockProfile YamlBB; + if (!BlockMap.isInputBlock(FromOffset)) + continue; + YamlBB.Index = BlockMap.getBBIndex(FromOffset); + YamlBB.Hash = BlockMap.getBBHash(FromOffset); + for (const auto &[SuccOffset, SuccDataIdx] : SuccKV) + addSuccProfile(YamlBB, SuccOffset, SuccDataIdx); + addCallsProfile(YamlBB, FromOffset); + if (YamlBB.ExecCount || !YamlBB.Successors.empty() || + !YamlBB.CallSites.empty()) + YamlBF.Blocks.emplace_back(YamlBB); + } + BP.Functions.emplace_back(YamlBF); + } + } + + // Write the profile. + yaml::Output Out(OutFile, nullptr, 0); + Out << BP; + return std::error_code(); +} + void DataAggregator::dump() const { DataReader::dump(); } void DataAggregator::dump(const LBREntry &LBR) const { diff --git a/bolt/lib/Profile/DataReader.cpp b/bolt/lib/Profile/DataReader.cpp index aa21eb121ad65256695dfff0318058879c0b203c..67f357fe4d3f0c42f704a52ca163e328652e7136 100644 --- a/bolt/lib/Profile/DataReader.cpp +++ b/bolt/lib/Profile/DataReader.cpp @@ -18,7 +18,6 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Errc.h" -#include #undef DEBUG_TYPE #define DEBUG_TYPE "bolt-prof" diff --git a/bolt/lib/Profile/Heatmap.cpp b/bolt/lib/Profile/Heatmap.cpp index 13541f6f6a4b64200429bf02ce2885d1e373835a..210a5cc98c1041035e7eb470d6a62fa1b2739873 100644 --- a/bolt/lib/Profile/Heatmap.cpp +++ b/bolt/lib/Profile/Heatmap.cpp @@ -10,7 +10,6 @@ #include "bolt/Utils/CommandLineOpts.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" diff --git a/bolt/lib/Profile/StaleProfileMatching.cpp b/bolt/lib/Profile/StaleProfileMatching.cpp index 631ccaec6ae61471edd81efcec353256c1d56d04..016962ff34d8dff0637ff6880f55f15aef6b0b19 100644 --- a/bolt/lib/Profile/StaleProfileMatching.cpp +++ b/bolt/lib/Profile/StaleProfileMatching.cpp @@ -705,6 +705,9 @@ void assignProfile(BinaryFunction &BF, bool YAMLProfileReader::inferStaleProfile( BinaryFunction &BF, const yaml::bolt::BinaryFunctionProfile &YamlBF) { + if (!BF.hasCFG()) + return false; + LLVM_DEBUG(dbgs() << "BOLT-INFO: applying profile inference for " << "\"" << BF.getPrintName() << "\"\n"); diff --git a/bolt/lib/Profile/YAMLProfileWriter.cpp b/bolt/lib/Profile/YAMLProfileWriter.cpp index dffd851a1d6f7743bdbf520306b01926e7102384..0f082086c1fc24810d97e2a078c6648eda753585 100644 --- a/bolt/lib/Profile/YAMLProfileWriter.cpp +++ b/bolt/lib/Profile/YAMLProfileWriter.cpp @@ -10,7 +10,6 @@ #include "bolt/Core/BinaryBasicBlock.h" #include "bolt/Core/BinaryFunction.h" #include "bolt/Profile/ProfileReaderBase.h" -#include "bolt/Profile/ProfileYAMLMapping.h" #include "bolt/Rewrite/RewriteInstance.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" @@ -26,15 +25,34 @@ extern llvm::cl::opt ProfileUseDFS; namespace llvm { namespace bolt { -namespace { -void convert(const BinaryFunction &BF, - yaml::bolt::BinaryFunctionProfile &YamlBF) { +/// Set CallSiteInfo destination fields from \p Symbol and return a target +/// BinaryFunction for that symbol. +static const BinaryFunction *setCSIDestination(const BinaryContext &BC, + yaml::bolt::CallSiteInfo &CSI, + const MCSymbol *Symbol) { + CSI.DestId = 0; // designated for unknown functions + CSI.EntryDiscriminator = 0; + if (Symbol) { + uint64_t EntryID = 0; + if (const BinaryFunction *const Callee = + BC.getFunctionForSymbol(Symbol, &EntryID)) { + CSI.DestId = Callee->getFunctionNumber(); + CSI.EntryDiscriminator = EntryID; + return Callee; + } + } + return nullptr; +} + +yaml::bolt::BinaryFunctionProfile +YAMLProfileWriter::convert(const BinaryFunction &BF, bool UseDFS) { + yaml::bolt::BinaryFunctionProfile YamlBF; const BinaryContext &BC = BF.getBinaryContext(); const uint16_t LBRProfile = BF.getProfileFlags() & BinaryFunction::PF_LBR; // Prepare function and block hashes - BF.computeHash(opts::ProfileUseDFS); + BF.computeHash(UseDFS); BF.computeBlockHashes(); YamlBF.Name = BF.getPrintName(); @@ -44,7 +62,7 @@ void convert(const BinaryFunction &BF, YamlBF.ExecCount = BF.getKnownExecutionCount(); BinaryFunction::BasicBlockOrderType Order; - llvm::copy(opts::ProfileUseDFS ? BF.dfs() : BF.getLayout().blocks(), + llvm::copy(UseDFS ? BF.dfs() : BF.getLayout().blocks(), std::back_inserter(Order)); for (const BinaryBasicBlock *BB : Order) { @@ -80,46 +98,29 @@ void convert(const BinaryFunction &BF, continue; for (const IndirectCallProfile &CSP : ICSP.get()) { StringRef TargetName = ""; - CSI.DestId = 0; // designated for unknown functions - CSI.EntryDiscriminator = 0; - if (CSP.Symbol) { - const BinaryFunction *Callee = BC.getFunctionForSymbol(CSP.Symbol); - if (Callee) { - CSI.DestId = Callee->getFunctionNumber(); - TargetName = Callee->getOneName(); - } - } + const BinaryFunction *Callee = setCSIDestination(BC, CSI, CSP.Symbol); + if (Callee) + TargetName = Callee->getOneName(); CSI.Count = CSP.Count; CSI.Mispreds = CSP.Mispreds; CSTargets.emplace_back(TargetName, CSI); } } else { // direct call or a tail call - uint64_t EntryID = 0; - CSI.DestId = 0; StringRef TargetName = ""; const MCSymbol *CalleeSymbol = BC.MIB->getTargetSymbol(Instr); const BinaryFunction *const Callee = - BC.getFunctionForSymbol(CalleeSymbol, &EntryID); - if (Callee) { - CSI.DestId = Callee->getFunctionNumber(); - CSI.EntryDiscriminator = EntryID; + setCSIDestination(BC, CSI, CalleeSymbol); + if (Callee) TargetName = Callee->getOneName(); - } + auto getAnnotationWithDefault = [&](const MCInst &Inst, StringRef Ann) { + return BC.MIB->getAnnotationWithDefault(Instr, Ann, 0ull); + }; if (BC.MIB->getConditionalTailCall(Instr)) { - auto CTCCount = - BC.MIB->tryGetAnnotationAs(Instr, "CTCTakenCount"); - if (CTCCount) { - CSI.Count = *CTCCount; - auto CTCMispreds = - BC.MIB->tryGetAnnotationAs(Instr, "CTCMispredCount"); - if (CTCMispreds) - CSI.Mispreds = *CTCMispreds; - } + CSI.Count = getAnnotationWithDefault(Instr, "CTCTakenCount"); + CSI.Mispreds = getAnnotationWithDefault(Instr, "CTCMispredCount"); } else { - auto Count = BC.MIB->tryGetAnnotationAs(Instr, "Count"); - if (Count) - CSI.Count = *Count; + CSI.Count = getAnnotationWithDefault(Instr, "Count"); } if (CSI.Count) @@ -165,8 +166,8 @@ void convert(const BinaryFunction &BF, YamlBF.Blocks.emplace_back(YamlBB); } + return YamlBF; } -} // end anonymous namespace std::error_code YAMLProfileWriter::writeProfile(const RewriteInstance &RI) { const BinaryContext &BC = RI.getBinaryContext(); @@ -222,9 +223,7 @@ std::error_code YAMLProfileWriter::writeProfile(const RewriteInstance &RI) { if (!BF.hasValidProfile() && !RI.getProfileReader()->isTrustedSource()) continue; - yaml::bolt::BinaryFunctionProfile YamlBF; - convert(BF, YamlBF); - BP.Functions.emplace_back(YamlBF); + BP.Functions.emplace_back(convert(BF, opts::ProfileUseDFS)); } } diff --git a/bolt/lib/Rewrite/BinaryPassManager.cpp b/bolt/lib/Rewrite/BinaryPassManager.cpp index 489b33fe1c7c201aa11b07f76d5d369170b9ef02..6c26bb7957269d71c06da0d33bfe80984b0f4e16 100644 --- a/bolt/lib/Rewrite/BinaryPassManager.cpp +++ b/bolt/lib/Rewrite/BinaryPassManager.cpp @@ -72,7 +72,7 @@ static cl::opt JTFootprintReductionFlag( "instructions at jump sites"), cl::cat(BoltOptCategory)); -static cl::opt +cl::opt KeepNops("keep-nops", cl::desc("keep no-op instructions. By default they are removed."), cl::Hidden, cl::cat(BoltOptCategory)); diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp index 85c2397dcc5b25ad18d4de453e21a3f4ce9e991d..feeba89a40dc4d03c48b3836c0e27fa5f68903d7 100644 --- a/bolt/lib/Rewrite/DWARFRewriter.cpp +++ b/bolt/lib/Rewrite/DWARFRewriter.cpp @@ -14,7 +14,6 @@ #include "bolt/Core/DynoStats.h" #include "bolt/Core/ParallelUtilities.h" #include "bolt/Rewrite/RewriteInstance.h" -#include "bolt/Utils/Utils.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -283,10 +282,9 @@ public: DIEStreamer(DIEBuilder *DIEBldr, DWARFRewriter &Rewriter, DWARFLinkerBase::OutputFileType OutFileType, raw_pwrite_stream &OutFile, - std::function Translator, DWARFLinkerBase::MessageHandlerTy Warning) - : DwarfStreamer(OutFileType, OutFile, Translator, Warning), - DIEBldr(DIEBldr), Rewriter(Rewriter){}; + : DwarfStreamer(OutFileType, OutFile, Warning), DIEBldr(DIEBldr), + Rewriter(Rewriter){}; using DwarfStreamer::emitCompileUnitHeader; @@ -376,12 +374,11 @@ static cl::opt AlwaysConvertToRanges( extern cl::opt CompDirOverride; } // namespace opts -static bool getLowAndHighPC(const DIE &Die, const DWARFUnit &DU, - uint64_t &LowPC, uint64_t &HighPC, - uint64_t &SectionIndex) { +/// If DW_AT_low_pc exists sets LowPC and returns true. +static bool getLowPC(const DIE &Die, const DWARFUnit &DU, uint64_t &LowPC, + uint64_t &SectionIndex) { DIEValue DvalLowPc = Die.findAttribute(dwarf::DW_AT_low_pc); - DIEValue DvalHighPc = Die.findAttribute(dwarf::DW_AT_high_pc); - if (!DvalLowPc || !DvalHighPc) + if (!DvalLowPc) return false; dwarf::Form Form = DvalLowPc.getForm(); @@ -404,14 +401,39 @@ static bool getLowAndHighPC(const DIE &Die, const DWARFUnit &DU, LowPC = LowPcValue; SectionIndex = 0; } + return true; +} + +/// If DW_AT_high_pc exists sets HighPC and returns true. +static bool getHighPC(const DIE &Die, const uint64_t LowPC, uint64_t &HighPC) { + DIEValue DvalHighPc = Die.findAttribute(dwarf::DW_AT_high_pc); + if (!DvalHighPc) + return false; if (DvalHighPc.getForm() == dwarf::DW_FORM_addr) HighPC = DvalHighPc.getDIEInteger().getValue(); else HighPC = LowPC + DvalHighPc.getDIEInteger().getValue(); - return true; } +/// If DW_AT_low_pc and DW_AT_high_pc exist sets LowPC and HighPC and returns +/// true. +static bool getLowAndHighPC(const DIE &Die, const DWARFUnit &DU, + uint64_t &LowPC, uint64_t &HighPC, + uint64_t &SectionIndex) { + uint64_t TempLowPC = LowPC; + uint64_t TempHighPC = HighPC; + uint64_t TempSectionIndex = SectionIndex; + if (getLowPC(Die, DU, TempLowPC, TempSectionIndex) && + getHighPC(Die, TempLowPC, TempHighPC)) { + LowPC = TempLowPC; + HighPC = TempHighPC; + SectionIndex = TempSectionIndex; + return true; + } + return false; +} + static Expected getDIEAddressRanges(const DIE &Die, DWARFUnit &DU) { uint64_t LowPC, HighPC, Index; @@ -469,7 +491,6 @@ createDIEStreamer(const Triple &TheTriple, raw_pwrite_stream &OutFile, std::unique_ptr Streamer = std::make_unique( &DIEBldr, Rewriter, DWARFLinkerBase::OutputFileType::Object, OutFile, - [](StringRef Input) -> StringRef { return Input; }, [&](const Twine &Warning, StringRef Context, const DWARFDie *) {}); Error Err = Streamer->init(TheTriple, Swift5ReflectionSegmentName); if (Err) @@ -1250,10 +1271,9 @@ void DWARFRewriter::updateUnitDebugInfo( } } } else if (LowPCAttrInfo) { - const std::optional Result = - LowPCAttrInfo.getDIEInteger().getValue(); - if (Result.has_value()) { - const uint64_t Address = Result.value(); + uint64_t Address = 0; + uint64_t SectionIndex = 0; + if (getLowPC(*Die, Unit, Address, SectionIndex)) { uint64_t NewAddress = 0; if (const BinaryFunction *Function = BC.getBinaryFunctionContainingAddress(Address)) { @@ -1664,7 +1684,7 @@ namespace { std::unique_ptr createDwarfOnlyBC(const object::ObjectFile &File) { return cantFail(BinaryContext::createBinaryContext( - &File, false, + File.makeTriple(), File.getFileName(), nullptr, false, DWARFContext::create(File, DWARFContext::ProcessDebugRelocations::Ignore, nullptr, "", WithColor::defaultErrorHandler, WithColor::defaultWarningHandler), diff --git a/bolt/lib/Rewrite/JITLinkLinker.cpp b/bolt/lib/Rewrite/JITLinkLinker.cpp index 66e129bf1d05db7a8136a6c1ae819e4d69315ae5..be8f9dd03467e17d297b26e94bafbbabcde68c1c 100644 --- a/bolt/lib/Rewrite/JITLinkLinker.cpp +++ b/bolt/lib/Rewrite/JITLinkLinker.cpp @@ -5,9 +5,11 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #include "bolt/Rewrite/JITLinkLinker.h" +#include "bolt/Core/BinaryContext.h" #include "bolt/Core/BinaryData.h" -#include "bolt/Rewrite/RewriteInstance.h" +#include "bolt/Core/BinarySection.h" #include "llvm/ExecutionEngine/JITLink/ELF_riscv.h" #include "llvm/ExecutionEngine/JITLink/JITLink.h" #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" diff --git a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp index a2bfd45a64e3040d5a8c9caf889ea24d0d780734..d96199e020d31a159c9505d846a3985d9df2223c 100644 --- a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp +++ b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp @@ -14,7 +14,9 @@ #include "bolt/Rewrite/MetadataRewriter.h" #include "bolt/Rewrite/MetadataRewriters.h" #include "bolt/Utils/CommandLineOpts.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" #include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -65,6 +67,16 @@ static cl::opt DumpStaticCalls("dump-static-calls", cl::init(false), cl::Hidden, cl::cat(BoltCategory)); +static cl::opt + DumpStaticKeys("dump-static-keys", + cl::desc("dump Linux kernel static keys jump table"), + cl::init(false), cl::Hidden, cl::cat(BoltCategory)); + +static cl::opt LongJumpLabels( + "long-jump-labels", + cl::desc("always use long jumps/nops for Linux kernel static keys"), + cl::init(false), cl::Hidden, cl::cat(BoltCategory)); + static cl::opt PrintORC("print-orc", cl::desc("print ORC unwind information for instructions"), @@ -151,6 +163,20 @@ class LinuxKernelRewriter final : public MetadataRewriter { /// Number of entries in the input file ORC sections. uint64_t NumORCEntries = 0; + /// Section containing static keys jump table. + ErrorOr StaticKeysJumpSection = std::errc::bad_address; + uint64_t StaticKeysJumpTableAddress = 0; + static constexpr size_t STATIC_KEYS_JUMP_ENTRY_SIZE = 8; + + struct JumpInfoEntry { + bool Likely; + bool InitValue; + }; + SmallVector JumpInfo; + + /// Static key entries that need nop conversion. + DenseSet NopIDs; + /// Section containing static call table. ErrorOr StaticCallSection = std::errc::bad_address; uint64_t StaticCallTableAddress = 0; @@ -186,6 +212,11 @@ class LinuxKernelRewriter final : public MetadataRewriter { /// Size of bug_entry struct. static constexpr size_t BUG_TABLE_ENTRY_SIZE = 12; + /// List of bug entries per function. + using FunctionBugListType = + DenseMap>; + FunctionBugListType FunctionBugList; + /// .pci_fixup section. ErrorOr PCIFixupSection = std::errc::bad_address; static constexpr size_t PCI_FIXUP_ENTRY_SIZE = 16; @@ -226,15 +257,28 @@ class LinuxKernelRewriter final : public MetadataRewriter { /// Paravirtual instruction patch sites. Error readParaInstructions(); + Error rewriteParaInstructions(); + /// __bug_table section handling. Error readBugTable(); + Error rewriteBugTable(); + + /// Do no process functions containing instruction annotated with + /// \p Annotation. + void skipFunctionsWithAnnotation(StringRef Annotation) const; - /// Read alternative instruction info from .altinstructions. + /// Handle alternative instruction info from .altinstructions. Error readAltInstructions(); + Error rewriteAltInstructions(); /// Read .pci_fixup Error readPCIFixupTable(); + /// Handle static keys jump table. + Error readStaticKeysJumpTable(); + Error rewriteStaticKeysJumpTable(); + Error updateStaticKeysJumpTablePostEmit(); + /// Mark instructions referenced by kernel metadata. Error markInstructions(); @@ -268,6 +312,9 @@ public: if (Error E = readPCIFixupTable()) return E; + if (Error E = readStaticKeysJumpTable()) + return E; + return Error::success(); } @@ -284,18 +331,33 @@ public: if (Error E = rewriteExceptionTable()) return E; + if (Error E = rewriteAltInstructions()) + return E; + + if (Error E = rewriteParaInstructions()) + return E; + if (Error E = rewriteORCTables()) return E; if (Error E = rewriteStaticCalls()) return E; + if (Error E = rewriteStaticKeysJumpTable()) + return E; + + if (Error E = rewriteBugTable()) + return E; + return Error::success(); } Error postEmitFinalizer() override { updateLKMarkers(); + if (Error E = updateStaticKeysJumpTablePostEmit()) + return E; + return Error::success(); } }; @@ -1086,16 +1148,43 @@ Error LinuxKernelRewriter::readParaInstructions() { return Error::success(); } +void LinuxKernelRewriter::skipFunctionsWithAnnotation( + StringRef Annotation) const { + for (BinaryFunction &BF : llvm::make_second_range(BC.getBinaryFunctions())) { + if (!BC.shouldEmit(BF)) + continue; + for (const BinaryBasicBlock &BB : BF) { + const bool HasAnnotation = llvm::any_of(BB, [&](const MCInst &Inst) { + return BC.MIB->hasAnnotation(Inst, Annotation); + }); + if (HasAnnotation) { + BF.setSimple(false); + break; + } + } + } +} + +Error LinuxKernelRewriter::rewriteParaInstructions() { + // Disable output of functions with paravirtual instructions before the + // rewrite support is complete. + skipFunctionsWithAnnotation("ParaSite"); + + return Error::success(); +} + /// Process __bug_table section. -/// This section contains information useful for kernel debugging. +/// This section contains information useful for kernel debugging, mostly +/// utilized by WARN()/WARN_ON() macros and deprecated BUG()/BUG_ON(). +/// /// Each entry in the section is a struct bug_entry that contains a pointer to /// the ud2 instruction corresponding to the bug, corresponding file name (both /// pointers use PC relative offset addressing), line number, and flags. /// The definition of the struct bug_entry can be found in -/// `include/asm-generic/bug.h` -/// -/// NB: find_bug() uses linear search to match an address to an entry in the bug -/// table. Hence there is no need to sort entries when rewriting the table. +/// `include/asm-generic/bug.h`. The first entry in the struct is an instruction +/// address encoded as a PC-relative offset. In theory, it could be an absolute +/// address if CONFIG_GENERIC_BUG_RELATIVE_POINTERS is not set, but in practice +/// the kernel code relies on it being a relative offset on x86-64. Error LinuxKernelRewriter::readBugTable() { BugTableSection = BC.getUniqueSectionByName("__bug_table"); if (!BugTableSection) @@ -1138,6 +1227,8 @@ Error LinuxKernelRewriter::readBugTable() { " referenced by bug table entry %d", InstAddress, EntryID); BC.MIB->addAnnotation(*Inst, "BugEntry", EntryID); + + FunctionBugList[BF].push_back(EntryID); } } @@ -1146,6 +1237,52 @@ Error LinuxKernelRewriter::readBugTable() { return Error::success(); } +/// find_bug() uses linear search to match an address to an entry in the bug +/// table. Hence, there is no need to sort entries when rewriting the table. +/// When we need to erase an entry, we set its instruction address to zero. +Error LinuxKernelRewriter::rewriteBugTable() { + if (!BugTableSection) + return Error::success(); + + for (BinaryFunction &BF : llvm::make_second_range(BC.getBinaryFunctions())) { + if (!BC.shouldEmit(BF)) + continue; + + if (!FunctionBugList.count(&BF)) + continue; + + // Bugs that will be emitted for this function. + DenseSet EmittedIDs; + for (BinaryBasicBlock &BB : BF) { + for (MCInst &Inst : BB) { + if (!BC.MIB->hasAnnotation(Inst, "BugEntry")) + continue; + const uint32_t ID = BC.MIB->getAnnotationAs(Inst, "BugEntry"); + EmittedIDs.insert(ID); + + // Create a relocation entry for this bug entry. + MCSymbol *Label = + BC.MIB->getOrCreateInstLabel(Inst, "__BUG_", BC.Ctx.get()); + const uint64_t EntryOffset = (ID - 1) * BUG_TABLE_ENTRY_SIZE; + BugTableSection->addRelocation(EntryOffset, Label, ELF::R_X86_64_PC32, + /*Addend*/ 0); + } + } + + // Clear bug entries that were not emitted for this function, e.g. as a + // result of DCE, but setting their instruction address to zero. + for (const uint32_t ID : FunctionBugList[&BF]) { + if (!EmittedIDs.count(ID)) { + const uint64_t EntryOffset = (ID - 1) * BUG_TABLE_ENTRY_SIZE; + BugTableSection->addRelocation(EntryOffset, nullptr, ELF::R_X86_64_PC32, + /*Addend*/ 0); + } + } + } + + return Error::success(); +} + /// The kernel can replace certain instruction sequences depending on hardware /// it is running on and features specified during boot time. The information /// about alternative instruction sequences is stored in .altinstructions @@ -1265,6 +1402,14 @@ Error LinuxKernelRewriter::readAltInstructions() { return Error::success(); } +Error LinuxKernelRewriter::rewriteAltInstructions() { + // Disable output of functions with alt instructions before the rewrite + // support is complete. + skipFunctionsWithAnnotation("AltInst"); + + return Error::success(); +} + /// When the Linux kernel needs to handle an error associated with a given PCI /// device, it uses a table stored in .pci_fixup section to locate a fixup code /// specific to the vendor and the problematic device. The section contains a @@ -1343,6 +1488,353 @@ Error LinuxKernelRewriter::readPCIFixupTable() { return Error::success(); } +/// Runtime code modification used by static keys is the most ubiquitous +/// self-modifying feature of the Linux kernel. The idea is to eliminate the +/// condition check and associated conditional jump on a hot path if that +/// condition (based on a boolean value of a static key) does not change often. +/// Whenever the condition changes, the kernel runtime modifies all code paths +/// associated with that key flipping the code between nop and (unconditional) +/// jump. The information about the code is stored in a static key jump table +/// and contains the list of entries of the following type from +/// include/linux/jump_label.h: +// +/// struct jump_entry { +/// s32 code; +/// s32 target; +/// long key; // key may be far away from the core kernel under KASLR +/// }; +/// +/// The list does not have to be stored in any sorted way, but it is sorted at +/// boot time (or module initialization time) first by "key" and then by "code". +/// jump_label_sort_entries() is responsible for sorting the table. +/// +/// The key in jump_entry structure uses lower two bits of the key address +/// (which itself is aligned) to store extra information. We are interested in +/// the lower bit which indicates if the key is likely to be set on the code +/// path associated with this jump_entry. +/// +/// static_key_{enable,disable}() functions modify the code based on key and +/// jump table entries. +/// +/// jump_label_update() updates all code entries for a given key. Batch mode is +/// used for x86. +/// +/// The actual patching happens in text_poke_bp_batch() that overrides the first +/// byte of the sequence with int3 before proceeding with actual code +/// replacement. +Error LinuxKernelRewriter::readStaticKeysJumpTable() { + const BinaryData *StaticKeysJumpTable = + BC.getBinaryDataByName("__start___jump_table"); + if (!StaticKeysJumpTable) + return Error::success(); + + StaticKeysJumpTableAddress = StaticKeysJumpTable->getAddress(); + + const BinaryData *Stop = BC.getBinaryDataByName("__stop___jump_table"); + if (!Stop) + return createStringError(errc::executable_format_error, + "missing __stop___jump_table symbol"); + + ErrorOr ErrorOrSection = + BC.getSectionForAddress(StaticKeysJumpTableAddress); + if (!ErrorOrSection) + return createStringError(errc::executable_format_error, + "no section matching __start___jump_table"); + + StaticKeysJumpSection = *ErrorOrSection; + if (!StaticKeysJumpSection->containsAddress(Stop->getAddress() - 1)) + return createStringError(errc::executable_format_error, + "__stop___jump_table not in the same section " + "as __start___jump_table"); + + if ((Stop->getAddress() - StaticKeysJumpTableAddress) % + STATIC_KEYS_JUMP_ENTRY_SIZE) + return createStringError(errc::executable_format_error, + "static keys jump table size error"); + + const uint64_t SectionAddress = StaticKeysJumpSection->getAddress(); + DataExtractor DE(StaticKeysJumpSection->getContents(), + BC.AsmInfo->isLittleEndian(), + BC.AsmInfo->getCodePointerSize()); + DataExtractor::Cursor Cursor(StaticKeysJumpTableAddress - SectionAddress); + uint32_t EntryID = 0; + while (Cursor && Cursor.tell() < Stop->getAddress() - SectionAddress) { + const uint64_t JumpAddress = + SectionAddress + Cursor.tell() + (int32_t)DE.getU32(Cursor); + const uint64_t TargetAddress = + SectionAddress + Cursor.tell() + (int32_t)DE.getU32(Cursor); + const uint64_t KeyAddress = + SectionAddress + Cursor.tell() + (int64_t)DE.getU64(Cursor); + + // Consume the status of the cursor. + if (!Cursor) + return createStringError( + errc::executable_format_error, + "out of bounds while reading static keys jump table: %s", + toString(Cursor.takeError()).c_str()); + + ++EntryID; + + JumpInfo.push_back(JumpInfoEntry()); + JumpInfoEntry &Info = JumpInfo.back(); + Info.Likely = KeyAddress & 1; + + if (opts::DumpStaticKeys) { + BC.outs() << "Static key jump entry: " << EntryID + << "\n\tJumpAddress: 0x" << Twine::utohexstr(JumpAddress) + << "\n\tTargetAddress: 0x" << Twine::utohexstr(TargetAddress) + << "\n\tKeyAddress: 0x" << Twine::utohexstr(KeyAddress) + << "\n\tIsLikely: " << Info.Likely << '\n'; + } + + BinaryFunction *BF = BC.getBinaryFunctionContainingAddress(JumpAddress); + if (!BF && opts::Verbosity) { + BC.outs() + << "BOLT-INFO: no function matches address 0x" + << Twine::utohexstr(JumpAddress) + << " of jump instruction referenced from static keys jump table\n"; + } + + if (!BF || !BC.shouldEmit(*BF)) + continue; + + MCInst *Inst = BF->getInstructionAtOffset(JumpAddress - BF->getAddress()); + if (!Inst) + return createStringError( + errc::executable_format_error, + "no instruction at static keys jump site address 0x%" PRIx64, + JumpAddress); + + if (!BF->containsAddress(TargetAddress)) + return createStringError( + errc::executable_format_error, + "invalid target of static keys jump at 0x%" PRIx64 " : 0x%" PRIx64, + JumpAddress, TargetAddress); + + const bool IsBranch = BC.MIB->isBranch(*Inst); + if (!IsBranch && !BC.MIB->isNoop(*Inst)) + return createStringError(errc::executable_format_error, + "jump or nop expected at address 0x%" PRIx64, + JumpAddress); + + const uint64_t Size = BC.computeInstructionSize(*Inst); + if (Size != 2 && Size != 5) { + return createStringError( + errc::executable_format_error, + "unexpected static keys jump size at address 0x%" PRIx64, + JumpAddress); + } + + MCSymbol *Target = BF->registerBranch(JumpAddress, TargetAddress); + MCInst StaticKeyBranch; + + // Create a conditional branch instruction. The actual conditional code type + // should not matter as long as it's a valid code. The instruction should be + // treated as a conditional branch for control-flow purposes. Before we emit + // the code, it will be converted to a different instruction in + // rewriteStaticKeysJumpTable(). + // + // NB: for older kernels, under LongJumpLabels option, we create long + // conditional branch to guarantee that code size estimation takes + // into account the extra bytes needed for long branch that will be used + // by the kernel patching code. Newer kernels can work with both short + // and long branches. The code for long conditional branch is larger + // than unconditional one, so we are pessimistic in our estimations. + if (opts::LongJumpLabels) + BC.MIB->createLongCondBranch(StaticKeyBranch, Target, 0, BC.Ctx.get()); + else + BC.MIB->createCondBranch(StaticKeyBranch, Target, 0, BC.Ctx.get()); + BC.MIB->moveAnnotations(std::move(*Inst), StaticKeyBranch); + BC.MIB->setDynamicBranch(StaticKeyBranch, EntryID); + *Inst = StaticKeyBranch; + + // IsBranch = InitialValue ^ LIKELY + // + // 0 0 0 + // 1 0 1 + // 1 1 0 + // 0 1 1 + // + // => InitialValue = IsBranch ^ LIKELY + Info.InitValue = IsBranch ^ Info.Likely; + + // Add annotations to facilitate manual code analysis. + BC.MIB->addAnnotation(*Inst, "Likely", Info.Likely); + BC.MIB->addAnnotation(*Inst, "InitValue", Info.InitValue); + if (!BC.MIB->getSize(*Inst)) + BC.MIB->setSize(*Inst, Size); + + if (opts::LongJumpLabels) + BC.MIB->setSize(*Inst, 5); + } + + BC.outs() << "BOLT-INFO: parsed " << EntryID << " static keys jump entries\n"; + + return Error::success(); +} + +// Pre-emit pass. Convert dynamic branch instructions into jumps that could be +// relaxed. In post-emit pass we will convert those jumps into nops when +// necessary. We do the unconditional conversion into jumps so that the jumps +// can be relaxed and the optimal size of jump/nop instruction is selected. +Error LinuxKernelRewriter::rewriteStaticKeysJumpTable() { + if (!StaticKeysJumpSection) + return Error::success(); + + uint64_t NumShort = 0; + uint64_t NumLong = 0; + for (BinaryFunction &BF : llvm::make_second_range(BC.getBinaryFunctions())) { + if (!BC.shouldEmit(BF)) + continue; + + for (BinaryBasicBlock &BB : BF) { + for (MCInst &Inst : BB) { + if (!BC.MIB->isDynamicBranch(Inst)) + continue; + + const uint32_t EntryID = *BC.MIB->getDynamicBranchID(Inst); + MCSymbol *Target = + const_cast(BC.MIB->getTargetSymbol(Inst)); + assert(Target && "Target symbol should be set."); + + const JumpInfoEntry &Info = JumpInfo[EntryID - 1]; + const bool IsBranch = Info.Likely ^ Info.InitValue; + + uint32_t Size = *BC.MIB->getSize(Inst); + if (Size == 2) + ++NumShort; + else if (Size == 5) + ++NumLong; + else + llvm_unreachable("Wrong size for static keys jump instruction."); + + MCInst NewInst; + // Replace the instruction with unconditional jump even if it needs to + // be nop in the binary. + if (opts::LongJumpLabels) { + BC.MIB->createLongUncondBranch(NewInst, Target, BC.Ctx.get()); + } else { + // Newer kernels can handle short and long jumps for static keys. + // Optimistically, emit short jump and check if it gets relaxed into + // a long one during post-emit. Only then convert the jump to a nop. + BC.MIB->createUncondBranch(NewInst, Target, BC.Ctx.get()); + } + + BC.MIB->moveAnnotations(std::move(Inst), NewInst); + Inst = NewInst; + + // Mark the instruction for nop conversion. + if (!IsBranch) + NopIDs.insert(EntryID); + + MCSymbol *Label = + BC.MIB->getOrCreateInstLabel(Inst, "__SK_", BC.Ctx.get()); + + // Create a relocation against the label. + const uint64_t EntryOffset = StaticKeysJumpTableAddress - + StaticKeysJumpSection->getAddress() + + (EntryID - 1) * 16; + StaticKeysJumpSection->addRelocation(EntryOffset, Label, + ELF::R_X86_64_PC32, + /*Addend*/ 0); + StaticKeysJumpSection->addRelocation(EntryOffset + 4, Target, + ELF::R_X86_64_PC32, /*Addend*/ 0); + } + } + } + + BC.outs() << "BOLT-INFO: the input contains " << NumShort << " short and " + << NumLong << " long static keys jumps in optimized functions\n"; + + return Error::success(); +} + +// Post-emit pass of static keys jump section. Convert jumps to nops. +Error LinuxKernelRewriter::updateStaticKeysJumpTablePostEmit() { + if (!StaticKeysJumpSection || !StaticKeysJumpSection->isFinalized()) + return Error::success(); + + const uint64_t SectionAddress = StaticKeysJumpSection->getAddress(); + DataExtractor DE(StaticKeysJumpSection->getOutputContents(), + BC.AsmInfo->isLittleEndian(), + BC.AsmInfo->getCodePointerSize()); + DataExtractor::Cursor Cursor(StaticKeysJumpTableAddress - SectionAddress); + const BinaryData *Stop = BC.getBinaryDataByName("__stop___jump_table"); + uint32_t EntryID = 0; + uint64_t NumShort = 0; + uint64_t NumLong = 0; + while (Cursor && Cursor.tell() < Stop->getAddress() - SectionAddress) { + const uint64_t JumpAddress = + SectionAddress + Cursor.tell() + (int32_t)DE.getU32(Cursor); + const uint64_t TargetAddress = + SectionAddress + Cursor.tell() + (int32_t)DE.getU32(Cursor); + const uint64_t KeyAddress = + SectionAddress + Cursor.tell() + (int64_t)DE.getU64(Cursor); + + // Consume the status of the cursor. + if (!Cursor) + return createStringError(errc::executable_format_error, + "out of bounds while updating static keys: %s", + toString(Cursor.takeError()).c_str()); + + ++EntryID; + + LLVM_DEBUG({ + dbgs() << "\n\tJumpAddress: 0x" << Twine::utohexstr(JumpAddress) + << "\n\tTargetAddress: 0x" << Twine::utohexstr(TargetAddress) + << "\n\tKeyAddress: 0x" << Twine::utohexstr(KeyAddress) << '\n'; + }); + (void)TargetAddress; + (void)KeyAddress; + + BinaryFunction *BF = + BC.getBinaryFunctionContainingAddress(JumpAddress, + /*CheckPastEnd*/ false, + /*UseMaxSize*/ true); + assert(BF && "Cannot get function for modified static key."); + + if (!BF->isEmitted()) + continue; + + // Disassemble instruction to collect stats even if nop-conversion is + // unnecessary. + MutableArrayRef Contents = MutableArrayRef( + reinterpret_cast(BF->getImageAddress()), BF->getImageSize()); + assert(Contents.size() && "Non-empty function image expected."); + + MCInst Inst; + uint64_t Size; + const uint64_t JumpOffset = JumpAddress - BF->getAddress(); + if (!BC.DisAsm->getInstruction(Inst, Size, Contents.slice(JumpOffset), 0, + nulls())) { + llvm_unreachable("Unable to disassemble jump instruction."); + } + assert(BC.MIB->isBranch(Inst) && "Branch instruction expected."); + + if (Size == 2) + ++NumShort; + else if (Size == 5) + ++NumLong; + else + llvm_unreachable("Unexpected size for static keys jump instruction."); + + // Check if we need to convert jump instruction into a nop. + if (!NopIDs.contains(EntryID)) + continue; + + SmallString<15> NopCode; + raw_svector_ostream VecOS(NopCode); + BC.MAB->writeNopData(VecOS, Size, BC.STI.get()); + for (uint64_t I = 0; I < Size; ++I) + Contents[JumpOffset + I] = NopCode[I]; + } + + BC.outs() << "BOLT-INFO: written " << NumShort << " short and " << NumLong + << " long static keys jumps in optimized functions\n"; + + return Error::success(); +} + } // namespace std::unique_ptr diff --git a/bolt/lib/Rewrite/MachORewriteInstance.cpp b/bolt/lib/Rewrite/MachORewriteInstance.cpp index 0970a0507ebe8803e6ae85789b8ec10618465211..172cb640bf911a96e11c3112b007cd1636479867 100644 --- a/bolt/lib/Rewrite/MachORewriteInstance.cpp +++ b/bolt/lib/Rewrite/MachORewriteInstance.cpp @@ -18,6 +18,7 @@ #include "bolt/Rewrite/BinaryPassManager.h" #include "bolt/Rewrite/ExecutableFileMemoryManager.h" #include "bolt/Rewrite/JITLinkLinker.h" +#include "bolt/Rewrite/RewriteInstance.h" #include "bolt/RuntimeLibs/InstrumentationRuntimeLibrary.h" #include "bolt/Utils/Utils.h" #include "llvm/MC/MCObjectStreamer.h" @@ -54,37 +55,6 @@ extern cl::opt Verbosity; namespace llvm { namespace bolt { -extern MCPlusBuilder *createX86MCPlusBuilder(const MCInstrAnalysis *, - const MCInstrInfo *, - const MCRegisterInfo *, - const MCSubtargetInfo *); -extern MCPlusBuilder *createAArch64MCPlusBuilder(const MCInstrAnalysis *, - const MCInstrInfo *, - const MCRegisterInfo *, - const MCSubtargetInfo *); - -namespace { - -MCPlusBuilder *createMCPlusBuilder(const Triple::ArchType Arch, - const MCInstrAnalysis *Analysis, - const MCInstrInfo *Info, - const MCRegisterInfo *RegInfo, - const MCSubtargetInfo *STI) { -#ifdef X86_AVAILABLE - if (Arch == Triple::x86_64) - return createX86MCPlusBuilder(Analysis, Info, RegInfo, STI); -#endif - -#ifdef AARCH64_AVAILABLE - if (Arch == Triple::aarch64) - return createAArch64MCPlusBuilder(Analysis, Info, RegInfo, STI); -#endif - - llvm_unreachable("architecture unsupported by MCPlusBuilder"); -} - -} // anonymous namespace - #define DEBUG_TYPE "bolt" Expected> @@ -103,7 +73,8 @@ MachORewriteInstance::MachORewriteInstance(object::MachOObjectFile *InputFile, : InputFile(InputFile), ToolPath(ToolPath) { ErrorAsOutParameter EAO(&Err); auto BCOrErr = BinaryContext::createBinaryContext( - InputFile, /* IsPIC */ true, DWARFContext::create(*InputFile), + InputFile->makeTriple(), InputFile->getFileName(), nullptr, + /* IsPIC */ true, DWARFContext::create(*InputFile), {llvm::outs(), llvm::errs()}); if (Error E = BCOrErr.takeError()) { Err = std::move(E); diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index cde195c1739074394726214f8c185c1d237ceaa4..0c8ee0d417233bb5617cb7a9fc2ddfa59a3dd710 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -81,8 +81,10 @@ extern cl::list HotTextMoveSections; extern cl::opt Hugify; extern cl::opt Instrument; extern cl::opt JumpTables; +extern cl::opt KeepNops; extern cl::list ReorderData; extern cl::opt ReorderFunctions; +extern cl::opt TerminalTrap; extern cl::opt TimeBuild; cl::opt AllowStripped("allow-stripped", @@ -199,10 +201,7 @@ static cl::opt RelocationMode( "relocs", cl::desc("use relocations in the binary (default=autodetect)"), cl::cat(BoltCategory)); -static cl::opt -SaveProfile("w", - cl::desc("save recorded profile to a file"), - cl::cat(BoltOutputCategory)); +extern cl::opt SaveProfile; static cl::list SkipFunctionNames("skip-funcs", @@ -269,6 +268,10 @@ namespace bolt { extern const char *BoltRevision; +// Weird location for createMCPlusBuilder, but this is here to avoid a +// cyclic dependency of libCore (its natural place) and libTarget. libRewrite +// can depend on libTarget, but not libCore. Since libRewrite is the only +// user of this function, we define it here. MCPlusBuilder *createMCPlusBuilder(const Triple::ArchType Arch, const MCInstrAnalysis *Analysis, const MCInstrInfo *Info, @@ -346,8 +349,21 @@ RewriteInstance::RewriteInstance(ELFObjectFileBase *File, const int Argc, Stderr.SetUnbuffered(); LLVM_DEBUG(dbgs().SetUnbuffered()); + // Read RISCV subtarget features from input file + std::unique_ptr Features; + Triple TheTriple = File->makeTriple(); + if (TheTriple.getArch() == llvm::Triple::riscv64) { + Expected FeaturesOrErr = File->getFeatures(); + if (auto E = FeaturesOrErr.takeError()) { + Err = std::move(E); + return; + } else { + Features.reset(new SubtargetFeatures(*FeaturesOrErr)); + } + } + auto BCOrErr = BinaryContext::createBinaryContext( - File, IsPIC, + TheTriple, File->getFileName(), Features.get(), IsPIC, DWARFContext::create(*File, DWARFContext::ProcessDebugRelocations::Ignore, nullptr, opts::DWPPathName, WithColor::defaultErrorHandler, @@ -732,6 +748,13 @@ Error RewriteInstance::run() { // Skip disassembling if we have a translation table and we are running an // aggregation job. if (opts::AggregateOnly && BAT->enabledFor(InputFile)) { + // YAML profile in BAT mode requires CFG for .bolt.org.text functions + if (!opts::SaveProfile.empty() || + opts::ProfileFormat == opts::ProfileFormatKind::PF_YAML) { + selectFunctionsToProcess(); + disassembleFunctions(); + buildFunctionsCFG(); + } processProfileData(); return Error::success(); } @@ -2028,12 +2051,13 @@ void RewriteInstance::adjustCommandLineOptions() { if (opts::Lite) BC->outs() << "BOLT-INFO: enabling lite mode\n"; - if (!opts::SaveProfile.empty() && BAT->enabledFor(InputFile)) { - BC->errs() - << "BOLT-ERROR: unable to save profile in YAML format for input " - "file processed by BOLT. Please remove -w option and use branch " - "profile.\n"; - exit(1); + if (BC->IsLinuxKernel) { + if (!opts::KeepNops.getNumOccurrences()) + opts::KeepNops = true; + + // Linux kernel may resume execution after a trap instruction in some cases. + if (!opts::TerminalTrap.getNumOccurrences()) + opts::TerminalTrap = false; } } @@ -3126,12 +3150,13 @@ void RewriteInstance::processProfileData() { } } - if (!opts::SaveProfile.empty()) { + if (!opts::SaveProfile.empty() && !BAT->enabledFor(InputFile)) { YAMLProfileWriter PW(opts::SaveProfile); PW.writeProfile(*this); } if (opts::AggregateOnly && - opts::ProfileFormat == opts::ProfileFormatKind::PF_YAML) { + opts::ProfileFormat == opts::ProfileFormatKind::PF_YAML && + !BAT->enabledFor(InputFile)) { YAMLProfileWriter PW(opts::OutputFilename); PW.writeProfile(*this); } diff --git a/bolt/lib/RuntimeLibs/HugifyRuntimeLibrary.cpp b/bolt/lib/RuntimeLibs/HugifyRuntimeLibrary.cpp index b6fc49d3f5d671b8a0205961f2aace7e39253418..d114d70f2d37668df5c39cf31a154126e537a109 100644 --- a/bolt/lib/RuntimeLibs/HugifyRuntimeLibrary.cpp +++ b/bolt/lib/RuntimeLibs/HugifyRuntimeLibrary.cpp @@ -11,10 +11,9 @@ //===----------------------------------------------------------------------===// #include "bolt/RuntimeLibs/HugifyRuntimeLibrary.h" -#include "bolt/Core/BinaryFunction.h" +#include "bolt/Core/BinaryContext.h" #include "bolt/Core/Linker.h" #include "llvm/MC/MCStreamer.h" -#include "llvm/Support/Alignment.h" #include "llvm/Support/CommandLine.h" using namespace llvm; diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp index 9efb428a6e1baef1adb0e35bd210f9ae4640f7ed..0ae9d3668b93bb87290a54b763e775a5234cfd6d 100644 --- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp +++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp @@ -1026,7 +1026,7 @@ public: return Code; } - bool createTailCall(MCInst &Inst, const MCSymbol *Target, + void createTailCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx) override { return createDirectCall(Inst, Target, Ctx, /*IsTailCall*/ true); } @@ -1036,11 +1036,10 @@ public: createShortJmp(Seq, Target, Ctx, /*IsTailCall*/ true); } - bool createTrap(MCInst &Inst) const override { + void createTrap(MCInst &Inst) const override { Inst.clear(); Inst.setOpcode(AArch64::BRK); Inst.addOperand(MCOperand::createImm(1)); - return true; } bool convertJmpToTailCall(MCInst &Inst) override { @@ -1068,16 +1067,15 @@ public: Inst.getOperand(0).getImm() == 0; } - bool createNoop(MCInst &Inst) const override { + void createNoop(MCInst &Inst) const override { Inst.setOpcode(AArch64::HINT); Inst.clear(); Inst.addOperand(MCOperand::createImm(0)); - return true; } bool mayStore(const MCInst &Inst) const override { return false; } - bool createDirectCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx, + void createDirectCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx, bool IsTailCall) override { Inst.setOpcode(IsTailCall ? AArch64::B : AArch64::BL); Inst.clear(); @@ -1086,7 +1084,6 @@ public: *Ctx, 0))); if (IsTailCall) convertJmpToTailCall(Inst); - return true; } bool analyzeBranch(InstructionIterator Begin, InstructionIterator End, @@ -1293,14 +1290,13 @@ public: return true; } - bool createUncondBranch(MCInst &Inst, const MCSymbol *TBB, + void createUncondBranch(MCInst &Inst, const MCSymbol *TBB, MCContext *Ctx) const override { Inst.setOpcode(AArch64::B); Inst.clear(); Inst.addOperand(MCOperand::createExpr(getTargetExprFor( Inst, MCSymbolRefExpr::create(TBB, MCSymbolRefExpr::VK_None, *Ctx), *Ctx, 0))); - return true; } bool shouldRecordCodeRelocation(uint64_t RelType) const override { @@ -1353,14 +1349,13 @@ public: return StringRef("\0\0\0\0", 4); } - bool createReturn(MCInst &Inst) const override { + void createReturn(MCInst &Inst) const override { Inst.setOpcode(AArch64::RET); Inst.clear(); Inst.addOperand(MCOperand::createReg(AArch64::LR)); - return true; } - bool createStackPointerIncrement( + void createStackPointerIncrement( MCInst &Inst, int Size, bool NoFlagsClobber = false /*unused for AArch64*/) const override { Inst.setOpcode(AArch64::SUBXri); @@ -1369,10 +1364,9 @@ public: Inst.addOperand(MCOperand::createReg(AArch64::SP)); Inst.addOperand(MCOperand::createImm(Size)); Inst.addOperand(MCOperand::createImm(0)); - return true; } - bool createStackPointerDecrement( + void createStackPointerDecrement( MCInst &Inst, int Size, bool NoFlagsClobber = false /*unused for AArch64*/) const override { Inst.setOpcode(AArch64::ADDXri); @@ -1381,12 +1375,12 @@ public: Inst.addOperand(MCOperand::createReg(AArch64::SP)); Inst.addOperand(MCOperand::createImm(Size)); Inst.addOperand(MCOperand::createImm(0)); - return true; } void createIndirectBranch(MCInst &Inst, MCPhysReg MemBaseReg, int64_t Disp) const { Inst.setOpcode(AArch64::BR); + Inst.clear(); Inst.addOperand(MCOperand::createReg(MemBaseReg)); } diff --git a/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp b/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp index e19c070b081733c1faea19e509c6e3933fc05107..74f2f0aae91e667d12d6edff81f371c1e1044bfe 100644 --- a/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp +++ b/bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp @@ -16,10 +16,7 @@ #include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" #define DEBUG_TYPE "mcplus" @@ -219,46 +216,43 @@ public: return true; } - bool createReturn(MCInst &Inst) const override { + void createReturn(MCInst &Inst) const override { // TODO "c.jr ra" when RVC is enabled Inst.setOpcode(RISCV::JALR); Inst.clear(); Inst.addOperand(MCOperand::createReg(RISCV::X0)); Inst.addOperand(MCOperand::createReg(RISCV::X1)); Inst.addOperand(MCOperand::createImm(0)); - return true; } - bool createUncondBranch(MCInst &Inst, const MCSymbol *TBB, + void createUncondBranch(MCInst &Inst, const MCSymbol *TBB, MCContext *Ctx) const override { Inst.setOpcode(RISCV::JAL); Inst.clear(); Inst.addOperand(MCOperand::createReg(RISCV::X0)); Inst.addOperand(MCOperand::createExpr( MCSymbolRefExpr::create(TBB, MCSymbolRefExpr::VK_None, *Ctx))); - return true; } StringRef getTrapFillValue() const override { return StringRef("\0\0\0\0", 4); } - bool createCall(unsigned Opcode, MCInst &Inst, const MCSymbol *Target, + void createCall(unsigned Opcode, MCInst &Inst, const MCSymbol *Target, MCContext *Ctx) { Inst.setOpcode(Opcode); Inst.clear(); Inst.addOperand(MCOperand::createExpr(RISCVMCExpr::create( MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx), RISCVMCExpr::VK_RISCV_CALL, *Ctx))); - return true; } - bool createCall(MCInst &Inst, const MCSymbol *Target, + void createCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx) override { return createCall(RISCV::PseudoCALL, Inst, Target, Ctx); } - bool createTailCall(MCInst &Inst, const MCSymbol *Target, + void createTailCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx) override { return createCall(RISCV::PseudoTAIL, Inst, Target, Ctx); } diff --git a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp index 387cf481ba304fa472e92ee7866c306cdf1cba28..8b1894953f3757f036aa2d7e58f2f033861b0efd 100644 --- a/bolt/lib/Target/X86/X86MCPlusBuilder.cpp +++ b/bolt/lib/Target/X86/X86MCPlusBuilder.cpp @@ -211,13 +211,6 @@ public: return false; } - // FIXME: For compatibility with old LLVM only! - bool isTerminator(const MCInst &Inst) const override { - unsigned Opcode = Inst.getOpcode(); - return Info->get(Opcode).isTerminator() || X86::isUD1(Opcode) || - X86::isUD2(Opcode); - } - bool isIndirectCall(const MCInst &Inst) const override { return isCall(Inst) && ((getMemoryOperandNo(Inst) != -1) || Inst.getOperand(0).isReg()); @@ -336,6 +329,9 @@ public: } bool isUnsupportedBranch(const MCInst &Inst) const override { + if (isDynamicBranch(Inst)) + return true; + switch (Inst.getOpcode()) { default: return false; @@ -2230,7 +2226,7 @@ public: return true; } - bool createStackPointerIncrement(MCInst &Inst, int Size, + void createStackPointerIncrement(MCInst &Inst, int Size, bool NoFlagsClobber) const override { if (NoFlagsClobber) { Inst.setOpcode(X86::LEA64r); @@ -2241,17 +2237,16 @@ public: Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // IndexReg Inst.addOperand(MCOperand::createImm(-Size)); // Displacement Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg - return true; + return; } Inst.setOpcode(X86::SUB64ri8); Inst.clear(); Inst.addOperand(MCOperand::createReg(X86::RSP)); Inst.addOperand(MCOperand::createReg(X86::RSP)); Inst.addOperand(MCOperand::createImm(Size)); - return true; } - bool createStackPointerDecrement(MCInst &Inst, int Size, + void createStackPointerDecrement(MCInst &Inst, int Size, bool NoFlagsClobber) const override { if (NoFlagsClobber) { Inst.setOpcode(X86::LEA64r); @@ -2262,22 +2257,22 @@ public: Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // IndexReg Inst.addOperand(MCOperand::createImm(Size)); // Displacement Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg - return true; + return; } Inst.setOpcode(X86::ADD64ri8); Inst.clear(); Inst.addOperand(MCOperand::createReg(X86::RSP)); Inst.addOperand(MCOperand::createReg(X86::RSP)); Inst.addOperand(MCOperand::createImm(Size)); - return true; } - bool createSaveToStack(MCInst &Inst, const MCPhysReg &StackReg, int Offset, + void createSaveToStack(MCInst &Inst, const MCPhysReg &StackReg, int Offset, const MCPhysReg &SrcReg, int Size) const override { unsigned NewOpcode; switch (Size) { default: - return false; + llvm_unreachable("Invalid operand size"); + return; case 2: NewOpcode = X86::MOV16mr; break; case 4: NewOpcode = X86::MOV32mr; break; case 8: NewOpcode = X86::MOV64mr; break; @@ -2290,10 +2285,9 @@ public: Inst.addOperand(MCOperand::createImm(Offset)); // Displacement Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg Inst.addOperand(MCOperand::createReg(SrcReg)); - return true; } - bool createRestoreFromStack(MCInst &Inst, const MCPhysReg &StackReg, + void createRestoreFromStack(MCInst &Inst, const MCPhysReg &StackReg, int Offset, const MCPhysReg &DstReg, int Size) const override { return createLoad(Inst, StackReg, /*Scale=*/1, /*IndexReg=*/X86::NoRegister, @@ -2301,14 +2295,15 @@ public: DstReg, Size); } - bool createLoad(MCInst &Inst, const MCPhysReg &BaseReg, int64_t Scale, + void createLoad(MCInst &Inst, const MCPhysReg &BaseReg, int64_t Scale, const MCPhysReg &IndexReg, int64_t Offset, const MCExpr *OffsetExpr, const MCPhysReg &AddrSegmentReg, const MCPhysReg &DstReg, int Size) const override { unsigned NewOpcode; switch (Size) { default: - return false; + llvm_unreachable("Invalid operand size"); + return; case 2: NewOpcode = X86::MOV16rm; break; case 4: NewOpcode = X86::MOV32rm; break; case 8: NewOpcode = X86::MOV64rm; break; @@ -2324,7 +2319,6 @@ public: else Inst.addOperand(MCOperand::createImm(Offset)); // Displacement Inst.addOperand(MCOperand::createReg(AddrSegmentReg)); // AddrSegmentReg - return true; } InstructionListType createLoadImmediate(const MCPhysReg Dest, @@ -2338,7 +2332,7 @@ public: return Insts; } - bool createIJmp32Frag(SmallVectorImpl &Insts, + void createIJmp32Frag(SmallVectorImpl &Insts, const MCOperand &BaseReg, const MCOperand &Scale, const MCOperand &IndexReg, const MCOperand &Offset, const MCOperand &TmpReg) const override { @@ -2362,17 +2356,16 @@ public: Insts.push_back(Load); Insts.push_back(IJmp); - return true; } - bool createNoop(MCInst &Inst) const override { + void createNoop(MCInst &Inst) const override { Inst.setOpcode(X86::NOOP); - return true; + Inst.clear(); } - bool createReturn(MCInst &Inst) const override { + void createReturn(MCInst &Inst) const override { Inst.setOpcode(X86::RET64); - return true; + Inst.clear(); } InstructionListType createInlineMemcpy(bool ReturnEnd) const override { @@ -2729,23 +2722,32 @@ public: return FoundOne; } - bool createUncondBranch(MCInst &Inst, const MCSymbol *TBB, + void createUncondBranch(MCInst &Inst, const MCSymbol *TBB, MCContext *Ctx) const override { + Inst.clear(); Inst.setOpcode(X86::JMP_1); + Inst.clear(); Inst.addOperand(MCOperand::createExpr( MCSymbolRefExpr::create(TBB, MCSymbolRefExpr::VK_None, *Ctx))); - return true; } - bool createCall(MCInst &Inst, const MCSymbol *Target, + void createLongUncondBranch(MCInst &Inst, const MCSymbol *Target, + MCContext *Ctx) const override { + Inst.setOpcode(X86::JMP_4); + Inst.clear(); + Inst.addOperand(MCOperand::createExpr( + MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx))); + } + + void createCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx) override { Inst.setOpcode(X86::CALL64pcrel32); + Inst.clear(); Inst.addOperand(MCOperand::createExpr( MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx))); - return true; } - bool createTailCall(MCInst &Inst, const MCSymbol *Target, + void createTailCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx) override { return createDirectCall(Inst, Target, Ctx, /*IsTailCall*/ true); } @@ -2757,10 +2759,27 @@ public: createDirectCall(Seq.back(), Target, Ctx, /*IsTailCall*/ true); } - bool createTrap(MCInst &Inst) const override { + void createTrap(MCInst &Inst) const override { Inst.clear(); Inst.setOpcode(X86::TRAP); - return true; + } + + void createCondBranch(MCInst &Inst, const MCSymbol *Target, unsigned CC, + MCContext *Ctx) const override { + Inst.setOpcode(X86::JCC_1); + Inst.clear(); + Inst.addOperand(MCOperand::createExpr( + MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx))); + Inst.addOperand(MCOperand::createImm(CC)); + } + + void createLongCondBranch(MCInst &Inst, const MCSymbol *Target, unsigned CC, + MCContext *Ctx) const override { + Inst.setOpcode(X86::JCC_4); + Inst.clear(); + Inst.addOperand(MCOperand::createExpr( + MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx))); + Inst.addOperand(MCOperand::createImm(CC)); } bool reverseBranchCondition(MCInst &Inst, const MCSymbol *TBB, @@ -2862,7 +2881,7 @@ public: Inst.setOpcode(X86::LFENCE); } - bool createDirectCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx, + void createDirectCall(MCInst &Inst, const MCSymbol *Target, MCContext *Ctx, bool IsTailCall) override { Inst.clear(); Inst.setOpcode(IsTailCall ? X86::JMP_4 : X86::CALL64pcrel32); @@ -2870,7 +2889,6 @@ public: MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *Ctx))); if (IsTailCall) setTailCall(Inst); - return true; } void createShortJmp(InstructionListType &Seq, const MCSymbol *Target, @@ -3066,6 +3084,7 @@ public: void createSwap(MCInst &Inst, MCPhysReg Source, MCPhysReg MemBaseReg, int64_t Disp) const { Inst.setOpcode(X86::XCHG64rm); + Inst.clear(); Inst.addOperand(MCOperand::createReg(Source)); Inst.addOperand(MCOperand::createReg(Source)); Inst.addOperand(MCOperand::createReg(MemBaseReg)); // BaseReg @@ -3078,6 +3097,7 @@ public: void createIndirectBranch(MCInst &Inst, MCPhysReg MemBaseReg, int64_t Disp) const { Inst.setOpcode(X86::JMP64m); + Inst.clear(); Inst.addOperand(MCOperand::createReg(MemBaseReg)); // BaseReg Inst.addOperand(MCOperand::createImm(1)); // ScaleAmt Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // IndexReg @@ -3540,9 +3560,10 @@ public: } private: - bool createMove(MCInst &Inst, const MCSymbol *Src, unsigned Reg, + void createMove(MCInst &Inst, const MCSymbol *Src, unsigned Reg, MCContext *Ctx) const { Inst.setOpcode(X86::MOV64rm); + Inst.clear(); Inst.addOperand(MCOperand::createReg(Reg)); Inst.addOperand(MCOperand::createReg(X86::RIP)); // BaseReg Inst.addOperand(MCOperand::createImm(1)); // ScaleAmt @@ -3551,13 +3572,12 @@ private: MCSymbolRefExpr::create(Src, MCSymbolRefExpr::VK_None, *Ctx))); // Displacement Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg - - return true; } - bool createLea(MCInst &Inst, const MCSymbol *Src, unsigned Reg, + void createLea(MCInst &Inst, const MCSymbol *Src, unsigned Reg, MCContext *Ctx) const { Inst.setOpcode(X86::LEA64r); + Inst.clear(); Inst.addOperand(MCOperand::createReg(Reg)); Inst.addOperand(MCOperand::createReg(X86::RIP)); // BaseReg Inst.addOperand(MCOperand::createImm(1)); // ScaleAmt @@ -3566,7 +3586,6 @@ private: MCSymbolRefExpr::create(Src, MCSymbolRefExpr::VK_None, *Ctx))); // Displacement Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg - return true; } }; diff --git a/bolt/lib/Utils/CommandLineOpts.cpp b/bolt/lib/Utils/CommandLineOpts.cpp index e910fa4f867225f10f835f1d0d53ec6894b67d38..ba296c10c00ae14169a9e819a07302d3506c7cea 100644 --- a/bolt/lib/Utils/CommandLineOpts.cpp +++ b/bolt/lib/Utils/CommandLineOpts.cpp @@ -162,6 +162,10 @@ cl::opt ProfileFormat( clEnumValN(PF_YAML, "yaml", "dense YAML representation")), cl::ZeroOrMore, cl::Hidden, cl::cat(BoltCategory)); +cl::opt SaveProfile("w", + cl::desc("save recorded profile to a file"), + cl::cat(BoltOutputCategory)); + cl::opt SplitEH("split-eh", cl::desc("split C++ exception handling code"), cl::Hidden, cl::cat(BoltOptCategory)); diff --git a/bolt/test/X86/Inputs/blarge_new.preagg.txt b/bolt/test/X86/Inputs/blarge_new.preagg.txt new file mode 100644 index 0000000000000000000000000000000000000000..e92f356d9188878a84409daac00ec4366fbd133c --- /dev/null +++ b/bolt/test/X86/Inputs/blarge_new.preagg.txt @@ -0,0 +1,81 @@ +B 40164b 401608 109 0 +B 401611 4017e0 115 0 +B 4017f0 401616 117 0 +B 401ba2 4015da 6 0 +B 4015d5 401b60 1 0 +B 40159a 401b60 5 0 +B 401b9d 401b70 615 2 +B 401b90 401b99 344 37 +B 401ba2 40159f 8 0 +B 4015b0 401070 9 0 +B 401544 4014a0 6 0 +B 40188a 401928 5 0 +B 40152a 4014b0 21 0 +B 40169e 40165b 2 0 +B 4014dd 401070 12 1 +B 401509 4014ec 2 2 +B 401510 401030 673 0 +B 4019de 401080 1 0 +B 401500 401070 22 0 +B 401921 4014d6 9 0 +B 4019b3 401080 3 0 +B 40162d 401070 113 0 +B 4014d1 401800 27 0 +B 401a3f 401080 1 0 +B 4018d2 401050 17 0 +B 401664 4017c0 2 0 +B 401680 401070 2 0 +B 4017d0 401669 2 0 +B 4018f7 40190d 9 0 +B 4015bc 401592 6 0 +B 401964 401090 5 0 +B 4015f8 4015cd 1 0 +B 4015ec 401070 6 0 +F 40165b 401664 2 +F 4017c0 4017d0 2 +F 401669 401680 2 +F 40190d 401921 9 +F 4014d6 4014dd 9 +F 401800 4018d2 17 +F 4018d7 4018f7 9 +F 40159f 4015b0 8 +F 401515 401544 6 +F 401070 401500 1 +F 401070 401070 157 +F 4014a0 4014d1 6 +F 401616 40162d 112 +F 4019e3 401a3f 1 +F 4014e2 401500 19 +F 401090 401090 5 +F 401030 401030 673 +F 401505 401510 668 +F 401616 4017f0 2 +F 401070 4015b0 1 +F 4015da 4015ec 6 +F 401b60 401b90 6 +F 4019b8 4019de 1 +F 401969 4019b3 3 +F 401505 401509 2 +F 401515 40152a 21 +F 401592 40159a 4 +F 401050 401050 17 +F 4015cd 4015d5 1 +F 401070 4014dd 1 +F 401b99 401ba2 8 +F 401b70 401b90 326 +F 401b99 401b9d 324 +F 401592 4015bc 1 +F 401608 401611 109 +F 401b70 401b9d 268 +F 4015b5 4015bc 5 +F 401b99 401b90 1 +F 401b70 401ba2 5 +F 401632 40164b 108 +F 401080 401080 5 +F 4014b0 4014d1 21 +F 4017e0 4017f0 115 +F 4015f1 4015f8 1 +F 401685 40169e 2 +F 401928 401964 5 +F 401800 40188a 5 +F 4014ec 401500 2 diff --git a/bolt/test/X86/Inputs/blarge_new.yaml b/bolt/test/X86/Inputs/blarge_new.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0380f5180e9055cddd46d451b2eb9c8d0422ef49 --- /dev/null +++ b/bolt/test/X86/Inputs/blarge_new.yaml @@ -0,0 +1,1648 @@ +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x4016D0 +ProgramHeaders: + - Type: PT_PHDR + Flags: [ PF_R ] + VAddr: 0x400040 + Align: 0x8 + Offset: 0x40 + - Type: PT_INTERP + Flags: [ PF_R ] + FirstSec: .interp + LastSec: .interp + VAddr: 0x4002A8 + Offset: 0x2A8 + - Type: PT_LOAD + Flags: [ PF_R ] + FirstSec: .interp + LastSec: .rela.plt + VAddr: 0x400000 + Align: 0x1000 + Offset: 0x0 + - Type: PT_LOAD + Flags: [ PF_X, PF_R ] + FirstSec: .init + LastSec: .fini + VAddr: 0x401000 + Align: 0x1000 + Offset: 0x1000 + - Type: PT_LOAD + Flags: [ PF_R ] + FirstSec: .rodata + LastSec: .eh_frame + VAddr: 0x402000 + Align: 0x1000 + Offset: 0x2000 + - Type: PT_LOAD + Flags: [ PF_W, PF_R ] + FirstSec: .init_array + LastSec: .bss + VAddr: 0x403E00 + Align: 0x1000 + Offset: 0x2E00 + - Type: PT_DYNAMIC + Flags: [ PF_W, PF_R ] + FirstSec: .dynamic + LastSec: .dynamic + VAddr: 0x403E10 + Align: 0x8 + Offset: 0x2E10 + - Type: PT_NOTE + Flags: [ PF_R ] + FirstSec: .note.gnu.build-id + LastSec: .note.ABI-tag + VAddr: 0x4002C4 + Align: 0x4 + Offset: 0x2C4 + - Type: PT_GNU_EH_FRAME + Flags: [ PF_R ] + FirstSec: .eh_frame_hdr + LastSec: .eh_frame_hdr + VAddr: 0x402270 + Align: 0x4 + Offset: 0x2270 + - Type: PT_GNU_STACK + Flags: [ PF_W, PF_R ] + Align: 0x10 + Offset: 0x0 + - Type: PT_GNU_RELRO + Flags: [ PF_R ] + FirstSec: .init_array + LastSec: .got + VAddr: 0x403E00 + Offset: 0x2E00 +Sections: + - Name: .interp + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x4002A8 + AddressAlign: 0x1 + Content: 2F6C696236342F6C642D6C696E75782D7838362D36342E736F2E3200 + - Name: .note.gnu.build-id + Type: SHT_NOTE + Flags: [ SHF_ALLOC ] + Address: 0x4002C4 + AddressAlign: 0x4 + Notes: + - Name: GNU + Desc: 66CF856212C3B313EA98AD840984B20EA781118A + Type: NT_PRPSINFO + - Name: .note.ABI-tag + Type: SHT_NOTE + Flags: [ SHF_ALLOC ] + Address: 0x4002E8 + AddressAlign: 0x4 + Notes: + - Name: GNU + Desc: '00000000030000000200000000000000' + Type: NT_VERSION + - Name: .gnu.hash + Type: SHT_GNU_HASH + Flags: [ SHF_ALLOC ] + Address: 0x400308 + Link: .dynsym + AddressAlign: 0x8 + Header: + SymNdx: 0x1 + Shift2: 0x0 + BloomFilter: [ 0x0 ] + HashBuckets: [ 0x0 ] + HashValues: [ ] + - Name: .dynsym + Type: SHT_DYNSYM + Flags: [ SHF_ALLOC ] + Address: 0x400328 + Link: .dynstr + AddressAlign: 0x8 + - Name: .dynstr + Type: SHT_STRTAB + Flags: [ SHF_ALLOC ] + Address: 0x400430 + AddressAlign: 0x1 + - Name: .gnu.version + Type: SHT_GNU_versym + Flags: [ SHF_ALLOC ] + Address: 0x4004BA + Link: .dynsym + AddressAlign: 0x2 + Entries: [ 0, 2, 2, 3, 4, 2, 5, 5, 2, 0, 5 ] + - Name: .gnu.version_r + Type: SHT_GNU_verneed + Flags: [ SHF_ALLOC ] + Address: 0x4004D0 + Link: .dynstr + AddressAlign: 0x8 + Dependencies: + - Version: 1 + File: libm.so.6 + Entries: + - Name: GLIBC_2.2.5 + Hash: 157882997 + Flags: 0 + Other: 5 + - Name: GLIBC_2.29 + Hash: 110530953 + Flags: 0 + Other: 3 + - Version: 1 + File: libc.so.6 + Entries: + - Name: GLIBC_2.4 + Hash: 225011988 + Flags: 0 + Other: 4 + - Name: GLIBC_2.2.5 + Hash: 157882997 + Flags: 0 + Other: 2 + - Name: .rela.dyn + Type: SHT_RELA + Flags: [ SHF_ALLOC ] + Address: 0x400530 + Link: .dynsym + AddressAlign: 0x8 + Relocations: + - Offset: 0x403FF0 + Symbol: __libc_start_main + Type: R_X86_64_GLOB_DAT + - Offset: 0x403FF8 + Symbol: __gmon_start__ + Type: R_X86_64_GLOB_DAT + - Name: .rela.plt + Type: SHT_RELA + Flags: [ SHF_ALLOC, SHF_INFO_LINK ] + Address: 0x400560 + Link: .dynsym + AddressAlign: 0x8 + Info: .got.plt + Relocations: + - Offset: 0x404018 + Symbol: putchar + Type: R_X86_64_JUMP_SLOT + - Offset: 0x404020 + Symbol: puts + Type: R_X86_64_JUMP_SLOT + - Offset: 0x404028 + Symbol: pow + Type: R_X86_64_JUMP_SLOT + - Offset: 0x404030 + Symbol: __stack_chk_fail + Type: R_X86_64_JUMP_SLOT + - Offset: 0x404038 + Symbol: printf + Type: R_X86_64_JUMP_SLOT + - Offset: 0x404040 + Symbol: cos + Type: R_X86_64_JUMP_SLOT + - Offset: 0x404048 + Symbol: acos + Type: R_X86_64_JUMP_SLOT + - Offset: 0x404050 + Symbol: sqrt + Type: R_X86_64_JUMP_SLOT + - Name: .init + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x401000 + AddressAlign: 0x4 + Offset: 0x1000 + Content: F30F1EFA4883EC08488B05E92F00004885C07402FFD04883C408C3 + - Name: .plt + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x401020 + AddressAlign: 0x10 + EntSize: 0x10 + Content: FF35E22F0000FF25E42F00000F1F4000FF25E22F00006800000000E9E0FFFFFFFF25DA2F00006801000000E9D0FFFFFFFF25D22F00006802000000E9C0FFFFFFFF25CA2F00006803000000E9B0FFFFFFFF25C22F00006804000000E9A0FFFFFFFF25BA2F00006805000000E990FFFFFFFF25B22F00006806000000E980FFFFFFFF25AA2F00006807000000E970FFFFFF + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x4010B0 + AddressAlign: 0x10 + Content: 4156BF082040004155415455534883EC5064488B042528000000488944244831C0E86AFFFFFF488D742430488D7C2424488B0529100000F20F101529100000F20F100D2910000066480F6ED8488B050510000066480F6EC0E8F3060000BFBF20400031C0E857FFFFFF448B5C24244585DB7E2131DBF20F1044DC30BFCA204000B8010000004883C301E832FFFFFF395C24247FE1BF0A000000E8E2FEFFFF488D742430488D7C2424488B05B10F0000F20F1015C10F0000F20F100DC10F000066480F6ED8488B058D0F000066480F6EC0E87B060000BFBF20400031C0E8DFFEFFFF448B5424244585D27E2131DBF20F1044DC30BFCA204000B8010000004883C301E8BAFEFFFF395C24247FE1BF0A000000E86AFEFFFF488B053B0F0000F20F101D630F0000488D742430F20F10155E0F0000F20F100D5E0F0000488D7C242466480F6EC0E807060000BFBF20400031C0E86BFEFFFF448B4C24244585C97E2131DBF20F1044DC30BFCA204000B8010000004883C301E846FEFFFF395C24247FE1BF0A000000E8F6FDFFFF488D742430488D7C2424488B05BD0E0000F20F101DFD0E0000F20F100DFD0E000066480F6ED066480F6EC0E896050000BFBF20400031C0E8FAFDFFFF448B4424244585C07E2131DBF20F1044DC30BFCA204000B8010000004883C301E8D5FDFFFF395C24247FE1BF0A000000E885FDFFFF488B05460E0000F20F101DA60E0000488D742430F20F100DA10E0000F20F1005A10E0000488D7C242466480F6ED0E822050000BFBF20400031C0E886FDFFFF8B7C242485FF7E2131DBF20F1044DC30BFCA204000B8010000004883C301E863FDFFFF395C24247FE1BF0A000000E813FDFFFFF20F101D530E0000F20F1015530E0000488D742430F20F100D4E0E0000F20F10054E0E0000488D7C2424E8B4040000BFBF20400031C0E818FDFFFF8B74242485F67E2131DBF20F1044DC30BFCA204000B8010000004883C301E8F5FCFFFF395C24247FE1BF0A000000E8A5FCFFFFF20F101D050E0000F20F1015050E0000488D742430F20F100D000E0000F20F1005000E0000488D7C2424E846040000BFBF20400031C0E8AAFCFFFF8B4C242485C97E2131DBF20F1044DC30BFCA204000B8010000004883C301E887FCFFFF395C24247FE1BF0A000000E837FCFFFFF20F101DB70D0000F20F1015B70D0000488D742430F20F100DB20D0000F20F1005B20D0000488D7C2424E8D8030000BFBF20400031C0E83CFCFFFF8B54242485D27E2131DBF20F1044DC30BFCA204000B8010000004883C301E819FCFFFF395C24247FE1BF0A00000041BD09000000E8C3FBFFFF488B05940C00004889442410488B05800C000041BE280000004889442418488B05660C000041BC1100000048894424080F1F00488B05490C0000BD0900000048890424F20F101C24488D742430488D7C2424F20F10542408F20F104C2418F20F10442410E82A030000BFBF20400031C0E88EFBFFFF8B44242485C07E2131DBF20F1044DC30BFCA204000B8010000004883C301E86BFBFFFF395C24247FE1BF0A000000E81BFBFFFFF20F102424F20F5C25B60C0000F20F11242483ED017584F20F102DAC0C0000F20F586C2408F20F116C24084183EC010F8556FFFFFFF20F107C2418F20F5C3D900C0000F20F117C24184183EE010F8523FFFFFFF20F103D980B0000F20F587C2410F20F117C24104183ED010F85F3FEFFFFBF3020400031DBE8AEFAFFFF4889DF488D742428E8C10500008B54242889DEBFCE20400031C04883C302E8BBFAFFFF4881FBA086010075D4BF0A000000BB6901ED3FE863FAFFFF4889DF488D742428E8860500008B5424284889DE31C0BFDF2040004883C301E87FFAFFFF4881FB6941ED3F75D3BF58204000E83CFAFFFF660FEFD2660F28C2F20F111424E8CA010000F20F101424BF80204000B802000000660F28C8660F28C2E83EFAFFFFF20F101424F20F5815B10B0000F20F103DB10B0000660F2FFA73BBBFEE204000E8E9F9FFFF660FEFD2660F28C2F20F111424E857010000F20F101424BFA0204000B802000000660F28C8660F28C2E8EBF9FFFFF20F101424F20F58156E0B0000F20F103D6E0B0000660F2FFA73BB488B442448644833042528000000750F4883C45031C05B5D415C415D415EC3E89CF9FFFF662E0F1F8400000000006690F30F1EFA31ED4989D15E4889E24883E4F0505449C7C0201C400048C7C1B01B400048C7C7B0104000FF15F2280000F490F30F1EFAC3662E0F1F84000000000090B868404000483D684040007413B8000000004885C07409BF68404000FFE06690C30F1F440000662E0F1F840000000000BE684040004881EE684040004889F048C1EE3F48C1F8034801C648D1FE7411B8000000004885C07407BF68404000FFE0C30F1F440000662E0F1F840000000000803DE1280000007517554889E5E87EFFFFFFC605CF280000015DC30F1F440000C30F1F440000662E0F1F840000000000EB8E662E0F1F8400000000000F1F4000F20F5905480A0000F20F5E05480A0000C366662E0F1F8400000000000F1F4000F20F5905300A0000F20F5E05200A0000C3662E0F1F8400000000000F1F440000F20F5EC8534889F34883EC50F20F5ED0F20F110C24DD0424660FEFC9DB3C24DB2C24F20F5ED8F20F11542418DD442418D9C1D8CAD905E6090000D8CADEE9D905E0090000DCF9F20F115C2418D9C3D8C4D8CCD8CCD9CCDEC9DECAD9CADEE1D905C4090000DC4C2418DEC1D835BC090000D9C1D8CAD8CAD9C1D8CAD8E1DD5C2418F20F10442418660F2FC80F8398000000DDD8660F2EC8660F28D0C70701000000F20F51D20F87B6010000D9C9DB7C2430F20F100D90090000DD542418F20F10442418660F540586090000DB7C2420F20F58C2E879F7FFFFF20F11442418DD442418DB6C2430D8F1DEC1DD5C2418DB6C2420D9EEDFF1DDD87714F20F107C2418660F573D59090000F20F117C2418DB2C24D8350A090000DC6C2418DD1B4883C4505BC3660F1F440000DD5C2418F20F10442418C70703000000660F28F0660F2EC8F20F51F6F20F117424180F8736010000D9C9DB7C2420DC742418DD5C2418F20F10442418E827F7FFFFDB6C2420660FEFC9F20F11442418DD5C2420F20F10542420660F2ECA660F28DAF20F51DB0F870D010000F20F102DD5070000F20F591D8D080000F20F5EC5F20F116C2430F20F115C2420E8C8F6FFFFDB2C24F20F11442440F20F10442418D83553080000F20F580563080000F20F5E442430DB3C24E89DF6FFFFF20F104C2440F20F10642420DB2C24660F28D0F20F59CCF20F59D4D9C0F20F114C2440DC6C2440DD5C2440F20F10442440F20F11542440DC6C2440DD5C2440660F164424400F1103F20F10442418F20F580507080000F20F5E442430E83CF6FFFFF20F59442420DB2C24F20F11442418DC6C2418DD5B104883C4505BC3DB7C2430F20F11542418DB7C2420E82DF6FFFFF20F10542418DB6C2430DB6C2420E926FEFFFFDB7C2430DB7C2420E80DF6FFFFDB6C2430DB6C2420E9B2FEFFFF660F28C2F20F11542448F20F115C2420E8EBF5FFFFF20F103DB3060000F20F10442418F20F105C2420F20F591D5F070000F20F5EC7F20F117C2430F20F115C2420E89AF5FFFFDB2C24F20F10742420F20F10542448D83525070000F20F59F0660F28C2F20F11742440D9C0DB3C24DC6C2440DD1BE887F5FFFFF20F10442418F20F580511070000F20F5E442430E84EF5FFFFDB2C24F20F10542448F20F59442420F20F11442440DC6C2440660F28C2DD5B08E849F5FFFFE9CFFEFFFF0F1F400041B82000000031C031D2660F1F4400004889F948C1E70248C1E91E83E103488D1491488D0C85010000004801C04839CA72074829CA4883C0014183E80175D1488906C3662E0F1F8400000000000F1F00F30F1EFA41574C8D3D4322000041564989D641554989F541544189FC55488D2D34220000534C29FD4883EC08E81FF4FFFF48C1FD03741F31DB0F1F80000000004C89F24C89EE4489E741FF14DF4883C3014839DD75EA4883C4085B5D415C415D415E415FC366662E0F1F840000000000F30F1EFAC3 + - Name: .fini + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x401C28 + AddressAlign: 0x4 + Content: F30F1EFA4883EC084883C408C3 + - Name: .rodata + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x402000 + AddressAlign: 0x10 + Offset: 0x2000 + Content: 01000200000000002A2A2A2A2A2A2A2A2A2043554249432046554E4354494F4E53202A2A2A2A2A2A2A2A2A2A2A0000002A2A2A2A2A2A2A2A2A20494E54454745522053515220524F4F5453202A2A2A2A2A2A2A2A2A2A2A002A2A2A2A2A2A2A2A2A20414E474C4520434F4E56455253494F4E202A2A2A2A2A2A2A2A2A2A2A000025332E30662064656772656573203D20252E3132662072616469616E730A0000252E3132662072616469616E73203D2025332E306620646567726565730A00536F6C7574696F6E733A0020256600737172742825336429203D202532640A007371727428256C5829203D2025580A0000000000000000F0BF00000000000014400000000000002440000000000000F03F0000000000003EC0000000000000404000000000000025C0000000000000314000000000000012C00000000000003FC000000000000036400000000000000CC000000000008041C06666666666662BC00000000000002840AE47E17A14AE284000000000000008409A999999999937C00000000000001840295C8FC2F5F850C000000000000020C000000000000041400000000000001E40D7A3703D0A572140000000000080464000000000000030403333333333331540333333333333FBBF00000000000028C077BE9F1A2FDDDC3F85EB51B81E85E33F000000000000D03FFCA9F1D24D62503F0000000000807640399D52A246DF413F9B0B6097FB2119400000000000806640182D4454FB21094000004040000010410000D8410000584200000000000000C0182D4454FB211940182D4454FB212940555555555555D53FFFFFFFFFFFFFFF7F000000000000000000000000000000800000000000000000 + - Name: .eh_frame_hdr + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x402270 + AddressAlign: 0x4 + Content: 011B033B5C0000000A000000B0EDFFFFA000000040EEFFFFC800000060F4FFFF7800000090F4FFFF8C00000050F5FFFF1001000070F5FFFF2401000090F5FFFF38010000F0F8FFFF6801000040F9FFFF80010000B0F9FFFFC8010000 + - Name: .eh_frame + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0x4022D0 + AddressAlign: 0x8 + Content: 1400000000000000017A5200017810011B0C070890010000100000001C000000E0F3FFFF2F000000004407101000000030000000FCF3FFFF0500000000000000240000004400000008EDFFFF90000000000E10460E184A0F0B770880003F1A3B2A33242200000000440000006C00000070EDFFFF1406000000420E108E02470E188D03420E208C04410E288605410E308306440E800103F3050A0E30430E28410E20420E18420E10420E08410B00000010000000B400000038F4FFFF110000000000000010000000C800000044F4FFFF11000000000000002C000000DC00000050F4FFFF5C03000000450E108302470E600314010A0E10410E08470B0336010A0E10410E08410B00140000000C01000080F7FFFF4300000000000000000000004400000024010000B8F7FFFF6500000000460E108F02490E188E03450E208D04450E288C05440E308606480E388307470E406E0E38410E30410E28420E20420E18420E10420E0800100000006C010000E0F7FFFF050000000000000000000000 + - Name: .init_array + Type: SHT_INIT_ARRAY + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x403E00 + AddressAlign: 0x8 + EntSize: 0x8 + Offset: 0x2E00 + Content: B017400000000000 + - Name: .fini_array + Type: SHT_FINI_ARRAY + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x403E08 + AddressAlign: 0x8 + EntSize: 0x8 + Content: '8017400000000000' + - Name: .dynamic + Type: SHT_DYNAMIC + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x403E10 + Link: .dynstr + AddressAlign: 0x8 + Entries: + - Tag: DT_NEEDED + Value: 0x1 + - Tag: DT_NEEDED + Value: 0x28 + - Tag: DT_INIT + Value: 0x401000 + - Tag: DT_FINI + Value: 0x401C28 + - Tag: DT_INIT_ARRAY + Value: 0x403E00 + - Tag: DT_INIT_ARRAYSZ + Value: 0x8 + - Tag: DT_FINI_ARRAY + Value: 0x403E08 + - Tag: DT_FINI_ARRAYSZ + Value: 0x8 + - Tag: DT_GNU_HASH + Value: 0x400308 + - Tag: DT_STRTAB + Value: 0x400430 + - Tag: DT_SYMTAB + Value: 0x400328 + - Tag: DT_STRSZ + Value: 0x8A + - Tag: DT_SYMENT + Value: 0x18 + - Tag: DT_DEBUG + Value: 0x0 + - Tag: DT_PLTGOT + Value: 0x404000 + - Tag: DT_PLTRELSZ + Value: 0xC0 + - Tag: DT_PLTREL + Value: 0x7 + - Tag: DT_JMPREL + Value: 0x400560 + - Tag: DT_RELA + Value: 0x400530 + - Tag: DT_RELASZ + Value: 0x30 + - Tag: DT_RELAENT + Value: 0x18 + - Tag: DT_VERNEED + Value: 0x4004D0 + - Tag: DT_VERNEEDNUM + Value: 0x2 + - Tag: DT_VERSYM + Value: 0x4004BA + - Tag: DT_NULL + Value: 0x0 + - Tag: DT_NULL + Value: 0x0 + - Tag: DT_NULL + Value: 0x0 + - Tag: DT_NULL + Value: 0x0 + - Tag: DT_NULL + Value: 0x0 + - Tag: DT_NULL + Value: 0x0 + - Name: .got + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x403FF0 + AddressAlign: 0x8 + EntSize: 0x8 + Content: '00000000000000000000000000000000' + - Name: .got.plt + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x404000 + AddressAlign: 0x8 + EntSize: 0x8 + Content: 103E400000000000000000000000000000000000000000003610400000000000461040000000000056104000000000006610400000000000761040000000000086104000000000009610400000000000A610400000000000 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x404058 + AddressAlign: 0x8 + Content: '00000000000000000000000000000000' + - Name: .tm_clone_table + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x404068 + AddressAlign: 0x8 + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x404068 + AddressAlign: 0x1 + Size: 0x8 + - Name: .comment + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x1 + EntSize: 0x1 + Content: 4743433A20285562756E747520392E342E302D317562756E7475317E31362E30342920392E342E3000 + - Name: .rela.init + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .init + Relocations: + - Offset: 0x40100B + Symbol: __gmon_start__ + Type: R_X86_64_REX_GOTPCRELX + Addend: -4 + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .text + Relocations: + - Offset: 0x4010B3 + Symbol: .rodata + Type: R_X86_64_32 + Addend: 8 + - Offset: 0x4010D2 + Symbol: 'puts@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4010E3 + Symbol: .LC6 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4010EB + Symbol: .LC7 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4010F3 + Symbol: .LC8 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4010FF + Symbol: .LC4 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401109 + Symbol: SolveCubic + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x40110E + Symbol: .rodata + Type: R_X86_64_32 + Addend: 191 + - Offset: 0x401115 + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x40112C + Symbol: .rodata + Type: R_X86_64_32 + Addend: 202 + - Offset: 0x40113A + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x40114A + Symbol: 'putchar@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x40115B + Symbol: .LC6 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401163 + Symbol: .LC11 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x40116B + Symbol: .LC12 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401177 + Symbol: .LC4 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401181 + Symbol: SolveCubic + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401186 + Symbol: .rodata + Type: R_X86_64_32 + Addend: 191 + - Offset: 0x40118D + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4011A4 + Symbol: .rodata + Type: R_X86_64_32 + Addend: 202 + - Offset: 0x4011B2 + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4011C2 + Symbol: 'putchar@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4011C9 + Symbol: .LC4 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4011D1 + Symbol: .LC13 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4011DE + Symbol: .LC14 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4011E6 + Symbol: .LC15 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4011F5 + Symbol: SolveCubic + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4011FA + Symbol: .rodata + Type: R_X86_64_32 + Addend: 191 + - Offset: 0x401201 + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401218 + Symbol: .rodata + Type: R_X86_64_32 + Addend: 202 + - Offset: 0x401226 + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401236 + Symbol: 'putchar@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401247 + Symbol: .LC4 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x40124F + Symbol: .LC16 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401257 + Symbol: .LC17 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401266 + Symbol: SolveCubic + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x40126B + Symbol: .rodata + Type: R_X86_64_32 + Addend: 191 + - Offset: 0x401272 + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401289 + Symbol: .rodata + Type: R_X86_64_32 + Addend: 202 + - Offset: 0x401297 + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4012A7 + Symbol: 'putchar@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4012AE + Symbol: .LC2 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4012B6 + Symbol: .LC18 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4012C3 + Symbol: .LC19 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4012CB + Symbol: .LC20 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4012DA + Symbol: SolveCubic + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4012DF + Symbol: .rodata + Type: R_X86_64_32 + Addend: 191 + - Offset: 0x4012E6 + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4012FB + Symbol: .rodata + Type: R_X86_64_32 + Addend: 202 + - Offset: 0x401309 + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401319 + Symbol: 'putchar@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401321 + Symbol: .LC21 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401329 + Symbol: .LC22 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401336 + Symbol: .LC23 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x40133E + Symbol: .LC24 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401348 + Symbol: SolveCubic + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x40134D + Symbol: .rodata + Type: R_X86_64_32 + Addend: 191 + - Offset: 0x401354 + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401369 + Symbol: .rodata + Type: R_X86_64_32 + Addend: 202 + - Offset: 0x401377 + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401387 + Symbol: 'putchar@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x40138F + Symbol: .LC25 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401397 + Symbol: .LC26 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4013A4 + Symbol: .LC27 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4013AC + Symbol: .LC28 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4013B6 + Symbol: SolveCubic + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4013BB + Symbol: .rodata + Type: R_X86_64_32 + Addend: 191 + - Offset: 0x4013C2 + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4013D7 + Symbol: .rodata + Type: R_X86_64_32 + Addend: 202 + - Offset: 0x4013E5 + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4013F5 + Symbol: 'putchar@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4013FD + Symbol: .LC29 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401405 + Symbol: .LC30 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401412 + Symbol: .LC31 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x40141A + Symbol: .LC32 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401424 + Symbol: SolveCubic + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401429 + Symbol: .rodata + Type: R_X86_64_32 + Addend: 191 + - Offset: 0x401430 + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401445 + Symbol: .rodata + Type: R_X86_64_32 + Addend: 202 + - Offset: 0x401453 + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401469 + Symbol: 'putchar@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401470 + Symbol: .LC4 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x40147C + Symbol: .LC3 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x40148E + Symbol: .LC2 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4014A3 + Symbol: .LC0 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4014D2 + Symbol: SolveCubic + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4014D7 + Symbol: .rodata + Type: R_X86_64_32 + Addend: 191 + - Offset: 0x4014DE + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4014F3 + Symbol: .rodata + Type: R_X86_64_32 + Addend: 202 + - Offset: 0x401501 + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401511 + Symbol: 'putchar@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x40151E + Symbol: .LC33 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401530 + Symbol: .LC34 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401554 + Symbol: .LC35 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x40156C + Symbol: .LC4 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401587 + Symbol: .rodata + Type: R_X86_64_32 + Addend: 48 + - Offset: 0x40158E + Symbol: 'puts@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x40159B + Symbol: usqrt + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4015A6 + Symbol: .rodata + Type: R_X86_64_32 + Addend: 206 + - Offset: 0x4015B1 + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4015C9 + Symbol: 'putchar@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4015D6 + Symbol: usqrt + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4015E4 + Symbol: .rodata + Type: R_X86_64_32 + Addend: 223 + - Offset: 0x4015ED + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4015FB + Symbol: .rodata + Type: R_X86_64_32 + Addend: 88 + - Offset: 0x401600 + Symbol: 'puts@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401612 + Symbol: deg2rad + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x40161C + Symbol: .rodata + Type: R_X86_64_32 + Addend: 128 + - Offset: 0x40162E + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x40163B + Symbol: .LC41 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401643 + Symbol: .LC42 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x40164E + Symbol: .rodata + Type: R_X86_64_32 + Addend: 238 + - Offset: 0x401653 + Symbol: 'puts@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401665 + Symbol: rad2deg + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x40166F + Symbol: .rodata + Type: R_X86_64_32 + Addend: 160 + - Offset: 0x401681 + Symbol: 'printf@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x40168E + Symbol: .LC45 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401696 + Symbol: .LC46 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4016C0 + Symbol: '__stack_chk_fail@@GLIBC_2.4' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4016E6 + Symbol: __libc_csu_fini + Type: R_X86_64_32S + - Offset: 0x4016ED + Symbol: __libc_csu_init + Type: R_X86_64_32S + - Offset: 0x4016F4 + Symbol: main + Type: R_X86_64_32S + - Offset: 0x4016FA + Symbol: '__libc_start_main@@GLIBC_2.2.5' + Type: R_X86_64_GOTPCRELX + Addend: -4 + - Offset: 0x401711 + Symbol: __TMC_END__ + Type: R_X86_64_32 + - Offset: 0x401717 + Symbol: .tm_clone_table + Type: R_X86_64_32S + - Offset: 0x40171E + Symbol: _ITM_deregisterTMCloneTable + Type: R_X86_64_32 + - Offset: 0x401728 + Symbol: .tm_clone_table + Type: R_X86_64_32 + - Offset: 0x401741 + Symbol: __TMC_END__ + Type: R_X86_64_32 + - Offset: 0x401748 + Symbol: .tm_clone_table + Type: R_X86_64_32S + - Offset: 0x401760 + Symbol: _ITM_registerTMCloneTable + Type: R_X86_64_32 + - Offset: 0x40176A + Symbol: .tm_clone_table + Type: R_X86_64_32 + - Offset: 0x401782 + Symbol: .bss + Type: R_X86_64_PC32 + Addend: -5 + - Offset: 0x401794 + Symbol: .bss + Type: R_X86_64_PC32 + Addend: -5 + - Offset: 0x4017C4 + Symbol: '.LC0 (1)' + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4017CC + Symbol: .LC1 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4017E4 + Symbol: .LC1 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4017EC + Symbol: '.LC0 (1)' + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401836 + Symbol: '.LC0 (2)' + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401840 + Symbol: '.LC1 (1)' + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401860 + Symbol: '.LC2 (1)' + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x40186C + Symbol: '.LC3 (1)' + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4018B4 + Symbol: .LC9 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4018C6 + Symbol: .LC10 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4018D3 + Symbol: 'pow@@GLIBC_2.29' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401903 + Symbol: '.LC12 (1)' + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401912 + Symbol: '.LC0 (2)' + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401965 + Symbol: 'acos@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401997 + Symbol: '.LC6 (1)' + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x40199F + Symbol: .LC5 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4019B4 + Symbol: 'cos@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x4019C9 + Symbol: '.LC0 (2)' + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4019D1 + Symbol: '.LC7 (1)' + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x4019DF + Symbol: 'cos@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401A35 + Symbol: '.LC8 (1)' + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401A40 + Symbol: 'cos@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401A6F + Symbol: 'sqrt@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401A8F + Symbol: 'sqrt@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401AB1 + Symbol: 'sqrt@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401AB9 + Symbol: '.LC6 (1)' + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401ACD + Symbol: .LC5 + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401AE2 + Symbol: 'cos@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401AF7 + Symbol: '.LC0 (2)' + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401B15 + Symbol: 'sqrt@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401B23 + Symbol: '.LC7 (1)' + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401B2E + Symbol: 'cos@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401B53 + Symbol: 'sqrt@@GLIBC_2.2.5' + Type: R_X86_64_PLT32 + Addend: -4 + - Offset: 0x401BB9 + Symbol: __init_array_start + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401BD0 + Symbol: __init_array_end + Type: R_X86_64_PC32 + Addend: -4 + - Offset: 0x401BDD + Symbol: _init + Type: R_X86_64_PLT32 + Addend: -4 + - Name: .rela.eh_frame + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .eh_frame + Relocations: + - Offset: 0x4022F0 + Symbol: .text + Type: R_X86_64_PC32 + Addend: 1568 + - Offset: 0x402304 + Symbol: .text + Type: R_X86_64_PC32 + Addend: 1616 + - Offset: 0x402340 + Symbol: .text + Type: R_X86_64_PC32 + - Offset: 0x402388 + Symbol: .text + Type: R_X86_64_PC32 + Addend: 1808 + - Offset: 0x40239C + Symbol: .text + Type: R_X86_64_PC32 + Addend: 1840 + - Offset: 0x4023B0 + Symbol: .text + Type: R_X86_64_PC32 + Addend: 1872 + - Offset: 0x4023E0 + Symbol: .text + Type: R_X86_64_PC32 + Addend: 2736 + - Offset: 0x4023F8 + Symbol: .text + Type: R_X86_64_PC32 + Addend: 2816 + - Offset: 0x402440 + Symbol: .text + Type: R_X86_64_PC32 + Addend: 2928 + - Name: .rela.init_array + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .init_array + Relocations: + - Offset: 0x403E00 + Symbol: .text + Type: R_X86_64_64 + Addend: 1792 + - Name: .rela.fini_array + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .fini_array + Relocations: + - Offset: 0x403E08 + Symbol: .text + Type: R_X86_64_64 + Addend: 1744 + - Type: SectionHeaderTable + Sections: + - Name: .interp + - Name: .note.gnu.build-id + - Name: .note.ABI-tag + - Name: .gnu.hash + - Name: .dynsym + - Name: .dynstr + - Name: .gnu.version + - Name: .gnu.version_r + - Name: .rela.dyn + - Name: .rela.plt + - Name: .init + - Name: .rela.init + - Name: .plt + - Name: .text + - Name: .rela.text + - Name: .fini + - Name: .rodata + - Name: .eh_frame_hdr + - Name: .eh_frame + - Name: .rela.eh_frame + - Name: .init_array + - Name: .rela.init_array + - Name: .fini_array + - Name: .rela.fini_array + - Name: .dynamic + - Name: .got + - Name: .got.plt + - Name: .data + - Name: .tm_clone_table + - Name: .bss + - Name: .comment + - Name: .symtab + - Name: .strtab + - Name: .shstrtab +Symbols: + - Name: .interp + Type: STT_SECTION + Section: .interp + Value: 0x4002A8 + - Name: .note.gnu.build-id + Type: STT_SECTION + Section: .note.gnu.build-id + Value: 0x4002C4 + - Name: .note.ABI-tag + Type: STT_SECTION + Section: .note.ABI-tag + Value: 0x4002E8 + - Name: .gnu.hash + Type: STT_SECTION + Section: .gnu.hash + Value: 0x400308 + - Name: .dynsym + Type: STT_SECTION + Section: .dynsym + Value: 0x400328 + - Name: .dynstr + Type: STT_SECTION + Section: .dynstr + Value: 0x400430 + - Name: .gnu.version + Type: STT_SECTION + Section: .gnu.version + Value: 0x4004BA + - Name: .gnu.version_r + Type: STT_SECTION + Section: .gnu.version_r + Value: 0x4004D0 + - Name: .rela.dyn + Type: STT_SECTION + Section: .rela.dyn + Value: 0x400530 + - Name: .rela.plt + Type: STT_SECTION + Section: .rela.plt + Value: 0x400560 + - Name: .init + Type: STT_SECTION + Section: .init + Value: 0x401000 + - Name: .plt + Type: STT_SECTION + Section: .plt + Value: 0x401020 + - Name: .text + Type: STT_SECTION + Section: .text + Value: 0x4010B0 + - Name: .fini + Type: STT_SECTION + Section: .fini + Value: 0x401C28 + - Name: .rodata + Type: STT_SECTION + Section: .rodata + Value: 0x402000 + - Name: .eh_frame_hdr + Type: STT_SECTION + Section: .eh_frame_hdr + Value: 0x402270 + - Name: .eh_frame + Type: STT_SECTION + Section: .eh_frame + Value: 0x4022D0 + - Name: .init_array + Type: STT_SECTION + Section: .init_array + Value: 0x403E00 + - Name: .fini_array + Type: STT_SECTION + Section: .fini_array + Value: 0x403E08 + - Name: .dynamic + Type: STT_SECTION + Section: .dynamic + Value: 0x403E10 + - Name: .got + Type: STT_SECTION + Section: .got + Value: 0x403FF0 + - Name: .got.plt + Type: STT_SECTION + Section: .got.plt + Value: 0x404000 + - Name: .data + Type: STT_SECTION + Section: .data + Value: 0x404058 + - Name: .tm_clone_table + Type: STT_SECTION + Section: .tm_clone_table + Value: 0x404068 + - Name: .bss + Type: STT_SECTION + Section: .bss + Value: 0x404068 + - Name: .comment + Type: STT_SECTION + Section: .comment + - Name: basicmath_large.c + Type: STT_FILE + Index: SHN_ABS + - Name: .LC6 + Section: .rodata + Value: 0x402110 + - Name: .LC7 + Section: .rodata + Value: 0x402118 + - Name: .LC8 + Section: .rodata + Value: 0x402120 + - Name: .LC4 + Section: .rodata + Value: 0x402108 + - Name: .LC11 + Section: .rodata + Value: 0x402128 + - Name: .LC12 + Section: .rodata + Value: 0x402130 + - Name: .LC13 + Section: .rodata + Value: 0x402138 + - Name: .LC14 + Section: .rodata + Value: 0x402140 + - Name: .LC15 + Section: .rodata + Value: 0x402148 + - Name: .LC16 + Section: .rodata + Value: 0x402150 + - Name: .LC17 + Section: .rodata + Value: 0x402158 + - Name: .LC2 + Section: .rodata + Value: 0x4020F8 + - Name: .LC18 + Section: .rodata + Value: 0x402160 + - Name: .LC19 + Section: .rodata + Value: 0x402168 + - Name: .LC20 + Section: .rodata + Value: 0x402170 + - Name: .LC21 + Section: .rodata + Value: 0x402178 + - Name: .LC22 + Section: .rodata + Value: 0x402180 + - Name: .LC23 + Section: .rodata + Value: 0x402188 + - Name: .LC24 + Section: .rodata + Value: 0x402190 + - Name: .LC25 + Section: .rodata + Value: 0x402198 + - Name: .LC26 + Section: .rodata + Value: 0x4021A0 + - Name: .LC27 + Section: .rodata + Value: 0x4021A8 + - Name: .LC28 + Section: .rodata + Value: 0x4021B0 + - Name: .LC29 + Section: .rodata + Value: 0x4021B8 + - Name: .LC30 + Section: .rodata + Value: 0x4021C0 + - Name: .LC31 + Section: .rodata + Value: 0x4021C8 + - Name: .LC32 + Section: .rodata + Value: 0x4021D0 + - Name: .LC3 + Section: .rodata + Value: 0x402100 + - Name: .LC0 + Section: .rodata + Value: 0x4020F0 + - Name: .LC33 + Section: .rodata + Value: 0x4021D8 + - Name: .LC34 + Section: .rodata + Value: 0x4021E0 + - Name: .LC35 + Section: .rodata + Value: 0x4021E8 + - Name: .LC41 + Section: .rodata + Value: 0x4021F0 + - Name: .LC42 + Section: .rodata + Value: 0x4021F8 + - Name: .LC45 + Section: .rodata + Value: 0x402200 + - Name: .LC46 + Section: .rodata + Value: 0x402208 + - Name: crtstuff.c + Type: STT_FILE + Index: SHN_ABS + - Name: __TMC_LIST__ + Type: STT_OBJECT + Section: .tm_clone_table + Value: 0x404068 + - Name: deregister_tm_clones + Type: STT_FUNC + Section: .text + Value: 0x401710 + - Name: register_tm_clones + Type: STT_FUNC + Section: .text + Value: 0x401740 + - Name: __do_global_dtors_aux + Type: STT_FUNC + Section: .text + Value: 0x401780 + - Name: completed.8023 + Type: STT_OBJECT + Section: .bss + Value: 0x404068 + Size: 0x1 + - Name: __do_global_dtors_aux_fini_array_entry + Type: STT_OBJECT + Section: .fini_array + Value: 0x403E08 + - Name: frame_dummy + Type: STT_FUNC + Section: .text + Value: 0x4017B0 + - Name: __frame_dummy_init_array_entry + Type: STT_OBJECT + Section: .init_array + Value: 0x403E00 + - Name: rad2deg.c + Type: STT_FILE + Index: SHN_ABS + - Name: '.LC0 (1)' + Section: .rodata + Value: 0x402210 + - Name: .LC1 + Section: .rodata + Value: 0x402218 + - Name: cubic.c + Type: STT_FILE + Index: SHN_ABS + - Name: '.LC0 (2)' + Section: .rodata + Value: 0x402220 + - Name: '.LC1 (1)' + Section: .rodata + Value: 0x402224 + - Name: '.LC2 (1)' + Section: .rodata + Value: 0x402228 + - Name: '.LC3 (1)' + Section: .rodata + Value: 0x40222C + - Name: .LC9 + Section: .rodata + Value: 0x402248 + - Name: .LC10 + Section: .rodata + Value: 0x402250 + - Name: '.LC12 (1)' + Section: .rodata + Value: 0x402260 + - Name: '.LC6 (1)' + Section: .rodata + Value: 0x402170 + - Name: .LC5 + Section: .rodata + Value: 0x402230 + - Name: '.LC7 (1)' + Section: .rodata + Value: 0x402238 + - Name: '.LC8 (1)' + Section: .rodata + Value: 0x402240 + - Name: isqrt.c + Type: STT_FILE + Index: SHN_ABS + - Name: 'crtstuff.c (1)' + Type: STT_FILE + Index: SHN_ABS + - Name: __FRAME_END__ + Type: STT_OBJECT + Section: .eh_frame + Value: 0x40244C + - Type: STT_FILE + Index: SHN_ABS + - Name: __init_array_end + Section: .init_array + Value: 0x403E08 + - Name: _DYNAMIC + Type: STT_OBJECT + Section: .dynamic + Value: 0x403E10 + - Name: __init_array_start + Section: .init_array + Value: 0x403E00 + - Name: __GNU_EH_FRAME_HDR + Section: .eh_frame_hdr + Value: 0x402270 + - Name: _GLOBAL_OFFSET_TABLE_ + Type: STT_OBJECT + Section: .got.plt + Value: 0x404000 + - Name: __libc_csu_fini + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x401C20 + Size: 0x5 + - Name: 'putchar@@GLIBC_2.2.5' + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: _ITM_deregisterTMCloneTable + Binding: STB_WEAK + - Name: data_start + Section: .data + Binding: STB_WEAK + Value: 0x404058 + - Name: 'puts@@GLIBC_2.2.5' + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: usqrt + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x401B60 + Size: 0x43 + - Name: _edata + Section: .tm_clone_table + Binding: STB_GLOBAL + Value: 0x404068 + - Name: 'pow@@GLIBC_2.29' + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: _fini + Type: STT_FUNC + Section: .fini + Binding: STB_GLOBAL + Value: 0x401C28 + Other: [ STV_HIDDEN ] + - Name: '__stack_chk_fail@@GLIBC_2.4' + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: 'printf@@GLIBC_2.2.5' + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: 'cos@@GLIBC_2.2.5' + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: 'acos@@GLIBC_2.2.5' + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: '__libc_start_main@@GLIBC_2.2.5' + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: deg2rad + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x4017E0 + Size: 0x11 + - Name: __data_start + Section: .data + Binding: STB_GLOBAL + Value: 0x404058 + - Name: SolveCubic + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x401800 + Size: 0x35C + - Name: __gmon_start__ + Binding: STB_WEAK + - Name: __dso_handle + Type: STT_OBJECT + Section: .data + Binding: STB_GLOBAL + Value: 0x404060 + Other: [ STV_HIDDEN ] + - Name: _IO_stdin_used + Type: STT_OBJECT + Section: .rodata + Binding: STB_GLOBAL + Value: 0x402000 + Size: 0x4 + - Name: __libc_csu_init + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x401BB0 + Size: 0x65 + - Name: _end + Section: .bss + Binding: STB_GLOBAL + Value: 0x404070 + - Name: _dl_relocate_static_pie + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x401700 + Size: 0x5 + Other: [ STV_HIDDEN ] + - Name: _start + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x4016D0 + Size: 0x2F + - Name: rad2deg + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x4017C0 + Size: 0x11 + - Name: __bss_start + Section: .bss + Binding: STB_GLOBAL + Value: 0x404068 + - Name: main + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x4010B0 + Size: 0x614 + - Name: __TMC_END__ + Type: STT_OBJECT + Section: .tm_clone_table + Binding: STB_GLOBAL + Value: 0x404068 + Other: [ STV_HIDDEN ] + - Name: _ITM_registerTMCloneTable + Binding: STB_WEAK + - Name: 'sqrt@@GLIBC_2.2.5' + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: _init + Type: STT_FUNC + Section: .init + Binding: STB_GLOBAL + Value: 0x401000 + Other: [ STV_HIDDEN ] +DynamicSymbols: + - Name: putchar + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: puts + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: pow + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: __stack_chk_fail + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: printf + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: cos + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: acos + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: __libc_start_main + Type: STT_FUNC + Binding: STB_GLOBAL + - Name: __gmon_start__ + Binding: STB_WEAK + - Name: sqrt + Type: STT_FUNC + Binding: STB_GLOBAL +... diff --git a/bolt/test/X86/Inputs/blarge_new_bat.preagg.txt b/bolt/test/X86/Inputs/blarge_new_bat.preagg.txt new file mode 100644 index 0000000000000000000000000000000000000000..e9e4553aad95c8adeb2b8348c775c6c334d21a80 --- /dev/null +++ b/bolt/test/X86/Inputs/blarge_new_bat.preagg.txt @@ -0,0 +1,79 @@ +B 40169e 40165b 7 0 +B 401664 800012 7 0 +B 401680 401070 7 0 +B 800022 401669 7 0 +B 401611 800000 121 0 +B 40162d 401070 119 0 +B 4015d5 800040 2 0 +B 800080 4015da 6 0 +B 40164b 401608 115 0 +B 800080 40159f 24 0 +B 4015ec 401070 6 0 +B 8001d0 401090 1 0 +B 4014d1 800082 25 0 +B 401510 401030 616 0 +B 8002ab 401080 1 0 +B 80007b 80004c 483 1 +B 800072 80004c 597 77 +B 80010c 800194 1 0 +B 401509 4014ec 1 0 +B 800010 401616 119 0 +B 80024a 401080 1 0 +B 800154 401050 20 0 +B 4014dd 401070 9 0 +B 80021f 401080 1 0 +B 800193 4014d6 8 0 +B 40159a 800040 19 0 +B 4015f8 4015cd 2 0 +B 40152a 4014b0 24 0 +B 401500 401070 15 0 +B 4015bc 401592 21 0 +B 401544 4014a0 1 0 +B 80004a 800052 24 0 +B 4015b0 401070 20 0 +B 800050 80007d 29 29 +F 401685 40169e 7 +F 4014a0 4014d1 1 +F 401090 401090 1 +F 401050 401050 20 +F 40159f 4015b0 20 +F 80007d 800080 27 +F 401515 401544 1 +F 4014e2 401500 13 +F 401592 40159a 19 +F 401505 401509 1 +F 4014b0 4014d1 24 +F 800194 8001d0 1 +F 8001d5 80021f 1 +F 401616 40162d 114 +F 80024f 8002ab 1 +F 800159 800193 7 +F 80004c 800050 26 +F 800224 80024a 1 +F 800082 80010c 1 +F 401080 401080 3 +F 401070 401070 168 +F 80004c 800072 555 +F 401616 800010 2 +F 401070 40162d 4 +F 800082 800154 20 +F 401669 401680 7 +F 40159f 800080 1 +F 4014ec 401500 1 +F 800012 800022 7 +F 401030 401030 616 +F 80004c 80007b 473 +F 800052 800072 24 +F 800040 80004a 21 +F 4015b5 4015bc 18 +F 4015cd 4015d5 2 +F 401592 4015bc 1 +F 4015da 4015ec 6 +F 4015f1 4015f8 2 +F 800000 800010 116 +F 401608 401611 115 +F 401632 40164b 114 +F 401515 40152a 24 +F 40165b 401664 7 +F 401505 401510 612 +F 4014d6 4014dd 8 diff --git a/bolt/test/X86/bolt-address-translation-yaml.test b/bolt/test/X86/bolt-address-translation-yaml.test new file mode 100644 index 0000000000000000000000000000000000000000..7fdf7709a8b9da3d2f103ec88c9b8ad1191893e7 --- /dev/null +++ b/bolt/test/X86/bolt-address-translation-yaml.test @@ -0,0 +1,64 @@ +# Check new BAT format containing hashes for YAML profile. + +RUN: yaml2obj %p/Inputs/blarge_new.yaml &> %t.exe +RUN: llvm-bolt %t.exe -o %t.out --pa -p %p/Inputs/blarge_new.preagg.txt \ +RUN: --reorder-blocks=ext-tsp --split-functions --split-strategy=cdsplit \ +RUN: --reorder-functions=cdsort --enable-bat --dyno-stats --skip-funcs=main \ +RUN: 2>&1 | FileCheck --check-prefix WRITE-BAT-CHECK %s +RUN: perf2bolt %t.out --pa -p %p/Inputs/blarge_new_bat.preagg.txt -w %t.yaml -o %t.fdata \ +RUN: 2>&1 | FileCheck --check-prefix READ-BAT-CHECK %s +RUN: FileCheck --input-file %t.yaml --check-prefix YAML-BAT-CHECK %s +# Check that YAML converted from fdata matches YAML created directly with BAT. +RUN: llvm-bolt %t.exe -data %t.fdata -w %t.yaml-fdata -o /dev/null +RUN: FileCheck --input-file %t.yaml-fdata --check-prefix YAML-BAT-CHECK %s + +# Test resulting YAML profile with the original binary (no-stale mode) +RUN: llvm-bolt %t.exe -data %t.yaml -o %t.null -dyno-stats \ +RUN: | FileCheck --check-prefix CHECK-BOLT-YAML %s + +WRITE-BAT-CHECK: BOLT-INFO: Wrote 5 BAT maps +WRITE-BAT-CHECK: BOLT-INFO: Wrote 4 function and 22 basic block hashes +WRITE-BAT-CHECK: BOLT-INFO: BAT section size (bytes): 384 + +READ-BAT-CHECK-NOT: BOLT-ERROR: unable to save profile in YAML format for input file processed by BOLT +READ-BAT-CHECK: BOLT-INFO: Parsed 5 BAT entries +READ-BAT-CHECK: PERF2BOLT: read 79 aggregated LBR entries + +YAML-BAT-CHECK: functions: +# Function not covered by BAT - has insns in basic block +YAML-BAT-CHECK: - name: main +YAML-BAT-CHECK-NEXT: fid: 2 +YAML-BAT-CHECK-NEXT: hash: 0x9895746D48B2C876 +YAML-BAT-CHECK-NEXT: exec: 0 +YAML-BAT-CHECK-NEXT: nblocks: 46 +YAML-BAT-CHECK-NEXT: blocks: +YAML-BAT-CHECK-NEXT: - bid: 0 +YAML-BAT-CHECK-NEXT: insns: 26 +YAML-BAT-CHECK-NEXT: hash: 0xA900AE79CFD40000 +YAML-BAT-CHECK-NEXT: succ: [ { bid: 3, cnt: 0 }, { bid: 1, cnt: 0 } ] +# Function covered by BAT with calls +YAML-BAT-CHECK: - name: SolveCubic +YAML-BAT-CHECK-NEXT: fid: [[#]] +YAML-BAT-CHECK-NEXT: hash: 0x6AF7E61EA3966722 +YAML-BAT-CHECK-NEXT: exec: 25 +YAML-BAT-CHECK-NEXT: nblocks: 15 +YAML-BAT-CHECK-NEXT: blocks: +YAML-BAT-CHECK: - bid: 3 +YAML-BAT-CHECK-NEXT: insns: [[#]] +YAML-BAT-CHECK-NEXT: hash: 0xDDA1DC5F69F900AC +YAML-BAT-CHECK-NEXT: calls: [ { off: 0x26, fid: [[#]], cnt: [[#]] } ] +YAML-BAT-CHECK-NEXT: succ: [ { bid: 5, cnt: [[#]] } +# Function covered by BAT - doesn't have insns in basic block +YAML-BAT-CHECK: - name: usqrt +YAML-BAT-CHECK-NEXT: fid: [[#]] +YAML-BAT-CHECK-NEXT: hash: 0x99E67ED32A203023 +YAML-BAT-CHECK-NEXT: exec: 21 +YAML-BAT-CHECK-NEXT: nblocks: 5 +YAML-BAT-CHECK-NEXT: blocks: +YAML-BAT-CHECK: - bid: 1 +YAML-BAT-CHECK-NEXT: insns: [[#]] +YAML-BAT-CHECK-NEXT: hash: 0xD70DC695320E0010 +YAML-BAT-CHECK-NEXT: succ: {{.*}} { bid: 2, cnt: [[#]] } + +CHECK-BOLT-YAML: pre-processing profile using YAML profile reader +CHECK-BOLT-YAML-NEXT: 5 out of 16 functions in the binary (31.2%) have non-empty execution profile diff --git a/bolt/test/X86/bolt-address-translation.test b/bolt/test/X86/bolt-address-translation.test index f2020af2edebde99cabcda9e97d7ec687123292e..63234b4c1d21851f447fa804669e780774a6e9c8 100644 --- a/bolt/test/X86/bolt-address-translation.test +++ b/bolt/test/X86/bolt-address-translation.test @@ -36,7 +36,8 @@ # # CHECK: BOLT: 3 out of 7 functions were overwritten. # CHECK: BOLT-INFO: Wrote 6 BAT maps -# CHECK: BOLT-INFO: BAT section size (bytes): 336 +# CHECK: BOLT-INFO: Wrote 3 function and 58 basic block hashes +# CHECK: BOLT-INFO: BAT section size (bytes): 924 # # usqrt mappings (hot part). We match against any key (left side containing # the bolted binary offsets) because BOLT may change where it puts instructions @@ -44,13 +45,13 @@ # binary offsets (right side) should be the same because these addresses are # hardcoded in the blarge.yaml file. # -# CHECK-BAT-DUMP: Function Address: 0x401170 +# CHECK-BAT-DUMP: Function Address: 0x401170, hash: 0xace6cbc638b31983 # CHECK-BAT-DUMP-NEXT: BB mappings: -# CHECK-BAT-DUMP-NEXT: 0x0 -> 0x0 +# CHECK-BAT-DUMP-NEXT: 0x0 -> 0x0 hash: 0x36007ba1d80c0000 # CHECK-BAT-DUMP-NEXT: 0x8 -> 0x8 (branch) -# CHECK-BAT-DUMP-NEXT: 0x{{.*}} -> 0x39 +# CHECK-BAT-DUMP-NEXT: 0x{{.*}} -> 0x39 hash: 0x5c06705524800039 # CHECK-BAT-DUMP-NEXT: 0x{{.*}} -> 0x3d (branch) -# CHECK-BAT-DUMP-NEXT: 0x{{.*}} -> 0x10 +# CHECK-BAT-DUMP-NEXT: 0x{{.*}} -> 0x10 hash: 0xd70d7a64320e0010 # CHECK-BAT-DUMP-NEXT: 0x{{.*}} -> 0x30 (branch) # # CHECK-BAT-DUMP: 3 cold mappings diff --git a/bolt/test/X86/dwarf4-label-low-pc.s b/bolt/test/X86/dwarf4-label-low-pc.s new file mode 100644 index 0000000000000000000000000000000000000000..dfd5af18c09b75934fb6cac317d4d6807bcea5d4 --- /dev/null +++ b/bolt/test/X86/dwarf4-label-low-pc.s @@ -0,0 +1,263 @@ + +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %s -o %tmain.o +# RUN: %clang %cflags -dwarf-4 %tmain.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections +# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s +# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt > %t.txt +# RUN: llvm-objdump -d %t.bolt >> %t.txt +# RUN: cat %t.txt | FileCheck --check-prefix=POSTCHECK %s + +## This test checks that we correctly handle DW_AT_low_pc [DW_FORM_addr] that is part of DW_TAG_label. + +# PRECHECK: version = 0x0004 +# PRECHECK: DW_TAG_label +# PRECHECK-NEXT: DW_AT_name +# PRECHECK-NEXT: DW_AT_decl_file +# PRECHECK-NEXT: DW_AT_decl_line +# PRECHECK-NEXT:DW_AT_low_pc [DW_FORM_addr] +# PRECHECK: DW_TAG_label +# PRECHECK-NEXT: DW_AT_name +# PRECHECK-NEXT: DW_AT_decl_file +# PRECHECK-NEXT: DW_AT_decl_line +# PRECHECK-NEXT:DW_AT_low_pc [DW_FORM_addr] + +# POSTCHECK: version = 0x0004 +# POSTCHECK: DW_TAG_label +# POSTCHECK-NEXT: DW_AT_name +# POSTCHECK-NEXT: DW_AT_decl_file +# POSTCHECK-NEXT: DW_AT_decl_line +# POSTCHECK-NEXT:DW_AT_low_pc [DW_FORM_addr] (0x[[ADDR:[1-9a-f]*]] +# POSTCHECK: DW_TAG_label +# POSTCHECK-NEXT: DW_AT_name +# POSTCHECK-NEXT: DW_AT_decl_file +# POSTCHECK-NEXT: DW_AT_decl_line +# POSTCHECK-NEXT:DW_AT_low_pc [DW_FORM_addr] (0x[[ADDR2:[1-9a-f]*]] + +# POSTCHECK: [[ADDR]]: 8b 45 f8 +# POSTCHECK: [[ADDR2]]: 8b 45 f8 + +## clang++ main.cpp -g2 -gdwarf-4 -S +## int main() { +## int a = 4; +## if (a == 5) +## goto LABEL1; +## else +## goto LABEL2; +## LABEL1:a++; +## LABEL2:a--; +## return 0; +## } + + .text + .file "main.cpp" + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .file 1 "/home" "main.cpp" + .loc 1 1 0 # main.cpp:1:0 + .cfi_startproc +# %bb.0: # %entry + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + movl $0, -4(%rbp) +.Ltmp0: + .loc 1 2 7 prologue_end # main.cpp:2:7 + movl $4, -8(%rbp) +.Ltmp1: + .loc 1 3 9 # main.cpp:3:9 + cmpl $5, -8(%rbp) +.Ltmp2: + .loc 1 3 7 is_stmt 0 # main.cpp:3:7 + jne .LBB0_2 +# %bb.1: # %if.then +.Ltmp3: + .loc 1 4 5 is_stmt 1 # main.cpp:4:5 + jmp .LBB0_3 +.LBB0_2: # %if.else + .loc 1 6 5 # main.cpp:6:5 + jmp .LBB0_4 +.Ltmp4: +.LBB0_3: # %LABEL1 + #DEBUG_LABEL: main:LABEL1 + .loc 1 7 11 # main.cpp:7:11 + movl -8(%rbp), %eax + addl $1, %eax + movl %eax, -8(%rbp) +.LBB0_4: # %LABEL2 +.Ltmp5: + #DEBUG_LABEL: main:LABEL2 + .loc 1 8 11 # main.cpp:8:11 + movl -8(%rbp), %eax + addl $-1, %eax + movl %eax, -8(%rbp) + .loc 1 9 3 # main.cpp:9:3 + xorl %eax, %eax + .loc 1 9 3 epilogue_begin is_stmt 0 # main.cpp:9:3 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp6: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 10 # DW_TAG_label + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x6d DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 33 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 2 # Abbrev [2] 0x2a:0x46 DW_TAG_subprogram + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .long .Linfo_string3 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long 112 # DW_AT_type + # DW_AT_external + .byte 3 # Abbrev [3] 0x43:0xe DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 120 + .long .Linfo_string5 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 112 # DW_AT_type + .byte 4 # Abbrev [4] 0x51:0xf DW_TAG_label + .long .Linfo_string6 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .quad .Ltmp4 # DW_AT_low_pc + .byte 4 # Abbrev [4] 0x60:0xf DW_TAG_label + .long .Linfo_string7 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .quad .Ltmp5 # DW_AT_low_pc + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x70:0x7 DW_TAG_base_type + .long .Linfo_string4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 19.0.0git" # string offset=0 +.Linfo_string1: + .asciz "main.cpp" # string offset=24 +.Linfo_string2: + .asciz "/home" # string offset=33 +.Linfo_string3: + .asciz "main" # string offset=71 +.Linfo_string4: + .asciz "int" # string offset=76 +.Linfo_string5: + .asciz "a" # string offset=80 +.Linfo_string6: + .asciz "LABEL1" # string offset=82 +.Linfo_string7: + .asciz "LABEL2" # string offset=89 + .ident "clang version 19.0.0git" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/dwarf5-debug-names-cross-cu.s b/bolt/test/X86/dwarf5-debug-names-cross-cu.s new file mode 100644 index 0000000000000000000000000000000000000000..73c50d6d41db09cf2976d91c71da4ed8dcaea3cd --- /dev/null +++ b/bolt/test/X86/dwarf5-debug-names-cross-cu.s @@ -0,0 +1,712 @@ + +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %tmain.o +# RUN: %clang %cflags -dwarf-5 %tmain.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections +# RUN: llvm-dwarfdump --debug-info -r 0 --debug-names %t.bolt > %t.txt +# RUN: cat %t.txt | FileCheck --check-prefix=CHECK %s + +## This test checks that BOLT generates Entries for DW_AT_abstract_origin when it has cross cu reference. + +# CHECK: [[OFFSET1:0x[0-9a-f]*]]: Compile Unit +# CHECK: [[OFFSET2:0x[0-9a-f]*]]: Compile Unit +# CHECK: Name Index @ 0x0 { +# CHECK-NEXT: Header { +# CHECK-NEXT: Length: 0xD2 +# CHECK-NEXT: Format: DWARF32 +# CHECK-NEXT: Version: 5 +# CHECK-NEXT: CU count: 2 +# CHECK-NEXT: Local TU count: 0 +# CHECK-NEXT: Foreign TU count: 0 +# CHECK-NEXT: Bucket count: 5 +# CHECK-NEXT: Name count: 5 +# CHECK-NEXT: Abbreviations table size: 0x1F +# CHECK-NEXT: Augmentation: 'BOLT' +# CHECK-NEXT: } +# CHECK-NEXT: Compilation Unit offsets [ +# CHECK-NEXT: CU[0]: [[OFFSET1]] +# CHECK-NEXT: CU[1]: [[OFFSET2]] +# CHECK-NEXT: ] +# CHECK-NEXT: Abbreviations [ +# CHECK-NEXT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] { +# CHECK-NEXT: Tag: DW_TAG_subprogram +# CHECK-NEXT: DW_IDX_compile_unit: DW_FORM_data1 +# CHECK-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +# CHECK-NEXT: DW_IDX_parent: DW_FORM_flag_present +# CHECK-NEXT: } +# CHECK-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] { +# CHECK-NEXT: Tag: DW_TAG_inlined_subroutine +# CHECK-NEXT: DW_IDX_compile_unit: DW_FORM_data1 +# CHECK-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +# CHECK-NEXT: DW_IDX_parent: DW_FORM_ref4 +# CHECK-NEXT: } +# CHECK-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] { +# CHECK-NEXT: Tag: DW_TAG_base_type +# CHECK-NEXT: DW_IDX_compile_unit: DW_FORM_data1 +# CHECK-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +# CHECK-NEXT: DW_IDX_parent: DW_FORM_flag_present +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: Bucket 0 [ +# CHECK-NEXT: EMPTY +# CHECK-NEXT: ] +# CHECK-NEXT: Bucket 1 [ +# CHECK-NEXT: Name 1 { +# CHECK-NEXT: Hash: 0x7C9A7F6A +# CHECK-NEXT: String: {{.+}} "main" +# CHECK-NEXT: Entry @ [[ENTRY:0x[0-9a-f]*]] { +# CHECK-NEXT: Abbrev: [[ABBREV1]] +# CHECK-NEXT: Tag: DW_TAG_subprogram +# CHECK-NEXT: DW_IDX_compile_unit: 0x00 +# CHECK-NEXT: DW_IDX_die_offset: 0x00000024 +# CHECK-NEXT: DW_IDX_parent: +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: Name 2 { +# CHECK-NEXT: Hash: 0xB5063CFE +# CHECK-NEXT: String: {{.+}} "_Z3fooi" +# CHECK-NEXT: Entry @ {{.+}} { +# CHECK-NEXT: Abbrev: [[ABBREV1]] +# CHECK-NEXT: Tag: DW_TAG_subprogram +# CHECK-NEXT: DW_IDX_compile_unit: 0x01 +# CHECK-NEXT: DW_IDX_die_offset: 0x0000003a +# CHECK-NEXT: DW_IDX_parent: +# CHECK-NEXT: } +# CHECK-NEXT: Entry @ {{.+}} { +# CHECK-NEXT: Abbrev: [[ABBREV2]] +# CHECK-NEXT: Tag: DW_TAG_inlined_subroutine +# CHECK-NEXT: DW_IDX_compile_unit: 0x00 +# CHECK-NEXT: DW_IDX_die_offset: 0x00000054 +# CHECK-NEXT: DW_IDX_parent: Entry @ [[ENTRY]] +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: Bucket 2 [ +# CHECK-NEXT: EMPTY +# CHECK-NEXT: ] +# CHECK-NEXT: Bucket 3 [ +# CHECK-NEXT: Name 3 { +# CHECK-NEXT: Hash: 0xB888030 +# CHECK-NEXT: String: {{.+}} "int" +# CHECK-NEXT: Entry @ {{.+}} { +# CHECK-NEXT: Abbrev: [[ABBREV3]] +# CHECK-NEXT: Tag: DW_TAG_base_type +# CHECK-NEXT: DW_IDX_compile_unit: 0x01 +# CHECK-NEXT: DW_IDX_die_offset: 0x00000036 +# CHECK-NEXT: DW_IDX_parent: +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: Bucket 4 [ +# CHECK-NEXT: Name 4 { +# CHECK-NEXT: Hash: 0xB887389 +# CHECK-NEXT: String: {{.+}} "foo" +# CHECK-NEXT: Entry @ {{.+}} { +# CHECK-NEXT: Abbrev: [[ABBREV1]] +# CHECK-NEXT: Tag: DW_TAG_subprogram +# CHECK-NEXT: DW_IDX_compile_unit: 0x01 +# CHECK-NEXT: DW_IDX_die_offset: 0x0000003a +# CHECK-NEXT: DW_IDX_parent: +# CHECK-NEXT: } +# CHECK-NEXT: Entry @ 0xc4 { +# CHECK-NEXT: Abbrev: [[ABBREV2]] +# CHECK-NEXT: Tag: DW_TAG_inlined_subroutine +# CHECK-NEXT: DW_IDX_compile_unit: 0x00 +# CHECK-NEXT: DW_IDX_die_offset: 0x00000054 +# CHECK-NEXT: DW_IDX_parent: Entry @ [[ENTRY]] +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: Name 5 { +# CHECK-NEXT: Hash: 0x7C952063 +# CHECK-NEXT: String: {{.+}} "char" +# CHECK-NEXT: Entry @ {{.+}} { +# CHECK-NEXT: Abbrev: [[ABBREV3]] +# CHECK-NEXT: Tag: DW_TAG_base_type +# CHECK-NEXT: DW_IDX_compile_unit: 0x00 +# CHECK-NEXT: DW_IDX_die_offset: 0x00000075 +# CHECK-NEXT: DW_IDX_parent: +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK-NEXT: } + +## clang++ -g2 -gpubnames -S -emit-llvm main.cpp -o main.ll +## clang++ -g2 -gpubnames -S -emit-llvm helper.cpp -o helper.ll +## llvm-link main.ll helper.ll -o combined.ll +## clang++ -g2 -gpubnames combined.ll -emit-llvm -S -o combined.opt.ll +## llc -dwarf-version=5 -filetype=asm -mtriple x86_64-unknown-linux combined.opt.ll -o combined.s +## main.cpp +## extern int foo(int); +## int main(int argc, char* argv[]) { +## int i = 0; +## [[clang::always_inline]] i = foo(argc); +## return i; +## } +## helper.cpp +## int foo(int i) { +## return i ++; +## } + + .text + .file "llvm-link" + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .file 1 "/home" "main.cpp" md5 0x24fb0b4c3900e91fece1ac87ed73ff3b + .loc 1 2 0 # main.cpp:2:0 + .cfi_startproc +# %bb.0: # %entry + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + movl $0, -16(%rbp) + movl %edi, -12(%rbp) + movq %rsi, -24(%rbp) +.Ltmp0: + .loc 1 3 7 prologue_end # main.cpp:3:7 + movl $0, -4(%rbp) + .loc 1 4 36 # main.cpp:4:36 + movl -12(%rbp), %eax + movl %eax, -8(%rbp) +.Ltmp1: + .file 2 "/home" "helper.cpp" md5 0x7d4429e24d8c74d7ee22c1889ad46d6b + .loc 2 2 12 # helper.cpp:2:12 + movl -8(%rbp), %eax + movl %eax, %ecx + addl $1, %ecx + movl %ecx, -8(%rbp) +.Ltmp2: + .loc 1 4 30 # main.cpp:4:30 + movl %eax, -4(%rbp) + .loc 1 5 10 # main.cpp:5:10 + movl -4(%rbp), %eax + .loc 1 5 3 epilogue_begin is_stmt 0 # main.cpp:5:3 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp3: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .globl _Z3fooi # -- Begin function _Z3fooi + .p2align 4, 0x90 + .type _Z3fooi,@function +_Z3fooi: # @_Z3fooi +.Lfunc_begin1: + .loc 2 1 0 is_stmt 1 # helper.cpp:1:0 + .cfi_startproc +# %bb.0: # %entry + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + movl %edi, -4(%rbp) +.Ltmp4: + .loc 2 2 12 prologue_end # helper.cpp:2:12 + movl -4(%rbp), %eax + movl %eax, %ecx + addl $1, %ecx + movl %ecx, -4(%rbp) + .loc 2 2 3 epilogue_begin is_stmt 0 # helper.cpp:2:3 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp5: +.Lfunc_end1: + .size _Z3fooi, .Lfunc_end1-_Z3fooi + .cfi_endproc + # -- End function + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 16 # DW_FORM_ref_addr + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 16 # DW_FORM_ref_addr + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 16 # DW_FORM_ref_addr + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 29 # DW_TAG_inlined_subroutine + .byte 1 # DW_CHILDREN_yes + .byte 49 # DW_AT_abstract_origin + .byte 16 # DW_FORM_ref_addr + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 88 # DW_AT_call_file + .byte 11 # DW_FORM_data1 + .byte 89 # DW_AT_call_line + .byte 11 # DW_FORM_data1 + .byte 87 # DW_AT_call_column + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 49 # DW_AT_abstract_origin + .byte 16 # DW_FORM_ref_addr + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 10 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 110 # DW_AT_linkage_name + .byte 37 # DW_FORM_strx1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 32 # DW_AT_inline + .byte 33 # DW_FORM_implicit_const + .byte 1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 11 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 12 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 49 # DW_AT_abstract_origin + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 13 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 49 # DW_AT_abstract_origin + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] 0xc:0x6d DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 2 # Abbrev [2] 0x23:0x47 DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .byte 8 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long .debug_info+174 # DW_AT_type + # DW_AT_external + .byte 3 # Abbrev [3] 0x32:0xb DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 116 + .byte 9 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long .debug_info+174 # DW_AT_type + .byte 4 # Abbrev [4] 0x3d:0xb DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 104 + .byte 10 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .long 106 # DW_AT_type + .byte 5 # Abbrev [5] 0x48:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 124 + .byte 7 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .long .debug_info+174 # DW_AT_type + .byte 6 # Abbrev [6] 0x53:0x16 DW_TAG_inlined_subroutine + .long .debug_info+156 # DW_AT_abstract_origin + .byte 1 # DW_AT_low_pc + .long .Ltmp2-.Ltmp1 # DW_AT_high_pc + .byte 1 # DW_AT_call_file + .byte 4 # DW_AT_call_line + .byte 32 # DW_AT_call_column + .byte 7 # Abbrev [7] 0x60:0x8 DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 120 + .long .debug_info+165 # DW_AT_abstract_origin + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark + .byte 8 # Abbrev [8] 0x6a:0x5 DW_TAG_pointer_type + .long 111 # DW_AT_type + .byte 8 # Abbrev [8] 0x6f:0x5 DW_TAG_pointer_type + .long 116 # DW_AT_type + .byte 9 # Abbrev [9] 0x74:0x4 DW_TAG_base_type + .byte 11 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: +.Lcu_begin1: + .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit +.Ldebug_info_start1: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] 0xc:0x43 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 3 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 2 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 10 # Abbrev [10] 0x23:0x12 DW_TAG_subprogram + .byte 4 # DW_AT_linkage_name + .byte 5 # DW_AT_name + .byte 2 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long 53 # DW_AT_type + # DW_AT_external + # DW_AT_inline + .byte 11 # Abbrev [11] 0x2c:0x8 DW_TAG_formal_parameter + .byte 7 # DW_AT_name + .byte 2 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long 53 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 9 # Abbrev [9] 0x35:0x4 DW_TAG_base_type + .byte 6 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 12 # Abbrev [12] 0x39:0x15 DW_TAG_subprogram + .byte 2 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .long 35 # DW_AT_abstract_origin + .byte 13 # Abbrev [13] 0x45:0x8 DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 124 + .long 44 # DW_AT_abstract_origin + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark +.Ldebug_info_end1: + .section .debug_str_offsets,"",@progbits + .long 52 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 19.0.0git" # string offset=0 +.Linfo_string1: + .asciz "main.cpp" # string offset=24 +.Linfo_string2: + .asciz "/home/ayermolo/local/tasks/T182867349" # string offset=33 +.Linfo_string3: + .asciz "helper.cpp" # string offset=71 +.Linfo_string4: + .asciz "_Z3fooi" # string offset=82 +.Linfo_string5: + .asciz "foo" # string offset=90 +.Linfo_string6: + .asciz "int" # string offset=94 +.Linfo_string7: + .asciz "i" # string offset=98 +.Linfo_string8: + .asciz "main" # string offset=100 +.Linfo_string9: + .asciz "argc" # string offset=105 +.Linfo_string10: + .asciz "argv" # string offset=110 +.Linfo_string11: + .asciz "char" # string offset=115 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string8 + .long .Linfo_string9 + .long .Linfo_string10 + .long .Linfo_string11 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad .Lfunc_begin0 + .quad .Ltmp1 + .quad .Lfunc_begin1 +.Ldebug_addr_end0: + .section .debug_names,"",@progbits + .long .Lnames_end0-.Lnames_start0 # Header: unit length +.Lnames_start0: + .short 5 # Header: version + .short 0 # Header: padding + .long 2 # Header: compilation unit count + .long 0 # Header: local type unit count + .long 0 # Header: foreign type unit count + .long 5 # Header: bucket count + .long 5 # Header: name count + .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size + .long 8 # Header: augmentation string size + .ascii "LLVM0700" # Header: augmentation string + .long .Lcu_begin0 # Compilation unit 0 + .long .Lcu_begin1 # Compilation unit 1 + .long 0 # Bucket 0 + .long 1 # Bucket 1 + .long 0 # Bucket 2 + .long 3 # Bucket 3 + .long 4 # Bucket 4 + .long 2090499946 # Hash in Bucket 1 + .long -1257882370 # Hash in Bucket 1 + .long 193495088 # Hash in Bucket 3 + .long 193491849 # Hash in Bucket 4 + .long 2090147939 # Hash in Bucket 4 + .long .Linfo_string8 # String in Bucket 1: main + .long .Linfo_string4 # String in Bucket 1: _Z3fooi + .long .Linfo_string6 # String in Bucket 3: int + .long .Linfo_string5 # String in Bucket 4: foo + .long .Linfo_string11 # String in Bucket 4: char + .long .Lnames1-.Lnames_entries0 # Offset in Bucket 1 + .long .Lnames3-.Lnames_entries0 # Offset in Bucket 1 + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 3 + .long .Lnames2-.Lnames_entries0 # Offset in Bucket 4 + .long .Lnames4-.Lnames_entries0 # Offset in Bucket 4 +.Lnames_abbrev_start0: + .byte 1 # Abbrev code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_IDX_compile_unit + .byte 11 # DW_FORM_data1 + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 2 # Abbrev code + .byte 29 # DW_TAG_inlined_subroutine + .byte 1 # DW_IDX_compile_unit + .byte 11 # DW_FORM_data1 + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 19 # DW_FORM_ref4 + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 3 # Abbrev code + .byte 36 # DW_TAG_base_type + .byte 1 # DW_IDX_compile_unit + .byte 11 # DW_FORM_data1 + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 0 # End of abbrev list +.Lnames_abbrev_end0: +.Lnames_entries0: +.Lnames1: +.L3: + .byte 1 # Abbreviation code + .byte 0 # DW_IDX_compile_unit + .long 35 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: main +.Lnames3: +.L0: + .byte 1 # Abbreviation code + .byte 1 # DW_IDX_compile_unit + .long 57 # DW_IDX_die_offset +.L2: # DW_IDX_parent + .byte 2 # Abbreviation code + .byte 0 # DW_IDX_compile_unit + .long 83 # DW_IDX_die_offset + .long .L3-.Lnames_entries0 # DW_IDX_parent + .byte 0 # End of list: _Z3fooi +.Lnames0: +.L4: + .byte 3 # Abbreviation code + .byte 1 # DW_IDX_compile_unit + .long 53 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: int +.Lnames2: + .byte 1 # Abbreviation code + .byte 1 # DW_IDX_compile_unit + .long 57 # DW_IDX_die_offset + .byte 2 # DW_IDX_parent + # Abbreviation code + .byte 0 # DW_IDX_compile_unit + .long 83 # DW_IDX_die_offset + .long .L3-.Lnames_entries0 # DW_IDX_parent + .byte 0 # End of list: foo +.Lnames4: +.L1: + .byte 3 # Abbreviation code + .byte 0 # DW_IDX_compile_unit + .long 116 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: char + .p2align 2, 0x0 +.Lnames_end0: + .ident "clang version 19.0.0git" + .ident "clang version 19.0.0git" + .section ".note.GNU-stack","",@progbits + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/dwarf5-debug-names-dw-at-specification.s b/bolt/test/X86/dwarf5-debug-names-dw-at-specification.s new file mode 100644 index 0000000000000000000000000000000000000000..ec5b425625ce9647d10a52b77e333c6bcf5d574d --- /dev/null +++ b/bolt/test/X86/dwarf5-debug-names-dw-at-specification.s @@ -0,0 +1,694 @@ +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %tmain.o +# RUN: %clang %cflags -gdwarf-5 %tmain.o -o %tmain.exe +# RUN: llvm-bolt %tmain.exe -o %tmain.exe.bolt --update-debug-sections +# RUN: llvm-dwarfdump --debug-info -r 0 --debug-names %tmain.exe.bolt > %tlog.txt +# RUN: cat %tlog.txt | FileCheck -check-prefix=BOLT %s + +## Tests that BOLT correctly generates entries in .debug_names with DW_AT_specification. + +# BOLT: [[OFFSET1:0x[0-9a-f]*]]: Compile Unit +# BOLT: Name Index @ 0x0 +# BOLT-NEXT: Header { +# BOLT-NEXT: Length: 0x10F +# BOLT-NEXT: Format: DWARF32 +# BOLT-NEXT: Version: 5 +# BOLT-NEXT: CU count: 1 +# BOLT-NEXT: Local TU count: 0 +# BOLT-NEXT: Foreign TU count: 0 +# BOLT-NEXT: Bucket count: 9 +# BOLT-NEXT: Name count: 9 +# BOLT-NEXT: Abbreviations table size: 0x21 +# BOLT-NEXT: Augmentation: 'BOLT' +# BOLT-NEXT: } +# BOLT-NEXT: Compilation Unit offsets [ +# BOLT-NEXT: CU[0]: [[OFFSET1]] +# BOLT-NEXT: ] +# BOLT-NEXT: Abbreviations [ +# BOLT-NEXT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] { +# BOLT-NEXT: Tag: DW_TAG_variable +# BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +# BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present +# BOLT-NEXT: } +# BOLT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] { +# BOLT-NEXT: Tag: DW_TAG_structure_type +# BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +# BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present +# BOLT-NEXT: } +# BOLT-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] { +# BOLT-NEXT: Tag: DW_TAG_base_type +# BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +# BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present +# BOLT-NEXT: } +# BOLT-NEXT: Abbreviation [[ABBREV4:0x[0-9a-f]*]] { +# BOLT-NEXT: Tag: DW_TAG_subprogram +# BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +# BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present +# BOLT-NEXT: } +# BOLT-NEXT: ] +# BOLT-NEXT: Bucket 0 [ +# BOLT-NEXT: Name 1 { +# BOLT-NEXT: Hash: 0x5D3CA9E0 +# BOLT-NEXT: String: {{.+}} "_ZN1A15fully_specifiedE" +# BOLT-NEXT: Entry @ {{.+}} { +# BOLT-NEXT: Abbrev: [[ABBREV1]] +# BOLT-NEXT: Tag: DW_TAG_variable +# BOLT-NEXT: DW_IDX_die_offset: 0x00000024 +# BOLT-NEXT: DW_IDX_parent: +# BOLT-NEXT: } +# BOLT-NEXT: } +# BOLT-NEXT: Name 2 { +# BOLT-NEXT: Hash: 0x7C9DFC37 +# BOLT-NEXT: String: {{.+}} "smem" +# BOLT-NEXT: Entry @ {{.+}} { +# BOLT-NEXT: Abbrev: [[ABBREV1]] +# BOLT-NEXT: Tag: DW_TAG_variable +# BOLT-NEXT: DW_IDX_die_offset: 0x00000057 +# BOLT-NEXT: DW_IDX_parent: +# BOLT-NEXT: } +# BOLT-NEXT: } +# BOLT-NEXT: ] +# BOLT-NEXT: Bucket 1 [ +# BOLT-NEXT: Name 3 { +# BOLT-NEXT: Hash: 0x2B606 +# BOLT-NEXT: String: {{.+}} "A" +# BOLT-NEXT: Entry @ {{.+}} { +# BOLT-NEXT: Abbrev: [[ABBREV2]] +# BOLT-NEXT: Tag: DW_TAG_structure_type +# BOLT-NEXT: DW_IDX_die_offset: 0x0000002d +# BOLT-NEXT: DW_IDX_parent: +# BOLT-NEXT: } +# BOLT-NEXT: } +# BOLT-NEXT: ] +# BOLT-NEXT: Bucket 2 [ +# BOLT-NEXT: Name 4 { +# BOLT-NEXT: Hash: 0xB888030 +# BOLT-NEXT: String: {{.+}} "int" +# BOLT-NEXT: Entry @ {{.+}} { +# BOLT-NEXT: Abbrev: [[ABBREV3]] +# BOLT-NEXT: Tag: DW_TAG_base_type +# BOLT-NEXT: DW_IDX_die_offset: 0x00000044 +# BOLT-NEXT: DW_IDX_parent: +# BOLT-NEXT: } +# BOLT-NEXT: } +# BOLT-NEXT: ] +# BOLT-NEXT: Bucket 3 [ +# BOLT-NEXT: EMPTY +# BOLT-NEXT: ] +# BOLT-NEXT: Bucket 4 [ +# BOLT-NEXT: EMPTY +# BOLT-NEXT: ] +# BOLT-NEXT: Bucket 5 [ +# BOLT-NEXT: EMPTY +# BOLT-NEXT: ] +# BOLT-NEXT: Bucket 6 [ +# BOLT-NEXT: EMPTY +# BOLT-NEXT: ] +# BOLT-NEXT: Bucket 7 [ +# BOLT-NEXT: Name 5 { +# BOLT-NEXT: Hash: 0x65788E1C +# BOLT-NEXT: String: {{.+}} "fully_specified" +# BOLT-NEXT: Entry @ {{.+}} { +# BOLT-NEXT: Abbrev: [[ABBREV1]] +# BOLT-NEXT: Tag: DW_TAG_variable +# BOLT-NEXT: DW_IDX_die_offset: 0x00000024 +# BOLT-NEXT: DW_IDX_parent: +# BOLT-NEXT: } +# BOLT-NEXT: } +# BOLT-NEXT: Name 6 { +# BOLT-NEXT: Hash: 0x7C9A7F6A +# BOLT-NEXT: String: {{.+}} "main" +# BOLT-NEXT: Entry @ {{.+}} { +# BOLT-NEXT: Abbrev: [[ABBREV4]] +# BOLT-NEXT: Tag: DW_TAG_subprogram +# BOLT-NEXT: DW_IDX_die_offset: 0x00000070 +# BOLT-NEXT: DW_IDX_parent: +# BOLT-NEXT: } +# BOLT-NEXT: } +# BOLT-NEXT: ] +# BOLT-NEXT: Bucket 8 [ +# BOLT-NEXT: Name 7 { +# BOLT-NEXT: Hash: 0xCEF4CFB +# BOLT-NEXT: String: {{.+}} "__ARRAY_SIZE_TYPE__" +# BOLT-NEXT: Entry @ {{.+}} { +# BOLT-NEXT: Abbrev: [[ABBREV3]] +# BOLT-NEXT: Tag: DW_TAG_base_type +# BOLT-NEXT: DW_IDX_die_offset: 0x00000053 +# BOLT-NEXT: DW_IDX_parent: +# BOLT-NEXT: } +# BOLT-NEXT: } +# BOLT-NEXT: Name 8 { +# BOLT-NEXT: Hash: 0x48684B69 +# BOLT-NEXT: String: {{.+}} "_ZN1A4smemE" +# BOLT-NEXT: Entry @ {{.+}} { +# BOLT-NEXT: Abbrev: [[ABBREV1]] +# BOLT-NEXT: Tag: DW_TAG_variable +# BOLT-NEXT: DW_IDX_die_offset: 0x00000057 +# BOLT-NEXT: DW_IDX_parent: +# BOLT-NEXT: } +# BOLT-NEXT: } +# BOLT-NEXT: Name 9 { +# BOLT-NEXT: Hash: 0x7C952063 +# BOLT-NEXT: String: {{.+}} "char" +# BOLT-NEXT: Entry @ {{.+}} { +# BOLT-NEXT: Abbrev: [[ABBREV3]] +# BOLT-NEXT: Tag: DW_TAG_base_type +# BOLT-NEXT: DW_IDX_die_offset: 0x0000009e +# BOLT-NEXT: DW_IDX_parent: +# BOLT-NEXT: } +# BOLT-NEXT: } +# BOLT-NEXT: ] +# BOLT-NEXT: } + +# clang++ main.cpp -O2 -g2 -gdwarf-5 -gpubnames -S +# struct A { +# static int fully_specified; +# static int smem[]; +# }; +# +# int A::fully_specified; +# int A::smem[] = { 0, 1, 2, 3 }; +# int main(int argc, char *argv[]) { +# return 0; +# } + .text + .file "main.cpp" + .file 0 "/specification" "main.cpp" md5 0x6c1b1c014d300f2e0efd26584acae1a9 + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: main:argc <- $edi + #DEBUG_VALUE: main:argv <- $rsi + .loc 0 9 3 prologue_end # main.cpp:9:3 + xorl %eax, %eax + retq +.Ltmp0: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .type _ZN1A15fully_specifiedE,@object # @_ZN1A15fully_specifiedE + .bss + .globl _ZN1A15fully_specifiedE + .p2align 2, 0x0 +_ZN1A15fully_specifiedE: + .long 0 # 0x0 + .size _ZN1A15fully_specifiedE, 4 + + .type _ZN1A4smemE,@object # @_ZN1A4smemE + .data + .globl _ZN1A4smemE + .p2align 4, 0x0 +_ZN1A4smemE: + .long 0 # 0x0 + .long 1 # 0x1 + .long 2 # 0x2 + .long 3 # 0x3 + .size _ZN1A4smemE, 16 + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 71 # DW_AT_specification + .byte 19 # DW_FORM_ref4 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 110 # DW_AT_linkage_name + .byte 37 # DW_FORM_strx1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 1 # DW_TAG_array_type + .byte 1 # DW_CHILDREN_yes + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 33 # DW_TAG_subrange_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 71 # DW_AT_specification + .byte 19 # DW_FORM_ref4 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 110 # DW_AT_linkage_name + .byte 37 # DW_FORM_strx1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 10 # Abbreviation Code + .byte 33 # DW_TAG_subrange_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 55 # DW_AT_count + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 11 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 12 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 13 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] 0xc:0x96 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 2 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 2 # Abbrev [2] 0x23:0x9 DW_TAG_variable + .long 50 # DW_AT_specification + .byte 2 # DW_AT_location + .byte 161 + .byte 0 + .byte 8 # DW_AT_linkage_name + .byte 3 # Abbrev [3] 0x2c:0x17 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 7 # DW_AT_name + .byte 1 # DW_AT_byte_size + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 4 # Abbrev [4] 0x32:0x8 DW_TAG_variable + .byte 3 # DW_AT_name + .long 67 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + # DW_AT_external + # DW_AT_declaration + .byte 4 # Abbrev [4] 0x3a:0x8 DW_TAG_variable + .byte 5 # DW_AT_name + .long 71 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + # DW_AT_external + # DW_AT_declaration + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x43:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 6 # Abbrev [6] 0x47:0xb DW_TAG_array_type + .long 67 # DW_AT_type + .byte 7 # Abbrev [7] 0x4c:0x5 DW_TAG_subrange_type + .long 82 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 8 # Abbrev [8] 0x52:0x4 DW_TAG_base_type + .byte 6 # DW_AT_name + .byte 8 # DW_AT_byte_size + .byte 7 # DW_AT_encoding + .byte 9 # Abbrev [9] 0x56:0xd DW_TAG_variable + .long 58 # DW_AT_specification + .long 99 # DW_AT_type + .byte 2 # DW_AT_location + .byte 161 + .byte 1 + .byte 9 # DW_AT_linkage_name + .byte 6 # Abbrev [6] 0x63:0xc DW_TAG_array_type + .long 67 # DW_AT_type + .byte 10 # Abbrev [10] 0x68:0x6 DW_TAG_subrange_type + .long 82 # DW_AT_type + .byte 4 # DW_AT_count + .byte 0 # End Of Children Mark + .byte 11 # Abbrev [11] 0x6f:0x24 DW_TAG_subprogram + .byte 2 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_call_all_calls + .byte 10 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .long 67 # DW_AT_type + # DW_AT_external + .byte 12 # Abbrev [12] 0x7e:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 85 + .byte 11 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .long 67 # DW_AT_type + .byte 12 # Abbrev [12] 0x88:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 84 + .byte 12 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .long 147 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 13 # Abbrev [13] 0x93:0x5 DW_TAG_pointer_type + .long 152 # DW_AT_type + .byte 13 # Abbrev [13] 0x98:0x5 DW_TAG_pointer_type + .long 157 # DW_AT_type + .byte 5 # Abbrev [5] 0x9d:0x4 DW_TAG_base_type + .byte 13 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 60 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)" # string offset=0 +.Linfo_string1: + .asciz "main.cpp" # string offset=104 +.Linfo_string2: + .asciz "/specification" # string offset=113 +.Linfo_string3: + .asciz "A" # string offset=165 +.Linfo_string4: + .asciz "fully_specified" # string offset=167 +.Linfo_string5: + .asciz "int" # string offset=183 +.Linfo_string6: + .asciz "smem" # string offset=187 +.Linfo_string7: + .asciz "__ARRAY_SIZE_TYPE__" # string offset=192 +.Linfo_string8: + .asciz "_ZN1A15fully_specifiedE" # string offset=212 +.Linfo_string9: + .asciz "_ZN1A4smemE" # string offset=236 +.Linfo_string10: + .asciz "main" # string offset=248 +.Linfo_string11: + .asciz "argc" # string offset=253 +.Linfo_string12: + .asciz "argv" # string offset=258 +.Linfo_string13: + .asciz "char" # string offset=263 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string3 + .long .Linfo_string8 + .long .Linfo_string9 + .long .Linfo_string10 + .long .Linfo_string11 + .long .Linfo_string12 + .long .Linfo_string13 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad _ZN1A15fully_specifiedE + .quad _ZN1A4smemE + .quad .Lfunc_begin0 +.Ldebug_addr_end0: + .section .debug_names,"",@progbits + .long .Lnames_end0-.Lnames_start0 # Header: unit length +.Lnames_start0: + .short 5 # Header: version + .short 0 # Header: padding + .long 1 # Header: compilation unit count + .long 0 # Header: local type unit count + .long 0 # Header: foreign type unit count + .long 9 # Header: bucket count + .long 9 # Header: name count + .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size + .long 8 # Header: augmentation string size + .ascii "LLVM0700" # Header: augmentation string + .long .Lcu_begin0 # Compilation unit 0 + .long 1 # Bucket 0 + .long 3 # Bucket 1 + .long 4 # Bucket 2 + .long 0 # Bucket 3 + .long 0 # Bucket 4 + .long 0 # Bucket 5 + .long 0 # Bucket 6 + .long 5 # Bucket 7 + .long 7 # Bucket 8 + .long 1564256736 # Hash in Bucket 0 + .long 2090728503 # Hash in Bucket 0 + .long 177670 # Hash in Bucket 1 + .long 193495088 # Hash in Bucket 2 + .long 1702399516 # Hash in Bucket 7 + .long 2090499946 # Hash in Bucket 7 + .long 217009403 # Hash in Bucket 8 + .long 1214794601 # Hash in Bucket 8 + .long 2090147939 # Hash in Bucket 8 + .long .Linfo_string8 # String in Bucket 0: _ZN1A15fully_specifiedE + .long .Linfo_string6 # String in Bucket 0: smem + .long .Linfo_string3 # String in Bucket 1: A + .long .Linfo_string5 # String in Bucket 2: int + .long .Linfo_string4 # String in Bucket 7: fully_specified + .long .Linfo_string10 # String in Bucket 7: main + .long .Linfo_string7 # String in Bucket 8: __ARRAY_SIZE_TYPE__ + .long .Linfo_string9 # String in Bucket 8: _ZN1A4smemE + .long .Linfo_string13 # String in Bucket 8: char + .long .Lnames4-.Lnames_entries0 # Offset in Bucket 0 + .long .Lnames5-.Lnames_entries0 # Offset in Bucket 0 + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 1 + .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2 + .long .Lnames3-.Lnames_entries0 # Offset in Bucket 7 + .long .Lnames7-.Lnames_entries0 # Offset in Bucket 7 + .long .Lnames2-.Lnames_entries0 # Offset in Bucket 8 + .long .Lnames6-.Lnames_entries0 # Offset in Bucket 8 + .long .Lnames8-.Lnames_entries0 # Offset in Bucket 8 +.Lnames_abbrev_start0: + .byte 1 # Abbrev code + .byte 52 # DW_TAG_variable + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 2 # Abbrev code + .byte 19 # DW_TAG_structure_type + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 3 # Abbrev code + .byte 36 # DW_TAG_base_type + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 4 # Abbrev code + .byte 46 # DW_TAG_subprogram + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 0 # End of abbrev list +.Lnames_abbrev_end0: +.Lnames_entries0: +.Lnames4: +.L3: + .byte 1 # Abbreviation code + .long 35 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: _ZN1A15fully_specifiedE +.Lnames5: +.L4: + .byte 1 # Abbreviation code + .long 86 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: smem +.Lnames0: +.L6: + .byte 2 # Abbreviation code + .long 44 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: A +.Lnames1: +.L5: + .byte 3 # Abbreviation code + .long 67 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: int +.Lnames3: + .byte 1 # Abbreviation code + .long 35 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: fully_specified +.Lnames7: +.L0: + .byte 4 # Abbreviation code + .long 111 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: main +.Lnames2: +.L2: + .byte 3 # Abbreviation code + .long 82 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: __ARRAY_SIZE_TYPE__ +.Lnames6: + .byte 1 # Abbreviation code + .long 86 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: _ZN1A4smemE +.Lnames8: +.L1: + .byte 3 # Abbreviation code + .long 157 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: char + .p2align 2, 0x0 +.Lnames_end0: + .ident "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/dwarf5-debug-names-generate-debug-names.test b/bolt/test/X86/dwarf5-debug-names-generate-debug-names.test index b8789a6ad2300a21c35a16fb65a36979ab3d82d9..b7d8fda63315fa6ff8f31d9b2b3e1faed6a49de5 100644 --- a/bolt/test/X86/dwarf5-debug-names-generate-debug-names.test +++ b/bolt/test/X86/dwarf5-debug-names-generate-debug-names.test @@ -14,15 +14,15 @@ ; BOLT: [[OFFSET2:0x[0-9a-f]*]]: Compile Unit ; BOLT: Name Index @ 0x0 { ; BOLT-NEXT: Header { -; BOLT-NEXT: Length: 0x103 +; BOLT-NEXT: Length: 0x155 ; BOLT-NEXT: Format: DWARF32 ; BOLT-NEXT: Version: 5 ; BOLT-NEXT: CU count: 2 ; BOLT-NEXT: Local TU count: 0 ; BOLT-NEXT: Foreign TU count: 0 -; BOLT-NEXT: Bucket count: 8 -; BOLT-NEXT: Name count: 8 -; BOLT-NEXT: Abbreviations table size: 0x19 +; BOLT-NEXT: Bucket count: 10 +; BOLT-NEXT: Name count: 10 +; BOLT-NEXT: Abbreviations table size: 0x29 ; BOLT-NEXT: Augmentation: 'BOLT' ; BOLT-NEXT: } ; BOLT-NEXT: Compilation Unit offsets [ @@ -31,124 +31,183 @@ ; BOLT-NEXT: ] ; BOLT-NEXT: Abbreviations [ ; BOLT-NEXT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] { -; BOLT-NEXT: Tag: DW_TAG_base_type +; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] { -; BOLT-NEXT: Tag: DW_TAG_subprogram -; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 -; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: Tag: DW_TAG_inlined_subroutine +; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 +; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_ref4 ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_variable ; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present +; BOLT-NEXT: } +; BOLT-NEXT: Abbreviation [[ABBREV4:0x[0-9a-f]*]] { +; BOLT-NEXT: Tag: DW_TAG_base_type +; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 +; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: ] ; BOLT-NEXT: Bucket 0 [ -; BOLT-NEXT: Name 1 { -; BOLT-NEXT: Hash: 0xB888030 -; BOLT-NEXT: String: {{.+}} "int" -; BOLT-NEXT: Entry @ {{.+}} { -; BOLT-NEXT: Abbrev: [[ABBREV1]] -; BOLT-NEXT: Tag: DW_TAG_base_type -; BOLT-NEXT: DW_IDX_compile_unit: 0x01 -; BOLT-NEXT: DW_IDX_die_offset: 0x00000033 +; BOLT-NEXT: Name 1 { +; BOLT-NEXT: Hash: 0x2124BB36 +; BOLT-NEXT: String: {{.+}} "useFoo" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV1]] +; BOLT-NEXT: Tag: DW_TAG_subprogram +; BOLT-NEXT: DW_IDX_compile_unit: 0x01 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000037 +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV2]] +; BOLT-NEXT: Tag: DW_TAG_inlined_subroutine +; BOLT-NEXT: DW_IDX_compile_unit: 0x01 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000081 +; BOLT-NEXT: DW_IDX_parent: Entry @ 0x14b +; BOLT-NEXT: } ; BOLT-NEXT: } -; BOLT-NEXT: Entry @ {{.+}} { -; BOLT-NEXT: Abbrev: [[ABBREV1]] -; BOLT-NEXT: Tag: DW_TAG_base_type -; BOLT-NEXT: DW_IDX_compile_unit: 0x00 -; BOLT-NEXT: DW_IDX_die_offset: 0x0000007f +; BOLT-NEXT: ] +; BOLT-NEXT: Bucket 1 [ +; BOLT-NEXT: EMPTY +; BOLT-NEXT: ] +; BOLT-NEXT: Bucket 2 [ +; BOLT-NEXT: Name 2 { +; BOLT-NEXT: Hash: 0xFDE4B5D2 +; BOLT-NEXT: String: {{.+}} "fooVar" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV3]] +; BOLT-NEXT: Tag: DW_TAG_variable +; BOLT-NEXT: DW_IDX_compile_unit: 0x01 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000028 +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } ; BOLT-NEXT: } -; BOLT-NEXT: } -; BOLT-NEXT: ] -; BOLT-NEXT: Bucket 1 [ -; BOLT-NEXT: Name 2 { -; BOLT-NEXT: Hash: 0xB887389 -; BOLT-NEXT: String: {{.+}} "foo" -; BOLT-NEXT: Entry @ {{.+}} { -; BOLT-NEXT: Abbrev: [[ABBREV2]] -; BOLT-NEXT: Tag: DW_TAG_subprogram -; BOLT-NEXT: DW_IDX_compile_unit: 0x01 -; BOLT-NEXT: DW_IDX_die_offset: 0x0000005e +; BOLT-NEXT: ] +; BOLT-NEXT: Bucket 3 [ +; BOLT-NEXT: EMPTY +; BOLT-NEXT: ] +; BOLT-NEXT: Bucket 4 [ +; BOLT-NEXT: EMPTY +; BOLT-NEXT: ] +; BOLT-NEXT: Bucket 5 [ +; BOLT-NEXT: EMPTY +; BOLT-NEXT: ] +; BOLT-NEXT: Bucket 6 [ +; BOLT-NEXT: Name 3 { +; BOLT-NEXT: Hash: 0xB88B3D2 +; BOLT-NEXT: String: {{.+}} "use" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV1]] +; BOLT-NEXT: Tag: DW_TAG_subprogram +; BOLT-NEXT: DW_IDX_compile_unit: 0x00 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000028 +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } ; BOLT-NEXT: } -; BOLT-NEXT: } -; BOLT-NEXT: Name 3 { -; BOLT-NEXT: Hash: 0x8C06E589 -; BOLT-NEXT: String: {{.+}} "_Z3usePiS_" -; BOLT-NEXT: Entry @ {{.+}} { -; BOLT-NEXT: Abbrev: [[ABBREV2]] -; BOLT-NEXT: Tag: DW_TAG_subprogram -; BOLT-NEXT: DW_IDX_compile_unit: 0x00 -; BOLT-NEXT: DW_IDX_die_offset: 0x00000028 +; BOLT-NEXT: Name 4 { +; BOLT-NEXT: Hash: 0x69A7307E +; BOLT-NEXT: String: {{.+}} "_Z6useFooPi" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV1]] +; BOLT-NEXT: Tag: DW_TAG_subprogram +; BOLT-NEXT: DW_IDX_compile_unit: 0x01 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000037 +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV2]] +; BOLT-NEXT: Tag: DW_TAG_inlined_subroutine +; BOLT-NEXT: DW_IDX_compile_unit: 0x01 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000081 +; BOLT-NEXT: DW_IDX_parent: Entry @ 0x14b +; BOLT-NEXT: } ; BOLT-NEXT: } -; BOLT-NEXT: } -; BOLT-NEXT: ] -; BOLT-NEXT: Bucket 2 [ -; BOLT-NEXT: Name 4 { -; BOLT-NEXT: Hash: 0xB88B3D2 -; BOLT-NEXT: String: {{.+}} "use" -; BOLT-NEXT: Entry @ {{.+}} { -; BOLT-NEXT: Abbrev: [[ABBREV2]] -; BOLT-NEXT: Tag: DW_TAG_subprogram -; BOLT-NEXT: DW_IDX_compile_unit: 0x00 -; BOLT-NEXT: DW_IDX_die_offset: 0x00000028 +; BOLT-NEXT: Name 5 { +; BOLT-NEXT: Hash: 0x7C9A7F6A +; BOLT-NEXT: String: {{.+}} "main" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV1]] +; BOLT-NEXT: Tag: DW_TAG_subprogram +; BOLT-NEXT: DW_IDX_compile_unit: 0x00 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000049 +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } ; BOLT-NEXT: } -; BOLT-NEXT: } -; BOLT-NEXT: Name 5 { -; BOLT-NEXT: Hash: 0x7C9A7F6A -; BOLT-NEXT: String: {{.+}} "main" -; BOLT-NEXT: Entry @ {{.+}} { -; BOLT-NEXT: Abbrev: [[ABBREV2]] -; BOLT-NEXT: Tag: DW_TAG_subprogram -; BOLT-NEXT: DW_IDX_compile_unit: 0x00 -; BOLT-NEXT: DW_IDX_die_offset: 0x00000049 +; BOLT-NEXT: Name 6 { +; BOLT-NEXT: Hash: 0xB5063CFE +; BOLT-NEXT: String: {{.+}} "_Z3fooi" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV1]] +; BOLT-NEXT: Tag: DW_TAG_subprogram +; BOLT-NEXT: DW_IDX_compile_unit: 0x01 +; BOLT-NEXT: DW_IDX_die_offset: 0x0000005e +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } ; BOLT-NEXT: } -; BOLT-NEXT: } -; BOLT-NEXT: Name 6 { -; BOLT-NEXT: Hash: 0xFDE4B5D2 -; BOLT-NEXT: String: {{.+}} "fooVar" -; BOLT-NEXT: Entry @ {{.+}} { -; BOLT-NEXT: Abbrev: [[ABBREV3]] -; BOLT-NEXT: Tag: DW_TAG_variable -; BOLT-NEXT: DW_IDX_compile_unit: 0x01 -; BOLT-NEXT: DW_IDX_die_offset: 0x00000028 +; BOLT-NEXT: ] +; BOLT-NEXT: Bucket 7 [ +; BOLT-NEXT: Name 7 { +; BOLT-NEXT: Hash: 0x8C06E589 +; BOLT-NEXT: String: {{.+}} "_Z3usePiS_" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV1]] +; BOLT-NEXT: Tag: DW_TAG_subprogram +; BOLT-NEXT: DW_IDX_compile_unit: 0x00 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000028 +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } ; BOLT-NEXT: } -; BOLT-NEXT: } -; BOLT-NEXT: ] -; BOLT-NEXT: Bucket 3 [ -; BOLT-NEXT: Name 7 { -; BOLT-NEXT: Hash: 0x7C952063 -; BOLT-NEXT: String: {{.+}} "char" -; BOLT-NEXT: Entry @ {{.+}} { -; BOLT-NEXT: Abbrev: [[ABBREV1]] -; BOLT-NEXT: Tag: DW_TAG_base_type -; BOLT-NEXT: DW_IDX_compile_unit: 0x00 -; BOLT-NEXT: DW_IDX_die_offset: 0x00000092 +; BOLT-NEXT: ] +; BOLT-NEXT: Bucket 8 [ +; BOLT-NEXT: Name 8 { +; BOLT-NEXT: Hash: 0xB888030 +; BOLT-NEXT: String: {{.+}} "int" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV4]] +; BOLT-NEXT: Tag: DW_TAG_base_type +; BOLT-NEXT: DW_IDX_compile_unit: 0x01 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000033 +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } +; BOLT-NEXT: Entry @ 0x{{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV4]] +; BOLT-NEXT: Tag: DW_TAG_base_type +; BOLT-NEXT: DW_IDX_compile_unit: 0x00 +; BOLT-NEXT: DW_IDX_die_offset: 0x0000007f +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } ; BOLT-NEXT: } -; BOLT-NEXT: } -; BOLT-NEXT: ] -; BOLT-NEXT: Bucket 4 [ -; BOLT-NEXT: EMPTY -; BOLT-NEXT: ] -; BOLT-NEXT: Bucket 5 [ -; BOLT-NEXT: EMPTY -; BOLT-NEXT: ] -; BOLT-NEXT: Bucket 6 [ -; BOLT-NEXT: Name 8 { -; BOLT-NEXT: Hash: 0xB5063CFE -; BOLT-NEXT: String: {{.+}} "_Z3fooi" -; BOLT-NEXT: Entry @ {{.+}} { -; BOLT-NEXT: Abbrev: [[ABBREV2]] -; BOLT-NEXT: Tag: DW_TAG_subprogram -; BOLT-NEXT: DW_IDX_compile_unit: 0x01 -; BOLT-NEXT: DW_IDX_die_offset: 0x0000005e +; BOLT-NEXT: ] +; BOLT-NEXT: Bucket 9 [ +; BOLT-NEXT: Name 9 { +; BOLT-NEXT: Hash: 0xB887389 +; BOLT-NEXT: String: {{.+}} "foo" +; BOLT-NEXT: Entry @ 0x14b { +; BOLT-NEXT: Abbrev: [[ABBREV1]] +; BOLT-NEXT: Tag: DW_TAG_subprogram +; BOLT-NEXT: DW_IDX_compile_unit: 0x01 +; BOLT-NEXT: DW_IDX_die_offset: 0x0000005e +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } ; BOLT-NEXT: } -; BOLT-NEXT: } -; BOLT-NEXT: ] -; BOLT-NEXT: Bucket 7 [ -; BOLT-NEXT: EMPTY -; BOLT-NEXT: ] -; BOLT-NEXT: } +; BOLT-NEXT: Name 10 { +; BOLT-NEXT: Hash: 0x7C952063 +; BOLT-NEXT: String: {{.+}} "char" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV4]] +; BOLT-NEXT: Tag: DW_TAG_base_type +; BOLT-NEXT: DW_IDX_compile_unit: 0x00 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000092 +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } +; BOLT-NEXT: } +; BOLT-NEXT: ] +; BOLT-NEXT: } diff --git a/bolt/test/X86/dwarf5-debug-names.test b/bolt/test/X86/dwarf5-debug-names.test index de0e88d7a36ae5b35eb6528eb18c7a3ba5ce3cfe..ef11ee0c479b7f8416a38367d220bed4bf9a0559 100644 --- a/bolt/test/X86/dwarf5-debug-names.test +++ b/bolt/test/X86/dwarf5-debug-names.test @@ -11,7 +11,7 @@ ; BOLT: [[OFFSET2:0x[0-9a-f]*]]: Compile Unit ; BOLT: Name Index @ 0x0 { ; BOLT-NEXT: Header { -; BOLT-NEXT: Length: 0x1C2 +; BOLT-NEXT: Length: 0x1D4 ; BOLT-NEXT: Format: DWARF32 ; BOLT-NEXT: Version: 5 ; BOLT-NEXT: CU count: 2 @@ -19,7 +19,7 @@ ; BOLT-NEXT: Foreign TU count: 0 ; BOLT-NEXT: Bucket count: 14 ; BOLT-NEXT: Name count: 15 -; BOLT-NEXT: Abbreviations table size: 0x29 +; BOLT-NEXT: Abbreviations table size: 0x3D ; BOLT-NEXT: Augmentation: 'BOLT' ; BOLT-NEXT: } ; BOLT-NEXT: Compilation Unit offsets [ @@ -31,27 +31,38 @@ ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_namespace ; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV4:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV5:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_variable ; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } +; BOLT-NEXT: Abbreviation [[ABBREV6:0x[0-9a-f]*]] { +; BOLT-NEXT: Tag: DW_TAG_structure_type +; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 +; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_ref4 +; BOLT-NEXT: } ; BOLT-NEXT: ] ; BOLT-NEXT: Bucket 0 [ ; BOLT-NEXT: Name 1 { @@ -62,6 +73,7 @@ ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x0000002f +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -74,6 +86,7 @@ ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x000000eb +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -81,17 +94,12 @@ ; BOLT-NEXT: Name 3 { ; BOLT-NEXT: Hash: 0x8CFC710C ; BOLT-NEXT: String: {{.+}} "(anonymous namespace)" -; BOLT-NEXT: Entry @ {{.+}} { -; BOLT-NEXT: Abbrev: [[ABBREV2]] -; BOLT-NEXT: Tag: DW_TAG_namespace -; BOLT-NEXT: DW_IDX_compile_unit: 0x00 -; BOLT-NEXT: DW_IDX_die_offset: 0x00000061 -; BOLT-NEXT: } -; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Entry @ [[ENTRY:0x[0-9a-f]*]] { ; BOLT-NEXT: Abbrev: [[ABBREV2]] ; BOLT-NEXT: Tag: DW_TAG_namespace ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000061 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 4 { @@ -102,6 +110,7 @@ ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x0000005a +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -120,6 +129,7 @@ ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x000000c9 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 6 { @@ -130,6 +140,7 @@ ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000033 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 7 { @@ -140,12 +151,14 @@ ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x0000009f +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: Entry @ {{.+}} { ; BOLT-NEXT: Abbrev: [[ABBREV4]] ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x000000c5 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -158,6 +171,7 @@ ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x0000003f +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 9 { @@ -168,6 +182,7 @@ ; BOLT-NEXT: Tag: DW_TAG_variable ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000024 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -180,6 +195,7 @@ ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000033 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -192,6 +208,7 @@ ; BOLT-NEXT: Tag: DW_TAG_variable ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000024 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -207,12 +224,14 @@ ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x0000002f +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: Entry @ {{.+}} { ; BOLT-NEXT: Abbrev: [[ABBREV4]] ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x0000005d +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 13 { @@ -223,12 +242,14 @@ ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000078 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: Entry @ {{.+}} { ; BOLT-NEXT: Abbrev: [[ABBREV1]] ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000104 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 14 { @@ -239,6 +260,7 @@ ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000073 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -250,10 +272,11 @@ ; BOLT-NEXT: Hash: 0x59796A ; BOLT-NEXT: String: {{.+}} "t1" ; BOLT-NEXT: Entry @ {{.+}} { -; BOLT-NEXT: Abbrev: [[ABBREV1]] +; BOLT-NEXT: Abbrev: [[ABBREV6]] ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000062 +; BOLT-NEXT: DW_IDX_parent: Entry @ [[ENTRY]] ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] diff --git a/bolt/test/X86/dwarf5-df-debug-names-generate-debug-names.test b/bolt/test/X86/dwarf5-df-debug-names-generate-debug-names.test index 3be327b780e525ad55d83441b03f6c4bd0ac2e44..b0b6707a4ea5cb4174355fbf75428e3890d889dc 100644 --- a/bolt/test/X86/dwarf5-df-debug-names-generate-debug-names.test +++ b/bolt/test/X86/dwarf5-df-debug-names-generate-debug-names.test @@ -17,7 +17,7 @@ ; BOLT: [[OFFSET2:0x[0-9a-f]*]]: Compile Unit ; BOLT: Name Index @ 0x0 { ; BOLT-NEXT: Header { -; BOLT-NEXT: Length: 0x148 +; BOLT-NEXT: Length: 0x14E ; BOLT-NEXT: Format: DWARF32 ; BOLT-NEXT: Version: 5 ; BOLT-NEXT: CU count: 2 @@ -25,7 +25,7 @@ ; BOLT-NEXT: Foreign TU count: 0 ; BOLT-NEXT: Bucket count: 11 ; BOLT-NEXT: Name count: 11 -; BOLT-NEXT: Abbreviations table size: 0x19 +; BOLT-NEXT: Abbreviations table size: 0x1F ; BOLT-NEXT: Augmentation: 'BOLT' ; BOLT-NEXT: } ; BOLT-NEXT: Compilation Unit offsets [ @@ -37,16 +37,19 @@ ; BOLT-NEXT: Tag: DW_TAG_variable ; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: ] ; BOLT-NEXT: Bucket 0 [ @@ -58,6 +61,7 @@ ; BOLT-NEXT: Tag: DW_TAG_variable ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000029 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 2 { @@ -68,6 +72,7 @@ ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x0000008c +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -80,6 +85,7 @@ ; BOLT-NEXT: Tag: DW_TAG_variable ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000029 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 4 { @@ -90,6 +96,7 @@ ; BOLT-NEXT: Tag: DW_TAG_variable ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x0000001a +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -102,6 +109,7 @@ ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000034 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -114,6 +122,7 @@ ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000034 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -129,6 +138,7 @@ ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000034 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -141,12 +151,14 @@ ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000025 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: Entry @ {{.+}} { ; BOLT-NEXT: Abbrev: [[ABBREV2]] ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000025 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -159,6 +171,7 @@ ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000034 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 10 { @@ -169,6 +182,7 @@ ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000057 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -187,6 +201,7 @@ ; BOLT-NEXT: Tag: DW_TAG_variable ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x0000001a +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] diff --git a/bolt/test/X86/dwarf5-df-debug-names.test b/bolt/test/X86/dwarf5-df-debug-names.test index 0352d0ff720822ea0a9bc5eeb5aedf8395c61925..d53f2bd13620fca52c4514c3fc019e75da10d898 100644 --- a/bolt/test/X86/dwarf5-df-debug-names.test +++ b/bolt/test/X86/dwarf5-df-debug-names.test @@ -14,136 +14,148 @@ ; BOLT: [[OFFSET:0x[0-9a-f]*]]: Compile Unit ; BOLT: [[OFFSET1:0x[0-9a-f]*]]: Compile Unit -: BOLT: Name Index @ 0x0 { -: BOLT-NEXT: Header { -: BOLT-NEXT: Length: 0xF4 -: BOLT-NEXT: Format: DWARF32 -: BOLT-NEXT: Version: 5 -: BOLT-NEXT: CU count: 2 -: BOLT-NEXT: Local TU count: 0 -: BOLT-NEXT: Foreign TU count: 0 -: BOLT-NEXT: Bucket count: 7 -: BOLT-NEXT: Name count: 7 -: BOLT-NEXT: Abbreviations table size: 0x21 -: BOLT-NEXT: Augmentation: 'BOLT' -: BOLT-NEXT: } -: BOLT-NEXT: Compilation Unit offsets [ -: BOLT-NEXT: CU[0]: [[OFFSET]] -: BOLT-NEXT: CU[1]: [[OFFSET1]] -: BOLT-NEXT: ] -: BOLT-NEXT: Abbreviations [ -: BOLT-NEXT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] { -: BOLT-NEXT: Tag: DW_TAG_structure_type -: BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 -: BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 -: BOLT-NEXT: } -: BOLT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] { -: BOLT-NEXT: Tag: DW_TAG_base_type -: BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 -: BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 -: BOLT-NEXT: } -: BOLT-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] { -: BOLT-NEXT: Tag: DW_TAG_variable -: BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 -: BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 -: BOLT-NEXT: } -: BOLT-NEXT: Abbreviation [[ABBREV4:0x[0-9a-f]*]] { -: BOLT-NEXT: Tag: DW_TAG_subprogram -: BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 -: BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 -: BOLT-NEXT: } -: BOLT-NEXT: ] -: BOLT-NEXT: Bucket 0 [ -: BOLT-NEXT: EMPTY -: BOLT-NEXT: ] -: BOLT-NEXT: Bucket 1 [ -: BOLT-NEXT: Name 1 { -: BOLT-NEXT: Hash: 0x7C96E4DB -: BOLT-NEXT: String: {{.+}} "Foo2" -: BOLT-NEXT: Entry @ {{.+}} { -: BOLT-NEXT: Abbrev: [[ABBREV1]] -: BOLT-NEXT: Tag: DW_TAG_structure_type -: BOLT-NEXT: DW_IDX_compile_unit: 0x00 -: BOLT-NEXT: DW_IDX_die_offset: 0x00000068 -: BOLT-NEXT: } -: BOLT-NEXT: } -: BOLT-NEXT: ] -: BOLT-NEXT: Bucket 2 [ -: BOLT-NEXT: Name 2 { -: BOLT-NEXT: Hash: 0xBA564846 -: BOLT-NEXT: String: {{.+}} "Foo2Int" -: BOLT-NEXT: Entry @ {{.+}} { -: BOLT-NEXT: Abbrev: [[ABBREV1]] -: BOLT-NEXT: Tag: DW_TAG_structure_type -: BOLT-NEXT: DW_IDX_compile_unit: 0x01 -: BOLT-NEXT: DW_IDX_die_offset: 0x00000025 -: BOLT-NEXT: } -: BOLT-NEXT: } -: BOLT-NEXT: ] -: BOLT-NEXT: Bucket 3 [ -: BOLT-NEXT: Name 3 { -: BOLT-NEXT: Hash: 0xB888030 -: BOLT-NEXT: String: {{.+}} "int" -: BOLT-NEXT: Entry @ {{.+}} { -: BOLT-NEXT: Abbrev: [[ABBREV2]] -: BOLT-NEXT: Tag: DW_TAG_base_type -: BOLT-NEXT: DW_IDX_compile_unit: 0x01 -: BOLT-NEXT: DW_IDX_die_offset: 0x00000043 -: BOLT-NEXT: } -: BOLT-NEXT: Entry @ {{.+}} { -: BOLT-NEXT: Abbrev: [[ABBREV2]] -: BOLT-NEXT: Tag: DW_TAG_base_type -: BOLT-NEXT: DW_IDX_compile_unit: 0x00 -: BOLT-NEXT: DW_IDX_die_offset: 0x00000056 -: BOLT-NEXT: } -: BOLT-NEXT: } -: BOLT-NEXT: Name 4 { -: BOLT-NEXT: Hash: 0xF73809C -: BOLT-NEXT: String: {{.+}} "Foo2a" -: BOLT-NEXT: Entry @ {{.+}} { -: BOLT-NEXT: Abbrev: [[ABBREV1]] -: BOLT-NEXT: Tag: DW_TAG_structure_type -: BOLT-NEXT: DW_IDX_compile_unit: 0x00 -: BOLT-NEXT: DW_IDX_die_offset: 0x00000078 -: BOLT-NEXT: } -: BOLT-NEXT: } -: BOLT-NEXT: Name 5 { -: BOLT-NEXT: Hash: 0x7C96CB76 -: BOLT-NEXT: String: {{.+}} "fint" -: BOLT-NEXT: Entry @ {{.+}} { -: BOLT-NEXT: Abbrev: [[ABBREV3]] -: BOLT-NEXT: Tag: DW_TAG_variable -: BOLT-NEXT: DW_IDX_compile_unit: 0x01 -: BOLT-NEXT: DW_IDX_die_offset: 0x0000001a -: BOLT-NEXT: } -: BOLT-NEXT: } -: BOLT-NEXT: Name 6 { -: BOLT-NEXT: Hash: 0x7C9A7F6A -: BOLT-NEXT: String: {{.+}} "main" -: BOLT-NEXT: Entry @ {{.+}} { -: BOLT-NEXT: Abbrev: [[ABBREV4]] -: BOLT-NEXT: Tag: DW_TAG_subprogram -: BOLT-NEXT: DW_IDX_compile_unit: 0x00 -: BOLT-NEXT: DW_IDX_die_offset: 0x0000001a -: BOLT-NEXT: } -: BOLT-NEXT: } -: BOLT-NEXT: ] -: BOLT-NEXT: Bucket 4 [ -: BOLT-NEXT: EMPTY -: BOLT-NEXT: ] -: BOLT-NEXT: Bucket 5 [ -: BOLT-NEXT: Name 7 { -: BOLT-NEXT: Hash: 0x7C952063 -: BOLT-NEXT: String: {{.+}} "char" -: BOLT-NEXT: Entry @ {{.+}} { -: BOLT-NEXT: Abbrev: [[ABBREV2]] -: BOLT-NEXT: Tag: DW_TAG_base_type -: BOLT-NEXT: DW_IDX_compile_unit: 0x00 -: BOLT-NEXT: DW_IDX_die_offset: 0x00000064 -: BOLT-NEXT: } -: BOLT-NEXT: } -: BOLT-NEXT: ] -: BOLT-NEXT: Bucket 6 [ -: BOLT-NEXT: EMPTY -: BOLT-NEXT: ] -: BOLT-NEXT: } +; BOLT: Name Index @ 0x0 { +; BOLT-NEXT: Header { +; BOLT-NEXT: Length: 0xFC +; BOLT-NEXT: Format: DWARF32 +; BOLT-NEXT: Version: 5 +; BOLT-NEXT: CU count: 2 +; BOLT-NEXT: Local TU count: 0 +; BOLT-NEXT: Foreign TU count: 0 +; BOLT-NEXT: Bucket count: 7 +; BOLT-NEXT: Name count: 7 +; BOLT-NEXT: Abbreviations table size: 0x29 +; BOLT-NEXT: Augmentation: 'BOLT' +; BOLT-NEXT: } +; BOLT-NEXT: Compilation Unit offsets [ +; BOLT-NEXT: CU[0]: [[OFFSET]] +; BOLT-NEXT: CU[1]: [[OFFSET1]] +; BOLT-NEXT: ] +; BOLT-NEXT: Abbreviations [ +; BOLT-NEXT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] { +; BOLT-NEXT: Tag: DW_TAG_structure_type +; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 +; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present +; BOLT-NEXT: } +; BOLT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] { +; BOLT-NEXT: Tag: DW_TAG_base_type +; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 +; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present +; BOLT-NEXT: } +; BOLT-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] { +; BOLT-NEXT: Tag: DW_TAG_variable +; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 +; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present +; BOLT-NEXT: } +; BOLT-NEXT: Abbreviation [[ABBREV4:0x[0-9a-f]*]] { +; BOLT-NEXT: Tag: DW_TAG_subprogram +; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 +; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present +; BOLT-NEXT: } +; BOLT-NEXT: ] +; BOLT-NEXT: Bucket 0 [ +; BOLT-NEXT: EMPTY +; BOLT-NEXT: ] +; BOLT-NEXT: Bucket 1 [ +; BOLT-NEXT: Name 1 { +; BOLT-NEXT: Hash: 0x7C96E4DB +; BOLT-NEXT: String: {{.+}} "Foo2" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV1]] +; BOLT-NEXT: Tag: DW_TAG_structure_type +; BOLT-NEXT: DW_IDX_compile_unit: 0x00 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000068 +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } +; BOLT-NEXT: } +; BOLT-NEXT: ] +; BOLT-NEXT: Bucket 2 [ +; BOLT-NEXT: Name 2 { +; BOLT-NEXT: Hash: 0xBA564846 +; BOLT-NEXT: String: {{.+}} "Foo2Int" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV1]] +; BOLT-NEXT: Tag: DW_TAG_structure_type +; BOLT-NEXT: DW_IDX_compile_unit: 0x01 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000025 +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } +; BOLT-NEXT: } +; BOLT-NEXT: ] +; BOLT-NEXT: Bucket 3 [ +; BOLT-NEXT: Name 3 { +; BOLT-NEXT: Hash: 0xB888030 +; BOLT-NEXT: String: {{.+}} "int" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV2]] +; BOLT-NEXT: Tag: DW_TAG_base_type +; BOLT-NEXT: DW_IDX_compile_unit: 0x01 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000043 +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV2]] +; BOLT-NEXT: Tag: DW_TAG_base_type +; BOLT-NEXT: DW_IDX_compile_unit: 0x00 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000056 +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } +; BOLT-NEXT: } +; BOLT-NEXT: Name 4 { +; BOLT-NEXT: Hash: 0xF73809C +; BOLT-NEXT: String: {{.+}} "Foo2a" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV1]] +; BOLT-NEXT: Tag: DW_TAG_structure_type +; BOLT-NEXT: DW_IDX_compile_unit: 0x00 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000078 +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } +; BOLT-NEXT: } +; BOLT-NEXT: Name 5 { +; BOLT-NEXT: Hash: 0x7C96CB76 +; BOLT-NEXT: String: {{.+}} "fint" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV3]] +; BOLT-NEXT: Tag: DW_TAG_variable +; BOLT-NEXT: DW_IDX_compile_unit: 0x01 +; BOLT-NEXT: DW_IDX_die_offset: 0x0000001a +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } +; BOLT-NEXT: } +; BOLT-NEXT: Name 6 { +; BOLT-NEXT: Hash: 0x7C9A7F6A +; BOLT-NEXT: String: {{.+}} "main" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV4]] +; BOLT-NEXT: Tag: DW_TAG_subprogram +; BOLT-NEXT: DW_IDX_compile_unit: 0x00 +; BOLT-NEXT: DW_IDX_die_offset: 0x0000001a +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } +; BOLT-NEXT: } +; BOLT-NEXT: ] +; BOLT-NEXT: Bucket 4 [ +; BOLT-NEXT: EMPTY +; BOLT-NEXT: ] +; BOLT-NEXT: Bucket 5 [ +; BOLT-NEXT: Name 7 { +; BOLT-NEXT: Hash: 0x7C952063 +; BOLT-NEXT: String: {{.+}} "char" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: [[ABBREV2]] +; BOLT-NEXT: Tag: DW_TAG_base_type +; BOLT-NEXT: DW_IDX_compile_unit: 0x00 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000064 +; BOLT-NEXT: DW_IDX_parent: +; BOLT-NEXT: } +; BOLT-NEXT: } +; BOLT-NEXT: ] +; BOLT-NEXT: Bucket 6 [ +; BOLT-NEXT: EMPTY +; BOLT-NEXT: ] +; BOLT-NEXT: } diff --git a/bolt/test/X86/dwarf5-df-main-debug-names-ftu-ltu-mix.test b/bolt/test/X86/dwarf5-df-main-debug-names-ftu-ltu-mix.test index 8a8a4b118b8c031c3ae96ed05d4a4c124543b2e5..3a0260fd0bfb91707a0e56f3451f492d688f8a44 100644 --- a/bolt/test/X86/dwarf5-df-main-debug-names-ftu-ltu-mix.test +++ b/bolt/test/X86/dwarf5-df-main-debug-names-ftu-ltu-mix.test @@ -31,6 +31,7 @@ ; BOLT-NEXT: Tag: DW_TAG_variable ; BOLT-NEXT: DW_IDX_compile_unit: 0x02 ; BOLT-NEXT: DW_IDX_die_offset: 0x0000001e +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT: Name 6 { @@ -42,6 +43,7 @@ ; BOLT-NEXT: DW_IDX_type_unit: 0x02 ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000021 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT: Name 7 { @@ -52,5 +54,6 @@ ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_type_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000023 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } diff --git a/bolt/test/X86/dwarf5-df-one-cu-debug-names.test b/bolt/test/X86/dwarf5-df-one-cu-debug-names.test index 246ce7efb3bad66eec5c8aed14893e40114aed88..bf1cad81040bd93b204d221482b4377def89aaa3 100644 --- a/bolt/test/X86/dwarf5-df-one-cu-debug-names.test +++ b/bolt/test/X86/dwarf5-df-one-cu-debug-names.test @@ -13,7 +13,7 @@ ; BOLT: [[OFFSET:0x[0-9a-f]*]]: Compile Unit ; BOLT: Name Index @ 0x0 { ; BOLT-NEXT: Header { -; BOLT-NEXT: Length: 0xA9 +; BOLT-NEXT: Length: 0xAF ; BOLT-NEXT: Format: DWARF32 ; BOLT-NEXT: Version: 5 ; BOLT-NEXT: CU count: 1 @@ -21,7 +21,7 @@ ; BOLT-NEXT: Foreign TU count: 0 ; BOLT-NEXT: Bucket count: 5 ; BOLT-NEXT: Name count: 5 -; BOLT-NEXT: Abbreviations table size: 0x13 +; BOLT-NEXT: Abbreviations table size: 0x19 ; BOLT-NEXT: Augmentation: 'BOLT' ; BOLT-NEXT: } ; BOLT-NEXT: Compilation Unit offsets [ @@ -31,14 +31,17 @@ ; BOLT-NEXT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: ] ; BOLT-NEXT: Bucket 0 [ @@ -52,6 +55,7 @@ ; BOLT-NEXT: Abbrev: [[ABBREV1]] ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_die_offset: 0x00000068 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 2 { @@ -61,6 +65,7 @@ ; BOLT-NEXT: Abbrev: [[ABBREV2]] ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_die_offset: 0x0000001a +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -75,6 +80,7 @@ ; BOLT-NEXT: Abbrev: [[ABBREV3]] ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_die_offset: 0x00000056 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -86,6 +92,7 @@ ; BOLT-NEXT: Abbrev: [[ABBREV1]] ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_die_offset: 0x00000078 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 5 { @@ -95,6 +102,7 @@ ; BOLT-NEXT: Abbrev: [[ABBREV3]] ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_die_offset: 0x00000064 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] diff --git a/bolt/test/X86/dwarf5-df-types-debug-names.test b/bolt/test/X86/dwarf5-df-types-debug-names.test index fdb962b80c75122bd1948de5da12610ab43b2c82..f5a2c9c10353e9a98e41f5d6701545a29ffeaba8 100644 --- a/bolt/test/X86/dwarf5-df-types-debug-names.test +++ b/bolt/test/X86/dwarf5-df-types-debug-names.test @@ -25,7 +25,7 @@ ; BOLT: Name Index @ 0x0 { ; BOLT-NEXT: Header { -; BOLT-NEXT: Length: 0x174 +; BOLT-NEXT: Length: 0x17E ; BOLT-NEXT: Format: DWARF32 ; BOLT-NEXT: Version: 5 ; BOLT-NEXT: CU count: 2 @@ -33,7 +33,7 @@ ; BOLT-NEXT: Foreign TU count: 4 ; BOLT-NEXT: Bucket count: 9 ; BOLT-NEXT: Name count: 9 -; BOLT-NEXT: Abbreviations table size: 0x2D +; BOLT-NEXT: Abbreviations table size: 0x37 ; BOLT-NEXT: Augmentation: 'BOLT' ; BOLT-NEXT: } ; BOLT-NEXT: Compilation Unit offsets [ @@ -52,27 +52,32 @@ ; BOLT-NEXT: DW_IDX_type_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_variable ; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV4:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_type_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_compile_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: ] ; BOLT-NEXT: Bucket 0 [ @@ -88,6 +93,7 @@ ; BOLT-NEXT: DW_IDX_type_unit: 0x00 ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000021 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 2 { @@ -98,6 +104,7 @@ ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000029 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 3 { @@ -108,6 +115,7 @@ ; BOLT-NEXT: Tag: DW_TAG_variable ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x0000001a +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -120,6 +128,7 @@ ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000025 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: Entry @ {{.+}} { ; BOLT-NEXT: Abbrev: 0x5 @@ -127,12 +136,14 @@ ; BOLT-NEXT: DW_IDX_type_unit: 0x02 ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x0000003f +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: Entry @ {{.+}} { ; BOLT-NEXT: Abbrev: [[ABBREV3]] ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000056 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -145,6 +156,7 @@ ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000029 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 6 { @@ -156,6 +168,7 @@ ; BOLT-NEXT: DW_IDX_type_unit: 0x01 ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000021 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: Entry @ {{.+}} { ; BOLT-NEXT: Abbrev: [[ABBREV]] @@ -163,6 +176,7 @@ ; BOLT-NEXT: DW_IDX_type_unit: 0x03 ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000021 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 7 { @@ -174,6 +188,7 @@ ; BOLT-NEXT: DW_IDX_type_unit: 0x02 ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000021 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -195,6 +210,7 @@ ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x0000001a +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -208,6 +224,7 @@ ; BOLT-NEXT: DW_IDX_type_unit: 0x00 ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000036 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: Entry @ {{.+}} { ; BOLT-NEXT: Abbrev: 0x5 @@ -215,6 +232,7 @@ ; BOLT-NEXT: DW_IDX_type_unit: 0x01 ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000048 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: Entry @ {{.+}} { ; BOLT-NEXT: Abbrev: 0x5 @@ -222,12 +240,14 @@ ; BOLT-NEXT: DW_IDX_type_unit: 0x03 ; BOLT-NEXT: DW_IDX_compile_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000048 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: Entry @ {{.+}} { ; BOLT-NEXT: Abbrev: [[ABBREV3]] ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_compile_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000064 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] diff --git a/bolt/test/X86/dwarf5-df-types-one-cu-debug-names.test b/bolt/test/X86/dwarf5-df-types-one-cu-debug-names.test index 1c77583f50883f5e26a1a9019c6f32f341a8e4c6..2a489d86f5d7def0a5ea8e1cbbec48c15955213b 100644 --- a/bolt/test/X86/dwarf5-df-types-one-cu-debug-names.test +++ b/bolt/test/X86/dwarf5-df-types-one-cu-debug-names.test @@ -17,7 +17,7 @@ ; BOLT: [[OFFSET:0x[0-9a-f]*]]: Compile Unit ; BOLT: Name Index @ 0x0 { ; BOLT-NEXT: Header { -; BOLT-NEXT: Length: 0xD1 +; BOLT-NEXT: Length: 0xD9 ; BOLT-NEXT: Format: DWARF32 ; BOLT-NEXT: Version: 5 ; BOLT-NEXT: CU count: 1 @@ -25,7 +25,7 @@ ; BOLT-NEXT: Foreign TU count: 2 ; BOLT-NEXT: Bucket count: 5 ; BOLT-NEXT: Name count: 5 -; BOLT-NEXT: Abbreviations table size: 0x1D +; BOLT-NEXT: Abbreviations table size: 0x25 ; BOLT-NEXT: Augmentation: 'BOLT' ; BOLT-NEXT: } ; BOLT-NEXT: Compilation Unit offsets [ @@ -40,19 +40,23 @@ ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_type_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV4:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_type_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: ] ; BOLT-NEXT: Bucket 0 [ @@ -67,6 +71,7 @@ ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_type_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000021 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 2 { @@ -76,6 +81,7 @@ ; BOLT-NEXT: Abbrev: [[ABBREV2]] ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_die_offset: 0x0000001a +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -90,6 +96,7 @@ ; BOLT-NEXT: Abbrev: [[ABBREV3]] ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_die_offset: 0x00000056 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -102,6 +109,7 @@ ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_type_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000021 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 5 { @@ -112,17 +120,20 @@ ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_type_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000036 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: Entry @ {{.+}} { ; BOLT-NEXT: Abbrev: [[ABBREV4]] ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_type_unit: 0x01 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000048 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: Entry @ {{.+}} { ; BOLT-NEXT: Abbrev: [[ABBREV3]] ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_die_offset: 0x00000064 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] diff --git a/bolt/test/X86/dwarf5-label-low-pc.s b/bolt/test/X86/dwarf5-label-low-pc.s index b713097163348e4ce728fa2c117371d397592d11..1e3fc17ad516acb70410e60e4b860c0702f379ea 100644 --- a/bolt/test/X86/dwarf5-label-low-pc.s +++ b/bolt/test/X86/dwarf5-label-low-pc.s @@ -8,8 +8,10 @@ # RUN: llvm-dwarfdump --show-form --verbose --debug-addr %t.bolt > %t.txt # RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt >> %t.txt +# RUN: llvm-objdump -d %t.bolt >> %t.txt +# RUN: cat %t.txt | FileCheck --check-prefix=POSTCHECK %s -# This test checks that we correctly handle DW_AT_low_pc [DW_FORM_addrx] that is part of DW_TAG_label. +## This test checks that we correctly handle DW_AT_low_pc [DW_FORM_addrx] that is part of DW_TAG_label. # PRECHECK: version = 0x0005 # PRECHECK: DW_TAG_label @@ -27,36 +29,37 @@ # POSTCHECK: Addrs: [ # POSTCHECK-NEXT: 0x # POSTCHECK-NEXT: 0x -# POSTCHECK-NEXT: 0x[[#%.16x,ADDR:]] -# POSTCHECK-NEXT: 0x[[#%.16x,ADDR2:]] +# POSTCHECK-NEXT: 0x[[ADDR:[1-9a-f]*]] +# POSTCHECK-NEXT: 0x[[ADDR2:[1-9a-f]*]] # POSTCHECK: version = 0x0005 # POSTCHECK: DW_TAG_label # POSTCHECK-NEXT: DW_AT_name # POSTCHECK-NEXT: DW_AT_decl_file # POSTCHECK-NEXT: DW_AT_decl_line -# POSTCHECK-NEXT: # POSTCHECK-NEXT:DW_AT_low_pc [DW_FORM_addrx] (indexed (00000002) -# POSTCHECK-SAME: [0x[[#ADDR]] +# POSTCHECK-SAME: 0x[[ADDR]] # POSTCHECK: DW_TAG_label # POSTCHECK-NEXT: DW_AT_name # POSTCHECK-NEXT: DW_AT_decl_file # POSTCHECK-NEXT: DW_AT_decl_line -# POSTCHECK-NEXT: # POSTCHECK-NEXT:DW_AT_low_pc [DW_FORM_addrx] (indexed (00000003) -# POSTCHECK-SAME: [0x[[#ADDR2]] +# POSTCHECK-SAME: 0x[[ADDR2]] -# clang++ main.cpp -g -S -# int main() { -# int a = 4; -# if (a == 5) -# goto LABEL1; -# else -# goto LABEL2; -# LABEL1:a++; -# LABEL2:a--; -# return 0; -# } +# POSTCHECK: [[ADDR]]: 8b 45 f8 +# POSTCHECK: [[ADDR2]]: 8b 45 f8 + +## clang++ main.cpp -g -S +## int main() { +## int a = 4; +## if (a == 5) +## goto LABEL1; +## else +## goto LABEL2; +## LABEL1:a++; +## LABEL2:a--; +## return 0; +## } .text .file "main.cpp" diff --git a/bolt/test/X86/dwarf5-one-cu-debug-names.test b/bolt/test/X86/dwarf5-one-cu-debug-names.test index e7754521d61cbe8f5c919a0c0d7ea6a8106b91fa..74d6b3041c93359564e758ce629c2f7e5d4b0439 100644 --- a/bolt/test/X86/dwarf5-one-cu-debug-names.test +++ b/bolt/test/X86/dwarf5-one-cu-debug-names.test @@ -9,7 +9,7 @@ ; BOLT: [[OFFSET1:0x[0-9a-f]*]]: Compile Unit ; BOLT: Name Index @ 0x0 { ; BOLT-NEXT: Header { -; BOLT-NEXT: Length: 0x13E +; BOLT-NEXT: Length: 0x14F ; BOLT-NEXT: Format: DWARF32 ; BOLT-NEXT: Version: 5 ; BOLT-NEXT: CU count: 1 @@ -17,7 +17,7 @@ ; BOLT-NEXT: Foreign TU count: 0 ; BOLT-NEXT: Bucket count: 11 ; BOLT-NEXT: Name count: 11 -; BOLT-NEXT: Abbreviations table size: 0x1F +; BOLT-NEXT: Abbreviations table size: 0x31 ; BOLT-NEXT: Augmentation: 'BOLT' ; BOLT-NEXT: } ; BOLT-NEXT: Compilation Unit offsets [ @@ -27,22 +27,32 @@ ; BOLT-NEXT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] { +; BOLT-NEXT: Tag: DW_TAG_structure_type +; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_ref4 +; BOLT-NEXT: } +; BOLT-NEXT: Abbreviation [[ABBREV4:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_variable ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } -; BOLT-NEXT: Abbreviation [[ABBREV4:0x[0-9a-f]*]] { +; BOLT-NEXT: Abbreviation [[ABBREV5:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } -; BOLT-NEXT: Abbreviation [[ABBREV5:0x[0-9a-f]*]] { +; BOLT-NEXT: Abbreviation [[ABBREV6:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_namespace ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: ] ; BOLT-NEXT: Bucket 0 [ @@ -53,6 +63,7 @@ ; BOLT-NEXT: Abbrev: [[ABBREV1]] ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_die_offset: 0x00000104 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 2 { @@ -62,6 +73,7 @@ ; BOLT-NEXT: Abbrev: [[ABBREV2]] ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_die_offset: 0x000000c5 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -73,6 +85,7 @@ ; BOLT-NEXT: Abbrev: [[ABBREV1]] ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_die_offset: 0x000000c9 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 4 { @@ -82,6 +95,7 @@ ; BOLT-NEXT: Abbrev: [[ABBREV1]] ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_die_offset: 0x0000003f +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -93,6 +107,7 @@ ; BOLT-NEXT: Abbrev: [[ABBREV1]] ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_die_offset: 0x000000eb +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -107,18 +122,20 @@ ; BOLT-NEXT: Hash: 0x59796A ; BOLT-NEXT: String: {{.+}} "t1" ; BOLT-NEXT: Entry @ {{.+}} { -; BOLT-NEXT: Abbrev: [[ABBREV1]] +; BOLT-NEXT: Abbrev: [[ABBREV3]] ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_die_offset: 0x00000062 +; BOLT-NEXT: DW_IDX_parent: Entry @ 0x14d ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 7 { ; BOLT-NEXT: Hash: 0x5979AC ; BOLT-NEXT: String: {{.+}} "v1" ; BOLT-NEXT: Entry @ {{.+}} { -; BOLT-NEXT: Abbrev: [[ABBREV3]] +; BOLT-NEXT: Abbrev: [[ABBREV4]] ; BOLT-NEXT: Tag: DW_TAG_variable ; BOLT-NEXT: DW_IDX_die_offset: 0x00000024 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -130,6 +147,7 @@ ; BOLT-NEXT: Abbrev: [[ABBREV2]] ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_die_offset: 0x0000005d +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -141,15 +159,17 @@ ; BOLT-NEXT: Abbrev: [[ABBREV1]] ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_die_offset: 0x0000002f +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 10 { ; BOLT-NEXT: Hash: 0x7C9A7F6A ; BOLT-NEXT: String: {{.+}} "main" ; BOLT-NEXT: Entry @ {{.+}} { -; BOLT-NEXT: Abbrev: [[ABBREV4]] +; BOLT-NEXT: Abbrev: [[ABBREV5]] ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_die_offset: 0x00000073 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -157,15 +177,11 @@ ; BOLT-NEXT: Name 11 { ; BOLT-NEXT: Hash: 0x8CFC710C ; BOLT-NEXT: String: {{.+}} "(anonymous namespace)" -; BOLT-NEXT: Entry @ {{.+}} { -; BOLT-NEXT: Abbrev: [[ABBREV5]] -; BOLT-NEXT: Tag: DW_TAG_namespace -; BOLT-NEXT: DW_IDX_die_offset: 0x00000061 -; BOLT-NEXT: } -; BOLT-NEXT: Entry @ {{.+}} { -; BOLT-NEXT: Abbrev: [[ABBREV5]] +; BOLT-NEXT: Entry @ 0x14d { +; BOLT-NEXT: Abbrev: [[ABBREV6]] ; BOLT-NEXT: Tag: DW_TAG_namespace ; BOLT-NEXT: DW_IDX_die_offset: 0x00000061 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] diff --git a/bolt/test/X86/dwarf5-types-debug-names.test b/bolt/test/X86/dwarf5-types-debug-names.test index 6a26477d4cdb5578d22fdff3ce7afa9cbfd6104a..94624298e289de7c3b02f018d75bf8ccf3623371 100644 --- a/bolt/test/X86/dwarf5-types-debug-names.test +++ b/bolt/test/X86/dwarf5-types-debug-names.test @@ -14,7 +14,7 @@ ; BOLT: Name Index @ 0x0 { ; BOLT: Header { -; BOLT: Length: 0xE1 +; BOLT: Length: 0xE9 ; BOLT: Format: DWARF32 ; BOLT: Version: 5 ; BOLT: CU count: 2 @@ -22,7 +22,7 @@ ; BOLT: Foreign TU count: 0 ; BOLT: Bucket count: 6 ; BOLT: Name count: 6 -; BOLT: Abbreviations table size: 0x21 +; BOLT: Abbreviations table size: 0x29 ; BOLT: Augmentation: 'BOLT' ; BOLT: } ; BOLT: Compilation Unit offsets [ @@ -37,21 +37,25 @@ ; BOLT: Tag: DW_TAG_structure_type ; BOLT: DW_IDX_type_unit: DW_FORM_data1 ; BOLT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT: DW_IDX_parent: DW_FORM_flag_present ; BOLT: } ; BOLT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] { ; BOLT: Tag: DW_TAG_subprogram ; BOLT: DW_IDX_compile_unit: DW_FORM_data1 ; BOLT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT: DW_IDX_parent: DW_FORM_flag_present ; BOLT: } ; BOLT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] { ; BOLT: Tag: DW_TAG_base_type ; BOLT: DW_IDX_compile_unit: DW_FORM_data1 ; BOLT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT: DW_IDX_parent: DW_FORM_flag_present ; BOLT: } ; BOLT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] { ; BOLT: Tag: DW_TAG_base_type ; BOLT: DW_IDX_type_unit: DW_FORM_data1 ; BOLT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT: DW_IDX_parent: DW_FORM_flag_present ; BOLT: } ; BOLT: ] ; BOLT: Bucket 0 [ @@ -63,6 +67,7 @@ ; BOLT: Tag: DW_TAG_structure_type ; BOLT: DW_IDX_type_unit: 0x00 ; BOLT: DW_IDX_die_offset: 0x00000023 +; BOLT: DW_IDX_parent: ; BOLT: } ; BOLT: } ; BOLT: ] @@ -75,6 +80,7 @@ ; BOLT: Tag: DW_TAG_subprogram ; BOLT: DW_IDX_compile_unit: 0x01 ; BOLT: DW_IDX_die_offset: 0x00000024 +; BOLT: DW_IDX_parent: ; BOLT: } ; BOLT: } ; BOLT: ] @@ -87,6 +93,7 @@ ; BOLT: Tag: DW_TAG_base_type ; BOLT: DW_IDX_compile_unit: 0x01 ; BOLT: DW_IDX_die_offset: 0x00000040 +; BOLT: DW_IDX_parent: ; BOLT: } ; BOLT: } ; BOLT: ] @@ -99,6 +106,7 @@ ; BOLT: Tag: DW_TAG_subprogram ; BOLT: DW_IDX_compile_unit: 0x01 ; BOLT: DW_IDX_die_offset: 0x00000024 +; BOLT: DW_IDX_parent: ; BOLT: } ; BOLT: } ; BOLT: ] @@ -111,6 +119,7 @@ ; BOLT: Tag: DW_TAG_subprogram ; BOLT: DW_IDX_compile_unit: 0x00 ; BOLT: DW_IDX_die_offset: 0x00000024 +; BOLT: DW_IDX_parent: ; BOLT: } ; BOLT: } ; BOLT: ] @@ -123,6 +132,7 @@ ; BOLT: Tag: DW_TAG_base_type ; BOLT: DW_IDX_type_unit: 0x00 ; BOLT: DW_IDX_die_offset: 0x00000038 +; BOLT: DW_IDX_parent: ; BOLT: } ; BOLT: } ; BOLT: ] diff --git a/bolt/test/X86/dwarf5-types-one-cu-debug-names.test b/bolt/test/X86/dwarf5-types-one-cu-debug-names.test index 00a1319a557869e9ee2ab1da01931b4a76df602a..02c0ef81351f1f842f1167b0a097024bc1368a4c 100644 --- a/bolt/test/X86/dwarf5-types-one-cu-debug-names.test +++ b/bolt/test/X86/dwarf5-types-one-cu-debug-names.test @@ -11,7 +11,7 @@ ; BOLT:Name Index @ 0x0 { ; BOLT-NEXT: Header { -; BOLT-NEXT: Length: 0xA3 +; BOLT-NEXT: Length: 0xAB ; BOLT-NEXT: Format: DWARF32 ; BOLT-NEXT: Version: 5 ; BOLT-NEXT: CU count: 1 @@ -19,7 +19,7 @@ ; BOLT-NEXT: Foreign TU count: 0 ; BOLT-NEXT: Bucket count: 4 ; BOLT-NEXT: Name count: 4 -; BOLT-NEXT: Abbreviations table size: 0x1D +; BOLT-NEXT: Abbreviations table size: 0x25 ; BOLT-NEXT: Augmentation: 'BOLT' ; BOLT-NEXT: } ; BOLT-NEXT: Compilation Unit offsets [ @@ -32,20 +32,24 @@ ; BOLT-NEXT: Abbreviation [[ABBREV:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV1:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_type_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV2:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: Abbreviation [[ABBREV3:0x[0-9a-f]*]] { ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_type_unit: DW_FORM_data1 ; BOLT-NEXT: DW_IDX_die_offset: DW_FORM_ref4 +; BOLT-NEXT: DW_IDX_parent: DW_FORM_flag_present ; BOLT-NEXT: } ; BOLT-NEXT: ] ; BOLT-NEXT: Bucket 0 [ @@ -56,6 +60,7 @@ ; BOLT-NEXT: Abbrev: [[ABBREV]] ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_die_offset: 0x0000003f +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: Name 2 { @@ -66,6 +71,7 @@ ; BOLT-NEXT: Tag: DW_TAG_structure_type ; BOLT-NEXT: DW_IDX_type_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000023 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -80,6 +86,7 @@ ; BOLT-NEXT: Abbrev: [[ABBREV2]] ; BOLT-NEXT: Tag: DW_TAG_subprogram ; BOLT-NEXT: DW_IDX_die_offset: 0x00000024 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] @@ -92,6 +99,7 @@ ; BOLT-NEXT: Tag: DW_TAG_base_type ; BOLT-NEXT: DW_IDX_type_unit: 0x00 ; BOLT-NEXT: DW_IDX_die_offset: 0x00000038 +; BOLT-NEXT: DW_IDX_parent: ; BOLT-NEXT: } ; BOLT-NEXT: } ; BOLT-NEXT: ] diff --git a/bolt/test/X86/linux-alt-instruction.s b/bolt/test/X86/linux-alt-instruction.s index 5dcc6fe3ab0c81f178bd447be064529d79f11593..2cdf31519682a8e300a05efe46ccd4a867ddd133 100644 --- a/bolt/test/X86/linux-alt-instruction.s +++ b/bolt/test/X86/linux-alt-instruction.s @@ -6,8 +6,8 @@ # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o # RUN: %clang %cflags -nostdlib %t.o -o %t.exe \ # RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr,--no-pie -# RUN: llvm-bolt %t.exe --print-normalized --keep-nops -o %t.out \ -# RUN: --alt-inst-feature-size=2 | FileCheck %s +# RUN: llvm-bolt %t.exe --print-normalized --alt-inst-feature-size=2 -o %t.out \ +# RUN: | FileCheck %s ## Older kernels used to have padlen field in alt_instr. Check compatibility. @@ -15,8 +15,8 @@ # RUN: %s -o %t.o # RUN: %clang %cflags -nostdlib %t.o -o %t.exe \ # RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr,--no-pie -# RUN: llvm-bolt %t.exe --print-normalized --keep-nops --alt-inst-has-padlen \ -# RUN: -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --print-normalized --alt-inst-has-padlen -o %t.out \ +# RUN: | FileCheck %s ## Check with a larger size of "feature" field in alt_instr. @@ -24,13 +24,12 @@ # RUN: --defsym FEATURE_SIZE_4=1 %s -o %t.o # RUN: %clang %cflags -nostdlib %t.o -o %t.exe \ # RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr,--no-pie -# RUN: llvm-bolt %t.exe --print-normalized --keep-nops \ -# RUN: --alt-inst-feature-size=4 -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --print-normalized --alt-inst-feature-size=4 -o %t.out \ +# RUN: | FileCheck %s ## Check that out-of-bounds read is handled properly. -# RUN: not llvm-bolt %t.exe --print-normalized --keep-nops \ -# RUN: --alt-inst-feature-size=2 -o %t.out +# RUN: not llvm-bolt %t.exe --print-normalized --alt-inst-feature-size=2 -o %t.out # CHECK: BOLT-INFO: Linux kernel binary detected # CHECK: BOLT-INFO: parsed 2 alternative instruction entries diff --git a/bolt/test/X86/linux-bug-table.s b/bolt/test/X86/linux-bug-table.s index e8de2fb6cba79ddab8061705700f263200c0701e..63f70a0b35d9fe59c85a68998a019a2175a74c46 100644 --- a/bolt/test/X86/linux-bug-table.s +++ b/bolt/test/X86/linux-bug-table.s @@ -1,6 +1,7 @@ # REQUIRES: system-linux -## Check that BOLT correctly parses the Linux kernel __bug_table section. +## Check that BOLT correctly parses and updates the Linux kernel __bug_table +## section. # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o # RUN: %clang %cflags -nostdlib %t.o -o %t.exe \ @@ -8,7 +9,13 @@ ## Verify bug entry bindings to instructions. -# RUN: llvm-bolt %t.exe --print-normalized -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --print-normalized --print-only=_start -o %t.out \ +# RUN: --eliminate-unreachable=1 --bolt-info=0 | FileCheck %s + +## Verify bug entry bindings again after unreachable code elimination. + +# RUN: llvm-bolt %t.out -o %t.out.1 --print-only=_start --print-normalized \ +# RUN: |& FileCheck --check-prefix=CHECK-REOPT %s # CHECK: BOLT-INFO: Linux kernel binary detected # CHECK: BOLT-INFO: parsed 2 bug table entries @@ -17,18 +24,26 @@ .globl _start .type _start, %function _start: -# CHECK: Binary Function "_start" - nop + jmp .L1 .L0: ud2 # CHECK: ud2 # CHECK-SAME: BugEntry: 1 - nop .L1: ud2 # CHECK: ud2 # CHECK-SAME: BugEntry: 2 + +## Only the second entry should remain after the first pass. + +# CHECK-REOPT: ud2 +# CHECK-REOPT-SAME: BugEntry: 2 + ret +## The return instruction is reachable only via preceding ud2. Test that it is +## treated as a reachable instruction in the Linux kernel mode. + +# CHECK-REOPT-NEXT: ret .size _start, .-_start diff --git a/bolt/test/X86/linux-orc.s b/bolt/test/X86/linux-orc.s index 4da19989408e2458c156c6cc97e95147d1419326..5f2096278e92d6a10c04bb387b74d52833d2a540 100644 --- a/bolt/test/X86/linux-orc.s +++ b/bolt/test/X86/linux-orc.s @@ -27,7 +27,7 @@ ## Verify ORC bindings to instructions. # RUN: llvm-bolt %t.exe --print-normalized --dump-orc --print-orc -o %t.out \ -# RUN: --bolt-info=0 |& FileCheck %s +# RUN: --keep-nops=0 --bolt-info=0 |& FileCheck %s ## Verify ORC bindings after rewrite. @@ -37,7 +37,7 @@ ## Verify ORC binding after rewrite when some of the functions are skipped. -# RUN: llvm-bolt %t.exe -o %t.out --skip-funcs=bar --bolt-info=0 +# RUN: llvm-bolt %t.exe -o %t.out --skip-funcs=bar --bolt-info=0 --keep-nops=0 # RUN: llvm-bolt %t.out -o %t.out.1 --print-normalized --print-orc \ # RUN: |& FileCheck %s diff --git a/bolt/test/X86/linux-parainstructions.s b/bolt/test/X86/linux-parainstructions.s index 4bdfde5fb7f24bf505ae4537b988fa8321d6db20..07fca6bbedafaba54b44106519634d93712dad7e 100644 --- a/bolt/test/X86/linux-parainstructions.s +++ b/bolt/test/X86/linux-parainstructions.s @@ -8,7 +8,7 @@ ## Verify paravirtual bindings to instructions. -# RUN: llvm-bolt %t.exe --print-normalized -o %t.out | FileCheck %s +# RUN: llvm-bolt %t.exe --print-normalized -o %t.out --keep-nops=0 | FileCheck %s # CHECK: BOLT-INFO: Linux kernel binary detected # CHECK: BOLT-INFO: parsed 2 paravirtual patch sites diff --git a/bolt/test/X86/linux-static-keys.s b/bolt/test/X86/linux-static-keys.s new file mode 100644 index 0000000000000000000000000000000000000000..08454bf9763193d2de46005cd470d38f5661a959 --- /dev/null +++ b/bolt/test/X86/linux-static-keys.s @@ -0,0 +1,67 @@ +# REQUIRES: system-linux + +## Check that BOLT correctly updates the Linux kernel static keys jump table. + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o +# RUN: %clang %cflags -nostdlib %t.o -o %t.exe \ +# RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr + +## Verify static keys jump bindings to instructions. + +# RUN: llvm-bolt %t.exe --print-normalized -o %t.out --keep-nops=0 \ +# RUN: --bolt-info=0 |& FileCheck %s + +## Verify the bindings again on the rewritten binary with nops removed. + +# RUN: llvm-bolt %t.out -o %t.out.1 --print-normalized |& FileCheck %s + +# CHECK: BOLT-INFO: Linux kernel binary detected +# CHECK: BOLT-INFO: parsed 2 static keys jump entries + + .text + .globl _start + .type _start, %function +_start: +# CHECK: Binary Function "_start" + nop +.L0: + jmp .L1 +# CHECK: jit +# CHECK-SAME: # ID: 1 {{.*}} # Likely: 0 # InitValue: 1 + nop +.L1: + .nops 5 +# CHECK: jit +# CHECK-SAME: # ID: 2 {{.*}} # Likely: 1 # InitValue: 1 +.L2: + nop + .size _start, .-_start + + .globl foo + .type foo, %function +foo: + ret + .size foo, .-foo + + +## Static keys jump table. + .rodata + .globl __start___jump_table + .type __start___jump_table, %object +__start___jump_table: + + .long .L0 - . # Jump address + .long .L1 - . # Target address + .quad 1 # Key address + + .long .L1 - . # Jump address + .long .L2 - . # Target address + .quad 0 # Key address + + .globl __stop___jump_table + .type __stop___jump_table, %object +__stop___jump_table: + +## Fake Linux Kernel sections. + .section __ksymtab,"a",@progbits + .section __ksymtab_gpl,"a",@progbits diff --git a/bolt/test/X86/reader-stale-yaml.test b/bolt/test/X86/reader-stale-yaml.test index 533ed917c1aeb07f032bb888bac1560da8975c79..f4a8865b1f9a46506ecd068cf4fb0c25d51e0b66 100644 --- a/bolt/test/X86/reader-stale-yaml.test +++ b/bolt/test/X86/reader-stale-yaml.test @@ -14,6 +14,10 @@ RUN: --profile-ignore-hash=1 --profile-use-dfs=0 --debug-only=bolt-prof 2>&1 | RUN: llvm-bolt %t.exe -o %t.null --b %p/Inputs/blarge_profile_stale.yaml \ RUN: --print-cfg --print-only=SolveCubic --infer-stale-profile=1 \ RUN: --profile-ignore-hash=1 --profile-use-dfs=0 --debug-only=bolt-prof 2>&1 | FileCheck %s -check-prefix=CHECK2 +# Testing skipped function +RUN: llvm-bolt %t.exe -o %t.null --b %p/Inputs/blarge_profile_stale.yaml \ +RUN: --print-cfg --print-only=usqrt --infer-stale-profile=1 --skip-funcs=usqrt \ +RUN: --profile-ignore-hash=1 --profile-use-dfs=0 CHECK0: BOLT-INFO: 2 out of 7 functions in the binary (28.6%) have non-empty execution profile CHECK0: BOLT-WARNING: 2 (100.0% of all profiled) functions have invalid (possibly stale) profile diff --git a/bolt/test/X86/yaml-secondary-entry-discriminator.s b/bolt/test/X86/yaml-secondary-entry-discriminator.s new file mode 100644 index 0000000000000000000000000000000000000000..43c2e2a7f05549289293a39808762cc5a68cc285 --- /dev/null +++ b/bolt/test/X86/yaml-secondary-entry-discriminator.s @@ -0,0 +1,74 @@ +# This reproduces a bug with BOLT setting incorrect discriminator for +# secondary entry points in YAML profile. + +# REQUIRES: system-linux +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o +# RUN: link_fdata %s %t.o %t.fdata +# RUN: llvm-strip --strip-unneeded %t.o +# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib +# RUN: llvm-bolt %t.exe -o %t.out --data %t.fdata -w %t.yaml --print-profile \ +# RUN: --print-only=main | FileCheck %s --check-prefix=CHECK-CFG +# RUN: FileCheck %s -input-file %t.yaml +# CHECK: - name: main +# CHECK-NEXT: fid: 2 +# CHECK-NEXT: hash: 0xADF270D550151185 +# CHECK-NEXT: exec: 0 +# CHECK-NEXT: nblocks: 4 +# CHECK-NEXT: blocks: +# CHECK: - bid: 1 +# CHECK-NEXT: insns: 1 +# CHECK-NEXT: hash: 0x36A303CBA4360014 +# CHECK-NEXT: calls: [ { off: 0x0, fid: 1, disc: 1, cnt: 1 } ] +# CHECK: - bid: 2 +# CHECK-NEXT: insns: 5 +# CHECK-NEXT: hash: 0x8B2F5747CD0019 +# CHECK-NEXT: calls: [ { off: 0x0, fid: 1, disc: 1, cnt: 1, mis: 1 } ] + +# Make sure that the profile is attached correctly +# RUN: llvm-bolt %t.exe -o %t.out --data %t.yaml --print-profile \ +# RUN: --print-only=main | FileCheck %s --check-prefix=CHECK-CFG + +# CHECK-CFG: Binary Function "main" after attaching profile { +# CHECK-CFG: callq secondary_entry # Offset: [[#]] # Count: 1 +# CHECK-CFG: callq *%rax # Offset: [[#]] # CallProfile: 1 (1 misses) : +# CHECK-CFG-NEXT: { secondary_entry: 1 (1 misses) } + +.globl func +.type func, @function +func: +# FDATA: 0 [unknown] 0 1 func 0 1 0 + .cfi_startproc + pushq %rbp + movq %rsp, %rbp +.globl secondary_entry +secondary_entry: + popq %rbp + retq + nopl (%rax) + .cfi_endproc + .size func, .-func + +.globl main +.type main, @function +main: + .cfi_startproc + pushq %rbp + movq %rsp, %rbp + subq $16, %rsp + movl $0, -4(%rbp) + testq %rax, %rax + jne Lindcall +Lcall: + call secondary_entry +# FDATA: 1 main #Lcall# 1 secondary_entry 0 1 1 +Lindcall: + callq *%rax +# FDATA: 1 main #Lindcall# 1 secondary_entry 0 1 1 + xorl %eax, %eax + addq $16, %rsp + popq %rbp + retq +# For relocations against .text + call exit + .cfi_endproc + .size main, .-main diff --git a/bolt/tools/bat-dump/bat-dump.cpp b/bolt/tools/bat-dump/bat-dump.cpp index 2e9b26cc137a8621eb2faeebdfca47dbfb031976..709eb076bca2da7976a0e9c6199f1c9c7b9398a6 100644 --- a/bolt/tools/bat-dump/bat-dump.cpp +++ b/bolt/tools/bat-dump/bat-dump.cpp @@ -1,9 +1,16 @@ +//===- bolt/tools/bat-dump/bat-dump.cpp - BAT dumper utility --------------===// +// +// 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 "bolt/Profile/BoltAddressTranslation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/Object/Binary.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/Error.h" @@ -18,7 +25,6 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Program.h" #include "llvm/Support/raw_ostream.h" -#include #include #include #include @@ -27,7 +33,6 @@ #include #include #include -#include using namespace llvm; using namespace bolt; diff --git a/bolt/tools/heatmap/heatmap.cpp b/bolt/tools/heatmap/heatmap.cpp index 9b190dd288b279deb411b63500ef909e4cc667a9..3bb9f2ce7491db6f1dbf08cbb2dec6cdb92b3ea9 100644 --- a/bolt/tools/heatmap/heatmap.cpp +++ b/bolt/tools/heatmap/heatmap.cpp @@ -1,4 +1,11 @@ -#include "bolt/Profile/DataAggregator.h" +//===- bolt/tools/heatmap/heatmap.cpp - Profile heatmap visualization tool ===// +// +// 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 "bolt/Rewrite/RewriteInstance.h" #include "bolt/Utils/CommandLineOpts.h" #include "llvm/MC/TargetRegistry.h" @@ -6,7 +13,8 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Errc.h" #include "llvm/Support/Error.h" -#include "llvm/Support/Path.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Program.h" #include "llvm/Support/TargetSelect.h" using namespace llvm; diff --git a/bolt/unittests/Core/BinaryContext.cpp b/bolt/unittests/Core/BinaryContext.cpp index 08619eccdd75ab765db3951a565466218313b64d..cfec72a34a59f24eebaf3e09b8de13e3794c8e20 100644 --- a/bolt/unittests/Core/BinaryContext.cpp +++ b/bolt/unittests/Core/BinaryContext.cpp @@ -1,7 +1,14 @@ +//===- bolt/unittest/Core/BinaryContext.cpp -------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + #include "bolt/Core/BinaryContext.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" -#include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/TargetSelect.h" #include "gtest/gtest.h" @@ -40,8 +47,8 @@ protected: void initializeBOLT() { BC = cantFail(BinaryContext::createBinaryContext( - ObjFile.get(), true, DWARFContext::create(*ObjFile.get()), - {llvm::outs(), llvm::errs()})); + ObjFile->makeTriple(), ObjFile->getFileName(), nullptr, true, + DWARFContext::create(*ObjFile.get()), {llvm::outs(), llvm::errs()})); ASSERT_FALSE(!BC); } diff --git a/bolt/unittests/Core/MCPlusBuilder.cpp b/bolt/unittests/Core/MCPlusBuilder.cpp index 63448039c53e677e33bdb2e7f4472f22e297a748..62f3aaab4a725cbcfcfb445bc44ffc001152fc70 100644 --- a/bolt/unittests/Core/MCPlusBuilder.cpp +++ b/bolt/unittests/Core/MCPlusBuilder.cpp @@ -1,3 +1,11 @@ +//===- bolt/unittest/Core/MCPlusBuilder.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 +// +//===----------------------------------------------------------------------===// + #ifdef AARCH64_AVAILABLE #include "AArch64Subtarget.h" #endif // AARCH64_AVAILABLE @@ -11,7 +19,6 @@ #include "bolt/Rewrite/RewriteInstance.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" -#include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/TargetSelect.h" #include "gtest/gtest.h" @@ -50,8 +57,8 @@ protected: void initializeBolt() { BC = cantFail(BinaryContext::createBinaryContext( - ObjFile.get(), true, DWARFContext::create(*ObjFile.get()), - {llvm::outs(), llvm::errs()})); + ObjFile->makeTriple(), ObjFile->getFileName(), nullptr, true, + DWARFContext::create(*ObjFile.get()), {llvm::outs(), llvm::errs()})); ASSERT_FALSE(!BC); BC->initializeTarget(std::unique_ptr( createMCPlusBuilder(GetParam(), BC->MIA.get(), BC->MII.get(), @@ -134,9 +141,8 @@ TEST_P(MCPlusBuilderTester, ReplaceRegWithImm) { TEST_P(MCPlusBuilderTester, Annotation) { MCInst Inst; - bool Success = BC->MIB->createTailCall(Inst, BC->Ctx->createNamedTempSymbol(), - BC->Ctx.get()); - ASSERT_TRUE(Success); + BC->MIB->createTailCall(Inst, BC->Ctx->createNamedTempSymbol(), + BC->Ctx.get()); MCSymbol *LPSymbol = BC->Ctx->createNamedTempSymbol("LP"); uint64_t Value = INT32_MIN; // Test encodeAnnotationImm using this indirect way @@ -151,9 +157,8 @@ TEST_P(MCPlusBuilderTester, Annotation) { // Large int64 should trigger an out of range assertion Value = 0x1FF'FFFF'FFFF'FFFFULL; Inst.clear(); - Success = BC->MIB->createTailCall(Inst, BC->Ctx->createNamedTempSymbol(), - BC->Ctx.get()); - ASSERT_TRUE(Success); + BC->MIB->createTailCall(Inst, BC->Ctx->createNamedTempSymbol(), + BC->Ctx.get()); ASSERT_DEATH(BC->MIB->addEHInfo(Inst, MCPlus::MCLandingPad(LPSymbol, Value)), "annotation value out of range"); } diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index 40ac6918faf40786b1add8fb16e1c5933d76ca2e..b877ea06dc05cd78b5536155efb25afa4ae32906 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -233,7 +233,7 @@ public: if (!tooling::applyAllReplacements(Replacements.get(), Rewrite)) { llvm::errs() << "Can't apply replacements for file " << File << "\n"; } - AnyNotWritten &= Rewrite.overwriteChangedFiles(); + AnyNotWritten |= Rewrite.overwriteChangedFiles(); } if (AnyNotWritten) { diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp index e518a64abc52eb30a60d127fdd2cf4da77a26077..2931325d8b57981fc097fb19a3f6cfbc0746ad54 100644 --- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp @@ -73,6 +73,7 @@ #include "SuspiciousReallocUsageCheck.h" #include "SuspiciousSemicolonCheck.h" #include "SuspiciousStringCompareCheck.h" +#include "SuspiciousStringviewDataUsageCheck.h" #include "SwappedArgumentsCheck.h" #include "SwitchMissingDefaultCaseCheck.h" #include "TerminatingContinueCheck.h" @@ -218,6 +219,8 @@ public: "bugprone-suspicious-semicolon"); CheckFactories.registerCheck( "bugprone-suspicious-string-compare"); + CheckFactories.registerCheck( + "bugprone-suspicious-stringview-data-usage"); CheckFactories.registerCheck( "bugprone-swapped-arguments"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt index 638fba03a4358795cb1fb75384d250f2f527c239..081ba67efe1538e3378e53a1f7718299a650d4e7 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt @@ -26,6 +26,7 @@ add_clang_library(clangTidyBugproneModule ImplicitWideningOfMultiplicationResultCheck.cpp InaccurateEraseCheck.cpp IncorrectEnableIfCheck.cpp + SuspiciousStringviewDataUsageCheck.cpp SwitchMissingDefaultCaseCheck.cpp IncDecInConditionsCheck.cpp IncorrectRoundingsCheck.cpp diff --git a/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp index 16f43128d55e87ed43a0f16a227bc16a07297959..9b3b01eb02683324d16ee91050116332c9281a1f 100644 --- a/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp @@ -31,6 +31,10 @@ void IncDecInConditionsCheck::registerMatchers(MatchFinder *Finder) { anyOf(binaryOperator(anyOf(isComparisonOperator(), isLogicalOperator())), cxxOperatorCallExpr(isComparisonOperator()))); + auto IsInUnevaluatedContext = + expr(anyOf(hasAncestor(expr(matchers::hasUnevaluatedContext())), + hasAncestor(typeLoc()))); + Finder->addMatcher( expr( OperatorMatcher, unless(isExpansionInSystemHeader()), @@ -42,12 +46,14 @@ void IncDecInConditionsCheck::registerMatchers(MatchFinder *Finder) { cxxOperatorCallExpr( isPrePostOperator(), hasUnaryOperand(expr().bind("operand")))), + unless(IsInUnevaluatedContext), hasAncestor( expr(equalsBoundNode("parent"), hasDescendant( expr(unless(equalsBoundNode("operand")), matchers::isStatementIdenticalToBoundNode( - "operand")) + "operand"), + unless(IsInUnevaluatedContext)) .bind("second"))))) .bind("operator"))), this); diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringviewDataUsageCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringviewDataUsageCheck.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8f4b0c5e0dceda03489131fe99b57fc7731640a2 --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringviewDataUsageCheck.cpp @@ -0,0 +1,97 @@ +//===--- SuspiciousStringviewDataUsageCheck.cpp - clang-tidy --------------===// +// +// 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 "SuspiciousStringviewDataUsageCheck.h" +#include "../utils/Matchers.h" +#include "../utils/OptionsUtils.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::bugprone { + +SuspiciousStringviewDataUsageCheck::SuspiciousStringviewDataUsageCheck( + StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + StringViewTypes(utils::options::parseStringList(Options.get( + "StringViewTypes", "::std::basic_string_view;::llvm::StringRef"))), + AllowedCallees( + utils::options::parseStringList(Options.get("AllowedCallees", ""))) {} + +void SuspiciousStringviewDataUsageCheck::storeOptions( + ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "StringViewTypes", + utils::options::serializeStringList(StringViewTypes)); + Options.store(Opts, "AllowedCallees", + utils::options::serializeStringList(AllowedCallees)); +} + +bool SuspiciousStringviewDataUsageCheck::isLanguageVersionSupported( + const LangOptions &LangOpts) const { + return LangOpts.CPlusPlus; +} + +std::optional +SuspiciousStringviewDataUsageCheck::getCheckTraversalKind() const { + return TK_AsIs; +} + +void SuspiciousStringviewDataUsageCheck::registerMatchers(MatchFinder *Finder) { + + auto AncestorCall = anyOf( + cxxConstructExpr(), callExpr(unless(cxxOperatorCallExpr())), lambdaExpr(), + initListExpr( + hasType(qualType(hasCanonicalType(hasDeclaration(recordDecl())))))); + + auto DataMethod = + cxxMethodDecl(hasName("data"), + ofClass(matchers::matchesAnyListedName(StringViewTypes))); + + auto SizeCall = cxxMemberCallExpr( + callee(cxxMethodDecl(hasAnyName("size", "length"))), + on(ignoringParenImpCasts( + matchers::isStatementIdenticalToBoundNode("self")))); + + auto DescendantSizeCall = expr(hasDescendant( + expr(SizeCall, hasAncestor(expr(AncestorCall).bind("ancestor-size")), + hasAncestor(expr(equalsBoundNode("parent"), + equalsBoundNode("ancestor-size")))))); + + Finder->addMatcher( + cxxMemberCallExpr( + on(ignoringParenImpCasts(expr().bind("self"))), callee(DataMethod), + expr().bind("data-call"), + hasParent(expr(anyOf( + invocation( + expr().bind("parent"), unless(cxxOperatorCallExpr()), + hasAnyArgument( + ignoringParenImpCasts(equalsBoundNode("data-call"))), + unless(hasAnyArgument(ignoringParenImpCasts(SizeCall))), + unless(hasAnyArgument(DescendantSizeCall)), + hasDeclaration(namedDecl( + unless(matchers::matchesAnyListedName(AllowedCallees))))), + initListExpr(expr().bind("parent"), + hasType(qualType(hasCanonicalType(hasDeclaration( + recordDecl(unless(matchers::matchesAnyListedName( + AllowedCallees))))))), + unless(DescendantSizeCall)))))), + this); +} + +void SuspiciousStringviewDataUsageCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *DataCallExpr = + Result.Nodes.getNodeAs("data-call"); + diag(DataCallExpr->getExprLoc(), + "result of a `data()` call may not be null terminated, provide size " + "information to the callee to prevent potential issues") + << DataCallExpr->getCallee()->getSourceRange(); +} + +} // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringviewDataUsageCheck.h b/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringviewDataUsageCheck.h new file mode 100644 index 0000000000000000000000000000000000000000..31eca0a48722fedf5ede59c1b4ef8e9030f021af --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringviewDataUsageCheck.h @@ -0,0 +1,38 @@ +//===--- SuspiciousStringviewDataUsageCheck.h - clang-tidy -------//C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSSTRINGVIEWDATAUSAGECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSSTRINGVIEWDATAUSAGECHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::bugprone { + +/// Identifies suspicious usages of std::string_view::data() that could lead to +/// reading out-of-bounds data due to inadequate or incorrect string null +/// termination. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/suspicious-stringview-data-usage.html +class SuspiciousStringviewDataUsageCheck : public ClangTidyCheck { +public: + SuspiciousStringviewDataUsageCheck(StringRef Name, ClangTidyContext *Context); + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override; + std::optional getCheckTraversalKind() const override; + +private: + std::vector StringViewTypes; + std::vector AllowedCallees; +}; + +} // namespace clang::tidy::bugprone + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSSTRINGVIEWDATAUSAGECHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp index 243fe47c2036b6c3104c8e419c070a591b8fcc7f..73373147e96fc9efb091c2f66aa1f49544db6ed0 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp @@ -31,9 +31,16 @@ AST_MATCHER_P(FunctionDecl, isInstantiatedFrom, Matcher, Finder, Builder); } -AST_MATCHER_P(CXXMethodDecl, isOperatorOverloading, - llvm::SmallVector, Kinds) { - return llvm::is_contained(Kinds, Node.getOverloadedOperator()); +constexpr std::initializer_list + AssignmentOverloadedOperatorKinds = { + OO_Equal, OO_PlusEqual, OO_MinusEqual, OO_StarEqual, + OO_SlashEqual, OO_PercentEqual, OO_CaretEqual, OO_AmpEqual, + OO_PipeEqual, OO_LessLessEqual, OO_GreaterGreaterEqual, OO_PlusPlus, + OO_MinusMinus}; + +AST_MATCHER(FunctionDecl, isAssignmentOverloadedOperator) { + return llvm::is_contained(AssignmentOverloadedOperatorKinds, + Node.getOverloadedOperator()); } } // namespace @@ -164,22 +171,18 @@ void UnusedReturnValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { } void UnusedReturnValueCheck::registerMatchers(MatchFinder *Finder) { - auto MatchedDirectCallExpr = expr( - callExpr( - callee(functionDecl( - // Don't match void overloads of checked functions. - unless(returns(voidType())), - // Don't match copy or move assignment operator. - unless(cxxMethodDecl(isOperatorOverloading( - {OO_Equal, OO_PlusEqual, OO_MinusEqual, OO_StarEqual, - OO_SlashEqual, OO_PercentEqual, OO_CaretEqual, OO_AmpEqual, - OO_PipeEqual, OO_LessLessEqual, OO_GreaterGreaterEqual}))), - anyOf( - isInstantiatedFrom( - matchers::matchesAnyListedName(CheckedFunctions)), - returns(hasCanonicalType(hasDeclaration(namedDecl( - matchers::matchesAnyListedName(CheckedReturnTypes))))))))) - .bind("match")); + auto MatchedDirectCallExpr = + expr(callExpr(callee(functionDecl( + // Don't match copy or move assignment operator. + unless(isAssignmentOverloadedOperator()), + // Don't match void overloads of checked functions. + unless(returns(voidType())), + anyOf(isInstantiatedFrom(matchers::matchesAnyListedName( + CheckedFunctions)), + returns(hasCanonicalType(hasDeclaration( + namedDecl(matchers::matchesAnyListedName( + CheckedReturnTypes))))))))) + .bind("match")); auto CheckCastToVoid = AllowCastToVoid ? castExpr(unless(hasCastKind(CK_ToVoid))) : castExpr(); diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp index 9215b833573afddbbf8c7e9123868aaa62f3c3ed..9b4d2ef99e5bf1a2d877d7b328f69c1c2ae446c4 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp @@ -19,6 +19,17 @@ using namespace clang::ast_matchers::internal; namespace clang::tidy::cppcoreguidelines { +namespace { +AST_MATCHER_P(LambdaExpr, hasCallOperator, Matcher, + InnerMatcher) { + return InnerMatcher.matches(*Node.getCallOperator(), Finder, Builder); +} + +AST_MATCHER_P(LambdaExpr, hasLambdaBody, Matcher, InnerMatcher) { + return InnerMatcher.matches(*Node.getBody(), Finder, Builder); +} +} // namespace + void OwningMemoryCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "LegacyResourceProducers", LegacyResourceProducers); Options.store(Opts, "LegacyResourceConsumers", LegacyResourceConsumers); @@ -55,6 +66,8 @@ void OwningMemoryCheck::registerMatchers(MatchFinder *Finder) { CreatesLegacyOwner, LegacyOwnerCast); const auto ConsideredOwner = eachOf(IsOwnerType, CreatesOwner); + const auto ScopeDeclaration = anyOf(translationUnitDecl(), namespaceDecl(), + recordDecl(), functionDecl()); // Find delete expressions that delete non-owners. Finder->addMatcher( @@ -144,13 +157,51 @@ void OwningMemoryCheck::registerMatchers(MatchFinder *Finder) { .bind("bad_owner_creation_parameter"))), this); + auto IsNotInSubLambda = stmt( + hasAncestor( + stmt(anyOf(equalsBoundNode("body"), lambdaExpr())).bind("scope")), + hasAncestor(stmt(equalsBoundNode("scope"), equalsBoundNode("body")))); + // Matching on functions, that return an owner/resource, but don't declare // their return type as owner. Finder->addMatcher( - functionDecl(hasDescendant(returnStmt(hasReturnValue(ConsideredOwner)) - .bind("bad_owner_return")), - unless(returns(qualType(hasDeclaration(OwnerDecl))))) - .bind("function_decl"), + functionDecl( + decl().bind("function_decl"), + hasBody( + stmt(stmt().bind("body"), + hasDescendant( + returnStmt(hasReturnValue(ConsideredOwner), + // Ignore sub-lambda expressions + IsNotInSubLambda, + // Ignore sub-functions + hasAncestor(functionDecl().bind("context")), + hasAncestor(functionDecl( + equalsBoundNode("context"), + equalsBoundNode("function_decl")))) + .bind("bad_owner_return")))), + returns(qualType(unless(hasDeclaration(OwnerDecl))).bind("result"))), + this); + + // Matching on lambdas, that return an owner/resource, but don't declare + // their return type as owner. + Finder->addMatcher( + lambdaExpr( + hasAncestor(decl(ScopeDeclaration).bind("scope-decl")), + hasLambdaBody( + stmt(stmt().bind("body"), + hasDescendant( + returnStmt( + hasReturnValue(ConsideredOwner), + // Ignore sub-lambdas + IsNotInSubLambda, + // Ignore sub-functions + hasAncestor(decl(ScopeDeclaration).bind("context")), + hasAncestor(decl(equalsBoundNode("context"), + equalsBoundNode("scope-decl")))) + .bind("bad_owner_return")))), + hasCallOperator(returns( + qualType(unless(hasDeclaration(OwnerDecl))).bind("result")))) + .bind("lambda"), this); // Match on classes that have an owner as member, but don't declare a @@ -329,7 +380,7 @@ bool OwningMemoryCheck::handleReturnValues(const BoundNodes &Nodes) { // Function return statements, that are owners/resources, but the function // declaration does not declare its return value as owner. const auto *BadReturnType = Nodes.getNodeAs("bad_owner_return"); - const auto *Function = Nodes.getNodeAs("function_decl"); + const auto *ResultType = Nodes.getNodeAs("result"); // Function return values, that should be owners but aren't. if (BadReturnType) { @@ -338,8 +389,9 @@ bool OwningMemoryCheck::handleReturnValues(const BoundNodes &Nodes) { diag(BadReturnType->getBeginLoc(), "returning a newly created resource of " "type %0 or 'gsl::owner<>' from a " - "function whose return type is not 'gsl::owner<>'") - << Function->getReturnType() << BadReturnType->getSourceRange(); + "%select{function|lambda}1 whose return type is not 'gsl::owner<>'") + << *ResultType << (Nodes.getNodeAs("lambda") != nullptr) + << BadReturnType->getSourceRange(); // FIXME: Rewrite the return type as 'gsl::owner' return true; diff --git a/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.cpp b/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.cpp index ef511e9108f2ee957c9ff466fc8aa069b137312b..359d8efd100bad9bdbfe369afec099a20f87834d 100644 --- a/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.cpp @@ -40,6 +40,34 @@ namespace { AST_MATCHER(FunctionDecl, isUserDefineLiteral) { return Node.getLiteralIdentifier() != nullptr; } + +AST_MATCHER(TypeLoc, isValidAndNotInMacro) { + const SourceLocation Loc = Node.getBeginLoc(); + return Loc.isValid() && !Loc.isMacroID(); +} + +AST_MATCHER(TypeLoc, isBuiltinType) { + TypeLoc TL = Node; + if (auto QualLoc = Node.getAs()) + TL = QualLoc.getUnqualifiedLoc(); + + const auto BuiltinLoc = TL.getAs(); + if (!BuiltinLoc) + return false; + + switch (BuiltinLoc.getTypePtr()->getKind()) { + case BuiltinType::Short: + case BuiltinType::Long: + case BuiltinType::LongLong: + case BuiltinType::UShort: + case BuiltinType::ULong: + case BuiltinType::ULongLong: + return true; + default: + return false; + } +} + } // namespace namespace tidy::google::runtime { @@ -63,11 +91,11 @@ void IntegerTypesCheck::registerMatchers(MatchFinder *Finder) { // "Where possible, avoid passing arguments of types specified by // bitwidth typedefs to printf-based APIs." Finder->addMatcher( - typeLoc(loc(isInteger()), - unless(anyOf(hasAncestor(callExpr( - callee(functionDecl(hasAttr(attr::Format))))), - hasParent(parmVarDecl(hasAncestor( - functionDecl(isUserDefineLiteral()))))))) + typeLoc(loc(isInteger()), isValidAndNotInMacro(), isBuiltinType(), + unless(hasAncestor( + callExpr(callee(functionDecl(hasAttr(attr::Format)))))), + unless(hasParent(parmVarDecl( + hasAncestor(functionDecl(isUserDefineLiteral())))))) .bind("tl"), this); IdentTable = std::make_unique(getLangOpts()); @@ -77,9 +105,6 @@ void IntegerTypesCheck::check(const MatchFinder::MatchResult &Result) { auto TL = *Result.Nodes.getNodeAs("tl"); SourceLocation Loc = TL.getBeginLoc(); - if (Loc.isInvalid() || Loc.isMacroID()) - return; - // Look through qualification. if (auto QualLoc = TL.getAs()) TL = QualLoc.getUnqualifiedLoc(); diff --git a/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h b/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h index 3be7d24021b9ffcbc25f35321d3af2a6d9f05a76..c62bda67ae2d987d68dc7cb1dc78b506e0ac6f63 100644 --- a/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h +++ b/clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h @@ -35,6 +35,9 @@ public: void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + std::optional getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } private: const StringRef UnsignedTypePrefix; diff --git a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp index bb05f206c717cea3a4c2067e7473d4a30dccdc12..24eefdb082eb32ad2c0195030d1e1d3f10f2af67 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp @@ -8,6 +8,7 @@ #include "UseUsingCheck.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/DeclGroup.h" #include "clang/Lex/Lexer.h" using namespace clang::ast_matchers; @@ -24,6 +25,7 @@ static constexpr llvm::StringLiteral ExternCDeclName = "extern-c-decl"; static constexpr llvm::StringLiteral ParentDeclName = "parent-decl"; static constexpr llvm::StringLiteral TagDeclName = "tag-decl"; static constexpr llvm::StringLiteral TypedefName = "typedef"; +static constexpr llvm::StringLiteral DeclStmtName = "decl-stmt"; UseUsingCheck::UseUsingCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), @@ -41,7 +43,8 @@ void UseUsingCheck::registerMatchers(MatchFinder *Finder) { unless(isInstantiated()), optionally(hasAncestor( linkageSpecDecl(isExternCLinkage()).bind(ExternCDeclName))), - hasParent(decl().bind(ParentDeclName))) + anyOf(hasParent(decl().bind(ParentDeclName)), + hasParent(declStmt().bind(DeclStmtName)))) .bind(TypedefName), this); @@ -51,17 +54,32 @@ void UseUsingCheck::registerMatchers(MatchFinder *Finder) { tagDecl( anyOf(allOf(unless(anyOf(isImplicit(), classTemplateSpecializationDecl())), - hasParent(decl().bind(ParentDeclName))), + anyOf(hasParent(decl().bind(ParentDeclName)), + hasParent(declStmt().bind(DeclStmtName)))), // We want the parent of the ClassTemplateDecl, not the parent // of the specialization. classTemplateSpecializationDecl(hasAncestor(classTemplateDecl( - hasParent(decl().bind(ParentDeclName))))))) + anyOf(hasParent(decl().bind(ParentDeclName)), + hasParent(declStmt().bind(DeclStmtName)))))))) .bind(TagDeclName), this); } void UseUsingCheck::check(const MatchFinder::MatchResult &Result) { const auto *ParentDecl = Result.Nodes.getNodeAs(ParentDeclName); + + if (!ParentDecl) { + const auto *ParentDeclStmt = Result.Nodes.getNodeAs(DeclStmtName); + if (ParentDeclStmt) { + if (ParentDeclStmt->isSingleDecl()) + ParentDecl = ParentDeclStmt->getSingleDecl(); + else + ParentDecl = + ParentDeclStmt->getDeclGroup().getDeclGroup() + [ParentDeclStmt->getDeclGroup().getDeclGroup().size() - 1]; + } + } + if (!ParentDecl) return; diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt index 5728c9970fb65d5334225cce3d3db69e013bdf62..dd772d692025481a9eae7475168f96ec29baf6fe 100644 --- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt @@ -17,6 +17,7 @@ add_clang_library(clangTidyReadabilityModule DeleteNullPointerCheck.cpp DuplicateIncludeCheck.cpp ElseAfterReturnCheck.cpp + EnumInitialValueCheck.cpp FunctionCognitiveComplexityCheck.cpp FunctionSizeCheck.cpp IdentifierLengthCheck.cpp diff --git a/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8f2841c32259a254a9b2821e6382e6b51714e177 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp @@ -0,0 +1,200 @@ +//===--- EnumInitialValueCheck.cpp - clang-tidy ---------------------------===// +// +// 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 "EnumInitialValueCheck.h" +#include "../utils/LexerUtils.h" +#include "clang/AST/Decl.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +static bool isNoneEnumeratorsInitialized(const EnumDecl &Node) { + return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) { + return ECD->getInitExpr() == nullptr; + }); +} + +static bool isOnlyFirstEnumeratorInitialized(const EnumDecl &Node) { + bool IsFirst = true; + for (const EnumConstantDecl *ECD : Node.enumerators()) { + if ((IsFirst && ECD->getInitExpr() == nullptr) || + (!IsFirst && ECD->getInitExpr() != nullptr)) + return false; + IsFirst = false; + } + return !IsFirst; +} + +static bool areAllEnumeratorsInitialized(const EnumDecl &Node) { + return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) { + return ECD->getInitExpr() != nullptr; + }); +} + +/// Check if \p Enumerator is initialized with a (potentially negated) \c +/// IntegerLiteral. +static bool isInitializedByLiteral(const EnumConstantDecl *Enumerator) { + const Expr *const Init = Enumerator->getInitExpr(); + if (!Init) + return false; + return Init->isIntegerConstantExpr(Enumerator->getASTContext()); +} + +static void cleanInitialValue(DiagnosticBuilder &Diag, + const EnumConstantDecl *ECD, + const SourceManager &SM, + const LangOptions &LangOpts) { + const SourceRange InitExprRange = ECD->getInitExpr()->getSourceRange(); + if (InitExprRange.isInvalid() || InitExprRange.getBegin().isMacroID() || + InitExprRange.getEnd().isMacroID()) + return; + std::optional EqualToken = utils::lexer::findNextTokenSkippingComments( + ECD->getLocation(), SM, LangOpts); + if (!EqualToken.has_value() || + EqualToken.value().getKind() != tok::TokenKind::equal) + return; + const SourceLocation EqualLoc{EqualToken->getLocation()}; + if (EqualLoc.isInvalid() || EqualLoc.isMacroID()) + return; + Diag << FixItHint::CreateRemoval(EqualLoc) + << FixItHint::CreateRemoval(InitExprRange); + return; +} + +namespace { + +AST_MATCHER(EnumDecl, isMacro) { + SourceLocation Loc = Node.getBeginLoc(); + return Loc.isMacroID(); +} + +AST_MATCHER(EnumDecl, hasConsistentInitialValues) { + return isNoneEnumeratorsInitialized(Node) || + isOnlyFirstEnumeratorInitialized(Node) || + areAllEnumeratorsInitialized(Node); +} + +AST_MATCHER(EnumDecl, hasZeroInitialValueForFirstEnumerator) { + const EnumDecl::enumerator_range Enumerators = Node.enumerators(); + if (Enumerators.empty()) + return false; + const EnumConstantDecl *ECD = *Enumerators.begin(); + return isOnlyFirstEnumeratorInitialized(Node) && + isInitializedByLiteral(ECD) && ECD->getInitVal().isZero(); +} + +/// Excludes bitfields because enumerators initialized with the result of a +/// bitwise operator on enumeration values or any other expr that is not a +/// potentially negative integer literal. +/// Enumerations where it is not directly clear if they are used with +/// bitmask, evident when enumerators are only initialized with (potentially +/// negative) integer literals, are ignored. This is also the case when all +/// enumerators are powers of two (e.g., 0, 1, 2). +AST_MATCHER(EnumDecl, hasSequentialInitialValues) { + const EnumDecl::enumerator_range Enumerators = Node.enumerators(); + if (Enumerators.empty()) + return false; + const EnumConstantDecl *const FirstEnumerator = *Node.enumerator_begin(); + llvm::APSInt PrevValue = FirstEnumerator->getInitVal(); + if (!isInitializedByLiteral(FirstEnumerator)) + return false; + bool AllEnumeratorsArePowersOfTwo = true; + for (const EnumConstantDecl *Enumerator : llvm::drop_begin(Enumerators)) { + const llvm::APSInt NewValue = Enumerator->getInitVal(); + if (NewValue != ++PrevValue) + return false; + if (!isInitializedByLiteral(Enumerator)) + return false; + PrevValue = NewValue; + AllEnumeratorsArePowersOfTwo &= NewValue.isPowerOf2(); + } + return !AllEnumeratorsArePowersOfTwo; +} + +} // namespace + +EnumInitialValueCheck::EnumInitialValueCheck(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + AllowExplicitZeroFirstInitialValue( + Options.get("AllowExplicitZeroFirstInitialValue", true)), + AllowExplicitSequentialInitialValues( + Options.get("AllowExplicitSequentialInitialValues", true)) {} + +void EnumInitialValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "AllowExplicitZeroFirstInitialValue", + AllowExplicitZeroFirstInitialValue); + Options.store(Opts, "AllowExplicitSequentialInitialValues", + AllowExplicitSequentialInitialValues); +} + +void EnumInitialValueCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + enumDecl(unless(isMacro()), unless(hasConsistentInitialValues())) + .bind("inconsistent"), + this); + if (!AllowExplicitZeroFirstInitialValue) + Finder->addMatcher( + enumDecl(hasZeroInitialValueForFirstEnumerator()).bind("zero_first"), + this); + if (!AllowExplicitSequentialInitialValues) + Finder->addMatcher(enumDecl(unless(isMacro()), hasSequentialInitialValues()) + .bind("sequential"), + this); +} + +void EnumInitialValueCheck::check(const MatchFinder::MatchResult &Result) { + if (const auto *Enum = Result.Nodes.getNodeAs("inconsistent")) { + DiagnosticBuilder Diag = + diag(Enum->getBeginLoc(), + "inital values in enum %0 are not consistent, consider explicit " + "initialization of all, none or only the first enumerator") + << Enum; + for (const EnumConstantDecl *ECD : Enum->enumerators()) + if (ECD->getInitExpr() == nullptr) { + const SourceLocation EndLoc = Lexer::getLocForEndOfToken( + ECD->getLocation(), 0, *Result.SourceManager, getLangOpts()); + if (EndLoc.isMacroID()) + continue; + llvm::SmallString<8> Str{" = "}; + ECD->getInitVal().toString(Str); + Diag << FixItHint::CreateInsertion(EndLoc, Str); + } + return; + } + + if (const auto *Enum = Result.Nodes.getNodeAs("zero_first")) { + const EnumConstantDecl *ECD = *Enum->enumerator_begin(); + const SourceLocation Loc = ECD->getLocation(); + if (Loc.isInvalid() || Loc.isMacroID()) + return; + DiagnosticBuilder Diag = diag(Loc, "zero initial value for the first " + "enumerator in %0 can be disregarded") + << Enum; + cleanInitialValue(Diag, ECD, *Result.SourceManager, getLangOpts()); + return; + } + if (const auto *Enum = Result.Nodes.getNodeAs("sequential")) { + DiagnosticBuilder Diag = + diag(Enum->getBeginLoc(), + "sequential initial value in %0 can be ignored") + << Enum; + for (const EnumConstantDecl *ECD : llvm::drop_begin(Enum->enumerators())) + cleanInitialValue(Diag, ECD, *Result.SourceManager, getLangOpts()); + return; + } +} + +} // namespace clang::tidy::readability diff --git a/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.h b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.h new file mode 100644 index 0000000000000000000000000000000000000000..66087e4ee170da955c43bfa6cb553a092442705b --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.h @@ -0,0 +1,38 @@ +//===--- EnumInitialValueCheck.h - clang-tidy -------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_ENUMINITIALVALUECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_ENUMINITIALVALUECHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::readability { + +/// Enforces consistent style for enumerators' initialization, covering three +/// styles: none, first only, or all initialized explicitly. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/readability/enum-initial-value.html +class EnumInitialValueCheck : public ClangTidyCheck { +public: + EnumInitialValueCheck(StringRef Name, ClangTidyContext *Context); + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + std::optional getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } + +private: + const bool AllowExplicitZeroFirstInitialValue; + const bool AllowExplicitSequentialInitialValues; +}; + +} // namespace clang::tidy::readability + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_ENUMINITIALVALUECHECK_H diff --git a/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp b/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp index 4f02950e7794cbea6f4a1249da136e7193acd399..74152c6034510b9e4b881c6c4e00ec20ca821c09 100644 --- a/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp @@ -81,8 +81,7 @@ void fixGenericExprCastToBool(DiagnosticBuilder &Diag, const Expr *SubExpr = Cast->getSubExpr(); - bool NeedInnerParens = - SubExpr != nullptr && utils::fixit::areParensNeededForStatement(*SubExpr); + bool NeedInnerParens = utils::fixit::areParensNeededForStatement(*SubExpr); bool NeedOuterParens = Parent != nullptr && utils::fixit::areParensNeededForStatement(*Parent); diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp index bca2c425111f6cd1594316ca05971d290dbf1062..376b84683df74e4e8880431b58a70220b600e486 100644 --- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -22,6 +22,7 @@ #include "DeleteNullPointerCheck.h" #include "DuplicateIncludeCheck.h" #include "ElseAfterReturnCheck.h" +#include "EnumInitialValueCheck.h" #include "FunctionCognitiveComplexityCheck.h" #include "FunctionSizeCheck.h" #include "IdentifierLengthCheck.h" @@ -92,6 +93,8 @@ public: "readability-duplicate-include"); CheckFactories.registerCheck( "readability-else-after-return"); + CheckFactories.registerCheck( + "readability-enum-initial-value"); CheckFactories.registerCheck( "readability-function-cognitive-complexity"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h b/clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h index c28087e07e9b61f55a048c4b533c9045b44c9fe6..620cd6e3f2f8779792ddec763a7d636234217698 100644 --- a/clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h +++ b/clang-tools-extra/clang-tidy/readability/StaticDefinitionInAnonymousNamespaceCheck.h @@ -24,6 +24,12 @@ public: : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus; + } + std::optional getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } }; } // namespace clang::tidy::readability diff --git a/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp b/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp index b6d9c50d0b109c1c24323e304500165a607287d3..a44720c47eca2d7eb9ef815d7cea3dc18a44c616 100644 --- a/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp +++ b/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp @@ -108,7 +108,7 @@ int compareHeaders(StringRef LHS, StringRef RHS, IncludeSorter::IncludeStyle Style) { if (Style == IncludeSorter::IncludeStyle::IS_Google_ObjC) { const std::pair &Mismatch = - std::mismatch(LHS.begin(), LHS.end(), RHS.begin()); + std::mismatch(LHS.begin(), LHS.end(), RHS.begin(), RHS.end()); if ((Mismatch.first != LHS.end()) && (Mismatch.second != RHS.end())) { if ((*Mismatch.first == '.') && (*Mismatch.second == '+')) { return -1; diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp index f29dadde2b86d5a20d542e0c6812d42ba2be1910..7fd599d4e1a0b0e393ee6a36291955496073f12e 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -1390,7 +1390,7 @@ void ClangdLSPServer::onClangdInlayHints(const InlayHintsParams &Params, // Extension doesn't have paddingLeft/Right so adjust the label // accordingly. {"label", - ((Hint.paddingLeft ? " " : "") + llvm::StringRef(Hint.label) + + ((Hint.paddingLeft ? " " : "") + llvm::StringRef(Hint.joinLabels()) + (Hint.paddingRight ? " " : "")) .str()}, }); diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 036eb9808ea082be28229e849382927522b47fbd..9e321dce4c5041901ef21708b2366f2722514b7a 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -619,7 +619,8 @@ private: } // 'CompletionItemKind::Interface' matches template type aliases. if (Completion.Kind == CompletionItemKind::Interface || - Completion.Kind == CompletionItemKind::Class) { + Completion.Kind == CompletionItemKind::Class || + Completion.Kind == CompletionItemKind::Variable) { if (Snippet->front() != '<') return *Snippet; // Not an arg snippet? diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index a0ebc631ef8285ad37ac5da70df63bb3152494f7..cd4f1931b3ce1dabd27195366c66349f0ff01cf0 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -977,8 +977,9 @@ private: return; bool PadLeft = Prefix.consume_front(" "); bool PadRight = Suffix.consume_back(" "); - Results.push_back(InlayHint{LSPPos, (Prefix + Label + Suffix).str(), Kind, - PadLeft, PadRight, LSPRange}); + Results.push_back(InlayHint{LSPPos, + /*label=*/{(Prefix + Label + Suffix).str()}, + Kind, PadLeft, PadRight, LSPRange}); } // Get the range of the main file that *exactly* corresponds to R. diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp index c6553e00dcae28209da96ff0eb6a7dd2288d008f..c08f80442eaa0605c1a7513ace13cb57032518c3 100644 --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -1501,6 +1501,10 @@ bool operator<(const InlayHint &A, const InlayHint &B) { return std::tie(A.position, A.range, A.kind, A.label) < std::tie(B.position, B.range, B.kind, B.label); } +std::string InlayHint::joinLabels() const { + return llvm::join(llvm::map_range(label, [](auto &L) { return L.value; }), + ""); +} llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, InlayHintKind Kind) { auto ToString = [](InlayHintKind K) { @@ -1519,6 +1523,33 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, InlayHintKind Kind) { return OS << ToString(Kind); } +llvm::json::Value toJSON(const InlayHintLabelPart &L) { + llvm::json::Object Result{{"value", L.value}}; + if (L.tooltip) + Result["tooltip"] = *L.tooltip; + if (L.location) + Result["location"] = *L.location; + if (L.command) + Result["command"] = *L.command; + return Result; +} + +bool operator==(const InlayHintLabelPart &LHS, const InlayHintLabelPart &RHS) { + return std::tie(LHS.value, LHS.location) == std::tie(RHS.value, RHS.location); +} + +bool operator<(const InlayHintLabelPart &LHS, const InlayHintLabelPart &RHS) { + return std::tie(LHS.value, LHS.location) < std::tie(RHS.value, RHS.location); +} + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const InlayHintLabelPart &L) { + OS << L.value; + if (L.location) + OS << " (" << L.location << ")"; + return OS; +} + static const char *toString(OffsetEncoding OE) { switch (OE) { case OffsetEncoding::UTF8: diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h index 358d4c6feaf87d45c5f0a3fc4f3f0635af168a8d..a0f8b04bc4ffdb043212d13861d78e7dbc8ecdd2 100644 --- a/clang-tools-extra/clangd/Protocol.h +++ b/clang-tools-extra/clangd/Protocol.h @@ -1689,6 +1689,48 @@ enum class InlayHintKind { }; llvm::json::Value toJSON(const InlayHintKind &); +/// An inlay hint label part allows for interactive and composite labels +/// of inlay hints. +struct InlayHintLabelPart { + + InlayHintLabelPart() = default; + + InlayHintLabelPart(std::string value, + std::optional location = std::nullopt) + : value(std::move(value)), location(std::move(location)) {} + + /// The value of this label part. + std::string value; + + /// The tooltip text when you hover over this label part. Depending on + /// the client capability `inlayHint.resolveSupport`, clients might resolve + /// this property late using the resolve request. + std::optional tooltip; + + /// An optional source code location that represents this + /// label part. + /// + /// The editor will use this location for the hover and for code navigation + /// features: This part will become a clickable link that resolves to the + /// definition of the symbol at the given location (not necessarily the + /// location itself), it shows the hover that shows at the given location, + /// and it shows a context menu with further code navigation commands. + /// + /// Depending on the client capability `inlayHint.resolveSupport` clients + /// might resolve this property late using the resolve request. + std::optional location; + + /// An optional command for this label part. + /// + /// Depending on the client capability `inlayHint.resolveSupport` clients + /// might resolve this property late using the resolve request. + std::optional command; +}; +llvm::json::Value toJSON(const InlayHintLabelPart &); +bool operator==(const InlayHintLabelPart &, const InlayHintLabelPart &); +bool operator<(const InlayHintLabelPart &, const InlayHintLabelPart &); +llvm::raw_ostream &operator<<(llvm::raw_ostream &, const InlayHintLabelPart &); + /// Inlay hint information. struct InlayHint { /// The position of this hint. @@ -1698,7 +1740,7 @@ struct InlayHint { /// InlayHintLabelPart label parts. /// /// *Note* that neither the string nor the label part can be empty. - std::string label; + std::vector label; /// The kind of this hint. Can be omitted in which case the client should fall /// back to a reasonable default. @@ -1724,6 +1766,9 @@ struct InlayHint { /// The range allows clients more flexibility of when/how to display the hint. /// This is an (unserialized) clangd extension. Range range; + + /// Join the label[].value together. + std::string joinLabels() const; }; llvm::json::Value toJSON(const InlayHint &); bool operator==(const InlayHint &, const InlayHint &); diff --git a/clang-tools-extra/clangd/support/Trace.h b/clang-tools-extra/clangd/support/Trace.h index 1bfc75b874d8a9b1bee0de26990e9fff3f0cacdb..36c3745a41e969f03866931aa9bcefddffda4ce3 100644 --- a/clang-tools-extra/clangd/support/Trace.h +++ b/clang-tools-extra/clangd/support/Trace.h @@ -143,8 +143,8 @@ bool enabled(); class Span { public: Span(llvm::Twine Name); - /// Records span's duration in seconds to \p LatencyMetric with \p Name as the - /// label. + /// Records span's duration in milliseconds to \p LatencyMetric with \p Name + /// as the label. Span(llvm::Twine Name, const Metric &LatencyMetric); ~Span(); diff --git a/clang-tools-extra/clangd/test/inlayHints.test b/clang-tools-extra/clangd/test/inlayHints.test index 8f302dd17a5494f246d15b9a2468c04664d1d105..e5b3c0fb0b960aa13a1acefb184e9795ff4854c8 100644 --- a/clang-tools-extra/clangd/test/inlayHints.test +++ b/clang-tools-extra/clangd/test/inlayHints.test @@ -51,7 +51,11 @@ # CHECK-NEXT: "result": [ # CHECK-NEXT: { # CHECK-NEXT: "kind": 2, -# CHECK-NEXT: "label": "bar:", +# CHECK-NEXT: "label": [ +# CHECK-NEXT: { +# CHECK-NEXT: "value": "bar:" +# CHECK-NEXT: } +# CHECK-NEXT: ], # CHECK-NEXT: "paddingLeft": false, # CHECK-NEXT: "paddingRight": true, # CHECK-NEXT: "position": { diff --git a/clang-tools-extra/clangd/tool/Check.cpp b/clang-tools-extra/clangd/tool/Check.cpp index 45e2e1e278deafa4843d8f7945472b961f7519a4..25005ec1bd04532093d24334ece75f7661f5c0e7 100644 --- a/clang-tools-extra/clangd/tool/Check.cpp +++ b/clang-tools-extra/clangd/tool/Check.cpp @@ -367,7 +367,13 @@ public: auto Hints = inlayHints(*AST, LineRange); for (const auto &Hint : Hints) { - vlog(" {0} {1} {2}", Hint.kind, Hint.position, Hint.label); + vlog(" {0} {1} [{2}]", Hint.kind, Hint.position, [&] { + return llvm::join(llvm::map_range(Hint.label, + [&](auto &L) { + return llvm::formatv("{{{0}}", L); + }), + ", "); + }()); } } diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 5721feecd58ea89219e193aa18c9be15321cb8e4..49337bddf98d5d93c22f75169844bc08ded35426 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -2648,12 +2648,15 @@ TEST(CompletionTest, CompletionFunctionArgsDisabled) { class foo_class{}; template using foo_alias = T**; + template + T foo_var = T{}; void f() { foo_^ })cpp", {}, Opts); EXPECT_THAT( Results.Completions, UnorderedElementsAre(AllOf(named("foo_class"), snippetSuffix("<$0>")), - AllOf(named("foo_alias"), snippetSuffix("<$0>")))); + AllOf(named("foo_alias"), snippetSuffix("<$0>")), + AllOf(named("foo_var"), snippetSuffix("<$0>")))); } { auto Results = completions( diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp index 0fff0dfca6c9b8f21a459a4ec63b4821555c21a0..5b1531eb2fa60bcd0ae81137fcc3cf5b26fd79ee 100644 --- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp +++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp @@ -25,7 +25,7 @@ namespace clangd { llvm::raw_ostream &operator<<(llvm::raw_ostream &Stream, const InlayHint &Hint) { - return Stream << Hint.label << "@" << Hint.range; + return Stream << Hint.joinLabels() << "@" << Hint.range; } namespace { @@ -57,10 +57,11 @@ struct ExpectedHint { MATCHER_P2(HintMatcher, Expected, Code, llvm::to_string(Expected)) { llvm::StringRef ExpectedView(Expected.Label); - if (arg.label != ExpectedView.trim(" ") || + std::string ResultLabel = arg.joinLabels(); + if (ResultLabel != ExpectedView.trim(" ") || arg.paddingLeft != ExpectedView.starts_with(" ") || arg.paddingRight != ExpectedView.ends_with(" ")) { - *result_listener << "label is '" << arg.label << "'"; + *result_listener << "label is '" << ResultLabel << "'"; return false; } if (arg.range != Code.range(Expected.RangeName)) { @@ -72,7 +73,7 @@ MATCHER_P2(HintMatcher, Expected, Code, llvm::to_string(Expected)) { return true; } -MATCHER_P(labelIs, Label, "") { return arg.label == Label; } +MATCHER_P(labelIs, Label, "") { return arg.joinLabels() == Label; } Config noHintsConfig() { Config C; diff --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp index 754e8c287c514869506c7efde8816f340d664466..db516a1f62a35773b9e46932fec066984afb8a93 100644 --- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp +++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp @@ -10,6 +10,7 @@ #include "SourceCode.h" #include "TestTU.h" #include "support/TestTracer.h" +#include "clang/AST/ASTConcept.h" #include "clang/AST/Decl.h" #include "llvm/Support/Casting.h" #include "gmock/gmock.h" @@ -893,6 +894,33 @@ TEST(SelectionTest, DeclContextLambda) { EXPECT_TRUE(ST.commonAncestor()->getDeclContext().isFunctionOrMethod()); } +TEST(SelectionTest, UsingConcepts) { + llvm::Annotations Test(R"cpp( +namespace ns { +template +concept Foo = true; +} + +using ns::Foo; + +template +auto Func(Fo^o auto V) -> Fo^o decltype(auto) { + Fo^o auto W = V; + return W; +} +)cpp"); + auto TU = TestTU::withCode(Test.code()); + TU.ExtraArgs.emplace_back("-std=c++2c"); + auto AST = TU.build(); + for (auto Point : Test.points()) { + auto ST = SelectionTree::createRight(AST.getASTContext(), AST.getTokens(), + Point, Point); + auto *C = ST.commonAncestor()->ASTNode.get(); + EXPECT_TRUE(C && C->getFoundDecl() && + C->getFoundDecl()->getKind() == Decl::UsingShadow); + } +} + } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/unittests/tweaks/ExtractVariableTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/ExtractVariableTests.cpp index 42dd612eeeec46c3e65383af5f085e662a3359aa..656b62c9a1f4e17ec1fd8aaab60348340114383d 100644 --- a/clang-tools-extra/clangd/unittests/tweaks/ExtractVariableTests.cpp +++ b/clang-tools-extra/clangd/unittests/tweaks/ExtractVariableTests.cpp @@ -72,6 +72,22 @@ TEST_F(ExtractVariableTest, Test) { )cpp"; EXPECT_UNAVAILABLE(NoCrashCasesC); + ExtraArgs = {"-xc"}; + const char *NoCrashDesignator = R"cpp( + struct A { + struct { + int x; + }; + }; + struct B { + int y; + }; + void foo(struct B *b) { + struct A a = {.x=b[[->]]y}; + } + )cpp"; + EXPECT_AVAILABLE(NoCrashDesignator); + ExtraArgs = {"-xobjective-c"}; const char *AvailableObjC = R"cpp( __attribute__((objc_root_class)) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 44680f79de6f543e84cc05fb39c2c97a5e1a5dfa..309b844615a1212c4983815ae6eabee086e68e3c 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -110,12 +110,25 @@ New checks Detects error-prone Curiously Recurring Template Pattern usage, when the CRTP can be constructed outside itself and the derived class. +- New :doc:`bugprone-suspicious-stringview-data-usage + ` check. + + Identifies suspicious usages of ``std::string_view::data()`` that could lead + to reading out-of-bounds data due to inadequate or incorrect string null + termination. + - New :doc:`modernize-use-designated-initializers ` check. Finds initializer lists for aggregate types that could be written as designated initializers instead. +- New :doc:`readability-enum-initial-value + ` check. + + Enforces consistent style for enumerators' initialization, covering three + styles: none, first only, or all initialized explicitly. + - New :doc:`readability-use-std-min-max ` check. @@ -132,6 +145,10 @@ Changes in existing checks ` check by detecting side effect from calling a method with non-const reference parameters. +- Improved :doc:`bugprone-inc-dec-in-conditions + ` check to ignore code + within unevaluated contexts, such as ``decltype``. + - Improved :doc:`bugprone-non-zero-enum-to-bool-conversion ` check by eliminating false positives resulting from direct usage of bitwise operators @@ -165,13 +182,17 @@ Changes in existing checks giving false positives for deleted functions and fix false negative when some parameters are forwarded, but other aren't. -- Cleaned up :doc:`cppcoreguidelines-prefer-member-initializer - ` +- Improved :doc:`cppcoreguidelines-owning-memory + ` check to properly handle + return type in lambdas and in nested functions. + +- Improved :doc:`cppcoreguidelines-prefer-member-initializer + ` check by removing enforcement of rule `C.48 `_, which was deprecated since :program:`clang-tidy` 17. This rule is now covered by :doc:`cppcoreguidelines-use-default-member-init - ` and fixes + `. Fixed incorrect hints when using list-initialization. - Improved :doc:`google-build-namespaces @@ -186,6 +207,9 @@ Changes in existing checks ` check by replacing the local option `HeaderFileExtensions` by the global option of the same name. +- Improved :doc:`google-runtime-int ` + check performance through optimizations. + - Improved :doc:`llvm-header-guard ` check by replacing the local option `HeaderFileExtensions` by the global option of the same name. @@ -218,12 +242,20 @@ Changes in existing checks ` check to also remove any trailing whitespace when deleting the ``virtual`` keyword. +- Improved :doc:`modernize-use-using ` + check by adding support for detection of typedefs declared on function level. + - Improved :doc:`performance-unnecessary-copy-initialization ` check by detecting more cases of constant access. In particular, pointers can be analyzed, se the check now handles the common patterns `const auto e = (*vector_ptr)[i]` and `const auto e = vector_ptr->at(i);`. +- Improved :doc:`readability-identifier-naming + ` check in `GetConfigPerFile` + mode by resolving symbolic links to header files. Fixed handling of Hungarian + Prefix when configured to `LowerCase`. + - Improved :doc:`readability-implicit-bool-conversion ` check to provide valid fix suggestions for ``static_cast`` without a preceding space and @@ -233,10 +265,10 @@ Changes in existing checks ` check to properly emit warnings for static data member with an in-class initializer. -- Improved :doc:`readability-identifier-naming - ` check in `GetConfigPerFile` - mode by resolving symbolic links to header files. Fixed handling of Hungarian - Prefix when configured to `LowerCase`. +- Improved :doc:`readability-static-definition-in-anonymous-namespace + ` + check by resolving fix-it overlaps in template code by disregarding implicit + instances. Removed checks ^^^^^^^^^^^^^^ @@ -247,9 +279,9 @@ Removed checks Miscellaneous ^^^^^^^^^^^^^ -- Fixed incorrect formatting in ``clang-apply-replacements`` when no ``--format`` - option is specified. Now ``clang-apply-replacements`` applies formatting only with - the option. +- Fixed incorrect formatting in :program:`clang-apply-replacements` when no + ``--format`` option is specified. Now :program:`clang-apply-replacements` + applies formatting only with the option. Improvements to include-fixer ----------------------------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-stringview-data-usage.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-stringview-data-usage.rst new file mode 100644 index 0000000000000000000000000000000000000000..9b38d836018103e4890fc8668601e870e86c1b16 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-stringview-data-usage.rst @@ -0,0 +1,58 @@ +.. title:: clang-tidy - bugprone-suspicious-stringview-data-usage + +bugprone-suspicious-stringview-data-usage +========================================= + +Identifies suspicious usages of ``std::string_view::data()`` that could lead to +reading out-of-bounds data due to inadequate or incorrect string null +termination. + +It warns when the result of ``data()`` is passed to a constructor or function +without also passing the corresponding result of ``size()`` or ``length()`` +member function. Such usage can lead to unintended behavior, particularly when +assuming the data pointed to by ``data()`` is null-terminated. + +The absence of a ``c_str()`` method in ``std::string_view`` often leads +developers to use ``data()`` as a substitute, especially when interfacing with +C APIs that expect null-terminated strings. However, since ``data()`` does not +guarantee null termination, this can result in unintended behavior if the API +relies on proper null termination for correct string interpretation. + +In today's programming landscape, this scenario can occur when implicitly +converting an ``std::string_view`` to an ``std::string``. Since the constructor +in ``std::string`` designed for string-view-like objects is ``explicit``, +attempting to pass an ``std::string_view`` to a function expecting an +``std::string`` will result in a compilation error. As a workaround, developers +may be tempted to utilize the ``.data()`` method to achieve compilation, +introducing potential risks. + +For instance: + +.. code-block:: c++ + + void printString(const std::string& str) { + std::cout << "String: " << str << std::endl; + } + + void something(std::string_view sv) { + printString(sv.data()); + } + +In this example, directly passing ``sv`` to the ``printString`` function would +lead to a compilation error due to the explicit nature of the ``std::string`` +constructor. Consequently, developers might opt for ``sv.data()`` to resolve the +compilation error, albeit introducing potential hazards as discussed. + +.. option:: StringViewTypes + + Option allows users to specify custom string view-like types for analysis. It + accepts a semicolon-separated list of type names or regular expressions + matching these types. Default value is: + `::std::basic_string_view;::llvm::StringRef`. + +.. option:: AllowedCallees + + Specifies methods, functions, or classes where the result of ``.data()`` is + passed to. Allows to exclude such calls from the analysis. Accepts a + semicolon-separated list of names or regular expressions matching these + entities. Default value is: empty string. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index d03e7af688f007aead351335a5af647e9c2b386b..188a42bfddd383619ed1e143543bf5a5201c7881 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -139,6 +139,7 @@ Clang-Tidy Checks :doc:`bugprone-suspicious-realloc-usage `, :doc:`bugprone-suspicious-semicolon `, "Yes" :doc:`bugprone-suspicious-string-compare `, "Yes" + :doc:`bugprone-suspicious-stringview-data-usage `, :doc:`bugprone-swapped-arguments `, "Yes" :doc:`bugprone-switch-missing-default-case `, :doc:`bugprone-terminating-continue `, "Yes" @@ -351,6 +352,7 @@ Clang-Tidy Checks :doc:`readability-delete-null-pointer `, "Yes" :doc:`readability-duplicate-include `, "Yes" :doc:`readability-else-after-return `, "Yes" + :doc:`readability-enum-initial-value `, "Yes" :doc:`readability-function-cognitive-complexity `, :doc:`readability-function-size `, :doc:`readability-identifier-length `, diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/enum-initial-value.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/enum-initial-value.rst new file mode 100644 index 0000000000000000000000000000000000000000..660efc1eaff3e53527aad41a19151be0fe13062d --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/enum-initial-value.rst @@ -0,0 +1,75 @@ +.. title:: clang-tidy - readability-enum-initial-value + +readability-enum-initial-value +============================== + +Enforces consistent style for enumerators' initialization, covering three +styles: none, first only, or all initialized explicitly. + +When adding new enumerations, inconsistent initial value will cause potential +enumeration value conflicts. + +In an enumeration, the following three cases are accepted. +1. none of enumerators are explicit initialized. +2. the first enumerator is explicit initialized. +3. all of enumerators are explicit initialized. + +.. code-block:: c++ + + // valid, none of enumerators are initialized. + enum A { + e0, + e1, + e2, + }; + + // valid, the first enumerator is initialized. + enum A { + e0 = 0, + e1, + e2, + }; + + // valid, all of enumerators are initialized. + enum A { + e0 = 0, + e1 = 1, + e2 = 2, + }; + + // invalid, e1 is not explicit initialized. + enum A { + e0 = 0, + e1, + e2 = 2, + }; + +Options +------- + +.. option:: AllowExplicitZeroFirstInitialValue + + If set to `false`, the first enumerator must not be explicitly initialized. + See examples below. Default is `true`. + + .. code-block:: c++ + + enum A { + e0 = 0, // not allowed if AllowExplicitZeroFirstInitialValue is false + e1, + e2, + }; + + +.. option:: AllowExplicitSequentialInitialValues + + If set to `false`, sequential initializations are not allowed. + See examples below. Default is `true`. + + .. code-block:: c++ + + enum A { + e0 = 1, // not allowed if AllowExplicitSequentialInitialValues is false + e1 = 2, + e2 = 3, + }; diff --git a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp index 5dc88157e13af01af2d0492a39e2aaf695e5613d..dac3f39e1a65842a700b0c7c2e0e28ae641c79aa 100644 --- a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp +++ b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp @@ -548,9 +548,7 @@ TEST(WalkAST, Concepts) { testWalk(Concept, "template requires ^Foo void func() {}"); testWalk(Concept, "template void func() requires ^Foo {}"); testWalk(Concept, "void func(^Foo auto x) {}"); - // FIXME: Foo should be explicitly referenced. - testWalk("template concept Foo = true;", - "void func() { ^Foo auto x = 1; }"); + testWalk(Concept, "void func() { ^Foo auto x = 1; }"); } TEST(WalkAST, FriendDecl) { diff --git a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string index f2e4159a224513f073890f1c86c9964327336a14..28e2b4a231e52edbb3697d2e5c76d513c3062089 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string +++ b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string @@ -24,6 +24,7 @@ struct basic_string { basic_string(); basic_string(const C *p, const A &a = A()); basic_string(const C *p, size_type count); + basic_string(const C *b, const C *e); ~basic_string(); @@ -85,6 +86,12 @@ struct basic_string_view { const C *str; constexpr basic_string_view(const C* s) : str(s) {} + const C *data() const; + + bool empty() const; + size_type size() const; + size_type length() const; + size_type find(_Type v, size_type pos = 0) const; size_type find(C ch, size_type pos = 0) const; size_type find(const C* s, size_type pos, size_type count) const; diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/inc-dec-in-conditions.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/inc-dec-in-conditions.cpp index 82af039973c3bb76dab22c57bb0e0f7c2e703d6a..91de013138f0deea472742be633bec41e34417aa 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/inc-dec-in-conditions.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/inc-dec-in-conditions.cpp @@ -68,3 +68,13 @@ bool doubleCheck(Container x) { // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: decrementing and referencing a variable in a complex condition can cause unintended side-effects due to C++'s order of evaluation, consider moving the modification outside of the condition to avoid misunderstandings [bugprone-inc-dec-in-conditions] // CHECK-MESSAGES: :[[@LINE-2]]:31: warning: incrementing and referencing a variable in a complex condition can cause unintended side-effects due to C++'s order of evaluation, consider moving the modification outside of the condition to avoid misunderstandings [bugprone-inc-dec-in-conditions] } + +namespace PR85838 { + void test() + { + auto foo = 0; + auto bar = 0; + if (++foo < static_cast(bar)) {} + if (static_cast(bar) < foo) {} + } +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-stringview-data-usage.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-stringview-data-usage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8072d60a2f47a1fad3addad14d67265225387fc7 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-stringview-data-usage.cpp @@ -0,0 +1,56 @@ +// RUN: %check_clang_tidy -std=c++17-or-later %s bugprone-suspicious-stringview-data-usage %t -- -- -isystem %clang_tidy_headers +#include + +struct View { + const char* str; +}; + +struct Pair { + const char* begin; + const char* end; +}; + +struct ViewWithSize { + const char* str; + std::string_view::size_type size; +}; + +void something(const char*); +void something(const char*, unsigned); +void something(const char*, unsigned, const char*); +void something_str(std::string, unsigned); + +void invalid(std::string_view sv, std::string_view sv2) { + std::string s(sv.data()); +// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: result of a `data()` call may not be null terminated, provide size information to the callee to prevent potential issues + std::string si{sv.data()}; +// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: result of a `data()` call may not be null terminated, provide size information to the callee to prevent potential issues + std::string_view s2(sv.data()); +// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: result of a `data()` call may not be null terminated, provide size information to the callee to prevent potential issues + something(sv.data()); +// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: result of a `data()` call may not be null terminated, provide size information to the callee to prevent potential issues + something(sv.data(), sv.size(), sv2.data()); +// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: result of a `data()` call may not be null terminated, provide size information to the callee to prevent potential issues + something_str(sv.data(), sv.size()); +// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: result of a `data()` call may not be null terminated, provide size information to the callee to prevent potential issues + View view{sv.data()}; +// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: result of a `data()` call may not be null terminated, provide size information to the callee to prevent potential issues +} + +void valid(std::string_view sv) { + std::string s1(sv.data(), sv.data() + sv.size()); + std::string s2(sv.data(), sv.data() + sv.length()); + std::string s3(sv.data(), sv.size() + sv.data()); + std::string s4(sv.data(), sv.length() + sv.data()); + std::string s5(sv.data(), sv.size()); + std::string s6(sv.data(), sv.length()); + something(sv.data(), sv.size()); + something(sv.data(), sv.length()); + ViewWithSize view1{sv.data(), sv.size()}; + ViewWithSize view2{sv.data(), sv.length()}; + Pair view3{sv.data(), sv.data() + sv.size()}; + Pair view4{sv.data(), sv.data() + sv.length()}; + Pair view5{sv.data(), sv.size() + sv.data()}; + Pair view6{sv.data(), sv.length() + sv.data()}; + const char* str{sv.data()}; +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-avoid-assignment.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-avoid-assignment.cpp index b4a41004adf8949ef6145d7f5cbb86b447122dfb..564c07a724ccdec9305c70ea24acf1f5333a4b04 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-avoid-assignment.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-avoid-assignment.cpp @@ -3,23 +3,37 @@ // RUN: {bugprone-unused-return-value.CheckedFunctions: "::*"}}' \ // RUN: -- -struct S { - S(){}; - S(S const &); - S(S &&); - S &operator=(S const &); - S &operator=(S &&); - S &operator+=(S); +struct S1 { + S1(){}; + S1(S1 const &); + S1(S1 &&); + S1 &operator=(S1 const &); + S1 &operator=(S1 &&); + S1 &operator+=(S1); + S1 &operator++(); + S1 &operator++(int); + S1 &operator--(); + S1 &operator--(int); }; -S returnValue(); -S const &returnRef(); +struct S2 { + S2(){}; + S2(S2 const &); + S2(S2 &&); +}; + +S2 &operator-=(S2&, int); +S2 &operator++(S2 &); +S2 &operator++(S2 &, int); + +S1 returnValue(); +S1 const &returnRef(); void bar() { returnValue(); // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors - S a{}; + S1 a{}; a = returnValue(); a.operator=(returnValue()); @@ -27,4 +41,15 @@ void bar() { a.operator=(returnRef()); a += returnRef(); + + a++; + ++a; + a--; + --a; + + S2 b{}; + + b -= 1; + b++; + ++b; } diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/owning-memory.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/owning-memory.cpp index eb8ad1b8b879250b8d643126e68ea3db651177f4..574efe7bd91478de9c25ab92570c28eb292e0ef2 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/owning-memory.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/owning-memory.cpp @@ -395,3 +395,109 @@ namespace PR63994 { // CHECK-NOTES: [[@LINE-1]]:5: warning: returning a newly created resource of type 'A *' or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>' } } + +namespace PR59389 { + struct S { + S(); + S(int); + + int value = 1; + }; + + void testLambdaInFunctionNegative() { + const auto MakeS = []() -> ::gsl::owner { + return ::gsl::owner{new S{}}; + }; + } + + void testLambdaInFunctionPositive() { + const auto MakeS = []() -> S* { + return ::gsl::owner{new S{}}; + // CHECK-NOTES: [[@LINE-1]]:7: warning: returning a newly created resource of type 'S *' or 'gsl::owner<>' from a lambda whose return type is not 'gsl::owner<>' + }; + } + + void testFunctionInFunctionNegative() { + struct C { + ::gsl::owner test() { + return ::gsl::owner{new S{}}; + } + }; + } + + void testFunctionInFunctionPositive() { + struct C { + S* test() { + return ::gsl::owner{new S{}}; + // CHECK-NOTES: [[@LINE-1]]:9: warning: returning a newly created resource of type 'S *' or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>' + } + }; + } + + ::gsl::owner testReverseLambdaNegative() { + const auto MakeI = [] -> int { return 5; }; + return ::gsl::owner{new S(MakeI())}; + } + + S* testReverseLambdaPositive() { + const auto MakeI = [] -> int { return 5; }; + return ::gsl::owner{new S(MakeI())}; + // CHECK-NOTES: [[@LINE-1]]:5: warning: returning a newly created resource of type 'S *' or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>' + } + + ::gsl::owner testReverseFunctionNegative() { + struct C { + int test() { return 5; } + }; + return ::gsl::owner{new S(C().test())}; + } + + S* testReverseFunctionPositive() { + struct C { + int test() { return 5; } + }; + return ::gsl::owner{new S(C().test())}; + // CHECK-NOTES: [[@LINE-1]]:5: warning: returning a newly created resource of type 'S *' or 'gsl::owner<>' from a function whose return type is not 'gsl::owner<>' + } + + void testLambdaInLambdaNegative() { + const auto MakeS = []() -> ::gsl::owner { + const auto MakeI = []() -> int { return 5; }; + return ::gsl::owner{new S(MakeI())}; + }; + } + + void testLambdaInLambdaPositive() { + const auto MakeS = []() -> S* { + const auto MakeI = []() -> int { return 5; }; + return ::gsl::owner{new S(MakeI())}; + // CHECK-NOTES: [[@LINE-1]]:7: warning: returning a newly created resource of type 'S *' or 'gsl::owner<>' from a lambda whose return type is not 'gsl::owner<>' + }; + } + + void testLambdaInLambdaWithDoubleReturns() { + const auto MakeS = []() -> S* { + const auto MakeS2 = []() -> S* { + return ::gsl::owner{new S(1)}; + // CHECK-NOTES: [[@LINE-1]]:9: warning: returning a newly created resource of type 'S *' or 'gsl::owner<>' from a lambda whose return type is not 'gsl::owner<>' [cppcoreguidelines-owning-memory] + }; + return ::gsl::owner{new S(2)}; + // CHECK-NOTES: [[@LINE-1]]:7: warning: returning a newly created resource of type 'S *' or 'gsl::owner<>' from a lambda whose return type is not 'gsl::owner<>' + }; + } + + void testReverseLambdaInLambdaNegative() { + const auto MakeI = []() -> int { + const auto MakeS = []() -> ::gsl::owner { return new S(); }; + return 5; + }; + } + + void testReverseLambdaInLambdaPositive() { + const auto MakeI = []() -> int { + const auto MakeS = []() -> S* { return new S(); }; + // CHECK-NOTES: [[@LINE-1]]:39: warning: returning a newly created resource of type 'S *' or 'gsl::owner<>' from a lambda whose return type is not 'gsl::owner<>' + return 5; + }; + } +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp index 462bc984fd3ad5609fabde7a313d9c03e4de8abd..925e5f9c1ca54e8b274139ee114b1556dcfeb327 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s modernize-use-using %t -- -- -I %S/Inputs/use-using/ +// RUN: %check_clang_tidy %s modernize-use-using %t -- -- -fno-delayed-template-parsing -I %S/Inputs/use-using/ typedef int Type; // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef' [modernize-use-using] @@ -342,3 +342,44 @@ typedef int InExternCPP; // CHECK-FIXES: using InExternCPP = int; } + +namespace ISSUE_72179 +{ + void foo() + { + typedef int a; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'using' instead of 'typedef' [modernize-use-using] + // CHECK-FIXES: using a = int; + + } + + void foo2() + { + typedef struct { int a; union { int b; }; } c; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'using' instead of 'typedef' [modernize-use-using] + // CHECK-FIXES: using c = struct { int a; union { int b; }; }; + } + + template + void foo3() + { + typedef T b; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'using' instead of 'typedef' [modernize-use-using] + // CHECK-FIXES: using b = T; + } + + template + class MyClass + { + void foo() + { + typedef MyClass c; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use 'using' instead of 'typedef' [modernize-use-using] + // CHECK-FIXES: using c = MyClass; + } + }; + + const auto foo4 = [](int a){typedef int d;}; + // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use 'using' instead of 'typedef' [modernize-use-using] + // CHECK-FIXES: const auto foo4 = [](int a){using d = int;}; +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.c b/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.c new file mode 100644 index 0000000000000000000000000000000000000000..c66288cbe3e9575da8f963d59874cf5ab76bddd0 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.c @@ -0,0 +1,80 @@ +// RUN: %check_clang_tidy %s readability-enum-initial-value %t +// RUN: %check_clang_tidy -check-suffix=ENABLE %s readability-enum-initial-value %t -- \ +// RUN: -config='{CheckOptions: { \ +// RUN: readability-enum-initial-value.AllowExplicitZeroFirstInitialValue: false, \ +// RUN: readability-enum-initial-value.AllowExplicitSequentialInitialValues: false, \ +// RUN: }}' + +enum EError { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: inital values in enum 'EError' are not consistent + // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: inital values in enum 'EError' are not consistent + EError_a = 1, + EError_b, + // CHECK-FIXES: EError_b = 2, + EError_c = 3, +}; + +enum ENone { + ENone_a, + ENone_b, + EENone_c, +}; + +enum EFirst { + EFirst_a = 1, + EFirst_b, + EFirst_c, +}; + +enum EAll { + EAll_a = 1, + EAll_b = 2, + EAll_c = 4, +}; + +#define ENUMERATOR_1 EMacro1_b +enum EMacro1 { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: inital values in enum 'EMacro1' are not consistent + // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: inital values in enum 'EMacro1' are not consistent + EMacro1_a = 1, + ENUMERATOR_1, + // CHECK-FIXES: ENUMERATOR_1 = 2, + EMacro1_c = 3, +}; + + +#define ENUMERATOR_2 EMacro2_b = 2 +enum EMacro2 { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: inital values in enum 'EMacro2' are not consistent + // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: inital values in enum 'EMacro2' are not consistent + EMacro2_a = 1, + ENUMERATOR_2, + EMacro2_c, + // CHECK-FIXES: EMacro2_c = 3, +}; + +enum EnumZeroFirstInitialValue { + EnumZeroFirstInitialValue_0 = 0, + // CHECK-MESSAGES-ENABLE: :[[@LINE-1]]:3: warning: zero initial value for the first enumerator in 'EnumZeroFirstInitialValue' can be disregarded + // CHECK-FIXES-ENABLE: EnumZeroFirstInitialValue_0 , + EnumZeroFirstInitialValue_1, + EnumZeroFirstInitialValue_2, +}; + +enum EnumZeroFirstInitialValueWithComment { + EnumZeroFirstInitialValueWithComment_0 = /* == */ 0, + // CHECK-MESSAGES-ENABLE: :[[@LINE-1]]:3: warning: zero initial value for the first enumerator in 'EnumZeroFirstInitialValueWithComment' can be disregarded + // CHECK-FIXES-ENABLE: EnumZeroFirstInitialValueWithComment_0 /* == */ , + EnumZeroFirstInitialValueWithComment_1, + EnumZeroFirstInitialValueWithComment_2, +}; + +enum EnumSequentialInitialValue { + // CHECK-MESSAGES-ENABLE: :[[@LINE-1]]:1: warning: sequential initial value in 'EnumSequentialInitialValue' can be ignored + EnumSequentialInitialValue_0 = 2, + // CHECK-FIXES-ENABLE: EnumSequentialInitialValue_0 = 2, + EnumSequentialInitialValue_1 = 3, + // CHECK-FIXES-ENABLE: EnumSequentialInitialValue_1 , + EnumSequentialInitialValue_2 = 4, + // CHECK-FIXES-ENABLE: EnumSequentialInitialValue_2 , +}; diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3c4ba970372a077bf12ad7bb84dc7ce1836ed8ac --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.cpp @@ -0,0 +1,27 @@ +// RUN: %check_clang_tidy %s readability-enum-initial-value %t + +enum class EError { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: inital values in enum 'EError' are not consistent + EError_a = 1, + EError_b, + // CHECK-FIXES: EError_b = 2, + EError_c = 3, +}; + +enum class ENone { + ENone_a, + ENone_b, + EENone_c, +}; + +enum class EFirst { + EFirst_a = 1, + EFirst_b, + EFirst_c, +}; + +enum class EAll { + EAll_a = 1, + EAll_b = 2, + EAll_c = 3, +}; diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/static-definition-in-anonymous-namespace.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/static-definition-in-anonymous-namespace.cpp index e9938db4f5b83f216570aefe9001010b3f05e2ec..e204199393db4221feb89a4366673b92deb96ece 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/static-definition-in-anonymous-namespace.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/static-definition-in-anonymous-namespace.cpp @@ -51,6 +51,17 @@ static int c = 1; } // namespace deep_inner } // namespace inner +template +static void printTemplate(T&&) {} +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: 'printTemplate' is a static definition in anonymous namespace; static is redundant here [readability-static-definition-in-anonymous-namespace] +// CHECK-FIXES: {{^}}void printTemplate(T&&) {} + +void testTemplate() { + printTemplate(5); + printTemplate(5U); + printTemplate("some string"); +} + } // namespace namespace N { diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp index d0efc5ca7637538859ab4865eaa3e28e44a60bf1..57d930b26e64c0f1920ff932e18e48e279a0ec0e 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp @@ -25,7 +25,7 @@ // RUN: not clang-tidy -checks='-*,modernize-use-override' %T/diagnostics/input.cpp -- -DCOMPILATION_ERROR 2>&1 | FileCheck -check-prefix=CHECK6 -implicit-check-not='{{warning:|error:}}' %s // RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %s -- -DMACRO_FROM_COMMAND_LINE -std=c++20 | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s // RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined,clang-diagnostic-literal-conversion' %s -- -DMACRO_FROM_COMMAND_LINE -std=c++20 -Wno-macro-redefined | FileCheck --check-prefix=CHECK7 -implicit-check-not='{{warning:|error:}}' %s -// RUN: not clang-tidy -checks='-*,modernize-use-override' %s -- -std=c++20 -DPR64602 | FileCheck -check-prefix=CHECK8 -implicit-check-not='{{warning:|error:}}' %s +// RUN: clang-tidy -checks='-*,modernize-use-override' %s -- -std=c++20 -DPR64602 // CHECK1: error: no input files [clang-diagnostic-error] // CHECK1: error: no such file or directory: '{{.*}}nonexistent.cpp' [clang-diagnostic-error] @@ -68,6 +68,4 @@ auto S<>::foo(auto) { return 1; } -// CHECK8: error: conflicting types for 'foo' [clang-diagnostic-error] -// CHECK8: note: previous declaration is here #endif diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index 47fc2e4886cfc2862ed8e6b0158a06b77f05076e..284b2af24ddaa0405398e8ea1826856e93401ba6 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -13,8 +13,16 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) set(CLANG_BUILT_STANDALONE TRUE) endif() +# Make sure that our source directory is on the current cmake module path so that +# we can include cmake files from this directory. +list(INSERT CMAKE_MODULE_PATH 0 + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" + "${LLVM_COMMON_CMAKE_UTILS}/Modules" + ) + # Must go below project(..) include(GNUInstallDirs) +include(GetDarwinLinkerVersion) if(CLANG_BUILT_STANDALONE) set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to conform to") @@ -140,13 +148,6 @@ if(CLANG_BUILT_STANDALONE) endif() # LLVM_INCLUDE_TESTS endif() # standalone -# Make sure that our source directory is on the current cmake module path so that -# we can include cmake files from this directory. -list(INSERT CMAKE_MODULE_PATH 0 - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" - "${LLVM_COMMON_CMAKE_UTILS}/Modules" - ) - # This allows disabling clang's XML dependency even if LLVM finds libxml2. # By default, clang depends on libxml2 if LLVM does. option(CLANG_ENABLE_LIBXML2 "Whether libclang may depend on libxml2" @@ -190,11 +191,12 @@ set(CLANG_RESOURCE_DIR "" CACHE STRING set(C_INCLUDE_DIRS "" CACHE STRING "Colon separated list of directories clang will search for headers.") +set(USE_DEPRECATED_GCC_INSTALL_PREFIX OFF CACHE BOOL "Temporary workaround before GCC_INSTALL_PREFIX is completely removed") set(GCC_INSTALL_PREFIX "" CACHE PATH "Directory where gcc is installed." ) set(DEFAULT_SYSROOT "" CACHE STRING "Default to all compiler invocations for --sysroot=." ) -if(GCC_INSTALL_PREFIX) - message(WARNING "GCC_INSTALL_PREFIX is deprecated and will be removed. Use " +if(GCC_INSTALL_PREFIX AND NOT USE_DEPRECATED_GCC_INSTALL_PREFIX) + message(FATAL_ERROR "GCC_INSTALL_PREFIX is deprecated and will be removed. Use " "configuration files (https://clang.llvm.org/docs/UsersManual.html#configuration-files)" "to specify the default --gcc-install-dir= or --gcc-triple=. --gcc-toolchain= is discouraged. " "See https://github.com/llvm/llvm-project/pull/77537 for detail.") @@ -345,20 +347,7 @@ endif () # Determine HOST_LINK_VERSION on Darwin. set(HOST_LINK_VERSION) if (APPLE AND NOT CMAKE_LINKER MATCHES ".*lld.*") - set(LD_V_OUTPUT) - execute_process( - COMMAND sh -c "${CMAKE_LINKER} -v 2>&1 | head -1" - RESULT_VARIABLE HAD_ERROR - OUTPUT_VARIABLE LD_V_OUTPUT - ) - if (HAD_ERROR) - message(FATAL_ERROR "${CMAKE_LINKER} failed with status ${HAD_ERROR}") - endif() - if ("${LD_V_OUTPUT}" MATCHES ".*ld64-([0-9.]+).*") - string(REGEX REPLACE ".*ld64-([0-9.]+).*" "\\1" HOST_LINK_VERSION ${LD_V_OUTPUT}) - elseif ("${LD_V_OUTPUT}" MATCHES "[^0-9]*([0-9.]+).*") - string(REGEX REPLACE "[^0-9]*([0-9.]+).*" "\\1" HOST_LINK_VERSION ${LD_V_OUTPUT}) - endif() + get_darwin_linker_version(HOST_LINK_VERSION) message(STATUS "Host linker version: ${HOST_LINK_VERSION}") endif() diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py index 44a34ca196274c0a38f1f9675db4337fe3e5f1e4..302d99dccd77b5fec1e82acf428273c256d8b2f9 100644 --- a/clang/bindings/python/clang/cindex.py +++ b/clang/bindings/python/clang/cindex.py @@ -1091,6 +1091,29 @@ CursorKind.OMP_ARRAY_SECTION_EXPR = CursorKind(147) # Represents an @available(...) check. CursorKind.OBJC_AVAILABILITY_CHECK_EXPR = CursorKind(148) +# Fixed point literal. +CursorKind.FIXED_POINT_LITERAL = CursorKind(149) + +# OpenMP 5.0 [2.1.4, Array Shaping]. +CursorKind.OMP_ARRAY_SHAPING_EXPR = CursorKind(150) + +# OpenMP 5.0 [2.1.6 Iterators]. +CursorKind.OMP_ITERATOR_EXPR = CursorKind(151) + +# OpenCL's addrspace_cast<> expression. +CursorKind.CXX_ADDRSPACE_CAST_EXPR = CursorKind(152) + +# Expression that references a C++20 concept. +CursorKind.CONCEPT_SPECIALIZATION_EXPR = CursorKind(153) + +# Expression that references a C++20 requires expression. +CursorKind.REQUIRES_EXPR = CursorKind(154) + +# Expression that references a C++20 parenthesized list aggregate initializer. +CursorKind.CXX_PAREN_LIST_INIT_EXPR = CursorKind(155) + +# Represents a C++26 pack indexing expression. +CursorKind.PACK_INDEXING_EXPR = CursorKind(156) # A statement whose specific kind is not exposed via this interface. # @@ -1312,6 +1335,114 @@ CursorKind.OMP_TARGET_SIMD_DIRECTIVE = CursorKind(270) # OpenMP teams distribute directive. CursorKind.OMP_TEAMS_DISTRIBUTE_DIRECTIVE = CursorKind(271) +# OpenMP teams distribute simd directive. +CursorKind.OMP_TEAMS_DISTRIBUTE_DIRECTIVE = CursorKind(272) + +# OpenMP teams distribute parallel for simd directive. +CursorKind.OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE = CursorKind(273) + +# OpenMP teams distribute parallel for directive. +CursorKind.OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE = CursorKind(274) + +# OpenMP target teams directive. +CursorKind.OMP_TARGET_TEAMS_DIRECTIVE = CursorKind(275) + +# OpenMP target teams distribute directive. +CursorKind.OMP_TARGET_TEAMS_DISTRIBUTE_DIRECTIVE = CursorKind(276) + +# OpenMP target teams distribute parallel for directive. +CursorKind.OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE = CursorKind(277) + +# OpenMP target teams distribute parallel for simd directive. +CursorKind.OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE = CursorKind(278) + +# OpenMP target teams distribute simd directive. +CursorKind.OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE = CursorKind(279) + +# C++2a std::bit_cast expression. +CursorKind.BUILTIN_BIT_CAST_EXPR = CursorKind(280) + +# OpenMP master taskloop directive. +CursorKind.OMP_MASTER_TASK_LOOP_DIRECTIVE = CursorKind(281) + +# OpenMP parallel master taskloop directive. +CursorKind.OMP_PARALLEL_MASTER_TASK_LOOP_DIRECTIVE = CursorKind(282) + +# OpenMP master taskloop simd directive. +CursorKind.OMP_MASTER_TASK_LOOP_SIMD_DIRECTIVE = CursorKind(283) + +# OpenMP parallel master taskloop simd directive. +CursorKind.OMP_PARALLEL_MASTER_TASK_LOOP_SIMD_DIRECTIVE = CursorKind(284) + +# OpenMP parallel master directive. +CursorKind.OMP_PARALLEL_MASTER_DIRECTIVE = CursorKind(285) + +# OpenMP depobj directive. +CursorKind.OMP_DEPOBJ_DIRECTIVE = CursorKind(286) + +# OpenMP scan directive. +CursorKind.OMP_SCAN_DIRECTIVE = CursorKind(287) + +# OpenMP tile directive. +CursorKind.OMP_TILE_DIRECTIVE = CursorKind(288) + +# OpenMP canonical loop. +CursorKind.OMP_CANONICAL_LOOP = CursorKind(289) + +# OpenMP interop directive. +CursorKind.OMP_INTEROP_DIRECTIVE = CursorKind(290) + +# OpenMP dispatch directive. +CursorKind.OMP_DISPATCH_DIRECTIVE = CursorKind(291) + +# OpenMP masked directive. +CursorKind.OMP_MASKED_DIRECTIVE = CursorKind(292) + +# OpenMP unroll directive. +CursorKind.OMP_UNROLL_DIRECTIVE = CursorKind(293) + +# OpenMP metadirective directive. +CursorKind.OMP_META_DIRECTIVE = CursorKind(294) + +# OpenMP loop directive. +CursorKind.OMP_GENERIC_LOOP_DIRECTIVE = CursorKind(295) + +# OpenMP teams loop directive. +CursorKind.OMP_TEAMS_GENERIC_LOOP_DIRECTIVE = CursorKind(296) + +# OpenMP target teams loop directive. +CursorKind.OMP_TARGET_TEAMS_GENERIC_LOOP_DIRECTIVE = CursorKind(297) + +# OpenMP parallel loop directive. +CursorKind.OMP_PARALLEL_GENERIC_LOOP_DIRECTIVE = CursorKind(298) + +# OpenMP target parallel loop directive. +CursorKind.OMP_TARGET_PARALLEL_GENERIC_LOOP_DIRECTIVE = CursorKind(299) + +# OpenMP parallel masked directive. +CursorKind.OMP_PARALLEL_MASKED_DIRECTIVE = CursorKind(300) + +# OpenMP masked taskloop directive. +CursorKind.OMP_MASKED_TASK_LOOP_DIRECTIVE = CursorKind(301) + +# OpenMP masked taskloop simd directive. +CursorKind.OMP_MASKED_TASK_LOOP_SIMD_DIRECTIVE = CursorKind(302) + +# OpenMP parallel masked taskloop directive. +CursorKind.OMP_PARALLEL_MASKED_TASK_LOOP_DIRECTIVE = CursorKind(303) + +# OpenMP parallel masked taskloop simd directive. +CursorKind.OMP_PARALLEL_MASKED_TASK_LOOP_SIMD_DIRECTIVE = CursorKind(304) + +# OpenMP error directive. +CursorKind.OMP_ERROR_DIRECTIVE = CursorKind(305) + +# OpenMP scope directive. +CursorKind.OMP_SCOPE_DIRECTIVE = CursorKind(306) + +# OpenACC Compute Construct. +CursorKind.OPEN_ACC_COMPUTE_DIRECTIVE = CursorKind(320) + ### # Other Kinds @@ -1349,6 +1480,24 @@ CursorKind.VISIBILITY_ATTR = CursorKind(417) CursorKind.DLLEXPORT_ATTR = CursorKind(418) CursorKind.DLLIMPORT_ATTR = CursorKind(419) +CursorKind.NS_RETURNS_RETAINED = CursorKind(420) +CursorKind.NS_RETURNS_NOT_RETAINED = CursorKind(421) +CursorKind.NS_RETURNS_AUTORELEASED = CursorKind(422) +CursorKind.NS_CONSUMES_SELF = CursorKind(423) +CursorKind.NS_CONSUMED = CursorKind(424) +CursorKind.OBJC_EXCEPTION = CursorKind(425) +CursorKind.OBJC_NSOBJECT = CursorKind(426) +CursorKind.OBJC_INDEPENDENT_CLASS = CursorKind(427) +CursorKind.OBJC_PRECISE_LIFETIME = CursorKind(428) +CursorKind.OBJC_RETURNS_INNER_POINTER = CursorKind(429) +CursorKind.OBJC_REQUIRES_SUPER = CursorKind(430) +CursorKind.OBJC_ROOT_CLASS = CursorKind(431) +CursorKind.OBJC_SUBCLASSING_RESTRICTED = CursorKind(432) +CursorKind.OBJC_EXPLICIT_PROTOCOL_IMPL = CursorKind(433) +CursorKind.OBJC_DESIGNATED_INITIALIZER = CursorKind(434) +CursorKind.OBJC_RUNTIME_VISIBLE = CursorKind(435) +CursorKind.OBJC_BOXABLE = CursorKind(436) +CursorKind.FLAG_ENUM = CursorKind(437) CursorKind.CONVERGENT_ATTR = CursorKind(438) CursorKind.WARN_UNUSED_ATTR = CursorKind(439) CursorKind.WARN_UNUSED_RESULT_ATTR = CursorKind(440) @@ -1395,6 +1544,11 @@ TemplateArgumentKind.TYPE = TemplateArgumentKind(1) TemplateArgumentKind.DECLARATION = TemplateArgumentKind(2) TemplateArgumentKind.NULLPTR = TemplateArgumentKind(3) TemplateArgumentKind.INTEGRAL = TemplateArgumentKind(4) +TemplateArgumentKind.TEMPLATE = TemplateArgumentKind(5) +TemplateArgumentKind.TEMPLATE_EXPANSION = TemplateArgumentKind(6) +TemplateArgumentKind.EXPRESSION = TemplateArgumentKind(7) +TemplateArgumentKind.PACK = TemplateArgumentKind(8) +TemplateArgumentKind.INVALID = TemplateArgumentKind(9) ### Exception Specification Kinds ### class ExceptionSpecificationKind(BaseEnumeration): @@ -2240,9 +2394,26 @@ TypeKind.OCLEVENT = TypeKind(158) TypeKind.OCLQUEUE = TypeKind(159) TypeKind.OCLRESERVEID = TypeKind(160) +TypeKind.OBJCOBJECT = TypeKind(161) +TypeKind.OBJCCLASS = TypeKind(162) +TypeKind.ATTRIBUTED = TypeKind(163) + +TypeKind.OCLINTELSUBGROUPAVCMCEPAYLOAD = TypeKind(164) +TypeKind.OCLINTELSUBGROUPAVCIMEPAYLOAD = TypeKind(165) +TypeKind.OCLINTELSUBGROUPAVCREFPAYLOAD = TypeKind(166) +TypeKind.OCLINTELSUBGROUPAVCSICPAYLOAD = TypeKind(167) +TypeKind.OCLINTELSUBGROUPAVCMCERESULT = TypeKind(168) +TypeKind.OCLINTELSUBGROUPAVCIMERESULT = TypeKind(169) +TypeKind.OCLINTELSUBGROUPAVCREFRESULT = TypeKind(170) +TypeKind.OCLINTELSUBGROUPAVCSICRESULT = TypeKind(171) +TypeKind.OCLINTELSUBGROUPAVCIMERESULTSINGLEREFERENCESTREAMOUT = TypeKind(172) +TypeKind.OCLINTELSUBGROUPAVCIMERESULTSDUALREFERENCESTREAMOUT = TypeKind(173) +TypeKind.OCLINTELSUBGROUPAVCIMERESULTSSINGLEREFERENCESTREAMIN = TypeKind(174) +TypeKind.OCLINTELSUBGROUPAVCIMEDUALREFERENCESTREAMIN = TypeKind(175) + TypeKind.EXTVECTOR = TypeKind(176) TypeKind.ATOMIC = TypeKind(177) - +TypeKind.BTFTAGATTRIBUTED = TypeKind(178) class RefQualifierKind(BaseEnumeration): """Describes a specific ref-qualifier of a type.""" diff --git a/clang/cmake/caches/CrossWinToARMLinux.cmake b/clang/cmake/caches/CrossWinToARMLinux.cmake index 2a0953af53faddfdc7885cdd1021bb715165dc50..736a54ece550c62a589e0a48b97e7a61eccd01af 100644 --- a/clang/cmake/caches/CrossWinToARMLinux.cmake +++ b/clang/cmake/caches/CrossWinToARMLinux.cmake @@ -29,6 +29,11 @@ # cmake --build . --target check-cxxabi- # cmake --build . --target check-unwind- # cmake --build . --target check-cxx- +# (another way to execute the tests) +# python bin/llvm-lit.py -v --threads=32 runtimes/runtimes-bins/libunwind/test 2>&1 | tee libunwind-tests.log +# python bin/llvm-lit.py -v --threads=32 runtimes/runtimes--bins/libcxxabi/test 2>&1 | tee libcxxabi-tests.log +# python bin/llvm-lit.py -v --threads=32 runtimes/runtimes--bins/libcxx/test 2>&1 | tee libcxx-tests.log + # LLVM_PROJECT_DIR is the path to the llvm-project directory. # The right way to compute it would probably be to use "${CMAKE_SOURCE_DIR}/../", @@ -42,9 +47,6 @@ if (NOT DEFINED DEFAULT_SYSROOT) message(WARNING "DEFAULT_SYSROOT must be specified for the cross toolchain build.") endif() -if (NOT DEFINED LLVM_TARGETS_TO_BUILD) - set(LLVM_TARGETS_TO_BUILD "ARM" CACHE STRING "") -endif() if (NOT DEFINED LLVM_ENABLE_ASSERTIONS) set(LLVM_ENABLE_ASSERTIONS ON CACHE BOOL "") endif() @@ -56,7 +58,7 @@ if (NOT DEFINED LLVM_ENABLE_RUNTIMES) endif() if (NOT DEFINED TOOLCHAIN_TARGET_TRIPLE) - set(TOOLCHAIN_TARGET_TRIPLE "armv7-unknown-linux-gnueabihf") + set(TOOLCHAIN_TARGET_TRIPLE "aarch64-unknown-linux-gnu") else() #NOTE: we must normalize specified target triple to a fully specified triple, # including the vendor part. It is necessary to synchronize the runtime library @@ -74,24 +76,38 @@ else() string(REPLACE ";" "-" TOOLCHAIN_TARGET_TRIPLE "${TOOLCHAIN_TARGET_TRIPLE}") endif() +message(STATUS "Toolchain target triple: ${TOOLCHAIN_TARGET_TRIPLE}") + +if (NOT DEFINED LLVM_TARGETS_TO_BUILD) + if ("${TOOLCHAIN_TARGET_TRIPLE}" MATCHES "^(armv|arm32)+") + set(LLVM_TARGETS_TO_BUILD "ARM" CACHE STRING "") + endif() + if ("${TOOLCHAIN_TARGET_TRIPLE}" MATCHES "^(aarch64|arm64)+") + set(LLVM_TARGETS_TO_BUILD "AArch64" CACHE STRING "") + endif() +endif() + +message(STATUS "Toolchain target to build: ${LLVM_TARGETS_TO_BUILD}") + if (NOT DEFINED CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") endif() -message(STATUS "Toolchain target triple: ${TOOLCHAIN_TARGET_TRIPLE}") - set(CMAKE_CROSSCOMPILING ON CACHE BOOL "") set(CMAKE_CL_SHOWINCLUDES_PREFIX "Note: including file: " CACHE STRING "") # Required if COMPILER_RT_DEFAULT_TARGET_ONLY is ON set(CMAKE_C_COMPILER_TARGET "${TOOLCHAIN_TARGET_TRIPLE}" CACHE STRING "") set(CMAKE_CXX_COMPILER_TARGET "${TOOLCHAIN_TARGET_TRIPLE}" CACHE STRING "") -set(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR ON CACHE BOOL "") set(LLVM_DEFAULT_TARGET_TRIPLE "${TOOLCHAIN_TARGET_TRIPLE}" CACHE STRING "") set(LLVM_TARGET_ARCH "${TOOLCHAIN_TARGET_TRIPLE}" CACHE STRING "") set(LLVM_LIT_ARGS "-vv ${LLVM_LIT_ARGS}" CACHE STRING "" FORCE) +set(CLANG_DEFAULT_CXX_STDLIB "libc++" CACHE STRING "") set(CLANG_DEFAULT_LINKER "lld" CACHE STRING "") +set(CLANG_DEFAULT_OBJCOPY "llvm-objcopy" CACHE STRING "") +set(CLANG_DEFAULT_RTLIB "compiler-rt" CACHE STRING "") +set(CLANG_DEFAULT_UNWINDLIB "libunwind" CACHE STRING "") if(WIN32) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded" CACHE STRING "") @@ -109,9 +125,10 @@ set(BUILTINS_${TOOLCHAIN_TARGET_TRIPLE}_CMAKE_SYSTEM_NAME set(BUILTINS_${TOOLCHAIN_TARGET_TRIPLE}_CMAKE_SYSROOT "${DEFAULT_SYSROOT}" CACHE STRING "") set(BUILTINS_${TOOLCHAIN_TARGET_TRIPLE}_CMAKE_INSTALL_RPATH "${RUNTIMES_INSTALL_RPATH}" CACHE STRING "") set(BUILTINS_${TOOLCHAIN_TARGET_TRIPLE}_CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE BOOL "") - +set(BUILTINS_${TOOLCHAIN_TARGET_TRIPLE}_LLVM_CMAKE_DIR "${LLVM_PROJECT_DIR}/llvm/cmake/modules" CACHE PATH "") set(LLVM_RUNTIME_TARGETS "${TOOLCHAIN_TARGET_TRIPLE}" CACHE STRING "") +set(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR ON CACHE BOOL "") set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LLVM_ENABLE_RUNTIMES "${LLVM_ENABLE_RUNTIMES}" CACHE STRING "") @@ -125,13 +142,16 @@ set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_COMPILER_RT_BUILD_SANITIZERS set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_COMPILER_RT_BUILD_XRAY OFF CACHE BOOL "") set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_COMPILER_RT_BUILD_LIBFUZZER OFF CACHE BOOL "") set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_COMPILER_RT_BUILD_PROFILE OFF CACHE BOOL "") -set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_COMPILER_RT_BUILD_CRT OFF CACHE BOOL "") +set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_COMPILER_RT_BUILD_CRT ON CACHE BOOL "") set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_COMPILER_RT_BUILD_ORC OFF CACHE BOOL "") set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_COMPILER_RT_DEFAULT_TARGET_ONLY ON CACHE BOOL "") set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_COMPILER_RT_INCLUDE_TESTS ON CACHE BOOL "") set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_COMPILER_RT_CAN_EXECUTE_TESTS ON CACHE BOOL "") set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_COMPILER_RT_USE_BUILTINS_LIBRARY ON CACHE BOOL "") +set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_COMPILER_RT_CXX_LIBRARY libcxx CACHE STRING "") +# Tell Clang to seach C++ headers alongside with the just-built binaries for the C++ compiler-rt tests. +set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_COMPILER_RT_TEST_COMPILER_CFLAGS "--stdlib=libc++" CACHE STRING "") set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "") set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "") @@ -148,8 +168,10 @@ set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ABI_VERSION set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_CXX_ABI "libcxxabi" CACHE STRING "") #!!! set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS ON CACHE BOOL "") - +# Avoid searching for the python3 interpreter during the runtimes configuration for the cross builds. +# It starts searching the python3 package using the target's sysroot path, that usually is not compatible with the build host. find_package(Python3 COMPONENTS Interpreter) +set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_Python3_EXECUTABLE ${Python3_EXECUTABLE} CACHE PATH "") set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBUNWIND_TEST_PARAMS_default "${RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_TEST_PARAMS}") set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXXABI_TEST_PARAMS_default "${RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_TEST_PARAMS}") diff --git a/clang/cmake/caches/Fuchsia-stage2.cmake b/clang/cmake/caches/Fuchsia-stage2.cmake index db7430b3344c3e76c15b0038ad9011a0c8e2fecb..d5546e20873b3c580684a5b1d330aeb0a462a944 100644 --- a/clang/cmake/caches/Fuchsia-stage2.cmake +++ b/clang/cmake/caches/Fuchsia-stage2.cmake @@ -11,6 +11,7 @@ set(LLVM_ENABLE_RUNTIMES "compiler-rt;libcxx;libcxxabi;libunwind" CACHE STRING " set(LLVM_ENABLE_BACKTRACES OFF CACHE BOOL "") set(LLVM_ENABLE_DIA_SDK OFF CACHE BOOL "") +set(LLVM_ENABLE_FATLTO ON CACHE BOOL "") set(LLVM_ENABLE_HTTPLIB ON CACHE BOOL "") set(LLVM_ENABLE_LIBCXX ON CACHE BOOL "") set(LLVM_ENABLE_LIBEDIT OFF CACHE BOOL "") diff --git a/clang/cmake/caches/Fuchsia.cmake b/clang/cmake/caches/Fuchsia.cmake index 1209fd93598613f8ef23cdd554a892d683053ba3..df69d7d0dd414beb8be6752acae171cf6fd5272e 100644 --- a/clang/cmake/caches/Fuchsia.cmake +++ b/clang/cmake/caches/Fuchsia.cmake @@ -66,6 +66,7 @@ set(_FUCHSIA_BOOTSTRAP_PASSTHROUGH LLDB_PYTHON_HOME LLDB_PYTHON_RELATIVE_PATH LLDB_TEST_USE_VENDOR_PACKAGES + LLDB_TEST_USER_ARGS Python3_EXECUTABLE Python3_LIBRARIES Python3_INCLUDE_DIRS diff --git a/clang/cmake/caches/HLSL.cmake b/clang/cmake/caches/HLSL.cmake index 71f81e53f6bd351f18e8d23cbc1ec24ced9622ac..84850c86f12cd7ab92237452ce8b2bd8fdfb0dce 100644 --- a/clang/cmake/caches/HLSL.cmake +++ b/clang/cmake/caches/HLSL.cmake @@ -4,7 +4,7 @@ set(LLVM_TARGETS_TO_BUILD Native CACHE STRING "") # Include the DirectX target for DXIL code generation, eventually we'll include # SPIR-V here too. -set(LLVM_EXPERIMENTAL_TARGETS_TO_BUILD DirectX CACHE STRING "") +set(LLVM_EXPERIMENTAL_TARGETS_TO_BUILD "DirectX;SPIRV" CACHE STRING "") # HLSL support is currently limted to clang, eventually it will expand to # clang-tools-extra too. diff --git a/clang/docs/ClangFormat.rst b/clang/docs/ClangFormat.rst index 819d9ee9f9cde1cba0cad142364dab42c3f276c2..80dc38a075c8fcf572ce093da3893007e23342b4 100644 --- a/clang/docs/ClangFormat.rst +++ b/clang/docs/ClangFormat.rst @@ -61,6 +61,7 @@ to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# code. --dry-run - If set, do not actually make the formatting changes --dump-config - Dump configuration options to stdout and exit. Can be used with -style option. + --fail-on-incomplete-format - If set, fail with exit code 1 on incomplete format. --fallback-style= - The name of the predefined style used as a fallback in case clang-format is invoked with -style=file, but can not find the .clang-format diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 5b00a8f4c00fb81ebb95d9be945db223b2561803..39f7cded36edbff5846925aa56319682a04ed476 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -955,6 +955,151 @@ the configuration (without a prefix: ``Auto``). } +.. _AlignConsecutiveTableGenBreakingDAGArgColons: + +**AlignConsecutiveTableGenBreakingDAGArgColons** (``AlignConsecutiveStyle``) :versionbadge:`clang-format 19` :ref:`¶ ` + Style of aligning consecutive TableGen DAGArg operator colons. + If enabled, align the colon inside DAGArg which have line break inside. + This works only when TableGenBreakInsideDAGArg is BreakElements or + BreakAll and the DAGArg is not excepted by + TableGenBreakingDAGArgOperators's effect. + + .. code-block:: c++ + + let dagarg = (ins + a :$src1, + aa :$src2, + aaa:$src3 + ) + + Nested configuration flags: + + Alignment options. + + They can also be read as a whole for compatibility. The choices are: + - None + - Consecutive + - AcrossEmptyLines + - AcrossComments + - AcrossEmptyLinesAndComments + + For example, to align across empty lines and not across comments, either + of these work. + + .. code-block:: c++ + + AlignConsecutiveTableGenBreakingDAGArgColons: AcrossEmptyLines + + AlignConsecutiveTableGenBreakingDAGArgColons: + Enabled: true + AcrossEmptyLines: true + AcrossComments: false + + * ``bool Enabled`` Whether aligning is enabled. + + .. code-block:: c++ + + #define SHORT_NAME 42 + #define LONGER_NAME 0x007f + #define EVEN_LONGER_NAME (2) + #define foo(x) (x * x) + #define bar(y, z) (y + z) + + int a = 1; + int somelongname = 2; + double c = 3; + + int aaaa : 1; + int b : 12; + int ccc : 8; + + int aaaa = 12; + float b = 23; + std::string ccc; + + * ``bool AcrossEmptyLines`` Whether to align across empty lines. + + .. code-block:: c++ + + true: + int a = 1; + int somelongname = 2; + double c = 3; + + int d = 3; + + false: + int a = 1; + int somelongname = 2; + double c = 3; + + int d = 3; + + * ``bool AcrossComments`` Whether to align across comments. + + .. code-block:: c++ + + true: + int d = 3; + /* A comment. */ + double e = 4; + + false: + int d = 3; + /* A comment. */ + double e = 4; + + * ``bool AlignCompound`` Only for ``AlignConsecutiveAssignments``. Whether compound assignments + like ``+=`` are aligned along with ``=``. + + .. code-block:: c++ + + true: + a &= 2; + bbb = 2; + + false: + a &= 2; + bbb = 2; + + * ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are + aligned. + + .. code-block:: c++ + + true: + unsigned i; + int &r; + int *p; + int (*f)(); + + false: + unsigned i; + int &r; + int *p; + int (*f)(); + + * ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment + operators are left-padded to the same length as long ones in order to + put all assignment operators to the right of the left hand side. + + .. code-block:: c++ + + true: + a >>= 2; + bbb = 2; + + a = 2; + bbb >>= 2; + + false: + a >>= 2; + bbb = 2; + + a = 2; + bbb >>= 2; + + .. _AlignConsecutiveTableGenCondOperatorColons: **AlignConsecutiveTableGenCondOperatorColons** (``AlignConsecutiveStyle``) :versionbadge:`clang-format 19` :ref:`¶ ` @@ -3150,6 +3295,21 @@ the configuration (without a prefix: ``Auto``). +.. _BreakFunctionDefinitionParameters: + +**BreakFunctionDefinitionParameters** (``Boolean``) :versionbadge:`clang-format 19` :ref:`¶ ` + If ``true``, clang-format will always break before function definition + parameters. + + .. code-block:: c++ + + true: + void functionDefinition( + int A, int B) {} + + false: + void functionDefinition(int A, int B) {} + .. _BreakInheritanceList: **BreakInheritanceList** (``BreakInheritanceListStyle``) :versionbadge:`clang-format 7` :ref:`¶ ` @@ -6158,6 +6318,70 @@ the configuration (without a prefix: ``Auto``). **TabWidth** (``Unsigned``) :versionbadge:`clang-format 3.7` :ref:`¶ ` The number of columns used for tab stops. +.. _TableGenBreakInsideDAGArg: + +**TableGenBreakInsideDAGArg** (``DAGArgStyle``) :versionbadge:`clang-format 19` :ref:`¶ ` + The styles of the line break inside the DAGArg in TableGen. + + Possible values: + + * ``DAS_DontBreak`` (in configuration: ``DontBreak``) + Never break inside DAGArg. + + .. code-block:: c++ + + let DAGArgIns = (ins i32:$src1, i32:$src2); + + * ``DAS_BreakElements`` (in configuration: ``BreakElements``) + Break inside DAGArg after each list element but for the last. + This aligns to the first element. + + .. code-block:: c++ + + let DAGArgIns = (ins i32:$src1, + i32:$src2); + + * ``DAS_BreakAll`` (in configuration: ``BreakAll``) + Break inside DAGArg after the operator and the all elements. + + .. code-block:: c++ + + let DAGArgIns = (ins + i32:$src1, + i32:$src2 + ); + + + +.. _TableGenBreakingDAGArgOperators: + +**TableGenBreakingDAGArgOperators** (``List of Strings``) :versionbadge:`clang-format 19` :ref:`¶ ` + Works only when TableGenBreakInsideDAGArg is not DontBreak. + The string list needs to consist of identifiers in TableGen. + If any identifier is specified, this limits the line breaks by + TableGenBreakInsideDAGArg option only on DAGArg values beginning with + the specified identifiers. + + For example the configuration, + + .. code-block:: yaml + + TableGenBreakInsideDAGArg: BreakAll + TableGenBreakingDAGArgOperators: ['ins', 'outs'] + + makes the line break only occurs inside DAGArgs beginning with the + specified identifiers 'ins' and 'outs'. + + + .. code-block:: c++ + + let DAGArgIns = (ins + i32:$src1, + i32:$src2 + ); + let DAGArgOtherID = (other i32:$other1, i32:$other2); + let DAGArgBang = (!cast("Some") i32:$src1, i32:$src2) + .. _TypeNames: **TypeNames** (``List of Strings``) :versionbadge:`clang-format 17` :ref:`¶ ` diff --git a/clang/docs/HLSL/FunctionCalls.rst b/clang/docs/HLSL/FunctionCalls.rst index 7317de2163f8975b3d9d283a55aa8d4d9ba2ac55..6d65fe6e3fb20b90a3a755a13123042de2226958 100644 --- a/clang/docs/HLSL/FunctionCalls.rst +++ b/clang/docs/HLSL/FunctionCalls.rst @@ -157,22 +157,23 @@ Clang Implementation of the changes in the prototype implementation are restoring Clang-3.7 code that was previously modified to its original state. -The implementation in clang depends on two new AST nodes and minor extensions to -Clang's existing support for Objective-C write-back arguments. The goal of this -design is to capture the semantic details of HLSL function calls in the AST, and -minimize the amount of magic that needs to occur during IR generation. - -The two new AST nodes are ``HLSLArrayTemporaryExpr`` and ``HLSLOutParamExpr``, -which respectively represent the temporaries used for passing arrays by value -and the temporaries created for function outputs. +The implementation in clang adds a new non-decaying array type, a new AST node +to represent output parameters, and minor extensions to Clang's existing support +for Objective-C write-back arguments. The goal of this design is to capture the +semantic details of HLSL function calls in the AST, and minimize the amount of +magic that needs to occur during IR generation. Array Temporaries ----------------- -The ``HLSLArrayTemporaryExpr`` represents temporary values for input -constant-sized array arguments. This applies for all constant-sized array -arguments regardless of whether or not the parameter is constant-sized or -unsized. +The new ``ArrayParameterType`` is a sub-class of ``ConstantArrayType`` +inheriting all the behaviors and methods of the parent except that it does not +decay to a pointer during overload resolution or template type deduction. + +An argument of ``ConstantArrayType`` can be implicitly converted to an +equivalent non-decayed ``ArrayParameterType`` if the underlying canonical +``ConstantArrayType`` is the same. This occurs during overload resolution +instead of array to pointer decay. .. code-block:: c++ @@ -193,7 +194,7 @@ In the example above, the following AST is generated for the call to CallExpr 'void' |-ImplicitCastExpr 'void (*)(float [4])' | `-DeclRefExpr 'void (float [4])' lvalue Function 'SizedArray' 'void (float [4])' - `-HLSLArrayTemporaryExpr 'float [4]' + `-ImplicitCastExpr 'float [4]' `-DeclRefExpr 'float [4]' lvalue Var 'arr' 'float [4]' In the example above, the following AST is generated for the call to @@ -204,7 +205,7 @@ In the example above, the following AST is generated for the call to CallExpr 'void' |-ImplicitCastExpr 'void (*)(float [])' | `-DeclRefExpr 'void (float [])' lvalue Function 'UnsizedArray' 'void (float [])' - `-HLSLArrayTemporaryExpr 'float [4]' + `-ImplicitCastExpr 'float [4]' `-DeclRefExpr 'float [4]' lvalue Var 'arr' 'float [4]' In both of these cases the argument expression is of known array size so we can @@ -236,7 +237,7 @@ An expected AST should be something like: CallExpr 'void' |-ImplicitCastExpr 'void (*)(float [])' | `-DeclRefExpr 'void (float [])' lvalue Function 'UnsizedArray' 'void (float [])' - `-HLSLArrayTemporaryExpr 'float [4]' + `-ImplicitCastExpr 'float [4]' `-DeclRefExpr 'float [4]' lvalue Var 'arr' 'float [4]' Out Parameter Temporaries diff --git a/clang/docs/HLSL/HLSLSupport.rst b/clang/docs/HLSL/HLSLSupport.rst index b091c17fd2a764d68039e84d7282e4abfb82d586..2d309ddff2f36aa8413331627eb3fd6487bdd40c 100644 --- a/clang/docs/HLSL/HLSLSupport.rst +++ b/clang/docs/HLSL/HLSLSupport.rst @@ -91,7 +91,7 @@ performance win for HLSL. If precompiled headers are used when compiling HLSL, the ``ExternalSemaSource`` will be a ``MultiplexExternalSemaSource`` which includes both the ``ASTReader`` -and ``HLSLExternalSemaSource``. For Built-in declarations that are already +and -. For Built-in declarations that are already completed in the serialized AST, the ``HLSLExternalSemaSource`` will reuse the existing declarations and not introduce new declarations. If the built-in types are not completed in the serialized AST, the ``HLSLExternalSemaSource`` will @@ -114,6 +114,54 @@ not re-targetable, we want to share the Clang CodeGen implementation for HLSL with other GPU graphics targets like SPIR-V and possibly other GPU and even CPU targets. +hlsl.h +------ + +HLSL has a library of standalone functions. This is similar to OpenCL and CUDA, +and is analogous to C's standard library. The implementation approach for the +HLSL library functionality draws from patterns in use by OpenCL and other Clang +resource headers. All of the clang resource headers are part of the +``ClangHeaders`` component found in the source tree under +`clang/lib/Headers `_. + +.. note:: + + HLSL's complex data types are not defined in HLSL's header because many of + the semantics of those data types cannot be expressed in HLSL due to missing + language features. Data types that can't be expressed in HLSL are defined in + code in the ``HLSLExternalSemaSource``. + +Similar to OpenCL, the HLSL library functionality is implicitly declared in +translation units without needing to include a header to provide declarations. +In Clang this is handled by making ``hlsl.h`` an implicitly included header +distributed as part of the Clang resource directory. + +Similar to OpenCL, HLSL's implicit header will explicitly declare all overloads, +and each overload will map to a corresponding ``__builtin*`` compiler intrinsic +that is handled in ClangCodeGen. CUDA uses a similar pattern although many CUDA +functions have full definitions in the included headers which in turn call +corresponding ``__builtin*`` compiler intrinsics. By not having bodies HLSL +avoids the need for the inliner to clean up and inline large numbers of small +library functions. + +HLSL's implicit headers also define some of HLSL's typedefs. This is consistent +with how the AVX vector header is implemented. + +Concerns have been expressed that this approach may result in slower compile +times than the approach DXC uses where library functions are treated more like +Clang ``__builtin*`` intrinsics. No real world use cases have been identified +where parsing is a significant compile-time overhead, but the HLSL implicit +headers can be compiled into a module for performance if needed. + +Further, by treating these as functions rather than ``__builtin*`` compiler +intrinsics, the language behaviors are more consistent and aligned with user +expectation because normal overload resolution rules and implicit conversions +apply as expected. + +It is a feature of this design that clangd-powered "go to declaration" for +library functions will jump to a valid header declaration and all overloads will +be user readable. + HLSL Language ============= diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 06af93fd3c15ca8ce3da56190a024f3ee3ffb5e4..7b23e4d1c2f30c1544b2eba17b2a53849a6bc6a9 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -13,6 +13,7 @@ Clang Language Extensions BlockLanguageSpec Block-ABI-Apple AutomaticReferenceCounting + PointerAuthentication MatrixTypes Introduction @@ -1458,40 +1459,45 @@ More information could be found `here Language Extensions Back-ported to Previous Standards ===================================================== -====================================== ================================ ============= ============= -Feature Feature Test Macro Introduced In Backported To -====================================== ================================ ============= ============= -variadic templates __cpp_variadic_templates C++11 C++03 -Alias templates __cpp_alias_templates C++11 C++03 -Non-static data member initializers __cpp_nsdmi C++11 C++03 -Range-based ``for`` loop __cpp_range_based_for C++11 C++03 -RValue references __cpp_rvalue_references C++11 C++03 -Attributes __cpp_attributes C++11 C++03 -variable templates __cpp_variable_templates C++14 C++03 -Binary literals __cpp_binary_literals C++14 C++03 -Relaxed constexpr __cpp_constexpr C++14 C++11 -``if constexpr`` __cpp_if_constexpr C++17 C++11 -fold expressions __cpp_fold_expressions C++17 C++03 -Lambda capture of \*this by value __cpp_capture_star_this C++17 C++11 -Attributes on enums __cpp_enumerator_attributes C++17 C++03 -Guaranteed copy elision __cpp_guaranteed_copy_elision C++17 C++03 -Hexadecimal floating literals __cpp_hex_float C++17 C++03 -``inline`` variables __cpp_inline_variables C++17 C++03 -Attributes on namespaces __cpp_namespace_attributes C++17 C++11 -Structured bindings __cpp_structured_bindings C++17 C++03 -template template arguments __cpp_template_template_args C++17 C++03 -``static operator[]`` __cpp_multidimensional_subscript C++20 C++03 -Designated initializers __cpp_designated_initializers C++20 C++03 -Conditional ``explicit`` __cpp_conditional_explicit C++20 C++03 -``using enum`` __cpp_using_enum C++20 C++03 -``if consteval`` __cpp_if_consteval C++23 C++20 -``static operator()`` __cpp_static_call_operator C++23 C++03 -Attributes on Lambda-Expressions C++23 C++11 --------------------------------------- -------------------------------- ------------- ------------- -Designated initializers (N494) C99 C89 -Array & element qualification (N2607) C23 C89 -Attributes (N2335) C23 C89 -====================================== ================================ ============= ============= +============================================ ================================ ============= ============= +Feature Feature Test Macro Introduced In Backported To +============================================ ================================ ============= ============= +variadic templates __cpp_variadic_templates C++11 C++03 +Alias templates __cpp_alias_templates C++11 C++03 +Non-static data member initializers __cpp_nsdmi C++11 C++03 +Range-based ``for`` loop __cpp_range_based_for C++11 C++03 +RValue references __cpp_rvalue_references C++11 C++03 +Attributes __cpp_attributes C++11 C++03 +Lambdas __cpp_lambdas C++11 C++03 +Generalized lambda captures __cpp_init_captures C++14 C++03 +Generic lambda expressions __cpp_generic_lambdas C++14 C++03 +variable templates __cpp_variable_templates C++14 C++03 +Binary literals __cpp_binary_literals C++14 C++03 +Relaxed constexpr __cpp_constexpr C++14 C++11 +Pack expansion in generalized lambda-capture __cpp_init_captures C++17 C++03 +``if constexpr`` __cpp_if_constexpr C++17 C++11 +fold expressions __cpp_fold_expressions C++17 C++03 +Lambda capture of \*this by value __cpp_capture_star_this C++17 C++03 +Attributes on enums __cpp_enumerator_attributes C++17 C++03 +Guaranteed copy elision __cpp_guaranteed_copy_elision C++17 C++03 +Hexadecimal floating literals __cpp_hex_float C++17 C++03 +``inline`` variables __cpp_inline_variables C++17 C++03 +Attributes on namespaces __cpp_namespace_attributes C++17 C++11 +Structured bindings __cpp_structured_bindings C++17 C++03 +template template arguments __cpp_template_template_args C++17 C++03 +Familiar template syntax for generic lambdas __cpp_generic_lambdas C++20 C++03 +``static operator[]`` __cpp_multidimensional_subscript C++20 C++03 +Designated initializers __cpp_designated_initializers C++20 C++03 +Conditional ``explicit`` __cpp_conditional_explicit C++20 C++03 +``using enum`` __cpp_using_enum C++20 C++03 +``if consteval`` __cpp_if_consteval C++23 C++20 +``static operator()`` __cpp_static_call_operator C++23 C++03 +Attributes on Lambda-Expressions C++23 C++11 +-------------------------------------------- -------------------------------- ------------- ------------- +Designated initializers (N494) C99 C89 +Array & element qualification (N2607) C23 C89 +Attributes (N2335) C23 C89 +============================================ ================================ ============= ============= Type Trait Primitives ===================== @@ -3443,6 +3449,21 @@ Query for this feature with ``__has_builtin(__builtin_debugtrap)``. Query for this feature with ``__has_builtin(__builtin_trap)``. +``__builtin_arm_trap`` +---------------------- + +``__builtin_arm_trap`` is an AArch64 extension to ``__builtin_trap`` which also accepts a compile-time constant value, encoded directly into the trap instruction for later inspection. + +**Syntax**: + +.. code-block:: c++ + + __builtin_arm_trap(const unsigned short payload) + +**Description** + +``__builtin_arm_trap`` is lowered to the ``llvm.aarch64.break`` builtin, and then to ``brk #payload``. + ``__builtin_nondeterministic_value`` ------------------------------------ @@ -3532,6 +3553,47 @@ argument can be of any unsigned integer type. ``__builtin_popcount{,l,ll}`` builtins, with support for other integer types, such as ``unsigned __int128`` and C23 ``unsigned _BitInt(N)``. +``__builtin_clzg`` and ``__builtin_ctzg`` +----------------------------------------- + +``__builtin_clzg`` (respectively ``__builtin_ctzg``) returns the number of +leading (respectively trailing) 0 bits in the first argument. The first argument +can be of any unsigned integer type. + +If the first argument is 0 and an optional second argument of ``int`` type is +provided, then the second argument is returned. If the first argument is 0, but +only one argument is provided, then the behavior is undefined. + +**Syntax**: + +.. code-block:: c++ + + int __builtin_clzg(type x[, int fallback]) + int __builtin_ctzg(type x[, int fallback]) + +**Examples**: + +.. code-block:: c++ + + unsigned int x = 1; + int x_lz = __builtin_clzg(x); + int x_tz = __builtin_ctzg(x); + + unsigned long y = 2; + int y_lz = __builtin_clzg(y); + int y_tz = __builtin_ctzg(y); + + unsigned _BitInt(128) z = 4; + int z_lz = __builtin_clzg(z); + int z_tz = __builtin_ctzg(z); + +**Description**: + +``__builtin_clzg`` (respectively ``__builtin_ctzg``) is meant to be a +type-generic alternative to the ``__builtin_clz{,l,ll}`` (respectively +``__builtin_ctz{,l,ll}``) builtins, with support for other integer types, such +as ``unsigned __int128`` and C23 ``unsigned _BitInt(N)``. + Multiprecision Arithmetic Builtins ---------------------------------- @@ -4303,6 +4365,10 @@ reordering of memory accesses and side effect instructions. Other instructions like simple arithmetic may be reordered around the intrinsic. If you expect to have no reordering at all, use inline assembly instead. +Pointer Authentication +^^^^^^^^^^^^^^^^^^^^^^ +See :doc:`PointerAuthentication`. + X86/X86-64 Language Extensions ------------------------------ @@ -5354,10 +5420,12 @@ The following builtin intrinsics can be used in constant expressions: * ``__builtin_clzl`` * ``__builtin_clzll`` * ``__builtin_clzs`` +* ``__builtin_clzg`` * ``__builtin_ctz`` * ``__builtin_ctzl`` * ``__builtin_ctzll`` * ``__builtin_ctzs`` +* ``__builtin_ctzg`` * ``__builtin_ffs`` * ``__builtin_ffsl`` * ``__builtin_ffsll`` diff --git a/clang/docs/PointerAuthentication.rst b/clang/docs/PointerAuthentication.rst new file mode 100644 index 0000000000000000000000000000000000000000..19b3384293aedef5211a8d80a92efb1ba16c8cf7 --- /dev/null +++ b/clang/docs/PointerAuthentication.rst @@ -0,0 +1,485 @@ +Pointer Authentication +====================== + +.. contents:: + :local: + +Introduction +------------ + +Pointer authentication is a technology which offers strong probabilistic +protection against exploiting a broad class of memory bugs to take control of +program execution. When adopted consistently in a language ABI, it provides +a form of relatively fine-grained control flow integrity (CFI) check that +resists both return-oriented programming (ROP) and jump-oriented programming +(JOP) attacks. + +While pointer authentication can be implemented purely in software, direct +hardware support (e.g. as provided by Armv8.3 PAuth) can dramatically improve +performance and code size. Similarly, while pointer authentication +can be implemented on any architecture, taking advantage of the (typically) +excess addressing range of a target with 64-bit pointers minimizes the impact +on memory performance and can allow interoperation with existing code (by +disabling pointer authentication dynamically). This document will generally +attempt to present the pointer authentication feature independent of any +hardware implementation or ABI. Considerations that are +implementation-specific are clearly identified throughout. + +Note that there are several different terms in use: + +- **Pointer authentication** is a target-independent language technology. + +- **PAuth** (sometimes referred to as **PAC**, for Pointer Authentication + Codes) is an AArch64 architecture extension that provides hardware support + for pointer authentication. Additional extensions either modify some of the + PAuth instruction behavior (notably FPAC), or provide new instruction + variants (PAuth_LR). + +- **Armv8.3** is an AArch64 architecture revision that makes PAuth mandatory. + +- **arm64e** is a specific ABI (not yet fully stable) for implementing pointer + authentication using PAuth on certain Apple operating systems. + +This document serves four purposes: + +- It describes the basic ideas of pointer authentication. + +- It documents several language extensions that are useful on targets using + pointer authentication. + +- It will eventually present a theory of operation for the security mitigation, + describing the basic requirements for correctness, various weaknesses in the + mechanism, and ways in which programmers can strengthen its protections + (including recommendations for language implementors). + +- It will eventually document the language ABIs currently used for C, C++, + Objective-C, and Swift on arm64e, although these are not yet stable on any + target. + +Basic Concepts +-------------- + +The simple address of an object or function is a **raw pointer**. A raw +pointer can be **signed** to produce a **signed pointer**. A signed pointer +can be then **authenticated** in order to verify that it was **validly signed** +and extract the original raw pointer. These terms reflect the most likely +implementation technique: computing and storing a cryptographic signature along +with the pointer. + +An **abstract signing key** is a name which refers to a secret key which is +used to sign and authenticate pointers. The concrete key value for a +particular name is consistent throughout a process. + +A **discriminator** is an arbitrary value used to **diversify** signed pointers +so that one validly-signed pointer cannot simply be copied over another. +A discriminator is simply opaque data of some implementation-defined size that +is included in the signature as a salt (see `Discriminators`_ for details.) + +Nearly all aspects of pointer authentication use just these two primary +operations: + +- ``sign(raw_pointer, key, discriminator)`` produces a signed pointer given + a raw pointer, an abstract signing key, and a discriminator. + +- ``auth(signed_pointer, key, discriminator)`` produces a raw pointer given + a signed pointer, an abstract signing key, and a discriminator. + +``auth(sign(raw_pointer, key, discriminator), key, discriminator)`` must +succeed and produce ``raw_pointer``. ``auth`` applied to a value that was +ultimately produced in any other way is expected to fail, which halts the +program either: + +- immediately, on implementations that enforce ``auth`` success (e.g., when + using compiler-generated ``auth`` failure checks, or Armv8.3 with the FPAC + extension), or + +- when the resulting pointer value is used, on implementations that don't. + +However, regardless of the implementation's handling of ``auth`` failures, it +is permitted for ``auth`` to fail to detect that a signed pointer was not +produced in this way, in which case it may return anything; this is what makes +pointer authentication a probabilistic mitigation rather than a perfect one. + +There are two secondary operations which are required only to implement certain +intrinsics in ````: + +- ``strip(signed_pointer, key)`` produces a raw pointer given a signed pointer + and a key without verifying its validity, unlike ``auth``. This is useful + for certain kinds of tooling, such as crash backtraces; it should generally + not be used in the basic language ABI except in very careful ways. + +- ``sign_generic(value)`` produces a cryptographic signature for arbitrary + data, not necessarily a pointer. This is useful for efficiently verifying + that non-pointer data has not been tampered with. + +Whenever any of these operations is called for, the key value must be known +statically. This is because the layout of a signed pointer may vary according +to the signing key. (For example, in Armv8.3, the layout of a signed pointer +depends on whether Top Byte Ignore (TBI) is enabled, which can be set +independently for I and D keys.) + +.. admonition:: Note for API designers and language implementors + + These are the *primitive* operations of pointer authentication, provided for + clarity of description. They are not suitable either as high-level + interfaces or as primitives in a compiler IR because they expose raw + pointers. Raw pointers require special attention in the language + implementation to avoid the accidental creation of exploitable code + sequences. + +The following details are all implementation-defined: + +- the nature of a signed pointer +- the size of a discriminator +- the number and nature of the signing keys +- the implementation of the ``sign``, ``auth``, ``strip``, and ``sign_generic`` + operations + +While the use of the terms "sign" and "signed pointer" suggest the use of +a cryptographic signature, other implementations may be possible. See +`Alternative implementations`_ for an exploration of implementation options. + +.. admonition:: Implementation example: Armv8.3 + + Readers may find it helpful to know how these terms map to Armv8.3 PAuth: + + - A signed pointer is a pointer with a signature stored in the + otherwise-unused high bits. The kernel configures the address width based + on the system's addressing needs, and enables TBI for I or D keys as + needed. The bits above the address bits and below the TBI bits (if + enabled) are unused. The signature width then depends on this addressing + configuration. + + - A discriminator is a 64-bit integer. Constant discriminators are 16-bit + integers. Blending a constant discriminator into an address consists of + replacing the top 16 bits of the pointer containing the address with the + constant. Pointers used for blending purposes should only have address + bits, since higher bits will be at least partially overwritten with the + constant discriminator. + + - There are five 128-bit signing-key registers, each of which can only be + directly read or set by privileged code. Of these, four are used for + signing pointers, and the fifth is used only for ``sign_generic``. The key + data is simply a pepper added to the hash, not an encryption key, and so + can be initialized using random data. + + - ``sign`` computes a cryptographic hash of the pointer, discriminator, and + signing key, and stores it in the high bits as the signature. ``auth`` + removes the signature, computes the same hash, and compares the result with + the stored signature. ``strip`` removes the signature without + authenticating it. While ``aut*`` instructions do not themselves trap on + failure in Armv8.3 PAuth, they do with the later optional FPAC extension. + An implementation can also choose to emulate this trapping behavior by + emitting additional instructions around ``aut*``. + + - ``sign_generic`` corresponds to the ``pacga`` instruction, which takes two + 64-bit values and produces a 64-bit cryptographic hash. Implementations of + this instruction are not required to produce meaningful data in all bits of + the result. + +Discriminators +~~~~~~~~~~~~~~ + +A discriminator is arbitrary extra data which alters the signature calculated +for a pointer. When two pointers are signed differently --- either with +different keys or with different discriminators --- an attacker cannot simply +replace one pointer with the other. + +To use standard cryptographic terminology, a discriminator acts as a +`salt `_ in the signing of a +pointer, and the key data acts as a +`pepper `_. That is, +both the discriminator and key data are ultimately just added as inputs to the +signing algorithm along with the pointer, but they serve significantly +different roles. The key data is a common secret added to every signature, +whereas the discriminator is a value that can be derived from +the context in which a specific pointer is signed. However, unlike a password +salt, it's important that discriminators be *independently* derived from the +circumstances of the signing; they should never simply be stored alongside +a pointer. Discriminators are then re-derived in authentication operations. + +The intrinsic interface in ```` allows an arbitrary discriminator +value to be provided, but can only be used when running normal code. The +discriminators used by language ABIs must be restricted to make it feasible for +the loader to sign pointers stored in global memory without needing excessive +amounts of metadata. Under these restrictions, a discriminator may consist of +either or both of the following: + +- The address at which the pointer is stored in memory. A pointer signed with + a discriminator which incorporates its storage address is said to have + **address diversity**. In general, using address diversity means that + a pointer cannot be reliably copied by an attacker to or from a different + memory location. However, an attacker may still be able to attack a larger + call sequence if they can alter the address through which the pointer is + accessed. Furthermore, some situations cannot use address diversity because + of language or other restrictions. + +- A constant integer, called a **constant discriminator**. A pointer signed + with a non-zero constant discriminator is said to have **constant + diversity**. If the discriminator is specific to a single declaration, it is + said to have **declaration diversity**; if the discriminator is specific to + a type of value, it is said to have **type diversity**. For example, C++ + v-tables on arm64e sign their component functions using a hash of their + method names and signatures, which provides declaration diversity; similarly, + C++ member function pointers sign their invocation functions using a hash of + the member pointer type, which provides type diversity. + +The implementation may need to restrict constant discriminators to be +significantly smaller than the full size of a discriminator. For example, on +arm64e, constant discriminators are only 16-bit values. This is believed to +not significantly weaken the mitigation, since collisions remain uncommon. + +The algorithm for blending a constant discriminator with a storage address is +implementation-defined. + +.. _Signing schemas: + +Signing Schemas +~~~~~~~~~~~~~~~ + +Correct use of pointer authentication requires the signing code and the +authenticating code to agree about the **signing schema** for the pointer: + +- the abstract signing key with which the pointer should be signed and +- an algorithm for computing the discriminator. + +As described in the section above on `Discriminators`_, in most situations, the +discriminator is produced by taking a constant discriminator and optionally +blending it with the storage address of the pointer. In these situations, the +signing schema breaks down even more simply: + +- the abstract signing key, +- a constant discriminator, and +- whether to use address diversity. + +It is important that the signing schema be independently derived at all signing +and authentication sites. Preferably, the schema should be hard-coded +everywhere it is needed, but at the very least, it must not be derived by +inspecting information stored along with the pointer. + +Language Features +----------------- + +There is currently one main pointer authentication language feature: + +- The language provides the ```` intrinsic interface for manually + signing and authenticating pointers in code. These can be used in + circumstances where very specific behavior is required. + + +Language Extensions +~~~~~~~~~~~~~~~~~~~ + +Feature Testing +^^^^^^^^^^^^^^^ + +Whether the current target uses pointer authentication can be tested for with +a number of different tests. + +- ``__has_feature(ptrauth_intrinsics)`` is true if ```` provides its + normal interface. This may be true even on targets where pointer + authentication is not enabled by default. + +```` +~~~~~~~~~~~~~~~ + +This header defines the following types and operations: + +``ptrauth_key`` +^^^^^^^^^^^^^^^ + +This ``enum`` is the type of abstract signing keys. In addition to defining +the set of implementation-specific signing keys (for example, Armv8.3 defines +``ptrauth_key_asia``), it also defines some portable aliases for those keys. +For example, ``ptrauth_key_function_pointer`` is the key generally used for +C function pointers, which will generally be suitable for other +function-signing schemas. + +In all the operation descriptions below, key values must be constant values +corresponding to one of the implementation-specific abstract signing keys from +this ``enum``. + +``ptrauth_extra_data_t`` +^^^^^^^^^^^^^^^^^^^^^^^^ + +This is a ``typedef`` of a standard integer type of the correct size to hold +a discriminator value. + +In the signing and authentication operation descriptions below, discriminator +values must have either pointer type or integer type. If the discriminator is +an integer, it will be coerced to ``ptrauth_extra_data_t``. + +``ptrauth_blend_discriminator`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c + + ptrauth_blend_discriminator(pointer, integer) + +Produce a discriminator value which blends information from the given pointer +and the given integer. + +Implementations may ignore some bits from each value, which is to say, the +blending algorithm may be chosen for speed and convenience over theoretical +strength as a hash-combining algorithm. For example, arm64e simply overwrites +the high 16 bits of the pointer with the low 16 bits of the integer, which can +be done in a single instruction with an immediate integer. + +``pointer`` must have pointer type, and ``integer`` must have integer type. The +result has type ``ptrauth_extra_data_t``. + +``ptrauth_strip`` +^^^^^^^^^^^^^^^^^ + +.. code-block:: c + + ptrauth_strip(signedPointer, key) + +Given that ``signedPointer`` matches the layout for signed pointers signed with +the given key, extract the raw pointer from it. This operation does not trap +and cannot fail, even if the pointer is not validly signed. + +``ptrauth_sign_unauthenticated`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c + + ptrauth_sign_unauthenticated(pointer, key, discriminator) + +Produce a signed pointer for the given raw pointer without applying any +authentication or extra treatment. This operation is not required to have the +same behavior on a null pointer that the language implementation would. + +This is a treacherous operation that can easily result in signing oracles. +Programs should use it seldom and carefully. + +``ptrauth_auth_and_resign`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c + + ptrauth_auth_and_resign(pointer, oldKey, oldDiscriminator, newKey, newDiscriminator) + +Authenticate that ``pointer`` is signed with ``oldKey`` and +``oldDiscriminator`` and then resign the raw-pointer result of that +authentication with ``newKey`` and ``newDiscriminator``. + +``pointer`` must have pointer type. The result will have the same type as +``pointer``. This operation is not required to have the same behavior on +a null pointer that the language implementation would. + +The code sequence produced for this operation must not be directly attackable. +However, if the discriminator values are not constant integers, their +computations may still be attackable. In the future, Clang should be enhanced +to guaranteed non-attackability if these expressions are safely-derived. + +``ptrauth_auth_data`` +^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c + + ptrauth_auth_data(pointer, key, discriminator) + +Authenticate that ``pointer`` is signed with ``key`` and ``discriminator`` and +remove the signature. + +``pointer`` must have object pointer type. The result will have the same type +as ``pointer``. This operation is not required to have the same behavior on +a null pointer that the language implementation would. + +In the future when Clang makes safe derivation guarantees, the result of +this operation should be considered safely-derived. + +``ptrauth_sign_generic_data`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c + + ptrauth_sign_generic_data(value1, value2) + +Computes a signature for the given pair of values, incorporating a secret +signing key. + +This operation can be used to verify that arbitrary data has not been tampered +with by computing a signature for the data, storing that signature, and then +repeating this process and verifying that it yields the same result. This can +be reasonably done in any number of ways; for example, a library could compute +an ordinary checksum of the data and just sign the result in order to get the +tamper-resistance advantages of the secret signing key (since otherwise an +attacker could reliably overwrite both the data and the checksum). + +``value1`` and ``value2`` must be either pointers or integers. If the integers +are larger than ``uintptr_t`` then data not representable in ``uintptr_t`` may +be discarded. + +The result will have type ``ptrauth_generic_signature_t``, which is an integer +type. Implementations are not required to make all bits of the result equally +significant; in particular, some implementations are known to not leave +meaningful data in the low bits. + + + +Alternative Implementations +--------------------------- + +Signature Storage +~~~~~~~~~~~~~~~~~ + +It is not critical for the security of pointer authentication that the +signature be stored "together" with the pointer, as it is in Armv8.3. An +implementation could just as well store the signature in a separate word, so +that the ``sizeof`` a signed pointer would be larger than the ``sizeof`` a raw +pointer. + +Storing the signature in the high bits, as Armv8.3 does, has several trade-offs: + +- Disadvantage: there are substantially fewer bits available for the signature, + weakening the mitigation by making it much easier for an attacker to simply + guess the correct signature. + +- Disadvantage: future growth of the address space will necessarily further + weaken the mitigation. + +- Advantage: memory layouts don't change, so it's possible for + pointer-authentication-enabled code (for example, in a system library) to + efficiently interoperate with existing code, as long as pointer + authentication can be disabled dynamically. + +- Advantage: the size of a signed pointer doesn't grow, which might + significantly increase memory requirements, code size, and register pressure. + +- Advantage: the size of a signed pointer is the same as a raw pointer, so + generic APIs which work in types like `void *` (such as `dlsym`) can still + return signed pointers. This means that clients of these APIs will not + require insecure code in order to correctly receive a function pointer. + +Hashing vs. Encrypting Pointers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Armv8.3 implements ``sign`` by computing a cryptographic hash and storing that +in the spare bits of the pointer. This means that there are relatively few +possible values for the valid signed pointer, since the bits corresponding to +the raw pointer are known. Together with an ``auth`` oracle, this can make it +computationally feasible to discover the correct signature with brute force. +(The implementation should of course endeavor not to introduce ``auth`` +oracles, but this can be difficult, and attackers can be devious.) + +If the implementation can instead *encrypt* the pointer during ``sign`` and +*decrypt* it during ``auth``, this brute-force attack becomes far less +feasible, even with an ``auth`` oracle. However, there are several problems +with this idea: + +- It's unclear whether this kind of encryption is even possible without + increasing the storage size of a signed pointer. If the storage size can be + increased, brute-force atacks can be equally well mitigated by simply storing + a larger signature. + +- It would likely be impossible to implement a ``strip`` operation, which might + make debuggers and other out-of-process tools far more difficult to write, as + well as generally making primitive debugging more challenging. + +- Implementations can benefit from being able to extract the raw pointer + immediately from a signed pointer. An Armv8.3 processor executing an + ``auth``-and-load instruction can perform the load and ``auth`` in parallel; + a processor which instead encrypted the pointer would be forced to perform + these operations serially. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 64a9fe0d8bcc48e89a5aac685be67c202db5b0e0..d5ce54e185600cab7885936d6442910aabbcc576 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -37,6 +37,9 @@ These changes are ones which we think may surprise users when upgrading to Clang |release| because of the opportunity they pose for disruption to existing code bases. +- Setting the deprecated CMake variable ``GCC_INSTALL_PREFIX`` (which sets the + default ``--gcc-toolchain=``) now leads to a fatal error. + C/C++ Language Potentially Breaking Changes ------------------------------------------- @@ -47,6 +50,18 @@ C++ Specific Potentially Breaking Changes ABI Changes in This Version --------------------------- +- Fixed Microsoft name mangling of implicitly defined variables used for thread + safe static initialization of static local variables. This change resolves + incompatibilities with code compiled by MSVC but might introduce + incompatibilities with code compiled by earlier versions of Clang when an + inline member function that contains a static local variable with a dynamic + initializer is declared with ``__declspec(dllimport)``. (#GH83616). + +- Fixed Microsoft name mangling of lifetime extended temporary objects. This + change corrects missing back reference registrations that could result in + incorrect back reference indexes and suprising demangled name results. Since + MSVC uses a different mangling for these objects, compatibility is not affected. + (#GH85423). AST Dumping Potentially Breaking Changes ---------------------------------------- @@ -171,6 +186,13 @@ Non-comprehensive list of changes in this release the previous builtins, this new builtin is constexpr and may be used in constant expressions. +- Lambda expressions are now accepted in C++03 mode as an extension. + +- Added ``__builtin_clzg`` and ``__builtin_ctzg`` as type-generic alternatives + to ``__builtin_clz{,s,l,ll}`` and ``__builtin_ctz{,s,l,ll}`` respectively, + with support for any unsigned integer type. Like the previous builtins, these + new builtins are constexpr and may be used in constant expressions. + New Compiler Flags ------------------ @@ -187,10 +209,33 @@ Modified Compiler Flags ``-Wreturn-type``, and moved some of the diagnostics previously controlled by ``-Wreturn-type`` under this new flag. Fixes #GH72116. +- Added ``-Wcast-function-type-mismatch`` under the ``-Wcast-function-type`` + warning group. Moved the diagnostic previously controlled by + ``-Wcast-function-type`` to the new warning group and added + ``-Wcast-function-type-mismatch`` to ``-Wextra``. #GH76872 + + .. code-block:: c + + int x(long); + typedef int (f2)(void*); + typedef int (f3)(); + + void func(void) { + // Diagnoses under -Wcast-function-type, -Wcast-function-type-mismatch, + // -Wcast-function-type-strict, -Wextra + f2 *b = (f2 *)x; + // Diagnoses under -Wcast-function-type, -Wcast-function-type-strict + f3 *c = (f3 *)x; + } + + Removed Compiler Flags ------------------------- - The ``-freroll-loops`` flag has been removed. It had no effect since Clang 13. +- ``-m[no-]unaligned-access`` is removed for RISC-V and LoongArch. + ``-m[no-]strict-align``, also supported by GCC, should be used instead. + (`#85350 `_.) Attribute Changes in Clang -------------------------- @@ -201,6 +246,28 @@ Attribute Changes in Clang and each must be a positive integer when provided. The parameter ``x`` is required, while ``y`` and ``z`` are optional with default value of 1. +- The ``swiftasynccc`` attribute is now considered to be a Clang extension + rather than a language standard feature. Please use + ``__has_extension(swiftasynccc)`` to check the availability of this attribute + for the target platform instead of ``__has_feature(swiftasynccc)``. Also, + added a new extension query ``__has_extension(swiftcc)`` corresponding to the + ``__attribute__((swiftcc))`` attribute. + +- The ``_Nullable`` and ``_Nonnull`` family of type attributes can now apply + to certain C++ class types, such as smart pointers: + ``void useObject(std::unique_ptr _Nonnull obj);``. + + This works for standard library types including ``unique_ptr``, ``shared_ptr``, + and ``function``. See + `the attribute reference documentation `_ + for the full list. + +- The ``_Nullable`` attribute can be applied to C++ class declarations: + ``template class _Nullable MySmartPointer {};``. + + This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to + apply to this class. + Improvements to Clang's diagnostics ----------------------------------- - Clang now applies syntax highlighting to the code snippets it @@ -237,6 +304,30 @@ Improvements to Clang's diagnostics - Clang now diagnoses lambda function expressions being implicitly cast to boolean values, under ``-Wpointer-bool-conversion``. Fixes #GH82512. +- Clang now provides improved warnings for the ``cleanup`` attribute to detect misuse scenarios, + such as attempting to call ``free`` on an unallocated object. Fixes + `#79443 `_. + +- Clang no longer warns when the ``bitand`` operator is used with boolean + operands, distinguishing it from potential typographical errors or unintended + bitwise operations. Fixes #GH77601. + +- Clang now correctly diagnoses no arguments to a variadic macro parameter as a C23/C++20 extension. + Fixes #GH84495. + +- Clang no longer emits a ``-Wexit-time destructors`` warning on static variables explicitly + annotated with the ``clang::always_destroy`` attribute. + Fixes #GH68686, #GH86486 + +- ``-Wmicrosoft``, ``-Wgnu``, or ``-pedantic`` is now required to diagnose C99 + flexible array members in a union or alone in a struct. Fixes GH#84565. + +- Clang now no longer diagnoses type definitions in ``offsetof`` in C23 mode. + Fixes #GH83658. + +- New ``-Wformat-signedness`` diagnostic that warn if the format string requires an + unsigned argument and the argument is signed and vice versa. + Improvements to Clang's time-trace ---------------------------------- @@ -267,6 +358,9 @@ Bug Fixes in This Version for variables created through copy initialization having side-effects in C++17 and later. Fixes (#GH64356) (#GH79518). +- Fix value of predefined macro ``__FUNCTION__`` in MSVC compatibility mode. + Fixes (#GH66114). + - Clang now emits errors for explicit specializations/instatiations of lambda call operator. Fixes (#GH83267). @@ -274,6 +368,19 @@ Bug Fixes in This Version - Clang now correctly generates overloads for bit-precise integer types for builtin operators in C++. Fixes #GH82998. +- When performing mixed arithmetic between ``_Complex`` floating-point types and integers, + Clang now correctly promotes the integer to its corresponding real floating-point + type only rather than to the complex type (e.g. ``_Complex float / int`` is now evaluated + as ``_Complex float / float`` rather than ``_Complex float / _Complex float``), as mandated + by the C standard. This significantly improves codegen of `*` and `/` especially. + Fixes (`#31205 `_). + +- Fixes an assertion failure on invalid code when trying to define member + functions in lambdas. + +- Fixed a regression in CTAD that a friend declaration that befriends itself may cause + incorrect constraint substitution. (#GH86769). + Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -362,9 +469,29 @@ Bug Fixes to C++ Support and (`#74494 `_) - Allow access to a public template alias declaration that refers to friend's private nested type. (#GH25708). +- Fixed a crash in constant evaluation when trying to access a + captured ``this`` pointer in a lambda with an explicit object parameter. + Fixes (#GH80997) +- Fix an issue where missing set friend declaration in template class instantiation. + Fixes (#GH84368). +- Fixed a crash while checking constraints of a trailing requires-expression of a lambda, that the + expression references to an entity declared outside of the lambda. (#GH64808) +- Clang's __builtin_bit_cast will now produce a constant value for records with empty bases. See: + (#GH82383) +- Fix a crash when instantiating a lambda that captures ``this`` outside of its context. Fixes (#GH85343). +- Fix an issue where a namespace alias could be defined using a qualified name (all name components + following the first `::` were ignored). +- Fix an out-of-bounds crash when checking the validity of template partial specializations. (part of #GH86757). +- Fix an issue caused by not handling invalid cases when substituting into the parameter mapping of a constraint. Fixes (#GH86757). +- Fixed a bug that prevented member function templates of class templates declared with a deduced return type + from being explicitly specialized for a given implicit instantiation of the class template. + +- Fix crash when inheriting from a cv-qualified type. Fixes: + (`#35603 `_) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ +- Clang now properly preserves ``FoundDecls`` within a ``ConceptReference``. (#GH82628) Miscellaneous Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^ @@ -408,6 +535,8 @@ Arm and AArch64 Support like ``target_version`` or ``target_clones``. - Support has been added for the following processors (-mcpu identifiers in parenthesis): * Arm Cortex-A78AE (cortex-a78ae). + * Arm Cortex-A520AE (cortex-a520ae). + * Arm Cortex-A720AE (cortex-a720ae). Android Support ^^^^^^^^^^^^^^^ @@ -415,6 +544,26 @@ Android Support Windows Support ^^^^^^^^^^^^^^^ +- Clang-cl now supports function targets with intrinsic headers. This allows + for runtime feature detection of intrinsics. Previously under clang-cl + ``immintrin.h`` and similar intrinsic headers would only include the intrinsics + if building with that feature enabled at compile time, e.g. ``avxintrin.h`` + would only be included if AVX was enabled at compile time. This was done to work + around include times from MSVC STL including ``intrin.h`` under clang-cl. + Clang-cl now provides ``intrin0.h`` for MSVC STL and therefore all intrinsic + features without requiring enablement at compile time. + Fixes: (`#53520 `_) + +- Improved compile times with MSVC STL. MSVC provides ``intrin0.h`` which is a + header that only includes intrinsics that are used by MSVC STL to avoid the + use of ``intrin.h``. MSVC STL when compiled under clang uses ``intrin.h`` + instead. Clang-cl now provides ``intrin0.h`` for the same compiler throughput + purposes as MSVC. Clang-cl also provides ``yvals_core.h`` to redefine + ``_STL_INTRIN_HEADER`` to expand to ``intrin0.h`` instead of ``intrin.h``. + This also means that if all intrinsic features are enabled at compile time + including STL headers will no longer slow down compile times since ``intrin.h`` + is not included from MSVC STL. + LoongArch Support ^^^^^^^^^^^^^^^^^ @@ -422,6 +571,7 @@ RISC-V Support ^^^^^^^^^^^^^^ - ``__attribute__((rvv_vector_bits(N)))`` is now supported for RVV vbool*_t types. +- Profile names in ``-march`` option are now supported. CUDA/HIP Language Changes ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -475,6 +625,11 @@ libclang Static Analyzer --------------- +- Fixed crashing on loops if the loop variable was declared in switch blocks + but not under any case blocks if ``unroll-loops=true`` analyzer config is + set. (#GH68819) +- Support C++23 static operator calls. (#GH84972) + New features ^^^^^^^^^^^^ @@ -505,10 +660,16 @@ Sanitizers manually disable potentially noisy signed integer overflow checks with ``-fno-sanitize=signed-integer-overflow`` +- ``-fsanitize=cfi -fsanitize-cfi-cross-dso`` (cross-DSO CFI instrumentation) + now generates the ``__cfi_check`` function with proper target-specific + attributes, for example allowing unwind table generation. + Python Binding Changes ---------------------- - Exposed `CXRewriter` API as `class Rewriter`. +- Add some missing kinds from Index.h (CursorKind: 149-156, 272-320, 420-437. + TemplateArgumentKind: 5-9. TypeKind: 161-175 and 178). OpenMP Support -------------- diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 7391e4cf3a9aeb47bc949a2121db80896a903b89..c464bc3a69adc51c1f59db5245f1fc077aed4a11 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -1847,19 +1847,50 @@ floating point semantic models: precise (the default), strict, and fast. * ``16`` - Forces ``_Float16`` operations to be emitted without using excess precision arithmetic. +.. option:: -fcomplex-arithmetic=: + + This option specifies the implementation for complex multiplication and division. + + Valid values are: ``basic``, ``improved``, ``full`` and ``promoted``. + + * ``basic`` Implementation of complex division and multiplication using + algebraic formulas at source precision. No special handling to avoid + overflow. NaN and infinite values are not handled. + * ``improved`` Implementation of complex division using the Smith algorithm + at source precision. Smith's algorithm for complex division. + See SMITH, R. L. Algorithm 116: Complex division. Commun. ACM 5, 8 (1962). + This value offers improved handling for overflow in intermediate + calculations, but overflow may occur. NaN and infinite values are not + handled in some cases. + * ``full`` Implementation of complex division and multiplication using a + 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 + 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 + 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. + .. option:: -fcx-limited-range: - This option enables the naive mathematical formulas for complex division and - multiplication with no NaN checking of results. The default is - ``-fno-cx-limited-range``, but this option is enabled by the ``-ffast-math`` + This option is aliased to ``-fcomplex-arithmetic=basic``. It enables the + naive mathematical formulas for complex division and multiplication with no + NaN checking of results. The default is ``-fno-cx-limited-range`` aliased to + ``-fcomplex-arithmetic=full``. This option is enabled by the ``-ffast-math`` option. .. option:: -fcx-fortran-rules: - This option enables the naive mathematical formulas for complex - multiplication and enables application of Smith's algorithm for complex - division. See SMITH, R. L. Algorithm 116: Complex division. Commun. - ACM 5, 8 (1962). The default is ``-fno-cx-fortran-rules``. + This option is aliased to ``-fcomplex-arithmetic=improved``. It enables the + naive mathematical formulas for complex multiplication and enables application + of Smith's algorithm for complex division. See SMITH, R. L. Algorithm 116: + Complex division. Commun. ACM 5, 8 (1962). + The default is ``-fno-cx-fortran-rules`` aliased to + ``-fcomplex-arithmetic=full``. .. _floating-point-environment: @@ -2410,20 +2441,39 @@ usual build cycle when using sample profilers for optimization: 1. Build the code with source line table information. You can use all the usual build flags that you always build your application with. The only - requirement is that you add ``-gline-tables-only`` or ``-g`` to the - command line. This is important for the profiler to be able to map - instructions back to source line locations. + requirement is that DWARF debug info including source line information is + generated. This DWARF information is important for the profiler to be able + to map instructions back to source line locations. + + On Linux, ``-g`` or just ``-gline-tables-only`` is sufficient: .. code-block:: console $ clang++ -O2 -gline-tables-only code.cc -o code + While MSVC-style targets default to CodeView debug information, DWARF debug + information is required to generate source-level LLVM profiles. Use + ``-gdwarf`` to include DWARF debug information: + + .. code-block:: console + + $ clang-cl -O2 -gdwarf -gline-tables-only coff-profile.cpp -fuse-ld=lld -link -debug:dwarf + 2. Run the executable under a sampling profiler. The specific profiler you use does not really matter, as long as its output can be converted - into the format that the LLVM optimizer understands. Currently, there - exists a conversion tool for the Linux Perf profiler - (https://perf.wiki.kernel.org/), so these examples assume that you - are using Linux Perf to profile your code. + into the format that the LLVM optimizer understands. + + Two such profilers are the the Linux Perf profiler + (https://perf.wiki.kernel.org/) and Intel's Sampling Enabling Product (SEP), + available as part of `Intel VTune + `_. + While Perf is Linux-specific, SEP can be used on Linux, Windows, and FreeBSD. + + The LLVM tool ``llvm-profgen`` can convert output of either Perf or SEP. An + external project, `AutoFDO `_, also + provides a ``create_llvm_prof`` tool which supports Linux Perf output. + + When using Perf: .. code-block:: console @@ -2434,11 +2484,19 @@ usual build cycle when using sample profilers for optimization: it provides better call information, which improves the accuracy of the profile data. -3. Convert the collected profile data to LLVM's sample profile format. - This is currently supported via the AutoFDO converter ``create_llvm_prof``. - It is available at https://github.com/google/autofdo. Once built and - installed, you can convert the ``perf.data`` file to LLVM using - the command: + When using SEP: + + .. code-block:: console + + $ sep -start -out code.tb7 -ec BR_INST_RETIRED.NEAR_TAKEN:precise=yes:pdir -lbr no_filter:usr -perf-script brstack -app ./code + + This produces a ``code.perf.data.script`` output which can be used with + ``llvm-profgen``'s ``--perfscript`` input option. + +3. Convert the collected profile data to LLVM's sample profile format. This is + currently supported via the `AutoFDO `_ + converter ``create_llvm_prof``. Once built and installed, you can convert + the ``perf.data`` file to LLVM using the command: .. code-block:: console @@ -2454,7 +2512,14 @@ usual build cycle when using sample profilers for optimization: .. code-block:: console - $ llvm-profgen --binary=./code --output=code.prof--perfdata=perf.data + $ llvm-profgen --binary=./code --output=code.prof --perfdata=perf.data + + When using SEP the output is in the textual format corresponding to + ``llvm-profgen --perfscript``. For example: + + .. code-block:: console + + $ llvm-profgen --binary=./code --output=code.prof --perfscript=code.perf.data.script 4. Build the code again using the collected profile. This step feeds @@ -4227,7 +4292,68 @@ Clang expects the GCC executable "gcc.exe" compiled for AIX ^^^ +TOC Data Transformation +""""""""""""""""""""""" +TOC data transformation is off by default (``-mno-tocdata``). +When ``-mtocdata`` is specified, the TOC data transformation will be applied to +all suitable variables with static storage duration, including static data +members of classes and block-scope static variables (if not marked as exceptions, +see further below). + +Suitable variables must: + +- have complete types +- be independently generated (i.e., not placed in a pool) +- be at most as large as a pointer +- not be aligned more strictly than a pointer +- not be structs containing flexible array members +- not have internal linkage +- not have aliases +- not have section attributes +- not be thread local storage + +The TOC data transformation results in the variable, not its address, +being placed in the TOC. This eliminates the need to load the address of the +variable from the TOC. + +Note: +If the TOC data transformation is applied to a variable whose definition +is imported, the linker will generate fixup code for reading or writing to the +variable. + +When multiple toc-data options are used, the last option used has the affect. +For example: -mno-tocdata=g5,g1 -mtocdata=g1,g2 -mno-tocdata=g2 -mtocdata=g3,g4 +results in -mtocdata=g1,g3,g4 + +Names of variables not having external linkage will be ignored. + +**Options:** + +.. option:: -mno-tocdata + + This is the default behaviour. Only variables explicitly specified with + ``-mtocdata=`` will have the TOC data transformation applied. + +.. option:: -mtocdata + + Apply the TOC data transformation to all suitable variables with static + storage duration (including static data members of classes and block-scope + static variables) that are not explicitly specified with ``-mno-tocdata=``. + +.. option:: -mno-tocdata= + + Can be used in conjunction with ``-mtocdata`` to mark the comma-separated + list of external linkage variables, specified using their mangled names, as + exceptions to ``-mtocdata``. + +.. option:: -mtocdata= + + Apply the TOC data transformation to the comma-separated list of external + linkage variables, specified using their mangled names, if they are suitable. + Emit diagnostics for all unsuitable variables specified. +Default Visibility Export Mapping +""""""""""""""""""""""""""""""""" The ``-mdefault-visibility-export-mapping=`` option can be used to control mapping of default visibility to an explicit shared object export (i.e. XCOFF exported visibility). Three values are provided for the option: diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst index fe2115149142723724feea43e0af6d285d9dd604..f188f18ba5557e48efe4b5586e93cf90e1b1fafe 100644 --- a/clang/docs/analyzer/checkers.rst +++ b/clang/docs/analyzer/checkers.rst @@ -340,6 +340,51 @@ cplusplus C++ Checkers. +.. _cplusplus-ArrayDelete: + +cplusplus.ArrayDelete (C++) +""""""""""""""""""""""""""" + +Reports destructions of arrays of polymorphic objects that are destructed as +their base class. If the dynamic type of the array is different from its static +type, calling `delete[]` is undefined. + +This checker corresponds to the SEI CERT rule `EXP51-CPP: Do not delete an array through a pointer of the incorrect type `_. + +.. code-block:: cpp + + class Base { + public: + virtual ~Base() {} + }; + class Derived : public Base {}; + + Base *create() { + Base *x = new Derived[10]; // note: Casting from 'Derived' to 'Base' here + return x; + } + + void foo() { + Base *x = create(); + delete[] x; // warn: Deleting an array of 'Derived' objects as their base class 'Base' is undefined + } + +**Limitations** + +The checker does not emit note tags when casting to and from reference types, +even though the pointer values are tracked across references. + +.. code-block:: cpp + + void foo() { + Derived *d = new Derived[10]; + Derived &dref = *d; + + Base &bref = static_cast(dref); // no note + Base *b = &bref; + delete[] b; // warn: Deleting an array of 'Derived' objects as their base class 'Base' is undefined + } + .. _cplusplus-InnerPointer: cplusplus.InnerPointer (C++) @@ -804,10 +849,89 @@ Check for performance anti-patterns when using Grand Central Dispatch. .. _optin-performance-Padding: -optin.performance.Padding -""""""""""""""""""""""""" +optin.performance.Padding (C, C++, ObjC) +"""""""""""""""""""""""""""""""""""""""" Check for excessively padded structs. +This checker detects structs with excessive padding, which can lead to wasted +memory thus decreased performance by reducing the effectiveness of the +processor cache. Padding bytes are added by compilers to align data accesses +as some processors require data to be aligned to certain boundaries. On others, +unaligned data access are possible, but impose significantly larger latencies. + +To avoid padding bytes, the fields of a struct should be ordered by decreasing +by alignment. Usually, its easier to think of the ``sizeof`` of the fields, and +ordering the fields by ``sizeof`` would usually also lead to the same optimal +layout. + +In rare cases, one can use the ``#pragma pack(1)`` directive to enforce a packed +layout too, but it can significantly increase the access times, so reordering the +fields is usually a better solution. + + +.. code-block:: cpp + + // warn: Excessive padding in 'struct NonOptimal' (35 padding bytes, where 3 is optimal) + struct NonOptimal { + char c1; + // 7 bytes of padding + std::int64_t big1; // 8 bytes + char c2; + // 7 bytes of padding + std::int64_t big2; // 8 bytes + char c3; + // 7 bytes of padding + std::int64_t big3; // 8 bytes + char c4; + // 7 bytes of padding + std::int64_t big4; // 8 bytes + char c5; + // 7 bytes of padding + }; + static_assert(sizeof(NonOptimal) == 4*8+5+5*7); + + // no-warning: The fields are nicely aligned to have the minimal amount of padding bytes. + struct Optimal { + std::int64_t big1; // 8 bytes + std::int64_t big2; // 8 bytes + std::int64_t big3; // 8 bytes + std::int64_t big4; // 8 bytes + char c1; + char c2; + char c3; + char c4; + char c5; + // 3 bytes of padding + }; + static_assert(sizeof(Optimal) == 4*8+5+3); + + // no-warning: Bit packing representation is also accepted by this checker, but + // it can significantly increase access times, so prefer reordering the fields. + #pragma pack(1) + struct BitPacked { + char c1; + std::int64_t big1; // 8 bytes + char c2; + std::int64_t big2; // 8 bytes + char c3; + std::int64_t big3; // 8 bytes + char c4; + std::int64_t big4; // 8 bytes + char c5; + }; + static_assert(sizeof(BitPacked) == 4*8+5); + +The ``AllowedPad`` option can be used to specify a threshold for the number +padding bytes raising the warning. If the number of padding bytes of the struct +and the optimal number of padding bytes differ by more than the threshold value, +a warning will be raised. + +By default, the ``AllowedPad`` threshold is 24 bytes. + +To override this threshold to e.g. 4 bytes, use the +``-analyzer-config optin.performance.Padding:AllowedPad=4`` option. + + .. _optin-portability-UnixAPI: optin.portability.UnixAPI @@ -2139,30 +2263,6 @@ Either the comparison is useless or there is division by zero. alpha.cplusplus ^^^^^^^^^^^^^^^ -.. _alpha-cplusplus-ArrayDelete: - -alpha.cplusplus.ArrayDelete (C++) -""""""""""""""""""""""""""""""""" -Reports destructions of arrays of polymorphic objects that are destructed as their base class. -This checker corresponds to the CERT rule `EXP51-CPP: Do not delete an array through a pointer of the incorrect type `_. - -.. code-block:: cpp - - class Base { - virtual ~Base() {} - }; - class Derived : public Base {} - - Base *create() { - Base *x = new Derived[10]; // note: Casting from 'Derived' to 'Base' here - return x; - } - - void foo() { - Base *x = create(); - delete[] x; // warn: Deleting an array of 'Derived' objects as their base class 'Base' is undefined - } - .. _alpha-cplusplus-DeleteWithNonVirtualDtor: alpha.cplusplus.DeleteWithNonVirtualDtor (C++) @@ -3020,44 +3120,82 @@ Check for misuses of stream APIs. Check for misuses of stream APIs: ``fopen, fcl alpha.unix.Stream (C) """"""""""""""""""""" -Check stream handling functions: ``fopen, tmpfile, fclose, fread, fwrite, fseek, ftell, rewind, fgetpos,`` -``fsetpos, clearerr, feof, ferror, fileno``. +Check C stream handling functions: +``fopen, fdopen, freopen, tmpfile, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, fprintf, fscanf, ungetc, getdelim, getline, fseek, fseeko, ftell, ftello, fflush, rewind, fgetpos, fsetpos, clearerr, feof, ferror, fileno``. + +The checker maintains information about the C stream objects (``FILE *``) and +can detect error conditions related to use of streams. The following conditions +are detected: + +* The ``FILE *`` pointer passed to the function is NULL (the single exception is + ``fflush`` where NULL is allowed). +* Use of stream after close. +* Opened stream is not closed. +* Read from a stream after end-of-file. (This is not a fatal error but reported + by the checker. Stream remains in EOF state and the read operation fails.) +* Use of stream when the file position is indeterminate after a previous failed + operation. Some functions (like ``ferror``, ``clearerr``, ``fseek``) are + allowed in this state. +* Invalid 3rd ("``whence``") argument to ``fseek``. + +The checker does not track the correspondence between integer file descriptors +and ``FILE *`` pointers. Operations on standard streams like ``stdin`` are not +treated specially and are therefore often not recognized (because these streams +are usually not opened explicitly by the program, and are global variables). .. code-block:: c - void test() { + void test1() { FILE *p = fopen("foo", "r"); } // warn: opened file is never closed - void test() { + void test2() { FILE *p = fopen("foo", "r"); fseek(p, 1, SEEK_SET); // warn: stream pointer might be NULL fclose(p); } - void test() { + void test3() { FILE *p = fopen("foo", "r"); + if (p) { + fseek(p, 1, 3); // warn: third arg should be SEEK_SET, SEEK_END, or SEEK_CUR + fclose(p); + } + } - if (p) - fseek(p, 1, 3); - // warn: third arg should be SEEK_SET, SEEK_END, or SEEK_CUR + void test4() { + FILE *p = fopen("foo", "r"); + if (!p) + return; fclose(p); + fclose(p); // warn: stream already closed } - void test() { + void test5() { FILE *p = fopen("foo", "r"); + if (!p) + return; + + fgetc(p); + if (!ferror(p)) + fgetc(p); // warn: possible read after end-of-file + fclose(p); - fclose(p); // warn: already closed } - void test() { - FILE *p = tmpfile(); - ftell(p); // warn: stream pointer might be NULL + void test6() { + FILE *p = fopen("foo", "r"); + if (!p) + return; + + fgetc(p); + if (!feof(p)) + fgetc(p); // warn: file position may be indeterminate after I/O error + fclose(p); } - .. _alpha-unix-cstring-BufferOverlap: alpha.unix.cstring.BufferOverlap (C) diff --git a/clang/docs/tools/clang-formatted-files.txt b/clang/docs/tools/clang-formatted-files.txt index 40ab76fa26a9e347b7c08d490b13601a6416b820..70687c23b15e61e3417ff09cf32b78781b7e9c18 100644 --- a/clang/docs/tools/clang-formatted-files.txt +++ b/clang/docs/tools/clang-formatted-files.txt @@ -122,6 +122,7 @@ clang/include/clang/Analysis/MacroExpansionContext.h clang/include/clang/Analysis/Analyses/CalledOnceCheck.h clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h clang/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h +clang/include/clang/Analysis/FlowSensitive/AdornedCFG.h clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h @@ -306,7 +307,7 @@ clang/include/clang-c/Index.h clang/lib/Analysis/CalledOnceCheck.cpp clang/lib/Analysis/CloneDetection.cpp clang/lib/Analysis/CodeInjector.cpp -clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp +clang/lib/Analysis/FlowSensitive/AdornedCFG.cpp clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp clang/lib/Analysis/FlowSensitive/DebugSupport.cpp diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h index 3f3620609b6ddc08c88752c0aa744c9f083d01ff..7a8bd985a91fc00b2c3a6c488aca5030fc211c8d 100644 --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -1675,7 +1675,7 @@ enum CXCursorKind { CXCursor_ConceptSpecializationExpr = 153, /** - * Expression that references a C++20 concept. + * Expression that references a C++20 requires expression. */ CXCursor_RequiresExpr = 154, @@ -2991,6 +2991,7 @@ enum CXCallingConv { CXCallingConv_AArch64SVEPCS = 18, CXCallingConv_M68kRTD = 19, CXCallingConv_PreserveNone = 20, + CXCallingConv_RISCVVectorCall = 21, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index ff6b64c7f72d57f59172eb0d7155ffa8e5da76c4..08f71051e6cbf32c20830d2503f8c511099f8908 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -250,6 +250,8 @@ class ASTContext : public RefCountedBase { DependentBitIntTypes; llvm::FoldingSet BTFTagAttributedTypes; + mutable llvm::FoldingSet CountAttributedTypes; + mutable llvm::FoldingSet QualifiedTemplateNames; mutable llvm::FoldingSet DependentTemplateNames; mutable llvm::FoldingSet @@ -258,6 +260,9 @@ class ASTContext : public RefCountedBase { ASTContext&> SubstTemplateTemplateParmPacks; + mutable llvm::ContextualFoldingSet + ArrayParameterTypes; + /// The set of nested name specifiers. /// /// This set is managed by the NestedNameSpecifier class. @@ -1341,6 +1346,11 @@ public: return CanQualType::CreateUnsafe(getPointerType((QualType) T)); } + QualType + getCountAttributedType(QualType T, Expr *CountExpr, bool CountInBytes, + bool OrNull, + ArrayRef DependentDecls) const; + /// Return the uniqued reference to a type adjusted from the original /// type to a new type. QualType getAdjustedType(QualType Orig, QualType New) const; @@ -1360,6 +1370,10 @@ public: /// type to the decayed type. QualType getDecayedType(QualType Orig, QualType Decayed) const; + /// Return the uniqued reference to a specified array parameter type from the + /// original array type. + QualType getArrayParameterType(QualType Ty) const; + /// Return the uniqued reference to the atomic type for the specified /// type. QualType getAtomicType(QualType T) const; diff --git a/clang/include/clang/AST/Availability.h b/clang/include/clang/AST/Availability.h index ae3acbeffe7f189f9ff3f907eb9250b870c6d273..26ae622e5b4496fb1afa3b4e9e0b1cbffd1093be 100644 --- a/clang/include/clang/AST/Availability.h +++ b/clang/include/clang/AST/Availability.h @@ -67,6 +67,7 @@ struct AvailabilityInfo { VersionTuple Introduced; VersionTuple Deprecated; VersionTuple Obsoleted; + bool Unavailable = false; bool UnconditionallyDeprecated = false; bool UnconditionallyUnavailable = false; @@ -75,6 +76,15 @@ struct AvailabilityInfo { /// Determine if this AvailabilityInfo represents the default availability. bool isDefault() const { return *this == AvailabilityInfo(); } + /// Check if the symbol has been obsoleted. + bool isObsoleted() const { return !Obsoleted.empty(); } + + /// Check if the symbol is unavailable unconditionally or + /// on the active platform and os version. + bool isUnavailable() const { + return Unavailable || isUnconditionallyUnavailable(); + } + /// Check if the symbol is unconditionally deprecated. /// /// i.e. \code __attribute__((deprecated)) \endcode @@ -88,9 +98,10 @@ struct AvailabilityInfo { } AvailabilityInfo(StringRef Domain, VersionTuple I, VersionTuple D, - VersionTuple O, bool UD, bool UU) + VersionTuple O, bool U, bool UD, bool UU) : Domain(Domain), Introduced(I), Deprecated(D), Obsoleted(O), - UnconditionallyDeprecated(UD), UnconditionallyUnavailable(UU) {} + Unavailable(U), UnconditionallyDeprecated(UD), + UnconditionallyUnavailable(UU) {} friend bool operator==(const AvailabilityInfo &Lhs, const AvailabilityInfo &Rhs); @@ -102,10 +113,10 @@ public: inline bool operator==(const AvailabilityInfo &Lhs, const AvailabilityInfo &Rhs) { return std::tie(Lhs.Introduced, Lhs.Deprecated, Lhs.Obsoleted, - Lhs.UnconditionallyDeprecated, + Lhs.Unavailable, Lhs.UnconditionallyDeprecated, Lhs.UnconditionallyUnavailable) == std::tie(Rhs.Introduced, Rhs.Deprecated, Rhs.Obsoleted, - Rhs.UnconditionallyDeprecated, + Rhs.Unavailable, Rhs.UnconditionallyDeprecated, Rhs.UnconditionallyUnavailable); } diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 47ed6d0d1db0df804f55cdfca4c5c0ddd4868bb9..858450926455c602030671323257a4470bc096f7 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -669,9 +669,8 @@ public: /// Whether this declaration comes from another module unit. bool isInAnotherModuleUnit() const; - /// FIXME: Implement discarding declarations actually in global module - /// fragment. See [module.global.frag]p3,4 for details. - bool isDiscardedInGlobalModuleFragment() const { return false; } + /// Whether this declaration comes from explicit global module. + bool isFromExplicitGlobalModule() const; /// Check if we should skip checking ODRHash for declaration \param D. /// diff --git a/clang/include/clang/AST/DeclContextInternals.h b/clang/include/clang/AST/DeclContextInternals.h index 903cdb7bfcc822a2a066fe0e96d96f44f1e6e217..c4734ab578953835ee9719264ae2e9279d7d979f 100644 --- a/clang/include/clang/AST/DeclContextInternals.h +++ b/clang/include/clang/AST/DeclContextInternals.h @@ -205,7 +205,7 @@ public: Data.setPointer(Head); } - /// Return an array of all the decls that this list represents. + /// Return the list of all the decls. DeclContext::lookup_result getLookupResult() const { return DeclContext::lookup_result(Data.getPointer()); } diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 446bec4081e86908b337ae17bdaf0c9ac6340815..2bfefeabc348bee1cc399a43bfd8aa057a18ec3d 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -2045,7 +2045,8 @@ public: } static std::string ComputeName(PredefinedIdentKind IK, - const Decl *CurrentDecl); + const Decl *CurrentDecl, + bool ForceElaboratedPrinting = false); SourceLocation getBeginLoc() const { return getLocation(); } SourceLocation getEndLoc() const { return getLocation(); } @@ -3162,23 +3163,12 @@ public: } }; -/// Extra data stored in some MemberExpr objects. -struct MemberExprNameQualifier { - /// The nested-name-specifier that qualifies the name, including - /// source-location information. - NestedNameSpecifierLoc QualifierLoc; - - /// The DeclAccessPair through which the MemberDecl was found due to - /// name qualifiers. - DeclAccessPair FoundDecl; -}; - /// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F. /// class MemberExpr final : public Expr, - private llvm::TrailingObjects { friend class ASTReader; friend class ASTStmtReader; @@ -3200,26 +3190,30 @@ class MemberExpr final /// MemberLoc - This is the location of the member name. SourceLocation MemberLoc; - size_t numTrailingObjects(OverloadToken) const { - return hasQualifierOrFoundDecl(); + size_t numTrailingObjects(OverloadToken) const { + return hasQualifier(); + } + + size_t numTrailingObjects(OverloadToken) const { + return hasFoundDecl(); } size_t numTrailingObjects(OverloadToken) const { return hasTemplateKWAndArgsInfo(); } - bool hasQualifierOrFoundDecl() const { - return MemberExprBits.HasQualifierOrFoundDecl; - } + bool hasFoundDecl() const { return MemberExprBits.HasFoundDecl; } bool hasTemplateKWAndArgsInfo() const { return MemberExprBits.HasTemplateKWAndArgsInfo; } MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, - ValueDecl *MemberDecl, const DeclarationNameInfo &NameInfo, - QualType T, ExprValueKind VK, ExprObjectKind OK, - NonOdrUseReason NOUR); + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, + ValueDecl *MemberDecl, DeclAccessPair FoundDecl, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs, QualType T, + ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR); MemberExpr(EmptyShell Empty) : Expr(MemberExprClass, Empty), Base(), MemberDecl() {} @@ -3263,24 +3257,24 @@ public: /// Retrieves the declaration found by lookup. DeclAccessPair getFoundDecl() const { - if (!hasQualifierOrFoundDecl()) + if (!hasFoundDecl()) return DeclAccessPair::make(getMemberDecl(), getMemberDecl()->getAccess()); - return getTrailingObjects()->FoundDecl; + return *getTrailingObjects(); } /// Determines whether this member expression actually had /// a C++ nested-name-specifier prior to the name of the member, e.g., /// x->Base::foo. - bool hasQualifier() const { return getQualifier() != nullptr; } + bool hasQualifier() const { return MemberExprBits.HasQualifier; } /// If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name, with source-location /// information. NestedNameSpecifierLoc getQualifierLoc() const { - if (!hasQualifierOrFoundDecl()) + if (!hasQualifier()) return NestedNameSpecifierLoc(); - return getTrailingObjects()->QualifierLoc; + return *getTrailingObjects(); } /// If the member name was qualified, retrieves the @@ -3561,6 +3555,18 @@ public: path_const_iterator path_begin() const { return path_buffer(); } path_const_iterator path_end() const { return path_buffer() + path_size(); } + /// Path through the class hierarchy taken by casts between base and derived + /// classes (see implementation of `CastConsistency()` for a full list of + /// cast kinds that have a path). + /// + /// For each derived-to-base edge in the path, the path contains a + /// `CXXBaseSpecifier` for the base class of that edge; the entries are + /// ordered from derived class to base class. + /// + /// For example, given classes `Base`, `Intermediate : public Base` and + /// `Derived : public Intermediate`, the path for a cast from `Derived *` to + /// `Base *` contains two entries: One for `Intermediate`, and one for `Base`, + /// in that order. llvm::iterator_range path() { return llvm::make_range(path_begin(), path_end()); } diff --git a/clang/include/clang/AST/FormatString.h b/clang/include/clang/AST/FormatString.h index e2232fb4a47153f77882427d83046108525c691b..a074dd23e2ad4c7600b4206e3f36ec10f85b3d73 100644 --- a/clang/include/clang/AST/FormatString.h +++ b/clang/include/clang/AST/FormatString.h @@ -284,6 +284,8 @@ public: /// The conversion specifier and the argument type are disallowed by the C /// standard, but are in practice harmless. For instance, "%p" and int*. NoMatchPedantic, + /// The conversion specifier and the argument type have different sign. + NoMatchSignedness, /// The conversion specifier and the argument type are compatible, but still /// seems likely to be an error. For instance, "%hd" and _Bool. NoMatchTypeConfusion, diff --git a/clang/include/clang/AST/OperationKinds.def b/clang/include/clang/AST/OperationKinds.def index ef05072800f11a1bcd6a7ee48824150ea92104b6..8788b8ff0ef0a4538ff8bed81b05f1993d3a6c24 100644 --- a/clang/include/clang/AST/OperationKinds.def +++ b/clang/include/clang/AST/OperationKinds.def @@ -364,6 +364,9 @@ CAST_OPERATION(IntToOCLSampler) // Truncate a vector type by dropping elements from the end (HLSL only). CAST_OPERATION(HLSLVectorTruncation) +// Non-decaying array RValue cast (HLSL only). +CAST_OPERATION(HLSLArrayRValue) + //===- Binary Operations -------------------------------------------------===// // Operators listed in order of precedence. // Note that additions to this should also update the StmtVisitor class, diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td index 0270c086d06b6ad8e316aecda7c414cfef77f78a..6df1d93a7ba2eb9fffa827cb4e1639d115add152 100644 --- a/clang/include/clang/AST/PropertiesBase.td +++ b/clang/include/clang/AST/PropertiesBase.td @@ -143,6 +143,7 @@ def UInt32 : CountPropertyType<"uint32_t">; def UInt64 : CountPropertyType<"uint64_t">; def UnaryTypeTransformKind : EnumPropertyType<"UnaryTransformType::UTTKind">; def VectorKind : EnumPropertyType<"VectorKind">; +def TypeCoupledDeclRefInfo : PropertyType; def ExceptionSpecInfo : PropertyType<"FunctionProtoType::ExceptionSpecInfo"> { let BufferElementTypes = [ QualType ]; diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 5080551ada4fc67b09791a5d2499e5430614d5ef..8630317795a9ad94313f59bba25eac6db36422b6 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -993,6 +993,12 @@ DEF_TRAVERSE_TYPE(ConstantArrayType, { TRY_TO(TraverseStmt(const_cast(T->getSizeExpr()))); }) +DEF_TRAVERSE_TYPE(ArrayParameterType, { + TRY_TO(TraverseType(T->getElementType())); + if (T->getSizeExpr()) + TRY_TO(TraverseStmt(const_cast(T->getSizeExpr()))); +}) + DEF_TRAVERSE_TYPE(IncompleteArrayType, { TRY_TO(TraverseType(T->getElementType())); }) @@ -1110,6 +1116,12 @@ DEF_TRAVERSE_TYPE(InjectedClassNameType, {}) DEF_TRAVERSE_TYPE(AttributedType, { TRY_TO(TraverseType(T->getModifiedType())); }) +DEF_TRAVERSE_TYPE(CountAttributedType, { + if (T->getCountExpr()) + TRY_TO(TraverseStmt(T->getCountExpr())); + TRY_TO(TraverseType(T->desugar())); +}) + DEF_TRAVERSE_TYPE(BTFTagAttributedType, { TRY_TO(TraverseType(T->getWrappedType())); }) @@ -1254,6 +1266,11 @@ DEF_TRAVERSE_TYPELOC(ConstantArrayType, { TRY_TO(TraverseArrayTypeLocHelper(TL)); }) +DEF_TRAVERSE_TYPELOC(ArrayParameterType, { + TRY_TO(TraverseTypeLoc(TL.getElementLoc())); + TRY_TO(TraverseArrayTypeLocHelper(TL)); +}) + DEF_TRAVERSE_TYPELOC(IncompleteArrayType, { TRY_TO(TraverseTypeLoc(TL.getElementLoc())); TRY_TO(TraverseArrayTypeLocHelper(TL)); @@ -1401,6 +1418,9 @@ DEF_TRAVERSE_TYPELOC(MacroQualifiedType, DEF_TRAVERSE_TYPELOC(AttributedType, { TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); }) +DEF_TRAVERSE_TYPELOC(CountAttributedType, + { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); }) + DEF_TRAVERSE_TYPELOC(BTFTagAttributedType, { TRY_TO(TraverseTypeLoc(TL.getWrappedLoc())); }) diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 55eca4007d17ea25c9244cf94fe34b849461149b..8892518d58e853230751cf3cf67d1eaff8258e5d 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -583,11 +583,13 @@ protected: unsigned IsArrow : 1; /// True if this member expression used a nested-name-specifier to - /// refer to the member, e.g., "x->Base::f", or found its member via - /// a using declaration. When true, a MemberExprNameQualifier - /// structure is allocated immediately after the MemberExpr. + /// refer to the member, e.g., "x->Base::f". LLVM_PREFERRED_TYPE(bool) - unsigned HasQualifierOrFoundDecl : 1; + unsigned HasQualifier : 1; + + // True if this member expression found its member via a using declaration. + LLVM_PREFERRED_TYPE(bool) + unsigned HasFoundDecl : 1; /// True if this member expression specified a template keyword /// and/or a template argument list explicitly, e.g., x->f, diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h index de67f0b5714846f11ff2c5c2f76e8b1d972158f0..efb5bfe7f83d408717179e17a401dbb3075d1115 100644 --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -352,6 +352,7 @@ public: void VisitEnumConstantDecl(const EnumConstantDecl *D); void VisitIndirectFieldDecl(const IndirectFieldDecl *D); void VisitFunctionDecl(const FunctionDecl *D); + void VisitCXXDeductionGuideDecl(const CXXDeductionGuideDecl *D); void VisitFieldDecl(const FieldDecl *D); void VisitVarDecl(const VarDecl *D); void VisitBindingDecl(const BindingDecl *D); diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 1942b0e67f65a3157a36ae1b7dbf55bf9398a10f..99f45d518c7960fab956a317719a6870a2c8fdf4 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -61,6 +61,7 @@ class BTFTypeTagAttr; class ExtQuals; class QualType; class ConceptDecl; +class ValueDecl; class TagDecl; class TemplateParameterList; class Type; @@ -1689,7 +1690,10 @@ protected: /// Whether we have a stored size expression. LLVM_PREFERRED_TYPE(bool) - unsigned HasStoredSizeExpr : 1; + unsigned HasExternalSize : 1; + + LLVM_PREFERRED_TYPE(unsigned) + unsigned SizeWidth : 5; }; class BuiltinTypeBitfields { @@ -2000,6 +2004,21 @@ protected: unsigned NumExpansions; }; + class CountAttributedTypeBitfields { + friend class CountAttributedType; + + LLVM_PREFERRED_TYPE(TypeBitfields) + unsigned : NumTypeBits; + + static constexpr unsigned NumCoupledDeclsBits = 4; + unsigned NumCoupledDecls : NumCoupledDeclsBits; + LLVM_PREFERRED_TYPE(bool) + unsigned CountInBytes : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned OrNull : 1; + }; + static_assert(sizeof(CountAttributedTypeBitfields) <= sizeof(unsigned)); + union { TypeBitfields TypeBits; ArrayTypeBitfields ArrayTypeBits; @@ -2022,6 +2041,7 @@ protected: DependentTemplateSpecializationTypeBitfields DependentTemplateSpecializationTypeBits; PackExpansionTypeBitfields PackExpansionTypeBits; + CountAttributedTypeBitfields CountAttributedTypeBits; }; private: @@ -2244,6 +2264,8 @@ public: bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex) bool isHalfType() const; // OpenCL 6.1.1.1, NEON (IEEE 754-2008 half) bool isFloat16Type() const; // C11 extension ISO/IEC TS 18661 + bool isFloat32Type() const; + bool isDoubleType() const; bool isBFloat16Type() const; bool isFloat128Type() const; bool isIbm128Type() const; @@ -2262,6 +2284,7 @@ public: bool isFunctionProtoType() const { return getAs(); } bool isPointerType() const; bool isAnyPointerType() const; // Any C pointer or ObjC object pointer + bool isCountAttributedType() const; bool isBlockPointerType() const; bool isVoidPointerType() const; bool isReferenceType() const; @@ -2277,6 +2300,7 @@ public: bool isConstantArrayType() const; bool isIncompleteArrayType() const; bool isVariableArrayType() const; + bool isArrayParameterType() const; bool isDependentSizedArrayType() const; bool isRecordType() const; bool isClassType() const; @@ -2722,6 +2746,14 @@ template <> const TemplateSpecializationType *Type::getAs() const; /// until it reaches an AttributedType or a non-sugared type. template <> const AttributedType *Type::getAs() const; +/// This will check for a BoundsAttributedType by removing any existing +/// sugar until it reaches an BoundsAttributedType or a non-sugared type. +template <> const BoundsAttributedType *Type::getAs() const; + +/// This will check for a CountAttributedType by removing any existing +/// sugar until it reaches an CountAttributedType or a non-sugared type. +template <> const CountAttributedType *Type::getAs() const; + // We can do canonical leaf types faster, because we don't have to // worry about preserving child type decoration. #define TYPE(Class, Base) @@ -2920,6 +2952,136 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == Pointer; } }; +/// [BoundsSafety] Represents information of declarations referenced by the +/// arguments of the `counted_by` attribute and the likes. +class TypeCoupledDeclRefInfo { +public: + using BaseTy = llvm::PointerIntPair; + +private: + enum { + DerefShift = 0, + DerefMask = 1, + }; + BaseTy Data; + +public: + /// \p D is to a declaration referenced by the argument of attribute. \p Deref + /// indicates whether \p D is referenced as a dereferenced form, e.g., \p + /// Deref is true for `*n` in `int *__counted_by(*n)`. + TypeCoupledDeclRefInfo(ValueDecl *D = nullptr, bool Deref = false); + + bool isDeref() const; + ValueDecl *getDecl() const; + unsigned getInt() const; + void *getOpaqueValue() const; + bool operator==(const TypeCoupledDeclRefInfo &Other) const; + void setFromOpaqueValue(void *V); +}; + +/// [BoundsSafety] Represents a parent type class for CountAttributedType and +/// similar sugar types that will be introduced to represent a type with a +/// bounds attribute. +/// +/// Provides a common interface to navigate declarations referred to by the +/// bounds expression. + +class BoundsAttributedType : public Type, public llvm::FoldingSetNode { + QualType WrappedTy; + +protected: + ArrayRef Decls; // stored in trailing objects + + BoundsAttributedType(TypeClass TC, QualType Wrapped, QualType Canon); + +public: + bool isSugared() const { return true; } + QualType desugar() const { return WrappedTy; } + + using decl_iterator = const TypeCoupledDeclRefInfo *; + using decl_range = llvm::iterator_range; + + decl_iterator dependent_decl_begin() const { return Decls.begin(); } + decl_iterator dependent_decl_end() const { return Decls.end(); } + + unsigned getNumCoupledDecls() const { return Decls.size(); } + + decl_range dependent_decls() const { + return decl_range(dependent_decl_begin(), dependent_decl_end()); + } + + ArrayRef getCoupledDecls() const { + return {dependent_decl_begin(), dependent_decl_end()}; + } + + bool referencesFieldDecls() const; + + static bool classof(const Type *T) { + // Currently, only `class CountAttributedType` inherits + // `BoundsAttributedType` but the subclass will grow as we add more bounds + // annotations. + switch (T->getTypeClass()) { + case CountAttributed: + return true; + default: + return false; + } + } +}; + +/// Represents a sugar type with `__counted_by` or `__sized_by` annotations, +/// including their `_or_null` variants. +class CountAttributedType final + : public BoundsAttributedType, + public llvm::TrailingObjects { + friend class ASTContext; + + Expr *CountExpr; + /// \p CountExpr represents the argument of __counted_by or the likes. \p + /// CountInBytes indicates that \p CountExpr is a byte count (i.e., + /// __sized_by(_or_null)) \p OrNull means it's an or_null variant (i.e., + /// __counted_by_or_null or __sized_by_or_null) \p CoupledDecls contains the + /// list of declarations referenced by \p CountExpr, which the type depends on + /// for the bounds information. + CountAttributedType(QualType Wrapped, QualType Canon, Expr *CountExpr, + bool CountInBytes, bool OrNull, + ArrayRef CoupledDecls); + + unsigned numTrailingObjects(OverloadToken) const { + return CountAttributedTypeBits.NumCoupledDecls; + } + +public: + enum DynamicCountPointerKind { + CountedBy = 0, + SizedBy, + CountedByOrNull, + SizedByOrNull, + }; + + Expr *getCountExpr() const { return CountExpr; } + bool isCountInBytes() const { return CountAttributedTypeBits.CountInBytes; } + bool isOrNull() const { return CountAttributedTypeBits.OrNull; } + + DynamicCountPointerKind getKind() const { + if (isOrNull()) + return isCountInBytes() ? SizedByOrNull : CountedByOrNull; + return isCountInBytes() ? SizedBy : CountedBy; + } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, desugar(), CountExpr, isCountInBytes(), isOrNull()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, QualType WrappedTy, + Expr *CountExpr, bool CountInBytes, bool Nullable); + + static bool classof(const Type *T) { + return T->getTypeClass() == CountAttributed; + } +}; + /// Represents a type which was implicitly adjusted by the semantic /// engine for arbitrary reasons. For example, array and function types can /// decay, and function types can have their calling conventions adjusted. @@ -3173,42 +3335,114 @@ public: return T->getTypeClass() == ConstantArray || T->getTypeClass() == VariableArray || T->getTypeClass() == IncompleteArray || - T->getTypeClass() == DependentSizedArray; + T->getTypeClass() == DependentSizedArray || + T->getTypeClass() == ArrayParameter; } }; /// Represents the canonical version of C arrays with a specified constant size. /// For example, the canonical type for 'int A[4 + 4*100]' is a /// ConstantArrayType where the element type is 'int' and the size is 404. -class ConstantArrayType final - : public ArrayType, - private llvm::TrailingObjects { +class ConstantArrayType : public ArrayType { friend class ASTContext; // ASTContext creates these. - friend TrailingObjects; - llvm::APInt Size; // Allows us to unique the type. + struct ExternalSize { + ExternalSize(const llvm::APInt &Sz, const Expr *SE) + : Size(Sz), SizeExpr(SE) {} + llvm::APInt Size; // Allows us to unique the type. + const Expr *SizeExpr; + }; - ConstantArrayType(QualType et, QualType can, const llvm::APInt &size, - const Expr *sz, ArraySizeModifier sm, unsigned tq) - : ArrayType(ConstantArray, et, can, sm, tq, sz), Size(size) { - ConstantArrayTypeBits.HasStoredSizeExpr = sz != nullptr; - if (ConstantArrayTypeBits.HasStoredSizeExpr) { - assert(!can.isNull() && "canonical constant array should not have size"); - *getTrailingObjects() = sz; - } + union { + uint64_t Size; + ExternalSize *SizePtr; + }; + + ConstantArrayType(QualType Et, QualType Can, uint64_t Width, uint64_t Sz, + ArraySizeModifier SM, unsigned TQ) + : ArrayType(ConstantArray, Et, Can, SM, TQ, nullptr), Size(Sz) { + ConstantArrayTypeBits.HasExternalSize = false; + ConstantArrayTypeBits.SizeWidth = Width / 8; + // The in-structure size stores the size in bytes rather than bits so we + // drop the three least significant bits since they're always zero anyways. + assert(Width < 0xFF && "Type width in bits must be less than 8 bits"); } - unsigned numTrailingObjects(OverloadToken) const { - return ConstantArrayTypeBits.HasStoredSizeExpr; + ConstantArrayType(QualType Et, QualType Can, ExternalSize *SzPtr, + ArraySizeModifier SM, unsigned TQ) + : ArrayType(ConstantArray, Et, Can, SM, TQ, SzPtr->SizeExpr), + SizePtr(SzPtr) { + ConstantArrayTypeBits.HasExternalSize = true; + ConstantArrayTypeBits.SizeWidth = 0; + + assert((SzPtr->SizeExpr == nullptr || !Can.isNull()) && + "canonical constant array should not have size expression"); + } + + static ConstantArrayType *Create(const ASTContext &Ctx, QualType ET, + QualType Can, const llvm::APInt &Sz, + const Expr *SzExpr, ArraySizeModifier SzMod, + unsigned Qual); + +protected: + ConstantArrayType(TypeClass Tc, const ConstantArrayType *ATy, QualType Can) + : ArrayType(Tc, ATy->getElementType(), Can, ATy->getSizeModifier(), + ATy->getIndexTypeQualifiers().getAsOpaqueValue(), nullptr) { + ConstantArrayTypeBits.HasExternalSize = + ATy->ConstantArrayTypeBits.HasExternalSize; + if (!ConstantArrayTypeBits.HasExternalSize) { + ConstantArrayTypeBits.SizeWidth = ATy->ConstantArrayTypeBits.SizeWidth; + Size = ATy->Size; + } else + SizePtr = ATy->SizePtr; } public: - const llvm::APInt &getSize() const { return Size; } + /// Return the constant array size as an APInt. + llvm::APInt getSize() const { + return ConstantArrayTypeBits.HasExternalSize + ? SizePtr->Size + : llvm::APInt(ConstantArrayTypeBits.SizeWidth * 8, Size); + } + + /// Return the bit width of the size type. + unsigned getSizeBitWidth() const { + return ConstantArrayTypeBits.HasExternalSize + ? SizePtr->Size.getBitWidth() + : static_cast(ConstantArrayTypeBits.SizeWidth * 8); + } + + /// Return true if the size is zero. + bool isZeroSize() const { + return ConstantArrayTypeBits.HasExternalSize ? SizePtr->Size.isZero() + : 0 == Size; + } + + /// Return the size zero-extended as a uint64_t. + uint64_t getZExtSize() const { + return ConstantArrayTypeBits.HasExternalSize ? SizePtr->Size.getZExtValue() + : Size; + } + + /// Return the size sign-extended as a uint64_t. + int64_t getSExtSize() const { + return ConstantArrayTypeBits.HasExternalSize ? SizePtr->Size.getSExtValue() + : static_cast(Size); + } + + /// Return the size zero-extended to uint64_t or UINT64_MAX if the value is + /// larger than UINT64_MAX. + uint64_t getLimitedSize() const { + return ConstantArrayTypeBits.HasExternalSize + ? SizePtr->Size.getLimitedValue() + : Size; + } + + /// Return a pointer to the size expression. const Expr *getSizeExpr() const { - return ConstantArrayTypeBits.HasStoredSizeExpr - ? *getTrailingObjects() - : nullptr; + return ConstantArrayTypeBits.HasExternalSize ? SizePtr->SizeExpr : nullptr; } + bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -3225,17 +3459,31 @@ public: static unsigned getMaxSizeBits(const ASTContext &Context); void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) { - Profile(ID, Ctx, getElementType(), getSize(), getSizeExpr(), + Profile(ID, Ctx, getElementType(), getZExtSize(), getSizeExpr(), getSizeModifier(), getIndexTypeCVRQualifiers()); } static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx, - QualType ET, const llvm::APInt &ArraySize, - const Expr *SizeExpr, ArraySizeModifier SizeMod, - unsigned TypeQuals); + QualType ET, uint64_t ArraySize, const Expr *SizeExpr, + ArraySizeModifier SizeMod, unsigned TypeQuals); static bool classof(const Type *T) { - return T->getTypeClass() == ConstantArray; + return T->getTypeClass() == ConstantArray || + T->getTypeClass() == ArrayParameter; + } +}; + +/// Represents a constant array type that does not decay to a pointer when used +/// as a function parameter. +class ArrayParameterType : public ConstantArrayType { + friend class ASTContext; // ASTContext creates these. + + ArrayParameterType(const ConstantArrayType *ATy, QualType CanTy) + : ConstantArrayType(ArrayParameter, ATy, CanTy) {} + +public: + static bool classof(const Type *T) { + return T->getTypeClass() == ArrayParameter; } }; @@ -6967,7 +7215,8 @@ inline bool QualType::isCanonicalAsParam() const { if (T->isVariablyModifiedType() && T->hasSizedVLAType()) return false; - return !isa(T) && !isa(T); + return !isa(T) && + (!isa(T) || isa(T)); } inline bool QualType::isConstQualified() const { @@ -7232,6 +7481,10 @@ inline bool Type::isVariableArrayType() const { return isa(CanonicalType); } +inline bool Type::isArrayParameterType() const { + return isa(CanonicalType); +} + inline bool Type::isDependentSizedArrayType() const { return isa(CanonicalType); } @@ -7452,6 +7705,14 @@ inline bool Type::isFloat16Type() const { return isSpecificBuiltinType(BuiltinType::Float16); } +inline bool Type::isFloat32Type() const { + return isSpecificBuiltinType(BuiltinType::Float); +} + +inline bool Type::isDoubleType() const { + return isSpecificBuiltinType(BuiltinType::Double); +} + inline bool Type::isBFloat16Type() const { return isSpecificBuiltinType(BuiltinType::BFloat16); } @@ -7587,7 +7848,7 @@ inline bool Type::isTypedefNameType() const { /// Determines whether this type can decay to a pointer type. inline bool Type::canDecayToPointerType() const { - return isFunctionType() || isArrayType(); + return isFunctionType() || (isArrayType() && !isArrayParameterType()); } inline bool Type::hasPointerRepresentation() const { diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index 32028e877fc8dc0f0efa0cc0e9f0c631cd9635ae..9f2dff7a782cb328289f3be17e6ab42f144689da 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -1120,6 +1120,32 @@ public: } }; +struct BoundsAttributedLocInfo {}; +class BoundsAttributedTypeLoc + : public ConcreteTypeLoc { +public: + TypeLoc getInnerLoc() const { return getInnerTypeLoc(); } + QualType getInnerType() const { return getTypePtr()->desugar(); } + void initializeLocal(ASTContext &Context, SourceLocation Loc) { + // nothing to do + } + // LocalData is empty and TypeLocBuilder doesn't handle DataSize 1. + unsigned getLocalDataSize() const { return 0; } +}; + +class CountAttributedTypeLoc final + : public InheritingConcreteTypeLoc { +public: + Expr *getCountExpr() const { return getTypePtr()->getCountExpr(); } + bool isCountInBytes() const { return getTypePtr()->isCountInBytes(); } + bool isOrNull() const { return getTypePtr()->isOrNull(); } + + SourceRange getLocalSourceRange() const; +}; + struct MacroQualifiedLocInfo { SourceLocation ExpansionLoc; }; @@ -1585,6 +1611,11 @@ class ConstantArrayTypeLoc : ConstantArrayType> { }; +/// Wrapper for source info for array parameter types. +class ArrayParameterTypeLoc + : public InheritingConcreteTypeLoc< + ConstantArrayTypeLoc, ArrayParameterTypeLoc, ArrayParameterType> {}; + class IncompleteArrayTypeLoc : public InheritingConcreteTypeLoc; } +let Class = CountAttributedType in { + def : Property<"WrappedTy", QualType> { + let Read = [{ node->desugar() }]; + } + def : Property<"CountExpr", ExprRef> { + let Read = [{ node->getCountExpr() }]; + } + def : Property<"CountInBytes", Bool> { + let Read = [{ node->isCountInBytes() }]; + } + def : Property<"OrNull", Bool> { + let Read = [{ node->isOrNull() }]; + } + def : Property<"CoupledDecls", Array> { + let Read = [{ node->getCoupledDecls() }]; + } + def : Creator<[{ return ctx.getCountAttributedType(WrappedTy, CountExpr, CountInBytes, OrNull, CoupledDecls); }]>; +} + let Class = AdjustedType in { def : Property<"originalType", QualType> { let Read = [{ node->getOriginalType() }]; @@ -117,6 +136,13 @@ let Class = ConstantArrayType in { }]>; } +let Class = ArrayParameterType in { + def : Creator<[{ return ctx.getAdjustedParameterType( + ctx.getConstantArrayType(elementType,sizeValue, + size,sizeModifier, + indexQualifiers.getCVRQualifiers())); }]>; +} + let Class = IncompleteArrayType in { def : Creator<[{ return ctx.getIncompleteArrayType(elementType, sizeModifier, diff --git a/clang/include/clang/Analysis/FlowSensitive/AdornedCFG.h b/clang/include/clang/Analysis/FlowSensitive/AdornedCFG.h new file mode 100644 index 0000000000000000000000000000000000000000..420f13ce11bfde5b12d8ebe1dcb1735c27db936d --- /dev/null +++ b/clang/include/clang/Analysis/FlowSensitive/AdornedCFG.h @@ -0,0 +1,96 @@ +//===-- AdornedCFG.h ------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines an AdornedCFG class that is used by dataflow analyses that +// run over Control-Flow Graphs (CFGs). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ADORNEDCFG_H +#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ADORNEDCFG_H + +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/Stmt.h" +#include "clang/Analysis/CFG.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/Error.h" +#include +#include + +namespace clang { +namespace dataflow { + +/// Holds CFG with additional information derived from it that is needed to +/// perform dataflow analysis. +class AdornedCFG { +public: + /// Builds an `AdornedCFG` from a `FunctionDecl`. + /// `Func.doesThisDeclarationHaveABody()` must be true, and + /// `Func.isTemplated()` must be false. + static llvm::Expected build(const FunctionDecl &Func); + + /// Builds an `AdornedCFG` from an AST node. `D` is the function in which + /// `S` resides. `D.isTemplated()` must be false. + static llvm::Expected build(const Decl &D, Stmt &S, + ASTContext &C); + + /// Returns the `Decl` containing the statement used to construct the CFG, if + /// available. + const Decl &getDecl() const { return ContainingDecl; } + + /// Returns the CFG that is stored in this context. + const CFG &getCFG() const { return *Cfg; } + + /// Returns a mapping from statements to basic blocks that contain them. + const llvm::DenseMap &getStmtToBlock() const { + return StmtToBlock; + } + + /// Returns whether `B` is reachable from the entry block. + bool isBlockReachable(const CFGBlock &B) const { + return BlockReachable[B.getBlockID()]; + } + + /// Returns whether `B` contains an expression that is consumed in a + /// different block than `B` (i.e. the parent of the expression is in a + /// different block). + /// This happens if there is control flow within a full-expression (triggered + /// by `&&`, `||`, or the conditional operator). Note that the operands of + /// these operators are not the only expressions that can be consumed in a + /// different block. For example, in the function call + /// `f(&i, cond() ? 1 : 0)`, `&i` is in a different block than the `CallExpr`. + bool containsExprConsumedInDifferentBlock(const CFGBlock &B) const { + return ContainsExprConsumedInDifferentBlock.contains(&B); + } + +private: + AdornedCFG( + const Decl &D, std::unique_ptr Cfg, + llvm::DenseMap StmtToBlock, + llvm::BitVector BlockReachable, + llvm::DenseSet ContainsExprConsumedInDifferentBlock) + : ContainingDecl(D), Cfg(std::move(Cfg)), + StmtToBlock(std::move(StmtToBlock)), + BlockReachable(std::move(BlockReachable)), + ContainsExprConsumedInDifferentBlock( + std::move(ContainsExprConsumedInDifferentBlock)) {} + + /// The `Decl` containing the statement used to construct the CFG. + const Decl &ContainingDecl; + std::unique_ptr Cfg; + llvm::DenseMap StmtToBlock; + llvm::BitVector BlockReachable; + llvm::DenseSet ContainsExprConsumedInDifferentBlock; +}; + +} // namespace dataflow +} // namespace clang + +#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_ADORNEDCFG_H diff --git a/clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h b/clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h index 9a0a00f3c0134303d1b30e5a703db15204f03817..3972962d0b2daa681b0cdc99b3e951507e2d61ee 100644 --- a/clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h +++ b/clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h @@ -6,89 +6,20 @@ // //===----------------------------------------------------------------------===// // -// This file defines a ControlFlowContext class that is used by dataflow -// analyses that run over Control-Flow Graphs (CFGs). +// This file defines a deprecated alias for AdornedCFG. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CONTROLFLOWCONTEXT_H #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CONTROLFLOWCONTEXT_H -#include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" -#include "clang/AST/Stmt.h" -#include "clang/Analysis/CFG.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/Support/Error.h" -#include -#include +#include "clang/Analysis/FlowSensitive/AdornedCFG.h" namespace clang { namespace dataflow { -/// Holds CFG and other derived context that is needed to perform dataflow -/// analysis. -class ControlFlowContext { -public: - /// Builds a ControlFlowContext from a `FunctionDecl`. - /// `Func.doesThisDeclarationHaveABody()` must be true, and - /// `Func.isTemplated()` must be false. - static llvm::Expected build(const FunctionDecl &Func); - - /// Builds a ControlFlowContext from an AST node. `D` is the function in which - /// `S` resides. `D.isTemplated()` must be false. - static llvm::Expected build(const Decl &D, Stmt &S, - ASTContext &C); - - /// Returns the `Decl` containing the statement used to construct the CFG, if - /// available. - const Decl &getDecl() const { return ContainingDecl; } - - /// Returns the CFG that is stored in this context. - const CFG &getCFG() const { return *Cfg; } - - /// Returns a mapping from statements to basic blocks that contain them. - const llvm::DenseMap &getStmtToBlock() const { - return StmtToBlock; - } - - /// Returns whether `B` is reachable from the entry block. - bool isBlockReachable(const CFGBlock &B) const { - return BlockReachable[B.getBlockID()]; - } - - /// Returns whether `B` contains an expression that is consumed in a - /// different block than `B` (i.e. the parent of the expression is in a - /// different block). - /// This happens if there is control flow within a full-expression (triggered - /// by `&&`, `||`, or the conditional operator). Note that the operands of - /// these operators are not the only expressions that can be consumed in a - /// different block. For example, in the function call - /// `f(&i, cond() ? 1 : 0)`, `&i` is in a different block than the `CallExpr`. - bool containsExprConsumedInDifferentBlock(const CFGBlock &B) const { - return ContainsExprConsumedInDifferentBlock.contains(&B); - } - -private: - ControlFlowContext( - const Decl &D, std::unique_ptr Cfg, - llvm::DenseMap StmtToBlock, - llvm::BitVector BlockReachable, - llvm::DenseSet ContainsExprConsumedInDifferentBlock) - : ContainingDecl(D), Cfg(std::move(Cfg)), - StmtToBlock(std::move(StmtToBlock)), - BlockReachable(std::move(BlockReachable)), - ContainsExprConsumedInDifferentBlock( - std::move(ContainsExprConsumedInDifferentBlock)) {} - - /// The `Decl` containing the statement used to construct the CFG. - const Decl &ContainingDecl; - std::unique_ptr Cfg; - llvm::DenseMap StmtToBlock; - llvm::BitVector BlockReachable; - llvm::DenseSet ContainsExprConsumedInDifferentBlock; -}; +// This is a deprecated alias. Use `AdornedCFG` instead. +using ControlFlowContext = AdornedCFG; } // namespace dataflow } // namespace clang diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h index 3c84704d0d6cebe5d6fcc51954eaf61602e7c913..67eccdd030dcdd43f9488c902db5da658550eb1d 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h @@ -22,7 +22,7 @@ #include "clang/AST/ASTContext.h" #include "clang/Analysis/CFG.h" -#include "clang/Analysis/FlowSensitive/ControlFlowContext.h" +#include "clang/Analysis/FlowSensitive/AdornedCFG.h" #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" #include "clang/Analysis/FlowSensitive/DataflowLattice.h" #include "clang/Analysis/FlowSensitive/MatchSwitch.h" @@ -195,8 +195,7 @@ template llvm::Expected>>> runDataflowAnalysis( - const ControlFlowContext &CFCtx, AnalysisT &Analysis, - const Environment &InitEnv, + const AdornedCFG &ACFG, AnalysisT &Analysis, const Environment &InitEnv, std::function &)> PostVisitCFG = nullptr, @@ -218,7 +217,7 @@ runDataflowAnalysis( } auto TypeErasedBlockStates = runTypeErasedDataflowAnalysis( - CFCtx, Analysis, InitEnv, PostVisitCFGClosure, MaxBlockVisits); + ACFG, Analysis, InitEnv, PostVisitCFGClosure, MaxBlockVisits); if (!TypeErasedBlockStates) return TypeErasedBlockStates.takeError(); @@ -280,8 +279,7 @@ llvm::Expected> diagnoseFunction( Diagnoser, std::int64_t MaxSATIterations = 1'000'000'000, std::int32_t MaxBlockVisits = 20'000) { - llvm::Expected Context = - ControlFlowContext::build(FuncDecl); + llvm::Expected Context = AdornedCFG::build(FuncDecl); if (!Context) return Context.takeError(); diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h index 98bdf037880ab09b73f3ca271fe523aeafcdf6e8..909a91059438ca0dc40885f06addaf5f70f57401 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h @@ -18,8 +18,8 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" #include "clang/AST/TypeOrdering.h" +#include "clang/Analysis/FlowSensitive/AdornedCFG.h" #include "clang/Analysis/FlowSensitive/Arena.h" -#include "clang/Analysis/FlowSensitive/ControlFlowContext.h" #include "clang/Analysis/FlowSensitive/Solver.h" #include "clang/Analysis/FlowSensitive/StorageLocation.h" #include "clang/Analysis/FlowSensitive/Value.h" @@ -183,9 +183,9 @@ public: LLVM_DUMP_METHOD void dumpFlowCondition(Atom Token, llvm::raw_ostream &OS = llvm::dbgs()); - /// Returns the `ControlFlowContext` registered for `F`, if any. Otherwise, + /// Returns the `AdornedCFG` registered for `F`, if any. Otherwise, /// returns null. - const ControlFlowContext *getControlFlowContext(const FunctionDecl *F); + const AdornedCFG *getAdornedCFG(const FunctionDecl *F); const Options &getOptions() { return Opts; } @@ -296,7 +296,7 @@ private: llvm::DenseMap FlowConditionConstraints; const Formula *Invariant = nullptr; - llvm::DenseMap FunctionContexts; + llvm::DenseMap FunctionContexts; // Fields modeled by environments covered by this context. FieldSet ModeledFields; diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h index 2330697299fdd7aaffe728dae049c33cb5efdf9f..c30bccd06674a4d9036930a386b9da4afae78418 100644 --- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h +++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h @@ -744,6 +744,35 @@ RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME, std::vector getFieldsForInitListExpr(const InitListExpr *InitList); +/// Helper class for initialization of a record with an `InitListExpr`. +/// `InitListExpr::inits()` contains the initializers for both the base classes +/// and the fields of the record; this helper class separates these out into two +/// different lists. In addition, it deals with special cases associated with +/// unions. +class RecordInitListHelper { +public: + // `InitList` must have record type. + RecordInitListHelper(const InitListExpr *InitList); + + // Base classes with their associated initializer expressions. + ArrayRef> base_inits() const { + return BaseInits; + } + + // Fields with their associated initializer expressions. + ArrayRef> field_inits() const { + return FieldInits; + } + +private: + SmallVector> BaseInits; + SmallVector> FieldInits; + + // We potentially synthesize an `ImplicitValueInitExpr` for unions. It's a + // member variable because we store a pointer to it in `FieldInits`. + std::optional ImplicitValueInitForUnion; +}; + /// Associates a new `RecordValue` with `Loc` and returns the new value. RecordValue &refreshRecordValue(RecordStorageLocation &Loc, Environment &Env); diff --git a/clang/include/clang/Analysis/FlowSensitive/Logger.h b/clang/include/clang/Analysis/FlowSensitive/Logger.h index f4bd39f6ed49ef737fec66856e3929a6ab1b14af..f2e64810d00506717569e2e1c58c5cadec590c50 100644 --- a/clang/include/clang/Analysis/FlowSensitive/Logger.h +++ b/clang/include/clang/Analysis/FlowSensitive/Logger.h @@ -15,7 +15,7 @@ namespace clang::dataflow { // Forward declarations so we can use Logger anywhere in the framework. -class ControlFlowContext; +class AdornedCFG; class TypeErasedDataflowAnalysis; struct TypeErasedDataflowAnalysisState; @@ -40,8 +40,8 @@ public: /// Called by the framework as we start analyzing a new function or statement. /// Forms a pair with endAnalysis(). - virtual void beginAnalysis(const ControlFlowContext &, - TypeErasedDataflowAnalysis &) {} + virtual void beginAnalysis(const AdornedCFG &, TypeErasedDataflowAnalysis &) { + } virtual void endAnalysis() {} // At any time during the analysis, we're computing the state for some target diff --git a/clang/include/clang/Analysis/FlowSensitive/RecordOps.h b/clang/include/clang/Analysis/FlowSensitive/RecordOps.h index 783e53e980aa2c7ab42c708786c3e6e45f151bc2..8fad45fc11d81e76960f1ffb5dc81e8f06991b4c 100644 --- a/clang/include/clang/Analysis/FlowSensitive/RecordOps.h +++ b/clang/include/clang/Analysis/FlowSensitive/RecordOps.h @@ -31,7 +31,11 @@ namespace dataflow { /// /// Requirements: /// -/// `Src` and `Dst` must have the same canonical unqualified type. +/// Either: +/// - `Src` and `Dest` must have the same canonical unqualified type, or +/// - The type of `Src` must be derived from `Dest`, or +/// - The type of `Dest` must be derived from `Src` (in this case, any fields +/// that are only present in `Dest` are not overwritten). void copyRecord(RecordStorageLocation &Src, RecordStorageLocation &Dst, Environment &Env); diff --git a/clang/include/clang/Analysis/FlowSensitive/Transfer.h b/clang/include/clang/Analysis/FlowSensitive/Transfer.h index 7713df747cb76e7125eed2d7e243b93c4e3e86f6..ed148250d8eb29ac7da1aac20bbf83bef9c15480 100644 --- a/clang/include/clang/Analysis/FlowSensitive/Transfer.h +++ b/clang/include/clang/Analysis/FlowSensitive/Transfer.h @@ -29,12 +29,12 @@ public: // `CurState` is the pending state currently associated with this block. These // are supplied separately as the pending state for the current block may not // yet be represented in `BlockToState`. - StmtToEnvMap(const ControlFlowContext &CFCtx, + StmtToEnvMap(const AdornedCFG &ACFG, llvm::ArrayRef> BlockToState, unsigned CurBlockID, const TypeErasedDataflowAnalysisState &CurState) - : CFCtx(CFCtx), BlockToState(BlockToState), CurBlockID(CurBlockID), + : ACFG(ACFG), BlockToState(BlockToState), CurBlockID(CurBlockID), CurState(CurState) {} /// Returns the environment of the basic block that contains `S`. @@ -42,7 +42,7 @@ public: const Environment *getEnvironment(const Stmt &S) const; private: - const ControlFlowContext &CFCtx; + const AdornedCFG &ACFG; llvm::ArrayRef> BlockToState; unsigned CurBlockID; const TypeErasedDataflowAnalysisState &CurState; diff --git a/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h b/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h index a0ca7440230b04c4670fabca2b6e08f641232513..b3722bf3ec80a839567f0baee3324c1db2a71192 100644 --- a/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h +++ b/clang/include/clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h @@ -21,7 +21,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Stmt.h" #include "clang/Analysis/CFG.h" -#include "clang/Analysis/FlowSensitive/ControlFlowContext.h" +#include "clang/Analysis/FlowSensitive/AdornedCFG.h" #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" #include "clang/Analysis/FlowSensitive/DataflowLattice.h" @@ -146,7 +146,7 @@ struct TypeErasedDataflowAnalysisState { /// from converging. llvm::Expected>> runTypeErasedDataflowAnalysis( - const ControlFlowContext &CFCtx, TypeErasedDataflowAnalysis &Analysis, + const AdornedCFG &ACFG, TypeErasedDataflowAnalysis &Analysis, const Environment &InitEnv, std::function diff --git a/clang/include/clang/Analysis/PathDiagnostic.h b/clang/include/clang/Analysis/PathDiagnostic.h index 90559e7efb06f05f341cc1f79798de561155f765..5907df022e449d5be5c74230e3f189c63ecbc481 100644 --- a/clang/include/clang/Analysis/PathDiagnostic.h +++ b/clang/include/clang/Analysis/PathDiagnostic.h @@ -780,6 +780,9 @@ class PathDiagnostic : public llvm::FoldingSetNode { PathDiagnosticLocation UniqueingLoc; const Decl *UniqueingDecl; + /// The top-level entry point from which this issue was discovered. + const Decl *AnalysisEntryPoint = nullptr; + /// Lines executed in the path. std::unique_ptr ExecutedLines; @@ -788,7 +791,7 @@ public: PathDiagnostic(StringRef CheckerName, const Decl *DeclWithIssue, StringRef bugtype, StringRef verboseDesc, StringRef shortDesc, StringRef category, PathDiagnosticLocation LocationToUnique, - const Decl *DeclToUnique, + const Decl *DeclToUnique, const Decl *AnalysisEntryPoint, std::unique_ptr ExecutedLines); ~PathDiagnostic(); @@ -852,6 +855,9 @@ public: return *ExecutedLines; } + /// Get the top-level entry point from which this issue was discovered. + const Decl *getAnalysisEntryPoint() const { return AnalysisEntryPoint; } + /// Return the semantic context where an issue occurred. If the /// issue occurs along a path, this represents the "central" area /// where the bug manifests. diff --git a/clang/include/clang/Basic/AllDiagnostics.h b/clang/include/clang/Basic/AllDiagnostics.h index cc6aa631534a5d4ad2a3bea23de1e9c77bba1078..e64634cc138f7fd75d2d17227ee69eafa5ea2461 100644 --- a/clang/include/clang/Basic/AllDiagnostics.h +++ b/clang/include/clang/Basic/AllDiagnostics.h @@ -20,6 +20,7 @@ #include "clang/Basic/DiagnosticCrossTU.h" #include "clang/Basic/DiagnosticDriver.h" #include "clang/Basic/DiagnosticFrontend.h" +#include "clang/Basic/DiagnosticInstallAPI.h" #include "clang/Basic/DiagnosticLex.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 63efd85dcd4e58e76b2969be5fabf5b90c6e0fb3..6584460cf5685ea031ab5a6f746ae10871c8caf2 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2178,9 +2178,10 @@ def TypeNonNull : TypeAttr { let Documentation = [TypeNonNullDocs]; } -def TypeNullable : TypeAttr { +def TypeNullable : DeclOrTypeAttr { let Spellings = [CustomKeyword<"_Nullable">]; let Documentation = [TypeNullableDocs]; +// let Subjects = SubjectList<[CXXRecord], ErrorDiag>; } def TypeNullableResult : TypeAttr { @@ -2193,6 +2194,15 @@ def TypeNullUnspecified : TypeAttr { let Documentation = [TypeNullUnspecifiedDocs]; } +def CountedBy : DeclOrTypeAttr { + let Spellings = [Clang<"counted_by">]; + let Subjects = SubjectList<[Field], ErrorDiag>; + let Args = [ExprArgument<"Count">, IntArgument<"NestedLevel">]; + let ParseArgumentsAsUnevaluated = 1; + let Documentation = [CountedByDocs]; + let LangOpts = [COnly]; +} + // This is a marker used to indicate that an __unsafe_unretained qualifier was // ignored because ARC is not enabled. The usual representation for this // qualifier is as an ObjCOwnership attribute with Kind == "none". @@ -2934,7 +2944,7 @@ def Suppress : DeclOrStmtAttr { def SysVABI : DeclOrTypeAttr { let Spellings = [GCC<"sysv_abi">]; // let Subjects = [Function, ObjCMethod]; - let Documentation = [Undocumented]; + let Documentation = [SysVABIDocs]; } def ThisCall : DeclOrTypeAttr { @@ -3002,6 +3012,13 @@ def PreserveNone : DeclOrTypeAttr, TargetSpecificAttr { let Documentation = [PreserveNoneDocs]; } +def RISCVVectorCC: DeclOrTypeAttr, TargetSpecificAttr { + let Spellings = [CXX11<"riscv", "vector_cc">, + C23<"riscv", "vector_cc">, + Clang<"riscv_vector_cc">]; + let Documentation = [RISCVVectorCCDocs]; +} + def Target : InheritableAttr { let Spellings = [GCC<"target">]; let Args = [StringArgument<"featuresStr">]; @@ -3079,6 +3096,20 @@ def TargetClones : InheritableAttr { StringRef getFeatureStr(unsigned Index) const { return *(featuresStrs_begin() + Index); } + bool isDefaultVersion(unsigned Index) const { + return getFeatureStr(Index) == "default"; + } + void getFeatures(llvm::SmallVectorImpl &Out, + unsigned Index) const { + if (isDefaultVersion(Index)) return; + StringRef Features = getFeatureStr(Index); + SmallVector AttrFeatures; + Features.split(AttrFeatures, "+"); + for (auto &Feature : AttrFeatures) { + Feature = Feature.trim(); + Out.push_back(Feature); + } + } // Given an index into the 'featuresStrs' sequence, compute a unique // ID to be used with function name mangling for the associated variant. // This mapping is necessary due to a requirement that the mangling ID @@ -4487,21 +4518,3 @@ def CodeAlign: StmtAttr { static constexpr int MaximumAlignment = 4096; }]; } - -def CountedBy : InheritableAttr { - let Spellings = [Clang<"counted_by">]; - let Subjects = SubjectList<[Field]>; - let Args = [IdentifierArgument<"CountedByField">]; - let Documentation = [CountedByDocs]; - let LangOpts = [COnly]; - // FIXME: This is ugly. Let using a DeclArgument would be nice, but a Decl - // isn't yet available due to the fact that we're still parsing the - // structure. Maybe that code could be changed sometime in the future. - code AdditionalMembers = [{ - private: - SourceRange CountedByFieldLoc; - public: - SourceRange getCountedByFieldLoc() const { return CountedByFieldLoc; } - void setCountedByFieldLoc(SourceRange Loc) { CountedByFieldLoc = Loc; } - }]; -} diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index d61f96ade557d545b1b8a57453a0749535c037df..0ca4ea377fc36aca742d155d53edb072474ab255 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -4151,6 +4151,20 @@ non-underscored keywords. For example: @property (assign, nullable) NSView *superview; @property (readonly, nonnull) NSArray *subviews; @end + +As well as built-in pointer types, the nullability attributes can be attached +to C++ classes marked with the ``_Nullable`` attribute. + +The following C++ standard library types are considered nullable: +``unique_ptr``, ``shared_ptr``, ``auto_ptr``, ``exception_ptr``, ``function``, +``move_only_function`` and ``coroutine_handle``. + +Types should be marked nullable only where the type itself leaves nullability +ambiguous. For example, ``std::optional`` is not marked ``_Nullable``, because +``optional _Nullable`` is redundant and ``optional _Nonnull`` is +not a useful type. ``std::weak_ptr`` is not nullable, because its nullability +can change with no visible modification, so static annotation is unlikely to be +unhelpful. }]; } @@ -4185,6 +4199,17 @@ The ``_Nullable`` nullability qualifier indicates that a value of the int fetch_or_zero(int * _Nullable ptr); a caller of ``fetch_or_zero`` can provide null. + +The ``_Nullable`` attribute on classes indicates that the given class can +represent null values, and so the ``_Nullable``, ``_Nonnull`` etc qualifiers +make sense for this type. For example: + + .. code-block:: c + + class _Nullable ArenaPointer { ... }; + + ArenaPointer _Nonnull x = ...; + ArenaPointer _Nullable y = nullptr; }]; } @@ -5137,10 +5162,11 @@ that does not. A single parameter may not have multiple ABI treatment attributes. Support for this feature is target-dependent, although it should be -supported on every target that Swift supports. Query for this support -with ``__has_attribute(swiftcall)``. This implies support for the -``swift_context``, ``swift_error_result``, and ``swift_indirect_result`` -attributes. +supported on every target that Swift supports. Query for this attribute +with ``__has_attribute(swiftcall)``. Query if the target supports the +calling convention with ``__has_extension(swiftcc)``. This implies +support for the ``swift_context``, ``swift_error_result``, and +``swift_indirect_result`` attributes. }]; } @@ -5187,6 +5213,10 @@ the following: semantically be performed after a guaranteed tail call, such as the non-trivial destruction of a local variable or temporary, then the program is ill-formed. + +Query for this attribute with ``__has_attribute(swiftasynccall)``. Query if +the target supports the calling convention with +``__has_extension(swiftasynccc)``. }]; } @@ -5489,6 +5519,17 @@ for clang builtin functions. }]; } +def RISCVVectorCCDocs : Documentation { + let Category = DocCatCallingConvs; + let Heading = "riscv::vector_cc, riscv_vector_cc, clang::riscv_vector_cc"; + let Content = [{ +The ``riscv_vector_cc`` attribute can be applied to a function. It preserves 15 +registers namely, v1-v7 and v24-v31 as callee-saved. Callers thus don't need +to save these registers before function calls, and callees only need to save +them if they use them. + }]; +} + def PreferredNameDocs : Documentation { let Category = DocCatDecl; let Content = [{ @@ -6064,6 +6105,9 @@ def AlwaysDestroyDocs : Documentation { The ``always_destroy`` attribute specifies that a variable with static or thread storage duration should have its exit-time destructor run. This attribute is the default unless clang was invoked with -fno-c++-static-destructors. + +If a variable is explicitly declared with this attribute, Clang will silence +otherwise applicable ``-Wexit-time-destructors`` warnings. }]; } diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def new file mode 100644 index 0000000000000000000000000000000000000000..f356f881d5ef9bc2e2a13f806d40e0ab8a93c283 --- /dev/null +++ b/clang/include/clang/Basic/Builtins.def @@ -0,0 +1,102 @@ +//===--- Builtins.def - Builtin function info database ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// This is only documentation for the database layout. This will be removed once +// all builtin databases are converted to tablegen files + +// The second value provided to the macro specifies the type of the function +// (result value, then each argument) as follows: +// v -> void +// b -> boolean +// c -> char +// s -> short +// i -> int +// h -> half (__fp16, OpenCL) +// x -> half (_Float16) +// y -> half (__bf16) +// f -> float +// d -> double +// z -> size_t +// w -> wchar_t +// F -> constant CFString +// G -> id +// H -> SEL +// M -> struct objc_super +// a -> __builtin_va_list +// A -> "reference" to __builtin_va_list +// V -> Vector, followed by the number of elements and the base type. +// q -> Scalable vector, followed by the number of elements and the base type. +// Q -> target builtin type, followed by a character to distinguish the builtin type +// Qa -> AArch64 svcount_t builtin type. +// E -> ext_vector, followed by the number of elements and the base type. +// X -> _Complex, followed by the base type. +// Y -> ptrdiff_t +// P -> FILE +// J -> jmp_buf +// SJ -> sigjmp_buf +// K -> ucontext_t +// p -> pid_t +// . -> "...". This may only occur at the end of the function list. +// +// Types may be prefixed with the following modifiers: +// L -> long (e.g. Li for 'long int', Ld for 'long double') +// LL -> long long (e.g. LLi for 'long long int', LLd for __float128) +// LLL -> __int128_t (e.g. LLLi) +// Z -> int32_t (require a native 32-bit integer type on the target) +// W -> int64_t (require a native 64-bit integer type on the target) +// N -> 'int' size if target is LP64, 'L' otherwise. +// O -> long for OpenCL targets, long long otherwise. +// S -> signed +// U -> unsigned +// I -> Required to constant fold to an integer constant expression. +// +// Types may be postfixed with the following modifiers: +// * -> pointer (optionally followed by an address space number, if no address +// space is specified than any address space will be accepted) +// & -> reference (optionally followed by an address space number) +// C -> const +// D -> volatile +// R -> restrict + +// The third value provided to the macro specifies information about attributes +// of the function. These must be kept in sync with the predicates in the +// Builtin::Context class. Currently we have: +// n -> nothrow +// r -> noreturn +// U -> pure +// c -> const +// t -> signature is meaningless, use custom typechecking +// T -> type is not important to semantic analysis and codegen; recognize as +// builtin even if type doesn't match signature, and don't warn if we +// can't be sure the type is right +// F -> this is a libc/libm function with a '__builtin_' prefix added. +// f -> this is a libc/libm function without a '__builtin_' prefix, or with +// 'z', a C++ standard library function in namespace std::. This builtin +// is disableable by '-fno-builtin-foo' / '-fno-builtin-std-foo'. +// h -> this function requires a specific header or an explicit declaration. +// i -> this is a runtime library implemented function without the +// '__builtin_' prefix. It will be implemented in compiler-rt or libgcc. +// p:N: -> this is a printf-like function whose Nth argument is the format +// string. +// P:N: -> similar to the p:N: attribute, but the function is like vprintf +// in that it accepts its arguments as a va_list rather than +// through an ellipsis +// s:N: -> this is a scanf-like function whose Nth argument is the format +// string. +// S:N: -> similar to the s:N: attribute, but the function is like vscanf +// in that it accepts its arguments as a va_list rather than +// through an ellipsis +// e -> const, but only when -fno-math-errno and FP exceptions are ignored +// g -> const when FP exceptions are ignored +// j -> returns_twice (like setjmp) +// u -> arguments are not evaluated for their side-effects +// V:N: -> requires vectors of at least N bits to be legal +// C -> callback behavior: argument N is called with argument +// M_0, ..., M_k as payload +// z -> this is a function in (possibly-versioned) namespace std +// E -> this function can be constant evaluated by Clang frontend diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 9c703377ca8d3e8d5bf47a6dd4ee3ad7fe4e7d97..f421223ff087de69fe33cfda2fbbda15876b058d 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -676,7 +676,11 @@ def Clz : Builtin, BitShort_Int_Long_LongLongTemplate { let Prototype = "int(unsigned T)"; } -// FIXME: Add int clzimax(uintmax_t) +def Clzg : Builtin { + let Spellings = ["__builtin_clzg"]; + let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking]; + let Prototype = "int(...)"; +} def Ctz : Builtin, BitShort_Int_Long_LongLongTemplate { let Spellings = ["__builtin_ctz"]; @@ -684,7 +688,11 @@ def Ctz : Builtin, BitShort_Int_Long_LongLongTemplate { let Prototype = "int(unsigned T)"; } -// FIXME: Add int ctzimax(uintmax_t) +def Ctzg : Builtin { + let Spellings = ["__builtin_ctzg"]; + let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking]; + let Prototype = "int(...)"; +} def FFS : Builtin, BitInt_Long_LongLongTemplate { let Spellings = ["__builtin_ffs"]; @@ -4354,6 +4362,43 @@ def CoroSuspend : CoroLangBuiltin { let Prototype = "char(_Constant bool)"; } +// Pointer authentication builtins. +def PtrauthStrip : Builtin { + let Spellings = ["__builtin_ptrauth_strip"]; + let Attributes = [CustomTypeChecking, NoThrow, Const]; + let Prototype = "void*(void*,int)"; +} + +def PtrauthBlendDiscriminator : Builtin { + let Spellings = ["__builtin_ptrauth_blend_discriminator"]; + let Attributes = [CustomTypeChecking, NoThrow, Const]; + let Prototype = "size_t(void*,int)"; +} + +def PtrauthSignUnauthenticated : Builtin { + let Spellings = ["__builtin_ptrauth_sign_unauthenticated"]; + let Attributes = [CustomTypeChecking, NoThrow, Const]; + let Prototype = "void*(void*,int,void*)"; +} + +def PtrauthSignGenericData : Builtin { + let Spellings = ["__builtin_ptrauth_sign_generic_data"]; + let Attributes = [CustomTypeChecking, NoThrow, Const]; + let Prototype = "size_t(void*,void*)"; +} + +def PtrauthAuthAndResign : Builtin { + let Spellings = ["__builtin_ptrauth_auth_and_resign"]; + let Attributes = [CustomTypeChecking, NoThrow]; + let Prototype = "void*(void*,int,void*,int,void*)"; +} + +def PtrauthAuth : Builtin { + let Spellings = ["__builtin_ptrauth_auth"]; + let Attributes = [CustomTypeChecking, NoThrow]; + let Prototype = "void*(void*,int,void*)"; +} + // OpenCL v2.0 s6.13.16, s9.17.3.5 - Pipe functions. // We need the generic prototype, since the packet type could be anything. def ReadPipe : OCLPipeLangBuiltin { @@ -4554,6 +4599,18 @@ def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> { let Prototype = "unsigned int(bool)"; } +def HLSLWaveGetLaneIndex : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_wave_get_lane_index"]; + let Attributes = [NoThrow, Const]; + let Prototype = "unsigned int()"; +} + +def HLSLClamp : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_elementwise_clamp"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLCreateHandle : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_create_handle"]; let Attributes = [NoThrow, Const]; @@ -4572,6 +4629,12 @@ def HLSLFrac : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLIsinf : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_elementwise_isinf"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def HLSLLerp : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_lerp"]; let Attributes = [NoThrow, Const]; @@ -4590,6 +4653,12 @@ def HLSLRcp : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(...)"; } +def HLSLRSqrt : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_elementwise_rsqrt"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + // Builtins for XRay. def XRayCustomEvent : Builtin { let Spellings = ["__xray_customevent"]; diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def index b5cbe90c8fd6a35186b327dd3ca8ab75e64a18c2..cf8711c6eaee37249f4a54effb379c733ab71d5e 100644 --- a/clang/include/clang/Basic/BuiltinsAArch64.def +++ b/clang/include/clang/Basic/BuiltinsAArch64.def @@ -50,6 +50,9 @@ BUILTIN(__builtin_arm_wfi, "v", "") BUILTIN(__builtin_arm_sev, "v", "") BUILTIN(__builtin_arm_sevl, "v", "") +// Like __builtin_trap but provide an 16-bit immediate reason code (which goes into `brk #N`). +BUILTIN(__builtin_arm_trap, "vUIs", "nr") + // CRC32 TARGET_BUILTIN(__builtin_arm_crc32b, "UiUiUc", "nc", "crc") TARGET_BUILTIN(__builtin_arm_crc32cb, "UiUiUc", "nc", "crc") diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def b/clang/include/clang/Basic/BuiltinsAMDGPU.def index 61ec8b79bf054daa03e02fddca3c4edb2da75088..c660582cc98e666031ae1dfbecf9d9b4612c9eae 100644 --- a/clang/include/clang/Basic/BuiltinsAMDGPU.def +++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def @@ -432,13 +432,10 @@ TARGET_BUILTIN(__builtin_amdgcn_s_wakeup_barrier, "vi", "n", "gfx12-insts") TARGET_BUILTIN(__builtin_amdgcn_s_barrier_leave, "b", "n", "gfx12-insts") TARGET_BUILTIN(__builtin_amdgcn_s_get_barrier_state, "Uii", "n", "gfx12-insts") -TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_v2i32, "V2iV2i*1", "nc", "gfx12-insts,wavefrontsize32") -TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_v8i16, "V8sV8s*1", "nc", "gfx12-insts,wavefrontsize32") -TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_v8f16, "V8hV8h*1", "nc", "gfx12-insts,wavefrontsize32") - -TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_i32, "ii*1", "nc", "gfx12-insts,wavefrontsize64") -TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_v4i16, "V4sV4s*1", "nc", "gfx12-insts,wavefrontsize64") -TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_v4f16, "V4hV4h*1", "nc", "gfx12-insts,wavefrontsize64") +TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b64_v2i32, "V2iV2i*1", "nc", "gfx12-insts,wavefrontsize32") +TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b128_v8i16, "V8sV8s*1", "nc", "gfx12-insts,wavefrontsize32") +TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b64_i32, "ii*1", "nc", "gfx12-insts,wavefrontsize64") +TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b128_v4i16, "V4sV4s*1", "nc", "gfx12-insts,wavefrontsize64") //===----------------------------------------------------------------------===// // WMMA builtins. diff --git a/clang/include/clang/Basic/CMakeLists.txt b/clang/include/clang/Basic/CMakeLists.txt index 7785fb430c069ba7d065d52ad9e9bdc1a3d0c4a4..7d53c751c13ac405d8293d912f97dd2a683e1659 100644 --- a/clang/include/clang/Basic/CMakeLists.txt +++ b/clang/include/clang/Basic/CMakeLists.txt @@ -12,6 +12,7 @@ clang_diag_gen(Common) clang_diag_gen(CrossTU) clang_diag_gen(Driver) clang_diag_gen(Frontend) +clang_diag_gen(InstallAPI) clang_diag_gen(Lex) clang_diag_gen(Parse) clang_diag_gen(Refactoring) diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 6ad05031962562c205e8d63dda3049e5422e4122..340b08dd7e2a33422dfc4680ff71d2f6152a709d 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -59,6 +59,7 @@ CODEGENOPT(UniqueBasicBlockSectionNames, 1, 1) ///< Set for -funique-basic-block ///< basic block sections. CODEGENOPT(EnableAIXExtendedAltivecABI, 1, 0) ///< Set for -mabi=vec-extabi. Enables the extended Altivec ABI on AIX. CODEGENOPT(XCOFFReadOnlyPointers, 1, 0) ///< Set for -mxcoff-roptr. +CODEGENOPT(AllTocData, 1, 0) ///< AIX -mtocdata ENUM_CODEGENOPT(FramePointer, FramePointerKind, 2, FramePointerKind::None) /// frame-pointer: all,non-leaf,none CODEGENOPT(ClearASTBeforeBackend , 1, 0) ///< Free the AST before running backend code generation. Only works with -disable-free. diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 3f8fe385fef3dff91d0ee35adabc69d5d42e4c1d..9469a424045bb0472a6cd725ebf55bfa1e0e08d8 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -404,6 +404,12 @@ public: /// List of pass builder callbacks. std::vector> PassBuilderCallbacks; + /// List of global variables explicitly specified by the user as toc-data. + std::vector TocDataVarsUserSpecified; + + /// List of global variables that over-ride the toc-data default. + std::vector NoTocDataVars; + /// Path to allowlist file specifying which objects /// (files, functions) should exclusively be instrumented /// by sanitizer coverage pass. diff --git a/clang/include/clang/Basic/Diagnostic.td b/clang/include/clang/Basic/Diagnostic.td index 8d66e265fbaef00db435bc2feb4c6fd1484862aa..0b8b3af939ba0e27da045ef20f0b47ec365f330b 100644 --- a/clang/include/clang/Basic/Diagnostic.td +++ b/clang/include/clang/Basic/Diagnostic.td @@ -162,6 +162,7 @@ include "DiagnosticCommonKinds.td" include "DiagnosticCrossTUKinds.td" include "DiagnosticDriverKinds.td" include "DiagnosticFrontendKinds.td" +include "DiagnosticInstallAPIKinds.td" include "DiagnosticLexKinds.td" include "DiagnosticParseKinds.td" include "DiagnosticRefactoringKinds.td" diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index 08bb1d81ba29f10c2361790a2f7efdd9055e3ca9..a52bf62e24202caf2746cc7c56332032c84eb214 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -45,6 +45,11 @@ def note_using : Note<"using">; def note_possibility : Note<"one possibility">; def note_also_found : Note<"also found">; +def warn_next_larger_fp_type_same_size_than_fp : Warning< + "higher precision floating-point type size has the same size than " + "floating-point type size">, + InGroup>; + // Parse && Lex let CategoryName = "Lexical or Preprocessor Issue" in { @@ -356,6 +361,8 @@ def warn_target_unrecognized_env : Warning< def warn_knl_knm_isa_support_removed : Warning< "KNL, KNM related Intel Xeon Phi CPU's specific ISA's supports will be removed in LLVM 19.">, InGroup>; +def err_target_unsupported_abi_with_fpu : Error< + "'%0' ABI is not supported with FPU">; // Source manager def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal; diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 1bc9885849d54bf2fdee50739caf48794880a8f6..592ed3bda51506624b0438f6fdce1ab31a7ab0b0 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -587,6 +587,9 @@ def warn_drv_unsupported_gpopt : Warning< "ignoring '-mgpopt' option as it cannot be used with %select{|the implicit" " usage of }0-mabicalls">, InGroup; +def warn_drv_unsupported_tocdata: Warning< + "ignoring '-mtocdata' as it is only supported for -mcmodel=small">, + InGroup; def warn_drv_unsupported_sdata : Warning< "ignoring '-msmall-data-limit=' with -mcmodel=large for -fpic or RV64">, InGroup; @@ -750,7 +753,8 @@ def err_drv_hlsl_unsupported_target : Error< "HLSL code generation is unsupported for target '%0'">; def err_drv_hlsl_bad_shader_required_in_target : Error< "%select{shader model|Vulkan environment|shader stage}0 is required as %select{OS|environment}1 in target '%2' for HLSL code generation">; - +def err_drv_hlsl_16bit_types_unsupported: Error< + "'%0' option requires target HLSL Version >= 2018%select{| and shader model >= 6.2}1, but HLSL Version is '%2'%select{| and shader model is '%3'}1">; def err_drv_hlsl_bad_shader_unsupported : Error< "%select{shader model|Vulkan environment|shader stage}0 '%1' in target '%2' is invalid for HLSL code generation">; def warn_drv_dxc_missing_dxv : Warning<"dxv not found. " diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index dcd2c19fb7ee3663ba99f71c36fdeaef8e11ebfd..ba23cf84c5e3438d860c0f65e5bbf472f3b63946 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -94,6 +94,8 @@ def err_fe_backend_error_attr : def warn_fe_backend_warning_attr : Warning<"call to '%0' declared with 'warning' attribute: %1">, BackendInfo, InGroup; +def warn_toc_unsupported_type : Warning<"-mtocdata option is ignored " + "for %0 because %1">, InGroup; def err_fe_invalid_code_complete_file : Error< "cannot locate code-completion file %0">, DefaultFatal; @@ -279,6 +281,8 @@ def err_builtin_needs_feature : Error<"%0 needs target feature %1">; def err_function_needs_feature : Error< "always_inline function %1 requires target feature '%2', but would " "be inlined into function %0 that is compiled without support for '%2'">; + +let CategoryName = "Codegen ABI Check" in { def err_function_always_inline_attribute_mismatch : Error< "always_inline function %1 and its caller %0 have mismatching %2 attributes">; def err_function_always_inline_new_za : Error< @@ -290,6 +294,10 @@ def warn_avx_calling_convention InGroup>; def err_avx_calling_convention : Error; +def err_target_unsupported_type_for_abi + : Error<"%0 requires %1 type support, but ABI '%2' does not support it">; +} + def err_alias_to_undefined : Error< "%select{alias|ifunc}0 must point to a defined " "%select{variable or |}1function">; diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 3f14167d6b84693a630622abc4bef061f7870b61..520168f01fd846c540c22e958b709f9d72b2e9c1 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -573,7 +573,10 @@ def SelTypeCast : DiagGroup<"cast-of-sel-type">; def FunctionDefInObjCContainer : DiagGroup<"function-def-in-objc-container">; def BadFunctionCast : DiagGroup<"bad-function-cast">; def CastFunctionTypeStrict : DiagGroup<"cast-function-type-strict">; -def CastFunctionType : DiagGroup<"cast-function-type", [CastFunctionTypeStrict]>; +def CastFunctionTypeMismatch : DiagGroup<"cast-function-type-mismatch">; +def CastFunctionType : DiagGroup<"cast-function-type", + [CastFunctionTypeStrict, + CastFunctionTypeMismatch]>; def ObjCPropertyImpl : DiagGroup<"objc-property-implementation">; def ObjCPropertyNoAttribute : DiagGroup<"objc-property-no-attribute">; def ObjCPropertyAssignOnObjectType : DiagGroup<"objc-property-assign-on-object-type">; @@ -875,6 +878,7 @@ def ZeroLengthArray : DiagGroup<"zero-length-array">; def GNUZeroLineDirective : DiagGroup<"gnu-zero-line-directive">; def GNUZeroVariadicMacroArguments : DiagGroup<"gnu-zero-variadic-macro-arguments">; def MisleadingIndentation : DiagGroup<"misleading-indentation">; +def PtrAuthNullPointers : DiagGroup<"ptrauth-null-pointers">; // This covers both the deprecated case (in C++98) // and the extension case (in C++11 onwards). @@ -981,6 +985,7 @@ def FormatSecurity : DiagGroup<"format-security">; def FormatNonStandard : DiagGroup<"format-non-iso">; def FormatY2K : DiagGroup<"format-y2k">; def FormatPedantic : DiagGroup<"format-pedantic">; +def FormatSignedness : DiagGroup<"format-signedness">; def FormatTypeConfusion : DiagGroup<"format-type-confusion">; def FormatOverflowNonKprintf: DiagGroup<"format-overflow-non-kprintf">; @@ -1037,6 +1042,7 @@ def Extra : DiagGroup<"extra", [ EmptyInitStatement, StringConcatation, FUseLdPath, + CastFunctionTypeMismatch, ]>; def Most : DiagGroup<"most", [ @@ -1507,3 +1513,7 @@ def ReadOnlyPlacementChecks : DiagGroup<"read-only-types">; // Warnings and fixes to support the "safe buffers" programming model. def UnsafeBufferUsageInContainer : DiagGroup<"unsafe-buffer-usage-in-container">; def UnsafeBufferUsage : DiagGroup<"unsafe-buffer-usage", [UnsafeBufferUsageInContainer]>; + +// Warnings and notes InstallAPI verification. +def InstallAPIViolation : DiagGroup<"installapi-violation">; + diff --git a/clang/include/clang/Basic/DiagnosticIDs.h b/clang/include/clang/Basic/DiagnosticIDs.h index 0cdda42793f6f0a0ac08bce4ca55b2d83ea06655..5ff782c7f8c7e812203a77fbc91beb751e8f78d9 100644 --- a/clang/include/clang/Basic/DiagnosticIDs.h +++ b/clang/include/clang/Basic/DiagnosticIDs.h @@ -42,6 +42,7 @@ namespace clang { DIAG_SIZE_SEMA = 4500, DIAG_SIZE_ANALYSIS = 100, DIAG_SIZE_REFACTORING = 1000, + DIAG_SIZE_INSTALLAPI = 100, }; // Start position for diagnostics. enum { @@ -57,7 +58,8 @@ namespace clang { DIAG_START_SEMA = DIAG_START_CROSSTU + static_cast(DIAG_SIZE_CROSSTU), DIAG_START_ANALYSIS = DIAG_START_SEMA + static_cast(DIAG_SIZE_SEMA), DIAG_START_REFACTORING = DIAG_START_ANALYSIS + static_cast(DIAG_SIZE_ANALYSIS), - DIAG_UPPER_LIMIT = DIAG_START_REFACTORING + static_cast(DIAG_SIZE_REFACTORING) + DIAG_START_INSTALLAPI = DIAG_START_REFACTORING + static_cast(DIAG_SIZE_REFACTORING), + DIAG_UPPER_LIMIT = DIAG_START_INSTALLAPI + static_cast(DIAG_SIZE_INSTALLAPI) }; class CustomDiagInfo; @@ -276,6 +278,9 @@ public: /// category. static bool isARCDiagnostic(unsigned DiagID); + /// Return true if a given diagnostic is a codegen-time ABI check. + static bool isCodegenABICheckDiagnostic(unsigned DiagID); + /// Enumeration describing how the emission of a diagnostic should /// be treated when it occurs during C++ template argument deduction. enum SFINAEResponse { diff --git a/clang/include/clang/Basic/DiagnosticInstallAPI.h b/clang/include/clang/Basic/DiagnosticInstallAPI.h new file mode 100644 index 0000000000000000000000000000000000000000..a76f6e087a2b0a7439082a76add6fa61950b5db7 --- /dev/null +++ b/clang/include/clang/Basic/DiagnosticInstallAPI.h @@ -0,0 +1,26 @@ +//===--- DiagnosticInstallAPI.h - Diagnostics for InstallAPI-----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_DIAGNOSTICINSTALLAPI_H +#define LLVM_CLANG_BASIC_DIAGNOSTICINSTALLAPI_H + +#include "clang/Basic/Diagnostic.h" +namespace clang { +namespace diag { +enum { +#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \ + SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \ + ENUM, +#define INSTALLAPISTART +#include "clang/Basic/DiagnosticInstallAPIKinds.inc" +#undef DIAG + NUM_BUILTIN_INSTALLAPI_DIAGNOSTICS +}; +} // namespace diag +} // namespace clang +#endif // LLVM_CLANG_BASIC_DIAGNOSTICINSTALLAPI_H diff --git a/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td new file mode 100644 index 0000000000000000000000000000000000000000..e3263fe9ccb9d4177a70b83ab5cf260693ed7278 --- /dev/null +++ b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td @@ -0,0 +1,48 @@ +//==--- DiagnosticInstallAPIKinds.td - installapi diagnostics -------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// InstallAPI Diagnostics +//===----------------------------------------------------------------------===// + +let Component = "InstallAPI" in { +let CategoryName = "Command line" in { +def err_cannot_write_file : Error<"cannot write file '%0': %1">; +def err_no_install_name : Error<"no install name specified: add -install_name ">; +def err_no_output_file: Error<"no output file specified">; +def err_no_such_header_file : Error<"no such %select{public|private|project}1 header file: '%0'">; +def warn_no_such_excluded_header_file : Warning<"no such excluded %select{public|private}0 header file: '%1'">, InGroup; +def warn_glob_did_not_match: Warning<"glob '%0' did not match any header file">, InGroup; +def err_no_such_umbrella_header_file : Error<"%select{public|private|project}1 umbrella header file not found in input: '%0'">; +} // end of command line category. + +let CategoryName = "Verification" in { +def warn_target: Warning<"violations found for %0">, InGroup; +def err_library_missing_symbol : Error<"declaration has external linkage, but dynamic library doesn't have symbol '%0'">; +def warn_library_missing_symbol : Warning<"declaration has external linkage, but dynamic library doesn't have symbol '%0'">, InGroup; +def err_library_hidden_symbol : Error<"declaration has external linkage, but symbol has internal linkage in dynamic library '%0'">; +def warn_library_hidden_symbol : Warning<"declaration has external linkage, but symbol has internal linkage in dynamic library '%0'">, InGroup; +def warn_header_hidden_symbol : Warning<"symbol exported in dynamic library, but marked hidden in declaration '%0'">, InGroup; +def err_header_hidden_symbol : Error<"symbol exported in dynamic library, but marked hidden in declaration '%0'">; +def err_header_symbol_missing : Error<"no declaration found for exported symbol '%0' in dynamic library">; +def warn_header_symbol_missing : Warning<"no declaration was found for exported symbol '%0' in dynamic library">, InGroup; +def warn_header_availability_mismatch : Warning<"declaration '%0' is marked %select{available|unavailable}1," + " but symbol is %select{not |}2exported in dynamic library">, InGroup; +def err_header_availability_mismatch : Error<"declaration '%0' is marked %select{available|unavailable}1," + " but symbol is %select{not |}2exported in dynamic library">; +def warn_dylib_symbol_flags_mismatch : Warning<"dynamic library symbol '%0' is " + "%select{weak defined|thread local}1, but its declaration is not">, InGroup; +def warn_header_symbol_flags_mismatch : Warning<"declaration '%0' is " + "%select{weak defined|thread local}1, but symbol is not in dynamic library">, InGroup; +def err_dylib_symbol_flags_mismatch : Error<"dynamic library symbol '%0' is " + "%select{weak defined|thread local}1, but its declaration is not">; +def err_header_symbol_flags_mismatch : Error<"declaration '%0' is " + "%select{weak defined|thread local}1, but symbol is not in dynamic library">; +} // end of Verification category. + +} // end of InstallAPI component diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td index d7c172e65463511031c51e8ca38705d7ff556625..ad6bacfb118d49f26b60f8795ca3679406becccf 100644 --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -465,9 +465,16 @@ def err_embedded_directive : Error< def ext_embedded_directive : Extension< "embedding a directive within macro arguments has undefined behavior">, InGroup>; -def ext_missing_varargs_arg : Extension< - "must specify at least one argument for '...' parameter of variadic macro">, - InGroup; +def ext_c_missing_varargs_arg : Extension< + "passing no argument for the '...' parameter of a variadic macro is " + "a C23 extension">, InGroup; +def ext_cxx_missing_varargs_arg : Extension< + "passing no argument for the '...' parameter of a variadic macro is " + "a C++20 extension">, InGroup; +def warn_c17_compat_missing_varargs_arg : Warning< + "passing no argument for the '...' parameter of a variadic macro is " + "incompatible with C standards before C23">, + InGroup, DefaultIgnore; def warn_cxx17_compat_missing_varargs_arg : Warning< "passing no argument for the '...' parameter of a variadic macro is " "incompatible with C++ standards before C++20">, diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 816c3ff5f8b2aa5cb6c16118f7e6522f908423e9..46a44418a3153bc75df0ac7327bab65ac1528bc3 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -268,6 +268,8 @@ def err_expected_semi_after_namespace_name : Error< "expected ';' after namespace name">; def err_unexpected_namespace_attributes_alias : Error< "attributes cannot be specified on namespace alias">; +def err_unexpected_qualified_namespace_alias : Error< + "namespace alias must be a single identifier">; def err_unexpected_nested_namespace_attribute : Error< "attributes cannot be specified on a nested namespace definition">; def err_inline_namespace_alias : Error<"namespace alias cannot be inline">; @@ -1029,6 +1031,7 @@ def err_expected_lambda_body : Error<"expected body of lambda expression">; def warn_cxx98_compat_lambda : Warning< "lambda expressions are incompatible with C++98">, InGroup, DefaultIgnore; +def ext_lambda : ExtWarn<"lambdas are a C++11 extension">, InGroup; def err_lambda_decl_specifier_repeated : Error< "%select{'mutable'|'static'|'constexpr'|'consteval'}0 cannot " "appear multiple times in a lambda declarator">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index c54105507753eb4ab3c4c99542af02123ca6617c..df57f5e6ce11ba02faf873f677242a26a8a2f881 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -911,6 +911,22 @@ def warn_fortify_scanf_overflow : Warning< def err_function_start_invalid_type: Error< "argument must be a function">; +def err_ptrauth_disabled : + Error<"this target does not support pointer authentication">; +def err_ptrauth_invalid_key : + Error<"%0 does not identify a valid pointer authentication key for " + "the current target">; +def err_ptrauth_value_bad_type : + Error<"%select{signed value|extra discriminator|blended pointer|blended " + "integer}0 must have %select{pointer|integer|pointer or integer}1 " + "type; type here is %2">; +def warn_ptrauth_sign_null_pointer : + Warning<"signing a null pointer will yield a non-null pointer">, + InGroup; +def warn_ptrauth_auth_null_pointer : + Warning<"authenticating a null pointer will almost certainly trap">, + InGroup; + /// main() // static main() is not an error in C, just in C++. def warn_static_main : Warning<"'main' should not be declared static">, @@ -1732,8 +1748,8 @@ def err_type_defined_in_condition : Error< def err_type_defined_in_enum : Error< "%0 cannot be defined in an enumeration">; def ext_type_defined_in_offsetof : Extension< - "defining a type within '%select{__builtin_offsetof|offsetof}0' is a Clang " - "extension">, InGroup; + "defining a type within '%select{__builtin_offsetof|offsetof}0' is a C23 " + "extension">, InGroup; def note_pure_virtual_function : Note< "unimplemented pure virtual method %0 in %1">; @@ -6448,9 +6464,6 @@ def ext_c99_flexible_array_member : Extension< def err_flexible_array_virtual_base : Error< "flexible array member %0 not allowed in " "%select{struct|interface|union|class|enum}1 which has a virtual base class">; -def err_flexible_array_empty_aggregate : Error< - "flexible array member %0 not allowed in otherwise empty " - "%select{struct|interface|union|class|enum}1">; def err_flexible_array_has_nontrivial_dtor : Error< "flexible array member %0 of type %1 with non-trivial destruction">; def ext_flexible_array_in_struct : Extension< @@ -6465,8 +6478,6 @@ def ext_flexible_array_empty_aggregate_ms : Extension< "flexible array member %0 in otherwise empty " "%select{struct|interface|union|class|enum}1 is a Microsoft extension">, InGroup; -def err_flexible_array_union : Error< - "flexible array member %0 in a union is not allowed">; def ext_flexible_array_union_ms : Extension< "flexible array member %0 in a union is a Microsoft extension">, InGroup; @@ -6503,12 +6514,18 @@ def err_flexible_array_count_not_in_same_struct : Error< "'counted_by' field %0 isn't within the same struct as the flexible array">; def err_counted_by_attr_not_on_flexible_array_member : Error< "'counted_by' only applies to C99 flexible array members">; -def err_counted_by_attr_refers_to_flexible_array : Error< - "'counted_by' cannot refer to the flexible array %0">; +def err_counted_by_attr_refer_to_itself : Error< + "'counted_by' cannot refer to the flexible array member %0">; def err_counted_by_must_be_in_structure : Error< "field %0 in 'counted_by' not inside structure">; -def err_flexible_array_counted_by_attr_field_not_integer : Error< - "field %0 in 'counted_by' must be a non-boolean integer type">; +def err_counted_by_attr_argument_not_integer : Error< + "'counted_by' requires a non-boolean integer type argument">; +def err_counted_by_attr_only_support_simple_decl_reference : Error< + "'counted_by' argument must be a simple declaration reference">; +def err_counted_by_attr_in_union : Error< + "'counted_by' cannot be applied to a union member">; +def err_counted_by_attr_refer_to_union : Error< + "'counted_by' argument cannot refer to a union member">; def note_flexible_array_counted_by_attr_field : Note< "field %0 declared here">; @@ -9036,7 +9053,7 @@ def warn_bad_function_cast : Warning< InGroup, DefaultIgnore; def warn_cast_function_type : Warning< "cast %diff{from $ to $ |}0,1converts to incompatible function type">, - InGroup, DefaultIgnore; + InGroup, DefaultIgnore; def warn_cast_function_type_strict : Warning, InGroup, DefaultIgnore; def err_cast_pointer_to_non_pointer_int : Error< @@ -9804,6 +9821,9 @@ def warn_format_conversion_argument_type_mismatch : Warning< def warn_format_conversion_argument_type_mismatch_pedantic : Extension< warn_format_conversion_argument_type_mismatch.Summary>, InGroup; +def warn_format_conversion_argument_type_mismatch_signedness : Warning< + warn_format_conversion_argument_type_mismatch.Summary>, + InGroup, DefaultIgnore; def warn_format_conversion_argument_type_mismatch_confusion : Warning< warn_format_conversion_argument_type_mismatch.Summary>, InGroup, DefaultIgnore; @@ -11516,8 +11536,6 @@ def err_module_not_defined : Error< def err_module_redeclaration : Error< "translation unit contains multiple module declarations">; def note_prev_module_declaration : Note<"previous module declaration is here">; -def err_module_declaration_missing : Error< - "missing 'export module' declaration in module interface unit">; def err_module_declaration_missing_after_global_module_introducer : Error< "missing 'module' declaration at end of global module fragment " "introduced here">; @@ -12000,13 +12018,14 @@ def err_builtin_launder_invalid_arg : Error< "'__builtin_launder' is not allowed">; def err_builtin_invalid_arg_type: Error < - "%ordinal0 argument must be a " - "%select{vector, integer or floating point type|matrix|" - "pointer to a valid matrix element type|" - "signed integer or floating point type|vector type|" - "floating point type|" - "vector of integers|" - "type of unsigned integer}1 (was %2)">; + "%ordinal0 argument must be " + "%select{a vector, integer or floating point type|a matrix|" + "a pointer to a valid matrix element type|" + "a signed integer or floating point type|a vector type|" + "a floating point type|" + "a vector of integers|" + "an unsigned integer|" + "an 'int'}1 (was %2)">; def err_builtin_matrix_disabled: Error< "matrix types extension is disabled. Pass -fenable-matrix to enable it">; diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def index 5fad5fc3623cb630da629ba095cf613a16d455ee..fe4d1c4afcca6538ecec88e77fc08970dc9d8d5c 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -94,6 +94,7 @@ EXTENSION(define_target_os_macros, FEATURE(enumerator_attributes, true) FEATURE(nullability, true) FEATURE(nullability_on_arrays, true) +FEATURE(nullability_on_classes, true) FEATURE(nullability_nullable_result, true) FEATURE(memory_sanitizer, LangOpts.Sanitize.hasOneOf(SanitizerKind::Memory | @@ -101,7 +102,11 @@ FEATURE(memory_sanitizer, FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread)) FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow)) FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo)) -FEATURE(swiftasynccc, +FEATURE(ptrauth_intrinsics, LangOpts.PointerAuthIntrinsics) +EXTENSION(swiftcc, + PP.getTargetInfo().checkCallingConvention(CC_Swift) == + clang::TargetInfo::CCCR_OK) +EXTENSION(swiftasynccc, PP.getTargetInfo().checkCallingConvention(CC_SwiftAsync) == clang::TargetInfo::CCCR_OK) FEATURE(pragma_stdc_cx_limited_range, true) @@ -257,6 +262,7 @@ EXTENSION(cxx_defaulted_functions, LangOpts.CPlusPlus) EXTENSION(cxx_deleted_functions, LangOpts.CPlusPlus) EXTENSION(cxx_explicit_conversions, LangOpts.CPlusPlus) EXTENSION(cxx_inline_namespaces, LangOpts.CPlusPlus) +EXTENSION(cxx_lambdas, LangOpts.CPlusPlus) EXTENSION(cxx_local_type_template_args, LangOpts.CPlusPlus) EXTENSION(cxx_nonstatic_member_init, LangOpts.CPlusPlus) EXTENSION(cxx_override_control, LangOpts.CPlusPlus) diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 472fd9f093a718a42ba6984308e41f4db255f27c..8ef6700ecdc78eca7ec8a245d37d5d49122dd0d6 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -161,6 +161,8 @@ LANGOPT(DllExportInlines , 1, 1, "dllexported classes dllexport inline methods" LANGOPT(RelaxedTemplateTemplateArgs, 1, 0, "C++17 relaxed matching of template template arguments") LANGOPT(ExperimentalLibrary, 1, 0, "enable unstable and experimental library features") +LANGOPT(PointerAuthIntrinsics, 1, 0, "pointer authentication intrinsics") + LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes") COMPATIBLE_LANGOPT(RecoveryAST, 1, 1, "Preserve expressions in AST when encountering errors") diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 862952d336ef3176fb6c814de78a376baa752f3e..24b109e32cdd3e95a0000411779374228a1e8477 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -396,7 +396,38 @@ public: IncompleteOnly = 3, }; - enum ComplexRangeKind { CX_Full, CX_Limited, CX_Fortran, CX_None }; + /// Controls the various implementations for complex multiplication and + // division. + enum ComplexRangeKind { + /// Implementation of complex division and multiplication using a 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. This is the default value. + CX_Full, + + /// Implementation of complex division offering an improved handling + /// for overflow in intermediate calculations with no special handling for + /// NaN and infinite values. + CX_Improved, + + /// Implementation of complex division using algebraic formulas at + /// higher precision. Overflow is handled. Non-finite values are handled in + /// some cases. If the target hardware does not have native support for a + /// higher precision data type, an implementation for the complex operation + /// will be used to provide improved guards against intermediate overflow, + /// but overflow and underflow may still occur in some cases. NaN and + /// infinite values are not handled. + CX_Promoted, + + /// Implementation of complex division and multiplication using + /// algebraic formulas at source precision. No special handling to avoid + /// overflow. NaN and infinite values are not handled. + CX_Basic, + + /// No range rule is enabled. + CX_None + }; // Define simple language options (with no accessors). #define LANGOPT(Name, Bits, Default, Description) unsigned Name : Bits; @@ -560,11 +591,6 @@ public: return getCompilingModule() != CMK_None; } - /// Are we compiling a standard c++ module interface? - bool isCompilingModuleInterface() const { - return getCompilingModule() == CMK_ModuleInterface; - } - /// Are we compiling a module implementation? bool isCompilingModuleImplementation() const { return !isCompilingModule() && !ModuleName.empty(); @@ -993,8 +1019,8 @@ enum TranslationUnitKind { /// not complete. TU_Prefix, - /// The translation unit is a module. - TU_Module, + /// The translation unit is a clang module. + TU_ClangModule, /// The translation unit is a is a complete translation unit that we might /// incrementally extend later. diff --git a/clang/include/clang/Basic/LangStandard.h b/clang/include/clang/Basic/LangStandard.h index bc49669a82ad2db3a5718bc07fb99b578eacbc03..8e25afc833661c42ab94f1d3426f25455929215c 100644 --- a/clang/include/clang/Basic/LangStandard.h +++ b/clang/include/clang/Basic/LangStandard.h @@ -26,8 +26,9 @@ enum class Language : uint8_t { /// Assembly: we accept this only so that we can preprocess it. Asm, - /// LLVM IR: we accept this so that we can run the optimizer on it, - /// and compile it to assembly or object code. + /// LLVM IR & CIR: we accept these so that we can run the optimizer on them, + /// and compile them to assembly or object code (or LLVM for CIR). + CIR, LLVM_IR, ///@{ Languages that the frontend can parse and compile. @@ -139,6 +140,7 @@ public: bool isOpenCL() const { return Flags & OpenCL; } static Kind getLangKind(StringRef Name); + static Kind getHLSLLangKind(StringRef Name); static const LangStandard &getLangStandardForKind(Kind K); static const LangStandard *getLangStandardForName(StringRef Name); }; diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h index 8586405825cfe01514754591f0855be2f5667c62..fb11e8212f8b68f235faa690aab875b56096c8f6 100644 --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -273,29 +273,30 @@ namespace clang { /// CallingConv - Specifies the calling convention that a function uses. enum CallingConv { - CC_C, // __attribute__((cdecl)) - CC_X86StdCall, // __attribute__((stdcall)) - CC_X86FastCall, // __attribute__((fastcall)) - CC_X86ThisCall, // __attribute__((thiscall)) - CC_X86VectorCall, // __attribute__((vectorcall)) - CC_X86Pascal, // __attribute__((pascal)) - CC_Win64, // __attribute__((ms_abi)) - CC_X86_64SysV, // __attribute__((sysv_abi)) - CC_X86RegCall, // __attribute__((regcall)) - CC_AAPCS, // __attribute__((pcs("aapcs"))) - CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp"))) - CC_IntelOclBicc, // __attribute__((intel_ocl_bicc)) - CC_SpirFunction, // default for OpenCL functions on SPIR target - CC_OpenCLKernel, // inferred for OpenCL kernels - CC_Swift, // __attribute__((swiftcall)) + CC_C, // __attribute__((cdecl)) + CC_X86StdCall, // __attribute__((stdcall)) + CC_X86FastCall, // __attribute__((fastcall)) + CC_X86ThisCall, // __attribute__((thiscall)) + CC_X86VectorCall, // __attribute__((vectorcall)) + CC_X86Pascal, // __attribute__((pascal)) + CC_Win64, // __attribute__((ms_abi)) + CC_X86_64SysV, // __attribute__((sysv_abi)) + CC_X86RegCall, // __attribute__((regcall)) + CC_AAPCS, // __attribute__((pcs("aapcs"))) + CC_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp"))) + CC_IntelOclBicc, // __attribute__((intel_ocl_bicc)) + CC_SpirFunction, // default for OpenCL functions on SPIR target + CC_OpenCLKernel, // inferred for OpenCL kernels + CC_Swift, // __attribute__((swiftcall)) CC_SwiftAsync, // __attribute__((swiftasynccall)) - CC_PreserveMost, // __attribute__((preserve_most)) - CC_PreserveAll, // __attribute__((preserve_all)) + CC_PreserveMost, // __attribute__((preserve_most)) + CC_PreserveAll, // __attribute__((preserve_all)) CC_AArch64VectorCall, // __attribute__((aarch64_vector_pcs)) - CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs)) - CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel)) - CC_M68kRTD, // __attribute__((m68k_rtd)) - CC_PreserveNone, // __attribute__((preserve_none)) + CC_AArch64SVEPCS, // __attribute__((aarch64_sve_pcs)) + CC_AMDGPUKernelCall, // __attribute__((amdgpu_kernel)) + CC_M68kRTD, // __attribute__((m68k_rtd)) + CC_PreserveNone, // __attribute__((preserve_none)) + CC_RISCVVectorCall, // __attribute__((riscv_vector_cc)) }; /// Checks whether the given calling convention supports variadic diff --git a/clang/include/clang/Basic/SyncScope.h b/clang/include/clang/Basic/SyncScope.h index bc7ec7b5cf777ef4556678445dc44fed078dcfb5..45beff41afa11d3286afad7b2336567b4aa72c8a 100644 --- a/clang/include/clang/Basic/SyncScope.h +++ b/clang/include/clang/Basic/SyncScope.h @@ -252,8 +252,7 @@ public: } bool isValid(unsigned S) const override { - return S >= static_cast(System) && - S <= static_cast(Last); + return S <= static_cast(Last); } ArrayRef getRuntimeValues() const override { diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 7682f84e491c7bc15d07c2e399a80769a9740916..e1ef7454f01669c4ecff7f1998275a0b2512ed71 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -24,6 +24,7 @@ #include "clang/Basic/TargetOptions.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" +#include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallSet.h" @@ -266,6 +267,9 @@ protected: LLVM_PREFERRED_TYPE(bool) unsigned AllowAMDGPUUnsafeFPAtomics : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned HasUnalignedAccess : 1; + unsigned ARMCDECoprocMask : 8; unsigned MaxOpenCLWorkGroupSize; @@ -858,6 +862,18 @@ public: return PointerWidth; } + /// Return true iff unaligned accesses are a single instruction (rather than + /// a synthesized sequence). + bool hasUnalignedAccess() const { return HasUnalignedAccess; } + + /// Return true iff unaligned accesses are cheap. This affects placement and + /// size of bitfield loads/stores. (Not the ABI-mandated placement of + /// the bitfields themselves.) + bool hasCheapUnalignedBitFieldAccess() const { + // Simply forward to the unaligned access getter. + return hasUnalignedAccess(); + } + /// \brief Returns the default value of the __USER_LABEL_PREFIX__ macro, /// which is the prefix given to user symbols by default. /// @@ -1571,6 +1587,11 @@ public: return getAddressSpaceMap()[(unsigned)AS]; } + /// Determine whether the given pointer-authentication key is valid. + /// + /// The value has been coerced to type 'int'. + virtual bool validatePointerAuthKey(const llvm::APSInt &value) const; + /// Map from the address space field in builtin description strings to the /// language address space. virtual LangAS getOpenCLBuiltinAddressSpace(unsigned AS) const { diff --git a/clang/include/clang/Basic/TypeNodes.td b/clang/include/clang/Basic/TypeNodes.td index 6419762417371b9fd2c8dd4ed406de4ecad867a8..fee49cf4326dfca96d040f0a369d72b5a1f0a506 100644 --- a/clang/include/clang/Basic/TypeNodes.td +++ b/clang/include/clang/Basic/TypeNodes.td @@ -64,6 +64,7 @@ def ConstantArrayType : TypeNode; def IncompleteArrayType : TypeNode; def VariableArrayType : TypeNode; def DependentSizedArrayType : TypeNode, AlwaysDependent; +def ArrayParameterType : TypeNode; def DependentSizedExtVectorType : TypeNode, AlwaysDependent; def DependentAddressSpaceType : TypeNode, AlwaysDependent; def VectorType : TypeNode; @@ -108,6 +109,8 @@ def ObjCTypeParamType : TypeNode, NeverCanonical; def ObjCObjectType : TypeNode; def ObjCInterfaceType : TypeNode, LeafType; def ObjCObjectPointerType : TypeNode; +def BoundsAttributedType : TypeNode; +def CountAttributedType : TypeNode, NeverCanonical; def PipeType : TypeNode; def AtomicType : TypeNode; def BitIntType : TypeNode; diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index c4cab360bab3bb3b31b117eb8ce2db5644b653fa..2ffc52bcb7ad3b74b6cbf54ba2d45ae1682f83f9 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -28,8 +28,8 @@ #include "llvm/Option/ArgList.h" #include "llvm/Support/StringSaver.h" -#include #include +#include #include #include @@ -615,6 +615,16 @@ public: // FIXME: This should be in CompilationInfo. std::string GetProgramPath(StringRef Name, const ToolChain &TC) const; + /// Lookup the path to the Standard library module manifest. + /// + /// \param C - The compilation. + /// \param TC - The tool chain for additional information on + /// directories to search. + // + // FIXME: This should be in CompilationInfo. + std::string GetStdModuleManifestPath(const Compilation &C, + const ToolChain &TC) const; + /// HandleAutocompletions - Handle --autocomplete by searching and printing /// possible flags, descriptions, and its arguments. void HandleAutocompletions(StringRef PassedFlags) const; @@ -839,6 +849,13 @@ llvm::Error expandResponseFiles(SmallVectorImpl &Args, bool ClangCLMode, llvm::BumpPtrAllocator &Alloc, llvm::vfs::FileSystem *FS = nullptr); +/// Apply a space separated list of edits to the input argument lists. +/// See applyOneOverrideOption. +void applyOverrideOptions(SmallVectorImpl &Args, + const char *OverrideOpts, + llvm::StringSet<> &SavedStrings, + raw_ostream *OS = nullptr); + } // end namespace driver } // end namespace clang diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index aca8c9b0d5487a8fe8b95761849262639a6df314..f5289fb00c895e676c43e20169ff2dffef359ab0 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1046,30 +1046,29 @@ defm offload_uniform_block : BoolFOption<"offload-uniform-block", NegFlag, BothFlags<[], [ClangOption], " that kernels are launched with uniform block sizes (default true for CUDA/HIP and false otherwise)">>; -def fcx_limited_range : Joined<["-"], "fcx-limited-range">, - Group, Visibility<[ClangOption, CC1Option]>, - HelpText<"Basic algebraic expansions of complex arithmetic operations " - "involving are enabled.">; - -def fno_cx_limited_range : Joined<["-"], "fno-cx-limited-range">, - Group, Visibility<[ClangOption, CC1Option]>, - HelpText<"Basic algebraic expansions of complex arithmetic operations " - "involving are disabled.">; - -def fcx_fortran_rules : Joined<["-"], "fcx-fortran-rules">, - Group, Visibility<[ClangOption, CC1Option]>, - HelpText<"Range reduction is enabled for complex arithmetic operations.">; - -def fno_cx_fortran_rules : Joined<["-"], "fno-cx-fortran-rules">, - Group, Visibility<[ClangOption, CC1Option]>, - HelpText<"Range reduction is disabled for complex arithmetic operations.">; +def fcomplex_arithmetic_EQ : Joined<["-"], "fcomplex-arithmetic=">, Group, + Visibility<[ClangOption, CC1Option]>, + Values<"full,improved,promoted,basic">, NormalizedValuesScope<"LangOptions">, + NormalizedValues<["CX_Full", "CX_Improved", "CX_Promoted", "CX_Basic"]>; def complex_range_EQ : Joined<["-"], "complex-range=">, Group, Visibility<[CC1Option]>, - Values<"full,limited,fortran">, NormalizedValuesScope<"LangOptions">, - NormalizedValues<["CX_Full", "CX_Limited", "CX_Fortran"]>, + Values<"full,improved,promoted,basic">, NormalizedValuesScope<"LangOptions">, + NormalizedValues<["CX_Full", "CX_Improved", "CX_Promoted", "CX_Basic"]>, MarshallingInfoEnum, "CX_Full">; +defm cx_limited_range: BoolOptionWithoutMarshalling<"f", "cx-limited-range", + PosFlag, + NegFlag>; + +defm cx_fortran_rules: BoolOptionWithoutMarshalling<"f", "cx-fortran-rules", + PosFlag, + NegFlag>; + // OpenCL-only Options def cl_opt_disable : Flag<["-"], "cl-opt-disable">, Group, Visibility<[ClangOption, CC1Option]>, @@ -3609,12 +3608,36 @@ def fpass_plugin_EQ : Joined<["-"], "fpass-plugin=">, MetaVarName<"">, HelpText<"Load pass plugin from a dynamic shared object file (only with new pass manager).">, MarshallingInfoStringVector>; +defm tocdata : BoolOption<"m","tocdata", + CodeGenOpts<"AllTocData">, DefaultFalse, + PosFlag, + NegFlag, + BothFlags<[TargetSpecific], [ClangOption, CLOption]>>, Group; +def mtocdata_EQ : CommaJoined<["-"], "mtocdata=">, + Visibility<[ClangOption, CC1Option]>, + Flags<[TargetSpecific]>, Group, + HelpText<"Specifies a list of variables to which the TOC data transformation" + "will be applied.">, + MarshallingInfoStringVector>; +def mno_tocdata_EQ : CommaJoined<["-"], "mno-tocdata=">, + Visibility<[ClangOption, CC1Option]>, + Flags<[TargetSpecific]>, Group, + HelpText<"Specifies a list of variables to be exempt from the TOC data" + "transformation.">, + MarshallingInfoStringVector>; defm preserve_as_comments : BoolFOption<"preserve-as-comments", CodeGenOpts<"PreserveAsmComments">, DefaultTrue, NegFlag, PosFlag>; def framework : Separate<["-"], "framework">, Flags<[LinkerInput]>; +def reexport_framework : Separate<["-"], "reexport_framework">, Flags<[LinkerInput]>; +def reexport_l : Joined<["-"], "reexport-l">, Flags<[LinkerInput]>; +def reexport_library : JoinedOrSeparate<["-"], "reexport_library">, Flags<[LinkerInput]>; def frandom_seed_EQ : Joined<["-"], "frandom-seed=">, Group; def freg_struct_return : Flag<["-"], "freg-struct-return">, Group, Visibility<[ClangOption, CC1Option]>, @@ -4085,6 +4108,10 @@ defm strict_return : BoolFOption<"strict-return", " of a non-void function as unreachable">, PosFlag>; +let Flags = [TargetSpecific] in { +defm ptrauth_intrinsics : OptInCC1FFlag<"ptrauth-intrinsics", "Enable pointer authentication intrinsics">; +} + def fenable_matrix : Flag<["-"], "fenable-matrix">, Group, Visibility<[ClangOption, CC1Option]>, HelpText<"Enable matrix data type and related builtin functions">, @@ -4483,6 +4510,9 @@ def mwindows : Joined<["-"], "mwindows">, Group; def mdll : Joined<["-"], "mdll">, Group; def municode : Joined<["-"], "municode">, Group; def mthreads : Joined<["-"], "mthreads">, Group; +def marm64x : Joined<["-"], "marm64x">, Group, + Visibility<[ClangOption, CLOption]>, + HelpText<"Link as a hybrid ARM64X image">; def mguard_EQ : Joined<["-"], "mguard=">, Group, HelpText<"Enable or disable Control Flow Guard checks and guard tables emission">, Values<"none,cf,cf-nochecks">; @@ -4675,21 +4705,17 @@ def mrvv_vector_bits_EQ : Joined<["-"], "mrvv-vector-bits=">, Group, " (RISC-V only)")>; def munaligned_access : Flag<["-"], "munaligned-access">, Group, - HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64/LoongArch/RISC-V only)">; + HelpText<"Allow memory accesses to be unaligned (AArch32/MIPSr6 only)">; def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group, - HelpText<"Force all memory accesses to be aligned (AArch32/AArch64/LoongArch/RISC-V only)">; + HelpText<"Force all memory accesses to be aligned (AArch32/MIPSr6 only)">; def munaligned_symbols : Flag<["-"], "munaligned-symbols">, Group, HelpText<"Expect external char-aligned symbols to be without ABI alignment (SystemZ only)">; def mno_unaligned_symbols : Flag<["-"], "mno-unaligned-symbols">, Group, HelpText<"Expect external char-aligned symbols to be without ABI alignment (SystemZ only)">; -} // let Flags = [TargetSpecific] -def mstrict_align : Flag<["-"], "mstrict-align">, Alias, - Flags<[HelpHidden]>, Visibility<[ClangOption, CC1Option]>, - HelpText<"Force all memory accesses to be aligned (same as mno-unaligned-access)">; -def mno_strict_align : Flag<["-"], "mno-strict-align">, Alias, - Flags<[HelpHidden]>, Visibility<[ClangOption, CC1Option]>, - HelpText<"Allow memory accesses to be unaligned (same as munaligned-access)">; -let Flags = [TargetSpecific] in { +def mstrict_align : Flag<["-"], "mstrict-align">, + HelpText<"Force all memory accesses to be aligned (AArch64/LoongArch/RISC-V only)">; +def mno_strict_align : Flag<["-"], "mno-strict-align">, + HelpText<"Allow memory accesses to be unaligned (AArch64/LoongArch/RISC-V only)">; def mno_thumb : Flag<["-"], "mno-thumb">, Group; def mrestrict_it: Flag<["-"], "mrestrict-it">, Group, HelpText<"Disallow generation of complex IT blocks. It is off by default.">; @@ -5374,6 +5400,9 @@ def print_resource_dir : Flag<["-", "--"], "print-resource-dir">, def print_search_dirs : Flag<["-", "--"], "print-search-dirs">, HelpText<"Print the paths used for finding libraries and programs">, Visibility<[ClangOption, CLOption]>; +def print_std_module_manifest_path : Flag<["-", "--"], "print-library-module-manifest-path">, + HelpText<"Print the path for the C++ Standard library module manifest">, + Visibility<[ClangOption, CLOption]>; def print_targets : Flag<["-", "--"], "print-targets">, HelpText<"Print the registered targets">, Visibility<[ClangOption, CLOption]>; @@ -6413,11 +6442,6 @@ def flang_deprecated_no_hlfir : Flag<["-"], "flang-deprecated-no-hlfir">, Flags<[HelpHidden]>, Visibility<[FlangOption, FC1Option]>, HelpText<"Do not use HLFIR lowering (deprecated)">; -def flang_experimental_polymorphism : Flag<["-"], "flang-experimental-polymorphism">, - Flags<[HelpHidden]>, Visibility<[FlangOption, FC1Option]>, - HelpText<"Enable Fortran 2003 polymorphism (experimental)">; - - //===----------------------------------------------------------------------===// // FLangOption + CoreOption + NoXarchOption //===----------------------------------------------------------------------===// @@ -6666,6 +6690,9 @@ def analyzer_opt_analyze_headers : Flag<["-"], "analyzer-opt-analyze-headers">, def analyzer_display_progress : Flag<["-"], "analyzer-display-progress">, HelpText<"Emit verbose output about the analyzer's progress">, MarshallingInfoFlag>; +def analyzer_note_analysis_entry_points : Flag<["-"], "analyzer-note-analysis-entry-points">, + HelpText<"Add a note for each bug report to denote their analysis entry points">, + MarshallingInfoFlag>; def analyze_function : Separate<["-"], "analyze-function">, HelpText<"Run analysis on specific function (for C++ include parameters in name)">, MarshallingInfoString>; @@ -8286,6 +8313,7 @@ def _SLASH_Fi : CLCompileJoined<"Fi">, def _SLASH_Fo : CLCompileJoined<"Fo">, HelpText<"Set output object file (with /c)">, MetaVarName<"">; +def _SLASH_Fo_COLON : CLCompileJoined<"Fo:">, Alias<_SLASH_Fo>; def _SLASH_guard : CLJoined<"guard:">, HelpText<"Enable Control Flow Guard with /guard:cf, or only the table with /guard:cf,nochecks. " "Enable EH Continuation Guard with /guard:ehcont">; @@ -8557,6 +8585,11 @@ def dxc_entrypoint : Option<["--", "/", "-"], "E", KIND_JOINED_OR_SEPARATE>, Group, Visibility<[DXCOption]>, HelpText<"Entry point name">; +def dxc_hlsl_version : Option<["/", "-"], "HV", KIND_JOINED_OR_SEPARATE>, + Group, + Visibility<[DXCOption]>, + HelpText<"HLSL Version">, + Values<"2016, 2017, 2018, 2021, 202x">; def dxc_validator_path_EQ : Joined<["--"], "dxv-path=">, Group, HelpText<"DXIL validator installation path">; def dxc_disable_validation : DXCFlag<"Vd">, diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index fbe2e8fe8e88d850fa1bb4d3240f45f43d20a285..a4f9cad98aa8b1e40d609d001d483e29f2b00077 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -580,7 +580,7 @@ public: // Return the DWARF version to emit, in the absence of arguments // to the contrary. - virtual unsigned GetDefaultDwarfVersion() const; + virtual unsigned GetDefaultDwarfVersion() const { return 5; } // Some toolchains may have different restrictions on the DWARF version and // may need to adjust it. E.g. NVPTX may need to enforce DWARF2 even when host diff --git a/clang/include/clang/Driver/Types.def b/clang/include/clang/Driver/Types.def index f72c27e1ee701931484792524a85f74050087e98..0e0cae5fb7068dec6561eb376fa37cd5db83316e 100644 --- a/clang/include/clang/Driver/Types.def +++ b/clang/include/clang/Driver/Types.def @@ -90,6 +90,7 @@ TYPE("ir", LLVM_BC, INVALID, "bc", phases TYPE("lto-ir", LTO_IR, INVALID, "s", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("lto-bc", LTO_BC, INVALID, "o", phases::Compile, phases::Backend, phases::Assemble, phases::Link) +TYPE("cir", CIR, INVALID, "cir", phases::Compile, phases::Backend, phases::Assemble, phases::Link) // Misc. TYPE("ast", AST, INVALID, "ast", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("ifs", IFS, INVALID, "ifs", phases::IfsMerge) diff --git a/clang/include/clang/ExtractAPI/DeclarationFragments.h b/clang/include/clang/ExtractAPI/DeclarationFragments.h index b85a5d21d61217e2404c7c54bde6ed5f5d2f34e2..8a3a22d9a594c6108a6e4ab73912d21ff99568eb 100644 --- a/clang/include/clang/ExtractAPI/DeclarationFragments.h +++ b/clang/include/clang/ExtractAPI/DeclarationFragments.h @@ -27,8 +27,6 @@ #include "clang/AST/TypeLoc.h" #include "clang/Basic/Specifiers.h" #include "clang/Lex/MacroInfo.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" #include namespace clang { @@ -315,13 +313,9 @@ public: static DeclarationFragments getFragmentsForTemplateParameters(ArrayRef); - static std::string - getNameForTemplateArgument(const ArrayRef, std::string); - - static DeclarationFragments - getFragmentsForTemplateArguments(const ArrayRef, - ASTContext &, - const std::optional>); + static DeclarationFragments getFragmentsForTemplateArguments( + const ArrayRef, ASTContext &, + const std::optional>); static DeclarationFragments getFragmentsForConcept(const ConceptDecl *); @@ -430,12 +424,7 @@ DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) { if (isa(Function) && dyn_cast(Function)->getDescribedFunctionTemplate() && StringRef(ReturnType.begin()->Spelling).starts_with("type-parameter")) { - std::string ProperArgName = - getNameForTemplateArgument(dyn_cast(Function) - ->getDescribedFunctionTemplate() - ->getTemplateParameters() - ->asArray(), - ReturnType.begin()->Spelling); + std::string ProperArgName = Function->getReturnType().getAsString(); ReturnType.begin()->Spelling.swap(ProperArgName); } ReturnType.append(std::move(After)); diff --git a/clang/include/clang/Format/.clang-format b/clang/include/clang/Format/.clang-format index f95602cab0f7fcdf5d34c485d52b65993dbb83d9..d7331b3c8cf02ef7944e83a4280476627e33b31d 100644 --- a/clang/include/clang/Format/.clang-format +++ b/clang/include/clang/Format/.clang-format @@ -1,6 +1 @@ -BasedOnStyle: LLVM -InsertBraces: true -InsertNewlineAtEOF: true -LineEnding: LF -RemoveBracesLLVM: true -RemoveParentheses: ReturnStatement +BasedOnStyle: clang-format diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 590297fd89a398a8284f038d7a06c3c071c40ac4..48f5fb441575704ece96966e57fb988649e4ff72 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -414,6 +414,21 @@ struct FormatStyle { /// \version 17 ShortCaseStatementsAlignmentStyle AlignConsecutiveShortCaseStatements; + /// Style of aligning consecutive TableGen DAGArg operator colons. + /// If enabled, align the colon inside DAGArg which have line break inside. + /// This works only when TableGenBreakInsideDAGArg is BreakElements or + /// BreakAll and the DAGArg is not excepted by + /// TableGenBreakingDAGArgOperators's effect. + /// \code + /// let dagarg = (ins + /// a :$src1, + /// aa :$src2, + /// aaa:$src3 + /// ) + /// \endcode + /// \version 19 + AlignConsecutiveStyle AlignConsecutiveTableGenBreakingDAGArgColons; + /// Style of aligning consecutive TableGen cond operator colons. /// Align the colons of cases inside !cond operators. /// \code @@ -2208,6 +2223,20 @@ struct FormatStyle { /// \version 5 BreakConstructorInitializersStyle BreakConstructorInitializers; + /// If ``true``, clang-format will always break before function definition + /// parameters. + /// \code + /// true: + /// void functionDefinition( + /// int A, int B) {} + /// + /// false: + /// void functionDefinition(int A, int B) {} + /// + /// \endcode + /// \version 19 + bool BreakFunctionDefinitionParameters; + /// Break after each annotation on a field in Java files. /// \code{.java} /// true: false: @@ -4728,6 +4757,60 @@ struct FormatStyle { /// \version 8 std::vector StatementMacros; + /// Works only when TableGenBreakInsideDAGArg is not DontBreak. + /// The string list needs to consist of identifiers in TableGen. + /// If any identifier is specified, this limits the line breaks by + /// TableGenBreakInsideDAGArg option only on DAGArg values beginning with + /// the specified identifiers. + /// + /// For example the configuration, + /// \code{.yaml} + /// TableGenBreakInsideDAGArg: BreakAll + /// TableGenBreakingDAGArgOperators: ['ins', 'outs'] + /// \endcode + /// + /// makes the line break only occurs inside DAGArgs beginning with the + /// specified identifiers 'ins' and 'outs'. + /// + /// \code + /// let DAGArgIns = (ins + /// i32:$src1, + /// i32:$src2 + /// ); + /// let DAGArgOtherID = (other i32:$other1, i32:$other2); + /// let DAGArgBang = (!cast("Some") i32:$src1, i32:$src2) + /// \endcode + /// \version 19 + std::vector TableGenBreakingDAGArgOperators; + + /// Different ways to control the format inside TableGen DAGArg. + enum DAGArgStyle : int8_t { + /// Never break inside DAGArg. + /// \code + /// let DAGArgIns = (ins i32:$src1, i32:$src2); + /// \endcode + DAS_DontBreak, + /// Break inside DAGArg after each list element but for the last. + /// This aligns to the first element. + /// \code + /// let DAGArgIns = (ins i32:$src1, + /// i32:$src2); + /// \endcode + DAS_BreakElements, + /// Break inside DAGArg after the operator and the all elements. + /// \code + /// let DAGArgIns = (ins + /// i32:$src1, + /// i32:$src2 + /// ); + /// \endcode + DAS_BreakAll, + }; + + /// The styles of the line break inside the DAGArg in TableGen. + /// \version 19 + DAGArgStyle TableGenBreakInsideDAGArg; + /// The number of columns used for tab stops. /// \version 3.7 unsigned TabWidth; @@ -4825,6 +4908,8 @@ struct FormatStyle { AlignConsecutiveMacros == R.AlignConsecutiveMacros && AlignConsecutiveShortCaseStatements == R.AlignConsecutiveShortCaseStatements && + AlignConsecutiveTableGenBreakingDAGArgColons == + R.AlignConsecutiveTableGenBreakingDAGArgColons && AlignConsecutiveTableGenCondOperatorColons == R.AlignConsecutiveTableGenCondOperatorColons && AlignConsecutiveTableGenDefinitionColons == @@ -4867,6 +4952,8 @@ struct FormatStyle { BreakBeforeInlineASMColon == R.BreakBeforeInlineASMColon && BreakBeforeTernaryOperators == R.BreakBeforeTernaryOperators && BreakConstructorInitializers == R.BreakConstructorInitializers && + BreakFunctionDefinitionParameters == + R.BreakFunctionDefinitionParameters && BreakInheritanceList == R.BreakInheritanceList && BreakStringLiterals == R.BreakStringLiterals && BreakTemplateDeclarations == R.BreakTemplateDeclarations && @@ -4980,9 +5067,12 @@ struct FormatStyle { SpacesInSquareBrackets == R.SpacesInSquareBrackets && Standard == R.Standard && StatementAttributeLikeMacros == R.StatementAttributeLikeMacros && - StatementMacros == R.StatementMacros && TabWidth == R.TabWidth && - TypeNames == R.TypeNames && TypenameMacros == R.TypenameMacros && - UseTab == R.UseTab && + StatementMacros == R.StatementMacros && + TableGenBreakingDAGArgOperators == + R.TableGenBreakingDAGArgOperators && + TableGenBreakInsideDAGArg == R.TableGenBreakInsideDAGArg && + TabWidth == R.TabWidth && TypeNames == R.TypeNames && + TypenameMacros == R.TypenameMacros && UseTab == R.UseTab && VerilogBreakBetweenInstancePorts == R.VerilogBreakBetweenInstancePorts && WhitespaceSensitiveMacros == R.WhitespaceSensitiveMacros; diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index cce91862ae3d03b210d5939ab17f29bb1f231f80..3464654284f199c73beeef8ea9d7858882e1173f 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -133,6 +133,24 @@ class CompilerInstance : public ModuleLoader { std::vector> DependencyCollectors; + /// Records the set of modules + class FailedModulesSet { + llvm::StringSet<> Failed; + + public: + bool hasAlreadyFailed(StringRef module) { return Failed.count(module) > 0; } + + void addFailed(StringRef module) { Failed.insert(module); } + }; + + /// The set of modules that failed to build. + /// + /// This pointer will be shared among all of the compiler instances created + /// to (re)build modules, so that once a module fails to build anywhere, + /// other instances will see that the module has failed and won't try to + /// build it again. + std::shared_ptr FailedModules; + /// The set of top-level modules that has already been built on the /// fly as part of this overall compilation action. std::map> BuiltModules; @@ -619,6 +637,24 @@ public: } /// @} + /// @name Failed modules set + /// @{ + + bool hasFailedModulesSet() const { return (bool)FailedModules; } + + void createFailedModulesSet() { + FailedModules = std::make_shared(); + } + + std::shared_ptr getFailedModulesSetPtr() const { + return FailedModules; + } + + void setFailedModulesSet(std::shared_ptr FMS) { + FailedModules = FMS; + } + + /// } /// @name Output Files /// @{ diff --git a/clang/include/clang/Frontend/FrontendActions.h b/clang/include/clang/Frontend/FrontendActions.h index 8441af2ee3e718603ac9dd2898dcee4b14b38d01..0518a8823a03ea94ca284aee9256bbb5f7295ac0 100644 --- a/clang/include/clang/Frontend/FrontendActions.h +++ b/clang/include/clang/Frontend/FrontendActions.h @@ -34,12 +34,18 @@ public: /// Preprocessor-based frontend action that also loads PCH files. class ReadPCHAndPreprocessAction : public FrontendAction { + llvm::unique_function AdjustCI; + void ExecuteAction() override; std::unique_ptr CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override; public: + ReadPCHAndPreprocessAction( + llvm::unique_function AdjustCI) + : AdjustCI(std::move(AdjustCI)) {} + bool usesPreprocessorOnly() const override { return false; } }; @@ -125,7 +131,7 @@ protected: StringRef InFile) override; TranslationUnitKind getTranslationUnitKind() override { - return TU_Module; + return TU_ClangModule; } bool hasASTFileSupport() const override { return false; } @@ -138,7 +144,9 @@ protected: std::unique_ptr CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override; - TranslationUnitKind getTranslationUnitKind() override { return TU_Module; } + TranslationUnitKind getTranslationUnitKind() override { + return TU_ClangModule; + } bool hasASTFileSupport() const override { return false; } }; @@ -159,6 +167,8 @@ protected: std::unique_ptr CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override; + TranslationUnitKind getTranslationUnitKind() override { return TU_Complete; } + std::unique_ptr CreateOutputFile(CompilerInstance &CI, StringRef InFile) override; }; @@ -317,11 +327,15 @@ protected: class GetDependenciesByModuleNameAction : public PreprocessOnlyAction { StringRef ModuleName; + llvm::unique_function AdjustCI; + void ExecuteAction() override; public: - GetDependenciesByModuleNameAction(StringRef ModuleName) - : ModuleName(ModuleName) {} + GetDependenciesByModuleNameAction( + StringRef ModuleName, + llvm::unique_function AdjustCI) + : ModuleName(ModuleName), AdjustCI(std::move(AdjustCI)) {} }; } // end namespace clang diff --git a/clang/include/clang/InstallAPI/Context.h b/clang/include/clang/InstallAPI/Context.h index bdb576d7d85fb6629f3aebc1d12cab2cf402105b..54e517544b8edf526097afd66347b9e55998c0f3 100644 --- a/clang/include/clang/InstallAPI/Context.h +++ b/clang/include/clang/InstallAPI/Context.h @@ -11,6 +11,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" +#include "clang/InstallAPI/DylibVerifier.h" #include "clang/InstallAPI/HeaderFile.h" #include "clang/InstallAPI/MachO.h" #include "llvm/ADT/DenseMap.h" @@ -45,6 +46,9 @@ struct InstallAPIContext { /// DiagnosticsEngine for all error reporting. DiagnosticsEngine *Diags = nullptr; + /// Verifier when binary dylib is passed as input. + std::unique_ptr Verifier = nullptr; + /// File Path of output location. llvm::StringRef OutputLoc{}; diff --git a/clang/include/clang/InstallAPI/DylibVerifier.h b/clang/include/clang/InstallAPI/DylibVerifier.h new file mode 100644 index 0000000000000000000000000000000000000000..22cdc234486cf330084c7c20629ac583036705f1 --- /dev/null +++ b/clang/include/clang/InstallAPI/DylibVerifier.h @@ -0,0 +1,178 @@ +//===- InstallAPI/DylibVerifier.h -------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INSTALLAPI_DYLIBVERIFIER_H +#define LLVM_CLANG_INSTALLAPI_DYLIBVERIFIER_H + +#include "clang/Basic/Diagnostic.h" +#include "clang/InstallAPI/MachO.h" + +namespace clang { +namespace installapi { +struct FrontendAttrs; + +/// A list of InstallAPI verification modes. +enum class VerificationMode { + Invalid, + ErrorsOnly, + ErrorsAndWarnings, + Pedantic, +}; + +/// Service responsible to tracking state of verification across the +/// lifetime of InstallAPI. +/// As declarations are collected during AST traversal, they are +/// compared as symbols against what is available in the binary dylib. +class DylibVerifier : llvm::MachO::RecordVisitor { +private: + struct SymbolContext; + struct DWARFContext; + +public: + enum class Result { NoVerify, Ignore, Valid, Invalid }; + struct VerifierContext { + // Current target being verified against the AST. + llvm::MachO::Target Target; + + // Target specific API from binary. + RecordsSlice *DylibSlice = nullptr; + + // Query state of verification after AST has been traversed. + Result FrontendState = Result::Ignore; + + // First error for AST traversal, which is tied to the target triple. + bool DiscoveredFirstError = false; + + // Determines what kind of banner to print a violation for. + bool PrintArch = false; + + // Engine for reporting violations. + DiagnosticsEngine *Diag = nullptr; + + // Handle diagnostics reporting for target level violations. + void emitDiag(llvm::function_ref Report, RecordLoc *Loc = nullptr); + + VerifierContext() = default; + VerifierContext(DiagnosticsEngine *Diag) : Diag(Diag) {} + }; + + DylibVerifier() = default; + + DylibVerifier(llvm::MachO::Records &&Dylib, DiagnosticsEngine *Diag, + VerificationMode Mode, bool Demangle, StringRef DSYMPath) + : Dylib(std::move(Dylib)), Mode(Mode), Demangle(Demangle), + DSYMPath(DSYMPath), Exports(std::make_unique()), + Ctx(VerifierContext{Diag}) {} + + Result verify(GlobalRecord *R, const FrontendAttrs *FA); + Result verify(ObjCInterfaceRecord *R, const FrontendAttrs *FA); + Result verify(ObjCIVarRecord *R, const FrontendAttrs *FA, + const StringRef SuperClass); + + // Scan through dylib slices and report any remaining missing exports. + Result verifyRemainingSymbols(); + + /// Initialize target for verification. + void setTarget(const Target &T); + + /// Release ownership over exports. + std::unique_ptr getExports() { return std::move(Exports); } + + /// Get result of verification. + Result getState() const { return Ctx.FrontendState; } + + /// Set different source managers to the same diagnostics engine. + void setSourceManager(SourceManager &SourceMgr) const { + if (!Ctx.Diag) + return; + Ctx.Diag->setSourceManager(&SourceMgr); + } + +private: + /// Determine whether to compare declaration to symbol in binary. + bool canVerify(); + + /// Shared implementation for verifying exported symbols. + Result verifyImpl(Record *R, SymbolContext &SymCtx); + + /// Check if declaration is marked as obsolete, they are + // expected to result in a symbol mismatch. + bool shouldIgnoreObsolete(const Record *R, SymbolContext &SymCtx, + const Record *DR); + + /// Compare the visibility declarations to the linkage of symbol found in + /// dylib. + Result compareVisibility(const Record *R, SymbolContext &SymCtx, + const Record *DR); + + /// An ObjCInterfaceRecord can represent up to three symbols. When verifying, + // account for this granularity. + bool compareObjCInterfaceSymbols(const Record *R, SymbolContext &SymCtx, + const ObjCInterfaceRecord *DR); + + /// Validate availability annotations against dylib. + Result compareAvailability(const Record *R, SymbolContext &SymCtx, + const Record *DR); + + /// Compare and validate matching symbol flags. + bool compareSymbolFlags(const Record *R, SymbolContext &SymCtx, + const Record *DR); + + /// Update result state on each call to `verify`. + void updateState(Result State); + + /// Add verified exported symbol. + void addSymbol(const Record *R, SymbolContext &SymCtx, + TargetList &&Targets = {}); + + /// Find matching dylib slice for target triple that is being parsed. + void assignSlice(const Target &T); + + /// Shared implementation for verifying exported symbols in dylib. + void visitSymbolInDylib(const Record &R, SymbolContext &SymCtx); + + void visitGlobal(const GlobalRecord &R) override; + void visitObjCInterface(const ObjCInterfaceRecord &R) override; + void visitObjCCategory(const ObjCCategoryRecord &R) override; + void visitObjCIVar(const ObjCIVarRecord &R, const StringRef Super); + + /// Gather annotations for symbol for error reporting. + std::string getAnnotatedName(const Record *R, SymbolContext &SymCtx, + bool ValidSourceLoc = true); + + /// Extract source location for symbol implementations. + /// As this is a relatively expensive operation, it is only used + /// when there is a violation to report and there is not a known declaration + /// in the interface. + void accumulateSrcLocForDylibSymbols(); + + // Symbols in dylib. + llvm::MachO::Records Dylib; + + // Controls what class of violations to report. + VerificationMode Mode = VerificationMode::Invalid; + + // Attempt to demangle when reporting violations. + bool Demangle = false; + + // File path to DSYM file. + StringRef DSYMPath; + + // Valid symbols in final text file. + std::unique_ptr Exports = std::make_unique(); + + // Track current state of verification while traversing AST. + VerifierContext Ctx; + + // Track DWARF provided source location for dylibs. + DWARFContext *DWARFCtx = nullptr; +}; + +} // namespace installapi +} // namespace clang +#endif // LLVM_CLANG_INSTALLAPI_DYLIBVERIFIER_H diff --git a/clang/include/clang/InstallAPI/Frontend.h b/clang/include/clang/InstallAPI/Frontend.h index 873cb50d60a5423da082a1aaaebed6abeaf3170a..5cccd891c58093ac540b5ac8af103b493f54871d 100644 --- a/clang/include/clang/InstallAPI/Frontend.h +++ b/clang/include/clang/InstallAPI/Frontend.h @@ -14,10 +14,10 @@ #define LLVM_CLANG_INSTALLAPI_FRONTEND_H #include "clang/AST/ASTConsumer.h" -#include "clang/AST/Availability.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendActions.h" #include "clang/InstallAPI/Context.h" +#include "clang/InstallAPI/DylibVerifier.h" #include "clang/InstallAPI/Visitor.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/MemoryBuffer.h" @@ -35,6 +35,8 @@ public: std::unique_ptr CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override { + Ctx.Diags->getClient()->BeginSourceFile(CI.getLangOpts()); + Ctx.Verifier->setSourceManager(CI.getSourceManager()); return std::make_unique( CI.getASTContext(), Ctx, CI.getSourceManager(), CI.getPreprocessor()); } diff --git a/clang/include/clang/InstallAPI/FrontendRecords.h b/clang/include/clang/InstallAPI/FrontendRecords.h index 333015b6a1136526126519be55568f1361771a81..59271e81e230c2f022e1bec0894e0529e3f3a0e2 100644 --- a/clang/include/clang/InstallAPI/FrontendRecords.h +++ b/clang/include/clang/InstallAPI/FrontendRecords.h @@ -11,6 +11,7 @@ #include "clang/AST/Availability.h" #include "clang/AST/DeclObjC.h" +#include "clang/InstallAPI/HeaderFile.h" #include "clang/InstallAPI/MachO.h" namespace clang { @@ -42,13 +43,13 @@ public: /// \param Flags The flags that describe attributes of the symbol. /// \param Inlined Whether declaration is inlined, only applicable to /// functions. - /// \return The non-owning pointer to added record in slice. - GlobalRecord *addGlobal(StringRef Name, RecordLinkage Linkage, - GlobalRecord::Kind GV, - const clang::AvailabilityInfo Avail, const Decl *D, - const HeaderType Access, - SymbolFlags Flags = SymbolFlags::None, - bool Inlined = false); + /// \return The non-owning pointer to added record in slice with it's frontend + /// attributes. + std::pair + addGlobal(StringRef Name, RecordLinkage Linkage, GlobalRecord::Kind GV, + const clang::AvailabilityInfo Avail, const Decl *D, + const HeaderType Access, SymbolFlags Flags = SymbolFlags::None, + bool Inlined = false); /// Add ObjC Class record with attributes from AST. /// @@ -59,11 +60,12 @@ public: /// \param D The pointer to the declaration from traversing AST. /// \param Access The intended access level of symbol. /// \param IsEHType Whether declaration has an exception attribute. - /// \return The non-owning pointer to added record in slice. - ObjCInterfaceRecord *addObjCInterface(StringRef Name, RecordLinkage Linkage, - const clang::AvailabilityInfo Avail, - const Decl *D, HeaderType Access, - bool IsEHType); + /// \return The non-owning pointer to added record in slice with it's frontend + /// attributes. + std::pair + addObjCInterface(StringRef Name, RecordLinkage Linkage, + const clang::AvailabilityInfo Avail, const Decl *D, + HeaderType Access, bool IsEHType); /// Add ObjC Category record with attributes from AST. /// @@ -74,11 +76,12 @@ public: /// to the active target triple. /// \param D The pointer to the declaration from traversing AST. /// \param Access The intended access level of symbol. - /// \return The non-owning pointer to added record in slice. - ObjCCategoryRecord *addObjCCategory(StringRef ClassToExtend, - StringRef CategoryName, - const clang::AvailabilityInfo Avail, - const Decl *D, HeaderType Access); + /// \return The non-owning pointer to added record in slice with it's frontend + /// attributes. + std::pair + addObjCCategory(StringRef ClassToExtend, StringRef CategoryName, + const clang::AvailabilityInfo Avail, const Decl *D, + HeaderType Access); /// Add ObjC IVar record with attributes from AST. /// @@ -90,12 +93,13 @@ public: /// \param D The pointer to the declaration from traversing AST. /// \param Access The intended access level of symbol. /// \param AC The access control tied to the ivar declaration. - /// \return The non-owning pointer to added record in slice. - ObjCIVarRecord *addObjCIVar(ObjCContainerRecord *Container, - StringRef IvarName, RecordLinkage Linkage, - const clang::AvailabilityInfo Avail, - const Decl *D, HeaderType Access, - const clang::ObjCIvarDecl::AccessControl AC); + /// \return The non-owning pointer to added record in slice with it's frontend + /// attributes. + std::pair + addObjCIVar(ObjCContainerRecord *Container, StringRef IvarName, + RecordLinkage Linkage, const clang::AvailabilityInfo Avail, + const Decl *D, HeaderType Access, + const clang::ObjCIvarDecl::AccessControl AC); private: /// Mapping of records stored in slice to their frontend attributes. diff --git a/clang/include/clang/InstallAPI/HeaderFile.h b/clang/include/clang/InstallAPI/HeaderFile.h index 70e83bbb3e76f6bb91030fb6edca023aa5450e36..c67503d4ad49e934a6e4ac6927e9bd95fabd4567 100644 --- a/clang/include/clang/InstallAPI/HeaderFile.h +++ b/clang/include/clang/InstallAPI/HeaderFile.h @@ -13,7 +13,9 @@ #ifndef LLVM_CLANG_INSTALLAPI_HEADERFILE_H #define LLVM_CLANG_INSTALLAPI_HEADERFILE_H +#include "clang/Basic/FileManager.h" #include "clang/Basic/LangStandard.h" +#include "clang/InstallAPI/MachO.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Regex.h" @@ -22,8 +24,6 @@ namespace clang::installapi { enum class HeaderType { - /// Unset or unknown type. - Unknown, /// Represents declarations accessible to all clients. Public, /// Represents declarations accessible to a disclosed set of clients. @@ -31,6 +31,8 @@ enum class HeaderType { /// Represents declarations only accessible as implementation details to the /// input library. Project, + /// Unset or unknown type. + Unknown, }; inline StringRef getName(const HeaderType T) { @@ -56,6 +58,12 @@ class HeaderFile { std::string IncludeName; /// Supported language mode for header. std::optional Language; + /// Exclude header file from processing. + bool Excluded{false}; + /// Add header file to processing. + bool Extra{false}; + /// Specify that header file is the umbrella header for library. + bool Umbrella{false}; public: HeaderFile() = delete; @@ -71,17 +79,52 @@ public: StringRef getIncludeName() const { return IncludeName; } StringRef getPath() const { return FullPath; } + void setExtra(bool V = true) { Extra = V; } + void setExcluded(bool V = true) { Excluded = V; } + void setUmbrellaHeader(bool V = true) { Umbrella = V; } + bool isExtra() const { return Extra; } + bool isExcluded() const { return Excluded; } + bool isUmbrellaHeader() const { return Umbrella; } + bool useIncludeName() const { return Type != HeaderType::Project && !IncludeName.empty(); } bool operator==(const HeaderFile &Other) const { - return std::tie(Type, FullPath, IncludeName, Language) == - std::tie(Other.Type, Other.FullPath, Other.IncludeName, - Other.Language); + return std::tie(Type, FullPath, IncludeName, Language, Excluded, Extra, + Umbrella) == std::tie(Other.Type, Other.FullPath, + Other.IncludeName, Other.Language, + Other.Excluded, Other.Extra, + Other.Umbrella); } }; +/// Glob that represents a pattern of header files to retreive. +class HeaderGlob { +private: + std::string GlobString; + llvm::Regex Rule; + HeaderType Type; + bool FoundMatch{false}; + +public: + HeaderGlob(StringRef GlobString, llvm::Regex &&, HeaderType Type); + + /// Create a header glob from string for the header access level. + static llvm::Expected> + create(StringRef GlobString, HeaderType Type); + + /// Query if provided header matches glob. + bool match(const HeaderFile &Header); + + /// Query if a header was matched in the glob, used primarily for error + /// reporting. + bool didMatch() { return FoundMatch; } + + /// Provide back input glob string. + StringRef str() { return GlobString; } +}; + /// Assemble expected way header will be included by clients. /// As in what maps inside the brackets of `#include ` /// For example, @@ -93,6 +136,19 @@ public: std::optional createIncludeHeaderName(const StringRef FullPath); using HeaderSeq = std::vector; +/// Determine if Path is a header file. +/// It does not touch the file system. +/// +/// \param Path File path to file. +bool isHeaderFile(StringRef Path); + +/// Given input directory, collect all header files. +/// +/// \param FM FileManager for finding input files. +/// \param Directory Path to directory file. +llvm::Expected enumerateFiles(clang::FileManager &FM, + StringRef Directory); + } // namespace clang::installapi #endif // LLVM_CLANG_INSTALLAPI_HEADERFILE_H diff --git a/clang/include/clang/InstallAPI/InstallAPIDiagnostic.h b/clang/include/clang/InstallAPI/InstallAPIDiagnostic.h new file mode 100644 index 0000000000000000000000000000000000000000..547fb0bcf9a8936591aa156f4c566b919b5a35bf --- /dev/null +++ b/clang/include/clang/InstallAPI/InstallAPIDiagnostic.h @@ -0,0 +1,14 @@ +//===--- InstallAPIDiagnostic.h - Diagnostics for InstallAPI ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INSTALLAPI_INSTALLAPIDIAGNOSTIC_H +#define LLVM_CLANG_INSTALLAPI_INSTALLAPIDIAGNOSTIC_H + +#include "clang/Basic/DiagnosticInstallAPI.h" + +#endif diff --git a/clang/include/clang/InstallAPI/MachO.h b/clang/include/clang/InstallAPI/MachO.h index 55e5591389ce1f9ccdddd767bc529b78f0f4802e..827220dbf39fb8aaaae1d1dac1bdc3d2e496cd9b 100644 --- a/clang/include/clang/InstallAPI/MachO.h +++ b/clang/include/clang/InstallAPI/MachO.h @@ -18,6 +18,7 @@ #include "llvm/TextAPI/PackedVersion.h" #include "llvm/TextAPI/Platform.h" #include "llvm/TextAPI/RecordVisitor.h" +#include "llvm/TextAPI/Symbol.h" #include "llvm/TextAPI/Target.h" #include "llvm/TextAPI/TextAPIWriter.h" #include "llvm/TextAPI/Utils.h" @@ -25,16 +26,23 @@ using SymbolFlags = llvm::MachO::SymbolFlags; using RecordLinkage = llvm::MachO::RecordLinkage; using Record = llvm::MachO::Record; +using EncodeKind = llvm::MachO::EncodeKind; using GlobalRecord = llvm::MachO::GlobalRecord; using ObjCContainerRecord = llvm::MachO::ObjCContainerRecord; using ObjCInterfaceRecord = llvm::MachO::ObjCInterfaceRecord; using ObjCCategoryRecord = llvm::MachO::ObjCCategoryRecord; using ObjCIVarRecord = llvm::MachO::ObjCIVarRecord; +using ObjCIFSymbolKind = llvm::MachO::ObjCIFSymbolKind; using Records = llvm::MachO::Records; +using RecordLoc = llvm::MachO::RecordLoc; +using RecordsSlice = llvm::MachO::RecordsSlice; using BinaryAttrs = llvm::MachO::RecordsSlice::BinaryAttrs; using SymbolSet = llvm::MachO::SymbolSet; +using SimpleSymbol = llvm::MachO::SimpleSymbol; using FileType = llvm::MachO::FileType; using PackedVersion = llvm::MachO::PackedVersion; +using PathSeq = llvm::MachO::PathSeq; using Target = llvm::MachO::Target; +using TargetList = llvm::MachO::TargetList; #endif // LLVM_CLANG_INSTALLAPI_MACHO_H diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index 1dcba1ef967980b7aa6297316b78912b3dbdb21d..970e0245417b5198b03b32f5ba4ee20ffe218128 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -30,6 +30,7 @@ namespace llvm { namespace orc { class LLJIT; +class LLJITBuilder; class ThreadSafeContext; } // namespace orc } // namespace llvm @@ -127,6 +128,13 @@ protected: // custom runtime. virtual std::unique_ptr FindRuntimeInterface(); + // Lazily construct thev ORCv2 JITBuilder. This called when the internal + // IncrementalExecutor is created. The default implementation populates an + // in-process JIT with debugging support. Override this to configure the JIT + // engine used for execution. + virtual llvm::Expected> + CreateJITBuilder(CompilerInstance &CI); + public: virtual ~Interpreter(); diff --git a/clang/include/clang/Interpreter/Value.h b/clang/include/clang/Interpreter/Value.h index c380cd91550defa524d87e5b074d9e0a130760eb..d70e8f8719026b9dfc17c573451a3c8fc9c9545d 100644 --- a/clang/include/clang/Interpreter/Value.h +++ b/clang/include/clang/Interpreter/Value.h @@ -76,6 +76,7 @@ class QualType; X(bool, Bool) \ X(char, Char_S) \ X(signed char, SChar) \ + X(unsigned char, Char_U) \ X(unsigned char, UChar) \ X(short, Short) \ X(unsigned short, UShort) \ diff --git a/clang/include/clang/Lex/ModuleMap.h b/clang/include/clang/Lex/ModuleMap.h index 867cb6eab42f2d7bf04bfa8e32c5e073170f7816..2e28ff6823cb2a73cd577bd96e483c71bd513011 100644 --- a/clang/include/clang/Lex/ModuleMap.h +++ b/clang/include/clang/Lex/ModuleMap.h @@ -263,8 +263,8 @@ private: Attributes Attrs; /// If \c InferModules is non-zero, the module map file that allowed - /// inferred modules. Otherwise, nullopt. - OptionalFileEntryRef ModuleMapFile; + /// inferred modules. Otherwise, invalid. + FileID ModuleMapFID; /// The names of modules that cannot be inferred within this /// directory. @@ -279,8 +279,7 @@ private: /// A mapping from an inferred module to the module map that allowed the /// inference. - // FIXME: Consider making the values non-optional. - llvm::DenseMap InferredModuleAllowedBy; + llvm::DenseMap InferredModuleAllowedBy; llvm::DenseMap AdditionalModMaps; @@ -618,8 +617,9 @@ public: /// /// \param Module The module whose module map file will be returned, if known. /// - /// \returns The file entry for the module map file containing the given - /// module, or nullptr if the module definition was inferred. + /// \returns The FileID for the module map file containing the given module, + /// invalid if the module definition was inferred. + FileID getContainingModuleMapFileID(const Module *Module) const; OptionalFileEntryRef getContainingModuleMapFile(const Module *Module) const; /// Get the module map file that (along with the module name) uniquely @@ -631,9 +631,10 @@ public: /// of inferred modules, returns the module map that allowed the inference /// (e.g. contained 'module *'). Otherwise, returns /// getContainingModuleMapFile(). + FileID getModuleMapFileIDForUniquing(const Module *M) const; OptionalFileEntryRef getModuleMapFileForUniquing(const Module *M) const; - void setInferredModuleAllowedBy(Module *M, OptionalFileEntryRef ModMap); + void setInferredModuleAllowedBy(Module *M, FileID ModMapFID); /// Canonicalize \p Path in a manner suitable for a module map file. In /// particular, this canonicalizes the parent directory separately from the diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 0836b7d439bb049054074c4cfa845d4e56bd085e..24e146a589a758baf7080d7dfcd066ec910a8f70 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -736,6 +736,19 @@ private: State ConditionalStackState = Off; } PreambleConditionalStack; + /// Function for getting the dependency preprocessor directives of a file. + /// + /// These are directives derived from a special form of lexing where the + /// source input is scanned for the preprocessor directives that might have an + /// effect on the dependencies for a compilation unit. + /// + /// Enables a client to cache the directives for a file and provide them + /// across multiple compiler invocations. + /// FIXME: Allow returning an error. + using DependencyDirectivesFn = llvm::unique_function>(FileEntryRef)>; + DependencyDirectivesFn DependencyDirectivesForFile; + /// The current top of the stack that we're lexing from if /// not expanding a macro and we are lexing directly from source code. /// @@ -1270,6 +1283,11 @@ public: /// false if it is producing tokens to be consumed by Parse and Sema. bool isPreprocessedOutput() const { return PreprocessedOutput; } + /// Set the function used to get dependency directives for a file. + void setDependencyDirectivesFn(DependencyDirectivesFn Fn) { + DependencyDirectivesForFile = std::move(Fn); + } + /// Return true if we are lexing directly from the specified lexer. bool isCurrentLexer(const PreprocessorLexer *L) const { return CurPPLexer == L; diff --git a/clang/include/clang/Lex/PreprocessorOptions.h b/clang/include/clang/Lex/PreprocessorOptions.h index f841e4a028df50d3030a21145fa8d9af8bb047a3..50b5fba0ff773ec5ba6aa4bdc2d1bcce9a38b02f 100644 --- a/clang/include/clang/Lex/PreprocessorOptions.h +++ b/clang/include/clang/Lex/PreprocessorOptions.h @@ -186,41 +186,6 @@ public: /// with support for lifetime-qualified pointers. ObjCXXARCStandardLibraryKind ObjCXXARCStandardLibrary = ARCXX_nolib; - /// Records the set of modules - class FailedModulesSet { - llvm::StringSet<> Failed; - - public: - bool hasAlreadyFailed(StringRef module) { - return Failed.count(module) > 0; - } - - void addFailed(StringRef module) { - Failed.insert(module); - } - }; - - /// The set of modules that failed to build. - /// - /// This pointer will be shared among all of the compiler instances created - /// to (re)build modules, so that once a module fails to build anywhere, - /// other instances will see that the module has failed and won't try to - /// build it again. - std::shared_ptr FailedModules; - - /// Function for getting the dependency preprocessor directives of a file. - /// - /// These are directives derived from a special form of lexing where the - /// source input is scanned for the preprocessor directives that might have an - /// effect on the dependencies for a compilation unit. - /// - /// Enables a client to cache the directives for a file and provide them - /// across multiple compiler invocations. - /// FIXME: Allow returning an error. - std::function>( - FileEntryRef)> - DependencyDirectivesForFile; - /// Set up preprocessor for RunAnalysis action. bool SetUpStaticAnalyzer = false; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 64e031d5094c74cd0dbef96df55e479661b033b2..580bf2a5d79df516b6e5008c5a7dcd34b6935f66 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3014,6 +3014,7 @@ private: void DiagnoseAndSkipExtendedMicrosoftTypeAttributes(); SourceLocation SkipExtendedMicrosoftTypeAttributes(); void ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs); + void ParseNullabilityClassAttributes(ParsedAttributes &attrs); void ParseBorlandTypeAttributes(ParsedAttributes &attrs); void ParseOpenCLKernelAttributes(ParsedAttributes &attrs); void ParseOpenCLQualifiers(ParsedAttributes &Attrs); @@ -3073,6 +3074,11 @@ private: SourceLocation ScopeLoc, ParsedAttr::Form Form); + void ParseBoundsAttribute(IdentifierInfo &AttrName, + SourceLocation AttrNameLoc, ParsedAttributes &Attrs, + IdentifierInfo *ScopeName, SourceLocation ScopeLoc, + ParsedAttr::Form Form); + void ParseTypeofSpecifier(DeclSpec &DS); SourceLocation ParseDecltypeSpecifier(DeclSpec &DS); void AnnotateExistingDecltypeSpecifier(const DeclSpec &DS, diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index e4717dd5baf1e8d2fd91f47291803ff81a72971c..76311b00d2fc586fc249b1a3e0456412ddc4b05e 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -198,6 +198,9 @@ class Sema; /// HLSL vector truncation. ICK_HLSL_Vector_Truncation, + /// HLSL non-decaying array rvalue cast. + ICK_HLSL_Array_RValue, + /// The number of conversion kinds ICK_Num_Conversion_Kinds, }; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index b226851f03038d39d96ab19108f110f3550868a9..8c98d8c7fef7a7a8f8945eee012e24226010e96c 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -33,7 +33,6 @@ #include "clang/AST/NSAPI.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/StmtCXX.h" -#include "clang/AST/StmtOpenACC.h" #include "clang/AST/StmtOpenMP.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeOrdering.h" @@ -42,7 +41,6 @@ #include "clang/Basic/DarwinSDKInfo.h" #include "clang/Basic/ExpressionTraits.h" #include "clang/Basic/Module.h" -#include "clang/Basic/OpenACCKinds.h" #include "clang/Basic/OpenCLOptions.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/PragmaKinds.h" @@ -183,6 +181,7 @@ class Preprocessor; class PseudoDestructorTypeStorage; class PseudoObjectExpr; class QualType; +class SemaOpenACC; class StandardConversionSequence; class Stmt; class StringLiteral; @@ -466,9 +465,8 @@ class Sema final { // 37. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp) // 38. CUDA (SemaCUDA.cpp) // 39. HLSL Constructs (SemaHLSL.cpp) - // 40. OpenACC Constructs (SemaOpenACC.cpp) - // 41. OpenMP Directives and Clauses (SemaOpenMP.cpp) - // 42. SYCL Constructs (SemaSYCL.cpp) + // 40. OpenMP Directives and Clauses (SemaOpenMP.cpp) + // 41. SYCL Constructs (SemaSYCL.cpp) /// \name Semantic Analysis /// Implementations are in Sema.cpp @@ -1162,6 +1160,11 @@ public: /// CurContext - This is the current declaration context of parsing. DeclContext *CurContext; + SemaOpenACC &OpenACC() { + assert(OpenACCPtr); + return *OpenACCPtr; + } + protected: friend class Parser; friend class InitializationSequence; @@ -1192,6 +1195,8 @@ private: mutable IdentifierInfo *Ident_super; + std::unique_ptr OpenACCPtr; + ///@} // @@ -1655,6 +1660,9 @@ public: /// Add [[gsl::Pointer]] attributes for std:: types. void inferGslPointerAttribute(TypedefNameDecl *TD); + /// Add _Nullable attributes for std:: types. + void inferNullableClassAttribute(CXXRecordDecl *CRD); + enum PragmaOptionsAlignKind { POAK_Native, // #pragma options align=native POAK_Natural, // #pragma options align=natural @@ -2152,14 +2160,15 @@ public: bool IsLayoutCompatible(QualType T1, QualType T2) const; + bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, + const FunctionProtoType *Proto); + private: void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, const ArraySubscriptExpr *ASE = nullptr, bool AllowOnePastEnd = true, bool IndexNegated = false); void CheckArrayAccess(const Expr *E); - bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, - const FunctionProtoType *Proto); bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc, ArrayRef Args); bool CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall, @@ -2233,7 +2242,8 @@ private: bool CheckRISCVLMUL(CallExpr *TheCall, unsigned ArgNum); bool CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall); - void checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D); + void checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D, + const llvm::StringMap &FeatureMap); bool CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall); bool CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI, @@ -3059,6 +3069,8 @@ public: TemplateIdAnnotation *TemplateId, bool IsMemberSpecialization); + bool checkConstantPointerAuthKey(Expr *keyExpr, unsigned &key); + void DiagnoseFunctionSpecifiers(const DeclSpec &DS); NamedDecl *getShadowedDeclaration(const TypedefNameDecl *D, const LookupResult &R); @@ -3928,8 +3940,6 @@ public: bool BestCase, MSInheritanceModel Model); - bool CheckCountedByAttr(Scope *Scope, const FieldDecl *FD); - EnforceTCBAttr *mergeEnforceTCBAttr(Decl *D, const EnforceTCBAttr &AL); EnforceTCBLeafAttr *mergeEnforceTCBLeafAttr(Decl *D, const EnforceTCBLeafAttr &AL); @@ -5242,6 +5252,7 @@ public: enum ExpressionKind { EK_Decltype, EK_TemplateArgument, + EK_BoundsAttrArgument, EK_Other } ExprContext; @@ -5359,6 +5370,12 @@ public: return ExprEvalContexts.back(); }; + bool isBoundsAttrContext() const { + return ExprEvalContexts.back().ExprContext == + ExpressionEvaluationContextRecord::ExpressionKind:: + EK_BoundsAttrArgument; + } + /// Increment when we find a reference; decrement when we find an ignored /// assignment. Ultimately the value is 0 if every reference is an ignored /// assignment. @@ -8064,13 +8081,13 @@ public: /// The parser has processed a module import translated from a /// #include or similar preprocessing directive. - void ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod); + void ActOnAnnotModuleInclude(SourceLocation DirectiveLoc, Module *Mod); void BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod); /// The parsed has entered a submodule. - void ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod); + void ActOnAnnotModuleBegin(SourceLocation DirectiveLoc, Module *Mod); /// The parser has left a submodule. - void ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod); + void ActOnAnnotModuleEnd(SourceLocation DirectiveLoc, Module *Mod); /// Create an implicit import of the given module at the given /// source location, for error recovery, if possible. @@ -9214,7 +9231,7 @@ public: bool AttachTypeConstraint(NestedNameSpecifierLoc NS, DeclarationNameInfo NameInfo, - ConceptDecl *NamedConcept, + ConceptDecl *NamedConcept, NamedDecl *FoundDecl, const TemplateArgumentListInfo *TemplateArgs, TemplateTypeParmDecl *ConstrainedParameter, SourceLocation EllipsisLoc); @@ -11744,6 +11761,8 @@ public: QualType BuildMatrixType(QualType T, Expr *NumRows, Expr *NumColumns, SourceLocation AttrLoc); + QualType BuildCountAttributedArrayType(QualType WrappedTy, Expr *CountExpr); + QualType BuildAddressSpaceAttr(QualType &T, LangAS ASIdx, Expr *AddrSpace, SourceLocation AttrLoc); @@ -13340,56 +13359,6 @@ public: // // - /// \name OpenACC Constructs - /// Implementations are in SemaOpenACC.cpp - ///@{ - -public: - /// Called after parsing an OpenACC Clause so that it can be checked. - bool ActOnOpenACCClause(OpenACCClauseKind ClauseKind, - SourceLocation StartLoc); - - /// Called after the construct has been parsed, but clauses haven't been - /// parsed. This allows us to diagnose not-implemented, as well as set up any - /// state required for parsing the clauses. - void ActOnOpenACCConstruct(OpenACCDirectiveKind K, SourceLocation StartLoc); - - /// Called after the directive, including its clauses, have been parsed and - /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES - /// happen before any associated declarations or statements have been parsed. - /// This function is only called when we are parsing a 'statement' context. - bool ActOnStartOpenACCStmtDirective(OpenACCDirectiveKind K, - SourceLocation StartLoc); - - /// Called after the directive, including its clauses, have been parsed and - /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES - /// happen before any associated declarations or statements have been parsed. - /// This function is only called when we are parsing a 'Decl' context. - bool ActOnStartOpenACCDeclDirective(OpenACCDirectiveKind K, - SourceLocation StartLoc); - /// Called when we encounter an associated statement for our construct, this - /// should check legality of the statement as it appertains to this Construct. - StmtResult ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K, - StmtResult AssocStmt); - - /// Called after the directive has been completely parsed, including the - /// declaration group or associated statement. - StmtResult ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K, - SourceLocation StartLoc, - SourceLocation EndLoc, - StmtResult AssocStmt); - /// Called after the directive has been completely parsed, including the - /// declaration group or associated statement. - DeclGroupRef ActOnEndOpenACCDeclDirective(); - - ///@} - - // - // - // ------------------------------------------------------------------------- - // - // - /// \name OpenMP Directives and Clauses /// Implementations are in SemaOpenMP.cpp ///@{ diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h new file mode 100644 index 0000000000000000000000000000000000000000..7f50d7889ad79bf237eeb3b7d6abdd7e013fd7cb --- /dev/null +++ b/clang/include/clang/Sema/SemaOpenACC.h @@ -0,0 +1,74 @@ +//===----- SemaOpenACC.h - Semantic Analysis for OpenACC constructs -------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// This file declares semantic analysis for OpenACC constructs and +/// clauses. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_SEMAOPENACC_H +#define LLVM_CLANG_SEMA_SEMAOPENACC_H + +#include "clang/AST/DeclGroup.h" +#include "clang/Basic/OpenACCKinds.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Sema/Ownership.h" + +namespace clang { + +class ASTContext; +class DiagnosticEngine; +class LangOptions; +class Sema; + +class SemaOpenACC { +public: + SemaOpenACC(Sema &S); + + ASTContext &getASTContext() const; + DiagnosticsEngine &getDiagnostics() const; + const LangOptions &getLangOpts() const; + + Sema &SemaRef; + + /// Called after parsing an OpenACC Clause so that it can be checked. + bool ActOnClause(OpenACCClauseKind ClauseKind, SourceLocation StartLoc); + + /// Called after the construct has been parsed, but clauses haven't been + /// parsed. This allows us to diagnose not-implemented, as well as set up any + /// state required for parsing the clauses. + void ActOnConstruct(OpenACCDirectiveKind K, SourceLocation StartLoc); + + /// Called after the directive, including its clauses, have been parsed and + /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES + /// happen before any associated declarations or statements have been parsed. + /// This function is only called when we are parsing a 'statement' context. + bool ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc); + + /// Called after the directive, including its clauses, have been parsed and + /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES + /// happen before any associated declarations or statements have been parsed. + /// This function is only called when we are parsing a 'Decl' context. + bool ActOnStartDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc); + /// Called when we encounter an associated statement for our construct, this + /// should check legality of the statement as it appertains to this Construct. + StmtResult ActOnAssociatedStmt(OpenACCDirectiveKind K, StmtResult AssocStmt); + + /// Called after the directive has been completely parsed, including the + /// declaration group or associated statement. + StmtResult ActOnEndStmtDirective(OpenACCDirectiveKind K, + SourceLocation StartLoc, + SourceLocation EndLoc, StmtResult AssocStmt); + /// Called after the directive has been completely parsed, including the + /// declaration group or associated statement. + DeclGroupRef ActOnEndDeclDirective(); +}; + +} // namespace clang + +#endif // LLVM_CLANG_SEMA_SEMAOPENACC_H diff --git a/clang/include/clang/Serialization/ASTRecordReader.h b/clang/include/clang/Serialization/ASTRecordReader.h index 80a1359fd16aa02b9f1b8bb5d5f1bc303fda95b0..5d3e95cb5d630f855cde1e00cbab9a3c1834eacd 100644 --- a/clang/include/clang/Serialization/ASTRecordReader.h +++ b/clang/include/clang/Serialization/ASTRecordReader.h @@ -221,6 +221,8 @@ public: return Reader->ReadSelector(*F, Record, Idx); } + TypeCoupledDeclRefInfo readTypeCoupledDeclRefInfo(); + /// Read a declaration name, advancing Idx. // DeclarationName readDeclarationName(); (inherited) DeclarationNameLoc readDeclarationNameLoc(DeclarationName Name); diff --git a/clang/include/clang/Serialization/ASTRecordWriter.h b/clang/include/clang/Serialization/ASTRecordWriter.h index 9a64735c9fa55d9ccf62c0522951fed2b83af63b..e007d4a70843a151f0958bcefc3e758503efbda9 100644 --- a/clang/include/clang/Serialization/ASTRecordWriter.h +++ b/clang/include/clang/Serialization/ASTRecordWriter.h @@ -141,6 +141,11 @@ public: AddSourceLocation(Loc); } + void writeTypeCoupledDeclRefInfo(TypeCoupledDeclRefInfo Info) { + writeDeclRef(Info.getDecl()); + writeBool(Info.isDeref()); + } + /// Emit a source range. void AddSourceRange(SourceRange Range, LocSeq *Seq = nullptr) { return Writer->AddSourceRange(Range, *Record, Seq); diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index e5db486a71a490565692cb90c2ecc2055007f530..3ed9803fa3745b237b0bcb77cbd7489666722021 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -868,6 +868,8 @@ protected: return SemaPtr->getDiagnostics(); } + virtual Module *getEmittingModule(ASTContext &Ctx); + public: PCHGenerator(const Preprocessor &PP, InMemoryModuleCache &ModuleCache, StringRef OutputFile, StringRef isysroot, @@ -887,10 +889,12 @@ public: }; class ReducedBMIGenerator : public PCHGenerator { +protected: + virtual Module *getEmittingModule(ASTContext &Ctx) override; + public: ReducedBMIGenerator(const Preprocessor &PP, InMemoryModuleCache &ModuleCache, - StringRef OutputFile, std::shared_ptr Buffer, - bool IncludeTimestamps); + StringRef OutputFile); void HandleTranslationUnit(ASTContext &Ctx) override; }; diff --git a/clang/include/clang/Serialization/TypeBitCodes.def b/clang/include/clang/Serialization/TypeBitCodes.def index adbd5ec5d4b544f128eeb1af2496aa0cdc839a13..82b053d4caca63514d3179b5f358cd650312cbec 100644 --- a/clang/include/clang/Serialization/TypeBitCodes.def +++ b/clang/include/clang/Serialization/TypeBitCodes.def @@ -65,6 +65,7 @@ TYPE_BIT_CODE(DependentSizedMatrix, DEPENDENT_SIZE_MATRIX, 53) TYPE_BIT_CODE(Using, USING, 54) TYPE_BIT_CODE(BTFTagAttributed, BTFTAG_ATTRIBUTED, 55) TYPE_BIT_CODE(PackIndexing, PACK_INDEXING, 56) - +TYPE_BIT_CODE(CountAttributed, COUNT_ATTRIBUTED, 57) +TYPE_BIT_CODE(ArrayParameter, ARRAY_PARAMETER, 58) #undef TYPE_BIT_CODE diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 686e5e99f4a62c4a2649ea40849998968aa3e92b..5fe5c9286dabb791937aa53041252745a605afe5 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -622,6 +622,11 @@ def BlockInCriticalSectionChecker : Checker<"BlockInCriticalSection">, let ParentPackage = Cplusplus in { +def ArrayDeleteChecker : Checker<"ArrayDelete">, + HelpText<"Reports destructions of arrays of polymorphic objects that are " + "destructed as their base class.">, + Documentation; + def InnerPointerChecker : Checker<"InnerPointer">, HelpText<"Check for inner pointers of C++ containers used after " "re/deallocation">, @@ -777,11 +782,6 @@ def ContainerModeling : Checker<"ContainerModeling">, Documentation, Hidden; -def CXXArrayDeleteChecker : Checker<"ArrayDelete">, - HelpText<"Reports destructions of arrays of polymorphic objects that are " - "destructed as their base class.">, - Documentation; - def DeleteWithNonVirtualDtorChecker : Checker<"DeleteWithNonVirtualDtor">, HelpText<"Reports destructions of polymorphic objects with a non-virtual " "destructor in their base class">, @@ -908,7 +908,7 @@ def PaddingChecker : Checker<"Padding">, "24", Released> ]>, - Documentation; + Documentation; } // end: "padding" diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index 276d11e80a5b21c78acd293650fadeddcf4bd1c3..3a3c1a13d67dd554bc39684ceeb8b6898073c5c5 100644 --- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -227,6 +227,7 @@ public: unsigned ShouldEmitErrorsOnInvalidConfigValue : 1; unsigned AnalyzeAll : 1; unsigned AnalyzerDisplayProgress : 1; + unsigned AnalyzerNoteAnalysisEntryPoints : 1; unsigned eagerlyAssumeBinOpBifurcation : 1; @@ -291,10 +292,10 @@ public: ShowCheckerOptionDeveloperList(false), ShowEnabledCheckerList(false), ShowConfigOptionsList(false), ShouldEmitErrorsOnInvalidConfigValue(false), AnalyzeAll(false), - AnalyzerDisplayProgress(false), eagerlyAssumeBinOpBifurcation(false), - TrimGraph(false), visualizeExplodedGraphWithGraphViz(false), - UnoptimizedCFG(false), PrintStats(false), NoRetryExhausted(false), - AnalyzerWerror(false) {} + AnalyzerDisplayProgress(false), AnalyzerNoteAnalysisEntryPoints(false), + eagerlyAssumeBinOpBifurcation(false), TrimGraph(false), + visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false), + PrintStats(false), NoRetryExhausted(false), AnalyzerWerror(false) {} /// Interprets an option's string value as a boolean. The "true" string is /// interpreted as true and the "false" string is interpreted as false. diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index e762f7548e0b54186883f140bcc793378913a67b..ead96ce6891c39a261fc47fe73b0753611d5eaaa 100644 --- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -586,6 +586,9 @@ class BugReporter { private: BugReporterData& D; + /// The top-level entry point for the issue to be reported. + const Decl *AnalysisEntryPoint = nullptr; + /// Generate and flush the diagnostics for the given bug report. void FlushReport(BugReportEquivClass& EQ); @@ -623,6 +626,14 @@ public: Preprocessor &getPreprocessor() { return D.getPreprocessor(); } + /// Get the top-level entry point for the issue to be reported. + const Decl *getAnalysisEntryPoint() const { return AnalysisEntryPoint; } + + void setAnalysisEntryPoint(const Decl *EntryPoint) { + assert(EntryPoint); + AnalysisEntryPoint = EntryPoint; + } + /// Add the given report to the set of reports tracked by BugReporter. /// /// The reports are usually generated by the checkers. Further, they are @@ -713,6 +724,7 @@ public: virtual ~BugReporterContext() = default; PathSensitiveBugReporter& getBugReporter() { return BR; } + const PathSensitiveBugReporter &getBugReporter() const { return BR; } ProgramStateManager& getStateManager() const { return BR.getStateManager(); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h index 3432d2648633c25a575e93087c766688bcd6ede6..b4e1636130ca7c2d10586749bff69519e8363ed1 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h @@ -41,12 +41,8 @@ public: /// - We also accept calls where the number of arguments or parameters is /// greater than the specified value. /// For the exact heuristics, see CheckerContext::isCLibraryFunction(). - /// Note that functions whose declaration context is not a TU (e.g. - /// methods, functions in namespaces) are not accepted as C library - /// functions. - /// FIXME: If I understand it correctly, this discards calls where C++ code - /// refers a C library function through the namespace `std::` via headers - /// like . + /// (This mode only matches functions that are declared either directly + /// within a TU or in the namespace `std`.) CLibrary, /// Matches "simple" functions that are not methods. (Static methods are diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index 0d36587484bf9c30c567ba242ab0df647ebc020d..549c864dc91ef2f74984122155f62c27152afe86 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -59,6 +59,7 @@ namespace ento { enum CallEventKind { CE_Function, + CE_CXXStaticOperator, CE_CXXMember, CE_CXXMemberOperator, CE_CXXDestructor, @@ -709,6 +710,77 @@ public: } }; +/// Represents a static C++ operator call. +/// +/// "A" in this example. +/// However, "B" and "C" are represented by SimpleFunctionCall. +/// \code +/// struct S { +/// int pad; +/// static void operator()(int x, int y); +/// }; +/// S s{10}; +/// void (*fptr)(int, int) = &S::operator(); +/// +/// s(1, 2); // A +/// S::operator()(1, 2); // B +/// fptr(1, 2); // C +/// \endcode +class CXXStaticOperatorCall : public SimpleFunctionCall { + friend class CallEventManager; + +protected: + CXXStaticOperatorCall(const CXXOperatorCallExpr *CE, ProgramStateRef St, + const LocationContext *LCtx, + CFGBlock::ConstCFGElementRef ElemRef) + : SimpleFunctionCall(CE, St, LCtx, ElemRef) {} + CXXStaticOperatorCall(const CXXStaticOperatorCall &Other) = default; + + void cloneTo(void *Dest) const override { + new (Dest) CXXStaticOperatorCall(*this); + } + +public: + const CXXOperatorCallExpr *getOriginExpr() const override { + return cast(SimpleFunctionCall::getOriginExpr()); + } + + unsigned getNumArgs() const override { + // Ignore the object parameter that is not used for static member functions. + assert(getOriginExpr()->getNumArgs() > 0); + return getOriginExpr()->getNumArgs() - 1; + } + + const Expr *getArgExpr(unsigned Index) const override { + // Ignore the object parameter that is not used for static member functions. + return getOriginExpr()->getArg(Index + 1); + } + + std::optional + getAdjustedParameterIndex(unsigned ASTArgumentIndex) const override { + // Ignore the object parameter that is not used for static member functions. + if (ASTArgumentIndex == 0) + return std::nullopt; + return ASTArgumentIndex - 1; + } + + unsigned getASTArgumentIndex(unsigned CallArgumentIndex) const override { + // Account for the object parameter for the static member function. + return CallArgumentIndex + 1; + } + + OverloadedOperatorKind getOverloadedOperator() const { + return getOriginExpr()->getOperator(); + } + + Kind getKind() const override { return CE_CXXStaticOperator; } + StringRef getKindAsString() const override { return "CXXStaticOperatorCall"; } + + static bool classof(const CallEvent *CA) { + return CA->getKind() == CE_CXXStaticOperator; + } +}; + /// Represents a non-static C++ member function call. /// /// Example: \c obj.fun() diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h index 60421e5437d82f7d35e2b3da4473098735d2c7dc..d053a97189123afbbb9da502e1397b83f19f9763 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h @@ -15,7 +15,6 @@ #include "ProgramState_Fwd.h" #include "SVals.h" - #include "clang/AST/OperationKinds.h" #include "clang/AST/Stmt.h" #include "clang/Basic/OperatorKinds.h" @@ -113,8 +112,7 @@ public: OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK, bool IsBinary); -std::optional getPointeeDefVal(SVal PtrSVal, - ProgramStateRef State); +std::optional getPointeeVal(SVal PtrSVal, ProgramStateRef State); } // namespace ento diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 859c1497d7e6db8f0f6bd6cfda62025ecc69cc36..e38a3bb56ece26f6b0ea326dcc364b5c79415f97 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -187,6 +187,8 @@ public: /// Returns true if there is still simulation state on the worklist. bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) { + assert(L->inTopFrame()); + BR.setAnalysisEntryPoint(L->getDecl()); return Engine.ExecuteWorkList(L, Steps, nullptr); } diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index ca75c2a756a4a5457663a92f088067c6b5f1cbe5..51d76dc257ee94008e26084de5f23c64360721f3 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -494,6 +494,8 @@ private: InvalidatedSymbols *IS, RegionAndSymbolInvalidationTraits *HTraits, const CallEvent *Call) const; + + SVal wrapSymbolicRegion(SVal Base) const; }; //===----------------------------------------------------------------------===// @@ -782,20 +784,6 @@ inline SVal ProgramState::getLValue(const ObjCIvarDecl *D, SVal Base) const { return getStateManager().StoreMgr->getLValueIvar(D, Base); } -inline SVal ProgramState::getLValue(const FieldDecl *D, SVal Base) const { - return getStateManager().StoreMgr->getLValueField(D, Base); -} - -inline SVal ProgramState::getLValue(const IndirectFieldDecl *D, - SVal Base) const { - StoreManager &SM = *getStateManager().StoreMgr; - for (const auto *I : D->chain()) { - Base = SM.getLValueField(cast(I), Base); - } - - return Base; -} - inline SVal ProgramState::getLValue(QualType ElementType, SVal Idx, SVal Base) const{ if (std::optional N = Idx.getAs()) return getStateManager().StoreMgr->getLValueElement(ElementType, *N, Base); diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h index 846fdc7253977f99f03d0359b909d1f6a99b0938..9a522a3e2fe252082e1b2ee5b839c3d1d519cb63 100644 --- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h +++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h @@ -242,6 +242,8 @@ class EntryRef { /// The underlying cached entry. const CachedFileSystemEntry &Entry; + friend class DependencyScanningWorkerFilesystem; + public: EntryRef(StringRef Name, const CachedFileSystemEntry &Entry) : Filename(Name), Entry(Entry) {} @@ -300,14 +302,15 @@ public: /// /// Attempts to use the local and shared caches first, then falls back to /// using the underlying filesystem. - llvm::ErrorOr - getOrCreateFileSystemEntry(StringRef Filename, - bool DisableDirectivesScanning = false); + llvm::ErrorOr getOrCreateFileSystemEntry(StringRef Filename); -private: - /// Check whether the file should be scanned for preprocessor directives. - bool shouldScanForDirectives(StringRef Filename); + /// Ensure the directive tokens are populated for this file entry. + /// + /// Returns true if the directive tokens are populated for this file entry, + /// false if not (i.e. this entry is not a file or its scan fails). + bool ensureDirectiveTokensArePopulated(EntryRef Entry); +private: /// For a filename that's not yet associated with any entry in the caches, /// uses the underlying filesystem to either look up the entry based in the /// shared cache indexed by unique ID, or creates new entry from scratch. @@ -317,11 +320,6 @@ private: computeAndStoreResult(StringRef OriginalFilename, StringRef FilenameForLookup); - /// Scan for preprocessor directives for the given entry if necessary and - /// returns a wrapper object with reference semantics. - EntryRef scanForDirectivesIfNecessary(const CachedFileSystemEntry &Entry, - StringRef Filename, bool Disable); - /// Represents a filesystem entry that has been stat-ed (and potentially read) /// and that's about to be inserted into the cache as `CachedFileSystemEntry`. struct TentativeEntry { diff --git a/clang/lib/APINotes/APINotesManager.cpp b/clang/lib/APINotes/APINotesManager.cpp index f60f09e2b3c23198b2cb58eea29beba8312efdb0..789bb97d81de004724f759f16f0dc7a496909f9d 100644 --- a/clang/lib/APINotes/APINotesManager.cpp +++ b/clang/lib/APINotes/APINotesManager.cpp @@ -221,6 +221,7 @@ APINotesManager::getCurrentModuleAPINotes(Module *M, bool LookInModule, ArrayRef SearchPaths) { FileManager &FM = SM.getFileManager(); auto ModuleName = M->getTopLevelModuleName(); + auto ExportedModuleName = M->getTopLevelModule()->ExportAsModule; llvm::SmallVector APINotes; // First, look relative to the module itself. @@ -233,6 +234,10 @@ APINotesManager::getCurrentModuleAPINotes(Module *M, bool LookInModule, APINotes.push_back(*File); } + // If module FooCore is re-exported through module Foo, try Foo.apinotes. + if (!ExportedModuleName.empty()) + if (auto File = findAPINotesFile(Dir, ExportedModuleName, WantPublic)) + APINotes.push_back(*File); }; if (M->IsFramework) { diff --git a/clang/lib/APINotes/APINotesWriter.cpp b/clang/lib/APINotes/APINotesWriter.cpp index 76fd24ccfae98469d96b41e4729f51983775ab83..e3f5d102fcd07fe5b398bfd95c0edc7df0cc5b2d 100644 --- a/clang/lib/APINotes/APINotesWriter.cpp +++ b/clang/lib/APINotes/APINotesWriter.cpp @@ -441,7 +441,7 @@ void emitVersionedInfo( std::sort(VI.begin(), VI.end(), [](const std::pair &LHS, const std::pair &RHS) -> bool { - assert(LHS.first != RHS.first && + assert((&LHS == &RHS || LHS.first != RHS.first) && "two entries for the same version"); return LHS.first < RHS.first; }); diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index 4eae308ef5b34c608df0783c187130ae5bcf792b..d8042321319a67b253b034d8a0d4572a97f14d2f 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -704,6 +704,9 @@ void APValue::printPretty(raw_ostream &Out, const PrintingPolicy &Policy, return; } + if (const auto *AT = Ty->getAs()) + Ty = AT->getValueType(); + switch (getKind()) { case APValue::None: Out << ""; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 5a8fae76a43a4d5cfd2b81a7d7f357f3d5689ce0..f7f55dc4e7a9f436cf3a84b2c54849514c352662 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -879,7 +879,8 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, TemplateSpecializationTypes(this_()), DependentTemplateSpecializationTypes(this_()), AutoTypes(this_()), DependentBitIntTypes(this_()), SubstTemplateTemplateParmPacks(this_()), - CanonTemplateTemplateParms(this_()), SourceMgr(SM), LangOpts(LOpts), + ArrayParameterTypes(this_()), CanonTemplateTemplateParms(this_()), + SourceMgr(SM), LangOpts(LOpts), NoSanitizeL(new NoSanitizeList(LangOpts.NoSanitizeFiles, SM)), XRayFilter(new XRayFunctionFilter(LangOpts.XRayAlwaysInstrumentFiles, LangOpts.XRayNeverInstrumentFiles, @@ -1766,7 +1767,7 @@ TypeInfoChars static getConstantArrayInfoInChars(const ASTContext &Context, const ConstantArrayType *CAT) { TypeInfoChars EltInfo = Context.getTypeInfoInChars(CAT->getElementType()); - uint64_t Size = CAT->getSize().getZExtValue(); + uint64_t Size = CAT->getZExtSize(); assert((Size == 0 || static_cast(EltInfo.Width.getQuantity()) <= (uint64_t)(-1)/Size) && "Overflow in array type char size evaluation"); @@ -1906,11 +1907,12 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { case Type::IncompleteArray: case Type::VariableArray: - case Type::ConstantArray: { + case Type::ConstantArray: + case Type::ArrayParameter: { // Model non-constant sized arrays as size zero, but track the alignment. uint64_t Size = 0; if (const auto *CAT = dyn_cast(T)) - Size = CAT->getSize().getZExtValue(); + Size = CAT->getZExtSize(); TypeInfo EltInfo = getTypeInfo(cast(T)->getElementType()); assert((Size == 0 || EltInfo.Width <= (uint64_t)(-1) / Size) && @@ -2348,6 +2350,9 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { return getTypeInfo( cast(T)->getEquivalentType().getTypePtr()); + case Type::CountAttributed: + return getTypeInfo(cast(T)->desugar().getTypePtr()); + case Type::BTFTagAttributed: return getTypeInfo( cast(T)->getWrappedType().getTypePtr()); @@ -3122,6 +3127,32 @@ QualType ASTContext::removePtrSizeAddrSpace(QualType T) const { return T; } +QualType ASTContext::getCountAttributedType( + QualType WrappedTy, Expr *CountExpr, bool CountInBytes, bool OrNull, + ArrayRef DependentDecls) const { + assert(WrappedTy->isPointerType() || WrappedTy->isArrayType()); + + llvm::FoldingSetNodeID ID; + CountAttributedType::Profile(ID, WrappedTy, CountExpr, CountInBytes, OrNull); + + void *InsertPos = nullptr; + CountAttributedType *CATy = + CountAttributedTypes.FindNodeOrInsertPos(ID, InsertPos); + if (CATy) + return QualType(CATy, 0); + + QualType CanonTy = getCanonicalType(WrappedTy); + size_t Size = CountAttributedType::totalSizeToAlloc( + DependentDecls.size()); + CATy = (CountAttributedType *)Allocate(Size, TypeAlignment); + new (CATy) CountAttributedType(WrappedTy, CanonTy, CountExpr, CountInBytes, + OrNull, DependentDecls); + Types.push_back(CATy); + CountAttributedTypes.InsertNode(CATy, InsertPos); + + return QualType(CATy, 0); +} + const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T, FunctionType::ExtInfo Info) { if (T->getExtInfo() == Info) @@ -3367,6 +3398,37 @@ QualType ASTContext::getDecayedType(QualType T) const { return getDecayedType(T, Decayed); } +QualType ASTContext::getArrayParameterType(QualType Ty) const { + if (Ty->isArrayParameterType()) + return Ty; + assert(Ty->isConstantArrayType() && "Ty must be an array type."); + const auto *ATy = cast(Ty); + llvm::FoldingSetNodeID ID; + ATy->Profile(ID, *this, ATy->getElementType(), ATy->getZExtSize(), + ATy->getSizeExpr(), ATy->getSizeModifier(), + ATy->getIndexTypeQualifiers().getAsOpaqueValue()); + void *InsertPos = nullptr; + ArrayParameterType *AT = + ArrayParameterTypes.FindNodeOrInsertPos(ID, InsertPos); + if (AT) + return QualType(AT, 0); + + QualType Canonical; + if (!Ty.isCanonical()) { + Canonical = getArrayParameterType(getCanonicalType(Ty)); + + // Get the new insert position for the node we care about. + AT = ArrayParameterTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!AT && "Shouldn't be in the map!"); + } + + AT = new (*this, alignof(ArrayParameterType)) + ArrayParameterType(ATy, Canonical); + Types.push_back(AT); + ArrayParameterTypes.InsertNode(AT, InsertPos); + return QualType(AT, 0); +} + /// getBlockPointerType - Return the uniqued reference to the type for /// a pointer to the specified block. QualType ASTContext::getBlockPointerType(QualType T) const { @@ -3531,8 +3593,8 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, ArySize = ArySize.zextOrTrunc(Target->getMaxPointerWidth()); llvm::FoldingSetNodeID ID; - ConstantArrayType::Profile(ID, *this, EltTy, ArySize, SizeExpr, ASM, - IndexTypeQuals); + ConstantArrayType::Profile(ID, *this, EltTy, ArySize.getZExtValue(), SizeExpr, + ASM, IndexTypeQuals); void *InsertPos = nullptr; if (ConstantArrayType *ATP = @@ -3556,11 +3618,8 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - void *Mem = Allocate( - ConstantArrayType::totalSizeToAlloc(SizeExpr ? 1 : 0), - alignof(ConstantArrayType)); - auto *New = new (Mem) - ConstantArrayType(EltTy, Canon, ArySize, SizeExpr, ASM, IndexTypeQuals); + auto *New = ConstantArrayType::Create(*this, EltTy, Canon, ArySize, SizeExpr, + ASM, IndexTypeQuals); ConstantArrayTypes.InsertNode(New, InsertPos); Types.push_back(New); return QualType(New, 0); @@ -3616,6 +3675,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { case Type::PackIndexing: case Type::BitInt: case Type::DependentBitInt: + case Type::ArrayParameter: llvm_unreachable("type should never be variably-modified"); // These types can be variably-modified but should never need to @@ -6025,7 +6085,9 @@ CanQualType ASTContext::getCanonicalParamType(QualType T) const { T = getVariableArrayDecayedType(T); const Type *Ty = T.getTypePtr(); QualType Result; - if (isa(Ty)) { + if (getLangOpts().HLSL && isa(Ty)) { + Result = getArrayParameterType(QualType(Ty, 0)); + } else if (isa(Ty)) { Result = getArrayDecayedType(QualType(Ty,0)); } else if (isa(Ty)) { Result = getPointerType(QualType(Ty, 0)); @@ -6947,6 +7009,8 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const { } QualType ASTContext::getAdjustedParameterType(QualType T) const { + if (getLangOpts().HLSL && T->isConstantArrayType()) + return getArrayParameterType(T); if (T->isArrayType() || T->isFunctionType()) return getDecayedType(T); return T; @@ -7022,7 +7086,7 @@ uint64_t ASTContext::getConstantArrayElementCount(const ConstantArrayType *CA) const { uint64_t ElementCount = 1; do { - ElementCount *= CA->getSize().getZExtValue(); + ElementCount *= CA->getZExtSize(); CA = dyn_cast_or_null( CA->getElementType()->getAsArrayTypeUnsafe()); } while (CA); @@ -8345,7 +8409,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S, S += '['; if (const auto *CAT = dyn_cast(AT)) - S += llvm::utostr(CAT->getSize().getZExtValue()); + S += llvm::utostr(CAT->getZExtSize()); else { //Variable length arrays are encoded as a regular array with 0 elements. assert((isa(AT) || isa(AT)) && @@ -8557,6 +8621,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S, case Type::DeducedTemplateSpecialization: return; + case Type::ArrayParameter: case Type::Pipe: #define ABSTRACT_TYPE(KIND, BASE) #define TYPE(KIND, BASE) @@ -9574,11 +9639,11 @@ static uint64_t getRVVTypeSize(ASTContext &Context, const BuiltinType *Ty) { ASTContext::BuiltinVectorTypeInfo Info = Context.getBuiltinVectorTypeInfo(Ty); - unsigned EltSize = Context.getTypeSize(Info.ElementType); + uint64_t EltSize = Context.getTypeSize(Info.ElementType); if (Info.ElementType == Context.BoolTy) EltSize = 1; - unsigned MinElts = Info.EC.getKnownMinValue(); + uint64_t MinElts = Info.EC.getKnownMinValue(); return VScale->first * MinElts * EltSize; } @@ -10779,7 +10844,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, bool OfBlockPointer, { const ConstantArrayType* LCAT = getAsConstantArrayType(LHS); const ConstantArrayType* RCAT = getAsConstantArrayType(RHS); - if (LCAT && RCAT && RCAT->getSize() != LCAT->getSize()) + if (LCAT && RCAT && RCAT->getZExtSize() != LCAT->getZExtSize()) return {}; QualType LHSElem = getAsArrayType(LHS)->getElementType(); @@ -10900,6 +10965,10 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, bool OfBlockPointer, assert(LHS != RHS && "Equivalent pipe types should have already been handled!"); return {}; + case Type::ArrayParameter: + assert(LHS != RHS && + "Equivalent ArrayParameter types should have already been handled!"); + return {}; case Type::BitInt: { // Merge two bit-precise int types, while trying to preserve typedef info. bool LHSUnsigned = LHS->castAs()->isUnsigned(); @@ -12791,6 +12860,18 @@ static QualType getCommonNonSugarTypeNode(ASTContext &Ctx, const Type *X, getCommonArrayElementType(Ctx, AX, QX, AY, QY), AX->getSize(), SizeExpr, getCommonSizeModifier(AX, AY), getCommonIndexTypeCVRQualifiers(AX, AY)); } + case Type::ArrayParameter: { + const auto *AX = cast(X), + *AY = cast(Y); + assert(AX->getSize() == AY->getSize()); + const Expr *SizeExpr = Ctx.hasSameExpr(AX->getSizeExpr(), AY->getSizeExpr()) + ? AX->getSizeExpr() + : nullptr; + auto ArrayTy = Ctx.getConstantArrayType( + getCommonArrayElementType(Ctx, AX, QX, AY, QY), AX->getSize(), SizeExpr, + getCommonSizeModifier(AX, AY), getCommonIndexTypeCVRQualifiers(AX, AY)); + return Ctx.getArrayParameterType(ArrayTy); + } case Type::Atomic: { const auto *AX = cast(X), *AY = cast(Y); return Ctx.getAtomicType( @@ -13052,6 +13133,7 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X, CANONICAL_TYPE(Builtin) CANONICAL_TYPE(Complex) CANONICAL_TYPE(ConstantArray) + CANONICAL_TYPE(ArrayParameter) CANONICAL_TYPE(ConstantMatrix) CANONICAL_TYPE(Enum) CANONICAL_TYPE(ExtVector) @@ -13234,6 +13316,32 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X, return QualType(); return Ctx.getUsingType(CD, Ctx.getQualifiedType(Underlying)); } + case Type::CountAttributed: { + const auto *DX = cast(X), + *DY = cast(Y); + if (DX->isCountInBytes() != DY->isCountInBytes()) + return QualType(); + if (DX->isOrNull() != DY->isOrNull()) + return QualType(); + Expr *CEX = DX->getCountExpr(); + Expr *CEY = DY->getCountExpr(); + llvm::ArrayRef CDX = DX->getCoupledDecls(); + if (Ctx.hasSameExpr(CEX, CEY)) + return Ctx.getCountAttributedType(Ctx.getQualifiedType(Underlying), CEX, + DX->isCountInBytes(), DX->isOrNull(), + CDX); + if (!CEX->isIntegerConstantExpr(Ctx) || !CEY->isIntegerConstantExpr(Ctx)) + return QualType(); + // Two declarations with the same integer constant may still differ in their + // expression pointers, so we need to evaluate them. + llvm::APSInt VX = *CEX->getIntegerConstantExpr(Ctx); + llvm::APSInt VY = *CEY->getIntegerConstantExpr(Ctx); + if (VX != VY) + return QualType(); + return Ctx.getCountAttributedType(Ctx.getQualifiedType(Underlying), CEX, + DX->isCountInBytes(), DX->isOrNull(), + CDX); + } } llvm_unreachable("Unhandled Type Class"); } @@ -13621,22 +13729,19 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap &FeatureMap, Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features); } else if (const auto *TC = FD->getAttr()) { std::vector Features; - StringRef VersionStr = TC->getFeatureStr(GD.getMultiVersionIndex()); if (Target->getTriple().isAArch64()) { // TargetClones for AArch64 - if (VersionStr != "default") { - SmallVector VersionFeatures; - VersionStr.split(VersionFeatures, "+"); - for (auto &VFeature : VersionFeatures) { - VFeature = VFeature.trim(); + llvm::SmallVector Feats; + TC->getFeatures(Feats, GD.getMultiVersionIndex()); + for (StringRef Feat : Feats) + if (Target->validateCpuSupports(Feat.str())) // Use '?' to mark features that came from AArch64 TargetClones. - Features.push_back((StringRef{"?"} + VFeature).str()); - } - } + Features.push_back("?" + Feat.str()); Features.insert(Features.begin(), Target->getTargetOpts().FeaturesAsWritten.begin(), Target->getTargetOpts().FeaturesAsWritten.end()); } else { + StringRef VersionStr = TC->getFeatureStr(GD.getMultiVersionIndex()); if (VersionStr.starts_with("arch=")) TargetCPU = VersionStr.drop_front(sizeof("arch=") - 1); else if (VersionStr != "default") diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 023aaa7f0572b4328bded417486b65d3e9979484..94a47a8f6190181a8dbf9ac6fb513d21294ff072 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1218,6 +1218,15 @@ ASTNodeImporter::VisitConstantArrayType(const ConstantArrayType *T) { T->getIndexTypeCVRQualifiers()); } +ExpectedType +ASTNodeImporter::VisitArrayParameterType(const ArrayParameterType *T) { + ExpectedType ToArrayTypeOrErr = VisitConstantArrayType(T); + if (!ToArrayTypeOrErr) + return ToArrayTypeOrErr.takeError(); + + return Importer.getToContext().getArrayParameterType(*ToArrayTypeOrErr); +} + ExpectedType ASTNodeImporter::VisitIncompleteArrayType(const IncompleteArrayType *T) { ExpectedType ToElementTypeOrErr = import(T->getElementType()); @@ -1527,6 +1536,28 @@ ExpectedType ASTNodeImporter::VisitAttributedType(const AttributedType *T) { *ToModifiedTypeOrErr, *ToEquivalentTypeOrErr); } +ExpectedType +ASTNodeImporter::VisitCountAttributedType(const CountAttributedType *T) { + ExpectedType ToWrappedTypeOrErr = import(T->desugar()); + if (!ToWrappedTypeOrErr) + return ToWrappedTypeOrErr.takeError(); + + Error Err = Error::success(); + Expr *CountExpr = importChecked(Err, T->getCountExpr()); + + SmallVector CoupledDecls; + for (auto TI : T->dependent_decls()) { + Expected ToDeclOrErr = import(TI.getDecl()); + if (!ToDeclOrErr) + return ToDeclOrErr.takeError(); + CoupledDecls.emplace_back(*ToDeclOrErr, TI.isDeref()); + } + + return Importer.getToContext().getCountAttributedType( + *ToWrappedTypeOrErr, CountExpr, T->isCountInBytes(), T->isOrNull(), + ArrayRef(CoupledDecls.data(), CoupledDecls.size())); +} + ExpectedType ASTNodeImporter::VisitTemplateTypeParmType( const TemplateTypeParmType *T) { Expected ToDeclOrErr = import(T->getDecl()); @@ -9305,16 +9336,6 @@ Expected ASTImporter::Import(const Attr *FromAttr) { From->args_size()); break; } - case attr::CountedBy: { - AI.cloneAttr(FromAttr); - const auto *CBA = cast(FromAttr); - Expected SR = Import(CBA->getCountedByFieldLoc()).get(); - if (!SR) - return SR.takeError(); - AI.castAttrAs()->setCountedByFieldLoc(SR.get()); - break; - } - default: { // The default branch works for attributes that have no arguments to import. // FIXME: Handle every attribute type that has arguments of type to import diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index fe6e03ce174e591b06f4a77437621f72a9593ed2..d56bf21b459e035cea410a56828dd78fec082686 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -840,6 +840,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, case Type::Adjusted: case Type::Decayed: + case Type::ArrayParameter: if (!IsStructurallyEquivalent(Context, cast(T1)->getOriginalType(), cast(T2)->getOriginalType())) @@ -1069,6 +1070,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; break; + case Type::CountAttributed: + if (!IsStructurallyEquivalent(Context, + cast(T1)->desugar(), + cast(T2)->desugar())) + return false; + break; + case Type::BTFTagAttributed: if (!IsStructurallyEquivalent( Context, cast(T1)->getWrappedType(), diff --git a/clang/lib/AST/Availability.cpp b/clang/lib/AST/Availability.cpp index d0054e37e4dcd2fc30abc63730ef5bebffe24e7c..238359a2dedfcf4e4fac9145727c68796c20fcff 100644 --- a/clang/lib/AST/Availability.cpp +++ b/clang/lib/AST/Availability.cpp @@ -28,9 +28,9 @@ AvailabilityInfo AvailabilityInfo::createFromDecl(const Decl *Decl) { for (const auto *A : RD->specific_attrs()) { if (A->getPlatform()->getName() != PlatformName) continue; - Availability = - AvailabilityInfo(A->getPlatform()->getName(), A->getIntroduced(), - A->getDeprecated(), A->getObsoleted(), false, false); + Availability = AvailabilityInfo( + A->getPlatform()->getName(), A->getIntroduced(), A->getDeprecated(), + A->getObsoleted(), A->getUnavailable(), false, false); break; } diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp index 9d3856b8f7e08a8ccbcc636ff16c6ba28d57791a..86b77b49a0fbc4f5b99041be851e7074d1bf8861 100644 --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -654,6 +654,9 @@ ExprDependence clang::computeDependence(MemberExpr *E) { D |= toExprDependence(NNS->getDependence() & ~NestedNameSpecifierDependence::Dependent); + for (const auto &A : E->template_arguments()) + D |= toExprDependence(A.getArgument().getDependence()); + auto *MemberDecl = E->getMemberDecl(); if (FieldDecl *FD = dyn_cast(MemberDecl)) { DeclContext *DC = MemberDecl->getDeclContext(); @@ -670,7 +673,6 @@ ExprDependence clang::computeDependence(MemberExpr *E) { D |= ExprDependence::Type; } } - // FIXME: move remaining dependence computation from MemberExpr::Create() return D; } diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 8626f04012f7d497af9d0b222b3c11842262e752..131f82985e903bb6e2e76458fc03686f0702e3ef 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2577,11 +2577,14 @@ APValue *VarDecl::evaluateValueImpl(SmallVectorImpl &Notes, bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, Ctx, this, Notes, IsConstantInitialization); - // In C++/C23, this isn't a constant initializer if we produced notes. In that - // case, we can't keep the result, because it may only be correct under the - // assumption that the initializer is a constant context. + // In C++, or in C23 if we're initialising a 'constexpr' variable, this isn't + // a constant initializer if we produced notes. In that case, we can't keep + // the result, because it may only be correct under the assumption that the + // initializer is a constant context. if (IsConstantInitialization && - (Ctx.getLangOpts().CPlusPlus || Ctx.getLangOpts().C23) && !Notes.empty()) + (Ctx.getLangOpts().CPlusPlus || + (isConstexpr() && Ctx.getLangOpts().C23)) && + !Notes.empty()) Result = false; // Ensure the computed APValue is cleaned up later if evaluation succeeded, @@ -2837,7 +2840,7 @@ bool VarDecl::hasFlexibleArrayInit(const ASTContext &Ctx) const { auto InitTy = Ctx.getAsConstantArrayType(FlexibleInit->getType()); if (!InitTy) return false; - return InitTy->getSize() != 0; + return !InitTy->isZeroSize(); } CharUnits VarDecl::getFlexibleArrayInitChars(const ASTContext &Ctx) const { diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 04bbc49ab2f3192aea29e9dd2d198c3d3fa6908c..2cbb86b31b5e2eda2ec09ad8004aeebc60e2610b 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -1102,9 +1102,13 @@ bool Decl::isInAnotherModuleUnit() const { return M != getASTContext().getCurrentNamedModule(); } +bool Decl::isFromExplicitGlobalModule() const { + return getOwningModule() && getOwningModule()->isExplicitGlobalModule(); +} + bool Decl::shouldSkipCheckingODR() const { - return getASTContext().getLangOpts().SkipODRCheckInGMF && getOwningModule() && - getOwningModule()->isExplicitGlobalModule(); + return getASTContext().getLangOpts().SkipODRCheckInGMF && + isFromExplicitGlobalModule(); } static Decl::Kind getKind(const Decl *D) { return D->getKind(); } diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 1c3dcf63465c68a6f3bacc3a8abba4fc97ade130..645ec2f7563bca86bee1613a2dbec89247eafc87 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1567,10 +1567,9 @@ bool CXXRecordDecl::isGenericLambda() const { #ifndef NDEBUG static bool allLookupResultsAreTheSame(const DeclContext::lookup_result &R) { - for (auto *D : R) - if (!declaresSameEntity(D, R.front())) - return false; - return true; + return llvm::all_of(R, [&](NamedDecl *D) { + return D->isInvalidDecl() || declaresSameEntity(D, R.front()); + }); } #endif diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index b701581b2474a96d16cd45828eb4170076c83971..edbcdfe4d55bc94beb16169f374c4ab386237573 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -679,6 +679,16 @@ static void printExplicitSpecifier(ExplicitSpecifier ES, llvm::raw_ostream &Out, Out << Proto; } +static void MaybePrintTagKeywordIfSupressingScopes(PrintingPolicy &Policy, + QualType T, + llvm::raw_ostream &Out) { + StringRef prefix = T->isClassType() ? "class " + : T->isStructureType() ? "struct " + : T->isUnionType() ? "union " + : ""; + Out << prefix; +} + void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (!D->getDescribedFunctionTemplate() && !D->isFunctionTemplateSpecialization()) @@ -855,6 +865,10 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { Out << Proto << " -> "; Proto.clear(); } + if (!Policy.SuppressTagKeyword && Policy.SuppressScope && + !Policy.SuppressUnwrittenScope) + MaybePrintTagKeywordIfSupressingScopes(Policy, AFT->getReturnType(), + Out); AFT->getReturnType().print(Out, Policy, Proto); Proto.clear(); } @@ -1022,6 +1036,9 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) { ? D->getIdentifier()->deuglifiedName() : D->getName(); + if (!Policy.SuppressTagKeyword && Policy.SuppressScope && + !Policy.SuppressUnwrittenScope) + MaybePrintTagKeywordIfSupressingScopes(Policy, T, Out); printDeclType(T, Name); // Print the attributes that should be placed right before the end of the diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index f5ad402e3bd73e35eae50fbb14ce634d2ab23d68..07c9f287dd0767208d783ad14d88169f7ba1efa0 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -676,7 +676,8 @@ StringRef PredefinedExpr::getIdentKindName(PredefinedIdentKind IK) { // FIXME: Maybe this should use DeclPrinter with a special "print predefined // expr" policy instead. std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK, - const Decl *CurrentDecl) { + const Decl *CurrentDecl, + bool ForceElaboratedPrinting) { ASTContext &Context = CurrentDecl->getASTContext(); if (IK == PredefinedIdentKind::FuncDName) { @@ -724,10 +725,21 @@ std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK, return std::string(Out.str()); } if (const FunctionDecl *FD = dyn_cast(CurrentDecl)) { - if (IK != PredefinedIdentKind::PrettyFunction && + const auto &LO = Context.getLangOpts(); + bool IsFuncOrFunctionInNonMSVCCompatEnv = + ((IK == PredefinedIdentKind::Func || + IK == PredefinedIdentKind ::Function) && + !LO.MSVCCompat); + bool IsLFunctionInMSVCCommpatEnv = + IK == PredefinedIdentKind::LFunction && LO.MSVCCompat; + bool IsFuncOrFunctionOrLFunctionOrFuncDName = + IK != PredefinedIdentKind::PrettyFunction && IK != PredefinedIdentKind::PrettyFunctionNoVirtual && IK != PredefinedIdentKind::FuncSig && - IK != PredefinedIdentKind::LFuncSig) + IK != PredefinedIdentKind::LFuncSig; + if ((ForceElaboratedPrinting && + (IsFuncOrFunctionInNonMSVCCompatEnv || IsLFunctionInMSVCCommpatEnv)) || + (!ForceElaboratedPrinting && IsFuncOrFunctionOrLFunctionOrFuncDName)) return FD->getNameAsString(); SmallString<256> Name; @@ -755,6 +767,8 @@ std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK, PrintingPolicy Policy(Context.getLangOpts()); PrettyCallbacks PrettyCB(Context.getLangOpts()); Policy.Callbacks = &PrettyCB; + if (IK == PredefinedIdentKind::Function && ForceElaboratedPrinting) + Policy.SuppressTagKeyword = !LO.MSVCCompat; std::string Proto; llvm::raw_string_ostream POut(Proto); @@ -782,6 +796,12 @@ std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK, FD->printQualifiedName(POut, Policy); + if (IK == PredefinedIdentKind::Function) { + POut.flush(); + Out << Proto; + return std::string(Name); + } + POut << "("; if (FT) { for (unsigned i = 0, e = Decl->getNumParams(); i != e; ++i) { @@ -1692,8 +1712,11 @@ UnaryExprOrTypeTraitExpr::UnaryExprOrTypeTraitExpr( } MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, - ValueDecl *MemberDecl, - const DeclarationNameInfo &NameInfo, QualType T, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, ValueDecl *MemberDecl, + DeclAccessPair FoundDecl, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs, QualType T, ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR) : Expr(MemberExprClass, T, VK, OK), Base(Base), MemberDecl(MemberDecl), @@ -1701,11 +1724,30 @@ MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, assert(!NameInfo.getName() || MemberDecl->getDeclName() == NameInfo.getName()); MemberExprBits.IsArrow = IsArrow; - MemberExprBits.HasQualifierOrFoundDecl = false; - MemberExprBits.HasTemplateKWAndArgsInfo = false; + MemberExprBits.HasQualifier = QualifierLoc.hasQualifier(); + MemberExprBits.HasFoundDecl = + FoundDecl.getDecl() != MemberDecl || + FoundDecl.getAccess() != MemberDecl->getAccess(); + MemberExprBits.HasTemplateKWAndArgsInfo = + TemplateArgs || TemplateKWLoc.isValid(); MemberExprBits.HadMultipleCandidates = false; MemberExprBits.NonOdrUseReason = NOUR; MemberExprBits.OperatorLoc = OperatorLoc; + + if (hasQualifier()) + new (getTrailingObjects()) + NestedNameSpecifierLoc(QualifierLoc); + if (hasFoundDecl()) + *getTrailingObjects() = FoundDecl; + if (TemplateArgs) { + auto Deps = TemplateArgumentDependence::None; + getTrailingObjects()->initializeFrom( + TemplateKWLoc, *TemplateArgs, getTrailingObjects(), + Deps); + } else if (TemplateKWLoc.isValid()) { + getTrailingObjects()->initializeFrom( + TemplateKWLoc); + } setDependence(computeDependence(this)); } @@ -1715,48 +1757,20 @@ MemberExpr *MemberExpr::Create( ValueDecl *MemberDecl, DeclAccessPair FoundDecl, DeclarationNameInfo NameInfo, const TemplateArgumentListInfo *TemplateArgs, QualType T, ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR) { - bool HasQualOrFound = QualifierLoc || FoundDecl.getDecl() != MemberDecl || - FoundDecl.getAccess() != MemberDecl->getAccess(); + bool HasQualifier = QualifierLoc.hasQualifier(); + bool HasFoundDecl = FoundDecl.getDecl() != MemberDecl || + FoundDecl.getAccess() != MemberDecl->getAccess(); bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid(); std::size_t Size = - totalSizeToAlloc( - HasQualOrFound ? 1 : 0, HasTemplateKWAndArgsInfo ? 1 : 0, + totalSizeToAlloc( + HasQualifier, HasFoundDecl, HasTemplateKWAndArgsInfo, TemplateArgs ? TemplateArgs->size() : 0); void *Mem = C.Allocate(Size, alignof(MemberExpr)); - MemberExpr *E = new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl, - NameInfo, T, VK, OK, NOUR); - - if (HasQualOrFound) { - E->MemberExprBits.HasQualifierOrFoundDecl = true; - - MemberExprNameQualifier *NQ = - E->getTrailingObjects(); - NQ->QualifierLoc = QualifierLoc; - NQ->FoundDecl = FoundDecl; - } - - E->MemberExprBits.HasTemplateKWAndArgsInfo = - TemplateArgs || TemplateKWLoc.isValid(); - - // FIXME: remove remaining dependence computation to computeDependence(). - auto Deps = E->getDependence(); - if (TemplateArgs) { - auto TemplateArgDeps = TemplateArgumentDependence::None; - E->getTrailingObjects()->initializeFrom( - TemplateKWLoc, *TemplateArgs, - E->getTrailingObjects(), TemplateArgDeps); - for (const TemplateArgumentLoc &ArgLoc : TemplateArgs->arguments()) { - Deps |= toExprDependence(ArgLoc.getArgument().getDependence()); - } - } else if (TemplateKWLoc.isValid()) { - E->getTrailingObjects()->initializeFrom( - TemplateKWLoc); - } - E->setDependence(Deps); - - return E; + return new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, QualifierLoc, + TemplateKWLoc, MemberDecl, FoundDecl, NameInfo, + TemplateArgs, T, VK, OK, NOUR); } MemberExpr *MemberExpr::CreateEmpty(const ASTContext &Context, @@ -1765,12 +1779,11 @@ MemberExpr *MemberExpr::CreateEmpty(const ASTContext &Context, unsigned NumTemplateArgs) { assert((!NumTemplateArgs || HasTemplateKWAndArgsInfo) && "template args but no template arg info?"); - bool HasQualOrFound = HasQualifier || HasFoundDecl; std::size_t Size = - totalSizeToAlloc(HasQualOrFound ? 1 : 0, - HasTemplateKWAndArgsInfo ? 1 : 0, - NumTemplateArgs); + totalSizeToAlloc( + HasQualifier, HasFoundDecl, HasTemplateKWAndArgsInfo, + NumTemplateArgs); void *Mem = Context.Allocate(Size, alignof(MemberExpr)); return new (Mem) MemberExpr(EmptyShell()); } @@ -1928,6 +1941,7 @@ bool CastExpr::CastConsistency() const { case CK_UserDefinedConversion: // operator bool() case CK_BuiltinFnToFnPtr: case CK_FixedPointToBoolean: + case CK_HLSLArrayRValue: CheckNoBasePath: assert(path_empty() && "Cast kind should not have a base path!"); break; @@ -4604,8 +4618,17 @@ SourceRange DesignatedInitExpr::getDesignatorsSourceRange() const { SourceLocation DesignatedInitExpr::getBeginLoc() const { auto *DIE = const_cast(this); Designator &First = *DIE->getDesignator(0); - if (First.isFieldDesignator()) - return GNUSyntax ? First.getFieldLoc() : First.getDotLoc(); + if (First.isFieldDesignator()) { + // Skip past implicit designators for anonymous structs/unions, since + // these do not have valid source locations. + for (unsigned int i = 0; i < DIE->size(); i++) { + Designator &Des = *DIE->getDesignator(i); + SourceLocation retval = GNUSyntax ? Des.getFieldLoc() : Des.getDotLoc(); + if (!retval.isValid()) + continue; + return retval; + } + } return First.getLBracketLoc(); } diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 726415cfbde08aeed17415b11669b498cb459281..88c8eaf6ef9b6eb86b288828cd5066ae911cb365 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -209,7 +209,7 @@ namespace { IsArray = true; if (auto *CAT = dyn_cast(AT)) { - ArraySize = CAT->getSize().getZExtValue(); + ArraySize = CAT->getZExtSize(); } else { assert(I == 0 && "unexpected unsized array designator"); FirstEntryIsUnsizedArray = true; @@ -401,7 +401,7 @@ namespace { // This is a most-derived object. MostDerivedType = CAT->getElementType(); MostDerivedIsArrayElement = true; - MostDerivedArraySize = CAT->getSize().getZExtValue(); + MostDerivedArraySize = CAT->getZExtSize(); MostDerivedPathLength = Entries.size(); } /// Update this designator to refer to the first element within the array of @@ -3476,7 +3476,7 @@ static void expandStringLiteral(EvalInfo &Info, const StringLiteral *S, QualType CharType = CAT->getElementType(); assert(CharType->isIntegerType() && "unexpected character type"); - unsigned Elts = CAT->getSize().getZExtValue(); + unsigned Elts = CAT->getZExtSize(); Result = APValue(APValue::UninitArray(), std::min(S->getLength(), Elts), Elts); APSInt Value(Info.Ctx.getTypeSize(CharType), @@ -3619,7 +3619,7 @@ static bool CheckArraySize(EvalInfo &Info, const ConstantArrayType *CAT, SourceLocation CallLoc = {}) { return Info.CheckArraySize( CAT->getSizeExpr() ? CAT->getSizeExpr()->getBeginLoc() : CallLoc, - CAT->getNumAddressingBits(Info.Ctx), CAT->getSize().getZExtValue(), + CAT->getNumAddressingBits(Info.Ctx), CAT->getZExtSize(), /*Diag=*/true); } @@ -4908,7 +4908,7 @@ static bool handleDefaultInitValue(QualType T, APValue &Result) { if (auto *AT = dyn_cast_or_null(T->getAsArrayTypeUnsafe())) { - Result = APValue(APValue::UninitArray(), 0, AT->getSize().getZExtValue()); + Result = APValue(APValue::UninitArray(), 0, AT->getZExtSize()); if (Result.hasArrayFiller()) Success &= handleDefaultInitValue(AT->getElementType(), Result.getArrayFiller()); @@ -5594,6 +5594,9 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, if (Assumption->isValueDependent()) return ESR_Failed; + if (Assumption->HasSideEffects(Info.getCtx())) + continue; + bool Value; if (!EvaluateAsBooleanCondition(Assumption, Value, Info)) return ESR_Failed; @@ -6453,7 +6456,7 @@ static bool HandleConstructorCall(const Expr *E, const LValue &This, // Non-virtual base classes are initialized in the order in the class // definition. We have already checked for virtual base classes. assert(!BaseIt->isVirtual() && "virtual base for literal type"); - assert(Info.Ctx.hasSameType(BaseIt->getType(), BaseType) && + assert(Info.Ctx.hasSameUnqualifiedType(BaseIt->getType(), BaseType) && "base class initializers not in expected order"); ++BaseIt; #endif @@ -6592,7 +6595,7 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceRange CallRange, // For arrays, destroy elements right-to-left. if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(T)) { - uint64_t Size = CAT->getSize().getZExtValue(); + uint64_t Size = CAT->getZExtSize(); QualType ElemT = CAT->getElementType(); if (!CheckArraySize(Info, CAT, CallRange.getBegin())) @@ -7344,9 +7347,6 @@ class BufferToAPValueConverter { for (size_t I = 0, E = CXXRD->getNumBases(); I != E; ++I) { const CXXBaseSpecifier &BS = CXXRD->bases_begin()[I]; CXXRecordDecl *BaseDecl = BS.getType()->getAsCXXRecordDecl(); - if (BaseDecl->isEmpty() || - Info.Ctx.getASTRecordLayout(BaseDecl).getNonVirtualSize().isZero()) - continue; std::optional SubObj = visitType( BS.getType(), Layout.getBaseClassOffset(BaseDecl) + Offset); @@ -7396,7 +7396,7 @@ class BufferToAPValueConverter { } std::optional visit(const ConstantArrayType *Ty, CharUnits Offset) { - size_t Size = Ty->getSize().getLimitedValue(); + size_t Size = Ty->getLimitedSize(); CharUnits ElementWidth = Info.Ctx.getTypeSizeInChars(Ty->getElementType()); APValue ArrayValue(APValue::UninitArray(), Size, Size); @@ -8517,6 +8517,53 @@ public: }; } // end anonymous namespace +/// Get an lvalue to a field of a lambda's closure type. +static bool HandleLambdaCapture(EvalInfo &Info, const Expr *E, LValue &Result, + const CXXMethodDecl *MD, const FieldDecl *FD, + bool LValueToRValueConversion) { + // Static lambda function call operators can't have captures. We already + // diagnosed this, so bail out here. + if (MD->isStatic()) { + assert(Info.CurrentCall->This == nullptr && + "This should not be set for a static call operator"); + return false; + } + + // Start with 'Result' referring to the complete closure object... + if (MD->isExplicitObjectMemberFunction()) { + // Self may be passed by reference or by value. + const ParmVarDecl *Self = MD->getParamDecl(0); + if (Self->getType()->isReferenceType()) { + APValue *RefValue = Info.getParamSlot(Info.CurrentCall->Arguments, Self); + Result.setFrom(Info.Ctx, *RefValue); + } else { + const ParmVarDecl *VD = Info.CurrentCall->Arguments.getOrigParam(Self); + CallStackFrame *Frame = + Info.getCallFrameAndDepth(Info.CurrentCall->Arguments.CallIndex) + .first; + unsigned Version = Info.CurrentCall->Arguments.Version; + Result.set({VD, Frame->Index, Version}); + } + } else + Result = *Info.CurrentCall->This; + + // ... then update it to refer to the field of the closure object + // that represents the capture. + if (!HandleLValueMember(Info, E, Result, FD)) + return false; + + // And if the field is of reference type (or if we captured '*this' by + // reference), update 'Result' to refer to what + // the field refers to. + if (LValueToRValueConversion) { + APValue RVal; + if (!handleLValueToRValueConversion(Info, E, FD->getType(), Result, RVal)) + return false; + Result.setFrom(Info.Ctx, RVal); + } + return true; +} + /// Evaluate an expression as an lvalue. This can be legitimately called on /// expressions which are not glvalues, in three cases: /// * function designators in C, and @@ -8561,37 +8608,8 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) { if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) { const auto *MD = cast(Info.CurrentCall->Callee); - - // Static lambda function call operators can't have captures. We already - // diagnosed this, so bail out here. - if (MD->isStatic()) { - assert(Info.CurrentCall->This == nullptr && - "This should not be set for a static call operator"); - return false; - } - - // Start with 'Result' referring to the complete closure object... - if (MD->isExplicitObjectMemberFunction()) { - APValue *RefValue = - Info.getParamSlot(Info.CurrentCall->Arguments, MD->getParamDecl(0)); - Result.setFrom(Info.Ctx, *RefValue); - } else - Result = *Info.CurrentCall->This; - - // ... then update it to refer to the field of the closure object - // that represents the capture. - if (!HandleLValueMember(Info, E, Result, FD)) - return false; - // And if the field is of reference type, update 'Result' to refer to what - // the field refers to. - if (FD->getType()->isReferenceType()) { - APValue RVal; - if (!handleLValueToRValueConversion(Info, E, FD->getType(), Result, - RVal)) - return false; - Result.setFrom(Info.Ctx, RVal); - } - return true; + return HandleLambdaCapture(Info, E, Result, MD, FD, + FD->getType()->isReferenceType()); } } @@ -9069,45 +9087,46 @@ public: return Error(E); } bool VisitCXXThisExpr(const CXXThisExpr *E) { - // Can't look at 'this' when checking a potential constant expression. - if (Info.checkingPotentialConstantExpression()) - return false; - if (!Info.CurrentCall->This) { + auto DiagnoseInvalidUseOfThis = [&] { if (Info.getLangOpts().CPlusPlus11) Info.FFDiag(E, diag::note_constexpr_this) << E->isImplicit(); else Info.FFDiag(E); + }; + + // Can't look at 'this' when checking a potential constant expression. + if (Info.checkingPotentialConstantExpression()) return false; + + bool IsExplicitLambda = + isLambdaCallWithExplicitObjectParameter(Info.CurrentCall->Callee); + if (!IsExplicitLambda) { + if (!Info.CurrentCall->This) { + DiagnoseInvalidUseOfThis(); + return false; + } + + Result = *Info.CurrentCall->This; } - Result = *Info.CurrentCall->This; if (isLambdaCallOperator(Info.CurrentCall->Callee)) { // Ensure we actually have captured 'this'. If something was wrong with // 'this' capture, the error would have been previously reported. // Otherwise we can be inside of a default initialization of an object // declared by lambda's body, so no need to return false. - if (!Info.CurrentCall->LambdaThisCaptureField) - return true; - - // If we have captured 'this', the 'this' expression refers - // to the enclosing '*this' object (either by value or reference) which is - // either copied into the closure object's field that represents the - // '*this' or refers to '*this'. - // Update 'Result' to refer to the data member/field of the closure object - // that represents the '*this' capture. - if (!HandleLValueMember(Info, E, Result, - Info.CurrentCall->LambdaThisCaptureField)) - return false; - // If we captured '*this' by reference, replace the field with its referent. - if (Info.CurrentCall->LambdaThisCaptureField->getType() - ->isPointerType()) { - APValue RVal; - if (!handleLValueToRValueConversion(Info, E, E->getType(), Result, - RVal)) + if (!Info.CurrentCall->LambdaThisCaptureField) { + if (IsExplicitLambda && !Info.CurrentCall->This) { + DiagnoseInvalidUseOfThis(); return false; + } - Result.setFrom(Info.Ctx, RVal); + return true; } + + const auto *MD = cast(Info.CurrentCall->Callee); + return HandleLambdaCapture( + Info, E, Result, MD, Info.CurrentCall->LambdaThisCaptureField, + Info.CurrentCall->LambdaThisCaptureField->getType()->isPointerType()); } return true; } @@ -9234,7 +9253,8 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) { Info.getLangOpts().CPlusPlus26)) { // Permitted. } else { - if (SubExpr->getType()->isVoidPointerType()) { + if (SubExpr->getType()->isVoidPointerType() && + Info.getLangOpts().CPlusPlus) { if (HasValidResult) CCEDiag(E, diag::note_constexpr_invalid_void_star_cast) << SubExpr->getType() << Info.getLangOpts().CPlusPlus26 @@ -9931,7 +9951,7 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { assert(CAT && "unexpected type for array initializer"); unsigned Bits = - std::max(CAT->getSize().getBitWidth(), ArrayBound.getBitWidth()); + std::max(CAT->getSizeBitWidth(), ArrayBound.getBitWidth()); llvm::APInt InitBound = CAT->getSize().zext(Bits); llvm::APInt AllocBound = ArrayBound.zext(Bits); if (InitBound.ugt(AllocBound)) { @@ -10390,7 +10410,7 @@ bool RecordExprEvaluator::VisitCXXParenListOrInitListExpr( if (Field->getType()->isIncompleteArrayType()) { if (auto *CAT = Info.Ctx.getAsConstantArrayType(Init->getType())) { - if (!CAT->getSize().isZero()) { + if (!CAT->isZeroSize()) { // Bail out for now. This might sort of "work", but the rest of the // code isn't really prepared to handle it. Info.FFDiag(Init, diag::note_constexpr_unsupported_flexible_array); @@ -10534,7 +10554,7 @@ bool RecordExprEvaluator::VisitCXXStdInitializerListExpr( // End pointer. if (!HandleLValueArrayAdjustment(Info, E, Array, ArrayType->getElementType(), - ArrayType->getSize().getZExtValue())) + ArrayType->getZExtSize())) return false; Array.moveInto(Result.getStructField(1)); } else if (Info.Ctx.hasSameType(Field->getType(), Info.Ctx.getSizeType())) @@ -10976,8 +10996,7 @@ namespace { return Error(E); } - Result = APValue(APValue::UninitArray(), 0, - CAT->getSize().getZExtValue()); + Result = APValue(APValue::UninitArray(), 0, CAT->getZExtSize()); if (!Result.hasArrayFiller()) return true; @@ -11102,7 +11121,7 @@ bool ArrayExprEvaluator::VisitCXXParenListOrInitListExpr( Filler = Result.getArrayFiller(); unsigned NumEltsToInit = Args.size(); - unsigned NumElts = CAT->getSize().getZExtValue(); + unsigned NumElts = CAT->getZExtSize(); // If the initializer might depend on the array index, run it for each // array element. @@ -11160,7 +11179,7 @@ bool ArrayExprEvaluator::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) { auto *CAT = cast(E->getType()->castAsArrayTypeUnsafe()); - uint64_t Elements = CAT->getSize().getZExtValue(); + uint64_t Elements = CAT->getZExtSize(); Result = APValue(APValue::UninitArray(), Elements, Elements); LValue Subobject = This; @@ -11205,7 +11224,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, bool HadZeroInit = Value->hasValue(); if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(Type)) { - unsigned FinalSize = CAT->getSize().getZExtValue(); + unsigned FinalSize = CAT->getZExtSize(); // Preserve the array filler if we had prior zero-initialization. APValue Filler = @@ -11680,6 +11699,7 @@ GCCTypeClass EvaluateBuiltinClassifyType(QualType T, case Type::IncompleteArray: case Type::FunctionNoProto: case Type::FunctionProto: + case Type::ArrayParameter: return GCCTypeClass::Pointer; case Type::MemberPointer: @@ -11839,8 +11859,8 @@ static QualType getObjectType(APValue::LValueBase B) { static const Expr *ignorePointerCastsAndParens(const Expr *E) { assert(E->isPRValue() && E->getType()->hasPointerRepresentation()); - auto *NoParens = E->IgnoreParens(); - auto *Cast = dyn_cast(NoParens); + const Expr *NoParens = E->IgnoreParens(); + const auto *Cast = dyn_cast(NoParens); if (Cast == nullptr) return NoParens; @@ -11851,7 +11871,7 @@ static const Expr *ignorePointerCastsAndParens(const Expr *E) { CastKind != CK_AddressSpaceConversion) return NoParens; - auto *SubExpr = Cast->getSubExpr(); + const auto *SubExpr = Cast->getSubExpr(); if (!SubExpr->getType()->hasPointerRepresentation() || !SubExpr->isPRValue()) return NoParens; return ignorePointerCastsAndParens(SubExpr); @@ -11920,7 +11940,7 @@ static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) { return true; const auto *CAT = cast(Ctx.getAsArrayType(BaseType)); uint64_t Index = Entry.getAsArrayIndex(); - if (Index + 1 != CAT->getSize()) + if (Index + 1 != CAT->getZExtSize()) return false; BaseType = CAT->getElementType(); } else if (BaseType->isAnyComplexType()) { @@ -12334,6 +12354,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, case Builtin::BI__builtin_clzl: case Builtin::BI__builtin_clzll: case Builtin::BI__builtin_clzs: + case Builtin::BI__builtin_clzg: case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes case Builtin::BI__lzcnt: case Builtin::BI__lzcnt64: { @@ -12341,14 +12362,28 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; - // When the argument is 0, the result of GCC builtins is undefined, whereas - // for Microsoft intrinsics, the result is the bit-width of the argument. - bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 && - BuiltinOp != Builtin::BI__lzcnt && - BuiltinOp != Builtin::BI__lzcnt64; + std::optional Fallback; + if (BuiltinOp == Builtin::BI__builtin_clzg && E->getNumArgs() > 1) { + APSInt FallbackTemp; + if (!EvaluateInteger(E->getArg(1), FallbackTemp, Info)) + return false; + Fallback = FallbackTemp; + } - if (ZeroIsUndefined && !Val) - return Error(E); + if (!Val) { + if (Fallback) + return Success(*Fallback, E); + + // When the argument is 0, the result of GCC builtins is undefined, + // whereas for Microsoft intrinsics, the result is the bit-width of the + // argument. + bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 && + BuiltinOp != Builtin::BI__lzcnt && + BuiltinOp != Builtin::BI__lzcnt64; + + if (ZeroIsUndefined) + return Error(E); + } return Success(Val.countl_zero(), E); } @@ -12390,12 +12425,26 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, case Builtin::BI__builtin_ctz: case Builtin::BI__builtin_ctzl: case Builtin::BI__builtin_ctzll: - case Builtin::BI__builtin_ctzs: { + case Builtin::BI__builtin_ctzs: + case Builtin::BI__builtin_ctzg: { APSInt Val; if (!EvaluateInteger(E->getArg(0), Val, Info)) return false; - if (!Val) + + std::optional Fallback; + if (BuiltinOp == Builtin::BI__builtin_ctzg && E->getNumArgs() > 1) { + APSInt FallbackTemp; + if (!EvaluateInteger(E->getArg(1), FallbackTemp, Info)) + return false; + Fallback = FallbackTemp; + } + + if (!Val) { + if (Fallback) + return Success(*Fallback, E); + return Error(E); + } return Success(Val.countr_zero(), E); } @@ -12923,6 +12972,10 @@ static bool isOnePastTheEndOfCompleteObject(const ASTContext &Ctx, if (Ty->isIncompleteType()) return true; + // Can't be past the end of an invalid object. + if (LV.getLValueDesignator().Invalid) + return false; + // We're a past-the-end pointer if we point to the byte after the object, // no matter what our type or path is. auto Size = Ctx.getTypeSizeInChars(Ty); @@ -14033,6 +14086,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_AtomicToNonAtomic: case CK_NoOp: case CK_LValueToRValueBitCast: + case CK_HLSLArrayRValue: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_MemberPointerToBoolean: @@ -14861,6 +14915,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_AtomicToNonAtomic: case CK_NoOp: case CK_LValueToRValueBitCast: + case CK_HLSLArrayRValue: return ExprEvaluatorBaseTy::VisitCastExpr(E); case CK_Dependent: diff --git a/clang/lib/AST/FormatString.cpp b/clang/lib/AST/FormatString.cpp index 0c80ad109ccbb272236706fefb6cbc70b2c66d7b..da8164bad518ec7d646030cabbcbb0bb0d26cb8f 100644 --- a/clang/lib/AST/FormatString.cpp +++ b/clang/lib/AST/FormatString.cpp @@ -413,7 +413,7 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { return Match; if (const auto *BT = argTy->getAs()) { // Check if the only difference between them is signed vs unsigned - // if true, we consider they are compatible. + // if true, return match signedness. switch (BT->getKind()) { default: break; @@ -423,44 +423,53 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const { [[fallthrough]]; case BuiltinType::Char_S: case BuiltinType::SChar: + if (T == C.UnsignedShortTy || T == C.ShortTy) + return NoMatchTypeConfusion; + if (T == C.UnsignedCharTy) + return NoMatchSignedness; + if (T == C.SignedCharTy) + return Match; + break; case BuiltinType::Char_U: case BuiltinType::UChar: if (T == C.UnsignedShortTy || T == C.ShortTy) return NoMatchTypeConfusion; - if (T == C.UnsignedCharTy || T == C.SignedCharTy) + if (T == C.UnsignedCharTy) return Match; + if (T == C.SignedCharTy) + return NoMatchSignedness; break; case BuiltinType::Short: if (T == C.UnsignedShortTy) - return Match; + return NoMatchSignedness; break; case BuiltinType::UShort: if (T == C.ShortTy) - return Match; + return NoMatchSignedness; break; case BuiltinType::Int: if (T == C.UnsignedIntTy) - return Match; + return NoMatchSignedness; break; case BuiltinType::UInt: if (T == C.IntTy) - return Match; + return NoMatchSignedness; break; case BuiltinType::Long: if (T == C.UnsignedLongTy) - return Match; + return NoMatchSignedness; break; case BuiltinType::ULong: if (T == C.LongTy) - return Match; + return NoMatchSignedness; break; case BuiltinType::LongLong: if (T == C.UnsignedLongLongTy) - return Match; + return NoMatchSignedness; break; case BuiltinType::ULongLong: if (T == C.LongLongTy) - return Match; + return NoMatchSignedness; break; } // "Partially matched" because of promotions? diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 86304a54473ceaef838db08179681a0061da9949..46182809810bcf5108e90ff8a05b84dbc35d8d07 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -82,15 +82,27 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { if (DiscardResult) return this->discard(SubExpr); - if (SubExpr->getType()->isAnyComplexType()) - return this->delegate(SubExpr); + std::optional SubExprT = classify(SubExpr->getType()); + // Prepare storage for the result. + if (!Initializing && !SubExprT) { + std::optional LocalIndex = + allocateLocal(SubExpr, /*IsExtended=*/false); + if (!LocalIndex) + return false; + if (!this->emitGetPtrLocal(*LocalIndex, CE)) + return false; + } if (!this->visit(SubExpr)) return false; - if (std::optional SubExprT = classify(SubExpr->getType())) + if (SubExprT) return this->emitLoadPop(*SubExprT, CE); - return false; + + // If the subexpr type is not primitive, we need to perform a copy here. + // This happens for example in C when dereferencing a pointer of struct + // type. + return this->emitMemcpy(CE); } case CK_UncheckedDerivedToBase: @@ -296,14 +308,11 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { // Location for the SubExpr. // Since SubExpr is of complex type, visiting it results in a pointer // anyway, so we just create a temporary pointer variable. - std::optional SubExprOffset = allocateLocalPrimitive( + unsigned SubExprOffset = allocateLocalPrimitive( SubExpr, PT_Ptr, /*IsConst=*/true, /*IsExtended=*/false); - if (!SubExprOffset) - return false; - if (!this->visit(SubExpr)) return false; - if (!this->emitSetLocal(PT_Ptr, *SubExprOffset, CE)) + if (!this->emitSetLocal(PT_Ptr, SubExprOffset, CE)) return false; PrimType SourceElemT = classifyComplexElementType(SubExpr->getType()); @@ -312,7 +321,7 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { PrimType DestElemT = classifyPrim(DestElemType); // Cast both elements individually. for (unsigned I = 0; I != 2; ++I) { - if (!this->emitGetLocal(PT_Ptr, *SubExprOffset, CE)) + if (!this->emitGetLocal(PT_Ptr, SubExprOffset, CE)) return false; if (!this->emitArrayElemPop(SourceElemT, I, CE)) return false; @@ -392,6 +401,17 @@ bool ByteCodeExprGen::VisitBinaryOperator(const BinaryOperator *BO) { const Expr *LHS = BO->getLHS(); const Expr *RHS = BO->getRHS(); + // Handle comma operators. Just discard the LHS + // and delegate to RHS. + if (BO->isCommaOp()) { + if (!this->discard(LHS)) + return false; + if (RHS->getType()->isVoidType()) + return this->discard(RHS); + + return this->delegate(RHS); + } + if (BO->getType()->isAnyComplexType()) return this->VisitComplexBinOp(BO); if ((LHS->getType()->isAnyComplexType() || @@ -407,16 +427,6 @@ bool ByteCodeExprGen::VisitBinaryOperator(const BinaryOperator *BO) { std::optional RT = classify(RHS->getType()); std::optional T = classify(BO->getType()); - // Deal with operations which have composite or void types. - if (BO->isCommaOp()) { - if (!this->discard(LHS)) - return false; - if (RHS->getType()->isVoidType()) - return this->discard(RHS); - - return this->delegate(RHS); - } - // Special case for C++'s three-way/spaceship operator <=>, which // returns a std::{strong,weak,partial}_ordering (which is a class, so doesn't // have a PrimType). @@ -676,11 +686,17 @@ bool ByteCodeExprGen::VisitComplexBinOp(const BinaryOperator *E) { if (!this->emitSetLocal(PT_Ptr, ResultOffset, E)) return false; } + QualType LHSType = LHS->getType(); + if (const auto *AT = LHSType->getAs()) + LHSType = AT->getValueType(); + QualType RHSType = RHS->getType(); + if (const auto *AT = RHSType->getAs()) + RHSType = AT->getValueType(); // Evaluate LHS and save value to LHSOffset. bool LHSIsComplex; unsigned LHSOffset; - if (LHS->getType()->isAnyComplexType()) { + if (LHSType->isAnyComplexType()) { LHSIsComplex = true; LHSOffset = this->allocateLocalPrimitive(LHS, PT_Ptr, true, false); if (!this->visit(LHS)) @@ -689,7 +705,7 @@ bool ByteCodeExprGen::VisitComplexBinOp(const BinaryOperator *E) { return false; } else { LHSIsComplex = false; - PrimType LHST = classifyPrim(LHS->getType()); + PrimType LHST = classifyPrim(LHSType); LHSOffset = this->allocateLocalPrimitive(LHS, LHST, true, false); if (!this->visit(LHS)) return false; @@ -700,7 +716,7 @@ bool ByteCodeExprGen::VisitComplexBinOp(const BinaryOperator *E) { // Same with RHS. bool RHSIsComplex; unsigned RHSOffset; - if (RHS->getType()->isAnyComplexType()) { + if (RHSType->isAnyComplexType()) { RHSIsComplex = true; RHSOffset = this->allocateLocalPrimitive(RHS, PT_Ptr, true, false); if (!this->visit(RHS)) @@ -709,7 +725,7 @@ bool ByteCodeExprGen::VisitComplexBinOp(const BinaryOperator *E) { return false; } else { RHSIsComplex = false; - PrimType RHST = classifyPrim(RHS->getType()); + PrimType RHST = classifyPrim(RHSType); RHSOffset = this->allocateLocalPrimitive(RHS, RHST, true, false); if (!this->visit(RHS)) return false; @@ -803,7 +819,7 @@ bool ByteCodeExprGen::VisitImplicitValueInitExpr(const ImplicitValueIni const ArrayType *AT = QT->getAsArrayTypeUnsafe(); assert(AT); const auto *CAT = cast(AT); - size_t NumElems = CAT->getSize().getZExtValue(); + size_t NumElems = CAT->getZExtSize(); PrimType ElemT = classifyPrim(CAT->getElementType()); for (size_t I = 0; I != NumElems; ++I) { @@ -976,7 +992,7 @@ bool ByteCodeExprGen::VisitInitListExpr(const InitListExpr *E) { if (const Expr *Filler = E->getArrayFiller()) { const ConstantArrayType *CAT = Ctx.getASTContext().getAsConstantArrayType(E->getType()); - uint64_t NumElems = CAT->getSize().getZExtValue(); + uint64_t NumElems = CAT->getZExtSize(); for (; ElementIndex != NumElems; ++ElementIndex) { if (!this->visitArrayElemInit(ElementIndex, Filler)) @@ -1081,9 +1097,9 @@ template bool ByteCodeExprGen::VisitUnaryExprOrTypeTraitExpr( const UnaryExprOrTypeTraitExpr *E) { UnaryExprOrTypeTrait Kind = E->getKind(); - ASTContext &ASTCtx = Ctx.getASTContext(); + const ASTContext &ASTCtx = Ctx.getASTContext(); - if (Kind == UETT_SizeOf) { + if (Kind == UETT_SizeOf || Kind == UETT_DataSizeOf) { QualType ArgType = E->getTypeOfArgument(); // C++ [expr.sizeof]p2: "When applied to a reference or a reference type, @@ -1098,7 +1114,10 @@ bool ByteCodeExprGen::VisitUnaryExprOrTypeTraitExpr( if (ArgType->isDependentType() || !ArgType->isConstantSizeType()) return false; - Size = ASTCtx.getTypeSizeInChars(ArgType); + if (Kind == UETT_SizeOf) + Size = ASTCtx.getTypeSizeInChars(ArgType); + else + Size = ASTCtx.getTypeInfoDataSizeInChars(ArgType).Width; } if (DiscardResult) @@ -1233,22 +1252,19 @@ bool ByteCodeExprGen::VisitOpaqueValueExpr(const OpaqueValueExpr *E) { // At this point we either have the evaluated source expression or a pointer // to an object on the stack. We want to create a local variable that stores // this value. - std::optional LocalIndex = - allocateLocalPrimitive(E, SubExprT, /*IsConst=*/true); - if (!LocalIndex) - return false; - if (!this->emitSetLocal(SubExprT, *LocalIndex, E)) + unsigned LocalIndex = allocateLocalPrimitive(E, SubExprT, /*IsConst=*/true); + if (!this->emitSetLocal(SubExprT, LocalIndex, E)) return false; // Here the local variable is created but the value is removed from the stack, // so we put it back if the caller needs it. if (!DiscardResult) { - if (!this->emitGetLocal(SubExprT, *LocalIndex, E)) + if (!this->emitGetLocal(SubExprT, LocalIndex, E)) return false; } // This is cleaned up when the local variable is destroyed. - OpaqueExprs.insert({E, *LocalIndex}); + OpaqueExprs.insert({E, LocalIndex}); return true; } @@ -1302,7 +1318,7 @@ bool ByteCodeExprGen::VisitStringLiteral(const StringLiteral *E) { // If the initializer string is too long, a diagnostic has already been // emitted. Read only the array length from the string literal. - unsigned ArraySize = CAT->getSize().getZExtValue(); + unsigned ArraySize = CAT->getZExtSize(); unsigned N = std::min(ArraySize, E->getLength()); size_t CharWidth = E->getCharByteWidth(); @@ -1642,14 +1658,13 @@ bool ByteCodeExprGen::VisitMaterializeTemporaryExpr( // For everyhing else, use local variables. if (SubExprT) { - if (std::optional LocalIndex = allocateLocalPrimitive( - SubExpr, *SubExprT, /*IsConst=*/true, /*IsExtended=*/true)) { - if (!this->visit(SubExpr)) - return false; - if (!this->emitSetLocal(*SubExprT, *LocalIndex, E)) - return false; - return this->emitGetPtrLocal(*LocalIndex, E); - } + unsigned LocalIndex = allocateLocalPrimitive( + SubExpr, *SubExprT, /*IsConst=*/true, /*IsExtended=*/true); + if (!this->visit(SubExpr)) + return false; + if (!this->emitSetLocal(*SubExprT, LocalIndex, E)) + return false; + return this->emitGetPtrLocal(LocalIndex, E); } else { const Expr *Inner = E->getSubExpr()->skipRValueSubobjectAdjustments(); @@ -1744,6 +1759,14 @@ bool ByteCodeExprGen::VisitTypeTraitExpr(const TypeTraitExpr *E) { return this->emitConst(E->getValue(), E); } +template +bool ByteCodeExprGen::VisitArrayTypeTraitExpr( + const ArrayTypeTraitExpr *E) { + if (DiscardResult) + return true; + return this->emitConst(E->getValue(), E); +} + template bool ByteCodeExprGen::VisitLambdaExpr(const LambdaExpr *E) { if (DiscardResult) @@ -1896,7 +1919,7 @@ bool ByteCodeExprGen::VisitCXXConstructExpr( const ConstantArrayType *CAT = Ctx.getASTContext().getAsConstantArrayType(E->getType()); assert(CAT); - size_t NumElems = CAT->getSize().getZExtValue(); + size_t NumElems = CAT->getZExtSize(); const Function *Func = getFunction(E->getConstructor()); if (!Func || !Func->isConstexpr()) return false; @@ -2215,6 +2238,12 @@ bool ByteCodeExprGen::VisitPseudoObjectExpr( return true; } +template +bool ByteCodeExprGen::VisitPackIndexingExpr( + const PackIndexingExpr *E) { + return this->delegate(E->getSelectedExpr()); +} + template bool ByteCodeExprGen::discard(const Expr *E) { if (E->containsErrors()) return false; @@ -2227,7 +2256,7 @@ template bool ByteCodeExprGen::discard(const Expr *E) { template bool ByteCodeExprGen::delegate(const Expr *E) { if (E->containsErrors()) - return false; + return this->emitError(E); // We're basically doing: // OptionScope Scope(this, DicardResult, Initializing); @@ -2237,7 +2266,7 @@ bool ByteCodeExprGen::delegate(const Expr *E) { template bool ByteCodeExprGen::visit(const Expr *E) { if (E->containsErrors()) - return false; + return this->emitError(E); if (E->getType()->isVoidType()) return this->discard(E); @@ -2266,7 +2295,7 @@ bool ByteCodeExprGen::visitInitializer(const Expr *E) { assert(!classify(E->getType())); if (E->containsErrors()) - return false; + return this->emitError(E); OptionScope Scope(this, /*NewDiscardResult=*/false, /*NewInitializing=*/true); @@ -2660,18 +2689,12 @@ bool ByteCodeExprGen::visitVarDecl(const VarDecl *VD) { if (P.getGlobal(VD)) return true; - // Ignore external declarations. We will instead emit a dummy - // pointer when we see a DeclRefExpr for them. - if (VD->hasExternalStorage()) - return true; - std::optional GlobalIndex = P.createGlobal(VD, Init); if (!GlobalIndex) return false; - assert(Init); - { + if (Init) { DeclScope LocalScope(this, VD); if (VarT) { @@ -2681,6 +2704,7 @@ bool ByteCodeExprGen::visitVarDecl(const VarDecl *VD) { } return this->visitGlobalInitializer(Init, *GlobalIndex); } + return true; } else { VariableScope LocalScope(this); if (VarT) { @@ -2893,11 +2917,7 @@ template bool ByteCodeExprGen::VisitCXXDefaultInitExpr( const CXXDefaultInitExpr *E) { SourceLocScope SLS(this, E); - if (Initializing) - return this->visitInitializer(E->getExpr()); - - assert(classify(E->getType())); - return this->visit(E->getExpr()); + return this->delegate(E->getExpr()); } template @@ -3247,53 +3267,20 @@ bool ByteCodeExprGen::VisitDeclRefExpr(const DeclRefExpr *E) { // pointer to the actual value) instead of a pointer to the pointer to the // value. bool IsReference = D->getType()->isReferenceType(); - // Complex values are copied in the AST via a simply assignment or - // ltor cast. But we represent them as two-element arrays, which means - // we pass them around as pointers. So, to assignm from them, we will - // have to copy both (primitive) elements instead. - bool IsComplex = D->getType()->isAnyComplexType(); // Check for local/global variables and parameters. if (auto It = Locals.find(D); It != Locals.end()) { const unsigned Offset = It->second.Offset; - // FIXME: Fix the code duplication here with the code in the global case. - if (Initializing && IsComplex) { - PrimType ElemT = classifyComplexElementType(D->getType()); - for (unsigned I = 0; I != 2; ++I) { - if (!this->emitGetPtrLocal(Offset, E)) - return false; - if (!this->emitArrayElemPop(ElemT, I, E)) - return false; - if (!this->emitInitElem(ElemT, I, E)) - return false; - } - return true; - } - if (IsReference) return this->emitGetLocal(PT_Ptr, Offset, E); return this->emitGetPtrLocal(Offset, E); } else if (auto GlobalIndex = P.getGlobal(D)) { - if (Initializing && IsComplex) { - PrimType ElemT = classifyComplexElementType(D->getType()); - for (unsigned I = 0; I != 2; ++I) { - if (!this->emitGetPtrGlobal(*GlobalIndex, E)) - return false; - if (!this->emitArrayElemPop(ElemT, I, E)) - return false; - if (!this->emitInitElem(ElemT, I, E)) - return false; - } - return true; - } - if (IsReference) return this->emitGetGlobalPtr(*GlobalIndex, E); return this->emitGetPtrGlobal(*GlobalIndex, E); } else if (const auto *PVD = dyn_cast(D)) { if (auto It = this->Params.find(PVD); It != this->Params.end()) { - // FIXME: _Complex initializing case? if (IsReference || !It->second.IsPtr) return this->emitGetParamPtr(It->second.Offset, E); @@ -3316,15 +3303,13 @@ bool ByteCodeExprGen::VisitDeclRefExpr(const DeclRefExpr *E) { if (Ctx.getLangOpts().CPlusPlus) { if (const auto *VD = dyn_cast(D)) { // Visit local const variables like normal. - if (VD->isLocalVarDecl() && VD->getType().isConstQualified()) { + if ((VD->isLocalVarDecl() || VD->isStaticDataMember()) && + VD->getType().isConstQualified()) { if (!this->visitVarDecl(VD)) return false; // Retry. return this->VisitDeclRefExpr(E); } - - if (VD->hasExternalStorage()) - return this->emitInvalidDeclRef(E, E); } } else { if (const auto *VD = dyn_cast(D); @@ -3352,6 +3337,8 @@ template unsigned ByteCodeExprGen::collectBaseOffset(const RecordType *BaseType, const RecordType *DerivedType) { + assert(BaseType); + assert(DerivedType); const auto *FinalDecl = cast(BaseType->getDecl()); const RecordDecl *CurDecl = DerivedType->getDecl(); const Record *CurRecord = getRecord(CurDecl); diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 5ad2e74d7c269324ad8e08847e5d014387490f30..db0d73ce23f7c450dc0eab43575056b4659c2d9f 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -99,6 +99,7 @@ public: bool VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *E); bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E); bool VisitTypeTraitExpr(const TypeTraitExpr *E); + bool VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E); bool VisitLambdaExpr(const LambdaExpr *E); bool VisitPredefinedExpr(const PredefinedExpr *E); bool VisitCXXThrowExpr(const CXXThrowExpr *E); @@ -119,6 +120,7 @@ public: bool VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E); bool VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *E); bool VisitPseudoObjectExpr(const PseudoObjectExpr *E); + bool VisitPackIndexingExpr(const PackIndexingExpr *E); protected: bool visitExpr(const Expr *E) override; diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp index 6da3860f98d8c022d53781eaba72b5167295b086..675063e74898867e0edc7875a252c8510a701a87 100644 --- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp @@ -273,15 +273,18 @@ bool ByteCodeStmtGen::visitStmt(const Stmt *S) { return visitCaseStmt(cast(S)); case Stmt::DefaultStmtClass: return visitDefaultStmt(cast(S)); - case Stmt::GCCAsmStmtClass: - case Stmt::MSAsmStmtClass: - return visitAsmStmt(cast(S)); case Stmt::AttributedStmtClass: return visitAttributedStmt(cast(S)); case Stmt::CXXTryStmtClass: return visitCXXTryStmt(cast(S)); case Stmt::NullStmtClass: return true; + // Always invalid statements. + case Stmt::GCCAsmStmtClass: + case Stmt::MSAsmStmtClass: + case Stmt::GotoStmtClass: + case Stmt::LabelStmtClass: + return this->emitInvalid(S); default: { if (auto *Exp = dyn_cast(S)) return this->discard(Exp); @@ -420,6 +423,11 @@ bool ByteCodeStmtGen::visitWhileStmt(const WhileStmt *S) { LoopScope LS(this, EndLabel, CondLabel); this->emitLabel(CondLabel); + + if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt()) + if (!visitDeclStmt(CondDecl)) + return false; + if (!this->visitBool(Cond)) return false; if (!this->jumpFalse(EndLabel)) @@ -484,6 +492,10 @@ bool ByteCodeStmtGen::visitForStmt(const ForStmt *S) { if (Init && !this->visitStmt(Init)) return false; this->emitLabel(CondLabel); + + if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt()) + if (!visitDeclStmt(CondDecl)) + return false; if (Cond) { if (!this->visitBool(Cond)) return false; @@ -582,17 +594,21 @@ bool ByteCodeStmtGen::visitContinueStmt(const ContinueStmt *S) { template bool ByteCodeStmtGen::visitSwitchStmt(const SwitchStmt *S) { const Expr *Cond = S->getCond(); - PrimType CondT = this->classifyPrim(Cond->getType()); LabelTy EndLabel = this->getLabel(); OptLabelTy DefaultLabel = std::nullopt; - unsigned CondVar = this->allocateLocalPrimitive(Cond, CondT, true, false); if (const auto *CondInit = S->getInit()) if (!visitStmt(CondInit)) return false; + if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt()) + if (!visitDeclStmt(CondDecl)) + return false; + // Initialize condition variable. + PrimType CondT = this->classifyPrim(Cond->getType()); + unsigned CondVar = this->allocateLocalPrimitive(Cond, CondT, true, false); if (!this->visit(Cond)) return false; if (!this->emitSetLocal(CondT, CondVar, S)) @@ -657,11 +673,6 @@ bool ByteCodeStmtGen::visitDefaultStmt(const DefaultStmt *S) { return this->visitStmt(S->getSubStmt()); } -template -bool ByteCodeStmtGen::visitAsmStmt(const AsmStmt *S) { - return this->emitInvalid(S); -} - template bool ByteCodeStmtGen::visitAttributedStmt(const AttributedStmt *S) { // Ignore all attributes. diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.h b/clang/lib/AST/Interp/ByteCodeStmtGen.h index 64e03587ab2112dad4fb29609ebf8bad61770d81..d7e6e5042c2740b72c38a219fcaf1a89ba9d3c7c 100644 --- a/clang/lib/AST/Interp/ByteCodeStmtGen.h +++ b/clang/lib/AST/Interp/ByteCodeStmtGen.h @@ -63,7 +63,6 @@ private: bool visitSwitchStmt(const SwitchStmt *S); bool visitCaseStmt(const CaseStmt *S); bool visitDefaultStmt(const DefaultStmt *S); - bool visitAsmStmt(const AsmStmt *S); bool visitAttributedStmt(const AttributedStmt *S); bool visitCXXTryStmt(const CXXTryStmt *S); @@ -83,6 +82,7 @@ private: OptLabelTy DefaultLabel; }; +extern template class ByteCodeStmtGen; extern template class ByteCodeExprGen; } // namespace interp diff --git a/clang/lib/AST/Interp/Descriptor.cpp b/clang/lib/AST/Interp/Descriptor.cpp index ce7ed9cec3db3f073825ca6e763a2d5a05867732..a4ccc0236d292ce40665aaf2d37138e1e9831b86 100644 --- a/clang/lib/AST/Interp/Descriptor.cpp +++ b/clang/lib/AST/Interp/Descriptor.cpp @@ -233,9 +233,10 @@ static BlockMoveFn getMoveArrayPrim(PrimType Type) { Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, bool IsConst, bool IsTemporary, bool IsMutable) : Source(D), ElemSize(primSize(Type)), Size(ElemSize), - MDSize(MD.value_or(0)), AllocSize(align(Size + MDSize)), IsConst(IsConst), - IsMutable(IsMutable), IsTemporary(IsTemporary), CtorFn(getCtorPrim(Type)), - DtorFn(getDtorPrim(Type)), MoveFn(getMovePrim(Type)) { + MDSize(MD.value_or(0)), AllocSize(align(Size + MDSize)), PrimT(Type), + IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary), + CtorFn(getCtorPrim(Type)), DtorFn(getDtorPrim(Type)), + MoveFn(getMovePrim(Type)) { assert(AllocSize >= Size); assert(Source && "Missing source"); } @@ -246,7 +247,7 @@ Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, bool IsMutable) : Source(D), ElemSize(primSize(Type)), Size(ElemSize * NumElems), MDSize(MD.value_or(0)), - AllocSize(align(MDSize) + align(Size) + sizeof(InitMapPtr)), + AllocSize(align(MDSize) + align(Size) + sizeof(InitMapPtr)), PrimT(Type), IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary), IsArray(true), CtorFn(getCtorArrayPrim(Type)), DtorFn(getDtorArrayPrim(Type)), MoveFn(getMoveArrayPrim(Type)) { @@ -300,10 +301,19 @@ Descriptor::Descriptor(const DeclTy &D, const Record *R, MetadataSize MD, assert(Source && "Missing source"); } -Descriptor::Descriptor(const DeclTy &D, MetadataSize MD) - : Source(D), ElemSize(1), Size(ElemSize), MDSize(MD.value_or(0)), - AllocSize(Size + MDSize), ElemRecord(nullptr), IsConst(true), - IsMutable(false), IsTemporary(false), IsDummy(true) { +/// Dummy. +Descriptor::Descriptor(const DeclTy &D) + : Source(D), ElemSize(1), Size(1), MDSize(0), AllocSize(MDSize), + ElemRecord(nullptr), IsConst(true), IsMutable(false), IsTemporary(false), + IsDummy(true) { + assert(Source && "Missing source"); +} + +/// Dummy array. +Descriptor::Descriptor(const DeclTy &D, UnknownSize) + : Source(D), ElemSize(1), Size(UnknownSizeMark), MDSize(0), + AllocSize(MDSize), ElemRecord(nullptr), IsConst(true), IsMutable(false), + IsTemporary(false), IsArray(true), IsDummy(true) { assert(Source && "Missing source"); } diff --git a/clang/lib/AST/Interp/Descriptor.h b/clang/lib/AST/Interp/Descriptor.h index 0f64d678f3ef6b9415d37f04eb9a87c40151371f..4e257361ad146bfaa14c78873cb1f08bf1bbf162 100644 --- a/clang/lib/AST/Interp/Descriptor.h +++ b/clang/lib/AST/Interp/Descriptor.h @@ -112,6 +112,10 @@ public: const Record *const ElemRecord = nullptr; /// Descriptor of the array element. const Descriptor *const ElemDesc = nullptr; + /// 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; /// Flag indicating if the block is mutable. const bool IsConst = false; /// Flag indicating if a field is mutable. @@ -152,7 +156,11 @@ public: Descriptor(const DeclTy &D, const Record *R, MetadataSize MD, bool IsConst, bool IsTemporary, bool IsMutable); - Descriptor(const DeclTy &D, MetadataSize MD); + /// Allocates a dummy descriptor. + Descriptor(const DeclTy &D); + + /// Allocates a dummy array descriptor. + Descriptor(const DeclTy &D, UnknownSize); QualType getType() const; QualType getElemQualType() const; @@ -183,6 +191,11 @@ public: return Size; } + PrimType getPrimType() const { + assert(isPrimitiveArray() || isPrimitive()); + return *PrimT; + } + /// Returns the allocated size, including metadata. unsigned getAllocSize() const { return AllocSize; } /// returns the size of an element when the structure is viewed as an array. diff --git a/clang/lib/AST/Interp/Disasm.cpp b/clang/lib/AST/Interp/Disasm.cpp index 315ddb293044b78e792e0c285b8c9148cabd4799..01ef1c24744a582f4df50980ec4ddd81ac86bc10 100644 --- a/clang/lib/AST/Interp/Disasm.cpp +++ b/clang/lib/AST/Interp/Disasm.cpp @@ -10,9 +10,13 @@ // //===----------------------------------------------------------------------===// +#include "Boolean.h" #include "Floating.h" #include "Function.h" +#include "FunctionPointer.h" +#include "Integral.h" #include "IntegralAP.h" +#include "InterpFrame.h" #include "Opcode.h" #include "PrimType.h" #include "Program.h" @@ -86,6 +90,40 @@ LLVM_DUMP_METHOD void Function::dump(llvm::raw_ostream &OS) const { LLVM_DUMP_METHOD void Program::dump() const { dump(llvm::errs()); } +static const char *primTypeToString(PrimType T) { + switch (T) { + case PT_Sint8: + return "Sint8"; + case PT_Uint8: + return "Uint8"; + case PT_Sint16: + return "Sint16"; + case PT_Uint16: + return "Uint16"; + case PT_Sint32: + return "Sint32"; + case PT_Uint32: + return "Uint32"; + case PT_Sint64: + return "Sint64"; + case PT_Uint64: + return "Uint64"; + case PT_IntAP: + return "IntAP"; + case PT_IntAPS: + return "IntAPS"; + case PT_Bool: + return "Bool"; + case PT_Float: + return "Float"; + case PT_Ptr: + return "Ptr"; + case PT_FnPtr: + return "FnPtr"; + } + llvm_unreachable("Unhandled PrimType"); +} + LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const { { ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_RED, true}); @@ -100,9 +138,10 @@ LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const { unsigned GI = 0; for (const Global *G : Globals) { const Descriptor *Desc = G->block()->getDescriptor(); + Pointer GP = getPtrGlobal(GI); + OS << GI << ": " << (void *)G->block() << " "; { - Pointer GP = getPtrGlobal(GI); ColorScope SC(OS, true, GP.isInitialized() ? TerminalColor{llvm::raw_ostream::GREEN, false} @@ -111,6 +150,15 @@ LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const { } Desc->dump(OS); OS << "\n"; + if (Desc->isPrimitive() && !Desc->isDummy()) { + OS << " "; + { + ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_CYAN, false}); + OS << primTypeToString(Desc->getPrimType()) << " "; + } + TYPE_SWITCH(Desc->getPrimType(), { GP.deref().print(OS); }); + OS << "\n"; + } ++GI; } @@ -136,7 +184,7 @@ LLVM_DUMP_METHOD void Descriptor::dump(llvm::raw_ostream &OS) const { { ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true}); if (const auto *ND = dyn_cast_if_present(asDecl())) - OS << ND->getName(); + ND->printQualifiedName(OS); else if (asExpr()) OS << "expr (TODO)"; } @@ -159,3 +207,29 @@ LLVM_DUMP_METHOD void Descriptor::dump(llvm::raw_ostream &OS) const { if (isDummy()) OS << " dummy"; } + +LLVM_DUMP_METHOD void InterpFrame::dump(llvm::raw_ostream &OS, + unsigned Indent) const { + unsigned Spaces = Indent * 2; + { + ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true}); + OS.indent(Spaces); + if (getCallee()) + describe(OS); + else + OS << "Frame (Depth: " << getDepth() << ")"; + OS << "\n"; + } + OS.indent(Spaces) << "Function: " << getFunction(); + if (const Function *F = getFunction()) { + OS << " (" << F->getName() << ")"; + } + OS << "\n"; + OS.indent(Spaces) << "This: " << getThis() << "\n"; + OS.indent(Spaces) << "RVO: " << getRVOPtr() << "\n"; + + while (const InterpFrame *F = this->Caller) { + F->dump(OS, Indent + 1); + F = F->Caller; + } +} diff --git a/clang/lib/AST/Interp/EvaluationResult.cpp b/clang/lib/AST/Interp/EvaluationResult.cpp index 07b28d07326f9017bfd0a0a6311f7fe0b75024fe..d567b551f7f6fcffbab18b4c067572f8f4960f15 100644 --- a/clang/lib/AST/Interp/EvaluationResult.cpp +++ b/clang/lib/AST/Interp/EvaluationResult.cpp @@ -66,7 +66,7 @@ static bool CheckArrayInitialized(InterpState &S, SourceLocation Loc, const Pointer &BasePtr, const ConstantArrayType *CAT) { bool Result = true; - size_t NumElems = CAT->getSize().getZExtValue(); + size_t NumElems = CAT->getZExtSize(); QualType ElemType = CAT->getElementType(); if (ElemType->isRecordType()) { diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index 4f3cd6cd21a15184f56de3df592da5fc70941944..0ce64a572c263f3daa07d3de4385037e24fa6496 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -254,10 +254,10 @@ bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc) { if (VD->isConstexpr()) return true; + QualType T = VD->getType(); if (S.getLangOpts().CPlusPlus && !S.getLangOpts().CPlusPlus11) - return false; + return T->isSignedIntegerOrEnumerationType() || T->isUnsignedIntegerOrEnumerationType(); - QualType T = VD->getType(); if (T.isConstQualified()) return true; @@ -485,7 +485,9 @@ bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) { // Don't emit anything if the function isn't defined and we're checking // for a constant expression. It might be defined at the point we're // actually calling it. - if (!DiagDecl->isDefined() && S.checkingPotentialConstantExpression()) + bool IsExtern = DiagDecl->getStorageClass() == SC_Extern; + if (!DiagDecl->isDefined() && !IsExtern && + S.checkingPotentialConstantExpression()) return false; // If the declaration is defined _and_ declared 'constexpr', the below diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index bb220657c2dadc18628a27078d691c6ab898d8bc..405993eb827036f620ec62e119ddb33667697682 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -122,6 +122,9 @@ bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F, bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC, const Pointer &Ptr, const APSInt &IntValue); +/// Copy the contents of Src into Dest. +bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest); + /// Checks if the shift operation is legal. template bool CheckShift(InterpState &S, CodePtr OpPC, const LT &LHS, const RT &RHS, @@ -165,7 +168,8 @@ bool CheckDivRem(InterpState &S, CodePtr OpPC, const T &LHS, const T &RHS) { const auto *Op = cast(S.Current->getExpr(OpPC)); S.FFDiag(Op, diag::note_expr_divide_by_zero) << Op->getRHS()->getSourceRange(); - return false; + if constexpr (!std::is_same_v) + return false; } if (LHS.isSigned() && LHS.isMin() && RHS.isNegative() && RHS.isMinusOne()) { @@ -846,8 +850,7 @@ bool CMP3(InterpState &S, CodePtr OpPC, const ComparisonCategoryInfo *CmpInfo) { CmpInfo->getValueInfo(CmpInfo->makeWeakResult(CmpResult)); assert(CmpValueInfo); assert(CmpValueInfo->hasValidIntValue()); - const APSInt &IntValue = CmpValueInfo->getIntValue(); - return SetThreeWayComparisonField(S, OpPC, P, IntValue); + return SetThreeWayComparisonField(S, OpPC, P, CmpValueInfo->getIntValue()); } template ::T> @@ -1488,6 +1491,16 @@ bool InitElemPop(InterpState &S, CodePtr OpPC, uint32_t Idx) { return true; } +inline bool Memcpy(InterpState &S, CodePtr OpPC) { + const Pointer &Src = S.Stk.pop(); + Pointer &Dest = S.Stk.peek(); + + if (!CheckLoad(S, OpPC, Src)) + return false; + + return DoMemcpy(S, OpPC, Src, Dest); +} + //===----------------------------------------------------------------------===// // AddOffset, SubOffset //===----------------------------------------------------------------------===// @@ -1934,8 +1947,15 @@ inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) { const T &Offset = S.Stk.pop(); const Pointer &Ptr = S.Stk.peek(); - if (Ptr.isDummy()) - return true; + if (!Ptr.isZero()) { + if (!CheckArray(S, OpPC, Ptr)) + return false; + + if (Ptr.isDummy()) { + S.Stk.push(Ptr); + return true; + } + } if (!OffsetHelper(S, OpPC, Offset, Ptr)) return false; @@ -1948,9 +1968,14 @@ inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) { const T &Offset = S.Stk.pop(); const Pointer &Ptr = S.Stk.pop(); - if (Ptr.isDummy()) { - S.Stk.push(Ptr); - return true; + if (!Ptr.isZero()) { + if (!CheckArray(S, OpPC, Ptr)) + return false; + + if (Ptr.isDummy()) { + S.Stk.push(Ptr); + return true; + } } if (!OffsetHelper(S, OpPC, Offset, Ptr)) @@ -2202,6 +2227,9 @@ inline bool Invalid(InterpState &S, CodePtr OpPC) { return false; } +/// Do nothing and just abort execution. +inline bool Error(InterpState &S, CodePtr OpPC) { return false; } + /// Same here, but only for casts. inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind) { const SourceLocation &Loc = S.Current->getLocation(OpPC); diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp index c500b9d502d707813a322faabbacd2a43f6c1ec6..1bf5d55314f1f2ac2a059defc40903cb2dec3e85 100644 --- a/clang/lib/AST/Interp/InterpBuiltin.cpp +++ b/clang/lib/AST/Interp/InterpBuiltin.cpp @@ -119,6 +119,36 @@ static bool retPrimValue(InterpState &S, CodePtr OpPC, APValue &Result, #undef RET_CASE } +static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC, + const InterpFrame *Frame, + const CallExpr *Call) { + // The current frame is the one for __builtin_is_constant_evaluated. + // The one above that, potentially the one for std::is_constant_evaluated(). + if (S.inConstantContext() && !S.checkingPotentialConstantExpression() && + Frame->Caller && S.getEvalStatus().Diag) { + auto isStdCall = [](const FunctionDecl *F) -> bool { + return F && F->isInStdNamespace() && F->getIdentifier() && + F->getIdentifier()->isStr("is_constant_evaluated"); + }; + const InterpFrame *Caller = Frame->Caller; + + if (Caller->Caller && isStdCall(Caller->getCallee())) { + const Expr *E = Caller->Caller->getExpr(Caller->getRetPC()); + S.report(E->getExprLoc(), + diag::warn_is_constant_evaluated_always_true_constexpr) + << "std::is_constant_evaluated"; + } else { + const Expr *E = Frame->Caller->getExpr(Frame->getRetPC()); + S.report(E->getExprLoc(), + diag::warn_is_constant_evaluated_always_true_constexpr) + << "__builtin_is_constant_evaluated"; + } + } + + S.Stk.push(Boolean::from(S.inConstantContext())); + return true; +} + static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { @@ -533,11 +563,12 @@ static bool interp__builtin_rotate(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call, bool Right) { - PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); - assert(ArgT == *S.getContext().classify(Call->getArg(1)->getType())); + PrimType AmountT = *S.getContext().classify(Call->getArg(1)->getType()); + PrimType ValueT = *S.getContext().classify(Call->getArg(0)->getType()); - APSInt Amount = peekToAPSInt(S.Stk, ArgT); - APSInt Value = peekToAPSInt(S.Stk, ArgT, align(primSize(ArgT)) * 2); + APSInt Amount = peekToAPSInt(S.Stk, AmountT); + APSInt Value = peekToAPSInt( + S.Stk, ValueT, align(primSize(AmountT)) + align(primSize(ValueT))); APSInt Result; if (Right) @@ -605,10 +636,9 @@ static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC, return true; } -static bool interp__builtin_launder(InterpState &S, CodePtr OpPC, - const InterpFrame *Frame, - const Function *Func, - const CallExpr *Call) { +/// Just takes the first Argument to the call and puts it on the stack. +static bool noopPointer(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, + const Function *Func, const CallExpr *Call) { const Pointer &Arg = S.Stk.peek(); S.Stk.push(Arg); return true; @@ -917,14 +947,15 @@ static bool interp__builtin_complex(InterpState &S, CodePtr OpPC, bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *Call) { - InterpFrame *Frame = S.Current; + const InterpFrame *Frame = S.Current; APValue Dummy; std::optional ReturnT = S.getContext().classify(Call); switch (F->getBuiltinID()) { case Builtin::BI__builtin_is_constant_evaluated: - S.Stk.push(Boolean::from(S.inConstantContext())); + if (!interp__builtin_is_constant_evaluated(S, OpPC, Frame, Call)) + return false; break; case Builtin::BI__builtin_assume: case Builtin::BI__assume: @@ -1143,7 +1174,9 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, break; case Builtin::BI__builtin_launder: - if (!interp__builtin_launder(S, OpPC, Frame, F, Call)) + case Builtin::BI__builtin___CFStringMakeConstantString: + case Builtin::BI__builtin___NSStringMakeConstantString: + if (!noopPointer(S, OpPC, Frame, F, Call)) return false; break; @@ -1326,5 +1359,50 @@ bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC, return true; } +bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest) { + assert(Src.isLive() && Dest.isLive()); + + [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc(); + const Descriptor *DestDesc = Dest.getFieldDesc(); + + assert(!DestDesc->isPrimitive() && !SrcDesc->isPrimitive()); + + if (DestDesc->isPrimitiveArray()) { + assert(SrcDesc->isPrimitiveArray()); + assert(SrcDesc->getNumElems() == DestDesc->getNumElems()); + PrimType ET = DestDesc->getPrimType(); + 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.initialize(); + }); + } + return true; + } + + if (DestDesc->isRecord()) { + assert(SrcDesc->isRecord()); + assert(SrcDesc->ElemRecord == DestDesc->ElemRecord); + const Record *R = DestDesc->ElemRecord; + for (const Record::Field &F : R->fields()) { + Pointer DestField = Dest.atField(F.Offset); + if (std::optional FT = S.Ctx.classify(F.Decl->getType())) { + TYPE_SWITCH(*FT, { + DestField.deref() = Src.atField(F.Offset).deref(); + DestField.initialize(); + }); + } else { + return Invalid(S, OpPC); + } + } + return true; + } + + // FIXME: Composite types. + + return Invalid(S, OpPC); +} + } // namespace interp } // namespace clang diff --git a/clang/lib/AST/Interp/InterpFrame.cpp b/clang/lib/AST/Interp/InterpFrame.cpp index f69ff06b5e81b5f2d593eade300b851e48cd7462..12e2e6ff9155b9a0ca5a2a5d1142e56903ef329e 100644 --- a/clang/lib/AST/Interp/InterpFrame.cpp +++ b/clang/lib/AST/Interp/InterpFrame.cpp @@ -190,6 +190,8 @@ SourceRange InterpFrame::getCallRange() const { } const FunctionDecl *InterpFrame::getCallee() const { + if (!Func) + return nullptr; return Func->getDecl(); } diff --git a/clang/lib/AST/Interp/InterpFrame.h b/clang/lib/AST/Interp/InterpFrame.h index 322d5dcfa698ae982d01bdbd913ce18120170073..1f80a0a5d2c492320bef1bc68b0b39a56f3c8319 100644 --- a/clang/lib/AST/Interp/InterpFrame.h +++ b/clang/lib/AST/Interp/InterpFrame.h @@ -123,6 +123,9 @@ public: unsigned getDepth() const { return Depth; } + void dump() const { dump(llvm::errs(), 0); } + void dump(llvm::raw_ostream &OS, unsigned Indent = 0) const; + private: /// Returns an original argument from the stack. template const T &stackRef(unsigned Offset) const { diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td index 9b99aa0ccb558a92b4913124c3ca9c72b7701b8b..cc1310f4c0d52aeb0b00ac8fd39acafdcce43fac 100644 --- a/clang/lib/AST/Interp/Opcodes.td +++ b/clang/lib/AST/Interp/Opcodes.td @@ -706,6 +706,7 @@ def Dup : Opcode { // [] -> [] def Invalid : Opcode {} +def Error : Opcode {} def InvalidCast : Opcode { let Args = [ArgCastKind]; } @@ -720,3 +721,5 @@ def CheckNonNullArg : Opcode { let Types = [PtrTypeClass]; let HasGroup = 1; } + +def Memcpy : Opcode; diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp index 3f85635f43674d1e964f441418d8e77c3d6fc23b..af60ced0e10e9ea2a6e4231a6bf34a3c841976d6 100644 --- a/clang/lib/AST/Interp/Pointer.cpp +++ b/clang/lib/AST/Interp/Pointer.cpp @@ -320,10 +320,10 @@ std::optional Pointer::toRValue(const Context &Ctx) const { // Complex types. if (const auto *CT = Ty->getAs()) { QualType ElemTy = CT->getElementType(); - std::optional ElemT = Ctx.classify(ElemTy); - assert(ElemT); if (ElemTy->isIntegerType()) { + std::optional ElemT = Ctx.classify(ElemTy); + assert(ElemT); INT_TYPE_SWITCH(*ElemT, { auto V1 = Ptr.atIndex(0).deref(); auto V2 = Ptr.atIndex(1).deref(); diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h index 34ecdb967960d534370e9dc3b2f32394454eee49..fffb4aba492fc83c8a3082342e324959bd10c151 100644 --- a/clang/lib/AST/Interp/Pointer.h +++ b/clang/lib/AST/Interp/Pointer.h @@ -285,6 +285,11 @@ public: bool inPrimitiveArray() const { return getFieldDesc()->isPrimitiveArray(); } /// Checks if the structure is an array of unknown size. bool isUnknownSizeArray() const { + // If this points inside a dummy block, return true. + // FIXME: This might change in the future. If it does, we need + // to set the proper Ctor/Dtor functions for dummy Descriptors. + if (Base != 0 && Base != sizeof(InlineDescriptor) && isDummy()) + return true; return getFieldDesc()->isUnknownSizeArray(); } /// Checks if the pointer points to an array. diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp index 86e18ede6381147287a5dd349cbe88eb52c8323b..25e938e0150322109fd619eada6970f7b6c09d8f 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/Interp/Program.cpp @@ -145,11 +145,20 @@ std::optional Program::getOrCreateGlobal(const ValueDecl *VD, std::optional Program::getOrCreateDummy(const ValueDecl *VD) { // Dedup blocks since they are immutable and pointers cannot be compared. - if (auto It = DummyParams.find(VD); It != DummyParams.end()) + if (auto It = DummyVariables.find(VD); It != DummyVariables.end()) return It->second; // Create dummy descriptor. - Descriptor *Desc = allocateDescriptor(VD, std::nullopt); + // We create desriptors of 'array of unknown size' if the type is an array + // type _and_ the size isn't known (it's not a ConstantArrayType). If the size + // is known however, we create a regular dummy pointer. + Descriptor *Desc; + if (const auto *AT = VD->getType()->getAsArrayTypeUnsafe(); + AT && !isa(AT)) + Desc = allocateDescriptor(VD, Descriptor::UnknownSize{}); + else + Desc = allocateDescriptor(VD); + // Allocate a block for storage. unsigned I = Globals.size(); @@ -158,7 +167,7 @@ std::optional Program::getOrCreateDummy(const ValueDecl *VD) { G->block()->invokeCtor(); Globals.push_back(G); - DummyParams[VD] = I; + DummyVariables[VD] = I; return I; } @@ -346,7 +355,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty, QualType ElemTy = ArrayType->getElementType(); // Array of well-known bounds. if (auto CAT = dyn_cast(ArrayType)) { - size_t NumElems = CAT->getSize().getZExtValue(); + size_t NumElems = CAT->getZExtSize(); if (std::optional T = Ctx.classify(ElemTy)) { // Arrays of primitives. unsigned ElemSize = primSize(*T); diff --git a/clang/lib/AST/Interp/Program.h b/clang/lib/AST/Interp/Program.h index 50bdb575e805cf61bf1589bacf7489285bbbf666..36b5a1faa513a913e7908a457778ffb204b97eb2 100644 --- a/clang/lib/AST/Interp/Program.h +++ b/clang/lib/AST/Interp/Program.h @@ -208,7 +208,7 @@ private: llvm::DenseMap Records; /// Dummy parameter to generate pointers from. - llvm::DenseMap DummyParams; + llvm::DenseMap DummyVariables; /// Creates a new descriptor. template diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 1b6141580a81d24af468bd0e40794ef5629e88f1..d632c697fa20dbc4e88e15a6715f923020680b19 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -2398,6 +2398,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::Complex: case Type::Adjusted: case Type::Decayed: + case Type::ArrayParameter: case Type::Pointer: case Type::BlockPointer: case Type::LValueReference: @@ -2431,6 +2432,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::MacroQualified: case Type::BitInt: case Type::DependentBitInt: + case Type::CountAttributed: llvm_unreachable("type is illegal as a nested name specifier"); case Type::SubstTemplateTypeParmPack: @@ -3444,6 +3446,7 @@ StringRef CXXNameMangler::getCallingConvQualifierName(CallingConv CC) { case CC_PreserveAll: case CC_M68kRTD: case CC_PreserveNone: + case CC_RISCVVectorCall: // FIXME: we should be mangling all of the above. return ""; @@ -4444,6 +4447,10 @@ void CXXNameMangler::mangleType(const DependentBitIntType *T) { Out << "_"; } +void CXXNameMangler::mangleType(const ArrayParameterType *T) { + mangleType(cast(T)); +} + void CXXNameMangler::mangleIntegerLiteral(QualType T, const llvm::APSInt &Value) { // ::= L E # integer literal diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index e27d44fc2ffe67316d2f4175c4c04856e8ae222e..5861d5a7ea0dd2df6686f4f61f086bf9e58275c5 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -695,7 +695,7 @@ void JSONNodeDumper::VisitArrayType(const ArrayType *AT) { void JSONNodeDumper::VisitConstantArrayType(const ConstantArrayType *CAT) { // FIXME: this should use ZExt instead of SExt, but JSON doesn't allow a // narrowing conversion to int64_t so it cannot be expressed. - JOS.attribute("size", CAT->getSize().getSExtValue()); + JOS.attribute("size", CAT->getSExtSize()); VisitArrayType(CAT); } diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index b272a546573a31bb3bfeee2afd9411779988966d..a0bb04e69c9be8ad244618fb51277344309811a6 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -390,6 +390,7 @@ public: const FunctionDecl *D = nullptr, bool ForceThisQuals = false, bool MangleExceptionSpec = true); + void mangleSourceName(StringRef Name); void mangleNestedName(GlobalDecl GD); private: @@ -408,7 +409,6 @@ private: mangleUnqualifiedName(GD, cast(GD.getDecl())->getDeclName()); } void mangleUnqualifiedName(GlobalDecl GD, DeclarationName Name); - void mangleSourceName(StringRef Name); void mangleOperatorName(OverloadedOperatorKind OO, SourceLocation Loc); void mangleCXXDtorType(CXXDtorType T); void mangleQualifiers(Qualifiers Quals, bool IsMember); @@ -3079,6 +3079,11 @@ void MicrosoftCXXNameMangler::mangleArrayType(const ArrayType *T) { mangleType(ElementTy, SourceRange(), QMM_Escape); } +void MicrosoftCXXNameMangler::mangleType(const ArrayParameterType *T, + Qualifiers, SourceRange) { + mangleArrayType(cast(T)); +} + // ::= // ::= // @@ -3911,7 +3916,8 @@ void MicrosoftMangleContextImpl::mangleReferenceTemporary( msvc_hashing_ostream MHO(Out); MicrosoftCXXNameMangler Mangler(*this, MHO); - Mangler.getStream() << "?$RT" << ManglingNumber << '@'; + Mangler.getStream() << "?"; + Mangler.mangleSourceName("$RT" + llvm::utostr(ManglingNumber)); Mangler.mangle(VD, ""); } @@ -3920,7 +3926,8 @@ void MicrosoftMangleContextImpl::mangleThreadSafeStaticGuardVariable( msvc_hashing_ostream MHO(Out); MicrosoftCXXNameMangler Mangler(*this, MHO); - Mangler.getStream() << "?$TSS" << GuardNum << '@'; + Mangler.getStream() << "?"; + Mangler.mangleSourceName("$TSS" + llvm::utostr(GuardNum)); Mangler.mangleNestedName(VD); Mangler.getStream() << "@4HA"; } @@ -4021,10 +4028,8 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL, // char bar[42] = "foobar"; // Where it is truncated or zero-padded to fit the array. This is the length // used for mangling, and any trailing null-bytes also need to be mangled. - unsigned StringLength = getASTContext() - .getAsConstantArrayType(SL->getType()) - ->getSize() - .getZExtValue(); + unsigned StringLength = + getASTContext().getAsConstantArrayType(SL->getType())->getZExtSize(); unsigned StringByteLength = StringLength * SL->getCharByteWidth(); // : The "kind" of string literal is encoded into the mangled name. diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 2dbc259138a897d46db6e76df532df62a4dda2e0..e159a1b00be552bab566c07313ff64264f9951ff 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -944,6 +944,10 @@ public: VisitArrayType(T); } + void VisitArrayParameterType(const ArrayParameterType *T) { + VisitConstantArrayType(T); + } + void VisitDependentSizedArrayType(const DependentSizedArrayType *T) { AddStmt(T->getSizeExpr()); VisitArrayType(T); diff --git a/clang/lib/AST/ScanfFormatString.cpp b/clang/lib/AST/ScanfFormatString.cpp index 64c430e623b577e1101f5807bea2d57b95b8ec56..7ee21c8c619544009c454cae8940832b2a40a967 100644 --- a/clang/lib/AST/ScanfFormatString.cpp +++ b/clang/lib/AST/ScanfFormatString.cpp @@ -448,9 +448,7 @@ bool ScanfSpecifier::fixType(QualType QT, QualType RawQT, if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(RawQT)) { if (CAT->getSizeModifier() == ArraySizeModifier::Normal) FieldWidth = OptionalAmount(OptionalAmount::Constant, - CAT->getSize().getZExtValue() - 1, - "", 0, false); - + CAT->getZExtSize() - 1, "", 0, false); } return true; } diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index b683eb1edd8f136eb9c878ce995a635f1685a721..413e452146bdb27ce55478e034b330302634e50a 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1990,6 +1990,19 @@ void TextNodeDumper::VisitFunctionDecl(const FunctionDecl *D) { } } +void TextNodeDumper::VisitCXXDeductionGuideDecl( + const CXXDeductionGuideDecl *D) { + VisitFunctionDecl(D); + switch (D->getDeductionCandidateKind()) { + case DeductionCandidate::Normal: + case DeductionCandidate::Copy: + return; + case DeductionCandidate::Aggregate: + OS << " aggregate "; + break; + } +} + void TextNodeDumper::VisitLifetimeExtendedTemporaryDecl( const LifetimeExtendedTemporaryDecl *D) { OS << " extended by "; diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 22666184c56ccfc9579fb2b6d28eb49c165e667d..cb22c91a12aa8911b9c487e7044f3032ef5c9654 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -159,6 +159,22 @@ ArrayType::ArrayType(TypeClass tc, QualType et, QualType can, ArrayTypeBits.SizeModifier = llvm::to_underlying(sm); } +ConstantArrayType * +ConstantArrayType::Create(const ASTContext &Ctx, QualType ET, QualType Can, + const llvm::APInt &Sz, const Expr *SzExpr, + ArraySizeModifier SzMod, unsigned Qual) { + bool NeedsExternalSize = SzExpr != nullptr || Sz.ugt(0x0FFFFFFFFFFFFFFF) || + Sz.getBitWidth() > 0xFF; + if (!NeedsExternalSize) + return new (Ctx, alignof(ConstantArrayType)) ConstantArrayType( + ET, Can, Sz.getBitWidth(), Sz.getZExtValue(), SzMod, Qual); + + auto *SzPtr = new (Ctx, alignof(ConstantArrayType::ExternalSize)) + ConstantArrayType::ExternalSize(Sz, SzExpr); + return new (Ctx, alignof(ConstantArrayType)) + ConstantArrayType(ET, Can, SzPtr, SzMod, Qual); +} + unsigned ConstantArrayType::getNumAddressingBits(const ASTContext &Context, QualType ElementType, const llvm::APInt &NumElements) { @@ -213,11 +229,10 @@ unsigned ConstantArrayType::getMaxSizeBits(const ASTContext &Context) { void ConstantArrayType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, QualType ET, - const llvm::APInt &ArraySize, - const Expr *SizeExpr, ArraySizeModifier SizeMod, - unsigned TypeQuals) { + uint64_t ArraySize, const Expr *SizeExpr, + ArraySizeModifier SizeMod, unsigned TypeQuals) { ID.AddPointer(ET.getAsOpaquePtr()); - ID.AddInteger(ArraySize.getZExtValue()); + ID.AddInteger(ArraySize); ID.AddInteger(llvm::to_underlying(SizeMod)); ID.AddInteger(TypeQuals); ID.AddBoolean(SizeExpr != nullptr); @@ -385,6 +400,26 @@ void DependentBitIntType::Profile(llvm::FoldingSetNodeID &ID, NumBitsExpr->Profile(ID, Context, true); } +bool BoundsAttributedType::referencesFieldDecls() const { + return llvm::any_of(dependent_decls(), + [](const TypeCoupledDeclRefInfo &Info) { + return isa(Info.getDecl()); + }); +} + +void CountAttributedType::Profile(llvm::FoldingSetNodeID &ID, + QualType WrappedTy, Expr *CountExpr, + bool CountInBytes, bool OrNull) { + ID.AddPointer(WrappedTy.getAsOpaquePtr()); + ID.AddBoolean(CountInBytes); + ID.AddBoolean(OrNull); + // We profile it as a pointer as the StmtProfiler considers parameter + // expressions on function declaration and function definition as the + // same, resulting in count expression being evaluated with ParamDecl + // not in the function scope. + ID.AddPointer(CountExpr); +} + /// getArrayElementTypeNoTypeQual - If this is an array type, return the /// element type of the array, potentially with type qualifiers missing. /// This method should never be used when type qualifiers are meaningful. @@ -432,12 +467,8 @@ QualType QualType::getSingleStepDesugaredTypeImpl(QualType type, // Check that no type class has a non-trival destructor. Types are // allocated with the BumpPtrAllocator from ASTContext and therefore // their destructor is not executed. -// -// FIXME: ConstantArrayType is not trivially destructible because of its -// APInt member. It should be replaced in favor of ASTContext allocation. #define TYPE(CLASS, BASE) \ - static_assert(std::is_trivially_destructible::value || \ - std::is_same::value, \ + static_assert(std::is_trivially_destructible::value, \ #CLASS "Type should be trivially destructible!"); #include "clang/AST/TypeNodes.inc" @@ -559,6 +590,14 @@ template <> const AttributedType *Type::getAs() const { return getAsSugar(this); } +template <> const BoundsAttributedType *Type::getAs() const { + return getAsSugar(this); +} + +template <> const CountAttributedType *Type::getAs() const { + return getAsSugar(this); +} + /// getUnqualifiedDesugaredType - Pull any qualifiers and syntactic /// sugar off the given type. This should produce an object of the /// same dynamic type as the canonical type. @@ -641,6 +680,10 @@ bool Type::isScopedEnumeralType() const { return false; } +bool Type::isCountAttributedType() const { + return getAs(); +} + const ComplexType *Type::getAsComplexIntegerType() const { if (const auto *Complex = getAs()) if (Complex->getElementType()->isIntegerType()) @@ -1154,6 +1197,14 @@ public: return Ctx.getDecayedType(originalType); } + QualType VisitArrayParameterType(const ArrayParameterType *T) { + QualType ArrTy = VisitConstantArrayType(T); + if (ArrTy.isNull()) + return {}; + + return Ctx.getArrayParameterType(ArrTy); + } + SUGARED_TYPE_CLASS(TypeOfExpr) SUGARED_TYPE_CLASS(TypeOf) SUGARED_TYPE_CLASS(Decltype) @@ -3441,6 +3492,9 @@ StringRef FunctionType::getNameForCallConv(CallingConv CC) { case CC_PreserveAll: return "preserve_all"; case CC_M68kRTD: return "m68k_rtd"; case CC_PreserveNone: return "preserve_none"; + // clang-format off + case CC_RISCVVectorCall: return "riscv_vector_cc"; + // clang-format on } llvm_unreachable("Invalid calling convention."); @@ -3709,6 +3763,43 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, getExtProtoInfo(), Ctx, isCanonicalUnqualified()); } +TypeCoupledDeclRefInfo::TypeCoupledDeclRefInfo(ValueDecl *D, bool Deref) + : Data(D, Deref << DerefShift) {} + +bool TypeCoupledDeclRefInfo::isDeref() const { + return Data.getInt() & DerefMask; +} +ValueDecl *TypeCoupledDeclRefInfo::getDecl() const { return Data.getPointer(); } +unsigned TypeCoupledDeclRefInfo::getInt() const { return Data.getInt(); } +void *TypeCoupledDeclRefInfo::getOpaqueValue() const { + return Data.getOpaqueValue(); +} +bool TypeCoupledDeclRefInfo::operator==( + const TypeCoupledDeclRefInfo &Other) const { + return getOpaqueValue() == Other.getOpaqueValue(); +} +void TypeCoupledDeclRefInfo::setFromOpaqueValue(void *V) { + Data.setFromOpaqueValue(V); +} + +BoundsAttributedType::BoundsAttributedType(TypeClass TC, QualType Wrapped, + QualType Canon) + : Type(TC, Canon, Wrapped->getDependence()), WrappedTy(Wrapped) {} + +CountAttributedType::CountAttributedType( + QualType Wrapped, QualType Canon, Expr *CountExpr, bool CountInBytes, + bool OrNull, ArrayRef CoupledDecls) + : BoundsAttributedType(CountAttributed, Wrapped, Canon), + CountExpr(CountExpr) { + CountAttributedTypeBits.NumCoupledDecls = CoupledDecls.size(); + CountAttributedTypeBits.CountInBytes = CountInBytes; + CountAttributedTypeBits.OrNull = OrNull; + auto *DeclSlot = getTrailingObjects(); + Decls = llvm::ArrayRef(DeclSlot, CoupledDecls.size()); + for (unsigned i = 0; i != CoupledDecls.size(); ++i) + DeclSlot[i] = CoupledDecls[i]; +} + TypedefType::TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType Underlying, QualType can) : Type(tc, can, toSemanticDependence(can->getDependence())), @@ -3994,6 +4085,7 @@ bool AttributedType::isCallingConv() const { case attr::PreserveAll: case attr::M68kRTD: case attr::PreserveNone: + case attr::RISCVVectorCC: return true; } llvm_unreachable("invalid attr kind"); @@ -4370,6 +4462,7 @@ static CachedProperties computeCachedProperties(const Type *T) { case Type::ConstantArray: case Type::IncompleteArray: case Type::VariableArray: + case Type::ArrayParameter: return Cache::get(cast(T)->getElementType()); case Type::Vector: case Type::ExtVector: @@ -4458,6 +4551,7 @@ LinkageInfo LinkageComputer::computeTypeLinkageInfo(const Type *T) { case Type::ConstantArray: case Type::IncompleteArray: case Type::VariableArray: + case Type::ArrayParameter: return computeTypeLinkageInfo(cast(T)->getElementType()); case Type::Vector: case Type::ExtVector: @@ -4558,16 +4652,15 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { case Type::Auto: return ResultIfUnknown; - // Dependent template specializations can instantiate to pointer - // types unless they're known to be specializations of a class - // template. + // Dependent template specializations could instantiate to pointer types. case Type::TemplateSpecialization: - if (TemplateDecl *templateDecl - = cast(type.getTypePtr()) - ->getTemplateName().getAsTemplateDecl()) { - if (isa(templateDecl)) - return false; - } + // If it's a known class template, we can already check if it's nullable. + if (TemplateDecl *templateDecl = + cast(type.getTypePtr()) + ->getTemplateName() + .getAsTemplateDecl()) + if (auto *CTD = dyn_cast(templateDecl)) + return CTD->getTemplatedDecl()->hasAttr(); return ResultIfUnknown; case Type::Builtin: @@ -4624,6 +4717,17 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { } llvm_unreachable("unknown builtin type"); + case Type::Record: { + const RecordDecl *RD = cast(type)->getDecl(); + // For template specializations, look only at primary template attributes. + // This is a consistent regardless of whether the instantiation is known. + if (const auto *CTSD = dyn_cast(RD)) + return CTSD->getSpecializedTemplate() + ->getTemplatedDecl() + ->hasAttr(); + return RD->hasAttr(); + } + // Non-pointer types. case Type::Complex: case Type::LValueReference: @@ -4641,7 +4745,6 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { case Type::DependentAddressSpace: case Type::FunctionProto: case Type::FunctionNoProto: - case Type::Record: case Type::DeducedTemplateSpecialization: case Type::Enum: case Type::InjectedClassName: @@ -4652,6 +4755,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const { case Type::Pipe: case Type::BitInt: case Type::DependentBitInt: + case Type::ArrayParameter: return false; } llvm_unreachable("bad type kind!"); diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp index b0acb182308755b630afaa73e936db2d41cf3372..21e152f6aea8a0e1cc03418c8a6e582b7dadafcf 100644 --- a/clang/lib/AST/TypeLoc.cpp +++ b/clang/lib/AST/TypeLoc.cpp @@ -516,6 +516,10 @@ SourceRange AttributedTypeLoc::getLocalSourceRange() const { return getAttr() ? getAttr()->getRange() : SourceRange(); } +SourceRange CountAttributedTypeLoc::getLocalSourceRange() const { + return getCountExpr() ? getCountExpr()->getSourceRange() : SourceRange(); +} + SourceRange BTFTagAttributedTypeLoc::getLocalSourceRange() const { return getAttr() ? getAttr()->getRange() : SourceRange(); } diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 7dcc4348f8e036d9319887037c991fc7e20f756f..9d551ff83151fd752ca7544cc11ffdf639d62061 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -268,6 +268,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::Adjusted: case Type::Decayed: + case Type::ArrayParameter: case Type::Pointer: case Type::BlockPointer: case Type::LValueReference: @@ -286,6 +287,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::PackExpansion: case Type::SubstTemplateTypeParm: case Type::MacroQualified: + case Type::CountAttributed: CanPrefixQualifiers = false; break; @@ -537,7 +539,7 @@ void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T, if (T->getSizeModifier() == ArraySizeModifier::Static) OS << "static "; - OS << T->getSize().getZExtValue() << ']'; + OS << T->getZExtSize() << ']'; printAfter(T->getElementType(), OS); } @@ -594,6 +596,16 @@ void TypePrinter::printDecayedBefore(const DecayedType *T, raw_ostream &OS) { printAdjustedBefore(T, OS); } +void TypePrinter::printArrayParameterAfter(const ArrayParameterType *T, + raw_ostream &OS) { + printConstantArrayAfter(T, OS); +} + +void TypePrinter::printArrayParameterBefore(const ArrayParameterType *T, + raw_ostream &OS) { + printConstantArrayBefore(T, OS); +} + void TypePrinter::printDecayedAfter(const DecayedType *T, raw_ostream &OS) { printAdjustedAfter(T, OS); } @@ -1070,6 +1082,9 @@ void TypePrinter::printFunctionAfter(const FunctionType::ExtInfo &Info, case CC_PreserveNone: OS << " __attribute__((preserve_none))"; break; + case CC_RISCVVectorCall: + OS << "__attribute__((riscv_vector_cc))"; + break; } } @@ -1635,6 +1650,17 @@ void TypePrinter::printElaboratedBefore(const ElaboratedType *T, if (T->getKeyword() != ElaboratedTypeKeyword::None) OS << " "; NestedNameSpecifier *Qualifier = T->getQualifier(); + if (!Policy.SuppressTagKeyword && Policy.SuppressScope && + !Policy.SuppressUnwrittenScope) { + bool OldTagKeyword = Policy.SuppressTagKeyword; + bool OldSupressScope = Policy.SuppressScope; + Policy.SuppressTagKeyword = true; + Policy.SuppressScope = false; + printBefore(T->getNamedType(), OS); + Policy.SuppressTagKeyword = OldTagKeyword; + Policy.SuppressScope = OldSupressScope; + return; + } if (Qualifier) Qualifier->print(OS, Policy); } @@ -1717,6 +1743,36 @@ void TypePrinter::printPackExpansionAfter(const PackExpansionType *T, OS << "..."; } +static void printCountAttributedImpl(const CountAttributedType *T, + raw_ostream &OS, + const PrintingPolicy &Policy) { + if (T->isCountInBytes() && T->isOrNull()) + OS << " __sized_by_or_null("; + else if (T->isCountInBytes()) + OS << " __sized_by("; + else if (T->isOrNull()) + OS << " __counted_by_or_null("; + else + OS << " __counted_by("; + if (T->getCountExpr()) + T->getCountExpr()->printPretty(OS, nullptr, Policy); + OS << ')'; +} + +void TypePrinter::printCountAttributedBefore(const CountAttributedType *T, + raw_ostream &OS) { + printBefore(T->desugar(), OS); + if (!T->desugar()->isArrayType()) + printCountAttributedImpl(T, OS, Policy); +} + +void TypePrinter::printCountAttributedAfter(const CountAttributedType *T, + raw_ostream &OS) { + printAfter(T->desugar(), OS); + if (T->desugar()->isArrayType()) + printCountAttributedImpl(T, OS, Policy); +} + void TypePrinter::printAttributedBefore(const AttributedType *T, raw_ostream &OS) { // FIXME: Generate this with TableGen. @@ -1847,6 +1903,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, // AttributedType nodes for them. break; + case attr::CountedBy: case attr::LifetimeBound: case attr::TypeNonNull: case attr::TypeNullable: @@ -1917,6 +1974,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case attr::PreserveNone: OS << "preserve_none"; break; + case attr::RISCVVectorCC: + OS << "riscv_vector_cc"; + break; case attr::NoDeref: OS << "noderef"; break; diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index de70cbbf6cdb3801709cced4e36e2c1bd1859c8e..64e6155de090c5f3e0626968485ca104baa00f9e 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -2039,7 +2039,7 @@ void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) { QualType QT = FI->getType(); // It may be a multidimensional array. while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { - if (AT->getSize() == 0) + if (AT->isZeroSize()) break; QT = AT->getElementType(); } @@ -2133,7 +2133,7 @@ bool CFGBuilder::hasTrivialDestructor(const VarDecl *VD) const { // Check for constant size array. Set type to array element type. while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) { - if (AT->getSize() == 0) + if (AT->isZeroSize()) return true; QT = AT->getElementType(); } diff --git a/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp b/clang/lib/Analysis/FlowSensitive/AdornedCFG.cpp similarity index 88% rename from clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp rename to clang/lib/Analysis/FlowSensitive/AdornedCFG.cpp index 7c9f8fbb0a7009cfa6bc5587cc7a25b67062f358..255543021a998c9dcb1801b9821b0ae37bd1bf14 100644 --- a/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp +++ b/clang/lib/Analysis/FlowSensitive/AdornedCFG.cpp @@ -1,4 +1,4 @@ -//===- ControlFlowContext.cpp ---------------------------------------------===// +//===- AdornedCFG.cpp ---------------------------------------------===// // // 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,12 @@ // //===----------------------------------------------------------------------===// // -// This file defines a ControlFlowContext class that is used by dataflow -// analyses that run over Control-Flow Graphs (CFGs). +// This file defines an `AdornedCFG` class that is used by dataflow analyses +// that run over Control-Flow Graphs (CFGs). // //===----------------------------------------------------------------------===// -#include "clang/Analysis/FlowSensitive/ControlFlowContext.h" +#include "clang/Analysis/FlowSensitive/AdornedCFG.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/Stmt.h" @@ -103,7 +103,7 @@ buildContainsExprConsumedInDifferentBlock( auto CheckChildExprs = [&Result, &StmtToBlock](const Stmt *S, const CFGBlock *Block) { for (const Stmt *Child : S->children()) { - if (!isa(Child)) + if (!isa_and_nonnull(Child)) continue; const CFGBlock *ChildBlock = StmtToBlock.lookup(Child); if (ChildBlock != Block) @@ -126,8 +126,7 @@ buildContainsExprConsumedInDifferentBlock( return Result; } -llvm::Expected -ControlFlowContext::build(const FunctionDecl &Func) { +llvm::Expected AdornedCFG::build(const FunctionDecl &Func) { if (!Func.doesThisDeclarationHaveABody()) return llvm::createStringError( std::make_error_code(std::errc::invalid_argument), @@ -136,8 +135,8 @@ ControlFlowContext::build(const FunctionDecl &Func) { return build(Func, *Func.getBody(), Func.getASTContext()); } -llvm::Expected -ControlFlowContext::build(const Decl &D, Stmt &S, ASTContext &C) { +llvm::Expected AdornedCFG::build(const Decl &D, Stmt &S, + ASTContext &C) { if (D.isTemplated()) return llvm::createStringError( std::make_error_code(std::errc::invalid_argument), @@ -145,7 +144,7 @@ ControlFlowContext::build(const Decl &D, Stmt &S, ASTContext &C) { // The shape of certain elements of the AST can vary depending on the // language. We currently only support C++. - if (!C.getLangOpts().CPlusPlus) + if (!C.getLangOpts().CPlusPlus || C.getLangOpts().ObjC) return llvm::createStringError( std::make_error_code(std::errc::invalid_argument), "Can only analyze C++"); @@ -175,9 +174,9 @@ ControlFlowContext::build(const Decl &D, Stmt &S, ASTContext &C) { llvm::DenseSet ContainsExprConsumedInDifferentBlock = buildContainsExprConsumedInDifferentBlock(*Cfg, StmtToBlock); - return ControlFlowContext(D, std::move(Cfg), std::move(StmtToBlock), - std::move(BlockReachable), - std::move(ContainsExprConsumedInDifferentBlock)); + return AdornedCFG(D, std::move(Cfg), std::move(StmtToBlock), + std::move(BlockReachable), + std::move(ContainsExprConsumedInDifferentBlock)); } } // namespace dataflow diff --git a/clang/lib/Analysis/FlowSensitive/CMakeLists.txt b/clang/lib/Analysis/FlowSensitive/CMakeLists.txt index 5af4ecfc9efa5dadd0f1572a1934fa04bca72ed0..a3b5d9adc24bda39aa7197aa5267c30a5487752d 100644 --- a/clang/lib/Analysis/FlowSensitive/CMakeLists.txt +++ b/clang/lib/Analysis/FlowSensitive/CMakeLists.txt @@ -1,6 +1,6 @@ add_clang_library(clangAnalysisFlowSensitive + AdornedCFG.cpp Arena.cpp - ControlFlowContext.cpp DataflowAnalysisContext.cpp DataflowEnvironment.cpp Formula.cpp diff --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp index f4c4af022f51f6be672127da84eb4c73f363180d..d520539dd2535541d3161e1602fdb199a5338ad0 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp @@ -288,8 +288,8 @@ void DataflowAnalysisContext::dumpFlowCondition(Atom Token, } } -const ControlFlowContext * -DataflowAnalysisContext::getControlFlowContext(const FunctionDecl *F) { +const AdornedCFG * +DataflowAnalysisContext::getAdornedCFG(const FunctionDecl *F) { // Canonicalize the key: F = F->getDefinition(); if (F == nullptr) @@ -299,10 +299,10 @@ DataflowAnalysisContext::getControlFlowContext(const FunctionDecl *F) { return &It->second; if (F->doesThisDeclarationHaveABody()) { - auto CFCtx = ControlFlowContext::build(*F); + auto ACFG = AdornedCFG::build(*F); // FIXME: Handle errors. - assert(CFCtx); - auto Result = FunctionContexts.insert({F, std::move(*CFCtx)}); + assert(ACFG); + auto Result = FunctionContexts.insert({F, std::move(*ACFG)}); return &Result.first->second; } diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 1d2bd9a9b08af363c0db33bc1523c40878f08fae..f729d676dd0de8c0d06d0dc71efd4908828b3d1c 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -416,7 +416,7 @@ void Environment::initialize() { assert(Parent != nullptr); if (Parent->isLambda()) { - for (auto Capture : Parent->captures()) { + for (const auto &Capture : Parent->captures()) { if (Capture.capturesVariable()) { const auto *VarDecl = Capture.getCapturedVar(); assert(VarDecl != nullptr); @@ -771,6 +771,7 @@ static bool isOriginalRecordConstructor(const Expr &RecordPRValue) { return !Init->isSemanticForm() || !Init->isTransparent(); return isa(RecordPRValue) || isa(RecordPRValue) || isa(RecordPRValue) || + isa(RecordPRValue) || isa(RecordPRValue) || // The framework currently does not propagate the objects created in // the two branches of a `ConditionalOperator` because there is no way @@ -1168,6 +1169,42 @@ getFieldsForInitListExpr(const InitListExpr *InitList) { return Fields; } +RecordInitListHelper::RecordInitListHelper(const InitListExpr *InitList) { + auto *RD = InitList->getType()->getAsCXXRecordDecl(); + assert(RD != nullptr); + + std::vector Fields = getFieldsForInitListExpr(InitList); + ArrayRef Inits = InitList->inits(); + + // Unions initialized with an empty initializer list need special treatment. + // For structs/classes initialized with an empty initializer list, Clang + // puts `ImplicitValueInitExpr`s in `InitListExpr::inits()`, but for unions, + // it doesn't do this -- so we create an `ImplicitValueInitExpr` ourselves. + SmallVector InitsForUnion; + if (InitList->getType()->isUnionType() && Inits.empty()) { + assert(Fields.size() == 1); + ImplicitValueInitForUnion.emplace(Fields.front()->getType()); + InitsForUnion.push_back(&*ImplicitValueInitForUnion); + Inits = InitsForUnion; + } + + size_t InitIdx = 0; + + assert(Fields.size() + RD->getNumBases() == Inits.size()); + for (const CXXBaseSpecifier &Base : RD->bases()) { + assert(InitIdx < Inits.size()); + Expr *Init = Inits[InitIdx++]; + BaseInits.emplace_back(&Base, Init); + } + + assert(Fields.size() == Inits.size() - InitIdx); + for (const FieldDecl *Field : Fields) { + assert(InitIdx < Inits.size()); + Expr *Init = Inits[InitIdx++]; + FieldInits.emplace_back(Field, Init); + } +} + RecordValue &refreshRecordValue(RecordStorageLocation &Loc, Environment &Env) { auto &NewVal = Env.create(Loc); Env.setValue(Loc, NewVal); diff --git a/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp b/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp index 6afd66d9dc6ac57c291ee76e3fda11010e5da9d8..397a8d87e114d7a90214f4bad99fb307ee605d3b 100644 --- a/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp +++ b/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp @@ -54,7 +54,7 @@ // //===----------------------------------------------------------------------===// -#include "clang/Analysis/FlowSensitive/ControlFlowContext.h" +#include "clang/Analysis/FlowSensitive/AdornedCFG.h" #include "clang/Analysis/FlowSensitive/DebugSupport.h" #include "clang/Analysis/FlowSensitive/Logger.h" #include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h" @@ -162,7 +162,7 @@ class HTMLLogger : public Logger { llvm::raw_string_ostream JStringStream{JSON}; llvm::json::OStream JOS{JStringStream, /*Indent=*/2}; - const ControlFlowContext *CFC; + const AdornedCFG *ACFG; // Timeline of iterations of CFG block visitation. std::vector Iters; // Indexes in `Iters` of the iterations for each block. @@ -176,15 +176,15 @@ class HTMLLogger : public Logger { public: explicit HTMLLogger(StreamFactory Streams) : Streams(std::move(Streams)) {} - void beginAnalysis(const ControlFlowContext &CFC, + void beginAnalysis(const AdornedCFG &ACFG, TypeErasedDataflowAnalysis &A) override { OS = Streams(); - this->CFC = &CFC; + this->ACFG = &ACFG; *OS << llvm::StringRef(HTMLLogger_html).split("").first; - BlockConverged.resize(CFC.getCFG().getNumBlockIDs()); + BlockConverged.resize(ACFG.getCFG().getNumBlockIDs()); - const auto &D = CFC.getDecl(); + const auto &D = ACFG.getDecl(); const auto &SM = A.getASTContext().getSourceManager(); *OS << ""; if (const auto *ND = dyn_cast<NamedDecl>(&D)) @@ -345,7 +345,7 @@ private: // tokens are associated with, and even which BB element (so that clicking // can select the right element). void writeCode() { - const auto &AST = CFC->getDecl().getASTContext(); + const auto &AST = ACFG->getDecl().getASTContext(); bool Invalid = false; // Extract the source code from the original file. @@ -353,7 +353,7 @@ private: // indentation to worry about), but we need the boundaries of particular // AST nodes and the printer doesn't provide this. auto Range = clang::Lexer::makeFileCharRange( - CharSourceRange::getTokenRange(CFC->getDecl().getSourceRange()), + CharSourceRange::getTokenRange(ACFG->getDecl().getSourceRange()), AST.getSourceManager(), AST.getLangOpts()); if (Range.isInvalid()) return; @@ -419,7 +419,7 @@ private: // Construct one TokenInfo per character in a flat array. // This is inefficient (chars in a token all have the same info) but simple. std::vector<TokenInfo> State(Code.size()); - for (const auto *Block : CFC->getCFG()) { + for (const auto *Block : ACFG->getCFG()) { unsigned EltIndex = 0; for (const auto& Elt : *Block) { ++EltIndex; @@ -480,7 +480,7 @@ private: // out to `dot` to turn it into an SVG. void writeCFG() { *OS << "<template data-copy='cfg'>\n"; - if (auto SVG = renderSVG(buildCFGDot(CFC->getCFG()))) + if (auto SVG = renderSVG(buildCFGDot(ACFG->getCFG()))) *OS << *SVG; else *OS << "Can't draw CFG: " << toString(SVG.takeError()); diff --git a/clang/lib/Analysis/FlowSensitive/Logger.cpp b/clang/lib/Analysis/FlowSensitive/Logger.cpp index 8c401df62e4459ca93ee9f37b0b0c136c9476c6b..8f40768171c94e8ca3b1a7644ab600df91734abc 100644 --- a/clang/lib/Analysis/FlowSensitive/Logger.cpp +++ b/clang/lib/Analysis/FlowSensitive/Logger.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/FlowSensitive/Logger.h" -#include "clang/Analysis/FlowSensitive/ControlFlowContext.h" +#include "clang/Analysis/FlowSensitive/AdornedCFG.h" #include "clang/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.h" #include "llvm/Support/WithColor.h" @@ -33,17 +33,17 @@ struct TextualLogger final : Logger { TextualLogger(llvm::raw_ostream &OS) : OS(OS), ShowColors(llvm::WithColor::defaultAutoDetectFunction()(OS)) {} - virtual void beginAnalysis(const ControlFlowContext &CFG, + virtual void beginAnalysis(const AdornedCFG &ACFG, TypeErasedDataflowAnalysis &Analysis) override { { llvm::WithColor Header(OS, llvm::raw_ostream::Colors::RED, /*Bold=*/true); OS << "=== Beginning data flow analysis ===\n"; } - auto &D = CFG.getDecl(); + auto &D = ACFG.getDecl(); D.print(OS); OS << "\n"; D.dump(OS); - CurrentCFG = &CFG.getCFG(); + CurrentCFG = &ACFG.getCFG(); CurrentCFG->print(OS, Analysis.getASTContext().getLangOpts(), ShowColors); CurrentAnalysis = &Analysis; } diff --git a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp index 1d31b22b6d25ff305f098160340471a50a333e4d..cadb1ceb2d850733829a9d18e1a0ddef67e80946 100644 --- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp +++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp @@ -64,39 +64,125 @@ static bool hasOptionalClassName(const CXXRecordDecl &RD) { return false; } +static const CXXRecordDecl *getOptionalBaseClass(const CXXRecordDecl *RD) { + if (RD == nullptr) + return nullptr; + if (hasOptionalClassName(*RD)) + return RD; + + if (!RD->hasDefinition()) + return nullptr; + + for (const CXXBaseSpecifier &Base : RD->bases()) + if (const CXXRecordDecl *BaseClass = + getOptionalBaseClass(Base.getType()->getAsCXXRecordDecl())) + return BaseClass; + + return nullptr; +} + namespace { using namespace ::clang::ast_matchers; using LatticeTransferState = TransferState<NoopLattice>; -AST_MATCHER(CXXRecordDecl, hasOptionalClassNameMatcher) { - return hasOptionalClassName(Node); +AST_MATCHER(CXXRecordDecl, optionalClass) { return hasOptionalClassName(Node); } + +AST_MATCHER(CXXRecordDecl, optionalOrDerivedClass) { + return getOptionalBaseClass(&Node) != nullptr; } -DeclarationMatcher optionalClass() { - return classTemplateSpecializationDecl( - hasOptionalClassNameMatcher(), - hasTemplateArgument(0, refersToType(type().bind("T")))); +auto desugarsToOptionalType() { + return hasUnqualifiedDesugaredType( + recordType(hasDeclaration(cxxRecordDecl(optionalClass())))); } -auto optionalOrAliasType() { +auto desugarsToOptionalOrDerivedType() { return hasUnqualifiedDesugaredType( - recordType(hasDeclaration(optionalClass()))); + recordType(hasDeclaration(cxxRecordDecl(optionalOrDerivedClass())))); +} + +auto hasOptionalType() { return hasType(desugarsToOptionalType()); } + +/// Matches any of the spellings of the optional types and sugar, aliases, +/// derived classes, etc. +auto hasOptionalOrDerivedType() { + return hasType(desugarsToOptionalOrDerivedType()); +} + +QualType getPublicType(const Expr *E) { + auto *Cast = dyn_cast<ImplicitCastExpr>(E->IgnoreParens()); + if (Cast == nullptr || Cast->getCastKind() != CK_UncheckedDerivedToBase) { + QualType Ty = E->getType(); + if (Ty->isPointerType()) + return Ty->getPointeeType(); + return Ty; + } + + // Is the derived type that we're casting from the type of `*this`? In this + // special case, we can upcast to the base class even if the base is + // non-public. + bool CastingFromThis = isa<CXXThisExpr>(Cast->getSubExpr()); + + // Find the least-derived type in the path (i.e. the last entry in the list) + // that we can access. + const CXXBaseSpecifier *PublicBase = nullptr; + for (const CXXBaseSpecifier *Base : Cast->path()) { + if (Base->getAccessSpecifier() != AS_public && !CastingFromThis) + break; + PublicBase = Base; + CastingFromThis = false; + } + + if (PublicBase != nullptr) + return PublicBase->getType(); + + // We didn't find any public type that we could cast to. There may be more + // casts in `getSubExpr()`, so recurse. (If there aren't any more casts, this + // will return the type of `getSubExpr()`.) + return getPublicType(Cast->getSubExpr()); } -/// Matches any of the spellings of the optional types and sugar, aliases, etc. -auto hasOptionalType() { return hasType(optionalOrAliasType()); } +// Returns the least-derived type for the receiver of `MCE` that +// `MCE.getImplicitObjectArgument()->IgnoreParentImpCasts()` can be downcast to. +// Effectively, we upcast until we reach a non-public base class, unless that +// base is a base of `*this`. +// +// This is needed to correctly match methods called on types derived from +// `std::optional`. +// +// Say we have a `struct Derived : public std::optional<int> {} d;` For a call +// `d.has_value()`, the `getImplicitObjectArgument()` looks like this: +// +// ImplicitCastExpr 'const std::__optional_storage_base<int>' lvalue +// | <UncheckedDerivedToBase (optional -> __optional_storage_base)> +// `-DeclRefExpr 'Derived' lvalue Var 'd' 'Derived' +// +// The type of the implicit object argument is `__optional_storage_base` +// (since this is the internal type that `has_value()` is declared on). If we +// call `IgnoreParenImpCasts()` on the implicit object argument, we get the +// `DeclRefExpr`, which has type `Derived`. Neither of these types is +// `optional`, and hence neither is sufficient for querying whether we are +// calling a method on `optional`. +// +// Instead, starting with the most derived type, we need to follow the chain of +// casts +QualType getPublicReceiverType(const CXXMemberCallExpr &MCE) { + return getPublicType(MCE.getImplicitObjectArgument()); +} + +AST_MATCHER_P(CXXMemberCallExpr, publicReceiverType, + ast_matchers::internal::Matcher<QualType>, InnerMatcher) { + return InnerMatcher.matches(getPublicReceiverType(Node), Finder, Builder); +} auto isOptionalMemberCallWithNameMatcher( ast_matchers::internal::Matcher<NamedDecl> matcher, const std::optional<StatementMatcher> &Ignorable = std::nullopt) { - auto Exception = unless(Ignorable ? expr(anyOf(*Ignorable, cxxThisExpr())) - : cxxThisExpr()); - return cxxMemberCallExpr( - on(expr(Exception, - anyOf(hasOptionalType(), - hasType(pointerType(pointee(optionalOrAliasType())))))), - callee(cxxMethodDecl(matcher))); + return cxxMemberCallExpr(Ignorable ? on(expr(unless(*Ignorable))) + : anything(), + publicReceiverType(desugarsToOptionalType()), + callee(cxxMethodDecl(matcher))); } auto isOptionalOperatorCallWithName( @@ -129,49 +215,51 @@ auto inPlaceClass() { auto isOptionalNulloptConstructor() { return cxxConstructExpr( - hasOptionalType(), hasDeclaration(cxxConstructorDecl(parameterCountIs(1), - hasParameter(0, hasNulloptType())))); + hasParameter(0, hasNulloptType()))), + hasOptionalOrDerivedType()); } auto isOptionalInPlaceConstructor() { - return cxxConstructExpr(hasOptionalType(), - hasArgument(0, hasType(inPlaceClass()))); + return cxxConstructExpr(hasArgument(0, hasType(inPlaceClass())), + hasOptionalOrDerivedType()); } auto isOptionalValueOrConversionConstructor() { return cxxConstructExpr( - hasOptionalType(), unless(hasDeclaration( cxxConstructorDecl(anyOf(isCopyConstructor(), isMoveConstructor())))), - argumentCountIs(1), hasArgument(0, unless(hasNulloptType()))); + argumentCountIs(1), hasArgument(0, unless(hasNulloptType())), + hasOptionalOrDerivedType()); } auto isOptionalValueOrConversionAssignment() { return cxxOperatorCallExpr( hasOverloadedOperatorName("="), - callee(cxxMethodDecl(ofClass(optionalClass()))), + callee(cxxMethodDecl(ofClass(optionalOrDerivedClass()))), unless(hasDeclaration(cxxMethodDecl( anyOf(isCopyAssignmentOperator(), isMoveAssignmentOperator())))), argumentCountIs(2), hasArgument(1, unless(hasNulloptType()))); } auto isOptionalNulloptAssignment() { - return cxxOperatorCallExpr(hasOverloadedOperatorName("="), - callee(cxxMethodDecl(ofClass(optionalClass()))), - argumentCountIs(2), - hasArgument(1, hasNulloptType())); + return cxxOperatorCallExpr( + hasOverloadedOperatorName("="), + callee(cxxMethodDecl(ofClass(optionalOrDerivedClass()))), + argumentCountIs(2), hasArgument(1, hasNulloptType())); } auto isStdSwapCall() { return callExpr(callee(functionDecl(hasName("std::swap"))), - argumentCountIs(2), hasArgument(0, hasOptionalType()), - hasArgument(1, hasOptionalType())); + argumentCountIs(2), + hasArgument(0, hasOptionalOrDerivedType()), + hasArgument(1, hasOptionalOrDerivedType())); } auto isStdForwardCall() { return callExpr(callee(functionDecl(hasName("std::forward"))), - argumentCountIs(1), hasArgument(0, hasOptionalType())); + argumentCountIs(1), + hasArgument(0, hasOptionalOrDerivedType())); } constexpr llvm::StringLiteral ValueOrCallID = "ValueOrCall"; @@ -212,8 +300,9 @@ auto isValueOrNotEqX() { } auto isCallReturningOptional() { - return callExpr(hasType(qualType(anyOf( - optionalOrAliasType(), referenceType(pointee(optionalOrAliasType())))))); + return callExpr(hasType(qualType( + anyOf(desugarsToOptionalOrDerivedType(), + referenceType(pointee(desugarsToOptionalOrDerivedType())))))); } template <typename L, typename R> @@ -275,12 +364,9 @@ BoolValue *getHasValue(Environment &Env, RecordStorageLocation *OptionalLoc) { return HasValueVal; } -/// Returns true if and only if `Type` is an optional type. -bool isOptionalType(QualType Type) { - if (!Type->isRecordType()) - return false; - const CXXRecordDecl *D = Type->getAsCXXRecordDecl(); - return D != nullptr && hasOptionalClassName(*D); +QualType valueTypeFromOptionalDecl(const CXXRecordDecl &RD) { + auto &CTSD = cast<ClassTemplateSpecializationDecl>(RD); + return CTSD.getTemplateArgs()[0].getAsType(); } /// Returns the number of optional wrappers in `Type`. @@ -288,15 +374,13 @@ bool isOptionalType(QualType Type) { /// For example, if `Type` is `optional<optional<int>>`, the result of this /// function will be 2. int countOptionalWrappers(const ASTContext &ASTCtx, QualType Type) { - if (!isOptionalType(Type)) + const CXXRecordDecl *Optional = + getOptionalBaseClass(Type->getAsCXXRecordDecl()); + if (Optional == nullptr) return 0; return 1 + countOptionalWrappers( ASTCtx, - cast<ClassTemplateSpecializationDecl>(Type->getAsRecordDecl()) - ->getTemplateArgs() - .get(0) - .getAsType() - .getDesugaredType(ASTCtx)); + valueTypeFromOptionalDecl(*Optional).getDesugaredType(ASTCtx)); } StorageLocation *getLocBehindPossiblePointer(const Expr &E, @@ -428,27 +512,26 @@ void constructOptionalValue(const Expr &E, Environment &Env, /// Returns a symbolic value for the "has_value" property of an `optional<T>` /// value that is constructed/assigned from a value of type `U` or `optional<U>` /// where `T` is constructible from `U`. -BoolValue &valueOrConversionHasValue(const FunctionDecl &F, const Expr &E, +BoolValue &valueOrConversionHasValue(QualType DestType, const Expr &E, const MatchFinder::MatchResult &MatchRes, LatticeTransferState &State) { - assert(F.getTemplateSpecializationArgs() != nullptr); - assert(F.getTemplateSpecializationArgs()->size() > 0); - - const int TemplateParamOptionalWrappersCount = - countOptionalWrappers(*MatchRes.Context, F.getTemplateSpecializationArgs() - ->get(0) - .getAsType() - .getNonReferenceType()); + const int DestTypeOptionalWrappersCount = + countOptionalWrappers(*MatchRes.Context, DestType); const int ArgTypeOptionalWrappersCount = countOptionalWrappers( *MatchRes.Context, E.getType().getNonReferenceType()); - // Check if this is a constructor/assignment call for `optional<T>` with - // argument of type `U` such that `T` is constructible from `U`. - if (TemplateParamOptionalWrappersCount == ArgTypeOptionalWrappersCount) + // Is this an constructor of the form `template<class U> optional(U &&)` / + // assignment of the form `template<class U> optional& operator=(U &&)` + // (where `T` is assignable / constructible from `U`)? + // We recognize this because the number of optionals in the optional being + // assigned to is different from the function argument type. + if (DestTypeOptionalWrappersCount != ArgTypeOptionalWrappersCount) return State.Env.getBoolLiteralValue(true); - // This is a constructor/assignment call for `optional<T>` with argument of - // type `optional<U>` such that `T` is constructible from `U`. + // Otherwise, this must be a constructor of the form + // `template <class U> optional<optional<U> &&)` / assignment of the form + // `template <class U> optional& operator=(optional<U> &&) + // (where, again, `T` is assignable / constructible from `U`). auto *Loc = State.Env.get<RecordStorageLocation>(E); if (auto *HasValueVal = getHasValue(State.Env, Loc)) return *HasValueVal; @@ -460,10 +543,11 @@ void transferValueOrConversionConstructor( LatticeTransferState &State) { assert(E->getNumArgs() > 0); - constructOptionalValue(*E, State.Env, - valueOrConversionHasValue(*E->getConstructor(), - *E->getArg(0), MatchRes, - State)); + constructOptionalValue( + *E, State.Env, + valueOrConversionHasValue( + E->getConstructor()->getThisType()->getPointeeType(), *E->getArg(0), + MatchRes, State)); } void transferAssignment(const CXXOperatorCallExpr *E, BoolValue &HasValueVal, @@ -482,10 +566,11 @@ void transferValueOrConversionAssignment( const CXXOperatorCallExpr *E, const MatchFinder::MatchResult &MatchRes, LatticeTransferState &State) { assert(E->getNumArgs() > 1); - transferAssignment(E, - valueOrConversionHasValue(*E->getDirectCallee(), - *E->getArg(1), MatchRes, State), - State); + transferAssignment( + E, + valueOrConversionHasValue(E->getArg(0)->getType().getNonReferenceType(), + *E->getArg(1), MatchRes, State), + State); } void transferNulloptAssignment(const CXXOperatorCallExpr *E, @@ -843,13 +928,7 @@ auto buildDiagnoseMatchSwitch( ast_matchers::DeclarationMatcher UncheckedOptionalAccessModel::optionalClassDecl() { - return optionalClass(); -} - -static QualType valueTypeFromOptionalType(QualType OptionalTy) { - auto *CTSD = - cast<ClassTemplateSpecializationDecl>(OptionalTy->getAsCXXRecordDecl()); - return CTSD->getTemplateArgs()[0].getAsType(); + return cxxRecordDecl(optionalClass()); } UncheckedOptionalAccessModel::UncheckedOptionalAccessModel(ASTContext &Ctx, @@ -858,9 +937,11 @@ UncheckedOptionalAccessModel::UncheckedOptionalAccessModel(ASTContext &Ctx, TransferMatchSwitch(buildTransferMatchSwitch()) { Env.getDataflowAnalysisContext().setSyntheticFieldCallback( [&Ctx](QualType Ty) -> llvm::StringMap<QualType> { - if (!isOptionalType(Ty)) + const CXXRecordDecl *Optional = + getOptionalBaseClass(Ty->getAsCXXRecordDecl()); + if (Optional == nullptr) return {}; - return {{"value", valueTypeFromOptionalType(Ty)}, + return {{"value", valueTypeFromOptionalDecl(*Optional)}, {"has_value", Ctx.BoolTy}}; }); } diff --git a/clang/lib/Analysis/FlowSensitive/RecordOps.cpp b/clang/lib/Analysis/FlowSensitive/RecordOps.cpp index da4dd6dc0785159acc4e1a15a70c8a56cdf26238..2f0b0e5c5640c342710762b5794e186ae72d8f12 100644 --- a/clang/lib/Analysis/FlowSensitive/RecordOps.cpp +++ b/clang/lib/Analysis/FlowSensitive/RecordOps.cpp @@ -14,18 +14,52 @@ #define DEBUG_TYPE "dataflow" -void clang::dataflow::copyRecord(RecordStorageLocation &Src, - RecordStorageLocation &Dst, Environment &Env) { +namespace clang::dataflow { + +static void copyField(const ValueDecl &Field, StorageLocation *SrcFieldLoc, + StorageLocation *DstFieldLoc, RecordStorageLocation &Dst, + Environment &Env) { + assert(Field.getType()->isReferenceType() || + (SrcFieldLoc != nullptr && DstFieldLoc != nullptr)); + + if (Field.getType()->isRecordType()) { + copyRecord(cast<RecordStorageLocation>(*SrcFieldLoc), + cast<RecordStorageLocation>(*DstFieldLoc), Env); + } else if (Field.getType()->isReferenceType()) { + Dst.setChild(Field, SrcFieldLoc); + } else { + if (Value *Val = Env.getValue(*SrcFieldLoc)) + Env.setValue(*DstFieldLoc, *Val); + else + Env.clearValue(*DstFieldLoc); + } +} + +static void copySyntheticField(QualType FieldType, StorageLocation &SrcFieldLoc, + StorageLocation &DstFieldLoc, Environment &Env) { + if (FieldType->isRecordType()) { + copyRecord(cast<RecordStorageLocation>(SrcFieldLoc), + cast<RecordStorageLocation>(DstFieldLoc), Env); + } else { + if (Value *Val = Env.getValue(SrcFieldLoc)) + Env.setValue(DstFieldLoc, *Val); + else + Env.clearValue(DstFieldLoc); + } +} + +void copyRecord(RecordStorageLocation &Src, RecordStorageLocation &Dst, + Environment &Env) { auto SrcType = Src.getType().getCanonicalType().getUnqualifiedType(); auto DstType = Dst.getType().getCanonicalType().getUnqualifiedType(); auto SrcDecl = SrcType->getAsCXXRecordDecl(); auto DstDecl = DstType->getAsCXXRecordDecl(); - bool compatibleTypes = + [[maybe_unused]] bool compatibleTypes = SrcType == DstType || - (SrcDecl && DstDecl && SrcDecl->isDerivedFrom(DstDecl)); - (void)compatibleTypes; + (SrcDecl != nullptr && DstDecl != nullptr && + (SrcDecl->isDerivedFrom(DstDecl) || DstDecl->isDerivedFrom(SrcDecl))); LLVM_DEBUG({ if (!compatibleTypes) { @@ -35,45 +69,27 @@ void clang::dataflow::copyRecord(RecordStorageLocation &Src, }); assert(compatibleTypes); - for (auto [Field, DstFieldLoc] : Dst.children()) { - StorageLocation *SrcFieldLoc = Src.getChild(*Field); - - assert(Field->getType()->isReferenceType() || - (SrcFieldLoc != nullptr && DstFieldLoc != nullptr)); - - if (Field->getType()->isRecordType()) { - copyRecord(cast<RecordStorageLocation>(*SrcFieldLoc), - cast<RecordStorageLocation>(*DstFieldLoc), Env); - } else if (Field->getType()->isReferenceType()) { - Dst.setChild(*Field, SrcFieldLoc); - } else { - if (Value *Val = Env.getValue(*SrcFieldLoc)) - Env.setValue(*DstFieldLoc, *Val); - else - Env.clearValue(*DstFieldLoc); - } - } - - for (const auto &[Name, SynthFieldLoc] : Src.synthetic_fields()) { - if (SynthFieldLoc->getType()->isRecordType()) { - copyRecord(*cast<RecordStorageLocation>(SynthFieldLoc), - cast<RecordStorageLocation>(Dst.getSyntheticField(Name)), Env); - } else { - if (Value *Val = Env.getValue(*SynthFieldLoc)) - Env.setValue(Dst.getSyntheticField(Name), *Val); - else - Env.clearValue(Dst.getSyntheticField(Name)); - } + if (SrcType == DstType || (SrcDecl != nullptr && DstDecl != nullptr && + SrcDecl->isDerivedFrom(DstDecl))) { + for (auto [Field, DstFieldLoc] : Dst.children()) + copyField(*Field, Src.getChild(*Field), DstFieldLoc, Dst, Env); + for (const auto &[Name, DstFieldLoc] : Dst.synthetic_fields()) + copySyntheticField(DstFieldLoc->getType(), Src.getSyntheticField(Name), + *DstFieldLoc, Env); + } else { + for (auto [Field, SrcFieldLoc] : Src.children()) + copyField(*Field, SrcFieldLoc, Dst.getChild(*Field), Dst, Env); + for (const auto &[Name, SrcFieldLoc] : Src.synthetic_fields()) + copySyntheticField(SrcFieldLoc->getType(), *SrcFieldLoc, + Dst.getSyntheticField(Name), Env); } RecordValue *DstVal = &Env.create<RecordValue>(Dst); Env.setValue(Dst, *DstVal); } -bool clang::dataflow::recordsEqual(const RecordStorageLocation &Loc1, - const Environment &Env1, - const RecordStorageLocation &Loc2, - const Environment &Env2) { +bool recordsEqual(const RecordStorageLocation &Loc1, const Environment &Env1, + const RecordStorageLocation &Loc2, const Environment &Env2) { LLVM_DEBUG({ if (Loc2.getType().getCanonicalType().getUnqualifiedType() != Loc1.getType().getCanonicalType().getUnqualifiedType()) { @@ -116,3 +132,5 @@ bool clang::dataflow::recordsEqual(const RecordStorageLocation &Loc1, return true; } + +} // namespace clang::dataflow diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp index 04aa2831df05580e0dd3e8c64bf3900ce0377847..0a2e8368d541dd0f684d7e8672b7b8fc82aeb40b 100644 --- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp +++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp @@ -20,7 +20,7 @@ #include "clang/AST/OperationKinds.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtVisitor.h" -#include "clang/Analysis/FlowSensitive/ControlFlowContext.h" +#include "clang/Analysis/FlowSensitive/AdornedCFG.h" #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" #include "clang/Analysis/FlowSensitive/NoopAnalysis.h" #include "clang/Analysis/FlowSensitive/RecordOps.h" @@ -38,9 +38,9 @@ namespace clang { namespace dataflow { const Environment *StmtToEnvMap::getEnvironment(const Stmt &S) const { - auto BlockIt = CFCtx.getStmtToBlock().find(&ignoreCFGOmittedNodes(S)); - assert(BlockIt != CFCtx.getStmtToBlock().end()); - if (!CFCtx.isBlockReachable(*BlockIt->getSecond())) + auto BlockIt = ACFG.getStmtToBlock().find(&ignoreCFGOmittedNodes(S)); + assert(BlockIt != ACFG.getStmtToBlock().end()); + if (!ACFG.isBlockReachable(*BlockIt->getSecond())) return nullptr; if (BlockIt->getSecond()->getBlockID() == CurBlockID) return &CurState.Env; @@ -450,6 +450,25 @@ public: Env.setStorageLocation(*S, *MemberLoc); } + void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *S) { + const Expr *ArgExpr = S->getExpr(); + assert(ArgExpr != nullptr); + propagateValueOrStorageLocation(*ArgExpr, *S, Env); + + // If this is a prvalue of record type, we consider it to be an "original + // record constructor", which we always require to have a `RecordValue`. + // So make sure we have a value if we didn't propagate one above. + if (S->isPRValue() && S->getType()->isRecordType()) { + if (Env.getValue(*S) == nullptr) { + Value *Val = Env.createValue(S->getType()); + // We're guaranteed to always be able to create a value for record + // types. + assert(Val != nullptr); + Env.setValue(*S, *Val); + } + } + } + void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *S) { const Expr *InitExpr = S->getExpr(); assert(InitExpr != nullptr); @@ -525,15 +544,6 @@ public: if (LocSrc == nullptr || LocDst == nullptr) return; - // The assignment operators are different from the type of the destination - // in this model (i.e. in one of their base classes). This must be very - // rare and we just bail. - if (Method->getFunctionObjectParameterType() - .getCanonicalType() - .getUnqualifiedType() != - LocDst->getType().getCanonicalType().getUnqualifiedType()) - return; - copyRecord(*LocSrc, *LocDst, Env); // If the expr is a glvalue, we can reasonably assume the operator is @@ -679,51 +689,22 @@ public: } llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs; - - // This only contains the direct fields for the given type. - std::vector<const FieldDecl *> FieldsForInit = getFieldsForInitListExpr(S); - - // `S->inits()` contains all the initializer expressions, including the - // ones for direct base classes. - ArrayRef<Expr *> Inits = S->inits(); - size_t InitIdx = 0; - - // Unions initialized with an empty initializer list need special treatment. - // For structs/classes initialized with an empty initializer list, Clang - // puts `ImplicitValueInitExpr`s in `InitListExpr::inits()`, but for unions, - // it doesn't do this -- so we create an `ImplicitValueInitExpr` ourselves. - std::optional<ImplicitValueInitExpr> ImplicitValueInitForUnion; - SmallVector<Expr *> InitsForUnion; - if (S->getType()->isUnionType() && Inits.empty()) { - assert(FieldsForInit.size() == 1); - ImplicitValueInitForUnion.emplace(FieldsForInit.front()->getType()); - InitsForUnion.push_back(&*ImplicitValueInitForUnion); - Inits = InitsForUnion; - } - - // Initialize base classes. - if (auto* R = S->getType()->getAsCXXRecordDecl()) { - assert(FieldsForInit.size() + R->getNumBases() == Inits.size()); - for ([[maybe_unused]] const CXXBaseSpecifier &Base : R->bases()) { - assert(InitIdx < Inits.size()); - auto Init = Inits[InitIdx++]; - assert(Base.getType().getCanonicalType() == - Init->getType().getCanonicalType()); - auto *BaseVal = Env.get<RecordValue>(*Init); - if (!BaseVal) - BaseVal = cast<RecordValue>(Env.createValue(Init->getType())); - // Take ownership of the fields of the `RecordValue` for the base class - // and incorporate them into the "flattened" set of fields for the - // derived class. - auto Children = BaseVal->getLoc().children(); - FieldLocs.insert(Children.begin(), Children.end()); - } - } - - assert(FieldsForInit.size() == Inits.size() - InitIdx); - for (auto Field : FieldsForInit) { - assert(InitIdx < Inits.size()); - auto Init = Inits[InitIdx++]; + RecordInitListHelper InitListHelper(S); + + for (auto [Base, Init] : InitListHelper.base_inits()) { + assert(Base->getType().getCanonicalType() == + Init->getType().getCanonicalType()); + auto *BaseVal = Env.get<RecordValue>(*Init); + if (!BaseVal) + BaseVal = cast<RecordValue>(Env.createValue(Init->getType())); + // Take ownership of the fields of the `RecordValue` for the base class + // and incorporate them into the "flattened" set of fields for the + // derived class. + auto Children = BaseVal->getLoc().children(); + FieldLocs.insert(Children.begin(), Children.end()); + } + + for (auto [Field, Init] : InitListHelper.field_inits()) { assert( // The types are same, or Field->getType().getCanonicalType().getUnqualifiedType() == @@ -836,27 +817,26 @@ private: Env.canDescend(Options.ContextSensitiveOpts->Depth, F))) return; - const ControlFlowContext *CFCtx = - Env.getDataflowAnalysisContext().getControlFlowContext(F); - if (!CFCtx) + const AdornedCFG *ACFG = Env.getDataflowAnalysisContext().getAdornedCFG(F); + if (!ACFG) return; // FIXME: We don't support context-sensitive analysis of recursion, so // we should return early here if `F` is the same as the `FunctionDecl` // holding `S` itself. - auto ExitBlock = CFCtx->getCFG().getExit().getBlockID(); + auto ExitBlock = ACFG->getCFG().getExit().getBlockID(); auto CalleeEnv = Env.pushCall(S); // FIXME: Use the same analysis as the caller for the callee. Note, // though, that doing so would require support for changing the analysis's // ASTContext. - auto Analysis = NoopAnalysis(CFCtx->getDecl().getASTContext(), + auto Analysis = NoopAnalysis(ACFG->getDecl().getASTContext(), DataflowAnalysisOptions{Options}); auto BlockToOutputState = - dataflow::runDataflowAnalysis(*CFCtx, Analysis, CalleeEnv); + dataflow::runDataflowAnalysis(*ACFG, Analysis, CalleeEnv); assert(BlockToOutputState); assert(ExitBlock < BlockToOutputState->size()); diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp index 939247c047c66e8d48bfdd4c121cfaa6859b72c3..595f70f819ddb518d01cf1a3ba2edbc3402cd21c 100644 --- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp +++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#include <algorithm> #include <optional> #include <system_error> #include <utility> @@ -33,7 +32,6 @@ #include "clang/Analysis/FlowSensitive/Value.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallBitVector.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Error.h" @@ -64,106 +62,44 @@ static bool isBackedgeNode(const CFGBlock &B) { namespace { -// The return type of the visit functions in TerminatorVisitor. The first -// element represents the terminator expression (that is the conditional -// expression in case of a path split in the CFG). The second element -// represents whether the condition was true or false. -using TerminatorVisitorRetTy = std::pair<const Expr *, bool>; - -/// Extends the flow condition of an environment based on a terminator -/// statement. +/// Extracts the terminator's condition expression. class TerminatorVisitor - : public ConstStmtVisitor<TerminatorVisitor, TerminatorVisitorRetTy> { + : public ConstStmtVisitor<TerminatorVisitor, const Expr *> { public: - TerminatorVisitor(Environment &Env, int BlockSuccIdx) - : Env(Env), BlockSuccIdx(BlockSuccIdx) {} - - TerminatorVisitorRetTy VisitIfStmt(const IfStmt *S) { - auto *Cond = S->getCond(); - assert(Cond != nullptr); - return extendFlowCondition(*Cond); - } - - TerminatorVisitorRetTy VisitWhileStmt(const WhileStmt *S) { - auto *Cond = S->getCond(); - assert(Cond != nullptr); - return extendFlowCondition(*Cond); - } - - TerminatorVisitorRetTy VisitDoStmt(const DoStmt *S) { - auto *Cond = S->getCond(); - assert(Cond != nullptr); - return extendFlowCondition(*Cond); - } - - TerminatorVisitorRetTy VisitForStmt(const ForStmt *S) { - auto *Cond = S->getCond(); - if (Cond != nullptr) - return extendFlowCondition(*Cond); - return {nullptr, false}; - } - - TerminatorVisitorRetTy VisitCXXForRangeStmt(const CXXForRangeStmt *) { + TerminatorVisitor() = default; + const Expr *VisitIfStmt(const IfStmt *S) { return S->getCond(); } + const Expr *VisitWhileStmt(const WhileStmt *S) { return S->getCond(); } + const Expr *VisitDoStmt(const DoStmt *S) { return S->getCond(); } + const Expr *VisitForStmt(const ForStmt *S) { return S->getCond(); } + const Expr *VisitCXXForRangeStmt(const CXXForRangeStmt *) { // Don't do anything special for CXXForRangeStmt, because the condition // (being implicitly generated) isn't visible from the loop body. - return {nullptr, false}; + return nullptr; } - - TerminatorVisitorRetTy VisitBinaryOperator(const BinaryOperator *S) { + const Expr *VisitBinaryOperator(const BinaryOperator *S) { assert(S->getOpcode() == BO_LAnd || S->getOpcode() == BO_LOr); - auto *LHS = S->getLHS(); - assert(LHS != nullptr); - return extendFlowCondition(*LHS); + return S->getLHS(); } - - TerminatorVisitorRetTy - VisitConditionalOperator(const ConditionalOperator *S) { - auto *Cond = S->getCond(); - assert(Cond != nullptr); - return extendFlowCondition(*Cond); + const Expr *VisitConditionalOperator(const ConditionalOperator *S) { + return S->getCond(); } - -private: - TerminatorVisitorRetTy extendFlowCondition(const Expr &Cond) { - auto *Val = Env.get<BoolValue>(Cond); - // In transferCFGBlock(), we ensure that we always have a `Value` for the - // terminator condition, so assert this. - // We consciously assert ourselves instead of asserting via `cast()` so - // that we get a more meaningful line number if the assertion fails. - assert(Val != nullptr); - - bool ConditionValue = true; - // The condition must be inverted for the successor that encompasses the - // "else" branch, if such exists. - if (BlockSuccIdx == 1) { - Val = &Env.makeNot(*Val); - ConditionValue = false; - } - - Env.assume(Val->formula()); - return {&Cond, ConditionValue}; - } - - Environment &Env; - int BlockSuccIdx; }; /// Holds data structures required for running dataflow analysis. struct AnalysisContext { - AnalysisContext(const ControlFlowContext &CFCtx, - TypeErasedDataflowAnalysis &Analysis, + AnalysisContext(const AdornedCFG &ACFG, TypeErasedDataflowAnalysis &Analysis, const Environment &InitEnv, llvm::ArrayRef<std::optional<TypeErasedDataflowAnalysisState>> BlockStates) - : CFCtx(CFCtx), Analysis(Analysis), InitEnv(InitEnv), + : ACFG(ACFG), Analysis(Analysis), InitEnv(InitEnv), Log(*InitEnv.getDataflowAnalysisContext().getOptions().Log), BlockStates(BlockStates) { - Log.beginAnalysis(CFCtx, Analysis); + Log.beginAnalysis(ACFG, Analysis); } ~AnalysisContext() { Log.endAnalysis(); } /// Contains the CFG being analyzed. - const ControlFlowContext &CFCtx; + const AdornedCFG &ACFG; /// The analysis to be run. TypeErasedDataflowAnalysis &Analysis; /// Initial state to start the analysis. @@ -176,19 +112,19 @@ struct AnalysisContext { class PrettyStackTraceAnalysis : public llvm::PrettyStackTraceEntry { public: - PrettyStackTraceAnalysis(const ControlFlowContext &CFCtx, const char *Message) - : CFCtx(CFCtx), Message(Message) {} + PrettyStackTraceAnalysis(const AdornedCFG &ACFG, const char *Message) + : ACFG(ACFG), Message(Message) {} void print(raw_ostream &OS) const override { OS << Message << "\n"; OS << "Decl:\n"; - CFCtx.getDecl().dump(OS); + ACFG.getDecl().dump(OS); OS << "CFG:\n"; - CFCtx.getCFG().print(OS, LangOptions(), false); + ACFG.getCFG().print(OS, LangOptions(), false); } private: - const ControlFlowContext &CFCtx; + const AdornedCFG &ACFG; const char *Message; }; @@ -264,9 +200,13 @@ public: return Result; } }; - } // namespace +static const Expr *getTerminatorCondition(const Stmt *TerminatorStmt) { + return TerminatorStmt == nullptr ? nullptr + : TerminatorVisitor().Visit(TerminatorStmt); +} + /// Computes the input state for a given basic block by joining the output /// states of its predecessors. /// @@ -303,7 +243,7 @@ computeBlockInputState(const CFGBlock &Block, AnalysisContext &AC) { // See `NoreturnDestructorTest` for concrete examples. if (Block.succ_begin()->getReachableBlock() != nullptr && Block.succ_begin()->getReachableBlock()->hasNoReturnElement()) { - auto &StmtToBlock = AC.CFCtx.getStmtToBlock(); + auto &StmtToBlock = AC.ACFG.getStmtToBlock(); auto StmtBlock = StmtToBlock.find(Block.getTerminatorStmt()); assert(StmtBlock != StmtToBlock.end()); llvm::erase(Preds, StmtBlock->getSecond()); @@ -319,7 +259,7 @@ computeBlockInputState(const CFGBlock &Block, AnalysisContext &AC) { // all predecessors have expression state consumed in a different block. Environment::ExprJoinBehavior JoinBehavior = Environment::DiscardExprState; for (const CFGBlock *Pred : Preds) { - if (Pred && AC.CFCtx.containsExprConsumedInDifferentBlock(*Pred)) { + if (Pred && AC.ACFG.containsExprConsumedInDifferentBlock(*Pred)) { JoinBehavior = Environment::KeepExprState; break; } @@ -338,25 +278,32 @@ computeBlockInputState(const CFGBlock &Block, AnalysisContext &AC) { if (!MaybePredState) continue; + const TypeErasedDataflowAnalysisState &PredState = *MaybePredState; + const Expr *Cond = getTerminatorCondition(Pred->getTerminatorStmt()); + if (Cond == nullptr) { + Builder.addUnowned(PredState); + continue; + } + + bool BranchVal = blockIndexInPredecessor(*Pred, Block) == 0; + + // `transferBranch` may need to mutate the environment to describe the + // dynamic effect of the terminator for a given branch. Copy now. + TypeErasedDataflowAnalysisState Copy = MaybePredState->fork(); if (AC.Analysis.builtinOptions()) { - if (const Stmt *PredTerminatorStmt = Pred->getTerminatorStmt()) { - // We have a terminator: we need to mutate an environment to describe - // when the terminator is taken. Copy now. - TypeErasedDataflowAnalysisState Copy = MaybePredState->fork(); - - auto [Cond, CondValue] = - TerminatorVisitor(Copy.Env, blockIndexInPredecessor(*Pred, Block)) - .Visit(PredTerminatorStmt); - if (Cond != nullptr) - // FIXME: Call transferBranchTypeErased even if BuiltinTransferOpts - // are not set. - AC.Analysis.transferBranchTypeErased(CondValue, Cond, Copy.Lattice, - Copy.Env); - Builder.addOwned(std::move(Copy)); - continue; - } + auto *CondVal = Copy.Env.get<BoolValue>(*Cond); + // In transferCFGBlock(), we ensure that we always have a `Value` + // for the terminator condition, so assert this. We consciously + // assert ourselves instead of asserting via `cast()` so that we get + // a more meaningful line number if the assertion fails. + assert(CondVal != nullptr); + BoolValue *AssertedVal = + BranchVal ? CondVal : &Copy.Env.makeNot(*CondVal); + Copy.Env.assume(AssertedVal->formula()); } - Builder.addUnowned(*MaybePredState); + AC.Analysis.transferBranchTypeErased(BranchVal, Cond, Copy.Lattice, + Copy.Env); + Builder.addOwned(std::move(Copy)); } return std::move(Builder).take(); } @@ -368,7 +315,7 @@ builtinTransferStatement(unsigned CurBlockID, const CFGStmt &Elt, AnalysisContext &AC) { const Stmt *S = Elt.getStmt(); assert(S != nullptr); - transfer(StmtToEnvMap(AC.CFCtx, AC.BlockStates, CurBlockID, InputState), *S, + transfer(StmtToEnvMap(AC.ACFG, AC.BlockStates, CurBlockID, InputState), *S, InputState.Env); } @@ -511,9 +458,8 @@ transferCFGBlock(const CFGBlock &Block, AnalysisContext &AC, // takes a `CFGElement` as input, but some expressions only show up as a // terminator condition, but not as a `CFGElement`. The condition of an if // statement is one such example. - transfer( - StmtToEnvMap(AC.CFCtx, AC.BlockStates, Block.getBlockID(), State), - *TerminatorCond, State.Env); + transfer(StmtToEnvMap(AC.ACFG, AC.BlockStates, Block.getBlockID(), State), + *TerminatorCond, State.Env); // If the transfer function didn't produce a value, create an atom so that // we have *some* value for the condition expression. This ensures that @@ -528,13 +474,13 @@ transferCFGBlock(const CFGBlock &Block, AnalysisContext &AC, llvm::Expected<std::vector<std::optional<TypeErasedDataflowAnalysisState>>> runTypeErasedDataflowAnalysis( - const ControlFlowContext &CFCtx, TypeErasedDataflowAnalysis &Analysis, + const AdornedCFG &ACFG, TypeErasedDataflowAnalysis &Analysis, const Environment &InitEnv, std::function<void(const CFGElement &, const TypeErasedDataflowAnalysisState &)> PostVisitCFG, std::int32_t MaxBlockVisits) { - PrettyStackTraceAnalysis CrashInfo(CFCtx, "runTypeErasedDataflowAnalysis"); + PrettyStackTraceAnalysis CrashInfo(ACFG, "runTypeErasedDataflowAnalysis"); std::optional<Environment> MaybeStartingEnv; if (InitEnv.callStackSize() == 1) { @@ -544,7 +490,7 @@ runTypeErasedDataflowAnalysis( const Environment &StartingEnv = MaybeStartingEnv ? *MaybeStartingEnv : InitEnv; - const clang::CFG &CFG = CFCtx.getCFG(); + const clang::CFG &CFG = ACFG.getCFG(); PostOrderCFGView POV(&CFG); ForwardDataflowWorklist Worklist(CFG, &POV); @@ -557,7 +503,7 @@ runTypeErasedDataflowAnalysis( StartingEnv.fork()}; Worklist.enqueueSuccessors(&Entry); - AnalysisContext AC(CFCtx, Analysis, StartingEnv, BlockStates); + AnalysisContext AC(ACFG, Analysis, StartingEnv, BlockStates); std::int32_t BlockVisits = 0; while (const CFGBlock *Block = Worklist.dequeue()) { LLVM_DEBUG(llvm::dbgs() @@ -615,7 +561,7 @@ runTypeErasedDataflowAnalysis( // state set to `std::nullopt` at this point) to also analyze dead code. if (PostVisitCFG) { - for (const CFGBlock *Block : CFCtx.getCFG()) { + for (const CFGBlock *Block : ACFG.getCFG()) { // Skip blocks that were not evaluated. if (!BlockStates[Block->getBlockID()]) continue; diff --git a/clang/lib/Analysis/PathDiagnostic.cpp b/clang/lib/Analysis/PathDiagnostic.cpp index 79f337a91ec8fafd581e89d1205e58ad3611e3ac..35472e705cfd8d55ac227733a957b58f33abb69f 100644 --- a/clang/lib/Analysis/PathDiagnostic.cpp +++ b/clang/lib/Analysis/PathDiagnostic.cpp @@ -115,14 +115,17 @@ PathDiagnostic::PathDiagnostic( StringRef CheckerName, const Decl *declWithIssue, StringRef bugtype, StringRef verboseDesc, StringRef shortDesc, StringRef category, PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique, + const Decl *AnalysisEntryPoint, std::unique_ptr<FilesToLineNumsMap> ExecutedLines) : CheckerName(CheckerName), DeclWithIssue(declWithIssue), BugType(StripTrailingDots(bugtype)), VerboseDesc(StripTrailingDots(verboseDesc)), ShortDesc(StripTrailingDots(shortDesc)), Category(StripTrailingDots(category)), UniqueingLoc(LocationToUnique), - UniqueingDecl(DeclToUnique), ExecutedLines(std::move(ExecutedLines)), - path(pathImpl) {} + UniqueingDecl(DeclToUnique), AnalysisEntryPoint(AnalysisEntryPoint), + ExecutedLines(std::move(ExecutedLines)), path(pathImpl) { + assert(AnalysisEntryPoint); +} void PathDiagnosticConsumer::anchor() {} diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index e1ff0d92f6b2f87e39be002044d1d372c92e7af5..e03fe1b68300435f41c73ab9e44fdd7a33884a35 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -403,10 +403,11 @@ AST_MATCHER(CXXConstructExpr, isSafeSpanTwoParamConstruct) { QualType Arg0Ty = Arg0->IgnoreImplicit()->getType(); if (Arg0Ty->isConstantArrayType()) { - const APInt &ConstArrSize = cast<ConstantArrayType>(Arg0Ty)->getSize(); + const APSInt ConstArrSize = + APSInt(cast<ConstantArrayType>(Arg0Ty)->getSize()); // Check form 4: - return Arg1CV && APSInt::compareValues(APSInt(ConstArrSize), *Arg1CV) == 0; + return Arg1CV && APSInt::compareValues(ConstArrSize, *Arg1CV) == 0; } return false; } @@ -429,14 +430,13 @@ AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) { BaseDRE->getDecl()->getType()); if (!CATy) return false; - const APInt ArrSize = CATy->getSize(); if (const auto *IdxLit = dyn_cast<IntegerLiteral>(Node.getIdx())) { const APInt ArrIdx = IdxLit->getValue(); // FIXME: ArrIdx.isNegative() we could immediately emit an error as that's a // bug if (ArrIdx.isNonNegative() && - ArrIdx.getLimitedValue() < ArrSize.getLimitedValue()) + ArrIdx.getLimitedValue() < CATy->getLimitedSize()) return true; } diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp index b353a6627f298bae566e27b2b8edfccca2449d76..cd42573968b2129fa9200122bffad13620444e68 100644 --- a/clang/lib/Basic/DiagnosticIDs.cpp +++ b/clang/lib/Basic/DiagnosticIDs.cpp @@ -49,6 +49,7 @@ struct StaticDiagInfoDescriptionStringTable { #include "clang/Basic/DiagnosticSemaKinds.inc" #include "clang/Basic/DiagnosticAnalysisKinds.inc" #include "clang/Basic/DiagnosticRefactoringKinds.inc" +#include "clang/Basic/DiagnosticInstallAPIKinds.inc" // clang-format on #undef DIAG }; @@ -70,7 +71,8 @@ const StaticDiagInfoDescriptionStringTable StaticDiagInfoDescriptions = { #include "clang/Basic/DiagnosticSemaKinds.inc" #include "clang/Basic/DiagnosticAnalysisKinds.inc" #include "clang/Basic/DiagnosticRefactoringKinds.inc" - // clang-format on +#include "clang/Basic/DiagnosticInstallAPIKinds.inc" +// clang-format on #undef DIAG }; @@ -95,7 +97,8 @@ const uint32_t StaticDiagInfoDescriptionOffsets[] = { #include "clang/Basic/DiagnosticSemaKinds.inc" #include "clang/Basic/DiagnosticAnalysisKinds.inc" #include "clang/Basic/DiagnosticRefactoringKinds.inc" - // clang-format on +#include "clang/Basic/DiagnosticInstallAPIKinds.inc" +// clang-format on #undef DIAG }; @@ -173,6 +176,7 @@ VALIDATE_DIAG_SIZE(CROSSTU) VALIDATE_DIAG_SIZE(SEMA) VALIDATE_DIAG_SIZE(ANALYSIS) VALIDATE_DIAG_SIZE(REFACTORING) +VALIDATE_DIAG_SIZE(INSTALLAPI) #undef VALIDATE_DIAG_SIZE #undef STRINGIFY_NAME @@ -204,6 +208,7 @@ const StaticDiagInfoRec StaticDiagInfo[] = { #include "clang/Basic/DiagnosticSemaKinds.inc" #include "clang/Basic/DiagnosticAnalysisKinds.inc" #include "clang/Basic/DiagnosticRefactoringKinds.inc" +#include "clang/Basic/DiagnosticInstallAPIKinds.inc" // clang-format on #undef DIAG }; @@ -246,6 +251,7 @@ CATEGORY(CROSSTU, COMMENT) CATEGORY(SEMA, CROSSTU) CATEGORY(ANALYSIS, SEMA) CATEGORY(REFACTORING, ANALYSIS) +CATEGORY(INSTALLAPI, REFACTORING) #undef CATEGORY // Avoid out of bounds reads. @@ -855,6 +861,9 @@ bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const { if (isARCDiagnostic(DiagID)) return false; + if (isCodegenABICheckDiagnostic(DiagID)) + return false; + return true; } @@ -862,3 +871,8 @@ bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) { unsigned cat = getCategoryNumberForDiag(DiagID); return DiagnosticIDs::getCategoryNameFromID(cat).starts_with("ARC "); } + +bool DiagnosticIDs::isCodegenABICheckDiagnostic(unsigned DiagID) { + unsigned cat = getCategoryNumberForDiag(DiagID); + return DiagnosticIDs::getCategoryNameFromID(cat) == "Codegen ABI Check"; +} diff --git a/clang/lib/Basic/LangStandards.cpp b/clang/lib/Basic/LangStandards.cpp index ab09c7221dda92f0a690e4544dc7624818f27bbc..c8c9292abcb22b6cde2f78c9b88151460aa1041b 100644 --- a/clang/lib/Basic/LangStandards.cpp +++ b/clang/lib/Basic/LangStandards.cpp @@ -21,6 +21,8 @@ StringRef clang::languageToString(Language L) { return "Asm"; case Language::LLVM_IR: return "LLVM IR"; + case Language::CIR: + return "ClangIR"; case Language::C: return "C"; case Language::CXX: @@ -69,6 +71,16 @@ LangStandard::Kind LangStandard::getLangKind(StringRef Name) { .Default(lang_unspecified); } +LangStandard::Kind LangStandard::getHLSLLangKind(StringRef Name) { + return llvm::StringSwitch<LangStandard::Kind>(Name) + .Case("2016", LangStandard::lang_hlsl2016) + .Case("2017", LangStandard::lang_hlsl2017) + .Case("2018", LangStandard::lang_hlsl2018) + .Case("2021", LangStandard::lang_hlsl2021) + .Case("202x", LangStandard::lang_hlsl202x) + .Default(LangStandard::lang_unspecified); +} + const LangStandard *LangStandard::getLangStandardForName(StringRef Name) { Kind K = getLangKind(Name); if (K == lang_unspecified) @@ -82,6 +94,7 @@ LangStandard::Kind clang::getDefaultLanguageStandard(clang::Language Lang, switch (Lang) { case Language::Unknown: case Language::LLVM_IR: + case Language::CIR: llvm_unreachable("Invalid input kind!"); case Language::OpenCL: return LangStandard::lang_opencl12; diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp index 9f597dcf8b0f5a59f347d888f6d7856ecc097e36..256365d66bb9074128d65c481a83165ff48a8b3a 100644 --- a/clang/lib/Basic/Module.cpp +++ b/clang/lib/Basic/Module.cpp @@ -301,10 +301,9 @@ bool Module::directlyUses(const Module *Requested) { if (Requested->isSubModuleOf(Use)) return true; - // Anyone is allowed to use our builtin stdarg.h and stddef.h and their - // accompanying modules. - if (Requested->getTopLevelModuleName() == "_Builtin_stdarg" || - Requested->getTopLevelModuleName() == "_Builtin_stddef") + // Anyone is allowed to use our builtin stddef.h and its accompanying modules. + if (Requested->fullModuleNameIs({"_Builtin_stddef", "max_align_t"}) || + Requested->fullModuleNameIs({"_Builtin_stddef_wint_t"})) return true; if (NoUndeclaredIncludes) diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index 96b3ad9ba2f2731b1bd3a5443a0b6d1a5ceae6f5..f96956f31d50dc404a05d7b691aec694ad9c4999 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -157,6 +157,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) { HasAArch64SVETypes = false; HasRISCVVTypes = false; AllowAMDGPUUnsafeFPAtomics = false; + HasUnalignedAccess = false; ARMCDECoprocMask = 0; // Default to no types using fpret. @@ -925,6 +926,10 @@ bool TargetInfo::validateInputConstraint( return true; } +bool TargetInfo::validatePointerAuthKey(const llvm::APSInt &value) const { + return false; +} + void TargetInfo::CheckFixedPointBits() const { // Check that the number of fractional and integral bits (and maybe sign) can // fit into the bits given for a fixed point type. diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 5abb060073c517eed192d8cf08dc4918893e9d2c..1569b5e04b770a0d2b8ef045263abb12d2c8f769 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -11,9 +11,11 @@ //===----------------------------------------------------------------------===// #include "AArch64.h" +#include "clang/Basic/Diagnostic.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" @@ -186,6 +188,8 @@ AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple, assert(UseBitFieldTypeAlignment && "bitfields affect type alignment"); UseZeroLengthBitfieldAlignment = true; + HasUnalignedAccess = true; + // AArch64 targets default to using the ARM C++ ABI. TheCXXABI.set(TargetCXXABI::GenericAArch64); @@ -199,13 +203,23 @@ AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple, StringRef AArch64TargetInfo::getABI() const { return ABI; } bool AArch64TargetInfo::setABI(const std::string &Name) { - if (Name != "aapcs" && Name != "darwinpcs") + if (Name != "aapcs" && Name != "aapcs-soft" && Name != "darwinpcs") return false; ABI = Name; return true; } +bool AArch64TargetInfo::validateTarget(DiagnosticsEngine &Diags) const { + if (hasFeature("fp") && ABI == "aapcs-soft") { + // aapcs-soft is not allowed for targets with an FPU, to avoid there being + // two incomatible ABIs. + Diags.Report(diag::err_target_unsupported_abi_with_fpu) << ABI; + return false; + } + return true; +} + bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef, BranchProtectionInfo &BPI, StringRef &Err) const { @@ -484,7 +498,7 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, if (HasPAuthLR) Builder.defineMacro("__ARM_FEATURE_PAUTH_LR", "1"); - if (HasUnaligned) + if (HasUnalignedAccess) Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1"); if ((FPU & NeonMode) && HasFullFP16) @@ -680,7 +694,8 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const { return llvm::StringSwitch<bool>(Feature) .Cases("aarch64", "arm64", "arm", true) .Case("fmv", HasFMV) - .Cases("neon", "fp", "simd", FPU & NeonMode) + .Case("fp", FPU & FPUMode) + .Cases("neon", "simd", FPU & NeonMode) .Case("jscvt", HasJSCVT) .Case("fcma", HasFCMA) .Case("rng", HasRandGen) @@ -908,7 +923,8 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features, HasSM4 = true; } if (Feature == "+strict-align") - HasUnaligned = false; + HasUnalignedAccess = false; + // All predecessor archs are added but select the latest one for ArchKind. if (Feature == "+v8a" && ArchInfo->Version < llvm::AArch64::ARMV8A.Version) ArchInfo = &llvm::AArch64::ARMV8A; @@ -1450,6 +1466,11 @@ int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const { return -1; } +bool AArch64TargetInfo::validatePointerAuthKey( + const llvm::APSInt &value) const { + return 0 <= value && value <= 3; +} + bool AArch64TargetInfo::hasInt128Type() const { return true; } AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple, diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h index c1ba156860a1220d72109a2abaeea5753c6a8f2b..12fb50286f7511a6c5bf461ba3cf041d5f8bda4b 100644 --- a/clang/lib/Basic/Targets/AArch64.h +++ b/clang/lib/Basic/Targets/AArch64.h @@ -38,7 +38,6 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo { bool HasSHA2 = false; bool HasSHA3 = false; bool HasSM4 = false; - bool HasUnaligned = true; bool HasFullFP16 = false; bool HasDotProd = false; bool HasFP16FML = false; @@ -195,10 +194,14 @@ public: int getEHDataRegisterNumber(unsigned RegNo) const override; + bool validatePointerAuthKey(const llvm::APSInt &value) const override; + const char *getBFloat16Mangling() const override { return "u6__bf16"; }; bool hasInt128Type() const override; bool hasBitIntType() const override { return true; } + + bool validateTarget(DiagnosticsEngine &Diags) const override; }; class LLVM_LIBRARY_VISIBILITY AArch64leTargetInfo : public AArch64TargetInfo { diff --git a/clang/lib/Basic/Targets/ARM.cpp b/clang/lib/Basic/Targets/ARM.cpp index 55b71557452fa04db6b60512368d8ab17c45cac0..877799c66ec4f234cb2682d76a1fd40994b09304 100644 --- a/clang/lib/Basic/Targets/ARM.cpp +++ b/clang/lib/Basic/Targets/ARM.cpp @@ -509,7 +509,7 @@ bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, SHA2 = 0; AES = 0; DSP = 0; - Unaligned = 1; + HasUnalignedAccess = true; SoftFloat = false; // Note that SoftFloatABI is initialized in our constructor. HWDiv = 0; @@ -576,7 +576,7 @@ bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, return false; } } else if (Feature == "+strict-align") { - Unaligned = 0; + HasUnalignedAccess = false; } else if (Feature == "+fp16") { HW_FP |= HW_FP_HP; } else if (Feature == "+fullfp16") { @@ -785,7 +785,7 @@ void ARMTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'"); // ACLE 6.4.3 Unaligned access supported in hardware - if (Unaligned) + if (HasUnalignedAccess) Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1"); // ACLE 6.4.4 LDREX/STREX diff --git a/clang/lib/Basic/Targets/ARM.h b/clang/lib/Basic/Targets/ARM.h index 71322a094f5edba2cd9a31a433accc1efac54ebf..e69adbe754739f66f6084b252661404bf96b892b 100644 --- a/clang/lib/Basic/Targets/ARM.h +++ b/clang/lib/Basic/Targets/ARM.h @@ -88,8 +88,6 @@ class LLVM_LIBRARY_VISIBILITY ARMTargetInfo : public TargetInfo { LLVM_PREFERRED_TYPE(bool) unsigned DSP : 1; LLVM_PREFERRED_TYPE(bool) - unsigned Unaligned : 1; - LLVM_PREFERRED_TYPE(bool) unsigned DotProd : 1; LLVM_PREFERRED_TYPE(bool) unsigned HasMatMul : 1; diff --git a/clang/lib/Basic/Targets/BPF.cpp b/clang/lib/Basic/Targets/BPF.cpp index 26a54f631fcfc4d6f83dfe37127ec5d2e426224d..b5ba11a3bdca9d709eef35c5ce531923c425aa01 100644 --- a/clang/lib/Basic/Targets/BPF.cpp +++ b/clang/lib/Basic/Targets/BPF.cpp @@ -36,7 +36,7 @@ void BPFTargetInfo::getTargetDefines(const LangOptions &Opts, return; } - Builder.defineMacro("__BPF_FEATURE_ARENA_CAST"); + Builder.defineMacro("__BPF_FEATURE_ADDR_SPACE_CAST"); if (CPU.empty() || CPU == "generic" || CPU == "v1") { Builder.defineMacro("__BPF_CPU_VERSION__", "1"); @@ -45,6 +45,7 @@ void BPFTargetInfo::getTargetDefines(const LangOptions &Opts, std::string CpuVerNumStr = CPU.substr(1); Builder.defineMacro("__BPF_CPU_VERSION__", CpuVerNumStr); + Builder.defineMacro("__BPF_FEATURE_MAY_GOTO"); int CpuVerNum = std::stoi(CpuVerNumStr); if (CpuVerNum >= 2) diff --git a/clang/lib/Basic/Targets/LoongArch.cpp b/clang/lib/Basic/Targets/LoongArch.cpp index 88537989a05129f553b89ac2e74a444e9472bea0..280bd1d8033cc6ff7de12b5c122632276026e461 100644 --- a/clang/lib/Basic/Targets/LoongArch.cpp +++ b/clang/lib/Basic/Targets/LoongArch.cpp @@ -285,6 +285,8 @@ bool LoongArchTargetInfo::handleTargetFeatures( HasFeatureLSX = true; else if (Feature == "+lasx") HasFeatureLASX = true; + else if (Feature == "-ual") + HasUnalignedAccess = false; } return true; } diff --git a/clang/lib/Basic/Targets/LoongArch.h b/clang/lib/Basic/Targets/LoongArch.h index 3313102492cb8dc41b484c650630d5f451992c8c..68572843f2d7486398361271abda589ab075ca69 100644 --- a/clang/lib/Basic/Targets/LoongArch.h +++ b/clang/lib/Basic/Targets/LoongArch.h @@ -132,6 +132,7 @@ public: : LoongArchTargetInfo(Triple, Opts) { LongWidth = LongAlign = PointerWidth = PointerAlign = 64; IntMaxType = Int64Type = SignedLong; + HasUnalignedAccess = true; resetDataLayout("e-m:e-p:64:64-i64:64-i128:128-n64-S128"); // TODO: select appropriate ABI. setABI("lp64d"); diff --git a/clang/lib/Basic/Targets/M68k.cpp b/clang/lib/Basic/Targets/M68k.cpp index 1b7e0a7f32c9be516415c2d57dbdfe0e12a5a996..8b8bf97d6f99a1b1745e4aee928025d7b0e39877 100644 --- a/clang/lib/Basic/Targets/M68k.cpp +++ b/clang/lib/Basic/Targets/M68k.cpp @@ -127,16 +127,21 @@ bool M68kTargetInfo::hasFeature(StringRef Feature) const { const char *const M68kTargetInfo::GCCRegNames[] = { "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", - "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", + "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp", "pc"}; ArrayRef<const char *> M68kTargetInfo::getGCCRegNames() const { return llvm::ArrayRef(GCCRegNames); } +const TargetInfo::GCCRegAlias M68kTargetInfo::GCCRegAliases[] = { + {{"bp"}, "a5"}, + {{"fp"}, "a6"}, + {{"usp", "ssp", "isp", "a7"}, "sp"}, +}; + ArrayRef<TargetInfo::GCCRegAlias> M68kTargetInfo::getGCCRegAliases() const { - // No aliases. - return std::nullopt; + return llvm::ArrayRef(GCCRegAliases); } bool M68kTargetInfo::validateAsmConstraint( diff --git a/clang/lib/Basic/Targets/M68k.h b/clang/lib/Basic/Targets/M68k.h index a9c262e62fbad0bf37b2dd728edb896560361e3e..7ffa901127e504046908f0ce659a2b0bc4d2c89c 100644 --- a/clang/lib/Basic/Targets/M68k.h +++ b/clang/lib/Basic/Targets/M68k.h @@ -25,6 +25,7 @@ namespace targets { class LLVM_LIBRARY_VISIBILITY M68kTargetInfo : public TargetInfo { static const char *const GCCRegNames[]; + static const TargetInfo::GCCRegAlias GCCRegAliases[]; enum CPUKind { CK_Unknown, diff --git a/clang/lib/Basic/Targets/Mips.h b/clang/lib/Basic/Targets/Mips.h index 23d4e1b598fa1e44d470cea120c016a82a954431..c9dcf434c93b0b0579f5d94f3c28a2fead582384 100644 --- a/clang/lib/Basic/Targets/Mips.h +++ b/clang/lib/Basic/Targets/Mips.h @@ -328,6 +328,8 @@ public: IsMips16 = true; else if (Feature == "+micromips") IsMicromips = true; + else if (Feature == "+mips32r6" || Feature == "+mips64r6") + HasUnalignedAccess = true; else if (Feature == "+dsp") DspRev = std::max(DspRev, DSP1); else if (Feature == "+dspr2") diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h index 70683916a8b04f6616eb363c6c5f0501909bad4b..fa2f442e25846de4ed0386e543a8613a213120b2 100644 --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -92,6 +92,7 @@ public: LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble(); HasStrictFP = true; HasIbm128 = true; + HasUnalignedAccess = true; } // Set the language option for altivec based on our value. diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index a6d4af2b88111a4821b7292d3eacb3c1eafab6b5..f3d705e1551fe29fca69fcb610b9bc15d7ee3b24 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -467,3 +467,14 @@ ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const { } return Ret; } + +TargetInfo::CallingConvCheckResult +RISCVTargetInfo::checkCallingConvention(CallingConv CC) const { + switch (CC) { + default: + return CCCR_Warning; + case CC_C: + case CC_RISCVVectorCall: + return CCCR_OK; + } +} diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h index bfbdafb682c851333d8371de12436f9dfaed278c..78580b5b1c1063cd5f39f44ca20dbafff121818a 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -110,6 +110,8 @@ public: bool hasBFloat16Type() const override { return true; } + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override; + bool useFP16ConversionIntrinsics() const override { return false; } diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h index 3e08b27972fa3966df5d5e5ffa83c21460b6773c..8e302acd51b8ad1d40e175e65c3e5ab7a2895dc6 100644 --- a/clang/lib/Basic/Targets/SystemZ.h +++ b/clang/lib/Basic/Targets/SystemZ.h @@ -47,6 +47,7 @@ public: LongDoubleFormat = &llvm::APFloat::IEEEquad(); DefaultAlignForAttributeAligned = 64; MinGlobalAlign = 16; + HasUnalignedAccess = true; if (Triple.isOSzOS()) { TLSSupported = false; // All vector types are default aligned on an 8-byte boundary, even if the diff --git a/clang/lib/Basic/Targets/VE.h b/clang/lib/Basic/Targets/VE.h index ea9a092cad80908539d279402458f93a9b06b45b..7e8fdf6096ef232c2212f883db2eb36309d6b3db 100644 --- a/clang/lib/Basic/Targets/VE.h +++ b/clang/lib/Basic/Targets/VE.h @@ -40,6 +40,7 @@ public: Int64Type = SignedLong; RegParmMax = 8; MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; + HasUnalignedAccess = true; WCharType = UnsignedInt; WIntType = UnsignedInt; diff --git a/clang/lib/Basic/Targets/WebAssembly.h b/clang/lib/Basic/Targets/WebAssembly.h index 83b1711f9fdf6a8ce8632913b7666d348c6b4550..5568aa28eaefa7152637b70f4343937676f2a3d4 100644 --- a/clang/lib/Basic/Targets/WebAssembly.h +++ b/clang/lib/Basic/Targets/WebAssembly.h @@ -84,6 +84,7 @@ public: SizeType = UnsignedLong; PtrDiffType = SignedLong; IntPtrType = SignedLong; + HasUnalignedAccess = true; } StringRef getABI() const override; diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index d2232c7d5275abf47a4955b5e30c1ae36f5ad584..c14e4d5f433d8244f3a45e9752a6d19cd7bd2aac 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -188,6 +188,7 @@ public: LongDoubleFormat = &llvm::APFloat::x87DoubleExtended(); AddrSpaceMap = &X86AddrSpaceMap; HasStrictFP = true; + HasUnalignedAccess = true; bool IsWinCOFF = getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF(); diff --git a/clang/lib/CodeGen/ABIInfo.cpp b/clang/lib/CodeGen/ABIInfo.cpp index efcff958ce545223d11932243f1fd7d8a9f3e2e0..acaae9f8c3d8437c840012a438978ee09f3507a5 100644 --- a/clang/lib/CodeGen/ABIInfo.cpp +++ b/clang/lib/CodeGen/ABIInfo.cpp @@ -61,7 +61,7 @@ bool ABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate() const { bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base, uint64_t &Members) const { if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) { - uint64_t NElements = AT->getSize().getZExtValue(); + uint64_t NElements = AT->getZExtSize(); if (NElements == 0) return false; if (!isHomogeneousAggregate(AT->getElementType(), Base, Members)) @@ -98,7 +98,7 @@ bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base, QualType FT = FD->getType(); while (const ConstantArrayType *AT = getContext().getAsConstantArrayType(FT)) { - if (AT->getSize().getZExtValue() == 0) + if (AT->isZeroSize()) return false; FT = AT->getElementType(); } diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp index 2b20d5a13346d3414430268ef53dc8e0dcbf8972..3e34d82cb399ba05f880cc7fd470cfac0af08a8d 100644 --- a/clang/lib/CodeGen/ABIInfoImpl.cpp +++ b/clang/lib/CodeGen/ABIInfoImpl.cpp @@ -187,7 +187,7 @@ CodeGen::emitVoidPtrDirectVAArg(CodeGenFunction &CGF, Address VAListAddr, CharUnits FullDirectSize = DirectSize.alignTo(SlotSize); Address NextPtr = CGF.Builder.CreateConstInBoundsByteGEP(Addr, FullDirectSize, "argp.next"); - CGF.Builder.CreateStore(NextPtr.getPointer(), VAListAddr); + CGF.Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr); // If the argument is smaller than a slot, and this is a big-endian // target, the argument will be right-adjusted in its slot. @@ -239,8 +239,8 @@ Address CodeGen::emitMergePHI(CodeGenFunction &CGF, Address Addr1, const llvm::Twine &Name) { assert(Addr1.getType() == Addr2.getType()); llvm::PHINode *PHI = CGF.Builder.CreatePHI(Addr1.getType(), 2, Name); - PHI->addIncoming(Addr1.getPointer(), Block1); - PHI->addIncoming(Addr2.getPointer(), Block2); + PHI->addIncoming(Addr1.emitRawPointer(CGF), Block1); + PHI->addIncoming(Addr2.emitRawPointer(CGF), Block2); CharUnits Align = std::min(Addr1.getAlignment(), Addr2.getAlignment()); return Address(PHI, Addr1.getElementType(), Align); } @@ -257,7 +257,7 @@ bool CodeGen::isEmptyField(ASTContext &Context, const FieldDecl *FD, bool WasArray = false; if (AllowArrays) while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) { - if (AT->getSize() == 0) + if (AT->isZeroSize()) return true; FT = AT->getElementType(); // The [[no_unique_address]] special case below does not apply to @@ -352,7 +352,7 @@ const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) { // Treat single element arrays as the element. while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) { - if (AT->getSize().getZExtValue() != 1) + if (AT->getZExtSize() != 1) break; FT = AT->getElementType(); } @@ -400,7 +400,7 @@ Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr, llvm::Type *ElementTy = CGF.ConvertTypeForMem(Ty); llvm::Type *BaseTy = llvm::PointerType::getUnqual(ElementTy); llvm::Value *Addr = - CGF.Builder.CreateVAArg(VAListAddr.getPointer(), BaseTy); + CGF.Builder.CreateVAArg(VAListAddr.emitRawPointer(CGF), BaseTy); return Address(Addr, ElementTy, TyAlignForABI); } else { assert((AI.isDirect() || AI.isExtend()) && @@ -416,7 +416,7 @@ Address CodeGen::EmitVAArgInstr(CodeGenFunction &CGF, Address VAListAddr, "Unexpected CoerceToType seen in arginfo in generic VAArg emitter!"); Address Temp = CGF.CreateMemTemp(Ty, "varet"); - Val = CGF.Builder.CreateVAArg(VAListAddr.getPointer(), + Val = CGF.Builder.CreateVAArg(VAListAddr.emitRawPointer(CGF), CGF.ConvertTypeForMem(Ty)); CGF.Builder.CreateStore(Val, Temp); return Temp; diff --git a/clang/lib/CodeGen/Address.h b/clang/lib/CodeGen/Address.h index cf48df8f5e7367e0c3737f837b83cd057dc07142..35ec370a139c92efc4686eac311947d74952a270 100644 --- a/clang/lib/CodeGen/Address.h +++ b/clang/lib/CodeGen/Address.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H #include "clang/AST/CharUnits.h" +#include "clang/AST/Type.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/IR/Constants.h" #include "llvm/Support/MathExtras.h" @@ -22,28 +23,41 @@ namespace clang { namespace CodeGen { +class Address; +class CGBuilderTy; +class CodeGenFunction; +class CodeGenModule; + // Indicates whether a pointer is known not to be null. enum KnownNonNull_t { NotKnownNonNull, KnownNonNull }; -/// An aligned address. -class Address { +/// An abstract representation of an aligned address. This is designed to be an +/// IR-level abstraction, carrying just the information necessary to perform IR +/// operations on an address like loads and stores. In particular, it doesn't +/// carry C type information or allow the representation of things like +/// bit-fields; clients working at that level should generally be using +/// `LValue`. +/// The pointer contained in this class is known to be unsigned. +class RawAddress { llvm::PointerIntPair<llvm::Value *, 1, bool> PointerAndKnownNonNull; llvm::Type *ElementType; CharUnits Alignment; protected: - Address(std::nullptr_t) : ElementType(nullptr) {} + RawAddress(std::nullptr_t) : ElementType(nullptr) {} public: - Address(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment, - KnownNonNull_t IsKnownNonNull = NotKnownNonNull) + RawAddress(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment, + KnownNonNull_t IsKnownNonNull = NotKnownNonNull) : PointerAndKnownNonNull(Pointer, IsKnownNonNull), ElementType(ElementType), Alignment(Alignment) { assert(Pointer != nullptr && "Pointer cannot be null"); assert(ElementType != nullptr && "Element type cannot be null"); } - static Address invalid() { return Address(nullptr); } + inline RawAddress(Address Addr); + + static RawAddress invalid() { return RawAddress(nullptr); } bool isValid() const { return PointerAndKnownNonNull.getPointer() != nullptr; } @@ -80,6 +94,133 @@ public: return Alignment; } + /// Return address with different element type, but same pointer and + /// alignment. + RawAddress withElementType(llvm::Type *ElemTy) const { + return RawAddress(getPointer(), ElemTy, getAlignment(), isKnownNonNull()); + } + + KnownNonNull_t isKnownNonNull() const { + assert(isValid()); + return (KnownNonNull_t)PointerAndKnownNonNull.getInt(); + } +}; + +/// Like RawAddress, an abstract representation of an aligned address, but the +/// pointer contained in this class is possibly signed. +class Address { + friend class CGBuilderTy; + + // The boolean flag indicates whether the pointer is known to be non-null. + llvm::PointerIntPair<llvm::Value *, 1, bool> Pointer; + + /// The expected IR type of the pointer. Carrying accurate element type + /// information in Address makes it more convenient to work with Address + /// values and allows frontend assertions to catch simple mistakes. + llvm::Type *ElementType = nullptr; + + CharUnits Alignment; + + /// Offset from the base pointer. + llvm::Value *Offset = nullptr; + + llvm::Value *emitRawPointerSlow(CodeGenFunction &CGF) const; + +protected: + Address(std::nullptr_t) : ElementType(nullptr) {} + +public: + Address(llvm::Value *pointer, llvm::Type *elementType, CharUnits alignment, + KnownNonNull_t IsKnownNonNull = NotKnownNonNull) + : Pointer(pointer, IsKnownNonNull), ElementType(elementType), + Alignment(alignment) { + assert(pointer != nullptr && "Pointer cannot be null"); + assert(elementType != nullptr && "Element type cannot be null"); + assert(!alignment.isZero() && "Alignment cannot be zero"); + } + + Address(llvm::Value *BasePtr, llvm::Type *ElementType, CharUnits Alignment, + llvm::Value *Offset, KnownNonNull_t IsKnownNonNull = NotKnownNonNull) + : Pointer(BasePtr, IsKnownNonNull), ElementType(ElementType), + Alignment(Alignment), Offset(Offset) {} + + Address(RawAddress RawAddr) + : Pointer(RawAddr.isValid() ? RawAddr.getPointer() : nullptr), + ElementType(RawAddr.isValid() ? RawAddr.getElementType() : nullptr), + Alignment(RawAddr.isValid() ? RawAddr.getAlignment() + : CharUnits::Zero()) {} + + static Address invalid() { return Address(nullptr); } + bool isValid() const { return Pointer.getPointer() != nullptr; } + + /// This function is used in situations where the caller is doing some sort of + /// opaque "laundering" of the pointer. + void replaceBasePointer(llvm::Value *P) { + assert(isValid() && "pointer isn't valid"); + assert(P->getType() == Pointer.getPointer()->getType() && + "Pointer's type changed"); + Pointer.setPointer(P); + assert(isValid() && "pointer is invalid after replacement"); + } + + CharUnits getAlignment() const { return Alignment; } + + void setAlignment(CharUnits Value) { Alignment = Value; } + + llvm::Value *getBasePointer() const { + assert(isValid() && "pointer isn't valid"); + return Pointer.getPointer(); + } + + /// Return the type of the pointer value. + llvm::PointerType *getType() const { + return llvm::PointerType::get( + ElementType, + llvm::cast<llvm::PointerType>(Pointer.getPointer()->getType()) + ->getAddressSpace()); + } + + /// Return the type of the values stored in this address. + llvm::Type *getElementType() const { + assert(isValid()); + return ElementType; + } + + /// Return the address space that this address resides in. + unsigned getAddressSpace() const { return getType()->getAddressSpace(); } + + /// Return the IR name of the pointer value. + llvm::StringRef getName() const { return Pointer.getPointer()->getName(); } + + // This function is called only in CGBuilderBaseTy::CreateElementBitCast. + void setElementType(llvm::Type *Ty) { + assert(hasOffset() && + "this funcion shouldn't be called when there is no offset"); + ElementType = Ty; + } + + /// Whether the pointer is known not to be null. + KnownNonNull_t isKnownNonNull() const { + assert(isValid()); + return (KnownNonNull_t)Pointer.getInt(); + } + + Address setKnownNonNull() { + assert(isValid()); + Pointer.setInt(KnownNonNull); + return *this; + } + + bool hasOffset() const { return Offset; } + + llvm::Value *getOffset() const { return Offset; } + + /// Return the pointer contained in this class after authenticating it and + /// adding offset to it if necessary. + llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { + return getBasePointer(); + } + /// Return address with different pointer, but same element type and /// alignment. Address withPointer(llvm::Value *NewPointer, @@ -91,61 +232,59 @@ public: /// Return address with different alignment, but same pointer and element /// type. Address withAlignment(CharUnits NewAlignment) const { - return Address(getPointer(), getElementType(), NewAlignment, + return Address(Pointer.getPointer(), getElementType(), NewAlignment, isKnownNonNull()); } /// Return address with different element type, but same pointer and /// alignment. Address withElementType(llvm::Type *ElemTy) const { - return Address(getPointer(), ElemTy, getAlignment(), isKnownNonNull()); - } - - /// Whether the pointer is known not to be null. - KnownNonNull_t isKnownNonNull() const { - assert(isValid()); - return (KnownNonNull_t)PointerAndKnownNonNull.getInt(); - } - - /// Set the non-null bit. - Address setKnownNonNull() { - assert(isValid()); - PointerAndKnownNonNull.setInt(true); - return *this; + if (!hasOffset()) + return Address(getBasePointer(), ElemTy, getAlignment(), nullptr, + isKnownNonNull()); + Address A(*this); + A.ElementType = ElemTy; + return A; } }; +inline RawAddress::RawAddress(Address Addr) + : PointerAndKnownNonNull(Addr.isValid() ? Addr.getBasePointer() : nullptr, + Addr.isValid() ? Addr.isKnownNonNull() + : NotKnownNonNull), + ElementType(Addr.isValid() ? Addr.getElementType() : nullptr), + Alignment(Addr.isValid() ? Addr.getAlignment() : CharUnits::Zero()) {} + /// A specialization of Address that requires the address to be an /// LLVM Constant. -class ConstantAddress : public Address { - ConstantAddress(std::nullptr_t) : Address(nullptr) {} +class ConstantAddress : public RawAddress { + ConstantAddress(std::nullptr_t) : RawAddress(nullptr) {} public: ConstantAddress(llvm::Constant *pointer, llvm::Type *elementType, CharUnits alignment) - : Address(pointer, elementType, alignment) {} + : RawAddress(pointer, elementType, alignment) {} static ConstantAddress invalid() { return ConstantAddress(nullptr); } llvm::Constant *getPointer() const { - return llvm::cast<llvm::Constant>(Address::getPointer()); + return llvm::cast<llvm::Constant>(RawAddress::getPointer()); } ConstantAddress withElementType(llvm::Type *ElemTy) const { return ConstantAddress(getPointer(), ElemTy, getAlignment()); } - static bool isaImpl(Address addr) { + static bool isaImpl(RawAddress addr) { return llvm::isa<llvm::Constant>(addr.getPointer()); } - static ConstantAddress castImpl(Address addr) { + static ConstantAddress castImpl(RawAddress addr) { return ConstantAddress(llvm::cast<llvm::Constant>(addr.getPointer()), addr.getElementType(), addr.getAlignment()); } }; - } // Present a minimal LLVM-like casting interface. diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 82b30b8d815629d367a9282abf1b4b3be99cce63..1220c575d1df9f0818a8b7640774cf07a8aeccb1 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -101,20 +101,19 @@ namespace llvm { extern cl::opt<bool> PrintPipelinePasses; cl::opt<bool> ClRemoveTraps("clang-remove-traps", cl::Optional, - cl::desc("Insert remove-traps pass."), - cl::init(false)); + cl::desc("Insert remove-traps pass.")); // Experiment to move sanitizers earlier. static cl::opt<bool> ClSanitizeOnOptimizerEarlyEP( "sanitizer-early-opt-ep", cl::Optional, - cl::desc("Insert sanitizers on OptimizerEarlyEP."), cl::init(false)); + cl::desc("Insert sanitizers on OptimizerEarlyEP.")); extern cl::opt<InstrProfCorrelator::ProfCorrelatorKind> ProfileCorrelate; // Re-link builtin bitcodes after optimization cl::opt<bool> ClRelinkBuiltinBitcodePostop( "relink-builtin-bitcode-postop", cl::Optional, - cl::desc("Re-link builtin bitcodes after optimization."), cl::init(false)); + cl::desc("Re-link builtin bitcodes after optimization.")); } // namespace llvm namespace { diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp index fb03d013e8afc7ba7c9e952eadabd44ae9e005a9..d35ce0409d723258cd82ec955071efa6d850921e 100644 --- a/clang/lib/CodeGen/CGAtomic.cpp +++ b/clang/lib/CodeGen/CGAtomic.cpp @@ -80,7 +80,7 @@ namespace { AtomicSizeInBits = C.toBits( C.toCharUnitsFromBits(Offset + OrigBFI.Size + C.getCharWidth() - 1) .alignTo(lvalue.getAlignment())); - llvm::Value *BitFieldPtr = lvalue.getBitFieldPointer(); + llvm::Value *BitFieldPtr = lvalue.getRawBitFieldPointer(CGF); auto OffsetInChars = (C.toCharUnitsFromBits(OrigBFI.Offset) / lvalue.getAlignment()) * lvalue.getAlignment(); @@ -139,13 +139,13 @@ namespace { const LValue &getAtomicLValue() const { return LVal; } llvm::Value *getAtomicPointer() const { if (LVal.isSimple()) - return LVal.getPointer(CGF); + return LVal.emitRawPointer(CGF); else if (LVal.isBitField()) - return LVal.getBitFieldPointer(); + return LVal.getRawBitFieldPointer(CGF); else if (LVal.isVectorElt()) - return LVal.getVectorPointer(); + return LVal.getRawVectorPointer(CGF); assert(LVal.isExtVectorElt()); - return LVal.getExtVectorPointer(); + return LVal.getRawExtVectorPointer(CGF); } Address getAtomicAddress() const { llvm::Type *ElTy; @@ -197,11 +197,11 @@ namespace { llvm::Value *getScalarRValValueOrNull(RValue RVal) const; /// Converts an rvalue to integer value if needed. - llvm::Value *convertRValueToInt(RValue RVal, bool CastFP = true) const; + llvm::Value *convertRValueToInt(RValue RVal, bool CmpXchg = false) const; RValue ConvertToValueOrAtomic(llvm::Value *IntVal, AggValueSlot ResultSlot, SourceLocation Loc, bool AsValue, - bool CastFP = true) const; + bool CmpXchg = false) const; /// Copy an atomic r-value into atomic-layout memory. void emitCopyIntoMemory(RValue rvalue) const; @@ -264,7 +264,7 @@ namespace { llvm::AtomicOrdering AO, bool IsVolatile); /// Emits atomic load as LLVM instruction. llvm::Value *EmitAtomicLoadOp(llvm::AtomicOrdering AO, bool IsVolatile, - bool CastFP = true); + bool CmpXchg = false); /// Emits atomic compare-and-exchange op as a libcall. llvm::Value *EmitAtomicCompareExchangeLibcall( llvm::Value *ExpectedAddr, llvm::Value *DesiredAddr, @@ -368,7 +368,7 @@ bool AtomicInfo::emitMemSetZeroIfNecessary() const { return false; CGF.Builder.CreateMemSet( - addr.getPointer(), llvm::ConstantInt::get(CGF.Int8Ty, 0), + addr.emitRawPointer(CGF), llvm::ConstantInt::get(CGF.Int8Ty, 0), CGF.getContext().toCharUnitsFromBits(AtomicSizeInBits).getQuantity(), LVal.getAlignment().getAsAlign()); return true; @@ -1055,7 +1055,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { return getTargetHooks().performAddrSpaceCast( *this, V, AS, LangAS::opencl_generic, DestType, false); }; - Args.add(RValue::get(CastToGenericAddrSpace(Ptr.getPointer(), + + Args.add(RValue::get(CastToGenericAddrSpace(Ptr.emitRawPointer(*this), E->getPtr()->getType())), getContext().VoidPtrTy); @@ -1086,10 +1087,10 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { LibCallName = "__atomic_compare_exchange"; RetTy = getContext().BoolTy; HaveRetTy = true; - Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(), + Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this), E->getVal1()->getType())), getContext().VoidPtrTy); - Args.add(RValue::get(CastToGenericAddrSpace(Val2.getPointer(), + Args.add(RValue::get(CastToGenericAddrSpace(Val2.emitRawPointer(*this), E->getVal2()->getType())), getContext().VoidPtrTy); Args.add(RValue::get(Order), getContext().IntTy); @@ -1105,7 +1106,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { case AtomicExpr::AO__scoped_atomic_exchange: case AtomicExpr::AO__scoped_atomic_exchange_n: LibCallName = "__atomic_exchange"; - Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(), + Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this), E->getVal1()->getType())), getContext().VoidPtrTy); break; @@ -1120,7 +1121,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { LibCallName = "__atomic_store"; RetTy = getContext().VoidTy; HaveRetTy = true; - Args.add(RValue::get(CastToGenericAddrSpace(Val1.getPointer(), + Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this), E->getVal1()->getType())), getContext().VoidPtrTy); break; @@ -1199,7 +1200,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { if (!HaveRetTy) { // Value is returned through parameter before the order. RetTy = getContext().VoidTy; - Args.add(RValue::get(CastToGenericAddrSpace(Dest.getPointer(), RetTy)), + Args.add(RValue::get( + CastToGenericAddrSpace(Dest.emitRawPointer(*this), RetTy)), getContext().VoidPtrTy); } // Order is always the last parameter. @@ -1399,13 +1401,26 @@ RValue AtomicInfo::convertAtomicTempToRValue(Address addr, LVal.getBaseInfo(), TBAAAccessInfo())); } +/// Return true if \param ValTy is a type that should be casted to integer +/// around the atomic memory operation. If \param CmpXchg is true, then the +/// cast of a floating point type is made as that instruction can not have +/// floating point operands. TODO: Allow compare-and-exchange and FP - see +/// comment in AtomicExpandPass.cpp. +static bool shouldCastToInt(llvm::Type *ValTy, bool CmpXchg) { + if (ValTy->isFloatingPointTy()) + return ValTy->isX86_FP80Ty() || CmpXchg; + return !ValTy->isIntegerTy() && !ValTy->isPointerTy(); +} + RValue AtomicInfo::ConvertToValueOrAtomic(llvm::Value *Val, AggValueSlot ResultSlot, SourceLocation Loc, bool AsValue, - bool CastFP) const { + bool CmpXchg) const { // Try not to in some easy cases. - assert((Val->getType()->isIntegerTy() || Val->getType()->isIEEELikeFPTy()) && - "Expected integer or floating point value"); + assert((Val->getType()->isIntegerTy() || Val->getType()->isPointerTy() || + Val->getType()->isIEEELikeFPTy()) && + "Expected integer, pointer or floating point value when converting " + "result."); if (getEvaluationKind() == TEK_Scalar && (((!LVal.isBitField() || LVal.getBitFieldInfo().Size == ValueSizeInBits) && @@ -1414,13 +1429,12 @@ RValue AtomicInfo::ConvertToValueOrAtomic(llvm::Value *Val, auto *ValTy = AsValue ? CGF.ConvertTypeForMem(ValueTy) : getAtomicAddress().getElementType(); - if (ValTy->isIntegerTy() || (!CastFP && ValTy->isIEEELikeFPTy())) { + if (!shouldCastToInt(ValTy, CmpXchg)) { assert((!ValTy->isIntegerTy() || Val->getType() == ValTy) && "Different integer types."); return RValue::get(CGF.EmitFromMemory(Val, ValueTy)); - } else if (ValTy->isPointerTy()) - return RValue::get(CGF.Builder.CreateIntToPtr(Val, ValTy)); - else if (llvm::CastInst::isBitCastable(Val->getType(), ValTy)) + } + if (llvm::CastInst::isBitCastable(Val->getType(), ValTy)) return RValue::get(CGF.Builder.CreateBitCast(Val, ValTy)); } @@ -1457,10 +1471,10 @@ void AtomicInfo::EmitAtomicLoadLibcall(llvm::Value *AddForLoaded, } llvm::Value *AtomicInfo::EmitAtomicLoadOp(llvm::AtomicOrdering AO, - bool IsVolatile, bool CastFP) { + bool IsVolatile, bool CmpXchg) { // Okay, we're doing this natively. Address Addr = getAtomicAddress(); - if (!(Addr.getElementType()->isIEEELikeFPTy() && !CastFP)) + if (shouldCastToInt(Addr.getElementType(), CmpXchg)) Addr = castToAtomicIntPointer(Addr); llvm::LoadInst *Load = CGF.Builder.CreateLoad(Addr, "atomic-load"); Load->setAtomic(AO); @@ -1513,7 +1527,7 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc, } else TempAddr = CreateTempAlloca(); - EmitAtomicLoadLibcall(TempAddr.getPointer(), AO, IsVolatile); + EmitAtomicLoadLibcall(TempAddr.emitRawPointer(CGF), AO, IsVolatile); // Okay, turn that back into the original value or whole atomic (for // non-simple lvalues) type. @@ -1521,7 +1535,7 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc, } // Okay, we're doing this natively. - auto *Load = EmitAtomicLoadOp(AO, IsVolatile, /*CastFP=*/false); + auto *Load = EmitAtomicLoadOp(AO, IsVolatile); // If we're ignoring an aggregate return, don't do anything. if (getEvaluationKind() == TEK_Aggregate && ResultSlot.isIgnored()) @@ -1529,8 +1543,7 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc, // Okay, turn that back into the original value or atomic (for non-simple // lvalues) type. - return ConvertToValueOrAtomic(Load, ResultSlot, Loc, AsValue, - /*CastFP=*/false); + return ConvertToValueOrAtomic(Load, ResultSlot, Loc, AsValue); } /// Emit a load from an l-value of atomic type. Note that the r-value @@ -1599,20 +1612,17 @@ llvm::Value *AtomicInfo::getScalarRValValueOrNull(RValue RVal) const { return nullptr; } -llvm::Value *AtomicInfo::convertRValueToInt(RValue RVal, bool CastFP) const { +llvm::Value *AtomicInfo::convertRValueToInt(RValue RVal, bool CmpXchg) const { // If we've got a scalar value of the right size, try to avoid going // through memory. Floats get casted if needed by AtomicExpandPass. if (llvm::Value *Value = getScalarRValValueOrNull(RVal)) { - if (isa<llvm::IntegerType>(Value->getType()) || - (!CastFP && Value->getType()->isIEEELikeFPTy())) + if (!shouldCastToInt(Value->getType(), CmpXchg)) return CGF.EmitToMemory(Value, ValueTy); else { llvm::IntegerType *InputIntTy = llvm::IntegerType::get( CGF.getLLVMContext(), LVal.isSimple() ? getValueSizeInBits() : getAtomicSizeInBits()); - if (isa<llvm::PointerType>(Value->getType())) - return CGF.Builder.CreatePtrToInt(Value, InputIntTy); - else if (llvm::BitCastInst::isBitCastable(Value->getType(), InputIntTy)) + if (llvm::BitCastInst::isBitCastable(Value->getType(), InputIntTy)) return CGF.Builder.CreateBitCast(Value, InputIntTy); } } @@ -1673,9 +1683,9 @@ std::pair<RValue, llvm::Value *> AtomicInfo::EmitAtomicCompareExchange( if (shouldUseLibcall()) { // Produce a source address. Address ExpectedAddr = materializeRValue(Expected); - Address DesiredAddr = materializeRValue(Desired); - auto *Res = EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(), - DesiredAddr.getPointer(), + llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF); + llvm::Value *DesiredPtr = materializeRValue(Desired).emitRawPointer(CGF); + auto *Res = EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, Success, Failure); return std::make_pair( convertAtomicTempToRValue(ExpectedAddr, AggValueSlot::ignored(), @@ -1685,13 +1695,14 @@ std::pair<RValue, llvm::Value *> AtomicInfo::EmitAtomicCompareExchange( // If we've got a scalar value of the right size, try to avoid going // through memory. - auto *ExpectedVal = convertRValueToInt(Expected); - auto *DesiredVal = convertRValueToInt(Desired); + auto *ExpectedVal = convertRValueToInt(Expected, /*CmpXchg=*/true); + auto *DesiredVal = convertRValueToInt(Desired, /*CmpXchg=*/true); auto Res = EmitAtomicCompareExchangeOp(ExpectedVal, DesiredVal, Success, Failure, IsWeak); return std::make_pair( ConvertToValueOrAtomic(Res.first, AggValueSlot::ignored(), - SourceLocation(), /*AsValue=*/false), + SourceLocation(), /*AsValue=*/false, + /*CmpXchg=*/true), Res.second); } @@ -1757,7 +1768,7 @@ void AtomicInfo::EmitAtomicUpdateLibcall( Address ExpectedAddr = CreateTempAlloca(); - EmitAtomicLoadLibcall(ExpectedAddr.getPointer(), AO, IsVolatile); + EmitAtomicLoadLibcall(ExpectedAddr.emitRawPointer(CGF), AO, IsVolatile); auto *ContBB = CGF.createBasicBlock("atomic_cont"); auto *ExitBB = CGF.createBasicBlock("atomic_exit"); CGF.EmitBlock(ContBB); @@ -1771,10 +1782,10 @@ void AtomicInfo::EmitAtomicUpdateLibcall( AggValueSlot::ignored(), SourceLocation(), /*AsValue=*/false); EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, DesiredAddr); + llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF); + llvm::Value *DesiredPtr = DesiredAddr.emitRawPointer(CGF); auto *Res = - EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(), - DesiredAddr.getPointer(), - AO, Failure); + EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, AO, Failure); CGF.Builder.CreateCondBr(Res, ExitBB, ContBB); CGF.EmitBlock(ExitBB, /*IsFinished=*/true); } @@ -1785,7 +1796,7 @@ void AtomicInfo::EmitAtomicUpdateOp( auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO); // Do the atomic load. - auto *OldVal = EmitAtomicLoadOp(Failure, IsVolatile); + auto *OldVal = EmitAtomicLoadOp(Failure, IsVolatile, /*CmpXchg=*/true); // For non-simple lvalues perform compare-and-swap procedure. auto *ContBB = CGF.createBasicBlock("atomic_cont"); auto *ExitBB = CGF.createBasicBlock("atomic_exit"); @@ -1801,7 +1812,8 @@ void AtomicInfo::EmitAtomicUpdateOp( CGF.Builder.CreateStore(PHI, NewAtomicIntAddr); } auto OldRVal = ConvertToValueOrAtomic(PHI, AggValueSlot::ignored(), - SourceLocation(), /*AsValue=*/false); + SourceLocation(), /*AsValue=*/false, + /*CmpXchg=*/true); EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, NewAtomicAddr); auto *DesiredVal = CGF.Builder.CreateLoad(NewAtomicIntAddr); // Try to write new value using cmpxchg operation. @@ -1843,7 +1855,7 @@ void AtomicInfo::EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO, Address ExpectedAddr = CreateTempAlloca(); - EmitAtomicLoadLibcall(ExpectedAddr.getPointer(), AO, IsVolatile); + EmitAtomicLoadLibcall(ExpectedAddr.emitRawPointer(CGF), AO, IsVolatile); auto *ContBB = CGF.createBasicBlock("atomic_cont"); auto *ExitBB = CGF.createBasicBlock("atomic_exit"); CGF.EmitBlock(ContBB); @@ -1854,10 +1866,10 @@ void AtomicInfo::EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO, CGF.Builder.CreateStore(OldVal, DesiredAddr); } EmitAtomicUpdateValue(CGF, *this, UpdateRVal, DesiredAddr); + llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF); + llvm::Value *DesiredPtr = DesiredAddr.emitRawPointer(CGF); auto *Res = - EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(), - DesiredAddr.getPointer(), - AO, Failure); + EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, AO, Failure); CGF.Builder.CreateCondBr(Res, ExitBB, ContBB); CGF.EmitBlock(ExitBB, /*IsFinished=*/true); } @@ -1867,7 +1879,7 @@ void AtomicInfo::EmitAtomicUpdateOp(llvm::AtomicOrdering AO, RValue UpdateRVal, auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO); // Do the atomic load. - auto *OldVal = EmitAtomicLoadOp(Failure, IsVolatile); + auto *OldVal = EmitAtomicLoadOp(Failure, IsVolatile, /*CmpXchg=*/true); // For non-simple lvalues perform compare-and-swap procedure. auto *ContBB = CGF.createBasicBlock("atomic_cont"); auto *ExitBB = CGF.createBasicBlock("atomic_exit"); @@ -1957,7 +1969,8 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, args.add(RValue::get(atomics.getAtomicSizeValue()), getContext().getSizeType()); args.add(RValue::get(atomics.getAtomicPointer()), getContext().VoidPtrTy); - args.add(RValue::get(srcAddr.getPointer()), getContext().VoidPtrTy); + args.add(RValue::get(srcAddr.emitRawPointer(*this)), + getContext().VoidPtrTy); args.add( RValue::get(llvm::ConstantInt::get(IntTy, (int)llvm::toCABI(AO))), getContext().IntTy); @@ -1966,21 +1979,16 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, } // Okay, we're doing this natively. - llvm::Value *ValToStore = - atomics.convertRValueToInt(rvalue, /*CastFP=*/false); + llvm::Value *ValToStore = atomics.convertRValueToInt(rvalue); // Do the atomic store. Address Addr = atomics.getAtomicAddress(); - bool ShouldCastToInt = true; if (llvm::Value *Value = atomics.getScalarRValValueOrNull(rvalue)) - if (isa<llvm::IntegerType>(Value->getType()) || - Value->getType()->isIEEELikeFPTy()) - ShouldCastToInt = false; - if (ShouldCastToInt) { - Addr = atomics.castToAtomicIntPointer(Addr); - ValToStore = Builder.CreateIntCast(ValToStore, Addr.getElementType(), - /*isSigned=*/false); - } + if (shouldCastToInt(Value->getType(), /*CmpXchg=*/false)) { + Addr = atomics.castToAtomicIntPointer(Addr); + ValToStore = Builder.CreateIntCast(ValToStore, Addr.getElementType(), + /*isSigned=*/false); + } llvm::StoreInst *store = Builder.CreateStore(ValToStore, Addr); if (AO == llvm::AtomicOrdering::Acquire) diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 0cbace7b7f7bbd5068c4cfe9c7b639e0100d7aea..a01f2c7c979840ca8be2cf10c6462633e70855bb 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -36,7 +36,8 @@ CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name) : Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false), NoEscape(false), HasCXXObject(false), UsesStret(false), HasCapturedVariableLayout(false), CapturesNonExternalType(false), - LocalAddress(Address::invalid()), StructureType(nullptr), Block(block) { + LocalAddress(RawAddress::invalid()), StructureType(nullptr), + Block(block) { // Skip asm prefix, if any. 'name' is usually taken directly from // the mangled name of the enclosing function. @@ -794,7 +795,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { // Otherwise, we have to emit this as a local block. - Address blockAddr = blockInfo.LocalAddress; + RawAddress blockAddr = blockInfo.LocalAddress; assert(blockAddr.isValid() && "block has no address!"); llvm::Constant *isa; @@ -939,7 +940,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { if (CI.isNested()) byrefPointer = Builder.CreateLoad(src, "byref.capture"); else - byrefPointer = src.getPointer(); + byrefPointer = src.emitRawPointer(*this); // Write that void* into the capture field. Builder.CreateStore(byrefPointer, blockField); @@ -961,10 +962,10 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { } // If it's a reference variable, copy the reference into the block field. - } else if (type->isReferenceType()) { - Builder.CreateStore(src.getPointer(), blockField); + } else if (auto refType = type->getAs<ReferenceType>()) { + Builder.CreateStore(src.emitRawPointer(*this), blockField); - // If type is const-qualified, copy the value into the block field. + // If type is const-qualified, copy the value into the block field. } else if (type.isConstQualified() && type.getObjCLifetime() == Qualifiers::OCL_Strong && CGM.getCodeGenOpts().OptimizationLevel != 0) { @@ -1377,7 +1378,7 @@ void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D, // Allocate a stack slot like for any local variable to guarantee optimal // debug info at -O0. The mem2reg pass will eliminate it when optimizing. - Address alloc = CreateMemTemp(D->getType(), D->getName() + ".addr"); + RawAddress alloc = CreateMemTemp(D->getType(), D->getName() + ".addr"); Builder.CreateStore(arg, alloc); if (CGDebugInfo *DI = getDebugInfo()) { if (CGM.getCodeGenOpts().hasReducedDebugInfo()) { @@ -1497,7 +1498,7 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction( // frame setup instruction by llvm::DwarfDebug::beginFunction(). auto NL = ApplyDebugLocation::CreateEmpty(*this); Builder.CreateStore(BlockPointer, Alloca); - BlockPointerDbgLoc = Alloca.getPointer(); + BlockPointerDbgLoc = Alloca.emitRawPointer(*this); } // If we have a C++ 'this' reference, go ahead and force it into @@ -1540,7 +1541,10 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction( llvm::BasicBlock *resume = Builder.GetInsertBlock(); // Go back to the entry. - ++entry_ptr; + if (entry_ptr->getNextNonDebugInstruction()) + entry_ptr = entry_ptr->getNextNonDebugInstruction()->getIterator(); + else + entry_ptr = entry->end(); Builder.SetInsertPoint(entry, entry_ptr); // Emit debug information for all the DeclRefExprs. @@ -1554,8 +1558,8 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction( const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); if (capture.isConstant()) { auto addr = LocalDeclMap.find(variable)->second; - (void)DI->EmitDeclareOfAutoVariable(variable, addr.getPointer(), - Builder); + (void)DI->EmitDeclareOfAutoVariable( + variable, addr.emitRawPointer(*this), Builder); continue; } @@ -1659,7 +1663,7 @@ struct CallBlockRelease final : EHScopeStack::Cleanup { if (LoadBlockVarAddr) { BlockVarAddr = CGF.Builder.CreateLoad(Addr); } else { - BlockVarAddr = Addr.getPointer(); + BlockVarAddr = Addr.emitRawPointer(CGF); } CGF.BuildBlockRelease(BlockVarAddr, FieldFlags, CanThrow); @@ -1959,13 +1963,15 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { // it. It's not quite worth the annoyance to avoid creating it in the // first place. if (!needsEHCleanup(captureType.isDestructedType())) - cast<llvm::Instruction>(dstField.getPointer())->eraseFromParent(); + if (auto *I = + cast_or_null<llvm::Instruction>(dstField.getBasePointer())) + I->eraseFromParent(); } break; } case BlockCaptureEntityKind::BlockObject: { llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src"); - llvm::Value *dstAddr = dstField.getPointer(); + llvm::Value *dstAddr = dstField.emitRawPointer(*this); llvm::Value *args[] = { dstAddr, srcValue, llvm::ConstantInt::get(Int32Ty, flags.getBitMask()) }; @@ -2136,7 +2142,7 @@ public: llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags); llvm::FunctionCallee fn = CGF.CGM.getBlockObjectAssign(); - llvm::Value *args[] = { destField.getPointer(), srcValue, flagsVal }; + llvm::Value *args[] = {destField.emitRawPointer(CGF), srcValue, flagsVal}; CGF.EmitNounwindRuntimeCall(fn, args); } @@ -2693,7 +2699,8 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) { storeHeaderField(V, getPointerSize(), "byref.isa"); // Store the address of the variable into its own forwarding pointer. - storeHeaderField(addr.getPointer(), getPointerSize(), "byref.forwarding"); + storeHeaderField(addr.emitRawPointer(*this), getPointerSize(), + "byref.forwarding"); // Blocks ABI: // c) the flags field is set to either 0 if no helper functions are diff --git a/clang/lib/CodeGen/CGBlocks.h b/clang/lib/CodeGen/CGBlocks.h index 4ef1ae9f33655cb8b76fbf19af4557be46f140c4..8d10c4f69b2026b4c5d254eadc2d037e88058d36 100644 --- a/clang/lib/CodeGen/CGBlocks.h +++ b/clang/lib/CodeGen/CGBlocks.h @@ -271,7 +271,8 @@ public: /// The block's captures. Non-constant captures are sorted by their offsets. llvm::SmallVector<Capture, 4> SortedCaptures; - Address LocalAddress; + // Currently we assume that block-pointer types are never signed. + RawAddress LocalAddress; llvm::StructType *StructureType; const BlockDecl *Block; const BlockExpr *BlockExpression; diff --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h index bf5ab171d720d9b148544ac6467652a5efea0edb..6dd9da7c4cadefb2063b5f55fdf3230476128c22 100644 --- a/clang/lib/CodeGen/CGBuilder.h +++ b/clang/lib/CodeGen/CGBuilder.h @@ -10,7 +10,9 @@ #define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H #include "Address.h" +#include "CGValue.h" #include "CodeGenTypeCache.h" +#include "llvm/Analysis/Utils/Local.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Type.h" @@ -18,12 +20,15 @@ namespace clang { namespace CodeGen { +class CGBuilderTy; class CodeGenFunction; /// This is an IRBuilder insertion helper that forwards to /// CodeGenFunction::InsertHelper, which adds necessary metadata to /// instructions. class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter { + friend CGBuilderTy; + public: CGBuilderInserter() = default; explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {} @@ -43,10 +48,42 @@ typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy> CGBuilderBaseTy; class CGBuilderTy : public CGBuilderBaseTy { + friend class Address; + /// Storing a reference to the type cache here makes it a lot easier /// to build natural-feeling, target-specific IR. const CodeGenTypeCache &TypeCache; + CodeGenFunction *getCGF() const { return getInserter().CGF; } + + llvm::Value *emitRawPointerFromAddress(Address Addr) const { + return Addr.getBasePointer(); + } + + template <bool IsInBounds> + Address createConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, + const llvm::Twine &Name) { + const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); + llvm::GetElementPtrInst *GEP; + if (IsInBounds) + GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32( + Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1, + Name)); + else + GEP = cast<llvm::GetElementPtrInst>(CreateConstGEP2_32( + Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1, + Name)); + llvm::APInt Offset( + DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0, + /*isSigned=*/true); + if (!GEP->accumulateConstantOffset(DL, Offset)) + llvm_unreachable("offset of GEP with constants is always computable"); + return Address(GEP, GEP->getResultElementType(), + Addr.getAlignment().alignmentAtOffset( + CharUnits::fromQuantity(Offset.getSExtValue())), + IsInBounds ? Addr.isKnownNonNull() : NotKnownNonNull); + } + public: CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C) : CGBuilderBaseTy(C), TypeCache(TypeCache) {} @@ -69,20 +106,22 @@ public: // Note that we intentionally hide the CreateLoad APIs that don't // take an alignment. llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") { - return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), + return CreateAlignedLoad(Addr.getElementType(), + emitRawPointerFromAddress(Addr), Addr.getAlignment().getAsAlign(), Name); } llvm::LoadInst *CreateLoad(Address Addr, const char *Name) { // This overload is required to prevent string literals from // ending up in the IsVolatile overload. - return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), + return CreateAlignedLoad(Addr.getElementType(), + emitRawPointerFromAddress(Addr), Addr.getAlignment().getAsAlign(), Name); } llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile, const llvm::Twine &Name = "") { - return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), - Addr.getAlignment().getAsAlign(), IsVolatile, - Name); + return CreateAlignedLoad( + Addr.getElementType(), emitRawPointerFromAddress(Addr), + Addr.getAlignment().getAsAlign(), IsVolatile, Name); } using CGBuilderBaseTy::CreateAlignedLoad; @@ -96,7 +135,7 @@ public: // take an alignment. llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile = false) { - return CreateAlignedStore(Val, Addr.getPointer(), + return CreateAlignedStore(Val, emitRawPointerFromAddress(Addr), Addr.getAlignment().getAsAlign(), IsVolatile); } @@ -132,33 +171,41 @@ public: llvm::AtomicOrdering FailureOrdering, llvm::SyncScope::ID SSID = llvm::SyncScope::System) { return CGBuilderBaseTy::CreateAtomicCmpXchg( - Addr.getPointer(), Cmp, New, Addr.getAlignment().getAsAlign(), - SuccessOrdering, FailureOrdering, SSID); + Addr.emitRawPointer(*getCGF()), Cmp, New, + Addr.getAlignment().getAsAlign(), SuccessOrdering, FailureOrdering, + SSID); } llvm::AtomicRMWInst * CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, llvm::AtomicOrdering Ordering, llvm::SyncScope::ID SSID = llvm::SyncScope::System) { - return CGBuilderBaseTy::CreateAtomicRMW(Op, Addr.getPointer(), Val, - Addr.getAlignment().getAsAlign(), - Ordering, SSID); + return CGBuilderBaseTy::CreateAtomicRMW( + Op, Addr.emitRawPointer(*getCGF()), Val, + Addr.getAlignment().getAsAlign(), Ordering, SSID); } using CGBuilderBaseTy::CreateAddrSpaceCast; Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, + llvm::Type *ElementTy, const llvm::Twine &Name = "") { - return Addr.withPointer(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name), - Addr.isKnownNonNull()); + if (!Addr.hasOffset()) + return Address(CreateAddrSpaceCast(Addr.getBasePointer(), Ty, Name), + ElementTy, Addr.getAlignment(), nullptr, + Addr.isKnownNonNull()); + // Eagerly force a raw address if these is an offset. + return RawAddress( + CreateAddrSpaceCast(Addr.emitRawPointer(*getCGF()), Ty, Name), + ElementTy, Addr.getAlignment(), Addr.isKnownNonNull()); } using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast; Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name = "") { - llvm::Value *Ptr = - CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name); - return Address(Ptr, ElementTy, Addr.getAlignment(), Addr.isKnownNonNull()); + if (Addr.getType()->getAddressSpace() == Ty->getPointerAddressSpace()) + return Addr.withElementType(ElementTy); + return CreateAddrSpaceCast(Addr, Ty, ElementTy, Name); } /// Given @@ -176,10 +223,11 @@ public: const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); - return Address( - CreateStructGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), - ElTy->getElementType(Index), - Addr.getAlignment().alignmentAtOffset(Offset), Addr.isKnownNonNull()); + return Address(CreateStructGEP(Addr.getElementType(), Addr.getBasePointer(), + Index, Name), + ElTy->getElementType(Index), + Addr.getAlignment().alignmentAtOffset(Offset), + Addr.isKnownNonNull()); } /// Given @@ -198,7 +246,7 @@ public: CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType())); return Address( - CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), + CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(), {getSize(CharUnits::Zero()), getSize(Index)}, Name), ElTy->getElementType(), Addr.getAlignment().alignmentAtOffset(Index * EltSize), @@ -216,10 +264,10 @@ public: const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); - return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), - getSize(Index), Name), - ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize), - Addr.isKnownNonNull()); + return Address( + CreateInBoundsGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name), + ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize), + Addr.isKnownNonNull()); } /// Given @@ -229,110 +277,133 @@ public: /// where i64 is actually the target word size. Address CreateConstGEP(Address Addr, uint64_t Index, const llvm::Twine &Name = "") { + llvm::Type *ElTy = Addr.getElementType(); const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); - CharUnits EltSize = - CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType())); + CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); - return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), - getSize(Index), Name), + return Address(CreateGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name), Addr.getElementType(), - Addr.getAlignment().alignmentAtOffset(Index * EltSize), - NotKnownNonNull); + Addr.getAlignment().alignmentAtOffset(Index * EltSize)); } /// Create GEP with single dynamic index. The address alignment is reduced /// according to the element size. using CGBuilderBaseTy::CreateGEP; - Address CreateGEP(Address Addr, llvm::Value *Index, + Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name = "") { const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType())); return Address( - CreateGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), + CreateGEP(Addr.getElementType(), Addr.emitRawPointer(CGF), Index, Name), Addr.getElementType(), - Addr.getAlignment().alignmentOfArrayElement(EltSize), NotKnownNonNull); + Addr.getAlignment().alignmentOfArrayElement(EltSize)); } /// Given a pointer to i8, adjust it by a given constant offset. Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name = "") { assert(Addr.getElementType() == TypeCache.Int8Ty); - return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), - getSize(Offset), Name), - Addr.getElementType(), - Addr.getAlignment().alignmentAtOffset(Offset), - Addr.isKnownNonNull()); + return Address( + CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(), + getSize(Offset), Name), + Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(Offset), + Addr.isKnownNonNull()); } + Address CreateConstByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name = "") { assert(Addr.getElementType() == TypeCache.Int8Ty); - return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), + return Address(CreateGEP(Addr.getElementType(), Addr.getBasePointer(), getSize(Offset), Name), Addr.getElementType(), - Addr.getAlignment().alignmentAtOffset(Offset), - NotKnownNonNull); + Addr.getAlignment().alignmentAtOffset(Offset)); } using CGBuilderBaseTy::CreateConstInBoundsGEP2_32; Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, const llvm::Twine &Name = "") { - const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); + return createConstGEP2_32<true>(Addr, Idx0, Idx1, Name); + } - auto *GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32( - Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name)); - llvm::APInt Offset( - DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0, - /*isSigned=*/true); - if (!GEP->accumulateConstantOffset(DL, Offset)) - llvm_unreachable("offset of GEP with constants is always computable"); - return Address(GEP, GEP->getResultElementType(), - Addr.getAlignment().alignmentAtOffset( - CharUnits::fromQuantity(Offset.getSExtValue())), - Addr.isKnownNonNull()); + using CGBuilderBaseTy::CreateConstGEP2_32; + Address CreateConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, + const llvm::Twine &Name = "") { + return createConstGEP2_32<false>(Addr, Idx0, Idx1, Name); + } + + Address CreateGEP(Address Addr, ArrayRef<llvm::Value *> IdxList, + llvm::Type *ElementType, CharUnits Align, + const Twine &Name = "") { + llvm::Value *Ptr = emitRawPointerFromAddress(Addr); + return RawAddress(CreateGEP(Addr.getElementType(), Ptr, IdxList, Name), + ElementType, Align); + } + + using CGBuilderBaseTy::CreateInBoundsGEP; + Address CreateInBoundsGEP(Address Addr, ArrayRef<llvm::Value *> IdxList, + llvm::Type *ElementType, CharUnits Align, + const Twine &Name = "") { + return RawAddress(CreateInBoundsGEP(Addr.getElementType(), + emitRawPointerFromAddress(Addr), + IdxList, Name), + ElementType, Align, Addr.isKnownNonNull()); + } + + using CGBuilderBaseTy::CreateIsNull; + llvm::Value *CreateIsNull(Address Addr, const Twine &Name = "") { + if (!Addr.hasOffset()) + return CreateIsNull(Addr.getBasePointer(), Name); + // The pointer isn't null if Addr has an offset since offsets can always + // be applied inbound. + return llvm::ConstantInt::getFalse(Context); } using CGBuilderBaseTy::CreateMemCpy; llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile = false) { - return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(), - Src.getPointer(), Src.getAlignment().getAsAlign(), Size, - IsVolatile); + llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); + llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); + return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, + Src.getAlignment().getAsAlign(), Size, IsVolatile); } llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size, bool IsVolatile = false) { - return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(), - Src.getPointer(), Src.getAlignment().getAsAlign(), Size, - IsVolatile); + llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); + llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); + return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, + Src.getAlignment().getAsAlign(), Size, IsVolatile); } using CGBuilderBaseTy::CreateMemCpyInline; llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) { - return CreateMemCpyInline( - Dest.getPointer(), Dest.getAlignment().getAsAlign(), Src.getPointer(), - Src.getAlignment().getAsAlign(), getInt64(Size)); + llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); + llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); + return CreateMemCpyInline(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, + Src.getAlignment().getAsAlign(), getInt64(Size)); } using CGBuilderBaseTy::CreateMemMove; llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile = false) { - return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getAsAlign(), - Src.getPointer(), Src.getAlignment().getAsAlign(), - Size, IsVolatile); + llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); + llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); + return CreateMemMove(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, + Src.getAlignment().getAsAlign(), Size, IsVolatile); } using CGBuilderBaseTy::CreateMemSet; llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value, llvm::Value *Size, bool IsVolatile = false) { - return CreateMemSet(Dest.getPointer(), Value, Size, + return CreateMemSet(emitRawPointerFromAddress(Dest), Value, Size, Dest.getAlignment().getAsAlign(), IsVolatile); } using CGBuilderBaseTy::CreateMemSetInline; llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value, uint64_t Size) { - return CreateMemSetInline(Dest.getPointer(), + return CreateMemSetInline(emitRawPointerFromAddress(Dest), Dest.getAlignment().getAsAlign(), Value, getInt64(Size)); } @@ -346,16 +417,31 @@ public: const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); - return Address(CreatePreserveStructAccessIndex(ElTy, Addr.getPointer(), - Index, FieldIndex, DbgInfo), - ElTy->getElementType(Index), - Addr.getAlignment().alignmentAtOffset(Offset)); + return Address( + CreatePreserveStructAccessIndex(ElTy, emitRawPointerFromAddress(Addr), + Index, FieldIndex, DbgInfo), + ElTy->getElementType(Index), + Addr.getAlignment().alignmentAtOffset(Offset)); + } + + using CGBuilderBaseTy::CreatePreserveUnionAccessIndex; + Address CreatePreserveUnionAccessIndex(Address Addr, unsigned FieldIndex, + llvm::MDNode *DbgInfo) { + Addr.replaceBasePointer(CreatePreserveUnionAccessIndex( + Addr.getBasePointer(), FieldIndex, DbgInfo)); + return Addr; } using CGBuilderBaseTy::CreateLaunderInvariantGroup; Address CreateLaunderInvariantGroup(Address Addr) { - return Addr.withPointer(CreateLaunderInvariantGroup(Addr.getPointer()), - Addr.isKnownNonNull()); + Addr.replaceBasePointer(CreateLaunderInvariantGroup(Addr.getBasePointer())); + return Addr; + } + + using CGBuilderBaseTy::CreateStripInvariantGroup; + Address CreateStripInvariantGroup(Address Addr) { + Addr.replaceBasePointer(CreateStripInvariantGroup(Addr.getBasePointer())); + return Addr; } }; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 93ab465079777bf9ad70c2bae38a0e4b4d1a39fe..483f9c26859923fa38920d7e670fe3ba2b1373d7 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -792,7 +792,8 @@ EncompassingIntegerType(ArrayRef<struct WidthAndSignedness> Types) { Value *CodeGenFunction::EmitVAStartEnd(Value *ArgValue, bool IsStart) { Intrinsic::ID inst = IsStart ? Intrinsic::vastart : Intrinsic::vaend; - return Builder.CreateCall(CGM.getIntrinsic(inst), ArgValue); + return Builder.CreateCall(CGM.getIntrinsic(inst, {ArgValue->getType()}), + ArgValue); } /// Checks if using the result of __builtin_object_size(p, @p From) in place of @@ -858,7 +859,7 @@ static unsigned CountCountedByAttrs(const RecordDecl *RD) { for (const Decl *D : RD->decls()) { if (const auto *FD = dyn_cast<FieldDecl>(D); - FD && FD->hasAttr<CountedByAttr>()) { + FD && FD->getType()->isCountAttributedType()) { return ++Num; } @@ -956,7 +957,7 @@ CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type, // }; // }; // - // We don't konw which 'count' to use in this scenario: + // We don't know which 'count' to use in this scenario: // // size_t get_size(struct union_of_fams *p) { // return __builtin_dynamic_object_size(p, 1); @@ -975,7 +976,7 @@ CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type, FindFlexibleArrayMemberField(Ctx, OuterRD, FAMName, Offset); Offset = Ctx.toCharUnitsFromBits(Offset).getQuantity(); - if (!FAMDecl || !FAMDecl->hasAttr<CountedByAttr>()) + if (!FAMDecl || !FAMDecl->getType()->isCountAttributedType()) // No flexible array member found or it doesn't have the "counted_by" // attribute. return nullptr; @@ -1130,8 +1131,92 @@ struct BitTest { static BitTest decodeBitTestBuiltin(unsigned BuiltinID); }; + +// Returns the first convergence entry/loop/anchor instruction found in |BB|. +// std::nullptr otherwise. +llvm::IntrinsicInst *getConvergenceToken(llvm::BasicBlock *BB) { + for (auto &I : *BB) { + auto *II = dyn_cast<llvm::IntrinsicInst>(&I); + if (II && isConvergenceControlIntrinsic(II->getIntrinsicID())) + return II; + } + return nullptr; +} + } // namespace +llvm::CallBase * +CodeGenFunction::addConvergenceControlToken(llvm::CallBase *Input, + llvm::Value *ParentToken) { + llvm::Value *bundleArgs[] = {ParentToken}; + llvm::OperandBundleDef OB("convergencectrl", bundleArgs); + auto Output = llvm::CallBase::addOperandBundle( + Input, llvm::LLVMContext::OB_convergencectrl, OB, Input); + Input->replaceAllUsesWith(Output); + Input->eraseFromParent(); + return Output; +} + +llvm::IntrinsicInst * +CodeGenFunction::emitConvergenceLoopToken(llvm::BasicBlock *BB, + llvm::Value *ParentToken) { + CGBuilderTy::InsertPoint IP = Builder.saveIP(); + Builder.SetInsertPoint(&BB->front()); + auto CB = Builder.CreateIntrinsic( + llvm::Intrinsic::experimental_convergence_loop, {}, {}); + Builder.restoreIP(IP); + + auto I = addConvergenceControlToken(CB, ParentToken); + return cast<llvm::IntrinsicInst>(I); +} + +llvm::IntrinsicInst * +CodeGenFunction::getOrEmitConvergenceEntryToken(llvm::Function *F) { + auto *BB = &F->getEntryBlock(); + auto *token = getConvergenceToken(BB); + if (token) + return token; + + // Adding a convergence token requires the function to be marked as + // convergent. + F->setConvergent(); + + CGBuilderTy::InsertPoint IP = Builder.saveIP(); + Builder.SetInsertPoint(&BB->front()); + auto I = Builder.CreateIntrinsic( + llvm::Intrinsic::experimental_convergence_entry, {}, {}); + assert(isa<llvm::IntrinsicInst>(I)); + Builder.restoreIP(IP); + + return cast<llvm::IntrinsicInst>(I); +} + +llvm::IntrinsicInst * +CodeGenFunction::getOrEmitConvergenceLoopToken(const LoopInfo *LI) { + assert(LI != nullptr); + + auto *token = getConvergenceToken(LI->getHeader()); + if (token) + return token; + + llvm::IntrinsicInst *PII = + LI->getParent() + ? emitConvergenceLoopToken( + LI->getHeader(), getOrEmitConvergenceLoopToken(LI->getParent())) + : getOrEmitConvergenceEntryToken(LI->getHeader()->getParent()); + + return emitConvergenceLoopToken(LI->getHeader(), PII); +} + +llvm::CallBase * +CodeGenFunction::addControlledConvergenceToken(llvm::CallBase *Input) { + llvm::Value *ParentToken = + LoopStack.hasInfo() + ? getOrEmitConvergenceLoopToken(&LoopStack.getInfo()) + : getOrEmitConvergenceEntryToken(Input->getFunction()); + return addConvergenceControlToken(Input, ParentToken); +} + BitTest BitTest::decodeBitTestBuiltin(unsigned BuiltinID) { switch (BuiltinID) { // Main portable variants. @@ -2116,9 +2201,9 @@ llvm::Function *CodeGenFunction::generateBuiltinOSLogHelperFunction( auto AL = ApplyDebugLocation::CreateArtificial(*this); CharUnits Offset; - Address BufAddr = - Address(Builder.CreateLoad(GetAddrOfLocalVar(Args[0]), "buf"), Int8Ty, - BufferAlignment); + Address BufAddr = makeNaturalAddressForPointer( + Builder.CreateLoad(GetAddrOfLocalVar(Args[0]), "buf"), Ctx.VoidTy, + BufferAlignment); Builder.CreateStore(Builder.getInt8(Layout.getSummaryByte()), Builder.CreateConstByteGEP(BufAddr, Offset++, "summary")); Builder.CreateStore(Builder.getInt8(Layout.getNumArgsByte()), @@ -2161,7 +2246,7 @@ RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { // Ignore argument 1, the format string. It is not currently used. CallArgList Args; - Args.add(RValue::get(BufAddr.getPointer()), Ctx.VoidPtrTy); + Args.add(RValue::get(BufAddr.emitRawPointer(*this)), Ctx.VoidPtrTy); for (const auto &Item : Layout.Items) { int Size = Item.getSizeByte(); @@ -2201,8 +2286,8 @@ RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { if (!isa<Constant>(ArgVal)) { CleanupKind Cleanup = getARCCleanupKind(); QualType Ty = TheExpr->getType(); - Address Alloca = Address::invalid(); - Address Addr = CreateMemTemp(Ty, "os.log.arg", &Alloca); + RawAddress Alloca = RawAddress::invalid(); + RawAddress Addr = CreateMemTemp(Ty, "os.log.arg", &Alloca); ArgVal = EmitARCRetain(Ty, ArgVal); Builder.CreateStore(ArgVal, Addr); pushLifetimeExtendedDestroy(Cleanup, Alloca, Ty, @@ -2235,7 +2320,7 @@ RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { llvm::Function *F = CodeGenFunction(CGM).generateBuiltinOSLogHelperFunction( Layout, BufAddr.getAlignment()); EmitCall(FI, CGCallee::forDirect(F), ReturnValueSlot(), Args); - return RValue::get(BufAddr.getPointer()); + return RValue::get(BufAddr, *this); } static bool isSpecialUnsignedMultiplySignedResult( @@ -2983,7 +3068,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // Check NonnullAttribute/NullabilityArg and Alignment. auto EmitArgCheck = [&](TypeCheckKind Kind, Address A, const Expr *Arg, unsigned ParmNum) { - Value *Val = A.getPointer(); + Value *Val = A.emitRawPointer(*this); EmitNonNullArgCheck(RValue::get(Val), Arg->getType(), Arg->getExprLoc(), FD, ParmNum); @@ -3012,13 +3097,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_va_end: EmitVAStartEnd(BuiltinID == Builtin::BI__va_start ? EmitScalarExpr(E->getArg(0)) - : EmitVAListRef(E->getArg(0)).getPointer(), + : EmitVAListRef(E->getArg(0)).emitRawPointer(*this), BuiltinID != Builtin::BI__builtin_va_end); return RValue::get(nullptr); case Builtin::BI__builtin_va_copy: { - Value *DstPtr = EmitVAListRef(E->getArg(0)).getPointer(); - Value *SrcPtr = EmitVAListRef(E->getArg(1)).getPointer(); - Builder.CreateCall(CGM.getIntrinsic(Intrinsic::vacopy), {DstPtr, SrcPtr}); + Value *DstPtr = EmitVAListRef(E->getArg(0)).emitRawPointer(*this); + Value *SrcPtr = EmitVAListRef(E->getArg(1)).emitRawPointer(*this); + Builder.CreateCall(CGM.getIntrinsic(Intrinsic::vacopy, {DstPtr->getType()}), + {DstPtr, SrcPtr}); return RValue::get(nullptr); } case Builtin::BIabs: @@ -3128,36 +3214,66 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_ctzs: case Builtin::BI__builtin_ctz: case Builtin::BI__builtin_ctzl: - case Builtin::BI__builtin_ctzll: { - Value *ArgValue = EmitCheckedArgForBuiltin(E->getArg(0), BCK_CTZPassedZero); + case Builtin::BI__builtin_ctzll: + case Builtin::BI__builtin_ctzg: { + bool HasFallback = BuiltinIDIfNoAsmLabel == Builtin::BI__builtin_ctzg && + E->getNumArgs() > 1; + + Value *ArgValue = + HasFallback ? EmitScalarExpr(E->getArg(0)) + : EmitCheckedArgForBuiltin(E->getArg(0), BCK_CTZPassedZero); llvm::Type *ArgType = ArgValue->getType(); Function *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType); llvm::Type *ResultType = ConvertType(E->getType()); - Value *ZeroUndef = Builder.getInt1(getTarget().isCLZForZeroUndef()); + Value *ZeroUndef = + Builder.getInt1(HasFallback || getTarget().isCLZForZeroUndef()); Value *Result = Builder.CreateCall(F, {ArgValue, ZeroUndef}); if (Result->getType() != ResultType) Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, "cast"); - return RValue::get(Result); + if (!HasFallback) + return RValue::get(Result); + + Value *Zero = Constant::getNullValue(ArgType); + Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero, "iszero"); + Value *FallbackValue = EmitScalarExpr(E->getArg(1)); + Value *ResultOrFallback = + Builder.CreateSelect(IsZero, FallbackValue, Result, "ctzg"); + return RValue::get(ResultOrFallback); } case Builtin::BI__builtin_clzs: case Builtin::BI__builtin_clz: case Builtin::BI__builtin_clzl: - case Builtin::BI__builtin_clzll: { - Value *ArgValue = EmitCheckedArgForBuiltin(E->getArg(0), BCK_CLZPassedZero); + case Builtin::BI__builtin_clzll: + case Builtin::BI__builtin_clzg: { + bool HasFallback = BuiltinIDIfNoAsmLabel == Builtin::BI__builtin_clzg && + E->getNumArgs() > 1; + + Value *ArgValue = + HasFallback ? EmitScalarExpr(E->getArg(0)) + : EmitCheckedArgForBuiltin(E->getArg(0), BCK_CLZPassedZero); llvm::Type *ArgType = ArgValue->getType(); Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType); llvm::Type *ResultType = ConvertType(E->getType()); - Value *ZeroUndef = Builder.getInt1(getTarget().isCLZForZeroUndef()); + Value *ZeroUndef = + Builder.getInt1(HasFallback || getTarget().isCLZForZeroUndef()); Value *Result = Builder.CreateCall(F, {ArgValue, ZeroUndef}); if (Result->getType() != ResultType) Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, "cast"); - return RValue::get(Result); + if (!HasFallback) + return RValue::get(Result); + + Value *Zero = Constant::getNullValue(ArgType); + Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero, "iszero"); + Value *FallbackValue = EmitScalarExpr(E->getArg(1)); + Value *ResultOrFallback = + Builder.CreateSelect(IsZero, FallbackValue, Result, "clzg"); + return RValue::get(ResultOrFallback); } case Builtin::BI__builtin_ffs: case Builtin::BI__builtin_ffsl: @@ -3817,13 +3933,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, bool IsVolatile = PtrTy->getPointeeType().isVolatileQualified(); Address Src = EmitPointerWithAlignment(E->getArg(0)); - EmitNonNullArgCheck(RValue::get(Src.getPointer()), E->getArg(0)->getType(), - E->getArg(0)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Src.emitRawPointer(*this)), + E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, + 0); Value *Result = MB.CreateColumnMajorLoad( - Src.getElementType(), Src.getPointer(), + Src.getElementType(), Src.emitRawPointer(*this), Align(Src.getAlignment().getQuantity()), Stride, IsVolatile, - ResultTy->getNumRows(), ResultTy->getNumColumns(), - "matrix"); + ResultTy->getNumRows(), ResultTy->getNumColumns(), "matrix"); return RValue::get(Result); } @@ -3838,11 +3954,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, assert(PtrTy && "arg1 must be of pointer type"); bool IsVolatile = PtrTy->getPointeeType().isVolatileQualified(); - EmitNonNullArgCheck(RValue::get(Dst.getPointer()), E->getArg(1)->getType(), - E->getArg(1)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Dst.emitRawPointer(*this)), + E->getArg(1)->getType(), E->getArg(1)->getExprLoc(), FD, + 0); Value *Result = MB.CreateColumnMajorStore( - Matrix, Dst.getPointer(), Align(Dst.getAlignment().getQuantity()), - Stride, IsVolatile, MatrixTy->getNumRows(), MatrixTy->getNumColumns()); + Matrix, Dst.emitRawPointer(*this), + Align(Dst.getAlignment().getQuantity()), Stride, IsVolatile, + MatrixTy->getNumRows(), MatrixTy->getNumColumns()); return RValue::get(Result); } @@ -4001,7 +4119,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_bzero: { Address Dest = EmitPointerWithAlignment(E->getArg(0)); Value *SizeVal = EmitScalarExpr(E->getArg(1)); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), + EmitNonNullArgCheck(Dest, E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, 0); Builder.CreateMemSet(Dest, Builder.getInt8(0), SizeVal, false); return RValue::get(nullptr); @@ -4012,10 +4130,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Src = EmitPointerWithAlignment(E->getArg(0)); Address Dest = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = EmitScalarExpr(E->getArg(2)); - EmitNonNullArgCheck(RValue::get(Src.getPointer()), E->getArg(0)->getType(), - E->getArg(0)->getExprLoc(), FD, 0); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(1)->getType(), - E->getArg(1)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Src.emitRawPointer(*this)), + E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, + 0); + EmitNonNullArgCheck(RValue::get(Dest.emitRawPointer(*this)), + E->getArg(1)->getType(), E->getArg(1)->getExprLoc(), FD, + 0); Builder.CreateMemMove(Dest, Src, SizeVal, false); return RValue::get(nullptr); } @@ -4032,10 +4152,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.CreateMemCpy(Dest, Src, SizeVal, false); if (BuiltinID == Builtin::BImempcpy || BuiltinID == Builtin::BI__builtin_mempcpy) - return RValue::get(Builder.CreateInBoundsGEP(Dest.getElementType(), - Dest.getPointer(), SizeVal)); + return RValue::get(Builder.CreateInBoundsGEP( + Dest.getElementType(), Dest.emitRawPointer(*this), SizeVal)); else - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BI__builtin_memcpy_inline: { @@ -4067,7 +4187,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Src = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); Builder.CreateMemCpy(Dest, Src, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BI__builtin_objc_memmove_collectable: { @@ -4076,7 +4196,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Value *SizeVal = EmitScalarExpr(E->getArg(2)); CGM.getObjCRuntime().EmitGCMemmoveCollectable(*this, DestAddr, SrcAddr, SizeVal); - return RValue::get(DestAddr.getPointer()); + return RValue::get(DestAddr, *this); } case Builtin::BI__builtin___memmove_chk: { @@ -4093,7 +4213,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Address Src = EmitPointerWithAlignment(E->getArg(1)); Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); Builder.CreateMemMove(Dest, Src, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BImemmove: @@ -4104,7 +4224,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, EmitArgCheck(TCK_Store, Dest, E->getArg(0), 0); EmitArgCheck(TCK_Load, Src, E->getArg(1), 1); Builder.CreateMemMove(Dest, Src, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BImemset: case Builtin::BI__builtin_memset: { @@ -4112,10 +4232,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Value *ByteVal = Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), Builder.getInt8Ty()); Value *SizeVal = EmitScalarExpr(E->getArg(2)); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), + EmitNonNullArgCheck(Dest, E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, 0); Builder.CreateMemSet(Dest, ByteVal, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BI__builtin_memset_inline: { Address Dest = EmitPointerWithAlignment(E->getArg(0)); @@ -4123,8 +4243,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), Builder.getInt8Ty()); uint64_t Size = E->getArg(2)->EvaluateKnownConstInt(getContext()).getZExtValue(); - EmitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(), - E->getArg(0)->getExprLoc(), FD, 0); + EmitNonNullArgCheck(RValue::get(Dest.emitRawPointer(*this)), + E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, + 0); Builder.CreateMemSetInline(Dest, ByteVal, Size); return RValue::get(nullptr); } @@ -4143,7 +4264,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Builder.getInt8Ty()); Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); Builder.CreateMemSet(Dest, ByteVal, SizeVal, false); - return RValue::get(Dest.getPointer()); + return RValue::get(Dest, *this); } case Builtin::BI__builtin_wmemchr: { // The MSVC runtime library does not provide a definition of wmemchr, so we @@ -4365,14 +4486,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // Store the stack pointer to the setjmp buffer. Value *StackAddr = Builder.CreateStackSave(); - assert(Buf.getPointer()->getType() == StackAddr->getType()); + assert(Buf.emitRawPointer(*this)->getType() == StackAddr->getType()); Address StackSaveSlot = Builder.CreateConstInBoundsGEP(Buf, 2); Builder.CreateStore(StackAddr, StackSaveSlot); // Call LLVM's EH setjmp, which is lightweight. Function *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_setjmp); - return RValue::get(Builder.CreateCall(F, Buf.getPointer())); + return RValue::get(Builder.CreateCall(F, Buf.emitRawPointer(*this))); } case Builtin::BI__builtin_longjmp: { Value *Buf = EmitScalarExpr(E->getArg(0)); @@ -5208,6 +5329,73 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__iso_volatile_store64: return RValue::get(EmitISOVolatileStore(*this, E)); + case Builtin::BI__builtin_ptrauth_auth: + case Builtin::BI__builtin_ptrauth_auth_and_resign: + case Builtin::BI__builtin_ptrauth_blend_discriminator: + case Builtin::BI__builtin_ptrauth_sign_generic_data: + case Builtin::BI__builtin_ptrauth_sign_unauthenticated: + case Builtin::BI__builtin_ptrauth_strip: { + // Emit the arguments. + SmallVector<llvm::Value *, 5> Args; + for (auto argExpr : E->arguments()) + Args.push_back(EmitScalarExpr(argExpr)); + + // Cast the value to intptr_t, saving its original type. + llvm::Type *OrigValueType = Args[0]->getType(); + if (OrigValueType->isPointerTy()) + Args[0] = Builder.CreatePtrToInt(Args[0], IntPtrTy); + + switch (BuiltinID) { + case Builtin::BI__builtin_ptrauth_auth_and_resign: + if (Args[4]->getType()->isPointerTy()) + Args[4] = Builder.CreatePtrToInt(Args[4], IntPtrTy); + LLVM_FALLTHROUGH; + + case Builtin::BI__builtin_ptrauth_auth: + case Builtin::BI__builtin_ptrauth_sign_unauthenticated: + if (Args[2]->getType()->isPointerTy()) + Args[2] = Builder.CreatePtrToInt(Args[2], IntPtrTy); + break; + + case Builtin::BI__builtin_ptrauth_sign_generic_data: + if (Args[1]->getType()->isPointerTy()) + Args[1] = Builder.CreatePtrToInt(Args[1], IntPtrTy); + break; + + case Builtin::BI__builtin_ptrauth_blend_discriminator: + case Builtin::BI__builtin_ptrauth_strip: + break; + } + + // Call the intrinsic. + auto IntrinsicID = [&]() -> unsigned { + switch (BuiltinID) { + case Builtin::BI__builtin_ptrauth_auth: + return llvm::Intrinsic::ptrauth_auth; + case Builtin::BI__builtin_ptrauth_auth_and_resign: + return llvm::Intrinsic::ptrauth_resign; + case Builtin::BI__builtin_ptrauth_blend_discriminator: + return llvm::Intrinsic::ptrauth_blend; + case Builtin::BI__builtin_ptrauth_sign_generic_data: + return llvm::Intrinsic::ptrauth_sign_generic; + case Builtin::BI__builtin_ptrauth_sign_unauthenticated: + return llvm::Intrinsic::ptrauth_sign; + case Builtin::BI__builtin_ptrauth_strip: + return llvm::Intrinsic::ptrauth_strip; + } + llvm_unreachable("bad ptrauth intrinsic"); + }(); + auto Intrinsic = CGM.getIntrinsic(IntrinsicID); + llvm::Value *Result = EmitRuntimeCall(Intrinsic, Args); + + if (BuiltinID != Builtin::BI__builtin_ptrauth_sign_generic_data && + BuiltinID != Builtin::BI__builtin_ptrauth_blend_discriminator && + OrigValueType->isPointerTy()) { + Result = Builder.CreateIntToPtr(Result, OrigValueType); + } + return RValue::get(Result); + } + case Builtin::BI__exception_code: case Builtin::BI_exception_code: return RValue::get(EmitSEHExceptionCode()); @@ -5478,7 +5666,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, llvm::Value *Queue = EmitScalarExpr(E->getArg(0)); llvm::Value *Flags = EmitScalarExpr(E->getArg(1)); LValue NDRangeL = EmitAggExprToLValue(E->getArg(2)); - llvm::Value *Range = NDRangeL.getAddress(*this).getPointer(); + llvm::Value *Range = NDRangeL.getAddress(*this).emitRawPointer(*this); llvm::Type *RangeTy = NDRangeL.getAddress(*this).getType(); if (NumArgs == 4) { @@ -5587,9 +5775,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, getContext(), Expr::NPC_ValueDependentIsNotNull)) { EventWaitList = llvm::ConstantPointerNull::get(PtrTy); } else { - EventWaitList = E->getArg(4)->getType()->isArrayType() - ? EmitArrayToPointerDecay(E->getArg(4)).getPointer() - : EmitScalarExpr(E->getArg(4)); + EventWaitList = + E->getArg(4)->getType()->isArrayType() + ? EmitArrayToPointerDecay(E->getArg(4)).emitRawPointer(*this) + : EmitScalarExpr(E->getArg(4)); // Convert to generic address space. EventWaitList = Builder.CreatePointerCast(EventWaitList, PtrTy); } @@ -5646,7 +5835,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, EmitLifetimeEnd(TmpSize, TmpPtr); return Call; } - [[fallthrough]]; + llvm_unreachable("Unexpected enqueue_kernel signature"); } // OpenCL v2.0 s6.13.17.6 - Kernel query functions need bitcast of block // parameter. @@ -5685,7 +5874,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, llvm::Type *GenericVoidPtrTy = Builder.getPtrTy( getContext().getTargetAddressSpace(LangAS::opencl_generic)); LValue NDRangeL = EmitAggExprToLValue(E->getArg(0)); - llvm::Value *NDRange = NDRangeL.getAddress(*this).getPointer(); + llvm::Value *NDRange = NDRangeL.getAddress(*this).emitRawPointer(*this); auto Info = CGM.getOpenCLRuntime().emitOpenCLEnqueuedBlock(*this, E->getArg(1)); Value *Kernel = @@ -5703,7 +5892,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, Name), {NDRange, Kernel, Block})); } - case Builtin::BI__builtin_store_half: case Builtin::BI__builtin_store_halff: { Value *Val = EmitScalarExpr(E->getArg(0)); @@ -5770,7 +5958,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, auto PTy0 = FTy->getParamType(0); if (PTy0 != Arg0Val->getType()) { if (Arg0Ty->isArrayType()) - Arg0Val = EmitArrayToPointerDecay(Arg0).getPointer(); + Arg0Val = EmitArrayToPointerDecay(Arg0).emitRawPointer(*this); else Arg0Val = Builder.CreatePointerCast(Arg0Val, PTy0); } @@ -5808,7 +5996,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, auto PTy1 = FTy->getParamType(1); if (PTy1 != Arg1Val->getType()) { if (Arg1Ty->isArrayType()) - Arg1Val = EmitArrayToPointerDecay(Arg1).getPointer(); + Arg1Val = EmitArrayToPointerDecay(Arg1).emitRawPointer(*this); else Arg1Val = Builder.CreatePointerCast(Arg1Val, PTy1); } @@ -5822,7 +6010,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_ms_va_start: case Builtin::BI__builtin_ms_va_end: return RValue::get( - EmitVAStartEnd(EmitMSVAListRef(E->getArg(0)).getPointer(), + EmitVAStartEnd(EmitMSVAListRef(E->getArg(0)).emitRawPointer(*this), BuiltinID == Builtin::BI__builtin_ms_va_start)); case Builtin::BI__builtin_ms_va_copy: { @@ -5864,8 +6052,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // If this is a predefined lib function (e.g. malloc), emit the call // using exactly the normal call path. if (getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID)) - return emitLibraryCall(*this, FD, E, - cast<llvm::Constant>(EmitScalarExpr(E->getCallee()))); + return emitLibraryCall( + *this, FD, E, cast<llvm::Constant>(EmitScalarExpr(E->getCallee()))); // Check that a call to a target specific builtin has the correct target // features. @@ -5982,7 +6170,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(nullptr); return RValue::get(V); case TEK_Aggregate: - return RValue::getAggregate(ReturnValue.getValue(), + return RValue::getAggregate(ReturnValue.getAddress(), ReturnValue.isVolatile()); case TEK_Complex: llvm_unreachable("No current target builtin returns complex"); @@ -8752,7 +8940,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, // Get the alignment for the argument in addition to the value; // we'll use it later. PtrOp0 = EmitPointerWithAlignment(E->getArg(0)); - Ops.push_back(PtrOp0.getPointer()); + Ops.push_back(PtrOp0.emitRawPointer(*this)); continue; } } @@ -8779,7 +8967,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, // Get the alignment for the argument in addition to the value; // we'll use it later. PtrOp1 = EmitPointerWithAlignment(E->getArg(1)); - Ops.push_back(PtrOp1.getPointer()); + Ops.push_back(PtrOp1.emitRawPointer(*this)); continue; } } @@ -9200,7 +9388,7 @@ Value *CodeGenFunction::EmitARMMVEBuiltinExpr(unsigned BuiltinID, if (ReturnValue.isNull()) return MvecOut; else - return Builder.CreateStore(MvecOut, ReturnValue.getValue()); + return Builder.CreateStore(MvecOut, ReturnValue.getAddress()); } case CustomCodeGen::VST24: { @@ -10686,6 +10874,12 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, return Builder.CreateCall(F, llvm::ConstantInt::get(Int32Ty, HintID)); } + if (BuiltinID == clang::AArch64::BI__builtin_arm_trap) { + Function *F = CGM.getIntrinsic(Intrinsic::aarch64_break); + llvm::Value *Arg = EmitScalarExpr(E->getArg(0)); + return Builder.CreateCall(F, Builder.CreateZExt(Arg, CGM.Int32Ty)); + } + if (BuiltinID == clang::AArch64::BI__builtin_arm_get_sme_state) { // Create call to __arm_sme_state and store the results to the two pointers. CallInst *CI = EmitRuntimeCall(CGM.CreateRuntimeFunction( @@ -11374,7 +11568,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, // Get the alignment for the argument in addition to the value; // we'll use it later. PtrOp0 = EmitPointerWithAlignment(E->getArg(0)); - Ops.push_back(PtrOp0.getPointer()); + Ops.push_back(PtrOp0.emitRawPointer(*this)); continue; } } @@ -13240,15 +13434,15 @@ Value *CodeGenFunction::EmitBPFBuiltinExpr(unsigned BuiltinID, if (!getDebugInfo()) { CGM.Error(E->getExprLoc(), "using __builtin_preserve_field_info() without -g"); - return IsBitField ? EmitLValue(Arg).getBitFieldPointer() - : EmitLValue(Arg).getPointer(*this); + return IsBitField ? EmitLValue(Arg).getRawBitFieldPointer(*this) + : EmitLValue(Arg).emitRawPointer(*this); } // Enable underlying preserve_*_access_index() generation. bool OldIsInPreservedAIRegion = IsInPreservedAIRegion; IsInPreservedAIRegion = true; - Value *FieldAddr = IsBitField ? EmitLValue(Arg).getBitFieldPointer() - : EmitLValue(Arg).getPointer(*this); + Value *FieldAddr = IsBitField ? EmitLValue(Arg).getRawBitFieldPointer(*this) + : EmitLValue(Arg).emitRawPointer(*this); IsInPreservedAIRegion = OldIsInPreservedAIRegion; ConstantInt *C = cast<ConstantInt>(EmitScalarExpr(E->getArg(1))); @@ -14240,14 +14434,14 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, } case X86::BI_mm_setcsr: case X86::BI__builtin_ia32_ldmxcsr: { - Address Tmp = CreateMemTemp(E->getArg(0)->getType()); + RawAddress Tmp = CreateMemTemp(E->getArg(0)->getType()); Builder.CreateStore(Ops[0], Tmp); return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_ldmxcsr), Tmp.getPointer()); } case X86::BI_mm_getcsr: case X86::BI__builtin_ia32_stmxcsr: { - Address Tmp = CreateMemTemp(E->getType()); + RawAddress Tmp = CreateMemTemp(E->getType()); Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_stmxcsr), Tmp.getPointer()); return Builder.CreateLoad(Tmp, "stmxcsr"); @@ -17522,7 +17716,8 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, SmallVector<Value *, 4> Ops; for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) if (E->getArg(i)->getType()->isArrayType()) - Ops.push_back(EmitArrayToPointerDecay(E->getArg(i)).getPointer()); + Ops.push_back( + EmitArrayToPointerDecay(E->getArg(i)).emitRawPointer(*this)); else Ops.push_back(EmitScalarExpr(E->getArg(i))); // The first argument of these two builtins is a pointer used to store their @@ -17963,6 +18158,24 @@ llvm::Value *CodeGenFunction::EmitScalarOrConstFoldImmArg(unsigned ICEArguments, return Arg; } +Intrinsic::ID getDotProductIntrinsic(QualType QT, int elementCount) { + if (QT->hasFloatingRepresentation()) { + switch (elementCount) { + case 2: + return Intrinsic::dx_dot2; + case 3: + return Intrinsic::dx_dot3; + case 4: + return Intrinsic::dx_dot4; + } + } + if (QT->hasSignedIntegerRepresentation()) + return Intrinsic::dx_sdot; + + assert(QT->hasUnsignedIntegerRepresentation()); + return Intrinsic::dx_udot; +} + Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { if (!getLangOpts().HLSL) @@ -17975,6 +18188,21 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, /*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()), Intrinsic::dx_any, ArrayRef<Value *>{Op0}, nullptr, "dx.any"); } + case Builtin::BI__builtin_hlsl_elementwise_clamp: { + Value *OpX = EmitScalarExpr(E->getArg(0)); + Value *OpMin = EmitScalarExpr(E->getArg(1)); + Value *OpMax = EmitScalarExpr(E->getArg(2)); + + QualType Ty = E->getArg(0)->getType(); + bool IsUnsigned = false; + if (auto *VecTy = Ty->getAs<VectorType>()) + Ty = VecTy->getElementType(); + IsUnsigned = Ty->isUnsignedIntegerType(); + return Builder.CreateIntrinsic( + /*ReturnType=*/OpX->getType(), + IsUnsigned ? Intrinsic::dx_uclamp : Intrinsic::dx_clamp, + ArrayRef<Value *>{OpX, OpMin, OpMax}, nullptr, "dx.clamp"); + } case Builtin::BI__builtin_hlsl_dot: { Value *Op0 = EmitScalarExpr(E->getArg(0)); Value *Op1 = EmitScalarExpr(E->getArg(1)); @@ -17999,8 +18227,7 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, assert(T0->getScalarType() == T1->getScalarType() && "Dot product of vectors need the same element types."); - [[maybe_unused]] auto *VecTy0 = - E->getArg(0)->getType()->getAs<VectorType>(); + auto *VecTy0 = E->getArg(0)->getType()->getAs<VectorType>(); [[maybe_unused]] auto *VecTy1 = E->getArg(1)->getType()->getAs<VectorType>(); // A HLSLVectorTruncation should have happend @@ -18008,45 +18235,20 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, "Dot product requires vectors to be of the same size."); return Builder.CreateIntrinsic( - /*ReturnType=*/T0->getScalarType(), Intrinsic::dx_dot, + /*ReturnType=*/T0->getScalarType(), + getDotProductIntrinsic(E->getArg(0)->getType(), + VecTy0->getNumElements()), ArrayRef<Value *>{Op0, Op1}, nullptr, "dx.dot"); } break; case Builtin::BI__builtin_hlsl_lerp: { Value *X = EmitScalarExpr(E->getArg(0)); Value *Y = EmitScalarExpr(E->getArg(1)); Value *S = EmitScalarExpr(E->getArg(2)); - llvm::Type *Xty = X->getType(); - llvm::Type *Yty = Y->getType(); - llvm::Type *Sty = S->getType(); - if (!Xty->isVectorTy() && !Yty->isVectorTy() && !Sty->isVectorTy()) { - if (Xty->isFloatingPointTy()) { - auto V = Builder.CreateFSub(Y, X); - V = Builder.CreateFMul(S, V); - return Builder.CreateFAdd(X, V, "dx.lerp"); - } - llvm_unreachable("Scalar Lerp is only supported on floats."); - } - // A VectorSplat should have happened - assert(Xty->isVectorTy() && Yty->isVectorTy() && Sty->isVectorTy() && - "Lerp of vector and scalar is not supported."); - - [[maybe_unused]] auto *XVecTy = - E->getArg(0)->getType()->getAs<VectorType>(); - [[maybe_unused]] auto *YVecTy = - E->getArg(1)->getType()->getAs<VectorType>(); - [[maybe_unused]] auto *SVecTy = - E->getArg(2)->getType()->getAs<VectorType>(); - // A HLSLVectorTruncation should have happend - assert(XVecTy->getNumElements() == YVecTy->getNumElements() && - XVecTy->getNumElements() == SVecTy->getNumElements() && - "Lerp requires vectors to be of the same size."); - assert(XVecTy->getElementType()->isRealFloatingType() && - XVecTy->getElementType() == YVecTy->getElementType() && - XVecTy->getElementType() == SVecTy->getElementType() && - "Lerp requires float vectors to be of the same type."); + if (!E->getArg(0)->getType()->hasFloatingRepresentation()) + llvm_unreachable("lerp operand must have a float representation"); return Builder.CreateIntrinsic( - /*ReturnType=*/Xty, Intrinsic::dx_lerp, ArrayRef<Value *>{X, Y, S}, - nullptr, "dx.lerp"); + /*ReturnType=*/X->getType(), Intrinsic::dx_lerp, + ArrayRef<Value *>{X, Y, S}, nullptr, "dx.lerp"); } case Builtin::BI__builtin_hlsl_elementwise_frac: { Value *Op0 = EmitScalarExpr(E->getArg(0)); @@ -18056,6 +18258,20 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, /*ReturnType=*/Op0->getType(), Intrinsic::dx_frac, ArrayRef<Value *>{Op0}, nullptr, "dx.frac"); } + case Builtin::BI__builtin_hlsl_elementwise_isinf: { + Value *Op0 = EmitScalarExpr(E->getArg(0)); + llvm::Type *Xty = Op0->getType(); + llvm::Type *retType = llvm::Type::getInt1Ty(this->getLLVMContext()); + if (Xty->isVectorTy()) { + auto *XVecTy = E->getArg(0)->getType()->getAs<VectorType>(); + retType = llvm::VectorType::get( + retType, ElementCount::getFixed(XVecTy->getNumElements())); + } + if (!E->getArg(0)->getType()->hasFloatingRepresentation()) + llvm_unreachable("isinf operand must have a float representation"); + return Builder.CreateIntrinsic(retType, Intrinsic::dx_isinf, + ArrayRef<Value *>{Op0}, nullptr, "dx.isinf"); + } case Builtin::BI__builtin_hlsl_mad: { Value *M = EmitScalarExpr(E->getArg(0)); Value *A = EmitScalarExpr(E->getArg(1)); @@ -18083,6 +18299,22 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, /*ReturnType=*/Op0->getType(), Intrinsic::dx_rcp, ArrayRef<Value *>{Op0}, nullptr, "dx.rcp"); } + case Builtin::BI__builtin_hlsl_elementwise_rsqrt: { + Value *Op0 = EmitScalarExpr(E->getArg(0)); + if (!E->getArg(0)->getType()->hasFloatingRepresentation()) + llvm_unreachable("rsqrt operand must have a float representation"); + return Builder.CreateIntrinsic( + /*ReturnType=*/Op0->getType(), Intrinsic::dx_rsqrt, + ArrayRef<Value *>{Op0}, nullptr, "dx.rsqrt"); + } + case Builtin::BI__builtin_hlsl_wave_get_lane_index: { + auto *CI = EmitRuntimeCall(CGM.CreateRuntimeFunction( + llvm::FunctionType::get(IntTy, {}, false), "__hlsl_wave_get_lane_index", + {}, false, true)); + if (getTarget().getTriple().isSPIRVLogical()) + CI = dyn_cast<CallInst>(addControlledConvergenceToken(CI)); + return CI; + } } return nullptr; } @@ -18406,43 +18638,25 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, llvm::Function *F = CGM.getIntrinsic(IID, {ArgTy}); return Builder.CreateCall(F, {Addr, Val, ZeroI32, ZeroI32, ZeroI1}); } - case AMDGPU::BI__builtin_amdgcn_global_load_tr_i32: - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v2i32: - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v4f16: - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v4i16: - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v8f16: - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v8i16: { + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b64_i32: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b64_v2i32: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4i16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8i16: { - llvm::Type *ArgTy; + Intrinsic::ID IID; switch (BuiltinID) { - case AMDGPU::BI__builtin_amdgcn_global_load_tr_i32: - ArgTy = llvm::Type::getInt32Ty(getLLVMContext()); + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b64_i32: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b64_v2i32: + IID = Intrinsic::amdgcn_global_load_tr_b64; break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v2i32: - ArgTy = llvm::FixedVectorType::get( - llvm::Type::getInt32Ty(getLLVMContext()), 2); - break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v4f16: - ArgTy = llvm::FixedVectorType::get( - llvm::Type::getHalfTy(getLLVMContext()), 4); - break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v4i16: - ArgTy = llvm::FixedVectorType::get( - llvm::Type::getInt16Ty(getLLVMContext()), 4); - break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v8f16: - ArgTy = llvm::FixedVectorType::get( - llvm::Type::getHalfTy(getLLVMContext()), 8); - break; - case AMDGPU::BI__builtin_amdgcn_global_load_tr_v8i16: - ArgTy = llvm::FixedVectorType::get( - llvm::Type::getInt16Ty(getLLVMContext()), 8); + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4i16: + case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8i16: + IID = Intrinsic::amdgcn_global_load_tr_b128; break; } - + llvm::Type *LoadTy = ConvertType(E->getType()); llvm::Value *Addr = EmitScalarExpr(E->getArg(0)); - llvm::Function *F = - CGM.getIntrinsic(Intrinsic::amdgcn_global_load_tr, {ArgTy}); + llvm::Function *F = CGM.getIntrinsic(IID, {LoadTy}); return Builder.CreateCall(F, {Addr}); } case AMDGPU::BI__builtin_amdgcn_get_fpenv: { @@ -19973,14 +20187,14 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, // Save returned values. assert(II.NumResults); if (II.NumResults == 1) { - Builder.CreateAlignedStore(Result, Dst.getPointer(), + Builder.CreateAlignedStore(Result, Dst.emitRawPointer(*this), CharUnits::fromQuantity(4)); } else { for (unsigned i = 0; i < II.NumResults; ++i) { Builder.CreateAlignedStore( Builder.CreateBitCast(Builder.CreateExtractValue(Result, i), Dst.getElementType()), - Builder.CreateGEP(Dst.getElementType(), Dst.getPointer(), + Builder.CreateGEP(Dst.getElementType(), Dst.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); } @@ -20020,7 +20234,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < II.NumResults; ++i) { Value *V = Builder.CreateAlignedLoad( Src.getElementType(), - Builder.CreateGEP(Src.getElementType(), Src.getPointer(), + Builder.CreateGEP(Src.getElementType(), Src.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, ParamType)); @@ -20092,7 +20306,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsA; ++i) { Value *V = Builder.CreateAlignedLoad( SrcA.getElementType(), - Builder.CreateGEP(SrcA.getElementType(), SrcA.getPointer(), + Builder.CreateGEP(SrcA.getElementType(), SrcA.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, AType)); @@ -20102,7 +20316,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsB; ++i) { Value *V = Builder.CreateAlignedLoad( SrcB.getElementType(), - Builder.CreateGEP(SrcB.getElementType(), SrcB.getPointer(), + Builder.CreateGEP(SrcB.getElementType(), SrcB.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, BType)); @@ -20113,7 +20327,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsC; ++i) { Value *V = Builder.CreateAlignedLoad( SrcC.getElementType(), - Builder.CreateGEP(SrcC.getElementType(), SrcC.getPointer(), + Builder.CreateGEP(SrcC.getElementType(), SrcC.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); Values.push_back(Builder.CreateBitCast(V, CType)); @@ -20123,7 +20337,7 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, for (unsigned i = 0; i < MI.NumEltsD; ++i) Builder.CreateAlignedStore( Builder.CreateBitCast(Builder.CreateExtractValue(Result, i), DType), - Builder.CreateGEP(Dst.getElementType(), Dst.getPointer(), + Builder.CreateGEP(Dst.getElementType(), Dst.emitRawPointer(*this), llvm::ConstantInt::get(IntTy, i)), CharUnits::fromQuantity(4)); return Result; @@ -20381,7 +20595,7 @@ struct BuiltinAlignArgs { BuiltinAlignArgs(const CallExpr *E, CodeGenFunction &CGF) { QualType AstType = E->getArg(0)->getType(); if (AstType->isArrayType()) - Src = CGF.EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Src = CGF.EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(CGF); else Src = CGF.EmitScalarExpr(E->getArg(0)); SrcType = Src->getType(); @@ -20999,7 +21213,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_get: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Value *Index = EmitScalarExpr(E->getArg(1)); Function *Callee; if (E->getType().isWebAssemblyExternrefType()) @@ -21013,7 +21227,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_set: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Value *Index = EmitScalarExpr(E->getArg(1)); Value *Val = EmitScalarExpr(E->getArg(2)); Function *Callee; @@ -21028,13 +21242,13 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_size: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Value = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Value = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_table_size); return Builder.CreateCall(Callee, Value); } case WebAssembly::BI__builtin_wasm_table_grow: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Value *Val = EmitScalarExpr(E->getArg(1)); Value *NElems = EmitScalarExpr(E->getArg(2)); @@ -21051,7 +21265,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_fill: { assert(E->getArg(0)->getType()->isArrayType()); - Value *Table = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); + Value *Table = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); Value *Index = EmitScalarExpr(E->getArg(1)); Value *Val = EmitScalarExpr(E->getArg(2)); Value *NElems = EmitScalarExpr(E->getArg(3)); @@ -21069,8 +21283,8 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_table_copy: { assert(E->getArg(0)->getType()->isArrayType()); - Value *TableX = EmitArrayToPointerDecay(E->getArg(0)).getPointer(); - Value *TableY = EmitArrayToPointerDecay(E->getArg(1)).getPointer(); + Value *TableX = EmitArrayToPointerDecay(E->getArg(0)).emitRawPointer(*this); + Value *TableY = EmitArrayToPointerDecay(E->getArg(1)).emitRawPointer(*this); Value *DstIdx = EmitScalarExpr(E->getArg(2)); Value *SrcIdx = EmitScalarExpr(E->getArg(3)); Value *NElems = EmitScalarExpr(E->getArg(4)); @@ -21149,7 +21363,7 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, auto MakeCircOp = [this, E](unsigned IntID, bool IsLoad) { // The base pointer is passed by address, so it needs to be loaded. Address A = EmitPointerWithAlignment(E->getArg(0)); - Address BP = Address(A.getPointer(), Int8PtrTy, A.getAlignment()); + Address BP = Address(A.emitRawPointer(*this), Int8PtrTy, A.getAlignment()); llvm::Value *Base = Builder.CreateLoad(BP); // The treatment of both loads and stores is the same: the arguments for // the builtin are the same as the arguments for the intrinsic. @@ -21190,8 +21404,8 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, // EmitPointerWithAlignment and EmitScalarExpr evaluates the expression // per call. Address DestAddr = EmitPointerWithAlignment(E->getArg(1)); - DestAddr = Address(DestAddr.getPointer(), Int8Ty, DestAddr.getAlignment()); - llvm::Value *DestAddress = DestAddr.getPointer(); + DestAddr = DestAddr.withElementType(Int8Ty); + llvm::Value *DestAddress = DestAddr.emitRawPointer(*this); // Operands are Base, Dest, Modifier. // The intrinsic format in LLVM IR is defined as @@ -21242,8 +21456,8 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, {EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1)), PredIn}); llvm::Value *PredOut = Builder.CreateExtractValue(Result, 1); - Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.getPointer(), - PredAddr.getAlignment()); + Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.emitRawPointer(*this), + PredAddr.getAlignment()); return Builder.CreateExtractValue(Result, 0); } // These are identical to the builtins above, except they don't consume @@ -21261,8 +21475,8 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID, {EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1))}); llvm::Value *PredOut = Builder.CreateExtractValue(Result, 1); - Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.getPointer(), - PredAddr.getAlignment()); + Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.emitRawPointer(*this), + PredAddr.getAlignment()); return Builder.CreateExtractValue(Result, 0); } diff --git a/clang/lib/CodeGen/CGCUDANV.cpp b/clang/lib/CodeGen/CGCUDANV.cpp index 49f93451db7bbba07c8dcc93a99074fad177bc85..0cb5b06a519c0098773e6ecafdd1c315048a8007 100644 --- a/clang/lib/CodeGen/CGCUDANV.cpp +++ b/clang/lib/CodeGen/CGCUDANV.cpp @@ -331,11 +331,11 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF, llvm::ConstantInt::get(SizeTy, std::max<size_t>(1, Args.size()))); // Store pointers to the arguments in a locally allocated launch_args. for (unsigned i = 0; i < Args.size(); ++i) { - llvm::Value* VarPtr = CGF.GetAddrOfLocalVar(Args[i]).getPointer(); + llvm::Value *VarPtr = CGF.GetAddrOfLocalVar(Args[i]).emitRawPointer(CGF); llvm::Value *VoidVarPtr = CGF.Builder.CreatePointerCast(VarPtr, PtrTy); CGF.Builder.CreateDefaultAlignedStore( - VoidVarPtr, - CGF.Builder.CreateConstGEP1_32(PtrTy, KernelArgs.getPointer(), i)); + VoidVarPtr, CGF.Builder.CreateConstGEP1_32( + PtrTy, KernelArgs.emitRawPointer(CGF), i)); } llvm::BasicBlock *EndBlock = CGF.createBasicBlock("setup.end"); @@ -393,9 +393,10 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF, /*isVarArg=*/false), addUnderscoredPrefixToName("PopCallConfiguration")); - CGF.EmitRuntimeCallOrInvoke(cudaPopConfigFn, - {GridDim.getPointer(), BlockDim.getPointer(), - ShmemSize.getPointer(), Stream.getPointer()}); + CGF.EmitRuntimeCallOrInvoke(cudaPopConfigFn, {GridDim.emitRawPointer(CGF), + BlockDim.emitRawPointer(CGF), + ShmemSize.emitRawPointer(CGF), + Stream.emitRawPointer(CGF)}); // Emit the call to cudaLaunch llvm::Value *Kernel = @@ -405,7 +406,7 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF, cudaLaunchKernelFD->getParamDecl(0)->getType()); LaunchKernelArgs.add(RValue::getAggregate(GridDim), Dim3Ty); LaunchKernelArgs.add(RValue::getAggregate(BlockDim), Dim3Ty); - LaunchKernelArgs.add(RValue::get(KernelArgs.getPointer()), + LaunchKernelArgs.add(RValue::get(KernelArgs, CGF), cudaLaunchKernelFD->getParamDecl(3)->getType()); LaunchKernelArgs.add(RValue::get(CGF.Builder.CreateLoad(ShmemSize)), cudaLaunchKernelFD->getParamDecl(4)->getType()); @@ -438,8 +439,8 @@ void CGNVCUDARuntime::emitDeviceStubBodyLegacy(CodeGenFunction &CGF, auto TInfo = CGM.getContext().getTypeInfoInChars(A->getType()); Offset = Offset.alignTo(TInfo.Align); llvm::Value *Args[] = { - CGF.Builder.CreatePointerCast(CGF.GetAddrOfLocalVar(A).getPointer(), - PtrTy), + CGF.Builder.CreatePointerCast( + CGF.GetAddrOfLocalVar(A).emitRawPointer(CGF), PtrTy), llvm::ConstantInt::get(SizeTy, TInfo.Width.getQuantity()), llvm::ConstantInt::get(SizeTy, Offset.getQuantity()), }; @@ -491,7 +492,8 @@ static void replaceManagedVar(llvm::GlobalVariable *Var, // variable with instructions. for (auto &&Op : WorkItem) { auto *CE = cast<llvm::ConstantExpr>(Op); - auto *NewInst = CE->getAsInstruction(I); + auto *NewInst = CE->getAsInstruction(); + NewInst->insertBefore(*I->getParent(), I->getIterator()); NewInst->replaceUsesOfWith(OldV, NewV); OldV = CE; NewV = NewInst; @@ -604,20 +606,10 @@ llvm::Function *CGNVCUDARuntime::makeRegisterGlobalsFn() { uint64_t VarSize = CGM.getDataLayout().getTypeAllocSize(Var->getValueType()); if (Info.Flags.isManaged()) { - auto *ManagedVar = new llvm::GlobalVariable( - CGM.getModule(), Var->getType(), - /*isConstant=*/false, Var->getLinkage(), - /*Init=*/Var->isDeclaration() - ? nullptr - : llvm::ConstantPointerNull::get(Var->getType()), - /*Name=*/"", /*InsertBefore=*/nullptr, - llvm::GlobalVariable::NotThreadLocal); - ManagedVar->setDSOLocal(Var->isDSOLocal()); - ManagedVar->setVisibility(Var->getVisibility()); - ManagedVar->setExternallyInitialized(true); - ManagedVar->takeName(Var); - Var->setName(Twine(ManagedVar->getName() + ".managed")); - replaceManagedVar(Var, ManagedVar); + assert(Var->getName().ends_with(".managed") && + "HIP managed variables not transformed"); + auto *ManagedVar = CGM.getModule().getNamedGlobal( + Var->getName().drop_back(StringRef(".managed").size())); llvm::Value *Args[] = { &GpuBinaryHandlePtr, ManagedVar, @@ -1092,7 +1084,9 @@ void CGNVCUDARuntime::transformManagedVars() { : llvm::ConstantPointerNull::get(Var->getType()), /*Name=*/"", /*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal, - CGM.getContext().getTargetAddressSpace(LangAS::cuda_device)); + CGM.getContext().getTargetAddressSpace(CGM.getLangOpts().CUDAIsDevice + ? LangAS::cuda_device + : LangAS::Default)); ManagedVar->setDSOLocal(Var->isDSOLocal()); ManagedVar->setVisibility(Var->getVisibility()); ManagedVar->setExternallyInitialized(true); @@ -1101,7 +1095,7 @@ void CGNVCUDARuntime::transformManagedVars() { Var->setName(Twine(ManagedVar->getName()) + ".managed"); // Keep managed variables even if they are not used in device code since // they need to be allocated by the runtime. - if (!Var->isDeclaration()) { + if (CGM.getLangOpts().CUDAIsDevice && !Var->isDeclaration()) { assert(!ManagedVar->isDeclaration()); CGM.addCompilerUsedGlobal(Var); CGM.addCompilerUsedGlobal(ManagedVar); @@ -1159,9 +1153,8 @@ void CGNVCUDARuntime::createOffloadingEntries() { // Returns module constructor to be added. llvm::Function *CGNVCUDARuntime::finalizeModule() { + transformManagedVars(); if (CGM.getLangOpts().CUDAIsDevice) { - transformManagedVars(); - // Mark ODR-used device variables as compiler used to prevent it from being // eliminated by optimization. This is necessary for device variables // ODR-used by host functions. Sema correctly marks them as ODR-used no diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index a8bf57a277e90963350a58848acdaa6579ce2236..7c6dfc3e59d8c0eb547fbd786378db2457f6a96f 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -20,6 +20,12 @@ using namespace CodeGen; CGCXXABI::~CGCXXABI() { } +Address CGCXXABI::getThisAddress(CodeGenFunction &CGF) { + return CGF.makeNaturalAddressForPointer( + CGF.CXXABIThisValue, CGF.CXXABIThisDecl->getType()->getPointeeType(), + CGF.CXXABIThisAlignment); +} + void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) { DiagnosticsEngine &Diags = CGF.CGM.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -44,8 +50,12 @@ CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer( llvm::Value *MemPtr, const MemberPointerType *MPT) { ErrorUnsupportedABI(CGF, "calls through member pointers"); - ThisPtrForCall = This.getPointer(); - const auto *FPT = MPT->getPointeeType()->castAs<FunctionProtoType>(); + const auto *RD = + cast<CXXRecordDecl>(MPT->getClass()->castAs<RecordType>()->getDecl()); + ThisPtrForCall = + CGF.getAsNaturalPointerTo(This, CGF.getContext().getRecordType(RD)); + const FunctionProtoType *FPT = + MPT->getPointeeType()->getAs<FunctionProtoType>(); llvm::Constant *FnPtr = llvm::Constant::getNullValue( llvm::PointerType::getUnqual(CGM.getLLVMContext())); return CGCallee::forDirect(FnPtr, FPT); @@ -251,16 +261,15 @@ void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr, // If we don't need an array cookie, bail out early. if (!requiresArrayCookie(expr, eltTy)) { - allocPtr = ptr.getPointer(); + allocPtr = ptr.emitRawPointer(CGF); numElements = nullptr; cookieSize = CharUnits::Zero(); return; } cookieSize = getArrayCookieSizeImpl(eltTy); - Address allocAddr = - CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize); - allocPtr = allocAddr.getPointer(); + Address allocAddr = CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize); + allocPtr = allocAddr.emitRawPointer(CGF); numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize); } diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index ad1ad08d0856887e9c37e9d9358e76a87f521a39..c7eccbd0095a94c494e13f9f3785294adad95aae 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -57,12 +57,8 @@ protected: llvm::Value *getThisValue(CodeGenFunction &CGF) { return CGF.CXXABIThisValue; } - Address getThisAddress(CodeGenFunction &CGF) { - return Address( - CGF.CXXABIThisValue, - CGF.ConvertTypeForMem(CGF.CXXABIThisDecl->getType()->getPointeeType()), - CGF.CXXABIThisAlignment); - } + + Address getThisAddress(CodeGenFunction &CGF); /// Issue a diagnostic about unsupported features in the ABI. void ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S); @@ -475,12 +471,6 @@ public: BaseSubobject Base, const CXXRecordDecl *NearestVBase) = 0; - /// Get the address point of the vtable for the given base subobject while - /// building a constexpr. - virtual llvm::Constant * - getVTableAddressPointForConstExpr(BaseSubobject Base, - const CXXRecordDecl *VTableClass) = 0; - /// Get the address of the vtable for the given record decl which should be /// used for the vptr at the given offset in RD. virtual llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index a28d7888715d858430ff9893a80a4d86c23f9dfd..f12765b826935b2d0c174f3a7ebb27d0dd6690c7 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -74,6 +74,9 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) { case CC_SwiftAsync: return llvm::CallingConv::SwiftTail; case CC_M68kRTD: return llvm::CallingConv::M68k_RTD; case CC_PreserveNone: return llvm::CallingConv::PreserveNone; + // clang-format off + case CC_RISCVVectorCall: return llvm::CallingConv::RISCV_VectorCall; + // clang-format on } } @@ -260,6 +263,9 @@ static CallingConv getCallingConventionForDecl(const ObjCMethodDecl *D, if (D->hasAttr<PreserveNoneAttr>()) return CC_PreserveNone; + if (D->hasAttr<RISCVVectorCCAttr>()) + return CC_RISCVVectorCall; + return CC_C; } @@ -933,8 +939,8 @@ struct NoExpansion : TypeExpansion { static std::unique_ptr<TypeExpansion> getTypeExpansion(QualType Ty, const ASTContext &Context) { if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) { - return std::make_unique<ConstantArrayExpansion>( - AT->getElementType(), AT->getSize().getZExtValue()); + return std::make_unique<ConstantArrayExpansion>(AT->getElementType(), + AT->getZExtSize()); } if (const RecordType *RT = Ty->getAs<RecordType>()) { SmallVector<const CXXBaseSpecifier *, 1> Bases; @@ -1031,15 +1037,9 @@ static void forConstantArrayExpansion(CodeGenFunction &CGF, ConstantArrayExpansion *CAE, Address BaseAddr, llvm::function_ref<void(Address)> Fn) { - CharUnits EltSize = CGF.getContext().getTypeSizeInChars(CAE->EltTy); - CharUnits EltAlign = - BaseAddr.getAlignment().alignmentOfArrayElement(EltSize); - llvm::Type *EltTy = CGF.ConvertTypeForMem(CAE->EltTy); - for (int i = 0, n = CAE->NumElts; i < n; i++) { - llvm::Value *EltAddr = CGF.Builder.CreateConstGEP2_32( - BaseAddr.getElementType(), BaseAddr.getPointer(), 0, i); - Fn(Address(EltAddr, EltTy, EltAlign)); + Address EltAddr = CGF.Builder.CreateConstGEP2_32(BaseAddr, 0, i); + Fn(EltAddr); } } @@ -1154,9 +1154,10 @@ void CodeGenFunction::ExpandTypeToArgs( } /// Create a temporary allocation for the purposes of coercion. -static Address CreateTempAllocaForCoercion(CodeGenFunction &CGF, llvm::Type *Ty, - CharUnits MinAlign, - const Twine &Name = "tmp") { +static RawAddress CreateTempAllocaForCoercion(CodeGenFunction &CGF, + llvm::Type *Ty, + CharUnits MinAlign, + const Twine &Name = "tmp") { // Don't use an alignment that's worse than what LLVM would prefer. auto PrefAlign = CGF.CGM.getDataLayout().getPrefTypeAlign(Ty); CharUnits Align = std::max(MinAlign, CharUnits::fromQuantity(PrefAlign)); @@ -1326,11 +1327,11 @@ static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty, } // Otherwise do coercion through memory. This is stupid, but simple. - Address Tmp = + RawAddress Tmp = CreateTempAllocaForCoercion(CGF, Ty, Src.getAlignment(), Src.getName()); CGF.Builder.CreateMemCpy( - Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), Src.getPointer(), - Src.getAlignment().getAsAlign(), + Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), + Src.emitRawPointer(CGF), Src.getAlignment().getAsAlign(), llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize.getKnownMinValue())); return CGF.Builder.CreateLoad(Tmp); } @@ -1414,11 +1415,12 @@ static void CreateCoercedStore(llvm::Value *Src, // // FIXME: Assert that we aren't truncating non-padding bits when have access // to that information. - Address Tmp = CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment()); + RawAddress Tmp = + CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment()); CGF.Builder.CreateStore(Src, Tmp); CGF.Builder.CreateMemCpy( - Dst.getPointer(), Dst.getAlignment().getAsAlign(), Tmp.getPointer(), - Tmp.getAlignment().getAsAlign(), + Dst.emitRawPointer(CGF), Dst.getAlignment().getAsAlign(), + Tmp.getPointer(), Tmp.getAlignment().getAsAlign(), llvm::ConstantInt::get(CGF.IntPtrTy, DstSize.getFixedValue())); } } @@ -3018,17 +3020,17 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, case ABIArgInfo::Indirect: case ABIArgInfo::IndirectAliased: { assert(NumIRArgs == 1); - Address ParamAddr = Address(Fn->getArg(FirstIRArg), ConvertTypeForMem(Ty), - ArgI.getIndirectAlign(), KnownNonNull); + Address ParamAddr = makeNaturalAddressForPointer( + Fn->getArg(FirstIRArg), Ty, ArgI.getIndirectAlign(), false, nullptr, + nullptr, KnownNonNull); if (!hasScalarEvaluationKind(Ty)) { // Aggregates and complex variables are accessed by reference. All we // need to do is realign the value, if requested. Also, if the address // may be aliased, copy it to ensure that the parameter variable is // mutable and has a unique adress, as C requires. - Address V = ParamAddr; if (ArgI.getIndirectRealign() || ArgI.isIndirectAliased()) { - Address AlignedTemp = CreateMemTemp(Ty, "coerce"); + RawAddress AlignedTemp = CreateMemTemp(Ty, "coerce"); // Copy from the incoming argument pointer to the temporary with the // appropriate alignment. @@ -3038,11 +3040,12 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, CharUnits Size = getContext().getTypeSizeInChars(Ty); Builder.CreateMemCpy( AlignedTemp.getPointer(), AlignedTemp.getAlignment().getAsAlign(), - ParamAddr.getPointer(), ParamAddr.getAlignment().getAsAlign(), + ParamAddr.emitRawPointer(*this), + ParamAddr.getAlignment().getAsAlign(), llvm::ConstantInt::get(IntPtrTy, Size.getQuantity())); - V = AlignedTemp; + ParamAddr = AlignedTemp; } - ArgVals.push_back(ParamValue::forIndirect(V)); + ArgVals.push_back(ParamValue::forIndirect(ParamAddr)); } else { // Load scalar value from indirect argument. llvm::Value *V = @@ -3086,7 +3089,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, llvm::Align Alignment = CGM.getNaturalTypeAlignment(ETy).getAsAlign(); AI->addAttrs(llvm::AttrBuilder(getLLVMContext()).addAlignmentAttr(Alignment)); - uint64_t ArrSize = ArrTy->getSize().getZExtValue(); + uint64_t ArrSize = ArrTy->getZExtSize(); if (!ETy->isIncompleteType() && ETy->isConstantSizeType() && ArrSize) { llvm::AttrBuilder Attrs(getLLVMContext()); @@ -3156,10 +3159,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, == ParameterABI::SwiftErrorResult) { QualType pointeeTy = Ty->getPointeeType(); assert(pointeeTy->isPointerType()); - Address temp = - CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); - Address arg(V, ConvertTypeForMem(pointeeTy), - getContext().getTypeAlignInChars(pointeeTy)); + RawAddress temp = + CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); + Address arg = makeNaturalAddressForPointer( + V, pointeeTy, getContext().getTypeAlignInChars(pointeeTy)); llvm::Value *incomingErrorValue = Builder.CreateLoad(arg); Builder.CreateStore(incomingErrorValue, temp); V = temp.getPointer(); @@ -3496,7 +3499,7 @@ static llvm::Value *tryRemoveRetainOfSelf(CodeGenFunction &CGF, llvm::LoadInst *load = dyn_cast<llvm::LoadInst>(retainedValue->stripPointerCasts()); if (!load || load->isAtomic() || load->isVolatile() || - load->getPointerOperand() != CGF.GetAddrOfLocalVar(self).getPointer()) + load->getPointerOperand() != CGF.GetAddrOfLocalVar(self).getBasePointer()) return nullptr; // Okay! Burn it all down. This relies for correctness on the @@ -3533,12 +3536,15 @@ static llvm::Value *emitAutoreleaseOfResult(CodeGenFunction &CGF, /// Heuristically search for a dominating store to the return-value slot. static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { + llvm::Value *ReturnValuePtr = CGF.ReturnValue.getBasePointer(); + // Check if a User is a store which pointerOperand is the ReturnValue. // We are looking for stores to the ReturnValue, not for stores of the // ReturnValue to some other location. - auto GetStoreIfValid = [&CGF](llvm::User *U) -> llvm::StoreInst * { + auto GetStoreIfValid = [&CGF, + ReturnValuePtr](llvm::User *U) -> llvm::StoreInst * { auto *SI = dyn_cast<llvm::StoreInst>(U); - if (!SI || SI->getPointerOperand() != CGF.ReturnValue.getPointer() || + if (!SI || SI->getPointerOperand() != ReturnValuePtr || SI->getValueOperand()->getType() != CGF.ReturnValue.getElementType()) return nullptr; // These aren't actually possible for non-coerced returns, and we @@ -3552,7 +3558,7 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { // for something immediately preceding the IP. Sometimes this can // happen with how we generate implicit-returns; it can also happen // with noreturn cleanups. - if (!CGF.ReturnValue.getPointer()->hasOneUse()) { + if (!ReturnValuePtr->hasOneUse()) { llvm::BasicBlock *IP = CGF.Builder.GetInsertBlock(); if (IP->empty()) return nullptr; @@ -3570,8 +3576,7 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { return nullptr; } - llvm::StoreInst *store = - GetStoreIfValid(CGF.ReturnValue.getPointer()->user_back()); + llvm::StoreInst *store = GetStoreIfValid(ReturnValuePtr->user_back()); if (!store) return nullptr; // Now do a first-and-dirty dominance check: just walk up the @@ -4115,7 +4120,11 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args, } static bool isProvablyNull(llvm::Value *addr) { - return isa<llvm::ConstantPointerNull>(addr); + return llvm::isa_and_nonnull<llvm::ConstantPointerNull>(addr); +} + +static bool isProvablyNonNull(Address Addr, CodeGenFunction &CGF) { + return llvm::isKnownNonZero(Addr.getBasePointer(), CGF.CGM.getDataLayout()); } /// Emit the actual writing-back of a writeback. @@ -4123,21 +4132,20 @@ static void emitWriteback(CodeGenFunction &CGF, const CallArgList::Writeback &writeback) { const LValue &srcLV = writeback.Source; Address srcAddr = srcLV.getAddress(CGF); - assert(!isProvablyNull(srcAddr.getPointer()) && + assert(!isProvablyNull(srcAddr.getBasePointer()) && "shouldn't have writeback for provably null argument"); llvm::BasicBlock *contBB = nullptr; // If the argument wasn't provably non-null, we need to null check // before doing the store. - bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(), - CGF.CGM.getDataLayout()); + bool provablyNonNull = isProvablyNonNull(srcAddr, CGF); + if (!provablyNonNull) { llvm::BasicBlock *writebackBB = CGF.createBasicBlock("icr.writeback"); contBB = CGF.createBasicBlock("icr.done"); - llvm::Value *isNull = - CGF.Builder.CreateIsNull(srcAddr.getPointer(), "icr.isnull"); + llvm::Value *isNull = CGF.Builder.CreateIsNull(srcAddr, "icr.isnull"); CGF.Builder.CreateCondBr(isNull, contBB, writebackBB); CGF.EmitBlock(writebackBB); } @@ -4241,7 +4249,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, CGF.ConvertTypeForMem(CRE->getType()->getPointeeType()); // If the address is a constant null, just pass the appropriate null. - if (isProvablyNull(srcAddr.getPointer())) { + if (isProvablyNull(srcAddr.getBasePointer())) { args.add(RValue::get(llvm::ConstantPointerNull::get(destType)), CRE->getType()); return; @@ -4270,17 +4278,16 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, // If the address is *not* known to be non-null, we need to switch. llvm::Value *finalArgument; - bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(), - CGF.CGM.getDataLayout()); + bool provablyNonNull = isProvablyNonNull(srcAddr, CGF); + if (provablyNonNull) { - finalArgument = temp.getPointer(); + finalArgument = temp.emitRawPointer(CGF); } else { - llvm::Value *isNull = - CGF.Builder.CreateIsNull(srcAddr.getPointer(), "icr.isnull"); + llvm::Value *isNull = CGF.Builder.CreateIsNull(srcAddr, "icr.isnull"); - finalArgument = CGF.Builder.CreateSelect(isNull, - llvm::ConstantPointerNull::get(destType), - temp.getPointer(), "icr.argument"); + finalArgument = CGF.Builder.CreateSelect( + isNull, llvm::ConstantPointerNull::get(destType), + temp.emitRawPointer(CGF), "icr.argument"); // If we need to copy, then the load has to be conditional, which // means we need control flow. @@ -4372,7 +4379,8 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType, NNAttr = getNonNullAttr(AC.getDecl(), PVD, ArgType, ArgNo); bool CanCheckNullability = false; - if (SanOpts.has(SanitizerKind::NullabilityArg) && !NNAttr && PVD) { + if (SanOpts.has(SanitizerKind::NullabilityArg) && !NNAttr && PVD && + !PVD->getType()->isRecordType()) { auto Nullability = PVD->getType()->getNullability(); CanCheckNullability = Nullability && *Nullability == NullabilityKind::NonNull && @@ -4404,6 +4412,16 @@ void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType, EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, std::nullopt); } +void CodeGenFunction::EmitNonNullArgCheck(Address Addr, QualType ArgType, + SourceLocation ArgLoc, + AbstractCallee AC, unsigned ParmNum) { + if (!AC.getDecl() || !(SanOpts.has(SanitizerKind::NonnullAttribute) || + SanOpts.has(SanitizerKind::NullabilityArg))) + return; + + EmitNonNullArgCheck(RValue::get(Addr, *this), ArgType, ArgLoc, AC, ParmNum); +} + // Check if the call is going to use the inalloca convention. This needs to // agree with CGFunctionInfo::usesInAlloca. The CGFunctionInfo is arranged // later, so we can't check it directly. @@ -4702,7 +4720,8 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, } if (HasAggregateEvalKind && isa<ImplicitCastExpr>(E) && - cast<CastExpr>(E)->getCastKind() == CK_LValueToRValue) { + cast<CastExpr>(E)->getCastKind() == CK_LValueToRValue && + !type->isArrayParameterType()) { LValue L = EmitLValue(cast<CastExpr>(E)->getSubExpr()); assert(L.isSimple()); args.addUncopiedAggregate(L, type); @@ -4744,10 +4763,20 @@ CodeGenFunction::AddObjCARCExceptionMetadata(llvm::Instruction *Inst) { llvm::CallInst * CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const llvm::Twine &name) { - return EmitNounwindRuntimeCall(callee, std::nullopt, name); + return EmitNounwindRuntimeCall(callee, ArrayRef<llvm::Value *>(), name); } /// Emits a call to the given nounwind runtime function. +llvm::CallInst * +CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee, + ArrayRef<Address> args, + const llvm::Twine &name) { + SmallVector<llvm::Value *, 3> values; + for (auto arg : args) + values.push_back(arg.emitRawPointer(*this)); + return EmitNounwindRuntimeCall(callee, values, name); +} + llvm::CallInst * CodeGenFunction::EmitNounwindRuntimeCall(llvm::FunctionCallee callee, ArrayRef<llvm::Value *> args, @@ -5026,7 +5055,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // If we're using inalloca, insert the allocation after the stack save. // FIXME: Do this earlier rather than hacking it in here! - Address ArgMemory = Address::invalid(); + RawAddress ArgMemory = RawAddress::invalid(); if (llvm::StructType *ArgStruct = CallInfo.getArgStruct()) { const llvm::DataLayout &DL = CGM.getDataLayout(); llvm::Instruction *IP = CallArgs.getStackBase(); @@ -5042,7 +5071,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, AI->setAlignment(Align.getAsAlign()); AI->setUsedWithInAlloca(true); assert(AI->isUsedWithInAlloca() && !AI->isStaticAlloca()); - ArgMemory = Address(AI, ArgStruct, Align); + ArgMemory = RawAddress(AI, ArgStruct, Align); } ClangToLLVMArgMapping IRFunctionArgs(CGM.getContext(), CallInfo); @@ -5051,11 +5080,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // If the call returns a temporary with struct return, create a temporary // alloca to hold the result, unless one is given to us. Address SRetPtr = Address::invalid(); - Address SRetAlloca = Address::invalid(); + RawAddress SRetAlloca = RawAddress::invalid(); llvm::Value *UnusedReturnSizePtr = nullptr; if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) { if (!ReturnValue.isNull()) { - SRetPtr = ReturnValue.getValue(); + SRetPtr = ReturnValue.getAddress(); } else { SRetPtr = CreateMemTemp(RetTy, "tmp", &SRetAlloca); if (HaveInsertPoint() && ReturnValue.isUnused()) { @@ -5065,15 +5094,16 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } } if (IRFunctionArgs.hasSRetArg()) { - IRCallArgs[IRFunctionArgs.getSRetArgNo()] = SRetPtr.getPointer(); + IRCallArgs[IRFunctionArgs.getSRetArgNo()] = + getAsNaturalPointerTo(SRetPtr, RetTy); } else if (RetAI.isInAlloca()) { Address Addr = Builder.CreateStructGEP(ArgMemory, RetAI.getInAllocaFieldIndex()); - Builder.CreateStore(SRetPtr.getPointer(), Addr); + Builder.CreateStore(getAsNaturalPointerTo(SRetPtr, RetTy), Addr); } } - Address swiftErrorTemp = Address::invalid(); + RawAddress swiftErrorTemp = RawAddress::invalid(); Address swiftErrorArg = Address::invalid(); // When passing arguments using temporary allocas, we need to add the @@ -5106,9 +5136,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, assert(NumIRArgs == 0); assert(getTarget().getTriple().getArch() == llvm::Triple::x86); if (I->isAggregate()) { - Address Addr = I->hasLValue() - ? I->getKnownLValue().getAddress(*this) - : I->getKnownRValue().getAggregateAddress(); + RawAddress Addr = I->hasLValue() + ? I->getKnownLValue().getAddress(*this) + : I->getKnownRValue().getAggregateAddress(); llvm::Instruction *Placeholder = cast<llvm::Instruction>(Addr.getPointer()); @@ -5132,7 +5162,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } else if (ArgInfo.getInAllocaIndirect()) { // Make a temporary alloca and store the address of it into the argument // struct. - Address Addr = CreateMemTempWithoutCast( + RawAddress Addr = CreateMemTempWithoutCast( I->Ty, getContext().getTypeAlignInChars(I->Ty), "indirect-arg-temp"); I->copyInto(*this, Addr); @@ -5154,12 +5184,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, assert(NumIRArgs == 1); if (!I->isAggregate()) { // Make a temporary alloca to pass the argument. - Address Addr = CreateMemTempWithoutCast( + RawAddress Addr = CreateMemTempWithoutCast( I->Ty, ArgInfo.getIndirectAlign(), "indirect-arg-temp"); - llvm::Value *Val = Addr.getPointer(); + llvm::Value *Val = getAsNaturalPointerTo(Addr, I->Ty); if (ArgHasMaybeUndefAttr) - Val = Builder.CreateFreeze(Addr.getPointer()); + Val = Builder.CreateFreeze(Val); IRCallArgs[FirstIRArg] = Val; I->copyInto(*this, Addr); @@ -5175,7 +5205,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, Address Addr = I->hasLValue() ? I->getKnownLValue().getAddress(*this) : I->getKnownRValue().getAggregateAddress(); - llvm::Value *V = Addr.getPointer(); CharUnits Align = ArgInfo.getIndirectAlign(); const llvm::DataLayout *TD = &CGM.getDataLayout(); @@ -5186,8 +5215,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, bool NeedCopy = false; if (Addr.getAlignment() < Align && - llvm::getOrEnforceKnownAlignment(V, Align.getAsAlign(), *TD) < - Align.getAsAlign()) { + llvm::getOrEnforceKnownAlignment(Addr.emitRawPointer(*this), + Align.getAsAlign(), + *TD) < Align.getAsAlign()) { NeedCopy = true; } else if (I->hasLValue()) { auto LV = I->getKnownLValue(); @@ -5218,11 +5248,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, if (NeedCopy) { // Create an aligned temporary, and copy to it. - Address AI = CreateMemTempWithoutCast( + RawAddress AI = CreateMemTempWithoutCast( I->Ty, ArgInfo.getIndirectAlign(), "byval-temp"); - llvm::Value *Val = AI.getPointer(); + llvm::Value *Val = getAsNaturalPointerTo(AI, I->Ty); if (ArgHasMaybeUndefAttr) - Val = Builder.CreateFreeze(AI.getPointer()); + Val = Builder.CreateFreeze(Val); IRCallArgs[FirstIRArg] = Val; // Emit lifetime markers for the temporary alloca. @@ -5239,6 +5269,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, I->copyInto(*this, AI); } else { // Skip the extra memcpy call. + llvm::Value *V = getAsNaturalPointerTo(Addr, I->Ty); auto *T = llvm::PointerType::get( CGM.getLLVMContext(), CGM.getDataLayout().getAllocaAddrSpace()); @@ -5278,8 +5309,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, assert(!swiftErrorTemp.isValid() && "multiple swifterror args"); QualType pointeeTy = I->Ty->getPointeeType(); - swiftErrorArg = Address(V, ConvertTypeForMem(pointeeTy), - getContext().getTypeAlignInChars(pointeeTy)); + swiftErrorArg = makeNaturalAddressForPointer( + V, pointeeTy, getContext().getTypeAlignInChars(pointeeTy)); swiftErrorTemp = CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); @@ -5416,7 +5447,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm::Value *tempSize = nullptr; Address addr = Address::invalid(); - Address AllocaAddr = Address::invalid(); + RawAddress AllocaAddr = RawAddress::invalid(); if (I->isAggregate()) { addr = I->hasLValue() ? I->getKnownLValue().getAddress(*this) : I->getKnownRValue().getAggregateAddress(); @@ -5686,6 +5717,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, if (!CI->getType()->isVoidTy()) CI->setName("call"); + if (getTarget().getTriple().isSPIRVLogical() && CI->isConvergent()) + CI = addControlledConvergenceToken(CI); + // Update largest vector width from the return type. LargestVectorWidth = std::max(LargestVectorWidth, getMaxVectorWidth(CI->getType())); @@ -5850,7 +5884,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, return RValue::getComplex(std::make_pair(Real, Imag)); } case TEK_Aggregate: { - Address DestPtr = ReturnValue.getValue(); + Address DestPtr = ReturnValue.getAddress(); bool DestIsVolatile = ReturnValue.isVolatile(); if (!DestPtr.isValid()) { diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h index 1bd48a07259307486a53f2eba0de9f221274d219..6b676ac196db2a9a19f721b924da2e9ea274324c 100644 --- a/clang/lib/CodeGen/CGCall.h +++ b/clang/lib/CodeGen/CGCall.h @@ -377,6 +377,7 @@ public: Address getValue() const { return Addr; } bool isUnused() const { return IsUnused; } bool isExternallyDestructed() const { return IsExternallyDestructed; } + Address getAddress() const { return Addr; } }; /// Adds attributes to \p F according to our \p CodeGenOpts and \p LangOpts, as diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 34319381901af6c9458fd6cea2af18cf97be75e7..8c1c8ee455d2e634dc83a8845f2a970125184b9d 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -139,8 +139,9 @@ Address CodeGenFunction::LoadCXXThisAddress() { CXXThisAlignment = CGM.getClassPointerAlignment(MD->getParent()); } - llvm::Type *Ty = ConvertType(MD->getFunctionObjectParameterType()); - return Address(LoadCXXThis(), Ty, CXXThisAlignment, KnownNonNull); + return makeNaturalAddressForPointer( + LoadCXXThis(), MD->getFunctionObjectParameterType(), CXXThisAlignment, + false, nullptr, nullptr, KnownNonNull); } /// Emit the address of a field using a member data pointer. @@ -270,7 +271,7 @@ ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, Address addr, } // Apply the base offset. - llvm::Value *ptr = addr.getPointer(); + llvm::Value *ptr = addr.emitRawPointer(CGF); ptr = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ptr, baseOffset, "add.ptr"); // If we have a virtual component, the alignment of the result will @@ -338,8 +339,8 @@ Address CodeGenFunction::GetAddressOfBaseClass( if (sanitizePerformTypeCheck()) { SanitizerSet SkippedChecks; SkippedChecks.set(SanitizerKind::Null, !NullCheckValue); - EmitTypeCheck(TCK_Upcast, Loc, Value.getPointer(), - DerivedTy, DerivedAlign, SkippedChecks); + EmitTypeCheck(TCK_Upcast, Loc, Value.emitRawPointer(*this), DerivedTy, + DerivedAlign, SkippedChecks); } return Value.withElementType(BaseValueTy); } @@ -354,7 +355,7 @@ Address CodeGenFunction::GetAddressOfBaseClass( llvm::BasicBlock *notNullBB = createBasicBlock("cast.notnull"); endBB = createBasicBlock("cast.end"); - llvm::Value *isNull = Builder.CreateIsNull(Value.getPointer()); + llvm::Value *isNull = Builder.CreateIsNull(Value); Builder.CreateCondBr(isNull, endBB, notNullBB); EmitBlock(notNullBB); } @@ -363,14 +364,15 @@ Address CodeGenFunction::GetAddressOfBaseClass( SanitizerSet SkippedChecks; SkippedChecks.set(SanitizerKind::Null, true); EmitTypeCheck(VBase ? TCK_UpcastToVirtualBase : TCK_Upcast, Loc, - Value.getPointer(), DerivedTy, DerivedAlign, SkippedChecks); + Value.emitRawPointer(*this), DerivedTy, DerivedAlign, + SkippedChecks); } // Compute the virtual offset. llvm::Value *VirtualOffset = nullptr; if (VBase) { VirtualOffset = - CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase); + CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase); } // Apply both offsets. @@ -387,7 +389,7 @@ Address CodeGenFunction::GetAddressOfBaseClass( EmitBlock(endBB); llvm::PHINode *PHI = Builder.CreatePHI(PtrTy, 2, "cast.result"); - PHI->addIncoming(Value.getPointer(), notNullBB); + PHI->addIncoming(Value.emitRawPointer(*this), notNullBB); PHI->addIncoming(llvm::Constant::getNullValue(PtrTy), origBB); Value = Value.withPointer(PHI, NotKnownNonNull); } @@ -424,15 +426,19 @@ CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr, CastNotNull = createBasicBlock("cast.notnull"); CastEnd = createBasicBlock("cast.end"); - llvm::Value *IsNull = Builder.CreateIsNull(BaseAddr.getPointer()); + llvm::Value *IsNull = Builder.CreateIsNull(BaseAddr); Builder.CreateCondBr(IsNull, CastNull, CastNotNull); EmitBlock(CastNotNull); } // Apply the offset. - llvm::Value *Value = BaseAddr.getPointer(); - Value = Builder.CreateInBoundsGEP( - Int8Ty, Value, Builder.CreateNeg(NonVirtualOffset), "sub.ptr"); + Address Addr = BaseAddr.withElementType(Int8Ty); + Addr = Builder.CreateInBoundsGEP( + Addr, Builder.CreateNeg(NonVirtualOffset), Int8Ty, + CGM.getClassPointerAlignment(Derived), "sub.ptr"); + + // Just cast. + Addr = Addr.withElementType(DerivedValueTy); // Produce a PHI if we had a null-check. if (NullCheckValue) { @@ -441,13 +447,15 @@ CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr, Builder.CreateBr(CastEnd); EmitBlock(CastEnd); + llvm::Value *Value = Addr.emitRawPointer(*this); llvm::PHINode *PHI = Builder.CreatePHI(Value->getType(), 2); PHI->addIncoming(Value, CastNotNull); PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), CastNull); - Value = PHI; + return Address(PHI, Addr.getElementType(), + CGM.getClassPointerAlignment(Derived)); } - return Address(Value, DerivedValueTy, CGM.getClassPointerAlignment(Derived)); + return Addr; } llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD, @@ -1719,7 +1727,7 @@ namespace { // Use the base class declaration location as inline DebugLocation. All // fields of the class are destroyed. DeclAsInlineDebugLocation InlineHere(CGF, *BaseClass); - EmitSanitizerDtorFieldsCallback(CGF, Addr.getPointer(), + EmitSanitizerDtorFieldsCallback(CGF, Addr.emitRawPointer(CGF), BaseSize.getQuantity()); // Prevent the current stack frame from disappearing from the stack trace. @@ -2022,7 +2030,7 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, // Find the end of the array. llvm::Type *elementType = arrayBase.getElementType(); - llvm::Value *arrayBegin = arrayBase.getPointer(); + llvm::Value *arrayBegin = arrayBase.emitRawPointer(*this); llvm::Value *arrayEnd = Builder.CreateInBoundsGEP( elementType, arrayBegin, numElements, "arrayctor.end"); @@ -2118,14 +2126,15 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, Address This = ThisAVS.getAddress(); LangAS SlotAS = ThisAVS.getQualifiers().getAddressSpace(); LangAS ThisAS = D->getFunctionObjectParameterType().getAddressSpace(); - llvm::Value *ThisPtr = This.getPointer(); + llvm::Value *ThisPtr = + getAsNaturalPointerTo(This, D->getThisType()->getPointeeType()); if (SlotAS != ThisAS) { unsigned TargetThisAS = getContext().getTargetAddressSpace(ThisAS); llvm::Type *NewType = llvm::PointerType::get(getLLVMContext(), TargetThisAS); - ThisPtr = getTargetHooks().performAddrSpaceCast(*this, This.getPointer(), - ThisAS, SlotAS, NewType); + ThisPtr = getTargetHooks().performAddrSpaceCast(*this, ThisPtr, ThisAS, + SlotAS, NewType); } // Push the this ptr. @@ -2194,7 +2203,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, const CXXRecordDecl *ClassDecl = D->getParent(); if (!NewPointerIsChecked) - EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This.getPointer(), + EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This, getContext().getRecordType(ClassDecl), CharUnits::Zero()); if (D->isTrivial() && D->isDefaultConstructor()) { @@ -2207,10 +2216,9 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, // model that copy. if (isMemcpyEquivalentSpecialMember(D)) { assert(Args.size() == 2 && "unexpected argcount for trivial ctor"); - QualType SrcTy = D->getParamDecl(0)->getType().getNonReferenceType(); - Address Src = Address(Args[1].getRValue(*this).getScalarVal(), ConvertTypeForMem(SrcTy), - CGM.getNaturalTypeAlignment(SrcTy)); + Address Src = makeNaturalAddressForPointer( + Args[1].getRValue(*this).getScalarVal(), SrcTy); LValue SrcLVal = MakeAddrLValue(Src, SrcTy); QualType DestTy = getContext().getTypeDeclType(ClassDecl); LValue DestLVal = MakeAddrLValue(This, DestTy); @@ -2263,7 +2271,9 @@ void CodeGenFunction::EmitInheritedCXXConstructorCall( const CXXConstructorDecl *D, bool ForVirtualBase, Address This, bool InheritedFromVBase, const CXXInheritedCtorInitExpr *E) { CallArgList Args; - CallArg ThisArg(RValue::get(This.getPointer()), D->getThisType()); + CallArg ThisArg(RValue::get(getAsNaturalPointerTo( + This, D->getThisType()->getPointeeType())), + D->getThisType()); // Forward the parameters. if (InheritedFromVBase && @@ -2388,12 +2398,14 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, CallArgList Args; // Push the this ptr. - Args.add(RValue::get(This.getPointer()), D->getThisType()); + Args.add(RValue::get(getAsNaturalPointerTo(This, D->getThisType())), + D->getThisType()); // Push the src ptr. QualType QT = *(FPT->param_type_begin()); llvm::Type *t = CGM.getTypes().ConvertType(QT); - llvm::Value *SrcVal = Builder.CreateBitCast(Src.getPointer(), t); + llvm::Value *Val = getAsNaturalPointerTo(Src, D->getThisType()); + llvm::Value *SrcVal = Builder.CreateBitCast(Val, t); Args.add(RValue::get(SrcVal), QT); // Skip over first argument (Src). @@ -2418,7 +2430,9 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, // this Address This = LoadCXXThisAddress(); - DelegateArgs.add(RValue::get(This.getPointer()), (*I)->getType()); + DelegateArgs.add(RValue::get(getAsNaturalPointerTo( + This, (*I)->getType()->getPointeeType())), + (*I)->getType()); ++I; // FIXME: The location of the VTT parameter in the parameter list is @@ -2775,7 +2789,7 @@ void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, Address Derived, if (MayBeNull) { llvm::Value *DerivedNotNull = - Builder.CreateIsNotNull(Derived.getPointer(), "cast.nonnull"); + Builder.CreateIsNotNull(Derived.emitRawPointer(*this), "cast.nonnull"); llvm::BasicBlock *CheckBlock = createBasicBlock("cast.check"); ContBlock = createBasicBlock("cast.cont"); @@ -2976,7 +2990,7 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() { QualType ThisType = getContext().getPointerType(getContext().getRecordType(Lambda)); Address ThisPtr = GetAddrOfBlockDecl(variable); - CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType); + CallArgs.add(RValue::get(getAsNaturalPointerTo(ThisPtr, ThisType)), ThisType); // Add the rest of the parameters. for (auto *param : BD->parameters()) @@ -3004,7 +3018,7 @@ void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) { QualType LambdaType = getContext().getRecordType(Lambda); QualType ThisType = getContext().getPointerType(LambdaType); Address ThisPtr = CreateMemTemp(LambdaType, "unused.capture"); - CallArgs.add(RValue::get(ThisPtr.getPointer()), ThisType); + CallArgs.add(RValue::get(ThisPtr.emitRawPointer(*this)), ThisType); EmitLambdaDelegatingInvokeBody(MD, CallArgs); } diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp index f87caf050eeaa74b31de1452327e67f6139afaa8..e6f8e6873004f29d716caea0e82fb902be0f8117 100644 --- a/clang/lib/CodeGen/CGCleanup.cpp +++ b/clang/lib/CodeGen/CGCleanup.cpp @@ -27,7 +27,7 @@ bool DominatingValue<RValue>::saved_type::needsSaving(RValue rv) { if (rv.isScalar()) return DominatingLLVMValue::needsSaving(rv.getScalarVal()); if (rv.isAggregate()) - return DominatingLLVMValue::needsSaving(rv.getAggregatePointer()); + return DominatingValue<Address>::needsSaving(rv.getAggregateAddress()); return true; } @@ -35,69 +35,40 @@ DominatingValue<RValue>::saved_type DominatingValue<RValue>::saved_type::save(CodeGenFunction &CGF, RValue rv) { if (rv.isScalar()) { llvm::Value *V = rv.getScalarVal(); - - // These automatically dominate and don't need to be saved. - if (!DominatingLLVMValue::needsSaving(V)) - return saved_type(V, nullptr, ScalarLiteral); - - // Everything else needs an alloca. - Address addr = - CGF.CreateDefaultAlignTempAlloca(V->getType(), "saved-rvalue"); - CGF.Builder.CreateStore(V, addr); - return saved_type(addr.getPointer(), nullptr, ScalarAddress); + return saved_type(DominatingLLVMValue::save(CGF, V), + DominatingLLVMValue::needsSaving(V) ? ScalarAddress + : ScalarLiteral); } if (rv.isComplex()) { CodeGenFunction::ComplexPairTy V = rv.getComplexVal(); - llvm::Type *ComplexTy = - llvm::StructType::get(V.first->getType(), V.second->getType()); - Address addr = CGF.CreateDefaultAlignTempAlloca(ComplexTy, "saved-complex"); - CGF.Builder.CreateStore(V.first, CGF.Builder.CreateStructGEP(addr, 0)); - CGF.Builder.CreateStore(V.second, CGF.Builder.CreateStructGEP(addr, 1)); - return saved_type(addr.getPointer(), nullptr, ComplexAddress); + return saved_type(DominatingLLVMValue::save(CGF, V.first), + DominatingLLVMValue::save(CGF, V.second)); } assert(rv.isAggregate()); - Address V = rv.getAggregateAddress(); // TODO: volatile? - if (!DominatingLLVMValue::needsSaving(V.getPointer())) - return saved_type(V.getPointer(), V.getElementType(), AggregateLiteral, - V.getAlignment().getQuantity()); - - Address addr = - CGF.CreateTempAlloca(V.getType(), CGF.getPointerAlign(), "saved-rvalue"); - CGF.Builder.CreateStore(V.getPointer(), addr); - return saved_type(addr.getPointer(), V.getElementType(), AggregateAddress, - V.getAlignment().getQuantity()); + Address V = rv.getAggregateAddress(); + return saved_type( + DominatingValue<Address>::save(CGF, V), rv.isVolatileQualified(), + DominatingValue<Address>::needsSaving(V) ? AggregateAddress + : AggregateLiteral); } /// Given a saved r-value produced by SaveRValue, perform the code /// necessary to restore it to usability at the current insertion /// point. RValue DominatingValue<RValue>::saved_type::restore(CodeGenFunction &CGF) { - auto getSavingAddress = [&](llvm::Value *value) { - auto *AI = cast<llvm::AllocaInst>(value); - return Address(value, AI->getAllocatedType(), - CharUnits::fromQuantity(AI->getAlign().value())); - }; switch (K) { case ScalarLiteral: - return RValue::get(Value); case ScalarAddress: - return RValue::get(CGF.Builder.CreateLoad(getSavingAddress(Value))); + return RValue::get(DominatingLLVMValue::restore(CGF, Vals.first)); case AggregateLiteral: + case AggregateAddress: return RValue::getAggregate( - Address(Value, ElementType, CharUnits::fromQuantity(Align))); - case AggregateAddress: { - auto addr = CGF.Builder.CreateLoad(getSavingAddress(Value)); - return RValue::getAggregate( - Address(addr, ElementType, CharUnits::fromQuantity(Align))); - } + DominatingValue<Address>::restore(CGF, AggregateAddr), IsVolatile); case ComplexAddress: { - Address address = getSavingAddress(Value); - llvm::Value *real = - CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(address, 0)); - llvm::Value *imag = - CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(address, 1)); + llvm::Value *real = DominatingLLVMValue::restore(CGF, Vals.first); + llvm::Value *imag = DominatingLLVMValue::restore(CGF, Vals.second); return RValue::getComplex(real, imag); } } @@ -294,14 +265,14 @@ void EHScopeStack::popNullFixups() { BranchFixups.pop_back(); } -Address CodeGenFunction::createCleanupActiveFlag() { +RawAddress CodeGenFunction::createCleanupActiveFlag() { // Create a variable to decide whether the cleanup needs to be run. - Address active = CreateTempAllocaWithoutCast( + RawAddress active = CreateTempAllocaWithoutCast( Builder.getInt1Ty(), CharUnits::One(), "cleanup.cond"); // Initialize it to false at a site that's guaranteed to be run // before each evaluation. - setBeforeOutermostConditional(Builder.getFalse(), active); + setBeforeOutermostConditional(Builder.getFalse(), active, *this); // Initialize it to true at the current location. Builder.CreateStore(Builder.getTrue(), active); @@ -309,7 +280,7 @@ Address CodeGenFunction::createCleanupActiveFlag() { return active; } -void CodeGenFunction::initFullExprCleanupWithFlag(Address ActiveFlag) { +void CodeGenFunction::initFullExprCleanupWithFlag(RawAddress ActiveFlag) { // Set that as the active flag in the cleanup. EHCleanupScope &cleanup = cast<EHCleanupScope>(*EHStack.begin()); assert(!cleanup.hasActiveFlag() && "cleanup already has active flag?"); @@ -322,15 +293,17 @@ void CodeGenFunction::initFullExprCleanupWithFlag(Address ActiveFlag) { void EHScopeStack::Cleanup::anchor() {} static void createStoreInstBefore(llvm::Value *value, Address addr, - llvm::Instruction *beforeInst) { - auto store = new llvm::StoreInst(value, addr.getPointer(), beforeInst); + llvm::Instruction *beforeInst, + CodeGenFunction &CGF) { + auto store = new llvm::StoreInst(value, addr.emitRawPointer(CGF), beforeInst); store->setAlignment(addr.getAlignment().getAsAlign()); } static llvm::LoadInst *createLoadInstBefore(Address addr, const Twine &name, - llvm::Instruction *beforeInst) { - return new llvm::LoadInst(addr.getElementType(), addr.getPointer(), name, - false, addr.getAlignment().getAsAlign(), + llvm::Instruction *beforeInst, + CodeGenFunction &CGF) { + return new llvm::LoadInst(addr.getElementType(), addr.emitRawPointer(CGF), + name, false, addr.getAlignment().getAsAlign(), beforeInst); } @@ -357,8 +330,8 @@ static void ResolveAllBranchFixups(CodeGenFunction &CGF, // entry which we're currently popping. if (Fixup.OptimisticBranchBlock == nullptr) { createStoreInstBefore(CGF.Builder.getInt32(Fixup.DestinationIndex), - CGF.getNormalCleanupDestSlot(), - Fixup.InitialBranch); + CGF.getNormalCleanupDestSlot(), Fixup.InitialBranch, + CGF); Fixup.InitialBranch->setSuccessor(0, CleanupEntry); } @@ -385,7 +358,7 @@ static llvm::SwitchInst *TransitionToCleanupSwitch(CodeGenFunction &CGF, if (llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Term)) { assert(Br->isUnconditional()); auto Load = createLoadInstBefore(CGF.getNormalCleanupDestSlot(), - "cleanup.dest", Term); + "cleanup.dest", Term, CGF); llvm::SwitchInst *Switch = llvm::SwitchInst::Create(Load, Br->getSuccessor(0), 4, Block); Br->eraseFromParent(); @@ -513,8 +486,8 @@ void CodeGenFunction::PopCleanupBlocks( I += Header.getSize(); if (Header.isConditional()) { - Address ActiveFlag = - reinterpret_cast<Address &>(LifetimeExtendedCleanupStack[I]); + RawAddress ActiveFlag = + reinterpret_cast<RawAddress &>(LifetimeExtendedCleanupStack[I]); initFullExprCleanupWithFlag(ActiveFlag); I += sizeof(ActiveFlag); } @@ -888,7 +861,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { if (NormalCleanupDestSlot->hasOneUse()) { NormalCleanupDestSlot->user_back()->eraseFromParent(); NormalCleanupDestSlot->eraseFromParent(); - NormalCleanupDest = Address::invalid(); + NormalCleanupDest = RawAddress::invalid(); } llvm::BasicBlock *BranchAfter = Scope.getBranchAfterBlock(0); @@ -912,9 +885,8 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { // pass the abnormal exit flag to Fn (SEH cleanup) cleanupFlags.setHasExitSwitch(); - llvm::LoadInst *Load = - createLoadInstBefore(getNormalCleanupDestSlot(), "cleanup.dest", - nullptr); + llvm::LoadInst *Load = createLoadInstBefore( + getNormalCleanupDestSlot(), "cleanup.dest", nullptr, *this); llvm::SwitchInst *Switch = llvm::SwitchInst::Create(Load, Default, SwitchCapacity); @@ -961,8 +933,8 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { if (!Fixup.Destination) continue; if (!Fixup.OptimisticBranchBlock) { createStoreInstBefore(Builder.getInt32(Fixup.DestinationIndex), - getNormalCleanupDestSlot(), - Fixup.InitialBranch); + getNormalCleanupDestSlot(), Fixup.InitialBranch, + *this); Fixup.InitialBranch->setSuccessor(0, NormalEntry); } Fixup.OptimisticBranchBlock = NormalExit; @@ -1135,7 +1107,7 @@ void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) { // Store the index at the start. llvm::ConstantInt *Index = Builder.getInt32(Dest.getDestIndex()); - createStoreInstBefore(Index, getNormalCleanupDestSlot(), BI); + createStoreInstBefore(Index, getNormalCleanupDestSlot(), BI, *this); // Adjust BI to point to the first cleanup block. { @@ -1269,9 +1241,9 @@ static void SetupCleanupBlockActivation(CodeGenFunction &CGF, // If we're in a conditional block, ignore the dominating IP and // use the outermost conditional branch. if (CGF.isInConditionalBranch()) { - CGF.setBeforeOutermostConditional(value, var); + CGF.setBeforeOutermostConditional(value, var, CGF); } else { - createStoreInstBefore(value, var, dominatingIP); + createStoreInstBefore(value, var, dominatingIP, CGF); } } @@ -1321,7 +1293,7 @@ void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C, Scope.setActive(false); } -Address CodeGenFunction::getNormalCleanupDestSlot() { +RawAddress CodeGenFunction::getNormalCleanupDestSlot() { if (!NormalCleanupDest.isValid()) NormalCleanupDest = CreateDefaultAlignTempAlloca(Builder.getInt32Ty(), "cleanup.dest.slot"); diff --git a/clang/lib/CodeGen/CGCleanup.h b/clang/lib/CodeGen/CGCleanup.h index 7a7344c07160db388ba8d743a37c245069c9af9c..03e4a29d7b3dbfa5b3953725e9fc1fe0fe55bb44 100644 --- a/clang/lib/CodeGen/CGCleanup.h +++ b/clang/lib/CodeGen/CGCleanup.h @@ -333,7 +333,7 @@ public: Address getActiveFlag() const { return ActiveFlag; } - void setActiveFlag(Address Var) { + void setActiveFlag(RawAddress Var) { assert(Var.getAlignment().isOne()); ActiveFlag = Var; } diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index b7142ec08af986d16656fdb7e10aed35b98912d1..93ca711f716fce5bec80f56f81e0f3749de5d3f8 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -867,8 +867,8 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) { EmitStmt(S.getPromiseDeclStmt()); Address PromiseAddr = GetAddrOfLocalVar(S.getPromiseDecl()); - auto *PromiseAddrVoidPtr = - new llvm::BitCastInst(PromiseAddr.getPointer(), VoidPtrTy, "", CoroId); + auto *PromiseAddrVoidPtr = new llvm::BitCastInst( + PromiseAddr.emitRawPointer(*this), VoidPtrTy, "", CoroId); // Update CoroId to refer to the promise. We could not do it earlier because // promise local variable was not emitted yet. CoroId->setArgOperand(1, PromiseAddrVoidPtr); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index c2c01439f2dc99319f08a1bbb276e9ff5532b360..8c284c332171a1bbdd9a3af14692e7de5ac81ec2 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1440,8 +1440,7 @@ static unsigned getDwarfCC(CallingConv CC) { case CC_Swift: return llvm::dwarf::DW_CC_LLVM_Swift; case CC_SwiftAsync: - // [FIXME: swiftasynccc] Update to SwiftAsync once LLVM support lands. - return llvm::dwarf::DW_CC_LLVM_Swift; + return llvm::dwarf::DW_CC_LLVM_SwiftTail; case CC_PreserveMost: return llvm::dwarf::DW_CC_LLVM_PreserveMost; case CC_PreserveAll: @@ -1452,6 +1451,8 @@ static unsigned getDwarfCC(CallingConv CC) { return llvm::dwarf::DW_CC_LLVM_M68kRTD; case CC_PreserveNone: return llvm::dwarf::DW_CC_LLVM_PreserveNone; + case CC_RISCVVectorCall: + return llvm::dwarf::DW_CC_LLVM_RISCVVectorCall; } return 0; } @@ -3239,7 +3240,7 @@ llvm::DIType *CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile *Unit) { // }; int64_t Count = -1; // Count == -1 is an unbounded array. if (const auto *CAT = dyn_cast<ConstantArrayType>(Ty)) - Count = CAT->getSize().getZExtValue(); + Count = CAT->getZExtSize(); else if (const auto *VAT = dyn_cast<VariableArrayType>(Ty)) { if (Expr *Size = VAT->getSizeExpr()) { Expr::EvalResult Result; @@ -3463,6 +3464,9 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) { case Type::BTFTagAttributed: T = cast<BTFTagAttributedType>(T)->getWrappedType(); break; + case Type::CountAttributed: + T = cast<CountAttributedType>(T)->desugar(); + break; case Type::Elaborated: T = cast<ElaboratedType>(T)->getNamedType(); break; @@ -3637,6 +3641,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { case Type::ConstantArray: case Type::VariableArray: case Type::IncompleteArray: + case Type::ArrayParameter: return CreateType(cast<ArrayType>(Ty), Unit); case Type::LValueReference: @@ -3658,6 +3663,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { case Type::TemplateSpecialization: return CreateType(cast<TemplateSpecializationType>(Ty), Unit); + case Type::CountAttributed: case Type::Auto: case Type::Attributed: case Type::BTFTagAttributed: diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index bbe14ef4c17244f75ecd6866d0e86e8e3ec36685..267f2e40a7bbaa198ed551bcc67702a38d783f11 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -284,6 +284,7 @@ llvm::Constant *CodeGenModule::getOrCreateStaticVarDecl( setTLSMode(GV, D); setGVProperties(GV, &D); + getTargetCodeGenInfo().setTargetAttributes(cast<Decl>(&D), GV, *this); // Make sure the result is of the correct type. LangAS ExpectedAS = Ty.getAddressSpace(); @@ -1241,27 +1242,38 @@ static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D, return; } - // If the initializer is small, use a handful of stores. + // If the initializer is small or trivialAutoVarInit is set, use a handful of + // stores. + bool IsTrivialAutoVarInitPattern = + CGM.getContext().getLangOpts().getTrivialAutoVarInit() == + LangOptions::TrivialAutoVarInitKind::Pattern; if (shouldSplitConstantStore(CGM, ConstantSize)) { if (auto *STy = dyn_cast<llvm::StructType>(Ty)) { - const llvm::StructLayout *Layout = - CGM.getDataLayout().getStructLayout(STy); - for (unsigned i = 0; i != constant->getNumOperands(); i++) { - CharUnits CurOff = CharUnits::fromQuantity(Layout->getElementOffset(i)); - Address EltPtr = Builder.CreateConstInBoundsByteGEP( - Loc.withElementType(CGM.Int8Ty), CurOff); - emitStoresForConstant(CGM, D, EltPtr, isVolatile, Builder, - constant->getAggregateElement(i), IsAutoInit); + if (STy == Loc.getElementType() || + (STy != Loc.getElementType() && IsTrivialAutoVarInitPattern)) { + const llvm::StructLayout *Layout = + CGM.getDataLayout().getStructLayout(STy); + for (unsigned i = 0; i != constant->getNumOperands(); i++) { + CharUnits CurOff = + CharUnits::fromQuantity(Layout->getElementOffset(i)); + Address EltPtr = Builder.CreateConstInBoundsByteGEP( + Loc.withElementType(CGM.Int8Ty), CurOff); + emitStoresForConstant(CGM, D, EltPtr, isVolatile, Builder, + constant->getAggregateElement(i), IsAutoInit); + } + return; } - return; } else if (auto *ATy = dyn_cast<llvm::ArrayType>(Ty)) { - for (unsigned i = 0; i != ATy->getNumElements(); i++) { - Address EltPtr = Builder.CreateConstGEP( - Loc.withElementType(ATy->getElementType()), i); - emitStoresForConstant(CGM, D, EltPtr, isVolatile, Builder, - constant->getAggregateElement(i), IsAutoInit); + if (ATy == Loc.getElementType() || + (ATy != Loc.getElementType() && IsTrivialAutoVarInitPattern)) { + for (unsigned i = 0; i != ATy->getNumElements(); i++) { + Address EltPtr = Builder.CreateConstGEP( + Loc.withElementType(ATy->getElementType()), i); + emitStoresForConstant(CGM, D, EltPtr, isVolatile, Builder, + constant->getAggregateElement(i), IsAutoInit); + } + return; } - return; } } @@ -1449,7 +1461,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { bool EmitDebugInfo = DI && CGM.getCodeGenOpts().hasReducedDebugInfo(); Address address = Address::invalid(); - Address AllocaAddr = Address::invalid(); + RawAddress AllocaAddr = RawAddress::invalid(); Address OpenMPLocalAddr = Address::invalid(); if (CGM.getLangOpts().OpenMPIRBuilder) OpenMPLocalAddr = OMPBuilderCBHelpers::getAddressOfLocalVariable(*this, &D); @@ -1512,7 +1524,10 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { // return slot, so that we can elide the copy when returning this // variable (C++0x [class.copy]p34). address = ReturnValue; - AllocaAddr = ReturnValue; + AllocaAddr = + RawAddress(ReturnValue.emitRawPointer(*this), + ReturnValue.getElementType(), ReturnValue.getAlignment()); + ; if (const RecordType *RecordTy = Ty->getAs<RecordType>()) { const auto *RD = RecordTy->getDecl(); @@ -1523,7 +1538,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { // to this variable. Set it to zero to indicate that NRVO was not // applied. llvm::Value *Zero = Builder.getFalse(); - Address NRVOFlag = + RawAddress NRVOFlag = CreateTempAlloca(Zero->getType(), CharUnits::One(), "nrvo"); EnsureInsertPoint(); Builder.CreateStore(Zero, NRVOFlag); @@ -1666,7 +1681,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { } if (D.hasAttr<AnnotateAttr>() && HaveInsertPoint()) - EmitVarAnnotations(&D, address.getPointer()); + EmitVarAnnotations(&D, address.emitRawPointer(*this)); // Make sure we call @llvm.lifetime.end. if (emission.useLifetimeMarkers()) @@ -1839,12 +1854,13 @@ void CodeGenFunction::emitZeroOrPatternForAutoVarInit(QualType type, llvm::Value *BaseSizeInChars = llvm::ConstantInt::get(IntPtrTy, EltSize.getQuantity()); Address Begin = Loc.withElementType(Int8Ty); - llvm::Value *End = Builder.CreateInBoundsGEP( - Begin.getElementType(), Begin.getPointer(), SizeVal, "vla.end"); + llvm::Value *End = Builder.CreateInBoundsGEP(Begin.getElementType(), + Begin.emitRawPointer(*this), + SizeVal, "vla.end"); llvm::BasicBlock *OriginBB = Builder.GetInsertBlock(); EmitBlock(LoopBB); llvm::PHINode *Cur = Builder.CreatePHI(Begin.getType(), 2, "vla.cur"); - Cur->addIncoming(Begin.getPointer(), OriginBB); + Cur->addIncoming(Begin.emitRawPointer(*this), OriginBB); CharUnits CurAlign = Loc.getAlignment().alignmentOfArrayElement(EltSize); auto *I = Builder.CreateMemCpy(Address(Cur, Int8Ty, CurAlign), @@ -2271,7 +2287,7 @@ void CodeGenFunction::emitDestroy(Address addr, QualType type, checkZeroLength = false; } - llvm::Value *begin = addr.getPointer(); + llvm::Value *begin = addr.emitRawPointer(*this); llvm::Value *end = Builder.CreateInBoundsGEP(addr.getElementType(), begin, length); emitArrayDestroy(begin, end, type, elementAlign, destroyer, @@ -2531,7 +2547,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, } Address DeclPtr = Address::invalid(); - Address AllocaPtr = Address::invalid(); + RawAddress AllocaPtr = Address::invalid(); bool DoStore = false; bool IsScalar = hasScalarEvaluationKind(Ty); bool UseIndirectDebugAddress = false; @@ -2543,8 +2559,8 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, // Indirect argument is in alloca address space, which may be different // from the default address space. auto AllocaAS = CGM.getASTAllocaAddressSpace(); - auto *V = DeclPtr.getPointer(); - AllocaPtr = DeclPtr; + auto *V = DeclPtr.emitRawPointer(*this); + AllocaPtr = RawAddress(V, DeclPtr.getElementType(), DeclPtr.getAlignment()); // For truly ABI indirect arguments -- those that are not `byval` -- store // the address of the argument on the stack to preserve debug information. @@ -2683,7 +2699,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, } if (D.hasAttr<AnnotateAttr>()) - EmitVarAnnotations(&D, DeclPtr.getPointer()); + EmitVarAnnotations(&D, DeclPtr.emitRawPointer(*this)); // We can only check return value nullability if all arguments to the // function satisfy their nullability preconditions. This makes it necessary diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 5a9d06da12de571ab376e8740b06fd63ac66cc9f..34f289334a7df90584d9b7f80bf57a99060a7af0 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -397,7 +397,7 @@ namespace { void CodeGenFunction::EmitAnyExprToExn(const Expr *e, Address addr) { // Make sure the exception object is cleaned up if there's an // exception during initialization. - pushFullExprCleanup<FreeException>(EHCleanup, addr.getPointer()); + pushFullExprCleanup<FreeException>(EHCleanup, addr.emitRawPointer(*this)); EHScopeStack::stable_iterator cleanup = EHStack.stable_begin(); // __cxa_allocate_exception returns a void*; we need to cast this @@ -416,8 +416,8 @@ void CodeGenFunction::EmitAnyExprToExn(const Expr *e, Address addr) { /*IsInit*/ true); // Deactivate the cleanup block. - DeactivateCleanupBlock(cleanup, - cast<llvm::Instruction>(typedAddr.getPointer())); + DeactivateCleanupBlock( + cleanup, cast<llvm::Instruction>(typedAddr.emitRawPointer(*this))); } Address CodeGenFunction::getExceptionSlot() { @@ -1834,7 +1834,8 @@ Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, llvm::Value *ParentFP) { llvm::CallInst *RecoverCall = nullptr; CGBuilderTy Builder(*this, AllocaInsertPt); - if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar.getPointer())) { + if (auto *ParentAlloca = + dyn_cast_or_null<llvm::AllocaInst>(ParentVar.getBasePointer())) { // Mark the variable escaped if nobody else referenced it and compute the // localescape index. auto InsertPair = ParentCGF.EscapedLocals.insert( @@ -1851,8 +1852,8 @@ Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, // If the parent didn't have an alloca, we're doing some nested outlining. // Just clone the existing localrecover call, but tweak the FP argument to // use our FP value. All other arguments are constants. - auto *ParentRecover = - cast<llvm::IntrinsicInst>(ParentVar.getPointer()->stripPointerCasts()); + auto *ParentRecover = cast<llvm::IntrinsicInst>( + ParentVar.emitRawPointer(*this)->stripPointerCasts()); assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::localrecover && "expected alloca or localrecover in parent LocalDeclMap"); RecoverCall = cast<llvm::CallInst>(ParentRecover->clone()); @@ -1925,7 +1926,8 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, if (isa<ImplicitParamDecl>(D) && D->getType() == getContext().VoidPtrTy) { assert(D->getName().starts_with("frame_pointer")); - FramePtrAddrAlloca = cast<llvm::AllocaInst>(I.second.getPointer()); + FramePtrAddrAlloca = + cast<llvm::AllocaInst>(I.second.getBasePointer()); break; } } @@ -1986,7 +1988,8 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, LValue ThisFieldLValue = EmitLValueForLambdaField(LambdaThisCaptureField); if (!LambdaThisCaptureField->getType()->isPointerType()) { - CXXThisValue = ThisFieldLValue.getAddress(*this).getPointer(); + CXXThisValue = + ThisFieldLValue.getAddress(*this).emitRawPointer(*this); } else { CXXThisValue = EmitLoadOfLValue(ThisFieldLValue, SourceLocation()) .getScalarVal(); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 59a7fe8925001cc497bfa8d8b8ba9ddf9fea2051..54432353e7420d184cc414f9a2e0efd9a87db2c3 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -56,8 +56,7 @@ using namespace CodeGen; // Experiment to make sanitizers easier to debug static llvm::cl::opt<bool> ClSanitizeDebugDeoptimization( "ubsan-unique-traps", llvm::cl::Optional, - llvm::cl::desc("Deoptimize traps for UBSAN so there is 1 trap per check"), - llvm::cl::init(false)); + llvm::cl::desc("Deoptimize traps for UBSAN so there is 1 trap per check")); //===--------------------------------------------------------------------===// // Miscellaneous Helper Methods @@ -65,21 +64,21 @@ static llvm::cl::opt<bool> ClSanitizeDebugDeoptimization( /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. -Address CodeGenFunction::CreateTempAllocaWithoutCast(llvm::Type *Ty, - CharUnits Align, - const Twine &Name, - llvm::Value *ArraySize) { +RawAddress +CodeGenFunction::CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits Align, + const Twine &Name, + llvm::Value *ArraySize) { auto Alloca = CreateTempAlloca(Ty, Name, ArraySize); Alloca->setAlignment(Align.getAsAlign()); - return Address(Alloca, Ty, Align, KnownNonNull); + return RawAddress(Alloca, Ty, Align, KnownNonNull); } /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. The alloca is casted to default address space if necessary. -Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align, - const Twine &Name, - llvm::Value *ArraySize, - Address *AllocaAddr) { +RawAddress CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align, + const Twine &Name, + llvm::Value *ArraySize, + RawAddress *AllocaAddr) { auto Alloca = CreateTempAllocaWithoutCast(Ty, Align, Name, ArraySize); if (AllocaAddr) *AllocaAddr = Alloca; @@ -101,7 +100,7 @@ Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align, Ty->getPointerTo(DestAddrSpace), /*non-null*/ true); } - return Address(V, Ty, Align, KnownNonNull); + return RawAddress(V, Ty, Align, KnownNonNull); } /// CreateTempAlloca - This creates an alloca and inserts it into the entry @@ -120,28 +119,29 @@ llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, /// default alignment of the corresponding LLVM type, which is *not* /// guaranteed to be related in any way to the expected alignment of /// an AST type that might have been lowered to Ty. -Address CodeGenFunction::CreateDefaultAlignTempAlloca(llvm::Type *Ty, - const Twine &Name) { +RawAddress CodeGenFunction::CreateDefaultAlignTempAlloca(llvm::Type *Ty, + const Twine &Name) { CharUnits Align = CharUnits::fromQuantity(CGM.getDataLayout().getPrefTypeAlign(Ty)); return CreateTempAlloca(Ty, Align, Name); } -Address CodeGenFunction::CreateIRTemp(QualType Ty, const Twine &Name) { +RawAddress CodeGenFunction::CreateIRTemp(QualType Ty, const Twine &Name) { CharUnits Align = getContext().getTypeAlignInChars(Ty); return CreateTempAlloca(ConvertType(Ty), Align, Name); } -Address CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name, - Address *Alloca) { +RawAddress CodeGenFunction::CreateMemTemp(QualType Ty, const Twine &Name, + RawAddress *Alloca) { // FIXME: Should we prefer the preferred type alignment here? return CreateMemTemp(Ty, getContext().getTypeAlignInChars(Ty), Name, Alloca); } -Address CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align, - const Twine &Name, Address *Alloca) { - Address Result = CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name, - /*ArraySize=*/nullptr, Alloca); +RawAddress CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align, + const Twine &Name, + RawAddress *Alloca) { + RawAddress Result = CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name, + /*ArraySize=*/nullptr, Alloca); if (Ty->isConstantMatrixType()) { auto *ArrayTy = cast<llvm::ArrayType>(Result.getElementType()); @@ -154,13 +154,14 @@ Address CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align, return Result; } -Address CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, CharUnits Align, - const Twine &Name) { +RawAddress CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, + CharUnits Align, + const Twine &Name) { return CreateTempAllocaWithoutCast(ConvertTypeForMem(Ty), Align, Name); } -Address CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, - const Twine &Name) { +RawAddress CodeGenFunction::CreateMemTempWithoutCast(QualType Ty, + const Twine &Name) { return CreateMemTempWithoutCast(Ty, getContext().getTypeAlignInChars(Ty), Name); } @@ -359,7 +360,7 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, } else { CleanupFn = CGF.CGM.getAddrAndTypeOfCXXStructor( GlobalDecl(ReferenceTemporaryDtor, Dtor_Complete)); - CleanupArg = cast<llvm::Constant>(ReferenceTemporary.getPointer()); + CleanupArg = cast<llvm::Constant>(ReferenceTemporary.emitRawPointer(CGF)); } CGF.CGM.getCXXABI().registerGlobalDtor( CGF, *cast<VarDecl>(M->getExtendingDecl()), CleanupFn, CleanupArg); @@ -384,10 +385,10 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, } } -static Address createReferenceTemporary(CodeGenFunction &CGF, - const MaterializeTemporaryExpr *M, - const Expr *Inner, - Address *Alloca = nullptr) { +static RawAddress createReferenceTemporary(CodeGenFunction &CGF, + const MaterializeTemporaryExpr *M, + const Expr *Inner, + RawAddress *Alloca = nullptr) { auto &TCG = CGF.getTargetHooks(); switch (M->getStorageDuration()) { case SD_FullExpression: @@ -416,7 +417,7 @@ static Address createReferenceTemporary(CodeGenFunction &CGF, GV->getValueType()->getPointerTo( CGF.getContext().getTargetAddressSpace(LangAS::Default))); // FIXME: Should we put the new global into a COMDAT? - return Address(C, GV->getValueType(), alignment); + return RawAddress(C, GV->getValueType(), alignment); } return CGF.CreateMemTemp(Ty, "ref.tmp", Alloca); } @@ -448,7 +449,7 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) { auto ownership = M->getType().getObjCLifetime(); if (ownership != Qualifiers::OCL_None && ownership != Qualifiers::OCL_ExplicitNone) { - Address Object = createReferenceTemporary(*this, M, E); + RawAddress Object = createReferenceTemporary(*this, M, E); if (auto *Var = dyn_cast<llvm::GlobalVariable>(Object.getPointer())) { llvm::Type *Ty = ConvertTypeForMem(E->getType()); Object = Object.withElementType(Ty); @@ -502,8 +503,8 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) { } // Create and initialize the reference temporary. - Address Alloca = Address::invalid(); - Address Object = createReferenceTemporary(*this, M, E, &Alloca); + RawAddress Alloca = Address::invalid(); + RawAddress Object = createReferenceTemporary(*this, M, E, &Alloca); if (auto *Var = dyn_cast<llvm::GlobalVariable>( Object.getPointer()->stripPointerCasts())) { llvm::Type *TemporaryType = ConvertTypeForMem(E->getType()); @@ -1111,12 +1112,12 @@ llvm::Value *CodeGenFunction::EmitCountedByFieldExpr( } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(StructBase)) { LValue LV = EmitMemberExpr(ME); Address Addr = LV.getAddress(*this); - Res = Addr.getPointer(); + Res = Addr.emitRawPointer(*this); } else if (StructBase->getType()->isPointerType()) { LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; Address Addr = EmitPointerWithAlignment(StructBase, &BaseInfo, &TBAAInfo); - Res = Addr.getPointer(); + Res = Addr.emitRawPointer(*this); } else { return nullptr; } @@ -1136,38 +1137,19 @@ llvm::Value *CodeGenFunction::EmitCountedByFieldExpr( } const FieldDecl *CodeGenFunction::FindCountedByField(const FieldDecl *FD) { - if (!FD || !FD->hasAttr<CountedByAttr>()) - return nullptr; - - const auto *CBA = FD->getAttr<CountedByAttr>(); - if (!CBA) - return nullptr; - - auto GetNonAnonStructOrUnion = - [](const RecordDecl *RD) -> const RecordDecl * { - while (RD && RD->isAnonymousStructOrUnion()) { - const auto *R = dyn_cast<RecordDecl>(RD->getDeclContext()); - if (!R) - return nullptr; - RD = R; - } - return RD; - }; - const RecordDecl *EnclosingRD = GetNonAnonStructOrUnion(FD->getParent()); - if (!EnclosingRD) + if (!FD) return nullptr; - DeclarationName DName(CBA->getCountedByField()); - DeclContext::lookup_result Lookup = EnclosingRD->lookup(DName); - - if (Lookup.empty()) + const auto *CAT = FD->getType()->getAs<CountAttributedType>(); + if (!CAT) return nullptr; - const NamedDecl *ND = Lookup.front(); - if (const auto *IFD = dyn_cast<IndirectFieldDecl>(ND)) - ND = IFD->getAnonField(); + const auto *CountDRE = cast<DeclRefExpr>(CAT->getCountExpr()); + const auto *CountDecl = CountDRE->getDecl(); + if (const auto *IFD = dyn_cast<IndirectFieldDecl>(CountDecl)) + CountDecl = IFD->getAnonField(); - return dyn_cast<FieldDecl>(ND); + return dyn_cast<FieldDecl>(CountDecl); } void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base, @@ -1301,8 +1283,7 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, if (InnerBaseInfo.getAlignmentSource() != AlignmentSource::Decl) { if (BaseInfo) BaseInfo->mergeForCast(TargetTypeBaseInfo); - Addr = Address(Addr.getPointer(), Addr.getElementType(), Align, - IsKnownNonNull); + Addr.setAlignment(Align); } } @@ -1319,8 +1300,8 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, CGF.ConvertTypeForMem(E->getType()->getPointeeType()); Addr = Addr.withElementType(ElemTy); if (CE->getCastKind() == CK_AddressSpaceConversion) - Addr = CGF.Builder.CreateAddrSpaceCast(Addr, - CGF.ConvertType(E->getType())); + Addr = CGF.Builder.CreateAddrSpaceCast( + Addr, CGF.ConvertType(E->getType()), ElemTy); return Addr; } break; @@ -1383,10 +1364,9 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, // TODO: conditional operators, comma. // Otherwise, use the alignment of the type. - CharUnits Align = - CGF.CGM.getNaturalPointeeTypeAlignment(E->getType(), BaseInfo, TBAAInfo); - llvm::Type *ElemTy = CGF.ConvertTypeForMem(E->getType()->getPointeeType()); - return Address(CGF.EmitScalarExpr(E), ElemTy, Align, IsKnownNonNull); + return CGF.makeNaturalAddressForPointer( + CGF.EmitScalarExpr(E), E->getType()->getPointeeType(), CharUnits(), + /*ForPointeeType=*/true, BaseInfo, TBAAInfo, IsKnownNonNull); } /// EmitPointerWithAlignment - Given an expression of pointer type, try to @@ -1487,8 +1467,7 @@ LValue CodeGenFunction::EmitCheckedLValue(const Expr *E, TypeCheckKind TCK) { if (IsBaseCXXThis || isa<DeclRefExpr>(ME->getBase())) SkippedChecks.set(SanitizerKind::Null, true); } - EmitTypeCheck(TCK, E->getExprLoc(), LV.getPointer(*this), E->getType(), - LV.getAlignment(), SkippedChecks); + EmitTypeCheck(TCK, E->getExprLoc(), LV, E->getType(), SkippedChecks); } return LV; } @@ -1600,11 +1579,11 @@ LValue CodeGenFunction::EmitLValueHelper(const Expr *E, // Defend against branches out of gnu statement expressions surrounded by // cleanups. Address Addr = LV.getAddress(*this); - llvm::Value *V = Addr.getPointer(); + llvm::Value *V = Addr.getBasePointer(); Scope.ForceCleanup({&V}); - return LValue::MakeAddr(Addr.withPointer(V, Addr.isKnownNonNull()), - LV.getType(), getContext(), LV.getBaseInfo(), - LV.getTBAAInfo()); + Addr.replaceBasePointer(V); + return LValue::MakeAddr(Addr, LV.getType(), getContext(), + LV.getBaseInfo(), LV.getTBAAInfo()); } // FIXME: Is it possible to create an ExprWithCleanups that produces a // bitfield lvalue or some other non-simple lvalue? @@ -1948,7 +1927,7 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, bool isNontemporal) { - if (auto *GV = dyn_cast<llvm::GlobalValue>(Addr.getPointer())) + if (auto *GV = dyn_cast<llvm::GlobalValue>(Addr.getBasePointer())) if (GV->isThreadLocal()) Addr = Addr.withPointer(Builder.CreateThreadLocalAddress(GV), NotKnownNonNull); @@ -2058,8 +2037,9 @@ llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) { // Convert the pointer of \p Addr to a pointer to a vector (the value type of // MatrixType), if it points to a array (the memory type of MatrixType). -static Address MaybeConvertMatrixAddress(Address Addr, CodeGenFunction &CGF, - bool IsVector = true) { +static RawAddress MaybeConvertMatrixAddress(RawAddress Addr, + CodeGenFunction &CGF, + bool IsVector = true) { auto *ArrayTy = dyn_cast<llvm::ArrayType>(Addr.getElementType()); if (ArrayTy && IsVector) { auto *VectorTy = llvm::FixedVectorType::get(ArrayTy->getElementType(), @@ -2096,7 +2076,7 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, bool isInit, bool isNontemporal) { - if (auto *GV = dyn_cast<llvm::GlobalValue>(Addr.getPointer())) + if (auto *GV = dyn_cast<llvm::GlobalValue>(Addr.getBasePointer())) if (GV->isThreadLocal()) Addr = Addr.withPointer(Builder.CreateThreadLocalAddress(GV), NotKnownNonNull); @@ -2451,14 +2431,12 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst, assert(Dst.getBaseIvarExp() && "BaseIvarExp is NULL"); llvm::Type *ResultType = IntPtrTy; Address dst = EmitPointerWithAlignment(Dst.getBaseIvarExp()); - llvm::Value *RHS = dst.getPointer(); + llvm::Value *RHS = dst.emitRawPointer(*this); RHS = Builder.CreatePtrToInt(RHS, ResultType, "sub.ptr.rhs.cast"); - llvm::Value *LHS = - Builder.CreatePtrToInt(LvalueDst.getPointer(), ResultType, - "sub.ptr.lhs.cast"); + llvm::Value *LHS = Builder.CreatePtrToInt(LvalueDst.emitRawPointer(*this), + ResultType, "sub.ptr.lhs.cast"); llvm::Value *BytesBetween = Builder.CreateSub(LHS, RHS, "ivar.offset"); - CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst, - BytesBetween); + CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, dst, BytesBetween); } else if (Dst.isGlobalObjCRef()) { CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst, Dst.isThreadLocalRef()); @@ -2789,12 +2767,9 @@ CodeGenFunction::EmitLoadOfReference(LValue RefLVal, llvm::LoadInst *Load = Builder.CreateLoad(RefLVal.getAddress(*this), RefLVal.isVolatile()); CGM.DecorateInstructionWithTBAA(Load, RefLVal.getTBAAInfo()); - - QualType PointeeType = RefLVal.getType()->getPointeeType(); - CharUnits Align = CGM.getNaturalTypeAlignment( - PointeeType, PointeeBaseInfo, PointeeTBAAInfo, - /* forPointeeType= */ true); - return Address(Load, ConvertTypeForMem(PointeeType), Align); + return makeNaturalAddressForPointer(Load, RefLVal.getType()->getPointeeType(), + CharUnits(), /*ForPointeeType=*/true, + PointeeBaseInfo, PointeeTBAAInfo); } LValue CodeGenFunction::EmitLoadOfReferenceLValue(LValue RefLVal) { @@ -2811,10 +2786,9 @@ Address CodeGenFunction::EmitLoadOfPointer(Address Ptr, LValueBaseInfo *BaseInfo, TBAAAccessInfo *TBAAInfo) { llvm::Value *Addr = Builder.CreateLoad(Ptr); - return Address(Addr, ConvertTypeForMem(PtrTy->getPointeeType()), - CGM.getNaturalTypeAlignment(PtrTy->getPointeeType(), BaseInfo, - TBAAInfo, - /*forPointeeType=*/true)); + return makeNaturalAddressForPointer(Addr, PtrTy->getPointeeType(), + CharUnits(), /*ForPointeeType=*/true, + BaseInfo, TBAAInfo); } LValue CodeGenFunction::EmitLoadOfPointerLValue(Address PtrAddr, @@ -3010,7 +2984,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { /* BaseInfo= */ nullptr, /* TBAAInfo= */ nullptr, /* forPointeeType= */ true); - Addr = Address(Val, ConvertTypeForMem(E->getType()), Alignment); + Addr = makeNaturalAddressForPointer(Val, T, Alignment); } return MakeAddrLValue(Addr, T, AlignmentSource::Decl); } @@ -3042,11 +3016,12 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { EmitCapturedFieldLValue(*this, CapturedStmtInfo->lookup(VD), CapturedStmtInfo->getContextValue()); Address LValueAddress = CapLVal.getAddress(*this); - CapLVal = MakeAddrLValue( - Address(LValueAddress.getPointer(), LValueAddress.getElementType(), - getContext().getDeclAlign(VD)), - CapLVal.getType(), LValueBaseInfo(AlignmentSource::Decl), - CapLVal.getTBAAInfo()); + CapLVal = MakeAddrLValue(Address(LValueAddress.emitRawPointer(*this), + LValueAddress.getElementType(), + getContext().getDeclAlign(VD)), + CapLVal.getType(), + LValueBaseInfo(AlignmentSource::Decl), + CapLVal.getTBAAInfo()); // Mark lvalue as nontemporal if the variable is marked as nontemporal // in simd context. if (getLangOpts().OpenMP && @@ -3102,7 +3077,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { // Handle threadlocal function locals. if (VD->getTLSKind() != VarDecl::TLS_None) addr = addr.withPointer( - Builder.CreateThreadLocalAddress(addr.getPointer()), NotKnownNonNull); + Builder.CreateThreadLocalAddress(addr.getBasePointer()), + NotKnownNonNull); // Check for OpenMP threadprivate variables. if (getLangOpts().OpenMP && !getLangOpts().OpenMPSimd && @@ -3370,7 +3346,7 @@ llvm::Value *CodeGenFunction::EmitCheckValue(llvm::Value *V) { // Pointers are passed directly, everything else is passed by address. if (!V->getType()->isPointerTy()) { - Address Ptr = CreateDefaultAlignTempAlloca(V->getType()); + RawAddress Ptr = CreateDefaultAlignTempAlloca(V->getType()); Builder.CreateStore(V, Ptr); V = Ptr.getPointer(); } @@ -3682,12 +3658,29 @@ void CodeGenFunction::EmitCfiSlowPathCheck( // symbol in LTO mode. void CodeGenFunction::EmitCfiCheckStub() { llvm::Module *M = &CGM.getModule(); - auto &Ctx = M->getContext(); + ASTContext &C = getContext(); + QualType QInt64Ty = C.getIntTypeForBitwidth(64, false); + + FunctionArgList FnArgs; + ImplicitParamDecl ArgCallsiteTypeId(C, QInt64Ty, ImplicitParamKind::Other); + ImplicitParamDecl ArgAddr(C, C.VoidPtrTy, ImplicitParamKind::Other); + ImplicitParamDecl ArgCFICheckFailData(C, C.VoidPtrTy, + ImplicitParamKind::Other); + FnArgs.push_back(&ArgCallsiteTypeId); + FnArgs.push_back(&ArgAddr); + FnArgs.push_back(&ArgCFICheckFailData); + const CGFunctionInfo &FI = + CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, FnArgs); + llvm::Function *F = llvm::Function::Create( - llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy, Int8PtrTy}, false), + llvm::FunctionType::get(VoidTy, {Int64Ty, VoidPtrTy, VoidPtrTy}, false), llvm::GlobalValue::WeakAnyLinkage, "__cfi_check", M); + CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F, /*IsThunk=*/false); + CGM.SetLLVMFunctionAttributesForDefinition(nullptr, F); F->setAlignment(llvm::Align(4096)); CGM.setDSOLocal(F); + + llvm::LLVMContext &Ctx = M->getContext(); llvm::BasicBlock *BB = llvm::BasicBlock::Create(Ctx, "entry", F); // CrossDSOCFI pass is not executed if there is no executable code. SmallVector<llvm::Value*> Args{F->getArg(2), F->getArg(1)}; @@ -3926,6 +3919,21 @@ static llvm::Value *emitArraySubscriptGEP(CodeGenFunction &CGF, } } +static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, + ArrayRef<llvm::Value *> indices, + llvm::Type *elementType, bool inbounds, + bool signedIndices, SourceLocation loc, + CharUnits align, + const llvm::Twine &name = "arrayidx") { + if (inbounds) { + return CGF.EmitCheckedInBoundsGEP(addr, indices, elementType, signedIndices, + CodeGenFunction::NotSubtraction, loc, + align, name); + } else { + return CGF.Builder.CreateGEP(addr, indices, elementType, align, name); + } +} + static CharUnits getArrayElementAlign(CharUnits arrayAlign, llvm::Value *idx, CharUnits eltSize) { @@ -3973,7 +3981,7 @@ static Address wrapWithBPFPreserveStaticOffset(CodeGenFunction &CGF, llvm::Function *Fn = CGF.CGM.getIntrinsic(llvm::Intrinsic::preserve_static_offset); - llvm::CallInst *Call = CGF.Builder.CreateCall(Fn, {Addr.getPointer()}); + llvm::CallInst *Call = CGF.Builder.CreateCall(Fn, {Addr.emitRawPointer(CGF)}); return Address(Call, Addr.getElementType(), Addr.getAlignment()); } @@ -4036,7 +4044,7 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, // We can use that to compute the best alignment of the element. CharUnits eltSize = CGF.getContext().getTypeSizeInChars(eltType); CharUnits eltAlign = - getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize); + getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize); if (hasBPFPreserveStaticOffset(Base)) addr = wrapWithBPFPreserveStaticOffset(CGF, addr); @@ -4045,19 +4053,19 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr, auto LastIndex = dyn_cast<llvm::ConstantInt>(indices.back()); if (!LastIndex || (!CGF.IsInPreservedAIRegion && !IsPreserveAIArrayBase(CGF, Base))) { - eltPtr = emitArraySubscriptGEP( - CGF, addr.getElementType(), addr.getPointer(), indices, inbounds, - signedIndices, loc, name); + addr = emitArraySubscriptGEP(CGF, addr, indices, + CGF.ConvertTypeForMem(eltType), inbounds, + signedIndices, loc, eltAlign, name); + return addr; } else { // Remember the original array subscript for bpf target unsigned idx = LastIndex->getZExtValue(); llvm::DIType *DbgInfo = nullptr; if (arrayType) DbgInfo = CGF.getDebugInfo()->getOrCreateStandaloneType(*arrayType, loc); - eltPtr = CGF.Builder.CreatePreserveArrayAccessIndex(addr.getElementType(), - addr.getPointer(), - indices.size() - 1, - idx, DbgInfo); + eltPtr = CGF.Builder.CreatePreserveArrayAccessIndex( + addr.getElementType(), addr.emitRawPointer(CGF), indices.size() - 1, + idx, DbgInfo); } return Address(eltPtr, CGF.ConvertTypeForMem(eltType), eltAlign); @@ -4226,8 +4234,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, CharUnits EltAlign = getArrayElementAlign(Addr.getAlignment(), Idx, InterfaceSize); llvm::Value *EltPtr = - emitArraySubscriptGEP(*this, Int8Ty, Addr.getPointer(), ScaledIdx, - false, SignedIndices, E->getExprLoc()); + emitArraySubscriptGEP(*this, Int8Ty, Addr.emitRawPointer(*this), + ScaledIdx, false, SignedIndices, E->getExprLoc()); Addr = Address(EltPtr, OrigBaseElemTy, EltAlign); } else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) { // If this is A[i] where A is an array, the frontend will have decayed the @@ -4259,7 +4267,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, if (const auto *ME = dyn_cast<MemberExpr>(Array); ME && ME->isFlexibleArrayMemberLike(getContext(), StrictFlexArraysLevel) && - ME->getMemberDecl()->hasAttr<CountedByAttr>()) { + ME->getMemberDecl()->getType()->isCountAttributedType()) { const FieldDecl *FAMDecl = dyn_cast<FieldDecl>(ME->getMemberDecl()); if (const FieldDecl *CountFD = FindCountedByField(FAMDecl)) { if (std::optional<int64_t> Diff = @@ -4273,7 +4281,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, llvm::Type *CountTy = ConvertType(CountFD->getType()); llvm::Value *Res = Builder.CreateInBoundsGEP( - Int8Ty, Addr.getPointer(), + Int8Ty, Addr.emitRawPointer(*this), Builder.getInt32(OffsetDiff.getQuantity()), ".counted_by.gep"); Res = Builder.CreateAlignedLoad(CountTy, Res, getIntAlign(), ".counted_by.load"); @@ -4519,9 +4527,9 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, BaseInfo = ArrayLV.getBaseInfo(); TBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, ResultExprTy); } else { - Address Base = emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, - TBAAInfo, BaseTy, ResultExprTy, - IsLowerBound); + Address Base = + emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, TBAAInfo, BaseTy, + ResultExprTy, IsLowerBound); EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy, !getLangOpts().isSignedOverflowDefined(), /*signedIndices=*/false, E->getExprLoc()); @@ -4608,7 +4616,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { SkippedChecks.set(SanitizerKind::Alignment, true); if (IsBaseCXXThis || isa<DeclRefExpr>(BaseExpr)) SkippedChecks.set(SanitizerKind::Null, true); - EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr.getPointer(), PtrTy, + EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr, PtrTy, /*Alignment=*/CharUnits::Zero(), SkippedChecks); BaseLV = MakeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo); } else @@ -4657,8 +4665,8 @@ LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field, LambdaLV = EmitLoadOfReferenceLValue(AddrOfExplicitObject, D->getType(), AlignmentSource::Decl); else - LambdaLV = MakeNaturalAlignAddrLValue(AddrOfExplicitObject.getPointer(), - D->getType().getNonReferenceType()); + LambdaLV = MakeAddrLValue(AddrOfExplicitObject, + D->getType().getNonReferenceType()); } else { QualType LambdaTagType = getContext().getTagDeclType(Field->getParent()); LambdaLV = MakeNaturalAlignAddrLValue(ThisValue, LambdaTagType); @@ -4848,7 +4856,8 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, // information provided by invariant.group. This is because accessing // fields may leak the real address of dynamic object, which could result // in miscompilation when leaked pointer would be compared. - auto *stripped = Builder.CreateStripInvariantGroup(addr.getPointer()); + auto *stripped = + Builder.CreateStripInvariantGroup(addr.emitRawPointer(*this)); addr = Address(stripped, addr.getElementType(), addr.getAlignment()); } } @@ -4867,10 +4876,11 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, // Remember the original union field index llvm::DIType *DbgInfo = getDebugInfo()->getOrCreateStandaloneType(base.getType(), rec->getLocation()); - addr = Address( - Builder.CreatePreserveUnionAccessIndex( - addr.getPointer(), getDebugInfoFIndex(rec, field->getFieldIndex()), DbgInfo), - addr.getElementType(), addr.getAlignment()); + addr = + Address(Builder.CreatePreserveUnionAccessIndex( + addr.emitRawPointer(*this), + getDebugInfoFIndex(rec, field->getFieldIndex()), DbgInfo), + addr.getElementType(), addr.getAlignment()); } if (FieldType->isReferenceType()) @@ -5107,11 +5117,9 @@ LValue CodeGenFunction::EmitConditionalOperatorLValue( if (Info.LHS && Info.RHS) { Address lhsAddr = Info.LHS->getAddress(*this); Address rhsAddr = Info.RHS->getAddress(*this); - llvm::PHINode *phi = Builder.CreatePHI(lhsAddr.getType(), 2, "cond-lvalue"); - phi->addIncoming(lhsAddr.getPointer(), Info.lhsBlock); - phi->addIncoming(rhsAddr.getPointer(), Info.rhsBlock); - Address result(phi, lhsAddr.getElementType(), - std::min(lhsAddr.getAlignment(), rhsAddr.getAlignment())); + Address result = mergeAddressesInConditionalExpr( + lhsAddr, rhsAddr, Info.lhsBlock, Info.rhsBlock, + Builder.GetInsertBlock(), expr->getType()); AlignmentSource alignSource = std::max(Info.LHS->getBaseInfo().getAlignmentSource(), Info.RHS->getBaseInfo().getAlignmentSource()); @@ -5181,6 +5189,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { case CK_IntegralToFixedPoint: case CK_MatrixCast: case CK_HLSLVectorTruncation: + case CK_HLSLArrayRValue: return EmitUnsupportedLValue(E, "unexpected cast lvalue"); case CK_Dependent: @@ -5198,7 +5207,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { LValue LV = EmitLValue(E->getSubExpr()); Address V = LV.getAddress(*this); const auto *DCE = cast<CXXDynamicCastExpr>(E); - return MakeNaturalAlignAddrLValue(EmitDynamicCast(V, DCE), E->getType()); + return MakeNaturalAlignRawAddrLValue(EmitDynamicCast(V, DCE), E->getType()); } case CK_ConstructorConversion: @@ -5263,8 +5272,8 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { // C++11 [expr.static.cast]p2: Behavior is undefined if a downcast is // performed and the object is not of the derived type. if (sanitizePerformTypeCheck()) - EmitTypeCheck(TCK_DowncastReference, E->getExprLoc(), - Derived.getPointer(), E->getType()); + EmitTypeCheck(TCK_DowncastReference, E->getExprLoc(), Derived, + E->getType()); if (SanOpts.has(SanitizerKind::CFIDerivedCast)) EmitVTablePtrCheckForCast(E->getType(), Derived, @@ -5620,7 +5629,7 @@ LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) { LValue CodeGenFunction::EmitCXXTypeidLValue(const CXXTypeidExpr *E) { - return MakeNaturalAlignAddrLValue(EmitCXXTypeidExpr(E), E->getType()); + return MakeNaturalAlignRawAddrLValue(EmitCXXTypeidExpr(E), E->getType()); } Address CodeGenFunction::EmitCXXUuidofExpr(const CXXUuidofExpr *E) { diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 5190b22bcc162254b09ef81bae7f7f3d7deb0502..1b9287ea239347d334c2c7d52e2cc092e281aeb5 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -294,10 +294,10 @@ void AggExprEmitter::withReturnValueSlot( // Otherwise, EmitCall will emit its own, notice that it's "unused", and end // its lifetime before we have the chance to emit a proper destructor call. bool UseTemp = Dest.isPotentiallyAliased() || Dest.requiresGCollection() || - (RequiresDestruction && !Dest.getAddress().isValid()); + (RequiresDestruction && Dest.isIgnored()); Address RetAddr = Address::invalid(); - Address RetAllocaAddr = Address::invalid(); + RawAddress RetAllocaAddr = RawAddress::invalid(); EHScopeStack::stable_iterator LifetimeEndBlock; llvm::Value *LifetimeSizePtr = nullptr; @@ -329,7 +329,8 @@ void AggExprEmitter::withReturnValueSlot( if (!UseTemp) return; - assert(Dest.isIgnored() || Dest.getPointer() != Src.getAggregatePointer()); + assert(Dest.isIgnored() || Dest.emitRawPointer(CGF) != + Src.getAggregatePointer(E->getType(), CGF)); EmitFinalDestCopy(E->getType(), Src); if (!RequiresDestruction && LifetimeStartInst) { @@ -448,7 +449,8 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { llvm::Value *Zero = llvm::ConstantInt::get(CGF.PtrDiffTy, 0); llvm::Value *IdxStart[] = { Zero, Zero }; llvm::Value *ArrayStart = Builder.CreateInBoundsGEP( - ArrayPtr.getElementType(), ArrayPtr.getPointer(), IdxStart, "arraystart"); + ArrayPtr.getElementType(), ArrayPtr.emitRawPointer(CGF), IdxStart, + "arraystart"); CGF.EmitStoreThroughLValue(RValue::get(ArrayStart), Start); ++Field; @@ -465,7 +467,8 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { // End pointer. llvm::Value *IdxEnd[] = { Zero, Size }; llvm::Value *ArrayEnd = Builder.CreateInBoundsGEP( - ArrayPtr.getElementType(), ArrayPtr.getPointer(), IdxEnd, "arrayend"); + ArrayPtr.getElementType(), ArrayPtr.emitRawPointer(CGF), IdxEnd, + "arrayend"); CGF.EmitStoreThroughLValue(RValue::get(ArrayEnd), EndOrLength); } else if (Ctx.hasSameType(Field->getType(), Ctx.getSizeType())) { // Length. @@ -516,9 +519,9 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, // down a level. llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); llvm::Value *indices[] = { zero, zero }; - llvm::Value *begin = Builder.CreateInBoundsGEP( - DestPtr.getElementType(), DestPtr.getPointer(), indices, - "arrayinit.begin"); + llvm::Value *begin = Builder.CreateInBoundsGEP(DestPtr.getElementType(), + DestPtr.emitRawPointer(CGF), + indices, "arrayinit.begin"); CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType); CharUnits elementAlign = @@ -880,6 +883,9 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { [[fallthrough]]; + case CK_HLSLArrayRValue: + Visit(E->getSubExpr()); + break; case CK_NoOp: case CK_UserDefinedConversion: @@ -1059,7 +1065,7 @@ void AggExprEmitter::VisitBinCmp(const BinaryOperator *E) { if (RV.isScalar()) return {RV.getScalarVal(), nullptr}; if (RV.isAggregate()) - return {RV.getAggregatePointer(), nullptr}; + return {RV.getAggregatePointer(E->getType(), CGF), nullptr}; assert(RV.isComplex()); return RV.getComplexVal(); }; @@ -1521,6 +1527,7 @@ static bool castPreservesZero(const CastExpr *CE) { case CK_LValueToRValue: case CK_LValueToRValueBitCast: case CK_UncheckedDerivedToBase: + case CK_HLSLArrayRValue: return false; } llvm_unreachable("Unhandled clang::CastKind enum"); @@ -1818,7 +1825,7 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr( // else, clean it up for -O0 builds and general tidiness. if (!pushedCleanup && LV.isSimple()) if (llvm::GetElementPtrInst *GEP = - dyn_cast<llvm::GetElementPtrInst>(LV.getPointer(CGF))) + dyn_cast<llvm::GetElementPtrInst>(LV.emitRawPointer(CGF))) if (GEP->use_empty()) GEP->eraseFromParent(); } @@ -1849,9 +1856,9 @@ void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E, // destPtr is an array*. Construct an elementType* by drilling down a level. llvm::Value *zero = llvm::ConstantInt::get(CGF.SizeTy, 0); llvm::Value *indices[] = {zero, zero}; - llvm::Value *begin = Builder.CreateInBoundsGEP( - destPtr.getElementType(), destPtr.getPointer(), indices, - "arrayinit.begin"); + llvm::Value *begin = Builder.CreateInBoundsGEP(destPtr.getElementType(), + destPtr.emitRawPointer(CGF), + indices, "arrayinit.begin"); // Prepare to special-case multidimensional array initialization: we avoid // emitting multiple destructor loops in that case. diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 2adbef6d55122c973a195260ad218354723ff035..a4fb673284ceca6bde6cc331279a4c4b42b6e39d 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -280,7 +280,8 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; Address ThisValue = EmitPointerWithAlignment(Base, &BaseInfo, &TBAAInfo); - This = MakeAddrLValue(ThisValue, Base->getType(), BaseInfo, TBAAInfo); + This = MakeAddrLValue(ThisValue, Base->getType()->getPointeeType(), + BaseInfo, TBAAInfo); } else { This = EmitLValue(Base); } @@ -353,10 +354,12 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( if (IsImplicitObjectCXXThis || isa<DeclRefExpr>(IOA)) SkippedChecks.set(SanitizerKind::Null, true); } - EmitTypeCheck(CodeGenFunction::TCK_MemberCall, CallLoc, - This.getPointer(*this), - C.getRecordType(CalleeDecl->getParent()), - /*Alignment=*/CharUnits::Zero(), SkippedChecks); + + if (sanitizePerformTypeCheck()) + EmitTypeCheck(CodeGenFunction::TCK_MemberCall, CallLoc, + This.emitRawPointer(*this), + C.getRecordType(CalleeDecl->getParent()), + /*Alignment=*/CharUnits::Zero(), SkippedChecks); // C++ [class.virtual]p12: // Explicit qualification with the scope operator (5.1) suppresses the @@ -455,7 +458,7 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, else This = EmitLValue(BaseExpr, KnownNonNull).getAddress(*this); - EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.getPointer(), + EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.emitRawPointer(*this), QualType(MPT->getClass(), 0)); // Get the member function pointer. @@ -1073,8 +1076,7 @@ void CodeGenFunction::EmitNewArrayInitializer( // Move past these elements. InitListElements = cast<ConstantArrayType>(Init->getType()->getAsArrayTypeUnsafe()) - ->getSize() - .getZExtValue(); + ->getZExtSize(); CurPtr = Builder.CreateConstInBoundsGEP( CurPtr, InitListElements, "string.init.end"); @@ -1110,9 +1112,10 @@ void CodeGenFunction::EmitNewArrayInitializer( // alloca. EndOfInit = CreateTempAlloca(BeginPtr.getType(), getPointerAlign(), "array.init.end"); - CleanupDominator = Builder.CreateStore(BeginPtr.getPointer(), EndOfInit); - pushIrregularPartialArrayCleanup(BeginPtr.getPointer(), EndOfInit, - ElementType, ElementAlign, + CleanupDominator = + Builder.CreateStore(BeginPtr.emitRawPointer(*this), EndOfInit); + pushIrregularPartialArrayCleanup(BeginPtr.emitRawPointer(*this), + EndOfInit, ElementType, ElementAlign, getDestroyer(DtorKind)); Cleanup = EHStack.stable_begin(); } @@ -1124,16 +1127,17 @@ void CodeGenFunction::EmitNewArrayInitializer( // element. TODO: some of these stores can be trivially // observed to be unnecessary. if (EndOfInit.isValid()) { - Builder.CreateStore(CurPtr.getPointer(), EndOfInit); + Builder.CreateStore(CurPtr.emitRawPointer(*this), EndOfInit); } // FIXME: If the last initializer is an incomplete initializer list for // an array, and we have an array filler, we can fold together the two // initialization loops. StoreAnyExprIntoOneUnit(*this, IE, IE->getType(), CurPtr, AggValueSlot::DoesNotOverlap); - CurPtr = Address(Builder.CreateInBoundsGEP( - CurPtr.getElementType(), CurPtr.getPointer(), - Builder.getSize(1), "array.exp.next"), + CurPtr = Address(Builder.CreateInBoundsGEP(CurPtr.getElementType(), + CurPtr.emitRawPointer(*this), + Builder.getSize(1), + "array.exp.next"), CurPtr.getElementType(), StartAlign.alignmentAtOffset((++i) * ElementSize)); } @@ -1187,7 +1191,7 @@ void CodeGenFunction::EmitNewArrayInitializer( // FIXME: Share this cleanup with the constructor call emission rather than // having it create a cleanup of its own. if (EndOfInit.isValid()) - Builder.CreateStore(CurPtr.getPointer(), EndOfInit); + Builder.CreateStore(CurPtr.emitRawPointer(*this), EndOfInit); // Emit a constructor call loop to initialize the remaining elements. if (InitListElements) @@ -1250,15 +1254,15 @@ void CodeGenFunction::EmitNewArrayInitializer( llvm::BasicBlock *ContBB = createBasicBlock("new.loop.end"); // Find the end of the array, hoisted out of the loop. - llvm::Value *EndPtr = - Builder.CreateInBoundsGEP(BeginPtr.getElementType(), BeginPtr.getPointer(), - NumElements, "array.end"); + llvm::Value *EndPtr = Builder.CreateInBoundsGEP( + BeginPtr.getElementType(), BeginPtr.emitRawPointer(*this), NumElements, + "array.end"); // If the number of elements isn't constant, we have to now check if there is // anything left to initialize. if (!ConstNum) { - llvm::Value *IsEmpty = - Builder.CreateICmpEQ(CurPtr.getPointer(), EndPtr, "array.isempty"); + llvm::Value *IsEmpty = Builder.CreateICmpEQ(CurPtr.emitRawPointer(*this), + EndPtr, "array.isempty"); Builder.CreateCondBr(IsEmpty, ContBB, LoopBB); } @@ -1268,19 +1272,20 @@ void CodeGenFunction::EmitNewArrayInitializer( // Set up the current-element phi. llvm::PHINode *CurPtrPhi = Builder.CreatePHI(CurPtr.getType(), 2, "array.cur"); - CurPtrPhi->addIncoming(CurPtr.getPointer(), EntryBB); + CurPtrPhi->addIncoming(CurPtr.emitRawPointer(*this), EntryBB); CurPtr = Address(CurPtrPhi, CurPtr.getElementType(), ElementAlign); // Store the new Cleanup position for irregular Cleanups. if (EndOfInit.isValid()) - Builder.CreateStore(CurPtr.getPointer(), EndOfInit); + Builder.CreateStore(CurPtr.emitRawPointer(*this), EndOfInit); // Enter a partial-destruction Cleanup if necessary. if (!CleanupDominator && needsEHCleanup(DtorKind)) { - pushRegularPartialArrayCleanup(BeginPtr.getPointer(), CurPtr.getPointer(), - ElementType, ElementAlign, - getDestroyer(DtorKind)); + llvm::Value *BeginPtrRaw = BeginPtr.emitRawPointer(*this); + llvm::Value *CurPtrRaw = CurPtr.emitRawPointer(*this); + pushRegularPartialArrayCleanup(BeginPtrRaw, CurPtrRaw, ElementType, + ElementAlign, getDestroyer(DtorKind)); Cleanup = EHStack.stable_begin(); CleanupDominator = Builder.CreateUnreachable(); } @@ -1296,9 +1301,8 @@ void CodeGenFunction::EmitNewArrayInitializer( } // Advance to the next element by adjusting the pointer type as necessary. - llvm::Value *NextPtr = - Builder.CreateConstInBoundsGEP1_32(ElementTy, CurPtr.getPointer(), 1, - "array.next"); + llvm::Value *NextPtr = Builder.CreateConstInBoundsGEP1_32( + ElementTy, CurPtr.emitRawPointer(*this), 1, "array.next"); // Check whether we've gotten to the end of the array and, if so, // exit the loop. @@ -1524,14 +1528,9 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, typedef CallDeleteDuringNew<DirectCleanupTraits> DirectCleanup; - DirectCleanup *Cleanup = CGF.EHStack - .pushCleanupWithExtra<DirectCleanup>(EHCleanup, - E->getNumPlacementArgs(), - E->getOperatorDelete(), - NewPtr.getPointer(), - AllocSize, - E->passAlignment(), - AllocAlign); + DirectCleanup *Cleanup = CGF.EHStack.pushCleanupWithExtra<DirectCleanup>( + EHCleanup, E->getNumPlacementArgs(), E->getOperatorDelete(), + NewPtr.emitRawPointer(CGF), AllocSize, E->passAlignment(), AllocAlign); for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) { auto &Arg = NewArgs[I + NumNonPlacementArgs]; Cleanup->setPlacementArg(I, Arg.getRValue(CGF), Arg.Ty); @@ -1542,7 +1541,7 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, // Otherwise, we need to save all this stuff. DominatingValue<RValue>::saved_type SavedNewPtr = - DominatingValue<RValue>::save(CGF, RValue::get(NewPtr.getPointer())); + DominatingValue<RValue>::save(CGF, RValue::get(NewPtr, CGF)); DominatingValue<RValue>::saved_type SavedAllocSize = DominatingValue<RValue>::save(CGF, RValue::get(AllocSize)); @@ -1591,8 +1590,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { isa<StringLiteral>(IgnoreParen) || isa<ObjCEncodeExpr>(IgnoreParen)) { minElements = cast<ConstantArrayType>(Init->getType()->getAsArrayTypeUnsafe()) - ->getSize() - .getZExtValue(); + ->getZExtSize(); } else if (ILE || CPLIE) { minElements = ILE ? ILE->getNumInits() : CPLIE->getInitExprs().size(); } @@ -1620,14 +1618,14 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { // In these cases, discard the computed alignment and use the // formal alignment of the allocated type. if (BaseInfo.getAlignmentSource() != AlignmentSource::Decl) - allocation = allocation.withAlignment(allocAlign); + allocation.setAlignment(allocAlign); // Set up allocatorArgs for the call to operator delete if it's not // the reserved global operator. if (E->getOperatorDelete() && !E->getOperatorDelete()->isReservedGlobalPlacementOperator()) { allocatorArgs.add(RValue::get(allocSize), getContext().getSizeType()); - allocatorArgs.add(RValue::get(allocation.getPointer()), arg->getType()); + allocatorArgs.add(RValue::get(allocation, *this), arg->getType()); } } else { @@ -1715,8 +1713,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { llvm::BasicBlock *notNullBB = createBasicBlock("new.notnull"); contBB = createBasicBlock("new.cont"); - llvm::Value *isNull = - Builder.CreateIsNull(allocation.getPointer(), "new.isnull"); + llvm::Value *isNull = Builder.CreateIsNull(allocation, "new.isnull"); Builder.CreateCondBr(isNull, contBB, notNullBB); EmitBlock(notNullBB); } @@ -1762,12 +1759,12 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { SkippedChecks.set(SanitizerKind::Null, nullCheck); EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, E->getAllocatedTypeSourceInfo()->getTypeLoc().getBeginLoc(), - result.getPointer(), allocType, result.getAlignment(), - SkippedChecks, numElements); + result, allocType, result.getAlignment(), SkippedChecks, + numElements); EmitNewInitializer(*this, E, allocType, elementTy, result, numElements, allocSizeWithoutCookie); - llvm::Value *resultPtr = result.getPointer(); + llvm::Value *resultPtr = result.emitRawPointer(*this); if (E->isArray()) { // NewPtr is a pointer to the base element type. If we're // allocating an array of arrays, we'll need to cast back to the @@ -1911,7 +1908,8 @@ static void EmitDestroyingObjectDelete(CodeGenFunction &CGF, CGF.CGM.getCXXABI().emitVirtualObjectDelete(CGF, DE, Ptr, ElementType, Dtor); else - CGF.EmitDeleteCall(DE->getOperatorDelete(), Ptr.getPointer(), ElementType); + CGF.EmitDeleteCall(DE->getOperatorDelete(), Ptr.emitRawPointer(CGF), + ElementType); } /// Emit the code for deleting a single object. @@ -1927,8 +1925,7 @@ static bool EmitObjectDelete(CodeGenFunction &CGF, // dynamic type, the static type shall be a base class of the dynamic type // of the object to be deleted and the static type shall have a virtual // destructor or the behavior is undefined. - CGF.EmitTypeCheck(CodeGenFunction::TCK_MemberCall, - DE->getExprLoc(), Ptr.getPointer(), + CGF.EmitTypeCheck(CodeGenFunction::TCK_MemberCall, DE->getExprLoc(), Ptr, ElementType); const FunctionDecl *OperatorDelete = DE->getOperatorDelete(); @@ -1977,9 +1974,8 @@ static bool EmitObjectDelete(CodeGenFunction &CGF, // Make sure that we call delete even if the dtor throws. // This doesn't have to a conditional cleanup because we're going // to pop it off in a second. - CGF.EHStack.pushCleanup<CallObjectDelete>(NormalAndEHCleanup, - Ptr.getPointer(), - OperatorDelete, ElementType); + CGF.EHStack.pushCleanup<CallObjectDelete>( + NormalAndEHCleanup, Ptr.emitRawPointer(CGF), OperatorDelete, ElementType); if (Dtor) CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, @@ -2066,7 +2062,7 @@ static void EmitArrayDelete(CodeGenFunction &CGF, CharUnits elementAlign = deletedPtr.getAlignment().alignmentOfArrayElement(elementSize); - llvm::Value *arrayBegin = deletedPtr.getPointer(); + llvm::Value *arrayBegin = deletedPtr.emitRawPointer(CGF); llvm::Value *arrayEnd = CGF.Builder.CreateInBoundsGEP( deletedPtr.getElementType(), arrayBegin, numElements, "delete.end"); @@ -2097,7 +2093,7 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull"); llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end"); - llvm::Value *IsNull = Builder.CreateIsNull(Ptr.getPointer(), "isnull"); + llvm::Value *IsNull = Builder.CreateIsNull(Ptr, "isnull"); Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull); EmitBlock(DeleteNotNull); @@ -2132,10 +2128,8 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { GEP.push_back(Zero); } - Ptr = Address(Builder.CreateInBoundsGEP(Ptr.getElementType(), - Ptr.getPointer(), GEP, "del.first"), - ConvertTypeForMem(DeleteTy), Ptr.getAlignment(), - Ptr.isKnownNonNull()); + Ptr = Builder.CreateInBoundsGEP(Ptr, GEP, ConvertTypeForMem(DeleteTy), + Ptr.getAlignment(), "del.first"); } assert(ConvertTypeForMem(DeleteTy) == Ptr.getElementType()); @@ -2193,7 +2187,7 @@ static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E, // destruction and the static type of the operand is neither the constructor // or destructor’s class nor one of its bases, the behavior is undefined. CGF.EmitTypeCheck(CodeGenFunction::TCK_DynamicOperation, E->getExprLoc(), - ThisPtr.getPointer(), SrcRecordTy); + ThisPtr, SrcRecordTy); // C++ [expr.typeid]p2: // If the glvalue expression is obtained by applying the unary * operator to @@ -2209,7 +2203,7 @@ static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E, CGF.createBasicBlock("typeid.bad_typeid"); llvm::BasicBlock *EndBlock = CGF.createBasicBlock("typeid.end"); - llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr.getPointer()); + llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr); CGF.Builder.CreateCondBr(IsNull, BadTypeidBlock, EndBlock); CGF.EmitBlock(BadTypeidBlock); @@ -2295,8 +2289,7 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr, // construction or destruction and the static type of the operand is not a // pointer to or object of the constructor or destructor’s own class or one // of its bases, the dynamic_cast results in undefined behavior. - EmitTypeCheck(TCK_DynamicOperation, DCE->getExprLoc(), ThisAddr.getPointer(), - SrcRecordTy); + EmitTypeCheck(TCK_DynamicOperation, DCE->getExprLoc(), ThisAddr, SrcRecordTy); if (DCE->isAlwaysNull()) { if (llvm::Value *T = EmitDynamicCastToNull(*this, DestTy)) { @@ -2331,7 +2324,7 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr, CastNull = createBasicBlock("dynamic_cast.null"); CastNotNull = createBasicBlock("dynamic_cast.notnull"); - llvm::Value *IsNull = Builder.CreateIsNull(ThisAddr.getPointer()); + llvm::Value *IsNull = Builder.CreateIsNull(ThisAddr); Builder.CreateCondBr(IsNull, CastNull, CastNotNull); EmitBlock(CastNotNull); } diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index 0266ba934da62c416fcbf61e81570126c7c2d63e..a793b214645cb3d8f30635cc383ad73f07c8371a 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -51,11 +51,12 @@ class ComplexExprEmitter CGBuilderTy &Builder; bool IgnoreReal; bool IgnoreImag; -public: - ComplexExprEmitter(CodeGenFunction &cgf, bool ir=false, bool ii=false) - : CGF(cgf), Builder(CGF.Builder), IgnoreReal(ir), IgnoreImag(ii) { - } + bool FPHasBeenPromoted; +public: + ComplexExprEmitter(CodeGenFunction &cgf, bool ir = false, bool ii = false) + : CGF(cgf), Builder(CGF.Builder), IgnoreReal(ir), IgnoreImag(ii), + FPHasBeenPromoted(false) {} //===--------------------------------------------------------------------===// // Utilities @@ -287,9 +288,54 @@ public: ComplexPairTy EmitComplexBinOpLibCall(StringRef LibCallName, const BinOpInfo &Op); - QualType getPromotionType(QualType Ty) { + QualType GetHigherPrecisionFPType(QualType ElementType) { + const auto *CurrentBT = cast<BuiltinType>(ElementType); + switch (CurrentBT->getKind()) { + case BuiltinType::Kind::Float16: + return CGF.getContext().FloatTy; + case BuiltinType::Kind::Float: + case BuiltinType::Kind::BFloat16: + return CGF.getContext().DoubleTy; + case BuiltinType::Kind::Double: + return CGF.getContext().LongDoubleTy; + default: + return ElementType; + } + } + + QualType HigherPrecisionTypeForComplexArithmetic(QualType ElementType, + bool IsDivOpCode) { + QualType HigherElementType = GetHigherPrecisionFPType(ElementType); + const llvm::fltSemantics &ElementTypeSemantics = + CGF.getContext().getFloatTypeSemantics(ElementType); + const llvm::fltSemantics &HigherElementTypeSemantics = + CGF.getContext().getFloatTypeSemantics(HigherElementType); + // Check that the promoted type can handle the intermediate values without + // overflowing. This can be interpreted as: + // (SmallerType.LargestFiniteVal * SmallerType.LargestFiniteVal) * 2 <= + // LargerType.LargestFiniteVal. + // In terms of exponent it gives this formula: + // (SmallerType.LargestFiniteVal * SmallerType.LargestFiniteVal + // doubles the exponent of SmallerType.LargestFiniteVal) + if (llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 <= + llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) { + return CGF.getContext().getComplexType(HigherElementType); + } else { + FPHasBeenPromoted = true; + DiagnosticsEngine &Diags = CGF.CGM.getDiags(); + Diags.Report(diag::warn_next_larger_fp_type_same_size_than_fp); + return CGF.getContext().getComplexType(ElementType); + } + } + + QualType getPromotionType(QualType Ty, bool IsDivOpCode = false) { if (auto *CT = Ty->getAs<ComplexType>()) { QualType ElementType = CT->getElementType(); + if (IsDivOpCode && ElementType->isFloatingType() && + CGF.getLangOpts().getComplexRange() == + LangOptions::ComplexRangeKind::CX_Promoted) + return HigherPrecisionTypeForComplexArithmetic(ElementType, + IsDivOpCode); if (ElementType.UseExcessPrecision(CGF.getContext())) return CGF.getContext().getComplexType(CGF.getContext().FloatTy); } @@ -300,11 +346,12 @@ public: #define HANDLEBINOP(OP) \ ComplexPairTy VisitBin##OP(const BinaryOperator *E) { \ - QualType promotionTy = getPromotionType(E->getType()); \ + QualType promotionTy = getPromotionType( \ + E->getType(), \ + (E->getOpcode() == BinaryOperatorKind::BO_Div) ? true : false); \ ComplexPairTy result = EmitBin##OP(EmitBinOps(E, promotionTy)); \ if (!promotionTy.isNull()) \ - result = \ - CGF.EmitUnPromotedValue(result, E->getType()); \ + result = CGF.EmitUnPromotedValue(result, E->getType()); \ return result; \ } @@ -569,6 +616,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op, case CK_IntegralToFixedPoint: case CK_MatrixCast: case CK_HLSLVectorTruncation: + case CK_HLSLArrayRValue: llvm_unreachable("invalid cast kind for complex value"); case CK_FloatingRealToComplex: @@ -794,8 +842,9 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) { ResR = Builder.CreateFSub(AC, BD, "mul_r"); ResI = Builder.CreateFAdd(AD, BC, "mul_i"); - if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Limited || - Op.FPFeatures.getComplexRange() == LangOptions::CX_Fortran) + if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Basic || + Op.FPFeatures.getComplexRange() == LangOptions::CX_Improved || + Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted) return ComplexPairTy(ResR, ResI); // Emit the test for the real part becoming NaN and create a branch to @@ -986,14 +1035,16 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) { llvm::Value *OrigLHSi = LHSi; if (!LHSi) LHSi = llvm::Constant::getNullValue(RHSi->getType()); - if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Fortran) + if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Improved || + (Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted && + FPHasBeenPromoted)) return EmitRangeReductionDiv(LHSr, LHSi, RHSr, RHSi); - else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Limited) + else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Basic || + Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted) return EmitAlgebraicDiv(LHSr, LHSi, RHSr, RHSi); - else if (!CGF.getLangOpts().FastMath || - // '-ffast-math' is used in the command line but followed by an - // '-fno-cx-limited-range'. - Op.FPFeatures.getComplexRange() == LangOptions::CX_Full) { + // '-ffast-math' is used in the command line but followed by an + // '-fno-cx-limited-range' or '-fcomplex-arithmetic=full'. + else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Full) { LHSi = OrigLHSi; // If we have a complex operand on the RHS and FastMath is not allowed, we // delegate to a libcall to handle all of the complexities and minimize diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 75286dceb13a7b2bcd5c90bbdae95a227ea36078..9f1b06eebf9ed089c4dc1d2cbce75a203ff951f9 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -656,7 +656,7 @@ static bool EmitDesignatedInitUpdater(ConstantEmitter &Emitter, } unsigned NumElementsToUpdate = - FillC ? CAT->getSize().getZExtValue() : Updater->getNumInits(); + FillC ? CAT->getZExtSize() : Updater->getNumInits(); for (unsigned I = 0; I != NumElementsToUpdate; ++I, Offset += ElemSize) { Expr *Init = nullptr; if (I < Updater->getNumInits()) @@ -800,8 +800,8 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD, // Add a vtable pointer, if we need one and it hasn't already been added. if (Layout.hasOwnVFPtr()) { llvm::Constant *VTableAddressPoint = - CGM.getCXXABI().getVTableAddressPointForConstExpr( - BaseSubobject(CD, Offset), VTableClass); + CGM.getCXXABI().getVTableAddressPoint(BaseSubobject(CD, Offset), + VTableClass); if (!AppendBytes(Offset, VTableAddressPoint)) return false; } @@ -1226,6 +1226,7 @@ public: case CK_ZeroToOCLOpaqueType: case CK_MatrixCast: case CK_HLSLVectorTruncation: + case CK_HLSLArrayRValue: return nullptr; } llvm_unreachable("Invalid CastKind"); @@ -1249,7 +1250,7 @@ public: auto *CAT = CGM.getContext().getAsConstantArrayType(ILE->getType()); assert(CAT && "can't emit array init for non-constant-bound array"); unsigned NumInitElements = ILE->getNumInits(); - unsigned NumElements = CAT->getSize().getZExtValue(); + unsigned NumElements = CAT->getZExtSize(); // Initialising an array requires us to automatically // initialise any elements that have not been initialised explicitly @@ -1374,7 +1375,7 @@ public: // Resize the string to the right size, adding zeros at the end, or // truncating as needed. - Str.resize(CAT->getSize().getZExtValue(), '\0'); + Str.resize(CAT->getZExtSize(), '\0'); return llvm::ConstantDataArray::getString(VMContext, Str, false); } @@ -2382,7 +2383,7 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) { llvm::Constant *Element = ConstantEmitter::emitNullForMemory(*this, ElementTy); - unsigned NumElements = CAT->getSize().getZExtValue(); + unsigned NumElements = CAT->getZExtSize(); SmallVector<llvm::Constant *, 8> Array(NumElements, Element); return llvm::ConstantArray::get(ATy, Array); } diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 8536570087ad0fe96016f169b6dfbbe031c3035d..397b4977acc3e9d536c000c12955a55f51262156 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2250,7 +2250,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { // performed and the object is not of the derived type. if (CGF.sanitizePerformTypeCheck()) CGF.EmitTypeCheck(CodeGenFunction::TCK_DowncastPointer, CE->getExprLoc(), - Derived.getPointer(), DestTy->getPointeeType()); + Derived, DestTy->getPointeeType()); if (CGF.SanOpts.has(SanitizerKind::CFIDerivedCast)) CGF.EmitVTablePtrCheckForCast(DestTy->getPointeeType(), Derived, @@ -2258,13 +2258,14 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { CodeGenFunction::CFITCK_DerivedCast, CE->getBeginLoc()); - return Derived.getPointer(); + return CGF.getAsNaturalPointerTo(Derived, CE->getType()->getPointeeType()); } case CK_UncheckedDerivedToBase: case CK_DerivedToBase: { // The EmitPointerWithAlignment path does this fine; just discard // the alignment. - return CGF.EmitPointerWithAlignment(CE).getPointer(); + return CGF.getAsNaturalPointerTo(CGF.EmitPointerWithAlignment(CE), + CE->getType()->getPointeeType()); } case CK_Dynamic: { @@ -2274,7 +2275,8 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { } case CK_ArrayToPointerDecay: - return CGF.EmitArrayToPointerDecay(E).getPointer(); + return CGF.getAsNaturalPointerTo(CGF.EmitArrayToPointerDecay(E), + CE->getType()->getPointeeType()); case CK_FunctionToPointerDecay: return EmitLValue(E).getPointer(CGF); @@ -2327,6 +2329,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { case CK_FloatingComplexToIntegralComplex: case CK_ConstructorConversion: case CK_ToUnion: + case CK_HLSLArrayRValue: llvm_unreachable("scalar cast to non-scalar value"); case CK_LValueToRValue: @@ -5588,3 +5591,16 @@ CodeGenFunction::EmitCheckedInBoundsGEP(llvm::Type *ElemTy, Value *Ptr, return GEPVal; } + +Address CodeGenFunction::EmitCheckedInBoundsGEP( + Address Addr, ArrayRef<Value *> IdxList, llvm::Type *elementType, + bool SignedIndices, bool IsSubtraction, SourceLocation Loc, CharUnits Align, + const Twine &Name) { + if (!SanOpts.has(SanitizerKind::PointerOverflow)) + return Builder.CreateInBoundsGEP(Addr, IdxList, elementType, Align, Name); + + return RawAddress( + EmitCheckedInBoundsGEP(Addr.getElementType(), Addr.emitRawPointer(*this), + IdxList, SignedIndices, IsSubtraction, Loc, Name), + elementType, Align); +} diff --git a/clang/lib/CodeGen/CGLoopInfo.h b/clang/lib/CodeGen/CGLoopInfo.h index a1c8c7e5307fd9c01b554a1e9cf98a40bd70e4af..0fe33b289130635586765a0714902eaf26012ce4 100644 --- a/clang/lib/CodeGen/CGLoopInfo.h +++ b/clang/lib/CodeGen/CGLoopInfo.h @@ -110,6 +110,10 @@ public: /// been processed. void finish(); + /// Returns the first outer loop containing this loop if any, nullptr + /// otherwise. + const LoopInfo *getParent() const { return Parent; } + private: /// Loop ID metadata. llvm::TempMDTuple TempLoopID; @@ -291,12 +295,13 @@ public: /// Set no progress for the next loop pushed. void setMustProgress(bool P) { StagedAttrs.MustProgress = P; } -private: /// Returns true if there is LoopInfo on the stack. bool hasInfo() const { return !Active.empty(); } /// Return the LoopInfo for the current loop. HasInfo should be called /// first to ensure LoopInfo is present. const LoopInfo &getInfo() const { return *Active.back(); } + +private: /// The set of attributes that will be applied to the next pushed loop. LoopAttributes StagedAttrs; /// Stack of active loops. diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/clang/lib/CodeGen/CGNonTrivialStruct.cpp index 75c1d7fbea840688ebe63d5939a08a09cdfd1243..8fade0fac21e9379df8c06aec1c301fdbaff6e85 100644 --- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp +++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp @@ -366,7 +366,7 @@ template <class Derived> struct GenFuncBase { llvm::Value *SizeInBytes = CGF.Builder.CreateNUWMul(BaseEltSizeVal, NumElts); llvm::Value *DstArrayEnd = CGF.Builder.CreateInBoundsGEP( - CGF.Int8Ty, DstAddr.getPointer(), SizeInBytes); + CGF.Int8Ty, DstAddr.emitRawPointer(CGF), SizeInBytes); llvm::BasicBlock *PreheaderBB = CGF.Builder.GetInsertBlock(); // Create the header block and insert the phi instructions. @@ -376,7 +376,7 @@ template <class Derived> struct GenFuncBase { for (unsigned I = 0; I < N; ++I) { PHIs[I] = CGF.Builder.CreatePHI(CGF.CGM.Int8PtrPtrTy, 2, "addr.cur"); - PHIs[I]->addIncoming(StartAddrs[I].getPointer(), PreheaderBB); + PHIs[I]->addIncoming(StartAddrs[I].emitRawPointer(CGF), PreheaderBB); } // Create the exit and loop body blocks. @@ -410,7 +410,7 @@ template <class Derived> struct GenFuncBase { // Instrs to update the destination and source addresses. // Update phi instructions. NewAddrs[I] = getAddrWithOffset(NewAddrs[I], EltSize); - PHIs[I]->addIncoming(NewAddrs[I].getPointer(), LoopBB); + PHIs[I]->addIncoming(NewAddrs[I].emitRawPointer(CGF), LoopBB); } // Insert an unconditional branch to the header block. @@ -488,7 +488,7 @@ template <class Derived> struct GenFuncBase { for (unsigned I = 0; I < N; ++I) { Alignments[I] = Addrs[I].getAlignment(); - Ptrs[I] = Addrs[I].getPointer(); + Ptrs[I] = Addrs[I].emitRawPointer(CallerCGF); } if (llvm::Function *F = diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index f3a948cf13f9c9098f8497a28aa1ee9102f59939..c7f497a7c8451be6918c726ebdb3423a600170db 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -94,8 +94,8 @@ CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) { // and cast value to correct type Address Temporary = CreateMemTemp(SubExpr->getType()); EmitAnyExprToMem(SubExpr, Temporary, Qualifiers(), /*isInit*/ true); - llvm::Value *BitCast = - Builder.CreateBitCast(Temporary.getPointer(), ConvertType(ArgQT)); + llvm::Value *BitCast = Builder.CreateBitCast( + Temporary.emitRawPointer(*this), ConvertType(ArgQT)); Args.add(RValue::get(BitCast), ArgQT); // Create char array to store type encoding @@ -204,11 +204,11 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E, ObjCMethodDecl::param_const_iterator PI = MethodWithObjects->param_begin(); const ParmVarDecl *argDecl = *PI++; QualType ArgQT = argDecl->getType().getUnqualifiedType(); - Args.add(RValue::get(Objects.getPointer()), ArgQT); + Args.add(RValue::get(Objects, *this), ArgQT); if (DLE) { argDecl = *PI++; ArgQT = argDecl->getType().getUnqualifiedType(); - Args.add(RValue::get(Keys.getPointer()), ArgQT); + Args.add(RValue::get(Keys, *this), ArgQT); } argDecl = *PI; ArgQT = argDecl->getType().getUnqualifiedType(); @@ -827,7 +827,7 @@ static void emitStructGetterCall(CodeGenFunction &CGF, ObjCIvarDecl *ivar, // sizeof (Type of Ivar), isAtomic, false); CallArgList args; - llvm::Value *dest = CGF.ReturnValue.getPointer(); + llvm::Value *dest = CGF.ReturnValue.emitRawPointer(CGF); args.add(RValue::get(dest), Context.VoidPtrTy); args.add(RValue::get(src), Context.VoidPtrTy); @@ -1147,8 +1147,8 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, callCStructCopyConstructor(Dst, Src); } else { ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); - emitCPPObjectAtomicGetterCall(*this, ReturnValue.getPointer(), ivar, - AtomicHelperFn); + emitCPPObjectAtomicGetterCall(*this, ReturnValue.emitRawPointer(*this), + ivar, AtomicHelperFn); } return; } @@ -1163,7 +1163,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, } else { ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); - emitCPPObjectAtomicGetterCall(*this, ReturnValue.getPointer(), + emitCPPObjectAtomicGetterCall(*this, ReturnValue.emitRawPointer(*this), ivar, AtomicHelperFn); } return; @@ -1287,7 +1287,7 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl, case TEK_Scalar: { llvm::Value *value; if (propType->isReferenceType()) { - value = LV.getAddress(*this).getPointer(); + value = LV.getAddress(*this).emitRawPointer(*this); } else { // We want to load and autoreleaseReturnValue ARC __weak ivars. if (LV.getQuals().getObjCLifetime() == Qualifiers::OCL_Weak) { @@ -1821,16 +1821,14 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ CallArgList Args; // The first argument is a temporary of the enumeration-state type. - Args.add(RValue::get(StatePtr.getPointer()), - getContext().getPointerType(StateTy)); + Args.add(RValue::get(StatePtr, *this), getContext().getPointerType(StateTy)); // The second argument is a temporary array with space for NumItems // pointers. We'll actually be loading elements from the array // pointer written into the control state; this buffer is so that // collections that *aren't* backed by arrays can still queue up // batches of elements. - Args.add(RValue::get(ItemsPtr.getPointer()), - getContext().getPointerType(ItemsTy)); + Args.add(RValue::get(ItemsPtr, *this), getContext().getPointerType(ItemsTy)); // The third argument is the capacity of that temporary array. llvm::Type *NSUIntegerTy = ConvertType(getContext().getNSUIntegerType()); @@ -2198,7 +2196,7 @@ static llvm::Value *emitARCLoadOperation(CodeGenFunction &CGF, Address addr, if (!fn) fn = getARCIntrinsic(IntID, CGF.CGM); - return CGF.EmitNounwindRuntimeCall(fn, addr.getPointer()); + return CGF.EmitNounwindRuntimeCall(fn, addr.emitRawPointer(CGF)); } /// Perform an operation having the following signature: @@ -2216,9 +2214,8 @@ static llvm::Value *emitARCStoreOperation(CodeGenFunction &CGF, Address addr, llvm::Type *origType = value->getType(); llvm::Value *args[] = { - CGF.Builder.CreateBitCast(addr.getPointer(), CGF.Int8PtrPtrTy), - CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy) - }; + CGF.Builder.CreateBitCast(addr.emitRawPointer(CGF), CGF.Int8PtrPtrTy), + CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy)}; llvm::CallInst *result = CGF.EmitNounwindRuntimeCall(fn, args); if (ignored) return nullptr; @@ -2237,9 +2234,8 @@ static void emitARCCopyOperation(CodeGenFunction &CGF, Address dst, Address src, fn = getARCIntrinsic(IntID, CGF.CGM); llvm::Value *args[] = { - CGF.Builder.CreateBitCast(dst.getPointer(), CGF.Int8PtrPtrTy), - CGF.Builder.CreateBitCast(src.getPointer(), CGF.Int8PtrPtrTy) - }; + CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), CGF.Int8PtrPtrTy), + CGF.Builder.CreateBitCast(src.emitRawPointer(CGF), CGF.Int8PtrPtrTy)}; CGF.EmitNounwindRuntimeCall(fn, args); } @@ -2490,9 +2486,8 @@ llvm::Value *CodeGenFunction::EmitARCStoreStrongCall(Address addr, fn = getARCIntrinsic(llvm::Intrinsic::objc_storeStrong, CGM); llvm::Value *args[] = { - Builder.CreateBitCast(addr.getPointer(), Int8PtrPtrTy), - Builder.CreateBitCast(value, Int8PtrTy) - }; + Builder.CreateBitCast(addr.emitRawPointer(*this), Int8PtrPtrTy), + Builder.CreateBitCast(value, Int8PtrTy)}; EmitNounwindRuntimeCall(fn, args); if (ignored) return nullptr; @@ -2643,7 +2638,7 @@ void CodeGenFunction::EmitARCDestroyWeak(Address addr) { if (!fn) fn = getARCIntrinsic(llvm::Intrinsic::objc_destroyWeak, CGM); - EmitNounwindRuntimeCall(fn, addr.getPointer()); + EmitNounwindRuntimeCall(fn, addr.emitRawPointer(*this)); } /// void \@objc_moveWeak(i8** %dest, i8** %src) diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index a36b0cdddaf0afd293592aac7fe7124ab8613db2..4e7f777ba1d9160fd872c7a3466fcf2a438f12e2 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -706,7 +706,8 @@ protected: llvm::Value *cmd, MessageSendInfo &MSI) override { CGBuilderTy &Builder = CGF.Builder; llvm::Value *lookupArgs[] = { - EnforceType(Builder, ObjCSuper.getPointer(), PtrToObjCSuperTy), cmd}; + EnforceType(Builder, ObjCSuper.emitRawPointer(CGF), PtrToObjCSuperTy), + cmd}; return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs); } @@ -761,8 +762,8 @@ class CGObjCGNUstep : public CGObjCGNU { llvm::FunctionCallee LookupFn = SlotLookupFn; // Store the receiver on the stack so that we can reload it later - Address ReceiverPtr = - CGF.CreateTempAlloca(Receiver->getType(), CGF.getPointerAlign()); + RawAddress ReceiverPtr = + CGF.CreateTempAlloca(Receiver->getType(), CGF.getPointerAlign()); Builder.CreateStore(Receiver, ReceiverPtr); llvm::Value *self; @@ -778,9 +779,9 @@ class CGObjCGNUstep : public CGObjCGNU { LookupFn2->addParamAttr(0, llvm::Attribute::NoCapture); llvm::Value *args[] = { - EnforceType(Builder, ReceiverPtr.getPointer(), PtrToIdTy), - EnforceType(Builder, cmd, SelectorTy), - EnforceType(Builder, self, IdTy) }; + EnforceType(Builder, ReceiverPtr.getPointer(), PtrToIdTy), + EnforceType(Builder, cmd, SelectorTy), + EnforceType(Builder, self, IdTy)}; llvm::CallBase *slot = CGF.EmitRuntimeCallOrInvoke(LookupFn, args); slot->setOnlyReadsMemory(); slot->setMetadata(msgSendMDKind, node); @@ -800,7 +801,7 @@ class CGObjCGNUstep : public CGObjCGNU { llvm::Value *cmd, MessageSendInfo &MSI) override { CGBuilderTy &Builder = CGF.Builder; - llvm::Value *lookupArgs[] = {ObjCSuper.getPointer(), cmd}; + llvm::Value *lookupArgs[] = {ObjCSuper.emitRawPointer(CGF), cmd}; llvm::CallInst *slot = CGF.EmitNounwindRuntimeCall(SlotLookupSuperFn, lookupArgs); @@ -1221,10 +1222,10 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { llvm::Value *cmd, MessageSendInfo &MSI) override { // Don't access the slot unless we're trying to cache the result. CGBuilderTy &Builder = CGF.Builder; - llvm::Value *lookupArgs[] = {CGObjCGNU::EnforceType(Builder, - ObjCSuper.getPointer(), - PtrToObjCSuperTy), - cmd}; + llvm::Value *lookupArgs[] = { + CGObjCGNU::EnforceType(Builder, ObjCSuper.emitRawPointer(CGF), + PtrToObjCSuperTy), + cmd}; return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs); } @@ -2186,7 +2187,8 @@ protected: llvm::Value *cmd, MessageSendInfo &MSI) override { CGBuilderTy &Builder = CGF.Builder; llvm::Value *lookupArgs[] = { - EnforceType(Builder, ObjCSuper.getPointer(), PtrToObjCSuperTy), cmd, + EnforceType(Builder, ObjCSuper.emitRawPointer(CGF), PtrToObjCSuperTy), + cmd, }; if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) @@ -4201,15 +4203,15 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF, llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGenFunction &CGF, Address AddrWeakObj) { CGBuilderTy &B = CGF.Builder; - return B.CreateCall(WeakReadFn, - EnforceType(B, AddrWeakObj.getPointer(), PtrToIdTy)); + return B.CreateCall( + WeakReadFn, EnforceType(B, AddrWeakObj.emitRawPointer(CGF), PtrToIdTy)); } void CGObjCGNU::EmitObjCWeakAssign(CodeGenFunction &CGF, llvm::Value *src, Address dst) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.getPointer(), PtrToIdTy); + llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), PtrToIdTy); B.CreateCall(WeakAssignFn, {src, dstVal}); } @@ -4218,7 +4220,7 @@ void CGObjCGNU::EmitObjCGlobalAssign(CodeGenFunction &CGF, bool threadlocal) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.getPointer(), PtrToIdTy); + llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), PtrToIdTy); // FIXME. Add threadloca assign API assert(!threadlocal && "EmitObjCGlobalAssign - Threal Local API NYI"); B.CreateCall(GlobalAssignFn, {src, dstVal}); @@ -4229,7 +4231,7 @@ void CGObjCGNU::EmitObjCIvarAssign(CodeGenFunction &CGF, llvm::Value *ivarOffset) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.getPointer(), IdTy); + llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), IdTy); B.CreateCall(IvarAssignFn, {src, dstVal, ivarOffset}); } @@ -4237,7 +4239,7 @@ void CGObjCGNU::EmitObjCStrongCastAssign(CodeGenFunction &CGF, llvm::Value *src, Address dst) { CGBuilderTy &B = CGF.Builder; src = EnforceType(B, src, IdTy); - llvm::Value *dstVal = EnforceType(B, dst.getPointer(), PtrToIdTy); + llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), PtrToIdTy); B.CreateCall(StrongCastAssignFn, {src, dstVal}); } @@ -4246,8 +4248,8 @@ void CGObjCGNU::EmitGCMemmoveCollectable(CodeGenFunction &CGF, Address SrcPtr, llvm::Value *Size) { CGBuilderTy &B = CGF.Builder; - llvm::Value *DestPtrVal = EnforceType(B, DestPtr.getPointer(), PtrTy); - llvm::Value *SrcPtrVal = EnforceType(B, SrcPtr.getPointer(), PtrTy); + llvm::Value *DestPtrVal = EnforceType(B, DestPtr.emitRawPointer(CGF), PtrTy); + llvm::Value *SrcPtrVal = EnforceType(B, SrcPtr.emitRawPointer(CGF), PtrTy); B.CreateCall(MemMoveFn, {DestPtrVal, SrcPtrVal, Size}); } diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index e815e097e1fb48e7e3037d8983174ed471259245..8a599c10e1caf17328d7f3e1d70f3b7d499aacbc 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -1310,7 +1310,7 @@ private: /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, /// for the given selector. llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel); - Address EmitSelectorAddr(Selector Sel); + ConstantAddress EmitSelectorAddr(Selector Sel); public: CGObjCMac(CodeGen::CodeGenModule &cgm); @@ -1538,7 +1538,7 @@ private: /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, /// for the given selector. llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel); - Address EmitSelectorAddr(Selector Sel); + ConstantAddress EmitSelectorAddr(Selector Sel); /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C /// interface. The return value has type EHTypePtrTy. @@ -2064,9 +2064,8 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, const ObjCMethodDecl *Method) { // Create and init a super structure; this is a (receiver, class) // pair we will pass to objc_msgSendSuper. - Address ObjCSuper = - CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(), - "objc_super"); + RawAddress ObjCSuper = CGF.CreateTempAlloca( + ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super"); llvm::Value *ReceiverAsObject = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); CGF.Builder.CreateStore(ReceiverAsObject, @@ -2501,12 +2500,12 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { auto *CArray = cast<ConstantArrayType>(Array); - uint64_t ElCount = CArray->getSize().getZExtValue(); + uint64_t ElCount = CArray->getZExtSize(); assert(CArray && "only array with known element size is supported"); FQT = CArray->getElementType(); while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { auto *CArray = cast<ConstantArrayType>(Array); - ElCount *= CArray->getSize().getZExtValue(); + ElCount *= CArray->getZExtSize(); FQT = CArray->getElementType(); } if (FQT->isRecordType() && ElCount) { @@ -4259,7 +4258,7 @@ namespace { CGF.EmitBlock(FinallyCallExit); CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(), - ExceptionData.getPointer()); + ExceptionData.emitRawPointer(CGF)); CGF.EmitBlock(FinallyNoCallExit); @@ -4425,7 +4424,9 @@ void FragileHazards::emitHazardsInNewBlocks() { } static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, Address V) { - if (V.isValid()) S.insert(V.getPointer()); + if (V.isValid()) + if (llvm::Value *Ptr = V.getBasePointer()) + S.insert(Ptr); } void FragileHazards::collectLocals() { @@ -4628,13 +4629,13 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // - Call objc_exception_try_enter to push ExceptionData on top of // the EH stack. CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), - ExceptionData.getPointer()); + ExceptionData.emitRawPointer(CGF)); // - Call setjmp on the exception data buffer. llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0); llvm::Value *GEPIndexes[] = { Zero, Zero, Zero }; llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP( - ObjCTypes.ExceptionDataTy, ExceptionData.getPointer(), GEPIndexes, + ObjCTypes.ExceptionDataTy, ExceptionData.emitRawPointer(CGF), GEPIndexes, "setjmp_buffer"); llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall( ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result"); @@ -4673,9 +4674,9 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, } else { // Retrieve the exception object. We may emit multiple blocks but // nothing can cross this so the value is already in SSA form. - llvm::CallInst *Caught = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), - ExceptionData.getPointer(), "caught"); + llvm::CallInst *Caught = CGF.EmitNounwindRuntimeCall( + ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF), + "caught"); // Push the exception to rethrow onto the EH value stack for the // benefit of any @throws in the handlers. @@ -4698,7 +4699,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Enter a new exception try block (in case a @catch block // throws an exception). CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), - ExceptionData.getPointer()); + ExceptionData.emitRawPointer(CGF)); llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(), @@ -4829,9 +4830,9 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Extract the new exception and save it to the // propagating-exception slot. assert(PropagatingExnVar.isValid()); - llvm::CallInst *NewCaught = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), - ExceptionData.getPointer(), "caught"); + llvm::CallInst *NewCaught = CGF.EmitNounwindRuntimeCall( + ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF), + "caught"); CGF.Builder.CreateStore(NewCaught, PropagatingExnVar); // Don't pop the catch handler; the throw already did. @@ -4861,9 +4862,8 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Otherwise, just look in the buffer for the exception to throw. } else { - llvm::CallInst *Caught = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), - ExceptionData.getPointer()); + llvm::CallInst *Caught = CGF.EmitNounwindRuntimeCall( + ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF)); PropagatingExn = Caught; } @@ -4906,7 +4906,7 @@ llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, Address AddrWeakObj) { llvm::Type* DestTy = AddrWeakObj.getElementType(); llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast( - AddrWeakObj.getPointer(), ObjCTypes.PtrObjectPtrTy); + AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy); llvm::Value *read_weak = CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal, "weakread"); @@ -4928,8 +4928,8 @@ void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = { src, dstVal }; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args, "weakassign"); @@ -4950,8 +4950,8 @@ void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; if (!threadlocal) CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), @@ -4977,8 +4977,8 @@ void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal, ivarOffset}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args); } @@ -4997,8 +4997,8 @@ void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args, "strongassign"); @@ -5007,7 +5007,8 @@ void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, Address DestPtr, Address SrcPtr, llvm::Value *size) { - llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), size }; + llvm::Value *args[] = {DestPtr.emitRawPointer(CGF), + SrcPtr.emitRawPointer(CGF), size}; CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args); } @@ -5243,7 +5244,7 @@ llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) { return CGF.Builder.CreateLoad(EmitSelectorAddr(Sel)); } -Address CGObjCMac::EmitSelectorAddr(Selector Sel) { +ConstantAddress CGObjCMac::EmitSelectorAddr(Selector Sel) { CharUnits Align = CGM.getPointerAlign(); llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; @@ -5254,7 +5255,7 @@ Address CGObjCMac::EmitSelectorAddr(Selector Sel) { Entry->setExternallyInitialized(true); } - return Address(Entry, ObjCTypes.SelectorPtrTy, Align); + return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align); } llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) { @@ -5326,7 +5327,7 @@ void IvarLayoutBuilder::visitField(const FieldDecl *field, } // Unlike incomplete arrays, constant arrays can be nested. while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) { - numElts *= arrayType->getSize().getZExtValue(); + numElts *= arrayType->getZExtSize(); fieldType = arrayType->getElementType(); } @@ -7323,7 +7324,7 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, ObjCTypes.MessageRefTy, CGF.getPointerAlign()); // Update the message ref argument. - args[1].setRValue(RValue::get(mref.getPointer())); + args[1].setRValue(RValue::get(mref, CGF)); // Load the function to call from the message ref table. Address calleeAddr = CGF.Builder.CreateStructGEP(mref, 0); @@ -7552,9 +7553,8 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, // ... // Create and init a super structure; this is a (receiver, class) // pair we will pass to objc_msgSendSuper. - Address ObjCSuper = - CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(), - "objc_super"); + RawAddress ObjCSuper = CGF.CreateTempAlloca( + ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super"); llvm::Value *ReceiverAsObject = CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); @@ -7594,7 +7594,7 @@ llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF, return LI; } -Address CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) { +ConstantAddress CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) { llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; CharUnits Align = CGM.getPointerAlign(); if (!Entry) { @@ -7610,7 +7610,7 @@ Address CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) { CGM.addCompilerUsedGlobal(Entry); } - return Address(Entry, ObjCTypes.SelectorPtrTy, Align); + return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align); } /// EmitObjCIvarAssign - Code gen for assigning to a __strong object. @@ -7629,8 +7629,8 @@ void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal, ivarOffset}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args); } @@ -7650,8 +7650,8 @@ void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args, "weakassign"); @@ -7660,7 +7660,8 @@ void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable( CodeGen::CodeGenFunction &CGF, Address DestPtr, Address SrcPtr, llvm::Value *Size) { - llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), Size }; + llvm::Value *args[] = {DestPtr.emitRawPointer(CGF), + SrcPtr.emitRawPointer(CGF), Size}; CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args); } @@ -7672,7 +7673,7 @@ llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead( Address AddrWeakObj) { llvm::Type *DestTy = AddrWeakObj.getElementType(); llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast( - AddrWeakObj.getPointer(), ObjCTypes.PtrObjectPtrTy); + AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy); llvm::Value *read_weak = CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal, "weakread"); @@ -7694,8 +7695,8 @@ void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args, "weakassign"); @@ -7716,8 +7717,8 @@ void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); - llvm::Value *dstVal = - CGF.Builder.CreateBitCast(dst.getPointer(), ObjCTypes.PtrObjectPtrTy); + llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), + ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; if (!threadlocal) CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), diff --git a/clang/lib/CodeGen/CGObjCRuntime.cpp b/clang/lib/CodeGen/CGObjCRuntime.cpp index 424564f9759995267ff2061cfbc6371ecbc7c2df..01d0f35da19643cf1d0b5b21439f6fbbe4ade22e 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.cpp +++ b/clang/lib/CodeGen/CGObjCRuntime.cpp @@ -67,7 +67,7 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, V = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, V, Offset, "add.ptr"); if (!Ivar->isBitField()) { - LValue LV = CGF.MakeNaturalAlignAddrLValue(V, IvarTy); + LValue LV = CGF.MakeNaturalAlignRawAddrLValue(V, IvarTy); return LV; } @@ -233,7 +233,7 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, llvm::Instruction *CPICandidate = Handler.Block->getFirstNonPHI(); if (auto *CPI = dyn_cast_or_null<llvm::CatchPadInst>(CPICandidate)) { CGF.CurrentFuncletPad = CPI; - CPI->setOperand(2, CGF.getExceptionSlot().getPointer()); + CPI->setOperand(2, CGF.getExceptionSlot().emitRawPointer(CGF)); CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI); } } @@ -405,7 +405,7 @@ bool CGObjCRuntime::canMessageReceiverBeNull(CodeGenFunction &CGF, auto self = curMethod->getSelfDecl(); if (self->getType().isConstQualified()) { if (auto LI = dyn_cast<llvm::LoadInst>(receiver->stripPointerCasts())) { - llvm::Value *selfAddr = CGF.GetAddrOfLocalVar(self).getPointer(); + llvm::Value *selfAddr = CGF.GetAddrOfLocalVar(self).emitRawPointer(CGF); if (selfAddr == LI->getPointerOperand()) { return false; } diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index e8a68dbcc68709c7afd7249032674409dd711e9f..bc363313dec6f8ba350eb4f8c29ea9f0df6effde 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -622,7 +622,7 @@ static void emitInitWithReductionInitializer(CodeGenFunction &CGF, auto *GV = new llvm::GlobalVariable( CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, Init, Name); - LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); + LValue LV = CGF.MakeNaturalAlignRawAddrLValue(GV, Ty); RValue InitRVal; switch (CGF.getEvaluationKind(Ty)) { case TEK_Scalar: @@ -668,8 +668,8 @@ static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, llvm::Value *SrcBegin = nullptr; if (DRD) - SrcBegin = SrcAddr.getPointer(); - llvm::Value *DestBegin = DestAddr.getPointer(); + SrcBegin = SrcAddr.emitRawPointer(CGF); + llvm::Value *DestBegin = DestAddr.emitRawPointer(CGF); // Cast from pointer to array type to pointer to single element. llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestAddr.getElementType(), DestBegin, NumElements); @@ -912,7 +912,7 @@ static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, Address OriginalBaseAddress, llvm::Value *Addr) { - Address Tmp = Address::invalid(); + RawAddress Tmp = RawAddress::invalid(); Address TopTmp = Address::invalid(); Address MostTopTmp = Address::invalid(); BaseTy = BaseTy.getNonReferenceType(); @@ -971,10 +971,10 @@ Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address SharedAddr = SharedAddresses[N].first.getAddress(CGF); llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( SharedAddr.getElementType(), BaseLValue.getPointer(CGF), - SharedAddr.getPointer()); + SharedAddr.emitRawPointer(CGF)); llvm::Value *PrivatePointer = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - PrivateAddr.getPointer(), SharedAddr.getType()); + PrivateAddr.emitRawPointer(CGF), SharedAddr.getType()); llvm::Value *Ptr = CGF.Builder.CreateGEP( SharedAddr.getElementType(), PrivatePointer, Adjustment); return castToBase(CGF, OrigVD->getType(), @@ -1557,7 +1557,7 @@ static llvm::TargetRegionEntryInfo getEntryInfoFromPresumedLoc( return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack, ParentName); } -Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { +ConstantAddress CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { auto AddrOfGlobal = [&VD, this]() { return CGM.GetAddrOfGlobal(VD); }; auto LinkageForVariable = [&VD, this]() { @@ -1579,8 +1579,8 @@ Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { LinkageForVariable); if (!addr) - return Address::invalid(); - return Address(addr, LlvmPtrTy, CGM.getContext().getDeclAlign(VD)); + return ConstantAddress::invalid(); + return ConstantAddress(addr, LlvmPtrTy, CGM.getContext().getDeclAlign(VD)); } llvm::Constant * @@ -1604,7 +1604,7 @@ Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, llvm::Type *VarTy = VDAddr.getElementType(); llvm::Value *Args[] = { emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), - CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.Int8PtrTy), + CGF.Builder.CreatePointerCast(VDAddr.emitRawPointer(CGF), CGM.Int8PtrTy), CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), getOrCreateThreadPrivateCache(VD)}; return Address( @@ -1627,7 +1627,8 @@ void CGOpenMPRuntime::emitThreadPrivateVarInit( // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) // to register constructor/destructor for variable. llvm::Value *Args[] = { - OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), + OMPLoc, + CGF.Builder.CreatePointerCast(VDAddr.emitRawPointer(CGF), CGM.VoidPtrTy), Ctor, CopyCtor, Dtor}; CGF.EmitRuntimeCall( OMPBuilder.getOrCreateRuntimeFunction( @@ -1900,13 +1901,13 @@ void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, // OutlinedFn(>id, &zero_bound, CapturedStruct); Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); - Address ZeroAddrBound = + RawAddress ZeroAddrBound = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, /*Name=*/".bound.zero.addr"); CGF.Builder.CreateStore(CGF.Builder.getInt32(/*C*/ 0), ZeroAddrBound); llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; // ThreadId for serialized parallels is 0. - OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); + OutlinedFnArgs.push_back(ThreadIDAddr.emitRawPointer(CGF)); OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); @@ -2272,7 +2273,7 @@ void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, emitUpdateLocation(CGF, Loc), // ident_t *<loc> getThreadID(CGF, Loc), // i32 <gtid> BufSize, // size_t <buf_size> - CL.getPointer(), // void *<copyprivate list> + CL.emitRawPointer(CGF), // void *<copyprivate list> CpyFn, // void (*) (void *, void *) <copy_func> DidItVal // i32 did_it }; @@ -2591,10 +2592,10 @@ static void emitForStaticInitCall( ThreadId, CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, M2)), // Schedule type - Values.IL.getPointer(), // &isLastIter - Values.LB.getPointer(), // &LB - Values.UB.getPointer(), // &UB - Values.ST.getPointer(), // &Stride + Values.IL.emitRawPointer(CGF), // &isLastIter + Values.LB.emitRawPointer(CGF), // &LB + Values.UB.emitRawPointer(CGF), // &UB + Values.ST.emitRawPointer(CGF), // &Stride CGF.Builder.getIntN(Values.IVSize, 1), // Incr Chunk // Chunk }; @@ -2697,12 +2698,11 @@ llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, // kmp_int[32|64] *p_stride); llvm::Value *Args[] = { - emitUpdateLocation(CGF, Loc), - getThreadID(CGF, Loc), - IL.getPointer(), // &isLastIter - LB.getPointer(), // &Lower - UB.getPointer(), // &Upper - ST.getPointer() // &Stride + emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), + IL.emitRawPointer(CGF), // &isLastIter + LB.emitRawPointer(CGF), // &Lower + UB.emitRawPointer(CGF), // &Upper + ST.emitRawPointer(CGF) // &Stride }; llvm::Value *Call = CGF.EmitRuntimeCall( OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args); @@ -3047,7 +3047,7 @@ emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, CGF.Builder .CreatePointerBitCastOrAddrSpaceCast(TDBase.getAddress(CGF), CGF.VoidPtrTy, CGF.Int8Ty) - .getPointer()}; + .emitRawPointer(CGF)}; SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), std::end(CommonArgs)); if (isOpenMPTaskLoopDirective(Kind)) { @@ -3574,7 +3574,8 @@ getPointerAndSize(CodeGenFunction &CGF, const Expr *E) { CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); Address UpAddrAddress = UpAddrLVal.getAddress(CGF); llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( - UpAddrAddress.getElementType(), UpAddrAddress.getPointer(), /*Idx0=*/1); + UpAddrAddress.getElementType(), UpAddrAddress.emitRawPointer(CGF), + /*Idx0=*/1); llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGF.SizeTy); llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGF.SizeTy); SizeVal = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); @@ -3888,8 +3889,9 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *Size; std::tie(Addr, Size) = getPointerAndSize(CGF, E); llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); - LValue Base = CGF.MakeAddrLValue( - CGF.Builder.CreateGEP(AffinitiesArray, Idx), KmpTaskAffinityInfoTy); + LValue Base = + CGF.MakeAddrLValue(CGF.Builder.CreateGEP(CGF, AffinitiesArray, Idx), + KmpTaskAffinityInfoTy); // affs[i].base_addr = &<Affinities[i].second>; LValue BaseAddrLVal = CGF.EmitLValueForField( Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr)); @@ -3910,7 +3912,7 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *LocRef = emitUpdateLocation(CGF, Loc); llvm::Value *GTid = getThreadID(CGF, Loc); llvm::Value *AffinListPtr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - AffinitiesArray.getPointer(), CGM.VoidPtrTy); + AffinitiesArray.emitRawPointer(CGF), CGM.VoidPtrTy); // FIXME: Emit the function and ignore its result for now unless the // runtime function is properly implemented. (void)CGF.EmitRuntimeCall( @@ -3921,8 +3923,8 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *NewTaskNewTaskTTy = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( NewTask, KmpTaskTWithPrivatesPtrTy); - LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, - KmpTaskTWithPrivatesQTy); + LValue Base = CGF.MakeNaturalAlignRawAddrLValue(NewTaskNewTaskTTy, + KmpTaskTWithPrivatesQTy); LValue TDBase = CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); // Fill the data in the resulting kmp_task_t record. @@ -4047,7 +4049,7 @@ CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, CGF.ConvertTypeForMem(KmpDependInfoPtrTy)), KmpDependInfoPtrTy->castAs<PointerType>()); Address DepObjAddr = CGF.Builder.CreateGEP( - Base.getAddress(CGF), + CGF, Base.getAddress(CGF), llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); LValue NumDepsBase = CGF.MakeAddrLValue( DepObjAddr, KmpDependInfoTy, Base.getBaseInfo(), Base.getTBAAInfo()); @@ -4097,7 +4099,7 @@ static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, LValue &PosLVal = *Pos.get<LValue *>(); llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); Base = CGF.MakeAddrLValue( - CGF.Builder.CreateGEP(DependenciesArray, Idx), KmpDependInfoTy); + CGF.Builder.CreateGEP(CGF, DependenciesArray, Idx), KmpDependInfoTy); } // deps[i].base_addr = &<Dependencies[i].second>; LValue BaseAddrLVal = CGF.EmitLValueForField( @@ -4195,7 +4197,7 @@ void CGOpenMPRuntime::emitDepobjElements(CodeGenFunction &CGF, ElSize, CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false)); llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); - Address DepAddr = CGF.Builder.CreateGEP(DependenciesArray, Pos); + Address DepAddr = CGF.Builder.CreateGEP(CGF, DependenciesArray, Pos); CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size); // Increase pos. @@ -4430,7 +4432,7 @@ void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy), CGF.ConvertTypeForMem(KmpDependInfoTy)); llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( - Addr.getElementType(), Addr.getPointer(), + Addr.getElementType(), Addr.emitRawPointer(CGF), llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr, CGF.VoidPtrTy); @@ -4460,8 +4462,8 @@ void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, Address Begin = Base.getAddress(CGF); // Cast from pointer to array type to pointer to single element. - llvm::Value *End = CGF.Builder.CreateGEP( - Begin.getElementType(), Begin.getPointer(), NumDeps); + llvm::Value *End = CGF.Builder.CreateGEP(Begin.getElementType(), + Begin.emitRawPointer(CGF), NumDeps); // The basic structure here is a while-do loop. llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body"); llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done"); @@ -4469,7 +4471,7 @@ void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, CGF.EmitBlock(BodyBB); llvm::PHINode *ElementPHI = CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast"); - ElementPHI->addIncoming(Begin.getPointer(), EntryBB); + ElementPHI->addIncoming(Begin.emitRawPointer(CGF), EntryBB); Begin = Begin.withPointer(ElementPHI, KnownNonNull); Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(), Base.getTBAAInfo()); @@ -4483,12 +4485,12 @@ void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, FlagsLVal); // Shift the address forward by one element. - Address ElementNext = - CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext"); - ElementPHI->addIncoming(ElementNext.getPointer(), - CGF.Builder.GetInsertBlock()); + llvm::Value *ElementNext = + CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext") + .emitRawPointer(CGF); + ElementPHI->addIncoming(ElementNext, CGF.Builder.GetInsertBlock()); llvm::Value *IsEmpty = - CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty"); + CGF.Builder.CreateICmpEQ(ElementNext, End, "omp.isempty"); CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); // Done. CGF.EmitBlock(DoneBB, /*IsFinished=*/true); @@ -4531,7 +4533,7 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, DepTaskArgs[1] = ThreadID; DepTaskArgs[2] = NewTask; DepTaskArgs[3] = NumOfElements; - DepTaskArgs[4] = DependenciesArray.getPointer(); + DepTaskArgs[4] = DependenciesArray.emitRawPointer(CGF); DepTaskArgs[5] = CGF.Builder.getInt32(0); DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); } @@ -4563,7 +4565,7 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, DepWaitTaskArgs[0] = UpLoc; DepWaitTaskArgs[1] = ThreadID; DepWaitTaskArgs[2] = NumOfElements; - DepWaitTaskArgs[3] = DependenciesArray.getPointer(); + DepWaitTaskArgs[3] = DependenciesArray.emitRawPointer(CGF); DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); DepWaitTaskArgs[6] = @@ -4725,8 +4727,8 @@ static void EmitOMPAggregateReduction( const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); - llvm::Value *RHSBegin = RHSAddr.getPointer(); - llvm::Value *LHSBegin = LHSAddr.getPointer(); + llvm::Value *RHSBegin = RHSAddr.emitRawPointer(CGF); + llvm::Value *LHSBegin = LHSAddr.emitRawPointer(CGF); // Cast from pointer to array type to pointer to single element. llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSAddr.getElementType(), LHSBegin, NumElements); @@ -4990,7 +4992,7 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, QualType ReductionArrayTy = C.getConstantArrayType( C.VoidPtrTy, ArraySize, nullptr, ArraySizeModifier::Normal, /*IndexTypeQuals=*/0); - Address ReductionList = + RawAddress ReductionList = CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); const auto *IPriv = Privates.begin(); unsigned Idx = 0; @@ -5462,7 +5464,7 @@ llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( C.getConstantArrayType(RDType, ArraySize, nullptr, ArraySizeModifier::Normal, /*IndexTypeQuals=*/0); // kmp_task_red_input_t .rd_input.[Size]; - Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); + RawAddress TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionOrigs, Data.ReductionCopies, Data.ReductionOps); for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { @@ -5473,7 +5475,7 @@ llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( TaskRedInput.getElementType(), TaskRedInput.getPointer(), Idxs, /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, ".rd_input.gep."); - LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); + LValue ElemLVal = CGF.MakeNaturalAlignRawAddrLValue(GEP, RDType); // ElemLVal.reduce_shar = &Shareds[Cnt]; LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); RCG.emitSharedOrigLValue(CGF, Cnt); @@ -5629,7 +5631,7 @@ void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, DepWaitTaskArgs[0] = UpLoc; DepWaitTaskArgs[1] = ThreadID; DepWaitTaskArgs[2] = NumOfElements; - DepWaitTaskArgs[3] = DependenciesArray.getPointer(); + DepWaitTaskArgs[3] = DependenciesArray.emitRawPointer(CGF); DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); DepWaitTaskArgs[6] = @@ -5852,7 +5854,7 @@ void CGOpenMPRuntime::emitUsesAllocatorsInit(CodeGenFunction &CGF, AllocatorTraitsLVal = CGF.MakeAddrLValue(Addr, CGF.getContext().VoidPtrTy, AllocatorTraitsLVal.getBaseInfo(), AllocatorTraitsLVal.getTBAAInfo()); - llvm::Value *Traits = Addr.getPointer(); + llvm::Value *Traits = Addr.emitRawPointer(CGF); llvm::Value *AllocatorVal = CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( @@ -6796,7 +6798,7 @@ private: OASE->getBase()->IgnoreParenImpCasts()) .getCanonicalType(); if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) - return ATy->getSize().getSExtValue() != 1; + return ATy->getSExtSize() != 1; // If we don't have a constant dimension length, we have to consider // the current section as having any size, so it is not necessarily // unitary. If it happen to be unity size, that's user fault. @@ -7312,17 +7314,19 @@ private: CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) .getAddress(CGF); } - Size = CGF.Builder.CreatePtrDiff( - CGF.Int8Ty, ComponentLB.getPointer(), LB.getPointer()); + llvm::Value *ComponentLBPtr = ComponentLB.emitRawPointer(CGF); + llvm::Value *LBPtr = LB.emitRawPointer(CGF); + Size = CGF.Builder.CreatePtrDiff(CGF.Int8Ty, ComponentLBPtr, + LBPtr); break; } } assert(Size && "Failed to determine structure size"); CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - CombinedInfo.BasePointers.push_back(BP.getPointer()); + CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF)); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - CombinedInfo.Pointers.push_back(LB.getPointer()); + CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( Size, CGF.Int64Ty, /*isSigned=*/true)); CombinedInfo.Types.push_back(Flags); @@ -7332,13 +7336,14 @@ private: LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); } CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - CombinedInfo.BasePointers.push_back(BP.getPointer()); + CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF)); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - CombinedInfo.Pointers.push_back(LB.getPointer()); + CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); + llvm::Value *LBPtr = LB.emitRawPointer(CGF); Size = CGF.Builder.CreatePtrDiff( - CGF.Int8Ty, CGF.Builder.CreateConstGEP(HB, 1).getPointer(), - LB.getPointer()); + CGF.Int8Ty, CGF.Builder.CreateConstGEP(HB, 1).emitRawPointer(CGF), + LBPtr); CombinedInfo.Sizes.push_back( CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); CombinedInfo.Types.push_back(Flags); @@ -7356,20 +7361,21 @@ private: (Next == CE && MapType != OMPC_MAP_unknown)) { if (!IsMappingWholeStruct) { CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - CombinedInfo.BasePointers.push_back(BP.getPointer()); + CombinedInfo.BasePointers.push_back(BP.emitRawPointer(CGF)); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - CombinedInfo.Pointers.push_back(LB.getPointer()); + CombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( Size, CGF.Int64Ty, /*isSigned=*/true)); CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1); } else { StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); - StructBaseCombinedInfo.BasePointers.push_back(BP.getPointer()); + StructBaseCombinedInfo.BasePointers.push_back( + BP.emitRawPointer(CGF)); StructBaseCombinedInfo.DevicePtrDecls.push_back(nullptr); StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); - StructBaseCombinedInfo.Pointers.push_back(LB.getPointer()); + StructBaseCombinedInfo.Pointers.push_back(LB.emitRawPointer(CGF)); StructBaseCombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( Size, CGF.Int64Ty, /*isSigned=*/true)); StructBaseCombinedInfo.NonContigInfo.Dims.push_back( @@ -7546,8 +7552,8 @@ private: // it. if (DimSizes.size() < Components.size() - 1) { if (CAT) - DimSizes.push_back(llvm::ConstantInt::get( - CGF.Int64Ty, CAT->getSize().getZExtValue())); + DimSizes.push_back( + llvm::ConstantInt::get(CGF.Int64Ty, CAT->getZExtSize())); else if (VAT) DimSizes.push_back(CGF.Builder.CreateIntCast( CGF.EmitScalarExpr(VAT->getSizeExpr()), CGF.Int64Ty, @@ -8211,11 +8217,11 @@ public: } CombinedInfo.Exprs.push_back(VD); // Base is the base of the struct - CombinedInfo.BasePointers.push_back(PartialStruct.Base.getPointer()); + CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF)); CombinedInfo.DevicePtrDecls.push_back(nullptr); CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None); // Pointer is the address of the lowest element - llvm::Value *LB = LBAddr.getPointer(); + llvm::Value *LB = LBAddr.emitRawPointer(CGF); const CXXMethodDecl *MD = CGF.CurFuncDecl ? dyn_cast<CXXMethodDecl>(CGF.CurFuncDecl) : nullptr; const CXXRecordDecl *RD = MD ? MD->getParent() : nullptr; @@ -8229,7 +8235,7 @@ public: // if the this[:1] expression had appeared in a map clause with a map-type // of tofrom. // Emit this[:1] - CombinedInfo.Pointers.push_back(PartialStruct.Base.getPointer()); + CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF)); QualType Ty = MD->getFunctionObjectParameterType(); llvm::Value *Size = CGF.Builder.CreateIntCast(CGF.getTypeSize(Ty), CGF.Int64Ty, @@ -8238,7 +8244,7 @@ public: } else { CombinedInfo.Pointers.push_back(LB); // Size is (addr of {highest+1} element) - (addr of lowest element) - llvm::Value *HB = HBAddr.getPointer(); + llvm::Value *HB = HBAddr.emitRawPointer(CGF); llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32( HBAddr.getElementType(), HB, /*Idx0=*/1); llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); @@ -8747,7 +8753,7 @@ public: Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( CV, ElementType, CGF.getContext().getDeclAlign(VD), AlignmentSource::Decl)); - CombinedInfo.Pointers.push_back(PtrAddr.getPointer()); + CombinedInfo.Pointers.push_back(PtrAddr.emitRawPointer(CGF)); } else { CombinedInfo.Pointers.push_back(CV); } @@ -9558,10 +9564,11 @@ static void emitTargetCallKernelLaunch( bool HasNoWait = D.hasClausesOfKind<OMPNowaitClause>(); unsigned NumTargetItems = InputInfo.NumberOfTargetItems; - llvm::Value *BasePointersArray = InputInfo.BasePointersArray.getPointer(); - llvm::Value *PointersArray = InputInfo.PointersArray.getPointer(); - llvm::Value *SizesArray = InputInfo.SizesArray.getPointer(); - llvm::Value *MappersArray = InputInfo.MappersArray.getPointer(); + llvm::Value *BasePointersArray = + InputInfo.BasePointersArray.emitRawPointer(CGF); + llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF); + llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF); + llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF); auto &&EmitTargetCallFallbackCB = [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS, @@ -10309,15 +10316,16 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall( // Source location for the ident struct llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); - llvm::Value *OffloadingArgs[] = {RTLoc, - DeviceID, - PointerNum, - InputInfo.BasePointersArray.getPointer(), - InputInfo.PointersArray.getPointer(), - InputInfo.SizesArray.getPointer(), - MapTypesArray, - MapNamesArray, - InputInfo.MappersArray.getPointer()}; + llvm::Value *OffloadingArgs[] = { + RTLoc, + DeviceID, + PointerNum, + InputInfo.BasePointersArray.emitRawPointer(CGF), + InputInfo.PointersArray.emitRawPointer(CGF), + InputInfo.SizesArray.emitRawPointer(CGF), + MapTypesArray, + MapNamesArray, + InputInfo.MappersArray.emitRawPointer(CGF)}; // Select the right runtime function call for each standalone // directive. @@ -11128,7 +11136,7 @@ void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, getThreadID(CGF, D.getBeginLoc()), llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), + CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).emitRawPointer(CGF), CGM.VoidPtrTy)}; llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( @@ -11162,7 +11170,8 @@ static void EmitDoacrossOrdered(CodeGenFunction &CGF, CodeGenModule &CGM, /*Volatile=*/false, Int64Ty); } llvm::Value *Args[] = { - ULoc, ThreadID, CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; + ULoc, ThreadID, + CGF.Builder.CreateConstArrayGEP(CntAddr, 0).emitRawPointer(CGF)}; llvm::FunctionCallee RTLFn; llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder(); OMPDoacrossKind<T> ODK; @@ -11332,7 +11341,7 @@ Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, Args[0] = CGF.CGM.getOpenMPRuntime().getThreadID( CGF, SourceLocation::getFromRawEncoding(LocEncoding)); Args[1] = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - Addr.getPointer(), CGF.VoidPtrTy); + Addr.emitRawPointer(CGF), CGF.VoidPtrTy); llvm::Value *AllocVal = getAllocatorVal(CGF, AllocExpr); Args[2] = AllocVal; CGF.EmitRuntimeCall(RTLFn, Args); @@ -11690,15 +11699,17 @@ void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LLIVTy, getName({UniqueDeclName, "iv"})); cast<llvm::GlobalVariable>(LastIV)->setAlignment( IVLVal.getAlignment().getAsAlign()); - LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); + LValue LastIVLVal = + CGF.MakeNaturalAlignRawAddrLValue(LastIV, IVLVal.getType()); // Last value of the lastprivate conditional. // decltype(priv_a) last_a; llvm::GlobalVariable *Last = OMPBuilder.getOrCreateInternalVariable( CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName); - Last->setAlignment(LVal.getAlignment().getAsAlign()); - LValue LastLVal = CGF.MakeAddrLValue( - Address(Last, Last->getValueType(), LVal.getAlignment()), LVal.getType()); + cast<llvm::GlobalVariable>(Last)->setAlignment( + LVal.getAlignment().getAsAlign()); + LValue LastLVal = + CGF.MakeRawAddrLValue(Last, LVal.getType(), LVal.getAlignment()); // Global loop counter. Required to handle inner parallel-for regions. // iv @@ -11871,9 +11882,8 @@ void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( // The variable was not updated in the region - exit. if (!GV) return; - LValue LPLVal = CGF.MakeAddrLValue( - Address(GV, GV->getValueType(), PrivLVal.getAlignment()), - PrivLVal.getType().getNonReferenceType()); + LValue LPLVal = CGF.MakeRawAddrLValue( + GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment()); llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); CGF.EmitStoreOfScalar(Res, PrivLVal); } diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.h b/clang/lib/CodeGen/CGOpenMPRuntime.h index c3206427b143e12b616bf5b1501ab6c6871870d0..522ae3d35d22d76e269b03ca0d26ef9ecc0b7bd2 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.h +++ b/clang/lib/CodeGen/CGOpenMPRuntime.h @@ -1068,13 +1068,12 @@ public: /// \param Loc Location of the reference to threadprivate var. /// \return Address of the threadprivate variable for the current thread. virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF, - const VarDecl *VD, - Address VDAddr, + const VarDecl *VD, Address VDAddr, SourceLocation Loc); /// Returns the address of the variable marked as declare target with link /// clause OR as declare target with to clause and unified memory. - virtual Address getAddrOfDeclareTargetVar(const VarDecl *VD); + virtual ConstantAddress getAddrOfDeclareTargetVar(const VarDecl *VD); /// Emit a code for initialization of threadprivate variable. It emits /// a call to runtime library which adds initial value to the newly created diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp index 299ee1460b3db0ef895c681246a8cc7f8bd42fb2..5baac8f0e3e268bf2789014edae018ec0436f557 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp @@ -1096,7 +1096,8 @@ void CGOpenMPRuntimeGPU::emitGenericVarsProlog(CodeGenFunction &CGF, llvm::PointerType *VarPtrTy = CGF.ConvertTypeForMem(VarTy)->getPointerTo(); llvm::Value *CastedVoidPtr = Bld.CreatePointerBitCastOrAddrSpaceCast( VoidPtr, VarPtrTy, VD->getName() + "_on_stack"); - LValue VarAddr = CGF.MakeNaturalAlignAddrLValue(CastedVoidPtr, VarTy); + LValue VarAddr = + CGF.MakeNaturalAlignPointeeRawAddrLValue(CastedVoidPtr, VarTy); Rec.second.PrivateAddr = VarAddr.getAddress(CGF); Rec.second.GlobalizedVal = VoidPtr; @@ -1206,8 +1207,8 @@ void CGOpenMPRuntimeGPU::emitTeamsCall(CodeGenFunction &CGF, bool IsBareKernel = D.getSingleClause<OMPXBareClause>(); - Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, - /*Name=*/".zero.addr"); + RawAddress ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, + /*Name=*/".zero.addr"); CGF.Builder.CreateStore(CGF.Builder.getInt32(/*C*/ 0), ZeroAddr); llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; // We don't emit any thread id function call in bare kernel, but because the @@ -1215,7 +1216,7 @@ void CGOpenMPRuntimeGPU::emitTeamsCall(CodeGenFunction &CGF, if (IsBareKernel) OutlinedFnArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); else - OutlinedFnArgs.push_back(emitThreadIDAddress(CGF, Loc).getPointer()); + OutlinedFnArgs.push_back(emitThreadIDAddress(CGF, Loc).emitRawPointer(CGF)); OutlinedFnArgs.push_back(ZeroAddr.getPointer()); OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); @@ -1289,7 +1290,7 @@ void CGOpenMPRuntimeGPU::emitParallelCall(CodeGenFunction &CGF, llvm::ConstantInt::get(CGF.Int32Ty, -1), FnPtr, ID, - Bld.CreateBitOrPointerCast(CapturedVarsAddrs.getPointer(), + Bld.CreateBitOrPointerCast(CapturedVarsAddrs.emitRawPointer(CGF), CGF.VoidPtrPtrTy), llvm::ConstantInt::get(CGM.SizeTy, CapturedVars.size())}; CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( @@ -1503,17 +1504,18 @@ static void shuffleAndStore(CodeGenFunction &CGF, Address SrcAddr, CGF.EmitBlock(PreCondBB); llvm::PHINode *PhiSrc = Bld.CreatePHI(Ptr.getType(), /*NumReservedValues=*/2); - PhiSrc->addIncoming(Ptr.getPointer(), CurrentBB); + PhiSrc->addIncoming(Ptr.emitRawPointer(CGF), CurrentBB); llvm::PHINode *PhiDest = Bld.CreatePHI(ElemPtr.getType(), /*NumReservedValues=*/2); - PhiDest->addIncoming(ElemPtr.getPointer(), CurrentBB); + PhiDest->addIncoming(ElemPtr.emitRawPointer(CGF), CurrentBB); Ptr = Address(PhiSrc, Ptr.getElementType(), Ptr.getAlignment()); ElemPtr = Address(PhiDest, ElemPtr.getElementType(), ElemPtr.getAlignment()); + llvm::Value *PtrEndRaw = PtrEnd.emitRawPointer(CGF); + llvm::Value *PtrRaw = Ptr.emitRawPointer(CGF); llvm::Value *PtrDiff = Bld.CreatePtrDiff( - CGF.Int8Ty, PtrEnd.getPointer(), - Bld.CreatePointerBitCastOrAddrSpaceCast(Ptr.getPointer(), - CGF.VoidPtrTy)); + CGF.Int8Ty, PtrEndRaw, + Bld.CreatePointerBitCastOrAddrSpaceCast(PtrRaw, CGF.VoidPtrTy)); Bld.CreateCondBr(Bld.CreateICmpSGT(PtrDiff, Bld.getInt64(IntSize - 1)), ThenBB, ExitBB); CGF.EmitBlock(ThenBB); @@ -1528,8 +1530,8 @@ static void shuffleAndStore(CodeGenFunction &CGF, Address SrcAddr, TBAAAccessInfo()); Address LocalPtr = Bld.CreateConstGEP(Ptr, 1); Address LocalElemPtr = Bld.CreateConstGEP(ElemPtr, 1); - PhiSrc->addIncoming(LocalPtr.getPointer(), ThenBB); - PhiDest->addIncoming(LocalElemPtr.getPointer(), ThenBB); + PhiSrc->addIncoming(LocalPtr.emitRawPointer(CGF), ThenBB); + PhiDest->addIncoming(LocalElemPtr.emitRawPointer(CGF), ThenBB); CGF.EmitBranch(PreCondBB); CGF.EmitBlock(ExitBB); } else { @@ -1676,10 +1678,10 @@ static void emitReductionListCopy( // scope and that of functions it invokes (i.e., reduce_function). // RemoteReduceData[i] = (void*)&RemoteElem if (UpdateDestListPtr) { - CGF.EmitStoreOfScalar(Bld.CreatePointerBitCastOrAddrSpaceCast( - DestElementAddr.getPointer(), CGF.VoidPtrTy), - DestElementPtrAddr, /*Volatile=*/false, - C.VoidPtrTy); + CGF.EmitStoreOfScalar( + Bld.CreatePointerBitCastOrAddrSpaceCast( + DestElementAddr.emitRawPointer(CGF), CGF.VoidPtrTy), + DestElementPtrAddr, /*Volatile=*/false, C.VoidPtrTy); } ++Idx; @@ -1830,7 +1832,7 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM, // elemptr = ((CopyType*)(elemptrptr)) + I Address ElemPtr(ElemPtrPtr, CopyType, Align); if (NumIters > 1) - ElemPtr = Bld.CreateGEP(ElemPtr, Cnt); + ElemPtr = Bld.CreateGEP(CGF, ElemPtr, Cnt); // Get pointer to location in transfer medium. // MediumPtr = &medium[warp_id] @@ -1894,7 +1896,7 @@ static llvm::Value *emitInterWarpCopyFunction(CodeGenModule &CGM, TargetElemPtrPtr, /*Volatile=*/false, C.VoidPtrTy, Loc); Address TargetElemPtr(TargetElemPtrVal, CopyType, Align); if (NumIters > 1) - TargetElemPtr = Bld.CreateGEP(TargetElemPtr, Cnt); + TargetElemPtr = Bld.CreateGEP(CGF, TargetElemPtr, Cnt); // *TargetElemPtr = SrcMediumVal; llvm::Value *SrcMediumValue = @@ -2105,9 +2107,9 @@ static llvm::Function *emitShuffleAndReduceFunction( CGF.EmitBlock(ThenBB); // reduce_function(LocalReduceList, RemoteReduceList) llvm::Value *LocalReduceListPtr = Bld.CreatePointerBitCastOrAddrSpaceCast( - LocalReduceList.getPointer(), CGF.VoidPtrTy); + LocalReduceList.emitRawPointer(CGF), CGF.VoidPtrTy); llvm::Value *RemoteReduceListPtr = Bld.CreatePointerBitCastOrAddrSpaceCast( - RemoteReduceList.getPointer(), CGF.VoidPtrTy); + RemoteReduceList.emitRawPointer(CGF), CGF.VoidPtrTy); CGM.getOpenMPRuntime().emitOutlinedFunctionCall( CGF, Loc, ReduceFn, {LocalReduceListPtr, RemoteReduceListPtr}); Bld.CreateBr(MergeBB); @@ -2218,9 +2220,9 @@ static llvm::Value *emitListToGlobalCopyFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - GlobLVal.setAddress(Address(GlobAddr.getPointer(), + GlobLVal.setAddress(Address(GlobAddr.emitRawPointer(CGF), CGF.ConvertTypeForMem(Private->getType()), GlobAddr.getAlignment())); switch (CGF.getEvaluationKind(Private->getType())) { @@ -2304,7 +2306,7 @@ static llvm::Value *emitListToGlobalReduceFunction( // 1. Build a list of reduction variables. // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; - Address ReductionList = + RawAddress ReductionList = CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); auto IPriv = Privates.begin(); llvm::Value *Idxs[] = {CGF.EmitLoadOfScalar(CGF.GetAddrOfLocalVar(&IdxArg), @@ -2319,10 +2321,10 @@ static llvm::Value *emitListToGlobalReduceFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - CGF.EmitStoreOfScalar(GlobAddr.getPointer(), Elem, /*Volatile=*/false, - C.VoidPtrTy); + CGF.EmitStoreOfScalar(GlobAddr.emitRawPointer(CGF), Elem, + /*Volatile=*/false, C.VoidPtrTy); if ((*IPriv)->getType()->isVariablyModifiedType()) { // Store array size. ++Idx; @@ -2425,9 +2427,9 @@ static llvm::Value *emitGlobalToListCopyFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - GlobLVal.setAddress(Address(GlobAddr.getPointer(), + GlobLVal.setAddress(Address(GlobAddr.emitRawPointer(CGF), CGF.ConvertTypeForMem(Private->getType()), GlobAddr.getAlignment())); switch (CGF.getEvaluationKind(Private->getType())) { @@ -2526,10 +2528,10 @@ static llvm::Value *emitGlobalToListReduceFunction( llvm::Value *BufferPtr = Bld.CreateInBoundsGEP(LLVMReductionsBufferTy, BufferArrPtr, Idxs); LValue GlobLVal = CGF.EmitLValueForField( - CGF.MakeNaturalAlignAddrLValue(BufferPtr, StaticTy), FD); + CGF.MakeNaturalAlignRawAddrLValue(BufferPtr, StaticTy), FD); Address GlobAddr = GlobLVal.getAddress(CGF); - CGF.EmitStoreOfScalar(GlobAddr.getPointer(), Elem, /*Volatile=*/false, - C.VoidPtrTy); + CGF.EmitStoreOfScalar(GlobAddr.emitRawPointer(CGF), Elem, + /*Volatile=*/false, C.VoidPtrTy); if ((*IPriv)->getType()->isVariablyModifiedType()) { // Store array size. ++Idx; @@ -2545,7 +2547,7 @@ static llvm::Value *emitGlobalToListReduceFunction( } // Call reduce_function(ReduceList, GlobalReduceList) - llvm::Value *GlobalReduceList = ReductionList.getPointer(); + llvm::Value *GlobalReduceList = ReductionList.emitRawPointer(CGF); Address AddrReduceListArg = CGF.GetAddrOfLocalVar(&ReduceListArg); llvm::Value *ReducedPtr = CGF.EmitLoadOfScalar( AddrReduceListArg, /*Volatile=*/false, C.VoidPtrTy, Loc); @@ -2876,7 +2878,7 @@ void CGOpenMPRuntimeGPU::emitReduction( } llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( - ReductionList.getPointer(), CGF.VoidPtrTy); + ReductionList.emitRawPointer(CGF), CGF.VoidPtrTy); llvm::Function *ReductionFn = emitReductionFunction( CGF.CurFn->getName(), Loc, CGF.ConvertTypeForMem(ReductionArrayTy), Privates, LHSExprs, RHSExprs, ReductionOps); @@ -3106,15 +3108,15 @@ llvm::Function *CGOpenMPRuntimeGPU::createParallelDataSharingWrapper( // Get the array of arguments. SmallVector<llvm::Value *, 8> Args; - Args.emplace_back(CGF.GetAddrOfLocalVar(&WrapperArg).getPointer()); - Args.emplace_back(ZeroAddr.getPointer()); + Args.emplace_back(CGF.GetAddrOfLocalVar(&WrapperArg).emitRawPointer(CGF)); + Args.emplace_back(ZeroAddr.emitRawPointer(CGF)); CGBuilderTy &Bld = CGF.Builder; auto CI = CS.capture_begin(); // Use global memory for data sharing. // Handle passing of global args to workers. - Address GlobalArgs = + RawAddress GlobalArgs = CGF.CreateDefaultAlignTempAlloca(CGF.VoidPtrPtrTy, "global_args"); llvm::Value *GlobalArgsPtr = GlobalArgs.getPointer(); llvm::Value *DataSharingArgs[] = {GlobalArgsPtr}; @@ -3400,7 +3402,7 @@ void CGOpenMPRuntimeGPU::adjustTargetSpecificDataForLambdas( VDAddr = CGF.EmitLoadOfReferenceLValue(VDAddr, VD->getType().getCanonicalType()) .getAddress(CGF); - CGF.EmitStoreOfScalar(VDAddr.getPointer(), VarLVal); + CGF.EmitStoreOfScalar(VDAddr.emitRawPointer(CGF), VarLVal); } } } diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp index 7822903b89ce47e174d24508d86609a42cb3dba7..634a55fec5182eb76dc0439b25c045dbc63bfa37 100644 --- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -47,8 +47,10 @@ namespace { /// [i8 x 3] instead of i24. The function clipTailPadding does this. /// C++ examples that require clipping: /// struct { int a : 24; char b; }; // a must be clipped, b goes at offset 3 -/// struct A { int a : 24; }; // a must be clipped because a struct like B -// could exist: struct B : A { char b; }; // b goes at offset 3 +/// struct A { int a : 24; ~A(); }; // a must be clipped because: +/// struct B : A { char b; }; // b goes at offset 3 +/// * The allocation of bitfield access units is described in more detail in +/// CGRecordLowering::accumulateBitFields. /// * Clang ignores 0 sized bitfields and 0 sized bases but *not* zero sized /// fields. The existing asserts suggest that LLVM assumes that *every* field /// has an underlying storage type. Therefore empty structures containing @@ -183,17 +185,21 @@ struct CGRecordLowering { /// Lowers an ASTRecordLayout to a llvm type. void lower(bool NonVirtualBaseType); void lowerUnion(bool isNoUniqueAddress); - void accumulateFields(); - void accumulateBitFields(RecordDecl::field_iterator Field, - RecordDecl::field_iterator FieldEnd); + void accumulateFields(bool isNonVirtualBaseType); + RecordDecl::field_iterator + accumulateBitFields(bool isNonVirtualBaseType, + RecordDecl::field_iterator Field, + RecordDecl::field_iterator FieldEnd); void computeVolatileBitfields(); void accumulateBases(); void accumulateVPtrs(); void accumulateVBases(); /// Recursively searches all of the bases to find out if a vbase is /// not the primary vbase of some base class. - bool hasOwnStorage(const CXXRecordDecl *Decl, const CXXRecordDecl *Query); + bool hasOwnStorage(const CXXRecordDecl *Decl, + const CXXRecordDecl *Query) const; void calculateZeroInit(); + CharUnits calculateTailClippingOffset(bool isNonVirtualBaseType) const; /// Lowers bitfield storage types to I8 arrays for bitfields with tail /// padding that is or can potentially be used. void clipTailPadding(); @@ -284,7 +290,7 @@ void CGRecordLowering::lower(bool NVBaseType) { computeVolatileBitfields(); return; } - accumulateFields(); + accumulateFields(NVBaseType); // RD implies C++. if (RD) { accumulateVPtrs(); @@ -375,16 +381,18 @@ void CGRecordLowering::lowerUnion(bool isNoUniqueAddress) { Packed = true; } -void CGRecordLowering::accumulateFields() { +void CGRecordLowering::accumulateFields(bool isNonVirtualBaseType) { for (RecordDecl::field_iterator Field = D->field_begin(), FieldEnd = D->field_end(); - Field != FieldEnd;) { + Field != FieldEnd;) { if (Field->isBitField()) { - RecordDecl::field_iterator Start = Field; - // Iterate to gather the list of bitfields. - for (++Field; Field != FieldEnd && Field->isBitField(); ++Field); - accumulateBitFields(Start, Field); - } else if (!Field->isZeroSize(Context)) { + Field = accumulateBitFields(isNonVirtualBaseType, Field, FieldEnd); + assert((Field == FieldEnd || !Field->isBitField()) && + "Failed to accumulate all the bitfields"); + } else if (Field->isZeroSize(Context)) { + // Empty fields have no storage. + ++Field; + } else { // Use base subobject layout for the potentially-overlapping field, // as it is done in RecordLayoutBuilder Members.push_back(MemberInfo( @@ -394,33 +402,36 @@ void CGRecordLowering::accumulateFields() { : getStorageType(*Field), *Field)); ++Field; - } else { - ++Field; } } } -void -CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field, +// Create members for bitfields. Field is a bitfield, and FieldEnd is the end +// iterator of the record. Return the first non-bitfield encountered. We need +// to know whether this is the base or complete layout, as virtual bases could +// affect the upper bound of bitfield access unit allocation. +RecordDecl::field_iterator +CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType, + RecordDecl::field_iterator Field, RecordDecl::field_iterator FieldEnd) { - // Run stores the first element of the current run of bitfields. FieldEnd is - // used as a special value to note that we don't have a current run. A - // bitfield run is a contiguous collection of bitfields that can be stored in - // the same storage block. Zero-sized bitfields and bitfields that would - // cross an alignment boundary break a run and start a new one. - RecordDecl::field_iterator Run = FieldEnd; - // Tail is the offset of the first bit off the end of the current run. It's - // used to determine if the ASTRecordLayout is treating these two bitfields as - // contiguous. StartBitOffset is offset of the beginning of the Run. - uint64_t StartBitOffset, Tail = 0; if (isDiscreteBitFieldABI()) { - for (; Field != FieldEnd; ++Field) { - uint64_t BitOffset = getFieldBitOffset(*Field); + // Run stores the first element of the current run of bitfields. FieldEnd is + // used as a special value to note that we don't have a current run. A + // bitfield run is a contiguous collection of bitfields that can be stored + // in the same storage block. Zero-sized bitfields and bitfields that would + // cross an alignment boundary break a run and start a new one. + RecordDecl::field_iterator Run = FieldEnd; + // Tail is the offset of the first bit off the end of the current run. It's + // used to determine if the ASTRecordLayout is treating these two bitfields + // as contiguous. StartBitOffset is offset of the beginning of the Run. + uint64_t StartBitOffset, Tail = 0; + for (; Field != FieldEnd && Field->isBitField(); ++Field) { // Zero-width bitfields end runs. if (Field->isZeroLengthBitField(Context)) { Run = FieldEnd; continue; } + uint64_t BitOffset = getFieldBitOffset(*Field); llvm::Type *Type = Types.ConvertTypeForMem(Field->getType(), /*ForBitField=*/true); // If we don't have a run yet, or don't live within the previous run's @@ -439,82 +450,256 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field, Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset), MemberInfo::Field, nullptr, *Field)); } - return; + return Field; } - // Check if OffsetInRecord (the size in bits of the current run) is better - // as a single field run. When OffsetInRecord has legal integer width, and - // its bitfield offset is naturally aligned, it is better to make the - // bitfield a separate storage component so as it can be accessed directly - // with lower cost. - auto IsBetterAsSingleFieldRun = [&](uint64_t OffsetInRecord, - uint64_t StartBitOffset) { - if (!Types.getCodeGenOpts().FineGrainedBitfieldAccesses) - return false; - if (OffsetInRecord < 8 || !llvm::isPowerOf2_64(OffsetInRecord) || - !DataLayout.fitsInLegalInteger(OffsetInRecord)) - return false; - // Make sure StartBitOffset is naturally aligned if it is treated as an - // IType integer. - if (StartBitOffset % - Context.toBits(getAlignment(getIntNType(OffsetInRecord))) != - 0) - return false; - return true; - }; + // The SysV ABI can overlap bitfield storage units with both other bitfield + // storage units /and/ other non-bitfield data members. Accessing a sequence + // of bitfields mustn't interfere with adjacent non-bitfields -- they're + // permitted to be accessed in separate threads for instance. + + // We split runs of bit-fields into a sequence of "access units". When we emit + // a load or store of a bit-field, we'll load/store the entire containing + // access unit. As mentioned, the standard requires that these loads and + // stores must not interfere with accesses to other memory locations, and it + // defines the bit-field's memory location as the current run of + // non-zero-width bit-fields. So an access unit must never overlap with + // non-bit-field storage or cross a zero-width bit-field. Otherwise, we're + // free to draw the lines as we see fit. + + // Drawing these lines well can be complicated. LLVM generally can't modify a + // program to access memory that it didn't before, so using very narrow access + // units can prevent the compiler from using optimal access patterns. For + // example, suppose a run of bit-fields occupies four bytes in a struct. If we + // split that into four 1-byte access units, then a sequence of assignments + // that doesn't touch all four bytes may have to be emitted with multiple + // 8-bit stores instead of a single 32-bit store. On the other hand, if we use + // very wide access units, we may find ourselves emitting accesses to + // bit-fields we didn't really need to touch, just because LLVM was unable to + // clean up after us. + + // It is desirable to have access units be aligned powers of 2 no larger than + // a register. (On non-strict alignment ISAs, the alignment requirement can be + // dropped.) A three byte access unit will be accessed using 2-byte and 1-byte + // accesses and bit manipulation. If no bitfield straddles across the two + // separate accesses, it is better to have separate 2-byte and 1-byte access + // units, as then LLVM will not generate unnecessary memory accesses, or bit + // manipulation. Similarly, on a strict-alignment architecture, it is better + // to keep access-units naturally aligned, to avoid similar bit + // manipulation synthesizing larger unaligned accesses. + + // Bitfields that share parts of a single byte are, of necessity, placed in + // the same access unit. That unit will encompass a consecutive run where + // adjacent bitfields share parts of a byte. (The first bitfield of such an + // access unit will start at the beginning of a byte.) + + // We then try and accumulate adjacent access units when the combined unit is + // naturally sized, no larger than a register, and (on a strict alignment + // ISA), naturally aligned. Note that this requires lookahead to one or more + // subsequent access units. For instance, consider a 2-byte access-unit + // followed by 2 1-byte units. We can merge that into a 4-byte access-unit, + // but we would not want to merge a 2-byte followed by a single 1-byte (and no + // available tail padding). We keep track of the best access unit seen so far, + // and use that when we determine we cannot accumulate any more. Then we start + // again at the bitfield following that best one. + + // The accumulation is also prevented when: + // *) it would cross a character-aigned zero-width bitfield, or + // *) fine-grained bitfield access option is in effect. + + CharUnits RegSize = + bitsToCharUnits(Context.getTargetInfo().getRegisterWidth()); + unsigned CharBits = Context.getCharWidth(); + + // Limit of useable tail padding at end of the record. Computed lazily and + // cached here. + CharUnits ScissorOffset = CharUnits::Zero(); + + // Data about the start of the span we're accumulating to create an access + // unit from. Begin is the first bitfield of the span. If Begin is FieldEnd, + // we've not got a current span. The span starts at the BeginOffset character + // boundary. BitSizeSinceBegin is the size (in bits) of the span -- this might + // include padding when we've advanced to a subsequent bitfield run. + RecordDecl::field_iterator Begin = FieldEnd; + CharUnits BeginOffset; + uint64_t BitSizeSinceBegin; + + // The (non-inclusive) end of the largest acceptable access unit we've found + // since Begin. If this is Begin, we're gathering the initial set of bitfields + // of a new span. BestEndOffset is the end of that acceptable access unit -- + // it might extend beyond the last character of the bitfield run, using + // available padding characters. + RecordDecl::field_iterator BestEnd = Begin; + CharUnits BestEndOffset; - // The start field is better as a single field run. - bool StartFieldAsSingleRun = false; for (;;) { - // Check to see if we need to start a new run. - if (Run == FieldEnd) { - // If we're out of fields, return. - if (Field == FieldEnd) + // AtAlignedBoundary is true iff Field is the (potential) start of a new + // span (or the end of the bitfields). When true, LimitOffset is the + // character offset of that span and Barrier indicates whether the new + // span cannot be merged into the current one. + bool AtAlignedBoundary = false; + bool Barrier = false; + + if (Field != FieldEnd && Field->isBitField()) { + uint64_t BitOffset = getFieldBitOffset(*Field); + if (Begin == FieldEnd) { + // Beginning a new span. + Begin = Field; + BestEnd = Begin; + + assert((BitOffset % CharBits) == 0 && "Not at start of char"); + BeginOffset = bitsToCharUnits(BitOffset); + BitSizeSinceBegin = 0; + } else if ((BitOffset % CharBits) != 0) { + // Bitfield occupies the same character as previous bitfield, it must be + // part of the same span. This can include zero-length bitfields, should + // the target not align them to character boundaries. Such non-alignment + // is at variance with the standards, which require zero-length + // bitfields be a barrier between access units. But of course we can't + // achieve that in the middle of a character. + assert(BitOffset == Context.toBits(BeginOffset) + BitSizeSinceBegin && + "Concatenating non-contiguous bitfields"); + } else { + // Bitfield potentially begins a new span. This includes zero-length + // bitfields on non-aligning targets that lie at character boundaries + // (those are barriers to merging). + if (Field->isZeroLengthBitField(Context)) + Barrier = true; + AtAlignedBoundary = true; + } + } else { + // We've reached the end of the bitfield run. Either we're done, or this + // is a barrier for the current span. + if (Begin == FieldEnd) break; - // Any non-zero-length bitfield can start a new run. - if (!Field->isZeroLengthBitField(Context)) { - Run = Field; - StartBitOffset = getFieldBitOffset(*Field); - Tail = StartBitOffset + Field->getBitWidthValue(Context); - StartFieldAsSingleRun = IsBetterAsSingleFieldRun(Tail - StartBitOffset, - StartBitOffset); + + Barrier = true; + AtAlignedBoundary = true; + } + + // InstallBest indicates whether we should create an access unit for the + // current best span: fields [Begin, BestEnd) occupying characters + // [BeginOffset, BestEndOffset). + bool InstallBest = false; + if (AtAlignedBoundary) { + // Field is the start of a new span or the end of the bitfields. The + // just-seen span now extends to BitSizeSinceBegin. + + // Determine if we can accumulate that just-seen span into the current + // accumulation. + CharUnits AccessSize = bitsToCharUnits(BitSizeSinceBegin + CharBits - 1); + if (BestEnd == Begin) { + // This is the initial run at the start of a new span. By definition, + // this is the best seen so far. + BestEnd = Field; + BestEndOffset = BeginOffset + AccessSize; + if (Types.getCodeGenOpts().FineGrainedBitfieldAccesses) + // Fine-grained access, so no merging of spans. + InstallBest = true; + else if (!BitSizeSinceBegin) + // A zero-sized initial span -- this will install nothing and reset + // for another. + InstallBest = true; + } else if (AccessSize > RegSize) + // Accumulating the just-seen span would create a multi-register access + // unit, which would increase register pressure. + InstallBest = true; + + if (!InstallBest) { + // Determine if accumulating the just-seen span will create an expensive + // access unit or not. + llvm::Type *Type = getIntNType(Context.toBits(AccessSize)); + if (!Context.getTargetInfo().hasCheapUnalignedBitFieldAccess()) { + // Unaligned accesses are expensive. Only accumulate if the new unit + // is naturally aligned. Otherwise install the best we have, which is + // either the initial access unit (can't do better), or a naturally + // aligned accumulation (since we would have already installed it if + // it wasn't naturally aligned). + CharUnits Align = getAlignment(Type); + if (Align > Layout.getAlignment()) + // The alignment required is greater than the containing structure + // itself. + InstallBest = true; + else if (!BeginOffset.isMultipleOf(Align)) + // The access unit is not at a naturally aligned offset within the + // structure. + InstallBest = true; + } + + if (!InstallBest) { + // Find the next used storage offset to determine what the limit of + // the current span is. That's either the offset of the next field + // with storage (which might be Field itself) or the end of the + // non-reusable tail padding. + CharUnits LimitOffset; + for (auto Probe = Field; Probe != FieldEnd; ++Probe) + if (!Probe->isZeroSize(Context)) { + // A member with storage sets the limit. + assert((getFieldBitOffset(*Probe) % CharBits) == 0 && + "Next storage is not byte-aligned"); + LimitOffset = bitsToCharUnits(getFieldBitOffset(*Probe)); + goto FoundLimit; + } + // We reached the end of the fields, determine the bounds of useable + // tail padding. As this can be complex for C++, we cache the result. + if (ScissorOffset.isZero()) { + ScissorOffset = calculateTailClippingOffset(isNonVirtualBaseType); + assert(!ScissorOffset.isZero() && "Tail clipping at zero"); + } + + LimitOffset = ScissorOffset; + FoundLimit:; + + CharUnits TypeSize = getSize(Type); + if (BeginOffset + TypeSize <= LimitOffset) { + // There is space before LimitOffset to create a naturally-sized + // access unit. + BestEndOffset = BeginOffset + TypeSize; + BestEnd = Field; + } + + if (Barrier) + // The next field is a barrier that we cannot merge across. + InstallBest = true; + else + // Otherwise, we're not installing. Update the bit size + // of the current span to go all the way to LimitOffset, which is + // the (aligned) offset of next bitfield to consider. + BitSizeSinceBegin = Context.toBits(LimitOffset - BeginOffset); + } } - ++Field; - continue; } - // If the start field of a new run is better as a single run, or - // if current field (or consecutive fields) is better as a single run, or - // if current field has zero width bitfield and either - // UseZeroLengthBitfieldAlignment or UseBitFieldTypeAlignment is set to - // true, or - // if the offset of current field is inconsistent with the offset of - // previous field plus its offset, - // skip the block below and go ahead to emit the storage. - // Otherwise, try to add bitfields to the run. - if (!StartFieldAsSingleRun && Field != FieldEnd && - !IsBetterAsSingleFieldRun(Tail - StartBitOffset, StartBitOffset) && - (!Field->isZeroLengthBitField(Context) || - (!Context.getTargetInfo().useZeroLengthBitfieldAlignment() && - !Context.getTargetInfo().useBitFieldTypeAlignment())) && - Tail == getFieldBitOffset(*Field)) { - Tail += Field->getBitWidthValue(Context); + if (InstallBest) { + assert((Field == FieldEnd || !Field->isBitField() || + (getFieldBitOffset(*Field) % CharBits) == 0) && + "Installing but not at an aligned bitfield or limit"); + CharUnits AccessSize = BestEndOffset - BeginOffset; + if (!AccessSize.isZero()) { + // Add the storage member for the access unit to the record. The + // bitfields get the offset of their storage but come afterward and + // remain there after a stable sort. + llvm::Type *Type = getIntNType(Context.toBits(AccessSize)); + Members.push_back(StorageInfo(BeginOffset, Type)); + for (; Begin != BestEnd; ++Begin) + if (!Begin->isZeroLengthBitField(Context)) + Members.push_back( + MemberInfo(BeginOffset, MemberInfo::Field, nullptr, *Begin)); + } + // Reset to start a new span. + Field = BestEnd; + Begin = FieldEnd; + } else { + assert(Field != FieldEnd && Field->isBitField() && + "Accumulating past end of bitfields"); + assert(!Barrier && "Accumulating across barrier"); + // Accumulate this bitfield into the current (potential) span. + BitSizeSinceBegin += Field->getBitWidthValue(Context); ++Field; - continue; } - - // We've hit a break-point in the run and need to emit a storage field. - llvm::Type *Type = getIntNType(Tail - StartBitOffset); - // Add the storage member to the record and set the bitfield info for all of - // the bitfields in the run. Bitfields get the offset of their storage but - // come afterward and remain there after a stable sort. - Members.push_back(StorageInfo(bitsToCharUnits(StartBitOffset), Type)); - for (; Run != Field; ++Run) - Members.push_back(MemberInfo(bitsToCharUnits(StartBitOffset), - MemberInfo::Field, nullptr, *Run)); - Run = FieldEnd; - StartFieldAsSingleRun = false; } + + return Field; } void CGRecordLowering::accumulateBases() { @@ -667,13 +852,17 @@ void CGRecordLowering::accumulateVPtrs() { llvm::PointerType::getUnqual(Types.getLLVMContext()))); } -void CGRecordLowering::accumulateVBases() { +CharUnits +CGRecordLowering::calculateTailClippingOffset(bool isNonVirtualBaseType) const { + if (!RD) + return Layout.getDataSize(); + CharUnits ScissorOffset = Layout.getNonVirtualSize(); // In the itanium ABI, it's possible to place a vbase at a dsize that is // smaller than the nvsize. Here we check to see if such a base is placed // before the nvsize and set the scissor offset to that, instead of the // nvsize. - if (isOverlappingVBaseABI()) + if (!isNonVirtualBaseType && isOverlappingVBaseABI()) for (const auto &Base : RD->vbases()) { const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); if (BaseDecl->isEmpty()) @@ -685,8 +874,13 @@ void CGRecordLowering::accumulateVBases() { ScissorOffset = std::min(ScissorOffset, Layout.getVBaseClassOffset(BaseDecl)); } - Members.push_back(MemberInfo(ScissorOffset, MemberInfo::Scissor, nullptr, - RD)); + + return ScissorOffset; +} + +void CGRecordLowering::accumulateVBases() { + Members.push_back(MemberInfo(calculateTailClippingOffset(false), + MemberInfo::Scissor, nullptr, RD)); for (const auto &Base : RD->vbases()) { const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); if (BaseDecl->isEmpty()) @@ -711,7 +905,7 @@ void CGRecordLowering::accumulateVBases() { } bool CGRecordLowering::hasOwnStorage(const CXXRecordDecl *Decl, - const CXXRecordDecl *Query) { + const CXXRecordDecl *Query) const { const ASTRecordLayout &DeclLayout = Context.getASTRecordLayout(Decl); if (DeclLayout.isPrimaryBaseVirtual() && DeclLayout.getPrimaryBase() == Query) return false; diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 8898e3f22a7df6d6ff8cd69b5255279d3ed8005a..576fe2f7a2d46f41aa6c60b4139a28753fd3314f 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -1341,10 +1341,8 @@ struct SaveRetExprRAII { }; } // namespace -/// If we have 'return f(...);', where both caller and callee are SwiftAsync, -/// codegen it as 'tail call ...; ret void;'. -static void makeTailCallIfSwiftAsync(const CallExpr *CE, CGBuilderTy &Builder, - const CGFunctionInfo *CurFnInfo) { +/// Determine if the given call uses the swiftasync calling convention. +static bool isSwiftAsyncCallee(const CallExpr *CE) { auto calleeQualType = CE->getCallee()->getType(); const FunctionType *calleeType = nullptr; if (calleeQualType->isFunctionPointerType() || @@ -1359,18 +1357,12 @@ static void makeTailCallIfSwiftAsync(const CallExpr *CE, CGBuilderTy &Builder, // getMethodDecl() doesn't handle member pointers at the moment. calleeType = methodDecl->getType()->castAs<FunctionType>(); } else { - return; + return false; } } else { - return; - } - if (calleeType->getCallConv() == CallingConv::CC_SwiftAsync && - (CurFnInfo->getASTCallingConvention() == CallingConv::CC_SwiftAsync)) { - auto CI = cast<llvm::CallInst>(&Builder.GetInsertBlock()->back()); - CI->setTailCallKind(llvm::CallInst::TCK_MustTail); - Builder.CreateRetVoid(); - Builder.ClearInsertionPoint(); + return false; } + return calleeType->getCallConv() == CallingConv::CC_SwiftAsync; } /// EmitReturnStmt - Note that due to GCC extensions, this can have an operand @@ -1410,6 +1402,19 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { RunCleanupsScope cleanupScope(*this); if (const auto *EWC = dyn_cast_or_null<ExprWithCleanups>(RV)) RV = EWC->getSubExpr(); + + // If we're in a swiftasynccall function, and the return expression is a + // call to a swiftasynccall function, mark the call as the musttail call. + std::optional<llvm::SaveAndRestore<const CallExpr *>> SaveMustTail; + if (RV && CurFnInfo && + CurFnInfo->getASTCallingConvention() == CallingConv::CC_SwiftAsync) { + if (auto CE = dyn_cast<CallExpr>(RV)) { + if (isSwiftAsyncCallee(CE)) { + SaveMustTail.emplace(MustTailCall, CE); + } + } + } + // FIXME: Clean this up by using an LValue for ReturnTemp, // EmitStoreThroughLValue, and EmitAnyExpr. // Check if the NRVO candidate was not globalized in OpenMP mode. @@ -1432,8 +1437,6 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { // for side effects. if (RV) { EmitAnyExpr(RV); - if (auto *CE = dyn_cast<CallExpr>(RV)) - makeTailCallIfSwiftAsync(CE, Builder, CurFnInfo); } } else if (!RV) { // Do nothing (return value is left uninitialized) @@ -2291,7 +2294,7 @@ std::pair<llvm::Value*, llvm::Type *> CodeGenFunction::EmitAsmInputLValue( Address Addr = InputValue.getAddress(*this); ConstraintStr += '*'; - return {Addr.getPointer(), Addr.getElementType()}; + return {InputValue.getPointer(*this), Addr.getElementType()}; } std::pair<llvm::Value *, llvm::Type *> @@ -2698,7 +2701,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { ArgTypes.push_back(DestAddr.getType()); ArgElemTypes.push_back(DestAddr.getElementType()); - Args.push_back(DestAddr.getPointer()); + Args.push_back(DestAddr.emitRawPointer(*this)); Constraints += "=*"; Constraints += OutputConstraint; ReadOnly = ReadNone = false; @@ -3073,8 +3076,8 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) { CapturedStmtInfo->setContextValue(Builder.CreateLoad(DeclPtr)); // Initialize variable-length arrays. - LValue Base = MakeNaturalAlignAddrLValue(CapturedStmtInfo->getContextValue(), - Ctx.getTagDeclType(RD)); + LValue Base = MakeNaturalAlignRawAddrLValue( + CapturedStmtInfo->getContextValue(), Ctx.getTagDeclType(RD)); for (auto *FD : RD->fields()) { if (FD->hasCapturedVLAType()) { auto *ExprArg = diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 452ce6983f6ac195785cbc0e508e5b46941dd206..e6d504bcdeca5b4e86d7f04974e8dd4713c2d0c0 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -350,7 +350,8 @@ void CodeGenFunction::GenerateOpenMPCapturedVars( LValue DstLV = MakeAddrLValue(DstAddr, Ctx.getUIntPtrType()); llvm::Value *SrcAddrVal = EmitScalarConversion( - DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()), + DstAddr.emitRawPointer(*this), + Ctx.getPointerType(Ctx.getUIntPtrType()), Ctx.getPointerType(CurField->getType()), CurCap->getLocation()); LValue SrcLV = MakeNaturalAlignAddrLValue(SrcAddrVal, CurField->getType()); @@ -364,7 +365,8 @@ void CodeGenFunction::GenerateOpenMPCapturedVars( CapturedVars.push_back(CV); } else { assert(CurCap->capturesVariable() && "Expected capture by reference."); - CapturedVars.push_back(EmitLValue(*I).getAddress(*this).getPointer()); + CapturedVars.push_back( + EmitLValue(*I).getAddress(*this).emitRawPointer(*this)); } } } @@ -375,8 +377,9 @@ static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, ASTContext &Ctx = CGF.getContext(); llvm::Value *CastedPtr = CGF.EmitScalarConversion( - AddrLV.getAddress(CGF).getPointer(), Ctx.getUIntPtrType(), + AddrLV.getAddress(CGF).emitRawPointer(CGF), Ctx.getUIntPtrType(), Ctx.getPointerType(DstType), Loc); + // FIXME: should the pointee type (DstType) be passed? Address TmpAddr = CGF.MakeNaturalAlignAddrLValue(CastedPtr, DstType).getAddress(CGF); return TmpAddr; @@ -702,8 +705,8 @@ void CodeGenFunction::EmitOMPAggregateAssign( llvm::Value *NumElements = emitArrayLength(ArrayTy, ElementTy, DestAddr); SrcAddr = SrcAddr.withElementType(DestAddr.getElementType()); - llvm::Value *SrcBegin = SrcAddr.getPointer(); - llvm::Value *DestBegin = DestAddr.getPointer(); + llvm::Value *SrcBegin = SrcAddr.emitRawPointer(*this); + llvm::Value *DestBegin = DestAddr.emitRawPointer(*this); // Cast from pointer to array type to pointer to single element. llvm::Value *DestEnd = Builder.CreateInBoundsGEP(DestAddr.getElementType(), DestBegin, NumElements); @@ -1007,10 +1010,10 @@ bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) { CopyBegin = createBasicBlock("copyin.not.master"); CopyEnd = createBasicBlock("copyin.not.master.end"); // TODO: Avoid ptrtoint conversion. - auto *MasterAddrInt = - Builder.CreatePtrToInt(MasterAddr.getPointer(), CGM.IntPtrTy); - auto *PrivateAddrInt = - Builder.CreatePtrToInt(PrivateAddr.getPointer(), CGM.IntPtrTy); + auto *MasterAddrInt = Builder.CreatePtrToInt( + MasterAddr.emitRawPointer(*this), CGM.IntPtrTy); + auto *PrivateAddrInt = Builder.CreatePtrToInt( + PrivateAddr.emitRawPointer(*this), CGM.IntPtrTy); Builder.CreateCondBr( Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin, CopyEnd); @@ -1666,7 +1669,7 @@ Address CodeGenFunction::OMPBuilderCBHelpers::getAddrOfThreadPrivate( llvm::Type *VarTy = VDAddr.getElementType(); llvm::Value *Data = - CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.Int8PtrTy); + CGF.Builder.CreatePointerCast(VDAddr.emitRawPointer(CGF), CGM.Int8PtrTy); llvm::ConstantInt *Size = CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)); std::string Suffix = getNameWithSeparators({"cache", ""}); llvm::Twine CacheName = Twine(CGM.getMangledName(VD)).concat(Suffix); @@ -2045,7 +2048,7 @@ void CodeGenFunction::EmitOMPCanonicalLoop(const OMPCanonicalLoop *S) { ->getParam(0) ->getType() .getNonReferenceType(); - Address CountAddr = CreateMemTemp(LogicalTy, ".count.addr"); + RawAddress CountAddr = CreateMemTemp(LogicalTy, ".count.addr"); emitCapturedStmtCall(*this, DistanceClosure, {CountAddr.getPointer()}); llvm::Value *DistVal = Builder.CreateLoad(CountAddr, ".count"); @@ -2061,7 +2064,7 @@ void CodeGenFunction::EmitOMPCanonicalLoop(const OMPCanonicalLoop *S) { LValue LCVal = EmitLValue(LoopVarRef); Address LoopVarAddress = LCVal.getAddress(*this); emitCapturedStmtCall(*this, LoopVarClosure, - {LoopVarAddress.getPointer(), IndVar}); + {LoopVarAddress.emitRawPointer(*this), IndVar}); RunCleanupsScope BodyScope(*this); EmitStmt(BodyStmt); @@ -4749,10 +4752,10 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo()) (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue, CGF.Builder, false); - llvm::Instruction &Last = CGF.Builder.GetInsertBlock()->back(); // Get the call dbg.declare instruction we just created and update // its DIExpression to add offset to base address. - if (auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&Last)) { + auto UpdateExpr = [](llvm::LLVMContext &Ctx, auto *Declare, + unsigned Offset) { SmallVector<uint64_t, 8> Ops; // Add offset to the base address if non zero. if (Offset) { @@ -4760,9 +4763,21 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( Ops.push_back(Offset); } Ops.push_back(llvm::dwarf::DW_OP_deref); - auto &Ctx = DDI->getContext(); - llvm::DIExpression *DIExpr = llvm::DIExpression::get(Ctx, Ops); - Last.setOperand(2, llvm::MetadataAsValue::get(Ctx, DIExpr)); + Declare->setExpression(llvm::DIExpression::get(Ctx, Ops)); + }; + llvm::Instruction &Last = CGF.Builder.GetInsertBlock()->back(); + if (auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&Last)) + UpdateExpr(DDI->getContext(), DDI, Offset); + // If we're emitting using the new debug info format into a block + // without a terminator, the record will be "trailing". + assert(!Last.isTerminator() && "unexpected terminator"); + if (auto *Marker = + CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) { + for (llvm::DbgVariableRecord &DVR : llvm::reverse( + llvm::filterDbgVars(Marker->getDbgRecordRange()))) { + UpdateExpr(Last.getContext(), &DVR, Offset); + break; + } } } } @@ -4783,7 +4798,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( ParamTypes.push_back(PrivatesPtr->getType()); for (const Expr *E : Data.PrivateVars) { const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - Address PrivatePtr = CGF.CreateMemTemp( + RawAddress PrivatePtr = CGF.CreateMemTemp( CGF.getContext().getPointerType(E->getType()), ".priv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); CallArgs.push_back(PrivatePtr.getPointer()); @@ -4791,7 +4806,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( } for (const Expr *E : Data.FirstprivateVars) { const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - Address PrivatePtr = + RawAddress PrivatePtr = CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), ".firstpriv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); @@ -4801,7 +4816,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( } for (const Expr *E : Data.LastprivateVars) { const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - Address PrivatePtr = + RawAddress PrivatePtr = CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), ".lastpriv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); @@ -4814,7 +4829,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( Ty = CGF.getContext().getPointerType(Ty); if (isAllocatableDecl(VD)) Ty = CGF.getContext().getPointerType(Ty); - Address PrivatePtr = CGF.CreateMemTemp( + RawAddress PrivatePtr = CGF.CreateMemTemp( CGF.getContext().getPointerType(Ty), ".local.ptr.addr"); auto Result = UntiedLocalVars.insert( std::make_pair(VD, std::make_pair(PrivatePtr, Address::invalid()))); @@ -4847,7 +4862,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( if (auto *DI = CGF.getDebugInfo()) if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo()) (void)DI->EmitDeclareOfAutoVariable( - Pair.first, Pair.second.getPointer(), CGF.Builder, + Pair.first, Pair.second.getBasePointer(), CGF.Builder, /*UsePointerValue*/ true); } // Adjust mapping for internal locals by mapping actual memory instead of @@ -4900,14 +4915,14 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( RedCG, Cnt); Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem( CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); - Replacement = - Address(CGF.EmitScalarConversion( - Replacement.getPointer(), CGF.getContext().VoidPtrTy, - CGF.getContext().getPointerType( - Data.ReductionCopies[Cnt]->getType()), - Data.ReductionCopies[Cnt]->getExprLoc()), - CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), - Replacement.getAlignment()); + Replacement = Address( + CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF), + CGF.getContext().VoidPtrTy, + CGF.getContext().getPointerType( + Data.ReductionCopies[Cnt]->getType()), + Data.ReductionCopies[Cnt]->getExprLoc()), + CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), + Replacement.getAlignment()); Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement); Scope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement); } @@ -4958,7 +4973,7 @@ void CodeGenFunction::EmitOMPTaskBasedDirective( CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); Replacement = Address( CGF.EmitScalarConversion( - Replacement.getPointer(), CGF.getContext().VoidPtrTy, + Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy, CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()), InRedPrivs[Cnt]->getExprLoc()), CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()), @@ -5077,7 +5092,7 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective( // If there is no user-defined mapper, the mapper array will be nullptr. In // this case, we don't need to privatize it. if (!isa_and_nonnull<llvm::ConstantPointerNull>( - InputInfo.MappersArray.getPointer())) { + InputInfo.MappersArray.emitRawPointer(*this))) { MVD = createImplicitFirstprivateForType( getContext(), Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc()); TargetScope.addPrivate(MVD, InputInfo.MappersArray); @@ -5103,7 +5118,7 @@ void CodeGenFunction::EmitOMPTargetTaskBasedDirective( ParamTypes.push_back(PrivatesPtr->getType()); for (const Expr *E : Data.FirstprivateVars) { const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); - Address PrivatePtr = + RawAddress PrivatePtr = CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()), ".firstpriv.ptr.addr"); PrivatePtrs.emplace_back(VD, PrivatePtr); @@ -5182,14 +5197,14 @@ void CodeGenFunction::processInReduction(const OMPExecutableDirective &S, RedCG, Cnt); Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem( CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); - Replacement = - Address(CGF.EmitScalarConversion( - Replacement.getPointer(), CGF.getContext().VoidPtrTy, - CGF.getContext().getPointerType( - Data.ReductionCopies[Cnt]->getType()), - Data.ReductionCopies[Cnt]->getExprLoc()), - CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), - Replacement.getAlignment()); + Replacement = Address( + CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF), + CGF.getContext().VoidPtrTy, + CGF.getContext().getPointerType( + Data.ReductionCopies[Cnt]->getType()), + Data.ReductionCopies[Cnt]->getExprLoc()), + CGF.ConvertTypeForMem(Data.ReductionCopies[Cnt]->getType()), + Replacement.getAlignment()); Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement); Scope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement); } @@ -5235,7 +5250,7 @@ void CodeGenFunction::processInReduction(const OMPExecutableDirective &S, CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt)); Replacement = Address( CGF.EmitScalarConversion( - Replacement.getPointer(), CGF.getContext().VoidPtrTy, + Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy, CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()), InRedPrivs[Cnt]->getExprLoc()), CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()), @@ -5382,7 +5397,7 @@ void CodeGenFunction::EmitOMPDepobjDirective(const OMPDepobjDirective &S) { Dependencies.DepExprs.append(DC->varlist_begin(), DC->varlist_end()); Address DepAddr = CGM.getOpenMPRuntime().emitDepobjDependClause( *this, Dependencies, DC->getBeginLoc()); - EmitStoreOfScalar(DepAddr.getPointer(), DOLVal); + EmitStoreOfScalar(DepAddr.emitRawPointer(*this), DOLVal); return; } if (const auto *DC = S.getSingleClause<OMPDestroyClause>()) { @@ -6459,21 +6474,21 @@ static void emitOMPAtomicCompareExpr( D->getType()->hasSignedIntegerRepresentation()); llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{ - XAddr.getPointer(), XAddr.getElementType(), + XAddr.emitRawPointer(CGF), XAddr.getElementType(), X->getType()->hasSignedIntegerRepresentation(), X->getType().isVolatileQualified()}; llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal; if (V) { LValue LV = CGF.EmitLValue(V); Address Addr = LV.getAddress(CGF); - VOpVal = {Addr.getPointer(), Addr.getElementType(), + VOpVal = {Addr.emitRawPointer(CGF), Addr.getElementType(), V->getType()->hasSignedIntegerRepresentation(), V->getType().isVolatileQualified()}; } if (R) { LValue LV = CGF.EmitLValue(R); Address Addr = LV.getAddress(CGF); - ROpVal = {Addr.getPointer(), Addr.getElementType(), + ROpVal = {Addr.emitRawPointer(CGF), Addr.getElementType(), R->getType()->hasSignedIntegerRepresentation(), R->getType().isVolatileQualified()}; } @@ -7017,7 +7032,7 @@ void CodeGenFunction::EmitOMPInteropDirective(const OMPInteropDirective &S) { std::tie(NumDependences, DependenciesArray) = CGM.getOpenMPRuntime().emitDependClause(*this, Data.Dependences, S.getBeginLoc()); - DependenceList = DependenciesArray.getPointer(); + DependenceList = DependenciesArray.emitRawPointer(*this); } Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>(); diff --git a/clang/lib/CodeGen/CGVTT.cpp b/clang/lib/CodeGen/CGVTT.cpp index 1d3f14f1c5344d7abe35debea62969a2c45a6998..d2376b14dd5826142c437ab47f26d98599a0e794 100644 --- a/clang/lib/CodeGen/CGVTT.cpp +++ b/clang/lib/CodeGen/CGVTT.cpp @@ -77,9 +77,18 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT, llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.AddressPointIndex), }; + // Add inrange attribute to indicate that only the VTableIndex can be + // accessed. + unsigned ComponentSize = + CGM.getDataLayout().getTypeAllocSize(getVTableComponentType()); + unsigned VTableSize = CGM.getDataLayout().getTypeAllocSize( + cast<llvm::StructType>(VTable->getValueType()) + ->getElementType(AddressPoint.VTableIndex)); + unsigned Offset = ComponentSize * AddressPoint.AddressPointIndex; + llvm::ConstantRange InRange(llvm::APInt(32, -Offset, true), + llvm::APInt(32, VTableSize - Offset, true)); llvm::Constant *Init = llvm::ConstantExpr::getGetElementPtr( - VTable->getValueType(), VTable, Idxs, /*InBounds=*/true, - /*InRangeIndex=*/1); + VTable->getValueType(), VTable, Idxs, /*InBounds=*/true, InRange); VTTComponents.push_back(Init); } diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 8dee3f74b44b4e66edfc8b2ffd1c41514671496b..862369ae009f4808c73cc0b32cd11101261fd4ba 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -201,14 +201,13 @@ CodeGenFunction::GenerateVarArgsThunk(llvm::Function *Fn, // Find the first store of "this", which will be to the alloca associated // with "this". - Address ThisPtr = - Address(&*AI, ConvertTypeForMem(MD->getFunctionObjectParameterType()), - CGM.getClassPointerAlignment(MD->getParent())); + Address ThisPtr = makeNaturalAddressForPointer( + &*AI, MD->getFunctionObjectParameterType(), + CGM.getClassPointerAlignment(MD->getParent())); llvm::BasicBlock *EntryBB = &Fn->front(); llvm::BasicBlock::iterator ThisStore = llvm::find_if(*EntryBB, [&](llvm::Instruction &I) { - return isa<llvm::StoreInst>(I) && - I.getOperand(0) == ThisPtr.getPointer(); + return isa<llvm::StoreInst>(I) && I.getOperand(0) == &*AI; }); assert(ThisStore != EntryBB->end() && "Store of this should be in entry block?"); diff --git a/clang/lib/CodeGen/CGValue.h b/clang/lib/CodeGen/CGValue.h index 1e6f67250583d66fda9c2552d61ce1e9ea629695..cc9ad10ae5969df3c30eac0f9db5234349af9ae6 100644 --- a/clang/lib/CodeGen/CGValue.h +++ b/clang/lib/CodeGen/CGValue.h @@ -14,12 +14,13 @@ #ifndef LLVM_CLANG_LIB_CODEGEN_CGVALUE_H #define LLVM_CLANG_LIB_CODEGEN_CGVALUE_H +#include "Address.h" +#include "CodeGenTBAA.h" +#include "EHScopeStack.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Type.h" -#include "llvm/IR/Value.h" #include "llvm/IR/Type.h" -#include "Address.h" -#include "CodeGenTBAA.h" +#include "llvm/IR/Value.h" namespace llvm { class Constant; @@ -28,57 +29,64 @@ namespace llvm { namespace clang { namespace CodeGen { - class AggValueSlot; - class CodeGenFunction; - struct CGBitFieldInfo; +class AggValueSlot; +class CGBuilderTy; +class CodeGenFunction; +struct CGBitFieldInfo; /// RValue - This trivial value class is used to represent the result of an /// expression that is evaluated. It can be one of three things: either a /// simple LLVM SSA value, a pair of SSA values for complex numbers, or the /// address of an aggregate value in memory. class RValue { - enum Flavor { Scalar, Complex, Aggregate }; + friend struct DominatingValue<RValue>; - // The shift to make to an aggregate's alignment to make it look - // like a pointer. - enum { AggAlignShift = 4 }; + enum FlavorEnum { Scalar, Complex, Aggregate }; - // Stores first value and flavor. - llvm::PointerIntPair<llvm::Value *, 2, Flavor> V1; - // Stores second value and volatility. - llvm::PointerIntPair<llvm::Value *, 1, bool> V2; - // Stores element type for aggregate values. - llvm::Type *ElementType; + union { + // Stores first and second value. + struct { + llvm::Value *first; + llvm::Value *second; + } Vals; + + // Stores aggregate address. + Address AggregateAddr; + }; + + unsigned IsVolatile : 1; + unsigned Flavor : 2; public: - bool isScalar() const { return V1.getInt() == Scalar; } - bool isComplex() const { return V1.getInt() == Complex; } - bool isAggregate() const { return V1.getInt() == Aggregate; } + RValue() : Vals{nullptr, nullptr}, Flavor(Scalar) {} + + bool isScalar() const { return Flavor == Scalar; } + bool isComplex() const { return Flavor == Complex; } + bool isAggregate() const { return Flavor == Aggregate; } - bool isVolatileQualified() const { return V2.getInt(); } + bool isVolatileQualified() const { return IsVolatile; } /// getScalarVal() - Return the Value* of this scalar value. llvm::Value *getScalarVal() const { assert(isScalar() && "Not a scalar!"); - return V1.getPointer(); + return Vals.first; } /// getComplexVal - Return the real/imag components of this complex value. /// std::pair<llvm::Value *, llvm::Value *> getComplexVal() const { - return std::make_pair(V1.getPointer(), V2.getPointer()); + return std::make_pair(Vals.first, Vals.second); } /// getAggregateAddr() - Return the Value* of the address of the aggregate. Address getAggregateAddress() const { assert(isAggregate() && "Not an aggregate!"); - auto align = reinterpret_cast<uintptr_t>(V2.getPointer()) >> AggAlignShift; - return Address( - V1.getPointer(), ElementType, CharUnits::fromQuantity(align)); + return AggregateAddr; } - llvm::Value *getAggregatePointer() const { - assert(isAggregate() && "Not an aggregate!"); - return V1.getPointer(); + + llvm::Value *getAggregatePointer(QualType PointeeType, + CodeGenFunction &CGF) const { + return getAggregateAddress().getBasePointer(); } static RValue getIgnored() { @@ -88,17 +96,19 @@ public: static RValue get(llvm::Value *V) { RValue ER; - ER.V1.setPointer(V); - ER.V1.setInt(Scalar); - ER.V2.setInt(false); + ER.Vals.first = V; + ER.Flavor = Scalar; + ER.IsVolatile = false; return ER; } + static RValue get(Address Addr, CodeGenFunction &CGF) { + return RValue::get(Addr.emitRawPointer(CGF)); + } static RValue getComplex(llvm::Value *V1, llvm::Value *V2) { RValue ER; - ER.V1.setPointer(V1); - ER.V2.setPointer(V2); - ER.V1.setInt(Complex); - ER.V2.setInt(false); + ER.Vals = {V1, V2}; + ER.Flavor = Complex; + ER.IsVolatile = false; return ER; } static RValue getComplex(const std::pair<llvm::Value *, llvm::Value *> &C) { @@ -107,15 +117,15 @@ public: // FIXME: Aggregate rvalues need to retain information about whether they are // volatile or not. Remove default to find all places that probably get this // wrong. + + /// Convert an Address to an RValue. If the Address is not + /// signed, create an RValue using the unsigned address. Otherwise, resign the + /// address using the provided type. static RValue getAggregate(Address addr, bool isVolatile = false) { RValue ER; - ER.V1.setPointer(addr.getPointer()); - ER.V1.setInt(Aggregate); - ER.ElementType = addr.getElementType(); - - auto align = static_cast<uintptr_t>(addr.getAlignment().getQuantity()); - ER.V2.setPointer(reinterpret_cast<llvm::Value*>(align << AggAlignShift)); - ER.V2.setInt(isVolatile); + ER.AggregateAddr = addr; + ER.Flavor = Aggregate; + ER.IsVolatile = isVolatile; return ER; } }; @@ -178,8 +188,10 @@ class LValue { MatrixElt // This is a matrix element, use getVector* } LVType; - llvm::Value *V; - llvm::Type *ElementType; + union { + Address Addr = Address::invalid(); + llvm::Value *V; + }; union { // Index into a vector subscript: V[i] @@ -197,10 +209,6 @@ class LValue { // 'const' is unused here Qualifiers Quals; - // The alignment to use when accessing this lvalue. (For vector elements, - // this is the alignment of the whole vector.) - unsigned Alignment; - // objective-c's ivar bool Ivar:1; @@ -234,23 +242,19 @@ class LValue { Expr *BaseIvarExp; private: - void Initialize(QualType Type, Qualifiers Quals, CharUnits Alignment, + void Initialize(QualType Type, Qualifiers Quals, Address Addr, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { - assert((!Alignment.isZero() || Type->isIncompleteType()) && - "initializing l-value with zero alignment!"); - if (isGlobalReg()) - assert(ElementType == nullptr && "Global reg does not store elem type"); - else - assert(ElementType != nullptr && "Must have elem type"); - this->Type = Type; this->Quals = Quals; const unsigned MaxAlign = 1U << 31; - this->Alignment = Alignment.getQuantity() <= MaxAlign - ? Alignment.getQuantity() - : MaxAlign; - assert(this->Alignment == Alignment.getQuantity() && - "Alignment exceeds allowed max!"); + CharUnits Alignment = Addr.getAlignment(); + assert((isGlobalReg() || !Alignment.isZero() || Type->isIncompleteType()) && + "initializing l-value with zero alignment!"); + if (Alignment.getQuantity() > MaxAlign) { + assert(false && "Alignment exceeds allowed max!"); + Alignment = CharUnits::fromQuantity(MaxAlign); + } + this->Addr = Addr; this->BaseInfo = BaseInfo; this->TBAAInfo = TBAAInfo; @@ -259,9 +263,20 @@ private: this->ImpreciseLifetime = false; this->Nontemporal = false; this->ThreadLocalRef = false; + this->IsKnownNonNull = false; this->BaseIvarExp = nullptr; } + void initializeSimpleLValue(Address Addr, QualType Type, + LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, + ASTContext &Context) { + Qualifiers QS = Type.getQualifiers(); + QS.setObjCGCAttr(Context.getObjCGCAttrKind(Type)); + LVType = Simple; + Initialize(Type, QS, Addr, BaseInfo, TBAAInfo); + assert(Addr.getBasePointer()->getType()->isPointerTy()); + } + public: bool isSimple() const { return LVType == Simple; } bool isVectorElt() const { return LVType == VectorElt; } @@ -328,8 +343,8 @@ public: LangAS getAddressSpace() const { return Quals.getAddressSpace(); } - CharUnits getAlignment() const { return CharUnits::fromQuantity(Alignment); } - void setAlignment(CharUnits A) { Alignment = A.getQuantity(); } + CharUnits getAlignment() const { return Addr.getAlignment(); } + void setAlignment(CharUnits A) { Addr.setAlignment(A); } LValueBaseInfo getBaseInfo() const { return BaseInfo; } void setBaseInfo(LValueBaseInfo Info) { BaseInfo = Info; } @@ -345,28 +360,32 @@ public: // simple lvalue llvm::Value *getPointer(CodeGenFunction &CGF) const { assert(isSimple()); - return V; + return Addr.getBasePointer(); } - Address getAddress(CodeGenFunction &CGF) const { - return Address(getPointer(CGF), ElementType, getAlignment(), - isKnownNonNull()); - } - void setAddress(Address address) { + llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { assert(isSimple()); - V = address.getPointer(); - ElementType = address.getElementType(); - Alignment = address.getAlignment().getQuantity(); - IsKnownNonNull = address.isKnownNonNull(); + return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; } + Address getAddress(CodeGenFunction &CGF) const { + // FIXME: remove parameter. + return Addr; + } + + void setAddress(Address address) { Addr = address; } + // vector elt lvalue Address getVectorAddress() const { - return Address(getVectorPointer(), ElementType, getAlignment(), - (KnownNonNull_t)isKnownNonNull()); + assert(isVectorElt()); + return Addr; + } + llvm::Value *getRawVectorPointer(CodeGenFunction &CGF) const { + assert(isVectorElt()); + return Addr.emitRawPointer(CGF); } llvm::Value *getVectorPointer() const { assert(isVectorElt()); - return V; + return Addr.getBasePointer(); } llvm::Value *getVectorIdx() const { assert(isVectorElt()); @@ -374,12 +393,12 @@ public: } Address getMatrixAddress() const { - return Address(getMatrixPointer(), ElementType, getAlignment(), - (KnownNonNull_t)isKnownNonNull()); + assert(isMatrixElt()); + return Addr; } llvm::Value *getMatrixPointer() const { assert(isMatrixElt()); - return V; + return Addr.getBasePointer(); } llvm::Value *getMatrixIdx() const { assert(isMatrixElt()); @@ -388,12 +407,12 @@ public: // extended vector elements. Address getExtVectorAddress() const { - return Address(getExtVectorPointer(), ElementType, getAlignment(), - (KnownNonNull_t)isKnownNonNull()); + assert(isExtVectorElt()); + return Addr; } - llvm::Value *getExtVectorPointer() const { + llvm::Value *getRawExtVectorPointer(CodeGenFunction &CGF) const { assert(isExtVectorElt()); - return V; + return Addr.emitRawPointer(CGF); } llvm::Constant *getExtVectorElts() const { assert(isExtVectorElt()); @@ -402,10 +421,14 @@ public: // bitfield lvalue Address getBitFieldAddress() const { - return Address(getBitFieldPointer(), ElementType, getAlignment(), - (KnownNonNull_t)isKnownNonNull()); + assert(isBitField()); + return Addr; + } + llvm::Value *getRawBitFieldPointer(CodeGenFunction &CGF) const { + assert(isBitField()); + return Addr.emitRawPointer(CGF); } - llvm::Value *getBitFieldPointer() const { assert(isBitField()); return V; } + const CGBitFieldInfo &getBitFieldInfo() const { assert(isBitField()); return *BitFieldInfo; @@ -414,18 +437,13 @@ public: // global register lvalue llvm::Value *getGlobalReg() const { assert(isGlobalReg()); return V; } - static LValue MakeAddr(Address address, QualType type, ASTContext &Context, + static LValue MakeAddr(Address Addr, QualType type, ASTContext &Context, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { - Qualifiers qs = type.getQualifiers(); - qs.setObjCGCAttr(Context.getObjCGCAttrKind(type)); - LValue R; R.LVType = Simple; - assert(address.getPointer()->getType()->isPointerTy()); - R.V = address.getPointer(); - R.ElementType = address.getElementType(); - R.IsKnownNonNull = address.isKnownNonNull(); - R.Initialize(type, qs, address.getAlignment(), BaseInfo, TBAAInfo); + R.initializeSimpleLValue(Addr, type, BaseInfo, TBAAInfo, Context); + R.Addr = Addr; + assert(Addr.getType()->isPointerTy()); return R; } @@ -434,26 +452,18 @@ public: TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = VectorElt; - R.V = vecAddress.getPointer(); - R.ElementType = vecAddress.getElementType(); R.VectorIdx = Idx; - R.IsKnownNonNull = vecAddress.isKnownNonNull(); - R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(), - BaseInfo, TBAAInfo); + R.Initialize(type, type.getQualifiers(), vecAddress, BaseInfo, TBAAInfo); return R; } - static LValue MakeExtVectorElt(Address vecAddress, llvm::Constant *Elts, + static LValue MakeExtVectorElt(Address Addr, llvm::Constant *Elts, QualType type, LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = ExtVectorElt; - R.V = vecAddress.getPointer(); - R.ElementType = vecAddress.getElementType(); R.VectorElts = Elts; - R.IsKnownNonNull = vecAddress.isKnownNonNull(); - R.Initialize(type, type.getQualifiers(), vecAddress.getAlignment(), - BaseInfo, TBAAInfo); + R.Initialize(type, type.getQualifiers(), Addr, BaseInfo, TBAAInfo); return R; } @@ -468,12 +478,8 @@ public: TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = BitField; - R.V = Addr.getPointer(); - R.ElementType = Addr.getElementType(); R.BitFieldInfo = &Info; - R.IsKnownNonNull = Addr.isKnownNonNull(); - R.Initialize(type, type.getQualifiers(), Addr.getAlignment(), BaseInfo, - TBAAInfo); + R.Initialize(type, type.getQualifiers(), Addr, BaseInfo, TBAAInfo); return R; } @@ -481,11 +487,9 @@ public: QualType type) { LValue R; R.LVType = GlobalReg; - R.V = V; - R.ElementType = nullptr; - R.IsKnownNonNull = true; - R.Initialize(type, type.getQualifiers(), alignment, + R.Initialize(type, type.getQualifiers(), Address::invalid(), LValueBaseInfo(AlignmentSource::Decl), TBAAAccessInfo()); + R.V = V; return R; } @@ -494,12 +498,8 @@ public: TBAAAccessInfo TBAAInfo) { LValue R; R.LVType = MatrixElt; - R.V = matAddress.getPointer(); - R.ElementType = matAddress.getElementType(); R.VectorIdx = Idx; - R.IsKnownNonNull = matAddress.isKnownNonNull(); - R.Initialize(type, type.getQualifiers(), matAddress.getAlignment(), - BaseInfo, TBAAInfo); + R.Initialize(type, type.getQualifiers(), matAddress, BaseInfo, TBAAInfo); return R; } @@ -643,17 +643,17 @@ public: return NeedsGCBarriers_t(ObjCGCFlag); } - llvm::Value *getPointer() const { - return Addr.getPointer(); + llvm::Value *getPointer(QualType PointeeTy, CodeGenFunction &CGF) const; + + llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { + return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; } Address getAddress() const { return Addr; } - bool isIgnored() const { - return !Addr.isValid(); - } + bool isIgnored() const { return !Addr.isValid(); } CharUnits getAlignment() const { return Addr.getAlignment(); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 4a3ff49b0007a3c6d70d9ef8974a1d7e00cc73ff..6474d6c8c1d1e42a2290e722371497165a6c4322 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -193,26 +193,35 @@ CodeGenFunction::CGFPOptionsRAII::~CGFPOptionsRAII() { CGF.Builder.setDefaultConstrainedRounding(OldRounding); } -LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) { +static LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, + bool ForPointeeType, + CodeGenFunction &CGF) { LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; - CharUnits Alignment = CGM.getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo); - Address Addr(V, ConvertTypeForMem(T), Alignment); - return LValue::MakeAddr(Addr, T, getContext(), BaseInfo, TBAAInfo); + CharUnits Alignment = + CGF.CGM.getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo, ForPointeeType); + Address Addr = Address(V, CGF.ConvertTypeForMem(T), Alignment); + return CGF.MakeAddrLValue(Addr, T, BaseInfo, TBAAInfo); +} + +LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) { + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, *this); } -/// Given a value of type T* that may not be to a complete object, -/// construct an l-value with the natural pointee alignment of T. LValue CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T) { - LValueBaseInfo BaseInfo; - TBAAAccessInfo TBAAInfo; - CharUnits Align = CGM.getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo, - /* forPointeeType= */ true); - Address Addr(V, ConvertTypeForMem(T), Align); - return MakeAddrLValue(Addr, T, BaseInfo, TBAAInfo); + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, *this); } +LValue CodeGenFunction::MakeNaturalAlignRawAddrLValue(llvm::Value *V, + QualType T) { + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, *this); +} + +LValue CodeGenFunction::MakeNaturalAlignPointeeRawAddrLValue(llvm::Value *V, + QualType T) { + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, *this); +} llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) { return CGM.getTypes().ConvertTypeForMem(T); @@ -267,6 +276,7 @@ TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) { case Type::Record: case Type::ObjCObject: case Type::ObjCInterface: + case Type::ArrayParameter: return TEK_Aggregate; // We operate on atomic values according to their underlying type. @@ -525,7 +535,8 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { ReturnBlock.getBlock()->eraseFromParent(); } if (ReturnValue.isValid()) { - auto *RetAlloca = dyn_cast<llvm::AllocaInst>(ReturnValue.getPointer()); + auto *RetAlloca = + dyn_cast<llvm::AllocaInst>(ReturnValue.emitRawPointer(*this)); if (RetAlloca && RetAlloca->use_empty()) { RetAlloca->eraseFromParent(); ReturnValue = Address::invalid(); @@ -979,7 +990,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, // return value. Initialize the flag to 'true' and refine it in EmitParmDecl. if (SanOpts.has(SanitizerKind::NullabilityReturn)) { auto Nullability = FnRetTy->getNullability(); - if (Nullability && *Nullability == NullabilityKind::NonNull) { + if (Nullability && *Nullability == NullabilityKind::NonNull && + !FnRetTy->isRecordType()) { if (!(SanOpts.has(SanitizerKind::ReturnsNonnullAttribute) && CurCodeDecl && CurCodeDecl->getAttr<ReturnsNonNullAttr>())) RetValNullabilityPrecondition = @@ -1122,13 +1134,14 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, auto AI = CurFn->arg_begin(); if (CurFnInfo->getReturnInfo().isSRetAfterThis()) ++AI; - ReturnValue = - Address(&*AI, ConvertType(RetTy), - CurFnInfo->getReturnInfo().getIndirectAlign(), KnownNonNull); + ReturnValue = makeNaturalAddressForPointer( + &*AI, RetTy, CurFnInfo->getReturnInfo().getIndirectAlign(), false, + nullptr, nullptr, KnownNonNull); if (!CurFnInfo->getReturnInfo().getIndirectByVal()) { - ReturnValuePointer = CreateDefaultAlignTempAlloca( - ReturnValue.getPointer()->getType(), "result.ptr"); - Builder.CreateStore(ReturnValue.getPointer(), ReturnValuePointer); + ReturnValuePointer = + CreateDefaultAlignTempAlloca(ReturnValue.getType(), "result.ptr"); + Builder.CreateStore(ReturnValue.emitRawPointer(*this), + ReturnValuePointer); } } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::InAlloca && !hasScalarEvaluationKind(CurFnInfo->getReturnType())) { @@ -1189,8 +1202,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, // or contains the address of the enclosing object). LValue ThisFieldLValue = EmitLValueForLambdaField(LambdaThisCaptureField); if (!LambdaThisCaptureField->getType()->isPointerType()) { - // If the enclosing object was captured by value, just use its address. - CXXThisValue = ThisFieldLValue.getAddress(*this).getPointer(); + // If the enclosing object was captured by value, just use its + // address. Sign this pointer. + CXXThisValue = ThisFieldLValue.getPointer(*this); } else { // Load the lvalue pointed to by the field, since '*this' was captured // by reference. @@ -1361,6 +1375,8 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, FunctionArgList Args; QualType ResTy = BuildFunctionArgList(GD, Args); + CGM.getTargetCodeGenInfo().checkFunctionABI(CGM, FD); + if (FD->isInlineBuiltinDeclaration()) { // When generating code for a builtin with an inline declaration, use a // mangled name to hold the actual body, while keeping an external @@ -2010,8 +2026,9 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType, = llvm::ConstantInt::get(CGF.IntPtrTy, baseSize.getQuantity()); Address begin = dest.withElementType(CGF.Int8Ty); - llvm::Value *end = Builder.CreateInBoundsGEP( - begin.getElementType(), begin.getPointer(), sizeInChars, "vla.end"); + llvm::Value *end = Builder.CreateInBoundsGEP(begin.getElementType(), + begin.emitRawPointer(CGF), + sizeInChars, "vla.end"); llvm::BasicBlock *originBB = CGF.Builder.GetInsertBlock(); llvm::BasicBlock *loopBB = CGF.createBasicBlock("vla-init.loop"); @@ -2022,7 +2039,7 @@ static void emitNonZeroVLAInit(CodeGenFunction &CGF, QualType baseType, CGF.EmitBlock(loopBB); llvm::PHINode *cur = Builder.CreatePHI(begin.getType(), 2, "vla.cur"); - cur->addIncoming(begin.getPointer(), originBB); + cur->addIncoming(begin.emitRawPointer(CGF), originBB); CharUnits curAlign = dest.getAlignment().alignmentOfArrayElement(baseSize); @@ -2187,8 +2204,8 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType, dyn_cast<llvm::ArrayType>(addr.getElementType()); while (llvmArrayType) { assert(isa<ConstantArrayType>(arrayType)); - assert(cast<ConstantArrayType>(arrayType)->getSize().getZExtValue() - == llvmArrayType->getNumElements()); + assert(cast<ConstantArrayType>(arrayType)->getZExtSize() == + llvmArrayType->getNumElements()); gepIndices.push_back(zero); countFromCLAs *= llvmArrayType->getNumElements(); @@ -2206,8 +2223,7 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType, // as some other type (probably a packed struct). Compute the array // size, and just emit the 'begin' expression as a bitcast. while (arrayType) { - countFromCLAs *= - cast<ConstantArrayType>(arrayType)->getSize().getZExtValue(); + countFromCLAs *= cast<ConstantArrayType>(arrayType)->getZExtSize(); eltType = arrayType->getElementType(); arrayType = getContext().getAsArrayType(eltType); } @@ -2216,10 +2232,10 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType, addr = addr.withElementType(baseType); } else { // Create the actual GEP. - addr = Address(Builder.CreateInBoundsGEP( - addr.getElementType(), addr.getPointer(), gepIndices, "array.begin"), - ConvertTypeForMem(eltType), - addr.getAlignment()); + addr = Address(Builder.CreateInBoundsGEP(addr.getElementType(), + addr.emitRawPointer(*this), + gepIndices, "array.begin"), + ConvertTypeForMem(eltType), addr.getAlignment()); } baseType = eltType; @@ -2347,6 +2363,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { type = cast<MemberPointerType>(ty)->getPointeeType(); break; + case Type::ArrayParameter: case Type::ConstantArray: case Type::IncompleteArray: // Losing element qualification here is fine. @@ -2407,6 +2424,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { case Type::BTFTagAttributed: case Type::SubstTemplateTypeParm: case Type::MacroQualified: + case Type::CountAttributed: // Keep walking after single level desugaring. type = type.getSingleStepDesugaredType(getContext()); break; @@ -2559,7 +2577,7 @@ void CodeGenFunction::EmitVarAnnotations(const VarDecl *D, llvm::Value *V) { Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D, Address Addr) { assert(D->hasAttr<AnnotateAttr>() && "no annotate attribute"); - llvm::Value *V = Addr.getPointer(); + llvm::Value *V = Addr.emitRawPointer(*this); llvm::Type *VTy = V->getType(); auto *PTy = dyn_cast<llvm::PointerType>(VTy); unsigned AS = PTy ? PTy->getAddressSpace() : 0; diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index e8f8aa601ed017b559d2b87548110423e5c78107..e2a7e28c8211ea7fd399aa0063f2cb7e9a0f3073 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -151,6 +151,9 @@ struct DominatingLLVMValue { /// Answer whether the given value needs extra work to be saved. static bool needsSaving(llvm::Value *value) { + if (!value) + return false; + // If it's not an instruction, we don't need to save. if (!isa<llvm::Instruction>(value)) return false; @@ -177,21 +180,28 @@ template <> struct DominatingValue<Address> { typedef Address type; struct saved_type { - DominatingLLVMValue::saved_type SavedValue; + DominatingLLVMValue::saved_type BasePtr; llvm::Type *ElementType; CharUnits Alignment; + DominatingLLVMValue::saved_type Offset; + llvm::PointerType *EffectiveType; }; static bool needsSaving(type value) { - return DominatingLLVMValue::needsSaving(value.getPointer()); + if (DominatingLLVMValue::needsSaving(value.getBasePointer()) || + DominatingLLVMValue::needsSaving(value.getOffset())) + return true; + return false; } static saved_type save(CodeGenFunction &CGF, type value) { - return { DominatingLLVMValue::save(CGF, value.getPointer()), - value.getElementType(), value.getAlignment() }; + return {DominatingLLVMValue::save(CGF, value.getBasePointer()), + value.getElementType(), value.getAlignment(), + DominatingLLVMValue::save(CGF, value.getOffset()), value.getType()}; } static type restore(CodeGenFunction &CGF, saved_type value) { - return Address(DominatingLLVMValue::restore(CGF, value.SavedValue), - value.ElementType, value.Alignment); + return Address(DominatingLLVMValue::restore(CGF, value.BasePtr), + value.ElementType, value.Alignment, + DominatingLLVMValue::restore(CGF, value.Offset)); } }; @@ -201,14 +211,26 @@ template <> struct DominatingValue<RValue> { class saved_type { enum Kind { ScalarLiteral, ScalarAddress, AggregateLiteral, AggregateAddress, ComplexAddress }; - - llvm::Value *Value; - llvm::Type *ElementType; + union { + struct { + DominatingLLVMValue::saved_type first, second; + } Vals; + DominatingValue<Address>::saved_type AggregateAddr; + }; LLVM_PREFERRED_TYPE(Kind) unsigned K : 3; - unsigned Align : 29; - saved_type(llvm::Value *v, llvm::Type *e, Kind k, unsigned a = 0) - : Value(v), ElementType(e), K(k), Align(a) {} + unsigned IsVolatile : 1; + + saved_type(DominatingLLVMValue::saved_type Val1, unsigned K) + : Vals{Val1, DominatingLLVMValue::saved_type()}, K(K) {} + + saved_type(DominatingLLVMValue::saved_type Val1, + DominatingLLVMValue::saved_type Val2) + : Vals{Val1, Val2}, K(ComplexAddress) {} + + saved_type(DominatingValue<Address>::saved_type AggregateAddr, + bool IsVolatile, unsigned K) + : AggregateAddr(AggregateAddr), K(K) {} public: static bool needsSaving(RValue value); @@ -659,7 +681,7 @@ public: llvm::Value *Size; public: - CallLifetimeEnd(Address addr, llvm::Value *size) + CallLifetimeEnd(RawAddress addr, llvm::Value *size) : Addr(addr.getPointer()), Size(size) {} void Emit(CodeGenFunction &CGF, Flags flags) override { @@ -684,7 +706,7 @@ public: }; /// i32s containing the indexes of the cleanup destinations. - Address NormalCleanupDest = Address::invalid(); + RawAddress NormalCleanupDest = RawAddress::invalid(); unsigned NextCleanupDestIndex = 1; @@ -819,10 +841,10 @@ public: template <class T, class... As> void pushCleanupAfterFullExpr(CleanupKind Kind, As... A) { if (!isInConditionalBranch()) - return pushCleanupAfterFullExprWithActiveFlag<T>(Kind, Address::invalid(), - A...); + return pushCleanupAfterFullExprWithActiveFlag<T>( + Kind, RawAddress::invalid(), A...); - Address ActiveFlag = createCleanupActiveFlag(); + RawAddress ActiveFlag = createCleanupActiveFlag(); assert(!DominatingValue<Address>::needsSaving(ActiveFlag) && "cleanup active flag should never need saving"); @@ -835,7 +857,7 @@ public: template <class T, class... As> void pushCleanupAfterFullExprWithActiveFlag(CleanupKind Kind, - Address ActiveFlag, As... A) { + RawAddress ActiveFlag, As... A) { LifetimeExtendedCleanupHeader Header = {sizeof(T), Kind, ActiveFlag.isValid()}; @@ -850,7 +872,7 @@ public: new (Buffer) LifetimeExtendedCleanupHeader(Header); new (Buffer + sizeof(Header)) T(A...); if (Header.IsConditional) - new (Buffer + sizeof(Header) + sizeof(T)) Address(ActiveFlag); + new (Buffer + sizeof(Header) + sizeof(T)) RawAddress(ActiveFlag); } /// Set up the last cleanup that was pushed as a conditional @@ -859,8 +881,8 @@ public: initFullExprCleanupWithFlag(createCleanupActiveFlag()); } - void initFullExprCleanupWithFlag(Address ActiveFlag); - Address createCleanupActiveFlag(); + void initFullExprCleanupWithFlag(RawAddress ActiveFlag); + RawAddress createCleanupActiveFlag(); /// PushDestructorCleanup - Push a cleanup to call the /// complete-object destructor of an object of the given type at the @@ -1048,7 +1070,7 @@ public: QualType VarTy = LocalVD->getType(); if (VarTy->isReferenceType()) { Address Temp = CGF.CreateMemTemp(VarTy); - CGF.Builder.CreateStore(TempAddr.getPointer(), Temp); + CGF.Builder.CreateStore(TempAddr.emitRawPointer(CGF), Temp); TempAddr = Temp; } SavedTempAddresses.try_emplace(LocalVD, TempAddr); @@ -1243,10 +1265,12 @@ public: /// one branch or the other of a conditional expression. bool isInConditionalBranch() const { return OutermostConditional != nullptr; } - void setBeforeOutermostConditional(llvm::Value *value, Address addr) { + void setBeforeOutermostConditional(llvm::Value *value, Address addr, + CodeGenFunction &CGF) { assert(isInConditionalBranch()); llvm::BasicBlock *block = OutermostConditional->getStartingBlock(); - auto store = new llvm::StoreInst(value, addr.getPointer(), &block->back()); + auto store = + new llvm::StoreInst(value, addr.emitRawPointer(CGF), &block->back()); store->setAlignment(addr.getAlignment().getAsAlign()); } @@ -1601,7 +1625,7 @@ public: /// If \p StepV is null, the default increment is 1. void maybeUpdateMCDCTestVectorBitmap(const Expr *E) { if (isMCDCCoverageEnabled() && isBinaryLogicalOp(E)) { - PGO.emitMCDCTestVectorBitmapUpdate(Builder, E, MCDCCondBitmapAddr); + PGO.emitMCDCTestVectorBitmapUpdate(Builder, E, MCDCCondBitmapAddr, *this); PGO.setCurrentStmt(E); } } @@ -1609,7 +1633,7 @@ public: /// Update the MCDC temp value with the condition's evaluated result. void maybeUpdateMCDCCondBitmap(const Expr *E, llvm::Value *Val) { if (isMCDCCoverageEnabled()) { - PGO.emitMCDCCondBitmapUpdate(Builder, E, MCDCCondBitmapAddr, Val); + PGO.emitMCDCCondBitmapUpdate(Builder, E, MCDCCondBitmapAddr, Val, *this); PGO.setCurrentStmt(E); } } @@ -1704,7 +1728,7 @@ public: : CGF(CGF), OldCXXThisValue(CGF.CXXThisValue), OldCXXThisAlignment(CGF.CXXThisAlignment), SourceLocScope(E, CGF.CurSourceLocExprScope) { - CGF.CXXThisValue = CGF.CXXDefaultInitExprThis.getPointer(); + CGF.CXXThisValue = CGF.CXXDefaultInitExprThis.getBasePointer(); CGF.CXXThisAlignment = CGF.CXXDefaultInitExprThis.getAlignment(); } ~CXXDefaultInitExprScope() { @@ -2090,7 +2114,7 @@ public: llvm::Value *getExceptionFromSlot(); llvm::Value *getSelectorFromSlot(); - Address getNormalCleanupDestSlot(); + RawAddress getNormalCleanupDestSlot(); llvm::BasicBlock *getUnreachableBlock() { if (!UnreachableBlock) { @@ -2579,10 +2603,40 @@ public: // Helpers //===--------------------------------------------------------------------===// + Address mergeAddressesInConditionalExpr(Address LHS, Address RHS, + llvm::BasicBlock *LHSBlock, + llvm::BasicBlock *RHSBlock, + llvm::BasicBlock *MergeBlock, + QualType MergedType) { + Builder.SetInsertPoint(MergeBlock); + llvm::PHINode *PtrPhi = Builder.CreatePHI(LHS.getType(), 2, "cond"); + PtrPhi->addIncoming(LHS.getBasePointer(), LHSBlock); + PtrPhi->addIncoming(RHS.getBasePointer(), RHSBlock); + LHS.replaceBasePointer(PtrPhi); + LHS.setAlignment(std::min(LHS.getAlignment(), RHS.getAlignment())); + return LHS; + } + + /// Construct an address with the natural alignment of T. If a pointer to T + /// is expected to be signed, the pointer passed to this function must have + /// been signed, and the returned Address will have the pointer authentication + /// information needed to authenticate the signed pointer. + Address makeNaturalAddressForPointer( + llvm::Value *Ptr, QualType T, CharUnits Alignment = CharUnits::Zero(), + bool ForPointeeType = false, LValueBaseInfo *BaseInfo = nullptr, + TBAAAccessInfo *TBAAInfo = nullptr, + KnownNonNull_t IsKnownNonNull = NotKnownNonNull) { + if (Alignment.isZero()) + Alignment = + CGM.getNaturalTypeAlignment(T, BaseInfo, TBAAInfo, ForPointeeType); + return Address(Ptr, ConvertTypeForMem(T), Alignment, nullptr, + IsKnownNonNull); + } + LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source = AlignmentSource::Type) { - return LValue::MakeAddr(Addr, T, getContext(), LValueBaseInfo(Source), - CGM.getTBAAAccessInfo(T)); + return MakeAddrLValue(Addr, T, LValueBaseInfo(Source), + CGM.getTBAAAccessInfo(T)); } LValue MakeAddrLValue(Address Addr, QualType T, LValueBaseInfo BaseInfo, @@ -2592,6 +2646,14 @@ public: LValue MakeAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, AlignmentSource Source = AlignmentSource::Type) { + return MakeAddrLValue(makeNaturalAddressForPointer(V, T, Alignment), T, + LValueBaseInfo(Source), CGM.getTBAAAccessInfo(T)); + } + + /// Same as MakeAddrLValue above except that the pointer is known to be + /// unsigned. + LValue MakeRawAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, + AlignmentSource Source = AlignmentSource::Type) { Address Addr(V, ConvertTypeForMem(T), Alignment); return LValue::MakeAddr(Addr, T, getContext(), LValueBaseInfo(Source), CGM.getTBAAAccessInfo(T)); @@ -2604,9 +2666,18 @@ public: TBAAAccessInfo()); } + /// Given a value of type T* that may not be to a complete object, construct + /// an l-value with the natural pointee alignment of T. LValue MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T); + LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T); + /// Same as MakeNaturalAlignPointeeAddrLValue except that the pointer is known + /// to be unsigned. + LValue MakeNaturalAlignPointeeRawAddrLValue(llvm::Value *V, QualType T); + + LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T); + Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo = nullptr, TBAAAccessInfo *PointeeTBAAInfo = nullptr); @@ -2655,13 +2726,13 @@ public: /// more efficient if the caller knows that the address will not be exposed. llvm::AllocaInst *CreateTempAlloca(llvm::Type *Ty, const Twine &Name = "tmp", llvm::Value *ArraySize = nullptr); - Address CreateTempAlloca(llvm::Type *Ty, CharUnits align, - const Twine &Name = "tmp", - llvm::Value *ArraySize = nullptr, - Address *Alloca = nullptr); - Address CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits align, - const Twine &Name = "tmp", - llvm::Value *ArraySize = nullptr); + RawAddress CreateTempAlloca(llvm::Type *Ty, CharUnits align, + const Twine &Name = "tmp", + llvm::Value *ArraySize = nullptr, + RawAddress *Alloca = nullptr); + RawAddress CreateTempAllocaWithoutCast(llvm::Type *Ty, CharUnits align, + const Twine &Name = "tmp", + llvm::Value *ArraySize = nullptr); /// CreateDefaultAlignedTempAlloca - This creates an alloca with the /// default ABI alignment of the given LLVM type. @@ -2673,8 +2744,8 @@ public: /// not hand this address off to arbitrary IRGen routines, and especially /// do not pass it as an argument to a function that might expect a /// properly ABI-aligned value. - Address CreateDefaultAlignTempAlloca(llvm::Type *Ty, - const Twine &Name = "tmp"); + RawAddress CreateDefaultAlignTempAlloca(llvm::Type *Ty, + const Twine &Name = "tmp"); /// CreateIRTemp - Create a temporary IR object of the given type, with /// appropriate alignment. This routine should only be used when an temporary @@ -2684,32 +2755,31 @@ public: /// /// That is, this is exactly equivalent to CreateMemTemp, but calling /// ConvertType instead of ConvertTypeForMem. - Address CreateIRTemp(QualType T, const Twine &Name = "tmp"); + RawAddress CreateIRTemp(QualType T, const Twine &Name = "tmp"); /// CreateMemTemp - Create a temporary memory object of the given type, with /// appropriate alignmen and cast it to the default address space. Returns /// the original alloca instruction by \p Alloca if it is not nullptr. - Address CreateMemTemp(QualType T, const Twine &Name = "tmp", - Address *Alloca = nullptr); - Address CreateMemTemp(QualType T, CharUnits Align, const Twine &Name = "tmp", - Address *Alloca = nullptr); + RawAddress CreateMemTemp(QualType T, const Twine &Name = "tmp", + RawAddress *Alloca = nullptr); + RawAddress CreateMemTemp(QualType T, CharUnits Align, + const Twine &Name = "tmp", + RawAddress *Alloca = nullptr); /// CreateMemTemp - Create a temporary memory object of the given type, with /// appropriate alignmen without casting it to the default address space. - Address CreateMemTempWithoutCast(QualType T, const Twine &Name = "tmp"); - Address CreateMemTempWithoutCast(QualType T, CharUnits Align, - const Twine &Name = "tmp"); + RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name = "tmp"); + RawAddress CreateMemTempWithoutCast(QualType T, CharUnits Align, + const Twine &Name = "tmp"); /// CreateAggTemp - Create a temporary memory object for the given /// aggregate type. AggValueSlot CreateAggTemp(QualType T, const Twine &Name = "tmp", - Address *Alloca = nullptr) { - return AggValueSlot::forAddr(CreateMemTemp(T, Name, Alloca), - T.getQualifiers(), - AggValueSlot::IsNotDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased, - AggValueSlot::DoesNotOverlap); + RawAddress *Alloca = nullptr) { + return AggValueSlot::forAddr( + CreateMemTemp(T, Name, Alloca), T.getQualifiers(), + AggValueSlot::IsNotDestructed, AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased, AggValueSlot::DoesNotOverlap); } /// EvaluateExprAsBool - Perform the usual unary conversions on the specified @@ -3083,6 +3153,25 @@ public: /// calls to EmitTypeCheck can be skipped. bool sanitizePerformTypeCheck() const; + void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, LValue LV, + QualType Type, SanitizerSet SkippedChecks = SanitizerSet(), + llvm::Value *ArraySize = nullptr) { + if (!sanitizePerformTypeCheck()) + return; + EmitTypeCheck(TCK, Loc, LV.emitRawPointer(*this), Type, LV.getAlignment(), + SkippedChecks, ArraySize); + } + + void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, Address Addr, + QualType Type, CharUnits Alignment = CharUnits::Zero(), + SanitizerSet SkippedChecks = SanitizerSet(), + llvm::Value *ArraySize = nullptr) { + if (!sanitizePerformTypeCheck()) + return; + EmitTypeCheck(TCK, Loc, Addr.emitRawPointer(*this), Type, Alignment, + SkippedChecks, ArraySize); + } + /// Emit a check that \p V is the address of storage of the /// appropriate size and alignment for an object of type \p Type /// (or if ArraySize is provided, for an array of that bound). @@ -3183,17 +3272,17 @@ public: /// Address with original alloca instruction. Invalid if the variable was /// emitted as a global constant. - Address AllocaAddr; + RawAddress AllocaAddr; struct Invalid {}; AutoVarEmission(Invalid) : Variable(nullptr), Addr(Address::invalid()), - AllocaAddr(Address::invalid()) {} + AllocaAddr(RawAddress::invalid()) {} AutoVarEmission(const VarDecl &variable) : Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr), IsEscapingByRef(false), IsConstantAggregate(false), - SizeForLifetimeMarkers(nullptr), AllocaAddr(Address::invalid()) {} + SizeForLifetimeMarkers(nullptr), AllocaAddr(RawAddress::invalid()) {} bool wasEmittedAsGlobal() const { return !Addr.isValid(); } @@ -3216,7 +3305,7 @@ public: } /// Returns the address for the original alloca instruction. - Address getOriginalAllocatedAddress() const { return AllocaAddr; } + RawAddress getOriginalAllocatedAddress() const { return AllocaAddr; } /// Returns the address of the object within this declaration. /// Note that this does not chase the forwarding pointer for @@ -3246,23 +3335,32 @@ public: llvm::GlobalValue::LinkageTypes Linkage); class ParamValue { - llvm::Value *Value; - llvm::Type *ElementType; - unsigned Alignment; - ParamValue(llvm::Value *V, llvm::Type *T, unsigned A) - : Value(V), ElementType(T), Alignment(A) {} + union { + Address Addr; + llvm::Value *Value; + }; + + bool IsIndirect; + + ParamValue(llvm::Value *V) : Value(V), IsIndirect(false) {} + ParamValue(Address A) : Addr(A), IsIndirect(true) {} + public: static ParamValue forDirect(llvm::Value *value) { - return ParamValue(value, nullptr, 0); + return ParamValue(value); } static ParamValue forIndirect(Address addr) { assert(!addr.getAlignment().isZero()); - return ParamValue(addr.getPointer(), addr.getElementType(), - addr.getAlignment().getQuantity()); + return ParamValue(addr); } - bool isIndirect() const { return Alignment != 0; } - llvm::Value *getAnyValue() const { return Value; } + bool isIndirect() const { return IsIndirect; } + llvm::Value *getAnyValue() const { + if (!isIndirect()) + return Value; + assert(!Addr.hasOffset() && "unexpected offset"); + return Addr.getBasePointer(); + } llvm::Value *getDirectValue() const { assert(!isIndirect()); @@ -3271,8 +3369,7 @@ public: Address getIndirectAddress() const { assert(isIndirect()); - return Address(Value, ElementType, CharUnits::fromQuantity(Alignment), - KnownNonNull); + return Addr; } }; @@ -4182,6 +4279,9 @@ public: const Twine &name = ""); llvm::CallInst *EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name = ""); + llvm::CallInst *EmitNounwindRuntimeCall(llvm::FunctionCallee callee, + ArrayRef<Address> args, + const Twine &name = ""); llvm::CallInst *EmitNounwindRuntimeCall(llvm::FunctionCallee callee, ArrayRef<llvm::Value *> args, const Twine &name = ""); @@ -4208,6 +4308,12 @@ public: CXXDtorType Type, const CXXRecordDecl *RD); + llvm::Value *getAsNaturalPointerTo(Address Addr, QualType PointeeType) { + return Addr.getBasePointer(); + } + + bool isPointerKnownNonNull(const Expr *E); + // Return the copy constructor name with the prefix "__copy_constructor_" // removed. static std::string getNonTrivialCopyConstructorStr(QualType QT, @@ -4780,6 +4886,11 @@ public: SourceLocation Loc, const Twine &Name = ""); + Address EmitCheckedInBoundsGEP(Address Addr, ArrayRef<llvm::Value *> IdxList, + llvm::Type *elementType, bool SignedIndices, + bool IsSubtraction, SourceLocation Loc, + CharUnits Align, const Twine &Name = ""); + /// Specifies which type of sanitizer check to apply when handling a /// particular builtin. enum BuiltinCheckKind { @@ -4842,6 +4953,10 @@ public: void EmitNonNullArgCheck(RValue RV, QualType ArgType, SourceLocation ArgLoc, AbstractCallee AC, unsigned ParmNum); + void EmitNonNullArgCheck(Address Addr, QualType ArgType, + SourceLocation ArgLoc, AbstractCallee AC, + unsigned ParmNum); + /// EmitCallArg - Emit a single call argument. void EmitCallArg(CallArgList &args, const Expr *E, QualType ArgType); @@ -4870,6 +4985,25 @@ public: llvm::Value *emitBoolVecConversion(llvm::Value *SrcVec, unsigned NumElementsDst, const llvm::Twine &Name = ""); + // Adds a convergence_ctrl token to |Input| and emits the required parent + // convergence instructions. + llvm::CallBase *addControlledConvergenceToken(llvm::CallBase *Input); + +private: + // Emits a convergence_loop instruction for the given |BB|, with |ParentToken| + // as it's parent convergence instr. + llvm::IntrinsicInst *emitConvergenceLoopToken(llvm::BasicBlock *BB, + llvm::Value *ParentToken); + // Adds a convergence_ctrl token with |ParentToken| as parent convergence + // instr to the call |Input|. + llvm::CallBase *addConvergenceControlToken(llvm::CallBase *Input, + llvm::Value *ParentToken); + // Find the convergence_entry instruction |F|, or emits ones if none exists. + // Returns the convergence instruction. + llvm::IntrinsicInst *getOrEmitConvergenceEntryToken(llvm::Function *F); + // Find the convergence_loop instruction for the loop defined by |LI|, or + // emits one if none exists. Returns the convergence instruction. + llvm::IntrinsicInst *getOrEmitConvergenceLoopToken(const LoopInfo *LI); private: llvm::MDNode *getRangeForLoadFromType(QualType Ty); @@ -5050,7 +5184,7 @@ DominatingLLVMValue::save(CodeGenFunction &CGF, llvm::Value *value) { CGF.CreateTempAlloca(value->getType(), align, "cond-cleanup.save"); CGF.Builder.CreateStore(value, alloca); - return saved_type(alloca.getPointer(), true); + return saved_type(alloca.emitRawPointer(CGF), true); } inline llvm::Value *DominatingLLVMValue::restore(CodeGenFunction &CGF, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 967319bdfc4571168f370c42b3b6ad26d21b8c6c..00b3bfcaa0bc2565862d659b122b1caf18ff0599 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -145,6 +145,8 @@ createTargetCodeGenInfo(CodeGenModule &CGM) { Kind = AArch64ABIKind::DarwinPCS; else if (Triple.isOSWindows()) return createWindowsAArch64TargetCodeGenInfo(CGM, AArch64ABIKind::Win64); + else if (Target.getABI() == "aapcs-soft") + Kind = AArch64ABIKind::AAPCSSoft; return createAArch64TargetCodeGenInfo(CGM, Kind); } @@ -626,6 +628,26 @@ static bool checkAliasedGlobal( return true; } +// Emit a warning if toc-data attribute is requested for global variables that +// have aliases and remove the toc-data attribute. +static void checkAliasForTocData(llvm::GlobalVariable *GVar, + const CodeGenOptions &CodeGenOpts, + DiagnosticsEngine &Diags, + SourceLocation Location) { + if (GVar->hasAttribute("toc-data")) { + auto GVId = GVar->getName(); + // Is this a global variable specified by the user as local? + if ((llvm::binary_search(CodeGenOpts.TocDataVarsUserSpecified, GVId))) { + Diags.Report(Location, diag::warn_toc_unsupported_type) + << GVId << "the variable has an alias"; + } + llvm::AttributeSet CurrAttributes = GVar->getAttributes(); + llvm::AttributeSet NewAttributes = + CurrAttributes.removeAttribute(GVar->getContext(), "toc-data"); + GVar->setAttributes(NewAttributes); + } +} + void CodeGenModule::checkAliases() { // Check if the constructed aliases are well formed. It is really unfortunate // that we have to do this in CodeGen, but we only construct mangled names @@ -652,6 +674,12 @@ void CodeGenModule::checkAliases() { continue; } + if (getContext().getTargetInfo().getTriple().isOSAIX()) + if (const llvm::GlobalVariable *GVar = + dyn_cast<const llvm::GlobalVariable>(GV)) + checkAliasForTocData(const_cast<llvm::GlobalVariable *>(GVar), + getCodeGenOpts(), Diags, Location); + llvm::Constant *Aliasee = IsIFunc ? cast<llvm::GlobalIFunc>(Alias)->getResolver() : cast<llvm::GlobalAlias>(Alias)->getAliasee(); @@ -3421,6 +3449,9 @@ bool CodeGenModule::MayBeEmittedEagerly(const ValueDecl *Global) { // Implicit template instantiations may change linkage if they are later // explicitly instantiated, so they should not be emitted eagerly. return false; + // Defer until all versions have been semantically checked. + if (FD->hasAttr<TargetVersionAttr>() && !FD->isMultiVersion()) + return false; } if (const auto *VD = dyn_cast<VarDecl>(Global)) { if (Context.getInlineVariableDefinitionKind(VD) == @@ -3680,7 +3711,9 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // Forward declarations are emitted lazily on first use. if (!FD->doesThisDeclarationHaveABody()) { - if (!FD->doesDeclarationForceExternallyVisibleDefinition()) + if (!FD->doesDeclarationForceExternallyVisibleDefinition() && + (!FD->isMultiVersion() || + !FD->getASTContext().getTargetInfo().getTriple().isAArch64())) return; StringRef MangledName = getMangledName(GD); @@ -3962,17 +3995,21 @@ void CodeGenModule::EmitMultiVersionFunctionDefinition(GlobalDecl GD, auto *Spec = FD->getAttr<CPUSpecificAttr>(); for (unsigned I = 0; I < Spec->cpus_size(); ++I) EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr); - } else if (FD->isTargetClonesMultiVersion()) { - auto *Clone = FD->getAttr<TargetClonesAttr>(); - for (unsigned I = 0; I < Clone->featuresStrs_size(); ++I) - if (Clone->isFirstOfVersion(I)) + } else if (auto *TC = FD->getAttr<TargetClonesAttr>()) { + for (unsigned I = 0; I < TC->featuresStrs_size(); ++I) + // AArch64 favors the default target version over the clone if any. + if ((!TC->isDefaultVersion(I) || !getTarget().getTriple().isAArch64()) && + TC->isFirstOfVersion(I)) EmitGlobalFunctionDefinition(GD.getWithMultiVersionIndex(I), nullptr); // Ensure that the resolver function is also emitted. GetOrCreateMultiVersionResolver(GD); - } else if (FD->hasAttr<TargetVersionAttr>()) { - GetOrCreateMultiVersionResolver(GD); } else EmitGlobalFunctionDefinition(GD, GV); + + // Defer the resolver emission until we can reason whether the TU + // contains a default target version implementation. + if (FD->isTargetVersionMultiVersion()) + AddDeferredMultiVersionResolverToEmit(GD); } void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) { @@ -4058,6 +4095,23 @@ llvm::GlobalValue::LinkageTypes getMultiversionLinkage(CodeGenModule &CGM, return llvm::GlobalValue::WeakODRLinkage; } +static FunctionDecl *createDefaultTargetVersionFrom(const FunctionDecl *FD) { + DeclContext *DeclCtx = FD->getASTContext().getTranslationUnitDecl(); + TypeSourceInfo *TInfo = FD->getTypeSourceInfo(); + StorageClass SC = FD->getStorageClass(); + DeclarationName Name = FD->getNameInfo().getName(); + + FunctionDecl *NewDecl = + FunctionDecl::Create(FD->getASTContext(), DeclCtx, FD->getBeginLoc(), + FD->getEndLoc(), Name, TInfo->getType(), TInfo, SC); + + NewDecl->setIsMultiVersion(); + NewDecl->addAttr(TargetVersionAttr::CreateImplicit( + NewDecl->getASTContext(), "default", NewDecl->getSourceRange())); + + return NewDecl; +} + void CodeGenModule::emitMultiVersionFunctions() { std::vector<GlobalDecl> MVFuncsToEmit; MultiVersionFuncs.swap(MVFuncsToEmit); @@ -4065,88 +4119,78 @@ void CodeGenModule::emitMultiVersionFunctions() { const auto *FD = cast<FunctionDecl>(GD.getDecl()); assert(FD && "Expected a FunctionDecl"); - SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options; - if (FD->isTargetMultiVersion()) { - getContext().forEachMultiversionedFunctionVersion( - FD, [this, &GD, &Options](const FunctionDecl *CurFD) { - GlobalDecl CurGD{ - (CurFD->isDefined() ? CurFD->getDefinition() : CurFD)}; - StringRef MangledName = getMangledName(CurGD); - llvm::Constant *Func = GetGlobalValue(MangledName); - if (!Func) { - if (CurFD->isDefined()) { - EmitGlobalFunctionDefinition(CurGD, nullptr); - Func = GetGlobalValue(MangledName); - } else { - const CGFunctionInfo &FI = - getTypes().arrangeGlobalDeclaration(GD); - llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); - Func = GetAddrOfFunction(CurGD, Ty, /*ForVTable=*/false, - /*DontDefer=*/false, ForDefinition); - } - assert(Func && "This should have just been created"); - } - if (CurFD->getMultiVersionKind() == MultiVersionKind::Target) { - const auto *TA = CurFD->getAttr<TargetAttr>(); - llvm::SmallVector<StringRef, 8> Feats; - TA->getAddedFeatures(Feats); - Options.emplace_back(cast<llvm::Function>(Func), - TA->getArchitecture(), Feats); - } else { - const auto *TVA = CurFD->getAttr<TargetVersionAttr>(); - llvm::SmallVector<StringRef, 8> Feats; - TVA->getFeatures(Feats); - Options.emplace_back(cast<llvm::Function>(Func), - /*Architecture*/ "", Feats); - } - }); - } else if (FD->isTargetClonesMultiVersion()) { - const auto *TC = FD->getAttr<TargetClonesAttr>(); - for (unsigned VersionIndex = 0; VersionIndex < TC->featuresStrs_size(); - ++VersionIndex) { - if (!TC->isFirstOfVersion(VersionIndex)) - continue; - GlobalDecl CurGD{(FD->isDefined() ? FD->getDefinition() : FD), - VersionIndex}; - StringRef Version = TC->getFeatureStr(VersionIndex); - StringRef MangledName = getMangledName(CurGD); - llvm::Constant *Func = GetGlobalValue(MangledName); - if (!Func) { - if (FD->isDefined()) { - EmitGlobalFunctionDefinition(CurGD, nullptr); - Func = GetGlobalValue(MangledName); - } else { - const CGFunctionInfo &FI = - getTypes().arrangeGlobalDeclaration(CurGD); - llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); - Func = GetAddrOfFunction(CurGD, Ty, /*ForVTable=*/false, - /*DontDefer=*/false, ForDefinition); - } - assert(Func && "This should have just been created"); + auto createFunction = [&](const FunctionDecl *Decl, unsigned MVIdx = 0) { + GlobalDecl CurGD{Decl->isDefined() ? Decl->getDefinition() : Decl, MVIdx}; + StringRef MangledName = getMangledName(CurGD); + llvm::Constant *Func = GetGlobalValue(MangledName); + if (!Func) { + if (Decl->isDefined()) { + EmitGlobalFunctionDefinition(CurGD, nullptr); + Func = GetGlobalValue(MangledName); + } else { + const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(CurGD); + llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); + Func = GetAddrOfFunction(CurGD, Ty, /*ForVTable=*/false, + /*DontDefer=*/false, ForDefinition); } + assert(Func && "This should have just been created"); + } + return cast<llvm::Function>(Func); + }; - StringRef Architecture; - llvm::SmallVector<StringRef, 1> Feature; + bool HasDefaultDecl = !FD->isTargetVersionMultiVersion(); + bool ShouldEmitResolver = + !getContext().getTargetInfo().getTriple().isAArch64(); + SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options; - if (getTarget().getTriple().isAArch64()) { - if (Version != "default") { - llvm::SmallVector<StringRef, 8> VerFeats; - Version.split(VerFeats, "+"); - for (auto &CurFeat : VerFeats) - Feature.push_back(CurFeat.trim()); - } - } else { - if (Version.starts_with("arch=")) - Architecture = Version.drop_front(sizeof("arch=") - 1); - else if (Version != "default") - Feature.push_back(Version); - } + getContext().forEachMultiversionedFunctionVersion( + FD, [&](const FunctionDecl *CurFD) { + llvm::SmallVector<StringRef, 8> Feats; + + if (const auto *TA = CurFD->getAttr<TargetAttr>()) { + TA->getAddedFeatures(Feats); + llvm::Function *Func = createFunction(CurFD); + Options.emplace_back(Func, TA->getArchitecture(), Feats); + } else if (const auto *TVA = CurFD->getAttr<TargetVersionAttr>()) { + bool HasDefaultDef = TVA->isDefaultVersion() && + CurFD->doesThisDeclarationHaveABody(); + HasDefaultDecl |= TVA->isDefaultVersion(); + ShouldEmitResolver |= (CurFD->isUsed() || HasDefaultDef); + TVA->getFeatures(Feats); + llvm::Function *Func = createFunction(CurFD); + Options.emplace_back(Func, /*Architecture*/ "", Feats); + } else if (const auto *TC = CurFD->getAttr<TargetClonesAttr>()) { + ShouldEmitResolver |= CurFD->doesThisDeclarationHaveABody(); + for (unsigned I = 0; I < TC->featuresStrs_size(); ++I) { + if (!TC->isFirstOfVersion(I)) + continue; + + llvm::Function *Func = createFunction(CurFD, I); + StringRef Architecture; + Feats.clear(); + if (getTarget().getTriple().isAArch64()) + TC->getFeatures(Feats, I); + else { + StringRef Version = TC->getFeatureStr(I); + if (Version.starts_with("arch=")) + Architecture = Version.drop_front(sizeof("arch=") - 1); + else if (Version != "default") + Feats.push_back(Version); + } + Options.emplace_back(Func, Architecture, Feats); + } + } else + llvm_unreachable("unexpected MultiVersionKind"); + }); - Options.emplace_back(cast<llvm::Function>(Func), Architecture, Feature); - } - } else { - assert(0 && "Expected a target or target_clones multiversion function"); + if (!ShouldEmitResolver) continue; + + if (!HasDefaultDecl) { + FunctionDecl *NewFD = createDefaultTargetVersionFrom(FD); + llvm::Function *Func = createFunction(NewFD); + llvm::SmallVector<StringRef, 1> Feats; + Options.emplace_back(Func, /*Architecture*/ "", Feats); } llvm::Constant *ResolverConstant = GetOrCreateMultiVersionResolver(GD); @@ -4154,17 +4198,19 @@ void CodeGenModule::emitMultiVersionFunctions() { ResolverConstant = IFunc->getResolver(); if (FD->isTargetClonesMultiVersion() || FD->isTargetVersionMultiVersion()) { - const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD); - llvm::FunctionType *DeclTy = getTypes().GetFunctionType(FI); std::string MangledName = getMangledNameImpl( *this, GD, FD, /*OmitMultiVersionMangling=*/true); - // In prior versions of Clang, the mangling for ifuncs incorrectly - // included an .ifunc suffix. This alias is generated for backward - // compatibility. It is deprecated, and may be removed in the future. - auto *Alias = llvm::GlobalAlias::create( - DeclTy, 0, getMultiversionLinkage(*this, GD), - MangledName + ".ifunc", IFunc, &getModule()); - SetCommonAttributes(FD, Alias); + if (!GetGlobalValue(MangledName + ".ifunc")) { + const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD); + llvm::FunctionType *DeclTy = getTypes().GetFunctionType(FI); + // In prior versions of Clang, the mangling for ifuncs incorrectly + // included an .ifunc suffix. This alias is generated for backward + // compatibility. It is deprecated, and may be removed in the future. + auto *Alias = llvm::GlobalAlias::create( + DeclTy, 0, getMultiversionLinkage(*this, GD), + MangledName + ".ifunc", IFunc, &getModule()); + SetCommonAttributes(FD, Alias); + } } } llvm::Function *ResolverFunc = cast<llvm::Function>(ResolverConstant); @@ -4321,6 +4367,20 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) { } } +/// Adds a declaration to the list of multi version functions if not present. +void CodeGenModule::AddDeferredMultiVersionResolverToEmit(GlobalDecl GD) { + const auto *FD = cast<FunctionDecl>(GD.getDecl()); + assert(FD && "Not a FunctionDecl?"); + + if (FD->isTargetVersionMultiVersion() || FD->isTargetClonesMultiVersion()) { + std::string MangledName = + getMangledNameImpl(*this, GD, FD, /*OmitMultiVersionMangling=*/true); + if (!DeferredResolversToEmit.insert(MangledName).second) + return; + } + MultiVersionFuncs.push_back(GD); +} + /// If a dispatcher for the specified mangled name is not in the module, create /// and return an llvm Function with the specified type. llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) { @@ -4360,7 +4420,7 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) { // The resolver needs to be created. For target and target_clones, defer // creation until the end of the TU. if (FD->isTargetMultiVersion() || FD->isTargetClonesMultiVersion()) - MultiVersionFuncs.push_back(GD); + AddDeferredMultiVersionResolverToEmit(GD); // For cpu_specific, don't create an ifunc yet because we don't know if the // cpu_dispatch will be emitted in this translation unit. @@ -4423,7 +4483,10 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( if (FD->isMultiVersion()) { UpdateMultiVersionNames(GD, FD, MangledName); - if (!IsForDefinition) + if (FD->getASTContext().getTargetInfo().getTriple().isAArch64() && + !FD->isUsed()) + AddDeferredMultiVersionResolverToEmit(GD); + else if (!IsForDefinition) return GetOrCreateMultiVersionResolver(GD); } } @@ -6218,7 +6281,7 @@ CodeGenModule::GetConstantArrayFromStringLiteral(const StringLiteral *E) { // Resize the string to the right size, which is indicated by its type. const ConstantArrayType *CAT = Context.getAsConstantArrayType(E->getType()); assert(CAT && "String literal not of constant array type!"); - Str.resize(CAT->getSize().getZExtValue()); + Str.resize(CAT->getZExtSize()); return llvm::ConstantDataArray::getString(VMContext, Str, false); } @@ -7204,7 +7267,7 @@ void CodeGenFunction::EmitDeclMetadata() { for (auto &I : LocalDeclMap) { const Decl *D = I.first; - llvm::Value *Addr = I.second.getPointer(); + llvm::Value *Addr = I.second.emitRawPointer(*this); if (auto *Alloca = dyn_cast<llvm::AllocaInst>(Addr)) { llvm::Value *DAddr = GetPointerConstant(getLLVMContext(), D); Alloca->setMetadata( diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index ec34680fd3f7e6e40b50b4cff39b19877aaf051a..1cc447765e2c977cec62df9b7aaa54c44e20ebc4 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -348,6 +348,8 @@ private: /// yet. llvm::DenseMap<StringRef, GlobalDecl> DeferredDecls; + llvm::StringSet<llvm::BumpPtrAllocator> DeferredResolversToEmit; + /// This is a list of deferred decls which we have seen that *are* actually /// referenced. These get code generated when the module is done. std::vector<GlobalDecl> DeferredDeclsToEmit; @@ -1588,6 +1590,9 @@ private: llvm::AttributeList ExtraAttrs = llvm::AttributeList(), ForDefinition_t IsForDefinition = NotForDefinition); + // Adds a declaration to the list of multi version functions if not present. + void AddDeferredMultiVersionResolverToEmit(GlobalDecl GD); + // References to multiversion functions are resolved through an implicitly // defined resolver function. This function is responsible for creating // the resolver symbol for the provided declaration. The value returned diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp index 2619edfeb7dc76c3e482b3c2da13dfdca1afc74d..76704c4d7be4a49de647c9f64aac615724215bb7 100644 --- a/clang/lib/CodeGen/CodeGenPGO.cpp +++ b/clang/lib/CodeGen/CodeGenPGO.cpp @@ -1239,7 +1239,8 @@ void CodeGenPGO::emitMCDCParameters(CGBuilderTy &Builder) { void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr) { + Address MCDCCondBitmapAddr, + CodeGenFunction &CGF) { if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState) return; @@ -1262,7 +1263,7 @@ void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, Builder.getInt64(FunctionHash), Builder.getInt32(RegionMCDCState->BitmapBytes), Builder.getInt32(MCDCTestVectorBitmapOffset), - MCDCCondBitmapAddr.getPointer()}; + MCDCCondBitmapAddr.emitRawPointer(CGF)}; Builder.CreateCall( CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_tvbitmap_update), Args); } @@ -1283,7 +1284,8 @@ void CodeGenPGO::emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S, void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, Address MCDCCondBitmapAddr, - llvm::Value *Val) { + llvm::Value *Val, + CodeGenFunction &CGF) { if (!canEmitMCDCCoverage(Builder) || !RegionMCDCState) return; @@ -1312,7 +1314,7 @@ void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, llvm::Value *Args[5] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy), Builder.getInt64(FunctionHash), Builder.getInt32(Branch.ID), - MCDCCondBitmapAddr.getPointer(), Val}; + MCDCCondBitmapAddr.emitRawPointer(CGF), Val}; Builder.CreateCall( CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_condbitmap_update), Args); diff --git a/clang/lib/CodeGen/CodeGenPGO.h b/clang/lib/CodeGen/CodeGenPGO.h index 036fbf6815a49da500970580c8ed6057bc317847..9d66ffad6f43509e991ca87c3605c94e27ea8833 100644 --- a/clang/lib/CodeGen/CodeGenPGO.h +++ b/clang/lib/CodeGen/CodeGenPGO.h @@ -113,12 +113,14 @@ public: void emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S, llvm::Value *StepV); void emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr); + Address MCDCCondBitmapAddr, + CodeGenFunction &CGF); void emitMCDCParameters(CGBuilderTy &Builder); void emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S, Address MCDCCondBitmapAddr); void emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, - Address MCDCCondBitmapAddr, llvm::Value *Val); + Address MCDCCondBitmapAddr, llvm::Value *Val, + CodeGenFunction &CGF); /// Return the region count for the counter at the given index. uint64_t getRegionCount(const Stmt *S) { diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index a6b51bfef87652d1b4101c0925ab92640a1ea0af..1568b6e6275b9dee1c65a56f872f2897c24cba0f 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -590,6 +590,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { ResultType = llvm::ArrayType::get(ResultType, 0); break; } + case Type::ArrayParameter: case Type::ConstantArray: { const ConstantArrayType *A = cast<ConstantArrayType>(Ty); llvm::Type *EltTy = ConvertTypeForMem(A->getElementType()); @@ -601,7 +602,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { EltTy = llvm::Type::getInt8Ty(getLLVMContext()); } - ResultType = llvm::ArrayType::get(EltTy, A->getSize().getZExtValue()); + ResultType = llvm::ArrayType::get(EltTy, A->getZExtSize()); break; } case Type::ExtVector: diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 60b45ee78d9316769481a64599b728050fe64b5f..18acf7784f714b4c8d083c086185efd1e45bdec2 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -307,10 +307,6 @@ public: CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, const CXXRecordDecl *NearestVBase); - llvm::Constant * - getVTableAddressPointForConstExpr(BaseSubobject Base, - const CXXRecordDecl *VTableClass) override; - llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) override; @@ -646,7 +642,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( // Apply the adjustment and cast back to the original struct type // for consistency. - llvm::Value *This = ThisAddr.getPointer(); + llvm::Value *This = ThisAddr.emitRawPointer(CGF); This = Builder.CreateInBoundsGEP(Builder.getInt8Ty(), This, Adj); ThisPtrForCall = This; @@ -850,7 +846,7 @@ llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress( CGBuilderTy &Builder = CGF.Builder; // Apply the offset, which we assume is non-null. - return Builder.CreateInBoundsGEP(CGF.Int8Ty, Base.getPointer(), MemPtr, + return Builder.CreateInBoundsGEP(CGF.Int8Ty, Base.emitRawPointer(CGF), MemPtr, "memptr.offset"); } @@ -1245,7 +1241,7 @@ void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, CGF.getPointerAlign()); // Apply the offset. - llvm::Value *CompletePtr = Ptr.getPointer(); + llvm::Value *CompletePtr = Ptr.emitRawPointer(CGF); CompletePtr = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, CompletePtr, Offset); @@ -1482,7 +1478,8 @@ llvm::Value *ItaniumCXXABI::emitDynamicCastCall( computeOffsetHint(CGF.getContext(), SrcDecl, DestDecl).getQuantity()); // Emit the call to __dynamic_cast. - llvm::Value *Args[] = {ThisAddr.getPointer(), SrcRTTI, DestRTTI, OffsetHint}; + llvm::Value *Args[] = {ThisAddr.emitRawPointer(CGF), SrcRTTI, DestRTTI, + OffsetHint}; llvm::Value *Value = CGF.EmitNounwindRuntimeCall(getItaniumDynamicCastFn(CGF), Args); @@ -1571,7 +1568,7 @@ llvm::Value *ItaniumCXXABI::emitExactDynamicCast( VPtr, CGM.getTBAAVTablePtrAccessInfo(CGF.VoidPtrPtrTy)); llvm::Value *Success = CGF.Builder.CreateICmpEQ( VPtr, getVTableAddressPoint(BaseSubobject(SrcDecl, *Offset), DestDecl)); - llvm::Value *Result = ThisAddr.getPointer(); + llvm::Value *Result = ThisAddr.emitRawPointer(CGF); if (!Offset->isZero()) Result = CGF.Builder.CreateInBoundsGEP( CGF.CharTy, Result, @@ -1611,7 +1608,7 @@ llvm::Value *ItaniumCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF, PtrDiffLTy, OffsetToTop, CGF.getPointerAlign(), "offset.to.top"); } // Finally, add the offset to the pointer. - return CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ThisAddr.getPointer(), + return CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ThisAddr.emitRawPointer(CGF), OffsetToTop); } @@ -1792,8 +1789,8 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF, else Callee = CGCallee::forDirect(CGM.getAddrOfCXXStructor(GD), GD); - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, VTT, VTTTy, - nullptr); + CGF.EmitCXXDestructorCall(GD, Callee, CGF.getAsNaturalPointerTo(This, ThisTy), + ThisTy, VTT, VTTTy, nullptr); } void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, @@ -1885,19 +1882,27 @@ ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base, // Find the appropriate vtable within the vtable group, and the address point // within that vtable. + const VTableLayout &Layout = + CGM.getItaniumVTableContext().getVTableLayout(VTableClass); VTableLayout::AddressPointLocation AddressPoint = - CGM.getItaniumVTableContext() - .getVTableLayout(VTableClass) - .getAddressPoint(Base); + Layout.getAddressPoint(Base); llvm::Value *Indices[] = { llvm::ConstantInt::get(CGM.Int32Ty, 0), llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.VTableIndex), llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.AddressPointIndex), }; - return llvm::ConstantExpr::getGetElementPtr(VTable->getValueType(), VTable, - Indices, /*InBounds=*/true, - /*InRangeIndex=*/1); + // Add inrange attribute to indicate that only the VTableIndex can be + // accessed. + unsigned ComponentSize = + CGM.getDataLayout().getTypeAllocSize(CGM.getVTableComponentType()); + unsigned VTableSize = + ComponentSize * Layout.getVTableSize(AddressPoint.VTableIndex); + unsigned Offset = ComponentSize * AddressPoint.AddressPointIndex; + llvm::ConstantRange InRange(llvm::APInt(32, -Offset, true), + llvm::APInt(32, VTableSize - Offset, true)); + return llvm::ConstantExpr::getGetElementPtr( + VTable->getValueType(), VTable, Indices, /*InBounds=*/true, InRange); } // Check whether all the non-inline virtual methods for the class have the @@ -1944,11 +1949,6 @@ llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT( CGF.getPointerAlign()); } -llvm::Constant *ItaniumCXXABI::getVTableAddressPointForConstExpr( - BaseSubobject Base, const CXXRecordDecl *VTableClass) { - return getVTableAddressPoint(Base, VTableClass); -} - llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) { assert(VPtrOffset.isZero() && "Itanium ABI only supports zero vptr offsets"); @@ -2080,8 +2080,8 @@ llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall( ThisTy = D->getDestroyedType(); } - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, nullptr, - QualType(), nullptr); + CGF.EmitCXXDestructorCall(GD, Callee, This.emitRawPointer(CGF), ThisTy, + nullptr, QualType(), nullptr); return nullptr; } @@ -2154,7 +2154,7 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF, int64_t VirtualAdjustment, bool IsReturnAdjustment) { if (!NonVirtualAdjustment && !VirtualAdjustment) - return InitialPtr.getPointer(); + return InitialPtr.emitRawPointer(CGF); Address V = InitialPtr.withElementType(CGF.Int8Ty); @@ -2187,10 +2187,10 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF, CGF.getPointerAlign()); } // Adjust our pointer. - ResultPtr = CGF.Builder.CreateInBoundsGEP( - V.getElementType(), V.getPointer(), Offset); + ResultPtr = CGF.Builder.CreateInBoundsGEP(V.getElementType(), + V.emitRawPointer(CGF), Offset); } else { - ResultPtr = V.getPointer(); + ResultPtr = V.emitRawPointer(CGF); } // In a derived-to-base conversion, the non-virtual adjustment is @@ -2276,7 +2276,7 @@ Address ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, llvm::FunctionType::get(CGM.VoidTy, NumElementsPtr.getType(), false); llvm::FunctionCallee F = CGM.CreateRuntimeFunction(FTy, "__asan_poison_cxx_array_cookie"); - CGF.Builder.CreateCall(F, NumElementsPtr.getPointer()); + CGF.Builder.CreateCall(F, NumElementsPtr.emitRawPointer(CGF)); } // Finally, compute a pointer to the actual data buffer by skipping @@ -2307,7 +2307,7 @@ llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF, llvm::FunctionType::get(CGF.SizeTy, CGF.UnqualPtrTy, false); llvm::FunctionCallee F = CGM.CreateRuntimeFunction(FTy, "__asan_load_cxx_array_cookie"); - return CGF.Builder.CreateCall(F, numElementsPtr.getPointer()); + return CGF.Builder.CreateCall(F, numElementsPtr.emitRawPointer(CGF)); } CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) { @@ -2619,7 +2619,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, // Call __cxa_guard_release. This cannot throw. CGF.EmitNounwindRuntimeCall(getGuardReleaseFn(CGM, guardPtrTy), - guardAddr.getPointer()); + guardAddr.emitRawPointer(CGF)); } else if (D.isLocalVarDecl()) { // For local variables, store 1 into the first byte of the guard variable // after the object initialization completes so that initialization is @@ -3112,10 +3112,10 @@ LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, LValue LV; if (VD->getType()->isReferenceType()) - LV = CGF.MakeNaturalAlignAddrLValue(CallVal, LValType); + LV = CGF.MakeNaturalAlignRawAddrLValue(CallVal, LValType); else - LV = CGF.MakeAddrLValue(CallVal, LValType, - CGF.getContext().getDeclAlign(VD)); + LV = CGF.MakeRawAddrLValue(CallVal, LValType, + CGF.getContext().getDeclAlign(VD)); // FIXME: need setObjCGCLValueClass? return LV; } @@ -3584,6 +3584,9 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) { case Type::Pipe: llvm_unreachable("Pipe types shouldn't get here"); + case Type::ArrayParameter: + llvm_unreachable("Array Parameter types should not get here."); + case Type::Builtin: case Type::BitInt: // GCC treats vector and complex types as fundamental types. @@ -3868,6 +3871,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( case Type::ConstantArray: case Type::IncompleteArray: case Type::VariableArray: + case Type::ArrayParameter: // Itanium C++ ABI 2.9.5p5: // abi::__array_type_info adds no data members to std::type_info. break; @@ -4596,7 +4600,7 @@ static void InitCatchParam(CodeGenFunction &CGF, CGF.Builder.CreateStore(Casted, ExnPtrTmp); // Bind the reference to the temporary. - AdjustedExn = ExnPtrTmp.getPointer(); + AdjustedExn = ExnPtrTmp.emitRawPointer(CGF); } } diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 172c4c937b97280d30ca5689ec58b600a852a809..d38a26940a3cb613a29557019f92b60b49cb7a9e 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -327,10 +327,6 @@ public: CodeGenFunction &CGF, const CXXRecordDecl *VTableClass, BaseSubobject Base, const CXXRecordDecl *NearestVBase) override; - llvm::Constant * - getVTableAddressPointForConstExpr(BaseSubobject Base, - const CXXRecordDecl *VTableClass) override; - llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) override; @@ -937,7 +933,7 @@ void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF, } CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam); - CPI->setArgOperand(2, var.getObjectAddress(CGF).getPointer()); + CPI->setArgOperand(2, var.getObjectAddress(CGF).emitRawPointer(CGF)); CGF.EHStack.pushCleanup<CatchRetScope>(NormalCleanup, CPI); CGF.EmitAutoVarCleanups(var); } @@ -974,7 +970,7 @@ MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address Value, llvm::Value *Offset = GetVirtualBaseClassOffset(CGF, Value, SrcDecl, PolymorphicBase); llvm::Value *Ptr = CGF.Builder.CreateInBoundsGEP( - Value.getElementType(), Value.getPointer(), Offset); + Value.getElementType(), Value.emitRawPointer(CGF), Offset); CharUnits VBaseAlign = CGF.CGM.getVBaseAlignment(Value.getAlignment(), SrcDecl, PolymorphicBase); return std::make_tuple(Address(Ptr, CGF.Int8Ty, VBaseAlign), Offset, @@ -1011,7 +1007,7 @@ llvm::Value *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF, llvm::Type *StdTypeInfoPtrTy) { std::tie(ThisPtr, std::ignore, std::ignore) = performBaseAdjustment(CGF, ThisPtr, SrcRecordTy); - llvm::CallBase *Typeid = emitRTtypeidCall(CGF, ThisPtr.getPointer()); + llvm::CallBase *Typeid = emitRTtypeidCall(CGF, ThisPtr.emitRawPointer(CGF)); return CGF.Builder.CreateBitCast(Typeid, StdTypeInfoPtrTy); } @@ -1033,7 +1029,7 @@ llvm::Value *MicrosoftCXXABI::emitDynamicCastCall( llvm::Value *Offset; std::tie(This, Offset, std::ignore) = performBaseAdjustment(CGF, This, SrcRecordTy); - llvm::Value *ThisPtr = This.getPointer(); + llvm::Value *ThisPtr = This.emitRawPointer(CGF); Offset = CGF.Builder.CreateTrunc(Offset, CGF.Int32Ty); // PVOID __RTDynamicCast( @@ -1065,7 +1061,7 @@ llvm::Value *MicrosoftCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF, llvm::FunctionCallee Function = CGF.CGM.CreateRuntimeFunction( llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false), "__RTCastToVoid"); - llvm::Value *Args[] = {Value.getPointer()}; + llvm::Value *Args[] = {Value.emitRawPointer(CGF)}; return CGF.EmitRuntimeCall(Function, Args); } @@ -1493,7 +1489,7 @@ Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall( llvm::Value *VBaseOffset = GetVirtualBaseClassOffset(CGF, Result, Derived, VBase); llvm::Value *VBasePtr = CGF.Builder.CreateInBoundsGEP( - Result.getElementType(), Result.getPointer(), VBaseOffset); + Result.getElementType(), Result.emitRawPointer(CGF), VBaseOffset); CharUnits VBaseAlign = CGF.CGM.getVBaseAlignment(Result.getAlignment(), Derived, VBase); Result = Address(VBasePtr, CGF.Int8Ty, VBaseAlign); @@ -1660,7 +1656,8 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, llvm::Value *Implicit = getCXXDestructorImplicitParam(CGF, DD, Type, ForVirtualBase, Delegating); // = nullptr - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, + CGF.EmitCXXDestructorCall(GD, Callee, CGF.getAsNaturalPointerTo(This, ThisTy), + ThisTy, /*ImplicitParam=*/Implicit, /*ImplicitParamTy=*/QualType(), nullptr); if (BaseDtorEndBB) { @@ -1791,13 +1788,6 @@ MicrosoftCXXABI::getVTableAddressPoint(BaseSubobject Base, return VFTablesMap[ID]; } -llvm::Constant *MicrosoftCXXABI::getVTableAddressPointForConstExpr( - BaseSubobject Base, const CXXRecordDecl *VTableClass) { - llvm::Constant *VFTable = getVTableAddressPoint(Base, VTableClass); - assert(VFTable && "Couldn't find a vftable for the given base?"); - return VFTable; -} - llvm::GlobalVariable *MicrosoftCXXABI::getAddrOfVTable(const CXXRecordDecl *RD, CharUnits VPtrOffset) { // getAddrOfVTable may return 0 if asked to get an address of a vtable which @@ -2013,8 +2003,9 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall( } This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true); - RValue RV = CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, - ImplicitParam, Context.IntTy, CE); + RValue RV = + CGF.EmitCXXDestructorCall(GD, Callee, This.emitRawPointer(CGF), ThisTy, + ImplicitParam, Context.IntTy, CE); return RV.getScalarVal(); } @@ -2212,13 +2203,13 @@ llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF, Address This, const ThisAdjustment &TA) { if (TA.isEmpty()) - return This.getPointer(); + return This.emitRawPointer(CGF); This = This.withElementType(CGF.Int8Ty); llvm::Value *V; if (TA.Virtual.isEmpty()) { - V = This.getPointer(); + V = This.emitRawPointer(CGF); } else { assert(TA.Virtual.Microsoft.VtordispOffset < 0); // Adjust the this argument based on the vtordisp value. @@ -2227,7 +2218,7 @@ llvm::Value *MicrosoftCXXABI::performThisAdjustment(CodeGenFunction &CGF, CharUnits::fromQuantity(TA.Virtual.Microsoft.VtordispOffset)); VtorDispPtr = VtorDispPtr.withElementType(CGF.Int32Ty); llvm::Value *VtorDisp = CGF.Builder.CreateLoad(VtorDispPtr, "vtordisp"); - V = CGF.Builder.CreateGEP(This.getElementType(), This.getPointer(), + V = CGF.Builder.CreateGEP(This.getElementType(), This.emitRawPointer(CGF), CGF.Builder.CreateNeg(VtorDisp)); // Unfortunately, having applied the vtordisp means that we no @@ -2264,11 +2255,11 @@ llvm::Value * MicrosoftCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret, const ReturnAdjustment &RA) { if (RA.isEmpty()) - return Ret.getPointer(); + return Ret.emitRawPointer(CGF); Ret = Ret.withElementType(CGF.Int8Ty); - llvm::Value *V = Ret.getPointer(); + llvm::Value *V = Ret.emitRawPointer(CGF); if (RA.Virtual.Microsoft.VBIndex) { assert(RA.Virtual.Microsoft.VBIndex > 0); int32_t IntSize = CGF.getIntSize().getQuantity(); @@ -2583,7 +2574,7 @@ struct ResetGuardBit final : EHScopeStack::Cleanup { struct CallInitThreadAbort final : EHScopeStack::Cleanup { llvm::Value *Guard; - CallInitThreadAbort(Address Guard) : Guard(Guard.getPointer()) {} + CallInitThreadAbort(RawAddress Guard) : Guard(Guard.getPointer()) {} void Emit(CodeGenFunction &CGF, Flags flags) override { // Calling _Init_thread_abort will reset the guard's state. @@ -3123,8 +3114,8 @@ MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF, llvm::Value **VBPtrOut) { CGBuilderTy &Builder = CGF.Builder; // Load the vbtable pointer from the vbptr in the instance. - llvm::Value *VBPtr = Builder.CreateInBoundsGEP(CGM.Int8Ty, This.getPointer(), - VBPtrOffset, "vbptr"); + llvm::Value *VBPtr = Builder.CreateInBoundsGEP( + CGM.Int8Ty, This.emitRawPointer(CGF), VBPtrOffset, "vbptr"); if (VBPtrOut) *VBPtrOut = VBPtr; @@ -3203,7 +3194,7 @@ llvm::Value *MicrosoftCXXABI::AdjustVirtualBase( Builder.CreateBr(SkipAdjustBB); CGF.EmitBlock(SkipAdjustBB); llvm::PHINode *Phi = Builder.CreatePHI(CGM.Int8PtrTy, 2, "memptr.base"); - Phi->addIncoming(Base.getPointer(), OriginalBB); + Phi->addIncoming(Base.emitRawPointer(CGF), OriginalBB); Phi->addIncoming(AdjustedBase, VBaseAdjustBB); return Phi; } @@ -3238,7 +3229,7 @@ llvm::Value *MicrosoftCXXABI::EmitMemberDataPointerAddress( Addr = AdjustVirtualBase(CGF, E, RD, Base, VirtualBaseAdjustmentOffset, VBPtrOffset); } else { - Addr = Base.getPointer(); + Addr = Base.emitRawPointer(CGF); } // Apply the offset, which we assume is non-null. @@ -3526,7 +3517,7 @@ CGCallee MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer( ThisPtrForCall = AdjustVirtualBase(CGF, E, RD, This, VirtualBaseAdjustmentOffset, VBPtrOffset); } else { - ThisPtrForCall = This.getPointer(); + ThisPtrForCall = This.emitRawPointer(CGF); } if (NonVirtualBaseAdjustment) @@ -4445,10 +4436,7 @@ void MicrosoftCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) { llvm::GlobalVariable *TI = getThrowInfo(ThrowType); // Call into the runtime to throw the exception. - llvm::Value *Args[] = { - AI.getPointer(), - TI - }; + llvm::Value *Args[] = {AI.emitRawPointer(CGF), TI}; CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(), Args); } diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp index 3594f4c66e677454dc1a2d9618ea3f1815e2b502..df85295cfb2e290534266756ac86fa8ce2f6d882 100644 --- a/clang/lib/CodeGen/ModuleBuilder.cpp +++ b/clang/lib/CodeGen/ModuleBuilder.cpp @@ -180,7 +180,7 @@ namespace { bool HandleTopLevelDecl(DeclGroupRef DG) override { // FIXME: Why not return false and abort parsing? - if (Diags.hasErrorOccurred()) + if (Diags.hasUnrecoverableErrorOccurred()) return true; HandlingTopLevelDeclRAII HandlingDecl(*this); @@ -206,7 +206,7 @@ namespace { } void HandleInlineFunctionDefinition(FunctionDecl *D) override { - if (Diags.hasErrorOccurred()) + if (Diags.hasUnrecoverableErrorOccurred()) return; assert(D->doesThisDeclarationHaveABody()); @@ -233,7 +233,7 @@ namespace { /// client hack on the type, which can occur at any point in the file /// (because these can be defined in declspecs). void HandleTagDeclDefinition(TagDecl *D) override { - if (Diags.hasErrorOccurred()) + if (Diags.hasUnrecoverableErrorOccurred()) return; // Don't allow re-entrant calls to CodeGen triggered by PCH @@ -269,7 +269,7 @@ namespace { } void HandleTagDeclRequiredDefinition(const TagDecl *D) override { - if (Diags.hasErrorOccurred()) + if (Diags.hasUnrecoverableErrorOccurred()) return; // Don't allow re-entrant calls to CodeGen triggered by PCH @@ -283,7 +283,7 @@ namespace { void HandleTranslationUnit(ASTContext &Ctx) override { // Release the Builder when there is no error. - if (!Diags.hasErrorOccurred() && Builder) + if (!Diags.hasUnrecoverableErrorOccurred() && Builder) Builder->Release(); // If there are errors before or when releasing the Builder, reset @@ -297,14 +297,14 @@ namespace { } void AssignInheritanceModel(CXXRecordDecl *RD) override { - if (Diags.hasErrorOccurred()) + if (Diags.hasUnrecoverableErrorOccurred()) return; Builder->RefreshTypeCacheForClass(RD); } void CompleteTentativeDefinition(VarDecl *D) override { - if (Diags.hasErrorOccurred()) + if (Diags.hasUnrecoverableErrorOccurred()) return; Builder->EmitTentativeDefinition(D); @@ -315,7 +315,7 @@ namespace { } void HandleVTable(CXXRecordDecl *RD) override { - if (Diags.hasErrorOccurred()) + if (Diags.hasUnrecoverableErrorOccurred()) return; Builder->EmitVTable(RD); diff --git a/clang/lib/CodeGen/SwiftCallingConv.cpp b/clang/lib/CodeGen/SwiftCallingConv.cpp index 16fbf52a517db48ddf8ebdb0d6887a20f7ea330c..ab2e2bd0b30646557c91f26e8353412990cbd5db 100644 --- a/clang/lib/CodeGen/SwiftCallingConv.cpp +++ b/clang/lib/CodeGen/SwiftCallingConv.cpp @@ -78,7 +78,7 @@ void SwiftAggLowering::addTypedData(QualType type, CharUnits begin) { QualType eltType = arrayType->getElementType(); auto eltSize = CGM.getContext().getTypeSizeInChars(eltType); - for (uint64_t i = 0, e = arrayType->getSize().getZExtValue(); i != e; ++i) { + for (uint64_t i = 0, e = arrayType->getZExtSize(); i != e; ++i) { addTypedData(eltType, begin + i * eltSize); } diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h index 7682f197041c748a4daebc0e15fe19d73eeccaea..b1dfe5bf8f274d1b43c7e3f531faf8da526233a7 100644 --- a/clang/lib/CodeGen/TargetInfo.h +++ b/clang/lib/CodeGen/TargetInfo.h @@ -84,6 +84,11 @@ public: /// Provides a convenient hook to handle extra target-specific globals. virtual void emitTargetGlobals(CodeGen::CodeGenModule &CGM) const {} + /// Any further codegen related checks that need to be done on a function + /// signature in a target specific manner. + virtual void checkFunctionABI(CodeGenModule &CGM, + const FunctionDecl *Decl) const {} + /// Any further codegen related checks that need to be done on a function call /// in a target specific manner. virtual void checkFunctionCallABI(CodeGenModule &CGM, SourceLocation CallLoc, @@ -290,6 +295,11 @@ public: /// Get the AST address space for alloca. virtual LangAS getASTAllocaAddressSpace() const { return LangAS::Default; } + Address performAddrSpaceCast(CodeGen::CodeGenFunction &CGF, Address Addr, + LangAS SrcAddr, LangAS DestAddr, + llvm::Type *DestTy, + bool IsNonNull = false) const; + /// Perform address space cast of an expression of pointer type. /// \param V is the LLVM value to be casted to another address space. /// \param SrcAddr is the language address space of \p V. @@ -416,6 +426,7 @@ enum class AArch64ABIKind { AAPCS = 0, DarwinPCS, Win64, + AAPCSSoft, }; std::unique_ptr<TargetCodeGenInfo> diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index 85117366de0ee8470b1f28f7a2b52a35e9ab4301..4c32f510101f0474529763dfc2b0ea116811e1cf 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -27,6 +27,8 @@ public: AArch64ABIInfo(CodeGenTypes &CGT, AArch64ABIKind Kind) : ABIInfo(CGT), Kind(Kind) {} + bool isSoftFloat() const { return Kind == AArch64ABIKind::AAPCSSoft; } + private: AArch64ABIKind getABIKind() const { return Kind; } bool isDarwinPCS() const { return Kind == AArch64ABIKind::DarwinPCS; } @@ -55,8 +57,8 @@ private: Address EmitDarwinVAArg(Address VAListAddr, QualType Ty, CodeGenFunction &CGF) const; - Address EmitAAPCSVAArg(Address VAListAddr, QualType Ty, - CodeGenFunction &CGF) const; + Address EmitAAPCSVAArg(Address VAListAddr, QualType Ty, CodeGenFunction &CGF, + AArch64ABIKind Kind) const; Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty) const override { @@ -67,7 +69,7 @@ private: return Kind == AArch64ABIKind::Win64 ? EmitMSVAArg(CGF, VAListAddr, Ty) : isDarwinPCS() ? EmitDarwinVAArg(VAListAddr, Ty, CGF) - : EmitAAPCSVAArg(VAListAddr, Ty, CGF); + : EmitAAPCSVAArg(VAListAddr, Ty, CGF, Kind); } Address EmitMSVAArg(CodeGenFunction &CGF, Address VAListAddr, @@ -163,6 +165,9 @@ public: return TargetCodeGenInfo::isScalarizableAsmOperand(CGF, Ty); } + void checkFunctionABI(CodeGenModule &CGM, + const FunctionDecl *Decl) const override; + void checkFunctionCallABI(CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller, const FunctionDecl *Callee, @@ -494,6 +499,11 @@ bool AArch64SwiftABIInfo::isLegalVectorType(CharUnits VectorSize, } bool AArch64ABIInfo::isHomogeneousAggregateBaseType(QualType Ty) const { + // For the soft-float ABI variant, no types are considered to be homogeneous + // aggregates. + if (Kind == AArch64ABIKind::AAPCSSoft) + return false; + // Homogeneous aggregates for AAPCS64 must have base types of a floating // point type or a short-vector type. This is the same as the 32-bit ABI, // but with the difference that any floating-point type is allowed, @@ -525,7 +535,8 @@ bool AArch64ABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate() } Address AArch64ABIInfo::EmitAAPCSVAArg(Address VAListAddr, QualType Ty, - CodeGenFunction &CGF) const { + CodeGenFunction &CGF, + AArch64ABIKind Kind) const { ABIArgInfo AI = classifyArgumentType(Ty, /*IsVariadic=*/true, CGF.CurFnInfo->getCallingConvention()); // Empty records are ignored for parameter passing purposes. @@ -550,7 +561,8 @@ Address AArch64ABIInfo::EmitAAPCSVAArg(Address VAListAddr, QualType Ty, BaseTy = ArrTy->getElementType(); NumRegs = ArrTy->getNumElements(); } - bool IsFPR = BaseTy->isFloatingPointTy() || BaseTy->isVectorTy(); + bool IsFPR = Kind != AArch64ABIKind::AAPCSSoft && + (BaseTy->isFloatingPointTy() || BaseTy->isVectorTy()); // The AArch64 va_list type and handling is specified in the Procedure Call // Standard, section B.4: @@ -841,6 +853,34 @@ static bool isStreamingCompatible(const FunctionDecl *F) { return false; } +void AArch64TargetCodeGenInfo::checkFunctionABI( + CodeGenModule &CGM, const FunctionDecl *FuncDecl) const { + const AArch64ABIInfo &ABIInfo = getABIInfo<AArch64ABIInfo>(); + const TargetInfo &TI = ABIInfo.getContext().getTargetInfo(); + + // If we are using a hard-float ABI, but do not have floating point + // registers, then report an error for any function arguments or returns + // which would be passed in floating-pint registers. + auto CheckType = [&CGM, &TI, &ABIInfo](const QualType &Ty, + const NamedDecl *D) { + const Type *HABase = nullptr; + uint64_t HAMembers = 0; + if (Ty->isFloatingType() || Ty->isVectorType() || + ABIInfo.isHomogeneousAggregate(Ty, HABase, HAMembers)) { + CGM.getDiags().Report(D->getLocation(), + diag::err_target_unsupported_type_for_abi) + << D->getDeclName() << Ty << TI.getABI(); + } + }; + + if (!TI.hasFeature("fp") && !ABIInfo.isSoftFloat()) { + CheckType(FuncDecl->getReturnType(), FuncDecl); + for (ParmVarDecl *PVD : FuncDecl->parameters()) { + CheckType(PVD->getType(), PVD); + } + } +} + void AArch64TargetCodeGenInfo::checkFunctionCallABI( CodeGenModule &CGM, SourceLocation CallLoc, const FunctionDecl *Caller, const FunctionDecl *Callee, const CallArgList &Args) const { diff --git a/clang/lib/CodeGen/Targets/ARM.cpp b/clang/lib/CodeGen/Targets/ARM.cpp index 5d42e6286e525b426341d31f553b8732019bdc05..885d9c77d0e76fd9d62d74c7c54f8bf60809e0b5 100644 --- a/clang/lib/CodeGen/Targets/ARM.cpp +++ b/clang/lib/CodeGen/Targets/ARM.cpp @@ -671,7 +671,7 @@ bool ARMABIInfo::isIllegalVectorType(QualType Ty) const { /// Return true if a type contains any 16-bit floating point vectors bool ARMABIInfo::containsAnyFP16Vectors(QualType Ty) const { if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) { - uint64_t NElements = AT->getSize().getZExtValue(); + uint64_t NElements = AT->getZExtSize(); if (NElements == 0) return false; return containsAnyFP16Vectors(AT->getElementType()); diff --git a/clang/lib/CodeGen/Targets/LoongArch.cpp b/clang/lib/CodeGen/Targets/LoongArch.cpp index 63b9a1fdb988ceba4142c412bbbd1e0c777ac196..3f01d9ad90f132db7230cd835bc41f8313a1eb53 100644 --- a/clang/lib/CodeGen/Targets/LoongArch.cpp +++ b/clang/lib/CodeGen/Targets/LoongArch.cpp @@ -146,7 +146,7 @@ bool LoongArchABIInfo::detectFARsEligibleStructHelper( } if (const ConstantArrayType *ATy = getContext().getAsConstantArrayType(Ty)) { - uint64_t ArraySize = ATy->getSize().getZExtValue(); + uint64_t ArraySize = ATy->getZExtSize(); QualType EltTy = ATy->getElementType(); // Non-zero-length arrays of empty records make the struct ineligible to be // passed via FARs in C++. diff --git a/clang/lib/CodeGen/Targets/NVPTX.cpp b/clang/lib/CodeGen/Targets/NVPTX.cpp index 8718f1ecf3a7e076b70bc3d18e2d668e0783c93a..7dce5042c3dc203b5fc6e4f16903b90cc9eb1c61 100644 --- a/clang/lib/CodeGen/Targets/NVPTX.cpp +++ b/clang/lib/CodeGen/Targets/NVPTX.cpp @@ -85,7 +85,7 @@ private: LValue Src) { llvm::Value *Handle = nullptr; llvm::Constant *C = - llvm::dyn_cast<llvm::Constant>(Src.getAddress(CGF).getPointer()); + llvm::dyn_cast<llvm::Constant>(Src.getAddress(CGF).emitRawPointer(CGF)); // Lookup `addrspacecast` through the constant pointer if any. if (auto *ASC = llvm::dyn_cast_or_null<llvm::AddrSpaceCastOperator>(C)) C = llvm::cast<llvm::Constant>(ASC->getPointerOperand()); diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index 40dddde508c1772da1fcf0475af07b5977b26490..174fddabbbdb6b9284ee82890d41619b2715a76b 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -8,6 +8,7 @@ #include "ABIInfoImpl.h" #include "TargetInfo.h" +#include "clang/Basic/DiagnosticFrontend.h" using namespace clang; using namespace clang::CodeGen; @@ -145,6 +146,9 @@ public: bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF, llvm::Value *Address) const override; + + void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, + CodeGen::CodeGenModule &M) const override; }; } // namespace @@ -265,6 +269,61 @@ bool AIXTargetCodeGenInfo::initDwarfEHRegSizeTable( return PPC_initDwarfEHRegSizeTable(CGF, Address, Is64Bit, /*IsAIX*/ true); } +void AIXTargetCodeGenInfo::setTargetAttributes( + const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &M) const { + if (!isa<llvm::GlobalVariable>(GV)) + return; + + auto *GVar = cast<llvm::GlobalVariable>(GV); + auto GVId = GV->getName(); + + // Is this a global variable specified by the user as toc-data? + bool UserSpecifiedTOC = + llvm::binary_search(M.getCodeGenOpts().TocDataVarsUserSpecified, GVId); + // Assumes the same variable cannot be in both TocVarsUserSpecified and + // NoTocVars. + if (UserSpecifiedTOC || + ((M.getCodeGenOpts().AllTocData) && + !llvm::binary_search(M.getCodeGenOpts().NoTocDataVars, GVId))) { + const unsigned long PointerSize = + GV->getParent()->getDataLayout().getPointerSizeInBits() / 8; + auto *VarD = dyn_cast<VarDecl>(D); + assert(VarD && "Invalid declaration of global variable."); + + ASTContext &Context = D->getASTContext(); + unsigned Alignment = Context.toBits(Context.getDeclAlign(D)) / 8; + const auto *Ty = VarD->getType().getTypePtr(); + const RecordDecl *RDecl = + Ty->isRecordType() ? Ty->getAs<RecordType>()->getDecl() : nullptr; + + bool EmitDiagnostic = UserSpecifiedTOC && GV->hasExternalLinkage(); + auto reportUnsupportedWarning = [&](bool ShouldEmitWarning, StringRef Msg) { + if (ShouldEmitWarning) + M.getDiags().Report(D->getLocation(), diag::warn_toc_unsupported_type) + << GVId << Msg; + }; + if (!Ty || Ty->isIncompleteType()) + reportUnsupportedWarning(EmitDiagnostic, "of incomplete type"); + else if (RDecl && RDecl->hasFlexibleArrayMember()) + reportUnsupportedWarning(EmitDiagnostic, + "it contains a flexible array member"); + else if (VarD->getTLSKind() != VarDecl::TLS_None) + reportUnsupportedWarning(EmitDiagnostic, "of thread local storage"); + else if (PointerSize < Context.getTypeInfo(VarD->getType()).Width / 8) + reportUnsupportedWarning(EmitDiagnostic, + "variable is larger than a pointer"); + else if (PointerSize < Alignment) + reportUnsupportedWarning(EmitDiagnostic, + "variable is aligned wider than a pointer"); + else if (D->hasAttr<SectionAttr>()) + reportUnsupportedWarning(EmitDiagnostic, + "variable has a section attribute"); + else if (GV->hasExternalLinkage() || + (M.getCodeGenOpts().AllTocData && !GV->hasLocalLinkage())) + GVar->addAttribute("toc-data"); + } +} + // PowerPC-32 namespace { /// PPC32_SVR4_ABIInfo - The 32-bit PowerPC ELF (SVR4) ABI information. @@ -454,9 +513,10 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, CharUnits RegSize = CharUnits::fromQuantity((isInt || IsSoftFloatABI) ? 4 : 8); llvm::Value *RegOffset = Builder.CreateMul(NumRegs, Builder.getInt8(RegSize.getQuantity())); - RegAddr = Address( - Builder.CreateInBoundsGEP(CGF.Int8Ty, RegAddr.getPointer(), RegOffset), - DirectTy, RegAddr.getAlignment().alignmentOfArrayElement(RegSize)); + RegAddr = Address(Builder.CreateInBoundsGEP( + CGF.Int8Ty, RegAddr.emitRawPointer(CGF), RegOffset), + DirectTy, + RegAddr.getAlignment().alignmentOfArrayElement(RegSize)); // Increase the used-register count. NumRegs = @@ -492,7 +552,7 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, // Round up address of argument to alignment CharUnits Align = CGF.getContext().getTypeAlignInChars(Ty); if (Align > OverflowAreaAlign) { - llvm::Value *Ptr = OverflowArea.getPointer(); + llvm::Value *Ptr = OverflowArea.emitRawPointer(CGF); OverflowArea = Address(emitRoundPointerUpToAlignment(CGF, Ptr, Align), OverflowArea.getElementType(), Align); } @@ -501,7 +561,7 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAList, // Increase the overflow area. OverflowArea = Builder.CreateConstInBoundsByteGEP(OverflowArea, Size); - Builder.CreateStore(OverflowArea.getPointer(), OverflowAreaAddr); + Builder.CreateStore(OverflowArea.emitRawPointer(CGF), OverflowAreaAddr); CGF.EmitBranch(Cont); } diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp index dec6540230a60fb4d29a0aee42b0111c33e3fe18..7b32c797235621e1df5bb952372a0d538f690a57 100644 --- a/clang/lib/CodeGen/Targets/RISCV.cpp +++ b/clang/lib/CodeGen/Targets/RISCV.cpp @@ -152,7 +152,7 @@ bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, } if (const ConstantArrayType *ATy = getContext().getAsConstantArrayType(Ty)) { - uint64_t ArraySize = ATy->getSize().getZExtValue(); + uint64_t ArraySize = ATy->getZExtSize(); QualType EltTy = ATy->getElementType(); // Non-zero-length arrays of empty records make the struct ineligible for // the FP calling convention in C++. @@ -529,7 +529,10 @@ public: RISCVTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen, unsigned FLen, bool EABI) : TargetCodeGenInfo( - std::make_unique<RISCVABIInfo>(CGT, XLen, FLen, EABI)) {} + std::make_unique<RISCVABIInfo>(CGT, XLen, FLen, EABI)) { + SwiftInfo = + std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false); + } void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const override { diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp index a337a52a94eca940409eb6cb7b5c76bd001668f5..9025a633f328e272901d90ff8effd6222d9842b0 100644 --- a/clang/lib/CodeGen/Targets/Sparc.cpp +++ b/clang/lib/CodeGen/Targets/Sparc.cpp @@ -326,7 +326,7 @@ Address SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Update VAList. Address NextPtr = Builder.CreateConstInBoundsByteGEP(Addr, Stride, "ap.next"); - Builder.CreateStore(NextPtr.getPointer(), VAListAddr); + Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr); return ArgAddr.withElementType(ArgTy); } diff --git a/clang/lib/CodeGen/Targets/SystemZ.cpp b/clang/lib/CodeGen/Targets/SystemZ.cpp index 6eb0c6ef2f7d637bce2093844ea5287c0ee217c2..deaafc85a31576b64379053669cfb678fbfc7cfd 100644 --- a/clang/lib/CodeGen/Targets/SystemZ.cpp +++ b/clang/lib/CodeGen/Targets/SystemZ.cpp @@ -306,7 +306,7 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Update overflow_arg_area_ptr pointer llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP( - OverflowArgArea.getElementType(), OverflowArgArea.getPointer(), + OverflowArgArea.getElementType(), OverflowArgArea.emitRawPointer(CGF), PaddedSizeV, "overflow_arg_area"); CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); @@ -382,10 +382,9 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, Address MemAddr = RawMemAddr.withElementType(DirectTy); // Update overflow_arg_area_ptr pointer - llvm::Value *NewOverflowArgArea = - CGF.Builder.CreateGEP(OverflowArgArea.getElementType(), - OverflowArgArea.getPointer(), PaddedSizeV, - "overflow_arg_area"); + llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP( + OverflowArgArea.getElementType(), OverflowArgArea.emitRawPointer(CGF), + PaddedSizeV, "overflow_arg_area"); CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr); CGF.EmitBranch(ContBlock); diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 2291c991fb11076632ab6419250d7f0b0f90e2e5..1146a851a7715d0099d7d845a682b56d8378d9ac 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -1993,7 +1993,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, // this, but it isn't worth it and would be harder to verify. Current = NoClass; uint64_t EltSize = getContext().getTypeSize(AT->getElementType()); - uint64_t ArraySize = AT->getSize().getZExtValue(); + uint64_t ArraySize = AT->getZExtSize(); // The only case a 256-bit wide vector could be used is when the array // contains a single 256-bit element. Since Lo and Hi logic isn't extended @@ -2295,7 +2295,7 @@ static bool BitsContainNoUserData(QualType Ty, unsigned StartBit, if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) { unsigned EltSize = (unsigned)Context.getTypeSize(AT->getElementType()); - unsigned NumElts = (unsigned)AT->getSize().getZExtValue(); + unsigned NumElts = (unsigned)AT->getZExtSize(); // Check each element to see if the element overlaps with the queried range. for (unsigned i = 0; i != NumElts; ++i) { @@ -2788,12 +2788,11 @@ X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned freeIntRegs, // memory), except in situations involving unions. case X87Up: case SSE: + ++neededSSE; HighPart = GetSSETypeAtOffset(CGT.ConvertType(Ty), 8, Ty, 8); if (Lo == NoClass) // Pass HighPart at offset 8 in memory. return ABIArgInfo::getDirect(HighPart, 8); - - ++neededSSE; break; // AMD64-ABI 3.2.3p3: Rule 4. If the class is SSEUP, the @@ -3019,6 +3018,10 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, ABIArgInfo AI = classifyArgumentType(Ty, 0, neededInt, neededSSE, /*isNamedArg*/false); + // Empty records are ignored for parameter passing purposes. + if (AI.isIgnore()) + return CGF.CreateMemTemp(Ty); + // AMD64-ABI 3.5.7p5: Step 1. Determine whether type may be passed // in the registers. If not go to step 7. if (!neededInt && !neededSSE) diff --git a/clang/lib/CodeGen/Targets/XCore.cpp b/clang/lib/CodeGen/Targets/XCore.cpp index aeb48f851e16936fea7c188e75cdebea3f2df927..88edb781a947b1f4be7efb7b722d034b9be322c7 100644 --- a/clang/lib/CodeGen/Targets/XCore.cpp +++ b/clang/lib/CodeGen/Targets/XCore.cpp @@ -180,7 +180,7 @@ Address XCoreABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Increment the VAList. if (!ArgSize.isZero()) { Address APN = Builder.CreateConstInBoundsByteGEP(AP, ArgSize); - Builder.CreateStore(APN.getPointer(), VAListAddr); + Builder.CreateStore(APN.emitRawPointer(CGF), VAListAddr); } return Val; diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 190782a79a24562d9058de0b53d8edf16b49cdbe..1a0f5f27eda2fcfeb480560df44dafa91648973b 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -87,6 +87,7 @@ #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" #include "llvm/Support/RISCVISAInfo.h" +#include "llvm/Support/Regex.h" #include "llvm/Support/StringSaver.h" #include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" @@ -2196,6 +2197,12 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { return false; } + if (C.getArgs().hasArg(options::OPT_print_std_module_manifest_path)) { + llvm::outs() << GetStdModuleManifestPath(C, C.getDefaultToolChain()) + << '\n'; + return false; + } + if (C.getArgs().hasArg(options::OPT_print_runtime_dir)) { if (std::optional<std::string> RuntimePath = TC.getRuntimePath()) llvm::outs() << *RuntimePath << '\n'; @@ -4638,12 +4645,17 @@ Action *Driver::BuildOffloadingActions(Compilation &C, } } + // HIP code in non-RDC mode will bundle the output if it invoked the linker. + bool ShouldBundleHIP = + C.isOffloadingHostKind(Action::OFK_HIP) && + Args.hasFlag(options::OPT_gpu_bundle_output, + options::OPT_no_gpu_bundle_output, true) && + !Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false) && + !llvm::any_of(OffloadActions, + [](Action *A) { return A->getType() != types::TY_Image; }); + // All kinds exit now in device-only mode except for non-RDC mode HIP. - if (offloadDeviceOnly() && - (!C.isOffloadingHostKind(Action::OFK_HIP) || - !Args.hasFlag(options::OPT_gpu_bundle_output, - options::OPT_no_gpu_bundle_output, true) || - Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false))) + if (offloadDeviceOnly() && !ShouldBundleHIP) return C.MakeAction<OffloadAction>(DDeps, types::TY_Nothing); if (OffloadActions.empty()) @@ -5802,19 +5814,9 @@ static const char *GetModuleOutputPath(Compilation &C, const JobAction &JA, (C.getArgs().hasArg(options::OPT_fmodule_output) || C.getArgs().hasArg(options::OPT_fmodule_output_EQ))); - if (Arg *ModuleOutputEQ = - C.getArgs().getLastArg(options::OPT_fmodule_output_EQ)) - return C.addResultFile(ModuleOutputEQ->getValue(), &JA); - - SmallString<64> OutputPath; - Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o); - if (FinalOutput && C.getArgs().hasArg(options::OPT_c)) - OutputPath = FinalOutput->getValue(); - else - OutputPath = BaseInput; + SmallString<256> OutputPath = + tools::getCXX20NamedModuleOutputPath(C.getArgs(), BaseInput); - const char *Extension = types::getTypeTempSuffix(JA.getType()); - llvm::sys::path::replace_extension(OutputPath, Extension); return C.addResultFile(C.getArgs().MakeArgString(OutputPath.c_str()), &JA); } @@ -6185,6 +6187,51 @@ std::string Driver::GetProgramPath(StringRef Name, const ToolChain &TC) const { return std::string(Name); } +std::string Driver::GetStdModuleManifestPath(const Compilation &C, + const ToolChain &TC) const { + std::string error = "<NOT PRESENT>"; + + switch (TC.GetCXXStdlibType(C.getArgs())) { + case ToolChain::CST_Libcxx: { + auto evaluate = [&](const char *library) -> std::optional<std::string> { + std::string lib = GetFilePath(library, TC); + + // Note when there are multiple flavours of libc++ the module json needs + // to look at the command-line arguments for the proper json. These + // flavours do not exist at the moment, but there are plans to provide a + // variant that is built with sanitizer instrumentation enabled. + + // For example + // StringRef modules = [&] { + // const SanitizerArgs &Sanitize = TC.getSanitizerArgs(C.getArgs()); + // if (Sanitize.needsAsanRt()) + // return "libc++.modules-asan.json"; + // return "libc++.modules.json"; + // }(); + + SmallString<128> path(lib.begin(), lib.end()); + llvm::sys::path::remove_filename(path); + llvm::sys::path::append(path, "libc++.modules.json"); + if (TC.getVFS().exists(path)) + return static_cast<std::string>(path); + + return {}; + }; + + if (std::optional<std::string> result = evaluate("libc++.so"); result) + return *result; + + return evaluate("libc++.a").value_or(error); + } + + case ToolChain::CST_Libstdcxx: + // libstdc++ does not provide Standard library modules yet. + return error; + } + + return error; +} + std::string Driver::GetTemporaryPath(StringRef Prefix, StringRef Suffix) const { SmallString<128> Path; std::error_code EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, Path); @@ -6677,3 +6724,131 @@ llvm::Error driver::expandResponseFiles(SmallVectorImpl<const char *> &Args, return llvm::Error::success(); } + +static const char *GetStableCStr(llvm::StringSet<> &SavedStrings, StringRef S) { + return SavedStrings.insert(S).first->getKeyData(); +} + +/// Apply a list of edits to the input argument lists. +/// +/// The input string is a space separated list of edits to perform, +/// they are applied in order to the input argument lists. Edits +/// should be one of the following forms: +/// +/// '#': Silence information about the changes to the command line arguments. +/// +/// '^': Add FOO as a new argument at the beginning of the command line. +/// +/// '+': Add FOO as a new argument at the end of the command line. +/// +/// 's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command +/// line. +/// +/// 'xOPTION': Removes all instances of the literal argument OPTION. +/// +/// 'XOPTION': Removes all instances of the literal argument OPTION, +/// and the following argument. +/// +/// 'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox' +/// at the end of the command line. +/// +/// \param OS - The stream to write edit information to. +/// \param Args - The vector of command line arguments. +/// \param Edit - The override command to perform. +/// \param SavedStrings - Set to use for storing string representations. +static void applyOneOverrideOption(raw_ostream &OS, + SmallVectorImpl<const char *> &Args, + StringRef Edit, + llvm::StringSet<> &SavedStrings) { + // This does not need to be efficient. + + if (Edit[0] == '^') { + const char *Str = GetStableCStr(SavedStrings, Edit.substr(1)); + OS << "### Adding argument " << Str << " at beginning\n"; + Args.insert(Args.begin() + 1, Str); + } else if (Edit[0] == '+') { + const char *Str = GetStableCStr(SavedStrings, Edit.substr(1)); + OS << "### Adding argument " << Str << " at end\n"; + Args.push_back(Str); + } else if (Edit[0] == 's' && Edit[1] == '/' && Edit.ends_with("/") && + Edit.slice(2, Edit.size() - 1).contains('/')) { + StringRef MatchPattern = Edit.substr(2).split('/').first; + StringRef ReplPattern = Edit.substr(2).split('/').second; + ReplPattern = ReplPattern.slice(0, ReplPattern.size() - 1); + + for (unsigned i = 1, e = Args.size(); i != e; ++i) { + // Ignore end-of-line response file markers + if (Args[i] == nullptr) + continue; + std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]); + + if (Repl != Args[i]) { + OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n"; + Args[i] = GetStableCStr(SavedStrings, Repl); + } + } + } else if (Edit[0] == 'x' || Edit[0] == 'X') { + auto Option = Edit.substr(1); + for (unsigned i = 1; i < Args.size();) { + if (Option == Args[i]) { + OS << "### Deleting argument " << Args[i] << '\n'; + Args.erase(Args.begin() + i); + if (Edit[0] == 'X') { + if (i < Args.size()) { + OS << "### Deleting argument " << Args[i] << '\n'; + Args.erase(Args.begin() + i); + } else + OS << "### Invalid X edit, end of command line!\n"; + } + } else + ++i; + } + } else if (Edit[0] == 'O') { + for (unsigned i = 1; i < Args.size();) { + const char *A = Args[i]; + // Ignore end-of-line response file markers + if (A == nullptr) + continue; + if (A[0] == '-' && A[1] == 'O' && + (A[2] == '\0' || (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' || + ('0' <= A[2] && A[2] <= '9'))))) { + OS << "### Deleting argument " << Args[i] << '\n'; + Args.erase(Args.begin() + i); + } else + ++i; + } + OS << "### Adding argument " << Edit << " at end\n"; + Args.push_back(GetStableCStr(SavedStrings, '-' + Edit.str())); + } else { + OS << "### Unrecognized edit: " << Edit << "\n"; + } +} + +void driver::applyOverrideOptions(SmallVectorImpl<const char *> &Args, + const char *OverrideStr, + llvm::StringSet<> &SavedStrings, + raw_ostream *OS) { + if (!OS) + OS = &llvm::nulls(); + + if (OverrideStr[0] == '#') { + ++OverrideStr; + OS = &llvm::nulls(); + } + + *OS << "### CCC_OVERRIDE_OPTIONS: " << OverrideStr << "\n"; + + // This does not need to be efficient. + + const char *S = OverrideStr; + while (*S) { + const char *End = ::strchr(S, ' '); + if (!End) + End = S + strlen(S); + if (End != S) + applyOneOverrideOption(*OS, Args, std::string(S, End), SavedStrings); + S = End; + if (*S != '\0') + ++S; + } +} diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 56d497eb4c32b86e7f57b1fa2a9758d1d77121a9..8bfe9f02a091d17a01c3c4c4fd48d38c50a25dca 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -487,6 +487,14 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, Add &= ~NotAllowedWithExecuteOnly; if (CfiCrossDso) Add &= ~SanitizerKind::CFIMFCall; + // -fsanitize=undefined does not expand to signed-integer-overflow in + // -fwrapv (implied by -fno-strict-overflow) mode. + if (Add & SanitizerKind::UndefinedGroup) { + bool S = Args.hasFlagNoClaim(options::OPT_fno_strict_overflow, + options::OPT_fstrict_overflow, false); + if (Args.hasFlagNoClaim(options::OPT_fwrapv, options::OPT_fno_wrapv, S)) + Add &= ~SanitizerKind::SignedIntegerOverflow; + } Add &= Supported; if (Add & SanitizerKind::Fuzzer) diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 08b1fd01b3c0ac1a6f3b6542268a6f3c3a7524e6..03450fc0f57b93e9acb16f1ece913f68d88f6a58 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -453,12 +453,6 @@ ToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const { return UnwindTableLevel::None; } -unsigned ToolChain::GetDefaultDwarfVersion() const { - // TODO: Remove the RISC-V special case when R_RISCV_SET_ULEB128 linker - // support becomes more widely available. - return getTriple().isRISCV() ? 4 : 5; -} - Tool *ToolChain::getClang() const { if (!Clang) Clang.reset(new tools::Clang(*this, useIntegratedBackend())); diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp index 3c7049a99982d0d2f22bf4c972a300e621610664..7a62b0f9aec419c2319ec39dfd853c3a059bd1d0 100644 --- a/clang/lib/Driver/ToolChains/AIX.cpp +++ b/clang/lib/Driver/ToolChains/AIX.cpp @@ -433,6 +433,88 @@ void AIX::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args, llvm_unreachable("Unexpected C++ library type; only libc++ is supported."); } +// This function processes all the mtocdata options to build the final +// simplified toc data options to pass to CC1. +static void addTocDataOptions(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CC1Args, + const Driver &D) { + + // Check the global toc-data setting. The default is -mno-tocdata. + // To enable toc-data globally, -mtocdata must be specified. + // Additionally, it must be last to take effect. + const bool TOCDataGloballyinEffect = [&Args]() { + if (const Arg *LastArg = + Args.getLastArg(options::OPT_mtocdata, options::OPT_mno_tocdata)) + return LastArg->getOption().matches(options::OPT_mtocdata); + else + return false; + }(); + + // Currently only supported for small code model. + if (TOCDataGloballyinEffect && + (Args.getLastArgValue(options::OPT_mcmodel_EQ).equals("large") || + Args.getLastArgValue(options::OPT_mcmodel_EQ).equals("medium"))) { + D.Diag(clang::diag::warn_drv_unsupported_tocdata); + return; + } + + enum TOCDataSetting { + AddressInTOC = 0, // Address of the symbol stored in the TOC. + DataInTOC = 1 // Symbol defined in the TOC. + }; + + const TOCDataSetting DefaultTocDataSetting = + TOCDataGloballyinEffect ? DataInTOC : AddressInTOC; + + // Process the list of variables in the explicitly specified options + // -mtocdata= and -mno-tocdata= to see which variables are opposite to + // the global setting of tocdata in TOCDataGloballyinEffect. + // Those that have the opposite setting to TOCDataGloballyinEffect, are added + // to ExplicitlySpecifiedGlobals. + std::set<llvm::StringRef> ExplicitlySpecifiedGlobals; + for (const auto Arg : + Args.filtered(options::OPT_mtocdata_EQ, options::OPT_mno_tocdata_EQ)) { + TOCDataSetting ArgTocDataSetting = + Arg->getOption().matches(options::OPT_mtocdata_EQ) ? DataInTOC + : AddressInTOC; + + if (ArgTocDataSetting != DefaultTocDataSetting) + for (const char *Val : Arg->getValues()) + ExplicitlySpecifiedGlobals.insert(Val); + else + for (const char *Val : Arg->getValues()) + ExplicitlySpecifiedGlobals.erase(Val); + } + + auto buildExceptionList = [](const std::set<llvm::StringRef> &ExplicitValues, + const char *OptionSpelling) { + std::string Option(OptionSpelling); + bool IsFirst = true; + for (const auto &E : ExplicitValues) { + if (!IsFirst) + Option += ","; + + IsFirst = false; + Option += E.str(); + } + return Option; + }; + + // Pass the final tocdata options to CC1 consisting of the default + // tocdata option (-mtocdata/-mno-tocdata) along with the list + // option (-mno-tocdata=/-mtocdata=) if there are any explicitly specified + // variables which would be exceptions to the default setting. + const char *TocDataGlobalOption = + TOCDataGloballyinEffect ? "-mtocdata" : "-mno-tocdata"; + CC1Args.push_back(TocDataGlobalOption); + + const char *TocDataListOption = + TOCDataGloballyinEffect ? "-mno-tocdata=" : "-mtocdata="; + if (!ExplicitlySpecifiedGlobals.empty()) + CC1Args.push_back(Args.MakeArgString(llvm::Twine( + buildExceptionList(ExplicitlySpecifiedGlobals, TocDataListOption)))); +} + void AIX::addClangTargetOptions( const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CC1Args, Action::OffloadKind DeviceOffloadingKind) const { @@ -440,6 +522,11 @@ void AIX::addClangTargetOptions( Args.AddLastArg(CC1Args, options::OPT_mdefault_visibility_export_mapping_EQ); Args.addOptInFlag(CC1Args, options::OPT_mxcoff_roptr, options::OPT_mno_xcoff_roptr); + // Forward last mtocdata/mno_tocdata options to -cc1. + if (Args.hasArg(options::OPT_mtocdata_EQ, options::OPT_mno_tocdata_EQ, + options::OPT_mtocdata)) + addTocDataOptions(Args, CC1Args, getDriver()); + if (Args.hasFlag(options::OPT_fxl_pragma_pack, options::OPT_fno_xl_pragma_pack, true)) CC1Args.push_back("-fxl-pragma-pack"); diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp index aa3b80cb16e55ab3496dbc1da27b33a480398a42..3e6e29584df3ac719a340293419fb2c0a11e6fb5 100644 --- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp +++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp @@ -321,9 +321,11 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, } } - if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, - options::OPT_munaligned_access)) { - if (A->getOption().matches(options::OPT_mno_unaligned_access)) + if (Arg *A = Args.getLastArg( + options::OPT_mstrict_align, options::OPT_mno_strict_align, + options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) { + if (A->getOption().matches(options::OPT_mstrict_align) || + A->getOption().matches(options::OPT_mno_unaligned_access)) Features.push_back("+strict-align"); } else if (Triple.isOSOpenBSD()) Features.push_back("+strict-align"); diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp index ba158b92bb44bacee3566072c00ca3773fedf0d6..a68368c4758651ab9fb60863df294b63285d5582 100644 --- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp +++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp @@ -868,12 +868,16 @@ fp16_fml_fallthrough: } } - // Kernel code has more strict alignment requirements. - if (KernelOrKext) { - Features.push_back("+strict-align"); - } else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, - options::OPT_munaligned_access)) { - if (A->getOption().matches(options::OPT_munaligned_access)) { + if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access, + options::OPT_munaligned_access, + options::OPT_mstrict_align, + options::OPT_mno_strict_align)) { + // Kernel code has more strict alignment requirements. + if (KernelOrKext || + A->getOption().matches(options::OPT_mno_unaligned_access) || + A->getOption().matches(options::OPT_mstrict_align)) { + Features.push_back("+strict-align"); + } else { // No v6M core supports unaligned memory access (v6M ARM ARM A3.2). if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) D.Diag(diag::err_target_unsupported_unaligned) << "v6m"; @@ -881,8 +885,7 @@ fp16_fml_fallthrough: // access either. else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline) D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base"; - } else - Features.push_back("+strict-align"); + } } else { // Assume pre-ARMv6 doesn't support unaligned accesses. // diff --git a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp index 31153a67ad284033d7a63282d093a849d8ec176a..d23f9b36efb9acf0591afe18b133de4a762260b9 100644 --- a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp +++ b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp @@ -165,10 +165,9 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D, } } - // Select the `ual` feature determined by -m[no-]unaligned-access - // or the alias -m[no-]strict-align. - AddTargetFeature(Args, Features, options::OPT_munaligned_access, - options::OPT_mno_unaligned_access, "ual"); + // Select the `ual` feature determined by -m[no-]strict-align. + AddTargetFeature(Args, Features, options::OPT_mno_strict_align, + options::OPT_mstrict_align, "ual"); // Accept but warn about these TargetSpecific options. if (Arg *A = Args.getLastArgNoClaim(options::OPT_mabi_EQ)) diff --git a/clang/lib/Driver/ToolChains/Arch/Mips.cpp b/clang/lib/Driver/ToolChains/Arch/Mips.cpp index fe9d112b8800b17d4ed15b999b9fc9f1f99c9642..74a8874a3ea2b79b1e99d1cb161184a7b340a2d4 100644 --- a/clang/lib/Driver/ToolChains/Arch/Mips.cpp +++ b/clang/lib/Driver/ToolChains/Arch/Mips.cpp @@ -341,6 +341,15 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, "dspr2"); AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa, "msa"); + if (Arg *A = Args.getLastArg( + options::OPT_mstrict_align, options::OPT_mno_strict_align, + options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) { + if (A->getOption().matches(options::OPT_mstrict_align) || + A->getOption().matches(options::OPT_mno_unaligned_access)) + Features.push_back(Args.MakeArgString("+strict-align")); + else + Features.push_back(Args.MakeArgString("-strict-align")); + } // Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32 // pass -mfpxx, or if none are given and fp64a is default, pass fp64 and diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp index a46b44f9ad2b2ddc84cbcb6d1b27ad61dd8935c3..b1dd7c4372d47540497c4dafc62abcfe1b9ebe65 100644 --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -167,9 +167,13 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple, Features.push_back("-relax"); } - // -mno-unaligned-access is default, unless -munaligned-access is specified. - AddTargetFeature(Args, Features, options::OPT_munaligned_access, - options::OPT_mno_unaligned_access, "fast-unaligned-access"); + // Android requires fast unaligned access on RISCV64. + if (Triple.isAndroid()) + Features.push_back("+fast-unaligned-access"); + + // -mstrict-align is default, unless -mno-strict-align is specified. + AddTargetFeature(Args, Features, options::OPT_mno_strict_align, + options::OPT_mstrict_align, "fast-unaligned-access"); // Now add any that the user explicitly requested on the command line, // which may override the defaults. diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 3a7a1cf99c79aca2913d52d5cd5fb7e338832f11..b03ac6018d2b808041c03f20df03aa26c7169856 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1776,6 +1776,9 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, } AddUnalignedAccessWarning(CmdArgs); + + Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_intrinsics, + options::OPT_fno_ptrauth_intrinsics); } void Clang::AddLoongArchTargetArgs(const ArgList &Args, @@ -2687,60 +2690,43 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, } } -static StringRef EnumComplexRangeToStr(LangOptions::ComplexRangeKind Range, - StringRef Option) { +static std::string ComplexRangeKindToStr(LangOptions::ComplexRangeKind Range) { switch (Range) { - case LangOptions::ComplexRangeKind::CX_Limited: - return "-fcx-limited-range"; + case LangOptions::ComplexRangeKind::CX_Full: + return "full"; break; - case LangOptions::ComplexRangeKind::CX_Fortran: - return "-fcx-fortran-rules"; + case LangOptions::ComplexRangeKind::CX_Basic: + return "basic"; break; - default: - return Option; + case LangOptions::ComplexRangeKind::CX_Improved: + return "improved"; + break; + case LangOptions::ComplexRangeKind::CX_Promoted: + return "promoted"; break; + default: + return ""; } } -static void EmitComplexRangeDiag(const Driver &D, - LangOptions::ComplexRangeKind Range1, - LangOptions::ComplexRangeKind Range2, - StringRef Option = StringRef()) { - if (Range1 != Range2 && Range1 != LangOptions::ComplexRangeKind::CX_None) { - bool NegateFortranOption = false; - bool NegateLimitedOption = false; - if (!Option.empty()) { - NegateFortranOption = - Range1 == LangOptions::ComplexRangeKind::CX_Fortran && - Option == "-fno-cx-fortran-rules"; - NegateLimitedOption = - Range1 == LangOptions::ComplexRangeKind::CX_Limited && - Option == "-fno-cx-limited-range"; - } - if (Option.empty() || - (!Option.empty() && !NegateFortranOption && !NegateLimitedOption)) - D.Diag(clang::diag::warn_drv_overriding_option) - << EnumComplexRangeToStr(Range1, Option) - << EnumComplexRangeToStr(Range2, Option); +static std::string ComplexArithmeticStr(LangOptions::ComplexRangeKind Range) { + return (Range == LangOptions::ComplexRangeKind::CX_None) + ? "" + : "-fcomplex-arithmetic=" + ComplexRangeKindToStr(Range); +} + +static void EmitComplexRangeDiag(const Driver &D, std::string str1, + std::string str2) { + if ((str1.compare(str2) != 0) && !str2.empty() && !str1.empty()) { + D.Diag(clang::diag::warn_drv_overriding_option) << str1 << str2; } } static std::string RenderComplexRangeOption(LangOptions::ComplexRangeKind Range) { - std::string ComplexRangeStr = "-complex-range="; - switch (Range) { - case LangOptions::ComplexRangeKind::CX_Full: - ComplexRangeStr += "full"; - break; - case LangOptions::ComplexRangeKind::CX_Limited: - ComplexRangeStr += "limited"; - break; - case LangOptions::ComplexRangeKind::CX_Fortran: - ComplexRangeStr += "fortran"; - break; - default: - assert(0 && "Unexpected range option"); - } + std::string ComplexRangeStr = ComplexRangeKindToStr(Range); + if (!ComplexRangeStr.empty()) + return "-complex-range=" + ComplexRangeStr; return ComplexRangeStr; } @@ -2792,6 +2778,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, StringRef BFloat16ExcessPrecision = ""; LangOptions::ComplexRangeKind Range = LangOptions::ComplexRangeKind::CX_None; std::string ComplexRangeStr = ""; + std::string GccRangeComplexOption = ""; // Lambda to set fast-math options. This is also used by -ffp-model=fast auto applyFastMath = [&]() { @@ -2807,9 +2794,19 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, FPExceptionBehavior = ""; // If fast-math is set then set the fp-contract mode to fast. FPContract = "fast"; - // ffast-math enables limited range rules for complex multiplication and + // ffast-math enables basic range rules for complex multiplication and // division. - Range = LangOptions::ComplexRangeKind::CX_Limited; + // Warn if user expects to perform full implementation of complex + // multiplication or division in the presence of nan or ninf flags. + if (Range == LangOptions::ComplexRangeKind::CX_Full || + Range == LangOptions::ComplexRangeKind::CX_Improved || + Range == LangOptions::ComplexRangeKind::CX_Promoted) + EmitComplexRangeDiag( + D, ComplexArithmeticStr(Range), + !GccRangeComplexOption.empty() + ? GccRangeComplexOption + : ComplexArithmeticStr(LangOptions::ComplexRangeKind::CX_Basic)); + Range = LangOptions::ComplexRangeKind::CX_Basic; SeenUnsafeMathModeOption = true; }; @@ -2824,26 +2821,87 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, switch (optID) { default: break; - case options::OPT_fcx_limited_range: { - EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Limited); - Range = LangOptions::ComplexRangeKind::CX_Limited; + case options::OPT_fcx_limited_range: + if (GccRangeComplexOption.empty()) { + if (Range != LangOptions::ComplexRangeKind::CX_Basic) + EmitComplexRangeDiag(D, RenderComplexRangeOption(Range), + "-fcx-limited-range"); + } else { + if (GccRangeComplexOption != "-fno-cx-limited-range") + EmitComplexRangeDiag(D, GccRangeComplexOption, "-fcx-limited-range"); + } + GccRangeComplexOption = "-fcx-limited-range"; + Range = LangOptions::ComplexRangeKind::CX_Basic; break; - } case options::OPT_fno_cx_limited_range: - EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Full, - "-fno-cx-limited-range"); + if (GccRangeComplexOption.empty()) { + EmitComplexRangeDiag(D, RenderComplexRangeOption(Range), + "-fno-cx-limited-range"); + } else { + if (GccRangeComplexOption.compare("-fcx-limited-range") != 0 && + GccRangeComplexOption.compare("-fno-cx-fortran-rules") != 0) + EmitComplexRangeDiag(D, GccRangeComplexOption, + "-fno-cx-limited-range"); + } + GccRangeComplexOption = "-fno-cx-limited-range"; Range = LangOptions::ComplexRangeKind::CX_Full; break; - case options::OPT_fcx_fortran_rules: { - EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Fortran); - Range = LangOptions::ComplexRangeKind::CX_Fortran; + case options::OPT_fcx_fortran_rules: + if (GccRangeComplexOption.empty()) + EmitComplexRangeDiag(D, RenderComplexRangeOption(Range), + "-fcx-fortran-rules"); + else + EmitComplexRangeDiag(D, GccRangeComplexOption, "-fcx-fortran-rules"); + GccRangeComplexOption = "-fcx-fortran-rules"; + Range = LangOptions::ComplexRangeKind::CX_Improved; break; - } case options::OPT_fno_cx_fortran_rules: - EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Full, - "-fno-cx-fortran-rules"); + if (GccRangeComplexOption.empty()) { + EmitComplexRangeDiag(D, RenderComplexRangeOption(Range), + "-fno-cx-fortran-rules"); + } else { + if (GccRangeComplexOption != "-fno-cx-limited-range") + EmitComplexRangeDiag(D, GccRangeComplexOption, + "-fno-cx-fortran-rules"); + } + GccRangeComplexOption = "-fno-cx-fortran-rules"; Range = LangOptions::ComplexRangeKind::CX_Full; break; + case options::OPT_fcomplex_arithmetic_EQ: { + LangOptions::ComplexRangeKind RangeVal; + StringRef Val = A->getValue(); + if (Val.equals("full")) + RangeVal = LangOptions::ComplexRangeKind::CX_Full; + else if (Val.equals("improved")) + RangeVal = LangOptions::ComplexRangeKind::CX_Improved; + else if (Val.equals("promoted")) + RangeVal = LangOptions::ComplexRangeKind::CX_Promoted; + else if (Val.equals("basic")) + RangeVal = LangOptions::ComplexRangeKind::CX_Basic; + else { + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getSpelling() << Val; + break; + } + if (!GccRangeComplexOption.empty()) { + if (GccRangeComplexOption.compare("-fcx-limited-range") != 0) { + if (GccRangeComplexOption.compare("-fcx-fortran-rules") != 0) { + if (RangeVal != LangOptions::ComplexRangeKind::CX_Improved) + EmitComplexRangeDiag(D, GccRangeComplexOption, + ComplexArithmeticStr(RangeVal)); + } else { + EmitComplexRangeDiag(D, GccRangeComplexOption, + ComplexArithmeticStr(RangeVal)); + } + } else { + if (RangeVal != LangOptions::ComplexRangeKind::CX_Basic) + EmitComplexRangeDiag(D, GccRangeComplexOption, + ComplexArithmeticStr(RangeVal)); + } + } + Range = RangeVal; + break; + } case options::OPT_ffp_model_EQ: { // If -ffp-model= is seen, reset to fno-fast-math HonorINFs = true; @@ -3256,8 +3314,12 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D, if (Range != LangOptions::ComplexRangeKind::CX_None) ComplexRangeStr = RenderComplexRangeOption(Range); - if (!ComplexRangeStr.empty()) + if (!ComplexRangeStr.empty()) { CmdArgs.push_back(Args.MakeArgString(ComplexRangeStr)); + if (Args.hasArg(options::OPT_fcomplex_arithmetic_EQ)) + CmdArgs.push_back(Args.MakeArgString("-fcomplex-arithmetic=" + + ComplexRangeKindToStr(Range))); + } if (Args.hasArg(options::OPT_fcx_limited_range)) CmdArgs.push_back("-fcx-limited-range"); if (Args.hasArg(options::OPT_fcx_fortran_rules)) @@ -3777,6 +3839,24 @@ bool Driver::getDefaultModuleCachePath(SmallVectorImpl<char> &Result) { return false; } +llvm::SmallString<256> +clang::driver::tools::getCXX20NamedModuleOutputPath(const ArgList &Args, + const char *BaseInput) { + if (Arg *ModuleOutputEQ = Args.getLastArg(options::OPT_fmodule_output_EQ)) + return StringRef(ModuleOutputEQ->getValue()); + + SmallString<256> OutputPath; + if (Arg *FinalOutput = Args.getLastArg(options::OPT_o); + FinalOutput && Args.hasArg(options::OPT_c)) + OutputPath = FinalOutput->getValue(); + else + OutputPath = BaseInput; + + const char *Extension = types::getTypeTempSuffix(types::TY_ModuleFile); + llvm::sys::path::replace_extension(OutputPath, Extension); + return OutputPath; +} + static bool RenderModulesOptions(Compilation &C, const Driver &D, const ArgList &Args, const InputInfo &Input, const InputInfo &Output, bool HaveStd20, @@ -5804,8 +5884,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } else if (Triple.getArch() == llvm::Triple::x86_64) { Ok = llvm::is_contained({"small", "kernel", "medium", "large", "tiny"}, CM); - } else if (Triple.isNVPTX() || Triple.isAMDGPU()) { - // NVPTX/AMDGPU does not care about the code model and will accept + } else if (Triple.isNVPTX() || Triple.isAMDGPU() || Triple.isSPIRV()) { + // NVPTX/AMDGPU/SPIRV does not care about the code model and will accept // whatever works for the host. Ok = true; } else if (Triple.isSPARC64()) { @@ -8477,6 +8557,14 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, case llvm::Triple::riscv64: AddRISCVTargetArgs(Args, CmdArgs); break; + + case llvm::Triple::hexagon: + if (Args.hasFlag(options::OPT_mdefault_build_attributes, + options::OPT_mno_default_build_attributes, true)) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-hexagon-add-build-attributes"); + } + break; } // Consume all the warning flags. Usually this would be handled more diff --git a/clang/lib/Driver/ToolChains/Clang.h b/clang/lib/Driver/ToolChains/Clang.h index 0f503c4bd1c4fea9cc45c47159cf40079fef6f63..18f6c5ed06a59aeed6f627f1829b418eb7648a43 100644 --- a/clang/lib/Driver/ToolChains/Clang.h +++ b/clang/lib/Driver/ToolChains/Clang.h @@ -193,6 +193,21 @@ DwarfFissionKind getDebugFissionKind(const Driver &D, const llvm::opt::ArgList &Args, llvm::opt::Arg *&Arg); +// Calculate the output path of the module file when compiling a module unit +// with the `-fmodule-output` option or `-fmodule-output=` option specified. +// The behavior is: +// - If `-fmodule-output=` is specfied, then the module file is +// writing to the value. +// - Otherwise if the output object file of the module unit is specified, the +// output path +// of the module file should be the same with the output object file except +// the corresponding suffix. This requires both `-o` and `-c` are specified. +// - Otherwise, the output path of the module file will be the same with the +// input with the corresponding suffix. +llvm::SmallString<256> +getCXX20NamedModuleOutputPath(const llvm::opt::ArgList &Args, + const char *BaseInput); + } // end namespace tools } // end namespace driver diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 100e71245394d845430bb371ff289d53c5e4af92..62a53b85ce098b89c83a54701e5c4e6d0bd63bd2 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -740,7 +740,8 @@ bool tools::isTLSDESCEnabled(const ToolChain &TC, SupportedArgument = V == "desc" || V == "trad"; EnableTLSDESC = V == "desc"; } else if (Triple.isX86()) { - SupportedArgument = V == "gnu"; + SupportedArgument = V == "gnu" || V == "gnu2"; + EnableTLSDESC = V == "gnu2"; } else { Unsupported = true; } @@ -757,15 +758,15 @@ bool tools::isTLSDESCEnabled(const ToolChain &TC, void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, ArgStringList &CmdArgs, const InputInfo &Output, const InputInfo &Input, bool IsThinLTO) { - const bool IsOSAIX = ToolChain.getTriple().isOSAIX(); - const bool IsAMDGCN = ToolChain.getTriple().isAMDGCN(); + const llvm::Triple &Triple = ToolChain.getTriple(); + const bool IsOSAIX = Triple.isOSAIX(); + const bool IsAMDGCN = Triple.isAMDGCN(); const char *Linker = Args.MakeArgString(ToolChain.GetLinkerPath()); const Driver &D = ToolChain.getDriver(); const bool IsFatLTO = Args.hasArg(options::OPT_ffat_lto_objects); const bool IsUnifiedLTO = Args.hasArg(options::OPT_funified_lto); if (llvm::sys::path::filename(Linker) != "ld.lld" && - llvm::sys::path::stem(Linker) != "ld.lld" && - !ToolChain.getTriple().isOSOpenBSD()) { + llvm::sys::path::stem(Linker) != "ld.lld" && !Triple.isOSOpenBSD()) { // Tell the linker to load the plugin. This has to come before // AddLinkerInputs as gold requires -plugin and AIX ld requires -bplugin to // come before any -plugin-opt/-bplugin_opt that -Wl might forward. @@ -834,7 +835,7 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, // the plugin. // Handle flags for selecting CPU variants. - std::string CPU = getCPUName(D, Args, ToolChain.getTriple()); + std::string CPU = getCPUName(D, Args, Triple); if (!CPU.empty()) CmdArgs.push_back( Args.MakeArgString(Twine(PluginOptPrefix) + ExtraDash + "mcpu=" + CPU)); @@ -965,10 +966,9 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, bool HasRoptr = Args.hasFlag(options::OPT_mxcoff_roptr, options::OPT_mno_xcoff_roptr, false); StringRef OptStr = HasRoptr ? "-mxcoff-roptr" : "-mno-xcoff-roptr"; - if (!IsOSAIX) D.Diag(diag::err_drv_unsupported_opt_for_target) - << OptStr << ToolChain.getTriple().str(); + << OptStr << Triple.str(); if (HasRoptr) { // The data sections option is on by default on AIX. We only need to error @@ -1031,7 +1031,7 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, } if (Args.hasFlag(options::OPT_femulated_tls, options::OPT_fno_emulated_tls, - ToolChain.getTriple().hasDefaultEmulatedTLS())) { + Triple.hasDefaultEmulatedTLS())) { CmdArgs.push_back( Args.MakeArgString(Twine(PluginOptPrefix) + "-emulated-tls")); } @@ -1075,14 +1075,14 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, /// Adds the '-lcgpu' and '-lmgpu' libraries to the compilation to include the /// LLVM C library for GPUs. -static void addOpenMPDeviceLibC(const ToolChain &TC, const ArgList &Args, +static void addOpenMPDeviceLibC(const Compilation &C, const ArgList &Args, ArgStringList &CmdArgs) { if (Args.hasArg(options::OPT_nogpulib) || Args.hasArg(options::OPT_nolibc)) return; // Check the resource directory for the LLVM libc GPU declarations. If it's // found we can assume that LLVM was built with support for the GPU libc. - SmallString<256> LibCDecls(TC.getDriver().ResourceDir); + SmallString<256> LibCDecls(C.getDriver().ResourceDir); llvm::sys::path::append(LibCDecls, "include", "llvm_libc_wrappers", "llvm-libc-decls"); bool HasLibC = llvm::sys::fs::exists(LibCDecls) && @@ -1090,38 +1090,23 @@ static void addOpenMPDeviceLibC(const ToolChain &TC, const ArgList &Args, if (!Args.hasFlag(options::OPT_gpulibc, options::OPT_nogpulibc, HasLibC)) return; - // We don't have access to the offloading toolchains here, so determine from - // the arguments if we have any active NVPTX or AMDGPU toolchains. - llvm::DenseSet<const char *> Libraries; - if (const Arg *Targets = Args.getLastArg(options::OPT_fopenmp_targets_EQ)) { - if (llvm::any_of(Targets->getValues(), - [](auto S) { return llvm::Triple(S).isAMDGPU(); })) { - Libraries.insert("-lcgpu-amdgpu"); - Libraries.insert("-lmgpu-amdgpu"); - } - if (llvm::any_of(Targets->getValues(), - [](auto S) { return llvm::Triple(S).isNVPTX(); })) { - Libraries.insert("-lcgpu-nvptx"); - Libraries.insert("-lmgpu-nvptx"); - } - } + SmallVector<const ToolChain *> ToolChains; + auto TCRange = C.getOffloadToolChains(Action::OFK_OpenMP); + for (auto TI = TCRange.first, TE = TCRange.second; TI != TE; ++TI) + ToolChains.push_back(TI->second); - for (StringRef Arch : Args.getAllArgValues(options::OPT_offload_arch_EQ)) { - if (llvm::any_of(llvm::split(Arch, ","), [](StringRef Str) { - return IsAMDGpuArch(StringToCudaArch(Str)); - })) { - Libraries.insert("-lcgpu-amdgpu"); - Libraries.insert("-lmgpu-amdgpu"); - } - if (llvm::any_of(llvm::split(Arch, ","), [](StringRef Str) { - return IsNVIDIAGpuArch(StringToCudaArch(Str)); - })) { - Libraries.insert("-lcgpu-nvptx"); - Libraries.insert("-lmgpu-nvptx"); - } + if (llvm::any_of(ToolChains, [](const ToolChain *TC) { + return TC->getTriple().isAMDGPU(); + })) { + CmdArgs.push_back("-lcgpu-amdgpu"); + CmdArgs.push_back("-lmgpu-amdgpu"); + } + if (llvm::any_of(ToolChains, [](const ToolChain *TC) { + return TC->getTriple().isNVPTX(); + })) { + CmdArgs.push_back("-lcgpu-nvptx"); + CmdArgs.push_back("-lmgpu-nvptx"); } - - llvm::append_range(CmdArgs, Libraries); } void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC, @@ -1141,7 +1126,11 @@ void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args, options::OPT_fno_rtlib_add_rpath, false)) return; - for (const auto &CandidateRPath : TC.getArchSpecificLibPaths()) { + SmallVector<std::string> CandidateRPaths(TC.getArchSpecificLibPaths()); + if (const auto CandidateRPath = TC.getStdlibPath()) + CandidateRPaths.emplace_back(*CandidateRPath); + + for (const auto &CandidateRPath : CandidateRPaths) { if (TC.getVFS().exists(CandidateRPath)) { CmdArgs.push_back("-rpath"); CmdArgs.push_back(Args.MakeArgString(CandidateRPath)); @@ -1149,9 +1138,10 @@ void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args, } } -bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC, - const ArgList &Args, bool ForceStaticHostRuntime, - bool IsOffloadingHost, bool GompNeedsRT) { +bool tools::addOpenMPRuntime(const Compilation &C, ArgStringList &CmdArgs, + const ToolChain &TC, const ArgList &Args, + bool ForceStaticHostRuntime, bool IsOffloadingHost, + bool GompNeedsRT) { if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, options::OPT_fno_openmp, false)) return false; @@ -1192,7 +1182,7 @@ bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC, CmdArgs.push_back("-lomptarget.devicertl"); if (IsOffloadingHost) - addOpenMPDeviceLibC(TC, Args, CmdArgs); + addOpenMPDeviceLibC(C, Args, CmdArgs); addArchSpecificRPath(TC, Args, CmdArgs); addOpenMPRuntimeLibraryPath(TC, Args, CmdArgs); @@ -2829,7 +2819,7 @@ void tools::addHIPRuntimeLibArgs(const ToolChain &TC, Compilation &C, llvm::opt::ArgStringList &CmdArgs) { if ((C.getActiveOffloadKinds() & Action::OFK_HIP) && !Args.hasArg(options::OPT_nostdlib) && - !Args.hasArg(options::OPT_no_hip_rt)) { + !Args.hasArg(options::OPT_no_hip_rt) && !Args.hasArg(options::OPT_r)) { TC.AddHIPRuntimeLibArgs(Args, CmdArgs); } else { // Claim "no HIP libraries" arguments if any diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h index bb37be4bd6ea05f04d08f3abad37ec256a59850f..5581905db3114463c118802e7d721d9e5a68f0d0 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -111,8 +111,8 @@ void addOpenMPRuntimeLibraryPath(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs); /// Returns true, if an OpenMP runtime has been added. -bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC, - const llvm::opt::ArgList &Args, +bool addOpenMPRuntime(const Compilation &C, llvm::opt::ArgStringList &CmdArgs, + const ToolChain &TC, const llvm::opt::ArgList &Args, bool ForceStaticHostRuntime = false, bool IsOffloadingHost = false, bool GompNeedsRT = false); diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp index c6007d3cfab8643ec7bb1510e1fde1dc4f7967cb..5f0b516e1a1a08f0d40bec2c8f66ba42a277c1b2 100644 --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -750,10 +750,12 @@ NVPTXToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args, if (!llvm::is_contained(*DAL, A)) DAL->append(A); - // TODO: We should accept 'generic' as a valid architecture. if (!DAL->hasArg(options::OPT_march_EQ) && OffloadKind != Action::OFK_None) { DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ), CudaArchToString(CudaArch::CudaDefault)); + } else if (DAL->getLastArgValue(options::OPT_march_EQ) == "generic" && + OffloadKind == Action::OFK_None) { + DAL->eraseArg(options::OPT_march_EQ); } else if (DAL->getLastArgValue(options::OPT_march_EQ) == "native") { auto GPUsOrErr = getSystemGPUArchs(Args); if (!GPUsOrErr) { diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index c7682c7f1d337999670b7ccfd3fa4e84ff0540b5..caf6c4a444fdcec76007c09ffc73c15bc4d3002c 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -686,7 +686,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA, } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) - addOpenMPRuntime(CmdArgs, getToolChain(), Args); + addOpenMPRuntime(C, CmdArgs, getToolChain(), Args); if (isObjCRuntimeLinked(Args) && !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { diff --git a/clang/lib/Driver/ToolChains/DragonFly.cpp b/clang/lib/Driver/ToolChains/DragonFly.cpp index b59a172bd6ae869633e65ccd436b9bfcb42c3195..1dbc46763c1156c47a771a326e38f268ea7f189b 100644 --- a/clang/lib/Driver/ToolChains/DragonFly.cpp +++ b/clang/lib/Driver/ToolChains/DragonFly.cpp @@ -136,7 +136,7 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA, // Use the static OpenMP runtime with -static-openmp bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static; - addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); + addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP); if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 6168b42dc78292d9d3aebf8a809c5257a0cf502f..70daa699e3a9497b6e8cf4cc59dc4d798d3f5608 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -148,7 +148,6 @@ void Flang::addCodegenOptions(const ArgList &Args, Args.addAllArgs(CmdArgs, {options::OPT_flang_experimental_hlfir, options::OPT_flang_deprecated_no_hlfir, - options::OPT_flang_experimental_polymorphism, options::OPT_fno_ppc_native_vec_elem_order, options::OPT_fppc_native_vec_elem_order}); } diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp index c5757ddebb0f3eed4b96200be1f5f0243d93dd03..a8ee6540001ee4faeef7ad5303c4c4b741314314 100644 --- a/clang/lib/Driver/ToolChains/FreeBSD.cpp +++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp @@ -295,7 +295,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, // Use the static OpenMP runtime with -static-openmp bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Args.hasArg(options::OPT_static); - addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); + addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP); if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index a9c9d2475809d70d73a13829829ffe8cb62d5ba9..dedbfac6cb25d26b67587d4ed273597366f1296d 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -598,7 +598,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, // FIXME: Only pass GompNeedsRT = true for platforms with libgomp that // require librt. Most modern Linux platforms do, but some may not. - if (addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP, + if (addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP, JA.isHostOffloading(Action::OFK_OpenMP), /* GompNeedsRT= */ true)) // OpenMP runtimes implies pthreads when using the GNU toolchain. diff --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp index c6ad862b229420b79a852660104d74bf0fe7c349..1169b5d8c92dd683495736b429809e1dd452f207 100644 --- a/clang/lib/Driver/ToolChains/HLSL.cpp +++ b/clang/lib/Driver/ToolChains/HLSL.cpp @@ -226,6 +226,21 @@ HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch, A->claim(); continue; } + if (A->getOption().getID() == options::OPT_dxc_hlsl_version) { + // Translate -HV into -std for llvm + // depending on the value given + LangStandard::Kind LangStd = LangStandard::getHLSLLangKind(A->getValue()); + if (LangStd != LangStandard::lang_unspecified) { + LangStandard l = LangStandard::getLangStandardForKind(LangStd); + DAL->AddSeparateArg(nullptr, Opts.getOption(options::OPT_std_EQ), + l.getName()); + } else { + getDriver().Diag(diag::err_drv_invalid_value) << "HV" << A->getValue(); + } + + A->claim(); + continue; + } DAL->append(A); } @@ -240,9 +255,7 @@ HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch, if (!DAL->hasArg(options::OPT_O_Group)) { DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_O), "3"); } - // FIXME: add validation for enable_16bit_types should be after HLSL 2018 and - // shader model 6.2. - // See: https://github.com/llvm/llvm-project/issues/57876 + return DAL; } diff --git a/clang/lib/Driver/ToolChains/Haiku.cpp b/clang/lib/Driver/ToolChains/Haiku.cpp index 30464e2229e65be28b81ddf7941320b754607233..346652a7e4bd8e4581699553769c87f56dda4353 100644 --- a/clang/lib/Driver/ToolChains/Haiku.cpp +++ b/clang/lib/Driver/ToolChains/Haiku.cpp @@ -107,7 +107,7 @@ void haiku::Linker::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_r)) { // Use the static OpenMP runtime with -static-openmp bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static; - addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); + addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP); if (D.CCCIsCXX() && ToolChain.ShouldLinkCXXStdlib(Args)) ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp index dc534a33e6d0efe6549e670b8cea660feb8b35d1..fbf2f45b543844827f388bcd24fc88b9e9b6f842 100644 --- a/clang/lib/Driver/ToolChains/MSVC.cpp +++ b/clang/lib/Driver/ToolChains/MSVC.cpp @@ -79,6 +79,11 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back( Args.MakeArgString(std::string("-out:") + Output.getFilename())); + if (Args.hasArg(options::OPT_marm64x)) + CmdArgs.push_back("-machine:arm64x"); + else if (TC.getTriple().isWindowsArm64EC()) + CmdArgs.push_back("-machine:arm64ec"); + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) && !C.getDriver().IsCLMode() && !C.getDriver().IsFlangMode()) { CmdArgs.push_back("-defaultlib:libcmt"); @@ -1017,4 +1022,7 @@ void MSVCToolChain::addClangTargetOptions( if (DriverArgs.hasFlag(options::OPT_fno_rtti, options::OPT_frtti, /*Default=*/false)) CC1Args.push_back("-D_HAS_STATIC_RTTI=0"); + + if (Arg *A = DriverArgs.getLastArgNoClaim(options::OPT_marm64x)) + A->ignoreTargetSpecific(); } diff --git a/clang/lib/Driver/ToolChains/NetBSD.cpp b/clang/lib/Driver/ToolChains/NetBSD.cpp index 0eec8fddabd5db6c53f18162549fc5516be95ddb..d54f2288294949f7f649931a86512b07a038a956 100644 --- a/clang/lib/Driver/ToolChains/NetBSD.cpp +++ b/clang/lib/Driver/ToolChains/NetBSD.cpp @@ -311,7 +311,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_r)) { // Use the static OpenMP runtime with -static-openmp bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static; - addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); + addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP); if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp index 6da6728585df93582b6e00ad6fc92264910239e6..e20d9fb1cfc41748cf81fd18ab4ad13f32a9284d 100644 --- a/clang/lib/Driver/ToolChains/OpenBSD.cpp +++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp @@ -221,7 +221,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_r)) { // Use the static OpenMP runtime with -static-openmp bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static; - addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); + addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP); if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) diff --git a/clang/lib/Driver/ToolChains/Solaris.cpp b/clang/lib/Driver/ToolChains/Solaris.cpp index 5d7f0ae2a392a675d454a0aa8834c2cfb2efdb5a..7126e018ca5b6f4db3ffe118156b22e544d25f4a 100644 --- a/clang/lib/Driver/ToolChains/Solaris.cpp +++ b/clang/lib/Driver/ToolChains/Solaris.cpp @@ -211,7 +211,7 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, // Use the static OpenMP runtime with -static-openmp bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Args.hasArg(options::OPT_static); - addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); + addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP); if (D.CCCIsCXX()) { if (ToolChain.ShouldLinkCXXStdlib(Args)) diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp index b8c2573d6265fb941d0cc9d0d6dc64952a67d1c5..b7c6efab83e8065d0531de458527e38ef169f26a 100644 --- a/clang/lib/Driver/ToolChains/WebAssembly.cpp +++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp @@ -44,8 +44,15 @@ std::string wasm::Linker::getLinkerPath(const ArgList &Args) const { llvm::sys::fs::can_execute(UseLinker)) return std::string(UseLinker); - // Accept 'lld', and 'ld' as aliases for the default linker - if (UseLinker != "lld" && UseLinker != "ld") + // Interpret 'lld' as explicitly requesting `wasm-ld`, so look for that + // linker. Note that for `wasm32-wasip2` this overrides the default linker + // of `wasm-component-ld`. + if (UseLinker == "lld") { + return ToolChain.GetProgramPath("wasm-ld"); + } + + // Allow 'ld' as an alias for the default linker + if (UseLinker != "ld") ToolChain.getDriver().Diag(diag::err_drv_invalid_linker_name) << A->getAsString(Args); } @@ -73,6 +80,16 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_s)) CmdArgs.push_back("--strip-all"); + // On `wasip2` the default linker is `wasm-component-ld` which wraps the + // execution of `wasm-ld`. Find `wasm-ld` and pass it as an argument of where + // to find it to avoid it needing to hunt and rediscover or search `PATH` for + // where it is. + if (llvm::sys::path::stem(Linker).ends_with_insensitive( + "wasm-component-ld")) { + CmdArgs.push_back("--wasm-ld-path"); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetProgramPath("wasm-ld"))); + } + Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u}); ToolChain.AddFilePathLibArgs(Args, CmdArgs); @@ -221,6 +238,12 @@ WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple, } } +const char *WebAssembly::getDefaultLinker() const { + if (getOS() == "wasip2") + return "wasm-component-ld"; + return "wasm-ld"; +} + bool WebAssembly::IsMathErrnoDefault() const { return false; } bool WebAssembly::IsObjCNonFragileABIDefault() const { return true; } diff --git a/clang/lib/Driver/ToolChains/WebAssembly.h b/clang/lib/Driver/ToolChains/WebAssembly.h index ae60f464c1081854de1356d9d989345d1314f9b9..76e0ca39bd748d8775aad58113cecaeb3681ca06 100644 --- a/clang/lib/Driver/ToolChains/WebAssembly.h +++ b/clang/lib/Driver/ToolChains/WebAssembly.h @@ -67,7 +67,7 @@ private: llvm::opt::ArgStringList &CmdArgs) const override; SanitizerMask getSupportedSanitizers() const override; - const char *getDefaultLinker() const override { return "wasm-ld"; } + const char *getDefaultLinker() const override; CXXStdlibType GetDefaultCXXStdlibType() const override { return ToolChain::CST_Libcxx; diff --git a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp index 22f2c47e1d6a13ce02519177432dd90fcfb2f46a..81797c8c4dc75a21f0ab2d48fd6a03ae974a4008 100644 --- a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp +++ b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -1000,6 +1000,7 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg, case CK_LValueToRValue: case CK_NoOp: case CK_UserDefinedConversion: + case CK_HLSLArrayRValue: break; case CK_IntegralCast: { diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 80a0a498dc40016238cb5bc9ae21bebbe8344afd..22b98e07c2c8909b4cc5e14f8d6e162517a49d12 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -14,14 +14,11 @@ #include "clang/ExtractAPI/DeclarationFragments.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/QualTypeNames.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" -#include "clang/Basic/OperatorKinds.h" #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h" #include "clang/Index/USRGeneration.h" #include "llvm/ADT/StringSwitch.h" -#include <typeinfo> using namespace clang::extractapi; using namespace llvm; @@ -535,9 +532,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) { getFragmentsForType(T, Var->getASTContext(), After); if (StringRef(ArgumentFragment.begin()->Spelling) .starts_with("type-parameter")) { - std::string ProperArgName = getNameForTemplateArgument( - Var->getDescribedVarTemplate()->getTemplateParameters()->asArray(), - ArgumentFragment.begin()->Spelling); + std::string ProperArgName = T.getAsString(); ArgumentFragment.begin()->Spelling.swap(ProperArgName); } Fragments.append(std::move(ArgumentFragment)) @@ -570,12 +565,7 @@ DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) { if (StringRef(TypeFragments.begin()->Spelling) .starts_with("type-parameter")) { - std::string ProperArgName = getNameForTemplateArgument( - dyn_cast<FunctionDecl>(Param->getDeclContext()) - ->getDescribedFunctionTemplate() - ->getTemplateParameters() - ->asArray(), - TypeFragments.begin()->Spelling); + std::string ProperArgName = Param->getOriginalType().getAsString(); TypeFragments.begin()->Spelling.swap(ProperArgName); } @@ -668,11 +658,7 @@ DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) { getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After); if (StringRef(ReturnValueFragment.begin()->Spelling) .starts_with("type-parameter")) { - std::string ProperArgName = - getNameForTemplateArgument(Func->getDescribedFunctionTemplate() - ->getTemplateParameters() - ->asArray(), - ReturnValueFragment.begin()->Spelling); + std::string ProperArgName = Func->getReturnType().getAsString(); ReturnValueFragment.begin()->Spelling.swap(ProperArgName); } @@ -961,25 +947,6 @@ DeclarationFragmentsBuilder::getFragmentsForTemplateParameters( return Fragments; } -// Find the name of a template argument from the template's parameters. -std::string DeclarationFragmentsBuilder::getNameForTemplateArgument( - const ArrayRef<NamedDecl *> TemplateParameters, std::string TypeParameter) { - // The arg is a generic parameter from a partial spec, e.g. - // T in template<typename T> Foo<T, int>. - // - // Those names appear as "type-parameter-<index>-<depth>", so we must find its - // name from the template's parameter list. - for (unsigned i = 0; i < TemplateParameters.size(); ++i) { - const auto *Parameter = - dyn_cast<TemplateTypeParmDecl>(TemplateParameters[i]); - if (TypeParameter.compare("type-parameter-" + - std::to_string(Parameter->getDepth()) + "-" + - std::to_string(Parameter->getIndex())) == 0) - return std::string(TemplateParameters[i]->getName()); - } - llvm_unreachable("Could not find the name of a template argument."); -} - // Get fragments for template arguments, e.g. int in template<typename T> // Foo<int>; // @@ -989,7 +956,7 @@ std::string DeclarationFragmentsBuilder::getNameForTemplateArgument( DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTemplateArguments( const ArrayRef<TemplateArgument> TemplateArguments, ASTContext &Context, - const std::optional<ArrayRef<NamedDecl *>> TemplateParameters) { + const std::optional<ArrayRef<TemplateArgumentLoc>> TemplateArgumentLocs) { DeclarationFragments Fragments; for (unsigned i = 0, end = TemplateArguments.size(); i != end; ++i) { if (i) @@ -1003,8 +970,10 @@ DeclarationFragmentsBuilder::getFragmentsForTemplateArguments( if (StringRef(ArgumentFragment.begin()->Spelling) .starts_with("type-parameter")) { - std::string ProperArgName = getNameForTemplateArgument( - TemplateParameters.value(), ArgumentFragment.begin()->Spelling); + std::string ProperArgName = TemplateArgumentLocs.value()[i] + .getTypeSourceInfo() + ->getType() + .getAsString(); ArgumentFragment.begin()->Spelling.swap(ProperArgName); } Fragments.append(std::move(ArgumentFragment)); @@ -1089,7 +1058,7 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization( .append("<", DeclarationFragments::FragmentKind::Text) .append(getFragmentsForTemplateArguments( Decl->getTemplateArgs().asArray(), Decl->getASTContext(), - Decl->getTemplateParameters()->asArray())) + Decl->getTemplateArgsAsWritten()->arguments())) .append(">", DeclarationFragments::FragmentKind::Text) .append(";", DeclarationFragments::FragmentKind::Text); } @@ -1130,7 +1099,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization( .append("<", DeclarationFragments::FragmentKind::Text) .append(getFragmentsForTemplateArguments( Decl->getTemplateArgs().asArray(), Decl->getASTContext(), - Decl->getTemplateParameters()->asArray())) + Decl->getTemplateArgsAsWritten()->arguments())) .append(">", DeclarationFragments::FragmentKind::Text) .append(";", DeclarationFragments::FragmentKind::Text); } diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index 349b93e2a2326f77b34b56aa4ee51f89038e1612..545860acb7db804fbe99321698b28db30ecc1eac 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -208,6 +208,7 @@ StringRef getLanguageName(Language Lang) { case Language::Unknown: case Language::Asm: case Language::LLVM_IR: + case Language::CIR: llvm_unreachable("Unsupported language kind"); } diff --git a/clang/lib/Format/.clang-format b/clang/lib/Format/.clang-format index f95602cab0f7fcdf5d34c485d52b65993dbb83d9..d7331b3c8cf02ef7944e83a4280476627e33b31d 100644 --- a/clang/lib/Format/.clang-format +++ b/clang/lib/Format/.clang-format @@ -1,6 +1 @@ -BasedOnStyle: LLVM -InsertBraces: true -InsertNewlineAtEOF: true -LineEnding: LF -RemoveBracesLLVM: true -RemoveParentheses: ReturnStatement +BasedOnStyle: clang-format diff --git a/clang/lib/Format/BreakableToken.h b/clang/lib/Format/BreakableToken.h index e7c0680641e294e940332887e5e1e9fe370e1916..8b9360a3335ef41965d5448793a358417d85f4df 100644 --- a/clang/lib/Format/BreakableToken.h +++ b/clang/lib/Format/BreakableToken.h @@ -18,11 +18,8 @@ #define LLVM_CLANG_LIB_FORMAT_BREAKABLETOKEN_H #include "Encoding.h" -#include "TokenAnnotator.h" #include "WhitespaceManager.h" #include "llvm/ADT/StringSet.h" -#include "llvm/Support/Regex.h" -#include <utility> namespace clang { namespace format { diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index df44e6994c478440f183ab06b366ec439f2a43f7..700bce35c86839a516079441676cd21e5ff099c2 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -822,6 +822,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, !CurrentState.IsCSharpGenericTypeConstraint && Previous.opensScope() && Previous.isNot(TT_ObjCMethodExpr) && Previous.isNot(TT_RequiresClause) && Previous.isNot(TT_TableGenDAGArgOpener) && + Previous.isNot(TT_TableGenDAGArgOpenerToBreak) && !(Current.MacroParent && Previous.MacroParent) && (Current.isNot(TT_LineComment) || Previous.isOneOf(BK_BracedInit, TT_VerilogMultiLineListLParen))) { @@ -1444,7 +1445,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { Style.BreakInheritanceList == FormatStyle::BILS_AfterColon) { return CurrentState.Indent; } - if (Previous.is(tok::r_paren) && !Current.isBinaryOperator() && + if (Previous.is(tok::r_paren) && + Previous.isNot(TT_TableGenDAGArgOperatorToBreak) && + !Current.isBinaryOperator() && !Current.isOneOf(tok::colon, tok::comment)) { return ContinuationIndent; } @@ -1705,7 +1708,8 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State, (Style.AlignAfterOpenBracket != FormatStyle::BAS_DontAlign || PrecedenceLevel != prec::Comma || Current.NestingLevel == 0) && (!Style.isTableGen() || - (Previous && Previous->is(TT_TableGenDAGArgListComma)))) { + (Previous && Previous->isOneOf(TT_TableGenDAGArgListComma, + TT_TableGenDAGArgListCommaToBreak)))) { NewParenState.Indent = std::max( std::max(State.Column, NewParenState.Indent), CurrentState.LastSpace); } @@ -1842,6 +1846,17 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, Style.ContinuationIndentWidth + std::max(CurrentState.LastSpace, CurrentState.StartOfFunctionCall); + if (Style.isTableGen() && Current.is(TT_TableGenDAGArgOpenerToBreak) && + Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakElements) { + // For the case the next token is a TableGen DAGArg operator identifier + // that is not marked to have a line break after it. + // In this case the option DAS_BreakElements requires to align the + // DAGArg elements to the operator. + const FormatToken *Next = Current.Next; + if (Next && Next->is(TT_TableGenDAGArgOperatorID)) + NewIndent = State.Column + Next->TokenText.size() + 2; + } + // Ensure that different different brackets force relative alignment, e.g.: // void SomeFunction(vector< // break // int> v); diff --git a/clang/lib/Format/ContinuationIndenter.h b/clang/lib/Format/ContinuationIndenter.h index 2598947bb624c52b5bbb78a1c6946212004fd10c..18441e10a124924c111e7bb68954e6c12ffc4f9b 100644 --- a/clang/lib/Format/ContinuationIndenter.h +++ b/clang/lib/Format/ContinuationIndenter.h @@ -17,11 +17,6 @@ #include "Encoding.h" #include "FormatToken.h" -#include "clang/Format/Format.h" -#include "llvm/Support/Regex.h" -#include <map> -#include <optional> -#include <tuple> namespace clang { class SourceManager; diff --git a/clang/lib/Format/Encoding.h b/clang/lib/Format/Encoding.h index a0d664121b2bba6a7fa492446696c7600aac04f9..12f9043bb95ad89106b8fc6dcc4c185833fa3641 100644 --- a/clang/lib/Format/Encoding.h +++ b/clang/lib/Format/Encoding.h @@ -16,7 +16,6 @@ #define LLVM_CLANG_LIB_FORMAT_ENCODING_H #include "clang/Basic/LLVM.h" -#include "llvm/ADT/StringRef.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Unicode.h" diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index e64ba7eebc1ce81f48197a5bf3fb1b3e89c200b8..e41cf2902a681897e219b745e7271261bf83c88d 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -13,44 +13,16 @@ //===----------------------------------------------------------------------===// #include "clang/Format/Format.h" -#include "AffectedRangeManager.h" -#include "BreakableToken.h" -#include "ContinuationIndenter.h" #include "DefinitionBlockSeparator.h" -#include "FormatInternal.h" -#include "FormatToken.h" -#include "FormatTokenLexer.h" #include "IntegerLiteralSeparatorFixer.h" #include "NamespaceEndCommentsFixer.h" #include "ObjCPropertyAttributeOrderFixer.h" #include "QualifierAlignmentFixer.h" #include "SortJavaScriptImports.h" -#include "TokenAnalyzer.h" -#include "TokenAnnotator.h" #include "UnwrappedLineFormatter.h" -#include "UnwrappedLineParser.h" #include "UsingDeclarationsSorter.h" -#include "WhitespaceManager.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/DiagnosticOptions.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Lex/Lexer.h" #include "clang/Tooling/Inclusions/HeaderIncludes.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Sequence.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/Regex.h" -#include "llvm/Support/VirtualFileSystem.h" -#include "llvm/Support/YAMLTraits.h" -#include <algorithm> -#include <memory> -#include <mutex> -#include <optional> -#include <string> -#include <unordered_map> #define DEBUG_TYPE "format-formatter" @@ -307,6 +279,14 @@ struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> { } }; +template <> struct ScalarEnumerationTraits<FormatStyle::DAGArgStyle> { + static void enumeration(IO &IO, FormatStyle::DAGArgStyle &Value) { + IO.enumCase(Value, "DontBreak", FormatStyle::DAS_DontBreak); + IO.enumCase(Value, "BreakElements", FormatStyle::DAS_BreakElements); + IO.enumCase(Value, "BreakAll", FormatStyle::DAS_BreakAll); + } +}; + template <> struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> { static void @@ -915,6 +895,8 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("AlignConsecutiveMacros", Style.AlignConsecutiveMacros); IO.mapOptional("AlignConsecutiveShortCaseStatements", Style.AlignConsecutiveShortCaseStatements); + IO.mapOptional("AlignConsecutiveTableGenBreakingDAGArgColons", + Style.AlignConsecutiveTableGenBreakingDAGArgColons); IO.mapOptional("AlignConsecutiveTableGenCondOperatorColons", Style.AlignConsecutiveTableGenCondOperatorColons); IO.mapOptional("AlignConsecutiveTableGenDefinitionColons", @@ -973,6 +955,8 @@ template <> struct MappingTraits<FormatStyle> { Style.BreakBeforeTernaryOperators); IO.mapOptional("BreakConstructorInitializers", Style.BreakConstructorInitializers); + IO.mapOptional("BreakFunctionDefinitionParameters", + Style.BreakFunctionDefinitionParameters); IO.mapOptional("BreakInheritanceList", Style.BreakInheritanceList); IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals); IO.mapOptional("BreakTemplateDeclarations", @@ -1120,6 +1104,10 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("StatementAttributeLikeMacros", Style.StatementAttributeLikeMacros); IO.mapOptional("StatementMacros", Style.StatementMacros); + IO.mapOptional("TableGenBreakingDAGArgOperators", + Style.TableGenBreakingDAGArgOperators); + IO.mapOptional("TableGenBreakInsideDAGArg", + Style.TableGenBreakInsideDAGArg); IO.mapOptional("TabWidth", Style.TabWidth); IO.mapOptional("TypeNames", Style.TypeNames); IO.mapOptional("TypenameMacros", Style.TypenameMacros); @@ -1424,6 +1412,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.AlignConsecutiveDeclarations = {}; LLVMStyle.AlignConsecutiveMacros = {}; LLVMStyle.AlignConsecutiveShortCaseStatements = {}; + LLVMStyle.AlignConsecutiveTableGenBreakingDAGArgColons = {}; LLVMStyle.AlignConsecutiveTableGenCondOperatorColons = {}; LLVMStyle.AlignConsecutiveTableGenDefinitionColons = {}; LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right; @@ -1478,6 +1467,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline; LLVMStyle.BreakBeforeTernaryOperators = true; LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; + LLVMStyle.BreakFunctionDefinitionParameters = false; LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon; LLVMStyle.BreakStringLiterals = true; LLVMStyle.BreakTemplateDeclarations = FormatStyle::BTDS_MultiLine; @@ -1580,6 +1570,8 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.StatementAttributeLikeMacros.push_back("Q_EMIT"); LLVMStyle.StatementMacros.push_back("Q_UNUSED"); LLVMStyle.StatementMacros.push_back("QT_REQUIRE_VERSION"); + LLVMStyle.TableGenBreakingDAGArgOperators = {}; + LLVMStyle.TableGenBreakInsideDAGArg = FormatStyle::DAS_DontBreak; LLVMStyle.TabWidth = 8; LLVMStyle.UseTab = FormatStyle::UT_Never; LLVMStyle.VerilogBreakBetweenInstancePorts = true; diff --git a/clang/lib/Format/FormatInternal.h b/clang/lib/Format/FormatInternal.h index 9043ce32e9e32aa157ee90acd691a5138d71bc25..60c5bf6b786b04f49238fd43ec15771a73d871a7 100644 --- a/clang/lib/Format/FormatInternal.h +++ b/clang/lib/Format/FormatInternal.h @@ -15,7 +15,9 @@ #ifndef LLVM_CLANG_LIB_FORMAT_FORMATINTERNAL_H #define LLVM_CLANG_LIB_FORMAT_FORMATINTERNAL_H -#include "BreakableToken.h" +#include "clang/Basic/LLVM.h" +#include "clang/Format/Format.h" +#include "clang/Tooling/Core/Replacement.h" #include <utility> namespace clang { diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index f4566e4a335138ebcf359af24a76f86ae8a3c3c9..48b6a9092a8c094531dd170cd7fba93b3a35adf7 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -19,8 +19,6 @@ #include "clang/Basic/OperatorPrecedence.h" #include "clang/Format/Format.h" #include "clang/Lex/Lexer.h" -#include <memory> -#include <optional> #include <unordered_set> namespace clang { @@ -154,8 +152,13 @@ namespace format { TYPE(TableGenCondOperatorComma) \ TYPE(TableGenDAGArgCloser) \ TYPE(TableGenDAGArgListColon) \ + TYPE(TableGenDAGArgListColonToAlign) \ TYPE(TableGenDAGArgListComma) \ + TYPE(TableGenDAGArgListCommaToBreak) \ TYPE(TableGenDAGArgOpener) \ + TYPE(TableGenDAGArgOpenerToBreak) \ + TYPE(TableGenDAGArgOperatorID) \ + TYPE(TableGenDAGArgOperatorToBreak) \ TYPE(TableGenListCloser) \ TYPE(TableGenListOpener) \ TYPE(TableGenMultiLineString) \ @@ -571,6 +574,9 @@ public: /// Is optional and can be removed. bool Optional = false; + /// Might be function declaration open/closing paren. + bool MightBeFunctionDeclParen = false; + /// Number of optional braces to be inserted after this token: /// -1: a single left brace /// 0: no braces diff --git a/clang/lib/Format/FormatTokenLexer.h b/clang/lib/Format/FormatTokenLexer.h index 65dd733bd53352a4b1be96b360090fde180fba50..277cc0a2dfde6663e84fe6d14716db98f8d874fd 100644 --- a/clang/lib/Format/FormatTokenLexer.h +++ b/clang/lib/Format/FormatTokenLexer.h @@ -17,14 +17,9 @@ #include "Encoding.h" #include "FormatToken.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/SourceLocation.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Format/Format.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringSet.h" -#include "llvm/Support/Regex.h" #include <stack> diff --git a/clang/lib/Format/FormatTokenSource.h b/clang/lib/Format/FormatTokenSource.h index 7819244eb7d19a489e11556c1253cbc5c9f297e1..cce19f527a9236df8dc8df12cdcfbe09cf87bd6e 100644 --- a/clang/lib/Format/FormatTokenSource.h +++ b/clang/lib/Format/FormatTokenSource.h @@ -15,10 +15,7 @@ #ifndef LLVM_CLANG_LIB_FORMAT_FORMATTOKENSOURCE_H #define LLVM_CLANG_LIB_FORMAT_FORMATTOKENSOURCE_H -#include "FormatToken.h" #include "UnwrappedLineParser.h" -#include "llvm/ADT/DenseMap.h" -#include <cstddef> #define DEBUG_TYPE "format-token-source" diff --git a/clang/lib/Format/Macros.h b/clang/lib/Format/Macros.h index d2f7fe502364cd5550756ea1292f8d17affeba25..fb12d22299dead2a8037595a3d351f7773bea59d 100644 --- a/clang/lib/Format/Macros.h +++ b/clang/lib/Format/Macros.h @@ -39,15 +39,9 @@ #define CLANG_LIB_FORMAT_MACROS_H #include <list> -#include <map> -#include <string> -#include <vector> #include "FormatToken.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" namespace clang { namespace format { diff --git a/clang/lib/Format/SortJavaScriptImports.h b/clang/lib/Format/SortJavaScriptImports.h index 7336db9537b0d5512e0132fca0c81513572c6371..b55b149aab4cd25881e9b6e2209f956d19e0f47c 100644 --- a/clang/lib/Format/SortJavaScriptImports.h +++ b/clang/lib/Format/SortJavaScriptImports.h @@ -14,10 +14,7 @@ #ifndef LLVM_CLANG_LIB_FORMAT_SORTJAVASCRIPTIMPORTS_H #define LLVM_CLANG_LIB_FORMAT_SORTJAVASCRIPTIMPORTS_H -#include "clang/Basic/LLVM.h" #include "clang/Format/Format.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" namespace clang { namespace format { diff --git a/clang/lib/Format/TokenAnalyzer.h b/clang/lib/Format/TokenAnalyzer.h index 4086dab1c94c3ad6a11fba34ad271e196392829d..b7494c395c8a29b36c8654ea2b2849b8437f8033 100644 --- a/clang/lib/Format/TokenAnalyzer.h +++ b/clang/lib/Format/TokenAnalyzer.h @@ -17,19 +17,8 @@ #define LLVM_CLANG_LIB_FORMAT_TOKENANALYZER_H #include "AffectedRangeManager.h" -#include "Encoding.h" -#include "FormatToken.h" #include "FormatTokenLexer.h" #include "TokenAnnotator.h" -#include "UnwrappedLineParser.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/DiagnosticOptions.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Format/Format.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/Debug.h" -#include <memory> namespace clang { namespace format { diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index d7b84e309e09644fabc2604b6dc11615a6c1411e..a405a348403bdffe0d52b2fe1dd796f63ddab462 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -975,12 +975,15 @@ private: // DagArg ::= Value [":" TokVarName] | TokVarName // Appears as a part of SimpleValue6. - bool parseTableGenDAGArg() { + bool parseTableGenDAGArg(bool AlignColon = false) { if (tryToParseTableGenTokVar()) return true; if (parseTableGenValue()) { if (CurrentToken && CurrentToken->is(tok::colon)) { - CurrentToken->setType(TT_TableGenDAGArgListColon); + if (AlignColon) + CurrentToken->setType(TT_TableGenDAGArgListColonToAlign); + else + CurrentToken->setType(TT_TableGenDAGArgListColon); skipToNextNonComment(); return tryToParseTableGenTokVar(); } @@ -989,16 +992,59 @@ private: return false; } + // Judge if the token is a operator ID to insert line break in DAGArg. + // That is, TableGenBreakingDAGArgOperators is empty (by the definition of the + // option) or the token is in the list. + bool isTableGenDAGArgBreakingOperator(const FormatToken &Tok) { + auto &Opes = Style.TableGenBreakingDAGArgOperators; + // If the list is empty, all operators are breaking operators. + if (Opes.empty()) + return true; + // Otherwise, the operator is limited to normal identifiers. + if (Tok.isNot(tok::identifier) || + Tok.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator)) { + return false; + } + // The case next is colon, it is not a operator of identifier. + if (!Tok.Next || Tok.Next->is(tok::colon)) + return false; + return std::find(Opes.begin(), Opes.end(), Tok.TokenText.str()) != + Opes.end(); + } + // SimpleValue6 ::= "(" DagArg [DagArgList] ")" // This parses SimpleValue 6's inside part of "(" ")" bool parseTableGenDAGArgAndList(FormatToken *Opener) { + FormatToken *FirstTok = CurrentToken; if (!parseTableGenDAGArg()) return false; + bool BreakInside = false; + if (Style.TableGenBreakInsideDAGArg != FormatStyle::DAS_DontBreak) { + // Specialized detection for DAGArgOperator, that determines the way of + // line break for this DAGArg elements. + if (isTableGenDAGArgBreakingOperator(*FirstTok)) { + // Special case for identifier DAGArg operator. + BreakInside = true; + Opener->setType(TT_TableGenDAGArgOpenerToBreak); + if (FirstTok->isOneOf(TT_TableGenBangOperator, + TT_TableGenCondOperator)) { + // Special case for bang/cond operators. Set the whole operator as + // the DAGArg operator. Always break after it. + CurrentToken->Previous->setType(TT_TableGenDAGArgOperatorToBreak); + } else if (FirstTok->is(tok::identifier)) { + if (Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakAll) + FirstTok->setType(TT_TableGenDAGArgOperatorToBreak); + else + FirstTok->setType(TT_TableGenDAGArgOperatorID); + } + } + } // Parse the [DagArgList] part bool FirstDAGArgListElm = true; while (CurrentToken) { if (!FirstDAGArgListElm && CurrentToken->is(tok::comma)) { - CurrentToken->setType(TT_TableGenDAGArgListComma); + CurrentToken->setType(BreakInside ? TT_TableGenDAGArgListCommaToBreak + : TT_TableGenDAGArgListComma); skipToNextNonComment(); } if (CurrentToken && CurrentToken->is(tok::r_paren)) { @@ -1008,8 +1054,11 @@ private: skipToNextNonComment(); return true; } - if (!parseTableGenDAGArg()) + if (!parseTableGenDAGArg( + BreakInside && + Style.AlignConsecutiveTableGenBreakingDAGArgColons.Enabled)) { return false; + } FirstDAGArgListElm = false; } return false; @@ -1501,6 +1550,7 @@ private: (!Previous->isAttribute() && !Previous->isOneOf(TT_RequiresClause, TT_LeadingJavaAnnotation))) { Line.MightBeFunctionDecl = true; + Tok->MightBeFunctionDeclParen = true; } } break; @@ -2704,10 +2754,9 @@ private: } // Heuristically try to determine whether the parentheses contain a type. - auto IsQualifiedPointerOrReference = [this](FormatToken *T) { + auto IsQualifiedPointerOrReference = [](FormatToken *T, bool IsCpp) { // This is used to handle cases such as x = (foo *const)&y; assert(!T->isTypeName(IsCpp) && "Should have already been checked"); - (void)IsCpp; // Avoid -Wunused-lambda-capture when assertion is disabled. // Strip trailing qualifiers such as const or volatile when checking // whether the parens could be a cast to a pointer/reference type. while (T) { @@ -2740,7 +2789,7 @@ private: !Tok.Previous || Tok.Previous->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) || Tok.Previous->isTypeName(IsCpp) || - IsQualifiedPointerOrReference(Tok.Previous); + IsQualifiedPointerOrReference(Tok.Previous, IsCpp); bool ParensCouldEndDecl = Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater); if (ParensAreType && !ParensCouldEndDecl) @@ -3596,6 +3645,13 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current, if (!Current.Tok.getIdentifierInfo()) return false; + const auto &Previous = *Current.Previous; + + if (const auto *PrevPrev = Previous.Previous; + PrevPrev && PrevPrev->is(TT_ObjCDecl)) { + return false; + } + auto skipOperatorName = [IsCpp](const FormatToken *Next) -> const FormatToken * { for (; Next; Next = Next->Next) { @@ -3635,18 +3691,17 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current, // Find parentheses of parameter list. const FormatToken *Next = Current.Next; if (Current.is(tok::kw_operator)) { - const auto *Previous = Current.Previous; - if (Previous->Tok.getIdentifierInfo() && - !Previous->isOneOf(tok::kw_return, tok::kw_co_return)) { + if (Previous.Tok.getIdentifierInfo() && + !Previous.isOneOf(tok::kw_return, tok::kw_co_return)) { return true; } - if (Previous->is(tok::r_paren) && Previous->is(TT_TypeDeclarationParen)) { - assert(Previous->MatchingParen); - assert(Previous->MatchingParen->is(tok::l_paren)); - assert(Previous->MatchingParen->is(TT_TypeDeclarationParen)); + if (Previous.is(tok::r_paren) && Previous.is(TT_TypeDeclarationParen)) { + assert(Previous.MatchingParen); + assert(Previous.MatchingParen->is(tok::l_paren)); + assert(Previous.MatchingParen->is(TT_TypeDeclarationParen)); return true; } - if (!Previous->isPointerOrReference() && Previous->isNot(TT_TemplateCloser)) + if (!Previous.isPointerOrReference() && Previous.isNot(TT_TemplateCloser)) return false; Next = skipOperatorName(Next); } else { @@ -4268,6 +4323,10 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, return Left.is(tok::hash); if (Left.isOneOf(tok::hashhash, tok::hash)) return Right.is(tok::hash); + if (Left.is(BK_Block) && Right.is(tok::r_brace) && + Right.MatchingParen == &Left && Line.Children.empty()) { + return Style.SpaceInEmptyBlock; + } if ((Left.is(tok::l_paren) && Right.is(tok::r_paren)) || (Left.is(tok::l_brace) && Left.isNot(BK_Block) && Right.is(tok::r_brace) && Right.isNot(BK_Block))) { @@ -4298,9 +4357,11 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, if (Left.is(tok::kw_auto) && Right.isOneOf(tok::l_paren, tok::l_brace)) return false; + const auto *BeforeLeft = Left.Previous; + // operator co_await(x) - if (Right.is(tok::l_paren) && Left.is(tok::kw_co_await) && Left.Previous && - Left.Previous->is(tok::kw_operator)) { + if (Right.is(tok::l_paren) && Left.is(tok::kw_co_await) && BeforeLeft && + BeforeLeft->is(tok::kw_operator)) { return false; } // co_await (x), co_yield (x), co_return (x) @@ -4335,8 +4396,10 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, } if (Left.is(tok::colon)) return Left.isNot(TT_ObjCMethodExpr); - if (Left.is(tok::coloncolon)) - return false; + if (Left.is(tok::coloncolon)) { + return Right.is(tok::star) && Right.is(TT_PointerOrReference) && + Style.PointerAlignment != FormatStyle::PAS_Left; + } if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less)) { if (Style.Language == FormatStyle::LK_TextProto || (Style.Language == FormatStyle::LK_Proto && @@ -4351,8 +4414,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, return false; } if (Right.is(tok::ellipsis)) { - return Left.Tok.isLiteral() || (Left.is(tok::identifier) && Left.Previous && - Left.Previous->is(tok::kw_case)); + return Left.Tok.isLiteral() || (Left.is(tok::identifier) && BeforeLeft && + BeforeLeft->is(tok::kw_case)); } if (Left.is(tok::l_square) && Right.is(tok::amp)) return Style.SpacesInSquareBrackets; @@ -4420,8 +4483,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, if (Right.is(tok::l_brace) && Right.is(BK_Block)) return true; // for (auto a = 0, b = 0; const auto& c : {1, 2, 3}) - if (Left.Previous && Left.Previous->isTypeOrIdentifier(IsCpp) && - Right.Next && Right.Next->is(TT_RangeBasedForLoopColon)) { + if (BeforeLeft && BeforeLeft->isTypeOrIdentifier(IsCpp) && Right.Next && + Right.Next->is(TT_RangeBasedForLoopColon)) { return getTokenPointerOrReferenceAlignment(Left) != FormatStyle::PAS_Right; } @@ -4443,12 +4506,17 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, startsWithInitStatement(Line)))) { return false; } - return Left.Previous && !Left.Previous->isOneOf( - tok::l_paren, tok::coloncolon, tok::l_square); + if (!BeforeLeft) + return false; + if (BeforeLeft->is(tok::coloncolon)) { + return Left.is(tok::star) && + Style.PointerAlignment != FormatStyle::PAS_Right; + } + return !BeforeLeft->isOneOf(tok::l_paren, tok::l_square); } // Ensure right pointer alignment with ellipsis e.g. int *...P - if (Left.is(tok::ellipsis) && Left.Previous && - Left.Previous->isPointerOrReference()) { + if (Left.is(tok::ellipsis) && BeforeLeft && + BeforeLeft->isPointerOrReference()) { return Style.PointerAlignment != FormatStyle::PAS_Right; } @@ -4610,13 +4678,13 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, return Style.SpaceBeforeParensOptions.AfterFunctionDefinitionName || spaceRequiredBeforeParens(Right); } - if (!Left.Previous || Left.Previous->isNot(tok::period)) { + if (!BeforeLeft || !BeforeLeft->isOneOf(tok::period, tok::arrow)) { if (Left.isOneOf(tok::kw_try, Keywords.kw___except, tok::kw_catch)) { return Style.SpaceBeforeParensOptions.AfterControlStatements || spaceRequiredBeforeParens(Right); } if (Left.isOneOf(tok::kw_new, tok::kw_delete)) { - return ((!Line.MightBeFunctionDecl || !Left.Previous) && + return ((!Line.MightBeFunctionDecl || !BeforeLeft) && Style.SpaceBeforeParens != FormatStyle::SBPO_Never) || spaceRequiredBeforeParens(Right); } @@ -4760,6 +4828,10 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, Right.is(TT_TemplateOpener)) { return true; } + if (Left.is(tok::identifier) && Right.is(tok::numeric_constant) && + Right.TokenText[0] == '.') { + return false; + } } else if (Style.isProto()) { if (Right.is(tok::period) && Left.isOneOf(Keywords.kw_optional, Keywords.kw_required, @@ -5077,12 +5149,19 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, if (Left.is(tok::r_brace) && Right.is(tok::r_square)) return true; // Do not insert around colon in DAGArg and cond operator. - if (Right.is(TT_TableGenDAGArgListColon) || - Left.is(TT_TableGenDAGArgListColon)) { + if (Right.isOneOf(TT_TableGenDAGArgListColon, + TT_TableGenDAGArgListColonToAlign) || + Left.isOneOf(TT_TableGenDAGArgListColon, + TT_TableGenDAGArgListColonToAlign)) { return false; } if (Right.is(TT_TableGenCondOperatorColon)) return false; + if (Left.isOneOf(TT_TableGenDAGArgOperatorID, + TT_TableGenDAGArgOperatorToBreak) && + Right.isNot(TT_TableGenDAGArgCloser)) { + return true; + } // Do not insert bang operators and consequent openers. if (Right.isOneOf(tok::l_paren, tok::less) && Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator)) { @@ -5314,6 +5393,12 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, if (Right.NewlinesBefore > 1 && Style.MaxEmptyLinesToKeep > 0) return true; + if (Style.BreakFunctionDefinitionParameters && Line.MightBeFunctionDecl && + Line.mightBeFunctionDefinition() && Left.MightBeFunctionDeclParen && + Left.ParameterCount > 0) { + return true; + } + if (Style.isCSharp()) { if (Left.is(TT_FatArrow) && Right.is(tok::l_brace) && Style.BraceWrapping.AfterFunction) { @@ -5459,6 +5544,18 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, // case2:0); if (Left.is(TT_TableGenCondOperatorComma)) return true; + if (Left.is(TT_TableGenDAGArgOperatorToBreak) && + Right.isNot(TT_TableGenDAGArgCloser)) { + return true; + } + if (Left.is(TT_TableGenDAGArgListCommaToBreak)) + return true; + if (Right.is(TT_TableGenDAGArgCloser) && Right.MatchingParen && + Right.MatchingParen->is(TT_TableGenDAGArgOpenerToBreak) && + &Left != Right.MatchingParen->Next) { + // Check to avoid empty DAGArg such as (ins). + return Style.TableGenBreakInsideDAGArg == FormatStyle::DAS_BreakAll; + } } if (Line.startsWith(tok::kw_asm) && Right.is(TT_InlineASMColon) && @@ -5873,6 +5970,8 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, // Avoid to break around paste operator. if (Left.is(tok::hash) || Right.is(tok::hash)) return false; + if (Left.isOneOf(TT_TableGenBangOperator, TT_TableGenCondOperator)) + return false; } if (Left.is(tok::at)) diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index a631e5f52bc60a3bc1ab167fa15a15e0e83e7af0..25a24dccb1b834bf7d4f587412aa3327c7a3688e 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -16,7 +16,6 @@ #define LLVM_CLANG_LIB_FORMAT_TOKENANNOTATOR_H #include "UnwrappedLineParser.h" -#include "clang/Format/Format.h" namespace clang { namespace format { diff --git a/clang/lib/Format/UnwrappedLineFormatter.h b/clang/lib/Format/UnwrappedLineFormatter.h index ee6d31de8c42232e065518a08d9ed9d39169234e..9b8acf427a2a000cb835a2d058dd4ba943b71808 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.h +++ b/clang/lib/Format/UnwrappedLineFormatter.h @@ -16,8 +16,6 @@ #define LLVM_CLANG_LIB_FORMAT_UNWRAPPEDLINEFORMATTER_H #include "ContinuationIndenter.h" -#include "clang/Format/Format.h" -#include <map> namespace clang { namespace format { diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index e3f0af176b567d1bfc15153714e765423ede3005..98ae1c8f62bbc259248a3ae2df9bee71707482fb 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -1222,7 +1222,6 @@ void UnwrappedLineParser::parsePPUnknown() { static bool tokenCanStartNewLine(const FormatToken &Tok) { // Semicolon can be a null-statement, l_square can be a start of a macro or // a C++11 attribute, but this doesn't seem to be common. - assert(Tok.isNot(TT_AttributeSquare)); return !Tok.isOneOf(tok::semi, tok::l_brace, // Tokens that can only be used as binary operators and a // part of overloaded operator names. @@ -3710,14 +3709,19 @@ bool UnwrappedLineParser::parseEnum() { if (Style.Language == FormatStyle::LK_Proto && FormatTok->is(tok::equal)) return false; - // Eat up enum class ... - if (FormatTok->isOneOf(tok::kw_class, tok::kw_struct)) - nextToken(); + if (IsCpp) { + // Eat up enum class ... + if (FormatTok->isOneOf(tok::kw_class, tok::kw_struct)) + nextToken(); + while (FormatTok->is(tok::l_square)) + if (!handleCppAttributes()) + return false; + } while (FormatTok->Tok.getIdentifierInfo() || FormatTok->isOneOf(tok::colon, tok::coloncolon, tok::less, tok::greater, tok::comma, tok::question, - tok::l_square, tok::r_square)) { + tok::l_square)) { if (Style.isVerilog()) { FormatTok->setFinalizedType(TT_VerilogDimensionedTypeName); nextToken(); @@ -3730,7 +3734,6 @@ bool UnwrappedLineParser::parseEnum() { // We can have macros or attributes in between 'enum' and the enum name. if (FormatTok->is(tok::l_paren)) parseParens(); - assert(FormatTok->isNot(TT_AttributeSquare)); if (FormatTok->is(tok::identifier)) { nextToken(); // If there are two identifiers in a row, this is likely an elaborate diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h index 619fbb217882b3399a92c829199f7ab00ba57519..e2cf28c0c065dc6a2e26e2ee626b38abd34748a9 100644 --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -15,17 +15,8 @@ #ifndef LLVM_CLANG_LIB_FORMAT_UNWRAPPEDLINEPARSER_H #define LLVM_CLANG_LIB_FORMAT_UNWRAPPEDLINEPARSER_H -#include "Encoding.h" -#include "FormatToken.h" #include "Macros.h" -#include "clang/Basic/IdentifierTable.h" -#include "clang/Format/Format.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/Support/Regex.h" -#include <list> #include <stack> -#include <vector> namespace clang { namespace format { diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index 753be25bfd67585380ad61be9c00fa7167ca9764..d06c42d5f4c5c5bf93db1c6c734da710a2450086 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -112,6 +112,7 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() { alignConsecutiveBitFields(); alignConsecutiveAssignments(); if (Style.isTableGen()) { + alignConsecutiveTableGenBreakingDAGArgColons(); alignConsecutiveTableGenCondOperatorColons(); alignConsecutiveTableGenDefinitions(); } @@ -463,10 +464,11 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End, if (i + 1 != Changes.size()) Changes[i + 1].PreviousEndOfTokenColumn += Shift; - // If PointerAlignment is PAS_Right, keep *s or &s next to the token + // If PointerAlignment is PAS_Right, keep *s or &s next to the token, + // except if the token is equal, then a space is needed. if ((Style.PointerAlignment == FormatStyle::PAS_Right || Style.ReferenceAlignment == FormatStyle::RAS_Right) && - CurrentChange.Spaces != 0) { + CurrentChange.Spaces != 0 && CurrentChange.Tok->isNot(tok::equal)) { const bool ReferenceNotRightAligned = Style.ReferenceAlignment != FormatStyle::RAS_Right && Style.ReferenceAlignment != FormatStyle::RAS_Pointer; @@ -981,6 +983,11 @@ void WhitespaceManager::alignConsecutiveShortCaseStatements() { Changes); } +void WhitespaceManager::alignConsecutiveTableGenBreakingDAGArgColons() { + alignConsecutiveColons(Style.AlignConsecutiveTableGenBreakingDAGArgColons, + TT_TableGenDAGArgListColonToAlign); +} + void WhitespaceManager::alignConsecutiveTableGenCondOperatorColons() { alignConsecutiveColons(Style.AlignConsecutiveTableGenCondOperatorColons, TT_TableGenCondOperatorColon); @@ -1485,7 +1492,7 @@ WhitespaceManager::CellDescriptions WhitespaceManager::getCells(unsigned Start, : Cell); // Go to the next non-comment and ensure there is a break in front const auto *NextNonComment = C.Tok->getNextNonComment(); - while (NextNonComment->is(tok::comma)) + while (NextNonComment && NextNonComment->is(tok::comma)) NextNonComment = NextNonComment->getNextNonComment(); auto j = i; while (j < End && Changes[j].Tok != NextNonComment) diff --git a/clang/lib/Format/WhitespaceManager.h b/clang/lib/Format/WhitespaceManager.h index 9942e0f35738fca054aebbc2106356fbce956dc6..98cf4a260cc46891ed7844fbca370c6d8921787e 100644 --- a/clang/lib/Format/WhitespaceManager.h +++ b/clang/lib/Format/WhitespaceManager.h @@ -17,11 +17,6 @@ #include "TokenAnnotator.h" #include "clang/Basic/SourceManager.h" -#include "clang/Format/Format.h" -#include "llvm/ADT/SmallVector.h" -#include <algorithm> -#include <string> -#include <tuple> namespace clang { namespace format { @@ -240,6 +235,9 @@ private: /// Align consecutive short case statements over all \c Changes. void alignConsecutiveShortCaseStatements(); + /// Align consecutive TableGen DAGArg colon over all \c Changes. + void alignConsecutiveTableGenBreakingDAGArgColons(); + /// Align consecutive TableGen cond operator colon over all \c Changes. void alignConsecutiveTableGenCondOperatorColons(); diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index ec4e68209d657d93398f3d845562c8bb30d3de33..6e3baf8386441593bd767ce2260bd1b107be3e6c 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -1047,6 +1047,11 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { if (getFrontendOpts().ShowStats || !getFrontendOpts().StatsFile.empty()) llvm::EnableStatistics(false); + // Sort vectors containing toc data and no toc data variables to facilitate + // binary search later. + llvm::sort(getCodeGenOpts().TocDataVarsUserSpecified); + llvm::sort(getCodeGenOpts().NoTocDataVars); + for (const FrontendInputFile &FIF : getFrontendOpts().Inputs) { // Reset the ID tables if we are reusing the SourceManager and parsing // regular files. @@ -1201,16 +1206,6 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, // Note the name of the module we're building. Invocation->getLangOpts().CurrentModule = std::string(ModuleName); - // Make sure that the failed-module structure has been allocated in - // the importing instance, and propagate the pointer to the newly-created - // instance. - PreprocessorOptions &ImportingPPOpts - = ImportingInstance.getInvocation().getPreprocessorOpts(); - if (!ImportingPPOpts.FailedModules) - ImportingPPOpts.FailedModules = - std::make_shared<PreprocessorOptions::FailedModulesSet>(); - PPOpts.FailedModules = ImportingPPOpts.FailedModules; - // If there is a module map file, build the module using the module map. // Set up the inputs/outputs so that we build the module from its umbrella // header. @@ -1264,6 +1259,13 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, SourceMgr.pushModuleBuildStack(ModuleName, FullSourceLoc(ImportLoc, ImportingInstance.getSourceManager())); + // Make sure that the failed-module structure has been allocated in + // the importing instance, and propagate the pointer to the newly-created + // instance. + if (!ImportingInstance.hasFailedModulesSet()) + ImportingInstance.createFailedModulesSet(); + Instance.setFailedModulesSet(ImportingInstance.getFailedModulesSetPtr()); + // If we're collecting module dependencies, we need to share a collector // between all of the module CompilerInstances. Other than that, we don't // want to produce any dependency output from the module build. @@ -1332,9 +1334,24 @@ static bool compileModule(CompilerInstance &ImportingInstance, // Get or create the module map that we'll use to build this module. ModuleMap &ModMap = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap(); + SourceManager &SourceMgr = ImportingInstance.getSourceManager(); bool Result; - if (OptionalFileEntryRef ModuleMapFile = - ModMap.getContainingModuleMapFile(Module)) { + if (FileID ModuleMapFID = ModMap.getContainingModuleMapFileID(Module); + ModuleMapFID.isValid()) { + // We want to use the top-level module map. If we don't, the compiling + // instance may think the containing module map is a top-level one, while + // the importing instance knows it's included from a parent module map via + // the extern directive. This mismatch could bite us later. + SourceLocation Loc = SourceMgr.getIncludeLoc(ModuleMapFID); + while (Loc.isValid() && isModuleMap(SourceMgr.getFileCharacteristic(Loc))) { + ModuleMapFID = SourceMgr.getFileID(Loc); + Loc = SourceMgr.getIncludeLoc(ModuleMapFID); + } + + OptionalFileEntryRef ModuleMapFile = + SourceMgr.getFileEntryRefForID(ModuleMapFID); + assert(ModuleMapFile && "Top-level module map with no FileID"); + // Canonicalize compilation to start with the public module map. This is // vital for submodules declarations in the private module maps to be // correctly parsed when depending on a top level module in the public one. @@ -1972,10 +1989,8 @@ ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST( return nullptr; } - // Check whether we have already attempted to build this module (but - // failed). - if (getPreprocessorOpts().FailedModules && - getPreprocessorOpts().FailedModules->hasAlreadyFailed(ModuleName)) { + // Check whether we have already attempted to build this module (but failed). + if (FailedModules && FailedModules->hasAlreadyFailed(ModuleName)) { getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_built) << ModuleName << SourceRange(ImportLoc, ModuleNameLoc); return nullptr; @@ -1986,8 +2001,8 @@ ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST( ModuleFilename)) { assert(getDiagnostics().hasErrorOccurred() && "undiagnosed error in compileModuleAndReadAST"); - if (getPreprocessorOpts().FailedModules) - getPreprocessorOpts().FailedModules->addFailed(ModuleName); + if (FailedModules) + FailedModules->addFailed(ModuleName); return nullptr; } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 451bdb9386f58779ef0c6ab4e6e3b96bece176a7..c5bfb8ef1b5607a752e4d389c566d7995ec240f5 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2757,6 +2757,9 @@ static void GenerateFrontendArgs(const FrontendOptions &Opts, case Language::HLSL: Lang = "hlsl"; break; + case Language::CIR: + Lang = "cir"; + break; } GenerateArg(Consumer, OPT_x, @@ -2958,6 +2961,7 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, .Cases("ast", "pcm", "precompiled-header", InputKind(Language::Unknown, InputKind::Precompiled)) .Case("ir", Language::LLVM_IR) + .Case("cir", Language::CIR) .Default(Language::Unknown); if (DashX.isUnknown()) @@ -3191,6 +3195,22 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, bool IsIndexHeaderMap = false; bool IsSysrootSpecified = Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot); + + // Expand a leading `=` to the sysroot if one was passed (and it's not a + // framework flag). + auto PrefixHeaderPath = [IsSysrootSpecified, + &Opts](const llvm::opt::Arg *A, + bool IsFramework = false) -> std::string { + assert(A->getNumValues() && "Unexpected empty search path flag!"); + if (IsSysrootSpecified && !IsFramework && A->getValue()[0] == '=') { + SmallString<32> Buffer; + llvm::sys::path::append(Buffer, Opts.Sysroot, + llvm::StringRef(A->getValue()).substr(1)); + return std::string(Buffer); + } + return A->getValue(); + }; + for (const auto *A : Args.filtered(OPT_I, OPT_F, OPT_index_header_map)) { if (A->getOption().matches(OPT_index_header_map)) { // -index-header-map applies to the next -I or -F. @@ -3202,16 +3222,7 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, IsIndexHeaderMap ? frontend::IndexHeaderMap : frontend::Angled; bool IsFramework = A->getOption().matches(OPT_F); - std::string Path = A->getValue(); - - if (IsSysrootSpecified && !IsFramework && A->getValue()[0] == '=') { - SmallString<32> Buffer; - llvm::sys::path::append(Buffer, Opts.Sysroot, - llvm::StringRef(A->getValue()).substr(1)); - Path = std::string(Buffer); - } - - Opts.AddPath(Path, Group, IsFramework, + Opts.AddPath(PrefixHeaderPath(A, IsFramework), Group, IsFramework, /*IgnoreSysroot*/ true); IsIndexHeaderMap = false; } @@ -3229,12 +3240,18 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, } for (const auto *A : Args.filtered(OPT_idirafter)) - Opts.AddPath(A->getValue(), frontend::After, false, true); + Opts.AddPath(PrefixHeaderPath(A), frontend::After, false, true); for (const auto *A : Args.filtered(OPT_iquote)) - Opts.AddPath(A->getValue(), frontend::Quoted, false, true); - for (const auto *A : Args.filtered(OPT_isystem, OPT_iwithsysroot)) - Opts.AddPath(A->getValue(), frontend::System, false, - !A->getOption().matches(OPT_iwithsysroot)); + Opts.AddPath(PrefixHeaderPath(A), frontend::Quoted, false, true); + + for (const auto *A : Args.filtered(OPT_isystem, OPT_iwithsysroot)) { + if (A->getOption().matches(OPT_iwithsysroot)) { + Opts.AddPath(A->getValue(), frontend::System, false, + /*IgnoreSysRoot=*/false); + continue; + } + Opts.AddPath(PrefixHeaderPath(A), frontend::System, false, true); + } for (const auto *A : Args.filtered(OPT_iframework)) Opts.AddPath(A->getValue(), frontend::System, true, true); for (const auto *A : Args.filtered(OPT_iframeworkwithsysroot)) @@ -3293,12 +3310,24 @@ static void ParseAPINotesArgs(APINotesOptions &Opts, ArgList &Args, Opts.ModuleSearchPaths.push_back(A->getValue()); } +static void GeneratePointerAuthArgs(const LangOptions &Opts, + ArgumentConsumer Consumer) { + if (Opts.PointerAuthIntrinsics) + GenerateArg(Consumer, OPT_fptrauth_intrinsics); +} + +static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args, + DiagnosticsEngine &Diags) { + Opts.PointerAuthIntrinsics = Args.hasArg(OPT_fptrauth_intrinsics); +} + /// Check if input file kind and language standard are compatible. static bool IsInputCompatibleWithStandard(InputKind IK, const LangStandard &S) { switch (IK.getLanguage()) { case Language::Unknown: case Language::LLVM_IR: + case Language::CIR: llvm_unreachable("should not parse language flags for this input"); case Language::C: @@ -3364,6 +3393,8 @@ static StringRef GetInputKindName(InputKind IK) { return "Asm"; case Language::LLVM_IR: return "LLVM IR"; + case Language::CIR: + return "Clang IR"; case Language::HLSL: return "HLSL"; @@ -3379,7 +3410,8 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts, const llvm::Triple &T, InputKind IK) { if (IK.getFormat() == InputKind::Precompiled || - IK.getLanguage() == Language::LLVM_IR) { + IK.getLanguage() == Language::LLVM_IR || + IK.getLanguage() == Language::CIR) { if (Opts.ObjCAutoRefCount) GenerateArg(Consumer, OPT_fobjc_arc); if (Opts.PICLevel != 0) @@ -3484,7 +3516,8 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts, GenerateArg(Consumer, OPT_fblocks); if (Opts.ConvergentFunctions && - !(Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) || Opts.SYCLIsDevice)) + !(Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) || Opts.SYCLIsDevice || + Opts.HLSL)) GenerateArg(Consumer, OPT_fconvergent_functions); if (Opts.NoBuiltin && !Opts.Freestanding) @@ -3665,7 +3698,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, unsigned NumErrorsBefore = Diags.getNumErrors(); if (IK.getFormat() == InputKind::Precompiled || - IK.getLanguage() == Language::LLVM_IR) { + IK.getLanguage() == Language::LLVM_IR || + IK.getLanguage() == Language::CIR) { // ObjCAAutoRefCount and Sanitize LangOpts are used to setup the // PassManager in BackendUtil.cpp. They need to be initialized no matter // what the input type is. @@ -3881,7 +3915,7 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.ConvergentFunctions = Args.hasArg(OPT_fconvergent_functions) || Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) || - Opts.SYCLIsDevice; + Opts.SYCLIsDevice || Opts.HLSL; Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; if (!Opts.NoBuiltin) @@ -4014,6 +4048,7 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, if (TT.getArch() == llvm::Triple::UnknownArch || !(TT.getArch() == llvm::Triple::aarch64 || TT.isPPC() || + TT.getArch() == llvm::Triple::systemz || TT.getArch() == llvm::Triple::nvptx || TT.getArch() == llvm::Triple::nvptx64 || TT.getArch() == llvm::Triple::amdgcn || @@ -4250,11 +4285,30 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported) << ShaderModel << T.getOSName() << T.str(); } + // Validate that if fnative-half-type is given, that + // the language standard is at least hlsl2018, and that + // the target shader model is at least 6.2. + if (Args.getLastArg(OPT_fnative_half_type)) { + const LangStandard &Std = + LangStandard::getLangStandardForKind(Opts.LangStd); + if (!(Opts.LangStd >= LangStandard::lang_hlsl2018 && + T.getOSVersion() >= VersionTuple(6, 2))) + Diags.Report(diag::err_drv_hlsl_16bit_types_unsupported) + << "-enable-16bit-types" << true << Std.getName() + << T.getOSVersion().getAsString(); + } } else if (T.isSPIRVLogical()) { if (!T.isVulkanOS() || T.getVulkanVersion() == VersionTuple(0)) { Diags.Report(diag::err_drv_hlsl_bad_shader_unsupported) << VulkanEnv << T.getOSName() << T.str(); } + if (Args.getLastArg(OPT_fnative_half_type)) { + const LangStandard &Std = + LangStandard::getLangStandardForKind(Opts.LangStd); + if (!(Opts.LangStd >= LangStandard::lang_hlsl2018)) + Diags.Report(diag::err_drv_hlsl_16bit_types_unsupported) + << "-fnative-half-type" << false << Std.getName(); + } } else { llvm_unreachable("expected DXIL or SPIR-V target"); } @@ -4612,6 +4666,8 @@ bool CompilerInvocation::CreateFromArgsImpl( Res.getFileSystemOpts().WorkingDir); ParseAPINotesArgs(Res.getAPINotesOpts(), Args, Diags); + ParsePointerAuthArgs(LangOpts, Args, Diags); + ParseLangArgs(LangOpts, Args, DashX, T, Res.getPreprocessorOpts().Includes, Diags); if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC) @@ -4842,6 +4898,7 @@ void CompilerInvocationBase::generateCC1CommandLine( GenerateTargetArgs(getTargetOpts(), Consumer); GenerateHeaderSearchArgs(getHeaderSearchOpts(), Consumer); GenerateAPINotesArgs(getAPINotesOpts(), Consumer); + GeneratePointerAuthArgs(getLangOpts(), Consumer); GenerateLangArgs(getLangOpts(), Consumer, T, getFrontendOpts().DashX); GenerateCodeGenArgs(getCodeGenOpts(), Consumer, T, getFrontendOpts().OutputFile, &getLangOpts()); diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index b9fd9b8897b7e7187bedd5789de4fbcd769e0295..b7c9967316f0b82ff2b211315d1be87a05d6340c 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -535,8 +535,14 @@ static Module *prepareToBuildModule(CompilerInstance &CI, if (*OriginalModuleMap != CI.getSourceManager().getFileEntryRefForID( CI.getSourceManager().getMainFileID())) { M->IsInferred = true; - CI.getPreprocessor().getHeaderSearchInfo().getModuleMap() - .setInferredModuleAllowedBy(M, *OriginalModuleMap); + auto FileCharacter = + M->IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap; + FileID OriginalModuleMapFID = CI.getSourceManager().getOrCreateFileID( + *OriginalModuleMap, FileCharacter); + CI.getPreprocessor() + .getHeaderSearchInfo() + .getModuleMap() + .setInferredModuleAllowedBy(M, OriginalModuleMapFID); } } diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 50338bfa670f8302e529c614d85eb2f82446e858..0bc26b694cfc8d477b96f4b33bc087fb717182d1 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -69,7 +69,10 @@ void InitOnlyAction::ExecuteAction() { // Basically PreprocessOnlyAction::ExecuteAction. void ReadPCHAndPreprocessAction::ExecuteAction() { - Preprocessor &PP = getCompilerInstance().getPreprocessor(); + CompilerInstance &CI = getCompilerInstance(); + AdjustCI(CI); + + Preprocessor &PP = CI.getPreprocessor(); // Ignore unknown pragmas. PP.IgnorePragmas(); @@ -293,11 +296,9 @@ GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI, std::unique_ptr<ASTConsumer> GenerateReducedModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - auto Buffer = std::make_shared<PCHBuffer>(); - return std::make_unique<ReducedBMIGenerator>( - CI.getPreprocessor(), CI.getModuleCache(), - CI.getFrontendOpts().OutputFile, Buffer, - /*IncludeTimestamps=*/+CI.getFrontendOpts().IncludeTimestamps); + return std::make_unique<ReducedBMIGenerator>(CI.getPreprocessor(), + CI.getModuleCache(), + CI.getFrontendOpts().OutputFile); } bool GenerateHeaderUnitAction::BeginSourceFileAction(CompilerInstance &CI) { @@ -1085,6 +1086,7 @@ void PrintPreambleAction::ExecuteAction() { case Language::CUDA: case Language::HIP: case Language::HLSL: + case Language::CIR: break; case Language::Unknown: @@ -1189,6 +1191,8 @@ void PrintDependencyDirectivesSourceMinimizerAction::ExecuteAction() { void GetDependenciesByModuleNameAction::ExecuteAction() { CompilerInstance &CI = getCompilerInstance(); + AdjustCI(CI); + Preprocessor &PP = CI.getPreprocessor(); SourceManager &SM = PP.getSourceManager(); FileID MainFileID = SM.getMainFileID(); diff --git a/clang/lib/Frontend/FrontendOptions.cpp b/clang/lib/Frontend/FrontendOptions.cpp index bf83b27c1367efdff086d77a98fe839bf33bd976..32ed99571e85d2cb35c9b6aa4926ac1cd442deb0 100644 --- a/clang/lib/Frontend/FrontendOptions.cpp +++ b/clang/lib/Frontend/FrontendOptions.cpp @@ -34,5 +34,6 @@ InputKind FrontendOptions::getInputKindForExtension(StringRef Extension) { .Case("hip", Language::HIP) .Cases("ll", "bc", Language::LLVM_IR) .Case("hlsl", Language::HLSL) + .Case("cir", Language::CIR) .Default(Language::Unknown); } diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt index b9a966be73ee97b2ef569e99d3634abfc28148bc..97104ccd8db59c5a7db747e1bb1375cc92d177d3 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -214,6 +214,7 @@ set(x86_files popcntintrin.h prfchiintrin.h prfchwintrin.h + ptrauth.h ptwriteintrin.h raointintrin.h rdpruintrin.h @@ -253,8 +254,10 @@ set(x86_files ) set(windows_only_files + intrin0.h intrin.h vadefs.h + yvals_core.h ) set(utility_files diff --git a/clang/lib/Headers/__stddef_null.h b/clang/lib/Headers/__stddef_null.h index 7336fdab389723d0277acc4f11d30253ab96fd8a..c10bd2d7d9887c65c3c67c7b10ba485be9dd605f 100644 --- a/clang/lib/Headers/__stddef_null.h +++ b/clang/lib/Headers/__stddef_null.h @@ -7,7 +7,7 @@ *===-----------------------------------------------------------------------=== */ -#if !defined(NULL) || !__has_feature(modules) +#if !defined(NULL) || !__building_module(_Builtin_stddef) /* linux/stddef.h will define NULL to 0. glibc (and other) headers then define * __need_NULL and rely on stddef.h to redefine NULL to the correct value again. diff --git a/clang/lib/Headers/__stddef_nullptr_t.h b/clang/lib/Headers/__stddef_nullptr_t.h index 183d394d56c1b70fd1c02f964837d415e2ab5918..7f3fbe6fe0d3a8ebc353d89833a43800fd61d478 100644 --- a/clang/lib/Headers/__stddef_nullptr_t.h +++ b/clang/lib/Headers/__stddef_nullptr_t.h @@ -7,7 +7,12 @@ *===-----------------------------------------------------------------------=== */ -#ifndef _NULLPTR_T +/* + * When -fbuiltin-headers-in-system-modules is set this is a non-modular header + * and needs to behave as if it was textual. + */ +#if !defined(_NULLPTR_T) || \ + (__has_feature(modules) && !__building_module(_Builtin_stddef)) #define _NULLPTR_T #ifdef __cplusplus diff --git a/clang/lib/Headers/__stddef_offsetof.h b/clang/lib/Headers/__stddef_offsetof.h index 3b347b3b92f62cec7baa85a7de83e3bf676ac209..84172c6cd27352222e7cb89af8933a2e6000c24e 100644 --- a/clang/lib/Headers/__stddef_offsetof.h +++ b/clang/lib/Headers/__stddef_offsetof.h @@ -7,6 +7,11 @@ *===-----------------------------------------------------------------------=== */ -#ifndef offsetof +/* + * When -fbuiltin-headers-in-system-modules is set this is a non-modular header + * and needs to behave as if it was textual. + */ +#if !defined(offsetof) || \ + (__has_feature(modules) && !__building_module(_Builtin_stddef)) #define offsetof(t, d) __builtin_offsetof(t, d) #endif diff --git a/clang/lib/Headers/__stddef_ptrdiff_t.h b/clang/lib/Headers/__stddef_ptrdiff_t.h index 3ea6d7d2852e1cca7ca1ddbe10daf69f896f292d..fd3c893c66c97940c7197d05286b34aaaac1ecd7 100644 --- a/clang/lib/Headers/__stddef_ptrdiff_t.h +++ b/clang/lib/Headers/__stddef_ptrdiff_t.h @@ -7,7 +7,12 @@ *===-----------------------------------------------------------------------=== */ -#ifndef _PTRDIFF_T +/* + * When -fbuiltin-headers-in-system-modules is set this is a non-modular header + * and needs to behave as if it was textual. + */ +#if !defined(_PTRDIFF_T) || \ + (__has_feature(modules) && !__building_module(_Builtin_stddef)) #define _PTRDIFF_T typedef __PTRDIFF_TYPE__ ptrdiff_t; diff --git a/clang/lib/Headers/__stddef_rsize_t.h b/clang/lib/Headers/__stddef_rsize_t.h index b6428d0c12b62aec8589488155da32ea1b5ac1ca..dd433d40d9733a7257fe7632771276b082dac469 100644 --- a/clang/lib/Headers/__stddef_rsize_t.h +++ b/clang/lib/Headers/__stddef_rsize_t.h @@ -7,7 +7,12 @@ *===-----------------------------------------------------------------------=== */ -#ifndef _RSIZE_T +/* + * When -fbuiltin-headers-in-system-modules is set this is a non-modular header + * and needs to behave as if it was textual. + */ +#if !defined(_RSIZE_T) || \ + (__has_feature(modules) && !__building_module(_Builtin_stddef)) #define _RSIZE_T typedef __SIZE_TYPE__ rsize_t; diff --git a/clang/lib/Headers/__stddef_size_t.h b/clang/lib/Headers/__stddef_size_t.h index e4a389510bcdbf330c6d39376cc593eed83c7941..3dd7b1f37929498cf574b72d62966c448a47c7c4 100644 --- a/clang/lib/Headers/__stddef_size_t.h +++ b/clang/lib/Headers/__stddef_size_t.h @@ -7,7 +7,12 @@ *===-----------------------------------------------------------------------=== */ -#ifndef _SIZE_T +/* + * When -fbuiltin-headers-in-system-modules is set this is a non-modular header + * and needs to behave as if it was textual. + */ +#if !defined(_SIZE_T) || \ + (__has_feature(modules) && !__building_module(_Builtin_stddef)) #define _SIZE_T typedef __SIZE_TYPE__ size_t; diff --git a/clang/lib/Headers/__stddef_unreachable.h b/clang/lib/Headers/__stddef_unreachable.h index 3e7fe01979662afc53985594c74e259810e277a7..518580c92d3f5d01ae73e45be3e6e2b2e0b3075b 100644 --- a/clang/lib/Headers/__stddef_unreachable.h +++ b/clang/lib/Headers/__stddef_unreachable.h @@ -7,6 +7,11 @@ *===-----------------------------------------------------------------------=== */ -#ifndef unreachable +/* + * When -fbuiltin-headers-in-system-modules is set this is a non-modular header + * and needs to behave as if it was textual. + */ +#if !defined(unreachable) || \ + (__has_feature(modules) && !__building_module(_Builtin_stddef)) #define unreachable() __builtin_unreachable() #endif diff --git a/clang/lib/Headers/__stddef_wchar_t.h b/clang/lib/Headers/__stddef_wchar_t.h index 16a6186512c0c35367b3949189ce8080e7b5f714..bd69f6322541637ab3cfbfbb9d09dca5393c5c5c 100644 --- a/clang/lib/Headers/__stddef_wchar_t.h +++ b/clang/lib/Headers/__stddef_wchar_t.h @@ -9,7 +9,12 @@ #if !defined(__cplusplus) || (defined(_MSC_VER) && !_NATIVE_WCHAR_T_DEFINED) -#ifndef _WCHAR_T +/* + * When -fbuiltin-headers-in-system-modules is set this is a non-modular header + * and needs to behave as if it was textual. + */ +#if !defined(_WCHAR_T) || \ + (__has_feature(modules) && !__building_module(_Builtin_stddef)) #define _WCHAR_T #ifdef _MSC_EXTENSIONS diff --git a/clang/lib/Headers/avxintrin.h b/clang/lib/Headers/avxintrin.h index ecd9bf18a41ca0d9ceb5bbf73d402c3cdbeff778..be7a0b247e03d45d7e7429de4dce85546b87206b 100644 --- a/clang/lib/Headers/avxintrin.h +++ b/clang/lib/Headers/avxintrin.h @@ -207,6 +207,8 @@ _mm256_div_ps(__m256 __a, __m256 __b) /// Compares two 256-bit vectors of [4 x double] and returns the greater /// of each pair of values. /// +/// If either value in a comparison is NaN, returns the value from \a __b. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VMAXPD </c> instruction. @@ -226,6 +228,8 @@ _mm256_max_pd(__m256d __a, __m256d __b) /// Compares two 256-bit vectors of [8 x float] and returns the greater /// of each pair of values. /// +/// If either value in a comparison is NaN, returns the value from \a __b. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VMAXPS </c> instruction. @@ -245,6 +249,8 @@ _mm256_max_ps(__m256 __a, __m256 __b) /// Compares two 256-bit vectors of [4 x double] and returns the lesser /// of each pair of values. /// +/// If either value in a comparison is NaN, returns the value from \a __b. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VMINPD </c> instruction. @@ -264,6 +270,8 @@ _mm256_min_pd(__m256d __a, __m256d __b) /// Compares two 256-bit vectors of [8 x float] and returns the lesser /// of each pair of values. /// +/// If either value in a comparison is NaN, returns the value from \a __b. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VMINPS </c> instruction. @@ -1604,9 +1612,9 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) /// 128-bit vectors of [2 x double], using the operation specified by the /// immediate integer operand. /// -/// Returns a [2 x double] vector consisting of two doubles corresponding to -/// the two comparison results: zero if the comparison is false, and all 1's -/// if the comparison is true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, comparisons that are ordered +/// return false, and comparisons that are unordered return true. /// /// \headerfile <x86intrin.h> /// @@ -1663,9 +1671,9 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) /// [4 x float], using the operation specified by the immediate integer /// operand. /// -/// Returns a [4 x float] vector consisting of four floats corresponding to -/// the four comparison results: zero if the comparison is false, and all 1's -/// if the comparison is true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. +/// If either value in a comparison is NaN, comparisons that are ordered +/// return false, and comparisons that are unordered return true. /// /// \headerfile <x86intrin.h> /// @@ -1721,9 +1729,9 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) /// 256-bit vectors of [4 x double], using the operation specified by the /// immediate integer operand. /// -/// Returns a [4 x double] vector consisting of four doubles corresponding to -/// the four comparison results: zero if the comparison is false, and all 1's -/// if the comparison is true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, comparisons that are ordered +/// return false, and comparisons that are unordered return true. /// /// \headerfile <x86intrin.h> /// @@ -1781,9 +1789,9 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) /// [8 x float], using the operation specified by the immediate integer /// operand. /// -/// Returns a [8 x float] vector consisting of eight floats corresponding to -/// the eight comparison results: zero if the comparison is false, and all -/// 1's if the comparison is true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. +/// If either value in a comparison is NaN, comparisons that are ordered +/// return false, and comparisons that are unordered return true. /// /// \headerfile <x86intrin.h> /// @@ -1842,8 +1850,9 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) /// two 128-bit vectors of [2 x double], using the operation specified by the /// immediate integer operand. /// -/// If the result is true, all 64 bits of the destination vector are set; -/// otherwise they are cleared. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, comparisons that are ordered +/// return false, and comparisons that are unordered return true. /// /// \headerfile <x86intrin.h> /// @@ -1900,8 +1909,9 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c) /// vectors of [4 x float], using the operation specified by the immediate /// integer operand. /// -/// If the result is true, all 32 bits of the destination vector are set; -/// otherwise they are cleared. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. +/// If either value in a comparison is NaN, comparisons that are ordered +/// return false, and comparisons that are unordered return true. /// /// \headerfile <x86intrin.h> /// @@ -2201,6 +2211,10 @@ _mm256_cvtpd_ps(__m256d __a) /// Converts a vector of [8 x float] into a vector of [8 x i32]. /// +/// If a converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VCVTPS2DQ </c> instruction. @@ -2230,9 +2244,13 @@ _mm256_cvtps_pd(__m128 __a) return (__m256d)__builtin_convertvector((__v4sf)__a, __v4df); } -/// Converts a 256-bit vector of [4 x double] into a 128-bit vector of [4 -/// x i32], truncating the result by rounding towards zero when it is -/// inexact. +/// Converts a 256-bit vector of [4 x double] into four signed truncated +/// (rounded toward zero) 32-bit integers returned in a 128-bit vector of +/// [4 x i32]. +/// +/// If a converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. /// /// \headerfile <x86intrin.h> /// @@ -2247,9 +2265,12 @@ _mm256_cvttpd_epi32(__m256d __a) return (__m128i)__builtin_ia32_cvttpd2dq256((__v4df) __a); } -/// Converts a 256-bit vector of [4 x double] into a 128-bit vector of [4 -/// x i32]. When a conversion is inexact, the value returned is rounded -/// according to the rounding control bits in the MXCSR register. +/// Converts a 256-bit vector of [4 x double] into a 128-bit vector of +/// [4 x i32]. +/// +/// If a converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. /// /// \headerfile <x86intrin.h> /// @@ -2264,8 +2285,12 @@ _mm256_cvtpd_epi32(__m256d __a) return (__m128i)__builtin_ia32_cvtpd2dq256((__v4df) __a); } -/// Converts a vector of [8 x float] into a vector of [8 x i32], -/// truncating the result by rounding towards zero when it is inexact. +/// Converts a vector of [8 x float] into eight signed truncated (rounded +/// toward zero) 32-bit integers returned in a vector of [8 x i32]. +/// +/// If a converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. /// /// \headerfile <x86intrin.h> /// diff --git a/clang/lib/Headers/bmiintrin.h b/clang/lib/Headers/bmiintrin.h index d8e57c0cb494043046fd84775ee7df5ac3c99356..78bffe68e221a93efc0d5b4c3704087a0c9f6bc9 100644 --- a/clang/lib/Headers/bmiintrin.h +++ b/clang/lib/Headers/bmiintrin.h @@ -161,8 +161,7 @@ _mm_tzcnt_64(unsigned long long __X) #undef __RELAXED_FN_ATTRS -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__BMI__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__BMI__) /* Define the default attributes for the functions in this file. */ #define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("bmi"))) @@ -610,7 +609,6 @@ __blsr_u64(unsigned long long __X) #undef __DEFAULT_FN_ATTRS -#endif /* !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) \ - || defined(__BMI__) */ +#endif /* !defined(__SCE__) || __has_feature(modules) || defined(__BMI__) */ #endif /* __BMIINTRIN_H */ diff --git a/clang/lib/Headers/emmintrin.h b/clang/lib/Headers/emmintrin.h index 984f0cf917e99bf576b4ab82c80a07106be86c65..e85bfc47aa5ccebc80d8f54952677e06bc846b34 100644 --- a/clang/lib/Headers/emmintrin.h +++ b/clang/lib/Headers/emmintrin.h @@ -259,6 +259,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_sqrt_pd(__m128d __a) { /// result. The upper 64 bits of the result are copied from the upper /// double-precision value of the first operand. /// +/// If either value in a comparison is NaN, returns the value from \a __b. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VMINSD / MINSD </c> instruction. @@ -278,9 +280,11 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_min_sd(__m128d __a, } /// Performs element-by-element comparison of the two 128-bit vectors of -/// [2 x double] and returns the vector containing the lesser of each pair of +/// [2 x double] and returns a vector containing the lesser of each pair of /// values. /// +/// If either value in a comparison is NaN, returns the value from \a __b. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VMINPD / MINPD </c> instruction. @@ -301,6 +305,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_min_pd(__m128d __a, /// result. The upper 64 bits of the result are copied from the upper /// double-precision value of the first operand. /// +/// If either value in a comparison is NaN, returns the value from \a __b. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VMAXSD / MAXSD </c> instruction. @@ -320,9 +326,11 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_max_sd(__m128d __a, } /// Performs element-by-element comparison of the two 128-bit vectors of -/// [2 x double] and returns the vector containing the greater of each pair +/// [2 x double] and returns a vector containing the greater of each pair /// of values. /// +/// If either value in a comparison is NaN, returns the value from \a __b. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VMAXPD / MAXPD </c> instruction. @@ -412,7 +420,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_xor_pd(__m128d __a, /// Compares each of the corresponding double-precision values of the /// 128-bit vectors of [2 x double] for equality. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -432,7 +441,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpeq_pd(__m128d __a, /// 128-bit vectors of [2 x double] to determine if the values in the first /// operand are less than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -452,7 +462,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmplt_pd(__m128d __a, /// 128-bit vectors of [2 x double] to determine if the values in the first /// operand are less than or equal to those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -472,7 +483,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmple_pd(__m128d __a, /// 128-bit vectors of [2 x double] to determine if the values in the first /// operand are greater than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -492,7 +504,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpgt_pd(__m128d __a, /// 128-bit vectors of [2 x double] to determine if the values in the first /// operand are greater than or equal to those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -512,8 +525,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpge_pd(__m128d __a, /// 128-bit vectors of [2 x double] to determine if the values in the first /// operand are ordered with respect to those in the second operand. /// -/// A pair of double-precision values are "ordered" with respect to each -/// other if neither value is a NaN. Each comparison yields 0x0 for false, +/// A pair of double-precision values are ordered with respect to each +/// other if neither value is a NaN. Each comparison returns 0x0 for false, /// 0xFFFFFFFFFFFFFFFF for true. /// /// \headerfile <x86intrin.h> @@ -534,8 +547,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpord_pd(__m128d __a, /// 128-bit vectors of [2 x double] to determine if the values in the first /// operand are unordered with respect to those in the second operand. /// -/// A pair of double-precision values are "unordered" with respect to each -/// other if one or both values are NaN. Each comparison yields 0x0 for +/// A pair of double-precision values are unordered with respect to each +/// other if one or both values are NaN. Each comparison returns 0x0 for /// false, 0xFFFFFFFFFFFFFFFF for true. /// /// \headerfile <x86intrin.h> @@ -557,7 +570,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpunord_pd(__m128d __a, /// 128-bit vectors of [2 x double] to determine if the values in the first /// operand are unequal to those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -577,7 +591,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpneq_pd(__m128d __a, /// 128-bit vectors of [2 x double] to determine if the values in the first /// operand are not less than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -597,7 +612,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpnlt_pd(__m128d __a, /// 128-bit vectors of [2 x double] to determine if the values in the first /// operand are not less than or equal to those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -617,7 +633,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpnle_pd(__m128d __a, /// 128-bit vectors of [2 x double] to determine if the values in the first /// operand are not greater than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -637,7 +654,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpngt_pd(__m128d __a, /// 128-bit vectors of [2 x double] to determine if the values in the first /// operand are not greater than or equal to those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -656,7 +674,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpnge_pd(__m128d __a, /// Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] for equality. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// The comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -680,7 +699,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpeq_sd(__m128d __a, /// the value in the first parameter is less than the corresponding value in /// the second parameter. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// The comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -704,7 +724,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmplt_sd(__m128d __a, /// the value in the first parameter is less than or equal to the /// corresponding value in the second parameter. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// The comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -728,7 +749,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmple_sd(__m128d __a, /// the value in the first parameter is greater than the corresponding value /// in the second parameter. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// The comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -753,7 +775,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpgt_sd(__m128d __a, /// the value in the first parameter is greater than or equal to the /// corresponding value in the second parameter. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// The comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -775,11 +798,11 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpge_sd(__m128d __a, /// Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if -/// the value in the first parameter is "ordered" with respect to the +/// the value in the first parameter is ordered with respect to the /// corresponding value in the second parameter. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. A pair -/// of double-precision values are "ordered" with respect to each other if +/// The comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. A pair +/// of double-precision values are ordered with respect to each other if /// neither value is a NaN. /// /// \headerfile <x86intrin.h> @@ -801,11 +824,11 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpord_sd(__m128d __a, /// Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] to determine if -/// the value in the first parameter is "unordered" with respect to the +/// the value in the first parameter is unordered with respect to the /// corresponding value in the second parameter. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. A pair -/// of double-precision values are "unordered" with respect to each other if +/// The comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. A pair +/// of double-precision values are unordered with respect to each other if /// one or both values are NaN. /// /// \headerfile <x86intrin.h> @@ -831,7 +854,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpunord_sd(__m128d __a, /// the value in the first parameter is unequal to the corresponding value in /// the second parameter. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// The comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -855,7 +879,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpneq_sd(__m128d __a, /// the value in the first parameter is not less than the corresponding /// value in the second parameter. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// The comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -879,7 +904,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpnlt_sd(__m128d __a, /// the value in the first parameter is not less than or equal to the /// corresponding value in the second parameter. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// The comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -903,7 +929,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpnle_sd(__m128d __a, /// the value in the first parameter is not greater than the corresponding /// value in the second parameter. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// The comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -928,7 +955,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpngt_sd(__m128d __a, /// the value in the first parameter is not greater than or equal to the /// corresponding value in the second parameter. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// The comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -951,8 +979,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpnge_sd(__m128d __a, /// Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] for equality. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower double-precision values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -975,8 +1003,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comieq_sd(__m128d __a, /// the value in the first parameter is less than the corresponding value in /// the second parameter. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower double-precision values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -999,8 +1027,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comilt_sd(__m128d __a, /// the value in the first parameter is less than or equal to the /// corresponding value in the second parameter. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower double-precision values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1023,8 +1051,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comile_sd(__m128d __a, /// the value in the first parameter is greater than the corresponding value /// in the second parameter. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower double-precision values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1047,8 +1075,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comigt_sd(__m128d __a, /// the value in the first parameter is greater than or equal to the /// corresponding value in the second parameter. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower double-precision values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1071,8 +1099,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comige_sd(__m128d __a, /// the value in the first parameter is unequal to the corresponding value in /// the second parameter. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower double-precision values is NaN, 1 is returned. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 1. /// /// \headerfile <x86intrin.h> /// @@ -1093,8 +1121,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comineq_sd(__m128d __a, /// Compares the lower double-precision floating-point values in each of /// the two 128-bit floating-point vectors of [2 x double] for equality. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower double-precision values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1117,8 +1145,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomieq_sd(__m128d __a, /// the value in the first parameter is less than the corresponding value in /// the second parameter. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower double-precision values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1141,8 +1169,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomilt_sd(__m128d __a, /// the value in the first parameter is less than or equal to the /// corresponding value in the second parameter. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower double-precision values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1165,8 +1193,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomile_sd(__m128d __a, /// the value in the first parameter is greater than the corresponding value /// in the second parameter. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower double-precision values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1189,8 +1217,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomigt_sd(__m128d __a, /// the value in the first parameter is greater than or equal to the /// corresponding value in the second parameter. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower double-precision values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1213,8 +1241,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomige_sd(__m128d __a, /// the value in the first parameter is unequal to the corresponding value in /// the second parameter. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower double-precision values is NaN, 1 is returned. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 1. /// /// \headerfile <x86intrin.h> /// @@ -1294,6 +1322,10 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cvtepi32_pd(__m128i __a) { /// returned in the lower 64 bits of a 128-bit vector of [4 x i32]. The upper /// 64 bits of the result vector are set to zero. /// +/// If a converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VCVTPD2DQ / CVTPD2DQ </c> instruction. @@ -1309,6 +1341,10 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cvtpd_epi32(__m128d __a) { /// Converts the low-order element of a 128-bit vector of [2 x double] /// into a 32-bit signed integer value. /// +/// If the converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VCVTSD2SI / CVTSD2SI </c> instruction. @@ -1394,12 +1430,13 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cvtss_sd(__m128d __a, } /// Converts the two double-precision floating-point elements of a -/// 128-bit vector of [2 x double] into two signed 32-bit integer values, -/// returned in the lower 64 bits of a 128-bit vector of [4 x i32]. +/// 128-bit vector of [2 x double] into two signed truncated (rounded +/// toward zero) 32-bit integer values, returned in the lower 64 bits +/// of a 128-bit vector of [4 x i32]. /// -/// If the result of either conversion is inexact, the result is truncated -/// (rounded towards zero) regardless of the current MXCSR setting. The upper -/// 64 bits of the result vector are set to zero. +/// If a converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. /// /// \headerfile <x86intrin.h> /// @@ -1415,7 +1452,11 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cvttpd_epi32(__m128d __a) { } /// Converts the low-order element of a [2 x double] vector into a 32-bit -/// signed integer value, truncating the result when it is inexact. +/// signed truncated (rounded toward zero) integer value. +/// +/// If the converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. /// /// \headerfile <x86intrin.h> /// @@ -1434,6 +1475,10 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_cvttsd_si32(__m128d __a) { /// 128-bit vector of [2 x double] into two signed 32-bit integer values, /// returned in a 64-bit vector of [2 x i32]. /// +/// If a converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> CVTPD2PI </c> instruction. @@ -1446,11 +1491,12 @@ static __inline__ __m64 __DEFAULT_FN_ATTRS_MMX _mm_cvtpd_pi32(__m128d __a) { } /// Converts the two double-precision floating-point elements of a -/// 128-bit vector of [2 x double] into two signed 32-bit integer values, -/// returned in a 64-bit vector of [2 x i32]. +/// 128-bit vector of [2 x double] into two signed truncated (rounded toward +/// zero) 32-bit integer values, returned in a 64-bit vector of [2 x i32]. /// -/// If the result of either conversion is inexact, the result is truncated -/// (rounded towards zero) regardless of the current MXCSR setting. +/// If a converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. /// /// \headerfile <x86intrin.h> /// @@ -3015,7 +3061,7 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_srl_epi64(__m128i __a, /// Compares each of the corresponding 8-bit values of the 128-bit /// integer vectors for equality. /// -/// Each comparison yields 0x0 for false, 0xFF for true. +/// Each comparison returns 0x0 for false, 0xFF for true. /// /// \headerfile <x86intrin.h> /// @@ -3034,7 +3080,7 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cmpeq_epi8(__m128i __a, /// Compares each of the corresponding 16-bit values of the 128-bit /// integer vectors for equality. /// -/// Each comparison yields 0x0 for false, 0xFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFF for true. /// /// \headerfile <x86intrin.h> /// @@ -3053,7 +3099,7 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cmpeq_epi16(__m128i __a, /// Compares each of the corresponding 32-bit values of the 128-bit /// integer vectors for equality. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. /// /// \headerfile <x86intrin.h> /// @@ -3073,7 +3119,7 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cmpeq_epi32(__m128i __a, /// integer vectors to determine if the values in the first operand are /// greater than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFF for true. +/// Each comparison returns 0x0 for false, 0xFF for true. /// /// \headerfile <x86intrin.h> /// @@ -3095,7 +3141,7 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cmpgt_epi8(__m128i __a, /// 128-bit integer vectors to determine if the values in the first operand /// are greater than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFF for true. /// /// \headerfile <x86intrin.h> /// @@ -3115,7 +3161,7 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cmpgt_epi16(__m128i __a, /// 128-bit integer vectors to determine if the values in the first operand /// are greater than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. /// /// \headerfile <x86intrin.h> /// @@ -3135,7 +3181,7 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cmpgt_epi32(__m128i __a, /// integer vectors to determine if the values in the first operand are less /// than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFF for true. +/// Each comparison returns 0x0 for false, 0xFF for true. /// /// \headerfile <x86intrin.h> /// @@ -3155,7 +3201,7 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cmplt_epi8(__m128i __a, /// 128-bit integer vectors to determine if the values in the first operand /// are less than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFF for true. /// /// \headerfile <x86intrin.h> /// @@ -3175,7 +3221,7 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cmplt_epi16(__m128i __a, /// 128-bit integer vectors to determine if the values in the first operand /// are less than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. /// /// \headerfile <x86intrin.h> /// @@ -3216,7 +3262,11 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cvtsi64_sd(__m128d __a, } /// Converts the first (lower) element of a vector of [2 x double] into a -/// 64-bit signed integer value, according to the current rounding mode. +/// 64-bit signed integer value. +/// +/// If the converted value does not fit in a 64-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. /// /// \headerfile <x86intrin.h> /// @@ -3231,7 +3281,11 @@ static __inline__ long long __DEFAULT_FN_ATTRS _mm_cvtsd_si64(__m128d __a) { } /// Converts the first (lower) element of a vector of [2 x double] into a -/// 64-bit signed integer value, truncating the result when it is inexact. +/// 64-bit signed truncated (rounded toward zero) integer value. +/// +/// If a converted value does not fit in a 64-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. /// /// \headerfile <x86intrin.h> /// @@ -3262,6 +3316,10 @@ static __inline__ __m128 __DEFAULT_FN_ATTRS _mm_cvtepi32_ps(__m128i __a) { /// Converts a vector of [4 x float] into a vector of [4 x i32]. /// +/// If a converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VCVTPS2DQ / CVTPS2DQ </c> instruction. @@ -3274,8 +3332,12 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cvtps_epi32(__m128 __a) { return (__m128i)__builtin_ia32_cvtps2dq((__v4sf)__a); } -/// Converts a vector of [4 x float] into a vector of [4 x i32], -/// truncating the result when it is inexact. +/// Converts a vector of [4 x float] into four signed truncated (rounded toward +/// zero) 32-bit integers, returned in a vector of [4 x i32]. +/// +/// If a converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. /// /// \headerfile <x86intrin.h> /// @@ -4743,7 +4805,9 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_castsi128_pd(__m128i __a) { /// 128-bit vectors of [2 x double], using the operation specified by the /// immediate integer operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, comparisons that are ordered +/// return false, and comparisons that are unordered return true. /// /// \headerfile <x86intrin.h> /// @@ -4777,7 +4841,9 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_castsi128_pd(__m128i __a) { /// two 128-bit vectors of [2 x double], using the operation specified by the /// immediate integer operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, comparisons that are ordered +/// return false, and comparisons that are unordered return true. /// /// \headerfile <x86intrin.h> /// diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 45f8544392584e49d3c5708b2be329f6d2e7b7e8..9fb6204f90c9a8c7d9980fe506d8b6e0e11f265b 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -243,14 +243,115 @@ float3 ceil(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_ceil) float4 ceil(float4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_ceil) -double ceil(double); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_ceil) -double2 ceil(double2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_ceil) -double3 ceil(double3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_ceil) -double4 ceil(double4); +//===----------------------------------------------------------------------===// +// clamp builtins +//===----------------------------------------------------------------------===// + +/// \fn T clamp(T X, T Min, T Max) +/// \brief Clamps the specified value \a X to the specified +/// minimum ( \a Min) and maximum ( \a Max) range. +/// \param X A value to clamp. +/// \param Min The specified minimum range. +/// \param Max The specified maximum range. +/// +/// Returns The clamped value for the \a X parameter. +/// For values of -INF or INF, clamp will behave as expected. +/// However for values of NaN, the results are undefined. + +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +half clamp(half, half, half); +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +half2 clamp(half2, half2, half2); +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +half3 clamp(half3, half3, half3); +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +half4 clamp(half4, half4, half4); + +#ifdef __HLSL_ENABLE_16_BIT +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int16_t clamp(int16_t, int16_t, int16_t); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int16_t2 clamp(int16_t2, int16_t2, int16_t2); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int16_t3 clamp(int16_t3, int16_t3, int16_t3); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int16_t4 clamp(int16_t4, int16_t4, int16_t4); + +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint16_t clamp(uint16_t, uint16_t, uint16_t); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint16_t2 clamp(uint16_t2, uint16_t2, uint16_t2); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint16_t3 clamp(uint16_t3, uint16_t3, uint16_t3); +_HLSL_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint16_t4 clamp(uint16_t4, uint16_t4, uint16_t4); +#endif + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int clamp(int, int, int); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int2 clamp(int2, int2, int2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int3 clamp(int3, int3, int3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int4 clamp(int4, int4, int4); + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint clamp(uint, uint, uint); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint2 clamp(uint2, uint2, uint2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint3 clamp(uint3, uint3, uint3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint4 clamp(uint4, uint4, uint4); + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int64_t clamp(int64_t, int64_t, int64_t); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int64_t2 clamp(int64_t2, int64_t2, int64_t2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int64_t3 clamp(int64_t3, int64_t3, int64_t3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +int64_t4 clamp(int64_t4, int64_t4, int64_t4); + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint64_t clamp(uint64_t, uint64_t, uint64_t); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint64_t2 clamp(uint64_t2, uint64_t2, uint64_t2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint64_t3 clamp(uint64_t3, uint64_t3, uint64_t3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +uint64_t4 clamp(uint64_t4, uint64_t4, uint64_t4); + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +float clamp(float, float, float); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +float2 clamp(float2, float2, float2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +float3 clamp(float3, float3, float3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +float4 clamp(float4, float4, float4); + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +double clamp(double, double, double); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +double2 clamp(double2, double2, double2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +double3 clamp(double3, double3, double3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_clamp) +double4 clamp(double4, double4, double4); //===----------------------------------------------------------------------===// // cos builtins @@ -282,15 +383,6 @@ float3 cos(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_cos) float4 cos(float4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_cos) -double cos(double); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_cos) -double2 cos(double2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_cos) -double3 cos(double3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_cos) -double4 cos(double4); - //===----------------------------------------------------------------------===// // dot product builtins //===----------------------------------------------------------------------===// @@ -484,15 +576,6 @@ float3 floor(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_floor) float4 floor(float4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_floor) -double floor(double); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_floor) -double2 floor(double2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_floor) -double3 floor(double3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_floor) -double4 floor(double4); - //===----------------------------------------------------------------------===// // frac builtins //===----------------------------------------------------------------------===// @@ -525,6 +608,39 @@ float3 frac(float3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac) float4 frac(float4); +//===----------------------------------------------------------------------===// +// isinf builtins +//===----------------------------------------------------------------------===// + +/// \fn T isinf(T x) +/// \brief Determines if the specified value \a x is infinite. +/// \param x The specified input value. +/// +/// Returns a value of the same size as the input, with a value set +/// to True if the x parameter is +INF or -INF. Otherwise, False. + +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf) +bool isinf(half); +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf) +bool2 isinf(half2); +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf) +bool3 isinf(half3); +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf) +bool4 isinf(half4); + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf) +bool isinf(float); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf) +bool2 isinf(float2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf) +bool3 isinf(float3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_isinf) +bool4 isinf(float4); + //===----------------------------------------------------------------------===// // lerp builtins //===----------------------------------------------------------------------===// @@ -594,15 +710,6 @@ float3 log(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_log) float4 log(float4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log) -double log(double); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log) -double2 log(double2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log) -double3 log(double3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log) -double4 log(double4); - //===----------------------------------------------------------------------===// // log10 builtins //===----------------------------------------------------------------------===// @@ -636,15 +743,6 @@ float3 log10(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_log10) float4 log10(float4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log10) -double log10(double); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log10) -double2 log10(double2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log10) -double3 log10(double3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log10) -double4 log10(double4); - //===----------------------------------------------------------------------===// // log2 builtins //===----------------------------------------------------------------------===// @@ -678,15 +776,6 @@ float3 log2(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_log2) float4 log2(float4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log2) -double log2(double); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log2) -double2 log2(double2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log2) -double3 log2(double3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_log2) -double4 log2(double4); - //===----------------------------------------------------------------------===// // mad builtins //===----------------------------------------------------------------------===// @@ -1031,15 +1120,6 @@ float3 pow(float3, float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_pow) float4 pow(float4, float4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_pow) -double pow(double, double); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_pow) -double2 pow(double2, double2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_pow) -double3 pow(double3, double3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_pow) -double4 pow(double4, double4); - //===----------------------------------------------------------------------===// // reversebits builtins //===----------------------------------------------------------------------===// @@ -1049,19 +1129,6 @@ double4 pow(double4, double4); /// \param Val The input value. #ifdef __HLSL_ENABLE_16_BIT -_HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int16_t reversebits(int16_t); -_HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int16_t2 reversebits(int16_t2); -_HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int16_t3 reversebits(int16_t3); -_HLSL_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int16_t4 reversebits(int16_t4); - _HLSL_AVAILABILITY(shadermodel, 6.2) _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) uint16_t reversebits(uint16_t); @@ -1076,15 +1143,6 @@ _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) uint16_t4 reversebits(uint16_t4); #endif -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int reversebits(int); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int2 reversebits(int2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int3 reversebits(int3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int4 reversebits(int4); - _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) uint reversebits(uint); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) @@ -1094,15 +1152,6 @@ uint3 reversebits(uint3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) uint4 reversebits(uint4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int64_t reversebits(int64_t); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int64_t2 reversebits(int64_t2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int64_t3 reversebits(int64_t3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) -int64_t4 reversebits(int64_t4); - _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) uint64_t reversebits(uint64_t); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse) @@ -1153,6 +1202,39 @@ double3 rcp(double3); _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rcp) double4 rcp(double4); +//===----------------------------------------------------------------------===// +// rsqrt builtins +//===----------------------------------------------------------------------===// + +/// \fn T rsqrt(T x) +/// \brief Returns the reciprocal of the square root of the specified value. +/// ie 1 / sqrt( \a x). +/// \param x The specified input value. +/// +/// This function uses the following formula: 1 / sqrt(x). + +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rsqrt) +half rsqrt(half); +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rsqrt) +half2 rsqrt(half2); +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rsqrt) +half3 rsqrt(half3); +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rsqrt) +half4 rsqrt(half4); + +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rsqrt) +float rsqrt(float); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rsqrt) +float2 rsqrt(float2); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rsqrt) +float3 rsqrt(float3); +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rsqrt) +float4 rsqrt(float4); + //===----------------------------------------------------------------------===// // round builtins //===----------------------------------------------------------------------===// @@ -1166,25 +1248,25 @@ double4 rcp(double4); /// rounded to the nearest even value. _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_roundeven) half round(half); _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_roundeven) half2 round(half2); _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_roundeven) half3 round(half3); _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_roundeven) half4 round(half4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_roundeven) float round(float); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_roundeven) float2 round(float2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_roundeven) float3 round(float3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_roundeven) float4 round(float4); //===----------------------------------------------------------------------===// @@ -1217,15 +1299,6 @@ float3 sin(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_sin) float4 sin(float4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sin) -double sin(double); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sin) -double2 sin(double2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sin) -double3 sin(double3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sin) -double4 sin(double4); - //===----------------------------------------------------------------------===// // sqrt builtins //===----------------------------------------------------------------------===// @@ -1235,14 +1308,26 @@ double4 sin(double4); /// \param Val The input value. _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_sqrtf16) -half sqrt(half In); - -_HLSL_BUILTIN_ALIAS(__builtin_sqrtf) -float sqrt(float In); +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sqrt) +half sqrt(half); +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sqrt) +half2 sqrt(half2); +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sqrt) +half3 sqrt(half3); +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sqrt) +half4 sqrt(half4); -_HLSL_BUILTIN_ALIAS(__builtin_sqrt) -double sqrt(double In); +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sqrt) +float sqrt(float); +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sqrt) +float2 sqrt(float2); +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sqrt) +float3 sqrt(float3); +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_sqrt) +float4 sqrt(float4); //===----------------------------------------------------------------------===// // trunc builtins @@ -1274,15 +1359,6 @@ float3 trunc(float3); _HLSL_BUILTIN_ALIAS(__builtin_elementwise_trunc) float4 trunc(float4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_trunc) -double trunc(double); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_trunc) -double2 trunc(double2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_trunc) -double3 trunc(double3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_trunc) -double4 trunc(double4); - //===----------------------------------------------------------------------===// // Wave* builtins //===----------------------------------------------------------------------===// @@ -1295,7 +1371,12 @@ double4 trunc(double4); /// true, across all active lanes in the current wave. _HLSL_AVAILABILITY(shadermodel, 6.0) _HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_active_count_bits) -uint WaveActiveCountBits(bool Val); +__attribute__((convergent)) uint WaveActiveCountBits(bool Val); + +/// \brief Returns the index of the current lane within the current wave. +_HLSL_AVAILABILITY(shadermodel, 6.0) +_HLSL_BUILTIN_ALIAS(__builtin_hlsl_wave_get_lane_index) +__attribute__((convergent)) uint WaveGetLaneIndex(); } // namespace hlsl #endif //_HLSL_HLSL_INTRINSICS_H_ diff --git a/clang/lib/Headers/immintrin.h b/clang/lib/Headers/immintrin.h index 27800f7a8202c16372ff26831229f74c78987554..508696d3725b9a4351d00ad35a76577e93bc4e2b 100644 --- a/clang/lib/Headers/immintrin.h +++ b/clang/lib/Headers/immintrin.h @@ -16,281 +16,239 @@ #include <x86gprintrin.h> -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__MMX__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__MMX__) #include <mmintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__SSE__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__SSE__) #include <xmmintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__SSE2__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__SSE2__) #include <emmintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__SSE3__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__SSE3__) #include <pmmintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__SSSE3__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__SSSE3__) #include <tmmintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ +#if !defined(__SCE__) || __has_feature(modules) || \ (defined(__SSE4_2__) || defined(__SSE4_1__)) #include <smmintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ +#if !defined(__SCE__) || __has_feature(modules) || \ (defined(__AES__) || defined(__PCLMUL__)) #include <wmmintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__CLFLUSHOPT__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__CLFLUSHOPT__) #include <clflushoptintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__CLWB__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__CLWB__) #include <clwbintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVX__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVX__) #include <avxintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVX2__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVX2__) #include <avx2intrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__F16C__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__F16C__) #include <f16cintrin.h> #endif /* No feature check desired due to internal checks */ #include <bmiintrin.h> -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__BMI2__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__BMI2__) #include <bmi2intrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__LZCNT__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__LZCNT__) #include <lzcntintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__POPCNT__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__POPCNT__) #include <popcntintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__FMA__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__FMA__) #include <fmaintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVX512F__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVX512F__) #include <avx512fintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVX512VL__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVX512VL__) #include <avx512vlintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVX512BW__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVX512BW__) #include <avx512bwintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVX512BITALG__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVX512BITALG__) #include <avx512bitalgintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVX512CD__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVX512CD__) #include <avx512cdintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVX512VPOPCNTDQ__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVX512VPOPCNTDQ__) #include <avx512vpopcntdqintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ +#if !defined(__SCE__) || __has_feature(modules) || \ (defined(__AVX512VL__) && defined(__AVX512VPOPCNTDQ__)) #include <avx512vpopcntdqvlintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVX512VNNI__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVX512VNNI__) #include <avx512vnniintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ +#if !defined(__SCE__) || __has_feature(modules) || \ (defined(__AVX512VL__) && defined(__AVX512VNNI__)) #include <avx512vlvnniintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVXVNNI__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVXVNNI__) #include <avxvnniintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVX512DQ__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVX512DQ__) #include <avx512dqintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ +#if !defined(__SCE__) || __has_feature(modules) || \ (defined(__AVX512VL__) && defined(__AVX512BITALG__)) #include <avx512vlbitalgintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ +#if !defined(__SCE__) || __has_feature(modules) || \ (defined(__AVX512VL__) && defined(__AVX512BW__)) #include <avx512vlbwintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ +#if !defined(__SCE__) || __has_feature(modules) || \ (defined(__AVX512VL__) && defined(__AVX512CD__)) #include <avx512vlcdintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ +#if !defined(__SCE__) || __has_feature(modules) || \ (defined(__AVX512VL__) && defined(__AVX512DQ__)) #include <avx512vldqintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVX512ER__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVX512ER__) #include <avx512erintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVX512IFMA__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVX512IFMA__) #include <avx512ifmaintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ +#if !defined(__SCE__) || __has_feature(modules) || \ (defined(__AVX512IFMA__) && defined(__AVX512VL__)) #include <avx512ifmavlintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVXIFMA__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVXIFMA__) #include <avxifmaintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVX512VBMI__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVX512VBMI__) #include <avx512vbmiintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ +#if !defined(__SCE__) || __has_feature(modules) || \ (defined(__AVX512VBMI__) && defined(__AVX512VL__)) #include <avx512vbmivlintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVX512VBMI2__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVX512VBMI2__) #include <avx512vbmi2intrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ +#if !defined(__SCE__) || __has_feature(modules) || \ (defined(__AVX512VBMI2__) && defined(__AVX512VL__)) #include <avx512vlvbmi2intrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVX512PF__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVX512PF__) #include <avx512pfintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVX512FP16__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVX512FP16__) #include <avx512fp16intrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ +#if !defined(__SCE__) || __has_feature(modules) || \ (defined(__AVX512VL__) && defined(__AVX512FP16__)) #include <avx512vlfp16intrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVX512BF16__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVX512BF16__) #include <avx512bf16intrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ +#if !defined(__SCE__) || __has_feature(modules) || \ (defined(__AVX512VL__) && defined(__AVX512BF16__)) #include <avx512vlbf16intrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__PKU__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__PKU__) #include <pkuintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__VPCLMULQDQ__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__VPCLMULQDQ__) #include <vpclmulqdqintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__VAES__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__VAES__) #include <vaesintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__GFNI__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__GFNI__) #include <gfniintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVXVNNIINT8__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVXVNNIINT8__) #include <avxvnniint8intrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVXNECONVERT__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVXNECONVERT__) #include <avxneconvertintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__SHA512__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__SHA512__) #include <sha512intrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__SM3__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__SM3__) #include <sm3intrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__SM4__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__SM4__) #include <sm4intrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AVXVNNIINT16__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AVXVNNIINT16__) #include <avxvnniint16intrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__RDPID__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__RDPID__) /// Reads the value of the IA32_TSC_AUX MSR (0xc0000103). /// /// \headerfile <immintrin.h> @@ -304,8 +262,7 @@ _rdpid_u32(void) { } #endif // __RDPID__ -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__RDRND__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__RDRND__) /// Returns a 16-bit hardware-generated random value. /// /// \headerfile <immintrin.h> @@ -367,8 +324,7 @@ _rdrand64_step(unsigned long long *__p) } #endif /* __RDRND__ */ -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__FSGSBASE__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__FSGSBASE__) #ifdef __x86_64__ /// Reads the FS base register. /// @@ -481,8 +437,7 @@ _writegsbase_u64(unsigned long long __V) #endif #endif /* __FSGSBASE__ */ -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__MOVBE__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__MOVBE__) /* The structs used below are to force the load/store to be unaligned. This * is accomplished with the __packed__ attribute. The __may_alias__ prevents @@ -598,139 +553,118 @@ _storebe_i64(void * __P, long long __D) { #endif #endif /* __MOVBE */ -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__RTM__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__RTM__) #include <rtmintrin.h> #include <xtestintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__SHA__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__SHA__) #include <shaintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__FXSR__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__FXSR__) #include <fxsrintrin.h> #endif /* No feature check desired due to internal MSC_VER checks */ #include <xsaveintrin.h> -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__XSAVEOPT__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__XSAVEOPT__) #include <xsaveoptintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__XSAVEC__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__XSAVEC__) #include <xsavecintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__XSAVES__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__XSAVES__) #include <xsavesintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__SHSTK__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__SHSTK__) #include <cetintrin.h> #endif /* Intrinsics inside adcintrin.h are available at all times. */ #include <adcintrin.h> -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__ADX__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__ADX__) #include <adxintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__RDSEED__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__RDSEED__) #include <rdseedintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__WBNOINVD__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__WBNOINVD__) #include <wbnoinvdintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__CLDEMOTE__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__CLDEMOTE__) #include <cldemoteintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__WAITPKG__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__WAITPKG__) #include <waitpkgintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__MOVDIRI__) || defined(__MOVDIR64B__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__MOVDIRI__) || \ + defined(__MOVDIR64B__) #include <movdirintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__PCONFIG__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__PCONFIG__) #include <pconfigintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__SGX__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__SGX__) #include <sgxintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__PTWRITE__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__PTWRITE__) #include <ptwriteintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__INVPCID__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__INVPCID__) #include <invpcidintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AMX_FP16__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AMX_FP16__) #include <amxfp16intrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__KL__) || defined(__WIDEKL__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__KL__) || \ + defined(__WIDEKL__) #include <keylockerintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AMX_TILE__) || defined(__AMX_INT8__) || defined(__AMX_BF16__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AMX_TILE__) || \ + defined(__AMX_INT8__) || defined(__AMX_BF16__) #include <amxintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__AMX_COMPLEX__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__AMX_COMPLEX__) #include <amxcomplexintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ +#if !defined(__SCE__) || __has_feature(modules) || \ defined(__AVX512VP2INTERSECT__) #include <avx512vp2intersectintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ +#if !defined(__SCE__) || __has_feature(modules) || \ (defined(__AVX512VL__) && defined(__AVX512VP2INTERSECT__)) #include <avx512vlvp2intersectintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__ENQCMD__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__ENQCMD__) #include <enqcmdintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__SERIALIZE__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__SERIALIZE__) #include <serializeintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__TSXLDTRK__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__TSXLDTRK__) #include <tsxldtrkintrin.h> #endif diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h index a6395143db54c23bcacd3327ad02dee262296aea..fd27955fbe002d8069a55d04de8f933edd7b2d75 100644 --- a/clang/lib/Headers/intrin.h +++ b/clang/lib/Headers/intrin.h @@ -15,6 +15,8 @@ #ifndef __INTRIN_H #define __INTRIN_H +#include <intrin0.h> + /* First include the standard intrinsics. */ #if defined(__i386__) || defined(__x86_64__) #include <x86intrin.h> @@ -131,8 +133,6 @@ void __writefsqword(unsigned long, unsigned __int64); void __writefsword(unsigned long, unsigned short); void __writemsr(unsigned long, unsigned __int64); void *_AddressOfReturnAddress(void); -unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask); -unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask); unsigned char _bittest(long const *, long); unsigned char _bittestandcomplement(long *, long); unsigned char _bittestandreset(long *, long); @@ -151,7 +151,6 @@ long _InterlockedExchangeAdd_HLERelease(long volatile *, long); __int64 _InterlockedExchangeAdd64_HLEAcquire(__int64 volatile *, __int64); __int64 _InterlockedExchangeAdd64_HLERelease(__int64 volatile *, __int64); void _ReadBarrier(void); -void _ReadWriteBarrier(void); unsigned int _rorx_u32(unsigned int, const unsigned int); int _sarx_i32(int, unsigned int); #if __STDC_HOSTED__ @@ -182,12 +181,6 @@ unsigned char __readgsbyte(unsigned long); unsigned long __readgsdword(unsigned long); unsigned __int64 __readgsqword(unsigned long); unsigned short __readgsword(unsigned long); -unsigned __int64 __shiftleft128(unsigned __int64 _LowPart, - unsigned __int64 _HighPart, - unsigned char _Shift); -unsigned __int64 __shiftright128(unsigned __int64 _LowPart, - unsigned __int64 _HighPart, - unsigned char _Shift); void __stosq(unsigned __int64 *, unsigned __int64, size_t); unsigned char __vmx_on(unsigned __int64 *); unsigned char __vmx_vmclear(unsigned __int64 *); @@ -236,212 +229,10 @@ unsigned __int64 _shlx_u64(unsigned __int64, unsigned int); unsigned __int64 _shrx_u64(unsigned __int64, unsigned int); __int64 __mulh(__int64, __int64); unsigned __int64 __umulh(unsigned __int64, unsigned __int64); -__int64 _mul128(__int64, __int64, __int64*); -unsigned __int64 _umul128(unsigned __int64, - unsigned __int64, - unsigned __int64*); +__int64 _mul128(__int64, __int64, __int64 *); #endif /* __x86_64__ */ -#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) - -unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask); -unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask); - -#endif - -#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) -__int64 _InterlockedDecrement64(__int64 volatile *_Addend); -__int64 _InterlockedExchange64(__int64 volatile *_Target, __int64 _Value); -__int64 _InterlockedExchangeAdd64(__int64 volatile *_Addend, __int64 _Value); -__int64 _InterlockedExchangeSub64(__int64 volatile *_Subend, __int64 _Value); -__int64 _InterlockedIncrement64(__int64 volatile *_Addend); -__int64 _InterlockedOr64(__int64 volatile *_Value, __int64 _Mask); -__int64 _InterlockedXor64(__int64 volatile *_Value, __int64 _Mask); -__int64 _InterlockedAnd64(__int64 volatile *_Value, __int64 _Mask); - -#endif - -/*----------------------------------------------------------------------------*\ -|* Interlocked Exchange Add -\*----------------------------------------------------------------------------*/ -#if defined(__arm__) || defined(__aarch64__) -char _InterlockedExchangeAdd8_acq(char volatile *_Addend, char _Value); -char _InterlockedExchangeAdd8_nf(char volatile *_Addend, char _Value); -char _InterlockedExchangeAdd8_rel(char volatile *_Addend, char _Value); -short _InterlockedExchangeAdd16_acq(short volatile *_Addend, short _Value); -short _InterlockedExchangeAdd16_nf(short volatile *_Addend, short _Value); -short _InterlockedExchangeAdd16_rel(short volatile *_Addend, short _Value); -long _InterlockedExchangeAdd_acq(long volatile *_Addend, long _Value); -long _InterlockedExchangeAdd_nf(long volatile *_Addend, long _Value); -long _InterlockedExchangeAdd_rel(long volatile *_Addend, long _Value); -__int64 _InterlockedExchangeAdd64_acq(__int64 volatile *_Addend, __int64 _Value); -__int64 _InterlockedExchangeAdd64_nf(__int64 volatile *_Addend, __int64 _Value); -__int64 _InterlockedExchangeAdd64_rel(__int64 volatile *_Addend, __int64 _Value); -#endif -/*----------------------------------------------------------------------------*\ -|* Interlocked Increment -\*----------------------------------------------------------------------------*/ -#if defined(__arm__) || defined(__aarch64__) -short _InterlockedIncrement16_acq(short volatile *_Value); -short _InterlockedIncrement16_nf(short volatile *_Value); -short _InterlockedIncrement16_rel(short volatile *_Value); -long _InterlockedIncrement_acq(long volatile *_Value); -long _InterlockedIncrement_nf(long volatile *_Value); -long _InterlockedIncrement_rel(long volatile *_Value); -__int64 _InterlockedIncrement64_acq(__int64 volatile *_Value); -__int64 _InterlockedIncrement64_nf(__int64 volatile *_Value); -__int64 _InterlockedIncrement64_rel(__int64 volatile *_Value); -#endif -/*----------------------------------------------------------------------------*\ -|* Interlocked Decrement -\*----------------------------------------------------------------------------*/ -#if defined(__arm__) || defined(__aarch64__) -short _InterlockedDecrement16_acq(short volatile *_Value); -short _InterlockedDecrement16_nf(short volatile *_Value); -short _InterlockedDecrement16_rel(short volatile *_Value); -long _InterlockedDecrement_acq(long volatile *_Value); -long _InterlockedDecrement_nf(long volatile *_Value); -long _InterlockedDecrement_rel(long volatile *_Value); -__int64 _InterlockedDecrement64_acq(__int64 volatile *_Value); -__int64 _InterlockedDecrement64_nf(__int64 volatile *_Value); -__int64 _InterlockedDecrement64_rel(__int64 volatile *_Value); -#endif -/*----------------------------------------------------------------------------*\ -|* Interlocked And -\*----------------------------------------------------------------------------*/ -#if defined(__arm__) || defined(__aarch64__) -char _InterlockedAnd8_acq(char volatile *_Value, char _Mask); -char _InterlockedAnd8_nf(char volatile *_Value, char _Mask); -char _InterlockedAnd8_rel(char volatile *_Value, char _Mask); -short _InterlockedAnd16_acq(short volatile *_Value, short _Mask); -short _InterlockedAnd16_nf(short volatile *_Value, short _Mask); -short _InterlockedAnd16_rel(short volatile *_Value, short _Mask); -long _InterlockedAnd_acq(long volatile *_Value, long _Mask); -long _InterlockedAnd_nf(long volatile *_Value, long _Mask); -long _InterlockedAnd_rel(long volatile *_Value, long _Mask); -__int64 _InterlockedAnd64_acq(__int64 volatile *_Value, __int64 _Mask); -__int64 _InterlockedAnd64_nf(__int64 volatile *_Value, __int64 _Mask); -__int64 _InterlockedAnd64_rel(__int64 volatile *_Value, __int64 _Mask); -#endif -/*----------------------------------------------------------------------------*\ -|* Bit Counting and Testing -\*----------------------------------------------------------------------------*/ -#if defined(__arm__) || defined(__aarch64__) -unsigned char _interlockedbittestandset_acq(long volatile *_BitBase, - long _BitPos); -unsigned char _interlockedbittestandset_nf(long volatile *_BitBase, - long _BitPos); -unsigned char _interlockedbittestandset_rel(long volatile *_BitBase, - long _BitPos); -unsigned char _interlockedbittestandreset_acq(long volatile *_BitBase, - long _BitPos); -unsigned char _interlockedbittestandreset_nf(long volatile *_BitBase, - long _BitPos); -unsigned char _interlockedbittestandreset_rel(long volatile *_BitBase, - long _BitPos); -#endif -/*----------------------------------------------------------------------------*\ -|* Interlocked Or -\*----------------------------------------------------------------------------*/ -#if defined(__arm__) || defined(__aarch64__) -char _InterlockedOr8_acq(char volatile *_Value, char _Mask); -char _InterlockedOr8_nf(char volatile *_Value, char _Mask); -char _InterlockedOr8_rel(char volatile *_Value, char _Mask); -short _InterlockedOr16_acq(short volatile *_Value, short _Mask); -short _InterlockedOr16_nf(short volatile *_Value, short _Mask); -short _InterlockedOr16_rel(short volatile *_Value, short _Mask); -long _InterlockedOr_acq(long volatile *_Value, long _Mask); -long _InterlockedOr_nf(long volatile *_Value, long _Mask); -long _InterlockedOr_rel(long volatile *_Value, long _Mask); -__int64 _InterlockedOr64_acq(__int64 volatile *_Value, __int64 _Mask); -__int64 _InterlockedOr64_nf(__int64 volatile *_Value, __int64 _Mask); -__int64 _InterlockedOr64_rel(__int64 volatile *_Value, __int64 _Mask); -#endif -/*----------------------------------------------------------------------------*\ -|* Interlocked Xor -\*----------------------------------------------------------------------------*/ -#if defined(__arm__) || defined(__aarch64__) -char _InterlockedXor8_acq(char volatile *_Value, char _Mask); -char _InterlockedXor8_nf(char volatile *_Value, char _Mask); -char _InterlockedXor8_rel(char volatile *_Value, char _Mask); -short _InterlockedXor16_acq(short volatile *_Value, short _Mask); -short _InterlockedXor16_nf(short volatile *_Value, short _Mask); -short _InterlockedXor16_rel(short volatile *_Value, short _Mask); -long _InterlockedXor_acq(long volatile *_Value, long _Mask); -long _InterlockedXor_nf(long volatile *_Value, long _Mask); -long _InterlockedXor_rel(long volatile *_Value, long _Mask); -__int64 _InterlockedXor64_acq(__int64 volatile *_Value, __int64 _Mask); -__int64 _InterlockedXor64_nf(__int64 volatile *_Value, __int64 _Mask); -__int64 _InterlockedXor64_rel(__int64 volatile *_Value, __int64 _Mask); -#endif -/*----------------------------------------------------------------------------*\ -|* Interlocked Exchange -\*----------------------------------------------------------------------------*/ -#if defined(__arm__) || defined(__aarch64__) -char _InterlockedExchange8_acq(char volatile *_Target, char _Value); -char _InterlockedExchange8_nf(char volatile *_Target, char _Value); -char _InterlockedExchange8_rel(char volatile *_Target, char _Value); -short _InterlockedExchange16_acq(short volatile *_Target, short _Value); -short _InterlockedExchange16_nf(short volatile *_Target, short _Value); -short _InterlockedExchange16_rel(short volatile *_Target, short _Value); -long _InterlockedExchange_acq(long volatile *_Target, long _Value); -long _InterlockedExchange_nf(long volatile *_Target, long _Value); -long _InterlockedExchange_rel(long volatile *_Target, long _Value); -__int64 _InterlockedExchange64_acq(__int64 volatile *_Target, __int64 _Value); -__int64 _InterlockedExchange64_nf(__int64 volatile *_Target, __int64 _Value); -__int64 _InterlockedExchange64_rel(__int64 volatile *_Target, __int64 _Value); -#endif -/*----------------------------------------------------------------------------*\ -|* Interlocked Compare Exchange -\*----------------------------------------------------------------------------*/ -#if defined(__arm__) || defined(__aarch64__) -char _InterlockedCompareExchange8_acq(char volatile *_Destination, - char _Exchange, char _Comparand); -char _InterlockedCompareExchange8_nf(char volatile *_Destination, - char _Exchange, char _Comparand); -char _InterlockedCompareExchange8_rel(char volatile *_Destination, - char _Exchange, char _Comparand); -short _InterlockedCompareExchange16_acq(short volatile *_Destination, - short _Exchange, short _Comparand); -short _InterlockedCompareExchange16_nf(short volatile *_Destination, - short _Exchange, short _Comparand); -short _InterlockedCompareExchange16_rel(short volatile *_Destination, - short _Exchange, short _Comparand); -long _InterlockedCompareExchange_acq(long volatile *_Destination, - long _Exchange, long _Comparand); -long _InterlockedCompareExchange_nf(long volatile *_Destination, - long _Exchange, long _Comparand); -long _InterlockedCompareExchange_rel(long volatile *_Destination, - long _Exchange, long _Comparand); -__int64 _InterlockedCompareExchange64_acq(__int64 volatile *_Destination, - __int64 _Exchange, __int64 _Comparand); -__int64 _InterlockedCompareExchange64_nf(__int64 volatile *_Destination, - __int64 _Exchange, __int64 _Comparand); -__int64 _InterlockedCompareExchange64_rel(__int64 volatile *_Destination, - __int64 _Exchange, __int64 _Comparand); -#endif -#if defined(__x86_64__) || defined(__aarch64__) -unsigned char _InterlockedCompareExchange128(__int64 volatile *_Destination, - __int64 _ExchangeHigh, - __int64 _ExchangeLow, - __int64 *_ComparandResult); -#endif -#if defined(__aarch64__) -unsigned char _InterlockedCompareExchange128_acq(__int64 volatile *_Destination, - __int64 _ExchangeHigh, - __int64 _ExchangeLow, - __int64 *_ComparandResult); -unsigned char _InterlockedCompareExchange128_nf(__int64 volatile *_Destination, - __int64 _ExchangeHigh, - __int64 _ExchangeLow, - __int64 *_ComparandResult); -unsigned char _InterlockedCompareExchange128_rel(__int64 volatile *_Destination, - __int64 _ExchangeHigh, - __int64 _ExchangeLow, - __int64 *_ComparandResult); -#endif - /*----------------------------------------------------------------------------*\ |* movs, stos \*----------------------------------------------------------------------------*/ @@ -583,8 +374,6 @@ unsigned int _CountLeadingOnes(unsigned long); unsigned int _CountLeadingOnes64(unsigned __int64); unsigned int _CountLeadingSigns(long); unsigned int _CountLeadingSigns64(__int64); -unsigned int _CountLeadingZeros(unsigned long); -unsigned int _CountLeadingZeros64(unsigned _int64); unsigned int _CountOneBits(unsigned long); unsigned int _CountOneBits64(unsigned __int64); diff --git a/clang/lib/Headers/intrin0.h b/clang/lib/Headers/intrin0.h new file mode 100644 index 0000000000000000000000000000000000000000..31f362ec84d5c571113c34f1ac2932d1af0ba699 --- /dev/null +++ b/clang/lib/Headers/intrin0.h @@ -0,0 +1,247 @@ +/* ===-------- intrin.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 + * + *===-----------------------------------------------------------------------=== + */ + +/* Only include this if we're compiling for the windows platform. */ +#ifndef _MSC_VER +#include_next <intrin0.h> +#else + +#ifndef __INTRIN0_H +#define __INTRIN0_H + +#ifdef __x86_64__ +#include <adcintrin.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask); +unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask); +void _ReadWriteBarrier(void); + +#if defined(__aarch64__) +unsigned int _CountLeadingZeros(unsigned long); +unsigned int _CountLeadingZeros64(unsigned _int64); +unsigned char _InterlockedCompareExchange128_acq(__int64 volatile *_Destination, + __int64 _ExchangeHigh, + __int64 _ExchangeLow, + __int64 *_ComparandResult); +unsigned char _InterlockedCompareExchange128_nf(__int64 volatile *_Destination, + __int64 _ExchangeHigh, + __int64 _ExchangeLow, + __int64 *_ComparandResult); +unsigned char _InterlockedCompareExchange128_rel(__int64 volatile *_Destination, + __int64 _ExchangeHigh, + __int64 _ExchangeLow, + __int64 *_ComparandResult); +#endif + +#ifdef __x86_64__ +unsigned __int64 _umul128(unsigned __int64, unsigned __int64, + unsigned __int64 *); +unsigned __int64 __shiftleft128(unsigned __int64 _LowPart, + unsigned __int64 _HighPart, + unsigned char _Shift); +unsigned __int64 __shiftright128(unsigned __int64 _LowPart, + unsigned __int64 _HighPart, + unsigned char _Shift); +#endif + +#if defined(__x86_64__) || defined(__i386__) +void _mm_pause(void); +#endif + +#if defined(__x86_64__) || defined(__aarch64__) +unsigned char _InterlockedCompareExchange128(__int64 volatile *_Destination, + __int64 _ExchangeHigh, + __int64 _ExchangeLow, + __int64 *_ComparandResult); +#endif + +#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) +unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask); +unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask); +#endif + +#if defined(__i386__) || defined(__x86_64__) || defined(__arm__) || \ + defined(__aarch64__) +__int64 _InterlockedDecrement64(__int64 volatile *_Addend); +__int64 _InterlockedExchange64(__int64 volatile *_Target, __int64 _Value); +__int64 _InterlockedExchangeAdd64(__int64 volatile *_Addend, __int64 _Value); +__int64 _InterlockedExchangeSub64(__int64 volatile *_Subend, __int64 _Value); +__int64 _InterlockedIncrement64(__int64 volatile *_Addend); +__int64 _InterlockedOr64(__int64 volatile *_Value, __int64 _Mask); +__int64 _InterlockedXor64(__int64 volatile *_Value, __int64 _Mask); +__int64 _InterlockedAnd64(__int64 volatile *_Value, __int64 _Mask); +#endif + +#if defined(__arm__) || defined(__aarch64__) +/*----------------------------------------------------------------------------*\ +|* Interlocked Exchange Add +\*----------------------------------------------------------------------------*/ +char _InterlockedExchangeAdd8_acq(char volatile *_Addend, char _Value); +char _InterlockedExchangeAdd8_nf(char volatile *_Addend, char _Value); +char _InterlockedExchangeAdd8_rel(char volatile *_Addend, char _Value); +short _InterlockedExchangeAdd16_acq(short volatile *_Addend, short _Value); +short _InterlockedExchangeAdd16_nf(short volatile *_Addend, short _Value); +short _InterlockedExchangeAdd16_rel(short volatile *_Addend, short _Value); +long _InterlockedExchangeAdd_acq(long volatile *_Addend, long _Value); +long _InterlockedExchangeAdd_nf(long volatile *_Addend, long _Value); +long _InterlockedExchangeAdd_rel(long volatile *_Addend, long _Value); +__int64 _InterlockedExchangeAdd64_acq(__int64 volatile *_Addend, + __int64 _Value); +__int64 _InterlockedExchangeAdd64_nf(__int64 volatile *_Addend, __int64 _Value); +__int64 _InterlockedExchangeAdd64_rel(__int64 volatile *_Addend, + __int64 _Value); + +/*----------------------------------------------------------------------------*\ +|* Interlocked Increment +\*----------------------------------------------------------------------------*/ +short _InterlockedIncrement16_acq(short volatile *_Value); +short _InterlockedIncrement16_nf(short volatile *_Value); +short _InterlockedIncrement16_rel(short volatile *_Value); +long _InterlockedIncrement_acq(long volatile *_Value); +long _InterlockedIncrement_nf(long volatile *_Value); +long _InterlockedIncrement_rel(long volatile *_Value); +__int64 _InterlockedIncrement64_acq(__int64 volatile *_Value); +__int64 _InterlockedIncrement64_nf(__int64 volatile *_Value); +__int64 _InterlockedIncrement64_rel(__int64 volatile *_Value); + +/*----------------------------------------------------------------------------*\ +|* Interlocked Decrement +\*----------------------------------------------------------------------------*/ +short _InterlockedDecrement16_acq(short volatile *_Value); +short _InterlockedDecrement16_nf(short volatile *_Value); +short _InterlockedDecrement16_rel(short volatile *_Value); +long _InterlockedDecrement_acq(long volatile *_Value); +long _InterlockedDecrement_nf(long volatile *_Value); +long _InterlockedDecrement_rel(long volatile *_Value); +__int64 _InterlockedDecrement64_acq(__int64 volatile *_Value); +__int64 _InterlockedDecrement64_nf(__int64 volatile *_Value); +__int64 _InterlockedDecrement64_rel(__int64 volatile *_Value); + +/*----------------------------------------------------------------------------*\ +|* Interlocked And +\*----------------------------------------------------------------------------*/ +char _InterlockedAnd8_acq(char volatile *_Value, char _Mask); +char _InterlockedAnd8_nf(char volatile *_Value, char _Mask); +char _InterlockedAnd8_rel(char volatile *_Value, char _Mask); +short _InterlockedAnd16_acq(short volatile *_Value, short _Mask); +short _InterlockedAnd16_nf(short volatile *_Value, short _Mask); +short _InterlockedAnd16_rel(short volatile *_Value, short _Mask); +long _InterlockedAnd_acq(long volatile *_Value, long _Mask); +long _InterlockedAnd_nf(long volatile *_Value, long _Mask); +long _InterlockedAnd_rel(long volatile *_Value, long _Mask); +__int64 _InterlockedAnd64_acq(__int64 volatile *_Value, __int64 _Mask); +__int64 _InterlockedAnd64_nf(__int64 volatile *_Value, __int64 _Mask); +__int64 _InterlockedAnd64_rel(__int64 volatile *_Value, __int64 _Mask); + +/*----------------------------------------------------------------------------*\ +|* Bit Counting and Testing +\*----------------------------------------------------------------------------*/ +unsigned char _interlockedbittestandset_acq(long volatile *_BitBase, + long _BitPos); +unsigned char _interlockedbittestandset_nf(long volatile *_BitBase, + long _BitPos); +unsigned char _interlockedbittestandset_rel(long volatile *_BitBase, + long _BitPos); +unsigned char _interlockedbittestandreset_acq(long volatile *_BitBase, + long _BitPos); +unsigned char _interlockedbittestandreset_nf(long volatile *_BitBase, + long _BitPos); +unsigned char _interlockedbittestandreset_rel(long volatile *_BitBase, + long _BitPos); + +/*----------------------------------------------------------------------------*\ +|* Interlocked Or +\*----------------------------------------------------------------------------*/ +char _InterlockedOr8_acq(char volatile *_Value, char _Mask); +char _InterlockedOr8_nf(char volatile *_Value, char _Mask); +char _InterlockedOr8_rel(char volatile *_Value, char _Mask); +short _InterlockedOr16_acq(short volatile *_Value, short _Mask); +short _InterlockedOr16_nf(short volatile *_Value, short _Mask); +short _InterlockedOr16_rel(short volatile *_Value, short _Mask); +long _InterlockedOr_acq(long volatile *_Value, long _Mask); +long _InterlockedOr_nf(long volatile *_Value, long _Mask); +long _InterlockedOr_rel(long volatile *_Value, long _Mask); +__int64 _InterlockedOr64_acq(__int64 volatile *_Value, __int64 _Mask); +__int64 _InterlockedOr64_nf(__int64 volatile *_Value, __int64 _Mask); +__int64 _InterlockedOr64_rel(__int64 volatile *_Value, __int64 _Mask); + +/*----------------------------------------------------------------------------*\ +|* Interlocked Xor +\*----------------------------------------------------------------------------*/ +char _InterlockedXor8_acq(char volatile *_Value, char _Mask); +char _InterlockedXor8_nf(char volatile *_Value, char _Mask); +char _InterlockedXor8_rel(char volatile *_Value, char _Mask); +short _InterlockedXor16_acq(short volatile *_Value, short _Mask); +short _InterlockedXor16_nf(short volatile *_Value, short _Mask); +short _InterlockedXor16_rel(short volatile *_Value, short _Mask); +long _InterlockedXor_acq(long volatile *_Value, long _Mask); +long _InterlockedXor_nf(long volatile *_Value, long _Mask); +long _InterlockedXor_rel(long volatile *_Value, long _Mask); +__int64 _InterlockedXor64_acq(__int64 volatile *_Value, __int64 _Mask); +__int64 _InterlockedXor64_nf(__int64 volatile *_Value, __int64 _Mask); +__int64 _InterlockedXor64_rel(__int64 volatile *_Value, __int64 _Mask); + +/*----------------------------------------------------------------------------*\ +|* Interlocked Exchange +\*----------------------------------------------------------------------------*/ +char _InterlockedExchange8_acq(char volatile *_Target, char _Value); +char _InterlockedExchange8_nf(char volatile *_Target, char _Value); +char _InterlockedExchange8_rel(char volatile *_Target, char _Value); +short _InterlockedExchange16_acq(short volatile *_Target, short _Value); +short _InterlockedExchange16_nf(short volatile *_Target, short _Value); +short _InterlockedExchange16_rel(short volatile *_Target, short _Value); +long _InterlockedExchange_acq(long volatile *_Target, long _Value); +long _InterlockedExchange_nf(long volatile *_Target, long _Value); +long _InterlockedExchange_rel(long volatile *_Target, long _Value); +__int64 _InterlockedExchange64_acq(__int64 volatile *_Target, __int64 _Value); +__int64 _InterlockedExchange64_nf(__int64 volatile *_Target, __int64 _Value); +__int64 _InterlockedExchange64_rel(__int64 volatile *_Target, __int64 _Value); + +/*----------------------------------------------------------------------------*\ +|* Interlocked Compare Exchange +\*----------------------------------------------------------------------------*/ +char _InterlockedCompareExchange8_acq(char volatile *_Destination, + char _Exchange, char _Comparand); +char _InterlockedCompareExchange8_nf(char volatile *_Destination, + char _Exchange, char _Comparand); +char _InterlockedCompareExchange8_rel(char volatile *_Destination, + char _Exchange, char _Comparand); +short _InterlockedCompareExchange16_acq(short volatile *_Destination, + short _Exchange, short _Comparand); +short _InterlockedCompareExchange16_nf(short volatile *_Destination, + short _Exchange, short _Comparand); +short _InterlockedCompareExchange16_rel(short volatile *_Destination, + short _Exchange, short _Comparand); +long _InterlockedCompareExchange_acq(long volatile *_Destination, + long _Exchange, long _Comparand); +long _InterlockedCompareExchange_nf(long volatile *_Destination, long _Exchange, + long _Comparand); +long _InterlockedCompareExchange_rel(long volatile *_Destination, + long _Exchange, long _Comparand); +__int64 _InterlockedCompareExchange64_acq(__int64 volatile *_Destination, + __int64 _Exchange, + __int64 _Comparand); +__int64 _InterlockedCompareExchange64_nf(__int64 volatile *_Destination, + __int64 _Exchange, __int64 _Comparand); +__int64 _InterlockedCompareExchange64_rel(__int64 volatile *_Destination, + __int64 _Exchange, + __int64 _Comparand); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __INTRIN0_H */ +#endif /* _MSC_VER */ diff --git a/clang/lib/Headers/keylockerintrin.h b/clang/lib/Headers/keylockerintrin.h index 1994ac42070ad3ff956933e8ffa05dffca5f46bd..f76e91b4d4b306dea4d4155eb1341ad2dd873f5c 100644 --- a/clang/lib/Headers/keylockerintrin.h +++ b/clang/lib/Headers/keylockerintrin.h @@ -28,8 +28,7 @@ #ifndef _KEYLOCKERINTRIN_H #define _KEYLOCKERINTRIN_H -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__KL__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__KL__) /* Define the default attributes for the functions in this file. */ #define __DEFAULT_FN_ATTRS \ @@ -327,11 +326,9 @@ _mm_aesdec256kl_u8(__m128i* __odata, __m128i __idata, const void *__h) { #undef __DEFAULT_FN_ATTRS -#endif /* !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) \ - || defined(__KL__) */ +#endif /* !defined(__SCE__ || __has_feature(modules) || defined(__KL__) */ -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__WIDEKL__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__WIDEKL__) /* Define the default attributes for the functions in this file. */ #define __DEFAULT_FN_ATTRS \ @@ -524,7 +521,7 @@ _mm_aesdecwide256kl_u8(__m128i __odata[8], const __m128i __idata[8], const void* #undef __DEFAULT_FN_ATTRS -#endif /* !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) \ - || defined(__WIDEKL__) */ +#endif /* !defined(__SCE__) || __has_feature(modules) || defined(__WIDEKL__) \ + */ #endif /* _KEYLOCKERINTRIN_H */ diff --git a/clang/lib/Headers/mmintrin.h b/clang/lib/Headers/mmintrin.h index 962d24738e7aa48e338e57141952ebf5d359c492..4e154e2d85935303eddf0dbaf0f62c7401adc09d 100644 --- a/clang/lib/Headers/mmintrin.h +++ b/clang/lib/Headers/mmintrin.h @@ -1141,7 +1141,7 @@ _mm_xor_si64(__m64 __m1, __m64 __m2) /// [8 x i8] to determine if the element of the first vector is equal to the /// corresponding element of the second vector. /// -/// The comparison yields 0 for false, 0xFF for true. +/// Each comparison returns 0 for false, 0xFF for true. /// /// \headerfile <x86intrin.h> /// @@ -1163,7 +1163,7 @@ _mm_cmpeq_pi8(__m64 __m1, __m64 __m2) /// [4 x i16] to determine if the element of the first vector is equal to the /// corresponding element of the second vector. /// -/// The comparison yields 0 for false, 0xFFFF for true. +/// Each comparison returns 0 for false, 0xFFFF for true. /// /// \headerfile <x86intrin.h> /// @@ -1185,7 +1185,7 @@ _mm_cmpeq_pi16(__m64 __m1, __m64 __m2) /// [2 x i32] to determine if the element of the first vector is equal to the /// corresponding element of the second vector. /// -/// The comparison yields 0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0 for false, 0xFFFFFFFF for true. /// /// \headerfile <x86intrin.h> /// @@ -1207,7 +1207,7 @@ _mm_cmpeq_pi32(__m64 __m1, __m64 __m2) /// [8 x i8] to determine if the element of the first vector is greater than /// the corresponding element of the second vector. /// -/// The comparison yields 0 for false, 0xFF for true. +/// Each comparison returns 0 for false, 0xFF for true. /// /// \headerfile <x86intrin.h> /// @@ -1229,7 +1229,7 @@ _mm_cmpgt_pi8(__m64 __m1, __m64 __m2) /// [4 x i16] to determine if the element of the first vector is greater than /// the corresponding element of the second vector. /// -/// The comparison yields 0 for false, 0xFFFF for true. +/// Each comparison returns 0 for false, 0xFFFF for true. /// /// \headerfile <x86intrin.h> /// @@ -1251,7 +1251,7 @@ _mm_cmpgt_pi16(__m64 __m1, __m64 __m2) /// [2 x i32] to determine if the element of the first vector is greater than /// the corresponding element of the second vector. /// -/// The comparison yields 0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0 for false, 0xFFFFFFFF for true. /// /// \headerfile <x86intrin.h> /// diff --git a/clang/lib/Headers/module.modulemap b/clang/lib/Headers/module.modulemap index a786689d391773c2b1bf61f04a947d15309b7bfa..8741968fa7f364b64394e3e985ce0e6d755b6a84 100644 --- a/clang/lib/Headers/module.modulemap +++ b/clang/lib/Headers/module.modulemap @@ -155,9 +155,9 @@ module _Builtin_intrinsics [system] [extern_c] { // Start -fbuiltin-headers-in-system-modules affected modules -// The following modules all ignore their top level headers -// when -fbuiltin-headers-in-system-modules is passed, and -// most of those headers join system modules when present. +// The following modules all ignore their headers when +// -fbuiltin-headers-in-system-modules is passed, and many of +// those headers join system modules when present. // e.g. if -fbuiltin-headers-in-system-modules is passed, then // float.h will not be in the _Builtin_float module (that module @@ -190,11 +190,6 @@ module _Builtin_stdalign [system] { export * } -// When -fbuiltin-headers-in-system-modules is passed, only -// the top level headers are removed, the implementation headers -// will always be in their submodules. That means when stdarg.h -// is included, it will still import this module and make the -// appropriate submodules visible. module _Builtin_stdarg [system] { textual header "stdarg.h" @@ -237,6 +232,8 @@ module _Builtin_stdbool [system] { module _Builtin_stddef [system] { textual header "stddef.h" + // __stddef_max_align_t.h is always in this module, even if + // -fbuiltin-headers-in-system-modules is passed. explicit module max_align_t { header "__stddef_max_align_t.h" export * @@ -283,9 +280,10 @@ module _Builtin_stddef [system] { } } -/* wint_t is provided by <wchar.h> and not <stddef.h>. It's here - * for compatibility, but must be explicitly requested. Therefore - * __stddef_wint_t.h is not part of _Builtin_stddef. */ +// wint_t is provided by <wchar.h> and not <stddef.h>. It's here +// for compatibility, but must be explicitly requested. Therefore +// __stddef_wint_t.h is not part of _Builtin_stddef. It is always in +// this module even if -fbuiltin-headers-in-system-modules is passed. module _Builtin_stddef_wint_t [system] { header "__stddef_wint_t.h" export * @@ -317,3 +315,8 @@ module opencl_c { header "opencl-c.h" header "opencl-c-base.h" } + +module ptrauth { + header "ptrauth.h" + export * +} diff --git a/clang/lib/Headers/ptrauth.h b/clang/lib/Headers/ptrauth.h new file mode 100644 index 0000000000000000000000000000000000000000..56c3c3636c9bcd9f76819ef9fb62777a79889b71 --- /dev/null +++ b/clang/lib/Headers/ptrauth.h @@ -0,0 +1,185 @@ +/*===---- ptrauth.h - Pointer authentication -------------------------------=== + * + * 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 __PTRAUTH_H +#define __PTRAUTH_H + +typedef enum { + ptrauth_key_asia = 0, + ptrauth_key_asib = 1, + ptrauth_key_asda = 2, + ptrauth_key_asdb = 3, +} ptrauth_key; + +/* An integer type of the appropriate size for a discriminator argument. */ +typedef __UINTPTR_TYPE__ ptrauth_extra_data_t; + +/* An integer type of the appropriate size for a generic signature. */ +typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t; + +/* A signed pointer value embeds the original pointer together with + a signature that attests to the validity of that pointer. Because + this signature must use only "spare" bits of the pointer, a + signature's validity is probabilistic in practice: it is unlikely + but still plausible that an invalidly-derived signature will + somehow equal the correct signature and therefore successfully + authenticate. Nonetheless, this scheme provides a strong degree + of protection against certain kinds of attacks. */ + +/* Authenticating a pointer that was not signed with the given key + and extra-data value will (likely) fail by trapping. */ + +#if __has_feature(ptrauth_intrinsics) + +/* Strip the signature from a value without authenticating it. + + If the value is a function pointer, the result will not be a + legal function pointer because of the missing signature, and + attempting to call it will result in an authentication failure. + + The value must be an expression of pointer type. + The key must be a constant expression of type ptrauth_key. + The result will have the same type as the original value. */ +#define ptrauth_strip(__value, __key) __builtin_ptrauth_strip(__value, __key) + +/* Blend a constant discriminator into the given pointer-like value + to form a new discriminator. Not all bits of the inputs are + guaranteed to contribute to the result. + + On arm64e, the integer must fall within the range of a uint16_t; + other bits may be ignored. + + The first argument must be an expression of pointer type. + The second argument must be an expression of integer type. + The result will have type uintptr_t. */ +#define ptrauth_blend_discriminator(__pointer, __integer) \ + __builtin_ptrauth_blend_discriminator(__pointer, __integer) + +/* Add a signature to the given pointer value using a specific key, + using the given extra data as a salt to the signing process. + + This operation does not authenticate the original value and is + therefore potentially insecure if an attacker could possibly + control that value. + + The value must be an expression of pointer type. + The key must be a constant expression of type ptrauth_key. + The extra data must be an expression of pointer or integer type; + if an integer, it will be coerced to ptrauth_extra_data_t. + The result will have the same type as the original value. */ +#define ptrauth_sign_unauthenticated(__value, __key, __data) \ + __builtin_ptrauth_sign_unauthenticated(__value, __key, __data) + +/* Authenticate a pointer using one scheme and resign it using another. + + If the result is subsequently authenticated using the new scheme, that + authentication is guaranteed to fail if and only if the initial + authentication failed. + + The value must be an expression of pointer type. + The key must be a constant expression of type ptrauth_key. + The extra data must be an expression of pointer or integer type; + if an integer, it will be coerced to ptrauth_extra_data_t. + The result will have the same type as the original value. + + This operation is guaranteed to not leave the intermediate value + available for attack before it is re-signed. + + Do not pass a null pointer to this function. A null pointer + will not successfully authenticate. + + This operation traps if the authentication fails. */ +#define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \ + __new_data) \ + __builtin_ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \ + __new_data) + +/* Authenticate a data pointer. + + The value must be an expression of non-function pointer type. + The key must be a constant expression of type ptrauth_key. + The extra data must be an expression of pointer or integer type; + if an integer, it will be coerced to ptrauth_extra_data_t. + The result will have the same type as the original value. + + This operation traps if the authentication fails. */ +#define ptrauth_auth_data(__value, __old_key, __old_data) \ + __builtin_ptrauth_auth(__value, __old_key, __old_data) + +/* Compute a signature for the given pair of pointer-sized values. + The order of the arguments is significant. + + Like a pointer signature, the resulting signature depends on + private key data and therefore should not be reliably reproducible + by attackers. That means that this can be used to validate the + integrity of arbitrary data by storing a signature for that data + alongside it, then checking that the signature is still valid later. + Data which exceeds two pointers in size can be signed by either + computing a tree of generic signatures or just signing an ordinary + cryptographic hash of the data. + + The result has type ptrauth_generic_signature_t. However, it may + not have as many bits of entropy as that type's width would suggest; + some implementations are known to compute a compressed signature as + if the arguments were a pointer and a discriminator. + + The arguments must be either pointers or integers; if integers, they + will be coerce to uintptr_t. */ +#define ptrauth_sign_generic_data(__value, __data) \ + __builtin_ptrauth_sign_generic_data(__value, __data) + +#else + +#define ptrauth_strip(__value, __key) \ + ({ \ + (void)__key; \ + __value; \ + }) + +#define ptrauth_blend_discriminator(__pointer, __integer) \ + ({ \ + (void)__pointer; \ + (void)__integer; \ + ((ptrauth_extra_data_t)0); \ + }) + +#define ptrauth_sign_unauthenticated(__value, __key, __data) \ + ({ \ + (void)__key; \ + (void)__data; \ + __value; \ + }) + +#define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \ + __new_data) \ + ({ \ + (void)__old_key; \ + (void)__old_data; \ + (void)__new_key; \ + (void)__new_data; \ + __value; \ + }) + +#define ptrauth_auth_data(__value, __old_key, __old_data) \ + ({ \ + (void)__old_key; \ + (void)__old_data; \ + __value; \ + }) + +#define ptrauth_sign_generic_data(__value, __data) \ + ({ \ + (void)__value; \ + (void)__data; \ + ((ptrauth_generic_signature_t)0); \ + }) + +#endif /* __has_feature(ptrauth_intrinsics) */ + +#endif /* __PTRAUTH_H */ diff --git a/clang/lib/Headers/smmintrin.h b/clang/lib/Headers/smmintrin.h index 9fb9cc9b01348cae2302249e55020fc0c36a58fb..b3fec474e35a1e03e7b4de6e434355a959caeb25 100644 --- a/clang/lib/Headers/smmintrin.h +++ b/clang/lib/Headers/smmintrin.h @@ -1188,7 +1188,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_testnzc_si128(__m128i __M, /// Compares each of the corresponding 64-bit values of the 128-bit /// integer vectors for equality. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. /// /// \headerfile <x86intrin.h> /// @@ -2303,7 +2303,7 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_minpos_epu16(__m128i __V) { /// integer vectors to determine if the values in the first operand are /// greater than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. /// /// \headerfile <x86intrin.h> /// diff --git a/clang/lib/Headers/x86gprintrin.h b/clang/lib/Headers/x86gprintrin.h index ed141879fbc744213807f5d400e44cd0f0eb807c..3d5cc606d7e63d85ccb068fd58df6a68c4b2f7f3 100644 --- a/clang/lib/Headers/x86gprintrin.h +++ b/clang/lib/Headers/x86gprintrin.h @@ -10,38 +10,31 @@ #ifndef __X86GPRINTRIN_H #define __X86GPRINTRIN_H -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__HRESET__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__HRESET__) #include <hresetintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__UINTR__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__UINTR__) #include <uintrintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__USERMSR__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__USERMSR__) #include <usermsrintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__CRC32__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__CRC32__) #include <crc32intrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__PRFCHI__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__PRFCHI__) #include <prfchiintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__RAOINT__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__RAOINT__) #include <raointintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__CMPCCXADD__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__CMPCCXADD__) #include <cmpccxaddintrin.h> #endif diff --git a/clang/lib/Headers/x86intrin.h b/clang/lib/Headers/x86intrin.h index 450fd008dab95ba2c69d7839c857bef07e4b07d2..c20bfbb8fe46e2f05ef95e03ebfa2aaf812b57d0 100644 --- a/clang/lib/Headers/x86intrin.h +++ b/clang/lib/Headers/x86intrin.h @@ -14,53 +14,43 @@ #include <immintrin.h> -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__3dNOW__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__3dNOW__) #include <mm3dnow.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__PRFCHW__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__PRFCHW__) #include <prfchwintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__SSE4A__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__SSE4A__) #include <ammintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__FMA4__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__FMA4__) #include <fma4intrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__XOP__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__XOP__) #include <xopintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__TBM__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__TBM__) #include <tbmintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__LWP__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__LWP__) #include <lwpintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__MWAITX__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__MWAITX__) #include <mwaitxintrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__CLZERO__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__CLZERO__) #include <clzerointrin.h> #endif -#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ - defined(__RDPRU__) +#if !defined(__SCE__) || __has_feature(modules) || defined(__RDPRU__) #include <rdpruintrin.h> #endif diff --git a/clang/lib/Headers/xmmintrin.h b/clang/lib/Headers/xmmintrin.h index 8e386a72cde78989cbb0324aaf011ef46bbe11d9..1ef89de9c9f5622d60b63fa19c06ddf7589488ef 100644 --- a/clang/lib/Headers/xmmintrin.h +++ b/clang/lib/Headers/xmmintrin.h @@ -316,6 +316,8 @@ _mm_rsqrt_ps(__m128 __a) /// operands and returns the lesser value in the low-order bits of the /// vector of [4 x float]. /// +/// If either value in a comparison is NaN, returns the value from \a __b. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VMINSS / MINSS </c> instructions. @@ -338,6 +340,8 @@ _mm_min_ss(__m128 __a, __m128 __b) /// Compares two 128-bit vectors of [4 x float] and returns the lesser /// of each pair of values. /// +/// If either value in a comparison is NaN, returns the value from \a __b. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VMINPS / MINPS </c> instructions. @@ -358,6 +362,8 @@ _mm_min_ps(__m128 __a, __m128 __b) /// operands and returns the greater value in the low-order bits of a 128-bit /// vector of [4 x float]. /// +/// If either value in a comparison is NaN, returns the value from \a __b. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VMAXSS / MAXSS </c> instructions. @@ -380,6 +386,8 @@ _mm_max_ss(__m128 __a, __m128 __b) /// Compares two 128-bit vectors of [4 x float] and returns the greater /// of each pair of values. /// +/// If either value in a comparison is NaN, returns the value from \a __b. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VMAXPS / MAXPS </c> instructions. @@ -476,8 +484,9 @@ _mm_xor_ps(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both /// operands for equality. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// The comparison returns 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector [4 x float]. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -500,7 +509,8 @@ _mm_cmpeq_ss(__m128 __a, __m128 __b) /// Compares each of the corresponding 32-bit float values of the /// 128-bit vectors of [4 x float] for equality. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -521,8 +531,9 @@ _mm_cmpeq_ps(__m128 __a, __m128 __b) /// operands to determine if the value in the first operand is less than the /// corresponding value in the second operand. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// The comparison returns 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector of [4 x float]. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -546,7 +557,8 @@ _mm_cmplt_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are less than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -567,8 +579,9 @@ _mm_cmplt_ps(__m128 __a, __m128 __b) /// operands to determine if the value in the first operand is less than or /// equal to the corresponding value in the second operand. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true, in +/// The comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true, in /// the low-order bits of a vector of [4 x float]. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -592,7 +605,8 @@ _mm_cmple_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are less than or equal to those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -613,8 +627,9 @@ _mm_cmple_ps(__m128 __a, __m128 __b) /// operands to determine if the value in the first operand is greater than /// the corresponding value in the second operand. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// The comparison returns 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector of [4 x float]. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -640,7 +655,8 @@ _mm_cmpgt_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are greater than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -661,8 +677,9 @@ _mm_cmpgt_ps(__m128 __a, __m128 __b) /// operands to determine if the value in the first operand is greater than /// or equal to the corresponding value in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector of [4 x float]. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -688,7 +705,8 @@ _mm_cmpge_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are greater than or equal to those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFFFFFFFFFF for true. +/// If either value in a comparison is NaN, returns false. /// /// \headerfile <x86intrin.h> /// @@ -708,8 +726,9 @@ _mm_cmpge_ps(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both operands /// for inequality. /// -/// The comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// The comparison returns 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector of [4 x float]. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -733,7 +752,8 @@ _mm_cmpneq_ss(__m128 __a, __m128 __b) /// Compares each of the corresponding 32-bit float values of the /// 128-bit vectors of [4 x float] for inequality. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -755,8 +775,9 @@ _mm_cmpneq_ps(__m128 __a, __m128 __b) /// operands to determine if the value in the first operand is not less than /// the corresponding value in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector of [4 x float]. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -781,7 +802,8 @@ _mm_cmpnlt_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are not less than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -803,8 +825,9 @@ _mm_cmpnlt_ps(__m128 __a, __m128 __b) /// operands to determine if the value in the first operand is not less than /// or equal to the corresponding value in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector of [4 x float]. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -829,7 +852,8 @@ _mm_cmpnle_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are not less than or equal to those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -851,8 +875,9 @@ _mm_cmpnle_ps(__m128 __a, __m128 __b) /// operands to determine if the value in the first operand is not greater /// than the corresponding value in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector of [4 x float]. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -879,7 +904,8 @@ _mm_cmpngt_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are not greater than those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -901,8 +927,9 @@ _mm_cmpngt_ps(__m128 __a, __m128 __b) /// operands to determine if the value in the first operand is not greater /// than or equal to the corresponding value in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true, in the /// low-order bits of a vector of [4 x float]. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -929,7 +956,8 @@ _mm_cmpnge_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are not greater than or equal to those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. +/// If either value in a comparison is NaN, returns true. /// /// \headerfile <x86intrin.h> /// @@ -951,8 +979,9 @@ _mm_cmpnge_ps(__m128 __a, __m128 __b) /// operands to determine if the value in the first operand is ordered with /// respect to the corresponding value in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the -/// low-order bits of a vector of [4 x float]. +/// A pair of floating-point values are ordered with respect to each +/// other if neither value is a NaN. Each comparison returns 0x0 for false, +/// 0xFFFFFFFF for true. /// /// \headerfile <x86intrin.h> /// @@ -977,7 +1006,9 @@ _mm_cmpord_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are ordered with respect to those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// A pair of floating-point values are ordered with respect to each +/// other if neither value is a NaN. Each comparison returns 0x0 for false, +/// 0xFFFFFFFF for true. /// /// \headerfile <x86intrin.h> /// @@ -999,8 +1030,9 @@ _mm_cmpord_ps(__m128 __a, __m128 __b) /// operands to determine if the value in the first operand is unordered /// with respect to the corresponding value in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the -/// low-order bits of a vector of [4 x float]. +/// A pair of double-precision values are unordered with respect to each +/// other if one or both values are NaN. Each comparison returns 0x0 for +/// false, 0xFFFFFFFF for true. /// /// \headerfile <x86intrin.h> /// @@ -1025,7 +1057,9 @@ _mm_cmpunord_ss(__m128 __a, __m128 __b) /// 128-bit vectors of [4 x float] to determine if the values in the first /// operand are unordered with respect to those in the second operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// A pair of double-precision values are unordered with respect to each +/// other if one or both values are NaN. Each comparison returns 0x0 for +/// false, 0xFFFFFFFFFFFFFFFF for true. /// /// \headerfile <x86intrin.h> /// @@ -1046,8 +1080,8 @@ _mm_cmpunord_ps(__m128 __a, __m128 __b) /// Compares two 32-bit float values in the low-order bits of both /// operands for equality. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower floating-point values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1071,8 +1105,8 @@ _mm_comieq_ss(__m128 __a, __m128 __b) /// operands to determine if the first operand is less than the second /// operand. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower floating-point values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1096,8 +1130,8 @@ _mm_comilt_ss(__m128 __a, __m128 __b) /// operands to determine if the first operand is less than or equal to the /// second operand. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower floating-point values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1120,8 +1154,8 @@ _mm_comile_ss(__m128 __a, __m128 __b) /// operands to determine if the first operand is greater than the second /// operand. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower floating-point values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1144,8 +1178,8 @@ _mm_comigt_ss(__m128 __a, __m128 __b) /// operands to determine if the first operand is greater than or equal to /// the second operand. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower floating-point values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1168,8 +1202,8 @@ _mm_comige_ss(__m128 __a, __m128 __b) /// operands to determine if the first operand is not equal to the second /// operand. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower floating-point values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 1. /// /// \headerfile <x86intrin.h> /// @@ -1191,8 +1225,8 @@ _mm_comineq_ss(__m128 __a, __m128 __b) /// Performs an unordered comparison of two 32-bit float values using /// the low-order bits of both operands to determine equality. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower floating-point values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1215,8 +1249,8 @@ _mm_ucomieq_ss(__m128 __a, __m128 __b) /// the low-order bits of both operands to determine if the first operand is /// less than the second operand. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower floating-point values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1239,8 +1273,8 @@ _mm_ucomilt_ss(__m128 __a, __m128 __b) /// the low-order bits of both operands to determine if the first operand is /// less than or equal to the second operand. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower floating-point values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1263,8 +1297,8 @@ _mm_ucomile_ss(__m128 __a, __m128 __b) /// the low-order bits of both operands to determine if the first operand is /// greater than the second operand. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower floating-point values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1287,8 +1321,8 @@ _mm_ucomigt_ss(__m128 __a, __m128 __b) /// the low-order bits of both operands to determine if the first operand is /// greater than or equal to the second operand. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower floating-point values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1310,8 +1344,8 @@ _mm_ucomige_ss(__m128 __a, __m128 __b) /// Performs an unordered comparison of two 32-bit float values using /// the low-order bits of both operands to determine inequality. /// -/// The comparison returns 0 for false, 1 for true. If either of the two -/// lower floating-point values is NaN, returns 0. +/// The comparison returns 0 for false, 1 for true. If either value in a +/// comparison is NaN, returns 0. /// /// \headerfile <x86intrin.h> /// @@ -1333,6 +1367,10 @@ _mm_ucomineq_ss(__m128 __a, __m128 __b) /// Converts a float value contained in the lower 32 bits of a vector of /// [4 x float] into a 32-bit integer. /// +/// If the converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VCVTSS2SI / CVTSS2SI </c> @@ -1351,6 +1389,10 @@ _mm_cvtss_si32(__m128 __a) /// Converts a float value contained in the lower 32 bits of a vector of /// [4 x float] into a 32-bit integer. /// +/// If the converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VCVTSS2SI / CVTSS2SI </c> @@ -1371,6 +1413,10 @@ _mm_cvt_ss2si(__m128 __a) /// Converts a float value contained in the lower 32 bits of a vector of /// [4 x float] into a 64-bit integer. /// +/// If the converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> VCVTSS2SI / CVTSS2SI </c> @@ -1391,6 +1437,10 @@ _mm_cvtss_si64(__m128 __a) /// Converts two low-order float values in a 128-bit vector of /// [4 x float] into a 64-bit vector of [2 x i32]. /// +/// If a converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> CVTPS2PI </c> instruction. @@ -1407,6 +1457,10 @@ _mm_cvtps_pi32(__m128 __a) /// Converts two low-order float values in a 128-bit vector of /// [4 x float] into a 64-bit vector of [2 x i32]. /// +/// If a converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. +/// /// \headerfile <x86intrin.h> /// /// This intrinsic corresponds to the <c> CVTPS2PI </c> instruction. @@ -1420,9 +1474,12 @@ _mm_cvt_ps2pi(__m128 __a) return _mm_cvtps_pi32(__a); } -/// Converts a float value contained in the lower 32 bits of a vector of -/// [4 x float] into a 32-bit integer, truncating the result when it is -/// inexact. +/// Converts the lower (first) element of a vector of [4 x float] into a signed +/// truncated (rounded toward zero) 32-bit integer. +/// +/// If the converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. /// /// \headerfile <x86intrin.h> /// @@ -1439,9 +1496,12 @@ _mm_cvttss_si32(__m128 __a) return __builtin_ia32_cvttss2si((__v4sf)__a); } -/// Converts a float value contained in the lower 32 bits of a vector of -/// [4 x float] into a 32-bit integer, truncating the result when it is -/// inexact. +/// Converts the lower (first) element of a vector of [4 x float] into a signed +/// truncated (rounded toward zero) 32-bit integer. +/// +/// If the converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. /// /// \headerfile <x86intrin.h> /// @@ -1459,9 +1519,12 @@ _mm_cvtt_ss2si(__m128 __a) } #ifdef __x86_64__ -/// Converts a float value contained in the lower 32 bits of a vector of -/// [4 x float] into a 64-bit integer, truncating the result when it is -/// inexact. +/// Converts the lower (first) element of a vector of [4 x float] into a signed +/// truncated (rounded toward zero) 64-bit integer. +/// +/// If the converted value does not fit in a 64-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. /// /// \headerfile <x86intrin.h> /// @@ -1479,9 +1542,13 @@ _mm_cvttss_si64(__m128 __a) } #endif -/// Converts two low-order float values in a 128-bit vector of -/// [4 x float] into a 64-bit vector of [2 x i32], truncating the result -/// when it is inexact. +/// Converts the lower (first) two elements of a 128-bit vector of [4 x float] +/// into two signed truncated (rounded toward zero) 32-bit integers, +/// returned in a 64-bit vector of [2 x i32]. +/// +/// If a converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. /// /// \headerfile <x86intrin.h> /// @@ -1497,9 +1564,13 @@ _mm_cvttps_pi32(__m128 __a) return (__m64)__builtin_ia32_cvttps2pi((__v4sf)__a); } -/// Converts two low-order float values in a 128-bit vector of [4 x -/// float] into a 64-bit vector of [2 x i32], truncating the result when it -/// is inexact. +/// Converts the lower (first) two elements of a 128-bit vector of [4 x float] +/// into two signed truncated (rounded toward zero) 64-bit integers, +/// returned in a 64-bit vector of [2 x i32]. +/// +/// If a converted value does not fit in a 32-bit integer, raises a +/// floating-point invalid exception. If the exception is masked, returns +/// the most negative integer. /// /// \headerfile <x86intrin.h> /// @@ -2990,7 +3061,9 @@ _mm_movemask_ps(__m128 __a) /// [4 x float], using the operation specified by the immediate integer /// operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. +/// If either value in a comparison is NaN, comparisons that are ordered +/// return false, and comparisons that are unordered return true. /// /// \headerfile <x86intrin.h> /// @@ -3023,7 +3096,9 @@ _mm_movemask_ps(__m128 __a) /// vectors of [4 x float], using the operation specified by the immediate /// integer operand. /// -/// Each comparison yields 0x0 for false, 0xFFFFFFFF for true. +/// Each comparison returns 0x0 for false, 0xFFFFFFFF for true. +/// If either value in a comparison is NaN, comparisons that are ordered +/// return false, and comparisons that are unordered return true. /// /// \headerfile <x86intrin.h> /// diff --git a/clang/lib/Headers/yvals_core.h b/clang/lib/Headers/yvals_core.h new file mode 100644 index 0000000000000000000000000000000000000000..5ee194a3e5f5f60b83cad4115fbb36c005e7646e --- /dev/null +++ b/clang/lib/Headers/yvals_core.h @@ -0,0 +1,25 @@ +//===----- yvals_core.h - Internal MSVC STL core header -------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// Only include this if we are aiming for MSVC compatibility. +#ifndef _MSC_VER +#include_next <yvals_core.h> +#else + +#ifndef __clang_yvals_core_h +#define __clang_yvals_core_h + +#include_next <yvals_core.h> + +#ifdef _STL_INTRIN_HEADER +#undef _STL_INTRIN_HEADER +#define _STL_INTRIN_HEADER <intrin0.h> +#endif + +#endif +#endif diff --git a/clang/lib/InstallAPI/CMakeLists.txt b/clang/lib/InstallAPI/CMakeLists.txt index dc90d6370de418f34f981e3993af658de62d9f38..e0bc8d969ecb3afc95498d177d2d63c9236f9616 100644 --- a/clang/lib/InstallAPI/CMakeLists.txt +++ b/clang/lib/InstallAPI/CMakeLists.txt @@ -1,10 +1,13 @@ set(LLVM_LINK_COMPONENTS Support TextAPI + TextAPIBinaryReader + Demangle Core ) add_clang_library(clangInstallAPI + DylibVerifier.cpp FileList.cpp Frontend.cpp HeaderFile.cpp diff --git a/clang/lib/InstallAPI/DylibVerifier.cpp b/clang/lib/InstallAPI/DylibVerifier.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c0eda1d81b9b9839fded64a905d0169ce95cbc5c --- /dev/null +++ b/clang/lib/InstallAPI/DylibVerifier.cpp @@ -0,0 +1,706 @@ +//===- DylibVerifier.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 "clang/InstallAPI/DylibVerifier.h" +#include "clang/InstallAPI/FrontendRecords.h" +#include "clang/InstallAPI/InstallAPIDiagnostic.h" +#include "llvm/Demangle/Demangle.h" +#include "llvm/TextAPI/DylibReader.h" + +using namespace llvm::MachO; + +namespace clang { +namespace installapi { + +/// Metadata stored about a mapping of a declaration to a symbol. +struct DylibVerifier::SymbolContext { + // Name to use for all querying and verification + // purposes. + std::string SymbolName{""}; + + // Kind to map symbol type against record. + EncodeKind Kind = EncodeKind::GlobalSymbol; + + // Frontend Attributes tied to the AST. + const FrontendAttrs *FA = nullptr; + + // The ObjCInterface symbol type, if applicable. + ObjCIFSymbolKind ObjCIFKind = ObjCIFSymbolKind::None; + + // Whether Decl is inlined. + bool Inlined = false; +}; + +struct DylibVerifier::DWARFContext { + // Track whether DSYM parsing has already been attempted to avoid re-parsing. + bool ParsedDSYM{false}; + + // Lookup table for source locations by symbol name. + DylibReader::SymbolToSourceLocMap SourceLocs{}; +}; + +static bool isCppMangled(StringRef Name) { + // InstallAPI currently only supports itanium manglings. + return (Name.starts_with("_Z") || Name.starts_with("__Z") || + Name.starts_with("___Z")); +} + +static std::string demangle(StringRef Name) { + // InstallAPI currently only supports itanium manglings. + if (!isCppMangled(Name)) + return Name.str(); + char *Result = llvm::itaniumDemangle(Name); + if (!Result) + return Name.str(); + + std::string Demangled(Result); + free(Result); + return Demangled; +} + +std::string DylibVerifier::getAnnotatedName(const Record *R, + SymbolContext &SymCtx, + bool ValidSourceLoc) { + assert(!SymCtx.SymbolName.empty() && "Expected symbol name"); + + const StringRef SymbolName = SymCtx.SymbolName; + std::string PrettyName = + (Demangle && (SymCtx.Kind == EncodeKind::GlobalSymbol)) + ? demangle(SymbolName) + : SymbolName.str(); + + std::string Annotation; + if (R->isWeakDefined()) + Annotation += "(weak-def) "; + if (R->isWeakReferenced()) + Annotation += "(weak-ref) "; + if (R->isThreadLocalValue()) + Annotation += "(tlv) "; + + // Check if symbol represents only part of a @interface declaration. + switch (SymCtx.ObjCIFKind) { + default: + break; + case ObjCIFSymbolKind::EHType: + return Annotation + "Exception Type of " + PrettyName; + case ObjCIFSymbolKind::MetaClass: + return Annotation + "Metaclass of " + PrettyName; + case ObjCIFSymbolKind::Class: + return Annotation + "Class of " + PrettyName; + } + + // Only print symbol type prefix or leading "_" if there is no source location + // tied to it. This can only ever happen when the location has to come from + // debug info. + if (ValidSourceLoc) { + StringRef PrettyNameRef(PrettyName); + if ((SymCtx.Kind == EncodeKind::GlobalSymbol) && + !isCppMangled(SymbolName) && PrettyNameRef.starts_with("_")) + return Annotation + PrettyNameRef.drop_front(1).str(); + return Annotation + PrettyName; + } + + switch (SymCtx.Kind) { + case EncodeKind::GlobalSymbol: + return Annotation + PrettyName; + case EncodeKind::ObjectiveCInstanceVariable: + return Annotation + "(ObjC IVar) " + PrettyName; + case EncodeKind::ObjectiveCClass: + return Annotation + "(ObjC Class) " + PrettyName; + case EncodeKind::ObjectiveCClassEHType: + return Annotation + "(ObjC Class EH) " + PrettyName; + } + + llvm_unreachable("unexpected case for EncodeKind"); +} + +static DylibVerifier::Result updateResult(const DylibVerifier::Result Prev, + const DylibVerifier::Result Curr) { + if (Prev == Curr) + return Prev; + + // Never update from invalid or noverify state. + if ((Prev == DylibVerifier::Result::Invalid) || + (Prev == DylibVerifier::Result::NoVerify)) + return Prev; + + // Don't let an ignored verification remove a valid one. + if (Prev == DylibVerifier::Result::Valid && + Curr == DylibVerifier::Result::Ignore) + return Prev; + + return Curr; +} +// __private_extern__ is a deprecated specifier that clang does not +// respect in all contexts, it should just be considered hidden for InstallAPI. +static bool shouldIgnorePrivateExternAttr(const Decl *D) { + if (const FunctionDecl *FD = cast<FunctionDecl>(D)) + return FD->getStorageClass() == StorageClass::SC_PrivateExtern; + if (const VarDecl *VD = cast<VarDecl>(D)) + return VD->getStorageClass() == StorageClass::SC_PrivateExtern; + + return false; +} + +Record *findRecordFromSlice(const RecordsSlice *Slice, StringRef Name, + EncodeKind Kind) { + switch (Kind) { + case EncodeKind::GlobalSymbol: + return Slice->findGlobal(Name); + case EncodeKind::ObjectiveCInstanceVariable: + return Slice->findObjCIVar(Name.contains('.'), Name); + case EncodeKind::ObjectiveCClass: + case EncodeKind::ObjectiveCClassEHType: + return Slice->findObjCInterface(Name); + } + llvm_unreachable("unexpected end when finding record"); +} + +void DylibVerifier::updateState(Result State) { + Ctx.FrontendState = updateResult(Ctx.FrontendState, State); +} + +void DylibVerifier::addSymbol(const Record *R, SymbolContext &SymCtx, + TargetList &&Targets) { + if (Targets.empty()) + Targets = {Ctx.Target}; + + Exports->addGlobal(SymCtx.Kind, SymCtx.SymbolName, R->getFlags(), Targets); +} + +bool DylibVerifier::shouldIgnoreObsolete(const Record *R, SymbolContext &SymCtx, + const Record *DR) { + return SymCtx.FA->Avail.isObsoleted(); +} + +bool DylibVerifier::compareObjCInterfaceSymbols(const Record *R, + SymbolContext &SymCtx, + const ObjCInterfaceRecord *DR) { + const bool IsDeclVersionComplete = + ((SymCtx.ObjCIFKind & ObjCIFSymbolKind::Class) == + ObjCIFSymbolKind::Class) && + ((SymCtx.ObjCIFKind & ObjCIFSymbolKind::MetaClass) == + ObjCIFSymbolKind::MetaClass); + + const bool IsDylibVersionComplete = DR->isCompleteInterface(); + + // The common case, a complete ObjCInterface. + if (IsDeclVersionComplete && IsDylibVersionComplete) + return true; + + auto PrintDiagnostic = [&](auto SymLinkage, const Record *Record, + StringRef SymName, bool PrintAsWarning = false) { + if (SymLinkage == RecordLinkage::Unknown) + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + PrintAsWarning ? diag::warn_library_missing_symbol + : diag::err_library_missing_symbol) + << SymName; + }); + else + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + PrintAsWarning ? diag::warn_library_hidden_symbol + : diag::err_library_hidden_symbol) + << SymName; + }); + }; + + if (IsDeclVersionComplete) { + // The decl represents a complete ObjCInterface, but the symbols in the + // dylib do not. Determine which symbol is missing. To keep older projects + // building, treat this as a warning. + if (!DR->isExportedSymbol(ObjCIFSymbolKind::Class)) { + SymCtx.ObjCIFKind = ObjCIFSymbolKind::Class; + PrintDiagnostic(DR->getLinkageForSymbol(ObjCIFSymbolKind::Class), R, + getAnnotatedName(R, SymCtx), + /*PrintAsWarning=*/true); + } + if (!DR->isExportedSymbol(ObjCIFSymbolKind::MetaClass)) { + SymCtx.ObjCIFKind = ObjCIFSymbolKind::MetaClass; + PrintDiagnostic(DR->getLinkageForSymbol(ObjCIFSymbolKind::MetaClass), R, + getAnnotatedName(R, SymCtx), + /*PrintAsWarning=*/true); + } + return true; + } + + if (DR->isExportedSymbol(SymCtx.ObjCIFKind)) { + if (!IsDylibVersionComplete) { + // Both the declaration and dylib have a non-complete interface. + SymCtx.Kind = EncodeKind::GlobalSymbol; + SymCtx.SymbolName = R->getName(); + } + return true; + } + + // At this point that means there was not a matching class symbol + // to represent the one discovered as a declaration. + PrintDiagnostic(DR->getLinkageForSymbol(SymCtx.ObjCIFKind), R, + SymCtx.SymbolName); + return false; +} + +DylibVerifier::Result DylibVerifier::compareVisibility(const Record *R, + SymbolContext &SymCtx, + const Record *DR) { + + if (R->isExported()) { + if (!DR) { + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + diag::err_library_missing_symbol) + << getAnnotatedName(R, SymCtx); + }); + return Result::Invalid; + } + if (DR->isInternal()) { + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + diag::err_library_hidden_symbol) + << getAnnotatedName(R, SymCtx); + }); + return Result::Invalid; + } + } + + // Emit a diagnostic for hidden declarations with external symbols, except + // when theres an inlined attribute. + if ((R->isInternal() && !SymCtx.Inlined) && DR && DR->isExported()) { + + if (Mode == VerificationMode::ErrorsOnly) + return Result::Ignore; + + if (shouldIgnorePrivateExternAttr(SymCtx.FA->D)) + return Result::Ignore; + + unsigned ID; + Result Outcome; + if (Mode == VerificationMode::ErrorsAndWarnings) { + ID = diag::warn_header_hidden_symbol; + Outcome = Result::Ignore; + } else { + ID = diag::err_header_hidden_symbol; + Outcome = Result::Invalid; + } + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), ID) + << getAnnotatedName(R, SymCtx); + }); + return Outcome; + } + + if (R->isInternal()) + return Result::Ignore; + + return Result::Valid; +} + +DylibVerifier::Result DylibVerifier::compareAvailability(const Record *R, + SymbolContext &SymCtx, + const Record *DR) { + if (!SymCtx.FA->Avail.isUnavailable()) + return Result::Valid; + + const bool IsDeclAvailable = SymCtx.FA->Avail.isUnavailable(); + + switch (Mode) { + case VerificationMode::ErrorsAndWarnings: + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + diag::warn_header_availability_mismatch) + << getAnnotatedName(R, SymCtx) << IsDeclAvailable << IsDeclAvailable; + }); + return Result::Ignore; + case VerificationMode::Pedantic: + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + diag::err_header_availability_mismatch) + << getAnnotatedName(R, SymCtx) << IsDeclAvailable << IsDeclAvailable; + }); + return Result::Invalid; + case VerificationMode::ErrorsOnly: + return Result::Ignore; + case VerificationMode::Invalid: + llvm_unreachable("Unexpected verification mode symbol verification"); + } + llvm_unreachable("Unexpected verification mode symbol verification"); +} + +bool DylibVerifier::compareSymbolFlags(const Record *R, SymbolContext &SymCtx, + const Record *DR) { + if (DR->isThreadLocalValue() && !R->isThreadLocalValue()) { + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + diag::err_dylib_symbol_flags_mismatch) + << getAnnotatedName(DR, SymCtx) << DR->isThreadLocalValue(); + }); + return false; + } + if (!DR->isThreadLocalValue() && R->isThreadLocalValue()) { + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + diag::err_header_symbol_flags_mismatch) + << getAnnotatedName(R, SymCtx) << R->isThreadLocalValue(); + }); + return false; + } + + if (DR->isWeakDefined() && !R->isWeakDefined()) { + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + diag::err_dylib_symbol_flags_mismatch) + << getAnnotatedName(DR, SymCtx) << R->isWeakDefined(); + }); + return false; + } + if (!DR->isWeakDefined() && R->isWeakDefined()) { + Ctx.emitDiag([&]() { + Ctx.Diag->Report(SymCtx.FA->D->getLocation(), + diag::err_header_symbol_flags_mismatch) + << getAnnotatedName(R, SymCtx) << R->isWeakDefined(); + }); + return false; + } + + return true; +} + +DylibVerifier::Result DylibVerifier::verifyImpl(Record *R, + SymbolContext &SymCtx) { + R->setVerify(); + if (!canVerify()) { + // Accumulate symbols when not in verifying against dylib. + if (R->isExported() && !SymCtx.FA->Avail.isUnavailable() && + !SymCtx.FA->Avail.isObsoleted()) { + addSymbol(R, SymCtx); + } + return Ctx.FrontendState; + } + + Record *DR = + findRecordFromSlice(Ctx.DylibSlice, SymCtx.SymbolName, SymCtx.Kind); + if (DR) + DR->setVerify(); + + if (shouldIgnoreObsolete(R, SymCtx, DR)) { + updateState(Result::Ignore); + return Ctx.FrontendState; + } + + // Unavailable declarations don't need matching symbols. + if (SymCtx.FA->Avail.isUnavailable() && (!DR || DR->isInternal())) { + updateState(Result::Valid); + return Ctx.FrontendState; + } + + Result VisibilityCheck = compareVisibility(R, SymCtx, DR); + if (VisibilityCheck != Result::Valid) { + updateState(VisibilityCheck); + return Ctx.FrontendState; + } + + // All missing symbol cases to diagnose have been handled now. + if (!DR) { + updateState(Result::Ignore); + return Ctx.FrontendState; + } + + // Check for mismatching ObjC interfaces. + if (SymCtx.ObjCIFKind != ObjCIFSymbolKind::None) { + if (!compareObjCInterfaceSymbols( + R, SymCtx, Ctx.DylibSlice->findObjCInterface(DR->getName()))) { + updateState(Result::Invalid); + return Ctx.FrontendState; + } + } + + Result AvailabilityCheck = compareAvailability(R, SymCtx, DR); + if (AvailabilityCheck != Result::Valid) { + updateState(AvailabilityCheck); + return Ctx.FrontendState; + } + + if (!compareSymbolFlags(R, SymCtx, DR)) { + updateState(Result::Invalid); + return Ctx.FrontendState; + } + + addSymbol(R, SymCtx); + updateState(Result::Valid); + return Ctx.FrontendState; +} + +bool DylibVerifier::canVerify() { + return Ctx.FrontendState != Result::NoVerify; +} + +void DylibVerifier::assignSlice(const Target &T) { + assert(T == Ctx.Target && "Active targets should match."); + if (Dylib.empty()) + return; + + // Note: there are no reexport slices with binaries, as opposed to TBD files, + // so it can be assumed that the target match is the active top-level library. + auto It = find_if( + Dylib, [&T](const auto &Slice) { return T == Slice->getTarget(); }); + + assert(It != Dylib.end() && "Target slice should always exist."); + Ctx.DylibSlice = It->get(); +} + +void DylibVerifier::setTarget(const Target &T) { + Ctx.Target = T; + Ctx.DiscoveredFirstError = false; + if (Dylib.empty()) { + updateState(Result::NoVerify); + return; + } + updateState(Result::Ignore); + assignSlice(T); +} + +DylibVerifier::Result DylibVerifier::verify(ObjCIVarRecord *R, + const FrontendAttrs *FA, + const StringRef SuperClass) { + if (R->isVerified()) + return getState(); + + std::string FullName = + ObjCIVarRecord::createScopedName(SuperClass, R->getName()); + SymbolContext SymCtx{FullName, EncodeKind::ObjectiveCInstanceVariable, FA}; + return verifyImpl(R, SymCtx); +} + +static ObjCIFSymbolKind assignObjCIFSymbolKind(const ObjCInterfaceRecord *R) { + ObjCIFSymbolKind Result = ObjCIFSymbolKind::None; + if (R->getLinkageForSymbol(ObjCIFSymbolKind::Class) != RecordLinkage::Unknown) + Result |= ObjCIFSymbolKind::Class; + if (R->getLinkageForSymbol(ObjCIFSymbolKind::MetaClass) != + RecordLinkage::Unknown) + Result |= ObjCIFSymbolKind::MetaClass; + if (R->getLinkageForSymbol(ObjCIFSymbolKind::EHType) != + RecordLinkage::Unknown) + Result |= ObjCIFSymbolKind::EHType; + return Result; +} + +DylibVerifier::Result DylibVerifier::verify(ObjCInterfaceRecord *R, + const FrontendAttrs *FA) { + if (R->isVerified()) + return getState(); + SymbolContext SymCtx; + SymCtx.SymbolName = R->getName(); + SymCtx.ObjCIFKind = assignObjCIFSymbolKind(R); + + SymCtx.Kind = R->hasExceptionAttribute() ? EncodeKind::ObjectiveCClassEHType + : EncodeKind::ObjectiveCClass; + SymCtx.FA = FA; + + return verifyImpl(R, SymCtx); +} + +DylibVerifier::Result DylibVerifier::verify(GlobalRecord *R, + const FrontendAttrs *FA) { + if (R->isVerified()) + return getState(); + + // Global classifications could be obfusciated with `asm`. + SimpleSymbol Sym = parseSymbol(R->getName()); + SymbolContext SymCtx; + SymCtx.SymbolName = Sym.Name; + SymCtx.Kind = Sym.Kind; + SymCtx.FA = FA; + SymCtx.Inlined = R->isInlined(); + return verifyImpl(R, SymCtx); +} + +void DylibVerifier::VerifierContext::emitDiag(llvm::function_ref<void()> Report, + RecordLoc *Loc) { + if (!DiscoveredFirstError) { + Diag->Report(diag::warn_target) + << (PrintArch ? getArchitectureName(Target.Arch) + : getTargetTripleName(Target)); + DiscoveredFirstError = true; + } + if (Loc && Loc->isValid()) + llvm::errs() << Loc->File << ":" << Loc->Line << ":" << 0 << ": "; + + Report(); +} + +// The existence of weak-defined RTTI can not always be inferred from the +// header files because they can be generated as part of an implementation +// file. +// InstallAPI doesn't warn about weak-defined RTTI, because this doesn't affect +// static linking and so can be ignored for text-api files. +static bool shouldIgnoreCpp(StringRef Name, bool IsWeakDef) { + return (IsWeakDef && + (Name.starts_with("__ZTI") || Name.starts_with("__ZTS"))); +} +void DylibVerifier::visitSymbolInDylib(const Record &R, SymbolContext &SymCtx) { + // Undefined symbols should not be in InstallAPI generated text-api files. + if (R.isUndefined()) { + updateState(Result::Valid); + return; + } + + // Internal symbols should not be in InstallAPI generated text-api files. + if (R.isInternal()) { + updateState(Result::Valid); + return; + } + + // Allow zippered symbols with potentially mismatching availability + // between macOS and macCatalyst in the final text-api file. + const StringRef SymbolName(SymCtx.SymbolName); + if (const Symbol *Sym = Exports->findSymbol(SymCtx.Kind, SymCtx.SymbolName, + SymCtx.ObjCIFKind)) { + if (Sym->hasArchitecture(Ctx.Target.Arch)) { + updateState(Result::Ignore); + return; + } + } + + if (shouldIgnoreCpp(SymbolName, R.isWeakDefined())) { + updateState(Result::Valid); + return; + } + + const bool IsLinkerSymbol = SymbolName.starts_with("$ld$"); + + // All checks at this point classify as some kind of violation. + // The different verification modes dictate whether they are reported to the + // user. + if (IsLinkerSymbol || (Mode > VerificationMode::ErrorsOnly)) + accumulateSrcLocForDylibSymbols(); + RecordLoc Loc = DWARFCtx->SourceLocs.lookup(SymCtx.SymbolName); + + // Regardless of verification mode, error out on mismatched special linker + // symbols. + if (IsLinkerSymbol) { + Ctx.emitDiag( + [&]() { + Ctx.Diag->Report(diag::err_header_symbol_missing) + << getAnnotatedName(&R, SymCtx, Loc.isValid()); + }, + &Loc); + updateState(Result::Invalid); + return; + } + + // Missing declarations for exported symbols are hard errors on Pedantic mode. + if (Mode == VerificationMode::Pedantic) { + Ctx.emitDiag( + [&]() { + Ctx.Diag->Report(diag::err_header_symbol_missing) + << getAnnotatedName(&R, SymCtx, Loc.isValid()); + }, + &Loc); + updateState(Result::Invalid); + return; + } + + // Missing declarations for exported symbols are warnings on ErrorsAndWarnings + // mode. + if (Mode == VerificationMode::ErrorsAndWarnings) { + Ctx.emitDiag( + [&]() { + Ctx.Diag->Report(diag::warn_header_symbol_missing) + << getAnnotatedName(&R, SymCtx, Loc.isValid()); + }, + &Loc); + updateState(Result::Ignore); + return; + } + + // Missing declarations are dropped for ErrorsOnly mode. It is the last + // remaining mode. + updateState(Result::Ignore); + return; +} + +void DylibVerifier::visitGlobal(const GlobalRecord &R) { + if (R.isVerified()) + return; + SymbolContext SymCtx; + SimpleSymbol Sym = parseSymbol(R.getName()); + SymCtx.SymbolName = Sym.Name; + SymCtx.Kind = Sym.Kind; + visitSymbolInDylib(R, SymCtx); +} + +void DylibVerifier::visitObjCIVar(const ObjCIVarRecord &R, + const StringRef Super) { + if (R.isVerified()) + return; + SymbolContext SymCtx; + SymCtx.SymbolName = ObjCIVarRecord::createScopedName(Super, R.getName()); + SymCtx.Kind = EncodeKind::ObjectiveCInstanceVariable; + visitSymbolInDylib(R, SymCtx); +} + +void DylibVerifier::accumulateSrcLocForDylibSymbols() { + if (DSYMPath.empty()) + return; + + assert(DWARFCtx != nullptr && "Expected an initialized DWARFContext"); + if (DWARFCtx->ParsedDSYM) + return; + DWARFCtx->ParsedDSYM = true; + DWARFCtx->SourceLocs = + DylibReader::accumulateSourceLocFromDSYM(DSYMPath, Ctx.Target); +} + +void DylibVerifier::visitObjCInterface(const ObjCInterfaceRecord &R) { + if (R.isVerified()) + return; + SymbolContext SymCtx; + SymCtx.SymbolName = R.getName(); + SymCtx.ObjCIFKind = assignObjCIFSymbolKind(&R); + if (SymCtx.ObjCIFKind > ObjCIFSymbolKind::EHType) { + if (R.hasExceptionAttribute()) { + SymCtx.Kind = EncodeKind::ObjectiveCClassEHType; + visitSymbolInDylib(R, SymCtx); + } + SymCtx.Kind = EncodeKind::ObjectiveCClass; + visitSymbolInDylib(R, SymCtx); + } else { + SymCtx.Kind = R.hasExceptionAttribute() ? EncodeKind::ObjectiveCClassEHType + : EncodeKind::ObjectiveCClass; + visitSymbolInDylib(R, SymCtx); + } + + for (const ObjCIVarRecord *IV : R.getObjCIVars()) + visitObjCIVar(*IV, R.getName()); +} + +void DylibVerifier::visitObjCCategory(const ObjCCategoryRecord &R) { + for (const ObjCIVarRecord *IV : R.getObjCIVars()) + visitObjCIVar(*IV, R.getSuperClassName()); +} + +DylibVerifier::Result DylibVerifier::verifyRemainingSymbols() { + if (getState() == Result::NoVerify) + return Result::NoVerify; + assert(!Dylib.empty() && "No binary to verify against"); + + DWARFContext DWARFInfo; + DWARFCtx = &DWARFInfo; + Ctx.DiscoveredFirstError = false; + Ctx.PrintArch = true; + for (std::shared_ptr<RecordsSlice> Slice : Dylib) { + Ctx.Target = Slice->getTarget(); + Ctx.DylibSlice = Slice.get(); + Slice->visit(*this); + } + return getState(); +} + +} // namespace installapi +} // namespace clang diff --git a/clang/lib/InstallAPI/Frontend.cpp b/clang/lib/InstallAPI/Frontend.cpp index 707aeb17dc890626d6999cd56e2450d12a4c312c..e07ccb14e0b80a4e4f87ccf804387832e64ab669 100644 --- a/clang/lib/InstallAPI/Frontend.cpp +++ b/clang/lib/InstallAPI/Frontend.cpp @@ -16,41 +16,47 @@ using namespace llvm; using namespace llvm::MachO; namespace clang::installapi { - -GlobalRecord *FrontendRecordsSlice::addGlobal( +std::pair<GlobalRecord *, FrontendAttrs *> FrontendRecordsSlice::addGlobal( StringRef Name, RecordLinkage Linkage, GlobalRecord::Kind GV, const clang::AvailabilityInfo Avail, const Decl *D, const HeaderType Access, SymbolFlags Flags, bool Inlined) { - auto *GR = + GlobalRecord *GR = llvm::MachO::RecordsSlice::addGlobal(Name, Linkage, GV, Flags, Inlined); - FrontendRecords.insert({GR, FrontendAttrs{Avail, D, Access}}); - return GR; + auto Result = FrontendRecords.insert({GR, FrontendAttrs{Avail, D, Access}}); + return {GR, &(Result.first->second)}; } -ObjCInterfaceRecord *FrontendRecordsSlice::addObjCInterface( - StringRef Name, RecordLinkage Linkage, const clang::AvailabilityInfo Avail, - const Decl *D, HeaderType Access, bool IsEHType) { +std::pair<ObjCInterfaceRecord *, FrontendAttrs *> +FrontendRecordsSlice::addObjCInterface(StringRef Name, RecordLinkage Linkage, + const clang::AvailabilityInfo Avail, + const Decl *D, HeaderType Access, + bool IsEHType) { ObjCIFSymbolKind SymType = ObjCIFSymbolKind::Class | ObjCIFSymbolKind::MetaClass; if (IsEHType) SymType |= ObjCIFSymbolKind::EHType; - auto *ObjCR = + + ObjCInterfaceRecord *ObjCR = llvm::MachO::RecordsSlice::addObjCInterface(Name, Linkage, SymType); - FrontendRecords.insert({ObjCR, FrontendAttrs{Avail, D, Access}}); - return ObjCR; + auto Result = + FrontendRecords.insert({ObjCR, FrontendAttrs{Avail, D, Access}}); + return {ObjCR, &(Result.first->second)}; } -ObjCCategoryRecord *FrontendRecordsSlice::addObjCCategory( - StringRef ClassToExtend, StringRef CategoryName, - const clang::AvailabilityInfo Avail, const Decl *D, HeaderType Access) { - auto *ObjCR = +std::pair<ObjCCategoryRecord *, FrontendAttrs *> +FrontendRecordsSlice::addObjCCategory(StringRef ClassToExtend, + StringRef CategoryName, + const clang::AvailabilityInfo Avail, + const Decl *D, HeaderType Access) { + ObjCCategoryRecord *ObjCR = llvm::MachO::RecordsSlice::addObjCCategory(ClassToExtend, CategoryName); - FrontendRecords.insert({ObjCR, FrontendAttrs{Avail, D, Access}}); - return ObjCR; + auto Result = + FrontendRecords.insert({ObjCR, FrontendAttrs{Avail, D, Access}}); + return {ObjCR, &(Result.first->second)}; } -ObjCIVarRecord *FrontendRecordsSlice::addObjCIVar( +std::pair<ObjCIVarRecord *, FrontendAttrs *> FrontendRecordsSlice::addObjCIVar( ObjCContainerRecord *Container, StringRef IvarName, RecordLinkage Linkage, const clang::AvailabilityInfo Avail, const Decl *D, HeaderType Access, const clang::ObjCIvarDecl::AccessControl AC) { @@ -59,11 +65,12 @@ ObjCIVarRecord *FrontendRecordsSlice::addObjCIVar( if ((Linkage == RecordLinkage::Exported) && ((AC == ObjCIvarDecl::Private) || (AC == ObjCIvarDecl::Package))) Linkage = RecordLinkage::Internal; - auto *ObjCR = + ObjCIVarRecord *ObjCR = llvm::MachO::RecordsSlice::addObjCIVar(Container, IvarName, Linkage); - FrontendRecords.insert({ObjCR, FrontendAttrs{Avail, D, Access}}); + auto Result = + FrontendRecords.insert({ObjCR, FrontendAttrs{Avail, D, Access}}); - return nullptr; + return {ObjCR, &(Result.first->second)}; } std::optional<HeaderType> @@ -131,6 +138,8 @@ std::unique_ptr<MemoryBuffer> createInputBuffer(InstallAPIContext &Ctx) { SmallString<4096> Contents; raw_svector_ostream OS(Contents); for (const HeaderFile &H : Ctx.InputHeaders) { + if (H.isExcluded()) + continue; if (H.getType() != Ctx.Type) continue; if (Ctx.LangMode == Language::C || Ctx.LangMode == Language::CXX) diff --git a/clang/lib/InstallAPI/HeaderFile.cpp b/clang/lib/InstallAPI/HeaderFile.cpp index c2d8372741ee07e801dff5d4c3edd5f4963e88f8..0b7041ec8147eb95fc96ad6899d065aa5b6dd185 100644 --- a/clang/lib/InstallAPI/HeaderFile.cpp +++ b/clang/lib/InstallAPI/HeaderFile.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "clang/InstallAPI/HeaderFile.h" +#include "llvm/TextAPI/Utils.h" using namespace llvm; namespace clang::installapi { @@ -34,4 +35,54 @@ std::optional<std::string> createIncludeHeaderName(const StringRef FullPath) { return Matches[1].drop_front(Matches[1].rfind('/') + 1).str() + "/" + Matches[3].str(); } + +bool isHeaderFile(StringRef Path) { + return StringSwitch<bool>(sys::path::extension(Path)) + .Cases(".h", ".H", ".hh", ".hpp", ".hxx", true) + .Default(false); +} + +llvm::Expected<PathSeq> enumerateFiles(FileManager &FM, StringRef Directory) { + PathSeq Files; + std::error_code EC; + auto &FS = FM.getVirtualFileSystem(); + for (llvm::vfs::recursive_directory_iterator i(FS, Directory, EC), ie; + i != ie; i.increment(EC)) { + if (EC) + return errorCodeToError(EC); + + // Skip files that do not exist. This usually happens for broken symlinks. + if (FS.status(i->path()) == std::errc::no_such_file_or_directory) + continue; + + StringRef Path = i->path(); + if (isHeaderFile(Path)) + Files.emplace_back(Path); + } + + return Files; +} + +HeaderGlob::HeaderGlob(StringRef GlobString, Regex &&Rule, HeaderType Type) + : GlobString(GlobString), Rule(std::move(Rule)), Type(Type) {} + +bool HeaderGlob::match(const HeaderFile &Header) { + if (Header.getType() != Type) + return false; + + bool Match = Rule.match(Header.getPath()); + if (Match) + FoundMatch = true; + return Match; +} + +Expected<std::unique_ptr<HeaderGlob>> HeaderGlob::create(StringRef GlobString, + HeaderType Type) { + auto Rule = MachO::createRegexFromGlob(GlobString); + if (!Rule) + return Rule.takeError(); + + return std::make_unique<HeaderGlob>(GlobString, std::move(*Rule), Type); +} + } // namespace clang::installapi diff --git a/clang/lib/InstallAPI/Visitor.cpp b/clang/lib/InstallAPI/Visitor.cpp index b4ed5974a05704bbb54a139e8d181220555f5e9a..cf3aaa4c6ec93115834bd65e993b35852a0c49e7 100644 --- a/clang/lib/InstallAPI/Visitor.cpp +++ b/clang/lib/InstallAPI/Visitor.cpp @@ -11,6 +11,7 @@ #include "clang/AST/ParentMapContext.h" #include "clang/AST/VTableBuilder.h" #include "clang/Basic/Linkage.h" +#include "clang/InstallAPI/DylibVerifier.h" #include "clang/InstallAPI/FrontendRecords.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" @@ -156,7 +157,9 @@ void InstallAPIVisitor::recordObjCInstanceVariables( StringRef Name = IV->getName(); const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(IV); auto AC = IV->getCanonicalAccessControl(); - Ctx.Slice->addObjCIVar(Record, Name, Linkage, Avail, IV, *Access, AC); + auto [ObjCIVR, FA] = + Ctx.Slice->addObjCIVar(Record, Name, Linkage, Avail, IV, *Access, AC); + Ctx.Verifier->verify(ObjCIVR, FA, SuperClass); } } @@ -178,15 +181,16 @@ bool InstallAPIVisitor::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { (!D->getASTContext().getLangOpts().ObjCRuntime.isFragile() && hasObjCExceptionAttribute(D)); - ObjCInterfaceRecord *Class = + auto [Class, FA] = Ctx.Slice->addObjCInterface(Name, Linkage, Avail, D, *Access, IsEHType); + Ctx.Verifier->verify(Class, FA); // Get base class. StringRef SuperClassName; if (const auto *SuperClass = D->getSuperClass()) SuperClassName = SuperClass->getObjCRuntimeNameAsString(); - recordObjCInstanceVariables(D->getASTContext(), Class, SuperClassName, + recordObjCInstanceVariables(D->getASTContext(), Class, Class->getName(), D->ivars()); return true; } @@ -201,9 +205,10 @@ bool InstallAPIVisitor::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { const ObjCInterfaceDecl *InterfaceD = D->getClassInterface(); const StringRef InterfaceName = InterfaceD->getName(); - ObjCCategoryRecord *Category = Ctx.Slice->addObjCCategory( - InterfaceName, CategoryName, Avail, D, *Access); - recordObjCInstanceVariables(D->getASTContext(), Category, InterfaceName, + ObjCCategoryRecord *CategoryRecord = + Ctx.Slice->addObjCCategory(InterfaceName, CategoryName, Avail, D, *Access) + .first; + recordObjCInstanceVariables(D->getASTContext(), CategoryRecord, InterfaceName, D->ivars()); return true; } @@ -236,8 +241,10 @@ bool InstallAPIVisitor::VisitVarDecl(const VarDecl *D) { const bool WeakDef = D->hasAttr<WeakAttr>(); const bool ThreadLocal = D->getTLSKind() != VarDecl::TLS_None; const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D); - Ctx.Slice->addGlobal(getMangledName(D), Linkage, GlobalRecord::Kind::Variable, - Avail, D, *Access, getFlags(WeakDef, ThreadLocal)); + auto [GR, FA] = Ctx.Slice->addGlobal(getMangledName(D), Linkage, + GlobalRecord::Kind::Variable, Avail, D, + *Access, getFlags(WeakDef, ThreadLocal)); + Ctx.Verifier->verify(GR, FA); return true; } @@ -248,7 +255,7 @@ bool InstallAPIVisitor::VisitFunctionDecl(const FunctionDecl *D) { return true; // Skip methods in CXX RecordDecls. - for (auto P : D->getASTContext().getParents(*M)) { + for (const DynTypedNode &P : D->getASTContext().getParents(*M)) { if (P.get<CXXRecordDecl>()) return true; } @@ -287,8 +294,10 @@ bool InstallAPIVisitor::VisitFunctionDecl(const FunctionDecl *D) { const RecordLinkage Linkage = (Inlined || !isExported(D)) ? RecordLinkage::Internal : RecordLinkage::Exported; - Ctx.Slice->addGlobal(Name, Linkage, GlobalRecord::Kind::Function, Avail, D, - *Access, getFlags(WeakDef), Inlined); + auto [GR, FA] = + Ctx.Slice->addGlobal(Name, Linkage, GlobalRecord::Kind::Function, Avail, + D, *Access, getFlags(WeakDef), Inlined); + Ctx.Verifier->verify(GR, FA); return true; } @@ -478,9 +487,10 @@ void InstallAPIVisitor::emitVTableSymbols(const CXXRecordDecl *D, VTableLinkage == CXXLinkage::WeakODRLinkage) { const std::string Name = getMangledCXXVTableName(D); const bool WeakDef = VTableLinkage == CXXLinkage::WeakODRLinkage; - Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, - GlobalRecord::Kind::Variable, Avail, D, Access, - getFlags(WeakDef)); + auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Variable, Avail, + D, Access, getFlags(WeakDef)); + Ctx.Verifier->verify(GR, FA); if (!D->getDescribedClassTemplate() && !D->isInvalidDecl()) { VTableContextBase *VTable = D->getASTContext().getVTableContext(); auto AddThunk = [&](GlobalDecl GD) { @@ -491,9 +501,10 @@ void InstallAPIVisitor::emitVTableSymbols(const CXXRecordDecl *D, for (const auto &Thunk : *Thunks) { const std::string Name = getMangledCXXThunk(GD, Thunk); - Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, - GlobalRecord::Kind::Function, Avail, - GD.getDecl(), Access); + auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Function, + Avail, GD.getDecl(), Access); + Ctx.Verifier->verify(GR, FA); } }; @@ -519,12 +530,16 @@ void InstallAPIVisitor::emitVTableSymbols(const CXXRecordDecl *D, if (hasRTTI(D)) { std::string Name = getMangledCXXRTTI(D); - Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, - GlobalRecord::Kind::Variable, Avail, D, Access); + auto [GR, FA] = + Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Variable, Avail, D, Access); + Ctx.Verifier->verify(GR, FA); Name = getMangledCXXRTTIName(D); - Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, - GlobalRecord::Kind::Variable, Avail, D, Access); + auto [NamedGR, NamedFA] = + Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Variable, Avail, D, Access); + Ctx.Verifier->verify(NamedGR, NamedFA); } for (const auto &It : D->bases()) { @@ -615,15 +630,17 @@ bool InstallAPIVisitor::VisitCXXRecordDecl(const CXXRecordDecl *D) { continue; std::string Name = getMangledCtorDtor(M, Ctor_Base); - Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, - GlobalRecord::Kind::Function, Avail, D, *Access, - getFlags(WeakDef)); + auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Function, Avail, + D, *Access, getFlags(WeakDef)); + Ctx.Verifier->verify(GR, FA); if (!D->isAbstract()) { std::string Name = getMangledCtorDtor(M, Ctor_Complete); - Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, - GlobalRecord::Kind::Function, Avail, D, *Access, - getFlags(WeakDef)); + auto [GR, FA] = Ctx.Slice->addGlobal( + Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail, + D, *Access, getFlags(WeakDef)); + Ctx.Verifier->verify(GR, FA); } continue; @@ -635,20 +652,23 @@ bool InstallAPIVisitor::VisitCXXRecordDecl(const CXXRecordDecl *D) { continue; std::string Name = getMangledCtorDtor(M, Dtor_Base); - Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, - GlobalRecord::Kind::Function, Avail, D, *Access, - getFlags(WeakDef)); + auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Function, Avail, + D, *Access, getFlags(WeakDef)); + Ctx.Verifier->verify(GR, FA); Name = getMangledCtorDtor(M, Dtor_Complete); - Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, - GlobalRecord::Kind::Function, Avail, D, *Access, - getFlags(WeakDef)); + auto [CompleteGR, CompleteFA] = Ctx.Slice->addGlobal( + Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail, D, + *Access, getFlags(WeakDef)); + Ctx.Verifier->verify(CompleteGR, CompleteFA); if (Dtor->isVirtual()) { Name = getMangledCtorDtor(M, Dtor_Deleting); - Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, - GlobalRecord::Kind::Function, Avail, D, *Access, - getFlags(WeakDef)); + auto [VirtualGR, VirtualFA] = Ctx.Slice->addGlobal( + Name, RecordLinkage::Exported, GlobalRecord::Kind::Function, Avail, + D, *Access, getFlags(WeakDef)); + Ctx.Verifier->verify(VirtualGR, VirtualFA); } continue; @@ -661,9 +681,10 @@ bool InstallAPIVisitor::VisitCXXRecordDecl(const CXXRecordDecl *D) { continue; std::string Name = getMangledName(M); - Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, - GlobalRecord::Kind::Function, Avail, D, *Access, - getFlags(WeakDef)); + auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Function, Avail, M, + *Access, getFlags(WeakDef)); + Ctx.Verifier->verify(GR, FA); } if (auto *Templ = dyn_cast<ClassTemplateSpecializationDecl>(D)) { @@ -694,9 +715,10 @@ bool InstallAPIVisitor::VisitCXXRecordDecl(const CXXRecordDecl *D) { const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(Var); const bool WeakDef = Var->hasAttr<WeakAttr>() || KeepInlineAsWeak; - Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, - GlobalRecord::Kind::Variable, Avail, D, *Access, - getFlags(WeakDef)); + auto [GR, FA] = Ctx.Slice->addGlobal(Name, RecordLinkage::Exported, + GlobalRecord::Kind::Variable, Avail, D, + *Access, getFlags(WeakDef)); + Ctx.Verifier->verify(GR, FA); } return true; diff --git a/clang/lib/Interpreter/IncrementalExecutor.cpp b/clang/lib/Interpreter/IncrementalExecutor.cpp index 40bcef94797d43d7b847a51691d6c06fbbc2bd90..6f036107c14a9c51143323ad7f59766aaac1fbd8 100644 --- a/clang/lib/Interpreter/IncrementalExecutor.cpp +++ b/clang/lib/Interpreter/IncrementalExecutor.cpp @@ -20,6 +20,7 @@ #include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h" #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h" @@ -36,26 +37,28 @@ LLVM_ATTRIBUTE_USED void linkComponents() { namespace clang { +llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> +IncrementalExecutor::createDefaultJITBuilder( + llvm::orc::JITTargetMachineBuilder JTMB) { + auto JITBuilder = std::make_unique<llvm::orc::LLJITBuilder>(); + JITBuilder->setJITTargetMachineBuilder(std::move(JTMB)); + JITBuilder->setPrePlatformSetup([](llvm::orc::LLJIT &J) { + // Try to enable debugging of JIT'd code (only works with JITLink for + // ELF and MachO). + consumeError(llvm::orc::enableDebuggerSupport(J)); + return llvm::Error::success(); + }); + return std::move(JITBuilder); +} + IncrementalExecutor::IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC, - llvm::Error &Err, - const clang::TargetInfo &TI) + llvm::orc::LLJITBuilder &JITBuilder, + llvm::Error &Err) : TSCtx(TSC) { using namespace llvm::orc; llvm::ErrorAsOutParameter EAO(&Err); - auto JTMB = JITTargetMachineBuilder(TI.getTriple()); - JTMB.addFeatures(TI.getTargetOpts().Features); - LLJITBuilder Builder; - Builder.setJITTargetMachineBuilder(JTMB); - Builder.setPrePlatformSetup( - [](LLJIT &J) { - // Try to enable debugging of JIT'd code (only works with JITLink for - // ELF and MachO). - consumeError(enableDebuggerSupport(J)); - return llvm::Error::success(); - }); - - if (auto JitOrErr = Builder.create()) + if (auto JitOrErr = JITBuilder.create()) Jit = std::move(*JitOrErr); else { Err = JitOrErr.takeError(); diff --git a/clang/lib/Interpreter/IncrementalExecutor.h b/clang/lib/Interpreter/IncrementalExecutor.h index dd0a210a0614154f3d81db726de059375533d6d6..b4347209e14fe33b782bcdf036b2ead590726a1b 100644 --- a/clang/lib/Interpreter/IncrementalExecutor.h +++ b/clang/lib/Interpreter/IncrementalExecutor.h @@ -23,7 +23,9 @@ namespace llvm { class Error; namespace orc { +class JITTargetMachineBuilder; class LLJIT; +class LLJITBuilder; class ThreadSafeContext; } // namespace orc } // namespace llvm @@ -44,8 +46,8 @@ class IncrementalExecutor { public: enum SymbolNameKind { IRName, LinkerName }; - IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC, llvm::Error &Err, - const clang::TargetInfo &TI); + IncrementalExecutor(llvm::orc::ThreadSafeContext &TSC, + llvm::orc::LLJITBuilder &JITBuilder, llvm::Error &Err); ~IncrementalExecutor(); llvm::Error addModule(PartialTranslationUnit &PTU); @@ -56,6 +58,9 @@ public: getSymbolAddress(llvm::StringRef Name, SymbolNameKind NameKind) const; llvm::orc::LLJIT &GetExecutionEngine() { return *Jit; } + + static llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> + createDefaultJITBuilder(llvm::orc::JITTargetMachineBuilder JTMB); }; } // end namespace clang diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index 370bcbfee8b014c1dea231949bc899c407b1bcdb..5eec2a2fd6d1a69c76a3464997394b681cb133a6 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -375,16 +375,22 @@ void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) { TranslationUnitDecl *MostRecentTU = PTU.TUPart; TranslationUnitDecl *FirstTU = MostRecentTU->getFirstDecl(); if (StoredDeclsMap *Map = FirstTU->getPrimaryContext()->getLookupPtr()) { - for (auto I = Map->begin(); I != Map->end(); ++I) { - StoredDeclsList &List = I->second; + for (auto &&[Key, List] : *Map) { DeclContextLookupResult R = List.getLookupResult(); + std::vector<NamedDecl *> NamedDeclsToRemove; + bool RemoveAll = true; for (NamedDecl *D : R) { - if (D->getTranslationUnitDecl() == MostRecentTU) { + if (D->getTranslationUnitDecl() == MostRecentTU) + NamedDeclsToRemove.push_back(D); + else + RemoveAll = false; + } + if (LLVM_LIKELY(RemoveAll)) { + Map->erase(Key); + } else { + for (NamedDecl *D : NamedDeclsToRemove) List.remove(D); - } } - if (List.isNull()) - Map->erase(I); } } } diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 7fa52f2f15fc4951da35e5700deb54ecc4e6b64d..cf31456b6950ac51de7c220c65d7f374c63ea781 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -372,15 +372,35 @@ Interpreter::Parse(llvm::StringRef Code) { return IncrParser->Parse(Code); } +static llvm::Expected<llvm::orc::JITTargetMachineBuilder> +createJITTargetMachineBuilder(const std::string &TT) { + if (TT == llvm::sys::getProcessTriple()) + // This fails immediately if the target backend is not registered + return llvm::orc::JITTargetMachineBuilder::detectHost(); + + // If the target backend is not registered, LLJITBuilder::create() will fail + return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT)); +} + +llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> +Interpreter::CreateJITBuilder(CompilerInstance &CI) { + auto JTMB = createJITTargetMachineBuilder(CI.getTargetOpts().Triple); + if (!JTMB) + return JTMB.takeError(); + return IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB)); +} + llvm::Error Interpreter::CreateExecutor() { - const clang::TargetInfo &TI = - getCompilerInstance()->getASTContext().getTargetInfo(); if (IncrExecutor) return llvm::make_error<llvm::StringError>("Operation failed. " "Execution engine exists", std::error_code()); + llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> JB = + CreateJITBuilder(*getCompilerInstance()); + if (!JB) + return JB.takeError(); llvm::Error Err = llvm::Error::success(); - auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, Err, TI); + auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, **JB, Err); if (!Err) IncrExecutor = std::move(Executor); diff --git a/clang/lib/Interpreter/Value.cpp b/clang/lib/Interpreter/Value.cpp index 1d6b2da087e9fbe40d85111bddc3159199ebd94d..eb2ce9c9fd330200bf10453fff74fb8789fe7b42 100644 --- a/clang/lib/Interpreter/Value.cpp +++ b/clang/lib/Interpreter/Value.cpp @@ -1,4 +1,4 @@ -//===--- Interpreter.h - Incremental Compiation and Execution---*- C++ -*-===// +//===------------ Value.cpp - Definition of interpreter value -------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -22,8 +22,6 @@ #include <cstdint> #include <utility> -using namespace clang; - namespace { // This is internal buffer maintained by Value, used to hold temporaries. @@ -61,7 +59,7 @@ public: void Release() { assert(RefCnt > 0 && "Can't release if reference count is already zero"); if (--RefCnt == 0) { - // We hace a non-trivial dtor. + // We have a non-trivial dtor. if (Dtor && IsAlive()) { assert(Elements && "We at least should have 1 element in Value"); size_t Stride = AllocSize / Elements; @@ -97,6 +95,8 @@ private: }; } // namespace +namespace clang { + static Value::Kind ConvertQualTypeToKind(const ASTContext &Ctx, QualType QT) { if (Ctx.hasSameType(QT, Ctx.VoidTy)) return Value::K_Void; @@ -265,3 +265,5 @@ void Value::print(llvm::raw_ostream &Out) const { assert(OpaqueType != nullptr && "Can't print default Value"); Out << "Not implement yet.\n"; } + +} // namespace clang diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index afb2948f05ae5b4c30073f1b8dc9dad08b0c0be2..eed7eca2e73562da5d819410fcde0535b410668d 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -648,8 +648,7 @@ ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File) { UmbrellaModule = UmbrellaModule->Parent; if (UmbrellaModule->InferSubmodules) { - OptionalFileEntryRef UmbrellaModuleMap = - getModuleMapFileForUniquing(UmbrellaModule); + FileID UmbrellaModuleMap = getModuleMapFileIDForUniquing(UmbrellaModule); // Infer submodules for each of the directories we found between // the directory of the umbrella header and the directory where @@ -1021,7 +1020,7 @@ Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir, // If the framework has a parent path from which we're allowed to infer // a framework module, do so. - OptionalFileEntryRef ModuleMapFile; + FileID ModuleMapFID; if (!Parent) { // Determine whether we're allowed to infer a module map. bool canInfer = false; @@ -1060,7 +1059,7 @@ Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir, Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive; Attrs.NoUndeclaredIncludes |= inferred->second.Attrs.NoUndeclaredIncludes; - ModuleMapFile = inferred->second.ModuleMapFile; + ModuleMapFID = inferred->second.ModuleMapFID; } } } @@ -1069,7 +1068,7 @@ Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir, if (!canInfer) return nullptr; } else { - ModuleMapFile = getModuleMapFileForUniquing(Parent); + ModuleMapFID = getModuleMapFileIDForUniquing(Parent); } // Look for an umbrella header. @@ -1086,7 +1085,7 @@ Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir, Module *Result = new Module(ModuleName, SourceLocation(), Parent, /*IsFramework=*/true, /*IsExplicit=*/false, NumCreatedModules++); - InferredModuleAllowedBy[Result] = ModuleMapFile; + InferredModuleAllowedBy[Result] = ModuleMapFID; Result->IsInferred = true; if (!Parent) { if (LangOpts.CurrentModule == ModuleName) @@ -1307,28 +1306,34 @@ void ModuleMap::addHeader(Module *Mod, Module::Header Header, Cb->moduleMapAddHeader(Header.Entry.getName()); } -OptionalFileEntryRef -ModuleMap::getContainingModuleMapFile(const Module *Module) const { +FileID ModuleMap::getContainingModuleMapFileID(const Module *Module) const { if (Module->DefinitionLoc.isInvalid()) - return std::nullopt; + return {}; - return SourceMgr.getFileEntryRefForID( - SourceMgr.getFileID(Module->DefinitionLoc)); + return SourceMgr.getFileID(Module->DefinitionLoc); } OptionalFileEntryRef -ModuleMap::getModuleMapFileForUniquing(const Module *M) const { +ModuleMap::getContainingModuleMapFile(const Module *Module) const { + return SourceMgr.getFileEntryRefForID(getContainingModuleMapFileID(Module)); +} + +FileID ModuleMap::getModuleMapFileIDForUniquing(const Module *M) const { if (M->IsInferred) { assert(InferredModuleAllowedBy.count(M) && "missing inferred module map"); return InferredModuleAllowedBy.find(M)->second; } - return getContainingModuleMapFile(M); + return getContainingModuleMapFileID(M); +} + +OptionalFileEntryRef +ModuleMap::getModuleMapFileForUniquing(const Module *M) const { + return SourceMgr.getFileEntryRefForID(getModuleMapFileIDForUniquing(M)); } -void ModuleMap::setInferredModuleAllowedBy(Module *M, - OptionalFileEntryRef ModMap) { +void ModuleMap::setInferredModuleAllowedBy(Module *M, FileID ModMapFID) { assert(M->IsInferred && "module not inferred"); - InferredModuleAllowedBy[M] = ModMap; + InferredModuleAllowedBy[M] = ModMapFID; } std::error_code @@ -1517,7 +1522,7 @@ namespace clang { ModuleMap ⤅ /// The current module map file. - FileEntryRef ModuleMapFile; + FileID ModuleMapFID; /// Source location of most recent parsed module declaration SourceLocation CurrModuleDeclLoc; @@ -1585,13 +1590,12 @@ namespace clang { bool parseOptionalAttributes(Attributes &Attrs); public: - explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, - const TargetInfo *Target, DiagnosticsEngine &Diags, - ModuleMap &Map, FileEntryRef ModuleMapFile, - DirectoryEntryRef Directory, bool IsSystem) + ModuleMapParser(Lexer &L, SourceManager &SourceMgr, + const TargetInfo *Target, DiagnosticsEngine &Diags, + ModuleMap &Map, FileID ModuleMapFID, + DirectoryEntryRef Directory, bool IsSystem) : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), - ModuleMapFile(ModuleMapFile), Directory(Directory), - IsSystem(IsSystem) { + ModuleMapFID(ModuleMapFID), Directory(Directory), IsSystem(IsSystem) { Tok.clear(); consumeToken(); } @@ -2011,11 +2015,13 @@ void ModuleMapParser::parseModuleDecl() { } if (TopLevelModule && - ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) { - assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) && + ModuleMapFID != Map.getContainingModuleMapFileID(TopLevelModule)) { + assert(ModuleMapFID != + Map.getModuleMapFileIDForUniquing(TopLevelModule) && "submodule defined in same file as 'module *' that allowed its " "top-level module"); - Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile); + Map.addAdditionalModuleMapFile( + TopLevelModule, *SourceMgr.getFileEntryRefForID(ModuleMapFID)); } } @@ -2120,7 +2126,8 @@ void ModuleMapParser::parseModuleDecl() { ActiveModule->NoUndeclaredIncludes = true; ActiveModule->Directory = Directory; - StringRef MapFileName(ModuleMapFile.getName()); + StringRef MapFileName( + SourceMgr.getFileEntryRefForID(ModuleMapFID)->getName()); if (MapFileName.ends_with("module.private.modulemap") || MapFileName.ends_with("module_private.map")) { ActiveModule->ModuleMapIsPrivate = true; @@ -2498,9 +2505,12 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, } bool NeedsFramework = false; - // Don't add the top level headers to the builtin modules if the builtin headers - // belong to the system modules. - if (!Map.LangOpts.BuiltinHeadersInSystemModules || ActiveModule->isSubModule() || !isBuiltInModuleName(ActiveModule->Name)) + // Don't add headers to the builtin modules if the builtin headers belong to + // the system modules, with the exception of __stddef_max_align_t.h which + // always had its own module. + if (!Map.LangOpts.BuiltinHeadersInSystemModules || + !isBuiltInModuleName(ActiveModule->getTopLevelModuleName()) || + ActiveModule->fullModuleNameIs({"_Builtin_stddef", "max_align_t"})) Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework); if (NeedsFramework) @@ -2903,7 +2913,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { // We'll be inferring framework modules for this directory. Map.InferredDirectories[Directory].InferModules = true; Map.InferredDirectories[Directory].Attrs = Attrs; - Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile; + Map.InferredDirectories[Directory].ModuleMapFID = ModuleMapFID; // FIXME: Handle the 'framework' keyword. } @@ -3136,8 +3146,7 @@ bool ModuleMap::parseModuleMapFile(FileEntryRef File, bool IsSystem, Buffer->getBufferStart() + (Offset ? *Offset : 0), Buffer->getBufferEnd()); SourceLocation Start = L.getSourceLocation(); - ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir, - IsSystem); + ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, ID, Dir, IsSystem); bool Result = Parser.parseModuleMapFile(); ParsedModuleMap[File] = Result; diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp index 3b1b6df1dbae4e6a8b6d09af637dadda150d3f05..a0cc2b516574c197ea3d2e1eaa0ab993c52a01f5 100644 --- a/clang/lib/Lex/PPLexerChange.cpp +++ b/clang/lib/Lex/PPLexerChange.cpp @@ -93,16 +93,10 @@ bool Preprocessor::EnterSourceFile(FileID FID, ConstSearchDirIterator CurDir, } Lexer *TheLexer = new Lexer(FID, *InputFile, *this, IsFirstIncludeOfFile); - if (getPreprocessorOpts().DependencyDirectivesForFile && - FID != PredefinesFileID) { - if (OptionalFileEntryRef File = SourceMgr.getFileEntryRefForID(FID)) { - if (std::optional<ArrayRef<dependency_directives_scan::Directive>> - DepDirectives = - getPreprocessorOpts().DependencyDirectivesForFile(*File)) { + if (DependencyDirectivesForFile && FID != PredefinesFileID) + if (OptionalFileEntryRef File = SourceMgr.getFileEntryRefForID(FID)) + if (auto DepDirectives = DependencyDirectivesForFile(*File)) TheLexer->DepDirectives = *DepDirectives; - } - } - } EnterSourceFileWithLexer(TheLexer, CurDir); return false; diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 3017461dc66e86473dd46f23320040248d43ce49..516269c0c6013e965e657713ef53ee2ce5dc2eff 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -993,11 +993,20 @@ MacroArgs *Preprocessor::ReadMacroCallArgumentList(Token &MacroName, // If the macro contains the comma pasting extension, the diagnostic // is suppressed; we know we'll get another diagnostic later. if (!MI->hasCommaPasting()) { - // C++20 allows this construct, but standards before C++20 and all C - // standards do not allow the construct (we allow it as an extension). - Diag(Tok, getLangOpts().CPlusPlus20 - ? diag::warn_cxx17_compat_missing_varargs_arg - : diag::ext_missing_varargs_arg); + // C++20 [cpp.replace]p15, C23 6.10.5p12 + // + // C++20 and C23 allow this construct, but standards before that + // do not (we allow it as an extension). + unsigned ID; + if (getLangOpts().CPlusPlus20) + ID = diag::warn_cxx17_compat_missing_varargs_arg; + else if (getLangOpts().CPlusPlus) + ID = diag::ext_cxx_missing_varargs_arg; + else if (getLangOpts().C23) + ID = diag::warn_c17_compat_missing_varargs_arg; + else + ID = diag::ext_c_missing_varargs_arg; + Diag(Tok, ID); Diag(MI->getDefinitionLoc(), diag::note_macro_here) << MacroName.getIdentifierInfo(); } diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index dd179414a14191e814779047d74c794e2ab1f844..0aa14b0510746b9378b4a82d540b4751e78e4422 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -629,6 +629,10 @@ void Parser::ParseGNUAttributeArgs( ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc, Form); return; + } else if (AttrKind == ParsedAttr::AT_CountedBy) { + ParseBoundsAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc, + Form); + return; } // These may refer to the function arguments, but need to be parsed early to @@ -3250,6 +3254,54 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs, } } +/// Bounds attributes (e.g., counted_by): +/// AttrName '(' expression ')' +void Parser::ParseBoundsAttribute(IdentifierInfo &AttrName, + SourceLocation AttrNameLoc, + ParsedAttributes &Attrs, + IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, + ParsedAttr::Form Form) { + assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); + + BalancedDelimiterTracker Parens(*this, tok::l_paren); + Parens.consumeOpen(); + + if (Tok.is(tok::r_paren)) { + Diag(Tok.getLocation(), diag::err_argument_required_after_attribute); + Parens.consumeClose(); + return; + } + + ArgsVector ArgExprs; + // Don't evaluate argument when the attribute is ignored. + using ExpressionKind = + Sema::ExpressionEvaluationContextRecord::ExpressionKind; + EnterExpressionEvaluationContext EC( + Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, nullptr, + ExpressionKind::EK_BoundsAttrArgument); + + ExprResult ArgExpr( + Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression())); + + if (ArgExpr.isInvalid()) { + Parens.skipToEnd(); + return; + } + + ArgExprs.push_back(ArgExpr.get()); + Parens.consumeClose(); + + ASTContext &Ctx = Actions.getASTContext(); + + ArgExprs.push_back(IntegerLiteral::Create( + Ctx, llvm::APInt(Ctx.getTypeSize(Ctx.getSizeType()), 0), + Ctx.getSizeType(), SourceLocation())); + + Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, Parens.getCloseLocation()), + ScopeName, ScopeLoc, ArgExprs.data(), ArgExprs.size(), Form); +} + ExprResult Parser::ParseExtIntegerArgument() { assert(Tok.isOneOf(tok::kw__ExtInt, tok::kw__BitInt) && "Not an extended int type"); @@ -4679,6 +4731,39 @@ void Parser::ParseDeclarationSpecifiers( } } +static void DiagnoseCountAttributedTypeInUnnamedAnon(ParsingDeclSpec &DS, + Parser &P) { + + if (DS.getTypeSpecType() != DeclSpec::TST_struct) + return; + + auto *RD = dyn_cast<RecordDecl>(DS.getRepAsDecl()); + // We're only interested in unnamed, non-anonymous struct + if (!RD || !RD->getName().empty() || RD->isAnonymousStructOrUnion()) + return; + + for (auto *I : RD->decls()) { + auto *VD = dyn_cast<ValueDecl>(I); + if (!VD) + continue; + + auto *CAT = VD->getType()->getAs<CountAttributedType>(); + if (!CAT) + continue; + + for (const auto &DD : CAT->dependent_decls()) { + if (!RD->containsDecl(DD.getDecl())) { + P.Diag(VD->getBeginLoc(), + diag::err_flexible_array_count_not_in_same_struct) + << DD.getDecl(); + P.Diag(DD.getDecl()->getBeginLoc(), + diag::note_flexible_array_counted_by_attr_field) + << DD.getDecl(); + } + } + } +} + /// ParseStructDeclaration - Parse a struct declaration without the terminating /// semicolon. /// @@ -4759,6 +4844,11 @@ void Parser::ParseStructDeclaration( } else DeclaratorInfo.D.SetIdentifier(nullptr, Tok.getLocation()); + // Here, we now know that the unnamed struct is not an anonymous struct. + // Report an error if a counted_by attribute refers to a field in a + // different named struct. + DiagnoseCountAttributedTypeInUnnamedAnon(DS, *this); + if (TryConsumeToken(tok::colon)) { ExprResult Res(ParseConstantExpression()); if (Res.isInvalid()) diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 77d2382ea6d907ae94d1caeefb7b0d0e8756331d..861a25dc5103c129c82ee5b2e11b1d57a168300d 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -140,6 +140,14 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, SkipUntil(tok::semi); return nullptr; } + if (!ExtraNSs.empty()) { + Diag(ExtraNSs.front().NamespaceLoc, + diag::err_unexpected_qualified_namespace_alias) + << SourceRange(ExtraNSs.front().NamespaceLoc, + ExtraNSs.back().IdentLoc); + SkipUntil(tok::semi); + return nullptr; + } if (attrLoc.isValid()) Diag(attrLoc, diag::err_unexpected_namespace_attributes_alias); if (InlineLoc.isValid()) @@ -1494,6 +1502,15 @@ void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) { } } +void Parser::ParseNullabilityClassAttributes(ParsedAttributes &attrs) { + while (Tok.is(tok::kw__Nullable)) { + IdentifierInfo *AttrName = Tok.getIdentifierInfo(); + auto Kind = Tok.getKind(); + SourceLocation AttrNameLoc = ConsumeToken(); + attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, Kind); + } +} + /// Determine whether the following tokens are valid after a type-specifier /// which could be a standalone declaration. This will conservatively return /// true if there's any doubt, and is appropriate for insert-';' fixits. @@ -1675,15 +1692,21 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, ParsedAttributes attrs(AttrFactory); // If attributes exist after tag, parse them. - MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs); - - // Parse inheritance specifiers. - if (Tok.isOneOf(tok::kw___single_inheritance, tok::kw___multiple_inheritance, - tok::kw___virtual_inheritance)) - ParseMicrosoftInheritanceClassAttributes(attrs); - - // Allow attributes to precede or succeed the inheritance specifiers. - MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs); + for (;;) { + MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs); + // Parse inheritance specifiers. + if (Tok.isOneOf(tok::kw___single_inheritance, + tok::kw___multiple_inheritance, + tok::kw___virtual_inheritance)) { + ParseMicrosoftInheritanceClassAttributes(attrs); + continue; + } + if (Tok.is(tok::kw__Nullable)) { + ParseNullabilityClassAttributes(attrs); + continue; + } + break; + } // Source location used by FIXIT to insert misplaced // C++11 attributes diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 88c3a1469e8ed44e9bb7622cf1c64f6fe1aa65f7..ae23cb432c43913b3d26cf663df93d7eb0eb8b1e 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1823,7 +1823,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, } goto ExpectedExpression; case tok::l_square: - if (getLangOpts().CPlusPlus11) { + if (getLangOpts().CPlusPlus) { if (getLangOpts().ObjC) { // C++11 lambda expressions and Objective-C message sends both start with a // square bracket. There are three possibilities here: diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 9471f6f725efb17dde13f4c1c42b1365a13777ce..73c85c585baae4f42dd52e75400af6fee40f1d6a 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -806,9 +806,8 @@ ExprResult Parser::ParseLambdaExpression() { /// /// If we are not looking at a lambda expression, returns ExprError(). ExprResult Parser::TryParseLambdaExpression() { - assert(getLangOpts().CPlusPlus11 - && Tok.is(tok::l_square) - && "Not at the start of a possible lambda expression."); + assert(getLangOpts().CPlusPlus && Tok.is(tok::l_square) && + "Not at the start of a possible lambda expression."); const Token Next = NextToken(); if (Next.is(tok::eof)) // Nothing else to lookup here... @@ -1326,7 +1325,9 @@ static void DiagnoseStaticSpecifierRestrictions(Parser &P, ExprResult Parser::ParseLambdaExpressionAfterIntroducer( LambdaIntroducer &Intro) { SourceLocation LambdaBeginLoc = Intro.Range.getBegin(); - Diag(LambdaBeginLoc, diag::warn_cxx98_compat_lambda); + Diag(LambdaBeginLoc, getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_lambda + : diag::ext_lambda); PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), LambdaBeginLoc, "lambda expression parsing"); diff --git a/clang/lib/Parse/ParseInit.cpp b/clang/lib/Parse/ParseInit.cpp index 637f21176792b6b70cd6280bcdfb0dbc523aa887..423497bfcb6621ae25b402d104d027923875df97 100644 --- a/clang/lib/Parse/ParseInit.cpp +++ b/clang/lib/Parse/ParseInit.cpp @@ -35,7 +35,7 @@ bool Parser::MayBeDesignationStart() { return true; case tok::l_square: { // designator: array-designator - if (!PP.getLangOpts().CPlusPlus11) + if (!PP.getLangOpts().CPlusPlus) return true; // C++11 lambda expressions and C99 designators can be ambiguous all the diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index 50e3c39f60919b8d0d7a60c241f9a9f4f1d923a5..07dd2ba0106a4e209debe366879156a50a4b8f17 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -14,6 +14,7 @@ #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" +#include "clang/Sema/SemaOpenACC.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" @@ -777,7 +778,7 @@ bool Parser::ParseOpenACCClause(OpenACCDirectiveKind DirKind) { SourceLocation ClauseLoc = ConsumeToken(); bool Result = ParseOpenACCClauseParams(DirKind, Kind); - getActions().ActOnOpenACCClause(Kind, ClauseLoc); + getActions().OpenACC().ActOnClause(Kind, ClauseLoc); return Result; } @@ -1151,7 +1152,7 @@ Parser::OpenACCDirectiveParseInfo Parser::ParseOpenACCDirective() { SourceLocation StartLoc = getCurToken().getLocation(); OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(*this); - getActions().ActOnOpenACCConstruct(DirKind, StartLoc); + getActions().OpenACC().ActOnConstruct(DirKind, StartLoc); // Once we've parsed the construct/directive name, some have additional // specifiers that need to be taken care of. Atomic has an 'atomic-clause' @@ -1223,12 +1224,12 @@ Parser::DeclGroupPtrTy Parser::ParseOpenACCDirectiveDecl() { OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective(); - if (getActions().ActOnStartOpenACCDeclDirective(DirInfo.DirKind, - DirInfo.StartLoc)) + if (getActions().OpenACC().ActOnStartDeclDirective(DirInfo.DirKind, + DirInfo.StartLoc)) return nullptr; // TODO OpenACC: Do whatever decl parsing is required here. - return DeclGroupPtrTy::make(getActions().ActOnEndOpenACCDeclDirective()); + return DeclGroupPtrTy::make(getActions().OpenACC().ActOnEndDeclDirective()); } // Parse OpenACC Directive on a Statement. @@ -1239,8 +1240,8 @@ StmtResult Parser::ParseOpenACCDirectiveStmt() { ConsumeAnnotationToken(); OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective(); - if (getActions().ActOnStartOpenACCStmtDirective(DirInfo.DirKind, - DirInfo.StartLoc)) + if (getActions().OpenACC().ActOnStartStmtDirective(DirInfo.DirKind, + DirInfo.StartLoc)) return StmtError(); StmtResult AssocStmt; @@ -1249,10 +1250,10 @@ StmtResult Parser::ParseOpenACCDirectiveStmt() { ParsingOpenACCDirectiveRAII DirScope(*this, /*Value=*/false); ParseScope ACCScope(this, getOpenACCScopeFlags(DirInfo.DirKind)); - AssocStmt = getActions().ActOnOpenACCAssociatedStmt(DirInfo.DirKind, - ParseStatement()); + AssocStmt = getActions().OpenACC().ActOnAssociatedStmt(DirInfo.DirKind, + ParseStatement()); } - return getActions().ActOnEndOpenACCStmtDirective( + return getActions().OpenACC().ActOnEndStmtDirective( DirInfo.DirKind, DirInfo.StartLoc, DirInfo.EndLoc, AssocStmt); } diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 730ac1a0fee5cc9f151759cac31706869983760c..0f692e2146a4901df7411ab11bfefa2746959fce 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -844,6 +844,11 @@ void Parser::HandlePragmaFPContract() { FPC = LangOptions::FPM_Off; break; case tok::OOS_DEFAULT: + // According to ISO C99 standard chapter 7.3.4, the default value + // for the pragma is ``off'. '-fcomplex-arithmetic=basic', + // '-fcx-limited-range', '-fcx-fortran-rules' and + // '-fcomplex-arithmetic=improved' control the default value of these + // pragmas. FPC = getLangOpts().getDefaultFPContractMode(); break; } @@ -909,15 +914,15 @@ void Parser::HandlePragmaCXLimitedRange() { LangOptions::ComplexRangeKind Range; switch (OOS) { case tok::OOS_ON: - Range = LangOptions::CX_Limited; + Range = LangOptions::CX_Basic; break; case tok::OOS_OFF: Range = LangOptions::CX_Full; break; case tok::OOS_DEFAULT: // According to ISO C99 standard chapter 7.3.4, the default value - // for the pragma is ``off'. -fcx-limited-range and -fcx-fortran-rules - // control the default value of these pragmas. + // for the pragma is ``off'. -fcomplex-arithmetic controls the default value + // of these pragmas. Range = getLangOpts().getComplexRange(); break; } diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 1701d153bd0ecaab8273c4933a1067924cbee4d1..cc0e41ed221c4f1d0058ea30a685e5ad01045824 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -685,7 +685,7 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result, // FIXME: We need a better way to disambiguate C++ clang modules and // standard C++ modules. if (!getLangOpts().CPlusPlusModules || !Mod->isHeaderUnit()) - Actions.ActOnModuleInclude(Loc, Mod); + Actions.ActOnAnnotModuleInclude(Loc, Mod); else { DeclResult Import = Actions.ActOnModuleImport(Loc, SourceLocation(), Loc, Mod); @@ -697,15 +697,17 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result, } case tok::annot_module_begin: - Actions.ActOnModuleBegin(Tok.getLocation(), reinterpret_cast<Module *>( - Tok.getAnnotationValue())); + Actions.ActOnAnnotModuleBegin( + Tok.getLocation(), + reinterpret_cast<Module *>(Tok.getAnnotationValue())); ConsumeAnnotationToken(); ImportState = Sema::ModuleImportState::NotACXX20Module; return false; case tok::annot_module_end: - Actions.ActOnModuleEnd(Tok.getLocation(), reinterpret_cast<Module *>( - Tok.getAnnotationValue())); + Actions.ActOnAnnotModuleEnd( + Tok.getLocation(), + reinterpret_cast<Module *>(Tok.getAnnotationValue())); ConsumeAnnotationToken(); ImportState = Sema::ModuleImportState::NotACXX20Module; return false; @@ -2708,9 +2710,9 @@ bool Parser::parseMisplacedModuleImport() { // happens. if (MisplacedModuleBeginCount) { --MisplacedModuleBeginCount; - Actions.ActOnModuleEnd(Tok.getLocation(), - reinterpret_cast<Module *>( - Tok.getAnnotationValue())); + Actions.ActOnAnnotModuleEnd( + Tok.getLocation(), + reinterpret_cast<Module *>(Tok.getAnnotationValue())); ConsumeAnnotationToken(); continue; } @@ -2720,18 +2722,18 @@ bool Parser::parseMisplacedModuleImport() { return true; case tok::annot_module_begin: // Recover by entering the module (Sema will diagnose). - Actions.ActOnModuleBegin(Tok.getLocation(), - reinterpret_cast<Module *>( - Tok.getAnnotationValue())); + Actions.ActOnAnnotModuleBegin( + Tok.getLocation(), + reinterpret_cast<Module *>(Tok.getAnnotationValue())); ConsumeAnnotationToken(); ++MisplacedModuleBeginCount; continue; case tok::annot_module_include: // Module import found where it should not be, for instance, inside a // namespace. Recover by importing the module. - Actions.ActOnModuleInclude(Tok.getLocation(), - reinterpret_cast<Module *>( - Tok.getAnnotationValue())); + Actions.ActOnAnnotModuleInclude( + Tok.getLocation(), + reinterpret_cast<Module *>(Tok.getAnnotationValue())); ConsumeAnnotationToken(); // If there is another module import, process it. continue; diff --git a/clang/lib/Sema/JumpDiagnostics.cpp b/clang/lib/Sema/JumpDiagnostics.cpp index 6722878883be8ed2c27dd023d65fea3f68df747c..ce6211c23218bbd2024bad7aa5dcb690e005ebeb 100644 --- a/clang/lib/Sema/JumpDiagnostics.cpp +++ b/clang/lib/Sema/JumpDiagnostics.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtOpenACC.h" #include "clang/AST/StmtOpenMP.h" #include "clang/Basic/SourceLocation.h" #include "clang/Sema/SemaInternal.h" diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 720d5fd5f0428dda84bc7c90008debb5e0c7ba89..b7e4fc0ac9b5b277f8f0bc1ca84c5aa0d2519254 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -43,6 +43,7 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaConsumer.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaOpenACC.h" #include "clang/Sema/TemplateDeduction.h" #include "clang/Sema/TemplateInstCallback.h" #include "clang/Sema/TypoCorrection.h" @@ -135,6 +136,7 @@ namespace sema { class SemaPPCallbacks : public PPCallbacks { Sema *S = nullptr; llvm::SmallVector<SourceLocation, 8> IncludeStack; + llvm::SmallVector<llvm::TimeTraceProfilerEntry *, 8> ProfilerStack; public: void set(Sema &S) { this->S = &S; } @@ -153,8 +155,8 @@ public: if (IncludeLoc.isValid()) { if (llvm::timeTraceProfilerEnabled()) { OptionalFileEntryRef FE = SM.getFileEntryRefForID(SM.getFileID(Loc)); - llvm::timeTraceProfilerBegin("Source", FE ? FE->getName() - : StringRef("<unknown>")); + ProfilerStack.push_back(llvm::timeTraceAsyncProfilerBegin( + "Source", FE ? FE->getName() : StringRef("<unknown>"))); } IncludeStack.push_back(IncludeLoc); @@ -167,7 +169,7 @@ public: case ExitFile: if (!IncludeStack.empty()) { if (llvm::timeTraceProfilerEnabled()) - llvm::timeTraceProfilerEnd(); + llvm::timeTraceProfilerEnd(ProfilerStack.pop_back_val()); S->DiagnoseNonDefaultPragmaAlignPack( Sema::PragmaAlignPackDiagnoseKind::ChangedStateAtExit, @@ -195,7 +197,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, ThreadSafetyDeclCache(nullptr), LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), CurContext(nullptr), ExternalSource(nullptr), CurScope(nullptr), - Ident_super(nullptr), + Ident_super(nullptr), OpenACCPtr(std::make_unique<SemaOpenACC>(*this)), MSPointerToMemberRepresentationMethod( LangOpts.getMSPointerToMemberRepresentationMethod()), MSStructPragmaOn(false), VtorDispStack(LangOpts.getVtorDispMode()), @@ -652,6 +654,7 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, case CK_FunctionToPointerDecay: case CK_ToVoid: case CK_NonAtomicToAtomic: + case CK_HLSLArrayRValue: break; } } @@ -1207,26 +1210,35 @@ void Sema::ActOnEndOfTranslationUnit() { } // A global-module-fragment is only permitted within a module unit. - bool DiagnosedMissingModuleDeclaration = false; if (!ModuleScopes.empty() && ModuleScopes.back().Module->Kind == Module::ExplicitGlobalModuleFragment) { Diag(ModuleScopes.back().BeginLoc, diag::err_module_declaration_missing_after_global_module_introducer); - DiagnosedMissingModuleDeclaration = true; - } - - if (TUKind == TU_Module) { - // If we are building a module interface unit, we need to have seen the - // module declaration by now. - if (getLangOpts().getCompilingModule() == - LangOptions::CMK_ModuleInterface && - !isCurrentModulePurview() && !DiagnosedMissingModuleDeclaration) { - // FIXME: Make a better guess as to where to put the module declaration. - Diag(getSourceManager().getLocForStartOfFile( - getSourceManager().getMainFileID()), - diag::err_module_declaration_missing); - } + } + + // Now we can decide whether the modules we're building need an initializer. + if (Module *CurrentModule = getCurrentModule(); + CurrentModule && CurrentModule->isInterfaceOrPartition()) { + auto DoesModNeedInit = [this](Module *M) { + if (!getASTContext().getModuleInitializers(M).empty()) + return true; + for (auto [Exported, _] : M->Exports) + if (Exported->isNamedModuleInterfaceHasInit()) + return true; + for (Module *I : M->Imports) + if (I->isNamedModuleInterfaceHasInit()) + return true; + + return false; + }; + + CurrentModule->NamedModuleHasInit = + DoesModNeedInit(CurrentModule) || + llvm::any_of(CurrentModule->submodules(), + [&](auto *SubM) { return DoesModNeedInit(SubM); }); + } + if (TUKind == TU_ClangModule) { // If we are building a module, resolve all of the exported declarations // now. if (Module *CurrentModule = PP.getCurrentModule()) { @@ -1251,28 +1263,6 @@ void Sema::ActOnEndOfTranslationUnit() { } } - // Now we can decide whether the modules we're building need an initializer. - if (Module *CurrentModule = getCurrentModule(); - CurrentModule && CurrentModule->isInterfaceOrPartition()) { - auto DoesModNeedInit = [this](Module *M) { - if (!getASTContext().getModuleInitializers(M).empty()) - return true; - for (auto [Exported, _] : M->Exports) - if (Exported->isNamedModuleInterfaceHasInit()) - return true; - for (Module *I : M->Imports) - if (I->isNamedModuleInterfaceHasInit()) - return true; - - return false; - }; - - CurrentModule->NamedModuleHasInit = - DoesModNeedInit(CurrentModule) || - llvm::any_of(CurrentModule->submodules(), - [&](auto *SubM) { return DoesModNeedInit(SubM); }); - } - // Warnings emitted in ActOnEndOfTranslationUnit() should be emitted for // modules when they are built, not every time they are used. emitAndClearUnusedLocalTypedefWarnings(); @@ -1358,7 +1348,7 @@ void Sema::ActOnEndOfTranslationUnit() { // noise. Don't warn for a use from a module: either we should warn on all // file-scope declarations in modules or not at all, but whether the // declaration is used is immaterial. - if (!Diags.hasErrorOccurred() && TUKind != TU_Module) { + if (!Diags.hasErrorOccurred() && TUKind != TU_ClangModule) { // Output warning for unused file scoped decls. for (UnusedFileScopedDeclsType::iterator I = UnusedFileScopedDecls.begin(ExternalSource.get()), @@ -2077,8 +2067,11 @@ void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) { targetDiag(D->getLocation(), diag::note_defined_here, FD) << D; } - if (TI.hasRISCVVTypes() && Ty->isRVVSizelessBuiltinType()) - checkRVVTypeSupport(Ty, Loc, D); + if (TI.hasRISCVVTypes() && Ty->isRVVSizelessBuiltinType() && FD) { + llvm::StringMap<bool> CallerFeatureMap; + Context.getFunctionFeatureMap(CallerFeatureMap, FD); + checkRVVTypeSupport(Ty, Loc, D, CallerFeatureMap); + } // Don't allow SVE types in functions without a SVE target. if (Ty->isSVESizelessBuiltinType() && FD && FD->hasBody()) { @@ -2219,7 +2212,7 @@ static void checkEscapingByref(VarDecl *VD, Sema &S) { // block copy/destroy functions. Resolve it here. if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) if (CXXDestructorDecl *DD = RD->getDestructor()) { - auto *FPT = DD->getType()->getAs<FunctionProtoType>(); + auto *FPT = DD->getType()->castAs<FunctionProtoType>(); S.ResolveExceptionSpec(Loc, FPT); } } diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index 836c633e9d20421e4be008599f001e211f75984b..a3128306c664fe17ffa439ceda3dda798c2e2f50 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -52,49 +52,54 @@ static void applyNullability(Sema &S, Decl *D, NullabilityKind Nullability, if (!Metadata.IsActive) return; - auto IsModified = [&](Decl *D, QualType QT, - NullabilityKind Nullability) -> bool { + auto GetModified = + [&](Decl *D, QualType QT, + NullabilityKind Nullability) -> std::optional<QualType> { QualType Original = QT; S.CheckImplicitNullabilityTypeSpecifier(QT, Nullability, D->getLocation(), isa<ParmVarDecl>(D), /*OverrideExisting=*/true); - return QT.getTypePtr() != Original.getTypePtr(); + return (QT.getTypePtr() != Original.getTypePtr()) ? std::optional(QT) + : std::nullopt; }; if (auto Function = dyn_cast<FunctionDecl>(D)) { - if (IsModified(D, Function->getReturnType(), Nullability)) { - QualType FnType = Function->getType(); - Function->setType(FnType); + if (auto Modified = + GetModified(D, Function->getReturnType(), Nullability)) { + const FunctionType *FnType = Function->getType()->castAs<FunctionType>(); + if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(FnType)) + Function->setType(S.Context.getFunctionType( + *Modified, proto->getParamTypes(), proto->getExtProtoInfo())); + else + Function->setType( + S.Context.getFunctionNoProtoType(*Modified, FnType->getExtInfo())); } } else if (auto Method = dyn_cast<ObjCMethodDecl>(D)) { - QualType Type = Method->getReturnType(); - if (IsModified(D, Type, Nullability)) { - Method->setReturnType(Type); + if (auto Modified = GetModified(D, Method->getReturnType(), Nullability)) { + Method->setReturnType(*Modified); // Make it a context-sensitive keyword if we can. - if (!isIndirectPointerType(Type)) + if (!isIndirectPointerType(*Modified)) Method->setObjCDeclQualifier(Decl::ObjCDeclQualifier( Method->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability)); } } else if (auto Value = dyn_cast<ValueDecl>(D)) { - QualType Type = Value->getType(); - if (IsModified(D, Type, Nullability)) { - Value->setType(Type); + if (auto Modified = GetModified(D, Value->getType(), Nullability)) { + Value->setType(*Modified); // Make it a context-sensitive keyword if we can. if (auto Parm = dyn_cast<ParmVarDecl>(D)) { - if (Parm->isObjCMethodParameter() && !isIndirectPointerType(Type)) + if (Parm->isObjCMethodParameter() && !isIndirectPointerType(*Modified)) Parm->setObjCDeclQualifier(Decl::ObjCDeclQualifier( Parm->getObjCDeclQualifier() | Decl::OBJC_TQ_CSNullability)); } } } else if (auto Property = dyn_cast<ObjCPropertyDecl>(D)) { - QualType Type = Property->getType(); - if (IsModified(D, Type, Nullability)) { - Property->setType(Type, Property->getTypeSourceInfo()); + if (auto Modified = GetModified(D, Property->getType(), Nullability)) { + Property->setType(*Modified, Property->getTypeSourceInfo()); // Make it a property attribute if we can. - if (!isIndirectPointerType(Type)) + if (!isIndirectPointerType(*Modified)) Property->setPropertyAttributes( ObjCPropertyAttribute::kind_null_resettable); } diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index 0dcf42e489971344d516153c872a36c1df03e188..a5dd158808f26b4bed173943d9940f7f76602d10 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -215,6 +215,18 @@ void Sema::inferGslOwnerPointerAttribute(CXXRecordDecl *Record) { inferGslPointerAttribute(Record, Record); } +void Sema::inferNullableClassAttribute(CXXRecordDecl *CRD) { + static llvm::StringSet<> Nullable{ + "auto_ptr", "shared_ptr", "unique_ptr", "exception_ptr", + "coroutine_handle", "function", "move_only_function", + }; + + if (CRD->isInStdNamespace() && Nullable.count(CRD->getName()) && + !CRD->hasAttr<TypeNullableAttr>()) + for (Decl *Redecl : CRD->redecls()) + Redecl->addAttr(TypeNullableAttr::CreateImplicit(Context)); +} + void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, SourceLocation PragmaLoc) { PragmaMsStackAction Action = Sema::PSK_Reset; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index a5f42b630c3fa2459b7d6e360838597d22028186..3dcd18b3afc8b4f23175c7c0dde74bedb5d3bd00 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -27,6 +27,7 @@ #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" #include "clang/AST/FormatString.h" +#include "clang/AST/IgnoreExpr.h" #include "clang/AST/NSAPI.h" #include "clang/AST/NonTrivialTypeVisitor.h" #include "clang/AST/OperationKinds.h" @@ -1098,7 +1099,7 @@ static bool ProcessFormatStringLiteral(const Expr *FormatExpr, const ConstantArrayType *T = Context.getAsConstantArrayType(Format->getType()); assert(T && "String literal not of constant array type!"); - size_t TypeSize = T->getSize().getZExtValue(); + size_t TypeSize = T->getZExtSize(); // In case there's a null byte somewhere. StrLen = std::min(std::max(TypeSize, size_t(1)) - 1, FormatStrRef.find(0)); return true; @@ -1971,6 +1972,191 @@ static bool SemaOpenCLBuiltinToAddr(Sema &S, unsigned BuiltinID, return false; } +namespace { +enum PointerAuthOpKind { + PAO_Strip, + PAO_Sign, + PAO_Auth, + PAO_SignGeneric, + PAO_Discriminator, + PAO_BlendPointer, + PAO_BlendInteger +}; +} + +static bool checkPointerAuthEnabled(Sema &S, Expr *E) { + if (S.getLangOpts().PointerAuthIntrinsics) + return false; + + S.Diag(E->getExprLoc(), diag::err_ptrauth_disabled) << E->getSourceRange(); + return true; +} + +static bool checkPointerAuthKey(Sema &S, Expr *&Arg) { + // Convert it to type 'int'. + if (convertArgumentToType(S, Arg, S.Context.IntTy)) + return true; + + // Value-dependent expressions are okay; wait for template instantiation. + if (Arg->isValueDependent()) + return false; + + unsigned KeyValue; + return S.checkConstantPointerAuthKey(Arg, KeyValue); +} + +bool Sema::checkConstantPointerAuthKey(Expr *Arg, unsigned &Result) { + // Attempt to constant-evaluate the expression. + std::optional<llvm::APSInt> KeyValue = Arg->getIntegerConstantExpr(Context); + if (!KeyValue) { + Diag(Arg->getExprLoc(), diag::err_expr_not_ice) + << 0 << Arg->getSourceRange(); + return true; + } + + // Ask the target to validate the key parameter. + if (!Context.getTargetInfo().validatePointerAuthKey(*KeyValue)) { + llvm::SmallString<32> Value; + { + llvm::raw_svector_ostream Str(Value); + Str << *KeyValue; + } + + Diag(Arg->getExprLoc(), diag::err_ptrauth_invalid_key) + << Value << Arg->getSourceRange(); + return true; + } + + Result = KeyValue->getZExtValue(); + return false; +} + +static bool checkPointerAuthValue(Sema &S, Expr *&Arg, + PointerAuthOpKind OpKind) { + if (Arg->hasPlaceholderType()) { + ExprResult R = S.CheckPlaceholderExpr(Arg); + if (R.isInvalid()) + return true; + Arg = R.get(); + } + + auto AllowsPointer = [](PointerAuthOpKind OpKind) { + return OpKind != PAO_BlendInteger; + }; + auto AllowsInteger = [](PointerAuthOpKind OpKind) { + return OpKind == PAO_Discriminator || OpKind == PAO_BlendInteger || + OpKind == PAO_SignGeneric; + }; + + // Require the value to have the right range of type. + QualType ExpectedTy; + if (AllowsPointer(OpKind) && Arg->getType()->isPointerType()) { + ExpectedTy = Arg->getType().getUnqualifiedType(); + } else if (AllowsPointer(OpKind) && Arg->getType()->isNullPtrType()) { + ExpectedTy = S.Context.VoidPtrTy; + } else if (AllowsInteger(OpKind) && + Arg->getType()->isIntegralOrUnscopedEnumerationType()) { + ExpectedTy = S.Context.getUIntPtrType(); + + } else { + // Diagnose the failures. + S.Diag(Arg->getExprLoc(), diag::err_ptrauth_value_bad_type) + << unsigned(OpKind == PAO_Discriminator ? 1 + : OpKind == PAO_BlendPointer ? 2 + : OpKind == PAO_BlendInteger ? 3 + : 0) + << unsigned(AllowsInteger(OpKind) ? (AllowsPointer(OpKind) ? 2 : 1) : 0) + << Arg->getType() << Arg->getSourceRange(); + return true; + } + + // Convert to that type. This should just be an lvalue-to-rvalue + // conversion. + if (convertArgumentToType(S, Arg, ExpectedTy)) + return true; + + // Warn about null pointers for non-generic sign and auth operations. + if ((OpKind == PAO_Sign || OpKind == PAO_Auth) && + Arg->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNull)) { + S.Diag(Arg->getExprLoc(), OpKind == PAO_Sign + ? diag::warn_ptrauth_sign_null_pointer + : diag::warn_ptrauth_auth_null_pointer) + << Arg->getSourceRange(); + } + + return false; +} + +static ExprResult SemaPointerAuthStrip(Sema &S, CallExpr *Call) { + if (checkArgCount(S, Call, 2)) + return ExprError(); + if (checkPointerAuthEnabled(S, Call)) + return ExprError(); + if (checkPointerAuthValue(S, Call->getArgs()[0], PAO_Strip) || + checkPointerAuthKey(S, Call->getArgs()[1])) + return ExprError(); + + Call->setType(Call->getArgs()[0]->getType()); + return Call; +} + +static ExprResult SemaPointerAuthBlendDiscriminator(Sema &S, CallExpr *Call) { + if (checkArgCount(S, Call, 2)) + return ExprError(); + if (checkPointerAuthEnabled(S, Call)) + return ExprError(); + if (checkPointerAuthValue(S, Call->getArgs()[0], PAO_BlendPointer) || + checkPointerAuthValue(S, Call->getArgs()[1], PAO_BlendInteger)) + return ExprError(); + + Call->setType(S.Context.getUIntPtrType()); + return Call; +} + +static ExprResult SemaPointerAuthSignGenericData(Sema &S, CallExpr *Call) { + if (checkArgCount(S, Call, 2)) + return ExprError(); + if (checkPointerAuthEnabled(S, Call)) + return ExprError(); + if (checkPointerAuthValue(S, Call->getArgs()[0], PAO_SignGeneric) || + checkPointerAuthValue(S, Call->getArgs()[1], PAO_Discriminator)) + return ExprError(); + + Call->setType(S.Context.getUIntPtrType()); + return Call; +} + +static ExprResult SemaPointerAuthSignOrAuth(Sema &S, CallExpr *Call, + PointerAuthOpKind OpKind) { + if (checkArgCount(S, Call, 3)) + return ExprError(); + if (checkPointerAuthEnabled(S, Call)) + return ExprError(); + if (checkPointerAuthValue(S, Call->getArgs()[0], OpKind) || + checkPointerAuthKey(S, Call->getArgs()[1]) || + checkPointerAuthValue(S, Call->getArgs()[2], PAO_Discriminator)) + return ExprError(); + + Call->setType(Call->getArgs()[0]->getType()); + return Call; +} + +static ExprResult SemaPointerAuthAuthAndResign(Sema &S, CallExpr *Call) { + if (checkArgCount(S, Call, 5)) + return ExprError(); + if (checkPointerAuthEnabled(S, Call)) + return ExprError(); + if (checkPointerAuthValue(S, Call->getArgs()[0], PAO_Auth) || + checkPointerAuthKey(S, Call->getArgs()[1]) || + checkPointerAuthValue(S, Call->getArgs()[2], PAO_Discriminator) || + checkPointerAuthKey(S, Call->getArgs()[3]) || + checkPointerAuthValue(S, Call->getArgs()[4], PAO_Discriminator)) + return ExprError(); + + Call->setType(Call->getArgs()[0]->getType()); + return Call; +} + static ExprResult SemaBuiltinLaunder(Sema &S, CallExpr *TheCall) { if (checkArgCount(S, TheCall, 1)) return ExprError(); @@ -2214,6 +2400,48 @@ static bool SemaBuiltinPopcountg(Sema &S, CallExpr *TheCall) { return false; } +/// Checks that __builtin_{clzg,ctzg} was called with a first argument, which is +/// an unsigned integer, and an optional second argument, which is promoted to +/// an 'int'. +static bool SemaBuiltinCountZeroBitsGeneric(Sema &S, CallExpr *TheCall) { + if (checkArgCountRange(S, TheCall, 1, 2)) + return true; + + ExprResult Arg0Res = S.DefaultLvalueConversion(TheCall->getArg(0)); + if (Arg0Res.isInvalid()) + return true; + + Expr *Arg0 = Arg0Res.get(); + TheCall->setArg(0, Arg0); + + QualType Arg0Ty = Arg0->getType(); + + if (!Arg0Ty->isUnsignedIntegerType()) { + S.Diag(Arg0->getBeginLoc(), diag::err_builtin_invalid_arg_type) + << 1 << /*unsigned integer ty*/ 7 << Arg0Ty; + return true; + } + + if (TheCall->getNumArgs() > 1) { + ExprResult Arg1Res = S.UsualUnaryConversions(TheCall->getArg(1)); + if (Arg1Res.isInvalid()) + return true; + + Expr *Arg1 = Arg1Res.get(); + TheCall->setArg(1, Arg1); + + QualType Arg1Ty = Arg1->getType(); + + if (!Arg1Ty->isSpecificBuiltinType(BuiltinType::Int)) { + S.Diag(Arg1->getBeginLoc(), diag::err_builtin_invalid_arg_type) + << 2 << /*'int' ty*/ 8 << Arg1Ty; + return true; + } + } + + return false; +} + ExprResult Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, CallExpr *TheCall) { @@ -2683,6 +2911,18 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, } break; } + case Builtin::BI__builtin_ptrauth_strip: + return SemaPointerAuthStrip(*this, TheCall); + case Builtin::BI__builtin_ptrauth_blend_discriminator: + return SemaPointerAuthBlendDiscriminator(*this, TheCall); + case Builtin::BI__builtin_ptrauth_sign_unauthenticated: + return SemaPointerAuthSignOrAuth(*this, TheCall, PAO_Sign); + case Builtin::BI__builtin_ptrauth_auth: + return SemaPointerAuthSignOrAuth(*this, TheCall, PAO_Auth); + case Builtin::BI__builtin_ptrauth_sign_generic_data: + return SemaPointerAuthSignGenericData(*this, TheCall); + case Builtin::BI__builtin_ptrauth_auth_and_resign: + return SemaPointerAuthAuthAndResign(*this, TheCall); // OpenCL v2.0, s6.13.16 - Pipe functions case Builtin::BIread_pipe: case Builtin::BIwrite_pipe: @@ -2990,6 +3230,11 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, if (SemaBuiltinPopcountg(*this, TheCall)) return ExprError(); break; + case Builtin::BI__builtin_clzg: + case Builtin::BI__builtin_ctzg: + if (SemaBuiltinCountZeroBitsGeneric(*this, TheCall)) + return ExprError(); + break; } if (getLangOpts().HLSL && CheckHLSLBuiltinFunctionCall(BuiltinID, TheCall)) @@ -4992,6 +5237,7 @@ static bool isPPC_64Builtin(unsigned BuiltinID) { case PPC::BI__builtin_ppc_fetch_and_andlp: case PPC::BI__builtin_ppc_fetch_and_orlp: case PPC::BI__builtin_ppc_fetch_and_swaplp: + case PPC::BI__builtin_ppc_rldimi: return true; } return false; @@ -5093,8 +5339,10 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, case PPC::BI__builtin_ppc_rlwnm: return SemaValueIsRunOfOnes(TheCall, 2); case PPC::BI__builtin_ppc_rlwimi: + return SemaBuiltinConstantArgRange(TheCall, 2, 0, 31) || + SemaValueIsRunOfOnes(TheCall, 3); case PPC::BI__builtin_ppc_rldimi: - return SemaBuiltinConstantArg(TheCall, 2, Result) || + return SemaBuiltinConstantArgRange(TheCall, 2, 0, 63) || SemaValueIsRunOfOnes(TheCall, 3); case PPC::BI__builtin_ppc_addex: { if (SemaBuiltinConstantArgRange(TheCall, 2, 0, 3)) @@ -5233,10 +5481,6 @@ bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall) { TheCall->getArg(1)->getEndLoc()); retValue = true; } - - if (!retValue) - TheCall->setType(VecTyA->getElementType()); - return retValue; } } @@ -5250,11 +5494,12 @@ bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall) { return true; } -bool CheckAllArgsHaveFloatRepresentation(Sema *S, CallExpr *TheCall) { - QualType ExpectedType = S->Context.FloatTy; +bool CheckArgsTypesAreCorrect( + Sema *S, CallExpr *TheCall, QualType ExpectedType, + llvm::function_ref<bool(clang::QualType PassedType)> Check) { for (unsigned i = 0; i < TheCall->getNumArgs(); ++i) { QualType PassedType = TheCall->getArg(i)->getType(); - if (!PassedType->hasFloatingRepresentation()) { + if (Check(PassedType)) { if (auto *VecTyA = PassedType->getAs<VectorType>()) ExpectedType = S->Context.getVectorType( ExpectedType, VecTyA->getNumElements(), VecTyA->getVectorKind()); @@ -5267,6 +5512,53 @@ bool CheckAllArgsHaveFloatRepresentation(Sema *S, CallExpr *TheCall) { return false; } +bool CheckAllArgsHaveFloatRepresentation(Sema *S, CallExpr *TheCall) { + auto checkAllFloatTypes = [](clang::QualType PassedType) -> bool { + return !PassedType->hasFloatingRepresentation(); + }; + return CheckArgsTypesAreCorrect(S, TheCall, S->Context.FloatTy, + checkAllFloatTypes); +} + +bool CheckFloatOrHalfRepresentations(Sema *S, CallExpr *TheCall) { + auto checkFloatorHalf = [](clang::QualType PassedType) -> bool { + clang::QualType BaseType = + PassedType->isVectorType() + ? PassedType->getAs<clang::VectorType>()->getElementType() + : PassedType; + return !BaseType->isHalfType() && !BaseType->isFloat32Type(); + }; + return CheckArgsTypesAreCorrect(S, TheCall, S->Context.FloatTy, + checkFloatorHalf); +} + +bool CheckNoDoubleVectors(Sema *S, CallExpr *TheCall) { + auto checkDoubleVector = [](clang::QualType PassedType) -> bool { + if (const auto *VecTy = PassedType->getAs<VectorType>()) + return VecTy->getElementType()->isDoubleType(); + return false; + }; + return CheckArgsTypesAreCorrect(S, TheCall, S->Context.FloatTy, + checkDoubleVector); +} + +bool CheckUnsignedIntRepresentation(Sema *S, CallExpr *TheCall) { + auto checkAllUnsignedTypes = [](clang::QualType PassedType) -> bool { + return !PassedType->hasUnsignedIntegerRepresentation(); + }; + return CheckArgsTypesAreCorrect(S, TheCall, S->Context.UnsignedIntTy, + checkAllUnsignedTypes); +} + +void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall, + QualType ReturnType) { + auto *VecTyA = TheCall->getArg(0)->getType()->getAs<VectorType>(); + if (VecTyA) + ReturnType = S->Context.getVectorType(ReturnType, VecTyA->getNumElements(), + VectorKind::Generic); + TheCall->setType(ReturnType); +} + // Note: returning true in this case results in CheckBuiltinFunctionCall // returning an ExprError bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { @@ -5276,6 +5568,17 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return true; break; } + case Builtin::BI__builtin_hlsl_elementwise_clamp: { + if (checkArgCount(*this, TheCall, 3)) + return true; + if (CheckVectorElementCallArgs(this, TheCall)) + return true; + if (SemaBuiltinElementwiseTernaryMath( + TheCall, /*CheckForFloatArgs*/ + TheCall->getArg(0)->getType()->hasFloatingRepresentation())) + return true; + break; + } case Builtin::BI__builtin_hlsl_dot: { if (checkArgCount(*this, TheCall, 2)) return true; @@ -5283,14 +5586,31 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return true; if (SemaBuiltinVectorToScalarMath(TheCall)) return true; + if (CheckNoDoubleVectors(this, TheCall)) + return true; + break; + } + case Builtin::BI__builtin_hlsl_elementwise_rcp: { + if (CheckAllArgsHaveFloatRepresentation(this, TheCall)) + return true; + if (PrepareBuiltinElementwiseMathOneArgCall(TheCall)) + return true; break; } - case Builtin::BI__builtin_hlsl_elementwise_rcp: + case Builtin::BI__builtin_hlsl_elementwise_rsqrt: case Builtin::BI__builtin_hlsl_elementwise_frac: { + if (CheckFloatOrHalfRepresentations(this, TheCall)) + return true; if (PrepareBuiltinElementwiseMathOneArgCall(TheCall)) return true; - if (CheckAllArgsHaveFloatRepresentation(this, TheCall)) + break; + } + case Builtin::BI__builtin_hlsl_elementwise_isinf: { + if (CheckFloatOrHalfRepresentations(this, TheCall)) + return true; + if (PrepareBuiltinElementwiseMathOneArgCall(TheCall)) return true; + SetElementTypeAsReturnType(this, TheCall, this->Context.BoolTy); break; } case Builtin::BI__builtin_hlsl_lerp: { @@ -5300,7 +5620,7 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return true; if (SemaBuiltinElementwiseTernaryMath(TheCall)) return true; - if (CheckAllArgsHaveFloatRepresentation(this, TheCall)) + if (CheckFloatOrHalfRepresentations(this, TheCall)) return true; break; } @@ -5309,8 +5629,35 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return true; if (CheckVectorElementCallArgs(this, TheCall)) return true; - if (SemaBuiltinElementwiseTernaryMath(TheCall, /*CheckForFloatArgs*/ false)) + if (SemaBuiltinElementwiseTernaryMath( + TheCall, /*CheckForFloatArgs*/ + TheCall->getArg(0)->getType()->hasFloatingRepresentation())) return true; + break; + } + // Note these are llvm builtins that we want to catch invalid intrinsic + // generation. Normal handling of these builitns will occur elsewhere. + case Builtin::BI__builtin_elementwise_bitreverse: { + if (CheckUnsignedIntRepresentation(this, TheCall)) + return true; + break; + } + case Builtin::BI__builtin_elementwise_ceil: + case Builtin::BI__builtin_elementwise_cos: + case Builtin::BI__builtin_elementwise_exp: + case Builtin::BI__builtin_elementwise_exp2: + case Builtin::BI__builtin_elementwise_floor: + case Builtin::BI__builtin_elementwise_log: + case Builtin::BI__builtin_elementwise_log2: + case Builtin::BI__builtin_elementwise_log10: + case Builtin::BI__builtin_elementwise_pow: + case Builtin::BI__builtin_elementwise_roundeven: + case Builtin::BI__builtin_elementwise_sin: + case Builtin::BI__builtin_elementwise_sqrt: + case Builtin::BI__builtin_elementwise_trunc: { + if (CheckFloatOrHalfRepresentations(this, TheCall)) + return true; + break; } } return false; @@ -5432,57 +5779,6 @@ static bool CheckInvalidVLENandLMUL(const TargetInfo &TI, CallExpr *TheCall, bool Sema::CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID, CallExpr *TheCall) { - // CodeGenFunction can also detect this, but this gives a better error - // message. - bool FeatureMissing = false; - SmallVector<StringRef> ReqFeatures; - StringRef Features = Context.BuiltinInfo.getRequiredFeatures(BuiltinID); - Features.split(ReqFeatures, ',', -1, false); - - // Check if each required feature is included - for (StringRef F : ReqFeatures) { - SmallVector<StringRef> ReqOpFeatures; - F.split(ReqOpFeatures, '|'); - - if (llvm::none_of(ReqOpFeatures, - [&TI](StringRef OF) { return TI.hasFeature(OF); })) { - std::string FeatureStrs; - bool IsExtension = true; - for (StringRef OF : ReqOpFeatures) { - // If the feature is 64bit, alter the string so it will print better in - // the diagnostic. - if (OF == "64bit") { - assert(ReqOpFeatures.size() == 1 && "Expected '64bit' to be alone"); - OF = "RV64"; - IsExtension = false; - } - if (OF == "32bit") { - assert(ReqOpFeatures.size() == 1 && "Expected '32bit' to be alone"); - OF = "RV32"; - IsExtension = false; - } - - // Convert features like "zbr" and "experimental-zbr" to "Zbr". - OF.consume_front("experimental-"); - std::string FeatureStr = OF.str(); - FeatureStr[0] = std::toupper(FeatureStr[0]); - // Combine strings. - FeatureStrs += FeatureStrs.empty() ? "" : ", "; - FeatureStrs += "'"; - FeatureStrs += FeatureStr; - FeatureStrs += "'"; - } - // Error message - FeatureMissing = true; - Diag(TheCall->getBeginLoc(), diag::err_riscv_builtin_requires_extension) - << IsExtension - << TheCall->getSourceRange() << StringRef(FeatureStrs); - } - } - - if (FeatureMissing) - return true; - // vmulh.vv, vmulh.vx, vmulhu.vv, vmulhu.vx, vmulhsu.vv, vmulhsu.vx, // vsmul.vv, vsmul.vx are not included for EEW=64 in Zve64*. switch (BuiltinID) { @@ -6386,36 +6682,35 @@ bool Sema::CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI, return false; } -void Sema::checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D) { - const TargetInfo &TI = Context.getTargetInfo(); - +void Sema::checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D, + const llvm::StringMap<bool> &FeatureMap) { ASTContext::BuiltinVectorTypeInfo Info = Context.getBuiltinVectorTypeInfo(Ty->castAs<BuiltinType>()); unsigned EltSize = Context.getTypeSize(Info.ElementType); unsigned MinElts = Info.EC.getKnownMinValue(); if (Info.ElementType->isSpecificBuiltinType(BuiltinType::Double) && - !TI.hasFeature("zve64d")) + !FeatureMap.lookup("zve64d")) Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve64d"; // (ELEN, LMUL) pairs of (8, mf8), (16, mf4), (32, mf2), (64, m1) requires at // least zve64x else if (((EltSize == 64 && Info.ElementType->isIntegerType()) || MinElts == 1) && - !TI.hasFeature("zve64x")) + !FeatureMap.lookup("zve64x")) Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve64x"; - else if (Info.ElementType->isFloat16Type() && !TI.hasFeature("zvfh") && - !TI.hasFeature("zvfhmin")) + else if (Info.ElementType->isFloat16Type() && !FeatureMap.lookup("zvfh") && + !FeatureMap.lookup("zvfhmin")) Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zvfh or zvfhmin"; else if (Info.ElementType->isBFloat16Type() && - !TI.hasFeature("experimental-zvfbfmin")) + !FeatureMap.lookup("experimental-zvfbfmin")) Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zvfbfmin"; else if (Info.ElementType->isSpecificBuiltinType(BuiltinType::Float) && - !TI.hasFeature("zve32f")) + !FeatureMap.lookup("zve32f")) Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve32f"; // Given that caller already checked isRVVType() before calling this function, // if we don't have at least zve32x supported, then we need to emit error. - else if (!TI.hasFeature("zve32x")) + else if (!FeatureMap.lookup("zve32x")) Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve32x"; } @@ -7316,6 +7611,14 @@ bool Sema::getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember, /// /// Returns true if the value evaluates to null. static bool CheckNonNullExpr(Sema &S, const Expr *Expr) { + // Treat (smart) pointers constructed from nullptr as null, whether we can + // const-evaluate them or not. + // This must happen first: the smart pointer expr might have _Nonnull type! + if (isa<CXXNullPtrLiteralExpr>( + IgnoreExprNodes(Expr, IgnoreImplicitAsWrittenSingleStep, + IgnoreElidableImplicitConstructorSingleStep))) + return true; + // If the expression has non-null type, it doesn't evaluate to null. if (auto nullability = Expr->IgnoreImplicit()->getType()->getNullability()) { if (*nullability == NullabilityKind::NonNull) @@ -9381,7 +9684,7 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs, // vector argument can be supported in all of them. if (ElementTy->isVectorType() && IsFPClass) { VectorResultTy = GetSignedVectorType(ElementTy); - ElementTy = ElementTy->getAs<VectorType>()->getElementType(); + ElementTy = ElementTy->castAs<VectorType>()->getElementType(); } // This operation requires a non-_Complex floating-point number. @@ -12152,6 +12455,19 @@ isArithmeticArgumentPromotion(Sema &S, const ImplicitCastExpr *ICE) { S.Context.getFloatingTypeOrder(From, To) < 0; } +static analyze_format_string::ArgType::MatchKind +handleFormatSignedness(analyze_format_string::ArgType::MatchKind Match, + DiagnosticsEngine &Diags, SourceLocation Loc) { + if (Match == analyze_format_string::ArgType::NoMatchSignedness) { + Match = + Diags.isIgnored( + diag::warn_format_conversion_argument_type_mismatch_signedness, Loc) + ? analyze_format_string::ArgType::Match + : analyze_format_string::ArgType::NoMatch; + } + return Match; +} + bool CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, const char *StartSpecifier, @@ -12195,6 +12511,9 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, ArgType::MatchKind ImplicitMatch = ArgType::NoMatch; ArgType::MatchKind Match = AT.matchesType(S.Context, ExprTy); + ArgType::MatchKind OrigMatch = Match; + + Match = handleFormatSignedness(Match, S.getDiagnostics(), E->getExprLoc()); if (Match == ArgType::Match) return true; @@ -12218,6 +12537,14 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, ICE->getType() == S.Context.UnsignedIntTy) { // All further checking is done on the subexpression ImplicitMatch = AT.matchesType(S.Context, ExprTy); + if (OrigMatch == ArgType::NoMatchSignedness && + ImplicitMatch != ArgType::NoMatchSignedness) + // If the original match was a signedness match this match on the + // implicit cast type also need to be signedness match otherwise we + // might introduce new unexpected warnings from -Wformat-signedness. + return true; + ImplicitMatch = handleFormatSignedness( + ImplicitMatch, S.getDiagnostics(), E->getExprLoc()); if (ImplicitMatch == ArgType::Match) return true; } @@ -12339,6 +12666,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, case ArgType::Match: case ArgType::MatchPromotion: case ArgType::NoMatchPromotionTypeConfusion: + case ArgType::NoMatchSignedness: llvm_unreachable("expected non-matching"); case ArgType::NoMatchPedantic: Diag = diag::warn_format_conversion_argument_type_mismatch_pedantic; @@ -12374,8 +12702,10 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, CastFix << (S.LangOpts.CPlusPlus ? ">" : ")"); SmallVector<FixItHint,4> Hints; - if (AT.matchesType(S.Context, IntendedTy) != ArgType::Match || - ShouldNotPrintDirectly) + ArgType::MatchKind IntendedMatch = AT.matchesType(S.Context, IntendedTy); + IntendedMatch = handleFormatSignedness(IntendedMatch, S.getDiagnostics(), + E->getExprLoc()); + if ((IntendedMatch != ArgType::Match) || ShouldNotPrintDirectly) Hints.push_back(FixItHint::CreateReplacement(SpecRange, os.str())); if (const CStyleCastExpr *CCast = dyn_cast<CStyleCastExpr>(E)) { @@ -12444,6 +12774,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, case ArgType::Match: case ArgType::MatchPromotion: case ArgType::NoMatchPromotionTypeConfusion: + case ArgType::NoMatchSignedness: llvm_unreachable("expected non-matching"); case ArgType::NoMatchPedantic: Diag = diag::warn_format_conversion_argument_type_mismatch_pedantic; @@ -12655,6 +12986,7 @@ bool CheckScanfHandler::HandleScanfSpecifier( analyze_format_string::ArgType::MatchKind Match = AT.matchesType(S.Context, Ex->getType()); + Match = handleFormatSignedness(Match, S.getDiagnostics(), Ex->getExprLoc()); bool Pedantic = Match == analyze_format_string::ArgType::NoMatchPedantic; if (Match == analyze_format_string::ArgType::Match) return true; @@ -12716,7 +13048,7 @@ static void CheckFormatString( const ConstantArrayType *T = S.Context.getAsConstantArrayType(FExpr->getType()); assert(T && "String literal not of constant array type!"); - size_t TypeSize = T->getSize().getZExtValue(); + size_t TypeSize = T->getZExtSize(); size_t StrLen = std::min(std::max(TypeSize, size_t(1)) - 1, StrRef.size()); const unsigned numDataArgs = Args.size() - firstDataArg; @@ -12776,7 +13108,7 @@ bool Sema::FormatStringHasSArg(const StringLiteral *FExpr) { // Account for cases where the string literal is truncated in a declaration. const ConstantArrayType *T = Context.getAsConstantArrayType(FExpr->getType()); assert(T && "String literal not of constant array type!"); - size_t TypeSize = T->getSize().getZExtValue(); + size_t TypeSize = T->getZExtSize(); size_t StrLen = std::min(std::max(TypeSize, size_t(1)) - 1, StrRef.size()); return analyze_format_string::ParseFormatStringHasSArg(Str, Str + StrLen, getLangOpts(), @@ -13739,7 +14071,7 @@ static bool isConstantSizeArrayWithMoreThanOneElement(QualType Ty, // Only handle constant-sized or VLAs, but not flexible members. if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(Ty)) { // Only issue the FIXIT for arrays of size > 1. - if (CAT->getSize().getSExtValue() <= 1) + if (CAT->getZExtSize() <= 1) return false; } else if (!Ty->isVariableArrayType()) { return false; @@ -16351,12 +16683,26 @@ static void AnalyzeImplicitConversions( BO->getRHS()->isKnownToHaveBooleanValue() && BO->getLHS()->HasSideEffects(S.Context) && BO->getRHS()->HasSideEffects(S.Context)) { - S.Diag(BO->getBeginLoc(), diag::warn_bitwise_instead_of_logical) - << (BO->getOpcode() == BO_And ? "&" : "|") << OrigE->getSourceRange() - << FixItHint::CreateReplacement( - BO->getOperatorLoc(), - (BO->getOpcode() == BO_And ? "&&" : "||")); - S.Diag(BO->getBeginLoc(), diag::note_cast_operand_to_int); + SourceManager &SM = S.getSourceManager(); + const LangOptions &LO = S.getLangOpts(); + SourceLocation BLoc = BO->getOperatorLoc(); + SourceLocation ELoc = Lexer::getLocForEndOfToken(BLoc, 0, SM, LO); + StringRef SR = clang::Lexer::getSourceText( + clang::CharSourceRange::getTokenRange(BLoc, ELoc), SM, LO); + // To reduce false positives, only issue the diagnostic if the operator + // is explicitly spelled as a punctuator. This suppresses the diagnostic + // when using 'bitand' or 'bitor' either as keywords in C++ or as macros + // in C, along with other macro spellings the user might invent. + if (SR.str() == "&" || SR.str() == "|") { + + S.Diag(BO->getBeginLoc(), diag::warn_bitwise_instead_of_logical) + << (BO->getOpcode() == BO_And ? "&" : "|") + << OrigE->getSourceRange() + << FixItHint::CreateReplacement( + BO->getOperatorLoc(), + (BO->getOpcode() == BO_And ? "&&" : "||")); + S.Diag(BO->getBeginLoc(), diag::note_cast_operand_to_int); + } } // For conditional operators, we analyze the arguments as if they diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 73e6baa5278262e29397f9b617e512ffa5d8423c..83ebcaf9e765a78e95de4630df7b0b8f55f370ff 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -20,6 +20,7 @@ #include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/OperationKinds.h" #include "clang/AST/QualTypeNames.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" @@ -5678,6 +5679,10 @@ QualType getApproximateType(const Expr *E) { return getApproximateType(VD->getInit()); } } + if (const auto *UO = llvm::dyn_cast<UnaryOperator>(E)) { + if (UO->getOpcode() == UnaryOperatorKind::UO_Deref) + return UO->getSubExpr()->getType()->getPointeeType(); + } return Unresolved; } diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index a8e387e35fb4c90095cb18212f413a34c6b7f87a..b2986c5012ea2bd45f03c1da9763c2206ea3a064 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -692,11 +692,15 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, // A lambda conversion operator has the same constraints as the call operator // and constraints checking relies on whether we are in a lambda call operator // (and may refer to its parameters), so check the call operator instead. + // Note that the declarations outside of the lambda should also be + // considered. Turning on the 'ForOverloadResolution' flag results in the + // LocalInstantiationScope not looking into its parents, but we can still + // access Decls from the parents while building a lambda RAII scope later. if (const auto *MD = dyn_cast<CXXConversionDecl>(FD); MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD))) return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(), Satisfaction, UsageLoc, - ForOverloadResolution); + /*ShouldAddDeclsFromParentScope=*/true); DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD); @@ -1265,10 +1269,20 @@ substituteParameterMappings(Sema &S, NormalizedConstraint &N, : SourceLocation())); Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count()); } + SourceLocation InstLocBegin = + ArgsAsWritten->arguments().empty() + ? ArgsAsWritten->getLAngleLoc() + : ArgsAsWritten->arguments().front().getSourceRange().getBegin(); + SourceLocation InstLocEnd = + ArgsAsWritten->arguments().empty() + ? ArgsAsWritten->getRAngleLoc() + : ArgsAsWritten->arguments().front().getSourceRange().getEnd(); Sema::InstantiatingTemplate Inst( - S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(), + S, InstLocBegin, Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept, - ArgsAsWritten->arguments().front().getSourceRange()); + {InstLocBegin, InstLocEnd}); + if (Inst.isInvalid()) + return true; if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs)) return true; @@ -1342,6 +1356,8 @@ NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) { S, CSE->getExprLoc(), Sema::InstantiatingTemplate::ConstraintNormalization{}, D, CSE->getSourceRange()); + if (Inst.isInvalid()) + return std::nullopt; // C++ [temp.constr.normal]p1.1 // [...] // The normal form of an id-expression of the form C<A1, A2, ..., AN>, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 1f4a041e88dfff1b2fea8154c549322808beb66d..5c1152896559b52291aae3264ad945d221ea74fe 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1192,9 +1192,13 @@ Corrected: return ParsedType::make(T); } - if (isa<ConceptDecl>(FirstDecl)) + if (isa<ConceptDecl>(FirstDecl)) { + // We want to preserve the UsingShadowDecl for concepts. + if (auto *USD = dyn_cast<UsingShadowDecl>(Result.getRepresentativeDecl())) + return NameClassification::Concept(TemplateName(USD)); return NameClassification::Concept( TemplateName(cast<TemplateDecl>(FirstDecl))); + } if (auto *EmptyD = dyn_cast<UnresolvedUsingIfExistsDecl>(FirstDecl)) { (void)DiagnoseUseOfDecl(EmptyD, NameLoc); @@ -2267,12 +2271,6 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { } ShadowingDecls.erase(ShadowI); } - - if (!getLangOpts().CPlusPlus && S->isClassScope()) { - if (auto *FD = dyn_cast<FieldDecl>(TmpD); - FD && FD->hasAttr<CountedByAttr>()) - CheckCountedByAttr(S, FD); - } } llvm::sort(DeclDiags, @@ -8839,7 +8837,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { return; } const auto *ATy = dyn_cast<ConstantArrayType>(T.getTypePtr()); - if (!ATy || ATy->getSize().getSExtValue() != 0) { + if (!ATy || ATy->getZExtSize() != 0) { Diag(NewVD->getLocation(), diag::err_typecheck_wasm_table_must_have_zero_length); NewVD->setInvalidDecl(); @@ -8964,8 +8962,13 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { } } - if (T->isRVVSizelessBuiltinType()) - checkRVVTypeSupport(T, NewVD->getLocation(), cast<Decl>(CurContext)); + if (T->isRVVSizelessBuiltinType() && isa<FunctionDecl>(CurContext)) { + const FunctionDecl *FD = cast<FunctionDecl>(CurContext); + llvm::StringMap<bool> CallerFeatureMap; + Context.getFunctionFeatureMap(CallerFeatureMap, FD); + checkRVVTypeSupport(T, NewVD->getLocation(), cast<Decl>(CurContext), + CallerFeatureMap); + } } /// Perform semantic checking on a newly-created variable @@ -9912,7 +9915,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // FIXME: We need a better way to separate C++ standard and clang modules. bool ImplicitInlineCXX20 = !getLangOpts().CPlusPlusModules || !NewFD->getOwningModule() || - NewFD->getOwningModule()->isGlobalModule() || + NewFD->isFromExplicitGlobalModule() || NewFD->getOwningModule()->isHeaderLikeModule(); bool isInline = D.getDeclSpec().isInlineSpecified(); bool isVirtual = D.getDeclSpec().isVirtualSpecified(); @@ -10121,23 +10124,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, Diag(D.getDeclSpec().getVirtualSpecLoc(), diag::err_auto_fn_virtual); } - if (getLangOpts().CPlusPlus14 && - (NewFD->isDependentContext() || - (isFriend && CurContext->isDependentContext())) && - NewFD->getReturnType()->isUndeducedType()) { - // If the function template is referenced directly (for instance, as a - // member of the current instantiation), pretend it has a dependent type. - // This is not really justified by the standard, but is the only sane - // thing to do. - // FIXME: For a friend function, we have not marked the function as being - // a friend yet, so 'isDependentContext' on the FD doesn't work. - const FunctionProtoType *FPT = - NewFD->getType()->castAs<FunctionProtoType>(); - QualType Result = SubstAutoTypeDependent(FPT->getReturnType()); - NewFD->setType(Context.getFunctionType(Result, FPT->getParamTypes(), - FPT->getExtProtoInfo())); - } - // C++ [dcl.fct.spec]p3: // The inline specifier shall not appear on a block scope function // declaration. @@ -11262,11 +11248,13 @@ static bool checkNonMultiVersionCompatAttributes(Sema &S, return Diagnose(S, A); break; case attr::TargetVersion: - if (MVKind != MultiVersionKind::TargetVersion) + if (MVKind != MultiVersionKind::TargetVersion && + MVKind != MultiVersionKind::TargetClones) return Diagnose(S, A); break; case attr::TargetClones: - if (MVKind != MultiVersionKind::TargetClones) + if (MVKind != MultiVersionKind::TargetClones && + MVKind != MultiVersionKind::TargetVersion) return Diagnose(S, A); break; default: @@ -11443,9 +11431,9 @@ static bool CheckMultiVersionFirstFunction(Sema &S, FunctionDecl *FD) { "Function lacks multiversion attribute"); const auto *TA = FD->getAttr<TargetAttr>(); const auto *TVA = FD->getAttr<TargetVersionAttr>(); - // Target and target_version only causes MV if it is default, otherwise this - // is a normal function. - if ((TA && !TA->isDefaultVersion()) || (TVA && !TVA->isDefaultVersion())) + // The target attribute only causes MV if this declaration is the default, + // otherwise it is treated as a normal function. + if (TA && !TA->isDefaultVersion()) return false; if ((TA || TVA) && CheckMultiVersionValue(S, FD)) { @@ -11471,6 +11459,22 @@ static bool PreviousDeclsHaveMultiVersionAttribute(const FunctionDecl *FD) { return false; } +static void patchDefaultTargetVersion(FunctionDecl *From, FunctionDecl *To) { + if (!From->getASTContext().getTargetInfo().getTriple().isAArch64()) + return; + + MultiVersionKind MVKindFrom = From->getMultiVersionKind(); + MultiVersionKind MVKindTo = To->getMultiVersionKind(); + + if (MVKindTo == MultiVersionKind::None && + (MVKindFrom == MultiVersionKind::TargetVersion || + MVKindFrom == MultiVersionKind::TargetClones)) { + To->setIsMultiVersion(); + To->addAttr(TargetVersionAttr::CreateImplicit( + To->getASTContext(), "default", To->getSourceRange())); + } +} + static bool CheckTargetCausesMultiVersioning(Sema &S, FunctionDecl *OldFD, FunctionDecl *NewFD, bool &Redeclaration, @@ -11481,10 +11485,7 @@ static bool CheckTargetCausesMultiVersioning(Sema &S, FunctionDecl *OldFD, // The definitions should be allowed in any order. If we have discovered // a new target version and the preceeding was the default, then add the // corresponding attribute to it. - if (OldFD->getMultiVersionKind() == MultiVersionKind::None && - NewFD->getMultiVersionKind() == MultiVersionKind::TargetVersion) - OldFD->addAttr(TargetVersionAttr::CreateImplicit(S.Context, "default", - OldFD->getSourceRange())); + patchDefaultTargetVersion(NewFD, OldFD); const auto *NewTA = NewFD->getAttr<TargetAttr>(); const auto *NewTVA = NewFD->getAttr<TargetVersionAttr>(); @@ -11585,36 +11586,60 @@ static bool CheckTargetCausesMultiVersioning(Sema &S, FunctionDecl *OldFD, return false; } -static bool MultiVersionTypesCompatible(MultiVersionKind Old, - MultiVersionKind New) { - if (Old == New || Old == MultiVersionKind::None || - New == MultiVersionKind::None) +static bool MultiVersionTypesCompatible(FunctionDecl *Old, FunctionDecl *New) { + MultiVersionKind OldKind = Old->getMultiVersionKind(); + MultiVersionKind NewKind = New->getMultiVersionKind(); + + if (OldKind == NewKind || OldKind == MultiVersionKind::None || + NewKind == MultiVersionKind::None) return true; - return (Old == MultiVersionKind::CPUDispatch && - New == MultiVersionKind::CPUSpecific) || - (Old == MultiVersionKind::CPUSpecific && - New == MultiVersionKind::CPUDispatch); + if (Old->getASTContext().getTargetInfo().getTriple().isAArch64()) { + switch (OldKind) { + case MultiVersionKind::TargetVersion: + return NewKind == MultiVersionKind::TargetClones; + case MultiVersionKind::TargetClones: + return NewKind == MultiVersionKind::TargetVersion; + default: + return false; + } + } else { + switch (OldKind) { + case MultiVersionKind::CPUDispatch: + return NewKind == MultiVersionKind::CPUSpecific; + case MultiVersionKind::CPUSpecific: + return NewKind == MultiVersionKind::CPUDispatch; + default: + return false; + } + } } /// Check the validity of a new function declaration being added to an existing /// multiversioned declaration collection. static bool CheckMultiVersionAdditionalDecl( Sema &S, FunctionDecl *OldFD, FunctionDecl *NewFD, - MultiVersionKind NewMVKind, const CPUDispatchAttr *NewCPUDisp, - const CPUSpecificAttr *NewCPUSpec, const TargetClonesAttr *NewClones, - bool &Redeclaration, NamedDecl *&OldDecl, LookupResult &Previous) { - const auto *NewTA = NewFD->getAttr<TargetAttr>(); - const auto *NewTVA = NewFD->getAttr<TargetVersionAttr>(); - MultiVersionKind OldMVKind = OldFD->getMultiVersionKind(); + const CPUDispatchAttr *NewCPUDisp, const CPUSpecificAttr *NewCPUSpec, + const TargetClonesAttr *NewClones, bool &Redeclaration, NamedDecl *&OldDecl, + LookupResult &Previous) { + // Disallow mixing of multiversioning types. - if (!MultiVersionTypesCompatible(OldMVKind, NewMVKind)) { + if (!MultiVersionTypesCompatible(OldFD, NewFD)) { S.Diag(NewFD->getLocation(), diag::err_multiversion_types_mixed); S.Diag(OldFD->getLocation(), diag::note_previous_declaration); NewFD->setInvalidDecl(); return true; } + // Add the default target_version attribute if it's missing. + patchDefaultTargetVersion(OldFD, NewFD); + patchDefaultTargetVersion(NewFD, OldFD); + + const auto *NewTA = NewFD->getAttr<TargetAttr>(); + const auto *NewTVA = NewFD->getAttr<TargetVersionAttr>(); + MultiVersionKind NewMVKind = NewFD->getMultiVersionKind(); + [[maybe_unused]] MultiVersionKind OldMVKind = OldFD->getMultiVersionKind(); + ParsedTargetAttr NewParsed; if (NewTA) { NewParsed = S.getASTContext().getTargetInfo().parseTargetAttr( @@ -11643,19 +11668,6 @@ static bool CheckMultiVersionAdditionalDecl( S.IsOverload(NewFD, CurFD, UseMemberUsingDeclRules)) continue; - if (NewMVKind == MultiVersionKind::None && - OldMVKind == MultiVersionKind::TargetVersion) { - NewFD->addAttr(TargetVersionAttr::CreateImplicit( - S.Context, "default", NewFD->getSourceRange())); - NewFD->setIsMultiVersion(); - NewMVKind = MultiVersionKind::TargetVersion; - if (!NewTVA) { - NewTVA = NewFD->getAttr<TargetVersionAttr>(); - NewTVA->getFeatures(NewFeats); - llvm::sort(NewFeats); - } - } - switch (NewMVKind) { case MultiVersionKind::None: assert(OldMVKind == MultiVersionKind::TargetClones && @@ -11683,43 +11695,81 @@ static bool CheckMultiVersionAdditionalDecl( break; } case MultiVersionKind::TargetVersion: { - const auto *CurTVA = CurFD->getAttr<TargetVersionAttr>(); - if (CurTVA->getName() == NewTVA->getName()) { - NewFD->setIsMultiVersion(); - Redeclaration = true; - OldDecl = ND; - return false; - } - llvm::SmallVector<StringRef, 8> CurFeats; - if (CurTVA) { + if (const auto *CurTVA = CurFD->getAttr<TargetVersionAttr>()) { + if (CurTVA->getName() == NewTVA->getName()) { + NewFD->setIsMultiVersion(); + Redeclaration = true; + OldDecl = ND; + return false; + } + llvm::SmallVector<StringRef, 8> CurFeats; CurTVA->getFeatures(CurFeats); llvm::sort(CurFeats); - } - if (CurFeats == NewFeats) { - S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate); - S.Diag(CurFD->getLocation(), diag::note_previous_declaration); - NewFD->setInvalidDecl(); - return true; + + if (CurFeats == NewFeats) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate); + S.Diag(CurFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } + } else if (const auto *CurClones = CurFD->getAttr<TargetClonesAttr>()) { + // Default + if (NewFeats.empty()) + break; + + for (unsigned I = 0; I < CurClones->featuresStrs_size(); ++I) { + llvm::SmallVector<StringRef, 8> CurFeats; + CurClones->getFeatures(CurFeats, I); + llvm::sort(CurFeats); + + if (CurFeats == NewFeats) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate); + S.Diag(CurFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } + } } break; } case MultiVersionKind::TargetClones: { - const auto *CurClones = CurFD->getAttr<TargetClonesAttr>(); + assert(NewClones && "MultiVersionKind does not match attribute type"); + if (const auto *CurClones = CurFD->getAttr<TargetClonesAttr>()) { + if (CurClones->featuresStrs_size() != NewClones->featuresStrs_size() || + !std::equal(CurClones->featuresStrs_begin(), + CurClones->featuresStrs_end(), + NewClones->featuresStrs_begin())) { + S.Diag(NewFD->getLocation(), diag::err_target_clone_doesnt_match); + S.Diag(CurFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } + } else if (const auto *CurTVA = CurFD->getAttr<TargetVersionAttr>()) { + llvm::SmallVector<StringRef, 8> CurFeats; + CurTVA->getFeatures(CurFeats); + llvm::sort(CurFeats); + + // Default + if (CurFeats.empty()) + break; + + for (unsigned I = 0; I < NewClones->featuresStrs_size(); ++I) { + NewFeats.clear(); + NewClones->getFeatures(NewFeats, I); + llvm::sort(NewFeats); + + if (CurFeats == NewFeats) { + S.Diag(NewFD->getLocation(), diag::err_multiversion_duplicate); + S.Diag(CurFD->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + return true; + } + } + break; + } Redeclaration = true; OldDecl = CurFD; NewFD->setIsMultiVersion(); - - if (CurClones && NewClones && - (CurClones->featuresStrs_size() != NewClones->featuresStrs_size() || - !std::equal(CurClones->featuresStrs_begin(), - CurClones->featuresStrs_end(), - NewClones->featuresStrs_begin()))) { - S.Diag(NewFD->getLocation(), diag::err_target_clone_doesnt_match); - S.Diag(CurFD->getLocation(), diag::note_previous_declaration); - NewFD->setInvalidDecl(); - return true; - } - return false; } case MultiVersionKind::CPUSpecific: @@ -11915,7 +11965,7 @@ static bool CheckMultiVersionFunction(Sema &S, FunctionDecl *NewFD, // At this point, we have a multiversion function decl (in OldFD) AND an // appropriate attribute in the current function decl. Resolve that these are // still compatible with previous declarations. - return CheckMultiVersionAdditionalDecl(S, OldFD, NewFD, MVKind, NewCPUDisp, + return CheckMultiVersionAdditionalDecl(S, OldFD, NewFD, NewCPUDisp, NewCPUSpec, NewClones, Redeclaration, OldDecl, Previous); } @@ -12045,6 +12095,35 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, CheckConstPureAttributesUsage(*this, NewFD); + // C++ [dcl.spec.auto.general]p12: + // Return type deduction for a templated function with a placeholder in its + // declared type occurs when the definition is instantiated even if the + // function body contains a return statement with a non-type-dependent + // operand. + // + // C++ [temp.dep.expr]p3: + // An id-expression is type-dependent if it is a template-id that is not a + // concept-id and is dependent; or if its terminal name is: + // - [...] + // - associated by name lookup with one or more declarations of member + // functions of a class that is the current instantiation declared with a + // return type that contains a placeholder type, + // - [...] + // + // If this is a templated function with a placeholder in its return type, + // make the placeholder type dependent since it won't be deduced until the + // definition is instantiated. We do this here because it needs to happen + // for implicitly instantiated member functions/member function templates. + if (getLangOpts().CPlusPlus14 && + (NewFD->isDependentContext() && + NewFD->getReturnType()->isUndeducedType())) { + const FunctionProtoType *FPT = + NewFD->getType()->castAs<FunctionProtoType>(); + QualType NewReturnType = SubstAutoTypeDependent(FPT->getReturnType()); + NewFD->setType(Context.getFunctionType(NewReturnType, FPT->getParamTypes(), + FPT->getExtProtoInfo())); + } + // C++11 [dcl.constexpr]p8: // A constexpr specifier for a non-static member function that is not // a constructor declares that member function to be const. @@ -16111,7 +16190,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, FD->setInvalidDecl(); } } - } else if (getLangOpts().CPlusPlus11 && isLambdaCallOperator(FD)) { + } else if (getLangOpts().CPlusPlus && isLambdaCallOperator(FD)) { // In C++11, we don't use 'auto' deduction rules for lambda call // operators because we don't support return type deduction. auto *LSI = getCurLambda(); @@ -18103,7 +18182,9 @@ CreateNewDecl: cast_or_null<RecordDecl>(PrevDecl)); } - if (OOK != OOK_Outside && TUK == TUK_Definition && !getLangOpts().CPlusPlus) + // Only C23 and later allow defining new types in 'offsetof()'. + if (OOK != OOK_Outside && TUK == TUK_Definition && !getLangOpts().CPlusPlus && + !getLangOpts().C23) Diag(New->getLocation(), diag::ext_type_defined_in_offsetof) << (OOK == OOK_Macro) << New->getSourceRange(); @@ -18250,8 +18331,10 @@ CreateNewDecl: if (PrevDecl) mergeDeclAttributes(New, PrevDecl); - if (auto *CXXRD = dyn_cast<CXXRecordDecl>(New)) + if (auto *CXXRD = dyn_cast<CXXRecordDecl>(New)) { inferGslOwnerPointerAttribute(CXXRD); + inferNullableClassAttribute(CXXRD); + } // If there's a #pragma GCC visibility in scope, set the visibility of this // record. @@ -19362,15 +19445,11 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, } else if (Record->isUnion()) DiagID = getLangOpts().MicrosoftExt ? diag::ext_flexible_array_union_ms - : getLangOpts().CPlusPlus - ? diag::ext_flexible_array_union_gnu - : diag::err_flexible_array_union; + : diag::ext_flexible_array_union_gnu; else if (NumNamedMembers < 1) DiagID = getLangOpts().MicrosoftExt ? diag::ext_flexible_array_empty_aggregate_ms - : getLangOpts().CPlusPlus - ? diag::ext_flexible_array_empty_aggregate_gnu - : diag::err_flexible_array_empty_aggregate; + : diag::ext_flexible_array_empty_aggregate_gnu; if (DiagID) Diag(FD->getLocation(), DiagID) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index e3da3e606435f415b31c5cfa2e6d296fa2920f29..8bce04640e748e8a419f6f76cfa38844568ea2c6 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3787,6 +3787,30 @@ static void handleCleanupAttr(Sema &S, Decl *D, const ParsedAttr &AL) { << NI.getName() << ParamTy << Ty; return; } + VarDecl *VD = cast<VarDecl>(D); + // Create a reference to the variable declaration. This is a fake/dummy + // reference. + DeclRefExpr *VariableReference = DeclRefExpr::Create( + S.Context, NestedNameSpecifierLoc{}, FD->getLocation(), VD, false, + DeclarationNameInfo{VD->getDeclName(), VD->getLocation()}, VD->getType(), + VK_LValue); + + // Create a unary operator expression that represents taking the address of + // the variable. This is a fake/dummy expression. + Expr *AddressOfVariable = UnaryOperator::Create( + S.Context, VariableReference, UnaryOperatorKind::UO_AddrOf, + S.Context.getPointerType(VD->getType()), VK_PRValue, OK_Ordinary, Loc, + +false, FPOptionsOverride{}); + + // Create a function call expression. This is a fake/dummy call expression. + CallExpr *FunctionCallExpression = + CallExpr::Create(S.Context, E, ArrayRef{AddressOfVariable}, + S.Context.VoidTy, VK_PRValue, Loc, FPOptionsOverride{}); + + if (S.CheckFunctionCall(FD, FunctionCallExpression, + FD->getType()->getAs<FunctionProtoType>())) { + return; + } D->addAttr(::new (S.Context) CleanupAttr(S.Context, AL, FD)); } @@ -5247,6 +5271,9 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) { case ParsedAttr::AT_PreserveNone: D->addAttr(::new (S.Context) PreserveNoneAttr(S.Context, AL)); return; + case ParsedAttr::AT_RISCVVectorCC: + D->addAttr(::new (S.Context) RISCVVectorCCAttr(S.Context, AL)); + return; default: llvm_unreachable("unexpected attribute kind"); } @@ -5451,6 +5478,9 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, case ParsedAttr::AT_PreserveNone: CC = CC_PreserveNone; break; + case ParsedAttr::AT_RISCVVectorCC: + CC = CC_RISCVVectorCall; + break; default: llvm_unreachable("unexpected attribute kind"); } @@ -5952,6 +5982,20 @@ static void handleBuiltinAliasAttr(Sema &S, Decl *D, D->addAttr(::new (S.Context) BuiltinAliasAttr(S.Context, AL, Ident)); } +static void handleNullableTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + if (AL.isUsedAsTypeAttr()) + return; + + if (auto *CRD = dyn_cast<CXXRecordDecl>(D); + !CRD || !(CRD->isClass() || CRD->isStruct())) { + S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type_str) + << AL << AL.isRegularKeywordAttribute() << "classes"; + return; + } + + handleSimpleAttribute<TypeNullableAttr>(S, D, AL); +} + static void handlePreferredTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!AL.hasParsedType()) { S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1; @@ -8532,133 +8576,114 @@ static void handleZeroCallUsedRegsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(ZeroCallUsedRegsAttr::Create(S.Context, Kind, AL)); } -static void handleCountedByAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (!AL.isArgIdent(0)) { - S.Diag(AL.getLoc(), diag::err_attribute_argument_type) - << AL << AANT_ArgumentIdentifier; - return; +static const RecordDecl *GetEnclosingNamedOrTopAnonRecord(const FieldDecl *FD) { + const auto *RD = FD->getParent(); + // An unnamed struct is anonymous struct only if it's not instantiated. + // However, the struct may not be fully processed yet to determine + // whether it's anonymous or not. In that case, this function treats it as + // an anonymous struct and tries to find a named parent. + while (RD && (RD->isAnonymousStructOrUnion() || + (!RD->isCompleteDefinition() && RD->getName().empty()))) { + const auto *Parent = dyn_cast<RecordDecl>(RD->getParent()); + if (!Parent) + break; + RD = Parent; } - - IdentifierLoc *IL = AL.getArgAsIdent(0); - CountedByAttr *CBA = - ::new (S.Context) CountedByAttr(S.Context, AL, IL->Ident); - CBA->setCountedByFieldLoc(IL->Loc); - D->addAttr(CBA); + return RD; } -static const FieldDecl * -FindFieldInTopLevelOrAnonymousStruct(const RecordDecl *RD, - const IdentifierInfo *FieldName) { - for (const Decl *D : RD->decls()) { - if (const auto *FD = dyn_cast<FieldDecl>(D)) - if (FD->getName() == FieldName->getName()) - return FD; - - if (const auto *R = dyn_cast<RecordDecl>(D)) - if (const FieldDecl *FD = - FindFieldInTopLevelOrAnonymousStruct(R, FieldName)) - return FD; +static bool +CheckCountExpr(Sema &S, FieldDecl *FD, Expr *E, + llvm::SmallVectorImpl<TypeCoupledDeclRefInfo> &Decls) { + if (FD->getParent()->isUnion()) { + S.Diag(FD->getBeginLoc(), diag::err_counted_by_attr_in_union) + << FD->getSourceRange(); + return true; } - return nullptr; -} + if (!E->getType()->isIntegerType() || E->getType()->isBooleanType()) { + S.Diag(E->getBeginLoc(), diag::err_counted_by_attr_argument_not_integer) + << E->getSourceRange(); + return true; + } -bool Sema::CheckCountedByAttr(Scope *S, const FieldDecl *FD) { LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel = LangOptions::StrictFlexArraysLevelKind::IncompleteOnly; - if (!Decl::isFlexibleArrayMemberLike(Context, FD, FD->getType(), + + if (!Decl::isFlexibleArrayMemberLike(S.getASTContext(), FD, FD->getType(), StrictFlexArraysLevel, true)) { // The "counted_by" attribute must be on a flexible array member. SourceRange SR = FD->getLocation(); - Diag(SR.getBegin(), diag::err_counted_by_attr_not_on_flexible_array_member) + S.Diag(SR.getBegin(), + diag::err_counted_by_attr_not_on_flexible_array_member) << SR; return true; } - const auto *CBA = FD->getAttr<CountedByAttr>(); - const IdentifierInfo *FieldName = CBA->getCountedByField(); - - auto GetNonAnonStructOrUnion = [](const RecordDecl *RD) { - while (RD && !RD->getDeclName()) - if (const auto *R = dyn_cast<RecordDecl>(RD->getDeclContext())) - RD = R; - else - break; - - return RD; - }; - - const RecordDecl *EnclosingRD = GetNonAnonStructOrUnion(FD->getParent()); - const FieldDecl *CountFD = - FindFieldInTopLevelOrAnonymousStruct(EnclosingRD, FieldName); + auto *DRE = dyn_cast<DeclRefExpr>(E); + if (!DRE) { + S.Diag(E->getBeginLoc(), + diag::err_counted_by_attr_only_support_simple_decl_reference) + << E->getSourceRange(); + return true; + } + auto *CountDecl = DRE->getDecl(); + FieldDecl *CountFD = dyn_cast<FieldDecl>(CountDecl); + if (auto *IFD = dyn_cast<IndirectFieldDecl>(CountDecl)) { + CountFD = IFD->getAnonField(); + } if (!CountFD) { - DeclarationNameInfo NameInfo(FieldName, - CBA->getCountedByFieldLoc().getBegin()); - LookupResult MemResult(*this, NameInfo, Sema::LookupMemberName); - LookupName(MemResult, S); - - if (!MemResult.empty()) { - SourceRange SR = CBA->getCountedByFieldLoc(); - Diag(SR.getBegin(), diag::err_flexible_array_count_not_in_same_struct) - << CBA->getCountedByField() << SR; - - if (auto *ND = MemResult.getAsSingle<NamedDecl>()) { - SR = ND->getLocation(); - Diag(SR.getBegin(), diag::note_flexible_array_counted_by_attr_field) - << ND << SR; - } + S.Diag(E->getBeginLoc(), diag::err_counted_by_must_be_in_structure) + << CountDecl << E->getSourceRange(); - return true; - } else { - // The "counted_by" field needs to exist in the struct. - LookupResult OrdResult(*this, NameInfo, Sema::LookupOrdinaryName); - LookupName(OrdResult, S); - - if (!OrdResult.empty()) { - SourceRange SR = FD->getLocation(); - Diag(SR.getBegin(), diag::err_counted_by_must_be_in_structure) - << FieldName << SR; - - if (auto *ND = OrdResult.getAsSingle<NamedDecl>()) { - SR = ND->getLocation(); - Diag(SR.getBegin(), diag::note_flexible_array_counted_by_attr_field) - << ND << SR; - } + S.Diag(CountDecl->getBeginLoc(), + diag::note_flexible_array_counted_by_attr_field) + << CountDecl << CountDecl->getSourceRange(); + return true; + } - return true; - } + if (FD->getParent() != CountFD->getParent()) { + if (CountFD->getParent()->isUnion()) { + S.Diag(CountFD->getBeginLoc(), diag::err_counted_by_attr_refer_to_union) + << CountFD->getSourceRange(); + return true; + } + // Whether CountRD is an anonymous struct is not determined at this + // point. Thus, an additional diagnostic in case it's not anonymous struct + // is done later in `Parser::ParseStructDeclaration`. + auto *RD = GetEnclosingNamedOrTopAnonRecord(FD); + auto *CountRD = GetEnclosingNamedOrTopAnonRecord(CountFD); + + if (RD != CountRD) { + S.Diag(E->getBeginLoc(), + diag::err_flexible_array_count_not_in_same_struct) + << CountFD << E->getSourceRange(); + S.Diag(CountFD->getBeginLoc(), + diag::note_flexible_array_counted_by_attr_field) + << CountFD << CountFD->getSourceRange(); + return true; } - - CXXScopeSpec SS; - DeclFilterCCC<FieldDecl> Filter(FieldName); - return DiagnoseEmptyLookup(S, SS, MemResult, Filter, nullptr, std::nullopt, - const_cast<DeclContext *>(FD->getDeclContext())); } - if (CountFD->hasAttr<CountedByAttr>()) { - // The "counted_by" field can't point to the flexible array member. - SourceRange SR = CBA->getCountedByFieldLoc(); - Diag(SR.getBegin(), diag::err_counted_by_attr_refers_to_flexible_array) - << CBA->getCountedByField() << SR; - return true; - } + Decls.push_back(TypeCoupledDeclRefInfo(CountFD, /*IsDref*/ false)); + return false; +} - if (!CountFD->getType()->isIntegerType() || - CountFD->getType()->isBooleanType()) { - // The "counted_by" field must have an integer type. - SourceRange SR = CBA->getCountedByFieldLoc(); - Diag(SR.getBegin(), - diag::err_flexible_array_counted_by_attr_field_not_integer) - << CBA->getCountedByField() << SR; +static void handleCountedByAttrField(Sema &S, Decl *D, const ParsedAttr &AL) { + auto *FD = dyn_cast<FieldDecl>(D); + assert(FD); - SR = CountFD->getLocation(); - Diag(SR.getBegin(), diag::note_flexible_array_counted_by_attr_field) - << CountFD << SR; - return true; - } + auto *CountExpr = AL.getArgAsExpr(0); + if (!CountExpr) + return; - return false; + llvm::SmallVector<TypeCoupledDeclRefInfo, 1> Decls; + if (CheckCountExpr(S, FD, CountExpr, Decls)) + return; + + QualType CAT = S.BuildCountAttributedArrayType(FD->getType(), CountExpr); + FD->setType(CAT); } static void handleFunctionReturnThunksAttr(Sema &S, Decl *D, @@ -9632,6 +9657,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_AMDGPUKernelCall: case ParsedAttr::AT_M68kRTD: case ParsedAttr::AT_PreserveNone: + case ParsedAttr::AT_RISCVVectorCC: handleCallConvAttr(S, D, AL); break; case ParsedAttr::AT_Suppress: @@ -9680,7 +9706,7 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, break; case ParsedAttr::AT_CountedBy: - handleCountedByAttr(S, D, AL); + handleCountedByAttrField(S, D, AL); break; // Microsoft attributes: @@ -9921,6 +9947,10 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_UsingIfExists: handleSimpleAttribute<UsingIfExistsAttr>(S, D, AL); break; + + case ParsedAttr::AT_TypeNullable: + handleNullableTypeAttr(S, D, AL); + break; } } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e258a4f7c894154a062757bb06924166709df94f..f32ff396f8a54356a898e00415c47b1d1aa82ed7 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -5282,7 +5282,7 @@ static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) { return true; while (const ConstantArrayType *ArrayT = Context.getAsConstantArrayType(T)) { - if (!ArrayT->getSize()) + if (ArrayT->isZeroSize()) return true; T = ArrayT->getElementType(); @@ -9738,7 +9738,8 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, return false; CXXRecordDecl *RD = MD->getParent(); assert(!RD->isDependentType() && "do deletion after instantiation"); - if (!LangOpts.CPlusPlus11 || RD->isInvalidDecl()) + if (!LangOpts.CPlusPlus || (!LangOpts.CPlusPlus11 && !RD->isLambda()) || + RD->isInvalidDecl()) return false; // C++11 [expr.lambda.prim]p19: @@ -11352,7 +11353,7 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { if (ConvType->isUndeducedAutoType()) { Diag(Conversion->getTypeSpecStartLoc(), diag::err_auto_not_allowed) << getReturnTypeLoc(Conversion).getSourceRange() - << llvm::to_underlying(ConvType->getAs<AutoType>()->getKeyword()) + << llvm::to_underlying(ConvType->castAs<AutoType>()->getKeyword()) << /* in declaration of conversion function template= */ 24; } @@ -13588,6 +13589,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS, Diag(UsingLoc, diag::err_alias_template_extra_headers) << SourceRange(TemplateParamLists[1]->getTemplateLoc(), TemplateParamLists[TemplateParamLists.size()-1]->getRAngleLoc()); + Invalid = true; } TemplateParameterList *TemplateParams = TemplateParamLists[0]; @@ -16201,7 +16203,8 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { // Emit warning for non-trivial dtor in global scope (a real global, // class-static, function-static). - Diag(VD->getLocation(), diag::warn_exit_time_destructor); + if (!VD->hasAttr<AlwaysDestroyAttr>()) + Diag(VD->getLocation(), diag::warn_exit_time_destructor); // TODO: this should be re-enabled for static locals by !CXAAtExit if (!VD->isStaticLocal()) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 93f82e68ab644047ec31fbc03150060bda3358f9..80b4257d9d83eda83f0fe2dbc34e9083fb210525 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -658,8 +658,9 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { QualType T = E->getType(); assert(!T.isNull() && "r-value conversion on typeless expression?"); - // lvalue-to-rvalue conversion cannot be applied to function or array types. - if (T->isFunctionType() || T->isArrayType()) + // lvalue-to-rvalue conversion cannot be applied to types that decay to + // pointers (i.e. function or array types). + if (T->canDecayToPointerType()) return E; // We don't want to throw lvalue-to-rvalue casts on top of @@ -1099,12 +1100,13 @@ ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, return E; } -/// Converts an integer to complex float type. Helper function of +/// Convert complex integers to complex floats and real integers to +/// real floats as required for complex arithmetic. Helper function of /// UsualArithmeticConversions() /// /// \return false if the integer expression is an integer type and is -/// successfully converted to the complex type. -static bool handleIntegerToComplexFloatConversion(Sema &S, ExprResult &IntExpr, +/// successfully converted to the (complex) float type. +static bool handleComplexIntegerToFloatConversion(Sema &S, ExprResult &IntExpr, ExprResult &ComplexExpr, QualType IntTy, QualType ComplexTy, @@ -1114,8 +1116,6 @@ static bool handleIntegerToComplexFloatConversion(Sema &S, ExprResult &IntExpr, if (IntTy->isIntegerType()) { QualType fpTy = ComplexTy->castAs<ComplexType>()->getElementType(); IntExpr = S.ImpCastExprToType(IntExpr.get(), fpTy, CK_IntegralToFloating); - IntExpr = S.ImpCastExprToType(IntExpr.get(), ComplexTy, - CK_FloatingRealToComplex); } else { assert(IntTy->isComplexIntegerType()); IntExpr = S.ImpCastExprToType(IntExpr.get(), ComplexTy, @@ -1160,11 +1160,11 @@ static QualType handleComplexFloatConversion(Sema &S, ExprResult &Shorter, static QualType handleComplexConversion(Sema &S, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, bool IsCompAssign) { - // if we have an integer operand, the result is the complex type. - if (!handleIntegerToComplexFloatConversion(S, RHS, LHS, RHSType, LHSType, + // Handle (complex) integer types. + if (!handleComplexIntegerToFloatConversion(S, RHS, LHS, RHSType, LHSType, /*SkipCast=*/false)) return LHSType; - if (!handleIntegerToComplexFloatConversion(S, LHS, RHS, LHSType, RHSType, + if (!handleComplexIntegerToFloatConversion(S, LHS, RHS, LHSType, RHSType, /*SkipCast=*/IsCompAssign)) return RHSType; @@ -2738,6 +2738,24 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, IsAddressOfOperand, TemplateArgs); + // BoundsSafety: This specially handles arguments of bounds attributes + // appertains to a type of C struct field such that the name lookup + // within a struct finds the member name, which is not the case for other + // contexts in C. + if (isBoundsAttrContext() && !getLangOpts().CPlusPlus && S->isClassScope()) { + // See if this is reference to a field of struct. + LookupResult R(*this, NameInfo, LookupMemberName); + // LookupParsedName handles a name lookup from within anonymous struct. + if (LookupParsedName(R, S, &SS)) { + if (auto *VD = dyn_cast<ValueDecl>(R.getFoundDecl())) { + QualType type = VD->getType().getNonReferenceType(); + // This will eventually be translated into MemberExpr upon + // the use of instantiated struct fields. + return BuildDeclRefExpr(VD, type, VK_PRValue, NameLoc); + } + } + } + // Perform the required lookup. LookupResult R(*this, NameInfo, (Id.getKind() == UnqualifiedIdKind::IK_ImplicitSelfParam) @@ -2894,7 +2912,8 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // to get this right here so that we don't end up making a // spuriously dependent expression if we're inside a dependent // instance method. - if (!R.empty() && (*R.begin())->isCXXClassMember()) { + if (getLangOpts().CPlusPlus && !R.empty() && + (*R.begin())->isCXXClassMember()) { bool MightBeImplicitMember; if (!IsAddressOfOperand) MightBeImplicitMember = true; @@ -3550,7 +3569,8 @@ ExprResult Sema::BuildDeclarationNameExpr( case Decl::Field: case Decl::IndirectField: case Decl::ObjCIvar: - assert(getLangOpts().CPlusPlus && "building reference to field in C?"); + assert((getLangOpts().CPlusPlus || isBoundsAttrContext()) && + "building reference to field in C?"); // These can't have reference type in well-formed programs, but // for internal consistency we do this anyway. @@ -3741,7 +3761,10 @@ ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc, else { // Pre-defined identifiers are of type char[x], where x is the length of // the string. - auto Str = PredefinedExpr::ComputeName(IK, currentDecl); + bool ForceElaboratedPrinting = + IK == PredefinedIdentKind::Function && getLangOpts().MSVCCompat; + auto Str = + PredefinedExpr::ComputeName(IK, currentDecl, ForceElaboratedPrinting); unsigned Length = Str.length(); llvm::APInt LengthI(32, Length + 1); @@ -4664,6 +4687,9 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T, case Type::Decayed: T = cast<DecayedType>(Ty)->getPointeeType(); break; + case Type::ArrayParameter: + T = cast<ArrayParameterType>(Ty)->getElementType(); + break; case Type::Pointer: T = cast<PointerType>(Ty)->getPointeeType(); break; @@ -4707,6 +4733,7 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T, case Type::BTFTagAttributed: case Type::SubstTemplateTypeParm: case Type::MacroQualified: + case Type::CountAttributed: // Keep walking after single level desugaring. T = T.getSingleStepDesugaredType(Context); break; @@ -6834,9 +6861,8 @@ Sema::CheckStaticArrayArgument(SourceLocation CallLoc, ArgCAT->getElementType())) { if (ArgCAT->getSize().ult(CAT->getSize())) { Diag(CallLoc, diag::warn_static_array_too_small) - << ArgExpr->getSourceRange() - << (unsigned)ArgCAT->getSize().getZExtValue() - << (unsigned)CAT->getSize().getZExtValue() << 0; + << ArgExpr->getSourceRange() << (unsigned)ArgCAT->getZExtSize() + << (unsigned)CAT->getZExtSize() << 0; DiagnoseCalleeStaticArrayParam(*this, Param); } return; @@ -12886,6 +12912,8 @@ static ImplicitConversionKind castKindToImplicitConversionKind(CastKind CK) { case CK_IntegralComplexToReal: case CK_IntegralRealToComplex: return ICK_Complex_Real; + case CK_HLSLArrayRValue: + return ICK_HLSL_Array_RValue; } } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index c34a40fa7c81ac9ac3d3c67371a1da05ebe17a92..76bb78aa8b5458fa2e7f9cd994ad9c05599def3f 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -4416,6 +4416,13 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, .get(); break; + case ICK_HLSL_Array_RValue: + FromType = Context.getArrayParameterType(FromType); + From = ImpCastExprToType(From, FromType, CK_HLSLArrayRValue, VK_PRValue, + /*BasePath=*/nullptr, CCK) + .get(); + break; + case ICK_Function_To_Pointer: FromType = Context.getPointerType(FromType); From = ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay, @@ -4793,6 +4800,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, case ICK_Num_Conversion_Kinds: case ICK_C_Only_Conversion: case ICK_Incompatible_Pointer_Conversion: + case ICK_HLSL_Array_RValue: llvm_unreachable("Improper second standard conversion"); } @@ -6083,7 +6091,7 @@ static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT, if (Matched && T->isArrayType()) { if (const ConstantArrayType *CAT = Self.Context.getAsConstantArrayType(T)) - return CAT->getSize().getLimitedValue(); + return CAT->getLimitedSize(); } } return 0; diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index aa470adb30b47f545e063cf7102c8c2ac7c32e02..e2a1951f1062cb7536b235492ef2de4457e27c64 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -213,7 +213,7 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, // Get the length of the string as parsed. auto *ConstantArrayTy = cast<ConstantArrayType>(Str->getType()->getAsArrayTypeUnsafe()); - uint64_t StrLength = ConstantArrayTy->getSize().getZExtValue(); + uint64_t StrLength = ConstantArrayTy->getZExtSize(); if (CheckC23ConstexprInit) if (const StringLiteral *SL = dyn_cast<StringLiteral>(Str->IgnoreParens())) @@ -246,14 +246,13 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, } // [dcl.init.string]p2 - if (StrLength > CAT->getSize().getZExtValue()) + if (StrLength > CAT->getZExtSize()) S.Diag(Str->getBeginLoc(), diag::err_initializer_string_for_char_array_too_long) - << CAT->getSize().getZExtValue() << StrLength - << Str->getSourceRange(); + << CAT->getZExtSize() << StrLength << Str->getSourceRange(); } else { // C99 6.7.8p14. - if (StrLength-1 > CAT->getSize().getZExtValue()) + if (StrLength - 1 > CAT->getZExtSize()) S.Diag(Str->getBeginLoc(), diag::ext_initializer_string_for_char_array_too_long) << Str->getSourceRange(); @@ -879,7 +878,7 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) { ElementType = AType->getElementType(); if (const auto *CAType = dyn_cast<ConstantArrayType>(AType)) - NumElements = CAType->getSize().getZExtValue(); + NumElements = CAType->getZExtSize(); // For an array new with an unknown bound, ask for one additional element // in order to populate the array filler. if (Entity.isVariableLengthArrayNew()) @@ -1016,7 +1015,7 @@ int InitListChecker::numArrayElements(QualType DeclType) { int maxElements = 0x7FFFFFFF; if (const ConstantArrayType *CAT = SemaRef.Context.getAsConstantArrayType(DeclType)) { - maxElements = static_cast<int>(CAT->getSize().getZExtValue()); + maxElements = static_cast<int>(CAT->getZExtSize()); } return maxElements; } @@ -2330,11 +2329,11 @@ void InitListChecker::CheckStructUnionTypes( break; } - // We've already initialized a member of a union. We're done. + // We've already initialized a member of a union. We can stop entirely. if (InitializedSomething && RD->isUnion()) - break; + return; - // If we've hit the flexible array member at the end, we're done. + // Stop if we've hit a flexible array member. if (Field->getType()->isIncompleteArrayType()) break; @@ -2457,6 +2456,11 @@ void InitListChecker::CheckStructUnionTypes( else CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index, StructuredList, StructuredIndex); + + if (RD->isUnion() && StructuredList) { + // Initialize the first field within the union. + StructuredList->setInitializedFieldInUnion(*Field); + } } /// Expand a field designator that refers to a member of an @@ -3101,7 +3105,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // Get the length of the string. uint64_t StrLen = SL->getLength(); if (cast<ConstantArrayType>(AT)->getSize().ult(StrLen)) - StrLen = cast<ConstantArrayType>(AT)->getSize().getZExtValue(); + StrLen = cast<ConstantArrayType>(AT)->getZExtSize(); StructuredList->resizeInits(Context, StrLen); // Build a literal for each character in the string, and put them into @@ -3124,7 +3128,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // Get the length of the string. uint64_t StrLen = Str.size(); if (cast<ConstantArrayType>(AT)->getSize().ult(StrLen)) - StrLen = cast<ConstantArrayType>(AT)->getSize().getZExtValue(); + StrLen = cast<ConstantArrayType>(AT)->getZExtSize(); StructuredList->resizeInits(Context, StrLen); // Build a literal for each character in the string, and put them into @@ -3283,7 +3287,7 @@ InitListChecker::createInitListExpr(QualType CurrentObjectType, if (const ArrayType *AType = SemaRef.Context.getAsArrayType(CurrentObjectType)) { if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType)) { - NumElements = CAType->getSize().getZExtValue(); + NumElements = CAType->getZExtSize(); // Simple heuristic so that we don't allocate a very large // initializer with many empty entries at the end. if (NumElements > ExpectedNumInits) @@ -5492,7 +5496,7 @@ static void TryOrBuildParenListInitialization( // having k elements. if (const ConstantArrayType *CAT = S.getASTContext().getAsConstantArrayType(Entity.getType())) { - ArrayLength = CAT->getSize().getZExtValue(); + ArrayLength = CAT->getZExtSize(); ResultType = Entity.getType(); } else if (const VariableArrayType *VAT = S.getASTContext().getAsVariableArrayType(Entity.getType())) { @@ -6265,7 +6269,10 @@ void InitializationSequence::InitializeFrom(Sema &S, // initializer is a string literal, see 8.5.2. // - Otherwise, if the destination type is an array, the program is // ill-formed. - if (const ArrayType *DestAT = Context.getAsArrayType(DestType)) { + // - Except in HLSL, where non-decaying array parameters behave like + // non-array types for initialization. + if (DestType->isArrayType() && !DestType->isArrayParameterType()) { + const ArrayType *DestAT = Context.getAsArrayType(DestType); if (Initializer && isa<VariableArrayType>(DestAT)) { SetFailed(FK_VariableLengthArrayHasInitializer); return; @@ -7075,6 +7082,11 @@ PerformConstructorInitialization(Sema &S, hasCopyOrMoveCtorParam(S.Context, getConstructorInfo(Step.Function.FoundDecl)); + // A smart pointer constructed from a nullable pointer is nullable. + if (NumArgs == 1 && !Kind.isExplicitCast()) + S.diagnoseNullableToNonnullConversion( + Entity.getType(), Args.front()->getType(), Kind.getLocation()); + // Determine the arguments required to actually perform the constructor // call. if (S.CompleteConstructorCall(Constructor, Step.Type, Args, Loc, diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index d3a9c7abd0e94465f307691e6ba7b0ed2962de48..38237ee578079db65a94f5af9614cd1d744f0a6f 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -3243,6 +3243,10 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { case Type::Pipe: T = cast<PipeType>(T)->getElementType().getTypePtr(); continue; + + // Array parameter types are treated as fundamental types. + case Type::ArrayParameter: + break; } if (Queue.empty()) diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp index f08c1cb3a13ef525add8252751fe1bebf4dff677..2ddf9d70263a094d1cf0d9e7fa387247771521a5 100644 --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -713,7 +713,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc, return Import; } -void Sema::ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod) { +void Sema::ActOnAnnotModuleInclude(SourceLocation DirectiveLoc, Module *Mod) { checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext, true); BuildModuleInclude(DirectiveLoc, Mod); } @@ -723,9 +723,9 @@ void Sema::BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod) { // in that buffer do not qualify as module imports; they're just an // implementation detail of us building the module. // - // FIXME: Should we even get ActOnModuleInclude calls for those? + // FIXME: Should we even get ActOnAnnotModuleInclude calls for those? bool IsInModuleIncludes = - TUKind == TU_Module && + TUKind == TU_ClangModule && getSourceManager().isWrittenInMainFile(DirectiveLoc); // If we are really importing a module (not just checking layering) due to an @@ -752,7 +752,7 @@ void Sema::BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod) { } } -void Sema::ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod) { +void Sema::ActOnAnnotModuleBegin(SourceLocation DirectiveLoc, Module *Mod) { checkModuleImportContext(*this, Mod, DirectiveLoc, CurContext, true); ModuleScopes.push_back({}); @@ -776,7 +776,7 @@ void Sema::ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod) { } } -void Sema::ActOnModuleEnd(SourceLocation EomLoc, Module *Mod) { +void Sema::ActOnAnnotModuleEnd(SourceLocation EomLoc, Module *Mod) { if (getLangOpts().ModulesLocalVisibility) { VisibleModules = std::move(ModuleScopes.back().OuterVisibleModules); // Leaving a module hides namespace names, so our visible namespace cache diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index 4636d89ebf2b84f5d817509495f5e3a6cb551c5e..f9e1ad0121e2a2ab9579674b7170598a0280bc05 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -638,8 +638,6 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, PDecl->setInvalidDecl(); } - ProcessDeclAttributes(S, PDecl, FD.D); - // Regardless of setter/getter attribute, we save the default getter/setter // selector names in anticipation of declaration of setter/getter methods. PDecl->setGetterName(GetterSel, GetterNameLoc); @@ -647,6 +645,8 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, PDecl->setPropertyAttributesAsWritten( makePropertyAttributesAsWritten(AttributesAsWritten)); + ProcessDeclAttributes(S, PDecl, FD.D); + if (Attributes & ObjCPropertyAttribute::kind_readonly) PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_readonly); diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index d3a602d1c382fa601b7eda1c369402a20bc0fc72..2ac994cac71e199ba08673813f6d4e939f09c43c 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -11,14 +11,15 @@ /// //===----------------------------------------------------------------------===// +#include "clang/AST/StmtOpenACC.h" +#include "clang/Sema/SemaOpenACC.h" #include "clang/Basic/DiagnosticSema.h" -#include "clang/Basic/OpenACCKinds.h" #include "clang/Sema/Sema.h" using namespace clang; namespace { -bool diagnoseConstructAppertainment(Sema &S, OpenACCDirectiveKind K, +bool diagnoseConstructAppertainment(SemaOpenACC &S, OpenACCDirectiveKind K, SourceLocation StartLoc, bool IsStmt) { switch (K) { default: @@ -30,14 +31,21 @@ bool diagnoseConstructAppertainment(Sema &S, OpenACCDirectiveKind K, case OpenACCDirectiveKind::Serial: case OpenACCDirectiveKind::Kernels: if (!IsStmt) - return S.Diag(StartLoc, diag::err_acc_construct_appertainment) << K; + return S.SemaRef.Diag(StartLoc, diag::err_acc_construct_appertainment) + << K; break; } return false; } } // namespace -bool Sema::ActOnOpenACCClause(OpenACCClauseKind ClauseKind, +SemaOpenACC::SemaOpenACC(Sema &S) : SemaRef(S) {} + +ASTContext &SemaOpenACC::getASTContext() const { return SemaRef.Context; } +DiagnosticsEngine &SemaOpenACC::getDiagnostics() const { return SemaRef.Diags; } +const LangOptions &SemaOpenACC::getLangOpts() const { return SemaRef.LangOpts; } + +bool SemaOpenACC::ActOnClause(OpenACCClauseKind ClauseKind, SourceLocation StartLoc) { if (ClauseKind == OpenACCClauseKind::Invalid) return false; @@ -45,9 +53,10 @@ bool Sema::ActOnOpenACCClause(OpenACCClauseKind ClauseKind, // whatever it can do. This function will eventually need to start returning // some sort of Clause AST type, but for now just return true/false based on // success. - return Diag(StartLoc, diag::warn_acc_clause_unimplemented) << ClauseKind; + return SemaRef.Diag(StartLoc, diag::warn_acc_clause_unimplemented) + << ClauseKind; } -void Sema::ActOnOpenACCConstruct(OpenACCDirectiveKind K, +void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K, SourceLocation StartLoc) { switch (K) { case OpenACCDirectiveKind::Invalid: @@ -63,17 +72,17 @@ void Sema::ActOnOpenACCConstruct(OpenACCDirectiveKind K, // here as these constructs do not take any arguments. break; default: - Diag(StartLoc, diag::warn_acc_construct_unimplemented) << K; + SemaRef.Diag(StartLoc, diag::warn_acc_construct_unimplemented) << K; break; } } -bool Sema::ActOnStartOpenACCStmtDirective(OpenACCDirectiveKind K, +bool SemaOpenACC::ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc) { return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true); } -StmtResult Sema::ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K, +StmtResult SemaOpenACC::ActOnEndStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation EndLoc, StmtResult AssocStmt) { @@ -92,7 +101,7 @@ StmtResult Sema::ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K, llvm_unreachable("Unhandled case in directive handling?"); } -StmtResult Sema::ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K, +StmtResult SemaOpenACC::ActOnAssociatedStmt(OpenACCDirectiveKind K, StmtResult AssocStmt) { switch (K) { default: @@ -114,9 +123,9 @@ StmtResult Sema::ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K, llvm_unreachable("Invalid associated statement application"); } -bool Sema::ActOnStartOpenACCDeclDirective(OpenACCDirectiveKind K, +bool SemaOpenACC::ActOnStartDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc) { return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/false); } -DeclGroupRef Sema::ActOnEndOpenACCDeclDirective() { return DeclGroupRef{}; } +DeclGroupRef SemaOpenACC::ActOnEndDeclDirective() { return DeclGroupRef{}; } diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 0cc0cbacb375489dd7d2d596d81bb7a4dfe8745d..0ba54a3a9cae3565bffc667b0b22e7ce3c825da1 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -14366,7 +14366,8 @@ StmtResult Sema::ActOnOpenMPTargetParallelForSimdDirective( // The point of exit cannot be a branch out of the structured block. // longjmp() and throw() must not violate the entry/exit criteria. CS->getCapturedDecl()->setNothrow(); - for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for); + for (int ThisCaptureLevel = + getOpenMPCaptureLevels(OMPD_target_parallel_for_simd); ThisCaptureLevel > 1; --ThisCaptureLevel) { CS = cast<CapturedStmt>(CS->getCapturedStmt()); // 1.2.2 OpenMP Language Terminology @@ -21283,7 +21284,7 @@ static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, if (isa<ArraySubscriptExpr>(E) || (OASE && OASE->getColonLocFirst().isInvalid())) { if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) - return ATy->getSize().getSExtValue() != 1; + return ATy->getSExtSize() != 1; // Size can't be evaluated statically. return false; } @@ -21324,7 +21325,7 @@ static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, return false; // Can't get the integer value as a constant. llvm::APSInt ConstLength = Result.Val.getInt(); - return CATy->getSize().getSExtValue() != ConstLength.getSExtValue(); + return CATy->getSExtSize() != ConstLength.getSExtValue(); } // Return true if it can be proven that the provided array expression (array @@ -21349,7 +21350,7 @@ static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef, // is pointer. if (!Length) { if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) - return ATy->getSize().getSExtValue() != 1; + return ATy->getSExtSize() != 1; // We cannot assume anything. return false; } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index f6bd85bdc64692e3de882b9006694bdf40e505eb..0c913bc700f4a1908cd3617d0c97c9bacb4438b7 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -160,6 +160,7 @@ ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) { ICR_C_Conversion_Extension, ICR_Conversion, ICR_Conversion, + ICR_Conversion, }; static_assert(std::size(Rank) == (int)ICK_Num_Conversion_Kinds); return Rank[(int)Kind]; @@ -201,6 +202,7 @@ static const char *GetImplicitConversionName(ImplicitConversionKind Kind) { "Incompatible pointer conversion", "Fixed point conversion", "HLSL vector truncation", + "Non-decaying array conversion", }; static_assert(std::size(Name) == (int)ICK_Num_Conversion_Kinds); return Name[Kind]; @@ -2131,8 +2133,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // A glvalue (3.10) of a non-function, non-array type T can // be converted to a prvalue. bool argIsLValue = From->isGLValue(); - if (argIsLValue && - !FromType->isFunctionType() && !FromType->isArrayType() && + if (argIsLValue && !FromType->canDecayToPointerType() && S.Context.getCanonicalType(FromType) != S.Context.OverloadTy) { SCS.First = ICK_Lvalue_To_Rvalue; @@ -2147,6 +2148,19 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // is T (C++ 4.1p1). C++ can't get here with class types; in C, we // just strip the qualifiers because they don't matter. FromType = FromType.getUnqualifiedType(); + } else if (S.getLangOpts().HLSL && FromType->isConstantArrayType() && + ToType->isArrayParameterType()) { + // HLSL constant array parameters do not decay, so if the argument is a + // constant array and the parameter is an ArrayParameterType we have special + // handling here. + FromType = S.Context.getArrayParameterType(FromType); + if (S.Context.getCanonicalType(FromType) != + S.Context.getCanonicalType(ToType)) + return false; + + SCS.First = ICK_HLSL_Array_RValue; + SCS.setAllToTypes(ToType); + return true; } else if (FromType->isArrayType()) { // Array-to-pointer conversion (C++ 4.2) SCS.First = ICK_Array_To_Pointer; @@ -6100,6 +6114,7 @@ static bool CheckConvertedConstantConversions(Sema &S, case ICK_Lvalue_To_Rvalue: case ICK_Array_To_Pointer: case ICK_Function_To_Pointer: + case ICK_HLSL_Array_RValue: llvm_unreachable("found a first conversion kind in Second"); case ICK_Function_Conversion: @@ -6865,6 +6880,32 @@ static bool IsAcceptableNonMemberOperatorCandidate(ASTContext &Context, return false; } +static bool isNonViableMultiVersionOverload(FunctionDecl *FD) { + if (FD->isTargetMultiVersionDefault()) + return false; + + if (!FD->getASTContext().getTargetInfo().getTriple().isAArch64()) + return FD->isTargetMultiVersion(); + + if (!FD->isMultiVersion()) + return false; + + // Among multiple target versions consider either the default, + // or the first non-default in the absence of default version. + unsigned SeenAt = 0; + unsigned I = 0; + bool HasDefault = false; + FD->getASTContext().forEachMultiversionedFunctionVersion( + FD, [&](const FunctionDecl *CurFD) { + if (FD == CurFD) + SeenAt = I; + else if (CurFD->isTargetMultiVersionDefault()) + HasDefault = true; + ++I; + }); + return HasDefault || SeenAt != 0; +} + /// AddOverloadCandidate - Adds the given function to the set of /// candidate functions, using the given function call arguments. If /// @p SuppressUserConversions, then don't allow user-defined @@ -6970,11 +7011,7 @@ void Sema::AddOverloadCandidate( } } - if (Function->isMultiVersion() && - ((Function->hasAttr<TargetAttr>() && - !Function->getAttr<TargetAttr>()->isDefaultVersion()) || - (Function->hasAttr<TargetVersionAttr>() && - !Function->getAttr<TargetVersionAttr>()->isDefaultVersion()))) { + if (isNonViableMultiVersionOverload(Function)) { Candidate.Viable = false; Candidate.FailureKind = ovl_non_default_multiversion_function; return; @@ -7637,11 +7674,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, return; } - if (Method->isMultiVersion() && - ((Method->hasAttr<TargetAttr>() && - !Method->getAttr<TargetAttr>()->isDefaultVersion()) || - (Method->hasAttr<TargetVersionAttr>() && - !Method->getAttr<TargetVersionAttr>()->isDefaultVersion()))) { + if (isNonViableMultiVersionOverload(Method)) { Candidate.Viable = false; Candidate.FailureKind = ovl_non_default_multiversion_function; } @@ -8127,11 +8160,7 @@ void Sema::AddConversionCandidate( return; } - if (Conversion->isMultiVersion() && - ((Conversion->hasAttr<TargetAttr>() && - !Conversion->getAttr<TargetAttr>()->isDefaultVersion()) || - (Conversion->hasAttr<TargetVersionAttr>() && - !Conversion->getAttr<TargetVersionAttr>()->isDefaultVersion()))) { + if (isNonViableMultiVersionOverload(Conversion)) { Candidate.Viable = false; Candidate.FailureKind = ovl_non_default_multiversion_function; } @@ -14797,6 +14826,13 @@ ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, } } + // Check for nonnull = nullable. + // This won't be caught in the arg's initialization: the parameter to + // the assignment operator is not marked nonnull. + if (Op == OO_Equal) + diagnoseNullableToNonnullConversion(Args[0]->getType(), + Args[1]->getType(), OpLoc); + // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { // Best->Access is only meaningful for class members. diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index ca0254d29e7f408a2499a895b428606933dcd3f5..18ebaa13346a443ee9bbff8346b2dbacc94271cf 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -35,7 +35,7 @@ Sema::SemaDiagnosticBuilder Sema::SYCLDiagIfDeviceCode(SourceLocation Loc, static bool isZeroSizedArray(Sema &SemaRef, QualType Ty) { if (const auto *CAT = SemaRef.getASTContext().getAsConstantArrayType(Ty)) - return CAT->getSize() == 0; + return CAT->isZeroSize(); return false; } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index d8c9a5c09944c4344655192d4a6c4aeaae433d03..a2b8cc14ca764f1f8d9c775fdcb703453e41aee4 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1156,6 +1156,7 @@ bool Sema::BuildTypeConstraint(const CXXScopeSpec &SS, TemplateName TN = TypeConstr->Template.get(); ConceptDecl *CD = cast<ConceptDecl>(TN.getAsTemplateDecl()); + UsingShadowDecl *USD = TN.getAsUsingShadowDecl(); DeclarationNameInfo ConceptName(DeclarationName(TypeConstr->Name), TypeConstr->TemplateNameLoc); @@ -1174,15 +1175,15 @@ bool Sema::BuildTypeConstraint(const CXXScopeSpec &SS, } return AttachTypeConstraint( SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc(), - ConceptName, CD, + ConceptName, CD, /*FoundDecl=*/USD ? cast<NamedDecl>(USD) : CD, TypeConstr->LAngleLoc.isValid() ? &TemplateArgs : nullptr, ConstrainedParameter, EllipsisLoc); } -template<typename ArgumentLocAppender> +template <typename ArgumentLocAppender> static ExprResult formImmediatelyDeclaredConstraint( Sema &S, NestedNameSpecifierLoc NS, DeclarationNameInfo NameInfo, - ConceptDecl *NamedConcept, SourceLocation LAngleLoc, + ConceptDecl *NamedConcept, NamedDecl *FoundDecl, SourceLocation LAngleLoc, SourceLocation RAngleLoc, QualType ConstrainedType, SourceLocation ParamNameLoc, ArgumentLocAppender Appender, SourceLocation EllipsisLoc) { @@ -1203,7 +1204,8 @@ static ExprResult formImmediatelyDeclaredConstraint( SS.Adopt(NS); ExprResult ImmediatelyDeclaredConstraint = S.CheckConceptTemplateId( SS, /*TemplateKWLoc=*/SourceLocation(), NameInfo, - /*FoundDecl=*/NamedConcept, NamedConcept, &ConstraintArgs); + /*FoundDecl=*/FoundDecl ? FoundDecl : NamedConcept, NamedConcept, + &ConstraintArgs); if (ImmediatelyDeclaredConstraint.isInvalid() || !EllipsisLoc.isValid()) return ImmediatelyDeclaredConstraint; @@ -1233,7 +1235,7 @@ static ExprResult formImmediatelyDeclaredConstraint( /// of arguments for the named concept). bool Sema::AttachTypeConstraint(NestedNameSpecifierLoc NS, DeclarationNameInfo NameInfo, - ConceptDecl *NamedConcept, + ConceptDecl *NamedConcept, NamedDecl *FoundDecl, const TemplateArgumentListInfo *TemplateArgs, TemplateTypeParmDecl *ConstrainedParameter, SourceLocation EllipsisLoc) { @@ -1246,24 +1248,24 @@ bool Sema::AttachTypeConstraint(NestedNameSpecifierLoc NS, QualType ParamAsArgument(ConstrainedParameter->getTypeForDecl(), 0); - ExprResult ImmediatelyDeclaredConstraint = - formImmediatelyDeclaredConstraint( - *this, NS, NameInfo, NamedConcept, - TemplateArgs ? TemplateArgs->getLAngleLoc() : SourceLocation(), - TemplateArgs ? TemplateArgs->getRAngleLoc() : SourceLocation(), - ParamAsArgument, ConstrainedParameter->getLocation(), - [&] (TemplateArgumentListInfo &ConstraintArgs) { - if (TemplateArgs) - for (const auto &ArgLoc : TemplateArgs->arguments()) - ConstraintArgs.addArgument(ArgLoc); - }, EllipsisLoc); + ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint( + *this, NS, NameInfo, NamedConcept, FoundDecl, + TemplateArgs ? TemplateArgs->getLAngleLoc() : SourceLocation(), + TemplateArgs ? TemplateArgs->getRAngleLoc() : SourceLocation(), + ParamAsArgument, ConstrainedParameter->getLocation(), + [&](TemplateArgumentListInfo &ConstraintArgs) { + if (TemplateArgs) + for (const auto &ArgLoc : TemplateArgs->arguments()) + ConstraintArgs.addArgument(ArgLoc); + }, + EllipsisLoc); if (ImmediatelyDeclaredConstraint.isInvalid()) return true; auto *CL = ConceptReference::Create(Context, /*NNS=*/NS, /*TemplateKWLoc=*/SourceLocation{}, /*ConceptNameInfo=*/NameInfo, - /*FoundDecl=*/NamedConcept, + /*FoundDecl=*/FoundDecl, /*NamedConcept=*/NamedConcept, /*ArgsWritten=*/ArgsAsWritten); ConstrainedParameter->setTypeConstraint(CL, @@ -1293,8 +1295,9 @@ bool Sema::AttachTypeConstraint(AutoTypeLoc TL, return true; ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint( *this, TL.getNestedNameSpecifierLoc(), TL.getConceptNameInfo(), - TL.getNamedConcept(), TL.getLAngleLoc(), TL.getRAngleLoc(), - BuildDecltypeType(Ref), OrigConstrainedParm->getLocation(), + TL.getNamedConcept(), /*FoundDecl=*/TL.getFoundDecl(), TL.getLAngleLoc(), + TL.getRAngleLoc(), BuildDecltypeType(Ref), + OrigConstrainedParm->getLocation(), [&](TemplateArgumentListInfo &ConstraintArgs) { for (unsigned I = 0, C = TL.getNumArgs(); I != C; ++I) ConstraintArgs.addArgument(TL.getArgLoc(I)); @@ -1833,7 +1836,27 @@ static TemplateParameterList *GetTemplateParameterList(TemplateDecl *TD) { // Make sure we get the template parameter list from the most // recent declaration, since that is the only one that is guaranteed to // have all the default template argument information. - return cast<TemplateDecl>(TD->getMostRecentDecl())->getTemplateParameters(); + Decl *D = TD->getMostRecentDecl(); + // C++11 N3337 [temp.param]p12: + // A default template argument shall not be specified in a friend class + // template declaration. + // + // Skip past friend *declarations* because they are not supposed to contain + // default template arguments. Moreover, these declarations may introduce + // template parameters living in different template depths than the + // corresponding template parameters in TD, causing unmatched constraint + // substitution. + // + // FIXME: Diagnose such cases within a class template: + // template <class T> + // struct S { + // template <class = void> friend struct C; + // }; + // template struct S<int>; + while (D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None && + D->getPreviousDecl()) + D = D->getPreviousDecl(); + return cast<TemplateDecl>(D)->getTemplateParameters(); } DeclResult Sema::CheckClassTemplate( @@ -2168,6 +2191,7 @@ DeclResult Sema::CheckClassTemplate( AddPushedVisibilityAttribute(NewClass); inferGslOwnerPointerAttribute(NewClass); + inferNullableClassAttribute(NewClass); if (TUK != TUK_Friend) { // Per C++ [basic.scope.temp]p2, skip the template parameter scopes. @@ -2696,6 +2720,12 @@ SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList( return true; } + bool TraverseTemplateName(TemplateName Template) { + if (auto *TD = Template.getAsTemplateDecl()) + MarkAppeared(TD); + return RecursiveASTVisitor::TraverseTemplateName(Template); + } + void MarkAppeared(NamedDecl *ND) { if (TemplateParams.contains(ND)) ReferencedTemplateParams.insert(ND); @@ -2728,6 +2758,8 @@ bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) { // Build deduction guides for a type alias template. void DeclareImplicitDeductionGuidesForTypeAlias( Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) { + if (AliasTemplate->isInvalidDecl()) + return; auto &Context = SemaRef.Context; // FIXME: if there is an explicit deduction guide after the first use of the // type alias usage, we will not cover this explicit deduction guide. fix this @@ -2906,18 +2938,27 @@ void DeclareImplicitDeductionGuidesForTypeAlias( Context.getCanonicalTemplateArgument( Context.getInjectedTemplateArg(NewParam)); } - // FIXME: implement the associated constraint per C++ + // Substitute new template parameters into requires-clause if present. + Expr *RequiresClause = nullptr; + if (Expr *InnerRC = F->getTemplateParameters()->getRequiresClause()) { + MultiLevelTemplateArgumentList Args; + Args.setKind(TemplateSubstitutionKind::Rewrite); + Args.addOuterTemplateArguments(TemplateArgsForBuildingFPrime); + ExprResult E = SemaRef.SubstExpr(InnerRC, Args); + if (E.isInvalid()) + return; + RequiresClause = E.getAs<Expr>(); + } + // FIXME: implement the is_deducible constraint per C++ // [over.match.class.deduct]p3.3: - // The associated constraints ([temp.constr.decl]) are the - // conjunction of the associated constraints of g and a - // constraint that is satisfied if and only if the arguments + // ... and a constraint that is satisfied if and only if the arguments // of A are deducible (see below) from the return type. auto *FPrimeTemplateParamList = TemplateParameterList::Create( Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(), AliasTemplate->getTemplateParameters()->getLAngleLoc(), FPrimeTemplateParams, AliasTemplate->getTemplateParameters()->getRAngleLoc(), - /*RequiresClause=*/nullptr); + /*RequiresClause=*/RequiresClause); // To form a deduction guide f' from f, we leverage clang's instantiation // mechanism, we construct a template argument list where the template @@ -2962,7 +3003,7 @@ void DeclareImplicitDeductionGuidesForTypeAlias( if (auto *FPrime = SemaRef.InstantiateFunctionDeclaration( F, TemplateArgListForBuildingFPrime, AliasTemplate->getLocation(), Sema::CodeSynthesisContext::BuildingDeductionGuides)) { - auto *GG = dyn_cast<CXXDeductionGuideDecl>(FPrime); + auto *GG = cast<CXXDeductionGuideDecl>(FPrime); buildDeductionGuide(SemaRef, AliasTemplate, FPrimeTemplateParamList, GG->getCorrespondingConstructor(), GG->getExplicitSpecifier(), GG->getTypeSourceInfo(), @@ -5406,7 +5447,7 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, if (R.getAsSingle<ConceptDecl>()) { return CheckConceptTemplateId(SS, TemplateKWLoc, R.getLookupNameInfo(), - R.getFoundDecl(), + R.getRepresentativeDecl(), R.getAsSingle<ConceptDecl>(), TemplateArgs); } @@ -6864,6 +6905,11 @@ bool UnnamedLocalNoLinkageFinder::VisitBitIntType(const BitIntType *T) { return false; } +bool UnnamedLocalNoLinkageFinder::VisitArrayParameterType( + const ArrayParameterType *T) { + return VisitConstantArrayType(T); +} + bool UnnamedLocalNoLinkageFinder::VisitDependentBitIntType( const DependentBitIntType *T) { return false; diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 97f8445bf819c8fa4cb8da6a5a8356afaa35e571..716660244537b81d827b4eb2d82a44bb9da02dd2 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2277,6 +2277,7 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch( case Type::DependentTemplateSpecialization: case Type::PackExpansion: case Type::Pipe: + case Type::ArrayParameter: // No template argument deduction for these types return TemplateDeductionResult::Success; @@ -5514,9 +5515,9 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate( QualType Obj2Ty; if (TPOC == TPOC_Call) { const FunctionProtoType *Proto1 = - FD1->getType()->getAs<FunctionProtoType>(); + FD1->getType()->castAs<FunctionProtoType>(); const FunctionProtoType *Proto2 = - FD2->getType()->getAs<FunctionProtoType>(); + FD2->getType()->castAs<FunctionProtoType>(); // - In the context of a function call, the function parameter types are // used. @@ -6355,11 +6356,11 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, case Type::ConstantArray: case Type::IncompleteArray: + case Type::ArrayParameter: MarkUsedTemplateParameters(Ctx, cast<ArrayType>(T)->getElementType(), OnlyDeduced, Depth, Used); break; - case Type::Vector: case Type::ExtVector: MarkUsedTemplateParameters(Ctx, diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 1a0c88703aca01c49c2556ee2886bd9ed1d9ebc8..5e05cb4f790b8504039f5e777542f6d3ed6f7255 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2970,7 +2970,8 @@ bool Sema::SubstTypeConstraint( } return AttachTypeConstraint( TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(), - TC->getNamedConcept(), &InstArgs, Inst, + TC->getNamedConcept(), + /*FoundDecl=*/TC->getConceptReference()->getFoundDecl(), &InstArgs, Inst, Inst->isParameterPack() ? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint()) ->getEllipsisLoc() diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 8ef8bfdf2a7b56cc37809ece33c6e22c78ffb8a0..dc972018e7b2815042708edf6a3cab1942f096f3 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1727,6 +1727,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { assert(!Owner->isDependentContext()); Inst->setLexicalDeclContext(Owner); RecordInst->setLexicalDeclContext(Owner); + Inst->setObjectOfFriendDecl(); if (PrevClassTemplate) { Inst->setCommonPtr(PrevClassTemplate->getCommonPtr()); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 3148299f6467af7f260b10de9d820947ed305128..8762744396f4dd3b8938f01020cdaa2214f2d52a 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -138,7 +138,8 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr, case ParsedAttr::AT_PreserveMost: \ case ParsedAttr::AT_PreserveAll: \ case ParsedAttr::AT_M68kRTD: \ - case ParsedAttr::AT_PreserveNone + case ParsedAttr::AT_PreserveNone: \ + case ParsedAttr::AT_RISCVVectorCC // Function type attributes. #define FUNCTION_TYPE_ATTRS_CASELIST \ @@ -1018,6 +1019,11 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, return type; } + // Types that have __attribute__((NSObject)) are permitted. + if (typeArg->isObjCNSObjectType()) { + continue; + } + // Dependent types will be checked at instantiation time. if (typeArg->isDependentType()) { continue; @@ -3499,7 +3505,7 @@ InventTemplateParameter(TypeProcessingState &state, QualType T, if (!Invalid) { S.AttachTypeConstraint( AutoLoc.getNestedNameSpecifierLoc(), AutoLoc.getConceptNameInfo(), - AutoLoc.getNamedConcept(), + AutoLoc.getNamedConcept(), /*FoundDecl=*/AutoLoc.getFoundDecl(), AutoLoc.hasExplicitTemplateArgs() ? &TAL : nullptr, InventedTemplateParam, D.getEllipsisLoc()); } @@ -3525,11 +3531,17 @@ InventTemplateParameter(TypeProcessingState &state, QualType T, } } if (!Invalid) { + UsingShadowDecl *USD = + TemplateId->Template.get().getAsUsingShadowDecl(); + auto *CD = + cast<ConceptDecl>(TemplateId->Template.get().getAsTemplateDecl()); S.AttachTypeConstraint( D.getDeclSpec().getTypeSpecScope().getWithLocInContext(S.Context), DeclarationNameInfo(DeclarationName(TemplateId->Name), TemplateId->TemplateNameLoc), - cast<ConceptDecl>(TemplateId->Template.get().getAsTemplateDecl()), + CD, + /*FoundDecl=*/ + USD ? cast<NamedDecl>(USD) : CD, TemplateId->LAngleLoc.isValid() ? &TemplateArgsInfo : nullptr, InventedTemplateParam, D.getEllipsisLoc()); } @@ -4705,6 +4717,18 @@ static bool DiagnoseMultipleAddrSpaceAttributes(Sema &S, LangAS ASOld, return false; } +// Whether this is a type broadly expected to have nullability attached. +// These types are affected by `#pragma assume_nonnull`, and missing nullability +// will be diagnosed with -Wnullability-completeness. +static bool shouldHaveNullability(QualType T) { + return T->canHaveNullability(/*ResultIfUnknown=*/false) && + // For now, do not infer/require nullability on C++ smart pointers. + // It's unclear whether the pragma's behavior is useful for C++. + // e.g. treating type-aliases and template-type-parameters differently + // from types of declarations can be surprising. + !isa<RecordType>(T->getCanonicalTypeInternal()); +} + static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, QualType declSpecType, TypeSourceInfo *TInfo) { @@ -4823,8 +4847,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // inner pointers. complainAboutMissingNullability = CAMN_InnerPointers; - if (T->canHaveNullability(/*ResultIfUnknown*/ false) && - !T->getNullability()) { + if (shouldHaveNullability(T) && !T->getNullability()) { // Note that we allow but don't require nullability on dependent types. ++NumPointersRemaining; } @@ -5047,8 +5070,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // If the type itself could have nullability but does not, infer pointer // nullability and perform consistency checking. if (S.CodeSynthesisContexts.empty()) { - if (T->canHaveNullability(/*ResultIfUnknown*/ false) && - !T->getNullability()) { + if (shouldHaveNullability(T) && !T->getNullability()) { if (isVaList(T)) { // Record that we've seen a pointer, but do nothing else. if (NumPointersRemaining > 0) @@ -6423,9 +6445,12 @@ namespace { DeclarationNameInfo DNI = DeclarationNameInfo( TL.getTypePtr()->getTypeConstraintConcept()->getDeclName(), TemplateId->TemplateNameLoc); + auto TN = TemplateId->Template.get(); auto *CR = ConceptReference::Create( Context, NNS, TemplateId->TemplateKWLoc, DNI, - /*FoundDecl=*/nullptr, + /*FoundDecl=*/TN.getKind() == TemplateName::NameKind::UsingTemplate + ? cast<NamedDecl>(TN.getAsUsingShadowDecl()) + : cast_if_present<NamedDecl>(TN.getAsTemplateDecl()), /*NamedDecl=*/TL.getTypePtr()->getTypeConstraintConcept(), ASTTemplateArgumentListInfo::Create(Context, TemplateArgsInfo)); TL.setConceptReference(CR); @@ -6490,10 +6515,16 @@ namespace { void VisitDecayedTypeLoc(DecayedTypeLoc TL) { llvm_unreachable("decayed type locs not expected here!"); } + void VisitArrayParameterTypeLoc(ArrayParameterTypeLoc TL) { + llvm_unreachable("array parameter type locs not expected here!"); + } void VisitAttributedTypeLoc(AttributedTypeLoc TL) { fillAttributedTypeLoc(TL, State); } + void VisitCountAttributedTypeLoc(CountAttributedTypeLoc TL) { + // nothing + } void VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) { // nothing } @@ -7922,6 +7953,8 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) { return createSimpleAttr<M68kRTDAttr>(Ctx, Attr); case ParsedAttr::AT_PreserveNone: return createSimpleAttr<PreserveNoneAttr>(Ctx, Attr); + case ParsedAttr::AT_RISCVVectorCC: + return createSimpleAttr<RISCVVectorCCAttr>(Ctx, Attr); } llvm_unreachable("unexpected attribute kind!"); } @@ -9745,6 +9778,26 @@ QualType Sema::BuildTypeofExprType(Expr *E, TypeOfKind Kind) { return Context.getTypeOfExprType(E, Kind); } +static void +BuildTypeCoupledDecls(Expr *E, + llvm::SmallVectorImpl<TypeCoupledDeclRefInfo> &Decls) { + // Currently, 'counted_by' only allows direct DeclRefExpr to FieldDecl. + auto *CountDecl = cast<DeclRefExpr>(E)->getDecl(); + Decls.push_back(TypeCoupledDeclRefInfo(CountDecl, /*IsDref*/ false)); +} + +QualType Sema::BuildCountAttributedArrayType(QualType WrappedTy, + Expr *CountExpr) { + assert(WrappedTy->isIncompleteArrayType()); + + llvm::SmallVector<TypeCoupledDeclRefInfo, 1> Decls; + BuildTypeCoupledDecls(CountExpr, Decls); + /// When the resulting expression is invalid, we still create the AST using + /// the original count expression for the sake of AST dump. + return Context.getCountAttributedType( + WrappedTy, CountExpr, /*CountInBytes*/ false, /*OrNull*/ false, Decls); +} + /// getDecltypeForExpr - Given an expr, will return the decltype for /// that expression, according to the rules in C++11 /// [dcl.type.simple]p4 and C++11 [expr.lambda.prim]p18. diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 2d22692f3ab7502543bc78bdb6d6d9ffac584fc9..a2568ad0f82cc28b315c6d3f1b30dd1dcc0e25c3 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -39,6 +39,7 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaDiagnostic.h" #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/SemaOpenACC.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/ErrorHandling.h" #include <algorithm> @@ -4000,16 +4001,16 @@ public: SourceLocation BeginLoc, SourceLocation EndLoc, StmtResult StrBlock) { - getSema().ActOnOpenACCConstruct(K, BeginLoc); + getSema().OpenACC().ActOnConstruct(K, BeginLoc); // TODO OpenACC: Include clauses. - if (getSema().ActOnStartOpenACCStmtDirective(K, BeginLoc)) + if (getSema().OpenACC().ActOnStartStmtDirective(K, BeginLoc)) return StmtError(); - StrBlock = getSema().ActOnOpenACCAssociatedStmt(K, StrBlock); + StrBlock = getSema().OpenACC().ActOnAssociatedStmt(K, StrBlock); - return getSema().ActOnEndOpenACCStmtDirective(K, BeginLoc, EndLoc, - StrBlock); + return getSema().OpenACC().ActOnEndStmtDirective(K, BeginLoc, EndLoc, + StrBlock); } private: @@ -5243,6 +5244,23 @@ QualType TreeTransform<Derived>::TransformDecayedType(TypeLocBuilder &TLB, return Result; } +template <typename Derived> +QualType +TreeTransform<Derived>::TransformArrayParameterType(TypeLocBuilder &TLB, + ArrayParameterTypeLoc TL) { + QualType OriginalType = getDerived().TransformType(TLB, TL.getElementLoc()); + if (OriginalType.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + OriginalType != TL.getElementLoc().getType()) + Result = SemaRef.Context.getArrayParameterType(OriginalType); + TLB.push<ArrayParameterTypeLoc>(Result); + // Nothing to set for ArrayParameterTypeLoc. + return Result; +} + template<typename Derived> QualType TreeTransform<Derived>::TransformPointerType(TypeLocBuilder &TLB, PointerTypeLoc TL) { @@ -7269,6 +7287,34 @@ QualType TreeTransform<Derived>::TransformAttributedType(TypeLocBuilder &TLB, }); } +template <typename Derived> +QualType TreeTransform<Derived>::TransformCountAttributedType( + TypeLocBuilder &TLB, CountAttributedTypeLoc TL) { + const CountAttributedType *OldTy = TL.getTypePtr(); + QualType InnerTy = getDerived().TransformType(TLB, TL.getInnerLoc()); + if (InnerTy.isNull()) + return QualType(); + + Expr *OldCount = TL.getCountExpr(); + Expr *NewCount = nullptr; + if (OldCount) { + ExprResult CountResult = getDerived().TransformExpr(OldCount); + if (CountResult.isInvalid()) + return QualType(); + NewCount = CountResult.get(); + } + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || InnerTy != OldTy->desugar() || + OldCount != NewCount) { + // Currently, CountAttributedType can only wrap incomplete array types. + Result = SemaRef.BuildCountAttributedArrayType(InnerTy, NewCount); + } + + TLB.push<CountAttributedTypeLoc>(Result); + return Result; +} + template <typename Derived> QualType TreeTransform<Derived>::TransformBTFTagAttributedType( TypeLocBuilder &TLB, BTFTagAttributedTypeLoc TL) { @@ -13714,6 +13760,16 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { // Capturing 'this' is trivial. if (C->capturesThis()) { + // If this is a lambda that is part of a default member initialiser + // and which we're instantiating outside the class that 'this' is + // supposed to refer to, adjust the type of 'this' accordingly. + // + // Otherwise, leave the type of 'this' as-is. + Sema::CXXThisScopeRAII ThisScope( + getSema(), + dyn_cast_if_present<CXXRecordDecl>( + getSema().getFunctionLevelDeclContext()), + Qualifiers()); getSema().CheckCXXThisCapture(C->getLocation(), C->isExplicit(), /*BuildAndDiagnose*/ true, nullptr, C->getCaptureKind() == LCK_StarThis); diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index ede9f6e93469b7ea32c4c3bc5eb863f145ffe75f..004859ed22bf160a957c5d7058c2c37733a11b88 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -6810,6 +6810,10 @@ void TypeLocReader::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { // nothing to do } +void TypeLocReader::VisitArrayParameterTypeLoc(ArrayParameterTypeLoc TL) { + // nothing to do +} + void TypeLocReader::VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) { TL.setExpansionLoc(readSourceLocation()); } @@ -6995,6 +6999,10 @@ void TypeLocReader::VisitAttributedTypeLoc(AttributedTypeLoc TL) { TL.setAttr(ReadAttr()); } +void TypeLocReader::VisitCountAttributedTypeLoc(CountAttributedTypeLoc TL) { + // Nothing to do +} + void TypeLocReader::VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) { // Nothing to do. } @@ -9116,6 +9124,10 @@ DeclarationNameInfo ASTRecordReader::readDeclarationNameInfo() { return NameInfo; } +TypeCoupledDeclRefInfo ASTRecordReader::readTypeCoupledDeclRefInfo() { + return TypeCoupledDeclRefInfo(readDeclAs<ValueDecl>(), readBool()); +} + void ASTRecordReader::readQualifierInfo(QualifierInfo &Info) { Info.QualifierLoc = readNestedNameSpecifierLoc(); unsigned NumTPLists = readInt(); diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 674ed47581dfd3098fe5990fc1452483e993641e..bbeb6db011646fd3314a25e2a8f7024b53628719 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1047,30 +1047,22 @@ void ASTStmtReader::VisitMemberExpr(MemberExpr *E) { E->MemberDNLoc = Record.readDeclarationNameLoc(E->MemberDecl->getDeclName()); E->MemberLoc = Record.readSourceLocation(); E->MemberExprBits.IsArrow = CurrentUnpackingBits->getNextBit(); - E->MemberExprBits.HasQualifierOrFoundDecl = HasQualifier || HasFoundDecl; + E->MemberExprBits.HasQualifier = HasQualifier; + E->MemberExprBits.HasFoundDecl = HasFoundDecl; E->MemberExprBits.HasTemplateKWAndArgsInfo = HasTemplateInfo; E->MemberExprBits.HadMultipleCandidates = CurrentUnpackingBits->getNextBit(); E->MemberExprBits.NonOdrUseReason = CurrentUnpackingBits->getNextBits(/*Width=*/2); E->MemberExprBits.OperatorLoc = Record.readSourceLocation(); - if (HasQualifier || HasFoundDecl) { - DeclAccessPair FoundDecl; - if (HasFoundDecl) { - auto *FoundD = Record.readDeclAs<NamedDecl>(); - auto AS = (AccessSpecifier)CurrentUnpackingBits->getNextBits(/*Width=*/2); - FoundDecl = DeclAccessPair::make(FoundD, AS); - } else { - FoundDecl = DeclAccessPair::make(E->MemberDecl, - E->MemberDecl->getAccess()); - } - E->getTrailingObjects<MemberExprNameQualifier>()->FoundDecl = FoundDecl; + if (HasQualifier) + new (E->getTrailingObjects<NestedNameSpecifierLoc>()) + NestedNameSpecifierLoc(Record.readNestedNameSpecifierLoc()); - NestedNameSpecifierLoc QualifierLoc; - if (HasQualifier) - QualifierLoc = Record.readNestedNameSpecifierLoc(); - E->getTrailingObjects<MemberExprNameQualifier>()->QualifierLoc = - QualifierLoc; + if (HasFoundDecl) { + auto *FoundD = Record.readDeclAs<NamedDecl>(); + auto AS = (AccessSpecifier)CurrentUnpackingBits->getNextBits(/*Width=*/2); + *E->getTrailingObjects<DeclAccessPair>() = DeclAccessPair::make(FoundD, AS); } if (HasTemplateInfo) diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 3653d94c6e073964eac259647f47059a90c0751c..a2668e61c51d129651c1e936b0e355f3f91728af 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -193,17 +193,17 @@ std::set<const FileEntry *> GetAffectingModuleMaps(const Preprocessor &PP, const ModuleMap &MM = HS.getModuleMap(); SourceManager &SourceMgr = PP.getSourceManager(); - std::set<const FileEntry *> ModuleMaps{}; - auto CollectIncludingModuleMaps = [&](FileEntryRef F) { + std::set<const FileEntry *> ModuleMaps; + auto CollectIncludingModuleMaps = [&](FileID FID, FileEntryRef F) { if (!ModuleMaps.insert(F).second) return; - FileID FID = SourceMgr.translateFile(F); SourceLocation Loc = SourceMgr.getIncludeLoc(FID); // The include location of inferred module maps can point into the header // file that triggered the inferring. Cut off the walk if that's the case. while (Loc.isValid() && isModuleMap(SourceMgr.getFileCharacteristic(Loc))) { FID = SourceMgr.getFileID(Loc); - if (!ModuleMaps.insert(*SourceMgr.getFileEntryRefForID(FID)).second) + F = *SourceMgr.getFileEntryRefForID(FID); + if (!ModuleMaps.insert(F).second) break; Loc = SourceMgr.getIncludeLoc(FID); } @@ -216,13 +216,13 @@ std::set<const FileEntry *> GetAffectingModuleMaps(const Preprocessor &PP, break; // The containing module map is affecting, because it's being pointed // into by Module::DefinitionLoc. - if (auto ModuleMapFile = MM.getContainingModuleMapFile(Mod)) - CollectIncludingModuleMaps(*ModuleMapFile); + if (FileID FID = MM.getContainingModuleMapFileID(Mod); FID.isValid()) + CollectIncludingModuleMaps(FID, *SourceMgr.getFileEntryRefForID(FID)); // For inferred modules, the module map that allowed inferring is not in // the include chain of the virtual containing module map file. It did // affect the compilation, though. - if (auto ModuleMapFile = MM.getModuleMapFileForUniquing(Mod)) - CollectIncludingModuleMaps(*ModuleMapFile); + if (FileID FID = MM.getModuleMapFileIDForUniquing(Mod); FID.isValid()) + CollectIncludingModuleMaps(FID, *SourceMgr.getFileEntryRefForID(FID)); } }; @@ -318,6 +318,10 @@ void TypeLocWriter::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { // nothing to do } +void TypeLocWriter::VisitArrayParameterTypeLoc(ArrayParameterTypeLoc TL) { + // nothing to do +} + void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { addSourceLocation(TL.getCaretLoc()); } @@ -514,6 +518,10 @@ void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) { Record.AddAttr(TL.getAttr()); } +void TypeLocWriter::VisitCountAttributedTypeLoc(CountAttributedTypeLoc TL) { + // Nothing to do +} + void TypeLocWriter::VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) { // Nothing to do. } @@ -3191,6 +3199,10 @@ uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context, if (DC->decls_empty()) return 0; + // In reduced BMI, we don't care the declarations in functions. + if (GeneratingReducedBMI && DC->isFunctionOrMethod()) + return 0; + uint64_t Offset = Stream.GetCurrentBitNo(); SmallVector<uint32_t, 128> KindDeclPairs; for (const auto *D : DC->decls()) { @@ -4724,7 +4736,6 @@ void ASTWriter::computeNonAffectingInputFiles() { continue; if (!isModuleMap(File.getFileCharacteristic()) || - AffectingModuleMaps.empty() || llvm::is_contained(AffectingModuleMaps, *Cache->OrigEntry)) continue; @@ -4952,38 +4963,12 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, Stream.EmitRecord(METADATA_OLD_FORMAT, Record); } - // Create a lexical update block containing all of the declarations in the - // translation unit that do not come from other AST files. const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); - SmallVector<uint32_t, 128> NewGlobalKindDeclPairs; - for (const auto *D : TU->noload_decls()) { - if (!D->isFromASTFile()) { - NewGlobalKindDeclPairs.push_back(D->getKind()); - NewGlobalKindDeclPairs.push_back(GetDeclRef(D)); - } - } - auto Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); - unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv)); - { - RecordData::value_type Record[] = {TU_UPDATE_LEXICAL}; - Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record, - bytes(NewGlobalKindDeclPairs)); - } - - // And a visible updates block for the translation unit. - Abv = std::make_shared<BitCodeAbbrev>(); - Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); - Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); - UpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv)); - WriteDeclContextVisibleUpdate(TU); - - // If we have any extern "C" names, write out a visible update for them. - if (Context.ExternCContext) - WriteDeclContextVisibleUpdate(Context.ExternCContext); + // Force all top level declarations to be emitted. + for (const auto *D : TU->noload_decls()) + if (!D->isFromASTFile()) + GetDeclRef(D); // If the translation unit has an anonymous namespace, and we don't already // have an update block for it, write it as an update block. @@ -5124,6 +5109,14 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, for (auto *D : SemaRef.DeclsToCheckForDeferredDiags) DeclsToCheckForDeferredDiags.push_back(GetDeclRef(D)); + { + auto Abv = std::make_shared<BitCodeAbbrev>(); + Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE)); + Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); + Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); + UpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv)); + } + RecordData DeclUpdatesOffsetsRecord; // Keep writing types, declarations, and declaration update records @@ -5151,6 +5144,35 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, WriteTypeDeclOffsets(); if (!DeclUpdatesOffsetsRecord.empty()) Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord); + + // Create a lexical update block containing all of the declarations in the + // translation unit that do not come from other AST files. + { + SmallVector<uint32_t, 128> NewGlobalKindDeclPairs; + for (const auto *D : TU->noload_decls()) { + if (!D->isFromASTFile()) { + NewGlobalKindDeclPairs.push_back(D->getKind()); + NewGlobalKindDeclPairs.push_back(GetDeclRef(D)); + } + } + + auto Abv = std::make_shared<BitCodeAbbrev>(); + Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL)); + Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); + unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv)); + + RecordData::value_type Record[] = {TU_UPDATE_LEXICAL}; + Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record, + bytes(NewGlobalKindDeclPairs)); + } + + // And a visible updates block for the translation unit. + WriteDeclContextVisibleUpdate(TU); + + // If we have any extern "C" names, write out a visible update for them. + if (Context.ExternCContext) + WriteDeclContextVisibleUpdate(Context.ExternCContext); + WriteFileDeclIDsMap(); WriteSourceManagerBlock(Context.getSourceManager(), PP); WriteComments(); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index d04e1c781b4e286ef1e74de74ef5cfea52501627..86f64bf2a24250b5ba50e854968fe897527c7fb1 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -281,11 +281,18 @@ bool clang::CanElideDeclDef(const Decl *D) { if (FD->isDependentContext()) return false; + + if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) + return false; } if (auto *VD = dyn_cast<VarDecl>(D)) { if (!VD->getDeclContext()->getRedeclContext()->isFileContext() || - VD->isInline() || VD->isConstexpr() || isa<ParmVarDecl>(VD)) + VD->isInline() || VD->isConstexpr() || isa<ParmVarDecl>(VD) || + // Constant initialized variable may not affect the ABI, but they + // may be used in constant evaluation in the frontend, so we have + // to remain them. + VD->hasConstantInitialization()) return false; if (VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 7ce48fede383ea6f200146f8d8438ec929c2124c..22e190450d3918f6e7cb87d1c641c25b3a269adb 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -970,10 +970,7 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { VisitExpr(E); bool HasQualifier = E->hasQualifier(); - bool HasFoundDecl = - E->hasQualifierOrFoundDecl() && - (E->getFoundDecl().getDecl() != E->getMemberDecl() || - E->getFoundDecl().getAccess() != E->getMemberDecl()->getAccess()); + bool HasFoundDecl = E->hasFoundDecl(); bool HasTemplateInfo = E->hasTemplateKWAndArgsInfo(); unsigned NumTemplateArgs = E->getNumTemplateArgs(); @@ -995,15 +992,15 @@ void ASTStmtWriter::VisitMemberExpr(MemberExpr *E) { CurrentPackingBits.addBits(E->isNonOdrUse(), /*Width=*/2); Record.AddSourceLocation(E->getOperatorLoc()); + if (HasQualifier) + Record.AddNestedNameSpecifierLoc(E->getQualifierLoc()); + if (HasFoundDecl) { DeclAccessPair FoundDecl = E->getFoundDecl(); Record.AddDeclRef(FoundDecl.getDecl()); CurrentPackingBits.addBits(FoundDecl.getAccess(), /*BitWidth=*/2); } - if (HasQualifier) - Record.AddNestedNameSpecifierLoc(E->getQualifierLoc()); - if (HasTemplateInfo) AddTemplateKWAndArgsInfo(*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(), E->getTrailingObjects<TemplateArgumentLoc>()); diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp index 2b511b2d5a90a219c655d8e73bbbf7f2dccbff27..f54db36d4a0199b8faac082dac18963d7c2f916f 100644 --- a/clang/lib/Serialization/GeneratePCH.cpp +++ b/clang/lib/Serialization/GeneratePCH.cpp @@ -41,6 +41,21 @@ PCHGenerator::PCHGenerator( PCHGenerator::~PCHGenerator() { } +Module *PCHGenerator::getEmittingModule(ASTContext &) { + Module *M = nullptr; + + if (PP.getLangOpts().isCompilingModule()) { + M = PP.getHeaderSearchInfo().lookupModule(PP.getLangOpts().CurrentModule, + SourceLocation(), + /*AllowSearch*/ false); + if (!M) + assert(PP.getDiagnostics().hasErrorOccurred() && + "emitting module but current module doesn't exist"); + } + + return M; +} + void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { // Don't create a PCH if there were fatal failures during module loading. if (PP.getModuleLoader().HadFatalFailure) @@ -50,16 +65,7 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { if (hasErrors && !AllowASTWithErrors) return; - Module *Module = nullptr; - if (PP.getLangOpts().isCompilingModule()) { - Module = PP.getHeaderSearchInfo().lookupModule( - PP.getLangOpts().CurrentModule, SourceLocation(), - /*AllowSearch*/ false); - if (!Module) { - assert(hasErrors && "emitting module but current module doesn't exist"); - return; - } - } + Module *Module = getEmittingModule(Ctx); // Errors that do not prevent the PCH from being written should not cause the // overall compilation to fail either. @@ -84,16 +90,22 @@ ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() { ReducedBMIGenerator::ReducedBMIGenerator(const Preprocessor &PP, InMemoryModuleCache &ModuleCache, - StringRef OutputFile, - std::shared_ptr<PCHBuffer> Buffer, - bool IncludeTimestamps) + StringRef OutputFile) : PCHGenerator( - PP, ModuleCache, OutputFile, llvm::StringRef(), Buffer, + PP, ModuleCache, OutputFile, llvm::StringRef(), + std::make_shared<PCHBuffer>(), /*Extensions=*/ArrayRef<std::shared_ptr<ModuleFileExtension>>(), - /*AllowASTWithErrors*/ false, /*IncludeTimestamps=*/IncludeTimestamps, + /*AllowASTWithErrors*/ false, /*IncludeTimestamps=*/false, /*BuildingImplicitModule=*/false, /*ShouldCacheASTInMemory=*/false, /*GeneratingReducedBMI=*/true) {} +Module *ReducedBMIGenerator::getEmittingModule(ASTContext &Ctx) { + Module *M = Ctx.getCurrentNamedModule(); + assert(M->isNamedModuleUnit() && + "ReducedBMIGenerator should only be used with C++20 Named modules."); + return M; +} + void ReducedBMIGenerator::HandleTranslationUnit(ASTContext &Ctx) { PCHGenerator::HandleTranslationUnit(Ctx); diff --git a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp index 29eb932584027d5a2766af68ff19a46a25cb6a67..f82288f1099e887e31eb24cfaf78fb86ccc1e92d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp @@ -83,6 +83,8 @@ public: AssumedUpperBound = UpperBoundVal; } + bool assumedNonNegative() { return AssumedNonNegative; } + const NoteTag *createNoteTag(CheckerContext &C) const; private: @@ -402,7 +404,8 @@ static bool tryDividePair(std::optional<int64_t> &Val1, } static Messages getExceedsMsgs(ASTContext &ACtx, const SubRegion *Region, - NonLoc Offset, NonLoc Extent, SVal Location) { + NonLoc Offset, NonLoc Extent, SVal Location, + bool AlsoMentionUnderflow) { std::string RegName = getRegionName(Region); const auto *EReg = Location.getAsRegion()->getAs<ElementRegion>(); assert(EReg && "this checker only handles element access"); @@ -414,6 +417,7 @@ static Messages getExceedsMsgs(ASTContext &ACtx, const SubRegion *Region, int64_t ElemSize = ACtx.getTypeSizeInChars(ElemType).getQuantity(); bool UseByteOffsets = !tryDividePair(OffsetN, ExtentN, ElemSize); + const char *OffsetOrIndex = UseByteOffsets ? "byte offset" : "index"; SmallString<256> Buf; llvm::raw_svector_ostream Out(Buf); @@ -421,10 +425,12 @@ static Messages getExceedsMsgs(ASTContext &ACtx, const SubRegion *Region, if (!ExtentN && !UseByteOffsets) Out << "'" << ElemType.getAsString() << "' element in "; Out << RegName << " at "; - if (OffsetN) { - Out << (UseByteOffsets ? "byte offset " : "index ") << *OffsetN; + if (AlsoMentionUnderflow) { + Out << "a negative or overflowing " << OffsetOrIndex; + } else if (OffsetN) { + Out << OffsetOrIndex << " " << *OffsetN; } else { - Out << "an overflowing " << (UseByteOffsets ? "byte offset" : "index"); + Out << "an overflowing " << OffsetOrIndex; } if (ExtentN) { Out << ", while it holds only "; @@ -441,17 +447,20 @@ static Messages getExceedsMsgs(ASTContext &ACtx, const SubRegion *Region, Out << "s"; } - return { - formatv("Out of bound access to memory after the end of {0}", RegName), - std::string(Buf)}; + return {formatv("Out of bound access to memory {0} {1}", + AlsoMentionUnderflow ? "around" : "after the end of", + RegName), + std::string(Buf)}; } -static Messages getTaintMsgs(const SubRegion *Region, const char *OffsetName) { +static Messages getTaintMsgs(const SubRegion *Region, const char *OffsetName, + bool AlsoMentionUnderflow) { std::string RegName = getRegionName(Region); return {formatv("Potential out of bound access to {0} with tainted {1}", RegName, OffsetName), - formatv("Access of {0} with a tainted {1} that may be too large", - RegName, OffsetName)}; + formatv("Access of {0} with a tainted {1} that may be {2}too large", + RegName, OffsetName, + AlsoMentionUnderflow ? "negative or " : "")}; } const NoteTag *StateUpdateReporter::createNoteTag(CheckerContext &C) const { @@ -600,6 +609,13 @@ void ArrayBoundCheckerV2::performCheck(const Expr *E, CheckerContext &C) const { // CHECK UPPER BOUND DefinedOrUnknownSVal Size = getDynamicExtent(State, Reg, SVB); if (auto KnownSize = Size.getAs<NonLoc>()) { + // In a situation where both overflow and overflow are possible (but the + // index is either tainted or known to be invalid), the logic of this + // checker will first assume that the offset is non-negative, and then + // (with this additional assumption) it will detect an overflow error. + // In this situation the warning message should mention both possibilities. + bool AlsoMentionUnderflow = SUR.assumedNonNegative(); + auto [WithinUpperBound, ExceedsUpperBound] = compareValueToThreshold(State, ByteOffset, *KnownSize, SVB); @@ -615,8 +631,9 @@ void ArrayBoundCheckerV2::performCheck(const Expr *E, CheckerContext &C) const { return; } - Messages Msgs = getExceedsMsgs(C.getASTContext(), Reg, ByteOffset, - *KnownSize, Location); + Messages Msgs = + getExceedsMsgs(C.getASTContext(), Reg, ByteOffset, *KnownSize, + Location, AlsoMentionUnderflow); reportOOB(C, ExceedsUpperBound, Msgs, ByteOffset, KnownSize); return; } @@ -632,7 +649,7 @@ void ArrayBoundCheckerV2::performCheck(const Expr *E, CheckerContext &C) const { if (isTainted(State, ASE->getIdx(), C.getLocationContext())) OffsetName = "index"; - Messages Msgs = getTaintMsgs(Reg, OffsetName); + Messages Msgs = getTaintMsgs(Reg, OffsetName, AlsoMentionUnderflow); reportOOB(C, ExceedsUpperBound, Msgs, ByteOffset, KnownSize, /*IsTaintBug=*/true); return; diff --git a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp index 66e080adb1382bcc273bb5161b93565a714a3d0c..e4373915410fb29e2f145bf3546a3a0f2e9a412a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp @@ -20,48 +20,178 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" + +#include <iterator> +#include <utility> +#include <variant> using namespace clang; using namespace ento; namespace { + +struct CritSectionMarker { + const Expr *LockExpr{}; + const MemRegion *LockReg{}; + + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.Add(LockExpr); + ID.Add(LockReg); + } + + [[nodiscard]] constexpr bool + operator==(const CritSectionMarker &Other) const noexcept { + return LockExpr == Other.LockExpr && LockReg == Other.LockReg; + } + [[nodiscard]] constexpr bool + operator!=(const CritSectionMarker &Other) const noexcept { + return !(*this == Other); + } +}; + +class CallDescriptionBasedMatcher { + CallDescription LockFn; + CallDescription UnlockFn; + +public: + CallDescriptionBasedMatcher(CallDescription &&LockFn, + CallDescription &&UnlockFn) + : LockFn(std::move(LockFn)), UnlockFn(std::move(UnlockFn)) {} + [[nodiscard]] bool matches(const CallEvent &Call, bool IsLock) const { + if (IsLock) { + return LockFn.matches(Call); + } + return UnlockFn.matches(Call); + } +}; + +class FirstArgMutexDescriptor : public CallDescriptionBasedMatcher { +public: + FirstArgMutexDescriptor(CallDescription &&LockFn, CallDescription &&UnlockFn) + : CallDescriptionBasedMatcher(std::move(LockFn), std::move(UnlockFn)) {} + + [[nodiscard]] const MemRegion *getRegion(const CallEvent &Call, bool) const { + return Call.getArgSVal(0).getAsRegion(); + } +}; + +class MemberMutexDescriptor : public CallDescriptionBasedMatcher { +public: + MemberMutexDescriptor(CallDescription &&LockFn, CallDescription &&UnlockFn) + : CallDescriptionBasedMatcher(std::move(LockFn), std::move(UnlockFn)) {} + + [[nodiscard]] const MemRegion *getRegion(const CallEvent &Call, bool) const { + return cast<CXXMemberCall>(Call).getCXXThisVal().getAsRegion(); + } +}; + +class RAIIMutexDescriptor { + mutable const IdentifierInfo *Guard{}; + mutable bool IdentifierInfoInitialized{}; + mutable llvm::SmallString<32> GuardName{}; + + void initIdentifierInfo(const CallEvent &Call) const { + if (!IdentifierInfoInitialized) { + // In case of checking C code, or when the corresponding headers are not + // included, we might end up query the identifier table every time when + // this function is called instead of early returning it. To avoid this, a + // bool variable (IdentifierInfoInitialized) is used and the function will + // be run only once. + Guard = &Call.getCalleeAnalysisDeclContext()->getASTContext().Idents.get( + GuardName); + IdentifierInfoInitialized = true; + } + } + + template <typename T> bool matchesImpl(const CallEvent &Call) const { + const T *C = dyn_cast<T>(&Call); + if (!C) + return false; + const IdentifierInfo *II = + cast<CXXRecordDecl>(C->getDecl()->getParent())->getIdentifier(); + return II == Guard; + } + +public: + RAIIMutexDescriptor(StringRef GuardName) : GuardName(GuardName) {} + [[nodiscard]] bool matches(const CallEvent &Call, bool IsLock) const { + initIdentifierInfo(Call); + if (IsLock) { + return matchesImpl<CXXConstructorCall>(Call); + } + return matchesImpl<CXXDestructorCall>(Call); + } + [[nodiscard]] const MemRegion *getRegion(const CallEvent &Call, + bool IsLock) const { + const MemRegion *LockRegion = nullptr; + if (IsLock) { + if (std::optional<SVal> Object = Call.getReturnValueUnderConstruction()) { + LockRegion = Object->getAsRegion(); + } + } else { + LockRegion = cast<CXXDestructorCall>(Call).getCXXThisVal().getAsRegion(); + } + return LockRegion; + } +}; + +using MutexDescriptor = + std::variant<FirstArgMutexDescriptor, MemberMutexDescriptor, + RAIIMutexDescriptor>; + class BlockInCriticalSectionChecker : public Checker<check::PostCall> { - mutable IdentifierInfo *IILockGuard = nullptr; - mutable IdentifierInfo *IIUniqueLock = nullptr; - mutable bool IdentifierInfoInitialized = false; - - const CallDescription LockFn{{"lock"}}; - const CallDescription UnlockFn{{"unlock"}}; - const CallDescription SleepFn{{"sleep"}}; - const CallDescription GetcFn{{"getc"}}; - const CallDescription FgetsFn{{"fgets"}}; - const CallDescription ReadFn{{"read"}}; - const CallDescription RecvFn{{"recv"}}; - const CallDescription PthreadLockFn{{"pthread_mutex_lock"}}; - const CallDescription PthreadTryLockFn{{"pthread_mutex_trylock"}}; - const CallDescription PthreadUnlockFn{{"pthread_mutex_unlock"}}; - const CallDescription MtxLock{{"mtx_lock"}}; - const CallDescription MtxTimedLock{{"mtx_timedlock"}}; - const CallDescription MtxTryLock{{"mtx_trylock"}}; - const CallDescription MtxUnlock{{"mtx_unlock"}}; - - const llvm::StringLiteral ClassLockGuard{"lock_guard"}; - const llvm::StringLiteral ClassUniqueLock{"unique_lock"}; +private: + const std::array<MutexDescriptor, 8> MutexDescriptors{ + MemberMutexDescriptor( + CallDescription(/*QualifiedName=*/{"std", "mutex", "lock"}, + /*RequiredArgs=*/0), + CallDescription({"std", "mutex", "unlock"}, 0)), + FirstArgMutexDescriptor(CallDescription({"pthread_mutex_lock"}, 1), + CallDescription({"pthread_mutex_unlock"}, 1)), + FirstArgMutexDescriptor(CallDescription({"mtx_lock"}, 1), + CallDescription({"mtx_unlock"}, 1)), + FirstArgMutexDescriptor(CallDescription({"pthread_mutex_trylock"}, 1), + CallDescription({"pthread_mutex_unlock"}, 1)), + FirstArgMutexDescriptor(CallDescription({"mtx_trylock"}, 1), + CallDescription({"mtx_unlock"}, 1)), + FirstArgMutexDescriptor(CallDescription({"mtx_timedlock"}, 1), + CallDescription({"mtx_unlock"}, 1)), + RAIIMutexDescriptor("lock_guard"), + RAIIMutexDescriptor("unique_lock")}; + + const std::array<CallDescription, 5> BlockingFunctions{ + ArrayRef{StringRef{"sleep"}}, ArrayRef{StringRef{"getc"}}, + ArrayRef{StringRef{"fgets"}}, ArrayRef{StringRef{"read"}}, + ArrayRef{StringRef{"recv"}}}; const BugType BlockInCritSectionBugType{ this, "Call to blocking function in critical section", "Blocking Error"}; - void initIdentifierInfo(ASTContext &Ctx) const; + void reportBlockInCritSection(const CallEvent &call, CheckerContext &C) const; - void reportBlockInCritSection(SymbolRef FileDescSym, - const CallEvent &call, - CheckerContext &C) const; + [[nodiscard]] const NoteTag *createCritSectionNote(CritSectionMarker M, + CheckerContext &C) const; -public: - bool isBlockingFunction(const CallEvent &Call) const; - bool isLockFunction(const CallEvent &Call) const; - bool isUnlockFunction(const CallEvent &Call) const; + [[nodiscard]] std::optional<MutexDescriptor> + checkDescriptorMatch(const CallEvent &Call, CheckerContext &C, + bool IsLock) const; + + void handleLock(const MutexDescriptor &Mutex, const CallEvent &Call, + CheckerContext &C) const; + void handleUnlock(const MutexDescriptor &Mutex, const CallEvent &Call, + CheckerContext &C) const; + + [[nodiscard]] bool isBlockingInCritSection(const CallEvent &Call, + CheckerContext &C) const; + +public: /// Process unlock. /// Process lock. /// Process blocking functions (sleep, getc, fgets, read, recv) @@ -70,73 +200,118 @@ public: } // end anonymous namespace -REGISTER_TRAIT_WITH_PROGRAMSTATE(MutexCounter, unsigned) - -void BlockInCriticalSectionChecker::initIdentifierInfo(ASTContext &Ctx) const { - if (!IdentifierInfoInitialized) { - /* In case of checking C code, or when the corresponding headers are not - * included, we might end up query the identifier table every time when this - * function is called instead of early returning it. To avoid this, a bool - * variable (IdentifierInfoInitialized) is used and the function will be run - * only once. */ - IILockGuard = &Ctx.Idents.get(ClassLockGuard); - IIUniqueLock = &Ctx.Idents.get(ClassUniqueLock); - IdentifierInfoInitialized = true; - } +REGISTER_LIST_WITH_PROGRAMSTATE(ActiveCritSections, CritSectionMarker) + +namespace std { +// Iterator traits for ImmutableList data structure +// that enable the use of STL algorithms. +// TODO: Move these to llvm::ImmutableList when overhauling immutable data +// structures for proper iterator concept support. +template <> +struct iterator_traits< + typename llvm::ImmutableList<CritSectionMarker>::iterator> { + using iterator_category = std::forward_iterator_tag; + using value_type = CritSectionMarker; + using difference_type = std::ptrdiff_t; + using reference = CritSectionMarker &; + using pointer = CritSectionMarker *; +}; +} // namespace std + +std::optional<MutexDescriptor> +BlockInCriticalSectionChecker::checkDescriptorMatch(const CallEvent &Call, + CheckerContext &C, + bool IsLock) const { + const auto Descriptor = + llvm::find_if(MutexDescriptors, [&Call, IsLock](auto &&Descriptor) { + return std::visit( + [&Call, IsLock](auto &&DescriptorImpl) { + return DescriptorImpl.matches(Call, IsLock); + }, + Descriptor); + }); + if (Descriptor != MutexDescriptors.end()) + return *Descriptor; + return std::nullopt; } -bool BlockInCriticalSectionChecker::isBlockingFunction(const CallEvent &Call) const { - return matchesAny(Call, SleepFn, GetcFn, FgetsFn, ReadFn, RecvFn); +static const MemRegion *getRegion(const CallEvent &Call, + const MutexDescriptor &Descriptor, + bool IsLock) { + return std::visit( + [&Call, IsLock](auto &&Descriptor) { + return Descriptor.getRegion(Call, IsLock); + }, + Descriptor); } -bool BlockInCriticalSectionChecker::isLockFunction(const CallEvent &Call) const { - if (const auto *Ctor = dyn_cast<CXXConstructorCall>(&Call)) { - auto IdentifierInfo = Ctor->getDecl()->getParent()->getIdentifier(); - if (IdentifierInfo == IILockGuard || IdentifierInfo == IIUniqueLock) - return true; - } +void BlockInCriticalSectionChecker::handleLock( + const MutexDescriptor &LockDescriptor, const CallEvent &Call, + CheckerContext &C) const { + const MemRegion *MutexRegion = + getRegion(Call, LockDescriptor, /*IsLock=*/true); + if (!MutexRegion) + return; - return matchesAny(Call, LockFn, PthreadLockFn, PthreadTryLockFn, MtxLock, - MtxTimedLock, MtxTryLock); + const CritSectionMarker MarkToAdd{Call.getOriginExpr(), MutexRegion}; + ProgramStateRef StateWithLockEvent = + C.getState()->add<ActiveCritSections>(MarkToAdd); + C.addTransition(StateWithLockEvent, createCritSectionNote(MarkToAdd, C)); } -bool BlockInCriticalSectionChecker::isUnlockFunction(const CallEvent &Call) const { - if (const auto *Dtor = dyn_cast<CXXDestructorCall>(&Call)) { - const auto *DRecordDecl = cast<CXXRecordDecl>(Dtor->getDecl()->getParent()); - auto IdentifierInfo = DRecordDecl->getIdentifier(); - if (IdentifierInfo == IILockGuard || IdentifierInfo == IIUniqueLock) - return true; +void BlockInCriticalSectionChecker::handleUnlock( + const MutexDescriptor &UnlockDescriptor, const CallEvent &Call, + CheckerContext &C) const { + const MemRegion *MutexRegion = + getRegion(Call, UnlockDescriptor, /*IsLock=*/false); + if (!MutexRegion) + return; + + ProgramStateRef State = C.getState(); + const auto ActiveSections = State->get<ActiveCritSections>(); + const auto MostRecentLock = + llvm::find_if(ActiveSections, [MutexRegion](auto &&Marker) { + return Marker.LockReg == MutexRegion; + }); + if (MostRecentLock == ActiveSections.end()) + return; + + // Build a new ImmutableList without this element. + auto &Factory = State->get_context<ActiveCritSections>(); + llvm::ImmutableList<CritSectionMarker> NewList = Factory.getEmptyList(); + for (auto It = ActiveSections.begin(), End = ActiveSections.end(); It != End; + ++It) { + if (It != MostRecentLock) + NewList = Factory.add(*It, NewList); } - return matchesAny(Call, UnlockFn, PthreadUnlockFn, MtxUnlock); + State = State->set<ActiveCritSections>(NewList); + C.addTransition(State); +} + +bool BlockInCriticalSectionChecker::isBlockingInCritSection( + const CallEvent &Call, CheckerContext &C) const { + return llvm::any_of(BlockingFunctions, + [&Call](auto &&Fn) { return Fn.matches(Call); }) && + !C.getState()->get<ActiveCritSections>().isEmpty(); } void BlockInCriticalSectionChecker::checkPostCall(const CallEvent &Call, CheckerContext &C) const { - initIdentifierInfo(C.getASTContext()); - - if (!isBlockingFunction(Call) - && !isLockFunction(Call) - && !isUnlockFunction(Call)) - return; - - ProgramStateRef State = C.getState(); - unsigned mutexCount = State->get<MutexCounter>(); - if (isUnlockFunction(Call) && mutexCount > 0) { - State = State->set<MutexCounter>(--mutexCount); - C.addTransition(State); - } else if (isLockFunction(Call)) { - State = State->set<MutexCounter>(++mutexCount); - C.addTransition(State); - } else if (mutexCount > 0) { - SymbolRef BlockDesc = Call.getReturnValue().getAsSymbol(); - reportBlockInCritSection(BlockDesc, Call, C); + if (isBlockingInCritSection(Call, C)) { + reportBlockInCritSection(Call, C); + } else if (std::optional<MutexDescriptor> LockDesc = + checkDescriptorMatch(Call, C, /*IsLock=*/true)) { + handleLock(*LockDesc, Call, C); + } else if (std::optional<MutexDescriptor> UnlockDesc = + checkDescriptorMatch(Call, C, /*IsLock=*/false)) { + handleUnlock(*UnlockDesc, Call, C); } } void BlockInCriticalSectionChecker::reportBlockInCritSection( - SymbolRef BlockDescSym, const CallEvent &Call, CheckerContext &C) const { - ExplodedNode *ErrNode = C.generateNonFatalErrorNode(); + const CallEvent &Call, CheckerContext &C) const { + ExplodedNode *ErrNode = C.generateNonFatalErrorNode(C.getState()); if (!ErrNode) return; @@ -147,14 +322,63 @@ void BlockInCriticalSectionChecker::reportBlockInCritSection( auto R = std::make_unique<PathSensitiveBugReport>(BlockInCritSectionBugType, os.str(), ErrNode); R->addRange(Call.getSourceRange()); - R->markInteresting(BlockDescSym); + R->markInteresting(Call.getReturnValue()); C.emitReport(std::move(R)); } +const NoteTag * +BlockInCriticalSectionChecker::createCritSectionNote(CritSectionMarker M, + CheckerContext &C) const { + const BugType *BT = &this->BlockInCritSectionBugType; + return C.getNoteTag([M, BT](PathSensitiveBugReport &BR, + llvm::raw_ostream &OS) { + if (&BR.getBugType() != BT) + return; + + // Get the lock events for the mutex of the current line's lock event. + const auto CritSectionBegins = + BR.getErrorNode()->getState()->get<ActiveCritSections>(); + llvm::SmallVector<CritSectionMarker, 4> LocksForMutex; + llvm::copy_if( + CritSectionBegins, std::back_inserter(LocksForMutex), + [M](const auto &Marker) { return Marker.LockReg == M.LockReg; }); + if (LocksForMutex.empty()) + return; + + // As the ImmutableList builds the locks by prepending them, we + // reverse the list to get the correct order. + std::reverse(LocksForMutex.begin(), LocksForMutex.end()); + + // Find the index of the lock expression in the list of all locks for a + // given mutex (in acquisition order). + const auto Position = + llvm::find_if(std::as_const(LocksForMutex), [M](const auto &Marker) { + return Marker.LockExpr == M.LockExpr; + }); + if (Position == LocksForMutex.end()) + return; + + // If there is only one lock event, we don't need to specify how many times + // the critical section was entered. + if (LocksForMutex.size() == 1) { + OS << "Entering critical section here"; + return; + } + + const auto IndexOfLock = + std::distance(std::as_const(LocksForMutex).begin(), Position); + + const auto OrdinalOfLock = IndexOfLock + 1; + OS << "Entering critical section for the " << OrdinalOfLock + << llvm::getOrdinalSuffix(OrdinalOfLock) << " time here"; + }); +} + void ento::registerBlockInCriticalSectionChecker(CheckerManager &mgr) { mgr.registerChecker<BlockInCriticalSectionChecker>(); } -bool ento::shouldRegisterBlockInCriticalSectionChecker(const CheckerManager &mgr) { +bool ento::shouldRegisterBlockInCriticalSectionChecker( + const CheckerManager &mgr) { return true; } diff --git a/clang/lib/StaticAnalyzer/Checkers/CXXDeleteChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CXXDeleteChecker.cpp index b4dee1e300e886369d43c374d63b72e4aa6d88cb..1b1226a7f1a71d861ce262e572822a24e0a660f1 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CXXDeleteChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CXXDeleteChecker.cpp @@ -220,11 +220,11 @@ CXXDeleteChecker::PtrCastVisitor::VisitNode(const ExplodedNode *N, /*addPosRange=*/true); } -void ento::registerCXXArrayDeleteChecker(CheckerManager &mgr) { +void ento::registerArrayDeleteChecker(CheckerManager &mgr) { mgr.registerChecker<CXXArrayDeleteChecker>(); } -bool ento::shouldRegisterCXXArrayDeleteChecker(const CheckerManager &mgr) { +bool ento::shouldRegisterArrayDeleteChecker(const CheckerManager &mgr) { return true; } diff --git a/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp index a50772f881f7d0fdabf0427c012fa0fe329331a3..2cff97a591b8c0ac8b3f855f96704cba2ba9774e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp @@ -68,7 +68,7 @@ static bool evenFlexibleArraySize(ASTContext &Ctx, CharUnits RegionSize, FlexSize = Ctx.getTypeSizeInChars(ElemType); if (ArrayTy->getSize() == 1 && TypeSize > FlexSize) TypeSize -= FlexSize; - else if (ArrayTy->getSize() != 0) + else if (!ArrayTy->isZeroSize()) return false; } else if (RD->hasFlexibleArrayMember()) { FlexSize = Ctx.getTypeSizeInChars(ElemType); diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 03cb7696707fe2f215db6192ee244e4a22784c50..88fb42b6625aa48eb796ad149576dca2c68d7986 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -394,8 +394,10 @@ private: const CallEvent &Call, CheckerContext &C)>; const CallDescriptionMap<CheckFn> PreFnMap{ - {{{"getline"}, 3}, &MallocChecker::preGetdelim}, - {{{"getdelim"}, 4}, &MallocChecker::preGetdelim}, + // NOTE: the following CallDescription also matches the C++ standard + // library function std::getline(); the callback will filter it out. + {{CDM::CLibrary, {"getline"}, 3}, &MallocChecker::preGetdelim}, + {{CDM::CLibrary, {"getdelim"}, 4}, &MallocChecker::preGetdelim}, }; const CallDescriptionMap<CheckFn> FreeingMemFnMap{ @@ -446,8 +448,11 @@ private: std::bind(&MallocChecker::checkRealloc, _1, _2, _3, false)}, {{{"g_realloc_n"}, 3}, &MallocChecker::checkReallocN}, {{{"g_try_realloc_n"}, 3}, &MallocChecker::checkReallocN}, - {{{"getline"}, 3}, &MallocChecker::checkGetdelim}, - {{{"getdelim"}, 4}, &MallocChecker::checkGetdelim}, + + // NOTE: the following CallDescription also matches the C++ standard + // library function std::getline(); the callback will filter it out. + {{CDM::CLibrary, {"getline"}, 3}, &MallocChecker::checkGetdelim}, + {{CDM::CLibrary, {"getdelim"}, 4}, &MallocChecker::checkGetdelim}, }; bool isMemCall(const CallEvent &Call) const; @@ -1435,13 +1440,21 @@ void MallocChecker::checkGMallocN0(const CallEvent &Call, C.addTransition(State); } +static bool isFromStdNamespace(const CallEvent &Call) { + const Decl *FD = Call.getDecl(); + assert(FD && "a CallDescription cannot match a call without a Decl"); + return FD->isInStdNamespace(); +} + void MallocChecker::preGetdelim(const CallEvent &Call, CheckerContext &C) const { - if (!Call.isGlobalCFunction()) + // Discard calls to the C++ standard library function std::getline(), which + // is completely unrelated to the POSIX getline() that we're checking. + if (isFromStdNamespace(Call)) return; ProgramStateRef State = C.getState(); - const auto LinePtr = getPointeeDefVal(Call.getArgSVal(0), State); + const auto LinePtr = getPointeeVal(Call.getArgSVal(0), State); if (!LinePtr) return; @@ -1458,7 +1471,9 @@ void MallocChecker::preGetdelim(const CallEvent &Call, void MallocChecker::checkGetdelim(const CallEvent &Call, CheckerContext &C) const { - if (!Call.isGlobalCFunction()) + // Discard calls to the C++ standard library function std::getline(), which + // is completely unrelated to the POSIX getline() that we're checking. + if (isFromStdNamespace(Call)) return; ProgramStateRef State = C.getState(); @@ -1470,8 +1485,10 @@ void MallocChecker::checkGetdelim(const CallEvent &Call, SValBuilder &SVB = C.getSValBuilder(); - const auto LinePtr = getPointeeDefVal(Call.getArgSVal(0), State); - const auto Size = getPointeeDefVal(Call.getArgSVal(1), State); + const auto LinePtr = + getPointeeVal(Call.getArgSVal(0), State)->getAs<DefinedSVal>(); + const auto Size = + getPointeeVal(Call.getArgSVal(1), State)->getAs<DefinedSVal>(); if (!LinePtr || !Size || !LinePtr->getAsRegion()) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp index eee9449f31805c2fe4aa32575c3f57302615ed6a..4f35d9442ad9886b90e4889657d7424bc683f6d5 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp @@ -117,7 +117,7 @@ public: return; uint64_t Elts = 0; if (const ConstantArrayType *CArrTy = dyn_cast<ConstantArrayType>(ArrTy)) - Elts = CArrTy->getSize().getZExtValue(); + Elts = CArrTy->getZExtSize(); if (Elts == 0) return; const RecordType *RT = ArrTy->getElementType()->getAs<RecordType>(); diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index 10972158f3986232db1dd2d9c0a5a0415a6b9e97..069e3a633c12141c76c1850ad5b45931a7f7749f 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -1200,10 +1200,25 @@ void StreamChecker::evalGetdelim(const FnDescription *Desc, // Add transition for the successful state. NonLoc RetVal = makeRetVal(C, E.CE).castAs<NonLoc>(); - ProgramStateRef StateNotFailed = - State->BindExpr(E.CE, C.getLocationContext(), RetVal); + ProgramStateRef StateNotFailed = E.bindReturnValue(State, C, RetVal); StateNotFailed = E.assumeBinOpNN(StateNotFailed, BO_GE, RetVal, E.getZeroVal(Call)); + + // On success, a buffer is allocated. + auto NewLinePtr = getPointeeVal(Call.getArgSVal(0), State); + if (NewLinePtr && isa<DefinedOrUnknownSVal>(*NewLinePtr)) + StateNotFailed = StateNotFailed->assume( + NewLinePtr->castAs<DefinedOrUnknownSVal>(), true); + + // The buffer size `*n` must be enough to hold the whole line, and + // greater than the return value, since it has to account for '\0'. + SVal SizePtrSval = Call.getArgSVal(1); + auto NVal = getPointeeVal(SizePtrSval, State); + if (NVal && isa<NonLoc>(*NVal)) { + StateNotFailed = E.assumeBinOpNN(StateNotFailed, BO_GT, + NVal->castAs<NonLoc>(), RetVal); + StateNotFailed = E.bindReturnValue(StateNotFailed, C, RetVal); + } if (!StateNotFailed) return; C.addTransition(StateNotFailed); @@ -1217,6 +1232,10 @@ void StreamChecker::evalGetdelim(const FnDescription *Desc, E.isStreamEof() ? ErrorFEof : ErrorFEof | ErrorFError; StateFailed = E.setStreamState( StateFailed, StreamState::getOpened(Desc, NewES, !NewES.isFEof())); + // On failure, the content of the buffer is undefined. + if (auto NewLinePtr = getPointeeVal(Call.getArgSVal(0), State)) + StateFailed = StateFailed->bindLoc(*NewLinePtr, UndefinedVal(), + C.getLocationContext()); C.addTransition(StateFailed, E.getFailureNoteTag(this, C)); } @@ -1245,15 +1264,10 @@ void StreamChecker::evalFseek(const FnDescription *Desc, const CallEvent &Call, if (!E.Init(Desc, Call, C, State)) return; - const llvm::APSInt *PosV = - C.getSValBuilder().getKnownValue(State, Call.getArgSVal(1)); - const llvm::APSInt *WhenceV = - C.getSValBuilder().getKnownValue(State, Call.getArgSVal(2)); - // Bifurcate the state into failed and non-failed. - // Return zero on success, nonzero on error. - ProgramStateRef StateNotFailed, StateFailed; - std::tie(StateFailed, StateNotFailed) = E.makeRetValAndAssumeDual(State, C); + // Return zero on success, -1 on error. + ProgramStateRef StateNotFailed = E.bindReturnValue(State, C, 0); + ProgramStateRef StateFailed = E.bindReturnValue(State, C, -1); // No failure: Reset the state to opened with no error. StateNotFailed = @@ -1263,12 +1277,10 @@ void StreamChecker::evalFseek(const FnDescription *Desc, const CallEvent &Call, // At error it is possible that fseek fails but sets none of the error flags. // If fseek failed, assume that the file position becomes indeterminate in any // case. - StreamErrorState NewErrS = ErrorNone | ErrorFError; - // Setting the position to start of file never produces EOF error. - if (!(PosV && *PosV == 0 && WhenceV && *WhenceV == SeekSetVal)) - NewErrS = NewErrS | ErrorFEof; - StateFailed = E.setStreamState(StateFailed, - StreamState::getOpened(Desc, NewErrS, true)); + // It is allowed to set the position beyond the end of the file. EOF error + // should not occur. + StateFailed = E.setStreamState( + StateFailed, StreamState::getOpened(Desc, ErrorNone | ErrorFError, true)); C.addTransition(StateFailed, E.getFailureNoteTag(this, C)); } diff --git a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp index 19f1ca2dc824c9c61e2904876e0a873efe5854c3..da2d16ca9b5dd74dd5192cb97ad948693052e4b6 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -17,8 +17,10 @@ #include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -41,25 +43,38 @@ enum class OpenVariant { namespace { class UnixAPIMisuseChecker - : public Checker<check::PreStmt<CallExpr>, - check::ASTDecl<TranslationUnitDecl>> { + : public Checker<check::PreCall, check::ASTDecl<TranslationUnitDecl>> { const BugType BT_open{this, "Improper use of 'open'", categories::UnixAPI}; + const BugType BT_getline{this, "Improper use of getdelim", + categories::UnixAPI}; const BugType BT_pthreadOnce{this, "Improper use of 'pthread_once'", categories::UnixAPI}; + const BugType BT_ArgumentNull{this, "NULL pointer", categories::UnixAPI}; mutable std::optional<uint64_t> Val_O_CREAT; + ProgramStateRef + EnsurePtrNotNull(SVal PtrVal, const Expr *PtrExpr, CheckerContext &C, + ProgramStateRef State, const StringRef PtrDescr, + std::optional<std::reference_wrapper<const BugType>> BT = + std::nullopt) const; + + ProgramStateRef EnsureGetdelimBufferAndSizeCorrect( + SVal LinePtrPtrSVal, SVal SizePtrSVal, const Expr *LinePtrPtrExpr, + const Expr *SizePtrExpr, CheckerContext &C, ProgramStateRef State) const; + public: void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager &Mgr, BugReporter &BR) const; - void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; + void checkPreCall(const CallEvent &Call, CheckerContext &C) const; - void CheckOpen(CheckerContext &C, const CallExpr *CE) const; - void CheckOpenAt(CheckerContext &C, const CallExpr *CE) const; - void CheckPthreadOnce(CheckerContext &C, const CallExpr *CE) const; + void CheckOpen(CheckerContext &C, const CallEvent &Call) const; + void CheckOpenAt(CheckerContext &C, const CallEvent &Call) const; + void CheckGetDelim(CheckerContext &C, const CallEvent &Call) const; + void CheckPthreadOnce(CheckerContext &C, const CallEvent &Call) const; - void CheckOpenVariant(CheckerContext &C, - const CallExpr *CE, OpenVariant Variant) const; + void CheckOpenVariant(CheckerContext &C, const CallEvent &Call, + OpenVariant Variant) const; void ReportOpenBug(CheckerContext &C, ProgramStateRef State, const char *Msg, SourceRange SR) const; @@ -95,6 +110,30 @@ private: } // end anonymous namespace +ProgramStateRef UnixAPIMisuseChecker::EnsurePtrNotNull( + SVal PtrVal, const Expr *PtrExpr, CheckerContext &C, ProgramStateRef State, + const StringRef PtrDescr, + std::optional<std::reference_wrapper<const BugType>> BT) const { + const auto Ptr = PtrVal.getAs<DefinedSVal>(); + if (!Ptr) + return State; + + const auto [PtrNotNull, PtrNull] = State->assume(*Ptr); + if (!PtrNotNull && PtrNull) { + if (ExplodedNode *N = C.generateErrorNode(PtrNull)) { + auto R = std::make_unique<PathSensitiveBugReport>( + BT.value_or(std::cref(BT_ArgumentNull)), + (PtrDescr + " pointer might be NULL.").str(), N); + if (PtrExpr) + bugreporter::trackExpressionValue(N, PtrExpr, *R); + C.emitReport(std::move(R)); + } + return nullptr; + } + + return PtrNotNull; +} + void UnixAPIMisuseChecker::checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager &Mgr, BugReporter &) const { @@ -113,9 +152,9 @@ void UnixAPIMisuseChecker::checkASTDecl(const TranslationUnitDecl *TU, // "open" (man 2 open) //===----------------------------------------------------------------------===/ -void UnixAPIMisuseChecker::checkPreStmt(const CallExpr *CE, +void UnixAPIMisuseChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const { - const FunctionDecl *FD = C.getCalleeDecl(CE); + const FunctionDecl *FD = dyn_cast_if_present<FunctionDecl>(Call.getDecl()); if (!FD || FD->getKind() != Decl::Function) return; @@ -130,13 +169,16 @@ void UnixAPIMisuseChecker::checkPreStmt(const CallExpr *CE, return; if (FName == "open") - CheckOpen(C, CE); + CheckOpen(C, Call); else if (FName == "openat") - CheckOpenAt(C, CE); + CheckOpenAt(C, Call); else if (FName == "pthread_once") - CheckPthreadOnce(C, CE); + CheckPthreadOnce(C, Call); + + else if (is_contained({"getdelim", "getline"}, FName)) + CheckGetDelim(C, Call); } void UnixAPIMisuseChecker::ReportOpenBug(CheckerContext &C, ProgramStateRef State, @@ -152,17 +194,17 @@ void UnixAPIMisuseChecker::ReportOpenBug(CheckerContext &C, } void UnixAPIMisuseChecker::CheckOpen(CheckerContext &C, - const CallExpr *CE) const { - CheckOpenVariant(C, CE, OpenVariant::Open); + const CallEvent &Call) const { + CheckOpenVariant(C, Call, OpenVariant::Open); } void UnixAPIMisuseChecker::CheckOpenAt(CheckerContext &C, - const CallExpr *CE) const { - CheckOpenVariant(C, CE, OpenVariant::OpenAt); + const CallEvent &Call) const { + CheckOpenVariant(C, Call, OpenVariant::OpenAt); } void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C, - const CallExpr *CE, + const CallEvent &Call, OpenVariant Variant) const { // The index of the argument taking the flags open flags (O_RDONLY, // O_WRONLY, O_CREAT, etc.), @@ -191,11 +233,11 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C, ProgramStateRef state = C.getState(); - if (CE->getNumArgs() < MinArgCount) { + if (Call.getNumArgs() < MinArgCount) { // The frontend should issue a warning for this case. Just return. return; - } else if (CE->getNumArgs() == MaxArgCount) { - const Expr *Arg = CE->getArg(CreateModeArgIndex); + } else if (Call.getNumArgs() == MaxArgCount) { + const Expr *Arg = Call.getArgExpr(CreateModeArgIndex); QualType QT = Arg->getType(); if (!QT->isIntegerType()) { SmallString<256> SBuf; @@ -209,15 +251,14 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C, Arg->getSourceRange()); return; } - } else if (CE->getNumArgs() > MaxArgCount) { + } else if (Call.getNumArgs() > MaxArgCount) { SmallString<256> SBuf; llvm::raw_svector_ostream OS(SBuf); OS << "Call to '" << VariantName << "' with more than " << MaxArgCount << " arguments"; - ReportOpenBug(C, state, - SBuf.c_str(), - CE->getArg(MaxArgCount)->getSourceRange()); + ReportOpenBug(C, state, SBuf.c_str(), + Call.getArgExpr(MaxArgCount)->getSourceRange()); return; } @@ -226,8 +267,8 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C, } // Now check if oflags has O_CREAT set. - const Expr *oflagsEx = CE->getArg(FlagsArgIndex); - const SVal V = C.getSVal(oflagsEx); + const Expr *oflagsEx = Call.getArgExpr(FlagsArgIndex); + const SVal V = Call.getArgSVal(FlagsArgIndex); if (!isa<NonLoc>(V)) { // The case where 'V' can be a location can only be due to a bad header, // so in this case bail out. @@ -253,7 +294,7 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C, if (!(trueState && !falseState)) return; - if (CE->getNumArgs() < MaxArgCount) { + if (Call.getNumArgs() < MaxArgCount) { SmallString<256> SBuf; llvm::raw_svector_ostream OS(SBuf); OS << "Call to '" << VariantName << "' requires a " @@ -266,23 +307,110 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C, } } +//===----------------------------------------------------------------------===// +// getdelim and getline +//===----------------------------------------------------------------------===// + +ProgramStateRef UnixAPIMisuseChecker::EnsureGetdelimBufferAndSizeCorrect( + SVal LinePtrPtrSVal, SVal SizePtrSVal, const Expr *LinePtrPtrExpr, + const Expr *SizePtrExpr, CheckerContext &C, ProgramStateRef State) const { + static constexpr llvm::StringLiteral SizeGreaterThanBufferSize = + "The buffer from the first argument is smaller than the size " + "specified by the second parameter"; + static constexpr llvm::StringLiteral SizeUndef = + "The buffer from the first argument is not NULL, but the size specified " + "by the second parameter is undefined."; + + auto EmitBugReport = [this, &C, SizePtrExpr, LinePtrPtrExpr]( + ProgramStateRef BugState, StringRef ErrMsg) { + if (ExplodedNode *N = C.generateErrorNode(BugState)) { + auto R = std::make_unique<PathSensitiveBugReport>(BT_getline, ErrMsg, N); + bugreporter::trackExpressionValue(N, SizePtrExpr, *R); + bugreporter::trackExpressionValue(N, LinePtrPtrExpr, *R); + C.emitReport(std::move(R)); + } + }; + + // We have a pointer to a pointer to the buffer, and a pointer to the size. + // We want what they point at. + auto LinePtrSVal = getPointeeVal(LinePtrPtrSVal, State)->getAs<DefinedSVal>(); + auto NSVal = getPointeeVal(SizePtrSVal, State); + if (!LinePtrSVal || !NSVal || NSVal->isUnknown()) + return nullptr; + + assert(LinePtrPtrExpr && SizePtrExpr); + + const auto [LinePtrNotNull, LinePtrNull] = State->assume(*LinePtrSVal); + if (LinePtrNotNull && !LinePtrNull) { + // If `*lineptr` is not null, but `*n` is undefined, there is UB. + if (NSVal->isUndef()) { + EmitBugReport(LinePtrNotNull, SizeUndef); + return nullptr; + } + + // If it is defined, and known, its size must be less than or equal to + // the buffer size. + auto NDefSVal = NSVal->getAs<DefinedSVal>(); + auto &SVB = C.getSValBuilder(); + auto LineBufSize = + getDynamicExtent(LinePtrNotNull, LinePtrSVal->getAsRegion(), SVB); + auto LineBufSizeGtN = SVB.evalBinOp(LinePtrNotNull, BO_GE, LineBufSize, + *NDefSVal, SVB.getConditionType()) + .getAs<DefinedOrUnknownSVal>(); + if (!LineBufSizeGtN) + return LinePtrNotNull; + if (auto LineBufSizeOk = LinePtrNotNull->assume(*LineBufSizeGtN, true)) + return LineBufSizeOk; + + EmitBugReport(LinePtrNotNull, SizeGreaterThanBufferSize); + return nullptr; + } + return State; +} + +void UnixAPIMisuseChecker::CheckGetDelim(CheckerContext &C, + const CallEvent &Call) const { + ProgramStateRef State = C.getState(); + + // The parameter `n` must not be NULL. + SVal SizePtrSval = Call.getArgSVal(1); + State = EnsurePtrNotNull(SizePtrSval, Call.getArgExpr(1), C, State, "Size"); + if (!State) + return; + + // The parameter `lineptr` must not be NULL. + SVal LinePtrPtrSVal = Call.getArgSVal(0); + State = + EnsurePtrNotNull(LinePtrPtrSVal, Call.getArgExpr(0), C, State, "Line"); + if (!State) + return; + + State = EnsureGetdelimBufferAndSizeCorrect(LinePtrPtrSVal, SizePtrSval, + Call.getArgExpr(0), + Call.getArgExpr(1), C, State); + if (!State) + return; + + C.addTransition(State); +} + //===----------------------------------------------------------------------===// // pthread_once //===----------------------------------------------------------------------===// void UnixAPIMisuseChecker::CheckPthreadOnce(CheckerContext &C, - const CallExpr *CE) const { + const CallEvent &Call) const { // This is similar to 'CheckDispatchOnce' in the MacOSXAPIChecker. // They can possibly be refactored. - if (CE->getNumArgs() < 1) + if (Call.getNumArgs() < 1) return; // Check if the first argument is stack allocated. If so, issue a warning // because that's likely to be bad news. ProgramStateRef state = C.getState(); - const MemRegion *R = C.getSVal(CE->getArg(0)).getAsRegion(); + const MemRegion *R = Call.getArgSVal(0).getAsRegion(); if (!R || !isa<StackSpaceRegion>(R->getMemorySpace())) return; @@ -304,7 +432,7 @@ void UnixAPIMisuseChecker::CheckPthreadOnce(CheckerContext &C, auto report = std::make_unique<PathSensitiveBugReport>(BT_pthreadOnce, os.str(), N); - report->addRange(CE->getArg(0)->getSourceRange()); + report->addRange(Call.getArgExpr(0)->getSourceRange()); C.emitReport(std::move(report)); } diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp index 1a9d6d3127fb7f48bbfec8f686799c5cf97c6b9d..b36fa95bc73f3ee48eb49717544724a55b0bb598 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp @@ -43,8 +43,7 @@ tryToFindPtrOrigin(const Expr *E, bool StopAtFirstRefCountedObj) { if (auto *call = dyn_cast<CallExpr>(E)) { if (auto *memberCall = dyn_cast<CXXMemberCallExpr>(call)) { if (auto *decl = memberCall->getMethodDecl()) { - std::optional<bool> IsGetterOfRefCt = - isGetterOfRefCounted(memberCall->getMethodDecl()); + std::optional<bool> IsGetterOfRefCt = isGetterOfRefCounted(decl); if (IsGetterOfRefCt && *IsGetterOfRefCt) { E = memberCall->getImplicitObjectArgument(); if (StopAtFirstRefCountedObj) { diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index 3617fdd778e3ca048834dd1d1f62b5ee27888a45..14ca507a16d5503c8d794a34a820e47906696fc8 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -138,7 +138,8 @@ public: public: PathDiagnosticConstruct(const PathDiagnosticConsumer *PDC, const ExplodedNode *ErrorNode, - const PathSensitiveBugReport *R); + const PathSensitiveBugReport *R, + const Decl *AnalysisEntryPoint); /// \returns the location context associated with the current position in the /// bug path. @@ -1323,24 +1324,26 @@ void PathDiagnosticBuilder::generatePathDiagnosticsForNode( } static std::unique_ptr<PathDiagnostic> -generateDiagnosticForBasicReport(const BasicBugReport *R) { +generateDiagnosticForBasicReport(const BasicBugReport *R, + const Decl *AnalysisEntryPoint) { const BugType &BT = R->getBugType(); return std::make_unique<PathDiagnostic>( BT.getCheckerName(), R->getDeclWithIssue(), BT.getDescription(), R->getDescription(), R->getShortDescription(/*UseFallback=*/false), BT.getCategory(), R->getUniqueingLocation(), R->getUniqueingDecl(), - std::make_unique<FilesToLineNumsMap>()); + AnalysisEntryPoint, std::make_unique<FilesToLineNumsMap>()); } static std::unique_ptr<PathDiagnostic> generateEmptyDiagnosticForReport(const PathSensitiveBugReport *R, - const SourceManager &SM) { + const SourceManager &SM, + const Decl *AnalysisEntryPoint) { const BugType &BT = R->getBugType(); return std::make_unique<PathDiagnostic>( BT.getCheckerName(), R->getDeclWithIssue(), BT.getDescription(), R->getDescription(), R->getShortDescription(/*UseFallback=*/false), BT.getCategory(), R->getUniqueingLocation(), R->getUniqueingDecl(), - findExecutedLines(SM, R->getErrorNode())); + AnalysisEntryPoint, findExecutedLines(SM, R->getErrorNode())); } static const Stmt *getStmtParent(const Stmt *S, const ParentMap &PM) { @@ -1976,10 +1979,11 @@ static void updateExecutedLinesWithDiagnosticPieces(PathDiagnostic &PD) { PathDiagnosticConstruct::PathDiagnosticConstruct( const PathDiagnosticConsumer *PDC, const ExplodedNode *ErrorNode, - const PathSensitiveBugReport *R) + const PathSensitiveBugReport *R, const Decl *AnalysisEntryPoint) : Consumer(PDC), CurrentNode(ErrorNode), SM(CurrentNode->getCodeDecl().getASTContext().getSourceManager()), - PD(generateEmptyDiagnosticForReport(R, getSourceManager())) { + PD(generateEmptyDiagnosticForReport(R, getSourceManager(), + AnalysisEntryPoint)) { LCM[&PD->getActivePath()] = ErrorNode->getLocationContext(); } @@ -1993,13 +1997,14 @@ PathDiagnosticBuilder::PathDiagnosticBuilder( std::unique_ptr<PathDiagnostic> PathDiagnosticBuilder::generate(const PathDiagnosticConsumer *PDC) const { - PathDiagnosticConstruct Construct(PDC, ErrorNode, R); + const Decl *EntryPoint = getBugReporter().getAnalysisEntryPoint(); + PathDiagnosticConstruct Construct(PDC, ErrorNode, R, EntryPoint); const SourceManager &SM = getSourceManager(); const AnalyzerOptions &Opts = getAnalyzerOptions(); if (!PDC->shouldGenerateDiagnostics()) - return generateEmptyDiagnosticForReport(R, getSourceManager()); + return generateEmptyDiagnosticForReport(R, getSourceManager(), EntryPoint); // Construct the final (warning) event for the bug report. auto EndNotes = VisitorsDiagnostics->find(ErrorNode); @@ -3123,6 +3128,16 @@ void BugReporter::FlushReport(BugReportEquivClass& EQ) { Pieces.back()->addFixit(I); updateExecutedLinesWithDiagnosticPieces(*PD); + + // If we are debugging, let's have the entry point as the first note. + if (getAnalyzerOptions().AnalyzerDisplayProgress || + getAnalyzerOptions().AnalyzerNoteAnalysisEntryPoints) { + const Decl *EntryPoint = getAnalysisEntryPoint(); + Pieces.push_front(std::make_shared<PathDiagnosticEventPiece>( + PathDiagnosticLocation{EntryPoint->getLocation(), getSourceManager()}, + "[debug] analyzing from " + + AnalysisDeclContext::getFunctionName(EntryPoint))); + } Consumer->HandlePathDiagnostic(std::move(PD)); } } @@ -3211,7 +3226,8 @@ BugReporter::generateDiagnosticForConsumerMap( auto *basicReport = cast<BasicBugReport>(exampleReport); auto Out = std::make_unique<DiagnosticForConsumerMapTy>(); for (auto *Consumer : consumers) - (*Out)[Consumer] = generateDiagnosticForBasicReport(basicReport); + (*Out)[Consumer] = + generateDiagnosticForBasicReport(basicReport, AnalysisEntryPoint); return Out; } diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp index bc14aea27f6736e8e0c9b3a4344fdaff65d83fb5..0e317ec765ec09d87ca419354994f59ca17a0480 100644 --- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -1408,9 +1408,12 @@ CallEventManager::getSimpleCall(const CallExpr *CE, ProgramStateRef State, if (const auto *OpCE = dyn_cast<CXXOperatorCallExpr>(CE)) { const FunctionDecl *DirectCallee = OpCE->getDirectCallee(); - if (const auto *MD = dyn_cast<CXXMethodDecl>(DirectCallee)) + if (const auto *MD = dyn_cast<CXXMethodDecl>(DirectCallee)) { if (MD->isImplicitObjectMemberFunction()) return create<CXXMemberOperatorCall>(OpCE, State, LCtx, ElemRef); + if (MD->isStatic()) + return create<CXXStaticOperatorCall>(OpCE, State, LCtx, ElemRef); + } } else if (CE->getCallee()->getType()->isBlockPointerType()) { return create<BlockCall>(CE, State, LCtx, ElemRef); diff --git a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp index d6d4cec9dd3d4d01dd5ab2ffb9fbbeab337e4ddb..1a9bff529e9bb124eff2747629b93e52c0535c75 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp @@ -87,9 +87,11 @@ bool CheckerContext::isCLibraryFunction(const FunctionDecl *FD, if (!II) return false; - // Look through 'extern "C"' and anything similar invented in the future. - // If this function is not in TU directly, it is not a C library function. - if (!FD->getDeclContext()->getRedeclContext()->isTranslationUnit()) + // C library functions are either declared directly within a TU (the common + // case) or they are accessed through the namespace `std` (when they are used + // in C++ via headers like <cstdlib>). + const DeclContext *DC = FD->getDeclContext()->getRedeclContext(); + if (!(DC->isTranslationUnit() || DC->isStdNamespace())) return false; // If this function is not externally visible, it is not a C library function. diff --git a/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp b/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp index 364c87e910b7b51a28c68705dbe8faadc6197cd1..d7137a915b3d3dda7e40afc16ae51a5e2835902b 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp @@ -183,10 +183,9 @@ OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK, } } -std::optional<DefinedSVal> getPointeeDefVal(SVal PtrSVal, - ProgramStateRef State) { +std::optional<SVal> getPointeeVal(SVal PtrSVal, ProgramStateRef State) { if (const auto *Ptr = PtrSVal.getAsRegion()) { - return State->getSVal(Ptr).getAs<DefinedSVal>(); + return State->getSVal(Ptr); } return std::nullopt; } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index c3fc56ac30ee9fd01345d42c864a67a63d8161ea..7a900780384a91db8f98b73d7e0ec8ae0207c094 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -330,7 +330,8 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, case CK_ConstructorConversion: case CK_UserDefinedConversion: case CK_FunctionToPointerDecay: - case CK_BuiltinFnToFnPtr: { + case CK_BuiltinFnToFnPtr: + case CK_HLSLArrayRValue: { // Copy the SVal of Ex to CastE. ProgramStateRef state = Pred->getState(); const LocationContext *LCtx = Pred->getLocationContext(); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index 4755b6bfa6dc0ab1cb17108317377ddd5b3592ba..9d3e4fc944fb7b74ee5fe9beabab11f65c02e200 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -846,6 +846,7 @@ ExprEngine::mayInlineCallKind(const CallEvent &Call, const ExplodedNode *Pred, const StackFrameContext *CallerSFC = CurLC->getStackFrame(); switch (Call.getKind()) { case CE_Function: + case CE_CXXStaticOperator: case CE_Block: break; case CE_CXXMember: diff --git a/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp b/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp index a80352816be6134337c81cde9c68343069a6e4d0..7042f1aeb803fcd66443ddd479f4f740ce1873f1 100644 --- a/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp +++ b/clang/lib/StaticAnalyzer/Core/LoopUnrolling.cpp @@ -190,6 +190,17 @@ static bool isCapturedByReference(ExplodedNode *N, const DeclRefExpr *DR) { return FD->getType()->isReferenceType(); } +static bool isFoundInStmt(const Stmt *S, const VarDecl *VD) { + if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) { + for (const Decl *D : DS->decls()) { + // Once we reach the declaration of the VD we can return. + if (D->getCanonicalDecl() == VD) + return true; + } + } + return false; +} + // A loop counter is considered escaped if: // case 1: It is a global variable. // case 2: It is a reference parameter or a reference capture. @@ -219,13 +230,19 @@ static bool isPossiblyEscaped(ExplodedNode *N, const DeclRefExpr *DR) { continue; } - if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) { - for (const Decl *D : DS->decls()) { - // Once we reach the declaration of the VD we can return. - if (D->getCanonicalDecl() == VD) - return false; + if (isFoundInStmt(S, VD)) { + return false; + } + + if (const auto *SS = dyn_cast<SwitchStmt>(S)) { + if (const auto *CST = dyn_cast<CompoundStmt>(SS->getBody())) { + for (const Stmt *CB : CST->body()) { + if (isFoundInStmt(CB, VD)) + return false; + } } } + // Check the usage of the pass-by-ref function calls and adress-of operator // on VD and reference initialized by VD. ASTContext &ASTCtx = diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index 16db6b249dc92b5c0f71e38c57e75bd4d41f3552..d6e4f23cc353f153c2db094ec625d7883f369cb6 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -720,13 +720,21 @@ std::string MemRegion::getDescriptiveName(bool UseQuotes) const { CI->getValue().toString(Idx); ArrayIndices = (llvm::Twine("[") + Idx.str() + "]" + ArrayIndices).str(); } - // If not a ConcreteInt, try to obtain the variable - // name by calling 'getDescriptiveName' recursively. + // Index is symbolic, but may have a descriptive name. else { - std::string Idx = ER->getDescriptiveName(false); - if (!Idx.empty()) { - ArrayIndices = (llvm::Twine("[") + Idx + "]" + ArrayIndices).str(); - } + auto SI = ER->getIndex().getAs<nonloc::SymbolVal>(); + if (!SI) + return ""; + + const MemRegion *OR = SI->getAsSymbol()->getOriginRegion(); + if (!OR) + return ""; + + std::string Idx = OR->getDescriptiveName(false); + if (Idx.empty()) + return ""; + + ArrayIndices = (llvm::Twine("[") + Idx + "]" + ArrayIndices).str(); } R = ER->getSuperRegion(); } @@ -817,7 +825,7 @@ DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR, }; auto IsArrayOfZero = [](const ArrayType *AT) { const auto *CAT = dyn_cast<ConstantArrayType>(AT); - return CAT && CAT->getSize() == 0; + return CAT && CAT->isZeroSize(); }; auto IsArrayOfOne = [](const ArrayType *AT) { const auto *CAT = dyn_cast<ConstantArrayType>(AT); diff --git a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp index f12f1a5ac970dd7709d49c9b5a8d6ce9e8b127cc..f82cd944750a3c6ba6a49011e941addfec9546db 100644 --- a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -226,6 +226,20 @@ ProgramStateRef ProgramState::killBinding(Loc LV) const { return makeWithStore(newStore); } +/// SymbolicRegions are expected to be wrapped by an ElementRegion as a +/// canonical representation. As a canonical representation, SymbolicRegions +/// should be wrapped by ElementRegions before getting a FieldRegion. +/// See f8643a9b31c4029942f67d4534c9139b45173504 why. +SVal ProgramState::wrapSymbolicRegion(SVal Val) const { + const auto *BaseReg = dyn_cast_or_null<SymbolicRegion>(Val.getAsRegion()); + if (!BaseReg) + return Val; + + StoreManager &SM = getStateManager().getStoreManager(); + QualType ElemTy = BaseReg->getPointeeStaticType(); + return loc::MemRegionVal{SM.GetElementZeroRegion(BaseReg, ElemTy)}; +} + ProgramStateRef ProgramState::enterStackFrame(const CallEvent &Call, const StackFrameContext *CalleeCtx) const { @@ -451,6 +465,24 @@ void ProgramState::setStore(const StoreRef &newStore) { store = newStoreStore; } +SVal ProgramState::getLValue(const FieldDecl *D, SVal Base) const { + Base = wrapSymbolicRegion(Base); + return getStateManager().StoreMgr->getLValueField(D, Base); +} + +SVal ProgramState::getLValue(const IndirectFieldDecl *D, SVal Base) const { + StoreManager &SM = *getStateManager().StoreMgr; + Base = wrapSymbolicRegion(Base); + + // FIXME: This should work with `SM.getLValueField(D->getAnonField(), Base)`, + // but that would break some tests. There is probably a bug somewhere that it + // would expose. + for (const auto *I : D->chain()) { + Base = SM.getLValueField(cast<FieldDecl>(I), Base); + } + return Base; +} + //===----------------------------------------------------------------------===// // State pretty-printing. //===----------------------------------------------------------------------===// diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index da9a1a1a4d1f6945713311ddd02d2e7ea47f879f..755a8c4b22fd9e907a68de2fbd3ec441ac29a8ec 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1166,7 +1166,7 @@ void InvalidateRegionsWorker::VisitCluster(const MemRegion *baseR, // Compute lower and upper offsets for region within array. if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) - NumElements = CAT->getSize().getZExtValue(); + NumElements = CAT->getZExtSize(); if (!NumElements) // We are not dealing with a constant size array goto conjure_default; QualType ElementTy = AT->getElementType(); @@ -1613,7 +1613,7 @@ getConstantArrayExtents(const ConstantArrayType *CAT) { CAT = cast<ConstantArrayType>(CAT->getCanonicalTypeInternal()); SmallVector<uint64_t, 2> Extents; do { - Extents.push_back(CAT->getSize().getZExtValue()); + Extents.push_back(CAT->getZExtSize()); } while ((CAT = dyn_cast<ConstantArrayType>(CAT->getElementType()))); return Extents; } @@ -2436,7 +2436,7 @@ std::optional<RegionBindingsRef> RegionStoreManager::tryBindSmallArray( return std::nullopt; // If the array is too big, create a LCV instead. - uint64_t ArrSize = CAT->getSize().getLimitedValue(); + uint64_t ArrSize = CAT->getLimitedSize(); if (ArrSize > SmallArrayLimit) return std::nullopt; @@ -2465,7 +2465,7 @@ RegionStoreManager::bindArray(RegionBindingsConstRef B, std::optional<uint64_t> Size; if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT)) - Size = CAT->getSize().getZExtValue(); + Size = CAT->getZExtSize(); // Check if the init expr is a literal. If so, bind the rvalue instead. // FIXME: It's not responsibility of the Store to transform this lvalue diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index b6ef40595e3c97a5e218516f84d5d325263a7540..03bc40804d73287319326af9a981e8bc8f4331af 100644 --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -527,7 +527,8 @@ static void reportAnalyzerFunctionMisuse(const AnalyzerOptions &Opts, void AnalysisConsumer::runAnalysisOnTranslationUnit(ASTContext &C) { BugReporter BR(*Mgr); - TranslationUnitDecl *TU = C.getTranslationUnitDecl(); + const TranslationUnitDecl *TU = C.getTranslationUnitDecl(); + BR.setAnalysisEntryPoint(TU); if (SyntaxCheckTimer) SyntaxCheckTimer->startTimer(); checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR); @@ -675,6 +676,7 @@ void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode, DisplayFunction(D, Mode, IMode); BugReporter BR(*Mgr); + BR.setAnalysisEntryPoint(D); if (Mode & AM_Syntax) { llvm::TimeRecord CheckerStartTime; diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp index 1b750cec41e1cc428b336b9e862595602eb410d7..9b7812a1adb9e32e8ec532d94eabbe494effe142 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp @@ -41,24 +41,25 @@ DependencyScanningWorkerFilesystem::readFile(StringRef Filename) { return TentativeEntry(Stat, std::move(Buffer)); } -EntryRef DependencyScanningWorkerFilesystem::scanForDirectivesIfNecessary( - const CachedFileSystemEntry &Entry, StringRef Filename, bool Disable) { - if (Entry.isError() || Entry.isDirectory() || Disable || - !shouldScanForDirectives(Filename)) - return EntryRef(Filename, Entry); +bool DependencyScanningWorkerFilesystem::ensureDirectiveTokensArePopulated( + EntryRef Ref) { + auto &Entry = Ref.Entry; + + if (Entry.isError() || Entry.isDirectory()) + return false; CachedFileContents *Contents = Entry.getCachedContents(); assert(Contents && "contents not initialized"); // Double-checked locking. if (Contents->DepDirectives.load()) - return EntryRef(Filename, Entry); + return true; std::lock_guard<std::mutex> GuardLock(Contents->ValueLock); // Double-checked locking. if (Contents->DepDirectives.load()) - return EntryRef(Filename, Entry); + return true; SmallVector<dependency_directives_scan::Directive, 64> Directives; // Scan the file for preprocessor directives that might affect the @@ -69,16 +70,16 @@ EntryRef DependencyScanningWorkerFilesystem::scanForDirectivesIfNecessary( Contents->DepDirectiveTokens.clear(); // FIXME: Propagate the diagnostic if desired by the client. Contents->DepDirectives.store(new std::optional<DependencyDirectivesTy>()); - return EntryRef(Filename, Entry); + return false; } // This function performed double-checked locking using `DepDirectives`. // Assigning it must be the last thing this function does, otherwise other - // threads may skip the - // critical section (`DepDirectives != nullptr`), leading to a data race. + // threads may skip the critical section (`DepDirectives != nullptr`), leading + // to a data race. Contents->DepDirectives.store( new std::optional<DependencyDirectivesTy>(std::move(Directives))); - return EntryRef(Filename, Entry); + return true; } DependencyScanningFilesystemSharedCache:: @@ -161,34 +162,11 @@ DependencyScanningFilesystemSharedCache::CacheShard:: return *EntriesByFilename.insert({Filename, &Entry}).first->getValue(); } -/// Whitelist file extensions that should be minimized, treating no extension as -/// a source file that should be minimized. -/// -/// This is kinda hacky, it would be better if we knew what kind of file Clang -/// was expecting instead. -static bool shouldScanForDirectivesBasedOnExtension(StringRef Filename) { - StringRef Ext = llvm::sys::path::extension(Filename); - if (Ext.empty()) - return true; // C++ standard library - return llvm::StringSwitch<bool>(Ext) - .CasesLower(".c", ".cc", ".cpp", ".c++", ".cxx", true) - .CasesLower(".h", ".hh", ".hpp", ".h++", ".hxx", true) - .CasesLower(".m", ".mm", true) - .CasesLower(".i", ".ii", ".mi", ".mmi", true) - .CasesLower(".def", ".inc", true) - .Default(false); -} - static bool shouldCacheStatFailures(StringRef Filename) { StringRef Ext = llvm::sys::path::extension(Filename); if (Ext.empty()) return false; // This may be the module cache directory. - // Only cache stat failures on files that are not expected to change during - // the build. - StringRef FName = llvm::sys::path::filename(Filename); - if (FName == "module.modulemap" || FName == "module.map") - return true; - return shouldScanForDirectivesBasedOnExtension(Filename); + return true; } DependencyScanningWorkerFilesystem::DependencyScanningWorkerFilesystem( @@ -201,11 +179,6 @@ DependencyScanningWorkerFilesystem::DependencyScanningWorkerFilesystem( updateWorkingDirForCacheLookup(); } -bool DependencyScanningWorkerFilesystem::shouldScanForDirectives( - StringRef Filename) { - return shouldScanForDirectivesBasedOnExtension(Filename); -} - const CachedFileSystemEntry & DependencyScanningWorkerFilesystem::getOrEmplaceSharedEntryForUID( TentativeEntry TEntry) { @@ -259,7 +232,7 @@ DependencyScanningWorkerFilesystem::computeAndStoreResult( llvm::ErrorOr<EntryRef> DependencyScanningWorkerFilesystem::getOrCreateFileSystemEntry( - StringRef OriginalFilename, bool DisableDirectivesScanning) { + StringRef OriginalFilename) { StringRef FilenameForLookup; SmallString<256> PathBuf; if (llvm::sys::path::is_absolute_gnu(OriginalFilename)) { @@ -276,15 +249,11 @@ DependencyScanningWorkerFilesystem::getOrCreateFileSystemEntry( assert(llvm::sys::path::is_absolute_gnu(FilenameForLookup)); if (const auto *Entry = findEntryByFilenameWithWriteThrough(FilenameForLookup)) - return scanForDirectivesIfNecessary(*Entry, OriginalFilename, - DisableDirectivesScanning) - .unwrapError(); + return EntryRef(OriginalFilename, *Entry).unwrapError(); auto MaybeEntry = computeAndStoreResult(OriginalFilename, FilenameForLookup); if (!MaybeEntry) return MaybeEntry.getError(); - return scanForDirectivesIfNecessary(*MaybeEntry, OriginalFilename, - DisableDirectivesScanning) - .unwrapError(); + return EntryRef(OriginalFilename, *MaybeEntry).unwrapError(); } llvm::ErrorOr<llvm::vfs::Status> diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index 76f3d950a13b8100f27642dd24be405709d29399..492b8f1e2b3863dabc02e4fcb34dbd7be11afc32 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -363,19 +363,22 @@ public: PrebuiltModuleVFSMap, ScanInstance.getDiagnostics())) return false; - // Use the dependency scanning optimized file system if requested to do so. - if (DepFS) { - llvm::IntrusiveRefCntPtr<DependencyScanningWorkerFilesystem> LocalDepFS = - DepFS; - ScanInstance.getPreprocessorOpts().DependencyDirectivesForFile = - [LocalDepFS = std::move(LocalDepFS)](FileEntryRef File) - -> std::optional<ArrayRef<dependency_directives_scan::Directive>> { - if (llvm::ErrorOr<EntryRef> Entry = - LocalDepFS->getOrCreateFileSystemEntry(File.getName())) - return Entry->getDirectiveTokens(); - return std::nullopt; - }; - } + auto AdjustCI = [&](CompilerInstance &CI) { + // Set up the dependency scanning file system callback if requested. + if (DepFS) { + auto GetDependencyDirectives = [LocalDepFS = DepFS](FileEntryRef File) + -> std::optional<ArrayRef<dependency_directives_scan::Directive>> { + if (llvm::ErrorOr<EntryRef> Entry = + LocalDepFS->getOrCreateFileSystemEntry(File.getName())) + if (LocalDepFS->ensureDirectiveTokensArePopulated(*Entry)) + return Entry->getDirectiveTokens(); + return std::nullopt; + }; + + CI.getPreprocessor().setDependencyDirectivesFn( + std::move(GetDependencyDirectives)); + } + }; // Create the dependency collector that will collect the produced // dependencies. @@ -427,9 +430,11 @@ public: std::unique_ptr<FrontendAction> Action; if (ModuleName) - Action = std::make_unique<GetDependenciesByModuleNameAction>(*ModuleName); + Action = std::make_unique<GetDependenciesByModuleNameAction>( + *ModuleName, std::move(AdjustCI)); else - Action = std::make_unique<ReadPCHAndPreprocessAction>(); + Action = + std::make_unique<ReadPCHAndPreprocessAction>(std::move(AdjustCI)); if (ScanInstance.getDiagnostics().hasErrorOccurred()) return false; diff --git a/clang/lib/Tooling/Inclusions/Stdlib/CSpecialSymbolMap.inc b/clang/lib/Tooling/Inclusions/Stdlib/CSpecialSymbolMap.inc new file mode 100644 index 0000000000000000000000000000000000000000..a515f69ea6a8cf0cc7ed1209299e7004ffafe15c --- /dev/null +++ b/clang/lib/Tooling/Inclusions/Stdlib/CSpecialSymbolMap.inc @@ -0,0 +1,14 @@ +//===-- StdSpecialSymbolMap.inc -----------------------------------*- C -*-===// +// +// This is a hand-curated list for C symbols that cannot be parsed/extracted +// via the include-mapping tool (gen_std.py). +// +//===----------------------------------------------------------------------===// + +SYMBOL(size_t, None, <stddef.h>) +SYMBOL(size_t, None, <stdio.h>) +SYMBOL(size_t, None, <stdlib.h>) +SYMBOL(size_t, None, <string.h>) +SYMBOL(size_t, None, <time.h>) +SYMBOL(size_t, None, <uchar.h>) +SYMBOL(size_t, None, <wchar.h>) diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp index adf1b230ff0318132b5d4e17db0aef2907be777b..0832bcf66145faf83d5bb38c8d4eba593f9ac479 100644 --- a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp +++ b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp @@ -55,11 +55,12 @@ static const SymbolHeaderMapping *getMappingPerLang(Lang L) { } static int countSymbols(Lang Language) { - ArrayRef<const char*> Symbols; + ArrayRef<const char *> Symbols; #define SYMBOL(Name, NS, Header) #NS #Name, switch (Language) { case Lang::C: { static constexpr const char *CSymbols[] = { +#include "CSpecialSymbolMap.inc" #include "CSymbolMap.inc" }; Symbols = CSymbols; @@ -147,6 +148,7 @@ static int initialize(Lang Language) { switch (Language) { case Lang::C: { static constexpr Symbol CSymbols[] = { +#include "CSpecialSymbolMap.inc" #include "CSymbolMap.inc" }; for (const Symbol &S : CSymbols) diff --git a/clang/test/APINotes/Inputs/APINotes/SomeOtherKit.apinotes b/clang/test/APINotes/Inputs/APINotes/SomeOtherKit.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..ccdc4e15d34d1b236332923843765d50ee8d976b --- /dev/null +++ b/clang/test/APINotes/Inputs/APINotes/SomeOtherKit.apinotes @@ -0,0 +1,8 @@ +Name: SomeOtherKit +Classes: + - Name: A + Methods: + - Selector: "methodB" + MethodKind: Instance + Availability: none + AvailabilityMsg: "anything but this" diff --git a/clang/test/APINotes/Inputs/BrokenHeaders/APINotes.apinotes b/clang/test/APINotes/Inputs/BrokenHeaders/APINotes.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..cd5475b1342315947390b65aca0f4640194fb946 --- /dev/null +++ b/clang/test/APINotes/Inputs/BrokenHeaders/APINotes.apinotes @@ -0,0 +1,5 @@ +Name: SomeBrokenLib +Functions: + - Name: do_something_with_pointers + Nu llabilityOfRet: O + # the space is intentional, to make sure we don't crash on malformed API Notes diff --git a/clang/test/APINotes/Inputs/BrokenHeaders/SomeBrokenLib.h b/clang/test/APINotes/Inputs/BrokenHeaders/SomeBrokenLib.h new file mode 100644 index 0000000000000000000000000000000000000000..b09c6f63eae02edcf0228bebec1a3f504085bb2d --- /dev/null +++ b/clang/test/APINotes/Inputs/BrokenHeaders/SomeBrokenLib.h @@ -0,0 +1,6 @@ +#ifndef SOME_BROKEN_LIB_H +#define SOME_BROKEN_LIB_H + +void do_something_with_pointers(int *ptr1, int *ptr2); + +#endif // SOME_BROKEN_LIB_H diff --git a/clang/test/APINotes/Inputs/BrokenHeaders2/APINotes.apinotes b/clang/test/APINotes/Inputs/BrokenHeaders2/APINotes.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..33eeaaada999d69f0bcb106598407226736abac4 --- /dev/null +++ b/clang/test/APINotes/Inputs/BrokenHeaders2/APINotes.apinotes @@ -0,0 +1,7 @@ +Name: SomeBrokenLib +Functions: + - Name: do_something_with_pointers + NullabilityOfRet: O + - Name: do_something_with_pointers + NullabilityOfRet: O + diff --git a/clang/test/APINotes/Inputs/BrokenHeaders2/SomeBrokenLib.h b/clang/test/APINotes/Inputs/BrokenHeaders2/SomeBrokenLib.h new file mode 100644 index 0000000000000000000000000000000000000000..b09c6f63eae02edcf0228bebec1a3f504085bb2d --- /dev/null +++ b/clang/test/APINotes/Inputs/BrokenHeaders2/SomeBrokenLib.h @@ -0,0 +1,6 @@ +#ifndef SOME_BROKEN_LIB_H +#define SOME_BROKEN_LIB_H + +void do_something_with_pointers(int *ptr1, int *ptr2); + +#endif // SOME_BROKEN_LIB_H diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Headers/FrameworkWithActualPrivateModule.h b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Headers/FrameworkWithActualPrivateModule.h new file mode 100644 index 0000000000000000000000000000000000000000..523de4f7ce0857b950f8d9a810db3db5e3c27545 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Headers/FrameworkWithActualPrivateModule.h @@ -0,0 +1 @@ +extern int FrameworkWithActualPrivateModule; diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..859d723716be217eb69f4474d1a1e82ab5d3c536 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module FrameworkWithActualPrivateModule { + umbrella header "FrameworkWithActualPrivateModule.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.private.modulemap b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.private.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..e7fafe3bcbb17faf02b5f929eb22512ee698f02a --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/Modules/module.private.modulemap @@ -0,0 +1,5 @@ +framework module FrameworkWithActualPrivateModule_Private { + umbrella header "FrameworkWithActualPrivateModule_Private.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.apinotes b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..831cf1e93d35191f02b5af8d98b07a27ee257b44 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.apinotes @@ -0,0 +1 @@ +Name: FrameworkWithActualPrivateModule_Private diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.h b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.h new file mode 100644 index 0000000000000000000000000000000000000000..c07a3e95d740491d7c83b6317e5de75dd92c3943 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithActualPrivateModule.framework/PrivateHeaders/FrameworkWithActualPrivateModule_Private.h @@ -0,0 +1,2 @@ +#include <FrameworkWithActualPrivateModule/FrameworkWithActualPrivateModule.h> +extern int FrameworkWithActualPrivateModule_Private; diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Headers/FrameworkWithWrongCase.h b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Headers/FrameworkWithWrongCase.h new file mode 100644 index 0000000000000000000000000000000000000000..4f3b631c27e30d0f7726d652138d50e3e24970c0 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Headers/FrameworkWithWrongCase.h @@ -0,0 +1 @@ +extern int FrameworkWithWrongCase; diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..e97d361039a150ff26e3b6ac39cd7e4887a7df08 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module FrameworkWithWrongCase { + umbrella header "FrameworkWithWrongCase.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/PrivateHeaders/FrameworkWithWrongCase_Private.apinotes b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/PrivateHeaders/FrameworkWithWrongCase_Private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..ae5447c61e33d08b400e2ece9608f34116ed94a3 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCase.framework/PrivateHeaders/FrameworkWithWrongCase_Private.apinotes @@ -0,0 +1 @@ +Name: FrameworkWithWrongCase diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Headers/FrameworkWithWrongCasePrivate.h b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Headers/FrameworkWithWrongCasePrivate.h new file mode 100644 index 0000000000000000000000000000000000000000..d3d61483191c6e017532bdaaa8f8b338bd79c325 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Headers/FrameworkWithWrongCasePrivate.h @@ -0,0 +1 @@ +extern int FrameworkWithWrongCasePrivate; diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..04b96adbbfeb99e45d4a6c33c7f23acced1fffb8 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module FrameworkWithWrongCasePrivate { + umbrella header "FrameworkWithWrongCasePrivate.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.private.modulemap b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.private.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..d6ad53cdc717970a0e9fc3bc0a60f73fa50c578d --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/Modules/module.private.modulemap @@ -0,0 +1 @@ +module FrameworkWithWrongCasePrivate.Inner {} diff --git a/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/PrivateHeaders/FrameworkWithWrongCasePrivate_Private.apinotes b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/PrivateHeaders/FrameworkWithWrongCasePrivate_Private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..d7af293e8125f1023d2bc490837f2496637ca8e8 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/FrameworkWithWrongCasePrivate.framework/PrivateHeaders/FrameworkWithWrongCasePrivate_Private.apinotes @@ -0,0 +1 @@ +Name: FrameworkWithWrongCasePrivate diff --git a/clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Headers/LayeredKit.h b/clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Headers/LayeredKit.h new file mode 100644 index 0000000000000000000000000000000000000000..a95d19ecbe9afc32a1e9c33e21394f737d804ef7 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Headers/LayeredKit.h @@ -0,0 +1,11 @@ +@import LayeredKitImpl; + +// @interface declarations already don't inherit attributes from forward +// declarations, so in order to test this properly we have to /not/ define +// UpwardClass anywhere. + +// @interface UpwardClass +// @end + +@protocol UpwardProto +@end diff --git a/clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..04bbe72a2b6e25cba06ac3ccb1d5957f46ce32ef --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/LayeredKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module LayeredKit { + umbrella header "LayeredKit.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.apinotes b/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..bece28cfe60577b114e748af5cf8b255a64a23e5 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.apinotes @@ -0,0 +1,9 @@ +Name: LayeredKitImpl +Classes: +- Name: PerfectlyNormalClass + Availability: none +- Name: UpwardClass + Availability: none +Protocols: +- Name: UpwardProto + Availability: none diff --git a/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.h b/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..99591d35803aa1be2eb15e9966a2459a536eb712 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Headers/LayeredKitImpl.h @@ -0,0 +1,7 @@ +@protocol UpwardProto; +@class UpwardClass; + +@interface PerfectlyNormalClass +@end + +void doImplementationThings(UpwardClass *first, id <UpwardProto> second) __attribute((unavailable)); diff --git a/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..58a6e55c1067f99f460f3a17659a880aec6750d8 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/LayeredKitImpl.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module LayeredKitImpl { + umbrella header "LayeredKitImpl.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/SimpleKit.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/SimpleKit.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..2d07e76c0a142af0ee3fa016732a85f06d591531 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SimpleKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module SimpleKit { + umbrella header "SimpleKit.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit.apinotes b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..817af123fc77b6b42c7ef20047dbd327ac0abb47 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit.apinotes @@ -0,0 +1,74 @@ +Name: SomeKit +Classes: + - Name: A + Methods: + - Selector: "transform:" + MethodKind: Instance + Availability: none + AvailabilityMsg: "anything but this" + - Selector: "transform:integer:" + MethodKind: Instance + NullabilityOfRet: N + Nullability: [ N, S ] + Properties: + - Name: intValue + PropertyKind: Instance + Availability: none + AvailabilityMsg: "wouldn't work anyway" + - Name: nonnullAInstance + PropertyKind: Instance + Nullability: N + - Name: nonnullAClass + PropertyKind: Class + Nullability: N + - Name: nonnullABoth + Nullability: N + - Name: B + Availability: none + AvailabilityMsg: "just don't" + - Name: C + Methods: + - Selector: "initWithA:" + MethodKind: Instance + DesignatedInit: true + - Name: OverriddenTypes + Methods: + - Selector: "methodToMangle:second:" + MethodKind: Instance + ResultType: 'char *' + Parameters: + - Position: 0 + Type: 'SOMEKIT_DOUBLE *' + - Position: 1 + Type: 'float *' + Properties: + - Name: intPropertyToMangle + PropertyKind: Instance + Type: 'double *' +Functions: + - Name: global_int_fun + ResultType: 'char *' + Parameters: + - Position: 0 + Type: 'double *' + - Position: 1 + Type: 'float *' +Globals: + - Name: global_int_ptr + Type: 'double *' +SwiftVersions: + - Version: 3.0 + Classes: + - Name: A + Methods: + - Selector: "transform:integer:" + MethodKind: Instance + NullabilityOfRet: O + Nullability: [ O, S ] + Properties: + - Name: explicitNonnullInstance + PropertyKind: Instance + Nullability: O + - Name: explicitNullableInstance + PropertyKind: Instance + Nullability: N diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit_private.apinotes b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit_private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..28ede9dfa25c08d9fb5067fa9f76ba0309e478ad --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/APINotes/SomeKit_private.apinotes @@ -0,0 +1,15 @@ +Name: SomeKit +Classes: + - Name: A + Methods: + - Selector: "privateTransform:input:" + MethodKind: Instance + NullabilityOfRet: N + Nullability: [ N, S ] + Properties: + - Name: internalProperty + Nullability: N +Protocols: + - Name: InternalProtocol + Availability: none + AvailabilityMsg: "not for you" diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKitForNullAnnotation.h b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKitForNullAnnotation.h new file mode 100644 index 0000000000000000000000000000000000000000..bc0c5da8848e9a8aed9cf39a6d6194e1ea856d38 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKitForNullAnnotation.h @@ -0,0 +1,55 @@ +#ifndef SOMEKIT_H +#define SOMEKIT_H + +#define ROOT_CLASS __attribute__((objc_root_class)) + +ROOT_CLASS +@interface A +-(A*)transform:(A*)input; +-(A*)transform:(A*)input integer:(int)integer; + +@property (nonatomic, readonly, retain) A* someA; +@property (nonatomic, retain) A* someOtherA; + +@property (nonatomic) int intValue; +@end + +@interface B : A +@end + +@interface C : A +- (instancetype)init; +- (instancetype)initWithA:(A*)a; +@end + + +@interface MyClass : A +- Inst; ++ Clas; +@end + +struct CGRect { + float origin; + float size; +}; +typedef struct CGRect NSRect; + +@interface I +- (void) Meth : (NSRect[4])exposedRects; +- (void) Meth1 : (const I*)exposedRects; +- (void) Meth2 : (const I*)exposedRects; +- (void) Meth3 : (I*)exposedRects; +- (const I*) Meth4; +- (const I*) Meth5 : (int) Arg1 : (const I*)Arg2 : (double)Arg3 : (const I*) Arg4 :(const volatile id) Arg5; +- (volatile const I*) Meth6 : (const char *)Arg1 : (const char *)Arg2 : (double)Arg3 : (const I*) Arg4 :(const volatile id) Arg5; +@end + +@class NSURL, NSArray, NSError; +@interface INTF_BLOCKS + + (void)getNonLocalVersionsOfItemAtURL:(NSURL *)url completionHandler:(void (^)(NSArray *nonLocalFileVersions, NSError *error))completionHandler; + + (void *)getNonLocalVersionsOfItemAtURL2:(NSURL *)url completionHandler:(void (^)(NSArray *nonLocalFileVersions, NSError *error))completionHandler; + + (NSError **)getNonLocalVersionsOfItemAtURL3:(int)url completionHandler:(void (^)(NSArray *nonLocalFileVersions, NSError *error))completionHandler; + + (id)getNonLocalVersionsOfItemAtURL4:(NSURL *)url completionHandler:(void (^)(int nonLocalFileVersions, NSError *error, NSURL*))completionHandler; +@end + +#endif diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..3abee2df0be1b754b8c65ed9325cea261f08d246 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module SomeKit { + umbrella header "SomeKit.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.private.modulemap b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.private.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..bbda9d08e3993ee224df34e60339802e2a9e140f --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module.private.modulemap @@ -0,0 +1,8 @@ +module SomeKit.Private { + header "SomeKit_Private.h" + export * + + explicit module NullAnnotation { + header "SomeKit_PrivateForNullAnnotation.h" + } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module_private.modulemap b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module_private.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..e31034317cb82ac91c81b596256a83bec859d005 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Modules/module_private.modulemap @@ -0,0 +1,8 @@ +explicit framework module SomeKit.Private { + header "SomeKit_Private.h" + explicit NullAnnotation { header "SomeKit_PrivateForNullAnnotation.h" } + export * + module * { export * } +syntax error + +} diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_Private.h b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_Private.h new file mode 100644 index 0000000000000000000000000000000000000000..c7611123e4ad2f3240ee6f1d3361dacf28967a22 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_Private.h @@ -0,0 +1,16 @@ +#ifndef SOMEKIT_PRIVATE_H +#define SOMEKIT_PRIVATE_H + +#import <SomeKit/SomeKit.h> + +@interface A(Private) +-(A*)privateTransform:(A*)input; + +@property (nonatomic) A* internalProperty; +@end + +@protocol InternalProtocol +@end + +#endif + diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_PrivateForNullAnnotation.h b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_PrivateForNullAnnotation.h new file mode 100644 index 0000000000000000000000000000000000000000..bae4456b4080931af638d0d0585bb58b20a1f232 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_PrivateForNullAnnotation.h @@ -0,0 +1,17 @@ +#ifndef SOMEKIT_PRIVATE_H +#define SOMEKIT_PRIVATE_H + +#import <SomeKit/SomeKitForNullAnnotation.h> + +@interface A(Private) +-(A*)privateTransform:(A*)input; + +@property (nonatomic) A* internalProperty; +@end + +@protocol InternalProtocol +- (id) MomeMethod; +@end + +#endif + diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_private.apinotes b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..28ede9dfa25c08d9fb5067fa9f76ba0309e478ad --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/PrivateHeaders/SomeKit_private.apinotes @@ -0,0 +1,15 @@ +Name: SomeKit +Classes: + - Name: A + Methods: + - Selector: "privateTransform:input:" + MethodKind: Instance + NullabilityOfRet: N + Nullability: [ N, S ] + Properties: + - Name: internalProperty + Nullability: N +Protocols: + - Name: InternalProtocol + Availability: none + AvailabilityMsg: "not for you" diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/APINotes/SomeOtherKit.apinotes b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/APINotes/SomeOtherKit.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..2ad546b8f8bccaba7ae7db6b335237780035dd59 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/APINotes/SomeOtherKit.apinotes @@ -0,0 +1,8 @@ +Name: SomeOtherKit +Classes: + - Name: A + Methods: + - Selector: "methodA" + MethodKind: Instance + Availability: none + AvailabilityMsg: "anything but this" diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.apinotes b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..2ad546b8f8bccaba7ae7db6b335237780035dd59 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.apinotes @@ -0,0 +1,8 @@ +Name: SomeOtherKit +Classes: + - Name: A + Methods: + - Selector: "methodA" + MethodKind: Instance + Availability: none + AvailabilityMsg: "anything but this" diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.h b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.h new file mode 100644 index 0000000000000000000000000000000000000000..3911d765230c6991b433548644e2e3abab16b950 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.h @@ -0,0 +1,9 @@ +#ifndef SOME_OTHER_KIT_H + +__attribute__((objc_root_class)) +@interface A +-(void)methodA; +-(void)methodB; +@end + +#endif diff --git a/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..0aaad92e041ce34c31eb4768c2577aa25ca86721 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/SomeOtherKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module SomeOtherKit { + umbrella header "SomeOtherKit.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit.h b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit.h new file mode 100644 index 0000000000000000000000000000000000000000..d3376f1dac5d11a7e63878c0395bfc402c2279f7 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit.h @@ -0,0 +1 @@ +extern int TopLevelPrivateKit_Public; diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit_Private.apinotes b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit_Private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..ece1dd220adf52f2073481d35a9d4f469439169e --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Headers/TopLevelPrivateKit_Private.apinotes @@ -0,0 +1 @@ +garbage here because this file shouldn't get read \ No newline at end of file diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..70faa54e8347784186ec2131e4c9414cd3ec7db8 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module TopLevelPrivateKit { + umbrella header "TopLevelPrivateKit.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.private.modulemap b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.private.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..0958a14d67108920f8ccee1ae3faf2d2ef59e38d --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/Modules/module.private.modulemap @@ -0,0 +1,5 @@ +framework module TopLevelPrivateKit_Private { + umbrella header "TopLevelPrivateKit_Private.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit.apinotes b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..908dae0e3b0b24cc8c04430a659e1aa0ace59b6c --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit.apinotes @@ -0,0 +1 @@ +garbage here because this file shouldn't get read diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.apinotes b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..43323621588bb2afff5ff6e425a63f834fe9b1c7 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.apinotes @@ -0,0 +1,4 @@ +Name: TopLevelPrivateKit_Private +Globals: +- Name: TopLevelPrivateKit_Private + Type: float diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.h b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.h new file mode 100644 index 0000000000000000000000000000000000000000..39cbfe6e9918ba7a39d43de5c2cd10cb7331350b --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private.h @@ -0,0 +1 @@ +extern int TopLevelPrivateKit_Private; diff --git a/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private_private.apinotes b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private_private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..ece1dd220adf52f2073481d35a9d4f469439169e --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/TopLevelPrivateKit.framework/PrivateHeaders/TopLevelPrivateKit_Private_private.apinotes @@ -0,0 +1 @@ +garbage here because this file shouldn't get read \ No newline at end of file diff --git a/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes b/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..572c714b3d61a71703c5162624efdc27cb87d0fa --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes @@ -0,0 +1,156 @@ +Name: VersionedKit +Classes: + - Name: TestProperties + SwiftObjCMembers: true + Properties: + - Name: accessorsOnly + PropertyKind: Instance + SwiftImportAsAccessors: true + - Name: accessorsOnlyForClass + PropertyKind: Class + SwiftImportAsAccessors: true + - Name: accessorsOnlyExceptInVersion3 + PropertyKind: Instance + SwiftImportAsAccessors: true + - Name: accessorsOnlyForClassExceptInVersion3 + PropertyKind: Class + SwiftImportAsAccessors: true +Functions: + - Name: unversionedRenameDUMP + SwiftName: 'unversionedRename_NOTES()' +Tags: + - Name: APINotedFlagEnum + FlagEnum: true + - Name: APINotedOpenEnum + EnumExtensibility: open + - Name: APINotedClosedEnum + EnumExtensibility: closed + - Name: SoonToBeCFEnum + EnumKind: CFEnum + - Name: SoonToBeNSEnum + EnumKind: NSEnum + - Name: SoonToBeCFOptions + EnumKind: CFOptions + - Name: SoonToBeNSOptions + EnumKind: NSOptions + - Name: SoonToBeCFClosedEnum + EnumKind: CFClosedEnum + - Name: SoonToBeNSClosedEnum + EnumKind: NSClosedEnum + - Name: UndoAllThatHasBeenDoneToMe + EnumKind: none +Typedefs: + - Name: MultiVersionedTypedef34Notes + SwiftName: MultiVersionedTypedef34Notes_NEW + - Name: MultiVersionedTypedef345Notes + SwiftName: MultiVersionedTypedef345Notes_NEW + - Name: MultiVersionedTypedef4Notes + SwiftName: MultiVersionedTypedef4Notes_NEW + - Name: MultiVersionedTypedef45Notes + SwiftName: MultiVersionedTypedef45Notes_NEW +SwiftVersions: + - Version: 3.0 + Classes: + - Name: MyReferenceType + SwiftBridge: '' + - Name: TestGenericDUMP + SwiftImportAsNonGeneric: true + - Name: TestProperties + SwiftObjCMembers: false + Properties: + - Name: accessorsOnlyInVersion3 + PropertyKind: Instance + SwiftImportAsAccessors: true + - Name: accessorsOnlyForClassInVersion3 + PropertyKind: Class + SwiftImportAsAccessors: true + - Name: accessorsOnlyExceptInVersion3 + PropertyKind: Instance + SwiftImportAsAccessors: false + - Name: accessorsOnlyForClassExceptInVersion3 + PropertyKind: Class + SwiftImportAsAccessors: false + - Name: Swift3RenamedOnlyDUMP + SwiftName: SpecialSwift3Name + - Name: Swift3RenamedAlsoDUMP + SwiftName: SpecialSwift3Also + Functions: + - Name: moveToPointDUMP + SwiftName: 'moveTo(a:b:)' + - Name: acceptClosure + Parameters: + - Position: 0 + NoEscape: false + - Name: privateFunc + SwiftPrivate: false + Tags: + - Name: MyErrorCode + NSErrorDomain: '' + - Name: NewlyFlagEnum + FlagEnum: false + - Name: OpenToClosedEnum + EnumExtensibility: open + - Name: ClosedToOpenEnum + EnumExtensibility: closed + - Name: NewlyClosedEnum + EnumExtensibility: none + - Name: NewlyOpenEnum + EnumExtensibility: none + Typedefs: + - Name: MyDoubleWrapper + SwiftWrapper: none + - Name: MultiVersionedTypedef34 + SwiftName: MultiVersionedTypedef34_3 + - Name: MultiVersionedTypedef34Header + SwiftName: MultiVersionedTypedef34Header_3 + - Name: MultiVersionedTypedef34Notes + SwiftName: MultiVersionedTypedef34Notes_3 + - Name: MultiVersionedTypedef345 + SwiftName: MultiVersionedTypedef345_3 + - Name: MultiVersionedTypedef345Header + SwiftName: MultiVersionedTypedef345Header_3 + - Name: MultiVersionedTypedef345Notes + SwiftName: MultiVersionedTypedef345Notes_3 + - Version: 5 + Typedefs: + - Name: MultiVersionedTypedef345 + SwiftName: MultiVersionedTypedef345_5 + - Name: MultiVersionedTypedef345Header + SwiftName: MultiVersionedTypedef345Header_5 + - Name: MultiVersionedTypedef345Notes + SwiftName: MultiVersionedTypedef345Notes_5 + - Name: MultiVersionedTypedef45 + SwiftName: MultiVersionedTypedef45_5 + - Name: MultiVersionedTypedef45Header + SwiftName: MultiVersionedTypedef45Header_5 + - Name: MultiVersionedTypedef45Notes + SwiftName: MultiVersionedTypedef45Notes_5 + - Version: 4 # Versions are deliberately ordered as "3, 5, 4" to catch bugs. + Classes: + - Name: Swift4RenamedDUMP + SwiftName: SpecialSwift4Name + Typedefs: + - Name: MultiVersionedTypedef34 + SwiftName: MultiVersionedTypedef34_4 + - Name: MultiVersionedTypedef34Header + SwiftName: MultiVersionedTypedef34Header_4 + - Name: MultiVersionedTypedef34Notes + SwiftName: MultiVersionedTypedef34Notes_4 + - Name: MultiVersionedTypedef345 + SwiftName: MultiVersionedTypedef345_4 + - Name: MultiVersionedTypedef345Header + SwiftName: MultiVersionedTypedef345Header_4 + - Name: MultiVersionedTypedef345Notes + SwiftName: MultiVersionedTypedef345Notes_4 + - Name: MultiVersionedTypedef4 + SwiftName: MultiVersionedTypedef4_4 + - Name: MultiVersionedTypedef4Header + SwiftName: MultiVersionedTypedef4Header_4 + - Name: MultiVersionedTypedef4Notes + SwiftName: MultiVersionedTypedef4Notes_4 + - Name: MultiVersionedTypedef45 + SwiftName: MultiVersionedTypedef45_4 + - Name: MultiVersionedTypedef45Header + SwiftName: MultiVersionedTypedef45Header_4 + - Name: MultiVersionedTypedef45Notes + SwiftName: MultiVersionedTypedef45Notes_4 diff --git a/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h b/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h new file mode 100644 index 0000000000000000000000000000000000000000..9ce95633c523b7bc8a203c9f49b1ed240ca41718 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h @@ -0,0 +1,137 @@ +void moveToPointDUMP(double x, double y) __attribute__((swift_name("moveTo(x:y:)"))); + +void unversionedRenameDUMP(void) __attribute__((swift_name("unversionedRename_HEADER()"))); + +void acceptClosure(void (^ __attribute__((noescape)) block)(void)); + +void privateFunc(void) __attribute__((swift_private)); + +typedef double MyDoubleWrapper __attribute__((swift_wrapper(struct))); + +#if __OBJC__ +@class NSString; + +extern NSString *MyErrorDomain; + +enum __attribute__((ns_error_domain(MyErrorDomain))) MyErrorCode { + MyErrorCodeFailed = 1 +}; + +__attribute__((swift_bridge("MyValueType"))) +@interface MyReferenceType +@end + +@interface TestProperties +@property (nonatomic, readwrite, retain) id accessorsOnly; +@property (nonatomic, readwrite, retain, class) id accessorsOnlyForClass; + +@property (nonatomic, readwrite, retain) id accessorsOnlyInVersion3; +@property (nonatomic, readwrite, retain, class) id accessorsOnlyForClassInVersion3; + +@property (nonatomic, readwrite, retain) id accessorsOnlyExceptInVersion3; +@property (nonatomic, readwrite, retain, class) id accessorsOnlyForClassExceptInVersion3; +@end + +@interface Base +@end + +@interface TestGenericDUMP<Element> : Base +- (Element)element; +@end + +@interface Swift3RenamedOnlyDUMP +@end + +__attribute__((swift_name("Swift4Name"))) +@interface Swift3RenamedAlsoDUMP +@end + +@interface Swift4RenamedDUMP +@end + +#endif + + +enum __attribute__((flag_enum)) FlagEnum { + FlagEnumA = 1, + FlagEnumB = 2 +}; + +enum __attribute__((flag_enum)) NewlyFlagEnum { + NewlyFlagEnumA = 1, + NewlyFlagEnumB = 2 +}; + +enum APINotedFlagEnum { + APINotedFlagEnumA = 1, + APINotedFlagEnumB = 2 +}; + + +enum __attribute__((enum_extensibility(open))) OpenEnum { + OpenEnumA = 1, +}; + +enum __attribute__((enum_extensibility(open))) NewlyOpenEnum { + NewlyOpenEnumA = 1, +}; + +enum __attribute__((enum_extensibility(closed))) NewlyClosedEnum { + NewlyClosedEnumA = 1, +}; + +enum __attribute__((enum_extensibility(open))) ClosedToOpenEnum { + ClosedToOpenEnumA = 1, +}; + +enum __attribute__((enum_extensibility(closed))) OpenToClosedEnum { + OpenToClosedEnumA = 1, +}; + +enum APINotedOpenEnum { + APINotedOpenEnumA = 1, +}; + +enum APINotedClosedEnum { + APINotedClosedEnumA = 1, +}; + + +enum SoonToBeCFEnum { + SoonToBeCFEnumA = 1 +}; +enum SoonToBeNSEnum { + SoonToBeNSEnumA = 1 +}; +enum SoonToBeCFOptions { + SoonToBeCFOptionsA = 1 +}; +enum SoonToBeNSOptions { + SoonToBeNSOptionsA = 1 +}; +enum SoonToBeCFClosedEnum { + SoonToBeCFClosedEnumA = 1 +}; +enum SoonToBeNSClosedEnum { + SoonToBeNSClosedEnumA = 1 +}; +enum UndoAllThatHasBeenDoneToMe { + UndoAllThatHasBeenDoneToMeA = 1 +} __attribute__((flag_enum)) __attribute__((enum_extensibility(closed))); + + +typedef int MultiVersionedTypedef4; +typedef int MultiVersionedTypedef4Notes; +typedef int MultiVersionedTypedef4Header __attribute__((swift_name("MultiVersionedTypedef4Header_NEW"))); + +typedef int MultiVersionedTypedef34; +typedef int MultiVersionedTypedef34Notes; +typedef int MultiVersionedTypedef34Header __attribute__((swift_name("MultiVersionedTypedef34Header_NEW"))); + +typedef int MultiVersionedTypedef45; +typedef int MultiVersionedTypedef45Notes; +typedef int MultiVersionedTypedef45Header __attribute__((swift_name("MultiVersionedTypedef45Header_NEW"))); + +typedef int MultiVersionedTypedef345; +typedef int MultiVersionedTypedef345Notes; +typedef int MultiVersionedTypedef345Header __attribute__((swift_name("MultiVersionedTypedef345Header_NEW"))); diff --git a/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Modules/module.modulemap b/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Modules/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..6d957fd68009f0c5a56d0dbf6088365bb12726d2 --- /dev/null +++ b/clang/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module VersionedKit { + umbrella header "VersionedKit.h" + export * + module * { export * } +} diff --git a/clang/test/APINotes/Inputs/Headers/APINotes.apinotes b/clang/test/APINotes/Inputs/Headers/APINotes.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..08210fc7056513b97b5c04622f318114ecf15847 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/APINotes.apinotes @@ -0,0 +1,18 @@ +Name: HeaderLib +SwiftInferImportAsMember: true +Functions: + - Name: custom_realloc + NullabilityOfRet: N + Nullability: [ N, S ] + - Name: unavailable_function + Availability: none + AvailabilityMsg: "I beg you not to use this" + - Name: do_something_with_pointers + NullabilityOfRet: O + Nullability: [ N, O ] + +Globals: + - Name: global_int + Nullability: N + - Name: unavailable_global_int + Availability: none diff --git a/clang/test/APINotes/Inputs/Headers/BrokenTypes.apinotes b/clang/test/APINotes/Inputs/Headers/BrokenTypes.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..00f7b5074e9850c3e516850646449aa7bc460e14 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/BrokenTypes.apinotes @@ -0,0 +1,10 @@ +Name: BrokenTypes +Functions: + - Name: break_me_function + ResultType: 'int * with extra junk' + Parameters: + - Position: 0 + Type: 'not_a_type' +Globals: + - Name: break_me_variable + Type: 'double' diff --git a/clang/test/APINotes/Inputs/Headers/BrokenTypes.h b/clang/test/APINotes/Inputs/Headers/BrokenTypes.h new file mode 100644 index 0000000000000000000000000000000000000000..fee054b74cf701b1a9c374faa259e38fe6f05fc1 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/BrokenTypes.h @@ -0,0 +1,8 @@ +#ifndef BROKEN_TYPES_H +#define BROKEN_TYPES_H + +char break_me_function(void *ptr); + +extern char break_me_variable; + +#endif // BROKEN_TYPES_H diff --git a/clang/test/APINotes/Inputs/Headers/ExportAs.apinotes b/clang/test/APINotes/Inputs/Headers/ExportAs.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..14c77afd8c30a1ad4996d489e5ecb4949a1c1de1 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ExportAs.apinotes @@ -0,0 +1,5 @@ +Name: ExportAs +Globals: + - Name: globalInt + Availability: none + AvailabilityMsg: "oh no" diff --git a/clang/test/APINotes/Inputs/Headers/ExportAs.h b/clang/test/APINotes/Inputs/Headers/ExportAs.h new file mode 100644 index 0000000000000000000000000000000000000000..ff490e0964176002686f816ec808d8f477441a60 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ExportAs.h @@ -0,0 +1 @@ +#include "ExportAsCore.h" diff --git a/clang/test/APINotes/Inputs/Headers/ExportAsCore.h b/clang/test/APINotes/Inputs/Headers/ExportAsCore.h new file mode 100644 index 0000000000000000000000000000000000000000..f7674c19935d64d19a3a5f78655c5a93b898b3a6 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ExportAsCore.h @@ -0,0 +1 @@ +static int globalInt = 123; diff --git a/clang/test/APINotes/Inputs/Headers/ExternCtx.apinotes b/clang/test/APINotes/Inputs/Headers/ExternCtx.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..0f47ac6deea85d270cc684853382b1f5d00e2e8c --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ExternCtx.apinotes @@ -0,0 +1,15 @@ +Name: ExternCtx +Globals: + - Name: globalInExternC + Availability: none + AvailabilityMsg: "oh no" + - Name: globalInExternCXX + Availability: none + AvailabilityMsg: "oh no #2" +Functions: + - Name: globalFuncInExternC + Availability: none + AvailabilityMsg: "oh no #3" + - Name: globalFuncInExternCXX + Availability: none + AvailabilityMsg: "oh no #4" diff --git a/clang/test/APINotes/Inputs/Headers/ExternCtx.h b/clang/test/APINotes/Inputs/Headers/ExternCtx.h new file mode 100644 index 0000000000000000000000000000000000000000..669d443f60ecf13d2ff63ad9b37ebb863ee88925 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ExternCtx.h @@ -0,0 +1,11 @@ +extern "C" { + static int globalInExternC = 1; + + static void globalFuncInExternC() {} +} + +extern "C++" { + static int globalInExternCXX = 2; + + static void globalFuncInExternCXX() {} +} diff --git a/clang/test/APINotes/Inputs/Headers/HeaderLib.apinotes b/clang/test/APINotes/Inputs/Headers/HeaderLib.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..7dcb22476a1d26af1e127e6b6963ae79c149fa9a --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/HeaderLib.apinotes @@ -0,0 +1,37 @@ +Name: HeaderLib +SwiftInferImportAsMember: true +Functions: + - Name: custom_realloc + NullabilityOfRet: N + Nullability: [ N, S ] + - Name: unavailable_function + Availability: none + AvailabilityMsg: "I beg you not to use this" + - Name: do_something_with_pointers + NullabilityOfRet: O + Nullability: [ N, O ] + - Name: do_something_with_arrays + Parameters: + - Position: 0 + Nullability: N + - Position: 1 + Nullability: N + - Name: take_pointer_and_int + Parameters: + - Position: 0 + Nullability: N + NoEscape: true + - Position: 1 + NoEscape: true +Globals: + - Name: global_int + Nullability: N + - Name: unavailable_global_int + Availability: none +Tags: + - Name: unavailable_struct + Availability: none + +Typedefs: + - Name: unavailable_typedef + Availability: none diff --git a/clang/test/APINotes/Inputs/Headers/HeaderLib.h b/clang/test/APINotes/Inputs/Headers/HeaderLib.h new file mode 100644 index 0000000000000000000000000000000000000000..8065249607851bd20152f47adfcfba99e698796d --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/HeaderLib.h @@ -0,0 +1,19 @@ +#ifndef HEADER_LIB_H +#define HEADER_LIB_H + +void *custom_realloc(void *member, unsigned size); + +int *global_int; + +int unavailable_function(void); +int unavailable_global_int; + +void do_something_with_pointers(int *ptr1, int *ptr2); +void do_something_with_arrays(int simple[], int nested[][2]); + +typedef int unavailable_typedef; +struct unavailable_struct { int x, y, z; }; + +void take_pointer_and_int(int *ptr1, int value); + +#endif diff --git a/clang/test/APINotes/Inputs/Headers/InstancetypeModule.apinotes b/clang/test/APINotes/Inputs/Headers/InstancetypeModule.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..813eb506f39a748eabaadff147379474fdc24617 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/InstancetypeModule.apinotes @@ -0,0 +1,10 @@ +Name: InstancetypeModule +Classes: +- Name: SomeBaseClass + Methods: + - Selector: instancetypeFactoryMethod + MethodKind: Class + ResultType: SomeBaseClass * _Nonnull + - Selector: staticFactoryMethod + MethodKind: Class + ResultType: SomeBaseClass * _Nonnull diff --git a/clang/test/APINotes/Inputs/Headers/InstancetypeModule.h b/clang/test/APINotes/Inputs/Headers/InstancetypeModule.h new file mode 100644 index 0000000000000000000000000000000000000000..767f201d9faf63c60413af95ee6f779f8cd9210c --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/InstancetypeModule.h @@ -0,0 +1,10 @@ +@interface Object +@end + +@interface SomeBaseClass : Object ++ (nullable instancetype)instancetypeFactoryMethod; ++ (nullable SomeBaseClass *)staticFactoryMethod; +@end + +@interface SomeSubclass : SomeBaseClass +@end diff --git a/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase.h b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase.h new file mode 100644 index 0000000000000000000000000000000000000000..867a15cae9a66413323319f78268bec39aa5bb68 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase.h @@ -0,0 +1 @@ +extern int ModuleWithWrongCase; diff --git a/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate.h b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate.h new file mode 100644 index 0000000000000000000000000000000000000000..aa014296ca7d232d29b3b979b6b30a459dd82147 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate.h @@ -0,0 +1 @@ +extern int ModuleWithWrongCasePrivate; diff --git a/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate_Private.apinotes b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate_Private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..dc6dc50bab6e6987a972bd06bcfdf5524b3c520e --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCasePrivate_Private.apinotes @@ -0,0 +1 @@ +Name: ModuleWithWrongCasePrivate diff --git a/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase_Private.apinotes b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase_Private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..dc6dc50bab6e6987a972bd06bcfdf5524b3c520e --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/ModuleWithWrongCase_Private.apinotes @@ -0,0 +1 @@ +Name: ModuleWithWrongCasePrivate diff --git a/clang/test/APINotes/Inputs/Headers/Namespaces.apinotes b/clang/test/APINotes/Inputs/Headers/Namespaces.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..e9da36787b638d1f08dbab87861d263ad743463c --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/Namespaces.apinotes @@ -0,0 +1,53 @@ +--- +Name: Namespaces +Globals: + - Name: varInInlineNamespace + SwiftName: swiftVarInInlineNamespace +Functions: + - Name: funcInNamespace + SwiftName: inWrongContext() + - Name: funcInInlineNamespace + SwiftName: swiftFuncInInlineNamespace() +Tags: + - Name: char_box + SwiftName: InWrongContext +Namespaces: + - Name: Namespace1 + Typedefs: + - Name: my_typedef + SwiftName: SwiftTypedef + - Name: my_using_decl + SwiftName: SwiftUsingDecl + Globals: + - Name: varInNamespace + SwiftName: swiftVarInNamespace + Functions: + - Name: funcInNamespace + SwiftName: swiftFuncInNamespace() + Tags: + - Name: char_box + SwiftName: CharBox + Namespaces: + - Name: Nested1 + Globals: + - Name: varInNestedNamespace + SwiftName: swiftVarInNestedNamespace + Functions: + - Name: funcInNestedNamespace + SwiftName: swiftFuncInNestedNamespace(_:) + Tags: + - Name: char_box + SwiftName: NestedCharBox + Namespaces: + - Name: Namespace1 + Tags: + - Name: char_box + SwiftName: DeepNestedCharBox + - Name: Nested2 + Globals: + - Name: varInNestedNamespace + SwiftName: swiftAnotherVarInNestedNamespace + - Name: InlineNamespace1 + Functions: + - Name: funcInInlineNamespace + SwiftName: shouldNotSpellOutInlineNamespaces() diff --git a/clang/test/APINotes/Inputs/Headers/Namespaces.h b/clang/test/APINotes/Inputs/Headers/Namespaces.h new file mode 100644 index 0000000000000000000000000000000000000000..6a79e996be86cd2ad07ef68b69274e8858095a77 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/Namespaces.h @@ -0,0 +1,39 @@ +namespace Namespace1 { namespace Nested1 {} } + +namespace Namespace1 { +static int varInNamespace = 1; +struct char_box { char c; }; +void funcInNamespace(); + +namespace Nested1 { +void funcInNestedNamespace(int i); +struct char_box { + char c; +}; +} + +namespace Nested1 { +static int varInNestedNamespace = 1; +void funcInNestedNamespace(int i); + +namespace Namespace1 { +struct char_box { char c; }; +} // namespace Namespace1 +} // namespace Nested1 + +namespace Nested2 { +static int varInNestedNamespace = 2; +} // namespace Nested2 + +namespace Nested1 { namespace Namespace1 {} } +} // namespace Namespace1 + +namespace Namespace1 { +typedef int my_typedef; +using my_using_decl = int; +} + +inline namespace InlineNamespace1 { +static int varInInlineNamespace = 3; +void funcInInlineNamespace(); +} diff --git a/clang/test/APINotes/Inputs/Headers/PrivateLib.apinotes b/clang/test/APINotes/Inputs/Headers/PrivateLib.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..5f62284aadcaf73e53a4a713e23439751eaf7b8b --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/PrivateLib.apinotes @@ -0,0 +1,4 @@ +Name: HeaderLib +Globals: +- Name: PrivateLib + Type: float diff --git a/clang/test/APINotes/Inputs/Headers/PrivateLib.h b/clang/test/APINotes/Inputs/Headers/PrivateLib.h new file mode 100644 index 0000000000000000000000000000000000000000..59aeef09bdd3b649b0157fee5c4b472e2c20fa84 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/PrivateLib.h @@ -0,0 +1 @@ +extern int PrivateLib; diff --git a/clang/test/APINotes/Inputs/Headers/PrivateLib_private.apinotes b/clang/test/APINotes/Inputs/Headers/PrivateLib_private.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..908dae0e3b0b24cc8c04430a659e1aa0ace59b6c --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/PrivateLib_private.apinotes @@ -0,0 +1 @@ +garbage here because this file shouldn't get read diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..5dbb83cab86bd7968b3e9248ef9f8bcdf8762130 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.apinotes @@ -0,0 +1,9 @@ +--- +Name: SwiftImportAs +Tags: +- Name: ImmortalRefType + SwiftImportAs: reference +- Name: RefCountedType + SwiftImportAs: reference + SwiftReleaseOp: RCRelease + SwiftRetainOp: RCRetain diff --git a/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h new file mode 100644 index 0000000000000000000000000000000000000000..82b8a6749c4fe2a8a714db5b2622cc8ab61f2b69 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/SwiftImportAs.h @@ -0,0 +1,6 @@ +struct ImmortalRefType {}; + +struct RefCountedType { int value; }; + +inline void RCRetain(RefCountedType *x) { x->value++; } +inline void RCRelease(RefCountedType *x) { x->value--; } diff --git a/clang/test/APINotes/Inputs/Headers/Templates.apinotes b/clang/test/APINotes/Inputs/Headers/Templates.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..b7336484da0c792c38a56a12e097f5bbee1ecfb1 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/Templates.apinotes @@ -0,0 +1,5 @@ +--- +Name: Templates +Tags: +- Name: Box + SwiftImportAs: owned diff --git a/clang/test/APINotes/Inputs/Headers/Templates.h b/clang/test/APINotes/Inputs/Headers/Templates.h new file mode 100644 index 0000000000000000000000000000000000000000..862035fee363f707f3ed1fd1dc14d55baae4c849 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/Templates.h @@ -0,0 +1,9 @@ +template <typename T> +struct Box { + T value; + + const T& get_value() const { return value; } + const T* get_ptr() const { return &value; } +}; + +using IntBox = Box<int>; diff --git a/clang/test/APINotes/Inputs/Headers/module.modulemap b/clang/test/APINotes/Inputs/Headers/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..d515169184f4f0a5040d8014f4bb525839797095 --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/module.modulemap @@ -0,0 +1,45 @@ +module ExternCtx { + header "ExternCtx.h" +} + +module ExportAsCore { + header "ExportAsCore.h" + export_as ExportAs +} + +module ExportAs { + header "ExportAs.h" + export * +} + +module HeaderLib { + header "HeaderLib.h" +} + +module InstancetypeModule { + header "InstancetypeModule.h" +} + +module BrokenTypes { + header "BrokenTypes.h" +} + +module ModuleWithWrongCase { + header "ModuleWithWrongCase.h" +} + +module ModuleWithWrongCasePrivate { + header "ModuleWithWrongCasePrivate.h" +} + +module Namespaces { + header "Namespaces.h" +} + +module Templates { + header "Templates.h" +} + +module SwiftImportAs { + header "SwiftImportAs.h" +} diff --git a/clang/test/APINotes/Inputs/Headers/module.private.modulemap b/clang/test/APINotes/Inputs/Headers/module.private.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..2ecf322ed18d9cca21d1036a4b5cdc3950c759fa --- /dev/null +++ b/clang/test/APINotes/Inputs/Headers/module.private.modulemap @@ -0,0 +1,5 @@ +module PrivateLib { + header "PrivateLib.h" +} + +module ModuleWithWrongCasePrivate.Inner {} diff --git a/clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.apinotes b/clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.apinotes new file mode 100644 index 0000000000000000000000000000000000000000..77db844008990d216c3e022908505365182538aa --- /dev/null +++ b/clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.apinotes @@ -0,0 +1,65 @@ +--- +Name: UIKit +Classes: + - Name: UIFont + Methods: + - Selector: 'fontWithName:size:' + MethodKind: Instance + Nullability: [ N ] + NullabilityOfRet: O + DesignatedInit: true +# CHECK: duplicate definition of method '-[UIFont fontWithName:size:]' + - Selector: 'fontWithName:size:' + MethodKind: Instance + Nullability: [ N ] + NullabilityOfRet: O + DesignatedInit: true + Properties: + - Name: familyName + Nullability: N + - Name: fontName + Nullability: N +# CHECK: duplicate definition of instance property 'UIFont.familyName' + - Name: familyName + Nullability: N +# CHECK: multiple definitions of class 'UIFont' + - Name: UIFont +Protocols: + - Name: MyProto + AuditedForNullability: true +# CHECK: multiple definitions of protocol 'MyProto' + - Name: MyProto + AuditedForNullability: true +Functions: + - Name: 'globalFoo' + Nullability: [ N, N, O, S ] + NullabilityOfRet: O + - Name: 'globalFoo2' + Nullability: [ N, N, O, S ] + NullabilityOfRet: O +Globals: + - Name: globalVar + Nullability: O + - Name: globalVar2 + Nullability: O +Tags: +# CHECK: cannot mix EnumKind and FlagEnum (for FlagAndEnumKind) + - Name: FlagAndEnumKind + FlagEnum: true + EnumKind: CFOptions +# CHECK: cannot mix EnumKind and FlagEnum (for FlagAndEnumKind2) + - Name: FlagAndEnumKind2 + EnumKind: CFOptions + FlagEnum: false +# CHECK: cannot mix EnumKind and EnumExtensibility (for ExtensibilityAndEnumKind) + - Name: ExtensibilityAndEnumKind + EnumExtensibility: open + EnumKind: CFOptions +# CHECK: cannot mix EnumKind and EnumExtensibility (for ExtensibilityAndEnumKind2) + - Name: ExtensibilityAndEnumKind2 + EnumKind: CFOptions + EnumExtensibility: closed +# CHECK: cannot mix EnumKind and EnumExtensibility (for ExtensibilityAndEnumKind3) + - Name: ExtensibilityAndEnumKind3 + EnumKind: none + EnumExtensibility: none diff --git a/clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.h b/clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.h new file mode 100644 index 0000000000000000000000000000000000000000..55313ae260ae11cce3d79d43dbcdb50100548766 --- /dev/null +++ b/clang/test/APINotes/Inputs/yaml-reader-errors/UIKit.h @@ -0,0 +1 @@ +extern int yesOfCourseThisIsWhatUIKitLooksLike; diff --git a/clang/test/APINotes/Inputs/yaml-reader-errors/module.modulemap b/clang/test/APINotes/Inputs/yaml-reader-errors/module.modulemap new file mode 100644 index 0000000000000000000000000000000000000000..3d683d705cacf8fa20f409f0e05fd7d374810a7c --- /dev/null +++ b/clang/test/APINotes/Inputs/yaml-reader-errors/module.modulemap @@ -0,0 +1,3 @@ +module UIKit { + header "UIKit.h" +} diff --git a/clang/test/APINotes/availability.m b/clang/test/APINotes/availability.m new file mode 100644 index 0000000000000000000000000000000000000000..2ddc2a73da80462b9ba0d6f4e712e1402d3ffebb --- /dev/null +++ b/clang/test/APINotes/availability.m @@ -0,0 +1,48 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -Wno-private-module -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify + +#include "HeaderLib.h" +#import <SomeKit/SomeKit.h> +#import <SomeKit/SomeKit_Private.h> + +int main() { + int i; + i = unavailable_function(); // expected-error{{'unavailable_function' is unavailable: I beg you not to use this}} + // expected-note@HeaderLib.h:8{{'unavailable_function' has been explicitly marked unavailable here}} + i = unavailable_global_int; // expected-error{{'unavailable_global_int' is unavailable}} + // expected-note@HeaderLib.h:9{{'unavailable_global_int' has been explicitly marked unavailable here}} + + unavailable_typedef t; // expected-error{{'unavailable_typedef' is unavailable}} + // expected-note@HeaderLib.h:14{{'unavailable_typedef' has been explicitly marked unavailable here}} + + struct unavailable_struct s; // expected-error{{'unavailable_struct' is unavailable}} + // expected-note@HeaderLib.h:15{{'unavailable_struct' has been explicitly marked unavailable here}} + + B *b = 0; // expected-error{{'B' is unavailable: just don't}} + // expected-note@SomeKit/SomeKit.h:15{{'B' has been explicitly marked unavailable here}} + + id<InternalProtocol> proto = 0; // expected-error{{'InternalProtocol' is unavailable: not for you}} + // expected-note@SomeKit/SomeKit_Private.h:12{{'InternalProtocol' has been explicitly marked unavailable here}} + + A *a = 0; + i = a.intValue; // expected-error{{intValue' is unavailable: wouldn't work anyway}} + // expected-note@SomeKit/SomeKit.h:12{{'intValue' has been explicitly marked unavailable here}} + + [a transform:a]; // expected-error{{'transform:' is unavailable: anything but this}} + // expected-note@SomeKit/SomeKit.h:6{{'transform:' has been explicitly marked unavailable here}} + + [a implicitGetOnlyInstance]; // expected-error{{'implicitGetOnlyInstance' is unavailable: getter gone}} + // expected-note@SomeKit/SomeKit.h:53{{'implicitGetOnlyInstance' has been explicitly marked unavailable here}} + [A implicitGetOnlyClass]; // expected-error{{'implicitGetOnlyClass' is unavailable: getter gone}} + // expected-note@SomeKit/SomeKit.h:54{{'implicitGetOnlyClass' has been explicitly marked unavailable here}} + [a implicitGetSetInstance]; // expected-error{{'implicitGetSetInstance' is unavailable: getter gone}} + // expected-note@SomeKit/SomeKit.h:56{{'implicitGetSetInstance' has been explicitly marked unavailable here}} + [a setImplicitGetSetInstance: a]; // expected-error{{'setImplicitGetSetInstance:' is unavailable: setter gone}} + // expected-note@SomeKit/SomeKit.h:56{{'setImplicitGetSetInstance:' has been explicitly marked unavailable here}} + [A implicitGetSetClass]; // expected-error{{'implicitGetSetClass' is unavailable: getter gone}} + // expected-note@SomeKit/SomeKit.h:57{{'implicitGetSetClass' has been explicitly marked unavailable here}} + [A setImplicitGetSetClass: a]; // expected-error{{'setImplicitGetSetClass:' is unavailable: setter gone}} + // expected-note@SomeKit/SomeKit.h:57{{'setImplicitGetSetClass:' has been explicitly marked unavailable here}} + return 0; +} + diff --git a/clang/test/APINotes/broken_types.m b/clang/test/APINotes/broken_types.m new file mode 100644 index 0000000000000000000000000000000000000000..ee33ff7c4b4b9cbe59b209abcd6f91bf77e71e3d --- /dev/null +++ b/clang/test/APINotes/broken_types.m @@ -0,0 +1,19 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s 2> %t.err +// RUN: FileCheck %s < %t.err + +#include "BrokenTypes.h" + +// CHECK: <API Notes>:1:1: error: unknown type name 'not_a_type' +// CHECK-NEXT: not_a_type +// CHECK-NEXT: ^ + +// CHECK: <API Notes>:1:7: error: unparsed tokens following type +// CHECK-NEXT: int * with extra junk +// CHECK-NEXT: ^ + +// CHECK: BrokenTypes.h:4:6: error: API notes replacement type 'int *' has a different size from original type 'char' + +// CHECK: BrokenTypes.h:6:13: error: API notes replacement type 'double' has a different size from original type 'char' + +// CHECK: 5 errors generated. diff --git a/clang/test/APINotes/case-for-private-apinotes-file.c b/clang/test/APINotes/case-for-private-apinotes-file.c new file mode 100644 index 0000000000000000000000000000000000000000..6aff3db54918e4a8dc68b20671f1172d3b99c335 --- /dev/null +++ b/clang/test/APINotes/case-for-private-apinotes-file.c @@ -0,0 +1,22 @@ +// REQUIRES: case-insensitive-filesystem + +// RUN: rm -rf %t +// RUN: %clang_cc1 -fsyntax-only -fmodules -fapinotes-modules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/Frameworks -I %S/Inputs/Headers %s 2>&1 | FileCheck %s + +// RUN: rm -rf %t +// RUN: %clang_cc1 -fsyntax-only -fmodules -fapinotes-modules -fimplicit-module-maps -fmodules-cache-path=%t -iframework %S/Inputs/Frameworks -isystem %S/Inputs/Headers %s -Werror + +// RUN: rm -rf %t +// RUN: %clang_cc1 -fsyntax-only -fmodules -fapinotes-modules -fimplicit-module-maps -fmodules-cache-path=%t -iframework %S/Inputs/Frameworks -isystem %S/Inputs/Headers %s -Wnonportable-private-system-apinotes-path 2>&1 | FileCheck %s + +#include <ModuleWithWrongCase.h> +#include <ModuleWithWrongCasePrivate.h> +#include <FrameworkWithWrongCase/FrameworkWithWrongCase.h> +#include <FrameworkWithWrongCasePrivate/FrameworkWithWrongCasePrivate.h> +#include <FrameworkWithActualPrivateModule/FrameworkWithActualPrivateModule_Private.h> + +// CHECK-NOT: warning: +// CHECK: warning: private API notes file for module 'ModuleWithWrongCasePrivate' should be named 'ModuleWithWrongCasePrivate_private.apinotes', not 'ModuleWithWrongCasePrivate_Private.apinotes' +// CHECK-NOT: warning: +// CHECK: warning: private API notes file for module 'FrameworkWithWrongCasePrivate' should be named 'FrameworkWithWrongCasePrivate_private.apinotes', not 'FrameworkWithWrongCasePrivate_Private.apinotes' +// CHECK-NOT: warning: diff --git a/clang/test/APINotes/export-as.c b/clang/test/APINotes/export-as.c new file mode 100644 index 0000000000000000000000000000000000000000..7a8a652ab755754e7b607780005294db6b73d48b --- /dev/null +++ b/clang/test/APINotes/export-as.c @@ -0,0 +1,8 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter globalInt -x c | FileCheck %s + +#include "ExportAs.h" + +// CHECK: Dumping globalInt: +// CHECK: VarDecl {{.+}} imported in ExportAsCore globalInt 'int' +// CHECK: UnavailableAttr {{.+}} <<invalid sloc>> "oh no" diff --git a/clang/test/APINotes/extern-context.cpp b/clang/test/APINotes/extern-context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..331dee002361c0271c12ac6b7d68780a0eae45a9 --- /dev/null +++ b/clang/test/APINotes/extern-context.cpp @@ -0,0 +1,23 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter globalInExternC -x c++ | FileCheck -check-prefix=CHECK-EXTERN-C %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter globalInExternCXX -x c++ | FileCheck -check-prefix=CHECK-EXTERN-CXX %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter globalFuncInExternC -x c++ | FileCheck -check-prefix=CHECK-FUNC-EXTERN-C %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -ast-dump -ast-dump-filter globalFuncInExternCXX -x c++ | FileCheck -check-prefix=CHECK-FUNC-EXTERN-CXX %s + +#include "ExternCtx.h" + +// CHECK-EXTERN-C: Dumping globalInExternC: +// CHECK-EXTERN-C: VarDecl {{.+}} imported in ExternCtx globalInExternC 'int' +// CHECK-EXTERN-C: UnavailableAttr {{.+}} <<invalid sloc>> "oh no" + +// CHECK-EXTERN-CXX: Dumping globalInExternCXX: +// CHECK-EXTERN-CXX: VarDecl {{.+}} imported in ExternCtx globalInExternCXX 'int' +// CHECK-EXTERN-CXX: UnavailableAttr {{.+}} <<invalid sloc>> "oh no #2" + +// CHECK-FUNC-EXTERN-C: Dumping globalFuncInExternC: +// CHECK-FUNC-EXTERN-C: FunctionDecl {{.+}} imported in ExternCtx globalFuncInExternC 'void ()' +// CHECK-FUNC-EXTERN-C: UnavailableAttr {{.+}} <<invalid sloc>> "oh no #3" + +// CHECK-FUNC-EXTERN-CXX: Dumping globalFuncInExternCXX: +// CHECK-FUNC-EXTERN-CXX: FunctionDecl {{.+}} imported in ExternCtx globalFuncInExternCXX 'void ()' +// CHECK-FUNC-EXTERN-CXX: UnavailableAttr {{.+}} <<invalid sloc>> "oh no #4" diff --git a/clang/test/APINotes/instancetype.m b/clang/test/APINotes/instancetype.m new file mode 100644 index 0000000000000000000000000000000000000000..30339e5386f634ad05262d097fcb547a3306e462 --- /dev/null +++ b/clang/test/APINotes/instancetype.m @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -verify %s + +@import InstancetypeModule; + +void test() { + // The nullability is here to verify that the API notes were applied. + int good = [SomeSubclass instancetypeFactoryMethod]; // expected-error {{initializing 'int' with an expression of type 'SomeSubclass * _Nonnull'}} + int bad = [SomeSubclass staticFactoryMethod]; // expected-error {{initializing 'int' with an expression of type 'SomeBaseClass * _Nonnull'}} +} diff --git a/clang/test/APINotes/module-cache.m b/clang/test/APINotes/module-cache.m new file mode 100644 index 0000000000000000000000000000000000000000..e5920884ad860f086d3ad1391748ced664c46032 --- /dev/null +++ b/clang/test/APINotes/module-cache.m @@ -0,0 +1,66 @@ +// RUN: rm -rf %t + +// Set up directories +// RUN: mkdir -p %t/APINotes +// RUN: cp %S/Inputs/APINotes/SomeOtherKit.apinotes %t/APINotes/SomeOtherKit.apinotes +// RUN: mkdir -p %t/Frameworks +// RUN: cp -r %S/Inputs/Frameworks/SomeOtherKit.framework %t/Frameworks + +// First build: check that 'methodB' is unavailable but 'methodA' is available. +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -Rmodule-build -fmodules-cache-path=%t/ModulesCache -iapinotes-modules %t/APINotes -F %t/Frameworks %s > %t/before.log 2>&1 +// RUN: FileCheck -check-prefix=CHECK-METHODB %s < %t/before.log +// RUN: FileCheck -check-prefix=CHECK-REBUILD %s < %t/before.log +// RUN: FileCheck -check-prefix=CHECK-ONE-ERROR %s < %t/before.log + +// Do it again; now we're using caches. +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -Rmodule-build -fmodules-cache-path=%t/ModulesCache -iapinotes-modules %t/APINotes -F %t/Frameworks %s > %t/before.log 2>&1 +// RUN: FileCheck -check-prefix=CHECK-METHODB %s < %t/before.log +// RUN: FileCheck -check-prefix=CHECK-WITHOUT-REBUILD %s < %t/before.log +// RUN: FileCheck -check-prefix=CHECK-ONE-ERROR %s < %t/before.log + +// Add a blank line to the header to force the module to rebuild, without +// (yet) changing API notes. +// RUN: echo >> %t/Frameworks/SomeOtherKit.framework/Headers/SomeOtherKit.h +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -Rmodule-build -fmodules-cache-path=%t/ModulesCache -iapinotes-modules %t/APINotes -F %t/Frameworks %s > %t/before.log 2>&1 +// RUN: FileCheck -check-prefix=CHECK-METHODB %s < %t/before.log +// RUN: FileCheck -check-prefix=CHECK-REBUILD %s < %t/before.log +// RUN: FileCheck -check-prefix=CHECK-ONE-ERROR %s < %t/before.log + +// Change the API notes file, after the module has rebuilt once. +// RUN: chmod u+w %t/APINotes/SomeOtherKit.apinotes +// RUN: echo ' - Selector: "methodA"' >> %t/APINotes/SomeOtherKit.apinotes +// RUN: echo ' MethodKind: Instance' >> %t/APINotes/SomeOtherKit.apinotes +// RUN: echo ' Availability: none' >> %t/APINotes/SomeOtherKit.apinotes +// RUN: echo ' AvailabilityMsg: "not here either"' >> %t/APINotes/SomeOtherKit.apinotes + +// Build again: check that both methods are now unavailable and that the module rebuilt. +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -Rmodule-build -fmodules-cache-path=%t/ModulesCache -iapinotes-modules %t/APINotes -F %t/Frameworks %s > %t/after.log 2>&1 +// RUN: FileCheck -check-prefix=CHECK-METHODA %s < %t/after.log +// RUN: FileCheck -check-prefix=CHECK-METHODB %s < %t/after.log +// RUN: FileCheck -check-prefix=CHECK-REBUILD %s < %t/after.log +// RUN: FileCheck -check-prefix=CHECK-TWO-ERRORS %s < %t/after.log + +// Run the build again: check that both methods are now unavailable +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -Rmodule-build -fmodules-cache-path=%t/ModulesCache -iapinotes-modules %t/APINotes -F %t/Frameworks %s > %t/after.log 2>&1 +// RUN: FileCheck -check-prefix=CHECK-METHODA %s < %t/after.log +// RUN: FileCheck -check-prefix=CHECK-METHODB %s < %t/after.log +// RUN: FileCheck -check-prefix=CHECK-WITHOUT-REBUILD %s < %t/after.log +// RUN: FileCheck -check-prefix=CHECK-TWO-ERRORS %s < %t/after.log + +@import SomeOtherKit; + +void test(A *a) { + // CHECK-METHODA: error: 'methodA' is unavailable: not here either + [a methodA]; + + // CHECK-METHODB: error: 'methodB' is unavailable: anything but this + [a methodB]; +} + +// CHECK-REBUILD: remark: building module{{.*}}SomeOtherKit + +// CHECK-WITHOUT-REBUILD-NOT: remark: building module{{.*}}SomeOtherKit + +// CHECK-ONE-ERROR: 1 error generated. +// CHECK-TWO-ERRORS: 2 errors generated. + diff --git a/clang/test/APINotes/namespaces.cpp b/clang/test/APINotes/namespaces.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f9d93c2ea0e5a3ad0763cba5c2995a4f498d447 --- /dev/null +++ b/clang/test/APINotes/namespaces.cpp @@ -0,0 +1,69 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -x objective-c++ +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::my_typedef -x objective-c++ | FileCheck -check-prefix=CHECK-TYPEDEF-IN-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::my_using_decl -x objective-c++ | FileCheck -check-prefix=CHECK-USING-DECL-IN-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::varInNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-GLOBAL-IN-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::funcInNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-FUNC-IN-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::char_box -x objective-c++ | FileCheck -check-prefix=CHECK-STRUCT-IN-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested1::varInNestedNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-GLOBAL-IN-NESTED-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested2::varInNestedNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-ANOTHER-GLOBAL-IN-NESTED-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested1::char_box -x objective-c++ | FileCheck -check-prefix=CHECK-STRUCT-IN-NESTED-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested1::funcInNestedNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-FUNC-IN-NESTED-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested1::Namespace1::char_box -x objective-c++ | FileCheck -check-prefix=CHECK-STRUCT-IN-DEEP-NESTED-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter varInInlineNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-GLOBAL-IN-INLINE-NAMESPACE %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter funcInInlineNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-FUNC-IN-INLINE-NAMESPACE %s + +#import <Namespaces.h> + +// CHECK-TYPEDEF-IN-NAMESPACE: Dumping Namespace1::my_typedef: +// CHECK-TYPEDEF-IN-NAMESPACE-NEXT: TypedefDecl {{.+}} imported in Namespaces my_typedef 'int' +// CHECK-TYPEDEF-IN-NAMESPACE: SwiftNameAttr {{.+}} <<invalid sloc>> "SwiftTypedef" + +// CHECK-USING-DECL-IN-NAMESPACE: Dumping Namespace1::my_using_decl: +// CHECK-USING-DECL-IN-NAMESPACE-NEXT: TypeAliasDecl {{.+}} imported in Namespaces my_using_decl 'int' +// CHECK-USING-DECL-IN-NAMESPACE: SwiftNameAttr {{.+}} <<invalid sloc>> "SwiftUsingDecl" + +// CHECK-GLOBAL-IN-NAMESPACE: Dumping Namespace1::varInNamespace: +// CHECK-GLOBAL-IN-NAMESPACE-NEXT: VarDecl {{.+}} imported in Namespaces varInNamespace 'int' static cinit +// CHECK-GLOBAL-IN-NAMESPACE-NEXT: IntegerLiteral {{.+}} 'int' 1 +// CHECK-GLOBAL-IN-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>> "swiftVarInNamespace" + +// CHECK-FUNC-IN-NAMESPACE: Dumping Namespace1::funcInNamespace: +// CHECK-FUNC-IN-NAMESPACE-NEXT: FunctionDecl {{.+}} imported in Namespaces funcInNamespace 'void ()' +// CHECK-FUNC-IN-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>> "swiftFuncInNamespace()" + +// CHECK-STRUCT-IN-NAMESPACE: Dumping Namespace1::char_box: +// CHECK-STRUCT-IN-NAMESPACE-NEXT: CXXRecordDecl {{.+}} imported in Namespaces <undeserialized declarations> struct char_box +// CHECK-STRUCT-IN-NAMESPACE: SwiftNameAttr {{.+}} <<invalid sloc>> "CharBox" + +// CHECK-GLOBAL-IN-NESTED-NAMESPACE: Dumping Namespace1::Nested1::varInNestedNamespace: +// CHECK-GLOBAL-IN-NESTED-NAMESPACE-NEXT: VarDecl {{.+}} imported in Namespaces varInNestedNamespace 'int' static cinit +// CHECK-GLOBAL-IN-NESTED-NAMESPACE-NEXT: IntegerLiteral {{.+}} 'int' 1 +// CHECK-GLOBAL-IN-NESTED-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>> "swiftVarInNestedNamespace" + +// CHECK-ANOTHER-GLOBAL-IN-NESTED-NAMESPACE: Dumping Namespace1::Nested2::varInNestedNamespace: +// CHECK-ANOTHER-GLOBAL-IN-NESTED-NAMESPACE-NEXT: VarDecl {{.+}} imported in Namespaces varInNestedNamespace 'int' static cinit +// CHECK-ANOTHER-GLOBAL-IN-NESTED-NAMESPACE-NEXT: IntegerLiteral {{.+}} 'int' 2 +// CHECK-ANOTHER-GLOBAL-IN-NESTED-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>> "swiftAnotherVarInNestedNamespace" + +// CHECK-FUNC-IN-NESTED-NAMESPACE: Dumping Namespace1::Nested1::funcInNestedNamespace: +// CHECK-FUNC-IN-NESTED-NAMESPACE-NEXT: FunctionDecl {{.+}} imported in Namespaces funcInNestedNamespace 'void (int)' +// CHECK-FUNC-IN-NESTED-NAMESPACE-NEXT: ParmVarDecl {{.+}} i 'int' +// CHECK-FUNC-IN-NESTED-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>> "swiftFuncInNestedNamespace(_:)" + +// CHECK-STRUCT-IN-NESTED-NAMESPACE: Dumping Namespace1::Nested1::char_box: +// CHECK-STRUCT-IN-NESTED-NAMESPACE-NEXT: CXXRecordDecl {{.+}} imported in Namespaces <undeserialized declarations> struct char_box +// CHECK-STRUCT-IN-NESTED-NAMESPACE: SwiftNameAttr {{.+}} <<invalid sloc>> "NestedCharBox" + +// CHECK-STRUCT-IN-DEEP-NESTED-NAMESPACE: Dumping Namespace1::Nested1::Namespace1::char_box: +// CHECK-STRUCT-IN-DEEP-NESTED-NAMESPACE-NEXT: CXXRecordDecl {{.+}} imported in Namespaces <undeserialized declarations> struct char_box +// CHECK-STRUCT-IN-DEEP-NESTED-NAMESPACE: SwiftNameAttr {{.+}} <<invalid sloc>> "DeepNestedCharBox" + +// CHECK-GLOBAL-IN-INLINE-NAMESPACE: Dumping varInInlineNamespace: +// CHECK-GLOBAL-IN-INLINE-NAMESPACE-NEXT: VarDecl {{.+}} imported in Namespaces varInInlineNamespace 'int' static cinit +// CHECK-GLOBAL-IN-INLINE-NAMESPACE-NEXT: IntegerLiteral {{.+}} 'int' 3 +// CHECK-GLOBAL-IN-INLINE-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>> "swiftVarInInlineNamespace" + +// CHECK-FUNC-IN-INLINE-NAMESPACE: Dumping funcInInlineNamespace: +// CHECK-FUNC-IN-INLINE-NAMESPACE-NEXT: FunctionDecl {{.+}} imported in Namespaces funcInInlineNamespace 'void ()' +// CHECK-FUNC-IN-INLINE-NAMESPACE-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>> "swiftFuncInInlineNamespace()" diff --git a/clang/test/APINotes/nullability.c b/clang/test/APINotes/nullability.c new file mode 100644 index 0000000000000000000000000000000000000000..e07fc2e5c11743e9a8bcc6333bff65cb97dff014 --- /dev/null +++ b/clang/test/APINotes/nullability.c @@ -0,0 +1,21 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify + +#include "HeaderLib.h" + +int main() { + custom_realloc(0, 0); // expected-warning{{null passed to a callee that requires a non-null argument}} + int i = 0; + do_something_with_pointers(&i, 0); + do_something_with_pointers(0, &i); // expected-warning{{null passed to a callee that requires a non-null argument}} + + extern void *p; + do_something_with_arrays(0, p); // expected-warning{{null passed to a callee that requires a non-null argument}} + do_something_with_arrays(p, 0); // expected-warning{{null passed to a callee that requires a non-null argument}} + + take_pointer_and_int(0, 0); // expected-warning{{null passed to a callee that requires a non-null argument}} + + float *fp = global_int; // expected-warning{{incompatible pointer types initializing 'float *' with an expression of type 'int * _Nonnull'}} + return 0; +} + diff --git a/clang/test/APINotes/nullability.m b/clang/test/APINotes/nullability.m new file mode 100644 index 0000000000000000000000000000000000000000..21ec6680fa714d1b2b629851ba4ea3243f08aba3 --- /dev/null +++ b/clang/test/APINotes/nullability.m @@ -0,0 +1,46 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -Wno-private-module -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify + +// Test with Swift version 3.0. This should only affect the few APIs that have an entry in the 3.0 tables. + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -Wno-private-module -fapinotes-swift-version=3.0 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify -DSWIFT_VERSION_3_0 -fmodules-ignore-macro=SWIFT_VERSION_3_0 + +#import <SomeKit/SomeKit.h> + +int main() { + A *a; + +#if SWIFT_VERSION_3_0 + float *fp = // expected-warning{{incompatible pointer types initializing 'float *' with an expression of type 'A * _Nullable'}} + [a transform: 0 integer: 0]; +#else + float *fp = // expected-warning{{incompatible pointer types initializing 'float *' with an expression of type 'A *'}} + [a transform: 0 integer: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} +#endif + + [a setNonnullAInstance: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} + [A setNonnullAInstance: 0]; // no warning + a.nonnullAInstance = 0; // expected-warning{{null passed to a callee that requires a non-null argument}} + A* _Nonnull aPtr = a.nonnullAInstance; // no warning + + [a setNonnullAClass: 0]; // no warning + [A setNonnullAClass: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} + + [a setNonnullABoth: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} + [A setNonnullABoth: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} + + [a setInternalProperty: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} + +#if SWIFT_VERSION_3_0 + // Version 3 information overrides header information. + [a setExplicitNonnullInstance: 0]; // okay + [a setExplicitNullableInstance: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} +#else + // Header information overrides unversioned information. + [a setExplicitNonnullInstance: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}} + [a setExplicitNullableInstance: 0]; // okay +#endif + + return 0; +} + diff --git a/clang/test/APINotes/objc-forward-declarations.m b/clang/test/APINotes/objc-forward-declarations.m new file mode 100644 index 0000000000000000000000000000000000000000..e82bed20555049b968cefe30faaf30c8d2f36a49 --- /dev/null +++ b/clang/test/APINotes/objc-forward-declarations.m @@ -0,0 +1,12 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -F %S/Inputs/Frameworks %s -verify + +@import LayeredKit; + +void test( + UpwardClass *okayClass, + id <UpwardProto> okayProto, + PerfectlyNormalClass *badClass // expected-error {{'PerfectlyNormalClass' is unavailable}} +) { + // expected-note@LayeredKitImpl/LayeredKitImpl.h:4 {{'PerfectlyNormalClass' has been explicitly marked unavailable here}} +} diff --git a/clang/test/APINotes/objc_designated_inits.m b/clang/test/APINotes/objc_designated_inits.m new file mode 100644 index 0000000000000000000000000000000000000000..1f2b8ed534b7a170b9915e8dfb2894d476e36b54 --- /dev/null +++ b/clang/test/APINotes/objc_designated_inits.m @@ -0,0 +1,17 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -Wno-private-module -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify + +#include "HeaderLib.h" +#import <SomeKit/SomeKit.h> + +@interface CSub : C +-(instancetype)initWithA:(A*)a; +@end + +@implementation CSub +-(instancetype)initWithA:(A*)a { // expected-warning{{designated initializer missing a 'super' call to a designated initializer of the super class}} + // expected-note@SomeKit/SomeKit.h:20 2{{method marked as designated initializer of the class here}} + self = [super init]; // expected-warning{{designated initializer invoked a non-designated initializer}} + return self; +} +@end diff --git a/clang/test/APINotes/properties.m b/clang/test/APINotes/properties.m new file mode 100644 index 0000000000000000000000000000000000000000..f218092a66e1dc10e07ace0b751c84660cf0e8f1 --- /dev/null +++ b/clang/test/APINotes/properties.m @@ -0,0 +1,42 @@ +// RUN: rm -rf %t && mkdir -p %t + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fblocks -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter 'TestProperties::' | FileCheck -check-prefix=CHECK -check-prefix=CHECK-4 %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fblocks -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter 'TestProperties::' -fapinotes-swift-version=3 | FileCheck -check-prefix=CHECK -check-prefix=CHECK-3 %s + +@import VersionedKit; + +// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnly 'id' +// CHECK-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <<invalid sloc>> +// CHECK-NOT: Attr + +// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyForClass 'id' +// CHECK-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <<invalid sloc>> +// CHECK-NOT: Attr + +// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyInVersion3 'id' +// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <<invalid sloc>> +// CHECK-4-NEXT: SwiftVersionedAdditionAttr {{.+}} 3.0{{$}} +// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <<invalid sloc>> +// CHECK-NOT: Attr + +// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyForClassInVersion3 'id' +// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <<invalid sloc>> +// CHECK-4-NEXT: SwiftVersionedAdditionAttr {{.+}} 3.0{{$}} +// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <<invalid sloc>> +// CHECK-NOT: Attr + +// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyExceptInVersion3 'id' +// CHECK-3-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}} +// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <<invalid sloc>> +// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <<invalid sloc>> +// CHECK-4-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0 {{[0-9]+}} +// CHECK-NOT: Attr + +// CHECK-LABEL: ObjCPropertyDecl {{.+}} accessorsOnlyForClassExceptInVersion3 'id' +// CHECK-3-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}} +// CHECK-3-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <<invalid sloc>> +// CHECK-4-NEXT: SwiftImportPropertyAsAccessorsAttr {{.+}} <<invalid sloc>> +// CHECK-4-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0 {{[0-9]+}} +// CHECK-NOT: Attr + +// CHECK-LABEL: Decl diff --git a/clang/test/APINotes/retain-count-convention.m b/clang/test/APINotes/retain-count-convention.m new file mode 100644 index 0000000000000000000000000000000000000000..4bf9610a352a7533de4522c1e6dc42fb890eb9e2 --- /dev/null +++ b/clang/test/APINotes/retain-count-convention.m @@ -0,0 +1,38 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fdisable-module-hash -fsyntax-only -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/SimpleKit.pcm | FileCheck %s +// RUN: %clang_cc1 -ast-dump -ast-dump-filter 'DUMP' %t/ModulesCache/SimpleKit.pcm | FileCheck -check-prefix CHECK-DUMP %s + +#import <SimpleKit/SimpleKit.h> + +// CHECK: void *getCFOwnedToUnowned(void) __attribute__((cf_returns_not_retained)); +// CHECK: void *getCFUnownedToOwned(void) __attribute__((cf_returns_retained)); +// CHECK: void *getCFOwnedToNone(void) __attribute__((cf_unknown_transfer)); +// CHECK: id getObjCOwnedToUnowned(void) __attribute__((ns_returns_not_retained)); +// CHECK: id getObjCUnownedToOwned(void) __attribute__((ns_returns_retained)); +// CHECK: int indirectGetCFOwnedToUnowned(void * _Nullable *out __attribute__((cf_returns_not_retained))); +// CHECK: int indirectGetCFUnownedToOwned(void * _Nullable *out __attribute__((cf_returns_retained))); +// CHECK: int indirectGetCFOwnedToNone(void * _Nullable *out); +// CHECK: int indirectGetCFNoneToOwned(void **out __attribute__((cf_returns_not_retained))); + +// CHECK-LABEL: @interface MethodTest +// CHECK: - (id)getOwnedToUnowned __attribute__((ns_returns_not_retained)); +// CHECK: - (id)getUnownedToOwned __attribute__((ns_returns_retained)); +// CHECK: @end + +// CHECK-DUMP-LABEL: Dumping getCFAuditedToUnowned_DUMP: +// CHECK-DUMP-NEXT: FunctionDecl +// CHECK-DUMP-NEXT: CFReturnsNotRetainedAttr +// CHECK-DUMP-NEXT: CFAuditedTransferAttr +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping getCFAuditedToOwned_DUMP: +// CHECK-DUMP-NEXT: FunctionDecl +// CHECK-DUMP-NEXT: CFReturnsRetainedAttr +// CHECK-DUMP-NEXT: CFAuditedTransferAttr +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping getCFAuditedToNone_DUMP: +// CHECK-DUMP-NEXT: FunctionDecl +// CHECK-DUMP-NEXT: CFUnknownTransferAttr +// CHECK-DUMP-NOT: Attr diff --git a/clang/test/APINotes/search-order.m b/clang/test/APINotes/search-order.m new file mode 100644 index 0000000000000000000000000000000000000000..17e81d5eb2d691d480a743f59368846b2a9438a4 --- /dev/null +++ b/clang/test/APINotes/search-order.m @@ -0,0 +1,25 @@ +// RUN: rm -rf %t && mkdir -p %t + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -DFROM_FRAMEWORK=1 -verify + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -iapinotes-modules %S/Inputs/APINotes -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -DFROM_SEARCH_PATH=1 -verify + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -iapinotes-modules %S/Inputs/APINotes -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -DFROM_FRAMEWORK=1 -verify + +@import SomeOtherKit; + +void test(A *a) { +#if FROM_FRAMEWORK + [a methodA]; // expected-error{{unavailable}} + [a methodB]; + + // expected-note@SomeOtherKit/SomeOtherKit.h:5{{'methodA' has been explicitly marked unavailable here}} +#elif FROM_SEARCH_PATH + [a methodA]; + [a methodB]; // expected-error{{unavailable}} + + // expected-note@SomeOtherKit/SomeOtherKit.h:6{{'methodB' has been explicitly marked unavailable here}} +#else +# error Not something we need to test +#endif +} diff --git a/clang/test/APINotes/swift-import-as.cpp b/clang/test/APINotes/swift-import-as.cpp new file mode 100644 index 0000000000000000000000000000000000000000..904857e5859303f9f498c98c6e7717bff9c4a2c7 --- /dev/null +++ b/clang/test/APINotes/swift-import-as.cpp @@ -0,0 +1,16 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -x c++ +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter ImmortalRefType | FileCheck -check-prefix=CHECK-IMMORTAL %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers %s -x c++ -ast-dump -ast-dump-filter RefCountedType | FileCheck -check-prefix=CHECK-REF-COUNTED %s + +#include <SwiftImportAs.h> + +// CHECK-IMMORTAL: Dumping ImmortalRefType: +// CHECK-IMMORTAL-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct ImmortalRefType +// CHECK-IMMORTAL: SwiftAttrAttr {{.+}} <<invalid sloc>> "import_reference" + +// CHECK-REF-COUNTED: Dumping RefCountedType: +// CHECK-REF-COUNTED-NEXT: CXXRecordDecl {{.+}} imported in SwiftImportAs {{.+}} struct RefCountedType +// CHECK-REF-COUNTED: SwiftAttrAttr {{.+}} <<invalid sloc>> "import_reference" +// CHECK-REF-COUNTED: SwiftAttrAttr {{.+}} <<invalid sloc>> "retain:RCRetain" +// CHECK-REF-COUNTED: SwiftAttrAttr {{.+}} <<invalid sloc>> "release:RCRelease" diff --git a/clang/test/APINotes/templates.cpp b/clang/test/APINotes/templates.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d4dce291615e18ac9d1b4b9bed32a4206f130c7f --- /dev/null +++ b/clang/test/APINotes/templates.cpp @@ -0,0 +1,9 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Tmpl -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -x c++ +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Tmpl -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Box -x c++ | FileCheck -check-prefix=CHECK-BOX %s + +#include "Templates.h" + +// CHECK-BOX: Dumping Box: +// CHECK-BOX-NEXT: ClassTemplateDecl {{.+}} imported in Templates Box +// CHECK-BOX: SwiftAttrAttr {{.+}} <<invalid sloc>> "import_owned" diff --git a/clang/test/APINotes/top-level-private-modules.c b/clang/test/APINotes/top-level-private-modules.c new file mode 100644 index 0000000000000000000000000000000000000000..0da72b2e36f4f2b1be3bb05e011963d4f559adfa --- /dev/null +++ b/clang/test/APINotes/top-level-private-modules.c @@ -0,0 +1,8 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -Wno-private-module -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify + +#include <PrivateLib.h> +#include <TopLevelPrivateKit/TopLevelPrivateKit_Private.h> + +void *testPlain = PrivateLib; // expected-error {{initializing 'void *' with an expression of incompatible type 'float'}} +void *testFramework = TopLevelPrivateKit_Private; // expected-error {{initializing 'void *' with an expression of incompatible type 'float'}} diff --git a/clang/test/APINotes/types.m b/clang/test/APINotes/types.m new file mode 100644 index 0000000000000000000000000000000000000000..133d504713d76cd97a1772fadfec3e9c5fcc1e07 --- /dev/null +++ b/clang/test/APINotes/types.m @@ -0,0 +1,28 @@ +// RUN: rm -rf %t && mkdir -p %t +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache -fapinotes-modules -Wno-private-module -fdisable-module-hash -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -verify +// RUN: %clang_cc1 -ast-print %t/ModulesCache/SimpleKit.pcm | FileCheck %s + +#import <SomeKit/SomeKit.h> +#import <SimpleKit/SimpleKit.h> + +// CHECK: struct __attribute__((swift_name("SuccessfullyRenamedA"))) RenamedAgainInAPINotesA { +// CHECK: struct __attribute__((swift_name("SuccessfullyRenamedB"))) RenamedAgainInAPINotesB { + +void test(OverriddenTypes *overridden) { + int *ip1 = global_int_ptr; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'double (*)(int, int)'}} + + int *ip2 = global_int_fun( // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'char *'}} + ip2, // expected-warning{{incompatible pointer types passing 'int *' to parameter of type 'double *'}} + ip2); // expected-warning{{incompatible pointer types passing 'int *' to parameter of type 'float *'}} + + int *ip3 = [overridden // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'char *'}} + methodToMangle: ip3 // expected-warning{{incompatible pointer types sending 'int *' to parameter of type 'double *'}} + second: ip3]; // expected-warning{{incompatible pointer types sending 'int *' to parameter of type 'float *'}} + + int *ip4 = overridden.intPropertyToMangle; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'double *'}} +} + +// expected-note@SomeKit/SomeKit.h:42{{passing argument to parameter 'ptr' here}} +// expected-note@SomeKit/SomeKit.h:42{{passing argument to parameter 'ptr2' here}} +// expected-note@SomeKit/SomeKit.h:48{{passing argument to parameter 'ptr1' here}} +// expected-note@SomeKit/SomeKit.h:48{{passing argument to parameter 'ptr2' here}} diff --git a/clang/test/APINotes/versioned-multi.c b/clang/test/APINotes/versioned-multi.c new file mode 100644 index 0000000000000000000000000000000000000000..48c51fd932e17ca43541d6dce4654546fbc7002f --- /dev/null +++ b/clang/test/APINotes/versioned-multi.c @@ -0,0 +1,69 @@ +// RUN: rm -rf %t && mkdir -p %t + +// Build and check the unversioned module file. +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Unversioned -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/Unversioned/VersionedKit.pcm | FileCheck -check-prefix=CHECK-UNVERSIONED %s + +// Build and check the various versions. +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Versioned3 -fdisable-module-hash -fapinotes-modules -fapinotes-swift-version=3 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/Versioned3/VersionedKit.pcm | FileCheck -check-prefix=CHECK-VERSIONED-3 %s + +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Versioned4 -fdisable-module-hash -fapinotes-modules -fapinotes-swift-version=4 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/Versioned4/VersionedKit.pcm | FileCheck -check-prefix=CHECK-VERSIONED-4 %s + +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Versioned5 -fdisable-module-hash -fapinotes-modules -fapinotes-swift-version=5 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/Versioned5/VersionedKit.pcm | FileCheck -check-prefix=CHECK-VERSIONED-5 %s + +#import <VersionedKit/VersionedKit.h> + +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef4; +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef4Notes __attribute__((swift_name("MultiVersionedTypedef4Notes_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef4Header __attribute__((swift_name("MultiVersionedTypedef4Header_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef34; +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef34Notes __attribute__((swift_name("MultiVersionedTypedef34Notes_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef34Header __attribute__((swift_name("MultiVersionedTypedef34Header_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef45; +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef45Notes __attribute__((swift_name("MultiVersionedTypedef45Notes_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef45Header __attribute__((swift_name("MultiVersionedTypedef45Header_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef345; +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef345Notes __attribute__((swift_name("MultiVersionedTypedef345Notes_NEW"))); +// CHECK-UNVERSIONED: typedef int MultiVersionedTypedef345Header __attribute__((swift_name("MultiVersionedTypedef345Header_NEW"))); + +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef4 __attribute__((swift_name("MultiVersionedTypedef4_4"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef4Notes __attribute__((swift_name("MultiVersionedTypedef4Notes_4"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef4Header __attribute__((swift_name("MultiVersionedTypedef4Header_4"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef34 __attribute__((swift_name("MultiVersionedTypedef34_3"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef34Notes __attribute__((swift_name("MultiVersionedTypedef34Notes_3"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef34Header __attribute__((swift_name("MultiVersionedTypedef34Header_3"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef45 __attribute__((swift_name("MultiVersionedTypedef45_4"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef45Notes __attribute__((swift_name("MultiVersionedTypedef45Notes_4"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef45Header __attribute__((swift_name("MultiVersionedTypedef45Header_4"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef345 __attribute__((swift_name("MultiVersionedTypedef345_3"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef345Notes __attribute__((swift_name("MultiVersionedTypedef345Notes_3"))); +// CHECK-VERSIONED-3: typedef int MultiVersionedTypedef345Header __attribute__((swift_name("MultiVersionedTypedef345Header_3"))); + +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef4 __attribute__((swift_name("MultiVersionedTypedef4_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef4Notes __attribute__((swift_name("MultiVersionedTypedef4Notes_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef4Header __attribute__((swift_name("MultiVersionedTypedef4Header_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef34 __attribute__((swift_name("MultiVersionedTypedef34_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef34Notes __attribute__((swift_name("MultiVersionedTypedef34Notes_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef34Header __attribute__((swift_name("MultiVersionedTypedef34Header_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef45 __attribute__((swift_name("MultiVersionedTypedef45_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef45Notes __attribute__((swift_name("MultiVersionedTypedef45Notes_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef45Header __attribute__((swift_name("MultiVersionedTypedef45Header_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef345 __attribute__((swift_name("MultiVersionedTypedef345_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef345Notes __attribute__((swift_name("MultiVersionedTypedef345Notes_4"))); +// CHECK-VERSIONED-4: typedef int MultiVersionedTypedef345Header __attribute__((swift_name("MultiVersionedTypedef345Header_4"))); + +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef4; +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef4Notes __attribute__((swift_name("MultiVersionedTypedef4Notes_NEW"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef4Header __attribute__((swift_name("MultiVersionedTypedef4Header_NEW"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef34; +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef34Notes __attribute__((swift_name("MultiVersionedTypedef34Notes_NEW"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef34Header __attribute__((swift_name("MultiVersionedTypedef34Header_NEW"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef45 __attribute__((swift_name("MultiVersionedTypedef45_5"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef45Notes __attribute__((swift_name("MultiVersionedTypedef45Notes_5"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef45Header __attribute__((swift_name("MultiVersionedTypedef45Header_5"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef345 __attribute__((swift_name("MultiVersionedTypedef345_5"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef345Notes __attribute__((swift_name("MultiVersionedTypedef345Notes_5"))); +// CHECK-VERSIONED-5: typedef int MultiVersionedTypedef345Header __attribute__((swift_name("MultiVersionedTypedef345Header_5"))); diff --git a/clang/test/APINotes/versioned.m b/clang/test/APINotes/versioned.m new file mode 100644 index 0000000000000000000000000000000000000000..61cc8c3f7c4d1ea80b2f71880d3ad13d24ae7b2d --- /dev/null +++ b/clang/test/APINotes/versioned.m @@ -0,0 +1,187 @@ +// RUN: rm -rf %t && mkdir -p %t + +// Build and check the unversioned module file. +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Unversioned -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/Unversioned/VersionedKit.pcm | FileCheck -check-prefix=CHECK-UNVERSIONED %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Unversioned -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter 'DUMP' | FileCheck -check-prefix=CHECK-DUMP -check-prefix=CHECK-UNVERSIONED-DUMP %s + +// Build and check the versioned module file. +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Versioned -fdisable-module-hash -fapinotes-modules -fapinotes-swift-version=3 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s +// RUN: %clang_cc1 -ast-print %t/ModulesCache/Versioned/VersionedKit.pcm | FileCheck -check-prefix=CHECK-VERSIONED %s +// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Versioned -fdisable-module-hash -fapinotes-modules -fapinotes-swift-version=3 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter 'DUMP' | FileCheck -check-prefix=CHECK-DUMP -check-prefix=CHECK-VERSIONED-DUMP %s + +#import <VersionedKit/VersionedKit.h> + +// CHECK-UNVERSIONED: void moveToPointDUMP(double x, double y) __attribute__((swift_name("moveTo(x:y:)"))); +// CHECK-VERSIONED: void moveToPointDUMP(double x, double y) __attribute__((swift_name("moveTo(a:b:)"))); + +// CHECK-DUMP-LABEL: Dumping moveToPointDUMP +// CHECK-VERSIONED-DUMP: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}} +// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "moveTo(x:y:)" +// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>> "moveTo(a:b:)" +// CHECK-UNVERSIONED-DUMP: SwiftNameAttr {{.+}} "moveTo(x:y:)" +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0{{$}} +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>> "moveTo(a:b:)" +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping unversionedRenameDUMP +// CHECK-DUMP: in VersionedKit unversionedRenameDUMP +// CHECK-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 0 IsReplacedByActive{{$}} +// CHECK-DUMP-NEXT: SwiftNameAttr {{.+}} "unversionedRename_HEADER()" +// CHECK-DUMP-NEXT: SwiftNameAttr {{.+}} "unversionedRename_NOTES()" +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping TestGenericDUMP +// CHECK-VERSIONED-DUMP: SwiftImportAsNonGenericAttr {{.+}} <<invalid sloc>> +// CHECK-UNVERSIONED-DUMP: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0{{$}} +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftImportAsNonGenericAttr {{.+}} <<invalid sloc>> +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping Swift3RenamedOnlyDUMP +// CHECK-DUMP: in VersionedKit Swift3RenamedOnlyDUMP +// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 3.0 {{[0-9]+}} IsReplacedByActive{{$}} +// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift3Name" +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0{{$}} +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>> "SpecialSwift3Name" +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping Swift3RenamedAlsoDUMP +// CHECK-DUMP: in VersionedKit Swift3RenamedAlsoDUMP +// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0 IsReplacedByActive{{$}} +// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <line:{{.+}}, col:{{.+}}> "Swift4Name" +// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift3Also" +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <line:{{.+}}, col:{{.+}}> "Swift4Name" +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 3.0{{$}} +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>> "SpecialSwift3Also" +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-LABEL: Dumping Swift4RenamedDUMP +// CHECK-DUMP: in VersionedKit Swift4RenamedDUMP +// CHECK-VERSIONED-DUMP-NEXT: SwiftVersionedRemovalAttr {{.+}} Implicit 4 {{[0-9]+}} IsReplacedByActive{{$}} +// CHECK-VERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} "SpecialSwift4Name" +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftVersionedAdditionAttr {{.+}} Implicit 4{{$}} +// CHECK-UNVERSIONED-DUMP-NEXT: SwiftNameAttr {{.+}} <<invalid sloc>> "SpecialSwift4Name" +// CHECK-DUMP-NOT: Attr + +// CHECK-DUMP-NOT: Dumping + +// CHECK-UNVERSIONED: void acceptClosure(void (^block)(void) __attribute__((noescape))); +// CHECK-VERSIONED: void acceptClosure(void (^block)(void)); + +// CHECK-UNVERSIONED: void privateFunc(void) __attribute__((swift_private)); + +// CHECK-UNVERSIONED: typedef double MyDoubleWrapper __attribute__((swift_wrapper("struct"))); + +// CHECK-UNVERSIONED: enum __attribute__((ns_error_domain(MyErrorDomain))) MyErrorCode { +// CHECK-UNVERSIONED-NEXT: MyErrorCodeFailed = 1 +// CHECK-UNVERSIONED-NEXT: }; + +// CHECK-UNVERSIONED: __attribute__((swift_bridge("MyValueType"))) +// CHECK-UNVERSIONED: @interface MyReferenceType + +// CHECK-VERSIONED: void privateFunc(void); + +// CHECK-VERSIONED: typedef double MyDoubleWrapper; + +// CHECK-VERSIONED: enum MyErrorCode { +// CHECK-VERSIONED-NEXT: MyErrorCodeFailed = 1 +// CHECK-VERSIONED-NEXT: }; + +// CHECK-VERSIONED-NOT: __attribute__((swift_bridge("MyValueType"))) +// CHECK-VERSIONED: @interface MyReferenceType + +// CHECK-UNVERSIONED: __attribute__((swift_objc_members) +// CHECK-UNVERSIONED-NEXT: @interface TestProperties +// CHECK-VERSIONED-NOT: __attribute__((swift_objc_members) +// CHECK-VERSIONED: @interface TestProperties + +// CHECK-UNVERSIONED-LABEL: enum __attribute__((flag_enum)) FlagEnum { +// CHECK-UNVERSIONED-NEXT: FlagEnumA = 1, +// CHECK-UNVERSIONED-NEXT: FlagEnumB = 2 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((flag_enum)) NewlyFlagEnum { +// CHECK-UNVERSIONED-NEXT: NewlyFlagEnumA = 1, +// CHECK-UNVERSIONED-NEXT: NewlyFlagEnumB = 2 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((flag_enum)) APINotedFlagEnum { +// CHECK-UNVERSIONED-NEXT: APINotedFlagEnumA = 1, +// CHECK-UNVERSIONED-NEXT: APINotedFlagEnumB = 2 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) OpenEnum { +// CHECK-UNVERSIONED-NEXT: OpenEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) NewlyOpenEnum { +// CHECK-UNVERSIONED-NEXT: NewlyOpenEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) NewlyClosedEnum { +// CHECK-UNVERSIONED-NEXT: NewlyClosedEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) ClosedToOpenEnum { +// CHECK-UNVERSIONED-NEXT: ClosedToOpenEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) OpenToClosedEnum { +// CHECK-UNVERSIONED-NEXT: OpenToClosedEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) APINotedOpenEnum { +// CHECK-UNVERSIONED-NEXT: APINotedOpenEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) APINotedClosedEnum { +// CHECK-UNVERSIONED-NEXT: APINotedClosedEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; + +// CHECK-VERSIONED-LABEL: enum __attribute__((flag_enum)) FlagEnum { +// CHECK-VERSIONED-NEXT: FlagEnumA = 1, +// CHECK-VERSIONED-NEXT: FlagEnumB = 2 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum NewlyFlagEnum { +// CHECK-VERSIONED-NEXT: NewlyFlagEnumA = 1, +// CHECK-VERSIONED-NEXT: NewlyFlagEnumB = 2 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum __attribute__((flag_enum)) APINotedFlagEnum { +// CHECK-VERSIONED-NEXT: APINotedFlagEnumA = 1, +// CHECK-VERSIONED-NEXT: APINotedFlagEnumB = 2 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) OpenEnum { +// CHECK-VERSIONED-NEXT: OpenEnumA = 1 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum NewlyOpenEnum { +// CHECK-VERSIONED-NEXT: NewlyOpenEnumA = 1 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum NewlyClosedEnum { +// CHECK-VERSIONED-NEXT: NewlyClosedEnumA = 1 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) ClosedToOpenEnum { +// CHECK-VERSIONED-NEXT: ClosedToOpenEnumA = 1 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) OpenToClosedEnum { +// CHECK-VERSIONED-NEXT: OpenToClosedEnumA = 1 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) APINotedOpenEnum { +// CHECK-VERSIONED-NEXT: APINotedOpenEnumA = 1 +// CHECK-VERSIONED-NEXT: }; +// CHECK-VERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) APINotedClosedEnum { +// CHECK-VERSIONED-NEXT: APINotedClosedEnumA = 1 +// CHECK-VERSIONED-NEXT: }; + +// These don't actually have versioned information, so we just check them once. +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) SoonToBeCFEnum { +// CHECK-UNVERSIONED-NEXT: SoonToBeCFEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) SoonToBeNSEnum { +// CHECK-UNVERSIONED-NEXT: SoonToBeNSEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) __attribute__((flag_enum)) SoonToBeCFOptions { +// CHECK-UNVERSIONED-NEXT: SoonToBeCFOptionsA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("open"))) __attribute__((flag_enum)) SoonToBeNSOptions { +// CHECK-UNVERSIONED-NEXT: SoonToBeNSOptionsA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) SoonToBeCFClosedEnum { +// CHECK-UNVERSIONED-NEXT: SoonToBeCFClosedEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum __attribute__((enum_extensibility("closed"))) SoonToBeNSClosedEnum { +// CHECK-UNVERSIONED-NEXT: SoonToBeNSClosedEnumA = 1 +// CHECK-UNVERSIONED-NEXT: }; +// CHECK-UNVERSIONED-LABEL: enum UndoAllThatHasBeenDoneToMe { +// CHECK-UNVERSIONED-NEXT: UndoAllThatHasBeenDoneToMeA = 1 +// CHECK-UNVERSIONED-NEXT: }; diff --git a/clang/test/APINotes/yaml-convert-diags.c b/clang/test/APINotes/yaml-convert-diags.c new file mode 100644 index 0000000000000000000000000000000000000000..1d352dc2c52309691a9c7a23460a0d20973a5e90 --- /dev/null +++ b/clang/test/APINotes/yaml-convert-diags.c @@ -0,0 +1,6 @@ +// RUN: rm -rf %t +// RUN: not %clang_cc1 -fsyntax-only -fapinotes %s -I %S/Inputs/BrokenHeaders2 2>&1 | FileCheck %s + +#include "SomeBrokenLib.h" + +// CHECK: error: multiple definitions of global function 'do_something_with_pointers' diff --git a/clang/test/APINotes/yaml-parse-diags.c b/clang/test/APINotes/yaml-parse-diags.c new file mode 100644 index 0000000000000000000000000000000000000000..3ae39ccb301d3d9af8604be4eeb9001c2095cca8 --- /dev/null +++ b/clang/test/APINotes/yaml-parse-diags.c @@ -0,0 +1,6 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fsyntax-only -fapinotes %s -I %S/Inputs/BrokenHeaders -verify + +#include "SomeBrokenLib.h" + +// expected-error@APINotes.apinotes:4{{unknown key 'Nu llabilityOfRet'}} diff --git a/clang/test/APINotes/yaml-reader-errors.m b/clang/test/APINotes/yaml-reader-errors.m new file mode 100644 index 0000000000000000000000000000000000000000..9e5ee34c3e4152feb2afb6dc45838642a6f5d442 --- /dev/null +++ b/clang/test/APINotes/yaml-reader-errors.m @@ -0,0 +1,5 @@ +// RUN: rm -rf %t +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fapinotes -fapinotes-modules -fmodules-cache-path=%t -I %S/Inputs/yaml-reader-errors/ -fsyntax-only %s > %t.err 2>&1 +// RUN: FileCheck %S/Inputs/yaml-reader-errors/UIKit.apinotes < %t.err + +@import UIKit; diff --git a/clang/test/AST/Interp/arrays.cpp b/clang/test/AST/Interp/arrays.cpp index 4b112d7fdddfdb8cc68a4ddab3953e3dee31ff9d..2443992f75fb7d09705b6adff9cf2566832c6110 100644 --- a/clang/test/AST/Interp/arrays.cpp +++ b/clang/test/AST/Interp/arrays.cpp @@ -429,18 +429,13 @@ namespace Incomplete { // both-note {{array-to-pointer decay of array member without known bound}} /// These are from test/SemaCXX/constant-expression-cxx11.cpp - /// and are the only tests using the 'indexing of array without known bound' diagnostic. - /// We currently diagnose them differently. - extern int arr[]; // expected-note 3{{declared here}} + extern int arr[]; constexpr int *c = &arr[1]; // both-error {{must be initialized by a constant expression}} \ - // ref-note {{indexing of array without known bound}} \ - // expected-note {{read of non-constexpr variable 'arr'}} + // both-note {{indexing of array without known bound}} constexpr int *d = &arr[1]; // both-error {{must be initialized by a constant expression}} \ - // ref-note {{indexing of array without known bound}} \ - // expected-note {{read of non-constexpr variable 'arr'}} + // both-note {{indexing of array without known bound}} constexpr int *e = arr + 1; // both-error {{must be initialized by a constant expression}} \ - // ref-note {{indexing of array without known bound}} \ - // expected-note {{read of non-constexpr variable 'arr'}} + // both-note {{indexing of array without known bound}} } namespace GH69115 { diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp index 08fca8428cf5e8ed1406ddbdbde5f7a113924efe..2e9d1a831dcf6e26ad70291b2dadec1121906717 100644 --- a/clang/test/AST/Interp/builtin-functions.cpp +++ b/clang/test/AST/Interp/builtin-functions.cpp @@ -510,3 +510,14 @@ namespace bswap { int h4 = __builtin_bswap32(0x1234) == 0x34120000 ? 1 : f(); int h5 = __builtin_bswap64(0x1234) == 0x3412000000000000 ? 1 : f(); } + +#define CFSTR __builtin___CFStringMakeConstantString +void test7(void) { + const void *X; +#if !defined(_AIX) + X = CFSTR("\242"); // both-warning {{input conversion stopped}} + X = CFSTR("\0"); // no-warning + X = CFSTR(242); // both-error {{cannot initialize a parameter of type 'const char *' with an rvalue of type 'int'}} + X = CFSTR("foo", "bar"); // both-error {{too many arguments to function call}} +#endif +} diff --git a/clang/test/AST/Interp/builtins.cpp b/clang/test/AST/Interp/builtins.cpp index 06a22b16b2dcbb4c9bd2d177709ddb99bdcace09..9095d1bf8d6a3a8170c3b4b72f6287522f03d6cf 100644 --- a/clang/test/AST/Interp/builtins.cpp +++ b/clang/test/AST/Interp/builtins.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter %s -verify -fms-extensions -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter %s -fms-extensions -S -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter %s -Wno-constant-evaluated -verify -fms-extensions +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter %s -Wno-constant-evaluated -fms-extensions -S -emit-llvm -o - | FileCheck %s // RUN: %clang_cc1 -verify=ref %s -Wno-constant-evaluated -fms-extensions // RUN: %clang_cc1 -verify=ref %s -Wno-constant-evaluated %s -fms-extensions -S -emit-llvm -o - | FileCheck %s diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c index 8de6139efbea09c620cc32fc44368129e96a7d84..10e23839f2ba2a889af774f49ecb03dd557da974 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/Interp/c.c @@ -66,11 +66,11 @@ _Static_assert((&a - 100) != 0, ""); // pedantic-ref-warning {{is a GNU extensio // pedantic-ref-note {{-100 of non-array}} \ // pedantic-expected-note {{-100 of non-array}} /// extern variable of a composite type. -/// FIXME: The 'cast from void*' note is missing in the new interpreter. +/// FIXME: The 'this conversion is not allowed' note is missing in the new interpreter. extern struct Test50S Test50; _Static_assert(&Test50 != (void*)0, ""); // all-warning {{always true}} \ // pedantic-ref-warning {{is a GNU extension}} \ - // pedantic-ref-note {{cast from 'void *' is not allowed}} \ + // pedantic-ref-note {{this conversion is not allowed in a constant expression}} \ // pedantic-expected-warning {{is a GNU extension}} struct y {int x,y;}; @@ -201,3 +201,11 @@ void localCompoundLiteral(void) { // pedantic-ref-warning {{use of an empty initializer}} }; } + +/// struct copy +struct StrA {int a; }; +const struct StrA sa = { 12 }; +const struct StrA * const sb = &sa; +const struct StrA sc = *sb; +_Static_assert(sc.a == 12, ""); // pedantic-ref-warning {{GNU extension}} \ + // pedantic-expected-warning {{GNU extension}} diff --git a/clang/test/AST/Interp/c23.c b/clang/test/AST/Interp/c23.c new file mode 100644 index 0000000000000000000000000000000000000000..cf1bf4d4e7d9052520520a7c14e6a445ab78d9d8 --- /dev/null +++ b/clang/test/AST/Interp/c23.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -std=c23 -fexperimental-new-constant-interpreter -verify=expected,both %s +// RUN: %clang_cc1 -std=c23 -verify=ref,both %s + + + +const _Bool inf1 = (1.0/0.0 == __builtin_inf()); +constexpr _Bool inf2 = (1.0/0.0 == __builtin_inf()); // both-error {{must be initialized by a constant expression}} \ + // both-note {{division by zero}} +constexpr _Bool inf3 = __builtin_inf() == __builtin_inf(); + + diff --git a/clang/test/AST/Interp/complex.c b/clang/test/AST/Interp/complex.c index b5f30b87baa79a513cd2e75603ff566d8b0db71f..a39f83160ef8ca449b0d0931fe6825c4294ccaba 100644 --- a/clang/test/AST/Interp/complex.c +++ b/clang/test/AST/Interp/complex.c @@ -19,3 +19,12 @@ const _Complex float FC = {0.0f, 0.0f}; _Static_assert(!FC, ""); const _Complex float FI = {0, 0}; _Static_assert(!FI, ""); + + +/// Make sure we're stripping the _Atomic part from the +/// complex type. +void testComplexFloat(_Atomic(_Complex float) *fp) { + _Atomic(_Complex float) x = 2.0f; + _Complex float f = *fp; + *fp = f; +} diff --git a/clang/test/AST/Interp/complex.cpp b/clang/test/AST/Interp/complex.cpp index 6a42afc68d26c78b1c016a0430839c8a763af5ac..09cb620d7b7c398cf1e51312a2ff64af3adc48cf 100644 --- a/clang/test/AST/Interp/complex.cpp +++ b/clang/test/AST/Interp/complex.cpp @@ -9,6 +9,9 @@ static_assert(&__imag z1 == &__real z1 + 1, ""); static_assert((*(&__imag z1)) == __imag z1, ""); static_assert((*(&__real z1)) == __real z1, ""); +constexpr _Complex int Comma1 = {1, 2}; +constexpr _Complex int Comma2 = (0, Comma1); +static_assert(Comma1 == Comma1, ""); constexpr double setter() { _Complex float d = {1.0, 2.0}; @@ -313,3 +316,53 @@ namespace Cmp { static_assert((0.0 + 0.0j) > (0.0 + 0.0j)); // both-error {{invalid operands to binary expression}} static_assert((0.0 + 0.0j) ^ (0.0 + 0.0j)); // both-error {{invalid operands to binary expression}} } + +/// From test/SemaCXX/constant-expression-cxx11.cpp +/// +/// Some of the diagnostics we emit are different than the one of the +/// current interpreter. +/// +/// FIXME: For the '&test3 + 1' test, we are _not_ creating an explicit pointer variable +/// anywhere and so the &test3+1 is the same as __imag(test3) for us. +namespace ComplexConstexpr { + constexpr _Complex float test1 = {}; + constexpr _Complex float test2 = {1}; + constexpr _Complex double test3 = {1,2}; + constexpr _Complex int test4 = {4}; + constexpr _Complex int test5 = 4; + constexpr _Complex int test6 = {5,6}; + typedef _Complex float fcomplex; + constexpr fcomplex test7 = fcomplex(); + + constexpr const double &t2r = __real test3; + constexpr const double &t2i = __imag test3; + static_assert(&t2r + 1 == &t2i, ""); + static_assert(t2r == 1.0, ""); + static_assert(t2i == 2.0, ""); + constexpr const double *t2p = &t2r; + static_assert(t2p[-1] == 0.0, ""); // both-error {{constant expr}} \ + // both-note {{cannot refer to element -1 of array of 2 elements}} + static_assert(t2p[0] == 1.0, ""); + static_assert(t2p[1] == 2.0, ""); + static_assert(t2p[2] == 0.0, ""); // both-error {{constant expr}} \ + // both-note {{one-past-the-end pointer}} + static_assert(t2p[3] == 0.0, ""); // both-error {{constant expr}} \ + // 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}} + constexpr float pi = __imag *p; // both-error {{constant expr}} \ + // ref-note {{cannot access imaginary component of null}} \ + // expected-note {{cannot perform pointer arithmetic on 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}} + constexpr double qi = __imag *q; // both-error {{constant expr}} \ + // ref-note {{cannot access imaginary component of pointer past the end}} \ + // expected-note {{read of dereferenced one-past-the-end pointer}} + + static_assert(__real test6 == 5, ""); + static_assert(__imag test6 == 6, ""); + static_assert(&__imag test6 == &__real test6 + 1, ""); +} diff --git a/clang/test/AST/Interp/cxx23.cpp b/clang/test/AST/Interp/cxx23.cpp index 127b58915127cf2d07307052e4056600f7593eb6..042e29613aa75301bc6a0b8eb584ad34187d204b 100644 --- a/clang/test/AST/Interp/cxx23.cpp +++ b/clang/test/AST/Interp/cxx23.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=ref20,all,all-20 %s +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=ref20,all,all20 %s // RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=ref23,all %s -// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected20,all,all-20 %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected20,all,all20 %s -fexperimental-new-constant-interpreter // RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=expected23,all %s -fexperimental-new-constant-interpreter /// FIXME: The new interpreter is missing all the 'control flows through...' diagnostics. @@ -108,9 +108,9 @@ namespace StaticOperators { static_assert(f2() == 3); struct S1 { - constexpr S1() { // all-20-error {{never produces a constant expression}} + constexpr S1() { // all20-error {{never produces a constant expression}} throw; // all-note {{not valid in a constant expression}} \ - // all-20-note {{not valid in a constant expression}} + // all20-note {{not valid in a constant expression}} } static constexpr int operator()() { return 3; } // ref20-warning {{C++23 extension}} \ // expected20-warning {{C++23 extension}} @@ -121,3 +121,28 @@ namespace StaticOperators { } + +int test_in_lambdas() { + auto c = [](int n) constexpr { + if (n == 0) + return 0; + else + goto test; // all-note {{subexpression not valid in a constant expression}} \ + // all20-warning {{use of this statement in a constexpr function is a C++23 extension}} + test: + return 1; + }; + c(0); + constexpr auto A = c(1); // all-error {{must be initialized by a constant expression}} \ + // all-note {{in call to}} + return 0; +} + +/// PackIndexExpr. +template <auto... p> +struct check_ice { + enum e { + x = p...[0] // all-warning {{is a C++2c extension}} + }; +}; +static_assert(check_ice<42>::x == 42); diff --git a/clang/test/AST/Interp/cxx98.cpp b/clang/test/AST/Interp/cxx98.cpp index 73e45372066334a862c8426f9383f4a2d4dd5eea..ba6bcd97d920dd4767ee2afff4bcee75b3c85cc7 100644 --- a/clang/test/AST/Interp/cxx98.cpp +++ b/clang/test/AST/Interp/cxx98.cpp @@ -18,13 +18,12 @@ template struct C<cval>; /// FIXME: This example does not get properly diagnosed in the new interpreter. extern const int recurse1; -const int recurse2 = recurse1; // both-note {{declared here}} +const int recurse2 = recurse1; // ref-note {{declared here}} const int recurse1 = 1; int array1[recurse1]; int array2[recurse2]; // ref-warning 2{{variable length array}} \ // ref-note {{initializer of 'recurse2' is not a constant expression}} \ // expected-warning {{variable length array}} \ - // expected-note {{read of non-const variable 'recurse2'}} \ // expected-error {{variable length array}} int NCI; // both-note {{declared here}} @@ -39,3 +38,10 @@ struct V { // both-error {{constructor cannot have a return type}} }; _Static_assert(V().c[0], ""); // both-error {{is not an integral constant expression}} + +struct C0 { + template<typename U> static U Data; // both-warning {{C++14 extension}} + template<typename U> static const U Data<U*> = U(); +}; +const int c0_test = C0::Data<int*>; +_Static_assert(c0_test == 0, ""); diff --git a/clang/test/AST/Interp/if.cpp b/clang/test/AST/Interp/if.cpp index 86ae8de6f73ebb7ec321c402320cd83e7cc9ac1b..37289d69d3255499b73236dcb09e25aa03d47b82 100644 --- a/clang/test/AST/Interp/if.cpp +++ b/clang/test/AST/Interp/if.cpp @@ -1,8 +1,5 @@ -// RUN: %clang_cc1 -std=c++23 -fsyntax-only -fexperimental-new-constant-interpreter %s -verify -// RUN: %clang_cc1 -std=c++23 -fsyntax-only %s -verify=ref - -// expected-no-diagnostics -// ref-no-diagnostics +// RUN: %clang_cc1 -std=c++23 -fsyntax-only -fexperimental-new-constant-interpreter %s -verify=expected,both +// RUN: %clang_cc1 -std=c++23 -fsyntax-only %s -verify=ref,both namespace ConstEval { constexpr int f() { @@ -51,3 +48,13 @@ namespace InitDecl { } static_assert(attrs() == 1, ""); }; + +/// The faulty if statement creates a RecoveryExpr with contains-errors, +/// but the execution will never reach that. +constexpr char g(char const (&x)[2]) { + return 'x'; + if (auto [a, b] = x) // both-error {{an array type is not allowed here}} \ + // both-warning {{ISO C++17 does not permit structured binding declaration in a condition}} + ; +} +static_assert(g("x") == 'x'); diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp index 7ae8499b1156dd2c2fbe9be4d81ccb6120a3ce4e..277438d2e6311431e60bb3c81a08261cf568e17a 100644 --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -910,6 +910,18 @@ namespace TypeTraits { struct U {}; static_assert(S3<U>{}.foo(), ""); static_assert(!S3<T>{}.foo(), ""); + + typedef int Int; + typedef Int IntAr[10]; + typedef const IntAr ConstIntAr; + typedef ConstIntAr ConstIntArAr[4]; + + static_assert(__array_rank(IntAr) == 1, ""); + static_assert(__array_rank(ConstIntArAr) == 2, ""); + + static_assert(__array_extent(IntAr, 0) == 10, ""); + static_assert(__array_extent(ConstIntArAr, 0) == 4, ""); + static_assert(__array_extent(ConstIntArAr, 1) == 10, ""); } #if __cplusplus >= 201402L @@ -1113,6 +1125,9 @@ namespace InvalidDeclRefs { int b03 = 3; // both-note {{declared here}} static_assert(b03, ""); // both-error {{not an integral constant expression}} \ // both-note {{read of non-const variable}} + + extern int var; + constexpr int *varp = &var; // Ok. } namespace NonConstReads { @@ -1182,8 +1197,16 @@ namespace incdecbool { } #if __cplusplus >= 201402L +/// NOTE: The diagnostics of the two interpreters are a little +/// different here, but they both make sense. constexpr int externvar1() { // both-error {{never produces a constant expression}} - extern char arr[]; // both-note {{declared here}} - return arr[0]; // both-note {{read of non-constexpr variable 'arr'}} + extern char arr[]; // ref-note {{declared here}} + return arr[0]; // ref-note {{read of non-constexpr variable 'arr'}} \ + // expected-note {{array-to-pointer decay of array member without known bound is not supported}} } #endif + +namespace Extern { + constexpr extern char Oops = 1; + static_assert(Oops == 1, ""); +} diff --git a/clang/test/AST/Interp/ms.cpp b/clang/test/AST/Interp/ms.cpp new file mode 100644 index 0000000000000000000000000000000000000000..99716e90c7a1db9054a01fc2fb50fac271463193 --- /dev/null +++ b/clang/test/AST/Interp/ms.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -verify=ref,both %s -fms-extensions +// RUN: %clang_cc1 -verify=expected,both %s -fexperimental-new-constant-interpreter -fms-extensions + +// ref-no-diagnostics +// expected-no-diagnostics + +/// Used to assert because the two parameters to _rotl do not have the same type. +static_assert(_rotl(0x01, 5) == 32); diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp index 7ddc56c9b5dfc4f2a34025b0959c8397202c0fef..0f76e0cfe99277386fa395f669c834e02a7dcc2e 100644 --- a/clang/test/AST/Interp/records.cpp +++ b/clang/test/AST/Interp/records.cpp @@ -1238,3 +1238,50 @@ namespace InvalidCtorInitializer { // no crash on evaluating the constexpr ctor. constexpr int Z = X().Y; // both-error {{constexpr variable 'Z' must be initialized by a constant expression}} } + +extern int f(); // both-note {{here}} +struct HasNonConstExprMemInit { + int x = f(); // both-note {{non-constexpr function}} + constexpr HasNonConstExprMemInit() {} // both-error {{never produces a constant expression}} +}; + +namespace { + template <class Tp, Tp v> + struct integral_constant { + static const Tp value = v; + }; + + template <class Tp, Tp v> + const Tp integral_constant<Tp, v>::value; + + typedef integral_constant<bool, true> true_type; + typedef integral_constant<bool, false> false_type; + + /// This might look innocent, but we get an evaluateAsInitializer call for the + /// static bool member before evaluating the first static_assert, but we do NOT + /// get such a call for the second one. So the second one needs to lazily visit + /// the data member itself. + static_assert(true_type::value, ""); + static_assert(true_type::value, ""); +} + +#if __cplusplus >= 202002L +namespace { + /// Used to crash because the CXXDefaultInitExpr is of compound type. + struct A { + int &x; + constexpr ~A() { --x; } + }; + struct B { + int &x; + const A &a = A{x}; + }; + constexpr int a() { + int x = 1; + int f = B{x}.x; + B{x}; // both-warning {{expression result unused}} + + return 1; + } +} +#endif diff --git a/clang/test/AST/ast-dump-concepts.cpp b/clang/test/AST/ast-dump-concepts.cpp index 06518a71987a2251f10ff27a6fafdefd326052e6..5bb174e3548ed2f28e8497537ab68f4a1873df38 100644 --- a/clang/test/AST/ast-dump-concepts.cpp +++ b/clang/test/AST/ast-dump-concepts.cpp @@ -57,3 +57,53 @@ struct Foo { template <variadic_concept<int>... Ts> Foo(); }; + +namespace GH82628 { +namespace ns { + +template <typename T> +concept C = true; + +} // namespace ns + +using ns::C; + +// CHECK: ConceptDecl {{.*}} Foo +// CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 T +// CHECK-NEXT: `-ConceptSpecializationExpr {{.*}} UsingShadow {{.*}} 'C' +template <typename T> +concept Foo = C<T>; + +// CHECK: TemplateTypeParmDecl {{.*}} Concept {{.*}} 'C' (UsingShadow {{.*}} 'C') +template <C T> +constexpr bool FooVar = false; + +// CHECK: ConceptSpecializationExpr {{.*}} UsingShadow {{.*}} 'C' +template <typename T> requires C<T> +constexpr bool FooVar2 = true; + +// CHECK: SimpleRequirement +// CHECK-NEXT: `-ConceptSpecializationExpr {{.*}} UsingShadow {{.*}} 'C' +template <typename T> requires requires (T) { C<T>; } +constexpr bool FooVar3 = true; + +// CHECK: NonTypeTemplateParmDecl +// CHECK-NEXT: `-ConceptSpecializationExpr {{.*}} UsingShadow {{.*}} 'C' +template <C auto T> +constexpr bool FooVar4 = bool(T()); + +// CHECK: FunctionTemplateDecl +// CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} Concept {{.*}} 'C' (UsingShadow {{.*}} 'C') depth 0 index 0 ... T +// CHECK: NonTypeTemplateParmDecl {{.*}} depth 0 index 1 U +// CHECK-NEXT: `-ConceptSpecializationExpr {{.*}} UsingShadow {{.*}} 'C' +// CHECK: |-TemplateTypeParmDecl {{.*}} Concept {{.*}} 'C' (UsingShadow {{.*}} 'C') depth 0 index 2 V:auto + +template <C... T, C auto U> +auto FooFunc(C auto V) -> C decltype(auto) { + // FIXME: TypeLocs inside of the function body cannot be dumped via -ast-dump for now. + // See clang-tools-extra/clangd/unittests/SelectionTests.cpp:SelectionTest.UsingConcepts for their checkings. + C auto W = V; + return W; +} + +} diff --git a/clang/test/AST/ast-dump-invalid.cpp b/clang/test/AST/ast-dump-invalid.cpp index 0a301dba51d288d08e0f119f261731ebe4431b81..5b6d74194b989d4dbf1a3d2a9a1702ba73d3f78f 100644 --- a/clang/test/AST/ast-dump-invalid.cpp +++ b/clang/test/AST/ast-dump-invalid.cpp @@ -60,3 +60,12 @@ double Str::foo1(double, invalid_type) // CHECK-NEXT: `-ReturnStmt {{.*}} <col:3, col:10> // CHECK-NEXT: `-ImplicitCastExpr {{.*}} <col:10> 'double' <IntegralToFloating> // CHECK-NEXT: `-IntegerLiteral {{.*}} <col:10> 'int' 45 + +namespace TestAliasTemplateDecl { +template<typename T> class A; + +template<typename T> +template<typename U> using InvalidAlias = A<U>; +// CHECK: TypeAliasTemplateDecl {{.*}} invalid InvalidAlias +// CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 T +} diff --git a/clang/test/Analysis/ArrayDelete.cpp b/clang/test/Analysis/ArrayDelete.cpp index 3b8d49552376ed9e1887ae8a408db5e5606cac9e..6887e0a35fb8bd882e3b1c6d38e48056aff44365 100644 --- a/clang/test/Analysis/ArrayDelete.cpp +++ b/clang/test/Analysis/ArrayDelete.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.ArrayDelete -std=c++11 -verify -analyzer-output=text %s +// RUN: %clang_cc1 -analyze -analyzer-checker=cplusplus.ArrayDelete -std=c++11 -verify -analyzer-output=text %s struct Base { virtual ~Base() = default; diff --git a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h index 3ef7af2ea6c6ab449b56c024ae43d990683bd9be..85db68d41a6c8040f229b3179607d2275ef35721 100644 --- a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h +++ b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h @@ -1106,11 +1106,20 @@ using ostream = basic_ostream<char>; extern std::ostream cout; ostream &operator<<(ostream &, const string &); - #if __cplusplus >= 202002L template <class T> ostream &operator<<(ostream &, const std::unique_ptr<T> &); #endif + +template <class CharT> +class basic_istream; + +using istream = basic_istream<char>; + +extern std::istream cin; + +istream &getline(istream &, string &, char); +istream &getline(istream &, string &); } // namespace std #ifdef TEST_INLINABLE_ALLOCATORS diff --git a/clang/test/Analysis/analyzer-display-progress.cpp b/clang/test/Analysis/analyzer-display-progress.cpp index dc8e27a8c3b45c70e095fa66a102bf348229ca68..fa1860004d0319680512f5bad60c5471e286e20b 100644 --- a/clang/test/Analysis/analyzer-display-progress.cpp +++ b/clang/test/Analysis/analyzer-display-progress.cpp @@ -1,22 +1,46 @@ -// RUN: %clang_analyze_cc1 -analyzer-display-progress %s 2>&1 | FileCheck %s +// RUN: %clang_analyze_cc1 -verify %s 2>&1 \ +// RUN: -analyzer-display-progress \ +// RUN: -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-output=text \ +// RUN: | FileCheck %s -void f() {}; -void g() {}; -void h() {} +void clang_analyzer_warnIfReached(); + +// expected-note@+2 {{[debug] analyzing from f()}} +// expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} +void f() { clang_analyzer_warnIfReached(); } + +// expected-note@+2 {{[debug] analyzing from g()}} +// expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} +void g() { clang_analyzer_warnIfReached(); } + +// expected-note@+2 {{[debug] analyzing from h()}} +// expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} +void h() { clang_analyzer_warnIfReached(); } struct SomeStruct { - void f() {} + // expected-note@+2 {{[debug] analyzing from SomeStruct::f()}} + // expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} + void f() { clang_analyzer_warnIfReached(); } }; struct SomeOtherStruct { - void f() {} + // expected-note@+2 {{[debug] analyzing from SomeOtherStruct::f()}} + // expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} + void f() { clang_analyzer_warnIfReached(); } }; namespace ns { struct SomeStruct { - void f(int) {} - void f(float, ::SomeStruct) {} - void f(float, SomeStruct) {} + // expected-note@+2 {{[debug] analyzing from ns::SomeStruct::f(int)}} + // expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} + void f(int) { clang_analyzer_warnIfReached(); } + // expected-note@+2 {{[debug] analyzing from ns::SomeStruct::f(float, ::SomeStruct)}} + // expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} + void f(float, ::SomeStruct) { clang_analyzer_warnIfReached(); } + // expected-note@+2 {{[debug] analyzing from ns::SomeStruct::f(float, SomeStruct)}} + // expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} + void f(float, SomeStruct) { clang_analyzer_warnIfReached(); } }; } diff --git a/clang/test/Analysis/analyzer-display-progress.m b/clang/test/Analysis/analyzer-display-progress.m index 24414f659c39ac7c9b4acc914e051968ebb90bc0..90f223b3486153ff90a6dd0aed5320dc2592ebbb 100644 --- a/clang/test/Analysis/analyzer-display-progress.m +++ b/clang/test/Analysis/analyzer-display-progress.m @@ -1,8 +1,16 @@ -// RUN: %clang_analyze_cc1 -fblocks -analyzer-display-progress %s 2>&1 | FileCheck %s +// RUN: %clang_analyze_cc1 -fblocks -verify %s 2>&1 \ +// RUN: -analyzer-display-progress \ +// RUN: -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-output=text \ +// RUN: | FileCheck %s #include "Inputs/system-header-simulator-objc.h" -static void f(void) {} +void clang_analyzer_warnIfReached(); + +// expected-note@+2 {{[debug] analyzing from f}} +// expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} +static void f(void) { clang_analyzer_warnIfReached(); } @interface I: NSObject -(void)instanceMethod:(int)arg1 with:(int)arg2; @@ -10,21 +18,26 @@ static void f(void) {} @end @implementation I --(void)instanceMethod:(int)arg1 with:(int)arg2 {} -+(void)classMethod {} +// expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} +-(void)instanceMethod:(int)arg1 with:(int)arg2 { clang_analyzer_warnIfReached(); } + +// expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} ++(void)classMethod { clang_analyzer_warnIfReached(); } @end +// expected-note@+1 3 {{[debug] analyzing from g}} void g(I *i, int x, int y) { - [I classMethod]; - [i instanceMethod: x with: y]; + [I classMethod]; // expected-note {{Calling 'classMethod'}} + [i instanceMethod: x with: y]; // expected-note {{Calling 'instanceMethod:with:'}} void (^block)(void); - block = ^{}; - block(); + // expected-warning@+1 {{REACHABLE}} expected-note@+1 {{REACHABLE}} + block = ^{ clang_analyzer_warnIfReached(); }; + block(); // expected-note {{Calling anonymous block}} } // CHECK: analyzer-display-progress.m f // CHECK: analyzer-display-progress.m -[I instanceMethod:with:] // CHECK: analyzer-display-progress.m +[I classMethod] // CHECK: analyzer-display-progress.m g -// CHECK: analyzer-display-progress.m block (line: 22, col: 11) +// CHECK: analyzer-display-progress.m block (line: 35, col: 11) diff --git a/clang/test/Analysis/analyzer-note-analysis-entry-points.cpp b/clang/test/Analysis/analyzer-note-analysis-entry-points.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d321bfae61c9de0ee20151dac7e2e4d78d6935f --- /dev/null +++ b/clang/test/Analysis/analyzer-note-analysis-entry-points.cpp @@ -0,0 +1,75 @@ +// RUN: %clang_analyze_cc1 -verify=common %s \ +// RUN: -analyzer-checker=deadcode.DeadStores,debug.ExprInspection \ +// RUN: -analyzer-note-analysis-entry-points + +// RUN: %clang_analyze_cc1 -verify=common,textout %s \ +// RUN: -analyzer-checker=deadcode.DeadStores,debug.ExprInspection \ +// RUN: -analyzer-note-analysis-entry-points \ +// RUN: -analyzer-output=text + +// Test the actual source locations/ranges of entry point notes. +// RUN: %clang_analyze_cc1 %s \ +// RUN: -analyzer-checker=deadcode.DeadStores,debug.ExprInspection \ +// RUN: -analyzer-note-analysis-entry-points \ +// RUN: -analyzer-output=text 2>&1 \ +// RUN: | FileCheck --strict-whitespace %s + + +void clang_analyzer_warnIfReached(); + +void other() { + // common-warning@+1 {{REACHABLE}} textout-note@+1 {{REACHABLE}} + clang_analyzer_warnIfReached(); +} + +struct SomeOtherStruct { + // CHECK: note: [debug] analyzing from SomeOtherStruct::f() + // CHECK-NEXT: | void f() { + // CHECK-NEXT: | ^ + // textout-note@+1 {{[debug] analyzing from SomeOtherStruct::f()}} + void f() { + other(); // textout-note {{Calling 'other'}} + } +}; + +// CHECK: note: [debug] analyzing from operator""_w(const char *) +// CHECK-NEXT: | unsigned operator ""_w(const char*) { +// CHECK-NEXT: | ^ +// textout-note@+1 {{[debug] analyzing from operator""_w(const char *)}} +unsigned operator ""_w(const char*) { + // common-warning@+1 {{REACHABLE}} textout-note@+1 {{REACHABLE}} + clang_analyzer_warnIfReached(); + return 404; +} + +// textout-note@+1 {{[debug] analyzing from checkASTCodeBodyHasAnalysisEntryPoints()}} +void checkASTCodeBodyHasAnalysisEntryPoints() { + int z = 1; + z = 2; + // common-warning@-1 {{Value stored to 'z' is never read}} + // textout-note@-2 {{Value stored to 'z' is never read}} +} + +void notInvokedLambdaScope() { + // CHECK: note: [debug] analyzing from notInvokedLambdaScope()::(anonymous class)::operator()() + // CHECK-NEXT: | auto notInvokedLambda = []() { + // CHECK-NEXT: | ^ + // textout-note@+1 {{[debug] analyzing from notInvokedLambdaScope()::(anonymous class)::operator()()}} + auto notInvokedLambda = []() { + // common-warning@+1 {{REACHABLE}} textout-note@+1 {{REACHABLE}} + clang_analyzer_warnIfReached(); + }; + (void)notInvokedLambda; // Not invoking the lambda. +} + +// CHECK: note: [debug] analyzing from invokedLambdaScope() +// CHECK-NEXT: | void invokedLambdaScope() { +// CHECK-NEXT: | ^ +// textout-note@+1 {{[debug] analyzing from invokedLambdaScope()}} +void invokedLambdaScope() { + auto invokedLambda = []() { + // common-warning@+1 {{REACHABLE}} textout-note@+1 {{REACHABLE}} + clang_analyzer_warnIfReached(); + }; + invokedLambda(); // textout-note {{Calling 'operator()'}} +} \ No newline at end of file diff --git a/clang/test/Analysis/block-in-critical-section.cpp b/clang/test/Analysis/block-in-critical-section.cpp index fcf6188fc033ec8f4f6f7990916003427b26a63b..87c26b9f1b5209fe72c4675f76117cd3a08e6c58 100644 --- a/clang/test/Analysis/block-in-critical-section.cpp +++ b/clang/test/Analysis/block-in-critical-section.cpp @@ -1,4 +1,8 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.unix.BlockInCriticalSection -std=c++11 -verify %s +// RUN: %clang_analyze_cc1 \ +// RUN: -analyzer-checker=alpha.unix.BlockInCriticalSection \ +// RUN: -std=c++11 \ +// RUN: -analyzer-output text \ +// RUN: -verify %s void sleep(int x) {} @@ -21,108 +25,242 @@ template<typename T> struct not_real_lock { not_real_lock<T>(std::mutex) {} }; -} +} // namespace std + +struct FILE; +int getc(FILE *stream); +char* fgets(char *str, FILE *stream); +using ssize_t = long long; +using size_t = unsigned long long; +ssize_t read(int fd, void *buf, size_t count); +ssize_t recv(int sockfd, void *buf, size_t len, int flags); -void getc() {} -void fgets() {} -void read() {} -void recv() {} +struct pthread_mutex_t; +void pthread_mutex_lock(pthread_mutex_t *mutex); +void pthread_mutex_trylock(pthread_mutex_t *mutex); +void pthread_mutex_unlock(pthread_mutex_t *mutex); -void pthread_mutex_lock() {} -void pthread_mutex_trylock() {} -void pthread_mutex_unlock() {} +struct mtx_t; +void mtx_lock(mtx_t *mutex); +void mtx_timedlock(mtx_t *mutex); +void mtx_trylock(mtx_t *mutex); +void mtx_unlock(mtx_t *mutex); -void mtx_lock() {} -void mtx_timedlock() {} -void mtx_trylock() {} -void mtx_unlock() {} +// global params for dummy function calls +FILE *stream; +char *str; +int fd; +void *buf; +size_t count; +int sockfd; +size_t len; +int flags; void testBlockInCriticalSectionWithStdMutex() { std::mutex m; - m.lock(); + m.lock(); // expected-note 5{{Entering critical section here}} sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} - getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}} - fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} - read(); // expected-warning {{Call to blocking function 'read' inside of critical section}} - recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} + getc(stream); // expected-warning {{Call to blocking function 'getc' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}} + fgets(str, stream); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}} + read(fd, buf, count); // expected-warning {{Call to blocking function 'read' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'read' inside of critical section}} + recv(sockfd, buf, count, flags); // expected-warning {{Call to blocking function 'recv' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}} m.unlock(); } -void testBlockInCriticalSectionWithPthreadMutex() { - pthread_mutex_lock(); +void testBlockInCriticalSectionWithPthreadMutex(pthread_mutex_t *mutex) { + pthread_mutex_lock(mutex); // expected-note 5{{Entering critical section here}} sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} - getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}} - fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} - read(); // expected-warning {{Call to blocking function 'read' inside of critical section}} - recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}} - pthread_mutex_unlock(); + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} + getc(stream); // expected-warning {{Call to blocking function 'getc' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}} + fgets(str, stream); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}} + read(fd, buf, count); // expected-warning {{Call to blocking function 'read' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'read' inside of critical section}} + recv(sockfd, buf, count, flags); // expected-warning {{Call to blocking function 'recv' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}} + pthread_mutex_unlock(mutex); - pthread_mutex_trylock(); + pthread_mutex_trylock(mutex); // expected-note 5{{Entering critical section here}} sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} - getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}} - fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} - read(); // expected-warning {{Call to blocking function 'read' inside of critical section}} - recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}} - pthread_mutex_unlock(); + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} + getc(stream); // expected-warning {{Call to blocking function 'getc' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}} + fgets(str, stream); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}} + read(fd, buf, count); // expected-warning {{Call to blocking function 'read' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'read' inside of critical section}} + recv(sockfd, buf, count, flags); // expected-warning {{Call to blocking function 'recv' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}} + pthread_mutex_unlock(mutex); } -void testBlockInCriticalSectionC11Locks() { - mtx_lock(); +void testBlockInCriticalSectionC11Locks(mtx_t *mutex) { + mtx_lock(mutex); // expected-note 5{{Entering critical section here}} sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} - getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}} - fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} - read(); // expected-warning {{Call to blocking function 'read' inside of critical section}} - recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}} - mtx_unlock(); + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} + getc(stream); // expected-warning {{Call to blocking function 'getc' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}} + fgets(str, stream); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}} + read(fd, buf, count); // expected-warning {{Call to blocking function 'read' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'read' inside of critical section}} + recv(sockfd, buf, count, flags); // expected-warning {{Call to blocking function 'recv' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}} + mtx_unlock(mutex); - mtx_timedlock(); + mtx_timedlock(mutex); // expected-note 5{{Entering critical section here}} sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} - getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}} - fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} - read(); // expected-warning {{Call to blocking function 'read' inside of critical section}} - recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}} - mtx_unlock(); + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} + getc(stream); // expected-warning {{Call to blocking function 'getc' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}} + fgets(str, stream); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}} + read(fd, buf, count); // expected-warning {{Call to blocking function 'read' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'read' inside of critical section}} + recv(sockfd, buf, count, flags); // expected-warning {{Call to blocking function 'recv' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}} + mtx_unlock(mutex); - mtx_trylock(); + mtx_trylock(mutex); // expected-note 5{{Entering critical section here}} sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} - getc(); // expected-warning {{Call to blocking function 'getc' inside of critical section}} - fgets(); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} - read(); // expected-warning {{Call to blocking function 'read' inside of critical section}} - recv(); // expected-warning {{Call to blocking function 'recv' inside of critical section}} - mtx_unlock(); + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} + getc(stream); // expected-warning {{Call to blocking function 'getc' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'getc' inside of critical section}} + fgets(str, stream); // expected-warning {{Call to blocking function 'fgets' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'fgets' inside of critical section}} + read(fd, buf, count); // expected-warning {{Call to blocking function 'read' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'read' inside of critical section}} + recv(sockfd, buf, count, flags); // expected-warning {{Call to blocking function 'recv' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'recv' inside of critical section}} + mtx_unlock(mutex); +} + +void testMultipleBlockingCalls() { + std::mutex m; + m.lock(); // expected-note 1{{Entering critical section here}} + sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} + m.unlock(); + sleep(2); // no-warning } -void testBlockInCriticalSectionWithNestedMutexes() { +void testMultipleMutexesMultipleBlockingCalls() { std::mutex m, n, k; - m.lock(); - n.lock(); - k.lock(); - sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + m.lock(); // expected-note 2{{Entering critical section here}} + n.lock(); // expected-note 2{{Entering critical section here}} + k.lock(); // expected-note 1{{Entering critical section here}} + sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} k.unlock(); - sleep(5); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + sleep(2); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} +} + + +void testRecursiveAcquisition() { + std::mutex m; + m.lock(); // expected-note {{Entering critical section for the 1st time here}} + m.lock(); // expected-note {{Entering critical section for the 2nd time here}} + sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} + m.unlock(); + m.unlock(); +} + +void testRecursiveAcquisitionWithMultipleBlockingCalls() { + std::mutex m; + m.lock(); // expected-note 1{{Entering critical section for the 1st time here}} + // expected-note@-1 {{Entering critical section here}} + m.lock(); // expected-note 1{{Entering critical section for the 2nd time here}} + sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} + m.unlock(); + // this next 'sleep' call is only in the critical section of the first lock + sleep(2); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} + m.unlock(); +} + +void testRecursiveAcquisitionWithMultipleMutexes() { + std::mutex m, n; + m.lock(); // expected-note 1{{Entering critical section here}} + n.lock(); // expected-note 2{{Entering critical section here}} + sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} + m.unlock(); + // this next 'sleep' call is only in the critical section of mutex 'n' + sleep(2); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} + n.unlock(); +} + + +void testNestedMutexes() { + std::mutex m, n, k; + m.lock(); // expected-note 3{{Entering critical section here}} + n.lock(); // expected-note 2{{Entering critical section here}} + k.lock(); // expected-note 1{{Entering critical section here}} + sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} + k.unlock(); + sleep(2); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} n.unlock(); sleep(3); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} + m.unlock(); + sleep(4); // no-warning +} + +void testNonOverlappingMutexes() { + std::mutex m; + m.lock(); // There should be no warning here + m.unlock(); + m.lock(); // expected-note {{Entering critical section here}} + sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} + m.unlock(); +} + +void testMixedMutexLocksWithIntermittentUnlock() { + std::mutex m, n, k; + m.lock(); // expected-note {{Entering critical section here}} + n.lock(); // the problem is not is this lock's critical section + n.unlock(); + k.lock(); // same as for n.lock() + k.unlock(); + sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} m.unlock(); - sleep(3); // no-warning } void f() { sleep(1000); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} } void testBlockInCriticalSectionInterProcedural() { std::mutex m; - m.lock(); - f(); + m.lock(); // expected-note {{Entering critical section here}} + f(); // expected-note {{Calling 'f'}} m.unlock(); } +void unknown_function_that_may_lock(std::mutex &); void testBlockInCriticalSectionUnexpectedUnlock() { std::mutex m; + unknown_function_that_may_lock(m); m.unlock(); sleep(1); // no-warning - m.lock(); - sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + m.lock(); // expected-note {{Entering critical section here}} + sleep(2); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} } void testBlockInCriticalSectionLockGuard() { @@ -130,12 +268,13 @@ void testBlockInCriticalSectionLockGuard() { std::not_real_lock<std::mutex> not_real_lock(g_mutex); sleep(1); // no-warning - std::lock_guard<std::mutex> lock(g_mutex); + std::lock_guard<std::mutex> lock(g_mutex); // expected-note {{Entering critical section here}} sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} } void testBlockInCriticalSectionLockGuardNested() { - testBlockInCriticalSectionLockGuard(); + testBlockInCriticalSectionLockGuard(); // expected-note {{Calling 'testBlockInCriticalSectionLockGuard'}} sleep(1); // no-warning } @@ -144,11 +283,12 @@ void testBlockInCriticalSectionUniqueLock() { std::not_real_lock<std::mutex> not_real_lock(g_mutex); sleep(1); // no-warning - std::unique_lock<std::mutex> lock(g_mutex); + std::unique_lock<std::mutex> lock(g_mutex); // expected-note {{Entering critical section here}} sleep(1); // expected-warning {{Call to blocking function 'sleep' inside of critical section}} + // expected-note@-1 {{Call to blocking function 'sleep' inside of critical section}} } void testBlockInCriticalSectionUniqueLockNested() { - testBlockInCriticalSectionUniqueLock(); + testBlockInCriticalSectionUniqueLock(); // expected-note {{Calling 'testBlockInCriticalSectionUniqueLock'}} sleep(1); // no-warning } diff --git a/clang/test/Analysis/cxx23-static-operator.cpp b/clang/test/Analysis/cxx23-static-operator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f380bd0dfa42819cac6d349b1851aefbb4f93b62 --- /dev/null +++ b/clang/test/Analysis/cxx23-static-operator.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_analyze_cc1 -std=c++2b -verify %s \ +// RUN: -analyzer-checker=core,debug.ExprInspection + +template <typename T> void clang_analyzer_dump(T); + +struct Adder { + int data; + static int operator()(int x, int y) { + clang_analyzer_dump(x); // expected-warning {{1}} + clang_analyzer_dump(y); // expected-warning {{2}} + return x + y; + } +}; + +void static_operator_call_inlines() { + Adder s{10}; + clang_analyzer_dump(s(1, 2)); // expected-warning {{3}} +} + +struct DataWithCtor { + int x; + int y; + DataWithCtor(int parm) : x(parm + 10), y(parm + 20) { + clang_analyzer_dump(this); // expected-warning {{&v}} + } +}; + +struct StaticSubscript { + static void operator[](DataWithCtor v) { + clang_analyzer_dump(v.x); // expected-warning {{20}} + clang_analyzer_dump(v.y); // expected-warning {{30}} + } +}; + +void top() { + StaticSubscript s; + s[DataWithCtor{10}]; +} diff --git a/clang/test/Analysis/eval-predefined-exprs.cpp b/clang/test/Analysis/eval-predefined-exprs.cpp index 1eec4476a065f31975a420fea87d6ca7733894e8..b26091869cd03f664b08d9dbb2c818db47d24700 100644 --- a/clang/test/Analysis/eval-predefined-exprs.cpp +++ b/clang/test/Analysis/eval-predefined-exprs.cpp @@ -52,12 +52,13 @@ void foo() { struct A { A() { - clang_analyzer_dump(__func__); - clang_analyzer_dump(__FUNCTION__); - clang_analyzer_dump(__PRETTY_FUNCTION__); - // expected-warning@-3 {{&Element{"A",0 S64b,char}}} - // expected-warning@-3 {{&Element{"A",0 S64b,char}}} - // expected-warning@-3 {{&Element{"A::A()",0 S64b,char}}} + clang_analyzer_dump(__func__); // expected-warning {{&Element{"A",0 S64b,char}}} +#ifdef ANALYZER_MS + clang_analyzer_dump(__FUNCTION__); // expected-warning {{&Element{"A::A",0 S64b,char}}} +#else + clang_analyzer_dump(__FUNCTION__); // expected-warning {{&Element{"A",0 S64b,char}}} +#endif + clang_analyzer_dump(__PRETTY_FUNCTION__); // expected-warning {{&Element{"A::A()",0 S64b,char}}} #ifdef ANALYZER_MS clang_analyzer_dump(__FUNCDNAME__); @@ -71,12 +72,13 @@ struct A { #endif } ~A() { - clang_analyzer_dump(__func__); - clang_analyzer_dump(__FUNCTION__); - clang_analyzer_dump(__PRETTY_FUNCTION__); - // expected-warning@-3 {{&Element{"~A",0 S64b,char}}} - // expected-warning@-3 {{&Element{"~A",0 S64b,char}}} - // expected-warning@-3 {{&Element{"A::~A()",0 S64b,char}}} + clang_analyzer_dump(__func__); // expected-warning {{&Element{"~A",0 S64b,char}}} +#ifdef ANALYZER_MS + clang_analyzer_dump(__FUNCTION__); // expected-warning {{&Element{"A::~A",0 S64b,char}}} +#else + clang_analyzer_dump(__FUNCTION__); // expected-warning {{&Element{"~A",0 S64b,char}}} +#endif + clang_analyzer_dump(__PRETTY_FUNCTION__); // expected-warning {{&Element{"A::~A()",0 S64b,char}}} #ifdef ANALYZER_MS clang_analyzer_dump(__FUNCDNAME__); diff --git a/clang/test/Analysis/getline-cpp.cpp b/clang/test/Analysis/getline-cpp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ef9d3186009c7fa4920368f7ab27910562d71acf --- /dev/null +++ b/clang/test/Analysis/getline-cpp.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix,debug.ExprInspection -verify %s + +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix,alpha.unix,debug.ExprInspection -verify %s +// +// expected-no-diagnostics + +#include "Inputs/system-header-simulator-cxx.h" + +void test_std_getline() { + std::string userid, comment; + // MallocChecker should not confuse the POSIX function getline() and the + // unrelated C++ standard library function std::getline. + std::getline(std::cin, userid, ' '); // no-crash + std::getline(std::cin, comment); // no-crash +} diff --git a/clang/test/Analysis/getline-unixapi.c b/clang/test/Analysis/getline-unixapi.c new file mode 100644 index 0000000000000000000000000000000000000000..86635ed8499793ccf897696e713b7193a1d69b7a --- /dev/null +++ b/clang/test/Analysis/getline-unixapi.c @@ -0,0 +1,322 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix,debug.ExprInspection -verify %s + +#include "Inputs/system-header-simulator.h" +#include "Inputs/system-header-simulator-for-malloc.h" +#include "Inputs/system-header-simulator-for-valist.h" + +void clang_analyzer_eval(int); +void clang_analyzer_dump_int(int); +void clang_analyzer_dump_ptr(void*); +void clang_analyzer_warnIfReached(); + +void test_getline_null_lineptr() { + FILE *F1 = tmpfile(); + if (!F1) + return; + + char **buffer = NULL; + size_t n = 0; + getline(buffer, &n, F1); // expected-warning {{Line pointer might be NULL}} + fclose(F1); +} + +void test_getline_null_size() { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + getline(&buffer, NULL, F1); // expected-warning {{Size pointer might be NULL}} + fclose(F1); +} + +void test_getline_null_buffer_size_gt0() { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + size_t n = 8; + getline(&buffer, &n, F1); // ok since posix 2018 + free(buffer); + fclose(F1); +} + +void test_getline_null_buffer_size_gt0_2(size_t n) { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + if (n > 0) { + getline(&buffer, &n, F1); // ok since posix 2018 + } + free(buffer); + fclose(F1); +} + +void test_getline_null_buffer_unknown_size(size_t n) { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + + getline(&buffer, &n, F1); // ok + fclose(F1); + free(buffer); +} + +void test_getline_null_buffer_undef_size() { + FILE *F1 = tmpfile(); + if (!F1) + return; + + char *buffer = NULL; + size_t n; + + getline(&buffer, &n, F1); // ok since posix 2018 + fclose(F1); + free(buffer); +} + +void test_getline_buffer_size_0() { + FILE *F1 = tmpfile(); + if (!F1) + return; + + char *buffer = malloc(10); + size_t n = 0; + if (buffer != NULL) + getline(&buffer, &n, F1); // ok, the buffer is enough for 0 character + fclose(F1); + free(buffer); +} + +void test_getline_buffer_bad_size() { + FILE *F1 = tmpfile(); + if (!F1) + return; + + char *buffer = malloc(10); + size_t n = 100; + if (buffer != NULL) + getline(&buffer, &n, F1); // expected-warning {{The buffer from the first argument is smaller than the size specified by the second parameter}} + fclose(F1); + free(buffer); +} + +void test_getline_buffer_smaller_size() { + FILE *F1 = tmpfile(); + if (!F1) + return; + + char *buffer = malloc(100); + size_t n = 10; + if (buffer != NULL) + getline(&buffer, &n, F1); // ok, there is enough space for 10 characters + fclose(F1); + free(buffer); +} + +void test_getline_buffer_undef_size() { + FILE *F1 = tmpfile(); + if (!F1) + return; + + char *buffer = malloc(100); + size_t n; + if (buffer != NULL) + getline(&buffer, &n, F1); // expected-warning {{The buffer from the first argument is not NULL, but the size specified by the second parameter is undefined}} + fclose(F1); + free(buffer); +} + + +void test_getline_null_buffer() { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + size_t n = 0; + ssize_t r = getline(&buffer, &n, F1); + // getline returns -1 on failure, number of char reads on success (>= 0) + if (r < -1) { + clang_analyzer_warnIfReached(); // must not happen + } else { + // The buffer could be allocated both on failure and success + clang_analyzer_dump_int(n); // expected-warning {{conj_$}} + clang_analyzer_dump_ptr(buffer); // expected-warning {{conj_$}} + } + free(buffer); + fclose(F1); +} + +void test_getdelim_null_size() { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + getdelim(&buffer, NULL, ',', F1); // expected-warning {{Size pointer might be NULL}} + fclose(F1); +} + +void test_getdelim_null_buffer_size_gt0() { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + size_t n = 8; + getdelim(&buffer, &n, ';', F1); // ok since posix 2018 + free(buffer); + fclose(F1); +} + +void test_getdelim_null_buffer_size_gt0_2(size_t n) { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + if (n > 0) { + getdelim(&buffer, &n, ' ', F1); // ok since posix 2018 + } + free(buffer); + fclose(F1); +} + +void test_getdelim_null_buffer_unknown_size(size_t n) { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + getdelim(&buffer, &n, '-', F1); // ok + fclose(F1); + free(buffer); +} + +void test_getdelim_null_buffer() { + FILE *F1 = tmpfile(); + if (!F1) + return; + char *buffer = NULL; + size_t n = 0; + ssize_t r = getdelim(&buffer, &n, '\r', F1); + // getdelim returns -1 on failure, number of char reads on success (>= 0) + if (r < -1) { + clang_analyzer_warnIfReached(); // must not happen + } + else { + // The buffer could be allocated both on failure and success + clang_analyzer_dump_int(n); // expected-warning {{conj_$}} + clang_analyzer_dump_ptr(buffer); // expected-warning {{conj_$}} + } + free(buffer); + fclose(F1); +} + +void test_getline_while() { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + char *line = NULL; + size_t len = 0; + ssize_t read; + + while ((read = getline(&line, &len, file)) != -1) { + printf("%s\n", line); + } + + free(line); + fclose(file); +} + +void test_getline_return_check() { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + char *line = NULL; + size_t len = 0; + ssize_t r = getline(&line, &len, file); + + if (r != -1) { + if (line[0] == '\0') {} // ok + } + free(line); + fclose(file); +} + +void test_getline_clear_eof() { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + size_t n = 10; + char *buffer = malloc(n); + ssize_t read = fread(buffer, n, 1, file); + if (feof(file)) { + clearerr(file); + getline(&buffer, &n, file); // ok + } + fclose(file); + free(buffer); +} + +void test_getline_not_null(char **buffer, size_t *size) { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + getline(buffer, size, file); + fclose(file); + + if (size == NULL || buffer == NULL) { + clang_analyzer_warnIfReached(); // must not happen + } +} + +void test_getline_size_constraint(size_t size) { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + size_t old_size = size; + char *buffer = malloc(10); + if (buffer != NULL) { + ssize_t r = getline(&buffer, &size, file); + if (r >= 0) { + // Since buffer has a size of 10, old_size must be less than or equal to 10. + // Otherwise, there would be UB. + clang_analyzer_eval(old_size <= 10); // expected-warning{{TRUE}} + } + } + fclose(file); + free(buffer); +} + +void test_getline_negative_buffer() { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + char *buffer = NULL; + size_t n = -1; + getline(&buffer, &n, file); // ok since posix 2018 + free(buffer); + fclose(file); +} + +void test_getline_negative_buffer_2(char *buffer) { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + size_t n = -1; + (void)getline(&buffer, &n, file); // ok + free(buffer); + fclose(file); +} diff --git a/clang/test/Analysis/inlining/false-positive-suppression.cpp b/clang/test/Analysis/inlining/false-positive-suppression.cpp index 56659b4a1941cc9ed64edb350d91735aa7df9cb6..2f9ed7f78b3f0786b912f5dff662bc87341d2d3f 100644 --- a/clang/test/Analysis/inlining/false-positive-suppression.cpp +++ b/clang/test/Analysis/inlining/false-positive-suppression.cpp @@ -210,3 +210,20 @@ namespace Cleanups { testArgumentHelper(NonTrivial().getNull()); } } + +class Bear *getNullBear() { return nullptr; } +class Bear { +public: + void brum() const; +}; +class Door { +public: + Door() : ptr(getNullBear()) { + ptr->brum(); +#ifndef SUPPRESSED + // expected-warning@-2 {{Called C++ object pointer is null}} +#endif + } +private: + Bear* ptr; +}; diff --git a/clang/test/Analysis/loop-unrolling.cpp b/clang/test/Analysis/loop-unrolling.cpp index fc1fb06cdc014ef57e5f9ef85aa142091a5c8a06..66a828abfb5133924015e7bd2c6e19a39fff49d0 100644 --- a/clang/test/Analysis/loop-unrolling.cpp +++ b/clang/test/Analysis/loop-unrolling.cpp @@ -547,3 +547,15 @@ void capture_implicitly_by_ref_as_loop_counter() { } }; } + + +void test_escaping_on_var_before_switch_case_no_crash(int c) { + // https://github.com/llvm/llvm-project/issues/68819 + switch (c) { + int i; // no-crash: The declaration of `i` is found here. + case 0: { + for (i = 0; i < 16; i++) {} + break; + } + } +} diff --git a/clang/test/Analysis/out-of-bounds-diagnostics.c b/clang/test/Analysis/out-of-bounds-diagnostics.c index 0c3c67c6a546ad20c8abd845f9173bcf321b9497..92f983d8b1561290094258aff1dd50a1fda61775 100644 --- a/clang/test/Analysis/out-of-bounds-diagnostics.c +++ b/clang/test/Analysis/out-of-bounds-diagnostics.c @@ -24,6 +24,33 @@ void taintedIndex(void) { scanf("%d", &index); // expected-note@-1 {{Taint originated here}} // expected-note@-2 {{Taint propagated to the 2nd argument}} + TenElements[index] = 5; + // expected-warning@-1 {{Potential out of bound access to 'TenElements' with tainted index}} + // expected-note@-2 {{Access of 'TenElements' with a tainted index that may be negative or too large}} +} + +void taintedIndexNonneg(void) { + int index; + scanf("%d", &index); + // expected-note@-1 {{Taint originated here}} + // expected-note@-2 {{Taint propagated to the 2nd argument}} + + // expected-note@+2 {{Assuming 'index' is >= 0}} + // expected-note@+1 {{Taking false branch}} + if (index < 0) + return; + + TenElements[index] = 5; + // expected-warning@-1 {{Potential out of bound access to 'TenElements' with tainted index}} + // expected-note@-2 {{Access of 'TenElements' with a tainted index that may be too large}} +} + +void taintedIndexUnsigned(void) { + unsigned index; + scanf("%u", &index); + // expected-note@-1 {{Taint originated here}} + // expected-note@-2 {{Taint propagated to the 2nd argument}} + TenElements[index] = 5; // expected-warning@-1 {{Potential out of bound access to 'TenElements' with tainted index}} // expected-note@-2 {{Access of 'TenElements' with a tainted index that may be too large}} @@ -59,7 +86,7 @@ void taintedOffset(void) { int *p = TenElements + index; p[0] = 5; // expected-warning@-1 {{Potential out of bound access to 'TenElements' with tainted offset}} - // expected-note@-2 {{Access of 'TenElements' with a tainted offset that may be too large}} + // expected-note@-2 {{Access of 'TenElements' with a tainted offset that may be negative or too large}} } void arrayOverflow(void) { @@ -109,6 +136,33 @@ int *potentialAfterTheEndPtr(int idx) { // &TenElements[idx]. } +int overflowOrUnderflow(int arg) { + // expected-note@+2 {{Assuming 'arg' is < 0}} + // expected-note@+1 {{Taking false branch}} + if (arg >= 0) + return 0; + + return TenElements[arg - 1]; + // expected-warning@-1 {{Out of bound access to memory around 'TenElements'}} + // expected-note@-2 {{Access of 'TenElements' at a negative or overflowing index, while it holds only 10 'int' elements}} +} + +char TwoElements[2] = {11, 22}; +char overflowOrUnderflowConcrete(int arg) { + // expected-note@#cond {{Assuming 'arg' is < 3}} + // expected-note@#cond {{Left side of '||' is false}} + // expected-note@#cond {{Assuming 'arg' is not equal to 0}} + // expected-note@#cond {{Left side of '||' is false}} + // expected-note@#cond {{Assuming 'arg' is not equal to 1}} + // expected-note@#cond {{Taking false branch}} + if (arg >= 3 || arg == 0 || arg == 1) // #cond + return 0; + + return TwoElements[arg]; + // expected-warning@-1 {{Out of bound access to memory around 'TwoElements'}} + // expected-note@-2 {{Access of 'TwoElements' at a negative or overflowing index, while it holds only 2 'char' elements}} +} + int scalar; int scalarOverflow(void) { return (&scalar)[1]; diff --git a/clang/test/Analysis/stream-error.c b/clang/test/Analysis/stream-error.c index 88f7de4234ffb4689a7e298e4f22dc8766b80887..7f9116ff401445b5917b0c6e18576e28be6cd96c 100644 --- a/clang/test/Analysis/stream-error.c +++ b/clang/test/Analysis/stream-error.c @@ -365,27 +365,22 @@ void error_fseek(void) { return; int rc = fseek(F, 1, SEEK_SET); if (rc) { + clang_analyzer_eval(rc == -1); // expected-warning {{TRUE}} int IsFEof = feof(F), IsFError = ferror(F); - // Get feof or ferror or no error. - clang_analyzer_eval(IsFEof || IsFError); - // expected-warning@-1 {{FALSE}} - // expected-warning@-2 {{TRUE}} - clang_analyzer_eval(IsFEof && IsFError); // expected-warning {{FALSE}} + // Get ferror or no error. + clang_analyzer_eval(IsFError); // expected-warning {{FALSE}} \ + // expected-warning {{TRUE}} + clang_analyzer_eval(IsFEof); // expected-warning {{FALSE}} // Error flags should not change. - if (IsFEof) - clang_analyzer_eval(feof(F)); // expected-warning {{TRUE}} - else - clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} if (IsFError) - clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} - else - clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}} } else { - clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} - clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} // Error flags should not change. - clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} - clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} } fclose(F); } @@ -396,15 +391,13 @@ void error_fseeko(void) { return; int rc = fseeko(F, 1, SEEK_SET); if (rc) { - int IsFEof = feof(F), IsFError = ferror(F); - // Get feof or ferror or no error. - clang_analyzer_eval(IsFEof || IsFError); - // expected-warning@-1 {{FALSE}} - // expected-warning@-2 {{TRUE}} - clang_analyzer_eval(IsFEof && IsFError); // expected-warning {{FALSE}} + // Get ferror or no error. + clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} \ + // expected-warning {{TRUE}} + clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} } else { - clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} - clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(feof(F)); // expected-warning {{FALSE}} + clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}} } fclose(F); } @@ -414,7 +407,7 @@ void error_fseek_0(void) { if (!F) return; int rc = fseek(F, 0, SEEK_SET); - if (rc) { + if (rc == -1) { int IsFEof = feof(F), IsFError = ferror(F); // Get ferror or no error, but not feof. clang_analyzer_eval(IsFError); diff --git a/clang/test/Analysis/stream-note.c b/clang/test/Analysis/stream-note.c index f77cd4aa62841dda006d01c13f7ca1a622deb567..54ea699f46674e93b4d94af2f7e693aec2ffbad4 100644 --- a/clang/test/Analysis/stream-note.c +++ b/clang/test/Analysis/stream-note.c @@ -226,10 +226,39 @@ void check_indeterminate_fseek(void) { return; int Ret = fseek(F, 1, SEEK_SET); // expected-note {{Assuming this stream operation fails}} if (Ret) { // expected-note {{Taking true branch}} \ - // expected-note {{'Ret' is not equal to 0}} + // expected-note {{'Ret' is -1}} char Buf[2]; fwrite(Buf, 1, 2, F); // expected-warning {{might be 'indeterminate'}} \ // expected-note {{might be 'indeterminate'}} } fclose(F); } + +void error_fseek_ftell(void) { + FILE *F = fopen("file", "r"); + if (!F) // expected-note {{Taking false branch}} \ + // expected-note {{'F' is non-null}} + return; + fseek(F, 0, SEEK_END); // expected-note {{Assuming this stream operation fails}} + long size = ftell(F); // expected-warning {{might be 'indeterminate'}} \ + // expected-note {{might be 'indeterminate'}} + if (size == -1) { + fclose(F); + return; + } + if (size == 1) + fprintf(F, "abcd"); + fclose(F); +} + +void error_fseek_read_eof(void) { + FILE *F = fopen("file", "r"); + if (!F) + return; + if (fseek(F, 22, SEEK_SET) == -1) { + fclose(F); + return; + } + fgetc(F); // no warning + fclose(F); +} diff --git a/clang/test/Analysis/stream.c b/clang/test/Analysis/stream.c index 7ba27740a93796a8e89066395a85a2bbb55afe7e..ba5e66a4102e3c869a601d66362dc7a718206ffc 100644 --- a/clang/test/Analysis/stream.c +++ b/clang/test/Analysis/stream.c @@ -4,6 +4,7 @@ // RUN: %clang_analyze_cc1 -triple=hexagon -analyzer-checker=core,alpha.unix.Stream,debug.ExprInspection -verify %s #include "Inputs/system-header-simulator.h" +#include "Inputs/system-header-simulator-for-malloc.h" #include "Inputs/system-header-simulator-for-valist.h" void clang_analyzer_eval(int); @@ -376,3 +377,75 @@ void fflush_on_open_failed_stream(void) { } fclose(F); } + +void getline_null_file() { + char *buffer = NULL; + size_t n = 0; + getline(&buffer, &n, NULL); // expected-warning {{Stream pointer might be NULL}} +} + +void getdelim_null_file() { + char *buffer = NULL; + size_t n = 0; + getdelim(&buffer, &n, '\n', NULL); // expected-warning {{Stream pointer might be NULL}} +} + +void getline_buffer_on_error() { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + char *line = NULL; + size_t len = 0; + if (getline(&line, &len, file) == -1) { + if (line[0] == '\0') {} // expected-warning {{The left operand of '==' is a garbage value}} + } else { + if (line[0] == '\0') {} // no warning + } + + free(line); + fclose(file); +} + +void getline_ret_value() { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + size_t n = 0; + char *buffer = NULL; + ssize_t r = getline(&buffer, &n, file); + + if (r > -1) { + // The return value does *not* include the terminating null byte. + // The buffer must be large enough to include it. + clang_analyzer_eval(n > r); // expected-warning{{TRUE}} + clang_analyzer_eval(buffer != NULL); // expected-warning{{TRUE}} + } + + fclose(file); + free(buffer); +} + + +void getline_buffer_size_negative() { + FILE *file = fopen("file.txt", "r"); + if (file == NULL) { + return; + } + + size_t n = -1; + clang_analyzer_eval((ssize_t)n >= 0); // expected-warning{{FALSE}} + char *buffer = NULL; + ssize_t r = getline(&buffer, &n, file); + + if (r > -1) { + clang_analyzer_eval((ssize_t)n > r); // expected-warning{{TRUE}} + clang_analyzer_eval(buffer != NULL); // expected-warning{{TRUE}} + } + + free(buffer); + fclose(file); +} diff --git a/clang/test/Analysis/taint-diagnostic-visitor.c b/clang/test/Analysis/taint-diagnostic-visitor.c index 020e9579ac535c2442eea7b8ecd2758e4077d86f..2ba7d9938fc3d86c9b0a6ec3f3ccc1cd0c6a3943 100644 --- a/clang/test/Analysis/taint-diagnostic-visitor.c +++ b/clang/test/Analysis/taint-diagnostic-visitor.c @@ -30,7 +30,7 @@ int taintDiagnosticOutOfBound(void) { scanf("%d", &index); // expected-note {{Taint originated here}} // expected-note@-1 {{Taint propagated to the 2nd argument}} return Array[index]; // expected-warning {{Potential out of bound access to 'Array' with tainted index}} - // expected-note@-1 {{Access of 'Array' with a tainted index that may be too large}} + // expected-note@-1 {{Access of 'Array' with a tainted index}} } int taintDiagnosticDivZero(int operand) { diff --git a/clang/test/C/C11/n1282.c b/clang/test/C/C11/n1282.c new file mode 100644 index 0000000000000000000000000000000000000000..ed952790c883338fdf4479e9d127c91e856c0ba9 --- /dev/null +++ b/clang/test/C/C11/n1282.c @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify -Wunsequenced -Wno-unused-value %s + +/* WG14 N1282: Yes + * Clarification of Expressions + */ + +int g; + +int f(int i) { + g = i; + return 0; +} + +int main(void) { + int x; + x = (10, g = 1, 20) + (30, g = 2, 40); /* Line A */ // expected-warning {{multiple unsequenced modifications to 'g'}} + x = (10, f(1), 20) + (30, f(2), 40); /* Line B */ + x = (g = 1) + (g = 2); /* Line C */ // expected-warning {{multiple unsequenced modifications to 'g'}} + return 0; +} diff --git a/clang/test/C/C11/n1310.c b/clang/test/C/C11/n1310.c new file mode 100644 index 0000000000000000000000000000000000000000..7f8dd754f74631eef9cd82f9206cb5249e2c46d0 --- /dev/null +++ b/clang/test/C/C11/n1310.c @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -verify -std=c89 %s +// RUN: %clang_cc1 -verify -std=c99 %s +// RUN: %clang_cc1 -verify -std=c11 %s +// RUN: %clang_cc1 -verify -std=c17 %s +// RUN: %clang_cc1 -verify -std=c23 %s +// expected-no-diagnostics + +/* WG14 N1310: Yes + * Requiring signed char to have no padding bits + */ + +/* This is shockingly hard to test, but we're trying our best by checking that + * setting each bit of an unsigned char, then bit-casting it to signed char, + * results in a value we expect to see. If we have padding bits, then it's + * possible (but not mandatory) for the value to not be as we expect, so a + * failing assertion means the implementation is broken but a passing test does + * not *prove* there aren't padding bits. + */ +_Static_assert(__CHAR_BIT__ == 8, ""); +_Static_assert(sizeof(signed char) == 1, ""); + +#define TEST(Bit, Expected) __builtin_bit_cast(signed char, (unsigned char)(1 << Bit)) == Expected +_Static_assert(TEST(0, 1), ""); +_Static_assert(TEST(1, 2), ""); +_Static_assert(TEST(2, 4), ""); +_Static_assert(TEST(3, 8), ""); +_Static_assert(TEST(4, 16), ""); +_Static_assert(TEST(5, 32), ""); +_Static_assert(TEST(6, 64), ""); +_Static_assert(TEST(7, (signed char)128), ""); + diff --git a/clang/test/C/C11/n1365.c b/clang/test/C/C11/n1365.c new file mode 100644 index 0000000000000000000000000000000000000000..d60bb546b29a71d34da9d2830c15a5cfbf9bfe91 --- /dev/null +++ b/clang/test/C/C11/n1365.c @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -ast-dump %s | FileCheck %s + +/* WG14 N1365: Clang 16 + * Constant expressions + */ + +// Note: we don't allow you to expand __FLT_EVAL_METHOD__ in the presence of a +// pragma that changes its value. However, we can test that we have the correct +// constant expression behavior by testing that the AST has the correct implicit +// casts, which also specify that the cast was inserted due to an evaluation +// method requirement. +void func(void) { + { + #pragma clang fp eval_method(double) + _Static_assert(123.0F * 2.0F == 246.0F, ""); + // CHECK: StaticAssertDecl + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Bool' <IntegralToBoolean> + // CHECK-NEXT: BinaryOperator {{.*}} 'int' '==' + // CHECK-NEXT: BinaryOperator {{.*}} 'double' '*' FPEvalMethod=1 + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' <FloatingCast> FPEvalMethod=1 + // CHECK-NEXT: FloatingLiteral + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' <FloatingCast> FPEvalMethod=1 + // CHECK-NEXT: FloatingLiteral + + // Ensure that a cast removes the extra precision. + _Static_assert(123.0F * 2.0F == 246.0F, ""); + // CHECK: StaticAssertDecl + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Bool' <IntegralToBoolean> + // CHECK-NEXT: BinaryOperator {{.*}} 'int' '==' + // CHECK-NEXT: BinaryOperator {{.*}} 'double' '*' FPEvalMethod=1 + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' <FloatingCast> FPEvalMethod=1 + // CHECK-NEXT: FloatingLiteral + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' <FloatingCast> FPEvalMethod=1 + // CHECK-NEXT: FloatingLiteral + } + + { + #pragma clang fp eval_method(extended) + _Static_assert(123.0F * 2.0F == 246.0F, ""); + // CHECK: StaticAssertDecl + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Bool' <IntegralToBoolean> + // CHECK-NEXT: BinaryOperator {{.*}} 'int' '==' + // CHECK-NEXT: BinaryOperator {{.*}} 'long double' '*' FPEvalMethod=2 + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'long double' <FloatingCast> FPEvalMethod=2 + // CHECK-NEXT: FloatingLiteral + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'long double' <FloatingCast> FPEvalMethod=2 + // CHECK-NEXT: FloatingLiteral + } + + { + #pragma clang fp eval_method(source) + _Static_assert(123.0F * 2.0F == 246.0F, ""); + // CHECK: StaticAssertDecl + // CHECK-NEXT: ImplicitCastExpr {{.*}} '_Bool' <IntegralToBoolean> + // CHECK-NEXT: BinaryOperator {{.*}} 'int' '==' + // CHECK-NEXT: BinaryOperator {{.*}} 'float' '*' FPEvalMethod=0 + // CHECK-NEXT: FloatingLiteral + // CHECK-NEXT: FloatingLiteral + } +} diff --git a/clang/test/C/C11/n1482.c b/clang/test/C/C11/n1482.c new file mode 100644 index 0000000000000000000000000000000000000000..493c7d0a18f109d2d204bd7ee0f8b589a98eebeb --- /dev/null +++ b/clang/test/C/C11/n1482.c @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 -verify -ffreestanding -std=c11 %s +// expected-no-diagnostics + +/* WG14 N1482: Clang 4 + * Explicit initializers for atomics + * + * NB: We can only test the compile time behavior from the paper, not the + * runtime behavior. + */ + +#include <stdatomic.h> + +#ifndef ATOMIC_BOOL_LOCK_FREE +#error "Missing ATOMIC_BOOL_LOCK_FREE" +#endif + +#ifndef ATOMIC_CHAR_LOCK_FREE +#error "Missing ATOMIC_CHAR_LOCK_FREE" +#endif + +#ifndef ATOMIC_CHAR16_T_LOCK_FREE +#error "Missing ATOMIC_CHAR16_T_LOCK_FREE" +#endif + +#ifndef ATOMIC_CHAR32_T_LOCK_FREE +#error "Missing ATOMIC_CHAR32_T_LOCK_FREE" +#endif + +#ifndef ATOMIC_WCHAR_T_LOCK_FREE +#error "Missing ATOMIC_WCHAR_T_LOCK_FREE" +#endif + +#ifndef ATOMIC_SHORT_LOCK_FREE +#error "Missing ATOMIC_SHORT_LOCK_FREE" +#endif + +#ifndef ATOMIC_INT_LOCK_FREE +#error "Missing ATOMIC_INT_LOCK_FREE" +#endif + +#ifndef ATOMIC_LONG_LOCK_FREE +#error "Missing ATOMIC_LONG_LOCK_FREE" +#endif + +#ifndef ATOMIC_LLONG_LOCK_FREE +#error "Missing ATOMIC_LLONG_LOCK_FREE" +#endif + +#ifndef ATOMIC_POINTER_LOCK_FREE +#error "Missing ATOMIC_POINTER_LOCK_FREE" +#endif + +#ifndef ATOMIC_VAR_INIT +#error "Missing ATOMIC_VAR_INIT" +#endif + +#ifndef atomic_init +#error "Missing atomic_init" +#endif diff --git a/clang/test/C/C2x/n2350.c b/clang/test/C/C2x/n2350.c index 2f738488a374270700ceeb9afb5e635ac6579b49..af0ca6d79be5e18315cad84a71e894d657249b41 100644 --- a/clang/test/C/C2x/n2350.c +++ b/clang/test/C/C2x/n2350.c @@ -5,7 +5,7 @@ // RUN: %clang_cc1 -fsyntax-only -pedantic -Wno-comment -std=c99 -verify %s // RUN: %clang_cc1 -fsyntax-only -pedantic -Wno-comment -std=c11 -verify %s // RUN: %clang_cc1 -fsyntax-only -pedantic -Wno-comment -std=c17 -verify %s -// RUN: %clang_cc1 -fsyntax-only -pedantic -Wno-comment -std=c2x -verify %s +// RUN: %clang_cc1 -fsyntax-only -pedantic -Wno-comment -std=c2x -verify=silent %s // silent-no-diagnostics @@ -13,10 +13,10 @@ // https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm int simple(void) { return __builtin_offsetof(struct A // cpp-error {{'A' cannot be defined in a type specifier}} \ - expected-warning {{defining a type within '__builtin_offsetof' is a Clang extension}} + expected-warning {{defining a type within '__builtin_offsetof' is a C23 extension}} { int a; - struct B // expected-warning {{defining a type within '__builtin_offsetof' is a Clang extension}} + struct B // expected-warning {{defining a type within '__builtin_offsetof' is a C23 extension}} { int c; int d; @@ -26,7 +26,7 @@ int simple(void) { int anonymous_struct(void) { return __builtin_offsetof(struct // cpp-error-re {{'(unnamed struct at {{.*}})' cannot be defined in a type specifier}} \ - expected-warning {{defining a type within '__builtin_offsetof' is a Clang extension}} + expected-warning {{defining a type within '__builtin_offsetof' is a C23 extension}} { int a; int b; @@ -47,7 +47,7 @@ int struct_in_second_param(void) { int macro(void) { return offsetof(struct A // cpp-error {{'A' cannot be defined in a type specifier}} \ - expected-warning 2 {{defining a type within 'offsetof' is a Clang extension}} + expected-warning 2 {{defining a type within 'offsetof' is a C23 extension}} { int a; struct B // verifier seems to think the error is emitted by the macro diff --git a/clang/test/C/C2x/n2975.c b/clang/test/C/C2x/n2975.c index 5fc641dd66e781596511dc8293162c3744407654..2269400fe47c3456080e5f7b7ab0349b5963b7b8 100644 --- a/clang/test/C/C2x/n2975.c +++ b/clang/test/C/C2x/n2975.c @@ -11,7 +11,7 @@ void func(...) { // expected-warning {{'...' as the only parameter of a function is incompatible with C standards before C23}} // Show that va_start doesn't require the second argument in C23 mode. va_list list; - va_start(list); // FIXME: it would be nice to issue a portability warning to C17 and earlier here. + va_start(list); // expected-warning {{passing no argument for the '...' parameter of a variadic macro is incompatible with C standards before C23}} expected-note@* {{macro 'va_start' defined here}} va_end(list); // Show that va_start doesn't expand or evaluate the second argument. @@ -26,7 +26,7 @@ void func(...) { // expected-warning {{'...' as the only parameter of a function __builtin_va_start(list); // expected-error {{too few arguments to function call, expected 2, have 1}} // Verify that the return type of a call to va_start is 'void'. - _Static_assert(__builtin_types_compatible_p(__typeof__(va_start(list)), void), ""); + _Static_assert(__builtin_types_compatible_p(__typeof__(va_start(list)), void), ""); // expected-warning {{passing no argument for the '...' parameter of a variadic macro is incompatible with C standards before C23}} expected-note@* {{macro 'va_start' defined here}} _Static_assert(__builtin_types_compatible_p(__typeof__(__builtin_va_start(list, 0)), void), ""); } diff --git a/clang/test/C/C99/Inputs/nested-include.h b/clang/test/C/C99/Inputs/nested-include.h new file mode 100644 index 0000000000000000000000000000000000000000..0f64473c0faef539fde8ab39f0a5f25fe355c6ba --- /dev/null +++ b/clang/test/C/C99/Inputs/nested-include.h @@ -0,0 +1,3 @@ +#if __COUNTER__ < 15 +#include __FILE__ +#endif diff --git a/clang/test/C/C99/block-scopes.c b/clang/test/C/C99/block-scopes.c new file mode 100644 index 0000000000000000000000000000000000000000..589047df3e52bcbf135fde88c045231a032d6196 --- /dev/null +++ b/clang/test/C/C99/block-scopes.c @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c89 -verify %s +// RUN: %clang_cc1 -std=c99 -verify %s +// RUN: %clang_cc1 -std=c11 -verify %s +// RUN: %clang_cc1 -std=c17 -verify %s +// RUN: %clang_cc1 -std=c23 -verify %s + +// expected-no-diagnostics + +/* WG14 ???: yes + * new block scopes for selection and iteration statements + * + * This is referenced in the C99 front matter as new changes to C99, but it is + * not clear which document number introduced the changes. It's possible this + * is WG14 N759, based on discussion in the C99 rationale document that claims + * these changes were made in response to surprising issues with the lifetime + * of compound literals in compound statements vs non-compound statements. + */ + +enum {a, b}; +void different(void) { + if (sizeof(enum {b, a}) != sizeof(int)) + _Static_assert(a == 1, ""); + /* In C89, the 'b' found here would have been from the enum declaration in + * the controlling expression of the selection statement, not from the global + * declaration. In C99 and later, that enumeration is scoped to the 'if' + * statement and the global declaration is what's found. + */ + #if __STDC_VERSION__ >= 199901L + _Static_assert(b == 1, ""); + #else + _Static_assert(b == 0, ""); + #endif +} + diff --git a/clang/test/C/C99/digraphs.c b/clang/test/C/C99/digraphs.c new file mode 100644 index 0000000000000000000000000000000000000000..870a441118161af9d05f8b868d6555af52c57c08 --- /dev/null +++ b/clang/test/C/C99/digraphs.c @@ -0,0 +1,90 @@ +// RUN: %clang_cc1 -verify -ffreestanding %s + +/* WG14 ???: yes + * restricted character set support via digraphs and <iso646.h> + * + * NB: I cannot find a definitive document number associated with the feature, + * which was pulled from the editor's report in the C99 front matter. However, + * based on discussion in the C99 rationale document, I believe this is + * referring to features added by AMD1 to support ISO 646 and digraphs. + */ + +// Validate that we provide iso646.h in freestanding mode. +#include <iso646.h> + +// Validate that we define all the expected macros and their expected +// expansions (when suitable for a constant expression) as well. +#ifndef and +#error "missing and" +#else +_Static_assert((1 and 1) == (1 && 1), ""); +#endif + +#ifndef and_eq +#error "missing and_eq" +#endif + +#ifndef bitand +#error "missing bitand" +#else +_Static_assert((1 bitand 3) == (1 & 3), ""); +#endif + +#ifndef bitor +#error "missing bitor" +#else +_Static_assert((1 bitor 2) == (1 | 2), ""); +#endif + +#ifndef compl +#error "missing compl" +#else +_Static_assert((compl 0) == (~0), ""); +#endif + +#ifndef not +#error "missing not" +#else +_Static_assert((not 12) == (!12), ""); +#endif + +#ifndef not_eq +#error "missing not_eq" +#else +_Static_assert((0 not_eq 12) == (0 != 12), ""); +#endif + +#ifndef or +#error "missing or" +#else +// This intentionally diagnoses use of '||' only, because the user likely did +// not confuse the operator when using 'or' instead. +_Static_assert((0 or 12) == (0 || 12), ""); // expected-warning {{use of logical '||' with constant operand}} \ + expected-note {{use '|' for a bitwise operation}} +#endif + +#ifndef or_eq +#error "missing or_eq" +#endif + +#ifndef xor +#error "missing xor" +#else +_Static_assert((1 xor 3) == (1 ^ 3), ""); +#endif + +#ifndef xor_eq +#error "missing xor_eq" +#endif + +// Validate that digraphs behave the same as their expected counterparts. The +// definition should match the declaration in every way except spelling. +#define DI_NAME(f, b) f %:%: b +#define STD_NAME(f, b) f ## b +void DI_NAME(foo, bar)(int (*array)<: 0 :>); +void STD_NAME(foo, bar)(int (*array)[0]) {} + +#define DI_STR(f) %:f +#define STD_STR(f) #f +_Static_assert(__builtin_strcmp(DI_STR(testing), STD_STR(testing)) == 0, ""); + diff --git a/clang/test/C/C99/float_h-characteristics.c b/clang/test/C/C99/float_h-characteristics.c new file mode 100644 index 0000000000000000000000000000000000000000..7e2a891ef87774fbd9521d4489e93c941742907f --- /dev/null +++ b/clang/test/C/C99/float_h-characteristics.c @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -verify -std=c99 -ffreestanding %s +// RUN: %clang_cc1 -verify -std=gnu89 -ffreestanding %s +// RUN: %clang_cc1 -verify -std=c89 -ffreestanding %s +// expected-no-diagnostics + +/* WG14 ???: Clang 16 + * Additional floating-point characteristics in <float.h> + * + * NB: the original paper number is unknown, this was gleaned from the editor's + * report in the C99 foreword. There were two new additions to <float.h> in + * C99, this is testing that we support both of them. + * + * Clang added the macros at least as far back as Clang 3.0, but it wasn't + * until Clang 16.0 that we stopped accidentally providing FLT_EVAL_METHOD in + * C89 (strict) mode. + */ + +#include <float.h> + +// We expect all the definitions in C99 mode. +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define EXPECT_DECIMAL_DIG +#define EXPECT_FLT_EVAL_METHOD +#endif + +// If we're not in C99 mode, we still expect the definition of DECIMAL_DIG +// unless we're in strict ansi mode. +#if !defined(EXPECT_DECIMAL_DIG) && !defined(__STRICT_ANSI__) +#define EXPECT_DECIMAL_DIG +#endif + +#if defined(EXPECT_DECIMAL_DIG) + #if !defined(DECIMAL_DIG) + #error "DECIMAL_DIG missing" + #endif +#else + #if defined(DECIMAL_DIG) + #error "DECIMAL_DIG provided when not expected" + #endif +#endif + +#if defined(EXPECT_FLT_EVAL_METHOD) + #if !defined(FLT_EVAL_METHOD) + #error "FLT_EVAL_METHOD missing" + #endif +#else + #if defined(FLT_EVAL_METHOD) + #error "FLT_EVAL_METHOD provided when not expected" + #endif +#endif diff --git a/clang/test/C/C99/n570.c b/clang/test/C/C99/n570.c new file mode 100644 index 0000000000000000000000000000000000000000..31c09224e618b5ab7f9e24d8a0b1f4c5589d79f3 --- /dev/null +++ b/clang/test/C/C99/n570.c @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -verify -std=c99 %s +// RUN: %clang_cc1 -E -std=c99 %s | FileCheck %s +// expected-no-diagnostics + +/* WG14 N570: Yes + * Empty macro arguments + * + * NB: the original paper is not available online anywhere, so the test + * coverage is coming from what could be gleaned from the C99 rationale + * document. In C89, it was UB to pass no arguments to a function-like macro, + * and that's now supported in C99. + */ + +#define TEN 10 +#define U u +#define I // expands into no preprocessing tokens +#define L L +#define glue(a, b) a ## b +#define xglue(a, b) glue(a, b) + +const unsigned u = xglue(TEN, U); +const int i = xglue(TEN, I); +const long l = xglue(TEN, L); + +// CHECK: const unsigned u = 10u; +// CHECK-NEXT: const int i = 10; +// CHECK-NEXT: const long l = 10L; + +_Static_assert(u == 10U, ""); +_Static_assert(i == 10, ""); +_Static_assert(l == 10L, ""); diff --git a/clang/test/C/C99/n590.c b/clang/test/C/C99/n590.c new file mode 100644 index 0000000000000000000000000000000000000000..7302e3c5cebabcc65590cb66079afa36e9868590 --- /dev/null +++ b/clang/test/C/C99/n590.c @@ -0,0 +1,390 @@ +// RUN: %clang_cc1 -verify -Wno-unused -I %S/Inputs %s + +/* WG14 N590: Clang 3.2 + * Increase minimum translation limits + * + * NB: the content of this document is not available, so this is testing + * against the implementation limits in C23, which are the most aggressive + * translation limits we can test against. + */ +// expected-no-diagnostics + +// 15 nesting levels for #included files +// NOTE: this relies on the value of __COUNTER__, so be very careful about +// adding code above this line of the test. +#include "nested-include.h" + +// Helpers for declaring unique variables. +#define CAT_IMPL(x, y) x ## y +#define CAT(x, y) CAT_IMPL(x, y) +#define ONCE(x) CAT(x, __COUNTER__) SEPARATOR +#define REPEAT10(x) ONCE(x) ONCE(x) ONCE(x) ONCE(x) ONCE(x) ONCE(x) ONCE(x) ONCE(x) ONCE(x) ONCE(x) +#define REPEAT63(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) ONCE(x) ONCE(x) ONCE(x) +#define REPEAT100(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) +#define REPEAT127(x) REPEAT100(x) REPEAT10(x) REPEAT10(x) ONCE(x) ONCE(x) ONCE(x) ONCE(x) ONCE(x) ONCE(x) ONCE(x) +#define REPEAT500(x) REPEAT100(x) REPEAT100(x) REPEAT100(x) REPEAT100(x) REPEAT100(x) +#define REPEAT1000(x) REPEAT500(x) REPEAT500(x) +#define REPEAT1023(x) REPEAT1000(x) REPEAT10(x) REPEAT10(x) ONCE(x) ONCE(x) ONCE(x) +#define REPEAT4095(x) REPEAT1000(x) REPEAT1000(x) REPEAT1000(x) REPEAT1000(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) REPEAT10(x) ONCE(x) ONCE(x) ONCE(x) ONCE(x) ONCE(x) + +// Limits taken from C23 5.2.5.2p1. +void func(void) { + // 127 nesting levels of blocks + {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ + }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} + + // 12 pointer, array, and function declarators (in any combination) modifying + // an arithmetic, structure, union, or void type in a declaration. + void (************fp)(int foo[1][2][3][4][5][6][7][8][9][10][11][12]); + + // 63 nesting levels of parenthesized declarators within a full declarator. + int (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((decl))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))); + + // 63 significant initial characters in an internal identifier or a macro + // name. + static int aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffggg; + + // 31 significant initial characters in an external identifier. + extern int gggggggggghhhhhhhhhhiiiiiiiiiijjjjjjjjjjkkkkkkkkkkllllllllllmmm; + + // 511 identifiers with block scope declared in one block. + { + #define SEPARATOR ; + REPEAT500(int a) + REPEAT10(int a) + ONCE(int a) + #undef SEPARATOR + } + + // 4095 characters in a logical source line. + (void)0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4; + + // 4095 characters in a string literal (after concatenation) + (void)"0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,\ + 9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,\ + 7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,\ + 5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,\ + 3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,\ + 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4"; + + // 1023 case labels for a switch statement. + switch (aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffggg) { + #define SEPARATOR : + REPEAT1023(case 0x) + #undef SEPARATOR + break; + } +} + +// 32767 bytes in an object. +struct S { + unsigned char mem[32767]; +}; +_Static_assert(sizeof(struct S) >= 32767, ""); + +// 1023 members in a single structure or union +struct T { +#define SEPARATOR ; + REPEAT1023(int mem) +#undef SEPARATOR +}; + +// 1023 enumeration constants in a single enumeration +enum E { +#define SEPARATOR , +REPEAT1023(e) +#undef SEPARATOR +}; + +// 127 parameters in one function definition. +#define SEPARATOR , +// Because the parameters are all separated by commas, we have to add a final +// parameter (without a preceeding comma) to form a valid declaration. +void lots_of_params(REPEAT127(int a) int last) { + // 127 arguments in one function call + lots_of_params(REPEAT127(0x0) 0); +} +#undef SEPARATOR + +// 63 levels of nested structure or union definitions in a single member +// declaration list. +struct U { +#define SEPARATOR ; +REPEAT63(struct { int a) +REPEAT63(} mem) +#undef SEPARATOR +}; + +// 63 nesting levels of conditional inclusion +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 +#if 1 + +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif +#endif + +// 63 initial characters in a macro name. +#define AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDDEEEEEEEEEEFFFFFFFFFFGGG + +// 4095 external identifiers in one translation unit. +#define SEPARATOR ; +REPEAT4095(extern int val) +#undef SEPARATOR + +// 127 parameters in one macro definition +#define BIG_UN(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, \ + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, \ + a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, \ + a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, \ + a40, a41, a42, a43, a44, a45, a46, a47, a48, a49, \ + a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, \ + a60, a61, a62, a63, a64, a65, a66, a67, a68, a69, \ + a70, a71, a72, a73, a74, a75, a76, a77, a78, a79, \ + a80, a81, a82, a83, a84, a85, a86, a87, a88, a89, \ + a90, a91, a92, a93, a94, a95, a96, a97, a98, a99, \ + a100, a101, a102, a103, a104, a105, a106, a107, a108, a109, \ + a110, a111, a112, a113, a114, a115, a116, a117, a118, a119, \ + a120, a121, a122, a123, a124, a125, a126) 0 + +// 127 arguments in one macro invocation +int val = BIG_UN(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, \ + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, \ + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, \ + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, \ + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, \ + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, \ + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, \ + 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, \ + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, \ + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, \ + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, \ + 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, \ + 120, 121, 122, 123, 124, 125, 126); + +// 4095 macro identifiers simultaneously defined in one preprocessing +// translation unit. Rather than write out 4095 macro definitions, we'll use a +// cheap python script to generate the contents and test that. +// RUN: %python -c "print('\n'.join(['// expected-no-diagnostics'] + [f'#define M{i}\n' for i in range(4096)]))" >%t.inc +// RUN: %clang_cc1 -verify %t.inc diff --git a/clang/test/C/C99/n696.c b/clang/test/C/C99/n696.c new file mode 100644 index 0000000000000000000000000000000000000000..4499c6e42226b547568402f528d8b951513ff0fe --- /dev/null +++ b/clang/test/C/C99/n696.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple x86_64 -verify %s + +/* WG14 N696: yes + * Standard pragmas - improved wording + * + * NB: this also covers N631 which changed these features into pragmas rather + * than macros. + */ + +// Verify that we do not expand macros in STDC pragmas. If we expanded them, +// this code would issue diagnostics. +#define ON 12 +#pragma STDC FENV_ACCESS ON +#pragma STDC CX_LIMITED_RANGE ON +#pragma STDC FP_CONTRACT ON + +// If we expanded macros, this code would not issue diagnostics. +#define BLERP OFF +#pragma STDC FENV_ACCESS BLERP // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}} +#pragma STDC CX_LIMITED_RANGE BLERP // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}} +#pragma STDC FP_CONTRACT BLERP // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}} + diff --git a/clang/test/C/C99/n782.c b/clang/test/C/C99/n782.c new file mode 100644 index 0000000000000000000000000000000000000000..d147fd6fb1a1a22df318451e1592f44d1a20baf9 --- /dev/null +++ b/clang/test/C/C99/n782.c @@ -0,0 +1,23 @@ +/* RUN: %clang_cc1 -verify -std=c99 -pedantic %s + RUN: %clang_cc1 -verify=c89 -std=c89 -pedantic %s + expected-no-diagnostics + */ + +/* WG14 N782: Clang 3.4 + * Relaxed constraints on aggregate and union initialization + */ + +void test(void) { + struct S { + int x, y; + }; + int a = 1, b = 2; + struct S s = { a, b }; /* c89-warning {{initializer for aggregate is not a compile-time constant}} */ + + union U { + int x; + float f; + }; + union U u = { a }; /* c89-warning {{initializer for aggregate is not a compile-time constant}} */ +} + diff --git a/clang/test/C/C99/n835.c b/clang/test/C/C99/n835.c new file mode 100644 index 0000000000000000000000000000000000000000..38a974e065724d1b769834f0315ccbcedc8d1721 --- /dev/null +++ b/clang/test/C/C99/n835.c @@ -0,0 +1,35 @@ +/* RUN: %clang_cc1 -verify -pedantic -std=c99 %s + RUN: %clang_cc1 -verify=c89 -pedantic -std=c89 %s + expected-no-diagnostics + */ + +/* WG14 N835: Yes + * Conversion of array to pointer not limited to lvalues + * + * NB: The crux of the change was C99 changing: + * + * C89 3.2.2.1: Except when it is the operand of ..., an lvalue that has type + * 'array of type' is converted to an expression that has type 'pointer to + * type' that points to the initial element of the array object and is not an + * lvalue. + * + * C99 6.3.2.1p3: Except when it is the operand of ..., an expression that has + * type 'array of type' is converted to an expression with type 'pointer to + * type' that points to the initial element of the array object and is not an + * lvalue. + */ + +struct S { + char arr[100]; +}; + +struct S f(void); + +void func(void) { + char c; + /* The return from f() is an rvalue, so this code is not valid in C89, but is + * valid in C99. + */ + c = f().arr[10]; /* c89-warning {{ISO C90 does not allow subscripting non-lvalue array}} */ +} + diff --git a/clang/test/C/drs/dr0xx.c b/clang/test/C/drs/dr0xx.c index c93cfb63d604cfaf77af8b58bc7cbf494e115188..36de32a93da95d51123d0f60746061a7440b5460 100644 --- a/clang/test/C/drs/dr0xx.c +++ b/clang/test/C/drs/dr0xx.c @@ -73,6 +73,10 @@ * WG14 DR085: yes * Returning from main * + * WG14 DR087: yes + * Order of evaluation + * Note: this DR is covered by C/C11/n1282.c + * * WG14 DR086: yes * Object-like macros in system headers * diff --git a/clang/test/C/drs/dr290.c b/clang/test/C/drs/dr290.c new file mode 100644 index 0000000000000000000000000000000000000000..3a6fd1d0dab6f69fa04e6552f6fca21ecfe2d9c9 --- /dev/null +++ b/clang/test/C/drs/dr290.c @@ -0,0 +1,20 @@ +/* RUN: %clang_cc1 -fsyntax-only -ast-dump %s | FileCheck %s + */ + +/* WG14 DR290: no + * FLT_EVAL_METHOD and extra precision and/or range + * + * We retain an implicit conversion based on the float eval method being used + * instead of dropping it due to the explicit cast. See GH86304 and C23 6.5.5p7. + */ + +#pragma clang fp eval_method(double) +_Static_assert((float)(123.0F * 2.0F) == (float)246.0F, ""); + +// CHECK: StaticAssertDecl +// CHECK-NEXT: ImplicitCastExpr {{.*}} '_Bool' <IntegralToBoolean> +// CHECK-NEXT: BinaryOperator {{.*}} 'int' '==' +// NB: the following implicit cast is incorrect. +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' <FloatingCast> FPEvalMethod=1 +// CHECK-NEXT: CStyleCastExpr {{.*}} 'float' <FloatingCast> FPEvalMethod=1 + diff --git a/clang/test/C/drs/dr4xx.c b/clang/test/C/drs/dr4xx.c index 30145dcfeef16861d746c1d38c64a417f1c8afdf..83d7b94cd67959dfeedf0141dd35b7d22e9049f8 100644 --- a/clang/test/C/drs/dr4xx.c +++ b/clang/test/C/drs/dr4xx.c @@ -1,7 +1,7 @@ -/* RUN: %clang_cc1 -std=c89 -verify=expected,c89only -pedantic -Wno-c11-extensions %s - RUN: %clang_cc1 -std=c99 -verify=expected -pedantic -Wno-c11-extensions %s - RUN: %clang_cc1 -std=c11 -verify=expected -pedantic %s - RUN: %clang_cc1 -std=c17 -verify=expected -pedantic %s +/* RUN: %clang_cc1 -std=c89 -verify=expected,c89only,pre-c23 -pedantic -Wno-c11-extensions %s + RUN: %clang_cc1 -std=c99 -verify=expected,pre-c23 -pedantic -Wno-c11-extensions %s + RUN: %clang_cc1 -std=c11 -verify=expected,pre-c23 -pedantic %s + RUN: %clang_cc1 -std=c17 -verify=expected,pre-c23 -pedantic %s RUN: %clang_cc1 -std=c2x -verify=expected -pedantic %s */ @@ -343,10 +343,13 @@ void dr496(void) { */ /* The DR asked a question about whether defining a new type within offsetof - * is allowed. C2x N2350 made this explicitly undefined behavior, but GCC and - * Clang both support it as an extension. + * is allowed. C23 N2350 had made this explicitly undefined behavior, but this + * was later overturned when C23 DE-137 was accepted, making it well-formed. + * + * Additionally, GCC and Clang both support it as an extension in pre-C23 + * mode. */ - (void)__builtin_offsetof(struct S { int a; }, a); /* expected-warning{{defining a type within '__builtin_offsetof' is a Clang extension}} */ + (void)__builtin_offsetof(struct S { int a; }, a); /* pre-c23-warning{{defining a type within '__builtin_offsetof' is a C23 extension}} */ } /* WG14 DR499: yes diff --git a/clang/test/C/drs/dr5xx.c b/clang/test/C/drs/dr5xx.c index 68bcef78baccd7caca8f0d373ca91bc2c72ab70d..13464f78b6a654a3821e8b587fd3642a6d1a1e0b 100644 --- a/clang/test/C/drs/dr5xx.c +++ b/clang/test/C/drs/dr5xx.c @@ -29,7 +29,7 @@ void dr502(void) { */ struct t { int i; - struct { int a[]; }; /* expected-error {{flexible array member 'a' not allowed in otherwise empty struct}} + struct { int a[]; }; /* expected-warning {{flexible array member 'a' in otherwise empty struct is a GNU extension}} c89only-warning {{flexible array members are a C99 feature}} expected-warning {{'' may not be nested in a struct due to flexible array member}} */ diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp index 766c90d3bc7bda9ec619928b7245e051a04e8331..f4d6c04fb8e0738d8d73a4f1a2f2ad13556bf897 100644 --- a/clang/test/CXX/drs/dr16xx.cpp +++ b/clang/test/CXX/drs/dr16xx.cpp @@ -35,6 +35,17 @@ void g() { } } // namespace dr1601 +namespace dr1606 { // dr1606: 3.1 +#if __cplusplus >= 201103L + std::size_t test() { + int i = 1; + int j = 1; + auto f = [=]{ return i + j; }; + return sizeof(f); + } +#endif +} // namespace dr1606 + namespace dr1611 { // dr1611: dup 1658 struct A { A(int); }; struct B : virtual A { virtual void f() = 0; }; 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 3072b760f9d7dd1101d9657e72b2c6295f7a2bf0..1a01ffac0154aefd35842b16ecb911c4074f19cb 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 @@ -15,10 +15,6 @@ module A; // #module-decl // expected-error@-2 {{missing 'export' specifier in module declaration while building module interface}} #define INTERFACE #endif -#else - #ifdef BUILT_AS_INTERFACE - // expected-error@1 {{missing 'export module' declaration in module interface unit}} - #endif #endif #ifndef INTERFACE diff --git a/clang/test/ClangScanDeps/modules-extension.c b/clang/test/ClangScanDeps/modules-extension.c new file mode 100644 index 0000000000000000000000000000000000000000..0f27f608440f4593effb010ebceef768e749544a --- /dev/null +++ b/clang/test/ClangScanDeps/modules-extension.c @@ -0,0 +1,33 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t + +// This test checks that source files with uncommon extensions still undergo +// dependency directives scan. If header.pch would not and b.h would, the scan +// would fail when parsing `void function(B)` and not knowing the symbol B. + +//--- module.modulemap +module __PCH { header "header.pch" } +module B { header "b.h" } + +//--- header.pch +#include "b.h" +void function(B); + +//--- b.h +typedef int B; + +//--- tu.c +int main() { + function(0); + return 0; +} + +//--- cdb.json.in +[{ + "directory": "DIR", + "file": "DIR/tu.c", + "command": "clang -c DIR/tu.c -fmodules -fmodules-cache-path=DIR/cache -fimplicit-module-maps -include DIR/header.pch" +}] + +// RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.in > %t/cdb.json +// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full > %t/deps.json diff --git a/clang/test/ClangScanDeps/modules-extern-unrelated.m b/clang/test/ClangScanDeps/modules-extern-unrelated.m index 442ee90aa1836d48dcd112cd5a1c4f59103e538d..76611c596d3effcc3287cc2f54a0c59e19ea1fb2 100644 --- a/clang/test/ClangScanDeps/modules-extern-unrelated.m +++ b/clang/test/ClangScanDeps/modules-extern-unrelated.m @@ -71,6 +71,7 @@ module second { header "second.h" } // CHECK-NEXT: "context-hash": "{{.*}}", // CHECK-NEXT: "file-deps": [ // CHECK-NEXT: "[[PREFIX]]/first/module.modulemap", +// CHECK-NEXT: "[[PREFIX]]/second/module.modulemap", // CHECK-NEXT: "[[PREFIX]]/second/second.h", // CHECK-NEXT: "[[PREFIX]]/second/second.modulemap" // CHECK-NEXT: ], diff --git a/clang/test/CodeCompletion/member-access.cpp b/clang/test/CodeCompletion/member-access.cpp index 474b909ab11592c5520b714dcb5744f65fcfe6e1..9f8c21c0bca6de1efaf6c4e74821e87274f09d01 100644 --- a/clang/test/CodeCompletion/member-access.cpp +++ b/clang/test/CodeCompletion/member-access.cpp @@ -348,7 +348,23 @@ namespace function_can_be_call { T foo(U, V); }; - &S::f - // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:351:7 %s -o - | FileCheck -check-prefix=CHECK_FUNCTION_CAN_BE_CALL %s + void test() { + &S::f + } + // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:352:9 %s -o - | FileCheck -check-prefix=CHECK_FUNCTION_CAN_BE_CALL %s // CHECK_FUNCTION_CAN_BE_CALL: COMPLETION: foo : [#T#]foo<<#typename T#>, <#typename U#>>(<#U#>, <#V#>) } + +namespace deref_dependent_this { +template <typename T> +class A { + int field; + + void function() { + (*this).field; +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:364:13 %s -o - | FileCheck -check-prefix=CHECK-DEREF-THIS %s +// CHECK-DEREF-THIS: field : [#int#]field +// CHECK-DEREF-THIS: [#void#]function() + } +}; +} diff --git a/clang/test/CodeGen/CSKY/csky-abi.c b/clang/test/CodeGen/CSKY/csky-abi.c index 2e549376ba93301b7eef4e746817fc2497843ead..29ed661aea75d94853ae28eff77136ee97547ee1 100644 --- a/clang/test/CodeGen/CSKY/csky-abi.c +++ b/clang/test/CodeGen/CSKY/csky-abi.c @@ -185,13 +185,13 @@ void f_va_caller(void) { // CHECK: [[VA:%.*]] = alloca ptr, align 4 // CHECK: [[V:%.*]] = alloca i32, align 4 // CHECK: store ptr %fmt, ptr [[FMT_ADDR]], align 4 -// CHECK: call void @llvm.va_start(ptr [[VA]]) +// CHECK: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK: [[TMP1:%.*]] = load i32, ptr [[ARGP_CUR]], align 4 // CHECK: store i32 [[TMP1]], ptr [[V]], align 4 -// CHECK: call void @llvm.va_end(ptr [[VA]]) +// CHECK: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK: [[TMP2:%.*]] = load i32, ptr [[V]], align 4 // CHECK: ret i32 [[TMP2]] // CHECK: } @@ -210,13 +210,13 @@ int f_va_1(char *fmt, ...) { // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[V:%.*]] = alloca double, align 4 // CHECK-NEXT: store ptr [[FMT:%.*]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP4:%.*]] = load double, ptr [[ARGP_CUR]], align 4 // CHECK-NEXT: store double [[TMP4]], ptr [[V]], align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP5:%.*]] = load double, ptr [[V]], align 4 // CHECK-NEXT: ret double [[TMP5]] double f_va_2(char *fmt, ...) { @@ -236,7 +236,7 @@ double f_va_2(char *fmt, ...) { // CHECK-NEXT: [[W:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[X:%.*]] = alloca double, align 4 // CHECK-NEXT: store ptr [[FMT:%.*]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -252,7 +252,7 @@ double f_va_2(char *fmt, ...) { // CHECK-NEXT: store ptr [[ARGP_NEXT5]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP11:%.*]] = load double, ptr [[ARGP_CUR4]], align 4 // CHECK-NEXT: store double [[TMP11]], ptr [[X]], align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP12:%.*]] = load double, ptr [[V]], align 4 // CHECK-NEXT: [[TMP13:%.*]] = load double, ptr [[X]], align 4 // CHECK-NEXT: [[ADD:%.*]] = fadd double [[TMP12]], [[TMP13]] @@ -279,7 +279,7 @@ double f_va_3(char *fmt, ...) { // CHECK-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4 // CHECK-NEXT: [[RET:%.*]] = alloca i32, align 4 // CHECK-NEXT: store ptr [[FMT:%.*]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -302,7 +302,7 @@ double f_va_3(char *fmt, ...) { // CHECK-NEXT: [[ARGP_NEXT9:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR8]], i32 16 // CHECK-NEXT: store ptr [[ARGP_NEXT9]], ptr [[VA]], align 4 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[LS]], ptr align 4 [[ARGP_CUR8]], i32 16, i1 false) -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) int f_va_4(char *fmt, ...) { __builtin_va_list va; diff --git a/clang/test/CodeGen/LoongArch/abi-lp64d.c b/clang/test/CodeGen/LoongArch/abi-lp64d.c index 66b480a7f068945484b3292014de43fe6db5dd23..fc7f1eada586b38e90fb610dee2f582ff5cce5a3 100644 --- a/clang/test/CodeGen/LoongArch/abi-lp64d.c +++ b/clang/test/CodeGen/LoongArch/abi-lp64d.c @@ -449,13 +449,13 @@ void f_va_caller(void) { // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[V:%.*]] = alloca i32, align 4 // CHECK-NEXT: store ptr [[FMT:%.*]], ptr [[FMT_ADDR]], align 8 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 8 // CHECK-NEXT: store i32 [[TMP0]], ptr [[V]], align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[V]], align 4 // CHECK-NEXT: ret i32 [[TMP1]] int f_va_int(char *fmt, ...) { diff --git a/clang/test/CodeGen/M68k/inline-asm-gcc-regs.c b/clang/test/CodeGen/M68k/inline-asm-gcc-regs.c new file mode 100644 index 0000000000000000000000000000000000000000..40d3543d8a6f90c64d6748bad16ee6fad53115bc --- /dev/null +++ b/clang/test/CodeGen/M68k/inline-asm-gcc-regs.c @@ -0,0 +1,134 @@ +// RUN: %clang_cc1 -triple m68k -emit-llvm -O2 %s -o - | FileCheck %s + +/// Check GCC register names and alias can be used in register variable definition. + +// CHECK-LABEL: @test_d0 +// CHECK: call void asm sideeffect "", "{d0}"(i32 undef) +void test_d0() { + register int a asm ("d0"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_d1 +// CHECK: call void asm sideeffect "", "{d1}"(i32 undef) +void test_d1() { + register int a asm ("d1"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_d2 +// CHECK: call void asm sideeffect "", "{d2}"(i32 undef) +void test_d2() { + register int a asm ("d2"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_d3 +// CHECK: call void asm sideeffect "", "{d3}"(i32 undef) +void test_d3() { + register int a asm ("d3"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_d4 +// CHECK: call void asm sideeffect "", "{d4}"(i32 undef) +void test_d4() { + register int a asm ("d4"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_d5 +// CHECK: call void asm sideeffect "", "{d5}"(i32 undef) +void test_d5() { + register int a asm ("d5"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_d6 +// CHECK: call void asm sideeffect "", "{d6}"(i32 undef) +void test_d6() { + register int a asm ("d6"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_d7 +// CHECK: call void asm sideeffect "", "{d7}"(i32 undef) +void test_d7() { + register int a asm ("d7"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_a0 +// CHECK: call void asm sideeffect "", "{a0}"(i32 undef) +void test_a0() { + register int a asm ("a0"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_a1 +// CHECK: call void asm sideeffect "", "{a1}"(i32 undef) +void test_a1() { + register int a asm ("a1"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_a2 +// CHECK: call void asm sideeffect "", "{a2}"(i32 undef) +void test_a2() { + register int a asm ("a2"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_a3 +// CHECK: call void asm sideeffect "", "{a3}"(i32 undef) +void test_a3() { + register int a asm ("a3"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_a4 +// CHECK: call void asm sideeffect "", "{a4}"(i32 undef) +void test_a4() { + register int a asm ("a4"); + asm ("" :: "r" (a)); +} + +// CHECK-LABEL: @test_a5 +// CHECK: call void asm sideeffect "", "{a5}"(i32 undef) +void test_a5() { + register int a asm ("a5"); + register int b asm ("bp"); + asm ("" :: "r" (a)); + asm ("" :: "r" (b)); +} + +// CHECK-LABEL: @test_a6 +// CHECK: call void asm sideeffect "", "{a6}"(i32 undef) +void test_a6() { + register int a asm ("a6"); + register int b asm ("fp"); + asm ("" :: "r" (a)); + asm ("" :: "r" (b)); +} + +// CHECK-LABEL: @test_sp +// CHECK: call void asm sideeffect "", "{sp}"(i32 undef) +void test_sp() { + register int a asm ("sp"); + register int b asm ("usp"); + register int c asm ("ssp"); + register int d asm ("isp"); + register int e asm ("a7"); + asm ("" :: "r" (a)); + asm ("" :: "r" (b)); + asm ("" :: "r" (c)); + asm ("" :: "r" (d)); + asm ("" :: "r" (e)); +} + +// CHECK-LABEL: @test_pc +// CHECK: call void asm sideeffect "", "{pc}"(i32 undef) +void test_pc() { + register int a asm ("pc"); + asm ("" :: "r" (a)); +} diff --git a/clang/test/CodeGen/PowerPC/aix-altivec-vaargs.c b/clang/test/CodeGen/PowerPC/aix-altivec-vaargs.c index 03182423a422c1e8bd440f3664a5b29dab9ef268..b3f1e93b6394405dd5c359cdf1bebd1ace550b5f 100644 --- a/clang/test/CodeGen/PowerPC/aix-altivec-vaargs.c +++ b/clang/test/CodeGen/PowerPC/aix-altivec-vaargs.c @@ -17,7 +17,7 @@ vector double vector_varargs(int count, ...) { } // CHECK: %arg_list = alloca ptr -// CHECK: call void @llvm.va_start(ptr %arg_list) +// CHECK: call void @llvm.va_start.p0(ptr %arg_list) // AIX32: for.body: // AIX32-NEXT: %argp.cur = load ptr, ptr %arg_list, align 4 @@ -41,4 +41,4 @@ vector double vector_varargs(int count, ...) { // CHECK: for.end: -// CHECK: call void @llvm.va_end(ptr %arg_list) +// CHECK: call void @llvm.va_end.p0(ptr %arg_list) diff --git a/clang/test/CodeGen/PowerPC/aix-vaargs.c b/clang/test/CodeGen/PowerPC/aix-vaargs.c index 8b8417d315a504577e8b5b2b5138532d999abe2d..724ba6560cdb97125c335e97336abcda537fcd96 100644 --- a/clang/test/CodeGen/PowerPC/aix-vaargs.c +++ b/clang/test/CodeGen/PowerPC/aix-vaargs.c @@ -35,7 +35,7 @@ void testva (int n, ...) { // CHECK-NEXT: %v = alloca i32, align 4 // CHECK-NEXT: store i32 %n, ptr %n.addr, align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr %ap) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr %ap) // AIX32-NEXT: %argp.cur = load ptr, ptr %ap, align 4 // AIX32-NEXT: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i32 16 @@ -48,7 +48,7 @@ void testva (int n, ...) { // AIX32-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 8 %t, ptr align 4 %argp.cur, i32 16, i1 false) // AIX64-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %t, ptr align 8 %argp.cur, i64 16, i1 false) -// CHECK-NEXT: call void @llvm.va_copy(ptr %ap2, ptr %ap) +// CHECK-NEXT: call void @llvm.va_copy.p0(ptr %ap2, ptr %ap) // AIX32-NEXT: %argp.cur1 = load ptr, ptr %ap2, align 4 // AIX32-NEXT: %argp.next2 = getelementptr inbounds i8, ptr %argp.cur1, i32 4 @@ -62,14 +62,14 @@ void testva (int n, ...) { // AIX64-NEXT: %1 = load i32, ptr %0, align 4 // AIX64-NEXT: store i32 %1, ptr %v, align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr %ap2) -// CHECK-NEXT: call void @llvm.va_end(ptr %ap) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr %ap2) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr %ap) // CHECK-NEXT: ret void -// CHECK: declare void @llvm.va_start(ptr) +// CHECK: declare void @llvm.va_start.p0(ptr) // AIX32: declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) // AIX64: declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) -// CHECK: declare void @llvm.va_copy(ptr, ptr) -// CHECK: declare void @llvm.va_end(ptr) +// CHECK: declare void @llvm.va_copy.p0(ptr, ptr) +// CHECK: declare void @llvm.va_end.p0(ptr) diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-error.c b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-error.c index 5f57d7575c859abba0b8fc083d38ceb397bc11be..272e0222dc9e41f9e078a0cf0e723fd8ca0be3b8 100644 --- a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-error.c +++ b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-error.c @@ -24,13 +24,16 @@ void test_trap(void) { __tw(ia, ib, 0); //expected-error {{argument value 0 is outside the valid range [1, 31]}} } +#ifdef __PPC64__ void test_builtin_ppc_rldimi() { unsigned int shift; unsigned long long mask; unsigned long long res = __builtin_ppc_rldimi(ull, ull, shift, 7); // expected-error {{argument to '__builtin_ppc_rldimi' must be a constant integer}} res = __builtin_ppc_rldimi(ull, ull, 63, mask); // expected-error {{argument to '__builtin_ppc_rldimi' must be a constant integer}} res = __builtin_ppc_rldimi(ull, ull, 63, 0xFFFF000000000F00); // expected-error {{argument 3 value should represent a contiguous bit field}} + res = __builtin_ppc_rldimi(ull, ull, 64, 0xFFFF000000000000); // expected-error {{argument value 64 is outside the valid range [0, 63]}} } +#endif void test_builtin_ppc_rlwimi() { unsigned int shift; @@ -83,6 +86,10 @@ void testalignx(const void *pointer, unsigned int alignment) { } #ifndef __PPC64__ +unsigned long long testrldimi32() { + return __rldimi(ull, ui, 3, 0x7ffff8ULL); //expected-error {{this builtin is only available on 64-bit targets}} +} + long long testbpermd(long long bit_selector, long long source) { return __bpermd(bit_selector, source); //expected-error {{this builtin is only available on 64-bit targets}} } diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-rotate.c b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-rotate.c index b218547c00d93111d25c25b0e7967590a784819a..4773d6cb1a0cfdfc0c05ae491589b1ee7e56293b 100644 --- a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-rotate.c +++ b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-rotate.c @@ -1,8 +1,10 @@ // REQUIRES: powerpc-registered-target // RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu \ -// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s \ +// RUN: -check-prefixes=PPC64,CHECK // RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu \ -// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s +// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s \ +// RUN: -check-prefixes=PPC64,CHECK // RUN: %clang_cc1 -triple powerpc-unknown-aix \ // RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s // RUN: %clang_cc1 -triple powerpc64-unknown-aix \ @@ -11,18 +13,20 @@ extern unsigned int ui; extern unsigned long long ull; +#ifdef __PPC64__ void test_builtin_ppc_rldimi() { - // CHECK-LABEL: test_builtin_ppc_rldimi - // CHECK: %res = alloca i64, align 8 - // CHECK-NEXT: [[RA:%[0-9]+]] = load i64, ptr @ull, align 8 - // CHECK-NEXT: [[RB:%[0-9]+]] = load i64, ptr @ull, align 8 - // CHECK-NEXT: [[RC:%[0-9]+]] = call i64 @llvm.ppc.rldimi(i64 [[RA]], i64 [[RB]], i32 63, i64 72057593769492480) - // CHECK-NEXT: store i64 [[RC]], ptr %res, align 8 - // CHECK-NEXT: ret void + // PPC64-LABEL: test_builtin_ppc_rldimi + // PPC64: %res = alloca i64, align 8 + // PPC64-NEXT: [[RA:%[0-9]+]] = load i64, ptr @ull, align 8 + // PPC64-NEXT: [[RB:%[0-9]+]] = load i64, ptr @ull, align 8 + // PPC64-NEXT: [[RC:%[0-9]+]] = call i64 @llvm.ppc.rldimi(i64 [[RA]], i64 [[RB]], i32 63, i64 72057593769492480) + // PPC64-NEXT: store i64 [[RC]], ptr %res, align 8 + // PPC64-NEXT: ret void /*shift = 63, mask = 0x00FFFFFFF0000000 = 72057593769492480, ~mask = 0xFF0000000FFFFFFF = -72057593769492481*/ unsigned long long res = __builtin_ppc_rldimi(ull, ull, 63, 0x00FFFFFFF0000000); } +#endif void test_builtin_ppc_rlwimi() { // CHECK-LABEL: test_builtin_ppc_rlwimi diff --git a/clang/test/CodeGen/PowerPC/ppc64le-varargs-f128.c b/clang/test/CodeGen/PowerPC/ppc64le-varargs-f128.c index 396614fe5bac2f326cda066041562370082f8fb3..2f5459d1bb9c4c14d347a8cd403c7d169acd3317 100644 --- a/clang/test/CodeGen/PowerPC/ppc64le-varargs-f128.c +++ b/clang/test/CodeGen/PowerPC/ppc64le-varargs-f128.c @@ -31,7 +31,7 @@ void foo_ls(ldbl128_s); // OMP-TARGET: call void @foo_ld(ppc_fp128 noundef %[[V3]]) // OMP-HOST-LABEL: define{{.*}} void @omp( -// OMP-HOST: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]]) +// OMP-HOST: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]]) // OMP-HOST: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]], align 8 // OMP-HOST: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15 // OMP-HOST: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16) @@ -49,13 +49,13 @@ void omp(int n, ...) { } // IEEE-LABEL: define{{.*}} void @f128 -// IEEE: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]]) +// IEEE: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]]) // IEEE: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]] // IEEE: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15 // IEEE: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16) // IEEE: %[[V4:[0-9a-zA-Z_.]+]] = load fp128, ptr %[[ALIGN]], align 16 // IEEE: call void @foo_fq(fp128 noundef %[[V4]]) -// IEEE: call void @llvm.va_end(ptr %[[AP]]) +// IEEE: call void @llvm.va_end.p0(ptr %[[AP]]) void f128(int n, ...) { va_list ap; va_start(ap, n); @@ -64,20 +64,20 @@ void f128(int n, ...) { } // IEEE-LABEL: define{{.*}} void @long_double -// IEEE: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]]) +// IEEE: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]]) // IEEE: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]] // IEEE: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15 // IEEE: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16) // IEEE: %[[V4:[0-9a-zA-Z_.]+]] = load fp128, ptr %[[ALIGN]], align 16 // IEEE: call void @foo_ld(fp128 noundef %[[V4]]) -// IEEE: call void @llvm.va_end(ptr %[[AP]]) +// IEEE: call void @llvm.va_end.p0(ptr %[[AP]]) // IBM-LABEL: define{{.*}} void @long_double -// IBM: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]]) +// IBM: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]]) // IBM: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]] // IBM: %[[V4:[0-9a-zA-Z_.]+]] = load ppc_fp128, ptr %[[CUR]], align 8 // IBM: call void @foo_ld(ppc_fp128 noundef %[[V4]]) -// IBM: call void @llvm.va_end(ptr %[[AP]]) +// IBM: call void @llvm.va_end.p0(ptr %[[AP]]) void long_double(int n, ...) { va_list ap; va_start(ap, n); @@ -86,7 +86,7 @@ void long_double(int n, ...) { } // IEEE-LABEL: define{{.*}} void @long_double_struct -// IEEE: call void @llvm.va_start(ptr %[[AP:[0-9a-zA-Z_.]+]]) +// IEEE: call void @llvm.va_start.p0(ptr %[[AP:[0-9a-zA-Z_.]+]]) // IEEE: %[[CUR:[0-9a-zA-Z_.]+]] = load ptr, ptr %[[AP]] // IEEE: %[[TMP0:[^ ]+]] = getelementptr inbounds i8, ptr %[[CUR]], i32 15 // IEEE: %[[ALIGN:[^ ]+]] = call ptr @llvm.ptrmask.p0.i64(ptr %[[TMP0]], i64 -16) @@ -96,7 +96,7 @@ void long_double(int n, ...) { // IEEE: %[[COERCE:[0-9a-zA-Z_.]+]] = getelementptr inbounds %struct.ldbl128_s, ptr %[[TMP]], i32 0, i32 0 // IEEE: %[[V4:[0-9a-zA-Z_.]+]] = load fp128, ptr %[[COERCE]], align 16 // IEEE: call void @foo_ls(fp128 inreg %[[V4]]) -// IEEE: call void @llvm.va_end(ptr %[[AP]]) +// IEEE: call void @llvm.va_end.p0(ptr %[[AP]]) void long_double_struct(int n, ...) { va_list ap; va_start(ap, n); diff --git a/clang/test/CodeGen/PowerPC/toc-data-attribute.c b/clang/test/CodeGen/PowerPC/toc-data-attribute.c new file mode 100644 index 0000000000000000000000000000000000000000..db23d74759eeff873e623ca3759708001ab93a58 --- /dev/null +++ b/clang/test/CodeGen/PowerPC/toc-data-attribute.c @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 %s -triple powerpc-ibm-aix-xcoff -S -mtocdata=f,g,h,i,j,k,l,m,n,o,p -emit-llvm -o - 2>&1 | FileCheck %s -check-prefixes=COMMON,CHECK32 --match-full-lines +// RUN: %clang_cc1 %s -triple powerpc-ibm-aix-xcoff -S -mtocdata -emit-llvm -o - 2>&1 | FileCheck %s -check-prefixes=COMMON,CHECK32 --match-full-lines + +// RUN: %clang_cc1 %s -triple powerpc64-ibm-aix-xcoff -S -mtocdata=f,g,h,i,j,k,l,m,n,o,p -emit-llvm -o - 2>&1 | FileCheck %s -check-prefixes=COMMON,CHECK64 --match-full-lines +// RUN: %clang_cc1 %s -triple powerpc64-ibm-aix-xcoff -S -mtocdata -emit-llvm -o - 2>&1 | FileCheck %s -check-prefixes=COMMON,CHECK64 --match-full-lines + +extern int f; +long long g = 5; +const char *h = "h"; +int *i; +int __attribute__((aligned(128))) j = 0; +float k = 100.00; +double l = 2.5; +int m __attribute__((section("foo"))) = 10; +__thread int n; + +extern int p[]; + +struct SomeStruct; +extern struct SomeStruct o; + +static int func_a() { + return g+(int)h[0]+*i+j+k+l+m+n+p[0]; +} + +int func_b() { + f = 1; + return func_a(); +} + +struct SomeStruct* getAddress(void) { + return &o; +} + +// CHECK32: @g = global i64 5, align 8 +// CHECK64: @g = global i64 5, align 8 #0 +// COMMON: {{.*}} = private unnamed_addr constant [2 x i8] c"h\00", align 1 +// COMMON: @h = global {{...*}} #0 +// COMMON: @j = global i32 0, align 128 +// COMMON: @k = global float 1.000000e+02, align 4 #0 +// CHECK32: @l = global double 2.500000e+00, align 8 +// CHECK64: @l = global double 2.500000e+00, align 8 #0 +// COMMON: @m = global i32 10, section "foo", align 4 +// COMMON: @f = external global i32, align 4 #0 +// COMMON: @o = external global %struct.SomeStruct, align 1 +// CHECK32: @i = global ptr null, align 4 #0 +// CHECK64: @i = global ptr null, align 8 #0 +// COMMON: @n = thread_local global i32 0, align 4 +// COMMON: @p = external global [0 x i32], align 4 +// COMMON: attributes #0 = { "toc-data" } diff --git a/clang/test/CodeGen/PowerPC/toc-data-attribute.cpp b/clang/test/CodeGen/PowerPC/toc-data-attribute.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8183e3b727e7b369fcf98ceca9ef20789bcf4516 --- /dev/null +++ b/clang/test/CodeGen/PowerPC/toc-data-attribute.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 %s -triple powerpc-ibm-aix-xcoff -S -mtocdata -emit-llvm -o - 2>&1 | FileCheck %s -check-prefixes=COMMON,ALLTOC +// RUN: %clang_cc1 %s -triple powerpc-ibm-aix-xcoff -S -mtocdata=n,_ZN11MyNamespace10myVariableE,_ZL1s,_ZZ4testvE7counter -emit-llvm -o - 2>&1 | FileCheck %s -check-prefixes=COMMON,TOCLIST +// RUN: %clang_cc1 %s -triple powerpc64-ibm-aix-xcoff -S -mtocdata -emit-llvm -o - 2>&1 | FileCheck %s -check-prefixes=COMMON,ALLTOC +// RUN: %clang_cc1 %s -triple powerpc64-ibm-aix-xcoff -S -mtocdata=n,_ZN11MyNamespace10myVariableE,_ZL1s,_ZZ4testvE7counter -emit-llvm -o - 2>&1 | FileCheck %s -check-prefixes=COMMON,TOCLIST + +extern int n; +static int s = 100; + +inline int test() { + static int counter = 0; + counter++; + return counter; +} + +int a () { + n = test(); + return 0; +} + +namespace MyNamespace { + int myVariable = 10; +} + +int b(int x) { + using namespace MyNamespace; + return x + myVariable; +} + +int c(int x) { + s += x; + return s; +} + +// COMMON: @n = external global i32, align 4 #0 +// COMMON: @_ZN11MyNamespace10myVariableE = global i32 10, align 4 #0 +// COMMON-NOT: @_ZL1s = internal global i32 100, align 4 #0 +// ALLTOC: @_ZZ4testvE7counter = linkonce_odr global i32 0, align 4 #0 +// TOCLIST-NOT: @_ZZ4testvE7counter = linkonce_odr global i32 0, align 4 #0 +// COMMON: attributes #0 = { "toc-data" } diff --git a/clang/test/CodeGen/PowerPC/toc-data-diagnostics.c b/clang/test/CodeGen/PowerPC/toc-data-diagnostics.c new file mode 100644 index 0000000000000000000000000000000000000000..ba8955530e46700bba5875fae6dc62f614a04a14 --- /dev/null +++ b/clang/test/CodeGen/PowerPC/toc-data-diagnostics.c @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 %s -triple=powerpc-ibm-aix-xcoff -S -mtocdata=h,g,f,e,d,c,b,a,globalOneWithAlias,globalTwoWithAlias,ll,t3 -verify -emit-llvm -o - | FileCheck %s -check-prefix=CHECK --match-full-lines +// RUN: %clang_cc1 %s -triple=powerpc-ibm-aix-xcoff -S -mtocdata -verify=none -emit-llvm -o - | FileCheck %s -check-prefix=CHECK --match-full-lines + +// none-no-diagnostics + +struct large_struct { + int x; + short y; + short z; + char c; +}; + +struct large_struct a; // expected-warning {{-mtocdata option is ignored for a because variable is larger than a pointer}} +long long b = 5; // expected-warning {{-mtocdata option is ignored for b because variable is larger than a pointer}} +int __attribute__((aligned(128))) c = 0; // expected-warning {{-mtocdata option is ignored for c because variable is aligned wider than a pointer}} +double d = 2.5; // expected-warning {{-mtocdata option is ignored for d because variable is larger than a pointer}} +int e __attribute__((section("foo"))) = 10; // expected-warning {{-mtocdata option is ignored for e because variable has a section attribute}} +__thread int f; // expected-warning {{-mtocdata option is ignored for f because of thread local storage}} + +struct SomeStruct; +extern struct SomeStruct g; // expected-warning {{-mtocdata option is ignored for g because of incomplete type}} + +extern int h[]; // expected-warning {{-mtocdata option is ignored for h because of incomplete type}} + +struct ty3 { + int A; + char C[]; +}; +struct ty3 t3 = { 4, "fo" }; // expected-warning {{-mtocdata option is ignored for t3 because it contains a flexible array member}} + +int globalOneWithAlias = 10; +__attribute__((__alias__("globalOneWithAlias"))) extern int aliasOne; // expected-warning {{-mtocdata option is ignored for globalOneWithAlias because the variable has an alias}} +__attribute__((__alias__("globalTwoWithAlias"))) extern int aliasTwo; // expected-warning {{-mtocdata option is ignored for globalTwoWithAlias because the variable has an alias}} +int globalTwoWithAlias = 20; + + +int func() { + return a.x+b+c+d+e+f+h[0]; +} + +struct SomeStruct* getAddress(void) { + return &g; +} + +int test() { + return globalOneWithAlias + globalTwoWithAlias + aliasOne + aliasTwo; +} + +long long test2() { + static long long ll = 5; + ll++; + return ll; +} + +// CHECK: @b = global i64 5, align 8 +// CHECK: @c = global i32 0, align 128 +// CHECK: @d = global double 2.500000e+00, align 8 +// CHECK: @e = global i32 10, section "foo", align 4 +// CHECK: @globalOneWithAlias = global i32 10, align 4 +// CHECK: @globalTwoWithAlias = global i32 20, align 4 +// CHECK: @a = global %struct.large_struct zeroinitializer, align 4 +// CHECK: @f = thread_local global i32 0, align 4 +// CHECK: @h = external global [0 x i32], align 4 +// CHECK: @g = external global %struct.SomeStruct, align 1 +// CHECK: @test2.ll = internal global i64 5, align 8 +// CHECK: @aliasOne = alias i32, ptr @globalOneWithAlias +// CHECK: @aliasTwo = alias i32, ptr @globalTwoWithAlias +// CHECK-NOT: attributes #0 = { "toc-data" } diff --git a/clang/test/CodeGen/PowerPC/toc-data-structs-arrays.cpp b/clang/test/CodeGen/PowerPC/toc-data-structs-arrays.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a717995cdceb1989be06ac8a1a072351aff18bb8 --- /dev/null +++ b/clang/test/CodeGen/PowerPC/toc-data-structs-arrays.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 %s -triple powerpc-ibm-aix-xcoff -S -mtocdata=a4,a5,a8,a9,b,c,d,e,v -emit-llvm -o - 2>&1 \ +// RUN: | FileCheck %s -check-prefixes=CHECK32 --match-full-lines +// RUN: %clang_cc1 %s -triple powerpc-ibm-aix-xcoff -S -mtocdata -emit-llvm -o - 2>&1 \ +// RUN: | FileCheck %s -check-prefixes=CHECK32 --match-full-lines + +// RUN: %clang_cc1 %s -triple powerpc64-ibm-aix-xcoff -S -mtocdata=a4,a5,a8,a9,b,c,d,e,v -emit-llvm -o - 2>&1 \ +// RUN: | FileCheck %s -check-prefixes=CHECK64 --match-full-lines +// RUN: %clang_cc1 %s -triple powerpc64-ibm-aix-xcoff -S -mtocdata -emit-llvm -o - 2>&1 \ +// RUN: | FileCheck %s -check-prefixes=CHECK64 --match-full-lines + +struct size4_struct { + int x; +}; + +struct size5_struct { + int x; + char c; +}; + +struct size8_struct { + int x; + short y; + short z; +}; + +struct size9_struct { + int x; + short y; + short z; + char c; +}; + +struct size4_struct a4; +struct size5_struct a5; +struct size8_struct a8; +struct size9_struct a9; + +short b[2]; +short c[3]; +short d[4]; +short e[5]; + +int func_a() { + return a4.x+a5.x+a8.x+a9.x+b[0]+c[0]+d[0]+e[0]; +} + +// CHECK32: @a4 = global %struct.size4_struct zeroinitializer, align 4 #0 +// CHECK32: @a5 = global %struct.size5_struct zeroinitializer, align 4 +// CHECK32: @a8 = global %struct.size8_struct zeroinitializer, align 4 +// CHECK32: @a9 = global %struct.size9_struct zeroinitializer, align 4 +// CHECK32: @b = global [2 x i16] zeroinitializer, align 2 #0 +// CHECK32: @c = global [3 x i16] zeroinitializer, align 2 +// CHECK32: @d = global [4 x i16] zeroinitializer, align 2 +// CHECK32: @e = global [5 x i16] zeroinitializer, align 2 +// CHECK32: attributes #0 = { "toc-data" } + +// CHECK64: @a4 = global %struct.size4_struct zeroinitializer, align 4 #0 +// CHECK64: @a5 = global %struct.size5_struct zeroinitializer, align 4 #0 +// CHECK64: @a8 = global %struct.size8_struct zeroinitializer, align 4 #0 +// CHECK64: @a9 = global %struct.size9_struct zeroinitializer, align 4 +// CHECK64: @b = global [2 x i16] zeroinitializer, align 2 #0 +// CHECK64: @c = global [3 x i16] zeroinitializer, align 2 #0 +// CHECK64: @d = global [4 x i16] zeroinitializer, align 2 #0 +// CHECK64: @e = global [5 x i16] zeroinitializer, align 2 +// CHECK64: attributes #0 = { "toc-data" } diff --git a/clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c b/clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c index 35d6973818d01c0e4134616a2706869505463711..b303d71304bf3ece9b14905e395618055f66a48a 100644 --- a/clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c +++ b/clang/test/CodeGen/RISCV/riscv-func-attr-target-err.c @@ -2,6 +2,28 @@ // RUN: not %clang_cc1 -triple riscv64 -target-feature +zifencei -target-feature +m -target-feature +a \ // RUN: -emit-llvm %s 2>&1 | FileCheck %s +#include <riscv_vector.h> + +void test_builtin() { +// CHECK: error: '__builtin_rvv_vsetvli' needs target feature zve32x + __riscv_vsetvl_e8m8(1); +} + +void test_rvv_i32_type() { +// CHECK: error: RISC-V type 'vint32m1_t' (aka '__rvv_int32m1_t') requires the 'zve32x' extension + vint32m1_t v; +} + +void test_rvv_f32_type() { +// CHECK: error: RISC-V type 'vfloat32m1_t' (aka '__rvv_float32m1_t') requires the 'zve32f' extension + vfloat32m1_t v; +} + +void test_rvv_f64_type() { +// CHECK: error: RISC-V type 'vfloat64m1_t' (aka '__rvv_float64m1_t') requires the 'zve64d' extension + vfloat64m1_t v; +} + // CHECK: error: duplicate 'arch=' in the 'target' attribute string; __attribute__((target("arch=rv64gc;arch=rv64gc_zbb"))) void testMultiArchSelectLast() {} // CHECK: error: duplicate 'cpu=' in the 'target' attribute string; diff --git a/clang/test/CodeGen/RISCV/riscv-func-attr-target.c b/clang/test/CodeGen/RISCV/riscv-func-attr-target.c index f216eaf735b4a8546c95008f4bd573225d1ad984..1f8682179ea813886c1a1d9f82dfa134f1f844d9 100644 --- a/clang/test/CodeGen/RISCV/riscv-func-attr-target.c +++ b/clang/test/CodeGen/RISCV/riscv-func-attr-target.c @@ -4,6 +4,8 @@ // RUN: -target-feature -relax -target-feature -zfa \ // RUN: -emit-llvm %s -o - | FileCheck %s +#include <riscv_vector.h> + // CHECK-LABEL: define dso_local void @testDefault // CHECK-SAME: () #0 { void testDefault() {} @@ -35,6 +37,34 @@ testAttrFullArchAndAttrCpu() {} // CHECK-SAME: () #8 { __attribute__((target("cpu=sifive-u54"))) void testAttrCpuOnly() {} +__attribute__((target("arch=+zve32x"))) +void test_builtin_w_zve32x() { +// CHECK-LABEL: test_builtin_w_zve32x +// CHECK-SAME: #9 + __riscv_vsetvl_e8m8(1); +} + +__attribute__((target("arch=+zve32x"))) +void test_rvv_i32_type_w_zve32x() { +// CHECK-LABEL: test_rvv_i32_type_w_zve32x +// CHECK-SAME: #9 + vint32m1_t v; +} + +__attribute__((target("arch=+zve32f"))) +void test_rvv_f32_type_w_zve32f() { +// CHECK-LABEL: test_rvv_f32_type_w_zve32f +// CHECK-SAME: #11 + vfloat32m1_t v; +} + +__attribute__((target("arch=+zve64d"))) +void test_rvv_f64_type_w_zve64d() { +// CHECK-LABEL: test_rvv_f64_type_w_zve64d +// CHECK-SAME: #12 + vfloat64m1_t v; +} + //. // CHECK: attributes #0 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zifencei,-relax,-zbb,-zfa" } // CHECK: attributes #1 = { {{.*}}"target-cpu"="rocket-rv64" "target-features"="+64bit,+a,+d,+f,+m,+save-restore,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl32b,+zvl64b,-relax,-zbb,-zfa" "tune-cpu"="generic-rv64" } @@ -46,3 +76,6 @@ __attribute__((target("cpu=sifive-u54"))) void testAttrCpuOnly() {} // CHECK: attributes #6 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+m,+save-restore,+zbb,+zifencei,-relax,-zfa" } // CHECK: attributes #7 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+m,+save-restore,{{(-[[:alnum:]-]+)(,-[[:alnum:]-]+)*}}" } // CHECK: attributes #8 = { {{.*}}"target-cpu"="sifive-u54" "target-features"="+64bit,+a,+c,+d,+f,+m,+save-restore,+zicsr,+zifencei,{{(-[[:alnum:]-]+)(,-[[:alnum:]-]+)*}}" } +// CHECK: attributes #9 = { {{.*}}"target-features"="+64bit,+a,+m,+save-restore,+zicsr,+zifencei,+zve32x,+zvl32b,-relax,-zbb,-zfa" } +// CHECK: attributes #11 = { {{.*}}"target-features"="+64bit,+a,+f,+m,+save-restore,+zicsr,+zifencei,+zve32f,+zve32x,+zvl32b,-relax,-zbb,-zfa" } +// CHECK: attributes #12 = { {{.*}}"target-features"="+64bit,+a,+d,+f,+m,+save-restore,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl32b,+zvl64b,-relax,-zbb,-zfa" } diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c new file mode 100644 index 0000000000000000000000000000000000000000..072d8a863d45705b7faacb0fa8f6abecea0655eb --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.c @@ -0,0 +1,34 @@ +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -triple riscv64 -target-feature +v \ +// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s +// RUN: %clang_cc1 -std=c23 -triple riscv64 -target-feature +v \ +// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s + +#include <riscv_vector.h> + +// CHECK-LLVM: call riscv_vector_cc <vscale x 2 x i32> @bar +vint32m1_t __attribute__((riscv_vector_cc)) bar(vint32m1_t input); +vint32m1_t test_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t val = __riscv_vle32_v_i32m1(base, vl); + vint32m1_t ret = bar(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} + +// CHECK-LLVM: call riscv_vector_cc <vscale x 2 x i32> @bar +[[riscv::vector_cc]] vint32m1_t bar(vint32m1_t input); +vint32m1_t test_vector_cc_attr2(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t val = __riscv_vle32_v_i32m1(base, vl); + vint32m1_t ret = bar(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} + +// CHECK-LLVM: call <vscale x 2 x i32> @baz +vint32m1_t baz(vint32m1_t input); +vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t val = __riscv_vle32_v_i32m1(base, vl); + vint32m1_t ret = baz(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c01aeb21f675714d328f375853671099e1789371 --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv-llvm-ir.cpp @@ -0,0 +1,32 @@ +// REQUIRES: riscv-registered-target +// RUN: %clang_cc1 -std=c++11 -triple riscv64 -target-feature +v \ +// RUN: -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-LLVM %s + +#include <riscv_vector.h> + +// CHECK-LLVM: call riscv_vector_cc <vscale x 2 x i32> @_Z3baru15__rvv_int32m1_t +vint32m1_t __attribute__((riscv_vector_cc)) bar(vint32m1_t input); +vint32m1_t test_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t val = __riscv_vle32_v_i32m1(base, vl); + vint32m1_t ret = bar(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} + +// CHECK-LLVM: call riscv_vector_cc <vscale x 2 x i32> @_Z3baru15__rvv_int32m1_t +[[riscv::vector_cc]] vint32m1_t bar(vint32m1_t input); +vint32m1_t test_vector_cc_attr2(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t val = __riscv_vle32_v_i32m1(base, vl); + vint32m1_t ret = bar(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} + +// CHECK-LLVM: call <vscale x 2 x i32> @_Z3bazu15__rvv_int32m1_t +vint32m1_t baz(vint32m1_t input); +vint32m1_t test_no_vector_cc_attr(vint32m1_t input, int32_t *base, size_t vl) { + vint32m1_t val = __riscv_vle32_v_i32m1(base, vl); + vint32m1_t ret = baz(input); + __riscv_vse32_v_i32m1(base, val, vl); + return ret; +} diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv.c b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.c new file mode 100644 index 0000000000000000000000000000000000000000..5c35901799b4276b8959003d904d5b210519645f --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 %s -std=c23 -triple riscv64 -target-feature +v -verify + +__attribute__((riscv_vector_cc)) int var; // expected-warning {{'riscv_vector_cc' only applies to function types; type here is 'int'}} + +__attribute__((riscv_vector_cc)) void func(); +__attribute__((riscv_vector_cc(1))) void func_invalid(); // expected-error {{'riscv_vector_cc' attribute takes no arguments}} + +void test_no_attribute(int); // expected-note {{previous declaration is here}} +void __attribute__((riscv_vector_cc)) test_no_attribute(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}} + +[[riscv::vector_cc]] int var2; // expected-warning {{'vector_cc' only applies to function types; type here is 'int'}} + +[[riscv::vector_cc]] void func2(); +[[riscv::vector_cc(1)]] void func_invalid2(); // expected-error {{'vector_cc' attribute takes no arguments}} + +void test_no_attribute2(int); // expected-note {{previous declaration is here}} +[[riscv::vector_cc]] void test_no_attribute2(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}} diff --git a/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp new file mode 100644 index 0000000000000000000000000000000000000000..264bb7d9ad7c00172a2c3dc9d5dcfa535054fe64 --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-vector-callingconv.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 %s -triple riscv64 -target-feature +v -verify + +__attribute__((riscv_vector_cc)) int var; // expected-warning {{'riscv_vector_cc' only applies to function types; type here is 'int'}} + +__attribute__((riscv_vector_cc)) void func(); +__attribute__((riscv_vector_cc(1))) void func_invalid(); // expected-error {{'riscv_vector_cc' attribute takes no arguments}} + +void test_no_attribute(int); // expected-note {{previous declaration is here}} +void __attribute__((riscv_vector_cc)) test_no_attribute(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}} + +class test_cc { + __attribute__((riscv_vector_cc)) void member_func(); +}; + +void test_lambda() { + __attribute__((riscv_vector_cc)) auto lambda = []() { // expected-warning {{'riscv_vector_cc' only applies to function types; type here is 'auto'}} + }; +} + +[[riscv::vector_cc]] int var2; // expected-warning {{'vector_cc' only applies to function types; type here is 'int'}} + +[[riscv::vector_cc]] void func2(); +[[riscv::vector_cc(1)]] void func_invalid2(); // expected-error {{'vector_cc' attribute takes no arguments}} + +void test_no_attribute2(int); // expected-note {{previous declaration is here}} +[[riscv::vector_cc]] void test_no_attribute2(int x) { } // expected-error {{function declared 'riscv_vector_cc' here was previously declared without calling convention}} + +class test_cc2 { + [[riscv::vector_cc]] void member_func(); +}; + +void test_lambda2() { + [[riscv::vector_cc]] auto lambda = []() { // expected-warning {{'vector_cc' only applies to function types; type here is 'auto'}} + }; +} diff --git a/clang/test/CodeGen/RISCV/riscv32-vararg.c b/clang/test/CodeGen/RISCV/riscv32-vararg.c index 1c4e41f2f54c8f77d632f5a251c81691bb5a67b2..00e04eb894675eb68b2174a66a276c2f1ca9355d 100644 --- a/clang/test/CodeGen/RISCV/riscv32-vararg.c +++ b/clang/test/CodeGen/RISCV/riscv32-vararg.c @@ -80,13 +80,13 @@ void f_va_caller(void) { // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[V:%.*]] = alloca i32, align 4 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 4 // CHECK-NEXT: store i32 [[TMP0]], ptr [[V]], align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[V]], align 4 // CHECK-NEXT: ret i32 [[TMP1]] // @@ -111,7 +111,7 @@ int f_va_1(char *fmt, ...) { // CHECK-ILP32F-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-ILP32F-NEXT: [[V:%.*]] = alloca double, align 8 // CHECK-ILP32F-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32F-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32F-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32F-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32F-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7 // CHECK-ILP32F-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8) @@ -119,7 +119,7 @@ int f_va_1(char *fmt, ...) { // CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-ILP32F-NEXT: [[TMP1:%.*]] = load double, ptr [[ARGP_CUR_ALIGNED]], align 8 // CHECK-ILP32F-NEXT: store double [[TMP1]], ptr [[V]], align 8 -// CHECK-ILP32F-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32F-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32F-NEXT: [[TMP2:%.*]] = load double, ptr [[V]], align 8 // CHECK-ILP32F-NEXT: ret double [[TMP2]] // @@ -130,7 +130,7 @@ int f_va_1(char *fmt, ...) { // CHECK-ILP32D-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-ILP32D-NEXT: [[V:%.*]] = alloca double, align 8 // CHECK-ILP32D-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32D-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32D-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32D-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32D-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7 // CHECK-ILP32D-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8) @@ -138,7 +138,7 @@ int f_va_1(char *fmt, ...) { // CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-ILP32D-NEXT: [[TMP1:%.*]] = load double, ptr [[ARGP_CUR_ALIGNED]], align 8 // CHECK-ILP32D-NEXT: store double [[TMP1]], ptr [[V]], align 8 -// CHECK-ILP32D-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32D-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32D-NEXT: [[TMP2:%.*]] = load double, ptr [[V]], align 8 // CHECK-ILP32D-NEXT: ret double [[TMP2]] // @@ -149,13 +149,13 @@ int f_va_1(char *fmt, ...) { // CHECK-ILP32E-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-ILP32E-NEXT: [[V:%.*]] = alloca double, align 8 // CHECK-ILP32E-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32E-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32E-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32E-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32E-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8 // CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-ILP32E-NEXT: [[TMP0:%.*]] = load double, ptr [[ARGP_CUR]], align 4 // CHECK-ILP32E-NEXT: store double [[TMP0]], ptr [[V]], align 8 -// CHECK-ILP32E-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32E-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32E-NEXT: [[TMP1:%.*]] = load double, ptr [[V]], align 8 // CHECK-ILP32E-NEXT: ret double [[TMP1]] // @@ -180,7 +180,7 @@ double f_va_2(char *fmt, ...) { // CHECK-ILP32F-NEXT: [[W:%.*]] = alloca i32, align 4 // CHECK-ILP32F-NEXT: [[X:%.*]] = alloca double, align 8 // CHECK-ILP32F-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32F-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32F-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32F-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32F-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7 // CHECK-ILP32F-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8) @@ -200,7 +200,7 @@ double f_va_2(char *fmt, ...) { // CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 4 // CHECK-ILP32F-NEXT: [[TMP4:%.*]] = load double, ptr [[ARGP_CUR3_ALIGNED]], align 8 // CHECK-ILP32F-NEXT: store double [[TMP4]], ptr [[X]], align 8 -// CHECK-ILP32F-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32F-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32F-NEXT: [[TMP5:%.*]] = load double, ptr [[V]], align 8 // CHECK-ILP32F-NEXT: [[TMP6:%.*]] = load double, ptr [[X]], align 8 // CHECK-ILP32F-NEXT: [[ADD:%.*]] = fadd double [[TMP5]], [[TMP6]] @@ -215,7 +215,7 @@ double f_va_2(char *fmt, ...) { // CHECK-ILP32D-NEXT: [[W:%.*]] = alloca i32, align 4 // CHECK-ILP32D-NEXT: [[X:%.*]] = alloca double, align 8 // CHECK-ILP32D-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32D-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32D-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32D-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32D-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7 // CHECK-ILP32D-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8) @@ -235,7 +235,7 @@ double f_va_2(char *fmt, ...) { // CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 4 // CHECK-ILP32D-NEXT: [[TMP4:%.*]] = load double, ptr [[ARGP_CUR3_ALIGNED]], align 8 // CHECK-ILP32D-NEXT: store double [[TMP4]], ptr [[X]], align 8 -// CHECK-ILP32D-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32D-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32D-NEXT: [[TMP5:%.*]] = load double, ptr [[V]], align 8 // CHECK-ILP32D-NEXT: [[TMP6:%.*]] = load double, ptr [[X]], align 8 // CHECK-ILP32D-NEXT: [[ADD:%.*]] = fadd double [[TMP5]], [[TMP6]] @@ -250,7 +250,7 @@ double f_va_2(char *fmt, ...) { // CHECK-ILP32E-NEXT: [[W:%.*]] = alloca i32, align 4 // CHECK-ILP32E-NEXT: [[X:%.*]] = alloca double, align 8 // CHECK-ILP32E-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32E-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32E-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32E-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32E-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 8 // CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -266,7 +266,7 @@ double f_va_2(char *fmt, ...) { // CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 4 // CHECK-ILP32E-NEXT: [[TMP2:%.*]] = load double, ptr [[ARGP_CUR3]], align 4 // CHECK-ILP32E-NEXT: store double [[TMP2]], ptr [[X]], align 8 -// CHECK-ILP32E-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32E-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32E-NEXT: [[TMP3:%.*]] = load double, ptr [[V]], align 8 // CHECK-ILP32E-NEXT: [[TMP4:%.*]] = load double, ptr [[X]], align 8 // CHECK-ILP32E-NEXT: [[ADD:%.*]] = fadd double [[TMP3]], [[TMP4]] @@ -296,7 +296,7 @@ double f_va_3(char *fmt, ...) { // CHECK-ILP32F-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4 // CHECK-ILP32F-NEXT: [[RET:%.*]] = alloca i32, align 4 // CHECK-ILP32F-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32F-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32F-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32F-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32F-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -321,7 +321,7 @@ double f_va_3(char *fmt, ...) { // CHECK-ILP32F-NEXT: store ptr [[ARGP_NEXT8]], ptr [[VA]], align 4 // CHECK-ILP32F-NEXT: [[TMP3:%.*]] = load ptr, ptr [[ARGP_CUR7]], align 4 // CHECK-ILP32F-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[LS]], ptr align 4 [[TMP3]], i32 16, i1 false) -// CHECK-ILP32F-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32F-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32F-NEXT: [[TMP4:%.*]] = load i32, ptr [[V]], align 4 // CHECK-ILP32F-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP4]] to fp128 // CHECK-ILP32F-NEXT: [[TMP5:%.*]] = load fp128, ptr [[LD]], align 16 @@ -384,7 +384,7 @@ double f_va_3(char *fmt, ...) { // CHECK-ILP32D-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4 // CHECK-ILP32D-NEXT: [[RET:%.*]] = alloca i32, align 4 // CHECK-ILP32D-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32D-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32D-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32D-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32D-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -409,7 +409,7 @@ double f_va_3(char *fmt, ...) { // CHECK-ILP32D-NEXT: store ptr [[ARGP_NEXT8]], ptr [[VA]], align 4 // CHECK-ILP32D-NEXT: [[TMP3:%.*]] = load ptr, ptr [[ARGP_CUR7]], align 4 // CHECK-ILP32D-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[LS]], ptr align 4 [[TMP3]], i32 16, i1 false) -// CHECK-ILP32D-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32D-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32D-NEXT: [[TMP4:%.*]] = load i32, ptr [[V]], align 4 // CHECK-ILP32D-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP4]] to fp128 // CHECK-ILP32D-NEXT: [[TMP5:%.*]] = load fp128, ptr [[LD]], align 16 @@ -472,7 +472,7 @@ double f_va_3(char *fmt, ...) { // CHECK-ILP32E-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 4 // CHECK-ILP32E-NEXT: [[RET:%.*]] = alloca i32, align 4 // CHECK-ILP32E-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-ILP32E-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-ILP32E-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-ILP32E-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-ILP32E-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -497,7 +497,7 @@ double f_va_3(char *fmt, ...) { // CHECK-ILP32E-NEXT: store ptr [[ARGP_NEXT8]], ptr [[VA]], align 4 // CHECK-ILP32E-NEXT: [[TMP3:%.*]] = load ptr, ptr [[ARGP_CUR7]], align 4 // CHECK-ILP32E-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[LS]], ptr align 4 [[TMP3]], i32 16, i1 false) -// CHECK-ILP32E-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-ILP32E-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-ILP32E-NEXT: [[TMP4:%.*]] = load i32, ptr [[V]], align 4 // CHECK-ILP32E-NEXT: [[CONV:%.*]] = sitofp i32 [[TMP4]] to fp128 // CHECK-ILP32E-NEXT: [[TMP5:%.*]] = load fp128, ptr [[LD]], align 16 diff --git a/clang/test/CodeGen/RISCV/riscv64-vararg.c b/clang/test/CodeGen/RISCV/riscv64-vararg.c index 634cde61320cb61e894ba386ba8813213371677a..efdffa2687e624125bcd882ff3b56c0cfccb3580 100644 --- a/clang/test/CodeGen/RISCV/riscv64-vararg.c +++ b/clang/test/CodeGen/RISCV/riscv64-vararg.c @@ -135,13 +135,13 @@ void f_va_caller(void) { // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[V:%.*]] = alloca i32, align 4 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 8 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 8 // CHECK-NEXT: store i32 [[TMP0]], ptr [[V]], align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[V]], align 4 // CHECK-NEXT: ret i32 [[TMP1]] // @@ -166,7 +166,7 @@ int f_va_1(char *fmt, ...) { // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[V:%.*]] = alloca fp128, align 16 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 8 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15 // CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP0]], i64 -16) @@ -174,7 +174,7 @@ int f_va_1(char *fmt, ...) { // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = load fp128, ptr [[ARGP_CUR_ALIGNED]], align 16 // CHECK-NEXT: store fp128 [[TMP1]], ptr [[V]], align 16 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP2:%.*]] = load fp128, ptr [[V]], align 16 // CHECK-NEXT: ret fp128 [[TMP2]] // @@ -199,7 +199,7 @@ long double f_va_2(char *fmt, ...) { // CHECK-NEXT: [[W:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[X:%.*]] = alloca fp128, align 16 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 8 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15 // CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP0]], i64 -16) @@ -219,7 +219,7 @@ long double f_va_2(char *fmt, ...) { // CHECK-NEXT: store ptr [[ARGP_NEXT4]], ptr [[VA]], align 8 // CHECK-NEXT: [[TMP4:%.*]] = load fp128, ptr [[ARGP_CUR3_ALIGNED]], align 16 // CHECK-NEXT: store fp128 [[TMP4]], ptr [[X]], align 16 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP5:%.*]] = load fp128, ptr [[V]], align 16 // CHECK-NEXT: [[TMP6:%.*]] = load fp128, ptr [[X]], align 16 // CHECK-NEXT: [[ADD:%.*]] = fadd fp128 [[TMP5]], [[TMP6]] @@ -248,7 +248,7 @@ long double f_va_3(char *fmt, ...) { // CHECK-NEXT: [[LS:%.*]] = alloca [[STRUCT_LARGE:%.*]], align 8 // CHECK-NEXT: [[RET:%.*]] = alloca i32, align 4 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 8 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 8 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 8 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 8 @@ -267,7 +267,7 @@ long double f_va_3(char *fmt, ...) { // CHECK-NEXT: store ptr [[ARGP_NEXT6]], ptr [[VA]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ARGP_CUR5]], align 8 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[LS]], ptr align 8 [[TMP1]], i64 32, i1 false) -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_TINY]], ptr [[TS]], i32 0, i32 0 // CHECK-NEXT: [[TMP2:%.*]] = load i16, ptr [[A]], align 2 // CHECK-NEXT: [[CONV:%.*]] = zext i16 [[TMP2]] to i64 diff --git a/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv32-zbb-error.c b/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv32-zbb-error.c index ecf090a128aac702d3ea6cb25fc5c4c1ed0827ab..bad68504fab055719a27dc19e6260952a5c67252 100644 --- a/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv32-zbb-error.c +++ b/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv32-zbb-error.c @@ -1,6 +1,6 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -triple riscv32 -target-feature +zbb -verify %s -o - +// RUN: %clang_cc1 -triple riscv32 -target-feature +zbb -S -verify %s -o - unsigned int orc_b_64(unsigned int a) { - return __builtin_riscv_orc_b_64(a); // expected-error {{builtin requires: 'RV64'}} + return __builtin_riscv_orc_b_64(a); // expected-error {{'__builtin_riscv_orc_b_64' needs target feature zbb,64bit}} } diff --git a/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv64-zbkb-error.c b/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv64-zbkb-error.c index d2e3e76043aef16304ff7ad0ad73709182d9a55c..a256bf75b031c6ddc13204bee185d5b087a4b03c 100644 --- a/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv64-zbkb-error.c +++ b/clang/test/CodeGen/RISCV/rvb-intrinsics/riscv64-zbkb-error.c @@ -1,14 +1,10 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py -// RUN: %clang_cc1 -triple riscv64 -target-feature +zbkb -verify %s -o - +// RUN: %clang_cc1 -triple riscv64 -target-feature +zbkb -S -verify %s -o - #include <stdint.h> -uint32_t zip(uint32_t rs1) +uint32_t zip_unzip(uint32_t rs1) { - return __builtin_riscv_zip_32(rs1); // expected-error {{builtin requires: 'RV32'}} -} - -uint32_t unzip(uint32_t rs1) -{ - return __builtin_riscv_unzip_32(rs1); // expected-error {{builtin requires: 'RV32'}} + (void)__builtin_riscv_zip_32(rs1); // expected-error {{'__builtin_riscv_zip_32' needs target feature zbkb,32bit}} + return __builtin_riscv_unzip_32(rs1); // expected-error {{'__builtin_riscv_unzip_32' needs target feature zbkb,32bit}} } diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/rvv-error.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/rvv-error.c index 6ec9b057997690a919a39da38a85e31372af0ffe..ecb6c5f27025779aafbdbd96606137f34cb2a60f 100644 --- a/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/rvv-error.c +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/rvv-error.c @@ -11,7 +11,7 @@ // CHECK-RV64V-NEXT: ret i32 [[CONV]] // -// CHECK-RV64-ERR: error: builtin requires at least one of the following extensions: 'Zve32x' +// CHECK-RV64-ERR: error: '__builtin_rvv_vsetvli' needs target feature zve32x int test() { return __builtin_rvv_vsetvli(1, 0, 0); diff --git a/clang/test/CodeGen/SystemZ/systemz-ppa2.c b/clang/test/CodeGen/SystemZ/systemz-ppa2.c index 0ff4cba5edfb6c68b32a16ed7e071ccd425360ad..26b068ff03d5397d580046d1febfc7976d652582 100644 --- a/clang/test/CodeGen/SystemZ/systemz-ppa2.c +++ b/clang/test/CodeGen/SystemZ/systemz-ppa2.c @@ -13,14 +13,14 @@ // REQUIRES: systemz-registered-target // RUN: %clang_cc1 -triple s390x-ibm-zos -xc -S -o - %s | FileCheck %s --check-prefix CHECK-C -// CHECK-C: [[PPA2:(.L)|(@@)PPA2]]: +// CHECK-C: [[PPA2:(.L)|(L#)PPA2]]: // CHECK-C-NEXT: .byte 3{{[[:space:]]*}}.byte 0 // CHECK-C-NEXT: .byte 34{{$}} // CHECK-C-NEXT: .byte {{4}} // CHECK-C-NEXT: .long {{(CELQSTRT)}}-[[PPA2]] // RUN: %clang_cc1 -triple s390x-ibm-zos -xc++ -S -o - %s | FileCheck %s --check-prefix CHECK-CXX -// CHECK-CXX: [[PPA2:(.L)|(@@)PPA2]]: +// CHECK-CXX: [[PPA2:(.L)|(L#)PPA2]]: // CHECK-CXX-NEXT: .byte 3{{[[:space:]]*}}.byte 1 // CHECK-CXX-NEXT: .byte 34{{$}} // CHECK-CXX-NEXT: .byte {{4}} diff --git a/clang/test/CodeGen/WebAssembly/wasm-varargs.c b/clang/test/CodeGen/WebAssembly/wasm-varargs.c index c475de19ae4487830f9f8f76d2cea5906819fd35..e794857304e1c9eab782ab9c817b0810f73b31cc 100644 --- a/clang/test/CodeGen/WebAssembly/wasm-varargs.c +++ b/clang/test/CodeGen/WebAssembly/wasm-varargs.c @@ -10,13 +10,13 @@ // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[V:%.*]] = alloca i32, align 4 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 4 // CHECK-NEXT: store i32 [[TMP0]], ptr [[V]], align 4 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[V]], align 4 // CHECK-NEXT: ret i32 [[TMP1]] // @@ -38,7 +38,7 @@ int test_i32(char *fmt, ...) { // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[V:%.*]] = alloca i64, align 8 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7 // CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i32(ptr [[TMP0]], i32 -8) @@ -46,7 +46,7 @@ int test_i32(char *fmt, ...) { // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[ARGP_CUR_ALIGNED]], align 8 // CHECK-NEXT: store i64 [[TMP1]], ptr [[V]], align 8 -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[V]], align 8 // CHECK-NEXT: ret i64 [[TMP2]] // @@ -73,13 +73,13 @@ struct S { // CHECK-NEXT: [[FMT_ADDR:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 4 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARGP_CUR]], align 4 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AGG_RESULT]], ptr align 4 [[TMP0]], i32 12, i1 false) -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: ret void // struct S test_struct(char *fmt, ...) { @@ -102,7 +102,7 @@ struct Z {}; // CHECK-NEXT: [[VA:%.*]] = alloca ptr, align 4 // CHECK-NEXT: [[U:%.*]] = alloca [[STRUCT_Z:%.*]], align 1 // CHECK-NEXT: store ptr [[FMT]], ptr [[FMT_ADDR]], align 4 -// CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]) // CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VA]], align 4 // CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 0 // CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VA]], align 4 @@ -112,7 +112,7 @@ struct Z {}; // CHECK-NEXT: store ptr [[ARGP_NEXT2]], ptr [[VA]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[ARGP_CUR1]], align 4 // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[AGG_RESULT]], ptr align 4 [[TMP0]], i32 12, i1 false) -// CHECK-NEXT: call void @llvm.va_end(ptr [[VA]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VA]]) // CHECK-NEXT: ret void // struct S test_empty_struct(char *fmt, ...) { diff --git a/clang/test/CodeGen/X86/avx-shuffle-builtins.c b/clang/test/CodeGen/X86/avx-shuffle-builtins.c index 9109247e534f4f0e1146ac5a95a9c66b9cd4739f..49a56e73230d7d4fc0d73fd30d0d810c1d2ba34c 100644 --- a/clang/test/CodeGen/X86/avx-shuffle-builtins.c +++ b/clang/test/CodeGen/X86/avx-shuffle-builtins.c @@ -1,3 +1,4 @@ +// REQUIRES: x86-registered-target // RUN: %clang_cc1 -ffreestanding %s -O3 -triple=x86_64-apple-darwin -target-feature +avx -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,X64 // RUN: %clang_cc1 -ffreestanding %s -O3 -triple=i386-apple-darwin -target-feature +avx -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,X86 // FIXME: This is testing optimized generation of shuffle instructions and should be fixed. @@ -60,7 +61,8 @@ __m256 test_mm256_permute2f128_ps(__m256 a, __m256 b) { __m256i test_mm256_permute2f128_si256(__m256i a, __m256i b) { // CHECK-LABEL: test_mm256_permute2f128_si256 - // CHECK: shufflevector{{.*}} <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11> + // X64: shufflevector{{.*}}<i32 0, i32 1, i32 4, i32 5> + // X86: shufflevector{{.*}}<i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11> return _mm256_permute2f128_si256(a, b, 0x20); } @@ -104,7 +106,8 @@ __m256d test_mm256_insertf128_pd_0(__m256d a, __m128d b) { __m256i test_mm256_insertf128_si256_0(__m256i a, __m128i b) { // CHECK-LABEL: test_mm256_insertf128_si256_0 - // CHECK: shufflevector{{.*}}<i32 0, i32 1, i32 2, i32 3, i32 12, i32 13, i32 14, i32 15> + // X64: shufflevector{{.*}}<i32 0, i32 1, i32 6, i32 7> + // X86: shufflevector{{.*}}<i32 0, i32 1, i32 2, i32 3, i32 12, i32 13, i32 14, i32 15> return _mm256_insertf128_si256(a, b, 0); } @@ -122,7 +125,8 @@ __m256d test_mm256_insertf128_pd_1(__m256d a, __m128d b) { __m256i test_mm256_insertf128_si256_1(__m256i a, __m128i b) { // CHECK-LABEL: test_mm256_insertf128_si256_1 - // CHECK: shufflevector{{.*}}<i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11> + // X64: shufflevector{{.*}}<i32 0, i32 1, i32 4, i32 5> + // X86: shufflevector{{.*}}<i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11> return _mm256_insertf128_si256(a, b, 1); } diff --git a/clang/test/CodeGen/X86/cx-complex-range.c b/clang/test/CodeGen/X86/cx-complex-range.c new file mode 100644 index 0000000000000000000000000000000000000000..fa46576266a205b1ec50346c41158ee652704a5c --- /dev/null +++ b/clang/test/CodeGen/X86/cx-complex-range.c @@ -0,0 +1,1425 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -o - | FileCheck %s --check-prefix=FULL + +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -complex-range=basic -o - | FileCheck %s --check-prefix=BASIC + +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -fno-cx-limited-range -o - | FileCheck %s --check-prefix=FULL + +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -complex-range=improved -o - | FileCheck %s --check-prefix=IMPRVD + +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -complex-range=promoted -o - | FileCheck %s --check-prefix=PRMTD + +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -complex-range=full -o - | FileCheck %s --check-prefix=FULL + +// RUN: %clang_cc1 -triple x86_64-windows-pc -complex-range=promoted \ +// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=X86WINPRMTD + +// Fast math +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu \ +// RUN: -ffast-math -complex-range=basic -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=BASIC_FAST + +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu \ +// RUN: -ffast-math -complex-range=full -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=FULL_FAST + +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -fno-cx-fortran-rules -o - | FileCheck %s --check-prefix=FULL + +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu \ +// RUN: -ffast-math -complex-range=improved -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=IMPRVD_FAST + +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu \ +// RUN: -ffast-math -complex-range=promoted -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=PRMTD_FAST + +// FULL-LABEL: define dso_local <2 x half> @divf16( +// FULL-SAME: <2 x half> noundef [[A_COERCE:%.*]], <2 x half> noundef [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// FULL-NEXT: entry: +// FULL-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// FULL-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// FULL-NEXT: [[B:%.*]] = alloca { half, half }, align 2 +// FULL-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4 +// FULL-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// FULL-NEXT: store <2 x half> [[B_COERCE]], ptr [[B]], align 2 +// FULL-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// FULL-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// FULL-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// FULL-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// FULL-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float +// FULL-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// FULL-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 0 +// FULL-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 +// FULL-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 1 +// FULL-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 +// FULL-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float +// FULL-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// FULL-NEXT: [[CALL:%.*]] = call <2 x float> @__divsc3(float noundef [[EXT]], float noundef [[EXT1]], float noundef [[EXT2]], float noundef [[EXT3]]) #[[ATTR1:[0-9]+]] +// FULL-NEXT: store <2 x float> [[CALL]], ptr [[COERCE]], align 4 +// FULL-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 0 +// FULL-NEXT: [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4 +// FULL-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 1 +// FULL-NEXT: [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4 +// FULL-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[COERCE_REAL]] to half +// FULL-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[COERCE_IMAG]] to half +// FULL-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// FULL-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// FULL-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// FULL-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 +// FULL-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// FULL-NEXT: ret <2 x half> [[TMP0]] +// +// BASIC-LABEL: define dso_local <2 x half> @divf16( +// BASIC-SAME: <2 x half> noundef [[A_COERCE:%.*]], <2 x half> noundef [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// BASIC-NEXT: entry: +// BASIC-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// BASIC-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// BASIC-NEXT: [[B:%.*]] = alloca { half, half }, align 2 +// BASIC-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// BASIC-NEXT: store <2 x half> [[B_COERCE]], ptr [[B]], align 2 +// BASIC-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// BASIC-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// BASIC-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// BASIC-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// BASIC-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float +// BASIC-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// BASIC-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 0 +// BASIC-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 +// BASIC-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 1 +// BASIC-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 +// BASIC-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float +// BASIC-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// BASIC-NEXT: [[TMP0:%.*]] = fmul float [[EXT]], [[EXT2]] +// BASIC-NEXT: [[TMP1:%.*]] = fmul float [[EXT1]], [[EXT3]] +// BASIC-NEXT: [[TMP2:%.*]] = fadd float [[TMP0]], [[TMP1]] +// BASIC-NEXT: [[TMP3:%.*]] = fmul float [[EXT2]], [[EXT2]] +// BASIC-NEXT: [[TMP4:%.*]] = fmul float [[EXT3]], [[EXT3]] +// BASIC-NEXT: [[TMP5:%.*]] = fadd float [[TMP3]], [[TMP4]] +// BASIC-NEXT: [[TMP6:%.*]] = fmul float [[EXT1]], [[EXT2]] +// BASIC-NEXT: [[TMP7:%.*]] = fmul float [[EXT]], [[EXT3]] +// BASIC-NEXT: [[TMP8:%.*]] = fsub float [[TMP6]], [[TMP7]] +// BASIC-NEXT: [[TMP9:%.*]] = fdiv float [[TMP2]], [[TMP5]] +// BASIC-NEXT: [[TMP10:%.*]] = fdiv float [[TMP8]], [[TMP5]] +// BASIC-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP9]] to half +// BASIC-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[TMP10]] to half +// BASIC-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// BASIC-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 +// BASIC-NEXT: [[TMP11:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// BASIC-NEXT: ret <2 x half> [[TMP11]] +// +// IMPRVD-LABEL: define dso_local <2 x half> @divf16( +// IMPRVD-SAME: <2 x half> noundef [[A_COERCE:%.*]], <2 x half> noundef [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// IMPRVD-NEXT: entry: +// IMPRVD-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// IMPRVD-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// IMPRVD-NEXT: [[B:%.*]] = alloca { half, half }, align 2 +// IMPRVD-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// IMPRVD-NEXT: store <2 x half> [[B_COERCE]], ptr [[B]], align 2 +// IMPRVD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// IMPRVD-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// IMPRVD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// IMPRVD-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// IMPRVD-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float +// IMPRVD-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// IMPRVD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 0 +// IMPRVD-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 +// IMPRVD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 1 +// IMPRVD-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 +// IMPRVD-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float +// IMPRVD-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// IMPRVD-NEXT: [[TMP0:%.*]] = call float @llvm.fabs.f32(float [[EXT2]]) +// IMPRVD-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[EXT3]]) +// IMPRVD-NEXT: [[ABS_CMP:%.*]] = fcmp ugt float [[TMP0]], [[TMP1]] +// IMPRVD-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// IMPRVD: abs_rhsr_greater_or_equal_abs_rhsi: +// IMPRVD-NEXT: [[TMP2:%.*]] = fdiv float [[EXT3]], [[EXT2]] +// IMPRVD-NEXT: [[TMP3:%.*]] = fmul float [[TMP2]], [[EXT3]] +// IMPRVD-NEXT: [[TMP4:%.*]] = fadd float [[EXT2]], [[TMP3]] +// IMPRVD-NEXT: [[TMP5:%.*]] = fmul float [[EXT1]], [[TMP2]] +// IMPRVD-NEXT: [[TMP6:%.*]] = fadd float [[EXT]], [[TMP5]] +// IMPRVD-NEXT: [[TMP7:%.*]] = fdiv float [[TMP6]], [[TMP4]] +// IMPRVD-NEXT: [[TMP8:%.*]] = fmul float [[EXT]], [[TMP2]] +// IMPRVD-NEXT: [[TMP9:%.*]] = fsub float [[EXT1]], [[TMP8]] +// IMPRVD-NEXT: [[TMP10:%.*]] = fdiv float [[TMP9]], [[TMP4]] +// IMPRVD-NEXT: br label [[COMPLEX_DIV:%.*]] +// IMPRVD: abs_rhsr_less_than_abs_rhsi: +// IMPRVD-NEXT: [[TMP11:%.*]] = fdiv float [[EXT2]], [[EXT3]] +// IMPRVD-NEXT: [[TMP12:%.*]] = fmul float [[TMP11]], [[EXT2]] +// IMPRVD-NEXT: [[TMP13:%.*]] = fadd float [[EXT3]], [[TMP12]] +// IMPRVD-NEXT: [[TMP14:%.*]] = fmul float [[EXT]], [[TMP11]] +// IMPRVD-NEXT: [[TMP15:%.*]] = fadd float [[TMP14]], [[EXT1]] +// IMPRVD-NEXT: [[TMP16:%.*]] = fdiv float [[TMP15]], [[TMP13]] +// IMPRVD-NEXT: [[TMP17:%.*]] = fmul float [[EXT1]], [[TMP11]] +// IMPRVD-NEXT: [[TMP18:%.*]] = fsub float [[TMP17]], [[EXT]] +// IMPRVD-NEXT: [[TMP19:%.*]] = fdiv float [[TMP18]], [[TMP13]] +// IMPRVD-NEXT: br label [[COMPLEX_DIV]] +// IMPRVD: complex_div: +// IMPRVD-NEXT: [[TMP20:%.*]] = phi float [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD-NEXT: [[TMP21:%.*]] = phi float [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP20]] to half +// IMPRVD-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[TMP21]] to half +// IMPRVD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// IMPRVD-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 +// IMPRVD-NEXT: [[TMP22:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// IMPRVD-NEXT: ret <2 x half> [[TMP22]] +// +// PRMTD-LABEL: define dso_local <2 x half> @divf16( +// PRMTD-SAME: <2 x half> noundef [[A_COERCE:%.*]], <2 x half> noundef [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// PRMTD-NEXT: entry: +// PRMTD-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// PRMTD-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// PRMTD-NEXT: [[B:%.*]] = alloca { half, half }, align 2 +// PRMTD-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// PRMTD-NEXT: store <2 x half> [[B_COERCE]], ptr [[B]], align 2 +// PRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// PRMTD-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// PRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// PRMTD-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// PRMTD-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float +// PRMTD-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// PRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 0 +// PRMTD-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 +// PRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 1 +// PRMTD-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 +// PRMTD-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float +// PRMTD-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// PRMTD-NEXT: [[TMP0:%.*]] = fmul float [[EXT]], [[EXT2]] +// PRMTD-NEXT: [[TMP1:%.*]] = fmul float [[EXT1]], [[EXT3]] +// PRMTD-NEXT: [[TMP2:%.*]] = fadd float [[TMP0]], [[TMP1]] +// PRMTD-NEXT: [[TMP3:%.*]] = fmul float [[EXT2]], [[EXT2]] +// PRMTD-NEXT: [[TMP4:%.*]] = fmul float [[EXT3]], [[EXT3]] +// PRMTD-NEXT: [[TMP5:%.*]] = fadd float [[TMP3]], [[TMP4]] +// PRMTD-NEXT: [[TMP6:%.*]] = fmul float [[EXT1]], [[EXT2]] +// PRMTD-NEXT: [[TMP7:%.*]] = fmul float [[EXT]], [[EXT3]] +// PRMTD-NEXT: [[TMP8:%.*]] = fsub float [[TMP6]], [[TMP7]] +// PRMTD-NEXT: [[TMP9:%.*]] = fdiv float [[TMP2]], [[TMP5]] +// PRMTD-NEXT: [[TMP10:%.*]] = fdiv float [[TMP8]], [[TMP5]] +// PRMTD-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP9]] to half +// PRMTD-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[TMP10]] to half +// PRMTD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// PRMTD-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 +// PRMTD-NEXT: [[TMP11:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// PRMTD-NEXT: ret <2 x half> [[TMP11]] +// +// X86WINPRMTD-LABEL: define dso_local i32 @divf16( +// X86WINPRMTD-SAME: i32 noundef [[A_COERCE:%.*]], i32 noundef [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// X86WINPRMTD-NEXT: entry: +// X86WINPRMTD-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// X86WINPRMTD-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// X86WINPRMTD-NEXT: [[B:%.*]] = alloca { half, half }, align 2 +// X86WINPRMTD-NEXT: store i32 [[A_COERCE]], ptr [[A]], align 2 +// X86WINPRMTD-NEXT: store i32 [[B_COERCE]], ptr [[B]], align 2 +// X86WINPRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// X86WINPRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// X86WINPRMTD-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float +// X86WINPRMTD-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// X86WINPRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 +// X86WINPRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 +// X86WINPRMTD-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float +// X86WINPRMTD-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// X86WINPRMTD-NEXT: [[TMP0:%.*]] = fmul float [[EXT]], [[EXT2]] +// X86WINPRMTD-NEXT: [[TMP1:%.*]] = fmul float [[EXT1]], [[EXT3]] +// X86WINPRMTD-NEXT: [[TMP2:%.*]] = fadd float [[TMP0]], [[TMP1]] +// X86WINPRMTD-NEXT: [[TMP3:%.*]] = fmul float [[EXT2]], [[EXT2]] +// X86WINPRMTD-NEXT: [[TMP4:%.*]] = fmul float [[EXT3]], [[EXT3]] +// X86WINPRMTD-NEXT: [[TMP5:%.*]] = fadd float [[TMP3]], [[TMP4]] +// X86WINPRMTD-NEXT: [[TMP6:%.*]] = fmul float [[EXT1]], [[EXT2]] +// X86WINPRMTD-NEXT: [[TMP7:%.*]] = fmul float [[EXT]], [[EXT3]] +// X86WINPRMTD-NEXT: [[TMP8:%.*]] = fsub float [[TMP6]], [[TMP7]] +// X86WINPRMTD-NEXT: [[TMP9:%.*]] = fdiv float [[TMP2]], [[TMP5]] +// X86WINPRMTD-NEXT: [[TMP10:%.*]] = fdiv float [[TMP8]], [[TMP5]] +// X86WINPRMTD-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP9]] to half +// X86WINPRMTD-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[TMP10]] to half +// X86WINPRMTD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// X86WINPRMTD-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// X86WINPRMTD-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 +// X86WINPRMTD-NEXT: [[TMP11:%.*]] = load i32, ptr [[RETVAL]], align 2 +// X86WINPRMTD-NEXT: ret i32 [[TMP11]] +// +// BASIC_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x half> @divf16( +// BASIC_FAST-SAME: <2 x half> noundef nofpclass(nan inf) [[A_COERCE:%.*]], <2 x half> noundef nofpclass(nan inf) [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// BASIC_FAST-NEXT: entry: +// BASIC_FAST-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// BASIC_FAST-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// BASIC_FAST-NEXT: [[B:%.*]] = alloca { half, half }, align 2 +// BASIC_FAST-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// BASIC_FAST-NEXT: store <2 x half> [[B_COERCE]], ptr [[B]], align 2 +// BASIC_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// BASIC_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// BASIC_FAST-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float +// BASIC_FAST-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// BASIC_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 +// BASIC_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 +// BASIC_FAST-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float +// BASIC_FAST-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// BASIC_FAST-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT2]] +// BASIC_FAST-NEXT: [[TMP1:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT3]] +// BASIC_FAST-NEXT: [[TMP2:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP0]], [[TMP1]] +// BASIC_FAST-NEXT: [[TMP3:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT2]], [[EXT2]] +// BASIC_FAST-NEXT: [[TMP4:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT3]], [[EXT3]] +// BASIC_FAST-NEXT: [[TMP5:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP3]], [[TMP4]] +// BASIC_FAST-NEXT: [[TMP6:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT2]] +// BASIC_FAST-NEXT: [[TMP7:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT3]] +// BASIC_FAST-NEXT: [[TMP8:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[TMP6]], [[TMP7]] +// BASIC_FAST-NEXT: [[TMP9:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP2]], [[TMP5]] +// BASIC_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP8]], [[TMP5]] +// BASIC_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP9]] to half +// BASIC_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[TMP10]] to half +// BASIC_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// BASIC_FAST-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 +// BASIC_FAST-NEXT: [[TMP11:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// BASIC_FAST-NEXT: ret <2 x half> [[TMP11]] +// +// FULL_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x half> @divf16( +// FULL_FAST-SAME: <2 x half> noundef nofpclass(nan inf) [[A_COERCE:%.*]], <2 x half> noundef nofpclass(nan inf) [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// FULL_FAST-NEXT: entry: +// FULL_FAST-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// FULL_FAST-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// FULL_FAST-NEXT: [[B:%.*]] = alloca { half, half }, align 2 +// FULL_FAST-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4 +// FULL_FAST-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// FULL_FAST-NEXT: store <2 x half> [[B_COERCE]], ptr [[B]], align 2 +// FULL_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// FULL_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// FULL_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// FULL_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// FULL_FAST-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float +// FULL_FAST-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// FULL_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 0 +// FULL_FAST-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 +// FULL_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 1 +// FULL_FAST-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 +// FULL_FAST-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float +// FULL_FAST-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// FULL_FAST-NEXT: [[CALL:%.*]] = call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) <2 x float> @__divsc3(float noundef nofpclass(nan inf) [[EXT]], float noundef nofpclass(nan inf) [[EXT1]], float noundef nofpclass(nan inf) [[EXT2]], float noundef nofpclass(nan inf) [[EXT3]]) #[[ATTR1:[0-9]+]] +// FULL_FAST-NEXT: store <2 x float> [[CALL]], ptr [[COERCE]], align 4 +// FULL_FAST-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 0 +// FULL_FAST-NEXT: [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4 +// FULL_FAST-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 1 +// FULL_FAST-NEXT: [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4 +// FULL_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[COERCE_REAL]] to half +// FULL_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[COERCE_IMAG]] to half +// FULL_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// FULL_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// FULL_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// FULL_FAST-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 +// FULL_FAST-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// FULL_FAST-NEXT: ret <2 x half> [[TMP0]] +// +// IMPRVD_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x half> @divf16( +// IMPRVD_FAST-SAME: <2 x half> noundef nofpclass(nan inf) [[A_COERCE:%.*]], <2 x half> noundef nofpclass(nan inf) [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// IMPRVD_FAST-NEXT: entry: +// IMPRVD_FAST-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// IMPRVD_FAST-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// IMPRVD_FAST-NEXT: [[B:%.*]] = alloca { half, half }, align 2 +// IMPRVD_FAST-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// IMPRVD_FAST-NEXT: store <2 x half> [[B_COERCE]], ptr [[B]], align 2 +// IMPRVD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// IMPRVD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// IMPRVD_FAST-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float +// IMPRVD_FAST-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// IMPRVD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 +// IMPRVD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 +// IMPRVD_FAST-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float +// IMPRVD_FAST-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// IMPRVD_FAST-NEXT: [[TMP0:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.fabs.f32(float [[EXT2]]) +// IMPRVD_FAST-NEXT: [[TMP1:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.fabs.f32(float [[EXT3]]) +// IMPRVD_FAST-NEXT: [[ABS_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn ugt float [[TMP0]], [[TMP1]] +// IMPRVD_FAST-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// IMPRVD_FAST: abs_rhsr_greater_or_equal_abs_rhsi: +// IMPRVD_FAST-NEXT: [[TMP2:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[EXT3]], [[EXT2]] +// IMPRVD_FAST-NEXT: [[TMP3:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP2]], [[EXT3]] +// IMPRVD_FAST-NEXT: [[TMP4:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[EXT2]], [[TMP3]] +// IMPRVD_FAST-NEXT: [[TMP5:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[TMP2]] +// IMPRVD_FAST-NEXT: [[TMP6:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[EXT]], [[TMP5]] +// IMPRVD_FAST-NEXT: [[TMP7:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP6]], [[TMP4]] +// IMPRVD_FAST-NEXT: [[TMP8:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[TMP2]] +// IMPRVD_FAST-NEXT: [[TMP9:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[EXT1]], [[TMP8]] +// IMPRVD_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP9]], [[TMP4]] +// IMPRVD_FAST-NEXT: br label [[COMPLEX_DIV:%.*]] +// IMPRVD_FAST: abs_rhsr_less_than_abs_rhsi: +// IMPRVD_FAST-NEXT: [[TMP11:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[EXT2]], [[EXT3]] +// IMPRVD_FAST-NEXT: [[TMP12:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP11]], [[EXT2]] +// IMPRVD_FAST-NEXT: [[TMP13:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[EXT3]], [[TMP12]] +// IMPRVD_FAST-NEXT: [[TMP14:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[TMP11]] +// IMPRVD_FAST-NEXT: [[TMP15:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP14]], [[EXT1]] +// IMPRVD_FAST-NEXT: [[TMP16:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP15]], [[TMP13]] +// IMPRVD_FAST-NEXT: [[TMP17:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[TMP11]] +// IMPRVD_FAST-NEXT: [[TMP18:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[TMP17]], [[EXT]] +// IMPRVD_FAST-NEXT: [[TMP19:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP18]], [[TMP13]] +// IMPRVD_FAST-NEXT: br label [[COMPLEX_DIV]] +// IMPRVD_FAST: complex_div: +// IMPRVD_FAST-NEXT: [[TMP20:%.*]] = phi reassoc nnan ninf nsz arcp afn float [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD_FAST-NEXT: [[TMP21:%.*]] = phi reassoc nnan ninf nsz arcp afn float [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP20]] to half +// IMPRVD_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[TMP21]] to half +// IMPRVD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// IMPRVD_FAST-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 +// IMPRVD_FAST-NEXT: [[TMP22:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// IMPRVD_FAST-NEXT: ret <2 x half> [[TMP22]] +// +// PRMTD_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x half> @divf16( +// PRMTD_FAST-SAME: <2 x half> noundef nofpclass(nan inf) [[A_COERCE:%.*]], <2 x half> noundef nofpclass(nan inf) [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// PRMTD_FAST-NEXT: entry: +// PRMTD_FAST-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// PRMTD_FAST-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// PRMTD_FAST-NEXT: [[B:%.*]] = alloca { half, half }, align 2 +// PRMTD_FAST-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// PRMTD_FAST-NEXT: store <2 x half> [[B_COERCE]], ptr [[B]], align 2 +// PRMTD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// PRMTD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// PRMTD_FAST-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float +// PRMTD_FAST-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// PRMTD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 +// PRMTD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 +// PRMTD_FAST-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float +// PRMTD_FAST-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// PRMTD_FAST-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT2]] +// PRMTD_FAST-NEXT: [[TMP1:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT3]] +// PRMTD_FAST-NEXT: [[TMP2:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP0]], [[TMP1]] +// PRMTD_FAST-NEXT: [[TMP3:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT2]], [[EXT2]] +// PRMTD_FAST-NEXT: [[TMP4:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT3]], [[EXT3]] +// PRMTD_FAST-NEXT: [[TMP5:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP3]], [[TMP4]] +// PRMTD_FAST-NEXT: [[TMP6:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT2]] +// PRMTD_FAST-NEXT: [[TMP7:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT3]] +// PRMTD_FAST-NEXT: [[TMP8:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[TMP6]], [[TMP7]] +// PRMTD_FAST-NEXT: [[TMP9:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP2]], [[TMP5]] +// PRMTD_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP8]], [[TMP5]] +// PRMTD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP9]] to half +// PRMTD_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[TMP10]] to half +// PRMTD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// PRMTD_FAST-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 +// PRMTD_FAST-NEXT: [[TMP11:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// PRMTD_FAST-NEXT: ret <2 x half> [[TMP11]] +// +_Complex _Float16 divf16(_Complex _Float16 a, _Complex _Float16 b) { + return a / b; +} + +// FULL-LABEL: define dso_local <2 x half> @mulf16( +// FULL-SAME: <2 x half> noundef [[A_COERCE:%.*]], <2 x half> noundef [[B_COERCE:%.*]]) #[[ATTR0]] { +// FULL-NEXT: entry: +// FULL-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// FULL-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// FULL-NEXT: [[B:%.*]] = alloca { half, half }, align 2 +// FULL-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4 +// FULL-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// FULL-NEXT: store <2 x half> [[B_COERCE]], ptr [[B]], align 2 +// FULL-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// FULL-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// FULL-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// FULL-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// FULL-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float +// FULL-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// FULL-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 0 +// FULL-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 +// FULL-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 1 +// FULL-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 +// FULL-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float +// FULL-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// FULL-NEXT: [[MUL_AC:%.*]] = fmul float [[EXT]], [[EXT2]] +// FULL-NEXT: [[MUL_BD:%.*]] = fmul float [[EXT1]], [[EXT3]] +// FULL-NEXT: [[MUL_AD:%.*]] = fmul float [[EXT]], [[EXT3]] +// FULL-NEXT: [[MUL_BC:%.*]] = fmul float [[EXT1]], [[EXT2]] +// FULL-NEXT: [[MUL_R:%.*]] = fsub float [[MUL_AC]], [[MUL_BD]] +// FULL-NEXT: [[MUL_I:%.*]] = fadd float [[MUL_AD]], [[MUL_BC]] +// FULL-NEXT: [[ISNAN_CMP:%.*]] = fcmp uno float [[MUL_R]], [[MUL_R]] +// FULL-NEXT: br i1 [[ISNAN_CMP]], label [[COMPLEX_MUL_IMAG_NAN:%.*]], label [[COMPLEX_MUL_CONT:%.*]], !prof [[PROF2:![0-9]+]] +// FULL: complex_mul_imag_nan: +// FULL-NEXT: [[ISNAN_CMP4:%.*]] = fcmp uno float [[MUL_I]], [[MUL_I]] +// FULL-NEXT: br i1 [[ISNAN_CMP4]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]] +// FULL: complex_mul_libcall: +// FULL-NEXT: [[CALL:%.*]] = call <2 x float> @__mulsc3(float noundef [[EXT]], float noundef [[EXT1]], float noundef [[EXT2]], float noundef [[EXT3]]) #[[ATTR1]] +// FULL-NEXT: store <2 x float> [[CALL]], ptr [[COERCE]], align 4 +// FULL-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 0 +// FULL-NEXT: [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4 +// FULL-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 1 +// FULL-NEXT: [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4 +// FULL-NEXT: br label [[COMPLEX_MUL_CONT]] +// FULL: complex_mul_cont: +// FULL-NEXT: [[REAL_MUL_PHI:%.*]] = phi float [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_REAL]], [[COMPLEX_MUL_LIBCALL]] ] +// FULL-NEXT: [[IMAG_MUL_PHI:%.*]] = phi float [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_IMAG]], [[COMPLEX_MUL_LIBCALL]] ] +// FULL-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[REAL_MUL_PHI]] to half +// FULL-NEXT: [[UNPROMOTION5:%.*]] = fptrunc float [[IMAG_MUL_PHI]] to half +// FULL-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// FULL-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// FULL-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// FULL-NEXT: store half [[UNPROMOTION5]], ptr [[RETVAL_IMAGP]], align 2 +// FULL-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// FULL-NEXT: ret <2 x half> [[TMP0]] +// +// BASIC-LABEL: define dso_local <2 x half> @mulf16( +// BASIC-SAME: <2 x half> noundef [[A_COERCE:%.*]], <2 x half> noundef [[B_COERCE:%.*]]) #[[ATTR0]] { +// BASIC-NEXT: entry: +// BASIC-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// BASIC-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// BASIC-NEXT: [[B:%.*]] = alloca { half, half }, align 2 +// BASIC-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// BASIC-NEXT: store <2 x half> [[B_COERCE]], ptr [[B]], align 2 +// BASIC-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// BASIC-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// BASIC-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// BASIC-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// BASIC-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float +// BASIC-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// BASIC-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 0 +// BASIC-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 +// BASIC-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 1 +// BASIC-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 +// BASIC-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float +// BASIC-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// BASIC-NEXT: [[MUL_AC:%.*]] = fmul float [[EXT]], [[EXT2]] +// BASIC-NEXT: [[MUL_BD:%.*]] = fmul float [[EXT1]], [[EXT3]] +// BASIC-NEXT: [[MUL_AD:%.*]] = fmul float [[EXT]], [[EXT3]] +// BASIC-NEXT: [[MUL_BC:%.*]] = fmul float [[EXT1]], [[EXT2]] +// BASIC-NEXT: [[MUL_R:%.*]] = fsub float [[MUL_AC]], [[MUL_BD]] +// BASIC-NEXT: [[MUL_I:%.*]] = fadd float [[MUL_AD]], [[MUL_BC]] +// BASIC-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[MUL_R]] to half +// BASIC-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[MUL_I]] to half +// BASIC-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// BASIC-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 +// BASIC-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// BASIC-NEXT: ret <2 x half> [[TMP0]] +// +// IMPRVD-LABEL: define dso_local <2 x half> @mulf16( +// IMPRVD-SAME: <2 x half> noundef [[A_COERCE:%.*]], <2 x half> noundef [[B_COERCE:%.*]]) #[[ATTR0]] { +// IMPRVD-NEXT: entry: +// IMPRVD-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// IMPRVD-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// IMPRVD-NEXT: [[B:%.*]] = alloca { half, half }, align 2 +// IMPRVD-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// IMPRVD-NEXT: store <2 x half> [[B_COERCE]], ptr [[B]], align 2 +// IMPRVD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// IMPRVD-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// IMPRVD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// IMPRVD-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// IMPRVD-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float +// IMPRVD-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// IMPRVD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 0 +// IMPRVD-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 +// IMPRVD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 1 +// IMPRVD-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 +// IMPRVD-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float +// IMPRVD-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// IMPRVD-NEXT: [[MUL_AC:%.*]] = fmul float [[EXT]], [[EXT2]] +// IMPRVD-NEXT: [[MUL_BD:%.*]] = fmul float [[EXT1]], [[EXT3]] +// IMPRVD-NEXT: [[MUL_AD:%.*]] = fmul float [[EXT]], [[EXT3]] +// IMPRVD-NEXT: [[MUL_BC:%.*]] = fmul float [[EXT1]], [[EXT2]] +// IMPRVD-NEXT: [[MUL_R:%.*]] = fsub float [[MUL_AC]], [[MUL_BD]] +// IMPRVD-NEXT: [[MUL_I:%.*]] = fadd float [[MUL_AD]], [[MUL_BC]] +// IMPRVD-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[MUL_R]] to half +// IMPRVD-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[MUL_I]] to half +// IMPRVD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// IMPRVD-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 +// IMPRVD-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// IMPRVD-NEXT: ret <2 x half> [[TMP0]] +// +// PRMTD-LABEL: define dso_local <2 x half> @mulf16( +// PRMTD-SAME: <2 x half> noundef [[A_COERCE:%.*]], <2 x half> noundef [[B_COERCE:%.*]]) #[[ATTR0]] { +// PRMTD-NEXT: entry: +// PRMTD-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// PRMTD-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// PRMTD-NEXT: [[B:%.*]] = alloca { half, half }, align 2 +// PRMTD-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// PRMTD-NEXT: store <2 x half> [[B_COERCE]], ptr [[B]], align 2 +// PRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// PRMTD-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// PRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// PRMTD-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// PRMTD-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float +// PRMTD-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// PRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 0 +// PRMTD-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 +// PRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 1 +// PRMTD-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 +// PRMTD-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float +// PRMTD-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// PRMTD-NEXT: [[MUL_AC:%.*]] = fmul float [[EXT]], [[EXT2]] +// PRMTD-NEXT: [[MUL_BD:%.*]] = fmul float [[EXT1]], [[EXT3]] +// PRMTD-NEXT: [[MUL_AD:%.*]] = fmul float [[EXT]], [[EXT3]] +// PRMTD-NEXT: [[MUL_BC:%.*]] = fmul float [[EXT1]], [[EXT2]] +// PRMTD-NEXT: [[MUL_R:%.*]] = fsub float [[MUL_AC]], [[MUL_BD]] +// PRMTD-NEXT: [[MUL_I:%.*]] = fadd float [[MUL_AD]], [[MUL_BC]] +// PRMTD-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[MUL_R]] to half +// PRMTD-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[MUL_I]] to half +// PRMTD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// PRMTD-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 +// PRMTD-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// PRMTD-NEXT: ret <2 x half> [[TMP0]] +// +// X86WINPRMTD-LABEL: define dso_local i32 @mulf16( +// X86WINPRMTD-SAME: i32 noundef [[A_COERCE:%.*]], i32 noundef [[B_COERCE:%.*]]) #[[ATTR0]] { +// X86WINPRMTD-NEXT: entry: +// X86WINPRMTD-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// X86WINPRMTD-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// X86WINPRMTD-NEXT: [[B:%.*]] = alloca { half, half }, align 2 +// X86WINPRMTD-NEXT: store i32 [[A_COERCE]], ptr [[A]], align 2 +// X86WINPRMTD-NEXT: store i32 [[B_COERCE]], ptr [[B]], align 2 +// X86WINPRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// X86WINPRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// X86WINPRMTD-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float +// X86WINPRMTD-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// X86WINPRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 +// X86WINPRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 +// X86WINPRMTD-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float +// X86WINPRMTD-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// X86WINPRMTD-NEXT: [[MUL_AC:%.*]] = fmul float [[EXT]], [[EXT2]] +// X86WINPRMTD-NEXT: [[MUL_BD:%.*]] = fmul float [[EXT1]], [[EXT3]] +// X86WINPRMTD-NEXT: [[MUL_AD:%.*]] = fmul float [[EXT]], [[EXT3]] +// X86WINPRMTD-NEXT: [[MUL_BC:%.*]] = fmul float [[EXT1]], [[EXT2]] +// X86WINPRMTD-NEXT: [[MUL_R:%.*]] = fsub float [[MUL_AC]], [[MUL_BD]] +// X86WINPRMTD-NEXT: [[MUL_I:%.*]] = fadd float [[MUL_AD]], [[MUL_BC]] +// X86WINPRMTD-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[MUL_R]] to half +// X86WINPRMTD-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[MUL_I]] to half +// X86WINPRMTD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// X86WINPRMTD-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// X86WINPRMTD-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 +// X86WINPRMTD-NEXT: [[TMP0:%.*]] = load i32, ptr [[RETVAL]], align 2 +// X86WINPRMTD-NEXT: ret i32 [[TMP0]] +// +// BASIC_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x half> @mulf16( +// BASIC_FAST-SAME: <2 x half> noundef nofpclass(nan inf) [[A_COERCE:%.*]], <2 x half> noundef nofpclass(nan inf) [[B_COERCE:%.*]]) #[[ATTR0]] { +// BASIC_FAST-NEXT: entry: +// BASIC_FAST-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// BASIC_FAST-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// BASIC_FAST-NEXT: [[B:%.*]] = alloca { half, half }, align 2 +// BASIC_FAST-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// BASIC_FAST-NEXT: store <2 x half> [[B_COERCE]], ptr [[B]], align 2 +// BASIC_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// BASIC_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// BASIC_FAST-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float +// BASIC_FAST-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// BASIC_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 +// BASIC_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 +// BASIC_FAST-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float +// BASIC_FAST-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// BASIC_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT2]] +// BASIC_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT3]] +// BASIC_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT3]] +// BASIC_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT2]] +// BASIC_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[MUL_AC]], [[MUL_BD]] +// BASIC_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[MUL_AD]], [[MUL_BC]] +// BASIC_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[MUL_R]] to half +// BASIC_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[MUL_I]] to half +// BASIC_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// BASIC_FAST-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 +// BASIC_FAST-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// BASIC_FAST-NEXT: ret <2 x half> [[TMP0]] +// +// FULL_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x half> @mulf16( +// FULL_FAST-SAME: <2 x half> noundef nofpclass(nan inf) [[A_COERCE:%.*]], <2 x half> noundef nofpclass(nan inf) [[B_COERCE:%.*]]) #[[ATTR0]] { +// FULL_FAST-NEXT: entry: +// FULL_FAST-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// FULL_FAST-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// FULL_FAST-NEXT: [[B:%.*]] = alloca { half, half }, align 2 +// FULL_FAST-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4 +// FULL_FAST-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// FULL_FAST-NEXT: store <2 x half> [[B_COERCE]], ptr [[B]], align 2 +// FULL_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// FULL_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// FULL_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// FULL_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// FULL_FAST-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float +// FULL_FAST-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// FULL_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 0 +// FULL_FAST-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 +// FULL_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 1 +// FULL_FAST-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 +// FULL_FAST-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float +// FULL_FAST-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// FULL_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT2]] +// FULL_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT3]] +// FULL_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT3]] +// FULL_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT2]] +// FULL_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[MUL_AC]], [[MUL_BD]] +// FULL_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[MUL_AD]], [[MUL_BC]] +// FULL_FAST-NEXT: [[ISNAN_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn uno float [[MUL_R]], [[MUL_R]] +// FULL_FAST-NEXT: br i1 [[ISNAN_CMP]], label [[COMPLEX_MUL_IMAG_NAN:%.*]], label [[COMPLEX_MUL_CONT:%.*]], !prof [[PROF2:![0-9]+]] +// FULL_FAST: complex_mul_imag_nan: +// FULL_FAST-NEXT: [[ISNAN_CMP4:%.*]] = fcmp reassoc nnan ninf nsz arcp afn uno float [[MUL_I]], [[MUL_I]] +// FULL_FAST-NEXT: br i1 [[ISNAN_CMP4]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]] +// FULL_FAST: complex_mul_libcall: +// FULL_FAST-NEXT: [[CALL:%.*]] = call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) <2 x float> @__mulsc3(float noundef nofpclass(nan inf) [[EXT]], float noundef nofpclass(nan inf) [[EXT1]], float noundef nofpclass(nan inf) [[EXT2]], float noundef nofpclass(nan inf) [[EXT3]]) #[[ATTR1]] +// FULL_FAST-NEXT: store <2 x float> [[CALL]], ptr [[COERCE]], align 4 +// FULL_FAST-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 0 +// FULL_FAST-NEXT: [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4 +// FULL_FAST-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 1 +// FULL_FAST-NEXT: [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4 +// FULL_FAST-NEXT: br label [[COMPLEX_MUL_CONT]] +// FULL_FAST: complex_mul_cont: +// FULL_FAST-NEXT: [[REAL_MUL_PHI:%.*]] = phi reassoc nnan ninf nsz arcp afn float [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_REAL]], [[COMPLEX_MUL_LIBCALL]] ] +// FULL_FAST-NEXT: [[IMAG_MUL_PHI:%.*]] = phi reassoc nnan ninf nsz arcp afn float [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_IMAG]], [[COMPLEX_MUL_LIBCALL]] ] +// FULL_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[REAL_MUL_PHI]] to half +// FULL_FAST-NEXT: [[UNPROMOTION5:%.*]] = fptrunc float [[IMAG_MUL_PHI]] to half +// FULL_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// FULL_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// FULL_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// FULL_FAST-NEXT: store half [[UNPROMOTION5]], ptr [[RETVAL_IMAGP]], align 2 +// FULL_FAST-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// FULL_FAST-NEXT: ret <2 x half> [[TMP0]] +// +// IMPRVD_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x half> @mulf16( +// IMPRVD_FAST-SAME: <2 x half> noundef nofpclass(nan inf) [[A_COERCE:%.*]], <2 x half> noundef nofpclass(nan inf) [[B_COERCE:%.*]]) #[[ATTR0]] { +// IMPRVD_FAST-NEXT: entry: +// IMPRVD_FAST-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// IMPRVD_FAST-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// IMPRVD_FAST-NEXT: [[B:%.*]] = alloca { half, half }, align 2 +// IMPRVD_FAST-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// IMPRVD_FAST-NEXT: store <2 x half> [[B_COERCE]], ptr [[B]], align 2 +// IMPRVD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// IMPRVD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// IMPRVD_FAST-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float +// IMPRVD_FAST-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// IMPRVD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 +// IMPRVD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 +// IMPRVD_FAST-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float +// IMPRVD_FAST-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// IMPRVD_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT2]] +// IMPRVD_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT3]] +// IMPRVD_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT3]] +// IMPRVD_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT2]] +// IMPRVD_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[MUL_AC]], [[MUL_BD]] +// IMPRVD_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[MUL_AD]], [[MUL_BC]] +// IMPRVD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[MUL_R]] to half +// IMPRVD_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[MUL_I]] to half +// IMPRVD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// IMPRVD_FAST-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 +// IMPRVD_FAST-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// IMPRVD_FAST-NEXT: ret <2 x half> [[TMP0]] +// +// PRMTD_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x half> @mulf16( +// PRMTD_FAST-SAME: <2 x half> noundef nofpclass(nan inf) [[A_COERCE:%.*]], <2 x half> noundef nofpclass(nan inf) [[B_COERCE:%.*]]) #[[ATTR0]] { +// PRMTD_FAST-NEXT: entry: +// PRMTD_FAST-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// PRMTD_FAST-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// PRMTD_FAST-NEXT: [[B:%.*]] = alloca { half, half }, align 2 +// PRMTD_FAST-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// PRMTD_FAST-NEXT: store <2 x half> [[B_COERCE]], ptr [[B]], align 2 +// PRMTD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// PRMTD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// PRMTD_FAST-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float +// PRMTD_FAST-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float +// PRMTD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 +// PRMTD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[B]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 +// PRMTD_FAST-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float +// PRMTD_FAST-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float +// PRMTD_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT2]] +// PRMTD_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT3]] +// PRMTD_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT3]] +// PRMTD_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT1]], [[EXT2]] +// PRMTD_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[MUL_AC]], [[MUL_BD]] +// PRMTD_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[MUL_AD]], [[MUL_BC]] +// PRMTD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[MUL_R]] to half +// PRMTD_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[MUL_I]] to half +// PRMTD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// PRMTD_FAST-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 +// PRMTD_FAST-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// PRMTD_FAST-NEXT: ret <2 x half> [[TMP0]] +// +_Complex _Float16 mulf16(_Complex _Float16 a, _Complex _Float16 b) { + return a * b; +} + +// FULL-LABEL: define dso_local <2 x half> @f1( +// FULL-SAME: <2 x half> noundef [[A_COERCE:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]], <2 x half> noundef [[C_COERCE:%.*]]) #[[ATTR0]] { +// FULL-NEXT: entry: +// FULL-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// FULL-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// FULL-NEXT: [[C:%.*]] = alloca { half, half }, align 2 +// FULL-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4 +// FULL-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// FULL-NEXT: store <2 x half> [[C_COERCE]], ptr [[C]], align 2 +// FULL-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// FULL-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// FULL-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// FULL-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// FULL-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 0 +// FULL-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 +// FULL-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 1 +// FULL-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 +// FULL-NEXT: [[CONV:%.*]] = fpext half [[C_REAL]] to x86_fp80 +// FULL-NEXT: [[CONV1:%.*]] = fpext half [[C_IMAG]] to x86_fp80 +// FULL-NEXT: [[CALL:%.*]] = call { x86_fp80, x86_fp80 } @__divxc3(x86_fp80 noundef [[B_REAL]], x86_fp80 noundef [[B_IMAG]], x86_fp80 noundef [[CONV]], x86_fp80 noundef [[CONV1]]) #[[ATTR1]] +// FULL-NEXT: [[TMP0:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 0 +// FULL-NEXT: [[TMP1:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 1 +// FULL-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP0]] to half +// FULL-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP1]] to half +// FULL-NEXT: [[EXT:%.*]] = fpext half [[CONV2]] to float +// FULL-NEXT: [[EXT4:%.*]] = fpext half [[CONV3]] to float +// FULL-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// FULL-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// FULL-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// FULL-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// FULL-NEXT: [[EXT5:%.*]] = fpext half [[A_REAL]] to float +// FULL-NEXT: [[EXT6:%.*]] = fpext half [[A_IMAG]] to float +// FULL-NEXT: [[CALL7:%.*]] = call <2 x float> @__divsc3(float noundef [[EXT]], float noundef [[EXT4]], float noundef [[EXT5]], float noundef [[EXT6]]) #[[ATTR1]] +// FULL-NEXT: store <2 x float> [[CALL7]], ptr [[COERCE]], align 4 +// FULL-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 0 +// FULL-NEXT: [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4 +// FULL-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 1 +// FULL-NEXT: [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4 +// FULL-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[COERCE_REAL]] to half +// FULL-NEXT: [[UNPROMOTION8:%.*]] = fptrunc float [[COERCE_IMAG]] to half +// FULL-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// FULL-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// FULL-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// FULL-NEXT: store half [[UNPROMOTION8]], ptr [[RETVAL_IMAGP]], align 2 +// FULL-NEXT: [[TMP2:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// FULL-NEXT: ret <2 x half> [[TMP2]] +// +// BASIC-LABEL: define dso_local <2 x half> @f1( +// BASIC-SAME: <2 x half> noundef [[A_COERCE:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]], <2 x half> noundef [[C_COERCE:%.*]]) #[[ATTR0]] { +// BASIC-NEXT: entry: +// BASIC-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// BASIC-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// BASIC-NEXT: [[C:%.*]] = alloca { half, half }, align 2 +// BASIC-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// BASIC-NEXT: store <2 x half> [[C_COERCE]], ptr [[C]], align 2 +// BASIC-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// BASIC-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// BASIC-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// BASIC-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// BASIC-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 0 +// BASIC-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 +// BASIC-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 1 +// BASIC-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 +// BASIC-NEXT: [[CONV:%.*]] = fpext half [[C_REAL]] to x86_fp80 +// BASIC-NEXT: [[CONV1:%.*]] = fpext half [[C_IMAG]] to x86_fp80 +// BASIC-NEXT: [[TMP0:%.*]] = fmul x86_fp80 [[B_REAL]], [[CONV]] +// BASIC-NEXT: [[TMP1:%.*]] = fmul x86_fp80 [[B_IMAG]], [[CONV1]] +// BASIC-NEXT: [[TMP2:%.*]] = fadd x86_fp80 [[TMP0]], [[TMP1]] +// BASIC-NEXT: [[TMP3:%.*]] = fmul x86_fp80 [[CONV]], [[CONV]] +// BASIC-NEXT: [[TMP4:%.*]] = fmul x86_fp80 [[CONV1]], [[CONV1]] +// BASIC-NEXT: [[TMP5:%.*]] = fadd x86_fp80 [[TMP3]], [[TMP4]] +// BASIC-NEXT: [[TMP6:%.*]] = fmul x86_fp80 [[B_IMAG]], [[CONV]] +// BASIC-NEXT: [[TMP7:%.*]] = fmul x86_fp80 [[B_REAL]], [[CONV1]] +// BASIC-NEXT: [[TMP8:%.*]] = fsub x86_fp80 [[TMP6]], [[TMP7]] +// BASIC-NEXT: [[TMP9:%.*]] = fdiv x86_fp80 [[TMP2]], [[TMP5]] +// BASIC-NEXT: [[TMP10:%.*]] = fdiv x86_fp80 [[TMP8]], [[TMP5]] +// BASIC-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP9]] to half +// BASIC-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP10]] to half +// BASIC-NEXT: [[EXT:%.*]] = fpext half [[CONV2]] to float +// BASIC-NEXT: [[EXT4:%.*]] = fpext half [[CONV3]] to float +// BASIC-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// BASIC-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// BASIC-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// BASIC-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// BASIC-NEXT: [[EXT5:%.*]] = fpext half [[A_REAL]] to float +// BASIC-NEXT: [[EXT6:%.*]] = fpext half [[A_IMAG]] to float +// BASIC-NEXT: [[TMP11:%.*]] = fmul float [[EXT]], [[EXT5]] +// BASIC-NEXT: [[TMP12:%.*]] = fmul float [[EXT4]], [[EXT6]] +// BASIC-NEXT: [[TMP13:%.*]] = fadd float [[TMP11]], [[TMP12]] +// BASIC-NEXT: [[TMP14:%.*]] = fmul float [[EXT5]], [[EXT5]] +// BASIC-NEXT: [[TMP15:%.*]] = fmul float [[EXT6]], [[EXT6]] +// BASIC-NEXT: [[TMP16:%.*]] = fadd float [[TMP14]], [[TMP15]] +// BASIC-NEXT: [[TMP17:%.*]] = fmul float [[EXT4]], [[EXT5]] +// BASIC-NEXT: [[TMP18:%.*]] = fmul float [[EXT]], [[EXT6]] +// BASIC-NEXT: [[TMP19:%.*]] = fsub float [[TMP17]], [[TMP18]] +// BASIC-NEXT: [[TMP20:%.*]] = fdiv float [[TMP13]], [[TMP16]] +// BASIC-NEXT: [[TMP21:%.*]] = fdiv float [[TMP19]], [[TMP16]] +// BASIC-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP20]] to half +// BASIC-NEXT: [[UNPROMOTION7:%.*]] = fptrunc float [[TMP21]] to half +// BASIC-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// BASIC-NEXT: store half [[UNPROMOTION7]], ptr [[RETVAL_IMAGP]], align 2 +// BASIC-NEXT: [[TMP22:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// BASIC-NEXT: ret <2 x half> [[TMP22]] +// +// IMPRVD-LABEL: define dso_local <2 x half> @f1( +// IMPRVD-SAME: <2 x half> noundef [[A_COERCE:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]], <2 x half> noundef [[C_COERCE:%.*]]) #[[ATTR0]] { +// IMPRVD-NEXT: entry: +// IMPRVD-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// IMPRVD-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// IMPRVD-NEXT: [[C:%.*]] = alloca { half, half }, align 2 +// IMPRVD-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// IMPRVD-NEXT: store <2 x half> [[C_COERCE]], ptr [[C]], align 2 +// IMPRVD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// IMPRVD-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// IMPRVD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// IMPRVD-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// IMPRVD-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 0 +// IMPRVD-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 +// IMPRVD-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 1 +// IMPRVD-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 +// IMPRVD-NEXT: [[CONV:%.*]] = fpext half [[C_REAL]] to x86_fp80 +// IMPRVD-NEXT: [[CONV1:%.*]] = fpext half [[C_IMAG]] to x86_fp80 +// IMPRVD-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV]]) +// IMPRVD-NEXT: [[TMP1:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV1]]) +// IMPRVD-NEXT: [[ABS_CMP:%.*]] = fcmp ugt x86_fp80 [[TMP0]], [[TMP1]] +// IMPRVD-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// IMPRVD: abs_rhsr_greater_or_equal_abs_rhsi: +// IMPRVD-NEXT: [[TMP2:%.*]] = fdiv x86_fp80 [[CONV1]], [[CONV]] +// IMPRVD-NEXT: [[TMP3:%.*]] = fmul x86_fp80 [[TMP2]], [[CONV1]] +// IMPRVD-NEXT: [[TMP4:%.*]] = fadd x86_fp80 [[CONV]], [[TMP3]] +// IMPRVD-NEXT: [[TMP5:%.*]] = fmul x86_fp80 [[B_IMAG]], [[TMP2]] +// IMPRVD-NEXT: [[TMP6:%.*]] = fadd x86_fp80 [[B_REAL]], [[TMP5]] +// IMPRVD-NEXT: [[TMP7:%.*]] = fdiv x86_fp80 [[TMP6]], [[TMP4]] +// IMPRVD-NEXT: [[TMP8:%.*]] = fmul x86_fp80 [[B_REAL]], [[TMP2]] +// IMPRVD-NEXT: [[TMP9:%.*]] = fsub x86_fp80 [[B_IMAG]], [[TMP8]] +// IMPRVD-NEXT: [[TMP10:%.*]] = fdiv x86_fp80 [[TMP9]], [[TMP4]] +// IMPRVD-NEXT: br label [[COMPLEX_DIV:%.*]] +// IMPRVD: abs_rhsr_less_than_abs_rhsi: +// IMPRVD-NEXT: [[TMP11:%.*]] = fdiv x86_fp80 [[CONV]], [[CONV1]] +// IMPRVD-NEXT: [[TMP12:%.*]] = fmul x86_fp80 [[TMP11]], [[CONV]] +// IMPRVD-NEXT: [[TMP13:%.*]] = fadd x86_fp80 [[CONV1]], [[TMP12]] +// IMPRVD-NEXT: [[TMP14:%.*]] = fmul x86_fp80 [[B_REAL]], [[TMP11]] +// IMPRVD-NEXT: [[TMP15:%.*]] = fadd x86_fp80 [[TMP14]], [[B_IMAG]] +// IMPRVD-NEXT: [[TMP16:%.*]] = fdiv x86_fp80 [[TMP15]], [[TMP13]] +// IMPRVD-NEXT: [[TMP17:%.*]] = fmul x86_fp80 [[B_IMAG]], [[TMP11]] +// IMPRVD-NEXT: [[TMP18:%.*]] = fsub x86_fp80 [[TMP17]], [[B_REAL]] +// IMPRVD-NEXT: [[TMP19:%.*]] = fdiv x86_fp80 [[TMP18]], [[TMP13]] +// IMPRVD-NEXT: br label [[COMPLEX_DIV]] +// IMPRVD: complex_div: +// IMPRVD-NEXT: [[TMP20:%.*]] = phi x86_fp80 [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD-NEXT: [[TMP21:%.*]] = phi x86_fp80 [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP20]] to half +// IMPRVD-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP21]] to half +// IMPRVD-NEXT: [[EXT:%.*]] = fpext half [[CONV2]] to float +// IMPRVD-NEXT: [[EXT4:%.*]] = fpext half [[CONV3]] to float +// IMPRVD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// IMPRVD-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// IMPRVD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// IMPRVD-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// IMPRVD-NEXT: [[EXT5:%.*]] = fpext half [[A_REAL]] to float +// IMPRVD-NEXT: [[EXT6:%.*]] = fpext half [[A_IMAG]] to float +// IMPRVD-NEXT: [[TMP22:%.*]] = call float @llvm.fabs.f32(float [[EXT5]]) +// IMPRVD-NEXT: [[TMP23:%.*]] = call float @llvm.fabs.f32(float [[EXT6]]) +// IMPRVD-NEXT: [[ABS_CMP7:%.*]] = fcmp ugt float [[TMP22]], [[TMP23]] +// IMPRVD-NEXT: br i1 [[ABS_CMP7]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI8:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI9:%.*]] +// IMPRVD: abs_rhsr_greater_or_equal_abs_rhsi8: +// IMPRVD-NEXT: [[TMP24:%.*]] = fdiv float [[EXT6]], [[EXT5]] +// IMPRVD-NEXT: [[TMP25:%.*]] = fmul float [[TMP24]], [[EXT6]] +// IMPRVD-NEXT: [[TMP26:%.*]] = fadd float [[EXT5]], [[TMP25]] +// IMPRVD-NEXT: [[TMP27:%.*]] = fmul float [[EXT4]], [[TMP24]] +// IMPRVD-NEXT: [[TMP28:%.*]] = fadd float [[EXT]], [[TMP27]] +// IMPRVD-NEXT: [[TMP29:%.*]] = fdiv float [[TMP28]], [[TMP26]] +// IMPRVD-NEXT: [[TMP30:%.*]] = fmul float [[EXT]], [[TMP24]] +// IMPRVD-NEXT: [[TMP31:%.*]] = fsub float [[EXT4]], [[TMP30]] +// IMPRVD-NEXT: [[TMP32:%.*]] = fdiv float [[TMP31]], [[TMP26]] +// IMPRVD-NEXT: br label [[COMPLEX_DIV10:%.*]] +// IMPRVD: abs_rhsr_less_than_abs_rhsi9: +// IMPRVD-NEXT: [[TMP33:%.*]] = fdiv float [[EXT5]], [[EXT6]] +// IMPRVD-NEXT: [[TMP34:%.*]] = fmul float [[TMP33]], [[EXT5]] +// IMPRVD-NEXT: [[TMP35:%.*]] = fadd float [[EXT6]], [[TMP34]] +// IMPRVD-NEXT: [[TMP36:%.*]] = fmul float [[EXT]], [[TMP33]] +// IMPRVD-NEXT: [[TMP37:%.*]] = fadd float [[TMP36]], [[EXT4]] +// IMPRVD-NEXT: [[TMP38:%.*]] = fdiv float [[TMP37]], [[TMP35]] +// IMPRVD-NEXT: [[TMP39:%.*]] = fmul float [[EXT4]], [[TMP33]] +// IMPRVD-NEXT: [[TMP40:%.*]] = fsub float [[TMP39]], [[EXT]] +// IMPRVD-NEXT: [[TMP41:%.*]] = fdiv float [[TMP40]], [[TMP35]] +// IMPRVD-NEXT: br label [[COMPLEX_DIV10]] +// IMPRVD: complex_div10: +// IMPRVD-NEXT: [[TMP42:%.*]] = phi float [ [[TMP29]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI8]] ], [ [[TMP38]], [[ABS_RHSR_LESS_THAN_ABS_RHSI9]] ] +// IMPRVD-NEXT: [[TMP43:%.*]] = phi float [ [[TMP32]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI8]] ], [ [[TMP41]], [[ABS_RHSR_LESS_THAN_ABS_RHSI9]] ] +// IMPRVD-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP42]] to half +// IMPRVD-NEXT: [[UNPROMOTION11:%.*]] = fptrunc float [[TMP43]] to half +// IMPRVD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// IMPRVD-NEXT: store half [[UNPROMOTION11]], ptr [[RETVAL_IMAGP]], align 2 +// IMPRVD-NEXT: [[TMP44:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// IMPRVD-NEXT: ret <2 x half> [[TMP44]] +// +// PRMTD-LABEL: define dso_local <2 x half> @f1( +// PRMTD-SAME: <2 x half> noundef [[A_COERCE:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]], <2 x half> noundef [[C_COERCE:%.*]]) #[[ATTR0]] { +// PRMTD-NEXT: entry: +// PRMTD-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// PRMTD-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// PRMTD-NEXT: [[C:%.*]] = alloca { half, half }, align 2 +// PRMTD-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// PRMTD-NEXT: store <2 x half> [[C_COERCE]], ptr [[C]], align 2 +// PRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// PRMTD-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// PRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// PRMTD-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// PRMTD-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 0 +// PRMTD-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 +// PRMTD-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 1 +// PRMTD-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 +// PRMTD-NEXT: [[CONV:%.*]] = fpext half [[C_REAL]] to x86_fp80 +// PRMTD-NEXT: [[CONV1:%.*]] = fpext half [[C_IMAG]] to x86_fp80 +// PRMTD-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV]]) +// PRMTD-NEXT: [[TMP1:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV1]]) +// PRMTD-NEXT: [[ABS_CMP:%.*]] = fcmp ugt x86_fp80 [[TMP0]], [[TMP1]] +// PRMTD-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// PRMTD: abs_rhsr_greater_or_equal_abs_rhsi: +// PRMTD-NEXT: [[TMP2:%.*]] = fdiv x86_fp80 [[CONV1]], [[CONV]] +// PRMTD-NEXT: [[TMP3:%.*]] = fmul x86_fp80 [[TMP2]], [[CONV1]] +// PRMTD-NEXT: [[TMP4:%.*]] = fadd x86_fp80 [[CONV]], [[TMP3]] +// PRMTD-NEXT: [[TMP5:%.*]] = fmul x86_fp80 [[B_IMAG]], [[TMP2]] +// PRMTD-NEXT: [[TMP6:%.*]] = fadd x86_fp80 [[B_REAL]], [[TMP5]] +// PRMTD-NEXT: [[TMP7:%.*]] = fdiv x86_fp80 [[TMP6]], [[TMP4]] +// PRMTD-NEXT: [[TMP8:%.*]] = fmul x86_fp80 [[B_REAL]], [[TMP2]] +// PRMTD-NEXT: [[TMP9:%.*]] = fsub x86_fp80 [[B_IMAG]], [[TMP8]] +// PRMTD-NEXT: [[TMP10:%.*]] = fdiv x86_fp80 [[TMP9]], [[TMP4]] +// PRMTD-NEXT: br label [[COMPLEX_DIV:%.*]] +// PRMTD: abs_rhsr_less_than_abs_rhsi: +// PRMTD-NEXT: [[TMP11:%.*]] = fdiv x86_fp80 [[CONV]], [[CONV1]] +// PRMTD-NEXT: [[TMP12:%.*]] = fmul x86_fp80 [[TMP11]], [[CONV]] +// PRMTD-NEXT: [[TMP13:%.*]] = fadd x86_fp80 [[CONV1]], [[TMP12]] +// PRMTD-NEXT: [[TMP14:%.*]] = fmul x86_fp80 [[B_REAL]], [[TMP11]] +// PRMTD-NEXT: [[TMP15:%.*]] = fadd x86_fp80 [[TMP14]], [[B_IMAG]] +// PRMTD-NEXT: [[TMP16:%.*]] = fdiv x86_fp80 [[TMP15]], [[TMP13]] +// PRMTD-NEXT: [[TMP17:%.*]] = fmul x86_fp80 [[B_IMAG]], [[TMP11]] +// PRMTD-NEXT: [[TMP18:%.*]] = fsub x86_fp80 [[TMP17]], [[B_REAL]] +// PRMTD-NEXT: [[TMP19:%.*]] = fdiv x86_fp80 [[TMP18]], [[TMP13]] +// PRMTD-NEXT: br label [[COMPLEX_DIV]] +// PRMTD: complex_div: +// PRMTD-NEXT: [[TMP20:%.*]] = phi x86_fp80 [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// PRMTD-NEXT: [[TMP21:%.*]] = phi x86_fp80 [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// PRMTD-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP20]] to half +// PRMTD-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP21]] to half +// PRMTD-NEXT: [[EXT:%.*]] = fpext half [[CONV2]] to float +// PRMTD-NEXT: [[EXT4:%.*]] = fpext half [[CONV3]] to float +// PRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// PRMTD-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// PRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// PRMTD-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// PRMTD-NEXT: [[EXT5:%.*]] = fpext half [[A_REAL]] to float +// PRMTD-NEXT: [[EXT6:%.*]] = fpext half [[A_IMAG]] to float +// PRMTD-NEXT: [[TMP22:%.*]] = fmul float [[EXT]], [[EXT5]] +// PRMTD-NEXT: [[TMP23:%.*]] = fmul float [[EXT4]], [[EXT6]] +// PRMTD-NEXT: [[TMP24:%.*]] = fadd float [[TMP22]], [[TMP23]] +// PRMTD-NEXT: [[TMP25:%.*]] = fmul float [[EXT5]], [[EXT5]] +// PRMTD-NEXT: [[TMP26:%.*]] = fmul float [[EXT6]], [[EXT6]] +// PRMTD-NEXT: [[TMP27:%.*]] = fadd float [[TMP25]], [[TMP26]] +// PRMTD-NEXT: [[TMP28:%.*]] = fmul float [[EXT4]], [[EXT5]] +// PRMTD-NEXT: [[TMP29:%.*]] = fmul float [[EXT]], [[EXT6]] +// PRMTD-NEXT: [[TMP30:%.*]] = fsub float [[TMP28]], [[TMP29]] +// PRMTD-NEXT: [[TMP31:%.*]] = fdiv float [[TMP24]], [[TMP27]] +// PRMTD-NEXT: [[TMP32:%.*]] = fdiv float [[TMP30]], [[TMP27]] +// PRMTD-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP31]] to half +// PRMTD-NEXT: [[UNPROMOTION7:%.*]] = fptrunc float [[TMP32]] to half +// PRMTD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// PRMTD-NEXT: store half [[UNPROMOTION7]], ptr [[RETVAL_IMAGP]], align 2 +// PRMTD-NEXT: [[TMP33:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// 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-NEXT: entry: +// X86WINPRMTD-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// X86WINPRMTD-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// X86WINPRMTD-NEXT: [[C:%.*]] = alloca { half, half }, align 2 +// X86WINPRMTD-NEXT: [[B_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// X86WINPRMTD-NEXT: store i32 [[A_COERCE]], ptr [[A]], align 2 +// X86WINPRMTD-NEXT: store i32 [[C_COERCE]], ptr [[C]], align 2 +// X86WINPRMTD-NEXT: store ptr [[B]], ptr [[B_INDIRECT_ADDR]], align 8 +// X86WINPRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// X86WINPRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// X86WINPRMTD-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 +// X86WINPRMTD-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 +// X86WINPRMTD-NEXT: [[CONV:%.*]] = fpext half [[C_REAL]] to double +// X86WINPRMTD-NEXT: [[CONV1:%.*]] = fpext half [[C_IMAG]] to double +// X86WINPRMTD-NEXT: [[TMP0:%.*]] = call double @llvm.fabs.f64(double [[CONV]]) +// X86WINPRMTD-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[CONV1]]) +// X86WINPRMTD-NEXT: [[ABS_CMP:%.*]] = fcmp ugt double [[TMP0]], [[TMP1]] +// X86WINPRMTD-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// X86WINPRMTD: abs_rhsr_greater_or_equal_abs_rhsi: +// X86WINPRMTD-NEXT: [[TMP2:%.*]] = fdiv double [[CONV1]], [[CONV]] +// X86WINPRMTD-NEXT: [[TMP3:%.*]] = fmul double [[TMP2]], [[CONV1]] +// X86WINPRMTD-NEXT: [[TMP4:%.*]] = fadd double [[CONV]], [[TMP3]] +// X86WINPRMTD-NEXT: [[TMP5:%.*]] = fmul double [[B_IMAG]], [[TMP2]] +// X86WINPRMTD-NEXT: [[TMP6:%.*]] = fadd double [[B_REAL]], [[TMP5]] +// X86WINPRMTD-NEXT: [[TMP7:%.*]] = fdiv double [[TMP6]], [[TMP4]] +// X86WINPRMTD-NEXT: [[TMP8:%.*]] = fmul double [[B_REAL]], [[TMP2]] +// X86WINPRMTD-NEXT: [[TMP9:%.*]] = fsub double [[B_IMAG]], [[TMP8]] +// X86WINPRMTD-NEXT: [[TMP10:%.*]] = fdiv double [[TMP9]], [[TMP4]] +// X86WINPRMTD-NEXT: br label [[COMPLEX_DIV:%.*]] +// X86WINPRMTD: abs_rhsr_less_than_abs_rhsi: +// X86WINPRMTD-NEXT: [[TMP11:%.*]] = fdiv double [[CONV]], [[CONV1]] +// X86WINPRMTD-NEXT: [[TMP12:%.*]] = fmul double [[TMP11]], [[CONV]] +// X86WINPRMTD-NEXT: [[TMP13:%.*]] = fadd double [[CONV1]], [[TMP12]] +// X86WINPRMTD-NEXT: [[TMP14:%.*]] = fmul double [[B_REAL]], [[TMP11]] +// X86WINPRMTD-NEXT: [[TMP15:%.*]] = fadd double [[TMP14]], [[B_IMAG]] +// X86WINPRMTD-NEXT: [[TMP16:%.*]] = fdiv double [[TMP15]], [[TMP13]] +// X86WINPRMTD-NEXT: [[TMP17:%.*]] = fmul double [[B_IMAG]], [[TMP11]] +// X86WINPRMTD-NEXT: [[TMP18:%.*]] = fsub double [[TMP17]], [[B_REAL]] +// X86WINPRMTD-NEXT: [[TMP19:%.*]] = fdiv double [[TMP18]], [[TMP13]] +// X86WINPRMTD-NEXT: br label [[COMPLEX_DIV]] +// X86WINPRMTD: complex_div: +// X86WINPRMTD-NEXT: [[TMP20:%.*]] = phi double [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// X86WINPRMTD-NEXT: [[TMP21:%.*]] = phi double [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// X86WINPRMTD-NEXT: [[CONV2:%.*]] = fptrunc double [[TMP20]] to half +// X86WINPRMTD-NEXT: [[CONV3:%.*]] = fptrunc double [[TMP21]] to half +// X86WINPRMTD-NEXT: [[EXT:%.*]] = fpext half [[CONV2]] to float +// X86WINPRMTD-NEXT: [[EXT4:%.*]] = fpext half [[CONV3]] to float +// X86WINPRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// X86WINPRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// X86WINPRMTD-NEXT: [[EXT5:%.*]] = fpext half [[A_REAL]] to float +// X86WINPRMTD-NEXT: [[EXT6:%.*]] = fpext half [[A_IMAG]] to float +// X86WINPRMTD-NEXT: [[TMP22:%.*]] = fmul float [[EXT]], [[EXT5]] +// X86WINPRMTD-NEXT: [[TMP23:%.*]] = fmul float [[EXT4]], [[EXT6]] +// X86WINPRMTD-NEXT: [[TMP24:%.*]] = fadd float [[TMP22]], [[TMP23]] +// X86WINPRMTD-NEXT: [[TMP25:%.*]] = fmul float [[EXT5]], [[EXT5]] +// X86WINPRMTD-NEXT: [[TMP26:%.*]] = fmul float [[EXT6]], [[EXT6]] +// X86WINPRMTD-NEXT: [[TMP27:%.*]] = fadd float [[TMP25]], [[TMP26]] +// X86WINPRMTD-NEXT: [[TMP28:%.*]] = fmul float [[EXT4]], [[EXT5]] +// X86WINPRMTD-NEXT: [[TMP29:%.*]] = fmul float [[EXT]], [[EXT6]] +// X86WINPRMTD-NEXT: [[TMP30:%.*]] = fsub float [[TMP28]], [[TMP29]] +// X86WINPRMTD-NEXT: [[TMP31:%.*]] = fdiv float [[TMP24]], [[TMP27]] +// X86WINPRMTD-NEXT: [[TMP32:%.*]] = fdiv float [[TMP30]], [[TMP27]] +// X86WINPRMTD-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP31]] to half +// X86WINPRMTD-NEXT: [[UNPROMOTION7:%.*]] = fptrunc float [[TMP32]] to half +// X86WINPRMTD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// X86WINPRMTD-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// X86WINPRMTD-NEXT: store half [[UNPROMOTION7]], ptr [[RETVAL_IMAGP]], align 2 +// X86WINPRMTD-NEXT: [[TMP33:%.*]] = load i32, ptr [[RETVAL]], align 2 +// X86WINPRMTD-NEXT: ret i32 [[TMP33]] +// +// BASIC_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x half> @f1( +// BASIC_FAST-SAME: <2 x half> noundef nofpclass(nan inf) [[A_COERCE:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]], <2 x half> noundef nofpclass(nan inf) [[C_COERCE:%.*]]) #[[ATTR0]] { +// BASIC_FAST-NEXT: entry: +// BASIC_FAST-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// BASIC_FAST-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// BASIC_FAST-NEXT: [[C:%.*]] = alloca { half, half }, align 2 +// BASIC_FAST-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// BASIC_FAST-NEXT: store <2 x half> [[C_COERCE]], ptr [[C]], align 2 +// BASIC_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// BASIC_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// BASIC_FAST-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 +// BASIC_FAST-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 +// BASIC_FAST-NEXT: [[CONV:%.*]] = fpext half [[C_REAL]] to x86_fp80 +// BASIC_FAST-NEXT: [[CONV1:%.*]] = fpext half [[C_IMAG]] to x86_fp80 +// BASIC_FAST-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[CONV]] +// BASIC_FAST-NEXT: [[TMP1:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[CONV1]] +// BASIC_FAST-NEXT: [[TMP2:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP0]], [[TMP1]] +// BASIC_FAST-NEXT: [[TMP3:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV]], [[CONV]] +// BASIC_FAST-NEXT: [[TMP4:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV1]], [[CONV1]] +// BASIC_FAST-NEXT: [[TMP5:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP3]], [[TMP4]] +// BASIC_FAST-NEXT: [[TMP6:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[CONV]] +// BASIC_FAST-NEXT: [[TMP7:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[CONV1]] +// BASIC_FAST-NEXT: [[TMP8:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP6]], [[TMP7]] +// BASIC_FAST-NEXT: [[TMP9:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP2]], [[TMP5]] +// BASIC_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP8]], [[TMP5]] +// BASIC_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP9]] to half +// BASIC_FAST-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP10]] to half +// BASIC_FAST-NEXT: [[EXT:%.*]] = fpext half [[CONV2]] to float +// BASIC_FAST-NEXT: [[EXT4:%.*]] = fpext half [[CONV3]] to float +// BASIC_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// BASIC_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// BASIC_FAST-NEXT: [[EXT5:%.*]] = fpext half [[A_REAL]] to float +// BASIC_FAST-NEXT: [[EXT6:%.*]] = fpext half [[A_IMAG]] to float +// BASIC_FAST-NEXT: [[TMP11:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT5]] +// BASIC_FAST-NEXT: [[TMP12:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT4]], [[EXT6]] +// BASIC_FAST-NEXT: [[TMP13:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP11]], [[TMP12]] +// BASIC_FAST-NEXT: [[TMP14:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT5]], [[EXT5]] +// BASIC_FAST-NEXT: [[TMP15:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT6]], [[EXT6]] +// BASIC_FAST-NEXT: [[TMP16:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP14]], [[TMP15]] +// BASIC_FAST-NEXT: [[TMP17:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT4]], [[EXT5]] +// BASIC_FAST-NEXT: [[TMP18:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT6]] +// BASIC_FAST-NEXT: [[TMP19:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[TMP17]], [[TMP18]] +// BASIC_FAST-NEXT: [[TMP20:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP13]], [[TMP16]] +// BASIC_FAST-NEXT: [[TMP21:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP19]], [[TMP16]] +// BASIC_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP20]] to half +// BASIC_FAST-NEXT: [[UNPROMOTION7:%.*]] = fptrunc float [[TMP21]] to half +// BASIC_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// BASIC_FAST-NEXT: store half [[UNPROMOTION7]], ptr [[RETVAL_IMAGP]], align 2 +// BASIC_FAST-NEXT: [[TMP22:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// BASIC_FAST-NEXT: ret <2 x half> [[TMP22]] +// +// FULL_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x half> @f1( +// FULL_FAST-SAME: <2 x half> noundef nofpclass(nan inf) [[A_COERCE:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]], <2 x half> noundef nofpclass(nan inf) [[C_COERCE:%.*]]) #[[ATTR0]] { +// FULL_FAST-NEXT: entry: +// FULL_FAST-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// FULL_FAST-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// FULL_FAST-NEXT: [[C:%.*]] = alloca { half, half }, align 2 +// FULL_FAST-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4 +// FULL_FAST-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// FULL_FAST-NEXT: store <2 x half> [[C_COERCE]], ptr [[C]], align 2 +// FULL_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// FULL_FAST-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// FULL_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// FULL_FAST-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// FULL_FAST-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 0 +// FULL_FAST-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 +// FULL_FAST-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 1 +// FULL_FAST-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 +// FULL_FAST-NEXT: [[CONV:%.*]] = fpext half [[C_REAL]] to x86_fp80 +// FULL_FAST-NEXT: [[CONV1:%.*]] = fpext half [[C_IMAG]] to x86_fp80 +// FULL_FAST-NEXT: [[CALL:%.*]] = call { x86_fp80, x86_fp80 } @__divxc3(x86_fp80 noundef nofpclass(nan inf) [[B_REAL]], x86_fp80 noundef nofpclass(nan inf) [[B_IMAG]], x86_fp80 noundef nofpclass(nan inf) [[CONV]], x86_fp80 noundef nofpclass(nan inf) [[CONV1]]) #[[ATTR1]] +// FULL_FAST-NEXT: [[TMP0:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 0 +// FULL_FAST-NEXT: [[TMP1:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 1 +// FULL_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP0]] to half +// FULL_FAST-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP1]] to half +// FULL_FAST-NEXT: [[EXT:%.*]] = fpext half [[CONV2]] to float +// FULL_FAST-NEXT: [[EXT4:%.*]] = fpext half [[CONV3]] to float +// FULL_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// FULL_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// FULL_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// FULL_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// FULL_FAST-NEXT: [[EXT5:%.*]] = fpext half [[A_REAL]] to float +// FULL_FAST-NEXT: [[EXT6:%.*]] = fpext half [[A_IMAG]] to float +// FULL_FAST-NEXT: [[CALL7:%.*]] = call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) <2 x float> @__divsc3(float noundef nofpclass(nan inf) [[EXT]], float noundef nofpclass(nan inf) [[EXT4]], float noundef nofpclass(nan inf) [[EXT5]], float noundef nofpclass(nan inf) [[EXT6]]) #[[ATTR1]] +// FULL_FAST-NEXT: store <2 x float> [[CALL7]], ptr [[COERCE]], align 4 +// FULL_FAST-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 0 +// FULL_FAST-NEXT: [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4 +// FULL_FAST-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 1 +// FULL_FAST-NEXT: [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4 +// FULL_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[COERCE_REAL]] to half +// FULL_FAST-NEXT: [[UNPROMOTION8:%.*]] = fptrunc float [[COERCE_IMAG]] to half +// FULL_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// FULL_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// FULL_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// FULL_FAST-NEXT: store half [[UNPROMOTION8]], ptr [[RETVAL_IMAGP]], align 2 +// FULL_FAST-NEXT: [[TMP2:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// FULL_FAST-NEXT: ret <2 x half> [[TMP2]] +// +// IMPRVD_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x half> @f1( +// IMPRVD_FAST-SAME: <2 x half> noundef nofpclass(nan inf) [[A_COERCE:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]], <2 x half> noundef nofpclass(nan inf) [[C_COERCE:%.*]]) #[[ATTR0]] { +// IMPRVD_FAST-NEXT: entry: +// IMPRVD_FAST-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// IMPRVD_FAST-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// IMPRVD_FAST-NEXT: [[C:%.*]] = alloca { half, half }, align 2 +// IMPRVD_FAST-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// IMPRVD_FAST-NEXT: store <2 x half> [[C_COERCE]], ptr [[C]], align 2 +// IMPRVD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// IMPRVD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// IMPRVD_FAST-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 +// IMPRVD_FAST-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 +// IMPRVD_FAST-NEXT: [[CONV:%.*]] = fpext half [[C_REAL]] to x86_fp80 +// IMPRVD_FAST-NEXT: [[CONV1:%.*]] = fpext half [[C_IMAG]] to x86_fp80 +// IMPRVD_FAST-NEXT: [[TMP0:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV]]) +// IMPRVD_FAST-NEXT: [[TMP1:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV1]]) +// IMPRVD_FAST-NEXT: [[ABS_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn ugt x86_fp80 [[TMP0]], [[TMP1]] +// IMPRVD_FAST-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// IMPRVD_FAST: abs_rhsr_greater_or_equal_abs_rhsi: +// IMPRVD_FAST-NEXT: [[TMP2:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV1]], [[CONV]] +// IMPRVD_FAST-NEXT: [[TMP3:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP2]], [[CONV1]] +// IMPRVD_FAST-NEXT: [[TMP4:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV]], [[TMP3]] +// IMPRVD_FAST-NEXT: [[TMP5:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[TMP2]] +// IMPRVD_FAST-NEXT: [[TMP6:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[TMP5]] +// IMPRVD_FAST-NEXT: [[TMP7:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP6]], [[TMP4]] +// IMPRVD_FAST-NEXT: [[TMP8:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[TMP2]] +// IMPRVD_FAST-NEXT: [[TMP9:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[TMP8]] +// IMPRVD_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP9]], [[TMP4]] +// IMPRVD_FAST-NEXT: br label [[COMPLEX_DIV:%.*]] +// IMPRVD_FAST: abs_rhsr_less_than_abs_rhsi: +// IMPRVD_FAST-NEXT: [[TMP11:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV]], [[CONV1]] +// IMPRVD_FAST-NEXT: [[TMP12:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP11]], [[CONV]] +// IMPRVD_FAST-NEXT: [[TMP13:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV1]], [[TMP12]] +// IMPRVD_FAST-NEXT: [[TMP14:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[TMP11]] +// IMPRVD_FAST-NEXT: [[TMP15:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP14]], [[B_IMAG]] +// IMPRVD_FAST-NEXT: [[TMP16:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP15]], [[TMP13]] +// IMPRVD_FAST-NEXT: [[TMP17:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[TMP11]] +// IMPRVD_FAST-NEXT: [[TMP18:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP17]], [[B_REAL]] +// IMPRVD_FAST-NEXT: [[TMP19:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP18]], [[TMP13]] +// IMPRVD_FAST-NEXT: br label [[COMPLEX_DIV]] +// IMPRVD_FAST: complex_div: +// IMPRVD_FAST-NEXT: [[TMP20:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD_FAST-NEXT: [[TMP21:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP20]] to half +// IMPRVD_FAST-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP21]] to half +// IMPRVD_FAST-NEXT: [[EXT:%.*]] = fpext half [[CONV2]] to float +// IMPRVD_FAST-NEXT: [[EXT4:%.*]] = fpext half [[CONV3]] to float +// IMPRVD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// IMPRVD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// IMPRVD_FAST-NEXT: [[EXT5:%.*]] = fpext half [[A_REAL]] to float +// IMPRVD_FAST-NEXT: [[EXT6:%.*]] = fpext half [[A_IMAG]] to float +// IMPRVD_FAST-NEXT: [[TMP22:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.fabs.f32(float [[EXT5]]) +// IMPRVD_FAST-NEXT: [[TMP23:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.fabs.f32(float [[EXT6]]) +// IMPRVD_FAST-NEXT: [[ABS_CMP7:%.*]] = fcmp reassoc nnan ninf nsz arcp afn ugt float [[TMP22]], [[TMP23]] +// IMPRVD_FAST-NEXT: br i1 [[ABS_CMP7]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI8:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI9:%.*]] +// IMPRVD_FAST: abs_rhsr_greater_or_equal_abs_rhsi8: +// IMPRVD_FAST-NEXT: [[TMP24:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[EXT6]], [[EXT5]] +// IMPRVD_FAST-NEXT: [[TMP25:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP24]], [[EXT6]] +// IMPRVD_FAST-NEXT: [[TMP26:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[EXT5]], [[TMP25]] +// IMPRVD_FAST-NEXT: [[TMP27:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT4]], [[TMP24]] +// IMPRVD_FAST-NEXT: [[TMP28:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[EXT]], [[TMP27]] +// IMPRVD_FAST-NEXT: [[TMP29:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP28]], [[TMP26]] +// IMPRVD_FAST-NEXT: [[TMP30:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[TMP24]] +// IMPRVD_FAST-NEXT: [[TMP31:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[EXT4]], [[TMP30]] +// IMPRVD_FAST-NEXT: [[TMP32:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP31]], [[TMP26]] +// IMPRVD_FAST-NEXT: br label [[COMPLEX_DIV10:%.*]] +// IMPRVD_FAST: abs_rhsr_less_than_abs_rhsi9: +// IMPRVD_FAST-NEXT: [[TMP33:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[EXT5]], [[EXT6]] +// IMPRVD_FAST-NEXT: [[TMP34:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP33]], [[EXT5]] +// IMPRVD_FAST-NEXT: [[TMP35:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[EXT6]], [[TMP34]] +// IMPRVD_FAST-NEXT: [[TMP36:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[TMP33]] +// IMPRVD_FAST-NEXT: [[TMP37:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP36]], [[EXT4]] +// IMPRVD_FAST-NEXT: [[TMP38:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP37]], [[TMP35]] +// IMPRVD_FAST-NEXT: [[TMP39:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT4]], [[TMP33]] +// IMPRVD_FAST-NEXT: [[TMP40:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[TMP39]], [[EXT]] +// IMPRVD_FAST-NEXT: [[TMP41:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP40]], [[TMP35]] +// IMPRVD_FAST-NEXT: br label [[COMPLEX_DIV10]] +// IMPRVD_FAST: complex_div10: +// IMPRVD_FAST-NEXT: [[TMP42:%.*]] = phi reassoc nnan ninf nsz arcp afn float [ [[TMP29]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI8]] ], [ [[TMP38]], [[ABS_RHSR_LESS_THAN_ABS_RHSI9]] ] +// IMPRVD_FAST-NEXT: [[TMP43:%.*]] = phi reassoc nnan ninf nsz arcp afn float [ [[TMP32]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI8]] ], [ [[TMP41]], [[ABS_RHSR_LESS_THAN_ABS_RHSI9]] ] +// IMPRVD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP42]] to half +// IMPRVD_FAST-NEXT: [[UNPROMOTION11:%.*]] = fptrunc float [[TMP43]] to half +// IMPRVD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// IMPRVD_FAST-NEXT: store half [[UNPROMOTION11]], ptr [[RETVAL_IMAGP]], align 2 +// IMPRVD_FAST-NEXT: [[TMP44:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// IMPRVD_FAST-NEXT: ret <2 x half> [[TMP44]] +// +// PRMTD_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x half> @f1( +// PRMTD_FAST-SAME: <2 x half> noundef nofpclass(nan inf) [[A_COERCE:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]], <2 x half> noundef nofpclass(nan inf) [[C_COERCE:%.*]]) #[[ATTR0]] { +// PRMTD_FAST-NEXT: entry: +// PRMTD_FAST-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 +// PRMTD_FAST-NEXT: [[A:%.*]] = alloca { half, half }, align 2 +// PRMTD_FAST-NEXT: [[C:%.*]] = alloca { half, half }, align 2 +// PRMTD_FAST-NEXT: store <2 x half> [[A_COERCE]], ptr [[A]], align 2 +// PRMTD_FAST-NEXT: store <2 x half> [[C_COERCE]], ptr [[C]], align 2 +// PRMTD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// PRMTD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// PRMTD_FAST-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 +// PRMTD_FAST-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[C]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 +// PRMTD_FAST-NEXT: [[CONV:%.*]] = fpext half [[C_REAL]] to x86_fp80 +// PRMTD_FAST-NEXT: [[CONV1:%.*]] = fpext half [[C_IMAG]] to x86_fp80 +// PRMTD_FAST-NEXT: [[TMP0:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV]]) +// PRMTD_FAST-NEXT: [[TMP1:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV1]]) +// PRMTD_FAST-NEXT: [[ABS_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn ugt x86_fp80 [[TMP0]], [[TMP1]] +// PRMTD_FAST-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// PRMTD_FAST: abs_rhsr_greater_or_equal_abs_rhsi: +// PRMTD_FAST-NEXT: [[TMP2:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV1]], [[CONV]] +// PRMTD_FAST-NEXT: [[TMP3:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP2]], [[CONV1]] +// PRMTD_FAST-NEXT: [[TMP4:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV]], [[TMP3]] +// PRMTD_FAST-NEXT: [[TMP5:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[TMP2]] +// PRMTD_FAST-NEXT: [[TMP6:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[TMP5]] +// PRMTD_FAST-NEXT: [[TMP7:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP6]], [[TMP4]] +// PRMTD_FAST-NEXT: [[TMP8:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[TMP2]] +// PRMTD_FAST-NEXT: [[TMP9:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[TMP8]] +// PRMTD_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP9]], [[TMP4]] +// PRMTD_FAST-NEXT: br label [[COMPLEX_DIV:%.*]] +// PRMTD_FAST: abs_rhsr_less_than_abs_rhsi: +// PRMTD_FAST-NEXT: [[TMP11:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV]], [[CONV1]] +// PRMTD_FAST-NEXT: [[TMP12:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP11]], [[CONV]] +// PRMTD_FAST-NEXT: [[TMP13:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV1]], [[TMP12]] +// PRMTD_FAST-NEXT: [[TMP14:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[TMP11]] +// PRMTD_FAST-NEXT: [[TMP15:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP14]], [[B_IMAG]] +// PRMTD_FAST-NEXT: [[TMP16:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP15]], [[TMP13]] +// PRMTD_FAST-NEXT: [[TMP17:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[TMP11]] +// PRMTD_FAST-NEXT: [[TMP18:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP17]], [[B_REAL]] +// PRMTD_FAST-NEXT: [[TMP19:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP18]], [[TMP13]] +// PRMTD_FAST-NEXT: br label [[COMPLEX_DIV]] +// PRMTD_FAST: complex_div: +// PRMTD_FAST-NEXT: [[TMP20:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// PRMTD_FAST-NEXT: [[TMP21:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// PRMTD_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP20]] to half +// PRMTD_FAST-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP21]] to half +// PRMTD_FAST-NEXT: [[EXT:%.*]] = fpext half [[CONV2]] to float +// PRMTD_FAST-NEXT: [[EXT4:%.*]] = fpext half [[CONV3]] to float +// PRMTD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 +// PRMTD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[A]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 +// PRMTD_FAST-NEXT: [[EXT5:%.*]] = fpext half [[A_REAL]] to float +// PRMTD_FAST-NEXT: [[EXT6:%.*]] = fpext half [[A_IMAG]] to float +// PRMTD_FAST-NEXT: [[TMP22:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT5]] +// PRMTD_FAST-NEXT: [[TMP23:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT4]], [[EXT6]] +// PRMTD_FAST-NEXT: [[TMP24:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP22]], [[TMP23]] +// PRMTD_FAST-NEXT: [[TMP25:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT5]], [[EXT5]] +// PRMTD_FAST-NEXT: [[TMP26:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT6]], [[EXT6]] +// PRMTD_FAST-NEXT: [[TMP27:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP25]], [[TMP26]] +// PRMTD_FAST-NEXT: [[TMP28:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT4]], [[EXT5]] +// PRMTD_FAST-NEXT: [[TMP29:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[EXT]], [[EXT6]] +// PRMTD_FAST-NEXT: [[TMP30:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[TMP28]], [[TMP29]] +// PRMTD_FAST-NEXT: [[TMP31:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP24]], [[TMP27]] +// PRMTD_FAST-NEXT: [[TMP32:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP30]], [[TMP27]] +// PRMTD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP31]] to half +// PRMTD_FAST-NEXT: [[UNPROMOTION7:%.*]] = fptrunc float [[TMP32]] to half +// PRMTD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { half, half }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD_FAST-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 +// PRMTD_FAST-NEXT: store half [[UNPROMOTION7]], ptr [[RETVAL_IMAGP]], align 2 +// PRMTD_FAST-NEXT: [[TMP33:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 +// PRMTD_FAST-NEXT: ret <2 x half> [[TMP33]] +// +_Complex _Float16 f1(_Complex _Float16 a, _Complex long double b, _Complex _Float16 c) { + return (_Complex _Float16)(b / c) / a; +} diff --git a/clang/test/CodeGen/X86/va-arg-sse.c b/clang/test/CodeGen/X86/va-arg-sse.c index e040b0e5790bd17c92381059d1a657fea6eeeb6d..b7d00dad1453d3b97297104733f8ac315bde71a4 100644 --- a/clang/test/CodeGen/X86/va-arg-sse.c +++ b/clang/test/CodeGen/X86/va-arg-sse.c @@ -21,7 +21,7 @@ struct S a[5]; // CHECK-NEXT: store i32 0, ptr [[J]], align 4 // CHECK-NEXT: store i32 0, ptr [[K]], align 4 // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[AP]], i64 0, i64 0 -// CHECK-NEXT: call void @llvm.va_start(ptr [[ARRAYDECAY]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) // CHECK-NEXT: store ptr getelementptr inbounds ([5 x %struct.S], ptr @a, i64 0, i64 2), ptr [[P]], align 8 // CHECK-NEXT: [[ARRAYDECAY2:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[AP]], i64 0, i64 0 // CHECK-NEXT: [[FP_OFFSET_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY2]], i32 0, i32 1 @@ -52,7 +52,7 @@ struct S a[5]; // CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[TMP]], [[VAARG_IN_REG]] ], [ [[OVERFLOW_ARG_AREA]], [[VAARG_IN_MEM]] ] // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[ARG]], ptr align 4 [[VAARG_ADDR]], i64 12, i1 false) // CHECK-NEXT: [[ARRAYDECAY3:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[AP]], i64 0, i64 0 -// CHECK-NEXT: call void @llvm.va_end(ptr [[ARRAYDECAY3]]) +// CHECK-NEXT: call void @llvm.va_end.p0(ptr [[ARRAYDECAY3]]) // CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[P]], align 8 // CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[TMP15]], null // CHECK-NEXT: br i1 [[TOBOOL]], label [[LAND_LHS_TRUE:%.*]], label [[IF_END:%.*]] diff --git a/clang/test/CodeGen/X86/x86_64-vaarg.c b/clang/test/CodeGen/X86/x86_64-vaarg.c new file mode 100644 index 0000000000000000000000000000000000000000..07c6df14a0b812061219e21cf2189e9b9a797e7a --- /dev/null +++ b/clang/test/CodeGen/X86/x86_64-vaarg.c @@ -0,0 +1,69 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s + + +typedef struct { struct {} a; } empty; + +// CHECK-LABEL: define dso_local void @empty_record_test( +// CHECK-SAME: i32 noundef [[Z:%.*]], ...) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1 +// CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_EMPTY]], align 1 +// CHECK-NEXT: store i32 [[Z]], ptr [[Z_ADDR]], align 4 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) +// CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[RETVAL]], ptr align 1 [[TMP]], i64 0, i1 false) +// CHECK-NEXT: ret void +// +empty empty_record_test(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); + return __builtin_va_arg(list, empty); +} + +typedef struct { + struct{} a; + double b; +} s1; + +// CHECK-LABEL: define dso_local double @f( +// CHECK-SAME: i32 noundef [[Z:%.*]], ...) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 +// CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT: store i32 [[Z]], ptr [[Z_ADDR]], align 4 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) +// CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 +// CHECK-NEXT: [[FP_OFFSET_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY1]], i32 0, i32 1 +// CHECK-NEXT: [[FP_OFFSET:%.*]] = load i32, ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT: [[FITS_IN_FP:%.*]] = icmp ule i32 [[FP_OFFSET]], 160 +// CHECK-NEXT: br i1 [[FITS_IN_FP]], label [[VAARG_IN_REG:%.*]], label [[VAARG_IN_MEM:%.*]] +// CHECK: vaarg.in_reg: +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 +// CHECK-NEXT: [[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] +// CHECK-NEXT: [[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT: br label [[VAARG_END:%.*]] +// CHECK: vaarg.in_mem: +// CHECK-NEXT: [[OVERFLOW_ARG_AREA_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 2 +// CHECK-NEXT: [[OVERFLOW_ARG_AREA:%.*]] = load ptr, ptr [[OVERFLOW_ARG_AREA_P]], align 8 +// CHECK-NEXT: [[OVERFLOW_ARG_AREA_NEXT:%.*]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i32 8 +// CHECK-NEXT: store ptr [[OVERFLOW_ARG_AREA_NEXT]], ptr [[OVERFLOW_ARG_AREA_P]], align 8 +// CHECK-NEXT: br label [[VAARG_END]] +// CHECK: vaarg.end: +// CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[TMP1]], [[VAARG_IN_REG]] ], [ [[OVERFLOW_ARG_AREA]], [[VAARG_IN_MEM]] ] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[VAARG_ADDR]], i64 8, i1 false) +// CHECK-NEXT: [[TMP3:%.*]] = load double, ptr [[RETVAL]], align 8 +// CHECK-NEXT: ret double [[TMP3]] +// +s1 f(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); + return __builtin_va_arg(list, s1); +} diff --git a/clang/test/CodeGen/aapcs-align.cpp b/clang/test/CodeGen/aapcs-align.cpp index 2886a32974b0665e2965e7dc246b0d1ccb38e1ac..4f393d9e6b7f3205534bfd27daed576d36c33b51 100644 --- a/clang/test/CodeGen/aapcs-align.cpp +++ b/clang/test/CodeGen/aapcs-align.cpp @@ -134,8 +134,8 @@ void g6() { f6m(1, 2, 3, 4, 5, s); } // CHECK: define{{.*}} void @g6 -// CHECK: call void @f6(i32 noundef 1, [4 x i32] [i32 6, i32 7, i32 0, i32 0]) -// CHECK: call void @f6m(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 noundef 4, i32 noundef 5, [4 x i32] [i32 6, i32 7, i32 0, i32 0]) +// CHECK: call void @f6(i32 noundef 1, [4 x i32] [i32 6, i32 7, i32 0, i32 undef]) +// CHECK: call void @f6m(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 noundef 4, i32 noundef 5, [4 x i32] [i32 6, i32 7, i32 0, i32 undef]) // CHECK: declare void @f6(i32 noundef, [4 x i32]) // CHECK: declare void @f6m(i32 noundef, i32 noundef, i32 noundef, i32 noundef, i32 noundef, [4 x i32]) } diff --git a/clang/test/CodeGen/aapcs-bitfield-access-unit.c b/clang/test/CodeGen/aapcs-bitfield-access-unit.c new file mode 100644 index 0000000000000000000000000000000000000000..e95dba1c5f50cf63f3f77c582f04b297b903e533 --- /dev/null +++ b/clang/test/CodeGen/aapcs-bitfield-access-unit.c @@ -0,0 +1,231 @@ +// RUN: %clang_cc1 -triple armv8-none-linux-eabi -fno-aapcs-bitfield-width -fdump-record-layouts-simple -emit-llvm -o /dev/null %s | FileCheck %s -check-prefixes=LAYOUT +// RUN: %clang_cc1 -triple armebv8-none-linux-eabi -fno-aapcs-bitfield-width -fdump-record-layouts-simple -emit-llvm -o /dev/null %s | FileCheck %s -check-prefixes=LAYOUT + +// RUN: %clang_cc1 -triple armv8-none-linux-eabi -faapcs-bitfield-width -fdump-record-layouts-simple -emit-llvm -o /dev/null %s | FileCheck %s -check-prefixes=LAYOUT +// RUN: %clang_cc1 -triple armebv8-none-linux-eabi -faapcs-bitfield-width -fdump-record-layouts-simple -emit-llvm -o /dev/null %s | FileCheck %s -check-prefixes=LAYOUT + +struct st0 { + short c : 7; +} st0; +// LAYOUT-LABEL: LLVMType:%struct.st0 = +// LAYOUT-SAME: type { i8, i8 } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:8 StorageOffset:0 +// LAYOUT-NEXT: ]> + +struct st1 { + int a : 10; + short c : 6; +} st1; +// LAYOUT-LABEL: LLVMType:%struct.st1 = +// LAYOUT-SAME: type { i16, [2 x i8] } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:10 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:6 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: ]> + +struct st2 { + int a : 10; + short c : 7; +} st2; +// LAYOUT-LABEL: LLVMType:%struct.st2 = +// LAYOUT-SAME: type { i32 } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:10 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: ]> + +struct st3 { + volatile short c : 7; +} st3; +// LAYOUT-LABEL: LLVMType:%struct.st3 = +// LAYOUT-SAME: type { i8, i8 } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:8 StorageOffset:0 +// LAYOUT-NEXT: ]> + +struct st4 { + int b : 9; + volatile char c : 5; +} st4; +// LAYOUT-LABEL: LLVMType:%struct.st4 = +// LAYOUT-SAME: type { i16, [2 x i8] } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:9 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:5 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: ]> + +struct st5 { + int a : 12; + volatile char c : 5; +} st5; +// LAYOUT-LABEL: LLVMType:%struct.st5 = +// LAYOUT-SAME: type { i32 } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:12 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:5 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: ]> + +struct st6 { + int a : 12; + char b; + int c : 5; +} st6; +// LAYOUT-LABEL: LLVMType:%struct.st6 = +// LAYOUT-SAME: type { i16, i8, i8 } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:12 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:5 IsSigned:1 StorageSize:8 StorageOffset:3 +// LAYOUT-NEXT: ]> + +struct st7a { + char a; + int b : 5; +} st7a; +// LAYOUT-LABEL: LLVMType:%struct.st7a = +// LAYOUT-SAME: type { i8, i8, [2 x i8] } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:5 IsSigned:1 StorageSize:8 StorageOffset:1 +// LAYOUT-NEXT: ]> + +struct st7b { + char x; + volatile struct st7a y; +} st7b; +// LAYOUT-LABEL: LLVMType:%struct.st7b = +// LAYOUT-SAME: type { i8, [3 x i8], %struct.st7a } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: ]> + +struct st8 { + unsigned f : 16; +} st8; +// LAYOUT-LABEL: LLVMType:%struct.st8 = +// LAYOUT-SAME: type { i16, [2 x i8] } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: ]> + +struct st9{ + int f : 8; +} st9; +// LAYOUT-LABEL: LLVMType:%struct.st9 = +// LAYOUT-SAME: type { i8, [3 x i8] } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:0 +// LAYOUT-NEXT: ]> + +struct st10{ + int e : 1; + int f : 8; +} st10; +// LAYOUT-LABEL: LLVMType:%struct.st10 = +// LAYOUT-SAME: type { i16, [2 x i8] } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:1 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: ]> + +struct st11{ + char e; + int f : 16; +} st11; +// LAYOUT-LABEL: LLVMType:%struct.st11 = +// LAYOUT-SAME: type <{ i8, i16, i8 }> +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:1 +// LAYOUT-NEXT: ]> + +struct st12{ + int e : 8; + int f : 16; +} st12; +// LAYOUT-LABEL: LLVMType:%struct.st12 = +// LAYOUT-SAME: type { i32 } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: ]> + +struct st13 { + char a : 8; + int b : 32; +} __attribute__((packed)) st13; +// LAYOUT-LABEL: LLVMType:%struct.st13 = +// LAYOUT-SAME: type <{ i8, i32 }> +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:32 IsSigned:1 StorageSize:32 StorageOffset:1 +// LAYOUT-NEXT: ]> + +struct st14 { + char a : 8; +} __attribute__((packed)) st14; +// LAYOUT-LABEL: LLVMType:%struct.st14 = +// LAYOUT-SAME: type { i8 } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:0 +// LAYOUT-NEXT: ]> + +struct st15 { + short a : 8; +} __attribute__((packed)) st15; +// LAYOUT-LABEL: LLVMType:%struct.st15 = +// LAYOUT-SAME: type { i8 } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:0 +// LAYOUT-NEXT: ]> + +struct st16 { + int a : 32; + int b : 16; + int c : 32; + int d : 16; +} st16; +// LAYOUT-LABEL: LLVMType:%struct.st16 = +// LAYOUT-SAME: type { i32, i16, i32, i16 } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:32 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:4 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:32 IsSigned:1 StorageSize:32 StorageOffset:8 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:12 +// LAYOUT-NEXT: ]> + +struct st17 { +int b : 32; +char c : 8; +} __attribute__((packed)) st17; +// LAYOUT-LABEL: LLVMType:%struct.st17 = +// LAYOUT-SAME: type <{ i32, i8 }> +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:32 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:4 +// LAYOUT-NEXT: ]> + +struct zero_bitfield { + int a : 8; + char : 0; + int b : 8; +} st18; +// LAYOUT-LABEL: LLVMType:%struct.zero_bitfield = +// LAYOUT-SAME: type { i8, i8, [2 x i8] } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:1 +// LAYOUT-NEXT: ]> + +struct zero_bitfield_ok { + short a : 8; + char a1 : 8; + long : 0; + int b : 24; +} st19; +// LAYOUT-LABEL: LLVMType:%struct.zero_bitfield_ok = +// LAYOUT-SAME: type { i16, i32 } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:24 IsSigned:1 StorageSize:32 StorageOffset:4 +// LAYOUT-NEXT: ]> + + diff --git a/clang/test/CodeGen/aapcs-bitfield.c b/clang/test/CodeGen/aapcs-bitfield.c index 152ee26e7a3ea94a60be2ccd546c666a2cd49bd9..0df250d4ebc53e45723f76f99a69b0e626a7fd2e 100644 --- a/clang/test/CodeGen/aapcs-bitfield.c +++ b/clang/test/CodeGen/aapcs-bitfield.c @@ -299,77 +299,73 @@ struct st2 { // LE-LABEL: @st2_check_load( // LE-NEXT: entry: -// LE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST2:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// LE-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[C]], align 2 -// LE-NEXT: [[BF_SHL:%.*]] = shl i8 [[BF_LOAD]], 1 -// LE-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_SHL]], 1 -// LE-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_ASHR]] to i16 +// LE-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[M:%.*]], align 4 +// LE-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_LOAD]], 9 +// LE-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_SHL]], 25 +// LE-NEXT: [[BF_CAST:%.*]] = trunc i32 [[BF_ASHR]] to i16 // LE-NEXT: [[CONV:%.*]] = sext i16 [[BF_CAST]] to i32 // LE-NEXT: ret i32 [[CONV]] // // BE-LABEL: @st2_check_load( // BE-NEXT: entry: -// BE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST2:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// BE-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[C]], align 2 -// BE-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_LOAD]], 1 -// BE-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_ASHR]] to i16 +// BE-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[M:%.*]], align 4 +// BE-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_LOAD]], 16 +// BE-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_SHL]], 25 +// BE-NEXT: [[BF_CAST:%.*]] = trunc i32 [[BF_ASHR]] to i16 // BE-NEXT: [[CONV:%.*]] = sext i16 [[BF_CAST]] to i32 // BE-NEXT: ret i32 [[CONV]] // // LENUMLOADS-LABEL: @st2_check_load( // LENUMLOADS-NEXT: entry: -// LENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST2:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[C]], align 2 -// LENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i8 [[BF_LOAD]], 1 -// LENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_SHL]], 1 -// LENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_ASHR]] to i16 +// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[M:%.*]], align 4 +// LENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_LOAD]], 9 +// LENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_SHL]], 25 +// LENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i32 [[BF_ASHR]] to i16 // LENUMLOADS-NEXT: [[CONV:%.*]] = sext i16 [[BF_CAST]] to i32 // LENUMLOADS-NEXT: ret i32 [[CONV]] // // BENUMLOADS-LABEL: @st2_check_load( // BENUMLOADS-NEXT: entry: -// BENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST2:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[C]], align 2 -// BENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_LOAD]], 1 -// BENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_ASHR]] to i16 +// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[M:%.*]], align 4 +// BENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_LOAD]], 16 +// BENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_SHL]], 25 +// BENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i32 [[BF_ASHR]] to i16 // BENUMLOADS-NEXT: [[CONV:%.*]] = sext i16 [[BF_CAST]] to i32 // BENUMLOADS-NEXT: ret i32 [[CONV]] // // LEWIDTH-LABEL: @st2_check_load( // LEWIDTH-NEXT: entry: -// LEWIDTH-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST2:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[C]], align 2 -// LEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i8 [[BF_LOAD]], 1 -// LEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_SHL]], 1 -// LEWIDTH-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_ASHR]] to i16 +// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[M:%.*]], align 4 +// LEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_LOAD]], 9 +// LEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_SHL]], 25 +// LEWIDTH-NEXT: [[BF_CAST:%.*]] = trunc i32 [[BF_ASHR]] to i16 // LEWIDTH-NEXT: [[CONV:%.*]] = sext i16 [[BF_CAST]] to i32 // LEWIDTH-NEXT: ret i32 [[CONV]] // // BEWIDTH-LABEL: @st2_check_load( // BEWIDTH-NEXT: entry: -// BEWIDTH-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST2:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[C]], align 2 -// BEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_LOAD]], 1 -// BEWIDTH-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_ASHR]] to i16 +// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[M:%.*]], align 4 +// BEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_LOAD]], 16 +// BEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_SHL]], 25 +// BEWIDTH-NEXT: [[BF_CAST:%.*]] = trunc i32 [[BF_ASHR]] to i16 // BEWIDTH-NEXT: [[CONV:%.*]] = sext i16 [[BF_CAST]] to i32 // BEWIDTH-NEXT: ret i32 [[CONV]] // // LEWIDTHNUM-LABEL: @st2_check_load( // LEWIDTHNUM-NEXT: entry: -// LEWIDTHNUM-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST2:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[C]], align 2 -// LEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i8 [[BF_LOAD]], 1 -// LEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_SHL]], 1 -// LEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_ASHR]] to i16 +// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[M:%.*]], align 4 +// LEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_LOAD]], 9 +// LEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_SHL]], 25 +// LEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = trunc i32 [[BF_ASHR]] to i16 // LEWIDTHNUM-NEXT: [[CONV:%.*]] = sext i16 [[BF_CAST]] to i32 // LEWIDTHNUM-NEXT: ret i32 [[CONV]] // // BEWIDTHNUM-LABEL: @st2_check_load( // BEWIDTHNUM-NEXT: entry: -// BEWIDTHNUM-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST2:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[C]], align 2 -// BEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_LOAD]], 1 -// BEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_ASHR]] to i16 +// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[M:%.*]], align 4 +// BEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_LOAD]], 16 +// BEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_SHL]], 25 +// BEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = trunc i32 [[BF_ASHR]] to i16 // BEWIDTHNUM-NEXT: [[CONV:%.*]] = sext i16 [[BF_CAST]] to i32 // BEWIDTHNUM-NEXT: ret i32 [[CONV]] // @@ -379,74 +375,66 @@ int st2_check_load(struct st2 *m) { // LE-LABEL: @st2_check_store( // LE-NEXT: entry: -// LE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST2:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// LE-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[C]], align 2 -// LE-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], -128 -// LE-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 1 -// LE-NEXT: store i8 [[BF_SET]], ptr [[C]], align 2 +// LE-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[M:%.*]], align 4 +// LE-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD]], -8323073 +// LE-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], 65536 +// LE-NEXT: store i32 [[BF_SET]], ptr [[M]], align 4 // LE-NEXT: ret void // // BE-LABEL: @st2_check_store( // BE-NEXT: entry: -// BE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST2:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// BE-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[C]], align 2 -// BE-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], 1 -// BE-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 2 -// BE-NEXT: store i8 [[BF_SET]], ptr [[C]], align 2 +// BE-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[M:%.*]], align 4 +// BE-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD]], -65025 +// BE-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], 512 +// BE-NEXT: store i32 [[BF_SET]], ptr [[M]], align 4 // BE-NEXT: ret void // // LENUMLOADS-LABEL: @st2_check_store( // LENUMLOADS-NEXT: entry: -// LENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST2:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[C]], align 2 -// LENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], -128 -// LENUMLOADS-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 1 -// LENUMLOADS-NEXT: store i8 [[BF_SET]], ptr [[C]], align 2 +// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[M:%.*]], align 4 +// LENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD]], -8323073 +// LENUMLOADS-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], 65536 +// LENUMLOADS-NEXT: store i32 [[BF_SET]], ptr [[M]], align 4 // LENUMLOADS-NEXT: ret void // // BENUMLOADS-LABEL: @st2_check_store( // BENUMLOADS-NEXT: entry: -// BENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST2:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[C]], align 2 -// BENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], 1 -// BENUMLOADS-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 2 -// BENUMLOADS-NEXT: store i8 [[BF_SET]], ptr [[C]], align 2 +// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[M:%.*]], align 4 +// BENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD]], -65025 +// BENUMLOADS-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], 512 +// BENUMLOADS-NEXT: store i32 [[BF_SET]], ptr [[M]], align 4 // BENUMLOADS-NEXT: ret void // // LEWIDTH-LABEL: @st2_check_store( // LEWIDTH-NEXT: entry: -// LEWIDTH-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST2:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[C]], align 2 -// LEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], -128 -// LEWIDTH-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 1 -// LEWIDTH-NEXT: store i8 [[BF_SET]], ptr [[C]], align 2 +// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[M:%.*]], align 4 +// LEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD]], -8323073 +// LEWIDTH-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], 65536 +// LEWIDTH-NEXT: store i32 [[BF_SET]], ptr [[M]], align 4 // LEWIDTH-NEXT: ret void // // BEWIDTH-LABEL: @st2_check_store( // BEWIDTH-NEXT: entry: -// BEWIDTH-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST2:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[C]], align 2 -// BEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], 1 -// BEWIDTH-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 2 -// BEWIDTH-NEXT: store i8 [[BF_SET]], ptr [[C]], align 2 +// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[M:%.*]], align 4 +// BEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD]], -65025 +// BEWIDTH-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], 512 +// BEWIDTH-NEXT: store i32 [[BF_SET]], ptr [[M]], align 4 // BEWIDTH-NEXT: ret void // // LEWIDTHNUM-LABEL: @st2_check_store( // LEWIDTHNUM-NEXT: entry: -// LEWIDTHNUM-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST2:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[C]], align 2 -// LEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], -128 -// LEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 1 -// LEWIDTHNUM-NEXT: store i8 [[BF_SET]], ptr [[C]], align 2 +// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[M:%.*]], align 4 +// LEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD]], -8323073 +// LEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], 65536 +// LEWIDTHNUM-NEXT: store i32 [[BF_SET]], ptr [[M]], align 4 // LEWIDTHNUM-NEXT: ret void // // BEWIDTHNUM-LABEL: @st2_check_store( // BEWIDTHNUM-NEXT: entry: -// BEWIDTHNUM-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST2:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[C]], align 2 -// BEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], 1 -// BEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 2 -// BEWIDTHNUM-NEXT: store i8 [[BF_SET]], ptr [[C]], align 2 +// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[M:%.*]], align 4 +// BEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD]], -65025 +// BEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], 512 +// BEWIDTHNUM-NEXT: store i32 [[BF_SET]], ptr [[M]], align 4 // BEWIDTHNUM-NEXT: ret void // void st2_check_store(struct st2 *m) { @@ -636,8 +624,8 @@ struct st4 { // // LEWIDTH-LABEL: @st4_check_load( // LEWIDTH-NEXT: entry: -// LEWIDTH-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 1 -// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP1]], align 1 +// LEWIDTH-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 1 +// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP0]], align 1 // LEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i8 [[BF_LOAD]], 2 // LEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_SHL]], 3 // LEWIDTH-NEXT: [[CONV:%.*]] = sext i8 [[BF_ASHR]] to i32 @@ -645,8 +633,8 @@ struct st4 { // // BEWIDTH-LABEL: @st4_check_load( // BEWIDTH-NEXT: entry: -// BEWIDTH-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 1 -// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP1]], align 1 +// BEWIDTH-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 1 +// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP0]], align 1 // BEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i8 [[BF_LOAD]], 1 // BEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_SHL]], 3 // BEWIDTH-NEXT: [[CONV:%.*]] = sext i8 [[BF_ASHR]] to i32 @@ -654,8 +642,8 @@ struct st4 { // // LEWIDTHNUM-LABEL: @st4_check_load( // LEWIDTHNUM-NEXT: entry: -// LEWIDTHNUM-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 1 -// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP1]], align 1 +// LEWIDTHNUM-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 1 +// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP0]], align 1 // LEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i8 [[BF_LOAD]], 2 // LEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_SHL]], 3 // LEWIDTHNUM-NEXT: [[CONV:%.*]] = sext i8 [[BF_ASHR]] to i32 @@ -663,8 +651,8 @@ struct st4 { // // BEWIDTHNUM-LABEL: @st4_check_load( // BEWIDTHNUM-NEXT: entry: -// BEWIDTHNUM-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 1 -// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP1]], align 1 +// BEWIDTHNUM-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 1 +// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP0]], align 1 // BEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i8 [[BF_LOAD]], 1 // BEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_SHL]], 3 // BEWIDTHNUM-NEXT: [[CONV:%.*]] = sext i8 [[BF_ASHR]] to i32 @@ -708,38 +696,38 @@ int st4_check_load(struct st4 *m) { // // LEWIDTH-LABEL: @st4_check_store( // LEWIDTH-NEXT: entry: -// LEWIDTH-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 1 -// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP1]], align 1 +// LEWIDTH-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 1 +// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP0]], align 1 // LEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], -63 // LEWIDTH-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 2 -// LEWIDTH-NEXT: store volatile i8 [[BF_SET]], ptr [[TMP1]], align 1 +// LEWIDTH-NEXT: store volatile i8 [[BF_SET]], ptr [[TMP0]], align 1 // LEWIDTH-NEXT: ret void // // BEWIDTH-LABEL: @st4_check_store( // BEWIDTH-NEXT: entry: -// BEWIDTH-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 1 -// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP1]], align 1 +// BEWIDTH-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 1 +// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP0]], align 1 // BEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], -125 // BEWIDTH-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 4 -// BEWIDTH-NEXT: store volatile i8 [[BF_SET]], ptr [[TMP1]], align 1 +// BEWIDTH-NEXT: store volatile i8 [[BF_SET]], ptr [[TMP0]], align 1 // BEWIDTH-NEXT: ret void // // LEWIDTHNUM-LABEL: @st4_check_store( // LEWIDTHNUM-NEXT: entry: -// LEWIDTHNUM-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 1 -// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP1]], align 1 +// LEWIDTHNUM-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 1 +// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP0]], align 1 // LEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], -63 // LEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 2 -// LEWIDTHNUM-NEXT: store volatile i8 [[BF_SET]], ptr [[TMP1]], align 1 +// LEWIDTHNUM-NEXT: store volatile i8 [[BF_SET]], ptr [[TMP0]], align 1 // LEWIDTHNUM-NEXT: ret void // // BEWIDTHNUM-LABEL: @st4_check_store( // BEWIDTHNUM-NEXT: entry: -// BEWIDTHNUM-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 1 -// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP1]], align 1 +// BEWIDTHNUM-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 1 +// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP0]], align 1 // BEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], -125 // BEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 4 -// BEWIDTHNUM-NEXT: store volatile i8 [[BF_SET]], ptr [[TMP1]], align 1 +// BEWIDTHNUM-NEXT: store volatile i8 [[BF_SET]], ptr [[TMP0]], align 1 // BEWIDTHNUM-NEXT: ret void // void st4_check_store(struct st4 *m) { @@ -821,42 +809,44 @@ struct st5 { // LE-LABEL: @st5_check_load( // LE-NEXT: entry: -// LE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST5:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// LE-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 2 -// LE-NEXT: [[BF_SHL:%.*]] = shl i8 [[BF_LOAD]], 3 -// LE-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_SHL]], 3 -// LE-NEXT: [[CONV:%.*]] = sext i8 [[BF_ASHR]] to i32 +// LE-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[M:%.*]], align 4 +// LE-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_LOAD]], 11 +// LE-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_SHL]], 27 +// LE-NEXT: [[BF_CAST:%.*]] = trunc i32 [[BF_ASHR]] to i8 +// LE-NEXT: [[CONV:%.*]] = sext i8 [[BF_CAST]] to i32 // LE-NEXT: ret i32 [[CONV]] // // BE-LABEL: @st5_check_load( // BE-NEXT: entry: -// BE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST5:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// BE-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 2 -// BE-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_LOAD]], 3 -// BE-NEXT: [[CONV:%.*]] = sext i8 [[BF_ASHR]] to i32 +// BE-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[M:%.*]], align 4 +// BE-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_LOAD]], 16 +// BE-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_SHL]], 27 +// BE-NEXT: [[BF_CAST:%.*]] = trunc i32 [[BF_ASHR]] to i8 +// BE-NEXT: [[CONV:%.*]] = sext i8 [[BF_CAST]] to i32 // BE-NEXT: ret i32 [[CONV]] // // LENUMLOADS-LABEL: @st5_check_load( // LENUMLOADS-NEXT: entry: -// LENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST5:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 2 -// LENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i8 [[BF_LOAD]], 3 -// LENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_SHL]], 3 -// LENUMLOADS-NEXT: [[CONV:%.*]] = sext i8 [[BF_ASHR]] to i32 +// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[M:%.*]], align 4 +// LENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_LOAD]], 11 +// LENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_SHL]], 27 +// LENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i32 [[BF_ASHR]] to i8 +// LENUMLOADS-NEXT: [[CONV:%.*]] = sext i8 [[BF_CAST]] to i32 // LENUMLOADS-NEXT: ret i32 [[CONV]] // // BENUMLOADS-LABEL: @st5_check_load( // BENUMLOADS-NEXT: entry: -// BENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST5:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 2 -// BENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_LOAD]], 3 -// BENUMLOADS-NEXT: [[CONV:%.*]] = sext i8 [[BF_ASHR]] to i32 +// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[M:%.*]], align 4 +// BENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_LOAD]], 16 +// BENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_SHL]], 27 +// BENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i32 [[BF_ASHR]] to i8 +// BENUMLOADS-NEXT: [[CONV:%.*]] = sext i8 [[BF_CAST]] to i32 // BENUMLOADS-NEXT: ret i32 [[CONV]] // // LEWIDTH-LABEL: @st5_check_load( // LEWIDTH-NEXT: entry: -// LEWIDTH-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST5:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 2 +// LEWIDTH-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 2 +// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP0]], align 2 // LEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i8 [[BF_LOAD]], 3 // LEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_SHL]], 3 // LEWIDTH-NEXT: [[CONV:%.*]] = sext i8 [[BF_ASHR]] to i32 @@ -864,16 +854,16 @@ struct st5 { // // BEWIDTH-LABEL: @st5_check_load( // BEWIDTH-NEXT: entry: -// BEWIDTH-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST5:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 2 +// BEWIDTH-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 2 +// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP0]], align 2 // BEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_LOAD]], 3 // BEWIDTH-NEXT: [[CONV:%.*]] = sext i8 [[BF_ASHR]] to i32 // BEWIDTH-NEXT: ret i32 [[CONV]] // // LEWIDTHNUM-LABEL: @st5_check_load( // LEWIDTHNUM-NEXT: entry: -// LEWIDTHNUM-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST5:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 2 +// LEWIDTHNUM-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 2 +// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP0]], align 2 // LEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i8 [[BF_LOAD]], 3 // LEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_SHL]], 3 // LEWIDTHNUM-NEXT: [[CONV:%.*]] = sext i8 [[BF_ASHR]] to i32 @@ -881,8 +871,8 @@ struct st5 { // // BEWIDTHNUM-LABEL: @st5_check_load( // BEWIDTHNUM-NEXT: entry: -// BEWIDTHNUM-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST5:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 2 +// BEWIDTHNUM-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 2 +// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP0]], align 2 // BEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i8 [[BF_LOAD]], 3 // BEWIDTHNUM-NEXT: [[CONV:%.*]] = sext i8 [[BF_ASHR]] to i32 // BEWIDTHNUM-NEXT: ret i32 [[CONV]] @@ -893,74 +883,70 @@ int st5_check_load(struct st5 *m) { // LE-LABEL: @st5_check_store( // LE-NEXT: entry: -// LE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST5:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// LE-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 2 -// LE-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], -32 -// LE-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 1 -// LE-NEXT: store volatile i8 [[BF_SET]], ptr [[C]], align 2 +// LE-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[M:%.*]], align 4 +// LE-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD]], -2031617 +// LE-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], 65536 +// LE-NEXT: store volatile i32 [[BF_SET]], ptr [[M]], align 4 // LE-NEXT: ret void // // BE-LABEL: @st5_check_store( // BE-NEXT: entry: -// BE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST5:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// BE-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 2 -// BE-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], 7 -// BE-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 8 -// BE-NEXT: store volatile i8 [[BF_SET]], ptr [[C]], align 2 +// BE-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[M:%.*]], align 4 +// BE-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD]], -63489 +// BE-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], 2048 +// BE-NEXT: store volatile i32 [[BF_SET]], ptr [[M]], align 4 // BE-NEXT: ret void // // LENUMLOADS-LABEL: @st5_check_store( // LENUMLOADS-NEXT: entry: -// LENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST5:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 2 -// LENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], -32 -// LENUMLOADS-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 1 -// LENUMLOADS-NEXT: store volatile i8 [[BF_SET]], ptr [[C]], align 2 +// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[M:%.*]], align 4 +// LENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD]], -2031617 +// LENUMLOADS-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], 65536 +// LENUMLOADS-NEXT: store volatile i32 [[BF_SET]], ptr [[M]], align 4 // LENUMLOADS-NEXT: ret void // // BENUMLOADS-LABEL: @st5_check_store( // BENUMLOADS-NEXT: entry: -// BENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST5:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 2 -// BENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], 7 -// BENUMLOADS-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 8 -// BENUMLOADS-NEXT: store volatile i8 [[BF_SET]], ptr [[C]], align 2 +// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[M:%.*]], align 4 +// BENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD]], -63489 +// BENUMLOADS-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], 2048 +// BENUMLOADS-NEXT: store volatile i32 [[BF_SET]], ptr [[M]], align 4 // BENUMLOADS-NEXT: ret void // // LEWIDTH-LABEL: @st5_check_store( // LEWIDTH-NEXT: entry: -// LEWIDTH-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST5:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 2 +// LEWIDTH-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 2 +// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP0]], align 2 // LEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], -32 // LEWIDTH-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 1 -// LEWIDTH-NEXT: store volatile i8 [[BF_SET]], ptr [[C]], align 2 +// LEWIDTH-NEXT: store volatile i8 [[BF_SET]], ptr [[TMP0]], align 2 // LEWIDTH-NEXT: ret void // // BEWIDTH-LABEL: @st5_check_store( // BEWIDTH-NEXT: entry: -// BEWIDTH-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST5:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 2 +// BEWIDTH-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 2 +// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP0]], align 2 // BEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], 7 // BEWIDTH-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 8 -// BEWIDTH-NEXT: store volatile i8 [[BF_SET]], ptr [[C]], align 2 +// BEWIDTH-NEXT: store volatile i8 [[BF_SET]], ptr [[TMP0]], align 2 // BEWIDTH-NEXT: ret void // // LEWIDTHNUM-LABEL: @st5_check_store( // LEWIDTHNUM-NEXT: entry: -// LEWIDTHNUM-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST5:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 2 +// LEWIDTHNUM-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 2 +// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP0]], align 2 // LEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], -32 // LEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 1 -// LEWIDTHNUM-NEXT: store volatile i8 [[BF_SET]], ptr [[C]], align 2 +// LEWIDTHNUM-NEXT: store volatile i8 [[BF_SET]], ptr [[TMP0]], align 2 // LEWIDTHNUM-NEXT: ret void // // BEWIDTHNUM-LABEL: @st5_check_store( // BEWIDTHNUM-NEXT: entry: -// BEWIDTHNUM-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST5:%.*]], ptr [[M:%.*]], i32 0, i32 1 -// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 2 +// BEWIDTHNUM-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[M:%.*]], i32 2 +// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP0]], align 2 // BEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i8 [[BF_LOAD]], 7 // BEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i8 [[BF_CLEAR]], 8 -// BEWIDTHNUM-NEXT: store volatile i8 [[BF_SET]], ptr [[C]], align 2 +// BEWIDTHNUM-NEXT: store volatile i8 [[BF_SET]], ptr [[TMP0]], align 2 // BEWIDTHNUM-NEXT: ret void // void st5_check_store(struct st5 *m) { @@ -980,8 +966,8 @@ struct st6 { // LE-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_SHL]], 4 // LE-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_ASHR]] to i32 // LE-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST6:%.*]], ptr [[M]], i32 0, i32 1 -// LE-NEXT: [[TMP1:%.*]] = load volatile i8, ptr [[B]], align 2 -// LE-NEXT: [[CONV:%.*]] = sext i8 [[TMP1]] to i32 +// LE-NEXT: [[TMP0:%.*]] = load volatile i8, ptr [[B]], align 2 +// LE-NEXT: [[CONV:%.*]] = sext i8 [[TMP0]] to i32 // LE-NEXT: [[ADD:%.*]] = add nsw i32 [[BF_CAST]], [[CONV]] // LE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST6]], ptr [[M]], i32 0, i32 2 // LE-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[C]], align 1 @@ -997,8 +983,8 @@ struct st6 { // BE-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_LOAD]], 4 // BE-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_ASHR]] to i32 // BE-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST6:%.*]], ptr [[M]], i32 0, i32 1 -// BE-NEXT: [[TMP1:%.*]] = load volatile i8, ptr [[B]], align 2 -// BE-NEXT: [[CONV:%.*]] = sext i8 [[TMP1]] to i32 +// BE-NEXT: [[TMP0:%.*]] = load volatile i8, ptr [[B]], align 2 +// BE-NEXT: [[CONV:%.*]] = sext i8 [[TMP0]] to i32 // BE-NEXT: [[ADD:%.*]] = add nsw i32 [[BF_CAST]], [[CONV]] // BE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST6]], ptr [[M]], i32 0, i32 2 // BE-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[C]], align 1 @@ -1014,8 +1000,8 @@ struct st6 { // LENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_SHL]], 4 // LENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_ASHR]] to i32 // LENUMLOADS-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST6:%.*]], ptr [[M]], i32 0, i32 1 -// LENUMLOADS-NEXT: [[TMP1:%.*]] = load volatile i8, ptr [[B]], align 2 -// LENUMLOADS-NEXT: [[CONV:%.*]] = sext i8 [[TMP1]] to i32 +// LENUMLOADS-NEXT: [[TMP0:%.*]] = load volatile i8, ptr [[B]], align 2 +// LENUMLOADS-NEXT: [[CONV:%.*]] = sext i8 [[TMP0]] to i32 // LENUMLOADS-NEXT: [[ADD:%.*]] = add nsw i32 [[BF_CAST]], [[CONV]] // LENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST6]], ptr [[M]], i32 0, i32 2 // LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[C]], align 1 @@ -1031,8 +1017,8 @@ struct st6 { // BENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_LOAD]], 4 // BENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_ASHR]] to i32 // BENUMLOADS-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST6:%.*]], ptr [[M]], i32 0, i32 1 -// BENUMLOADS-NEXT: [[TMP1:%.*]] = load volatile i8, ptr [[B]], align 2 -// BENUMLOADS-NEXT: [[CONV:%.*]] = sext i8 [[TMP1]] to i32 +// BENUMLOADS-NEXT: [[TMP0:%.*]] = load volatile i8, ptr [[B]], align 2 +// BENUMLOADS-NEXT: [[CONV:%.*]] = sext i8 [[TMP0]] to i32 // BENUMLOADS-NEXT: [[ADD:%.*]] = add nsw i32 [[BF_CAST]], [[CONV]] // BENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST6]], ptr [[M]], i32 0, i32 2 // BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[C]], align 1 @@ -1048,8 +1034,8 @@ struct st6 { // LEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_SHL]], 4 // LEWIDTH-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_ASHR]] to i32 // LEWIDTH-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST6:%.*]], ptr [[M]], i32 0, i32 1 -// LEWIDTH-NEXT: [[TMP1:%.*]] = load volatile i8, ptr [[B]], align 2 -// LEWIDTH-NEXT: [[CONV:%.*]] = sext i8 [[TMP1]] to i32 +// LEWIDTH-NEXT: [[TMP0:%.*]] = load volatile i8, ptr [[B]], align 2 +// LEWIDTH-NEXT: [[CONV:%.*]] = sext i8 [[TMP0]] to i32 // LEWIDTH-NEXT: [[ADD:%.*]] = add nsw i32 [[BF_CAST]], [[CONV]] // LEWIDTH-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST6]], ptr [[M]], i32 0, i32 2 // LEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[C]], align 1 @@ -1065,8 +1051,8 @@ struct st6 { // BEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_LOAD]], 4 // BEWIDTH-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_ASHR]] to i32 // BEWIDTH-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST6:%.*]], ptr [[M]], i32 0, i32 1 -// BEWIDTH-NEXT: [[TMP1:%.*]] = load volatile i8, ptr [[B]], align 2 -// BEWIDTH-NEXT: [[CONV:%.*]] = sext i8 [[TMP1]] to i32 +// BEWIDTH-NEXT: [[TMP0:%.*]] = load volatile i8, ptr [[B]], align 2 +// BEWIDTH-NEXT: [[CONV:%.*]] = sext i8 [[TMP0]] to i32 // BEWIDTH-NEXT: [[ADD:%.*]] = add nsw i32 [[BF_CAST]], [[CONV]] // BEWIDTH-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST6]], ptr [[M]], i32 0, i32 2 // BEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[C]], align 1 @@ -1082,8 +1068,8 @@ struct st6 { // LEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_SHL]], 4 // LEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_ASHR]] to i32 // LEWIDTHNUM-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST6:%.*]], ptr [[M]], i32 0, i32 1 -// LEWIDTHNUM-NEXT: [[TMP1:%.*]] = load volatile i8, ptr [[B]], align 2 -// LEWIDTHNUM-NEXT: [[CONV:%.*]] = sext i8 [[TMP1]] to i32 +// LEWIDTHNUM-NEXT: [[TMP0:%.*]] = load volatile i8, ptr [[B]], align 2 +// LEWIDTHNUM-NEXT: [[CONV:%.*]] = sext i8 [[TMP0]] to i32 // LEWIDTHNUM-NEXT: [[ADD:%.*]] = add nsw i32 [[BF_CAST]], [[CONV]] // LEWIDTHNUM-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST6]], ptr [[M]], i32 0, i32 2 // LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[C]], align 1 @@ -1099,8 +1085,8 @@ struct st6 { // BEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_LOAD]], 4 // BEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_ASHR]] to i32 // BEWIDTHNUM-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST6:%.*]], ptr [[M]], i32 0, i32 1 -// BEWIDTHNUM-NEXT: [[TMP1:%.*]] = load volatile i8, ptr [[B]], align 2 -// BEWIDTHNUM-NEXT: [[CONV:%.*]] = sext i8 [[TMP1]] to i32 +// BEWIDTHNUM-NEXT: [[TMP0:%.*]] = load volatile i8, ptr [[B]], align 2 +// BEWIDTHNUM-NEXT: [[CONV:%.*]] = sext i8 [[TMP0]] to i32 // BEWIDTHNUM-NEXT: [[ADD:%.*]] = add nsw i32 [[BF_CAST]], [[CONV]] // BEWIDTHNUM-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST6]], ptr [[M]], i32 0, i32 2 // BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[C]], align 1 @@ -1704,9 +1690,9 @@ void store_st9(volatile struct st9 *m) { // LE-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[M:%.*]], align 4 // LE-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i32 // LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LE-NEXT: [[TMP1:%.*]] = trunc i32 [[INC]] to i8 -// LE-NEXT: store volatile i8 [[TMP1]], ptr [[M]], align 4 -// LE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i32 +// LE-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i8 +// LE-NEXT: store volatile i8 [[TMP0]], ptr [[M]], align 4 +// LE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i32 // LE-NEXT: ret void // // BE-LABEL: @increment_st9( @@ -1714,9 +1700,9 @@ void store_st9(volatile struct st9 *m) { // BE-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[M:%.*]], align 4 // BE-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i32 // BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BE-NEXT: [[TMP1:%.*]] = trunc i32 [[INC]] to i8 -// BE-NEXT: store volatile i8 [[TMP1]], ptr [[M]], align 4 -// BE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i32 +// BE-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i8 +// BE-NEXT: store volatile i8 [[TMP0]], ptr [[M]], align 4 +// BE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i32 // BE-NEXT: ret void // // LENUMLOADS-LABEL: @increment_st9( @@ -1724,10 +1710,10 @@ void store_st9(volatile struct st9 *m) { // LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[M:%.*]], align 4 // LENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i32 // LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LENUMLOADS-NEXT: [[TMP1:%.*]] = trunc i32 [[INC]] to i8 +// LENUMLOADS-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i8 // LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[M]], align 4 -// LENUMLOADS-NEXT: store volatile i8 [[TMP1]], ptr [[M]], align 4 -// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i32 +// LENUMLOADS-NEXT: store volatile i8 [[TMP0]], ptr [[M]], align 4 +// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i32 // LENUMLOADS-NEXT: ret void // // BENUMLOADS-LABEL: @increment_st9( @@ -1735,10 +1721,10 @@ void store_st9(volatile struct st9 *m) { // BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[M:%.*]], align 4 // BENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i32 // BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BENUMLOADS-NEXT: [[TMP1:%.*]] = trunc i32 [[INC]] to i8 +// BENUMLOADS-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i8 // BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[M]], align 4 -// BENUMLOADS-NEXT: store volatile i8 [[TMP1]], ptr [[M]], align 4 -// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i32 +// BENUMLOADS-NEXT: store volatile i8 [[TMP0]], ptr [[M]], align 4 +// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i32 // BENUMLOADS-NEXT: ret void // // LEWIDTH-LABEL: @increment_st9( @@ -1949,9 +1935,9 @@ void store_st10(volatile struct st10 *m) { // LE-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_SHL]], 8 // LE-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_ASHR]] to i32 // LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LE-NEXT: [[TMP1:%.*]] = trunc i32 [[INC]] to i16 +// LE-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 // LE-NEXT: [[BF_LOAD1:%.*]] = load volatile i16, ptr [[M]], align 4 -// LE-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP1]], 255 +// LE-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP0]], 255 // LE-NEXT: [[BF_SHL2:%.*]] = shl i16 [[BF_VALUE]], 1 // LE-NEXT: [[BF_CLEAR:%.*]] = and i16 [[BF_LOAD1]], -511 // LE-NEXT: [[BF_SET:%.*]] = or i16 [[BF_CLEAR]], [[BF_SHL2]] @@ -1968,9 +1954,9 @@ void store_st10(volatile struct st10 *m) { // BE-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_SHL]], 8 // BE-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_ASHR]] to i32 // BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BE-NEXT: [[TMP1:%.*]] = trunc i32 [[INC]] to i16 +// BE-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 // BE-NEXT: [[BF_LOAD1:%.*]] = load volatile i16, ptr [[M]], align 4 -// BE-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP1]], 255 +// BE-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP0]], 255 // BE-NEXT: [[BF_SHL2:%.*]] = shl i16 [[BF_VALUE]], 7 // BE-NEXT: [[BF_CLEAR:%.*]] = and i16 [[BF_LOAD1]], -32641 // BE-NEXT: [[BF_SET:%.*]] = or i16 [[BF_CLEAR]], [[BF_SHL2]] @@ -1987,9 +1973,9 @@ void store_st10(volatile struct st10 *m) { // LENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_SHL]], 8 // LENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_ASHR]] to i32 // LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LENUMLOADS-NEXT: [[TMP1:%.*]] = trunc i32 [[INC]] to i16 +// LENUMLOADS-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 // LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i16, ptr [[M]], align 4 -// LENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP1]], 255 +// LENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP0]], 255 // LENUMLOADS-NEXT: [[BF_SHL2:%.*]] = shl i16 [[BF_VALUE]], 1 // LENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i16 [[BF_LOAD1]], -511 // LENUMLOADS-NEXT: [[BF_SET:%.*]] = or i16 [[BF_CLEAR]], [[BF_SHL2]] @@ -2006,9 +1992,9 @@ void store_st10(volatile struct st10 *m) { // BENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_SHL]], 8 // BENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_ASHR]] to i32 // BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BENUMLOADS-NEXT: [[TMP1:%.*]] = trunc i32 [[INC]] to i16 +// BENUMLOADS-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 // BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i16, ptr [[M]], align 4 -// BENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP1]], 255 +// BENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP0]], 255 // BENUMLOADS-NEXT: [[BF_SHL2:%.*]] = shl i16 [[BF_VALUE]], 7 // BENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i16 [[BF_LOAD1]], -32641 // BENUMLOADS-NEXT: [[BF_SET:%.*]] = or i16 [[BF_CLEAR]], [[BF_SHL2]] @@ -2767,146 +2753,70 @@ struct st13 { // LE-LABEL: @increment_b_st13( // LE-NEXT: entry: -// LE-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// LE-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_LOAD]], 8 -// LE-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i32 -// LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i40 -// LE-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// LE-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 4294967295 -// LE-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// LE-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], 255 -// LE-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_SHL]] -// LE-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// LE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// LE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 8 -// LE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i32 +// LE-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST13:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// LE-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[B]], align 1 +// LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LE-NEXT: store volatile i32 [[INC]], ptr [[B]], align 1 // LE-NEXT: ret void // // BE-LABEL: @increment_b_st13( // BE-NEXT: entry: -// BE-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// BE-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_LOAD]], 8 -// BE-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_SHL]], 8 -// BE-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i32 -// BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i40 -// BE-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// BE-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 4294967295 -// BE-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], -4294967296 -// BE-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_VALUE]] -// BE-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// BE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// BE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 8 -// BE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i32 +// BE-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST13:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// BE-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[B]], align 1 +// BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BE-NEXT: store volatile i32 [[INC]], ptr [[B]], align 1 // BE-NEXT: ret void // // LENUMLOADS-LABEL: @increment_b_st13( // LENUMLOADS-NEXT: entry: -// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// LENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_LOAD]], 8 -// LENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i32 -// LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i40 -// LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// LENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 4294967295 -// LENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// LENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], 255 -// LENUMLOADS-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_SHL]] -// LENUMLOADS-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// LENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// LENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 8 -// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i32 +// LENUMLOADS-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST13:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[B]], align 1 +// LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[B]], align 1 +// LENUMLOADS-NEXT: store volatile i32 [[INC]], ptr [[B]], align 1 // LENUMLOADS-NEXT: ret void // // BENUMLOADS-LABEL: @increment_b_st13( // BENUMLOADS-NEXT: entry: -// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// BENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_LOAD]], 8 -// BENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_SHL]], 8 -// BENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i32 -// BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i40 -// BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// BENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 4294967295 -// BENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], -4294967296 -// BENUMLOADS-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_VALUE]] -// BENUMLOADS-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// BENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// BENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 8 -// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i32 +// BENUMLOADS-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST13:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[B]], align 1 +// BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[B]], align 1 +// BENUMLOADS-NEXT: store volatile i32 [[INC]], ptr [[B]], align 1 // BENUMLOADS-NEXT: ret void // // LEWIDTH-LABEL: @increment_b_st13( // LEWIDTH-NEXT: entry: -// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// LEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_LOAD]], 8 -// LEWIDTH-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i32 -// LEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LEWIDTH-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i40 -// LEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// LEWIDTH-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 4294967295 -// LEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// LEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], 255 -// LEWIDTH-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_SHL]] -// LEWIDTH-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// LEWIDTH-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// LEWIDTH-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 8 -// LEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i32 +// LEWIDTH-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST13:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[B]], align 1 +// LEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LEWIDTH-NEXT: store volatile i32 [[INC]], ptr [[B]], align 1 // LEWIDTH-NEXT: ret void // // BEWIDTH-LABEL: @increment_b_st13( // BEWIDTH-NEXT: entry: -// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// BEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_LOAD]], 8 -// BEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_SHL]], 8 -// BEWIDTH-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i32 -// BEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BEWIDTH-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i40 -// BEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// BEWIDTH-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 4294967295 -// BEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], -4294967296 -// BEWIDTH-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_VALUE]] -// BEWIDTH-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// BEWIDTH-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// BEWIDTH-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 8 -// BEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i32 +// BEWIDTH-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST13:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[B]], align 1 +// BEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BEWIDTH-NEXT: store volatile i32 [[INC]], ptr [[B]], align 1 // BEWIDTH-NEXT: ret void // // LEWIDTHNUM-LABEL: @increment_b_st13( // LEWIDTHNUM-NEXT: entry: -// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// LEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_LOAD]], 8 -// LEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i32 -// LEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LEWIDTHNUM-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i40 -// LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// LEWIDTHNUM-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 4294967295 -// LEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// LEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], 255 -// LEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_SHL]] -// LEWIDTHNUM-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// LEWIDTHNUM-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// LEWIDTHNUM-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 8 -// LEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i32 +// LEWIDTHNUM-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST13:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[B]], align 1 +// LEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[B]], align 1 +// LEWIDTHNUM-NEXT: store volatile i32 [[INC]], ptr [[B]], align 1 // LEWIDTHNUM-NEXT: ret void // // BEWIDTHNUM-LABEL: @increment_b_st13( // BEWIDTHNUM-NEXT: entry: -// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// BEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_LOAD]], 8 -// BEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_SHL]], 8 -// BEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i32 -// BEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BEWIDTHNUM-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i40 -// BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// BEWIDTHNUM-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 4294967295 -// BEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], -4294967296 -// BEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_VALUE]] -// BEWIDTHNUM-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// BEWIDTHNUM-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// BEWIDTHNUM-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 8 -// BEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i32 +// BEWIDTHNUM-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST13:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[B]], align 1 +// BEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[B]], align 1 +// BEWIDTHNUM-NEXT: store volatile i32 [[INC]], ptr [[B]], align 1 // BEWIDTHNUM-NEXT: ret void // void increment_b_st13(volatile struct st13 *s) { @@ -2990,9 +2900,9 @@ struct st15 { // LE-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[S:%.*]], align 1 // LE-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i16 // LE-NEXT: [[INC:%.*]] = add i16 [[BF_CAST]], 1 -// LE-NEXT: [[TMP1:%.*]] = trunc i16 [[INC]] to i8 -// LE-NEXT: store volatile i8 [[TMP1]], ptr [[S]], align 1 -// LE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i16 +// LE-NEXT: [[TMP0:%.*]] = trunc i16 [[INC]] to i8 +// LE-NEXT: store volatile i8 [[TMP0]], ptr [[S]], align 1 +// LE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i16 // LE-NEXT: ret void // // BE-LABEL: @increment_a_st15( @@ -3000,9 +2910,9 @@ struct st15 { // BE-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[S:%.*]], align 1 // BE-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i16 // BE-NEXT: [[INC:%.*]] = add i16 [[BF_CAST]], 1 -// BE-NEXT: [[TMP1:%.*]] = trunc i16 [[INC]] to i8 -// BE-NEXT: store volatile i8 [[TMP1]], ptr [[S]], align 1 -// BE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i16 +// BE-NEXT: [[TMP0:%.*]] = trunc i16 [[INC]] to i8 +// BE-NEXT: store volatile i8 [[TMP0]], ptr [[S]], align 1 +// BE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i16 // BE-NEXT: ret void // // LENUMLOADS-LABEL: @increment_a_st15( @@ -3010,10 +2920,10 @@ struct st15 { // LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[S:%.*]], align 1 // LENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i16 // LENUMLOADS-NEXT: [[INC:%.*]] = add i16 [[BF_CAST]], 1 -// LENUMLOADS-NEXT: [[TMP1:%.*]] = trunc i16 [[INC]] to i8 +// LENUMLOADS-NEXT: [[TMP0:%.*]] = trunc i16 [[INC]] to i8 // LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[S]], align 1 -// LENUMLOADS-NEXT: store volatile i8 [[TMP1]], ptr [[S]], align 1 -// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i16 +// LENUMLOADS-NEXT: store volatile i8 [[TMP0]], ptr [[S]], align 1 +// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i16 // LENUMLOADS-NEXT: ret void // // BENUMLOADS-LABEL: @increment_a_st15( @@ -3021,10 +2931,10 @@ struct st15 { // BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[S:%.*]], align 1 // BENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i16 // BENUMLOADS-NEXT: [[INC:%.*]] = add i16 [[BF_CAST]], 1 -// BENUMLOADS-NEXT: [[TMP1:%.*]] = trunc i16 [[INC]] to i8 +// BENUMLOADS-NEXT: [[TMP0:%.*]] = trunc i16 [[INC]] to i8 // BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[S]], align 1 -// BENUMLOADS-NEXT: store volatile i8 [[TMP1]], ptr [[S]], align 1 -// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i16 +// BENUMLOADS-NEXT: store volatile i8 [[TMP0]], ptr [[S]], align 1 +// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i16 // BENUMLOADS-NEXT: ret void // // LEWIDTH-LABEL: @increment_a_st15( @@ -3032,9 +2942,9 @@ struct st15 { // LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[S:%.*]], align 1 // LEWIDTH-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i16 // LEWIDTH-NEXT: [[INC:%.*]] = add i16 [[BF_CAST]], 1 -// LEWIDTH-NEXT: [[TMP1:%.*]] = trunc i16 [[INC]] to i8 -// LEWIDTH-NEXT: store volatile i8 [[TMP1]], ptr [[S]], align 1 -// LEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i16 +// LEWIDTH-NEXT: [[TMP0:%.*]] = trunc i16 [[INC]] to i8 +// LEWIDTH-NEXT: store volatile i8 [[TMP0]], ptr [[S]], align 1 +// LEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i16 // LEWIDTH-NEXT: ret void // // BEWIDTH-LABEL: @increment_a_st15( @@ -3042,9 +2952,9 @@ struct st15 { // BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[S:%.*]], align 1 // BEWIDTH-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i16 // BEWIDTH-NEXT: [[INC:%.*]] = add i16 [[BF_CAST]], 1 -// BEWIDTH-NEXT: [[TMP1:%.*]] = trunc i16 [[INC]] to i8 -// BEWIDTH-NEXT: store volatile i8 [[TMP1]], ptr [[S]], align 1 -// BEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i16 +// BEWIDTH-NEXT: [[TMP0:%.*]] = trunc i16 [[INC]] to i8 +// BEWIDTH-NEXT: store volatile i8 [[TMP0]], ptr [[S]], align 1 +// BEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i16 // BEWIDTH-NEXT: ret void // // LEWIDTHNUM-LABEL: @increment_a_st15( @@ -3052,10 +2962,10 @@ struct st15 { // LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[S:%.*]], align 1 // LEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i16 // LEWIDTHNUM-NEXT: [[INC:%.*]] = add i16 [[BF_CAST]], 1 -// LEWIDTHNUM-NEXT: [[TMP1:%.*]] = trunc i16 [[INC]] to i8 +// LEWIDTHNUM-NEXT: [[TMP0:%.*]] = trunc i16 [[INC]] to i8 // LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[S]], align 1 -// LEWIDTHNUM-NEXT: store volatile i8 [[TMP1]], ptr [[S]], align 1 -// LEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i16 +// LEWIDTHNUM-NEXT: store volatile i8 [[TMP0]], ptr [[S]], align 1 +// LEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i16 // LEWIDTHNUM-NEXT: ret void // // BEWIDTHNUM-LABEL: @increment_a_st15( @@ -3063,10 +2973,10 @@ struct st15 { // BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[S:%.*]], align 1 // BEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i16 // BEWIDTHNUM-NEXT: [[INC:%.*]] = add i16 [[BF_CAST]], 1 -// BEWIDTHNUM-NEXT: [[TMP1:%.*]] = trunc i16 [[INC]] to i8 +// BEWIDTHNUM-NEXT: [[TMP0:%.*]] = trunc i16 [[INC]] to i8 // BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[S]], align 1 -// BEWIDTHNUM-NEXT: store volatile i8 [[TMP1]], ptr [[S]], align 1 -// BEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i16 +// BEWIDTHNUM-NEXT: store volatile i8 [[TMP0]], ptr [[S]], align 1 +// BEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i16 // BEWIDTHNUM-NEXT: ret void // void increment_a_st15(volatile struct st15 *s) { @@ -3082,146 +2992,58 @@ struct st16 { // LE-LABEL: @increment_a_st16( // LE-NEXT: entry: -// LE-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[S:%.*]], align 4 -// LE-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// LE-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 32 -// LE-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LE-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[S]], align 4 -// LE-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// LE-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294967296 -// LE-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_VALUE]] -// LE-NEXT: store i64 [[BF_SET]], ptr [[S]], align 4 -// LE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// LE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// LE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LE-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[S:%.*]], align 4 +// LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LE-NEXT: store i32 [[INC]], ptr [[S]], align 4 // LE-NEXT: ret void // // BE-LABEL: @increment_a_st16( // BE-NEXT: entry: -// BE-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[S:%.*]], align 4 -// BE-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_LOAD]], 32 -// BE-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BE-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[S]], align 4 -// BE-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// BE-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BE-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], 4294967295 -// BE-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL]] -// BE-NEXT: store i64 [[BF_SET]], ptr [[S]], align 4 -// BE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// BE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BE-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[S:%.*]], align 4 +// BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BE-NEXT: store i32 [[INC]], ptr [[S]], align 4 // BE-NEXT: ret void // // LENUMLOADS-LABEL: @increment_a_st16( // LENUMLOADS-NEXT: entry: -// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[S:%.*]], align 4 -// LENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// LENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 32 -// LENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[S]], align 4 -// LENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// LENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294967296 -// LENUMLOADS-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_VALUE]] -// LENUMLOADS-NEXT: store i64 [[BF_SET]], ptr [[S]], align 4 -// LENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// LENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[S:%.*]], align 4 +// LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LENUMLOADS-NEXT: store i32 [[INC]], ptr [[S]], align 4 // LENUMLOADS-NEXT: ret void // // BENUMLOADS-LABEL: @increment_a_st16( // BENUMLOADS-NEXT: entry: -// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[S:%.*]], align 4 -// BENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_LOAD]], 32 -// BENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[S]], align 4 -// BENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// BENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], 4294967295 -// BENUMLOADS-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL]] -// BENUMLOADS-NEXT: store i64 [[BF_SET]], ptr [[S]], align 4 -// BENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[S:%.*]], align 4 +// BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BENUMLOADS-NEXT: store i32 [[INC]], ptr [[S]], align 4 // BENUMLOADS-NEXT: ret void // // LEWIDTH-LABEL: @increment_a_st16( // LEWIDTH-NEXT: entry: -// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[S:%.*]], align 4 -// LEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// LEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 32 -// LEWIDTH-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// LEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LEWIDTH-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[S]], align 4 -// LEWIDTH-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// LEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294967296 -// LEWIDTH-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_VALUE]] -// LEWIDTH-NEXT: store i64 [[BF_SET]], ptr [[S]], align 4 -// LEWIDTH-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// LEWIDTH-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// LEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[S:%.*]], align 4 +// LEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LEWIDTH-NEXT: store i32 [[INC]], ptr [[S]], align 4 // LEWIDTH-NEXT: ret void // // BEWIDTH-LABEL: @increment_a_st16( // BEWIDTH-NEXT: entry: -// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[S:%.*]], align 4 -// BEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_LOAD]], 32 -// BEWIDTH-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// BEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BEWIDTH-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[S]], align 4 -// BEWIDTH-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// BEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], 4294967295 -// BEWIDTH-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL]] -// BEWIDTH-NEXT: store i64 [[BF_SET]], ptr [[S]], align 4 -// BEWIDTH-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BEWIDTH-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// BEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[S:%.*]], align 4 +// BEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BEWIDTH-NEXT: store i32 [[INC]], ptr [[S]], align 4 // BEWIDTH-NEXT: ret void // // LEWIDTHNUM-LABEL: @increment_a_st16( // LEWIDTHNUM-NEXT: entry: -// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[S:%.*]], align 4 -// LEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// LEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 32 -// LEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// LEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LEWIDTHNUM-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[S]], align 4 -// LEWIDTHNUM-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// LEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294967296 -// LEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_VALUE]] -// LEWIDTHNUM-NEXT: store i64 [[BF_SET]], ptr [[S]], align 4 -// LEWIDTHNUM-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// LEWIDTHNUM-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// LEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[S:%.*]], align 4 +// LEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LEWIDTHNUM-NEXT: store i32 [[INC]], ptr [[S]], align 4 // LEWIDTHNUM-NEXT: ret void // // BEWIDTHNUM-LABEL: @increment_a_st16( // BEWIDTHNUM-NEXT: entry: -// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[S:%.*]], align 4 -// BEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_LOAD]], 32 -// BEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// BEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BEWIDTHNUM-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[S]], align 4 -// BEWIDTHNUM-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// BEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], 4294967295 -// BEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL]] -// BEWIDTHNUM-NEXT: store i64 [[BF_SET]], ptr [[S]], align 4 -// BEWIDTHNUM-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BEWIDTHNUM-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// BEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[S:%.*]], align 4 +// BEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BEWIDTHNUM-NEXT: store i32 [[INC]], ptr [[S]], align 4 // BEWIDTHNUM-NEXT: ret void // void increment_a_st16(struct st16 *s) { @@ -3230,154 +3052,90 @@ void increment_a_st16(struct st16 *s) { // LE-LABEL: @increment_b_st16( // LE-NEXT: entry: -// LE-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[S:%.*]], align 4 -// LE-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 16 -// LE-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// LE-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// LE-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// LE-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[B]], align 4 +// LE-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LE-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[S]], align 4 -// LE-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// LE-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 32 -// LE-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -281470681743361 -// LE-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// LE-NEXT: store i64 [[BF_SET]], ptr [[S]], align 4 -// LE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// LE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// LE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LE-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// LE-NEXT: store i16 [[TMP0]], ptr [[B]], align 4 +// LE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // LE-NEXT: ret void // // BE-LABEL: @increment_b_st16( // BE-NEXT: entry: -// BE-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[S:%.*]], align 4 -// BE-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// BE-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// BE-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// BE-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// BE-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[B]], align 4 +// BE-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BE-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[S]], align 4 -// BE-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// BE-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 16 -// BE-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294901761 -// BE-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// BE-NEXT: store i64 [[BF_SET]], ptr [[S]], align 4 -// BE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// BE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// BE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BE-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// BE-NEXT: store i16 [[TMP0]], ptr [[B]], align 4 +// BE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // BE-NEXT: ret void // // LENUMLOADS-LABEL: @increment_b_st16( // LENUMLOADS-NEXT: entry: -// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[S:%.*]], align 4 -// LENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 16 -// LENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// LENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// LENUMLOADS-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[B]], align 4 +// LENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[S]], align 4 -// LENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// LENUMLOADS-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 32 -// LENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -281470681743361 -// LENUMLOADS-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// LENUMLOADS-NEXT: store i64 [[BF_SET]], ptr [[S]], align 4 -// LENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// LENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LENUMLOADS-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// LENUMLOADS-NEXT: store i16 [[TMP0]], ptr [[B]], align 4 +// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // LENUMLOADS-NEXT: ret void // // BENUMLOADS-LABEL: @increment_b_st16( // BENUMLOADS-NEXT: entry: -// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[S:%.*]], align 4 -// BENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// BENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// BENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// BENUMLOADS-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[B]], align 4 +// BENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[S]], align 4 -// BENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// BENUMLOADS-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 16 -// BENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294901761 -// BENUMLOADS-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// BENUMLOADS-NEXT: store i64 [[BF_SET]], ptr [[S]], align 4 -// BENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// BENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BENUMLOADS-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// BENUMLOADS-NEXT: store i16 [[TMP0]], ptr [[B]], align 4 +// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // BENUMLOADS-NEXT: ret void // // LEWIDTH-LABEL: @increment_b_st16( // LEWIDTH-NEXT: entry: -// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[S:%.*]], align 4 -// LEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 16 -// LEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// LEWIDTH-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// LEWIDTH-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[B]], align 4 +// LEWIDTH-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // LEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LEWIDTH-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[S]], align 4 -// LEWIDTH-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// LEWIDTH-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 32 -// LEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -281470681743361 -// LEWIDTH-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// LEWIDTH-NEXT: store i64 [[BF_SET]], ptr [[S]], align 4 -// LEWIDTH-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// LEWIDTH-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// LEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LEWIDTH-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// LEWIDTH-NEXT: store i16 [[TMP0]], ptr [[B]], align 4 +// LEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // LEWIDTH-NEXT: ret void // // BEWIDTH-LABEL: @increment_b_st16( // BEWIDTH-NEXT: entry: -// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[S:%.*]], align 4 -// BEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// BEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// BEWIDTH-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// BEWIDTH-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[B]], align 4 +// BEWIDTH-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // BEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BEWIDTH-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[S]], align 4 -// BEWIDTH-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// BEWIDTH-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 16 -// BEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294901761 -// BEWIDTH-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// BEWIDTH-NEXT: store i64 [[BF_SET]], ptr [[S]], align 4 -// BEWIDTH-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// BEWIDTH-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// BEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BEWIDTH-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// BEWIDTH-NEXT: store i16 [[TMP0]], ptr [[B]], align 4 +// BEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // BEWIDTH-NEXT: ret void // // LEWIDTHNUM-LABEL: @increment_b_st16( // LEWIDTHNUM-NEXT: entry: -// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[S:%.*]], align 4 -// LEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 16 -// LEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// LEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// LEWIDTHNUM-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[B]], align 4 +// LEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // LEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LEWIDTHNUM-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[S]], align 4 -// LEWIDTHNUM-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// LEWIDTHNUM-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 32 -// LEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -281470681743361 -// LEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// LEWIDTHNUM-NEXT: store i64 [[BF_SET]], ptr [[S]], align 4 -// LEWIDTHNUM-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// LEWIDTHNUM-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// LEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LEWIDTHNUM-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// LEWIDTHNUM-NEXT: store i16 [[TMP0]], ptr [[B]], align 4 +// LEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // LEWIDTHNUM-NEXT: ret void // // BEWIDTHNUM-LABEL: @increment_b_st16( // BEWIDTHNUM-NEXT: entry: -// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[S:%.*]], align 4 -// BEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// BEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// BEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// BEWIDTHNUM-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[B]], align 4 +// BEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // BEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BEWIDTHNUM-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[S]], align 4 -// BEWIDTHNUM-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// BEWIDTHNUM-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 16 -// BEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294901761 -// BEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// BEWIDTHNUM-NEXT: store i64 [[BF_SET]], ptr [[S]], align 4 -// BEWIDTHNUM-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// BEWIDTHNUM-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// BEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BEWIDTHNUM-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// BEWIDTHNUM-NEXT: store i16 [[TMP0]], ptr [[B]], align 4 +// BEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // BEWIDTHNUM-NEXT: ret void // void increment_b_st16(struct st16 *s) { @@ -3386,154 +3144,66 @@ void increment_b_st16(struct st16 *s) { // LE-LABEL: @increment_c_st16( // LE-NEXT: entry: -// LE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// LE-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[C]], align 4 -// LE-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// LE-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 32 -// LE-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LE-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[C]], align 4 -// LE-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// LE-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294967296 -// LE-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_VALUE]] -// LE-NEXT: store i64 [[BF_SET]], ptr [[C]], align 4 -// LE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// LE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// LE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 2 +// LE-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[C]], align 4 +// LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LE-NEXT: store i32 [[INC]], ptr [[C]], align 4 // LE-NEXT: ret void // // BE-LABEL: @increment_c_st16( // BE-NEXT: entry: -// BE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// BE-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[C]], align 4 -// BE-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_LOAD]], 32 -// BE-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BE-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[C]], align 4 -// BE-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// BE-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BE-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], 4294967295 -// BE-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL]] -// BE-NEXT: store i64 [[BF_SET]], ptr [[C]], align 4 -// BE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// BE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 2 +// BE-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[C]], align 4 +// BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BE-NEXT: store i32 [[INC]], ptr [[C]], align 4 // BE-NEXT: ret void // // LENUMLOADS-LABEL: @increment_c_st16( // LENUMLOADS-NEXT: entry: -// LENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[C]], align 4 -// LENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// LENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 32 -// LENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[C]], align 4 -// LENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// LENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294967296 -// LENUMLOADS-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_VALUE]] -// LENUMLOADS-NEXT: store i64 [[BF_SET]], ptr [[C]], align 4 -// LENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// LENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 2 +// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[C]], align 4 +// LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LENUMLOADS-NEXT: store i32 [[INC]], ptr [[C]], align 4 // LENUMLOADS-NEXT: ret void // // BENUMLOADS-LABEL: @increment_c_st16( // BENUMLOADS-NEXT: entry: -// BENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[C]], align 4 -// BENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_LOAD]], 32 -// BENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[C]], align 4 -// BENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// BENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], 4294967295 -// BENUMLOADS-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL]] -// BENUMLOADS-NEXT: store i64 [[BF_SET]], ptr [[C]], align 4 -// BENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 2 +// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[C]], align 4 +// BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BENUMLOADS-NEXT: store i32 [[INC]], ptr [[C]], align 4 // BENUMLOADS-NEXT: ret void // // LEWIDTH-LABEL: @increment_c_st16( // LEWIDTH-NEXT: entry: -// LEWIDTH-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[C]], align 4 -// LEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// LEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 32 -// LEWIDTH-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// LEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LEWIDTH-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[C]], align 4 -// LEWIDTH-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// LEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294967296 -// LEWIDTH-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_VALUE]] -// LEWIDTH-NEXT: store i64 [[BF_SET]], ptr [[C]], align 4 -// LEWIDTH-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// LEWIDTH-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// LEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LEWIDTH-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 2 +// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[C]], align 4 +// LEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LEWIDTH-NEXT: store i32 [[INC]], ptr [[C]], align 4 // LEWIDTH-NEXT: ret void // // BEWIDTH-LABEL: @increment_c_st16( // BEWIDTH-NEXT: entry: -// BEWIDTH-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[C]], align 4 -// BEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_LOAD]], 32 -// BEWIDTH-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// BEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BEWIDTH-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[C]], align 4 -// BEWIDTH-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// BEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], 4294967295 -// BEWIDTH-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL]] -// BEWIDTH-NEXT: store i64 [[BF_SET]], ptr [[C]], align 4 -// BEWIDTH-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BEWIDTH-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// BEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BEWIDTH-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 2 +// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[C]], align 4 +// BEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BEWIDTH-NEXT: store i32 [[INC]], ptr [[C]], align 4 // BEWIDTH-NEXT: ret void // // LEWIDTHNUM-LABEL: @increment_c_st16( // LEWIDTHNUM-NEXT: entry: -// LEWIDTHNUM-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[C]], align 4 -// LEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// LEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 32 -// LEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// LEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LEWIDTHNUM-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[C]], align 4 -// LEWIDTHNUM-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// LEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294967296 -// LEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_VALUE]] -// LEWIDTHNUM-NEXT: store i64 [[BF_SET]], ptr [[C]], align 4 -// LEWIDTHNUM-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// LEWIDTHNUM-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// LEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LEWIDTHNUM-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 2 +// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[C]], align 4 +// LEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LEWIDTHNUM-NEXT: store i32 [[INC]], ptr [[C]], align 4 // LEWIDTHNUM-NEXT: ret void // // BEWIDTHNUM-LABEL: @increment_c_st16( // BEWIDTHNUM-NEXT: entry: -// BEWIDTHNUM-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[C]], align 4 -// BEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_LOAD]], 32 -// BEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// BEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BEWIDTHNUM-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[C]], align 4 -// BEWIDTHNUM-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// BEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], 4294967295 -// BEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL]] -// BEWIDTHNUM-NEXT: store i64 [[BF_SET]], ptr [[C]], align 4 -// BEWIDTHNUM-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BEWIDTHNUM-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// BEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BEWIDTHNUM-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 2 +// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[C]], align 4 +// BEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BEWIDTHNUM-NEXT: store i32 [[INC]], ptr [[C]], align 4 // BEWIDTHNUM-NEXT: ret void // void increment_c_st16(struct st16 *s) { @@ -3542,162 +3212,90 @@ void increment_c_st16(struct st16 *s) { // LE-LABEL: @increment_d_st16( // LE-NEXT: entry: -// LE-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// LE-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[D]], align 4 -// LE-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 16 -// LE-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// LE-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// LE-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 3 +// LE-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[D]], align 4 +// LE-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LE-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[D]], align 4 -// LE-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// LE-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 32 -// LE-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -281470681743361 -// LE-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// LE-NEXT: store i64 [[BF_SET]], ptr [[D]], align 4 -// LE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// LE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// LE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LE-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// LE-NEXT: store i16 [[TMP0]], ptr [[D]], align 4 +// LE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // LE-NEXT: ret void // // BE-LABEL: @increment_d_st16( // BE-NEXT: entry: -// BE-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// BE-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[D]], align 4 -// BE-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// BE-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// BE-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// BE-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 3 +// BE-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[D]], align 4 +// BE-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BE-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[D]], align 4 -// BE-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// BE-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 16 -// BE-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294901761 -// BE-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// BE-NEXT: store i64 [[BF_SET]], ptr [[D]], align 4 -// BE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// BE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// BE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BE-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// BE-NEXT: store i16 [[TMP0]], ptr [[D]], align 4 +// BE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // BE-NEXT: ret void // // LENUMLOADS-LABEL: @increment_d_st16( // LENUMLOADS-NEXT: entry: -// LENUMLOADS-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[D]], align 4 -// LENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 16 -// LENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// LENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// LENUMLOADS-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 3 +// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[D]], align 4 +// LENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[D]], align 4 -// LENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// LENUMLOADS-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 32 -// LENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -281470681743361 -// LENUMLOADS-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// LENUMLOADS-NEXT: store i64 [[BF_SET]], ptr [[D]], align 4 -// LENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// LENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LENUMLOADS-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// LENUMLOADS-NEXT: store i16 [[TMP0]], ptr [[D]], align 4 +// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // LENUMLOADS-NEXT: ret void // // BENUMLOADS-LABEL: @increment_d_st16( // BENUMLOADS-NEXT: entry: -// BENUMLOADS-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[D]], align 4 -// BENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// BENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// BENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// BENUMLOADS-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 3 +// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[D]], align 4 +// BENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[D]], align 4 -// BENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// BENUMLOADS-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 16 -// BENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294901761 -// BENUMLOADS-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// BENUMLOADS-NEXT: store i64 [[BF_SET]], ptr [[D]], align 4 -// BENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// BENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BENUMLOADS-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// BENUMLOADS-NEXT: store i16 [[TMP0]], ptr [[D]], align 4 +// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // BENUMLOADS-NEXT: ret void // // LEWIDTH-LABEL: @increment_d_st16( // LEWIDTH-NEXT: entry: -// LEWIDTH-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[D]], align 4 -// LEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 16 -// LEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// LEWIDTH-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// LEWIDTH-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 3 +// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[D]], align 4 +// LEWIDTH-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // LEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LEWIDTH-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[D]], align 4 -// LEWIDTH-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// LEWIDTH-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 32 -// LEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -281470681743361 -// LEWIDTH-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// LEWIDTH-NEXT: store i64 [[BF_SET]], ptr [[D]], align 4 -// LEWIDTH-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// LEWIDTH-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// LEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LEWIDTH-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// LEWIDTH-NEXT: store i16 [[TMP0]], ptr [[D]], align 4 +// LEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // LEWIDTH-NEXT: ret void // // BEWIDTH-LABEL: @increment_d_st16( // BEWIDTH-NEXT: entry: -// BEWIDTH-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[D]], align 4 -// BEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// BEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// BEWIDTH-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// BEWIDTH-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 3 +// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[D]], align 4 +// BEWIDTH-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // BEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BEWIDTH-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[D]], align 4 -// BEWIDTH-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// BEWIDTH-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 16 -// BEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294901761 -// BEWIDTH-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// BEWIDTH-NEXT: store i64 [[BF_SET]], ptr [[D]], align 4 -// BEWIDTH-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// BEWIDTH-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// BEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BEWIDTH-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// BEWIDTH-NEXT: store i16 [[TMP0]], ptr [[D]], align 4 +// BEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // BEWIDTH-NEXT: ret void // // LEWIDTHNUM-LABEL: @increment_d_st16( // LEWIDTHNUM-NEXT: entry: -// LEWIDTHNUM-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[D]], align 4 -// LEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 16 -// LEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// LEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// LEWIDTHNUM-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 3 +// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[D]], align 4 +// LEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // LEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LEWIDTHNUM-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[D]], align 4 -// LEWIDTHNUM-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// LEWIDTHNUM-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 32 -// LEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -281470681743361 -// LEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// LEWIDTHNUM-NEXT: store i64 [[BF_SET]], ptr [[D]], align 4 -// LEWIDTHNUM-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// LEWIDTHNUM-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// LEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LEWIDTHNUM-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// LEWIDTHNUM-NEXT: store i16 [[TMP0]], ptr [[D]], align 4 +// LEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // LEWIDTHNUM-NEXT: ret void // // BEWIDTHNUM-LABEL: @increment_d_st16( // BEWIDTHNUM-NEXT: entry: -// BEWIDTHNUM-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i64, ptr [[D]], align 4 -// BEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// BEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// BEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// BEWIDTHNUM-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 3 +// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[D]], align 4 +// BEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // BEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BEWIDTHNUM-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load i64, ptr [[D]], align 4 -// BEWIDTHNUM-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// BEWIDTHNUM-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 16 -// BEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294901761 -// BEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// BEWIDTHNUM-NEXT: store i64 [[BF_SET]], ptr [[D]], align 4 -// BEWIDTHNUM-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// BEWIDTHNUM-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// BEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BEWIDTHNUM-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// BEWIDTHNUM-NEXT: store i16 [[TMP0]], ptr [[D]], align 4 +// BEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // BEWIDTHNUM-NEXT: ret void // void increment_d_st16(struct st16 *s) { @@ -3706,74 +3304,32 @@ void increment_d_st16(struct st16 *s) { // LE-LABEL: @increment_v_a_st16( // LE-NEXT: entry: -// LE-NEXT: [[BF_LOAD:%.*]] = load volatile i64, ptr [[S:%.*]], align 4 -// LE-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// LE-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 32 -// LE-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LE-NEXT: [[BF_LOAD1:%.*]] = load volatile i64, ptr [[S]], align 4 -// LE-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// LE-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294967296 -// LE-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_VALUE]] -// LE-NEXT: store volatile i64 [[BF_SET]], ptr [[S]], align 4 -// LE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// LE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// LE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LE-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[S:%.*]], align 4 +// LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LE-NEXT: store volatile i32 [[INC]], ptr [[S]], align 4 // LE-NEXT: ret void // // BE-LABEL: @increment_v_a_st16( // BE-NEXT: entry: -// BE-NEXT: [[BF_LOAD:%.*]] = load volatile i64, ptr [[S:%.*]], align 4 -// BE-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_LOAD]], 32 -// BE-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BE-NEXT: [[BF_LOAD1:%.*]] = load volatile i64, ptr [[S]], align 4 -// BE-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// BE-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BE-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], 4294967295 -// BE-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL]] -// BE-NEXT: store volatile i64 [[BF_SET]], ptr [[S]], align 4 -// BE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// BE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BE-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[S:%.*]], align 4 +// BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BE-NEXT: store volatile i32 [[INC]], ptr [[S]], align 4 // BE-NEXT: ret void // // LENUMLOADS-LABEL: @increment_v_a_st16( // LENUMLOADS-NEXT: entry: -// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i64, ptr [[S:%.*]], align 4 -// LENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// LENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 32 -// LENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i64, ptr [[S]], align 4 -// LENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// LENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294967296 -// LENUMLOADS-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_VALUE]] -// LENUMLOADS-NEXT: store volatile i64 [[BF_SET]], ptr [[S]], align 4 -// LENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// LENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[S:%.*]], align 4 +// LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[S]], align 4 +// LENUMLOADS-NEXT: store volatile i32 [[INC]], ptr [[S]], align 4 // LENUMLOADS-NEXT: ret void // // BENUMLOADS-LABEL: @increment_v_a_st16( // BENUMLOADS-NEXT: entry: -// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i64, ptr [[S:%.*]], align 4 -// BENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_LOAD]], 32 -// BENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i64, ptr [[S]], align 4 -// BENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// BENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], 4294967295 -// BENUMLOADS-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL]] -// BENUMLOADS-NEXT: store volatile i64 [[BF_SET]], ptr [[S]], align 4 -// BENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[S:%.*]], align 4 +// BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[S]], align 4 +// BENUMLOADS-NEXT: store volatile i32 [[INC]], ptr [[S]], align 4 // BENUMLOADS-NEXT: ret void // // LEWIDTH-LABEL: @increment_v_a_st16( @@ -3812,140 +3368,110 @@ void increment_v_a_st16(volatile struct st16 *s) { // LE-LABEL: @increment_v_b_st16( // LE-NEXT: entry: -// LE-NEXT: [[BF_LOAD:%.*]] = load volatile i64, ptr [[S:%.*]], align 4 -// LE-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 16 -// LE-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// LE-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// LE-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// LE-NEXT: [[BF_LOAD:%.*]] = load volatile i16, ptr [[B]], align 4 +// LE-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LE-NEXT: [[BF_LOAD1:%.*]] = load volatile i64, ptr [[S]], align 4 -// LE-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// LE-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 32 -// LE-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -281470681743361 -// LE-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// LE-NEXT: store volatile i64 [[BF_SET]], ptr [[S]], align 4 -// LE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// LE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// LE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LE-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// LE-NEXT: store volatile i16 [[TMP0]], ptr [[B]], align 4 +// LE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // LE-NEXT: ret void // // BE-LABEL: @increment_v_b_st16( // BE-NEXT: entry: -// BE-NEXT: [[BF_LOAD:%.*]] = load volatile i64, ptr [[S:%.*]], align 4 -// BE-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// BE-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// BE-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// BE-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// BE-NEXT: [[BF_LOAD:%.*]] = load volatile i16, ptr [[B]], align 4 +// BE-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BE-NEXT: [[BF_LOAD1:%.*]] = load volatile i64, ptr [[S]], align 4 -// BE-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// BE-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 16 -// BE-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294901761 -// BE-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// BE-NEXT: store volatile i64 [[BF_SET]], ptr [[S]], align 4 -// BE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// BE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// BE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BE-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// BE-NEXT: store volatile i16 [[TMP0]], ptr [[B]], align 4 +// BE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // BE-NEXT: ret void // // LENUMLOADS-LABEL: @increment_v_b_st16( // LENUMLOADS-NEXT: entry: -// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i64, ptr [[S:%.*]], align 4 -// LENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 16 -// LENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// LENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// LENUMLOADS-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i16, ptr [[B]], align 4 +// LENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i64, ptr [[S]], align 4 -// LENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// LENUMLOADS-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 32 -// LENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -281470681743361 -// LENUMLOADS-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// LENUMLOADS-NEXT: store volatile i64 [[BF_SET]], ptr [[S]], align 4 -// LENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// LENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LENUMLOADS-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i16, ptr [[B]], align 4 +// LENUMLOADS-NEXT: store volatile i16 [[TMP0]], ptr [[B]], align 4 +// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // LENUMLOADS-NEXT: ret void // // BENUMLOADS-LABEL: @increment_v_b_st16( // BENUMLOADS-NEXT: entry: -// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i64, ptr [[S:%.*]], align 4 -// BENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// BENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// BENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// BENUMLOADS-NEXT: [[B:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i16, ptr [[B]], align 4 +// BENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i64, ptr [[S]], align 4 -// BENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// BENUMLOADS-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 16 -// BENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294901761 -// BENUMLOADS-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// BENUMLOADS-NEXT: store volatile i64 [[BF_SET]], ptr [[S]], align 4 -// BENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// BENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BENUMLOADS-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i16, ptr [[B]], align 4 +// BENUMLOADS-NEXT: store volatile i16 [[TMP0]], ptr [[B]], align 4 +// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // BENUMLOADS-NEXT: ret void // // LEWIDTH-LABEL: @increment_v_b_st16( // LEWIDTH-NEXT: entry: -// LEWIDTH-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 1 -// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// LEWIDTH-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 1 +// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP0]], align 4 // LEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_LOAD]], 16 // LEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_SHL]], 16 // LEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_ASHR]], 1 -// LEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// LEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[TMP0]], align 4 // LEWIDTH-NEXT: [[BF_VALUE:%.*]] = and i32 [[INC]], 65535 // LEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD1]], -65536 // LEWIDTH-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], [[BF_VALUE]] -// LEWIDTH-NEXT: store volatile i32 [[BF_SET]], ptr [[TMP1]], align 4 +// LEWIDTH-NEXT: store volatile i32 [[BF_SET]], ptr [[TMP0]], align 4 // LEWIDTH-NEXT: [[BF_RESULT_SHL:%.*]] = shl i32 [[BF_VALUE]], 16 // LEWIDTH-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i32 [[BF_RESULT_SHL]], 16 // LEWIDTH-NEXT: ret void // // BEWIDTH-LABEL: @increment_v_b_st16( // BEWIDTH-NEXT: entry: -// BEWIDTH-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 1 -// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// BEWIDTH-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 1 +// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP0]], align 4 // BEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_LOAD]], 16 // BEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_ASHR]], 1 -// BEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// BEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[TMP0]], align 4 // BEWIDTH-NEXT: [[BF_VALUE:%.*]] = and i32 [[INC]], 65535 // BEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_VALUE]], 16 // BEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD1]], 65535 // BEWIDTH-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], [[BF_SHL]] -// BEWIDTH-NEXT: store volatile i32 [[BF_SET]], ptr [[TMP1]], align 4 +// BEWIDTH-NEXT: store volatile i32 [[BF_SET]], ptr [[TMP0]], align 4 // BEWIDTH-NEXT: [[BF_RESULT_SHL:%.*]] = shl i32 [[BF_VALUE]], 16 // BEWIDTH-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i32 [[BF_RESULT_SHL]], 16 // BEWIDTH-NEXT: ret void // // LEWIDTHNUM-LABEL: @increment_v_b_st16( // LEWIDTHNUM-NEXT: entry: -// LEWIDTHNUM-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 1 -// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// LEWIDTHNUM-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 1 +// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP0]], align 4 // LEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_LOAD]], 16 // LEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_SHL]], 16 // LEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_ASHR]], 1 -// LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[TMP0]], align 4 // LEWIDTHNUM-NEXT: [[BF_VALUE:%.*]] = and i32 [[INC]], 65535 // LEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD1]], -65536 // LEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], [[BF_VALUE]] -// LEWIDTHNUM-NEXT: store volatile i32 [[BF_SET]], ptr [[TMP1]], align 4 +// LEWIDTHNUM-NEXT: store volatile i32 [[BF_SET]], ptr [[TMP0]], align 4 // LEWIDTHNUM-NEXT: [[BF_RESULT_SHL:%.*]] = shl i32 [[BF_VALUE]], 16 // LEWIDTHNUM-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i32 [[BF_RESULT_SHL]], 16 // LEWIDTHNUM-NEXT: ret void // // BEWIDTHNUM-LABEL: @increment_v_b_st16( // BEWIDTHNUM-NEXT: entry: -// BEWIDTHNUM-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 1 -// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// BEWIDTHNUM-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 1 +// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP0]], align 4 // BEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_LOAD]], 16 // BEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_ASHR]], 1 -// BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[TMP0]], align 4 // BEWIDTHNUM-NEXT: [[BF_VALUE:%.*]] = and i32 [[INC]], 65535 // BEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_VALUE]], 16 // BEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD1]], 65535 // BEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], [[BF_SHL]] -// BEWIDTHNUM-NEXT: store volatile i32 [[BF_SET]], ptr [[TMP1]], align 4 +// BEWIDTHNUM-NEXT: store volatile i32 [[BF_SET]], ptr [[TMP0]], align 4 // BEWIDTHNUM-NEXT: [[BF_RESULT_SHL:%.*]] = shl i32 [[BF_VALUE]], 16 // BEWIDTHNUM-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i32 [[BF_RESULT_SHL]], 16 // BEWIDTHNUM-NEXT: ret void @@ -3956,112 +3482,70 @@ void increment_v_b_st16(volatile struct st16 *s) { // LE-LABEL: @increment_v_c_st16( // LE-NEXT: entry: -// LE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// LE-NEXT: [[BF_LOAD:%.*]] = load volatile i64, ptr [[C]], align 4 -// LE-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// LE-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 32 -// LE-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LE-NEXT: [[BF_LOAD1:%.*]] = load volatile i64, ptr [[C]], align 4 -// LE-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// LE-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294967296 -// LE-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_VALUE]] -// LE-NEXT: store volatile i64 [[BF_SET]], ptr [[C]], align 4 -// LE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// LE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// LE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 2 +// LE-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[C]], align 4 +// LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LE-NEXT: store volatile i32 [[INC]], ptr [[C]], align 4 // LE-NEXT: ret void // // BE-LABEL: @increment_v_c_st16( // BE-NEXT: entry: -// BE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// BE-NEXT: [[BF_LOAD:%.*]] = load volatile i64, ptr [[C]], align 4 -// BE-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_LOAD]], 32 -// BE-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BE-NEXT: [[BF_LOAD1:%.*]] = load volatile i64, ptr [[C]], align 4 -// BE-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// BE-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BE-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], 4294967295 -// BE-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL]] -// BE-NEXT: store volatile i64 [[BF_SET]], ptr [[C]], align 4 -// BE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// BE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 2 +// BE-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[C]], align 4 +// BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BE-NEXT: store volatile i32 [[INC]], ptr [[C]], align 4 // BE-NEXT: ret void // // LENUMLOADS-LABEL: @increment_v_c_st16( // LENUMLOADS-NEXT: entry: -// LENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i64, ptr [[C]], align 4 -// LENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// LENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 32 -// LENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i64, ptr [[C]], align 4 -// LENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// LENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294967296 -// LENUMLOADS-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_VALUE]] -// LENUMLOADS-NEXT: store volatile i64 [[BF_SET]], ptr [[C]], align 4 -// LENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// LENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 2 +// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[C]], align 4 +// LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[C]], align 4 +// LENUMLOADS-NEXT: store volatile i32 [[INC]], ptr [[C]], align 4 // LENUMLOADS-NEXT: ret void // // BENUMLOADS-LABEL: @increment_v_c_st16( // BENUMLOADS-NEXT: entry: -// BENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i64, ptr [[C]], align 4 -// BENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_LOAD]], 32 -// BENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 -// BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i64, ptr [[C]], align 4 -// BENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 4294967295 -// BENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], 4294967295 -// BENUMLOADS-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL]] -// BENUMLOADS-NEXT: store volatile i64 [[BF_SET]], ptr [[C]], align 4 -// BENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 32 -// BENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 32 -// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 2 +// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[C]], align 4 +// BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[C]], align 4 +// BENUMLOADS-NEXT: store volatile i32 [[INC]], ptr [[C]], align 4 // BENUMLOADS-NEXT: ret void // // LEWIDTH-LABEL: @increment_v_c_st16( // LEWIDTH-NEXT: entry: -// LEWIDTH-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 2 -// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// LEWIDTH-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 2 +// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[C]], align 4 // LEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 -// LEWIDTH-NEXT: store volatile i32 [[INC]], ptr [[TMP1]], align 4 +// LEWIDTH-NEXT: store volatile i32 [[INC]], ptr [[C]], align 4 // LEWIDTH-NEXT: ret void // // BEWIDTH-LABEL: @increment_v_c_st16( // BEWIDTH-NEXT: entry: -// BEWIDTH-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 2 -// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// BEWIDTH-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 2 +// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[C]], align 4 // BEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 -// BEWIDTH-NEXT: store volatile i32 [[INC]], ptr [[TMP1]], align 4 +// BEWIDTH-NEXT: store volatile i32 [[INC]], ptr [[C]], align 4 // BEWIDTH-NEXT: ret void // // LEWIDTHNUM-LABEL: @increment_v_c_st16( // LEWIDTHNUM-NEXT: entry: -// LEWIDTHNUM-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 2 -// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// LEWIDTHNUM-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 2 +// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[C]], align 4 // LEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 -// LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[TMP1]], align 4 -// LEWIDTHNUM-NEXT: store volatile i32 [[INC]], ptr [[TMP1]], align 4 +// LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[C]], align 4 +// LEWIDTHNUM-NEXT: store volatile i32 [[INC]], ptr [[C]], align 4 // LEWIDTHNUM-NEXT: ret void // // BEWIDTHNUM-LABEL: @increment_v_c_st16( // BEWIDTHNUM-NEXT: entry: -// BEWIDTHNUM-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 2 -// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// BEWIDTHNUM-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 2 +// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[C]], align 4 // BEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 -// BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[TMP1]], align 4 -// BEWIDTHNUM-NEXT: store volatile i32 [[INC]], ptr [[TMP1]], align 4 +// BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[C]], align 4 +// BEWIDTHNUM-NEXT: store volatile i32 [[INC]], ptr [[C]], align 4 // BEWIDTHNUM-NEXT: ret void // void increment_v_c_st16(volatile struct st16 *s) { @@ -4070,144 +3554,110 @@ void increment_v_c_st16(volatile struct st16 *s) { // LE-LABEL: @increment_v_d_st16( // LE-NEXT: entry: -// LE-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// LE-NEXT: [[BF_LOAD:%.*]] = load volatile i64, ptr [[D]], align 4 -// LE-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 16 -// LE-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// LE-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// LE-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 3 +// LE-NEXT: [[BF_LOAD:%.*]] = load volatile i16, ptr [[D]], align 4 +// LE-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LE-NEXT: [[BF_LOAD1:%.*]] = load volatile i64, ptr [[D]], align 4 -// LE-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// LE-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 32 -// LE-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -281470681743361 -// LE-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// LE-NEXT: store volatile i64 [[BF_SET]], ptr [[D]], align 4 -// LE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// LE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// LE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LE-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// LE-NEXT: store volatile i16 [[TMP0]], ptr [[D]], align 4 +// LE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // LE-NEXT: ret void // // BE-LABEL: @increment_v_d_st16( // BE-NEXT: entry: -// BE-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// BE-NEXT: [[BF_LOAD:%.*]] = load volatile i64, ptr [[D]], align 4 -// BE-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// BE-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// BE-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// BE-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 3 +// BE-NEXT: [[BF_LOAD:%.*]] = load volatile i16, ptr [[D]], align 4 +// BE-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BE-NEXT: [[BF_LOAD1:%.*]] = load volatile i64, ptr [[D]], align 4 -// BE-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// BE-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 16 -// BE-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294901761 -// BE-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// BE-NEXT: store volatile i64 [[BF_SET]], ptr [[D]], align 4 -// BE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// BE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// BE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BE-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// BE-NEXT: store volatile i16 [[TMP0]], ptr [[D]], align 4 +// BE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // BE-NEXT: ret void // // LENUMLOADS-LABEL: @increment_v_d_st16( // LENUMLOADS-NEXT: entry: -// LENUMLOADS-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i64, ptr [[D]], align 4 -// LENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 16 -// LENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// LENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// LENUMLOADS-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 3 +// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i16, ptr [[D]], align 4 +// LENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i64, ptr [[D]], align 4 -// LENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// LENUMLOADS-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 32 -// LENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -281470681743361 -// LENUMLOADS-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// LENUMLOADS-NEXT: store volatile i64 [[BF_SET]], ptr [[D]], align 4 -// LENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// LENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// LENUMLOADS-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i16, ptr [[D]], align 4 +// LENUMLOADS-NEXT: store volatile i16 [[TMP0]], ptr [[D]], align 4 +// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // LENUMLOADS-NEXT: ret void // // BENUMLOADS-LABEL: @increment_v_d_st16( // BENUMLOADS-NEXT: entry: -// BENUMLOADS-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 1 -// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i64, ptr [[D]], align 4 -// BENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i64 [[BF_LOAD]], 32 -// BENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i64 [[BF_SHL]], 48 -// BENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i64 [[BF_ASHR]] to i32 +// BENUMLOADS-NEXT: [[D:%.*]] = getelementptr inbounds [[STRUCT_ST16:%.*]], ptr [[S:%.*]], i32 0, i32 3 +// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i16, ptr [[D]], align 4 +// BENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i16 [[BF_LOAD]] to i32 // BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i64 -// BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i64, ptr [[D]], align 4 -// BENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i64 [[TMP1]], 65535 -// BENUMLOADS-NEXT: [[BF_SHL2:%.*]] = shl i64 [[BF_VALUE]], 16 -// BENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i64 [[BF_LOAD1]], -4294901761 -// BENUMLOADS-NEXT: [[BF_SET:%.*]] = or i64 [[BF_CLEAR]], [[BF_SHL2]] -// BENUMLOADS-NEXT: store volatile i64 [[BF_SET]], ptr [[D]], align 4 -// BENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i64 [[BF_VALUE]], 48 -// BENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i64 [[BF_RESULT_SHL]], 48 -// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i64 [[BF_RESULT_ASHR]] to i32 +// BENUMLOADS-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i16 +// BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i16, ptr [[D]], align 4 +// BENUMLOADS-NEXT: store volatile i16 [[TMP0]], ptr [[D]], align 4 +// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i16 [[TMP0]] to i32 // BENUMLOADS-NEXT: ret void // // LEWIDTH-LABEL: @increment_v_d_st16( // LEWIDTH-NEXT: entry: -// LEWIDTH-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 3 -// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// LEWIDTH-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 3 +// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP0]], align 4 // LEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_LOAD]], 16 // LEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_SHL]], 16 // LEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_ASHR]], 1 -// LEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// LEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[TMP0]], align 4 // LEWIDTH-NEXT: [[BF_VALUE:%.*]] = and i32 [[INC]], 65535 // LEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD1]], -65536 // LEWIDTH-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], [[BF_VALUE]] -// LEWIDTH-NEXT: store volatile i32 [[BF_SET]], ptr [[TMP1]], align 4 +// LEWIDTH-NEXT: store volatile i32 [[BF_SET]], ptr [[TMP0]], align 4 // LEWIDTH-NEXT: [[BF_RESULT_SHL:%.*]] = shl i32 [[BF_VALUE]], 16 // LEWIDTH-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i32 [[BF_RESULT_SHL]], 16 // LEWIDTH-NEXT: ret void // // BEWIDTH-LABEL: @increment_v_d_st16( // BEWIDTH-NEXT: entry: -// BEWIDTH-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 3 -// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// BEWIDTH-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 3 +// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP0]], align 4 // BEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_LOAD]], 16 // BEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_ASHR]], 1 -// BEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// BEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[TMP0]], align 4 // BEWIDTH-NEXT: [[BF_VALUE:%.*]] = and i32 [[INC]], 65535 // BEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_VALUE]], 16 // BEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD1]], 65535 // BEWIDTH-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], [[BF_SHL]] -// BEWIDTH-NEXT: store volatile i32 [[BF_SET]], ptr [[TMP1]], align 4 +// BEWIDTH-NEXT: store volatile i32 [[BF_SET]], ptr [[TMP0]], align 4 // BEWIDTH-NEXT: [[BF_RESULT_SHL:%.*]] = shl i32 [[BF_VALUE]], 16 // BEWIDTH-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i32 [[BF_RESULT_SHL]], 16 // BEWIDTH-NEXT: ret void // // LEWIDTHNUM-LABEL: @increment_v_d_st16( // LEWIDTHNUM-NEXT: entry: -// LEWIDTHNUM-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 3 -// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// LEWIDTHNUM-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 3 +// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP0]], align 4 // LEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_LOAD]], 16 // LEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_SHL]], 16 // LEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_ASHR]], 1 -// LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[TMP0]], align 4 // LEWIDTHNUM-NEXT: [[BF_VALUE:%.*]] = and i32 [[INC]], 65535 // LEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD1]], -65536 // LEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], [[BF_VALUE]] -// LEWIDTHNUM-NEXT: store volatile i32 [[BF_SET]], ptr [[TMP1]], align 4 +// LEWIDTHNUM-NEXT: store volatile i32 [[BF_SET]], ptr [[TMP0]], align 4 // LEWIDTHNUM-NEXT: [[BF_RESULT_SHL:%.*]] = shl i32 [[BF_VALUE]], 16 // LEWIDTHNUM-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i32 [[BF_RESULT_SHL]], 16 // LEWIDTHNUM-NEXT: ret void // // BEWIDTHNUM-LABEL: @increment_v_d_st16( // BEWIDTHNUM-NEXT: entry: -// BEWIDTHNUM-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 3 -// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// BEWIDTHNUM-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[S:%.*]], i32 3 +// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[TMP0]], align 4 // BEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i32 [[BF_LOAD]], 16 // BEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_ASHR]], 1 -// BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[TMP1]], align 4 +// BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[TMP0]], align 4 // BEWIDTHNUM-NEXT: [[BF_VALUE:%.*]] = and i32 [[INC]], 65535 // BEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i32 [[BF_VALUE]], 16 // BEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD1]], 65535 // BEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], [[BF_SHL]] -// BEWIDTHNUM-NEXT: store volatile i32 [[BF_SET]], ptr [[TMP1]], align 4 +// BEWIDTHNUM-NEXT: store volatile i32 [[BF_SET]], ptr [[TMP0]], align 4 // BEWIDTHNUM-NEXT: [[BF_RESULT_SHL:%.*]] = shl i32 [[BF_VALUE]], 16 // BEWIDTHNUM-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i32 [[BF_RESULT_SHL]], 16 // BEWIDTHNUM-NEXT: ret void @@ -4224,146 +3674,62 @@ char c : 8; // LE-LABEL: @increment_v_b_st17( // LE-NEXT: entry: -// LE-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// LE-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_LOAD]], 8 -// LE-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_SHL]], 8 -// LE-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i32 -// LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i40 -// LE-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// LE-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 4294967295 -// LE-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], -4294967296 -// LE-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_VALUE]] -// LE-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// LE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// LE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 8 -// LE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i32 +// LE-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[S:%.*]], align 1 +// LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LE-NEXT: store volatile i32 [[INC]], ptr [[S]], align 1 // LE-NEXT: ret void // // BE-LABEL: @increment_v_b_st17( // BE-NEXT: entry: -// BE-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// BE-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_LOAD]], 8 -// BE-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i32 -// BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BE-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i40 -// BE-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// BE-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 4294967295 -// BE-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// BE-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], 255 -// BE-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_SHL]] -// BE-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// BE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// BE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 8 -// BE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i32 +// BE-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[S:%.*]], align 1 +// BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BE-NEXT: store volatile i32 [[INC]], ptr [[S]], align 1 // BE-NEXT: ret void // // LENUMLOADS-LABEL: @increment_v_b_st17( // LENUMLOADS-NEXT: entry: -// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// LENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_LOAD]], 8 -// LENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_SHL]], 8 -// LENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i32 -// LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i40 -// LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// LENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 4294967295 -// LENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], -4294967296 -// LENUMLOADS-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_VALUE]] -// LENUMLOADS-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// LENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// LENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 8 -// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i32 +// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[S:%.*]], align 1 +// LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[S]], align 1 +// LENUMLOADS-NEXT: store volatile i32 [[INC]], ptr [[S]], align 1 // LENUMLOADS-NEXT: ret void // // BENUMLOADS-LABEL: @increment_v_b_st17( // BENUMLOADS-NEXT: entry: -// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// BENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_LOAD]], 8 -// BENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i32 -// BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BENUMLOADS-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i40 -// BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// BENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 4294967295 -// BENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// BENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], 255 -// BENUMLOADS-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_SHL]] -// BENUMLOADS-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// BENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// BENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 8 -// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i32 +// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[S:%.*]], align 1 +// BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[S]], align 1 +// BENUMLOADS-NEXT: store volatile i32 [[INC]], ptr [[S]], align 1 // BENUMLOADS-NEXT: ret void // // LEWIDTH-LABEL: @increment_v_b_st17( // LEWIDTH-NEXT: entry: -// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// LEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_LOAD]], 8 -// LEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_SHL]], 8 -// LEWIDTH-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i32 -// LEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LEWIDTH-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i40 -// LEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// LEWIDTH-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 4294967295 -// LEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], -4294967296 -// LEWIDTH-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_VALUE]] -// LEWIDTH-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// LEWIDTH-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// LEWIDTH-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 8 -// LEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i32 +// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[S:%.*]], align 1 +// LEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LEWIDTH-NEXT: store volatile i32 [[INC]], ptr [[S]], align 1 // LEWIDTH-NEXT: ret void // // BEWIDTH-LABEL: @increment_v_b_st17( // BEWIDTH-NEXT: entry: -// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// BEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_LOAD]], 8 -// BEWIDTH-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i32 -// BEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BEWIDTH-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i40 -// BEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// BEWIDTH-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 4294967295 -// BEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// BEWIDTH-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], 255 -// BEWIDTH-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_SHL]] -// BEWIDTH-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// BEWIDTH-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// BEWIDTH-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 8 -// BEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i32 +// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[S:%.*]], align 1 +// BEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BEWIDTH-NEXT: store volatile i32 [[INC]], ptr [[S]], align 1 // BEWIDTH-NEXT: ret void // // LEWIDTHNUM-LABEL: @increment_v_b_st17( // LEWIDTHNUM-NEXT: entry: -// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// LEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_LOAD]], 8 -// LEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_SHL]], 8 -// LEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i32 -// LEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LEWIDTHNUM-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i40 -// LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// LEWIDTHNUM-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 4294967295 -// LEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], -4294967296 -// LEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_VALUE]] -// LEWIDTHNUM-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// LEWIDTHNUM-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// LEWIDTHNUM-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 8 -// LEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i32 +// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[S:%.*]], align 1 +// LEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[S]], align 1 +// LEWIDTHNUM-NEXT: store volatile i32 [[INC]], ptr [[S]], align 1 // LEWIDTHNUM-NEXT: ret void // // BEWIDTHNUM-LABEL: @increment_v_b_st17( // BEWIDTHNUM-NEXT: entry: -// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// BEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_LOAD]], 8 -// BEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i32 -// BEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BEWIDTHNUM-NEXT: [[TMP1:%.*]] = zext i32 [[INC]] to i40 -// BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// BEWIDTHNUM-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 4294967295 -// BEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// BEWIDTHNUM-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], 255 -// BEWIDTHNUM-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_SHL]] -// BEWIDTHNUM-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// BEWIDTHNUM-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 8 -// BEWIDTHNUM-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 8 -// BEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i32 +// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i32, ptr [[S:%.*]], align 1 +// BEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_LOAD]], 1 +// BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i32, ptr [[S]], align 1 +// BEWIDTHNUM-NEXT: store volatile i32 [[INC]], ptr [[S]], align 1 // BEWIDTHNUM-NEXT: ret void // void increment_v_b_st17(volatile struct st17 *s) { @@ -4372,108 +3738,70 @@ void increment_v_b_st17(volatile struct st17 *s) { // LE-LABEL: @increment_v_c_st17( // LE-NEXT: entry: -// LE-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// LE-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_LOAD]], 32 -// LE-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i8 -// LE-NEXT: [[INC:%.*]] = add i8 [[BF_CAST]], 1 -// LE-NEXT: [[TMP1:%.*]] = zext i8 [[INC]] to i40 -// LE-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// LE-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 255 -// LE-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_VALUE]], 32 -// LE-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], 4294967295 -// LE-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_SHL]] -// LE-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// LE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 32 -// LE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 32 -// LE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i8 +// LE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST17:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// LE-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 1 +// LE-NEXT: [[INC:%.*]] = add i8 [[BF_LOAD]], 1 +// LE-NEXT: store volatile i8 [[INC]], ptr [[C]], align 1 // LE-NEXT: ret void // // BE-LABEL: @increment_v_c_st17( // BE-NEXT: entry: -// BE-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// BE-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_LOAD]], 32 -// BE-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_SHL]], 32 -// BE-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i8 -// BE-NEXT: [[INC:%.*]] = add i8 [[BF_CAST]], 1 -// BE-NEXT: [[TMP1:%.*]] = zext i8 [[INC]] to i40 -// BE-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// BE-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 255 -// BE-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], -256 -// BE-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_VALUE]] -// BE-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// BE-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 32 -// BE-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 32 -// BE-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i8 +// BE-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST17:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// BE-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 1 +// BE-NEXT: [[INC:%.*]] = add i8 [[BF_LOAD]], 1 +// BE-NEXT: store volatile i8 [[INC]], ptr [[C]], align 1 // BE-NEXT: ret void // // LENUMLOADS-LABEL: @increment_v_c_st17( // LENUMLOADS-NEXT: entry: -// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// LENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_LOAD]], 32 -// LENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i8 -// LENUMLOADS-NEXT: [[INC:%.*]] = add i8 [[BF_CAST]], 1 -// LENUMLOADS-NEXT: [[TMP1:%.*]] = zext i8 [[INC]] to i40 -// LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// LENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 255 -// LENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_VALUE]], 32 -// LENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], 4294967295 -// LENUMLOADS-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_SHL]] -// LENUMLOADS-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// LENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 32 -// LENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 32 -// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i8 +// LENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST17:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 1 +// LENUMLOADS-NEXT: [[INC:%.*]] = add i8 [[BF_LOAD]], 1 +// LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[C]], align 1 +// LENUMLOADS-NEXT: store volatile i8 [[INC]], ptr [[C]], align 1 // LENUMLOADS-NEXT: ret void // // BENUMLOADS-LABEL: @increment_v_c_st17( // BENUMLOADS-NEXT: entry: -// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i40, ptr [[S:%.*]], align 1 -// BENUMLOADS-NEXT: [[BF_SHL:%.*]] = shl i40 [[BF_LOAD]], 32 -// BENUMLOADS-NEXT: [[BF_ASHR:%.*]] = ashr i40 [[BF_SHL]], 32 -// BENUMLOADS-NEXT: [[BF_CAST:%.*]] = trunc i40 [[BF_ASHR]] to i8 -// BENUMLOADS-NEXT: [[INC:%.*]] = add i8 [[BF_CAST]], 1 -// BENUMLOADS-NEXT: [[TMP1:%.*]] = zext i8 [[INC]] to i40 -// BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i40, ptr [[S]], align 1 -// BENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i40 [[TMP1]], 255 -// BENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i40 [[BF_LOAD1]], -256 -// BENUMLOADS-NEXT: [[BF_SET:%.*]] = or i40 [[BF_CLEAR]], [[BF_VALUE]] -// BENUMLOADS-NEXT: store volatile i40 [[BF_SET]], ptr [[S]], align 1 -// BENUMLOADS-NEXT: [[BF_RESULT_SHL:%.*]] = shl i40 [[BF_VALUE]], 32 -// BENUMLOADS-NEXT: [[BF_RESULT_ASHR:%.*]] = ashr i40 [[BF_RESULT_SHL]], 32 -// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = trunc i40 [[BF_RESULT_ASHR]] to i8 +// BENUMLOADS-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST17:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 1 +// BENUMLOADS-NEXT: [[INC:%.*]] = add i8 [[BF_LOAD]], 1 +// BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[C]], align 1 +// BENUMLOADS-NEXT: store volatile i8 [[INC]], ptr [[C]], align 1 // BENUMLOADS-NEXT: ret void // // LEWIDTH-LABEL: @increment_v_c_st17( // LEWIDTH-NEXT: entry: -// LEWIDTH-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[S:%.*]], i32 4 -// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP1]], align 1 +// LEWIDTH-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST17:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 1 // LEWIDTH-NEXT: [[INC:%.*]] = add i8 [[BF_LOAD]], 1 -// LEWIDTH-NEXT: store volatile i8 [[INC]], ptr [[TMP1]], align 1 +// LEWIDTH-NEXT: store volatile i8 [[INC]], ptr [[C]], align 1 // LEWIDTH-NEXT: ret void // // BEWIDTH-LABEL: @increment_v_c_st17( // BEWIDTH-NEXT: entry: -// BEWIDTH-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[S:%.*]], i32 4 -// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP1]], align 1 +// BEWIDTH-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST17:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 1 // BEWIDTH-NEXT: [[INC:%.*]] = add i8 [[BF_LOAD]], 1 -// BEWIDTH-NEXT: store volatile i8 [[INC]], ptr [[TMP1]], align 1 +// BEWIDTH-NEXT: store volatile i8 [[INC]], ptr [[C]], align 1 // BEWIDTH-NEXT: ret void // // LEWIDTHNUM-LABEL: @increment_v_c_st17( // LEWIDTHNUM-NEXT: entry: -// LEWIDTHNUM-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[S:%.*]], i32 4 -// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP1]], align 1 +// LEWIDTHNUM-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST17:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 1 // LEWIDTHNUM-NEXT: [[INC:%.*]] = add i8 [[BF_LOAD]], 1 -// LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[TMP1]], align 1 -// LEWIDTHNUM-NEXT: store volatile i8 [[INC]], ptr [[TMP1]], align 1 +// LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[C]], align 1 +// LEWIDTHNUM-NEXT: store volatile i8 [[INC]], ptr [[C]], align 1 // LEWIDTHNUM-NEXT: ret void // // BEWIDTHNUM-LABEL: @increment_v_c_st17( // BEWIDTHNUM-NEXT: entry: -// BEWIDTHNUM-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[S:%.*]], i32 4 -// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[TMP1]], align 1 +// BEWIDTHNUM-NEXT: [[C:%.*]] = getelementptr inbounds [[STRUCT_ST17:%.*]], ptr [[S:%.*]], i32 0, i32 1 +// BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[C]], align 1 // BEWIDTHNUM-NEXT: [[INC:%.*]] = add i8 [[BF_LOAD]], 1 -// BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[TMP1]], align 1 -// BEWIDTHNUM-NEXT: store volatile i8 [[INC]], ptr [[TMP1]], align 1 +// BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[C]], align 1 +// BEWIDTHNUM-NEXT: store volatile i8 [[INC]], ptr [[C]], align 1 // BEWIDTHNUM-NEXT: ret void // void increment_v_c_st17(volatile struct st17 *s) { @@ -4493,9 +3821,9 @@ struct zero_bitfield { // LE-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[S:%.*]], align 4 // LE-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i32 // LE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LE-NEXT: [[TMP1:%.*]] = trunc i32 [[INC]] to i8 -// LE-NEXT: store volatile i8 [[TMP1]], ptr [[S]], align 4 -// LE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i32 +// LE-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i8 +// LE-NEXT: store volatile i8 [[TMP0]], ptr [[S]], align 4 +// LE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i32 // LE-NEXT: ret void // // BE-LABEL: @increment_a_zero_bitfield( @@ -4503,9 +3831,9 @@ struct zero_bitfield { // BE-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[S:%.*]], align 4 // BE-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i32 // BE-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BE-NEXT: [[TMP1:%.*]] = trunc i32 [[INC]] to i8 -// BE-NEXT: store volatile i8 [[TMP1]], ptr [[S]], align 4 -// BE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i32 +// BE-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i8 +// BE-NEXT: store volatile i8 [[TMP0]], ptr [[S]], align 4 +// BE-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i32 // BE-NEXT: ret void // // LENUMLOADS-LABEL: @increment_a_zero_bitfield( @@ -4513,10 +3841,10 @@ struct zero_bitfield { // LENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[S:%.*]], align 4 // LENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i32 // LENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LENUMLOADS-NEXT: [[TMP1:%.*]] = trunc i32 [[INC]] to i8 +// LENUMLOADS-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i8 // LENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[S]], align 4 -// LENUMLOADS-NEXT: store volatile i8 [[TMP1]], ptr [[S]], align 4 -// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i32 +// LENUMLOADS-NEXT: store volatile i8 [[TMP0]], ptr [[S]], align 4 +// LENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i32 // LENUMLOADS-NEXT: ret void // // BENUMLOADS-LABEL: @increment_a_zero_bitfield( @@ -4524,10 +3852,10 @@ struct zero_bitfield { // BENUMLOADS-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[S:%.*]], align 4 // BENUMLOADS-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i32 // BENUMLOADS-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BENUMLOADS-NEXT: [[TMP1:%.*]] = trunc i32 [[INC]] to i8 +// BENUMLOADS-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i8 // BENUMLOADS-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[S]], align 4 -// BENUMLOADS-NEXT: store volatile i8 [[TMP1]], ptr [[S]], align 4 -// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i32 +// BENUMLOADS-NEXT: store volatile i8 [[TMP0]], ptr [[S]], align 4 +// BENUMLOADS-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i32 // BENUMLOADS-NEXT: ret void // // LEWIDTH-LABEL: @increment_a_zero_bitfield( @@ -4535,9 +3863,9 @@ struct zero_bitfield { // LEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[S:%.*]], align 4 // LEWIDTH-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i32 // LEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LEWIDTH-NEXT: [[TMP1:%.*]] = trunc i32 [[INC]] to i8 -// LEWIDTH-NEXT: store volatile i8 [[TMP1]], ptr [[S]], align 4 -// LEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i32 +// LEWIDTH-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i8 +// LEWIDTH-NEXT: store volatile i8 [[TMP0]], ptr [[S]], align 4 +// LEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i32 // LEWIDTH-NEXT: ret void // // BEWIDTH-LABEL: @increment_a_zero_bitfield( @@ -4545,9 +3873,9 @@ struct zero_bitfield { // BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[S:%.*]], align 4 // BEWIDTH-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i32 // BEWIDTH-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BEWIDTH-NEXT: [[TMP1:%.*]] = trunc i32 [[INC]] to i8 -// BEWIDTH-NEXT: store volatile i8 [[TMP1]], ptr [[S]], align 4 -// BEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i32 +// BEWIDTH-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i8 +// BEWIDTH-NEXT: store volatile i8 [[TMP0]], ptr [[S]], align 4 +// BEWIDTH-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i32 // BEWIDTH-NEXT: ret void // // LEWIDTHNUM-LABEL: @increment_a_zero_bitfield( @@ -4555,10 +3883,10 @@ struct zero_bitfield { // LEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[S:%.*]], align 4 // LEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i32 // LEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// LEWIDTHNUM-NEXT: [[TMP1:%.*]] = trunc i32 [[INC]] to i8 +// LEWIDTHNUM-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i8 // LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[S]], align 4 -// LEWIDTHNUM-NEXT: store volatile i8 [[TMP1]], ptr [[S]], align 4 -// LEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i32 +// LEWIDTHNUM-NEXT: store volatile i8 [[TMP0]], ptr [[S]], align 4 +// LEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i32 // LEWIDTHNUM-NEXT: ret void // // BEWIDTHNUM-LABEL: @increment_a_zero_bitfield( @@ -4566,10 +3894,10 @@ struct zero_bitfield { // BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i8, ptr [[S:%.*]], align 4 // BEWIDTHNUM-NEXT: [[BF_CAST:%.*]] = sext i8 [[BF_LOAD]] to i32 // BEWIDTHNUM-NEXT: [[INC:%.*]] = add nsw i32 [[BF_CAST]], 1 -// BEWIDTHNUM-NEXT: [[TMP1:%.*]] = trunc i32 [[INC]] to i8 +// BEWIDTHNUM-NEXT: [[TMP0:%.*]] = trunc i32 [[INC]] to i8 // BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[S]], align 4 -// BEWIDTHNUM-NEXT: store volatile i8 [[TMP1]], ptr [[S]], align 4 -// BEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP1]] to i32 +// BEWIDTHNUM-NEXT: store volatile i8 [[TMP0]], ptr [[S]], align 4 +// BEWIDTHNUM-NEXT: [[BF_RESULT_CAST:%.*]] = sext i8 [[TMP0]] to i32 // BEWIDTHNUM-NEXT: ret void // void increment_a_zero_bitfield(volatile struct zero_bitfield *s) { @@ -4692,9 +4020,9 @@ struct zero_bitfield_ok { // LE-NEXT: [[CONV3:%.*]] = sext i8 [[BF_CAST]] to i32 // LE-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV3]], [[CONV]] // LE-NEXT: [[CONV4:%.*]] = trunc i32 [[ADD]] to i8 -// LE-NEXT: [[TMP2:%.*]] = zext i8 [[CONV4]] to i16 +// LE-NEXT: [[TMP0:%.*]] = zext i8 [[CONV4]] to i16 // LE-NEXT: [[BF_LOAD5:%.*]] = load volatile i16, ptr [[S]], align 4 -// LE-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP2]], 255 +// LE-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP0]], 255 // LE-NEXT: [[BF_SHL6:%.*]] = shl i16 [[BF_VALUE]], 8 // LE-NEXT: [[BF_CLEAR:%.*]] = and i16 [[BF_LOAD5]], 255 // LE-NEXT: [[BF_SET:%.*]] = or i16 [[BF_CLEAR]], [[BF_SHL6]] @@ -4716,9 +4044,9 @@ struct zero_bitfield_ok { // BE-NEXT: [[CONV3:%.*]] = sext i8 [[BF_CAST]] to i32 // BE-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV3]], [[CONV]] // BE-NEXT: [[CONV4:%.*]] = trunc i32 [[ADD]] to i8 -// BE-NEXT: [[TMP2:%.*]] = zext i8 [[CONV4]] to i16 +// BE-NEXT: [[TMP0:%.*]] = zext i8 [[CONV4]] to i16 // BE-NEXT: [[BF_LOAD5:%.*]] = load volatile i16, ptr [[S]], align 4 -// BE-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP2]], 255 +// BE-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP0]], 255 // BE-NEXT: [[BF_CLEAR:%.*]] = and i16 [[BF_LOAD5]], -256 // BE-NEXT: [[BF_SET:%.*]] = or i16 [[BF_CLEAR]], [[BF_VALUE]] // BE-NEXT: store volatile i16 [[BF_SET]], ptr [[S]], align 4 @@ -4739,9 +4067,9 @@ struct zero_bitfield_ok { // LENUMLOADS-NEXT: [[CONV3:%.*]] = sext i8 [[BF_CAST]] to i32 // LENUMLOADS-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV3]], [[CONV]] // LENUMLOADS-NEXT: [[CONV4:%.*]] = trunc i32 [[ADD]] to i8 -// LENUMLOADS-NEXT: [[TMP2:%.*]] = zext i8 [[CONV4]] to i16 +// LENUMLOADS-NEXT: [[TMP0:%.*]] = zext i8 [[CONV4]] to i16 // LENUMLOADS-NEXT: [[BF_LOAD5:%.*]] = load volatile i16, ptr [[S]], align 4 -// LENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP2]], 255 +// LENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP0]], 255 // LENUMLOADS-NEXT: [[BF_SHL6:%.*]] = shl i16 [[BF_VALUE]], 8 // LENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i16 [[BF_LOAD5]], 255 // LENUMLOADS-NEXT: [[BF_SET:%.*]] = or i16 [[BF_CLEAR]], [[BF_SHL6]] @@ -4763,9 +4091,9 @@ struct zero_bitfield_ok { // BENUMLOADS-NEXT: [[CONV3:%.*]] = sext i8 [[BF_CAST]] to i32 // BENUMLOADS-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV3]], [[CONV]] // BENUMLOADS-NEXT: [[CONV4:%.*]] = trunc i32 [[ADD]] to i8 -// BENUMLOADS-NEXT: [[TMP2:%.*]] = zext i8 [[CONV4]] to i16 +// BENUMLOADS-NEXT: [[TMP0:%.*]] = zext i8 [[CONV4]] to i16 // BENUMLOADS-NEXT: [[BF_LOAD5:%.*]] = load volatile i16, ptr [[S]], align 4 -// BENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP2]], 255 +// BENUMLOADS-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP0]], 255 // BENUMLOADS-NEXT: [[BF_CLEAR:%.*]] = and i16 [[BF_LOAD5]], -256 // BENUMLOADS-NEXT: [[BF_SET:%.*]] = or i16 [[BF_CLEAR]], [[BF_VALUE]] // BENUMLOADS-NEXT: store volatile i16 [[BF_SET]], ptr [[S]], align 4 @@ -4780,12 +4108,12 @@ struct zero_bitfield_ok { // LEWIDTH-NEXT: [[BF_SHL:%.*]] = shl i16 [[BF_LOAD]], 8 // LEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_SHL]], 8 // LEWIDTH-NEXT: [[CONV:%.*]] = sext i16 [[BF_ASHR]] to i32 -// LEWIDTH-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 1 -// LEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[TMP2]], align 1 +// LEWIDTH-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 1 +// LEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[TMP0]], align 1 // LEWIDTH-NEXT: [[CONV2:%.*]] = sext i8 [[BF_LOAD1]] to i32 // LEWIDTH-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV2]], [[CONV]] // LEWIDTH-NEXT: [[CONV3:%.*]] = trunc i32 [[ADD]] to i8 -// LEWIDTH-NEXT: store volatile i8 [[CONV3]], ptr [[TMP2]], align 1 +// LEWIDTH-NEXT: store volatile i8 [[CONV3]], ptr [[TMP0]], align 1 // LEWIDTH-NEXT: ret void // // BEWIDTH-LABEL: @increment_a_zero_bitfield_ok( @@ -4793,12 +4121,12 @@ struct zero_bitfield_ok { // BEWIDTH-NEXT: [[BF_LOAD:%.*]] = load volatile i16, ptr [[S:%.*]], align 4 // BEWIDTH-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_LOAD]], 8 // BEWIDTH-NEXT: [[CONV:%.*]] = sext i16 [[BF_ASHR]] to i32 -// BEWIDTH-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 1 -// BEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[TMP2]], align 1 +// BEWIDTH-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 1 +// BEWIDTH-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[TMP0]], align 1 // BEWIDTH-NEXT: [[CONV2:%.*]] = sext i8 [[BF_LOAD1]] to i32 // BEWIDTH-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV2]], [[CONV]] // BEWIDTH-NEXT: [[CONV3:%.*]] = trunc i32 [[ADD]] to i8 -// BEWIDTH-NEXT: store volatile i8 [[CONV3]], ptr [[TMP2]], align 1 +// BEWIDTH-NEXT: store volatile i8 [[CONV3]], ptr [[TMP0]], align 1 // BEWIDTH-NEXT: ret void // // LEWIDTHNUM-LABEL: @increment_a_zero_bitfield_ok( @@ -4807,13 +4135,13 @@ struct zero_bitfield_ok { // LEWIDTHNUM-NEXT: [[BF_SHL:%.*]] = shl i16 [[BF_LOAD]], 8 // LEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_SHL]], 8 // LEWIDTHNUM-NEXT: [[CONV:%.*]] = sext i16 [[BF_ASHR]] to i32 -// LEWIDTHNUM-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 1 -// LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[TMP2]], align 1 +// LEWIDTHNUM-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 1 +// LEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[TMP0]], align 1 // LEWIDTHNUM-NEXT: [[CONV2:%.*]] = sext i8 [[BF_LOAD1]] to i32 // LEWIDTHNUM-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV2]], [[CONV]] // LEWIDTHNUM-NEXT: [[CONV3:%.*]] = trunc i32 [[ADD]] to i8 -// LEWIDTHNUM-NEXT: [[BF_LOAD4:%.*]] = load volatile i8, ptr [[TMP2]], align 1 -// LEWIDTHNUM-NEXT: store volatile i8 [[CONV3]], ptr [[TMP2]], align 1 +// LEWIDTHNUM-NEXT: [[BF_LOAD4:%.*]] = load volatile i8, ptr [[TMP0]], align 1 +// LEWIDTHNUM-NEXT: store volatile i8 [[CONV3]], ptr [[TMP0]], align 1 // LEWIDTHNUM-NEXT: ret void // // BEWIDTHNUM-LABEL: @increment_a_zero_bitfield_ok( @@ -4821,13 +4149,13 @@ struct zero_bitfield_ok { // BEWIDTHNUM-NEXT: [[BF_LOAD:%.*]] = load volatile i16, ptr [[S:%.*]], align 4 // BEWIDTHNUM-NEXT: [[BF_ASHR:%.*]] = ashr i16 [[BF_LOAD]], 8 // BEWIDTHNUM-NEXT: [[CONV:%.*]] = sext i16 [[BF_ASHR]] to i32 -// BEWIDTHNUM-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 1 -// BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[TMP2]], align 1 +// BEWIDTHNUM-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 1 +// BEWIDTHNUM-NEXT: [[BF_LOAD1:%.*]] = load volatile i8, ptr [[TMP0]], align 1 // BEWIDTHNUM-NEXT: [[CONV2:%.*]] = sext i8 [[BF_LOAD1]] to i32 // BEWIDTHNUM-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV2]], [[CONV]] // BEWIDTHNUM-NEXT: [[CONV3:%.*]] = trunc i32 [[ADD]] to i8 -// BEWIDTHNUM-NEXT: [[BF_LOAD4:%.*]] = load volatile i8, ptr [[TMP2]], align 1 -// BEWIDTHNUM-NEXT: store volatile i8 [[CONV3]], ptr [[TMP2]], align 1 +// BEWIDTHNUM-NEXT: [[BF_LOAD4:%.*]] = load volatile i8, ptr [[TMP0]], align 1 +// BEWIDTHNUM-NEXT: store volatile i8 [[CONV3]], ptr [[TMP0]], align 1 // BEWIDTHNUM-NEXT: ret void // void increment_a_zero_bitfield_ok(volatile struct zero_bitfield_ok *s) { diff --git a/clang/test/CodeGen/aapcs64-align.cpp b/clang/test/CodeGen/aapcs64-align.cpp index 759413cbc4b56f6d337bd1ad2c617128e13d51cf..de231f2123b975546a525303593e316437966c16 100644 --- a/clang/test/CodeGen/aapcs64-align.cpp +++ b/clang/test/CodeGen/aapcs64-align.cpp @@ -75,8 +75,8 @@ void g4() { f4m(1, 2, 3, 4, 5, s); } // CHECK: define{{.*}} void @g4() -// CHECK: call void @f4(i32 noundef 1, [2 x i64] %{{.*}}) -// CHECK: void @f4m(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 noundef 4, i32 noundef 5, [2 x i64] %{{.*}}) +// CHECK: call void @f4(i32 noundef 1, [2 x i64] [i64 30064771078, i64 0]) +// CHECK: void @f4m(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 noundef 4, i32 noundef 5, [2 x i64] [i64 30064771078, i64 0]) // CHECK: declare void @f4(i32 noundef, [2 x i64]) // CHECK: declare void @f4m(i32 noundef, i32 noundef, i32 noundef, i32 noundef, i32 noundef, [2 x i64]) @@ -95,8 +95,8 @@ void f5m(int, int, int, int, int, P16); f5m(1, 2, 3, 4, 5, s); } // CHECK: define{{.*}} void @g5() -// CHECK: call void @f5(i32 noundef 1, [2 x i64] %{{.*}}) -// CHECK: void @f5m(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 noundef 4, i32 noundef 5, [2 x i64] %{{.*}}) +// CHECK: call void @f5(i32 noundef 1, [2 x i64] [i64 30064771078, i64 0]) +// CHECK: void @f5m(i32 noundef 1, i32 noundef 2, i32 noundef 3, i32 noundef 4, i32 noundef 5, [2 x i64] [i64 30064771078, i64 0]) // CHECK: declare void @f5(i32 noundef, [2 x i64]) // CHECK: declare void @f5m(i32 noundef, i32 noundef, i32 noundef, i32 noundef, i32 noundef, [2 x i64]) diff --git a/clang/test/CodeGen/aarch64-ABI-align-packed.c b/clang/test/CodeGen/aarch64-ABI-align-packed.c index 2b029f6458956758892c07b2ac89d70bb200f16e..13c68fe54b849fe03ee3c9a061c4e4a90e91f249 100644 --- a/clang/test/CodeGen/aarch64-ABI-align-packed.c +++ b/clang/test/CodeGen/aarch64-ABI-align-packed.c @@ -73,7 +73,7 @@ __attribute__((noinline)) void named_arg_non_packed_struct(double d0, double d1, // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6:[0-9]+]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_non_packed_struct(double d0, double d1, double d2, double d3, @@ -128,7 +128,7 @@ __attribute__((noinline)) void named_arg_packed_struct(double d0, double d1, dou // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_packed_struct(double d0, double d1, double d2, double d3, @@ -183,7 +183,7 @@ __attribute__((noinline)) void named_arg_packed_member(double d0, double d1, dou // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_packed_member(double d0, double d1, double d2, double d3, @@ -238,7 +238,7 @@ __attribute__((noinline)) void named_arg_aligned_struct_8(double d0, double d1, // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_aligned_struct_8(double d0, double d1, double d2, double d3, @@ -293,7 +293,7 @@ __attribute__((noinline)) void named_arg_aligned_member_8(double d0, double d1, // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_aligned_member_8(double d0, double d1, double d2, double d3, @@ -348,7 +348,7 @@ __attribute__((noinline)) void named_arg_pragma_packed_struct_8(double d0, doubl // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_pragma_packed_struct_8(double d0, double d1, double d2, double d3, @@ -403,7 +403,7 @@ __attribute__((noinline)) void named_arg_pragma_packed_struct_4(double d0, doubl // CHECK-NEXT: entry: // CHECK-NEXT: [[VL:%.*]] = alloca [[STRUCT___VA_LIST:%.*]], align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] -// CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[VL]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[VL]]) // CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[VL]]) #[[ATTR6]] // CHECK-NEXT: ret void void variadic_pragma_packed_struct_4(double d0, double d1, double d2, double d3, diff --git a/clang/test/CodeGen/aarch64-mixed-target-attributes.c b/clang/test/CodeGen/aarch64-mixed-target-attributes.c new file mode 100644 index 0000000000000000000000000000000000000000..aef6ce36ab1c05a09c03f04dfd267423dc9cb118 --- /dev/null +++ b/clang/test/CodeGen/aarch64-mixed-target-attributes.c @@ -0,0 +1,278 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals --include-generated-funcs +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -v9.5a -S -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -fmv -S -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-NOFMV + +// The following is guarded because in NOFMV we get an error for redefining the default. +#ifdef __HAVE_FUNCTION_MULTI_VERSIONING +int explicit_default(void) { return 0; } +__attribute__((target_version("jscvt"))) int explicit_default(void) { return 1; } +__attribute__((target_clones("dotprod", "lse"))) int explicit_default(void) { return 2; } +__attribute__((target_version("rdma"))) int explicit_default(void) { return 3; } + +int foo(void) { return explicit_default(); } +#endif + +__attribute__((target_version("jscvt"))) int implicit_default(void) { return 1; } +__attribute__((target_clones("dotprod", "lse"))) int implicit_default(void) { return 2; } +__attribute__((target_version("rdma"))) int implicit_default(void) { return 3; } + +int bar(void) { return implicit_default(); } + +// These shouldn't generate anything. +int unused_version_declarations(void); +__attribute__((target_clones("dotprod", "lse"))) int unused_version_declarations(void); +__attribute__((target_version("jscvt"))) int unused_version_declarations(void); + +// These should generate the default (mangled) version and the resolver. +int default_def_with_version_decls(void) { return 0; } +__attribute__((target_clones("dotprod", "lse"))) int default_def_with_version_decls(void); +__attribute__((target_version("jscvt"))) int default_def_with_version_decls(void); + +//. +// CHECK: @__aarch64_cpu_features = external dso_local global { i64 } +// CHECK: @explicit_default.ifunc = weak_odr alias i32 (), ptr @explicit_default +// CHECK: @implicit_default.ifunc = weak_odr alias i32 (), ptr @implicit_default +// CHECK: @default_def_with_version_decls.ifunc = weak_odr alias i32 (), ptr @default_def_with_version_decls +// CHECK: @explicit_default = weak_odr ifunc i32 (), ptr @explicit_default.resolver +// CHECK: @implicit_default = weak_odr ifunc i32 (), ptr @implicit_default.resolver +// CHECK: @default_def_with_version_decls = weak_odr ifunc i32 (), ptr @default_def_with_version_decls.resolver +//. +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@explicit_default.default +// CHECK-SAME: () #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 0 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@explicit_default._Mjscvt +// CHECK-SAME: () #[[ATTR1:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@explicit_default._Mdotprod +// CHECK-SAME: () #[[ATTR2:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@explicit_default._Mlse +// CHECK-SAME: () #[[ATTR3:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// +// CHECK-LABEL: define {{[^@]+}}@explicit_default.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1048576 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1048576 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @explicit_default._Mjscvt +// CHECK: resolver_else: +// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 64 +// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 64 +// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]] +// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] +// CHECK: resolver_return1: +// CHECK-NEXT: ret ptr @explicit_default._Mrdm +// CHECK: resolver_else2: +// CHECK-NEXT: [[TMP8:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = and i64 [[TMP8]], 16 +// CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 16 +// CHECK-NEXT: [[TMP11:%.*]] = and i1 true, [[TMP10]] +// CHECK-NEXT: br i1 [[TMP11]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]] +// CHECK: resolver_return3: +// CHECK-NEXT: ret ptr @explicit_default._Mdotprod +// CHECK: resolver_else4: +// CHECK-NEXT: [[TMP12:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = and i64 [[TMP12]], 128 +// CHECK-NEXT: [[TMP14:%.*]] = icmp eq i64 [[TMP13]], 128 +// CHECK-NEXT: [[TMP15:%.*]] = and i1 true, [[TMP14]] +// CHECK-NEXT: br i1 [[TMP15]], label [[RESOLVER_RETURN5:%.*]], label [[RESOLVER_ELSE6:%.*]] +// CHECK: resolver_return5: +// CHECK-NEXT: ret ptr @explicit_default._Mlse +// CHECK: resolver_else6: +// CHECK-NEXT: ret ptr @explicit_default.default +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@explicit_default._Mrdm +// CHECK-SAME: () #[[ATTR4:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 3 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@foo +// CHECK-SAME: () #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = call i32 @explicit_default() +// CHECK-NEXT: ret i32 [[CALL]] +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@implicit_default._Mjscvt +// CHECK-SAME: () #[[ATTR1]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@implicit_default._Mdotprod +// CHECK-SAME: () #[[ATTR2]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@implicit_default._Mlse +// CHECK-SAME: () #[[ATTR3]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// +// CHECK-LABEL: define {{[^@]+}}@implicit_default.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1048576 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1048576 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @implicit_default._Mjscvt +// CHECK: resolver_else: +// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 64 +// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 64 +// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]] +// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] +// CHECK: resolver_return1: +// CHECK-NEXT: ret ptr @implicit_default._Mrdm +// CHECK: resolver_else2: +// CHECK-NEXT: [[TMP8:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = and i64 [[TMP8]], 16 +// CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 16 +// CHECK-NEXT: [[TMP11:%.*]] = and i1 true, [[TMP10]] +// CHECK-NEXT: br i1 [[TMP11]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]] +// CHECK: resolver_return3: +// CHECK-NEXT: ret ptr @implicit_default._Mdotprod +// CHECK: resolver_else4: +// CHECK-NEXT: [[TMP12:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = and i64 [[TMP12]], 128 +// CHECK-NEXT: [[TMP14:%.*]] = icmp eq i64 [[TMP13]], 128 +// CHECK-NEXT: [[TMP15:%.*]] = and i1 true, [[TMP14]] +// CHECK-NEXT: br i1 [[TMP15]], label [[RESOLVER_RETURN5:%.*]], label [[RESOLVER_ELSE6:%.*]] +// CHECK: resolver_return5: +// CHECK-NEXT: ret ptr @implicit_default._Mlse +// CHECK: resolver_else6: +// CHECK-NEXT: ret ptr @implicit_default.default +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@implicit_default._Mrdm +// CHECK-SAME: () #[[ATTR4]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 3 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@bar +// CHECK-SAME: () #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[CALL:%.*]] = call i32 @implicit_default() +// CHECK-NEXT: ret i32 [[CALL]] +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@default_def_with_version_decls.default +// CHECK-SAME: () #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 0 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@implicit_default.default +// CHECK-SAME: () #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// +// CHECK-LABEL: define {{[^@]+}}@default_def_with_version_decls.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1048576 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1048576 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @default_def_with_version_decls._Mjscvt +// CHECK: resolver_else: +// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 16 +// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 16 +// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]] +// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] +// CHECK: resolver_return1: +// CHECK-NEXT: ret ptr @default_def_with_version_decls._Mdotprod +// CHECK: resolver_else2: +// CHECK-NEXT: [[TMP8:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = and i64 [[TMP8]], 128 +// CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 128 +// CHECK-NEXT: [[TMP11:%.*]] = and i1 true, [[TMP10]] +// CHECK-NEXT: br i1 [[TMP11]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]] +// CHECK: resolver_return3: +// CHECK-NEXT: ret ptr @default_def_with_version_decls._Mlse +// CHECK: resolver_else4: +// CHECK-NEXT: ret ptr @default_def_with_version_decls.default +// +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@implicit_default +// CHECK-NOFMV-SAME: () #[[ATTR0:[0-9]+]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: ret i32 2 +// +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@bar +// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: [[CALL:%.*]] = call i32 @implicit_default() +// CHECK-NOFMV-NEXT: ret i32 [[CALL]] +// +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@default_def_with_version_decls +// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: ret i32 0 +// +//. +// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-v9.5a" } +// CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+jsconv,+neon,-v9.5a" } +// CHECK: attributes #[[ATTR2]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+neon,-v9.5a" } +// CHECK: attributes #[[ATTR3]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,-v9.5a" } +// CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rdm,-v9.5a" } +// CHECK: attributes #[[ATTR5:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+neon,-v9.5a" } +// CHECK: attributes #[[ATTR6:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+jsconv,+neon,-v9.5a" } +// CHECK: attributes #[[ATTR7:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-v9.5a" } +// CHECK: attributes #[[ATTR8:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,-v9.5a" } +//. +// CHECK-NOFMV: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" } +//. +// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} +// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"} +//. +// CHECK-NOFMV: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} +// CHECK-NOFMV: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"} +//. diff --git a/clang/test/CodeGen/aarch64-soft-float-abi-errors.c b/clang/test/CodeGen/aarch64-soft-float-abi-errors.c new file mode 100644 index 0000000000000000000000000000000000000000..551e53bcd63d8a9390bce58760141cc18066cac3 --- /dev/null +++ b/clang/test/CodeGen/aarch64-soft-float-abi-errors.c @@ -0,0 +1,99 @@ +// REQUIRES: aarch64-registered-target + +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +fp-armv8 -S -o /dev/null -target-abi aapcs -verify=fp-hard %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -fp-armv8 -S -o /dev/null -target-abi aapcs-soft -verify=nofp-soft %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -fp-armv8 -S -o /dev/null -target-abi aapcs -verify=nofp-hard %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -fp-armv8 -S -o /dev/null -target-abi aapcs -O1 -verify=nofp-hard,nofp-hard-opt -emit-llvm %s +// No run line needed for soft-float ABI with an FPU because that is rejected by the driver + +// With the hard-float ABI and a target with an FPU, FP arguments are passed in +// FP registers, no diagnostics needed. +// fp-hard-no-diagnostics + +// With the soft-float ABI, FP arguments are passed in integer registers, no +// diagnostics needed. +// nofp-soft-no-diagnostics + +// With the hard-float ABI but no FPU, FP arguments cannot be passed in an +// ABI-compatible way, so we report errors for these cases: + +struct HFA { + float x, y; +}; + +struct non_HFA { + float x; + int y; +}; + +// Floating-point arguments are returns are rejected +void test_fp16_arg(__fp16 a) {} +// nofp-hard-error@-1 {{'a' requires '__fp16' type support, but ABI 'aapcs' does not support it}} +__fp16 test_fp16_ret(void) { return 3.141; } +// nofp-hard-error@-1 {{'test_fp16_ret' requires '__fp16' type support, but ABI 'aapcs' does not support it}} +void test_float_arg(float a) {} +// nofp-hard-error@-1 {{'a' requires 'float' type support, but ABI 'aapcs' does not support it}} +float test_float_ret(void) { return 3.141f; } +// nofp-hard-error@-1 {{'test_float_ret' requires 'float' type support, but ABI 'aapcs' does not support it}} +void test_double_arg(double a) {} +// nofp-hard-error@-1 {{'a' requires 'double' type support, but ABI 'aapcs' does not support it}} +double test_double_ret(void) { return 3.141; } +// nofp-hard-error@-1 {{'test_double_ret' requires 'double' type support, but ABI 'aapcs' does not support it}} +void test_long_double_arg(long double a) {} +// nofp-hard-error@-1 {{'a' requires 'long double' type support, but ABI 'aapcs' does not support it}} +long double test_long_double_ret(void) { return 3.141L; } +// nofp-hard-error@-1 {{'test_long_double_ret' requires 'long double' type support, but ABI 'aapcs' does not support it}} + +// HFAs would be passed in floating-point registers, so are rejected. +void test_hfa_arg(struct HFA a) {} +// nofp-hard-error@-1 {{'a' requires 'struct HFA' type support, but ABI 'aapcs' does not support it}} +struct HFA test_hfa_ret(void) { return (struct HFA){}; } +// nofp-hard-error@-1 {{'test_hfa_ret' requires 'struct HFA' type support, but ABI 'aapcs' does not support it}} + +// Note: vector types cannot be created at all for targets without an FPU, so +// it is not possible to create a function which passes/returns them when using +// either the default or soft-float ABI. This is tested elsewhere. + +// This struct contains a floating-point type, but is not an HFA, so can be +// passed/returned without affecting the ABI. +struct non_HFA test_non_hfa_ret(void) { return (struct non_HFA){}; } +void test_non_hfa_arg(struct non_HFA a) {} + +// This inline function does not get code-generated because there is no use of +// it in this file, so we we don't emit an error for it, matching GCC's +// behaviour. +inline void test_float_arg_inline(float a) {} + +// This inline function is used, so we emit the error if we generate code for +// it. The code isn't generated at -O0, so no error is emitted there. +inline void test_float_arg_inline_used(float a) {} +// nofp-hard-opt-error@-1 {{'a' requires 'float' type support, but ABI 'aapcs' does not support it}} +void use_inline() { test_float_arg_inline_used(1.0f); } + +// The always_inline attribute causes an inline function to always be +// code-genned, even at -O0, so we always emit the error. +__attribute((always_inline)) +inline void test_float_arg_always_inline_used(float a) {} +// nofp-hard-error@-1 {{'a' requires 'float' type support, but ABI 'aapcs' does not support it}} +void use_always_inline() { test_float_arg_always_inline_used(1.0f); } + +// Floating-point expressions, global variables and local variables do not +// affect the ABI, so are allowed. GCC does reject some uses of floating point +// types like this, but it does so after optimisation, which we can't +// accurately match in clang. +int test_expr_float(int a) { return a + 1.0f; } +int test_expr_double(int a) { return a + 1.0; } + +float global_float = 2.0f * 3.5f; +float global_double = 2.0 * 3.5; + +int test_var_float(int a) { + float f = a; + f *= 6.0; + return (int)f; +} +int test_var_double(int a) { + double d = a; + d *= 6.0; + return (int)d; +} diff --git a/clang/test/CodeGen/aarch64-soft-float-abi.c b/clang/test/CodeGen/aarch64-soft-float-abi.c new file mode 100644 index 0000000000000000000000000000000000000000..143377e218a19714e872e989d3628936550dcc08 --- /dev/null +++ b/clang/test/CodeGen/aarch64-soft-float-abi.c @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -triple aarch64 -target-feature +fp-armv8 -target-abi aapcs -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,HARD +// RUN: %clang_cc1 -triple aarch64 -target-feature -fp-armv8 -target-abi aapcs-soft -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,SOFT + +// See also llvm/test/CodeGen/AArch64/soft-float-abi.ll, which checks the LLVM +// backend parts of the soft-float ABI. + +// The va_list type does not change between the ABIs +// CHECK: %struct.__va_list = type { ptr, ptr, ptr, i32, i32 } + +// Floats are passed in integer registers, this will be handled by the backend. +// CHECK: define dso_local half @test0(half noundef %a) +// CHECK: define dso_local bfloat @test1(bfloat noundef %a) +// CHECK: define dso_local float @test2(float noundef %a) +// CHECK: define dso_local double @test3(double noundef %a) +// CHECK: define dso_local fp128 @test4(fp128 noundef %a) +__fp16 test0(__fp16 a) { return a; } +__bf16 test1(__bf16 a) { return a; } +float test2(float a) { return a; } +double test3(double a) { return a; } +long double test4(long double a) { return a; } + +// No types are considered to be HFAs or HVAs by the soft-float PCS, so these +// are converted to integer types. +struct A { + float x; +}; +// SOFT: define dso_local i32 @test10(i64 %a.coerce) +// HARD: define dso_local %struct.A @test10([1 x float] alignstack(8) %a.coerce) +struct A test10(struct A a) { return a; } + +struct B { + double x; + double y; +}; +// SOFT: define dso_local [2 x i64] @test11([2 x i64] %a.coerce) +// HARD: define dso_local %struct.B @test11([2 x double] alignstack(8) %a.coerce) +struct B test11(struct B a) { return a; } + +#include <stdarg.h> + +// The layout of the va_list struct is unchanged between the ABIs, but for +// aapcs-soft, floating-point arguments will be retreived from the GPR save +// area, as if they were an integer type of the same size. +// CHECK-LABEL: define dso_local double @test20(i32 noundef %a, ...) +// CHECK: %vl = alloca %struct.__va_list, align 8 +// SOFT: %gr_offs_p = getelementptr inbounds %struct.__va_list, ptr %vl, i32 0, i32 3 +// SOFT: %reg_top_p = getelementptr inbounds %struct.__va_list, ptr %vl, i32 0, i32 1 +// HARD: %vr_offs_p = getelementptr inbounds %struct.__va_list, ptr %vl, i32 0, i32 4 +// HARD: %reg_top_p = getelementptr inbounds %struct.__va_list, ptr %vl, i32 0, i32 2 +double test20(int a, ...) { + va_list vl; + va_start(vl, a); + return va_arg(vl, double); +} + +// Vector types are only available for targets with the correct hardware, and +// their calling-convention is left undefined by the soft-float ABI, so they +// aren't tested here. diff --git a/clang/test/CodeGen/aarch64-varargs.c b/clang/test/CodeGen/aarch64-varargs.c index 44b87029e7b3d3fe1e43edd2f32e302d24e19be3..ee4e88eda4ef44142f1afb0d44e73beb57bd5e60 100644 --- a/clang/test/CodeGen/aarch64-varargs.c +++ b/clang/test/CodeGen/aarch64-varargs.c @@ -837,7 +837,7 @@ void check_start(int n, ...) { va_list the_list; va_start(the_list, n); // CHECK: [[THE_LIST:%[a-z_0-9]+]] = alloca %struct.__va_list -// CHECK: call void @llvm.va_start(ptr [[THE_LIST]]) +// CHECK: call void @llvm.va_start.p0(ptr [[THE_LIST]]) } typedef struct {} empty; diff --git a/clang/test/CodeGen/arm-bitfield-alignment.c b/clang/test/CodeGen/arm-bitfield-alignment.c index e34789face5584a663db4271fd23c8be97ea8ad9..5d0967ec70346cd0b83e894595bec002a5060893 100644 --- a/clang/test/CodeGen/arm-bitfield-alignment.c +++ b/clang/test/CodeGen/arm-bitfield-alignment.c @@ -1,5 +1,7 @@ -// RUN: %clang_cc1 -triple arm-none-eabi -ffreestanding -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple aarch64 -ffreestanding -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple arm-none-eabi -fdump-record-layouts-simple -ffreestanding -emit-llvm -o %t %s | FileCheck %s -check-prefixes=LAYOUT,LAYOUT-32 +// RUN: FileCheck %s -check-prefixes=IR,IR-32 <%t +// RUN: %clang_cc1 -triple aarch64 -fdump-record-layouts-simple -ffreestanding -emit-llvm -o %t %s | FileCheck %s -check-prefixes=LAYOUT,LAYOUT-64 +// RUN: FileCheck %s -check-prefixes=IR,IR-64 <%t extern struct T { int b0 : 8; @@ -11,5 +13,18 @@ int func(void) { return g.b1; } -// CHECK: @g = external global %struct.T, align 4 -// CHECK: %{{.*}} = load i64, ptr @g, align 4 +// IR: @g = external global %struct.T, align 4 +// IR-32: %{{.*}} = load i32, ptr @g, align 4 +// IR-64: %{{.*}} = load i64, ptr @g, align 4 + +// LAYOUT-LABEL: LLVMType:%struct.T = +// LAYOUT-32-SAME: type { i32, i8 } +// LAYOUT-64-SAME: type { i64 } +// LAYOUT: BitFields:[ +// LAYOUT-32-NEXT: <CGBitFieldInfo Offset:0 Size:8 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-32-NEXT: <CGBitFieldInfo Offset:8 Size:24 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-32-NEXT: <CGBitFieldInfo Offset:0 Size:1 IsSigned:1 StorageSize:8 StorageOffset:4 +// LAYOUT-64-NEXT: <CGBitFieldInfo Offset:0 Size:8 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-64-NEXT: <CGBitFieldInfo Offset:8 Size:24 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-64-NEXT: <CGBitFieldInfo Offset:32 Size:1 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-NEXT: ]> diff --git a/clang/test/CodeGen/arm-varargs.c b/clang/test/CodeGen/arm-varargs.c index f754c7f52e59046e5cf659023be5a58f282b792a..ab4ac46924e605d3d5b6c9d52f7fa9327d645acd 100644 --- a/clang/test/CodeGen/arm-varargs.c +++ b/clang/test/CodeGen/arm-varargs.c @@ -264,5 +264,5 @@ void check_start(int n, ...) { va_list the_list; va_start(the_list, n); // CHECK: [[THE_LIST:%[a-z0-9._]+]] = alloca %struct.__va_list -// CHECK: call void @llvm.va_start(ptr [[THE_LIST]]) +// CHECK: call void @llvm.va_start.p0(ptr [[THE_LIST]]) } diff --git a/clang/test/CodeGen/arm64-be-bitfield.c b/clang/test/CodeGen/arm64-be-bitfield.c index 58c318539298475588b8d1520c6b6f9349267a08..57e20b5b62b9ca93407425781109c691eaa32388 100644 --- a/clang/test/CodeGen/arm64-be-bitfield.c +++ b/clang/test/CodeGen/arm64-be-bitfield.c @@ -1,11 +1,25 @@ -// RUN: %clang_cc1 -triple aarch64_be-linux-gnu -ffreestanding -emit-llvm -O0 -o - %s | FileCheck --check-prefix IR %s +// RUN: %clang_cc1 -triple aarch64_be-linux-gnu -ffreestanding -emit-llvm -O0 -o %t -fdump-record-layouts-simple %s | FileCheck %s --check-prefix=LAYOUT +// RUN: FileCheck %s --check-prefix=IR <%t struct bt3 { signed b2:10; signed b3:10; } b16; // Get the high 32-bits and then shift appropriately for big-endian. signed callee_b0f(struct bt3 bp11) { // IR: callee_b0f(i64 [[ARG:%.*]]) -// IR: store i64 [[ARG]], ptr [[PTR:%.*]], align 8 -// IR: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}}, ptr align 8 [[PTR]], i64 4 +// IR: [[BP11:%.*]] = alloca %struct.bt3, align 4 +// IR: [[COERCE_DIVE:%.*]] = getelementptr inbounds %struct.bt3, ptr [[BP11]], i32 0, i32 0 +// IR: [[COERCE_HIGHBITS:%.*]] = lshr i64 [[ARG]], 32 +// IR: [[COERCE_VAL_II:%.*]] = trunc i64 [[COERCE_HIGHBITS]] to i32 +// IR: store i32 [[COERCE_VAL_II]], ptr [[COERCE_DIVE]], align 4 +// IR: [[BF_LOAD:%.*]] = load i32, ptr [[BP11]], align 4 +// IR: [[BF_ASHR:%.*]] = ashr i32 [[BF_LOAD]], 22 +// IR: ret i32 [[BF_ASHR]] return bp11.b2; } + +// LAYOUT-LABEL: LLVMType:%struct.bt3 = +// LAYOUT-SAME: type { i32 } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:22 Size:10 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:12 Size:10 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: ]> diff --git a/clang/test/CodeGen/atomic.c b/clang/test/CodeGen/atomic.c index af5c056bbfe6e8ad4cb4679a35c70796d5267584..16c29e282ddd9f742a7378670c37173657681499 100644 --- a/clang/test/CodeGen/atomic.c +++ b/clang/test/CodeGen/atomic.c @@ -1,10 +1,14 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-apple-darwin9 | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-apple-darwin9 | FileCheck %s --check-prefixes=CHECK,X86 +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=s390x-linux-gnu | FileCheck %s --check-prefixes=CHECK,SYSTEMZ // CHECK: @[[NONSTATIC_GLOB_POINTER_FROM_INT:.+]] = global ptr null // CHECK: @[[GLOB_POINTER:.+]] = internal global ptr null // CHECK: @[[GLOB_POINTER_FROM_INT:.+]] = internal global ptr null // CHECK: @[[GLOB_INT:.+]] = internal global i32 0 // CHECK: @[[GLOB_FLT:.+]] = internal global float {{[0e\+-\.]+}}, align +// CHECK: @[[GLOB_DBL:.+]] = internal global double {{[0e\+-\.]+}}, align +// X86: @[[GLOB_LONGDBL:.+]] = internal global x86_fp80 {{[0xK]+}}, align +// SYSTEMZ: @[[GLOB_LONGDBL:.+]] = internal global fp128 {{[0xL]+}}, align int atomic(void) { // non-sensical test for sync functions @@ -79,8 +83,10 @@ int atomic(void) { // CHECK: atomicrmw nand ptr %valc, i8 6 seq_cst, align 1 __sync_val_compare_and_swap((void **)0, (void *)0, (void *)0); - // CHECK: [[PAIR:%[a-z0-9_.]+]] = cmpxchg ptr null, i32 0, i32 0 seq_cst seq_cst, align 4 - // CHECK: extractvalue { i32, i1 } [[PAIR]], 0 + // X86: [[PAIR:%[a-z0-9_.]+]] = cmpxchg ptr null, i32 0, i32 0 seq_cst seq_cst, align 4 + // X86-NEXT: extractvalue { i32, i1 } [[PAIR]], 0 + // SYSTEMZ: [[PAIR:%[a-z0-9_.]+]] = cmpxchg ptr null, i64 0, i64 0 seq_cst seq_cst, align 8 + // SYSTEMZ-NEXT: extractvalue { i64, i1 } [[PAIR]], 0 if ( __sync_val_compare_and_swap(&valb, 0, 1)) { // CHECK: [[PAIR:%[a-z0-9_.]+]] = cmpxchg ptr %valb, i8 0, i8 1 seq_cst seq_cst, align 1 @@ -90,13 +96,15 @@ int atomic(void) { } __sync_bool_compare_and_swap((void **)0, (void *)0, (void *)0); - // CHECK: cmpxchg ptr null, i32 0, i32 0 seq_cst seq_cst, align 4 + // X86: cmpxchg ptr null, i32 0, i32 0 seq_cst seq_cst, align 4 + // SYSTEMZ: cmpxchg ptr null, i64 0, i64 0 seq_cst seq_cst, align 8 __sync_lock_release(&val); // CHECK: store atomic i32 0, {{.*}} release, align 4 __sync_lock_release(&ptrval); - // CHECK: store atomic i32 0, {{.*}} release, align 4 + // X86: store atomic i32 0, {{.*}} release, align 4 + // SYSTEMZ: store atomic i64 0, {{.*}} release, align 8 __sync_synchronize (); // CHECK: fence seq_cst @@ -131,19 +139,25 @@ static _Atomic(int *) glob_pointer_from_int = 0; _Atomic(int *) nonstatic_glob_pointer_from_int = 0LL; static _Atomic int glob_int = 0; static _Atomic float glob_flt = 0.0f; +static _Atomic double glob_dbl = 0.0f; +static _Atomic long double glob_longdbl = 0.0f; void force_global_uses(void) { + // X86: %atomic-temp = alloca x86_fp80, align 16 (void)glob_pointer; - // CHECK: %[[LOCAL_INT:.+]] = load atomic i32, ptr @[[GLOB_POINTER]] seq_cst - // CHECK-NEXT: inttoptr i32 %[[LOCAL_INT]] to ptr + // CHECK: load atomic ptr, ptr @[[GLOB_POINTER]] seq_cst (void)glob_pointer_from_int; - // CHECK: %[[LOCAL_INT_2:.+]] = load atomic i32, ptr @[[GLOB_POINTER_FROM_INT]] seq_cst - // CHECK-NEXT: inttoptr i32 %[[LOCAL_INT_2]] to ptr + // CHECK-NEXT: load atomic ptr, ptr @[[GLOB_POINTER_FROM_INT]] seq_cst (void)nonstatic_glob_pointer_from_int; - // CHECK: %[[LOCAL_INT_3:.+]] = load atomic i32, ptr @[[NONSTATIC_GLOB_POINTER_FROM_INT]] seq_cst - // CHECK-NEXT: inttoptr i32 %[[LOCAL_INT_3]] to ptr + // CHECK-NEXT: load atomic ptr, ptr @[[NONSTATIC_GLOB_POINTER_FROM_INT]] seq_cst (void)glob_int; - // CHECK: load atomic i32, ptr @[[GLOB_INT]] seq_cst + // CHECK-NEXT: load atomic i32, ptr @[[GLOB_INT]] seq_cst (void)glob_flt; - // CHECK: load atomic float, ptr @[[GLOB_FLT]] seq_cst + // CHECK-NEXT: load atomic float, ptr @[[GLOB_FLT]] seq_cst + (void)glob_dbl; + // CHECK-NEXT: load atomic double, ptr @[[GLOB_DBL]] seq_cst + (void)glob_longdbl; + // X86: call void @__atomic_load(i32 noundef 16, ptr noundef @glob_longdbl, ptr noundef %atomic-temp + // X86-NEXT: %0 = load x86_fp80, ptr %atomic-temp, align 16 + // SYSTEMZ: load atomic fp128, ptr @[[GLOB_LONGDBL]] seq_cst } diff --git a/clang/test/CodeGen/attr-counted-by-debug-info.c b/clang/test/CodeGen/attr-counted-by-debug-info.c new file mode 100644 index 0000000000000000000000000000000000000000..a6c2b1382b796bffa1dad5f0dae61eef41ec3443 --- /dev/null +++ b/clang/test/CodeGen/attr-counted-by-debug-info.c @@ -0,0 +1,18 @@ +// RUN: %clang -emit-llvm -DCOUNTED_BY -S -g %s -o - | FileCheck %s +// RUN: %clang -emit-llvm -S -g %s -o - | FileCheck %s + +#ifdef COUNTED_BY +#define __counted_by(member) __attribute__((__counted_by__(member))) +#else +#define __counted_by(member) +#endif + +struct { + int num_counters; + long value[] __counted_by(num_counters); +} agent_send_response_port_num; + +// CHECK: !DICompositeType(tag: DW_TAG_array_type, baseType: ![[BT:.*]], elements: ![[ELEMENTS:.*]]) +// CHECK: ![[BT]] = !DIBasicType(name: "long", size: {{.*}}, encoding: DW_ATE_signed) +// CHECK: ![[ELEMENTS]] = !{![[COUNT:.*]]} +// CHECK: ![[COUNT]] = !DISubrange(count: -1) \ No newline at end of file diff --git a/clang/test/CodeGen/attr-counted-by.c b/clang/test/CodeGen/attr-counted-by.c index e5685e39173b0fbbb0db796c8175f2ec549c0911..1fb39f9a3466675402c5bb51a1f04856d18eb79e 100644 --- a/clang/test/CodeGen/attr-counted-by.c +++ b/clang/test/CodeGen/attr-counted-by.c @@ -1314,17 +1314,10 @@ int test14(int idx) { // NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test15( // NO-SANITIZE-WITH-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR4]] { // NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[FOO:%.*]] = alloca [[STRUCT_ANON_8:%.*]], align 4 -// NO-SANITIZE-WITH-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr nonnull [[FOO]]) #[[ATTR12]] -// NO-SANITIZE-WITH-ATTR-NEXT: store i32 1, ptr [[FOO]], align 4 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 4 -// NO-SANITIZE-WITH-ATTR-NEXT: store i32 2, ptr [[TMP0]], align 4 -// NO-SANITIZE-WITH-ATTR-NEXT: [[BLAH:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 8 // NO-SANITIZE-WITH-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 -// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[BLAH]], i64 0, i64 [[IDXPROM]] -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITH-ATTR-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr nonnull [[FOO]]) #[[ATTR12]] -// NO-SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP1]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr getelementptr inbounds ([[STRUCT_ANON_8:%.*]], ptr @__const.test15.foo, i64 1, i32 0), i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITH-ATTR-NEXT: ret i32 [[TMP0]] // // SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test15( // SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR0]] { @@ -1342,17 +1335,10 @@ int test14(int idx) { // NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test15( // NO-SANITIZE-WITHOUT-ATTR-SAME: i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR1]] { // NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[FOO:%.*]] = alloca [[STRUCT_ANON_8:%.*]], align 4 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr nonnull [[FOO]]) #[[ATTR9]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 1, ptr [[FOO]], align 4 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 4 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: store i32 2, ptr [[TMP0]], align 4 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[BLAH:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 8 // NO-SANITIZE-WITHOUT-ATTR-NEXT: [[IDXPROM:%.*]] = sext i32 [[IDX]] to i64 -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr [[BLAH]], i64 0, i64 [[IDXPROM]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr nonnull [[FOO]]) #[[ATTR9]] -// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i32 [[TMP1]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], ptr getelementptr inbounds ([[STRUCT_ANON_8:%.*]], ptr @__const.test15.foo, i64 1, i32 0), i64 0, i64 [[IDXPROM]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4, !tbaa [[TBAA2]] +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i32 [[TMP0]] // int test15(int idx) { struct { diff --git a/clang/test/CodeGen/attr-target-clones-aarch64.c b/clang/test/CodeGen/attr-target-clones-aarch64.c index 276a7b87b7a1b45de70b0a98287215917570d0a9..8c8b951e9118d7a421af644b726011b07895d890 100644 --- a/clang/test/CodeGen/attr-target-clones-aarch64.c +++ b/clang/test/CodeGen/attr-target-clones-aarch64.c @@ -23,16 +23,14 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) - - //. // CHECK: @__aarch64_cpu_features = external dso_local global { i64 } // CHECK: @ftc.ifunc = weak_odr alias i32 (), ptr @ftc // CHECK: @ftc_def.ifunc = weak_odr alias i32 (), ptr @ftc_def // CHECK: @ftc_dup1.ifunc = weak_odr alias i32 (), ptr @ftc_dup1 // CHECK: @ftc_dup2.ifunc = weak_odr alias i32 (), ptr @ftc_dup2 -// CHECK: @ftc_inline1.ifunc = weak_odr alias i32 (), ptr @ftc_inline1 // CHECK: @ftc_inline2.ifunc = weak_odr alias i32 (), ptr @ftc_inline2 +// CHECK: @ftc_inline1.ifunc = weak_odr alias i32 (), ptr @ftc_inline1 // CHECK: @ftc_inline3.ifunc = weak_odr alias i32 (), ptr @ftc_inline3 // CHECK: @ftc = weak_odr ifunc i32 (), ptr @ftc.resolver // CHECK: @ftc_def = weak_odr ifunc i32 (), ptr @ftc_def.resolver @@ -54,12 +52,6 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // CHECK-NEXT: ret i32 0 // // -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc.default( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 0 -// -// // CHECK-LABEL: @ftc.resolver( // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -94,12 +86,6 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // CHECK-NEXT: ret i32 1 // // -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_def.default( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 -// -// // CHECK-LABEL: @ftc_def.resolver( // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -128,12 +114,6 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // CHECK-NEXT: ret i32 2 // // -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_dup1.default( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 -// -// // CHECK-LABEL: @ftc_dup1.resolver( // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -160,12 +140,6 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // CHECK-NEXT: ret i32 3 // // -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_dup2.default( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 3 -// -// // CHECK-LABEL: @ftc_dup2.resolver( // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -177,15 +151,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // CHECK: resolver_return: // CHECK-NEXT: ret ptr @ftc_dup2._McrcMdotprod // CHECK: resolver_else: -// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 256 -// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 256 -// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]] -// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] -// CHECK: resolver_return1: // CHECK-NEXT: ret ptr @ftc_dup2._Mfp -// CHECK: resolver_else2: -// CHECK-NEXT: ret ptr @ftc_dup2.default // // // CHECK: Function Attrs: noinline nounwind optnone @@ -202,6 +168,12 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // // // CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: @ftc_inline2._Mfp16( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// +// CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: @ftc_direct( // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 4 @@ -297,45 +269,63 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_inline1._MrngMsimd( +// CHECK-LABEL: @ftc_inline2._MfcmaMsve2-bitperm( // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 +// CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_inline1._MpredresMrcpc( +// CHECK-LABEL: @ftc.default( // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 +// CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_inline1._Msve2-aesMwfxt( +// CHECK-LABEL: @ftc_def.default( // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_inline1.default( +// CHECK-LABEL: @ftc_dup1.default( // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 +// CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_inline2._Mfp16( +// CHECK-LABEL: @ftc_dup2.default( // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 +// CHECK-NEXT: ret i32 3 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_inline2._MfcmaMsve2-bitperm( +// CHECK-LABEL: @ftc_inline2.default( // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @ftc_inline2.default( +// CHECK-LABEL: @ftc_inline1._MrngMsimd( // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 +// CHECK-NEXT: ret i32 1 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: @ftc_inline1._MpredresMrcpc( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: @ftc_inline1._Msve2-aesMwfxt( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: @ftc_inline1.default( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone @@ -416,16 +406,16 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default")) //. // CHECK: attributes #[[ATTR0:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+lse,+neon" } // CHECK: attributes #[[ATTR1:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2" } -// CHECK: attributes #[[ATTR2:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } -// CHECK: attributes #[[ATTR3:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+sha2" } -// CHECK: attributes #[[ATTR4:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+mte,+neon,+sha2" } -// CHECK: attributes #[[ATTR5:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon" } -// CHECK: attributes #[[ATTR6:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+dotprod,+fp-armv8,+neon" } -// CHECK: attributes #[[ATTR7:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rand" } -// CHECK: attributes #[[ATTR8:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+predres,+rcpc" } -// CHECK: attributes #[[ATTR9:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-aes,+wfxt" } -// CHECK: attributes #[[ATTR10:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" } -// CHECK: attributes #[[ATTR11:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+complxnum,+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-bitperm" } +// CHECK: attributes #[[ATTR2:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+sha2" } +// CHECK: attributes #[[ATTR3:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+mte,+neon,+sha2" } +// CHECK: attributes #[[ATTR4:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon" } +// CHECK: attributes #[[ATTR5:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+dotprod,+fp-armv8,+neon" } +// CHECK: attributes #[[ATTR6:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +// CHECK: attributes #[[ATTR7:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" } +// CHECK: attributes #[[ATTR8:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+complxnum,+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-bitperm" } +// CHECK: attributes #[[ATTR9:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rand" } +// CHECK: attributes #[[ATTR10:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+predres,+rcpc" } +// CHECK: attributes #[[ATTR11:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve,+sve2,+sve2-aes,+wfxt" } // CHECK: attributes #[[ATTR12:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bti" } // CHECK: attributes #[[ATTR13:[0-9]+]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sb,+sve" } //. diff --git a/clang/test/CodeGen/attr-target-version.c b/clang/test/CodeGen/attr-target-version.c index b7112c783da913726d5c8404ebb96d1d3ccdd988..dd4cbbf5a8986084c73f2108bfc1e21029026b44 100644 --- a/clang/test/CodeGen/attr-target-version.c +++ b/clang/test/CodeGen/attr-target-version.c @@ -1,5 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals --include-generated-funcs -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +ls64 -target-feature +fullfp16 -S -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -v9.5a -target-feature -fp-armv8 -S -emit-llvm -o - %s | FileCheck %s // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature -fmv -S -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-NOFMV int __attribute__((target_version("rng+flagm+fp16fml"))) fmv(void) { return 1; } @@ -11,15 +11,15 @@ int __attribute__((target_version("fp+aes"))) fmv(void) { return 6; } int __attribute__((target_version("crc+ls64_v"))) fmv(void) { return 7; } int __attribute__((target_version("bti"))) fmv(void) { return 8; } int __attribute__((target_version("sme2"))) fmv(void) { return 9; } -int __attribute__((target_version("default"))) fmv(void) { return 0; } +int __attribute__((target_version("default"))) fmv(void); int __attribute__((target_version("ls64+simd"))) fmv_one(void) { return 1; } int __attribute__((target_version("dpb"))) fmv_one(void) { return 2; } -int __attribute__((target_version("default"))) fmv_one(void) { return 0; } +int __attribute__((target_version("default"))) fmv_one(void); int __attribute__((target_version("fp"))) fmv_two(void) { return 1; } int __attribute__((target_version("simd"))) fmv_two(void) { return 2; } int __attribute__((target_version("dgh"))) fmv_two(void) { return 3; } int __attribute__((target_version("fp16+simd"))) fmv_two(void) { return 4; } -int __attribute__((target_version("default"))) fmv_two(void) { return 0; } +int __attribute__((target_version("default"))) fmv_two(void); int foo() { return fmv()+fmv_one()+fmv_two(); } @@ -84,9 +84,56 @@ int hoo(void) { return fp1() + fp2(); } +// This should generate one target version but no resolver. +__attribute__((target_version("default"))) int unused_with_forward_default_decl(void); +__attribute__((target_version("mops"))) int unused_with_forward_default_decl(void) { return 0; } +// This should also generate one target version but no resolver. +extern int unused_with_implicit_extern_forward_default_decl(void); +__attribute__((target_version("dotprod"))) +int unused_with_implicit_extern_forward_default_decl(void) { return 0; } +// This should also generate one target version but no resolver. +__attribute__((target_version("aes"))) int unused_with_default_decl(void) { return 0; } +__attribute__((target_version("default"))) int unused_with_default_decl(void); +// This should generate two target versions and the resolver. +__attribute__((target_version("sve"))) int unused_with_default_def(void) { return 0; } +__attribute__((target_version("default"))) int unused_with_default_def(void) { return 1; } + +// This should also generate two target versions and the resolver. +__attribute__((target_version("fp16"))) int unused_with_implicit_default_def(void) { return 0; } +int unused_with_implicit_default_def(void) { return 1; } + +// This should also generate two target versions and the resolver. +int unused_with_implicit_forward_default_def(void) { return 0; } +__attribute__((target_version("lse"))) int unused_with_implicit_forward_default_def(void) { return 1; } + +// This should generate a target version despite the default not being declared. +__attribute__((target_version("rdm"))) int unused_without_default(void) { return 0; } + +// These shouldn't generate anything. +int unused_version_declarations(void); +__attribute__((target_version("jscvt"))) int unused_version_declarations(void); +__attribute__((target_version("rdma"))) int unused_version_declarations(void); + +// These should generate the default (mangled) version and the resolver. +int default_def_with_version_decls(void) { return 0; } +__attribute__((target_version("jscvt"))) int default_def_with_version_decls(void); +__attribute__((target_version("rdma"))) int default_def_with_version_decls(void); + +// The following is guarded because in NOFMV we get errors for calling undeclared functions. +#ifdef __HAVE_FUNCTION_MULTI_VERSIONING +// This should generate a default declaration, two target versions and the resolver. +__attribute__((target_version("jscvt"))) int used_def_without_default_decl(void) { return 1; } +__attribute__((target_version("rdma"))) int used_def_without_default_decl(void) { return 2; } + +// This should generate a default declaration and the resolver. +__attribute__((target_version("jscvt"))) int used_decl_without_default_decl(void); +__attribute__((target_version("rdma"))) int used_decl_without_default_decl(void); + +int caller(void) { return used_def_without_default_decl() + used_decl_without_default_decl(); } +#endif //. // CHECK: @__aarch64_cpu_features = external dso_local global { i64 } @@ -94,16 +141,28 @@ int hoo(void) { // CHECK: @fmv_one.ifunc = weak_odr alias i32 (), ptr @fmv_one // CHECK: @fmv_two.ifunc = weak_odr alias i32 (), ptr @fmv_two // CHECK: @fmv_e.ifunc = weak_odr alias i32 (), ptr @fmv_e +// CHECK: @fmv_d.ifunc = internal alias i32 (), ptr @fmv_d // CHECK: @fmv_c.ifunc = weak_odr alias void (), ptr @fmv_c // CHECK: @fmv_inline.ifunc = weak_odr alias i32 (), ptr @fmv_inline -// CHECK: @fmv_d.ifunc = internal alias i32 (), ptr @fmv_d +// CHECK: @unused_with_default_def.ifunc = weak_odr alias i32 (), ptr @unused_with_default_def +// CHECK: @unused_with_implicit_default_def.ifunc = weak_odr alias i32 (), ptr @unused_with_implicit_default_def +// CHECK: @unused_with_implicit_forward_default_def.ifunc = weak_odr alias i32 (), ptr @unused_with_implicit_forward_default_def +// CHECK: @default_def_with_version_decls.ifunc = weak_odr alias i32 (), ptr @default_def_with_version_decls +// CHECK: @used_def_without_default_decl.ifunc = weak_odr alias i32 (), ptr @used_def_without_default_decl +// CHECK: @used_decl_without_default_decl.ifunc = weak_odr alias i32 (), ptr @used_decl_without_default_decl // CHECK: @fmv = weak_odr ifunc i32 (), ptr @fmv.resolver // CHECK: @fmv_one = weak_odr ifunc i32 (), ptr @fmv_one.resolver // CHECK: @fmv_two = weak_odr ifunc i32 (), ptr @fmv_two.resolver -// CHECK: @fmv_e = weak_odr ifunc i32 (), ptr @fmv_e.resolver -// CHECK: @fmv_c = weak_odr ifunc void (), ptr @fmv_c.resolver // CHECK: @fmv_inline = weak_odr ifunc i32 (), ptr @fmv_inline.resolver +// CHECK: @fmv_e = weak_odr ifunc i32 (), ptr @fmv_e.resolver // CHECK: @fmv_d = internal ifunc i32 (), ptr @fmv_d.resolver +// CHECK: @fmv_c = weak_odr ifunc void (), ptr @fmv_c.resolver +// CHECK: @used_def_without_default_decl = weak_odr ifunc i32 (), ptr @used_def_without_default_decl.resolver +// CHECK: @used_decl_without_default_decl = weak_odr ifunc i32 (), ptr @used_decl_without_default_decl.resolver +// CHECK: @unused_with_default_def = weak_odr ifunc i32 (), ptr @unused_with_default_def.resolver +// CHECK: @unused_with_implicit_default_def = weak_odr ifunc i32 (), ptr @unused_with_implicit_default_def.resolver +// CHECK: @unused_with_implicit_forward_default_def = weak_odr ifunc i32 (), ptr @unused_with_implicit_forward_default_def.resolver +// CHECK: @default_def_with_version_decls = weak_odr ifunc i32 (), ptr @default_def_with_version_decls.resolver //. // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv._MflagmMfp16fmlMrng @@ -113,22 +172,106 @@ int hoo(void) { // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_one._Mls64Msimd +// CHECK-LABEL: define {{[^@]+}}@fmv._Mflagm2Msme-i16i64 // CHECK-SAME: () #[[ATTR1:[0-9]+]] { // CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv._MlseMsha2 +// CHECK-SAME: () #[[ATTR2:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 3 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv._MdotprodMls64_accdata +// CHECK-SAME: () #[[ATTR3:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 4 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv._Mfp16fmlMmemtag +// CHECK-SAME: () #[[ATTR4:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 5 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv._MaesMfp +// CHECK-SAME: () #[[ATTR5:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 6 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv._McrcMls64_v +// CHECK-SAME: () #[[ATTR6:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 7 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv._Mbti +// CHECK-SAME: () #[[ATTR7:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 8 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv._Msme2 +// CHECK-SAME: () #[[ATTR8:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 9 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv_one._Mls64Msimd +// CHECK-SAME: () #[[ATTR5]] { +// CHECK-NEXT: entry: // CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv_one._Mdpb +// CHECK-SAME: () #[[ATTR10:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// +// CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_two._Mfp -// CHECK-SAME: () #[[ATTR1]] { +// CHECK-SAME: () #[[ATTR5]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv_two._Msimd +// CHECK-SAME: () #[[ATTR5]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv_two._Mdgh +// CHECK-SAME: () #[[ATTR11:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 3 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv_two._Mfp16Msimd +// CHECK-SAME: () #[[ATTR12:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 4 +// +// +// CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@foo -// CHECK-SAME: () #[[ATTR2:[0-9]+]] { +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv() // CHECK-NEXT: [[CALL1:%.*]] = call i32 @fmv_one() @@ -158,16 +301,16 @@ int hoo(void) { // CHECK-NEXT: ret ptr @fmv._Mflagm2Msme-i16i64 // CHECK: resolver_else2: // CHECK-NEXT: [[TMP8:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP9:%.*]] = and i64 [[TMP8]], 16 -// CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 16 +// CHECK-NEXT: [[TMP9:%.*]] = and i64 [[TMP8]], 9007199254741008 +// CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 9007199254741008 // CHECK-NEXT: [[TMP11:%.*]] = and i1 true, [[TMP10]] // CHECK-NEXT: br i1 [[TMP11]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]] // CHECK: resolver_return3: // CHECK-NEXT: ret ptr @fmv._MdotprodMls64_accdata // CHECK: resolver_else4: // CHECK-NEXT: [[TMP12:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP13:%.*]] = and i64 [[TMP12]], 1024 -// CHECK-NEXT: [[TMP14:%.*]] = icmp eq i64 [[TMP13]], 1024 +// CHECK-NEXT: [[TMP13:%.*]] = and i64 [[TMP12]], 4503599627371520 +// CHECK-NEXT: [[TMP14:%.*]] = icmp eq i64 [[TMP13]], 4503599627371520 // CHECK-NEXT: [[TMP15:%.*]] = and i1 true, [[TMP14]] // CHECK-NEXT: br i1 [[TMP15]], label [[RESOLVER_RETURN5:%.*]], label [[RESOLVER_ELSE6:%.*]] // CHECK: resolver_return5: @@ -182,8 +325,8 @@ int hoo(void) { // CHECK-NEXT: ret ptr @fmv._Mfp16fmlMmemtag // CHECK: resolver_else8: // CHECK-NEXT: [[TMP20:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP21:%.*]] = and i64 [[TMP20]], 16384 -// CHECK-NEXT: [[TMP22:%.*]] = icmp eq i64 [[TMP21]], 16384 +// CHECK-NEXT: [[TMP21:%.*]] = and i64 [[TMP20]], 16640 +// CHECK-NEXT: [[TMP22:%.*]] = icmp eq i64 [[TMP21]], 16640 // CHECK-NEXT: [[TMP23:%.*]] = and i1 true, [[TMP22]] // CHECK-NEXT: br i1 [[TMP23]], label [[RESOLVER_RETURN9:%.*]], label [[RESOLVER_ELSE10:%.*]] // CHECK: resolver_return9: @@ -218,43 +361,109 @@ int hoo(void) { // // CHECK-LABEL: define {{[^@]+}}@fmv_one.resolver() comdat { // CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 2251799813685760 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 2251799813685760 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: // CHECK-NEXT: ret ptr @fmv_one._Mls64Msimd +// CHECK: resolver_else: +// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 262144 +// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 262144 +// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]] +// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] +// CHECK: resolver_return1: +// CHECK-NEXT: ret ptr @fmv_one._Mdpb +// CHECK: resolver_else2: +// CHECK-NEXT: ret ptr @fmv_one.default // // // CHECK-LABEL: define {{[^@]+}}@fmv_two.resolver() comdat { // CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 66048 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 66048 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: // CHECK-NEXT: ret ptr @fmv_two._Mfp16Msimd +// CHECK: resolver_else: +// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 33554432 +// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 33554432 +// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]] +// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] +// CHECK: resolver_return1: +// CHECK-NEXT: ret ptr @fmv_two._Mdgh +// CHECK: resolver_else2: +// CHECK-NEXT: [[TMP8:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP9:%.*]] = and i64 [[TMP8]], 512 +// CHECK-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 512 +// CHECK-NEXT: [[TMP11:%.*]] = and i1 true, [[TMP10]] +// CHECK-NEXT: br i1 [[TMP11]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]] +// CHECK: resolver_return3: +// CHECK-NEXT: ret ptr @fmv_two._Msimd +// CHECK: resolver_else4: +// CHECK-NEXT: [[TMP12:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP13:%.*]] = and i64 [[TMP12]], 256 +// CHECK-NEXT: [[TMP14:%.*]] = icmp eq i64 [[TMP13]], 256 +// CHECK-NEXT: [[TMP15:%.*]] = and i1 true, [[TMP14]] +// CHECK-NEXT: br i1 [[TMP15]], label [[RESOLVER_RETURN5:%.*]], label [[RESOLVER_ELSE6:%.*]] +// CHECK: resolver_return5: +// CHECK-NEXT: ret ptr @fmv_two._Mfp +// CHECK: resolver_else6: +// CHECK-NEXT: ret ptr @fmv_two.default // // -// CHECK-LABEL: define {{[^@]+}}@fmv_e.resolver() comdat { -// CHECK-NEXT: resolver_entry: -// CHECK-NEXT: ret ptr @fmv_e._Mls64 +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv_e.default +// CHECK-SAME: () #[[ATTR11]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 20 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv_d._Msb +// CHECK-SAME: () #[[ATTR13:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 0 +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv_d.default +// CHECK-SAME: () #[[ATTR11]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_default -// CHECK-SAME: () #[[ATTR2]] { +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 111 // // -// CHECK-LABEL: define {{[^@]+}}@fmv_c.resolver() comdat { -// CHECK-NEXT: resolver_entry: -// CHECK-NEXT: call void @__init_cpu_features_resolver() -// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 281474976710656 -// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 281474976710656 -// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] -// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] -// CHECK: resolver_return: -// CHECK-NEXT: ret ptr @fmv_c._Mssbs -// CHECK: resolver_else: -// CHECK-NEXT: ret ptr @fmv_c.default +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv_c._Mssbs +// CHECK-SAME: () #[[ATTR11]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void +// +// +// CHECK: Function Attrs: noinline nounwind optnone +// CHECK-LABEL: define {{[^@]+}}@fmv_c.default +// CHECK-SAME: () #[[ATTR11]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: ret void // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@goo -// CHECK-SAME: () #[[ATTR2]] { +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[CALL:%.*]] = call i32 @fmv_inline() // CHECK-NEXT: [[CALL1:%.*]] = call i32 @fmv_e() @@ -268,8 +477,8 @@ int hoo(void) { // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() // CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 4398048608320 -// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 4398048608320 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 4398048673856 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 4398048673856 // CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] // CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] // CHECK: resolver_return: @@ -364,8 +573,8 @@ int hoo(void) { // CHECK-NEXT: ret ptr @fmv_inline._Mdpb2Mjscvt // CHECK: resolver_else22: // CHECK-NEXT: [[TMP48:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP49:%.*]] = and i64 [[TMP48]], 8 -// CHECK-NEXT: [[TMP50:%.*]] = icmp eq i64 [[TMP49]], 8 +// CHECK-NEXT: [[TMP49:%.*]] = and i64 [[TMP48]], 520 +// CHECK-NEXT: [[TMP50:%.*]] = icmp eq i64 [[TMP49]], 520 // CHECK-NEXT: [[TMP51:%.*]] = and i1 true, [[TMP50]] // CHECK-NEXT: br i1 [[TMP51]], label [[RESOLVER_RETURN23:%.*]], label [[RESOLVER_ELSE24:%.*]] // CHECK: resolver_return23: @@ -388,8 +597,8 @@ int hoo(void) { // CHECK-NEXT: ret ptr @fmv_inline._MlseMrdm // CHECK: resolver_else28: // CHECK-NEXT: [[TMP60:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 -// CHECK-NEXT: [[TMP61:%.*]] = and i64 [[TMP60]], 32 -// CHECK-NEXT: [[TMP62:%.*]] = icmp eq i64 [[TMP61]], 32 +// CHECK-NEXT: [[TMP61:%.*]] = and i64 [[TMP60]], 288 +// CHECK-NEXT: [[TMP62:%.*]] = icmp eq i64 [[TMP61]], 288 // CHECK-NEXT: [[TMP63:%.*]] = and i1 true, [[TMP62]] // CHECK-NEXT: br i1 [[TMP63]], label [[RESOLVER_RETURN29:%.*]], label [[RESOLVER_ELSE30:%.*]] // CHECK: resolver_return29: @@ -398,6 +607,20 @@ int hoo(void) { // CHECK-NEXT: ret ptr @fmv_inline.default // // +// CHECK-LABEL: define {{[^@]+}}@fmv_e.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 2251799813685248 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 2251799813685248 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @fmv_e._Mls64 +// CHECK: resolver_else: +// CHECK-NEXT: ret ptr @fmv_e.default +// +// // CHECK-LABEL: define {{[^@]+}}@fmv_d.resolver() { // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -412,9 +635,23 @@ int hoo(void) { // CHECK-NEXT: ret ptr @fmv_d.default // // +// CHECK-LABEL: define {{[^@]+}}@fmv_c.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 281474976710656 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 281474976710656 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @fmv_c._Mssbs +// CHECK: resolver_else: +// CHECK-NEXT: ret ptr @fmv_c.default +// +// // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@recur -// CHECK-SAME: () #[[ATTR2]] { +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: call void @reca() // CHECK-NEXT: ret void @@ -422,7 +659,7 @@ int hoo(void) { // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@main -// CHECK-SAME: () #[[ATTR2]] { +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 // CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4 @@ -433,7 +670,7 @@ int hoo(void) { // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@hoo -// CHECK-SAME: () #[[ATTR2]] { +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: [[FP1:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[FP2:%.*]] = alloca ptr, align 8 @@ -449,288 +686,336 @@ int hoo(void) { // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv._Mflagm2Msme-i16i64 -// CHECK-SAME: () #[[ATTR4:[0-9]+]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 -// -// -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv._MlseMsha2 -// CHECK-SAME: () #[[ATTR5:[0-9]+]] { +// CHECK-LABEL: define {{[^@]+}}@unused_with_forward_default_decl._Mmops +// CHECK-SAME: () #[[ATTR14:[0-9]+]] { // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 3 +// CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv._MdotprodMls64_accdata -// CHECK-SAME: () #[[ATTR6:[0-9]+]] { +// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_extern_forward_default_decl._Mdotprod +// CHECK-SAME: () #[[ATTR15:[0-9]+]] { // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 4 +// CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv._Mfp16fmlMmemtag -// CHECK-SAME: () #[[ATTR7:[0-9]+]] { +// CHECK-LABEL: define {{[^@]+}}@unused_with_default_decl._Maes +// CHECK-SAME: () #[[ATTR5]] { // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 5 +// CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv._MaesMfp -// CHECK-SAME: () #[[ATTR1]] { +// CHECK-LABEL: define {{[^@]+}}@unused_with_default_def._Msve +// CHECK-SAME: () #[[ATTR16:[0-9]+]] { // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 6 +// CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv._McrcMls64_v -// CHECK-SAME: () #[[ATTR8:[0-9]+]] { +// CHECK-LABEL: define {{[^@]+}}@unused_with_default_def.default +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 7 +// CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv._Mbti -// CHECK-SAME: () #[[ATTR9:[0-9]+]] { +// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_default_def._Mfp16 +// CHECK-SAME: () #[[ATTR12]] { // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 8 +// CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv._Msme2 -// CHECK-SAME: () #[[ATTR10:[0-9]+]] { +// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_default_def.default +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 9 +// CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv.default -// CHECK-SAME: () #[[ATTR2]] { +// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_forward_default_def.default +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_one._Mdpb -// CHECK-SAME: () #[[ATTR11:[0-9]+]] { +// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_forward_default_def._Mlse +// CHECK-SAME: () #[[ATTR17:[0-9]+]] { // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 +// CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_one.default -// CHECK-SAME: () #[[ATTR2]] { +// CHECK-LABEL: define {{[^@]+}}@unused_without_default._Mrdm +// CHECK-SAME: () #[[ATTR18:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_two._Msimd -// CHECK-SAME: () #[[ATTR1]] { +// CHECK-LABEL: define {{[^@]+}}@default_def_with_version_decls.default +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 -// -// -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_two._Mdgh -// CHECK-SAME: () #[[ATTR2]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 3 +// CHECK-NEXT: ret i32 0 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_two._Mfp16Msimd -// CHECK-SAME: () #[[ATTR1]] { +// CHECK-LABEL: define {{[^@]+}}@used_def_without_default_decl._Mjscvt +// CHECK-SAME: () #[[ATTR21:[0-9]+]] { // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 4 +// CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_two.default -// CHECK-SAME: () #[[ATTR2]] { +// CHECK-LABEL: define {{[^@]+}}@used_def_without_default_decl._Mrdm +// CHECK-SAME: () #[[ATTR18]] { // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 0 +// CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_e.default -// CHECK-SAME: () #[[ATTR2]] { +// CHECK-LABEL: define {{[^@]+}}@caller +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 20 +// CHECK-NEXT: [[CALL:%.*]] = call i32 @used_def_without_default_decl() +// CHECK-NEXT: [[CALL1:%.*]] = call i32 @used_decl_without_default_decl() +// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]] +// CHECK-NEXT: ret i32 [[ADD]] // // -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_c.default -// CHECK-SAME: () #[[ATTR2]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret void +// CHECK-LABEL: define {{[^@]+}}@used_def_without_default_decl.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1048576 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1048576 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @used_def_without_default_decl._Mjscvt +// CHECK: resolver_else: +// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 64 +// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 64 +// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]] +// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] +// CHECK: resolver_return1: +// CHECK-NEXT: ret ptr @used_def_without_default_decl._Mrdm +// CHECK: resolver_else2: +// CHECK-NEXT: ret ptr @used_def_without_default_decl.default // // -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_c._Mssbs -// CHECK-SAME: () #[[ATTR2]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret void +// CHECK-LABEL: define {{[^@]+}}@used_decl_without_default_decl.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1048576 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1048576 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @used_decl_without_default_decl._Mjscvt +// CHECK: resolver_else: +// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 64 +// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 64 +// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]] +// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] +// CHECK: resolver_return1: +// CHECK-NEXT: ret ptr @used_decl_without_default_decl._Mrdm +// CHECK: resolver_else2: +// CHECK-NEXT: ret ptr @used_decl_without_default_decl.default // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mf64mmMpmullMsha1 -// CHECK-SAME: () #[[ATTR12:[0-9]+]] { +// CHECK-SAME: () #[[ATTR22:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 1 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MfcmaMfp16MrdmMsme -// CHECK-SAME: () #[[ATTR13:[0-9]+]] { +// CHECK-SAME: () #[[ATTR23:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 2 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mf32mmMi8mmMsha3 -// CHECK-SAME: () #[[ATTR14:[0-9]+]] { +// CHECK-SAME: () #[[ATTR24:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 12 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MditMsve-ebf16 -// CHECK-SAME: () #[[ATTR15:[0-9]+]] { +// CHECK-SAME: () #[[ATTR25:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 8 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MdpbMrcpc2 -// CHECK-SAME: () #[[ATTR16:[0-9]+]] { +// CHECK-SAME: () #[[ATTR26:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 6 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mdpb2Mjscvt -// CHECK-SAME: () #[[ATTR17:[0-9]+]] { +// CHECK-SAME: () #[[ATTR27:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 7 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MfrinttsMrcpc -// CHECK-SAME: () #[[ATTR18:[0-9]+]] { +// CHECK-SAME: () #[[ATTR28:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 3 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MsveMsve-bf16 -// CHECK-SAME: () #[[ATTR19:[0-9]+]] { +// CHECK-SAME: () #[[ATTR29:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 4 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Msve2-aesMsve2-sha3 -// CHECK-SAME: () #[[ATTR20:[0-9]+]] { +// CHECK-SAME: () #[[ATTR30:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 5 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Msve2Msve2-bitpermMsve2-pmull128 -// CHECK-SAME: () #[[ATTR21:[0-9]+]] { +// CHECK-SAME: () #[[ATTR31:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 9 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mmemtag2Msve2-sm4 -// CHECK-SAME: () #[[ATTR22:[0-9]+]] { +// CHECK-SAME: () #[[ATTR32:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 10 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mmemtag3MmopsMrcpc3 -// CHECK-SAME: () #[[ATTR23:[0-9]+]] { +// CHECK-SAME: () #[[ATTR33:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 11 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MaesMdotprod -// CHECK-SAME: () #[[ATTR6]] { +// CHECK-SAME: () #[[ATTR15]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 13 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mfp16fmlMsimd -// CHECK-SAME: () #[[ATTR7]] { +// CHECK-SAME: () #[[ATTR4]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 14 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MfpMsm4 -// CHECK-SAME: () #[[ATTR24:[0-9]+]] { +// CHECK-SAME: () #[[ATTR34:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 15 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline._MlseMrdm -// CHECK-SAME: () #[[ATTR25:[0-9]+]] { +// CHECK-SAME: () #[[ATTR35:[0-9]+]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 16 // // // CHECK: Function Attrs: noinline nounwind optnone // CHECK-LABEL: define {{[^@]+}}@fmv_inline.default -// CHECK-SAME: () #[[ATTR2]] { +// CHECK-SAME: () #[[ATTR11]] { // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 3 // // -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_d._Msb -// CHECK-SAME: () #[[ATTR26:[0-9]+]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 0 -// -// -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: define {{[^@]+}}@fmv_d.default -// CHECK-SAME: () #[[ATTR2]] { -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 1 +// CHECK-LABEL: define {{[^@]+}}@unused_with_default_def.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1073741824 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1073741824 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @unused_with_default_def._Msve +// CHECK: resolver_else: +// CHECK-NEXT: ret ptr @unused_with_default_def.default // // -// CHECK-NOFMV: Function Attrs: noinline nounwind optnone -// CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv -// CHECK-NOFMV-SAME: () #[[ATTR0:[0-9]+]] { -// CHECK-NOFMV-NEXT: entry: -// CHECK-NOFMV-NEXT: ret i32 0 +// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_default_def.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 65536 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 65536 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @unused_with_implicit_default_def._Mfp16 +// CHECK: resolver_else: +// CHECK-NEXT: ret ptr @unused_with_implicit_default_def.default // // -// CHECK-NOFMV: Function Attrs: noinline nounwind optnone -// CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv_one -// CHECK-NOFMV-SAME: () #[[ATTR0]] { -// CHECK-NOFMV-NEXT: entry: -// CHECK-NOFMV-NEXT: ret i32 0 +// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_forward_default_def.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 128 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 128 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @unused_with_implicit_forward_default_def._Mlse +// CHECK: resolver_else: +// CHECK-NEXT: ret ptr @unused_with_implicit_forward_default_def.default // // -// CHECK-NOFMV: Function Attrs: noinline nounwind optnone -// CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv_two -// CHECK-NOFMV-SAME: () #[[ATTR0]] { -// CHECK-NOFMV-NEXT: entry: -// CHECK-NOFMV-NEXT: ret i32 0 +// CHECK-LABEL: define {{[^@]+}}@default_def_with_version_decls.resolver() comdat { +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1048576 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1048576 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @default_def_with_version_decls._Mjscvt +// CHECK: resolver_else: +// CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 64 +// CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 64 +// CHECK-NEXT: [[TMP7:%.*]] = and i1 true, [[TMP6]] +// CHECK-NEXT: br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]] +// CHECK: resolver_return1: +// CHECK-NEXT: ret ptr @default_def_with_version_decls._Mrdm +// CHECK: resolver_else2: +// CHECK-NEXT: ret ptr @default_def_with_version_decls.default // // // CHECK-NOFMV: Function Attrs: noinline nounwind optnone // CHECK-NOFMV-LABEL: define {{[^@]+}}@foo -// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-SAME: () #[[ATTR0:[0-9]+]] { // CHECK-NOFMV-NEXT: entry: // CHECK-NOFMV-NEXT: [[CALL:%.*]] = call i32 @fmv() // CHECK-NOFMV-NEXT: [[CALL1:%.*]] = call i32 @fmv_one() @@ -815,34 +1100,71 @@ int hoo(void) { // CHECK-NOFMV-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]] // CHECK-NOFMV-NEXT: ret i32 [[ADD]] // +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@unused_with_default_def +// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: ret i32 1 +// +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@unused_with_implicit_default_def +// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: ret i32 1 +// +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@unused_with_implicit_forward_default_def +// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: ret i32 0 +// +// +// CHECK-NOFMV: Function Attrs: noinline nounwind optnone +// CHECK-NOFMV-LABEL: define {{[^@]+}}@default_def_with_version_decls +// CHECK-NOFMV-SAME: () #[[ATTR0]] { +// CHECK-NOFMV-NEXT: entry: +// CHECK-NOFMV-NEXT: ret i32 0 +// //. -// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+flagm,+fp-armv8,+fp16fml,+fullfp16,+ls64,+neon,+rand" } -// CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+neon" } -// CHECK: attributes #[[ATTR2]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64" } -// CHECK: attributes #[[ATTR3:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64" } -// CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+altnzcv,+bf16,+flagm,+fullfp16,+ls64,+sme,+sme-i16i64" } -// CHECK: attributes #[[ATTR5]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+lse,+neon,+sha2" } -// CHECK: attributes #[[ATTR6]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+fullfp16,+ls64,+neon" } -// CHECK: attributes #[[ATTR7]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fp16fml,+fullfp16,+ls64,+neon" } -// CHECK: attributes #[[ATTR8]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,+fullfp16,+ls64" } -// CHECK: attributes #[[ATTR9]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bti,+fullfp16,+ls64" } -// CHECK: attributes #[[ATTR10]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fullfp16,+ls64,+sme,+sme2" } -// CHECK: attributes #[[ATTR11]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp,+fullfp16,+ls64" } -// CHECK: attributes #[[ATTR12]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+aes,+f64mm,+fp-armv8,+fullfp16,+ls64,+neon,+sve" } -// CHECK: attributes #[[ATTR13]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+complxnum,+fp-armv8,+fullfp16,+ls64,+neon,+rdm,+sme" } -// CHECK: attributes #[[ATTR14]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+f32mm,+fp-armv8,+fullfp16,+i8mm,+ls64,+neon,+sha2,+sha3,+sve" } -// CHECK: attributes #[[ATTR15]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+dit,+fp-armv8,+fullfp16,+ls64,+neon,+sve" } -// CHECK: attributes #[[ATTR16]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp,+fullfp16,+ls64,+rcpc" } -// CHECK: attributes #[[ATTR17]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccdp,+ccpp,+fp-armv8,+fullfp16,+jsconv,+ls64,+neon" } -// CHECK: attributes #[[ATTR18]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fptoint,+fullfp16,+ls64,+rcpc" } -// CHECK: attributes #[[ATTR19]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fp-armv8,+fullfp16,+ls64,+neon,+sve" } -// CHECK: attributes #[[ATTR20]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+neon,+sve,+sve2,+sve2-aes,+sve2-sha3" } -// CHECK: attributes #[[ATTR21]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+neon,+sve,+sve2,+sve2-aes,+sve2-bitperm" } -// CHECK: attributes #[[ATTR22]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+mte,+neon,+sve,+sve2,+sve2-sm4" } -// CHECK: attributes #[[ATTR23]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64,+mops,+mte,+rcpc,+rcpc3" } -// CHECK: attributes #[[ATTR24]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+neon,+sm4" } -// CHECK: attributes #[[ATTR25]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+lse,+neon,+rdm" } -// CHECK: attributes #[[ATTR26]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64,+sb" } +// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+flagm,+fp16fml,+fullfp16,+neon,+rand,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+altnzcv,+bf16,+flagm,+sme,+sme-i16i64,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR2]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,+neon,+sha2,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR3]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+ls64,+neon,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp16fml,+fullfp16,+neon,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR5]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR6]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR7]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bti,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR8]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme,+sme2,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR9:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR10]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR11]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR12]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR13]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+sb,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR14]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR15]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+neon,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR16]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR17]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR18]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,+rdm,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR19:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+jsconv,+neon,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR20:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,+rdm,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR21]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+jsconv,+neon,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR22]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+aes,+f64mm,+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR23]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+complxnum,+fullfp16,+neon,+rdm,+sme,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR24]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+f32mm,+fullfp16,+i8mm,+neon,+sha2,+sha3,+sve,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR25]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+dit,+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR26]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp,+rcpc,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR27]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccdp,+ccpp,+jsconv,+neon,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR28]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fptoint,+rcpc,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR29]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fullfp16,+neon,+sve,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR30]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sve,+sve2,+sve2-aes,+sve2-sha3,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR31]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+neon,+sve,+sve2,+sve2-aes,+sve2-bitperm,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR32]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+mte,+neon,+sve,+sve2,+sve2-sm4,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR33]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops,+mte,+rcpc,+rcpc3,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR34]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon,+sm4,-fp-armv8,-v9.5a" } +// CHECK: attributes #[[ATTR35]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,+neon,+rdm,-fp-armv8,-v9.5a" } //. // CHECK-NOFMV: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" } // CHECK-NOFMV: attributes #[[ATTR1:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-fmv" } diff --git a/clang/test/CodeGen/bitfield-2.c b/clang/test/CodeGen/bitfield-2.c index 3e0b30c7a17d8092140f75bac3dcbf1cc181a99c..8688ba6390ddbee311ec840843780df7a383134b 100644 --- a/clang/test/CodeGen/bitfield-2.c +++ b/clang/test/CodeGen/bitfield-2.c @@ -271,11 +271,11 @@ _Bool test_6(void) { // CHECK-RECORD: *** Dumping IRgen Record Layout // CHECK-RECORD: Record: RecordDecl{{.*}}s7 // CHECK-RECORD: Layout: <CGRecordLayout -// CHECK-RECORD: LLVMType:%struct.s7 = type { i32, i32, i32, i8, i32, [12 x i8] } +// CHECK-RECORD: LLVMType:%struct.s7 = type <{ i32, i32, i32, i64, [12 x i8] }> // CHECK-RECORD: IsZeroInitializable:1 // CHECK-RECORD: BitFields:[ -// CHECK-RECORD: <CGBitFieldInfo Offset:0 Size:5 IsSigned:1 StorageSize:8 StorageOffset:12 -// CHECK-RECORD: <CGBitFieldInfo Offset:0 Size:29 IsSigned:1 StorageSize:32 StorageOffset:16 +// CHECK-RECORD: <CGBitFieldInfo Offset:0 Size:5 IsSigned:1 StorageSize:64 StorageOffset:12 +// CHECK-RECORD: <CGBitFieldInfo Offset:32 Size:29 IsSigned:1 StorageSize:64 StorageOffset:12 struct __attribute__((aligned(16))) s7 { int a, b, c; diff --git a/clang/test/CodeGen/bitfield-access-pad.c b/clang/test/CodeGen/bitfield-access-pad.c new file mode 100644 index 0000000000000000000000000000000000000000..edda7b7798d057bf78347de521fc7338e44ae25a --- /dev/null +++ b/clang/test/CodeGen/bitfield-access-pad.c @@ -0,0 +1,396 @@ +// Tests for bitfield access with zero-length bitfield padding + +// Configs that have cheap unaligned access +// Little Endian +// RUN: %clang_cc1 -triple=aarch64-apple-darwin %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-T %s +// RUN: %clang_cc1 -triple=aarch64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-T %s +// RUN: %clang_cc1 -triple=arm-apple-darwin %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-DWN32 %s +// RUN: %clang_cc1 -triple=arm-none-eabi %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-T %s +// RUN: %clang_cc1 -triple=i686-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-T %s +// RUN: %clang_cc1 -triple=x86_64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-T %s + +// Big Endian +// RUN: %clang_cc1 -triple=powerpc-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-T %s +// RUN: %clang_cc1 -triple=powerpc64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-T %s + +// Configs that have expensive unaligned access +// Little Endian +// RUN: %clang_cc1 -triple=hexagon-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-T %s +// RUN: %clang_cc1 -triple=le64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-T %s + +// Big endian +// RUN: %clang_cc1 -triple=m68k-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-T %s +// RUN: %clang_cc1 -triple=mips-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-T %s + +// And now a few with -fno-bitfield-type-align. Precisely how this behaves is +// ABI-dependent. +// Cheap unaligned +// RUN: %clang_cc1 -triple=aarch64-apple-darwin -fno-bitfield-type-align %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-NT %s +// RUN: %clang_cc1 -triple=aarch64-linux-gnu -fno-bitfield-type-align %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-ARM64-T %s +// RUN: %clang_cc1 -triple=arm-apple-darwin -fno-bitfield-type-align %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-DWN32 %s +// RUN: %clang_cc1 -triple=i686-linux-gnu -fno-bitfield-type-align %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-NT %s +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -fno-bitfield-type-align %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-NT %s +// RUN: %clang_cc1 -triple=powerpc-linux-gnu -fno-bitfield-type-align %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-NT %s +// RUN: %clang_cc1 -triple=powerpc64-linux-gnu -fno-bitfield-type-align %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-NT %s + +// Expensive unaligned +// RUN: %clang_cc1 -triple=hexagon-elf -fno-bitfield-type-align %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-STRICT-NT %s +// RUN: %clang_cc1 -triple=mips-elf -fno-bitfield-type-align %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-STRICT-NT %s + + +struct P1 { + unsigned a :8; + char :0; + unsigned b :8; +} p1; +// CHECK-LABEL: LLVMType:%struct.P1 = +// LAYOUT-T-SAME: type { i8, i8, [2 x i8] } +// LAYOUT-ARM64-T-SAME: type { i8, i8 } +// LAYOUT-NT-SAME: type { i8, i8 } +// LAYOUT-STRICT-NT-SAME: type { i8, i8 } +// LAYOUT-DWN32-SAME: type { i8, [3 x i8], i8, [3 x i8] } +// CHECK: BitFields:[ +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:4 +// CHECK-NEXT: ]> + +// This will often be align(1) with -fno-bitfield-type-align +struct P2 { + unsigned a :8; + char :0; + short :0; + unsigned b :8; +} p2; +// CHECK-LABEL: LLVMType:%struct.P2 = +// LAYOUT-T-SAME: type { i8, i8, i8, i8 } +// LAYOUT-ARM64-T-SAME: type { i8, i8, i8, i8 } +// LAYOUT-NT-SAME: type { i8, i8 } +// LAYOUT-STRICT-NT-SAME: type { i8, i8 } +// LAYOUT-DWN32-SAME: type { i8, [3 x i8], i8, [3 x i8] } +// CHECK: BitFields:[ +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:2 + +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:2 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:4 +// CHECK-NEXT: ]> + +struct P3 { + unsigned a :8; + char :0; + short :0; + unsigned :0; + unsigned b :8; +} p3; +// CHECK-LABEL: LLVMType:%struct.P3 = +// LAYOUT-T-SAME: type { i8, [3 x i8], i8, [3 x i8] } +// LAYOUT-ARM64-T-SAME: type { i8, [3 x i8], i8, [3 x i8] } +// LAYOUT-NT-SAME: type { i8, i8 } +// LAYOUT-STRICT-NT-SAME: type { i8, i8 } +// LAYOUT-DWN32-SAME: type { i8, [3 x i8], i8, [3 x i8] } +// CHECK: BitFields:[ +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:4 + +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:4 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:4 +// CHECK-NEXT: ]> + +struct P4 { + unsigned a :8; + short :0; + unsigned :0; + unsigned b :8; +} p4; +// CHECK-LABEL: LLVMType:%struct.P4 = +// LAYOUT-T-SAME: type { i8, [3 x i8], i8, [3 x i8] } +// LAYOUT-ARM64-T-SAME: type { i8, [3 x i8], i8, [3 x i8] } +// LAYOUT-NT-SAME: type { i8, i8 } +// LAYOUT-STRICT-NT-SAME: type { i8, i8 } +// LAYOUT-DWN32-SAME: type { i8, [3 x i8], i8, [3 x i8] } +// CHECK: BitFields:[ +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:4 + +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:4 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:4 +// CHECK-NEXT: ]> + +struct P5 { + unsigned a :8; + unsigned :0; + unsigned b :8; +} p5; +// CHECK-LABEL: LLVMType:%struct.P5 = +// LAYOUT-T-SAME: type { i8, [3 x i8], i8, [3 x i8] } +// LAYOUT-ARM64-T-SAME: type { i8, [3 x i8], i8, [3 x i8] } +// LAYOUT-NT-SAME: type { i8, i8 } +// LAYOUT-STRICT-NT-SAME: type { i8, i8 } +// LAYOUT-DWN32-SAME: type { i8, [3 x i8], i8, [3 x i8] } +// CHECK: BitFields:[ +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:4 + +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:4 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:4 +// CHECK-NEXT: ]> + +struct P6 { + unsigned a :8; + unsigned :0; + short :0; + char :0; + unsigned b :8; +} p6; +// CHECK-LABEL: LLVMType:%struct.P6 = +// LAYOUT-T-SAME: type { i8, [3 x i8], i8, [3 x i8] } +// LAYOUT-ARM64-T-SAME: type { i8, [3 x i8], i8, [3 x i8] } +// LAYOUT-NT-SAME: type { i8, i8 } +// LAYOUT-STRICT-NT-SAME: type { i8, i8 } +// LAYOUT-DWN32-SAME: type { i8, [3 x i8], i8, [3 x i8] } +// CHECK: BitFields:[ +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:4 + +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:4 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:4 +// CHECK-NEXT: ]> + +struct P7 { + unsigned a : 8; + short : 0; + unsigned char b : 8; +} p7; +// CHECK-LABEL: LLVMType:%struct.P7 = +// LAYOUT-T-SAME: type { i8, i8, i8, i8 } +// LAYOUT-ARM64-T-SAME: type { i8, i8, i8, i8 } +// LAYOUT-NT-SAME: type { i8, i8 } +// LAYOUT-STRICT-NT-SAME: type { i8, i8 } +// LAYOUT-DWN32-SAME: type { i8, [3 x i8], i8, [3 x i8] } +// CHECK: BitFields:[ +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:2 + +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:2 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:4 +// CHECK-NEXT: ]> + +// And with forced alignment for !useZeroLengthBitfieldAlignment machines (eg +// hexagon) +struct __attribute__ ((aligned (2))) P7_align { + unsigned a : 8; + short : 0; + unsigned char b : 8; +} p7_align; +// CHECK-LABEL: LLVMType:%struct.P7_align = +// LAYOUT-T-SAME: type { i8, i8, i8, i8 } +// LAYOUT-ARM64-T-SAME: type { i8, i8, i8, i8 } +// LAYOUT-NT-SAME: type { i8, i8 } +// LAYOUT-STRICT-NT-SAME: type { i8, i8 } +// LAYOUT-DWN32-SAME: type { i8, [3 x i8], i8, [3 x i8] } +// CHECK: BitFields:[ +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:2 + +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:2 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:4 +// CHECK-NEXT: ]> + +struct P8 { + unsigned a : 7; + short : 0; + unsigned char b : 7; +} p8; +// CHECK-LABEL: LLVMType:%struct.P8 = +// LAYOUT-T-SAME: type { i8, i8, i8, i8 } +// LAYOUT-ARM64-T-SAME: type { i8, i8, i8, i8 } +// LAYOUT-NT-SAME: type { i16 } +// LAYOUT-STRICT-NT-SAME: type { i16 } +// LAYOUT-DWN32-SAME: type { i8, [3 x i8], i8, [3 x i8] } +// CHECK: BitFields:[ +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:8 StorageOffset:2 + +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:16 StorageOffset:0 +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:16 StorageOffset:0 + +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:16 StorageOffset:0 +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:16 StorageOffset:0 + +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:8 StorageOffset:2 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:8 StorageOffset:4 +// CHECK-NEXT: ]> + +struct P9 { + unsigned a : 7; + char : 0; + unsigned short b : 7; +} p9; +// CHECK-LABEL: LLVMType:%struct.P9 = +// LAYOUT-T-SAME: type { i8, i8, [2 x i8] } +// LAYOUT-ARM64-T-SAME: type { i8, i8 } +// LAYOUT-NT-SAME: type { i16 } +// LAYOUT-STRICT-NT-SAME: type { i16 } +// LAYOUT-DWN32-SAME: type { i8, [3 x i8], i8, [3 x i8] } +// CHECK: BitFields:[ +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:16 StorageOffset:0 +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:16 StorageOffset:0 + +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:16 StorageOffset:0 +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:16 StorageOffset:0 + +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:8 StorageOffset:1 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:8 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:8 StorageOffset:4 +// CHECK-NEXT: ]> + +struct __attribute__((aligned(4))) P10 { + unsigned a : 7; + unsigned short b : 7; + unsigned c : 7; + char : 0; +} p10; +// CHECK-LABEL: LLVMType:%struct.P10 = +// LAYOUT-T-SAME: type { i32 } +// LAYOUT-ARM64-T-SAME: type { i32 } +// LAYOUT-NT-SAME: type { i32 } +// LAYOUT-STRICT-NT-SAME: type { i32 } +// LAYOUT-DWN32-SAME: type { i32 } +// CHECK: BitFields:[ +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 + +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 + +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 + +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// CHECK-NEXT: ]> + +struct __attribute__((aligned(4))) P11 { + unsigned a : 7; + unsigned short b : 7; + unsigned c : 10; + char : 0; // at a char boundary +} p11; +// CHECK-LABEL: LLVMType:%struct.P11 = +// LAYOUT-T-SAME: type { i32 } +// LAYOUT-ARM64-T-SAME: type { i32 } +// LAYOUT-NT-SAME: type { i32 } +// LAYOUT-STRICT-NT-SAME: type { i32 } +// LAYOUT-DWN32-SAME: type { i32 } +// CHECK: BitFields:[ +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:10 IsSigned:0 StorageSize:32 StorageOffset:0 + +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:10 IsSigned:0 StorageSize:32 StorageOffset:0 + +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-STRICT-NT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:10 IsSigned:0 StorageSize:32 StorageOffset:0 + +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-ARM64-T-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:10 IsSigned:0 StorageSize:32 StorageOffset:0 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:10 IsSigned:0 StorageSize:32 StorageOffset:0 +// CHECK-NEXT: ]> diff --git a/clang/test/CodeGen/bitfield-access-unit.c b/clang/test/CodeGen/bitfield-access-unit.c new file mode 100644 index 0000000000000000000000000000000000000000..1aed2e7202fc654f56e4279779c43f1ceb14deb1 --- /dev/null +++ b/clang/test/CodeGen/bitfield-access-unit.c @@ -0,0 +1,302 @@ +// Check arches with 32bit ints. (Not you, AVR & MSP430) + +// Configs that have cheap unaligned access + +// 64-bit Little Endian +// RUN: %clang_cc1 -triple=aarch64-apple-darwin %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-FLEX,LAYOUT-FLEX64,CHECK-64,LAYOUT-64-DWN %s +// RUN: %clang_cc1 -triple=aarch64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-FLEX,LAYOUT-FLEX64,CHECK-64,LAYOUT-64,LAYOUT-64-FLEX %s +// RUN: %clang_cc1 -triple=loongarch64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-FLEX,LAYOUT-FLEX64,CHECK-64,LAYOUT-64,LAYOUT-64-FLEX %s +// RUN: %clang_cc1 -triple=ve-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-FLEX,LAYOUT-FLEX64 %s +// RUN: %clang_cc1 -triple=wasm64 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-FLEX,LAYOUT-FLEX64 %s +// RUN: %clang_cc1 -triple=x86_64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-FLEX,LAYOUT-FLEX64,CHECK-64,LAYOUT-64,LAYOUT-64-FLEX %s + +// 64-bit Big Endian +// RUN: %clang_cc1 -triple=powerpc64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-FLEX,LAYOUT-FLEX64,CHECK-64,LAYOUT-64,LAYOUT-64-FLEX %s +// RUN: %clang_cc1 -triple=systemz %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-FLEX,LAYOUT-FLEX64,CHECK-64,LAYOUT-64,LAYOUT-64-FLEX %s + +// 32-bit Little Endian +// RUN: %clang_cc1 -triple=arm-apple-darwin %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-DWN32,LAYOUT-DWN32-FLEX %s +// RUN: %clang_cc1 -triple=arm-none-eabi %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-FLEX,LAYOUT-FLEX32 %s +// RUN: %clang_cc1 -triple=i686-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-FLEX,LAYOUT-FLEX32 %s +// RUN: %clang_cc1 -triple=powerpcle-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-FLEX,LAYOUT-FLEX32 %s +// RUN: %clang_cc1 -triple=wasm32 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-FLEX,LAYOUT-FLEX32 %s + +// 32-bit Big Endian +// RUN: %clang_cc1 -triple=powerpc-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-FLEX,LAYOUT-FLEX32 %s + +// Configs that have expensive unaligned access +// 64-bit Little Endian +// RUN: %clang_cc1 -triple=aarch64-linux-gnu %s -target-feature +strict-align -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT,CHECK-64,LAYOUT-64,LAYOUT-64-STRICT %s +// RUN: %clang_cc1 -triple=amdgcn-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT,CHECK-64,LAYOUT-64,LAYOUT-64-STRICT %s +// RUN: %clang_cc1 -triple=loongarch64-elf -target-feature -ual %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT,CHECK-64,LAYOUT-64,LAYOUT-64-STRICT %s +// RUN: %clang_cc1 -triple=riscv64 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT,CHECK-64,LAYOUT-64,LAYOUT-64-STRICT %s + +// 64-big Big endian +// RUN: %clang_cc1 -triple=mips64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT,CHECK-64,LAYOUT-64,LAYOUT-64-STRICT %s + +// 32-bit Little Endian +// RUN: %clang_cc1 -triple=arc-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT %s +// RUN: %clang_cc1 -triple=arm-apple-darwin %s -target-feature +strict-align -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-DWN32,LAYOUT-DWN32-STRICT %s +// RUN: %clang_cc1 -triple=arm-none-eabi %s -target-feature +strict-align -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT %s +// RUN: %clang_cc1 -triple=bpf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT %s +// RUN: %clang_cc1 -triple=csky %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT %s +// RUN: %clang_cc1 -triple=hexagon-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT %s +// RUN: %clang_cc1 -triple=loongarch32-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT %s +// RUN: %clang_cc1 -triple=nvptx-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT %s +// RUN: %clang_cc1 -triple=riscv32 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT %s +// RUN: %clang_cc1 -triple=spir-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT %s +// RUN: %clang_cc1 -triple=xcore-none-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT %s + +// 32-bit Big Endian +// RUN: %clang_cc1 -triple=lanai-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT %s +// RUN: %clang_cc1 -triple=mips-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT %s +// RUN: %clang_cc1 -triple=sparc-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT %s +// RUN: %clang_cc1 -triple=tce-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT-STRICT %s + +// Both le64-elf and m68-elf are strict alignment ISAs with 4-byte aligned +// 64-bit or 2-byte aligned 32-bit integer types. This more compex to describe here. + +// If unaligned access is expensive don't stick these together. +struct A { + char a : 7; + char b : 7; +} a; +// CHECK-LABEL: LLVMType:%struct.A = +// LAYOUT-FLEX-SAME: type { i16 } +// LAYOUT-STRICT-SAME: type { i8, i8 } +// LAYOUT-DWN32-SAME: type { i16 } +// CHECK: BitFields:[ +// LAYOUT-FLEX-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-FLEX-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:16 StorageOffset:0 + +// LAYOUT-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:8 StorageOffset:0 +// LAYOUT-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:8 StorageOffset:1 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:16 StorageOffset:0 +// CHECK-NEXT: ]> + +// But do here. +struct __attribute__((aligned(2))) B { + char a : 7; + char b : 7; +} b; +// CHECK-LABEL: LLVMType:%struct.B = +// LAYOUT-SAME: type { i16 } +// LAYOUT-DWN32-SAME: type { i16 } +// CHECK: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:16 StorageOffset:0 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:16 StorageOffset:0 +// CHECK-NEXT: ]> + +// Not here -- poor alignment within struct +struct C { + int f1; + char f2; + char a : 7; + char b : 7; +} c; +// CHECK-LABEL: LLVMType:%struct.C = +// LAYOUT-FLEX-SAME: type <{ i32, i8, i16, i8 }> +// LAYOUT-STRICT-SAME: type { i32, i8, i8, i8 } +// LAYOUT-DWN32-SAME: type <{ i32, i8, i16, i8 }> +// CHECK: BitFields:[ +// LAYOUT-FLEX-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:16 StorageOffset:5 +// LAYOUT-FLEX-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:16 StorageOffset:5 + +// LAYOUT-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:8 StorageOffset:5 +// LAYOUT-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:8 StorageOffset:6 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:16 StorageOffset:5 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:16 StorageOffset:5 +// CHECK-NEXT: ]> + +// Not here, we're packed +struct __attribute__((packed)) D { + int f1; + int a : 8; + int b : 8; + char _; +} d; +// CHECK-LABEL: LLVMType:%struct.D = +// LAYOUT-FLEX-SAME: type <{ i32, i16, i8 }> +// LAYOUT-STRICT-SAME: type <{ i32, i8, i8, i8 }> +// LAYOUT-DWN32-FLEX-SAME: type <{ i32, i16, i8 }> +// LAYOUT-DWN32-STRICT-SAME: type <{ i32, i8, i8, i8 }> +// CHECK: BitFields:[ +// LAYOUT-FLEX-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:16 StorageOffset:4 +// LAYOUT-FLEX-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:16 StorageOffset:4 + +// LAYOUT-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:4 +// LAYOUT-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:5 + +// LAYOUT-DWN32-FLEX-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:16 StorageOffset:4 +// LAYOUT-DWN32-FLEX-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:16 StorageOffset:4 +// LAYOUT-DWN32-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:4 +// LAYOUT-DWN32-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:5 +// CHECK-NEXT: ]> + +struct E { + char a : 7; + short b : 13; + unsigned c : 12; +} e; +// CHECK-LABEL: LLVMType:%struct.E = +// LAYOUT-FLEX64-SAME: type { i64 } +// LAYOUT-FLEX32-SAME: type { i32, i16 } +// LAYOUT-STRICT-SAME: type { i32, i16 } +// LAYOUT-DWN32-SAME: type { i32 } +// CHECK: BitFields:[ +// LAYOUT-FLEX64-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-FLEX64-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:13 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-FLEX64-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:12 IsSigned:0 StorageSize:64 StorageOffset:0 + +// LAYOUT-FLEX32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-FLEX32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:13 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-FLEX32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:12 IsSigned:0 StorageSize:16 StorageOffset:4 + +// LAYOUT-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:13 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:12 IsSigned:0 StorageSize:16 StorageOffset:4 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:13 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:12 IsSigned:0 StorageSize:32 StorageOffset:0 +// CHECK-NEXT: ]> + +struct F { + char a : 7; + short b : 13; + unsigned c : 12; + signed char d : 7; +} f; +// CHECK-LABEL: LLVMType:%struct.F = +// LAYOUT-FLEX64-SAME: type { i64 } +// LAYOUT-FLEX32-SAME: type { i32, i32 } +// LAYOUT-STRICT-SAME: type { i32, i32 } +// LAYOUT-DWN32-SAME: type <{ i32, i8 }> +// CHECK: BitFields:[ +// LAYOUT-FLEX64-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-FLEX64-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:13 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-FLEX64-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:12 IsSigned:0 StorageSize:64 StorageOffset:0 +// LAYOUT-FLEX64-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:64 StorageOffset:0 + +// LAYOUT-FLEX32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-FLEX32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:13 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-FLEX32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:12 IsSigned:0 StorageSize:32 StorageOffset:4 +// LAYOUT-FLEX32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:32 StorageOffset:4 + +// LAYOUT-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:13 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:12 IsSigned:0 StorageSize:32 StorageOffset:4 +// LAYOUT-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:32 StorageOffset:4 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:13 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:12 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:8 StorageOffset:4 +// CHECK-NEXT: ]> + +struct G { + char a : 7; + short b : 13; + unsigned c : 12; + signed char d : 7; + signed char e; +} g; +// CHECK-LABEL: LLVMType:%struct.G = +// LAYOUT-SAME: type { i32, i16, i8, i8 } +// LAYOUT-DWN32-SAME: type <{ i32, i8, i8 }> +// CHECK: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:13 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:12 IsSigned:0 StorageSize:16 StorageOffset:4 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:8 StorageOffset:6 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:13 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:12 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:8 StorageOffset:4 +// CHECK-NEXT: ]> + +#if _LP64 +struct A64 { + int a : 16; + short b : 8; + long c : 16; + int d : 16; + signed char e : 8; +} a64; +// CHECK-64-LABEL: LLVMType:%struct.A64 = +// LAYOUT-64-SAME: type { i64 } +// LAYOUT-64-DWN-SAME: type { i64 } +// CHECK-64: BitFields:[ +// LAYOUT-64-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-64-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-64-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-64-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-64-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:64 StorageOffset:0 + +// LAYOUT-64-DWN-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-64-DWN-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-64-DWN-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-64-DWN-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-64-DWN-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:64 StorageOffset:0 +// CHECK-64-NEXT: ]> + +struct B64 { + int a : 16; + short b : 8; + long c : 16; + int d : 16; + signed char e; // not a bitfield +} b64; +// CHECK-64-LABEL: LLVMType:%struct.B64 = +// LAYOUT-64-FLEX-SAME: type <{ i16, i8, i32, i8 }> +// LAYOUT-64-STRICT-SAME: type <{ i16, i8, i16, i16, i8 }> +// LAYOUT-64-DWN-SAME: type <{ i16, i8, i32, i8 }> +// CHECK-64: BitFields:[ +// LAYOUT-64-FLEX-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-64-FLEX-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:2 +// LAYOUT-64-FLEX-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:32 StorageOffset:3 +// LAYOUT-64-FLEX-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:32 StorageOffset:3 + +// LAYOUT-64-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-64-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:2 +// LAYOUT-64-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:3 +// LAYOUT-64-STRICT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:5 + +// LAYOUT-64-DWN-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-64-DWN-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:2 +// LAYOUT-64-DWN-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:32 StorageOffset:3 +// LAYOUT-64-DWN-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:32 StorageOffset:3 +// CHECK-64-NEXT: ]> + +struct C64 { + int a : 15; + short b : 8; + long c : 16; + int d : 15; + signed char e : 7; +} c64; +// CHECK-64-LABEL: LLVMType:%struct.C64 = +// LAYOUT-64-SAME: type { i64 } +// LAYOUT-64-DWN-SAME: type { i64 } +// CHECK-64: BitFields:[ +// LAYOUT-64-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:15 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-64-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-64-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-64-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:15 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-64-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:64 StorageOffset:0 + +// LAYOUT-64-DWN-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:15 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-64-DWN-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-64-DWN-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-64-DWN-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:15 IsSigned:1 StorageSize:64 StorageOffset:0 +// LAYOUT-64-DWN-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:7 IsSigned:1 StorageSize:64 StorageOffset:0 +// CHECK-64-NEXT: ]> + +#endif diff --git a/clang/test/CodeGen/builtins-arm64.c b/clang/test/CodeGen/builtins-arm64.c index 05ea1c719edff3651d5a4dbe848e7088a3abb780..8bd68d9ceb48ec90a43295c8092e096a33ac3148 100644 --- a/clang/test/CodeGen/builtins-arm64.c +++ b/clang/test/CodeGen/builtins-arm64.c @@ -156,4 +156,10 @@ int rndrrs(uint64_t *__addr) { return __builtin_arm_rndrrs(__addr); } +// CHECK-LABEL: @trap( +// CHECK: call void @llvm.aarch64.break(i32 42) +void trap() { + __builtin_arm_trap(42); +} + // CHECK: ![[M0]] = !{!"1:2:3:4:5"} diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c index 4f9641d357b7baa1a7a53fa6cb18f3ca3e8f3187..407e0857d2231136c03cdbc9e893414447cffc62 100644 --- a/clang/test/CodeGen/builtins.c +++ b/clang/test/CodeGen/builtins.c @@ -983,4 +983,208 @@ void test_builtin_popcountg(unsigned char uc, unsigned short us, // CHECK-NEXT: ret void } +// CHECK-LABEL: define{{.*}} void @test_builtin_clzg +void test_builtin_clzg(unsigned char uc, unsigned short us, unsigned int ui, + unsigned long ul, unsigned long long ull, + unsigned __int128 ui128, unsigned _BitInt(128) ubi128, + signed char sc, short s, int i) { + volatile int lz; + lz = __builtin_clzg(uc); + // CHECK: %1 = load i8, ptr %uc.addr, align 1 + // CHECK-NEXT: %2 = call i8 @llvm.ctlz.i8(i8 %1, i1 true) + // CHECK-NEXT: %cast = sext i8 %2 to i32 + // CHECK-NEXT: store volatile i32 %cast, ptr %lz, align 4 + lz = __builtin_clzg(us); + // CHECK-NEXT: %3 = load i16, ptr %us.addr, align 2 + // CHECK-NEXT: %4 = call i16 @llvm.ctlz.i16(i16 %3, i1 true) + // CHECK-NEXT: %cast1 = sext i16 %4 to i32 + // CHECK-NEXT: store volatile i32 %cast1, ptr %lz, align 4 + lz = __builtin_clzg(ui); + // CHECK-NEXT: %5 = load i32, ptr %ui.addr, align 4 + // CHECK-NEXT: %6 = call i32 @llvm.ctlz.i32(i32 %5, i1 true) + // CHECK-NEXT: store volatile i32 %6, ptr %lz, align 4 + lz = __builtin_clzg(ul); + // CHECK-NEXT: %7 = load i64, ptr %ul.addr, align 8 + // CHECK-NEXT: %8 = call i64 @llvm.ctlz.i64(i64 %7, i1 true) + // CHECK-NEXT: %cast2 = trunc i64 %8 to i32 + // CHECK-NEXT: store volatile i32 %cast2, ptr %lz, align 4 + lz = __builtin_clzg(ull); + // CHECK-NEXT: %9 = load i64, ptr %ull.addr, align 8 + // CHECK-NEXT: %10 = call i64 @llvm.ctlz.i64(i64 %9, i1 true) + // CHECK-NEXT: %cast3 = trunc i64 %10 to i32 + // CHECK-NEXT: store volatile i32 %cast3, ptr %lz, align 4 + lz = __builtin_clzg(ui128); + // CHECK-NEXT: %11 = load i128, ptr %ui128.addr, align 16 + // CHECK-NEXT: %12 = call i128 @llvm.ctlz.i128(i128 %11, i1 true) + // CHECK-NEXT: %cast4 = trunc i128 %12 to i32 + // CHECK-NEXT: store volatile i32 %cast4, ptr %lz, align 4 + lz = __builtin_clzg(ubi128); + // CHECK-NEXT: %13 = load i128, ptr %ubi128.addr, align 8 + // CHECK-NEXT: %14 = call i128 @llvm.ctlz.i128(i128 %13, i1 true) + // CHECK-NEXT: %cast5 = trunc i128 %14 to i32 + // CHECK-NEXT: store volatile i32 %cast5, ptr %lz, align 4 + lz = __builtin_clzg(uc, sc); + // CHECK-NEXT: %15 = load i8, ptr %uc.addr, align 1 + // CHECK-NEXT: %16 = call i8 @llvm.ctlz.i8(i8 %15, i1 true) + // CHECK-NEXT: %cast6 = sext i8 %16 to i32 + // CHECK-NEXT: %iszero = icmp eq i8 %15, 0 + // CHECK-NEXT: %17 = load i8, ptr %sc.addr, align 1 + // CHECK-NEXT: %conv = sext i8 %17 to i32 + // CHECK-NEXT: %clzg = select i1 %iszero, i32 %conv, i32 %cast6 + // CHECK-NEXT: store volatile i32 %clzg, ptr %lz, align 4 + lz = __builtin_clzg(us, uc); + // CHECK-NEXT: %18 = load i16, ptr %us.addr, align 2 + // CHECK-NEXT: %19 = call i16 @llvm.ctlz.i16(i16 %18, i1 true) + // CHECK-NEXT: %cast7 = sext i16 %19 to i32 + // CHECK-NEXT: %iszero8 = icmp eq i16 %18, 0 + // CHECK-NEXT: %20 = load i8, ptr %uc.addr, align 1 + // CHECK-NEXT: %conv9 = zext i8 %20 to i32 + // CHECK-NEXT: %clzg10 = select i1 %iszero8, i32 %conv9, i32 %cast7 + // CHECK-NEXT: store volatile i32 %clzg10, ptr %lz, align 4 + lz = __builtin_clzg(ui, s); + // CHECK-NEXT: %21 = load i32, ptr %ui.addr, align 4 + // CHECK-NEXT: %22 = call i32 @llvm.ctlz.i32(i32 %21, i1 true) + // CHECK-NEXT: %iszero11 = icmp eq i32 %21, 0 + // CHECK-NEXT: %23 = load i16, ptr %s.addr, align 2 + // CHECK-NEXT: %conv12 = sext i16 %23 to i32 + // CHECK-NEXT: %clzg13 = select i1 %iszero11, i32 %conv12, i32 %22 + // CHECK-NEXT: store volatile i32 %clzg13, ptr %lz, align 4 + lz = __builtin_clzg(ul, us); + // CHECK-NEXT: %24 = load i64, ptr %ul.addr, align 8 + // CHECK-NEXT: %25 = call i64 @llvm.ctlz.i64(i64 %24, i1 true) + // CHECK-NEXT: %cast14 = trunc i64 %25 to i32 + // CHECK-NEXT: %iszero15 = icmp eq i64 %24, 0 + // CHECK-NEXT: %26 = load i16, ptr %us.addr, align 2 + // CHECK-NEXT: %conv16 = zext i16 %26 to i32 + // CHECK-NEXT: %clzg17 = select i1 %iszero15, i32 %conv16, i32 %cast14 + // CHECK-NEXT: store volatile i32 %clzg17, ptr %lz, align 4 + lz = __builtin_clzg(ull, i); + // CHECK-NEXT: %27 = load i64, ptr %ull.addr, align 8 + // CHECK-NEXT: %28 = call i64 @llvm.ctlz.i64(i64 %27, i1 true) + // CHECK-NEXT: %cast18 = trunc i64 %28 to i32 + // CHECK-NEXT: %iszero19 = icmp eq i64 %27, 0 + // CHECK-NEXT: %29 = load i32, ptr %i.addr, align 4 + // CHECK-NEXT: %clzg20 = select i1 %iszero19, i32 %29, i32 %cast18 + // CHECK-NEXT: store volatile i32 %clzg20, ptr %lz, align 4 + lz = __builtin_clzg(ui128, i); + // CHECK-NEXT: %30 = load i128, ptr %ui128.addr, align 16 + // CHECK-NEXT: %31 = call i128 @llvm.ctlz.i128(i128 %30, i1 true) + // CHECK-NEXT: %cast21 = trunc i128 %31 to i32 + // CHECK-NEXT: %iszero22 = icmp eq i128 %30, 0 + // CHECK-NEXT: %32 = load i32, ptr %i.addr, align 4 + // CHECK-NEXT: %clzg23 = select i1 %iszero22, i32 %32, i32 %cast21 + // CHECK-NEXT: store volatile i32 %clzg23, ptr %lz, align 4 + lz = __builtin_clzg(ubi128, i); + // CHECK-NEXT: %33 = load i128, ptr %ubi128.addr, align 8 + // CHECK-NEXT: %34 = call i128 @llvm.ctlz.i128(i128 %33, i1 true) + // CHECK-NEXT: %cast24 = trunc i128 %34 to i32 + // CHECK-NEXT: %iszero25 = icmp eq i128 %33, 0 + // CHECK-NEXT: %35 = load i32, ptr %i.addr, align 4 + // CHECK-NEXT: %clzg26 = select i1 %iszero25, i32 %35, i32 %cast24 + // CHECK-NEXT: store volatile i32 %clzg26, ptr %lz, align 4 + // CHECK-NEXT: ret void +} + +// CHECK-LABEL: define{{.*}} void @test_builtin_ctzg +void test_builtin_ctzg(unsigned char uc, unsigned short us, unsigned int ui, + unsigned long ul, unsigned long long ull, + unsigned __int128 ui128, unsigned _BitInt(128) ubi128, + signed char sc, short s, int i) { + volatile int tz; + tz = __builtin_ctzg(uc); + // CHECK: %1 = load i8, ptr %uc.addr, align 1 + // CHECK-NEXT: %2 = call i8 @llvm.cttz.i8(i8 %1, i1 true) + // CHECK-NEXT: %cast = sext i8 %2 to i32 + // CHECK-NEXT: store volatile i32 %cast, ptr %tz, align 4 + tz = __builtin_ctzg(us); + // CHECK-NEXT: %3 = load i16, ptr %us.addr, align 2 + // CHECK-NEXT: %4 = call i16 @llvm.cttz.i16(i16 %3, i1 true) + // CHECK-NEXT: %cast1 = sext i16 %4 to i32 + // CHECK-NEXT: store volatile i32 %cast1, ptr %tz, align 4 + tz = __builtin_ctzg(ui); + // CHECK-NEXT: %5 = load i32, ptr %ui.addr, align 4 + // CHECK-NEXT: %6 = call i32 @llvm.cttz.i32(i32 %5, i1 true) + // CHECK-NEXT: store volatile i32 %6, ptr %tz, align 4 + tz = __builtin_ctzg(ul); + // CHECK-NEXT: %7 = load i64, ptr %ul.addr, align 8 + // CHECK-NEXT: %8 = call i64 @llvm.cttz.i64(i64 %7, i1 true) + // CHECK-NEXT: %cast2 = trunc i64 %8 to i32 + // CHECK-NEXT: store volatile i32 %cast2, ptr %tz, align 4 + tz = __builtin_ctzg(ull); + // CHECK-NEXT: %9 = load i64, ptr %ull.addr, align 8 + // CHECK-NEXT: %10 = call i64 @llvm.cttz.i64(i64 %9, i1 true) + // CHECK-NEXT: %cast3 = trunc i64 %10 to i32 + // CHECK-NEXT: store volatile i32 %cast3, ptr %tz, align 4 + tz = __builtin_ctzg(ui128); + // CHECK-NEXT: %11 = load i128, ptr %ui128.addr, align 16 + // CHECK-NEXT: %12 = call i128 @llvm.cttz.i128(i128 %11, i1 true) + // CHECK-NEXT: %cast4 = trunc i128 %12 to i32 + // CHECK-NEXT: store volatile i32 %cast4, ptr %tz, align 4 + tz = __builtin_ctzg(ubi128); + // CHECK-NEXT: %13 = load i128, ptr %ubi128.addr, align 8 + // CHECK-NEXT: %14 = call i128 @llvm.cttz.i128(i128 %13, i1 true) + // CHECK-NEXT: %cast5 = trunc i128 %14 to i32 + // CHECK-NEXT: store volatile i32 %cast5, ptr %tz, align 4 + tz = __builtin_ctzg(uc, sc); + // CHECK-NEXT: %15 = load i8, ptr %uc.addr, align 1 + // CHECK-NEXT: %16 = call i8 @llvm.cttz.i8(i8 %15, i1 true) + // CHECK-NEXT: %cast6 = sext i8 %16 to i32 + // CHECK-NEXT: %iszero = icmp eq i8 %15, 0 + // CHECK-NEXT: %17 = load i8, ptr %sc.addr, align 1 + // CHECK-NEXT: %conv = sext i8 %17 to i32 + // CHECK-NEXT: %ctzg = select i1 %iszero, i32 %conv, i32 %cast6 + // CHECK-NEXT: store volatile i32 %ctzg, ptr %tz, align 4 + tz = __builtin_ctzg(us, uc); + // CHECK-NEXT: %18 = load i16, ptr %us.addr, align 2 + // CHECK-NEXT: %19 = call i16 @llvm.cttz.i16(i16 %18, i1 true) + // CHECK-NEXT: %cast7 = sext i16 %19 to i32 + // CHECK-NEXT: %iszero8 = icmp eq i16 %18, 0 + // CHECK-NEXT: %20 = load i8, ptr %uc.addr, align 1 + // CHECK-NEXT: %conv9 = zext i8 %20 to i32 + // CHECK-NEXT: %ctzg10 = select i1 %iszero8, i32 %conv9, i32 %cast7 + // CHECK-NEXT: store volatile i32 %ctzg10, ptr %tz, align 4 + tz = __builtin_ctzg(ui, s); + // CHECK-NEXT: %21 = load i32, ptr %ui.addr, align 4 + // CHECK-NEXT: %22 = call i32 @llvm.cttz.i32(i32 %21, i1 true) + // CHECK-NEXT: %iszero11 = icmp eq i32 %21, 0 + // CHECK-NEXT: %23 = load i16, ptr %s.addr, align 2 + // CHECK-NEXT: %conv12 = sext i16 %23 to i32 + // CHECK-NEXT: %ctzg13 = select i1 %iszero11, i32 %conv12, i32 %22 + // CHECK-NEXT: store volatile i32 %ctzg13, ptr %tz, align 4 + tz = __builtin_ctzg(ul, us); + // CHECK-NEXT: %24 = load i64, ptr %ul.addr, align 8 + // CHECK-NEXT: %25 = call i64 @llvm.cttz.i64(i64 %24, i1 true) + // CHECK-NEXT: %cast14 = trunc i64 %25 to i32 + // CHECK-NEXT: %iszero15 = icmp eq i64 %24, 0 + // CHECK-NEXT: %26 = load i16, ptr %us.addr, align 2 + // CHECK-NEXT: %conv16 = zext i16 %26 to i32 + // CHECK-NEXT: %ctzg17 = select i1 %iszero15, i32 %conv16, i32 %cast14 + // CHECK-NEXT: store volatile i32 %ctzg17, ptr %tz, align 4 + tz = __builtin_ctzg(ull, i); + // CHECK-NEXT: %27 = load i64, ptr %ull.addr, align 8 + // CHECK-NEXT: %28 = call i64 @llvm.cttz.i64(i64 %27, i1 true) + // CHECK-NEXT: %cast18 = trunc i64 %28 to i32 + // CHECK-NEXT: %iszero19 = icmp eq i64 %27, 0 + // CHECK-NEXT: %29 = load i32, ptr %i.addr, align 4 + // CHECK-NEXT: %ctzg20 = select i1 %iszero19, i32 %29, i32 %cast18 + // CHECK-NEXT: store volatile i32 %ctzg20, ptr %tz, align 4 + tz = __builtin_ctzg(ui128, i); + // CHECK-NEXT: %30 = load i128, ptr %ui128.addr, align 16 + // CHECK-NEXT: %31 = call i128 @llvm.cttz.i128(i128 %30, i1 true) + // CHECK-NEXT: %cast21 = trunc i128 %31 to i32 + // CHECK-NEXT: %iszero22 = icmp eq i128 %30, 0 + // CHECK-NEXT: %32 = load i32, ptr %i.addr, align 4 + // CHECK-NEXT: %ctzg23 = select i1 %iszero22, i32 %32, i32 %cast21 + // CHECK-NEXT: store volatile i32 %ctzg23, ptr %tz, align 4 + tz = __builtin_ctzg(ubi128, i); + // CHECK-NEXT: %33 = load i128, ptr %ubi128.addr, align 8 + // CHECK-NEXT: %34 = call i128 @llvm.cttz.i128(i128 %33, i1 true) + // CHECK-NEXT: %cast24 = trunc i128 %34 to i32 + // CHECK-NEXT: %iszero25 = icmp eq i128 %33, 0 + // CHECK-NEXT: %35 = load i32, ptr %i.addr, align 4 + // CHECK-NEXT: %ctzg26 = select i1 %iszero25, i32 %35, i32 %cast24 + // CHECK-NEXT: store volatile i32 %ctzg26, ptr %tz, align 4 + // CHECK-NEXT: ret void +} + #endif diff --git a/clang/test/CodeGen/cfi-check-attrs.c b/clang/test/CodeGen/cfi-check-attrs.c new file mode 100644 index 0000000000000000000000000000000000000000..375aa30074d8874b5a5ddae8c5b15652af10044a --- /dev/null +++ b/clang/test/CodeGen/cfi-check-attrs.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -triple arm-unknown-linux -funwind-tables=1 -fsanitize-cfi-cross-dso -emit-llvm -o - %s | FileCheck %s + +// CHECK: define weak {{.*}}void @__cfi_check({{.*}} [[ATTR:#[0-9]*]] + +// CHECK: attributes [[ATTR]] = {{.*}} uwtable(sync) diff --git a/clang/test/CodeGen/cfi-check-fail.c b/clang/test/CodeGen/cfi-check-fail.c index 2f12cee9dec6026b0c8b93c6ec10e54f57c1e9c7..15f6c77abf2b20a86154abfa11e67abc6f435b8b 100644 --- a/clang/test/CodeGen/cfi-check-fail.c +++ b/clang/test/CodeGen/cfi-check-fail.c @@ -72,7 +72,7 @@ void caller(void (*f)(void)) { // CHECK: [[CONT5]]: // CHECK: ret void -// CHECK: define weak void @__cfi_check(i64 %[[TYPE:.*]], ptr %[[ADDR:.*]], ptr %[[DATA:.*]]) align 4096 +// CHECK: define weak void @__cfi_check(i64 noundef %[[TYPE:.*]], ptr noundef %[[ADDR:.*]], ptr noundef %[[DATA:.*]]){{.*}} align 4096 // CHECK-NOT: } // CHECK: call void @__cfi_check_fail(ptr %[[DATA]], ptr %[[ADDR]]) // CHECK-NEXT: ret void diff --git a/clang/test/CodeGen/complex-math-mixed.c b/clang/test/CodeGen/complex-math-mixed.c new file mode 100644 index 0000000000000000000000000000000000000000..050163cca80aab4bb8a6ea1178e44c8f7f44f2f6 --- /dev/null +++ b/clang/test/CodeGen/complex-math-mixed.c @@ -0,0 +1,146 @@ +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown -o - | FileCheck %s --check-prefix=X86 +// RUN: %clang_cc1 %s -O0 -triple x86_64-unknown-unknown -fsyntax-only -ast-dump | FileCheck %s --check-prefix=AST + +// Check that for 'F _Complex + int' (F = real floating-point type), we emit an +// implicit cast from 'int' to 'F', but NOT to 'F _Complex' (i.e. that we do +// 'F _Complex + F', NOT 'F _Complex + F _Complex'), and likewise for -/*. + +// AST-NOT: FloatingRealToComplex + +float _Complex add_float_ci(float _Complex a, int b) { + // X86-LABEL: @add_float_ci + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to float + // X86: fadd float {{.*}}, [[I]] + // X86-NOT: fadd + return a + b; +} + +float _Complex add_float_ic(int a, float _Complex b) { + // X86-LABEL: @add_float_ic + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to float + // X86: fadd float [[I]] + // X86-NOT: fadd + return a + b; +} + +float _Complex sub_float_ci(float _Complex a, int b) { + // X86-LABEL: @sub_float_ci + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to float + // X86: fsub float {{.*}}, [[I]] + // X86-NOT: fsub + return a - b; +} + +float _Complex sub_float_ic(int a, float _Complex b) { + // X86-LABEL: @sub_float_ic + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to float + // X86: fsub float [[I]] + // X86: fneg + // X86-NOT: fsub + return a - b; +} + +float _Complex mul_float_ci(float _Complex a, int b) { + // X86-LABEL: @mul_float_ci + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to float + // X86: fmul float {{.*}}, [[I]] + // X86: fmul float {{.*}}, [[I]] + // X86-NOT: fmul + return a * b; +} + +float _Complex mul_float_ic(int a, float _Complex b) { + // X86-LABEL: @mul_float_ic + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to float + // X86: fmul float [[I]] + // X86: fmul float [[I]] + // X86-NOT: fmul + return a * b; +} + +float _Complex div_float_ci(float _Complex a, int b) { + // X86-LABEL: @div_float_ci + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to float + // X86: fdiv float {{.*}}, [[I]] + // X86: fdiv float {{.*}}, [[I]] + // X86-NOT: @__divsc3 + return a / b; +} + +// There is no good way of doing this w/o converting the 'int' to a complex +// number, so we expect complex division here. +float _Complex div_float_ic(int a, float _Complex b) { + // X86-LABEL: @div_float_ic + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to float + // X86: call {{.*}} @__divsc3(float {{.*}} [[I]], float noundef 0.{{0+}}e+00, float {{.*}}, float {{.*}}) + return a / b; +} + +double _Complex add_double_ci(double _Complex a, int b) { + // X86-LABEL: @add_double_ci + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to double + // X86: fadd double {{.*}}, [[I]] + // X86-NOT: fadd + return a + b; +} + +double _Complex add_double_ic(int a, double _Complex b) { + // X86-LABEL: @add_double_ic + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to double + // X86: fadd double [[I]] + // X86-NOT: fadd + return a + b; +} + +double _Complex sub_double_ci(double _Complex a, int b) { + // X86-LABEL: @sub_double_ci + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to double + // X86: fsub double {{.*}}, [[I]] + // X86-NOT: fsub + return a - b; +} + +double _Complex sub_double_ic(int a, double _Complex b) { + // X86-LABEL: @sub_double_ic + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to double + // X86: fsub double [[I]] + // X86: fneg + // X86-NOT: fsub + return a - b; +} + +double _Complex mul_double_ci(double _Complex a, int b) { + // X86-LABEL: @mul_double_ci + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to double + // X86: fmul double {{.*}}, [[I]] + // X86: fmul double {{.*}}, [[I]] + // X86-NOT: fmul + return a * b; +} + +double _Complex mul_double_ic(int a, double _Complex b) { + // X86-LABEL: @mul_double_ic + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to double + // X86: fmul double [[I]] + // X86: fmul double [[I]] + // X86-NOT: fmul + return a * b; +} + +double _Complex div_double_ci(double _Complex a, int b) { + // X86-LABEL: @div_double_ci + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to double + // X86: fdiv double {{.*}}, [[I]] + // X86: fdiv double {{.*}}, [[I]] + // X86-NOT: @__divdc3 + return a / b; +} + +// There is no good way of doing this w/o converting the 'int' to a complex +// number, so we expect complex division here. +double _Complex div_double_ic(int a, double _Complex b) { + // X86-LABEL: @div_double_ic + // X86: [[I:%.*]] = sitofp i32 {{%.*}} to double + // X86: call {{.*}} @__divdc3(double {{.*}} [[I]], double noundef 0.{{0+}}e+00, double {{.*}}, double {{.*}}) + return a / b; +} diff --git a/clang/test/CodeGen/complex-math.c b/clang/test/CodeGen/complex-math.c index a44aa0014a6587955bdac9d6fca37d5e42adb3d7..ba00b9cbecd2fe6bf7d69a452fb49bde5e859eea 100644 --- a/clang/test/CodeGen/complex-math.c +++ b/clang/test/CodeGen/complex-math.c @@ -5,7 +5,7 @@ // RUN: %clang_cc1 %s -O0 -emit-llvm -triple armv7-none-linux-gnueabi -o - | FileCheck %s --check-prefix=ARM // RUN: %clang_cc1 %s -O0 -emit-llvm -triple armv7-none-linux-gnueabihf -o - | FileCheck %s --check-prefix=ARMHF // RUN: %clang_cc1 %s -O0 -emit-llvm -triple thumbv7k-apple-watchos2.0 -o - -target-abi aapcs16 | FileCheck %s --check-prefix=ARM7K -// RUN: %clang_cc1 %s -O0 -emit-llvm -triple aarch64-unknown-unknown -ffast-math -ffp-contract=fast -complex-range=fortran -o - | FileCheck %s --check-prefix=AARCH64-FASTMATH +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple aarch64-unknown-unknown -ffast-math -ffp-contract=fast -complex-range=improved -o - | FileCheck %s --check-prefix=AARCH64-FASTMATH // RUN: %clang_cc1 %s -O0 -emit-llvm -triple spir -o - | FileCheck %s --check-prefix=SPIR float _Complex add_float_rr(float a, float b) { diff --git a/clang/test/CodeGen/const-init.c b/clang/test/CodeGen/const-init.c index 0e4fc4ad48af8dba4bdc5c2d4e6f9f10724a4965..ad3e9551199ac25622463d335ef4964db2b25951 100644 --- a/clang/test/CodeGen/const-init.c +++ b/clang/test/CodeGen/const-init.c @@ -216,3 +216,6 @@ int PR4517_x2 = PR4517_arrc[PR4517_idx]; // CHECK: @PR4517_x = global i32 42, align 4 // CHECK: @PR4517_idx = constant i32 1, align 4 // CHECK: @PR4517_x2 = global i32 42, align 4 + +// CHECK: @GH84784_inf = constant i8 1 +_Bool const GH84784_inf = (1.0/0.0); diff --git a/clang/test/CodeGen/cx-complex-range.c b/clang/test/CodeGen/cx-complex-range.c index 2d8507c710f2021449386c08d6d78c19e0cafdc7..9ec80252085b87ac8298a723a36d261f013a378d 100644 --- a/clang/test/CodeGen/cx-complex-range.c +++ b/clang/test/CodeGen/cx-complex-range.c @@ -1,124 +1,3451 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ // RUN: -o - | FileCheck %s --check-prefix=FULL // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ -// RUN: -complex-range=limited -o - | FileCheck %s --check-prefix=LMTD +// RUN: -complex-range=basic -o - | FileCheck %s --check-prefix=BASIC // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ // RUN: -fno-cx-limited-range -o - | FileCheck %s --check-prefix=FULL // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ -// RUN: -complex-range=fortran -o - | FileCheck %s --check-prefix=FRTRN +// RUN: -complex-range=improved -o - | FileCheck %s --check-prefix=IMPRVD + +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -complex-range=promoted -o - | FileCheck %s --check-prefix=PRMTD + +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -complex-range=full -o - | FileCheck %s --check-prefix=FULL + +// RUN: %clang_cc1 -triple x86_64-windows-pc -complex-range=promoted \ +// RUN: -emit-llvm -o - %s | FileCheck %s --check-prefix=X86WINPRMTD + +// RUN: %clang_cc1 -triple=avr-unknown-unknown -mdouble=32 \ +// RUN: -complex-range=promoted -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=AVRFP32 + +// RUN: %clang_cc1 -triple=avr-unknown-unknown -mdouble=64 \ +// RUN: -complex-range=promoted -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=AVRFP64 // Fast math // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu \ -// RUN: -ffast-math -complex-range=limited -emit-llvm -o - %s \ -// RUN: | FileCheck %s --check-prefix=LMTD-FAST +// RUN: -ffast-math -complex-range=basic -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=BASIC_FAST // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu \ // RUN: -ffast-math -complex-range=full -emit-llvm -o - %s \ -// RUN: | FileCheck %s --check-prefix=FULL +// RUN: | FileCheck %s --check-prefix=FULL_FAST // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ // RUN: -fno-cx-fortran-rules -o - | FileCheck %s --check-prefix=FULL -// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ -// RUN: -fcx-limited-range -fno-cx-limited-range -o - \ -// RUN: | FileCheck %s --check-prefix=FULL +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu \ +// RUN: -ffast-math -complex-range=improved -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=IMPRVD_FAST -// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ -// RUN: -fno-cx-limited-range -fcx-limited-range -o - \ -// RUN: | FileCheck %s --check-prefix=FULL +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu \ +// RUN: -ffast-math -complex-range=promoted -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=PRMTD_FAST -// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ -// RUN: -fno-cx-fortran-rules -fcx-fortran-rules -o - \ -// RUN: | FileCheck %s --check-prefix=FULL - -_Complex float div(_Complex float a, _Complex float b) { - // LABEL: define {{.*}} @div( - // FULL: call {{.*}} @__divsc3 - - // LMTD: fmul float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fadd float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fadd float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fsub float - // LMTD-NEXT: fdiv float - // LMTD-NEXT: fdiv float - - // FRTRN: call {{.*}}float @llvm.fabs.f32(float {{.*}}) - // FRTRN-NEXT: call {{.*}}float @llvm.fabs.f32(float {{.*}}) - // FRTRN-NEXT: fcmp {{.*}}ugt float - // FRTRN-NEXT: br i1 {{.*}}, label - // FRTRN: abs_rhsr_greater_or_equal_abs_rhsi: - // FRTRN-NEXT: fdiv {{.*}}float - // FRTRN-NEXT: fmul {{.*}}float - // FRTRN-NEXT: fadd {{.*}}float - // FRTRN-NEXT: fmul {{.*}}float - // FRTRN-NEXT: fadd {{.*}}float - // FRTRN-NEXT: fdiv {{.*}}float - // FRTRN-NEXT: fmul {{.*}}float - // FRTRN-NEXT: fsub {{.*}}float - // FRTRN-NEXT: fdiv {{.*}}float - // FRTRN-NEXT: br label - // FRTRN: abs_rhsr_less_than_abs_rhsi: - // FRTRN-NEXT: fdiv {{.*}}float - // FRTRN-NEXT: fmul {{.*}}float - // FRTRN-NEXT: fadd {{.*}}float - // FRTRN-NEXT: fmul {{.*}}float - // FRTRN-NEXT: fadd {{.*}}float - // FRTRN-NEXT: fdiv {{.*}}float - // FRTRN-NEXT: fmul {{.*}}float - // FRTRN-NEXT: fsub {{.*}}float - // FRTRN-NEXT: fdiv {{.*}}float - // FRTRN-NEXT: br label - // FRTRN: complex_div: - // FRTRN-NEXT: phi {{.*}}float - // FRTRN-NEXT: phi {{.*}}float - - // LMTD-FAST: fmul {{.*}} float - // LMTD-FAST-NEXT: fmul {{.*}} float - // LMTD-FAST-NEXT: fadd {{.*}} float - // LMTD-FAST-NEXT: fmul {{.*}} float - // LMTD-FAST-NEXT: fmul {{.*}} float - // LMTD-FAST-NEXT: fadd {{.*}} float - // LMTD-FAST-NEXT: fmul {{.*}} float - // LMTD-FAST-NEXT: fmul {{.*}} float - // LMTD-FAST-NEXT: fsub {{.*}} float - // LMTD-FAST-NEXT: fdiv {{.*}} float - // LMTD-FAST-NEXT: fdiv {{.*}} float +// FULL-LABEL: define dso_local <2 x float> @divf( +// FULL-SAME: <2 x float> noundef [[A_COERCE:%.*]], <2 x float> noundef [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// FULL-NEXT: entry: +// FULL-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// FULL-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// FULL-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// FULL-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4 +// FULL-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// FULL-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4 +// FULL-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// FULL-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// FULL-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// FULL-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// FULL-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// FULL-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// FULL-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// FULL-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// FULL-NEXT: [[CALL:%.*]] = call <2 x float> @__divsc3(float noundef [[A_REAL]], float noundef [[A_IMAG]], float noundef [[B_REAL]], float noundef [[B_IMAG]]) #[[ATTR2:[0-9]+]] +// FULL-NEXT: store <2 x float> [[CALL]], ptr [[COERCE]], align 4 +// FULL-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 0 +// FULL-NEXT: [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4 +// FULL-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 1 +// FULL-NEXT: [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4 +// FULL-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// FULL-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// FULL-NEXT: store float [[COERCE_REAL]], ptr [[RETVAL_REALP]], align 4 +// FULL-NEXT: store float [[COERCE_IMAG]], ptr [[RETVAL_IMAGP]], align 4 +// FULL-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// FULL-NEXT: ret <2 x float> [[TMP0]] +// +// BASIC-LABEL: define dso_local <2 x float> @divf( +// BASIC-SAME: <2 x float> noundef [[A_COERCE:%.*]], <2 x float> noundef [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// BASIC-NEXT: entry: +// BASIC-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// BASIC-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// BASIC-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// BASIC-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// BASIC-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4 +// BASIC-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// BASIC-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// BASIC-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// BASIC-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// BASIC-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// BASIC-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// BASIC-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// BASIC-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// BASIC-NEXT: [[TMP0:%.*]] = fmul float [[A_REAL]], [[B_REAL]] +// BASIC-NEXT: [[TMP1:%.*]] = fmul float [[A_IMAG]], [[B_IMAG]] +// BASIC-NEXT: [[TMP2:%.*]] = fadd float [[TMP0]], [[TMP1]] +// BASIC-NEXT: [[TMP3:%.*]] = fmul float [[B_REAL]], [[B_REAL]] +// BASIC-NEXT: [[TMP4:%.*]] = fmul float [[B_IMAG]], [[B_IMAG]] +// BASIC-NEXT: [[TMP5:%.*]] = fadd float [[TMP3]], [[TMP4]] +// BASIC-NEXT: [[TMP6:%.*]] = fmul float [[A_IMAG]], [[B_REAL]] +// BASIC-NEXT: [[TMP7:%.*]] = fmul float [[A_REAL]], [[B_IMAG]] +// BASIC-NEXT: [[TMP8:%.*]] = fsub float [[TMP6]], [[TMP7]] +// BASIC-NEXT: [[TMP9:%.*]] = fdiv float [[TMP2]], [[TMP5]] +// BASIC-NEXT: [[TMP10:%.*]] = fdiv float [[TMP8]], [[TMP5]] +// BASIC-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC-NEXT: store float [[TMP9]], ptr [[RETVAL_REALP]], align 4 +// BASIC-NEXT: store float [[TMP10]], ptr [[RETVAL_IMAGP]], align 4 +// BASIC-NEXT: [[TMP11:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// BASIC-NEXT: ret <2 x float> [[TMP11]] +// +// IMPRVD-LABEL: define dso_local <2 x float> @divf( +// IMPRVD-SAME: <2 x float> noundef [[A_COERCE:%.*]], <2 x float> noundef [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// IMPRVD-NEXT: entry: +// IMPRVD-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// IMPRVD-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// IMPRVD-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// IMPRVD-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// IMPRVD-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4 +// IMPRVD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// IMPRVD-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// IMPRVD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// IMPRVD-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// IMPRVD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// IMPRVD-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// IMPRVD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// IMPRVD-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// IMPRVD-NEXT: [[TMP0:%.*]] = call float @llvm.fabs.f32(float [[B_REAL]]) +// IMPRVD-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[B_IMAG]]) +// IMPRVD-NEXT: [[ABS_CMP:%.*]] = fcmp ugt float [[TMP0]], [[TMP1]] +// IMPRVD-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// IMPRVD: abs_rhsr_greater_or_equal_abs_rhsi: +// IMPRVD-NEXT: [[TMP2:%.*]] = fdiv float [[B_IMAG]], [[B_REAL]] +// IMPRVD-NEXT: [[TMP3:%.*]] = fmul float [[TMP2]], [[B_IMAG]] +// IMPRVD-NEXT: [[TMP4:%.*]] = fadd float [[B_REAL]], [[TMP3]] +// IMPRVD-NEXT: [[TMP5:%.*]] = fmul float [[A_IMAG]], [[TMP2]] +// IMPRVD-NEXT: [[TMP6:%.*]] = fadd float [[A_REAL]], [[TMP5]] +// IMPRVD-NEXT: [[TMP7:%.*]] = fdiv float [[TMP6]], [[TMP4]] +// IMPRVD-NEXT: [[TMP8:%.*]] = fmul float [[A_REAL]], [[TMP2]] +// IMPRVD-NEXT: [[TMP9:%.*]] = fsub float [[A_IMAG]], [[TMP8]] +// IMPRVD-NEXT: [[TMP10:%.*]] = fdiv float [[TMP9]], [[TMP4]] +// IMPRVD-NEXT: br label [[COMPLEX_DIV:%.*]] +// IMPRVD: abs_rhsr_less_than_abs_rhsi: +// IMPRVD-NEXT: [[TMP11:%.*]] = fdiv float [[B_REAL]], [[B_IMAG]] +// IMPRVD-NEXT: [[TMP12:%.*]] = fmul float [[TMP11]], [[B_REAL]] +// IMPRVD-NEXT: [[TMP13:%.*]] = fadd float [[B_IMAG]], [[TMP12]] +// IMPRVD-NEXT: [[TMP14:%.*]] = fmul float [[A_REAL]], [[TMP11]] +// IMPRVD-NEXT: [[TMP15:%.*]] = fadd float [[TMP14]], [[A_IMAG]] +// IMPRVD-NEXT: [[TMP16:%.*]] = fdiv float [[TMP15]], [[TMP13]] +// IMPRVD-NEXT: [[TMP17:%.*]] = fmul float [[A_IMAG]], [[TMP11]] +// IMPRVD-NEXT: [[TMP18:%.*]] = fsub float [[TMP17]], [[A_REAL]] +// IMPRVD-NEXT: [[TMP19:%.*]] = fdiv float [[TMP18]], [[TMP13]] +// IMPRVD-NEXT: br label [[COMPLEX_DIV]] +// IMPRVD: complex_div: +// IMPRVD-NEXT: [[TMP20:%.*]] = phi float [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD-NEXT: [[TMP21:%.*]] = phi float [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD-NEXT: store float [[TMP20]], ptr [[RETVAL_REALP]], align 4 +// IMPRVD-NEXT: store float [[TMP21]], ptr [[RETVAL_IMAGP]], align 4 +// IMPRVD-NEXT: [[TMP22:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// IMPRVD-NEXT: ret <2 x float> [[TMP22]] +// +// PRMTD-LABEL: define dso_local <2 x float> @divf( +// PRMTD-SAME: <2 x float> noundef [[A_COERCE:%.*]], <2 x float> noundef [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// PRMTD-NEXT: entry: +// PRMTD-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// PRMTD-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// PRMTD-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// PRMTD-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// PRMTD-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4 +// PRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// PRMTD-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// PRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// PRMTD-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// PRMTD-NEXT: [[EXT:%.*]] = fpext float [[A_REAL]] to double +// PRMTD-NEXT: [[EXT1:%.*]] = fpext float [[A_IMAG]] to double +// PRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// PRMTD-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// PRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// PRMTD-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// PRMTD-NEXT: [[EXT2:%.*]] = fpext float [[B_REAL]] to double +// PRMTD-NEXT: [[EXT3:%.*]] = fpext float [[B_IMAG]] to double +// PRMTD-NEXT: [[TMP0:%.*]] = fmul double [[EXT]], [[EXT2]] +// PRMTD-NEXT: [[TMP1:%.*]] = fmul double [[EXT1]], [[EXT3]] +// PRMTD-NEXT: [[TMP2:%.*]] = fadd double [[TMP0]], [[TMP1]] +// PRMTD-NEXT: [[TMP3:%.*]] = fmul double [[EXT2]], [[EXT2]] +// PRMTD-NEXT: [[TMP4:%.*]] = fmul double [[EXT3]], [[EXT3]] +// PRMTD-NEXT: [[TMP5:%.*]] = fadd double [[TMP3]], [[TMP4]] +// PRMTD-NEXT: [[TMP6:%.*]] = fmul double [[EXT1]], [[EXT2]] +// PRMTD-NEXT: [[TMP7:%.*]] = fmul double [[EXT]], [[EXT3]] +// PRMTD-NEXT: [[TMP8:%.*]] = fsub double [[TMP6]], [[TMP7]] +// PRMTD-NEXT: [[TMP9:%.*]] = fdiv double [[TMP2]], [[TMP5]] +// PRMTD-NEXT: [[TMP10:%.*]] = fdiv double [[TMP8]], [[TMP5]] +// PRMTD-NEXT: [[UNPROMOTION:%.*]] = fptrunc double [[TMP9]] to float +// PRMTD-NEXT: [[UNPROMOTION4:%.*]] = fptrunc double [[TMP10]] to float +// PRMTD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD-NEXT: store float [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 4 +// PRMTD-NEXT: store float [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 4 +// PRMTD-NEXT: [[TMP11:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// PRMTD-NEXT: ret <2 x float> [[TMP11]] +// +// X86WINPRMTD-LABEL: define dso_local i64 @divf( +// X86WINPRMTD-SAME: i64 noundef [[A_COERCE:%.*]], i64 noundef [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// X86WINPRMTD-NEXT: entry: +// X86WINPRMTD-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// X86WINPRMTD-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// X86WINPRMTD-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// X86WINPRMTD-NEXT: store i64 [[A_COERCE]], ptr [[A]], align 4 +// X86WINPRMTD-NEXT: store i64 [[B_COERCE]], ptr [[B]], align 4 +// X86WINPRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// X86WINPRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// X86WINPRMTD-NEXT: [[EXT:%.*]] = fpext float [[A_REAL]] to double +// X86WINPRMTD-NEXT: [[EXT1:%.*]] = fpext float [[A_IMAG]] to double +// X86WINPRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// X86WINPRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// X86WINPRMTD-NEXT: [[EXT2:%.*]] = fpext float [[B_REAL]] to double +// X86WINPRMTD-NEXT: [[EXT3:%.*]] = fpext float [[B_IMAG]] to double +// X86WINPRMTD-NEXT: [[TMP0:%.*]] = fmul double [[EXT]], [[EXT2]] +// X86WINPRMTD-NEXT: [[TMP1:%.*]] = fmul double [[EXT1]], [[EXT3]] +// X86WINPRMTD-NEXT: [[TMP2:%.*]] = fadd double [[TMP0]], [[TMP1]] +// X86WINPRMTD-NEXT: [[TMP3:%.*]] = fmul double [[EXT2]], [[EXT2]] +// X86WINPRMTD-NEXT: [[TMP4:%.*]] = fmul double [[EXT3]], [[EXT3]] +// X86WINPRMTD-NEXT: [[TMP5:%.*]] = fadd double [[TMP3]], [[TMP4]] +// X86WINPRMTD-NEXT: [[TMP6:%.*]] = fmul double [[EXT1]], [[EXT2]] +// X86WINPRMTD-NEXT: [[TMP7:%.*]] = fmul double [[EXT]], [[EXT3]] +// X86WINPRMTD-NEXT: [[TMP8:%.*]] = fsub double [[TMP6]], [[TMP7]] +// X86WINPRMTD-NEXT: [[TMP9:%.*]] = fdiv double [[TMP2]], [[TMP5]] +// X86WINPRMTD-NEXT: [[TMP10:%.*]] = fdiv double [[TMP8]], [[TMP5]] +// X86WINPRMTD-NEXT: [[UNPROMOTION:%.*]] = fptrunc double [[TMP9]] to float +// X86WINPRMTD-NEXT: [[UNPROMOTION4:%.*]] = fptrunc double [[TMP10]] to float +// X86WINPRMTD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// X86WINPRMTD-NEXT: store float [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 4 +// X86WINPRMTD-NEXT: store float [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 4 +// X86WINPRMTD-NEXT: [[TMP11:%.*]] = load i64, ptr [[RETVAL]], align 4 +// X86WINPRMTD-NEXT: ret i64 [[TMP11]] +// +// AVRFP32-LABEL: define dso_local { float, float } @divf( +// AVRFP32-SAME: float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]], float noundef [[B_COERCE0:%.*]], float noundef [[B_COERCE1:%.*]]) addrspace(1) #[[ATTR0:[0-9]+]] { +// AVRFP32-NEXT: entry: +// AVRFP32-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[A:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[B:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[TMP0:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP32-NEXT: store float [[A_COERCE0]], ptr [[TMP0]], align 1 +// AVRFP32-NEXT: [[TMP1:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[A_COERCE1]], ptr [[TMP1]], align 1 +// AVRFP32-NEXT: [[TMP2:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// AVRFP32-NEXT: store float [[B_COERCE0]], ptr [[TMP2]], align 1 +// AVRFP32-NEXT: [[TMP3:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[B_COERCE1]], ptr [[TMP3]], align 1 +// AVRFP32-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP32-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 1 +// AVRFP32-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP32-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 1 +// AVRFP32-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// AVRFP32-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 1 +// AVRFP32-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// AVRFP32-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 1 +// AVRFP32-NEXT: [[TMP4:%.*]] = call addrspace(1) float @llvm.fabs.f32(float [[B_REAL]]) +// AVRFP32-NEXT: [[TMP5:%.*]] = call addrspace(1) float @llvm.fabs.f32(float [[B_IMAG]]) +// AVRFP32-NEXT: [[ABS_CMP:%.*]] = fcmp ugt float [[TMP4]], [[TMP5]] +// AVRFP32-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// AVRFP32: abs_rhsr_greater_or_equal_abs_rhsi: +// AVRFP32-NEXT: [[TMP6:%.*]] = fdiv float [[B_IMAG]], [[B_REAL]] +// AVRFP32-NEXT: [[TMP7:%.*]] = fmul float [[TMP6]], [[B_IMAG]] +// AVRFP32-NEXT: [[TMP8:%.*]] = fadd float [[B_REAL]], [[TMP7]] +// AVRFP32-NEXT: [[TMP9:%.*]] = fmul float [[A_IMAG]], [[TMP6]] +// AVRFP32-NEXT: [[TMP10:%.*]] = fadd float [[A_REAL]], [[TMP9]] +// AVRFP32-NEXT: [[TMP11:%.*]] = fdiv float [[TMP10]], [[TMP8]] +// AVRFP32-NEXT: [[TMP12:%.*]] = fmul float [[A_REAL]], [[TMP6]] +// AVRFP32-NEXT: [[TMP13:%.*]] = fsub float [[A_IMAG]], [[TMP12]] +// AVRFP32-NEXT: [[TMP14:%.*]] = fdiv float [[TMP13]], [[TMP8]] +// AVRFP32-NEXT: br label [[COMPLEX_DIV:%.*]] +// AVRFP32: abs_rhsr_less_than_abs_rhsi: +// AVRFP32-NEXT: [[TMP15:%.*]] = fdiv float [[B_REAL]], [[B_IMAG]] +// AVRFP32-NEXT: [[TMP16:%.*]] = fmul float [[TMP15]], [[B_REAL]] +// AVRFP32-NEXT: [[TMP17:%.*]] = fadd float [[B_IMAG]], [[TMP16]] +// AVRFP32-NEXT: [[TMP18:%.*]] = fmul float [[A_REAL]], [[TMP15]] +// AVRFP32-NEXT: [[TMP19:%.*]] = fadd float [[TMP18]], [[A_IMAG]] +// AVRFP32-NEXT: [[TMP20:%.*]] = fdiv float [[TMP19]], [[TMP17]] +// AVRFP32-NEXT: [[TMP21:%.*]] = fmul float [[A_IMAG]], [[TMP15]] +// AVRFP32-NEXT: [[TMP22:%.*]] = fsub float [[TMP21]], [[A_REAL]] +// AVRFP32-NEXT: [[TMP23:%.*]] = fdiv float [[TMP22]], [[TMP17]] +// AVRFP32-NEXT: br label [[COMPLEX_DIV]] +// AVRFP32: complex_div: +// AVRFP32-NEXT: [[TMP24:%.*]] = phi float [ [[TMP11]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP20]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// AVRFP32-NEXT: [[TMP25:%.*]] = phi float [ [[TMP14]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP23]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// AVRFP32-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// AVRFP32-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[TMP24]], ptr [[RETVAL_REALP]], align 1 +// AVRFP32-NEXT: store float [[TMP25]], ptr [[RETVAL_IMAGP]], align 1 +// AVRFP32-NEXT: [[TMP26:%.*]] = load { float, float }, ptr [[RETVAL]], align 1 +// AVRFP32-NEXT: ret { float, float } [[TMP26]] +// +// AVRFP64-LABEL: define dso_local { float, float } @divf( +// AVRFP64-SAME: float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]], float noundef [[B_COERCE0:%.*]], float noundef [[B_COERCE1:%.*]]) addrspace(1) #[[ATTR0:[0-9]+]] { +// AVRFP64-NEXT: entry: +// AVRFP64-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 1 +// AVRFP64-NEXT: [[A:%.*]] = alloca { float, float }, align 1 +// AVRFP64-NEXT: [[B:%.*]] = alloca { float, float }, align 1 +// AVRFP64-NEXT: [[TMP0:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP64-NEXT: store float [[A_COERCE0]], ptr [[TMP0]], align 1 +// AVRFP64-NEXT: [[TMP1:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP64-NEXT: store float [[A_COERCE1]], ptr [[TMP1]], align 1 +// AVRFP64-NEXT: [[TMP2:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// AVRFP64-NEXT: store float [[B_COERCE0]], ptr [[TMP2]], align 1 +// AVRFP64-NEXT: [[TMP3:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// AVRFP64-NEXT: store float [[B_COERCE1]], ptr [[TMP3]], align 1 +// AVRFP64-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP64-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 1 +// AVRFP64-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP64-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 1 +// AVRFP64-NEXT: [[EXT:%.*]] = fpext float [[A_REAL]] to double +// AVRFP64-NEXT: [[EXT1:%.*]] = fpext float [[A_IMAG]] to double +// AVRFP64-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// AVRFP64-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 1 +// AVRFP64-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// AVRFP64-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 1 +// AVRFP64-NEXT: [[EXT2:%.*]] = fpext float [[B_REAL]] to double +// AVRFP64-NEXT: [[EXT3:%.*]] = fpext float [[B_IMAG]] to double +// AVRFP64-NEXT: [[TMP4:%.*]] = fmul double [[EXT]], [[EXT2]] +// AVRFP64-NEXT: [[TMP5:%.*]] = fmul double [[EXT1]], [[EXT3]] +// AVRFP64-NEXT: [[TMP6:%.*]] = fadd double [[TMP4]], [[TMP5]] +// AVRFP64-NEXT: [[TMP7:%.*]] = fmul double [[EXT2]], [[EXT2]] +// AVRFP64-NEXT: [[TMP8:%.*]] = fmul double [[EXT3]], [[EXT3]] +// AVRFP64-NEXT: [[TMP9:%.*]] = fadd double [[TMP7]], [[TMP8]] +// AVRFP64-NEXT: [[TMP10:%.*]] = fmul double [[EXT1]], [[EXT2]] +// AVRFP64-NEXT: [[TMP11:%.*]] = fmul double [[EXT]], [[EXT3]] +// AVRFP64-NEXT: [[TMP12:%.*]] = fsub double [[TMP10]], [[TMP11]] +// AVRFP64-NEXT: [[TMP13:%.*]] = fdiv double [[TMP6]], [[TMP9]] +// AVRFP64-NEXT: [[TMP14:%.*]] = fdiv double [[TMP12]], [[TMP9]] +// AVRFP64-NEXT: [[UNPROMOTION:%.*]] = fptrunc double [[TMP13]] to float +// AVRFP64-NEXT: [[UNPROMOTION4:%.*]] = fptrunc double [[TMP14]] to float +// AVRFP64-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// AVRFP64-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// AVRFP64-NEXT: store float [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 1 +// AVRFP64-NEXT: store float [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 1 +// AVRFP64-NEXT: [[TMP15:%.*]] = load { float, float }, ptr [[RETVAL]], align 1 +// AVRFP64-NEXT: ret { float, float } [[TMP15]] +// +// BASIC_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x float> @divf( +// BASIC_FAST-SAME: <2 x float> noundef nofpclass(nan inf) [[A_COERCE:%.*]], <2 x float> noundef nofpclass(nan inf) [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// BASIC_FAST-NEXT: entry: +// BASIC_FAST-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// BASIC_FAST-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// BASIC_FAST-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// BASIC_FAST-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// BASIC_FAST-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4 +// BASIC_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// BASIC_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// BASIC_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// BASIC_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// BASIC_FAST-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_REAL]], [[B_REAL]] +// BASIC_FAST-NEXT: [[TMP1:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_IMAG]], [[B_IMAG]] +// BASIC_FAST-NEXT: [[TMP2:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP0]], [[TMP1]] +// BASIC_FAST-NEXT: [[TMP3:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[B_REAL]], [[B_REAL]] +// BASIC_FAST-NEXT: [[TMP4:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[B_IMAG]], [[B_IMAG]] +// BASIC_FAST-NEXT: [[TMP5:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP3]], [[TMP4]] +// BASIC_FAST-NEXT: [[TMP6:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_IMAG]], [[B_REAL]] +// BASIC_FAST-NEXT: [[TMP7:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_REAL]], [[B_IMAG]] +// BASIC_FAST-NEXT: [[TMP8:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[TMP6]], [[TMP7]] +// BASIC_FAST-NEXT: [[TMP9:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP2]], [[TMP5]] +// BASIC_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP8]], [[TMP5]] +// BASIC_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC_FAST-NEXT: store float [[TMP9]], ptr [[RETVAL_REALP]], align 4 +// BASIC_FAST-NEXT: store float [[TMP10]], ptr [[RETVAL_IMAGP]], align 4 +// BASIC_FAST-NEXT: [[TMP11:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// BASIC_FAST-NEXT: ret <2 x float> [[TMP11]] +// +// FULL_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x float> @divf( +// FULL_FAST-SAME: <2 x float> noundef nofpclass(nan inf) [[A_COERCE:%.*]], <2 x float> noundef nofpclass(nan inf) [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// FULL_FAST-NEXT: entry: +// FULL_FAST-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// FULL_FAST-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// FULL_FAST-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// FULL_FAST-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4 +// FULL_FAST-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// FULL_FAST-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4 +// FULL_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// FULL_FAST-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// FULL_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// FULL_FAST-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// FULL_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// FULL_FAST-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// FULL_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// FULL_FAST-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// FULL_FAST-NEXT: [[CALL:%.*]] = call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) <2 x float> @__divsc3(float noundef nofpclass(nan inf) [[A_REAL]], float noundef nofpclass(nan inf) [[A_IMAG]], float noundef nofpclass(nan inf) [[B_REAL]], float noundef nofpclass(nan inf) [[B_IMAG]]) #[[ATTR2:[0-9]+]] +// FULL_FAST-NEXT: store <2 x float> [[CALL]], ptr [[COERCE]], align 4 +// FULL_FAST-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 0 +// FULL_FAST-NEXT: [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4 +// FULL_FAST-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 1 +// FULL_FAST-NEXT: [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4 +// FULL_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// FULL_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// FULL_FAST-NEXT: store float [[COERCE_REAL]], ptr [[RETVAL_REALP]], align 4 +// FULL_FAST-NEXT: store float [[COERCE_IMAG]], ptr [[RETVAL_IMAGP]], align 4 +// FULL_FAST-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// FULL_FAST-NEXT: ret <2 x float> [[TMP0]] +// +// IMPRVD_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x float> @divf( +// IMPRVD_FAST-SAME: <2 x float> noundef nofpclass(nan inf) [[A_COERCE:%.*]], <2 x float> noundef nofpclass(nan inf) [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// IMPRVD_FAST-NEXT: entry: +// IMPRVD_FAST-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// IMPRVD_FAST-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// IMPRVD_FAST-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// IMPRVD_FAST-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// IMPRVD_FAST-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4 +// IMPRVD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// IMPRVD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// IMPRVD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// IMPRVD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// IMPRVD_FAST-NEXT: [[TMP0:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.fabs.f32(float [[B_REAL]]) +// IMPRVD_FAST-NEXT: [[TMP1:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.fabs.f32(float [[B_IMAG]]) +// IMPRVD_FAST-NEXT: [[ABS_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn ugt float [[TMP0]], [[TMP1]] +// IMPRVD_FAST-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// IMPRVD_FAST: abs_rhsr_greater_or_equal_abs_rhsi: +// IMPRVD_FAST-NEXT: [[TMP2:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[B_IMAG]], [[B_REAL]] +// IMPRVD_FAST-NEXT: [[TMP3:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP2]], [[B_IMAG]] +// IMPRVD_FAST-NEXT: [[TMP4:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[B_REAL]], [[TMP3]] +// IMPRVD_FAST-NEXT: [[TMP5:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_IMAG]], [[TMP2]] +// IMPRVD_FAST-NEXT: [[TMP6:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[A_REAL]], [[TMP5]] +// IMPRVD_FAST-NEXT: [[TMP7:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP6]], [[TMP4]] +// IMPRVD_FAST-NEXT: [[TMP8:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_REAL]], [[TMP2]] +// IMPRVD_FAST-NEXT: [[TMP9:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[A_IMAG]], [[TMP8]] +// IMPRVD_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP9]], [[TMP4]] +// IMPRVD_FAST-NEXT: br label [[COMPLEX_DIV:%.*]] +// IMPRVD_FAST: abs_rhsr_less_than_abs_rhsi: +// IMPRVD_FAST-NEXT: [[TMP11:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[B_REAL]], [[B_IMAG]] +// IMPRVD_FAST-NEXT: [[TMP12:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP11]], [[B_REAL]] +// IMPRVD_FAST-NEXT: [[TMP13:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[B_IMAG]], [[TMP12]] +// IMPRVD_FAST-NEXT: [[TMP14:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_REAL]], [[TMP11]] +// IMPRVD_FAST-NEXT: [[TMP15:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP14]], [[A_IMAG]] +// IMPRVD_FAST-NEXT: [[TMP16:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP15]], [[TMP13]] +// IMPRVD_FAST-NEXT: [[TMP17:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_IMAG]], [[TMP11]] +// IMPRVD_FAST-NEXT: [[TMP18:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[TMP17]], [[A_REAL]] +// IMPRVD_FAST-NEXT: [[TMP19:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP18]], [[TMP13]] +// IMPRVD_FAST-NEXT: br label [[COMPLEX_DIV]] +// IMPRVD_FAST: complex_div: +// IMPRVD_FAST-NEXT: [[TMP20:%.*]] = phi reassoc nnan ninf nsz arcp afn float [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD_FAST-NEXT: [[TMP21:%.*]] = phi reassoc nnan ninf nsz arcp afn float [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: store float [[TMP20]], ptr [[RETVAL_REALP]], align 4 +// IMPRVD_FAST-NEXT: store float [[TMP21]], ptr [[RETVAL_IMAGP]], align 4 +// IMPRVD_FAST-NEXT: [[TMP22:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// IMPRVD_FAST-NEXT: ret <2 x float> [[TMP22]] +// +// PRMTD_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x float> @divf( +// PRMTD_FAST-SAME: <2 x float> noundef nofpclass(nan inf) [[A_COERCE:%.*]], <2 x float> noundef nofpclass(nan inf) [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// PRMTD_FAST-NEXT: entry: +// PRMTD_FAST-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// PRMTD_FAST-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// PRMTD_FAST-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// PRMTD_FAST-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// PRMTD_FAST-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4 +// PRMTD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// PRMTD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// PRMTD_FAST-NEXT: [[EXT:%.*]] = fpext float [[A_REAL]] to double +// PRMTD_FAST-NEXT: [[EXT1:%.*]] = fpext float [[A_IMAG]] to double +// PRMTD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// PRMTD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// PRMTD_FAST-NEXT: [[EXT2:%.*]] = fpext float [[B_REAL]] to double +// PRMTD_FAST-NEXT: [[EXT3:%.*]] = fpext float [[B_IMAG]] to double +// PRMTD_FAST-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[EXT]], [[EXT2]] +// PRMTD_FAST-NEXT: [[TMP1:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[EXT1]], [[EXT3]] +// PRMTD_FAST-NEXT: [[TMP2:%.*]] = fadd reassoc nnan ninf nsz arcp afn double [[TMP0]], [[TMP1]] +// PRMTD_FAST-NEXT: [[TMP3:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[EXT2]], [[EXT2]] +// PRMTD_FAST-NEXT: [[TMP4:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[EXT3]], [[EXT3]] +// PRMTD_FAST-NEXT: [[TMP5:%.*]] = fadd reassoc nnan ninf nsz arcp afn double [[TMP3]], [[TMP4]] +// PRMTD_FAST-NEXT: [[TMP6:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[EXT1]], [[EXT2]] +// PRMTD_FAST-NEXT: [[TMP7:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[EXT]], [[EXT3]] +// PRMTD_FAST-NEXT: [[TMP8:%.*]] = fsub reassoc nnan ninf nsz arcp afn double [[TMP6]], [[TMP7]] +// PRMTD_FAST-NEXT: [[TMP9:%.*]] = fdiv reassoc nnan ninf nsz arcp afn double [[TMP2]], [[TMP5]] +// PRMTD_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn double [[TMP8]], [[TMP5]] +// PRMTD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc double [[TMP9]] to float +// PRMTD_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc double [[TMP10]] to float +// PRMTD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD_FAST-NEXT: store float [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 4 +// PRMTD_FAST-NEXT: store float [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 4 +// PRMTD_FAST-NEXT: [[TMP11:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// PRMTD_FAST-NEXT: ret <2 x float> [[TMP11]] +// +_Complex float divf(_Complex float a, _Complex float b) { + return a / b; +} + +// FULL-LABEL: define dso_local <2 x float> @mulf( +// FULL-SAME: <2 x float> noundef [[A_COERCE:%.*]], <2 x float> noundef [[B_COERCE:%.*]]) #[[ATTR0]] { +// FULL-NEXT: entry: +// FULL-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// FULL-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// FULL-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// FULL-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4 +// FULL-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// FULL-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4 +// FULL-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// FULL-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// FULL-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// FULL-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// FULL-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// FULL-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// FULL-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// FULL-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// FULL-NEXT: [[MUL_AC:%.*]] = fmul float [[A_REAL]], [[B_REAL]] +// FULL-NEXT: [[MUL_BD:%.*]] = fmul float [[A_IMAG]], [[B_IMAG]] +// FULL-NEXT: [[MUL_AD:%.*]] = fmul float [[A_REAL]], [[B_IMAG]] +// FULL-NEXT: [[MUL_BC:%.*]] = fmul float [[A_IMAG]], [[B_REAL]] +// FULL-NEXT: [[MUL_R:%.*]] = fsub float [[MUL_AC]], [[MUL_BD]] +// FULL-NEXT: [[MUL_I:%.*]] = fadd float [[MUL_AD]], [[MUL_BC]] +// FULL-NEXT: [[ISNAN_CMP:%.*]] = fcmp uno float [[MUL_R]], [[MUL_R]] +// FULL-NEXT: br i1 [[ISNAN_CMP]], label [[COMPLEX_MUL_IMAG_NAN:%.*]], label [[COMPLEX_MUL_CONT:%.*]], !prof [[PROF2:![0-9]+]] +// FULL: complex_mul_imag_nan: +// FULL-NEXT: [[ISNAN_CMP1:%.*]] = fcmp uno float [[MUL_I]], [[MUL_I]] +// FULL-NEXT: br i1 [[ISNAN_CMP1]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]] +// FULL: complex_mul_libcall: +// FULL-NEXT: [[CALL:%.*]] = call <2 x float> @__mulsc3(float noundef [[A_REAL]], float noundef [[A_IMAG]], float noundef [[B_REAL]], float noundef [[B_IMAG]]) #[[ATTR2]] +// FULL-NEXT: store <2 x float> [[CALL]], ptr [[COERCE]], align 4 +// FULL-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 0 +// FULL-NEXT: [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4 +// FULL-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 1 +// FULL-NEXT: [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4 +// FULL-NEXT: br label [[COMPLEX_MUL_CONT]] +// FULL: complex_mul_cont: +// FULL-NEXT: [[REAL_MUL_PHI:%.*]] = phi float [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_REAL]], [[COMPLEX_MUL_LIBCALL]] ] +// FULL-NEXT: [[IMAG_MUL_PHI:%.*]] = phi float [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_IMAG]], [[COMPLEX_MUL_LIBCALL]] ] +// FULL-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// FULL-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// FULL-NEXT: store float [[REAL_MUL_PHI]], ptr [[RETVAL_REALP]], align 4 +// FULL-NEXT: store float [[IMAG_MUL_PHI]], ptr [[RETVAL_IMAGP]], align 4 +// FULL-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// FULL-NEXT: ret <2 x float> [[TMP0]] +// +// BASIC-LABEL: define dso_local <2 x float> @mulf( +// BASIC-SAME: <2 x float> noundef [[A_COERCE:%.*]], <2 x float> noundef [[B_COERCE:%.*]]) #[[ATTR0]] { +// BASIC-NEXT: entry: +// BASIC-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// BASIC-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// BASIC-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// BASIC-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// BASIC-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4 +// BASIC-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// BASIC-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// BASIC-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// BASIC-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// BASIC-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// BASIC-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// BASIC-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// BASIC-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// BASIC-NEXT: [[MUL_AC:%.*]] = fmul float [[A_REAL]], [[B_REAL]] +// BASIC-NEXT: [[MUL_BD:%.*]] = fmul float [[A_IMAG]], [[B_IMAG]] +// BASIC-NEXT: [[MUL_AD:%.*]] = fmul float [[A_REAL]], [[B_IMAG]] +// BASIC-NEXT: [[MUL_BC:%.*]] = fmul float [[A_IMAG]], [[B_REAL]] +// BASIC-NEXT: [[MUL_R:%.*]] = fsub float [[MUL_AC]], [[MUL_BD]] +// BASIC-NEXT: [[MUL_I:%.*]] = fadd float [[MUL_AD]], [[MUL_BC]] +// BASIC-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC-NEXT: store float [[MUL_R]], ptr [[RETVAL_REALP]], align 4 +// BASIC-NEXT: store float [[MUL_I]], ptr [[RETVAL_IMAGP]], align 4 +// BASIC-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// BASIC-NEXT: ret <2 x float> [[TMP0]] +// +// IMPRVD-LABEL: define dso_local <2 x float> @mulf( +// IMPRVD-SAME: <2 x float> noundef [[A_COERCE:%.*]], <2 x float> noundef [[B_COERCE:%.*]]) #[[ATTR0]] { +// IMPRVD-NEXT: entry: +// IMPRVD-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// IMPRVD-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// IMPRVD-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// IMPRVD-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// IMPRVD-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4 +// IMPRVD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// IMPRVD-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// IMPRVD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// IMPRVD-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// IMPRVD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// IMPRVD-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// IMPRVD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// IMPRVD-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// IMPRVD-NEXT: [[MUL_AC:%.*]] = fmul float [[A_REAL]], [[B_REAL]] +// IMPRVD-NEXT: [[MUL_BD:%.*]] = fmul float [[A_IMAG]], [[B_IMAG]] +// IMPRVD-NEXT: [[MUL_AD:%.*]] = fmul float [[A_REAL]], [[B_IMAG]] +// IMPRVD-NEXT: [[MUL_BC:%.*]] = fmul float [[A_IMAG]], [[B_REAL]] +// IMPRVD-NEXT: [[MUL_R:%.*]] = fsub float [[MUL_AC]], [[MUL_BD]] +// IMPRVD-NEXT: [[MUL_I:%.*]] = fadd float [[MUL_AD]], [[MUL_BC]] +// IMPRVD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD-NEXT: store float [[MUL_R]], ptr [[RETVAL_REALP]], align 4 +// IMPRVD-NEXT: store float [[MUL_I]], ptr [[RETVAL_IMAGP]], align 4 +// IMPRVD-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// IMPRVD-NEXT: ret <2 x float> [[TMP0]] +// +// PRMTD-LABEL: define dso_local <2 x float> @mulf( +// PRMTD-SAME: <2 x float> noundef [[A_COERCE:%.*]], <2 x float> noundef [[B_COERCE:%.*]]) #[[ATTR0]] { +// PRMTD-NEXT: entry: +// PRMTD-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// PRMTD-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// PRMTD-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// PRMTD-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// PRMTD-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4 +// PRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// PRMTD-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// PRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// PRMTD-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// PRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// PRMTD-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// PRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// PRMTD-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// PRMTD-NEXT: [[MUL_AC:%.*]] = fmul float [[A_REAL]], [[B_REAL]] +// PRMTD-NEXT: [[MUL_BD:%.*]] = fmul float [[A_IMAG]], [[B_IMAG]] +// PRMTD-NEXT: [[MUL_AD:%.*]] = fmul float [[A_REAL]], [[B_IMAG]] +// PRMTD-NEXT: [[MUL_BC:%.*]] = fmul float [[A_IMAG]], [[B_REAL]] +// PRMTD-NEXT: [[MUL_R:%.*]] = fsub float [[MUL_AC]], [[MUL_BD]] +// PRMTD-NEXT: [[MUL_I:%.*]] = fadd float [[MUL_AD]], [[MUL_BC]] +// PRMTD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD-NEXT: store float [[MUL_R]], ptr [[RETVAL_REALP]], align 4 +// PRMTD-NEXT: store float [[MUL_I]], ptr [[RETVAL_IMAGP]], align 4 +// PRMTD-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// PRMTD-NEXT: ret <2 x float> [[TMP0]] +// +// X86WINPRMTD-LABEL: define dso_local i64 @mulf( +// X86WINPRMTD-SAME: i64 noundef [[A_COERCE:%.*]], i64 noundef [[B_COERCE:%.*]]) #[[ATTR0]] { +// X86WINPRMTD-NEXT: entry: +// X86WINPRMTD-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// X86WINPRMTD-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// X86WINPRMTD-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// X86WINPRMTD-NEXT: store i64 [[A_COERCE]], ptr [[A]], align 4 +// X86WINPRMTD-NEXT: store i64 [[B_COERCE]], ptr [[B]], align 4 +// X86WINPRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// X86WINPRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// X86WINPRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// X86WINPRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// X86WINPRMTD-NEXT: [[MUL_AC:%.*]] = fmul float [[A_REAL]], [[B_REAL]] +// X86WINPRMTD-NEXT: [[MUL_BD:%.*]] = fmul float [[A_IMAG]], [[B_IMAG]] +// X86WINPRMTD-NEXT: [[MUL_AD:%.*]] = fmul float [[A_REAL]], [[B_IMAG]] +// X86WINPRMTD-NEXT: [[MUL_BC:%.*]] = fmul float [[A_IMAG]], [[B_REAL]] +// X86WINPRMTD-NEXT: [[MUL_R:%.*]] = fsub float [[MUL_AC]], [[MUL_BD]] +// X86WINPRMTD-NEXT: [[MUL_I:%.*]] = fadd float [[MUL_AD]], [[MUL_BC]] +// X86WINPRMTD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// X86WINPRMTD-NEXT: store float [[MUL_R]], ptr [[RETVAL_REALP]], align 4 +// X86WINPRMTD-NEXT: store float [[MUL_I]], ptr [[RETVAL_IMAGP]], align 4 +// X86WINPRMTD-NEXT: [[TMP0:%.*]] = load i64, ptr [[RETVAL]], align 4 +// X86WINPRMTD-NEXT: ret i64 [[TMP0]] +// +// AVRFP32-LABEL: define dso_local { float, float } @mulf( +// AVRFP32-SAME: float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]], float noundef [[B_COERCE0:%.*]], float noundef [[B_COERCE1:%.*]]) addrspace(1) #[[ATTR0]] { +// AVRFP32-NEXT: entry: +// AVRFP32-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[A:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[B:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[TMP0:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP32-NEXT: store float [[A_COERCE0]], ptr [[TMP0]], align 1 +// AVRFP32-NEXT: [[TMP1:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[A_COERCE1]], ptr [[TMP1]], align 1 +// AVRFP32-NEXT: [[TMP2:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// AVRFP32-NEXT: store float [[B_COERCE0]], ptr [[TMP2]], align 1 +// AVRFP32-NEXT: [[TMP3:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[B_COERCE1]], ptr [[TMP3]], align 1 +// AVRFP32-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP32-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 1 +// AVRFP32-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP32-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 1 +// AVRFP32-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// AVRFP32-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 1 +// AVRFP32-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// AVRFP32-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 1 +// AVRFP32-NEXT: [[MUL_AC:%.*]] = fmul float [[A_REAL]], [[B_REAL]] +// AVRFP32-NEXT: [[MUL_BD:%.*]] = fmul float [[A_IMAG]], [[B_IMAG]] +// AVRFP32-NEXT: [[MUL_AD:%.*]] = fmul float [[A_REAL]], [[B_IMAG]] +// AVRFP32-NEXT: [[MUL_BC:%.*]] = fmul float [[A_IMAG]], [[B_REAL]] +// AVRFP32-NEXT: [[MUL_R:%.*]] = fsub float [[MUL_AC]], [[MUL_BD]] +// AVRFP32-NEXT: [[MUL_I:%.*]] = fadd float [[MUL_AD]], [[MUL_BC]] +// AVRFP32-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// AVRFP32-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[MUL_R]], ptr [[RETVAL_REALP]], align 1 +// AVRFP32-NEXT: store float [[MUL_I]], ptr [[RETVAL_IMAGP]], align 1 +// AVRFP32-NEXT: [[TMP4:%.*]] = load { float, float }, ptr [[RETVAL]], align 1 +// AVRFP32-NEXT: ret { float, float } [[TMP4]] +// +// AVRFP64-LABEL: define dso_local { float, float } @mulf( +// AVRFP64-SAME: float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]], float noundef [[B_COERCE0:%.*]], float noundef [[B_COERCE1:%.*]]) addrspace(1) #[[ATTR0]] { +// AVRFP64-NEXT: entry: +// AVRFP64-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 1 +// AVRFP64-NEXT: [[A:%.*]] = alloca { float, float }, align 1 +// AVRFP64-NEXT: [[B:%.*]] = alloca { float, float }, align 1 +// AVRFP64-NEXT: [[TMP0:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP64-NEXT: store float [[A_COERCE0]], ptr [[TMP0]], align 1 +// AVRFP64-NEXT: [[TMP1:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP64-NEXT: store float [[A_COERCE1]], ptr [[TMP1]], align 1 +// AVRFP64-NEXT: [[TMP2:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// AVRFP64-NEXT: store float [[B_COERCE0]], ptr [[TMP2]], align 1 +// AVRFP64-NEXT: [[TMP3:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// AVRFP64-NEXT: store float [[B_COERCE1]], ptr [[TMP3]], align 1 +// AVRFP64-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP64-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 1 +// AVRFP64-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP64-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 1 +// AVRFP64-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// AVRFP64-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 1 +// AVRFP64-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// AVRFP64-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 1 +// AVRFP64-NEXT: [[MUL_AC:%.*]] = fmul float [[A_REAL]], [[B_REAL]] +// AVRFP64-NEXT: [[MUL_BD:%.*]] = fmul float [[A_IMAG]], [[B_IMAG]] +// AVRFP64-NEXT: [[MUL_AD:%.*]] = fmul float [[A_REAL]], [[B_IMAG]] +// AVRFP64-NEXT: [[MUL_BC:%.*]] = fmul float [[A_IMAG]], [[B_REAL]] +// AVRFP64-NEXT: [[MUL_R:%.*]] = fsub float [[MUL_AC]], [[MUL_BD]] +// AVRFP64-NEXT: [[MUL_I:%.*]] = fadd float [[MUL_AD]], [[MUL_BC]] +// AVRFP64-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// AVRFP64-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// AVRFP64-NEXT: store float [[MUL_R]], ptr [[RETVAL_REALP]], align 1 +// AVRFP64-NEXT: store float [[MUL_I]], ptr [[RETVAL_IMAGP]], align 1 +// AVRFP64-NEXT: [[TMP4:%.*]] = load { float, float }, ptr [[RETVAL]], align 1 +// AVRFP64-NEXT: ret { float, float } [[TMP4]] +// +// BASIC_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x float> @mulf( +// BASIC_FAST-SAME: <2 x float> noundef nofpclass(nan inf) [[A_COERCE:%.*]], <2 x float> noundef nofpclass(nan inf) [[B_COERCE:%.*]]) #[[ATTR0]] { +// BASIC_FAST-NEXT: entry: +// BASIC_FAST-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// BASIC_FAST-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// BASIC_FAST-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// BASIC_FAST-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// BASIC_FAST-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4 +// BASIC_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// BASIC_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// BASIC_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// BASIC_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// BASIC_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_REAL]], [[B_REAL]] +// BASIC_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_IMAG]], [[B_IMAG]] +// BASIC_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_REAL]], [[B_IMAG]] +// BASIC_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_IMAG]], [[B_REAL]] +// BASIC_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[MUL_AC]], [[MUL_BD]] +// BASIC_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[MUL_AD]], [[MUL_BC]] +// BASIC_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC_FAST-NEXT: store float [[MUL_R]], ptr [[RETVAL_REALP]], align 4 +// BASIC_FAST-NEXT: store float [[MUL_I]], ptr [[RETVAL_IMAGP]], align 4 +// BASIC_FAST-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// BASIC_FAST-NEXT: ret <2 x float> [[TMP0]] +// +// FULL_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x float> @mulf( +// FULL_FAST-SAME: <2 x float> noundef nofpclass(nan inf) [[A_COERCE:%.*]], <2 x float> noundef nofpclass(nan inf) [[B_COERCE:%.*]]) #[[ATTR0]] { +// FULL_FAST-NEXT: entry: +// FULL_FAST-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// FULL_FAST-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// FULL_FAST-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// FULL_FAST-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4 +// FULL_FAST-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// FULL_FAST-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4 +// FULL_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// FULL_FAST-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// FULL_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// FULL_FAST-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// FULL_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// FULL_FAST-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// FULL_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// FULL_FAST-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// FULL_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_REAL]], [[B_REAL]] +// FULL_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_IMAG]], [[B_IMAG]] +// FULL_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_REAL]], [[B_IMAG]] +// FULL_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_IMAG]], [[B_REAL]] +// FULL_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[MUL_AC]], [[MUL_BD]] +// FULL_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[MUL_AD]], [[MUL_BC]] +// FULL_FAST-NEXT: [[ISNAN_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn uno float [[MUL_R]], [[MUL_R]] +// FULL_FAST-NEXT: br i1 [[ISNAN_CMP]], label [[COMPLEX_MUL_IMAG_NAN:%.*]], label [[COMPLEX_MUL_CONT:%.*]], !prof [[PROF2:![0-9]+]] +// FULL_FAST: complex_mul_imag_nan: +// FULL_FAST-NEXT: [[ISNAN_CMP1:%.*]] = fcmp reassoc nnan ninf nsz arcp afn uno float [[MUL_I]], [[MUL_I]] +// FULL_FAST-NEXT: br i1 [[ISNAN_CMP1]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]] +// FULL_FAST: complex_mul_libcall: +// FULL_FAST-NEXT: [[CALL:%.*]] = call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) <2 x float> @__mulsc3(float noundef nofpclass(nan inf) [[A_REAL]], float noundef nofpclass(nan inf) [[A_IMAG]], float noundef nofpclass(nan inf) [[B_REAL]], float noundef nofpclass(nan inf) [[B_IMAG]]) #[[ATTR2]] +// FULL_FAST-NEXT: store <2 x float> [[CALL]], ptr [[COERCE]], align 4 +// FULL_FAST-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 0 +// FULL_FAST-NEXT: [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4 +// FULL_FAST-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 1 +// FULL_FAST-NEXT: [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4 +// FULL_FAST-NEXT: br label [[COMPLEX_MUL_CONT]] +// FULL_FAST: complex_mul_cont: +// FULL_FAST-NEXT: [[REAL_MUL_PHI:%.*]] = phi reassoc nnan ninf nsz arcp afn float [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_REAL]], [[COMPLEX_MUL_LIBCALL]] ] +// FULL_FAST-NEXT: [[IMAG_MUL_PHI:%.*]] = phi reassoc nnan ninf nsz arcp afn float [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_IMAG]], [[COMPLEX_MUL_LIBCALL]] ] +// FULL_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// FULL_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// FULL_FAST-NEXT: store float [[REAL_MUL_PHI]], ptr [[RETVAL_REALP]], align 4 +// FULL_FAST-NEXT: store float [[IMAG_MUL_PHI]], ptr [[RETVAL_IMAGP]], align 4 +// FULL_FAST-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// FULL_FAST-NEXT: ret <2 x float> [[TMP0]] +// +// IMPRVD_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x float> @mulf( +// IMPRVD_FAST-SAME: <2 x float> noundef nofpclass(nan inf) [[A_COERCE:%.*]], <2 x float> noundef nofpclass(nan inf) [[B_COERCE:%.*]]) #[[ATTR0]] { +// IMPRVD_FAST-NEXT: entry: +// IMPRVD_FAST-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// IMPRVD_FAST-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// IMPRVD_FAST-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// IMPRVD_FAST-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// IMPRVD_FAST-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4 +// IMPRVD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// IMPRVD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// IMPRVD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// IMPRVD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// IMPRVD_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_REAL]], [[B_REAL]] +// IMPRVD_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_IMAG]], [[B_IMAG]] +// IMPRVD_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_REAL]], [[B_IMAG]] +// IMPRVD_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_IMAG]], [[B_REAL]] +// IMPRVD_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[MUL_AC]], [[MUL_BD]] +// IMPRVD_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[MUL_AD]], [[MUL_BC]] +// IMPRVD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: store float [[MUL_R]], ptr [[RETVAL_REALP]], align 4 +// IMPRVD_FAST-NEXT: store float [[MUL_I]], ptr [[RETVAL_IMAGP]], align 4 +// IMPRVD_FAST-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// IMPRVD_FAST-NEXT: ret <2 x float> [[TMP0]] +// +// PRMTD_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x float> @mulf( +// PRMTD_FAST-SAME: <2 x float> noundef nofpclass(nan inf) [[A_COERCE:%.*]], <2 x float> noundef nofpclass(nan inf) [[B_COERCE:%.*]]) #[[ATTR0]] { +// PRMTD_FAST-NEXT: entry: +// PRMTD_FAST-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// PRMTD_FAST-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// PRMTD_FAST-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// PRMTD_FAST-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// PRMTD_FAST-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4 +// PRMTD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// PRMTD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// PRMTD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// PRMTD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// PRMTD_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_REAL]], [[B_REAL]] +// PRMTD_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_IMAG]], [[B_IMAG]] +// PRMTD_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_REAL]], [[B_IMAG]] +// PRMTD_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_IMAG]], [[B_REAL]] +// PRMTD_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[MUL_AC]], [[MUL_BD]] +// PRMTD_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[MUL_AD]], [[MUL_BC]] +// PRMTD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD_FAST-NEXT: store float [[MUL_R]], ptr [[RETVAL_REALP]], align 4 +// PRMTD_FAST-NEXT: store float [[MUL_I]], ptr [[RETVAL_IMAGP]], align 4 +// PRMTD_FAST-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// PRMTD_FAST-NEXT: ret <2 x float> [[TMP0]] +// +_Complex float mulf(_Complex float a, _Complex float b) { + return a * b; +} +// FULL-LABEL: define dso_local { double, double } @divd( +// FULL-SAME: double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]]) #[[ATTR1:[0-9]+]] { +// FULL-NEXT: entry: +// FULL-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// FULL-NEXT: [[A:%.*]] = alloca { double, double }, align 8 +// FULL-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// FULL-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// FULL-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// FULL-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// FULL-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// FULL-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// FULL-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// FULL-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// FULL-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// FULL-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// FULL-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// FULL-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// FULL-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// FULL-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// FULL-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// FULL-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// FULL-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// FULL-NEXT: [[CALL:%.*]] = call { double, double } @__divdc3(double noundef [[A_REAL]], double noundef [[A_IMAG]], double noundef [[B_REAL]], double noundef [[B_IMAG]]) #[[ATTR2]] +// FULL-NEXT: [[TMP4:%.*]] = extractvalue { double, double } [[CALL]], 0 +// FULL-NEXT: [[TMP5:%.*]] = extractvalue { double, double } [[CALL]], 1 +// FULL-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// FULL-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// FULL-NEXT: store double [[TMP4]], ptr [[RETVAL_REALP]], align 8 +// FULL-NEXT: store double [[TMP5]], ptr [[RETVAL_IMAGP]], align 8 +// FULL-NEXT: [[TMP6:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 +// FULL-NEXT: ret { double, double } [[TMP6]] +// +// BASIC-LABEL: define dso_local { double, double } @divd( +// BASIC-SAME: double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]]) #[[ATTR1:[0-9]+]] { +// BASIC-NEXT: entry: +// BASIC-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// BASIC-NEXT: [[A:%.*]] = alloca { double, double }, align 8 +// BASIC-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// BASIC-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// BASIC-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// BASIC-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// BASIC-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// BASIC-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// BASIC-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// BASIC-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// BASIC-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// BASIC-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// BASIC-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// BASIC-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// BASIC-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// BASIC-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// BASIC-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// BASIC-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// BASIC-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// BASIC-NEXT: [[TMP4:%.*]] = fmul double [[A_REAL]], [[B_REAL]] +// BASIC-NEXT: [[TMP5:%.*]] = fmul double [[A_IMAG]], [[B_IMAG]] +// BASIC-NEXT: [[TMP6:%.*]] = fadd double [[TMP4]], [[TMP5]] +// BASIC-NEXT: [[TMP7:%.*]] = fmul double [[B_REAL]], [[B_REAL]] +// BASIC-NEXT: [[TMP8:%.*]] = fmul double [[B_IMAG]], [[B_IMAG]] +// BASIC-NEXT: [[TMP9:%.*]] = fadd double [[TMP7]], [[TMP8]] +// BASIC-NEXT: [[TMP10:%.*]] = fmul double [[A_IMAG]], [[B_REAL]] +// BASIC-NEXT: [[TMP11:%.*]] = fmul double [[A_REAL]], [[B_IMAG]] +// BASIC-NEXT: [[TMP12:%.*]] = fsub double [[TMP10]], [[TMP11]] +// BASIC-NEXT: [[TMP13:%.*]] = fdiv double [[TMP6]], [[TMP9]] +// BASIC-NEXT: [[TMP14:%.*]] = fdiv double [[TMP12]], [[TMP9]] +// BASIC-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC-NEXT: store double [[TMP13]], ptr [[RETVAL_REALP]], align 8 +// BASIC-NEXT: store double [[TMP14]], ptr [[RETVAL_IMAGP]], align 8 +// BASIC-NEXT: [[TMP15:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 +// BASIC-NEXT: ret { double, double } [[TMP15]] +// +// IMPRVD-LABEL: define dso_local { double, double } @divd( +// IMPRVD-SAME: double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]]) #[[ATTR2:[0-9]+]] { +// IMPRVD-NEXT: entry: +// IMPRVD-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// IMPRVD-NEXT: [[A:%.*]] = alloca { double, double }, align 8 +// IMPRVD-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// IMPRVD-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// IMPRVD-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// IMPRVD-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// IMPRVD-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// IMPRVD-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// IMPRVD-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// IMPRVD-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// IMPRVD-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// IMPRVD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// IMPRVD-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// IMPRVD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// IMPRVD-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// IMPRVD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// IMPRVD-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// IMPRVD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// IMPRVD-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// IMPRVD-NEXT: [[TMP4:%.*]] = call double @llvm.fabs.f64(double [[B_REAL]]) +// IMPRVD-NEXT: [[TMP5:%.*]] = call double @llvm.fabs.f64(double [[B_IMAG]]) +// IMPRVD-NEXT: [[ABS_CMP:%.*]] = fcmp ugt double [[TMP4]], [[TMP5]] +// IMPRVD-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// IMPRVD: abs_rhsr_greater_or_equal_abs_rhsi: +// IMPRVD-NEXT: [[TMP6:%.*]] = fdiv double [[B_IMAG]], [[B_REAL]] +// IMPRVD-NEXT: [[TMP7:%.*]] = fmul double [[TMP6]], [[B_IMAG]] +// IMPRVD-NEXT: [[TMP8:%.*]] = fadd double [[B_REAL]], [[TMP7]] +// IMPRVD-NEXT: [[TMP9:%.*]] = fmul double [[A_IMAG]], [[TMP6]] +// IMPRVD-NEXT: [[TMP10:%.*]] = fadd double [[A_REAL]], [[TMP9]] +// IMPRVD-NEXT: [[TMP11:%.*]] = fdiv double [[TMP10]], [[TMP8]] +// IMPRVD-NEXT: [[TMP12:%.*]] = fmul double [[A_REAL]], [[TMP6]] +// IMPRVD-NEXT: [[TMP13:%.*]] = fsub double [[A_IMAG]], [[TMP12]] +// IMPRVD-NEXT: [[TMP14:%.*]] = fdiv double [[TMP13]], [[TMP8]] +// IMPRVD-NEXT: br label [[COMPLEX_DIV:%.*]] +// IMPRVD: abs_rhsr_less_than_abs_rhsi: +// IMPRVD-NEXT: [[TMP15:%.*]] = fdiv double [[B_REAL]], [[B_IMAG]] +// IMPRVD-NEXT: [[TMP16:%.*]] = fmul double [[TMP15]], [[B_REAL]] +// IMPRVD-NEXT: [[TMP17:%.*]] = fadd double [[B_IMAG]], [[TMP16]] +// IMPRVD-NEXT: [[TMP18:%.*]] = fmul double [[A_REAL]], [[TMP15]] +// IMPRVD-NEXT: [[TMP19:%.*]] = fadd double [[TMP18]], [[A_IMAG]] +// IMPRVD-NEXT: [[TMP20:%.*]] = fdiv double [[TMP19]], [[TMP17]] +// IMPRVD-NEXT: [[TMP21:%.*]] = fmul double [[A_IMAG]], [[TMP15]] +// IMPRVD-NEXT: [[TMP22:%.*]] = fsub double [[TMP21]], [[A_REAL]] +// IMPRVD-NEXT: [[TMP23:%.*]] = fdiv double [[TMP22]], [[TMP17]] +// IMPRVD-NEXT: br label [[COMPLEX_DIV]] +// IMPRVD: complex_div: +// IMPRVD-NEXT: [[TMP24:%.*]] = phi double [ [[TMP11]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP20]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD-NEXT: [[TMP25:%.*]] = phi double [ [[TMP14]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP23]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD-NEXT: store double [[TMP24]], ptr [[RETVAL_REALP]], align 8 +// IMPRVD-NEXT: store double [[TMP25]], ptr [[RETVAL_IMAGP]], align 8 +// IMPRVD-NEXT: [[TMP26:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 +// IMPRVD-NEXT: ret { double, double } [[TMP26]] +// +// PRMTD-LABEL: define dso_local { double, double } @divd( +// PRMTD-SAME: double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]]) #[[ATTR1:[0-9]+]] { +// PRMTD-NEXT: entry: +// PRMTD-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// PRMTD-NEXT: [[A:%.*]] = alloca { double, double }, align 8 +// PRMTD-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// PRMTD-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// PRMTD-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// PRMTD-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// PRMTD-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// PRMTD-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// PRMTD-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// PRMTD-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// PRMTD-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// PRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// PRMTD-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// PRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// PRMTD-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// PRMTD-NEXT: [[EXT:%.*]] = fpext double [[A_REAL]] to x86_fp80 +// PRMTD-NEXT: [[EXT1:%.*]] = fpext double [[A_IMAG]] to x86_fp80 +// PRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// PRMTD-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// PRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// PRMTD-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// PRMTD-NEXT: [[EXT2:%.*]] = fpext double [[B_REAL]] to x86_fp80 +// PRMTD-NEXT: [[EXT3:%.*]] = fpext double [[B_IMAG]] to x86_fp80 +// PRMTD-NEXT: [[TMP4:%.*]] = fmul x86_fp80 [[EXT]], [[EXT2]] +// PRMTD-NEXT: [[TMP5:%.*]] = fmul x86_fp80 [[EXT1]], [[EXT3]] +// PRMTD-NEXT: [[TMP6:%.*]] = fadd x86_fp80 [[TMP4]], [[TMP5]] +// PRMTD-NEXT: [[TMP7:%.*]] = fmul x86_fp80 [[EXT2]], [[EXT2]] +// PRMTD-NEXT: [[TMP8:%.*]] = fmul x86_fp80 [[EXT3]], [[EXT3]] +// PRMTD-NEXT: [[TMP9:%.*]] = fadd x86_fp80 [[TMP7]], [[TMP8]] +// PRMTD-NEXT: [[TMP10:%.*]] = fmul x86_fp80 [[EXT1]], [[EXT2]] +// PRMTD-NEXT: [[TMP11:%.*]] = fmul x86_fp80 [[EXT]], [[EXT3]] +// PRMTD-NEXT: [[TMP12:%.*]] = fsub x86_fp80 [[TMP10]], [[TMP11]] +// PRMTD-NEXT: [[TMP13:%.*]] = fdiv x86_fp80 [[TMP6]], [[TMP9]] +// PRMTD-NEXT: [[TMP14:%.*]] = fdiv x86_fp80 [[TMP12]], [[TMP9]] +// PRMTD-NEXT: [[UNPROMOTION:%.*]] = fptrunc x86_fp80 [[TMP13]] to double +// PRMTD-NEXT: [[UNPROMOTION4:%.*]] = fptrunc x86_fp80 [[TMP14]] to double +// PRMTD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD-NEXT: store double [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 8 +// PRMTD-NEXT: store double [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 8 +// PRMTD-NEXT: [[TMP15:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 +// PRMTD-NEXT: ret { double, double } [[TMP15]] +// +// 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-NEXT: entry: +// X86WINPRMTD-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 8 +// X86WINPRMTD-NEXT: [[B_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// X86WINPRMTD-NEXT: [[A_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// X86WINPRMTD-NEXT: store ptr [[AGG_RESULT]], ptr [[RESULT_PTR]], align 8 +// X86WINPRMTD-NEXT: store ptr [[B]], ptr [[B_INDIRECT_ADDR]], align 8 +// X86WINPRMTD-NEXT: store ptr [[A]], ptr [[A_INDIRECT_ADDR]], align 8 +// X86WINPRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// X86WINPRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// X86WINPRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// X86WINPRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// X86WINPRMTD-NEXT: [[TMP0:%.*]] = call double @llvm.fabs.f64(double [[B_REAL]]) +// X86WINPRMTD-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[B_IMAG]]) +// X86WINPRMTD-NEXT: [[ABS_CMP:%.*]] = fcmp ugt double [[TMP0]], [[TMP1]] +// X86WINPRMTD-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// X86WINPRMTD: abs_rhsr_greater_or_equal_abs_rhsi: +// X86WINPRMTD-NEXT: [[TMP2:%.*]] = fdiv double [[B_IMAG]], [[B_REAL]] +// X86WINPRMTD-NEXT: [[TMP3:%.*]] = fmul double [[TMP2]], [[B_IMAG]] +// X86WINPRMTD-NEXT: [[TMP4:%.*]] = fadd double [[B_REAL]], [[TMP3]] +// X86WINPRMTD-NEXT: [[TMP5:%.*]] = fmul double [[A_IMAG]], [[TMP2]] +// X86WINPRMTD-NEXT: [[TMP6:%.*]] = fadd double [[A_REAL]], [[TMP5]] +// X86WINPRMTD-NEXT: [[TMP7:%.*]] = fdiv double [[TMP6]], [[TMP4]] +// X86WINPRMTD-NEXT: [[TMP8:%.*]] = fmul double [[A_REAL]], [[TMP2]] +// X86WINPRMTD-NEXT: [[TMP9:%.*]] = fsub double [[A_IMAG]], [[TMP8]] +// X86WINPRMTD-NEXT: [[TMP10:%.*]] = fdiv double [[TMP9]], [[TMP4]] +// X86WINPRMTD-NEXT: br label [[COMPLEX_DIV:%.*]] +// X86WINPRMTD: abs_rhsr_less_than_abs_rhsi: +// X86WINPRMTD-NEXT: [[TMP11:%.*]] = fdiv double [[B_REAL]], [[B_IMAG]] +// X86WINPRMTD-NEXT: [[TMP12:%.*]] = fmul double [[TMP11]], [[B_REAL]] +// X86WINPRMTD-NEXT: [[TMP13:%.*]] = fadd double [[B_IMAG]], [[TMP12]] +// X86WINPRMTD-NEXT: [[TMP14:%.*]] = fmul double [[A_REAL]], [[TMP11]] +// X86WINPRMTD-NEXT: [[TMP15:%.*]] = fadd double [[TMP14]], [[A_IMAG]] +// X86WINPRMTD-NEXT: [[TMP16:%.*]] = fdiv double [[TMP15]], [[TMP13]] +// X86WINPRMTD-NEXT: [[TMP17:%.*]] = fmul double [[A_IMAG]], [[TMP11]] +// X86WINPRMTD-NEXT: [[TMP18:%.*]] = fsub double [[TMP17]], [[A_REAL]] +// X86WINPRMTD-NEXT: [[TMP19:%.*]] = fdiv double [[TMP18]], [[TMP13]] +// X86WINPRMTD-NEXT: br label [[COMPLEX_DIV]] +// X86WINPRMTD: complex_div: +// X86WINPRMTD-NEXT: [[TMP20:%.*]] = phi double [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// X86WINPRMTD-NEXT: [[TMP21:%.*]] = phi double [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// X86WINPRMTD-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// X86WINPRMTD-NEXT: store double [[TMP20]], ptr [[AGG_RESULT_REALP]], align 8 +// X86WINPRMTD-NEXT: store double [[TMP21]], ptr [[AGG_RESULT_IMAGP]], align 8 +// X86WINPRMTD-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[AGG_RESULT_REAL:%.*]] = load double, ptr [[AGG_RESULT_REALP1]], align 8 +// X86WINPRMTD-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[AGG_RESULT_IMAG:%.*]] = load double, ptr [[AGG_RESULT_IMAGP2]], align 8 +// X86WINPRMTD-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// X86WINPRMTD-NEXT: store double [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 8 +// X86WINPRMTD-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 8 +// X86WINPRMTD-NEXT: ret void +// +// AVRFP32-LABEL: define dso_local { float, float } @divd( +// AVRFP32-SAME: float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]], float noundef [[B_COERCE0:%.*]], float noundef [[B_COERCE1:%.*]]) addrspace(1) #[[ATTR0]] { +// AVRFP32-NEXT: entry: +// AVRFP32-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// AVRFP32-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// AVRFP32-NEXT: [[TMP0:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP32-NEXT: store float [[A_COERCE0]], ptr [[TMP0]], align 4 +// AVRFP32-NEXT: [[TMP1:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[A_COERCE1]], ptr [[TMP1]], align 4 +// AVRFP32-NEXT: [[TMP2:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// AVRFP32-NEXT: store float [[B_COERCE0]], ptr [[TMP2]], align 4 +// AVRFP32-NEXT: [[TMP3:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[B_COERCE1]], ptr [[TMP3]], align 4 +// AVRFP32-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP32-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// AVRFP32-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP32-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// AVRFP32-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// AVRFP32-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// AVRFP32-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// AVRFP32-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// AVRFP32-NEXT: [[TMP4:%.*]] = call addrspace(1) float @llvm.fabs.f32(float [[B_REAL]]) +// AVRFP32-NEXT: [[TMP5:%.*]] = call addrspace(1) float @llvm.fabs.f32(float [[B_IMAG]]) +// AVRFP32-NEXT: [[ABS_CMP:%.*]] = fcmp ugt float [[TMP4]], [[TMP5]] +// AVRFP32-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// AVRFP32: abs_rhsr_greater_or_equal_abs_rhsi: +// AVRFP32-NEXT: [[TMP6:%.*]] = fdiv float [[B_IMAG]], [[B_REAL]] +// AVRFP32-NEXT: [[TMP7:%.*]] = fmul float [[TMP6]], [[B_IMAG]] +// AVRFP32-NEXT: [[TMP8:%.*]] = fadd float [[B_REAL]], [[TMP7]] +// AVRFP32-NEXT: [[TMP9:%.*]] = fmul float [[A_IMAG]], [[TMP6]] +// AVRFP32-NEXT: [[TMP10:%.*]] = fadd float [[A_REAL]], [[TMP9]] +// AVRFP32-NEXT: [[TMP11:%.*]] = fdiv float [[TMP10]], [[TMP8]] +// AVRFP32-NEXT: [[TMP12:%.*]] = fmul float [[A_REAL]], [[TMP6]] +// AVRFP32-NEXT: [[TMP13:%.*]] = fsub float [[A_IMAG]], [[TMP12]] +// AVRFP32-NEXT: [[TMP14:%.*]] = fdiv float [[TMP13]], [[TMP8]] +// AVRFP32-NEXT: br label [[COMPLEX_DIV:%.*]] +// AVRFP32: abs_rhsr_less_than_abs_rhsi: +// AVRFP32-NEXT: [[TMP15:%.*]] = fdiv float [[B_REAL]], [[B_IMAG]] +// AVRFP32-NEXT: [[TMP16:%.*]] = fmul float [[TMP15]], [[B_REAL]] +// AVRFP32-NEXT: [[TMP17:%.*]] = fadd float [[B_IMAG]], [[TMP16]] +// AVRFP32-NEXT: [[TMP18:%.*]] = fmul float [[A_REAL]], [[TMP15]] +// AVRFP32-NEXT: [[TMP19:%.*]] = fadd float [[TMP18]], [[A_IMAG]] +// AVRFP32-NEXT: [[TMP20:%.*]] = fdiv float [[TMP19]], [[TMP17]] +// AVRFP32-NEXT: [[TMP21:%.*]] = fmul float [[A_IMAG]], [[TMP15]] +// AVRFP32-NEXT: [[TMP22:%.*]] = fsub float [[TMP21]], [[A_REAL]] +// AVRFP32-NEXT: [[TMP23:%.*]] = fdiv float [[TMP22]], [[TMP17]] +// AVRFP32-NEXT: br label [[COMPLEX_DIV]] +// AVRFP32: complex_div: +// AVRFP32-NEXT: [[TMP24:%.*]] = phi float [ [[TMP11]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP20]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// AVRFP32-NEXT: [[TMP25:%.*]] = phi float [ [[TMP14]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP23]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// AVRFP32-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// AVRFP32-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[TMP24]], ptr [[RETVAL_REALP]], align 1 +// AVRFP32-NEXT: store float [[TMP25]], ptr [[RETVAL_IMAGP]], align 1 +// AVRFP32-NEXT: [[TMP26:%.*]] = load { float, float }, ptr [[RETVAL]], align 1 +// AVRFP32-NEXT: ret { float, float } [[TMP26]] +// +// AVRFP64-LABEL: define dso_local void @divd( +// AVRFP64-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 1 [[AGG_RESULT:%.*]], double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]]) addrspace(1) #[[ATTR0]] { +// AVRFP64-NEXT: entry: +// AVRFP64-NEXT: [[A:%.*]] = alloca { double, double }, align 8 +// AVRFP64-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// AVRFP64-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// AVRFP64-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// AVRFP64-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// AVRFP64-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// AVRFP64-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// AVRFP64-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// AVRFP64-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// AVRFP64-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// AVRFP64-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// AVRFP64-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// AVRFP64-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// AVRFP64-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// AVRFP64-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// AVRFP64-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// AVRFP64-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// AVRFP64-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// AVRFP64-NEXT: [[TMP4:%.*]] = call addrspace(1) double @llvm.fabs.f64(double [[B_REAL]]) +// AVRFP64-NEXT: [[TMP5:%.*]] = call addrspace(1) double @llvm.fabs.f64(double [[B_IMAG]]) +// AVRFP64-NEXT: [[ABS_CMP:%.*]] = fcmp ugt double [[TMP4]], [[TMP5]] +// AVRFP64-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// AVRFP64: abs_rhsr_greater_or_equal_abs_rhsi: +// AVRFP64-NEXT: [[TMP6:%.*]] = fdiv double [[B_IMAG]], [[B_REAL]] +// AVRFP64-NEXT: [[TMP7:%.*]] = fmul double [[TMP6]], [[B_IMAG]] +// AVRFP64-NEXT: [[TMP8:%.*]] = fadd double [[B_REAL]], [[TMP7]] +// AVRFP64-NEXT: [[TMP9:%.*]] = fmul double [[A_IMAG]], [[TMP6]] +// AVRFP64-NEXT: [[TMP10:%.*]] = fadd double [[A_REAL]], [[TMP9]] +// AVRFP64-NEXT: [[TMP11:%.*]] = fdiv double [[TMP10]], [[TMP8]] +// AVRFP64-NEXT: [[TMP12:%.*]] = fmul double [[A_REAL]], [[TMP6]] +// AVRFP64-NEXT: [[TMP13:%.*]] = fsub double [[A_IMAG]], [[TMP12]] +// AVRFP64-NEXT: [[TMP14:%.*]] = fdiv double [[TMP13]], [[TMP8]] +// AVRFP64-NEXT: br label [[COMPLEX_DIV:%.*]] +// AVRFP64: abs_rhsr_less_than_abs_rhsi: +// AVRFP64-NEXT: [[TMP15:%.*]] = fdiv double [[B_REAL]], [[B_IMAG]] +// AVRFP64-NEXT: [[TMP16:%.*]] = fmul double [[TMP15]], [[B_REAL]] +// AVRFP64-NEXT: [[TMP17:%.*]] = fadd double [[B_IMAG]], [[TMP16]] +// AVRFP64-NEXT: [[TMP18:%.*]] = fmul double [[A_REAL]], [[TMP15]] +// AVRFP64-NEXT: [[TMP19:%.*]] = fadd double [[TMP18]], [[A_IMAG]] +// AVRFP64-NEXT: [[TMP20:%.*]] = fdiv double [[TMP19]], [[TMP17]] +// AVRFP64-NEXT: [[TMP21:%.*]] = fmul double [[A_IMAG]], [[TMP15]] +// AVRFP64-NEXT: [[TMP22:%.*]] = fsub double [[TMP21]], [[A_REAL]] +// AVRFP64-NEXT: [[TMP23:%.*]] = fdiv double [[TMP22]], [[TMP17]] +// AVRFP64-NEXT: br label [[COMPLEX_DIV]] +// AVRFP64: complex_div: +// AVRFP64-NEXT: [[TMP24:%.*]] = phi double [ [[TMP11]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP20]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// AVRFP64-NEXT: [[TMP25:%.*]] = phi double [ [[TMP14]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP23]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// AVRFP64-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// AVRFP64-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// AVRFP64-NEXT: store double [[TMP24]], ptr [[AGG_RESULT_REALP]], align 1 +// AVRFP64-NEXT: store double [[TMP25]], ptr [[AGG_RESULT_IMAGP]], align 1 +// AVRFP64-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// AVRFP64-NEXT: [[AGG_RESULT_REAL:%.*]] = load double, ptr [[AGG_RESULT_REALP1]], align 1 +// AVRFP64-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// AVRFP64-NEXT: [[AGG_RESULT_IMAG:%.*]] = load double, ptr [[AGG_RESULT_IMAGP2]], align 1 +// AVRFP64-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// AVRFP64-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// AVRFP64-NEXT: store double [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 1 +// AVRFP64-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 1 +// AVRFP64-NEXT: ret void +// +// BASIC_FAST-LABEL: define dso_local { double, double } @divd( +// BASIC_FAST-SAME: double noundef nofpclass(nan inf) [[A_COERCE0:%.*]], double noundef nofpclass(nan inf) [[A_COERCE1:%.*]], double noundef nofpclass(nan inf) [[B_COERCE0:%.*]], double noundef nofpclass(nan inf) [[B_COERCE1:%.*]]) #[[ATTR1:[0-9]+]] { +// BASIC_FAST-NEXT: entry: +// BASIC_FAST-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// BASIC_FAST-NEXT: [[A:%.*]] = alloca { double, double }, align 8 +// BASIC_FAST-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// BASIC_FAST-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// BASIC_FAST-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// BASIC_FAST-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// BASIC_FAST-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// BASIC_FAST-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// BASIC_FAST-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// BASIC_FAST-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// BASIC_FAST-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// BASIC_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// BASIC_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// BASIC_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// BASIC_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// BASIC_FAST-NEXT: [[TMP4:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_REAL]], [[B_REAL]] +// BASIC_FAST-NEXT: [[TMP5:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_IMAG]], [[B_IMAG]] +// BASIC_FAST-NEXT: [[TMP6:%.*]] = fadd reassoc nnan ninf nsz arcp afn double [[TMP4]], [[TMP5]] +// BASIC_FAST-NEXT: [[TMP7:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[B_REAL]], [[B_REAL]] +// BASIC_FAST-NEXT: [[TMP8:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[B_IMAG]], [[B_IMAG]] +// BASIC_FAST-NEXT: [[TMP9:%.*]] = fadd reassoc nnan ninf nsz arcp afn double [[TMP7]], [[TMP8]] +// BASIC_FAST-NEXT: [[TMP10:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_IMAG]], [[B_REAL]] +// BASIC_FAST-NEXT: [[TMP11:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_REAL]], [[B_IMAG]] +// BASIC_FAST-NEXT: [[TMP12:%.*]] = fsub reassoc nnan ninf nsz arcp afn double [[TMP10]], [[TMP11]] +// BASIC_FAST-NEXT: [[TMP13:%.*]] = fdiv reassoc nnan ninf nsz arcp afn double [[TMP6]], [[TMP9]] +// BASIC_FAST-NEXT: [[TMP14:%.*]] = fdiv reassoc nnan ninf nsz arcp afn double [[TMP12]], [[TMP9]] +// BASIC_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC_FAST-NEXT: store double [[TMP13]], ptr [[RETVAL_REALP]], align 8 +// BASIC_FAST-NEXT: store double [[TMP14]], ptr [[RETVAL_IMAGP]], align 8 +// BASIC_FAST-NEXT: [[TMP15:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 +// BASIC_FAST-NEXT: ret { double, double } [[TMP15]] +// +// FULL_FAST-LABEL: define dso_local { double, double } @divd( +// FULL_FAST-SAME: double noundef nofpclass(nan inf) [[A_COERCE0:%.*]], double noundef nofpclass(nan inf) [[A_COERCE1:%.*]], double noundef nofpclass(nan inf) [[B_COERCE0:%.*]], double noundef nofpclass(nan inf) [[B_COERCE1:%.*]]) #[[ATTR1:[0-9]+]] { +// FULL_FAST-NEXT: entry: +// FULL_FAST-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// FULL_FAST-NEXT: [[A:%.*]] = alloca { double, double }, align 8 +// FULL_FAST-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// FULL_FAST-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// FULL_FAST-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// FULL_FAST-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// FULL_FAST-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// FULL_FAST-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// FULL_FAST-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// FULL_FAST-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// FULL_FAST-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// FULL_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// FULL_FAST-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// FULL_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// FULL_FAST-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// FULL_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// FULL_FAST-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// FULL_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// FULL_FAST-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// FULL_FAST-NEXT: [[CALL:%.*]] = call { double, double } @__divdc3(double noundef nofpclass(nan inf) [[A_REAL]], double noundef nofpclass(nan inf) [[A_IMAG]], double noundef nofpclass(nan inf) [[B_REAL]], double noundef nofpclass(nan inf) [[B_IMAG]]) #[[ATTR2]] +// FULL_FAST-NEXT: [[TMP4:%.*]] = extractvalue { double, double } [[CALL]], 0 +// FULL_FAST-NEXT: [[TMP5:%.*]] = extractvalue { double, double } [[CALL]], 1 +// FULL_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// FULL_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// FULL_FAST-NEXT: store double [[TMP4]], ptr [[RETVAL_REALP]], align 8 +// FULL_FAST-NEXT: store double [[TMP5]], ptr [[RETVAL_IMAGP]], align 8 +// FULL_FAST-NEXT: [[TMP6:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 +// FULL_FAST-NEXT: ret { double, double } [[TMP6]] +// +// IMPRVD_FAST-LABEL: define dso_local { double, double } @divd( +// IMPRVD_FAST-SAME: double noundef nofpclass(nan inf) [[A_COERCE0:%.*]], double noundef nofpclass(nan inf) [[A_COERCE1:%.*]], double noundef nofpclass(nan inf) [[B_COERCE0:%.*]], double noundef nofpclass(nan inf) [[B_COERCE1:%.*]]) #[[ATTR2:[0-9]+]] { +// IMPRVD_FAST-NEXT: entry: +// IMPRVD_FAST-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// IMPRVD_FAST-NEXT: [[A:%.*]] = alloca { double, double }, align 8 +// IMPRVD_FAST-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// IMPRVD_FAST-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// IMPRVD_FAST-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// IMPRVD_FAST-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// IMPRVD_FAST-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// IMPRVD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// IMPRVD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// IMPRVD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// IMPRVD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// IMPRVD_FAST-NEXT: [[TMP4:%.*]] = call reassoc nnan ninf nsz arcp afn double @llvm.fabs.f64(double [[B_REAL]]) +// IMPRVD_FAST-NEXT: [[TMP5:%.*]] = call reassoc nnan ninf nsz arcp afn double @llvm.fabs.f64(double [[B_IMAG]]) +// IMPRVD_FAST-NEXT: [[ABS_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn ugt double [[TMP4]], [[TMP5]] +// IMPRVD_FAST-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// IMPRVD_FAST: abs_rhsr_greater_or_equal_abs_rhsi: +// IMPRVD_FAST-NEXT: [[TMP6:%.*]] = fdiv reassoc nnan ninf nsz arcp afn double [[B_IMAG]], [[B_REAL]] +// IMPRVD_FAST-NEXT: [[TMP7:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[TMP6]], [[B_IMAG]] +// IMPRVD_FAST-NEXT: [[TMP8:%.*]] = fadd reassoc nnan ninf nsz arcp afn double [[B_REAL]], [[TMP7]] +// IMPRVD_FAST-NEXT: [[TMP9:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_IMAG]], [[TMP6]] +// IMPRVD_FAST-NEXT: [[TMP10:%.*]] = fadd reassoc nnan ninf nsz arcp afn double [[A_REAL]], [[TMP9]] +// IMPRVD_FAST-NEXT: [[TMP11:%.*]] = fdiv reassoc nnan ninf nsz arcp afn double [[TMP10]], [[TMP8]] +// IMPRVD_FAST-NEXT: [[TMP12:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_REAL]], [[TMP6]] +// IMPRVD_FAST-NEXT: [[TMP13:%.*]] = fsub reassoc nnan ninf nsz arcp afn double [[A_IMAG]], [[TMP12]] +// IMPRVD_FAST-NEXT: [[TMP14:%.*]] = fdiv reassoc nnan ninf nsz arcp afn double [[TMP13]], [[TMP8]] +// IMPRVD_FAST-NEXT: br label [[COMPLEX_DIV:%.*]] +// IMPRVD_FAST: abs_rhsr_less_than_abs_rhsi: +// IMPRVD_FAST-NEXT: [[TMP15:%.*]] = fdiv reassoc nnan ninf nsz arcp afn double [[B_REAL]], [[B_IMAG]] +// IMPRVD_FAST-NEXT: [[TMP16:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[TMP15]], [[B_REAL]] +// IMPRVD_FAST-NEXT: [[TMP17:%.*]] = fadd reassoc nnan ninf nsz arcp afn double [[B_IMAG]], [[TMP16]] +// IMPRVD_FAST-NEXT: [[TMP18:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_REAL]], [[TMP15]] +// IMPRVD_FAST-NEXT: [[TMP19:%.*]] = fadd reassoc nnan ninf nsz arcp afn double [[TMP18]], [[A_IMAG]] +// IMPRVD_FAST-NEXT: [[TMP20:%.*]] = fdiv reassoc nnan ninf nsz arcp afn double [[TMP19]], [[TMP17]] +// IMPRVD_FAST-NEXT: [[TMP21:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_IMAG]], [[TMP15]] +// IMPRVD_FAST-NEXT: [[TMP22:%.*]] = fsub reassoc nnan ninf nsz arcp afn double [[TMP21]], [[A_REAL]] +// IMPRVD_FAST-NEXT: [[TMP23:%.*]] = fdiv reassoc nnan ninf nsz arcp afn double [[TMP22]], [[TMP17]] +// IMPRVD_FAST-NEXT: br label [[COMPLEX_DIV]] +// IMPRVD_FAST: complex_div: +// IMPRVD_FAST-NEXT: [[TMP24:%.*]] = phi reassoc nnan ninf nsz arcp afn double [ [[TMP11]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP20]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD_FAST-NEXT: [[TMP25:%.*]] = phi reassoc nnan ninf nsz arcp afn double [ [[TMP14]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP23]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: store double [[TMP24]], ptr [[RETVAL_REALP]], align 8 +// IMPRVD_FAST-NEXT: store double [[TMP25]], ptr [[RETVAL_IMAGP]], align 8 +// IMPRVD_FAST-NEXT: [[TMP26:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 +// IMPRVD_FAST-NEXT: ret { double, double } [[TMP26]] +// +// PRMTD_FAST-LABEL: define dso_local { double, double } @divd( +// PRMTD_FAST-SAME: double noundef nofpclass(nan inf) [[A_COERCE0:%.*]], double noundef nofpclass(nan inf) [[A_COERCE1:%.*]], double noundef nofpclass(nan inf) [[B_COERCE0:%.*]], double noundef nofpclass(nan inf) [[B_COERCE1:%.*]]) #[[ATTR1:[0-9]+]] { +// PRMTD_FAST-NEXT: entry: +// PRMTD_FAST-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// PRMTD_FAST-NEXT: [[A:%.*]] = alloca { double, double }, align 8 +// PRMTD_FAST-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// PRMTD_FAST-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// PRMTD_FAST-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// PRMTD_FAST-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// PRMTD_FAST-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// PRMTD_FAST-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// PRMTD_FAST-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// PRMTD_FAST-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// PRMTD_FAST-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// PRMTD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// PRMTD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// PRMTD_FAST-NEXT: [[EXT:%.*]] = fpext double [[A_REAL]] to x86_fp80 +// PRMTD_FAST-NEXT: [[EXT1:%.*]] = fpext double [[A_IMAG]] to x86_fp80 +// PRMTD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// PRMTD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// PRMTD_FAST-NEXT: [[EXT2:%.*]] = fpext double [[B_REAL]] to x86_fp80 +// PRMTD_FAST-NEXT: [[EXT3:%.*]] = fpext double [[B_IMAG]] to x86_fp80 +// PRMTD_FAST-NEXT: [[TMP4:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[EXT]], [[EXT2]] +// PRMTD_FAST-NEXT: [[TMP5:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[EXT1]], [[EXT3]] +// PRMTD_FAST-NEXT: [[TMP6:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP4]], [[TMP5]] +// PRMTD_FAST-NEXT: [[TMP7:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[EXT2]], [[EXT2]] +// PRMTD_FAST-NEXT: [[TMP8:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[EXT3]], [[EXT3]] +// PRMTD_FAST-NEXT: [[TMP9:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP7]], [[TMP8]] +// PRMTD_FAST-NEXT: [[TMP10:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[EXT1]], [[EXT2]] +// PRMTD_FAST-NEXT: [[TMP11:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[EXT]], [[EXT3]] +// PRMTD_FAST-NEXT: [[TMP12:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP10]], [[TMP11]] +// PRMTD_FAST-NEXT: [[TMP13:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP6]], [[TMP9]] +// PRMTD_FAST-NEXT: [[TMP14:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP12]], [[TMP9]] +// PRMTD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc x86_fp80 [[TMP13]] to double +// PRMTD_FAST-NEXT: [[UNPROMOTION4:%.*]] = fptrunc x86_fp80 [[TMP14]] to double +// PRMTD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD_FAST-NEXT: store double [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 8 +// PRMTD_FAST-NEXT: store double [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 8 +// PRMTD_FAST-NEXT: [[TMP15:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 +// PRMTD_FAST-NEXT: ret { double, double } [[TMP15]] +// +_Complex double divd(_Complex double a, _Complex double b) { return a / b; } -_Complex float mul(_Complex float a, _Complex float b) { - // LABEL: define {{.*}} @mul( - // FULL: call {{.*}} @__mulsc3 - - // LMTD: fmul float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fsub float - // LMTD-NEXT: fadd float - - // FRTRN: fmul {{.*}}float - // FRTRN-NEXT: fmul {{.*}}float - // FRTRN-NEXT: fmul {{.*}}float - // FRTRN-NEXT: fmul {{.*}}float - // FRTRN-NEXT: fsub {{.*}}float - // FRTRN-NEXT: fadd {{.*}}float - - // LMTD-FAST: fmul {{.*}} float - // LMTD-FAST-NEXT: fmul {{.*}} float - // LMTD-FAST-NEXT: fmul {{.*}} float - // LMTD-FAST-NEXT: fmul {{.*}} float - // LMTD-FAST-NEXT: fsub {{.*}} float - // LMTD-FAST-NEXT: fadd {{.*}} float +// FULL-LABEL: define dso_local { double, double } @muld( +// FULL-SAME: double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]]) #[[ATTR1]] { +// FULL-NEXT: entry: +// FULL-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// FULL-NEXT: [[A:%.*]] = alloca { double, double }, align 8 +// FULL-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// FULL-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// FULL-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// FULL-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// FULL-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// FULL-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// FULL-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// FULL-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// FULL-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// FULL-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// FULL-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// FULL-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// FULL-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// FULL-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// FULL-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// FULL-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// FULL-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// FULL-NEXT: [[MUL_AC:%.*]] = fmul double [[A_REAL]], [[B_REAL]] +// FULL-NEXT: [[MUL_BD:%.*]] = fmul double [[A_IMAG]], [[B_IMAG]] +// FULL-NEXT: [[MUL_AD:%.*]] = fmul double [[A_REAL]], [[B_IMAG]] +// FULL-NEXT: [[MUL_BC:%.*]] = fmul double [[A_IMAG]], [[B_REAL]] +// FULL-NEXT: [[MUL_R:%.*]] = fsub double [[MUL_AC]], [[MUL_BD]] +// FULL-NEXT: [[MUL_I:%.*]] = fadd double [[MUL_AD]], [[MUL_BC]] +// FULL-NEXT: [[ISNAN_CMP:%.*]] = fcmp uno double [[MUL_R]], [[MUL_R]] +// FULL-NEXT: br i1 [[ISNAN_CMP]], label [[COMPLEX_MUL_IMAG_NAN:%.*]], label [[COMPLEX_MUL_CONT:%.*]], !prof [[PROF2]] +// FULL: complex_mul_imag_nan: +// FULL-NEXT: [[ISNAN_CMP1:%.*]] = fcmp uno double [[MUL_I]], [[MUL_I]] +// FULL-NEXT: br i1 [[ISNAN_CMP1]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]] +// FULL: complex_mul_libcall: +// FULL-NEXT: [[CALL:%.*]] = call { double, double } @__muldc3(double noundef [[A_REAL]], double noundef [[A_IMAG]], double noundef [[B_REAL]], double noundef [[B_IMAG]]) #[[ATTR2]] +// FULL-NEXT: [[TMP4:%.*]] = extractvalue { double, double } [[CALL]], 0 +// FULL-NEXT: [[TMP5:%.*]] = extractvalue { double, double } [[CALL]], 1 +// FULL-NEXT: br label [[COMPLEX_MUL_CONT]] +// FULL: complex_mul_cont: +// FULL-NEXT: [[REAL_MUL_PHI:%.*]] = phi double [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[TMP4]], [[COMPLEX_MUL_LIBCALL]] ] +// FULL-NEXT: [[IMAG_MUL_PHI:%.*]] = phi double [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[TMP5]], [[COMPLEX_MUL_LIBCALL]] ] +// FULL-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// FULL-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// FULL-NEXT: store double [[REAL_MUL_PHI]], ptr [[RETVAL_REALP]], align 8 +// FULL-NEXT: store double [[IMAG_MUL_PHI]], ptr [[RETVAL_IMAGP]], align 8 +// FULL-NEXT: [[TMP6:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 +// FULL-NEXT: ret { double, double } [[TMP6]] +// +// BASIC-LABEL: define dso_local { double, double } @muld( +// BASIC-SAME: double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]]) #[[ATTR1]] { +// BASIC-NEXT: entry: +// BASIC-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// BASIC-NEXT: [[A:%.*]] = alloca { double, double }, align 8 +// BASIC-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// BASIC-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// BASIC-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// BASIC-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// BASIC-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// BASIC-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// BASIC-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// BASIC-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// BASIC-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// BASIC-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// BASIC-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// BASIC-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// BASIC-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// BASIC-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// BASIC-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// BASIC-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// BASIC-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// BASIC-NEXT: [[MUL_AC:%.*]] = fmul double [[A_REAL]], [[B_REAL]] +// BASIC-NEXT: [[MUL_BD:%.*]] = fmul double [[A_IMAG]], [[B_IMAG]] +// BASIC-NEXT: [[MUL_AD:%.*]] = fmul double [[A_REAL]], [[B_IMAG]] +// BASIC-NEXT: [[MUL_BC:%.*]] = fmul double [[A_IMAG]], [[B_REAL]] +// BASIC-NEXT: [[MUL_R:%.*]] = fsub double [[MUL_AC]], [[MUL_BD]] +// BASIC-NEXT: [[MUL_I:%.*]] = fadd double [[MUL_AD]], [[MUL_BC]] +// BASIC-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC-NEXT: store double [[MUL_R]], ptr [[RETVAL_REALP]], align 8 +// BASIC-NEXT: store double [[MUL_I]], ptr [[RETVAL_IMAGP]], align 8 +// BASIC-NEXT: [[TMP4:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 +// BASIC-NEXT: ret { double, double } [[TMP4]] +// +// IMPRVD-LABEL: define dso_local { double, double } @muld( +// IMPRVD-SAME: double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]]) #[[ATTR2]] { +// IMPRVD-NEXT: entry: +// IMPRVD-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// IMPRVD-NEXT: [[A:%.*]] = alloca { double, double }, align 8 +// IMPRVD-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// IMPRVD-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// IMPRVD-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// IMPRVD-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// IMPRVD-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// IMPRVD-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// IMPRVD-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// IMPRVD-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// IMPRVD-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// IMPRVD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// IMPRVD-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// IMPRVD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// IMPRVD-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// IMPRVD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// IMPRVD-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// IMPRVD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// IMPRVD-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// IMPRVD-NEXT: [[MUL_AC:%.*]] = fmul double [[A_REAL]], [[B_REAL]] +// IMPRVD-NEXT: [[MUL_BD:%.*]] = fmul double [[A_IMAG]], [[B_IMAG]] +// IMPRVD-NEXT: [[MUL_AD:%.*]] = fmul double [[A_REAL]], [[B_IMAG]] +// IMPRVD-NEXT: [[MUL_BC:%.*]] = fmul double [[A_IMAG]], [[B_REAL]] +// IMPRVD-NEXT: [[MUL_R:%.*]] = fsub double [[MUL_AC]], [[MUL_BD]] +// IMPRVD-NEXT: [[MUL_I:%.*]] = fadd double [[MUL_AD]], [[MUL_BC]] +// IMPRVD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD-NEXT: store double [[MUL_R]], ptr [[RETVAL_REALP]], align 8 +// IMPRVD-NEXT: store double [[MUL_I]], ptr [[RETVAL_IMAGP]], align 8 +// IMPRVD-NEXT: [[TMP4:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 +// IMPRVD-NEXT: ret { double, double } [[TMP4]] +// +// PRMTD-LABEL: define dso_local { double, double } @muld( +// PRMTD-SAME: double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]]) #[[ATTR1]] { +// PRMTD-NEXT: entry: +// PRMTD-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// PRMTD-NEXT: [[A:%.*]] = alloca { double, double }, align 8 +// PRMTD-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// PRMTD-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// PRMTD-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// PRMTD-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// PRMTD-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// PRMTD-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// PRMTD-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// PRMTD-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// PRMTD-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// PRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// PRMTD-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// PRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// PRMTD-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// PRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// PRMTD-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// PRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// PRMTD-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// PRMTD-NEXT: [[MUL_AC:%.*]] = fmul double [[A_REAL]], [[B_REAL]] +// PRMTD-NEXT: [[MUL_BD:%.*]] = fmul double [[A_IMAG]], [[B_IMAG]] +// PRMTD-NEXT: [[MUL_AD:%.*]] = fmul double [[A_REAL]], [[B_IMAG]] +// PRMTD-NEXT: [[MUL_BC:%.*]] = fmul double [[A_IMAG]], [[B_REAL]] +// PRMTD-NEXT: [[MUL_R:%.*]] = fsub double [[MUL_AC]], [[MUL_BD]] +// PRMTD-NEXT: [[MUL_I:%.*]] = fadd double [[MUL_AD]], [[MUL_BC]] +// PRMTD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD-NEXT: store double [[MUL_R]], ptr [[RETVAL_REALP]], align 8 +// PRMTD-NEXT: store double [[MUL_I]], ptr [[RETVAL_IMAGP]], align 8 +// PRMTD-NEXT: [[TMP4:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 +// PRMTD-NEXT: ret { double, double } [[TMP4]] +// +// 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-NEXT: entry: +// X86WINPRMTD-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 8 +// X86WINPRMTD-NEXT: [[B_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// X86WINPRMTD-NEXT: [[A_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// X86WINPRMTD-NEXT: store ptr [[AGG_RESULT]], ptr [[RESULT_PTR]], align 8 +// X86WINPRMTD-NEXT: store ptr [[B]], ptr [[B_INDIRECT_ADDR]], align 8 +// X86WINPRMTD-NEXT: store ptr [[A]], ptr [[A_INDIRECT_ADDR]], align 8 +// X86WINPRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// X86WINPRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// X86WINPRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// X86WINPRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// X86WINPRMTD-NEXT: [[MUL_AC:%.*]] = fmul double [[A_REAL]], [[B_REAL]] +// X86WINPRMTD-NEXT: [[MUL_BD:%.*]] = fmul double [[A_IMAG]], [[B_IMAG]] +// X86WINPRMTD-NEXT: [[MUL_AD:%.*]] = fmul double [[A_REAL]], [[B_IMAG]] +// X86WINPRMTD-NEXT: [[MUL_BC:%.*]] = fmul double [[A_IMAG]], [[B_REAL]] +// X86WINPRMTD-NEXT: [[MUL_R:%.*]] = fsub double [[MUL_AC]], [[MUL_BD]] +// X86WINPRMTD-NEXT: [[MUL_I:%.*]] = fadd double [[MUL_AD]], [[MUL_BC]] +// X86WINPRMTD-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// X86WINPRMTD-NEXT: store double [[MUL_R]], ptr [[AGG_RESULT_REALP]], align 8 +// X86WINPRMTD-NEXT: store double [[MUL_I]], ptr [[AGG_RESULT_IMAGP]], align 8 +// X86WINPRMTD-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[AGG_RESULT_REAL:%.*]] = load double, ptr [[AGG_RESULT_REALP1]], align 8 +// X86WINPRMTD-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[AGG_RESULT_IMAG:%.*]] = load double, ptr [[AGG_RESULT_IMAGP2]], align 8 +// X86WINPRMTD-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// X86WINPRMTD-NEXT: store double [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 8 +// X86WINPRMTD-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 8 +// X86WINPRMTD-NEXT: ret void +// +// AVRFP32-LABEL: define dso_local { float, float } @muld( +// AVRFP32-SAME: float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]], float noundef [[B_COERCE0:%.*]], float noundef [[B_COERCE1:%.*]]) addrspace(1) #[[ATTR0]] { +// AVRFP32-NEXT: entry: +// AVRFP32-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// AVRFP32-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// AVRFP32-NEXT: [[TMP0:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP32-NEXT: store float [[A_COERCE0]], ptr [[TMP0]], align 4 +// AVRFP32-NEXT: [[TMP1:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[A_COERCE1]], ptr [[TMP1]], align 4 +// AVRFP32-NEXT: [[TMP2:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// AVRFP32-NEXT: store float [[B_COERCE0]], ptr [[TMP2]], align 4 +// AVRFP32-NEXT: [[TMP3:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[B_COERCE1]], ptr [[TMP3]], align 4 +// AVRFP32-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP32-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// AVRFP32-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP32-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// AVRFP32-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// AVRFP32-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// AVRFP32-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// AVRFP32-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// AVRFP32-NEXT: [[MUL_AC:%.*]] = fmul float [[A_REAL]], [[B_REAL]] +// AVRFP32-NEXT: [[MUL_BD:%.*]] = fmul float [[A_IMAG]], [[B_IMAG]] +// AVRFP32-NEXT: [[MUL_AD:%.*]] = fmul float [[A_REAL]], [[B_IMAG]] +// AVRFP32-NEXT: [[MUL_BC:%.*]] = fmul float [[A_IMAG]], [[B_REAL]] +// AVRFP32-NEXT: [[MUL_R:%.*]] = fsub float [[MUL_AC]], [[MUL_BD]] +// AVRFP32-NEXT: [[MUL_I:%.*]] = fadd float [[MUL_AD]], [[MUL_BC]] +// AVRFP32-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// AVRFP32-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[MUL_R]], ptr [[RETVAL_REALP]], align 1 +// AVRFP32-NEXT: store float [[MUL_I]], ptr [[RETVAL_IMAGP]], align 1 +// AVRFP32-NEXT: [[TMP4:%.*]] = load { float, float }, ptr [[RETVAL]], align 1 +// AVRFP32-NEXT: ret { float, float } [[TMP4]] +// +// AVRFP64-LABEL: define dso_local void @muld( +// AVRFP64-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 1 [[AGG_RESULT:%.*]], double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]]) addrspace(1) #[[ATTR0]] { +// AVRFP64-NEXT: entry: +// AVRFP64-NEXT: [[A:%.*]] = alloca { double, double }, align 8 +// AVRFP64-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// AVRFP64-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// AVRFP64-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// AVRFP64-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// AVRFP64-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// AVRFP64-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// AVRFP64-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// AVRFP64-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// AVRFP64-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// AVRFP64-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// AVRFP64-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// AVRFP64-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// AVRFP64-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// AVRFP64-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// AVRFP64-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// AVRFP64-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// AVRFP64-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// AVRFP64-NEXT: [[MUL_AC:%.*]] = fmul double [[A_REAL]], [[B_REAL]] +// AVRFP64-NEXT: [[MUL_BD:%.*]] = fmul double [[A_IMAG]], [[B_IMAG]] +// AVRFP64-NEXT: [[MUL_AD:%.*]] = fmul double [[A_REAL]], [[B_IMAG]] +// AVRFP64-NEXT: [[MUL_BC:%.*]] = fmul double [[A_IMAG]], [[B_REAL]] +// AVRFP64-NEXT: [[MUL_R:%.*]] = fsub double [[MUL_AC]], [[MUL_BD]] +// AVRFP64-NEXT: [[MUL_I:%.*]] = fadd double [[MUL_AD]], [[MUL_BC]] +// AVRFP64-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// AVRFP64-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// AVRFP64-NEXT: store double [[MUL_R]], ptr [[AGG_RESULT_REALP]], align 1 +// AVRFP64-NEXT: store double [[MUL_I]], ptr [[AGG_RESULT_IMAGP]], align 1 +// AVRFP64-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// AVRFP64-NEXT: [[AGG_RESULT_REAL:%.*]] = load double, ptr [[AGG_RESULT_REALP1]], align 1 +// AVRFP64-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// AVRFP64-NEXT: [[AGG_RESULT_IMAG:%.*]] = load double, ptr [[AGG_RESULT_IMAGP2]], align 1 +// AVRFP64-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// AVRFP64-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// AVRFP64-NEXT: store double [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 1 +// AVRFP64-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 1 +// AVRFP64-NEXT: ret void +// +// BASIC_FAST-LABEL: define dso_local { double, double } @muld( +// BASIC_FAST-SAME: double noundef nofpclass(nan inf) [[A_COERCE0:%.*]], double noundef nofpclass(nan inf) [[A_COERCE1:%.*]], double noundef nofpclass(nan inf) [[B_COERCE0:%.*]], double noundef nofpclass(nan inf) [[B_COERCE1:%.*]]) #[[ATTR1]] { +// BASIC_FAST-NEXT: entry: +// BASIC_FAST-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// BASIC_FAST-NEXT: [[A:%.*]] = alloca { double, double }, align 8 +// BASIC_FAST-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// BASIC_FAST-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// BASIC_FAST-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// BASIC_FAST-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// BASIC_FAST-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// BASIC_FAST-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// BASIC_FAST-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// BASIC_FAST-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// BASIC_FAST-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// BASIC_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// BASIC_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// BASIC_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// BASIC_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// BASIC_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_REAL]], [[B_REAL]] +// BASIC_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_IMAG]], [[B_IMAG]] +// BASIC_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_REAL]], [[B_IMAG]] +// BASIC_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_IMAG]], [[B_REAL]] +// BASIC_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn double [[MUL_AC]], [[MUL_BD]] +// BASIC_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn double [[MUL_AD]], [[MUL_BC]] +// BASIC_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC_FAST-NEXT: store double [[MUL_R]], ptr [[RETVAL_REALP]], align 8 +// BASIC_FAST-NEXT: store double [[MUL_I]], ptr [[RETVAL_IMAGP]], align 8 +// BASIC_FAST-NEXT: [[TMP4:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 +// BASIC_FAST-NEXT: ret { double, double } [[TMP4]] +// +// FULL_FAST-LABEL: define dso_local { double, double } @muld( +// FULL_FAST-SAME: double noundef nofpclass(nan inf) [[A_COERCE0:%.*]], double noundef nofpclass(nan inf) [[A_COERCE1:%.*]], double noundef nofpclass(nan inf) [[B_COERCE0:%.*]], double noundef nofpclass(nan inf) [[B_COERCE1:%.*]]) #[[ATTR1]] { +// FULL_FAST-NEXT: entry: +// FULL_FAST-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// FULL_FAST-NEXT: [[A:%.*]] = alloca { double, double }, align 8 +// FULL_FAST-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// FULL_FAST-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// FULL_FAST-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// FULL_FAST-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// FULL_FAST-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// FULL_FAST-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// FULL_FAST-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// FULL_FAST-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// FULL_FAST-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// FULL_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// FULL_FAST-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// FULL_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// FULL_FAST-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// FULL_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// FULL_FAST-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// FULL_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// FULL_FAST-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// FULL_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_REAL]], [[B_REAL]] +// FULL_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_IMAG]], [[B_IMAG]] +// FULL_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_REAL]], [[B_IMAG]] +// FULL_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_IMAG]], [[B_REAL]] +// FULL_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn double [[MUL_AC]], [[MUL_BD]] +// FULL_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn double [[MUL_AD]], [[MUL_BC]] +// FULL_FAST-NEXT: [[ISNAN_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn uno double [[MUL_R]], [[MUL_R]] +// FULL_FAST-NEXT: br i1 [[ISNAN_CMP]], label [[COMPLEX_MUL_IMAG_NAN:%.*]], label [[COMPLEX_MUL_CONT:%.*]], !prof [[PROF2]] +// FULL_FAST: complex_mul_imag_nan: +// FULL_FAST-NEXT: [[ISNAN_CMP1:%.*]] = fcmp reassoc nnan ninf nsz arcp afn uno double [[MUL_I]], [[MUL_I]] +// FULL_FAST-NEXT: br i1 [[ISNAN_CMP1]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]] +// FULL_FAST: complex_mul_libcall: +// FULL_FAST-NEXT: [[CALL:%.*]] = call { double, double } @__muldc3(double noundef nofpclass(nan inf) [[A_REAL]], double noundef nofpclass(nan inf) [[A_IMAG]], double noundef nofpclass(nan inf) [[B_REAL]], double noundef nofpclass(nan inf) [[B_IMAG]]) #[[ATTR2]] +// FULL_FAST-NEXT: [[TMP4:%.*]] = extractvalue { double, double } [[CALL]], 0 +// FULL_FAST-NEXT: [[TMP5:%.*]] = extractvalue { double, double } [[CALL]], 1 +// FULL_FAST-NEXT: br label [[COMPLEX_MUL_CONT]] +// FULL_FAST: complex_mul_cont: +// FULL_FAST-NEXT: [[REAL_MUL_PHI:%.*]] = phi reassoc nnan ninf nsz arcp afn double [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[TMP4]], [[COMPLEX_MUL_LIBCALL]] ] +// FULL_FAST-NEXT: [[IMAG_MUL_PHI:%.*]] = phi reassoc nnan ninf nsz arcp afn double [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[TMP5]], [[COMPLEX_MUL_LIBCALL]] ] +// FULL_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// FULL_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// FULL_FAST-NEXT: store double [[REAL_MUL_PHI]], ptr [[RETVAL_REALP]], align 8 +// FULL_FAST-NEXT: store double [[IMAG_MUL_PHI]], ptr [[RETVAL_IMAGP]], align 8 +// FULL_FAST-NEXT: [[TMP6:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 +// FULL_FAST-NEXT: ret { double, double } [[TMP6]] +// +// IMPRVD_FAST-LABEL: define dso_local { double, double } @muld( +// IMPRVD_FAST-SAME: double noundef nofpclass(nan inf) [[A_COERCE0:%.*]], double noundef nofpclass(nan inf) [[A_COERCE1:%.*]], double noundef nofpclass(nan inf) [[B_COERCE0:%.*]], double noundef nofpclass(nan inf) [[B_COERCE1:%.*]]) #[[ATTR2]] { +// IMPRVD_FAST-NEXT: entry: +// IMPRVD_FAST-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// IMPRVD_FAST-NEXT: [[A:%.*]] = alloca { double, double }, align 8 +// IMPRVD_FAST-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// IMPRVD_FAST-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// IMPRVD_FAST-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// IMPRVD_FAST-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// IMPRVD_FAST-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// IMPRVD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// IMPRVD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// IMPRVD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// IMPRVD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// IMPRVD_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_REAL]], [[B_REAL]] +// IMPRVD_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_IMAG]], [[B_IMAG]] +// IMPRVD_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_REAL]], [[B_IMAG]] +// IMPRVD_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_IMAG]], [[B_REAL]] +// IMPRVD_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn double [[MUL_AC]], [[MUL_BD]] +// IMPRVD_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn double [[MUL_AD]], [[MUL_BC]] +// IMPRVD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: store double [[MUL_R]], ptr [[RETVAL_REALP]], align 8 +// IMPRVD_FAST-NEXT: store double [[MUL_I]], ptr [[RETVAL_IMAGP]], align 8 +// IMPRVD_FAST-NEXT: [[TMP4:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 +// IMPRVD_FAST-NEXT: ret { double, double } [[TMP4]] +// +// PRMTD_FAST-LABEL: define dso_local { double, double } @muld( +// PRMTD_FAST-SAME: double noundef nofpclass(nan inf) [[A_COERCE0:%.*]], double noundef nofpclass(nan inf) [[A_COERCE1:%.*]], double noundef nofpclass(nan inf) [[B_COERCE0:%.*]], double noundef nofpclass(nan inf) [[B_COERCE1:%.*]]) #[[ATTR1]] { +// PRMTD_FAST-NEXT: entry: +// PRMTD_FAST-NEXT: [[RETVAL:%.*]] = alloca { double, double }, align 8 +// PRMTD_FAST-NEXT: [[A:%.*]] = alloca { double, double }, align 8 +// PRMTD_FAST-NEXT: [[B:%.*]] = alloca { double, double }, align 8 +// PRMTD_FAST-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// PRMTD_FAST-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 8 +// PRMTD_FAST-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// PRMTD_FAST-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 8 +// PRMTD_FAST-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// PRMTD_FAST-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 8 +// PRMTD_FAST-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// PRMTD_FAST-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 8 +// PRMTD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// PRMTD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// PRMTD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// PRMTD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// PRMTD_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_REAL]], [[B_REAL]] +// PRMTD_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_IMAG]], [[B_IMAG]] +// PRMTD_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_REAL]], [[B_IMAG]] +// PRMTD_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[A_IMAG]], [[B_REAL]] +// PRMTD_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn double [[MUL_AC]], [[MUL_BD]] +// PRMTD_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn double [[MUL_AD]], [[MUL_BC]] +// PRMTD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD_FAST-NEXT: store double [[MUL_R]], ptr [[RETVAL_REALP]], align 8 +// PRMTD_FAST-NEXT: store double [[MUL_I]], ptr [[RETVAL_IMAGP]], align 8 +// PRMTD_FAST-NEXT: [[TMP4:%.*]] = load { double, double }, ptr [[RETVAL]], align 8 +// PRMTD_FAST-NEXT: ret { double, double } [[TMP4]] +// +_Complex double muld(_Complex double a, _Complex double b) { + return a * b; +} + +// FULL-LABEL: define dso_local { x86_fp80, x86_fp80 } @divld( +// FULL-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR1]] { +// FULL-NEXT: entry: +// FULL-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16 +// FULL-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 0 +// FULL-NEXT: [[A_REAL:%.*]] = load x86_fp80, ptr [[A_REALP]], align 16 +// FULL-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 1 +// FULL-NEXT: [[A_IMAG:%.*]] = load x86_fp80, ptr [[A_IMAGP]], align 16 +// FULL-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// FULL-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// FULL-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// FULL-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// FULL-NEXT: [[CALL:%.*]] = call { x86_fp80, x86_fp80 } @__divxc3(x86_fp80 noundef [[A_REAL]], x86_fp80 noundef [[A_IMAG]], x86_fp80 noundef [[B_REAL]], x86_fp80 noundef [[B_IMAG]]) #[[ATTR2]] +// FULL-NEXT: [[TMP0:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 0 +// FULL-NEXT: [[TMP1:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 1 +// FULL-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0 +// FULL-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 1 +// FULL-NEXT: store x86_fp80 [[TMP0]], ptr [[RETVAL_REALP]], align 16 +// FULL-NEXT: store x86_fp80 [[TMP1]], ptr [[RETVAL_IMAGP]], align 16 +// FULL-NEXT: [[TMP2:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16 +// FULL-NEXT: ret { x86_fp80, x86_fp80 } [[TMP2]] +// +// BASIC-LABEL: define dso_local { x86_fp80, x86_fp80 } @divld( +// BASIC-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR1]] { +// BASIC-NEXT: entry: +// BASIC-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16 +// BASIC-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 0 +// BASIC-NEXT: [[A_REAL:%.*]] = load x86_fp80, ptr [[A_REALP]], align 16 +// BASIC-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 1 +// BASIC-NEXT: [[A_IMAG:%.*]] = load x86_fp80, ptr [[A_IMAGP]], align 16 +// BASIC-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// BASIC-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// BASIC-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// BASIC-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// BASIC-NEXT: [[TMP0:%.*]] = fmul x86_fp80 [[A_REAL]], [[B_REAL]] +// BASIC-NEXT: [[TMP1:%.*]] = fmul x86_fp80 [[A_IMAG]], [[B_IMAG]] +// BASIC-NEXT: [[TMP2:%.*]] = fadd x86_fp80 [[TMP0]], [[TMP1]] +// BASIC-NEXT: [[TMP3:%.*]] = fmul x86_fp80 [[B_REAL]], [[B_REAL]] +// BASIC-NEXT: [[TMP4:%.*]] = fmul x86_fp80 [[B_IMAG]], [[B_IMAG]] +// BASIC-NEXT: [[TMP5:%.*]] = fadd x86_fp80 [[TMP3]], [[TMP4]] +// BASIC-NEXT: [[TMP6:%.*]] = fmul x86_fp80 [[A_IMAG]], [[B_REAL]] +// BASIC-NEXT: [[TMP7:%.*]] = fmul x86_fp80 [[A_REAL]], [[B_IMAG]] +// BASIC-NEXT: [[TMP8:%.*]] = fsub x86_fp80 [[TMP6]], [[TMP7]] +// BASIC-NEXT: [[TMP9:%.*]] = fdiv x86_fp80 [[TMP2]], [[TMP5]] +// BASIC-NEXT: [[TMP10:%.*]] = fdiv x86_fp80 [[TMP8]], [[TMP5]] +// BASIC-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC-NEXT: store x86_fp80 [[TMP9]], ptr [[RETVAL_REALP]], align 16 +// BASIC-NEXT: store x86_fp80 [[TMP10]], ptr [[RETVAL_IMAGP]], align 16 +// BASIC-NEXT: [[TMP11:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16 +// BASIC-NEXT: ret { x86_fp80, x86_fp80 } [[TMP11]] +// +// IMPRVD-LABEL: define dso_local { x86_fp80, x86_fp80 } @divld( +// IMPRVD-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR2]] { +// IMPRVD-NEXT: entry: +// IMPRVD-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16 +// IMPRVD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 0 +// IMPRVD-NEXT: [[A_REAL:%.*]] = load x86_fp80, ptr [[A_REALP]], align 16 +// IMPRVD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 1 +// IMPRVD-NEXT: [[A_IMAG:%.*]] = load x86_fp80, ptr [[A_IMAGP]], align 16 +// IMPRVD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// IMPRVD-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// IMPRVD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// IMPRVD-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// IMPRVD-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[B_REAL]]) +// IMPRVD-NEXT: [[TMP1:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[B_IMAG]]) +// IMPRVD-NEXT: [[ABS_CMP:%.*]] = fcmp ugt x86_fp80 [[TMP0]], [[TMP1]] +// IMPRVD-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// IMPRVD: abs_rhsr_greater_or_equal_abs_rhsi: +// IMPRVD-NEXT: [[TMP2:%.*]] = fdiv x86_fp80 [[B_IMAG]], [[B_REAL]] +// IMPRVD-NEXT: [[TMP3:%.*]] = fmul x86_fp80 [[TMP2]], [[B_IMAG]] +// IMPRVD-NEXT: [[TMP4:%.*]] = fadd x86_fp80 [[B_REAL]], [[TMP3]] +// IMPRVD-NEXT: [[TMP5:%.*]] = fmul x86_fp80 [[A_IMAG]], [[TMP2]] +// IMPRVD-NEXT: [[TMP6:%.*]] = fadd x86_fp80 [[A_REAL]], [[TMP5]] +// IMPRVD-NEXT: [[TMP7:%.*]] = fdiv x86_fp80 [[TMP6]], [[TMP4]] +// IMPRVD-NEXT: [[TMP8:%.*]] = fmul x86_fp80 [[A_REAL]], [[TMP2]] +// IMPRVD-NEXT: [[TMP9:%.*]] = fsub x86_fp80 [[A_IMAG]], [[TMP8]] +// IMPRVD-NEXT: [[TMP10:%.*]] = fdiv x86_fp80 [[TMP9]], [[TMP4]] +// IMPRVD-NEXT: br label [[COMPLEX_DIV:%.*]] +// IMPRVD: abs_rhsr_less_than_abs_rhsi: +// IMPRVD-NEXT: [[TMP11:%.*]] = fdiv x86_fp80 [[B_REAL]], [[B_IMAG]] +// IMPRVD-NEXT: [[TMP12:%.*]] = fmul x86_fp80 [[TMP11]], [[B_REAL]] +// IMPRVD-NEXT: [[TMP13:%.*]] = fadd x86_fp80 [[B_IMAG]], [[TMP12]] +// IMPRVD-NEXT: [[TMP14:%.*]] = fmul x86_fp80 [[A_REAL]], [[TMP11]] +// IMPRVD-NEXT: [[TMP15:%.*]] = fadd x86_fp80 [[TMP14]], [[A_IMAG]] +// IMPRVD-NEXT: [[TMP16:%.*]] = fdiv x86_fp80 [[TMP15]], [[TMP13]] +// IMPRVD-NEXT: [[TMP17:%.*]] = fmul x86_fp80 [[A_IMAG]], [[TMP11]] +// IMPRVD-NEXT: [[TMP18:%.*]] = fsub x86_fp80 [[TMP17]], [[A_REAL]] +// IMPRVD-NEXT: [[TMP19:%.*]] = fdiv x86_fp80 [[TMP18]], [[TMP13]] +// IMPRVD-NEXT: br label [[COMPLEX_DIV]] +// IMPRVD: complex_div: +// IMPRVD-NEXT: [[TMP20:%.*]] = phi x86_fp80 [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD-NEXT: [[TMP21:%.*]] = phi x86_fp80 [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD-NEXT: store x86_fp80 [[TMP20]], ptr [[RETVAL_REALP]], align 16 +// IMPRVD-NEXT: store x86_fp80 [[TMP21]], ptr [[RETVAL_IMAGP]], align 16 +// IMPRVD-NEXT: [[TMP22:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16 +// IMPRVD-NEXT: ret { x86_fp80, x86_fp80 } [[TMP22]] +// +// PRMTD-LABEL: define dso_local { x86_fp80, x86_fp80 } @divld( +// PRMTD-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR1]] { +// PRMTD-NEXT: entry: +// PRMTD-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16 +// PRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 0 +// PRMTD-NEXT: [[A_REAL:%.*]] = load x86_fp80, ptr [[A_REALP]], align 16 +// PRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 1 +// PRMTD-NEXT: [[A_IMAG:%.*]] = load x86_fp80, ptr [[A_IMAGP]], align 16 +// PRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// PRMTD-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// PRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// PRMTD-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// PRMTD-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[B_REAL]]) +// PRMTD-NEXT: [[TMP1:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[B_IMAG]]) +// PRMTD-NEXT: [[ABS_CMP:%.*]] = fcmp ugt x86_fp80 [[TMP0]], [[TMP1]] +// PRMTD-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// PRMTD: abs_rhsr_greater_or_equal_abs_rhsi: +// PRMTD-NEXT: [[TMP2:%.*]] = fdiv x86_fp80 [[B_IMAG]], [[B_REAL]] +// PRMTD-NEXT: [[TMP3:%.*]] = fmul x86_fp80 [[TMP2]], [[B_IMAG]] +// PRMTD-NEXT: [[TMP4:%.*]] = fadd x86_fp80 [[B_REAL]], [[TMP3]] +// PRMTD-NEXT: [[TMP5:%.*]] = fmul x86_fp80 [[A_IMAG]], [[TMP2]] +// PRMTD-NEXT: [[TMP6:%.*]] = fadd x86_fp80 [[A_REAL]], [[TMP5]] +// PRMTD-NEXT: [[TMP7:%.*]] = fdiv x86_fp80 [[TMP6]], [[TMP4]] +// PRMTD-NEXT: [[TMP8:%.*]] = fmul x86_fp80 [[A_REAL]], [[TMP2]] +// PRMTD-NEXT: [[TMP9:%.*]] = fsub x86_fp80 [[A_IMAG]], [[TMP8]] +// PRMTD-NEXT: [[TMP10:%.*]] = fdiv x86_fp80 [[TMP9]], [[TMP4]] +// PRMTD-NEXT: br label [[COMPLEX_DIV:%.*]] +// PRMTD: abs_rhsr_less_than_abs_rhsi: +// PRMTD-NEXT: [[TMP11:%.*]] = fdiv x86_fp80 [[B_REAL]], [[B_IMAG]] +// PRMTD-NEXT: [[TMP12:%.*]] = fmul x86_fp80 [[TMP11]], [[B_REAL]] +// PRMTD-NEXT: [[TMP13:%.*]] = fadd x86_fp80 [[B_IMAG]], [[TMP12]] +// PRMTD-NEXT: [[TMP14:%.*]] = fmul x86_fp80 [[A_REAL]], [[TMP11]] +// PRMTD-NEXT: [[TMP15:%.*]] = fadd x86_fp80 [[TMP14]], [[A_IMAG]] +// PRMTD-NEXT: [[TMP16:%.*]] = fdiv x86_fp80 [[TMP15]], [[TMP13]] +// PRMTD-NEXT: [[TMP17:%.*]] = fmul x86_fp80 [[A_IMAG]], [[TMP11]] +// PRMTD-NEXT: [[TMP18:%.*]] = fsub x86_fp80 [[TMP17]], [[A_REAL]] +// PRMTD-NEXT: [[TMP19:%.*]] = fdiv x86_fp80 [[TMP18]], [[TMP13]] +// PRMTD-NEXT: br label [[COMPLEX_DIV]] +// PRMTD: complex_div: +// PRMTD-NEXT: [[TMP20:%.*]] = phi x86_fp80 [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// PRMTD-NEXT: [[TMP21:%.*]] = phi x86_fp80 [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// PRMTD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD-NEXT: store x86_fp80 [[TMP20]], ptr [[RETVAL_REALP]], align 16 +// PRMTD-NEXT: store x86_fp80 [[TMP21]], ptr [[RETVAL_IMAGP]], align 16 +// PRMTD-NEXT: [[TMP22:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16 +// PRMTD-NEXT: ret { x86_fp80, x86_fp80 } [[TMP22]] +// +// 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-NEXT: entry: +// X86WINPRMTD-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 8 +// X86WINPRMTD-NEXT: [[B_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// X86WINPRMTD-NEXT: [[A_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// X86WINPRMTD-NEXT: store ptr [[AGG_RESULT]], ptr [[RESULT_PTR]], align 8 +// X86WINPRMTD-NEXT: store ptr [[B]], ptr [[B_INDIRECT_ADDR]], align 8 +// X86WINPRMTD-NEXT: store ptr [[A]], ptr [[A_INDIRECT_ADDR]], align 8 +// X86WINPRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// X86WINPRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// X86WINPRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// X86WINPRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// X86WINPRMTD-NEXT: [[TMP0:%.*]] = call double @llvm.fabs.f64(double [[B_REAL]]) +// X86WINPRMTD-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[B_IMAG]]) +// X86WINPRMTD-NEXT: [[ABS_CMP:%.*]] = fcmp ugt double [[TMP0]], [[TMP1]] +// X86WINPRMTD-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// X86WINPRMTD: abs_rhsr_greater_or_equal_abs_rhsi: +// X86WINPRMTD-NEXT: [[TMP2:%.*]] = fdiv double [[B_IMAG]], [[B_REAL]] +// X86WINPRMTD-NEXT: [[TMP3:%.*]] = fmul double [[TMP2]], [[B_IMAG]] +// X86WINPRMTD-NEXT: [[TMP4:%.*]] = fadd double [[B_REAL]], [[TMP3]] +// X86WINPRMTD-NEXT: [[TMP5:%.*]] = fmul double [[A_IMAG]], [[TMP2]] +// X86WINPRMTD-NEXT: [[TMP6:%.*]] = fadd double [[A_REAL]], [[TMP5]] +// X86WINPRMTD-NEXT: [[TMP7:%.*]] = fdiv double [[TMP6]], [[TMP4]] +// X86WINPRMTD-NEXT: [[TMP8:%.*]] = fmul double [[A_REAL]], [[TMP2]] +// X86WINPRMTD-NEXT: [[TMP9:%.*]] = fsub double [[A_IMAG]], [[TMP8]] +// X86WINPRMTD-NEXT: [[TMP10:%.*]] = fdiv double [[TMP9]], [[TMP4]] +// X86WINPRMTD-NEXT: br label [[COMPLEX_DIV:%.*]] +// X86WINPRMTD: abs_rhsr_less_than_abs_rhsi: +// X86WINPRMTD-NEXT: [[TMP11:%.*]] = fdiv double [[B_REAL]], [[B_IMAG]] +// X86WINPRMTD-NEXT: [[TMP12:%.*]] = fmul double [[TMP11]], [[B_REAL]] +// X86WINPRMTD-NEXT: [[TMP13:%.*]] = fadd double [[B_IMAG]], [[TMP12]] +// X86WINPRMTD-NEXT: [[TMP14:%.*]] = fmul double [[A_REAL]], [[TMP11]] +// X86WINPRMTD-NEXT: [[TMP15:%.*]] = fadd double [[TMP14]], [[A_IMAG]] +// X86WINPRMTD-NEXT: [[TMP16:%.*]] = fdiv double [[TMP15]], [[TMP13]] +// X86WINPRMTD-NEXT: [[TMP17:%.*]] = fmul double [[A_IMAG]], [[TMP11]] +// X86WINPRMTD-NEXT: [[TMP18:%.*]] = fsub double [[TMP17]], [[A_REAL]] +// X86WINPRMTD-NEXT: [[TMP19:%.*]] = fdiv double [[TMP18]], [[TMP13]] +// X86WINPRMTD-NEXT: br label [[COMPLEX_DIV]] +// X86WINPRMTD: complex_div: +// X86WINPRMTD-NEXT: [[TMP20:%.*]] = phi double [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// X86WINPRMTD-NEXT: [[TMP21:%.*]] = phi double [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// X86WINPRMTD-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// X86WINPRMTD-NEXT: store double [[TMP20]], ptr [[AGG_RESULT_REALP]], align 8 +// X86WINPRMTD-NEXT: store double [[TMP21]], ptr [[AGG_RESULT_IMAGP]], align 8 +// X86WINPRMTD-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[AGG_RESULT_REAL:%.*]] = load double, ptr [[AGG_RESULT_REALP1]], align 8 +// X86WINPRMTD-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[AGG_RESULT_IMAG:%.*]] = load double, ptr [[AGG_RESULT_IMAGP2]], align 8 +// X86WINPRMTD-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// X86WINPRMTD-NEXT: store double [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 8 +// X86WINPRMTD-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 8 +// X86WINPRMTD-NEXT: ret void +// +// AVRFP32-LABEL: define dso_local { float, float } @divld( +// AVRFP32-SAME: float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]], float noundef [[B_COERCE0:%.*]], float noundef [[B_COERCE1:%.*]]) addrspace(1) #[[ATTR0]] { +// AVRFP32-NEXT: entry: +// AVRFP32-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[A:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[B:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[TMP0:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP32-NEXT: store float [[A_COERCE0]], ptr [[TMP0]], align 1 +// AVRFP32-NEXT: [[TMP1:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[A_COERCE1]], ptr [[TMP1]], align 1 +// AVRFP32-NEXT: [[TMP2:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// AVRFP32-NEXT: store float [[B_COERCE0]], ptr [[TMP2]], align 1 +// AVRFP32-NEXT: [[TMP3:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[B_COERCE1]], ptr [[TMP3]], align 1 +// AVRFP32-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP32-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 1 +// AVRFP32-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP32-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 1 +// AVRFP32-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// AVRFP32-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 1 +// AVRFP32-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// AVRFP32-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 1 +// AVRFP32-NEXT: [[TMP4:%.*]] = call addrspace(1) float @llvm.fabs.f32(float [[B_REAL]]) +// AVRFP32-NEXT: [[TMP5:%.*]] = call addrspace(1) float @llvm.fabs.f32(float [[B_IMAG]]) +// AVRFP32-NEXT: [[ABS_CMP:%.*]] = fcmp ugt float [[TMP4]], [[TMP5]] +// AVRFP32-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// AVRFP32: abs_rhsr_greater_or_equal_abs_rhsi: +// AVRFP32-NEXT: [[TMP6:%.*]] = fdiv float [[B_IMAG]], [[B_REAL]] +// AVRFP32-NEXT: [[TMP7:%.*]] = fmul float [[TMP6]], [[B_IMAG]] +// AVRFP32-NEXT: [[TMP8:%.*]] = fadd float [[B_REAL]], [[TMP7]] +// AVRFP32-NEXT: [[TMP9:%.*]] = fmul float [[A_IMAG]], [[TMP6]] +// AVRFP32-NEXT: [[TMP10:%.*]] = fadd float [[A_REAL]], [[TMP9]] +// AVRFP32-NEXT: [[TMP11:%.*]] = fdiv float [[TMP10]], [[TMP8]] +// AVRFP32-NEXT: [[TMP12:%.*]] = fmul float [[A_REAL]], [[TMP6]] +// AVRFP32-NEXT: [[TMP13:%.*]] = fsub float [[A_IMAG]], [[TMP12]] +// AVRFP32-NEXT: [[TMP14:%.*]] = fdiv float [[TMP13]], [[TMP8]] +// AVRFP32-NEXT: br label [[COMPLEX_DIV:%.*]] +// AVRFP32: abs_rhsr_less_than_abs_rhsi: +// AVRFP32-NEXT: [[TMP15:%.*]] = fdiv float [[B_REAL]], [[B_IMAG]] +// AVRFP32-NEXT: [[TMP16:%.*]] = fmul float [[TMP15]], [[B_REAL]] +// AVRFP32-NEXT: [[TMP17:%.*]] = fadd float [[B_IMAG]], [[TMP16]] +// AVRFP32-NEXT: [[TMP18:%.*]] = fmul float [[A_REAL]], [[TMP15]] +// AVRFP32-NEXT: [[TMP19:%.*]] = fadd float [[TMP18]], [[A_IMAG]] +// AVRFP32-NEXT: [[TMP20:%.*]] = fdiv float [[TMP19]], [[TMP17]] +// AVRFP32-NEXT: [[TMP21:%.*]] = fmul float [[A_IMAG]], [[TMP15]] +// AVRFP32-NEXT: [[TMP22:%.*]] = fsub float [[TMP21]], [[A_REAL]] +// AVRFP32-NEXT: [[TMP23:%.*]] = fdiv float [[TMP22]], [[TMP17]] +// AVRFP32-NEXT: br label [[COMPLEX_DIV]] +// AVRFP32: complex_div: +// AVRFP32-NEXT: [[TMP24:%.*]] = phi float [ [[TMP11]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP20]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// AVRFP32-NEXT: [[TMP25:%.*]] = phi float [ [[TMP14]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP23]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// AVRFP32-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// AVRFP32-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[TMP24]], ptr [[RETVAL_REALP]], align 1 +// AVRFP32-NEXT: store float [[TMP25]], ptr [[RETVAL_IMAGP]], align 1 +// AVRFP32-NEXT: [[TMP26:%.*]] = load { float, float }, ptr [[RETVAL]], align 1 +// AVRFP32-NEXT: ret { float, float } [[TMP26]] +// +// AVRFP64-LABEL: define dso_local void @divld( +// AVRFP64-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 1 [[AGG_RESULT:%.*]], double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]]) addrspace(1) #[[ATTR0]] { +// AVRFP64-NEXT: entry: +// AVRFP64-NEXT: [[A:%.*]] = alloca { double, double }, align 1 +// AVRFP64-NEXT: [[B:%.*]] = alloca { double, double }, align 1 +// AVRFP64-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// AVRFP64-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 1 +// AVRFP64-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// AVRFP64-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 1 +// AVRFP64-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// AVRFP64-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 1 +// AVRFP64-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// AVRFP64-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 1 +// AVRFP64-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// AVRFP64-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 1 +// AVRFP64-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// AVRFP64-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 1 +// AVRFP64-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// AVRFP64-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 1 +// AVRFP64-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// AVRFP64-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 1 +// AVRFP64-NEXT: [[TMP4:%.*]] = call addrspace(1) double @llvm.fabs.f64(double [[B_REAL]]) +// AVRFP64-NEXT: [[TMP5:%.*]] = call addrspace(1) double @llvm.fabs.f64(double [[B_IMAG]]) +// AVRFP64-NEXT: [[ABS_CMP:%.*]] = fcmp ugt double [[TMP4]], [[TMP5]] +// AVRFP64-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// AVRFP64: abs_rhsr_greater_or_equal_abs_rhsi: +// AVRFP64-NEXT: [[TMP6:%.*]] = fdiv double [[B_IMAG]], [[B_REAL]] +// AVRFP64-NEXT: [[TMP7:%.*]] = fmul double [[TMP6]], [[B_IMAG]] +// AVRFP64-NEXT: [[TMP8:%.*]] = fadd double [[B_REAL]], [[TMP7]] +// AVRFP64-NEXT: [[TMP9:%.*]] = fmul double [[A_IMAG]], [[TMP6]] +// AVRFP64-NEXT: [[TMP10:%.*]] = fadd double [[A_REAL]], [[TMP9]] +// AVRFP64-NEXT: [[TMP11:%.*]] = fdiv double [[TMP10]], [[TMP8]] +// AVRFP64-NEXT: [[TMP12:%.*]] = fmul double [[A_REAL]], [[TMP6]] +// AVRFP64-NEXT: [[TMP13:%.*]] = fsub double [[A_IMAG]], [[TMP12]] +// AVRFP64-NEXT: [[TMP14:%.*]] = fdiv double [[TMP13]], [[TMP8]] +// AVRFP64-NEXT: br label [[COMPLEX_DIV:%.*]] +// AVRFP64: abs_rhsr_less_than_abs_rhsi: +// AVRFP64-NEXT: [[TMP15:%.*]] = fdiv double [[B_REAL]], [[B_IMAG]] +// AVRFP64-NEXT: [[TMP16:%.*]] = fmul double [[TMP15]], [[B_REAL]] +// AVRFP64-NEXT: [[TMP17:%.*]] = fadd double [[B_IMAG]], [[TMP16]] +// AVRFP64-NEXT: [[TMP18:%.*]] = fmul double [[A_REAL]], [[TMP15]] +// AVRFP64-NEXT: [[TMP19:%.*]] = fadd double [[TMP18]], [[A_IMAG]] +// AVRFP64-NEXT: [[TMP20:%.*]] = fdiv double [[TMP19]], [[TMP17]] +// AVRFP64-NEXT: [[TMP21:%.*]] = fmul double [[A_IMAG]], [[TMP15]] +// AVRFP64-NEXT: [[TMP22:%.*]] = fsub double [[TMP21]], [[A_REAL]] +// AVRFP64-NEXT: [[TMP23:%.*]] = fdiv double [[TMP22]], [[TMP17]] +// AVRFP64-NEXT: br label [[COMPLEX_DIV]] +// AVRFP64: complex_div: +// AVRFP64-NEXT: [[TMP24:%.*]] = phi double [ [[TMP11]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP20]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// AVRFP64-NEXT: [[TMP25:%.*]] = phi double [ [[TMP14]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP23]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// AVRFP64-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// AVRFP64-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// AVRFP64-NEXT: store double [[TMP24]], ptr [[AGG_RESULT_REALP]], align 1 +// AVRFP64-NEXT: store double [[TMP25]], ptr [[AGG_RESULT_IMAGP]], align 1 +// AVRFP64-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// AVRFP64-NEXT: [[AGG_RESULT_REAL:%.*]] = load double, ptr [[AGG_RESULT_REALP1]], align 1 +// AVRFP64-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// AVRFP64-NEXT: [[AGG_RESULT_IMAG:%.*]] = load double, ptr [[AGG_RESULT_IMAGP2]], align 1 +// AVRFP64-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// AVRFP64-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// AVRFP64-NEXT: store double [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 1 +// AVRFP64-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 1 +// AVRFP64-NEXT: ret void +// +// BASIC_FAST-LABEL: define dso_local { x86_fp80, x86_fp80 } @divld( +// BASIC_FAST-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR1]] { +// BASIC_FAST-NEXT: entry: +// BASIC_FAST-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16 +// BASIC_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[A_REAL:%.*]] = load x86_fp80, ptr [[A_REALP]], align 16 +// BASIC_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[A_IMAG:%.*]] = load x86_fp80, ptr [[A_IMAGP]], align 16 +// BASIC_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// BASIC_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// BASIC_FAST-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_REAL]], [[B_REAL]] +// BASIC_FAST-NEXT: [[TMP1:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_IMAG]], [[B_IMAG]] +// BASIC_FAST-NEXT: [[TMP2:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP0]], [[TMP1]] +// BASIC_FAST-NEXT: [[TMP3:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[B_REAL]] +// BASIC_FAST-NEXT: [[TMP4:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[B_IMAG]] +// BASIC_FAST-NEXT: [[TMP5:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP3]], [[TMP4]] +// BASIC_FAST-NEXT: [[TMP6:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_IMAG]], [[B_REAL]] +// BASIC_FAST-NEXT: [[TMP7:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_REAL]], [[B_IMAG]] +// BASIC_FAST-NEXT: [[TMP8:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP6]], [[TMP7]] +// BASIC_FAST-NEXT: [[TMP9:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP2]], [[TMP5]] +// BASIC_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP8]], [[TMP5]] +// BASIC_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC_FAST-NEXT: store x86_fp80 [[TMP9]], ptr [[RETVAL_REALP]], align 16 +// BASIC_FAST-NEXT: store x86_fp80 [[TMP10]], ptr [[RETVAL_IMAGP]], align 16 +// BASIC_FAST-NEXT: [[TMP11:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16 +// BASIC_FAST-NEXT: ret { x86_fp80, x86_fp80 } [[TMP11]] +// +// FULL_FAST-LABEL: define dso_local { x86_fp80, x86_fp80 } @divld( +// FULL_FAST-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR1]] { +// FULL_FAST-NEXT: entry: +// FULL_FAST-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16 +// FULL_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 0 +// FULL_FAST-NEXT: [[A_REAL:%.*]] = load x86_fp80, ptr [[A_REALP]], align 16 +// FULL_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 1 +// FULL_FAST-NEXT: [[A_IMAG:%.*]] = load x86_fp80, ptr [[A_IMAGP]], align 16 +// FULL_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// FULL_FAST-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// FULL_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// FULL_FAST-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// FULL_FAST-NEXT: [[CALL:%.*]] = call { x86_fp80, x86_fp80 } @__divxc3(x86_fp80 noundef nofpclass(nan inf) [[A_REAL]], x86_fp80 noundef nofpclass(nan inf) [[A_IMAG]], x86_fp80 noundef nofpclass(nan inf) [[B_REAL]], x86_fp80 noundef nofpclass(nan inf) [[B_IMAG]]) #[[ATTR2]] +// FULL_FAST-NEXT: [[TMP0:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 0 +// FULL_FAST-NEXT: [[TMP1:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 1 +// FULL_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0 +// FULL_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 1 +// FULL_FAST-NEXT: store x86_fp80 [[TMP0]], ptr [[RETVAL_REALP]], align 16 +// FULL_FAST-NEXT: store x86_fp80 [[TMP1]], ptr [[RETVAL_IMAGP]], align 16 +// FULL_FAST-NEXT: [[TMP2:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16 +// FULL_FAST-NEXT: ret { x86_fp80, x86_fp80 } [[TMP2]] +// +// IMPRVD_FAST-LABEL: define dso_local { x86_fp80, x86_fp80 } @divld( +// IMPRVD_FAST-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR2]] { +// IMPRVD_FAST-NEXT: entry: +// IMPRVD_FAST-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16 +// IMPRVD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[A_REAL:%.*]] = load x86_fp80, ptr [[A_REALP]], align 16 +// IMPRVD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[A_IMAG:%.*]] = load x86_fp80, ptr [[A_IMAGP]], align 16 +// IMPRVD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// IMPRVD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// IMPRVD_FAST-NEXT: [[TMP0:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[B_REAL]]) +// IMPRVD_FAST-NEXT: [[TMP1:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[B_IMAG]]) +// IMPRVD_FAST-NEXT: [[ABS_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn ugt x86_fp80 [[TMP0]], [[TMP1]] +// IMPRVD_FAST-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// IMPRVD_FAST: abs_rhsr_greater_or_equal_abs_rhsi: +// IMPRVD_FAST-NEXT: [[TMP2:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[B_REAL]] +// IMPRVD_FAST-NEXT: [[TMP3:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP2]], [[B_IMAG]] +// IMPRVD_FAST-NEXT: [[TMP4:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[TMP3]] +// IMPRVD_FAST-NEXT: [[TMP5:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_IMAG]], [[TMP2]] +// IMPRVD_FAST-NEXT: [[TMP6:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[A_REAL]], [[TMP5]] +// IMPRVD_FAST-NEXT: [[TMP7:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP6]], [[TMP4]] +// IMPRVD_FAST-NEXT: [[TMP8:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_REAL]], [[TMP2]] +// IMPRVD_FAST-NEXT: [[TMP9:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[A_IMAG]], [[TMP8]] +// IMPRVD_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP9]], [[TMP4]] +// IMPRVD_FAST-NEXT: br label [[COMPLEX_DIV:%.*]] +// IMPRVD_FAST: abs_rhsr_less_than_abs_rhsi: +// IMPRVD_FAST-NEXT: [[TMP11:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[B_IMAG]] +// IMPRVD_FAST-NEXT: [[TMP12:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP11]], [[B_REAL]] +// IMPRVD_FAST-NEXT: [[TMP13:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[TMP12]] +// IMPRVD_FAST-NEXT: [[TMP14:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_REAL]], [[TMP11]] +// IMPRVD_FAST-NEXT: [[TMP15:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP14]], [[A_IMAG]] +// IMPRVD_FAST-NEXT: [[TMP16:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP15]], [[TMP13]] +// IMPRVD_FAST-NEXT: [[TMP17:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_IMAG]], [[TMP11]] +// IMPRVD_FAST-NEXT: [[TMP18:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP17]], [[A_REAL]] +// IMPRVD_FAST-NEXT: [[TMP19:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP18]], [[TMP13]] +// IMPRVD_FAST-NEXT: br label [[COMPLEX_DIV]] +// IMPRVD_FAST: complex_div: +// IMPRVD_FAST-NEXT: [[TMP20:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD_FAST-NEXT: [[TMP21:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: store x86_fp80 [[TMP20]], ptr [[RETVAL_REALP]], align 16 +// IMPRVD_FAST-NEXT: store x86_fp80 [[TMP21]], ptr [[RETVAL_IMAGP]], align 16 +// IMPRVD_FAST-NEXT: [[TMP22:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16 +// IMPRVD_FAST-NEXT: ret { x86_fp80, x86_fp80 } [[TMP22]] +// +// PRMTD_FAST-LABEL: define dso_local { x86_fp80, x86_fp80 } @divld( +// PRMTD_FAST-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR1]] { +// PRMTD_FAST-NEXT: entry: +// PRMTD_FAST-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16 +// PRMTD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[A_REAL:%.*]] = load x86_fp80, ptr [[A_REALP]], align 16 +// PRMTD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[A_IMAG:%.*]] = load x86_fp80, ptr [[A_IMAGP]], align 16 +// PRMTD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// PRMTD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// PRMTD_FAST-NEXT: [[TMP0:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[B_REAL]]) +// PRMTD_FAST-NEXT: [[TMP1:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[B_IMAG]]) +// PRMTD_FAST-NEXT: [[ABS_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn ugt x86_fp80 [[TMP0]], [[TMP1]] +// PRMTD_FAST-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// PRMTD_FAST: abs_rhsr_greater_or_equal_abs_rhsi: +// PRMTD_FAST-NEXT: [[TMP2:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[B_REAL]] +// PRMTD_FAST-NEXT: [[TMP3:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP2]], [[B_IMAG]] +// PRMTD_FAST-NEXT: [[TMP4:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[TMP3]] +// PRMTD_FAST-NEXT: [[TMP5:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_IMAG]], [[TMP2]] +// PRMTD_FAST-NEXT: [[TMP6:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[A_REAL]], [[TMP5]] +// PRMTD_FAST-NEXT: [[TMP7:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP6]], [[TMP4]] +// PRMTD_FAST-NEXT: [[TMP8:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_REAL]], [[TMP2]] +// PRMTD_FAST-NEXT: [[TMP9:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[A_IMAG]], [[TMP8]] +// PRMTD_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP9]], [[TMP4]] +// PRMTD_FAST-NEXT: br label [[COMPLEX_DIV:%.*]] +// PRMTD_FAST: abs_rhsr_less_than_abs_rhsi: +// PRMTD_FAST-NEXT: [[TMP11:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[B_IMAG]] +// PRMTD_FAST-NEXT: [[TMP12:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP11]], [[B_REAL]] +// PRMTD_FAST-NEXT: [[TMP13:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[TMP12]] +// PRMTD_FAST-NEXT: [[TMP14:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_REAL]], [[TMP11]] +// PRMTD_FAST-NEXT: [[TMP15:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP14]], [[A_IMAG]] +// PRMTD_FAST-NEXT: [[TMP16:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP15]], [[TMP13]] +// PRMTD_FAST-NEXT: [[TMP17:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_IMAG]], [[TMP11]] +// PRMTD_FAST-NEXT: [[TMP18:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP17]], [[A_REAL]] +// PRMTD_FAST-NEXT: [[TMP19:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP18]], [[TMP13]] +// PRMTD_FAST-NEXT: br label [[COMPLEX_DIV]] +// PRMTD_FAST: complex_div: +// PRMTD_FAST-NEXT: [[TMP20:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// PRMTD_FAST-NEXT: [[TMP21:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// PRMTD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD_FAST-NEXT: store x86_fp80 [[TMP20]], ptr [[RETVAL_REALP]], align 16 +// PRMTD_FAST-NEXT: store x86_fp80 [[TMP21]], ptr [[RETVAL_IMAGP]], align 16 +// PRMTD_FAST-NEXT: [[TMP22:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16 +// PRMTD_FAST-NEXT: ret { x86_fp80, x86_fp80 } [[TMP22]] +// +_Complex long double divld(_Complex long double a, _Complex long double b) { + return a / b; +} +// FULL-LABEL: define dso_local { x86_fp80, x86_fp80 } @mulld( +// FULL-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR1]] { +// FULL-NEXT: entry: +// FULL-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16 +// FULL-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 0 +// FULL-NEXT: [[A_REAL:%.*]] = load x86_fp80, ptr [[A_REALP]], align 16 +// FULL-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 1 +// FULL-NEXT: [[A_IMAG:%.*]] = load x86_fp80, ptr [[A_IMAGP]], align 16 +// FULL-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// FULL-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// FULL-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// FULL-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// FULL-NEXT: [[MUL_AC:%.*]] = fmul x86_fp80 [[A_REAL]], [[B_REAL]] +// FULL-NEXT: [[MUL_BD:%.*]] = fmul x86_fp80 [[A_IMAG]], [[B_IMAG]] +// FULL-NEXT: [[MUL_AD:%.*]] = fmul x86_fp80 [[A_REAL]], [[B_IMAG]] +// FULL-NEXT: [[MUL_BC:%.*]] = fmul x86_fp80 [[A_IMAG]], [[B_REAL]] +// FULL-NEXT: [[MUL_R:%.*]] = fsub x86_fp80 [[MUL_AC]], [[MUL_BD]] +// FULL-NEXT: [[MUL_I:%.*]] = fadd x86_fp80 [[MUL_AD]], [[MUL_BC]] +// FULL-NEXT: [[ISNAN_CMP:%.*]] = fcmp uno x86_fp80 [[MUL_R]], [[MUL_R]] +// FULL-NEXT: br i1 [[ISNAN_CMP]], label [[COMPLEX_MUL_IMAG_NAN:%.*]], label [[COMPLEX_MUL_CONT:%.*]], !prof [[PROF2]] +// FULL: complex_mul_imag_nan: +// FULL-NEXT: [[ISNAN_CMP1:%.*]] = fcmp uno x86_fp80 [[MUL_I]], [[MUL_I]] +// FULL-NEXT: br i1 [[ISNAN_CMP1]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]] +// FULL: complex_mul_libcall: +// FULL-NEXT: [[CALL:%.*]] = call { x86_fp80, x86_fp80 } @__mulxc3(x86_fp80 noundef [[A_REAL]], x86_fp80 noundef [[A_IMAG]], x86_fp80 noundef [[B_REAL]], x86_fp80 noundef [[B_IMAG]]) #[[ATTR2]] +// FULL-NEXT: [[TMP0:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 0 +// FULL-NEXT: [[TMP1:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 1 +// FULL-NEXT: br label [[COMPLEX_MUL_CONT]] +// FULL: complex_mul_cont: +// FULL-NEXT: [[REAL_MUL_PHI:%.*]] = phi x86_fp80 [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[TMP0]], [[COMPLEX_MUL_LIBCALL]] ] +// FULL-NEXT: [[IMAG_MUL_PHI:%.*]] = phi x86_fp80 [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[TMP1]], [[COMPLEX_MUL_LIBCALL]] ] +// FULL-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0 +// FULL-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 1 +// FULL-NEXT: store x86_fp80 [[REAL_MUL_PHI]], ptr [[RETVAL_REALP]], align 16 +// FULL-NEXT: store x86_fp80 [[IMAG_MUL_PHI]], ptr [[RETVAL_IMAGP]], align 16 +// FULL-NEXT: [[TMP2:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16 +// FULL-NEXT: ret { x86_fp80, x86_fp80 } [[TMP2]] +// +// BASIC-LABEL: define dso_local { x86_fp80, x86_fp80 } @mulld( +// BASIC-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR1]] { +// BASIC-NEXT: entry: +// BASIC-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16 +// BASIC-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 0 +// BASIC-NEXT: [[A_REAL:%.*]] = load x86_fp80, ptr [[A_REALP]], align 16 +// BASIC-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 1 +// BASIC-NEXT: [[A_IMAG:%.*]] = load x86_fp80, ptr [[A_IMAGP]], align 16 +// BASIC-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// BASIC-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// BASIC-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// BASIC-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// BASIC-NEXT: [[MUL_AC:%.*]] = fmul x86_fp80 [[A_REAL]], [[B_REAL]] +// BASIC-NEXT: [[MUL_BD:%.*]] = fmul x86_fp80 [[A_IMAG]], [[B_IMAG]] +// BASIC-NEXT: [[MUL_AD:%.*]] = fmul x86_fp80 [[A_REAL]], [[B_IMAG]] +// BASIC-NEXT: [[MUL_BC:%.*]] = fmul x86_fp80 [[A_IMAG]], [[B_REAL]] +// BASIC-NEXT: [[MUL_R:%.*]] = fsub x86_fp80 [[MUL_AC]], [[MUL_BD]] +// BASIC-NEXT: [[MUL_I:%.*]] = fadd x86_fp80 [[MUL_AD]], [[MUL_BC]] +// BASIC-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC-NEXT: store x86_fp80 [[MUL_R]], ptr [[RETVAL_REALP]], align 16 +// BASIC-NEXT: store x86_fp80 [[MUL_I]], ptr [[RETVAL_IMAGP]], align 16 +// BASIC-NEXT: [[TMP0:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16 +// BASIC-NEXT: ret { x86_fp80, x86_fp80 } [[TMP0]] +// +// IMPRVD-LABEL: define dso_local { x86_fp80, x86_fp80 } @mulld( +// IMPRVD-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR2]] { +// IMPRVD-NEXT: entry: +// IMPRVD-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16 +// IMPRVD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 0 +// IMPRVD-NEXT: [[A_REAL:%.*]] = load x86_fp80, ptr [[A_REALP]], align 16 +// IMPRVD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 1 +// IMPRVD-NEXT: [[A_IMAG:%.*]] = load x86_fp80, ptr [[A_IMAGP]], align 16 +// IMPRVD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// IMPRVD-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// IMPRVD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// IMPRVD-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// IMPRVD-NEXT: [[MUL_AC:%.*]] = fmul x86_fp80 [[A_REAL]], [[B_REAL]] +// IMPRVD-NEXT: [[MUL_BD:%.*]] = fmul x86_fp80 [[A_IMAG]], [[B_IMAG]] +// IMPRVD-NEXT: [[MUL_AD:%.*]] = fmul x86_fp80 [[A_REAL]], [[B_IMAG]] +// IMPRVD-NEXT: [[MUL_BC:%.*]] = fmul x86_fp80 [[A_IMAG]], [[B_REAL]] +// IMPRVD-NEXT: [[MUL_R:%.*]] = fsub x86_fp80 [[MUL_AC]], [[MUL_BD]] +// IMPRVD-NEXT: [[MUL_I:%.*]] = fadd x86_fp80 [[MUL_AD]], [[MUL_BC]] +// IMPRVD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD-NEXT: store x86_fp80 [[MUL_R]], ptr [[RETVAL_REALP]], align 16 +// IMPRVD-NEXT: store x86_fp80 [[MUL_I]], ptr [[RETVAL_IMAGP]], align 16 +// IMPRVD-NEXT: [[TMP0:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16 +// IMPRVD-NEXT: ret { x86_fp80, x86_fp80 } [[TMP0]] +// +// PRMTD-LABEL: define dso_local { x86_fp80, x86_fp80 } @mulld( +// PRMTD-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR1]] { +// PRMTD-NEXT: entry: +// PRMTD-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16 +// PRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 0 +// PRMTD-NEXT: [[A_REAL:%.*]] = load x86_fp80, ptr [[A_REALP]], align 16 +// PRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 1 +// PRMTD-NEXT: [[A_IMAG:%.*]] = load x86_fp80, ptr [[A_IMAGP]], align 16 +// PRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// PRMTD-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// PRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// PRMTD-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// PRMTD-NEXT: [[MUL_AC:%.*]] = fmul x86_fp80 [[A_REAL]], [[B_REAL]] +// PRMTD-NEXT: [[MUL_BD:%.*]] = fmul x86_fp80 [[A_IMAG]], [[B_IMAG]] +// PRMTD-NEXT: [[MUL_AD:%.*]] = fmul x86_fp80 [[A_REAL]], [[B_IMAG]] +// PRMTD-NEXT: [[MUL_BC:%.*]] = fmul x86_fp80 [[A_IMAG]], [[B_REAL]] +// PRMTD-NEXT: [[MUL_R:%.*]] = fsub x86_fp80 [[MUL_AC]], [[MUL_BD]] +// PRMTD-NEXT: [[MUL_I:%.*]] = fadd x86_fp80 [[MUL_AD]], [[MUL_BC]] +// PRMTD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD-NEXT: store x86_fp80 [[MUL_R]], ptr [[RETVAL_REALP]], align 16 +// PRMTD-NEXT: store x86_fp80 [[MUL_I]], ptr [[RETVAL_IMAGP]], align 16 +// PRMTD-NEXT: [[TMP0:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16 +// PRMTD-NEXT: ret { x86_fp80, x86_fp80 } [[TMP0]] +// +// 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-NEXT: entry: +// X86WINPRMTD-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 8 +// X86WINPRMTD-NEXT: [[B_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// X86WINPRMTD-NEXT: [[A_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// X86WINPRMTD-NEXT: store ptr [[AGG_RESULT]], ptr [[RESULT_PTR]], align 8 +// X86WINPRMTD-NEXT: store ptr [[B]], ptr [[B_INDIRECT_ADDR]], align 8 +// X86WINPRMTD-NEXT: store ptr [[A]], ptr [[A_INDIRECT_ADDR]], align 8 +// X86WINPRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 8 +// X86WINPRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 8 +// X86WINPRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// X86WINPRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// X86WINPRMTD-NEXT: [[MUL_AC:%.*]] = fmul double [[A_REAL]], [[B_REAL]] +// X86WINPRMTD-NEXT: [[MUL_BD:%.*]] = fmul double [[A_IMAG]], [[B_IMAG]] +// X86WINPRMTD-NEXT: [[MUL_AD:%.*]] = fmul double [[A_REAL]], [[B_IMAG]] +// X86WINPRMTD-NEXT: [[MUL_BC:%.*]] = fmul double [[A_IMAG]], [[B_REAL]] +// X86WINPRMTD-NEXT: [[MUL_R:%.*]] = fsub double [[MUL_AC]], [[MUL_BD]] +// X86WINPRMTD-NEXT: [[MUL_I:%.*]] = fadd double [[MUL_AD]], [[MUL_BC]] +// X86WINPRMTD-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// X86WINPRMTD-NEXT: store double [[MUL_R]], ptr [[AGG_RESULT_REALP]], align 8 +// X86WINPRMTD-NEXT: store double [[MUL_I]], ptr [[AGG_RESULT_IMAGP]], align 8 +// X86WINPRMTD-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[AGG_RESULT_REAL:%.*]] = load double, ptr [[AGG_RESULT_REALP1]], align 8 +// X86WINPRMTD-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[AGG_RESULT_IMAG:%.*]] = load double, ptr [[AGG_RESULT_IMAGP2]], align 8 +// X86WINPRMTD-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// X86WINPRMTD-NEXT: store double [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 8 +// X86WINPRMTD-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 8 +// X86WINPRMTD-NEXT: ret void +// +// AVRFP32-LABEL: define dso_local { float, float } @mulld( +// AVRFP32-SAME: float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]], float noundef [[B_COERCE0:%.*]], float noundef [[B_COERCE1:%.*]]) addrspace(1) #[[ATTR0]] { +// AVRFP32-NEXT: entry: +// AVRFP32-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[A:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[B:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[TMP0:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP32-NEXT: store float [[A_COERCE0]], ptr [[TMP0]], align 1 +// AVRFP32-NEXT: [[TMP1:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[A_COERCE1]], ptr [[TMP1]], align 1 +// AVRFP32-NEXT: [[TMP2:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// AVRFP32-NEXT: store float [[B_COERCE0]], ptr [[TMP2]], align 1 +// AVRFP32-NEXT: [[TMP3:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[B_COERCE1]], ptr [[TMP3]], align 1 +// AVRFP32-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP32-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 1 +// AVRFP32-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP32-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 1 +// AVRFP32-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// AVRFP32-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 1 +// AVRFP32-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// AVRFP32-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 1 +// AVRFP32-NEXT: [[MUL_AC:%.*]] = fmul float [[A_REAL]], [[B_REAL]] +// AVRFP32-NEXT: [[MUL_BD:%.*]] = fmul float [[A_IMAG]], [[B_IMAG]] +// AVRFP32-NEXT: [[MUL_AD:%.*]] = fmul float [[A_REAL]], [[B_IMAG]] +// AVRFP32-NEXT: [[MUL_BC:%.*]] = fmul float [[A_IMAG]], [[B_REAL]] +// AVRFP32-NEXT: [[MUL_R:%.*]] = fsub float [[MUL_AC]], [[MUL_BD]] +// AVRFP32-NEXT: [[MUL_I:%.*]] = fadd float [[MUL_AD]], [[MUL_BC]] +// AVRFP32-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// AVRFP32-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[MUL_R]], ptr [[RETVAL_REALP]], align 1 +// AVRFP32-NEXT: store float [[MUL_I]], ptr [[RETVAL_IMAGP]], align 1 +// AVRFP32-NEXT: [[TMP4:%.*]] = load { float, float }, ptr [[RETVAL]], align 1 +// AVRFP32-NEXT: ret { float, float } [[TMP4]] +// +// AVRFP64-LABEL: define dso_local void @mulld( +// AVRFP64-SAME: ptr dead_on_unwind noalias writable sret({ double, double }) align 1 [[AGG_RESULT:%.*]], double noundef [[A_COERCE0:%.*]], double noundef [[A_COERCE1:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]]) addrspace(1) #[[ATTR0]] { +// AVRFP64-NEXT: entry: +// AVRFP64-NEXT: [[A:%.*]] = alloca { double, double }, align 1 +// AVRFP64-NEXT: [[B:%.*]] = alloca { double, double }, align 1 +// AVRFP64-NEXT: [[TMP0:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// AVRFP64-NEXT: store double [[A_COERCE0]], ptr [[TMP0]], align 1 +// AVRFP64-NEXT: [[TMP1:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// AVRFP64-NEXT: store double [[A_COERCE1]], ptr [[TMP1]], align 1 +// AVRFP64-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// AVRFP64-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 1 +// AVRFP64-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// AVRFP64-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 1 +// AVRFP64-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 0 +// AVRFP64-NEXT: [[A_REAL:%.*]] = load double, ptr [[A_REALP]], align 1 +// AVRFP64-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[A]], i32 0, i32 1 +// AVRFP64-NEXT: [[A_IMAG:%.*]] = load double, ptr [[A_IMAGP]], align 1 +// AVRFP64-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// AVRFP64-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 1 +// AVRFP64-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// AVRFP64-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 1 +// AVRFP64-NEXT: [[MUL_AC:%.*]] = fmul double [[A_REAL]], [[B_REAL]] +// AVRFP64-NEXT: [[MUL_BD:%.*]] = fmul double [[A_IMAG]], [[B_IMAG]] +// AVRFP64-NEXT: [[MUL_AD:%.*]] = fmul double [[A_REAL]], [[B_IMAG]] +// AVRFP64-NEXT: [[MUL_BC:%.*]] = fmul double [[A_IMAG]], [[B_REAL]] +// AVRFP64-NEXT: [[MUL_R:%.*]] = fsub double [[MUL_AC]], [[MUL_BD]] +// AVRFP64-NEXT: [[MUL_I:%.*]] = fadd double [[MUL_AD]], [[MUL_BC]] +// AVRFP64-NEXT: [[AGG_RESULT_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// AVRFP64-NEXT: [[AGG_RESULT_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// AVRFP64-NEXT: store double [[MUL_R]], ptr [[AGG_RESULT_REALP]], align 1 +// AVRFP64-NEXT: store double [[MUL_I]], ptr [[AGG_RESULT_IMAGP]], align 1 +// AVRFP64-NEXT: [[AGG_RESULT_REALP1:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// AVRFP64-NEXT: [[AGG_RESULT_REAL:%.*]] = load double, ptr [[AGG_RESULT_REALP1]], align 1 +// AVRFP64-NEXT: [[AGG_RESULT_IMAGP2:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// AVRFP64-NEXT: [[AGG_RESULT_IMAG:%.*]] = load double, ptr [[AGG_RESULT_IMAGP2]], align 1 +// AVRFP64-NEXT: [[AGG_RESULT_REALP3:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 0 +// AVRFP64-NEXT: [[AGG_RESULT_IMAGP4:%.*]] = getelementptr inbounds { double, double }, ptr [[AGG_RESULT]], i32 0, i32 1 +// AVRFP64-NEXT: store double [[AGG_RESULT_REAL]], ptr [[AGG_RESULT_REALP3]], align 1 +// AVRFP64-NEXT: store double [[AGG_RESULT_IMAG]], ptr [[AGG_RESULT_IMAGP4]], align 1 +// AVRFP64-NEXT: ret void +// +// BASIC_FAST-LABEL: define dso_local { x86_fp80, x86_fp80 } @mulld( +// BASIC_FAST-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR1]] { +// BASIC_FAST-NEXT: entry: +// BASIC_FAST-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16 +// BASIC_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[A_REAL:%.*]] = load x86_fp80, ptr [[A_REALP]], align 16 +// BASIC_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[A_IMAG:%.*]] = load x86_fp80, ptr [[A_IMAGP]], align 16 +// BASIC_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// BASIC_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// BASIC_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_REAL]], [[B_REAL]] +// BASIC_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_IMAG]], [[B_IMAG]] +// BASIC_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_REAL]], [[B_IMAG]] +// BASIC_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_IMAG]], [[B_REAL]] +// BASIC_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[MUL_AC]], [[MUL_BD]] +// BASIC_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[MUL_AD]], [[MUL_BC]] +// BASIC_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC_FAST-NEXT: store x86_fp80 [[MUL_R]], ptr [[RETVAL_REALP]], align 16 +// BASIC_FAST-NEXT: store x86_fp80 [[MUL_I]], ptr [[RETVAL_IMAGP]], align 16 +// BASIC_FAST-NEXT: [[TMP0:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16 +// BASIC_FAST-NEXT: ret { x86_fp80, x86_fp80 } [[TMP0]] +// +// FULL_FAST-LABEL: define dso_local { x86_fp80, x86_fp80 } @mulld( +// FULL_FAST-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR1]] { +// FULL_FAST-NEXT: entry: +// FULL_FAST-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16 +// FULL_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 0 +// FULL_FAST-NEXT: [[A_REAL:%.*]] = load x86_fp80, ptr [[A_REALP]], align 16 +// FULL_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 1 +// FULL_FAST-NEXT: [[A_IMAG:%.*]] = load x86_fp80, ptr [[A_IMAGP]], align 16 +// FULL_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// FULL_FAST-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// FULL_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// FULL_FAST-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// FULL_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_REAL]], [[B_REAL]] +// FULL_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_IMAG]], [[B_IMAG]] +// FULL_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_REAL]], [[B_IMAG]] +// FULL_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_IMAG]], [[B_REAL]] +// FULL_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[MUL_AC]], [[MUL_BD]] +// FULL_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[MUL_AD]], [[MUL_BC]] +// FULL_FAST-NEXT: [[ISNAN_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn uno x86_fp80 [[MUL_R]], [[MUL_R]] +// FULL_FAST-NEXT: br i1 [[ISNAN_CMP]], label [[COMPLEX_MUL_IMAG_NAN:%.*]], label [[COMPLEX_MUL_CONT:%.*]], !prof [[PROF2]] +// FULL_FAST: complex_mul_imag_nan: +// FULL_FAST-NEXT: [[ISNAN_CMP1:%.*]] = fcmp reassoc nnan ninf nsz arcp afn uno x86_fp80 [[MUL_I]], [[MUL_I]] +// FULL_FAST-NEXT: br i1 [[ISNAN_CMP1]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]] +// FULL_FAST: complex_mul_libcall: +// FULL_FAST-NEXT: [[CALL:%.*]] = call { x86_fp80, x86_fp80 } @__mulxc3(x86_fp80 noundef nofpclass(nan inf) [[A_REAL]], x86_fp80 noundef nofpclass(nan inf) [[A_IMAG]], x86_fp80 noundef nofpclass(nan inf) [[B_REAL]], x86_fp80 noundef nofpclass(nan inf) [[B_IMAG]]) #[[ATTR2]] +// FULL_FAST-NEXT: [[TMP0:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 0 +// FULL_FAST-NEXT: [[TMP1:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 1 +// FULL_FAST-NEXT: br label [[COMPLEX_MUL_CONT]] +// FULL_FAST: complex_mul_cont: +// FULL_FAST-NEXT: [[REAL_MUL_PHI:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[TMP0]], [[COMPLEX_MUL_LIBCALL]] ] +// FULL_FAST-NEXT: [[IMAG_MUL_PHI:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[TMP1]], [[COMPLEX_MUL_LIBCALL]] ] +// FULL_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0 +// FULL_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 1 +// FULL_FAST-NEXT: store x86_fp80 [[REAL_MUL_PHI]], ptr [[RETVAL_REALP]], align 16 +// FULL_FAST-NEXT: store x86_fp80 [[IMAG_MUL_PHI]], ptr [[RETVAL_IMAGP]], align 16 +// FULL_FAST-NEXT: [[TMP2:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16 +// FULL_FAST-NEXT: ret { x86_fp80, x86_fp80 } [[TMP2]] +// +// IMPRVD_FAST-LABEL: define dso_local { x86_fp80, x86_fp80 } @mulld( +// IMPRVD_FAST-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR2]] { +// IMPRVD_FAST-NEXT: entry: +// IMPRVD_FAST-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16 +// IMPRVD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[A_REAL:%.*]] = load x86_fp80, ptr [[A_REALP]], align 16 +// IMPRVD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[A_IMAG:%.*]] = load x86_fp80, ptr [[A_IMAGP]], align 16 +// IMPRVD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// IMPRVD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// IMPRVD_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_REAL]], [[B_REAL]] +// IMPRVD_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_IMAG]], [[B_IMAG]] +// IMPRVD_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_REAL]], [[B_IMAG]] +// IMPRVD_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_IMAG]], [[B_REAL]] +// IMPRVD_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[MUL_AC]], [[MUL_BD]] +// IMPRVD_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[MUL_AD]], [[MUL_BC]] +// IMPRVD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: store x86_fp80 [[MUL_R]], ptr [[RETVAL_REALP]], align 16 +// IMPRVD_FAST-NEXT: store x86_fp80 [[MUL_I]], ptr [[RETVAL_IMAGP]], align 16 +// IMPRVD_FAST-NEXT: [[TMP0:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16 +// IMPRVD_FAST-NEXT: ret { x86_fp80, x86_fp80 } [[TMP0]] +// +// PRMTD_FAST-LABEL: define dso_local { x86_fp80, x86_fp80 } @mulld( +// PRMTD_FAST-SAME: ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[A:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]]) #[[ATTR1]] { +// PRMTD_FAST-NEXT: entry: +// PRMTD_FAST-NEXT: [[RETVAL:%.*]] = alloca { x86_fp80, x86_fp80 }, align 16 +// PRMTD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[A_REAL:%.*]] = load x86_fp80, ptr [[A_REALP]], align 16 +// PRMTD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[A]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[A_IMAG:%.*]] = load x86_fp80, ptr [[A_IMAGP]], align 16 +// PRMTD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// PRMTD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// PRMTD_FAST-NEXT: [[MUL_AC:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_REAL]], [[B_REAL]] +// PRMTD_FAST-NEXT: [[MUL_BD:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_IMAG]], [[B_IMAG]] +// PRMTD_FAST-NEXT: [[MUL_AD:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_REAL]], [[B_IMAG]] +// PRMTD_FAST-NEXT: [[MUL_BC:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[A_IMAG]], [[B_REAL]] +// PRMTD_FAST-NEXT: [[MUL_R:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[MUL_AC]], [[MUL_BD]] +// PRMTD_FAST-NEXT: [[MUL_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[MUL_AD]], [[MUL_BC]] +// PRMTD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD_FAST-NEXT: store x86_fp80 [[MUL_R]], ptr [[RETVAL_REALP]], align 16 +// PRMTD_FAST-NEXT: store x86_fp80 [[MUL_I]], ptr [[RETVAL_IMAGP]], align 16 +// PRMTD_FAST-NEXT: [[TMP0:%.*]] = load { x86_fp80, x86_fp80 }, ptr [[RETVAL]], align 16 +// PRMTD_FAST-NEXT: ret { x86_fp80, x86_fp80 } [[TMP0]] +// +_Complex long double mulld(_Complex long double a, _Complex long double b) { return a * b; } + +// FULL-LABEL: define dso_local <2 x float> @f1( +// FULL-SAME: <2 x float> noundef [[A_COERCE:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]], <2 x float> noundef [[C_COERCE:%.*]]) #[[ATTR0]] { +// FULL-NEXT: entry: +// FULL-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// FULL-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// FULL-NEXT: [[C:%.*]] = alloca { float, float }, align 4 +// FULL-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4 +// FULL-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// FULL-NEXT: store <2 x float> [[C_COERCE]], ptr [[C]], align 4 +// FULL-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// FULL-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// FULL-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// FULL-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// FULL-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 0 +// FULL-NEXT: [[C_REAL:%.*]] = load float, ptr [[C_REALP]], align 4 +// FULL-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 1 +// FULL-NEXT: [[C_IMAG:%.*]] = load float, ptr [[C_IMAGP]], align 4 +// FULL-NEXT: [[CONV:%.*]] = fpext float [[C_REAL]] to x86_fp80 +// FULL-NEXT: [[CONV1:%.*]] = fpext float [[C_IMAG]] to x86_fp80 +// FULL-NEXT: [[CALL:%.*]] = call { x86_fp80, x86_fp80 } @__divxc3(x86_fp80 noundef [[B_REAL]], x86_fp80 noundef [[B_IMAG]], x86_fp80 noundef [[CONV]], x86_fp80 noundef [[CONV1]]) #[[ATTR2]] +// FULL-NEXT: [[TMP0:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 0 +// FULL-NEXT: [[TMP1:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 1 +// FULL-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP0]] to float +// FULL-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP1]] to float +// FULL-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// FULL-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// FULL-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// FULL-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// FULL-NEXT: [[CALL4:%.*]] = call <2 x float> @__divsc3(float noundef [[CONV2]], float noundef [[CONV3]], float noundef [[A_REAL]], float noundef [[A_IMAG]]) #[[ATTR2]] +// FULL-NEXT: store <2 x float> [[CALL4]], ptr [[COERCE]], align 4 +// FULL-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 0 +// FULL-NEXT: [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4 +// FULL-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 1 +// FULL-NEXT: [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4 +// FULL-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// FULL-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// FULL-NEXT: store float [[COERCE_REAL]], ptr [[RETVAL_REALP]], align 4 +// FULL-NEXT: store float [[COERCE_IMAG]], ptr [[RETVAL_IMAGP]], align 4 +// FULL-NEXT: [[TMP2:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// FULL-NEXT: ret <2 x float> [[TMP2]] +// +// BASIC-LABEL: define dso_local <2 x float> @f1( +// BASIC-SAME: <2 x float> noundef [[A_COERCE:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]], <2 x float> noundef [[C_COERCE:%.*]]) #[[ATTR0]] { +// BASIC-NEXT: entry: +// BASIC-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// BASIC-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// BASIC-NEXT: [[C:%.*]] = alloca { float, float }, align 4 +// BASIC-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// BASIC-NEXT: store <2 x float> [[C_COERCE]], ptr [[C]], align 4 +// BASIC-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// BASIC-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// BASIC-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// BASIC-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// BASIC-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 0 +// BASIC-NEXT: [[C_REAL:%.*]] = load float, ptr [[C_REALP]], align 4 +// BASIC-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 1 +// BASIC-NEXT: [[C_IMAG:%.*]] = load float, ptr [[C_IMAGP]], align 4 +// BASIC-NEXT: [[CONV:%.*]] = fpext float [[C_REAL]] to x86_fp80 +// BASIC-NEXT: [[CONV1:%.*]] = fpext float [[C_IMAG]] to x86_fp80 +// BASIC-NEXT: [[TMP0:%.*]] = fmul x86_fp80 [[B_REAL]], [[CONV]] +// BASIC-NEXT: [[TMP1:%.*]] = fmul x86_fp80 [[B_IMAG]], [[CONV1]] +// BASIC-NEXT: [[TMP2:%.*]] = fadd x86_fp80 [[TMP0]], [[TMP1]] +// BASIC-NEXT: [[TMP3:%.*]] = fmul x86_fp80 [[CONV]], [[CONV]] +// BASIC-NEXT: [[TMP4:%.*]] = fmul x86_fp80 [[CONV1]], [[CONV1]] +// BASIC-NEXT: [[TMP5:%.*]] = fadd x86_fp80 [[TMP3]], [[TMP4]] +// BASIC-NEXT: [[TMP6:%.*]] = fmul x86_fp80 [[B_IMAG]], [[CONV]] +// BASIC-NEXT: [[TMP7:%.*]] = fmul x86_fp80 [[B_REAL]], [[CONV1]] +// BASIC-NEXT: [[TMP8:%.*]] = fsub x86_fp80 [[TMP6]], [[TMP7]] +// BASIC-NEXT: [[TMP9:%.*]] = fdiv x86_fp80 [[TMP2]], [[TMP5]] +// BASIC-NEXT: [[TMP10:%.*]] = fdiv x86_fp80 [[TMP8]], [[TMP5]] +// BASIC-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP9]] to float +// BASIC-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP10]] to float +// BASIC-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// BASIC-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// BASIC-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// BASIC-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// BASIC-NEXT: [[TMP11:%.*]] = fmul float [[CONV2]], [[A_REAL]] +// BASIC-NEXT: [[TMP12:%.*]] = fmul float [[CONV3]], [[A_IMAG]] +// BASIC-NEXT: [[TMP13:%.*]] = fadd float [[TMP11]], [[TMP12]] +// BASIC-NEXT: [[TMP14:%.*]] = fmul float [[A_REAL]], [[A_REAL]] +// BASIC-NEXT: [[TMP15:%.*]] = fmul float [[A_IMAG]], [[A_IMAG]] +// BASIC-NEXT: [[TMP16:%.*]] = fadd float [[TMP14]], [[TMP15]] +// BASIC-NEXT: [[TMP17:%.*]] = fmul float [[CONV3]], [[A_REAL]] +// BASIC-NEXT: [[TMP18:%.*]] = fmul float [[CONV2]], [[A_IMAG]] +// BASIC-NEXT: [[TMP19:%.*]] = fsub float [[TMP17]], [[TMP18]] +// BASIC-NEXT: [[TMP20:%.*]] = fdiv float [[TMP13]], [[TMP16]] +// BASIC-NEXT: [[TMP21:%.*]] = fdiv float [[TMP19]], [[TMP16]] +// BASIC-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC-NEXT: store float [[TMP20]], ptr [[RETVAL_REALP]], align 4 +// BASIC-NEXT: store float [[TMP21]], ptr [[RETVAL_IMAGP]], align 4 +// BASIC-NEXT: [[TMP22:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// BASIC-NEXT: ret <2 x float> [[TMP22]] +// +// IMPRVD-LABEL: define dso_local <2 x float> @f1( +// IMPRVD-SAME: <2 x float> noundef [[A_COERCE:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]], <2 x float> noundef [[C_COERCE:%.*]]) #[[ATTR0]] { +// IMPRVD-NEXT: entry: +// IMPRVD-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// IMPRVD-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// IMPRVD-NEXT: [[C:%.*]] = alloca { float, float }, align 4 +// IMPRVD-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// IMPRVD-NEXT: store <2 x float> [[C_COERCE]], ptr [[C]], align 4 +// IMPRVD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// IMPRVD-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// IMPRVD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// IMPRVD-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// IMPRVD-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 0 +// IMPRVD-NEXT: [[C_REAL:%.*]] = load float, ptr [[C_REALP]], align 4 +// IMPRVD-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 1 +// IMPRVD-NEXT: [[C_IMAG:%.*]] = load float, ptr [[C_IMAGP]], align 4 +// IMPRVD-NEXT: [[CONV:%.*]] = fpext float [[C_REAL]] to x86_fp80 +// IMPRVD-NEXT: [[CONV1:%.*]] = fpext float [[C_IMAG]] to x86_fp80 +// IMPRVD-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV]]) +// IMPRVD-NEXT: [[TMP1:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV1]]) +// IMPRVD-NEXT: [[ABS_CMP:%.*]] = fcmp ugt x86_fp80 [[TMP0]], [[TMP1]] +// IMPRVD-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// IMPRVD: abs_rhsr_greater_or_equal_abs_rhsi: +// IMPRVD-NEXT: [[TMP2:%.*]] = fdiv x86_fp80 [[CONV1]], [[CONV]] +// IMPRVD-NEXT: [[TMP3:%.*]] = fmul x86_fp80 [[TMP2]], [[CONV1]] +// IMPRVD-NEXT: [[TMP4:%.*]] = fadd x86_fp80 [[CONV]], [[TMP3]] +// IMPRVD-NEXT: [[TMP5:%.*]] = fmul x86_fp80 [[B_IMAG]], [[TMP2]] +// IMPRVD-NEXT: [[TMP6:%.*]] = fadd x86_fp80 [[B_REAL]], [[TMP5]] +// IMPRVD-NEXT: [[TMP7:%.*]] = fdiv x86_fp80 [[TMP6]], [[TMP4]] +// IMPRVD-NEXT: [[TMP8:%.*]] = fmul x86_fp80 [[B_REAL]], [[TMP2]] +// IMPRVD-NEXT: [[TMP9:%.*]] = fsub x86_fp80 [[B_IMAG]], [[TMP8]] +// IMPRVD-NEXT: [[TMP10:%.*]] = fdiv x86_fp80 [[TMP9]], [[TMP4]] +// IMPRVD-NEXT: br label [[COMPLEX_DIV:%.*]] +// IMPRVD: abs_rhsr_less_than_abs_rhsi: +// IMPRVD-NEXT: [[TMP11:%.*]] = fdiv x86_fp80 [[CONV]], [[CONV1]] +// IMPRVD-NEXT: [[TMP12:%.*]] = fmul x86_fp80 [[TMP11]], [[CONV]] +// IMPRVD-NEXT: [[TMP13:%.*]] = fadd x86_fp80 [[CONV1]], [[TMP12]] +// IMPRVD-NEXT: [[TMP14:%.*]] = fmul x86_fp80 [[B_REAL]], [[TMP11]] +// IMPRVD-NEXT: [[TMP15:%.*]] = fadd x86_fp80 [[TMP14]], [[B_IMAG]] +// IMPRVD-NEXT: [[TMP16:%.*]] = fdiv x86_fp80 [[TMP15]], [[TMP13]] +// IMPRVD-NEXT: [[TMP17:%.*]] = fmul x86_fp80 [[B_IMAG]], [[TMP11]] +// IMPRVD-NEXT: [[TMP18:%.*]] = fsub x86_fp80 [[TMP17]], [[B_REAL]] +// IMPRVD-NEXT: [[TMP19:%.*]] = fdiv x86_fp80 [[TMP18]], [[TMP13]] +// IMPRVD-NEXT: br label [[COMPLEX_DIV]] +// IMPRVD: complex_div: +// IMPRVD-NEXT: [[TMP20:%.*]] = phi x86_fp80 [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD-NEXT: [[TMP21:%.*]] = phi x86_fp80 [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP20]] to float +// IMPRVD-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP21]] to float +// IMPRVD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// IMPRVD-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// IMPRVD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// IMPRVD-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// IMPRVD-NEXT: [[TMP22:%.*]] = call float @llvm.fabs.f32(float [[A_REAL]]) +// IMPRVD-NEXT: [[TMP23:%.*]] = call float @llvm.fabs.f32(float [[A_IMAG]]) +// IMPRVD-NEXT: [[ABS_CMP4:%.*]] = fcmp ugt float [[TMP22]], [[TMP23]] +// IMPRVD-NEXT: br i1 [[ABS_CMP4]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI5:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI6:%.*]] +// IMPRVD: abs_rhsr_greater_or_equal_abs_rhsi5: +// IMPRVD-NEXT: [[TMP24:%.*]] = fdiv float [[A_IMAG]], [[A_REAL]] +// IMPRVD-NEXT: [[TMP25:%.*]] = fmul float [[TMP24]], [[A_IMAG]] +// IMPRVD-NEXT: [[TMP26:%.*]] = fadd float [[A_REAL]], [[TMP25]] +// IMPRVD-NEXT: [[TMP27:%.*]] = fmul float [[CONV3]], [[TMP24]] +// IMPRVD-NEXT: [[TMP28:%.*]] = fadd float [[CONV2]], [[TMP27]] +// IMPRVD-NEXT: [[TMP29:%.*]] = fdiv float [[TMP28]], [[TMP26]] +// IMPRVD-NEXT: [[TMP30:%.*]] = fmul float [[CONV2]], [[TMP24]] +// IMPRVD-NEXT: [[TMP31:%.*]] = fsub float [[CONV3]], [[TMP30]] +// IMPRVD-NEXT: [[TMP32:%.*]] = fdiv float [[TMP31]], [[TMP26]] +// IMPRVD-NEXT: br label [[COMPLEX_DIV7:%.*]] +// IMPRVD: abs_rhsr_less_than_abs_rhsi6: +// IMPRVD-NEXT: [[TMP33:%.*]] = fdiv float [[A_REAL]], [[A_IMAG]] +// IMPRVD-NEXT: [[TMP34:%.*]] = fmul float [[TMP33]], [[A_REAL]] +// IMPRVD-NEXT: [[TMP35:%.*]] = fadd float [[A_IMAG]], [[TMP34]] +// IMPRVD-NEXT: [[TMP36:%.*]] = fmul float [[CONV2]], [[TMP33]] +// IMPRVD-NEXT: [[TMP37:%.*]] = fadd float [[TMP36]], [[CONV3]] +// IMPRVD-NEXT: [[TMP38:%.*]] = fdiv float [[TMP37]], [[TMP35]] +// IMPRVD-NEXT: [[TMP39:%.*]] = fmul float [[CONV3]], [[TMP33]] +// IMPRVD-NEXT: [[TMP40:%.*]] = fsub float [[TMP39]], [[CONV2]] +// IMPRVD-NEXT: [[TMP41:%.*]] = fdiv float [[TMP40]], [[TMP35]] +// IMPRVD-NEXT: br label [[COMPLEX_DIV7]] +// IMPRVD: complex_div7: +// IMPRVD-NEXT: [[TMP42:%.*]] = phi float [ [[TMP29]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI5]] ], [ [[TMP38]], [[ABS_RHSR_LESS_THAN_ABS_RHSI6]] ] +// IMPRVD-NEXT: [[TMP43:%.*]] = phi float [ [[TMP32]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI5]] ], [ [[TMP41]], [[ABS_RHSR_LESS_THAN_ABS_RHSI6]] ] +// IMPRVD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD-NEXT: store float [[TMP42]], ptr [[RETVAL_REALP]], align 4 +// IMPRVD-NEXT: store float [[TMP43]], ptr [[RETVAL_IMAGP]], align 4 +// IMPRVD-NEXT: [[TMP44:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// IMPRVD-NEXT: ret <2 x float> [[TMP44]] +// +// PRMTD-LABEL: define dso_local <2 x float> @f1( +// PRMTD-SAME: <2 x float> noundef [[A_COERCE:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]], <2 x float> noundef [[C_COERCE:%.*]]) #[[ATTR0]] { +// PRMTD-NEXT: entry: +// PRMTD-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// PRMTD-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// PRMTD-NEXT: [[C:%.*]] = alloca { float, float }, align 4 +// PRMTD-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// PRMTD-NEXT: store <2 x float> [[C_COERCE]], ptr [[C]], align 4 +// PRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// PRMTD-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// PRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// PRMTD-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// PRMTD-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 0 +// PRMTD-NEXT: [[C_REAL:%.*]] = load float, ptr [[C_REALP]], align 4 +// PRMTD-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 1 +// PRMTD-NEXT: [[C_IMAG:%.*]] = load float, ptr [[C_IMAGP]], align 4 +// PRMTD-NEXT: [[CONV:%.*]] = fpext float [[C_REAL]] to x86_fp80 +// PRMTD-NEXT: [[CONV1:%.*]] = fpext float [[C_IMAG]] to x86_fp80 +// PRMTD-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV]]) +// PRMTD-NEXT: [[TMP1:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV1]]) +// PRMTD-NEXT: [[ABS_CMP:%.*]] = fcmp ugt x86_fp80 [[TMP0]], [[TMP1]] +// PRMTD-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// PRMTD: abs_rhsr_greater_or_equal_abs_rhsi: +// PRMTD-NEXT: [[TMP2:%.*]] = fdiv x86_fp80 [[CONV1]], [[CONV]] +// PRMTD-NEXT: [[TMP3:%.*]] = fmul x86_fp80 [[TMP2]], [[CONV1]] +// PRMTD-NEXT: [[TMP4:%.*]] = fadd x86_fp80 [[CONV]], [[TMP3]] +// PRMTD-NEXT: [[TMP5:%.*]] = fmul x86_fp80 [[B_IMAG]], [[TMP2]] +// PRMTD-NEXT: [[TMP6:%.*]] = fadd x86_fp80 [[B_REAL]], [[TMP5]] +// PRMTD-NEXT: [[TMP7:%.*]] = fdiv x86_fp80 [[TMP6]], [[TMP4]] +// PRMTD-NEXT: [[TMP8:%.*]] = fmul x86_fp80 [[B_REAL]], [[TMP2]] +// PRMTD-NEXT: [[TMP9:%.*]] = fsub x86_fp80 [[B_IMAG]], [[TMP8]] +// PRMTD-NEXT: [[TMP10:%.*]] = fdiv x86_fp80 [[TMP9]], [[TMP4]] +// PRMTD-NEXT: br label [[COMPLEX_DIV:%.*]] +// PRMTD: abs_rhsr_less_than_abs_rhsi: +// PRMTD-NEXT: [[TMP11:%.*]] = fdiv x86_fp80 [[CONV]], [[CONV1]] +// PRMTD-NEXT: [[TMP12:%.*]] = fmul x86_fp80 [[TMP11]], [[CONV]] +// PRMTD-NEXT: [[TMP13:%.*]] = fadd x86_fp80 [[CONV1]], [[TMP12]] +// PRMTD-NEXT: [[TMP14:%.*]] = fmul x86_fp80 [[B_REAL]], [[TMP11]] +// PRMTD-NEXT: [[TMP15:%.*]] = fadd x86_fp80 [[TMP14]], [[B_IMAG]] +// PRMTD-NEXT: [[TMP16:%.*]] = fdiv x86_fp80 [[TMP15]], [[TMP13]] +// PRMTD-NEXT: [[TMP17:%.*]] = fmul x86_fp80 [[B_IMAG]], [[TMP11]] +// PRMTD-NEXT: [[TMP18:%.*]] = fsub x86_fp80 [[TMP17]], [[B_REAL]] +// PRMTD-NEXT: [[TMP19:%.*]] = fdiv x86_fp80 [[TMP18]], [[TMP13]] +// PRMTD-NEXT: br label [[COMPLEX_DIV]] +// PRMTD: complex_div: +// PRMTD-NEXT: [[TMP20:%.*]] = phi x86_fp80 [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// PRMTD-NEXT: [[TMP21:%.*]] = phi x86_fp80 [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// PRMTD-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP20]] to float +// PRMTD-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP21]] to float +// PRMTD-NEXT: [[EXT:%.*]] = fpext float [[CONV2]] to double +// PRMTD-NEXT: [[EXT4:%.*]] = fpext float [[CONV3]] to double +// PRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// PRMTD-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// PRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// PRMTD-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// PRMTD-NEXT: [[EXT5:%.*]] = fpext float [[A_REAL]] to double +// PRMTD-NEXT: [[EXT6:%.*]] = fpext float [[A_IMAG]] to double +// PRMTD-NEXT: [[TMP22:%.*]] = fmul double [[EXT]], [[EXT5]] +// PRMTD-NEXT: [[TMP23:%.*]] = fmul double [[EXT4]], [[EXT6]] +// PRMTD-NEXT: [[TMP24:%.*]] = fadd double [[TMP22]], [[TMP23]] +// PRMTD-NEXT: [[TMP25:%.*]] = fmul double [[EXT5]], [[EXT5]] +// PRMTD-NEXT: [[TMP26:%.*]] = fmul double [[EXT6]], [[EXT6]] +// PRMTD-NEXT: [[TMP27:%.*]] = fadd double [[TMP25]], [[TMP26]] +// PRMTD-NEXT: [[TMP28:%.*]] = fmul double [[EXT4]], [[EXT5]] +// PRMTD-NEXT: [[TMP29:%.*]] = fmul double [[EXT]], [[EXT6]] +// PRMTD-NEXT: [[TMP30:%.*]] = fsub double [[TMP28]], [[TMP29]] +// PRMTD-NEXT: [[TMP31:%.*]] = fdiv double [[TMP24]], [[TMP27]] +// PRMTD-NEXT: [[TMP32:%.*]] = fdiv double [[TMP30]], [[TMP27]] +// PRMTD-NEXT: [[UNPROMOTION:%.*]] = fptrunc double [[TMP31]] to float +// PRMTD-NEXT: [[UNPROMOTION7:%.*]] = fptrunc double [[TMP32]] to float +// PRMTD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD-NEXT: store float [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 4 +// PRMTD-NEXT: store float [[UNPROMOTION7]], ptr [[RETVAL_IMAGP]], align 4 +// PRMTD-NEXT: [[TMP33:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// PRMTD-NEXT: ret <2 x float> [[TMP33]] +// +// X86WINPRMTD-LABEL: define dso_local i64 @f1( +// X86WINPRMTD-SAME: i64 noundef [[A_COERCE:%.*]], ptr noundef [[B:%.*]], i64 noundef [[C_COERCE:%.*]]) #[[ATTR0]] { +// X86WINPRMTD-NEXT: entry: +// X86WINPRMTD-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// X86WINPRMTD-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// X86WINPRMTD-NEXT: [[C:%.*]] = alloca { float, float }, align 4 +// X86WINPRMTD-NEXT: [[B_INDIRECT_ADDR:%.*]] = alloca ptr, align 8 +// X86WINPRMTD-NEXT: store i64 [[A_COERCE]], ptr [[A]], align 4 +// X86WINPRMTD-NEXT: store i64 [[C_COERCE]], ptr [[C]], align 4 +// X86WINPRMTD-NEXT: store ptr [[B]], ptr [[B_INDIRECT_ADDR]], align 8 +// X86WINPRMTD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 8 +// X86WINPRMTD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 8 +// X86WINPRMTD-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[C_REAL:%.*]] = load float, ptr [[C_REALP]], align 4 +// X86WINPRMTD-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[C_IMAG:%.*]] = load float, ptr [[C_IMAGP]], align 4 +// X86WINPRMTD-NEXT: [[CONV:%.*]] = fpext float [[C_REAL]] to double +// X86WINPRMTD-NEXT: [[CONV1:%.*]] = fpext float [[C_IMAG]] to double +// X86WINPRMTD-NEXT: [[TMP0:%.*]] = call double @llvm.fabs.f64(double [[CONV]]) +// X86WINPRMTD-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[CONV1]]) +// X86WINPRMTD-NEXT: [[ABS_CMP:%.*]] = fcmp ugt double [[TMP0]], [[TMP1]] +// X86WINPRMTD-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// X86WINPRMTD: abs_rhsr_greater_or_equal_abs_rhsi: +// X86WINPRMTD-NEXT: [[TMP2:%.*]] = fdiv double [[CONV1]], [[CONV]] +// X86WINPRMTD-NEXT: [[TMP3:%.*]] = fmul double [[TMP2]], [[CONV1]] +// X86WINPRMTD-NEXT: [[TMP4:%.*]] = fadd double [[CONV]], [[TMP3]] +// X86WINPRMTD-NEXT: [[TMP5:%.*]] = fmul double [[B_IMAG]], [[TMP2]] +// X86WINPRMTD-NEXT: [[TMP6:%.*]] = fadd double [[B_REAL]], [[TMP5]] +// X86WINPRMTD-NEXT: [[TMP7:%.*]] = fdiv double [[TMP6]], [[TMP4]] +// X86WINPRMTD-NEXT: [[TMP8:%.*]] = fmul double [[B_REAL]], [[TMP2]] +// X86WINPRMTD-NEXT: [[TMP9:%.*]] = fsub double [[B_IMAG]], [[TMP8]] +// X86WINPRMTD-NEXT: [[TMP10:%.*]] = fdiv double [[TMP9]], [[TMP4]] +// X86WINPRMTD-NEXT: br label [[COMPLEX_DIV:%.*]] +// X86WINPRMTD: abs_rhsr_less_than_abs_rhsi: +// X86WINPRMTD-NEXT: [[TMP11:%.*]] = fdiv double [[CONV]], [[CONV1]] +// X86WINPRMTD-NEXT: [[TMP12:%.*]] = fmul double [[TMP11]], [[CONV]] +// X86WINPRMTD-NEXT: [[TMP13:%.*]] = fadd double [[CONV1]], [[TMP12]] +// X86WINPRMTD-NEXT: [[TMP14:%.*]] = fmul double [[B_REAL]], [[TMP11]] +// X86WINPRMTD-NEXT: [[TMP15:%.*]] = fadd double [[TMP14]], [[B_IMAG]] +// X86WINPRMTD-NEXT: [[TMP16:%.*]] = fdiv double [[TMP15]], [[TMP13]] +// X86WINPRMTD-NEXT: [[TMP17:%.*]] = fmul double [[B_IMAG]], [[TMP11]] +// X86WINPRMTD-NEXT: [[TMP18:%.*]] = fsub double [[TMP17]], [[B_REAL]] +// X86WINPRMTD-NEXT: [[TMP19:%.*]] = fdiv double [[TMP18]], [[TMP13]] +// X86WINPRMTD-NEXT: br label [[COMPLEX_DIV]] +// X86WINPRMTD: complex_div: +// X86WINPRMTD-NEXT: [[TMP20:%.*]] = phi double [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// X86WINPRMTD-NEXT: [[TMP21:%.*]] = phi double [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// X86WINPRMTD-NEXT: [[CONV2:%.*]] = fptrunc double [[TMP20]] to float +// X86WINPRMTD-NEXT: [[CONV3:%.*]] = fptrunc double [[TMP21]] to float +// X86WINPRMTD-NEXT: [[EXT:%.*]] = fpext float [[CONV2]] to double +// X86WINPRMTD-NEXT: [[EXT4:%.*]] = fpext float [[CONV3]] to double +// X86WINPRMTD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// X86WINPRMTD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// X86WINPRMTD-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// X86WINPRMTD-NEXT: [[EXT5:%.*]] = fpext float [[A_REAL]] to double +// X86WINPRMTD-NEXT: [[EXT6:%.*]] = fpext float [[A_IMAG]] to double +// X86WINPRMTD-NEXT: [[TMP22:%.*]] = fmul double [[EXT]], [[EXT5]] +// X86WINPRMTD-NEXT: [[TMP23:%.*]] = fmul double [[EXT4]], [[EXT6]] +// X86WINPRMTD-NEXT: [[TMP24:%.*]] = fadd double [[TMP22]], [[TMP23]] +// X86WINPRMTD-NEXT: [[TMP25:%.*]] = fmul double [[EXT5]], [[EXT5]] +// X86WINPRMTD-NEXT: [[TMP26:%.*]] = fmul double [[EXT6]], [[EXT6]] +// X86WINPRMTD-NEXT: [[TMP27:%.*]] = fadd double [[TMP25]], [[TMP26]] +// X86WINPRMTD-NEXT: [[TMP28:%.*]] = fmul double [[EXT4]], [[EXT5]] +// X86WINPRMTD-NEXT: [[TMP29:%.*]] = fmul double [[EXT]], [[EXT6]] +// X86WINPRMTD-NEXT: [[TMP30:%.*]] = fsub double [[TMP28]], [[TMP29]] +// X86WINPRMTD-NEXT: [[TMP31:%.*]] = fdiv double [[TMP24]], [[TMP27]] +// X86WINPRMTD-NEXT: [[TMP32:%.*]] = fdiv double [[TMP30]], [[TMP27]] +// X86WINPRMTD-NEXT: [[UNPROMOTION:%.*]] = fptrunc double [[TMP31]] to float +// X86WINPRMTD-NEXT: [[UNPROMOTION7:%.*]] = fptrunc double [[TMP32]] to float +// X86WINPRMTD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// X86WINPRMTD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// X86WINPRMTD-NEXT: store float [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 4 +// X86WINPRMTD-NEXT: store float [[UNPROMOTION7]], ptr [[RETVAL_IMAGP]], align 4 +// X86WINPRMTD-NEXT: [[TMP33:%.*]] = load i64, ptr [[RETVAL]], align 4 +// X86WINPRMTD-NEXT: ret i64 [[TMP33]] +// +// AVRFP32-LABEL: define dso_local { float, float } @f1( +// AVRFP32-SAME: float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]], float noundef [[B_COERCE0:%.*]], float noundef [[B_COERCE1:%.*]], float noundef [[C_COERCE0:%.*]], float noundef [[C_COERCE1:%.*]]) addrspace(1) #[[ATTR0]] { +// AVRFP32-NEXT: entry: +// AVRFP32-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[A:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[B:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[C:%.*]] = alloca { float, float }, align 1 +// AVRFP32-NEXT: [[TMP0:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP32-NEXT: store float [[A_COERCE0]], ptr [[TMP0]], align 1 +// AVRFP32-NEXT: [[TMP1:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[A_COERCE1]], ptr [[TMP1]], align 1 +// AVRFP32-NEXT: [[TMP2:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// AVRFP32-NEXT: store float [[B_COERCE0]], ptr [[TMP2]], align 1 +// AVRFP32-NEXT: [[TMP3:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[B_COERCE1]], ptr [[TMP3]], align 1 +// AVRFP32-NEXT: [[TMP4:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 0 +// AVRFP32-NEXT: store float [[C_COERCE0]], ptr [[TMP4]], align 1 +// AVRFP32-NEXT: [[TMP5:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[C_COERCE1]], ptr [[TMP5]], align 1 +// AVRFP32-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// AVRFP32-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 1 +// AVRFP32-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// AVRFP32-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 1 +// AVRFP32-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 0 +// AVRFP32-NEXT: [[C_REAL:%.*]] = load float, ptr [[C_REALP]], align 1 +// AVRFP32-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 1 +// AVRFP32-NEXT: [[C_IMAG:%.*]] = load float, ptr [[C_IMAGP]], align 1 +// AVRFP32-NEXT: [[TMP6:%.*]] = call addrspace(1) float @llvm.fabs.f32(float [[C_REAL]]) +// AVRFP32-NEXT: [[TMP7:%.*]] = call addrspace(1) float @llvm.fabs.f32(float [[C_IMAG]]) +// AVRFP32-NEXT: [[ABS_CMP:%.*]] = fcmp ugt float [[TMP6]], [[TMP7]] +// AVRFP32-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// AVRFP32: abs_rhsr_greater_or_equal_abs_rhsi: +// AVRFP32-NEXT: [[TMP8:%.*]] = fdiv float [[C_IMAG]], [[C_REAL]] +// AVRFP32-NEXT: [[TMP9:%.*]] = fmul float [[TMP8]], [[C_IMAG]] +// AVRFP32-NEXT: [[TMP10:%.*]] = fadd float [[C_REAL]], [[TMP9]] +// AVRFP32-NEXT: [[TMP11:%.*]] = fmul float [[B_IMAG]], [[TMP8]] +// AVRFP32-NEXT: [[TMP12:%.*]] = fadd float [[B_REAL]], [[TMP11]] +// AVRFP32-NEXT: [[TMP13:%.*]] = fdiv float [[TMP12]], [[TMP10]] +// AVRFP32-NEXT: [[TMP14:%.*]] = fmul float [[B_REAL]], [[TMP8]] +// AVRFP32-NEXT: [[TMP15:%.*]] = fsub float [[B_IMAG]], [[TMP14]] +// AVRFP32-NEXT: [[TMP16:%.*]] = fdiv float [[TMP15]], [[TMP10]] +// AVRFP32-NEXT: br label [[COMPLEX_DIV:%.*]] +// AVRFP32: abs_rhsr_less_than_abs_rhsi: +// AVRFP32-NEXT: [[TMP17:%.*]] = fdiv float [[C_REAL]], [[C_IMAG]] +// AVRFP32-NEXT: [[TMP18:%.*]] = fmul float [[TMP17]], [[C_REAL]] +// AVRFP32-NEXT: [[TMP19:%.*]] = fadd float [[C_IMAG]], [[TMP18]] +// AVRFP32-NEXT: [[TMP20:%.*]] = fmul float [[B_REAL]], [[TMP17]] +// AVRFP32-NEXT: [[TMP21:%.*]] = fadd float [[TMP20]], [[B_IMAG]] +// AVRFP32-NEXT: [[TMP22:%.*]] = fdiv float [[TMP21]], [[TMP19]] +// AVRFP32-NEXT: [[TMP23:%.*]] = fmul float [[B_IMAG]], [[TMP17]] +// AVRFP32-NEXT: [[TMP24:%.*]] = fsub float [[TMP23]], [[B_REAL]] +// AVRFP32-NEXT: [[TMP25:%.*]] = fdiv float [[TMP24]], [[TMP19]] +// AVRFP32-NEXT: br label [[COMPLEX_DIV]] +// AVRFP32: complex_div: +// AVRFP32-NEXT: [[TMP26:%.*]] = phi float [ [[TMP13]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP22]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// AVRFP32-NEXT: [[TMP27:%.*]] = phi float [ [[TMP16]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP25]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// AVRFP32-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP32-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 1 +// AVRFP32-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP32-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 1 +// AVRFP32-NEXT: [[TMP28:%.*]] = call addrspace(1) float @llvm.fabs.f32(float [[A_REAL]]) +// AVRFP32-NEXT: [[TMP29:%.*]] = call addrspace(1) float @llvm.fabs.f32(float [[A_IMAG]]) +// AVRFP32-NEXT: [[ABS_CMP1:%.*]] = fcmp ugt float [[TMP28]], [[TMP29]] +// AVRFP32-NEXT: br i1 [[ABS_CMP1]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI2:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI3:%.*]] +// AVRFP32: abs_rhsr_greater_or_equal_abs_rhsi2: +// AVRFP32-NEXT: [[TMP30:%.*]] = fdiv float [[A_IMAG]], [[A_REAL]] +// AVRFP32-NEXT: [[TMP31:%.*]] = fmul float [[TMP30]], [[A_IMAG]] +// AVRFP32-NEXT: [[TMP32:%.*]] = fadd float [[A_REAL]], [[TMP31]] +// AVRFP32-NEXT: [[TMP33:%.*]] = fmul float [[TMP27]], [[TMP30]] +// AVRFP32-NEXT: [[TMP34:%.*]] = fadd float [[TMP26]], [[TMP33]] +// AVRFP32-NEXT: [[TMP35:%.*]] = fdiv float [[TMP34]], [[TMP32]] +// AVRFP32-NEXT: [[TMP36:%.*]] = fmul float [[TMP26]], [[TMP30]] +// AVRFP32-NEXT: [[TMP37:%.*]] = fsub float [[TMP27]], [[TMP36]] +// AVRFP32-NEXT: [[TMP38:%.*]] = fdiv float [[TMP37]], [[TMP32]] +// AVRFP32-NEXT: br label [[COMPLEX_DIV4:%.*]] +// AVRFP32: abs_rhsr_less_than_abs_rhsi3: +// AVRFP32-NEXT: [[TMP39:%.*]] = fdiv float [[A_REAL]], [[A_IMAG]] +// AVRFP32-NEXT: [[TMP40:%.*]] = fmul float [[TMP39]], [[A_REAL]] +// AVRFP32-NEXT: [[TMP41:%.*]] = fadd float [[A_IMAG]], [[TMP40]] +// AVRFP32-NEXT: [[TMP42:%.*]] = fmul float [[TMP26]], [[TMP39]] +// AVRFP32-NEXT: [[TMP43:%.*]] = fadd float [[TMP42]], [[TMP27]] +// AVRFP32-NEXT: [[TMP44:%.*]] = fdiv float [[TMP43]], [[TMP41]] +// AVRFP32-NEXT: [[TMP45:%.*]] = fmul float [[TMP27]], [[TMP39]] +// AVRFP32-NEXT: [[TMP46:%.*]] = fsub float [[TMP45]], [[TMP26]] +// AVRFP32-NEXT: [[TMP47:%.*]] = fdiv float [[TMP46]], [[TMP41]] +// AVRFP32-NEXT: br label [[COMPLEX_DIV4]] +// AVRFP32: complex_div4: +// AVRFP32-NEXT: [[TMP48:%.*]] = phi float [ [[TMP35]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI2]] ], [ [[TMP44]], [[ABS_RHSR_LESS_THAN_ABS_RHSI3]] ] +// AVRFP32-NEXT: [[TMP49:%.*]] = phi float [ [[TMP38]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI2]] ], [ [[TMP47]], [[ABS_RHSR_LESS_THAN_ABS_RHSI3]] ] +// AVRFP32-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// AVRFP32-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// AVRFP32-NEXT: store float [[TMP48]], ptr [[RETVAL_REALP]], align 1 +// AVRFP32-NEXT: store float [[TMP49]], ptr [[RETVAL_IMAGP]], align 1 +// AVRFP32-NEXT: [[TMP50:%.*]] = load { float, float }, ptr [[RETVAL]], align 1 +// AVRFP32-NEXT: ret { float, float } [[TMP50]] +// +// AVRFP64-LABEL: define dso_local { float, float } @f1( +// AVRFP64-SAME: float noundef [[A_COERCE0:%.*]], float noundef [[A_COERCE1:%.*]], double noundef [[B_COERCE0:%.*]], double noundef [[B_COERCE1:%.*]], float noundef [[C_COERCE0:%.*]], float noundef [[C_COERCE1:%.*]]) addrspace(1) #[[ATTR0]] { +// AVRFP64-NEXT: entry: +// AVRFP64-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 1 +// AVRFP64-NEXT: [[A:%.*]] = alloca { float, float }, align 1 +// AVRFP64-NEXT: [[B:%.*]] = alloca { double, double }, align 1 +// AVRFP64-NEXT: [[C:%.*]] = alloca { float, float }, align 1 +// AVRFP64-NEXT: [[TMP0:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP64-NEXT: store float [[A_COERCE0]], ptr [[TMP0]], align 1 +// AVRFP64-NEXT: [[TMP1:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP64-NEXT: store float [[A_COERCE1]], ptr [[TMP1]], align 1 +// AVRFP64-NEXT: [[TMP2:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// AVRFP64-NEXT: store double [[B_COERCE0]], ptr [[TMP2]], align 1 +// AVRFP64-NEXT: [[TMP3:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// AVRFP64-NEXT: store double [[B_COERCE1]], ptr [[TMP3]], align 1 +// AVRFP64-NEXT: [[TMP4:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 0 +// AVRFP64-NEXT: store float [[C_COERCE0]], ptr [[TMP4]], align 1 +// AVRFP64-NEXT: [[TMP5:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 1 +// AVRFP64-NEXT: store float [[C_COERCE1]], ptr [[TMP5]], align 1 +// AVRFP64-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 0 +// AVRFP64-NEXT: [[B_REAL:%.*]] = load double, ptr [[B_REALP]], align 1 +// AVRFP64-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { double, double }, ptr [[B]], i32 0, i32 1 +// AVRFP64-NEXT: [[B_IMAG:%.*]] = load double, ptr [[B_IMAGP]], align 1 +// AVRFP64-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 0 +// AVRFP64-NEXT: [[C_REAL:%.*]] = load float, ptr [[C_REALP]], align 1 +// AVRFP64-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 1 +// AVRFP64-NEXT: [[C_IMAG:%.*]] = load float, ptr [[C_IMAGP]], align 1 +// AVRFP64-NEXT: [[CONV:%.*]] = fpext float [[C_REAL]] to double +// AVRFP64-NEXT: [[CONV1:%.*]] = fpext float [[C_IMAG]] to double +// AVRFP64-NEXT: [[TMP6:%.*]] = call addrspace(1) double @llvm.fabs.f64(double [[CONV]]) +// AVRFP64-NEXT: [[TMP7:%.*]] = call addrspace(1) double @llvm.fabs.f64(double [[CONV1]]) +// AVRFP64-NEXT: [[ABS_CMP:%.*]] = fcmp ugt double [[TMP6]], [[TMP7]] +// AVRFP64-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// AVRFP64: abs_rhsr_greater_or_equal_abs_rhsi: +// AVRFP64-NEXT: [[TMP8:%.*]] = fdiv double [[CONV1]], [[CONV]] +// AVRFP64-NEXT: [[TMP9:%.*]] = fmul double [[TMP8]], [[CONV1]] +// AVRFP64-NEXT: [[TMP10:%.*]] = fadd double [[CONV]], [[TMP9]] +// AVRFP64-NEXT: [[TMP11:%.*]] = fmul double [[B_IMAG]], [[TMP8]] +// AVRFP64-NEXT: [[TMP12:%.*]] = fadd double [[B_REAL]], [[TMP11]] +// AVRFP64-NEXT: [[TMP13:%.*]] = fdiv double [[TMP12]], [[TMP10]] +// AVRFP64-NEXT: [[TMP14:%.*]] = fmul double [[B_REAL]], [[TMP8]] +// AVRFP64-NEXT: [[TMP15:%.*]] = fsub double [[B_IMAG]], [[TMP14]] +// AVRFP64-NEXT: [[TMP16:%.*]] = fdiv double [[TMP15]], [[TMP10]] +// AVRFP64-NEXT: br label [[COMPLEX_DIV:%.*]] +// AVRFP64: abs_rhsr_less_than_abs_rhsi: +// AVRFP64-NEXT: [[TMP17:%.*]] = fdiv double [[CONV]], [[CONV1]] +// AVRFP64-NEXT: [[TMP18:%.*]] = fmul double [[TMP17]], [[CONV]] +// AVRFP64-NEXT: [[TMP19:%.*]] = fadd double [[CONV1]], [[TMP18]] +// AVRFP64-NEXT: [[TMP20:%.*]] = fmul double [[B_REAL]], [[TMP17]] +// AVRFP64-NEXT: [[TMP21:%.*]] = fadd double [[TMP20]], [[B_IMAG]] +// AVRFP64-NEXT: [[TMP22:%.*]] = fdiv double [[TMP21]], [[TMP19]] +// AVRFP64-NEXT: [[TMP23:%.*]] = fmul double [[B_IMAG]], [[TMP17]] +// AVRFP64-NEXT: [[TMP24:%.*]] = fsub double [[TMP23]], [[B_REAL]] +// AVRFP64-NEXT: [[TMP25:%.*]] = fdiv double [[TMP24]], [[TMP19]] +// AVRFP64-NEXT: br label [[COMPLEX_DIV]] +// AVRFP64: complex_div: +// AVRFP64-NEXT: [[TMP26:%.*]] = phi double [ [[TMP13]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP22]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// AVRFP64-NEXT: [[TMP27:%.*]] = phi double [ [[TMP16]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP25]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// AVRFP64-NEXT: [[CONV2:%.*]] = fptrunc double [[TMP26]] to float +// AVRFP64-NEXT: [[CONV3:%.*]] = fptrunc double [[TMP27]] to float +// AVRFP64-NEXT: [[EXT:%.*]] = fpext float [[CONV2]] to double +// AVRFP64-NEXT: [[EXT4:%.*]] = fpext float [[CONV3]] to double +// AVRFP64-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// AVRFP64-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 1 +// AVRFP64-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// AVRFP64-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 1 +// AVRFP64-NEXT: [[EXT5:%.*]] = fpext float [[A_REAL]] to double +// AVRFP64-NEXT: [[EXT6:%.*]] = fpext float [[A_IMAG]] to double +// AVRFP64-NEXT: [[TMP28:%.*]] = fmul double [[EXT]], [[EXT5]] +// AVRFP64-NEXT: [[TMP29:%.*]] = fmul double [[EXT4]], [[EXT6]] +// AVRFP64-NEXT: [[TMP30:%.*]] = fadd double [[TMP28]], [[TMP29]] +// AVRFP64-NEXT: [[TMP31:%.*]] = fmul double [[EXT5]], [[EXT5]] +// AVRFP64-NEXT: [[TMP32:%.*]] = fmul double [[EXT6]], [[EXT6]] +// AVRFP64-NEXT: [[TMP33:%.*]] = fadd double [[TMP31]], [[TMP32]] +// AVRFP64-NEXT: [[TMP34:%.*]] = fmul double [[EXT4]], [[EXT5]] +// AVRFP64-NEXT: [[TMP35:%.*]] = fmul double [[EXT]], [[EXT6]] +// AVRFP64-NEXT: [[TMP36:%.*]] = fsub double [[TMP34]], [[TMP35]] +// AVRFP64-NEXT: [[TMP37:%.*]] = fdiv double [[TMP30]], [[TMP33]] +// AVRFP64-NEXT: [[TMP38:%.*]] = fdiv double [[TMP36]], [[TMP33]] +// AVRFP64-NEXT: [[UNPROMOTION:%.*]] = fptrunc double [[TMP37]] to float +// AVRFP64-NEXT: [[UNPROMOTION7:%.*]] = fptrunc double [[TMP38]] to float +// AVRFP64-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// AVRFP64-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// AVRFP64-NEXT: store float [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 1 +// AVRFP64-NEXT: store float [[UNPROMOTION7]], ptr [[RETVAL_IMAGP]], align 1 +// AVRFP64-NEXT: [[TMP39:%.*]] = load { float, float }, ptr [[RETVAL]], align 1 +// AVRFP64-NEXT: ret { float, float } [[TMP39]] +// +// BASIC_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x float> @f1( +// BASIC_FAST-SAME: <2 x float> noundef nofpclass(nan inf) [[A_COERCE:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]], <2 x float> noundef nofpclass(nan inf) [[C_COERCE:%.*]]) #[[ATTR0]] { +// BASIC_FAST-NEXT: entry: +// BASIC_FAST-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// BASIC_FAST-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// BASIC_FAST-NEXT: [[C:%.*]] = alloca { float, float }, align 4 +// BASIC_FAST-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// BASIC_FAST-NEXT: store <2 x float> [[C_COERCE]], ptr [[C]], align 4 +// BASIC_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// BASIC_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// BASIC_FAST-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[C_REAL:%.*]] = load float, ptr [[C_REALP]], align 4 +// BASIC_FAST-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[C_IMAG:%.*]] = load float, ptr [[C_IMAGP]], align 4 +// BASIC_FAST-NEXT: [[CONV:%.*]] = fpext float [[C_REAL]] to x86_fp80 +// BASIC_FAST-NEXT: [[CONV1:%.*]] = fpext float [[C_IMAG]] to x86_fp80 +// BASIC_FAST-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[CONV]] +// BASIC_FAST-NEXT: [[TMP1:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[CONV1]] +// BASIC_FAST-NEXT: [[TMP2:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP0]], [[TMP1]] +// BASIC_FAST-NEXT: [[TMP3:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV]], [[CONV]] +// BASIC_FAST-NEXT: [[TMP4:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV1]], [[CONV1]] +// BASIC_FAST-NEXT: [[TMP5:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP3]], [[TMP4]] +// BASIC_FAST-NEXT: [[TMP6:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[CONV]] +// BASIC_FAST-NEXT: [[TMP7:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[CONV1]] +// BASIC_FAST-NEXT: [[TMP8:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP6]], [[TMP7]] +// BASIC_FAST-NEXT: [[TMP9:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP2]], [[TMP5]] +// BASIC_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP8]], [[TMP5]] +// BASIC_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP9]] to float +// BASIC_FAST-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP10]] to float +// BASIC_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// BASIC_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// BASIC_FAST-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// BASIC_FAST-NEXT: [[TMP11:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[CONV2]], [[A_REAL]] +// BASIC_FAST-NEXT: [[TMP12:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[CONV3]], [[A_IMAG]] +// BASIC_FAST-NEXT: [[TMP13:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP11]], [[TMP12]] +// BASIC_FAST-NEXT: [[TMP14:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_REAL]], [[A_REAL]] +// BASIC_FAST-NEXT: [[TMP15:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[A_IMAG]], [[A_IMAG]] +// BASIC_FAST-NEXT: [[TMP16:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP14]], [[TMP15]] +// BASIC_FAST-NEXT: [[TMP17:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[CONV3]], [[A_REAL]] +// BASIC_FAST-NEXT: [[TMP18:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[CONV2]], [[A_IMAG]] +// BASIC_FAST-NEXT: [[TMP19:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[TMP17]], [[TMP18]] +// BASIC_FAST-NEXT: [[TMP20:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP13]], [[TMP16]] +// BASIC_FAST-NEXT: [[TMP21:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP19]], [[TMP16]] +// BASIC_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// BASIC_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// BASIC_FAST-NEXT: store float [[TMP20]], ptr [[RETVAL_REALP]], align 4 +// BASIC_FAST-NEXT: store float [[TMP21]], ptr [[RETVAL_IMAGP]], align 4 +// BASIC_FAST-NEXT: [[TMP22:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// BASIC_FAST-NEXT: ret <2 x float> [[TMP22]] +// +// FULL_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x float> @f1( +// FULL_FAST-SAME: <2 x float> noundef nofpclass(nan inf) [[A_COERCE:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]], <2 x float> noundef nofpclass(nan inf) [[C_COERCE:%.*]]) #[[ATTR0]] { +// FULL_FAST-NEXT: entry: +// FULL_FAST-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// FULL_FAST-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// FULL_FAST-NEXT: [[C:%.*]] = alloca { float, float }, align 4 +// FULL_FAST-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4 +// FULL_FAST-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// FULL_FAST-NEXT: store <2 x float> [[C_COERCE]], ptr [[C]], align 4 +// FULL_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// FULL_FAST-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// FULL_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// FULL_FAST-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// FULL_FAST-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 0 +// FULL_FAST-NEXT: [[C_REAL:%.*]] = load float, ptr [[C_REALP]], align 4 +// FULL_FAST-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 1 +// FULL_FAST-NEXT: [[C_IMAG:%.*]] = load float, ptr [[C_IMAGP]], align 4 +// FULL_FAST-NEXT: [[CONV:%.*]] = fpext float [[C_REAL]] to x86_fp80 +// FULL_FAST-NEXT: [[CONV1:%.*]] = fpext float [[C_IMAG]] to x86_fp80 +// FULL_FAST-NEXT: [[CALL:%.*]] = call { x86_fp80, x86_fp80 } @__divxc3(x86_fp80 noundef nofpclass(nan inf) [[B_REAL]], x86_fp80 noundef nofpclass(nan inf) [[B_IMAG]], x86_fp80 noundef nofpclass(nan inf) [[CONV]], x86_fp80 noundef nofpclass(nan inf) [[CONV1]]) #[[ATTR2]] +// FULL_FAST-NEXT: [[TMP0:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 0 +// FULL_FAST-NEXT: [[TMP1:%.*]] = extractvalue { x86_fp80, x86_fp80 } [[CALL]], 1 +// FULL_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP0]] to float +// FULL_FAST-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP1]] to float +// FULL_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// FULL_FAST-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// FULL_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// FULL_FAST-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// FULL_FAST-NEXT: [[CALL4:%.*]] = call reassoc nnan ninf nsz arcp afn nofpclass(nan inf) <2 x float> @__divsc3(float noundef nofpclass(nan inf) [[CONV2]], float noundef nofpclass(nan inf) [[CONV3]], float noundef nofpclass(nan inf) [[A_REAL]], float noundef nofpclass(nan inf) [[A_IMAG]]) #[[ATTR2]] +// FULL_FAST-NEXT: store <2 x float> [[CALL4]], ptr [[COERCE]], align 4 +// FULL_FAST-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 0 +// FULL_FAST-NEXT: [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4 +// FULL_FAST-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[COERCE]], i32 0, i32 1 +// FULL_FAST-NEXT: [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4 +// FULL_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// FULL_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// FULL_FAST-NEXT: store float [[COERCE_REAL]], ptr [[RETVAL_REALP]], align 4 +// FULL_FAST-NEXT: store float [[COERCE_IMAG]], ptr [[RETVAL_IMAGP]], align 4 +// FULL_FAST-NEXT: [[TMP2:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// FULL_FAST-NEXT: ret <2 x float> [[TMP2]] +// +// IMPRVD_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x float> @f1( +// IMPRVD_FAST-SAME: <2 x float> noundef nofpclass(nan inf) [[A_COERCE:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]], <2 x float> noundef nofpclass(nan inf) [[C_COERCE:%.*]]) #[[ATTR0]] { +// IMPRVD_FAST-NEXT: entry: +// IMPRVD_FAST-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// IMPRVD_FAST-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// IMPRVD_FAST-NEXT: [[C:%.*]] = alloca { float, float }, align 4 +// IMPRVD_FAST-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// IMPRVD_FAST-NEXT: store <2 x float> [[C_COERCE]], ptr [[C]], align 4 +// IMPRVD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// IMPRVD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// IMPRVD_FAST-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[C_REAL:%.*]] = load float, ptr [[C_REALP]], align 4 +// IMPRVD_FAST-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[C_IMAG:%.*]] = load float, ptr [[C_IMAGP]], align 4 +// IMPRVD_FAST-NEXT: [[CONV:%.*]] = fpext float [[C_REAL]] to x86_fp80 +// IMPRVD_FAST-NEXT: [[CONV1:%.*]] = fpext float [[C_IMAG]] to x86_fp80 +// IMPRVD_FAST-NEXT: [[TMP0:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV]]) +// IMPRVD_FAST-NEXT: [[TMP1:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV1]]) +// IMPRVD_FAST-NEXT: [[ABS_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn ugt x86_fp80 [[TMP0]], [[TMP1]] +// IMPRVD_FAST-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// IMPRVD_FAST: abs_rhsr_greater_or_equal_abs_rhsi: +// IMPRVD_FAST-NEXT: [[TMP2:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV1]], [[CONV]] +// IMPRVD_FAST-NEXT: [[TMP3:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP2]], [[CONV1]] +// IMPRVD_FAST-NEXT: [[TMP4:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV]], [[TMP3]] +// IMPRVD_FAST-NEXT: [[TMP5:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[TMP2]] +// IMPRVD_FAST-NEXT: [[TMP6:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[TMP5]] +// IMPRVD_FAST-NEXT: [[TMP7:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP6]], [[TMP4]] +// IMPRVD_FAST-NEXT: [[TMP8:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[TMP2]] +// IMPRVD_FAST-NEXT: [[TMP9:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[TMP8]] +// IMPRVD_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP9]], [[TMP4]] +// IMPRVD_FAST-NEXT: br label [[COMPLEX_DIV:%.*]] +// IMPRVD_FAST: abs_rhsr_less_than_abs_rhsi: +// IMPRVD_FAST-NEXT: [[TMP11:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV]], [[CONV1]] +// IMPRVD_FAST-NEXT: [[TMP12:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP11]], [[CONV]] +// IMPRVD_FAST-NEXT: [[TMP13:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV1]], [[TMP12]] +// IMPRVD_FAST-NEXT: [[TMP14:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[TMP11]] +// IMPRVD_FAST-NEXT: [[TMP15:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP14]], [[B_IMAG]] +// IMPRVD_FAST-NEXT: [[TMP16:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP15]], [[TMP13]] +// IMPRVD_FAST-NEXT: [[TMP17:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[TMP11]] +// IMPRVD_FAST-NEXT: [[TMP18:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP17]], [[B_REAL]] +// IMPRVD_FAST-NEXT: [[TMP19:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP18]], [[TMP13]] +// IMPRVD_FAST-NEXT: br label [[COMPLEX_DIV]] +// IMPRVD_FAST: complex_div: +// IMPRVD_FAST-NEXT: [[TMP20:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD_FAST-NEXT: [[TMP21:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP20]] to float +// IMPRVD_FAST-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP21]] to float +// IMPRVD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// IMPRVD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// IMPRVD_FAST-NEXT: [[TMP22:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.fabs.f32(float [[A_REAL]]) +// IMPRVD_FAST-NEXT: [[TMP23:%.*]] = call reassoc nnan ninf nsz arcp afn float @llvm.fabs.f32(float [[A_IMAG]]) +// IMPRVD_FAST-NEXT: [[ABS_CMP4:%.*]] = fcmp reassoc nnan ninf nsz arcp afn ugt float [[TMP22]], [[TMP23]] +// IMPRVD_FAST-NEXT: br i1 [[ABS_CMP4]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI5:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI6:%.*]] +// IMPRVD_FAST: abs_rhsr_greater_or_equal_abs_rhsi5: +// IMPRVD_FAST-NEXT: [[TMP24:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[A_IMAG]], [[A_REAL]] +// IMPRVD_FAST-NEXT: [[TMP25:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP24]], [[A_IMAG]] +// IMPRVD_FAST-NEXT: [[TMP26:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[A_REAL]], [[TMP25]] +// IMPRVD_FAST-NEXT: [[TMP27:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[CONV3]], [[TMP24]] +// IMPRVD_FAST-NEXT: [[TMP28:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[CONV2]], [[TMP27]] +// IMPRVD_FAST-NEXT: [[TMP29:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP28]], [[TMP26]] +// IMPRVD_FAST-NEXT: [[TMP30:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[CONV2]], [[TMP24]] +// IMPRVD_FAST-NEXT: [[TMP31:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[CONV3]], [[TMP30]] +// IMPRVD_FAST-NEXT: [[TMP32:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP31]], [[TMP26]] +// IMPRVD_FAST-NEXT: br label [[COMPLEX_DIV7:%.*]] +// IMPRVD_FAST: abs_rhsr_less_than_abs_rhsi6: +// IMPRVD_FAST-NEXT: [[TMP33:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[A_REAL]], [[A_IMAG]] +// IMPRVD_FAST-NEXT: [[TMP34:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP33]], [[A_REAL]] +// IMPRVD_FAST-NEXT: [[TMP35:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[A_IMAG]], [[TMP34]] +// IMPRVD_FAST-NEXT: [[TMP36:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[CONV2]], [[TMP33]] +// IMPRVD_FAST-NEXT: [[TMP37:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP36]], [[CONV3]] +// IMPRVD_FAST-NEXT: [[TMP38:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP37]], [[TMP35]] +// IMPRVD_FAST-NEXT: [[TMP39:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[CONV3]], [[TMP33]] +// IMPRVD_FAST-NEXT: [[TMP40:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[TMP39]], [[CONV2]] +// IMPRVD_FAST-NEXT: [[TMP41:%.*]] = fdiv reassoc nnan ninf nsz arcp afn float [[TMP40]], [[TMP35]] +// IMPRVD_FAST-NEXT: br label [[COMPLEX_DIV7]] +// IMPRVD_FAST: complex_div7: +// IMPRVD_FAST-NEXT: [[TMP42:%.*]] = phi reassoc nnan ninf nsz arcp afn float [ [[TMP29]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI5]] ], [ [[TMP38]], [[ABS_RHSR_LESS_THAN_ABS_RHSI6]] ] +// IMPRVD_FAST-NEXT: [[TMP43:%.*]] = phi reassoc nnan ninf nsz arcp afn float [ [[TMP32]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI5]] ], [ [[TMP41]], [[ABS_RHSR_LESS_THAN_ABS_RHSI6]] ] +// IMPRVD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD_FAST-NEXT: store float [[TMP42]], ptr [[RETVAL_REALP]], align 4 +// IMPRVD_FAST-NEXT: store float [[TMP43]], ptr [[RETVAL_IMAGP]], align 4 +// IMPRVD_FAST-NEXT: [[TMP44:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// IMPRVD_FAST-NEXT: ret <2 x float> [[TMP44]] +// +// PRMTD_FAST-LABEL: define dso_local nofpclass(nan inf) <2 x float> @f1( +// PRMTD_FAST-SAME: <2 x float> noundef nofpclass(nan inf) [[A_COERCE:%.*]], ptr noundef byval({ x86_fp80, x86_fp80 }) align 16 [[B:%.*]], <2 x float> noundef nofpclass(nan inf) [[C_COERCE:%.*]]) #[[ATTR0]] { +// PRMTD_FAST-NEXT: entry: +// PRMTD_FAST-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// PRMTD_FAST-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// PRMTD_FAST-NEXT: [[C:%.*]] = alloca { float, float }, align 4 +// PRMTD_FAST-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// PRMTD_FAST-NEXT: store <2 x float> [[C_COERCE]], ptr [[C]], align 4 +// PRMTD_FAST-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[B_REAL:%.*]] = load x86_fp80, ptr [[B_REALP]], align 16 +// PRMTD_FAST-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { x86_fp80, x86_fp80 }, ptr [[B]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[B_IMAG:%.*]] = load x86_fp80, ptr [[B_IMAGP]], align 16 +// PRMTD_FAST-NEXT: [[C_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[C_REAL:%.*]] = load float, ptr [[C_REALP]], align 4 +// PRMTD_FAST-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[C]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[C_IMAG:%.*]] = load float, ptr [[C_IMAGP]], align 4 +// PRMTD_FAST-NEXT: [[CONV:%.*]] = fpext float [[C_REAL]] to x86_fp80 +// PRMTD_FAST-NEXT: [[CONV1:%.*]] = fpext float [[C_IMAG]] to x86_fp80 +// PRMTD_FAST-NEXT: [[TMP0:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV]]) +// PRMTD_FAST-NEXT: [[TMP1:%.*]] = call reassoc nnan ninf nsz arcp afn x86_fp80 @llvm.fabs.f80(x86_fp80 [[CONV1]]) +// PRMTD_FAST-NEXT: [[ABS_CMP:%.*]] = fcmp reassoc nnan ninf nsz arcp afn ugt x86_fp80 [[TMP0]], [[TMP1]] +// PRMTD_FAST-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// PRMTD_FAST: abs_rhsr_greater_or_equal_abs_rhsi: +// PRMTD_FAST-NEXT: [[TMP2:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV1]], [[CONV]] +// PRMTD_FAST-NEXT: [[TMP3:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP2]], [[CONV1]] +// PRMTD_FAST-NEXT: [[TMP4:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV]], [[TMP3]] +// PRMTD_FAST-NEXT: [[TMP5:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[TMP2]] +// PRMTD_FAST-NEXT: [[TMP6:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[TMP5]] +// PRMTD_FAST-NEXT: [[TMP7:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP6]], [[TMP4]] +// PRMTD_FAST-NEXT: [[TMP8:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[TMP2]] +// PRMTD_FAST-NEXT: [[TMP9:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[TMP8]] +// PRMTD_FAST-NEXT: [[TMP10:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP9]], [[TMP4]] +// PRMTD_FAST-NEXT: br label [[COMPLEX_DIV:%.*]] +// PRMTD_FAST: abs_rhsr_less_than_abs_rhsi: +// PRMTD_FAST-NEXT: [[TMP11:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV]], [[CONV1]] +// PRMTD_FAST-NEXT: [[TMP12:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP11]], [[CONV]] +// PRMTD_FAST-NEXT: [[TMP13:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[CONV1]], [[TMP12]] +// PRMTD_FAST-NEXT: [[TMP14:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_REAL]], [[TMP11]] +// PRMTD_FAST-NEXT: [[TMP15:%.*]] = fadd reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP14]], [[B_IMAG]] +// PRMTD_FAST-NEXT: [[TMP16:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP15]], [[TMP13]] +// PRMTD_FAST-NEXT: [[TMP17:%.*]] = fmul reassoc nnan ninf nsz arcp afn x86_fp80 [[B_IMAG]], [[TMP11]] +// PRMTD_FAST-NEXT: [[TMP18:%.*]] = fsub reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP17]], [[B_REAL]] +// PRMTD_FAST-NEXT: [[TMP19:%.*]] = fdiv reassoc nnan ninf nsz arcp afn x86_fp80 [[TMP18]], [[TMP13]] +// PRMTD_FAST-NEXT: br label [[COMPLEX_DIV]] +// PRMTD_FAST: complex_div: +// PRMTD_FAST-NEXT: [[TMP20:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// PRMTD_FAST-NEXT: [[TMP21:%.*]] = phi reassoc nnan ninf nsz arcp afn x86_fp80 [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// PRMTD_FAST-NEXT: [[CONV2:%.*]] = fptrunc x86_fp80 [[TMP20]] to float +// PRMTD_FAST-NEXT: [[CONV3:%.*]] = fptrunc x86_fp80 [[TMP21]] to float +// PRMTD_FAST-NEXT: [[EXT:%.*]] = fpext float [[CONV2]] to double +// PRMTD_FAST-NEXT: [[EXT4:%.*]] = fpext float [[CONV3]] to double +// PRMTD_FAST-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// PRMTD_FAST-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// PRMTD_FAST-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// PRMTD_FAST-NEXT: [[EXT5:%.*]] = fpext float [[A_REAL]] to double +// PRMTD_FAST-NEXT: [[EXT6:%.*]] = fpext float [[A_IMAG]] to double +// PRMTD_FAST-NEXT: [[TMP22:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[EXT]], [[EXT5]] +// PRMTD_FAST-NEXT: [[TMP23:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[EXT4]], [[EXT6]] +// PRMTD_FAST-NEXT: [[TMP24:%.*]] = fadd reassoc nnan ninf nsz arcp afn double [[TMP22]], [[TMP23]] +// PRMTD_FAST-NEXT: [[TMP25:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[EXT5]], [[EXT5]] +// PRMTD_FAST-NEXT: [[TMP26:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[EXT6]], [[EXT6]] +// PRMTD_FAST-NEXT: [[TMP27:%.*]] = fadd reassoc nnan ninf nsz arcp afn double [[TMP25]], [[TMP26]] +// PRMTD_FAST-NEXT: [[TMP28:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[EXT4]], [[EXT5]] +// PRMTD_FAST-NEXT: [[TMP29:%.*]] = fmul reassoc nnan ninf nsz arcp afn double [[EXT]], [[EXT6]] +// PRMTD_FAST-NEXT: [[TMP30:%.*]] = fsub reassoc nnan ninf nsz arcp afn double [[TMP28]], [[TMP29]] +// PRMTD_FAST-NEXT: [[TMP31:%.*]] = fdiv reassoc nnan ninf nsz arcp afn double [[TMP24]], [[TMP27]] +// PRMTD_FAST-NEXT: [[TMP32:%.*]] = fdiv reassoc nnan ninf nsz arcp afn double [[TMP30]], [[TMP27]] +// PRMTD_FAST-NEXT: [[UNPROMOTION:%.*]] = fptrunc double [[TMP31]] to float +// PRMTD_FAST-NEXT: [[UNPROMOTION7:%.*]] = fptrunc double [[TMP32]] to float +// PRMTD_FAST-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// PRMTD_FAST-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// PRMTD_FAST-NEXT: store float [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 4 +// PRMTD_FAST-NEXT: store float [[UNPROMOTION7]], ptr [[RETVAL_IMAGP]], align 4 +// PRMTD_FAST-NEXT: [[TMP33:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// PRMTD_FAST-NEXT: ret <2 x float> [[TMP33]] +// +_Complex float f1(_Complex float a, _Complex long double b, _Complex float c) { + return (_Complex float)(b / c) / a; +} diff --git a/clang/test/CodeGen/debug-info-bitfield-0-struct.c b/clang/test/CodeGen/debug-info-bitfield-0-struct.c index 0535b626771429153456d2cc5c71c437b6d5ffe8..9fadf898e34661856806832d2ed60f8b1da271f5 100644 --- a/clang/test/CodeGen/debug-info-bitfield-0-struct.c +++ b/clang/test/CodeGen/debug-info-bitfield-0-struct.c @@ -101,8 +101,10 @@ struct None_B { int y : 4; }; -struct None_C { - // BOTH-DAG: ![[NONE_C:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "None_C", file: !{{[0-9]+}}, line: {{[0-9]+}}, size: 32, elements: ![[NONE_C_ELEMENTS:[0-9]+]]) +// AMDGCN does not do unaligned access cheaply, so the bitfield access units +// would remain single bytes, without the aligned attribure +struct __attribute__((aligned(4))) None_C { + // BOTH-DAG: ![[NONE_C:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "None_C", file: !{{[0-9]+}}, line: {{[0-9]+}}, size: 32, align: 32, elements: ![[NONE_C_ELEMENTS:[0-9]+]]) // BOTH-DAG: ![[NONE_C_ELEMENTS]] = !{![[NONE_C_X:[0-9]+]], ![[NONE_C_Y:[0-9]+]], ![[NONE_C_A:[0-9]+]], ![[NONE_C_B:[0-9]+]]} // BOTH-DAG: ![[NONE_C_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: ![[NONE_C]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 8, flags: DIFlagBitField, extraData: i64 0) // BOTH-DAG: ![[NONE_C_Y]] = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: ![[NONE_C]], file: !{{[0-9]+}}, line: {{[0-9]+}}, baseType: !{{[0-9]+}}, size: 8, offset: 8, flags: DIFlagBitField, extraData: i64 0) diff --git a/clang/test/CodeGen/debug-info-cc.c b/clang/test/CodeGen/debug-info-cc.c index 2664bcd4cb6b2d2fed409ac685c0aa8c31f653f7..2bfb1c28e9353bb7b34f2785c9aaf0f2d6cf1ee7 100644 --- a/clang/test/CodeGen/debug-info-cc.c +++ b/clang/test/CodeGen/debug-info-cc.c @@ -64,11 +64,10 @@ __attribute__((swiftcall)) int add_swiftcall(int a, int b) { return a+b; } -// [FIXME: swiftasynccc] Update debuginfo tag to SwiftAsync once LLVM support lands. // LINUX: !DISubprogram({{.*}}"add_swiftasynccall", {{.*}}type: ![[FTY:[0-9]+]] -// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_Swift, -__attribute__((swiftasynccall)) int add_swiftasynccall(int a, int b, int c) { - return a+b+c; +// LINUX: ![[FTY]] = !DISubroutineType({{.*}}cc: DW_CC_LLVM_SwiftTail, +__attribute__((swiftasynccall)) int add_swiftasynccall(int a, int b) { + return a+b; } // LINUX: !DISubprogram({{.*}}"add_inteloclbicc", {{.*}}type: ![[FTY:[0-9]+]] diff --git a/clang/test/CodeGen/flexible-array-init.c b/clang/test/CodeGen/flexible-array-init.c index bae926da5feb0701a5a5f5ec0af2009ff6c65b32..15a30c15ac966effae52a0716a5ca4f8e2ccb5b1 100644 --- a/clang/test/CodeGen/flexible-array-init.c +++ b/clang/test/CodeGen/flexible-array-init.c @@ -3,9 +3,15 @@ struct { int x; int y[]; } a = { 1, 7, 11 }; // CHECK: @a ={{.*}} global { i32, [2 x i32] } { i32 1, [2 x i32] [i32 7, i32 11] } +struct { int y[]; } a1 = { 8, 12 }; +// CHECK: @a1 ={{.*}} global { [2 x i32] } { [2 x i32] [i32 8, i32 12] } + struct { int x; int y[]; } b = { 1, { 13, 15 } }; // CHECK: @b ={{.*}} global { i32, [2 x i32] } { i32 1, [2 x i32] [i32 13, i32 15] } +struct { int y[]; } b1 = { { 14, 16 } }; +// CHECK: @b1 ={{.*}} global { [2 x i32] } { [2 x i32] [i32 14, i32 16] } + // sizeof(c) == 8, so this global should be at least 8 bytes. struct { int x; char c; char y[]; } c = { 1, 2, { 13, 15 } }; // CHECK: @c ={{.*}} global { i32, i8, [2 x i8] } { i32 1, i8 2, [2 x i8] c"\0D\0F" } @@ -21,10 +27,79 @@ struct __attribute((packed, aligned(4))) { char a; int x; char z[]; } e = { 1, 2 struct { int x; char y[]; } f = { 1, { 13, 15 } }; // CHECK: @f ={{.*}} global <{ i32, [2 x i8] }> <{ i32 1, [2 x i8] c"\0D\0F" }> -union { - struct { - int a; - char b[]; - } x; -} in_union = {}; -// CHECK: @in_union ={{.*}} global %union.anon zeroinitializer +struct __attribute((packed)) { short a; char z[]; } g = { 2, { 11, 13, 15 } }; +// CHECK: @g ={{.*}} <{ i16, [3 x i8] }> <{ i16 2, [3 x i8] c"\0B\0D\0F" }>, + +// Last member is the potential flexible array, unnamed initializer skips it. +struct { int a; union { int b; short x; }; int c; int d; } h = {1, 2, {}, 3}; +// CHECK: @h = global %struct.anon{{.*}} { i32 1, %union.anon{{.*}} { i32 2 }, i32 0, i32 3 } +struct { int a; union { int b; short x[0]; }; int c; int d; } h0 = {1, 2, {}, 3}; +// CHECK: @h0 = global %struct.anon{{.*}} { i32 1, %union.anon{{.*}} { i32 2 }, i32 0, i32 3 } +struct { int a; union { int b; short x[1]; }; int c; int d; } h1 = {1, 2, {}, 3}; +// CHECK: @h1 = global %struct.anon{{.*}} { i32 1, %union.anon{{.*}} { i32 2 }, i32 0, i32 3 } +struct { + int a; + union { + int b; + struct { + struct { } __ununsed; + short x[]; + }; + }; + int c; + int d; +} hiding = {1, 2, {}, 3}; +// CHECK: @hiding = global %struct.anon{{.*}} { i32 1, %union.anon{{.*}} { i32 2 }, i32 0, i32 3 } +struct { int a; union { int b; short x[]; }; int c; int d; } hf = {1, 2, {}, 3}; +// CHECK: @hf = global %struct.anon{{.*}} { i32 1, %union.anon{{.*}} { i32 2 }, i32 0, i32 3 } + +// First member is the potential flexible array, initialization requires braces. +struct { int a; union { short x; int b; }; int c; int d; } i = {1, 2, {}, 3}; +// CHECK: @i = global { i32, { i16, [2 x i8] }, i32, i32 } { i32 1, { i16, [2 x i8] } { i16 2, [2 x i8] undef }, i32 0, i32 3 } +struct { int a; union { short x[0]; int b; }; int c; int d; } i0 = {1, {}, 2, 3}; +// CHECK: @i0 = global { i32, { [0 x i16], [4 x i8] }, i32, i32 } { i32 1, { [0 x i16], [4 x i8] } { [0 x i16] zeroinitializer, [4 x i8] undef }, i32 2, i32 3 } +struct { int a; union { short x[1]; int b; }; int c; int d; } i1 = {1, {2}, {}, 3}; +// CHECK: @i1 = global { i32, { [1 x i16], [2 x i8] }, i32, i32 } { i32 1, { [1 x i16], [2 x i8] } { [1 x i16] [i16 2], [2 x i8] undef }, i32 0, i32 3 } +struct { int a; union { short x[]; int b; }; int c; int d; } i_f = {4, {}, {}, 6}; +// CHECK: @i_f = global { i32, { [0 x i16], [4 x i8] }, i32, i32 } { i32 4, { [0 x i16], [4 x i8] } { [0 x i16] zeroinitializer, [4 x i8] undef }, i32 0, i32 6 } + +// Named initializers; order doesn't matter. +struct { int a; union { int b; short x; }; int c; int d; } hn = {.a = 1, .x = 2, .c = 3}; +// CHECK: @hn = global { i32, { i16, [2 x i8] }, i32, i32 } { i32 1, { i16, [2 x i8] } { i16 2, [2 x i8] undef }, i32 3, i32 0 } +struct { int a; union { int b; short x[0]; }; int c; int d; } hn0 = {.a = 1, .x = {2}, .c = 3}; +// CHECK: @hn0 = global { i32, { [0 x i16], [4 x i8] }, i32, i32 } { i32 1, { [0 x i16], [4 x i8] } { [0 x i16] zeroinitializer, [4 x i8] undef }, i32 3, i32 0 } +struct { int a; union { int b; short x[1]; }; int c; int d; } hn1 = {.a = 1, .x = {2}, .c = 3}; +// CHECK: @hn1 = global { i32, { [1 x i16], [2 x i8] }, i32, i32 } { i32 1, { [1 x i16], [2 x i8] } { [1 x i16] [i16 2], [2 x i8] undef }, i32 3, i32 0 } + +struct { char a[]; } empty_struct = {}; +// CHECK: @empty_struct ={{.*}} global %struct.anon{{.*}} zeroinitializer, align 1 + +struct { char a[]; } empty_struct0 = {0}; +// CHECK: @empty_struct0 = global { [1 x i8] } zeroinitializer, align 1 + +union { struct { int a; char b[]; }; } struct_in_union = {}; +// CHECK: @struct_in_union = global %union.anon{{.*}} zeroinitializer, align 4 + +union { struct { int a; char b[]; }; } struct_in_union0 = {0}; +// CHECK: @struct_in_union0 = global %union.anon{{.*}} zeroinitializer, align 4 + +union { int a; char b[]; } trailing_in_union = {}; +// CHECK: @trailing_in_union = global %union.anon{{.*}} zeroinitializer, align 4 + +union { int a; char b[]; } trailing_in_union0 = {0}; +// CHECK: @trailing_in_union0 = global %union.anon{{.*}} zeroinitializer, align 4 + +union { char a[]; } only_in_union = {}; +// CHECK: @only_in_union = global %union.anon{{.*}} zeroinitializer, align 1 + +union { char a[]; } only_in_union0 = {0}; +// CHECK: @only_in_union0 = global { [1 x i8] } zeroinitializer, align 1 + +union { char a[]; int b; } first_in_union = {}; +// CHECK: @first_in_union = global { [0 x i8], [4 x i8] } { [0 x i8] zeroinitializer, [4 x i8] undef }, align 4 + +union { char a[]; int b; } first_in_union0 = {0}; +// CHECK: @first_in_union0 = global { [1 x i8], [3 x i8] } { [1 x i8] zeroinitializer, [3 x i8] undef }, align 4 + +union { char a[]; int b; } first_in_union123 = { {1, 2, 3} }; +// CHECK: @first_in_union123 = global { [3 x i8], i8 } { [3 x i8] c"\01\02\03", i8 undef }, align 4 diff --git a/clang/test/CodeGen/flexible-array-init.cpp b/clang/test/CodeGen/flexible-array-init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d067a614e1afe5da1d8d9dc4fb08323cd175f745 --- /dev/null +++ b/clang/test/CodeGen/flexible-array-init.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -triple i386-unknown-unknown -x c++ -emit-llvm -o - %s | FileCheck %s + +union _u { char a[]; } u = {}; +union _u0 { char a[]; } u0 = {0}; + +// CHECK: %union._u = type { [0 x i8] } + +// CHECK: @u = global %union._u zeroinitializer, align 1 +// CHECK: @u0 = global { [1 x i8] } zeroinitializer, align 1 + +union { char a[]; } z = {}; +// CHECK: @z = internal global %union.{{.*}} zeroinitializer, align 1 +union { char a[]; } z0 = {0}; +// CHECK: @z0 = internal global { [1 x i8] } zeroinitializer, align 1 + +/* C++ requires global anonymous unions have static storage, so we have to + reference them to keep them in the IR output. */ +char keep(int pick) +{ + if (pick) + return z.a[0]; + else + return z0.a[0]; +} diff --git a/clang/test/CodeGen/hexagon-linux-vararg.c b/clang/test/CodeGen/hexagon-linux-vararg.c index 033e72ab449d319991203fc6376343a38a4bd60b..84945e872d28bc8f0522cc35abb4b72aca795439 100644 --- a/clang/test/CodeGen/hexagon-linux-vararg.c +++ b/clang/test/CodeGen/hexagon-linux-vararg.c @@ -9,7 +9,7 @@ struct AAA { int d; }; -// CHECK: call void @llvm.va_start(ptr %arraydecay) +// CHECK: call void @llvm.va_start.p0(ptr %arraydecay) // CHECK: %arraydecay1 = getelementptr inbounds [1 x %struct.__va_list_tag], // ptr %ap, i32 0, i32 0 // CHECK: br label %vaarg.maybe_reg diff --git a/clang/test/CodeGen/mips-varargs.c b/clang/test/CodeGen/mips-varargs.c index 052aedd1cd1e2c7dbfecce85c417277f319db378..029f000c121a5b8c4b18d4e9d4fafa0cc6d4f8e6 100644 --- a/clang/test/CodeGen/mips-varargs.c +++ b/clang/test/CodeGen/mips-varargs.c @@ -29,7 +29,7 @@ int test_i32(char *fmt, ...) { // ALL: [[V:%.*]] = alloca i32, align 4 // NEW: [[PROMOTION_TEMP:%.*]] = alloca i32, align 4 // -// ALL: call void @llvm.va_start(ptr %va) +// ALL: call void @llvm.va_start.p0(ptr %va) // ALL: [[AP_CUR:%.+]] = load ptr, ptr %va, align [[$PTRALIGN]] // O32: [[AP_NEXT:%.+]] = getelementptr inbounds i8, ptr [[AP_CUR]], [[$INTPTR_T:i32]] [[$CHUNKSIZE:4]] // NEW: [[AP_NEXT:%.+]] = getelementptr inbounds i8, ptr [[AP_CUR]], [[$INTPTR_T:i32|i64]] [[$CHUNKSIZE:8]] @@ -45,7 +45,7 @@ int test_i32(char *fmt, ...) { // NEW: [[ARG:%.+]] = load i32, ptr [[PROMOTION_TEMP]], align 4 // ALL: store i32 [[ARG]], ptr [[V]], align 4 // -// ALL: call void @llvm.va_end(ptr %va) +// ALL: call void @llvm.va_end.p0(ptr %va) // ALL: } long long test_i64(char *fmt, ...) { @@ -61,7 +61,7 @@ long long test_i64(char *fmt, ...) { // ALL-LABEL: define{{.*}} i64 @test_i64(ptr{{.*}} %fmt, ...) // // ALL: %va = alloca ptr, align [[$PTRALIGN]] -// ALL: call void @llvm.va_start(ptr %va) +// ALL: call void @llvm.va_start.p0(ptr %va) // ALL: [[AP_CUR:%.+]] = load ptr, ptr %va, align [[$PTRALIGN]] // // i64 is 8-byte aligned, while this is within O32's stack alignment there's no @@ -74,7 +74,7 @@ long long test_i64(char *fmt, ...) { // // ALL: [[ARG:%.+]] = load i64, ptr [[AP_CUR]], align 8 // -// ALL: call void @llvm.va_end(ptr %va) +// ALL: call void @llvm.va_end.p0(ptr %va) // ALL: } char *test_ptr(char *fmt, ...) { @@ -92,7 +92,7 @@ char *test_ptr(char *fmt, ...) { // ALL: %va = alloca ptr, align [[$PTRALIGN]] // ALL: [[V:%.*]] = alloca ptr, align [[$PTRALIGN]] // N32: [[AP_CAST:%.+]] = alloca ptr, align 4 -// ALL: call void @llvm.va_start(ptr %va) +// ALL: call void @llvm.va_start.p0(ptr %va) // ALL: [[AP_CUR:%.+]] = load ptr, ptr %va, align [[$PTRALIGN]] // ALL: [[AP_NEXT:%.+]] = getelementptr inbounds i8, ptr [[AP_CUR]], [[$INTPTR_T]] [[$CHUNKSIZE]] // ALL: store ptr [[AP_NEXT]], ptr %va, align [[$PTRALIGN]] @@ -109,7 +109,7 @@ char *test_ptr(char *fmt, ...) { // N64: [[ARG:%.+]] = load ptr, ptr [[AP_CUR]], align [[$PTRALIGN]] // ALL: store ptr [[ARG]], ptr [[V]], align [[$PTRALIGN]] // -// ALL: call void @llvm.va_end(ptr %va) +// ALL: call void @llvm.va_end.p0(ptr %va) // ALL: } int test_v4i32(char *fmt, ...) { @@ -128,7 +128,7 @@ int test_v4i32(char *fmt, ...) { // // ALL: %va = alloca ptr, align [[$PTRALIGN]] // ALL: [[V:%.+]] = alloca <4 x i32>, align 16 -// ALL: call void @llvm.va_start(ptr %va) +// ALL: call void @llvm.va_start.p0(ptr %va) // ALL: [[AP_CUR:%.+]] = load ptr, ptr %va, align [[$PTRALIGN]] // // Vectors are 16-byte aligned, however the O32 ABI has a maximum alignment of @@ -152,7 +152,7 @@ int test_v4i32(char *fmt, ...) { // N32: [[ARG:%.+]] = load <4 x i32>, ptr [[AP_CUR]], align 16 // ALL: store <4 x i32> [[ARG]], ptr [[V]], align 16 // -// ALL: call void @llvm.va_end(ptr %va) +// ALL: call void @llvm.va_end.p0(ptr %va) // ALL: [[VECEXT:%.+]] = extractelement <4 x i32> {{.*}}, i32 0 // ALL: ret i32 [[VECEXT]] // ALL: } diff --git a/clang/test/CodeGen/no-bitfield-type-align.c b/clang/test/CodeGen/no-bitfield-type-align.c index 53ed5e9ad8f854fa89869974de9bb0c2b1ca8bc5..1861c6886a35b3826b3707cb647eb8637ce721bb 100644 --- a/clang/test/CodeGen/no-bitfield-type-align.c +++ b/clang/test/CodeGen/no-bitfield-type-align.c @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -fno-bitfield-type-align -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fno-bitfield-type-align -fdump-record-layouts-simple -emit-llvm -o %t %s | FileCheck %s -check-prefix=LAYOUT +// RUN: FileCheck %s <%t struct S { unsigned short: 0; @@ -7,6 +8,13 @@ struct S { unsigned short f2:15; }; +// LAYOUT-LABEL: LLVMType:%struct.S = +// LAYOUT-SAME: type { i32 } +// LAYOUT: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:0 Size:15 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:15 Size:15 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: ]> + // CHECK: define{{.*}} void @test_zero_width_bitfield(ptr noundef %[[A:.*]]) // CHECK: %[[BF_LOAD:.*]] = load i32, ptr %[[V1:.*]], align 1 // CHECK: %[[BF_CLEAR:.*]] = and i32 %[[BF_LOAD]], 32767 diff --git a/clang/test/CodeGen/pr53127.cpp b/clang/test/CodeGen/pr53127.cpp index 97fe1291352d3cf642b301e73b0403a411fa99bc..5a52b4860eecdd3eec7447f55cad7613c0a1b38f 100644 --- a/clang/test/CodeGen/pr53127.cpp +++ b/clang/test/CodeGen/pr53127.cpp @@ -34,7 +34,7 @@ void operator delete(void*); // CHECK-NEXT: br i1 [[CALL6]], label [[COND_TRUE7:%.*]], label [[COND_FALSE8:%.*]] // CHECK: cond.true7: // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[L]], i64 0, i64 0 -// CHECK-NEXT: call void @llvm.va_start(ptr [[ARRAYDECAY]]) +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) // CHECK-NEXT: br label [[COND_END9:%.*]] // CHECK: cond.false8: // CHECK-NEXT: br label [[COND_END9]] @@ -44,7 +44,7 @@ void operator delete(void*); // CHECK: cond.true11: // CHECK-NEXT: [[ARRAYDECAY12:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[L]], i64 0, i64 0 // CHECK-NEXT: [[ARRAYDECAY13:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[L2]], i64 0, i64 0 -// CHECK-NEXT: call void @llvm.va_copy(ptr [[ARRAYDECAY12]], ptr [[ARRAYDECAY13]]) +// CHECK-NEXT: call void @llvm.va_copy.p0(ptr [[ARRAYDECAY12]], ptr [[ARRAYDECAY13]]) // CHECK-NEXT: br label [[COND_END15:%.*]] // CHECK: cond.false14: // CHECK-NEXT: br label [[COND_END15]] diff --git a/clang/test/CodeGen/pragma-cx-limited-range.c b/clang/test/CodeGen/pragma-cx-limited-range.c index 926da8afbee558c9428b0ed2e41605597b6e6a58..68615348c1871f4eed27380a4a6ca0141da3f22c 100644 --- a/clang/test/CodeGen/pragma-cx-limited-range.c +++ b/clang/test/CodeGen/pragma-cx-limited-range.c @@ -2,20 +2,24 @@ // RUN: -o - | FileCheck %s --check-prefix=FULL // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ -// RUN: -complex-range=limited -o - | FileCheck --check-prefix=LMTD %s +// RUN: -complex-range=basic -o - | FileCheck --check-prefix=BASIC %s // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ // RUN: -fno-cx-limited-range -o - | FileCheck %s --check-prefix=FULL // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ -// RUN: -complex-range=fortran -o - | FileCheck --check-prefix=FRTRN %s +// RUN: -complex-range=improved -o - | FileCheck --check-prefix=IMPRVD %s // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ -// RUN: -fno-cx-fortran-rules -o - | FileCheck --check-prefix=FULL %s +// RUN: -complex-range=promoted -o - | FileCheck --check-prefix=PRMTD %s + +// RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ +// RUN: -complex-range=full -o - | FileCheck --check-prefix=FULL %s _Complex float pragma_on_mul(_Complex float a, _Complex float b) { #pragma STDC CX_LIMITED_RANGE ON // LABEL: define {{.*}} @pragma_on_mul( + // FULL: fmul float // FULL-NEXT: fmul float // FULL-NEXT: fmul float @@ -23,19 +27,26 @@ _Complex float pragma_on_mul(_Complex float a, _Complex float b) { // FULL-NEXT: fsub float // FULL-NEXT: fadd float - // LMTD: fmul float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fsub float - // LMTD-NEXT: fadd float - - // FRTRN: fmul float - // FRTRN-NEXT: fmul float - // FRTRN-NEXT: fmul float - // FRTRN-NEXT: fmul float - // FRTRN-NEXT: fsub float - // FRTRN-NEXT: fadd float + // BASIC: fmul float + // BASIC-NEXT: fmul float + // BASIC-NEXT: fmul float + // BASIC-NEXT: fmul float + // BASIC-NEXT: fsub float + // BASIC-NEXT: fadd float + + // IMPRVD: fmul float + // IMPRVD-NEXT: fmul float + // IMPRVD-NEXT: fmul float + // IMPRVD-NEXT: fmul float + // IMPRVD-NEXT: fsub float + // IMPRVD-NEXT: fadd float + + // PRMTD: fmul float + // PRMTD-NEXT: fmul float + // PRMTD-NEXT: fmul float + // PRMTD-NEXT: fmul float + // PRMTD-NEXT: fsub float + // PRMTD-NEXT: fadd float return a * b; } @@ -43,11 +54,14 @@ _Complex float pragma_on_mul(_Complex float a, _Complex float b) { _Complex float pragma_off_mul(_Complex float a, _Complex float b) { #pragma STDC CX_LIMITED_RANGE OFF // LABEL: define {{.*}} @pragma_off_mul( + // FULL: call {{.*}} @__mulsc3 - // LMTD: call {{.*}} @__mulsc3 + // BASIC: call {{.*}} @__mulsc3 + + // IMPRVD: call {{.*}} @__mulsc3 - // FRTRN: call {{.*}} @__mulsc3 + // PRMTD: call {{.*}} @__mulsc3 return a * b; } @@ -55,6 +69,7 @@ _Complex float pragma_off_mul(_Complex float a, _Complex float b) { _Complex float pragma_on_div(_Complex float a, _Complex float b) { #pragma STDC CX_LIMITED_RANGE ON // LABEL: define {{.*}} @pragma_on_div( + // FULL: fmul float // FULL-NEXT: fmul float // FULL-NEXT: fadd float @@ -67,29 +82,45 @@ _Complex float pragma_on_div(_Complex float a, _Complex float b) { // FULL-NEXT: fdiv float // FULL: fdiv float - // LMTD: fmul float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fadd float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fadd float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fmul float - // LMTD-NEXT: fsub float - // LMTD-NEXT: fdiv float - // LMTD-NEXT: fdiv float - - // FRTRN: fmul float - // FRTRN-NEXT: fmul float - // FRTRN-NEXT: fadd float - // FRTRN-NEXT: fmul float - // FRTRN-NEXT: fmul float - // FRTRN-NEXT: fadd float - // FRTRN-NEXT: fmul float - // FRTRN-NEXT: fmul float - // FRTRN-NEXT: fsub float - // FRTRN-NEXT: fdiv float - // FRTRN-NEXT: fdiv float + // BASIC: fmul float + // BASIC-NEXT: fmul float + // BASIC-NEXT: fadd float + // BASIC-NEXT: fmul float + // BASIC-NEXT: fmul float + // BASIC-NEXT: fadd float + // BASIC-NEXT: fmul float + // BASIC-NEXT: fmul float + // BASIC-NEXT: fsub float + // BASIC-NEXT: fdiv float + // BASIC-NEXT: fdiv float + + // IMPRVD: fmul float + // IMPRVD-NEXT: fmul float + // IMPRVD-NEXT: fadd float + // IMPRVD-NEXT: fmul float + // IMPRVD-NEXT: fmul float + // IMPRVD-NEXT: fadd float + // IMPRVD-NEXT: fmul float + // IMPRVD-NEXT: fmul float + // IMPRVD-NEXT: fsub float + // IMPRVD-NEXT: fdiv float + // IMPRVD-NEXT: fdiv float + + // PRMTD: fpext float {{.*}} to double + // PRMTD: fpext float {{.*}} to double + // PRMTD: fmul double + // PRMTD: fmul double + // PRMTD: fadd double + // PRMTD: fmul double + // PRMTD: fmul double + // PRMTD: fadd double + // PRMTD: fmul double + // PRMTD: fmul double + // PRMTD: fsub double + // PRMTD: fdiv double + // PRMTD: fdiv double + // PRMTD: fptrunc double + // PRMTD: fptrunc double return a / b; } @@ -97,11 +128,118 @@ _Complex float pragma_on_div(_Complex float a, _Complex float b) { _Complex float pragma_off_div(_Complex float a, _Complex float b) { #pragma STDC CX_LIMITED_RANGE OFF // LABEL: define {{.*}} @pragma_off_div( + // FULL: call {{.*}} @__divsc3 - // LMTD: call {{.*}} @__divsc3 + // BASIC: call {{.*}} @__divsc3 + + // IMPRVD: call {{.*}} @__divsc3 + + // PRMTD: call {{.*}} @__divdc3 + + return a / b; +} + +_Complex float pragma_default_mul(_Complex float a, _Complex float b) { +#pragma STDC CX_LIMITED_RANGE DEFAULT + // LABEL: define {{.*}} @pragma_on_mul( + + // FULL: fmul float + // FULL-NEXT: fmul float + // FULL-NEXT: fmul float + // FULL-NEXT: fmul float + // FULL-NEXT: fsub float + // FULL-NEXT: fadd float + + // BASIC: fmul float + // BASIC-NEXT: fmul float + // BASIC-NEXT: fmul float + // BASIC-NEXT: fmul float + // BASIC-NEXT: fsub float + // BASIC-NEXT: fadd float + + // IMPRVD: fmul float + // IMPRVD-NEXT: fmul float + // IMPRVD-NEXT: fmul float + // IMPRVD-NEXT: fmul float + // IMPRVD-NEXT: fsub float + // IMPRVD-NEXT: fadd float + + // PRMTD: fmul float + // PRMTD-NEXT: fmul float + // PRMTD-NEXT: fmul float + // PRMTD-NEXT: fmul float + // PRMTD-NEXT: fsub float + // PRMTD-NEXT: fadd float + + return a * b; +} +_Complex float pragma_default_div(_Complex float a, _Complex float b) { +#pragma STDC CX_LIMITED_RANGE DEFAULT + // LABEL: define {{.*}} @pragma_on_divx( + + // FULL: call {{.*}} @__divsc3 - // FRTRN: call {{.*}} @__divsc3 + // BASIC: fmul float + // BASIC-NEXT: fmul float + // BASIC-NEXT: fadd float + // BASIC-NEXT: fmul float + // BASIC-NEXT: fmul float + // BASIC-NEXT: fadd float + // BASIC-NEXT: fmul float + // BASIC-NEXT: fmul float + // BASIC-NEXT: fsub float + // BASIC-NEXT: fdiv float + // BASIC-NEXT: fdiv float + + // IMPRVD: call{{.*}}float @llvm.fabs.f32(float {{.*}}) + // IMPRVD-NEXT: call{{.*}}float @llvm.fabs.f32(float {{.*}}) + // IMPRVD-NEXT: fcmp{{.*}}ugt float {{.*}}, {{.*}} + // IMPRVD-NEXT: br i1 {{.*}}, label + // IMPRVD: abs_rhsr_greater_or_equal_abs_rhsi: + // IMPRVD-NEXT: fdiv float + // IMPRVD-NEXT: fmul float + // IMPRVD-NEXT: fadd float + // IMPRVD-NEXT: fmul float + // IMPRVD-NEXT: fadd float + // IMPRVD-NEXT: fdiv float + // IMPRVD-NEXT: fmul float + // IMPRVD-NEXT: fsub float + // IMPRVD-NEXT: fdiv float + // IMPRVD-NEXT: br label + // IMPRVD: abs_rhsr_less_than_abs_rhsi: + // IMPRVD-NEXT: fdiv float + // IMPRVD-NEXT: fmul float + // IMPRVD-NEXT: fadd float + // IMPRVD-NEXT: fmul float + // IMPRVD-NEXT: fadd float + // IMPRVD-NEXT: fdiv float + // IMPRVD-NEXT: fmul float + // IMPRVD-NEXT: fsub float + // IMPRVD-NEXT: fdiv float + + // PRMTD: load float, ptr {{.*}} + // PRMTD: fpext float {{.*}} to double + // PRMTD-NEXT: fpext float {{.*}} to double + // PRMTD-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 0 + // PRMTD-NEXT: load float, ptr {{.*}} + // PRMTD-NEXT: getelementptr inbounds { float, float }, ptr {{.*}}, i32 0, i32 1 + // PRMTD-NEXT: load float, ptr {{.*}} + // PRMTD-NEXT: fpext float {{.*}} to double + // PRMTD-NEXT: fpext float {{.*}} to double + // PRMTD-NEXT: fmul double + // PRMTD-NEXT: fmul double + // PRMTD-NEXT: fadd double + // PRMTD-NEXT: fmul double + // PRMTD-NEXT: fmul double + // PRMTD-NEXT: fadd double + // PRMTD-NEXT: fmul double + // PRMTD-NEXT: fmul double + // PRMTD-NEXT: fsub double + // PRMTD-NEXT: fdiv double + // PRMTD-NEXT: fdiv double + // PRMTD-NEXT: fptrunc double {{.*}} to float + // PRMTD-NEXT: fptrunc double {{.*}} to float return a / b; } diff --git a/clang/test/CodeGen/ptrauth-intrinsics.c b/clang/test/CodeGen/ptrauth-intrinsics.c new file mode 100644 index 0000000000000000000000000000000000000000..17f28dddb380153685416f0d497c49fb417847bc --- /dev/null +++ b/clang/test/CodeGen/ptrauth-intrinsics.c @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-intrinsics -emit-llvm %s -o - | FileCheck %s + +void (*fnptr)(void); +long int_discriminator; +void *ptr_discriminator; +long signature; + +// CHECK-LABEL: define void @test_auth() +void test_auth() { + // CHECK: [[PTR:%.*]] = load ptr, ptr @fnptr, + // CHECK-NEXT: [[DISC0:%.*]] = load ptr, ptr @ptr_discriminator, + // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[PTR]] to i64 + // CHECK-NEXT: [[DISC:%.*]] = ptrtoint ptr [[DISC0]] to i64 + // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[T0]], i32 0, i64 [[DISC]]) + // CHECK-NEXT: [[RESULT:%.*]] = inttoptr i64 [[T1]] to ptr + // CHECK-NEXT: store ptr [[RESULT]], ptr @fnptr, + fnptr = __builtin_ptrauth_auth(fnptr, 0, ptr_discriminator); +} + +// CHECK-LABEL: define void @test_strip() +void test_strip() { + // CHECK: [[PTR:%.*]] = load ptr, ptr @fnptr, + // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[PTR]] to i64 + // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.strip(i64 [[T0]], i32 0) + // CHECK-NEXT: [[RESULT:%.*]] = inttoptr i64 [[T1]] to ptr + // CHECK-NEXT: store ptr [[RESULT]], ptr @fnptr, + fnptr = __builtin_ptrauth_strip(fnptr, 0); +} + +// CHECK-LABEL: define void @test_sign_unauthenticated() +void test_sign_unauthenticated() { + // CHECK: [[PTR:%.*]] = load ptr, ptr @fnptr, + // CHECK-NEXT: [[DISC0:%.*]] = load ptr, ptr @ptr_discriminator, + // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[PTR]] to i64 + // CHECK-NEXT: [[DISC:%.*]] = ptrtoint ptr [[DISC0]] to i64 + // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.sign(i64 [[T0]], i32 0, i64 [[DISC]]) + // CHECK-NEXT: [[RESULT:%.*]] = inttoptr i64 [[T1]] to ptr + // CHECK-NEXT: store ptr [[RESULT]], ptr @fnptr, + fnptr = __builtin_ptrauth_sign_unauthenticated(fnptr, 0, ptr_discriminator); +} + +// CHECK-LABEL: define void @test_auth_and_resign() +void test_auth_and_resign() { + // CHECK: [[PTR:%.*]] = load ptr, ptr @fnptr, + // CHECK-NEXT: [[DISC0:%.*]] = load ptr, ptr @ptr_discriminator, + // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[PTR]] to i64 + // CHECK-NEXT: [[DISC:%.*]] = ptrtoint ptr [[DISC0]] to i64 + // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 0, i64 [[DISC]], i32 3, i64 15) + // CHECK-NEXT: [[RESULT:%.*]] = inttoptr i64 [[T1]] to ptr + // CHECK-NEXT: store ptr [[RESULT]], ptr @fnptr, + fnptr = __builtin_ptrauth_auth_and_resign(fnptr, 0, ptr_discriminator, 3, 15); +} + +// CHECK-LABEL: define void @test_blend_discriminator() +void test_blend_discriminator() { + // CHECK: [[PTR:%.*]] = load ptr, ptr @fnptr, + // CHECK-NEXT: [[DISC:%.*]] = load i64, ptr @int_discriminator, + // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[PTR]] to i64 + // CHECK-NEXT: [[RESULT:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 [[DISC]]) + // CHECK-NEXT: store i64 [[RESULT]], ptr @int_discriminator, + int_discriminator = __builtin_ptrauth_blend_discriminator(fnptr, int_discriminator); +} + +// CHECK-LABEL: define void @test_sign_generic_data() +void test_sign_generic_data() { + // CHECK: [[PTR:%.*]] = load ptr, ptr @fnptr, + // CHECK-NEXT: [[DISC0:%.*]] = load ptr, ptr @ptr_discriminator, + // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[PTR]] to i64 + // CHECK-NEXT: [[DISC:%.*]] = ptrtoint ptr [[DISC0]] to i64 + // CHECK-NEXT: [[RESULT:%.*]] = call i64 @llvm.ptrauth.sign.generic(i64 [[T0]], i64 [[DISC]]) + // CHECK-NEXT: store i64 [[RESULT]], ptr @signature, + signature = __builtin_ptrauth_sign_generic_data(fnptr, ptr_discriminator); +} diff --git a/clang/test/CodeGen/smiths-complex-div.c b/clang/test/CodeGen/smiths-complex-div.c index 75775675c923811a2586d14b000d8b732aa2f230..5882f8b3545f9f9da90cb1307eea1faee6de764f 100644 --- a/clang/test/CodeGen/smiths-complex-div.c +++ b/clang/test/CodeGen/smiths-complex-div.c @@ -1,58 +1,58 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown \ -// RUN: -complex-range=fortran -o - | FileCheck %s --check-prefix=FRTRN +// RUN: -complex-range=improved -o - | FileCheck %s --check-prefix=IMPRVD -// FRTRN-LABEL: define dso_local <2 x float> @div( -// FRTRN-SAME: <2 x float> noundef [[A_COERCE:%.*]], <2 x float> noundef [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { -// FRTRN-NEXT: entry: -// FRTRN-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 -// FRTRN-NEXT: [[A:%.*]] = alloca { float, float }, align 4 -// FRTRN-NEXT: [[B:%.*]] = alloca { float, float }, align 4 -// FRTRN-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 -// FRTRN-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4 -// FRTRN-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 -// FRTRN-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 -// FRTRN-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 -// FRTRN-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 -// FRTRN-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 -// FRTRN-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 -// FRTRN-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 -// FRTRN-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 -// FRTRN-NEXT: [[TMP0:%.*]] = call float @llvm.fabs.f32(float [[B_REAL]]) -// FRTRN-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[B_IMAG]]) -// FRTRN-NEXT: [[ABS_CMP:%.*]] = fcmp ugt float [[TMP0]], [[TMP1]] -// FRTRN-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] -// FRTRN: abs_rhsr_greater_or_equal_abs_rhsi: -// FRTRN-NEXT: [[TMP2:%.*]] = fdiv float [[B_IMAG]], [[B_REAL]] -// FRTRN-NEXT: [[TMP3:%.*]] = fmul float [[TMP2]], [[B_IMAG]] -// FRTRN-NEXT: [[TMP4:%.*]] = fadd float [[B_REAL]], [[TMP3]] -// FRTRN-NEXT: [[TMP5:%.*]] = fmul float [[A_IMAG]], [[TMP2]] -// FRTRN-NEXT: [[TMP6:%.*]] = fadd float [[A_REAL]], [[TMP5]] -// FRTRN-NEXT: [[TMP7:%.*]] = fdiv float [[TMP6]], [[TMP4]] -// FRTRN-NEXT: [[TMP8:%.*]] = fmul float [[A_REAL]], [[TMP2]] -// FRTRN-NEXT: [[TMP9:%.*]] = fsub float [[A_IMAG]], [[TMP8]] -// FRTRN-NEXT: [[TMP10:%.*]] = fdiv float [[TMP9]], [[TMP4]] -// FRTRN-NEXT: br label [[COMPLEX_DIV:%.*]] -// FRTRN: abs_rhsr_less_than_abs_rhsi: -// FRTRN-NEXT: [[TMP11:%.*]] = fdiv float [[B_REAL]], [[B_IMAG]] -// FRTRN-NEXT: [[TMP12:%.*]] = fmul float [[TMP11]], [[B_REAL]] -// FRTRN-NEXT: [[TMP13:%.*]] = fadd float [[B_IMAG]], [[TMP12]] -// FRTRN-NEXT: [[TMP14:%.*]] = fmul float [[A_REAL]], [[TMP11]] -// FRTRN-NEXT: [[TMP15:%.*]] = fadd float [[TMP14]], [[A_IMAG]] -// FRTRN-NEXT: [[TMP16:%.*]] = fdiv float [[TMP15]], [[TMP13]] -// FRTRN-NEXT: [[TMP17:%.*]] = fmul float [[A_IMAG]], [[TMP11]] -// FRTRN-NEXT: [[TMP18:%.*]] = fsub float [[TMP17]], [[A_REAL]] -// FRTRN-NEXT: [[TMP19:%.*]] = fdiv float [[TMP18]], [[TMP13]] -// FRTRN-NEXT: br label [[COMPLEX_DIV]] -// FRTRN: complex_div: -// FRTRN-NEXT: [[TMP20:%.*]] = phi float [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] -// FRTRN-NEXT: [[TMP21:%.*]] = phi float [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] -// FRTRN-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 -// FRTRN-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 -// FRTRN-NEXT: store float [[TMP20]], ptr [[RETVAL_REALP]], align 4 -// FRTRN-NEXT: store float [[TMP21]], ptr [[RETVAL_IMAGP]], align 4 -// FRTRN-NEXT: [[TMP22:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 -// FRTRN-NEXT: ret <2 x float> [[TMP22]] +// IMPRVD-LABEL: define dso_local <2 x float> @div( +// IMPRVD-SAME: <2 x float> noundef [[A_COERCE:%.*]], <2 x float> noundef [[B_COERCE:%.*]]) #[[ATTR0:[0-9]+]] { +// IMPRVD-NEXT: entry: +// IMPRVD-NEXT: [[RETVAL:%.*]] = alloca { float, float }, align 4 +// IMPRVD-NEXT: [[A:%.*]] = alloca { float, float }, align 4 +// IMPRVD-NEXT: [[B:%.*]] = alloca { float, float }, align 4 +// IMPRVD-NEXT: store <2 x float> [[A_COERCE]], ptr [[A]], align 4 +// IMPRVD-NEXT: store <2 x float> [[B_COERCE]], ptr [[B]], align 4 +// IMPRVD-NEXT: [[A_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 0 +// IMPRVD-NEXT: [[A_REAL:%.*]] = load float, ptr [[A_REALP]], align 4 +// IMPRVD-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[A]], i32 0, i32 1 +// IMPRVD-NEXT: [[A_IMAG:%.*]] = load float, ptr [[A_IMAGP]], align 4 +// IMPRVD-NEXT: [[B_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 0 +// IMPRVD-NEXT: [[B_REAL:%.*]] = load float, ptr [[B_REALP]], align 4 +// IMPRVD-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[B]], i32 0, i32 1 +// IMPRVD-NEXT: [[B_IMAG:%.*]] = load float, ptr [[B_IMAGP]], align 4 +// IMPRVD-NEXT: [[TMP0:%.*]] = call float @llvm.fabs.f32(float [[B_REAL]]) +// IMPRVD-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[B_IMAG]]) +// IMPRVD-NEXT: [[ABS_CMP:%.*]] = fcmp ugt float [[TMP0]], [[TMP1]] +// IMPRVD-NEXT: br i1 [[ABS_CMP]], label [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI:%.*]], label [[ABS_RHSR_LESS_THAN_ABS_RHSI:%.*]] +// IMPRVD: abs_rhsr_greater_or_equal_abs_rhsi: +// IMPRVD-NEXT: [[TMP2:%.*]] = fdiv float [[B_IMAG]], [[B_REAL]] +// IMPRVD-NEXT: [[TMP3:%.*]] = fmul float [[TMP2]], [[B_IMAG]] +// IMPRVD-NEXT: [[TMP4:%.*]] = fadd float [[B_REAL]], [[TMP3]] +// IMPRVD-NEXT: [[TMP5:%.*]] = fmul float [[A_IMAG]], [[TMP2]] +// IMPRVD-NEXT: [[TMP6:%.*]] = fadd float [[A_REAL]], [[TMP5]] +// IMPRVD-NEXT: [[TMP7:%.*]] = fdiv float [[TMP6]], [[TMP4]] +// IMPRVD-NEXT: [[TMP8:%.*]] = fmul float [[A_REAL]], [[TMP2]] +// IMPRVD-NEXT: [[TMP9:%.*]] = fsub float [[A_IMAG]], [[TMP8]] +// IMPRVD-NEXT: [[TMP10:%.*]] = fdiv float [[TMP9]], [[TMP4]] +// IMPRVD-NEXT: br label [[COMPLEX_DIV:%.*]] +// IMPRVD: abs_rhsr_less_than_abs_rhsi: +// IMPRVD-NEXT: [[TMP11:%.*]] = fdiv float [[B_REAL]], [[B_IMAG]] +// IMPRVD-NEXT: [[TMP12:%.*]] = fmul float [[TMP11]], [[B_REAL]] +// IMPRVD-NEXT: [[TMP13:%.*]] = fadd float [[B_IMAG]], [[TMP12]] +// IMPRVD-NEXT: [[TMP14:%.*]] = fmul float [[A_REAL]], [[TMP11]] +// IMPRVD-NEXT: [[TMP15:%.*]] = fadd float [[TMP14]], [[A_IMAG]] +// IMPRVD-NEXT: [[TMP16:%.*]] = fdiv float [[TMP15]], [[TMP13]] +// IMPRVD-NEXT: [[TMP17:%.*]] = fmul float [[A_IMAG]], [[TMP11]] +// IMPRVD-NEXT: [[TMP18:%.*]] = fsub float [[TMP17]], [[A_REAL]] +// IMPRVD-NEXT: [[TMP19:%.*]] = fdiv float [[TMP18]], [[TMP13]] +// IMPRVD-NEXT: br label [[COMPLEX_DIV]] +// IMPRVD: complex_div: +// IMPRVD-NEXT: [[TMP20:%.*]] = phi float [ [[TMP7]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP16]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD-NEXT: [[TMP21:%.*]] = phi float [ [[TMP10]], [[ABS_RHSR_GREATER_OR_EQUAL_ABS_RHSI]] ], [ [[TMP19]], [[ABS_RHSR_LESS_THAN_ABS_RHSI]] ] +// IMPRVD-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 0 +// IMPRVD-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds { float, float }, ptr [[RETVAL]], i32 0, i32 1 +// IMPRVD-NEXT: store float [[TMP20]], ptr [[RETVAL_REALP]], align 4 +// IMPRVD-NEXT: store float [[TMP21]], ptr [[RETVAL_IMAGP]], align 4 +// IMPRVD-NEXT: [[TMP22:%.*]] = load <2 x float>, ptr [[RETVAL]], align 4 +// IMPRVD-NEXT: ret <2 x float> [[TMP22]] // _Complex float div(_Complex float a, _Complex float b) { return a / b; diff --git a/clang/test/CodeGen/struct-x86-darwin.c b/clang/test/CodeGen/struct-x86-darwin.c index 5191441cabaf040158f0e49fc9ec2e36520fa92e..e79ecefb880dfb9f042de82302e89f6ec92a2144 100644 --- a/clang/test/CodeGen/struct-x86-darwin.c +++ b/clang/test/CodeGen/struct-x86-darwin.c @@ -1,25 +1,70 @@ -// RUN: %clang_cc1 %s -emit-llvm -triple=i686-apple-darwin9 -o - | FileCheck %s -// CHECK: STest1 = type { i32, [4 x i16], double } -// CHECK: STest2 = type { i16, i16, i32, i32 } -// CHECK: STest3 = type { i8, i16, i32 } -// CHECK: STestB1 = type { i8, i8 } -// CHECK: STestB2 = type { i8, i8, i8 } -// CHECK: STestB3 = type { i8, i8 } -// CHECK: STestB4 = type { i8, i8, i8, i8 } -// CHECK: STestB5 = type { i8, i16, i8 } -// CHECK: STestB6 = type { i8, i8, i16 } +// RUN: %clang_cc1 %s -emit-llvm -o /dev/null -triple=i686-apple-darwin9 -fdump-record-layouts-simple | FileCheck %s + // Test struct layout for x86-darwin target struct STest1 {int x; short y[4]; double z; } st1; struct STest2 {short a,b; int c,d; } st2; struct STest3 {char a; short b; int c; } st3; -// Bitfields +// Bitfields struct STestB1 {char a; char b:2; } stb1; struct STestB2 {char a; char b:5; char c:4; } stb2; struct STestB3 {char a; char b:2; } stb3; struct STestB4 {char a; short b:2; char c; } stb4; struct STestB5 {char a; short b:10; char c; } stb5; -struct STestB6 {int a:1; char b; int c:13 } stb6; +struct STestB6 {int a:1; char b; int c:13; } stb6; // Packed struct STestP1 {char a; short b; int c; } __attribute__((__packed__)) stp1; + +// CHECK-LABEL: LLVMType:%struct.STest1 = +// CHECK-SAME: type { i32, [4 x i16], double } +// CHECK: BitFields:[ +// CHECK-NEXT: ]> + +// CHECK-LABEL: LLVMType:%struct.STest2 = +// CHECK-SAME: type { i16, i16, i32, i32 } +// CHECK: BitFields:[ +// CHECK-NEXT: ]> + +// CHECK-LABEL: LLVMType:%struct.STest3 = +// CHECK-SAME: type { i8, i16, i32 } +// CHECK: BitFields:[ +// CHECK-NEXT: ]> + +// CHECK-LABEL: LLVMType:%struct.STestB1 = +// CHECK-SAME: type { i8, i8 } +// CHECK: BitFields:[ +// CHECK-NEXT: <CGBitFieldInfo Offset:0 Size:2 IsSigned:1 StorageSize:8 StorageOffset:1 +// CHECK-NEXT: ]> + +// CHECK-LABEL: LLVMType:%struct.STestB2 = +// CHECK-SAME: type <{ i8, i16 }> +// CHECK: BitFields:[ +// CHECK-NEXT: <CGBitFieldInfo Offset:0 Size:5 IsSigned:1 StorageSize:16 StorageOffset:1 +// CHECK-NEXT: <CGBitFieldInfo Offset:8 Size:4 IsSigned:1 StorageSize:16 StorageOffset:1 +// CHECK-NEXT: ]> + +// CHECK-LABEL: LLVMType:%struct.STestB3 = +// CHECK-SAME: type { i8, i8 } +// CHECK: BitFields:[ +// CHECK-NEXT: <CGBitFieldInfo Offset:0 Size:2 IsSigned:1 StorageSize:8 StorageOffset:1 +// CHECK-NEXT: ]> + +// CHECK-LABEL: LLVMType:%struct.STestB4 = +// CHECK-SAME: type { i8, i8, i8, i8 } +// CHECK: BitFields:[ +// CHECK-NEXT: <CGBitFieldInfo Offset:0 Size:2 IsSigned:1 StorageSize:8 StorageOffset:1 +// CHECK-NEXT: ]> + +// CHECK-LABEL: LLVMType:%struct.STestB5 = +// CHECK-SAME: type { i8, i16, i8 } +// CHECK: BitFields:[ +// CHECK-NEXT: <CGBitFieldInfo Offset:0 Size:10 IsSigned:1 StorageSize:16 StorageOffset:2 +// CHECK-NEXT: ]> + +// CHECK-LABEL: LLVMType:%struct.STestB6 = +// CHECK-SAME: type { i8, i8, i16 } +// CHECK: BitFields:[ +// CHECK-NEXT: <CGBitFieldInfo Offset:0 Size:1 IsSigned:1 StorageSize:8 StorageOffset:0 +// CHECK-NEXT: <CGBitFieldInfo Offset:0 Size:13 IsSigned:1 StorageSize:16 StorageOffset:2 +// CHECK-NEXT: ]> diff --git a/clang/test/CodeGen/swift-async-call-conv.c b/clang/test/CodeGen/swift-async-call-conv.c index ce32c22fe809847832b244bc2ff1748d73338e8c..39511698bbae9d6523f1025c08ab6733f67af960 100644 --- a/clang/test/CodeGen/swift-async-call-conv.c +++ b/clang/test/CodeGen/swift-async-call-conv.c @@ -182,3 +182,19 @@ SWIFTASYNCCALL void async_struct_field_and_methods(int i, S &sref, S *sptr) { // CPPONLY-LABEL: define{{.*}} swifttailcc void @{{.*}}async_nonleaf_method2 // CPPONLY: musttail call swifttailcc void @{{.*}}async_leaf_method #endif + +// Passing this as an argument requires a coerce-and-expand operation, +// which requires a temporary. Make sure that cleaning up that temporary +// doesn't mess around with the musttail handling. +struct coerce_and_expand { + char a,b,c,d; +}; +struct coerce_and_expand return_coerced(void); +SWIFTASYNCCALL void take_coerced_async(struct coerce_and_expand); + +// CHECK-LABEL: swifttailcc void @{{.*}}test_coerced +SWIFTASYNCCALL void test_coerced() { + // CHECK: musttail call swifttailcc void @{{.*}}take_coerced_async + // CHECK-NEXT: ret void + return take_coerced_async(return_coerced()); +} diff --git a/clang/test/CodeGen/target-avx-abi-diag.c b/clang/test/CodeGen/target-avx-abi-diag.c index 84be9e252db5cc7f1041c9b33f6e19d61d657ff5..dfbbc3213ca6b26690ce69ef7010c8d8491b32fd 100644 --- a/clang/test/CodeGen/target-avx-abi-diag.c +++ b/clang/test/CodeGen/target-avx-abi-diag.c @@ -2,13 +2,9 @@ // RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -target-feature +avx -verify=no512 -o - -S // RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -target-feature +avx512f -verify=both -o - -S // RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -target-feature +avx512f -target-feature +evex512 -verify=both -o - -S -// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -target-feature +avx512f -target-feature -evex512 -verify=avx512-256 -DAVX512_ERR=1 -o - -S -// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -target-feature +avx512f -target-feature -evex512 -verify=avx512-256 -DAVX512_ERR=2 -DNOEVEX512 -o - -S -// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -target-feature +avx512f -target-feature -evex512 -verify=avx512-256 -DAVX512_ERR=3 -DNOEVEX512 -o - -S +// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -target-feature +avx512f -target-feature -evex512 -verify=avx512-256 -DNOEVEX512 -o - -S // RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -target-feature +avx10.1-512 -verify=both -o - -S -// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -target-feature +avx10.1-256 -verify=avx512-256 -DAVX512_ERR=1 -o - -S -// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -target-feature +avx10.1-256 -verify=avx512-256 -DAVX512_ERR=2 -o - -S -// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -target-feature +avx10.1-256 -verify=avx512-256 -DAVX512_ERR=3 -o - -S +// RUN: %clang_cc1 %s -triple=x86_64-linux-gnu -target-feature +avx10.1-256 -verify=avx512-256 -o - -S // REQUIRES: x86-registered-target // both-no-diagnostics @@ -25,7 +21,6 @@ void takesAvx512_no_target(avx512fType t); void variadic(int i, ...); __attribute__((target("avx512f"))) void variadic_err(int i, ...); -#if !defined(AVX512_ERR) || AVX512_ERR == 1 // If neither side has an attribute, warn. void call_warn(void) { avx256Type t1; @@ -39,9 +34,7 @@ void call_warn(void) { // avx512-256-error@+1 {{AVX vector argument of type 'avx512fType' (vector of 32 'short' values) without 'evex512' enabled changes the ABI}} variadic(3, t2); // no512-warning {{AVX vector argument of type 'avx512fType' (vector of 32 'short' values) without 'avx512f' enabled changes the ABI}} } -#endif -#if !defined(AVX512_ERR) || AVX512_ERR == 2 // If only 1 side has an attribute, error. void call_errors(void) { avx256Type t1; @@ -54,16 +47,21 @@ void call_errors(void) { // avx512-256-error@+1 {{AVX vector argument of type 'avx512fType' (vector of 32 'short' values) without 'evex512' enabled changes the ABI}} variadic_err(3, t2); // no512-error {{AVX vector argument of type 'avx512fType' (vector of 32 'short' values) without 'avx512f' enabled changes the ABI}} } -#if defined(__AVX10_1__) -// avx512-256-warning@*:* {{invalid feature combination: +avx512f +avx10.1-256; will be promoted to avx10.1-512}} -// avx512-256-warning@*:* {{invalid feature combination: +avx512f +avx10.1-256; will be promoted to avx10.1-512}} -// avx512-256-warning@*:* {{invalid feature combination: +avx512f +avx10.1-256; will be promoted to avx10.1-512}} -// avx512-256-warning@*:* {{invalid feature combination: +avx512f +avx10.1-256; will be promoted to avx10.1-512}} -// avx512-256-warning@*:* {{invalid feature combination: +avx512f +avx10.1-256; will be promoted to avx10.1-512}} -#endif -#endif -#if !defined(AVX512_ERR) || AVX512_ERR == 3 +// Check that these errors are treated as non-fatal, so we can report them for +// all functions, not just the first. +void call_errors_2(void) { + avx256Type t1; + takesAvx256(t1); // no256-error {{AVX vector argument of type 'avx256Type' (vector of 16 'short' values) without 'avx' enabled changes the ABI}} + avx512fType t2; + // avx512-256-error@+1 {{AVX vector argument of type 'avx512fType' (vector of 32 'short' values) without 'evex512' enabled changes the ABI}} + takesAvx512(t2); // no512-error {{AVX vector argument of type 'avx512fType' (vector of 32 'short' values) without 'avx512f' enabled changes the ABI}} + + variadic_err(1, t1); // no256-error {{AVX vector argument of type 'avx256Type' (vector of 16 'short' values) without 'avx' enabled changes the ABI}} + // avx512-256-error@+1 {{AVX vector argument of type 'avx512fType' (vector of 32 'short' values) without 'evex512' enabled changes the ABI}} + variadic_err(3, t2); // no512-error {{AVX vector argument of type 'avx512fType' (vector of 32 'short' values) without 'avx512f' enabled changes the ABI}} +} + __attribute__((target("avx"))) void call_avx256_ok(void) { avx256Type t; takesAvx256(t); @@ -93,5 +91,11 @@ __attribute__((target("avx512f"))) void call_avx512_ok2(void) { // avx512-256-warning@*:* {{invalid feature combination: +avx512f +avx10.1-256; will be promoted to avx10.1-512}} // avx512-256-warning@*:* {{invalid feature combination: +avx512f +avx10.1-256; will be promoted to avx10.1-512}} // avx512-256-warning@*:* {{invalid feature combination: +avx512f +avx10.1-256; will be promoted to avx10.1-512}} -#endif +// avx512-256-warning@*:* {{invalid feature combination: +avx512f +avx10.1-256; will be promoted to avx10.1-512}} +// avx512-256-warning@*:* {{invalid feature combination: +avx512f +avx10.1-256; will be promoted to avx10.1-512}} +// avx512-256-warning@*:* {{invalid feature combination: +avx512f +avx10.1-256; will be promoted to avx10.1-512}} +// avx512-256-warning@*:* {{invalid feature combination: +avx512f +avx10.1-256; will be promoted to avx10.1-512}} +// avx512-256-warning@*:* {{invalid feature combination: +avx512f +avx10.1-256; will be promoted to avx10.1-512}} +// avx512-256-warning@*:* {{invalid feature combination: +avx512f +avx10.1-256; will be promoted to avx10.1-512}} +// avx512-256-warning@*:* {{invalid feature combination: +avx512f +avx10.1-256; will be promoted to avx10.1-512}} #endif diff --git a/clang/test/CodeGen/tbaa-struct.cpp b/clang/test/CodeGen/tbaa-struct.cpp index 9b4b7415142d933be0a89e1a87520dc4d5a726bd..ca076ce5aa27327d91c0265b354e0f0297d6e86c 100644 --- a/clang/test/CodeGen/tbaa-struct.cpp +++ b/clang/test/CodeGen/tbaa-struct.cpp @@ -197,7 +197,7 @@ void copy12(UnionMember2 *a1, UnionMember2 *a2) { // CHECK-OLD: [[TS6]] = !{i64 0, i64 2, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE:!.+]]} // CHECK-OLD: [[TAG_DOUBLE]] = !{[[DOUBLE:!.+]], [[DOUBLE]], i64 0} // CHECK-OLD [[DOUBLE]] = !{!"double", [[CHAR]], i64 0} -// CHECK-OLD: [[TS7]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]], i64 3, i64 1, [[TAG_CHAR]], i64 4, i64 1, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE]], i64 16, i64 1, [[TAG_CHAR]]} +// CHECK-OLD: [[TS7]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]], i64 3, i64 2, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE]], i64 16, i64 1, [[TAG_CHAR]]} // CHECK-OLD: [[TS8]] = !{i64 0, i64 4, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE]]} // CHECK-OLD: [[TS9]] = !{i64 0, i64 8, [[TAG_CHAR]], i64 8, i64 4, [[TAG_INT]]} // CHECK-OLD: [[TS10]] = !{i64 0, i64 4, [[TAG_INT]], i64 8, i64 8, [[TAG_CHAR]]} diff --git a/clang/test/CodeGen/ubsan-builtin-checks.c b/clang/test/CodeGen/ubsan-builtin-checks.c index 2bc32d8df4850d5fe0dbdc3188cecbc96673e008..c7f6078f903bad815544f65acdb6a7ce57c7e437 100644 --- a/clang/test/CodeGen/ubsan-builtin-checks.c +++ b/clang/test/CodeGen/ubsan-builtin-checks.c @@ -23,6 +23,9 @@ void check_ctz(int n) { // CHECK: call void @__ubsan_handle_invalid_builtin __builtin_ctzll(n); + + // CHECK: call void @__ubsan_handle_invalid_builtin + __builtin_ctzg((unsigned int)n); } // CHECK: define{{.*}} void @check_clz @@ -44,4 +47,7 @@ void check_clz(int n) { // CHECK: call void @__ubsan_handle_invalid_builtin __builtin_clzll(n); + + // CHECK: call void @__ubsan_handle_invalid_builtin + __builtin_clzg((unsigned int)n); } diff --git a/clang/test/CodeGen/varargs-with-nonzero-default-address-space.c b/clang/test/CodeGen/varargs-with-nonzero-default-address-space.c new file mode 100644 index 0000000000000000000000000000000000000000..b087da34c3dfb57bc09dead1e1d20318ceb98aa0 --- /dev/null +++ b/clang/test/CodeGen/varargs-with-nonzero-default-address-space.c @@ -0,0 +1,46 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// RUN: %clang_cc1 -triple spirv64-unknown-unknown -fcuda-is-device -emit-llvm -o - %s | FileCheck %s + +struct x { + double b; + long a; +}; + +// CHECK-LABEL: define spir_func void @testva( +// CHECK-SAME: i32 noundef [[N:%.*]], ...) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[AP:%.*]] = alloca ptr addrspace(4), align 8 +// CHECK-NEXT: [[T:%.*]] = alloca [[STRUCT_X:%.*]], align 8 +// CHECK-NEXT: [[AP2:%.*]] = alloca ptr addrspace(4), align 8 +// CHECK-NEXT: [[V:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[VARET:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[N_ADDR_ASCAST:%.*]] = addrspacecast ptr [[N_ADDR]] to ptr addrspace(4) +// CHECK-NEXT: [[AP_ASCAST:%.*]] = addrspacecast ptr [[AP]] to ptr addrspace(4) +// CHECK-NEXT: [[T_ASCAST:%.*]] = addrspacecast ptr [[T]] to ptr addrspace(4) +// CHECK-NEXT: [[AP2_ASCAST:%.*]] = addrspacecast ptr [[AP2]] to ptr addrspace(4) +// CHECK-NEXT: [[V_ASCAST:%.*]] = addrspacecast ptr [[V]] to ptr addrspace(4) +// CHECK-NEXT: [[VARET_ASCAST:%.*]] = addrspacecast ptr [[VARET]] to ptr addrspace(4) +// CHECK-NEXT: store i32 [[N]], ptr addrspace(4) [[N_ADDR_ASCAST]], align 4 +// CHECK-NEXT: call void @llvm.va_start.p4(ptr addrspace(4) [[AP_ASCAST]]) +// CHECK-NEXT: [[TMP0:%.*]] = va_arg ptr addrspace(4) [[AP_ASCAST]], ptr +// CHECK-NEXT: call void @llvm.memcpy.p4.p0.i64(ptr addrspace(4) align 8 [[T_ASCAST]], ptr align 8 [[TMP0]], i64 16, i1 false) +// CHECK-NEXT: call void @llvm.va_copy.p4(ptr addrspace(4) [[AP2_ASCAST]], ptr addrspace(4) [[AP_ASCAST]]) +// CHECK-NEXT: [[TMP1:%.*]] = va_arg ptr addrspace(4) [[AP2_ASCAST]], i32 +// CHECK-NEXT: store i32 [[TMP1]], ptr addrspace(4) [[VARET_ASCAST]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(4) [[VARET_ASCAST]], align 4 +// CHECK-NEXT: store i32 [[TMP2]], ptr addrspace(4) [[V_ASCAST]], align 4 +// CHECK-NEXT: call void @llvm.va_end.p4(ptr addrspace(4) [[AP2_ASCAST]]) +// CHECK-NEXT: call void @llvm.va_end.p4(ptr addrspace(4) [[AP_ASCAST]]) +// CHECK-NEXT: ret void + +void testva(int n, ...) { + __builtin_va_list ap; + __builtin_va_start(ap, n); + struct x t = __builtin_va_arg(ap, struct x); + __builtin_va_list ap2; + __builtin_va_copy(ap2, ap); + int v = __builtin_va_arg(ap2, int); + __builtin_va_end(ap2); + __builtin_va_end(ap); +} diff --git a/clang/test/CodeGen/volatile.cpp b/clang/test/CodeGen/volatile.cpp index 38724659ad8a3557cad7ad6b44e4f6cdfbeb5649..70f523b93852ed16875effc915f4289f1e9ff0f6 100644 --- a/clang/test/CodeGen/volatile.cpp +++ b/clang/test/CodeGen/volatile.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -O2 -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK +// RUN: %clang_cc1 -O2 -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s struct agg { int a ; @@ -10,34 +10,32 @@ _Complex float cf; int volatile vol =10; void f0() { const_cast<volatile _Complex float &>(cf) = const_cast<volatile _Complex float&>(cf) + 1; -// CHECK: %cf.real = load volatile float, ptr @cf -// CHECK: %cf.imag = load volatile float, ptr getelementptr -// CHECK: %add.r = fadd float %cf.real, 1.000000e+00 -// CHECK: %add.i = fadd float %cf.imag, 0.000000e+00 -// CHECK: store volatile float %add.r -// CHECK: store volatile float %add.i, ptr getelementptr +// CHECK: [[Re1:%.*]] = load volatile float, ptr @cf +// CHECK: [[Im1:%.*]] = load volatile float, ptr getelementptr +// CHECK: [[Add1:%.*]] = fadd float [[Re1]], 1.000000e+00 +// CHECK: store volatile float [[Add1]], ptr @cf +// CHECK: store volatile float [[Im1]], ptr getelementptr static_cast<volatile _Complex float &>(cf) = static_cast<volatile _Complex float&>(cf) + 1; -// CHECK: %cf.real1 = load volatile float, ptr @cf -// CHECK: %cf.imag2 = load volatile float, ptr getelementptr -// CHECK: %add.r3 = fadd float %cf.real1, 1.000000e+00 -// CHECK: %add.i4 = fadd float %cf.imag2, 0.000000e+00 -// CHECK: store volatile float %add.r3, ptr @cf -// CHECK: store volatile float %add.i4, ptr getelementptr +// CHECK: [[Re2:%.*]] = load volatile float, ptr @cf +// CHECK: [[Im2:%.*]] = load volatile float, ptr getelementptr +// CHECK: [[Add2:%.*]] = fadd float [[Re2]], 1.000000e+00 +// CHECK: store volatile float [[Add2]], ptr @cf +// CHECK: store volatile float [[Im2]], ptr getelementptr const_cast<volatile int &>(a.a) = const_cast<volatile int &>(t.a) ; -// CHECK: %0 = load volatile i32, ptr @t -// CHECK: store volatile i32 %0, ptr @a +// CHECK: [[I1:%.*]] = load volatile i32, ptr @t +// CHECK: store volatile i32 [[I1]], ptr @a static_cast<volatile int &>(a.b) = static_cast<volatile int &>(t.a) ; -// CHECK: %1 = load volatile i32, ptr @t -// CHECK: store volatile i32 %1, ptr getelementptr +// CHECK: [[I2:%.*]] = load volatile i32, ptr @t +// CHECK: store volatile i32 [[I2]], ptr getelementptr const_cast<volatile int&>(vt) = const_cast<volatile int&>(vt) + 1; -// CHECK: %2 = load volatile i32, ptr @vt -// CHECK: %add = add nsw i32 %2, 1 -// CHECK: store volatile i32 %add, ptr @vt +// CHECK: [[I3:%.*]] = load volatile i32, ptr @vt +// CHECK: [[Add3:%.*]] = add nsw i32 [[I3]], 1 +// CHECK: store volatile i32 [[Add3]], ptr @vt static_cast<volatile int&>(vt) = static_cast<volatile int&>(vt) + 1; -// CHECK: %3 = load volatile i32, ptr @vt -// CHECK: %add5 = add nsw i32 %3, 1 -// CHECK: store volatile i32 %add5, ptr @vt +// CHECK: [[I4:%.*]] = load volatile i32, ptr @vt +// CHECK: [[Add4:%.*]] = add nsw i32 [[I4]], 1 +// CHECK: store volatile i32 [[Add4]], ptr @vt vt = const_cast<int&>(vol); -// %4 = load i32, ptr @vol -// store i32 %4, ptr @vt +// [[I5:%.*]] = load i32, ptr @vol +// store i32 [[I5]], ptr @vt } diff --git a/clang/test/CodeGen/xcore-abi.c b/clang/test/CodeGen/xcore-abi.c index 4dd0f221533b942ae58c0d108da9bd8fd2c3b9ad..bb8d2fec46bdb2faedfe8544ee607fb96ce4e231 100644 --- a/clang/test/CodeGen/xcore-abi.c +++ b/clang/test/CodeGen/xcore-abi.c @@ -28,7 +28,7 @@ void testva (int n, ...) { // CHECK: [[AP:%[a-z0-9]+]] = alloca ptr, align 4 // CHECK: [[V5:%[a-z0-9]+]] = alloca %struct.x, align 4 // CHECK: [[TMP:%[a-z0-9]+]] = alloca [4 x i32], align 4 - // CHECK: call void @llvm.va_start(ptr [[AP]]) + // CHECK: call void @llvm.va_start.p0(ptr [[AP]]) char* v1 = va_arg (ap, char*); f(v1); diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/diamond-virtual-inheritance.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/diamond-virtual-inheritance.cpp index f6cf834b5032510730918c809ba34bd201468bc5..f03bb747b2a7b1606d7f6e1416f237c31ba480af 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/diamond-virtual-inheritance.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/diamond-virtual-inheritance.cpp @@ -9,19 +9,19 @@ // CHECK: @_ZTV1B.local = private unnamed_addr constant { [4 x i32], [4 x i32] } { [4 x i32] [i32 8, i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1B.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1B.local, i32 0, i32 0, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1B4barBEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1B.local, i32 0, i32 0, i32 3) to i64)) to i32)], [4 x i32] [i32 0, i32 -8, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1B.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1B.local, i32 0, i32 1, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1B.local, i32 0, i32 1, i32 3) to i64)) to i32)] }, align 4 // VTT for B -// CHECK: @_ZTT1B ={{.*}} unnamed_addr constant [2 x ptr] [ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1B.local, i32 0, inrange i32 0, i32 3), ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1B.local, i32 0, inrange i32 1, i32 3)], align 8 +// CHECK: @_ZTT1B ={{.*}} unnamed_addr constant [2 x ptr] [ptr getelementptr inbounds inrange(-12, 4) ({ [4 x i32], [4 x i32] }, ptr @_ZTV1B.local, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-12, 4) ({ [4 x i32], [4 x i32] }, ptr @_ZTV1B.local, i32 0, i32 1, i32 3)], align 8 // VTable for C // CHECK: @_ZTV1C.local = private unnamed_addr constant { [4 x i32], [4 x i32] } { [4 x i32] [i32 8, i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1C.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1C.local, i32 0, i32 0, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1C4barCEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1C.local, i32 0, i32 0, i32 3) to i64)) to i32)], [4 x i32] [i32 0, i32 -8, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1C.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1C.local, i32 0, i32 1, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1C.local, i32 0, i32 1, i32 3) to i64)) to i32)] }, align 4 // VTT for C -// CHECK: @_ZTT1C ={{.*}} unnamed_addr constant [2 x ptr] [ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1C.local, i32 0, inrange i32 0, i32 3), ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTV1C.local, i32 0, inrange i32 1, i32 3)], align 8 +// CHECK: @_ZTT1C ={{.*}} unnamed_addr constant [2 x ptr] [ptr getelementptr inbounds inrange(-12, 4) ({ [4 x i32], [4 x i32] }, ptr @_ZTV1C.local, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-12, 4) ({ [4 x i32], [4 x i32] }, ptr @_ZTV1C.local, i32 0, i32 1, i32 3)], align 8 // VTable for D // CHECK: @_ZTV1D.local = private unnamed_addr constant { [5 x i32], [4 x i32], [4 x i32] } { [5 x i32] [i32 16, i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1D.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 0, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1B4barBEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 0, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1D3bazEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 0, i32 3) to i64)) to i32)], [4 x i32] [i32 8, i32 -8, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1D.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 1, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1C4barCEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 1, i32 3) to i64)) to i32)], [4 x i32] [i32 0, i32 -16, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1D.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 2, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 2, i32 3) to i64)) to i32)] }, align 4 // VTT for D -// CHECK: @_ZTT1D ={{.*}} unnamed_addr constant [7 x ptr] [ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, inrange i32 0, i32 3), ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D0_1B.local, i32 0, inrange i32 0, i32 3), ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D0_1B.local, i32 0, inrange i32 1, i32 3), ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D8_1C.local, i32 0, inrange i32 0, i32 3), ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D8_1C.local, i32 0, inrange i32 1, i32 3), ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, inrange i32 2, i32 3), ptr getelementptr inbounds ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, inrange i32 1, i32 3)], align 8 +// CHECK: @_ZTT1D ={{.*}} unnamed_addr constant [7 x ptr] [ptr getelementptr inbounds inrange(-12, 8) ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-12, 4) ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D0_1B.local, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-12, 4) ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D0_1B.local, i32 0, i32 1, i32 3), ptr getelementptr inbounds inrange(-12, 4) ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D8_1C.local, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-12, 4) ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D8_1C.local, i32 0, i32 1, i32 3), ptr getelementptr inbounds inrange(-12, 4) ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 2, i32 3), ptr getelementptr inbounds inrange(-12, 4) ({ [5 x i32], [4 x i32], [4 x i32] }, ptr @_ZTV1D.local, i32 0, i32 1, i32 3)], align 8 // Construction vtable for B-in-D // CHECK: @_ZTC1D0_1B.local = private unnamed_addr constant { [4 x i32], [4 x i32] } { [4 x i32] [i32 16, i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1B.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D0_1B.local, i32 0, i32 0, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1B4barBEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D0_1B.local, i32 0, i32 0, i32 3) to i64)) to i32)], [4 x i32] [i32 0, i32 -16, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1B.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D0_1B.local, i32 0, i32 1, i32 3) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32], [4 x i32] }, ptr @_ZTC1D0_1B.local, i32 0, i32 1, i32 3) to i64)) to i32)] }, align 4 diff --git a/clang/test/CodeGenCXX/arm-swiftcall.cpp b/clang/test/CodeGenCXX/arm-swiftcall.cpp index e60c1482700a4b9ffcf80b5043be71d7eb8ae6ae..45eea7bfd853b992f9f88b8394676abd494aad1b 100644 --- a/clang/test/CodeGenCXX/arm-swiftcall.cpp +++ b/clang/test/CodeGenCXX/arm-swiftcall.cpp @@ -1,5 +1,9 @@ // RUN: %clang_cc1 -triple armv7-apple-darwin9 -emit-llvm -o - %s -Wno-return-type-c-linkage -std=c++03 | FileCheck %s -check-prefixes=CHECK +// For now just check that the RISC-V triples are accepted, but don't check the IR, as swiftcall is not yet supported. +// RUN: %clang_cc1 -triple riscv32-unknown-linux-gnu -emit-llvm -o - %s -Wno-return-type-c-linkage -std=c++03 +// RUN: %clang_cc1 -triple riscv64-unknown-linux-gnu -emit-llvm -o - %s -Wno-return-type-c-linkage -std=c++03 + // This isn't really testing anything ARM-specific; it's just a convenient // 32-bit platform. diff --git a/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp b/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp index 14963867798d34f1fc5a7881ba55120f66b6c1b0..7953f902bf09b2abe6281981a853c96da48466fc 100644 --- a/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp +++ b/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp @@ -56,13 +56,6 @@ void run_foo_tml() { // CHECK-NEXT: ret i32 1 // // -// CHECK-LABEL: @_Z7foo_ovli.default( -// CHECK-NEXT: entry: -// CHECK-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 -// CHECK-NEXT: store i32 [[TMP0:%.*]], ptr [[DOTADDR]], align 4 -// CHECK-NEXT: ret i32 1 -// -// // CHECK-LABEL: @_Z7foo_ovli.resolver( // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -82,11 +75,6 @@ void run_foo_tml() { // CHECK-NEXT: ret i32 2 // // -// CHECK-LABEL: @_Z7foo_ovlv.default( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 2 -// -// // CHECK-LABEL: @_Z7foo_ovlv.resolver( // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -182,6 +170,18 @@ void run_foo_tml() { // CHECK-NEXT: ret i32 4 // // +// CHECK-LABEL: @_Z7foo_ovli.default( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store i32 [[TMP0:%.*]], ptr [[DOTADDR]], align 4 +// CHECK-NEXT: ret i32 1 +// +// +// CHECK-LABEL: @_Z7foo_ovlv.default( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 2 +// +// // CHECK-LABEL: @_ZN7MyClassIssE7foo_tmlEv._Mfrintts( // CHECK-NEXT: entry: // CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 @@ -231,8 +231,8 @@ void run_foo_tml() { // //. // CHECK: attributes #[[ATTR0:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" } -// CHECK: attributes #[[ATTR1:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } -// CHECK: attributes #[[ATTR2:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ls64" } +// CHECK: attributes #[[ATTR1:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ls64" } +// CHECK: attributes #[[ATTR2:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } // CHECK: attributes #[[ATTR3:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fptoint" } // CHECK: attributes #[[ATTR4:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme,+sme-f64f64" } //. diff --git a/clang/test/CodeGenCXX/attr-target-version.cpp b/clang/test/CodeGenCXX/attr-target-version.cpp index 82a928a385e16ba9b365fa736047902847c47687..8b7273fe3bb517e23642a266c5a526848537e2c5 100644 --- a/clang/test/CodeGenCXX/attr-target-version.cpp +++ b/clang/test/CodeGenCXX/attr-target-version.cpp @@ -10,28 +10,70 @@ struct MyClass { int __attribute__((target_version("dotprod"))) goo(int); int __attribute__((target_version("crc"))) goo(int); int __attribute__((target_version("default"))) goo(int); + + // This should generate one target version but no resolver. + int __attribute__((target_version("default"))) unused_with_forward_default_decl(void); + int __attribute__((target_version("mops"))) unused_with_forward_default_decl(void); + + // This should also generate one target version but no resolver. + int unused_with_implicit_forward_default_decl(void); + int __attribute__((target_version("dotprod"))) unused_with_implicit_forward_default_decl(void); + + // This should also generate one target version but no resolver. + int __attribute__((target_version("aes"))) unused_with_default_decl(void); + int __attribute__((target_version("default"))) unused_with_default_decl(void); + + // This should generate two target versions and the resolver. + int __attribute__((target_version("sve"))) unused_with_default_def(void); + int __attribute__((target_version("default"))) unused_with_default_def(void); + + // This should also generate two target versions and the resolver. + int __attribute__((target_version("fp16"))) unused_with_implicit_default_def(void); + int unused_with_implicit_default_def(void); + + // This should also generate two target versions and the resolver. + int unused_with_implicit_forward_default_def(void); + int __attribute__((target_version("lse"))) unused_with_implicit_forward_default_def(void); + + // This should generate a target version despite the default not being declared. + int __attribute__((target_version("rdm"))) unused_without_default(void); }; int __attribute__((target_version("default"))) MyClass::goo(int) { return 1; } int __attribute__((target_version("crc"))) MyClass::goo(int) { return 2; } int __attribute__((target_version("dotprod"))) MyClass::goo(int) { return 3; } +int __attribute__((target_version("mops"))) MyClass::unused_with_forward_default_decl(void) { return 0; } +int __attribute__((target_version("dotprod"))) MyClass::unused_with_implicit_forward_default_decl(void) { return 0; } +int __attribute__((target_version("aes"))) MyClass::unused_with_default_decl(void) { return 0; } +int __attribute__((target_version("sve"))) MyClass::unused_with_default_def(void) { return 0; } +int __attribute__((target_version("default"))) MyClass::unused_with_default_def(void) { return 1; } +int __attribute__((target_version("fp16"))) MyClass::unused_with_implicit_default_def(void) { return 0; } +int MyClass::unused_with_implicit_default_def(void) { return 1; } +int MyClass::unused_with_implicit_forward_default_def(void) { return 0; } +int __attribute__((target_version("lse"))) MyClass::unused_with_implicit_forward_default_def(void) { return 1; } +int __attribute__((target_version("rdm"))) MyClass::unused_without_default(void) { return 0; } + int bar() { MyClass m; return m.goo(1) + foo(1) + foo(); } - - //. // CHECK: @__aarch64_cpu_features = external dso_local global { i64 } -// CHECK: @_ZN7MyClass3gooEi.ifunc = weak_odr alias i32 (ptr, i32), ptr @_ZN7MyClass3gooEi // CHECK: @_Z3fooi.ifunc = weak_odr alias i32 (i32), ptr @_Z3fooi // CHECK: @_Z3foov.ifunc = weak_odr alias i32 (), ptr @_Z3foov +// CHECK: @_ZN7MyClass3gooEi.ifunc = weak_odr alias i32 (ptr, i32), ptr @_ZN7MyClass3gooEi +// CHECK: @_ZN7MyClass23unused_with_default_defEv.ifunc = weak_odr alias i32 (ptr), ptr @_ZN7MyClass23unused_with_default_defEv +// CHECK: @_ZN7MyClass32unused_with_implicit_default_defEv.ifunc = weak_odr alias i32 (ptr), ptr @_ZN7MyClass32unused_with_implicit_default_defEv +// CHECK: @_ZN7MyClass40unused_with_implicit_forward_default_defEv.ifunc = weak_odr alias i32 (ptr), ptr @_ZN7MyClass40unused_with_implicit_forward_default_defEv // CHECK: @_ZN7MyClass3gooEi = weak_odr ifunc i32 (ptr, i32), ptr @_ZN7MyClass3gooEi.resolver // CHECK: @_Z3fooi = weak_odr ifunc i32 (i32), ptr @_Z3fooi.resolver // CHECK: @_Z3foov = weak_odr ifunc i32 (), ptr @_Z3foov.resolver +// CHECK: @_ZN7MyClass23unused_with_default_defEv = weak_odr ifunc i32 (ptr), ptr @_ZN7MyClass23unused_with_default_defEv.resolver +// CHECK: @_ZN7MyClass32unused_with_implicit_default_defEv = weak_odr ifunc i32 (ptr), ptr @_ZN7MyClass32unused_with_implicit_default_defEv.resolver +// CHECK: @_ZN7MyClass40unused_with_implicit_forward_default_defEv = weak_odr ifunc i32 (ptr), ptr @_ZN7MyClass40unused_with_implicit_forward_default_defEv.resolver //. // CHECK-LABEL: @_Z3fooi._Mbf16Msme-f64f64( // CHECK-NEXT: entry: @@ -40,11 +82,144 @@ int bar() { // CHECK-NEXT: ret i32 1 // // +// CHECK-LABEL: @_Z3fooi.default( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store i32 [[TMP0:%.*]], ptr [[DOTADDR]], align 4 +// CHECK-NEXT: ret i32 2 +// +// // CHECK-LABEL: @_Z3foov._Mebf16Msm4( // CHECK-NEXT: entry: // CHECK-NEXT: ret i32 3 // // +// CHECK-LABEL: @_Z3foov.default( +// CHECK-NEXT: entry: +// CHECK-NEXT: ret i32 4 +// +// +// CHECK-LABEL: @_ZN7MyClass3gooEi.default( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: store i32 [[TMP0:%.*]], ptr [[DOTADDR]], align 4 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 1 +// +// +// CHECK-LABEL: @_ZN7MyClass3gooEi._Mcrc( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: store i32 [[TMP0:%.*]], ptr [[DOTADDR]], align 4 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 2 +// +// +// CHECK-LABEL: @_ZN7MyClass3gooEi._Mdotprod( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: store i32 [[TMP0:%.*]], ptr [[DOTADDR]], align 4 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 3 +// +// +// CHECK-LABEL: @_ZN7MyClass32unused_with_forward_default_declEv._Mmops( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 0 +// +// +// CHECK-LABEL: @_ZN7MyClass41unused_with_implicit_forward_default_declEv._Mdotprod( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 0 +// +// +// CHECK-LABEL: @_ZN7MyClass24unused_with_default_declEv._Maes( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 0 +// +// +// CHECK-LABEL: @_ZN7MyClass23unused_with_default_defEv._Msve( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 0 +// +// +// CHECK-LABEL: @_ZN7MyClass23unused_with_default_defEv.default( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 1 +// +// +// CHECK-LABEL: @_ZN7MyClass32unused_with_implicit_default_defEv._Mfp16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 0 +// +// +// CHECK-LABEL: @_ZN7MyClass32unused_with_implicit_default_defEv.default( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 1 +// +// +// CHECK-LABEL: @_ZN7MyClass40unused_with_implicit_forward_default_defEv.default( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 0 +// +// +// CHECK-LABEL: @_ZN7MyClass40unused_with_implicit_forward_default_defEv._Mlse( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 1 +// +// +// CHECK-LABEL: @_ZN7MyClass22unused_without_defaultEv._Mrdm( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 0 +// +// +// CHECK-LABEL: @_Z3barv( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[M:%.*]] = alloca [[STRUCT_MYCLASS:%.*]], align 1 +// CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_ZN7MyClass3gooEi(ptr noundef nonnull align 1 dereferenceable(1) [[M]], i32 noundef 1) +// CHECK-NEXT: [[CALL1:%.*]] = call noundef i32 @_Z3fooi(i32 noundef 1) +// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]] +// CHECK-NEXT: [[CALL2:%.*]] = call noundef i32 @_Z3foov() +// CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[ADD]], [[CALL2]] +// CHECK-NEXT: ret i32 [[ADD3]] +// +// // CHECK-LABEL: @_ZN7MyClass3gooEi.resolver( // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -67,17 +242,6 @@ int bar() { // CHECK-NEXT: ret ptr @_ZN7MyClass3gooEi.default // // -// CHECK-LABEL: @_Z3barv( -// CHECK-NEXT: entry: -// CHECK-NEXT: [[M:%.*]] = alloca [[STRUCT_MYCLASS:%.*]], align 1 -// CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_ZN7MyClass3gooEi(ptr noundef nonnull align 1 dereferenceable(1) [[M]], i32 noundef 1) -// CHECK-NEXT: [[CALL1:%.*]] = call noundef i32 @_Z3fooi(i32 noundef 1) -// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]] -// CHECK-NEXT: [[CALL2:%.*]] = call noundef i32 @_Z3foov() -// CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[ADD]], [[CALL2]] -// CHECK-NEXT: ret i32 [[ADD3]] -// -// // CHECK-LABEL: @_Z3fooi.resolver( // CHECK-NEXT: resolver_entry: // CHECK-NEXT: call void @__init_cpu_features_resolver() @@ -106,53 +270,60 @@ int bar() { // CHECK-NEXT: ret ptr @_Z3foov.default // // -// CHECK-LABEL: @_ZN7MyClass3gooEi._Mdotprod( -// CHECK-NEXT: entry: -// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 -// CHECK-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 -// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8 -// CHECK-NEXT: store i32 [[TMP0:%.*]], ptr [[DOTADDR]], align 4 -// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK-NEXT: ret i32 3 -// -// -// CHECK-LABEL: @_ZN7MyClass3gooEi._Mcrc( -// CHECK-NEXT: entry: -// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 -// CHECK-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 -// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8 -// CHECK-NEXT: store i32 [[TMP0:%.*]], ptr [[DOTADDR]], align 4 -// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK-NEXT: ret i32 2 -// -// -// CHECK-LABEL: @_ZN7MyClass3gooEi.default( -// CHECK-NEXT: entry: -// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 -// CHECK-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 -// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8 -// CHECK-NEXT: store i32 [[TMP0:%.*]], ptr [[DOTADDR]], align 4 -// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK-NEXT: ret i32 1 +// CHECK-LABEL: @_ZN7MyClass23unused_with_default_defEv.resolver( +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1073741824 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1073741824 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @_ZN7MyClass23unused_with_default_defEv._Msve +// CHECK: resolver_else: +// CHECK-NEXT: ret ptr @_ZN7MyClass23unused_with_default_defEv.default // // -// CHECK-LABEL: @_Z3fooi.default( -// CHECK-NEXT: entry: -// CHECK-NEXT: [[DOTADDR:%.*]] = alloca i32, align 4 -// CHECK-NEXT: store i32 [[TMP0:%.*]], ptr [[DOTADDR]], align 4 -// CHECK-NEXT: ret i32 2 +// CHECK-LABEL: @_ZN7MyClass32unused_with_implicit_default_defEv.resolver( +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 65536 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 65536 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @_ZN7MyClass32unused_with_implicit_default_defEv._Mfp16 +// CHECK: resolver_else: +// CHECK-NEXT: ret ptr @_ZN7MyClass32unused_with_implicit_default_defEv.default // // -// CHECK-LABEL: @_Z3foov.default( -// CHECK-NEXT: entry: -// CHECK-NEXT: ret i32 4 +// CHECK-LABEL: @_ZN7MyClass40unused_with_implicit_forward_default_defEv.resolver( +// CHECK-NEXT: resolver_entry: +// CHECK-NEXT: call void @__init_cpu_features_resolver() +// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 128 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 128 +// CHECK-NEXT: [[TMP3:%.*]] = and i1 true, [[TMP2]] +// CHECK-NEXT: br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]] +// CHECK: resolver_return: +// CHECK-NEXT: ret ptr @_ZN7MyClass40unused_with_implicit_forward_default_defEv._Mlse +// CHECK: resolver_else: +// CHECK-NEXT: ret ptr @_ZN7MyClass40unused_with_implicit_forward_default_defEv.default // //. // CHECK: attributes #[[ATTR0:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme,+sme-f64f64" } -// CHECK: attributes #[[ATTR1:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fp-armv8,+neon,+sm4" } -// CHECK: attributes #[[ATTR2:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } -// CHECK: attributes #[[ATTR3:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+neon" } -// CHECK: attributes #[[ATTR4:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc" } +// CHECK: attributes #[[ATTR1:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +// CHECK: attributes #[[ATTR2:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fp-armv8,+neon,+sm4" } +// CHECK: attributes #[[ATTR3:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+crc" } +// CHECK: attributes #[[ATTR4:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+neon" } +// CHECK: attributes #[[ATTR5:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops" } +// CHECK: attributes #[[ATTR6:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon" } +// CHECK: attributes #[[ATTR7:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve" } +// CHECK: attributes #[[ATTR8:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" } +// CHECK: attributes #[[ATTR9:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse" } +// CHECK: attributes #[[ATTR10:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rdm" } +// CHECK: attributes #[[ATTR11:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" } //. // CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4} // CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"} diff --git a/clang/test/CodeGenCXX/auto-var-init.cpp b/clang/test/CodeGenCXX/auto-var-init.cpp index e5a9d015f22f276cdcb4f8e010544e043f10a84f..7803ed5b633fede5beebe41359e08fd188919bd2 100644 --- a/clang/test/CodeGenCXX/auto-var-init.cpp +++ b/clang/test/CodeGenCXX/auto-var-init.cpp @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown -fblocks %s -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK,CHECK-O0 // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=pattern %s -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK-O0,PATTERN,PATTERN-O0 -// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=pattern %s -O1 -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK-O1,PATTERN,PATTERN-O1 +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=pattern %s -O1 -emit-llvm -o - | FileCheck %s -check-prefixes=PATTERN,PATTERN-O1 // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=zero %s -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK-O0,ZERO,ZERO-O0 -// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=zero %s -O1 -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK-O1,ZERO,ZERO-O1 +// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=zero %s -O1 -emit-llvm -o - | FileCheck %s -check-prefixes=ZERO,ZERO-O1 // RUN: %clang_cc1 -std=c++14 -triple i386-unknown-unknown -fblocks -ftrivial-auto-var-init=pattern %s -emit-llvm -o - | FileCheck %s -check-prefixes=CHECK-O0,PATTERN,PATTERN-O0 #pragma clang diagnostic ignored "-Winaccessible-base" @@ -1303,9 +1303,10 @@ TEST_CUSTOM(semivolatile, semivolatile, { 0x44444444, 0x44444444 }); // CHECK-O0: call void @llvm.memcpy // CHECK-NOT: !annotation // CHECK-O0: call void @{{.*}}used{{.*}}%custom) -// CHECK-O1: store i32 1145324612, ptr %custom, align 4 -// CHECK-O1-NEXT: %[[I:[^ ]*]] = getelementptr inbounds i8, ptr %custom, i64 4 -// CHECK-O1-NEXT: store i32 1145324612, ptr %[[I]], align 4 +// PATTERN-O1: store i32 1145324612, ptr %custom, align 4 +// PATTERN-O1-NEXT: %[[I:[^ ]*]] = getelementptr inbounds i8, ptr %custom, i64 4 +// PATTERN-O1-NEXT: store i32 1145324612, ptr %[[I]], align 4 +// ZERO-O1: store i64 4919131752989213764, ptr %custom, align 8 // CHECK-NOT: !annotation TEST_UNINIT(semivolatileinit, semivolatileinit); @@ -1345,7 +1346,7 @@ TEST_UNINIT(base, base); // PATTERN-O0: call void @llvm.memcpy{{.*}} @__const.test_base_uninit.uninit{{.+}}), !annotation [[AUTO_INIT]] // ZERO-LABEL: @test_base_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0,{{.+}}), !annotation [[AUTO_INIT]] -// ZERO-O1: store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV4base, i64 0, inrange i32 0, i64 2), {{.*}}, align 8 +// ZERO-O1: store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV4base, i64 0, i32 0, i64 2), {{.*}}, align 8 // ZERO-O1-NOT: !annotation TEST_BRACES(base, base); @@ -1366,7 +1367,7 @@ TEST_UNINIT(derived, derived); // ZERO-LABEL: @test_derived_uninit() // ZERO-O0: call void @llvm.memset{{.*}}, i8 0, {{.+}}), !annotation [[AUTO_INIT]] // ZERO-O1: store i64 0, {{.*}} align 8, !annotation [[AUTO_INIT]] -// ZERO-O1: store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV7derived, i64 0, inrange i32 0, i64 2), {{.*}} align 8 +// ZERO-O1: store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV7derived, i64 0, i32 0, i64 2), {{.*}} align 8 TEST_BRACES(derived, derived); // CHECK-LABEL: @test_derived_braces() @@ -1418,7 +1419,8 @@ TEST_CUSTOM(matching, matching, { .f = 0xf00f }); // CHECK-O0: call void @llvm.memcpy // CHECK-NOT: !annotation // CHECK-O0: call void @{{.*}}used{{.*}}%custom) -// CHECK-O1: store float 6.145500e+04, ptr {{.*}}, align 4 +// PATTERN-O1: store float 6.145500e+04, ptr {{.*}}, align 4 +// ZERO-O1: store i32 1198526208, ptr %custom, align 4 // CHECK-NOT: !annotation TEST_UNINIT(matchingreverse, matchingreverse); @@ -1445,7 +1447,8 @@ TEST_CUSTOM(matchingreverse, matchingreverse, { .i = 0xf00f }); // CHECK-O0: call void @llvm.memcpy // CHECK-NOT: !annotation // CHECK-O0: call void @{{.*}}used{{.*}}%custom) -// CHECK-O1: store i32 61455, ptr %custom, align 4 +// PATTERN-O1: store i32 61455, ptr %custom, align 4 +// ZERO-O1: store i32 61455, ptr %custom, align 4 // CHECK-NOT: !annotation TEST_UNINIT(unmatched, unmatched); @@ -1471,7 +1474,8 @@ TEST_CUSTOM(unmatched, unmatched, { .i = 0x3badbeef }); // CHECK-O0: call void @llvm.memcpy // CHECK-NOT: !annotation // CHECK-O0: call void @{{.*}}used{{.*}}%custom) -// CHECK-O1: store i32 1001242351, ptr {{.*}}, align 4 +// PATTERN-O1: store i32 1001242351, ptr {{.*}}, align 4 +// ZERO-O1: store i32 1001242351, ptr {{.*}}, align 4 // CHECK-NOT: !annotation TEST_UNINIT(unmatchedreverse, unmatchedreverse); @@ -1504,9 +1508,7 @@ TEST_CUSTOM(unmatchedreverse, unmatchedreverse, { .c = 42 }); // PATTERN-O1-NEXT: store i8 -86, ptr %[[I]], align {{.*}} // PATTERN-O1-NEXT: %[[I:[^ ]*]] = getelementptr inbounds i8, ptr %custom, i64 3 // PATTERN-O1-NEXT: store i8 -86, ptr %[[I]], align {{.*}} -// ZERO-O1: store i8 42, ptr {{.*}}, align 4 -// ZERO-O1-NEXT: %[[I:[^ ]*]] = getelementptr inbounds i8, ptr %custom, i64 1 -// ZERO-O1-NEXT: call void @llvm.memset.{{.*}}({{.*}}, i8 0, i64 3, {{.*}}) +// ZERO-O1: store i32 42, ptr {{.*}}, align 4 TEST_UNINIT(unmatchedfp, unmatchedfp); // CHECK-LABEL: @test_unmatchedfp_uninit() @@ -1531,7 +1533,8 @@ TEST_CUSTOM(unmatchedfp, unmatchedfp, { .d = 3.1415926535897932384626433 }); // CHECK-O0: call void @llvm.memcpy // CHECK-NOT: !annotation // CHECK-O0: call void @{{.*}}used{{.*}}%custom) -// CHECK-O1: store double 0x400921FB54442D18, ptr %custom, align 8 +// PATTERN-O1: store double 0x400921FB54442D18, ptr %custom, align 8 +// ZERO-O1: store i64 4614256656552045848, ptr %custom, align 8 // CHECK-NOT: !annotation TEST_UNINIT(emptyenum, emptyenum); diff --git a/clang/test/CodeGenCXX/bitfield-access-empty.cpp b/clang/test/CodeGenCXX/bitfield-access-empty.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c5e6f55ffa6964302ff53b520c4d07d16b08aa0d --- /dev/null +++ b/clang/test/CodeGenCXX/bitfield-access-empty.cpp @@ -0,0 +1,150 @@ +// Check if we can merge bitfields across empty members + +// Configs that have cheap unaligned access +// Little Endian +// RUN: %clang_cc1 -triple=aarch64-apple-darwin %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=aarch64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=arm-apple-darwin %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-DWN32 %s +// RUN: %clang_cc1 -triple=arm-none-eabi %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=i686-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=loongarch64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=powerpcle-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=ve-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=wasm32 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=wasm64 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=x86_64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s + +// Big Endian +// RUN: %clang_cc1 -triple=powerpc-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=powerpc64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=systemz %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s + +// Configs that have expensive unaligned access +// Little Endian +// RUN: %clang_cc1 -triple=amdgcn-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=arc-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=bpf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=csky %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=hexagon-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=le64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=loongarch32-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=nvptx-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=riscv32 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=riscv64 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=spir-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=xcore-none-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s + +// Big endian +// RUN: %clang_cc1 -triple=lanai-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=m68k-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=mips-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=mips64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=sparc-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s +// RUN: %clang_cc1 -triple=tce-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT %s + +struct Empty {}; + +struct P1 { + unsigned a : 16; + [[no_unique_address]] Empty e; + unsigned b : 16; +} p1; +// CHECK-LABEL: LLVMType:%struct.P1 = +// LAYOUT-SAME: type { i16, i16 } +// LAYOUT-DWN32-SAME: type { i16, i16 } +// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.P1 = +// CHECK: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:2 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:2 +// CHECK-NEXT: ]> + +struct P2 { + unsigned a : 15; + [[no_unique_address]] Empty e; + unsigned b : 15; +} p2; +// CHECK-LABEL: LLVMType:%struct.P2 = +// LAYOUT-SAME: type { i16, i16 } +// LAYOUT-DWN32-SAME: type { i16, i16 } +// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.P2 = +// CHECK: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:15 IsSigned:0 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:15 IsSigned:0 StorageSize:16 StorageOffset:2 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:15 IsSigned:0 StorageSize:16 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:15 IsSigned:0 StorageSize:16 StorageOffset:2 +// CHECK-NEXT: ]> + +struct P3 { + unsigned a : 16; + Empty e; + unsigned b : 16; +} p3; +// CHECK-LABEL: LLVMType:%struct.P3 = +// LAYOUT-SAME: type { i16, %struct.Empty, i16, [2 x i8] } +// LAYOUT-DWN32-SAME: type <{ i16, %struct.Empty, i16 }> +// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.P3 = +// CHECK: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:4 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:3 +// CHECK-NEXT: ]> + +struct P4 { + unsigned : 0; +} p4; +// CHECK-LABEL: LLVMType:%struct.P4 = +// LAYOUT-SAME: type { {{.+}} } +// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.P4 = +// CHECK: BitFields:[ +// CHECK-NEXT: ]> + +struct P5 { + ~P5(); + unsigned : 0; +} p5; +// CHECK-LABEL: LLVMType:%struct.P5 = +// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.P5.base = type {} +// CHECK: BitFields:[ +// CHECK-NEXT: ]> + +struct P6 { + unsigned a : 16; + unsigned b : 8; + [[no_unique_address]] Empty e; + unsigned c; +} p6; +// CHECK-LABEL: LLVMType:%struct.P6 = +// LAYOUT-SAME: type { i32, i32 } +// LAYOUT-DWN32-SAME: type { i32, i32 } +// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.P6 = +// CHECK: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:32 StorageOffset:0 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:32 StorageOffset:0 +// CHECK-NEXT: ]> + +struct P7 { + unsigned a : 16; + unsigned b : 8; + Empty e; + unsigned c; +} p7; +// CHECK-LABEL: LLVMType:%struct.P7 = +// LAYOUT-SAME: type { i16, i8, %struct.Empty, i32 } +// LAYOUT-DWN32-SAME: type { i16, i8, %struct.Empty, i32 } +// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.P7 = +// CHECK: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:2 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:0 StorageSize:16 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:0 StorageSize:8 StorageOffset:2 +// CHECK-NEXT: ]> diff --git a/clang/test/CodeGenCXX/bitfield-access-tail.cpp b/clang/test/CodeGenCXX/bitfield-access-tail.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1539e17cad4369c21d3596d2c551374040b60c4c --- /dev/null +++ b/clang/test/CodeGenCXX/bitfield-access-tail.cpp @@ -0,0 +1,157 @@ +// Check we use tail padding if it is known to be safe + +// Configs that have cheap unaligned access +// Little Endian +// RUN: %clang_cc1 -triple=aarch64-apple-darwin %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=aarch64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=arm-apple-darwin %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT-DWN32 %s +// RUN: %clang_cc1 -triple=arm-none-eabi %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=i686-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=loongarch64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=powerpcle-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=ve-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=wasm32 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=wasm64 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=x86_64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s + +// Big Endian +// RUN: %clang_cc1 -triple=powerpc-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=powerpc64-linux-gnu %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=systemz %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s + +// Configs that have expensive unaligned access +// Little Endian +// RUN: %clang_cc1 -triple=amdgcn-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=arc-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=bpf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=csky %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=hexagon-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=le64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=loongarch32-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=nvptx-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=riscv32 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=riscv64 %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=spir-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=xcore-none-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s + +// Big endian +// RUN: %clang_cc1 -triple=lanai-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=m68k-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=mips-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=mips64-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT64 %s +// RUN: %clang_cc1 -triple=sparc-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s +// RUN: %clang_cc1 -triple=tce-elf %s -emit-llvm -o /dev/null -fdump-record-layouts-simple | FileCheck --check-prefixes CHECK,LAYOUT,LAYOUT32 %s + +// Can use tail padding +struct Pod { + int a : 16; + int b : 8; +} P; +// CHECK-LABEL: LLVMType:%struct.Pod = +// LAYOUT-SAME: type { i32 } +// LAYOUT-DWN32-SAME: type <{ i16, i8 }> +// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.Pod = +// CHECK: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:32 StorageOffset:0 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:2 +// CHECK-NEXT: ]> + +// No tail padding +struct __attribute__((packed)) PPod { + int a : 16; + int b : 8; +} PP; +// CHECK-LABEL: LLVMType:%struct.PPod = +// LAYOUT-SAME: type <{ i16, i8 }> +// LAYOUT-DWN32-SAME: type <{ i16, i8 }> +// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.PPod = +// CHECK: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:2 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:2 +// CHECK-NEXT: ]> + +// Cannot use tail padding +struct NonPod { + ~NonPod(); + int a : 16; + int b : 8; +} NP; +// CHECK-LABEL: LLVMType:%struct.NonPod = +// LAYOUT-SAME: type <{ i16, i8, i8 }> +// LAYOUT-DWN32-SAME: type <{ i16, i8 }> +// CHECK-NEXT: NonVirtualBaseLLVMType:%struct. +// LAYOUT-SAME: NonPod.base = type <{ i16, i8 }> +// LAYOUT-DWN32-SAME: NonPod = type <{ i16, i8 }> +// CHECK: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:2 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:2 +// CHECK-NEXT: ]> + +// No tail padding +struct __attribute__((packed)) PNonPod { + ~PNonPod(); + int a : 16; + int b : 8; +} PNP; +// CHECK-LABEL: LLVMType:%struct.PNonPod = +// LAYOUT-SAME: type <{ i16, i8 }> +// LAYOUT-DWN32-SAME: type <{ i16, i8 }> +// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.PNonPod = +// CHECK: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:2 + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:16 IsSigned:1 StorageSize:16 StorageOffset:0 +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:8 IsSigned:1 StorageSize:8 StorageOffset:2 +// CHECK-NEXT: ]> + +struct __attribute__((aligned(4))) Empty {} empty; + +struct Char { char a; } cbase; +struct D : virtual Char { + [[no_unique_address]] Empty e0; + [[no_unique_address]] Empty e1; + unsigned a : 24; // keep as 24bits +} d; +// CHECK-LABEL: LLVMType:%struct.D = +// LAYOUT64-SAME: type <{ ptr, [3 x i8], %struct.Char, [4 x i8] }> +// LAYOUT32-SAME: type { ptr, [3 x i8], %struct.Char } +// LAYOUT-DWN32-SAME: type { ptr, [3 x i8], %struct.Char } +// CHECK-NEXT: NonVirtualBaseLLVMType: +// LAYOUT64-SAME: %struct.D.base = type <{ ptr, i32 }> +// LAYOUT32-SAME: %struct.D = type { ptr, [3 x i8], %struct.Char } +// LAYOUT-DWN32-SAME: %struct.D = type { ptr, [3 x i8], %struct.Char } +// CHECK: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:24 IsSigned:0 StorageSize:24 StorageOffset:{{(4|8)}} + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:24 IsSigned:0 StorageSize:24 StorageOffset:{{(4|8)}} +// CHECK-NEXT: ]> + +struct Int { int a; } ibase; +struct E : virtual Int { + [[no_unique_address]] Empty e0; + [[no_unique_address]] Empty e1; + unsigned a : 24; // expand to 32 +} e; +// CHECK-LABEL: LLVMType:%struct.E = +// LAYOUT64-SAME: type <{ ptr, i32, %struct.Int }> +// LAYOUT32-SAME: type { ptr, i32, %struct.Int } +// LAYOUT-DWN32-SAME: type { ptr, i32, %struct.Int } +// CHECK-NEXT: NonVirtualBaseLLVMType:%struct.E.base = +// LAYOUT64-SAME: type <{ ptr, i32 }> +// LAYOUT32-SAME: type { ptr, i32 } +// LAYOUT-DWN32-SAME: type { ptr, i32 } +// CHECK: BitFields:[ +// LAYOUT-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:24 IsSigned:0 StorageSize:32 StorageOffset:{{(4|8)}} + +// LAYOUT-DWN32-NEXT: <CGBitFieldInfo Offset:{{[0-9]+}} Size:24 IsSigned:0 StorageSize:32 StorageOffset:{{(4|8)}} +// CHECK-NEXT: ]> diff --git a/clang/test/CodeGenCXX/bitfield-ir.cpp b/clang/test/CodeGenCXX/bitfield-ir.cpp new file mode 100644 index 0000000000000000000000000000000000000000..76c144072da686794181e459fbbc43121c441f92 --- /dev/null +++ b/clang/test/CodeGenCXX/bitfield-ir.cpp @@ -0,0 +1,101 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2 +// RUN: %clang_cc1 -triple x86_64-linux-gnu -O2 -emit-llvm -o - %s | FileCheck %s + +struct Tail { + ~Tail(); + int a : 16; + int b : 8; +}; + +struct Char { + int a : 16; + int b : 8; + char c; +}; + +struct Int { + int a : 16; + int b : 8; + int c; +}; + + +// CHECK-LABEL: define dso_local void @_Z1AP4Tail +// CHECK-SAME: (ptr nocapture noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[P]], align 4 +// CHECK-NEXT: [[INC:%.*]] = add i16 [[BF_LOAD]], 1 +// CHECK-NEXT: store i16 [[INC]], ptr [[P]], align 4 +// CHECK-NEXT: ret void +// +void A (Tail *p) { + p->a++; +} + +// CHECK-LABEL: define dso_local void @_Z1BP4Tail +// CHECK-SAME: (ptr nocapture noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 2 +// CHECK-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[B]], align 2 +// CHECK-NEXT: [[INC:%.*]] = add i8 [[BF_LOAD]], 1 +// CHECK-NEXT: store i8 [[INC]], ptr [[B]], align 2 +// CHECK-NEXT: ret void +// +void B (Tail *p) { + p->b++; +} + +// CHECK-LABEL: define dso_local void @_Z1AP4Char +// CHECK-SAME: (ptr nocapture noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[P]], align 4 +// CHECK-NEXT: [[INC:%.*]] = add i16 [[BF_LOAD]], 1 +// CHECK-NEXT: store i16 [[INC]], ptr [[P]], align 4 +// CHECK-NEXT: ret void +// +void A (Char *p) { + p->a++; +} + +// CHECK-LABEL: define dso_local void @_Z1BP4Char +// CHECK-SAME: (ptr nocapture noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 2 +// CHECK-NEXT: [[BF_LOAD:%.*]] = load i8, ptr [[B]], align 2 +// CHECK-NEXT: [[INC:%.*]] = add i8 [[BF_LOAD]], 1 +// CHECK-NEXT: store i8 [[INC]], ptr [[B]], align 2 +// CHECK-NEXT: ret void +// +void B (Char *p) { + p->b++; +} + +// CHECK-LABEL: define dso_local void @_Z1AP3Int +// CHECK-SAME: (ptr nocapture noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[P]], align 4 +// CHECK-NEXT: [[INC:%.*]] = add i32 [[BF_LOAD]], 1 +// CHECK-NEXT: [[BF_VALUE:%.*]] = and i32 [[INC]], 65535 +// CHECK-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD]], -65536 +// CHECK-NEXT: [[BF_SET:%.*]] = or disjoint i32 [[BF_VALUE]], [[BF_CLEAR]] +// CHECK-NEXT: store i32 [[BF_SET]], ptr [[P]], align 4 +// CHECK-NEXT: ret void +// +void A (Int *p) { + p->a++; +} + +// CHECK-LABEL: define dso_local void @_Z1BP3Int +// CHECK-SAME: (ptr nocapture noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[BF_LOAD:%.*]] = load i32, ptr [[P]], align 4 +// CHECK-NEXT: [[BF_VALUE:%.*]] = add i32 [[BF_LOAD]], 65536 +// CHECK-NEXT: [[BF_SHL2:%.*]] = and i32 [[BF_VALUE]], 16711680 +// CHECK-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD]], -16711681 +// CHECK-NEXT: [[BF_SET:%.*]] = or disjoint i32 [[BF_SHL2]], [[BF_CLEAR]] +// CHECK-NEXT: store i32 [[BF_SET]], ptr [[P]], align 4 +// CHECK-NEXT: ret void +// +void B (Int *p) { + p->b++; +} diff --git a/clang/test/CodeGenCXX/bitfield.cpp b/clang/test/CodeGenCXX/bitfield.cpp index a478eb44915e7a3a86ab4c8a91597c615adc3a30..7545e02840e6b2edbdae216b601ff8b448869f6d 100644 --- a/clang/test/CodeGenCXX/bitfield.cpp +++ b/clang/test/CodeGenCXX/bitfield.cpp @@ -1,7 +1,9 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s \ -// RUN: | FileCheck -check-prefix=CHECK-X86-64 %s -// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -emit-llvm -o - %s \ -// RUN: | FileCheck -check-prefix=CHECK-PPC64 %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fdump-record-layouts-simple \ +// RUN: -emit-llvm -o %t %s | FileCheck -check-prefixes=LAYOUT,LAYOUT-X86-64 %s +// RUN: FileCheck -check-prefix=CHECK-X86-64 %s <%t +// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -fdump-record-layouts-simple\ +// RUN: -emit-llvm -o %t %s | FileCheck -check-prefixes=LAYOUT,LAYOUT-PPC64 %s +// RUN: FileCheck -check-prefix=CHECK-PPC64 %s <%t // // Tests for bitfield access patterns in C++ with special attention to // conformance to C++11 memory model requirements. @@ -19,6 +21,27 @@ namespace N0 { unsigned b70 : 6; unsigned b71 : 2; }; +// LAYOUT-LABEL: LLVMType:%"struct.N0::S" = +// LAYOUT-SAME: type { i64 } +// LAYOUT: BitFields:[ +// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:14 IsSigned:0 StorageSize:64 StorageOffset:0 +// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:14 Size:2 IsSigned:0 StorageSize:64 StorageOffset:0 +// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:16 Size:6 IsSigned:0 StorageSize:64 StorageOffset:0 +// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:22 Size:2 IsSigned:0 StorageSize:64 StorageOffset:0 +// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:24 Size:30 IsSigned:0 StorageSize:64 StorageOffset:0 +// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:54 Size:2 IsSigned:0 StorageSize:64 StorageOffset:0 +// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:56 Size:6 IsSigned:0 StorageSize:64 StorageOffset:0 +// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:62 Size:2 IsSigned:0 StorageSize:64 StorageOffset:0 +// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:50 Size:14 IsSigned:0 StorageSize:64 StorageOffset:0 +// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:48 Size:2 IsSigned:0 StorageSize:64 StorageOffset:0 +// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:42 Size:6 IsSigned:0 StorageSize:64 StorageOffset:0 +// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:40 Size:2 IsSigned:0 StorageSize:64 StorageOffset:0 +// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:10 Size:30 IsSigned:0 StorageSize:64 StorageOffset:0 +// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:8 Size:2 IsSigned:0 StorageSize:64 StorageOffset:0 +// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:2 Size:6 IsSigned:0 StorageSize:64 StorageOffset:0 +// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:0 Size:2 IsSigned:0 StorageSize:64 StorageOffset:0 +// LAYOUT-NEXT: ]> + unsigned read00(S* s) { // CHECK-X86-64-LABEL: define{{.*}} i32 @_ZN2N06read00 // CHECK-X86-64: %[[val:.*]] = load i64, ptr %{{.*}} @@ -149,6 +172,13 @@ namespace N1 { unsigned b : 1; char c; }; +// LAYOUT-LABEL: LLVMType:%"struct.N1::S" = +// LAYOUT-SAME: type { i8, i8, i8, i8 } +// LAYOUT: BitFields:[ +// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:1 IsSigned:0 StorageSize:8 StorageOffset:1 +// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:7 Size:1 IsSigned:0 StorageSize:8 StorageOffset:1 +// LAYOUT-NEXT: ]> + unsigned read(S* s) { // CHECK-X86-64-LABEL: define{{.*}} i32 @_ZN2N14read // CHECK-X86-64: %[[ptr:.*]] = getelementptr inbounds %{{.*}}, ptr %{{.*}}, i32 0, i32 1 @@ -193,6 +223,13 @@ namespace N2 { unsigned b : 24; void *p; }; +// LAYOUT-LABEL: LLVMType:%"struct.N2::S" = +// LAYOUT-SAME: type { i32, ptr } +// LAYOUT: BitFields:[ +// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:8 Size:24 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: ]> + unsigned read(S* s) { // CHECK-X86-64-LABEL: define{{.*}} i32 @_ZN2N24read // CHECK-X86-64: %[[val:.*]] = load i32, ptr %{{.*}} @@ -230,6 +267,13 @@ namespace N3 { struct S { unsigned b : 24; }; +// LAYOUT-LABEL: LLVMType:%"struct.N3::S" = +// LAYOUT-SAME: type { i32 } +// LAYOUT: BitFields:[ +// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:8 Size:24 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: ]> + unsigned read(S* s) { // CHECK-X86-64-LABEL: define{{.*}} i32 @_ZN2N34read // CHECK-X86-64: %[[val:.*]] = load i32, ptr %{{.*}} @@ -276,6 +320,14 @@ namespace N4 { char c; }; #endif +// LAYOUT-LABEL: LLVMType:%"struct.N4::Base" = +// LAYOUT-SAME: type <{ ptr, [3 x i8], [5 x i8] }> +// LAYOUT-NEXT: NonVirtualBaseLLVMType:%"struct.N4::Base.base" = type <{ ptr, [3 x i8] }> +// LAYOUT: BitFields:[ +// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:8 +// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:8 +// LAYOUT-NEXT: ]> + unsigned read(Base* s) { // FIXME: We should widen this load as long as the function isn't being // instrumented by ThreadSanitizer. @@ -317,6 +369,22 @@ namespace N5 { struct X { unsigned b : 24; char c; } x; struct Y { unsigned b : 24; } y; }; +// LAYOUT-LABEL: LLVMType:%"struct.N5::U::X" = +// LAYOUT-SAME: type { [3 x i8], i8 } +// LAYOUT-NEXT: NonVirtualBaseLLVMType:%"struct.N5::U::X" = +// LAYOUT: BitFields:[ +// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:0 +// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:0 +// LAYOUT-NEXT: ]> + +// LAYOUT-LABEL: LLVMType:%"struct.N5::U::Y" = +// LAYOUT-SAME: type { i32 } +// LAYOUT-NEXT: NonVirtualBaseLLVMType:%"struct.N5::U::Y" = +// LAYOUT: BitFields:[ +// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:8 Size:24 IsSigned:0 StorageSize:32 StorageOffset:0 +// LAYOUT-NEXT: ]> + unsigned read(U* u) { // CHECK-X86-64-LABEL: define{{.*}} i32 @_ZN2N54read // CHECK-X86-64: %[[val:.*]] = load i32, ptr %{{.*}} @@ -360,6 +428,15 @@ namespace N6 { unsigned char : 0; unsigned char b2 : 8; }; +// LAYOUT-LABEL: LLVMType:%"struct.N6::S" = +// LAYOUT-SAME: type { [3 x i8], i8 } +// LAYOUT: BitFields:[ +// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:0 +// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:8 IsSigned:0 StorageSize:8 StorageOffset:3 +// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:0 +// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:0 Size:8 IsSigned:0 StorageSize:8 StorageOffset:3 +// LAYOUT-NEXT: ]> + unsigned read(S* s) { // CHECK-X86-64-LABEL: define{{.*}} i32 @_ZN2N64read // CHECK-X86-64: %[[val1:.*]] = load i24, ptr %{{.*}} @@ -416,6 +493,22 @@ namespace N7 { char c; }; #endif +// LAYOUT-LABEL: LLVMType:%"struct.N7::B1" = +// LAYOUT-SAME: type <{ ptr, [3 x i8], [5 x i8] }> +// LAYOUT-NEXT: NonVirtualBaseLLVMType:%"struct.N7::B1.base" = type <{ ptr, [3 x i8] }> +// LAYOUT: BitFields:[ +// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:8 +// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:8 +// LAYOUT-NEXT: ]> + +// LAYOUT-LABEL: LLVMType:%"struct.N7::B2" = +// LAYOUT-SAME: type <{ ptr, [3 x i8], [5 x i8], %"struct.N7::B1.base", [5 x i8] }> +// LAYOUT-NEXT: NonVirtualBaseLLVMType:%"struct.N7::B2.base" = type <{ ptr, [3 x i8] }> +// LAYOUT: BitFields:[ +// LAYOUT-X86-64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:8 +// LAYOUT-PPC64-NEXT: <CGBitFieldInfo Offset:0 Size:24 IsSigned:0 StorageSize:24 StorageOffset:8 +// LAYOUT-NEXT: ]> + unsigned read(B2* s) { // FIXME: We should widen this load as long as the function isn't being // instrumented by ThreadSanitizer. diff --git a/clang/test/CodeGenCXX/const-init-cxx11.cpp b/clang/test/CodeGenCXX/const-init-cxx11.cpp index 3a12fe444f137bf96612337864f1be1141e70f95..7c92af0def527966ab2f8ca49b3fef2d787380d9 100644 --- a/clang/test/CodeGenCXX/const-init-cxx11.cpp +++ b/clang/test/CodeGenCXX/const-init-cxx11.cpp @@ -344,13 +344,13 @@ namespace VirtualMembers { constexpr E() : B(3), c{'b','y','e'} {} char c[3]; }; - // CHECK: @_ZN14VirtualMembers1eE ={{.*}} global { ptr, double, i32, ptr, double, [5 x i8], i16, ptr, double, [5 x i8], [3 x i8] } { ptr getelementptr inbounds ({ [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN14VirtualMembers1EE, i32 0, inrange i32 0, i32 2), double 1.000000e+00, i32 64, ptr getelementptr inbounds ({ [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN14VirtualMembers1EE, i32 0, inrange i32 1, i32 2), double 2.000000e+00, [5 x i8] c"hello", i16 5, ptr getelementptr inbounds ({ [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN14VirtualMembers1EE, i32 0, inrange i32 2, i32 2), double 3.000000e+00, [5 x i8] c"world", [3 x i8] c"bye" } + // CHECK: @_ZN14VirtualMembers1eE ={{.*}} global { ptr, double, i32, ptr, double, [5 x i8], i16, ptr, double, [5 x i8], [3 x i8] } { ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN14VirtualMembers1EE, i32 0, i32 0, i32 2), double 1.000000e+00, i32 64, ptr getelementptr inbounds inrange(-16, 16) ({ [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN14VirtualMembers1EE, i32 0, i32 1, i32 2), double 2.000000e+00, [5 x i8] c"hello", i16 5, ptr getelementptr inbounds inrange(-16, 16) ({ [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN14VirtualMembers1EE, i32 0, i32 2, i32 2), double 3.000000e+00, [5 x i8] c"world", [3 x i8] c"bye" } E e; struct nsMemoryImpl { virtual void f(); }; - // CHECK: @_ZN14VirtualMembersL13sGlobalMemoryE = internal global %"struct.VirtualMembers::nsMemoryImpl" { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN14VirtualMembers12nsMemoryImplE, i32 0, inrange i32 0, i32 2) } + // CHECK: @_ZN14VirtualMembersL13sGlobalMemoryE = internal global %"struct.VirtualMembers::nsMemoryImpl" { ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN14VirtualMembers12nsMemoryImplE, i32 0, i32 0, i32 2) } __attribute__((used)) static nsMemoryImpl sGlobalMemory; @@ -361,7 +361,7 @@ namespace VirtualMembers { T t; }; - // CHECK: @_ZN14VirtualMembers1tE ={{.*}} global { ptr, i32 } { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN14VirtualMembers13TemplateClassIiEE, i32 0, inrange i32 0, i32 2), i32 42 } + // CHECK: @_ZN14VirtualMembers1tE ={{.*}} global { ptr, i32 } { ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN14VirtualMembers13TemplateClassIiEE, i32 0, i32 0, i32 2), i32 42 } TemplateClass<int> t; } diff --git a/clang/test/CodeGenCXX/constructor-init.cpp b/clang/test/CodeGenCXX/constructor-init.cpp index 3d473e67ea0d8e3f391c38c95c9dcf871779b9bb..f191599f360e7babf7b0a8feb048c156528b14d3 100644 --- a/clang/test/CodeGenCXX/constructor-init.cpp +++ b/clang/test/CodeGenCXX/constructor-init.cpp @@ -94,20 +94,20 @@ namespace InitVTable { }; // CHECK-LABEL: define{{.*}} void @_ZN10InitVTable1BC2Ev(ptr {{[^,]*}} %this) unnamed_addr - // CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN10InitVTable1BE, i32 0, inrange i32 0, i32 2), ptr [[THIS:%.*]], + // CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN10InitVTable1BE, i32 0, i32 0, i32 2), ptr [[THIS:%.*]], // CHECK: [[VTBL:%.*]] = load ptr, ptr {{%.*}} // CHECK-NEXT: [[FNP:%.*]] = getelementptr inbounds ptr, ptr [[VTBL]], i64 0 // CHECK-NEXT: [[FN:%.*]] = load ptr, ptr [[FNP]] // CHECK-NEXT: [[ARG:%.*]] = call noundef i32 [[FN]](ptr {{[^,]*}} [[THIS]]) // CHECK-NEXT: call void @_ZN10InitVTable1AC2Ei(ptr {{[^,]*}} {{%.*}}, i32 noundef [[ARG]]) - // CHECK-NEXT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN10InitVTable1BE, i32 0, inrange i32 0, i32 2), ptr [[THIS]] + // CHECK-NEXT: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN10InitVTable1BE, i32 0, i32 0, i32 2), ptr [[THIS]] // CHECK-NEXT: ret void B::B() : A(foo()) {} // CHECK-LABEL: define{{.*}} void @_ZN10InitVTable1BC2Ei(ptr {{[^,]*}} %this, i32 noundef %x) unnamed_addr // CHECK: [[ARG:%.*]] = add nsw i32 {{%.*}}, 5 // CHECK-NEXT: call void @_ZN10InitVTable1AC2Ei(ptr {{[^,]*}} {{%.*}}, i32 noundef [[ARG]]) - // CHECK-NEXT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN10InitVTable1BE, i32 0, inrange i32 0, i32 2), ptr {{%.*}} + // CHECK-NEXT: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN10InitVTable1BE, i32 0, i32 0, i32 2), ptr {{%.*}} // CHECK-NEXT: ret void B::B(int x) : A(x + 5) {} } diff --git a/clang/test/CodeGenCXX/copy-constructor-synthesis-2.cpp b/clang/test/CodeGenCXX/copy-constructor-synthesis-2.cpp index 043dff44f37c261ca2ebf61f461f459d6b92e5ae..ae0c3a26c597ea6445ea5339b540f12b43272565 100644 --- a/clang/test/CodeGenCXX/copy-constructor-synthesis-2.cpp +++ b/clang/test/CodeGenCXX/copy-constructor-synthesis-2.cpp @@ -24,4 +24,4 @@ struct A { virtual void a(); }; A x(A& y) { return y; } // CHECK: define linkonce_odr {{.*}} @_ZN1AC1ERKS_(ptr {{.*}}%this, ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %0) unnamed_addr -// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, inrange i32 0, i32 2) +// CHECK: store ptr getelementptr inbounds inrange(-{{[0-9]+}}, {{[0-9]+}}) ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 2) diff --git a/clang/test/CodeGenCXX/copy-constructor-synthesis.cpp b/clang/test/CodeGenCXX/copy-constructor-synthesis.cpp index 3548897ec4ba0feb4a9c3268f460d8fea0ae9135..e4f6995aec3cfdc1f6db1f9edd84a8b50ac701da 100644 --- a/clang/test/CodeGenCXX/copy-constructor-synthesis.cpp +++ b/clang/test/CodeGenCXX/copy-constructor-synthesis.cpp @@ -163,7 +163,7 @@ void f(B b1) { // CHECK-LABEL: define linkonce_odr void @_ZN12rdar138169401AC2ERKS0_( // CHECK: [[THIS:%.*]] = load ptr, ptr -// CHECK-NEXT: store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTVN12rdar138169401AE, i32 0, inrange i32 0, i32 2), ptr [[THIS]] +// CHECK-NEXT: store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTVN12rdar138169401AE, i32 0, i32 0, i32 2), ptr [[THIS]] // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[A]], ptr [[THIS]], i32 0, i32 1 // CHECK-NEXT: [[OTHER:%.*]] = load ptr, ptr // CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]], ptr [[OTHER]], i32 0, i32 1 diff --git a/clang/test/CodeGenCXX/dynamic-cast-exact.cpp b/clang/test/CodeGenCXX/dynamic-cast-exact.cpp index bd283e85101b4b6dfeece4a89a41af6cc328d2d9..86e1965b4ba68bdf25f0b3cc050e3e34cdf36e4c 100644 --- a/clang/test/CodeGenCXX/dynamic-cast-exact.cpp +++ b/clang/test/CodeGenCXX/dynamic-cast-exact.cpp @@ -23,7 +23,7 @@ B *exact_single(A *a) { // CHECK: [[LABEL_NOTNULL]]: // CHECK: %[[VPTR:.*]] = load ptr, ptr %[[PTR]] - // CHECK: %[[MATCH:.*]] = icmp eq ptr %[[VPTR]], getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr @_ZTV1B, i32 0, inrange i32 1, i32 2) + // CHECK: %[[MATCH:.*]] = icmp eq ptr %[[VPTR]], getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [4 x ptr] }, ptr @_ZTV1B, i32 0, i32 1, i32 2) // CHECK: %[[RESULT:.*]] = getelementptr inbounds i8, ptr %[[PTR]], i64 -8 // CHECK: br i1 %[[MATCH]], label %[[LABEL_END:.*]], label %[[LABEL_FAILED]] @@ -42,7 +42,7 @@ B &exact_ref(A &a) { // CHECK: [[LABEL_NOTNULL]]: // CHECK: %[[VPTR:.*]] = load ptr, ptr %[[PTR]] - // CHECK: %[[MATCH:.*]] = icmp eq ptr %[[VPTR]], getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr @_ZTV1B, i32 0, inrange i32 1, i32 2) + // CHECK: %[[MATCH:.*]] = icmp eq ptr %[[VPTR]], getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [4 x ptr] }, ptr @_ZTV1B, i32 0, i32 1, i32 2) // CHECK: %[[RESULT:.*]] = getelementptr inbounds i8, ptr %[[PTR]], i64 -8 // CHECK: br i1 %[[MATCH]], label %[[LABEL_END:.*]], label %[[LABEL_FAILED]] @@ -66,7 +66,7 @@ H *exact_multi(A *a) { // CHECK: %[[OFFSET_TO_TOP:.*]] = load i64, ptr %[[OFFSET_TO_TOP_SLOT]] // CHECK: %[[RESULT:.*]] = getelementptr inbounds i8, ptr %[[PTR]], i64 %[[OFFSET_TO_TOP]] // CHECK: %[[DERIVED_VPTR:.*]] = load ptr, ptr %[[RESULT]] - // CHECK: %[[MATCH:.*]] = icmp eq ptr %[[DERIVED_VPTR]], getelementptr inbounds ({ [5 x ptr], [4 x ptr], [4 x ptr], [6 x ptr], [6 x ptr] }, ptr @_ZTV1H, i32 0, inrange i32 0, i32 3) + // CHECK: %[[MATCH:.*]] = icmp eq ptr %[[DERIVED_VPTR]], getelementptr inbounds inrange(-24, 16) ({ [5 x ptr], [4 x ptr], [4 x ptr], [6 x ptr], [6 x ptr] }, ptr @_ZTV1H, i32 0, i32 0, i32 3) // CHECK: br i1 %[[MATCH]], label %[[LABEL_END:.*]], label %[[LABEL_FAILED]] // CHECK: [[LABEL_FAILED]]: diff --git a/clang/test/CodeGenCXX/ext-int.cpp b/clang/test/CodeGenCXX/ext-int.cpp index 5a4270aef28542e74e9692005c2e77d43688ba35..a1d17c840ee46054bf791efc560cbc591fb87c78 100644 --- a/clang/test/CodeGenCXX/ext-int.cpp +++ b/clang/test/CodeGenCXX/ext-int.cpp @@ -159,9 +159,9 @@ void TakesVarargs(int i, ...) { // WIN: %[[ARGS:.+]] = alloca ptr __builtin_va_start(args, i); // LIN64: %[[STARTAD:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[ARGS]] - // LIN64: call void @llvm.va_start(ptr %[[STARTAD]]) - // LIN32: call void @llvm.va_start(ptr %[[ARGS]]) - // WIN: call void @llvm.va_start(ptr %[[ARGS]]) + // LIN64: call void @llvm.va_start.p0(ptr %[[STARTAD]]) + // LIN32: call void @llvm.va_start.p0(ptr %[[ARGS]]) + // WIN: call void @llvm.va_start.p0(ptr %[[ARGS]]) _BitInt(92) A = __builtin_va_arg(args, _BitInt(92)); // LIN64: %[[AD1:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[ARGS]] @@ -302,9 +302,9 @@ void TakesVarargs(int i, ...) { __builtin_va_end(args); // LIN64: %[[ENDAD:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[ARGS]] - // LIN64: call void @llvm.va_end(ptr %[[ENDAD]]) - // LIN32: call void @llvm.va_end(ptr %[[ARGS]]) - // WIN: call void @llvm.va_end(ptr %[[ARGS]]) + // LIN64: call void @llvm.va_end.p0(ptr %[[ENDAD]]) + // LIN32: call void @llvm.va_end.p0(ptr %[[ARGS]]) + // WIN: call void @llvm.va_end.p0(ptr %[[ARGS]]) } void typeid_tests() { // LIN: define{{.*}} void @_Z12typeid_testsv() diff --git a/clang/test/CodeGenCXX/ibm128-declarations.cpp b/clang/test/CodeGenCXX/ibm128-declarations.cpp index 5ee4f354d379570e987d0b66551bbdb7fe3760d3..e0187e20cde423edf970057b6e94f9c9d247a249 100644 --- a/clang/test/CodeGenCXX/ibm128-declarations.cpp +++ b/clang/test/CodeGenCXX/ibm128-declarations.cpp @@ -107,13 +107,13 @@ int main(void) { // CHECK: define dso_local noundef ppc_fp128 @_Z10func_vaargiz(i32 noundef signext %n, ...) // CHECK: entry: // CHECK: store i32 %n, ptr %n.addr, align 4 -// CHECK: call void @llvm.va_start(ptr %ap) +// CHECK: call void @llvm.va_start.p0(ptr %ap) // CHECK: %argp.cur = load ptr, ptr %ap, align 8 // CHECK: %argp.next = getelementptr inbounds i8, ptr %argp.cur, i64 16 // CHECK: store ptr %argp.next, ptr %ap, align 8 // CHECK: %0 = load ppc_fp128, ptr %argp.cur, align 8 // CHECK: store ppc_fp128 %0, ptr %r, align 16 -// CHECK: call void @llvm.va_end(ptr %ap) +// CHECK: call void @llvm.va_end.p0(ptr %ap) // CHECK: %1 = load ppc_fp128, ptr %r, align 16 // CHECK: ret ppc_fp128 %1 // CHECK: } diff --git a/clang/test/CodeGenCXX/mangle-ms-back-references.cpp b/clang/test/CodeGenCXX/mangle-ms-back-references.cpp index cb95c100b3d22e0fe8500c8a87f5c9543eac36b4..8707bff95340703be8afc2b982848f12238e0a19 100644 --- a/clang/test/CodeGenCXX/mangle-ms-back-references.cpp +++ b/clang/test/CodeGenCXX/mangle-ms-back-references.cpp @@ -1,5 +1,18 @@ // RUN: %clang_cc1 -fms-extensions -fblocks -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s +namespace NS { +// The name "RT1" for the name of the class below has been specifically +// chosen to ensure that back reference lookup does not match against the +// implicitly generated "$RT1" name of the reference temporary symbol. +struct RT1 { + static const RT1& singleton; + int i; +}; +const RT1& RT1::singleton = RT1{1}; +} +// CHECK: "?$RT1@singleton@RT1@NS@@2ABU23@B" +// CHECK: "?singleton@RT1@NS@@2ABU12@B" + void f1(const char* a, const char* b) {} // CHECK: "?f1@@YAXPBD0@Z" @@ -83,3 +96,20 @@ class H; void ManyParams(T01 &, T02 &, T03 &, T04 &, T05 &, T06 &, T07 &, T08 &, T09 &, T10 &, H<T11> &, H<T11> &) {} // CHECK: "?ManyParams@@YAXAAVT01@@AAVT02@@AAVT03@@AAVT04@@AAVT05@@AAVT06@@AAVT07@@AAVT08@@AAVT09@@AAVT10@@AAV?$H@VT11@@@@AAV?$H@VT11@@@@@Z" + +namespace NS { +// The name "TSS0" for the name of the class below has been specifically +// chosen to ensure that back reference lookup does not match against the +// implicitly generated "$TSS0" name of the thread safe static initialization +// variable. +struct __declspec(dllexport) TSS0 { + static TSS0& get(); + __forceinline static TSS0& singleton() { + static TSS0& lsv = get(); + return lsv; + } +}; +} +// CHECK: "?singleton@TSS0@NS@@SAAAU12@XZ" +// CHECK: "?lsv@?1??singleton@TSS0@NS@@SAAAU23@XZ@4AAU23@A" +// CHECK: "?$TSS0@?1??singleton@TSS0@NS@@SAAAU23@XZ@4HA" diff --git a/clang/test/CodeGenCXX/microsoft-interface.cpp b/clang/test/CodeGenCXX/microsoft-interface.cpp index d70caa15ed3c18a9e8f6ca0e3c1b01df27c14356..09b30bc96c855a105a77e4e159accbfea1f20d14 100644 --- a/clang/test/CodeGenCXX/microsoft-interface.cpp +++ b/clang/test/CodeGenCXX/microsoft-interface.cpp @@ -31,10 +31,10 @@ int fn() { // CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @_ZN1SC2Ev(ptr {{[^,]*}} %this) // CHECK: call x86_thiscallcc void @_ZN1IC2Ev(ptr {{[^,]*}} %{{[.0-9A-Z_a-z]+}}) -// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1S, i32 0, inrange i32 0, i32 2), ptr %{{[.0-9A-Z_a-z]+}} +// CHECK: store ptr getelementptr inbounds inrange(-8, 4) ({ [3 x ptr] }, ptr @_ZTV1S, i32 0, i32 0, i32 2), ptr %{{[.0-9A-Z_a-z]+}} // CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @_ZN1IC2Ev(ptr {{[^,]*}} %this) -// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1I, i32 0, inrange i32 0, i32 2), ptr %{{[.0-9A-Z_a-z]+}} +// CHECK: store ptr getelementptr inbounds inrange(-8, 4) ({ [3 x ptr] }, ptr @_ZTV1I, i32 0, i32 0, i32 2), ptr %{{[.0-9A-Z_a-z]+}} // CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef i32 @_ZN1I4testEv(ptr {{[^,]*}} %this) // CHECK: ret i32 1 diff --git a/clang/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp b/clang/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp index eb8f21b57aa7b6ef2441c3d7a8208a88b4307515..c001ce9b755d14e9a5433269d122cb2f370fd111 100644 --- a/clang/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp +++ b/clang/test/CodeGenCXX/skip-vtable-pointer-initialization.cpp @@ -27,7 +27,7 @@ struct A { }; // CHECK-LABEL: define{{.*}} void @_ZN5Test21AD2Ev -// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5Test21AE, i32 0, inrange i32 0, i32 2), ptr +// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test21AE, i32 0, i32 0, i32 2), ptr A::~A() { f(); } @@ -50,7 +50,7 @@ struct A { }; // CHECK-LABEL: define{{.*}} void @_ZN5Test31AD2Ev -// CHECK-NOT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5Test31AE, i32 0, inrange i32 0, i32 2), ptr +// CHECK-NOT: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test31AE, i32 0, i32 0, i32 2), ptr A::~A() { } @@ -76,7 +76,7 @@ struct A { }; // CHECK-LABEL: define{{.*}} void @_ZN5Test41AD2Ev -// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5Test41AE, i32 0, inrange i32 0, i32 2), ptr +// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test41AE, i32 0, i32 0, i32 2), ptr A::~A() { } @@ -100,7 +100,7 @@ struct A { }; // CHECK-LABEL: define{{.*}} void @_ZN5Test51AD2Ev -// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5Test51AE, i32 0, inrange i32 0, i32 2), ptr +// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test51AE, i32 0, i32 0, i32 2), ptr A::~A() { } @@ -128,7 +128,7 @@ struct A { }; // CHECK-LABEL: define{{.*}} void @_ZN5Test61AD2Ev -// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5Test61AE, i32 0, inrange i32 0, i32 2), ptr +// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test61AE, i32 0, i32 0, i32 2), ptr A::~A() { } @@ -154,7 +154,7 @@ struct A { }; // CHECK-LABEL: define{{.*}} void @_ZN5Test71AD2Ev -// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5Test71AE, i32 0, inrange i32 0, i32 2), ptr +// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test71AE, i32 0, i32 0, i32 2), ptr A::~A() { } @@ -180,7 +180,7 @@ struct A { }; // CHECK-LABEL: define{{.*}} void @_ZN5Test81AD2Ev -// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5Test81AE, i32 0, inrange i32 0, i32 2), ptr +// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5Test81AE, i32 0, i32 0, i32 2), ptr A::~A() { } diff --git a/clang/test/CodeGenCXX/static-init.cpp b/clang/test/CodeGenCXX/static-init.cpp index a44f78116dbbee2d971c6c0de267f663a8f0574a..51080c895ec65ab2e2ff13352259b9bdb5a4335c 100644 --- a/clang/test/CodeGenCXX/static-init.cpp +++ b/clang/test/CodeGenCXX/static-init.cpp @@ -14,7 +14,7 @@ // CHECK: @_ZGVZ2h2vE1i = linkonce_odr global i64 0, comdat, align 8{{$}} // CHECK: @_ZZN5test1L6getvarEiE3var = internal constant [4 x i32] [i32 1, i32 0, i32 2, i32 4], align 16 // CHECK98: @_ZZN5test414useStaticLocalEvE3obj = linkonce_odr global %"struct.test4::HasVTable" zeroinitializer, comdat, align 8 -// CHECK11: @_ZZN5test414useStaticLocalEvE3obj = linkonce_odr global %"struct.test4::HasVTable" { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5test49HasVTableE, i32 0, inrange i32 0, i32 2) }, comdat, align 8 +// CHECK11: @_ZZN5test414useStaticLocalEvE3obj = linkonce_odr global %"struct.test4::HasVTable" { ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5test49HasVTableE, i32 0, i32 0, i32 2) }, comdat, align 8 struct A { A(); diff --git a/clang/test/CodeGenCXX/strict-vtable-pointers.cpp b/clang/test/CodeGenCXX/strict-vtable-pointers.cpp index 34e50b39a5daa4afee44bb48761bccef97463850..6dffa50a5430d0e8d289650d71071b56440d9b8f 100644 --- a/clang/test/CodeGenCXX/strict-vtable-pointers.cpp +++ b/clang/test/CodeGenCXX/strict-vtable-pointers.cpp @@ -154,10 +154,10 @@ struct DynamicDerivedMultiple; // CHECK-CTORS: call void @_ZN12DynamicBase2C2Ev( // CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0 -// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 0, i32 2), {{.*}} %[[THIS0]] +// CHECK-CTORS: store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [3 x ptr] }, ptr @_ZTV22DynamicDerivedMultiple, i32 0, i32 0, i32 2), ptr %[[THIS0]] // CHECK-CTORS: %[[THIS_ADD:.*]] = getelementptr inbounds i8, ptr %[[THIS0]], i64 16 -// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 1, i32 2), {{.*}} %[[THIS_ADD]] +// CHECK-CTORS: store ptr getelementptr inbounds inrange(-16, 8) ({ [4 x ptr], [3 x ptr] }, ptr @_ZTV22DynamicDerivedMultiple, i32 0, i32 1, i32 2), ptr %[[THIS_ADD]] // CHECK-CTORS-LABEL: {{^}}} struct DynamicFromStatic; diff --git a/clang/test/CodeGenCXX/visibility.cpp b/clang/test/CodeGenCXX/visibility.cpp index e307b8747c84779fda1d16b91d51d5a88933186d..e1061f3dbd18f81baddff4a974f18cce36d2977f 100644 --- a/clang/test/CodeGenCXX/visibility.cpp +++ b/clang/test/CodeGenCXX/visibility.cpp @@ -207,7 +207,7 @@ namespace test27 { // CHECK-HIDDEN: @_ZGVZN6test681fC1EvE4test = linkonce_odr hidden global // CHECK-HIDDEN: @_ZTVN6test701DE = linkonce_odr hidden unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @_ZTIN6test701DE] }, align 8 -// CHECK-HIDDEN: @_ZTTN6test701DE = linkonce_odr hidden unnamed_addr constant [1 x ptr] [ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN6test701DE, i32 0, inrange i32 0, i32 3)], align 8 +// CHECK-HIDDEN: @_ZTTN6test701DE = linkonce_odr hidden unnamed_addr constant [1 x ptr] [ptr getelementptr inbounds inrange(-24, 0) ({ [3 x ptr] }, ptr @_ZTVN6test701DE, i32 0, i32 0, i32 3)], align 8 // CHECK: @_ZZN6Test193fooIiEEvvE1a = linkonce_odr global // CHECK-HIDDEN: @_ZZN6Test193fooIiEEvvE1a = linkonce_odr hidden global diff --git a/clang/test/CodeGenCXX/vtable-assume-load-address-space.cpp b/clang/test/CodeGenCXX/vtable-assume-load-address-space.cpp index 251d12bbb62f3095cc5e491b356cbcee1763366c..d765fe94d9b084ed9e25767527492d4a7ecd179f 100644 --- a/clang/test/CodeGenCXX/vtable-assume-load-address-space.cpp +++ b/clang/test/CodeGenCXX/vtable-assume-load-address-space.cpp @@ -25,7 +25,7 @@ void g(A *a) { a->foo(); } // CHECK1-LABEL: define{{.*}} void @_ZN5test14fooAEv() // CHECK1: call void @_ZN5test11AC1Ev(ptr // CHECK1: %[[VTABLE:.*]] = load ptr addrspace(1), ptr %{{.*}} -// CHECK1: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test11AE, i32 0, inrange i32 0, i32 2) +// CHECK1: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test11AE, i32 0, i32 0, i32 2) // CHECK1: call void @llvm.assume(i1 %[[CMP]]) // CHECK1-LABEL: {{^}}} @@ -37,7 +37,7 @@ void fooA() { // CHECK1-LABEL: define{{.*}} void @_ZN5test14fooBEv() // CHECK1: call void @_ZN5test11BC1Ev(ptr {{[^,]*}} %{{.*}}) // CHECK1: %[[VTABLE:.*]] = load ptr addrspace(1), ptr %{{.*}} -// CHECK1: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test11BE, i32 0, inrange i32 0, i32 2) +// CHECK1: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test11BE, i32 0, i32 0, i32 2) // CHECK1: call void @llvm.assume(i1 %[[CMP]]) // CHECK1-LABEL: {{^}}} @@ -71,12 +71,12 @@ void h(B *b) { b->bar(); } // CHECK2-LABEL: define{{.*}} void @_ZN5test24testEv() // CHECK2: call void @_ZN5test21CC1Ev(ptr // CHECK2: %[[VTABLE:.*]] = load ptr addrspace(1), ptr {{.*}} -// CHECK2: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds ({ [3 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test21CE, i32 0, inrange i32 0, i32 2) +// CHECK2: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test21CE, i32 0, i32 0, i32 2) // CHECK2: call void @llvm.assume(i1 %[[CMP]]) // CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i64 8 // CHECK2: %[[VTABLE2:.*]] = load ptr addrspace(1), ptr %[[ADD_PTR]] -// CHECK2: %[[CMP2:.*]] = icmp eq ptr addrspace(1) %[[VTABLE2]], getelementptr inbounds ({ [3 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test21CE, i32 0, inrange i32 1, i32 2) +// CHECK2: %[[CMP2:.*]] = icmp eq ptr addrspace(1) %[[VTABLE2]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test21CE, i32 0, i32 1, i32 2) // CHECK2: call void @llvm.assume(i1 %[[CMP2]]) // CHECK2: call void @_ZN5test21gEPNS_1AE( @@ -107,7 +107,7 @@ void g(B *a) { a->foo(); } // CHECK3-LABEL: define{{.*}} void @_ZN5test34testEv() // CHECK3: call void @_ZN5test31CC1Ev(ptr -// CHECK3: %[[CMP:.*]] = icmp eq ptr addrspace(1) %{{.*}}, getelementptr inbounds ({ [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test31CE, i32 0, inrange i32 0, i32 3) +// CHECK3: %[[CMP:.*]] = icmp eq ptr addrspace(1) %{{.*}}, getelementptr inbounds inrange(-24, 8) ({ [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test31CE, i32 0, i32 0, i32 3) // CHECK3: call void @llvm.assume(i1 %[[CMP]]) // CHECK3-LABLEL: } void test() { @@ -136,11 +136,11 @@ void g(C *c) { c->foo(); } // CHECK4-LABEL: define{{.*}} void @_ZN5test44testEv() // CHECK4: call void @_ZN5test41CC1Ev(ptr // CHECK4: %[[VTABLE:.*]] = load ptr addrspace(1), ptr %{{.*}} -// CHECK4: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test41CE, i32 0, inrange i32 0, i32 4) +// CHECK4: %[[CMP:.*]] = icmp eq ptr addrspace(1) %[[VTABLE]], getelementptr inbounds inrange(-32, 8) ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test41CE, i32 0, i32 0, i32 4) // CHECK4: call void @llvm.assume(i1 %[[CMP]] // CHECK4: %[[VTABLE2:.*]] = load ptr addrspace(1), ptr %{{.*}} -// CHECK4: %[[CMP2:.*]] = icmp eq ptr addrspace(1) %[[VTABLE2]], getelementptr inbounds ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test41CE, i32 0, inrange i32 0, i32 4) +// CHECK4: %[[CMP2:.*]] = icmp eq ptr addrspace(1) %[[VTABLE2]], getelementptr inbounds inrange(-32, 8) ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5test41CE, i32 0, i32 0, i32 4) // CHECK4: call void @llvm.assume(i1 %[[CMP2]]) // CHECK4-LABEL: {{^}}} diff --git a/clang/test/CodeGenCXX/vtable-assume-load.cpp b/clang/test/CodeGenCXX/vtable-assume-load.cpp index bd9e4fc62520d8477ca71b20394d7e0a0df96c33..6ce07d0db1b15a945f1c8fac87c88e777a91f283 100644 --- a/clang/test/CodeGenCXX/vtable-assume-load.cpp +++ b/clang/test/CodeGenCXX/vtable-assume-load.cpp @@ -27,7 +27,7 @@ void g(A *a) { a->foo(); } // CHECK1-LABEL: define{{.*}} void @_ZN5test14fooAEv() // CHECK1: call void @_ZN5test11AC1Ev(ptr // CHECK1: %[[VTABLE:.*]] = load ptr, ptr %{{.*}} -// CHECK1: %[[CMP:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5test11AE, i32 0, inrange i32 0, i32 2) +// CHECK1: %[[CMP:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5test11AE, i32 0, i32 0, i32 2) // CHECK1: call void @llvm.assume(i1 %[[CMP]]) // CHECK1-LABEL: {{^}}} @@ -39,7 +39,7 @@ void fooA() { // CHECK1-LABEL: define{{.*}} void @_ZN5test14fooBEv() // CHECK1: call void @_ZN5test11BC1Ev(ptr {{[^,]*}} %{{.*}}) // CHECK1: %[[VTABLE:.*]] = load ptr, ptr %{{.*}} -// CHECK1: %[[CMP:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN5test11BE, i32 0, inrange i32 0, i32 2) +// CHECK1: %[[CMP:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN5test11BE, i32 0, i32 0, i32 2) // CHECK1: call void @llvm.assume(i1 %[[CMP]]) // CHECK1-LABEL: {{^}}} @@ -73,12 +73,12 @@ void h(B *b) { b->bar(); } // CHECK2-LABEL: define{{.*}} void @_ZN5test24testEv() // CHECK2: call void @_ZN5test21CC1Ev(ptr // CHECK2: %[[VTABLE:.*]] = load ptr, ptr {{.*}} -// CHECK2: %[[CMP:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds ({ [3 x ptr], [3 x ptr] }, ptr @_ZTVN5test21CE, i32 0, inrange i32 0, i32 2) +// CHECK2: %[[CMP:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr], [3 x ptr] }, ptr @_ZTVN5test21CE, i32 0, i32 0, i32 2) // CHECK2: call void @llvm.assume(i1 %[[CMP]]) // CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr %{{.*}}, i64 8 // CHECK2: %[[VTABLE2:.*]] = load ptr, ptr %[[ADD_PTR]] -// CHECK2: %[[CMP2:.*]] = icmp eq ptr %[[VTABLE2]], getelementptr inbounds ({ [3 x ptr], [3 x ptr] }, ptr @_ZTVN5test21CE, i32 0, inrange i32 1, i32 2) +// CHECK2: %[[CMP2:.*]] = icmp eq ptr %[[VTABLE2]], getelementptr inbounds inrange(-16, 8) ({ [3 x ptr], [3 x ptr] }, ptr @_ZTVN5test21CE, i32 0, i32 1, i32 2) // CHECK2: call void @llvm.assume(i1 %[[CMP2]]) // CHECK2: call void @_ZN5test21gEPNS_1AE( @@ -109,7 +109,7 @@ void g(B *a) { a->foo(); } // CHECK3-LABEL: define{{.*}} void @_ZN5test34testEv() // CHECK3: call void @_ZN5test31CC1Ev(ptr -// CHECK3: %[[CMP:.*]] = icmp eq ptr %{{.*}}, getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTVN5test31CE, i32 0, inrange i32 0, i32 3) +// CHECK3: %[[CMP:.*]] = icmp eq ptr %{{.*}}, getelementptr inbounds inrange(-24, 8) ({ [4 x ptr] }, ptr @_ZTVN5test31CE, i32 0, i32 0, i32 3) // CHECK3: call void @llvm.assume(i1 %[[CMP]]) // CHECK3-LABLEL: } void test() { @@ -138,11 +138,11 @@ void g(C *c) { c->foo(); } // CHECK4-LABEL: define{{.*}} void @_ZN5test44testEv() // CHECK4: call void @_ZN5test41CC1Ev(ptr // CHECK4: %[[VTABLE:.*]] = load ptr, ptr %{{.*}} -// CHECK4: %[[CMP:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTVN5test41CE, i32 0, inrange i32 0, i32 4) +// CHECK4: %[[CMP:.*]] = icmp eq ptr %[[VTABLE]], getelementptr inbounds inrange(-32, 8) ({ [5 x ptr] }, ptr @_ZTVN5test41CE, i32 0, i32 0, i32 4) // CHECK4: call void @llvm.assume(i1 %[[CMP]] // CHECK4: %[[VTABLE2:.*]] = load ptr, ptr %{{.*}} -// CHECK4: %[[CMP2:.*]] = icmp eq ptr %[[VTABLE2]], getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTVN5test41CE, i32 0, inrange i32 0, i32 4) +// CHECK4: %[[CMP2:.*]] = icmp eq ptr %[[VTABLE2]], getelementptr inbounds inrange(-32, 8) ({ [5 x ptr] }, ptr @_ZTVN5test41CE, i32 0, i32 0, i32 4) // CHECK4: call void @llvm.assume(i1 %[[CMP2]]) // CHECK4-LABEL: {{^}}} diff --git a/clang/test/CodeGenCXX/vtable-pointer-initialization-address-space.cpp b/clang/test/CodeGenCXX/vtable-pointer-initialization-address-space.cpp index 247864862fecf817f1d6cd5834d91ff75173f2e4..a3f12f0ebfc87bd237d3f85d007e2e9e31f0168e 100644 --- a/clang/test/CodeGenCXX/vtable-pointer-initialization-address-space.cpp +++ b/clang/test/CodeGenCXX/vtable-pointer-initialization-address-space.cpp @@ -21,13 +21,13 @@ struct A : Base { // CHECK-LABEL: define{{.*}} void @_ZN1AC2Ev(ptr {{[^,]*}} %this) unnamed_addr // CHECK: call void @_ZN4BaseC2Ev( -// CHECK: store ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1A, i32 0, inrange i32 0, i32 2) +// CHECK: store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1A, i32 0, i32 0, i32 2) // CHECK: call void @_ZN5FieldC1Ev( // CHECK: ret void A::A() { } // CHECK-LABEL: define{{.*}} void @_ZN1AD2Ev(ptr {{[^,]*}} %this) unnamed_addr -// CHECK: store ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1A, i32 0, inrange i32 0, i32 2) +// CHECK: store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1A, i32 0, i32 0, i32 2) // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( // CHECK: ret void @@ -49,12 +49,12 @@ void f() { B b; } // CHECK-LABEL: define linkonce_odr void @_ZN1BC2Ev(ptr {{[^,]*}} %this) unnamed_addr // CHECK: call void @_ZN4BaseC2Ev( -// CHECK: store ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, inrange i32 0, i32 2) +// CHECK: store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, i32 0, i32 2) // CHECK: call void @_ZN5FieldC1Ev // CHECK: ret void // CHECK-LABEL: define linkonce_odr void @_ZN1BD2Ev(ptr {{[^,]*}} %this) unnamed_addr -// CHECK: store ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, inrange i32 0, i32 2) +// CHECK: store ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, i32 0, i32 2) // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( // CHECK: ret void diff --git a/clang/test/CodeGenCXX/vtable-pointer-initialization.cpp b/clang/test/CodeGenCXX/vtable-pointer-initialization.cpp index 00eda6233d940bfb91a113bfe9e67c354ca82805..16b180705fa6cb22b989a1dfd57595318928da54 100644 --- a/clang/test/CodeGenCXX/vtable-pointer-initialization.cpp +++ b/clang/test/CodeGenCXX/vtable-pointer-initialization.cpp @@ -21,13 +21,13 @@ struct A : Base { // CHECK-LABEL: define{{.*}} void @_ZN1AC2Ev(ptr {{[^,]*}} %this) unnamed_addr // CHECK: call void @_ZN4BaseC2Ev( -// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, inrange i32 0, i32 2) +// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 2) // CHECK: call void @_ZN5FieldC1Ev( // CHECK: ret void A::A() { } // CHECK-LABEL: define{{.*}} void @_ZN1AD2Ev(ptr {{[^,]*}} %this) unnamed_addr -// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, inrange i32 0, i32 2) +// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 2) // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( // CHECK: ret void @@ -49,12 +49,12 @@ void f() { B b; } // CHECK-LABEL: define linkonce_odr void @_ZN1BC2Ev(ptr {{[^,]*}} %this) unnamed_addr // CHECK: call void @_ZN4BaseC2Ev( -// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, inrange i32 0, i32 2) +// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 2) // CHECK: call void @_ZN5FieldC1Ev // CHECK: ret void // CHECK-LABEL: define linkonce_odr void @_ZN1BD2Ev(ptr {{[^,]*}} %this) unnamed_addr -// CHECK: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, inrange i32 0, i32 2) +// CHECK: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 2) // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( // CHECK: ret void diff --git a/clang/test/CodeGenCXX/vtt-address-space.cpp b/clang/test/CodeGenCXX/vtt-address-space.cpp index e567ae49811a47bddbbbb1bc62ac93d04a1a6e0c..24f4e2a755da0489ecb010890af9967d1a39197c 100644 --- a/clang/test/CodeGenCXX/vtt-address-space.cpp +++ b/clang/test/CodeGenCXX/vtt-address-space.cpp @@ -18,7 +18,7 @@ namespace Test { D d; } -// CHECK: linkonce_odr unnamed_addr addrspace(1) constant [13 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, inrange i32 0, i32 5), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE0_NS_2C1E, i32 0, inrange i32 0, i32 3), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE0_NS_2C1E, i32 0, inrange i32 1, i32 3), ptr addrspace(1) getelementptr inbounds ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE16_NS_2C2E, i32 0, inrange i32 0, i32 6), ptr addrspace(1) getelementptr inbounds ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE16_NS_2C2E, i32 0, inrange i32 0, i32 6), ptr addrspace(1) getelementptr inbounds ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE16_NS_2C2E, i32 0, inrange i32 1, i32 3), ptr addrspace(1) getelementptr inbounds ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE16_NS_2C2E, i32 0, inrange i32 2, i32 3), ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, inrange i32 2, i32 3), ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, inrange i32 1, i32 6), ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, inrange i32 1, i32 6), ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, inrange i32 3, i32 3), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE64_NS_2V2E, i32 0, inrange i32 0, i32 3), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE64_NS_2V2E, i32 0, inrange i32 1, i32 3)], comdat, align 8 +// CHECK: linkonce_odr unnamed_addr addrspace(1) constant [13 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds inrange(-40, 0) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, i32 0, i32 5), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE0_NS_2C1E, i32 0, i32 0, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE0_NS_2C1E, i32 0, i32 1, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-48, 8) ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE16_NS_2C2E, i32 0, i32 0, i32 6), ptr addrspace(1) getelementptr inbounds inrange(-48, 8) ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE16_NS_2C2E, i32 0, i32 0, i32 6), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE16_NS_2C2E, i32 0, i32 1, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE16_NS_2C2E, i32 0, i32 2, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, i32 2, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-48, 8) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, i32 1, i32 6), ptr addrspace(1) getelementptr inbounds inrange(-48, 8) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, i32 1, i32 6), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN4Test1DE, i32 0, i32 3, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE64_NS_2V2E, i32 0, i32 0, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN4Test1DE64_NS_2V2E, i32 0, i32 1, i32 3)], comdat, align 8 // CHECK: call void @_ZN4Test2V2C2Ev(ptr noundef nonnull align 8 dereferenceable(20) %2, ptr addrspace(1) noundef getelementptr inbounds ([13 x ptr addrspace(1)], ptr addrspace(1) @_ZTTN4Test1DE, i64 0, i64 11)) // CHECK: call void @_ZN4Test2C1C2Ev(ptr noundef nonnull align 8 dereferenceable(12) %this1, ptr addrspace(1) noundef getelementptr inbounds ([13 x ptr addrspace(1)], ptr addrspace(1) @_ZTTN4Test1DE, i64 0, i64 1)) // CHECK: call void @_ZN4Test2C2C2Ev(ptr noundef nonnull align 8 dereferenceable(12) %3, ptr addrspace(1) noundef getelementptr inbounds ([13 x ptr addrspace(1)], ptr addrspace(1) @_ZTTN4Test1DE, i64 0, i64 3)) diff --git a/clang/test/CodeGenCXX/vtt-layout-address-space.cpp b/clang/test/CodeGenCXX/vtt-layout-address-space.cpp index 2f80c9ec5f9fe1973cfbcf5235ae1df576f0740f..409efb9be0215efd0078c7fee5314c0c01c2b791 100644 --- a/clang/test/CodeGenCXX/vtt-layout-address-space.cpp +++ b/clang/test/CodeGenCXX/vtt-layout-address-space.cpp @@ -78,12 +78,12 @@ namespace Test6 { } } -// CHECK: @_ZTTN5Test11BE ={{.*}} unnamed_addr addrspace(1) constant [1 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds ({ [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test11BE, i32 0, inrange i32 0, i32 3)] +// CHECK: @_ZTTN5Test11BE ={{.*}} unnamed_addr addrspace(1) constant [1 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test11BE, i32 0, i32 0, i32 3)] // CHECK: @_ZTVN5Test51AE ={{.*}} unnamed_addr addrspace(1) constant { [4 x ptr addrspace(1)] } { [4 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) @_ZTIN5Test51AE, ptr addrspace(1) addrspacecast (ptr @__cxa_pure_virtual to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr @_ZN5Test51A6anchorEv to ptr addrspace(1))] } // CHECK: @_ZTVN5Test61AE ={{.*}} unnamed_addr addrspace(1) constant { [4 x ptr addrspace(1)] } { [4 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) @_ZTIN5Test61AE, ptr addrspace(1) addrspacecast (ptr @__cxa_deleted_virtual to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr @_ZN5Test61A6anchorEv to ptr addrspace(1))] } -// CHECK: @_ZTTN5Test21CE = linkonce_odr unnamed_addr addrspace(1) constant [2 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test21CE, i32 0, inrange i32 0, i32 4), ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test21CE, i32 0, inrange i32 0, i32 4)] -// CHECK: @_ZTTN5Test31DE = linkonce_odr unnamed_addr addrspace(1) constant [13 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, inrange i32 0, i32 5), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE0_NS_2C1E, i32 0, inrange i32 0, i32 3), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE0_NS_2C1E, i32 0, inrange i32 1, i32 3), ptr addrspace(1) getelementptr inbounds ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 0, i32 6), ptr addrspace(1) getelementptr inbounds ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 0, i32 6), ptr addrspace(1) getelementptr inbounds ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 1, i32 3), ptr addrspace(1) getelementptr inbounds ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 2, i32 3), ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, inrange i32 2, i32 3), ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, inrange i32 1, i32 6), ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, inrange i32 1, i32 6), ptr addrspace(1) getelementptr inbounds ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, inrange i32 3, i32 3), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE64_NS_2V2E, i32 0, inrange i32 0, i32 3), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE64_NS_2V2E, i32 0, inrange i32 1, i32 3)] +// CHECK: @_ZTTN5Test21CE = linkonce_odr unnamed_addr addrspace(1) constant [2 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds inrange(-32, 8) ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test21CE, i32 0, i32 0, i32 4), ptr addrspace(1) getelementptr inbounds inrange(-32, 8) ({ [5 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test21CE, i32 0, i32 0, i32 4)] +// CHECK: @_ZTTN5Test31DE = linkonce_odr unnamed_addr addrspace(1) constant [13 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds inrange(-40, 0) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, i32 0, i32 5), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE0_NS_2C1E, i32 0, i32 0, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE0_NS_2C1E, i32 0, i32 1, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-48, 8) ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 0, i32 6), ptr addrspace(1) getelementptr inbounds inrange(-48, 8) ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 0, i32 6), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 1, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [7 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 2, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, i32 2, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-48, 8) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, i32 1, i32 6), ptr addrspace(1) getelementptr inbounds inrange(-48, 8) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, i32 1, i32 6), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [5 x ptr addrspace(1)], [7 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test31DE, i32 0, i32 3, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE64_NS_2V2E, i32 0, i32 0, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test31DE64_NS_2V2E, i32 0, i32 1, i32 3)] // CHECK: @_ZTVN5Test41DE = linkonce_odr unnamed_addr addrspace(1) constant { [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] } { [6 x ptr addrspace(1)] [ptr addrspace(1) inttoptr (i64 72 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 16 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 56 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 40 to ptr addrspace(1)), ptr addrspace(1) null, ptr addrspace(1) @_ZTIN5Test41DE], [8 x ptr addrspace(1)] [ptr addrspace(1) inttoptr (i64 40 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 24 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 56 to ptr addrspace(1)), ptr addrspace(1) null, ptr addrspace(1) null, ptr addrspace(1) inttoptr (i64 -16 to ptr addrspace(1)), ptr addrspace(1) @_ZTIN5Test41DE, ptr addrspace(1) addrspacecast (ptr @_ZN5Test42V31gEv to ptr addrspace(1))], [3 x ptr addrspace(1)] [ptr addrspace(1) inttoptr (i64 16 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 -40 to ptr addrspace(1)), ptr addrspace(1) @_ZTIN5Test41DE], [4 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) inttoptr (i64 -56 to ptr addrspace(1)), ptr addrspace(1) @_ZTIN5Test41DE, ptr addrspace(1) addrspacecast (ptr @_ZN5Test42A21fEv to ptr addrspace(1))], [4 x ptr addrspace(1)] [ptr addrspace(1) inttoptr (i64 -16 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 -32 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 -72 to ptr addrspace(1)), ptr addrspace(1) @_ZTIN5Test41DE] } -// CHECK: @_ZTTN5Test41DE = linkonce_odr unnamed_addr addrspace(1) constant [19 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, inrange i32 0, i32 6), ptr addrspace(1) getelementptr inbounds ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 0, i32 4), ptr addrspace(1) getelementptr inbounds ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 1, i32 3), ptr addrspace(1) getelementptr inbounds ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 2, i32 3), ptr addrspace(1) getelementptr inbounds ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 0, i32 7), ptr addrspace(1) getelementptr inbounds ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 0, i32 7), ptr addrspace(1) getelementptr inbounds ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 1, i32 4), ptr addrspace(1) getelementptr inbounds ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 2, i32 3), ptr addrspace(1) getelementptr inbounds ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 3, i32 3), ptr addrspace(1) getelementptr inbounds ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, inrange i32 2, i32 3), ptr addrspace(1) getelementptr inbounds ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, inrange i32 3, i32 3), ptr addrspace(1) getelementptr inbounds ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, inrange i32 1, i32 7), ptr addrspace(1) getelementptr inbounds ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, inrange i32 1, i32 7), ptr addrspace(1) getelementptr inbounds ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, inrange i32 4, i32 4), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE40_NS_2V1E, i32 0, inrange i32 0, i32 3), ptr addrspace(1) getelementptr inbounds ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE40_NS_2V1E, i32 0, inrange i32 1, i32 3), ptr addrspace(1) getelementptr inbounds ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 0, i32 4), ptr addrspace(1) getelementptr inbounds ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 1, i32 3), ptr addrspace(1) getelementptr inbounds ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 2, i32 3)] +// CHECK: @_ZTTN5Test41DE = linkonce_odr unnamed_addr addrspace(1) constant [19 x ptr addrspace(1)] [ptr addrspace(1) getelementptr inbounds inrange(-48, 0) ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, i32 0, i32 6), ptr addrspace(1) getelementptr inbounds inrange(-32, 0) ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 0, i32 4), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 1, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 2, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-56, 8) ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 0, i32 7), ptr addrspace(1) getelementptr inbounds inrange(-56, 8) ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 0, i32 7), ptr addrspace(1) getelementptr inbounds inrange(-32, 0) ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 1, i32 4), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 2, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [8 x ptr addrspace(1)], [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 3, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, i32 2, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, i32 3, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-56, 8) ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, i32 1, i32 7), ptr addrspace(1) getelementptr inbounds inrange(-56, 8) ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, i32 1, i32 7), ptr addrspace(1) getelementptr inbounds inrange(-32, 0) ({ [6 x ptr addrspace(1)], [8 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTVN5Test41DE, i32 0, i32 4, i32 4), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE40_NS_2V1E, i32 0, i32 0, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE40_NS_2V1E, i32 0, i32 1, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-32, 0) ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 0, i32 4), ptr addrspace(1) getelementptr inbounds inrange(-24, 0) ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 1, i32 3), ptr addrspace(1) getelementptr inbounds inrange(-24, 8) ({ [4 x ptr addrspace(1)], [3 x ptr addrspace(1)], [4 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 2, i32 3)] // CHECK: declare void @__cxa_pure_virtual() unnamed_addr // CHECK: declare void @__cxa_deleted_virtual() unnamed_addr diff --git a/clang/test/CodeGenCXX/vtt-layout.cpp b/clang/test/CodeGenCXX/vtt-layout.cpp index 595c64c6a33bd1ee31ba8007bc31a84814466dbe..573a8de3094a123ca17998070cd85496686107f1 100644 --- a/clang/test/CodeGenCXX/vtt-layout.cpp +++ b/clang/test/CodeGenCXX/vtt-layout.cpp @@ -78,12 +78,12 @@ namespace Test6 { } } -// CHECK: @_ZTTN5Test11BE ={{.*}} unnamed_addr constant [1 x ptr] [ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTVN5Test11BE, i32 0, inrange i32 0, i32 3)] +// CHECK: @_ZTTN5Test11BE ={{.*}} unnamed_addr constant [1 x ptr] [ptr getelementptr inbounds inrange(-24, 8) ({ [4 x ptr] }, ptr @_ZTVN5Test11BE, i32 0, i32 0, i32 3)] // CHECK: @_ZTVN5Test51AE ={{.*}} unnamed_addr constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr @_ZTIN5Test51AE, ptr @__cxa_pure_virtual, ptr @_ZN5Test51A6anchorEv] } // CHECK: @_ZTVN5Test61AE ={{.*}} unnamed_addr constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr @_ZTIN5Test61AE, ptr @__cxa_deleted_virtual, ptr @_ZN5Test61A6anchorEv] } -// CHECK: @_ZTTN5Test21CE = linkonce_odr unnamed_addr constant [2 x ptr] [ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTVN5Test21CE, i32 0, inrange i32 0, i32 4), ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTVN5Test21CE, i32 0, inrange i32 0, i32 4)] -// CHECK: @_ZTTN5Test31DE = linkonce_odr unnamed_addr constant [13 x ptr] [ptr getelementptr inbounds ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, inrange i32 0, i32 5), ptr getelementptr inbounds ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE0_NS_2C1E, i32 0, inrange i32 0, i32 3), ptr getelementptr inbounds ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE0_NS_2C1E, i32 0, inrange i32 1, i32 3), ptr getelementptr inbounds ({ [7 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 0, i32 6), ptr getelementptr inbounds ({ [7 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 0, i32 6), ptr getelementptr inbounds ({ [7 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 1, i32 3), ptr getelementptr inbounds ({ [7 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 2, i32 3), ptr getelementptr inbounds ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, inrange i32 2, i32 3), ptr getelementptr inbounds ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, inrange i32 1, i32 6), ptr getelementptr inbounds ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, inrange i32 1, i32 6), ptr getelementptr inbounds ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, inrange i32 3, i32 3), ptr getelementptr inbounds ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE64_NS_2V2E, i32 0, inrange i32 0, i32 3), ptr getelementptr inbounds ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE64_NS_2V2E, i32 0, inrange i32 1, i32 3)] +// CHECK: @_ZTTN5Test21CE = linkonce_odr unnamed_addr constant [2 x ptr] [ptr getelementptr inbounds inrange(-32, 8) ({ [5 x ptr] }, ptr @_ZTVN5Test21CE, i32 0, i32 0, i32 4), ptr getelementptr inbounds inrange(-32, 8) ({ [5 x ptr] }, ptr @_ZTVN5Test21CE, i32 0, i32 0, i32 4)] +// CHECK: @_ZTTN5Test31DE = linkonce_odr unnamed_addr constant [13 x ptr] [ptr getelementptr inbounds inrange(-40, 0) ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, i32 0, i32 5), ptr getelementptr inbounds inrange(-24, 0) ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE0_NS_2C1E, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE0_NS_2C1E, i32 0, i32 1, i32 3), ptr getelementptr inbounds inrange(-48, 8) ({ [7 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 0, i32 6), ptr getelementptr inbounds inrange(-48, 8) ({ [7 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 0, i32 6), ptr getelementptr inbounds inrange(-24, 0) ({ [7 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 1, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [7 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE16_NS_2C2E, i32 0, i32 2, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, i32 2, i32 3), ptr getelementptr inbounds inrange(-48, 8) ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, i32 1, i32 6), ptr getelementptr inbounds inrange(-48, 8) ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, i32 1, i32 6), ptr getelementptr inbounds inrange(-24, 0) ({ [5 x ptr], [7 x ptr], [4 x ptr], [3 x ptr] }, ptr @_ZTVN5Test31DE, i32 0, i32 3, i32 3), ptr getelementptr inbounds inrange(-24, 0) ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE64_NS_2V2E, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test31DE64_NS_2V2E, i32 0, i32 1, i32 3)] // CHECK: @_ZTVN5Test41DE = linkonce_odr unnamed_addr constant { [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] } { [6 x ptr] [ptr inttoptr (i64 72 to ptr), ptr inttoptr (i64 16 to ptr), ptr inttoptr (i64 56 to ptr), ptr inttoptr (i64 40 to ptr), ptr null, ptr @_ZTIN5Test41DE], [8 x ptr] [ptr inttoptr (i64 40 to ptr), ptr inttoptr (i64 24 to ptr), ptr inttoptr (i64 56 to ptr), ptr null, ptr null, ptr inttoptr (i64 -16 to ptr), ptr @_ZTIN5Test41DE, ptr @_ZN5Test42V31gEv], [3 x ptr] [ptr inttoptr (i64 16 to ptr), ptr inttoptr (i64 -40 to ptr), ptr @_ZTIN5Test41DE], [4 x ptr] [ptr null, ptr inttoptr (i64 -56 to ptr), ptr @_ZTIN5Test41DE, ptr @_ZN5Test42A21fEv], [4 x ptr] [ptr inttoptr (i64 -16 to ptr), ptr inttoptr (i64 -32 to ptr), ptr inttoptr (i64 -72 to ptr), ptr @_ZTIN5Test41DE] } -// CHECK: @_ZTTN5Test41DE = linkonce_odr unnamed_addr constant [19 x ptr] [ptr getelementptr inbounds ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, inrange i32 0, i32 6), ptr getelementptr inbounds ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 0, i32 4), ptr getelementptr inbounds ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 1, i32 3), ptr getelementptr inbounds ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 2, i32 3), ptr getelementptr inbounds ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 0, i32 7), ptr getelementptr inbounds ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 0, i32 7), ptr getelementptr inbounds ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 1, i32 4), ptr getelementptr inbounds ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 2, i32 3), ptr getelementptr inbounds ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 3, i32 3), ptr getelementptr inbounds ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, inrange i32 2, i32 3), ptr getelementptr inbounds ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, inrange i32 3, i32 3), ptr getelementptr inbounds ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, inrange i32 1, i32 7), ptr getelementptr inbounds ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, inrange i32 1, i32 7), ptr getelementptr inbounds ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, inrange i32 4, i32 4), ptr getelementptr inbounds ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE40_NS_2V1E, i32 0, inrange i32 0, i32 3), ptr getelementptr inbounds ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE40_NS_2V1E, i32 0, inrange i32 1, i32 3), ptr getelementptr inbounds ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 0, i32 4), ptr getelementptr inbounds ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 1, i32 3), ptr getelementptr inbounds ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 2, i32 3)] +// CHECK: @_ZTTN5Test41DE = linkonce_odr unnamed_addr constant [19 x ptr] [ptr getelementptr inbounds inrange(-48, 0) ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, i32 0, i32 6), ptr getelementptr inbounds inrange(-32, 0) ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 0, i32 4), ptr getelementptr inbounds inrange(-24, 0) ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 1, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE0_NS_2C1E, i32 0, i32 2, i32 3), ptr getelementptr inbounds inrange(-56, 8) ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 0, i32 7), ptr getelementptr inbounds inrange(-56, 8) ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 0, i32 7), ptr getelementptr inbounds inrange(-32, 0) ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 1, i32 4), ptr getelementptr inbounds inrange(-24, 0) ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 2, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [8 x ptr], [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE16_NS_2C2E, i32 0, i32 3, i32 3), ptr getelementptr inbounds inrange(-24, 0) ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, i32 2, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, i32 3, i32 3), ptr getelementptr inbounds inrange(-56, 8) ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, i32 1, i32 7), ptr getelementptr inbounds inrange(-56, 8) ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, i32 1, i32 7), ptr getelementptr inbounds inrange(-32, 0) ({ [6 x ptr], [8 x ptr], [3 x ptr], [4 x ptr], [4 x ptr] }, ptr @_ZTVN5Test41DE, i32 0, i32 4, i32 4), ptr getelementptr inbounds inrange(-24, 0) ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE40_NS_2V1E, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE40_NS_2V1E, i32 0, i32 1, i32 3), ptr getelementptr inbounds inrange(-32, 0) ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 0, i32 4), ptr getelementptr inbounds inrange(-24, 0) ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 1, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [4 x ptr], [3 x ptr], [4 x ptr] }, ptr @_ZTCN5Test41DE72_NS_2V2E, i32 0, i32 2, i32 3)] // CHECK: declare void @__cxa_pure_virtual() unnamed_addr // CHECK: declare void @__cxa_deleted_virtual() unnamed_addr diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..985a0cc41a14106f31af840f0e325343a03bfa08 --- /dev/null +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -0,0 +1,67 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s + +typedef struct { struct {} a; } empty; + +// CHECK-LABEL: @_Z17empty_record_testiz( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1 +// CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_EMPTY]], align 1 +// CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) +// CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[RETVAL]], ptr align 1 [[TMP]], i64 1, i1 false) +// CHECK-NEXT: ret void +// +empty empty_record_test(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); + return __builtin_va_arg(list, empty); +} + +typedef struct { + struct{} a; + double b; +} s1; + +// CHECK-LABEL: @_Z1fiz( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 +// CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 +// CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 +// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) +// CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 +// CHECK-NEXT: [[FP_OFFSET_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY1]], i32 0, i32 1 +// CHECK-NEXT: [[FP_OFFSET:%.*]] = load i32, ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT: [[FITS_IN_FP:%.*]] = icmp ule i32 [[FP_OFFSET]], 160 +// CHECK-NEXT: br i1 [[FITS_IN_FP]], label [[VAARG_IN_REG:%.*]], label [[VAARG_IN_MEM:%.*]] +// CHECK: vaarg.in_reg: +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 +// CHECK-NEXT: [[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] +// CHECK-NEXT: [[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT: br label [[VAARG_END:%.*]] +// CHECK: vaarg.in_mem: +// CHECK-NEXT: [[OVERFLOW_ARG_AREA_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 2 +// CHECK-NEXT: [[OVERFLOW_ARG_AREA:%.*]] = load ptr, ptr [[OVERFLOW_ARG_AREA_P]], align 8 +// CHECK-NEXT: [[OVERFLOW_ARG_AREA_NEXT:%.*]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i32 16 +// CHECK-NEXT: store ptr [[OVERFLOW_ARG_AREA_NEXT]], ptr [[OVERFLOW_ARG_AREA_P]], align 8 +// CHECK-NEXT: br label [[VAARG_END]] +// CHECK: vaarg.end: +// CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[TMP1]], [[VAARG_IN_REG]] ], [ [[OVERFLOW_ARG_AREA]], [[VAARG_IN_MEM]] ] +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[VAARG_ADDR]], i64 16, i1 false) +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[RETVAL]], i64 8 +// CHECK-NEXT: [[TMP4:%.*]] = load double, ptr [[TMP3]], align 8 +// CHECK-NEXT: ret double [[TMP4]] +// +s1 f(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); + return __builtin_va_arg(list, s1); +} diff --git a/clang/test/CodeGenCoroutines/coro-symmetric-transfer-04.cpp b/clang/test/CodeGenCoroutines/coro-symmetric-transfer-04.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cf9170d7e711058475845862c67528310bba2d20 --- /dev/null +++ b/clang/test/CodeGenCoroutines/coro-symmetric-transfer-04.cpp @@ -0,0 +1,66 @@ +// This tests that the symmetric transfer at the final suspend point could happen successfully. +// Based on https://github.com/llvm/llvm-project/pull/85271#issuecomment-2007554532 +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -O2 -emit-llvm %s -o - | FileCheck %s + +#include "Inputs/coroutine.h" + +struct Task { + struct promise_type { + struct FinalAwaiter { + bool await_ready() const noexcept { return false; } + template <typename PromiseType> + std::coroutine_handle<> await_suspend(std::coroutine_handle<PromiseType> h) noexcept { + return h.promise().continuation; + } + void await_resume() noexcept {} + }; + Task get_return_object() noexcept { + return std::coroutine_handle<promise_type>::from_promise(*this); + } + std::suspend_always initial_suspend() noexcept { return {}; } + FinalAwaiter final_suspend() noexcept { return {}; } + void unhandled_exception() noexcept {} + void return_value(int x) noexcept { + _value = x; + } + std::coroutine_handle<> continuation; + int _value; + }; + + Task(std::coroutine_handle<promise_type> handle) : handle(handle), stuff(123) {} + + struct Awaiter { + std::coroutine_handle<promise_type> handle; + Awaiter(std::coroutine_handle<promise_type> handle) : handle(handle) {} + bool await_ready() const noexcept { return false; } + std::coroutine_handle<void> await_suspend(std::coroutine_handle<void> continuation) noexcept { + handle.promise().continuation = continuation; + return handle; + } + int await_resume() noexcept { + int ret = handle.promise()._value; + handle.destroy(); + return ret; + } + }; + + auto operator co_await() { + auto handle_ = handle; + handle = nullptr; + return Awaiter(handle_); + } + +private: + std::coroutine_handle<promise_type> handle; + int stuff; +}; + +Task task0() { + co_return 43; +} + +// CHECK-LABEL: define{{.*}} void @_Z5task0v.resume +// This checks we are still in the scope of the current function. +// CHECK-NOT: {{^}}} +// CHECK: musttail call fastcc void +// CHECK-NEXT: ret void diff --git a/clang/test/CodeGenHLSL/ArrayTemporary.hlsl b/clang/test/CodeGenHLSL/ArrayTemporary.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..63a30b61440eb51273a4097a27a62b22c9785bb3 --- /dev/null +++ b/clang/test/CodeGenHLSL/ArrayTemporary.hlsl @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s + +void fn(float x[2]) { } + +// CHECK-LABEL: define void {{.*}}call{{.*}} +// CHECK: [[Arr:%.*]] = alloca [2 x float] +// CHECK: [[Tmp:%.*]] = alloca [2 x float] +// CHECK: call void @llvm.memset.p0.i32(ptr align 4 [[Arr]], i8 0, i32 8, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[Arr]], i32 8, i1 false) +// CHECK: call void {{.*}}fn{{.*}}(ptr noundef byval([2 x float]) align 4 [[Tmp]]) +void call() { + float Arr[2] = {0, 0}; + fn(Arr); +} + +struct Obj { + float V; + int X; +}; + +void fn2(Obj O[4]) { } + +// CHECK-LABEL: define void {{.*}}call2{{.*}} +// CHECK: [[Arr:%.*]] = alloca [4 x %struct.Obj] +// CHECK: [[Tmp:%.*]] = alloca [4 x %struct.Obj] +// CHECK: call void @llvm.memset.p0.i32(ptr align 4 [[Arr]], i8 0, i32 32, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[Arr]], i32 32, i1 false) +// CHECK: call void {{.*}}fn2{{.*}}(ptr noundef byval([4 x %struct.Obj]) align 4 [[Tmp]]) +void call2() { + Obj Arr[4] = {}; + fn2(Arr); +} + + +void fn3(float x[2][2]) { } + +// CHECK-LABEL: define void {{.*}}call3{{.*}} +// CHECK: [[Arr:%.*]] = alloca [2 x [2 x float]] +// CHECK: [[Tmp:%.*]] = alloca [2 x [2 x float]] +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Arr]], ptr align 4 {{.*}}, i32 16, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[Arr]], i32 16, i1 false) +// CHECK: call void {{.*}}fn3{{.*}}(ptr noundef byval([2 x [2 x float]]) align 4 [[Tmp]]) +void call3() { + float Arr[2][2] = {{0, 0}, {1,1}}; + fn3(Arr); +} + +// CHECK-LABEL: define void {{.*}}call4{{.*}}(ptr +// CHECK-SAME: noundef byval([2 x [2 x float]]) align 4 [[Arr:%.*]]) +// CHECK: [[Tmp:%.*]] = alloca [2 x [2 x float]] +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[Arr]], i32 16, i1 false) +// CHECK: call void {{.*}}fn3{{.*}}(ptr noundef byval([2 x [2 x float]]) align 4 [[Tmp]]) + +void call4(float Arr[2][2]) { + fn3(Arr); +} + +// Verify that each template instantiation codegens to a unique and correctly +// mangled function name. + +// CHECK-LABEL: define void {{.*}}template_call{{.*}}(ptr + +// CHECK-SAME: noundef byval([2 x float]) align 4 [[FA2:%[0-9A-Z]+]], +// CHECK-SAME: ptr noundef byval([4 x float]) align 4 [[FA4:%[0-9A-Z]+]], +// CHECK-SAME: ptr noundef byval([3 x i32]) align 4 [[IA3:%[0-9A-Z]+]] + +// CHECK: [[Tmp1:%.*]] = alloca [2 x float] +// CHECK: [[Tmp2:%.*]] = alloca [4 x float] +// CHECK: [[Tmp3:%.*]] = alloca [3 x i32] +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp1]], ptr align 4 [[FA2]], i32 8, i1 false) +// CHECK: call void @"??$template_fn@$$BY01M@@YAXY01M@Z"(ptr noundef byval([2 x float]) align 4 [[Tmp1]]) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp2]], ptr align 4 [[FA4]], i32 16, i1 false) +// CHECK: call void @"??$template_fn@$$BY03M@@YAXY03M@Z"(ptr noundef byval([4 x float]) align 4 [[Tmp2]]) +// CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp3]], ptr align 4 [[IA3]], i32 12, i1 false) +// CHECK: call void @"??$template_fn@$$BY02H@@YAXY02H@Z"(ptr noundef byval([3 x i32]) align 4 [[Tmp3]]) + +template<typename T> +void template_fn(T Val) {} + +void template_call(float FA2[2], float FA4[4], int IA3[3]) { + template_fn(FA2); + template_fn(FA4); + template_fn(IA3); +} + + +// Verify that Array parameter element access correctly codegens. +// CHECK-LABEL: define void {{.*}}element_access{{.*}}(ptr +// CHECK-SAME: noundef byval([2 x float]) align 4 [[FA2:%[0-9A-Z]+]] + +// CHECK: [[Addr:%.*]] = getelementptr inbounds [2 x float], ptr [[FA2]], i32 0, i32 0 +// CHECK: [[Tmp:%.*]] = load float, ptr [[Addr]] +// CHECK: call void @"??$template_fn@M@@YAXM@Z"(float noundef [[Tmp]]) + +// CHECK: [[Idx0:%.*]] = getelementptr inbounds [2 x float], ptr [[FA2]], i32 0, i32 0 +// CHECK: [[Val0:%.*]] = load float, ptr [[Idx0]] +// CHECK: [[Sum:%.*]] = fadd float [[Val0]], 5.000000e+00 +// CHECK: [[Idx1:%.*]] = getelementptr inbounds [2 x float], ptr [[FA2]], i32 0, i32 1 +// CHECK: store float [[Sum]], ptr [[Idx1]] + +void element_access(float FA2[2]) { + template_fn(FA2[0]); + FA2[1] = FA2[0] + 5; +} diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-elementtype.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-elementtype.hlsl index 87002ccd462d3f2c4ed086bcb1d2a7ccbf2e5599..036c9c28ef277908686959f399ad8ee3cddd3af4 100644 --- a/clang/test/CodeGenHLSL/builtins/RWBuffer-elementtype.hlsl +++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-elementtype.hlsl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s RWBuffer<int16_t> BufI16; RWBuffer<uint16_t> BufU16; diff --git a/clang/test/CodeGenHLSL/builtins/bitreverse.hlsl b/clang/test/CodeGenHLSL/builtins/bitreverse.hlsl deleted file mode 100644 index e7609a2b61e25913ae531fd4c6745ae1694324bd..0000000000000000000000000000000000000000 --- a/clang/test/CodeGenHLSL/builtins/bitreverse.hlsl +++ /dev/null @@ -1,155 +0,0 @@ -// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ -// RUN: dxil-pc-shadermodel6.3-library %s -D__HLSL_ENABLE_16_BIT \ -// RUN: -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s - -#ifdef __HLSL_ENABLE_16_BIT -// CHECK: define noundef i16 @ -// CHECK: call i16 @llvm.bitreverse.i16( -int16_t test_bitreverse_short(int16_t p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i16> @ -// CHECK: call <2 x i16> @llvm.bitreverse.v2i16( -int16_t2 test_bitreverse_short2(int16_t2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i16> @ -// CHECK: call <3 x i16> @llvm.bitreverse.v3i16 -int16_t3 test_bitreverse_short3(int16_t3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i16> @ -// CHECK: call <4 x i16> @llvm.bitreverse.v4i16 -int16_t4 test_bitreverse_short4(int16_t4 p0) -{ - return reversebits(p0); -} - -// CHECK: define noundef i16 @ -// CHECK: call i16 @llvm.bitreverse.i16( -uint16_t test_bitreverse_ushort(uint16_t p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i16> @ -// CHECK: call <2 x i16> @llvm.bitreverse.v2i16 -uint16_t2 test_bitreverse_ushort2(uint16_t2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i16> @ -// CHECK: call <3 x i16> @llvm.bitreverse.v3i16 -uint16_t3 test_bitreverse_ushort3(uint16_t3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i16> @ -// CHECK: call <4 x i16> @llvm.bitreverse.v4i16 -uint16_t4 test_bitreverse_ushort4(uint16_t4 p0) -{ - return reversebits(p0); -} -#endif - -// CHECK: define noundef i32 @ -// CHECK: call i32 @llvm.bitreverse.i32( -int test_bitreverse_int(int p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i32> @ -// CHECK: call <2 x i32> @llvm.bitreverse.v2i32 -int2 test_bitreverse_int2(int2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i32> @ -// CHECK: call <3 x i32> @llvm.bitreverse.v3i32 -int3 test_bitreverse_int3(int3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i32> @ -// CHECK: call <4 x i32> @llvm.bitreverse.v4i32 -int4 test_bitreverse_int4(int4 p0) -{ - return reversebits(p0); -} - -// CHECK: define noundef i32 @ -// CHECK: call i32 @llvm.bitreverse.i32( -int test_bitreverse_uint(uint p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i32> @ -// CHECK: call <2 x i32> @llvm.bitreverse.v2i32 -uint2 test_bitreverse_uint2(uint2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i32> @ -// CHECK: call <3 x i32> @llvm.bitreverse.v3i32 -uint3 test_bitreverse_uint3(uint3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i32> @ -// CHECK: call <4 x i32> @llvm.bitreverse.v4i32 -uint4 test_bitreverse_uint4(uint4 p0) -{ - return reversebits(p0); -} - -// CHECK: define noundef i64 @ -// CHECK: call i64 @llvm.bitreverse.i64( -int64_t test_bitreverse_long(int64_t p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i64> @ -// CHECK: call <2 x i64> @llvm.bitreverse.v2i64 -int64_t2 test_bitreverse_long2(int64_t2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i64> @ -// CHECK: call <3 x i64> @llvm.bitreverse.v3i64 -int64_t3 test_bitreverse_long3(int64_t3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i64> @ -// CHECK: call <4 x i64> @llvm.bitreverse.v4i64 -int64_t4 test_bitreverse_long4(int64_t4 p0) -{ - return reversebits(p0); -} - -// CHECK: define noundef i64 @ -// CHECK: call i64 @llvm.bitreverse.i64( -uint64_t test_bitreverse_long(uint64_t p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i64> @ -// CHECK: call <2 x i64> @llvm.bitreverse.v2i64 -uint64_t2 test_bitreverse_long2(uint64_t2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i64> @ -// CHECK: call <3 x i64> @llvm.bitreverse.v3i64 -uint64_t3 test_bitreverse_long3(uint64_t3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i64> @ -// CHECK: call <4 x i64> @llvm.bitreverse.v4i64 -uint64_t4 test_bitreverse_long4(uint64_t4 p0) -{ - return reversebits(p0); -} diff --git a/clang/test/CodeGenHLSL/builtins/ceil.hlsl b/clang/test/CodeGenHLSL/builtins/ceil.hlsl index 06d0d4c2cf546d04557f21a43a24504e3dfb6250..be7725cd4d66c1d1ddb5387a1d2b6173b3c6b1c3 100644 --- a/clang/test/CodeGenHLSL/builtins/ceil.hlsl +++ b/clang/test/CodeGenHLSL/builtins/ceil.hlsl @@ -41,16 +41,3 @@ float3 test_ceil_float3(float3 p0) { return ceil(p0); } // CHECK: define noundef <4 x float> @ // CHECK: call <4 x float> @llvm.ceil.v4f32( float4 test_ceil_float4(float4 p0) { return ceil(p0); } - -// CHECK: define noundef double @ -// CHECK: call double @llvm.ceil.f64( -double test_ceil_double(double p0) { return ceil(p0); } -// CHECK: define noundef <2 x double> @ -// CHECK: call <2 x double> @llvm.ceil.v2f64( -double2 test_ceil_double2(double2 p0) { return ceil(p0); } -// CHECK: define noundef <3 x double> @ -// CHECK: call <3 x double> @llvm.ceil.v3f64( -double3 test_ceil_double3(double3 p0) { return ceil(p0); } -// CHECK: define noundef <4 x double> @ -// CHECK: call <4 x double> @llvm.ceil.v4f64( -double4 test_ceil_double4(double4 p0) { return ceil(p0); } diff --git a/clang/test/CodeGenHLSL/builtins/clamp-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/clamp-builtin.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..e3ef26429e7e40f00d2dc482a521d4f71d5218b8 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/clamp-builtin.hlsl @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK-LABEL: builtin_test_clamp_int4 +// CHECK: %dx.clamp = call <4 x i32> @llvm.dx.clamp.v4i32(<4 x i32> %0, <4 x i32> %1, <4 x i32> %2) +// CHECK: ret <4 x i32> %dx.clamp +int4 builtin_test_clamp_int4(int4 p0, int4 p1, int4 p2) { + return __builtin_hlsl_elementwise_clamp(p0, p1, p2); +} diff --git a/clang/test/CodeGenHLSL/builtins/clamp.hlsl b/clang/test/CodeGenHLSL/builtins/clamp.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..029e48ffe25865fb51a0872b2a7be93375e52a3f --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/clamp.hlsl @@ -0,0 +1,134 @@ +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF + +#ifdef __HLSL_ENABLE_16_BIT +// NATIVE_HALF: define noundef i16 @ +// NATIVE_HALF: call i16 @llvm.dx.clamp.i16( +int16_t test_clamp_short(int16_t p0, int16_t p1) { return clamp(p0, p1,p1); } +// NATIVE_HALF: define noundef <2 x i16> @ +// NATIVE_HALF: call <2 x i16> @llvm.dx.clamp.v2i16( +int16_t2 test_clamp_short2(int16_t2 p0, int16_t2 p1) { return clamp(p0, p1,p1); } +// NATIVE_HALF: define noundef <3 x i16> @ +// NATIVE_HALF: call <3 x i16> @llvm.dx.clamp.v3i16 +int16_t3 test_clamp_short3(int16_t3 p0, int16_t3 p1) { return clamp(p0, p1,p1); } +// NATIVE_HALF: define noundef <4 x i16> @ +// NATIVE_HALF: call <4 x i16> @llvm.dx.clamp.v4i16 +int16_t4 test_clamp_short4(int16_t4 p0, int16_t4 p1) { return clamp(p0, p1,p1); } + +// NATIVE_HALF: define noundef i16 @ +// NATIVE_HALF: call i16 @llvm.dx.uclamp.i16( +uint16_t test_clamp_ushort(uint16_t p0, uint16_t p1) { return clamp(p0, p1,p1); } +// NATIVE_HALF: define noundef <2 x i16> @ +// NATIVE_HALF: call <2 x i16> @llvm.dx.uclamp.v2i16 +uint16_t2 test_clamp_ushort2(uint16_t2 p0, uint16_t2 p1) { return clamp(p0, p1,p1); } +// NATIVE_HALF: define noundef <3 x i16> @ +// NATIVE_HALF: call <3 x i16> @llvm.dx.uclamp.v3i16 +uint16_t3 test_clamp_ushort3(uint16_t3 p0, uint16_t3 p1) { return clamp(p0, p1,p1); } +// NATIVE_HALF: define noundef <4 x i16> @ +// NATIVE_HALF: call <4 x i16> @llvm.dx.uclamp.v4i16 +uint16_t4 test_clamp_ushort4(uint16_t4 p0, uint16_t4 p1) { return clamp(p0, p1,p1); } +#endif + +// CHECK: define noundef i32 @ +// CHECK: call i32 @llvm.dx.clamp.i32( +int test_clamp_int(int p0, int p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <2 x i32> @ +// CHECK: call <2 x i32> @llvm.dx.clamp.v2i32 +int2 test_clamp_int2(int2 p0, int2 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <3 x i32> @ +// CHECK: call <3 x i32> @llvm.dx.clamp.v3i32 +int3 test_clamp_int3(int3 p0, int3 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <4 x i32> @ +// CHECK: call <4 x i32> @llvm.dx.clamp.v4i32 +int4 test_clamp_int4(int4 p0, int4 p1) { return clamp(p0, p1,p1); } + +// CHECK: define noundef i32 @ +// CHECK: call i32 @llvm.dx.uclamp.i32( +int test_clamp_uint(uint p0, uint p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <2 x i32> @ +// CHECK: call <2 x i32> @llvm.dx.uclamp.v2i32 +uint2 test_clamp_uint2(uint2 p0, uint2 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <3 x i32> @ +// CHECK: call <3 x i32> @llvm.dx.uclamp.v3i32 +uint3 test_clamp_uint3(uint3 p0, uint3 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <4 x i32> @ +// CHECK: call <4 x i32> @llvm.dx.uclamp.v4i32 +uint4 test_clamp_uint4(uint4 p0, uint4 p1) { return clamp(p0, p1,p1); } + +// CHECK: define noundef i64 @ +// CHECK: call i64 @llvm.dx.clamp.i64( +int64_t test_clamp_long(int64_t p0, int64_t p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <2 x i64> @ +// CHECK: call <2 x i64> @llvm.dx.clamp.v2i64 +int64_t2 test_clamp_long2(int64_t2 p0, int64_t2 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <3 x i64> @ +// CHECK: call <3 x i64> @llvm.dx.clamp.v3i64 +int64_t3 test_clamp_long3(int64_t3 p0, int64_t3 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <4 x i64> @ +// CHECK: call <4 x i64> @llvm.dx.clamp.v4i64 +int64_t4 test_clamp_long4(int64_t4 p0, int64_t4 p1) { return clamp(p0, p1,p1); } + +// CHECK: define noundef i64 @ +// CHECK: call i64 @llvm.dx.uclamp.i64( +uint64_t test_clamp_long(uint64_t p0, uint64_t p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <2 x i64> @ +// CHECK: call <2 x i64> @llvm.dx.uclamp.v2i64 +uint64_t2 test_clamp_long2(uint64_t2 p0, uint64_t2 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <3 x i64> @ +// CHECK: call <3 x i64> @llvm.dx.uclamp.v3i64 +uint64_t3 test_clamp_long3(uint64_t3 p0, uint64_t3 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <4 x i64> @ +// CHECK: call <4 x i64> @llvm.dx.uclamp.v4i64 +uint64_t4 test_clamp_long4(uint64_t4 p0, uint64_t4 p1) { return clamp(p0, p1,p1); } + +// NATIVE_HALF: define noundef half @ +// NATIVE_HALF: call half @llvm.dx.clamp.f16( +// NO_HALF: define noundef float @"?test_clamp_half +// NO_HALF: call float @llvm.dx.clamp.f32( +half test_clamp_half(half p0, half p1) { return clamp(p0, p1,p1); } +// NATIVE_HALF: define noundef <2 x half> @ +// NATIVE_HALF: call <2 x half> @llvm.dx.clamp.v2f16 +// NO_HALF: define noundef <2 x float> @"?test_clamp_half2 +// NO_HALF: call <2 x float> @llvm.dx.clamp.v2f32( +half2 test_clamp_half2(half2 p0, half2 p1) { return clamp(p0, p1,p1); } +// NATIVE_HALF: define noundef <3 x half> @ +// NATIVE_HALF: call <3 x half> @llvm.dx.clamp.v3f16 +// NO_HALF: define noundef <3 x float> @"?test_clamp_half3 +// NO_HALF: call <3 x float> @llvm.dx.clamp.v3f32( +half3 test_clamp_half3(half3 p0, half3 p1) { return clamp(p0, p1,p1); } +// NATIVE_HALF: define noundef <4 x half> @ +// NATIVE_HALF: call <4 x half> @llvm.dx.clamp.v4f16 +// NO_HALF: define noundef <4 x float> @"?test_clamp_half4 +// NO_HALF: call <4 x float> @llvm.dx.clamp.v4f32( +half4 test_clamp_half4(half4 p0, half4 p1) { return clamp(p0, p1,p1); } + +// CHECK: define noundef float @"?test_clamp_float +// CHECK: call float @llvm.dx.clamp.f32( +float test_clamp_float(float p0, float p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <2 x float> @"?test_clamp_float2 +// CHECK: call <2 x float> @llvm.dx.clamp.v2f32 +float2 test_clamp_float2(float2 p0, float2 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <3 x float> @"?test_clamp_float3 +// CHECK: call <3 x float> @llvm.dx.clamp.v3f32 +float3 test_clamp_float3(float3 p0, float3 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <4 x float> @"?test_clamp_float4 +// CHECK: call <4 x float> @llvm.dx.clamp.v4f32 +float4 test_clamp_float4(float4 p0, float4 p1) { return clamp(p0, p1,p1); } + +// CHECK: define noundef double @ +// CHECK: call double @llvm.dx.clamp.f64( +double test_clamp_double(double p0, double p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <2 x double> @ +// CHECK: call <2 x double> @llvm.dx.clamp.v2f64 +double2 test_clamp_double2(double2 p0, double2 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <3 x double> @ +// CHECK: call <3 x double> @llvm.dx.clamp.v3f64 +double3 test_clamp_double3(double3 p0, double3 p1) { return clamp(p0, p1,p1); } +// CHECK: define noundef <4 x double> @ +// CHECK: call <4 x double> @llvm.dx.clamp.v4f64 +double4 test_clamp_double4(double4 p0, double4 p1) { return clamp(p0, p1,p1); } diff --git a/clang/test/CodeGenHLSL/builtins/dot.hlsl b/clang/test/CodeGenHLSL/builtins/dot.hlsl index c064d118caf3e74d5d4dc77a9b7b473b8363d7f2..307d71cce3cb6dfc1e180926b27d733cc166c6c0 100644 --- a/clang/test/CodeGenHLSL/builtins/dot.hlsl +++ b/clang/test/CodeGenHLSL/builtins/dot.hlsl @@ -11,15 +11,15 @@ // NATIVE_HALF: ret i16 %dx.dot int16_t test_dot_short(int16_t p0, int16_t p1) { return dot(p0, p1); } -// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.dot.v2i16(<2 x i16> %0, <2 x i16> %1) +// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.sdot.v2i16(<2 x i16> %0, <2 x i16> %1) // NATIVE_HALF: ret i16 %dx.dot int16_t test_dot_short2(int16_t2 p0, int16_t2 p1) { return dot(p0, p1); } -// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.dot.v3i16(<3 x i16> %0, <3 x i16> %1) +// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.sdot.v3i16(<3 x i16> %0, <3 x i16> %1) // NATIVE_HALF: ret i16 %dx.dot int16_t test_dot_short3(int16_t3 p0, int16_t3 p1) { return dot(p0, p1); } -// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.dot.v4i16(<4 x i16> %0, <4 x i16> %1) +// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.sdot.v4i16(<4 x i16> %0, <4 x i16> %1) // NATIVE_HALF: ret i16 %dx.dot int16_t test_dot_short4(int16_t4 p0, int16_t4 p1) { return dot(p0, p1); } @@ -27,15 +27,15 @@ int16_t test_dot_short4(int16_t4 p0, int16_t4 p1) { return dot(p0, p1); } // NATIVE_HALF: ret i16 %dx.dot uint16_t test_dot_ushort(uint16_t p0, uint16_t p1) { return dot(p0, p1); } -// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.dot.v2i16(<2 x i16> %0, <2 x i16> %1) +// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.udot.v2i16(<2 x i16> %0, <2 x i16> %1) // NATIVE_HALF: ret i16 %dx.dot uint16_t test_dot_ushort2(uint16_t2 p0, uint16_t2 p1) { return dot(p0, p1); } -// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.dot.v3i16(<3 x i16> %0, <3 x i16> %1) +// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.udot.v3i16(<3 x i16> %0, <3 x i16> %1) // NATIVE_HALF: ret i16 %dx.dot uint16_t test_dot_ushort3(uint16_t3 p0, uint16_t3 p1) { return dot(p0, p1); } -// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.dot.v4i16(<4 x i16> %0, <4 x i16> %1) +// NATIVE_HALF: %dx.dot = call i16 @llvm.dx.udot.v4i16(<4 x i16> %0, <4 x i16> %1) // NATIVE_HALF: ret i16 %dx.dot uint16_t test_dot_ushort4(uint16_t4 p0, uint16_t4 p1) { return dot(p0, p1); } #endif @@ -44,15 +44,15 @@ uint16_t test_dot_ushort4(uint16_t4 p0, uint16_t4 p1) { return dot(p0, p1); } // CHECK: ret i32 %dx.dot int test_dot_int(int p0, int p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call i32 @llvm.dx.dot.v2i32(<2 x i32> %0, <2 x i32> %1) +// CHECK: %dx.dot = call i32 @llvm.dx.sdot.v2i32(<2 x i32> %0, <2 x i32> %1) // CHECK: ret i32 %dx.dot int test_dot_int2(int2 p0, int2 p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call i32 @llvm.dx.dot.v3i32(<3 x i32> %0, <3 x i32> %1) +// CHECK: %dx.dot = call i32 @llvm.dx.sdot.v3i32(<3 x i32> %0, <3 x i32> %1) // CHECK: ret i32 %dx.dot int test_dot_int3(int3 p0, int3 p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call i32 @llvm.dx.dot.v4i32(<4 x i32> %0, <4 x i32> %1) +// CHECK: %dx.dot = call i32 @llvm.dx.sdot.v4i32(<4 x i32> %0, <4 x i32> %1) // CHECK: ret i32 %dx.dot int test_dot_int4(int4 p0, int4 p1) { return dot(p0, p1); } @@ -60,15 +60,15 @@ int test_dot_int4(int4 p0, int4 p1) { return dot(p0, p1); } // CHECK: ret i32 %dx.dot uint test_dot_uint(uint p0, uint p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call i32 @llvm.dx.dot.v2i32(<2 x i32> %0, <2 x i32> %1) +// CHECK: %dx.dot = call i32 @llvm.dx.udot.v2i32(<2 x i32> %0, <2 x i32> %1) // CHECK: ret i32 %dx.dot uint test_dot_uint2(uint2 p0, uint2 p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call i32 @llvm.dx.dot.v3i32(<3 x i32> %0, <3 x i32> %1) +// CHECK: %dx.dot = call i32 @llvm.dx.udot.v3i32(<3 x i32> %0, <3 x i32> %1) // CHECK: ret i32 %dx.dot uint test_dot_uint3(uint3 p0, uint3 p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call i32 @llvm.dx.dot.v4i32(<4 x i32> %0, <4 x i32> %1) +// CHECK: %dx.dot = call i32 @llvm.dx.udot.v4i32(<4 x i32> %0, <4 x i32> %1) // CHECK: ret i32 %dx.dot uint test_dot_uint4(uint4 p0, uint4 p1) { return dot(p0, p1); } @@ -76,15 +76,15 @@ uint test_dot_uint4(uint4 p0, uint4 p1) { return dot(p0, p1); } // CHECK: ret i64 %dx.dot int64_t test_dot_long(int64_t p0, int64_t p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call i64 @llvm.dx.dot.v2i64(<2 x i64> %0, <2 x i64> %1) +// CHECK: %dx.dot = call i64 @llvm.dx.sdot.v2i64(<2 x i64> %0, <2 x i64> %1) // CHECK: ret i64 %dx.dot int64_t test_dot_long2(int64_t2 p0, int64_t2 p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call i64 @llvm.dx.dot.v3i64(<3 x i64> %0, <3 x i64> %1) +// CHECK: %dx.dot = call i64 @llvm.dx.sdot.v3i64(<3 x i64> %0, <3 x i64> %1) // CHECK: ret i64 %dx.dot int64_t test_dot_long3(int64_t3 p0, int64_t3 p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call i64 @llvm.dx.dot.v4i64(<4 x i64> %0, <4 x i64> %1) +// CHECK: %dx.dot = call i64 @llvm.dx.sdot.v4i64(<4 x i64> %0, <4 x i64> %1) // CHECK: ret i64 %dx.dot int64_t test_dot_long4(int64_t4 p0, int64_t4 p1) { return dot(p0, p1); } @@ -92,15 +92,15 @@ int64_t test_dot_long4(int64_t4 p0, int64_t4 p1) { return dot(p0, p1); } // CHECK: ret i64 %dx.dot uint64_t test_dot_ulong(uint64_t p0, uint64_t p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call i64 @llvm.dx.dot.v2i64(<2 x i64> %0, <2 x i64> %1) +// CHECK: %dx.dot = call i64 @llvm.dx.udot.v2i64(<2 x i64> %0, <2 x i64> %1) // CHECK: ret i64 %dx.dot uint64_t test_dot_ulong2(uint64_t2 p0, uint64_t2 p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call i64 @llvm.dx.dot.v3i64(<3 x i64> %0, <3 x i64> %1) +// CHECK: %dx.dot = call i64 @llvm.dx.udot.v3i64(<3 x i64> %0, <3 x i64> %1) // CHECK: ret i64 %dx.dot uint64_t test_dot_ulong3(uint64_t3 p0, uint64_t3 p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call i64 @llvm.dx.dot.v4i64(<4 x i64> %0, <4 x i64> %1) +// CHECK: %dx.dot = call i64 @llvm.dx.udot.v4i64(<4 x i64> %0, <4 x i64> %1) // CHECK: ret i64 %dx.dot uint64_t test_dot_ulong4(uint64_t4 p0, uint64_t4 p1) { return dot(p0, p1); } @@ -110,21 +110,21 @@ uint64_t test_dot_ulong4(uint64_t4 p0, uint64_t4 p1) { return dot(p0, p1); } // NO_HALF: ret float %dx.dot half test_dot_half(half p0, half p1) { return dot(p0, p1); } -// NATIVE_HALF: %dx.dot = call half @llvm.dx.dot.v2f16(<2 x half> %0, <2 x half> %1) +// NATIVE_HALF: %dx.dot = call half @llvm.dx.dot2.v2f16(<2 x half> %0, <2 x half> %1) // NATIVE_HALF: ret half %dx.dot -// NO_HALF: %dx.dot = call float @llvm.dx.dot.v2f32(<2 x float> %0, <2 x float> %1) +// NO_HALF: %dx.dot = call float @llvm.dx.dot2.v2f32(<2 x float> %0, <2 x float> %1) // NO_HALF: ret float %dx.dot half test_dot_half2(half2 p0, half2 p1) { return dot(p0, p1); } -// NATIVE_HALF: %dx.dot = call half @llvm.dx.dot.v3f16(<3 x half> %0, <3 x half> %1) +// NATIVE_HALF: %dx.dot = call half @llvm.dx.dot3.v3f16(<3 x half> %0, <3 x half> %1) // NATIVE_HALF: ret half %dx.dot -// NO_HALF: %dx.dot = call float @llvm.dx.dot.v3f32(<3 x float> %0, <3 x float> %1) +// NO_HALF: %dx.dot = call float @llvm.dx.dot3.v3f32(<3 x float> %0, <3 x float> %1) // NO_HALF: ret float %dx.dot half test_dot_half3(half3 p0, half3 p1) { return dot(p0, p1); } -// NATIVE_HALF: %dx.dot = call half @llvm.dx.dot.v4f16(<4 x half> %0, <4 x half> %1) +// NATIVE_HALF: %dx.dot = call half @llvm.dx.dot4.v4f16(<4 x half> %0, <4 x half> %1) // NATIVE_HALF: ret half %dx.dot -// NO_HALF: %dx.dot = call float @llvm.dx.dot.v4f32(<4 x float> %0, <4 x float> %1) +// NO_HALF: %dx.dot = call float @llvm.dx.dot4.v4f32(<4 x float> %0, <4 x float> %1) // NO_HALF: ret float %dx.dot half test_dot_half4(half4 p0, half4 p1) { return dot(p0, p1); } @@ -132,34 +132,34 @@ half test_dot_half4(half4 p0, half4 p1) { return dot(p0, p1); } // CHECK: ret float %dx.dot float test_dot_float(float p0, float p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call float @llvm.dx.dot.v2f32(<2 x float> %0, <2 x float> %1) +// CHECK: %dx.dot = call float @llvm.dx.dot2.v2f32(<2 x float> %0, <2 x float> %1) // CHECK: ret float %dx.dot float test_dot_float2(float2 p0, float2 p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call float @llvm.dx.dot.v3f32(<3 x float> %0, <3 x float> %1) +// CHECK: %dx.dot = call float @llvm.dx.dot3.v3f32(<3 x float> %0, <3 x float> %1) // CHECK: ret float %dx.dot float test_dot_float3(float3 p0, float3 p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call float @llvm.dx.dot.v4f32(<4 x float> %0, <4 x float> %1) +// CHECK: %dx.dot = call float @llvm.dx.dot4.v4f32(<4 x float> %0, <4 x float> %1) // CHECK: ret float %dx.dot float test_dot_float4(float4 p0, float4 p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call float @llvm.dx.dot.v2f32(<2 x float> %splat.splat, <2 x float> %1) +// CHECK: %dx.dot = call float @llvm.dx.dot2.v2f32(<2 x float> %splat.splat, <2 x float> %1) // CHECK: ret float %dx.dot float test_dot_float2_splat(float p0, float2 p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call float @llvm.dx.dot.v3f32(<3 x float> %splat.splat, <3 x float> %1) +// CHECK: %dx.dot = call float @llvm.dx.dot3.v3f32(<3 x float> %splat.splat, <3 x float> %1) // CHECK: ret float %dx.dot float test_dot_float3_splat(float p0, float3 p1) { return dot(p0, p1); } -// CHECK: %dx.dot = call float @llvm.dx.dot.v4f32(<4 x float> %splat.splat, <4 x float> %1) +// CHECK: %dx.dot = call float @llvm.dx.dot4.v4f32(<4 x float> %splat.splat, <4 x float> %1) // CHECK: ret float %dx.dot float test_dot_float4_splat(float p0, float4 p1) { return dot(p0, p1); } // CHECK: %conv = sitofp i32 %1 to float // CHECK: %splat.splatinsert = insertelement <2 x float> poison, float %conv, i64 0 // CHECK: %splat.splat = shufflevector <2 x float> %splat.splatinsert, <2 x float> poison, <2 x i32> zeroinitializer -// CHECK: %dx.dot = call float @llvm.dx.dot.v2f32(<2 x float> %0, <2 x float> %splat.splat) +// CHECK: %dx.dot = call float @llvm.dx.dot2.v2f32(<2 x float> %0, <2 x float> %splat.splat) // CHECK: ret float %dx.dot float test_builtin_dot_float2_int_splat(float2 p0, int p1) { return dot(p0, p1); @@ -168,7 +168,7 @@ float test_builtin_dot_float2_int_splat(float2 p0, int p1) { // CHECK: %conv = sitofp i32 %1 to float // CHECK: %splat.splatinsert = insertelement <3 x float> poison, float %conv, i64 0 // CHECK: %splat.splat = shufflevector <3 x float> %splat.splatinsert, <3 x float> poison, <3 x i32> zeroinitializer -// CHECK: %dx.dot = call float @llvm.dx.dot.v3f32(<3 x float> %0, <3 x float> %splat.splat) +// CHECK: %dx.dot = call float @llvm.dx.dot3.v3f32(<3 x float> %0, <3 x float> %splat.splat) // CHECK: ret float %dx.dot float test_builtin_dot_float3_int_splat(float3 p0, int p1) { return dot(p0, p1); diff --git a/clang/test/CodeGenHLSL/builtins/floor.hlsl b/clang/test/CodeGenHLSL/builtins/floor.hlsl index d2a2f6e52f1ec3d305173769734310eba1b22d57..07803bfae3be68c839651dd65e54a10212ffc1c2 100644 --- a/clang/test/CodeGenHLSL/builtins/floor.hlsl +++ b/clang/test/CodeGenHLSL/builtins/floor.hlsl @@ -41,16 +41,3 @@ float3 test_floor_float3(float3 p0) { return floor(p0); } // CHECK: define noundef <4 x float> @ // CHECK: call <4 x float> @llvm.floor.v4f32( float4 test_floor_float4(float4 p0) { return floor(p0); } - -// CHECK: define noundef double @ -// CHECK: call double @llvm.floor.f64( -double test_floor_double(double p0) { return floor(p0); } -// CHECK: define noundef <2 x double> @ -// CHECK: call <2 x double> @llvm.floor.v2f64( -double2 test_floor_double2(double2 p0) { return floor(p0); } -// CHECK: define noundef <3 x double> @ -// CHECK: call <3 x double> @llvm.floor.v3f64( -double3 test_floor_double3(double3 p0) { return floor(p0); } -// CHECK: define noundef <4 x double> @ -// CHECK: call <4 x double> @llvm.floor.v4f64( -double4 test_floor_double4(double4 p0) { return floor(p0); } diff --git a/clang/test/CodeGenHLSL/builtins/isinf.hlsl b/clang/test/CodeGenHLSL/builtins/isinf.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..df44fc4a91dfd014d6dc91e8e6aacd3bff5846cf --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/isinf.hlsl @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF + +// CHECK: define noundef i1 @ +// NATIVE_HALF: %dx.isinf = call i1 @llvm.dx.isinf.f16( +// NO_HALF: %dx.isinf = call i1 @llvm.dx.isinf.f32( +// CHECK: ret i1 %dx.isinf +bool test_isinf_half(half p0) { return isinf(p0); } +// CHECK: define noundef <2 x i1> @ +// NATIVE_HALF: %dx.isinf = call <2 x i1> @llvm.dx.isinf.v2f16 +// NO_HALF: %dx.isinf = call <2 x i1> @llvm.dx.isinf.v2f32( +// CHECK: ret <2 x i1> %dx.isinf +bool2 test_isinf_half2(half2 p0) { return isinf(p0); } +// NATIVE_HALF: define noundef <3 x i1> @ +// NATIVE_HALF: %dx.isinf = call <3 x i1> @llvm.dx.isinf.v3f16 +// NO_HALF: %dx.isinf = call <3 x i1> @llvm.dx.isinf.v3f32( +// CHECK: ret <3 x i1> %dx.isinf +bool3 test_isinf_half3(half3 p0) { return isinf(p0); } +// NATIVE_HALF: define noundef <4 x i1> @ +// NATIVE_HALF: %dx.isinf = call <4 x i1> @llvm.dx.isinf.v4f16 +// NO_HALF: %dx.isinf = call <4 x i1> @llvm.dx.isinf.v4f32( +// CHECK: ret <4 x i1> %dx.isinf +bool4 test_isinf_half4(half4 p0) { return isinf(p0); } + +// CHECK: define noundef i1 @ +// CHECK: %dx.isinf = call i1 @llvm.dx.isinf.f32( +// CHECK: ret i1 %dx.isinf +bool test_isinf_float(float p0) { return isinf(p0); } +// CHECK: define noundef <2 x i1> @ +// CHECK: %dx.isinf = call <2 x i1> @llvm.dx.isinf.v2f32 +// CHECK: ret <2 x i1> %dx.isinf +bool2 test_isinf_float2(float2 p0) { return isinf(p0); } +// CHECK: define noundef <3 x i1> @ +// CHECK: %dx.isinf = call <3 x i1> @llvm.dx.isinf.v3f32 +// CHECK: ret <3 x i1> %dx.isinf +bool3 test_isinf_float3(float3 p0) { return isinf(p0); } +// CHECK: define noundef <4 x i1> @ +// CHECK: %dx.isinf = call <4 x i1> @llvm.dx.isinf.v4f32 +// CHECK: ret <4 x i1> %dx.isinf +bool4 test_isinf_float4(float4 p0) { return isinf(p0); } diff --git a/clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl index 1f16dec68212e49051ec86d7bec55220760c5cb9..2fd5a19fc33521641ef04a378b33eef7586f36a6 100644 --- a/clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl +++ b/clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl @@ -1,27 +1,5 @@ // RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -o - | FileCheck %s - - -// CHECK-LABEL: builtin_lerp_half_scalar -// CHECK: %3 = fsub double %conv1, %conv -// CHECK: %4 = fmul double %conv2, %3 -// CHECK: %dx.lerp = fadd double %conv, %4 -// CHECK: %conv3 = fptrunc double %dx.lerp to half -// CHECK: ret half %conv3 -half builtin_lerp_half_scalar (half p0) { - return __builtin_hlsl_lerp ( p0, p0, p0 ); -} - -// CHECK-LABEL: builtin_lerp_float_scalar -// CHECK: %3 = fsub double %conv1, %conv -// CHECK: %4 = fmul double %conv2, %3 -// CHECK: %dx.lerp = fadd double %conv, %4 -// CHECK: %conv3 = fptrunc double %dx.lerp to float -// CHECK: ret float %conv3 -float builtin_lerp_float_scalar ( float p0) { - return __builtin_hlsl_lerp ( p0, p0, p0 ); -} - // CHECK-LABEL: builtin_lerp_half_vector // CHECK: %dx.lerp = call <3 x half> @llvm.dx.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) // CHECK: ret <3 x half> %dx.lerp diff --git a/clang/test/CodeGenHLSL/builtins/lerp.hlsl b/clang/test/CodeGenHLSL/builtins/lerp.hlsl index a6b3d9643d674ca840dcc317223f6d00251a8dc3..49cd04a10115aee13f70700baddee400b6013d62 100644 --- a/clang/test/CodeGenHLSL/builtins/lerp.hlsl +++ b/clang/test/CodeGenHLSL/builtins/lerp.hlsl @@ -6,13 +6,10 @@ // RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ // RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF -// NATIVE_HALF: %3 = fsub half %1, %0 -// NATIVE_HALF: %4 = fmul half %2, %3 -// NATIVE_HALF: %dx.lerp = fadd half %0, %4 + +// NATIVE_HALF: %dx.lerp = call half @llvm.dx.lerp.f16(half %0, half %1, half %2) // NATIVE_HALF: ret half %dx.lerp -// NO_HALF: %3 = fsub float %1, %0 -// NO_HALF: %4 = fmul float %2, %3 -// NO_HALF: %dx.lerp = fadd float %0, %4 +// NO_HALF: %dx.lerp = call float @llvm.dx.lerp.f32(float %0, float %1, float %2) // NO_HALF: ret float %dx.lerp half test_lerp_half(half p0) { return lerp(p0, p0, p0); } @@ -20,37 +17,35 @@ half test_lerp_half(half p0) { return lerp(p0, p0, p0); } // NATIVE_HALF: ret <2 x half> %dx.lerp // NO_HALF: %dx.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) // NO_HALF: ret <2 x float> %dx.lerp -half2 test_lerp_half2(half2 p0, half2 p1) { return lerp(p0, p0, p0); } +half2 test_lerp_half2(half2 p0) { return lerp(p0, p0, p0); } // NATIVE_HALF: %dx.lerp = call <3 x half> @llvm.dx.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2) // NATIVE_HALF: ret <3 x half> %dx.lerp // NO_HALF: %dx.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) // NO_HALF: ret <3 x float> %dx.lerp -half3 test_lerp_half3(half3 p0, half3 p1) { return lerp(p0, p0, p0); } +half3 test_lerp_half3(half3 p0) { return lerp(p0, p0, p0); } // NATIVE_HALF: %dx.lerp = call <4 x half> @llvm.dx.lerp.v4f16(<4 x half> %0, <4 x half> %1, <4 x half> %2) // NATIVE_HALF: ret <4 x half> %dx.lerp // NO_HALF: %dx.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) // NO_HALF: ret <4 x float> %dx.lerp -half4 test_lerp_half4(half4 p0, half4 p1) { return lerp(p0, p0, p0); } +half4 test_lerp_half4(half4 p0) { return lerp(p0, p0, p0); } -// CHECK: %3 = fsub float %1, %0 -// CHECK: %4 = fmul float %2, %3 -// CHECK: %dx.lerp = fadd float %0, %4 +// CHECK: %dx.lerp = call float @llvm.dx.lerp.f32(float %0, float %1, float %2) // CHECK: ret float %dx.lerp -float test_lerp_float(float p0, float p1) { return lerp(p0, p0, p0); } +float test_lerp_float(float p0) { return lerp(p0, p0, p0); } // CHECK: %dx.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2) // CHECK: ret <2 x float> %dx.lerp -float2 test_lerp_float2(float2 p0, float2 p1) { return lerp(p0, p0, p0); } +float2 test_lerp_float2(float2 p0) { return lerp(p0, p0, p0); } // CHECK: %dx.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2) // CHECK: ret <3 x float> %dx.lerp -float3 test_lerp_float3(float3 p0, float3 p1) { return lerp(p0, p0, p0); } +float3 test_lerp_float3(float3 p0) { return lerp(p0, p0, p0); } // CHECK: %dx.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) // CHECK: ret <4 x float> %dx.lerp -float4 test_lerp_float4(float4 p0, float4 p1) { return lerp(p0, p0, p0); } +float4 test_lerp_float4(float4 p0) { return lerp(p0, p0, p0); } // CHECK: %dx.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %splat.splat, <2 x float> %1, <2 x float> %2) // CHECK: ret <2 x float> %dx.lerp diff --git a/clang/test/CodeGenHLSL/builtins/pow.hlsl b/clang/test/CodeGenHLSL/builtins/pow.hlsl index e996ca2f3364101405f0357acea5c5dd184811c7..057cd7215aa5af3f70dc0bce4cd8312a2f84a178 100644 --- a/clang/test/CodeGenHLSL/builtins/pow.hlsl +++ b/clang/test/CodeGenHLSL/builtins/pow.hlsl @@ -39,16 +39,3 @@ float3 test_pow_float3(float3 p0, float3 p1) { return pow(p0, p1); } // CHECK: define noundef <4 x float> @"?test_pow_float4 // CHECK: call <4 x float> @llvm.pow.v4f32 float4 test_pow_float4(float4 p0, float4 p1) { return pow(p0, p1); } - -// CHECK: define noundef double @"?test_pow_double@@YANNN@Z"( -// CHECK: call double @llvm.pow.f64( -double test_pow_double(double p0, double p1) { return pow(p0, p1); } -// CHECK: define noundef <2 x double> @"?test_pow_double2@@YAT?$__vector@N$01@__clang@@T12@0@Z"( -// CHECK: call <2 x double> @llvm.pow.v2f64 -double2 test_pow_double2(double2 p0, double2 p1) { return pow(p0, p1); } -// CHECK: define noundef <3 x double> @"?test_pow_double3@@YAT?$__vector@N$02@__clang@@T12@0@Z"( -// CHECK: call <3 x double> @llvm.pow.v3f64 -double3 test_pow_double3(double3 p0, double3 p1) { return pow(p0, p1); } -// CHECK: define noundef <4 x double> @"?test_pow_double4@@YAT?$__vector@N$03@__clang@@T12@0@Z"( -// CHECK: call <4 x double> @llvm.pow.v4f64 -double4 test_pow_double4(double4 p0, double4 p1) { return pow(p0, p1); } diff --git a/clang/test/CodeGenHLSL/builtins/reversebits.hlsl b/clang/test/CodeGenHLSL/builtins/reversebits.hlsl index 6da7d289f82e8044a57e454f05163fa2a38d4a85..a319417e97a436dcf52f8807c7e7e82816722599 100644 --- a/clang/test/CodeGenHLSL/builtins/reversebits.hlsl +++ b/clang/test/CodeGenHLSL/builtins/reversebits.hlsl @@ -3,31 +3,6 @@ // RUN: -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s #ifdef __HLSL_ENABLE_16_BIT -// CHECK: define noundef i16 @ -// CHECK: call i16 @llvm.bitreverse.i16( -int16_t test_bitreverse_short(int16_t p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i16> @ -// CHECK: call <2 x i16> @llvm.bitreverse.v2i16( -int16_t2 test_bitreverse_short2(int16_t2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i16> @ -// CHECK: call <3 x i16> @llvm.bitreverse.v3i16 -int16_t3 test_bitreverse_short3(int16_t3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i16> @ -// CHECK: call <4 x i16> @llvm.bitreverse.v4i16 -int16_t4 test_bitreverse_short4(int16_t4 p0) -{ - return reversebits(p0); -} - // CHECK: define noundef i16 @ // CHECK: call i16 @llvm.bitreverse.i16( uint16_t test_bitreverse_ushort(uint16_t p0) @@ -54,31 +29,6 @@ uint16_t4 test_bitreverse_ushort4(uint16_t4 p0) } #endif -// CHECK: define noundef i32 @ -// CHECK: call i32 @llvm.bitreverse.i32( -int test_bitreverse_int(int p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i32> @ -// CHECK: call <2 x i32> @llvm.bitreverse.v2i32 -int2 test_bitreverse_int2(int2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i32> @ -// CHECK: call <3 x i32> @llvm.bitreverse.v3i32 -int3 test_bitreverse_int3(int3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i32> @ -// CHECK: call <4 x i32> @llvm.bitreverse.v4i32 -int4 test_bitreverse_int4(int4 p0) -{ - return reversebits(p0); -} - // CHECK: define noundef i32 @ // CHECK: call i32 @llvm.bitreverse.i32( int test_bitreverse_uint(uint p0) @@ -104,31 +54,6 @@ uint4 test_bitreverse_uint4(uint4 p0) return reversebits(p0); } -// CHECK: define noundef i64 @ -// CHECK: call i64 @llvm.bitreverse.i64( -int64_t test_bitreverse_long(int64_t p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <2 x i64> @ -// CHECK: call <2 x i64> @llvm.bitreverse.v2i64 -int64_t2 test_bitreverse_long2(int64_t2 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <3 x i64> @ -// CHECK: call <3 x i64> @llvm.bitreverse.v3i64 -int64_t3 test_bitreverse_long3(int64_t3 p0) -{ - return reversebits(p0); -} -// CHECK: define noundef <4 x i64> @ -// CHECK: call <4 x i64> @llvm.bitreverse.v4i64 -int64_t4 test_bitreverse_long4(int64_t4 p0) -{ - return reversebits(p0); -} - // CHECK: define noundef i64 @ // CHECK: call i64 @llvm.bitreverse.i64( uint64_t test_bitreverse_long(uint64_t p0) diff --git a/clang/test/CodeGenHLSL/builtins/round.hlsl b/clang/test/CodeGenHLSL/builtins/round.hlsl index b9f35bd3712d18a23afc717ba6be821f93a1262d..33d761dbdfbeaecf10ea0bbd5516bdbf7bacbdfd 100644 --- a/clang/test/CodeGenHLSL/builtins/round.hlsl +++ b/clang/test/CodeGenHLSL/builtins/round.hlsl @@ -7,47 +7,47 @@ // RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF // NATIVE_HALF: define noundef half @ -// NATIVE_HALF: %elt.round = call half @llvm.round.f16( -// NATIVE_HALF: ret half %elt.round +// NATIVE_HALF: %elt.roundeven = call half @llvm.roundeven.f16( +// NATIVE_HALF: ret half %elt.roundeven // NO_HALF: define noundef float @"?test_round_half@@YA$halff@$halff@@Z"( -// NO_HALF: %elt.round = call float @llvm.round.f32( -// NO_HALF: ret float %elt.round +// NO_HALF: %elt.roundeven = call float @llvm.roundeven.f32( +// NO_HALF: ret float %elt.roundeven half test_round_half(half p0) { return round(p0); } // NATIVE_HALF: define noundef <2 x half> @ -// NATIVE_HALF: %elt.round = call <2 x half> @llvm.round.v2f16 -// NATIVE_HALF: ret <2 x half> %elt.round +// NATIVE_HALF: %elt.roundeven = call <2 x half> @llvm.roundeven.v2f16 +// NATIVE_HALF: ret <2 x half> %elt.roundeven // NO_HALF: define noundef <2 x float> @ -// NO_HALF: %elt.round = call <2 x float> @llvm.round.v2f32( -// NO_HALF: ret <2 x float> %elt.round +// NO_HALF: %elt.roundeven = call <2 x float> @llvm.roundeven.v2f32( +// NO_HALF: ret <2 x float> %elt.roundeven half2 test_round_half2(half2 p0) { return round(p0); } // NATIVE_HALF: define noundef <3 x half> @ -// NATIVE_HALF: %elt.round = call <3 x half> @llvm.round.v3f16 -// NATIVE_HALF: ret <3 x half> %elt.round +// NATIVE_HALF: %elt.roundeven = call <3 x half> @llvm.roundeven.v3f16 +// NATIVE_HALF: ret <3 x half> %elt.roundeven // NO_HALF: define noundef <3 x float> @ -// NO_HALF: %elt.round = call <3 x float> @llvm.round.v3f32( -// NO_HALF: ret <3 x float> %elt.round +// NO_HALF: %elt.roundeven = call <3 x float> @llvm.roundeven.v3f32( +// NO_HALF: ret <3 x float> %elt.roundeven half3 test_round_half3(half3 p0) { return round(p0); } // NATIVE_HALF: define noundef <4 x half> @ -// NATIVE_HALF: %elt.round = call <4 x half> @llvm.round.v4f16 -// NATIVE_HALF: ret <4 x half> %elt.round +// NATIVE_HALF: %elt.roundeven = call <4 x half> @llvm.roundeven.v4f16 +// NATIVE_HALF: ret <4 x half> %elt.roundeven // NO_HALF: define noundef <4 x float> @ -// NO_HALF: %elt.round = call <4 x float> @llvm.round.v4f32( -// NO_HALF: ret <4 x float> %elt.round +// NO_HALF: %elt.roundeven = call <4 x float> @llvm.roundeven.v4f32( +// NO_HALF: ret <4 x float> %elt.roundeven half4 test_round_half4(half4 p0) { return round(p0); } // CHECK: define noundef float @ -// CHECK: %elt.round = call float @llvm.round.f32( -// CHECK: ret float %elt.round +// CHECK: %elt.roundeven = call float @llvm.roundeven.f32( +// CHECK: ret float %elt.roundeven float test_round_float(float p0) { return round(p0); } // CHECK: define noundef <2 x float> @ -// CHECK: %elt.round = call <2 x float> @llvm.round.v2f32 -// CHECK: ret <2 x float> %elt.round +// CHECK: %elt.roundeven = call <2 x float> @llvm.roundeven.v2f32 +// CHECK: ret <2 x float> %elt.roundeven float2 test_round_float2(float2 p0) { return round(p0); } // CHECK: define noundef <3 x float> @ -// CHECK: %elt.round = call <3 x float> @llvm.round.v3f32 -// CHECK: ret <3 x float> %elt.round +// CHECK: %elt.roundeven = call <3 x float> @llvm.roundeven.v3f32 +// CHECK: ret <3 x float> %elt.roundeven float3 test_round_float3(float3 p0) { return round(p0); } // CHECK: define noundef <4 x float> @ -// CHECK: %elt.round = call <4 x float> @llvm.round.v4f32 -// CHECK: ret <4 x float> %elt.round +// CHECK: %elt.roundeven = call <4 x float> @llvm.roundeven.v4f32 +// CHECK: ret <4 x float> %elt.roundeven float4 test_round_float4(float4 p0) { return round(p0); } diff --git a/clang/test/CodeGenHLSL/builtins/rsqrt.hlsl b/clang/test/CodeGenHLSL/builtins/rsqrt.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..c87a8c404b08e1e6eafaefcc01bbb8f65e9b0381 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/rsqrt.hlsl @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF + +// NATIVE_HALF: define noundef half @ +// NATIVE_HALF: %dx.rsqrt = call half @llvm.dx.rsqrt.f16( +// NATIVE_HALF: ret half %dx.rsqrt +// NO_HALF: define noundef float @"?test_rsqrt_half@@YA$halff@$halff@@Z"( +// NO_HALF: %dx.rsqrt = call float @llvm.dx.rsqrt.f32( +// NO_HALF: ret float %dx.rsqrt +half test_rsqrt_half(half p0) { return rsqrt(p0); } +// NATIVE_HALF: define noundef <2 x half> @ +// NATIVE_HALF: %dx.rsqrt = call <2 x half> @llvm.dx.rsqrt.v2f16 +// NATIVE_HALF: ret <2 x half> %dx.rsqrt +// NO_HALF: define noundef <2 x float> @ +// NO_HALF: %dx.rsqrt = call <2 x float> @llvm.dx.rsqrt.v2f32( +// NO_HALF: ret <2 x float> %dx.rsqrt +half2 test_rsqrt_half2(half2 p0) { return rsqrt(p0); } +// NATIVE_HALF: define noundef <3 x half> @ +// NATIVE_HALF: %dx.rsqrt = call <3 x half> @llvm.dx.rsqrt.v3f16 +// NATIVE_HALF: ret <3 x half> %dx.rsqrt +// NO_HALF: define noundef <3 x float> @ +// NO_HALF: %dx.rsqrt = call <3 x float> @llvm.dx.rsqrt.v3f32( +// NO_HALF: ret <3 x float> %dx.rsqrt +half3 test_rsqrt_half3(half3 p0) { return rsqrt(p0); } +// NATIVE_HALF: define noundef <4 x half> @ +// NATIVE_HALF: %dx.rsqrt = call <4 x half> @llvm.dx.rsqrt.v4f16 +// NATIVE_HALF: ret <4 x half> %dx.rsqrt +// NO_HALF: define noundef <4 x float> @ +// NO_HALF: %dx.rsqrt = call <4 x float> @llvm.dx.rsqrt.v4f32( +// NO_HALF: ret <4 x float> %dx.rsqrt +half4 test_rsqrt_half4(half4 p0) { return rsqrt(p0); } + +// CHECK: define noundef float @ +// CHECK: %dx.rsqrt = call float @llvm.dx.rsqrt.f32( +// CHECK: ret float %dx.rsqrt +float test_rsqrt_float(float p0) { return rsqrt(p0); } +// CHECK: define noundef <2 x float> @ +// CHECK: %dx.rsqrt = call <2 x float> @llvm.dx.rsqrt.v2f32 +// CHECK: ret <2 x float> %dx.rsqrt +float2 test_rsqrt_float2(float2 p0) { return rsqrt(p0); } +// CHECK: define noundef <3 x float> @ +// CHECK: %dx.rsqrt = call <3 x float> @llvm.dx.rsqrt.v3f32 +// CHECK: ret <3 x float> %dx.rsqrt +float3 test_rsqrt_float3(float3 p0) { return rsqrt(p0); } +// CHECK: define noundef <4 x float> @ +// CHECK: %dx.rsqrt = call <4 x float> @llvm.dx.rsqrt.v4f32 +// CHECK: ret <4 x float> %dx.rsqrt +float4 test_rsqrt_float4(float4 p0) { return rsqrt(p0); } diff --git a/clang/test/CodeGenHLSL/builtins/sqrt.hlsl b/clang/test/CodeGenHLSL/builtins/sqrt.hlsl index 2c2a09617cf86ae38ef419677e1f363e6d330294..adbbf69a8e068580ba2f5e84aafca385b43d7ce0 100644 --- a/clang/test/CodeGenHLSL/builtins/sqrt.hlsl +++ b/clang/test/CodeGenHLSL/builtins/sqrt.hlsl @@ -1,29 +1,53 @@ -// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ -// RUN: dxil-pc-shadermodel6.2-library %s -fnative-half-type \ -// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ +// RUN: --check-prefixes=CHECK,NATIVE_HALF +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF -using hlsl::sqrt; +// NATIVE_HALF: define noundef half @ +// NATIVE_HALF: %{{.*}} = call half @llvm.sqrt.f16( +// NATIVE_HALF: ret half %{{.*}} +// NO_HALF: define noundef float @"?test_sqrt_half@@YA$halff@$halff@@Z"( +// NO_HALF: %{{.*}} = call float @llvm.sqrt.f32( +// NO_HALF: ret float %{{.*}} +half test_sqrt_half(half p0) { return sqrt(p0); } +// NATIVE_HALF: define noundef <2 x half> @ +// NATIVE_HALF: %{{.*}} = call <2 x half> @llvm.sqrt.v2f16 +// NATIVE_HALF: ret <2 x half> %{{.*}} +// NO_HALF: define noundef <2 x float> @ +// NO_HALF: %{{.*}} = call <2 x float> @llvm.sqrt.v2f32( +// NO_HALF: ret <2 x float> %{{.*}} +half2 test_sqrt_half2(half2 p0) { return sqrt(p0); } +// NATIVE_HALF: define noundef <3 x half> @ +// NATIVE_HALF: %{{.*}} = call <3 x half> @llvm.sqrt.v3f16 +// NATIVE_HALF: ret <3 x half> %{{.*}} +// NO_HALF: define noundef <3 x float> @ +// NO_HALF: %{{.*}} = call <3 x float> @llvm.sqrt.v3f32( +// NO_HALF: ret <3 x float> %{{.*}} +half3 test_sqrt_half3(half3 p0) { return sqrt(p0); } +// NATIVE_HALF: define noundef <4 x half> @ +// NATIVE_HALF: %{{.*}} = call <4 x half> @llvm.sqrt.v4f16 +// NATIVE_HALF: ret <4 x half> %{{.*}} +// NO_HALF: define noundef <4 x float> @ +// NO_HALF: %{{.*}} = call <4 x float> @llvm.sqrt.v4f32( +// NO_HALF: ret <4 x float> %{{.*}} +half4 test_sqrt_half4(half4 p0) { return sqrt(p0); } -double sqrt_d(double x) -{ - return sqrt(x); -} - -// CHECK: define noundef double @"?sqrt_d@@YANN@Z"( -// CHECK: call double @llvm.sqrt.f64(double %0) - -float sqrt_f(float x) -{ - return sqrt(x); -} - -// CHECK: define noundef float @"?sqrt_f@@YAMM@Z"( -// CHECK: call float @llvm.sqrt.f32(float %0) - -half sqrt_h(half x) -{ - return sqrt(x); -} - -// CHECK: define noundef half @"?sqrt_h@@YA$f16@$f16@@Z"( -// CHECK: call half @llvm.sqrt.f16(half %0) +// CHECK: define noundef float @ +// CHECK: %{{.*}} = call float @llvm.sqrt.f32( +// CHECK: ret float %{{.*}} +float test_sqrt_float(float p0) { return sqrt(p0); } +// CHECK: define noundef <2 x float> @ +// CHECK: %{{.*}} = call <2 x float> @llvm.sqrt.v2f32 +// CHECK: ret <2 x float> %{{.*}} +float2 test_sqrt_float2(float2 p0) { return sqrt(p0); } +// CHECK: define noundef <3 x float> @ +// CHECK: %{{.*}} = call <3 x float> @llvm.sqrt.v3f32 +// CHECK: ret <3 x float> %{{.*}} +float3 test_sqrt_float3(float3 p0) { return sqrt(p0); } +// CHECK: define noundef <4 x float> @ +// CHECK: %{{.*}} = call <4 x float> @llvm.sqrt.v4f32 +// CHECK: ret <4 x float> %{{.*}} +float4 test_sqrt_float4(float4 p0) { return sqrt(p0); } diff --git a/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_do_while.hlsl b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_do_while.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..9481b0d60a27237d2f98d13bbafd0b33b65e3986 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_do_while.hlsl @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK: define spir_func void @main() [[A0:#[0-9]+]] { +void main() { +// CHECK: entry: +// CHECK: %[[CT_ENTRY:[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: br label %[[LABEL_WHILE_COND:.+]] + int cond = 0; + +// CHECK: [[LABEL_WHILE_COND]]: +// CHECK: %[[CT_LOOP:[0-9]+]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %[[CT_ENTRY]]) ] +// CHECK: br label %[[LABEL_WHILE_BODY:.+]] + while (true) { + +// CHECK: [[LABEL_WHILE_BODY]]: +// CHECK: br i1 {{%.+}}, label %[[LABEL_IF_THEN:.+]], label %[[LABEL_IF_END:.+]] + +// CHECK: [[LABEL_IF_THEN]]: +// CHECK: call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %[[CT_LOOP]]) ] +// CHECK: br label %[[LABEL_WHILE_END:.+]] + if (cond == 2) { + uint index = WaveGetLaneIndex(); + break; + } + +// CHECK: [[LABEL_IF_END]]: +// CHECK: br label %[[LABEL_WHILE_COND]] + cond++; + } + +// CHECK: [[LABEL_WHILE_END]]: +// CHECK: ret void +} + +// CHECK-DAG: declare i32 @__hlsl_wave_get_lane_index() [[A1:#[0-9]+]] + +// CHECK-DAG: attributes [[A0]] = {{{.*}}convergent{{.*}}} +// CHECK-DAG: attributes [[A1]] = {{{.*}}convergent{{.*}}} + diff --git a/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..8f52d81091c180ee80d7f95d7f8cf1ce3fb140d7 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK: define spir_func noundef i32 @_Z6test_1v() [[A0:#[0-9]+]] { +// CHECK: %[[CI:[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %[[CI]]) ] +uint test_1() { + return WaveGetLaneIndex(); +} + +// CHECK: declare i32 @__hlsl_wave_get_lane_index() [[A1:#[0-9]+]] + +// CHECK-DAG: attributes [[A0]] = { {{.*}}convergent{{.*}} } +// CHECK-DAG: attributes [[A1]] = { {{.*}}convergent{{.*}} } diff --git a/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_subcall.hlsl b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_subcall.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..6ea80d692cd2444608267aafac7413f80f7fcd56 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/wave_get_lane_index_subcall.hlsl @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ +// RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK: define spir_func noundef i32 @_Z6test_1v() [[A0:#[0-9]+]] { +// CHECK: %[[C1:[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %[[C1]]) ] +uint test_1() { + return WaveGetLaneIndex(); +} + +// CHECK-DAG: declare i32 @__hlsl_wave_get_lane_index() [[A1:#[0-9]+]] + +// CHECK: define spir_func noundef i32 @_Z6test_2v() [[A0]] { +// CHECK: %[[C2:[0-9]+]] = call token @llvm.experimental.convergence.entry() +// CHECK: call spir_func noundef i32 @_Z6test_1v() {{#[0-9]+}} [ "convergencectrl"(token %[[C2]]) ] +uint test_2() { + return test_1(); +} + +// CHECK-DAG: attributes [[A0]] = {{{.*}}convergent{{.*}}} +// CHECK-DAG: attributes [[A1]] = {{{.*}}convergent{{.*}}} diff --git a/clang/test/CodeGenHLSL/convergent-functions.hlsl b/clang/test/CodeGenHLSL/convergent-functions.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..f7c8b642272b1e77d98d2feed6ba8e75ab2f4717 --- /dev/null +++ b/clang/test/CodeGenHLSL/convergent-functions.hlsl @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.4-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s + +void fn() { +}; + +// CHECK: define{{.*| }}void {{.*}}fn{{.*}}() +// CHECK-SAME: #[[Attr:[0-9]+]] +// CHECK: attributes #[[Attr]] = { {{[^}]*}}convergent{{[^}]*}} } diff --git a/clang/test/CodeGenObjC/debug-info-blocks.m b/clang/test/CodeGenObjC/debug-info-blocks.m index 14b29f222fbe8ed31488092380e5e8c350c31929..59171da016da1e248efe05fc7a81732f4beb62d2 100644 --- a/clang/test/CodeGenObjC/debug-info-blocks.m +++ b/clang/test/CodeGenObjC/debug-info-blocks.m @@ -5,8 +5,8 @@ // CHECK: define {{.*}}_block_invoke // CHECK: store ptr %.block_descriptor, ptr %[[ALLOCA:block.addr]], align -// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr %[[ALLOCA]], metadata ![[SELF:[0-9]+]], metadata !{{.*}}) // CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr %d, metadata ![[D:[0-9]+]], metadata !{{.*}}) +// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr %[[ALLOCA]], metadata ![[SELF:[0-9]+]], metadata !{{.*}}) // Test that we do emit scope info for the helper functions, and that the // parameters to these functions are marked as artificial (so the debugger diff --git a/clang/test/CodeGenOpenCL/amdgpu-printf.cl b/clang/test/CodeGenOpenCL/amdgpu-printf.cl index 6c84485b66b4a098fd0df09096efcf94f78c6f33..edf6dbf8657cbe5468998a689537d9aa33d71ad3 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-printf.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-printf.cl @@ -30,14 +30,7 @@ __kernel void test_printf_int(int i) { // CHECK-NEXT: [[S:%.*]] = alloca [4 x i8], align 1, addrspace(5) // CHECK-NEXT: store i32 [[I:%.*]], ptr addrspace(5) [[I_ADDR]], align 4, !tbaa [[TBAA8]] // CHECK-NEXT: call void @llvm.lifetime.start.p5(i64 4, ptr addrspace(5) [[S]]) #[[ATTR5:[0-9]+]] -// CHECK-NEXT: [[LOC0:%.*]] = getelementptr i8, ptr addrspace(5) [[S]], i64 0 -// CHECK-NEXT: store i8 102, ptr addrspace(5) [[LOC0]], align 1 -// CHECK-NEXT: [[LOC1:%.*]] = getelementptr i8, ptr addrspace(5) [[S]], i64 1 -// CHECK-NEXT: store i8 111, ptr addrspace(5) [[LOC1]], align 1 -// CHECK-NEXT: [[LOC2:%.*]] = getelementptr i8, ptr addrspace(5) [[S]], i64 2 -// CHECK-NEXT: store i8 111, ptr addrspace(5) [[LOC2]], align 1 -// CHECK-NEXT: [[LOC3:%.*]] = getelementptr i8, ptr addrspace(5) [[S]], i64 3 -// CHECK-NEXT: store i8 0, ptr addrspace(5) [[LOC3]], align 1 +// CHECK-NEXT: call void @llvm.memcpy.p5.p4.i64(ptr addrspace(5) align 1 [[S]], ptr addrspace(4) align 1 @__const.test_printf_str_int.s, i64 4, i1 false) // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [4 x i8], ptr addrspace(5) [[S]], i64 0, i64 0 // CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr addrspace(5) [[I_ADDR]], align 4, !tbaa [[TBAA8]] // CHECK-NEXT: [[CALL:%.*]] = call i32 (ptr addrspace(4), ...) @printf(ptr addrspace(4) noundef @.str.2, ptr addrspace(5) noundef [[ARRAYDECAY]], i32 noundef [[TMP2]]) #[[ATTR4]] diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx11-err.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx11-err.cl index f7afb7cb97edad0bdd2bda7238d4f95c8b2fcadb..1e78ab283486820572ce9067f3fb9d5f45cf2824 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx11-err.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx11-err.cl @@ -4,23 +4,14 @@ // REQUIRES: amdgpu-registered-target typedef int v2i __attribute__((ext_vector_type(2))); -typedef half v8h __attribute__((ext_vector_type(8))); typedef short v8s __attribute__((ext_vector_type(8))); - -typedef half v4h __attribute__((ext_vector_type(4))); typedef short v4s __attribute__((ext_vector_type(4))); - - -void amdgcn_global_load_tr(global v2i* v2i_inptr, global v8s* v8s_inptr, global v8h* v8h_inptr, - global int* int_inptr, global v4s* v4s_inptr, global v4h* v4h_inptr) +void amdgcn_global_load_tr(global v2i* v2i_inptr, global v8s* v8s_inptr, global int* int_inptr, global v4s* v4s_inptr) { - v2i out_1 = __builtin_amdgcn_global_load_tr_v2i32(v2i_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v2i32' needs target feature gfx12-insts,wavefrontsize32}} - v8s out_2 = __builtin_amdgcn_global_load_tr_v8i16(v8s_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v8i16' needs target feature gfx12-insts,wavefrontsize32}} - v8h out_3 = __builtin_amdgcn_global_load_tr_v8f16(v8h_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v8f16' needs target feature gfx12-insts,wavefrontsize32}} + v2i out_1 = __builtin_amdgcn_global_load_tr_b64_v2i32(v2i_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b64_v2i32' needs target feature gfx12-insts,wavefrontsize32}} + v8s out_2 = __builtin_amdgcn_global_load_tr_b128_v8i16(v8s_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v8i16' needs target feature gfx12-insts,wavefrontsize32}} - int out_4 = __builtin_amdgcn_global_load_tr_i32(int_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_i32' needs target feature gfx12-insts,wavefrontsize64}} - v4s out_5 = __builtin_amdgcn_global_load_tr_v4i16(v4s_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v4i16' needs target feature gfx12-insts,wavefrontsize64}} - v4h out_6 = __builtin_amdgcn_global_load_tr_v4f16(v4h_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v4f16' needs target feature gfx12-insts,wavefrontsize64}} + int out_3 = __builtin_amdgcn_global_load_tr_b64_i32(int_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b64_i32' needs target feature gfx12-insts,wavefrontsize64}} + v4s out_4 = __builtin_amdgcn_global_load_tr_b128_v4i16(v4s_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v4i16' needs target feature gfx12-insts,wavefrontsize64}} } - diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx12-w32-err.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx12-w32-err.cl index 04ac0a66db7ce74d0e52f41ac079102aacc12577..1acc4cd7adc9609575b528bc77cfe6378a40aa78 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx12-w32-err.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx12-w32-err.cl @@ -3,13 +3,10 @@ // REQUIRES: amdgpu-registered-target -typedef half v4h __attribute__((ext_vector_type(4))); typedef short v4s __attribute__((ext_vector_type(4))); -void amdgcn_global_load_tr(global int* int_inptr, global v4s* v4s_inptr, global v4h* v4h_inptr) +void amdgcn_global_load_tr(global int* int_inptr, global v4s* v4s_inptr) { - int out_4 = __builtin_amdgcn_global_load_tr_i32(int_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_i32' needs target feature gfx12-insts,wavefrontsize64}} - v4s out_5 = __builtin_amdgcn_global_load_tr_v4i16(v4s_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v4i16' needs target feature gfx12-insts,wavefrontsize64}} - v4h out_6 = __builtin_amdgcn_global_load_tr_v4f16(v4h_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v4f16' needs target feature gfx12-insts,wavefrontsize64}} + int out_1 = __builtin_amdgcn_global_load_tr_b64_i32(int_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b64_i32' needs target feature gfx12-insts,wavefrontsize64}} + v4s out_2 = __builtin_amdgcn_global_load_tr_b128_v4i16(v4s_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v4i16' needs target feature gfx12-insts,wavefrontsize64}} } - diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx12-w64-err.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx12-w64-err.cl index 113b54b853a9f48e3628bd4cdfa627536cf7c9ba..96b0e4c3993ab6ccc644692e28cf61387d607f48 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx12-w64-err.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-gfx12-w64-err.cl @@ -4,13 +4,10 @@ // REQUIRES: amdgpu-registered-target typedef int v2i __attribute__((ext_vector_type(2))); -typedef half v8h __attribute__((ext_vector_type(8))); typedef short v8s __attribute__((ext_vector_type(8))); -void amdgcn_global_load_tr(global v2i* v2i_inptr, global v8s* v8s_inptr, global v8h* v8h_inptr) +void amdgcn_global_load_tr(global v2i* v2i_inptr, global v8s* v8s_inptr) { - v2i out_1 = __builtin_amdgcn_global_load_tr_v2i32(v2i_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v2i32' needs target feature gfx12-insts,wavefrontsize32}} - v8s out_2 = __builtin_amdgcn_global_load_tr_v8i16(v8s_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v8i16' needs target feature gfx12-insts,wavefrontsize32}} - v8h out_3 = __builtin_amdgcn_global_load_tr_v8f16(v8h_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_v8f16' needs target feature gfx12-insts,wavefrontsize32}} + v2i out_1 = __builtin_amdgcn_global_load_tr_b64_v2i32(v2i_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b64_v2i32' needs target feature gfx12-insts,wavefrontsize32}} + v8s out_2 = __builtin_amdgcn_global_load_tr_b128_v8i16(v8s_inptr); // expected-error{{'__builtin_amdgcn_global_load_tr_b128_v8i16' needs target feature gfx12-insts,wavefrontsize32}} } - diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w32.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w32.cl index b5fcad68a470204fd6504aa589662f1ae30709db..126d7d6fb7b05323cbcf0ef73f2df6d6b254325f 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w32.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w32.cl @@ -3,46 +3,24 @@ // RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1200 -target-feature +wavefrontsize32 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-GFX1200 typedef int v2i __attribute__((ext_vector_type(2))); -typedef half v8h __attribute__((ext_vector_type(8))); typedef short v8s __attribute__((ext_vector_type(8))); -// Wave32 - -// -// amdgcn_global_load_tr -// - -// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_v2i32( +// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_b64_v2i32( // CHECK-GFX1200-NEXT: entry: -// CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call <2 x i32> @llvm.amdgcn.global.load.tr.v2i32(ptr addrspace(1) [[INPTR:%.*]]) +// CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call <2 x i32> @llvm.amdgcn.global.load.tr.b64.v2i32(ptr addrspace(1) [[INPTR:%.*]]) // CHECK-GFX1200-NEXT: ret <2 x i32> [[TMP0]] // -v2i test_amdgcn_global_load_tr_v2i32(global v2i* inptr) +v2i test_amdgcn_global_load_tr_b64_v2i32(global v2i* inptr) { - return __builtin_amdgcn_global_load_tr_v2i32(inptr); + return __builtin_amdgcn_global_load_tr_b64_v2i32(inptr); } -// -// amdgcn_global_load_tr -// - -// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_v8i16( +// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_b128_v8i16( // CHECK-GFX1200-NEXT: entry: -// CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call <8 x i16> @llvm.amdgcn.global.load.tr.v8i16(ptr addrspace(1) [[INPTR:%.*]]) +// CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call <8 x i16> @llvm.amdgcn.global.load.tr.b128.v8i16(ptr addrspace(1) [[INPTR:%.*]]) // CHECK-GFX1200-NEXT: ret <8 x i16> [[TMP0]] // -v8s test_amdgcn_global_load_tr_v8i16(global v8s* inptr) +v8s test_amdgcn_global_load_tr_b128_v8i16(global v8s* inptr) { - return __builtin_amdgcn_global_load_tr_v8i16(inptr); + return __builtin_amdgcn_global_load_tr_b128_v8i16(inptr); } - -// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_v8f16( -// CHECK-GFX1200-NEXT: entry: -// CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call <8 x half> @llvm.amdgcn.global.load.tr.v8f16(ptr addrspace(1) [[INPTR:%.*]]) -// CHECK-GFX1200-NEXT: ret <8 x half> [[TMP0]] -// -v8h test_amdgcn_global_load_tr_v8f16(global v8h* inptr) -{ - return __builtin_amdgcn_global_load_tr_v8f16(inptr); -} - diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w64.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w64.cl index 9c48ac071b4d3fa7e80ee5ab7f12f4462f279013..7c70ccf73ad385e8f3dbc9411e71d7f7c545848f 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w64.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-global-load-tr-w64.cl @@ -2,46 +2,24 @@ // REQUIRES: amdgpu-registered-target // RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1200 -target-feature +wavefrontsize64 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-GFX1200 -typedef half v4h __attribute__((ext_vector_type(4))); typedef short v4s __attribute__((ext_vector_type(4))); -// Wave64 - -// -// amdgcn_global_load_tr -// - -// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_i32( +// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_b64_i32( // CHECK-GFX1200-NEXT: entry: -// CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.amdgcn.global.load.tr.i32(ptr addrspace(1) [[INPTR:%.*]]) +// CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.amdgcn.global.load.tr.b64.i32(ptr addrspace(1) [[INPTR:%.*]]) // CHECK-GFX1200-NEXT: ret i32 [[TMP0]] // -int test_amdgcn_global_load_tr_i32(global int* inptr) +int test_amdgcn_global_load_tr_b64_i32(global int* inptr) { - return __builtin_amdgcn_global_load_tr_i32(inptr); + return __builtin_amdgcn_global_load_tr_b64_i32(inptr); } -// -// amdgcn_global_load_tr -// - -// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_v4i16( +// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_b128_v4i16( // CHECK-GFX1200-NEXT: entry: -// CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call <4 x i16> @llvm.amdgcn.global.load.tr.v4i16(ptr addrspace(1) [[INPTR:%.*]]) +// CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call <4 x i16> @llvm.amdgcn.global.load.tr.b128.v4i16(ptr addrspace(1) [[INPTR:%.*]]) // CHECK-GFX1200-NEXT: ret <4 x i16> [[TMP0]] // -v4s test_amdgcn_global_load_tr_v4i16(global v4s* inptr) +v4s test_amdgcn_global_load_tr_b128_v4i16(global v4s* inptr) { - return __builtin_amdgcn_global_load_tr_v4i16(inptr); + return __builtin_amdgcn_global_load_tr_b128_v4i16(inptr); } - -// CHECK-GFX1200-LABEL: @test_amdgcn_global_load_tr_v4f16( -// CHECK-GFX1200-NEXT: entry: -// CHECK-GFX1200-NEXT: [[TMP0:%.*]] = tail call <4 x half> @llvm.amdgcn.global.load.tr.v4f16(ptr addrspace(1) [[INPTR:%.*]]) -// CHECK-GFX1200-NEXT: ret <4 x half> [[TMP0]] -// -v4h test_amdgcn_global_load_tr_v4f16(global v4h* inptr) -{ - return __builtin_amdgcn_global_load_tr_v4f16(inptr); -} - diff --git a/clang/test/Driver/Inputs/in.so b/clang/test/Driver/Inputs/in.so deleted file mode 100644 index 8b137891791fe96927ad78e64b0aad7bded08bdc..0000000000000000000000000000000000000000 --- a/clang/test/Driver/Inputs/in.so +++ /dev/null @@ -1 +0,0 @@ - diff --git a/clang/test/Driver/Inputs/libomptarget/libomptarget-new-nvptx-sm_35.bc b/clang/test/Driver/Inputs/libomptarget/libomptarget-new-nvptx-sm_35.bc deleted file mode 100644 index 8b137891791fe96927ad78e64b0aad7bded08bdc..0000000000000000000000000000000000000000 --- a/clang/test/Driver/Inputs/libomptarget/libomptarget-new-nvptx-sm_35.bc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/clang/test/Driver/Inputs/libomptarget/libomptarget-new-nvptx-test.bc b/clang/test/Driver/Inputs/libomptarget/libomptarget-new-nvptx-test.bc deleted file mode 100644 index 8b137891791fe96927ad78e64b0aad7bded08bdc..0000000000000000000000000000000000000000 --- a/clang/test/Driver/Inputs/libomptarget/libomptarget-new-nvptx-test.bc +++ /dev/null @@ -1 +0,0 @@ - diff --git a/clang/test/Driver/Inputs/openmp_static_device_link/empty.o b/clang/test/Driver/Inputs/openmp_static_device_link/empty.o deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/clang/test/Driver/Inputs/openmp_static_device_link/lib.bc b/clang/test/Driver/Inputs/openmp_static_device_link/lib.bc deleted file mode 100644 index 1a87fd836dba2c8b03f53733e4782e15996b96b9..0000000000000000000000000000000000000000 Binary files a/clang/test/Driver/Inputs/openmp_static_device_link/lib.bc and /dev/null differ diff --git a/clang/test/Driver/Inputs/openmp_static_device_link/libFatArchive.a b/clang/test/Driver/Inputs/openmp_static_device_link/libFatArchive.a deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/clang/test/Driver/aarch64-mcpu.c b/clang/test/Driver/aarch64-mcpu.c index cacfc691058d13709b22de2bf1ebc9be119236d7..77ba43122b24531e4c01f3cbab3bc8c36180696d 100644 --- a/clang/test/Driver/aarch64-mcpu.c +++ b/clang/test/Driver/aarch64-mcpu.c @@ -56,6 +56,8 @@ // CORTEX-A715: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a715" // RUN: %clang --target=aarch64 -mcpu=cortex-a720 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A720 %s // CORTEX-A720: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a720" +// RUN: %clang --target=aarch64 -mcpu=cortex-a720ae -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A720AE %s +// CORTEX-A720AE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a720ae" // RUN: %clang --target=aarch64 -mcpu=neoverse-e1 -### -c %s 2>&1 | FileCheck -check-prefix=NEOVERSE-E1 %s // NEOVERSE-E1: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "neoverse-e1" // RUN: %clang --target=aarch64 -mcpu=neoverse-v1 -### -c %s 2>&1 | FileCheck -check-prefix=NEOVERSE-V1 %s @@ -70,6 +72,8 @@ // NEOVERSE-512TVB: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "neoverse-512tvb" // RUN: %clang --target=aarch64 -mcpu=cortex-a520 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A520 %s // CORTEX-A520: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a520" +// RUN: %clang --target=aarch64 -mcpu=cortex-a520ae -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A520AE %s +// CORTEX-A520AE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a520ae" // RUN: %clang --target=aarch64 -mcpu=cortex-r82 -### -c %s 2>&1 | FileCheck -check-prefix=CORTEXR82 %s // CORTEXR82: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-r82" diff --git a/clang/test/Driver/aarch64-ptrauth.c b/clang/test/Driver/aarch64-ptrauth.c new file mode 100644 index 0000000000000000000000000000000000000000..1a69b2c6edfb17a93b726eccfbc2890a59c5915e --- /dev/null +++ b/clang/test/Driver/aarch64-ptrauth.c @@ -0,0 +1,5 @@ +// RUN: %clang -### -c --target=aarch64 -fno-ptrauth-intrinsics -fptrauth-intrinsics %s 2>&1 | FileCheck %s --check-prefix=INTRIN +// INTRIN: "-cc1"{{.*}} "-fptrauth-intrinsics" + +// RUN: not %clang -### -c --target=x86_64 -fptrauth-intrinsics %s 2>&1 | FileCheck %s --check-prefix=ERR +// ERR: error: unsupported option '-fptrauth-intrinsics' for target '{{.*}}' diff --git a/clang/test/Driver/aarch64-soft-float-abi.c b/clang/test/Driver/aarch64-soft-float-abi.c new file mode 100644 index 0000000000000000000000000000000000000000..0486d94e66072e28836ae186042cd83dc27049b3 --- /dev/null +++ b/clang/test/Driver/aarch64-soft-float-abi.c @@ -0,0 +1,26 @@ +// REQUIRES: aarch64-registered-target + +// Hard-float, valid +// RUN: %clang --target=aarch64-none-elf -c %s -o /dev/null +// RUN: %clang --target=aarch64-none-elf -mabi=aapcs -c %s -o /dev/null +// RUN: %clang --target=aarch64-none-elf -march=armv8-r -c %s -o /dev/null +// RUN: %clang --target=aarch64-none-elf -march=armv8-r -mabi=aapcs -c %s -o /dev/null +// RUN: %clang --target=aarch64-none-elf -march=armv8-r+fp -mabi=aapcs -c %s -o /dev/null + +// Soft-float, no FP +// RUN: %clang --target=aarch64-none-elf -march=armv8-r+nofp -mabi=aapcs-soft -c %s -o /dev/null +// RUN: %clang --target=aarch64-none-elf -mgeneral-regs-only -mabi=aapcs-soft -c %s -o /dev/null + +// Soft-float, FP hardware: Rejected, to avoid having two incompatible ABIs for common targets. +// RUN: not %clang --target=aarch64-none-elf -mabi=aapcs-soft -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=INVALID-SOFT +// RUN: not %clang --target=aarch64-none-elf -march=armv8-r+fp -mabi=aapcs-soft -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=INVALID-SOFT +// RUN: not %clang --target=aarch64-none-elf -march=armv8-r+nofp+fp -mabi=aapcs-soft -c %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=INVALID-SOFT + +// No FP, hard-float. This is accepted by the driver, but functions which +// require arguments or returns to be passed in FP registers will be rejected +// (tested elsewhere). +// RUN: %clang --target=aarch64-none-elf -march=armv8-r+nofp -c %s -o /dev/null +// RUN: %clang --target=aarch64-none-elf -march=armv8-r+nofp -mabi=aapcs -c %s -o /dev/null +// RUN: %clang --target=aarch64-none-elf -mgeneral-regs-only -mabi=aapcs -c %s -o /dev/null + +// INVALID-SOFT: error: 'aapcs-soft' ABI is not supported with FPU diff --git a/clang/test/Driver/aarch64-sve.c b/clang/test/Driver/aarch64-sve.c index f34b2700deb91c34d1ad0ccd545e618523995d5a..4a33c2e3c8d3677957b4da4131320701e8640823 100644 --- a/clang/test/Driver/aarch64-sve.c +++ b/clang/test/Driver/aarch64-sve.c @@ -6,12 +6,11 @@ // RUN: %clang --target=aarch64 -march=armv8.6a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV8A-NOSVE %s // GENERICV8A-NOSVE-NOT: "-target-feature" "+sve" -// The 32-bit floating point matrix multiply extension is enabled by default -// for armv8.6-a targets (or later) with SVE, and can optionally be enabled for -// any target from armv8.2a onwards (we don't enforce not using it with earlier -// targets). +// The 32-bit floating point matrix multiply extension is an optional feature +// that can be used for any target from armv8.2a and onwards. This can be +// enabled using the `+f32mm` option.`. // RUN: %clang --target=aarch64 -march=armv8.6a -### -c %s 2>&1 | FileCheck -check-prefix=NO-F32MM %s -// RUN: %clang --target=aarch64 -march=armv8.6a+sve -### -c %s 2>&1 | FileCheck -check-prefix=F32MM %s +// RUN: %clang --target=aarch64 -march=armv8.6a+sve+f32mm -### -c %s 2>&1 | FileCheck -check-prefix=F32MM %s // RUN: %clang --target=aarch64 -march=armv8.5a+f32mm -### -c %s 2>&1 | FileCheck -check-prefix=F32MM %s // NO-F32MM-NOT: "-target-feature" "+f32mm" // F32MM: "-target-feature" "+f32mm" diff --git a/clang/test/Driver/apple-kext-mkernel.c b/clang/test/Driver/apple-kext-mkernel.c index f03ed4a09b47d3558fed7312b1ffa108df8cabfc..de905e169c139e4f9b177b4410952b1604ce0fde 100644 --- a/clang/test/Driver/apple-kext-mkernel.c +++ b/clang/test/Driver/apple-kext-mkernel.c @@ -13,8 +13,8 @@ // CHECK-X86-2: "-fno-rtti" // CHECK-X86-2-NOT: "-fno-common" -// RUN: not %clang -target x86_64-apple-darwin11 -arch armv7 -mkernel -mstrict-align -### -fsyntax-only %s 2>&1 | FileCheck --check-prefix=CHECK-ARM %s -// RUN: not %clang -target x86_64-apple-darwin11 -arch armv7 -mkernel -mstrict-align -### -fsyntax-only -fbuiltin -fno-builtin -fcommon -fno-common %s 2>&1 | FileCheck --check-prefix=CHECK-ARM %s +// RUN: %clang --target=x86_64-apple-darwin11 -arch armv7 -mkernel -mstrict-align -### -fsyntax-only %s 2>&1 | FileCheck --check-prefix=CHECK-ARM %s +// RUN: %clang --target=x86_64-apple-darwin11 -arch armv7 -mkernel -mstrict-align -### -fsyntax-only -fbuiltin -fno-builtin -fcommon -fno-common %s 2>&1 | FileCheck --check-prefix=CHECK-ARM %s // CHECK-ARM: "-target-feature" "+long-calls" // CHECK-ARM: "-target-feature" "+strict-align" diff --git a/clang/test/Driver/cl-outputs.c b/clang/test/Driver/cl-outputs.c index 07ff43642a62be0c353b6619bdcdcf1113914104..4d58f0fb548b5793de03e7de76e5deec422f60ee 100644 --- a/clang/test/Driver/cl-outputs.c +++ b/clang/test/Driver/cl-outputs.c @@ -301,5 +301,8 @@ // RUN: %clang_cl -fdebug-compilation-dir=. /Z7 /Foa.obj -### -- %s 2>&1 | FileCheck -check-prefix=RELATIVE_OBJPATH1 %s // RELATIVE_OBJPATH1: "-object-file-name=a.obj" +// RUN: %clang_cl -fdebug-compilation-dir=. /Z7 /Fo:a.obj -### -- %s 2>&1 | FileCheck -check-prefix=RELATIVE_OBJPATH1_COLON %s +// RELATIVE_OBJPATH1_COLON: "-object-file-name=a.obj" + // RUN: %clang_cl -fdebug-compilation-dir=. /Z7 /Fofoo/a.obj -### -- %s 2>&1 | FileCheck -check-prefix=RELATIVE_OBJPATH2 %s // RELATIVE_OBJPATH2: "-object-file-name=foo\\a.obj" diff --git a/clang/test/Driver/clang-g-opts.c b/clang/test/Driver/clang-g-opts.c index b73602a155b00947043731d9678d17d813a7e41d..fdbe0b96420c5193925567f4426a2de6add0ae5f 100644 --- a/clang/test/Driver/clang-g-opts.c +++ b/clang/test/Driver/clang-g-opts.c @@ -42,8 +42,3 @@ // CHECK-WITH-G-STANDALONE: "-debug-info-kind=standalone" // CHECK-WITH-G-STANDALONE: "-dwarf-version=2" - -/// TODO: Special case before R_RISCV_SET_ULEB128 linker support becomes more widely available. -// RUN: %clang -### -S %s -g --target=riscv64-linux-gnu 2>&1 | FileCheck --check-prefix=VERSION4 %s -// RUN: %clang -### -S %s -g --target=riscv64-unknown-elf 2>&1 | FileCheck --check-prefix=VERSION4 %s -// VERSION4: "-dwarf-version=4" diff --git a/clang/test/Driver/clang-offload-bundler-asserts-on.c b/clang/test/Driver/clang-offload-bundler-asserts-on.c index 521c8641ff54686250198b51d556c41e726c655b..eb11d5fbbee4a7df7e2e08b531713b519f42eaaf 100644 --- a/clang/test/Driver/clang-offload-bundler-asserts-on.c +++ b/clang/test/Driver/clang-offload-bundler-asserts-on.c @@ -1,6 +1,6 @@ // REQUIRES: x86-registered-target // REQUIRES: asserts -// UNSUPPORTED: target={{.*}}-darwin{{.*}}, target={{.*}}-aix{{.*}} +// UNSUPPORTED: target={{.*}}-macosx{{.*}}, target={{.*}}-darwin{{.*}}, target={{.*}}-aix{{.*}} // Generate the file we can bundle. // RUN: %clang -O0 -target %itanium_abi_triple %s -c -o %t.o diff --git a/clang/test/Driver/clang-offload-bundler-standardize.c b/clang/test/Driver/clang-offload-bundler-standardize.c index 6a24968c30efd68153c2c0a61e6561573e8d86c1..91dc8947aabb9a1bd83c6024edadb7ce2f2d93d4 100644 --- a/clang/test/Driver/clang-offload-bundler-standardize.c +++ b/clang/test/Driver/clang-offload-bundler-standardize.c @@ -1,6 +1,6 @@ // REQUIRES: x86-registered-target // REQUIRES: asserts -// UNSUPPORTED: target={{.*}}-darwin{{.*}}, target={{.*}}-aix{{.*}} +// UNSUPPORTED: target={{.*}}-macosx{{.*}}, target={{.*}}-darwin{{.*}}, target={{.*}}-aix{{.*}} // REQUIRES: asserts // Generate the file we can bundle. diff --git a/clang/test/Driver/clang-offload-bundler.c b/clang/test/Driver/clang-offload-bundler.c index f3cd2493e052772a75d2e4dd5fbd01d064995554..a56a5424abf88defb63d2c411e52d4449e4a473e 100644 --- a/clang/test/Driver/clang-offload-bundler.c +++ b/clang/test/Driver/clang-offload-bundler.c @@ -1,5 +1,5 @@ // REQUIRES: x86-registered-target -// UNSUPPORTED: target={{.*}}-darwin{{.*}}, target={{.*}}-aix{{.*}} +// UNSUPPORTED: target={{.*}}-macosx{{.*}}, target={{.*}}-darwin{{.*}}, target={{.*}}-aix{{.*}} // // Generate all the types of files we can bundle. diff --git a/clang/test/Driver/compiler-rt-unwind.c b/clang/test/Driver/compiler-rt-unwind.c index 4260dab9302c787ea4766b39932e2a76bf9970e5..7f4e3f22ab19ae7521f35a7898b855d819d0a0ff 100644 --- a/clang/test/Driver/compiler-rt-unwind.c +++ b/clang/test/Driver/compiler-rt-unwind.c @@ -3,7 +3,7 @@ // // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=libgcc --unwindlib=platform \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-GCC %s // RTLIB-GCC: "-lgcc" // RTLIB-GCC-SAME: "--as-needed" @@ -12,7 +12,7 @@ // // RUN: %clangxx -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=libgcc --unwindlib=platform \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-GXX %s // RTLIB-GXX: "-lgcc" // RTLIB-GXX-NOT: "--as-needed" @@ -21,11 +21,11 @@ // // RUN: not %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=libgcc --unwindlib=libunwind \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-GCC-UNWINDLIB-COMPILER-RT %s // RUN: not %clangxx -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=libgcc --unwindlib=libunwind \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-GCC-UNWINDLIB-COMPILER-RT %s // RTLIB-GCC-UNWINDLIB-COMPILER-RT: "-lgcc" // RTLIB-GCC-UNWINDLIB-COMPILER-RT-SAME: "--as-needed" @@ -35,7 +35,7 @@ // RUN: not %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=libgcc --unwindlib=libunwind \ // RUN: -shared-libgcc \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-GCC-SHARED-UNWINDLIB-COMPILER-RT %s // RTLIB-GCC-SHARED-UNWINDLIB-COMPILER-RT: "-l:libunwind.so" // RTLIB-GCC-SHARED-UNWINDLIB-COMPILER-RT-SAME: "-lgcc" @@ -43,24 +43,24 @@ // RUN: not %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=libgcc --unwindlib=libunwind \ // RUN: -static-libgcc \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-GCC-STATIC-UNWINDLIB-COMPILER-RT %s // RTLIB-GCC-STATIC-UNWINDLIB-COMPILER-RT: "-lgcc" // RTLIB-GCC-STATIC-UNWINDLIB-COMPILER-RT-SAME: "-l:libunwind.a" // // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=compiler-rt \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-COMPILER-RT %s // RTLIB-COMPILER-RT: "{{.*}}libclang_rt.builtins.a" // // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=compiler-rt --unwindlib=libunwind \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-COMPILER-RT-UNWINDLIB-COMPILER-RT %s // RUN: %clangxx -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=compiler-rt --unwindlib=libunwind \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-COMPILER-RT-UNWINDLIB-COMPILER-RT %s // RTLIB-COMPILER-RT-UNWINDLIB-COMPILER-RT: "{{.*}}libclang_rt.builtins.a" // RTLIB-COMPILER-RT-UNWINDLIB-COMPILER-RT-SAME: "--as-needed" @@ -69,21 +69,21 @@ // // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=compiler-rt --unwindlib=libgcc \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-COMPILER-RT-UNWINDLIB-GCC %s // RTLIB-COMPILER-RT-UNWINDLIB-GCC: "{{.*}}libclang_rt.builtins.a" // RTLIB-COMPILER-RT-UNWINDLIB-GCC-SAME: "-lgcc_s" // // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=compiler-rt --unwindlib=libgcc \ -// RUN: -static --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -static -resource-dir=%S/Inputs/resource_dir \ // RUN: | FileCheck --check-prefix=RTLIB-COMPILER-RT-UNWINDLIB-GCC-STATIC %s // RTLIB-COMPILER-RT-UNWINDLIB-GCC-STATIC: "{{.*}}libclang_rt.builtins.a" // RTLIB-COMPILER-RT-UNWINDLIB-GCC-STATIC-SAME: "-lgcc_eh" // // RUN: not %clang %s 2> %t.err \ // RUN: --target=x86_64-unknown-linux -rtlib=libgcc --unwindlib=libunwind \ -// RUN: --gcc-toolchain="" -resource-dir=%S/Inputs/resource_dir \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: FileCheck --input-file=%t.err --check-prefix=RTLIB-GCC-UNWINDLIB-COMPILER_RT %s // RTLIB-GCC-UNWINDLIB-COMPILER_RT: "{{[.|\\\n]*}}--rtlib=libgcc requires --unwindlib=libgcc" // @@ -97,7 +97,6 @@ // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-w64-mingw32 -rtlib=compiler-rt --unwindlib=libunwind \ // RUN: -shared-libgcc \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=MINGW-RTLIB-COMPILER-RT-SHARED-UNWINDLIB-COMPILER-RT %s // MINGW-RTLIB-COMPILER-RT-SHARED-UNWINDLIB-COMPILER-RT: "{{.*}}libclang_rt.builtins-x86_64.a" // MINGW-RTLIB-COMPILER-RT-SHARED-UNWINDLIB-COMPILER-RT-SAME: "-l:libunwind.dll.a" @@ -105,18 +104,15 @@ // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-w64-mingw32 -rtlib=compiler-rt --unwindlib=libunwind \ // RUN: -static-libgcc \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=MINGW-RTLIB-COMPILER-RT-STATIC-UNWINDLIB-COMPILER-RT %s // MINGW-RTLIB-COMPILER-RT-STATIC-UNWINDLIB-COMPILER-RT: "{{.*}}libclang_rt.builtins-x86_64.a" // MINGW-RTLIB-COMPILER-RT-STATIC-UNWINDLIB-COMPILER-RT-SAME: "-l:libunwind.a" // // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-w64-mingw32 -rtlib=compiler-rt --unwindlib=libunwind \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=MINGW-RTLIB-COMPILER-RT-UNWINDLIB-COMPILER-RT %s // RUN: %clangxx -### %s 2>&1 \ // RUN: --target=x86_64-w64-mingw32 -rtlib=compiler-rt --unwindlib=libunwind \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=MINGW-RTLIB-COMPILER-RT-UNWINDLIB-COMPILER-RT %s // MINGW-RTLIB-COMPILER-RT-UNWINDLIB-COMPILER-RT: "{{.*}}libclang_rt.builtins-x86_64.a" // MINGW-RTLIB-COMPILER-RT-UNWINDLIB-COMPILER-RT-SAME: "-lunwind" diff --git a/clang/test/Driver/constructors.c b/clang/test/Driver/constructors.c index 1cb3aec840c2d91c47b56d444fd7a7837f92a9df..570b6ec94617f2c97dbf1adc56d3672ff3b24b3b 100644 --- a/clang/test/Driver/constructors.c +++ b/clang/test/Driver/constructors.c @@ -7,58 +7,49 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=i386-unknown-linux \ // RUN: --sysroot=%S/Inputs/resource_dir \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=i386-unknown-linux \ // RUN: --sysroot=%S/Inputs/fake_install_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: -fno-use-init-array \ // RUN: --target=i386-unknown-linux \ // RUN: --sysroot=%S/Inputs/fake_install_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-NO-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: -fno-use-init-array -fuse-init-array \ // RUN: --target=i386-unknown-linux \ // RUN: --sysroot=%S/Inputs/fake_install_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=i386-unknown-linux \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: -fuse-init-array \ // RUN: --target=i386-unknown-linux \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=arm-unknown-linux-androideabi \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=i386-unknown-linux-android \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=aarch64-none-linux-gnu \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ @@ -68,7 +59,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=arm64-none-linux-gnu \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-INIT-ARRAY %s // // RUN: %clang -### %s -fsyntax-only 2>&1 \ diff --git a/clang/test/Driver/cuda-cross-compiling.c b/clang/test/Driver/cuda-cross-compiling.c index 086840accebe7f5623fd322e26927de323fa2b33..a1719a6fbe042b5f3b48bfaa4acc5e56ee69d9c6 100644 --- a/clang/test/Driver/cuda-cross-compiling.c +++ b/clang/test/Driver/cuda-cross-compiling.c @@ -80,11 +80,15 @@ // // RUN: not %clang -target nvptx64-nvidia-cuda %s -### 2>&1 \ // RUN: | FileCheck -check-prefix=MISSING %s +// RUN: not %clang -target nvptx64-nvidia-cuda -march=generic %s -### 2>&1 \ +// RUN: | FileCheck -check-prefix=MISSING %s // MISSING: error: Must pass in an explicit nvptx64 gpu architecture to 'ptxas' // MISSING: error: Must pass in an explicit nvptx64 gpu architecture to 'nvlink' // RUN: %clang -target nvptx64-nvidia-cuda -flto -c %s -### 2>&1 \ // RUN: | FileCheck -check-prefix=GENERIC %s +// RUN: %clang -target nvptx64-nvidia-cuda -march=sm_52 -march=generic -flto -c %s -### 2>&1 \ +// RUN: | FileCheck -check-prefix=GENERIC %s // GENERIC-NOT: -cc1" "-triple" "nvptx64-nvidia-cuda" {{.*}} "-target-cpu" diff --git a/clang/test/Driver/cuda-detect.cu b/clang/test/Driver/cuda-detect.cu index 49e58004e672c3ae79a828b17510e5d99aa6c76d..67af470018ff968e0d5fb7ffbb5508d24d138472 100644 --- a/clang/test/Driver/cuda-detect.cu +++ b/clang/test/Driver/cuda-detect.cu @@ -146,8 +146,8 @@ // Verify that C++ include paths are passed for both host and device frontends. // RUN: %clang -### --target=x86_64-linux-gnu %s \ -// RUN: --stdlib=libstdc++ --sysroot=%S/Inputs/ubuntu_14.04_multiarch_tree2 \ -// RUN: -nogpulib -nogpuinc --gcc-toolchain="" 2>&1 \ +// RUN: --stdlib=libstdc++ --sysroot=%S/Inputs/ubuntu_14.04_multiarch_tree2 \ +// RUN: -nogpulib -nogpuinc 2>&1 \ // RUN: | FileCheck %s --check-prefix CHECK-CXXINCLUDE // Verify that CUDA SDK version is propagated to the CC1 compilations. diff --git a/clang/test/Driver/darwin-ld-reexports.c b/clang/test/Driver/darwin-ld-reexports.c new file mode 100644 index 0000000000000000000000000000000000000000..2e96db49a8a3871902f7dd55a16f4ea2d9d273ce --- /dev/null +++ b/clang/test/Driver/darwin-ld-reexports.c @@ -0,0 +1,21 @@ +// RUN: touch %t.o +// RUN: %clang -target arm64-apple-darwin13 -### \ +// RUN: -reexport_framework Foo -reexport-lBar -reexport_library Baz %t.o 2> %t.log + +// Check older spellings also work. +// RUN: %clang -target arm64-apple-darwin13 -### \ +// RUN: -Xlinker -reexport_framework -Xlinker Forest \ +// RUN: -Xlinker -reexport-lBranch \ +// RUN: -Xlinker -reexport_library -Xlinker Flower %t.o 2>> %t.log +// RUN: FileCheck -check-prefix=LINK_REEXPORT %s < %t.log + +// LINK_REEXPORT: {{ld(.exe)?"}} +// LINK_REEXPORT: "-reexport_framework" "Foo" +// LINK_REEXPORT: "-reexport-lBar" +// LINK_REEXPORT: "-reexport_library" "Baz" +// LINK_REEXPORT: "-reexport_framework" "Forest" +// LINK_REEXPORT: "-reexport-lBranch" +// LINK_REEXPORT: "-reexport_library" "Flower" + +// Make sure arguments are not repeated. +// LINK_REEXPORT-NOT: "-reexport diff --git a/clang/test/Driver/dragonfly.c b/clang/test/Driver/dragonfly.c index 931f23f6f57b5fca95a4c8f208bb4094dba2f230..33c4e4c77eac5ec4bef7ef8d2900d5429329271d 100644 --- a/clang/test/Driver/dragonfly.c +++ b/clang/test/Driver/dragonfly.c @@ -5,7 +5,6 @@ // Check x86_64-unknown-dragonfly, X86_64 // RUN: %clang -### %s 2>&1 --target=x86_64-unknown-dragonfly \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_dragonfly_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X86_64 %s // CHECK-LD-X86_64: "-cc1" "-triple" "x86_64-unknown-dragonfly" diff --git a/clang/test/Driver/env.c b/clang/test/Driver/env.c index 40a42dc9618576ef3f829b87f30cc24e21d51557..3f56c7fdae9022a9eeae3d2251a2c3f0d6990449 100644 --- a/clang/test/Driver/env.c +++ b/clang/test/Driver/env.c @@ -8,13 +8,13 @@ // RUN: %clang %s -### -o %t.o --target=i386-unknown-linux \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: --rtlib=platform --unwindlib=platform -no-pie \ -// RUN: --gcc-toolchain="" 2>&1 | FileCheck --check-prefix=CHECK-LD-32 %s +// RUN: 2>&1 | FileCheck --check-prefix=CHECK-LD-32 %s // // RUN: env -i LC_ALL=C PATH="" LD_LIBRARY_PATH="$LD_LIBRARY_PATH" CLANG_NO_DEFAULT_CONFIG=1 \ // RUN: %clang %s -### -o %t.o --target=i386-unknown-linux \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: --rtlib=platform --unwindlib=platform -no-pie \ -// RUN: --gcc-toolchain="" 2>&1 | FileCheck --check-prefix=CHECK-LD-32 %s +// RUN: 2>&1 | FileCheck --check-prefix=CHECK-LD-32 %s // // CHECK-LD-32-NOT: warning: // CHECK-LD-32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" diff --git a/clang/test/Driver/fat-archive-unbundle-ext.c b/clang/test/Driver/fat-archive-unbundle-ext.c index b409aa6313b1ea6faf1b85745b1a077072aded52..e98b872f0c0c3190feab8b6c001ceb84d57efb13 100644 --- a/clang/test/Driver/fat-archive-unbundle-ext.c +++ b/clang/test/Driver/fat-archive-unbundle-ext.c @@ -1,5 +1,5 @@ // REQUIRES: x86-registered-target -// UNSUPPORTED: target={{.*-windows.*}}, target={{.*-darwin.*}}, target={{.*}}-aix{{.*}} +// UNSUPPORTED: target={{.*-windows.*}}, target={{.*}}-macosx{{.*}}, target={{.*-darwin.*}}, target={{.*}}-aix{{.*}} // Generate dummy fat object // RUN: %clang -O0 -target %itanium_abi_triple %s -c -o %t.host.o diff --git a/clang/test/Driver/fsanitize-signed-integer-overflow.c b/clang/test/Driver/fsanitize-signed-integer-overflow.c new file mode 100644 index 0000000000000000000000000000000000000000..4a9345493b6aa804bd4231b742c20f62e6fb3dfa --- /dev/null +++ b/clang/test/Driver/fsanitize-signed-integer-overflow.c @@ -0,0 +1,28 @@ +/// When -fwrapv (implied by -fno-strict-overflow) is enabled, +/// -fsanitize=undefined does not expand to signed-integer-overflow. +/// -fsanitize=signed-integer-overflow is unaffected by -fwrapv. + +// RUN: %clang -### --target=x86_64-linux -fwrapv -fsanitize=signed-integer-overflow %s 2>&1 | FileCheck %s +// CHECK: -fsanitize=signed-integer-overflow +// CHECK: -fsanitize-recover=signed-integer-overflow + +// RUN: %clang -### --target=x86_64-linux -fno-strict-overflow -fsanitize=undefined %s 2>&1 | FileCheck %s --check-prefix=EXCLUDE +// RUN: %clang -### --target=x86_64-linux -fstrict-overflow -fwrapv -fsanitize=undefined %s 2>&1 | FileCheck %s --check-prefix=EXCLUDE +// EXCLUDE: -fsanitize=alignment,array-bounds, +// EXCLUDE-NOT: signed-integer-overflow, +// EXCLUDE: -fsanitize-recover=alignment,array-bounds, +// EXCLUDE-SAME: signed-integer-overflow + +// RUN: %clang -### --target=x86_64-linux -fwrapv -fsanitize=undefined -fsanitize=signed-integer-overflow %s 2>&1 | FileCheck %s --check-prefix=INCLUDE +// RUN: %clang -### --target=x86_64-linux -fno-strict-overflow -fno-sanitize=signed-integer-overflow -fsanitize=undefined -fsanitize=signed-integer-overflow %s 2>&1 | FileCheck %s --check-prefix=INCLUDE +// INCLUDE: -fsanitize=alignment,array-bounds, +// INCLUDE-SAME: signed-integer-overflow +// INCLUDE: -fsanitize-recover=alignment,array-bounds, +// INCLUDE-SAME: signed-integer-overflow + +/// -fsanitize-trap=undefined expands to signed-integer-overflow regardless of -fwrapv. +// RUN: %clang -### --target=x86_64-linux -fwrapv -fsanitize=undefined -fsanitize=signed-integer-overflow -fsanitize-trap=undefined %s 2>&1 | FileCheck %s --check-prefix=INCLUDE-TRAP +// INCLUDE-TRAP: -fsanitize=alignment,array-bounds, +// INCLUDE-TRAP-SAME: signed-integer-overflow +// INCLUDE-TRAP: -fsanitize-trap=alignment,array-bounds, +// INCLUDE-TRAP-SAME: signed-integer-overflow diff --git a/clang/test/Driver/haiku.c b/clang/test/Driver/haiku.c index 060a56b3c70e562dc516d2d592fb736009d6926f..3f421ab6e81e686878a1010de5c26801d9ecb254 100644 --- a/clang/test/Driver/haiku.c +++ b/clang/test/Driver/haiku.c @@ -39,7 +39,6 @@ // Check x86_64-unknown-haiku, X86_64 // RUN: %clang -### %s 2>&1 --target=x86_64-unknown-haiku \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/haiku_x86_64_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X86_64 %s // CHECK-LD-X86_64: "-cc1" "-triple" "x86_64-unknown-haiku" @@ -63,7 +62,6 @@ // Check the right flags are present with -shared // RUN: %clang -### %s -shared 2>&1 --target=x86_64-unknown-haiku \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/haiku_x86_64_tree \ // RUN: | FileCheck --check-prefix=CHECK-X86_64-SHARED %s // CHECK-X86_64-SHARED: "-cc1" "-triple" "x86_64-unknown-haiku" diff --git a/clang/test/Driver/hexagon-default-build-attributes.s b/clang/test/Driver/hexagon-default-build-attributes.s new file mode 100644 index 0000000000000000000000000000000000000000..58f246c2f805da93f1166f70da16faab2c9e921b --- /dev/null +++ b/clang/test/Driver/hexagon-default-build-attributes.s @@ -0,0 +1,21 @@ +/// Enabled by default for assembly +// RUN: %clang --target=hexagon-unknown-elf -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-ENABLED + +/// Can be forced on or off for assembly. +// RUN: %clang --target=hexagon-unknown-elf -### %s 2>&1 -mno-default-build-attributes \ +// RUN: | FileCheck %s -check-prefix CHECK-DISABLED +// RUN: %clang --target=hexagon-unknown-elf -### %s 2>&1 -mdefault-build-attributes \ +// RUN: | FileCheck %s -check-prefix CHECK-ENABLED + +/// Option ignored C/C++ (since we always emit hardware and ABI build attributes +/// during codegen). +// RUN: %clang --target=hexagon-unknown-elf -### -x c %s -mdefault-build-attributes 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-DISABLED-C +// RUN: %clang --target=hexagon-unknown-elf -### -x c++ %s -mdefault-build-attributes 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-DISABLED-C + +// CHECK-DISABLED-NOT: "-hexagon-add-build-attributes" +// CHECK-DISABLED-C-NOT: "-hexagon-add-build-attributes" +// CHECK-ENABLED: "-hexagon-add-build-attributes" +// CHECK-DISABLED-C: argument unused during compilation: '-mdefault-build-attributes' diff --git a/clang/test/Driver/hexagon-toolchain-elf.c b/clang/test/Driver/hexagon-toolchain-elf.c index da859a144cfc888cb8550de076e0815c41ca4533..ac921547266c95475a62f1e4276cab3f1ed24ab1 100644 --- a/clang/test/Driver/hexagon-toolchain-elf.c +++ b/clang/test/Driver/hexagon-toolchain-elf.c @@ -36,7 +36,6 @@ // RUN: %clangxx -### --target=hexagon-unknown-elf -fno-integrated-as \ // RUN: -ccc-install-dir %S/Inputs/hexagon_tree/qc/bin \ -// RUN: --gcc-toolchain="" \ // RUN: -nostdlibinc %s 2>&1 | FileCheck -check-prefix=CHECK113 %s // CHECK113: "-cc1" // CHECK113-NOT: "-internal-isystem" diff --git a/clang/test/Driver/hip-link-shared-library.hip b/clang/test/Driver/hip-link-shared-library.hip index 73643682dda8ae57ad86831f94ba56baff975f49..a075ee82dda1cb3954e51338eca26fd323206ae9 100644 --- a/clang/test/Driver/hip-link-shared-library.hip +++ b/clang/test/Driver/hip-link-shared-library.hip @@ -1,6 +1,7 @@ // RUN: touch %t.o +// RUN: touch %t.so // RUN: %clang --hip-link -ccc-print-bindings --target=x86_64-linux-gnu \ -// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t.o %S/Inputs/in.so \ +// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t.o %t.so \ // RUN: --no-offload-new-driver -fgpu-rdc 2>&1 | FileCheck %s // CHECK: # "x86_64-unknown-linux-gnu" - "offload bundler", inputs: ["[[IN:.*o]]"], outputs: ["[[HOSTOBJ:.*o]]", "{{.*o}}", "{{.*o}}"] @@ -11,4 +12,4 @@ // CHECK-NOT: offload bundler // CHECK: # "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[IMG1]]", "[[IMG2]]"], output: "[[FATBINOBJ:.*o]]" // CHECK-NOT: offload bundler -// CHECK: # "x86_64-unknown-linux-gnu" - "GNU::Linker", inputs: ["[[HOSTOBJ]]", "{{.*}}/Inputs/in.so", "[[FATBINOBJ]]"], output: "a.out" +// CHECK: # "x86_64-unknown-linux-gnu" - "GNU::Linker", inputs: ["[[HOSTOBJ]]", "{{.*}}.so", "[[FATBINOBJ]]"], output: "a.out" diff --git a/clang/test/Driver/hip-partial-link.hip b/clang/test/Driver/hip-partial-link.hip index faa185972abc33e52d02c0866dbc8f3af645cbd5..c8451ec81ed37ef86415f24157f1723c690f5ac8 100644 --- a/clang/test/Driver/hip-partial-link.hip +++ b/clang/test/Driver/hip-partial-link.hip @@ -47,7 +47,7 @@ // OBJ: D __hip_gpubin_handle_[[ID2]] // RUN: %clang -v --target=x86_64-unknown-linux-gnu --no-offload-new-driver \ -// RUN: --hip-link -no-hip-rt -fgpu-rdc --offload-arch=gfx906 \ +// RUN: --hip-link -fgpu-rdc --offload-arch=gfx906 \ // RUN: -fuse-ld=lld -nostdlib -r %t.main.o %t.lib.o -o %t.final.o \ // RUN: 2>&1 | FileCheck -check-prefix=LINK-O %s // LINK-O-NOT: Found undefined HIP {{.*}}symbol diff --git a/clang/test/Driver/hip-phases.hip b/clang/test/Driver/hip-phases.hip index ca63d4304d3959949b0d2976c608d33334c69de2..180ef43022f818bc830e700c4106a8e8b876ffa6 100644 --- a/clang/test/Driver/hip-phases.hip +++ b/clang/test/Driver/hip-phases.hip @@ -648,3 +648,15 @@ // LTO-NEXT: 14: offload, "host-hip (x86_64-unknown-linux-gnu)" {2}, "device-hip (x86_64-unknown-linux-gnu)" {13}, ir // LTO-NEXT: 15: backend, {14}, assembler, (host-hip) // LTO-NEXT: 16: assembler, {15}, object, (host-hip) + +// +// Test the new driver when not bundling +// +// RUN: %clang -### --target=x86_64-linux-gnu --offload-new-driver -ccc-print-phases \ +// RUN: --offload-device-only --offload-arch=gfx90a -emit-llvm -c %s 2>&1 \ +// RUN: | FileCheck -check-prefix=DEVICE-ONLY %s +// DEVICE-ONLY: 0: input, "[[INPUT:.+]]", hip, (device-hip, gfx90a) +// DEVICE-ONLY-NEXT: 1: preprocessor, {0}, hip-cpp-output, (device-hip, gfx90a) +// DEVICE-ONLY-NEXT: 2: compiler, {1}, ir, (device-hip, gfx90a) +// DEVICE-ONLY-NEXT: 3: backend, {2}, ir, (device-hip, gfx90a) +// DEVICE-ONLY-NEXT: 4: offload, "device-hip (amdgcn-amd-amdhsa:gfx90a)" {3}, none diff --git a/clang/test/Driver/hip-runtime-libs-linux.hip b/clang/test/Driver/hip-runtime-libs-linux.hip index 142582963c958fdfea0e4c91b21e7112b837e70b..a4cd2733114b69a018ee474aaaea424b22bffbff 100644 --- a/clang/test/Driver/hip-runtime-libs-linux.hip +++ b/clang/test/Driver/hip-runtime-libs-linux.hip @@ -43,6 +43,11 @@ // RUN: --rocm-path=%S/Inputs/rocm %t.o 2>&1 \ // RUN: | FileCheck -check-prefixes=NOHIPRT %s +// Test HIP runtime lib is not linked with -r. +// RUN: %clang -### --hip-link -r --target=x86_64-linux-gnu \ +// RUN: --rocm-path=%S/Inputs/rocm %t.o 2>&1 \ +// RUN: | FileCheck -check-prefixes=NOHIPRT %s + // Test HIP runtime lib is linked without hip-link if there is HIP input file. // RUN: %clang -### --target=x86_64-linux-gnu -nogpuinc -nogpulib \ // RUN: --rocm-path=%S/Inputs/rocm %s 2>&1 \ diff --git a/clang/test/Driver/linker-wrapper-image.c b/clang/test/Driver/linker-wrapper-image.c index 7547526413522475e5f47de5b0700b344e4e1230..d01445e3aed04ee3e35c59a69a598a724cc3a259 100644 --- a/clang/test/Driver/linker-wrapper-image.c +++ b/clang/test/Driver/linker-wrapper-image.c @@ -26,11 +26,11 @@ // OPENMP: @.omp_offloading.device_image = internal unnamed_addr constant [[[SIZE:[0-9]+]] x i8] c"\10\FF\10\AD{{.*}}", section ".llvm.offloading", align 8 // OPENMP-NEXT: @.omp_offloading.device_images = internal unnamed_addr constant [1 x %__tgt_device_image] [%__tgt_device_image { ptr getelementptr inbounds ([[[BEGIN:[0-9]+]] x i8], ptr @.omp_offloading.device_image, i64 1, i64 0), ptr getelementptr inbounds ([[[END:[0-9]+]] x i8], ptr @.omp_offloading.device_image, i64 1, i64 0), ptr @__start_omp_offloading_entries, ptr @__stop_omp_offloading_entries }] // OPENMP-NEXT: @.omp_offloading.descriptor = internal constant %__tgt_bin_desc { i32 1, ptr @.omp_offloading.device_images, ptr @__start_omp_offloading_entries, ptr @__stop_omp_offloading_entries } -// OPENMP-NEXT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.omp_offloading.descriptor_reg, ptr null }] -// OPENMP-NEXT: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.omp_offloading.descriptor_unreg, ptr null }] +// OPENMP-NEXT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @.omp_offloading.descriptor_reg, ptr null }] // OPENMP: define internal void @.omp_offloading.descriptor_reg() section ".text.startup" { // OPENMP-NEXT: entry: +// OPENMP-NEXT: %0 = call i32 @atexit(ptr @.omp_offloading.descriptor_unreg) // OPENMP-NEXT: call void @__tgt_register_lib(ptr @.omp_offloading.descriptor) // OPENMP-NEXT: ret void // OPENMP-NEXT: } @@ -62,7 +62,7 @@ // CUDA-NEXT: @.fatbin_wrapper = internal constant %fatbin_wrapper { i32 1180844977, i32 1, ptr @.fatbin_image, ptr null }, section ".nvFatBinSegment", align 8 // CUDA-NEXT: @.cuda.binary_handle = internal global ptr null -// CUDA: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.cuda.fatbin_reg, ptr null }] +// CUDA: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @.cuda.fatbin_reg, ptr null }] // CUDA: define internal void @.cuda.fatbin_reg() section ".text.startup" { // CUDA-NEXT: entry: @@ -162,7 +162,7 @@ // HIP-NEXT: @.fatbin_wrapper = internal constant %fatbin_wrapper { i32 1212764230, i32 1, ptr @.fatbin_image, ptr null }, section ".hipFatBinSegment", align 8 // HIP-NEXT: @.hip.binary_handle = internal global ptr null -// HIP: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.hip.fatbin_reg, ptr null }] +// HIP: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 101, ptr @.hip.fatbin_reg, ptr null }] // HIP: define internal void @.hip.fatbin_reg() section ".text.startup" { // HIP-NEXT: entry: diff --git a/clang/test/Driver/linux-header-search.cpp b/clang/test/Driver/linux-header-search.cpp index dd4d6eb483a3fb777f487bcb5128eea5b2d297cc..70a85deac89e403b79440dfa32db989e6553a358 100644 --- a/clang/test/Driver/linux-header-search.cpp +++ b/clang/test/Driver/linux-header-search.cpp @@ -9,7 +9,6 @@ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-SYSROOT %s // CHECK-BASIC-LIBCXX-SYSROOT: "-cc1" // CHECK-BASIC-LIBCXX-SYSROOT: "-isysroot" "[[SYSROOT:[^"]+]]" @@ -24,7 +23,6 @@ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree/ \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-SYSROOT-SLASH %s // CHECK-BASIC-LIBCXX-SYSROOT-SLASH: "-cc1" // CHECK-BASIC-LIBCXX-SYSROOT-SLASH-SAME: "-isysroot" "[[SYSROOT:[^"]+/]]" @@ -38,7 +36,6 @@ // RUN: -ccc-install-dir %S/Inputs/basic_linux_libcxx_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-INSTALL %s // CHECK-BASIC-LIBCXX-INSTALL: "-cc1" // CHECK-BASIC-LIBCXX-INSTALL: "-isysroot" "[[SYSROOT:[^"]+]]" @@ -52,7 +49,6 @@ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxxv2_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXXV2-SYSROOT %s // CHECK-BASIC-LIBCXXV2-SYSROOT: "-cc1" // CHECK-BASIC-LIBCXXV2-SYSROOT: "-isysroot" "[[SYSROOT:[^"]+]]" @@ -65,7 +61,6 @@ // RUN: -ccc-install-dir %S/Inputs/basic_linux_libcxxv2_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxxv2_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXXV2-INSTALL %s // CHECK-BASIC-LIBCXXV2-INSTALL: "-cc1" // CHECK-BASIC-LIBCXXV2-INSTALL: "-isysroot" "[[SYSROOT:[^"]+]]" @@ -80,7 +75,6 @@ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libstdcxx_tree/ \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBSTDCXX-SYSROOT-SLASH %s // CHECK-BASIC-LIBSTDCXX-SYSROOT-SLASH: "-cc1" // CHECK-BASIC-LIBSTDCXX-SYSROOT-SLASH-SAME: "-isysroot" "[[SYSROOT:[^"]+/]]" @@ -93,7 +87,6 @@ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libstdcxx_libcxxv2_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBSTDCXX-LIBCXXV2-SYSROOT %s // CHECK-BASIC-LIBSTDCXX-LIBCXXV2-SYSROOT: "-cc1" // CHECK-BASIC-LIBSTDCXX-LIBCXXV2-SYSROOT: "-isysroot" "[[SYSROOT:[^"]+]]" @@ -106,7 +99,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnu -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_4.6.2_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-6-2 %s // CHECK-GENTOO-4-6-2: "-cc1" // CHECK-GENTOO-4-6-2: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -121,7 +113,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnu -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_4.6.4_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-6-4 %s // CHECK-GENTOO-4-6-4: "-cc1" // CHECK-GENTOO-4-6-4: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -136,7 +127,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnu -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_4.9.3_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-3 %s // CHECK-GENTOO-4-9-3: "-cc1" // CHECK-GENTOO-4-9-3: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -155,14 +145,12 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnu -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-3 %s // // Test that gcc-config support does not break multilib. // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnux32 -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-3-X32 %s // CHECK-GENTOO-4-9-3-X32: "-cc1" // CHECK-GENTOO-4-9-3-X32: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -178,7 +166,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=i386-unknown-linux-gnu -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-3-32 %s // CHECK-GENTOO-4-9-3-32: "-cc1" // CHECK-GENTOO-4-9-3-32: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -198,7 +185,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnu -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_4.9.x_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-X %s // // CHECK-GENTOO-4-9-X: "-cc1" @@ -215,7 +201,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnux32 -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_4.9.x_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-X-X32 %s // CHECK-GENTOO-4-9-X-X32: "-cc1" // CHECK-GENTOO-4-9-X-X32: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -231,7 +216,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=i386-unknown-linux-gnu -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_4.9.x_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-X-32 %s // CHECK-GENTOO-4-9-X-32: "-cc1" // CHECK-GENTOO-4-9-X-32: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -248,14 +232,12 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=loongarch64-unknown-linux-gnu -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/debian_loong64_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-LOONG64-GNU %s // // Check that "-gnuf64" is seen as "-gnu" for loong64. // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=loongarch64-unknown-linux-gnuf64 -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/debian_loong64_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-LOONG64-GNU %s // CHECK-LOONG64-GNU: "-cc1" // CHECK-LOONG64-GNU: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -274,7 +256,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=mips64-unknown-linux-gnuabi64 -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/debian_6_mips64_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-MIPS64-GNUABI %s // CHECK-MIPS64-GNUABI: "-cc1" // CHECK-MIPS64-GNUABI: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -292,7 +273,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=mips64el-unknown-linux-gnuabi64 -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/debian_6_mips64_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-MIPS64EL-GNUABI %s // CHECK-MIPS64EL-GNUABI: "-cc1" // CHECK-MIPS64EL-GNUABI: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -311,7 +291,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=arm-oe-linux-gnueabi -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/openembedded_arm_linux_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-OE-ARM %s // CHECK-OE-ARM: "-cc1" @@ -323,7 +302,6 @@ // RUN: %clang -### %s -fsyntax-only 2>&1 \ // RUN: --target=aarch64-oe-linux -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/openembedded_aarch64_linux_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-OE-AARCH64 %s // CHECK-OE-AARCH64: "-cc1" diff --git a/clang/test/Driver/linux-ld.c b/clang/test/Driver/linux-ld.c index d77367b4ece7b98c1838826c50e3172882f4c94a..4020b138dc8fdef0c3f0e4dab3760c7e25bbfb33 100644 --- a/clang/test/Driver/linux-ld.c +++ b/clang/test/Driver/linux-ld.c @@ -4,7 +4,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i386-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-32 %s // CHECK-LD-32-NOT: warning: @@ -17,7 +16,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-64 %s // CHECK-LD-64-NOT: warning: @@ -36,7 +34,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnux32 -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X32 %s // CHECK-LD-X32-NOT: warning: @@ -51,7 +48,6 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux \ // RUN: -resource-dir=%S/Inputs/resource_dir \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: --rtlib=compiler-rt \ // RUN: | FileCheck --check-prefix=CHECK-LD-RT %s @@ -74,7 +70,6 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i686-unknown-linux \ // RUN: -resource-dir=%S/Inputs/resource_dir \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: --rtlib=compiler-rt \ // RUN: | FileCheck --check-prefix=CHECK-LD-RT-I686 %s @@ -96,7 +91,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-androideabi \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: --rtlib=compiler-rt \ // RUN: | FileCheck --check-prefix=CHECK-LD-RT-ANDROID %s @@ -111,7 +105,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-GCC %s // CHECK-LD-GCC-NOT: warning: @@ -131,7 +124,6 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ // RUN: -static-libgcc \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-64-STATIC-LIBGCC %s // CHECK-LD-64-STATIC-LIBGCC-NOT: warning: @@ -150,7 +142,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-NO-LIBGCC %s // CHECK-CLANG-NO-LIBGCC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -160,7 +151,6 @@ // // RUN: %clangxx -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANGXX-NO-LIBGCC %s // CHECK-CLANGXX-NO-LIBGCC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -170,7 +160,6 @@ // // RUN: %clang -static -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-NO-LIBGCC-STATIC %s // CHECK-CLANG-NO-LIBGCC-STATIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -178,7 +167,6 @@ // // RUN: %clang -static-pie -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-LD-STATIC-PIE %s // CHECK-CLANG-LD-STATIC-PIE: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -189,7 +177,6 @@ // // RUN: not %clang -static-pie -pie -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-LD-STATIC-PIE-PIE %s // CHECK-CLANG-LD-STATIC-PIE-PIE: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -200,7 +187,6 @@ // // RUN: not %clang -static-pie -static -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-LD-STATIC-PIE-STATIC %s // CHECK-CLANG-LD-STATIC-PIE-STATIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -211,14 +197,12 @@ // // RUN: not %clang -static-pie -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-LD-STATIC-PIE-NOPIE %s // CHECK-CLANG-LD-STATIC-PIE-NOPIE: error: cannot specify 'nopie' along with 'static-pie' // // RUN: %clang -dynamic -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-NO-LIBGCC-DYNAMIC %s // CHECK-CLANG-NO-LIBGCC-DYNAMIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -228,7 +212,6 @@ // // RUN: %clang -static-libgcc -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-STATIC-LIBGCC %s // CHECK-CLANG-STATIC-LIBGCC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -238,7 +221,6 @@ // // RUN: %clang -static-libgcc -dynamic -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-STATIC-LIBGCC-DYNAMIC %s // CHECK-CLANG-STATIC-LIBGCC-DYNAMIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -248,7 +230,6 @@ // // RUN: %clang -shared-libgcc -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-SHARED-LIBGCC %s // CHECK-CLANG-SHARED-LIBGCC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -258,7 +239,6 @@ // // RUN: %clang -shared-libgcc -dynamic -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-SHARED-LIBGCC-DYNAMIC %s // CHECK-CLANG-SHARED-LIBGCC-DYNAMIC: "-lgcc_s" "-lgcc" @@ -267,7 +247,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-ANDROID-NONE %s // CHECK-CLANG-ANDROID-NONE: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -275,7 +254,6 @@ // // RUN: %clang -shared -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-ANDROID-SHARED %s // CHECK-CLANG-ANDROID-SHARED: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -283,7 +261,6 @@ // // RUN: %clang -static -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-CLANG-ANDROID-STATIC %s // CHECK-CLANG-ANDROID-STATIC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -292,7 +269,6 @@ // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ // RUN: -static \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-64-STATIC %s // CHECK-LD-64-STATIC-NOT: warning: @@ -309,7 +285,7 @@ // CHECK-LD-64-STATIC: "--start-group" "-lgcc" "-lgcc_eh" "-lc" "--end-group" // RUN: %clang -no-pie -### %s --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform -shared -static \ -// RUN: --gcc-toolchain= --sysroot=%S/Inputs/basic_linux_tree 2>&1 | FileCheck --check-prefix=CHECK-LD-SHARED-STATIC %s +// RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 | FileCheck --check-prefix=CHECK-LD-SHARED-STATIC %s // CHECK-LD-SHARED-STATIC: "-shared" "-static" // CHECK-LD-SHARED-STATIC: "{{.*}}/usr/lib/gcc/x86_64-unknown-linux/10.2.0{{/|\\\\}}crtbeginS.o" // CHECK-LD-SHARED-STATIC: "{{.*}}/usr/lib/gcc/x86_64-unknown-linux/10.2.0{{/|\\\\}}crtendS.o" @@ -318,13 +294,11 @@ // RUN: %clang -### %s 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform \ // RUN: -static-libgcc -static \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-64-STATIC %s // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i386-unknown-linux -rtlib=platform --unwindlib=platform -m32 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/multilib_32bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-32-TO-32 %s // CHECK-32-TO-32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -340,7 +314,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i386-unknown-linux -rtlib=platform --unwindlib=platform -m64 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/multilib_32bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-32-TO-64 %s // CHECK-32-TO-64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -356,7 +329,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform -m64 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-64-TO-64 %s // CHECK-64-TO-64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -372,7 +344,6 @@ // // RUN: not %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=plaform --unwindlib=platform -m32 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-64-TO-32 %s // CHECK-64-TO-32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -388,7 +359,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnux32 -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-X32 %s // CHECK-X32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -404,7 +374,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux -rtlib=platform --unwindlib=platform -mx32 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-64-TO-X32 %s // CHECK-64-TO-X32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -420,7 +389,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i386-unknown-linux -rtlib=platform --unwindlib=platform -mx32 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-32-TO-X32 %s // CHECK-32-TO-X32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -436,7 +404,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnux32 -rtlib=platform --unwindlib=platform -m64 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-X32-TO-64 %s // CHECK-X32-TO-64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -452,7 +419,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnux32 -rtlib=platform --unwindlib=platform -m32 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/multilib_64bit_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-X32-TO-32 %s // CHECK-X32-TO-32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -484,7 +450,6 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i386-unknown-linux -rtlib=platform --unwindlib=platform -m32 \ // RUN: -ccc-install-dir %S/Inputs/gcc_version_parsing1/bin \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-GCC-VERSION1 %s // CHECK-GCC-VERSION1: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -496,7 +461,6 @@ // RUN: --target=x86_64-unknown-linux-gnu \ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ -// RUN: --gcc-toolchain="" \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-SYSROOT %s @@ -509,7 +473,6 @@ // RUN: --target=x86_64-unknown-linux-gnu \ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_libcxx_tree/usr/bin \ -// RUN: --gcc-toolchain="" \ // RUN: -resource-dir=%S/Inputs/resource_dir \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-INSTALL %s @@ -525,7 +488,6 @@ // RUN: --target=x86_64-unknown-linux-gnu \ // RUN: -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_libcxx_tree/usr/bin \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-C-LINK %s // CHECK-BASIC-LIBCXX-C-LINK-NOT: warning: @@ -538,7 +500,6 @@ // Check multi arch support on Ubuntu 12.04 LTS. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-unknown-linux-gnueabihf -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/ubuntu_12.04_LTS_multiarch_tree \ // RUN: | FileCheck --check-prefix=CHECK-UBUNTU-12-04-ARM-HF %s // @@ -547,7 +508,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-unknown-linux-musleabihf -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/ubuntu_12.04_LTS_multiarch_tree \ // RUN: | FileCheck --check-prefix=CHECK-UBUNTU-12-04-ARM-HF %s // CHECK-UBUNTU-12-04-ARM-HF: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -563,7 +523,6 @@ // Check Ubuntu 13.10 on x86-64 targeting arm-linux-gnueabihf. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-gnueabihf -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/x86-64_ubuntu_13.10 \ // RUN: | FileCheck --check-prefix=CHECK-X86-64-UBUNTU-13-10-ARM-HF %s // CHECK-X86-64-UBUNTU-13-10-ARM-HF: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -582,7 +541,6 @@ // Check Ubuntu 13.10 on x86-64 targeting arm-linux-gnueabi. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-gnueabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/x86-64_ubuntu_13.10 \ // RUN: | FileCheck --check-prefix=CHECK-X86-64-UBUNTU-13-10-ARM %s // CHECK-X86-64-UBUNTU-13-10-ARM: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -601,7 +559,6 @@ // Check Ubuntu 14.04 on powerpc64le. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=powerpc64le-unknown-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/ubuntu_14.04_multiarch_tree \ // RUN: | FileCheck --check-prefix=CHECK-UBUNTU-14-04-PPC64LE %s // CHECK-UBUNTU-14-04-PPC64LE: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -618,7 +575,6 @@ // "/usr/lib/gcc/x86_64-linux-gnu/4.8/x32/crtend.o" "/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../libx32/crtn.o" // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnux32 -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/ubuntu_14.04_multiarch_tree \ // RUN: | FileCheck --check-prefix=CHECK-UBUNTU-14-04-X32 %s // CHECK-UBUNTU-14-04-X32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -635,7 +591,6 @@ // Check fedora 18 on arm. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armv7-unknown-linux-gnueabihf -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/fedora_18_tree \ // RUN: | FileCheck --check-prefix=CHECK-FEDORA-18-ARM-HF %s // CHECK-FEDORA-18-ARM-HF: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -650,12 +605,10 @@ // Check Fedora 21 on AArch64. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm64-unknown-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/fedora_21_tree \ // RUN: | FileCheck --check-prefix=CHECK-FEDORA-21-AARCH64 %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-unknown-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/fedora_21_tree \ // RUN: | FileCheck --check-prefix=CHECK-FEDORA-21-AARCH64 %s // CHECK-FEDORA-21-AARCH64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -670,7 +623,6 @@ // Check Fedora 31 on riscv64. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=riscv64-redhat-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/fedora_31_riscv64_tree \ // RUN: | FileCheck --check-prefix=CHECK-FEDORA-31-RISCV64 %s // CHECK-FEDORA-31-RISCV64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -684,7 +636,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-unknown-linux-gnueabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/ubuntu_12.04_LTS_multiarch_tree \ // RUN: | FileCheck --check-prefix=CHECK-UBUNTU-12-04-ARM %s // CHECK-UBUNTU-12-04-ARM: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -700,7 +651,6 @@ // Test the setup that shipped in SUSE 10.3 on ppc64. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=powerpc64-suse-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/suse_10.3_ppc64_tree \ // RUN: | FileCheck --check-prefix=CHECK-SUSE-10-3-PPC64 %s // CHECK-SUSE-10-3-PPC64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -713,12 +663,10 @@ // Check openSuse Leap 42.2 on AArch64 // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm64-unknown-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/opensuse_42.2_aarch64_tree \ // RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-42-2-AARCH64 %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-unknown-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/opensuse_42.2_aarch64_tree \ // RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-42-2-AARCH64 %s // CHECK-OPENSUSE-42-2-AARCH64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -733,12 +681,10 @@ // Check openSUSE Tumbleweed on armv6hl // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armv6hl-suse-linux-gnueabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/opensuse_tumbleweed_armv6hl_tree \ // RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-TW-ARMV6HL %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armv6hl-suse-linux-gnueabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/opensuse_tumbleweed_armv6hl_tree \ // RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-TW-ARMV6HL %s // CHECK-OPENSUSE-TW-ARMV6HL: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -753,12 +699,10 @@ // Check openSUSE Tumbleweed on armv7hl // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armv7hl-suse-linux-gnueabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/opensuse_tumbleweed_armv7hl_tree \ // RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-TW-ARMV7HL %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armv7hl-suse-linux-gnueabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/opensuse_tumbleweed_armv7hl_tree \ // RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-TW-ARMV7HL %s // CHECK-OPENSUSE-TW-ARMV7HL: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -773,12 +717,10 @@ // Check openSUSE Tumbleweed on riscv64 // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=riscv64-suse-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/opensuse_tumbleweed_riscv64_tree \ // RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-TW-RISCV64 %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=riscv64-suse-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/opensuse_tumbleweed_riscv64_tree \ // RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-TW-RISCV64 %s // CHECK-OPENSUSE-TW-RISCV64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -793,7 +735,6 @@ // Check openSUSE Tumbleweed on ppc // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=powerpc-unknown-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/opensuse_tumbleweed_ppc_tree \ // RUN: | FileCheck --check-prefix=CHECK-OPENSUSE-TW-PPC %s // CHECK-OPENSUSE-TW-PPC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1048,32 +989,26 @@ // Test linker invocation on Android. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-androideabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i686-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID %s // CHECK-ANDROID: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1090,19 +1025,16 @@ // CHECK-ANDROID: "{{.*}}{{/|\\\\}}crtend_android.o" // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-androideabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s @@ -1113,13 +1045,11 @@ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i686-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-SO %s @@ -1136,7 +1066,6 @@ // CHECK-ANDROID-SO: "{{.*}}{{/|\\\\}}crtend_so.o" // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-androideabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -static \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s @@ -1147,7 +1076,6 @@ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -static \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s @@ -1158,13 +1086,11 @@ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i686-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -static \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -static \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-STATIC %s @@ -1180,37 +1106,31 @@ // CHECK-ANDROID-STATIC: "{{.*}}{{/|\\\\}}crtend_android.o" // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-androideabi -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -pie \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -pie \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -pie \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -pie \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i686-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -pie \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -pie \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PIE %s @@ -1225,32 +1145,26 @@ // CHECK-ANDROID-PIE: "{{.*}}{{/|\\\\}}crtend_android.o" // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-androideabi \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-32 %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-android \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-32 %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-64 %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm64-linux-android \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-64 %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i686-linux-android \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-32 %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-linux-android \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-64 %s // CHECK-ANDROID-32: "-dynamic-linker" "/system/bin/linker" @@ -1260,13 +1174,11 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: -fsanitize=hwaddress \ // RUN: --target=x86_64-linux-android33 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-OLD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: -fsanitize=hwaddress \ // RUN: --target=x86_64-linux-android34 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-NEW %s // CHECK-ANDROID-OLD: "-dynamic-linker" "/system/bin/linker64" @@ -1275,67 +1187,55 @@ // Test that -pthread does not add -lpthread on Android. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-androideabi -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm64-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i686-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-androideabi -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm64-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i686-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-linux-android -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD %s @@ -1343,20 +1243,19 @@ // // RUN: not %clang %t.o -no-pie -### -o %t 2>&1 \ // RUN: --target=arm-linux-androideabi -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-PTHREAD-LINK %s // CHECK-ANDROID-PTHREAD-LINK-NOT: argument unused during compilation: '-pthread' /// Check -fandroid-pad-segment. // RUN: %clang -### %s --target=aarch64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/basic_android_tree/sysroot \ +// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -fandroid-pad-segment 2>&1 | FileCheck --check-prefix=CHECK-ANDROID-PAD-PHDR %s // CHECK-ANDROID-PAD-PHDR: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" // CHECK-ANDROID-PAD-PHDR: "[[SYSROOT]]/usr/lib/crtbegin_dynamic.o" "[[SYSROOT]]/usr/lib/crt_pad_segment.o" // RUN: %clang -### %s --target=aarch64-linux-android -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/basic_android_tree/sysroot \ +// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ // RUN: -fandroid-pad-segment -fno-android-pad-segment 2>&1 | FileCheck --check-prefix=CHECK-NO-ANDROID-PAD-PHDR %s // CHECK-NO-ANDROID-PAD-PHDR: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" // CHECK-NO-ANDROID-PAD-PHDR: "[[SYSROOT]]/usr/lib/crtbegin_dynamic.o" @@ -1368,14 +1267,12 @@ // Check linker invocation on a Debian LoongArch sysroot. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=loongarch64-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_loong64_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-LOONG64 %s // // Check that "-gnuf64" is seen as "-gnu" for loong64. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=loongarch64-linux-gnuf64 -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_loong64_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-LOONG64 %s // CHECK-DEBIAN-ML-LOONG64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1391,7 +1288,6 @@ // Check linker invocation on Debian 6 MIPS 32/64-bit. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=mipsel-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_6_mips_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPSEL %s // CHECK-DEBIAN-ML-MIPSEL: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1407,7 +1303,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=mips64el-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_6_mips_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPS64EL %s // CHECK-DEBIAN-ML-MIPS64EL: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1423,7 +1318,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=mips64el-linux-gnu -rtlib=platform --unwindlib=platform -mabi=n32 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_6_mips_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPS64EL-N32 %s // CHECK-DEBIAN-ML-MIPS64EL-N32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1439,7 +1333,6 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=mips64el-linux-gnuabi64 -rtlib=platform --unwindlib=platform -mabi=32 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_6_mips64_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPS64EL-O32 %s // CHECK-DEBIAN-ML-MIPS64EL-O32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1455,12 +1348,10 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=mips64-unknown-linux-gnu --rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_6_mips64_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPS64-GNUABI %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=mips64-linux-gnuabi64 -rtlib=platform --unwindlib=platform -mabi=n64 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_6_mips64_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPS64-GNUABI %s // CHECK-DEBIAN-ML-MIPS64-GNUABI: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1477,12 +1368,10 @@ // // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=mips64el-unknown-linux-gnu -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_6_mips64_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPS64EL-GNUABI %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=mips64el-linux-gnuabi64 -rtlib=platform --unwindlib=platform -mabi=n64 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/debian_6_mips64_tree \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPS64EL-GNUABI %s // CHECK-DEBIAN-ML-MIPS64EL-GNUABI: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1500,7 +1389,6 @@ // Test linker invocation for Freescale SDK (OpenEmbedded). // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=powerpc-fsl-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/freescale_ppc_tree \ // RUN: | FileCheck --check-prefix=CHECK-FSL-PPC %s // CHECK-FSL-PPC: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1510,7 +1398,6 @@ // CHECK-FSL-PPC: "-L[[SYSROOT]]/usr/lib" // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=powerpc64-fsl-linux -rtlib=platform --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/freescale_ppc64_tree \ // RUN: | FileCheck --check-prefix=CHECK-FSL-PPC64 %s // CHECK-FSL-PPC64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1520,53 +1407,41 @@ // // Check that crtfastmath.o is linked with -ffast-math and with -Ofast. // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -ffast-math \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -funsafe-math-optimizations\ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -Ofast\ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -Ofast -O3\ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -O3 -Ofast\ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -ffast-math -fno-fast-math \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -Ofast -fno-fast-math \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -Ofast -fno-unsafe-math-optimizations \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -fno-fast-math -Ofast \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s // RUN: %clang --target=x86_64-unknown-linux -no-pie -### %s -fno-unsafe-math-optimizations -Ofast \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH %s // We don't have crtfastmath.o in the i386 tree, use it to check that file // detection works. // RUN: %clang --target=i386-unknown-linux -no-pie -### %s -ffast-math \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH %s // CHECK-CRTFASTMATH: usr/lib/gcc/x86_64-unknown-linux/10.2.0{{/|\\\\}}crtfastmath.o @@ -1574,21 +1449,18 @@ // Check that we link in gcrt1.o when compiling with -pg // RUN: %clang -pg --target=x86_64-unknown-linux -no-pie -### %s \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>& 1 \ // RUN: | FileCheck --check-prefix=CHECK-PG %s // CHECK-PG: gcrt1.o // GCC forwards -u to the linker. // RUN: %clang -u asdf --target=x86_64-unknown-linux -no-pie -### %s \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>& 1 \ // RUN: | FileCheck --check-prefix=CHECK-u %s // CHECK-u: "-u" "asdf" // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armeb-unknown-linux \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-ARMEB %s // CHECK-ARMEB: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1598,7 +1470,6 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armebv7-unknown-linux \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7EB %s // CHECK-ARMV7EB: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1609,20 +1480,17 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armv7-unknown-linux \ // RUN: -mbig-endian \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7EB %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armebv7-unknown-linux \ // RUN: -mbig-endian \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7EB %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armv7-unknown-linux \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7EL %s // CHECK-ARMV7EL: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1633,20 +1501,17 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armebv7-unknown-linux \ // RUN: -mlittle-endian \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7EL %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=armv7-unknown-linux \ // RUN: -mlittle-endian \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-ARMV7EL %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64_be-unknown-linux \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-AARCH64BE %s // CHECK-AARCH64BE: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1657,20 +1522,17 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-unknown-linux \ // RUN: -mbig-endian \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-AARCH64BE %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64_be-unknown-linux \ // RUN: -mbig-endian \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-AARCH64BE %s // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-unknown-linux \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-AARCH64LE %s // CHECK-AARCH64LE: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1681,7 +1543,6 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64_be-unknown-linux \ // RUN: -mlittle-endian \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-AARCH64LE %s @@ -1775,7 +1636,6 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnu -rtlib=platform --unwindlib=platform \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-LD-GENTOO %s // CHECK-LD-GENTOO-NOT: warning: // CHECK-LD-GENTOO: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1791,7 +1651,6 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=i686-unknown-linux-gnu -rtlib=platform --unwindlib=platform \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-LD-GENTOO-32 %s // CHECK-LD-GENTOO-32-NOT: warning: // CHECK-LD-GENTOO-32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1807,7 +1666,6 @@ // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-unknown-linux-gnux32 -rtlib=platform --unwindlib=platform \ // RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-LD-GENTOO-X32 %s // CHECK-LD-GENTOO-X32-NOT: warning: // CHECK-LD-GENTOO-X32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" @@ -1833,7 +1691,6 @@ // Check whether gcc7 install works fine on Amazon Linux AMI // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=x86_64-amazon-linux -rtlib=libgcc --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/ami_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-AMI %s // CHECK-LD-AMI-NOT: warning: @@ -1853,7 +1710,6 @@ // Check whether the OpenEmbedded ARM libs are added correctly. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=arm-oe-linux-gnueabi -rtlib=libgcc --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/openembedded_arm_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-OE-ARM %s @@ -1872,7 +1728,6 @@ // Check whether the OpenEmbedded AArch64 libs are added correctly. // RUN: %clang -### %s -no-pie 2>&1 \ // RUN: --target=aarch64-oe-linux -rtlib=libgcc --unwindlib=platform \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/openembedded_aarch64_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-OE-AARCH64 %s diff --git a/clang/test/Driver/linux-musl-header-search.cpp b/clang/test/Driver/linux-musl-header-search.cpp index c6d958583d015822119d5b18653f0b60be8f176c..acff5b71aa65a8cb839478b75b6bfca5189156c4 100644 --- a/clang/test/Driver/linux-musl-header-search.cpp +++ b/clang/test/Driver/linux-musl-header-search.cpp @@ -2,7 +2,7 @@ // RUN: --target=x86_64-linux-musl -stdlib=libc++ \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ -// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree --gcc-toolchain= \ +// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ // RUN: | FileCheck --check-prefix=CHECK-X86-64-LIBCXX %s // RESOURCE_DIR/include comes after /usr/include on linux-musl. @@ -18,7 +18,7 @@ // RUN: --target=x86_64-linux-musl \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ -// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree --gcc-toolchain= \ +// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ // RUN: | FileCheck --check-prefix=CHECK-NOBUILTININC %s // CHECK-NOBUILTININC: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" @@ -28,7 +28,7 @@ // RUN: --target=x86_64-linux-musl \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir \ -// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree --gcc-toolchain= \ +// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ // RUN: | FileCheck --check-prefix=CHECK-NOSTDLIBINC %s // CHECK-NOSTDLIBINC: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" diff --git a/clang/test/Driver/linux-per-target-runtime-dir.c b/clang/test/Driver/linux-per-target-runtime-dir.c index 8c721d82821f6adb894fc7cb74b329eb302e803b..97e746f57eda13da59b0fc715e081389b748d304 100644 --- a/clang/test/Driver/linux-per-target-runtime-dir.c +++ b/clang/test/Driver/linux-per-target-runtime-dir.c @@ -3,7 +3,6 @@ // RUN: -stdlib=libc++ \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_libcxx_tree/usr/bin \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree \ // RUN: | FileCheck --check-prefix=CHECK-PER-TARGET-RUNTIME %s // CHECK-PER-TARGET-RUNTIME: "-cc1" diff --git a/clang/test/Driver/loongarch-munaligned-access.c b/clang/test/Driver/loongarch-munaligned-access.c index 44edb2eb17e6ab603136b1e0db795562194e0693..a545679949973a6e94910e9c1d8e0a79bfb173e6 100644 --- a/clang/test/Driver/loongarch-munaligned-access.c +++ b/clang/test/Driver/loongarch-munaligned-access.c @@ -1,54 +1,25 @@ /// Test -m[no-]unaligned-access and -m[no-]strict-align options. -// RUN: %clang --target=loongarch64 -munaligned-access -fsyntax-only %s -### 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CC1-UNALIGNED -// RUN: %clang --target=loongarch64 -mno-unaligned-access -fsyntax-only %s -### 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CC1-NO-UNALIGNED // RUN: %clang --target=loongarch64 -mstrict-align -fsyntax-only %s -### 2>&1 | \ // RUN: FileCheck %s --check-prefix=CC1-NO-UNALIGNED // RUN: %clang --target=loongarch64 -mno-strict-align -fsyntax-only %s -### 2>&1 | \ // RUN: FileCheck %s --check-prefix=CC1-UNALIGNED -// RUN: %clang --target=loongarch64 -munaligned-access -mno-unaligned-access -fsyntax-only %s -### 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CC1-NO-UNALIGNED -// RUN: %clang --target=loongarch64 -mno-unaligned-access -munaligned-access -fsyntax-only %s -### 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CC1-UNALIGNED // RUN: %clang --target=loongarch64 -mstrict-align -mno-strict-align -fsyntax-only %s -### 2>&1 | \ // RUN: FileCheck %s --check-prefix=CC1-UNALIGNED // RUN: %clang --target=loongarch64 -mno-strict-align -mstrict-align -fsyntax-only %s -### 2>&1 | \ // RUN: FileCheck %s --check-prefix=CC1-NO-UNALIGNED -// RUN: %clang --target=loongarch64 -munaligned-access -mstrict-align -fsyntax-only %s -### 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CC1-NO-UNALIGNED -// RUN: %clang --target=loongarch64 -mstrict-align -munaligned-access -fsyntax-only %s -### 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CC1-UNALIGNED -// RUN: %clang --target=loongarch64 -mno-unaligned-access -mno-strict-align -fsyntax-only %s -### 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CC1-UNALIGNED -// RUN: %clang --target=loongarch64 -mno-strict-align -mno-unaligned-access -fsyntax-only %s -### 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CC1-NO-UNALIGNED -// RUN: %clang --target=loongarch64 -munaligned-access -S -emit-llvm %s -o - | \ -// RUN: FileCheck %s --check-prefix=IR-UNALIGNED -// RUN: %clang --target=loongarch64 -mno-unaligned-access -S -emit-llvm %s -o - | \ -// RUN: FileCheck %s --check-prefix=IR-NO-UNALIGNED // RUN: %clang --target=loongarch64 -mstrict-align -S -emit-llvm %s -o - | \ // RUN: FileCheck %s --check-prefix=IR-NO-UNALIGNED // RUN: %clang --target=loongarch64 -mno-strict-align -S -emit-llvm %s -o - | \ // RUN: FileCheck %s --check-prefix=IR-UNALIGNED -// RUN: %clang --target=loongarch64 -munaligned-access -mno-unaligned-access -S -emit-llvm %s -o - | \ -// RUN: FileCheck %s --check-prefix=IR-NO-UNALIGNED -// RUN: %clang --target=loongarch64 -mno-unaligned-access -munaligned-access -S -emit-llvm %s -o - | \ -// RUN: FileCheck %s --check-prefix=IR-UNALIGNED // RUN: %clang --target=loongarch64 -mstrict-align -mno-strict-align -S -emit-llvm %s -o - | \ // RUN: FileCheck %s --check-prefix=IR-UNALIGNED // RUN: %clang --target=loongarch64 -mno-strict-align -mstrict-align -S -emit-llvm %s -o - | \ // RUN: FileCheck %s --check-prefix=IR-NO-UNALIGNED -// RUN: %clang --target=loongarch64 -munaligned-access -mstrict-align -S -emit-llvm %s -o - | \ -// RUN: FileCheck %s --check-prefix=IR-NO-UNALIGNED -// RUN: %clang --target=loongarch64 -mstrict-align -munaligned-access -S -emit-llvm %s -o - | \ -// RUN: FileCheck %s --check-prefix=IR-UNALIGNED -// RUN: %clang --target=loongarch64 -mno-unaligned-access -mno-strict-align -S -emit-llvm %s -o - | \ -// RUN: FileCheck %s --check-prefix=IR-UNALIGNED -// RUN: %clang --target=loongarch64 -mno-strict-align -mno-unaligned-access -S -emit-llvm %s -o - | \ -// RUN: FileCheck %s --check-prefix=IR-NO-UNALIGNED + +// RUN: not %clang -### --target=loongarch64 -mno-unaligned-access -munaligned-access %s 2>&1 | \ +// RUN: FileCheck %s --check-prefix=ERR // CC1-UNALIGNED: "-target-feature" "+ual" // CC1-NO-UNALIGNED: "-target-feature" "-ual" @@ -56,6 +27,9 @@ // IR-UNALIGNED: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}+ual{{(,.*)?}}" // IR-NO-UNALIGNED: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}-ual{{(,.*)?}}" +// ERR: error: unsupported option '-mno-unaligned-access' for target 'loongarch64' +// ERR: error: unsupported option '-munaligned-access' for target 'loongarch64' + int foo(void) { return 3; } diff --git a/clang/test/Driver/mips-features.c b/clang/test/Driver/mips-features.c index fd06b1400c3123105ab3e16ff5aa15e8ea2939dc..5e92dccaa02abb3aabad977d5344c915129eab44 100644 --- a/clang/test/Driver/mips-features.c +++ b/clang/test/Driver/mips-features.c @@ -462,3 +462,29 @@ // RUN: -mrelax-pic-calls -mno-relax-pic-calls 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO-RELAX-PIC-CALLS %s // CHECK-NO-RELAX-PIC-CALLS: "-mllvm" "-mips-jalr-reloc=0" +// +// -mno-unaligned-access +// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \ +// RUN: -munaligned-access -mno-strict-align \ +// RUN: -mno-unaligned-access 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-STRICT-ALIGN %s +// CHECK-STRICT-ALIGN: "-target-feature" "+strict-align" +// +// -munaligned-access +// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \ +// RUN: -mno-unaligned-access -mstrict-align \ +// RUN: -munaligned-access 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-STRICT-ALIGN %s +// CHECK-NO-STRICT-ALIGN: "-target-feature" "-strict-align" +// +// -mstrict-align +// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \ +// RUN: -munaligned-access -mno-strict-align \ +// RUN: -mstrict-align 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-STRICT-ALIGN %s +// +// -mno-strict-align +// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \ +// RUN: -mno-unaligned-access -mstrict-align \ +// RUN: -mno-strict-align 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-STRICT-ALIGN %s diff --git a/clang/test/Driver/mips-reduced-toolchain.cpp b/clang/test/Driver/mips-reduced-toolchain.cpp index 54d269562b3a23fb7b3b2af1c363ad0d6da4d231..4c15271f7a5f5525574b1e210d06769c78419afa 100644 --- a/clang/test/Driver/mips-reduced-toolchain.cpp +++ b/clang/test/Driver/mips-reduced-toolchain.cpp @@ -4,7 +4,7 @@ // RUN: %clang -### %s 2>&1 \ // RUN: --target=mips-linux-gnu \ // RUN: --sysroot=%S/Inputs/debian_reduced_mips_tree \ -// RUN: --gcc-toolchain="" -no-pie \ +// RUN: -no-pie \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-MIPS %s // CHECK-DEBIAN-MIPS: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" // CHECK-DEBIAN-MIPS: "{{.*}}/usr/lib/gcc/mips-linux-gnu/4.7{{/|\\\\}}crtbegin.o" @@ -16,7 +16,7 @@ // RUN: %clang -### %s 2>&1 \ // RUN: --target=mipsel-linux-gnu \ // RUN: --sysroot=%S/Inputs/debian_reduced_mips_tree \ -// RUN: --gcc-toolchain="" -no-pie \ +// RUN: -no-pie \ // RUN: | FileCheck --check-prefix=CHECK-DEBIAN-MIPSEL %s // CHECK-DEBIAN-MIPSEL: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" // CHECK-DEBIAN-MIPSEL: "{{.*}}/usr/lib/gcc/mipsel-linux-gnu/4.7{{/|\\\\}}crtbegin.o" diff --git a/clang/test/Driver/modules-print-library-module-manifest-path.cpp b/clang/test/Driver/modules-print-library-module-manifest-path.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3ba2709ad95cc8c8e6f720729c5f42bc8ebde074 --- /dev/null +++ b/clang/test/Driver/modules-print-library-module-manifest-path.cpp @@ -0,0 +1,51 @@ +// Test that -print-library-module-manifest-path finds the correct file. + +// RUN: rm -rf %t && split-file %s %t && cd %t +// RUN: mkdir -p %t/Inputs/usr/lib/x86_64-linux-gnu +// RUN: touch %t/Inputs/usr/lib/x86_64-linux-gnu/libc++.so +// RUN: touch %t/Inputs/usr/lib/x86_64-linux-gnu/libc++.a + +// RUN: %clang -print-library-module-manifest-path \ +// RUN: -stdlib=libc++ \ +// RUN: -resource-dir=%t/Inputs/usr/lib/x86_64-linux-gnu \ +// RUN: --target=x86_64-linux-gnu 2>&1 \ +// RUN: | FileCheck libcxx-no-module-json.cpp + +// RUN: touch %t/Inputs/usr/lib/x86_64-linux-gnu/libc++.modules.json +// RUN: %clang -print-library-module-manifest-path \ +// RUN: -stdlib=libc++ \ +// RUN: -resource-dir=%t/Inputs/usr/lib/x86_64-linux-gnu \ +// RUN: --target=x86_64-linux-gnu 2>&1 \ +// RUN: | FileCheck libcxx.cpp + +// RUN: rm %t/Inputs/usr/lib/x86_64-linux-gnu/libc++.so +// RUN: touch %t/Inputs/usr/lib/x86_64-linux-gnu/libc++.a +// RUN: %clang -print-library-module-manifest-path \ +// RUN: -stdlib=libc++ \ +// RUN: -resource-dir=%t/Inputs/usr/lib/x86_64-linux-gnu \ +// RUN: --target=x86_64-linux-gnu 2>&1 \ +// RUN: | FileCheck libcxx-no-shared-lib.cpp + +// RUN: %clang -print-library-module-manifest-path \ +// RUN: -stdlib=libstdc++ \ +// RUN: -resource-dir=%t/Inputs/usr/lib/x86_64-linux-gnu \ +// RUN: --target=x86_64-linux-gnu 2>&1 \ +// RUN: | FileCheck libstdcxx.cpp + +//--- libcxx-no-module-json.cpp + +// CHECK: <NOT PRESENT> + +//--- libcxx.cpp + +// CHECK: {{.*}}/Inputs/usr/lib/x86_64-linux-gnu{{/|\\}}libc++.modules.json + +//--- libcxx-no-shared-lib.cpp + +// Note this might find a different path depending whether search path +// contains a different libc++.so. +// CHECK: {{.*}}libc++.modules.json + +//--- libstdcxx.cpp + +// CHECK: <NOT PRESENT> diff --git a/clang/test/Driver/msvc-link.c b/clang/test/Driver/msvc-link.c index 64e099ea63042f4b598121fd4f59eaff68ae093a..b5c32b173785220943e52fabc9809b5767c00873 100644 --- a/clang/test/Driver/msvc-link.c +++ b/clang/test/Driver/msvc-link.c @@ -36,3 +36,23 @@ // VFSOVERLAY: "--vfsoverlay" // VFSOVERLAY: lld-link // VFSOVERLAY: "/vfsoverlay:{{.*}}" "{{.*}}.obj" + +// RUN: %clang -target arm64ec-pc-windows-msvc -fuse-ld=link -### %s 2>&1 | FileCheck --check-prefix=ARM64EC %s +// RUN: %clang_cl -target arm64ec-pc-windows-msvc -fuse-ld=link -### -- %s 2>&1 | FileCheck --check-prefix=ARM64EC %s +// RUN: %clang_cl -arm64EC -fuse-ld=link -### -- %s 2>&1 | FileCheck --check-prefix=ARM64EC %s +// ARM64EC: "-machine:arm64ec" + +// RUN: %clang -target arm64ec-pc-windows-msvc -fuse-ld=link -marm64x -### %s 2>&1 | \ +// RUN: FileCheck --check-prefix=ARM64X %s +// RUN: %clang -target aarch64-pc-windows-msvc -fuse-ld=link -marm64x -### %s 2>&1 | \ +// RUN: FileCheck --check-prefix=ARM64X %s +// RUN: %clang_cl -marm64x -fuse-ld=link -### -- %s 2>&1 | FileCheck --check-prefix=ARM64X %s +// RUN: %clang_cl -arm64EC -marm64x -fuse-ld=link -### -- %s 2>&1 | FileCheck --check-prefix=ARM64X %s +// ARM64X: "-machine:arm64x" + +// RUN: not %clang -target x86_64-linux-gnu -marm64x -### %s 2>&1 | FileCheck --check-prefix=HYBRID-ERR %s +// HYBRID-ERR: error: unsupported option '-marm64x' for target 'x86_64-linux-gnu' + +// RUN: %clang -c -marm64x -target arm64ec-pc-windows-msvc -fuse-ld=link -### %s 2>&1 | \ +// RUN: FileCheck --check-prefix=HYBRID-WARN %s +// HYBRID-WARN: warning: argument unused during compilation: '-marm64x' [-Wunused-command-line-argument] diff --git a/clang/test/Driver/munaligned-access-unused.c b/clang/test/Driver/munaligned-access-unused.c index 1d86edb798ef2dc232350e30e212e5aaf6fd10a8..4060b53c42fe5f478e6c9efc2b15308046baedf0 100644 --- a/clang/test/Driver/munaligned-access-unused.c +++ b/clang/test/Driver/munaligned-access-unused.c @@ -1,8 +1,9 @@ -/// Check -m[no-]unaligned-access and -m[no-]strict-align are warned unused on a target that does not support them. +/// Check -m[no-]unaligned-access and -m[no-]strict-align are errored on a target that does not support them. // RUN: not %clang --target=x86_64 -munaligned-access -fsyntax-only %s -### 2>&1 | FileCheck %s -DOPTION=unaligned-access // RUN: not %clang --target=x86_64 -mno-unaligned-access -fsyntax-only %s -### 2>&1 | FileCheck %s -DOPTION=no-unaligned-access -// RUN: not %clang --target=x86_64 -mstrict-align -fsyntax-only %s -### 2>&1 | FileCheck %s -DOPTION=strict-align -// RUN: not %clang --target=x86_64 -mno-strict-align -fsyntax-only %s -### 2>&1 | FileCheck %s -DOPTION=no-strict-align +// RUN: not %clang --target=x86_64 -mno-strict-align -mstrict-align -fsyntax-only %s -### 2>&1 | FileCheck %s --check-prefix=ALIGN // CHECK: error: unsupported option '-m{{(no-)?}}unaligned-access' for target '{{.*}}' +// ALIGN: error: unsupported option '-mno-strict-align' for target '{{.*}}' +// ALIGN: error: unsupported option '-mstrict-align' for target '{{.*}}' diff --git a/clang/test/Driver/netbsd.cpp b/clang/test/Driver/netbsd.cpp index f63391580ad0ba86beb7b7988273b6e301e08907..6b8a86d6ee532cfb606b2189d800701e7b16c794 100644 --- a/clang/test/Driver/netbsd.cpp +++ b/clang/test/Driver/netbsd.cpp @@ -196,7 +196,6 @@ // RUN: --target=x86_64-unknown-netbsd \ // RUN: -stdlib=libstdc++ \ // RUN: --sysroot=%S/Inputs/basic_netbsd_tree/ \ -// RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBSTDCXX-SYSROOT-SLASH %s // CHECK-BASIC-LIBSTDCXX-SYSROOT-SLASH: "-cc1" // CHECK-BASIC-LIBSTDCXX-SYSROOT-SLASH-SAME: "-isysroot" "[[SYSROOT:[^"]+/]]" diff --git a/clang/test/Driver/ohos.c b/clang/test/Driver/ohos.c index dfb7981525fd2a9a5a5b5a2ba18b5808080f6c48..b1ce61e7227b6b7d130d553ee89557bb2b846005 100644 --- a/clang/test/Driver/ohos.c +++ b/clang/test/Driver/ohos.c @@ -230,7 +230,6 @@ // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: --target=arm64-linux-ohos -pthread \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/ohos_native_tree/sysroot \ // RUN: -shared \ // RUN: | FileCheck --check-prefix=CHECK-OHOS-PTHREAD %s diff --git a/clang/test/Driver/openmp-offload-gpu.c b/clang/test/Driver/openmp-offload-gpu.c index d705be44e595d80f07ad32ef8ad09f77362bf2b7..d21db7019a1aa606729ff5a5beee1920f8ae7446 100644 --- a/clang/test/Driver/openmp-offload-gpu.c +++ b/clang/test/Driver/openmp-offload-gpu.c @@ -304,8 +304,7 @@ // RUN: | FileCheck %s --check-prefix=CHECK-EMIT-LLVM-IR-BC // CHECK-EMIT-LLVM-IR-BC: "-cc1"{{.*}}"-triple" "nvptx64-nvidia-cuda"{{.*}}"-emit-llvm-bc" -// RUN: %clang -### -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target=nvptx64-nvida-cuda -march=sm_70 \ -// RUN: --libomptarget-nvptx-bc-path=%S/Inputs/libomptarget/libomptarget-new-nvptx-test.bc \ +// RUN: %clang -### -fopenmp=libomp --offload-arch=sm_89 \ // RUN: -nogpulib %s -o openmp-offload-gpu 2>&1 \ // RUN: | FileCheck -check-prefix=DRIVER_EMBEDDING %s diff --git a/clang/test/Driver/pic.c b/clang/test/Driver/pic.c index aeddead6dbf8f4c4c3238af6985a83c11874fe35..f5d0745422790629bb5dc55812df2f28e4ae9bb1 100644 --- a/clang/test/Driver/pic.c +++ b/clang/test/Driver/pic.c @@ -128,15 +128,15 @@ // Make sure -pie is passed to along to ld and that the right *crt* files // are linked in. // RUN: %clang %s -target i386-unknown-freebsd -fPIE -pie -### \ -// RUN: --gcc-toolchain="" -rtlib=platform \ +// RUN: -rtlib=platform \ // RUN: --sysroot=%S/Inputs/basic_freebsd_tree 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-PIE-LD // RUN: %clang %s -target i386-linux-gnu -fPIE -pie -### \ -// RUN: --gcc-toolchain="" -rtlib=platform --unwindlib=platform \ +// RUN: -rtlib=platform --unwindlib=platform \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-PIE-LD // RUN: %clang %s -target i386-linux-gnu -fPIC -pie -### \ -// RUN: --gcc-toolchain="" -rtlib=platform --unwindlib=platform \ +// RUN: -rtlib=platform --unwindlib=platform \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-PIE-LD // @@ -149,7 +149,6 @@ // RUN: %clang -c %s -target i386-unknown-unknown -static -fPIC -### 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-PIC2 // RUN: %clang %s -target i386-linux-gnu -static -fPIC -### \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/basic_linux_tree 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-STATIC // diff --git a/clang/test/Driver/range.c b/clang/test/Driver/range.c index 2d1fd7f9f1a9d53d573b30eed2b275263e704581..da5748d7c723c121369ac5f7ecb9c1344d9ee37c 100644 --- a/clang/test/Driver/range.c +++ b/clang/test/Driver/range.c @@ -1,16 +1,37 @@ // Test range options for complex multiplication and division. // RUN: %clang -### -target x86_64 -fcx-limited-range -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=LMTD %s +// RUN: | FileCheck --check-prefix=BASIC %s // RUN: %clang -### -target x86_64 -fno-cx-limited-range -c %s 2>&1 \ -// RUN: | FileCheck %s +// RUN: | FileCheck --check-prefix=FULL %s + +// RUN: %clang -### -target x86_64 -fcx-limited-range -fcx-fortran-rules \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN1 %s + +// RUN: %clang -### -target x86_64 -fno-cx-limited-range -fcx-fortran-rules \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN2 %s // RUN: %clang -### -target x86_64 -fcx-limited-range -fno-cx-limited-range \ // RUN: -c %s 2>&1 | FileCheck --check-prefix=FULL %s +// RUN: %clang -### -target x86_64 -fno-cx-limited-range -fcx-limited-range \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=BASIC %s + +// RUN: %clang -### -target x86_64 -fno-cx-limited-range -fno-cx-fortran-rules \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=FULL %s + +// RUN: %clang -### -target x86_64 -fno-cx-fortran-rules -fno-cx-limited-range \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=FULL %s + +// RUN: %clang -### -target x86_64 -fcx-limited-range -fno-cx-fortran-rules \ +// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN4 %s + // RUN: %clang -### -target x86_64 -fcx-fortran-rules -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=FRTRN %s +// RUN: | FileCheck --check-prefix=IMPRVD %s + +// RUN: %clang -### -target x86_64 -fno-cx-fortran-rules -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=FULL %s // RUN: %clang -### -target x86_64 -fcx-fortran-rules -c %s 2>&1 \ // RUN: -fno-cx-fortran-rules | FileCheck --check-prefix=FULL %s @@ -32,34 +53,148 @@ // RUN: %clang -### -target x86_64 -fcx-fortran-rules \ // RUN: -fcx-limited-range -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=WARN2 %s +// RUN: | FileCheck --check-prefix=WARN20 %s // RUN: %clang -### -target x86_64 -ffast-math -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=LMTD %s +// RUN: | FileCheck --check-prefix=BASIC %s // RUN: %clang -### -target x86_64 -ffast-math -fcx-limited-range -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=LMTD %s +// RUN: | FileCheck --check-prefix=BASIC %s // RUN: %clang -### -target x86_64 -fcx-limited-range -ffast-math -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=LMTD %s +// RUN: | FileCheck --check-prefix=BASIC %s // RUN: %clang -### -target x86_64 -ffast-math -fno-cx-limited-range \ // RUN: -c %s 2>&1 | FileCheck --check-prefix=FULL %s +// RUN: not %clang -### -target x86_64 -fcomplex-arithmetic=foo -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=ERR %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=basic -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=BASIC %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=improved -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=IMPRVD %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=promoted -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=PRMTD %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=full -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=FULL %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=basic \ +// RUN: -fcx-limited-range -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=BASIC %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=basic \ +// RUN: -fcomplex-arithmetic=improved -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=IMPRVD %s + +// RUN: %clang -### -target x86_64 -fcx-limited-range \ +// RUN: -fcomplex-arithmetic=improved -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=WARN6 %s + +// RUN: %clang -### -target x86_64 -fcx-fortran-rules \ +// RUN: -fcomplex-arithmetic=basic -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=WARN7 %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=basic \ +// RUN: -fcomplex-arithmetic=full -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=FULL %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=basic \ +// RUN: -fcomplex-arithmetic=promoted -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=PRMTD %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=improved \ +// RUN: -fcomplex-arithmetic=basic -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=BASIC %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=improved \ +// RUN: -fcomplex-arithmetic=full -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=FULL %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=improved \ +// RUN: -fcomplex-arithmetic=promoted -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=PRMTD %s + + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=promoted \ +// RUN: -fcomplex-arithmetic=basic -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=BASIC %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=promoted \ +// RUN: -fcx-limited-range -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=WARN14 %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=promoted \ +// RUN: -fcomplex-arithmetic=improved -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=IMPRVD %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=promoted \ +// RUN: -fcomplex-arithmetic=full -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=FULL %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=full \ +// RUN: -fcomplex-arithmetic=basic -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=BASIC %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=full \ +// RUN: -ffast-math -c %s 2>&1 | FileCheck --check-prefix=WARN17 %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=full \ +// RUN: -fcomplex-arithmetic=improved -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=IMPRVD %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=full \ +// RUN: -fcomplex-arithmetic=promoted -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=PRMTD %s + +// RUN: %clang -### -target x86_64 -ffast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=BASIC %s + +// RUN: %clang -### -target x86_64 -ffast-math -fcx-limited-range -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=BASIC %s + +// RUN: %clang -### -target x86_64 -fcx-limited-range -ffast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=BASIC %s + +// RUN: %clang -### -target x86_64 -ffast-math -fno-cx-limited-range -c %s \ +// RUN: 2>&1 | FileCheck --check-prefix=FULL %s + +// RUN: %clang -### -target x86_64 -ffast-math -fcomplex-arithmetic=basic -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=BASIC %s + +// RUN: %clang -### -target x86_64 -fcomplex-arithmetic=basic -ffast-math -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=BASIC %s + // RUN: %clang -### -Werror -target x86_64 -fcx-limited-range -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=LMTD %s +// RUN: | FileCheck --check-prefix=BASIC %s + +// RUN: %clang -### -target x86_64 -ffast-math -fcomplex-arithmetic=full -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=FULL %s -// RUN: %clang -### -Werror -target x86_64 -fcx-fortran-rules -c %s 2>&1 \ -// RUN: | FileCheck --check-prefix=FRTRN %s +// RUN: %clang -### -target x86_64 -ffast-math -fcomplex-arithmetic=basic -c %s 2>&1 \ +// RUN: | FileCheck --check-prefix=BASIC %s -// LMTD: -complex-range=limited +// BASIC: -complex-range=basic // FULL: -complex-range=full -// LMTD-NOT: -complex-range=fortran -// CHECK-NOT: -complex-range=limited -// FRTRN: -complex-range=fortran -// FRTRN-NOT: -complex-range=limited -// CHECK-NOT: -complex-range=fortran +// PRMTD: -complex-range=promoted +// BASIC-NOT: -complex-range=improved +// CHECK-NOT: -complex-range=basic +// IMPRVD: -complex-range=improved +// IMPRVD-NOT: -complex-range=basic +// CHECK-NOT: -complex-range=improved + // WARN1: warning: overriding '-fcx-limited-range' option with '-fcx-fortran-rules' [-Woverriding-option] -// WARN2: warning: overriding '-fcx-fortran-rules' option with '-fcx-limited-range' [-Woverriding-option] +// WARN2: warning: overriding '-fno-cx-limited-range' option with '-fcx-fortran-rules' [-Woverriding-option] // WARN3: warning: overriding '-fcx-fortran-rules' option with '-fno-cx-limited-range' [-Woverriding-option] // WARN4: warning: overriding '-fcx-limited-range' option with '-fno-cx-fortran-rules' [-Woverriding-option] +// WARN5: warning: overriding '-fcomplex-arithmetic=basic' option with '-fcomplex-arithmetic=improved' [-Woverriding-option] +// WARN6: warning: overriding '-fcx-limited-range' option with '-fcomplex-arithmetic=improved' [-Woverriding-option] +// WARN7: warning: overriding '-fcx-fortran-rules' option with '-fcomplex-arithmetic=basic' [-Woverriding-option] +// WARN14: overriding '-complex-range=promoted' option with '-fcx-limited-range' [-Woverriding-option] +// WARN17: warning: overriding '-fcomplex-arithmetic=full' option with '-fcomplex-arithmetic=basic' [-Woverriding-option] +// WARN20: warning: overriding '-fcx-fortran-rules' option with '-fcx-limited-range' [-Woverriding-option] + +// ERR: error: unsupported argument 'foo' to option '-fcomplex-arithmetic=' diff --git a/clang/test/Driver/riscv-features.c b/clang/test/Driver/riscv-features.c index fc5fb0f27e3af4393f432fcb91e86676522c74fa..ce4947d2bc47b4bf0ab00eb6336414fbe6f1daa3 100644 --- a/clang/test/Driver/riscv-features.c +++ b/clang/test/Driver/riscv-features.c @@ -1,7 +1,9 @@ // RUN: %clang --target=riscv32-unknown-elf -### %s -fsyntax-only 2>&1 | FileCheck %s // RUN: %clang --target=riscv64-unknown-elf -### %s -fsyntax-only 2>&1 | FileCheck %s -// RUN: %clang --target=riscv64-linux-android -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ANDROID,DEFAULT -// RUN: %clang -mabi=lp64d --target=riscv64-linux-android -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ANDROID,DEFAULT +// RUN: %clang --target=riscv64-linux-android -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ANDROID,DEFAULT,FAST-UNALIGNED-ACCESS +// RUN: %clang -mabi=lp64d --target=riscv64-linux-android -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=ANDROID,DEFAULT,FAST-UNALIGNED-ACCESS +// RUN: %clang -mabi=lp64d --target=riscv64-linux-android -mstrict-align -### %s -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=NO-FAST-UNALIGNED-ACCESS + // CHECK: fno-signed-char @@ -33,18 +35,16 @@ // NO-FORCE-SW-SCS: "-target-feature" "-forced-sw-shadow-stack" // DEFAULT-NOT: "-target-feature" "+forced-sw-shadow-stack" -// RUN: %clang --target=riscv32-unknown-elf -### %s -munaligned-access 2>&1 | FileCheck %s -check-prefix=FAST-UNALIGNED-ACCESS -// RUN: %clang --target=riscv32-unknown-elf -### %s -mno-unaligned-access 2>&1 | FileCheck %s -check-prefix=NO-FAST-UNALIGNED-ACCESS // RUN: %clang --target=riscv32-unknown-elf -### %s -mno-strict-align 2>&1 | FileCheck %s -check-prefix=FAST-UNALIGNED-ACCESS // RUN: %clang --target=riscv32-unknown-elf -### %s -mstrict-align 2>&1 | FileCheck %s -check-prefix=NO-FAST-UNALIGNED-ACCESS // FAST-UNALIGNED-ACCESS: "-target-feature" "+fast-unaligned-access" // NO-FAST-UNALIGNED-ACCESS: "-target-feature" "-fast-unaligned-access" -// RUN: %clang --target=riscv32-unknown-elf --gcc-toolchain="" -### %s 2>&1 | FileCheck %s -check-prefix=NOUWTABLE -// RUN: %clang --target=riscv32-unknown-elf --gcc-toolchain="" -fasynchronous-unwind-tables -### %s 2>&1 | FileCheck %s -check-prefix=UWTABLE -// RUN: %clang --target=riscv64-unknown-elf --gcc-toolchain="" -### %s 2>&1 | FileCheck %s -check-prefix=NOUWTABLE -// RUN: %clang --target=riscv64-unknown-elf --gcc-toolchain="" -fasynchronous-unwind-tables -### %s 2>&1 | FileCheck %s -check-prefix=UWTABLE +// RUN: %clang --target=riscv32-unknown-elf -### %s 2>&1 | FileCheck %s -check-prefix=NOUWTABLE +// RUN: %clang --target=riscv32-unknown-elf -fasynchronous-unwind-tables -### %s 2>&1 | FileCheck %s -check-prefix=UWTABLE +// RUN: %clang --target=riscv64-unknown-elf -### %s 2>&1 | FileCheck %s -check-prefix=NOUWTABLE +// RUN: %clang --target=riscv64-unknown-elf -fasynchronous-unwind-tables -### %s 2>&1 | FileCheck %s -check-prefix=UWTABLE // // UWTABLE: "-funwind-tables=2" // NOUWTABLE-NOT: "-funwind-tables=2" diff --git a/clang/test/Driver/riscv-profiles.c b/clang/test/Driver/riscv-profiles.c new file mode 100644 index 0000000000000000000000000000000000000000..0227487015ba7c0549570e3413ce2f75b24ed767 --- /dev/null +++ b/clang/test/Driver/riscv-profiles.c @@ -0,0 +1,324 @@ +// RUN: %clang --target=riscv32 -### -c %s 2>&1 -march=rvi20u32 \ +// RUN: | FileCheck -check-prefix=RVI20U32 %s +// RVI20U32: "-target-feature" "-a" +// RVI20U32: "-target-feature" "-c" +// RVI20U32: "-target-feature" "-d" +// RVI20U32: "-target-feature" "-f" +// RVI20U32: "-target-feature" "-m" + +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rvi20u64 \ +// RUN: | FileCheck -check-prefix=RVI20U64 %s +// RVI20U64: "-target-feature" "-a" +// RVI20U64: "-target-feature" "-c" +// RVI20U64: "-target-feature" "-d" +// RVI20U64: "-target-feature" "-f" +// RVI20U64: "-target-feature" "-m" + +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rva20u64 \ +// RUN: | FileCheck -check-prefix=RVA20U64 %s +// RVA20U64: "-target-feature" "+m" +// RVA20U64: "-target-feature" "+a" +// RVA20U64: "-target-feature" "+f" +// RVA20U64: "-target-feature" "+d" +// RVA20U64: "-target-feature" "+c" +// RVA20U64: "-target-feature" "+ziccamoa" +// RVA20U64: "-target-feature" "+ziccif" +// RVA20U64: "-target-feature" "+zicclsm" +// RVA20U64: "-target-feature" "+ziccrse" +// RVA20U64: "-target-feature" "+zicntr" +// RVA20U64: "-target-feature" "+zicsr" +// RVA20U64: "-target-feature" "+za128rs" + +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rva20s64 \ +// RUN: | FileCheck -check-prefix=RVA20S64 %s +// RVA20S64: "-target-feature" "+m" +// RVA20S64: "-target-feature" "+a" +// RVA20S64: "-target-feature" "+f" +// RVA20S64: "-target-feature" "+d" +// RVA20S64: "-target-feature" "+c" +// RVA20S64: "-target-feature" "+ziccamoa" +// RVA20S64: "-target-feature" "+ziccif" +// RVA20S64: "-target-feature" "+zicclsm" +// RVA20S64: "-target-feature" "+ziccrse" +// RVA20S64: "-target-feature" "+zicntr" +// RVA20S64: "-target-feature" "+zicsr" +// RVA20S64: "-target-feature" "+zifencei" +// RVA20S64: "-target-feature" "+za128rs" +// RVA20S64: "-target-feature" "+ssccptr" +// RVA20S64: "-target-feature" "+sstvala" +// RVA20S64: "-target-feature" "+sstvecd" +// RVA20S64: "-target-feature" "+svade" +// RVA20S64: "-target-feature" "+svbare" + +// RUN: %clang --target=riscv64 --target=riscv64 -### -c %s 2>&1 -march=rva22u64 \ +// RUN: | FileCheck -check-prefix=RVA22U64 %s +// RVA22U64: "-target-feature" "+m" +// RVA22U64: "-target-feature" "+a" +// RVA22U64: "-target-feature" "+f" +// RVA22U64: "-target-feature" "+d" +// RVA22U64: "-target-feature" "+c" +// RVA22U64: "-target-feature" "+zic64b" +// RVA22U64: "-target-feature" "+zicbom" +// RVA22U64: "-target-feature" "+zicbop" +// RVA22U64: "-target-feature" "+zicboz" +// RVA22U64: "-target-feature" "+ziccamoa" +// RVA22U64: "-target-feature" "+ziccif" +// RVA22U64: "-target-feature" "+zicclsm" +// RVA22U64: "-target-feature" "+ziccrse" +// RVA22U64: "-target-feature" "+zicntr" +// RVA22U64: "-target-feature" "+zicsr" +// RVA22U64: "-target-feature" "+zihintpause" +// RVA22U64: "-target-feature" "+zihpm" +// RVA22U64: "-target-feature" "+za64rs" +// RVA22U64: "-target-feature" "+zfhmin" +// RVA22U64: "-target-feature" "+zba" +// RVA22U64: "-target-feature" "+zbb" +// RVA22U64: "-target-feature" "+zbs" +// RVA22U64: "-target-feature" "+zkt" + +// RUN: %clang --target=riscv64 --target=riscv64 -### -c %s 2>&1 -march=rva22s64 \ +// RUN: | FileCheck -check-prefix=RVA22S64 %s +// RVA22S64: "-target-feature" "+m" +// RVA22S64: "-target-feature" "+a" +// RVA22S64: "-target-feature" "+f" +// RVA22S64: "-target-feature" "+d" +// RVA22S64: "-target-feature" "+c" +// RVA22S64: "-target-feature" "+zic64b" +// RVA22S64: "-target-feature" "+zicbom" +// RVA22S64: "-target-feature" "+zicbop" +// RVA22S64: "-target-feature" "+zicboz" +// RVA22S64: "-target-feature" "+ziccamoa" +// RVA22S64: "-target-feature" "+ziccif" +// RVA22S64: "-target-feature" "+zicclsm" +// RVA22S64: "-target-feature" "+ziccrse" +// RVA22S64: "-target-feature" "+zicntr" +// RVA22S64: "-target-feature" "+zicsr" +// RVA22S64: "-target-feature" "+zifencei" +// RVA22S64: "-target-feature" "+zihintpause" +// RVA22S64: "-target-feature" "+zihpm" +// RVA22S64: "-target-feature" "+za64rs" +// RVA22S64: "-target-feature" "+zfhmin" +// RVA22S64: "-target-feature" "+zba" +// RVA22S64: "-target-feature" "+zbb" +// RVA22S64: "-target-feature" "+zbs" +// RVA22S64: "-target-feature" "+zkt" +// RVA22S64: "-target-feature" "+ssccptr" +// RVA22S64: "-target-feature" "+sscounterenw" +// RVA22S64: "-target-feature" "+sstvala" +// RVA22S64: "-target-feature" "+sstvecd" +// RVA22S64: "-target-feature" "+svade" +// RVA22S64: "-target-feature" "+svbare" +// RVA22S64: "-target-feature" "+svinval" +// RVA22S64: "-target-feature" "+svpbmt" + +// RUN: %clang --target=riscv64 --target=riscv64 -### -c %s 2>&1 -march=rva23u64 -menable-experimental-extensions \ +// RUN: | FileCheck -check-prefix=RVA23U64 %s +// RVA23U64: "-target-feature" "+m" +// RVA23U64: "-target-feature" "+a" +// RVA23U64: "-target-feature" "+f" +// RVA23U64: "-target-feature" "+d" +// RVA23U64: "-target-feature" "+c" +// RVA23U64: "-target-feature" "+v" +// RVA23U64: "-target-feature" "+zic64b" +// RVA23U64: "-target-feature" "+zicbom" +// RVA23U64: "-target-feature" "+zicbop" +// RVA23U64: "-target-feature" "+zicboz" +// RVA23U64: "-target-feature" "+ziccamoa" +// RVA23U64: "-target-feature" "+ziccif" +// RVA23U64: "-target-feature" "+zicclsm" +// RVA23U64: "-target-feature" "+ziccrse" +// RVA23U64: "-target-feature" "+zicntr" +// RVA23U64: "-target-feature" "+zicond" +// RVA23U64: "-target-feature" "+zicsr" +// RVA23U64: "-target-feature" "+zihintntl" +// RVA23U64: "-target-feature" "+zihintpause" +// RVA23U64: "-target-feature" "+zihpm" +// RVA23U64: "-target-feature" "+experimental-zimop" +// RVA23U64: "-target-feature" "+za64rs" +// RVA23U64: "-target-feature" "+zawrs" +// RVA23U64: "-target-feature" "+zfa" +// RVA23U64: "-target-feature" "+zfhmin" +// RVA23U64: "-target-feature" "+zcb" +// RVA23U64: "-target-feature" "+experimental-zcmop" +// RVA23U64: "-target-feature" "+zba" +// RVA23U64: "-target-feature" "+zbb" +// RVA23U64: "-target-feature" "+zbs" +// RVA23U64: "-target-feature" "+zkt" +// RVA23U64: "-target-feature" "+zvbb" +// RVA23U64: "-target-feature" "+zvfhmin" +// RVA23U64: "-target-feature" "+zvkt" + +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rva23s64 -menable-experimental-extensions \ +// RUN: | FileCheck -check-prefix=RVA23S64 %s +// RVA23S64: "-target-feature" "+m" +// RVA23S64: "-target-feature" "+a" +// RVA23S64: "-target-feature" "+f" +// RVA23S64: "-target-feature" "+d" +// RVA23S64: "-target-feature" "+c" +// RVA23S64: "-target-feature" "+v" +// RVA23S64: "-target-feature" "+h" +// RVA23S64: "-target-feature" "+zic64b" +// RVA23S64: "-target-feature" "+zicbom" +// RVA23S64: "-target-feature" "+zicbop" +// RVA23S64: "-target-feature" "+zicboz" +// RVA23S64: "-target-feature" "+ziccamoa" +// RVA23S64: "-target-feature" "+ziccif" +// RVA23S64: "-target-feature" "+zicclsm" +// RVA23S64: "-target-feature" "+ziccrse" +// RVA23S64: "-target-feature" "+zicntr" +// RVA23S64: "-target-feature" "+zicond" +// RVA23S64: "-target-feature" "+zicsr" +// RVA23S64: "-target-feature" "+zifencei" +// RVA23S64: "-target-feature" "+zihintntl" +// RVA23S64: "-target-feature" "+zihintpause" +// RVA23S64: "-target-feature" "+zihpm" +// RVA23S64: "-target-feature" "+experimental-zimop" +// RVA23S64: "-target-feature" "+za64rs" +// RVA23S64: "-target-feature" "+zawrs" +// RVA23S64: "-target-feature" "+zfa" +// RVA23S64: "-target-feature" "+zfhmin" +// RVA23S64: "-target-feature" "+zcb" +// RVA23S64: "-target-feature" "+experimental-zcmop" +// RVA23S64: "-target-feature" "+zba" +// RVA23S64: "-target-feature" "+zbb" +// RVA23S64: "-target-feature" "+zbs" +// RVA23S64: "-target-feature" "+zkt" +// RVA23S64: "-target-feature" "+zvbb" +// RVA23S64: "-target-feature" "+zvfhmin" +// RVA23S64: "-target-feature" "+zvkt" +// RVA23S64: "-target-feature" "+shcounterenw" +// RVA23S64: "-target-feature" "+shgatpa" +// RVA23S64: "-target-feature" "+shtvala" +// RVA23S64: "-target-feature" "+shvsatpa" +// RVA23S64: "-target-feature" "+shvstvala" +// RVA23S64: "-target-feature" "+shvstvecd" +// RVA23S64: "-target-feature" "+ssccptr" +// RVA23S64: "-target-feature" "+sscofpmf" +// RVA23S64: "-target-feature" "+sscounterenw" +// RVA23S64: "-target-feature" "+experimental-ssnpm" +// RVA23S64: "-target-feature" "+ssstateen" +// RVA23S64: "-target-feature" "+sstc" +// RVA23S64: "-target-feature" "+sstvala" +// RVA23S64: "-target-feature" "+sstvecd" +// RVA23S64: "-target-feature" "+ssu64xl" +// RVA23S64: "-target-feature" "+svade" +// RVA23S64: "-target-feature" "+svbare" +// RVA23S64: "-target-feature" "+svinval" +// RVA23S64: "-target-feature" "+svnapot" +// RVA23S64: "-target-feature" "+svpbmt" + +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rvb23u64 -menable-experimental-extensions \ +// RUN: | FileCheck -check-prefix=RVB23U64 %s +// RVB23U64: "-target-feature" "+m" +// RVB23U64: "-target-feature" "+a" +// RVB23U64: "-target-feature" "+f" +// RVB23U64: "-target-feature" "+d" +// RVB23U64: "-target-feature" "+c" +// RVB23U64: "-target-feature" "+zic64b" +// RVB23U64: "-target-feature" "+zicbom" +// RVB23U64: "-target-feature" "+zicbop" +// RVB23U64: "-target-feature" "+zicboz" +// RVB23U64: "-target-feature" "+ziccamoa" +// RVB23U64: "-target-feature" "+ziccif" +// RVB23U64: "-target-feature" "+zicclsm" +// RVB23U64: "-target-feature" "+ziccrse" +// RVB23U64: "-target-feature" "+zicntr" +// RVB23U64: "-target-feature" "+zicond" +// RVB23U64: "-target-feature" "+zicsr" +// RVB23U64: "-target-feature" "+zihintntl" +// RVB23U64: "-target-feature" "+zihintpause" +// RVB23U64: "-target-feature" "+zihpm" +// RVB23U64: "-target-feature" "+experimental-zimop" +// RVB23U64: "-target-feature" "+za64rs" +// RVB23U64: "-target-feature" "+zawrs" +// RVB23U64: "-target-feature" "+zfa" +// RVB23U64: "-target-feature" "+zcb" +// RVB23U64: "-target-feature" "+experimental-zcmop" +// RVB23U64: "-target-feature" "+zba" +// RVB23U64: "-target-feature" "+zbb" +// RVB23U64: "-target-feature" "+zbs" +// RVB23U64: "-target-feature" "+zkt" + +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rvb23s64 -menable-experimental-extensions \ +// RUN: | FileCheck -check-prefix=RVB23S64 %s +// RVB23S64: "-target-feature" "+m" +// RVB23S64: "-target-feature" "+a" +// RVB23S64: "-target-feature" "+f" +// RVB23S64: "-target-feature" "+d" +// RVB23S64: "-target-feature" "+c" +// RVB23S64: "-target-feature" "+zic64b" +// RVB23S64: "-target-feature" "+zicbom" +// RVB23S64: "-target-feature" "+zicbop" +// RVB23S64: "-target-feature" "+zicboz" +// RVB23S64: "-target-feature" "+ziccamoa" +// RVB23S64: "-target-feature" "+ziccif" +// RVB23S64: "-target-feature" "+zicclsm" +// RVB23S64: "-target-feature" "+ziccrse" +// RVB23S64: "-target-feature" "+zicntr" +// RVB23S64: "-target-feature" "+zicond" +// RVB23S64: "-target-feature" "+zicsr" +// RVB23S64: "-target-feature" "+zifencei" +// RVB23S64: "-target-feature" "+zihintntl" +// RVB23S64: "-target-feature" "+zihintpause" +// RVB23S64: "-target-feature" "+zihpm" +// RVB23S64: "-target-feature" "+experimental-zimop" +// RVB23S64: "-target-feature" "+za64rs" +// RVB23S64: "-target-feature" "+zawrs" +// RVB23S64: "-target-feature" "+zfa" +// RVB23S64: "-target-feature" "+zcb" +// RVB23S64: "-target-feature" "+experimental-zcmop" +// RVB23S64: "-target-feature" "+zba" +// RVB23S64: "-target-feature" "+zbb" +// RVB23S64: "-target-feature" "+zbs" +// RVB23S64: "-target-feature" "+zkt" +// RVB23S64: "-target-feature" "+ssccptr" +// RVB23S64: "-target-feature" "+sscofpmf" +// RVB23S64: "-target-feature" "+sscounterenw" +// RVB23S64: "-target-feature" "+sstc" +// RVB23S64: "-target-feature" "+sstvala" +// RVB23S64: "-target-feature" "+sstvecd" +// RVB23S64: "-target-feature" "+ssu64xl" +// RVB23S64: "-target-feature" "+svade" +// RVB23S64: "-target-feature" "+svbare" +// RVB23S64: "-target-feature" "+svinval" +// RVB23S64: "-target-feature" "+svnapot" +// RVB23S64: "-target-feature" "+svpbmt" + +// RUN: %clang --target=riscv32 -### -c %s 2>&1 -march=rvm23u32 -menable-experimental-extensions \ +// RUN: | FileCheck -check-prefix=RVM23U32 %s +// RVM23U32: "-target-feature" "+m" +// RVM23U32: "-target-feature" "+zicbop" +// RVM23U32: "-target-feature" "+zicond" +// RVM23U32: "-target-feature" "+zicsr" +// RVM23U32: "-target-feature" "+zihintntl" +// RVM23U32: "-target-feature" "+zihintpause" +// RVM23U32: "-target-feature" "+experimental-zimop" +// RVM23U32: "-target-feature" "+zce" +// RVM23U32: "-target-feature" "+experimental-zcmop" +// RVM23U32: "-target-feature" "+zba" +// RVM23U32: "-target-feature" "+zbb" +// RVM23U32: "-target-feature" "+zbs" + +// RUN: %clang --target=riscv64 -### -c %s 2>&1 -march=rva22u64_zfa \ +// RUN: | FileCheck -check-prefix=PROFILE-WITH-ADDITIONAL %s +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+m" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+a" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+f" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+d" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+c" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zicbom" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zicbop" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zicboz" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zihintpause" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zfa" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zfhmin" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zba" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zbb" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zbs" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zkt" + +// RUN: not %clang --target=riscv64 -### -c %s 2>&1 -march=rva19u64_zfa | FileCheck -check-prefix=INVALID-PROFILE %s +// INVALID-PROFILE: error: invalid arch name 'rva19u64_zfa', unsupported profile + +// RUN: not %clang --target=riscv64 -### -c %s 2>&1 -march=rva22u64zfa | FileCheck -check-prefix=INVALID-ADDITIONAL %s +// INVALID-ADDITIONAL: error: invalid arch name 'rva22u64zfa', additional extensions must be after separator '_' diff --git a/clang/test/Driver/solaris-ld-sanitizer.c b/clang/test/Driver/solaris-ld-sanitizer.c index a59164787cada1367d81b78fa81cd3b1bcf4560c..fbbd83f2d9e528296d91eec6d397db09cefefbbe 100644 --- a/clang/test/Driver/solaris-ld-sanitizer.c +++ b/clang/test/Driver/solaris-ld-sanitizer.c @@ -4,47 +4,47 @@ /// Check sparc-sun-solaris2.11, 32bit // RUN: %clang --target=sparc-sun-solaris2.11 %s -### -fuse-ld= \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD %s /// Check sparc-sun-solaris2.11, 32bit // RUN: %clang -fsanitize=undefined --target=sparc-sun-solaris2.11 %s -### -fuse-ld= \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD %s /// Check sparc-sun-solaris2.11, 64bit // RUN: %clang -m64 --target=sparc-sun-solaris2.11 %s -### -fuse-ld= \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD %s /// Check sparc-sun-solaris2.11, 64bit // RUN: %clang -m64 -fsanitize=undefined --target=sparc-sun-solaris2.11 %s -### -fuse-ld= \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD %s /// Check i386-pc-solaris2.11, 32bit // RUN: %clang --target=i386-pc-solaris2.11 %s -### -fuse-ld= \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD %s /// Check i386-pc-solaris2.11, 32bit // RUN: %clang -fsanitize=undefined --target=i386-pc-solaris2.11 %s -### -fuse-ld= \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD %s /// Check i386-pc-solaris2.11, 64bit // RUN: %clang -m64 --target=i386-pc-solaris2.11 %s -### -fuse-ld= \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD %s // CHECK-LD-NOT: "-z" "relax=transtls" /// Check i386-pc-solaris2.11, 64bit // RUN: %clang -m64 -fsanitize=undefined --target=i386-pc-solaris2.11 %s -### -fuse-ld= \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LD-X64-UBSAN %s // RUN: %clang -m64 -fsanitize=undefined --target=i386-pc-solaris2.11 %s -### -fuse-ld=gld \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-GLD-X64-UBSAN %s // CHECK-LD-X64-UBSAN: "-z" "relax=transtls" @@ -56,12 +56,12 @@ /// Check i386-pc-solaris2.11, 32bit, shared libclang_rt.asan // RUN: %clang -fsanitize=address -shared-libasan --target=i386-pc-solaris2.11 %s -### 2>&1 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree \ +// RUN: --sysroot=%S/Inputs/solaris_x86_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X32-ASAN-SHARED %s // CHECK-LD-X32-ASAN-SHARED: "-z" "now" /// Check i386-pc-solaris2.11, 32bit, static libclang_rt.asan // RUN: %clang -fsanitize=address --target=i386-pc-solaris2.11 %s -### 2>&1 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_x86_tree \ +// RUN: --sysroot=%S/Inputs/solaris_x86_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X32-ASAN %s // CHECK-LD-X32-ASAN-NOT: "-z" "now" diff --git a/clang/test/Driver/solaris-ld-values.c b/clang/test/Driver/solaris-ld-values.c index d7b6734f9f91ec857952ba031444d2dd01893255..6f0a5b5957f01402d5a489780ea0b75946eee38e 100644 --- a/clang/test/Driver/solaris-ld-values.c +++ b/clang/test/Driver/solaris-ld-values.c @@ -5,7 +5,6 @@ // Check sparc-sun-solaris2.11, 32bit // RUN: %clang -ansi -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-ANSI %s // CHECK-LD-SPARC32-ANSI: values-Xc.o @@ -13,7 +12,6 @@ // RUN: %clang -std=c89 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-C89 %s // CHECK-LD-SPARC32-C89: values-Xc.o @@ -21,7 +19,6 @@ // RUN: %clang -std=c90 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-C90 %s // CHECK-LD-SPARC32-C90: values-Xc.o @@ -29,7 +26,6 @@ // RUN: %clang -std=iso9899:199409 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-C94 %s // CHECK-LD-SPARC32-C94: values-Xc.o @@ -37,7 +33,6 @@ // RUN: %clang -std=c11 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-C11 %s // CHECK-LD-SPARC32-C11: values-Xc.o @@ -45,7 +40,6 @@ // RUN: %clang -std=gnu89 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-GNU89 %s // CHECK-LD-SPARC32-GNU89: values-Xa.o @@ -53,7 +47,6 @@ // RUN: %clang -std=gnu90 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-GNU90 %s // CHECK-LD-SPARC32-GNU90: values-Xa.o @@ -61,7 +54,6 @@ // RUN: %clang -std=gnu11 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-GNU11 %s // CHECK-LD-SPARC32-GNU11: values-Xa.o @@ -70,7 +62,6 @@ // Check i386-pc-solaris2.11, 32bit // RUN: %clang -ansi -### %s 2>&1 \ // RUN: --target=i386-pc-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X32-ANSI %s // CHECK-LD-X32-ANSI: values-Xc.o diff --git a/clang/test/Driver/solaris-ld-values.cpp b/clang/test/Driver/solaris-ld-values.cpp index 4230fabffcbbc621005855a825274b9787d89f83..566252f551d513d729b29c999e9df92ff99342b8 100644 --- a/clang/test/Driver/solaris-ld-values.cpp +++ b/clang/test/Driver/solaris-ld-values.cpp @@ -5,7 +5,6 @@ // Check sparc-sun-solaris2.11, 32bit // RUN: %clang -ansi -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-ANSI %s // CHECK-LD-SPARC32-ANSI: values-Xc.o @@ -13,7 +12,6 @@ // RUN: %clang -std=c++98 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-CPP98 %s // CHECK-LD-SPARC32-CPP98: values-Xc.o @@ -21,7 +19,6 @@ // RUN: %clang -std=c++11 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-CPP11 %s // CHECK-LD-SPARC32-CPP11: values-Xc.o @@ -29,7 +26,6 @@ // RUN: %clang -std=gnu++98 -### %s 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC32-GNUPP98 %s // CHECK-LD-SPARC32-GNUPP98: values-Xa.o @@ -38,7 +34,6 @@ // Check i386-pc-solaris2.11, 32bit // RUN: %clang -ANSI -### %s 2>&1 \ // RUN: --target=i386-pc-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X32-ANSI %s // CHECK-LD-X32-ANSI: values-Xa.o diff --git a/clang/test/Driver/solaris-ld.c b/clang/test/Driver/solaris-ld.c index df4fa7b4c9ebd6da24fbfe0edd29d25f3279ba26..6d74389e89222ca91025411fb59af63dc0e0d9fd 100644 --- a/clang/test/Driver/solaris-ld.c +++ b/clang/test/Driver/solaris-ld.c @@ -3,11 +3,9 @@ // Check sparc-sun-solaris2.11, 32bit // RUN: %clang -### %s --target=sparc-sun-solaris2.11 -fuse-ld= \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefixes=CHECK-LD-SPARC32,CHECK-LD %s // RUN: %clang -### %s --target=sparc-sun-solaris2.11 -fuse-ld=gld \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefixes=CHECK-LD-SPARC32,CHECK-GLD %s // CHECK-LD-SPARC32-NOT: warning: @@ -31,7 +29,6 @@ // Check sparc-sun-solaris2.11, 64bit // RUN: %clang -m64 -### %s 2>&1 --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-SPARC64 %s // CHECK-LD-SPARC64-NOT: warning: @@ -53,7 +50,6 @@ // Check i386-pc-solaris2.11, 32bit // RUN: %clang -### %s 2>&1 --target=i386-pc-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X32 %s // CHECK-LD-X32-NOT: warning: @@ -76,7 +72,6 @@ // Check i386-pc-solaris2.11, 64bit // RUN: %clang -m64 -### %s 2>&1 \ // RUN: --target=i386-pc-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree \ // RUN: | FileCheck --check-prefix=CHECK-LD-X64 %s // CHECK-LD-X64-NOT: warning: @@ -99,7 +94,6 @@ // Check the right -l flags are present with -shared // RUN: %clang -### %s -shared 2>&1 \ // RUN: --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree \ // RUN: | FileCheck --check-prefix=CHECK-SPARC32-SHARED %s // CHECK-SPARC32-SHARED: "{{.*}}ld{{(.exe)?}}" @@ -109,61 +103,51 @@ // Check that libm is only linked with clang++. // RUN: %clang -### %s --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOLIBM %s // RUN: %clang -### %s -shared --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOLIBM %s // RUN: %clangxx -### %s --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LIBM %s // RUN: %clangxx -### %s -shared --target=sparc-sun-solaris2.11 \ -// RUN: --gcc-toolchain="" --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ +// RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-LIBM %s // CHECK-LIBM: "-lm" // CHECK-NOLIBM-NOT: "-lm" // Check the right ld flags are present with -pie. // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -pie -fuse-ld= \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-PIE-LD %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -pie -fuse-ld=gld \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-PIE-GLD %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -no-pie -fuse-ld= \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOPIE-LD %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -no-pie -fuse-ld=gld \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOPIE-GLD %s // Check that -shared/-r/-static disable PIE. // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -shared -pie -fuse-ld= \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOPIE-LD %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -shared -pie -fuse-ld=gld \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOPIE-GLD %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -r -pie -fuse-ld= \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOPIE-LD %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -r -pie -fuse-ld=gld \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOPIE-GLD %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -static -pie -fuse-ld= \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOPIE-LD %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -static -pie -fuse-ld=gld \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOPIE-GLD %s @@ -184,19 +168,15 @@ // Check that crt{begin,end}S.o is linked with -shared/-pie. // RUN: %clang --target=sparc-sun-solaris2.11 -### %s \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTS %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -shared \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTS %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -no-pie \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTS %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -pie \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTS %s // CHECK-CRTS: crtbeginS.o @@ -208,11 +188,9 @@ // Check sparc-sun-solaris2.11, 32bit // RUN: %clang --target=sparc-sun-solaris2.11 -### %s \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH-SPARC32 %s // RUN: %clang --target=sparc-sun-solaris2.11 -### %s -ffast-math \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH-SPARC32 %s // CHECK-CRTFASTMATH-SPARC32: "-isysroot" "[[SYSROOT:[^"]+]]" @@ -221,11 +199,9 @@ // Check sparc-pc-solaris2.11, 64bit // RUN: %clang -m64 --target=sparc-sun-solaris2.11 -### %s \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH-SPARC64 %s // RUN: %clang -m64 --target=sparc-sun-solaris2.11 -### %s -ffast-math \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_sparc_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH-SPARC64 %s // CHECK-CRTFASTMATH-SPARC64: "-isysroot" "[[SYSROOT:[^"]+]]" @@ -234,11 +210,9 @@ // Check i386-pc-solaris2.11, 32bit // RUN: %clang --target=i386-pc-solaris2.11 -### %s \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH-X32 %s // RUN: %clang --target=i386-pc-solaris2.11 -### %s -ffast-math \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH-X32 %s // CHECK-CRTFASTMATH-X32: "-isysroot" "[[SYSROOT:[^"]+]]" @@ -247,11 +221,9 @@ // Check i386-pc-solaris2.11, 64bit // RUN: %clang -m64 --target=i386-pc-solaris2.11 -### %s \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NOCRTFASTMATH-X64 %s // RUN: %clang -m64 --target=i386-pc-solaris2.11 -### %s -ffast-math \ -// RUN: --gcc-toolchain="" \ // RUN: --sysroot=%S/Inputs/solaris_x86_tree 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CRTFASTMATH-X64 %s // CHECK-CRTFASTMATH-X64: "-isysroot" "[[SYSROOT:[^"]+]]" diff --git a/clang/test/Driver/tls-dialect.c b/clang/test/Driver/tls-dialect.c index f73915b28ec2a301f8b8f32ece70e605cf0f80ca..a808dd81531ce72fe7bd61a8eefdac398ad03450 100644 --- a/clang/test/Driver/tls-dialect.c +++ b/clang/test/Driver/tls-dialect.c @@ -2,6 +2,7 @@ // RUN: %clang -### --target=riscv64-linux -mtls-dialect=trad %s 2>&1 | FileCheck --check-prefix=NODESC %s // RUN: %clang -### --target=riscv64-linux %s 2>&1 | FileCheck --check-prefix=NODESC %s // RUN: %clang -### --target=x86_64-linux -mtls-dialect=gnu %s 2>&1 | FileCheck --check-prefix=NODESC %s +// RUN: %clang -### --target=x86_64-linux -mtls-dialect=gnu2 %s 2>&1 | FileCheck --check-prefix=DESC %s /// Android supports TLSDESC by default on RISC-V /// TLSDESC is not on by default in Linux, even on RISC-V, and is covered above @@ -18,7 +19,6 @@ /// Unsupported argument // RUN: not %clang -### --target=riscv64-linux -mtls-dialect=gnu2 %s 2>&1 | FileCheck --check-prefix=UNSUPPORTED-ARG %s -// RUN: not %clang -### --target=x86_64-linux -mtls-dialect=gnu2 %s 2>&1 | FileCheck --check-prefix=UNSUPPORTED-ARG %s // DESC: "-cc1" {{.*}}"-enable-tlsdesc" // NODESC-NOT: "-enable-tlsdesc" diff --git a/clang/test/Driver/toc-conf.c b/clang/test/Driver/toc-conf.c new file mode 100644 index 0000000000000000000000000000000000000000..7b2d5122ebc6ce4648c035f34e270c7652070052 --- /dev/null +++ b/clang/test/Driver/toc-conf.c @@ -0,0 +1,30 @@ +// RUN: %clang %s --target=powerpc-unknown-aix -mno-tocdata -mtocdata -mno-tocdata -### 2>&1 | FileCheck %s -check-prefix=CHECK-FLAG1 +// RUN: %clang %s --target=powerpc-unknown-aix -mno-tocdata -mtocdata -mno-tocdata -mtocdata -### 2>&1 | FileCheck %s -check-prefix=CHECK-FLAG2 +// RUN: %clang %s --target=powerpc-unknown-aix -mtocdata=g1,g2 -mno-tocdata=g2 -mtocdata=g3,g4 -mno-tocdata=g5,g1 -### 2>&1 | FileCheck %s -check-prefix=CHECK-EQCONF +// RUN: %clang %s --target=powerpc-unknown-aix -mtocdata=g1 -mtocdata -mno-tocdata -mtocdata=g2,g3 -mno-tocdata=g4,g5,g3 -### 2>&1 | FileCheck %s -check-prefix=CHECK-CONF1 +// RUN: %clang %s --target=powerpc-unknown-aix -mno-tocdata=g1 -mno-tocdata -mtocdata -### 2>&1 | FileCheck %s -check-prefix=CHECK-CONF2 + +int g1, g4, g5; +extern int g2; +int g3 = 0; +void func() { + g2 = 0; +} + +// CHECK-FLAG1-NOT: warning: +// CHECK-FLAG1: "-cc1"{{.*}}" "-mno-tocdata" + +// CHECK-FLAG2-NOT: warning: +// CHECK-FLAG2: "-cc1"{{.*}}" "-mtocdata" + +// CHECK-EQCONF-NOT: warning: +// CHECK-EQCONF: "-cc1"{{.*}}" "-mno-tocdata" +// CHECK-EQCONF: "-mtocdata=g3,g4" + +// CHECK-CONF1-NOT: warning: +// CHECK-CONF1: "-cc1"{{.*}}" "-mno-tocdata" +// CHECK-CONF1: "-mtocdata=g1,g2" + +// CHECK-CONF2-NOT: warning: +// CHECK-CONF2: "-cc1"{{.*}}" "-mtocdata" +// CHECK-CONF2: "-mno-tocdata=g1" diff --git a/clang/test/Driver/tocdata-cc1.c b/clang/test/Driver/tocdata-cc1.c new file mode 100644 index 0000000000000000000000000000000000000000..fe0d97ea02db1f549af1b1e81655593c3c0a5ffc --- /dev/null +++ b/clang/test/Driver/tocdata-cc1.c @@ -0,0 +1,16 @@ +// RUN: %clang -### --target=powerpc-ibm-aix-xcoff -mcmodel=medium -mtocdata %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: %clang -### --target=powerpc-ibm-aix-xcoff -mcmodel=large -mtocdata %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: %clang -### --target=powerpc-ibm-aix-xcoff -mtocdata %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-TOC %s +// RUN: %clang -### --target=powerpc64-ibm-aix-xcoff -mcmodel=medium -mtocdata %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: %clang -### --target=powerpc64-ibm-aix-xcoff -mcmodel=large -mtocdata %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: %clang -### --target=powerpc64-ibm-aix-xcoff -mtocdata %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-TOC %s +// CHECK-NOTOC: warning: ignoring '-mtocdata' as it is only supported for -mcmodel=small +// CHECK-NOTOC-NOT: "-cc1"{{.*}}" "-mtocdata" +// CHECK-TOC: "-cc1"{{.*}}" "-mtocdata" +// CHECK-TOC-NOT: warning: ignoring '-mtocdata' as it is only supported for -mcmodel=small diff --git a/clang/test/Driver/unsupported-option-gpu.c b/clang/test/Driver/unsupported-option-gpu.c index f23cb71ebfb08eff8a796eee83712330498ccc2c..5618b2cba72e169faeb118824f2e35c99c7af365 100644 --- a/clang/test/Driver/unsupported-option-gpu.c +++ b/clang/test/Driver/unsupported-option-gpu.c @@ -2,4 +2,5 @@ // DEFINE: %{check} = %clang -### --target=x86_64-linux-gnu -c -mcmodel=medium // RUN: %{check} -x cuda %s --cuda-path=%S/Inputs/CUDA/usr/local/cuda --offload-arch=sm_60 --no-cuda-version-check -fbasic-block-sections=all +// RUN: %{check} -x hip %s --offload=spirv64 -nogpulib -nogpuinc // RUN: %{check} -x hip %s --rocm-path=%S/Inputs/rocm -nogpulib -nogpuinc diff --git a/clang/test/Driver/wasm-toolchain.c b/clang/test/Driver/wasm-toolchain.c index f950283ec42aa0124b691bce9893838dab9b073d..88590a3ba4c453c203f58e96f6cac6fab91e6334 100644 --- a/clang/test/Driver/wasm-toolchain.c +++ b/clang/test/Driver/wasm-toolchain.c @@ -197,3 +197,27 @@ // RUN: not %clang -### %s --target=wasm32-unknown-unknown --sysroot=%s/no-sysroot-there -fPIC -mno-mutable-globals %s 2>&1 \ // RUN: | FileCheck -check-prefix=PIC_NO_MUTABLE_GLOBALS %s // PIC_NO_MUTABLE_GLOBALS: error: invalid argument '-fPIC' not allowed with '-mno-mutable-globals' + +// Test that `wasm32-wasip2` invokes the `wasm-component-ld` linker by default +// instead of `wasm-ld`. + +// RUN: %clang -### -O2 --target=wasm32-wasip2 %s --sysroot /foo 2>&1 \ +// RUN: | FileCheck -check-prefix=LINK_WASIP2 %s +// LINK_WASIP2: "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" +// LINK_WASIP2: wasm-component-ld{{.*}}" "-L/foo/lib/wasm32-wasip2" "crt1.o" "[[temp]]" "-lc" "{{.*[/\\]}}libclang_rt.builtins-wasm32.a" "-o" "a.out" + +// Test that on `wasm32-wasip2` the `wasm-component-ld` programs is told where +// to find `wasm-ld` by default. + +// RUN: %clang -### -O2 --target=wasm32-wasip2 %s --sysroot /foo 2>&1 \ +// RUN: | FileCheck -check-prefix=LINK_WASIP2_FIND_WASMLD %s +// LINK_WASIP2_FIND_WASMLD: "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" +// LINK_WASIP2_FIND_WASMLD: wasm-component-ld{{.*}}" {{.*}} "--wasm-ld-path" "{{.*}}wasm-ld{{.*}}" {{.*}} "[[temp]]" {{.*}} + +// If `wasm32-wasip2` is configured with `wasm-ld` as a linker then don't pass +// the `--wasm-ld-path` flag. + +// RUN: %clang -### -O2 --target=wasm32-wasip2 -fuse-ld=lld %s --sysroot /foo 2>&1 \ +// RUN: | FileCheck -check-prefix=LINK_WASIP2_USE_WASMLD %s +// LINK_WASIP2_USE_WASMLD: "-cc1" {{.*}} "-o" "[[temp:[^"]*]]" +// LINK_WASIP2_USE_WASMLD: wasm-ld{{.*}}" "-m" "wasm32" {{.*}} "[[temp]]" {{.*}} diff --git a/clang/test/Format/fail-on-incomplete.cpp b/clang/test/Format/fail-on-incomplete.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ccd77af4d59947da758e9345ab906b9ed3fd433a --- /dev/null +++ b/clang/test/Format/fail-on-incomplete.cpp @@ -0,0 +1,4 @@ +// RUN: not clang-format -style=LLVM -fail-on-incomplete-format %s +// RUN: clang-format -style=LLVM %s + +int a( diff --git a/clang/test/InstallAPI/Inputs/Simple/Extra/SimpleExtraAPI1.h b/clang/test/InstallAPI/Inputs/Simple/Extra/SimpleExtraAPI1.h new file mode 100644 index 0000000000000000000000000000000000000000..83a5b9507de307ea599b505e17586f71bf0e41a2 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/Extra/SimpleExtraAPI1.h @@ -0,0 +1 @@ +extern int extraGlobalAPI1; diff --git a/clang/test/InstallAPI/Inputs/Simple/Extra/SimpleExtraAPI2.h b/clang/test/InstallAPI/Inputs/Simple/Extra/SimpleExtraAPI2.h new file mode 100644 index 0000000000000000000000000000000000000000..34fe3364bba84eaaa79becbdcfa1d0a64faba59c --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/Extra/SimpleExtraAPI2.h @@ -0,0 +1 @@ +extern int extraGlobalAPI2; diff --git a/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/Basic.h b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/Basic.h new file mode 100644 index 0000000000000000000000000000000000000000..08412bb2de2838b3aef30693261f2b3ef34cbd70 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/Basic.h @@ -0,0 +1,103 @@ +#import <Foundation/Foundation.h> + +// Basic class with no super class +@interface Basic1 +@end + +@interface Basic2 : NSObject +@end + +@interface Basic3 : NSObject +@property BOOL property1; +@property(readonly) BOOL property2; +@property(getter=isProperty3) BOOL property3; +@property BOOL dynamicProp; +@end + +@interface Basic4 : NSObject { +@public + BOOL ivar1; +@protected + BOOL ivar2; +@package + BOOL ivar3; +@private + BOOL ivar4; +} +@end + +__attribute__((visibility("hidden"))) @interface Basic4_1 : NSObject { +@public + BOOL ivar1; +@protected + BOOL ivar2; +@package + BOOL ivar3; +@private + BOOL ivar4; +} +@end + +@interface Basic4_2 : NSObject { +@private + BOOL ivar4; +@package + BOOL ivar3; +@protected + BOOL ivar2; +@public + BOOL ivar1; +} +@end + +@interface Basic5 : NSObject ++ (void)aClassMethod; +- (void)anInstanceMethod; +@end + +@interface Basic6 : NSObject +@end + +@interface Basic6 () { +@public + BOOL ivar1; +} +@property BOOL property1; +- (void)anInstanceMethodFromAnExtension; +@end + +@interface Basic6 (Foo) +@property BOOL property2; +- (void)anInstanceMethodFromACategory; +@end + +__attribute__((visibility("hidden"))) +@interface Basic7 : NSObject +@end + +@interface Basic7 () +- (void) anInstanceMethodFromAnHiddenExtension; +@end + +@interface Basic8 : NSObject ++ (void)useSameName; +@end + +// Classes and protocols can have the same name. For now they would only clash +// in the selector map if the protocl starts with '_'. +@protocol _A +- (void)aMethod; +@end + +@interface A : NSObject +- (void)aMethod NS_AVAILABLE(10_11, 9_0); +- (void)bMethod NS_UNAVAILABLE; +@end + +@interface Basic9 : NSObject +@property(readonly) BOOL aProperty NS_AVAILABLE(10_10, 8_0); +@end + +@interface Basic9 (deprecated) +@property(readwrite) BOOL aProperty NS_DEPRECATED_MAC(10_8, 10_10); +@end diff --git a/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/External.h b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/External.h new file mode 100644 index 0000000000000000000000000000000000000000..5dc3c92f34c24de8cb076b4483071a61c600c48d --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/External.h @@ -0,0 +1,19 @@ +#import <Foundation/Foundation.h> + +// Sub-class an external defined ObjC Class. +@interface ExternalManagedObject : NSManagedObject +- (void)foo; +@end + +// Add category to external defined ObjC Class. +@interface NSManagedObject (Simple) +- (int)supportsSimple; +@end + +// CoreData Accessors are dynamically generated and have no implementation. +@interface ExternalManagedObject (CoreDataGeneratedAccessors) +- (void)addChildObject:(ExternalManagedObject *)value; +- (void)removeChildObject:(ExternalManagedObject *)value; +- (void)addChild:(NSSet *)values; +- (void)removeChild:(NSSet *)values; +@end diff --git a/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/Simple.h b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/Simple.h new file mode 100644 index 0000000000000000000000000000000000000000..12c77098a8d9a759cffd86fe004b9ffbd25cb45e --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/Simple.h @@ -0,0 +1,45 @@ +#import <Foundation/Foundation.h> + +// Useless forward declaration. This is used for testing. +@class FooBar; +@protocol FooProtocol; + +@protocol ForwardProcotol; + +// Test public global. +extern int publicGlobalVariable; + +// Test weak public global. +extern int weakPublicGlobalVariable __attribute__((weak)); + +// Test public ObjC class +@interface Simple : NSObject +@end + +__attribute__((objc_exception)) +@interface Base : NSObject +@end + +@interface SubClass : Base +@end + +@protocol BaseProtocol +- (void) baseMethod; +@end + +NS_AVAILABLE(10_11, 9_0) +@protocol FooProtocol <BaseProtocol> +- (void) protocolMethod; +@end + +@protocol BarProtocol +- (void) barMethod; +@end + +@interface FooClass <FooProtocol, BarProtocol> +@end + +// Create an empty category conforms to a forward declared protocol. +// <rdar://problem/35605892> +@interface FooClass (Test) <ForwardProcotol> +@end diff --git a/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/SimpleAPI.h b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/SimpleAPI.h new file mode 100644 index 0000000000000000000000000000000000000000..d953fac966daf3d72e49ab595ed48a824b1fc267 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/Headers/SimpleAPI.h @@ -0,0 +1 @@ +extern int otherFrameworkAPI; diff --git a/clang/test/InstallAPI/Inputs/Simple/Simple.framework/PrivateHeaders/SimplePrivate.h b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/PrivateHeaders/SimplePrivate.h new file mode 100644 index 0000000000000000000000000000000000000000..5a28cda3928e3d8b5f1a0f199af04f748ac75d43 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/PrivateHeaders/SimplePrivate.h @@ -0,0 +1,5 @@ +// Test private global variable. +extern int privateGlobalVariable; + +// Test weak private global. +extern int weakPrivateGlobalVariable __attribute__((weak)); diff --git a/clang/test/InstallAPI/Inputs/Simple/Simple.framework/PrivateHeaders/SimplePrivateSPI.h b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/PrivateHeaders/SimplePrivateSPI.h new file mode 100644 index 0000000000000000000000000000000000000000..c9aca30fa82fa851b16420a572dce36c32718fb3 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/Simple.framework/PrivateHeaders/SimplePrivateSPI.h @@ -0,0 +1,2 @@ +// Test private global variable. +extern int otherFrameworkSPI; diff --git a/clang/test/InstallAPI/Inputs/Simple/Simple.yaml b/clang/test/InstallAPI/Inputs/Simple/Simple.yaml new file mode 100644 index 0000000000000000000000000000000000000000..998e51f1a67dcc9915f661e68975f3998d6b0412 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/Simple.yaml @@ -0,0 +1,3196 @@ +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x1000007 + cpusubtype: 0x3 + filetype: 0x6 + ncmds: 15 + sizeofcmds: 1952 + flags: 0x118085 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 472 + segname: __TEXT + vmaddr: 0 + vmsize: 12288 + fileoff: 0 + filesize: 12288 + maxprot: 5 + initprot: 5 + nsects: 5 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x1BC0 + size: 180 + offset: 0x1BC0 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 554889E50FBE47085DC3554889E58857085DC3554889E50FBE47095DC3554889E50FBE470A5DC3554889E588570A5DC3554889E55DC3554889E55DC3554889E55DC3554889E50FBE47095DC3554889E58857095DC3554889E5B8010000005DC3554889E55DC3554889E55DC3554889E55DC3554889E55DC3554889E5B0015DC3554889E55DC3554889E55DC3554889E55DC3554889E50FBE47085DC3554889E55DC3554889E55DC3554889E55DC3554889E55DC3 + - sectname: __cstring + segname: __TEXT + addr: 0x1C74 + size: 296 + offset: 0x1C74 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 53696D706C65004261736500537562436C6173730053696D706C65496E7465726E616C4150490053696D706C65496E7465726E616C53504900426173696331004261736963320042617369633300426173696334004261736963345F31004261736963345F32004261736963350042617369633600466F6F004261736963370045787465726E616C4D616E616765644F626A6563740048696464656E436C61737300426173696338004100426173696339006465707265636174656400466F6F436C61737300466F6F50726F746F636F6C004261736550726F746F636F6C0042617250726F746F636F6C0050726976617465005072697661746550726F746F636F6C0063313640303A380076323040303A3863313600630076313640303A380042313640303A3800 + - sectname: __objc_methname + segname: __TEXT + addr: 0x1D9C + size: 450 + offset: 0x1D9C + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 70726F7065727479310073657450726F7065727479313A0070726F70657274793200697350726F7065727479330073657450726F7065727479333A0070726F7065727479330054632C5670726F7065727479310054632C522C5670726F7065727479320054632C47697350726F7065727479332C5670726F7065727479330064796E616D696350726F700054632C440069766172310069766172320069766172330069766172340061436C6173734D6574686F6400616E496E7374616E63654D6574686F6400616E496E7374616E63654D6574686F6446726F6D416E457874656E73696F6E0073657450726F7065727479323A00616E496E7374616E63654D6574686F6446726F6D4143617465676F727900546300616E496E7374616E63654D6574686F6446726F6D416E48696464656E457874656E73696F6E00666F6F00737570706F72747353696D706C650075736553616D654E616D6500614D6574686F64006150726F7065727479005F6150726F70657274790054632C522C565F6150726F706572747900626173654D6574686F640070726F746F636F6C4D6574686F64006261724D6574686F64007072697661746550726F636F746F6C4D6574686F6400 + - sectname: __unwind_info + segname: __TEXT + addr: 0x1F60 + size: 4152 + offset: 0x1F60 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 010000001C000000010000002000000000000000200000000200000000000001C01B00003800000038000000741C00000000000038000000030000000C0001001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + - sectname: __eh_frame + segname: __TEXT + addr: 0x2F98 + size: 24 + offset: 0x2F98 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x6000000B + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 1400000000000000017A520001781001100C070890010000 + - cmd: LC_SEGMENT_64 + cmdsize: 792 + segname: __DATA + vmaddr: 12288 + vmsize: 8192 + fileoff: 12288 + filesize: 8192 + maxprot: 3 + initprot: 3 + nsects: 9 + flags: 0 + Sections: + - sectname: __objc_const + segname: __DATA + addr: 0x3000 + size: 4952 + offset: 0x3000 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 010000002800000028000000000000000000000000000000741C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000008000000000000000000000000000000741C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000028000000280000000000000000000000000000007B1C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000008000000080000000000000000000000000000007B1C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000007B1C000000000000D043000000000000010000002800000028000000000000000000000000000000801C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000008000000000000000000000000000000801C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000801C0000000000002044000000000000010000002800000028000000000000000000000000000000891C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800000008000000000000000000000000000000891C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000891C00000000000070440000000000000100000028000000280000000000000000000000000000009B1C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000008000000080000000000000000000000000000009B1C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000009B1C000000000000C044000000000000030000002800000028000000000000000000000000000000AD1C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000AD1C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000002800000028000000000000000000000000000000B41C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000008000000000000000000000000000000B41C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000002800000028000000000000000000000000000000BB1C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018000000050000009C1D000000000000771D000000000000C01B000000000000A61D0000000000007F1D000000000000CA1B000000000000B41D000000000000771D000000000000D31B000000000000BE1D000000000000771D000000000000DD1B000000000000CA1D0000000000007F1D000000000000E71B000000000000200000000300000098490000000000009C1D0000000000008A1D0000000000000000000001000000A049000000000000B41D0000000000008A1D0000000000000000000001000000A849000000000000D81D0000000000008A1D000000000000000000000100000010000000040000009C1D000000000000E21D000000000000B41D000000000000F01D000000000000D81D000000000000001E0000000000001B1E000000000000271E00000000000000000000080000000B000000000000000000000000000000BB1C00000000000098340000000000000000000000000000183500000000000000000000000000008035000000000000010000002800000028000000000000000000000000000000C21C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000004000000B0490000000000002C1E0000000000008A1D0000000000000000000001000000B849000000000000321E0000000000008A1D0000000000000000000001000000C049000000000000381E0000000000008A1D0000000000000000000001000000C8490000000000003E1E0000000000008A1D000000000000000000000100000000000000080000000C000000000000000000000000000000C21C00000000000000000000000000000000000000000000583600000000000000000000000000000000000000000000110000002800000028000000000000000000000000000000C91C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000004000000D0490000000000002C1E0000000000008A1D0000000000000000000001000000D849000000000000321E0000000000008A1D0000000000000000000001000000E049000000000000381E0000000000008A1D0000000000000000000001000000E8490000000000003E1E0000000000008A1D000000000000000000000100000010000000080000000C000000000000000000000000000000C91C00000000000000000000000000000000000000000000703700000000000000000000000000000000000000000000010000002800000028000000000000000000000000000000D21C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000004000000F0490000000000003E1E0000000000008A1D0000000000000000000001000000F849000000000000381E0000000000008A1D0000000000000000000001000000004A000000000000321E0000000000008A1D0000000000000000000001000000084A0000000000002C1E0000000000008A1D000000000000000000000100000000000000080000000C000000000000000000000000000000D21C000000000000000000000000000000000000000000008838000000000000000000000000000000000000000000001800000001000000441E0000000000008C1D000000000000F01B000000000000010000002800000028000000000000000000000000000000DB1C000000000000583900000000000000000000000000000000000000000000000000000000000000000000000000001800000001000000511E0000000000008C1D000000000000F61B000000000000000000000800000008000000000000000000000000000000DB1C000000000000C0390000000000000000000000000000000000000000000000000000000000000000000000000000010000002800000028000000000000000000000000000000E21C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000003000000621E0000000000008C1D000000000000FC1B0000000000009C1D000000000000771D000000000000021C000000000000A61D0000000000007F1D0000000000000C1C0000000000002000000002000000104A0000000000002C1E0000000000008A1D0000000000000000000001000000184A0000000000009C1D0000000000008A1D000000000000000000000100000010000000010000009C1D000000000000E21D00000000000000000000080000000A000000000000000000000000000000E21C000000000000703A0000000000000000000000000000C03A0000000000000000000000000000083B0000000000001800000003000000B41D000000000000771D000000000000151C000000000000821E0000000000007F1D000000000000201C000000000000901E0000000000008C1D000000000000261C0000000000001000000001000000B41D000000000000AE1E000000000000E91C0000000000004047000000000000683B00000000000000000000000000000000000000000000B83B00000000000000000000000000004000000000000000110000002800000028000000000000000000000000000000ED1C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000001000000B11E0000000000008C1D0000000000002C1C000000000000100000000800000008000000000000000000000000000000ED1C000000000000583C0000000000000000000000000000000000000000000000000000000000000000000000000000010000002800000028000000000000000000000000000000F41C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000001000000D71E0000000000008C1D000000000000321C000000000000000000000800000008000000000000000000000000000000F41C000000000000083D00000000000000000000000000000000000000000000000000000000000000000000000000001800000001000000DB1E000000000000941D000000000000381C000000000000741C0000000000000000000000000000703D000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000001100000028000000280000000000000000000000000000000A1D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000008000000080000000000000000000000000000000A1D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000001000000EA1E0000000000008C1D000000000000401C000000000000010000002800000028000000000000000000000000000000161D000000000000603E00000000000000000000000000000000000000000000000000000000000000000000000000001800000001000000EA1E0000000000008C1D000000000000461C000000000000000000000800000008000000000000000000000000000000161D000000000000C83E00000000000000000000000000000000000000000000000000000000000000000000000000000100000028000000280000000000000000000000000000001D1D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000001000000F61E0000000000008C1D0000000000004C1C0000000000000000000008000000080000000000000000000000000000001D1D000000000000783F00000000000000000000000000000000000000000000000000000000000000000000000000000100000028000000280000000000000000000000000000001F1D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001800000001000000FE1E000000000000771D000000000000521C0000000000002000000001000000204A000000000000081F0000000000008A1D00000000000000000000010000001000000001000000FE1E000000000000131F0000000000000000000008000000090000000000000000000000000000001F1D000000000000284000000000000000000000000000004840000000000000000000000000000070400000000000001000000001000000FE1E000000000000AE1E000000000000261D0000000000002049000000000000000000000000000000000000000000000000000000000000D040000000000000000000000000000040000000000000001800000001000000241F0000000000008C1D00000000000000000000000000008C1D0000000000000100000000000000284A000000000000000000000000000018000000010000002F1F0000000000008C1D00000000000000000000000000008C1D00000000000018000000010000003E1F0000000000008C1D00000000000000000000000000008C1D0000000000000200000000000000884A000000000000E84A0000000000000000000000000000030000002800000028000000000000000000000000000000311D0000000000000000000000000000B8410000000000000000000000000000000000000000000000000000000000001800000003000000241F0000000000008C1D0000000000005C1C0000000000002F1F0000000000008C1D000000000000621C0000000000003E1F0000000000008C1D000000000000681C000000000000020000000000000000000000000000000000000000000000311D0000000000002042000000000000B8410000000000000000000000000000000000000000000000000000000000001800000001000000481F0000000000008C1D0000000000006E1C0000000000001800000001000000481F0000000000008C1D00000000000000000000000000008C1D0000000000000100000000000000484B00000000000000000000000000005F1D0000000000004849000000000000B84200000000000000000000000000000043000000000000000000000000000000000000000000004000000000000000 + - sectname: __objc_data + segname: __DATA + addr: 0x4358 + size: 1600 + offset: 0x4358 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 000000000000000000000000000000000000000000000000000000000000000000300000000000005843000000000000000000000000000000000000000000000000000000000000483000000000000000000000000000000000000000000000000000000000000000000000000000009030000000000000A843000000000000000000000000000000000000000000000000000000000000D8300000000000000000000000000000A843000000000000000000000000000000000000000000003831000000000000F843000000000000D0430000000000000000000000000000000000000000000080310000000000000000000000000000000000000000000000000000000000000000000000000000E03100000000000048440000000000000000000000000000000000000000000000000000000000002832000000000000000000000000000000000000000000000000000000000000000000000000000088320000000000009844000000000000000000000000000000000000000000000000000000000000D032000000000000104500000000000000000000000000000000000000000000000000000000000078330000000000001045000000000000E8440000000000000000000000000000000000000000000030330000000000000000000000000000000000000000000000000000000000000000000000000000C03300000000000038450000000000000000000000000000000000000000000000000000000000000834000000000000000000000000000000000000000000000000000000000000000000000000000050340000000000008845000000000000000000000000000000000000000000000000000000000000C83500000000000000000000000000000000000000000000000000000000000000000000000000001036000000000000D845000000000000000000000000000000000000000000000000000000000000E036000000000000000000000000000000000000000000000000000000000000000000000000000028370000000000002846000000000000000000000000000000000000000000000000000000000000F837000000000000000000000000000000000000000000000000000000000000000000000000000040380000000000007846000000000000000000000000000000000000000000000000000000000000103900000000000000000000000000000000000000000000000000000000000000000000000000007839000000000000C846000000000000000000000000000000000000000000000000000000000000E0390000000000000000000000000000000000000000000000000000000000000000000000000000283A0000000000001847000000000000000000000000000000000000000000000000000000000000203B0000000000000000000000000000000000000000000000000000000000000000000000000000103C0000000000006847000000000000000000000000000000000000000000000000000000000000783C0000000000000000000000000000000000000000000000000000000000000000000000000000C03C000000000000B847000000000000000000000000000000000000000000000000000000000000283D0000000000000000000000000000000000000000000000000000000000000000000000000000D03D0000000000000848000000000000000000000000000000000000000000000000000000000000183E0000000000000000000000000000000000000000000000000000000000000000000000000000803E0000000000005848000000000000000000000000000000000000000000000000000000000000E83E0000000000000000000000000000000000000000000000000000000000000000000000000000303F000000000000A848000000000000000000000000000000000000000000000000000000000000983F0000000000000000000000000000000000000000000000000000000000000000000000000000E03F000000000000F8480000000000000000000000000000000000000000000000000000000000008840000000000000704900000000000000000000000000000000000000000000000000000000000070420000000000007049000000000000484900000000000000000000000000000000000000000000D841000000000000 + - sectname: __objc_ivar + segname: __DATA + addr: 0x4998 + size: 144 + offset: 0x4998 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 080000000000000009000000000000000A00000000000000080000000000000009000000000000000A000000000000000B00000000000000080000000000000009000000000000000A000000000000000B00000000000000080000000000000009000000000000000A000000000000000B00000000000000080000000000000009000000000000000800000000000000 + - sectname: __data + segname: __DATA + addr: 0x4A28 + size: 392 + offset: 0x4A28 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 0000000000000000461D000000000000000000000000000028410000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000048410000000000000000000000000000000000000000000000000000000000003A1D00000000000050410000000000006841000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000008841000000000000000000000000000000000000000000000000000000000000531D0000000000000000000000000000904100000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000B041000000000000000000000000000000000000000000000000000000000000671D0000000000000000000000000000D84200000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000F842000000000000000000000000000000000000000000000000000000000000 + - sectname: __objc_protolist + segname: __DATA + addr: 0x4BB0 + size: 32 + offset: 0x4BB0 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x1000000B + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 284A000000000000884A000000000000E84A000000000000484B000000000000 + - sectname: __objc_classlist + segname: __DATA + addr: 0x4BD0 + size: 160 + offset: 0x4BD0 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x10000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 8043000000000000D04300000000000020440000000000007044000000000000C044000000000000E8440000000000006045000000000000B04500000000000000460000000000005046000000000000A046000000000000F04600000000000040470000000000009047000000000000E04700000000000030480000000000008048000000000000D04800000000000020490000000000004849000000000000 + - sectname: __objc_catlist + segname: __DATA + addr: 0x4C70 + size: 32 + offset: 0x4C70 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x10000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: D03B000000000000903D000000000000E8400000000000001843000000000000 + - sectname: __objc_imageinfo + segname: __DATA + addr: 0x4C90 + size: 8 + offset: 0x4C90 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '0000000040000000' + - sectname: __common + segname: __DATA + addr: 0x4C98 + size: 16 + offset: 0x0 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x1 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 20480 + vmsize: 10272 + fileoff: 20480 + filesize: 10272 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 20480 + rebase_size: 320 + bind_off: 20800 + bind_size: 480 + weak_bind_off: 0 + weak_bind_size: 0 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 21280 + export_size: 896 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 22208 + nsyms: 187 + stroff: 25200 + strsize: 5552 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 131 + iextdefsym: 131 + nextdefsym: 49 + iundefsym: 180 + nundefsym: 7 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_ID_DYLIB + cmdsize: 88 + dylib: + name: 24 + timestamp: 0 + current_version: 66051 + compatibility_version: 65536 + Content: '/System/Library/Frameworks/Simple.framework/Versions/A/Simple' + ZeroPadBytes: 3 + - cmd: LC_UUID + cmdsize: 24 + uuid: 4C4C441D-5555-3144-A104-DD1AF4EF8FE7 + - cmd: LC_VERSION_MIN_MACOSX + cmdsize: 16 + version: 658432 + sdk: 983040 + - cmd: LC_LOAD_DYLIB + cmdsize: 96 + dylib: + name: 24 + timestamp: 0 + current_version: 197722368 + compatibility_version: 19660800 + Content: '/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation' + ZeroPadBytes: 3 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 14942208 + compatibility_version: 65536 + Content: '/usr/lib/libobjc.A.dylib' + ZeroPadBytes: 8 + - cmd: LC_LOAD_DYLIB + cmdsize: 96 + dylib: + name: 24 + timestamp: 0 + current_version: 91750400 + compatibility_version: 65536 + Content: '/System/Library/Frameworks/CoreData.framework/Versions/A/CoreData' + ZeroPadBytes: 7 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 88539136 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 22176 + datasize: 32 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 22208 + datasize: 0 +LinkEditData: + RebaseOpcodes: + - Opcode: REBASE_OPCODE_SET_TYPE_IMM + Imm: 1 + - Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + Imm: 1 + ExtraData: [ 0x18 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x3, 0x40 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x40 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x40 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x40 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x4, 0x40 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 15 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 2 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 8 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 2 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 4 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x10 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 4 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x10 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 4 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x10 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 5 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 7 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 9 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 2 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 9 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 5 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 2 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x28 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 7 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 5 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 4 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x40 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 5 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 7 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 7 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x30 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 2 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 4 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x18 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x8 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x8 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 4 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 9 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 4 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x38 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 2 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 2 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x20 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 2 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x98 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 4 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x18 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 3 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 5 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x18 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 4 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x18 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x8 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 4 + - Opcode: REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB + Imm: 0 + ExtraData: [ 0x18 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES + Imm: 0 + ExtraData: [ 0x1C ] + - Opcode: REBASE_OPCODE_DONE + Imm: 0 + BindOpcodes: + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: _objc_ehtype_vtable + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM + Imm: 2 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + Imm: 1 + ULEBExtraData: [ 0x120 ] + Symbol: '' + - Opcode: BIND_OPCODE_SET_ADDEND_SLEB + Imm: 0 + SLEBExtraData: [ 16 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xA0 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xA0 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xA0 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: '_OBJC_CLASS_$_NSManagedObject' + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM + Imm: 3 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xA78 ] + Symbol: '' + - Opcode: BIND_OPCODE_SET_ADDEND_SLEB + Imm: 0 + SLEBExtraData: [ 0 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xA48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: '_OBJC_METACLASS_$_NSObject' + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM + Imm: 2 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xFFFFFFFFFFFFFB68 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x90 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x40 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: __objc_empty_cache + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xFFFFFFFFFFFFFA60 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: '_OBJC_CLASS_$_NSObject' + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xFFFFFFFFFFFFFA00 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x98 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x98 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x98 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x48 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: '_OBJC_METACLASS_$_NSManagedObject' + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM + Imm: 3 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xFFFFFFFFFFFFFE90 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DONE + Imm: 0 + Symbol: '' + ExportTrie: + TerminalSize: 0 + NodeOffset: 0 + Name: '' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 5 + Name: _ + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 41 + Name: p + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 86 + Name: rivateGlobalVariable + Flags: 0x0 + Address: 0x4CA0 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 92 + Name: ublicGlobalVariable + Flags: 0x0 + Address: 0x4CA4 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 98 + Name: extraGlobalAPI + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 106 + Name: '1' + Flags: 0x0 + Address: 0x4C98 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 112 + Name: '2' + Flags: 0x0 + Address: 0x4C9C + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 118 + Name: weakP + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 165 + Name: rivateGlobalVariable + Flags: 0x4 + Address: 0x4BAC + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 171 + Name: ublicGlobalVariable + Flags: 0x4 + Address: 0x4BA8 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 177 + Name: OBJC_ + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 232 + Name: 'IVAR_$_Basic' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 248 + Name: 6.ivar1 + Flags: 0x0 + Address: 0x4A10 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 254 + Name: '4' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 274 + Name: .ivar + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 284 + Name: '2' + Flags: 0x0 + Address: 0x49B8 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 290 + Name: '1' + Flags: 0x0 + Address: 0x49B0 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 296 + Name: _2.ivar + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 306 + Name: '1' + Flags: 0x0 + Address: 0x4A08 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 312 + Name: '2' + Flags: 0x0 + Address: 0x4A00 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 318 + Name: 'METACLASS_$_' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 369 + Name: FooClass + Flags: 0x0 + Address: 0x4970 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 375 + Name: ExternalManagedObject + Flags: 0x0 + Address: 0x47B8 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 381 + Name: S + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 401 + Name: imple + Flags: 0x0 + Address: 0x4358 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 418 + Name: Internal + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 432 + Name: SPI + Flags: 0x0 + Address: 0x4498 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 438 + Name: API + Flags: 0x0 + Address: 0x4448 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 444 + Name: ubClass + Flags: 0x0 + Address: 0x43F8 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 450 + Name: Bas + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 461 + Name: e + Flags: 0x0 + Address: 0x43A8 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 467 + Name: ic + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 501 + Name: '2' + Flags: 0x0 + Address: 0x4538 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 507 + Name: '3' + Flags: 0x0 + Address: 0x4588 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 513 + Name: '5' + Flags: 0x0 + Address: 0x46C8 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 519 + Name: '4' + Flags: 0x0 + Address: 0x45D8 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 530 + Name: _2 + Flags: 0x0 + Address: 0x4678 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 536 + Name: '9' + Flags: 0x0 + Address: 0x48F8 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 542 + Name: '8' + Flags: 0x0 + Address: 0x4858 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 548 + Name: '6' + Flags: 0x0 + Address: 0x4718 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 554 + Name: '1' + Flags: 0x0 + Address: 0x4510 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 560 + Name: A + Flags: 0x0 + Address: 0x48A8 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 566 + Name: 'EHTYPE_$_' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 579 + Name: Base + Flags: 0x0 + Address: 0x3120 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 584 + Name: S + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 612 + Name: ubClass + Flags: 0x0 + Address: 0x31C8 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 617 + Name: impleInternal + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 631 + Name: SPI + Flags: 0x0 + Address: 0x3318 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 636 + Name: API + Flags: 0x0 + Address: 0x3270 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 641 + Name: 'CLASS_$_' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 692 + Name: A + Flags: 0x0 + Address: 0x48D0 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 698 + Name: ExternalManagedObject + Flags: 0x0 + Address: 0x47E0 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 704 + Name: FooClass + Flags: 0x0 + Address: 0x4948 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 710 + Name: S + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 730 + Name: ubClass + Flags: 0x0 + Address: 0x4420 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 736 + Name: imple + Flags: 0x0 + Address: 0x4380 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 753 + Name: Internal + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 767 + Name: API + Flags: 0x0 + Address: 0x4470 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 773 + Name: SPI + Flags: 0x0 + Address: 0x44C0 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 779 + Name: Bas + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 790 + Name: e + Flags: 0x0 + Address: 0x43D0 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 796 + Name: ic + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 830 + Name: '1' + Flags: 0x0 + Address: 0x44E8 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 836 + Name: '3' + Flags: 0x0 + Address: 0x45B0 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 842 + Name: '4' + Flags: 0x0 + Address: 0x4600 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 853 + Name: _2 + Flags: 0x0 + Address: 0x46A0 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 859 + Name: '2' + Flags: 0x0 + Address: 0x4560 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 865 + Name: '8' + Flags: 0x0 + Address: 0x4880 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 871 + Name: '9' + Flags: 0x0 + Address: 0x4920 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 877 + Name: '6' + Flags: 0x0 + Address: 0x4740 + Other: 0x0 + ImportName: '' + - TerminalSize: 4 + NodeOffset: 883 + Name: '5' + Flags: 0x0 + Address: 0x46F0 + Other: 0x0 + ImportName: '' + NameList: + - n_strx: 2 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7104 + - n_strx: 22 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7114 + - n_strx: 46 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7123 + - n_strx: 66 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7133 + - n_strx: 88 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7143 + - n_strx: 112 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7152 + - n_strx: 135 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7158 + - n_strx: 162 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7164 + - n_strx: 204 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7170 + - n_strx: 224 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7180 + - n_strx: 248 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7189 + - n_strx: 273 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7200 + - n_strx: 302 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7206 + - n_strx: 347 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7212 + - n_strx: 395 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7218 + - n_strx: 424 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7224 + - n_strx: 466 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7232 + - n_strx: 488 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7238 + - n_strx: 510 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7244 + - n_strx: 523 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7250 + - n_strx: 543 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7260 + - n_strx: 566 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7266 + - n_strx: 593 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7272 + - n_strx: 615 + n_type: 0xE + n_sect: 1 + n_desc: 0 + n_value: 7278 + - n_strx: 658 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 12288 + - n_strx: 687 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 12360 + - n_strx: 712 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 12432 + - n_strx: 739 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 12504 + - n_strx: 762 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 12600 + - n_strx: 793 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 12672 + - n_strx: 820 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 12768 + - n_strx: 860 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 12840 + - n_strx: 896 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 12936 + - n_strx: 936 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13008 + - n_strx: 972 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13176 + - n_strx: 997 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13104 + - n_strx: 1026 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13248 + - n_strx: 1055 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13320 + - n_strx: 1080 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13392 + - n_strx: 1109 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13464 + - n_strx: 1142 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13592 + - n_strx: 1177 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13696 + - n_strx: 1203 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13768 + - n_strx: 1228 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13840 + - n_strx: 1257 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 13912 + - n_strx: 1292 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14048 + - n_strx: 1317 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14120 + - n_strx: 1348 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14192 + - n_strx: 1385 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14328 + - n_strx: 1412 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14400 + - n_strx: 1443 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14472 + - n_strx: 1480 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14608 + - n_strx: 1507 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14680 + - n_strx: 1537 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14712 + - n_strx: 1566 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14784 + - n_strx: 1599 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14816 + - n_strx: 1624 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14888 + - n_strx: 1653 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 14960 + - n_strx: 1686 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15040 + - n_strx: 1721 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15112 + - n_strx: 1747 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15136 + - n_strx: 1772 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15208 + - n_strx: 1820 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15288 + - n_strx: 1852 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15312 + - n_strx: 1883 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15376 + - n_strx: 1912 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15448 + - n_strx: 1945 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15480 + - n_strx: 1970 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15552 + - n_strx: 2014 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15624 + - n_strx: 2062 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15656 + - n_strx: 2102 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15728 + - n_strx: 2162 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15760 + - n_strx: 2205 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15824 + - n_strx: 2239 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15896 + - n_strx: 2269 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 15968 + - n_strx: 2299 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16000 + - n_strx: 2328 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16072 + - n_strx: 2361 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16104 + - n_strx: 2386 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16176 + - n_strx: 2410 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16248 + - n_strx: 2438 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16280 + - n_strx: 2458 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16352 + - n_strx: 2487 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16424 + - n_strx: 2520 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16456 + - n_strx: 2555 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16496 + - n_strx: 2581 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16520 + - n_strx: 2606 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16592 + - n_strx: 2645 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16616 + - n_strx: 2683 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 17008 + - n_strx: 2710 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16856 + - n_strx: 2741 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16680 + - n_strx: 2789 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16712 + - n_strx: 2833 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16720 + - n_strx: 2868 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16744 + - n_strx: 2915 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16776 + - n_strx: 2958 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16784 + - n_strx: 3005 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16816 + - n_strx: 3048 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16824 + - n_strx: 3082 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 16928 + - n_strx: 3117 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 17080 + - n_strx: 3171 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 17112 + - n_strx: 3222 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 17144 + - n_strx: 3269 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 17152 + - n_strx: 3316 + n_type: 0xE + n_sect: 6 + n_desc: 0 + n_value: 17176 + - n_strx: 4000 + n_type: 0x1E + n_sect: 7 + n_desc: 0 + n_value: 17960 + - n_strx: 4027 + n_type: 0x1E + n_sect: 7 + n_desc: 0 + n_value: 18000 + - n_strx: 4192 + n_type: 0x1E + n_sect: 7 + n_desc: 0 + n_value: 18280 + - n_strx: 4217 + n_type: 0x1E + n_sect: 7 + n_desc: 0 + n_value: 18320 + - n_strx: 4314 + n_type: 0x1E + n_sect: 7 + n_desc: 0 + n_value: 18440 + - n_strx: 4344 + n_type: 0x1E + n_sect: 7 + n_desc: 0 + n_value: 18480 + - n_strx: 4548 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18840 + - n_strx: 4578 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18848 + - n_strx: 4608 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18856 + - n_strx: 4690 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18880 + - n_strx: 4716 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18888 + - n_strx: 4742 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18896 + - n_strx: 4770 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18904 + - n_strx: 4798 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18912 + - n_strx: 4826 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18920 + - n_strx: 4854 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18928 + - n_strx: 4882 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18936 + - n_strx: 4992 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18968 + - n_strx: 5022 + n_type: 0x1E + n_sect: 8 + n_desc: 0 + n_value: 18976 + - n_strx: 5053 + n_type: 0x1E + n_sect: 9 + n_desc: 0 + n_value: 18984 + - n_strx: 5084 + n_type: 0x1E + n_sect: 9 + n_desc: 0 + n_value: 19080 + - n_strx: 5114 + n_type: 0x1E + n_sect: 9 + n_desc: 0 + n_value: 19176 + - n_strx: 5144 + n_type: 0x1E + n_sect: 9 + n_desc: 0 + n_value: 19272 + - n_strx: 5231 + n_type: 0x1E + n_sect: 10 + n_desc: 0 + n_value: 19376 + - n_strx: 5268 + n_type: 0x1E + n_sect: 10 + n_desc: 0 + n_value: 19384 + - n_strx: 5304 + n_type: 0x1E + n_sect: 10 + n_desc: 0 + n_value: 19392 + - n_strx: 5340 + n_type: 0x1E + n_sect: 10 + n_desc: 0 + n_value: 19400 + - n_strx: 3353 + n_type: 0xF + n_sect: 14 + n_desc: 0 + n_value: 19608 + - n_strx: 3370 + n_type: 0xF + n_sect: 14 + n_desc: 0 + n_value: 19612 + - n_strx: 3387 + n_type: 0xF + n_sect: 14 + n_desc: 0 + n_value: 19616 + - n_strx: 3410 + n_type: 0xF + n_sect: 14 + n_desc: 0 + n_value: 19620 + - n_strx: 3432 + n_type: 0xF + n_sect: 6 + n_desc: 0 + n_value: 12576 + - n_strx: 3452 + n_type: 0xF + n_sect: 6 + n_desc: 0 + n_value: 12744 + - n_strx: 3476 + n_type: 0xF + n_sect: 6 + n_desc: 0 + n_value: 12912 + - n_strx: 3509 + n_type: 0xF + n_sect: 6 + n_desc: 0 + n_value: 13080 + - n_strx: 3542 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17240 + - n_strx: 3567 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17280 + - n_strx: 3588 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17320 + - n_strx: 3611 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17360 + - n_strx: 3630 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17400 + - n_strx: 3657 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17440 + - n_strx: 3680 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17480 + - n_strx: 3716 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17520 + - n_strx: 3748 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17560 + - n_strx: 3784 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17600 + - n_strx: 3816 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17640 + - n_strx: 3837 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17680 + - n_strx: 3862 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17720 + - n_strx: 3887 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17760 + - n_strx: 3908 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17800 + - n_strx: 3933 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17840 + - n_strx: 3954 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17880 + - n_strx: 3979 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 17920 + - n_strx: 4050 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18040 + - n_strx: 4077 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18080 + - n_strx: 4100 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18120 + - n_strx: 4125 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18160 + - n_strx: 4146 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18200 + - n_strx: 4171 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18240 + - n_strx: 4238 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18360 + - n_strx: 4278 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18400 + - n_strx: 4370 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18520 + - n_strx: 4395 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18560 + - n_strx: 4416 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18600 + - n_strx: 4436 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18640 + - n_strx: 4452 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18680 + - n_strx: 4477 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18720 + - n_strx: 4498 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18760 + - n_strx: 4521 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 18800 + - n_strx: 4638 + n_type: 0xF + n_sect: 8 + n_desc: 0 + n_value: 18864 + - n_strx: 4664 + n_type: 0xF + n_sect: 8 + n_desc: 0 + n_value: 18872 + - n_strx: 4910 + n_type: 0xF + n_sect: 8 + n_desc: 0 + n_value: 18944 + - n_strx: 4938 + n_type: 0xF + n_sect: 8 + n_desc: 0 + n_value: 18952 + - n_strx: 4966 + n_type: 0xF + n_sect: 8 + n_desc: 0 + n_value: 18960 + - n_strx: 5178 + n_type: 0xF + n_sect: 9 + n_desc: 128 + n_value: 19368 + - n_strx: 5204 + n_type: 0xF + n_sect: 9 + n_desc: 128 + n_value: 19372 + - n_strx: 5380 + n_type: 0x1 + n_sect: 0 + n_desc: 768 + n_value: 0 + - n_strx: 5410 + n_type: 0x1 + n_sect: 0 + n_desc: 512 + n_value: 0 + - n_strx: 5433 + n_type: 0x1 + n_sect: 0 + n_desc: 768 + n_value: 0 + - n_strx: 5467 + n_type: 0x1 + n_sect: 0 + n_desc: 512 + n_value: 0 + - n_strx: 5494 + n_type: 0x1 + n_sect: 0 + n_desc: 512 + n_value: 0 + - n_strx: 5513 + n_type: 0x1 + n_sect: 0 + n_desc: 512 + n_value: 0 + - n_strx: 5533 + n_type: 0x1 + n_sect: 0 + n_desc: 1024 + n_value: 0 + StringTable: + - ' ' + - '-[Basic3 property1]' + - '-[Basic3 setProperty1:]' + - '-[Basic3 property2]' + - '-[Basic3 isProperty3]' + - '-[Basic3 setProperty3:]' + - '+[Basic5 aClassMethod]' + - '-[Basic5 anInstanceMethod]' + - '-[Basic6 anInstanceMethodFromAnExtension]' + - '-[Basic6 property1]' + - '-[Basic6 setProperty1:]' + - '-[Basic6(Foo) property2]' + - '-[Basic6(Foo) setProperty2:]' + - '-[Basic6(Foo) anInstanceMethodFromACategory]' + - '-[Basic7 anInstanceMethodFromAnHiddenExtension]' + - '-[ExternalManagedObject foo]' + - '-[NSManagedObject(Simple) supportsSimple]' + - '+[Basic8 useSameName]' + - '-[Basic8 useSameName]' + - '-[A aMethod]' + - '-[Basic9 aProperty]' + - '-[FooClass baseMethod]' + - '-[FooClass protocolMethod]' + - '-[FooClass barMethod]' + - '-[FooClass(Private) privateProcotolMethod]' + - '__OBJC_METACLASS_RO_$_Simple' + - '__OBJC_CLASS_RO_$_Simple' + - '__OBJC_METACLASS_RO_$_Base' + - '__OBJC_CLASS_RO_$_Base' + - '__OBJC_METACLASS_RO_$_SubClass' + - '__OBJC_CLASS_RO_$_SubClass' + - '__OBJC_METACLASS_RO_$_SimpleInternalAPI' + - '__OBJC_CLASS_RO_$_SimpleInternalAPI' + - '__OBJC_METACLASS_RO_$_SimpleInternalSPI' + - '__OBJC_CLASS_RO_$_SimpleInternalSPI' + - '__OBJC_CLASS_RO_$_Basic1' + - '__OBJC_METACLASS_RO_$_Basic1' + - '__OBJC_METACLASS_RO_$_Basic2' + - '__OBJC_CLASS_RO_$_Basic2' + - '__OBJC_METACLASS_RO_$_Basic3' + - '__OBJC_$_INSTANCE_METHODS_Basic3' + - '__OBJC_$_INSTANCE_VARIABLES_Basic3' + - '__OBJC_$_PROP_LIST_Basic3' + - '__OBJC_CLASS_RO_$_Basic3' + - '__OBJC_METACLASS_RO_$_Basic4' + - '__OBJC_$_INSTANCE_VARIABLES_Basic4' + - '__OBJC_CLASS_RO_$_Basic4' + - '__OBJC_METACLASS_RO_$_Basic4_1' + - '__OBJC_$_INSTANCE_VARIABLES_Basic4_1' + - '__OBJC_CLASS_RO_$_Basic4_1' + - '__OBJC_METACLASS_RO_$_Basic4_2' + - '__OBJC_$_INSTANCE_VARIABLES_Basic4_2' + - '__OBJC_CLASS_RO_$_Basic4_2' + - '__OBJC_$_CLASS_METHODS_Basic5' + - '__OBJC_METACLASS_RO_$_Basic5' + - '__OBJC_$_INSTANCE_METHODS_Basic5' + - '__OBJC_CLASS_RO_$_Basic5' + - '__OBJC_METACLASS_RO_$_Basic6' + - '__OBJC_$_INSTANCE_METHODS_Basic6' + - '__OBJC_$_INSTANCE_VARIABLES_Basic6' + - '__OBJC_$_PROP_LIST_Basic6' + - '__OBJC_CLASS_RO_$_Basic6' + - '__OBJC_$_CATEGORY_INSTANCE_METHODS_Basic6_$_Foo' + - '__OBJC_$_PROP_LIST_Basic6_$_Foo' + - '__OBJC_$_CATEGORY_Basic6_$_Foo' + - '__OBJC_METACLASS_RO_$_Basic7' + - '__OBJC_$_INSTANCE_METHODS_Basic7' + - '__OBJC_CLASS_RO_$_Basic7' + - '__OBJC_METACLASS_RO_$_ExternalManagedObject' + - '__OBJC_$_INSTANCE_METHODS_ExternalManagedObject' + - '__OBJC_CLASS_RO_$_ExternalManagedObject' + - '__OBJC_$_CATEGORY_INSTANCE_METHODS_NSManagedObject_$_Simple' + - '__OBJC_$_CATEGORY_NSManagedObject_$_Simple' + - '__OBJC_METACLASS_RO_$_HiddenClass' + - '__OBJC_CLASS_RO_$_HiddenClass' + - '__OBJC_$_CLASS_METHODS_Basic8' + - '__OBJC_METACLASS_RO_$_Basic8' + - '__OBJC_$_INSTANCE_METHODS_Basic8' + - '__OBJC_CLASS_RO_$_Basic8' + - '__OBJC_METACLASS_RO_$_A' + - '__OBJC_$_INSTANCE_METHODS_A' + - '__OBJC_CLASS_RO_$_A' + - '__OBJC_METACLASS_RO_$_Basic9' + - '__OBJC_$_INSTANCE_METHODS_Basic9' + - '__OBJC_$_INSTANCE_VARIABLES_Basic9' + - '__OBJC_$_PROP_LIST_Basic9' + - '__OBJC_CLASS_RO_$_Basic9' + - '__OBJC_$_PROP_LIST_Basic9_$_deprecated' + - '__OBJC_$_CATEGORY_Basic9_$_deprecated' + - '__OBJC_CLASS_RO_$_FooClass' + - '__OBJC_METACLASS_RO_$_FooClass' + - '__OBJC_$_PROTOCOL_INSTANCE_METHODS_BaseProtocol' + - '__OBJC_$_PROTOCOL_METHOD_TYPES_BaseProtocol' + - '__OBJC_$_PROTOCOL_REFS_FooProtocol' + - '__OBJC_$_PROTOCOL_INSTANCE_METHODS_FooProtocol' + - '__OBJC_$_PROTOCOL_METHOD_TYPES_FooProtocol' + - '__OBJC_$_PROTOCOL_INSTANCE_METHODS_BarProtocol' + - '__OBJC_$_PROTOCOL_METHOD_TYPES_BarProtocol' + - '__OBJC_CLASS_PROTOCOLS_$_FooClass' + - '__OBJC_$_INSTANCE_METHODS_FooClass' + - '__OBJC_$_CATEGORY_INSTANCE_METHODS_FooClass_$_Private' + - '__OBJC_$_PROTOCOL_INSTANCE_METHODS_PrivateProtocol' + - '__OBJC_$_PROTOCOL_METHOD_TYPES_PrivateProtocol' + - '__OBJC_CATEGORY_PROTOCOLS_$_FooClass_$_Private' + - '__OBJC_$_CATEGORY_FooClass_$_Private' + - _extraGlobalAPI1 + - _extraGlobalAPI2 + - _privateGlobalVariable + - _publicGlobalVariable + - '_OBJC_EHTYPE_$_Base' + - '_OBJC_EHTYPE_$_SubClass' + - '_OBJC_EHTYPE_$_SimpleInternalAPI' + - '_OBJC_EHTYPE_$_SimpleInternalSPI' + - '_OBJC_METACLASS_$_Simple' + - '_OBJC_CLASS_$_Simple' + - '_OBJC_METACLASS_$_Base' + - '_OBJC_CLASS_$_Base' + - '_OBJC_METACLASS_$_SubClass' + - '_OBJC_CLASS_$_SubClass' + - '_OBJC_METACLASS_$_SimpleInternalAPI' + - '_OBJC_CLASS_$_SimpleInternalAPI' + - '_OBJC_METACLASS_$_SimpleInternalSPI' + - '_OBJC_CLASS_$_SimpleInternalSPI' + - '_OBJC_CLASS_$_Basic1' + - '_OBJC_METACLASS_$_Basic1' + - '_OBJC_METACLASS_$_Basic2' + - '_OBJC_CLASS_$_Basic2' + - '_OBJC_METACLASS_$_Basic3' + - '_OBJC_CLASS_$_Basic3' + - '_OBJC_METACLASS_$_Basic4' + - '_OBJC_CLASS_$_Basic4' + - '_OBJC_METACLASS_$_Basic4_1' + - '_OBJC_CLASS_$_Basic4_1' + - '_OBJC_METACLASS_$_Basic4_2' + - '_OBJC_CLASS_$_Basic4_2' + - '_OBJC_METACLASS_$_Basic5' + - '_OBJC_CLASS_$_Basic5' + - '_OBJC_METACLASS_$_Basic6' + - '_OBJC_CLASS_$_Basic6' + - '_OBJC_METACLASS_$_Basic7' + - '_OBJC_CLASS_$_Basic7' + - '_OBJC_METACLASS_$_ExternalManagedObject' + - '_OBJC_CLASS_$_ExternalManagedObject' + - '_OBJC_METACLASS_$_HiddenClass' + - '_OBJC_CLASS_$_HiddenClass' + - '_OBJC_METACLASS_$_Basic8' + - '_OBJC_CLASS_$_Basic8' + - '_OBJC_METACLASS_$_A' + - '_OBJC_CLASS_$_A' + - '_OBJC_METACLASS_$_Basic9' + - '_OBJC_CLASS_$_Basic9' + - '_OBJC_CLASS_$_FooClass' + - '_OBJC_METACLASS_$_FooClass' + - '_OBJC_IVAR_$_Basic3.property1' + - '_OBJC_IVAR_$_Basic3.property2' + - '_OBJC_IVAR_$_Basic3.property3' + - '_OBJC_IVAR_$_Basic4.ivar1' + - '_OBJC_IVAR_$_Basic4.ivar2' + - '_OBJC_IVAR_$_Basic4.ivar3' + - '_OBJC_IVAR_$_Basic4.ivar4' + - '_OBJC_IVAR_$_Basic4_1.ivar1' + - '_OBJC_IVAR_$_Basic4_1.ivar2' + - '_OBJC_IVAR_$_Basic4_1.ivar3' + - '_OBJC_IVAR_$_Basic4_1.ivar4' + - '_OBJC_IVAR_$_Basic4_2.ivar4' + - '_OBJC_IVAR_$_Basic4_2.ivar3' + - '_OBJC_IVAR_$_Basic4_2.ivar2' + - '_OBJC_IVAR_$_Basic4_2.ivar1' + - '_OBJC_IVAR_$_Basic6.ivar1' + - '_OBJC_IVAR_$_Basic6.property1' + - '_OBJC_IVAR_$_Basic9._aProperty' + - '__OBJC_PROTOCOL_$_BaseProtocol' + - '__OBJC_PROTOCOL_$_FooProtocol' + - '__OBJC_PROTOCOL_$_BarProtocol' + - '__OBJC_PROTOCOL_$_PrivateProtocol' + - _weakPublicGlobalVariable + - _weakPrivateGlobalVariable + - '__OBJC_LABEL_PROTOCOL_$_BaseProtocol' + - '__OBJC_LABEL_PROTOCOL_$_FooProtocol' + - '__OBJC_LABEL_PROTOCOL_$_BarProtocol' + - '__OBJC_LABEL_PROTOCOL_$_PrivateProtocol' + - '_OBJC_CLASS_$_NSManagedObject' + - '_OBJC_CLASS_$_NSObject' + - '_OBJC_METACLASS_$_NSManagedObject' + - '_OBJC_METACLASS_$_NSObject' + - __objc_empty_cache + - _objc_ehtype_vtable + - dyld_stub_binder + - '' + - '' + FunctionStarts: [ 0x1BC0, 0x1BCA, 0x1BD3, 0x1BDD, 0x1BE7, 0x1BF0, 0x1BF6, + 0x1BFC, 0x1C02, 0x1C0C, 0x1C15, 0x1C20, 0x1C26, 0x1C2C, + 0x1C32, 0x1C38, 0x1C40, 0x1C46, 0x1C4C, 0x1C52, 0x1C5C, + 0x1C62, 0x1C68, 0x1C6E ] +... diff --git a/clang/test/InstallAPI/Inputs/Simple/SimpleInternalAPI.h b/clang/test/InstallAPI/Inputs/Simple/SimpleInternalAPI.h new file mode 100644 index 0000000000000000000000000000000000000000..5dd416a0619cfb1c5185a6c5be00af90a4d588e0 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/SimpleInternalAPI.h @@ -0,0 +1,3 @@ +#ifndef HAVE_SEEN_PROJECT_HEADER_FIRST +#error "Project header was not included in the correct order!" +#endif diff --git a/clang/test/InstallAPI/Inputs/Simple/SimpleInternalAPI2.h b/clang/test/InstallAPI/Inputs/Simple/SimpleInternalAPI2.h new file mode 100644 index 0000000000000000000000000000000000000000..9bbae52d721538588333ae0d4c15fd276b5e9bf1 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/SimpleInternalAPI2.h @@ -0,0 +1,7 @@ +#import <Foundation/Foundation.h> + +__attribute__((objc_exception)) +@interface SimpleInternalAPI : NSObject +@end + +#define HAVE_SEEN_PROJECT_HEADER_FIRST 1 diff --git a/clang/test/InstallAPI/Inputs/Simple/SimpleInternalSPI.h b/clang/test/InstallAPI/Inputs/Simple/SimpleInternalSPI.h new file mode 100644 index 0000000000000000000000000000000000000000..a816c01abeb0d2c03303700417f89c07edfa1242 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Simple/SimpleInternalSPI.h @@ -0,0 +1,5 @@ +#import <Foundation/Foundation.h> + +__attribute__((objc_exception)) +@interface SimpleInternalSPI : NSObject +@end diff --git a/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/AAA.h b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/AAA.h new file mode 100644 index 0000000000000000000000000000000000000000..993d5d4abadb8e685a2e171701ae6845623ea98b --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/AAA.h @@ -0,0 +1,3 @@ +#ifndef PUBLIC_UMBRELLA_HEADER_FIRST +#error "Public umbrella header was not included first!" +#endif diff --git a/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/SpecialUmbrella.h b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/SpecialUmbrella.h new file mode 100644 index 0000000000000000000000000000000000000000..2599ff14ae1723b0bf67790519089714c35a2a76 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/Headers/SpecialUmbrella.h @@ -0,0 +1 @@ +#define PUBLIC_UMBRELLA_HEADER_FIRST diff --git a/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/AAA_Private.h b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/AAA_Private.h new file mode 100644 index 0000000000000000000000000000000000000000..557209bfeb86993e591de3587497cf4358432ca4 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/AAA_Private.h @@ -0,0 +1,3 @@ +#ifndef PRIVATE_UMBRELLA_HEADER_FIRST +#error "Private umbrella header was not included first!" +#endif diff --git a/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h new file mode 100644 index 0000000000000000000000000000000000000000..fd5b49b943161a7d088a88b39f71a77d04453b74 --- /dev/null +++ b/clang/test/InstallAPI/Inputs/Umbrella/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h @@ -0,0 +1 @@ +#define PRIVATE_UMBRELLA_HEADER_FIRST diff --git a/clang/test/InstallAPI/asm.test b/clang/test/InstallAPI/asm.test new file mode 100644 index 0000000000000000000000000000000000000000..b6af7f643d72f2253bcd3420323838b68996130b --- /dev/null +++ b/clang/test/InstallAPI/asm.test @@ -0,0 +1,90 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json + +// RUN: clang-installapi -target arm64-apple-macos13.1 \ +// RUN: -I%t/usr/include \ +// RUN: -install_name @rpath/lib/libasm.dylib \ +// RUN: %t/inputs.json -o %t/output.tbd 2>&1 | FileCheck %s --allow-empty +// RUN: llvm-readtapi -compare %t/output.tbd %t/expected.tbd 2>&1 | FileCheck %s --allow-empty + +// CHECK-NOT: error: +// CHECK-NOT: warning: + +//--- usr/include/asm.h +#ifndef ASM_H +#define ASM_H + +extern int ivar __asm("_OBJC_IVAR_$_SomeClass._ivar1"); +extern int objcClass1 __asm("_OBJC_CLASS_$_SomeClass"); +extern int objcClass2 __asm("_OBJC_METACLASS_$_SomeClass"); +extern int objcClass3 __asm("_OBJC_EHTYPE_$_SomeClass"); +extern int objcClass4 __asm(".objc_class_name_SomeClass"); + +__attribute__((visibility("hidden"))) +@interface NSString { +} +@end + +extern int ivarExtra __asm("_OBJC_IVAR_$_NSString._ivar1"); +#endif // ASM_H + +//--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/usr/include/asm.h", + "type" : "public" + }], + "version": "3" +} + +//--- expected.tbd +{ + "main_library": { + "compatibility_versions": [ + { + "version": "0" + } + ], + "current_versions": [ + { + "version": "0" + } + ], + "exported_symbols": [ + { + "data": { + "objc_class": [ + "SomeClass" + ], + "objc_eh_type": [ + "SomeClass" + ], + "objc_ivar": [ + "NSString._ivar1", + "SomeClass._ivar1" + ] + } + } + ], + "flags": [ + { + "attributes": [ + "not_app_extension_safe" + ] + } + ], + "install_names": [ + { + "name": "@rpath/lib/libasm.dylib" + } + ], + "target_info": [ + { + "min_deployment": "13.1", + "target": "arm64-macos" + } + ] + }, + "tapi_tbd_version": 5 +} diff --git a/clang/test/InstallAPI/availability.test b/clang/test/InstallAPI/availability.test new file mode 100644 index 0000000000000000000000000000000000000000..55c890b6d882ae046d5e249376b9b2c2e002288a --- /dev/null +++ b/clang/test/InstallAPI/availability.test @@ -0,0 +1,631 @@ +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json + +; RUN: yaml2obj %t/Availability.yaml -o %t/System/Library/Frameworks/Availability.framework/Availability + +; RUN: clang-installapi \ +; RUN: --target=x86_64-apple-macos13 \ +; RUN: -install_name /System/Library/Frameworks/Availability.framework/Versions/A/Availability \ +; RUN: -current_version 1 -compatibility_version 1 \ +; RUN: -F %t/System/Library/Frameworks \ +; RUN: %t/inputs.json -o %t/output.tbd \ +; RUN: --verify-against=%t/System/Library/Frameworks/Availability.framework/Availability \ +; RUN: --verify-mode=ErrorsOnly --filetype=tbd-v5 2> %t/errors.log +; RUN: FileCheck -allow-empty -check-prefix=ERRORSONLY -input-file %t/errors.log %s + +; RUN: clang-installapi \ +; RUN: --target=x86_64-apple-macos13 \ +; RUN: -install_name /System/Library/Frameworks/Availability.framework/Versions/A/Availability \ +; RUN: -current_version 1 -compatibility_version 1 \ +; RUN: -F %t/System/Library/Frameworks \ +; RUN: %t/inputs.json -o %t/output-warnings.tbd \ +; RUN: --verify-against=%t/System/Library/Frameworks/Availability.framework/Availability \ +; RUN: --verify-mode=ErrorsAndWarnings 2> %t/errors.log +; RUN: FileCheck -check-prefixes=VIOLATIONS,ERRORSANDWARNINGS -input-file %t/errors.log %s + +; RUN: not clang-installapi \ +; RUN: --target=x86_64-apple-macos13 \ +; RUN: -install_name /System/Library/Frameworks/Availability.framework/Versions/A/Availability \ +; RUN: -current_version 1 -compatibility_version 1 \ +; RUN: -F %t/System/Library/Frameworks \ +; RUN: %t/inputs.json -o %t/output-pedantic.tbd \ +; RUN: --verify-against=%t/System/Library/Frameworks/Availability.framework/Availability \ +; RUN: --verify-mode=Pedantic 2> %t/errors.log +; RUN: FileCheck -check-prefixes=VIOLATIONS,PEDANTIC -input-file %t/errors.log %s + +; ERRORSONLY-NOT: error +; ERRORSONLY-NOT: warning + +; ERRORSANDWARNINGS-NOT: error +; VIOLATIONS: warning: violations found for x86_64-apple-macos +; VIOLATIONS: declaration 'publicGlobalVariable' is marked unavailable, but symbol is exported in dynamic library +; VIOLATIONS-NEXT: extern int publicGlobalVariable NS_AVAILABLE +; VIOLATIONS: declaration 'Foo' is marked unavailable, but symbol is exported in dynamic library +; VIOLATIONS-NEXT: @interface Foo : NSObject +; VIOLATIONS: declaration 'publicGlobalVariable3' is marked unavailable, but symbol is exported in dynamic library +; VIOLATIONS-NEXT: extern int publicGlobalVariable3 __attribute__((unavailable)) +; VIOLATIONS: declaration 'privateGlobalVariable' is marked unavailable, but symbol is exported in dynamic library +; VIOLATIONS-NEXT: extern int privateGlobalVariable; + +; ERRORSANDWARNINGS-NOT: warning +; PEDANTIC-NOT: error + +;--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/System/Library/Frameworks/Availability.framework/Headers/Availability.h", + "type" : "public" + }, + { + "path" : "DSTROOT/System/Library/Frameworks/Availability.framework/PrivateHeaders/AvailabilityPrivate.h", + "type" : "private" + } + ], + "version": "3" +} + +;--- System/Library/Frameworks/Availability.framework/Headers/AV_Defines.h +#ifndef AV_DEFINES +#define AV_DEFINES + +#define NS_AVAILABLE __attribute__((availability(macosx,introduced=NA))) + +@interface NSObject +@end + +#endif //AV_DEFINES + +;--- System/Library/Frameworks/Availability.framework/PrivateHeaders/AvailabilityPrivate.h +#import <Availability/AV_Defines.h> +// Test private global variable. +NS_AVAILABLE +extern int privateGlobalVariable; + +;--- System/Library/Frameworks/Availability.framework/Headers/Availability.h +#import <Availability/AV_Defines.h> +extern int publicGlobalVariable NS_AVAILABLE; + +// Test public ObjC class +NS_AVAILABLE +@interface Foo : NSObject +@end + +// Test unavailable attribute. +#ifdef __i386__ +#define UNAVAILABLE_I386 __attribute__((unavailable)) +#else +#define UNAVAILABLE_I386 +#endif +extern int publicGlobalVariable2 UNAVAILABLE_I386; + +extern int publicGlobalVariable3 __attribute__((unavailable)) +__attribute__((availability(macosx, introduced = 10.9))); + +// Test obsoleted with exported variable. +extern int publicGlobalVariable4 __attribute__((availability( + macosx, introduced = 10.9, deprecated = 10.10, obsoleted = 10.11))); +// Test obsoleted with non-existent variable. +extern int publicGlobalVariable5 __attribute__((availability( + macosx, introduced = 10.9, deprecated = 10.10, obsoleted = 10.11))); + +#ifdef __i386__ +#define OBSOLETE_I386 __attribute__((availability(macosx, obsoleted = 10.11))) +#else +#define OBSOLETE_I386 +#endif +extern int publicGlobalVariable6 OBSOLETE_I386; + + +/// Created from: +// int publicGlobalVariable; int privateGlobalVariable; +// +// @implementation Foo +// @end +// +// #ifndef __i386__ +// int publicGlobalVariable2; +// #endif +// +// int publicGlobalVariable3; +// int publicGlobalVariable4; +// +// #ifndef __i386__ +// int publicGlobalVariable6; +// #endif +;--- Availability.yaml +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x1000007 + cpusubtype: 0x3 + filetype: 0x6 + ncmds: 14 + sizeofcmds: 1312 + flags: 0x100085 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __TEXT + vmaddr: 0 + vmsize: 8192 + fileoff: 0 + filesize: 8192 + maxprot: 5 + initprot: 5 + nsects: 2 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x1140 + size: 0 + offset: 0x1140 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x80000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '' + - sectname: __cstring + segname: __TEXT + addr: 0x1140 + size: 4 + offset: 0x1140 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x2 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 466F6F00 + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __DATA_CONST + vmaddr: 8192 + vmsize: 4096 + fileoff: 8192 + filesize: 4096 + maxprot: 3 + initprot: 3 + nsects: 2 + flags: 16 + Sections: + - sectname: __objc_classlist + segname: __DATA_CONST + addr: 0x2000 + size: 8 + offset: 0x2000 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x10000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: B830000000000000 + - sectname: __objc_imageinfo + segname: __DATA_CONST + addr: 0x2008 + size: 8 + offset: 0x2008 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '0000000040000000' + - cmd: LC_SEGMENT_64 + cmdsize: 312 + segname: __DATA + vmaddr: 12288 + vmsize: 4096 + fileoff: 12288 + filesize: 4096 + maxprot: 3 + initprot: 3 + nsects: 3 + flags: 0 + Sections: + - sectname: __objc_const + segname: __DATA + addr: 0x3000 + size: 144 + offset: 0x3000 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '010000002800000028000000000000000000000000000000401100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000008000000000000000000000000000000401100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' + - sectname: __objc_data + segname: __DATA + addr: 0x3090 + size: 80 + offset: 0x3090 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '0000000000000000000000000000000000000000000000000000000000000000003000000000000090300000000000000000000000000000000000000000000000000000000000004830000000000000' + - sectname: __common + segname: __DATA + addr: 0x30E0 + size: 24 + offset: 0x0 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x1 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 16384 + vmsize: 824 + fileoff: 16384 + filesize: 824 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 16384 + rebase_size: 16 + bind_off: 16400 + bind_size: 104 + weak_bind_off: 0 + weak_bind_size: 0 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 16504 + export_size: 152 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 16664 + nsyms: 14 + stroff: 16888 + strsize: 320 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 2 + iextdefsym: 2 + nextdefsym: 8 + iundefsym: 10 + nundefsym: 4 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_ID_DYLIB + cmdsize: 112 + dylib: + name: 24 + timestamp: 0 + current_version: 65536 + compatibility_version: 65536 + Content: '/System/Library/Frameworks/Availability.framework/Versions/A/Availability' + ZeroPadBytes: 7 + - cmd: LC_UUID + cmdsize: 24 + uuid: 4C4C4470-5555-3144-A142-4EE44DA08D2F + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 851968 + sdk: 983040 + ntools: 1 + Tools: + - tool: 4 + version: 1245184 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 14942208 + compatibility_version: 65536 + Content: '/usr/lib/libobjc.A.dylib' + ZeroPadBytes: 8 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 88473600 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 16656 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 16664 + datasize: 0 +LinkEditData: + RebaseOpcodes: + - Opcode: REBASE_OPCODE_SET_TYPE_IMM + Imm: 1 + - Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + Imm: 1 + ExtraData: [ 0x0 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 1 + - Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + Imm: 2 + ExtraData: [ 0x18 ] + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x2, 0x40 ] + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 3 + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 1 + - Opcode: REBASE_OPCODE_DONE + Imm: 0 + BindOpcodes: + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: '_OBJC_METACLASS_$_NSObject' + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + Imm: 2 + ULEBExtraData: [ 0x90 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: __objc_empty_cache + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x20 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: '_OBJC_CLASS_$_NSObject' + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0xFFFFFFFFFFFFFFF0 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DONE + Imm: 0 + Symbol: '' + ExportTrie: + TerminalSize: 0 + NodeOffset: 0 + Name: '' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 5 + Name: _ + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 17 + Name: OBJC_ + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 49 + Name: 'METACLASS_$_Foo' + Flags: 0x0 + Address: 0x3090 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 54 + Name: 'CLASS_$_Foo' + Flags: 0x0 + Address: 0x30B8 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 59 + Name: p + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 104 + Name: rivateGlobalVariable + Flags: 0x0 + Address: 0x30E0 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 109 + Name: ublicGlobalVariable + Flags: 0x0 + Address: 0x30E4 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 130 + Name: '4' + Flags: 0x0 + Address: 0x30F0 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 135 + Name: '3' + Flags: 0x0 + Address: 0x30EC + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 140 + Name: '2' + Flags: 0x0 + Address: 0x30E8 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 145 + Name: '6' + Flags: 0x0 + Address: 0x30F4 + Other: 0x0 + ImportName: '' + NameList: + - n_strx: 2 + n_type: 0xE + n_sect: 5 + n_desc: 0 + n_value: 12288 + - n_strx: 28 + n_type: 0xE + n_sect: 5 + n_desc: 0 + n_value: 12360 + - n_strx: 50 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 12512 + - n_strx: 73 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 12516 + - n_strx: 95 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 12520 + - n_strx: 118 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 12524 + - n_strx: 141 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 12528 + - n_strx: 164 + n_type: 0xF + n_sect: 7 + n_desc: 0 + n_value: 12532 + - n_strx: 187 + n_type: 0xF + n_sect: 6 + n_desc: 0 + n_value: 12432 + - n_strx: 209 + n_type: 0xF + n_sect: 6 + n_desc: 0 + n_value: 12472 + - n_strx: 227 + n_type: 0x1 + n_sect: 0 + n_desc: 256 + n_value: 0 + - n_strx: 250 + n_type: 0x1 + n_sect: 0 + n_desc: 256 + n_value: 0 + - n_strx: 277 + n_type: 0x1 + n_sect: 0 + n_desc: 256 + n_value: 0 + - n_strx: 296 + n_type: 0x1 + n_sect: 0 + n_desc: 512 + n_value: 0 + StringTable: + - ' ' + - '__OBJC_METACLASS_RO_$_Foo' + - '__OBJC_CLASS_RO_$_Foo' + - _privateGlobalVariable + - _publicGlobalVariable + - _publicGlobalVariable2 + - _publicGlobalVariable3 + - _publicGlobalVariable4 + - _publicGlobalVariable6 + - '_OBJC_METACLASS_$_Foo' + - '_OBJC_CLASS_$_Foo' + - '_OBJC_CLASS_$_NSObject' + - '_OBJC_METACLASS_$_NSObject' + - __objc_empty_cache + - dyld_stub_binder + - '' + - '' + - '' + - '' + - '' + - '' + - '' +... diff --git a/clang/test/InstallAPI/basic.test b/clang/test/InstallAPI/basic.test index 5b41ccd517b0afe667b08b6a52b892f61b96fa05..096911039d114e4fceed2e681a43634bd8b7c258 100644 --- a/clang/test/InstallAPI/basic.test +++ b/clang/test/InstallAPI/basic.test @@ -2,7 +2,8 @@ // RUN: split-file %s %t /// Check basic arguments are captured. // RUN: clang-installapi -x objective-c -target arm64-apple-ios13.0.0 \ -// RUN: -fapplication-extension -current_version 1 -install_name /usr/lib/basic.dylib \ +// RUN: -fapplication-extension -current_version 1 -compatibility_version 1 \ +// RUN: -install_name /usr/lib/basic.dylib \ // RUN: %t/basic_inputs.json -o %t/basic.tbd 2>&1 | FileCheck %s --allow-empty // RUN: llvm-readtapi -compare %t/basic.tbd %t/expected.tbd 2>&1 | FileCheck %s --allow-empty @@ -25,11 +26,6 @@ //--- expected.tbd { "main_library": { - "compatibility_versions": [ - { - "version": "0" - } - ], "install_names": [ { "name": "/usr/lib/basic.dylib" diff --git a/clang/test/InstallAPI/diagnostics-cpp.test b/clang/test/InstallAPI/diagnostics-cpp.test new file mode 100644 index 0000000000000000000000000000000000000000..51cca129ea0af2fb0f8009e7c1eefea850a5dc1b --- /dev/null +++ b/clang/test/InstallAPI/diagnostics-cpp.test @@ -0,0 +1,464 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json + +// RUN: yaml2obj %t/Mismatch.yaml -o %t/System/Library/Frameworks/MismatchCpp.framework/MismatchCpp + +// RUN: not clang-installapi --target=arm64-apple-macos13 -x objective-c++ \ +// RUN: -F %t/System/Library/Frameworks \ +// RUN: -install_name /System/Library/Frameworks/MismatchCpp.framework/Versions/A/MismatchCpp \ +// RUN: -current_version 1 -compatibility_version 1 %t/inputs.json \ +// RUN: --verify-against=%t/System/Library/Frameworks/MismatchCpp.framework/MismatchCpp \ +// RUN: --verify-mode=Pedantic -o %t/output.tbd --demangle 2> %t/errors.log +// RUN: FileCheck -input-file %t/errors.log %s + +CHECK: warning: violations found for arm64-apple-macos13 +CHECK: CPP.h:5:7: error: declaration has external linkage, but symbol has internal linkage in dynamic library 'vtable for Bar' +CHECK-NEXT: class Bar : Foo { +CHECK-NEXT: ^ +CHECK-NEXT: CPP.h:5:7: error: declaration has external linkage, but symbol has internal linkage in dynamic library 'typeinfo for Bar' +CHECK-NEXT: CPP.h:5:7: error: declaration has external linkage, but symbol has internal linkage in dynamic library 'typeinfo name for Bar' +CHECK-NEXT: CPP.h:6:7: error: dynamic library symbol '(weak-def) Bar::init()' is weak defined, but its declaration is not +CHECK-NEXT: int init(); +CHECK-NEXT: ^ +CHECK-NEXT: warning: violations found for arm64 +CHECK-NEXT: error: no declaration found for exported symbol 'int foo<unsigned int>(unsigned int)' in dynamic library + +//--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/System/Library/Frameworks/MismatchCpp.framework/Headers/CPP.h", + "type" : "public" + } + ], + "version": "3" +} + +//--- System/Library/Frameworks/MismatchCpp.framework/Headers/CPP.h +class Foo { + virtual int init() = 0; +}; + +class Bar : Foo { + int init(); +}; + +/// Created from: +// With LD flags: -exported_symbol,"__ZN3Bar4initEv" -exported_symbol,"__Z3fooIjEiT_" +// class Foo { virtual int init() = 0;}; +// +// class Bar : Foo {int init() { return 1;}}; +// Bar bar; +// +// template <typename T> int foo(T val) { return 1; } +// template <> int foo(unsigned val) { return 1; } + +//--- Mismatch.yaml +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x100000C + cpusubtype: 0x0 + filetype: 0x6 + ncmds: 15 + sizeofcmds: 1224 + flags: 0x118085 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 312 + segname: __TEXT + vmaddr: 0 + vmsize: 16384 + fileoff: 0 + filesize: 16384 + maxprot: 5 + initprot: 5 + nsects: 3 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x10E8 + size: 16 + offset: 0x10E8 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 20008052C0035FD620008052C0035FD6 + - sectname: __const + segname: __TEXT + addr: 0x10F8 + size: 10 + offset: 0x10F8 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 334261720033466F6F00 + - sectname: __unwind_info + segname: __TEXT + addr: 0x1104 + size: 4152 + offset: 0x1104 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 010000001C000000010000002000000000000000200000000200000000000002E81000003800000038000000F81000000000000038000000030000000C0001001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __DATA_CONST + vmaddr: 16384 + vmsize: 16384 + fileoff: 16384 + filesize: 16384 + maxprot: 3 + initprot: 3 + nsects: 2 + flags: 16 + Sections: + - sectname: __const + segname: __DATA_CONST + addr: 0x4000 + size: 80 + offset: 0x4000 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 00000000000000002840000000000000F0100000000000001000000000000000FD100000000000801000000000000000F810000000000080000000000100000018400000000000000000000000000000 + - sectname: __objc_imageinfo + segname: __DATA_CONST + addr: 0x4050 + size: 8 + offset: 0x4050 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '0000000040000000' + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __DATA + vmaddr: 32768 + vmsize: 16384 + fileoff: 32768 + filesize: 16384 + maxprot: 3 + initprot: 3 + nsects: 1 + flags: 0 + Sections: + - sectname: __data + segname: __DATA + addr: 0x8000 + size: 8 + offset: 0x8000 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '1040000000000000' + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 49152 + vmsize: 1104 + fileoff: 49152 + filesize: 1104 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 49152 + rebase_size: 16 + bind_off: 49168 + bind_size: 96 + weak_bind_off: 49264 + weak_bind_size: 24 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 49288 + export_size: 48 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 49344 + nsyms: 11 + stroff: 49520 + strsize: 192 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 6 + iextdefsym: 6 + nextdefsym: 2 + iundefsym: 8 + nundefsym: 3 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_ID_DYLIB + cmdsize: 96 + dylib: + name: 24 + timestamp: 0 + current_version: 65536 + compatibility_version: 65536 + Content: '/System/Library/Frameworks/MismatchCpp.framework/Versions/A/MismatchCpp' + ZeroPadBytes: 1 + - cmd: LC_UUID + cmdsize: 24 + uuid: 4C4C44F3-5555-3144-A13F-B3FE15787197 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 851968 + sdk: 983040 + ntools: 1 + Tools: + - tool: 4 + version: 1245184 + - cmd: LC_LOAD_DYLIB + cmdsize: 48 + dylib: + name: 24 + timestamp: 0 + current_version: 117985024 + compatibility_version: 65536 + Content: '/usr/lib/libc++.1.dylib' + ZeroPadBytes: 1 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 88473600 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 49336 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 49344 + datasize: 0 + - cmd: LC_CODE_SIGNATURE + cmdsize: 16 + dataoff: 49712 + datasize: 544 +LinkEditData: + RebaseOpcodes: + - Opcode: REBASE_OPCODE_SET_TYPE_IMM + Imm: 1 + - Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + Imm: 1 + ExtraData: [ 0x8 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 2 + - Opcode: REBASE_OPCODE_ADD_ADDR_IMM_SCALED + Imm: 1 + - Opcode: REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB + Imm: 0 + ExtraData: [ 0x3, 0x8 ] + - Opcode: REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + Imm: 2 + ExtraData: [ 0x0 ] + - Opcode: REBASE_OPCODE_DO_REBASE_IMM_TIMES + Imm: 1 + - Opcode: REBASE_OPCODE_DONE + Imm: 0 + BindOpcodes: + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: __ZTVN10__cxxabiv117__class_type_infoE + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + Imm: 1 + ULEBExtraData: [ 0x18 ] + Symbol: '' + - Opcode: BIND_OPCODE_SET_ADDEND_SLEB + Imm: 0 + SLEBExtraData: [ 16 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: __ZTVN10__cxxabiv121__vmi_class_type_infoE + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_ADD_ADDR_ULEB + Imm: 0 + ULEBExtraData: [ 0x8 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DONE + Imm: 0 + Symbol: '' + WeakBindOpcodes: + - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + Imm: 0 + Symbol: __ZN3Bar4initEv + - Opcode: BIND_OPCODE_SET_TYPE_IMM + Imm: 1 + Symbol: '' + - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + Imm: 1 + ULEBExtraData: [ 0x10 ] + Symbol: '' + - Opcode: BIND_OPCODE_DO_BIND + Imm: 0 + Symbol: '' + - Opcode: BIND_OPCODE_DONE + Imm: 0 + Symbol: '' + ExportTrie: + TerminalSize: 0 + NodeOffset: 0 + Name: '' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 7 + Name: __Z + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 35 + Name: 3fooIjEiT_ + Flags: 0x0 + Address: 0x10E8 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 40 + Name: N3Bar4initEv + Flags: 0x4 + Address: 0x10F0 + Other: 0x0 + ImportName: '' + NameList: + - n_strx: 32 + n_type: 0x1E + n_sect: 4 + n_desc: 0 + n_value: 16384 + - n_strx: 42 + n_type: 0x1E + n_sect: 4 + n_desc: 0 + n_value: 16408 + - n_strx: 52 + n_type: 0x1E + n_sect: 4 + n_desc: 0 + n_value: 16424 + - n_strx: 62 + n_type: 0x1E + n_sect: 6 + n_desc: 0 + n_value: 32768 + - n_strx: 67 + n_type: 0x1E + n_sect: 2 + n_desc: 0 + n_value: 4344 + - n_strx: 77 + n_type: 0x1E + n_sect: 2 + n_desc: 0 + n_value: 4349 + - n_strx: 2 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 4328 + - n_strx: 16 + n_type: 0xF + n_sect: 1 + n_desc: 128 + n_value: 4336 + - n_strx: 87 + n_type: 0x1 + n_sect: 0 + n_desc: 256 + n_value: 0 + - n_strx: 126 + n_type: 0x1 + n_sect: 0 + n_desc: 256 + n_value: 0 + - n_strx: 169 + n_type: 0x1 + n_sect: 0 + n_desc: 512 + n_value: 0 + StringTable: + - ' ' + - __Z3fooIjEiT_ + - __ZN3Bar4initEv + - __ZTV3Bar + - __ZTI3Foo + - __ZTI3Bar + - _bar + - __ZTS3Bar + - __ZTS3Foo + - __ZTVN10__cxxabiv117__class_type_infoE + - __ZTVN10__cxxabiv121__vmi_class_type_infoE + - dyld_stub_binder + - '' + - '' + - '' + - '' + - '' + - '' + FunctionStarts: [ 0x10E8, 0x10F0 ] +... diff --git a/clang/test/InstallAPI/diagnostics-dsym.test b/clang/test/InstallAPI/diagnostics-dsym.test new file mode 100644 index 0000000000000000000000000000000000000000..c9cbeffef7bacc5ca126e94c9c42c536a6feb1a4 --- /dev/null +++ b/clang/test/InstallAPI/diagnostics-dsym.test @@ -0,0 +1,40 @@ +; REQUIRES: system-darwin +; REQUIRES: target-aarch64 + +; RUN: rm -rf %t +; RUN: split-file %s %t + +// Build a simple dylib with debug info. +; RUN: %clang --target=arm64-apple-macos11 -g -dynamiclib %t/foo.c \ +; RUN: -current_version 1 -compatibility_version 1 -L%t/usr/lib \ +; RUN: -save-temps \ +; RUN: -o %t/foo.dylib -install_name %t/foo.dylib +; RUN: dsymutil %t/foo.dylib -o %t/foo.dSYM + +; RUN: not clang-installapi -x c++ --target=arm64-apple-macos11 \ +; RUN: -install_name %t/foo.dylib \ +; RUN: -current_version 1 -compatibility_version 1 \ +; RUN: -o %t/output.tbd \ +; RUN: --verify-against=%t/foo.dylib --dsym=%t/foo.dSYM \ +; RUN: --verify-mode=Pedantic 2>&1 | FileCheck %s + +; CHECK: violations found for arm64 +; CHECK: foo.c:5:0: error: no declaration found for exported symbol 'bar' in dynamic library +; CHECK: foo.c:1:0: error: no declaration found for exported symbol 'foo' in dynamic library + +;--- foo.c +int foo(void) { + return 1; +} +extern char bar; +char bar = 'a'; + +;--- usr/lib/libSystem.tbd +--- !tapi-tbd +tbd-version: 4 +targets: [ arm64-macos ] +install-name: '/usr/lib/libSystem.B.dylib' +exports: + - targets: [ arm64-macos ] + symbols: [ dyld_stub_binder ] +... diff --git a/clang/test/InstallAPI/driver-invalid-options.test b/clang/test/InstallAPI/driver-invalid-options.test index a2e008e1eb03e7adc40bc58e242208570fd78414..69f3b2d66ab8b6f78741487344aeb0b2e44fb285 100644 --- a/clang/test/InstallAPI/driver-invalid-options.test +++ b/clang/test/InstallAPI/driver-invalid-options.test @@ -1,4 +1,9 @@ /// Check non-darwin triple is rejected. -// RUN: not clang-installapi -target x86_64-unknown-unknown %s 2> %t +// RUN: not clang-installapi -target x86_64-unknown-unknown %s -o tmp.tbd 2> %t // RUN: FileCheck --check-prefix INVALID_INSTALLAPI -input-file %t %s // INVALID_INSTALLAPI: error: unsupported option 'installapi' for target 'x86_64-unknown-unknown' + +/// Check that missing install_name is reported. +// RUN: not clang-installapi -target x86_64-apple-ios-simulator %s -o tmp.tbd 2> %t +// RUN: FileCheck --check-prefix INVALID_INSTALL_NAME -input-file %t %s +// INVALID_INSTALL_NAME: error: no install name specified: add -install_name <path> diff --git a/clang/test/InstallAPI/extra-exclude-headers.test b/clang/test/InstallAPI/extra-exclude-headers.test new file mode 100644 index 0000000000000000000000000000000000000000..663ca1a5d5000d8bb8a486bba3951499da3b9bcc --- /dev/null +++ b/clang/test/InstallAPI/extra-exclude-headers.test @@ -0,0 +1,207 @@ +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: mkdir -p %t/System/Library/Frameworks +; RUN: cp -r %S/Inputs/Simple/Simple.framework %t/System/Library/Frameworks/ +; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json +; RUN: yaml2obj %S/Inputs/Simple/Simple.yaml -o %t/Simple + +// Add exclude options. +; RUN: clang-installapi -target x86_64-apple-macosx10.12 \ +; RUN: -install_name /System/Library/Frameworks/Simple.framework/Versions/A/Simple \ +; RUN: -current_version 1.2.3 -compatibility_version 1 \ +; RUN: -F%t/System/Library/Frameworks \ +; RUN: %t/inputs.json -o %t/Simple.tbd \ +; RUN: --verify-against=%t/Simple --verify-mode=ErrorsAndWarnings \ +; RUN: --exclude-public-header=**/SimpleAPI.h \ +; RUN: --exclude-private-header=**/SimplePrivateSPI.h 2>&1 | FileCheck -check-prefix=WARNINGS %s +; RUN: llvm-readtapi -compare %t/Simple.tbd %t/expected-excluded.tbd + +// Add extra options. +; RUN: clang-installapi -target x86_64-apple-macosx10.12 \ +; RUN: -install_name /System/Library/Frameworks/Simple.framework/Versions/A/Simple \ +; RUN: -current_version 1.2.3 -compatibility_version 1 \ +; RUN: -F%t/System/Library/Frameworks \ +; RUN: %t/inputs.json -o %t/Simple.tbd \ +; RUN: --verify-against=%t/Simple --verify-mode=Pedantic \ +; RUN: --extra-project-header=%S/Inputs/Simple/SimpleInternalAPI2.h \ +; RUN: --extra-project-header=%S/Inputs/Simple/SimpleInternalAPI.h \ +; RUN: --extra-public-header=%S/Inputs/Simple/Extra \ +; RUN: --extra-private-header=%S/Inputs/Simple/SimpleInternalSPI.h \ +; RUN: --exclude-public-header=**/SimpleAPI.h \ +; RUN: --exclude-private-header=**/SimplePrivateSPI.h 2>&1 | FileCheck -check-prefix=PEDANTIC -allow-empty %s +; RUN: llvm-readtapi -compare %t/Simple.tbd %t/expected-extra.tbd + +// Check fatal missing file input. +; RUN: not clang-installapi -target x86_64-apple-macosx10.12 \ +; RUN: -install_name /System/Library/Frameworks/Simple.framework/Versions/A/Simple \ +; RUN: -current_version 1.2.3 -compatibility_version 1 \ +; RUN: -F%t/System/Library/Frameworks \ +; RUN: %t/inputs.json -o %t/Simple.tbd \ +; RUN: --extra-public-header=%S/Inputs/Simple/NoSuchFile.h 2>&1 | FileCheck -allow-empty -check-prefix=NOPUBLIC %s + +; WARNINGS: warning: no declaration was found for exported symbol '_extraGlobalAPI1' in dynamic library +; WARNINGS: warning: no declaration was found for exported symbol '_extraGlobalAPI2' in dynamic library +; WARNINGS: warning: no declaration was found for exported symbol '(ObjC Class) SimpleInternalSPI' in dynamic library +; WARNINGS: warning: no declaration was found for exported symbol '(ObjC Class) SimpleInternalAPI' in dynamic library + +; PEDANTIC-NOT: error +; PEDANTIC: warning: cannot find protocol definition for 'ForwardProcotol' + +; NOPUBLIC: error: no such public header file: + +;--- expected-excluded.tbd +{ + "main_library": { + "current_versions": [ + { + "version": "1.2.3" + } + ], + "exported_symbols": [ + { + "data": { + "global": [ + "_publicGlobalVariable", + "_privateGlobalVariable" + ], + "objc_class": [ + "ExternalManagedObject", "Basic6", + "Basic1", "Base", "Basic3", + "FooClass", "Simple", + "Basic4_2", "Basic5", + "Basic9","Basic8", + "Basic2", "Basic4", "A", "SubClass" + ], + "objc_eh_type": [ + "SubClass", "Base" + ], + "objc_ivar": [ + "Basic4.ivar2", "Basic4_2.ivar1", "Basic6.ivar1", + "Basic4.ivar1", "Basic4_2.ivar2" + ], + "weak": [ + "_weakPrivateGlobalVariable", "_weakPublicGlobalVariable" + ] + } + } + ], + "flags": [ + { + "attributes": ["not_app_extension_safe"] + } + ], + "install_names": [ + { + "name": "/System/Library/Frameworks/Simple.framework/Versions/A/Simple" + } + ], + "target_info": [ + {"min_deployment": "10.12", "target": "x86_64-macos"} + ] + }, + "tapi_tbd_version": 5 +} + +;--- expected-extra.tbd +{ + "main_library": { + "current_versions": [ + { "version": "1.2.3" } + ], + "exported_symbols": [ + { + "data": { + "global": [ + "_publicGlobalVariable", "_extraGlobalAPI2", + "_extraGlobalAPI1", "_privateGlobalVariable" + ], + "objc_class": [ + "SubClass", "SimpleInternalSPI", + "Basic6", "Basic1", "Base", + "Basic3", "Simple", "Basic4_2", + "Basic5", "FooClass", "Basic9", + "Basic8", "Basic2", "Basic4", + "A", "SimpleInternalAPI", + "ExternalManagedObject" + ], + "objc_eh_type": [ + "SubClass", "SimpleInternalAPI", + "Base", "SimpleInternalSPI" + ], + "objc_ivar": [ + "Basic4.ivar2", "Basic4_2.ivar1", + "Basic6.ivar1", "Basic4.ivar1", + "Basic4_2.ivar2" + ], + "weak": [ + "_weakPrivateGlobalVariable", "_weakPublicGlobalVariable" + ] + } + } + ], + "flags": [ + { + "attributes": [ "not_app_extension_safe"] + } + ], + "install_names": [ + { "name": "/System/Library/Frameworks/Simple.framework/Versions/A/Simple" } + ], + "target_info": [ + { "min_deployment": "10.12", "target": "x86_64-macos" } + ] + }, + "tapi_tbd_version": 5 +} + +;--- inputs.json.in +{ + "headers": [ + { + "path" : "DSTROOT/System/Library/Frameworks/Simple.framework/Headers/Basic.h", + "type" : "public" + }, + { + "path" : "DSTROOT/System/Library/Frameworks/Simple.framework/Headers/External.h", + "type" : "public" + }, + { + "path" : "DSTROOT/System/Library/Frameworks/Simple.framework/Headers/Simple.h", + "type" : "public" + }, + { + "path" : "DSTROOT/System/Library/Frameworks/Simple.framework/Headers/SimpleAPI.h", + "type" : "public" + }, + { + "path" : "DSTROOT/System/Library/Frameworks/Simple.framework/PrivateHeaders/SimplePrivate.h", + "type" : "private" + }, + { + "path" : "DSTROOT/System/Library/Frameworks/Simple.framework/PrivateHeaders/SimplePrivateSPI.h", + "type" : "private" + } + ], + "version": "3" +} + +;--- System/Library/Frameworks/Foundation.framework/Headers/Foundation.h +@interface NSObject +@end + +typedef unsigned char BOOL; +#ifndef NS_AVAILABLE +#define NS_AVAILABLE(x,y) __attribute__((availability(macosx,introduced=x))) +#endif +#ifndef NS_UNAVAILABLE +#define NS_UNAVAILABLE __attribute__((unavailable)) +#endif +#ifndef NS_DEPRECATED_MAC +#define NS_DEPRECATED_MAC(x,y) __attribute__((availability(macosx,introduced=x,deprecated=y,message="" ))); +#endif + +@interface NSManagedObject +@end + +@interface NSSet +@end diff --git a/clang/test/InstallAPI/functions.test b/clang/test/InstallAPI/functions.test index 527965303cb351f4a8422e1ced40cf502c401f10..5b5fd1308842ede729da85e428919a7103170f5a 100644 --- a/clang/test/InstallAPI/functions.test +++ b/clang/test/InstallAPI/functions.test @@ -4,7 +4,7 @@ // RUN: clang-installapi -target arm64-apple-macos13.1 \ // RUN: -I%t/usr/include -I%t/usr/local/include \ -// RUN: -install_name @rpath/lib/libfunctions.dylib \ +// RUN: -install_name @rpath/lib/libfunctions.dylib --filetype=tbd-v4 \ // RUN: %t/inputs.json -o %t/outputs.tbd 2>&1 | FileCheck %s --allow-empty // RUN: llvm-readtapi -compare %t/outputs.tbd %t/expected.tbd 2>&1 | FileCheck %s --allow-empty diff --git a/clang/test/InstallAPI/hiddens.test b/clang/test/InstallAPI/hiddens.test new file mode 100644 index 0000000000000000000000000000000000000000..b3196ef945cd129979fc0665ff85fa986c480349 --- /dev/null +++ b/clang/test/InstallAPI/hiddens.test @@ -0,0 +1,262 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json + +// RUN: yaml2obj %t/Hidden.yaml -o %t/System/Library/Frameworks/Hidden.framework/Hidden + +// RUN: clang-installapi --target=x86_64-apple-macos13 -x objective-c \ +// RUN: -F %t/System/Library/Frameworks \ +// RUN: -install_name /System/Library/Frameworks/Hidden.framework/Versions/A/Hidden\ +// RUN: -current_version 1 -compatibility_version 1 %t/inputs.json \ +// RUN: --verify-against=%t/System/Library/Frameworks/Hidden.framework/Hidden \ +// RUN: --verify-mode=Pedantic -o %t/output.tbd 2>&1 | FileCheck %s + +// CHECK-NOT: error +// CHECK: warning: use of __private_extern__ + +// RUN: llvm-readtapi --compare %t/output.tbd %t/expected.tbd + +//--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/System/Library/Frameworks/Hidden.framework/Headers/Hidden.h", + "type" : "public" + } + ], + "version": "3" +} + +//--- System/Library/Frameworks/Hidden.framework/Headers/Hidden.h +__private_extern__ int foo(); // Clang doesn't warn on this, but should. +__private_extern__ int baz; +__attribute__((visibility("hidden"))) int bar(); + +/// Created from: +/// #import "Hidden.h" int foo(void) { return 1; } int bar(void) { return 1; } +//--- Hidden.yaml +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x1000007 + cpusubtype: 0x3 + filetype: 0x6 + ncmds: 12 + sizeofcmds: 920 + flags: 0x100085 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 312 + segname: __TEXT + vmaddr: 0 + vmsize: 8192 + fileoff: 0 + filesize: 8192 + maxprot: 5 + initprot: 5 + nsects: 3 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0xBB8 + size: 22 + offset: 0xBB8 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 554889E5B8010000005DC3554889E5B8010000005DC3 + - sectname: __unwind_info + segname: __TEXT + addr: 0xBD0 + size: 4152 + offset: 0xBD0 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 010000001C000000010000002000000000000000200000000200000000000001B80B00003800000038000000CE0B00000000000038000000030000000C0001001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + - sectname: __eh_frame + segname: __TEXT + addr: 0x1C08 + size: 24 + offset: 0x1C08 + align: 3 + reloff: 0x0 + nreloc: 0 + flags: 0x6000000B + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 1400000000000000017A520001781001100C070890010000 + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __DATA_CONST + vmaddr: 8192 + vmsize: 4096 + fileoff: 8192 + filesize: 4096 + maxprot: 3 + initprot: 3 + nsects: 1 + flags: 16 + Sections: + - sectname: __objc_imageinfo + segname: __DATA_CONST + addr: 0x2000 + size: 8 + offset: 0x2000 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '0000000040000000' + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 12288 + vmsize: 104 + fileoff: 12288 + filesize: 104 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 0 + rebase_size: 0 + bind_off: 0 + bind_size: 0 + weak_bind_off: 0 + weak_bind_size: 0 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 12288 + export_size: 16 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 12312 + nsyms: 3 + stroff: 12360 + strsize: 32 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 1 + iextdefsym: 1 + nextdefsym: 1 + iundefsym: 2 + nundefsym: 1 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_ID_DYLIB + cmdsize: 88 + dylib: + name: 24 + timestamp: 0 + current_version: 65536 + compatibility_version: 65536 + Content: '/System/Library/Frameworks/Hidden.framework/Versions/A/Hidden' + ZeroPadBytes: 3 + - cmd: LC_UUID + cmdsize: 24 + uuid: 4C4C44E7-5555-3144-A133-0271E799C487 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 851968 + sdk: 983040 + ntools: 1 + Tools: + - tool: 4 + version: 1245184 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 88473600 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 12304 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 12312 + datasize: 0 +LinkEditData: + ExportTrie: + TerminalSize: 0 + NodeOffset: 0 + Name: '' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 8 + Name: _foo + Flags: 0x0 + Address: 0xBB8 + Other: 0x0 + ImportName: '' + NameList: + - n_strx: 7 + n_type: 0x1E + n_sect: 1 + n_desc: 0 + n_value: 3011 + - n_strx: 2 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 3000 + - n_strx: 12 + n_type: 0x1 + n_sect: 0 + n_desc: 256 + n_value: 0 + StringTable: + - ' ' + - _foo + - _bar + - dyld_stub_binder + - '' + - '' + - '' + FunctionStarts: [ 0xBB8, 0xBC3 ] +... + +//--- expected.tbd +--- !tapi-tbd +tbd-version: 4 +targets: [ x86_64-macos ] +flags: [ not_app_extension_safe ] +install-name: '/System/Library/Frameworks/Hidden.framework/Versions/A/Hidden' +... + diff --git a/clang/test/InstallAPI/linker-symbols.test b/clang/test/InstallAPI/linker-symbols.test new file mode 100644 index 0000000000000000000000000000000000000000..1e4ddf9c45d5dffe5566ee1057da3f49534c9627 --- /dev/null +++ b/clang/test/InstallAPI/linker-symbols.test @@ -0,0 +1,440 @@ +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json + +; RUN: yaml2obj %t/MagicSymbols.yaml -o %t/MagicSymbols + +; RUN: not clang-installapi -target x86_64-apple-macosx13 \ +; RUN: -install_name \ +; RUN: /System/Library/Frameworks/SpecialLinkerSymbols.framework/Versions/A/SpecialLinkerSymbols \ +; RUN: -current_version 1 -compatibility_version 1 \ +; RUN: %t/inputs.json -o %t/output.tbd \ +; RUN: --verify-mode=ErrorsOnly \ +; RUN: --verify-against=%t/MagicSymbols 2>&1 | FileCheck %s + +CHECK: warning: violations found for x86_64 +CHECK: error: no declaration found for exported symbol '$ld$add$os10.4$_symbol2' in dynamic library +CHECK: error: no declaration found for exported symbol '$ld$add$os10.5$_symbol2' in dynamic library +CHECK: error: no declaration found for exported symbol '$ld$hide$os10.6$_symbol1' in dynamic library +CHECK: error: no declaration found for exported symbol '$ld$hide$os10.7$_symbol1' in dynamic library +CHECK: error: no declaration found for exported symbol '$ld$weak$os10.5$_symbol3' in dynamic library +CHECK: error: no declaration found for exported symbol '$ld$weak$os10.4$_symbol3' in dynamic library +CHECK: error: no declaration found for exported symbol '$ld$install_name$os10.4$/System/Library/Frameworks/A.framework/Versions/A/A' in dynamic library +CHECK: error: no declaration found for exported symbol '$ld$install_name$os10.5$/System/Library/Frameworks/B.framework/Versions/A/B' in dynamic library + +;--- MagicSymbols.h +#ifndef SPECIAL_LINKER_SYMBOLS_H +#define SPECIAL_LINKER_SYMBOLS_H + +extern const int SpecialLinkerSymbolsVersion; + +extern int symbol1; +extern int symbol3; + +#endif // SPECIAL_LINKER_SYMBOLS_H + +;--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/MagicSymbols.h", + "type" : "project" + } + ], + "version": "3" +} + +;--- MagicSymbols.yaml +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x1000007 + cpusubtype: 0x3 + filetype: 0x6 + ncmds: 12 + sizeofcmds: 952 + flags: 0x100085 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __TEXT + vmaddr: 0 + vmsize: 4096 + fileoff: 0 + filesize: 4096 + maxprot: 5 + initprot: 5 + nsects: 2 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0xBD8 + size: 0 + offset: 0xBD8 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x80000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '' + - sectname: __const + segname: __TEXT + addr: 0xBD8 + size: 4 + offset: 0xBD8 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '07000000' + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __DATA + vmaddr: 4096 + vmsize: 4096 + fileoff: 4096 + filesize: 4096 + maxprot: 3 + initprot: 3 + nsects: 2 + flags: 0 + Sections: + - sectname: __data + segname: __DATA + addr: 0x1000 + size: 8 + offset: 0x1000 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 4D00000009030000 + - sectname: __common + segname: __DATA + addr: 0x1008 + size: 8 + offset: 0x0 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x1 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 8192 + vmsize: 944 + fileoff: 8192 + filesize: 944 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 0 + rebase_size: 0 + bind_off: 0 + bind_size: 0 + weak_bind_off: 0 + weak_bind_size: 0 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 8192 + export_size: 376 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 8576 + nsyms: 12 + stroff: 8768 + strsize: 368 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 0 + iextdefsym: 0 + nextdefsym: 11 + iundefsym: 11 + nundefsym: 1 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_ID_DYLIB + cmdsize: 120 + dylib: + name: 24 + timestamp: 0 + current_version: 65536 + compatibility_version: 65536 + Content: '/System/Library/Frameworks/SpecialLinkerSymbols.framework/Versions/A/SpecialLinkerSymbols' + ZeroPadBytes: 7 + - cmd: LC_UUID + cmdsize: 24 + uuid: 4C4C4478-5555-3144-A106-356C3C9DACA3 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 851968 + sdk: 983040 + ntools: 1 + Tools: + - tool: 4 + version: 1245184 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 88539136 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 8568 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 8576 + datasize: 0 +LinkEditData: + ExportTrie: + TerminalSize: 0 + NodeOffset: 0 + Name: '' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 11 + Name: _ + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 50 + Name: SpecialLinkerSymbolsVersion + Flags: 0x0 + Address: 0xBD8 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 55 + Name: symbol + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 63 + Name: '3' + Flags: 0x0 + Address: 0x1004 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 68 + Name: '1' + Flags: 0x0 + Address: 0x1000 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 73 + Name: '$ld$' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 134 + Name: 'add$os10.' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 162 + Name: '4$_symbol2' + Flags: 0x0 + Address: 0x1008 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 167 + Name: '5$_symbol2' + Flags: 0x0 + Address: 0x1009 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 172 + Name: 'hide$os10.' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 200 + Name: '6$_symbol1' + Flags: 0x0 + Address: 0x100A + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 205 + Name: '7$_symbol1' + Flags: 0x0 + Address: 0x100B + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 210 + Name: 'weak$os10.' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 238 + Name: '5$_symbol3' + Flags: 0x0 + Address: 0x100F + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 243 + Name: '4$_symbol3' + Flags: 0x0 + Address: 0x100E + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 248 + Name: 'install_name$os10.' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 362 + Name: '4$/System/Library/Frameworks/A.framework/Versions/A/A' + Flags: 0x0 + Address: 0x100C + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 367 + Name: '5$/System/Library/Frameworks/B.framework/Versions/A/B' + Flags: 0x0 + Address: 0x100D + Other: 0x0 + ImportName: '' + NameList: + - n_strx: 2 + n_type: 0xF + n_sect: 4 + n_desc: 0 + n_value: 4104 + - n_strx: 26 + n_type: 0xF + n_sect: 4 + n_desc: 0 + n_value: 4105 + - n_strx: 50 + n_type: 0xF + n_sect: 4 + n_desc: 0 + n_value: 4106 + - n_strx: 75 + n_type: 0xF + n_sect: 4 + n_desc: 0 + n_value: 4107 + - n_strx: 100 + n_type: 0xF + n_sect: 4 + n_desc: 0 + n_value: 4108 + - n_strx: 176 + n_type: 0xF + n_sect: 4 + n_desc: 0 + n_value: 4109 + - n_strx: 252 + n_type: 0xF + n_sect: 4 + n_desc: 0 + n_value: 4110 + - n_strx: 277 + n_type: 0xF + n_sect: 4 + n_desc: 0 + n_value: 4111 + - n_strx: 302 + n_type: 0xF + n_sect: 2 + n_desc: 0 + n_value: 3032 + - n_strx: 331 + n_type: 0xF + n_sect: 3 + n_desc: 0 + n_value: 4096 + - n_strx: 340 + n_type: 0xF + n_sect: 3 + n_desc: 0 + n_value: 4100 + - n_strx: 349 + n_type: 0x1 + n_sect: 0 + n_desc: 256 + n_value: 0 + StringTable: + - ' ' + - '$ld$add$os10.4$_symbol2' + - '$ld$add$os10.5$_symbol2' + - '$ld$hide$os10.6$_symbol1' + - '$ld$hide$os10.7$_symbol1' + - '$ld$install_name$os10.4$/System/Library/Frameworks/A.framework/Versions/A/A' + - '$ld$install_name$os10.5$/System/Library/Frameworks/B.framework/Versions/A/B' + - '$ld$weak$os10.4$_symbol3' + - '$ld$weak$os10.5$_symbol3' + - _SpecialLinkerSymbolsVersion + - _symbol1 + - _symbol3 + - dyld_stub_binder + - '' + - '' +... diff --git a/clang/test/InstallAPI/mismatching-objc-class-symbols.test b/clang/test/InstallAPI/mismatching-objc-class-symbols.test new file mode 100644 index 0000000000000000000000000000000000000000..3b4acf1035ace382956431fcd944a2cf49ba1e08 --- /dev/null +++ b/clang/test/InstallAPI/mismatching-objc-class-symbols.test @@ -0,0 +1,269 @@ +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json +; RUN: yaml2obj %t/swift-objc-class.yaml -o %t/libswift-objc.dylib + +// Try out dylib that only has 1 symbol for a ObjCClass, with no declarations in header. +; RUN: clang-installapi -target arm64-apple-macos14 -dynamiclib \ +; RUN: -install_name tmp.dylib --verify-against=%t/libswift-objc.dylib \ +; RUN: -I%t/usr/include %t/inputs.json -o %t/missing.tbd \ +; RUN: --verify-mode=ErrorsAndWarnings 2>&1 | FileCheck --check-prefix MISSING_DECL %s +; RUN: llvm-readtapi --compare %t/missing.tbd %t/missing-expected.tbd + +// Try out a dylib that only has 1 symbol for a ObjCClass, +// but a complete ObjCClass decl in header. +; RUN: clang-installapi -target arm64-apple-macos14 -dynamiclib \ +; RUN: -install_name tmp.dylib --verify-against=%t/libswift-objc.dylib \ +; RUN: -I%t/usr/include %t/inputs.json -o %t/mismatching.tbd \ +; RUN: --verify-mode=Pedantic -DFULL_DECL 2>&1 | FileCheck --check-prefix MISMATCH_DECL %s +; RUN: llvm-readtapi -compare %t/mismatching.tbd %t/mismatching-expected.tbd + +// Try out a dylib that only has 1 symbol for a ObjCClass, but is represented in header. +; RUN: clang-installapi -target arm64-apple-macos14 \ +; RUN: -install_name tmp.dylib --verify-against=%t/libswift-objc.dylib \ +; RUN: -I%t/usr/include %t/inputs.json -o %t/matching.tbd \ +; RUN: --verify-mode=Pedantic \ +; RUN: -DHAS_META_DECL 2>&1 | FileCheck --allow-empty %s + +; MISSING_DECL: violations found for arm64 +; MISSING_DECL-NEXT: warning: no declaration was found for exported symbol 'Metaclass of Suggestion' in dynamic library + +; MISMATCH_DECL: violations found for arm64-apple-macos14 +; MISMATCH_DECL: warning: declaration has external linkage, but dynamic library doesn't have symbol 'Class of Suggestion' + +; CHECK-NOT: error +; CHECK-NOT: warning + + +;--- usr/include/mismatch.h +#if HAS_META_DECL +int metaclass __asm("_OBJC_METACLASS_$_Suggestion"); +#endif + +#if FULL_DECL +@interface Suggestion +@end +#endif + +;--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/usr/include/mismatch.h", + "type" : "public" + } + ], + "version": "3" +} + +;--- missing-expected.tbd +--- !tapi-tbd +tbd-version: 4 +targets: [ arm64-macos ] +flags: [ not_app_extension_safe ] +install-name: tmp.dylib +current-version: 0 +compatibility-version: 0 +... + +;--- mismatching-expected.tbd +--- !tapi-tbd +tbd-version: 4 +targets: [ arm64-macos ] +flags: [ not_app_extension_safe ] +install-name: tmp.dylib +current-version: 0 +compatibility-version: 0 +exports: + - targets: [ arm64-macos ] + objc-classes: [ Suggestion ] +... + +;--- swift-objc-class.yaml +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x100000C + cpusubtype: 0x0 + filetype: 0x6 + ncmds: 13 + sizeofcmds: 752 + flags: 0x100085 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __TEXT + vmaddr: 0 + vmsize: 16384 + fileoff: 0 + filesize: 16384 + maxprot: 5 + initprot: 5 + nsects: 2 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x330 + size: 0 + offset: 0x330 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x80000000 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '' + - sectname: __const + segname: __TEXT + addr: 0x330 + size: 1 + offset: 0x330 + align: 0 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: '61' + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 16384 + vmsize: 416 + fileoff: 16384 + filesize: 416 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 0 + rebase_size: 0 + bind_off: 0 + bind_size: 0 + weak_bind_off: 0 + weak_bind_size: 0 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 16384 + export_size: 40 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 16432 + nsyms: 2 + stroff: 16464 + strsize: 48 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 0 + iextdefsym: 0 + nextdefsym: 1 + iundefsym: 1 + nundefsym: 1 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_ID_DYLIB + cmdsize: 40 + dylib: + name: 24 + timestamp: 0 + current_version: 0 + compatibility_version: 0 + Content: tmp.dylib + ZeroPadBytes: 7 + - cmd: LC_UUID + cmdsize: 24 + uuid: 4C4C4443-5555-3144-A142-97179769CBE0 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 917504 + sdk: 983040 + ntools: 1 + Tools: + - tool: 4 + version: 1245184 + - cmd: LC_LOAD_DYLIB + cmdsize: 96 + dylib: + name: 24 + timestamp: 0 + current_version: 197656576 + compatibility_version: 19660800 + Content: '/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation' + ZeroPadBytes: 3 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 88473600 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 16424 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 16432 + datasize: 0 + - cmd: LC_CODE_SIGNATURE + cmdsize: 16 + dataoff: 16512 + datasize: 288 +LinkEditData: + ExportTrie: + TerminalSize: 0 + NodeOffset: 0 + Name: '' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 32 + Name: '_OBJC_METACLASS_$_Suggestion' + Flags: 0x0 + Address: 0x330 + Other: 0x0 + ImportName: '' + NameList: + - n_strx: 2 + n_type: 0xF + n_sect: 2 + n_desc: 0 + n_value: 816 + - n_strx: 31 + n_type: 0x1 + n_sect: 0 + n_desc: 512 + n_value: 0 + StringTable: + - ' ' + - '_OBJC_METACLASS_$_Suggestion' + - dyld_stub_binder + FunctionStarts: [ 0x330 ] +... +// Generated from: +// xcrun -sdk macosx clang tmp.c -dynamiclib -install_name tmp.dylib +// tmp.c: +// __attribute__((visibility("default"))) +// const char Meta __asm("_OBJC_METACLASS_$_Suggestion") = 'a'; diff --git a/clang/test/InstallAPI/symbol-flags.test b/clang/test/InstallAPI/symbol-flags.test new file mode 100644 index 0000000000000000000000000000000000000000..3f68afd17e3b2009135ca04ee0edb758cdba0f0e --- /dev/null +++ b/clang/test/InstallAPI/symbol-flags.test @@ -0,0 +1,290 @@ +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json + +; RUN: yaml2obj %t/flags.yaml -o %t/SymbolFlags + +; RUN: not clang-installapi -x c++ --target=arm64-apple-macos13 \ +; RUN: -install_name /System/Library/Frameworks/SymbolFlags.framework/Versions/A/SymbolFlags \ +; RUN: -current_version 1 -compatibility_version 1 \ +; RUN: %t/inputs.json -o output.tbd \ +; RUN: --verify-against=%t/SymbolFlags \ +; RUN: --verify-mode=ErrorsOnly 2>&1 | FileCheck %s + +; CHECK: project.h:2:21: error: declaration '(tlv) val' is thread local, but symbol is not in dynamic library +; CHECK-NEXT: extern __thread int val; +; CHECK: project.h:3:13: error: dynamic library symbol '(weak-def) __Z12my_weak_funcv' is weak defined, but its declaration is not +; CHECK-NEXT: extern void my_weak_func(); + +;--- project.h +extern void my_func(); +extern __thread int val; +extern void my_weak_func(); + +;--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/project.h", + "type" : "project" + } + ], + "version": "3" +} + +;--- flags.yaml +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x100000C + cpusubtype: 0x0 + filetype: 0x6 + ncmds: 14 + sizeofcmds: 912 + flags: 0x118085 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 232 + segname: __TEXT + vmaddr: 0 + vmsize: 16384 + fileoff: 0 + filesize: 16384 + maxprot: 5 + initprot: 5 + nsects: 2 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0xFB0 + size: 8 + offset: 0xFB0 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: C0035FD6C0035FD6 + - sectname: __unwind_info + segname: __TEXT + addr: 0xFB8 + size: 4152 + offset: 0xFB8 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x0 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 010000001C000000010000002000000000000000200000000200000000000002B00F00003800000038000000B80F00000000000038000000030000000C0001001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __DATA + vmaddr: 16384 + vmsize: 16384 + fileoff: 16384 + filesize: 0 + maxprot: 3 + initprot: 3 + nsects: 1 + flags: 0 + Sections: + - sectname: __common + segname: __DATA + addr: 0x4000 + size: 4 + offset: 0x0 + align: 2 + reloff: 0x0 + nreloc: 0 + flags: 0x1 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 32768 + vmsize: 480 + fileoff: 16384 + filesize: 480 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_DYLD_INFO_ONLY + cmdsize: 48 + rebase_off: 0 + rebase_size: 0 + bind_off: 0 + bind_size: 0 + weak_bind_off: 0 + weak_bind_size: 0 + lazy_bind_off: 0 + lazy_bind_size: 0 + export_off: 16384 + export_size: 64 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 16456 + nsyms: 4 + stroff: 16520 + strsize: 56 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 0 + iextdefsym: 0 + nextdefsym: 3 + iundefsym: 3 + nundefsym: 1 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 + - cmd: LC_ID_DYLIB + cmdsize: 96 + dylib: + name: 24 + timestamp: 0 + current_version: 65536 + compatibility_version: 65536 + Content: '/System/Library/Frameworks/SymbolFlags.framework/Versions/A/SymbolFlags' + ZeroPadBytes: 1 + - cmd: LC_UUID + cmdsize: 24 + uuid: 4C4C4436-5555-3144-A1AF-5D3063ACFC99 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 851968 + sdk: 983040 + ntools: 1 + Tools: + - tool: 4 + version: 1245184 + - cmd: LC_LOAD_DYLIB + cmdsize: 48 + dylib: + name: 24 + timestamp: 0 + current_version: 117985024 + compatibility_version: 65536 + Content: '/usr/lib/libc++.1.dylib' + ZeroPadBytes: 1 + - cmd: LC_LOAD_DYLIB + cmdsize: 56 + dylib: + name: 24 + timestamp: 0 + current_version: 88473600 + compatibility_version: 65536 + Content: '/usr/lib/libSystem.B.dylib' + ZeroPadBytes: 6 + - cmd: LC_FUNCTION_STARTS + cmdsize: 16 + dataoff: 16448 + datasize: 8 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 16456 + datasize: 0 + - cmd: LC_CODE_SIGNATURE + cmdsize: 16 + dataoff: 16576 + datasize: 288 +LinkEditData: + ExportTrie: + TerminalSize: 0 + NodeOffset: 0 + Name: '' + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 0 + NodeOffset: 5 + Name: _ + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 4 + NodeOffset: 16 + Name: val + Flags: 0x0 + Address: 0x4000 + Other: 0x0 + ImportName: '' + - TerminalSize: 0 + NodeOffset: 22 + Name: _Z + Flags: 0x0 + Address: 0x0 + Other: 0x0 + ImportName: '' + Children: + - TerminalSize: 3 + NodeOffset: 52 + Name: 7my_funcv + Flags: 0x0 + Address: 0xFB0 + Other: 0x0 + ImportName: '' + - TerminalSize: 3 + NodeOffset: 57 + Name: 12my_weak_funcv + Flags: 0x4 + Address: 0xFB4 + Other: 0x0 + ImportName: '' + NameList: + - n_strx: 2 + n_type: 0xF + n_sect: 1 + n_desc: 0 + n_value: 4016 + - n_strx: 15 + n_type: 0xF + n_sect: 1 + n_desc: 128 + n_value: 4020 + - n_strx: 34 + n_type: 0xF + n_sect: 3 + n_desc: 0 + n_value: 16384 + - n_strx: 39 + n_type: 0x1 + n_sect: 0 + n_desc: 512 + n_value: 0 + StringTable: + - ' ' + - __Z7my_funcv + - __Z12my_weak_funcv + - _val + - dyld_stub_binder + FunctionStarts: [ 0xFB0, 0xFB4 ] +... + +/// Generated from: +// clang++ -mtargetos=macosx13 -arch arm64 flags.cpp +// flags.cpp: +// __attribute__((visibility("default"))) void my_func() {} +// __attribute__((weak)) void my_weak_func() {} +// int val = 0; diff --git a/clang/test/InstallAPI/umbrella-headers-unix.test b/clang/test/InstallAPI/umbrella-headers-unix.test new file mode 100644 index 0000000000000000000000000000000000000000..46118779896cf1492a3522213d3fba93d7ded826 --- /dev/null +++ b/clang/test/InstallAPI/umbrella-headers-unix.test @@ -0,0 +1,40 @@ +// UNSUPPORTED: system-windows + +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json +; RUN: mkdir %t/Frameworks/ +; RUN: cp -r %S/Inputs/Umbrella/Umbrella.framework %t/Frameworks/ + +// Only validate path based input that rely on regex matching on unix based file systems. +; RUN: clang-installapi --target=arm64-apple-macosx13 \ +; RUN: -install_name /System/Library/Frameworks/Umbrella2.framework/Versions/A/Umbrella \ +; RUN: -ObjC -F%t/Frameworks/ %t/inputs.json \ +; RUN: --public-umbrella-header=%t/Frameworks/Umbrella.framework/Headers/SpecialUmbrella.h \ +; RUN: -private-umbrella-header \ +; RUN: %t/Frameworks/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h \ +; RUN: -o %t/output.tbd 2>&1 | FileCheck -allow-empty %s + +; CHECK-NOT: error +; CHECK-NOT: warning + +;--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/Frameworks/Umbrella.framework/Headers/AAA.h", + "type" : "public" + }, + { + "path" : "DSTROOT/Frameworks/Umbrella.framework/Headers/SpecialUmbrella.h", + "type" : "public" + }, + { + "path" : "DSTROOT/Frameworks/Umbrella.framework/PrivateHeaders/AAA_Private.h", + "type" : "private" + }, + { + "path" : "DSTROOT/Frameworks/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h", + "type" : "private" + }], + "version": "3" +} diff --git a/clang/test/InstallAPI/umbrella-headers.test b/clang/test/InstallAPI/umbrella-headers.test new file mode 100644 index 0000000000000000000000000000000000000000..ce9c50608c41194b648a29f1f987dfe28f6b9134 --- /dev/null +++ b/clang/test/InstallAPI/umbrella-headers.test @@ -0,0 +1,48 @@ +; RUN: rm -rf %t +; RUN: split-file %s %t +; RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json +; RUN: cp -r %S/Inputs/Umbrella/Umbrella.framework %t/Frameworks/ + +// Check base filename matches. +; RUN: clang-installapi --target=arm64-apple-macosx13 \ +; RUN: -install_name /System/Library/Frameworks/Umbrella.framework/Versions/A/Umbrella \ +; RUN: -ObjC -F%t/Frameworks/ %t/inputs.json \ +; RUN: --public-umbrella-header=SpecialUmbrella.h \ +; RUN: --private-umbrella-header=SpecialPrivateUmbrella.h \ +; RUN: -o %t/output.tbd 2>&1 | FileCheck -allow-empty %s + +// Try missing umbrella header argument. +; RUN: not clang-installapi --target=arm64-apple-macosx13 \ +; RUN: -install_name /System/Library/Frameworks/Umbrella.framework/Versions/A/Umbrella \ +; RUN: -ObjC -F%t/Frameworks/ %t/inputs.json \ +; RUN: --public-umbrella-header=Ignore.h \ +; RUN: -o %t/output.tbd 2>&1 | FileCheck %s -check-prefix=ERR + +; ERR: error: public umbrella header file not found in input: 'Ignore.h' + +; CHECK-NOT: error +; CHECK-NOT: warning + +;--- Frameworks/Umbrella.framework/Headers/Ignore.h +#error "This header should be ignored" + +;--- inputs.json.in +{ + "headers": [ { + "path" : "DSTROOT/Frameworks/Umbrella.framework/Headers/AAA.h", + "type" : "public" + }, + { + "path" : "DSTROOT/Frameworks/Umbrella.framework/Headers/SpecialUmbrella.h", + "type" : "public" + }, + { + "path" : "DSTROOT/Frameworks/Umbrella.framework/PrivateHeaders/AAA_Private.h", + "type" : "private" + }, + { + "path" : "DSTROOT/Frameworks/Umbrella.framework/PrivateHeaders/SpecialPrivateUmbrella.h", + "type" : "private" + }], + "version": "3" +} diff --git a/clang/test/Lexer/gnu-flags.c b/clang/test/Lexer/gnu-flags.c index 384339fc8594296585d0a7b0d4029d71cf11b2c7..4d6d216b101f4a690cabcf15458e370bfd83004b 100644 --- a/clang/test/Lexer/gnu-flags.c +++ b/clang/test/Lexer/gnu-flags.c @@ -17,8 +17,6 @@ #if ALL || ZEROARGS -// expected-warning@+9 {{must specify at least one argument for '...' parameter of variadic macro}} -// expected-note@+4 {{macro 'efoo' defined here}} // expected-warning@+3 {{token pasting of ',' and __VA_ARGS__ is a GNU extension}} #endif diff --git a/clang/test/Lexer/has_extension_cxx.cpp b/clang/test/Lexer/has_extension_cxx.cpp index 7941997428acab69dcd9b63baaa2596096686d92..7366029d3727a164b82c84537783e9721072a492 100644 --- a/clang/test/Lexer/has_extension_cxx.cpp +++ b/clang/test/Lexer/has_extension_cxx.cpp @@ -33,6 +33,11 @@ int has_deleted_functions(); int has_inline_namespaces(); #endif +// CHECK: has_lambdas +#if __has_extension(cxx_lambdas) +int has_lambdas(); +#endif + // CHECK: has_override_control #if __has_extension(cxx_override_control) int has_override_control(); diff --git a/clang/test/Misc/target-invalid-cpu-note.c b/clang/test/Misc/target-invalid-cpu-note.c index b65a8fb057ee53f51ae1b9f75d20b76d37372d01..9c91c4157cd6a06ba015b4b0a3f4f4414bd4545b 100644 --- a/clang/test/Misc/target-invalid-cpu-note.c +++ b/clang/test/Misc/target-invalid-cpu-note.c @@ -5,11 +5,11 @@ // RUN: not %clang_cc1 -triple arm64--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix AARCH64 // AARCH64: error: unknown target CPU 'not-a-cpu' -// AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, cobalt-100, grace{{$}} +// AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a520ae, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-a720ae, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, cobalt-100, grace{{$}} // RUN: not %clang_cc1 -triple arm64--- -tune-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix TUNE_AARCH64 // TUNE_AARCH64: error: unknown target CPU 'not-a-cpu' -// TUNE_AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, cobalt-100, grace{{$}} +// TUNE_AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a520ae, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-a720ae, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, cobalt-100, grace{{$}} // RUN: not %clang_cc1 -triple i386--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix X86 // X86: error: unknown target CPU 'not-a-cpu' diff --git a/clang/test/Modules/bounds-safety-attributed-type.c b/clang/test/Modules/bounds-safety-attributed-type.c new file mode 100644 index 0000000000000000000000000000000000000000..0aa2f16b321c5f99de559ed27fd67d83739fc7fe --- /dev/null +++ b/clang/test/Modules/bounds-safety-attributed-type.c @@ -0,0 +1,27 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -verify %s +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -ast-dump-all %s | FileCheck %s +// expected-no-diagnostics + +#pragma clang module build bounds_safety +module bounds_safety {} +#pragma clang module contents +#pragma clang module begin bounds_safety +struct Test { + int count; + int fam[] __attribute__((counted_by(count))); +}; +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module import bounds_safety + +struct Test *p; + +// CHECK: |-RecordDecl {{.*}}bounds_safety.map:4:1, line:7:1> line:4:8 imported in bounds_safety <undeserialized declarations> struct Test definition +// CHECK: | |-FieldDecl {{.*}} imported in bounds_safety referenced count 'int' +// CHECK: | `-FieldDecl {{.*}} imported in bounds_safety fam 'int[] __counted_by(count)':'int[]' + +// CHECK: |-ImportDecl {{.*}}bounds-safety-attributed-type.c:17:22> col:22 implicit bounds_safety +// CHECK: |-RecordDecl {{.*}} struct Test +// CHECK: `-VarDecl {{.*}} p 'struct Test *' diff --git a/clang/test/Modules/codegen.test b/clang/test/Modules/codegen.test index 77602056defd4e139a5b8e88ba2ccf9bfadc590b..0af630a754805684a68f99147f31c1768392d87a 100644 --- a/clang/test/Modules/codegen.test +++ b/clang/test/Modules/codegen.test @@ -26,7 +26,7 @@ USE: $_Z4instIiEvv = comdat any USE: $_Z10always_inlv = comdat any FOO: $_ZN13implicit_dtorD2Ev = comdat any FOO: define weak_odr void @_Z2f1PKcz(ptr noundef %fmt, ...) #{{[0-9]+}} comdat -FOO: call void @llvm.va_start(ptr %{{[a-zA-Z0-9]*}}) +FOO: call void @llvm.va_start.p0(ptr %{{[a-zA-Z0-9]*}}) Test that implicit special members are emitted into the FOO module if they're ODR used there, otherwise emit them linkonce_odr as usual in the use. diff --git a/clang/test/Modules/language-linkage.cppm b/clang/test/Modules/language-linkage.cppm index bf7982cd9207d630918ab40e56bb075678eb7ba8..a5db9e9ebc07ec58e67549342ad44e47a5a05492 100644 --- a/clang/test/Modules/language-linkage.cppm +++ b/clang/test/Modules/language-linkage.cppm @@ -14,5 +14,5 @@ void foo() {} extern "C" void bar() {} -// CHECK: define {{.*}}@bar( // CHECK: define {{.*}}@_Z3foov( +// CHECK: define {{.*}}@bar( diff --git a/clang/test/Modules/missing-module-declaration.cppm b/clang/test/Modules/missing-module-declaration.cppm deleted file mode 100644 index d52f6639fe4f6484cd5a0925f8a5ad5e3898d478..0000000000000000000000000000000000000000 --- a/clang/test/Modules/missing-module-declaration.cppm +++ /dev/null @@ -1,13 +0,0 @@ -// RUN: rm -rf %t -// RUN: split-file %s %t -// RUN: cd %t -// -// RUN: %clang_cc1 -std=c++20 %t/B.cppm -I%t -emit-module-interface -o %t/B.pcm -// RUN: %clang_cc1 -std=c++20 %t/A.cppm -I%t -fprebuilt-module-path=%t -emit-module-interface -verify - -//--- A.cppm -import B; // expected-error{{missing 'export module' declaration in module interface unit}} - -//--- B.cppm -module; -export module B; diff --git a/clang/test/Modules/no-local-decl-in-reduced-bmi.cppm b/clang/test/Modules/no-local-decl-in-reduced-bmi.cppm new file mode 100644 index 0000000000000000000000000000000000000000..41ae2bf0dec8098252d3f43f29dfe2270b7eff7b --- /dev/null +++ b/clang/test/Modules/no-local-decl-in-reduced-bmi.cppm @@ -0,0 +1,33 @@ +// Test that we won't record local declarations by default in reduced BMI. + +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: cd %t +// +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm +// RUN: llvm-bcanalyzer --dump --disable-histogram --show-binary-blobs %t/a.pcm > %t/a.dump +// RUN: cat %t/a.dump | FileCheck %t/a.cppm +// +// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-reduced-module-interface -o %t/b.pcm +// RUN: llvm-bcanalyzer --dump --disable-histogram --show-binary-blobs %t/b.pcm > %t/b.dump +// RUN: cat %t/b.dump | FileCheck %t/b.cppm + +//--- a.cppm +export module a; +export int func() { + int v = 43; + return 43; +} + +// Test that the variable declaration is not recorded completely. +// CHECK-NOT: <DECL_VAR + +//--- b.cppm +export module b; +export inline int func() { + int v = 43; + return v; +} + +// Check that we still records the declaration from inline functions. +// CHECK: <DECL_VAR diff --git a/clang/test/Modules/no-undeclared-includes-builtins.cpp b/clang/test/Modules/no-undeclared-includes-builtins.cpp index c9bffc55619905303d0b2669f196cafca722c8a1..f9eefd24a33c7d8903c5d20151ed1bccc716f6af 100644 --- a/clang/test/Modules/no-undeclared-includes-builtins.cpp +++ b/clang/test/Modules/no-undeclared-includes-builtins.cpp @@ -8,7 +8,7 @@ // headers. // RUN: rm -rf %t -// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/no-undeclared-includes-builtins/libcxx -I %S/Inputs/no-undeclared-includes-builtins/glibc %s +// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fbuiltin-headers-in-system-modules -fimplicit-module-maps -I %S/Inputs/no-undeclared-includes-builtins/libcxx -I %S/Inputs/no-undeclared-includes-builtins/glibc %s // expected-no-diagnostics #include <stddef.h> diff --git a/clang/test/Modules/pr72828.cppm b/clang/test/Modules/pr72828.cppm index 574523188507a17e1804cc70f173f2f0d3dde7eb..7432f2831f248a69a5967c3f1b07c753d1b76cd4 100644 --- a/clang/test/Modules/pr72828.cppm +++ b/clang/test/Modules/pr72828.cppm @@ -17,7 +17,7 @@ struct s { void f() { auto [x] = s(); - [x] {}; + (void) [x] {}; } // Check that we can generate the LLVM IR expectedly. diff --git a/clang/test/Modules/reduced-bmi-generating-codes.cppm b/clang/test/Modules/reduced-bmi-generating-codes.cppm new file mode 100644 index 0000000000000000000000000000000000000000..13dcda06437b29df26956b90950b3727ec5b0488 --- /dev/null +++ b/clang/test/Modules/reduced-bmi-generating-codes.cppm @@ -0,0 +1,40 @@ +// Although the reduced BMI are not designed to be generated, +// it is helpful for testing whether we've reduced the definitions. +// +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.cppm \ +// RUN: -emit-reduced-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cpp \ +// RUN: -fmodule-file=a=%t/a.pcm -S -emit-llvm -o - \ +// RUN: | FileCheck %t/b.cpp + +//--- a.cppm +export module a; + +export template <class T> +class A { +public: + int member() { + return 43; + } +}; + +// Instantiate `A<int>::member()`. +export int a_member = A<int>().member(); + +export const int a = 43; + +//--- b.cpp +import a; + +static_assert(a == 43); + +int b() { + A<int> a; + return a.member(); +} + +// CHECK: define{{.*}}@_ZNW1a1AIiE6memberEv diff --git a/clang/test/Modules/stddef.c b/clang/test/Modules/stddef.c index 5bc0d1e44c8563fc3e254e9fb5b84790bea3da75..7623982614681009cf6fefd358916f67f1e2ae0b 100644 --- a/clang/test/Modules/stddef.c +++ b/clang/test/Modules/stddef.c @@ -1,29 +1,33 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fbuiltin-headers-in-system-modules -fmodules-cache-path=%t -I%S/Inputs/StdDef %s -verify -fno-modules-error-recovery +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fbuiltin-headers-in-system-modules -fmodules-cache-path=%t -I%S/Inputs/StdDef %s -verify=builtin-headers-in-system-modules -fno-modules-error-recovery // RUN: rm -rf %t -// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I%S/Inputs/StdDef %s -verify -fno-modules-error-recovery +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I%S/Inputs/StdDef %s -verify=no-builtin-headers-in-system-modules -fno-modules-error-recovery #include "ptrdiff_t.h" ptrdiff_t pdt; -// size_t is declared in both size_t.h and __stddef_size_t.h, both of which are -// modular headers. Regardless of whether stddef.h joins the StdDef test module -// or is in its _Builtin_stddef module, __stddef_size_t.h will be in -// _Builtin_stddef.size_t. It's not defined which module will win as the expected -// provider of size_t. For the purposes of this test it doesn't matter which header -// gets reported, just as long as it isn't other.h or include_again.h. -size_t st; // expected-error-re {{missing '#include "{{size_t|__stddef_size_t}}.h"'; 'size_t' must be declared before it is used}} -// expected-note@size_t.h:* 0+ {{here}} -// expected-note@__stddef_size_t.h:* 0+ {{here}} +// size_t is declared in both size_t.h and __stddef_size_t.h. If +// -fbuiltin-headers-in-system-modules is set, then __stddef_size_t.h is a +// non-modular header that will be transitively pulled in the StdDef test module +// by include_again.h. Otherwise it will be in the _Builtin_stddef module. In +// any case it's not defined which module will win as the expected provider of +// size_t. For the purposes of this test it doesn't matter which of the two +// providing headers get reported. +size_t st; // builtin-headers-in-system-modules-error-re {{missing '#include "{{size_t|include_again}}.h"'; 'size_t' must be declared before it is used}} \ + no-builtin-headers-in-system-modules-error-re {{missing '#include "{{size_t|__stddef_size_t}}.h"'; 'size_t' must be declared before it is used}} +// builtin-headers-in-system-modules-note@size_t.h:* 0+ {{here}} \ + no-builtin-headers-in-system-modules-note@size_t.h:* 0+ {{here}} +// builtin-headers-in-system-modules-note@__stddef_size_t.h:* 0+ {{here}} \ + no-builtin-headers-in-system-modules-note@__stddef_size_t.h:* 0+ {{here}} #include "include_again.h" -// Includes <stddef.h> which includes <__stddef_size_t.h> which imports the -// _Builtin_stddef.size_t module. +// Includes <stddef.h> which includes <__stddef_size_t.h>. size_t st2; #include "size_t.h" -// Redeclares size_t, but the type merger should figure it out. +// Redeclares size_t when -fbuiltin-headers-in-system-modules is not passed, but +// the type merger should figure it out. size_t st3; diff --git a/clang/test/OpenMP/atomic_capture_codegen.cpp b/clang/test/OpenMP/atomic_capture_codegen.cpp index 08d1f21f8e0bda4b8cc6afbf5a30354d058ee07a..eba7906d8eb8a78e6aa28dfbc03fa60289a42de4 100644 --- a/clang/test/OpenMP/atomic_capture_codegen.cpp +++ b/clang/test/OpenMP/atomic_capture_codegen.cpp @@ -811,7 +811,7 @@ int main(void) { #pragma omp atomic relaxed capture iv = bfx4.a = bfx4.a * ldv; // CHECK: [[EXPR:%.+]] = load x86_fp80, ptr @{{.+}} -// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr (i8, ptr @{{.+}}, i64 2) monotonic, align 1 +// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1) monotonic, align 1 // CHECK: br label %[[CONT:.+]] // CHECK: [[CONT]] // CHECK: [[OLD_BF_VALUE:%.+]] = phi i8 [ [[PREV_VALUE]], %{{.+}} ], [ [[FAILED_OLD_VAL:%.+]], %[[CONT]] ] @@ -831,7 +831,7 @@ int main(void) { // CHECK: or i8 [[BF_CLEAR]], [[BF_VALUE]] // CHECK: store i8 %{{.+}}, ptr [[BITCAST1]] // CHECK: [[NEW_BF_VALUE:%.+]] = load i8, ptr [[BITCAST1]] -// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr (i8, ptr @{{.+}}, i64 2), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1 +// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1 // CHECK: [[FAILED_OLD_VAL]] = extractvalue { i8, i1 } [[RES]], 0 // CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i8, i1 } [[RES]], 1 // CHECK: br i1 [[FAIL_SUCCESS]], label %[[EXIT:.+]], label %[[CONT]] @@ -870,7 +870,7 @@ int main(void) { #pragma omp atomic capture release {bfx4.b /= ldv; iv = bfx4.b;} // CHECK: [[EXPR:%.+]] = load x86_fp80, ptr @{{.+}} -// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr (i8, ptr @{{.+}}, i64 2) acquire, align 1 +// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1) acquire, align 1 // CHECK: br label %[[CONT:.+]] // CHECK: [[CONT]] // CHECK: [[OLD_BF_VALUE:%.+]] = phi i8 [ [[PREV_VALUE]], %[[EXIT]] ], [ [[FAILED_OLD_VAL:%.+]], %[[CONT]] ] @@ -890,7 +890,7 @@ int main(void) { // CHECK: or i8 [[BF_CLEAR]], [[BF_VALUE]] // CHECK: store i8 %{{.+}}, ptr [[BITCAST1]] // CHECK: [[NEW_BF_VALUE:%.+]] = load i8, ptr [[BITCAST1]] -// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr (i8, ptr @{{.+}}, i64 2), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] acquire acquire, align 1 +// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] acquire acquire, align 1 // CHECK: [[FAILED_OLD_VAL]] = extractvalue { i8, i1 } [[RES]], 0 // CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i8, i1 } [[RES]], 1 // CHECK: br i1 [[FAIL_SUCCESS]], label %[[EXIT:.+]], label %[[CONT]] diff --git a/clang/test/OpenMP/atomic_read_codegen.c b/clang/test/OpenMP/atomic_read_codegen.c index 0a68c8e2c35a5636f4ccb80be25fd6bd21394a8d..4294c145fa1c977a0a9ebce60815ff3d1d514fa7 100644 --- a/clang/test/OpenMP/atomic_read_codegen.c +++ b/clang/test/OpenMP/atomic_read_codegen.c @@ -292,7 +292,7 @@ int main(void) { // CHECK: store x86_fp80 #pragma omp atomic read ldv = bfx4.a; -// CHECK: [[LD:%.+]] = load atomic i8, ptr getelementptr (i8, ptr @bfx4_packed, i64 2) monotonic, align 1 +// CHECK: [[LD:%.+]] = load atomic i8, ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @bfx4_packed, i32 0, i32 1) monotonic, align 1 // CHECK: store i8 [[LD]], ptr [[LDTEMP:%.+]] // CHECK: [[LD:%.+]] = load i8, ptr [[LDTEMP]] // CHECK: [[SHL:%.+]] = shl i8 [[LD]], 7 @@ -309,7 +309,7 @@ int main(void) { // CHECK: store x86_fp80 #pragma omp atomic read relaxed ldv = bfx4.b; -// CHECK: [[LD:%.+]] = load atomic i8, ptr getelementptr (i8, ptr @bfx4_packed, i64 2) acquire, align 1 +// CHECK: [[LD:%.+]] = load atomic i8, ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @bfx4_packed, i32 0, i32 1) acquire, align 1 // CHECK: store i8 [[LD]], ptr [[LDTEMP:%.+]] // CHECK: [[LD:%.+]] = load i8, ptr [[LDTEMP]] // CHECK: [[ASHR:%.+]] = ashr i8 [[LD]], 1 diff --git a/clang/test/OpenMP/atomic_update_codegen.cpp b/clang/test/OpenMP/atomic_update_codegen.cpp index 31160b41764698ee41f3b5f7c49690ae0e0f8aba..ce0765118922a10d788ad3cf2ce74db51f6c9014 100644 --- a/clang/test/OpenMP/atomic_update_codegen.cpp +++ b/clang/test/OpenMP/atomic_update_codegen.cpp @@ -737,7 +737,7 @@ int main(void) { #pragma omp atomic bfx4.a = bfx4.a * ldv; // CHECK: [[EXPR:%.+]] = load x86_fp80, ptr @{{.+}} -// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr (i8, ptr @{{.+}}, i64 2) monotonic, align 1 +// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1) monotonic, align 1 // CHECK: br label %[[CONT:.+]] // CHECK: [[CONT]] // CHECK: [[OLD_BF_VALUE:%.+]] = phi i8 [ [[PREV_VALUE]], %{{.+}} ], [ [[FAILED_OLD_VAL:%.+]], %[[CONT]] ] @@ -757,7 +757,7 @@ int main(void) { // CHECK: or i8 [[BF_CLEAR]], [[BF_VALUE]] // CHECK: store i8 %{{.+}}, ptr [[BITCAST1]] // CHECK: [[NEW_BF_VALUE:%.+]] = load i8, ptr [[BITCAST1]] -// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr (i8, ptr @{{.+}}, i64 2), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1 +// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1 // CHECK: [[FAILED_OLD_VAL]] = extractvalue { i8, i1 } [[RES]], 0 // CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i8, i1 } [[RES]], 1 // CHECK: br i1 [[FAIL_SUCCESS]], label %[[EXIT:.+]], label %[[CONT]] @@ -792,7 +792,7 @@ int main(void) { #pragma omp atomic bfx4.b /= ldv; // CHECK: [[EXPR:%.+]] = load x86_fp80, ptr @{{.+}} -// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr (i8, ptr @{{.+}}, i64 2) monotonic, align 1 +// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1) monotonic, align 1 // CHECK: br label %[[CONT:.+]] // CHECK: [[CONT]] // CHECK: [[OLD_BF_VALUE:%.+]] = phi i8 [ [[PREV_VALUE]], %[[EXIT]] ], [ [[FAILED_OLD_VAL:%.+]], %[[CONT]] ] @@ -812,7 +812,7 @@ int main(void) { // CHECK: or i8 [[BF_CLEAR]], [[BF_VALUE]] // CHECK: store i8 %{{.+}}, ptr [[BITCAST1]] // CHECK: [[NEW_BF_VALUE:%.+]] = load i8, ptr [[BITCAST1]] -// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr (i8, ptr @{{.+}}, i64 2), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1 +// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1 // CHECK: [[FAILED_OLD_VAL]] = extractvalue { i8, i1 } [[RES]], 0 // CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i8, i1 } [[RES]], 1 // CHECK: br i1 [[FAIL_SUCCESS]], label %[[EXIT:.+]], label %[[CONT]] diff --git a/clang/test/OpenMP/atomic_write_codegen.c b/clang/test/OpenMP/atomic_write_codegen.c index afe8737d30b06584fe1ac28eab8914be184698d3..493b01cbac76c4ef60ad8c489a8616d1a32fc69c 100644 --- a/clang/test/OpenMP/atomic_write_codegen.c +++ b/clang/test/OpenMP/atomic_write_codegen.c @@ -413,7 +413,7 @@ int main(void) { bfx4.a = ldv; // CHECK: load x86_fp80, ptr @{{.+}} // CHECK: [[NEW_VAL:%.+]] = fptosi x86_fp80 %{{.+}} to i32 -// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr (i8, ptr @{{.+}}, i64 2) monotonic, align 1 +// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1) monotonic, align 1 // CHECK: br label %[[CONT:.+]] // CHECK: [[CONT]] // CHECK: [[OLD_BF_VALUE:%.+]] = phi i8 [ [[PREV_VALUE]], %[[EXIT]] ], [ [[FAILED_OLD_VAL:%.+]], %[[CONT]] ] @@ -423,7 +423,7 @@ int main(void) { // CHECK: or i8 [[BF_CLEAR]], [[BF_VALUE]] // CHECK: store i8 %{{.+}}, ptr [[LDTEMP:%.+]] // CHECK: [[NEW_BF_VALUE:%.+]] = load i8, ptr [[LDTEMP]] -// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr (i8, ptr @{{.+}}, i64 2), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1 +// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1 // CHECK: [[FAILED_OLD_VAL]] = extractvalue { i8, i1 } [[RES]], 0 // CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i8, i1 } [[RES]], 1 // CHECK: br i1 [[FAIL_SUCCESS]], label %[[EXIT:.+]], label %[[CONT]] @@ -451,7 +451,7 @@ int main(void) { bfx4.b = ldv; // CHECK: load x86_fp80, ptr @{{.+}} // CHECK: [[NEW_VAL:%.+]] = fptosi x86_fp80 %{{.+}} to i64 -// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr (i8, ptr @{{.+}}, i64 2) monotonic, align 1 +// CHECK: [[PREV_VALUE:%.+]] = load atomic i8, ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1) monotonic, align 1 // CHECK: br label %[[CONT:.+]] // CHECK: [[CONT]] // CHECK: [[OLD_BF_VALUE:%.+]] = phi i8 [ [[PREV_VALUE]], %[[EXIT]] ], [ [[FAILED_OLD_VAL:%.+]], %[[CONT]] ] @@ -462,7 +462,7 @@ int main(void) { // CHECK: or i8 [[BF_CLEAR]], [[BF_VALUE]] // CHECK: store i8 %{{.+}}, ptr [[LDTEMP:%.+]] // CHECK: [[NEW_BF_VALUE:%.+]] = load i8, ptr [[LDTEMP]] -// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr (i8, ptr @{{.+}}, i64 2), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1 +// CHECK: [[RES:%.+]] = cmpxchg ptr getelementptr inbounds (%struct.BitFields4_packed, ptr @{{.+}}, i32 0, i32 1), i8 [[OLD_BF_VALUE]], i8 [[NEW_BF_VALUE]] monotonic monotonic, align 1 // CHECK: [[FAILED_OLD_VAL]] = extractvalue { i8, i1 } [[RES]], 0 // CHECK: [[FAIL_SUCCESS:%.+]] = extractvalue { i8, i1 } [[RES]], 1 // CHECK: br i1 [[FAIL_SUCCESS]], label %[[EXIT:.+]], label %[[CONT]] diff --git a/clang/test/OpenMP/bug54082.c b/clang/test/OpenMP/bug54082.c index b88b68fd43012a0918b79dfc13da65d22c012dd2..337c120983e0a3603622b526f3584d201217f66c 100644 --- a/clang/test/OpenMP/bug54082.c +++ b/clang/test/OpenMP/bug54082.c @@ -69,9 +69,7 @@ void foo() { // CHECK-NEXT: [[X_TRAITS:%.*]] = alloca [1 x %struct.omp_alloctrait_t], align 16 // CHECK-NEXT: [[X_ALLOC:%.*]] = alloca i64, align 8 // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 16, ptr nonnull [[X_TRAITS]]) #[[ATTR5:[0-9]+]] -// CHECK-NEXT: store i32 2, ptr [[X_TRAITS]], align 16 -// CHECK-NEXT: [[LOC0:%.*]] = getelementptr inbounds i8, ptr [[X_TRAITS]], i64 8 -// CHECK-NEXT: store i64 64, ptr [[LOC0]], align 8 +// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 16 dereferenceable(16) [[X_TRAITS]], ptr noundef nonnull align 16 dereferenceable(16) @__const.foo.x_traits, i64 16, i1 false) // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr nonnull [[X_ALLOC]]) #[[ATTR5]] // CHECK-NEXT: [[CALL:%.*]] = call i64 @omp_init_allocator(i64 noundef 0, i32 noundef 1, ptr noundef nonnull [[X_TRAITS]]) #[[ATTR5]] // CHECK-NEXT: store i64 [[CALL]], ptr [[X_ALLOC]], align 8, !tbaa [[TBAA3:![0-9]+]] diff --git a/clang/test/OpenMP/bug60602.cpp b/clang/test/OpenMP/bug60602.cpp index 48dc341a08224ec9d0483262536e2e564f824e7a..9c92ec27b86eea16ee06d5def41f4b31881a10c9 100644 --- a/clang/test/OpenMP/bug60602.cpp +++ b/clang/test/OpenMP/bug60602.cpp @@ -95,7 +95,7 @@ int kernel_within_loop(int *a, int *b, int N, int num_iters) { // CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -181,7 +181,7 @@ int kernel_within_loop(int *a, int *b, int N, int num_iters) { // CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP71]], 1 // CHECK-NEXT: [[TMP72:%.*]] = zext i32 [[ADD]] to i64 // CHECK-NEXT: [[TMP73:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP73]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP73]], align 4 // CHECK-NEXT: [[TMP74:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CHECK-NEXT: store i32 3, ptr [[TMP74]], align 4 // CHECK-NEXT: [[TMP75:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 diff --git a/clang/test/OpenMP/declare_reduction_messages.cpp b/clang/test/OpenMP/declare_reduction_messages.cpp index 38a5d766eeadf7deb151ac59bab562f8f0aff9a1..752cc4fb05a12395c1f7f1d4766d0e80f4e5b1e9 100644 --- a/clang/test/OpenMP/declare_reduction_messages.cpp +++ b/clang/test/OpenMP/declare_reduction_messages.cpp @@ -58,16 +58,10 @@ class Class2 : public Class1<T> { #pragma omp declare reduction(fun1 : long : omp_out += omp_in) initializer // expected-error {{expected '(' after 'initializer'}} #pragma omp declare reduction(fun2 : long : omp_out += omp_in) initializer { // expected-error {{expected '(' after 'initializer'}} expected-error {{expected expression}} expected-warning {{extra tokens at the end of '#pragma omp declare reduction' are ignored}} #pragma omp declare reduction(fun3 : long : omp_out += omp_in) initializer[ -#if __cplusplus <= 199711L -// expected-error@-2 {{expected '(' after 'initializer'}} -// expected-error@-3 {{expected expression}} -// expected-warning@-4 {{extra tokens at the end of '#pragma omp declare reduction' are ignored}} -#else -// expected-error@-6 {{expected '(' after 'initializer'}} -// expected-error@-7 {{expected variable name or 'this' in lambda capture list}} -// expected-error@-8 {{expected ')'}} -// expected-note@-9 {{to match this '('}} -#endif +// expected-error@-1 {{expected '(' after 'initializer'}} +// expected-error@-2 {{expected variable name or 'this' in lambda capture list}} +// expected-error@-3 {{expected ')'}} +// expected-note@-4 {{to match this '('}} #pragma omp declare reduction(fun4 : long : omp_out += omp_in) initializer() // expected-error {{expected expression}} #pragma omp declare reduction(fun5 : long : omp_out += omp_in) initializer(temp) // expected-error {{only 'omp_priv' or 'omp_orig' variables are allowed in initializer expression}} #pragma omp declare reduction(fun6 : long : omp_out += omp_in) initializer(omp_orig // expected-error {{expected ')'}} expected-note {{to match this '('}} diff --git a/clang/test/OpenMP/distribute_codegen.cpp b/clang/test/OpenMP/distribute_codegen.cpp index 31ec6ff911905e907e6828c2f2d0281b69ff483d..34d14c89fedaed99772cf3dfcf31f11845957481 100644 --- a/clang/test/OpenMP/distribute_codegen.cpp +++ b/clang/test/OpenMP/distribute_codegen.cpp @@ -163,7 +163,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -354,7 +354,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -545,7 +545,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -744,7 +744,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK1-NEXT: [[ADD4:%.*]] = add nsw i32 [[TMP9]], 1 // CHECK1-NEXT: [[TMP10:%.*]] = zext i32 [[ADD4]] to i64 // CHECK1-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP11]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP11]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP12]], align 4 // CHECK1-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -911,7 +911,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1084,7 +1084,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1271,7 +1271,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1458,7 +1458,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1653,7 +1653,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK3-NEXT: [[ADD4:%.*]] = add nsw i32 [[TMP9]], 1 // CHECK3-NEXT: [[TMP10:%.*]] = zext i32 [[ADD4]] to i64 // CHECK3-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP11]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP11]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP12]], align 4 // CHECK3-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1820,7 +1820,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_firstprivate_codegen.cpp b/clang/test/OpenMP/distribute_firstprivate_codegen.cpp index 800a002e4396800c46461ff4a03bed25024e5478..567d12119db2187842c67a6a9782230825918aad 100644 --- a/clang/test/OpenMP/distribute_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_firstprivate_codegen.cpp @@ -542,7 +542,7 @@ int main() { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -838,7 +838,7 @@ int main() { // CHECK9-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK9-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK9-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1207,7 +1207,7 @@ int main() { // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1501,7 +1501,7 @@ int main() { // CHECK11-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_lastprivate_codegen.cpp b/clang/test/OpenMP/distribute_lastprivate_codegen.cpp index 772372076e947749474a0c7b269669549153f12f..5d1a12d27145e03786acae6a0b5a0787d6ad374f 100644 --- a/clang/test/OpenMP/distribute_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_lastprivate_codegen.cpp @@ -527,7 +527,7 @@ int main() { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -841,7 +841,7 @@ int main() { // CHECK9-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK9-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK9-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1229,7 +1229,7 @@ int main() { // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1541,7 +1541,7 @@ int main() { // CHECK11-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_parallel_for_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_codegen.cpp index 9cb0a15530651b4a2f0c5043a431a2023e93b1d8..a8892a06d4b30641dae63bac77ba091bba3f4501 100644 --- a/clang/test/OpenMP/distribute_parallel_for_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_codegen.cpp @@ -4372,7 +4372,7 @@ int main() { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK9-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP24]], align 4 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4447,7 +4447,7 @@ int main() { // CHECK9-NEXT: [[ADD13:%.*]] = add nsw i32 [[TMP59]], 1 // CHECK9-NEXT: [[TMP60:%.*]] = zext i32 [[ADD13]] to i64 // CHECK9-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP61]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP61]], align 4 // CHECK9-NEXT: [[TMP62:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP62]], align 4 // CHECK9-NEXT: [[TMP63:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 @@ -4531,7 +4531,7 @@ int main() { // CHECK9-NEXT: [[ADD27:%.*]] = add nsw i32 [[TMP102]], 1 // CHECK9-NEXT: [[TMP103:%.*]] = zext i32 [[ADD27]] to i64 // CHECK9-NEXT: [[TMP104:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP104]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP104]], align 4 // CHECK9-NEXT: [[TMP105:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP105]], align 4 // CHECK9-NEXT: [[TMP106:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 2 @@ -4606,7 +4606,7 @@ int main() { // CHECK9-NEXT: [[ADD41:%.*]] = add nsw i32 [[TMP140]], 1 // CHECK9-NEXT: [[TMP141:%.*]] = zext i32 [[ADD41]] to i64 // CHECK9-NEXT: [[TMP142:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP142]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP142]], align 4 // CHECK9-NEXT: [[TMP143:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP143]], align 4 // CHECK9-NEXT: [[TMP144:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 2 @@ -4690,7 +4690,7 @@ int main() { // CHECK9-NEXT: [[ADD56:%.*]] = add nsw i32 [[TMP183]], 1 // CHECK9-NEXT: [[TMP184:%.*]] = zext i32 [[ADD56]] to i64 // CHECK9-NEXT: [[TMP185:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP185]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP185]], align 4 // CHECK9-NEXT: [[TMP186:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP186]], align 4 // CHECK9-NEXT: [[TMP187:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 2 @@ -4765,7 +4765,7 @@ int main() { // CHECK9-NEXT: [[ADD70:%.*]] = add nsw i32 [[TMP221]], 1 // CHECK9-NEXT: [[TMP222:%.*]] = zext i32 [[ADD70]] to i64 // CHECK9-NEXT: [[TMP223:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP223]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP223]], align 4 // CHECK9-NEXT: [[TMP224:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP224]], align 4 // CHECK9-NEXT: [[TMP225:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 2 @@ -4849,7 +4849,7 @@ int main() { // CHECK9-NEXT: [[ADD85:%.*]] = add nsw i32 [[TMP264]], 1 // CHECK9-NEXT: [[TMP265:%.*]] = zext i32 [[ADD85]] to i64 // CHECK9-NEXT: [[TMP266:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP266]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP266]], align 4 // CHECK9-NEXT: [[TMP267:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP267]], align 4 // CHECK9-NEXT: [[TMP268:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 2 @@ -6671,7 +6671,7 @@ int main() { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK9-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP24]], align 4 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -6746,7 +6746,7 @@ int main() { // CHECK9-NEXT: [[ADD13:%.*]] = add nsw i32 [[TMP59]], 1 // CHECK9-NEXT: [[TMP60:%.*]] = zext i32 [[ADD13]] to i64 // CHECK9-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP61]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP61]], align 4 // CHECK9-NEXT: [[TMP62:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP62]], align 4 // CHECK9-NEXT: [[TMP63:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 @@ -6830,7 +6830,7 @@ int main() { // CHECK9-NEXT: [[ADD27:%.*]] = add nsw i32 [[TMP102]], 1 // CHECK9-NEXT: [[TMP103:%.*]] = zext i32 [[ADD27]] to i64 // CHECK9-NEXT: [[TMP104:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP104]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP104]], align 4 // CHECK9-NEXT: [[TMP105:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP105]], align 4 // CHECK9-NEXT: [[TMP106:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 2 @@ -6905,7 +6905,7 @@ int main() { // CHECK9-NEXT: [[ADD41:%.*]] = add nsw i32 [[TMP140]], 1 // CHECK9-NEXT: [[TMP141:%.*]] = zext i32 [[ADD41]] to i64 // CHECK9-NEXT: [[TMP142:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP142]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP142]], align 4 // CHECK9-NEXT: [[TMP143:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP143]], align 4 // CHECK9-NEXT: [[TMP144:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 2 @@ -6989,7 +6989,7 @@ int main() { // CHECK9-NEXT: [[ADD56:%.*]] = add nsw i32 [[TMP183]], 1 // CHECK9-NEXT: [[TMP184:%.*]] = zext i32 [[ADD56]] to i64 // CHECK9-NEXT: [[TMP185:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP185]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP185]], align 4 // CHECK9-NEXT: [[TMP186:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP186]], align 4 // CHECK9-NEXT: [[TMP187:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 2 @@ -7064,7 +7064,7 @@ int main() { // CHECK9-NEXT: [[ADD70:%.*]] = add nsw i32 [[TMP221]], 1 // CHECK9-NEXT: [[TMP222:%.*]] = zext i32 [[ADD70]] to i64 // CHECK9-NEXT: [[TMP223:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP223]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP223]], align 4 // CHECK9-NEXT: [[TMP224:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP224]], align 4 // CHECK9-NEXT: [[TMP225:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 2 @@ -7148,7 +7148,7 @@ int main() { // CHECK9-NEXT: [[ADD85:%.*]] = add nsw i32 [[TMP264]], 1 // CHECK9-NEXT: [[TMP265:%.*]] = zext i32 [[ADD85]] to i64 // CHECK9-NEXT: [[TMP266:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP266]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP266]], align 4 // CHECK9-NEXT: [[TMP267:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP267]], align 4 // CHECK9-NEXT: [[TMP268:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 2 @@ -8986,7 +8986,7 @@ int main() { // CHECK11-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK11-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP24]], align 4 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -9061,7 +9061,7 @@ int main() { // CHECK11-NEXT: [[ADD13:%.*]] = add nsw i32 [[TMP59]], 1 // CHECK11-NEXT: [[TMP60:%.*]] = zext i32 [[ADD13]] to i64 // CHECK11-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP61]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP61]], align 4 // CHECK11-NEXT: [[TMP62:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP62]], align 4 // CHECK11-NEXT: [[TMP63:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 @@ -9145,7 +9145,7 @@ int main() { // CHECK11-NEXT: [[ADD27:%.*]] = add nsw i32 [[TMP102]], 1 // CHECK11-NEXT: [[TMP103:%.*]] = zext i32 [[ADD27]] to i64 // CHECK11-NEXT: [[TMP104:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP104]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP104]], align 4 // CHECK11-NEXT: [[TMP105:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP105]], align 4 // CHECK11-NEXT: [[TMP106:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 2 @@ -9220,7 +9220,7 @@ int main() { // CHECK11-NEXT: [[ADD41:%.*]] = add nsw i32 [[TMP140]], 1 // CHECK11-NEXT: [[TMP141:%.*]] = zext i32 [[ADD41]] to i64 // CHECK11-NEXT: [[TMP142:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP142]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP142]], align 4 // CHECK11-NEXT: [[TMP143:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP143]], align 4 // CHECK11-NEXT: [[TMP144:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 2 @@ -9304,7 +9304,7 @@ int main() { // CHECK11-NEXT: [[ADD56:%.*]] = add nsw i32 [[TMP183]], 1 // CHECK11-NEXT: [[TMP184:%.*]] = zext i32 [[ADD56]] to i64 // CHECK11-NEXT: [[TMP185:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP185]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP185]], align 4 // CHECK11-NEXT: [[TMP186:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP186]], align 4 // CHECK11-NEXT: [[TMP187:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 2 @@ -9379,7 +9379,7 @@ int main() { // CHECK11-NEXT: [[ADD70:%.*]] = add nsw i32 [[TMP221]], 1 // CHECK11-NEXT: [[TMP222:%.*]] = zext i32 [[ADD70]] to i64 // CHECK11-NEXT: [[TMP223:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP223]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP223]], align 4 // CHECK11-NEXT: [[TMP224:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP224]], align 4 // CHECK11-NEXT: [[TMP225:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 2 @@ -9463,7 +9463,7 @@ int main() { // CHECK11-NEXT: [[ADD85:%.*]] = add nsw i32 [[TMP264]], 1 // CHECK11-NEXT: [[TMP265:%.*]] = zext i32 [[ADD85]] to i64 // CHECK11-NEXT: [[TMP266:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP266]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP266]], align 4 // CHECK11-NEXT: [[TMP267:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP267]], align 4 // CHECK11-NEXT: [[TMP268:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 2 @@ -11234,7 +11234,7 @@ int main() { // CHECK11-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK11-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP24]], align 4 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -11309,7 +11309,7 @@ int main() { // CHECK11-NEXT: [[ADD13:%.*]] = add nsw i32 [[TMP59]], 1 // CHECK11-NEXT: [[TMP60:%.*]] = zext i32 [[ADD13]] to i64 // CHECK11-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP61]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP61]], align 4 // CHECK11-NEXT: [[TMP62:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP62]], align 4 // CHECK11-NEXT: [[TMP63:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 @@ -11393,7 +11393,7 @@ int main() { // CHECK11-NEXT: [[ADD27:%.*]] = add nsw i32 [[TMP102]], 1 // CHECK11-NEXT: [[TMP103:%.*]] = zext i32 [[ADD27]] to i64 // CHECK11-NEXT: [[TMP104:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP104]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP104]], align 4 // CHECK11-NEXT: [[TMP105:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP105]], align 4 // CHECK11-NEXT: [[TMP106:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 2 @@ -11468,7 +11468,7 @@ int main() { // CHECK11-NEXT: [[ADD41:%.*]] = add nsw i32 [[TMP140]], 1 // CHECK11-NEXT: [[TMP141:%.*]] = zext i32 [[ADD41]] to i64 // CHECK11-NEXT: [[TMP142:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP142]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP142]], align 4 // CHECK11-NEXT: [[TMP143:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP143]], align 4 // CHECK11-NEXT: [[TMP144:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 2 @@ -11552,7 +11552,7 @@ int main() { // CHECK11-NEXT: [[ADD56:%.*]] = add nsw i32 [[TMP183]], 1 // CHECK11-NEXT: [[TMP184:%.*]] = zext i32 [[ADD56]] to i64 // CHECK11-NEXT: [[TMP185:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP185]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP185]], align 4 // CHECK11-NEXT: [[TMP186:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP186]], align 4 // CHECK11-NEXT: [[TMP187:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 2 @@ -11627,7 +11627,7 @@ int main() { // CHECK11-NEXT: [[ADD70:%.*]] = add nsw i32 [[TMP221]], 1 // CHECK11-NEXT: [[TMP222:%.*]] = zext i32 [[ADD70]] to i64 // CHECK11-NEXT: [[TMP223:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP223]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP223]], align 4 // CHECK11-NEXT: [[TMP224:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP224]], align 4 // CHECK11-NEXT: [[TMP225:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 2 @@ -11711,7 +11711,7 @@ int main() { // CHECK11-NEXT: [[ADD85:%.*]] = add nsw i32 [[TMP264]], 1 // CHECK11-NEXT: [[TMP265:%.*]] = zext i32 [[ADD85]] to i64 // CHECK11-NEXT: [[TMP266:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP266]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP266]], align 4 // CHECK11-NEXT: [[TMP267:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP267]], align 4 // CHECK11-NEXT: [[TMP268:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp index 6084a9a6cf931457adf3a907d3e46a2fcdde62a2..faae599bb32afe7adc1f015792b3e4be42275035 100644 --- a/clang/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp @@ -825,7 +825,7 @@ int main() { // CHECK8-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK8-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK8-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK8-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK8-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK8-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK8-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK8-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1251,7 +1251,7 @@ int main() { // CHECK8-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK8-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK8-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK8-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK8-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK8-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK8-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK8-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1744,7 +1744,7 @@ int main() { // CHECK10-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK10-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK10-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK10-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK10-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK10-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK10-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK10-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2164,7 +2164,7 @@ int main() { // CHECK10-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK10-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK10-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK10-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK10-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK10-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK10-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK10-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_parallel_for_if_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_if_codegen.cpp index d3b6654e57e2c99e76564e487d0ef5ce2d618eba..4b3911daefbad13de426b6c511153c7aefb98086 100644 --- a/clang/test/OpenMP/distribute_parallel_for_if_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_if_codegen.cpp @@ -128,7 +128,7 @@ int main() { // CHECK1-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -161,7 +161,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -492,7 +492,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS6:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -525,7 +525,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -569,7 +569,7 @@ int main() { // CHECK1-NEXT: [[TMP35:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP36:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP37]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK1-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP38]], align 4 // CHECK1-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -1060,7 +1060,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS6:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 [[ARG]], ptr [[ARG_ADDR]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1093,7 +1093,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -1137,7 +1137,7 @@ int main() { // CHECK1-NEXT: [[TMP35:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP36:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP37]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK1-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP38]], align 4 // CHECK1-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp index 1f069c4070aecfa81c4a4ff68cca35117a3ec905..18a86c5e5666399e8779fccaede3c0038f597693 100644 --- a/clang/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp @@ -801,7 +801,7 @@ int main() { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1263,7 +1263,7 @@ int main() { // CHECK9-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK9-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK9-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1793,7 +1793,7 @@ int main() { // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2249,7 +2249,7 @@ int main() { // CHECK11-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp index b6ae783b74d049cf833e4849bcab1ae5096046ef..dfe79d6a949342b2d9f2de7d48ca06ad5f0f97fd 100644 --- a/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp @@ -116,7 +116,7 @@ int main() { // CHECK1: invoke.cont: // CHECK1-NEXT: store i8 [[CALL]], ptr [[A]], align 1 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -169,7 +169,7 @@ int main() { // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -565,7 +565,7 @@ int main() { // CHECK1-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -598,7 +598,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -641,7 +641,7 @@ int main() { // CHECK1-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -674,7 +674,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -1368,7 +1368,7 @@ int main() { // CHECK5: invoke.cont: // CHECK5-NEXT: store i8 [[CALL]], ptr [[A]], align 1 // CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK5-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK5-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1421,7 +1421,7 @@ int main() { // CHECK5-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK5-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK5-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -1817,7 +1817,7 @@ int main() { // CHECK5-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK5-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK5-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1850,7 +1850,7 @@ int main() { // CHECK5-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK5: omp_offload.cont: // CHECK5-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK5-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK5-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -1893,7 +1893,7 @@ int main() { // CHECK5-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK5-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK5-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1926,7 +1926,7 @@ int main() { // CHECK5-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK5: omp_offload.cont: // CHECK5-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK5-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK5-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -2620,7 +2620,7 @@ int main() { // CHECK9: invoke.cont: // CHECK9-NEXT: store i8 [[CALL]], ptr [[A]], align 1 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2673,7 +2673,7 @@ int main() { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -3069,7 +3069,7 @@ int main() { // CHECK9-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK9-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3102,7 +3102,7 @@ int main() { // CHECK9-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK9: omp_offload.cont: // CHECK9-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK9-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -3145,7 +3145,7 @@ int main() { // CHECK9-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK9-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3178,7 +3178,7 @@ int main() { // CHECK9-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK9: omp_offload.cont: // CHECK9-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK9-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -3872,7 +3872,7 @@ int main() { // CHECK13: invoke.cont: // CHECK13-NEXT: store i8 [[CALL]], ptr [[A]], align 1 // CHECK13-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK13-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK13-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK13-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3925,7 +3925,7 @@ int main() { // CHECK13-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK13-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK13-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK13-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK13-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK13-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -4321,7 +4321,7 @@ int main() { // CHECK13-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK13-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK13-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK13-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK13-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK13-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4354,7 +4354,7 @@ int main() { // CHECK13-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK13: omp_offload.cont: // CHECK13-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK13-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK13-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK13-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -4397,7 +4397,7 @@ int main() { // CHECK13-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK13-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK13-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK13-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK13-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK13-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4430,7 +4430,7 @@ int main() { // CHECK13-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK13: omp_offload.cont: // CHECK13-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK13-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK13-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK13-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_parallel_for_private_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_private_codegen.cpp index e2b0d64093ebc0313e4502f4af5cdb4cb959bd0d..0969a0ca21e7ab56141c21f25661169dab8936d1 100644 --- a/clang/test/OpenMP/distribute_parallel_for_private_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_private_codegen.cpp @@ -521,7 +521,7 @@ int main() { // CHECK9-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 // CHECK9-NEXT: store ptr undef, ptr [[_TMP1]], align 8 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -842,7 +842,7 @@ int main() { // CHECK9-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 // CHECK9-NEXT: store ptr undef, ptr [[_TMP1]], align 8 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1232,7 +1232,7 @@ int main() { // CHECK11-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 // CHECK11-NEXT: store ptr undef, ptr [[_TMP1]], align 4 // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1547,7 +1547,7 @@ int main() { // CHECK11-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 // CHECK11-NEXT: store ptr undef, ptr [[_TMP1]], align 4 // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp index 040f90b9ef78bd269355e1ac757e5b4498472b20..c1203349b7c1bc78a4535d6f7f0c222ceea56c0c 100644 --- a/clang/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp @@ -63,7 +63,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -96,7 +96,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -414,7 +414,7 @@ int main() { // CHECK1-NEXT: [[TMP:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_codegen.cpp index 77336877e2be0427f853f0572766a4ee7dc8e551..a23d538910edd77f6f64d1b7f59e0c1941272f7d 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_codegen.cpp @@ -4762,7 +4762,7 @@ int main() { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK9-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP24]], align 4 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4837,7 +4837,7 @@ int main() { // CHECK9-NEXT: [[ADD13:%.*]] = add nsw i32 [[TMP59]], 1 // CHECK9-NEXT: [[TMP60:%.*]] = zext i32 [[ADD13]] to i64 // CHECK9-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP61]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP61]], align 4 // CHECK9-NEXT: [[TMP62:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP62]], align 4 // CHECK9-NEXT: [[TMP63:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 @@ -4921,7 +4921,7 @@ int main() { // CHECK9-NEXT: [[ADD27:%.*]] = add nsw i32 [[TMP102]], 1 // CHECK9-NEXT: [[TMP103:%.*]] = zext i32 [[ADD27]] to i64 // CHECK9-NEXT: [[TMP104:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP104]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP104]], align 4 // CHECK9-NEXT: [[TMP105:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP105]], align 4 // CHECK9-NEXT: [[TMP106:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 2 @@ -4996,7 +4996,7 @@ int main() { // CHECK9-NEXT: [[ADD41:%.*]] = add nsw i32 [[TMP140]], 1 // CHECK9-NEXT: [[TMP141:%.*]] = zext i32 [[ADD41]] to i64 // CHECK9-NEXT: [[TMP142:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP142]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP142]], align 4 // CHECK9-NEXT: [[TMP143:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP143]], align 4 // CHECK9-NEXT: [[TMP144:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 2 @@ -5080,7 +5080,7 @@ int main() { // CHECK9-NEXT: [[ADD56:%.*]] = add nsw i32 [[TMP183]], 1 // CHECK9-NEXT: [[TMP184:%.*]] = zext i32 [[ADD56]] to i64 // CHECK9-NEXT: [[TMP185:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP185]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP185]], align 4 // CHECK9-NEXT: [[TMP186:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP186]], align 4 // CHECK9-NEXT: [[TMP187:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 2 @@ -5155,7 +5155,7 @@ int main() { // CHECK9-NEXT: [[ADD70:%.*]] = add nsw i32 [[TMP221]], 1 // CHECK9-NEXT: [[TMP222:%.*]] = zext i32 [[ADD70]] to i64 // CHECK9-NEXT: [[TMP223:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP223]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP223]], align 4 // CHECK9-NEXT: [[TMP224:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP224]], align 4 // CHECK9-NEXT: [[TMP225:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 2 @@ -5239,7 +5239,7 @@ int main() { // CHECK9-NEXT: [[ADD85:%.*]] = add nsw i32 [[TMP264]], 1 // CHECK9-NEXT: [[TMP265:%.*]] = zext i32 [[ADD85]] to i64 // CHECK9-NEXT: [[TMP266:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP266]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP266]], align 4 // CHECK9-NEXT: [[TMP267:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP267]], align 4 // CHECK9-NEXT: [[TMP268:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 2 @@ -7229,7 +7229,7 @@ int main() { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK9-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP24]], align 4 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -7304,7 +7304,7 @@ int main() { // CHECK9-NEXT: [[ADD13:%.*]] = add nsw i32 [[TMP59]], 1 // CHECK9-NEXT: [[TMP60:%.*]] = zext i32 [[ADD13]] to i64 // CHECK9-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP61]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP61]], align 4 // CHECK9-NEXT: [[TMP62:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP62]], align 4 // CHECK9-NEXT: [[TMP63:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 @@ -7388,7 +7388,7 @@ int main() { // CHECK9-NEXT: [[ADD27:%.*]] = add nsw i32 [[TMP102]], 1 // CHECK9-NEXT: [[TMP103:%.*]] = zext i32 [[ADD27]] to i64 // CHECK9-NEXT: [[TMP104:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP104]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP104]], align 4 // CHECK9-NEXT: [[TMP105:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP105]], align 4 // CHECK9-NEXT: [[TMP106:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 2 @@ -7463,7 +7463,7 @@ int main() { // CHECK9-NEXT: [[ADD41:%.*]] = add nsw i32 [[TMP140]], 1 // CHECK9-NEXT: [[TMP141:%.*]] = zext i32 [[ADD41]] to i64 // CHECK9-NEXT: [[TMP142:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP142]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP142]], align 4 // CHECK9-NEXT: [[TMP143:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP143]], align 4 // CHECK9-NEXT: [[TMP144:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 2 @@ -7547,7 +7547,7 @@ int main() { // CHECK9-NEXT: [[ADD56:%.*]] = add nsw i32 [[TMP183]], 1 // CHECK9-NEXT: [[TMP184:%.*]] = zext i32 [[ADD56]] to i64 // CHECK9-NEXT: [[TMP185:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP185]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP185]], align 4 // CHECK9-NEXT: [[TMP186:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP186]], align 4 // CHECK9-NEXT: [[TMP187:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 2 @@ -7622,7 +7622,7 @@ int main() { // CHECK9-NEXT: [[ADD70:%.*]] = add nsw i32 [[TMP221]], 1 // CHECK9-NEXT: [[TMP222:%.*]] = zext i32 [[ADD70]] to i64 // CHECK9-NEXT: [[TMP223:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP223]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP223]], align 4 // CHECK9-NEXT: [[TMP224:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP224]], align 4 // CHECK9-NEXT: [[TMP225:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 2 @@ -7706,7 +7706,7 @@ int main() { // CHECK9-NEXT: [[ADD85:%.*]] = add nsw i32 [[TMP264]], 1 // CHECK9-NEXT: [[TMP265:%.*]] = zext i32 [[ADD85]] to i64 // CHECK9-NEXT: [[TMP266:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP266]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP266]], align 4 // CHECK9-NEXT: [[TMP267:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP267]], align 4 // CHECK9-NEXT: [[TMP268:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 2 @@ -9697,7 +9697,7 @@ int main() { // CHECK11-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK11-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP24]], align 4 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -9772,7 +9772,7 @@ int main() { // CHECK11-NEXT: [[ADD13:%.*]] = add nsw i32 [[TMP59]], 1 // CHECK11-NEXT: [[TMP60:%.*]] = zext i32 [[ADD13]] to i64 // CHECK11-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP61]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP61]], align 4 // CHECK11-NEXT: [[TMP62:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP62]], align 4 // CHECK11-NEXT: [[TMP63:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 @@ -9856,7 +9856,7 @@ int main() { // CHECK11-NEXT: [[ADD27:%.*]] = add nsw i32 [[TMP102]], 1 // CHECK11-NEXT: [[TMP103:%.*]] = zext i32 [[ADD27]] to i64 // CHECK11-NEXT: [[TMP104:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP104]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP104]], align 4 // CHECK11-NEXT: [[TMP105:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP105]], align 4 // CHECK11-NEXT: [[TMP106:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 2 @@ -9931,7 +9931,7 @@ int main() { // CHECK11-NEXT: [[ADD41:%.*]] = add nsw i32 [[TMP140]], 1 // CHECK11-NEXT: [[TMP141:%.*]] = zext i32 [[ADD41]] to i64 // CHECK11-NEXT: [[TMP142:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP142]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP142]], align 4 // CHECK11-NEXT: [[TMP143:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP143]], align 4 // CHECK11-NEXT: [[TMP144:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 2 @@ -10015,7 +10015,7 @@ int main() { // CHECK11-NEXT: [[ADD56:%.*]] = add nsw i32 [[TMP183]], 1 // CHECK11-NEXT: [[TMP184:%.*]] = zext i32 [[ADD56]] to i64 // CHECK11-NEXT: [[TMP185:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP185]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP185]], align 4 // CHECK11-NEXT: [[TMP186:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP186]], align 4 // CHECK11-NEXT: [[TMP187:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 2 @@ -10090,7 +10090,7 @@ int main() { // CHECK11-NEXT: [[ADD70:%.*]] = add nsw i32 [[TMP221]], 1 // CHECK11-NEXT: [[TMP222:%.*]] = zext i32 [[ADD70]] to i64 // CHECK11-NEXT: [[TMP223:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP223]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP223]], align 4 // CHECK11-NEXT: [[TMP224:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP224]], align 4 // CHECK11-NEXT: [[TMP225:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 2 @@ -10174,7 +10174,7 @@ int main() { // CHECK11-NEXT: [[ADD85:%.*]] = add nsw i32 [[TMP264]], 1 // CHECK11-NEXT: [[TMP265:%.*]] = zext i32 [[ADD85]] to i64 // CHECK11-NEXT: [[TMP266:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP266]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP266]], align 4 // CHECK11-NEXT: [[TMP267:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP267]], align 4 // CHECK11-NEXT: [[TMP268:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 2 @@ -12113,7 +12113,7 @@ int main() { // CHECK11-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK11-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP24]], align 4 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -12188,7 +12188,7 @@ int main() { // CHECK11-NEXT: [[ADD13:%.*]] = add nsw i32 [[TMP59]], 1 // CHECK11-NEXT: [[TMP60:%.*]] = zext i32 [[ADD13]] to i64 // CHECK11-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP61]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP61]], align 4 // CHECK11-NEXT: [[TMP62:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP62]], align 4 // CHECK11-NEXT: [[TMP63:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 @@ -12272,7 +12272,7 @@ int main() { // CHECK11-NEXT: [[ADD27:%.*]] = add nsw i32 [[TMP102]], 1 // CHECK11-NEXT: [[TMP103:%.*]] = zext i32 [[ADD27]] to i64 // CHECK11-NEXT: [[TMP104:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP104]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP104]], align 4 // CHECK11-NEXT: [[TMP105:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP105]], align 4 // CHECK11-NEXT: [[TMP106:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 2 @@ -12347,7 +12347,7 @@ int main() { // CHECK11-NEXT: [[ADD41:%.*]] = add nsw i32 [[TMP140]], 1 // CHECK11-NEXT: [[TMP141:%.*]] = zext i32 [[ADD41]] to i64 // CHECK11-NEXT: [[TMP142:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP142]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP142]], align 4 // CHECK11-NEXT: [[TMP143:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP143]], align 4 // CHECK11-NEXT: [[TMP144:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS42]], i32 0, i32 2 @@ -12431,7 +12431,7 @@ int main() { // CHECK11-NEXT: [[ADD56:%.*]] = add nsw i32 [[TMP183]], 1 // CHECK11-NEXT: [[TMP184:%.*]] = zext i32 [[ADD56]] to i64 // CHECK11-NEXT: [[TMP185:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP185]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP185]], align 4 // CHECK11-NEXT: [[TMP186:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP186]], align 4 // CHECK11-NEXT: [[TMP187:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS57]], i32 0, i32 2 @@ -12506,7 +12506,7 @@ int main() { // CHECK11-NEXT: [[ADD70:%.*]] = add nsw i32 [[TMP221]], 1 // CHECK11-NEXT: [[TMP222:%.*]] = zext i32 [[ADD70]] to i64 // CHECK11-NEXT: [[TMP223:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP223]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP223]], align 4 // CHECK11-NEXT: [[TMP224:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP224]], align 4 // CHECK11-NEXT: [[TMP225:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS71]], i32 0, i32 2 @@ -12590,7 +12590,7 @@ int main() { // CHECK11-NEXT: [[ADD85:%.*]] = add nsw i32 [[TMP264]], 1 // CHECK11-NEXT: [[TMP265:%.*]] = zext i32 [[ADD85]] to i64 // CHECK11-NEXT: [[TMP266:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP266]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP266]], align 4 // CHECK11-NEXT: [[TMP267:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP267]], align 4 // CHECK11-NEXT: [[TMP268:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS86]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp index f47b64b1e299d597f722b779b649e6f8dde3ce0b..545ea9f0f43fdf947b726afd6942d0001886171e 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp @@ -888,7 +888,7 @@ int main() { // CHECK8-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK8-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK8-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK8-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK8-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK8-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK8-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK8-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1328,7 +1328,7 @@ int main() { // CHECK8-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK8-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK8-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK8-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK8-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK8-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK8-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK8-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1835,7 +1835,7 @@ int main() { // CHECK10-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK10-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK10-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK10-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK10-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK10-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK10-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK10-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2269,7 +2269,7 @@ int main() { // CHECK10-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK10-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK10-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK10-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK10-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK10-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK10-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK10-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_if_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_if_codegen.cpp index b3e964fddcf0d7afa4ab343a766069974c5919cf..4a321b24b8c3135c50379cb5440ed0ef575d96c2 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_if_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_if_codegen.cpp @@ -125,7 +125,7 @@ int main() { // CHECK1-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -158,7 +158,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -517,7 +517,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS6:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -550,7 +550,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -594,7 +594,7 @@ int main() { // CHECK1-NEXT: [[TMP35:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP36:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP37]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK1-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP38]], align 4 // CHECK1-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -1127,7 +1127,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS6:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 [[ARG]], ptr [[ARG_ADDR]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1160,7 +1160,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -1204,7 +1204,7 @@ int main() { // CHECK1-NEXT: [[TMP35:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP36:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP37]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK1-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP38]], align 4 // CHECK1-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -1727,7 +1727,7 @@ int main() { // CHECK3-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK3-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1760,7 +1760,7 @@ int main() { // CHECK3-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK3: omp_offload.cont: // CHECK3-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -2119,7 +2119,7 @@ int main() { // CHECK3-NEXT: [[KERNEL_ARGS6:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK3-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2152,7 +2152,7 @@ int main() { // CHECK3-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK3: omp_offload.cont: // CHECK3-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -2196,7 +2196,7 @@ int main() { // CHECK3-NEXT: [[TMP35:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP36:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP37]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK3-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP38]], align 4 // CHECK3-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -2964,7 +2964,7 @@ int main() { // CHECK3-NEXT: [[KERNEL_ARGS6:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK3-NEXT: store i32 [[ARG]], ptr [[ARG_ADDR]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2997,7 +2997,7 @@ int main() { // CHECK3-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK3: omp_offload.cont: // CHECK3-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -3041,7 +3041,7 @@ int main() { // CHECK3-NEXT: [[TMP35:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP36:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP37]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK3-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP38]], align 4 // CHECK3-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -4140,7 +4140,7 @@ int main() { // CHECK9-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK9-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4173,7 +4173,7 @@ int main() { // CHECK9-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK9: omp_offload.cont: // CHECK9-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK9-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -4532,7 +4532,7 @@ int main() { // CHECK9-NEXT: [[KERNEL_ARGS6:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK9-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4565,7 +4565,7 @@ int main() { // CHECK9-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK9: omp_offload.cont: // CHECK9-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK9-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -4609,7 +4609,7 @@ int main() { // CHECK9-NEXT: [[TMP35:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP36:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP37]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK9-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP38]], align 4 // CHECK9-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -5142,7 +5142,7 @@ int main() { // CHECK9-NEXT: [[KERNEL_ARGS6:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK9-NEXT: store i32 [[ARG]], ptr [[ARG_ADDR]], align 4 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5175,7 +5175,7 @@ int main() { // CHECK9-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK9: omp_offload.cont: // CHECK9-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK9-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -5219,7 +5219,7 @@ int main() { // CHECK9-NEXT: [[TMP35:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP36:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP37]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK9-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP38]], align 4 // CHECK9-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -5742,7 +5742,7 @@ int main() { // CHECK11-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK11-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5775,7 +5775,7 @@ int main() { // CHECK11-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK11: omp_offload.cont: // CHECK11-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK11-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK11-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -6134,7 +6134,7 @@ int main() { // CHECK11-NEXT: [[KERNEL_ARGS6:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK11-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -6167,7 +6167,7 @@ int main() { // CHECK11-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK11: omp_offload.cont: // CHECK11-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK11-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK11-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -6211,7 +6211,7 @@ int main() { // CHECK11-NEXT: [[TMP35:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP36:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP37]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK11-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP38]], align 4 // CHECK11-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -6979,7 +6979,7 @@ int main() { // CHECK11-NEXT: [[KERNEL_ARGS6:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK11-NEXT: store i32 [[ARG]], ptr [[ARG_ADDR]], align 4 // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -7012,7 +7012,7 @@ int main() { // CHECK11-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK11: omp_offload.cont: // CHECK11-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK11-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK11-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -7056,7 +7056,7 @@ int main() { // CHECK11-NEXT: [[TMP35:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP36:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP37]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK11-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP38]], align 4 // CHECK11-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp index 7656fb7bc2c519dc68b62a97ee344c76052e2b60..675f1313460e659e5822f7375ff1a32bcd28fe38 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp @@ -868,7 +868,7 @@ int main() { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1344,7 +1344,7 @@ int main() { // CHECK9-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK9-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK9-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1888,7 +1888,7 @@ int main() { // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2358,7 +2358,7 @@ int main() { // CHECK11-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp index 9f4fffbea63d16e3357eafe2fdab8fa0af5e8486..5c1ca41b1c62d106041149fc284071626d3aa7fa 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp @@ -116,7 +116,7 @@ int main() { // CHECK1: invoke.cont: // CHECK1-NEXT: store i8 [[CALL]], ptr [[A]], align 1 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -169,7 +169,7 @@ int main() { // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -593,7 +593,7 @@ int main() { // CHECK1-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -626,7 +626,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -669,7 +669,7 @@ int main() { // CHECK1-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -702,7 +702,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -1791,7 +1791,7 @@ int main() { // CHECK5: invoke.cont: // CHECK5-NEXT: store i8 [[CALL]], ptr [[A]], align 1 // CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK5-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK5-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1844,7 +1844,7 @@ int main() { // CHECK5-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK5-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK5-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -2268,7 +2268,7 @@ int main() { // CHECK5-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK5-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK5-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2301,7 +2301,7 @@ int main() { // CHECK5-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK5: omp_offload.cont: // CHECK5-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK5-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK5-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -2344,7 +2344,7 @@ int main() { // CHECK5-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK5-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK5-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2377,7 +2377,7 @@ int main() { // CHECK5-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK5: omp_offload.cont: // CHECK5-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK5-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK5-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -3127,7 +3127,7 @@ int main() { // CHECK9: invoke.cont: // CHECK9-NEXT: store i8 [[CALL]], ptr [[A]], align 1 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3180,7 +3180,7 @@ int main() { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -3604,7 +3604,7 @@ int main() { // CHECK9-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK9-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3637,7 +3637,7 @@ int main() { // CHECK9-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK9: omp_offload.cont: // CHECK9-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK9-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -3680,7 +3680,7 @@ int main() { // CHECK9-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK9-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3713,7 +3713,7 @@ int main() { // CHECK9-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK9: omp_offload.cont: // CHECK9-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK9-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -4802,7 +4802,7 @@ int main() { // CHECK13: invoke.cont: // CHECK13-NEXT: store i8 [[CALL]], ptr [[A]], align 1 // CHECK13-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK13-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK13-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK13-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4855,7 +4855,7 @@ int main() { // CHECK13-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK13-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK13-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK13-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK13-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK13-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -5279,7 +5279,7 @@ int main() { // CHECK13-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK13-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK13-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK13-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK13-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK13-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5312,7 +5312,7 @@ int main() { // CHECK13-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK13: omp_offload.cont: // CHECK13-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK13-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK13-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK13-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -5355,7 +5355,7 @@ int main() { // CHECK13-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK13-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK13-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK13-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK13-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK13-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5388,7 +5388,7 @@ int main() { // CHECK13-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK13: omp_offload.cont: // CHECK13-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK13-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK13-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK13-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_private_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_private_codegen.cpp index 61f35d8b456cea954a88940053a19d7f58634731..a74af2d7c3932044ea650144b94ea6cacaf2d981 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_private_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_private_codegen.cpp @@ -575,7 +575,7 @@ int main() { // CHECK9-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 // CHECK9-NEXT: store ptr undef, ptr [[_TMP1]], align 8 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -910,7 +910,7 @@ int main() { // CHECK9-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 // CHECK9-NEXT: store ptr undef, ptr [[_TMP1]], align 8 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1314,7 +1314,7 @@ int main() { // CHECK11-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 // CHECK11-NEXT: store ptr undef, ptr [[_TMP1]], align 4 // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1643,7 +1643,7 @@ int main() { // CHECK11-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 // CHECK11-NEXT: store ptr undef, ptr [[_TMP1]], align 4 // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp index 334965f59a826dba4ab7cc2cd59f4b1af33e1d1a..777d4a25ea9f346801d8e289320976cb36c7b67a 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp @@ -63,7 +63,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -96,7 +96,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -442,7 +442,7 @@ int main() { // CHECK1-NEXT: [[TMP:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_private_codegen.cpp b/clang/test/OpenMP/distribute_private_codegen.cpp index 8a47b15a24d2423ca8ee61513b660a255fd6c254..b6e796fb8027c05168fb1fdefce7e3fd79ce5410 100644 --- a/clang/test/OpenMP/distribute_private_codegen.cpp +++ b/clang/test/OpenMP/distribute_private_codegen.cpp @@ -351,7 +351,7 @@ int main() { // CHECK9-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 // CHECK9-NEXT: store ptr undef, ptr [[_TMP1]], align 8 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -384,7 +384,7 @@ int main() { // CHECK9-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK9: omp_offload.cont: // CHECK9-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS3]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK9-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS3]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS3]], i32 0, i32 2 @@ -668,7 +668,7 @@ int main() { // CHECK9-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 // CHECK9-NEXT: store ptr undef, ptr [[_TMP1]], align 8 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -957,7 +957,7 @@ int main() { // CHECK11-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 // CHECK11-NEXT: store ptr undef, ptr [[_TMP1]], align 4 // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -990,7 +990,7 @@ int main() { // CHECK11-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK11: omp_offload.cont: // CHECK11-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS3]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK11-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS3]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK11-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS3]], i32 0, i32 2 @@ -1272,7 +1272,7 @@ int main() { // CHECK11-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 // CHECK11-NEXT: store ptr undef, ptr [[_TMP1]], align 4 // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_simd_codegen.cpp b/clang/test/OpenMP/distribute_simd_codegen.cpp index 16d909e329514f7a117cbc88d815765a918721c1..9a192502125f9673c4b13608fed565e37acf03e4 100644 --- a/clang/test/OpenMP/distribute_simd_codegen.cpp +++ b/clang/test/OpenMP/distribute_simd_codegen.cpp @@ -191,7 +191,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -391,7 +391,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -589,7 +589,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -806,7 +806,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK1-NEXT: [[ADD4:%.*]] = add nsw i32 [[TMP14]], 1 // CHECK1-NEXT: [[TMP15:%.*]] = zext i32 [[ADD4]] to i64 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP17]], align 4 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -996,7 +996,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1176,7 +1176,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1372,7 +1372,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1566,7 +1566,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1779,7 +1779,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK3-NEXT: [[ADD4:%.*]] = add nsw i32 [[TMP14]], 1 // CHECK3-NEXT: [[TMP15:%.*]] = zext i32 [[ADD4]] to i64 // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP17]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1969,7 +1969,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2149,7 +2149,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK5-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK5-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK5-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2349,7 +2349,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK5-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK5-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK5-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2547,7 +2547,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK5-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK5-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK5-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2764,7 +2764,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK5-NEXT: [[ADD4:%.*]] = add nsw i32 [[TMP14]], 1 // CHECK5-NEXT: [[TMP15:%.*]] = zext i32 [[ADD4]] to i64 // CHECK5-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK5-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 2, ptr [[TMP17]], align 4 // CHECK5-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2985,7 +2985,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK5-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK5-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK5-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3165,7 +3165,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK7-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK7-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK7-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3361,7 +3361,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK7-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK7-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK7-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3555,7 +3555,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK7-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK7-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK7-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3768,7 +3768,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK7-NEXT: [[ADD4:%.*]] = add nsw i32 [[TMP14]], 1 // CHECK7-NEXT: [[TMP15:%.*]] = zext i32 [[ADD4]] to i64 // CHECK7-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK7-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 2, ptr [[TMP17]], align 4 // CHECK7-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3989,7 +3989,7 @@ int fint(void) { return ftemplate<int>(); } // CHECK7-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK7-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK7-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_simd_firstprivate_codegen.cpp b/clang/test/OpenMP/distribute_simd_firstprivate_codegen.cpp index e388393c37f18d2a08e60000970d80f2df0d7269..1b5950ce11d7fa2af7edcdfdde6fd55213266424 100644 --- a/clang/test/OpenMP/distribute_simd_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_simd_firstprivate_codegen.cpp @@ -595,7 +595,7 @@ int main() { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -898,7 +898,7 @@ int main() { // CHECK9-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK9-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK9-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1274,7 +1274,7 @@ int main() { // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1575,7 +1575,7 @@ int main() { // CHECK11-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/distribute_simd_lastprivate_codegen.cpp index 5720c3aaaaff5278eea28bc8cdb2c922ac28d1e5..92b73b220bcc218e30c0e86b180df8b4aa1636b1 100644 --- a/clang/test/OpenMP/distribute_simd_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/distribute_simd_lastprivate_codegen.cpp @@ -582,7 +582,7 @@ int main() { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -903,7 +903,7 @@ int main() { // CHECK9-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK9-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK9-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1298,7 +1298,7 @@ int main() { // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1617,7 +1617,7 @@ int main() { // CHECK11-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_simd_private_codegen.cpp b/clang/test/OpenMP/distribute_simd_private_codegen.cpp index eac5bce7d5da80fe138e211f5767ef8956b175a8..93b2bd8b12a8ee3b738b7b950d7bf4c3c9a08799 100644 --- a/clang/test/OpenMP/distribute_simd_private_codegen.cpp +++ b/clang/test/OpenMP/distribute_simd_private_codegen.cpp @@ -396,7 +396,7 @@ int main() { // CHECK9-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 // CHECK9-NEXT: store ptr undef, ptr [[_TMP1]], align 8 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -440,7 +440,7 @@ int main() { // CHECK9-NEXT: [[TMP20:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP21:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS3]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP22]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP22]], align 4 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS3]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS3]], i32 0, i32 2 @@ -742,7 +742,7 @@ int main() { // CHECK9-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 // CHECK9-NEXT: store ptr undef, ptr [[_TMP1]], align 8 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1042,7 +1042,7 @@ int main() { // CHECK11-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 // CHECK11-NEXT: store ptr undef, ptr [[_TMP1]], align 4 // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1086,7 +1086,7 @@ int main() { // CHECK11-NEXT: [[TMP20:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP21:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS3]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP22]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP22]], align 4 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS3]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS3]], i32 0, i32 2 @@ -1386,7 +1386,7 @@ int main() { // CHECK11-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 // CHECK11-NEXT: store ptr undef, ptr [[_TMP1]], align 4 // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/distribute_simd_reduction_codegen.cpp b/clang/test/OpenMP/distribute_simd_reduction_codegen.cpp index 31d276e984eee2fa138a494a3828492c50d9c648..b6cc1adfc76beb456c7096ca6702f904ce3abcca 100644 --- a/clang/test/OpenMP/distribute_simd_reduction_codegen.cpp +++ b/clang/test/OpenMP/distribute_simd_reduction_codegen.cpp @@ -105,7 +105,7 @@ int main() { // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -255,7 +255,7 @@ int main() { // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -402,7 +402,7 @@ int main() { // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -552,7 +552,7 @@ int main() { // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/map_struct_ordering.cpp b/clang/test/OpenMP/map_struct_ordering.cpp index dd0bb8e9d6e7cdb1083f2886798d6dfa5e54f75d..e422010f3dcdfa393c625db5cc8e556198fa8d6b 100644 --- a/clang/test/OpenMP/map_struct_ordering.cpp +++ b/clang/test/OpenMP/map_struct_ordering.cpp @@ -97,7 +97,7 @@ int map_struct() { // CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS4]], i32 0, i32 0 // CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS5]], i32 0, i32 0 // CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP24]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[TMP25]], align 4 // CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/nvptx_lambda_capturing.cpp b/clang/test/OpenMP/nvptx_lambda_capturing.cpp index 5d7da793e73267fd0a1ad2005e5bf9e28e8db276..86035e17ef3b60da4de1e859f2ac70eb6233c738 100644 --- a/clang/test/OpenMP/nvptx_lambda_capturing.cpp +++ b/clang/test/OpenMP/nvptx_lambda_capturing.cpp @@ -191,7 +191,7 @@ int main(int argc, char **argv) { // CHECK1-NEXT: [[TMP64:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP65:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP66]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP66]], align 4 // CHECK1-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 11, ptr [[TMP67]], align 4 // CHECK1-NEXT: [[TMP68:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -317,7 +317,7 @@ int main(int argc, char **argv) { // CHECK1-NEXT: [[TMP136:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0 // CHECK1-NEXT: [[TMP137:%.*]] = getelementptr inbounds [11 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0 // CHECK1-NEXT: [[TMP138:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP138]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP138]], align 4 // CHECK1-NEXT: [[TMP139:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 1 // CHECK1-NEXT: store i32 11, ptr [[TMP139]], align 4 // CHECK1-NEXT: [[TMP140:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 2 @@ -541,7 +541,7 @@ int main(int argc, char **argv) { // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -599,7 +599,7 @@ int main(int argc, char **argv) { // CHECK1-NEXT: [[TMP44:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP45:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP46]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP46]], align 4 // CHECK1-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP47]], align 4 // CHECK1-NEXT: [[TMP48:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -744,7 +744,7 @@ int main(int argc, char **argv) { // CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP11:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP12]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP12]], align 4 // CHECK1-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP13]], align 4 // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/openmp_check.cpp b/clang/test/OpenMP/openmp_check.cpp index 6a8dd17fc8367fe4e2967256f11305ea5106d5f5..b52ce0c066922aa3275b009ee41535705f275efb 100644 --- a/clang/test/OpenMP/openmp_check.cpp +++ b/clang/test/OpenMP/openmp_check.cpp @@ -18,7 +18,7 @@ int nested(int a) { auto F = [&]() { #if __cplusplus <= 199711L // expected-warning@-2 {{'auto' type specifier is a C++11 extension}} - // expected-error@-3 {{expected expression}} + // expected-warning@-3 {{lambdas are a C++11 extension}} #endif #pragma omp parallel diff --git a/clang/test/OpenMP/reduction_implicit_map.cpp b/clang/test/OpenMP/reduction_implicit_map.cpp index 7305c56289e01b68464427ba1660125ca645a0de..0f67cdc56ddcf818a5120f3cfa2fc283798590a0 100644 --- a/clang/test/OpenMP/reduction_implicit_map.cpp +++ b/clang/test/OpenMP/reduction_implicit_map.cpp @@ -318,7 +318,7 @@ int main() // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -359,7 +359,7 @@ int main() // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 2 @@ -890,7 +890,7 @@ int main() // CHECK2-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP26]], 1 // CHECK2-NEXT: [[TMP27:%.*]] = zext i32 [[ADD]] to i64 // CHECK2-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK2-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK2-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK2-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -971,7 +971,7 @@ int main() // CHECK2-NEXT: [[ADD17:%.*]] = add nsw i32 [[TMP69]], 1 // CHECK2-NEXT: [[TMP70:%.*]] = zext i32 [[ADD17]] to i64 // CHECK2-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP71]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP71]], align 4 // CHECK2-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 1 // CHECK2-NEXT: store i32 3, ptr [[TMP72]], align 4 // CHECK2-NEXT: [[TMP73:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 2 @@ -1022,7 +1022,7 @@ int main() // CHECK2-NEXT: [[TMP94:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0 // CHECK2-NEXT: [[TMP95:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0 // CHECK2-NEXT: [[TMP96:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP96]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP96]], align 4 // CHECK2-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 1 // CHECK2-NEXT: store i32 2, ptr [[TMP97]], align 4 // CHECK2-NEXT: [[TMP98:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 2 @@ -1073,7 +1073,7 @@ int main() // CHECK2-NEXT: [[TMP119:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS31]], i32 0, i32 0 // CHECK2-NEXT: [[TMP120:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS32]], i32 0, i32 0 // CHECK2-NEXT: [[TMP121:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP121]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP121]], align 4 // CHECK2-NEXT: [[TMP122:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 1 // CHECK2-NEXT: store i32 2, ptr [[TMP122]], align 4 // CHECK2-NEXT: [[TMP123:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS34]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_codegen_global_capture.cpp b/clang/test/OpenMP/target_codegen_global_capture.cpp index 0fb52c3fa6c55c98e2bc1de67ca94862260e2b0d..d2c800a56a104abb01fa6d6369531dbe1cf7fae4 100644 --- a/clang/test/OpenMP/target_codegen_global_capture.cpp +++ b/clang/test/OpenMP/target_codegen_global_capture.cpp @@ -288,7 +288,7 @@ int tbar2(short a, short b, short c, short d){ // CHECK1-NEXT: [[TMP48:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP49:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP50]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP50]], align 4 // CHECK1-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 9, ptr [[TMP51]], align 4 // CHECK1-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -615,7 +615,7 @@ int tbar2(short a, short b, short c, short d){ // CHECK1-NEXT: [[TMP52:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP53:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP54:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP54]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP54]], align 4 // CHECK1-NEXT: [[TMP55:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 9, ptr [[TMP55]], align 4 // CHECK1-NEXT: [[TMP56:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -938,7 +938,7 @@ int tbar2(short a, short b, short c, short d){ // CHECK1-NEXT: [[TMP52:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP53:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP54:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP54]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP54]], align 4 // CHECK1-NEXT: [[TMP55:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 9, ptr [[TMP55]], align 4 // CHECK1-NEXT: [[TMP56:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1184,7 +1184,7 @@ int tbar2(short a, short b, short c, short d){ // CHECK3-NEXT: [[TMP42:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP43:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP44:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP44]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP44]], align 4 // CHECK3-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 9, ptr [[TMP45]], align 4 // CHECK3-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1511,7 +1511,7 @@ int tbar2(short a, short b, short c, short d){ // CHECK3-NEXT: [[TMP46:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP47:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP48:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP48]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP48]], align 4 // CHECK3-NEXT: [[TMP49:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 9, ptr [[TMP49]], align 4 // CHECK3-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1834,7 +1834,7 @@ int tbar2(short a, short b, short c, short d){ // CHECK3-NEXT: [[TMP46:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP47:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP48:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP48]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP48]], align 4 // CHECK3-NEXT: [[TMP49:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 9, ptr [[TMP49]], align 4 // CHECK3-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_data_use_device_ptr_inheritance_codegen.cpp b/clang/test/OpenMP/target_data_use_device_ptr_inheritance_codegen.cpp index 3db18643d3f033df01301eb46bbaec8d5f268105..20d3bd2ce11c32fddfaa578ce29d73c130eb416e 100644 --- a/clang/test/OpenMP/target_data_use_device_ptr_inheritance_codegen.cpp +++ b/clang/test/OpenMP/target_data_use_device_ptr_inheritance_codegen.cpp @@ -91,7 +91,7 @@ void foo() { // CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 // CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK-NEXT: call void @_ZN1AC2Ev(ptr noundef nonnull align 8 dereferenceable(16) [[THIS1]]) #[[ATTR1]] -// CHECK-NEXT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, inrange i32 0, i32 2), ptr [[THIS1]], align 8 +// CHECK-NEXT: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 2), ptr [[THIS1]], align 8 // CHECK-NEXT: ret void // CHECK-LABEL: define {{[^@]+}}@_ZN1AC2Ev // CHECK-SAME: (ptr noundef nonnull align 8 dereferenceable(16) [[THIS:%.*]]) unnamed_addr #[[ATTR2]] comdat align 2 { @@ -99,7 +99,7 @@ void foo() { // CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 // CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK-NEXT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, inrange i32 0, i32 2), ptr [[THIS1]], align 8 +// CHECK-NEXT: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 2), ptr [[THIS1]], align 8 // CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [[CLASS_A:%.*]], ptr [[THIS1]], i32 0, i32 1 // CHECK-NEXT: store ptr null, ptr [[PTR]], align 8 // CHECK-NEXT: ret void @@ -168,7 +168,7 @@ void foo() { // CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: call void @_ZN1AC2Ev(ptr noundef nonnull align 8 dereferenceable(16) [[THIS1]]) #[[ATTR1]] -// CHECK1-NEXT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, inrange i32 0, i32 2), ptr [[THIS1]], align 8 +// CHECK1-NEXT: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 2), ptr [[THIS1]], align 8 // CHECK1-NEXT: ret void // // @@ -178,7 +178,7 @@ void foo() { // CHECK1-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 // CHECK1-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 // CHECK1-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 -// CHECK1-NEXT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, inrange i32 0, i32 2), ptr [[THIS1]], align 8 +// CHECK1-NEXT: store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 2), ptr [[THIS1]], align 8 // CHECK1-NEXT: [[PTR:%.*]] = getelementptr inbounds [[CLASS_A:%.*]], ptr [[THIS1]], i32 0, i32 1 // CHECK1-NEXT: store ptr null, ptr [[PTR]], align 8 // CHECK1-NEXT: ret void @@ -249,7 +249,7 @@ void foo() { // CHECK2-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 // CHECK2-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 // CHECK2-NEXT: call void @_ZN1AC2Ev(ptr noundef nonnull align 4 dereferenceable(8) [[THIS1]]) #[[ATTR1]] -// CHECK2-NEXT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, inrange i32 0, i32 2), ptr [[THIS1]], align 4 +// CHECK2-NEXT: store ptr getelementptr inbounds inrange(-8, 4) ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 2), ptr [[THIS1]], align 4 // CHECK2-NEXT: ret void // // @@ -259,7 +259,7 @@ void foo() { // CHECK2-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 4 // CHECK2-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 4 // CHECK2-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 4 -// CHECK2-NEXT: store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, inrange i32 0, i32 2), ptr [[THIS1]], align 4 +// CHECK2-NEXT: store ptr getelementptr inbounds inrange(-8, 4) ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 2), ptr [[THIS1]], align 4 // CHECK2-NEXT: [[PTR:%.*]] = getelementptr inbounds [[CLASS_A:%.*]], ptr [[THIS1]], i32 0, i32 1 // CHECK2-NEXT: store ptr null, ptr [[PTR]], align 4 // CHECK2-NEXT: ret void diff --git a/clang/test/OpenMP/target_firstprivate_codegen.cpp b/clang/test/OpenMP/target_firstprivate_codegen.cpp index 6314940730470ed3a2e1965080fd3ff1b9d35c0d..02de48e6aa395666dea3cef7154f867ffa1e124b 100644 --- a/clang/test/OpenMP/target_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/target_firstprivate_codegen.cpp @@ -6159,7 +6159,7 @@ int bar(int n, double *ptr) { // CHECK0-NEXT: [[TMP22:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK0-NEXT: [[TMP23:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK0-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK0-NEXT: store i32 2, ptr [[TMP24]], align 4 +// CHECK0-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK0-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK0-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK0-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -6260,7 +6260,7 @@ int bar(int n, double *ptr) { // CHECK0-NEXT: [[TMP74:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 // CHECK0-NEXT: [[TMP75:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK0-NEXT: [[TMP76:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK0-NEXT: store i32 2, ptr [[TMP76]], align 4 +// CHECK0-NEXT: store i32 3, ptr [[TMP76]], align 4 // CHECK0-NEXT: [[TMP77:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK0-NEXT: store i32 9, ptr [[TMP77]], align 4 // CHECK0-NEXT: [[TMP78:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -6308,7 +6308,7 @@ int bar(int n, double *ptr) { // CHECK0-NEXT: [[TMP98:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK0-NEXT: [[TMP99:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK0-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS11]], i32 0, i32 0 -// CHECK0-NEXT: store i32 2, ptr [[TMP100]], align 4 +// CHECK0-NEXT: store i32 3, ptr [[TMP100]], align 4 // CHECK0-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS11]], i32 0, i32 1 // CHECK0-NEXT: store i32 2, ptr [[TMP101]], align 4 // CHECK0-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS11]], i32 0, i32 2 @@ -6564,7 +6564,7 @@ int bar(int n, double *ptr) { // CHECK0-NEXT: [[TMP26:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK0-NEXT: [[TMP27:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK0-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK0-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK0-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK0-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK0-NEXT: store i32 5, ptr [[TMP29]], align 4 // CHECK0-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -6651,7 +6651,7 @@ int bar(int n, double *ptr) { // CHECK0-NEXT: [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK0-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK0-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK0-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK0-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK0-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK0-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK0-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -6718,7 +6718,7 @@ int bar(int n, double *ptr) { // CHECK0-NEXT: [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK0-NEXT: [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK0-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK0-NEXT: store i32 2, ptr [[TMP10]], align 4 +// CHECK0-NEXT: store i32 3, ptr [[TMP10]], align 4 // CHECK0-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK0-NEXT: store i32 2, ptr [[TMP11]], align 4 // CHECK0-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -6930,7 +6930,7 @@ int bar(int n, double *ptr) { // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP24]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -7031,7 +7031,7 @@ int bar(int n, double *ptr) { // CHECK1-NEXT: [[TMP74:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP75:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK1-NEXT: [[TMP76:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP76]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP76]], align 4 // CHECK1-NEXT: [[TMP77:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK1-NEXT: store i32 9, ptr [[TMP77]], align 4 // CHECK1-NEXT: [[TMP78:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -7079,7 +7079,7 @@ int bar(int n, double *ptr) { // CHECK1-NEXT: [[TMP98:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK1-NEXT: [[TMP99:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK1-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS11]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP100]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP100]], align 4 // CHECK1-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS11]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP101]], align 4 // CHECK1-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS11]], i32 0, i32 2 @@ -7335,7 +7335,7 @@ int bar(int n, double *ptr) { // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP29]], align 4 // CHECK1-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -7422,7 +7422,7 @@ int bar(int n, double *ptr) { // CHECK1-NEXT: [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -7489,7 +7489,7 @@ int bar(int n, double *ptr) { // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP10]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP10]], align 4 // CHECK1-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP11]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -7699,7 +7699,7 @@ int bar(int n, double *ptr) { // CHECK2-NEXT: [[TMP20:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK2-NEXT: [[TMP21:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK2-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP22]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP22]], align 4 // CHECK2-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK2-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK2-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -7802,7 +7802,7 @@ int bar(int n, double *ptr) { // CHECK2-NEXT: [[TMP74:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 // CHECK2-NEXT: [[TMP75:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK2-NEXT: [[TMP76:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP76]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP76]], align 4 // CHECK2-NEXT: [[TMP77:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK2-NEXT: store i32 9, ptr [[TMP77]], align 4 // CHECK2-NEXT: [[TMP78:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -7850,7 +7850,7 @@ int bar(int n, double *ptr) { // CHECK2-NEXT: [[TMP98:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK2-NEXT: [[TMP99:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK2-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS11]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP100]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP100]], align 4 // CHECK2-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS11]], i32 0, i32 1 // CHECK2-NEXT: store i32 2, ptr [[TMP101]], align 4 // CHECK2-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS11]], i32 0, i32 2 @@ -8106,7 +8106,7 @@ int bar(int n, double *ptr) { // CHECK2-NEXT: [[TMP26:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK2-NEXT: [[TMP27:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK2-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK2-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK2-NEXT: store i32 5, ptr [[TMP29]], align 4 // CHECK2-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -8193,7 +8193,7 @@ int bar(int n, double *ptr) { // CHECK2-NEXT: [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK2-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK2-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK2-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK2-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK2-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -8260,7 +8260,7 @@ int bar(int n, double *ptr) { // CHECK2-NEXT: [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK2-NEXT: [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK2-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP10]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP10]], align 4 // CHECK2-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK2-NEXT: store i32 2, ptr [[TMP11]], align 4 // CHECK2-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -8470,7 +8470,7 @@ int bar(int n, double *ptr) { // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP22]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP22]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK3-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -8573,7 +8573,7 @@ int bar(int n, double *ptr) { // CHECK3-NEXT: [[TMP74:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP75:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK3-NEXT: [[TMP76:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP76]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP76]], align 4 // CHECK3-NEXT: [[TMP77:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK3-NEXT: store i32 9, ptr [[TMP77]], align 4 // CHECK3-NEXT: [[TMP78:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -8621,7 +8621,7 @@ int bar(int n, double *ptr) { // CHECK3-NEXT: [[TMP98:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK3-NEXT: [[TMP99:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK3-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS11]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP100]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP100]], align 4 // CHECK3-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS11]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP101]], align 4 // CHECK3-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS11]], i32 0, i32 2 @@ -8877,7 +8877,7 @@ int bar(int n, double *ptr) { // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK3-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP29]], align 4 // CHECK3-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -8964,7 +8964,7 @@ int bar(int n, double *ptr) { // CHECK3-NEXT: [[TMP13:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -9031,7 +9031,7 @@ int bar(int n, double *ptr) { // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP10]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP10]], align 4 // CHECK3-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP11]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_has_device_addr_codegen.cpp b/clang/test/OpenMP/target_has_device_addr_codegen.cpp index e6a0e7bb38d646e9fef44620712b162e6774eeab..ba1b618ed8bdd7252320a5080874f2a2c971efb7 100644 --- a/clang/test/OpenMP/target_has_device_addr_codegen.cpp +++ b/clang/test/OpenMP/target_has_device_addr_codegen.cpp @@ -328,7 +328,7 @@ void use_template() { // CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP6]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP6]], align 4 // CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[TMP7]], align 4 // CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -372,7 +372,7 @@ void use_template() { // CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[TMP29]], align 4 // CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 2 @@ -413,7 +413,7 @@ void use_template() { // CHECK-NEXT: [[TMP46:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0 // CHECK-NEXT: [[TMP47:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0 // CHECK-NEXT: [[TMP48:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP48]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP48]], align 4 // CHECK-NEXT: [[TMP49:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[TMP49]], align 4 // CHECK-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 2 @@ -457,7 +457,7 @@ void use_template() { // CHECK-NEXT: [[TMP68:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS14]], i32 0, i32 0 // CHECK-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS15]], i32 0, i32 0 // CHECK-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP70]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP70]], align 4 // CHECK-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[TMP71]], align 4 // CHECK-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 2 @@ -498,7 +498,7 @@ void use_template() { // CHECK-NEXT: [[TMP88:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS20]], i32 0, i32 0 // CHECK-NEXT: [[TMP89:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS21]], i32 0, i32 0 // CHECK-NEXT: [[TMP90:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP90]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP90]], align 4 // CHECK-NEXT: [[TMP91:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[TMP91]], align 4 // CHECK-NEXT: [[TMP92:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -539,7 +539,7 @@ void use_template() { // CHECK-NEXT: [[TMP108:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS26]], i32 0, i32 0 // CHECK-NEXT: [[TMP109:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS27]], i32 0, i32 0 // CHECK-NEXT: [[TMP110:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS29]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP110]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP110]], align 4 // CHECK-NEXT: [[TMP111:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS29]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[TMP111]], align 4 // CHECK-NEXT: [[TMP112:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS29]], i32 0, i32 2 @@ -705,7 +705,7 @@ void use_template() { // CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP6]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP6]], align 4 // CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[TMP7]], align 4 // CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -749,7 +749,7 @@ void use_template() { // CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[TMP29]], align 4 // CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 2 @@ -790,7 +790,7 @@ void use_template() { // CHECK-NEXT: [[TMP46:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0 // CHECK-NEXT: [[TMP47:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0 // CHECK-NEXT: [[TMP48:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP48]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP48]], align 4 // CHECK-NEXT: [[TMP49:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[TMP49]], align 4 // CHECK-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 2 @@ -831,7 +831,7 @@ void use_template() { // CHECK-NEXT: [[TMP66:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS13]], i32 0, i32 0 // CHECK-NEXT: [[TMP67:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS14]], i32 0, i32 0 // CHECK-NEXT: [[TMP68:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP68]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP68]], align 4 // CHECK-NEXT: [[TMP69:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[TMP69]], align 4 // CHECK-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 2 @@ -911,7 +911,7 @@ void use_template() { // CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP6]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP6]], align 4 // CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[TMP7]], align 4 // CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -955,7 +955,7 @@ void use_template() { // CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[TMP29]], align 4 // CHECK-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 2 @@ -996,7 +996,7 @@ void use_template() { // CHECK-NEXT: [[TMP46:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0 // CHECK-NEXT: [[TMP47:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0 // CHECK-NEXT: [[TMP48:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP48]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP48]], align 4 // CHECK-NEXT: [[TMP49:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[TMP49]], align 4 // CHECK-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 2 @@ -1037,7 +1037,7 @@ void use_template() { // CHECK-NEXT: [[TMP66:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS13]], i32 0, i32 0 // CHECK-NEXT: [[TMP67:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS14]], i32 0, i32 0 // CHECK-NEXT: [[TMP68:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP68]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP68]], align 4 // CHECK-NEXT: [[TMP69:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[TMP69]], align 4 // CHECK-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 2 @@ -1239,7 +1239,7 @@ void use_template() { // CHECK-NEXT: [[TMP19:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 // CHECK-NEXT: [[TMP20:%.*]] = sext i32 [[TMP19]] to i64 // CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-NEXT: store i32 3, ptr [[TMP22]], align 4 // CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_has_device_addr_codegen_01.cpp b/clang/test/OpenMP/target_has_device_addr_codegen_01.cpp index efd0a1ee88fe23e407327ba255c88c475f6c60c8..6bbabdf51f6e7d3bdb1e84b986a8217557de5b91 100644 --- a/clang/test/OpenMP/target_has_device_addr_codegen_01.cpp +++ b/clang/test/OpenMP/target_has_device_addr_codegen_01.cpp @@ -102,7 +102,7 @@ int main() { // CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds [6 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds [6 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP26]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP26]], align 4 // CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-NEXT: store i32 6, ptr [[TMP27]], align 4 // CHECK-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -211,7 +211,7 @@ int main() { // CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_is_device_ptr_codegen.cpp b/clang/test/OpenMP/target_is_device_ptr_codegen.cpp index 162f18529a489d32fbe27d8cdac952a693f1a328..190032023aed394b69d919d583e916b779f9f5c6 100644 --- a/clang/test/OpenMP/target_is_device_ptr_codegen.cpp +++ b/clang/test/OpenMP/target_is_device_ptr_codegen.cpp @@ -1827,7 +1827,7 @@ void bar() { // CK10-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CK10-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CK10-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CK10-NEXT: store i32 2, ptr [[TMP6]], align 4 +// CK10-NEXT: store i32 3, ptr [[TMP6]], align 4 // CK10-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CK10-NEXT: store i32 1, ptr [[TMP7]], align 4 // CK10-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1869,7 +1869,7 @@ void bar() { // CK10-NEXT: [[TMP25:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CK10-NEXT: [[TMP26:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CK10-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 0 -// CK10-NEXT: store i32 2, ptr [[TMP27]], align 4 +// CK10-NEXT: store i32 3, ptr [[TMP27]], align 4 // CK10-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 1 // CK10-NEXT: store i32 1, ptr [[TMP28]], align 4 // CK10-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 2 @@ -1911,7 +1911,7 @@ void bar() { // CK10-NEXT: [[TMP46:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0 // CK10-NEXT: [[TMP47:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0 // CK10-NEXT: [[TMP48:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 0 -// CK10-NEXT: store i32 2, ptr [[TMP48]], align 4 +// CK10-NEXT: store i32 3, ptr [[TMP48]], align 4 // CK10-NEXT: [[TMP49:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 1 // CK10-NEXT: store i32 1, ptr [[TMP49]], align 4 // CK10-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 2 @@ -1956,7 +1956,7 @@ void bar() { // CK10-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS13]], i32 0, i32 0 // CK10-NEXT: [[TMP70:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS14]], i32 0, i32 0 // CK10-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 0 -// CK10-NEXT: store i32 2, ptr [[TMP71]], align 4 +// CK10-NEXT: store i32 3, ptr [[TMP71]], align 4 // CK10-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 1 // CK10-NEXT: store i32 1, ptr [[TMP72]], align 4 // CK10-NEXT: [[TMP73:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 2 @@ -2001,7 +2001,7 @@ void bar() { // CK10-NEXT: [[TMP92:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS20]], i32 0, i32 0 // CK10-NEXT: [[TMP93:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS21]], i32 0, i32 0 // CK10-NEXT: [[TMP94:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CK10-NEXT: store i32 2, ptr [[TMP94]], align 4 +// CK10-NEXT: store i32 3, ptr [[TMP94]], align 4 // CK10-NEXT: [[TMP95:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CK10-NEXT: store i32 1, ptr [[TMP95]], align 4 // CK10-NEXT: [[TMP96:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -2046,7 +2046,7 @@ void bar() { // CK10-NEXT: [[TMP115:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CK10-NEXT: [[TMP116:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CK10-NEXT: [[TMP117:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CK10-NEXT: store i32 2, ptr [[TMP117]], align 4 +// CK10-NEXT: store i32 3, ptr [[TMP117]], align 4 // CK10-NEXT: [[TMP118:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CK10-NEXT: store i32 1, ptr [[TMP118]], align 4 // CK10-NEXT: [[TMP119:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -2101,7 +2101,7 @@ void bar() { // CK10-NEXT: [[TMP144:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS35]], i32 0, i32 0 // CK10-NEXT: [[TMP145:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS36]], i32 0, i32 0 // CK10-NEXT: [[TMP146:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 0 -// CK10-NEXT: store i32 2, ptr [[TMP146]], align 4 +// CK10-NEXT: store i32 3, ptr [[TMP146]], align 4 // CK10-NEXT: [[TMP147:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 1 // CK10-NEXT: store i32 2, ptr [[TMP147]], align 4 // CK10-NEXT: [[TMP148:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 2 @@ -2298,7 +2298,7 @@ void bar() { // CK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CK11-NEXT: store i32 2, ptr [[TMP6]], align 4 +// CK11-NEXT: store i32 3, ptr [[TMP6]], align 4 // CK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CK11-NEXT: store i32 1, ptr [[TMP7]], align 4 // CK11-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2340,7 +2340,7 @@ void bar() { // CK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 0 -// CK11-NEXT: store i32 2, ptr [[TMP27]], align 4 +// CK11-NEXT: store i32 3, ptr [[TMP27]], align 4 // CK11-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 1 // CK11-NEXT: store i32 1, ptr [[TMP28]], align 4 // CK11-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 2 @@ -2382,7 +2382,7 @@ void bar() { // CK11-NEXT: [[TMP46:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0 // CK11-NEXT: [[TMP47:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0 // CK11-NEXT: [[TMP48:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 0 -// CK11-NEXT: store i32 2, ptr [[TMP48]], align 4 +// CK11-NEXT: store i32 3, ptr [[TMP48]], align 4 // CK11-NEXT: [[TMP49:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 1 // CK11-NEXT: store i32 1, ptr [[TMP49]], align 4 // CK11-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 2 @@ -2427,7 +2427,7 @@ void bar() { // CK11-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS13]], i32 0, i32 0 // CK11-NEXT: [[TMP70:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS14]], i32 0, i32 0 // CK11-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 0 -// CK11-NEXT: store i32 2, ptr [[TMP71]], align 4 +// CK11-NEXT: store i32 3, ptr [[TMP71]], align 4 // CK11-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 1 // CK11-NEXT: store i32 1, ptr [[TMP72]], align 4 // CK11-NEXT: [[TMP73:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 2 @@ -2472,7 +2472,7 @@ void bar() { // CK11-NEXT: [[TMP92:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS20]], i32 0, i32 0 // CK11-NEXT: [[TMP93:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS21]], i32 0, i32 0 // CK11-NEXT: [[TMP94:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CK11-NEXT: store i32 2, ptr [[TMP94]], align 4 +// CK11-NEXT: store i32 3, ptr [[TMP94]], align 4 // CK11-NEXT: [[TMP95:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CK11-NEXT: store i32 1, ptr [[TMP95]], align 4 // CK11-NEXT: [[TMP96:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -2517,7 +2517,7 @@ void bar() { // CK11-NEXT: [[TMP115:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CK11-NEXT: [[TMP116:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CK11-NEXT: [[TMP117:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CK11-NEXT: store i32 2, ptr [[TMP117]], align 4 +// CK11-NEXT: store i32 3, ptr [[TMP117]], align 4 // CK11-NEXT: [[TMP118:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CK11-NEXT: store i32 1, ptr [[TMP118]], align 4 // CK11-NEXT: [[TMP119:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -2572,7 +2572,7 @@ void bar() { // CK11-NEXT: [[TMP144:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS35]], i32 0, i32 0 // CK11-NEXT: [[TMP145:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS36]], i32 0, i32 0 // CK11-NEXT: [[TMP146:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 0 -// CK11-NEXT: store i32 2, ptr [[TMP146]], align 4 +// CK11-NEXT: store i32 3, ptr [[TMP146]], align 4 // CK11-NEXT: [[TMP147:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 1 // CK11-NEXT: store i32 2, ptr [[TMP147]], align 4 // CK11-NEXT: [[TMP148:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 2 @@ -2769,7 +2769,7 @@ void bar() { // CK12-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CK12-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CK12-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CK12-NEXT: store i32 2, ptr [[TMP6]], align 4 +// CK12-NEXT: store i32 3, ptr [[TMP6]], align 4 // CK12-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CK12-NEXT: store i32 1, ptr [[TMP7]], align 4 // CK12-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2811,7 +2811,7 @@ void bar() { // CK12-NEXT: [[TMP25:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CK12-NEXT: [[TMP26:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CK12-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 0 -// CK12-NEXT: store i32 2, ptr [[TMP27]], align 4 +// CK12-NEXT: store i32 3, ptr [[TMP27]], align 4 // CK12-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 1 // CK12-NEXT: store i32 1, ptr [[TMP28]], align 4 // CK12-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 2 @@ -2853,7 +2853,7 @@ void bar() { // CK12-NEXT: [[TMP46:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0 // CK12-NEXT: [[TMP47:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0 // CK12-NEXT: [[TMP48:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 0 -// CK12-NEXT: store i32 2, ptr [[TMP48]], align 4 +// CK12-NEXT: store i32 3, ptr [[TMP48]], align 4 // CK12-NEXT: [[TMP49:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 1 // CK12-NEXT: store i32 1, ptr [[TMP49]], align 4 // CK12-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 2 @@ -2898,7 +2898,7 @@ void bar() { // CK12-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS13]], i32 0, i32 0 // CK12-NEXT: [[TMP70:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS14]], i32 0, i32 0 // CK12-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 0 -// CK12-NEXT: store i32 2, ptr [[TMP71]], align 4 +// CK12-NEXT: store i32 3, ptr [[TMP71]], align 4 // CK12-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 1 // CK12-NEXT: store i32 1, ptr [[TMP72]], align 4 // CK12-NEXT: [[TMP73:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 2 @@ -2943,7 +2943,7 @@ void bar() { // CK12-NEXT: [[TMP92:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS20]], i32 0, i32 0 // CK12-NEXT: [[TMP93:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS21]], i32 0, i32 0 // CK12-NEXT: [[TMP94:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CK12-NEXT: store i32 2, ptr [[TMP94]], align 4 +// CK12-NEXT: store i32 3, ptr [[TMP94]], align 4 // CK12-NEXT: [[TMP95:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CK12-NEXT: store i32 1, ptr [[TMP95]], align 4 // CK12-NEXT: [[TMP96:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -2988,7 +2988,7 @@ void bar() { // CK12-NEXT: [[TMP115:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CK12-NEXT: [[TMP116:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CK12-NEXT: [[TMP117:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CK12-NEXT: store i32 2, ptr [[TMP117]], align 4 +// CK12-NEXT: store i32 3, ptr [[TMP117]], align 4 // CK12-NEXT: [[TMP118:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CK12-NEXT: store i32 1, ptr [[TMP118]], align 4 // CK12-NEXT: [[TMP119:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -3043,7 +3043,7 @@ void bar() { // CK12-NEXT: [[TMP144:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS35]], i32 0, i32 0 // CK12-NEXT: [[TMP145:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS36]], i32 0, i32 0 // CK12-NEXT: [[TMP146:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 0 -// CK12-NEXT: store i32 2, ptr [[TMP146]], align 4 +// CK12-NEXT: store i32 3, ptr [[TMP146]], align 4 // CK12-NEXT: [[TMP147:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 1 // CK12-NEXT: store i32 2, ptr [[TMP147]], align 4 // CK12-NEXT: [[TMP148:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 2 @@ -3240,7 +3240,7 @@ void bar() { // CK13-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CK13-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CK13-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CK13-NEXT: store i32 2, ptr [[TMP6]], align 4 +// CK13-NEXT: store i32 3, ptr [[TMP6]], align 4 // CK13-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CK13-NEXT: store i32 1, ptr [[TMP7]], align 4 // CK13-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3282,7 +3282,7 @@ void bar() { // CK13-NEXT: [[TMP25:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CK13-NEXT: [[TMP26:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CK13-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 0 -// CK13-NEXT: store i32 2, ptr [[TMP27]], align 4 +// CK13-NEXT: store i32 3, ptr [[TMP27]], align 4 // CK13-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 1 // CK13-NEXT: store i32 1, ptr [[TMP28]], align 4 // CK13-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 2 @@ -3324,7 +3324,7 @@ void bar() { // CK13-NEXT: [[TMP46:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS7]], i32 0, i32 0 // CK13-NEXT: [[TMP47:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS8]], i32 0, i32 0 // CK13-NEXT: [[TMP48:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 0 -// CK13-NEXT: store i32 2, ptr [[TMP48]], align 4 +// CK13-NEXT: store i32 3, ptr [[TMP48]], align 4 // CK13-NEXT: [[TMP49:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 1 // CK13-NEXT: store i32 1, ptr [[TMP49]], align 4 // CK13-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS10]], i32 0, i32 2 @@ -3369,7 +3369,7 @@ void bar() { // CK13-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS13]], i32 0, i32 0 // CK13-NEXT: [[TMP70:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS14]], i32 0, i32 0 // CK13-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 0 -// CK13-NEXT: store i32 2, ptr [[TMP71]], align 4 +// CK13-NEXT: store i32 3, ptr [[TMP71]], align 4 // CK13-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 1 // CK13-NEXT: store i32 1, ptr [[TMP72]], align 4 // CK13-NEXT: [[TMP73:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 2 @@ -3414,7 +3414,7 @@ void bar() { // CK13-NEXT: [[TMP92:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS20]], i32 0, i32 0 // CK13-NEXT: [[TMP93:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS21]], i32 0, i32 0 // CK13-NEXT: [[TMP94:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CK13-NEXT: store i32 2, ptr [[TMP94]], align 4 +// CK13-NEXT: store i32 3, ptr [[TMP94]], align 4 // CK13-NEXT: [[TMP95:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CK13-NEXT: store i32 1, ptr [[TMP95]], align 4 // CK13-NEXT: [[TMP96:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -3459,7 +3459,7 @@ void bar() { // CK13-NEXT: [[TMP115:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CK13-NEXT: [[TMP116:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CK13-NEXT: [[TMP117:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CK13-NEXT: store i32 2, ptr [[TMP117]], align 4 +// CK13-NEXT: store i32 3, ptr [[TMP117]], align 4 // CK13-NEXT: [[TMP118:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CK13-NEXT: store i32 1, ptr [[TMP118]], align 4 // CK13-NEXT: [[TMP119:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -3514,7 +3514,7 @@ void bar() { // CK13-NEXT: [[TMP144:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS35]], i32 0, i32 0 // CK13-NEXT: [[TMP145:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS36]], i32 0, i32 0 // CK13-NEXT: [[TMP146:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 0 -// CK13-NEXT: store i32 2, ptr [[TMP146]], align 4 +// CK13-NEXT: store i32 3, ptr [[TMP146]], align 4 // CK13-NEXT: [[TMP147:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 1 // CK13-NEXT: store i32 2, ptr [[TMP147]], align 4 // CK13-NEXT: [[TMP148:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 2 @@ -4003,7 +4003,7 @@ void bar() { // CK20-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CK20-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CK20-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CK20-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CK20-NEXT: store i32 3, ptr [[TMP5]], align 4 // CK20-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CK20-NEXT: store i32 1, ptr [[TMP6]], align 4 // CK20-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4061,7 +4061,7 @@ void bar() { // CK20-NEXT: [[TMP34:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 // CK20-NEXT: [[TMP35:%.*]] = getelementptr inbounds [2 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CK20-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CK20-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CK20-NEXT: store i32 3, ptr [[TMP36]], align 4 // CK20-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CK20-NEXT: store i32 2, ptr [[TMP37]], align 4 // CK20-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -4126,7 +4126,7 @@ void bar() { // CK20-NEXT: [[TMP68:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS11]], i32 0, i32 0 // CK20-NEXT: [[TMP69:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES13]], i32 0, i32 0 // CK20-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CK20-NEXT: store i32 2, ptr [[TMP70]], align 4 +// CK20-NEXT: store i32 3, ptr [[TMP70]], align 4 // CK20-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CK20-NEXT: store i32 3, ptr [[TMP71]], align 4 // CK20-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 @@ -4283,7 +4283,7 @@ void bar() { // CK21-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CK21-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CK21-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CK21-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CK21-NEXT: store i32 3, ptr [[TMP5]], align 4 // CK21-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CK21-NEXT: store i32 1, ptr [[TMP6]], align 4 // CK21-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4341,7 +4341,7 @@ void bar() { // CK21-NEXT: [[TMP34:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 // CK21-NEXT: [[TMP35:%.*]] = getelementptr inbounds [2 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CK21-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CK21-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CK21-NEXT: store i32 3, ptr [[TMP36]], align 4 // CK21-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CK21-NEXT: store i32 2, ptr [[TMP37]], align 4 // CK21-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -4406,7 +4406,7 @@ void bar() { // CK21-NEXT: [[TMP68:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS11]], i32 0, i32 0 // CK21-NEXT: [[TMP69:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES13]], i32 0, i32 0 // CK21-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CK21-NEXT: store i32 2, ptr [[TMP70]], align 4 +// CK21-NEXT: store i32 3, ptr [[TMP70]], align 4 // CK21-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CK21-NEXT: store i32 3, ptr [[TMP71]], align 4 // CK21-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 @@ -4563,7 +4563,7 @@ void bar() { // CK22-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CK22-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CK22-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CK22-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CK22-NEXT: store i32 3, ptr [[TMP5]], align 4 // CK22-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CK22-NEXT: store i32 1, ptr [[TMP6]], align 4 // CK22-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4621,7 +4621,7 @@ void bar() { // CK22-NEXT: [[TMP34:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 // CK22-NEXT: [[TMP35:%.*]] = getelementptr inbounds [2 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CK22-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CK22-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CK22-NEXT: store i32 3, ptr [[TMP36]], align 4 // CK22-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CK22-NEXT: store i32 2, ptr [[TMP37]], align 4 // CK22-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -4686,7 +4686,7 @@ void bar() { // CK22-NEXT: [[TMP68:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS11]], i32 0, i32 0 // CK22-NEXT: [[TMP69:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES13]], i32 0, i32 0 // CK22-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CK22-NEXT: store i32 2, ptr [[TMP70]], align 4 +// CK22-NEXT: store i32 3, ptr [[TMP70]], align 4 // CK22-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CK22-NEXT: store i32 3, ptr [[TMP71]], align 4 // CK22-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 @@ -4843,7 +4843,7 @@ void bar() { // CK23-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CK23-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CK23-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CK23-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CK23-NEXT: store i32 3, ptr [[TMP5]], align 4 // CK23-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CK23-NEXT: store i32 1, ptr [[TMP6]], align 4 // CK23-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4901,7 +4901,7 @@ void bar() { // CK23-NEXT: [[TMP34:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 // CK23-NEXT: [[TMP35:%.*]] = getelementptr inbounds [2 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CK23-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CK23-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CK23-NEXT: store i32 3, ptr [[TMP36]], align 4 // CK23-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CK23-NEXT: store i32 2, ptr [[TMP37]], align 4 // CK23-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -4966,7 +4966,7 @@ void bar() { // CK23-NEXT: [[TMP68:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS11]], i32 0, i32 0 // CK23-NEXT: [[TMP69:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES13]], i32 0, i32 0 // CK23-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CK23-NEXT: store i32 2, ptr [[TMP70]], align 4 +// CK23-NEXT: store i32 3, ptr [[TMP70]], align 4 // CK23-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CK23-NEXT: store i32 3, ptr [[TMP71]], align 4 // CK23-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 @@ -5376,7 +5376,7 @@ void bar() { // CK30-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CK30-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CK30-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CK30-NEXT: store i32 2, ptr [[TMP6]], align 4 +// CK30-NEXT: store i32 3, ptr [[TMP6]], align 4 // CK30-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CK30-NEXT: store i32 1, ptr [[TMP7]], align 4 // CK30-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5439,7 +5439,7 @@ void bar() { // CK31-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CK31-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CK31-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CK31-NEXT: store i32 2, ptr [[TMP6]], align 4 +// CK31-NEXT: store i32 3, ptr [[TMP6]], align 4 // CK31-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CK31-NEXT: store i32 1, ptr [[TMP7]], align 4 // CK31-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5502,7 +5502,7 @@ void bar() { // CK32-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CK32-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CK32-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CK32-NEXT: store i32 2, ptr [[TMP6]], align 4 +// CK32-NEXT: store i32 3, ptr [[TMP6]], align 4 // CK32-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CK32-NEXT: store i32 1, ptr [[TMP7]], align 4 // CK32-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5565,7 +5565,7 @@ void bar() { // CK33-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CK33-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CK33-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CK33-NEXT: store i32 2, ptr [[TMP6]], align 4 +// CK33-NEXT: store i32 3, ptr [[TMP6]], align 4 // CK33-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CK33-NEXT: store i32 1, ptr [[TMP7]], align 4 // CK33-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_map_codegen_03.cpp b/clang/test/OpenMP/target_map_codegen_03.cpp index cd28e7bf848e0672c893ff8f9dea2a5a107589eb..959018647906f897da8ec18ece7e9b10dec22ac6 100644 --- a/clang/test/OpenMP/target_map_codegen_03.cpp +++ b/clang/test/OpenMP/target_map_codegen_03.cpp @@ -96,7 +96,7 @@ void implicit_maps_nested_integer (int a){ // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP8]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP9]], align 4 // CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -195,7 +195,7 @@ void implicit_maps_nested_integer (int a){ // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP8]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP9]], align 4 // CHECK3-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_map_codegen_hold.cpp b/clang/test/OpenMP/target_map_codegen_hold.cpp index 81306ccb4cf5543bd5bdff1d3f959be67e19fb12..c6ee673d9598e105b3a01685f5ac7fd623fd9bf9 100644 --- a/clang/test/OpenMP/target_map_codegen_hold.cpp +++ b/clang/test/OpenMP/target_map_codegen_hold.cpp @@ -245,7 +245,7 @@ void ST::test_present_members() { // CHECK-USE-PPC64LE-NEXT: [[TMP35:%.*]] = getelementptr inbounds [7 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-USE-PPC64LE-NEXT: [[TMP36:%.*]] = getelementptr inbounds [7 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK-USE-PPC64LE-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-USE-PPC64LE-NEXT: store i32 2, ptr [[TMP37]], align 4 +// CHECK-USE-PPC64LE-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK-USE-PPC64LE-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-USE-PPC64LE-NEXT: store i32 7, ptr [[TMP38]], align 4 // CHECK-USE-PPC64LE-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -286,7 +286,7 @@ void ST::test_present_members() { // CHECK-USE-PPC64LE-NEXT: [[TMP55:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK-USE-PPC64LE-NEXT: [[TMP56:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK-USE-PPC64LE-NEXT: [[TMP57:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK-USE-PPC64LE-NEXT: store i32 2, ptr [[TMP57]], align 4 +// CHECK-USE-PPC64LE-NEXT: store i32 3, ptr [[TMP57]], align 4 // CHECK-USE-PPC64LE-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK-USE-PPC64LE-NEXT: store i32 1, ptr [[TMP58]], align 4 // CHECK-USE-PPC64LE-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -410,7 +410,7 @@ void ST::test_present_members() { // CHECK-USE-PPC64LE-NEXT: [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-USE-PPC64LE-NEXT: [[TMP17:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK-USE-PPC64LE-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-USE-PPC64LE-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK-USE-PPC64LE-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK-USE-PPC64LE-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-USE-PPC64LE-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK-USE-PPC64LE-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -546,7 +546,7 @@ void ST::test_present_members() { // CHECK-USE-I386-NEXT: [[TMP35:%.*]] = getelementptr inbounds [7 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-USE-I386-NEXT: [[TMP36:%.*]] = getelementptr inbounds [7 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK-USE-I386-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-USE-I386-NEXT: store i32 2, ptr [[TMP37]], align 4 +// CHECK-USE-I386-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK-USE-I386-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-USE-I386-NEXT: store i32 7, ptr [[TMP38]], align 4 // CHECK-USE-I386-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -587,7 +587,7 @@ void ST::test_present_members() { // CHECK-USE-I386-NEXT: [[TMP55:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK-USE-I386-NEXT: [[TMP56:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK-USE-I386-NEXT: [[TMP57:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK-USE-I386-NEXT: store i32 2, ptr [[TMP57]], align 4 +// CHECK-USE-I386-NEXT: store i32 3, ptr [[TMP57]], align 4 // CHECK-USE-I386-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK-USE-I386-NEXT: store i32 1, ptr [[TMP58]], align 4 // CHECK-USE-I386-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -711,7 +711,7 @@ void ST::test_present_members() { // CHECK-USE-I386-NEXT: [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-USE-I386-NEXT: [[TMP17:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK-USE-I386-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-USE-I386-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK-USE-I386-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK-USE-I386-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-USE-I386-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK-USE-I386-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -847,7 +847,7 @@ void ST::test_present_members() { // CHECK-NOUSE-PPC64LE-NEXT: [[TMP35:%.*]] = getelementptr inbounds [7 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-NOUSE-PPC64LE-NEXT: [[TMP36:%.*]] = getelementptr inbounds [7 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK-NOUSE-PPC64LE-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-NOUSE-PPC64LE-NEXT: store i32 2, ptr [[TMP37]], align 4 +// CHECK-NOUSE-PPC64LE-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK-NOUSE-PPC64LE-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-NOUSE-PPC64LE-NEXT: store i32 7, ptr [[TMP38]], align 4 // CHECK-NOUSE-PPC64LE-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -888,7 +888,7 @@ void ST::test_present_members() { // CHECK-NOUSE-PPC64LE-NEXT: [[TMP55:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK-NOUSE-PPC64LE-NEXT: [[TMP56:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK-NOUSE-PPC64LE-NEXT: [[TMP57:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK-NOUSE-PPC64LE-NEXT: store i32 2, ptr [[TMP57]], align 4 +// CHECK-NOUSE-PPC64LE-NEXT: store i32 3, ptr [[TMP57]], align 4 // CHECK-NOUSE-PPC64LE-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK-NOUSE-PPC64LE-NEXT: store i32 1, ptr [[TMP58]], align 4 // CHECK-NOUSE-PPC64LE-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -978,7 +978,7 @@ void ST::test_present_members() { // CHECK-NOUSE-PPC64LE-NEXT: [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-NOUSE-PPC64LE-NEXT: [[TMP17:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK-NOUSE-PPC64LE-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-NOUSE-PPC64LE-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK-NOUSE-PPC64LE-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK-NOUSE-PPC64LE-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-NOUSE-PPC64LE-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK-NOUSE-PPC64LE-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1103,7 +1103,7 @@ void ST::test_present_members() { // CHECK-NOUSE-I386-NEXT: [[TMP35:%.*]] = getelementptr inbounds [7 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-NOUSE-I386-NEXT: [[TMP36:%.*]] = getelementptr inbounds [7 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK-NOUSE-I386-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-NOUSE-I386-NEXT: store i32 2, ptr [[TMP37]], align 4 +// CHECK-NOUSE-I386-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK-NOUSE-I386-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-NOUSE-I386-NEXT: store i32 7, ptr [[TMP38]], align 4 // CHECK-NOUSE-I386-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1144,7 +1144,7 @@ void ST::test_present_members() { // CHECK-NOUSE-I386-NEXT: [[TMP55:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK-NOUSE-I386-NEXT: [[TMP56:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK-NOUSE-I386-NEXT: [[TMP57:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK-NOUSE-I386-NEXT: store i32 2, ptr [[TMP57]], align 4 +// CHECK-NOUSE-I386-NEXT: store i32 3, ptr [[TMP57]], align 4 // CHECK-NOUSE-I386-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK-NOUSE-I386-NEXT: store i32 1, ptr [[TMP58]], align 4 // CHECK-NOUSE-I386-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -1234,7 +1234,7 @@ void ST::test_present_members() { // CHECK-NOUSE-I386-NEXT: [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-NOUSE-I386-NEXT: [[TMP17:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK-NOUSE-I386-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-NOUSE-I386-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK-NOUSE-I386-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK-NOUSE-I386-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-NOUSE-I386-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK-NOUSE-I386-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_map_deref_array_codegen.cpp b/clang/test/OpenMP/target_map_deref_array_codegen.cpp index da4176f20109c1fdb5413f76aaa8d44c4b4eba3f..b854333002299af4419ab7f434c42c4ae8985964 100644 --- a/clang/test/OpenMP/target_map_deref_array_codegen.cpp +++ b/clang/test/OpenMP/target_map_deref_array_codegen.cpp @@ -91,7 +91,7 @@ void foo(int **t1d) // CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP19]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-NEXT: store i32 2, ptr [[TMP20]], align 4 // CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -143,7 +143,7 @@ void foo(int **t1d) // CHECK-NEXT: [[TMP45:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0 // CHECK-NEXT: [[TMP46:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 // CHECK-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP47]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP47]], align 4 // CHECK-NEXT: [[TMP48:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK-NEXT: store i32 2, ptr [[TMP48]], align 4 // CHECK-NEXT: [[TMP49:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -224,7 +224,7 @@ void foo(int **t1d) // CHECK-NEXT: [[TMP86:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS12]], i32 0, i32 0 // CHECK-NEXT: [[TMP87:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS13]], i32 0, i32 0 // CHECK-NEXT: [[TMP88:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP88]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP88]], align 4 // CHECK-NEXT: [[TMP89:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK-NEXT: store i32 4, ptr [[TMP89]], align 4 // CHECK-NEXT: [[TMP90:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_map_member_expr_codegen.cpp b/clang/test/OpenMP/target_map_member_expr_codegen.cpp index 84844cff09b934cab011b70d2ec7f397f3939fc8..9979f381a706768df09ec77df8138ac8ab36fe7d 100644 --- a/clang/test/OpenMP/target_map_member_expr_codegen.cpp +++ b/clang/test/OpenMP/target_map_member_expr_codegen.cpp @@ -138,7 +138,7 @@ void foo() { // CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP14]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP14]], align 4 // CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-NEXT: store i32 4, ptr [[TMP15]], align 4 // CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -295,7 +295,7 @@ void foo() { // CHECK-NEXT: [[TMP53:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS9]], i32 0, i32 0 // CHECK-NEXT: [[TMP54:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS10]], i32 0, i32 0 // CHECK-NEXT: [[TMP55:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP55]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP55]], align 4 // CHECK-NEXT: [[TMP56:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-NEXT: store i32 2, ptr [[TMP56]], align 4 // CHECK-NEXT: [[TMP57:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -379,7 +379,7 @@ void foo() { // CHECK-NEXT: [[TMP100:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS19]], i32 0, i32 0 // CHECK-NEXT: [[TMP101:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES21]], i32 0, i32 0 // CHECK-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP102]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP102]], align 4 // CHECK-NEXT: [[TMP103:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 1 // CHECK-NEXT: store i32 3, ptr [[TMP103]], align 4 // CHECK-NEXT: [[TMP104:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS22]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_offload_mandatory_codegen.cpp b/clang/test/OpenMP/target_offload_mandatory_codegen.cpp index 04360f1ea03bd9e7aeb49d273518d4f12daddf5d..3bf15277aa1c393c5d0bdfc914f7f661234d5a17 100644 --- a/clang/test/OpenMP/target_offload_mandatory_codegen.cpp +++ b/clang/test/OpenMP/target_offload_mandatory_codegen.cpp @@ -33,7 +33,7 @@ void host_dev(int device) { // MANDATORY-NEXT: entry: // MANDATORY-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // MANDATORY-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// MANDATORY-NEXT: store i32 2, ptr [[TMP0]], align 4 +// MANDATORY-NEXT: store i32 3, ptr [[TMP0]], align 4 // MANDATORY-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // MANDATORY-NEXT: store i32 0, ptr [[TMP1]], align 4 // MANDATORY-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -79,7 +79,7 @@ void host_dev(int device) { // MANDATORY-NEXT: br i1 [[TOBOOL]], label [[OMP_IF_THEN:%.*]], label [[OMP_IF_ELSE:%.*]] // MANDATORY: omp_if.then: // MANDATORY-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// MANDATORY-NEXT: store i32 2, ptr [[TMP1]], align 4 +// MANDATORY-NEXT: store i32 3, ptr [[TMP1]], align 4 // MANDATORY-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // MANDATORY-NEXT: store i32 0, ptr [[TMP2]], align 4 // MANDATORY-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -129,7 +129,7 @@ void host_dev(int device) { // MANDATORY-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 // MANDATORY-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i64 // MANDATORY-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// MANDATORY-NEXT: store i32 2, ptr [[TMP3]], align 4 +// MANDATORY-NEXT: store i32 3, ptr [[TMP3]], align 4 // MANDATORY-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // MANDATORY-NEXT: store i32 0, ptr [[TMP4]], align 4 // MANDATORY-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_ompx_dyn_cgroup_mem_codegen.cpp b/clang/test/OpenMP/target_ompx_dyn_cgroup_mem_codegen.cpp index e8b074a9d5f8be980b00ba24d776e1e3bbd4bbd6..10c4ac38e6a89b2a04760ff3b69775f7c2a7e0e5 100644 --- a/clang/test/OpenMP/target_ompx_dyn_cgroup_mem_codegen.cpp +++ b/clang/test/OpenMP/target_ompx_dyn_cgroup_mem_codegen.cpp @@ -256,7 +256,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -298,7 +298,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP36:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP37:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP38]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP38]], align 4 // CHECK1-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP39]], align 4 // CHECK1-NEXT: [[TMP40:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -408,7 +408,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP25:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP20]], 0 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP27]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP27]], align 4 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -493,7 +493,7 @@ int bar(int n){ // CHECK1-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4 // CHECK1-NEXT: store i32 0, ptr [[A]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -561,7 +561,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP34:%.*]] = sext i16 [[TMP33]] to i32 // CHECK1-NEXT: [[TMP35:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP34]], 0 // CHECK1-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK1-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK1-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 2 @@ -958,7 +958,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR1_I]], align 8, !noalias [[META27]] // CHECK1-NEXT: [[TMP14:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR2_I]], align 8, !noalias [[META27]] // CHECK1-NEXT: [[TMP15:%.*]] = load i32, ptr [[TMP9]], align 4 -// CHECK1-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META27]] +// CHECK1-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META27]] // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP16]], align 4, !noalias [[META27]] // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -1138,7 +1138,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1180,7 +1180,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP36:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP37:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK3-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP38]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP38]], align 4 // CHECK3-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP39]], align 4 // CHECK3-NEXT: [[TMP40:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -1290,7 +1290,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP25:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 // CHECK3-NEXT: [[TMP26:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP20]], 0 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP27]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP27]], align 4 // CHECK3-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1375,7 +1375,7 @@ int bar(int n){ // CHECK3-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4 // CHECK3-NEXT: store i32 0, ptr [[A]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1443,7 +1443,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP34:%.*]] = sext i16 [[TMP33]] to i32 // CHECK3-NEXT: [[TMP35:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP34]], 0 // CHECK3-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK3-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK3-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 2 @@ -1836,7 +1836,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP13:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR1_I]], align 4, !noalias [[META28]] // CHECK3-NEXT: [[TMP14:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR2_I]], align 4, !noalias [[META28]] // CHECK3-NEXT: [[TMP15:%.*]] = load i32, ptr [[TMP9]], align 4 -// CHECK3-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META28]] +// CHECK3-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META28]] // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP16]], align 4, !noalias [[META28]] // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_parallel_codegen.cpp b/clang/test/OpenMP/target_parallel_codegen.cpp index 84b7f1ae4ec045b87d1c2cdc4b8b0a45449e0963..ad5a9d53bcf652e0a7268a7e0697b56508529793 100644 --- a/clang/test/OpenMP/target_parallel_codegen.cpp +++ b/clang/test/OpenMP/target_parallel_codegen.cpp @@ -356,7 +356,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP19]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP20]], align 4 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -413,7 +413,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP45:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP46:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS5]], i32 0, i32 0 // CHECK1-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP47]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP47]], align 4 // CHECK1-NEXT: [[TMP48:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP48]], align 4 // CHECK1-NEXT: [[TMP49:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -523,7 +523,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP98:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS14]], i32 0, i32 0 // CHECK1-NEXT: [[TMP99:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK1-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP100]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP100]], align 4 // CHECK1-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 1 // CHECK1-NEXT: store i32 9, ptr [[TMP101]], align 4 // CHECK1-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 2 @@ -614,7 +614,7 @@ int bar(int n){ // CHECK1-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias [[META21]] // CHECK1-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META21]] // CHECK1-NEXT: [[TMP8:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META21]] -// CHECK1-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META21]] +// CHECK1-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META21]] // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP9]], align 4, !noalias [[META21]] // CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -972,7 +972,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK1-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP30]], align 4 // CHECK1-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1080,7 +1080,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP22]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1168,7 +1168,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1450,7 +1450,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP15:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP17]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP18]], align 4 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1507,7 +1507,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP43:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS4]], i32 0, i32 0 // CHECK3-NEXT: [[TMP44:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS5]], i32 0, i32 0 // CHECK3-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK3-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP46]], align 4 // CHECK3-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -1619,7 +1619,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP98:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS14]], i32 0, i32 0 // CHECK3-NEXT: [[TMP99:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK3-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP100]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP100]], align 4 // CHECK3-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 1 // CHECK3-NEXT: store i32 9, ptr [[TMP101]], align 4 // CHECK3-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 2 @@ -1710,7 +1710,7 @@ int bar(int n){ // CHECK3-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 4, !noalias [[META22]] // CHECK3-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META22]] // CHECK3-NEXT: [[TMP8:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META22]] -// CHECK3-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META22]] +// CHECK3-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META22]] // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP9]], align 4, !noalias [[META22]] // CHECK3-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -2068,7 +2068,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP28:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK3-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP30]], align 4 // CHECK3-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2176,7 +2176,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP22]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2264,7 +2264,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_parallel_for_codegen.cpp b/clang/test/OpenMP/target_parallel_for_codegen.cpp index 31f6d0b8ad9ae18afc0daf6aaf752fa5ea0ea9ac..73504cf7a8024ea5768ea929021761c66f0167ac 100644 --- a/clang/test/OpenMP/target_parallel_for_codegen.cpp +++ b/clang/test/OpenMP/target_parallel_for_codegen.cpp @@ -366,7 +366,7 @@ int bar(int n){ // CHECK1-NEXT: [[VLA1:%.*]] = alloca double, i64 [[TMP6]], align 8 // CHECK1-NEXT: store i64 [[TMP5]], ptr [[__VLA_EXPR1]], align 8 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -487,7 +487,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP71:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0 // CHECK1-NEXT: [[TMP72:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0 // CHECK1-NEXT: [[TMP73:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP73]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP73]], align 4 // CHECK1-NEXT: [[TMP74:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP74]], align 4 // CHECK1-NEXT: [[TMP75:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 2 @@ -608,7 +608,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP130:%.*]] = getelementptr inbounds [10 x ptr], ptr [[DOTOFFLOAD_PTRS15]], i32 0, i32 0 // CHECK1-NEXT: [[TMP131:%.*]] = getelementptr inbounds [10 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK1-NEXT: [[TMP132:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP132]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP132]], align 4 // CHECK1-NEXT: [[TMP133:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 1 // CHECK1-NEXT: store i32 10, ptr [[TMP133]], align 4 // CHECK1-NEXT: [[TMP134:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 2 @@ -1047,7 +1047,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR3_I]], align 8, !noalias [[META24]] // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], ptr [[TMP9]], i32 0, i32 1 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2 -// CHECK1-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META24]] +// CHECK1-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META24]] // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP18]], align 4, !noalias [[META24]] // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -1475,7 +1475,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK1-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP30]], align 4 // CHECK1-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1583,7 +1583,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP22]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1671,7 +1671,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2032,7 +2032,7 @@ int bar(int n){ // CHECK3-NEXT: [[VLA1:%.*]] = alloca double, i32 [[TMP4]], align 8 // CHECK3-NEXT: store i32 [[TMP3]], ptr [[__VLA_EXPR1]], align 4 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2150,7 +2150,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP67:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0 // CHECK3-NEXT: [[TMP68:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0 // CHECK3-NEXT: [[TMP69:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP69]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP69]], align 4 // CHECK3-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP70]], align 4 // CHECK3-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 2 @@ -2273,7 +2273,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP128:%.*]] = getelementptr inbounds [10 x ptr], ptr [[DOTOFFLOAD_PTRS15]], i32 0, i32 0 // CHECK3-NEXT: [[TMP129:%.*]] = getelementptr inbounds [10 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK3-NEXT: [[TMP130:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP130]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP130]], align 4 // CHECK3-NEXT: [[TMP131:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 1 // CHECK3-NEXT: store i32 10, ptr [[TMP131]], align 4 // CHECK3-NEXT: [[TMP132:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 2 @@ -2710,7 +2710,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR3_I]], align 4, !noalias [[META25]] // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], ptr [[TMP9]], i32 0, i32 1 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2 -// CHECK3-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META25]] +// CHECK3-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META25]] // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP18]], align 4, !noalias [[META25]] // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -3138,7 +3138,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP28:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK3-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP30]], align 4 // CHECK3-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3246,7 +3246,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP22]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3334,7 +3334,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5256,7 +5256,7 @@ int bar(int n){ // CHECK17-NEXT: [[VLA1:%.*]] = alloca double, i64 [[TMP6]], align 8 // CHECK17-NEXT: store i64 [[TMP5]], ptr [[__VLA_EXPR1]], align 8 // CHECK17-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK17-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 0, ptr [[TMP8]], align 4 // CHECK17-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5377,7 +5377,7 @@ int bar(int n){ // CHECK17-NEXT: [[TMP71:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0 // CHECK17-NEXT: [[TMP72:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0 // CHECK17-NEXT: [[TMP73:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP73]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP73]], align 4 // CHECK17-NEXT: [[TMP74:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 1 // CHECK17-NEXT: store i32 2, ptr [[TMP74]], align 4 // CHECK17-NEXT: [[TMP75:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 2 @@ -5498,7 +5498,7 @@ int bar(int n){ // CHECK17-NEXT: [[TMP130:%.*]] = getelementptr inbounds [10 x ptr], ptr [[DOTOFFLOAD_PTRS15]], i32 0, i32 0 // CHECK17-NEXT: [[TMP131:%.*]] = getelementptr inbounds [10 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK17-NEXT: [[TMP132:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP132]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP132]], align 4 // CHECK17-NEXT: [[TMP133:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 1 // CHECK17-NEXT: store i32 10, ptr [[TMP133]], align 4 // CHECK17-NEXT: [[TMP134:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 2 @@ -5937,7 +5937,7 @@ int bar(int n){ // CHECK17-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR3_I]], align 8, !noalias [[META24]] // CHECK17-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], ptr [[TMP9]], i32 0, i32 1 // CHECK17-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2 -// CHECK17-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META24]] +// CHECK17-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META24]] // CHECK17-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK17-NEXT: store i32 3, ptr [[TMP18]], align 4, !noalias [[META24]] // CHECK17-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -6365,7 +6365,7 @@ int bar(int n){ // CHECK17-NEXT: [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP28:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK17-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK17-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 5, ptr [[TMP30]], align 4 // CHECK17-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -6473,7 +6473,7 @@ int bar(int n){ // CHECK17-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK17-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 4, ptr [[TMP22]], align 4 // CHECK17-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -6561,7 +6561,7 @@ int bar(int n){ // CHECK17-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK17-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK17-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -6922,7 +6922,7 @@ int bar(int n){ // CHECK19-NEXT: [[VLA1:%.*]] = alloca double, i32 [[TMP4]], align 8 // CHECK19-NEXT: store i32 [[TMP3]], ptr [[__VLA_EXPR1]], align 4 // CHECK19-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK19-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 0, ptr [[TMP6]], align 4 // CHECK19-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -7040,7 +7040,7 @@ int bar(int n){ // CHECK19-NEXT: [[TMP67:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0 // CHECK19-NEXT: [[TMP68:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0 // CHECK19-NEXT: [[TMP69:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP69]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP69]], align 4 // CHECK19-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 1 // CHECK19-NEXT: store i32 2, ptr [[TMP70]], align 4 // CHECK19-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 2 @@ -7163,7 +7163,7 @@ int bar(int n){ // CHECK19-NEXT: [[TMP128:%.*]] = getelementptr inbounds [10 x ptr], ptr [[DOTOFFLOAD_PTRS15]], i32 0, i32 0 // CHECK19-NEXT: [[TMP129:%.*]] = getelementptr inbounds [10 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK19-NEXT: [[TMP130:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP130]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP130]], align 4 // CHECK19-NEXT: [[TMP131:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 1 // CHECK19-NEXT: store i32 10, ptr [[TMP131]], align 4 // CHECK19-NEXT: [[TMP132:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 2 @@ -7600,7 +7600,7 @@ int bar(int n){ // CHECK19-NEXT: [[TMP15:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR3_I]], align 4, !noalias [[META25]] // CHECK19-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], ptr [[TMP9]], i32 0, i32 1 // CHECK19-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2 -// CHECK19-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META25]] +// CHECK19-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META25]] // CHECK19-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK19-NEXT: store i32 3, ptr [[TMP18]], align 4, !noalias [[META25]] // CHECK19-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -8028,7 +8028,7 @@ int bar(int n){ // CHECK19-NEXT: [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP28:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK19-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK19-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 5, ptr [[TMP30]], align 4 // CHECK19-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -8136,7 +8136,7 @@ int bar(int n){ // CHECK19-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK19-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 4, ptr [[TMP22]], align 4 // CHECK19-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -8224,7 +8224,7 @@ int bar(int n){ // CHECK19-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK19-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK19-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_parallel_for_simd_codegen.cpp b/clang/test/OpenMP/target_parallel_for_simd_codegen.cpp index 7751ae93d59fa447ac990681e13bae15911049af..8009e06666c821f79ebd0a35e482aa1aba8e7480 100644 --- a/clang/test/OpenMP/target_parallel_for_simd_codegen.cpp +++ b/clang/test/OpenMP/target_parallel_for_simd_codegen.cpp @@ -395,7 +395,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP30:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP31]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP31]], align 4 // CHECK1-NEXT: [[TMP32:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP32]], align 4 // CHECK1-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -452,7 +452,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP57:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0 // CHECK1-NEXT: [[TMP58:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0 // CHECK1-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP59]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK1-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP60]], align 4 // CHECK1-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 2 @@ -573,7 +573,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP116:%.*]] = getelementptr inbounds [10 x ptr], ptr [[DOTOFFLOAD_PTRS15]], i32 0, i32 0 // CHECK1-NEXT: [[TMP117:%.*]] = getelementptr inbounds [10 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK1-NEXT: [[TMP118:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP118]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP118]], align 4 // CHECK1-NEXT: [[TMP119:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 1 // CHECK1-NEXT: store i32 10, ptr [[TMP119]], align 4 // CHECK1-NEXT: [[TMP120:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 2 @@ -721,7 +721,7 @@ int bar(int n){ // CHECK1-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias [[META25]] // CHECK1-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META25]] // CHECK1-NEXT: [[TMP8:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META25]] -// CHECK1-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META25]] +// CHECK1-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META25]] // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP9]], align 4, !noalias [[META25]] // CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -1403,7 +1403,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK1-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP30]], align 4 // CHECK1-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1511,7 +1511,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP22]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1599,7 +1599,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2013,7 +2013,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP25:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP27]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP27]], align 4 // CHECK3-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2070,7 +2070,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP53:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0 // CHECK3-NEXT: [[TMP54:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0 // CHECK3-NEXT: [[TMP55:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP55]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP55]], align 4 // CHECK3-NEXT: [[TMP56:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP56]], align 4 // CHECK3-NEXT: [[TMP57:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 2 @@ -2193,7 +2193,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP114:%.*]] = getelementptr inbounds [10 x ptr], ptr [[DOTOFFLOAD_PTRS15]], i32 0, i32 0 // CHECK3-NEXT: [[TMP115:%.*]] = getelementptr inbounds [10 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK3-NEXT: [[TMP116:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP116]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP116]], align 4 // CHECK3-NEXT: [[TMP117:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 1 // CHECK3-NEXT: store i32 10, ptr [[TMP117]], align 4 // CHECK3-NEXT: [[TMP118:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 2 @@ -2341,7 +2341,7 @@ int bar(int n){ // CHECK3-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 4, !noalias [[META26]] // CHECK3-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META26]] // CHECK3-NEXT: [[TMP8:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META26]] -// CHECK3-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META26]] +// CHECK3-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META26]] // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP9]], align 4, !noalias [[META26]] // CHECK3-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -3021,7 +3021,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP28:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK3-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP30]], align 4 // CHECK3-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3129,7 +3129,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP22]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3217,7 +3217,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3637,7 +3637,7 @@ int bar(int n){ // CHECK5-NEXT: [[TMP29:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP30:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP31]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP31]], align 4 // CHECK5-NEXT: [[TMP32:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 3, ptr [[TMP32]], align 4 // CHECK5-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3694,7 +3694,7 @@ int bar(int n){ // CHECK5-NEXT: [[TMP57:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0 // CHECK5-NEXT: [[TMP58:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0 // CHECK5-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP59]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK5-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 1 // CHECK5-NEXT: store i32 2, ptr [[TMP60]], align 4 // CHECK5-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 2 @@ -3815,7 +3815,7 @@ int bar(int n){ // CHECK5-NEXT: [[TMP116:%.*]] = getelementptr inbounds [10 x ptr], ptr [[DOTOFFLOAD_PTRS15]], i32 0, i32 0 // CHECK5-NEXT: [[TMP117:%.*]] = getelementptr inbounds [10 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK5-NEXT: [[TMP118:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP118]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP118]], align 4 // CHECK5-NEXT: [[TMP119:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 1 // CHECK5-NEXT: store i32 10, ptr [[TMP119]], align 4 // CHECK5-NEXT: [[TMP120:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 2 @@ -3963,7 +3963,7 @@ int bar(int n){ // CHECK5-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias [[META25]] // CHECK5-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META25]] // CHECK5-NEXT: [[TMP8:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META25]] -// CHECK5-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META25]] +// CHECK5-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META25]] // CHECK5-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP9]], align 4, !noalias [[META25]] // CHECK5-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -4666,7 +4666,7 @@ int bar(int n){ // CHECK5-NEXT: [[TMP36:%.*]] = select i1 [[TOBOOL4]], i32 0, i32 1 // CHECK5-NEXT: [[TMP37:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP36]], 0 // CHECK5-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP38]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP38]], align 4 // CHECK5-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 6, ptr [[TMP39]], align 4 // CHECK5-NEXT: [[TMP40:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4774,7 +4774,7 @@ int bar(int n){ // CHECK5-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK5-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 4, ptr [[TMP22]], align 4 // CHECK5-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4862,7 +4862,7 @@ int bar(int n){ // CHECK5-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK5-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK5-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5362,7 +5362,7 @@ int bar(int n){ // CHECK7-NEXT: [[TMP25:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP26:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP27]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP27]], align 4 // CHECK7-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK7-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5419,7 +5419,7 @@ int bar(int n){ // CHECK7-NEXT: [[TMP53:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0 // CHECK7-NEXT: [[TMP54:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0 // CHECK7-NEXT: [[TMP55:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP55]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP55]], align 4 // CHECK7-NEXT: [[TMP56:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 1 // CHECK7-NEXT: store i32 2, ptr [[TMP56]], align 4 // CHECK7-NEXT: [[TMP57:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 2 @@ -5542,7 +5542,7 @@ int bar(int n){ // CHECK7-NEXT: [[TMP114:%.*]] = getelementptr inbounds [10 x ptr], ptr [[DOTOFFLOAD_PTRS15]], i32 0, i32 0 // CHECK7-NEXT: [[TMP115:%.*]] = getelementptr inbounds [10 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK7-NEXT: [[TMP116:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP116]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP116]], align 4 // CHECK7-NEXT: [[TMP117:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 1 // CHECK7-NEXT: store i32 10, ptr [[TMP117]], align 4 // CHECK7-NEXT: [[TMP118:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS17]], i32 0, i32 2 @@ -5690,7 +5690,7 @@ int bar(int n){ // CHECK7-NEXT: store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 4, !noalias [[META26]] // CHECK7-NEXT: store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META26]] // CHECK7-NEXT: [[TMP8:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 4, !noalias [[META26]] -// CHECK7-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META26]] +// CHECK7-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META26]] // CHECK7-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK7-NEXT: store i32 0, ptr [[TMP9]], align 4, !noalias [[META26]] // CHECK7-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -6391,7 +6391,7 @@ int bar(int n){ // CHECK7-NEXT: [[TMP36:%.*]] = select i1 [[TOBOOL4]], i32 0, i32 1 // CHECK7-NEXT: [[TMP37:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP36]], 0 // CHECK7-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP38]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP38]], align 4 // CHECK7-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 6, ptr [[TMP39]], align 4 // CHECK7-NEXT: [[TMP40:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -6499,7 +6499,7 @@ int bar(int n){ // CHECK7-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK7-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 4, ptr [[TMP22]], align 4 // CHECK7-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -6587,7 +6587,7 @@ int bar(int n){ // CHECK7-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK7-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK7-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_parallel_generic_loop_codegen-1.cpp b/clang/test/OpenMP/target_parallel_generic_loop_codegen-1.cpp index fa3d182b62ad2da80ade36df2033407d22c2a105..bbefab195b9ae74593cddee04cf8cdf34431457f 100644 --- a/clang/test/OpenMP/target_parallel_generic_loop_codegen-1.cpp +++ b/clang/test/OpenMP/target_parallel_generic_loop_codegen-1.cpp @@ -4185,7 +4185,7 @@ int bar(int a){ // OMP-DEfAULT-NEXT: [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// OMP-DEfAULT-NEXT: store i32 2, ptr [[TMP9]], align 4 +// OMP-DEfAULT-NEXT: store i32 3, ptr [[TMP9]], align 4 // OMP-DEfAULT-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // OMP-DEfAULT-NEXT: store i32 1, ptr [[TMP10]], align 4 // OMP-DEfAULT-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4394,7 +4394,7 @@ int bar(int a){ // OMP-DEfAULT-NEXT: [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// OMP-DEfAULT-NEXT: store i32 2, ptr [[TMP9]], align 4 +// OMP-DEfAULT-NEXT: store i32 3, ptr [[TMP9]], align 4 // OMP-DEfAULT-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // OMP-DEfAULT-NEXT: store i32 1, ptr [[TMP10]], align 4 // OMP-DEfAULT-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4565,7 +4565,7 @@ int bar(int a){ // OMP-DEfAULT-NEXT: [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// OMP-DEfAULT-NEXT: store i32 2, ptr [[TMP9]], align 4 +// OMP-DEfAULT-NEXT: store i32 3, ptr [[TMP9]], align 4 // OMP-DEfAULT-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // OMP-DEfAULT-NEXT: store i32 1, ptr [[TMP10]], align 4 // OMP-DEfAULT-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4708,7 +4708,7 @@ int bar(int a){ // OMP-DEfAULT-NEXT: [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// OMP-DEfAULT-NEXT: store i32 2, ptr [[TMP9]], align 4 +// OMP-DEfAULT-NEXT: store i32 3, ptr [[TMP9]], align 4 // OMP-DEfAULT-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // OMP-DEfAULT-NEXT: store i32 1, ptr [[TMP10]], align 4 // OMP-DEfAULT-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4879,7 +4879,7 @@ int bar(int a){ // OMP-DEfAULT-NEXT: [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// OMP-DEfAULT-NEXT: store i32 2, ptr [[TMP9]], align 4 +// OMP-DEfAULT-NEXT: store i32 3, ptr [[TMP9]], align 4 // OMP-DEfAULT-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // OMP-DEfAULT-NEXT: store i32 1, ptr [[TMP10]], align 4 // OMP-DEfAULT-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5022,7 +5022,7 @@ int bar(int a){ // OMP-DEfAULT-NEXT: [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// OMP-DEfAULT-NEXT: store i32 2, ptr [[TMP9]], align 4 +// OMP-DEfAULT-NEXT: store i32 3, ptr [[TMP9]], align 4 // OMP-DEfAULT-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // OMP-DEfAULT-NEXT: store i32 1, ptr [[TMP10]], align 4 // OMP-DEfAULT-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5193,7 +5193,7 @@ int bar(int a){ // OMP-DEfAULT-NEXT: [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// OMP-DEfAULT-NEXT: store i32 2, ptr [[TMP9]], align 4 +// OMP-DEfAULT-NEXT: store i32 3, ptr [[TMP9]], align 4 // OMP-DEfAULT-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // OMP-DEfAULT-NEXT: store i32 1, ptr [[TMP10]], align 4 // OMP-DEfAULT-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5336,7 +5336,7 @@ int bar(int a){ // OMP-DEfAULT-NEXT: [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// OMP-DEfAULT-NEXT: store i32 2, ptr [[TMP9]], align 4 +// OMP-DEfAULT-NEXT: store i32 3, ptr [[TMP9]], align 4 // OMP-DEfAULT-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // OMP-DEfAULT-NEXT: store i32 1, ptr [[TMP10]], align 4 // OMP-DEfAULT-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5486,7 +5486,7 @@ int bar(int a){ // OMP-DEfAULT-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// OMP-DEfAULT-NEXT: store i32 2, ptr [[TMP8]], align 4 +// OMP-DEfAULT-NEXT: store i32 3, ptr [[TMP8]], align 4 // OMP-DEfAULT-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // OMP-DEfAULT-NEXT: store i32 1, ptr [[TMP9]], align 4 // OMP-DEfAULT-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5571,7 +5571,7 @@ int bar(int a){ // OMP-DEfAULT-NEXT: [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// OMP-DEfAULT-NEXT: store i32 2, ptr [[TMP9]], align 4 +// OMP-DEfAULT-NEXT: store i32 3, ptr [[TMP9]], align 4 // OMP-DEfAULT-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // OMP-DEfAULT-NEXT: store i32 1, ptr [[TMP10]], align 4 // OMP-DEfAULT-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5695,7 +5695,7 @@ int bar(int a){ // OMP-DEfAULT-NEXT: [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// OMP-DEfAULT-NEXT: store i32 2, ptr [[TMP9]], align 4 +// OMP-DEfAULT-NEXT: store i32 3, ptr [[TMP9]], align 4 // OMP-DEfAULT-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // OMP-DEfAULT-NEXT: store i32 1, ptr [[TMP10]], align 4 // OMP-DEfAULT-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5760,7 +5760,7 @@ int bar(int a){ // OMP-DEfAULT-NEXT: [[TMP7:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP8:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // OMP-DEfAULT-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// OMP-DEfAULT-NEXT: store i32 2, ptr [[TMP9]], align 4 +// OMP-DEfAULT-NEXT: store i32 3, ptr [[TMP9]], align 4 // OMP-DEfAULT-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // OMP-DEfAULT-NEXT: store i32 1, ptr [[TMP10]], align 4 // OMP-DEfAULT-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_parallel_generic_loop_codegen-2.cpp b/clang/test/OpenMP/target_parallel_generic_loop_codegen-2.cpp index a7b7278dff8d9d47997dacd6ac3f0312f20c43e1..a92f052085c74cef7bfcc62a038351d7294c5d2e 100644 --- a/clang/test/OpenMP/target_parallel_generic_loop_codegen-2.cpp +++ b/clang/test/OpenMP/target_parallel_generic_loop_codegen-2.cpp @@ -88,7 +88,7 @@ int nested(int a){ // CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -306,7 +306,7 @@ int nested(int a){ // CHECK-X86-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK-X86-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-X86-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-X86-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK-X86-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK-X86-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-X86-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK-X86-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_parallel_generic_loop_uses_allocators_codegen.cpp b/clang/test/OpenMP/target_parallel_generic_loop_uses_allocators_codegen.cpp index 472811c5c56672886881370816cc558118af0dc7..0171d97e2f54586399400d1f4589e2b46f993601 100644 --- a/clang/test/OpenMP/target_parallel_generic_loop_uses_allocators_codegen.cpp +++ b/clang/test/OpenMP/target_parallel_generic_loop_uses_allocators_codegen.cpp @@ -90,7 +90,7 @@ void foo() { // CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_parallel_if_codegen.cpp b/clang/test/OpenMP/target_parallel_if_codegen.cpp index 841c49e31ccb9ebd77af053d5560a6ccbf474216..6447a76dd467c48fd2b62f7bd9182829efa9bde3 100644 --- a/clang/test/OpenMP/target_parallel_if_codegen.cpp +++ b/clang/test/OpenMP/target_parallel_if_codegen.cpp @@ -270,7 +270,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP17:%.*]] = select i1 [[TOBOOL3]], i32 0, i32 1 // CHECK1-NEXT: [[TMP18:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP17]], 0 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP19]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -335,7 +335,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP47:%.*]] = select i1 [[TOBOOL15]], i32 0, i32 1 // CHECK1-NEXT: [[TMP48:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP47]], 0 // CHECK1-NEXT: [[TMP49:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP49]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP49]], align 4 // CHECK1-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP50]], align 4 // CHECK1-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 2 @@ -416,7 +416,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP10:%.*]] = select i1 [[TOBOOL3]], i32 0, i32 1 // CHECK1-NEXT: [[TMP11:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP10]], 0 // CHECK1-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP12]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP12]], align 4 // CHECK1-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP13]], align 4 // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -459,7 +459,7 @@ int bar(int n){ // CHECK1-NEXT: br i1 [[CMP4]], label [[OMP_IF_THEN5:%.*]], label [[OMP_IF_ELSE9:%.*]] // CHECK1: omp_if.then5: // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP29]], align 4 // CHECK1-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -532,7 +532,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -586,7 +586,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP32:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0 // CHECK1-NEXT: [[TMP33:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP34:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP34]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP34]], align 4 // CHECK1-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP35]], align 4 // CHECK1-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -932,7 +932,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP17:%.*]] = select i1 [[TOBOOL3]], i32 0, i32 1 // CHECK3-NEXT: [[TMP18:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP17]], 0 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP19]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -997,7 +997,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP47:%.*]] = select i1 [[TOBOOL15]], i32 0, i32 1 // CHECK3-NEXT: [[TMP48:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP47]], 0 // CHECK3-NEXT: [[TMP49:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP49]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP49]], align 4 // CHECK3-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP50]], align 4 // CHECK3-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS16]], i32 0, i32 2 @@ -1078,7 +1078,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP10:%.*]] = select i1 [[TOBOOL3]], i32 0, i32 1 // CHECK3-NEXT: [[TMP11:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP10]], 0 // CHECK3-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP12]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP12]], align 4 // CHECK3-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP13]], align 4 // CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1121,7 +1121,7 @@ int bar(int n){ // CHECK3-NEXT: br i1 [[CMP4]], label [[OMP_IF_THEN5:%.*]], label [[OMP_IF_ELSE9:%.*]] // CHECK3: omp_if.then5: // CHECK3-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP29]], align 4 // CHECK3-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -1194,7 +1194,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1248,7 +1248,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP32:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0 // CHECK3-NEXT: [[TMP33:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP34:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP34]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP34]], align 4 // CHECK3-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP35]], align 4 // CHECK3-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_parallel_num_threads_codegen.cpp b/clang/test/OpenMP/target_parallel_num_threads_codegen.cpp index 0778bca8c3f43e728a5f2291102bcc92907a693c..a14518286dc9183e04741f175f7f142b89dacf6c 100644 --- a/clang/test/OpenMP/target_parallel_num_threads_codegen.cpp +++ b/clang/test/OpenMP/target_parallel_num_threads_codegen.cpp @@ -271,7 +271,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 // CHECK1-NEXT: [[TMP18:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP17]], 0 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP19]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -313,7 +313,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP37:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP38:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP39]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP39]], align 4 // CHECK1-NEXT: [[TMP40:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP40]], align 4 // CHECK1-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -384,7 +384,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP8]], 0 // CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP10]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP10]], align 4 // CHECK1-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP11]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -433,7 +433,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP33:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 // CHECK1-NEXT: [[TMP34:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP33]], 0 // CHECK1-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP35]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP35]], align 4 // CHECK1-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP36]], align 4 // CHECK1-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -488,7 +488,7 @@ int bar(int n){ // CHECK1-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4 // CHECK1-NEXT: store i32 0, ptr [[A]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -556,7 +556,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP34:%.*]] = zext i16 [[TMP33]] to i32 // CHECK1-NEXT: [[TMP35:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP34]], 0 // CHECK1-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK1-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK1-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 2 @@ -849,7 +849,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP17]], 0 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP19]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -891,7 +891,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP37:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP38:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK3-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP39]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP39]], align 4 // CHECK3-NEXT: [[TMP40:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP40]], align 4 // CHECK3-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -962,7 +962,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP8]], 0 // CHECK3-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP10]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP10]], align 4 // CHECK3-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP11]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1011,7 +1011,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP33:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 // CHECK3-NEXT: [[TMP34:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP33]], 0 // CHECK3-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP35]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP35]], align 4 // CHECK3-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP36]], align 4 // CHECK3-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -1066,7 +1066,7 @@ int bar(int n){ // CHECK3-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4 // CHECK3-NEXT: store i32 0, ptr [[A]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1134,7 +1134,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP34:%.*]] = zext i16 [[TMP33]] to i32 // CHECK3-NEXT: [[TMP35:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP34]], 0 // CHECK3-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK3-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK3-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_task_affinity_codegen.cpp b/clang/test/OpenMP/target_task_affinity_codegen.cpp index 472c50235bf9e3bdef705431726221715dc4195f..2ef6e5a2f7a3de094c43a969ecf23cd9b216e8bc 100644 --- a/clang/test/OpenMP/target_task_affinity_codegen.cpp +++ b/clang/test/OpenMP/target_task_affinity_codegen.cpp @@ -118,7 +118,7 @@ int main() { // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP27]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP27]], align 4 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP28]], align 4 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -341,7 +341,7 @@ int main() { // CHECK3-NEXT: [[TMP25:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0 // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP27]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP27]], align 4 // CHECK3-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP28]], align 4 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_codegen.cpp b/clang/test/OpenMP/target_teams_codegen.cpp index e22fcbbcd277bcd6c0b7e85276b9dcb1aec41486..24dc2fd2e49f445d9e4fa352e7b6cba010d13749 100644 --- a/clang/test/OpenMP/target_teams_codegen.cpp +++ b/clang/test/OpenMP/target_teams_codegen.cpp @@ -453,7 +453,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP50:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0 // CHECK1-NEXT: [[TMP51:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0 // CHECK1-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP52]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP52]], align 4 // CHECK1-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP53]], align 4 // CHECK1-NEXT: [[TMP54:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -510,7 +510,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP78:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS10]], i32 0, i32 0 // CHECK1-NEXT: [[TMP79:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS11]], i32 0, i32 0 // CHECK1-NEXT: [[TMP80:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS13]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP80]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP80]], align 4 // CHECK1-NEXT: [[TMP81:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS13]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP81]], align 4 // CHECK1-NEXT: [[TMP82:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS13]], i32 0, i32 2 @@ -568,7 +568,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP105:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS18]], i32 0, i32 0 // CHECK1-NEXT: [[TMP106:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS19]], i32 0, i32 0 // CHECK1-NEXT: [[TMP107:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP107]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP107]], align 4 // CHECK1-NEXT: [[TMP108:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP108]], align 4 // CHECK1-NEXT: [[TMP109:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 2 @@ -673,7 +673,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP158:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CHECK1-NEXT: [[TMP159:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK1-NEXT: [[TMP160:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP160]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP160]], align 4 // CHECK1-NEXT: [[TMP161:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CHECK1-NEXT: store i32 9, ptr [[TMP161]], align 4 // CHECK1-NEXT: [[TMP162:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -723,7 +723,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP180:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS35]], i32 0, i32 0 // CHECK1-NEXT: [[TMP181:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS36]], i32 0, i32 0 // CHECK1-NEXT: [[TMP182:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP182]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP182]], align 4 // CHECK1-NEXT: [[TMP183:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP183]], align 4 // CHECK1-NEXT: [[TMP184:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 2 @@ -767,7 +767,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP202:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS42]], i32 0, i32 0 // CHECK1-NEXT: [[TMP203:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS43]], i32 0, i32 0 // CHECK1-NEXT: [[TMP204:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP204]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP204]], align 4 // CHECK1-NEXT: [[TMP205:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP205]], align 4 // CHECK1-NEXT: [[TMP206:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 2 @@ -919,7 +919,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP19:%.*]] = load i32, ptr [[TMP17]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP18]], 0 // CHECK1-NEXT: [[TMP21:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP19]], 0 -// CHECK1-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META25]] +// CHECK1-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META25]] // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP22]], align 4, !noalias [[META25]] // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -1317,7 +1317,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1482,7 +1482,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK1-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP30]], align 4 // CHECK1-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1590,7 +1590,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP22]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1678,7 +1678,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2040,7 +2040,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP48:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0 // CHECK3-NEXT: [[TMP49:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0 // CHECK3-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP50]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP50]], align 4 // CHECK3-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP51]], align 4 // CHECK3-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2097,7 +2097,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP76:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS10]], i32 0, i32 0 // CHECK3-NEXT: [[TMP77:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS11]], i32 0, i32 0 // CHECK3-NEXT: [[TMP78:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS13]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP78]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP78]], align 4 // CHECK3-NEXT: [[TMP79:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS13]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP79]], align 4 // CHECK3-NEXT: [[TMP80:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS13]], i32 0, i32 2 @@ -2155,7 +2155,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP103:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS18]], i32 0, i32 0 // CHECK3-NEXT: [[TMP104:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS19]], i32 0, i32 0 // CHECK3-NEXT: [[TMP105:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP105]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP105]], align 4 // CHECK3-NEXT: [[TMP106:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP106]], align 4 // CHECK3-NEXT: [[TMP107:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS21]], i32 0, i32 2 @@ -2262,7 +2262,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP158:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CHECK3-NEXT: [[TMP159:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK3-NEXT: [[TMP160:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP160]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP160]], align 4 // CHECK3-NEXT: [[TMP161:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CHECK3-NEXT: store i32 9, ptr [[TMP161]], align 4 // CHECK3-NEXT: [[TMP162:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -2312,7 +2312,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP180:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS35]], i32 0, i32 0 // CHECK3-NEXT: [[TMP181:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS36]], i32 0, i32 0 // CHECK3-NEXT: [[TMP182:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP182]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP182]], align 4 // CHECK3-NEXT: [[TMP183:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP183]], align 4 // CHECK3-NEXT: [[TMP184:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS38]], i32 0, i32 2 @@ -2356,7 +2356,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP202:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS42]], i32 0, i32 0 // CHECK3-NEXT: [[TMP203:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS43]], i32 0, i32 0 // CHECK3-NEXT: [[TMP204:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP204]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP204]], align 4 // CHECK3-NEXT: [[TMP205:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP205]], align 4 // CHECK3-NEXT: [[TMP206:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 2 @@ -2508,7 +2508,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP19:%.*]] = load i32, ptr [[TMP17]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP18]], 0 // CHECK3-NEXT: [[TMP21:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP19]], 0 -// CHECK3-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META26]] +// CHECK3-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META26]] // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP22]], align 4, !noalias [[META26]] // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -2905,7 +2905,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP6]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3070,7 +3070,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP28:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK3-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP30]], align 4 // CHECK3-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3178,7 +3178,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP22]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3266,7 +3266,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_codegen.cpp index 1ad3d8333ba60f7169cd1090005bd617a223b804..bd33e52ca3ef08a4a833445b2bf6b0eb670cc9a9 100644 --- a/clang/test/OpenMP/target_teams_distribute_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_codegen.cpp @@ -427,7 +427,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP50:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0 // CHECK1-NEXT: [[TMP51:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0 // CHECK1-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP52]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP52]], align 4 // CHECK1-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP53]], align 4 // CHECK1-NEXT: [[TMP54:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -484,7 +484,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP78:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS10]], i32 0, i32 0 // CHECK1-NEXT: [[TMP79:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS11]], i32 0, i32 0 // CHECK1-NEXT: [[TMP80:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP80]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP80]], align 4 // CHECK1-NEXT: [[TMP81:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP81]], align 4 // CHECK1-NEXT: [[TMP82:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 @@ -605,7 +605,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP137:%.*]] = getelementptr inbounds [10 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 0 // CHECK1-NEXT: [[TMP138:%.*]] = getelementptr inbounds [10 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK1-NEXT: [[TMP139:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP139]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP139]], align 4 // CHECK1-NEXT: [[TMP140:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 1 // CHECK1-NEXT: store i32 10, ptr [[TMP140]], align 4 // CHECK1-NEXT: [[TMP141:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 2 @@ -812,7 +812,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP19:%.*]] = load i32, ptr [[TMP17]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP18]], 0 // CHECK1-NEXT: [[TMP21:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP19]], 0 -// CHECK1-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META21]] +// CHECK1-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META21]] // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP22]], align 4, !noalias [[META21]] // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -1397,7 +1397,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK1-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP30]], align 4 // CHECK1-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1534,7 +1534,7 @@ int bar(int n){ // CHECK1-NEXT: [[ADD5:%.*]] = add i32 [[TMP30]], 1 // CHECK1-NEXT: [[TMP31:%.*]] = zext i32 [[ADD5]] to i64 // CHECK1-NEXT: [[TMP32:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP32]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP32]], align 4 // CHECK1-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP33]], align 4 // CHECK1-NEXT: [[TMP34:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1623,7 +1623,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2163,7 +2163,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP48:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0 // CHECK3-NEXT: [[TMP49:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0 // CHECK3-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP50]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP50]], align 4 // CHECK3-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP51]], align 4 // CHECK3-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2220,7 +2220,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP76:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS10]], i32 0, i32 0 // CHECK3-NEXT: [[TMP77:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS11]], i32 0, i32 0 // CHECK3-NEXT: [[TMP78:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP78]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP78]], align 4 // CHECK3-NEXT: [[TMP79:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP79]], align 4 // CHECK3-NEXT: [[TMP80:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 @@ -2343,7 +2343,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP137:%.*]] = getelementptr inbounds [10 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 0 // CHECK3-NEXT: [[TMP138:%.*]] = getelementptr inbounds [10 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK3-NEXT: [[TMP139:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP139]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP139]], align 4 // CHECK3-NEXT: [[TMP140:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 1 // CHECK3-NEXT: store i32 10, ptr [[TMP140]], align 4 // CHECK3-NEXT: [[TMP141:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 2 @@ -2550,7 +2550,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP19:%.*]] = load i32, ptr [[TMP17]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP18]], 0 // CHECK3-NEXT: [[TMP21:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP19]], 0 -// CHECK3-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META22]] +// CHECK3-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META22]] // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP22]], align 4, !noalias [[META22]] // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -3135,7 +3135,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP28:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK3-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP30]], align 4 // CHECK3-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3272,7 +3272,7 @@ int bar(int n){ // CHECK3-NEXT: [[ADD5:%.*]] = add i32 [[TMP30]], 1 // CHECK3-NEXT: [[TMP31:%.*]] = zext i32 [[ADD5]] to i64 // CHECK3-NEXT: [[TMP32:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP32]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP32]], align 4 // CHECK3-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP33]], align 4 // CHECK3-NEXT: [[TMP34:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3361,7 +3361,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_collapse_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_collapse_codegen.cpp index 2d886109b95b96f679cf06ccec69b4b7eeeb33ea..52b40ede902ce31da3de73da75c004f66b9e4ee2 100644 --- a/clang/test/OpenMP/target_teams_distribute_collapse_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_collapse_codegen.cpp @@ -124,7 +124,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -285,7 +285,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -514,7 +514,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP35:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK9-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP35]], 1 // CHECK9-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK9-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP37]], align 4 // CHECK9-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -750,7 +750,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -975,7 +975,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP34:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK11-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP34]], 1 // CHECK11-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP35]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP35]], align 4 // CHECK11-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP36]], align 4 // CHECK11-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1209,7 +1209,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_dist_schedule_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_dist_schedule_codegen.cpp index 714ed708e71a855417facb2161ed0f2ee35eec80..e898f6cff7e7d0902b89803afb0e404606313fe7 100644 --- a/clang/test/OpenMP/target_teams_distribute_dist_schedule_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_dist_schedule_codegen.cpp @@ -161,7 +161,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -203,7 +203,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -245,7 +245,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK1-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK1-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK1-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK1-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -573,7 +573,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -615,7 +615,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK3-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -657,7 +657,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK3-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK3-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK3-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK3-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1030,7 +1030,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK9-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1101,7 +1101,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK9-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK9-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK9-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK9-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1183,7 +1183,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD30:%.*]] = add nsw i32 [[TMP97]], 1 // CHECK9-NEXT: [[TMP98:%.*]] = zext i32 [[ADD30]] to i64 // CHECK9-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP99]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP99]], align 4 // CHECK9-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP100]], align 4 // CHECK9-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -1619,7 +1619,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1660,7 +1660,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -1701,7 +1701,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK9-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK9-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK9-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK9-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -2071,7 +2071,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK11-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2143,7 +2143,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP57]], 1 // CHECK11-NEXT: [[TMP58:%.*]] = zext i32 [[ADD14]] to i64 // CHECK11-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP59]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK11-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP60]], align 4 // CHECK11-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -2226,7 +2226,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD30:%.*]] = add nsw i32 [[TMP99]], 1 // CHECK11-NEXT: [[TMP100:%.*]] = zext i32 [[ADD30]] to i64 // CHECK11-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP101]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP101]], align 4 // CHECK11-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP102]], align 4 // CHECK11-NEXT: [[TMP103:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -2659,7 +2659,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2700,7 +2700,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -2741,7 +2741,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK11-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK11-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK11-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK11-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp index 1d6f69079df969a12b5cdd098b7e41875ddd004c..da69e19a890efa72621f2a9e7e176f7d8e4ea551 100644 --- a/clang/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_firstprivate_codegen.cpp @@ -303,7 +303,7 @@ int main() { // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP22]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -584,7 +584,7 @@ int main() { // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1105,7 +1105,7 @@ int main() { // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP22]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1384,7 +1384,7 @@ int main() { // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_lastprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_lastprivate_codegen.cpp index ffba1c2221c248a4b068b52fd63df5eede001989..e23435d13e9aecd37d41e59d4e8d8932065f4151 100644 --- a/clang/test/OpenMP/target_teams_distribute_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_lastprivate_codegen.cpp @@ -522,7 +522,7 @@ int main() { // CHECK9-NEXT: [[TMP21:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP24]], align 4 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -837,7 +837,7 @@ int main() { // CHECK9-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK9-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK9-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1223,7 +1223,7 @@ int main() { // CHECK11-NEXT: [[TMP21:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP24]], align 4 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1536,7 +1536,7 @@ int main() { // CHECK11-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK11-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK11-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp index 7e06d8c16169f74d14cad7613054d35555923e37..0d0d9967472144aa80b0cdc29450fd520091fa40 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp @@ -653,7 +653,7 @@ int target_teams_fun(int *g){ // CHECK2-NEXT: [[TMP29:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP23]], 0 // CHECK2-NEXT: [[TMP30:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP24]], 0 // CHECK2-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP31]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP31]], align 4 // CHECK2-NEXT: [[TMP32:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK2-NEXT: store i32 4, ptr [[TMP32]], align 4 // CHECK2-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -720,7 +720,7 @@ int target_teams_fun(int *g){ // CHECK2-NEXT: [[ADD17:%.*]] = add nsw i32 [[TMP62]], 1 // CHECK2-NEXT: [[TMP63:%.*]] = zext i32 [[ADD17]] to i64 // CHECK2-NEXT: [[TMP64:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP64]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP64]], align 4 // CHECK2-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 1 // CHECK2-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK2-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 2 @@ -1295,7 +1295,7 @@ int target_teams_fun(int *g){ // CHECK4-NEXT: [[TMP29:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP23]], 0 // CHECK4-NEXT: [[TMP30:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP24]], 0 // CHECK4-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK4-NEXT: store i32 2, ptr [[TMP31]], align 4 +// CHECK4-NEXT: store i32 3, ptr [[TMP31]], align 4 // CHECK4-NEXT: [[TMP32:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK4-NEXT: store i32 4, ptr [[TMP32]], align 4 // CHECK4-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1362,7 +1362,7 @@ int target_teams_fun(int *g){ // CHECK4-NEXT: [[ADD17:%.*]] = add nsw i32 [[TMP62]], 1 // CHECK4-NEXT: [[TMP63:%.*]] = zext i32 [[ADD17]] to i64 // CHECK4-NEXT: [[TMP64:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 0 -// CHECK4-NEXT: store i32 2, ptr [[TMP64]], align 4 +// CHECK4-NEXT: store i32 3, ptr [[TMP64]], align 4 // CHECK4-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 1 // CHECK4-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK4-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_collapse_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_collapse_codegen.cpp index b812011ea4ca0413522eebf21a2d00de1a969a19..da85b23de2e2965a7a1c35d77dc82d0c293dba70 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_collapse_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_collapse_codegen.cpp @@ -129,7 +129,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -365,7 +365,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -665,7 +665,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP35:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK9-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP35]], 1 // CHECK9-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK9-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP37]], align 4 // CHECK9-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1027,7 +1027,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1327,7 +1327,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP34:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK11-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP34]], 1 // CHECK11-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP35]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP35]], align 4 // CHECK11-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP36]], align 4 // CHECK11-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1691,7 +1691,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_codegen.cpp index 0aa75952a3c2b90f0a8087864944df87816a5773..e0b722bd804673ea01ab947a919a720db532b49e 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_codegen.cpp @@ -173,7 +173,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -215,7 +215,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -257,7 +257,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK1-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK1-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK1-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK1-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -807,7 +807,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -849,7 +849,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK3-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -891,7 +891,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK3-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK3-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK3-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK3-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1476,7 +1476,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK9-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1547,7 +1547,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK9-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK9-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK9-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK9-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1629,7 +1629,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD30:%.*]] = add nsw i32 [[TMP97]], 1 // CHECK9-NEXT: [[TMP98:%.*]] = zext i32 [[ADD30]] to i64 // CHECK9-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP99]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP99]], align 4 // CHECK9-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP100]], align 4 // CHECK9-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -2394,7 +2394,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2435,7 +2435,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -2487,7 +2487,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK9-NEXT: [[TMP50:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK9-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP51]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP51]], align 4 // CHECK9-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK9-NEXT: store i32 2, ptr [[TMP52]], align 4 // CHECK9-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -3096,7 +3096,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK11-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3168,7 +3168,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP57]], 1 // CHECK11-NEXT: [[TMP58:%.*]] = zext i32 [[ADD14]] to i64 // CHECK11-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP59]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK11-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP60]], align 4 // CHECK11-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -3251,7 +3251,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD30:%.*]] = add nsw i32 [[TMP99]], 1 // CHECK11-NEXT: [[TMP100:%.*]] = zext i32 [[ADD30]] to i64 // CHECK11-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP101]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP101]], align 4 // CHECK11-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP102]], align 4 // CHECK11-NEXT: [[TMP103:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -4001,7 +4001,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4042,7 +4042,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -4094,7 +4094,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK11-NEXT: [[TMP50:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK11-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP51]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP51]], align 4 // CHECK11-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK11-NEXT: store i32 2, ptr [[TMP52]], align 4 // CHECK11-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 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 375279d9636080c2d2656afd91596d8379388853..bf1fc1d7cbae5f6b94645116ca0f9822f9cc16a1 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 @@ -364,7 +364,7 @@ int main() { // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP22]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -775,7 +775,7 @@ int main() { // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1426,7 +1426,7 @@ int main() { // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP22]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1831,7 +1831,7 @@ int main() { // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp index 9baf13385bef5bbf184d0e0990c136bed97b9e97..9be3ca8fd7587c4546811377a41cdd13ec29ea2b 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp @@ -113,7 +113,7 @@ int main() { // CHECK1-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -146,7 +146,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -476,7 +476,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS6:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -535,7 +535,7 @@ int main() { // CHECK1-NEXT: [[TMP25:%.*]] = select i1 [[TOBOOL4]], i32 0, i32 1 // CHECK1-NEXT: [[TMP26:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP25]], 0 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP27]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP27]], align 4 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP28]], align 4 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -1035,7 +1035,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS5:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 [[ARG]], ptr [[ARG_ADDR]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1090,7 +1090,7 @@ int main() { // CHECK1-NEXT: [[TMP24:%.*]] = select i1 [[TOBOOL3]], i32 0, i32 1 // CHECK1-NEXT: [[TMP25:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP24]], 0 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP26]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP26]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP27]], align 4 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp index e54c230eea7eefd96af9b8c30f2ae684a928ee22..ae900d2dc53b9c1914c580f0b6b029fae008a871 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp @@ -783,7 +783,7 @@ int main() { // CHECK5-NEXT: [[TMP21:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK5-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 5, ptr [[TMP24]], align 4 // CHECK5-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1252,7 +1252,7 @@ int main() { // CHECK5-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK5-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK5-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1783,7 +1783,7 @@ int main() { // CHECK7-NEXT: [[TMP21:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK7-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 5, ptr [[TMP24]], align 4 // CHECK7-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2246,7 +2246,7 @@ int main() { // CHECK7-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK7-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK7-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp index feab9cdc948bcba8fb8552ad79b83b34021a4d00..a64110f581df8e8aef66503e66f4fa430f39aa7d 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp @@ -27,7 +27,7 @@ void gtid_test() { // CHECK1-NEXT: [[TMP:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp index 066d926e5abcbf2ec545ffbdb2cba6f61795f175..49e4681c051530b603ac7c12bc8859effa6a1488 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp @@ -301,7 +301,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -571,7 +571,7 @@ int main() { // CHECK1-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 // CHECK1-NEXT: store ptr undef, ptr [[_TMP1]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1034,7 +1034,7 @@ int main() { // CHECK3-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK3-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1298,7 +1298,7 @@ int main() { // CHECK3-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 // CHECK3-NEXT: store ptr undef, ptr [[_TMP1]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp index 9f3e50fe20a62a08f035cf5a2ad6a4e8b069025d..caac6edfc51dd160d57d7797415397b4e4843748 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp @@ -58,7 +58,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -91,7 +91,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -409,7 +409,7 @@ int main() { // CHECK1-NEXT: [[TMP:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_codegen.cpp index 1036ffd195de00e8544c669ee18c5580a14e2455..d5f1b0b9e59dccb41d07358df3f220ea5d994822 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_codegen.cpp @@ -109,7 +109,7 @@ int main() { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -400,7 +400,7 @@ int main() { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -688,7 +688,7 @@ int main() { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -975,7 +975,7 @@ int main() { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_schedule_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_schedule_codegen.cpp index 3d031e09aa07d698c637a51632c621cf1c1fc26e..fb0b2893d95290135e63fa416a8323c0049fadf7 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_schedule_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_schedule_codegen.cpp @@ -243,7 +243,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -285,7 +285,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -327,7 +327,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK1-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK1-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK1-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK1-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -369,7 +369,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP63:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 // CHECK1-NEXT: [[TMP64:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 // CHECK1-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK1-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP66]], align 4 // CHECK1-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -411,7 +411,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP83:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CHECK1-NEXT: [[TMP84:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CHECK1-NEXT: [[TMP85:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP85]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP85]], align 4 // CHECK1-NEXT: [[TMP86:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP86]], align 4 // CHECK1-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -1270,7 +1270,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1312,7 +1312,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK3-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -1354,7 +1354,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK3-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK3-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK3-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK3-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1396,7 +1396,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP63:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 // CHECK3-NEXT: [[TMP64:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 // CHECK3-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK3-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP66]], align 4 // CHECK3-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -1438,7 +1438,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP83:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CHECK3-NEXT: [[TMP84:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CHECK3-NEXT: [[TMP85:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP85]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP85]], align 4 // CHECK3-NEXT: [[TMP86:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP86]], align 4 // CHECK3-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -2270,7 +2270,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK5-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK5-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2312,7 +2312,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK5-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK5-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK5-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK5-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -2354,7 +2354,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK5-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK5-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK5-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK5-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -2396,7 +2396,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP63:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 // CHECK5-NEXT: [[TMP64:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 // CHECK5-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK5-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP66]], align 4 // CHECK5-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -2438,7 +2438,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP83:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CHECK5-NEXT: [[TMP84:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CHECK5-NEXT: [[TMP85:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP85]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP85]], align 4 // CHECK5-NEXT: [[TMP86:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP86]], align 4 // CHECK5-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -3297,7 +3297,7 @@ int main (int argc, char **argv) { // CHECK7-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK7-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK7-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3339,7 +3339,7 @@ int main (int argc, char **argv) { // CHECK7-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK7-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK7-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK7-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK7-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK7-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -3381,7 +3381,7 @@ int main (int argc, char **argv) { // CHECK7-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK7-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK7-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK7-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK7-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK7-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -3423,7 +3423,7 @@ int main (int argc, char **argv) { // CHECK7-NEXT: [[TMP63:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 // CHECK7-NEXT: [[TMP64:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 // CHECK7-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK7-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CHECK7-NEXT: store i32 1, ptr [[TMP66]], align 4 // CHECK7-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -3465,7 +3465,7 @@ int main (int argc, char **argv) { // CHECK7-NEXT: [[TMP83:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CHECK7-NEXT: [[TMP84:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CHECK7-NEXT: [[TMP85:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP85]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP85]], align 4 // CHECK7-NEXT: [[TMP86:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK7-NEXT: store i32 1, ptr [[TMP86]], align 4 // CHECK7-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -4357,7 +4357,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK13-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK13-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK13-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK13-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK13-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4428,7 +4428,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK13-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK13-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK13-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK13-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK13-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -4510,7 +4510,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD30:%.*]] = add nsw i32 [[TMP97]], 1 // CHECK13-NEXT: [[TMP98:%.*]] = zext i32 [[ADD30]] to i64 // CHECK13-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP99]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP99]], align 4 // CHECK13-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK13-NEXT: store i32 4, ptr [[TMP100]], align 4 // CHECK13-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -4581,7 +4581,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD45:%.*]] = add nsw i32 [[TMP132]], 1 // CHECK13-NEXT: [[TMP133:%.*]] = zext i32 [[ADD45]] to i64 // CHECK13-NEXT: [[TMP134:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP134]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP134]], align 4 // CHECK13-NEXT: [[TMP135:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 1 // CHECK13-NEXT: store i32 3, ptr [[TMP135]], align 4 // CHECK13-NEXT: [[TMP136:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 2 @@ -4663,7 +4663,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD62:%.*]] = add nsw i32 [[TMP173]], 1 // CHECK13-NEXT: [[TMP174:%.*]] = zext i32 [[ADD62]] to i64 // CHECK13-NEXT: [[TMP175:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP175]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP175]], align 4 // CHECK13-NEXT: [[TMP176:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 1 // CHECK13-NEXT: store i32 4, ptr [[TMP176]], align 4 // CHECK13-NEXT: [[TMP177:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 2 @@ -5881,7 +5881,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK13-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK13-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK13-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK13-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK13-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5922,7 +5922,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK13-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK13-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK13-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK13-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK13-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -5974,7 +5974,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK13-NEXT: [[TMP50:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK13-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP51]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP51]], align 4 // CHECK13-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK13-NEXT: store i32 2, ptr [[TMP52]], align 4 // CHECK13-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -6015,7 +6015,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK13-NEXT: [[TMP70:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK13-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP71]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP71]], align 4 // CHECK13-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK13-NEXT: store i32 1, ptr [[TMP72]], align 4 // CHECK13-NEXT: [[TMP73:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -6067,7 +6067,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP95:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS24]], i32 0, i32 0 // CHECK13-NEXT: [[TMP96:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS25]], i32 0, i32 0 // CHECK13-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP97]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP97]], align 4 // CHECK13-NEXT: [[TMP98:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 1 // CHECK13-NEXT: store i32 2, ptr [[TMP98]], align 4 // CHECK13-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 2 @@ -7008,7 +7008,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK15-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK15-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK15-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK15-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK15-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -7080,7 +7080,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP57]], 1 // CHECK15-NEXT: [[TMP58:%.*]] = zext i32 [[ADD14]] to i64 // CHECK15-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP59]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK15-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK15-NEXT: store i32 3, ptr [[TMP60]], align 4 // CHECK15-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -7163,7 +7163,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[ADD30:%.*]] = add nsw i32 [[TMP99]], 1 // CHECK15-NEXT: [[TMP100:%.*]] = zext i32 [[ADD30]] to i64 // CHECK15-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP101]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP101]], align 4 // CHECK15-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK15-NEXT: store i32 4, ptr [[TMP102]], align 4 // CHECK15-NEXT: [[TMP103:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -7235,7 +7235,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[ADD45:%.*]] = add nsw i32 [[TMP135]], 1 // CHECK15-NEXT: [[TMP136:%.*]] = zext i32 [[ADD45]] to i64 // CHECK15-NEXT: [[TMP137:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP137]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP137]], align 4 // CHECK15-NEXT: [[TMP138:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 1 // CHECK15-NEXT: store i32 3, ptr [[TMP138]], align 4 // CHECK15-NEXT: [[TMP139:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 2 @@ -7318,7 +7318,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[ADD62:%.*]] = add nsw i32 [[TMP177]], 1 // CHECK15-NEXT: [[TMP178:%.*]] = zext i32 [[ADD62]] to i64 // CHECK15-NEXT: [[TMP179:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP179]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP179]], align 4 // CHECK15-NEXT: [[TMP180:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 1 // CHECK15-NEXT: store i32 4, ptr [[TMP180]], align 4 // CHECK15-NEXT: [[TMP181:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 2 @@ -8511,7 +8511,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK15-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK15-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK15-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK15-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK15-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -8552,7 +8552,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK15-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK15-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK15-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK15-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK15-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -8604,7 +8604,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK15-NEXT: [[TMP50:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK15-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP51]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP51]], align 4 // CHECK15-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK15-NEXT: store i32 2, ptr [[TMP52]], align 4 // CHECK15-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -8645,7 +8645,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK15-NEXT: [[TMP70:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK15-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP71]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP71]], align 4 // CHECK15-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK15-NEXT: store i32 1, ptr [[TMP72]], align 4 // CHECK15-NEXT: [[TMP73:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -8697,7 +8697,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[TMP95:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS24]], i32 0, i32 0 // CHECK15-NEXT: [[TMP96:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS25]], i32 0, i32 0 // CHECK15-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP97]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP97]], align 4 // CHECK15-NEXT: [[TMP98:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 1 // CHECK15-NEXT: store i32 2, ptr [[TMP98]], align 4 // CHECK15-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 2 @@ -9611,7 +9611,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK17-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK17-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK17-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK17-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -9682,7 +9682,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK17-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK17-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK17-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK17-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK17-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -9764,7 +9764,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD30:%.*]] = add nsw i32 [[TMP97]], 1 // CHECK17-NEXT: [[TMP98:%.*]] = zext i32 [[ADD30]] to i64 // CHECK17-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP99]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP99]], align 4 // CHECK17-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK17-NEXT: store i32 4, ptr [[TMP100]], align 4 // CHECK17-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -9835,7 +9835,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD45:%.*]] = add nsw i32 [[TMP132]], 1 // CHECK17-NEXT: [[TMP133:%.*]] = zext i32 [[ADD45]] to i64 // CHECK17-NEXT: [[TMP134:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP134]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP134]], align 4 // CHECK17-NEXT: [[TMP135:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 1 // CHECK17-NEXT: store i32 3, ptr [[TMP135]], align 4 // CHECK17-NEXT: [[TMP136:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 2 @@ -9917,7 +9917,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD62:%.*]] = add nsw i32 [[TMP173]], 1 // CHECK17-NEXT: [[TMP174:%.*]] = zext i32 [[ADD62]] to i64 // CHECK17-NEXT: [[TMP175:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP175]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP175]], align 4 // CHECK17-NEXT: [[TMP176:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 1 // CHECK17-NEXT: store i32 4, ptr [[TMP176]], align 4 // CHECK17-NEXT: [[TMP177:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 2 @@ -11135,7 +11135,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK17-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK17-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -11176,7 +11176,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK17-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK17-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK17-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK17-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK17-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -11228,7 +11228,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK17-NEXT: [[TMP50:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK17-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP51]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP51]], align 4 // CHECK17-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK17-NEXT: store i32 2, ptr [[TMP52]], align 4 // CHECK17-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -11269,7 +11269,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK17-NEXT: [[TMP70:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK17-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP71]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP71]], align 4 // CHECK17-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK17-NEXT: store i32 1, ptr [[TMP72]], align 4 // CHECK17-NEXT: [[TMP73:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -11321,7 +11321,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP95:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS24]], i32 0, i32 0 // CHECK17-NEXT: [[TMP96:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS25]], i32 0, i32 0 // CHECK17-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP97]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP97]], align 4 // CHECK17-NEXT: [[TMP98:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 1 // CHECK17-NEXT: store i32 2, ptr [[TMP98]], align 4 // CHECK17-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 2 @@ -12262,7 +12262,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK19-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK19-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK19-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK19-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -12334,7 +12334,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP57]], 1 // CHECK19-NEXT: [[TMP58:%.*]] = zext i32 [[ADD14]] to i64 // CHECK19-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP59]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK19-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK19-NEXT: store i32 3, ptr [[TMP60]], align 4 // CHECK19-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -12417,7 +12417,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD30:%.*]] = add nsw i32 [[TMP99]], 1 // CHECK19-NEXT: [[TMP100:%.*]] = zext i32 [[ADD30]] to i64 // CHECK19-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP101]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP101]], align 4 // CHECK19-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK19-NEXT: store i32 4, ptr [[TMP102]], align 4 // CHECK19-NEXT: [[TMP103:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -12489,7 +12489,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD45:%.*]] = add nsw i32 [[TMP135]], 1 // CHECK19-NEXT: [[TMP136:%.*]] = zext i32 [[ADD45]] to i64 // CHECK19-NEXT: [[TMP137:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP137]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP137]], align 4 // CHECK19-NEXT: [[TMP138:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 1 // CHECK19-NEXT: store i32 3, ptr [[TMP138]], align 4 // CHECK19-NEXT: [[TMP139:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 2 @@ -12572,7 +12572,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD62:%.*]] = add nsw i32 [[TMP177]], 1 // CHECK19-NEXT: [[TMP178:%.*]] = zext i32 [[ADD62]] to i64 // CHECK19-NEXT: [[TMP179:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP179]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP179]], align 4 // CHECK19-NEXT: [[TMP180:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 1 // CHECK19-NEXT: store i32 4, ptr [[TMP180]], align 4 // CHECK19-NEXT: [[TMP181:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 2 @@ -13765,7 +13765,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK19-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK19-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -13806,7 +13806,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK19-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK19-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK19-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK19-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK19-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -13858,7 +13858,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK19-NEXT: [[TMP50:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK19-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP51]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP51]], align 4 // CHECK19-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK19-NEXT: store i32 2, ptr [[TMP52]], align 4 // CHECK19-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -13899,7 +13899,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK19-NEXT: [[TMP70:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK19-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP71]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP71]], align 4 // CHECK19-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK19-NEXT: store i32 1, ptr [[TMP72]], align 4 // CHECK19-NEXT: [[TMP73:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -13951,7 +13951,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP95:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS24]], i32 0, i32 0 // CHECK19-NEXT: [[TMP96:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS25]], i32 0, i32 0 // CHECK19-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP97]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP97]], align 4 // CHECK19-NEXT: [[TMP98:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 1 // CHECK19-NEXT: store i32 2, ptr [[TMP98]], align 4 // CHECK19-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp index 109063c623a11da7de177058c66963289e71f9cb..a4119a07f61f2df50553573becf45f07b1e998c2 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp @@ -181,7 +181,7 @@ void test_target_teams_atomic() { // CHECK1-NEXT: [[TMP34:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP28]], 0 // CHECK1-NEXT: [[TMP35:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP29]], 0 // CHECK1-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK1-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP37]], align 4 // CHECK1-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -248,7 +248,7 @@ void test_target_teams_atomic() { // CHECK1-NEXT: [[ADD17:%.*]] = add nsw i32 [[TMP67]], 1 // CHECK1-NEXT: [[TMP68:%.*]] = zext i32 [[ADD17]] to i64 // CHECK1-NEXT: [[TMP69:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP69]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP69]], align 4 // CHECK1-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP70]], align 4 // CHECK1-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 2 @@ -821,7 +821,7 @@ void test_target_teams_atomic() { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1116,7 +1116,7 @@ void test_target_teams_atomic() { // CHECK3-NEXT: [[TMP34:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP28]], 0 // CHECK3-NEXT: [[TMP35:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP29]], 0 // CHECK3-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK3-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP37]], align 4 // CHECK3-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1183,7 +1183,7 @@ void test_target_teams_atomic() { // CHECK3-NEXT: [[ADD17:%.*]] = add nsw i32 [[TMP67]], 1 // CHECK3-NEXT: [[TMP68:%.*]] = zext i32 [[ADD17]] to i64 // CHECK3-NEXT: [[TMP69:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP69]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP69]], align 4 // CHECK3-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP70]], align 4 // CHECK3-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 2 @@ -1746,7 +1746,7 @@ void test_target_teams_atomic() { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_codegen.cpp index 306ec1db2ab2158a7ffdf3f5a60f44913842ba75..53a13e129d3b26e5e5e95c81fca56e0b3d061f07 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_codegen.cpp @@ -129,7 +129,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -381,7 +381,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -837,7 +837,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP35:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK9-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP35]], 1 // CHECK9-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK9-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP37]], align 4 // CHECK9-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1235,7 +1235,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1551,7 +1551,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP34:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK11-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP34]], 1 // CHECK11-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP35]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP35]], align 4 // CHECK11-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP36]], align 4 // CHECK11-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1951,7 +1951,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp index c265c1c616b14a4423b092f99fd5336ddbef8a14..d449406927e716198526abbf02d99d520df6c163 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp @@ -173,7 +173,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -215,7 +215,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -257,7 +257,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK1-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK1-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK1-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK1-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -849,7 +849,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -891,7 +891,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK3-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -933,7 +933,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK3-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK3-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK3-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK3-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1807,7 +1807,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK9-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1878,7 +1878,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK9-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK9-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK9-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK9-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1960,7 +1960,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD30:%.*]] = add nsw i32 [[TMP97]], 1 // CHECK9-NEXT: [[TMP98:%.*]] = zext i32 [[ADD30]] to i64 // CHECK9-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP99]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP99]], align 4 // CHECK9-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP100]], align 4 // CHECK9-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -2797,7 +2797,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2838,7 +2838,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -2890,7 +2890,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK9-NEXT: [[TMP50:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK9-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP51]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP51]], align 4 // CHECK9-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK9-NEXT: store i32 2, ptr [[TMP52]], align 4 // CHECK9-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -3541,7 +3541,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK11-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3613,7 +3613,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP57]], 1 // CHECK11-NEXT: [[TMP58:%.*]] = zext i32 [[ADD14]] to i64 // CHECK11-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP59]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK11-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP60]], align 4 // CHECK11-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -3696,7 +3696,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD30:%.*]] = add nsw i32 [[TMP99]], 1 // CHECK11-NEXT: [[TMP100:%.*]] = zext i32 [[ADD30]] to i64 // CHECK11-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP101]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP101]], align 4 // CHECK11-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP102]], align 4 // CHECK11-NEXT: [[TMP103:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -4518,7 +4518,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4559,7 +4559,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -4611,7 +4611,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK11-NEXT: [[TMP50:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK11-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP51]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP51]], align 4 // CHECK11-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK11-NEXT: store i32 2, ptr [[TMP52]], align 4 // CHECK11-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp index 37c1f428ef9a3010b934c0cc1bd2cc6975cb1592..ea05aecebf3713cbd319dcee8509eb4520fc279f 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp @@ -362,7 +362,7 @@ int main() { // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP22]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -787,7 +787,7 @@ int main() { // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1452,7 +1452,7 @@ int main() { // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP22]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1871,7 +1871,7 @@ int main() { // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp index df5dd7ba680523cc1fe9583627f5980021b39696..71f4506fb6348e0922eb3bcb72957e8c4a2f1bde 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp @@ -130,7 +130,7 @@ int main() { // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -163,7 +163,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP22]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP22]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP23]], align 4 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -536,7 +536,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS6:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -595,7 +595,7 @@ int main() { // CHECK1-NEXT: [[TMP25:%.*]] = select i1 [[TOBOOL4]], i32 0, i32 1 // CHECK1-NEXT: [[TMP26:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP25]], 0 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP27]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP27]], align 4 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP28]], align 4 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -1137,7 +1137,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS5:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 [[ARG]], ptr [[ARG_ADDR]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1192,7 +1192,7 @@ int main() { // CHECK1-NEXT: [[TMP24:%.*]] = select i1 [[TOBOOL3]], i32 0, i32 1 // CHECK1-NEXT: [[TMP25:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP24]], 0 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP26]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP26]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP27]], align 4 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -1735,7 +1735,7 @@ int main() { // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1768,7 +1768,7 @@ int main() { // CHECK3-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK3: omp_offload.cont: // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP22]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP22]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP23]], align 4 // CHECK3-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -2141,7 +2141,7 @@ int main() { // CHECK3-NEXT: [[KERNEL_ARGS6:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK3-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2200,7 +2200,7 @@ int main() { // CHECK3-NEXT: [[TMP25:%.*]] = select i1 [[TOBOOL4]], i32 0, i32 1 // CHECK3-NEXT: [[TMP26:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP25]], 0 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP27]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP27]], align 4 // CHECK3-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP28]], align 4 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -2972,7 +2972,7 @@ int main() { // CHECK3-NEXT: [[KERNEL_ARGS5:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK3-NEXT: store i32 [[ARG]], ptr [[ARG_ADDR]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3027,7 +3027,7 @@ int main() { // CHECK3-NEXT: [[TMP24:%.*]] = select i1 [[TOBOOL3]], i32 0, i32 1 // CHECK3-NEXT: [[TMP25:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP24]], 0 // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP26]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP26]], align 4 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP27]], align 4 // CHECK3-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -4163,7 +4163,7 @@ int main() { // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK9-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK9-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4196,7 +4196,7 @@ int main() { // CHECK9-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK9: omp_offload.cont: // CHECK9-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP22]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP22]], align 4 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -4569,7 +4569,7 @@ int main() { // CHECK9-NEXT: [[KERNEL_ARGS6:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK9-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4628,7 +4628,7 @@ int main() { // CHECK9-NEXT: [[TMP25:%.*]] = select i1 [[TOBOOL4]], i32 0, i32 1 // CHECK9-NEXT: [[TMP26:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP25]], 0 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP27]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP27]], align 4 // CHECK9-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP28]], align 4 // CHECK9-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -5170,7 +5170,7 @@ int main() { // CHECK9-NEXT: [[KERNEL_ARGS5:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK9-NEXT: store i32 [[ARG]], ptr [[ARG_ADDR]], align 4 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5225,7 +5225,7 @@ int main() { // CHECK9-NEXT: [[TMP24:%.*]] = select i1 [[TOBOOL3]], i32 0, i32 1 // CHECK9-NEXT: [[TMP25:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP24]], 0 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP26]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP27]], align 4 // CHECK9-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -5768,7 +5768,7 @@ int main() { // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK11-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK11-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5801,7 +5801,7 @@ int main() { // CHECK11-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK11: omp_offload.cont: // CHECK11-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP22]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP22]], align 4 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -6174,7 +6174,7 @@ int main() { // CHECK11-NEXT: [[KERNEL_ARGS6:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK11-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -6233,7 +6233,7 @@ int main() { // CHECK11-NEXT: [[TMP25:%.*]] = select i1 [[TOBOOL4]], i32 0, i32 1 // CHECK11-NEXT: [[TMP26:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP25]], 0 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP27]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP27]], align 4 // CHECK11-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP28]], align 4 // CHECK11-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -7005,7 +7005,7 @@ int main() { // CHECK11-NEXT: [[KERNEL_ARGS5:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK11-NEXT: store i32 [[ARG]], ptr [[ARG_ADDR]], align 4 // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -7060,7 +7060,7 @@ int main() { // CHECK11-NEXT: [[TMP24:%.*]] = select i1 [[TOBOOL3]], i32 0, i32 1 // CHECK11-NEXT: [[TMP25:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP24]], 0 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP26]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP27]], align 4 // CHECK11-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp index 3fdc0c482541084b9a5245d7692f8e4167b6f6e7..b2b9e2082fa3a8dd1e01d4de683805c26930587f 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp @@ -811,7 +811,7 @@ int main() { // CHECK5-NEXT: [[TMP21:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK5-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 5, ptr [[TMP24]], align 4 // CHECK5-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1294,7 +1294,7 @@ int main() { // CHECK5-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK5-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK5-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1839,7 +1839,7 @@ int main() { // CHECK7-NEXT: [[TMP21:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK7-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 5, ptr [[TMP24]], align 4 // CHECK7-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2316,7 +2316,7 @@ int main() { // CHECK7-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK7-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK7-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp index bba97a750adc6294190ae92cf4c83bb05b55a953..0cc07c86aaea7d7e694730c8a4ca53cd5536f296 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp @@ -301,7 +301,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -585,7 +585,7 @@ int main() { // CHECK1-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 // CHECK1-NEXT: store ptr undef, ptr [[_TMP1]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1062,7 +1062,7 @@ int main() { // CHECK3-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK3-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1340,7 +1340,7 @@ int main() { // CHECK3-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 // CHECK3-NEXT: store ptr undef, ptr [[_TMP1]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp index c347743bd4fdd7efb5c01593c2835fd0d0d4f4ab..7619bf7502e788cd0cbe199455cd91013531e8bb 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp @@ -58,7 +58,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -91,7 +91,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -437,7 +437,7 @@ int main() { // CHECK1-NEXT: [[TMP:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_codegen.cpp index 52430d51cde1b5866a75a746d2fbe2a6d32cb863..3bff9904850f513ca0d937c7e1a188eece64d208 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_codegen.cpp @@ -109,7 +109,7 @@ int main() { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -414,7 +414,7 @@ int main() { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -716,7 +716,7 @@ int main() { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1017,7 +1017,7 @@ int main() { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_codegen.cpp index f7c0666d58b66183ad6ecb1a52244609b8ebf49b..b92dd14de108d91faf6841ce1d3d6d4aeffe9fb0 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_codegen.cpp @@ -243,7 +243,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -285,7 +285,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -327,7 +327,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK1-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK1-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK1-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK1-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -369,7 +369,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP63:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 // CHECK1-NEXT: [[TMP64:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 // CHECK1-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK1-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP66]], align 4 // CHECK1-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -411,7 +411,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP83:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CHECK1-NEXT: [[TMP84:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CHECK1-NEXT: [[TMP85:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP85]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP85]], align 4 // CHECK1-NEXT: [[TMP86:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP86]], align 4 // CHECK1-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -1340,7 +1340,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1382,7 +1382,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK3-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -1424,7 +1424,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK3-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK3-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK3-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK3-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1466,7 +1466,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP63:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 // CHECK3-NEXT: [[TMP64:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 // CHECK3-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK3-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP66]], align 4 // CHECK3-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -1508,7 +1508,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP83:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CHECK3-NEXT: [[TMP84:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CHECK3-NEXT: [[TMP85:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP85]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP85]], align 4 // CHECK3-NEXT: [[TMP86:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP86]], align 4 // CHECK3-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -2410,7 +2410,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK5-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK5-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2452,7 +2452,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK5-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK5-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK5-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK5-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -2494,7 +2494,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK5-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK5-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK5-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK5-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -2536,7 +2536,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP63:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 // CHECK5-NEXT: [[TMP64:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 // CHECK5-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK5-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP66]], align 4 // CHECK5-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -2578,7 +2578,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP83:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CHECK5-NEXT: [[TMP84:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CHECK5-NEXT: [[TMP85:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP85]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP85]], align 4 // CHECK5-NEXT: [[TMP86:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP86]], align 4 // CHECK5-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -3507,7 +3507,7 @@ int main (int argc, char **argv) { // CHECK7-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK7-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK7-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3549,7 +3549,7 @@ int main (int argc, char **argv) { // CHECK7-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK7-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK7-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK7-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK7-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK7-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -3591,7 +3591,7 @@ int main (int argc, char **argv) { // CHECK7-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK7-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK7-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK7-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK7-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK7-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -3633,7 +3633,7 @@ int main (int argc, char **argv) { // CHECK7-NEXT: [[TMP63:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 // CHECK7-NEXT: [[TMP64:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 // CHECK7-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK7-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CHECK7-NEXT: store i32 1, ptr [[TMP66]], align 4 // CHECK7-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -3675,7 +3675,7 @@ int main (int argc, char **argv) { // CHECK7-NEXT: [[TMP83:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CHECK7-NEXT: [[TMP84:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CHECK7-NEXT: [[TMP85:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP85]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP85]], align 4 // CHECK7-NEXT: [[TMP86:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK7-NEXT: store i32 1, ptr [[TMP86]], align 4 // CHECK7-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -5022,7 +5022,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK13-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK13-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK13-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK13-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK13-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5093,7 +5093,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK13-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK13-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK13-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK13-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK13-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -5175,7 +5175,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD30:%.*]] = add nsw i32 [[TMP97]], 1 // CHECK13-NEXT: [[TMP98:%.*]] = zext i32 [[ADD30]] to i64 // CHECK13-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP99]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP99]], align 4 // CHECK13-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK13-NEXT: store i32 4, ptr [[TMP100]], align 4 // CHECK13-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -5246,7 +5246,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD45:%.*]] = add nsw i32 [[TMP132]], 1 // CHECK13-NEXT: [[TMP133:%.*]] = zext i32 [[ADD45]] to i64 // CHECK13-NEXT: [[TMP134:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP134]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP134]], align 4 // CHECK13-NEXT: [[TMP135:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 1 // CHECK13-NEXT: store i32 3, ptr [[TMP135]], align 4 // CHECK13-NEXT: [[TMP136:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 2 @@ -5328,7 +5328,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD62:%.*]] = add nsw i32 [[TMP173]], 1 // CHECK13-NEXT: [[TMP174:%.*]] = zext i32 [[ADD62]] to i64 // CHECK13-NEXT: [[TMP175:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP175]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP175]], align 4 // CHECK13-NEXT: [[TMP176:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 1 // CHECK13-NEXT: store i32 4, ptr [[TMP176]], align 4 // CHECK13-NEXT: [[TMP177:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 2 @@ -6666,7 +6666,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK13-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK13-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK13-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK13-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK13-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -6707,7 +6707,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK13-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK13-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK13-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK13-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK13-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -6759,7 +6759,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK13-NEXT: [[TMP50:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK13-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP51]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP51]], align 4 // CHECK13-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK13-NEXT: store i32 2, ptr [[TMP52]], align 4 // CHECK13-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -6800,7 +6800,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK13-NEXT: [[TMP70:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK13-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP71]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP71]], align 4 // CHECK13-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK13-NEXT: store i32 1, ptr [[TMP72]], align 4 // CHECK13-NEXT: [[TMP73:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -6852,7 +6852,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP95:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS24]], i32 0, i32 0 // CHECK13-NEXT: [[TMP96:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS25]], i32 0, i32 0 // CHECK13-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP97]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP97]], align 4 // CHECK13-NEXT: [[TMP98:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 1 // CHECK13-NEXT: store i32 2, ptr [[TMP98]], align 4 // CHECK13-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 2 @@ -7863,7 +7863,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK15-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK15-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK15-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK15-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK15-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -7935,7 +7935,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP57]], 1 // CHECK15-NEXT: [[TMP58:%.*]] = zext i32 [[ADD14]] to i64 // CHECK15-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP59]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK15-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK15-NEXT: store i32 3, ptr [[TMP60]], align 4 // CHECK15-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -8018,7 +8018,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[ADD30:%.*]] = add nsw i32 [[TMP99]], 1 // CHECK15-NEXT: [[TMP100:%.*]] = zext i32 [[ADD30]] to i64 // CHECK15-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP101]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP101]], align 4 // CHECK15-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK15-NEXT: store i32 4, ptr [[TMP102]], align 4 // CHECK15-NEXT: [[TMP103:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -8090,7 +8090,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[ADD45:%.*]] = add nsw i32 [[TMP135]], 1 // CHECK15-NEXT: [[TMP136:%.*]] = zext i32 [[ADD45]] to i64 // CHECK15-NEXT: [[TMP137:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP137]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP137]], align 4 // CHECK15-NEXT: [[TMP138:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 1 // CHECK15-NEXT: store i32 3, ptr [[TMP138]], align 4 // CHECK15-NEXT: [[TMP139:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 2 @@ -8173,7 +8173,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[ADD62:%.*]] = add nsw i32 [[TMP177]], 1 // CHECK15-NEXT: [[TMP178:%.*]] = zext i32 [[ADD62]] to i64 // CHECK15-NEXT: [[TMP179:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP179]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP179]], align 4 // CHECK15-NEXT: [[TMP180:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 1 // CHECK15-NEXT: store i32 4, ptr [[TMP180]], align 4 // CHECK15-NEXT: [[TMP181:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 2 @@ -9486,7 +9486,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK15-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK15-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK15-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK15-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK15-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -9527,7 +9527,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK15-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK15-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK15-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK15-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK15-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -9579,7 +9579,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK15-NEXT: [[TMP50:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK15-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP51]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP51]], align 4 // CHECK15-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK15-NEXT: store i32 2, ptr [[TMP52]], align 4 // CHECK15-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -9620,7 +9620,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK15-NEXT: [[TMP70:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK15-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP71]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP71]], align 4 // CHECK15-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK15-NEXT: store i32 1, ptr [[TMP72]], align 4 // CHECK15-NEXT: [[TMP73:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -9672,7 +9672,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[TMP95:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS24]], i32 0, i32 0 // CHECK15-NEXT: [[TMP96:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS25]], i32 0, i32 0 // CHECK15-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP97]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP97]], align 4 // CHECK15-NEXT: [[TMP98:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 1 // CHECK15-NEXT: store i32 2, ptr [[TMP98]], align 4 // CHECK15-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 2 @@ -10656,7 +10656,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK17-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK17-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK17-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK17-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -10727,7 +10727,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK17-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK17-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK17-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK17-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK17-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -10809,7 +10809,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD30:%.*]] = add nsw i32 [[TMP97]], 1 // CHECK17-NEXT: [[TMP98:%.*]] = zext i32 [[ADD30]] to i64 // CHECK17-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP99]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP99]], align 4 // CHECK17-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK17-NEXT: store i32 4, ptr [[TMP100]], align 4 // CHECK17-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -10880,7 +10880,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD45:%.*]] = add nsw i32 [[TMP132]], 1 // CHECK17-NEXT: [[TMP133:%.*]] = zext i32 [[ADD45]] to i64 // CHECK17-NEXT: [[TMP134:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP134]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP134]], align 4 // CHECK17-NEXT: [[TMP135:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 1 // CHECK17-NEXT: store i32 3, ptr [[TMP135]], align 4 // CHECK17-NEXT: [[TMP136:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 2 @@ -10962,7 +10962,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD62:%.*]] = add nsw i32 [[TMP173]], 1 // CHECK17-NEXT: [[TMP174:%.*]] = zext i32 [[ADD62]] to i64 // CHECK17-NEXT: [[TMP175:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP175]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP175]], align 4 // CHECK17-NEXT: [[TMP176:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 1 // CHECK17-NEXT: store i32 4, ptr [[TMP176]], align 4 // CHECK17-NEXT: [[TMP177:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 2 @@ -12300,7 +12300,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK17-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK17-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -12341,7 +12341,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK17-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK17-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK17-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK17-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK17-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -12393,7 +12393,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK17-NEXT: [[TMP50:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK17-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP51]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP51]], align 4 // CHECK17-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK17-NEXT: store i32 2, ptr [[TMP52]], align 4 // CHECK17-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -12434,7 +12434,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK17-NEXT: [[TMP70:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK17-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP71]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP71]], align 4 // CHECK17-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK17-NEXT: store i32 1, ptr [[TMP72]], align 4 // CHECK17-NEXT: [[TMP73:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -12486,7 +12486,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP95:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS24]], i32 0, i32 0 // CHECK17-NEXT: [[TMP96:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS25]], i32 0, i32 0 // CHECK17-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP97]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP97]], align 4 // CHECK17-NEXT: [[TMP98:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 1 // CHECK17-NEXT: store i32 2, ptr [[TMP98]], align 4 // CHECK17-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 2 @@ -13497,7 +13497,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK19-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK19-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK19-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK19-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -13569,7 +13569,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP57]], 1 // CHECK19-NEXT: [[TMP58:%.*]] = zext i32 [[ADD14]] to i64 // CHECK19-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP59]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK19-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK19-NEXT: store i32 3, ptr [[TMP60]], align 4 // CHECK19-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -13652,7 +13652,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD30:%.*]] = add nsw i32 [[TMP99]], 1 // CHECK19-NEXT: [[TMP100:%.*]] = zext i32 [[ADD30]] to i64 // CHECK19-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP101]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP101]], align 4 // CHECK19-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK19-NEXT: store i32 4, ptr [[TMP102]], align 4 // CHECK19-NEXT: [[TMP103:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -13724,7 +13724,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD45:%.*]] = add nsw i32 [[TMP135]], 1 // CHECK19-NEXT: [[TMP136:%.*]] = zext i32 [[ADD45]] to i64 // CHECK19-NEXT: [[TMP137:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP137]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP137]], align 4 // CHECK19-NEXT: [[TMP138:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 1 // CHECK19-NEXT: store i32 3, ptr [[TMP138]], align 4 // CHECK19-NEXT: [[TMP139:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS46]], i32 0, i32 2 @@ -13807,7 +13807,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD62:%.*]] = add nsw i32 [[TMP177]], 1 // CHECK19-NEXT: [[TMP178:%.*]] = zext i32 [[ADD62]] to i64 // CHECK19-NEXT: [[TMP179:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP179]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP179]], align 4 // CHECK19-NEXT: [[TMP180:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 1 // CHECK19-NEXT: store i32 4, ptr [[TMP180]], align 4 // CHECK19-NEXT: [[TMP181:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS63]], i32 0, i32 2 @@ -15120,7 +15120,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK19-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK19-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -15161,7 +15161,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK19-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK19-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK19-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK19-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK19-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -15213,7 +15213,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK19-NEXT: [[TMP50:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK19-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP51]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP51]], align 4 // CHECK19-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK19-NEXT: store i32 2, ptr [[TMP52]], align 4 // CHECK19-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -15254,7 +15254,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK19-NEXT: [[TMP70:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK19-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP71]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP71]], align 4 // CHECK19-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK19-NEXT: store i32 1, ptr [[TMP72]], align 4 // CHECK19-NEXT: [[TMP73:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -15306,7 +15306,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP95:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS24]], i32 0, i32 0 // CHECK19-NEXT: [[TMP96:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS25]], i32 0, i32 0 // CHECK19-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP97]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP97]], align 4 // CHECK19-NEXT: [[TMP98:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 1 // CHECK19-NEXT: store i32 2, ptr [[TMP98]], align 4 // CHECK19-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_private_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_private_codegen.cpp index 5bc78062c8309b85c10903cc262929998a1eeb20..3cb2d2c2f9b43ef8d18036ae718a1024be5984e6 100644 --- a/clang/test/OpenMP/target_teams_distribute_private_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_private_codegen.cpp @@ -240,7 +240,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -409,7 +409,7 @@ int main() { // CHECK1-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 // CHECK1-NEXT: store ptr undef, ptr [[_TMP1]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -768,7 +768,7 @@ int main() { // CHECK3-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK3-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -935,7 +935,7 @@ int main() { // CHECK3-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 // CHECK3-NEXT: store ptr undef, ptr [[_TMP1]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_reduction_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_reduction_codegen.cpp index 9e9306a5e749f8d316f98fefe30b00f94ab8ee0c..47251b00c7a144160f4fb02302a71107f274b00f 100644 --- a/clang/test/OpenMP/target_teams_distribute_reduction_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_reduction_codegen.cpp @@ -335,7 +335,7 @@ int main() { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -376,7 +376,7 @@ int main() { // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -418,7 +418,7 @@ int main() { // CHECK1-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK1-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK1-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK1-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK1-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -460,7 +460,7 @@ int main() { // CHECK1-NEXT: [[TMP63:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK1-NEXT: [[TMP64:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK1-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK1-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP66]], align 4 // CHECK1-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -502,7 +502,7 @@ int main() { // CHECK1-NEXT: [[TMP83:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 0 // CHECK1-NEXT: [[TMP84:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 0 // CHECK1-NEXT: [[TMP85:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP85]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP85]], align 4 // CHECK1-NEXT: [[TMP86:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP86]], align 4 // CHECK1-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 2 @@ -544,7 +544,7 @@ int main() { // CHECK1-NEXT: [[TMP103:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0 // CHECK1-NEXT: [[TMP104:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0 // CHECK1-NEXT: [[TMP105:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS33]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP105]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP105]], align 4 // CHECK1-NEXT: [[TMP106:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS33]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP106]], align 4 // CHECK1-NEXT: [[TMP107:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS33]], i32 0, i32 2 @@ -585,7 +585,7 @@ int main() { // CHECK1-NEXT: [[TMP123:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS36]], i32 0, i32 0 // CHECK1-NEXT: [[TMP124:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS37]], i32 0, i32 0 // CHECK1-NEXT: [[TMP125:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS40]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP125]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP125]], align 4 // CHECK1-NEXT: [[TMP126:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS40]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP126]], align 4 // CHECK1-NEXT: [[TMP127:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS40]], i32 0, i32 2 @@ -626,7 +626,7 @@ int main() { // CHECK1-NEXT: [[TMP143:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS43]], i32 0, i32 0 // CHECK1-NEXT: [[TMP144:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS44]], i32 0, i32 0 // CHECK1-NEXT: [[TMP145:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS47]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP145]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP145]], align 4 // CHECK1-NEXT: [[TMP146:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS47]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP146]], align 4 // CHECK1-NEXT: [[TMP147:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS47]], i32 0, i32 2 @@ -668,7 +668,7 @@ int main() { // CHECK1-NEXT: [[TMP163:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS50]], i32 0, i32 0 // CHECK1-NEXT: [[TMP164:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS51]], i32 0, i32 0 // CHECK1-NEXT: [[TMP165:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS54]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP165]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP165]], align 4 // CHECK1-NEXT: [[TMP166:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS54]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP166]], align 4 // CHECK1-NEXT: [[TMP167:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS54]], i32 0, i32 2 @@ -710,7 +710,7 @@ int main() { // CHECK1-NEXT: [[TMP183:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS57]], i32 0, i32 0 // CHECK1-NEXT: [[TMP184:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS58]], i32 0, i32 0 // CHECK1-NEXT: [[TMP185:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP185]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP185]], align 4 // CHECK1-NEXT: [[TMP186:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP186]], align 4 // CHECK1-NEXT: [[TMP187:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 2 @@ -2179,7 +2179,7 @@ int main() { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2226,7 +2226,7 @@ int main() { // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP29]], align 4 // CHECK1-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -2274,7 +2274,7 @@ int main() { // CHECK1-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK1-NEXT: [[TMP50:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK1-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP51]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP51]], align 4 // CHECK1-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP52]], align 4 // CHECK1-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -2322,7 +2322,7 @@ int main() { // CHECK1-NEXT: [[TMP72:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK1-NEXT: [[TMP73:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK1-NEXT: [[TMP74:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP74]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP74]], align 4 // CHECK1-NEXT: [[TMP75:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP75]], align 4 // CHECK1-NEXT: [[TMP76:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -2370,7 +2370,7 @@ int main() { // CHECK1-NEXT: [[TMP95:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 0 // CHECK1-NEXT: [[TMP96:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 0 // CHECK1-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP97]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP97]], align 4 // CHECK1-NEXT: [[TMP98:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP98]], align 4 // CHECK1-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 2 @@ -2418,7 +2418,7 @@ int main() { // CHECK1-NEXT: [[TMP118:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0 // CHECK1-NEXT: [[TMP119:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0 // CHECK1-NEXT: [[TMP120:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS33]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP120]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP120]], align 4 // CHECK1-NEXT: [[TMP121:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS33]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP121]], align 4 // CHECK1-NEXT: [[TMP122:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS33]], i32 0, i32 2 @@ -2465,7 +2465,7 @@ int main() { // CHECK1-NEXT: [[TMP141:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS36]], i32 0, i32 0 // CHECK1-NEXT: [[TMP142:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS37]], i32 0, i32 0 // CHECK1-NEXT: [[TMP143:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS40]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP143]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP143]], align 4 // CHECK1-NEXT: [[TMP144:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS40]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP144]], align 4 // CHECK1-NEXT: [[TMP145:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS40]], i32 0, i32 2 @@ -2512,7 +2512,7 @@ int main() { // CHECK1-NEXT: [[TMP164:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS43]], i32 0, i32 0 // CHECK1-NEXT: [[TMP165:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS44]], i32 0, i32 0 // CHECK1-NEXT: [[TMP166:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS47]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP166]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP166]], align 4 // CHECK1-NEXT: [[TMP167:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS47]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP167]], align 4 // CHECK1-NEXT: [[TMP168:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS47]], i32 0, i32 2 @@ -2560,7 +2560,7 @@ int main() { // CHECK1-NEXT: [[TMP187:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS50]], i32 0, i32 0 // CHECK1-NEXT: [[TMP188:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS51]], i32 0, i32 0 // CHECK1-NEXT: [[TMP189:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS54]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP189]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP189]], align 4 // CHECK1-NEXT: [[TMP190:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS54]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP190]], align 4 // CHECK1-NEXT: [[TMP191:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS54]], i32 0, i32 2 @@ -2608,7 +2608,7 @@ int main() { // CHECK1-NEXT: [[TMP210:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS57]], i32 0, i32 0 // CHECK1-NEXT: [[TMP211:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS58]], i32 0, i32 0 // CHECK1-NEXT: [[TMP212:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP212]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP212]], align 4 // CHECK1-NEXT: [[TMP213:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP213]], align 4 // CHECK1-NEXT: [[TMP214:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 2 @@ -4163,7 +4163,7 @@ int main() { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4204,7 +4204,7 @@ int main() { // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK3-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK3-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -4246,7 +4246,7 @@ int main() { // CHECK3-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK3-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK3-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK3-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK3-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -4288,7 +4288,7 @@ int main() { // CHECK3-NEXT: [[TMP63:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK3-NEXT: [[TMP64:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK3-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK3-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP66]], align 4 // CHECK3-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -4330,7 +4330,7 @@ int main() { // CHECK3-NEXT: [[TMP83:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 0 // CHECK3-NEXT: [[TMP84:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 0 // CHECK3-NEXT: [[TMP85:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP85]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP85]], align 4 // CHECK3-NEXT: [[TMP86:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP86]], align 4 // CHECK3-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 2 @@ -4372,7 +4372,7 @@ int main() { // CHECK3-NEXT: [[TMP103:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0 // CHECK3-NEXT: [[TMP104:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0 // CHECK3-NEXT: [[TMP105:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS33]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP105]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP105]], align 4 // CHECK3-NEXT: [[TMP106:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS33]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP106]], align 4 // CHECK3-NEXT: [[TMP107:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS33]], i32 0, i32 2 @@ -4413,7 +4413,7 @@ int main() { // CHECK3-NEXT: [[TMP123:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS36]], i32 0, i32 0 // CHECK3-NEXT: [[TMP124:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS37]], i32 0, i32 0 // CHECK3-NEXT: [[TMP125:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS40]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP125]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP125]], align 4 // CHECK3-NEXT: [[TMP126:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS40]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP126]], align 4 // CHECK3-NEXT: [[TMP127:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS40]], i32 0, i32 2 @@ -4454,7 +4454,7 @@ int main() { // CHECK3-NEXT: [[TMP143:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS43]], i32 0, i32 0 // CHECK3-NEXT: [[TMP144:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS44]], i32 0, i32 0 // CHECK3-NEXT: [[TMP145:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS47]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP145]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP145]], align 4 // CHECK3-NEXT: [[TMP146:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS47]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP146]], align 4 // CHECK3-NEXT: [[TMP147:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS47]], i32 0, i32 2 @@ -4496,7 +4496,7 @@ int main() { // CHECK3-NEXT: [[TMP163:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS50]], i32 0, i32 0 // CHECK3-NEXT: [[TMP164:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS51]], i32 0, i32 0 // CHECK3-NEXT: [[TMP165:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS54]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP165]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP165]], align 4 // CHECK3-NEXT: [[TMP166:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS54]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP166]], align 4 // CHECK3-NEXT: [[TMP167:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS54]], i32 0, i32 2 @@ -4538,7 +4538,7 @@ int main() { // CHECK3-NEXT: [[TMP183:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS57]], i32 0, i32 0 // CHECK3-NEXT: [[TMP184:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS58]], i32 0, i32 0 // CHECK3-NEXT: [[TMP185:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP185]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP185]], align 4 // CHECK3-NEXT: [[TMP186:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP186]], align 4 // CHECK3-NEXT: [[TMP187:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 2 @@ -6007,7 +6007,7 @@ int main() { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -6054,7 +6054,7 @@ int main() { // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK3-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP29]], align 4 // CHECK3-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -6102,7 +6102,7 @@ int main() { // CHECK3-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK3-NEXT: [[TMP50:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK3-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP51]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP51]], align 4 // CHECK3-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP52]], align 4 // CHECK3-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -6150,7 +6150,7 @@ int main() { // CHECK3-NEXT: [[TMP72:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK3-NEXT: [[TMP73:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK3-NEXT: [[TMP74:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP74]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP74]], align 4 // CHECK3-NEXT: [[TMP75:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP75]], align 4 // CHECK3-NEXT: [[TMP76:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -6198,7 +6198,7 @@ int main() { // CHECK3-NEXT: [[TMP95:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS22]], i32 0, i32 0 // CHECK3-NEXT: [[TMP96:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS23]], i32 0, i32 0 // CHECK3-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP97]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP97]], align 4 // CHECK3-NEXT: [[TMP98:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP98]], align 4 // CHECK3-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS26]], i32 0, i32 2 @@ -6246,7 +6246,7 @@ int main() { // CHECK3-NEXT: [[TMP118:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS29]], i32 0, i32 0 // CHECK3-NEXT: [[TMP119:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS30]], i32 0, i32 0 // CHECK3-NEXT: [[TMP120:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS33]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP120]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP120]], align 4 // CHECK3-NEXT: [[TMP121:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS33]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP121]], align 4 // CHECK3-NEXT: [[TMP122:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS33]], i32 0, i32 2 @@ -6293,7 +6293,7 @@ int main() { // CHECK3-NEXT: [[TMP141:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS36]], i32 0, i32 0 // CHECK3-NEXT: [[TMP142:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS37]], i32 0, i32 0 // CHECK3-NEXT: [[TMP143:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS40]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP143]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP143]], align 4 // CHECK3-NEXT: [[TMP144:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS40]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP144]], align 4 // CHECK3-NEXT: [[TMP145:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS40]], i32 0, i32 2 @@ -6340,7 +6340,7 @@ int main() { // CHECK3-NEXT: [[TMP164:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS43]], i32 0, i32 0 // CHECK3-NEXT: [[TMP165:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS44]], i32 0, i32 0 // CHECK3-NEXT: [[TMP166:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS47]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP166]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP166]], align 4 // CHECK3-NEXT: [[TMP167:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS47]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP167]], align 4 // CHECK3-NEXT: [[TMP168:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS47]], i32 0, i32 2 @@ -6388,7 +6388,7 @@ int main() { // CHECK3-NEXT: [[TMP187:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS50]], i32 0, i32 0 // CHECK3-NEXT: [[TMP188:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS51]], i32 0, i32 0 // CHECK3-NEXT: [[TMP189:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS54]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP189]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP189]], align 4 // CHECK3-NEXT: [[TMP190:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS54]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP190]], align 4 // CHECK3-NEXT: [[TMP191:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS54]], i32 0, i32 2 @@ -6436,7 +6436,7 @@ int main() { // CHECK3-NEXT: [[TMP210:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS57]], i32 0, i32 0 // CHECK3-NEXT: [[TMP211:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS58]], i32 0, i32 0 // CHECK3-NEXT: [[TMP212:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP212]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP212]], align 4 // CHECK3-NEXT: [[TMP213:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP213]], align 4 // CHECK3-NEXT: [[TMP214:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_simd_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_simd_codegen.cpp index 5091d41eec4f3de71394db5d3f21c690884aa000..d2a5d1f62a8b9d0ba1c1e56e78d55b3da3c1b4ff 100644 --- a/clang/test/OpenMP/target_teams_distribute_simd_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_simd_codegen.cpp @@ -424,7 +424,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP50:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0 // CHECK1-NEXT: [[TMP51:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0 // CHECK1-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP52]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP52]], align 4 // CHECK1-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP53]], align 4 // CHECK1-NEXT: [[TMP54:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -481,7 +481,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP78:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS10]], i32 0, i32 0 // CHECK1-NEXT: [[TMP79:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS11]], i32 0, i32 0 // CHECK1-NEXT: [[TMP80:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP80]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP80]], align 4 // CHECK1-NEXT: [[TMP81:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP81]], align 4 // CHECK1-NEXT: [[TMP82:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 @@ -591,7 +591,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP131:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS21]], i32 0, i32 0 // CHECK1-NEXT: [[TMP132:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK1-NEXT: [[TMP133:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS24]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP133]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP133]], align 4 // CHECK1-NEXT: [[TMP134:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS24]], i32 0, i32 1 // CHECK1-NEXT: store i32 9, ptr [[TMP134]], align 4 // CHECK1-NEXT: [[TMP135:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS24]], i32 0, i32 2 @@ -803,7 +803,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2 // CHECK1-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP18]], 0 -// CHECK1-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META26]] +// CHECK1-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META26]] // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP20]], align 4, !noalias [[META26]] // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -1392,7 +1392,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK1-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP30]], align 4 // CHECK1-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1529,7 +1529,7 @@ int bar(int n){ // CHECK1-NEXT: [[ADD5:%.*]] = add i32 [[TMP30]], 1 // CHECK1-NEXT: [[TMP31:%.*]] = zext i32 [[ADD5]] to i64 // CHECK1-NEXT: [[TMP32:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP32]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP32]], align 4 // CHECK1-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP33]], align 4 // CHECK1-NEXT: [[TMP34:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1618,7 +1618,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2186,7 +2186,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP48:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0 // CHECK3-NEXT: [[TMP49:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0 // CHECK3-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP50]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP50]], align 4 // CHECK3-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP51]], align 4 // CHECK3-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2243,7 +2243,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP76:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS10]], i32 0, i32 0 // CHECK3-NEXT: [[TMP77:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS11]], i32 0, i32 0 // CHECK3-NEXT: [[TMP78:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP78]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP78]], align 4 // CHECK3-NEXT: [[TMP79:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP79]], align 4 // CHECK3-NEXT: [[TMP80:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 @@ -2355,7 +2355,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP131:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS21]], i32 0, i32 0 // CHECK3-NEXT: [[TMP132:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK3-NEXT: [[TMP133:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS24]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP133]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP133]], align 4 // CHECK3-NEXT: [[TMP134:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS24]], i32 0, i32 1 // CHECK3-NEXT: store i32 9, ptr [[TMP134]], align 4 // CHECK3-NEXT: [[TMP135:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS24]], i32 0, i32 2 @@ -2567,7 +2567,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2 // CHECK3-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP16]], align 4 // CHECK3-NEXT: [[TMP19:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP18]], 0 -// CHECK3-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META27]] +// CHECK3-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META27]] // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP20]], align 4, !noalias [[META27]] // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -3156,7 +3156,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP28:%.*]] = getelementptr inbounds [5 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK3-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP30]], align 4 // CHECK3-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3293,7 +3293,7 @@ int bar(int n){ // CHECK3-NEXT: [[ADD5:%.*]] = add i32 [[TMP30]], 1 // CHECK3-NEXT: [[TMP31:%.*]] = zext i32 [[ADD5]] to i64 // CHECK3-NEXT: [[TMP32:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP32]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP32]], align 4 // CHECK3-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP33]], align 4 // CHECK3-NEXT: [[TMP34:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3382,7 +3382,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3952,7 +3952,7 @@ int bar(int n){ // CHECK5-NEXT: [[TMP50:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0 // CHECK5-NEXT: [[TMP51:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0 // CHECK5-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP52]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP52]], align 4 // CHECK5-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP53]], align 4 // CHECK5-NEXT: [[TMP54:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4009,7 +4009,7 @@ int bar(int n){ // CHECK5-NEXT: [[TMP78:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS10]], i32 0, i32 0 // CHECK5-NEXT: [[TMP79:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS11]], i32 0, i32 0 // CHECK5-NEXT: [[TMP80:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP80]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP80]], align 4 // CHECK5-NEXT: [[TMP81:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CHECK5-NEXT: store i32 2, ptr [[TMP81]], align 4 // CHECK5-NEXT: [[TMP82:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 @@ -4119,7 +4119,7 @@ int bar(int n){ // CHECK5-NEXT: [[TMP131:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS21]], i32 0, i32 0 // CHECK5-NEXT: [[TMP132:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK5-NEXT: [[TMP133:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS24]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP133]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP133]], align 4 // CHECK5-NEXT: [[TMP134:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS24]], i32 0, i32 1 // CHECK5-NEXT: store i32 9, ptr [[TMP134]], align 4 // CHECK5-NEXT: [[TMP135:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS24]], i32 0, i32 2 @@ -4331,7 +4331,7 @@ int bar(int n){ // CHECK5-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2 // CHECK5-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP16]], align 4 // CHECK5-NEXT: [[TMP19:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP18]], 0 -// CHECK5-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META26]] +// CHECK5-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META26]] // CHECK5-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK5-NEXT: store i32 3, ptr [[TMP20]], align 4, !noalias [[META26]] // CHECK5-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -4937,7 +4937,7 @@ int bar(int n){ // CHECK5-NEXT: [[TMP33:%.*]] = getelementptr inbounds [6 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP34:%.*]] = getelementptr inbounds [6 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK5-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP35]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP35]], align 4 // CHECK5-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 6, ptr [[TMP36]], align 4 // CHECK5-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5074,7 +5074,7 @@ int bar(int n){ // CHECK5-NEXT: [[ADD5:%.*]] = add i32 [[TMP30]], 1 // CHECK5-NEXT: [[TMP31:%.*]] = zext i32 [[ADD5]] to i64 // CHECK5-NEXT: [[TMP32:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP32]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP32]], align 4 // CHECK5-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 5, ptr [[TMP33]], align 4 // CHECK5-NEXT: [[TMP34:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5163,7 +5163,7 @@ int bar(int n){ // CHECK5-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK5-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK5-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5783,7 +5783,7 @@ int bar(int n){ // CHECK7-NEXT: [[TMP48:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS5]], i32 0, i32 0 // CHECK7-NEXT: [[TMP49:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS6]], i32 0, i32 0 // CHECK7-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP50]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP50]], align 4 // CHECK7-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 1, ptr [[TMP51]], align 4 // CHECK7-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5840,7 +5840,7 @@ int bar(int n){ // CHECK7-NEXT: [[TMP76:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS10]], i32 0, i32 0 // CHECK7-NEXT: [[TMP77:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS11]], i32 0, i32 0 // CHECK7-NEXT: [[TMP78:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP78]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP78]], align 4 // CHECK7-NEXT: [[TMP79:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 1 // CHECK7-NEXT: store i32 2, ptr [[TMP79]], align 4 // CHECK7-NEXT: [[TMP80:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS14]], i32 0, i32 2 @@ -5952,7 +5952,7 @@ int bar(int n){ // CHECK7-NEXT: [[TMP131:%.*]] = getelementptr inbounds [9 x ptr], ptr [[DOTOFFLOAD_PTRS21]], i32 0, i32 0 // CHECK7-NEXT: [[TMP132:%.*]] = getelementptr inbounds [9 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK7-NEXT: [[TMP133:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS24]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP133]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP133]], align 4 // CHECK7-NEXT: [[TMP134:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS24]], i32 0, i32 1 // CHECK7-NEXT: store i32 9, ptr [[TMP134]], align 4 // CHECK7-NEXT: [[TMP135:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS24]], i32 0, i32 2 @@ -6164,7 +6164,7 @@ int bar(int n){ // CHECK7-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2 // CHECK7-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP16]], align 4 // CHECK7-NEXT: [[TMP19:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP18]], 0 -// CHECK7-NEXT: store i32 2, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META27]] +// CHECK7-NEXT: store i32 3, ptr [[KERNEL_ARGS_I]], align 4, !noalias [[META27]] // CHECK7-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 1 // CHECK7-NEXT: store i32 3, ptr [[TMP20]], align 4, !noalias [[META27]] // CHECK7-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS_I]], i32 0, i32 2 @@ -6770,7 +6770,7 @@ int bar(int n){ // CHECK7-NEXT: [[TMP33:%.*]] = getelementptr inbounds [6 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP34:%.*]] = getelementptr inbounds [6 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK7-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP35]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP35]], align 4 // CHECK7-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 6, ptr [[TMP36]], align 4 // CHECK7-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -6907,7 +6907,7 @@ int bar(int n){ // CHECK7-NEXT: [[ADD5:%.*]] = add i32 [[TMP30]], 1 // CHECK7-NEXT: [[TMP31:%.*]] = zext i32 [[ADD5]] to i64 // CHECK7-NEXT: [[TMP32:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP32]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP32]], align 4 // CHECK7-NEXT: [[TMP33:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 5, ptr [[TMP33]], align 4 // CHECK7-NEXT: [[TMP34:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -6996,7 +6996,7 @@ int bar(int n){ // CHECK7-NEXT: [[TMP14:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP15:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK7-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 3, ptr [[TMP17]], align 4 // CHECK7-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_simd_collapse_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_simd_collapse_codegen.cpp index ac7fc7c1acf91e3efbd5990a8da2f4a1adba7109..b052a2200479ac4d38d2ee6265203356204cbde8 100644 --- a/clang/test/OpenMP/target_teams_distribute_simd_collapse_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_simd_collapse_codegen.cpp @@ -124,7 +124,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -293,7 +293,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -670,7 +670,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP35:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK9-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP35]], 1 // CHECK9-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK9-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP37]], align 4 // CHECK9-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -924,7 +924,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1157,7 +1157,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP34:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK11-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP34]], 1 // CHECK11-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP35]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP35]], align 4 // CHECK11-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP36]], align 4 // CHECK11-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1409,7 +1409,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_simd_dist_schedule_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_simd_dist_schedule_codegen.cpp index 867ec89421402c1cfe0f9eb7ecc654213af19554..7f7e83c4dee39674bb67efa99a59828d3168e08a 100644 --- a/clang/test/OpenMP/target_teams_distribute_simd_dist_schedule_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_simd_dist_schedule_codegen.cpp @@ -161,7 +161,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -203,7 +203,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -245,7 +245,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK1-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK1-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK1-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK1-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -594,7 +594,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -636,7 +636,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK3-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -678,7 +678,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK3-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK3-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK3-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK3-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1319,7 +1319,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK9-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1390,7 +1390,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK9-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK9-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK9-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK9-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1472,7 +1472,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD30:%.*]] = add nsw i32 [[TMP97]], 1 // CHECK9-NEXT: [[TMP98:%.*]] = zext i32 [[ADD30]] to i64 // CHECK9-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP99]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP99]], align 4 // CHECK9-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP100]], align 4 // CHECK9-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -1944,7 +1944,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1985,7 +1985,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -2026,7 +2026,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK9-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK9-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK9-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK9-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -2417,7 +2417,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK11-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2489,7 +2489,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP57]], 1 // CHECK11-NEXT: [[TMP58:%.*]] = zext i32 [[ADD14]] to i64 // CHECK11-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP59]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK11-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP60]], align 4 // CHECK11-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -2572,7 +2572,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD30:%.*]] = add nsw i32 [[TMP99]], 1 // CHECK11-NEXT: [[TMP100:%.*]] = zext i32 [[ADD30]] to i64 // CHECK11-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP101]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP101]], align 4 // CHECK11-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP102]], align 4 // CHECK11-NEXT: [[TMP103:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -3041,7 +3041,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3082,7 +3082,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -3123,7 +3123,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK11-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK11-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK11-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK11-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_simd_firstprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_simd_firstprivate_codegen.cpp index 425bcaf6c3f3d5b966be9995e81d119ea5f56375..d22aeee120d5d5caf73e9e489cf0c56ab4f26fe9 100644 --- a/clang/test/OpenMP/target_teams_distribute_simd_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_simd_firstprivate_codegen.cpp @@ -303,7 +303,7 @@ int main() { // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP22]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -591,7 +591,7 @@ int main() { // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1119,7 +1119,7 @@ int main() { // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP22]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1405,7 +1405,7 @@ int main() { // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_simd_lastprivate_codegen.cpp index 4c9e83afb3bb3e9f6fe459c11d28b54d9243986a..93c570ac0604ff4e3ca364a9188b297fc8a37f26 100644 --- a/clang/test/OpenMP/target_teams_distribute_simd_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_simd_lastprivate_codegen.cpp @@ -572,7 +572,7 @@ int main() { // CHECK9-NEXT: [[TMP21:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP24]], align 4 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -894,7 +894,7 @@ int main() { // CHECK9-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK9-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK9-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1287,7 +1287,7 @@ int main() { // CHECK11-NEXT: [[TMP21:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP22:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP24]], align 4 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1607,7 +1607,7 @@ int main() { // CHECK11-NEXT: [[TMP16:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP17:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK11-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP19]], align 4 // CHECK11-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_simd_private_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_simd_private_codegen.cpp index 6cfec0010d00cb957cc93aa7beee64e570cf16a9..4e9b4e1027e6863d619fddea390ed445c33028a7 100644 --- a/clang/test/OpenMP/target_teams_distribute_simd_private_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_simd_private_codegen.cpp @@ -240,7 +240,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -416,7 +416,7 @@ int main() { // CHECK1-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 // CHECK1-NEXT: store ptr undef, ptr [[_TMP1]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -782,7 +782,7 @@ int main() { // CHECK3-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK3-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -956,7 +956,7 @@ int main() { // CHECK3-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 // CHECK3-NEXT: store ptr undef, ptr [[_TMP1]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_distribute_simd_reduction_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_simd_reduction_codegen.cpp index 1481b4fe85fde9bef4488c313914b2d02ae20ac5..667450c32f1dd0982852c9776106a4ca51dcdb80 100644 --- a/clang/test/OpenMP/target_teams_distribute_simd_reduction_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_simd_reduction_codegen.cpp @@ -97,7 +97,7 @@ int main() { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -281,7 +281,7 @@ int main() { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -462,7 +462,7 @@ int main() { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -646,7 +646,7 @@ int main() { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_generic_loop_codegen-1.cpp b/clang/test/OpenMP/target_teams_generic_loop_codegen-1.cpp index 190ea17e96070455c1955b4414679be029870d00..ec806081a3e442bd185b857ae792c3c32060d732 100644 --- a/clang/test/OpenMP/target_teams_generic_loop_codegen-1.cpp +++ b/clang/test/OpenMP/target_teams_generic_loop_codegen-1.cpp @@ -635,7 +635,7 @@ int target_teams_fun(int *g){ // CHECK2-NEXT: [[TMP27:%.*]] = zext i32 [[ADD]] to i64 // CHECK2-NEXT: [[TMP28:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP23]], 0 // CHECK2-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK2-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK2-NEXT: store i32 4, ptr [[TMP30]], align 4 // CHECK2-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -702,7 +702,7 @@ int target_teams_fun(int *g){ // CHECK2-NEXT: [[ADD17:%.*]] = add nsw i32 [[TMP60]], 1 // CHECK2-NEXT: [[TMP61:%.*]] = zext i32 [[ADD17]] to i64 // CHECK2-NEXT: [[TMP62:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP62]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP62]], align 4 // CHECK2-NEXT: [[TMP63:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 1 // CHECK2-NEXT: store i32 3, ptr [[TMP63]], align 4 // CHECK2-NEXT: [[TMP64:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 2 @@ -1260,7 +1260,7 @@ int target_teams_fun(int *g){ // CHECK4-NEXT: [[TMP27:%.*]] = zext i32 [[ADD]] to i64 // CHECK4-NEXT: [[TMP28:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP23]], 0 // CHECK4-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK4-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK4-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK4-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK4-NEXT: store i32 4, ptr [[TMP30]], align 4 // CHECK4-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1327,7 +1327,7 @@ int target_teams_fun(int *g){ // CHECK4-NEXT: [[ADD17:%.*]] = add nsw i32 [[TMP60]], 1 // CHECK4-NEXT: [[TMP61:%.*]] = zext i32 [[ADD17]] to i64 // CHECK4-NEXT: [[TMP62:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 0 -// CHECK4-NEXT: store i32 2, ptr [[TMP62]], align 4 +// CHECK4-NEXT: store i32 3, ptr [[TMP62]], align 4 // CHECK4-NEXT: [[TMP63:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 1 // CHECK4-NEXT: store i32 3, ptr [[TMP63]], align 4 // CHECK4-NEXT: [[TMP64:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS18]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_generic_loop_collapse_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_collapse_codegen.cpp index 82ad43373327af7f7e7cedc394c55d7e1430e2bf..f4aea067ba22ab8537ab2846496e89a279b82089 100644 --- a/clang/test/OpenMP/target_teams_generic_loop_collapse_codegen.cpp +++ b/clang/test/OpenMP/target_teams_generic_loop_collapse_codegen.cpp @@ -129,7 +129,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -365,7 +365,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -665,7 +665,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP35:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK9-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP35]], 1 // CHECK9-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK9-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP37]], align 4 // CHECK9-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1027,7 +1027,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1327,7 +1327,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP34:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK11-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP34]], 1 // CHECK11-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP35]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP35]], align 4 // CHECK11-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP36]], align 4 // CHECK11-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1691,7 +1691,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_generic_loop_if_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_if_codegen.cpp index b2ff4c20db7a12ad70cdb887ae4c76396f0fbf50..1edcbfe2d777983abf8dfcdc976b05e052bfbb15 100644 --- a/clang/test/OpenMP/target_teams_generic_loop_if_codegen.cpp +++ b/clang/test/OpenMP/target_teams_generic_loop_if_codegen.cpp @@ -111,7 +111,7 @@ int main() { // CHECK1-NEXT: [[TMP:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -437,7 +437,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS6:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -496,7 +496,7 @@ int main() { // CHECK1-NEXT: [[TMP25:%.*]] = select i1 [[TOBOOL4]], i32 0, i32 1 // CHECK1-NEXT: [[TMP26:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP25]], 0 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP27]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP27]], align 4 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP28]], align 4 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -991,7 +991,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 [[ARG]], ptr [[ARG_ADDR]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1029,7 +1029,7 @@ int main() { // CHECK1-NEXT: br i1 [[TOBOOL]], label [[OMP_IF_THEN:%.*]], label [[OMP_IF_ELSE:%.*]] // CHECK1: omp_if.then: // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP17]], align 4 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_generic_loop_order_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_order_codegen.cpp index 85f6a85a11bd815bfd797bfbdce332dde8c08a1c..fbf7b004d5efb071d76a74109535d41595a44078 100644 --- a/clang/test/OpenMP/target_teams_generic_loop_order_codegen.cpp +++ b/clang/test/OpenMP/target_teams_generic_loop_order_codegen.cpp @@ -27,7 +27,7 @@ void gtid_test() { // CHECK1-NEXT: [[TMP:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_generic_loop_private_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_private_codegen.cpp index 7503b69b92aa91005cdd4153b1ab58f2e1321cc5..99416f76e409c5a509541d8b84030dd85eb89c9c 100644 --- a/clang/test/OpenMP/target_teams_generic_loop_private_codegen.cpp +++ b/clang/test/OpenMP/target_teams_generic_loop_private_codegen.cpp @@ -301,7 +301,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -571,7 +571,7 @@ int main() { // CHECK1-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 // CHECK1-NEXT: store ptr undef, ptr [[_TMP1]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1034,7 +1034,7 @@ int main() { // CHECK3-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK3-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1298,7 +1298,7 @@ int main() { // CHECK3-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 // CHECK3-NEXT: store ptr undef, ptr [[_TMP1]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_generic_loop_reduction_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_reduction_codegen.cpp index 1036ffd195de00e8544c669ee18c5580a14e2455..d5f1b0b9e59dccb41d07358df3f220ea5d994822 100644 --- a/clang/test/OpenMP/target_teams_generic_loop_reduction_codegen.cpp +++ b/clang/test/OpenMP/target_teams_generic_loop_reduction_codegen.cpp @@ -109,7 +109,7 @@ int main() { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -400,7 +400,7 @@ int main() { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -688,7 +688,7 @@ int main() { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -975,7 +975,7 @@ int main() { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_generic_loop_uses_allocators_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_uses_allocators_codegen.cpp index 0dc2c95641e286d20a5a9ea38d8ee2cf83e82d94..5001f9cc89151139fe2ce9e5f29d2dfb5d94bc28 100644 --- a/clang/test/OpenMP/target_teams_generic_loop_uses_allocators_codegen.cpp +++ b/clang/test/OpenMP/target_teams_generic_loop_uses_allocators_codegen.cpp @@ -291,7 +291,7 @@ void foo() { // CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_map_codegen.cpp b/clang/test/OpenMP/target_teams_map_codegen.cpp index 9ccf74514691ba4c381de9e2bdedca608160feb3..974ba36e6bb0d622fd8954921f1766bedcaa824d 100644 --- a/clang/test/OpenMP/target_teams_map_codegen.cpp +++ b/clang/test/OpenMP/target_teams_map_codegen.cpp @@ -100,7 +100,7 @@ void mapInt128() { // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP8]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP9]], align 4 // CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -178,7 +178,7 @@ void mapInt128() { // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP8]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP9]], align 4 // CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -272,7 +272,7 @@ void mapInt128() { // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP8]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP9]], align 4 // CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -416,7 +416,7 @@ void mapInt128() { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -494,7 +494,7 @@ void mapInt128() { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -572,7 +572,7 @@ void mapInt128() { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -668,7 +668,7 @@ void mapInt128() { // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP11]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP11]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP12]], align 4 // CHECK1-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -721,7 +721,7 @@ void mapInt128() { // CHECK1-NEXT: [[TMP35:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK1-NEXT: [[TMP36:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK1-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP37]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK1-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP38]], align 4 // CHECK1-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 2 @@ -1031,7 +1031,7 @@ void mapInt128() { // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP11]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP11]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP12]], align 4 // CHECK1-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1084,7 +1084,7 @@ void mapInt128() { // CHECK1-NEXT: [[TMP35:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK1-NEXT: [[TMP36:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK1-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP37]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK1-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP38]], align 4 // CHECK1-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 2 @@ -1327,7 +1327,7 @@ void mapInt128() { // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP8]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP9]], align 4 // CHECK3-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1405,7 +1405,7 @@ void mapInt128() { // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP8]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP9]], align 4 // CHECK3-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1499,7 +1499,7 @@ void mapInt128() { // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP8]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP9]], align 4 // CHECK3-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1643,7 +1643,7 @@ void mapInt128() { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1721,7 +1721,7 @@ void mapInt128() { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1799,7 +1799,7 @@ void mapInt128() { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1895,7 +1895,7 @@ void mapInt128() { // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP10:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP11]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP11]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP12]], align 4 // CHECK3-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1948,7 +1948,7 @@ void mapInt128() { // CHECK3-NEXT: [[TMP35:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK3-NEXT: [[TMP36:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK3-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP37]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK3-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP38]], align 4 // CHECK3-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS4]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_num_teams_codegen.cpp b/clang/test/OpenMP/target_teams_num_teams_codegen.cpp index e5618aefaf3cbd2f83aa7952a308379cb4cc3b1c..ba01a411670ce5f68deb227798e214b086fadc54 100644 --- a/clang/test/OpenMP/target_teams_num_teams_codegen.cpp +++ b/clang/test/OpenMP/target_teams_num_teams_codegen.cpp @@ -256,7 +256,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 // CHECK1-NEXT: [[TMP18:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP17]], 0 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP19]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -298,7 +298,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP37:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP38:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP39]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP39]], align 4 // CHECK1-NEXT: [[TMP40:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP40]], align 4 // CHECK1-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -369,7 +369,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP8]], 0 // CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP10]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP10]], align 4 // CHECK1-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP11]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -418,7 +418,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP33:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 // CHECK1-NEXT: [[TMP34:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP33]], 0 // CHECK1-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP35]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP35]], align 4 // CHECK1-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP36]], align 4 // CHECK1-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -473,7 +473,7 @@ int bar(int n){ // CHECK1-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4 // CHECK1-NEXT: store i32 0, ptr [[A]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -541,7 +541,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP34:%.*]] = sext i16 [[TMP33]] to i32 // CHECK1-NEXT: [[TMP35:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP34]], 0 // CHECK1-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK1-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK1-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 2 @@ -834,7 +834,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP17]], 0 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP19]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -876,7 +876,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP37:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP38:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK3-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP39]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP39]], align 4 // CHECK3-NEXT: [[TMP40:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP40]], align 4 // CHECK3-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -947,7 +947,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP8]], 0 // CHECK3-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP10]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP10]], align 4 // CHECK3-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP11]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -996,7 +996,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP33:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4 // CHECK3-NEXT: [[TMP34:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP33]], 0 // CHECK3-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP35]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP35]], align 4 // CHECK3-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP36]], align 4 // CHECK3-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -1051,7 +1051,7 @@ int bar(int n){ // CHECK3-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4 // CHECK3-NEXT: store i32 0, ptr [[A]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1119,7 +1119,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP34:%.*]] = sext i16 [[TMP33]] to i32 // CHECK3-NEXT: [[TMP35:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP34]], 0 // CHECK3-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK3-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK3-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 2 diff --git a/clang/test/OpenMP/target_teams_thread_limit_codegen.cpp b/clang/test/OpenMP/target_teams_thread_limit_codegen.cpp index b6593b7e5368547409fc2a8b237c3b24a5a25c99..c081f6e52d7afb5bad5af898b9024e8c5a59e0fd 100644 --- a/clang/test/OpenMP/target_teams_thread_limit_codegen.cpp +++ b/clang/test/OpenMP/target_teams_thread_limit_codegen.cpp @@ -256,7 +256,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 // CHECK1-NEXT: [[TMP18:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP17]], 0 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP19]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -298,7 +298,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP37:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP38:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP39]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP39]], align 4 // CHECK1-NEXT: [[TMP40:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP40]], align 4 // CHECK1-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -385,7 +385,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP16:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP14]], 0 // CHECK1-NEXT: [[TMP17:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP15]], 0 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -434,7 +434,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP41:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_3]], align 4 // CHECK1-NEXT: [[TMP42:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP41]], 0 // CHECK1-NEXT: [[TMP43:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP43]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP43]], align 4 // CHECK1-NEXT: [[TMP44:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP44]], align 4 // CHECK1-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 2 @@ -489,7 +489,7 @@ int bar(int n){ // CHECK1-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4 // CHECK1-NEXT: store i32 0, ptr [[A]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -557,7 +557,7 @@ int bar(int n){ // CHECK1-NEXT: [[TMP34:%.*]] = sext i16 [[TMP33]] to i32 // CHECK1-NEXT: [[TMP35:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP34]], 0 // CHECK1-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK1-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK1-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 2 @@ -853,7 +853,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_]], align 4 // CHECK3-NEXT: [[TMP18:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP17]], 0 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP19]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -895,7 +895,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP37:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP38:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK3-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP39]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP39]], align 4 // CHECK3-NEXT: [[TMP40:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP40]], align 4 // CHECK3-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS6]], i32 0, i32 2 @@ -982,7 +982,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP16:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP14]], 0 // CHECK3-NEXT: [[TMP17:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP15]], 0 // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP19]], align 4 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1031,7 +1031,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP41:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_3]], align 4 // CHECK3-NEXT: [[TMP42:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP41]], 0 // CHECK3-NEXT: [[TMP43:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP43]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP43]], align 4 // CHECK3-NEXT: [[TMP44:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP44]], align 4 // CHECK3-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 2 @@ -1086,7 +1086,7 @@ int bar(int n){ // CHECK3-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4 // CHECK3-NEXT: store i32 0, ptr [[A]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1154,7 +1154,7 @@ int bar(int n){ // CHECK3-NEXT: [[TMP34:%.*]] = sext i16 [[TMP33]] to i32 // CHECK3-NEXT: [[TMP35:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP34]], 0 // CHECK3-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK3-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP37]], align 4 // CHECK3-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS1]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_codegen.cpp b/clang/test/OpenMP/teams_codegen.cpp index 4aab9dae2d6ad68ae0506d474685444f1aa89e5c..91702fb47af73f0c7065ef70d2cc5949b8bd813d 100644 --- a/clang/test/OpenMP/teams_codegen.cpp +++ b/clang/test/OpenMP/teams_codegen.cpp @@ -361,7 +361,7 @@ void foo() { // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -405,7 +405,7 @@ void foo() { // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0 // CHECK1-NEXT: [[TMP28:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK1-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP30]], align 4 // CHECK1-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -460,7 +460,7 @@ void foo() { // CHECK1-NEXT: [[TMP56:%.*]] = load i32, ptr [[LA]], align 4 // CHECK1-NEXT: [[TMP57:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP56]], 0 // CHECK1-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK1-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP59]], align 4 // CHECK1-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -515,7 +515,7 @@ void foo() { // CHECK1-NEXT: [[TMP85:%.*]] = load i32, ptr [[LA]], align 4 // CHECK1-NEXT: [[TMP86:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP85]], 0 // CHECK1-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS20]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP87]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP87]], align 4 // CHECK1-NEXT: [[TMP88:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS20]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP88]], align 4 // CHECK1-NEXT: [[TMP89:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS20]], i32 0, i32 2 @@ -605,7 +605,7 @@ void foo() { // CHECK1-NEXT: [[TMP134:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[ADD]], 0 // CHECK1-NEXT: [[TMP135:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP133]], 0 // CHECK1-NEXT: [[TMP136:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP136]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP136]], align 4 // CHECK1-NEXT: [[TMP137:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP137]], align 4 // CHECK1-NEXT: [[TMP138:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 2 @@ -670,7 +670,7 @@ void foo() { // CHECK1-NEXT: [[TMP168:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[ADD36]], 0 // CHECK1-NEXT: [[TMP169:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[ADD38]], 0 // CHECK1-NEXT: [[TMP170:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS39]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP170]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP170]], align 4 // CHECK1-NEXT: [[TMP171:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS39]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP171]], align 4 // CHECK1-NEXT: [[TMP172:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS39]], i32 0, i32 2 @@ -963,7 +963,7 @@ void foo() { // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1007,7 +1007,7 @@ void foo() { // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0 // CHECK3-NEXT: [[TMP28:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK3-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP30]], align 4 // CHECK3-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -1062,7 +1062,7 @@ void foo() { // CHECK3-NEXT: [[TMP56:%.*]] = load i32, ptr [[LA]], align 4 // CHECK3-NEXT: [[TMP57:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP56]], 0 // CHECK3-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK3-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP59]], align 4 // CHECK3-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -1117,7 +1117,7 @@ void foo() { // CHECK3-NEXT: [[TMP85:%.*]] = load i32, ptr [[LA]], align 4 // CHECK3-NEXT: [[TMP86:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP85]], 0 // CHECK3-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS20]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP87]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP87]], align 4 // CHECK3-NEXT: [[TMP88:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS20]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP88]], align 4 // CHECK3-NEXT: [[TMP89:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS20]], i32 0, i32 2 @@ -1204,7 +1204,7 @@ void foo() { // CHECK3-NEXT: [[TMP132:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[ADD]], 0 // CHECK3-NEXT: [[TMP133:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP131]], 0 // CHECK3-NEXT: [[TMP134:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP134]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP134]], align 4 // CHECK3-NEXT: [[TMP135:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP135]], align 4 // CHECK3-NEXT: [[TMP136:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS28]], i32 0, i32 2 @@ -1269,7 +1269,7 @@ void foo() { // CHECK3-NEXT: [[TMP166:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[ADD36]], 0 // CHECK3-NEXT: [[TMP167:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[ADD38]], 0 // CHECK3-NEXT: [[TMP168:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS39]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP168]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP168]], align 4 // CHECK3-NEXT: [[TMP169:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS39]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP169]], align 4 // CHECK3-NEXT: [[TMP170:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS39]], i32 0, i32 2 @@ -1552,7 +1552,7 @@ void foo() { // CHECK9-NEXT: [[TMP16:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP13]], 0 // CHECK9-NEXT: [[TMP17:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP15]], 0 // CHECK9-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK9-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK9-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1616,7 +1616,7 @@ void foo() { // CHECK9-NEXT: [[TMP50:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP47]], 0 // CHECK9-NEXT: [[TMP51:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP49]], 0 // CHECK9-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP52]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP52]], align 4 // CHECK9-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP53]], align 4 // CHECK9-NEXT: [[TMP54:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -1779,7 +1779,7 @@ void foo() { // CHECK11-NEXT: [[TMP16:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP13]], 0 // CHECK11-NEXT: [[TMP17:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP15]], 0 // CHECK11-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK11-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK11-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1843,7 +1843,7 @@ void foo() { // CHECK11-NEXT: [[TMP50:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP47]], 0 // CHECK11-NEXT: [[TMP51:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP49]], 0 // CHECK11-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP52]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP52]], align 4 // CHECK11-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP53]], align 4 // CHECK11-NEXT: [[TMP54:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -2006,7 +2006,7 @@ void foo() { // CHECK17-NEXT: [[TMP10:%.*]] = load i32, ptr [[A2]], align 4 // CHECK17-NEXT: [[TMP11:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP10]], 0 // CHECK17-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP12]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP12]], align 4 // CHECK17-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 2, ptr [[TMP13]], align 4 // CHECK17-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2062,7 +2062,7 @@ void foo() { // CHECK17-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV]], 123 // CHECK17-NEXT: [[TMP38:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[ADD]], 0 // CHECK17-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP39]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP39]], align 4 // CHECK17-NEXT: [[TMP40:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 1 // CHECK17-NEXT: store i32 2, ptr [[TMP40]], align 4 // CHECK17-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 2 @@ -2212,7 +2212,7 @@ void foo() { // CHECK19-NEXT: [[TMP10:%.*]] = load i32, ptr [[A2]], align 4 // CHECK19-NEXT: [[TMP11:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP10]], 0 // CHECK19-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP12]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP12]], align 4 // CHECK19-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 2, ptr [[TMP13]], align 4 // CHECK19-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2268,7 +2268,7 @@ void foo() { // CHECK19-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV]], 123 // CHECK19-NEXT: [[TMP38:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[ADD]], 0 // CHECK19-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP39]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP39]], align 4 // CHECK19-NEXT: [[TMP40:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 1 // CHECK19-NEXT: store i32 2, ptr [[TMP40]], align 4 // CHECK19-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS8]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_codegen.cpp b/clang/test/OpenMP/teams_distribute_codegen.cpp index 0bfadcf70d9bc3837a265b29f705889121ec3efd..11b5c9a212985cb809d35666e61e4b431cc90d20 100644 --- a/clang/test/OpenMP/teams_distribute_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_codegen.cpp @@ -254,7 +254,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP27:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP21]], 0 // CHECK1-NEXT: [[TMP28:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP22]], 0 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK1-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP30]], align 4 // CHECK1-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -314,7 +314,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK1-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK1-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK1-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP59]], align 4 // CHECK1-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -645,7 +645,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP27:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP21]], 0 // CHECK3-NEXT: [[TMP28:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP22]], 0 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK3-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP30]], align 4 // CHECK3-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -705,7 +705,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK3-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK3-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK3-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP59]], align 4 // CHECK3-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1016,7 +1016,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK9-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1226,7 +1226,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK11-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1403,7 +1403,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK17-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK17-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1548,7 +1548,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK19-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK19-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1730,7 +1730,7 @@ int main (int argc, char **argv) { // CHECK25-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK25-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK25-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK25-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK25-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK25-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK25-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK25-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1929,7 +1929,7 @@ int main (int argc, char **argv) { // CHECK25-NEXT: [[TMP17:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP15]], 0 // CHECK25-NEXT: [[TMP18:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP16]], 0 // CHECK25-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK25-NEXT: store i32 2, ptr [[TMP19]], align 4 +// CHECK25-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK25-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK25-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK25-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2116,7 +2116,7 @@ int main (int argc, char **argv) { // CHECK27-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK27-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK27-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK27-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK27-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK27-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK27-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK27-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2314,7 +2314,7 @@ int main (int argc, char **argv) { // CHECK27-NEXT: [[TMP17:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP15]], 0 // CHECK27-NEXT: [[TMP18:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP16]], 0 // CHECK27-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK27-NEXT: store i32 2, ptr [[TMP19]], align 4 +// CHECK27-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK27-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK27-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK27-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_collapse_codegen.cpp b/clang/test/OpenMP/teams_distribute_collapse_codegen.cpp index 178af730a8d4ae74a7d5bdd6746a477868ba6e3d..42b355f39e6b9eb08bbb65d6585a3908c71096fd 100644 --- a/clang/test/OpenMP/teams_distribute_collapse_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_collapse_codegen.cpp @@ -127,7 +127,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -288,7 +288,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -517,7 +517,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP35:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK9-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP35]], 1 // CHECK9-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK9-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP37]], align 4 // CHECK9-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -747,7 +747,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -972,7 +972,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP34:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK11-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP34]], 1 // CHECK11-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP35]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP35]], align 4 // CHECK11-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP36]], align 4 // CHECK11-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1200,7 +1200,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_dist_schedule_codegen.cpp b/clang/test/OpenMP/teams_distribute_dist_schedule_codegen.cpp index f21c7e9be9205ad2c6628669fbc254760a0172c3..39c260996fcbd2fa0eb696c1767e83b5debefaba 100644 --- a/clang/test/OpenMP/teams_distribute_dist_schedule_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_dist_schedule_codegen.cpp @@ -170,7 +170,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -212,7 +212,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -254,7 +254,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK1-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK1-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK1-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK1-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -582,7 +582,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -624,7 +624,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK3-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -666,7 +666,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK3-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK3-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK3-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK3-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1037,7 +1037,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK9-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1108,7 +1108,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK9-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK9-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK9-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK9-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1179,7 +1179,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD29:%.*]] = add nsw i32 [[TMP91]], 1 // CHECK9-NEXT: [[TMP92:%.*]] = zext i32 [[ADD29]] to i64 // CHECK9-NEXT: [[TMP93:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP93]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP93]], align 4 // CHECK9-NEXT: [[TMP94:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP94]], align 4 // CHECK9-NEXT: [[TMP95:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -1607,7 +1607,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1648,7 +1648,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -1689,7 +1689,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK9-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK9-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK9-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK9-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -2057,7 +2057,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK11-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2129,7 +2129,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP57]], 1 // CHECK11-NEXT: [[TMP58:%.*]] = zext i32 [[ADD14]] to i64 // CHECK11-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP59]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK11-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP60]], align 4 // CHECK11-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -2201,7 +2201,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD29:%.*]] = add nsw i32 [[TMP93]], 1 // CHECK11-NEXT: [[TMP94:%.*]] = zext i32 [[ADD29]] to i64 // CHECK11-NEXT: [[TMP95:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP95]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP95]], align 4 // CHECK11-NEXT: [[TMP96:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP96]], align 4 // CHECK11-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -2626,7 +2626,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2667,7 +2667,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -2708,7 +2708,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK11-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK11-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK11-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK11-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_firstprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_firstprivate_codegen.cpp index 57175e72b79f8a3473b507aff4010f86fabbccc7..8b3e657428ec64253c51669fe91f4a88e90e40af 100644 --- a/clang/test/OpenMP/teams_distribute_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_firstprivate_codegen.cpp @@ -306,7 +306,7 @@ int main() { // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP22]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -589,7 +589,7 @@ int main() { // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1110,7 +1110,7 @@ int main() { // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP22]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1391,7 +1391,7 @@ int main() { // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_lastprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_lastprivate_codegen.cpp index 5ee4a5ce9e29dca9f398114cc325947d44f95dcf..66c952f3281fb54e3f0454c3acef1f933df2b0c3 100644 --- a/clang/test/OpenMP/teams_distribute_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_lastprivate_codegen.cpp @@ -518,7 +518,7 @@ int main() { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -829,7 +829,7 @@ int main() { // CHECK9-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK9-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK9-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1214,7 +1214,7 @@ int main() { // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1523,7 +1523,7 @@ int main() { // CHECK11-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp index a13b565cb38d854ad66237cef295bda78948889c..85b20e9b21cfad1d68c48556f1d2a0c54b07bd56 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp @@ -254,7 +254,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP27:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP21]], 0 // CHECK1-NEXT: [[TMP28:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP22]], 0 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK1-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP30]], align 4 // CHECK1-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -314,7 +314,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK1-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK1-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK1-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP59]], align 4 // CHECK1-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -856,7 +856,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP27:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP21]], 0 // CHECK3-NEXT: [[TMP28:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP22]], 0 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK3-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP30]], align 4 // CHECK3-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -916,7 +916,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK3-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK3-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK3-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP59]], align 4 // CHECK3-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1430,7 +1430,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK9-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1741,7 +1741,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK11-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2015,7 +2015,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK17-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK17-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2233,7 +2233,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK19-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK19-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2484,7 +2484,7 @@ int main (int argc, char **argv) { // CHECK25-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK25-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK25-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK25-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK25-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK25-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK25-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK25-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2784,7 +2784,7 @@ int main (int argc, char **argv) { // CHECK25-NEXT: [[TMP17:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP15]], 0 // CHECK25-NEXT: [[TMP18:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP16]], 0 // CHECK25-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK25-NEXT: store i32 2, ptr [[TMP19]], align 4 +// CHECK25-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK25-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK25-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK25-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3044,7 +3044,7 @@ int main (int argc, char **argv) { // CHECK27-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK27-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK27-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK27-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK27-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK27-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK27-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK27-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3339,7 +3339,7 @@ int main (int argc, char **argv) { // CHECK27-NEXT: [[TMP17:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP15]], 0 // CHECK27-NEXT: [[TMP18:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP16]], 0 // CHECK27-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK27-NEXT: store i32 2, ptr [[TMP19]], align 4 +// CHECK27-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK27-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK27-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK27-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_collapse_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_collapse_codegen.cpp index 64ee660b706ccf1c5f3ee54c24a581ae11164798..f1c74bd6a0d792376cf67719ec418f01296e84e5 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_collapse_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_collapse_codegen.cpp @@ -132,7 +132,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -368,7 +368,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -668,7 +668,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP35:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK9-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP35]], 1 // CHECK9-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK9-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP37]], align 4 // CHECK9-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1018,7 +1018,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1318,7 +1318,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP34:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK11-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP34]], 1 // CHECK11-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP35]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP35]], align 4 // CHECK11-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP36]], align 4 // CHECK11-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1670,7 +1670,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_copyin_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_copyin_codegen.cpp index 37d19f86a9509ba7db7d99ae332f63dae029232e..2fda35f3e0009d1dfb75f48c2cb65f113b642355 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_copyin_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_copyin_codegen.cpp @@ -123,7 +123,7 @@ int main() { // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP11]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP11]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP12]], align 4 // CHECK1-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -347,7 +347,7 @@ int main() { // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP11]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP11]], align 4 // CHECK1-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP12]], align 4 // CHECK1-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -578,7 +578,7 @@ int main() { // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP11]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP11]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP12]], align 4 // CHECK3-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -797,7 +797,7 @@ int main() { // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP10:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP11]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP11]], align 4 // CHECK3-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP12]], align 4 // CHECK3-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_codegen.cpp index eb3d2fc84568ab92ebcd9eb7781c9ad6e2a596d5..070bb1ce3fed26321186b1e751c34938578b90fd 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_codegen.cpp @@ -182,7 +182,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -224,7 +224,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -266,7 +266,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK1-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK1-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK1-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK1-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -816,7 +816,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -858,7 +858,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK3-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -900,7 +900,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK3-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK3-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK3-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK3-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1484,7 +1484,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK9-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1555,7 +1555,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK9-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK9-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK9-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK9-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1635,7 +1635,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD29:%.*]] = add nsw i32 [[TMP96]], 1 // CHECK9-NEXT: [[TMP97:%.*]] = zext i32 [[ADD29]] to i64 // CHECK9-NEXT: [[TMP98:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP98]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP98]], align 4 // CHECK9-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP99]], align 4 // CHECK9-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -2384,7 +2384,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2425,7 +2425,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -2475,7 +2475,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP48:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK9-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK9-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP50]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP50]], align 4 // CHECK9-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK9-NEXT: store i32 2, ptr [[TMP51]], align 4 // CHECK9-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -3086,7 +3086,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK11-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3158,7 +3158,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP57]], 1 // CHECK11-NEXT: [[TMP58:%.*]] = zext i32 [[ADD14]] to i64 // CHECK11-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP59]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK11-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP60]], align 4 // CHECK11-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -3239,7 +3239,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD29:%.*]] = add nsw i32 [[TMP98]], 1 // CHECK11-NEXT: [[TMP99:%.*]] = zext i32 [[ADD29]] to i64 // CHECK11-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP100]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP100]], align 4 // CHECK11-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP101]], align 4 // CHECK11-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -3973,7 +3973,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4014,7 +4014,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -4064,7 +4064,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP48:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK11-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK11-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP50]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP50]], align 4 // CHECK11-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK11-NEXT: store i32 2, ptr [[TMP51]], align 4 // CHECK11-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 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 904e6a1c1ce7bb045a58ae3c7ad42c164e77cbae..0726fb659e7d15d990cf2157d43efd9ccf2e3ac6 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp @@ -340,7 +340,7 @@ int main() { // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP22]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -753,7 +753,7 @@ int main() { // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1404,7 +1404,7 @@ int main() { // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP22]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1811,7 +1811,7 @@ int main() { // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_if_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_if_codegen.cpp index 49ff6a5d08beed513035186f560fb30c700d3f73..aed27c47fa1d366a8d69eb7dd4f974499b04a6e1 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_if_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_if_codegen.cpp @@ -121,7 +121,7 @@ int main() { // CHECK1-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -154,7 +154,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -486,7 +486,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS7:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -519,7 +519,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -571,7 +571,7 @@ int main() { // CHECK1-NEXT: [[TMP39:%.*]] = select i1 [[TOBOOL5]], i32 0, i32 1 // CHECK1-NEXT: [[TMP40:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP39]], 0 // CHECK1-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP41]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP41]], align 4 // CHECK1-NEXT: [[TMP42:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP42]], align 4 // CHECK1-NEXT: [[TMP43:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -1073,7 +1073,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS7:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 [[ARG]], ptr [[ARG_ADDR]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1106,7 +1106,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -1158,7 +1158,7 @@ int main() { // CHECK1-NEXT: [[TMP39:%.*]] = select i1 [[TOBOOL5]], i32 0, i32 1 // CHECK1-NEXT: [[TMP40:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP39]], 0 // CHECK1-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP41]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP41]], align 4 // CHECK1-NEXT: [[TMP42:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP42]], align 4 // CHECK1-NEXT: [[TMP43:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp index 7b8df7367b828ff62e6ae478d8474c6a2b6c4279..06fc87d7da4c6c3c626293fa8fa5a735939b3b21 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp @@ -766,7 +766,7 @@ int main() { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1225,7 +1225,7 @@ int main() { // CHECK9-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK9-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK9-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1752,7 +1752,7 @@ int main() { // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2205,7 +2205,7 @@ int main() { // CHECK11-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp index a7b1f6eb309ee9e4891fc5c89c1329e814a37d59..6b200403637b6fe5ab3cb0b467bff134bae2ea5f 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp @@ -97,7 +97,7 @@ int main() { // CHECK1: invoke.cont: // CHECK1-NEXT: store i8 [[CALL]], ptr [[A]], align 1 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -155,7 +155,7 @@ int main() { // CHECK1-NEXT: [[TMP27:%.*]] = zext i8 [[TMP26]] to i32 // CHECK1-NEXT: [[TMP28:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP27]], 0 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK1-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP30]], align 4 // CHECK1-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -556,7 +556,7 @@ int main() { // CHECK1-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -589,7 +589,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -634,7 +634,7 @@ int main() { // CHECK1-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -676,7 +676,7 @@ int main() { // CHECK1-NEXT: [[TMP16:%.*]] = zext i8 [[TMP15]] to i32 // CHECK1-NEXT: [[TMP17:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP16]], 0 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -1384,7 +1384,7 @@ int main() { // CHECK5: invoke.cont: // CHECK5-NEXT: store i8 [[CALL]], ptr [[A]], align 1 // CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK5-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK5-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1442,7 +1442,7 @@ int main() { // CHECK5-NEXT: [[TMP27:%.*]] = zext i8 [[TMP26]] to i32 // CHECK5-NEXT: [[TMP28:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP27]], 0 // CHECK5-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK5-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP30]], align 4 // CHECK5-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -1843,7 +1843,7 @@ int main() { // CHECK5-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK5-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK5-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1876,7 +1876,7 @@ int main() { // CHECK5-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK5: omp_offload.cont: // CHECK5-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK5-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK5-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -1921,7 +1921,7 @@ int main() { // CHECK5-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK5-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK5-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1963,7 +1963,7 @@ int main() { // CHECK5-NEXT: [[TMP16:%.*]] = zext i8 [[TMP15]] to i32 // CHECK5-NEXT: [[TMP17:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP16]], 0 // CHECK5-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK5-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP19]], align 4 // CHECK5-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp index dc430fc55787c11f370ef715316199196ff2256f..4d10d16f47ed8716661415c52c45a663de983f5d 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp @@ -263,7 +263,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -533,7 +533,7 @@ int main() { // CHECK1-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 // CHECK1-NEXT: store ptr undef, ptr [[_TMP1]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -996,7 +996,7 @@ int main() { // CHECK3-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK3-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1260,7 +1260,7 @@ int main() { // CHECK3-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 // CHECK3-NEXT: store ptr undef, ptr [[_TMP1]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp index 386e772b78970f8843ea19d17def0ad5eca3241c..5e3962d96121cf683bb43efbf49e1aa34d81219a 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp @@ -60,7 +60,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -93,7 +93,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -411,7 +411,7 @@ int main() { // CHECK1-NEXT: [[TMP:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_reduction_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_reduction_codegen.cpp index 7ac42579e91b95e7fba950f92ed8d9a06d4be59d..2e800745baf2fb9566e29642c33125731aa6db78 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_reduction_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_reduction_codegen.cpp @@ -116,7 +116,7 @@ int main() { // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -410,7 +410,7 @@ int main() { // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -701,7 +701,7 @@ int main() { // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -991,7 +991,7 @@ int main() { // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_schedule_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_schedule_codegen.cpp index 7518179f477655773bbf95eafa4cbdbede186af8..2dd2302c0f2cf67acad57b4f01195a5c8cad3f75 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_schedule_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_schedule_codegen.cpp @@ -257,7 +257,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -299,7 +299,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -341,7 +341,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK1-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK1-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK1-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK1-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -383,7 +383,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP63:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 // CHECK1-NEXT: [[TMP64:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 // CHECK1-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK1-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP66]], align 4 // CHECK1-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -425,7 +425,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP83:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CHECK1-NEXT: [[TMP84:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CHECK1-NEXT: [[TMP85:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP85]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP85]], align 4 // CHECK1-NEXT: [[TMP86:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP86]], align 4 // CHECK1-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -1284,7 +1284,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1326,7 +1326,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK3-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -1368,7 +1368,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK3-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK3-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK3-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK3-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1410,7 +1410,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP63:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 // CHECK3-NEXT: [[TMP64:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 // CHECK3-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK3-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP66]], align 4 // CHECK3-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -1452,7 +1452,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP83:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CHECK3-NEXT: [[TMP84:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CHECK3-NEXT: [[TMP85:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP85]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP85]], align 4 // CHECK3-NEXT: [[TMP86:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP86]], align 4 // CHECK3-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -2284,7 +2284,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK5-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK5-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2326,7 +2326,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK5-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK5-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK5-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK5-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -2368,7 +2368,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK5-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK5-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK5-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK5-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -2410,7 +2410,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP63:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 // CHECK5-NEXT: [[TMP64:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 // CHECK5-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK5-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP66]], align 4 // CHECK5-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -2452,7 +2452,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP83:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CHECK5-NEXT: [[TMP84:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CHECK5-NEXT: [[TMP85:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP85]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP85]], align 4 // CHECK5-NEXT: [[TMP86:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP86]], align 4 // CHECK5-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -3311,7 +3311,7 @@ int main (int argc, char **argv) { // CHECK7-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK7-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK7-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK7-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK7-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3353,7 +3353,7 @@ int main (int argc, char **argv) { // CHECK7-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK7-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK7-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK7-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK7-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK7-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -3395,7 +3395,7 @@ int main (int argc, char **argv) { // CHECK7-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK7-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK7-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK7-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK7-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK7-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -3437,7 +3437,7 @@ int main (int argc, char **argv) { // CHECK7-NEXT: [[TMP63:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 // CHECK7-NEXT: [[TMP64:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 // CHECK7-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK7-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CHECK7-NEXT: store i32 1, ptr [[TMP66]], align 4 // CHECK7-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -3479,7 +3479,7 @@ int main (int argc, char **argv) { // CHECK7-NEXT: [[TMP83:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CHECK7-NEXT: [[TMP84:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CHECK7-NEXT: [[TMP85:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK7-NEXT: store i32 2, ptr [[TMP85]], align 4 +// CHECK7-NEXT: store i32 3, ptr [[TMP85]], align 4 // CHECK7-NEXT: [[TMP86:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK7-NEXT: store i32 1, ptr [[TMP86]], align 4 // CHECK7-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -4369,7 +4369,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK13-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK13-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK13-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK13-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK13-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4440,7 +4440,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK13-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK13-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK13-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK13-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK13-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -4520,7 +4520,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD29:%.*]] = add nsw i32 [[TMP96]], 1 // CHECK13-NEXT: [[TMP97:%.*]] = zext i32 [[ADD29]] to i64 // CHECK13-NEXT: [[TMP98:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP98]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP98]], align 4 // CHECK13-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CHECK13-NEXT: store i32 4, ptr [[TMP99]], align 4 // CHECK13-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -4591,7 +4591,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD44:%.*]] = add nsw i32 [[TMP131]], 1 // CHECK13-NEXT: [[TMP132:%.*]] = zext i32 [[ADD44]] to i64 // CHECK13-NEXT: [[TMP133:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP133]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP133]], align 4 // CHECK13-NEXT: [[TMP134:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 1 // CHECK13-NEXT: store i32 3, ptr [[TMP134]], align 4 // CHECK13-NEXT: [[TMP135:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 2 @@ -4671,7 +4671,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD60:%.*]] = add nsw i32 [[TMP171]], 1 // CHECK13-NEXT: [[TMP172:%.*]] = zext i32 [[ADD60]] to i64 // CHECK13-NEXT: [[TMP173:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP173]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP173]], align 4 // CHECK13-NEXT: [[TMP174:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 1 // CHECK13-NEXT: store i32 4, ptr [[TMP174]], align 4 // CHECK13-NEXT: [[TMP175:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 2 @@ -5863,7 +5863,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK13-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK13-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK13-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK13-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK13-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5904,7 +5904,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK13-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK13-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK13-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK13-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK13-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -5954,7 +5954,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP48:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK13-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK13-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP50]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP50]], align 4 // CHECK13-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK13-NEXT: store i32 2, ptr [[TMP51]], align 4 // CHECK13-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -5995,7 +5995,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP68:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK13-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK13-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP70]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP70]], align 4 // CHECK13-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK13-NEXT: store i32 1, ptr [[TMP71]], align 4 // CHECK13-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -6045,7 +6045,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP93:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0 // CHECK13-NEXT: [[TMP94:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0 // CHECK13-NEXT: [[TMP95:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP95]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP95]], align 4 // CHECK13-NEXT: [[TMP96:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 1 // CHECK13-NEXT: store i32 2, ptr [[TMP96]], align 4 // CHECK13-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 2 @@ -6990,7 +6990,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK15-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK15-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK15-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK15-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK15-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -7062,7 +7062,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP57]], 1 // CHECK15-NEXT: [[TMP58:%.*]] = zext i32 [[ADD14]] to i64 // CHECK15-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP59]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK15-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK15-NEXT: store i32 3, ptr [[TMP60]], align 4 // CHECK15-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -7143,7 +7143,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[ADD29:%.*]] = add nsw i32 [[TMP98]], 1 // CHECK15-NEXT: [[TMP99:%.*]] = zext i32 [[ADD29]] to i64 // CHECK15-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP100]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP100]], align 4 // CHECK15-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CHECK15-NEXT: store i32 4, ptr [[TMP101]], align 4 // CHECK15-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -7215,7 +7215,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[ADD44:%.*]] = add nsw i32 [[TMP134]], 1 // CHECK15-NEXT: [[TMP135:%.*]] = zext i32 [[ADD44]] to i64 // CHECK15-NEXT: [[TMP136:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP136]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP136]], align 4 // CHECK15-NEXT: [[TMP137:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 1 // CHECK15-NEXT: store i32 3, ptr [[TMP137]], align 4 // CHECK15-NEXT: [[TMP138:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 2 @@ -7296,7 +7296,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[ADD60:%.*]] = add nsw i32 [[TMP175]], 1 // CHECK15-NEXT: [[TMP176:%.*]] = zext i32 [[ADD60]] to i64 // CHECK15-NEXT: [[TMP177:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP177]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP177]], align 4 // CHECK15-NEXT: [[TMP178:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 1 // CHECK15-NEXT: store i32 4, ptr [[TMP178]], align 4 // CHECK15-NEXT: [[TMP179:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 2 @@ -8463,7 +8463,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK15-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK15-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK15-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK15-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK15-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -8504,7 +8504,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK15-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK15-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK15-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK15-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK15-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -8554,7 +8554,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[TMP48:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK15-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK15-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP50]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP50]], align 4 // CHECK15-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK15-NEXT: store i32 2, ptr [[TMP51]], align 4 // CHECK15-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -8595,7 +8595,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[TMP68:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK15-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK15-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP70]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP70]], align 4 // CHECK15-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK15-NEXT: store i32 1, ptr [[TMP71]], align 4 // CHECK15-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -8645,7 +8645,7 @@ int main (int argc, char **argv) { // CHECK15-NEXT: [[TMP93:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0 // CHECK15-NEXT: [[TMP94:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0 // CHECK15-NEXT: [[TMP95:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 0 -// CHECK15-NEXT: store i32 2, ptr [[TMP95]], align 4 +// CHECK15-NEXT: store i32 3, ptr [[TMP95]], align 4 // CHECK15-NEXT: [[TMP96:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 1 // CHECK15-NEXT: store i32 2, ptr [[TMP96]], align 4 // CHECK15-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 2 @@ -9563,7 +9563,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK17-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK17-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK17-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK17-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -9634,7 +9634,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK17-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK17-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK17-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK17-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK17-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -9714,7 +9714,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD29:%.*]] = add nsw i32 [[TMP96]], 1 // CHECK17-NEXT: [[TMP97:%.*]] = zext i32 [[ADD29]] to i64 // CHECK17-NEXT: [[TMP98:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP98]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP98]], align 4 // CHECK17-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CHECK17-NEXT: store i32 4, ptr [[TMP99]], align 4 // CHECK17-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -9785,7 +9785,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD44:%.*]] = add nsw i32 [[TMP131]], 1 // CHECK17-NEXT: [[TMP132:%.*]] = zext i32 [[ADD44]] to i64 // CHECK17-NEXT: [[TMP133:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP133]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP133]], align 4 // CHECK17-NEXT: [[TMP134:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 1 // CHECK17-NEXT: store i32 3, ptr [[TMP134]], align 4 // CHECK17-NEXT: [[TMP135:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 2 @@ -9865,7 +9865,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD60:%.*]] = add nsw i32 [[TMP171]], 1 // CHECK17-NEXT: [[TMP172:%.*]] = zext i32 [[ADD60]] to i64 // CHECK17-NEXT: [[TMP173:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP173]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP173]], align 4 // CHECK17-NEXT: [[TMP174:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 1 // CHECK17-NEXT: store i32 4, ptr [[TMP174]], align 4 // CHECK17-NEXT: [[TMP175:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 2 @@ -11057,7 +11057,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK17-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK17-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -11098,7 +11098,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK17-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK17-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK17-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK17-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK17-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -11148,7 +11148,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP48:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK17-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK17-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP50]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP50]], align 4 // CHECK17-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK17-NEXT: store i32 2, ptr [[TMP51]], align 4 // CHECK17-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -11189,7 +11189,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP68:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK17-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK17-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP70]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP70]], align 4 // CHECK17-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK17-NEXT: store i32 1, ptr [[TMP71]], align 4 // CHECK17-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -11239,7 +11239,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP93:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0 // CHECK17-NEXT: [[TMP94:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0 // CHECK17-NEXT: [[TMP95:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP95]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP95]], align 4 // CHECK17-NEXT: [[TMP96:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 1 // CHECK17-NEXT: store i32 2, ptr [[TMP96]], align 4 // CHECK17-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 2 @@ -12184,7 +12184,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK19-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK19-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK19-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK19-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -12256,7 +12256,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP57]], 1 // CHECK19-NEXT: [[TMP58:%.*]] = zext i32 [[ADD14]] to i64 // CHECK19-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP59]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK19-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK19-NEXT: store i32 3, ptr [[TMP60]], align 4 // CHECK19-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -12337,7 +12337,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD29:%.*]] = add nsw i32 [[TMP98]], 1 // CHECK19-NEXT: [[TMP99:%.*]] = zext i32 [[ADD29]] to i64 // CHECK19-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP100]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP100]], align 4 // CHECK19-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CHECK19-NEXT: store i32 4, ptr [[TMP101]], align 4 // CHECK19-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -12409,7 +12409,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD44:%.*]] = add nsw i32 [[TMP134]], 1 // CHECK19-NEXT: [[TMP135:%.*]] = zext i32 [[ADD44]] to i64 // CHECK19-NEXT: [[TMP136:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP136]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP136]], align 4 // CHECK19-NEXT: [[TMP137:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 1 // CHECK19-NEXT: store i32 3, ptr [[TMP137]], align 4 // CHECK19-NEXT: [[TMP138:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 2 @@ -12490,7 +12490,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD60:%.*]] = add nsw i32 [[TMP175]], 1 // CHECK19-NEXT: [[TMP176:%.*]] = zext i32 [[ADD60]] to i64 // CHECK19-NEXT: [[TMP177:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP177]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP177]], align 4 // CHECK19-NEXT: [[TMP178:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 1 // CHECK19-NEXT: store i32 4, ptr [[TMP178]], align 4 // CHECK19-NEXT: [[TMP179:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 2 @@ -13657,7 +13657,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK19-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK19-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -13698,7 +13698,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK19-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK19-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK19-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK19-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK19-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -13748,7 +13748,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP48:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK19-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK19-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP50]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP50]], align 4 // CHECK19-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK19-NEXT: store i32 2, ptr [[TMP51]], align 4 // CHECK19-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -13789,7 +13789,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP68:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK19-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK19-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP70]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP70]], align 4 // CHECK19-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK19-NEXT: store i32 1, ptr [[TMP71]], align 4 // CHECK19-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -13839,7 +13839,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP93:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0 // CHECK19-NEXT: [[TMP94:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0 // CHECK19-NEXT: [[TMP95:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP95]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP95]], align 4 // CHECK19-NEXT: [[TMP96:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 1 // CHECK19-NEXT: store i32 2, ptr [[TMP96]], align 4 // CHECK19-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp index 854afe3b9bbc827e217ee9eed8992092e21c8e4c..0a492152e9e01af8f3a2f81e646e13aaf3a09bc2 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp @@ -262,7 +262,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP27:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP21]], 0 // CHECK1-NEXT: [[TMP28:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP22]], 0 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK1-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP30]], align 4 // CHECK1-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -331,7 +331,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP61]], 1 // CHECK1-NEXT: [[TMP62:%.*]] = zext i32 [[ADD14]] to i64 // CHECK1-NEXT: [[TMP63:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP63]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP63]], align 4 // CHECK1-NEXT: [[TMP64:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK1-NEXT: store i32 3, ptr [[TMP64]], align 4 // CHECK1-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -933,7 +933,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP27:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP21]], 0 // CHECK3-NEXT: [[TMP28:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP22]], 0 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK3-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP30]], align 4 // CHECK3-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1002,7 +1002,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP61]], 1 // CHECK3-NEXT: [[TMP62:%.*]] = zext i32 [[ADD14]] to i64 // CHECK3-NEXT: [[TMP63:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP63]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP63]], align 4 // CHECK3-NEXT: [[TMP64:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK3-NEXT: store i32 3, ptr [[TMP64]], align 4 // CHECK3-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1853,7 +1853,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP26]], 1 // CHECK9-NEXT: [[TMP27:%.*]] = zext i32 [[ADD]] to i64 // CHECK9-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK9-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP29]], align 4 // CHECK9-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2222,7 +2222,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP26]], 1 // CHECK11-NEXT: [[TMP27:%.*]] = zext i32 [[ADD]] to i64 // CHECK11-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK11-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP29]], align 4 // CHECK11-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2718,7 +2718,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP10]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP10]], align 4 // CHECK17-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 2, ptr [[TMP11]], align 4 // CHECK17-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2986,7 +2986,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP8:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP9:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP10]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP10]], align 4 // CHECK19-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 2, ptr [[TMP11]], align 4 // CHECK19-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3412,7 +3412,7 @@ int main (int argc, char **argv) { // CHECK25-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP26]], 1 // CHECK25-NEXT: [[TMP27:%.*]] = zext i32 [[ADD]] to i64 // CHECK25-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK25-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK25-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK25-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK25-NEXT: store i32 4, ptr [[TMP29]], align 4 // CHECK25-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3759,7 +3759,7 @@ int main (int argc, char **argv) { // CHECK25-NEXT: [[TMP17:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP15]], 0 // CHECK25-NEXT: [[TMP18:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP16]], 0 // CHECK25-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK25-NEXT: store i32 2, ptr [[TMP19]], align 4 +// CHECK25-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK25-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK25-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK25-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4044,7 +4044,7 @@ int main (int argc, char **argv) { // CHECK27-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP26]], 1 // CHECK27-NEXT: [[TMP27:%.*]] = zext i32 [[ADD]] to i64 // CHECK27-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK27-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK27-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK27-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK27-NEXT: store i32 4, ptr [[TMP29]], align 4 // CHECK27-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4386,7 +4386,7 @@ int main (int argc, char **argv) { // CHECK27-NEXT: [[TMP17:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP15]], 0 // CHECK27-NEXT: [[TMP18:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP16]], 0 // CHECK27-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK27-NEXT: store i32 2, ptr [[TMP19]], align 4 +// CHECK27-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK27-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK27-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK27-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_collapse_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_collapse_codegen.cpp index e7b9978dd43cd81d2298a03927affddc2a861357..910805c3107457085ee1ec21d19fbe5e72def430 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_collapse_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_collapse_codegen.cpp @@ -137,7 +137,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -389,7 +389,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -845,7 +845,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP35:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK9-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP35]], 1 // CHECK9-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK9-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP37]], align 4 // CHECK9-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1231,7 +1231,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1547,7 +1547,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP34:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK11-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP34]], 1 // CHECK11-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP35]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP35]], align 4 // CHECK11-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP36]], align 4 // CHECK11-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1935,7 +1935,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp index d3777e81047ca0bdfae179d438146458532745a2..aa6d6c67c20f1cbf714983c2d9a300e8517c2adf 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp @@ -185,7 +185,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -227,7 +227,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -269,7 +269,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK1-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK1-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK1-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK1-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -861,7 +861,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -903,7 +903,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK3-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -945,7 +945,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK3-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK3-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK3-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK3-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1818,7 +1818,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK9-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1889,7 +1889,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK9-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK9-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK9-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK9-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1969,7 +1969,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD29:%.*]] = add nsw i32 [[TMP96]], 1 // CHECK9-NEXT: [[TMP97:%.*]] = zext i32 [[ADD29]] to i64 // CHECK9-NEXT: [[TMP98:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP98]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP98]], align 4 // CHECK9-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP99]], align 4 // CHECK9-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -2790,7 +2790,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2831,7 +2831,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -2881,7 +2881,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP48:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK9-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK9-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP50]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP50]], align 4 // CHECK9-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK9-NEXT: store i32 2, ptr [[TMP51]], align 4 // CHECK9-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -3534,7 +3534,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK11-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3606,7 +3606,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP57]], 1 // CHECK11-NEXT: [[TMP58:%.*]] = zext i32 [[ADD14]] to i64 // CHECK11-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP59]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK11-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP60]], align 4 // CHECK11-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -3687,7 +3687,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD29:%.*]] = add nsw i32 [[TMP98]], 1 // CHECK11-NEXT: [[TMP99:%.*]] = zext i32 [[ADD29]] to i64 // CHECK11-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP100]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP100]], align 4 // CHECK11-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP101]], align 4 // CHECK11-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -4493,7 +4493,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4534,7 +4534,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -4584,7 +4584,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP48:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK11-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK11-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP50]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP50]], align 4 // CHECK11-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK11-NEXT: store i32 2, ptr [[TMP51]], align 4 // CHECK11-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp index 4f87d40e58f683f1a572d61289d7052fff795d3a..7d9e2ab89676f689576d3084493a5d1aa54bd0c7 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp @@ -343,7 +343,7 @@ int main() { // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP22]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -770,7 +770,7 @@ int main() { // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1435,7 +1435,7 @@ int main() { // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP22]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1856,7 +1856,7 @@ int main() { // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_if_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_if_codegen.cpp index 7c86b180ec674bd347fc090086ee42536fe8cf7f..58c1f4155abfbb36597363b6a2ce91bee572bd66 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_if_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_if_codegen.cpp @@ -118,7 +118,7 @@ int main() { // CHECK1-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -151,7 +151,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -511,7 +511,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS7:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -544,7 +544,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -596,7 +596,7 @@ int main() { // CHECK1-NEXT: [[TMP39:%.*]] = select i1 [[TOBOOL5]], i32 0, i32 1 // CHECK1-NEXT: [[TMP40:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP39]], 0 // CHECK1-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP41]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP41]], align 4 // CHECK1-NEXT: [[TMP42:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP42]], align 4 // CHECK1-NEXT: [[TMP43:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -1140,7 +1140,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS7:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 [[ARG]], ptr [[ARG_ADDR]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1173,7 +1173,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -1225,7 +1225,7 @@ int main() { // CHECK1-NEXT: [[TMP39:%.*]] = select i1 [[TOBOOL5]], i32 0, i32 1 // CHECK1-NEXT: [[TMP40:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP39]], 0 // CHECK1-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP41]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP41]], align 4 // CHECK1-NEXT: [[TMP42:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP42]], align 4 // CHECK1-NEXT: [[TMP43:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -1758,7 +1758,7 @@ int main() { // CHECK3-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK3-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1791,7 +1791,7 @@ int main() { // CHECK3-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK3: omp_offload.cont: // CHECK3-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -2151,7 +2151,7 @@ int main() { // CHECK3-NEXT: [[KERNEL_ARGS7:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK3-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2184,7 +2184,7 @@ int main() { // CHECK3-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK3: omp_offload.cont: // CHECK3-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -2236,7 +2236,7 @@ int main() { // CHECK3-NEXT: [[TMP39:%.*]] = select i1 [[TOBOOL5]], i32 0, i32 1 // CHECK3-NEXT: [[TMP40:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP39]], 0 // CHECK3-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP41]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP41]], align 4 // CHECK3-NEXT: [[TMP42:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP42]], align 4 // CHECK3-NEXT: [[TMP43:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -3010,7 +3010,7 @@ int main() { // CHECK3-NEXT: [[KERNEL_ARGS7:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK3-NEXT: store i32 [[ARG]], ptr [[ARG_ADDR]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3043,7 +3043,7 @@ int main() { // CHECK3-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK3: omp_offload.cont: // CHECK3-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK3-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK3-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -3095,7 +3095,7 @@ int main() { // CHECK3-NEXT: [[TMP39:%.*]] = select i1 [[TOBOOL5]], i32 0, i32 1 // CHECK3-NEXT: [[TMP40:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP39]], 0 // CHECK3-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP41]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP41]], align 4 // CHECK3-NEXT: [[TMP42:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP42]], align 4 // CHECK3-NEXT: [[TMP43:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -4219,7 +4219,7 @@ int main() { // CHECK9-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK9-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4252,7 +4252,7 @@ int main() { // CHECK9-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK9: omp_offload.cont: // CHECK9-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK9-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -4612,7 +4612,7 @@ int main() { // CHECK9-NEXT: [[KERNEL_ARGS7:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK9-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4645,7 +4645,7 @@ int main() { // CHECK9-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK9: omp_offload.cont: // CHECK9-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK9-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -4697,7 +4697,7 @@ int main() { // CHECK9-NEXT: [[TMP39:%.*]] = select i1 [[TOBOOL5]], i32 0, i32 1 // CHECK9-NEXT: [[TMP40:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP39]], 0 // CHECK9-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP41]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP41]], align 4 // CHECK9-NEXT: [[TMP42:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP42]], align 4 // CHECK9-NEXT: [[TMP43:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -5241,7 +5241,7 @@ int main() { // CHECK9-NEXT: [[KERNEL_ARGS7:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK9-NEXT: store i32 [[ARG]], ptr [[ARG_ADDR]], align 4 // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5274,7 +5274,7 @@ int main() { // CHECK9-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK9: omp_offload.cont: // CHECK9-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK9-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -5326,7 +5326,7 @@ int main() { // CHECK9-NEXT: [[TMP39:%.*]] = select i1 [[TOBOOL5]], i32 0, i32 1 // CHECK9-NEXT: [[TMP40:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP39]], 0 // CHECK9-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP41]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP41]], align 4 // CHECK9-NEXT: [[TMP42:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP42]], align 4 // CHECK9-NEXT: [[TMP43:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -5859,7 +5859,7 @@ int main() { // CHECK11-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK11-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5892,7 +5892,7 @@ int main() { // CHECK11-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK11: omp_offload.cont: // CHECK11-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK11-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK11-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -6252,7 +6252,7 @@ int main() { // CHECK11-NEXT: [[KERNEL_ARGS7:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK11-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -6285,7 +6285,7 @@ int main() { // CHECK11-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK11: omp_offload.cont: // CHECK11-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK11-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK11-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -6337,7 +6337,7 @@ int main() { // CHECK11-NEXT: [[TMP39:%.*]] = select i1 [[TOBOOL5]], i32 0, i32 1 // CHECK11-NEXT: [[TMP40:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP39]], 0 // CHECK11-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP41]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP41]], align 4 // CHECK11-NEXT: [[TMP42:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP42]], align 4 // CHECK11-NEXT: [[TMP43:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -7111,7 +7111,7 @@ int main() { // CHECK11-NEXT: [[KERNEL_ARGS7:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK11-NEXT: store i32 [[ARG]], ptr [[ARG_ADDR]], align 4 // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -7144,7 +7144,7 @@ int main() { // CHECK11-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK11: omp_offload.cont: // CHECK11-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK11-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK11-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -7196,7 +7196,7 @@ int main() { // CHECK11-NEXT: [[TMP39:%.*]] = select i1 [[TOBOOL5]], i32 0, i32 1 // CHECK11-NEXT: [[TMP40:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP39]], 0 // CHECK11-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP41]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP41]], align 4 // CHECK11-NEXT: [[TMP42:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP42]], align 4 // CHECK11-NEXT: [[TMP43:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp index 268298c14801cdd6ab3b2e78f4fb9339a3533a0a..8643cb9bb84a8bd8ac3ba2c562cfbcfe6c7430c8 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp @@ -839,7 +839,7 @@ int main() { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1312,7 +1312,7 @@ int main() { // CHECK9-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK9-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK9-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1853,7 +1853,7 @@ int main() { // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2320,7 +2320,7 @@ int main() { // CHECK11-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp index fa8bcf65b8fb63d87dd582a92d43c8c714a1f271..47d067256fb3a96c034fe71e8cd6a81cb9f24597 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp @@ -99,7 +99,7 @@ int main() { // CHECK1: invoke.cont: // CHECK1-NEXT: store i8 [[CALL]], ptr [[A]], align 1 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -157,7 +157,7 @@ int main() { // CHECK1-NEXT: [[TMP27:%.*]] = zext i8 [[TMP26]] to i32 // CHECK1-NEXT: [[TMP28:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP27]], 0 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK1-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP30]], align 4 // CHECK1-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -586,7 +586,7 @@ int main() { // CHECK1-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -619,7 +619,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -664,7 +664,7 @@ int main() { // CHECK1-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -706,7 +706,7 @@ int main() { // CHECK1-NEXT: [[TMP16:%.*]] = zext i8 [[TMP15]] to i32 // CHECK1-NEXT: [[TMP17:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP16]], 0 // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP19]], align 4 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -1819,7 +1819,7 @@ int main() { // CHECK5: invoke.cont: // CHECK5-NEXT: store i8 [[CALL]], ptr [[A]], align 1 // CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK5-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK5-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1877,7 +1877,7 @@ int main() { // CHECK5-NEXT: [[TMP27:%.*]] = zext i8 [[TMP26]] to i32 // CHECK5-NEXT: [[TMP28:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP27]], 0 // CHECK5-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK5-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP30]], align 4 // CHECK5-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -2306,7 +2306,7 @@ int main() { // CHECK5-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK5-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK5-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2339,7 +2339,7 @@ int main() { // CHECK5-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK5: omp_offload.cont: // CHECK5-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK5-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK5-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -2384,7 +2384,7 @@ int main() { // CHECK5-NEXT: [[_TMP1:%.*]] = alloca i32, align 4 // CHECK5-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK5-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK5-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2426,7 +2426,7 @@ int main() { // CHECK5-NEXT: [[TMP16:%.*]] = zext i8 [[TMP15]] to i32 // CHECK5-NEXT: [[TMP17:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP16]], 0 // CHECK5-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK5-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK5-NEXT: store i32 0, ptr [[TMP19]], align 4 // CHECK5-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp index 03bee1dbb63c099b9374580b580eb3cf07705807..f40acb42f9dae46b935242d75278471a760f1223 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp @@ -265,7 +265,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -549,7 +549,7 @@ int main() { // CHECK1-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 // CHECK1-NEXT: store ptr undef, ptr [[_TMP1]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1026,7 +1026,7 @@ int main() { // CHECK3-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK3-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1304,7 +1304,7 @@ int main() { // CHECK3-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 // CHECK3-NEXT: store ptr undef, ptr [[_TMP1]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp index 7d35ea305f92b57c9d323223780c46baaf2a6c28..c473e8532189b14c077662f7c2993b15abb76ca9 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp @@ -62,7 +62,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS2:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -95,7 +95,7 @@ int main() { // CHECK1-NEXT: br label [[OMP_OFFLOAD_CONT]] // CHECK1: omp_offload.cont: // CHECK1-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP15]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP15]], align 4 // CHECK1-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP16]], align 4 // CHECK1-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS2]], i32 0, i32 2 @@ -441,7 +441,7 @@ int main() { // CHECK1-NEXT: [[TMP:%.*]] = alloca i32, align 4 // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_reduction_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_reduction_codegen.cpp index 2dd1db48f0306bee4bc912e3d2e1115152eed1b2..669ca4a6b76ecefdd7481a41ef8833e902345286 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_reduction_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_reduction_codegen.cpp @@ -120,7 +120,7 @@ int main() { // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -428,7 +428,7 @@ int main() { // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -733,7 +733,7 @@ int main() { // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1037,7 +1037,7 @@ int main() { // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_schedule_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_schedule_codegen.cpp index ff70e71e0126739ce20d354fef168413432c623e..3d40ac12e5ec623b4590271fdc596ed98c11463e 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_schedule_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_schedule_codegen.cpp @@ -267,7 +267,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -309,7 +309,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -351,7 +351,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK1-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK1-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK1-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK1-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -393,7 +393,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP63:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 // CHECK1-NEXT: [[TMP64:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 // CHECK1-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK1-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP66]], align 4 // CHECK1-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -435,7 +435,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP83:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CHECK1-NEXT: [[TMP84:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CHECK1-NEXT: [[TMP85:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP85]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP85]], align 4 // CHECK1-NEXT: [[TMP86:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP86]], align 4 // CHECK1-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -1364,7 +1364,7 @@ int main (int argc, char **argv) { // CHECK2-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK2-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK2-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK2-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK2-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK2-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1406,7 +1406,7 @@ int main (int argc, char **argv) { // CHECK2-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK2-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK2-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK2-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK2-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK2-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -1448,7 +1448,7 @@ int main (int argc, char **argv) { // CHECK2-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK2-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK2-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK2-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK2-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK2-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1490,7 +1490,7 @@ int main (int argc, char **argv) { // CHECK2-NEXT: [[TMP63:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 // CHECK2-NEXT: [[TMP64:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 // CHECK2-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK2-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CHECK2-NEXT: store i32 1, ptr [[TMP66]], align 4 // CHECK2-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -1532,7 +1532,7 @@ int main (int argc, char **argv) { // CHECK2-NEXT: [[TMP83:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CHECK2-NEXT: [[TMP84:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CHECK2-NEXT: [[TMP85:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK2-NEXT: store i32 2, ptr [[TMP85]], align 4 +// CHECK2-NEXT: store i32 3, ptr [[TMP85]], align 4 // CHECK2-NEXT: [[TMP86:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK2-NEXT: store i32 1, ptr [[TMP86]], align 4 // CHECK2-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -2461,7 +2461,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK5-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK5-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK5-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2503,7 +2503,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK5-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK5-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK5-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK5-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -2545,7 +2545,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK5-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK5-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK5-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK5-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -2587,7 +2587,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP63:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 // CHECK5-NEXT: [[TMP64:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 // CHECK5-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK5-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP66]], align 4 // CHECK5-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -2629,7 +2629,7 @@ int main (int argc, char **argv) { // CHECK5-NEXT: [[TMP83:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CHECK5-NEXT: [[TMP84:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CHECK5-NEXT: [[TMP85:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK5-NEXT: store i32 2, ptr [[TMP85]], align 4 +// CHECK5-NEXT: store i32 3, ptr [[TMP85]], align 4 // CHECK5-NEXT: [[TMP86:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK5-NEXT: store i32 1, ptr [[TMP86]], align 4 // CHECK5-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -3531,7 +3531,7 @@ int main (int argc, char **argv) { // CHECK6-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK6-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK6-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK6-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK6-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK6-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK6-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK6-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3573,7 +3573,7 @@ int main (int argc, char **argv) { // CHECK6-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK6-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK6-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK6-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK6-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK6-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK6-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK6-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -3615,7 +3615,7 @@ int main (int argc, char **argv) { // CHECK6-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK6-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK6-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK6-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK6-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK6-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK6-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK6-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -3657,7 +3657,7 @@ int main (int argc, char **argv) { // CHECK6-NEXT: [[TMP63:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS19]], i32 0, i32 0 // CHECK6-NEXT: [[TMP64:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS20]], i32 0, i32 0 // CHECK6-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 0 -// CHECK6-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK6-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK6-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 1 // CHECK6-NEXT: store i32 1, ptr [[TMP66]], align 4 // CHECK6-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS23]], i32 0, i32 2 @@ -3699,7 +3699,7 @@ int main (int argc, char **argv) { // CHECK6-NEXT: [[TMP83:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS27]], i32 0, i32 0 // CHECK6-NEXT: [[TMP84:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS28]], i32 0, i32 0 // CHECK6-NEXT: [[TMP85:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 0 -// CHECK6-NEXT: store i32 2, ptr [[TMP85]], align 4 +// CHECK6-NEXT: store i32 3, ptr [[TMP85]], align 4 // CHECK6-NEXT: [[TMP86:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 1 // CHECK6-NEXT: store i32 1, ptr [[TMP86]], align 4 // CHECK6-NEXT: [[TMP87:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS31]], i32 0, i32 2 @@ -5044,7 +5044,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK13-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK13-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK13-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK13-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK13-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -5115,7 +5115,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK13-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK13-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK13-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK13-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK13-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -5195,7 +5195,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD29:%.*]] = add nsw i32 [[TMP96]], 1 // CHECK13-NEXT: [[TMP97:%.*]] = zext i32 [[ADD29]] to i64 // CHECK13-NEXT: [[TMP98:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP98]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP98]], align 4 // CHECK13-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CHECK13-NEXT: store i32 4, ptr [[TMP99]], align 4 // CHECK13-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -5266,7 +5266,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD44:%.*]] = add nsw i32 [[TMP131]], 1 // CHECK13-NEXT: [[TMP132:%.*]] = zext i32 [[ADD44]] to i64 // CHECK13-NEXT: [[TMP133:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP133]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP133]], align 4 // CHECK13-NEXT: [[TMP134:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 1 // CHECK13-NEXT: store i32 3, ptr [[TMP134]], align 4 // CHECK13-NEXT: [[TMP135:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 2 @@ -5346,7 +5346,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[ADD60:%.*]] = add nsw i32 [[TMP171]], 1 // CHECK13-NEXT: [[TMP172:%.*]] = zext i32 [[ADD60]] to i64 // CHECK13-NEXT: [[TMP173:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP173]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP173]], align 4 // CHECK13-NEXT: [[TMP174:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 1 // CHECK13-NEXT: store i32 4, ptr [[TMP174]], align 4 // CHECK13-NEXT: [[TMP175:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 2 @@ -6658,7 +6658,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK13-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK13-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK13-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK13-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK13-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -6699,7 +6699,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK13-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK13-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK13-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK13-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK13-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -6749,7 +6749,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP48:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK13-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK13-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP50]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP50]], align 4 // CHECK13-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK13-NEXT: store i32 2, ptr [[TMP51]], align 4 // CHECK13-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -6790,7 +6790,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP68:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK13-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK13-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP70]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP70]], align 4 // CHECK13-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK13-NEXT: store i32 1, ptr [[TMP71]], align 4 // CHECK13-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -6840,7 +6840,7 @@ int main (int argc, char **argv) { // CHECK13-NEXT: [[TMP93:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0 // CHECK13-NEXT: [[TMP94:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0 // CHECK13-NEXT: [[TMP95:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 0 -// CHECK13-NEXT: store i32 2, ptr [[TMP95]], align 4 +// CHECK13-NEXT: store i32 3, ptr [[TMP95]], align 4 // CHECK13-NEXT: [[TMP96:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 1 // CHECK13-NEXT: store i32 2, ptr [[TMP96]], align 4 // CHECK13-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 2 @@ -7855,7 +7855,7 @@ int main (int argc, char **argv) { // CHECK14-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK14-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK14-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK14-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK14-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK14-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK14-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK14-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -7926,7 +7926,7 @@ int main (int argc, char **argv) { // CHECK14-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK14-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK14-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK14-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK14-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK14-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK14-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK14-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -8006,7 +8006,7 @@ int main (int argc, char **argv) { // CHECK14-NEXT: [[ADD29:%.*]] = add nsw i32 [[TMP96]], 1 // CHECK14-NEXT: [[TMP97:%.*]] = zext i32 [[ADD29]] to i64 // CHECK14-NEXT: [[TMP98:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK14-NEXT: store i32 2, ptr [[TMP98]], align 4 +// CHECK14-NEXT: store i32 3, ptr [[TMP98]], align 4 // CHECK14-NEXT: [[TMP99:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CHECK14-NEXT: store i32 4, ptr [[TMP99]], align 4 // CHECK14-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -8077,7 +8077,7 @@ int main (int argc, char **argv) { // CHECK14-NEXT: [[ADD44:%.*]] = add nsw i32 [[TMP131]], 1 // CHECK14-NEXT: [[TMP132:%.*]] = zext i32 [[ADD44]] to i64 // CHECK14-NEXT: [[TMP133:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 0 -// CHECK14-NEXT: store i32 2, ptr [[TMP133]], align 4 +// CHECK14-NEXT: store i32 3, ptr [[TMP133]], align 4 // CHECK14-NEXT: [[TMP134:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 1 // CHECK14-NEXT: store i32 3, ptr [[TMP134]], align 4 // CHECK14-NEXT: [[TMP135:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 2 @@ -8157,7 +8157,7 @@ int main (int argc, char **argv) { // CHECK14-NEXT: [[ADD60:%.*]] = add nsw i32 [[TMP171]], 1 // CHECK14-NEXT: [[TMP172:%.*]] = zext i32 [[ADD60]] to i64 // CHECK14-NEXT: [[TMP173:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 0 -// CHECK14-NEXT: store i32 2, ptr [[TMP173]], align 4 +// CHECK14-NEXT: store i32 3, ptr [[TMP173]], align 4 // CHECK14-NEXT: [[TMP174:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 1 // CHECK14-NEXT: store i32 4, ptr [[TMP174]], align 4 // CHECK14-NEXT: [[TMP175:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 2 @@ -9469,7 +9469,7 @@ int main (int argc, char **argv) { // CHECK14-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK14-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK14-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK14-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK14-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK14-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK14-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK14-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -9510,7 +9510,7 @@ int main (int argc, char **argv) { // CHECK14-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK14-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK14-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK14-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK14-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK14-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK14-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK14-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -9560,7 +9560,7 @@ int main (int argc, char **argv) { // CHECK14-NEXT: [[TMP48:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK14-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK14-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK14-NEXT: store i32 2, ptr [[TMP50]], align 4 +// CHECK14-NEXT: store i32 3, ptr [[TMP50]], align 4 // CHECK14-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK14-NEXT: store i32 2, ptr [[TMP51]], align 4 // CHECK14-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -9601,7 +9601,7 @@ int main (int argc, char **argv) { // CHECK14-NEXT: [[TMP68:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK14-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK14-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK14-NEXT: store i32 2, ptr [[TMP70]], align 4 +// CHECK14-NEXT: store i32 3, ptr [[TMP70]], align 4 // CHECK14-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK14-NEXT: store i32 1, ptr [[TMP71]], align 4 // CHECK14-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -9651,7 +9651,7 @@ int main (int argc, char **argv) { // CHECK14-NEXT: [[TMP93:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0 // CHECK14-NEXT: [[TMP94:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0 // CHECK14-NEXT: [[TMP95:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 0 -// CHECK14-NEXT: store i32 2, ptr [[TMP95]], align 4 +// CHECK14-NEXT: store i32 3, ptr [[TMP95]], align 4 // CHECK14-NEXT: [[TMP96:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 1 // CHECK14-NEXT: store i32 2, ptr [[TMP96]], align 4 // CHECK14-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 2 @@ -10666,7 +10666,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK17-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK17-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK17-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK17-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -10738,7 +10738,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP57]], 1 // CHECK17-NEXT: [[TMP58:%.*]] = zext i32 [[ADD14]] to i64 // CHECK17-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP59]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK17-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK17-NEXT: store i32 3, ptr [[TMP60]], align 4 // CHECK17-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -10819,7 +10819,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD29:%.*]] = add nsw i32 [[TMP98]], 1 // CHECK17-NEXT: [[TMP99:%.*]] = zext i32 [[ADD29]] to i64 // CHECK17-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP100]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP100]], align 4 // CHECK17-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CHECK17-NEXT: store i32 4, ptr [[TMP101]], align 4 // CHECK17-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -10891,7 +10891,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD44:%.*]] = add nsw i32 [[TMP134]], 1 // CHECK17-NEXT: [[TMP135:%.*]] = zext i32 [[ADD44]] to i64 // CHECK17-NEXT: [[TMP136:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP136]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP136]], align 4 // CHECK17-NEXT: [[TMP137:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 1 // CHECK17-NEXT: store i32 3, ptr [[TMP137]], align 4 // CHECK17-NEXT: [[TMP138:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 2 @@ -10972,7 +10972,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[ADD60:%.*]] = add nsw i32 [[TMP175]], 1 // CHECK17-NEXT: [[TMP176:%.*]] = zext i32 [[ADD60]] to i64 // CHECK17-NEXT: [[TMP177:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP177]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP177]], align 4 // CHECK17-NEXT: [[TMP178:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 1 // CHECK17-NEXT: store i32 4, ptr [[TMP178]], align 4 // CHECK17-NEXT: [[TMP179:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 2 @@ -12259,7 +12259,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK17-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK17-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -12300,7 +12300,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK17-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK17-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK17-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK17-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK17-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -12350,7 +12350,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP48:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK17-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK17-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP50]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP50]], align 4 // CHECK17-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK17-NEXT: store i32 2, ptr [[TMP51]], align 4 // CHECK17-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -12391,7 +12391,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP68:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK17-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK17-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP70]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP70]], align 4 // CHECK17-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK17-NEXT: store i32 1, ptr [[TMP71]], align 4 // CHECK17-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -12441,7 +12441,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP93:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0 // CHECK17-NEXT: [[TMP94:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0 // CHECK17-NEXT: [[TMP95:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP95]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP95]], align 4 // CHECK17-NEXT: [[TMP96:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 1 // CHECK17-NEXT: store i32 2, ptr [[TMP96]], align 4 // CHECK17-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 2 @@ -13429,7 +13429,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK19-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK19-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK19-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK19-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -13501,7 +13501,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP57]], 1 // CHECK19-NEXT: [[TMP58:%.*]] = zext i32 [[ADD14]] to i64 // CHECK19-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP59]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK19-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK19-NEXT: store i32 3, ptr [[TMP60]], align 4 // CHECK19-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -13582,7 +13582,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD29:%.*]] = add nsw i32 [[TMP98]], 1 // CHECK19-NEXT: [[TMP99:%.*]] = zext i32 [[ADD29]] to i64 // CHECK19-NEXT: [[TMP100:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP100]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP100]], align 4 // CHECK19-NEXT: [[TMP101:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CHECK19-NEXT: store i32 4, ptr [[TMP101]], align 4 // CHECK19-NEXT: [[TMP102:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -13654,7 +13654,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD44:%.*]] = add nsw i32 [[TMP134]], 1 // CHECK19-NEXT: [[TMP135:%.*]] = zext i32 [[ADD44]] to i64 // CHECK19-NEXT: [[TMP136:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP136]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP136]], align 4 // CHECK19-NEXT: [[TMP137:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 1 // CHECK19-NEXT: store i32 3, ptr [[TMP137]], align 4 // CHECK19-NEXT: [[TMP138:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS45]], i32 0, i32 2 @@ -13735,7 +13735,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[ADD60:%.*]] = add nsw i32 [[TMP175]], 1 // CHECK19-NEXT: [[TMP176:%.*]] = zext i32 [[ADD60]] to i64 // CHECK19-NEXT: [[TMP177:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP177]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP177]], align 4 // CHECK19-NEXT: [[TMP178:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 1 // CHECK19-NEXT: store i32 4, ptr [[TMP178]], align 4 // CHECK19-NEXT: [[TMP179:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS61]], i32 0, i32 2 @@ -15022,7 +15022,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK19-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK19-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -15063,7 +15063,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK19-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK19-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK19-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK19-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK19-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -15113,7 +15113,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP48:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK19-NEXT: [[TMP49:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK19-NEXT: [[TMP50:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP50]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP50]], align 4 // CHECK19-NEXT: [[TMP51:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK19-NEXT: store i32 2, ptr [[TMP51]], align 4 // CHECK19-NEXT: [[TMP52:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -15154,7 +15154,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP68:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS15]], i32 0, i32 0 // CHECK19-NEXT: [[TMP69:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS16]], i32 0, i32 0 // CHECK19-NEXT: [[TMP70:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP70]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP70]], align 4 // CHECK19-NEXT: [[TMP71:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 1 // CHECK19-NEXT: store i32 1, ptr [[TMP71]], align 4 // CHECK19-NEXT: [[TMP72:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS19]], i32 0, i32 2 @@ -15204,7 +15204,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP93:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_BASEPTRS23]], i32 0, i32 0 // CHECK19-NEXT: [[TMP94:%.*]] = getelementptr inbounds [2 x ptr], ptr [[DOTOFFLOAD_PTRS24]], i32 0, i32 0 // CHECK19-NEXT: [[TMP95:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP95]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP95]], align 4 // CHECK19-NEXT: [[TMP96:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 1 // CHECK19-NEXT: store i32 2, ptr [[TMP96]], align 4 // CHECK19-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS27]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_private_codegen.cpp b/clang/test/OpenMP/teams_distribute_private_codegen.cpp index bdc001fe5d5d8b08d2d913b26741a5cec403ed32..78b42e3194c796067eeb3a7ce56a5005dacedb08 100644 --- a/clang/test/OpenMP/teams_distribute_private_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_private_codegen.cpp @@ -243,7 +243,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -412,7 +412,7 @@ int main() { // CHECK1-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 // CHECK1-NEXT: store ptr undef, ptr [[_TMP1]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -771,7 +771,7 @@ int main() { // CHECK3-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK3-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -938,7 +938,7 @@ int main() { // CHECK3-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 // CHECK3-NEXT: store ptr undef, ptr [[_TMP1]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_reduction_codegen.cpp b/clang/test/OpenMP/teams_distribute_reduction_codegen.cpp index 309cbffcf616251e991a7f42c4d84bec63b70c75..ff2defa849efb7365317532e5fb8df759b7420dd 100644 --- a/clang/test/OpenMP/teams_distribute_reduction_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_reduction_codegen.cpp @@ -105,7 +105,7 @@ int main() { // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -285,7 +285,7 @@ int main() { // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -462,7 +462,7 @@ int main() { // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -642,7 +642,7 @@ int main() { // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_simd_codegen.cpp b/clang/test/OpenMP/teams_distribute_simd_codegen.cpp index ee5d5cad72fe2040e8989bb77a5b13cb38036ebc..2fab0cff55373a1658aa672e6b1534c947881e94 100644 --- a/clang/test/OpenMP/teams_distribute_simd_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_simd_codegen.cpp @@ -302,7 +302,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP34:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP26]], 0 // CHECK1-NEXT: [[TMP35:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP29]], 0 // CHECK1-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK1-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP37]], align 4 // CHECK1-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -362,7 +362,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP63]], 1 // CHECK1-NEXT: [[TMP64:%.*]] = zext i32 [[ADD14]] to i64 // CHECK1-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK1-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP66]], align 4 // CHECK1-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -737,7 +737,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP34:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP26]], 0 // CHECK3-NEXT: [[TMP35:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP29]], 0 // CHECK3-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK3-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP37]], align 4 // CHECK3-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -797,7 +797,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP63]], 1 // CHECK3-NEXT: [[TMP64:%.*]] = zext i32 [[ADD14]] to i64 // CHECK3-NEXT: [[TMP65:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP65]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP65]], align 4 // CHECK3-NEXT: [[TMP66:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP66]], align 4 // CHECK3-NEXT: [[TMP67:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1407,7 +1407,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK9-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1629,7 +1629,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK11-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1993,7 +1993,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP17:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK17-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK17-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK17-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2171,7 +2171,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP17:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK19-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK19-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK19-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2348,7 +2348,7 @@ int main (int argc, char **argv) { // CHECK21-NEXT: [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK21-NEXT: [[TMP17:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK21-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK21-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK21-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK21-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK21-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK21-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2576,7 +2576,7 @@ int main (int argc, char **argv) { // CHECK23-NEXT: [[TMP16:%.*]] = getelementptr inbounds [3 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK23-NEXT: [[TMP17:%.*]] = getelementptr inbounds [3 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK23-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK23-NEXT: store i32 2, ptr [[TMP18]], align 4 +// CHECK23-NEXT: store i32 3, ptr [[TMP18]], align 4 // CHECK23-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK23-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK23-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3130,7 +3130,7 @@ int main (int argc, char **argv) { // CHECK33-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK33-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK33-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK33-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK33-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK33-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK33-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK33-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3343,7 +3343,7 @@ int main (int argc, char **argv) { // CHECK33-NEXT: [[TMP19:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP15]], 0 // CHECK33-NEXT: [[TMP20:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP18]], 0 // CHECK33-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK33-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK33-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK33-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK33-NEXT: store i32 3, ptr [[TMP22]], align 4 // CHECK33-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3537,7 +3537,7 @@ int main (int argc, char **argv) { // CHECK35-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK35-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK35-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK35-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK35-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK35-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK35-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK35-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3749,7 +3749,7 @@ int main (int argc, char **argv) { // CHECK35-NEXT: [[TMP19:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP15]], 0 // CHECK35-NEXT: [[TMP20:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP18]], 0 // CHECK35-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK35-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK35-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK35-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK35-NEXT: store i32 3, ptr [[TMP22]], align 4 // CHECK35-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3952,7 +3952,7 @@ int main (int argc, char **argv) { // CHECK37-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP26]], 1 // CHECK37-NEXT: [[TMP27:%.*]] = zext i32 [[ADD]] to i64 // CHECK37-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK37-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK37-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK37-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK37-NEXT: store i32 4, ptr [[TMP29]], align 4 // CHECK37-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4212,7 +4212,7 @@ int main (int argc, char **argv) { // CHECK37-NEXT: [[TMP19:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP15]], 0 // CHECK37-NEXT: [[TMP20:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP18]], 0 // CHECK37-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK37-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK37-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK37-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK37-NEXT: store i32 3, ptr [[TMP22]], align 4 // CHECK37-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4416,7 +4416,7 @@ int main (int argc, char **argv) { // CHECK39-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP26]], 1 // CHECK39-NEXT: [[TMP27:%.*]] = zext i32 [[ADD]] to i64 // CHECK39-NEXT: [[TMP28:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK39-NEXT: store i32 2, ptr [[TMP28]], align 4 +// CHECK39-NEXT: store i32 3, ptr [[TMP28]], align 4 // CHECK39-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK39-NEXT: store i32 4, ptr [[TMP29]], align 4 // CHECK39-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -4674,7 +4674,7 @@ int main (int argc, char **argv) { // CHECK39-NEXT: [[TMP19:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP15]], 0 // CHECK39-NEXT: [[TMP20:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP18]], 0 // CHECK39-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK39-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK39-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK39-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK39-NEXT: store i32 3, ptr [[TMP22]], align 4 // CHECK39-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_simd_collapse_codegen.cpp b/clang/test/OpenMP/teams_distribute_simd_collapse_codegen.cpp index 292bfb2a296c68b1be4d5e8ade9cc3c747bbdb47..da0e7703e30cdf4d2ade45bf7d2c5efd21787afc 100644 --- a/clang/test/OpenMP/teams_distribute_simd_collapse_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_simd_collapse_codegen.cpp @@ -128,7 +128,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -297,7 +297,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -674,7 +674,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP35:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK9-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP35]], 1 // CHECK9-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK9-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP37]], align 4 // CHECK9-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -922,7 +922,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1155,7 +1155,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP34:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK11-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP34]], 1 // CHECK11-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP35]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP35]], align 4 // CHECK11-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP36]], align 4 // CHECK11-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1401,7 +1401,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_simd_dist_schedule_codegen.cpp b/clang/test/OpenMP/teams_distribute_simd_dist_schedule_codegen.cpp index a18b4d2feeec60656a01e57c847338d219481300..1266534b890f8a52a328b60a16a4f86f85988122 100644 --- a/clang/test/OpenMP/teams_distribute_simd_dist_schedule_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_simd_dist_schedule_codegen.cpp @@ -170,7 +170,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -212,7 +212,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK1-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK1-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK1-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK1-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -254,7 +254,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK1-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK1-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK1-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK1-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -603,7 +603,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -645,7 +645,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS3]], i32 0, i32 0 // CHECK3-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS4]], i32 0, i32 0 // CHECK3-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK3-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK3-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS7]], i32 0, i32 2 @@ -687,7 +687,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS11]], i32 0, i32 0 // CHECK3-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS12]], i32 0, i32 0 // CHECK3-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK3-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK3-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1326,7 +1326,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK9-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1397,7 +1397,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK9-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK9-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK9-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK9-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1468,7 +1468,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD29:%.*]] = add nsw i32 [[TMP91]], 1 // CHECK9-NEXT: [[TMP92:%.*]] = zext i32 [[ADD29]] to i64 // CHECK9-NEXT: [[TMP93:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP93]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP93]], align 4 // CHECK9-NEXT: [[TMP94:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP94]], align 4 // CHECK9-NEXT: [[TMP95:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -1932,7 +1932,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1973,7 +1973,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -2014,7 +2014,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK9-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK9-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK9-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK9-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 @@ -2403,7 +2403,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK11-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2475,7 +2475,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP57]], 1 // CHECK11-NEXT: [[TMP58:%.*]] = zext i32 [[ADD14]] to i64 // CHECK11-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP59]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP59]], align 4 // CHECK11-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP60]], align 4 // CHECK11-NEXT: [[TMP61:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -2547,7 +2547,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD29:%.*]] = add nsw i32 [[TMP93]], 1 // CHECK11-NEXT: [[TMP94:%.*]] = zext i32 [[ADD29]] to i64 // CHECK11-NEXT: [[TMP95:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP95]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP95]], align 4 // CHECK11-NEXT: [[TMP96:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP96]], align 4 // CHECK11-NEXT: [[TMP97:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS30]], i32 0, i32 2 @@ -3008,7 +3008,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3049,7 +3049,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS1]], i32 0, i32 0 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS2]], i32 0, i32 0 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -3090,7 +3090,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP43:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS8]], i32 0, i32 0 // CHECK11-NEXT: [[TMP44:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS9]], i32 0, i32 0 // CHECK11-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP45]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP45]], align 4 // CHECK11-NEXT: [[TMP46:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP46]], align 4 // CHECK11-NEXT: [[TMP47:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS12]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_simd_firstprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_simd_firstprivate_codegen.cpp index dd3daf865512abc842941311941e2dbb367d2930..2d3fccd90c0a5d19867d7283a20bad0ce81ccdc6 100644 --- a/clang/test/OpenMP/teams_distribute_simd_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_simd_firstprivate_codegen.cpp @@ -306,7 +306,7 @@ int main() { // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 5, ptr [[TMP22]], align 4 // CHECK1-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -596,7 +596,7 @@ int main() { // CHECK1-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK1-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK1-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1124,7 +1124,7 @@ int main() { // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 5, ptr [[TMP22]], align 4 // CHECK3-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1412,7 +1412,7 @@ int main() { // CHECK3-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK3-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK3-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_simd_lastprivate_codegen.cpp index 073960cc5a4601b6bbd9ec939f44723ba9aa41c4..ec95ab55b1552a9911931f9786a95418fa27d164 100644 --- a/clang/test/OpenMP/teams_distribute_simd_lastprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_simd_lastprivate_codegen.cpp @@ -568,7 +568,7 @@ int main() { // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK9-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK9-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -886,7 +886,7 @@ int main() { // CHECK9-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK9-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK9-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1278,7 +1278,7 @@ int main() { // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP25]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP25]], align 4 // CHECK11-NEXT: [[TMP26:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP26]], align 4 // CHECK11-NEXT: [[TMP27:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1594,7 +1594,7 @@ int main() { // CHECK11-NEXT: [[TMP18:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP19:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP20]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK11-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP21]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_simd_private_codegen.cpp b/clang/test/OpenMP/teams_distribute_simd_private_codegen.cpp index 52b213c34591517853aafc3fcc162d7fd8a726c7..c839268ada753485516ae92981bf19e6c5410c83 100644 --- a/clang/test/OpenMP/teams_distribute_simd_private_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_simd_private_codegen.cpp @@ -244,7 +244,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -420,7 +420,7 @@ int main() { // CHECK1-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 // CHECK1-NEXT: store ptr undef, ptr [[_TMP1]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -786,7 +786,7 @@ int main() { // CHECK3-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK3-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -960,7 +960,7 @@ int main() { // CHECK3-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 // CHECK3-NEXT: store ptr undef, ptr [[_TMP1]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_distribute_simd_reduction_codegen.cpp b/clang/test/OpenMP/teams_distribute_simd_reduction_codegen.cpp index e660009f1cd7f8e36f2bc96ad9d3d2a36905548b..27c47f50547eaa819ce704481c18846176cae57f 100644 --- a/clang/test/OpenMP/teams_distribute_simd_reduction_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_simd_reduction_codegen.cpp @@ -105,7 +105,7 @@ int main() { // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -292,7 +292,7 @@ int main() { // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -476,7 +476,7 @@ int main() { // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -663,7 +663,7 @@ int main() { // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_firstprivate_codegen.cpp b/clang/test/OpenMP/teams_firstprivate_codegen.cpp index c023de8cf010dd63fb9b774ddb87815ccb1d71bd..649fae99b21ac35a6a7ce3b38e325b010713ea52 100644 --- a/clang/test/OpenMP/teams_firstprivate_codegen.cpp +++ b/clang/test/OpenMP/teams_firstprivate_codegen.cpp @@ -327,7 +327,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK9-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP22]], align 4 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -371,7 +371,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: [[TMP41:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0 // CHECK9-NEXT: [[TMP42:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 // CHECK9-NEXT: [[TMP43:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP43]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP43]], align 4 // CHECK9-NEXT: [[TMP44:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP44]], align 4 // CHECK9-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -663,7 +663,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: [[TMP14:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP15:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK9-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 4, ptr [[TMP17]], align 4 // CHECK9-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -707,7 +707,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK9-NEXT: [[TMP36:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0 // CHECK9-NEXT: [[TMP37:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 // CHECK9-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP38]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP38]], align 4 // CHECK9-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP39]], align 4 // CHECK9-NEXT: [[TMP40:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -1121,7 +1121,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK11-NEXT: [[TMP19:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP20:%.*]] = getelementptr inbounds [5 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP21]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP21]], align 4 // CHECK11-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP22]], align 4 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1165,7 +1165,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK11-NEXT: [[TMP41:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0 // CHECK11-NEXT: [[TMP42:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 // CHECK11-NEXT: [[TMP43:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP43]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP43]], align 4 // CHECK11-NEXT: [[TMP44:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP44]], align 4 // CHECK11-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -1457,7 +1457,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK11-NEXT: [[TMP14:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP15:%.*]] = getelementptr inbounds [4 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP16:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP16]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP16]], align 4 // CHECK11-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 4, ptr [[TMP17]], align 4 // CHECK11-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1501,7 +1501,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK11-NEXT: [[TMP36:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS2]], i32 0, i32 0 // CHECK11-NEXT: [[TMP37:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS3]], i32 0, i32 0 // CHECK11-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP38]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP38]], align 4 // CHECK11-NEXT: [[TMP39:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP39]], align 4 // CHECK11-NEXT: [[TMP40:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS5]], i32 0, i32 2 @@ -1942,7 +1942,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK17-NEXT: [[TMP41:%.*]] = getelementptr inbounds [8 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP42:%.*]] = getelementptr inbounds [8 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK17-NEXT: [[TMP43:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP43]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP43]], align 4 // CHECK17-NEXT: [[TMP44:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 8, ptr [[TMP44]], align 4 // CHECK17-NEXT: [[TMP45:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2180,7 +2180,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK17-NEXT: [[TMP53:%.*]] = getelementptr inbounds [10 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP54:%.*]] = getelementptr inbounds [10 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK17-NEXT: [[TMP55:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP55]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP55]], align 4 // CHECK17-NEXT: [[TMP56:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 10, ptr [[TMP56]], align 4 // CHECK17-NEXT: [[TMP57:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2405,7 +2405,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK19-NEXT: [[TMP39:%.*]] = getelementptr inbounds [8 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP40:%.*]] = getelementptr inbounds [8 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK19-NEXT: [[TMP41:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP41]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP41]], align 4 // CHECK19-NEXT: [[TMP42:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 8, ptr [[TMP42]], align 4 // CHECK19-NEXT: [[TMP43:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2641,7 +2641,7 @@ void array_func(float a[3], St s[2], int n, long double vla1[n]) { // CHECK19-NEXT: [[TMP51:%.*]] = getelementptr inbounds [10 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP52:%.*]] = getelementptr inbounds [10 x i64], ptr [[DOTOFFLOAD_SIZES]], i32 0, i32 0 // CHECK19-NEXT: [[TMP53:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP53]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP53]], align 4 // CHECK19-NEXT: [[TMP54:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 10, ptr [[TMP54]], align 4 // CHECK19-NEXT: [[TMP55:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_generic_loop_codegen-1.cpp b/clang/test/OpenMP/teams_generic_loop_codegen-1.cpp index 85a4dfea91a21aa5ba251d36fd9ae71d8555899b..d4a98f07fe24d5791f0b9c8fd67883d00cb105c9 100644 --- a/clang/test/OpenMP/teams_generic_loop_codegen-1.cpp +++ b/clang/test/OpenMP/teams_generic_loop_codegen-1.cpp @@ -253,7 +253,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP27:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP21]], 0 // CHECK1-NEXT: [[TMP28:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP22]], 0 // CHECK1-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK1-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 4, ptr [[TMP30]], align 4 // CHECK1-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -313,7 +313,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK1-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK1-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK1-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK1-NEXT: store i32 2, ptr [[TMP59]], align 4 // CHECK1-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -840,7 +840,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP27:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP21]], 0 // CHECK3-NEXT: [[TMP28:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP22]], 0 // CHECK3-NEXT: [[TMP29:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP29]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP29]], align 4 // CHECK3-NEXT: [[TMP30:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 4, ptr [[TMP30]], align 4 // CHECK3-NEXT: [[TMP31:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -900,7 +900,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[ADD14:%.*]] = add nsw i32 [[TMP56]], 1 // CHECK3-NEXT: [[TMP57:%.*]] = zext i32 [[ADD14]] to i64 // CHECK3-NEXT: [[TMP58:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP58]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP58]], align 4 // CHECK3-NEXT: [[TMP59:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 1 // CHECK3-NEXT: store i32 2, ptr [[TMP59]], align 4 // CHECK3-NEXT: [[TMP60:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS15]], i32 0, i32 2 @@ -1399,7 +1399,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK9-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK9-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK9-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK9-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1710,7 +1710,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK11-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK11-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK11-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK11-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1984,7 +1984,7 @@ int main (int argc, char **argv) { // CHECK17-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK17-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK17-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK17-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK17-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK17-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK17-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2202,7 +2202,7 @@ int main (int argc, char **argv) { // CHECK19-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK19-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK19-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK19-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK19-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK19-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK19-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2453,7 +2453,7 @@ int main (int argc, char **argv) { // CHECK25-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK25-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK25-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK25-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK25-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK25-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK25-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK25-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -2753,7 +2753,7 @@ int main (int argc, char **argv) { // CHECK25-NEXT: [[TMP17:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP15]], 0 // CHECK25-NEXT: [[TMP18:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP16]], 0 // CHECK25-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK25-NEXT: store i32 2, ptr [[TMP19]], align 4 +// CHECK25-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK25-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK25-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK25-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3013,7 +3013,7 @@ int main (int argc, char **argv) { // CHECK27-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP21]], 1 // CHECK27-NEXT: [[TMP22:%.*]] = zext i32 [[ADD]] to i64 // CHECK27-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK27-NEXT: store i32 2, ptr [[TMP23]], align 4 +// CHECK27-NEXT: store i32 3, ptr [[TMP23]], align 4 // CHECK27-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK27-NEXT: store i32 3, ptr [[TMP24]], align 4 // CHECK27-NEXT: [[TMP25:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -3308,7 +3308,7 @@ int main (int argc, char **argv) { // CHECK27-NEXT: [[TMP17:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP15]], 0 // CHECK27-NEXT: [[TMP18:%.*]] = insertvalue [3 x i32] zeroinitializer, i32 [[TMP16]], 0 // CHECK27-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK27-NEXT: store i32 2, ptr [[TMP19]], align 4 +// CHECK27-NEXT: store i32 3, ptr [[TMP19]], align 4 // CHECK27-NEXT: [[TMP20:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK27-NEXT: store i32 3, ptr [[TMP20]], align 4 // CHECK27-NEXT: [[TMP21:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_generic_loop_collapse_codegen.cpp b/clang/test/OpenMP/teams_generic_loop_collapse_codegen.cpp index 49df83c9c765cfad07207ea1f799fbb602359ef7..c0c04986f147e064d2c17071a0d429eec35f5c3d 100644 --- a/clang/test/OpenMP/teams_generic_loop_collapse_codegen.cpp +++ b/clang/test/OpenMP/teams_generic_loop_collapse_codegen.cpp @@ -132,7 +132,7 @@ int main (int argc, char **argv) { // CHECK1-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -368,7 +368,7 @@ int main (int argc, char **argv) { // CHECK3-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -668,7 +668,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP35:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK9-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP35]], 1 // CHECK9-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP36]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP36]], align 4 // CHECK9-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 5, ptr [[TMP37]], align 4 // CHECK9-NEXT: [[TMP38:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1018,7 +1018,7 @@ int main (int argc, char **argv) { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1318,7 +1318,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP34:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_3]], align 8 // CHECK11-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP34]], 1 // CHECK11-NEXT: [[TMP35:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP35]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP35]], align 4 // CHECK11-NEXT: [[TMP36:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 5, ptr [[TMP36]], align 4 // CHECK11-NEXT: [[TMP37:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1670,7 +1670,7 @@ int main (int argc, char **argv) { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_generic_loop_private_codegen.cpp b/clang/test/OpenMP/teams_generic_loop_private_codegen.cpp index 5ef729f044e09708a860fe1d49c3cb96d425b4fb..303bce8c648c2038d30f6935bb324963cf9fa57d 100644 --- a/clang/test/OpenMP/teams_generic_loop_private_codegen.cpp +++ b/clang/test/OpenMP/teams_generic_loop_private_codegen.cpp @@ -263,7 +263,7 @@ int main() { // CHECK1-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -533,7 +533,7 @@ int main() { // CHECK1-NEXT: store ptr [[TEST]], ptr [[VAR]], align 8 // CHECK1-NEXT: store ptr undef, ptr [[_TMP1]], align 8 // CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK1-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK1-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -996,7 +996,7 @@ int main() { // CHECK3-NEXT: [[KERNEL_ARGS:%.*]] = alloca [[STRUCT___TGT_KERNEL_ARGUMENTS:%.*]], align 8 // CHECK3-NEXT: store i32 0, ptr [[RETVAL]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1260,7 +1260,7 @@ int main() { // CHECK3-NEXT: store ptr [[TEST]], ptr [[VAR]], align 4 // CHECK3-NEXT: store ptr undef, ptr [[_TMP1]], align 4 // CHECK3-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK3-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK3-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_generic_loop_reduction_codegen.cpp b/clang/test/OpenMP/teams_generic_loop_reduction_codegen.cpp index 4da49eed32efd2dfcd9b6bb0b8e0c0f7db51d4b4..d80c003c0109955ceaf33f1af4f22a25e08e22ea 100644 --- a/clang/test/OpenMP/teams_generic_loop_reduction_codegen.cpp +++ b/clang/test/OpenMP/teams_generic_loop_reduction_codegen.cpp @@ -116,7 +116,7 @@ int main() { // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -410,7 +410,7 @@ int main() { // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK1-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -701,7 +701,7 @@ int main() { // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -991,7 +991,7 @@ int main() { // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP7]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP8]], align 4 // CHECK3-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/OpenMP/teams_private_codegen.cpp b/clang/test/OpenMP/teams_private_codegen.cpp index 0126545c5915bc4d3240895199b2477f58c6d2b4..1d0b2435ff005819dd23f8d460f510c769c6f901 100644 --- a/clang/test/OpenMP/teams_private_codegen.cpp +++ b/clang/test/OpenMP/teams_private_codegen.cpp @@ -219,7 +219,7 @@ int main() { // CHECK1-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK1-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK1-NEXT: store i32 2, ptr [[TMP6]], align 4 +// CHECK1-NEXT: store i32 3, ptr [[TMP6]], align 4 // CHECK1-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK1-NEXT: store i32 1, ptr [[TMP7]], align 4 // CHECK1-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -405,7 +405,7 @@ int main() { // CHECK3-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK3-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK3-NEXT: store i32 2, ptr [[TMP6]], align 4 +// CHECK3-NEXT: store i32 3, ptr [[TMP6]], align 4 // CHECK3-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK3-NEXT: store i32 1, ptr [[TMP7]], align 4 // CHECK3-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -557,7 +557,7 @@ int main() { // CHECK9-NEXT: call void @_ZN1SIfEC1Ef(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], float noundef 2.000000e+00) // CHECK9-NEXT: call void @_ZN1SIfEC1Ef(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]], float noundef 3.000000e+00) // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -724,7 +724,7 @@ int main() { // CHECK9-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], i32 noundef signext 2) // CHECK9-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]], i32 noundef signext 3) // CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK9-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK9-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -804,7 +804,7 @@ int main() { // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP6]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP7]], align 4 // CHECK9-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1037,7 +1037,7 @@ int main() { // CHECK9-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK9-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK9-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK9-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK9-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK9-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK9-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1147,7 +1147,7 @@ int main() { // CHECK11-NEXT: call void @_ZN1SIfEC1Ef(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], float noundef 2.000000e+00) // CHECK11-NEXT: call void @_ZN1SIfEC1Ef(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]], float noundef 3.000000e+00) // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1314,7 +1314,7 @@ int main() { // CHECK11-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT]], i32 noundef 2) // CHECK11-NEXT: call void @_ZN1SIiEC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]], i32 noundef 3) // CHECK11-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP0]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP0]], align 4 // CHECK11-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 0, ptr [[TMP1]], align 4 // CHECK11-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1394,7 +1394,7 @@ int main() { // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP6]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP7]], align 4 // CHECK11-NEXT: [[TMP8:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 @@ -1627,7 +1627,7 @@ int main() { // CHECK11-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_BASEPTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP4:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOFFLOAD_PTRS]], i32 0, i32 0 // CHECK11-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0 -// CHECK11-NEXT: store i32 2, ptr [[TMP5]], align 4 +// CHECK11-NEXT: store i32 3, ptr [[TMP5]], align 4 // CHECK11-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 1 // CHECK11-NEXT: store i32 1, ptr [[TMP6]], align 4 // CHECK11-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 2 diff --git a/clang/test/Options/HV.hlsl b/clang/test/Options/HV.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..9f7e1ebc02f25179681a5cfb08453b4bb2b809c9 --- /dev/null +++ b/clang/test/Options/HV.hlsl @@ -0,0 +1,20 @@ +// RUN: %clang_dxc -T lib_6_4 -HV 2016 %s 2>&1 -### | FileCheck -check-prefix=2016 %s +// RUN: %clang_dxc -T lib_6_4 -HV 2017 %s 2>&1 -### | FileCheck -check-prefix=2017 %s +// RUN: %clang_dxc -T lib_6_4 /HV 2018 %s 2>&1 -### | FileCheck -check-prefix=2018 %s +// RUN: %clang_dxc -T lib_6_4 /HV 2021 %s 2>&1 -### | FileCheck -check-prefix=2021 %s +// RUN: %clang_dxc -T lib_6_4 /HV 202x %s 2>&1 -### | FileCheck -check-prefix=202x %s +// RUN: %clang_dxc -T lib_6_4 %s 2>&1 -### | FileCheck -check-prefix=NO_HV %s +// RUN: not %clang_dxc -T lib_6_4 /HV gibberish -### %s 2>&1 | FileCheck -check-prefix=CHECK-ERR %s + +// 2016: "-std=hlsl2016" +// 2017: "-std=hlsl2017" +// 2018: "-std=hlsl2018" +// 2021: "-std=hlsl2021" +// 202x: "-std=hlsl202x" +// NO_HV-NOT: "-std=" +// CHECK-ERR: error: invalid value 'gibberish' in 'HV' +float4 main(float4 a : A) : SV_TARGET +{ + return -a.yxxx; +} + diff --git a/clang/test/Options/enable_16bit_types_validation.hlsl b/clang/test/Options/enable_16bit_types_validation.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..71d336f6f5039f2be5908ac6f3b26a870572e1f8 --- /dev/null +++ b/clang/test/Options/enable_16bit_types_validation.hlsl @@ -0,0 +1,25 @@ +// RUN: not %clang_dxc -enable-16bit-types -T cs_6_0 -HV 2016 %s 2>&1 | FileCheck -check-prefix=both_invalid %s +// RUN: not %clang_dxc -enable-16bit-types -T lib_6_4 -HV 2017 %s 2>&1 | FileCheck -check-prefix=HV_invalid_2017 %s +// RUN: not %clang_dxc -enable-16bit-types -T cs_6_0 /HV 2021 %s 2>&1 | FileCheck -check-prefix=TP_invalid %s +// RUN: %clang_dxc -enable-16bit-types -T lib_6_4 /HV 2018 %s 2>&1 -### | FileCheck -check-prefix=valid_2018 %s +// RUN: %clang_dxc -enable-16bit-types -T lib_6_4 /HV 2021 %s 2>&1 -### | FileCheck -check-prefix=valid_2021 %s + + +// both_invalid: error: '-enable-16bit-types' option requires target HLSL Version >= 2018 and shader model >= 6.2, but HLSL Version is 'hlsl2016' and shader model is '6.0' +// HV_invalid_2017: error: '-enable-16bit-types' option requires target HLSL Version >= 2018 and shader model >= 6.2, but HLSL Version is 'hlsl2017' and shader model is '6.4' +// TP_invalid: error: '-enable-16bit-types' option requires target HLSL Version >= 2018 and shader model >= 6.2, but HLSL Version is 'hlsl2021' and shader model is '6.0' + +// valid_2021: "dxil-unknown-shadermodel6.4-library" +// valid_2021-SAME: "-std=hlsl2021" +// valid_2021-SAME: "-fnative-half-type" + +// valid_2018: "dxil-unknown-shadermodel6.4-library" +// valid_2018-SAME: "-std=hlsl2018" +// valid_2018-SAME: "-fnative-half-type" + +[numthreads(1,1,1)] +void main() +{ + return; +} + diff --git a/clang/test/Options/enable_16bit_types_validation_spirv.hlsl b/clang/test/Options/enable_16bit_types_validation_spirv.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..a9700ef87a27c3fc205148339e4da2cadb86a1a4 --- /dev/null +++ b/clang/test/Options/enable_16bit_types_validation_spirv.hlsl @@ -0,0 +1,14 @@ +// RUN: not %clang_cc1 -internal-isystem D:\llvm-project\build\x64-Release\lib\clang\19\include -nostdsysteminc -triple spirv-vulkan-library -x hlsl -std=hlsl2016 -fnative-half-type -emit-llvm -disable-llvm-passes -o - %s 2>&1 | FileCheck %s --check-prefix=SPIRV +// RUN: %clang_cc1 -internal-isystem D:\llvm-project\build\x64-Release\lib\clang\19\include -nostdsysteminc -triple spirv-vulkan-library -x hlsl -std=hlsl2021 -fnative-half-type -emit-llvm -disable-llvm-passes -o - %s 2>&1 | FileCheck %s --check-prefix=valid + +// SPIRV: error: '-fnative-half-type' option requires target HLSL Version >= 2018, but HLSL Version is 'hlsl2016' + +// valid: "spirv-unknown-vulkan-library" +// valid: define spir_func void @main() #0 { + +[numthreads(1,1,1)] +void main() +{ + return; +} + diff --git a/clang/test/PCH/Inputs/bounds-safety-attributed-type.h b/clang/test/PCH/Inputs/bounds-safety-attributed-type.h new file mode 100644 index 0000000000000000000000000000000000000000..9bfd9615c2bfc1206a294e06a43ddeda534b7b54 --- /dev/null +++ b/clang/test/PCH/Inputs/bounds-safety-attributed-type.h @@ -0,0 +1,4 @@ +struct Test { + int count; + int fam[] __attribute__((counted_by(count))); +}; diff --git a/clang/test/PCH/bounds-safety-attributed-type.c b/clang/test/PCH/bounds-safety-attributed-type.c new file mode 100644 index 0000000000000000000000000000000000000000..c2dc0272bbd6059244e6f68784889cd16cc030ab --- /dev/null +++ b/clang/test/PCH/bounds-safety-attributed-type.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -include %S/Inputs/bounds-safety-attributed-type.h -fsyntax-only -verify %s + +// Test with pch. +// RUN: %clang_cc1 -emit-pch -o %t %S/Inputs/bounds-safety-attributed-type.h +// RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s +// RUN: %clang_cc1 -include-pch %t -ast-print %s | FileCheck %s --check-prefix PRINT +// RUN: %clang_cc1 -include-pch %t -ast-dump-all %s | FileCheck %s --check-prefix DUMP +// expected-no-diagnostics + +// PRINT: struct Test { +// PRINT-NEXT: int count; +// PRINT-NEXT: int fam[] __counted_by(count); +// PRINT-NEXT: }; + +// DUMP: RecordDecl {{.*}} imported <undeserialized declarations> struct Test definition +// DUMP-NEXT: |-FieldDecl {{.*}} imported referenced count 'int' +// DUMP-NEXT: `-FieldDecl {{.*}} imported fam 'int[] __counted_by(count)':'int[]' diff --git a/clang/test/Parser/cxx03-lambda-extension.cpp b/clang/test/Parser/cxx03-lambda-extension.cpp new file mode 100644 index 0000000000000000000000000000000000000000..82ae7da305305cf237ba52a7babfe2f219bbc40d --- /dev/null +++ b/clang/test/Parser/cxx03-lambda-extension.cpp @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify -std=c++03 %s + +void func() { + []() {}; // expected-warning {{lambdas are a C++11 extension}} +} diff --git a/clang/test/Parser/cxx0x-lambda-expressions.cpp b/clang/test/Parser/cxx0x-lambda-expressions.cpp index 72b315a497c06790fd2fe78147ca5f320beb5579..a786a964163e4c4d076a33521f2b5a9a50a56462 100644 --- a/clang/test/Parser/cxx0x-lambda-expressions.cpp +++ b/clang/test/Parser/cxx0x-lambda-expressions.cpp @@ -1,10 +1,15 @@ -// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify -std=c++11 -Wno-c99-designator %s -// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify -std=c++20 -Wno-c99-designator %s -// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify -std=c++23 -Wno-c99-designator %s +// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=expected,cxx14ext,cxx17ext,cxx20ext,cxx23ext -std=c++03 -Wno-c99-designator %s -Wno-c++11-extensions +// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=expected,cxx14ext,cxx17ext,cxx20ext,cxx23ext -std=c++11 -Wno-c99-designator %s +// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=expected,cxx17ext,cxx20ext,cxx23ext -std=c++14 -Wno-c99-designator %s +// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=expected,cxx20ext,cxx23ext -std=c++17 -Wno-c99-designator %s +// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=expected,cxx23ext -std=c++20 -Wno-c99-designator %s +// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=expected -std=c++23 -Wno-c99-designator %s enum E { e }; +#if __cplusplus >= 201103L constexpr int id(int n) { return n; } +#endif class C { @@ -19,28 +24,25 @@ class C { [&,] {}; // expected-error {{expected variable name or 'this' in lambda capture list}} [=,] {}; // expected-error {{expected variable name or 'this' in lambda capture list}} [] {}; - [=] (int i) {}; - [&] (int) mutable -> void {}; - [foo,bar] () { return 3; }; - [=,&foo] () {}; - [&,foo] () {}; - [this] () {}; + [=] (int i) {}; + [&] (int) mutable -> void {}; + [foo,bar] () { return 3; }; + [=,&foo] () {}; + [&,foo] () {}; + [this] () {}; [] () -> class C { return C(); }; [] () -> enum E { return e; }; - [] -> int { return 0; }; - [] mutable -> int { return 0; }; -#if __cplusplus <= 202002L - // expected-warning@-3 {{lambda without a parameter clause is a C++23 extension}} - // expected-warning@-3 {{is a C++23 extension}} -#endif + [] -> int { return 0; }; // cxx23ext-warning {{lambda without a parameter clause is a C++23 extension}} + [] mutable -> int { return 0; }; // cxx23ext-warning {{is a C++23 extension}} + [](int) -> {}; // PR13652 expected-error {{expected a type}} return 1; } void designator_or_lambda() { - typedef int T; - const int b = 0; + typedef int T; + const int b = 0; const int c = 1; int d; int a1[1] = {[b] (T()) {}}; // expected-error{{no viable conversion from '(lambda}} @@ -49,19 +51,18 @@ class C { int a4[1] = {[&b] = 1 }; // expected-error{{integral constant expression must have integral or unscoped enumeration type, not 'const int *'}} int a5[3] = { []{return 0;}() }; int a6[1] = {[this] = 1 }; // expected-error{{integral constant expression must have integral or unscoped enumeration type, not 'C *'}} - int a7[1] = {[d(0)] { return d; } ()}; - int a8[1] = {[d = 0] { return d; } ()}; - int a10[1] = {[id(0)] { return id; } ()}; -#if __cplusplus <= 201103L - // expected-warning@-4{{extension}} - // expected-warning@-4{{extension}} - // expected-warning@-4{{extension}} + int a7[1] = {[d(0)] { return d; } ()}; // cxx14ext-warning {{initialized lambda captures are a C++14 extension}} + int a8[1] = {[d = 0] { return d; } ()}; // cxx14ext-warning {{initialized lambda captures are a C++14 extension}} +#if __cplusplus >= 201103L + int a10[1] = {[id(0)] { return id; } ()}; // cxx14ext-warning {{initialized lambda captures are a C++14 extension}} #endif int a9[1] = {[d = 0] = 1}; // expected-error{{is not an integral constant expression}} #if __cplusplus >= 201402L // expected-note@-2{{constant expression cannot modify an object that is visible outside that expression}} #endif +#if __cplusplus >= 201103L int a11[1] = {[id(0)] = 1}; +#endif } void delete_lambda(int *p) { @@ -80,43 +81,33 @@ class C { // We support init-captures in C++11 as an extension. int z; void init_capture() { - [n(0)] () mutable -> int { return ++n; }; - [n{0}] { return; }; - [a([&b = z]{})](){}; - [n = 0] { return ++n; }; // expected-error {{captured by copy in a non-mutable}} - [n = {0}] { return; }; // expected-error {{<initializer_list>}} -#if __cplusplus <= 201103L - // expected-warning@-6{{extension}} - // expected-warning@-6{{extension}} - // expected-warning@-6{{extension}} - // expected-warning@-7{{extension}} - // expected-warning@-7{{extension}} - // expected-warning@-7{{extension}} -#endif + [n(0)] () mutable -> int { return ++n; }; // cxx14ext-warning {{initialized lambda captures are a C++14 extension}} + [n{0}] { return; }; // cxx14ext-warning {{initialized lambda captures are a C++14 extension}} + [a([&b = z]{})](){}; // cxx14ext-warning 2 {{initialized lambda captures are a C++14 extension}} + [n = 0] { return ++n; }; // expected-error {{captured by copy in a non-mutable}} + // cxx14ext-warning@-1 {{initialized lambda captures are a C++14 extension}} + [n = {0}] { return; }; // expected-error {{<initializer_list>}} + // cxx14ext-warning@-1 {{initialized lambda captures are a C++14 extension}} int x = 4; - auto y = [&r = x, x = x + 1]() -> int { -#if __cplusplus <= 201103L - // expected-warning@-2{{extension}} - // expected-warning@-3{{extension}} -#endif + auto y = [&r = x, x = x + 1]() -> int { // cxx14ext-warning 2 {{initialized lambda captures are a C++14 extension}} r += 2; return x + 2; } (); } void attributes() { - [] __attribute__((noreturn)){}; -#if __cplusplus <= 202002L - // expected-warning@-2 {{is a C++23 extension}} -#endif + [] __attribute__((noreturn)){}; // cxx23ext-warning {{lambda without a parameter clause is a C++23 extension}} + []() [[]] mutable {}; // expected-error {{expected body of lambda expression}} []() [[]] {}; []() [[]] -> void {}; []() mutable [[]] -> void {}; +#if __cplusplus >= 201103L []() mutable noexcept [[]] -> void {}; +#endif // Testing GNU-style attributes on lambdas -- the attribute is specified // before the mutable specifier instead of after (unlike C++11). @@ -126,28 +117,18 @@ class C { // Testing support for P2173 on adding attributes to the declaration // rather than the type. - [][[]](){}; -#if __cplusplus <= 202002L - // expected-warning@-2 {{an attribute specifier sequence in this position is a C++23 extension}} -#endif -#if __cplusplus > 201703L - []<typename>[[]](){}; -#if __cplusplus <= 202002L - // expected-warning@-2 {{an attribute specifier sequence in this position is a C++23 extension}} -#endif -#endif - [][[]]{}; -#if __cplusplus <= 202002L - // expected-warning@-2 {{an attribute specifier sequence in this position is a C++23 extension}} -#endif + [][[]](){}; // cxx23ext-warning {{an attribute specifier sequence in this position is a C++23 extension}} + + []<typename>[[]](){}; // cxx20ext-warning {{explicit template parameter list for lambdas is a C++20 extension}} + // cxx23ext-warning@-1 {{an attribute specifier sequence in this position is a C++23 extension}} + + [][[]]{}; // cxx23ext-warning {{an attribute specifier sequence in this position is a C++23 extension}} } void missing_parens() { - [] mutable {}; - [] noexcept {}; -#if __cplusplus <= 202002L - // expected-warning@-3 {{is a C++23 extension}} - // expected-warning@-3 {{is a C++23 extension}} + [] mutable {}; // cxx23ext-warning {{is a C++23 extension}} +#if __cplusplus >= 201103L + [] noexcept {}; // cxx23ext-warning {{is a C++23 extension}} #endif } }; @@ -165,10 +146,7 @@ struct A { }; struct S { - void mf() { A{[*this]{}}; } -#if __cplusplus < 201703L - // expected-warning@-2 {{C++17 extension}} -#endif + void mf() { A(([*this]{})); } // cxx17ext-warning {{'*this' by copy is a C++17 extension}} }; } diff --git a/clang/test/Parser/cxx2b-lambdas.cpp b/clang/test/Parser/cxx2b-lambdas.cpp index ad975a17b6e476db538d234edb9dcc95f885a8f1..758ec9a42f56d58e309226e5084d49d9a20dbf59 100644 --- a/clang/test/Parser/cxx2b-lambdas.cpp +++ b/clang/test/Parser/cxx2b-lambdas.cpp @@ -1,30 +1,48 @@ +// RUN: %clang_cc1 -std=c++03 %s -verify -Wno-c++23-extensions -Wno-c++20-extensions -Wno-c++17-extensions -Wno-c++14-extensions -Wno-c++11-extensions +// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11 -Wno-c++23-extensions -Wno-c++20-extensions -Wno-c++17-extensions -Wno-c++14-extensions +// RUN: %clang_cc1 -std=c++14 %s -verify -Wno-c++23-extensions -Wno-c++20-extensions -Wno-c++17-extensions +// RUN: %clang_cc1 -std=c++17 %s -verify -Wno-c++23-extensions -Wno-c++20-extensions +// RUN: %clang_cc1 -std=c++20 %s -verify -Wno-c++23-extensions // RUN: %clang_cc1 -std=c++23 %s -verify auto LL0 = [] {}; auto LL1 = []() {}; auto LL2 = []() mutable {}; -auto LL3 = []() constexpr {}; +#if __cplusplus >= 201103L +auto LL3 = []() constexpr {}; // cxx11-error {{return type 'void' is not a literal type}} +#endif -auto L0 = [] constexpr {}; +#if __cplusplus >= 201103L +auto L0 = [] constexpr {}; // cxx11-error {{return type 'void' is not a literal type}} +#endif auto L1 = [] mutable {}; +#if __cplusplus >= 201103L auto L2 = [] noexcept {}; -auto L3 = [] constexpr mutable {}; -auto L4 = [] mutable constexpr {}; -auto L5 = [] constexpr mutable noexcept {}; +auto L3 = [] constexpr mutable {}; // cxx11-error {{return type 'void' is not a literal type}} +auto L4 = [] mutable constexpr {}; // cxx11-error {{return type 'void' is not a literal type}} +auto L5 = [] constexpr mutable noexcept {}; // cxx11-error {{return type 'void' is not a literal type}} +#endif auto L6 = [s = 1] mutable {}; -auto L7 = [s = 1] constexpr mutable noexcept {}; +#if __cplusplus >= 201103L +auto L7 = [s = 1] constexpr mutable noexcept {}; // cxx11-error {{return type 'void' is not a literal type}} +#endif auto L8 = [] -> bool { return true; }; auto L9 = []<typename T> { return true; }; +#if __cplusplus >= 201103L auto L10 = []<typename T> noexcept { return true; }; +#endif auto L11 = []<typename T> -> bool { return true; }; +#if __cplusplus >= 202002L auto L12 = [] consteval {}; auto L13 = []() requires true {}; // expected-error{{non-templated function cannot have a requires clause}} auto L14 = []<auto> requires true() requires true {}; auto L15 = []<auto> requires true noexcept {}; +#endif auto L16 = [] [[maybe_unused]]{}; -auto XL0 = [] mutable constexpr mutable {}; // expected-error{{cannot appear multiple times}} -auto XL1 = [] constexpr mutable constexpr {}; // expected-error{{cannot appear multiple times}} +#if __cplusplus >= 201103L +auto XL0 = [] mutable constexpr mutable {}; // expected-error{{cannot appear multiple times}} cxx11-error {{return type 'void' is not a literal type}} +auto XL1 = [] constexpr mutable constexpr {}; // expected-error{{cannot appear multiple times}} cxx11-error {{return type 'void' is not a literal type}} auto XL2 = []) constexpr mutable constexpr {}; // expected-error{{expected body of lambda expression}} auto XL3 = []( constexpr mutable constexpr {}; // expected-error{{invalid storage class specifier}} \ // expected-error{{function parameter cannot be constexpr}} \ @@ -33,16 +51,23 @@ auto XL3 = []( constexpr mutable constexpr {}; // expected-error{{invalid storag // expected-note{{to match this '('}} \ // expected-error{{expected body}} \ // expected-warning{{duplicate 'constexpr'}} +#endif // http://llvm.org/PR49736 auto XL4 = [] requires true {}; // expected-error{{expected body}} +#if __cplusplus >= 201703L auto XL5 = []<auto> requires true requires true {}; // expected-error{{expected body}} auto XL6 = []<auto> requires true noexcept requires true {}; // expected-error{{expected body}} +#endif auto XL7 = []() static static {}; // expected-error {{cannot appear multiple times}} auto XL8 = []() static mutable {}; // expected-error {{cannot be both mutable and static}} +#if __cplusplus >= 202002L auto XL9 = []() static consteval {}; -auto XL10 = []() static constexpr {}; +#endif +#if __cplusplus >= 201103L +auto XL10 = []() static constexpr {}; // cxx11-error {{return type 'void' is not a literal type}} +#endif auto XL11 = [] static {}; auto XL12 = []() static {}; @@ -67,6 +92,7 @@ void static_captures() { }; } +#if __cplusplus >= 201703L constexpr auto static_capture_constexpr() { char n = 'n'; return [n] static { return n; }(); // expected-error {{a static lambda cannot have any captures}} @@ -78,3 +104,4 @@ constexpr auto capture_constexpr() { return [n] { return n; }(); } static_assert(capture_constexpr()); +#endif diff --git a/clang/test/Parser/objcxx-lambda-expressions-neg.mm b/clang/test/Parser/objcxx-lambda-expressions-neg.mm index b2fe39dfbf70827fd77dee668977b519102b3caa..795157816dcfdb9eb3cc5ff17590f018dec2303c 100644 --- a/clang/test/Parser/objcxx-lambda-expressions-neg.mm +++ b/clang/test/Parser/objcxx-lambda-expressions-neg.mm @@ -1,13 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify %s -// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify -std=c++98 %s +// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=cxx03 -std=c++98 %s // RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify -std=c++11 %s int main() { - []{}; -#if __cplusplus <= 199711L - // expected-error@-2 {{expected expression}} -#else + []{}; // cxx03-warning {{lambdas are a C++11 extension}} // expected-no-diagnostics -#endif - } diff --git a/clang/test/ParserHLSL/group_shared.hlsl b/clang/test/ParserHLSL/group_shared.hlsl index 0b9f28395ee486f382ecba76475f1284aee3f0ef..44f3a2e5b4505d0cd2899b9131ecef4eaa55dd04 100644 --- a/clang/test/ParserHLSL/group_shared.hlsl +++ b/clang/test/ParserHLSL/group_shared.hlsl @@ -3,8 +3,8 @@ extern groupshared float f; extern float groupshared f; // Ok, redeclaration? -// NOTE:lambda is not enabled except for hlsl202x. -// expected-error@+2 {{expected expression}} +// expected-warning@+3 {{lambdas are a C++11 extension}} +// expected-error@+2 {{expected body of lambda expression}} // expected-warning@+1 {{'auto' type specifier is a C++11 extension}} auto l = []() groupshared {}; diff --git a/clang/test/Preprocessor/aarch64-target-features.c b/clang/test/Preprocessor/aarch64-target-features.c index 6ec4dcd60cf6010104585525a7f2a1a2b1edda60..85762b7fed4d719aad07a251cb8a30611290db0b 100644 --- a/clang/test/Preprocessor/aarch64-target-features.c +++ b/clang/test/Preprocessor/aarch64-target-features.c @@ -196,7 +196,7 @@ // CHECK-8_6-NOT: __ARM_FEATURE_SHA3 1 // CHECK-8_6-NOT: __ARM_FEATURE_SM4 1 -// RUN: %clang -target aarch64-none-linux-gnu -march=armv8.6-a+sve -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE-8_6 %s +// RUN: %clang -target aarch64-none-linux-gnu -march=armv8.6-a+sve+f32mm -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE-8_6 %s // CHECK-SVE-8_6: __ARM_FEATURE_SVE 1 // CHECK-SVE-8_6: __ARM_FEATURE_SVE_BF16 1 // CHECK-SVE-8_6: __ARM_FEATURE_SVE_MATMUL_FP32 1 @@ -342,15 +342,15 @@ // RUN: %clang -target aarch64 -march=armv8-a+fp+simd+crc+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-1 %s // RUN: %clang -target aarch64 -march=armv8-a+nofp+nosimd+nocrc+nocrypto+fp+simd+crc+crypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-1 %s -// RUN: %clang -target aarch64 -march=armv8-a+nofp+nosimd+nocrc+nocrypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-2 %s -// RUN: %clang -target aarch64 -march=armv8-a+fp+simd+crc+crypto+nofp+nosimd+nocrc+nocrypto -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-2 %s +// RUN: %clang -target aarch64 -march=armv8-a+nofp+nosimd+nocrc+nocrypto -mabi=aapcs-soft -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-2 %s +// RUN: %clang -target aarch64 -march=armv8-a+fp+simd+crc+crypto+nofp+nosimd+nocrc+nocrypto -mabi=aapcs-soft -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-2 %s // RUN: %clang -target aarch64 -march=armv8-a+nosimd -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MARCH-3 %s // CHECK-MARCH-1: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "+v8a" "-target-feature" "+aes" "-target-feature" "+crc" "-target-feature" "+crypto" "-target-feature" "+fp-armv8" "-target-feature" "+sha2" "-target-feature" "+neon" // CHECK-MARCH-2: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "-fp-armv8"{{.*}} "-target-feature" "-neon" // CHECK-MARCH-3: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-feature" "-neon" // While we're checking +nofp, also make sure it stops defining __ARM_FP -// RUN: %clang -target aarch64-none-linux-gnu -march=armv8-r+nofp -x c -E -dM %s -o - | FileCheck -check-prefix=CHECK-NOFP %s +// RUN: %clang -target aarch64-none-linux-gnu -march=armv8-r+nofp -mabi=aapcs-soft -x c -E -dM %s -o - | FileCheck -check-prefix=CHECK-NOFP %s // CHECK-NOFP-NOT: #define __ARM_FP{{ }} // Check +sm4: diff --git a/clang/test/Preprocessor/bpf-predefined-macros.c b/clang/test/Preprocessor/bpf-predefined-macros.c index fea24d1ea0ff7bede175acbf2bef2d113206ff9a..246cbfa2d6ab7db1d52c925e69c72c9e2aac0ba3 100644 --- a/clang/test/Preprocessor/bpf-predefined-macros.c +++ b/clang/test/Preprocessor/bpf-predefined-macros.c @@ -61,7 +61,7 @@ int r; #ifdef __BPF_FEATURE_ST int s; #endif -#ifdef __BPF_FEATURE_ARENA_CAST +#ifdef __BPF_FEATURE_ADDR_SPACE_CAST int t; #endif diff --git a/clang/test/Preprocessor/empty_va_arg.cpp b/clang/test/Preprocessor/empty_va_arg.cpp index 2ee431f6bde83805dc232808240836e228e45895..7c7d49d8fb16326fc0cdc424bd5f8b6f76346f14 100644 --- a/clang/test/Preprocessor/empty_va_arg.cpp +++ b/clang/test/Preprocessor/empty_va_arg.cpp @@ -1,12 +1,16 @@ -// RUN: %clang_cc1 -Eonly -std=c++17 -pedantic -verify %s -// RUN: %clang_cc1 -Eonly -std=c17 -pedantic -verify -x c %s -// RUN: %clang_cc1 -Eonly -std=c++20 -pedantic -Wpre-c++20-compat -verify=compat %s +// RUN: %clang_cc1 -Eonly -std=c17 -pedantic -verify=c17,expected -x c %s +// RUN: %clang_cc1 -Eonly -std=c23 -pedantic -Wpre-c23-compat -verify=c23,expected -x c %s +// RUN: %clang_cc1 -Eonly -std=c++17 -pedantic -verify=cxx17,expected %s +// RUN: %clang_cc1 -Eonly -std=c++20 -pedantic -Wpre-c++20-compat -verify=cxx20,expected %s -#define FOO(x, ...) // expected-note {{macro 'FOO' defined here}} \ - // compat-note {{macro 'FOO' defined here}} +// silent-no-diagnostics + +#define FOO(x, ...) // expected-note {{macro 'FOO' defined here}} int main() { - FOO(42) // expected-warning {{must specify at least one argument for '...' parameter of variadic macro}} \ - // compat-warning {{passing no argument for the '...' parameter of a variadic macro is incompatible with C++ standards before C++20}} + FOO(42) // c17-warning {{passing no argument for the '...' parameter of a variadic macro is a C23 extension}} \ + // cxx17-warning {{passing no argument for the '...' parameter of a variadic macro is a C++20 extension}} \ + // c23-warning {{passing no argument for the '...' parameter of a variadic macro is incompatible with C standards before C23}} \ + // cxx20-warning {{passing no argument for the '...' parameter of a variadic macro is incompatible with C++ standards before C++20}} } diff --git a/clang/test/Preprocessor/macro_fn.c b/clang/test/Preprocessor/macro_fn.c index 5f4ea0e26d5d8b643ec2b535489ae8f502002cc3..81d836321407886609917311c0b939abba95f641 100644 --- a/clang/test/Preprocessor/macro_fn.c +++ b/clang/test/Preprocessor/macro_fn.c @@ -37,8 +37,8 @@ e(x) e() zero_dot() -one_dot(x) /* empty ... argument: expected-warning {{must specify at least one argument for '...' parameter of variadic macro}} */ -one_dot() /* empty first argument, elided ...: expected-warning {{must specify at least one argument for '...' parameter of variadic macro}} */ +one_dot(x) /* empty ... argument: expected-warning {{passing no argument for the '...' parameter of a variadic macro is a C23 extension}} */ +one_dot() /* empty first argument, elided ...: expected-warning {{passing no argument for the '...' parameter of a variadic macro is a C23 extension}} */ /* Crash with function-like macro test at end of directive. */ diff --git a/clang/test/Preprocessor/ptrauth_feature.c b/clang/test/Preprocessor/ptrauth_feature.c new file mode 100644 index 0000000000000000000000000000000000000000..e45c6ea90fd11f611de5a3be8cfb37c20ace1d10 --- /dev/null +++ b/clang/test/Preprocessor/ptrauth_feature.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 %s -E -triple=arm64-- | FileCheck %s --check-prefixes=NOINTRIN +// RUN: %clang_cc1 %s -E -triple=arm64-- -fptrauth-intrinsics | FileCheck %s --check-prefixes=INTRIN + +#if __has_feature(ptrauth_intrinsics) +// INTRIN: has_ptrauth_intrinsics +void has_ptrauth_intrinsics() {} +#else +// NOINTRIN: no_ptrauth_intrinsics +void no_ptrauth_intrinsics() {} +#endif diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c index 1a15be1c6e4dc13642db0a4b315f688fc2d8eac1..dfc6d18dee504ee942c380a6844c325e97b519a5 100644 --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -56,11 +56,14 @@ // CHECK-NOT: __riscv_xcvmac {{.*$}} // CHECK-NOT: __riscv_xcvmem {{.*$}} // CHECK-NOT: __riscv_xcvsimd {{.*$}} +// CHECK-NOT: __riscv_xsfcease {{.*$}} // CHECK-NOT: __riscv_xsfvcp {{.*$}} // CHECK-NOT: __riscv_xsfvfnrclipxfqf {{.*$}} // CHECK-NOT: __riscv_xsfvfwmaccqqq {{.*$}} // CHECK-NOT: __riscv_xsfqmaccdod {{.*$}} // CHECK-NOT: __riscv_xsfvqmaccqoq {{.*$}} +// CHECK-NOT: __riscv_xsifivecdiscarddlone {{.*$}} +// CHECK-NOT: __riscv_xsifivecflushdlone {{.*$}} // CHECK-NOT: __riscv_xtheadba {{.*$}} // CHECK-NOT: __riscv_xtheadbb {{.*$}} // CHECK-NOT: __riscv_xtheadbs {{.*$}} @@ -517,6 +520,14 @@ // RUN: -o - | FileCheck --check-prefix=CHECK-XCVSIMD-EXT %s // CHECK-XCVSIMD-EXT: __riscv_xcvsimd 1000000{{$}} +// RUN: %clang --target=riscv32-unknown-linux-gnu \ +// RUN: -march=rv32ixsfcease -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-XSFCEASE-EXT %s +// RUN: %clang --target=riscv64-unknown-linux-gnu \ +// RUN: -march=rv64ixsfcease -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-XSFCEASE-EXT %s +// CHECK-XSFCEASE-EXT: __riscv_xsfcease 1000000{{$}} + // RUN: %clang --target=riscv32-unknown-linux-gnu \ // RUN: -march=rv32ixsfvcp -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-XSFVCP-EXT %s @@ -557,6 +568,22 @@ // RUN: -o - | FileCheck --check-prefix=CHECK-XSFVQMACCQOQ-EXT %s // CHECK-XSFVQMACCQOQ-EXT: __riscv_xsfvqmaccqoq 1000000{{$}} +// RUN: %clang --target=riscv32-unknown-linux-gnu \ +// RUN: -march=rv32ixsifivecdiscarddlone -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-XSIFIVECDISCARDDLONE-EXT %s +// RUN: %clang --target=riscv64-unknown-linux-gnu \ +// RUN: -march=rv64ixsifivecdiscarddlone -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-XSIFIVECDISCARDDLONE-EXT %s +// CHECK-XSIFIVECDISCARDDLONE-EXT: __riscv_xsifivecdiscarddlone 1000000{{$}} + +// RUN: %clang --target=riscv32-unknown-linux-gnu \ +// RUN: -march=rv32ixsifivecflushdlone -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-XSIFIVECFLUSHDLONE-EXT %s +// RUN: %clang --target=riscv64-unknown-linux-gnu \ +// RUN: -march=rv64ixsifivecflushdlone -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-XSIFIVECFLUSHDLONE-EXT %s +// CHECK-XSIFIVECFLUSHDLONE-EXT: __riscv_xsifivecflushdlone 1000000{{$}} + // RUN: %clang --target=riscv32-unknown-linux-gnu \ // RUN: -march=rv32ixtheadba -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-XTHEADBA-EXT %s @@ -1639,9 +1666,9 @@ // CHECK-MISALIGNED-AVOID: __riscv_misaligned_avoid 1 // RUN: %clang --target=riscv32-unknown-linux-gnu -march=rv32i -E -dM %s \ -// RUN: -munaligned-access -o - | FileCheck %s --check-prefix=CHECK-MISALIGNED-FAST +// RUN: -mno-strict-align -o - | FileCheck %s --check-prefix=CHECK-MISALIGNED-FAST // RUN: %clang --target=riscv64-unknown-linux-gnu -march=rv64i -E -dM %s \ -// RUN: -munaligned-access -o - | FileCheck %s --check-prefix=CHECK-MISALIGNED-FAST +// RUN: -mno-strict-align -o - | FileCheck %s --check-prefix=CHECK-MISALIGNED-FAST // RUN: %clang --target=riscv64-unknown-linux-gnu -mcpu=sifive-p450 -E -dM %s \ // RUN: -o - | FileCheck %s --check-prefix=CHECK-MISALIGNED-FAST // CHECK-MISALIGNED-FAST: __riscv_misaligned_fast 1 diff --git a/clang/test/Preprocessor/sysroot-prefix.c b/clang/test/Preprocessor/sysroot-prefix.c index 08c72f53b44e9f8dd16d6b00cc4b480dd1f22185..eff71f5e3d5a3642dd57067745c7a0119479e18c 100644 --- a/clang/test/Preprocessor/sysroot-prefix.c +++ b/clang/test/Preprocessor/sysroot-prefix.c @@ -4,6 +4,16 @@ // RUN: %clang_cc1 -v -isysroot /var/empty -I =null -E %s -o /dev/null 2>&1 | FileCheck -check-prefix CHECK-ISYSROOT_SYSROOT_NULL %s // RUN: %clang_cc1 -v -isysroot /var/empty -isysroot /var/empty/root -I =null -E %s -o /dev/null 2>&1 | FileCheck -check-prefix CHECK-ISYSROOT_ISYSROOT_SYSROOT_NULL %s // RUN: %clang_cc1 -v -isysroot /var/empty/root -isysroot /var/empty -I =null -E %s -o /dev/null 2>&1 | FileCheck -check-prefix CHECK-ISYSROOT_ISYSROOT_SWAPPED_SYSROOT_NULL %s +// RUN: %clang_cc1 -v -isystem=/usr/include -isysroot /var/empty -E %s -o /dev/null 2>&1 | FileCheck -check-prefix CHECK-ISYSROOT_ISYSTEM_SYSROOT %s +// RUN: %clang_cc1 -v -isystem=/usr/include -E %s -o /dev/null 2>&1 | FileCheck -check-prefix CHECK-ISYSROOT_ISYSTEM_NO_SYSROOT %s +// RUN: %clang_cc1 -v -iquote=/usr/include -isysroot /var/empty -E %s -o /dev/null 2>&1 | FileCheck -check-prefix CHECK-ISYSROOT_IQUOTE_SYSROOT %s +// RUN: %clang_cc1 -v -iquote=/usr/include -E %s -o /dev/null 2>&1 | FileCheck -check-prefix CHECK-ISYSROOT_IQUOTE_NO_SYSROOT %s +// RUN: %clang_cc1 -v -idirafter=/usr/include -isysroot /var/empty -E %s -o /dev/null 2>&1 | FileCheck -check-prefix CHECK-ISYSROOT_IDIRAFTER_SYSROOT %s +// RUN: %clang_cc1 -v -idirafter=/usr/include -E %s -o /dev/null 2>&1 | FileCheck -check-prefix CHECK-ISYSROOT_IDIRAFTER_NO_SYSROOT %s +// RUN: %clang_cc1 -v -isysroot /var/empty -isystem=/usr/include -iwithsysroot /opt/include -isystem=/usr/local/include -E %s -o /dev/null 2>&1 | FileCheck -check-prefix CHECK-INTERLEAVE_I_PATHS %s + +// RUN: not %clang_cc1 -v -isysroot /var/empty -E %s -o /dev/null -I 2>&1 | FileCheck -check-prefix CHECK-EMPTY_I_PATH %s +// RUN: %clang_cc1 -v -isysroot /var/empty/usr -E %s -o /dev/null -I= 2>&1 | FileCheck -check-prefix CHECK-SYSROOT_I_PATH %s // CHECK-ISYSROOT_NO_SYSROOT: ignoring nonexistent directory "/var/empty/include" // CHECK-ISYSROOT_NO_SYSROOT-NOT: ignoring nonexistent directory "/var/empty/var/empty/include" @@ -23,3 +33,18 @@ // CHECK-ISYSROOT_ISYSROOT_SWAPPED_SYSROOT_NULL: ignoring nonexistent directory "/var/empty{{.}}null" // CHECK-ISYSROOT_ISYSROOT_SWAPPED_SYSROOT_NULL-NOT: ignoring nonexistent directory "=null" +// CHECK-ISYSROOT_ISYSTEM_SYSROOT: ignoring nonexistent directory "/var/empty/usr/include" +// CHECK-ISYSROOT_ISYSTEM_NO_SYSROOT: ignoring nonexistent directory "=/usr/include" + +// CHECK-ISYSROOT_IQUOTE_SYSROOT: ignoring nonexistent directory "/var/empty/usr/include" +// CHECK-ISYSROOT_IQUOTE_NO_SYSROOT: ignoring nonexistent directory "=/usr/include" + +// CHECK-ISYSROOT_IDIRAFTER_SYSROOT: ignoring nonexistent directory "/var/empty/usr/include" +// CHECK-ISYSROOT_IDIRAFTER_NO_SYSROOT: ignoring nonexistent directory "=/usr/include" + +// CHECK-INTERLEAVE_I_PATHS: ignoring nonexistent directory "/var/empty/usr/include" +// CHECK-INTERLEAVE_I_PATHS: ignoring nonexistent directory "/var/empty/opt/include" +// CHECK-INTERLEAVE_I_PATHS: ignoring nonexistent directory "/var/empty/usr/local/include" + +// CHECK-EMPTY_I_PATH: argument to '-I' is missing +// CHECK-SYSROOT_I_PATH: ignoring nonexistent directory "/var/empty/usr{{/|\\}}" diff --git a/clang/test/Sema/GH70594.cpp b/clang/test/Sema/GH70594.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ce98e9b12b5cba3eb2e5c35e7d540d7ec66d3a65 --- /dev/null +++ b/clang/test/Sema/GH70594.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify +// RUN: %clang_cc1 -fsyntax-only -std=c++23 %s -verify + +// expected-no-diagnostics + +struct A {}; +using CA = const A; + +struct S1 : CA { + constexpr S1() : CA() {} +}; + +struct S2 : A { + constexpr S2() : CA() {} +}; + +struct S3 : CA { + constexpr S3() : A() {} +}; + +struct Int {}; + +template <class _Hp> +struct __tuple_leaf : _Hp { + constexpr __tuple_leaf() : _Hp() {} +}; + +constexpr __tuple_leaf<const Int> t; diff --git a/clang/test/Sema/PR84368.cpp b/clang/test/Sema/PR84368.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6551df29358920b2719e8843185e24add437d83e --- /dev/null +++ b/clang/test/Sema/PR84368.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++20 -verify %s +// RUN: %clang_cc1 -std=c++23 -verify %s +// expected-no-diagnostics + +template<class T> concept IsOk = requires() { typename T::Float; }; + +template<IsOk T> struct Thing; + +template<IsOk T> struct Foobar { + template<int> struct Inner { + template<IsOk T2> friend struct Thing; + }; +}; + +struct MyType { using Float=float; }; +Foobar<MyType>::Inner<0> foobar; diff --git a/clang/test/Sema/PR85343.cpp b/clang/test/Sema/PR85343.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d90ef19d42345517090f81fd5d55642b28bf3c47 --- /dev/null +++ b/clang/test/Sema/PR85343.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++14 -verify %s +// expected-no-diagnostics + +template <typename c> auto ab() -> c ; + +template <typename> struct e {}; + +template <typename f> struct ac { + template <typename h> static e<decltype(ab<h>()(ab<int>))> i; + decltype(i<f>) j; +}; + +struct d { + template <typename f> + d(f) { + ac<f> a; + } +}; +struct a { + d b = [=](auto) { (void)[this] {}; }; +}; +void b() { new a; } diff --git a/clang/test/Sema/aarch64-sme-func-attrs.c b/clang/test/Sema/aarch64-sme-func-attrs.c index 47dbeca206a94e67b02004f3dda2c6677aafb77a..bfc8768c3f36e1c0c07cf1b1362275870aca2323 100644 --- a/clang/test/Sema/aarch64-sme-func-attrs.c +++ b/clang/test/Sema/aarch64-sme-func-attrs.c @@ -483,14 +483,16 @@ void just_fine(void) {} __arm_locally_streaming __attribute__((target_version("sme2"))) -void just_fine_locally_streaming(void) {} +void incompatible_locally_streaming(void) {} +// expected-error@-1 {{attribute 'target_version' multiversioning cannot be combined with attribute '__arm_locally_streaming'}} +// expected-cpp-error@-2 {{attribute 'target_version' multiversioning cannot be combined with attribute '__arm_locally_streaming'}} __attribute__((target_version("default"))) -void just_fine_locally_streaming(void) {} +void incompatible_locally_streaming(void) {} void fmv_caller() { cannot_work_version(); cannot_work_clones(); just_fine(); - just_fine_locally_streaming(); + incompatible_locally_streaming(); } diff --git a/clang/test/Sema/arm-vector-types-support.c b/clang/test/Sema/arm-vector-types-support.c index 83a83ddfe780170cde85da81058b22d425ced113..ed5f5ba175a94a4e94f618cbb2862624b6fb3259 100644 --- a/clang/test/Sema/arm-vector-types-support.c +++ b/clang/test/Sema/arm-vector-types-support.c @@ -1,4 +1,6 @@ // RUN: %clang_cc1 %s -triple armv7 -fsyntax-only -verify +// RUN: %clang_cc1 %s -triple aarch64 -fsyntax-only -verify +// RUN: %clang_cc1 %s -triple aarch64 -target-feature -fp-armv8 -target-abi aapcs-soft -fsyntax-only -verify typedef __attribute__((neon_vector_type(2))) int int32x2_t; // expected-error{{'neon_vector_type' attribute is not supported on targets missing 'neon', 'mve', 'sve' or 'sme'; specify an appropriate -march= or -mcpu=}} typedef __attribute__((neon_polyvector_type(16))) short poly8x16_t; // expected-error{{'neon_polyvector_type' attribute is not supported on targets missing 'neon' or 'mve'; specify an appropriate -march= or -mcpu=}} diff --git a/clang/test/Sema/attr-cleanup.c b/clang/test/Sema/attr-cleanup.c index 2c38687622c2bbc3ccaf148b7d9ef577b93e6990..95baf2e675a086695d159f41cafeccc2da74e7b8 100644 --- a/clang/test/Sema/attr-cleanup.c +++ b/clang/test/Sema/attr-cleanup.c @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 %s -verify -fsyntax-only +// RUN: %clang_cc1 -Wfree-nonheap-object -fsyntax-only -verify %s void c1(int *a); - +typedef __typeof__(sizeof(0)) size_t; extern int g1 __attribute((cleanup(c1))); // expected-warning {{'cleanup' attribute only applies to local variables}} int g2 __attribute((cleanup(c1))); // expected-warning {{'cleanup' attribute only applies to local variables}} static int g3 __attribute((cleanup(c1))); // expected-warning {{'cleanup' attribute only applies to local variables}} @@ -48,3 +48,27 @@ void t6(void) { } void t7(__attribute__((cleanup(c4))) int a) {} // expected-warning {{'cleanup' attribute only applies to local variables}} + +extern void free(void *); +extern void *malloc(size_t size); +void t8(void) { + void *p + __attribute__(( + cleanup( + free // expected-warning{{attempt to call free on non-heap object 'p'}} + ) + )) + = malloc(10); +} +typedef __attribute__((aligned(2))) int Aligned2Int; +void t9(void){ + Aligned2Int __attribute__((cleanup(c1))) xwarn; // expected-warning{{passing 2-byte aligned argument to 4-byte aligned parameter 1 of 'c1' may result in an unaligned pointer access}} +} + +__attribute__((enforce_tcb("TCB1"))) void func1(int *x) { + *x = 5; +} +__attribute__((enforce_tcb("TCB2"))) void t10() { + int __attribute__((cleanup(func1))) x = 5; // expected-warning{{calling 'func1' is a violation of trusted computing base 'TCB2'}} +} + diff --git a/clang/test/Sema/attr-counted-by.c b/clang/test/Sema/attr-counted-by.c index f14da9c77fa8b42bb7d955b67150ffc8d4ffcb22..d5d4ebf55739223ffaeca33f48498525e08dd51b 100644 --- a/clang/test/Sema/attr-counted-by.c +++ b/clang/test/Sema/attr-counted-by.c @@ -11,16 +11,64 @@ struct not_found { struct no_found_count_not_in_substruct { unsigned long flags; - unsigned char count; // expected-note {{field 'count' declared here}} + unsigned char count; // expected-note {{'count' declared here}} struct A { int dummy; int array[] __counted_by(count); // expected-error {{'counted_by' field 'count' isn't within the same struct as the flexible array}} } a; }; +struct not_found_count_not_in_unnamed_substruct { + unsigned char count; // expected-note {{'count' declared here}} + struct { + int dummy; + int array[] __counted_by(count); // expected-error {{'counted_by' field 'count' isn't within the same struct as the flexible array}} + } a; +}; + +struct not_found_count_not_in_unnamed_substruct_2 { + struct { + unsigned char count; // expected-note {{'count' declared here}} + }; + struct { + int dummy; + int array[] __counted_by(count); // expected-error {{'counted_by' field 'count' isn't within the same struct as the flexible array}} + } a; +}; + +struct not_found_count_in_other_unnamed_substruct { + struct { + unsigned char count; + } a1; + + struct { + int dummy; + int array[] __counted_by(count); // expected-error {{use of undeclared identifier 'count'}} + }; +}; + +struct not_found_count_in_other_substruct { + struct _a1 { + unsigned char count; + } a1; + + struct { + int dummy; + int array[] __counted_by(count); // expected-error {{use of undeclared identifier 'count'}} + }; +}; + +struct not_found_count_in_other_substruct_2 { + struct _a2 { + unsigned char count; + } a2; + + int array[] __counted_by(count); // expected-error {{use of undeclared identifier 'count'}} +}; + struct not_found_suggest { - int bork; // expected-note {{'bork' declared here}} - struct bar *fam[] __counted_by(blork); // expected-error {{use of undeclared identifier 'blork'; did you mean 'bork'?}} + int bork; + struct bar *fam[] __counted_by(blork); // expected-error {{use of undeclared identifier 'blork'}} }; int global; // expected-note {{'global' declared here}} @@ -32,17 +80,17 @@ struct found_outside_of_struct { struct self_referrential { int bork; - struct bar *self[] __counted_by(self); // expected-error {{'counted_by' cannot refer to the flexible array 'self'}} + struct bar *self[] __counted_by(self); // expected-error {{use of undeclared identifier 'self'}} }; struct non_int_count { - double dbl_count; // expected-note {{field 'dbl_count' declared here}} - struct bar *fam[] __counted_by(dbl_count); // expected-error {{field 'dbl_count' in 'counted_by' must be a non-boolean integer type}} + double dbl_count; + struct bar *fam[] __counted_by(dbl_count); // expected-error {{'counted_by' requires a non-boolean integer type argument}} }; struct array_of_ints_count { - int integers[2]; // expected-note {{field 'integers' declared here}} - struct bar *fam[] __counted_by(integers); // expected-error {{field 'integers' in 'counted_by' must be a non-boolean integer type}} + int integers[2]; + struct bar *fam[] __counted_by(integers); // expected-error {{'counted_by' requires a non-boolean integer type argument}} }; struct not_a_fam { @@ -58,7 +106,7 @@ struct not_a_c99_fam { struct annotated_with_anon_struct { unsigned long flags; struct { - unsigned char count; // expected-note {{'count' declared here}} - int array[] __counted_by(crount); // expected-error {{use of undeclared identifier 'crount'; did you mean 'count'?}} + unsigned char count; + int array[] __counted_by(crount); // expected-error {{use of undeclared identifier 'crount'}} }; }; diff --git a/clang/test/Sema/attr-target-clones-aarch64.c b/clang/test/Sema/attr-target-clones-aarch64.c index 0ce277f41884c6dffc39606fd3cae75c1046b172..bc3fceab82825bff5f20fd69aa529d5bc6b2d288 100644 --- a/clang/test/Sema/attr-target-clones-aarch64.c +++ b/clang/test/Sema/attr-target-clones-aarch64.c @@ -27,7 +27,7 @@ int __attribute__((target_clones("rng", "fp16fml+fp", "default"))) redecl4(void) int __attribute__((target_clones("dgh+memtag+rpres+ls64_v", "ebf16+dpb+sha1", "default"))) redecl4(void) { return 1; } int __attribute__((target_version("flagm2"))) redef2(void) { return 1; } -// expected-error@+2 {{multiversioning attributes cannot be combined}} +// expected-error@+2 {{multiversioned function redeclarations require identical target attributes}} // expected-note@-2 {{previous declaration is here}} int __attribute__((target_clones("flagm2", "default"))) redef2(void) { return 1; } diff --git a/clang/test/Sema/attr-target-version.c b/clang/test/Sema/attr-target-version.c index e2940c434c2ff5f2528a1eb1947efecb73022b33..cd5be459456eb70e6a15ea2ecf32caab4c21ba32 100644 --- a/clang/test/Sema/attr-target-version.c +++ b/clang/test/Sema/attr-target-version.c @@ -68,13 +68,15 @@ int __attribute__((target_version(""))) unsup1(void) { return 1; } void __attribute__((target_version("crc32"))) unsup2(void) {} void __attribute__((target_version("default+fp16"))) koo(void) {} +//expected-error@-1 {{function multiversioning doesn't support feature 'default'}} void __attribute__((target_version("default+default+default"))) loo(void) {} +//expected-error@-1 {{function multiversioning doesn't support feature 'default'}} void __attribute__((target_version("rdm+rng+crc"))) redef(void) {} //expected-error@+2 {{redefinition of 'redef'}} //expected-note@-2 {{previous definition is here}} void __attribute__((target_version("rdm+rng+crc"))) redef(void) {} -int __attribute__((target_version("sm4"))) def(void); +int def(void); void __attribute__((target_version("dit"))) nodef(void); void __attribute__((target_version("ls64"))) nodef(void); void __attribute__((target_version("aes"))) ovl(void); @@ -83,7 +85,6 @@ int bar() { // expected-error@+2 {{reference to overloaded function could not be resolved; did you mean to call it?}} // expected-note@-3 {{possible target for call}} ovl++; - // expected-error@+1 {{no matching function for call to 'nodef'}} nodef(); return def(); } @@ -92,8 +93,6 @@ int __attribute__((target_version("sha1"))) def(void) { return 1; } int __attribute__((target_version("sve"))) prot(); // expected-error@-1 {{multiversioned function must have a prototype}} -// expected-note@+1 {{function multiversioning caused by this declaration}} -int __attribute__((target_version("fcma"))) prot(); int __attribute__((target_version("pmull"))) rtype(int); // expected-error@+1 {{multiversioned function declaration has a different return type}} @@ -104,6 +103,7 @@ int __attribute__((target_version("sha2"))) combine(void) { return 1; } int __attribute__((aarch64_vector_pcs, target_version("sha3"))) combine(void) { return 2; } int __attribute__((target_version("fp+aes+pmull+rcpc"))) unspec_args() { return -1; } +// expected-error@-1 {{multiversioned function must have a prototype}} // expected-error@+1 {{multiversioned function must have a prototype}} int __attribute__((target_version("default"))) unspec_args() { return 0; } int cargs() { return unspec_args(); } diff --git a/clang/test/Sema/builtin-popcountg.c b/clang/test/Sema/builtin-popcountg.c deleted file mode 100644 index 9d095927d24e1a2430739301dd3848b7cab86580..0000000000000000000000000000000000000000 --- a/clang/test/Sema/builtin-popcountg.c +++ /dev/null @@ -1,23 +0,0 @@ -// RUN: %clang_cc1 -std=c23 -triple=x86_64-pc-linux-gnu -fsyntax-only -verify -Wpedantic %s - -typedef int int2 __attribute__((ext_vector_type(2))); - -void test_builtin_popcountg(short s, int i, __int128 i128, _BitInt(128) bi128, - double d, int2 i2) { - __builtin_popcountg(); - // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} - __builtin_popcountg(i, i); - // expected-error@-1 {{too many arguments to function call, expected 1, have 2}} - __builtin_popcountg(s); - // expected-error@-1 {{1st argument must be a type of unsigned integer (was 'short')}} - __builtin_popcountg(i); - // expected-error@-1 {{1st argument must be a type of unsigned integer (was 'int')}} - __builtin_popcountg(i128); - // expected-error@-1 {{1st argument must be a type of unsigned integer (was '__int128')}} - __builtin_popcountg(bi128); - // expected-error@-1 {{1st argument must be a type of unsigned integer (was '_BitInt(128)')}} - __builtin_popcountg(d); - // expected-error@-1 {{1st argument must be a type of unsigned integer (was 'double')}} - __builtin_popcountg(i2); - // expected-error@-1 {{1st argument must be a type of unsigned integer (was 'int2' (vector of 2 'int' values))}} -} diff --git a/clang/test/Sema/builtins-arm64.c b/clang/test/Sema/builtins-arm64.c index e711121f7260ffcdeac230b77697fa2879b07a13..f094162b3aadc98700ab850b5e9c5b2eb9259b34 100644 --- a/clang/test/Sema/builtins-arm64.c +++ b/clang/test/Sema/builtins-arm64.c @@ -29,3 +29,12 @@ void test_prefetch(void) { __builtin_arm_prefetch(0, 0, 0, 2, 0); // expected-error-re {{argument value {{.*}} is outside the valid range}} __builtin_arm_prefetch(0, 0, 0, 0, 2); // expected-error-re {{argument value {{.*}} is outside the valid range}} } + +void test_trap(short s, unsigned short us) { + __builtin_arm_trap(42); + __builtin_arm_trap(65535); + __builtin_arm_trap(-1); + __builtin_arm_trap(65536); // expected-warning {{implicit conversion from 'int' to 'unsigned short' changes value from 65536 to 0}} + __builtin_arm_trap(s); // expected-error {{argument to '__builtin_arm_trap' must be a constant integer}} + __builtin_arm_trap(us); // expected-error {{argument to '__builtin_arm_trap' must be a constant integer}} +} \ No newline at end of file diff --git a/clang/test/Sema/complex-arithmetic.c b/clang/test/Sema/complex-arithmetic.c new file mode 100644 index 0000000000000000000000000000000000000000..c9e84da6daa9dcc3bfefff9bc3848e1d74cc8ce4 --- /dev/null +++ b/clang/test/Sema/complex-arithmetic.c @@ -0,0 +1,115 @@ +// RUN: %clang_cc1 -verify %s +// expected-no-diagnostics + +// This tests evaluation of _Complex arithmetic at compile time. + +#define APPROX_EQ(a, b) ( \ + __builtin_fabs(__real (a) - __real (b)) < 0.0001 && \ + __builtin_fabs(__imag (a) - __imag (b)) < 0.0001 \ +) + +#define EVAL(a, b) _Static_assert(a == b, "") +#define EVALF(a, b) _Static_assert(APPROX_EQ(a, b), "") + +// _Complex float + _Complex float +void a() { + EVALF((2.f + 3i) + (4.f + 5i), 6.f + 8i); + EVALF((2.f + 3i) - (4.f + 5i), -2.f - 2i); + EVALF((2.f + 3i) * (4.f + 5i), -7.f + 22i); + EVALF((2.f + 3i) / (4.f + 5i), 0.5609f + 0.0487i); + + EVALF((2. + 3i) + (4. + 5i), 6. + 8i); + EVALF((2. + 3i) - (4. + 5i), -2. - 2i); + EVALF((2. + 3i) * (4. + 5i), -7. + 22i); + EVALF((2. + 3i) / (4. + 5i), .5609 + .0487i); +} + +// _Complex int + _Complex int +void b() { + EVAL((2 + 3i) + (4 + 5i), 6 + 8i); + EVAL((2 + 3i) - (4 + 5i), -2 - 2i); + EVAL((2 + 3i) * (4 + 5i), -7 + 22i); + EVAL((8 + 30i) / (4 + 5i), 4 + 1i); +} + +// _Complex float + float +void c() { + EVALF((2.f + 4i) + 3.f, 5.f + 4i); + EVALF((2.f + 4i) - 3.f, -1.f + 4i); + EVALF((2.f + 4i) * 3.f, 6.f + 12i); + EVALF((2.f + 4i) / 2.f, 1.f + 2i); + + EVALF(3.f + (2.f + 4i), 5.f + 4i); + EVALF(3.f - (2.f + 4i), 1.f - 4i); + EVALF(3.f * (2.f + 4i), 6.f + 12i); + EVALF(3.f / (2.f + 4i), .3f - 0.6i); + + EVALF((2. + 4i) + 3., 5. + 4i); + EVALF((2. + 4i) - 3., -1. + 4i); + EVALF((2. + 4i) * 3., 6. + 12i); + EVALF((2. + 4i) / 2., 1. + 2i); + + EVALF(3. + (2. + 4i), 5. + 4i); + EVALF(3. - (2. + 4i), 1. - 4i); + EVALF(3. * (2. + 4i), 6. + 12i); + EVALF(3. / (2. + 4i), .3 - 0.6i); +} + +// _Complex int + int +void d() { + EVAL((2 + 4i) + 3, 5 + 4i); + EVAL((2 + 4i) - 3, -1 + 4i); + EVAL((2 + 4i) * 3, 6 + 12i); + EVAL((2 + 4i) / 2, 1 + 2i); + + EVAL(3 + (2 + 4i), 5 + 4i); + EVAL(3 - (2 + 4i), 1 - 4i); + EVAL(3 * (2 + 4i), 6 + 12i); + EVAL(20 / (2 + 4i), 2 - 4i); +} + +// _Complex float + int +void e() { + EVALF((2.f + 4i) + 3, 5.f + 4i); + EVALF((2.f + 4i) - 3, -1.f + 4i); + EVALF((2.f + 4i) * 3, 6.f + 12i); + EVALF((2.f + 4i) / 2, 1.f + 2i); + + EVALF(3 + (2.f + 4i), 5.f + 4i); + EVALF(3 - (2.f + 4i), 1.f - 4i); + EVALF(3 * (2.f + 4i), 6.f + 12i); + EVALF(3 / (2.f + 4i), .3f - 0.6i); + + EVALF((2. + 4i) + 3, 5. + 4i); + EVALF((2. + 4i) - 3, -1. + 4i); + EVALF((2. + 4i) * 3, 6. + 12i); + EVALF((2. + 4i) / 2, 1. + 2i); + + EVALF(3 + (2. + 4i), 5. + 4i); + EVALF(3 - (2. + 4i), 1. - 4i); + EVALF(3 * (2. + 4i), 6. + 12i); + EVALF(3 / (2. + 4i), .3 - 0.6i); +} + +// _Complex int + float +void f() { + EVALF((2 + 4i) + 3.f, 5.f + 4i); + EVALF((2 + 4i) - 3.f, -1.f + 4i); + EVALF((2 + 4i) * 3.f, 6.f + 12i); + EVALF((2 + 4i) / 2.f, 1.f + 2i); + + EVALF(3.f + (2 + 4i), 5.f + 4i); + EVALF(3.f - (2 + 4i), 1.f - 4i); + EVALF(3.f * (2 + 4i), 6.f + 12i); + EVALF(3.f / (2 + 4i), .3f - 0.6i); + + EVALF((2 + 4i) + 3., 5. + 4i); + EVALF((2 + 4i) - 3., -1. + 4i); + EVALF((2 + 4i) * 3., 6. + 12i); + EVALF((2 + 4i) / 2., 1. + 2i); + + EVALF(3. + (2 + 4i), 5. + 4i); + EVALF(3. - (2 + 4i), 1. - 4i); + EVALF(3. * (2 + 4i), 6. + 12i); + EVALF(3. / (2 + 4i), .3 - 0.6i); +} diff --git a/clang/test/Sema/const-eval.c b/clang/test/Sema/const-eval.c index 2e38d5e23c208acc5028b566783b064214c82a03..e358aceaad5a43bca19bc590b76b838a2810048a 100644 --- a/clang/test/Sema/const-eval.c +++ b/clang/test/Sema/const-eval.c @@ -134,8 +134,7 @@ void PR21945(void) { int i = (({}), 0l); } void PR24622(void); struct PR24622 {} pr24622; -EVAL_EXPR(52, &pr24622 == (void *)&PR24622); // expected-error {{not an integer constant expression}} - // expected-note@-1 {{past the end}} +EVAL_EXPR(52, &pr24622 == (void *)&PR24622); // We evaluate these by providing 2s' complement semantics in constant // expressions, like we do for integers. diff --git a/clang/test/Sema/const-init.c b/clang/test/Sema/const-init.c new file mode 100644 index 0000000000000000000000000000000000000000..5b07ede747ebc4ba2b66e2e287406311d99d5c84 --- /dev/null +++ b/clang/test/Sema/const-init.c @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c23 %s + +// Division by 0 here is an error iff the variable is 'constexpr'. +const _Bool inf1 = (1.0/0.0 == __builtin_inf()); +constexpr _Bool inf2 = (1.0/0.0 == __builtin_inf()); // expected-error {{must be initialized by a constant expression}} expected-note {{division by zero}} +constexpr _Bool inf3 = __builtin_inf() == __builtin_inf(); diff --git a/clang/test/Sema/constant-builtins-2.c b/clang/test/Sema/constant-builtins-2.c index 6dd1d88759c751837e536549068279f6aab2234a..a60a1f16a458741bfdd9b2428a19459c62d0a283 100644 --- a/clang/test/Sema/constant-builtins-2.c +++ b/clang/test/Sema/constant-builtins-2.c @@ -218,6 +218,64 @@ char clz6[__builtin_clzll(0xFFLL) == BITSIZE(long long) - 8 ? 1 : -1]; char clz7[__builtin_clzs(0x1) == BITSIZE(short) - 1 ? 1 : -1]; char clz8[__builtin_clzs(0xf) == BITSIZE(short) - 4 ? 1 : -1]; char clz9[__builtin_clzs(0xfff) == BITSIZE(short) - 12 ? 1 : -1]; +int clz10 = __builtin_clzg((unsigned char)0); // expected-error {{not a compile-time constant}} +char clz11[__builtin_clzg((unsigned char)0, 42) == 42 ? 1 : -1]; +char clz12[__builtin_clzg((unsigned char)0x1) == BITSIZE(char) - 1 ? 1 : -1]; +char clz13[__builtin_clzg((unsigned char)0x1, 42) == BITSIZE(char) - 1 ? 1 : -1]; +char clz14[__builtin_clzg((unsigned char)0xf) == BITSIZE(char) - 4 ? 1 : -1]; +char clz15[__builtin_clzg((unsigned char)0xf, 42) == BITSIZE(char) - 4 ? 1 : -1]; +char clz16[__builtin_clzg((unsigned char)(1 << (BITSIZE(char) - 1))) == 0 ? 1 : -1]; +char clz17[__builtin_clzg((unsigned char)(1 << (BITSIZE(char) - 1)), 42) == 0 ? 1 : -1]; +int clz18 = __builtin_clzg((unsigned short)0); // expected-error {{not a compile-time constant}} +char clz19[__builtin_clzg((unsigned short)0, 42) == 42 ? 1 : -1]; +char clz20[__builtin_clzg((unsigned short)0x1) == BITSIZE(short) - 1 ? 1 : -1]; +char clz21[__builtin_clzg((unsigned short)0x1, 42) == BITSIZE(short) - 1 ? 1 : -1]; +char clz22[__builtin_clzg((unsigned short)0xf) == BITSIZE(short) - 4 ? 1 : -1]; +char clz23[__builtin_clzg((unsigned short)0xf, 42) == BITSIZE(short) - 4 ? 1 : -1]; +char clz24[__builtin_clzg((unsigned short)(1 << (BITSIZE(short) - 1))) == 0 ? 1 : -1]; +char clz25[__builtin_clzg((unsigned short)(1 << (BITSIZE(short) - 1)), 42) == 0 ? 1 : -1]; +int clz26 = __builtin_clzg(0U); // expected-error {{not a compile-time constant}} +char clz27[__builtin_clzg(0U, 42) == 42 ? 1 : -1]; +char clz28[__builtin_clzg(0x1U) == BITSIZE(int) - 1 ? 1 : -1]; +char clz29[__builtin_clzg(0x1U, 42) == BITSIZE(int) - 1 ? 1 : -1]; +char clz30[__builtin_clzg(0xfU) == BITSIZE(int) - 4 ? 1 : -1]; +char clz31[__builtin_clzg(0xfU, 42) == BITSIZE(int) - 4 ? 1 : -1]; +char clz32[__builtin_clzg(1U << (BITSIZE(int) - 1)) == 0 ? 1 : -1]; +char clz33[__builtin_clzg(1U << (BITSIZE(int) - 1), 42) == 0 ? 1 : -1]; +int clz34 = __builtin_clzg(0UL); // expected-error {{not a compile-time constant}} +char clz35[__builtin_clzg(0UL, 42) == 42 ? 1 : -1]; +char clz36[__builtin_clzg(0x1UL) == BITSIZE(long) - 1 ? 1 : -1]; +char clz37[__builtin_clzg(0x1UL, 42) == BITSIZE(long) - 1 ? 1 : -1]; +char clz38[__builtin_clzg(0xfUL) == BITSIZE(long) - 4 ? 1 : -1]; +char clz39[__builtin_clzg(0xfUL, 42) == BITSIZE(long) - 4 ? 1 : -1]; +char clz40[__builtin_clzg(1UL << (BITSIZE(long) - 1)) == 0 ? 1 : -1]; +char clz41[__builtin_clzg(1UL << (BITSIZE(long) - 1), 42) == 0 ? 1 : -1]; +int clz42 = __builtin_clzg(0ULL); // expected-error {{not a compile-time constant}} +char clz43[__builtin_clzg(0ULL, 42) == 42 ? 1 : -1]; +char clz44[__builtin_clzg(0x1ULL) == BITSIZE(long long) - 1 ? 1 : -1]; +char clz45[__builtin_clzg(0x1ULL, 42) == BITSIZE(long long) - 1 ? 1 : -1]; +char clz46[__builtin_clzg(0xfULL) == BITSIZE(long long) - 4 ? 1 : -1]; +char clz47[__builtin_clzg(0xfULL, 42) == BITSIZE(long long) - 4 ? 1 : -1]; +char clz48[__builtin_clzg(1ULL << (BITSIZE(long long) - 1)) == 0 ? 1 : -1]; +char clz49[__builtin_clzg(1ULL << (BITSIZE(long long) - 1), 42) == 0 ? 1 : -1]; +#ifdef __SIZEOF_INT128__ +int clz50 = __builtin_clzg((unsigned __int128)0); // expected-error {{not a compile-time constant}} +char clz51[__builtin_clzg((unsigned __int128)0, 42) == 42 ? 1 : -1]; +char clz52[__builtin_clzg((unsigned __int128)0x1) == BITSIZE(__int128) - 1 ? 1 : -1]; +char clz53[__builtin_clzg((unsigned __int128)0x1, 42) == BITSIZE(__int128) - 1 ? 1 : -1]; +char clz54[__builtin_clzg((unsigned __int128)0xf) == BITSIZE(__int128) - 4 ? 1 : -1]; +char clz55[__builtin_clzg((unsigned __int128)0xf, 42) == BITSIZE(__int128) - 4 ? 1 : -1]; +char clz56[__builtin_clzg((unsigned __int128)(1 << (BITSIZE(__int128) - 1))) == 0 ? 1 : -1]; +char clz57[__builtin_clzg((unsigned __int128)(1 << (BITSIZE(__int128) - 1)), 42) == 0 ? 1 : -1]; +#endif +int clz58 = __builtin_clzg((unsigned _BitInt(128))0); // expected-error {{not a compile-time constant}} +char clz59[__builtin_clzg((unsigned _BitInt(128))0, 42) == 42 ? 1 : -1]; +char clz60[__builtin_clzg((unsigned _BitInt(128))0x1) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1]; +char clz61[__builtin_clzg((unsigned _BitInt(128))0x1, 42) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1]; +char clz62[__builtin_clzg((unsigned _BitInt(128))0xf) == BITSIZE(_BitInt(128)) - 4 ? 1 : -1]; +char clz63[__builtin_clzg((unsigned _BitInt(128))0xf, 42) == BITSIZE(_BitInt(128)) - 4 ? 1 : -1]; +char clz64[__builtin_clzg((unsigned _BitInt(128))(1 << (BITSIZE(_BitInt(128)) - 1))) == 0 ? 1 : -1]; +char clz65[__builtin_clzg((unsigned _BitInt(128))(1 << (BITSIZE(_BitInt(128)) - 1)), 42) == 0 ? 1 : -1]; char ctz1[__builtin_ctz(1) == 0 ? 1 : -1]; char ctz2[__builtin_ctz(8) == 3 ? 1 : -1]; @@ -226,6 +284,64 @@ int ctz4 = __builtin_ctz(0); // expected-error {{not a compile-time constant}} char ctz5[__builtin_ctzl(0x10L) == 4 ? 1 : -1]; char ctz6[__builtin_ctzll(0x100LL) == 8 ? 1 : -1]; char ctz7[__builtin_ctzs(1 << (BITSIZE(short) - 1)) == BITSIZE(short) - 1 ? 1 : -1]; +int ctz8 = __builtin_ctzg((unsigned char)0); // expected-error {{not a compile-time constant}} +char ctz9[__builtin_ctzg((unsigned char)0, 42) == 42 ? 1 : -1]; +char ctz10[__builtin_ctzg((unsigned char)0x1) == 0 ? 1 : -1]; +char ctz11[__builtin_ctzg((unsigned char)0x1, 42) == 0 ? 1 : -1]; +char ctz12[__builtin_ctzg((unsigned char)0x10) == 4 ? 1 : -1]; +char ctz13[__builtin_ctzg((unsigned char)0x10, 42) == 4 ? 1 : -1]; +char ctz14[__builtin_ctzg((unsigned char)(1 << (BITSIZE(char) - 1))) == BITSIZE(char) - 1 ? 1 : -1]; +char ctz15[__builtin_ctzg((unsigned char)(1 << (BITSIZE(char) - 1)), 42) == BITSIZE(char) - 1 ? 1 : -1]; +int ctz16 = __builtin_ctzg((unsigned short)0); // expected-error {{not a compile-time constant}} +char ctz17[__builtin_ctzg((unsigned short)0, 42) == 42 ? 1 : -1]; +char ctz18[__builtin_ctzg((unsigned short)0x1) == 0 ? 1 : -1]; +char ctz19[__builtin_ctzg((unsigned short)0x1, 42) == 0 ? 1 : -1]; +char ctz20[__builtin_ctzg((unsigned short)0x10) == 4 ? 1 : -1]; +char ctz21[__builtin_ctzg((unsigned short)0x10, 42) == 4 ? 1 : -1]; +char ctz22[__builtin_ctzg((unsigned short)(1 << (BITSIZE(short) - 1))) == BITSIZE(short) - 1 ? 1 : -1]; +char ctz23[__builtin_ctzg((unsigned short)(1 << (BITSIZE(short) - 1)), 42) == BITSIZE(short) - 1 ? 1 : -1]; +int ctz24 = __builtin_ctzg(0U); // expected-error {{not a compile-time constant}} +char ctz25[__builtin_ctzg(0U, 42) == 42 ? 1 : -1]; +char ctz26[__builtin_ctzg(0x1U) == 0 ? 1 : -1]; +char ctz27[__builtin_ctzg(0x1U, 42) == 0 ? 1 : -1]; +char ctz28[__builtin_ctzg(0x10U) == 4 ? 1 : -1]; +char ctz29[__builtin_ctzg(0x10U, 42) == 4 ? 1 : -1]; +char ctz30[__builtin_ctzg(1U << (BITSIZE(int) - 1)) == BITSIZE(int) - 1 ? 1 : -1]; +char ctz31[__builtin_ctzg(1U << (BITSIZE(int) - 1), 42) == BITSIZE(int) - 1 ? 1 : -1]; +int ctz32 = __builtin_ctzg(0UL); // expected-error {{not a compile-time constant}} +char ctz33[__builtin_ctzg(0UL, 42) == 42 ? 1 : -1]; +char ctz34[__builtin_ctzg(0x1UL) == 0 ? 1 : -1]; +char ctz35[__builtin_ctzg(0x1UL, 42) == 0 ? 1 : -1]; +char ctz36[__builtin_ctzg(0x10UL) == 4 ? 1 : -1]; +char ctz37[__builtin_ctzg(0x10UL, 42) == 4 ? 1 : -1]; +char ctz38[__builtin_ctzg(1UL << (BITSIZE(long) - 1)) == BITSIZE(long) - 1 ? 1 : -1]; +char ctz39[__builtin_ctzg(1UL << (BITSIZE(long) - 1), 42) == BITSIZE(long) - 1 ? 1 : -1]; +int ctz40 = __builtin_ctzg(0ULL); // expected-error {{not a compile-time constant}} +char ctz41[__builtin_ctzg(0ULL, 42) == 42 ? 1 : -1]; +char ctz42[__builtin_ctzg(0x1ULL) == 0 ? 1 : -1]; +char ctz43[__builtin_ctzg(0x1ULL, 42) == 0 ? 1 : -1]; +char ctz44[__builtin_ctzg(0x10ULL) == 4 ? 1 : -1]; +char ctz45[__builtin_ctzg(0x10ULL, 42) == 4 ? 1 : -1]; +char ctz46[__builtin_ctzg(1ULL << (BITSIZE(long long) - 1)) == BITSIZE(long long) - 1 ? 1 : -1]; +char ctz47[__builtin_ctzg(1ULL << (BITSIZE(long long) - 1), 42) == BITSIZE(long long) - 1 ? 1 : -1]; +#ifdef __SIZEOF_INT128__ +int ctz48 = __builtin_ctzg((unsigned __int128)0); // expected-error {{not a compile-time constant}} +char ctz49[__builtin_ctzg((unsigned __int128)0, 42) == 42 ? 1 : -1]; +char ctz50[__builtin_ctzg((unsigned __int128)0x1) == 0 ? 1 : -1]; +char ctz51[__builtin_ctzg((unsigned __int128)0x1, 42) == 0 ? 1 : -1]; +char ctz52[__builtin_ctzg((unsigned __int128)0x10) == 4 ? 1 : -1]; +char ctz53[__builtin_ctzg((unsigned __int128)0x10, 42) == 4 ? 1 : -1]; +char ctz54[__builtin_ctzg((unsigned __int128)1 << (BITSIZE(__int128) - 1)) == BITSIZE(__int128) - 1 ? 1 : -1]; +char ctz55[__builtin_ctzg((unsigned __int128)1 << (BITSIZE(__int128) - 1), 42) == BITSIZE(__int128) - 1 ? 1 : -1]; +#endif +int ctz56 = __builtin_ctzg((unsigned _BitInt(128))0); // expected-error {{not a compile-time constant}} +char ctz57[__builtin_ctzg((unsigned _BitInt(128))0, 42) == 42 ? 1 : -1]; +char ctz58[__builtin_ctzg((unsigned _BitInt(128))0x1) == 0 ? 1 : -1]; +char ctz59[__builtin_ctzg((unsigned _BitInt(128))0x1, 42) == 0 ? 1 : -1]; +char ctz60[__builtin_ctzg((unsigned _BitInt(128))0x10) == 4 ? 1 : -1]; +char ctz61[__builtin_ctzg((unsigned _BitInt(128))0x10, 42) == 4 ? 1 : -1]; +char ctz62[__builtin_ctzg((unsigned _BitInt(128))1 << (BITSIZE(_BitInt(128)) - 1)) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1]; +char ctz63[__builtin_ctzg((unsigned _BitInt(128))1 << (BITSIZE(_BitInt(128)) - 1), 42) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1]; char popcount1[__builtin_popcount(0) == 0 ? 1 : -1]; char popcount2[__builtin_popcount(0xF0F0) == 8 ? 1 : -1]; diff --git a/clang/test/Sema/constant-builtins-all-args-evaluated.cpp b/clang/test/Sema/constant-builtins-all-args-evaluated.cpp new file mode 100644 index 0000000000000000000000000000000000000000..db55e24cecda7a4c2704827c17421fdb3be9fedb --- /dev/null +++ b/clang/test/Sema/constant-builtins-all-args-evaluated.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// expected-no-diagnostics + +constexpr int test_clzg_0() { + int x = 0; + (void)__builtin_clzg(0U, ++x); + return x; +} + +static_assert(test_clzg_0() == 1); + +constexpr int test_clzg_1() { + int x = 0; + (void)__builtin_clzg(1U, ++x); + return x; +} + +static_assert(test_clzg_1() == 1); + +constexpr int test_ctzg_0() { + int x = 0; + (void)__builtin_ctzg(0U, ++x); + return x; +} + +static_assert(test_ctzg_0() == 1); + +constexpr int test_ctzg_1() { + int x = 0; + (void)__builtin_ctzg(1U, ++x); + return x; +} + +static_assert(test_ctzg_1() == 1); diff --git a/clang/test/Sema/constexpr-void-cast.c b/clang/test/Sema/constexpr-void-cast.c new file mode 100644 index 0000000000000000000000000000000000000000..91e4027f67fe387850891099e773b490d74e5c26 --- /dev/null +++ b/clang/test/Sema/constexpr-void-cast.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -x c -fsyntax-only %s -verify=c -std=c11 +// RUN: %clang_cc1 -x c -fsyntax-only %s -pedantic -verify=c-pedantic -std=c11 +// +// RUN: %clang_cc1 -x c++ -fsyntax-only %s -verify=cxx +// RUN: %clang_cc1 -x c++ -fsyntax-only %s -pedantic -verify=cxx-pedantic + +// c-no-diagnostics +// cxx-no-diagnostics + +void f(void); +struct S {char c;} s; +_Static_assert(&s != (void *)&f, ""); // c-pedantic-warning {{not an integer constant expression}} \ + // c-pedantic-note {{this conversion is not allowed in a constant expression}} \ + // cxx-pedantic-warning {{'_Static_assert' is a C11 extension}} diff --git a/clang/test/Sema/count-builtins.c b/clang/test/Sema/count-builtins.c new file mode 100644 index 0000000000000000000000000000000000000000..79fa812f3f206bb7ec3f8f8d0dd60027cb0eaab9 --- /dev/null +++ b/clang/test/Sema/count-builtins.c @@ -0,0 +1,87 @@ +// RUN: %clang_cc1 -std=c23 -triple=x86_64-pc-linux-gnu -fsyntax-only -verify -Wpedantic %s + +typedef int int2 __attribute__((ext_vector_type(2))); + +void test_builtin_popcountg(short s, int i, __int128 i128, _BitInt(128) bi128, + double d, int2 i2) { + __builtin_popcountg(); + // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} + __builtin_popcountg(i, i); + // expected-error@-1 {{too many arguments to function call, expected 1, have 2}} + __builtin_popcountg(s); + // expected-error@-1 {{1st argument must be an unsigned integer (was 'short')}} + __builtin_popcountg(i); + // expected-error@-1 {{1st argument must be an unsigned integer (was 'int')}} + __builtin_popcountg(i128); + // expected-error@-1 {{1st argument must be an unsigned integer (was '__int128')}} + __builtin_popcountg(bi128); + // expected-error@-1 {{1st argument must be an unsigned integer (was '_BitInt(128)')}} + __builtin_popcountg(d); + // expected-error@-1 {{1st argument must be an unsigned integer (was 'double')}} + __builtin_popcountg(i2); + // expected-error@-1 {{1st argument must be an unsigned integer (was 'int2' (vector of 2 'int' values))}} +} + +void test_builtin_clzg(short s, int i, unsigned int ui, __int128 i128, + _BitInt(128) bi128, double d, int2 i2) { + __builtin_clzg(); + // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} + __builtin_clzg(i, i, i); + // expected-error@-1 {{too many arguments to function call, expected at most 2, have 3}} + __builtin_clzg(s); + // expected-error@-1 {{1st argument must be an unsigned integer (was 'short')}} + __builtin_clzg(i); + // expected-error@-1 {{1st argument must be an unsigned integer (was 'int')}} + __builtin_clzg(i128); + // expected-error@-1 {{1st argument must be an unsigned integer (was '__int128')}} + __builtin_clzg(bi128); + // expected-error@-1 {{1st argument must be an unsigned integer (was '_BitInt(128)')}} + __builtin_clzg(d); + // expected-error@-1 {{1st argument must be an unsigned integer (was 'double')}} + __builtin_clzg(i2); + // expected-error@-1 {{1st argument must be an unsigned integer (was 'int2' (vector of 2 'int' values))}} + __builtin_clzg(i2); + // expected-error@-1 {{1st argument must be an unsigned integer (was 'int2' (vector of 2 'int' values))}} + __builtin_clzg(ui, ui); + // expected-error@-1 {{2nd argument must be an 'int' (was 'unsigned int')}} + __builtin_clzg(ui, i128); + // expected-error@-1 {{2nd argument must be an 'int' (was '__int128')}} + __builtin_clzg(ui, bi128); + // expected-error@-1 {{2nd argument must be an 'int' (was '_BitInt(128)')}} + __builtin_clzg(ui, d); + // expected-error@-1 {{2nd argument must be an 'int' (was 'double')}} + __builtin_clzg(ui, i2); + // expected-error@-1 {{2nd argument must be an 'int' (was 'int2' (vector of 2 'int' values))}} +} + +void test_builtin_ctzg(short s, int i, unsigned int ui, __int128 i128, + _BitInt(128) bi128, double d, int2 i2) { + __builtin_ctzg(); + // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} + __builtin_ctzg(i, i, i); + // expected-error@-1 {{too many arguments to function call, expected at most 2, have 3}} + __builtin_ctzg(s); + // expected-error@-1 {{1st argument must be an unsigned integer (was 'short')}} + __builtin_ctzg(i); + // expected-error@-1 {{1st argument must be an unsigned integer (was 'int')}} + __builtin_ctzg(i128); + // expected-error@-1 {{1st argument must be an unsigned integer (was '__int128')}} + __builtin_ctzg(bi128); + // expected-error@-1 {{1st argument must be an unsigned integer (was '_BitInt(128)')}} + __builtin_ctzg(d); + // expected-error@-1 {{1st argument must be an unsigned integer (was 'double')}} + __builtin_ctzg(i2); + // expected-error@-1 {{1st argument must be an unsigned integer (was 'int2' (vector of 2 'int' values))}} + __builtin_ctzg(i2); + // expected-error@-1 {{1st argument must be an unsigned integer (was 'int2' (vector of 2 'int' values))}} + __builtin_ctzg(ui, ui); + // expected-error@-1 {{2nd argument must be an 'int' (was 'unsigned int')}} + __builtin_ctzg(ui, i128); + // expected-error@-1 {{2nd argument must be an 'int' (was '__int128')}} + __builtin_ctzg(ui, bi128); + // expected-error@-1 {{2nd argument must be an 'int' (was '_BitInt(128)')}} + __builtin_ctzg(ui, d); + // expected-error@-1 {{2nd argument must be an 'int' (was 'double')}} + __builtin_ctzg(ui, i2); + // expected-error@-1 {{2nd argument must be an 'int' (was 'int2' (vector of 2 'int' values))}} +} diff --git a/clang/test/Sema/flexible-array-in-union.c b/clang/test/Sema/flexible-array-in-union.c index 5fabfbe0b1eaabfd6d73b5b8ab242dea45341880..dd5e8069665feabe88c56db27b6747d35fd6d4c1 100644 --- a/clang/test/Sema/flexible-array-in-union.c +++ b/clang/test/Sema/flexible-array-in-union.c @@ -1,13 +1,188 @@ -// RUN: %clang_cc1 %s -verify=c -fsyntax-only -// RUN: %clang_cc1 %s -verify -fsyntax-only -x c++ -// RUN: %clang_cc1 %s -verify -fsyntax-only -fms-compatibility -// RUN: %clang_cc1 %s -verify -fsyntax-only -fms-compatibility -x c++ +// RUN: %clang_cc1 %s -verify=stock,c -fsyntax-only +// RUN: %clang_cc1 %s -verify=stock,cpp -fsyntax-only -x c++ +// RUN: %clang_cc1 %s -verify=stock,cpp -fsyntax-only -fms-compatibility -x c++ +// RUN: %clang_cc1 %s -verify=stock,c,gnu -fsyntax-only -Wgnu-flexible-array-union-member -Wgnu-empty-struct +// RUN: %clang_cc1 %s -verify=stock,c,microsoft -fsyntax-only -fms-compatibility -Wmicrosoft // The test checks that an attempt to initialize union with flexible array // member with an initializer list doesn't crash clang. -union { char x[]; } r = {0}; // c-error {{flexible array member 'x' in a union is not allowed}} +union { char x[]; } r = {0}; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ +struct _name1 { + int a; + union { + int b; + char x[]; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ + }; +} name1 = { + 10, + 42, /* initializes "b" */ +}; -// expected-no-diagnostics +struct _name1i { + int a; + union { + int b; + char x[]; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ + }; +} name1i = { + .a = 10, + .b = 42, +}; + +/* Initialization of flexible array in a union is never allowed. */ +struct _name2 { + int a; + union { + int b; + char x[]; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ + }; +} name2 = { + 12, + 13, + { 'c' }, /* c-warning {{excess elements in struct initializer}} + cpp-error {{excess elements in struct initializer}} + */ +}; + +/* Initialization of flexible array in a union is never allowed. */ +struct _name2i { + int a; + union { + int b; + char x[]; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + stock-note {{initialized flexible array member 'x' is here}} + */ + }; +} name2i = { + .a = 12, + .b = 13, /* stock-note {{previous initialization is here}} */ + .x = { 'c' }, /* stock-error {{initialization of flexible array member is not allowed}} + c-warning {{initializer overrides prior initialization of this subobject}} + cpp-error {{initializer partially overrides prior initialization of this subobject}} + */ +}; + +/* Flexible array initialization always allowed when not in a union, + and when struct has another member. + */ +struct _okay { + int a; + char x[]; +} okay = { + 22, + { 'x', 'y', 'z' }, +}; + +struct _okayi { + int a; + char x[]; +} okayi = { + .a = 22, + .x = { 'x', 'y', 'z' }, +}; + +struct _okay0 { + int a; + char x[]; +} okay0 = { }; + +struct _flex_extension { + char x[]; /* gnu-warning {{flexible array member 'x' in otherwise empty struct is a GNU extension}} + microsoft-warning {{flexible array member 'x' in otherwise empty struct is a Microsoft extension}} + */ +} flex_extension = { + { 'x', 'y', 'z' }, +}; + +struct _flex_extensioni { + char x[]; /* gnu-warning {{flexible array member 'x' in otherwise empty struct is a GNU extension}} + microsoft-warning {{flexible array member 'x' in otherwise empty struct is a Microsoft extension}} + */ +} flex_extensioni = { + .x = { 'x', 'y', 'z' }, +}; + +struct already_hidden { + int a; + union { + int b; + struct { + struct { } __empty; // gnu-warning {{empty struct is a GNU extension}} + char x[]; + }; + }; +}; +struct still_zero_sized { + struct { } __unused; // gnu-warning {{empty struct is a GNU extension}} + int x[]; +}; + +struct warn1 { + int a; + union { + int b; + char x[]; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ + }; +}; + +struct warn2 { + int x[]; /* gnu-warning {{flexible array member 'x' in otherwise empty struct is a GNU extension}} + microsoft-warning {{flexible array member 'x' in otherwise empty struct is a Microsoft extension}} + */ +}; + +union warn3 { + short x[]; /* gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ +}; + +struct quiet1 { + int a; + short x[]; +}; + +struct _not_at_end { + union { short x[]; }; /* stock-warning-re {{field '' with variable sized type '{{.*}}' not at the end of a struct or class is a GNU extension}} + gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ + int y; +} not_at_end = {{}, 3}; + +struct _not_at_end_s { + struct { int a; short x[]; }; /* stock-warning-re {{field '' with variable sized type '{{.*}}' not at the end of a struct or class is a GNU extension}} */ + int y; +} not_at_end_s = {{}, 3}; + +struct { + int a; + union { /* stock-warning-re {{field '' with variable sized type '{{.*}}' not at the end of a struct or class is a GNU extension}} */ + short x[]; /* stock-note {{initialized flexible array member 'x' is here}} + gnu-warning {{flexible array member 'x' in a union is a GNU extension}} + microsoft-warning {{flexible array member 'x' in a union is a Microsoft extension}} + */ + int b; + }; + int c; + int d; +} i_f = { 4, + {5}, /* stock-error {{initialization of flexible array member is not allowed}} */ + {}, + 6}; + +// expected-no-diagnostics diff --git a/clang/test/Sema/format-strings-signedness-fixit.c b/clang/test/Sema/format-strings-signedness-fixit.c new file mode 100644 index 0000000000000000000000000000000000000000..b4e6e975657aaed4f1b5b3e439f610d4215cfec5 --- /dev/null +++ b/clang/test/Sema/format-strings-signedness-fixit.c @@ -0,0 +1,98 @@ +// RUN: cp %s %t +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -Wformat -Wformat-signedness -fixit %t +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -Wformat -Wformat-signedness -Werror %t +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -E -o - %t | FileCheck %s + +#include <limits.h> + +int printf(const char *restrict format, ...); + +void test_printf_int(int x) +{ + printf("%u", x); +} + +void test_printf_unsigned(unsigned x) +{ + printf("%d", x); +} + +void test_printf_long(long x) +{ + printf("%lu", x); +} + +void test_printf_unsigned_long(unsigned long x) +{ + printf("%ld", x); +} + +void test_printf_long_long(long long x) +{ + printf("%llu", x); +} + +void test_printf_unsigned_long_long(unsigned long long x) +{ + printf("%lld", x); +} + +enum enum_int { + minus_1 = -1 +}; + +void test_printf_enum_int(enum enum_int x) +{ + printf("%u", x); +} + +enum enum_unsigned { + zero = 0 +}; + +void test_printf_enum_unsigned(enum enum_unsigned x) +{ + printf("%d", x); +} + +enum enum_long { + minus_one = -1, + int_val = INT_MAX, + unsigned_val = (unsigned)INT_MIN +}; + +void test_printf_enum_long(enum enum_long x) +{ + printf("%lu", x); +} + +enum enum_unsigned_long { + uint_max_plus = (unsigned long)UINT_MAX+1, +}; + +void test_printf_enum_unsigned_long(enum enum_unsigned_long x) +{ + printf("%ld", x); +} + +// Validate the fixes. +// CHECK: void test_printf_int(int x) +// CHECK: printf("%d", x); +// CHECK: void test_printf_unsigned(unsigned x) +// CHECK: printf("%u", x); +// CHECK: void test_printf_long(long x) +// CHECK: printf("%ld", x); +// CHECK: void test_printf_unsigned_long(unsigned long x) +// CHECK: printf("%lu", x); +// CHECK: void test_printf_long_long(long long x) +// CHECK: printf("%lld", x); +// CHECK: void test_printf_unsigned_long_long(unsigned long long x) +// CHECK: printf("%llu", x); +// CHECK: void test_printf_enum_int(enum enum_int x) +// CHECK: printf("%d", x); +// CHECK: void test_printf_enum_unsigned(enum enum_unsigned x) +// CHECK: printf("%u", x); +// CHECK: void test_printf_enum_long(enum enum_long x) +// CHECK: printf("%ld", x); +// CHECK: void test_printf_enum_unsigned_long(enum enum_unsigned_long x) +// CHECK: printf("%lu", x); diff --git a/clang/test/Sema/format-strings-signedness.c b/clang/test/Sema/format-strings-signedness.c new file mode 100644 index 0000000000000000000000000000000000000000..d5a8140d9ef8a084ea6c8dd7b58f578bea474178 --- /dev/null +++ b/clang/test/Sema/format-strings-signedness.c @@ -0,0 +1,222 @@ +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -std=c11 -fsyntax-only -verify -Wformat -Wformat-signedness %s +// RUN: %clang_cc1 -triple=x86_64-pc-win32 -std=c11 -fsyntax-only -verify -Wformat -Wformat-signedness %s + +// Verify that -Wformat-signedness alone (without -Wformat) trigger the +// warnings. Note in gcc this will not trigger the signedness warnings as +// -Wformat is default off in gcc. +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -std=c11 -fsyntax-only -verify -Wformat-signedness %s +// RUN: %clang_cc1 -triple=x86_64-pc-win32 -std=c11 -fsyntax-only -verify -Wformat-signedness %s + +// Verify that -Wformat-signedness warnings are not reported with only -Wformat +// (gcc compat). +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -std=c11 -fsyntax-only -Wformat -verify=okay %s + +// Verify that -Wformat-signedness with -Wno-format are not reported (gcc compat). +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -std=c11 -fsyntax-only -Wformat-signedness -Wno-format -verify=okay %s +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -std=c11 -fsyntax-only -Wno-format -Wformat-signedness -verify=okay %s +// okay-no-diagnostics + +int printf(const char *restrict format, ...); +int scanf(const char * restrict, ...); + +void test_printf_bool(_Bool x) +{ + printf("%d", x); // no-warning + printf("%u", x); // no-warning + printf("%x", x); // no-warning +} + +void test_printf_char(char x) +{ + printf("%c", x); // no-warning +} + +void test_printf_unsigned_char(unsigned char x) +{ + printf("%c", x); // no-warning +} + +void test_printf_int(int x) +{ + printf("%d", x); // no-warning + printf("%u", x); // expected-warning{{format specifies type 'unsigned int' but the argument has type 'int'}} + printf("%x", x); // expected-warning{{format specifies type 'unsigned int' but the argument has type 'int'}} +} + +void test_printf_unsigned(unsigned x) +{ + printf("%d", x); // expected-warning{{format specifies type 'int' but the argument has type 'unsigned int'}} + printf("%u", x); // no-warning + printf("%x", x); // no-warning +} + +void test_printf_long(long x) +{ + printf("%ld", x); // no-warning + printf("%lu", x); // expected-warning{{format specifies type 'unsigned long' but the argument has type 'long'}} + printf("%lx", x); // expected-warning{{format specifies type 'unsigned long' but the argument has type 'long'}} +} + +void test_printf_unsigned_long(unsigned long x) +{ + printf("%ld", x); // expected-warning{{format specifies type 'long' but the argument has type 'unsigned long'}} + printf("%lu", x); // no-warning + printf("%lx", x); // no-warning +} + +void test_printf_long_long(long long x) +{ + printf("%lld", x); // no-warning + printf("%llu", x); // expected-warning{{format specifies type 'unsigned long long' but the argument has type 'long long'}} + printf("%llx", x); // expected-warning{{format specifies type 'unsigned long long' but the argument has type 'long long'}} +} + +void test_printf_unsigned_long_long(unsigned long long x) +{ + printf("%lld", x); // expected-warning{{format specifies type 'long long' but the argument has type 'unsigned long long'}} + printf("%llu", x); // no-warning + printf("%llx", x); // no-warning +} + +enum enum_int { + minus_1 = -1 +}; + +void test_printf_enum_int(enum enum_int x) +{ + printf("%d", x); // no-warning + printf("%u", x); // expected-warning{{format specifies type 'unsigned int' but the argument has underlying type 'int'}} + printf("%x", x); // expected-warning{{format specifies type 'unsigned int' but the argument has underlying type 'int'}} +} + +#ifndef _WIN32 // Disabled due to enums have different underlying type on _WIN32 +enum enum_unsigned { + zero = 0 +}; + +void test_printf_enum_unsigned(enum enum_unsigned x) +{ + printf("%d", x); // expected-warning{{format specifies type 'int' but the argument has underlying type 'unsigned int'}} + printf("%u", x); // no-warning + printf("%x", x); // no-warning +} + +enum enum_long { + minus_one = -1, + int_val = __INT_MAX__, // INT_MAX + unsigned_val = (unsigned)(-__INT_MAX__ -1) // (unsigned)INT_MIN +}; + +void test_printf_enum_long(enum enum_long x) +{ + printf("%ld", x); // no-warning + printf("%lu", x); // expected-warning{{format specifies type 'unsigned long' but the argument has underlying type 'long'}} + printf("%lx", x); // expected-warning{{format specifies type 'unsigned long' but the argument has underlying type 'long'}} +} + +enum enum_unsigned_long { + uint_max_plus = (unsigned long)(__INT_MAX__ *2U +1U)+1, // (unsigned long)UINT_MAX+1 +}; + +void test_printf_enum_unsigned_long(enum enum_unsigned_long x) +{ + printf("%ld", x); // expected-warning{{format specifies type 'long' but the argument has underlying type 'unsigned long'}} + printf("%lu", x); // no-warning + printf("%lx", x); // no-warning +} +#endif + +void test_scanf_char(char *y) { + scanf("%c", y); // no-warning +} + +void test_scanf_unsigned_char(unsigned char *y) { + scanf("%c", y); // no-warning +} + +void test_scanf_int(int *x) { + scanf("%d", x); // no-warning + scanf("%u", x); // expected-warning{{format specifies type 'unsigned int *' but the argument has type 'int *'}} + scanf("%x", x); // expected-warning{{format specifies type 'unsigned int *' but the argument has type 'int *'}} +} + +void test_scanf_unsigned(unsigned *x) { + scanf("%d", x); // expected-warning{{format specifies type 'int *' but the argument has type 'unsigned int *'}} + scanf("%u", x); // no-warning + scanf("%x", x); // no-warning +} + +void test_scanf_long(long *x) { + scanf("%ld", x); // no-warning + scanf("%lu", x); // expected-warning{{format specifies type 'unsigned long *' but the argument has type 'long *'}} + scanf("%lx", x); // expected-warning{{format specifies type 'unsigned long *' but the argument has type 'long *'}} +} + +void test_scanf_unsigned_long(unsigned long *x) { + scanf("%ld", x); // expected-warning{{format specifies type 'long *' but the argument has type 'unsigned long *'}} + scanf("%lu", x); // no-warning + scanf("%lx", x); // no-warning +} + +void test_scanf_longlong(long long *x) { + scanf("%lld", x); // no-warning + scanf("%llu", x); // expected-warning{{format specifies type 'unsigned long long *' but the argument has type 'long long *'}} + scanf("%llx", x); // expected-warning{{format specifies type 'unsigned long long *' but the argument has type 'long long *'}} +} + +void test_scanf_unsigned_longlong(unsigned long long *x) { + scanf("%lld", x); // expected-warning{{format specifies type 'long long *' but the argument has type 'unsigned long long *'}} + scanf("%llu", x); // no-warning + scanf("%llx", x); // no-warning +} + +void test_scanf_enum_int(enum enum_int *x) { + scanf("%d", x); // no-warning + scanf("%u", x); // expected-warning{{format specifies type 'unsigned int *' but the argument has type 'enum enum_int *'}} + scanf("%x", x); // expected-warning{{format specifies type 'unsigned int *' but the argument has type 'enum enum_int *'}} +} + +#ifndef _WIN32 // Disabled due to enums have different underlying type on _WIN32 +void test_scanf_enum_unsigned(enum enum_unsigned *x) { + scanf("%d", x); // expected-warning{{format specifies type 'int *' but the argument has type 'enum enum_unsigned *'}} + scanf("%u", x); // no-warning + scanf("%x", x); // no-warning +} + +void test_scanf_enum_long(enum enum_long *x) { + scanf("%ld", x); // no-warning + scanf("%lu", x); // expected-warning{{format specifies type 'unsigned long *' but the argument has type 'enum enum_long *'}} + scanf("%lx", x); // expected-warning{{format specifies type 'unsigned long *' but the argument has type 'enum enum_long *'}} +} + +void test_scanf_enum_unsigned_long(enum enum_unsigned_long *x) { + scanf("%ld", x); // expected-warning{{format specifies type 'long *' but the argument has type 'enum enum_unsigned_long *'}} + scanf("%lu", x); // no-warning + scanf("%lx", x); // no-warning +} +#endif + +// Verify that we get no warnings from <inttypes.h> + +typedef short int int16_t; +typedef unsigned short int uint16_t; + +void test_printf_priX16(int16_t x) { + printf("PRId16: %" "d" /*PRId16*/ "\n", x); // no-warning + printf("PRIi16: %" "i" /*PRIi16*/ "\n", x); // no-warning +} + +void test_printf_unsigned_priX16(uint16_t x) { + printf("PRIo16: %" "o" /*PRIo16*/ "\n", x); // no-warning + printf("PRIu16: %" "u" /*PRIu16*/ "\n", x); // no-warning + printf("PRIx16: %" "x" /*PRIx16*/ "\n", x); // no-warning + printf("PRIX16: %" "X" /*PRIX16*/ "\n", x); // no-warning +} + +// Verify that we can suppress a -Wformat-signedness warning by ignoring +// -Wformat (gcc compat). +void test_suppress(int x) +{ +#pragma GCC diagnostic ignored "-Wformat" + printf("%u", x); +} diff --git a/clang/test/Sema/nullability.c b/clang/test/Sema/nullability.c index 7d193bea46771ff2f38d9f31dc4dc8f90e8348ba..0401516233b6db13929c6ab429e14d8a81fd8546 100644 --- a/clang/test/Sema/nullability.c +++ b/clang/test/Sema/nullability.c @@ -248,3 +248,5 @@ void arraysInBlocks(void) { void (^withTypedefBad)(INTS _Nonnull [2]) = // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int[4]')}} ^(INTS _Nonnull x[2]) {}; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int[4]')}} } + +struct _Nullable NotCplusplusClass {}; // expected-error {{'_Nullable' attribute only applies to classes}} diff --git a/clang/test/Sema/ptrauth-intrinsics-macro.c b/clang/test/Sema/ptrauth-intrinsics-macro.c new file mode 100644 index 0000000000000000000000000000000000000000..07d63740451452302a5e78a90d372a46020bd02c --- /dev/null +++ b/clang/test/Sema/ptrauth-intrinsics-macro.c @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -triple arm64-apple-ios -Wall -fsyntax-only -verify -fptrauth-intrinsics %s +// RUN: %clang_cc1 -triple arm64-apple-ios -Wall -fsyntax-only -verify %s + +// expected-no-diagnostics + +#include <ptrauth.h> + +#define VALID_CODE_KEY 0 +#define VALID_DATA_KEY 2 + +extern int dv; + +void test(int *dp, int value) { + dp = ptrauth_strip(dp, VALID_DATA_KEY); + ptrauth_extra_data_t t0 = ptrauth_blend_discriminator(dp, value); + (void)t0; + dp = ptrauth_sign_unauthenticated(dp, VALID_DATA_KEY, 0); + dp = ptrauth_auth_and_resign(dp, VALID_DATA_KEY, dp, VALID_DATA_KEY, dp); + dp = ptrauth_auth_data(dp, VALID_DATA_KEY, 0); + int pu0 = 0, pu1 = 0, pu2 = 0, pu3 = 0, pu4 = 0, pu5 = 0, pu6 = 0, pu7 = 0; + ptrauth_blend_discriminator(&pu0, value); + ptrauth_auth_and_resign(&pu1, VALID_DATA_KEY, dp, VALID_DATA_KEY, dp); + ptrauth_auth_and_resign(dp, VALID_DATA_KEY, &pu2, VALID_DATA_KEY, dp); + ptrauth_auth_and_resign(dp, VALID_DATA_KEY, dp, VALID_DATA_KEY, &pu3); + ptrauth_sign_generic_data(pu4, dp); + ptrauth_sign_generic_data(dp, pu5); + ptrauth_auth_data(&pu6, VALID_DATA_KEY, value); + ptrauth_auth_data(dp, VALID_DATA_KEY, pu7); + + + + int t2 = ptrauth_sign_generic_data(dp, 0); + (void)t2; +} diff --git a/clang/test/Sema/ptrauth.c b/clang/test/Sema/ptrauth.c new file mode 100644 index 0000000000000000000000000000000000000000..3ad3d70c24e4130b9747b25af1030576316e10d9 --- /dev/null +++ b/clang/test/Sema/ptrauth.c @@ -0,0 +1,126 @@ +// RUN: %clang_cc1 -triple arm64-apple-ios -fsyntax-only -verify -fptrauth-intrinsics %s + +#if __has_feature(ptrauth_intrinsics) +#warning Pointer authentication enabled! +// expected-warning@-1 {{Pointer authentication enabled!}} +#endif + +#if __aarch64__ +#define VALID_CODE_KEY 0 +#define VALID_DATA_KEY 2 +#define INVALID_KEY 200 +#else +#error Provide these constants if you port this test +#endif + +#define NULL ((void*) 0) +struct A { int x; } mismatched_type; + +extern int dv; +extern int fv(int); + +void test_strip(int *dp, int (*fp)(int)) { + __builtin_ptrauth_strip(dp); // expected-error {{too few arguments}} + __builtin_ptrauth_strip(dp, VALID_DATA_KEY, dp); // expected-error {{too many arguments}} + (void) __builtin_ptrauth_strip(NULL, VALID_DATA_KEY); // no warning + + __builtin_ptrauth_strip(mismatched_type, VALID_DATA_KEY); // expected-error {{signed value must have pointer type; type here is 'struct A'}} + __builtin_ptrauth_strip(dp, mismatched_type); // expected-error {{passing 'struct A' to parameter of incompatible type 'int'}} + + int *dr = __builtin_ptrauth_strip(dp, VALID_DATA_KEY); + dr = __builtin_ptrauth_strip(dp, INVALID_KEY); // expected-error {{does not identify a valid pointer authentication key for the current target}} + + int (*fr)(int) = __builtin_ptrauth_strip(fp, VALID_CODE_KEY); + fr = __builtin_ptrauth_strip(fp, INVALID_KEY); // expected-error {{does not identify a valid pointer authentication key for the current target}} + + float *mismatch = __builtin_ptrauth_strip(dp, VALID_DATA_KEY); // expected-warning {{incompatible pointer types initializing 'float *' with an expression of type 'int *'}} +} + +void test_blend_discriminator(int *dp, int (*fp)(int), int value) { + __builtin_ptrauth_blend_discriminator(dp); // expected-error {{too few arguments}} + __builtin_ptrauth_blend_discriminator(dp, dp, dp); // expected-error {{too many arguments}} + (void) __builtin_ptrauth_blend_discriminator(dp, value); // no warning + + __builtin_ptrauth_blend_discriminator(mismatched_type, value); // expected-error {{blended pointer must have pointer type; type here is 'struct A'}} + __builtin_ptrauth_blend_discriminator(dp, mismatched_type); // expected-error {{blended integer must have integer type; type here is 'struct A'}} + + float *mismatch = __builtin_ptrauth_blend_discriminator(dp, value); // expected-error {{incompatible integer to pointer conversion initializing 'float *' with an expression of type}} +} + +void test_sign_unauthenticated(int *dp, int (*fp)(int)) { + __builtin_ptrauth_sign_unauthenticated(dp, VALID_DATA_KEY); // expected-error {{too few arguments}} + __builtin_ptrauth_sign_unauthenticated(dp, VALID_DATA_KEY, dp, dp); // expected-error {{too many arguments}} + + __builtin_ptrauth_sign_unauthenticated(mismatched_type, VALID_DATA_KEY, 0); // expected-error {{signed value must have pointer type; type here is 'struct A'}} + __builtin_ptrauth_sign_unauthenticated(dp, mismatched_type, 0); // expected-error {{passing 'struct A' to parameter of incompatible type 'int'}} + __builtin_ptrauth_sign_unauthenticated(dp, VALID_DATA_KEY, mismatched_type); // expected-error {{extra discriminator must have pointer or integer type; type here is 'struct A'}} + + (void) __builtin_ptrauth_sign_unauthenticated(NULL, VALID_DATA_KEY, 0); // expected-warning {{signing a null pointer will yield a non-null pointer}} + + int *dr = __builtin_ptrauth_sign_unauthenticated(dp, VALID_DATA_KEY, 0); + dr = __builtin_ptrauth_sign_unauthenticated(dp, INVALID_KEY, 0); // expected-error {{does not identify a valid pointer authentication key for the current target}} + + int (*fr)(int) = __builtin_ptrauth_sign_unauthenticated(fp, VALID_CODE_KEY, 0); + fr = __builtin_ptrauth_sign_unauthenticated(fp, INVALID_KEY, 0); // expected-error {{does not identify a valid pointer authentication key for the current target}} + + float *mismatch = __builtin_ptrauth_sign_unauthenticated(dp, VALID_DATA_KEY, 0); // expected-warning {{incompatible pointer types initializing 'float *' with an expression of type 'int *'}} +} + +void test_auth(int *dp, int (*fp)(int)) { + __builtin_ptrauth_auth(dp, VALID_DATA_KEY); // expected-error {{too few arguments}} + __builtin_ptrauth_auth(dp, VALID_DATA_KEY, dp, dp); // expected-error {{too many arguments}} + + __builtin_ptrauth_auth(mismatched_type, VALID_DATA_KEY, 0); // expected-error {{signed value must have pointer type; type here is 'struct A'}} + __builtin_ptrauth_auth(dp, mismatched_type, 0); // expected-error {{passing 'struct A' to parameter of incompatible type 'int'}} + __builtin_ptrauth_auth(dp, VALID_DATA_KEY, mismatched_type); // expected-error {{extra discriminator must have pointer or integer type; type here is 'struct A'}} + + (void) __builtin_ptrauth_auth(NULL, VALID_DATA_KEY, 0); // expected-warning {{authenticating a null pointer will almost certainly trap}} + + int *dr = __builtin_ptrauth_auth(dp, VALID_DATA_KEY, 0); + dr = __builtin_ptrauth_auth(dp, INVALID_KEY, 0); // expected-error {{does not identify a valid pointer authentication key for the current target}} + + int (*fr)(int) = __builtin_ptrauth_auth(fp, VALID_CODE_KEY, 0); + fr = __builtin_ptrauth_auth(fp, INVALID_KEY, 0); // expected-error {{does not identify a valid pointer authentication key for the current target}} + + float *mismatch = __builtin_ptrauth_auth(dp, VALID_DATA_KEY, 0); // expected-warning {{incompatible pointer types initializing 'float *' with an expression of type 'int *'}} +} + +void test_auth_and_resign(int *dp, int (*fp)(int)) { + __builtin_ptrauth_auth_and_resign(dp, VALID_DATA_KEY, 0, VALID_DATA_KEY); // expected-error {{too few arguments}} + __builtin_ptrauth_auth_and_resign(dp, VALID_DATA_KEY, dp, VALID_DATA_KEY, dp, 0); // expected-error {{too many arguments}} + + __builtin_ptrauth_auth_and_resign(mismatched_type, VALID_DATA_KEY, 0, VALID_DATA_KEY, dp); // expected-error {{signed value must have pointer type; type here is 'struct A'}} + __builtin_ptrauth_auth_and_resign(dp, mismatched_type, 0, VALID_DATA_KEY, dp); // expected-error {{passing 'struct A' to parameter of incompatible type 'int'}} + __builtin_ptrauth_auth_and_resign(dp, VALID_DATA_KEY, mismatched_type, VALID_DATA_KEY, dp); // expected-error {{extra discriminator must have pointer or integer type; type here is 'struct A'}} + __builtin_ptrauth_auth_and_resign(dp, VALID_DATA_KEY, 0, mismatched_type, dp); // expected-error {{passing 'struct A' to parameter of incompatible type 'int'}} + __builtin_ptrauth_auth_and_resign(dp, VALID_DATA_KEY, 0, VALID_DATA_KEY, mismatched_type); // expected-error {{extra discriminator must have pointer or integer type; type here is 'struct A'}} + + (void) __builtin_ptrauth_auth_and_resign(NULL, VALID_DATA_KEY, 0, VALID_DATA_KEY, dp); // expected-warning {{authenticating a null pointer will almost certainly trap}} + + int *dr = __builtin_ptrauth_auth_and_resign(dp, VALID_DATA_KEY, 0, VALID_DATA_KEY, dp); + dr = __builtin_ptrauth_auth_and_resign(dp, INVALID_KEY, 0, VALID_DATA_KEY, dp); // expected-error {{does not identify a valid pointer authentication key for the current target}} + dr = __builtin_ptrauth_auth_and_resign(dp, VALID_DATA_KEY, 0, INVALID_KEY, dp); // expected-error {{does not identify a valid pointer authentication key for the current target}} + + int (*fr)(int) = __builtin_ptrauth_auth_and_resign(fp, VALID_CODE_KEY, 0, VALID_CODE_KEY, dp); + fr = __builtin_ptrauth_auth_and_resign(fp, INVALID_KEY, 0, VALID_CODE_KEY, dp); // expected-error {{does not identify a valid pointer authentication key for the current target}} + fr = __builtin_ptrauth_auth_and_resign(fp, VALID_CODE_KEY, 0, INVALID_KEY, dp); // expected-error {{does not identify a valid pointer authentication key for the current target}} + + float *mismatch = __builtin_ptrauth_auth_and_resign(dp, VALID_DATA_KEY, 0, VALID_DATA_KEY, dp); // expected-warning {{incompatible pointer types initializing 'float *' with an expression of type 'int *'}} +} + +void test_sign_generic_data(int *dp) { + __builtin_ptrauth_sign_generic_data(dp); // expected-error {{too few arguments}} + __builtin_ptrauth_sign_generic_data(dp, 0, 0); // expected-error {{too many arguments}} + + __builtin_ptrauth_sign_generic_data(mismatched_type, 0); // expected-error {{signed value must have pointer or integer type; type here is 'struct A'}} + __builtin_ptrauth_sign_generic_data(dp, mismatched_type); // expected-error {{extra discriminator must have pointer or integer type; type here is 'struct A'}} + + (void) __builtin_ptrauth_sign_generic_data(NULL, 0); // no warning + + unsigned long dr = __builtin_ptrauth_sign_generic_data(dp, 0); + dr = __builtin_ptrauth_sign_generic_data(dp, &dv); + dr = __builtin_ptrauth_sign_generic_data(12314, 0); + dr = __builtin_ptrauth_sign_generic_data(12314, &dv); + + int *mismatch = __builtin_ptrauth_sign_generic_data(dp, 0); // expected-error {{incompatible integer to pointer conversion initializing 'int *' with an expression of type}} +} diff --git a/clang/test/Sema/swift-call-conv.c b/clang/test/Sema/swift-call-conv.c index 755c18f5183f8584ff7ceaf49cd7fb74604cb938..2c9be8405584813d3054e9984d71c3d3bc21f390 100644 --- a/clang/test/Sema/swift-call-conv.c +++ b/clang/test/Sema/swift-call-conv.c @@ -1,7 +1,19 @@ // RUN: %clang_cc1 -triple aarch64-unknown-windows-msvc -fsyntax-only %s -verify // RUN: %clang_cc1 -triple thumbv7-unknown-windows-msvc -fsyntax-only %s -verify // RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fsyntax-only %s -verify +// RISC-V does not support swiftcall +// RUN: %clang_cc1 -triple riscv32-unknown-elf -fsyntax-only %s -verify +#if __has_extension(swiftcc) // expected-no-diagnostics - +#else +// expected-warning@+2 {{'__swiftcall__' calling convention is not supported for this target}} +#endif void __attribute__((__swiftcall__)) f(void) {} + +#if __has_extension(swiftasynccc) +// expected-no-diagnostics +#else +// expected-warning@+2 {{'__swiftasynccall__' calling convention is not supported for this target}} +#endif +void __attribute__((__swiftasynccall__)) g(void) {} diff --git a/clang/test/Sema/transparent-union.c b/clang/test/Sema/transparent-union.c index c134a7a9b1c4d0077d592c7a7c73eb52917604c7..f02c2298b51ce1433fecfa5709f5fad15359ee9c 100644 --- a/clang/test/Sema/transparent-union.c +++ b/clang/test/Sema/transparent-union.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -Wgnu-flexible-array-union-member %s typedef union { int *ip; float *fp; @@ -131,7 +131,7 @@ union pr15134v2 { union pr30520v { void b; } __attribute__((transparent_union)); // expected-error {{field has incomplete type 'void'}} -union pr30520a { int b[]; } __attribute__((transparent_union)); // expected-error {{flexible array member 'b' in a union is not allowed}} +union pr30520a { int b[]; } __attribute__((transparent_union)); // expected-warning {{flexible array member 'b' in a union is a GNU extension}} // expected-note@+1 2 {{forward declaration of 'struct stb'}} union pr30520s { struct stb b; } __attribute__((transparent_union)); // expected-error {{field has incomplete type 'struct stb'}} diff --git a/clang/test/Sema/warn-bitwise-and-bool.c b/clang/test/Sema/warn-bitwise-and-bool.c index 6bec1be1abdef6600969c275327133de06cead4f..c30498e2bd8d1ab52fcdf5eb6540cd6c38db79c9 100644 --- a/clang/test/Sema/warn-bitwise-and-bool.c +++ b/clang/test/Sema/warn-bitwise-and-bool.c @@ -19,6 +19,8 @@ boolean baz(void) __attribute__((const)); void sink(boolean); #define FOO foo() +#define MY_AND & +#define My_BITAND bitand void test(boolean a, boolean b, int *p, volatile int *q, int i) { b = a & b; @@ -44,9 +46,12 @@ void test(boolean a, boolean b, int *p, volatile int *q, int i) { b = b & foo(); b = bar() & (i > 4); b = (i == 7) & foo(); + b = b MY_AND foo(); // OK, no warning expected + #ifdef __cplusplus - b = foo() bitand bar(); // expected-warning {{use of bitwise '&' with boolean operands}} - // expected-note@-1 {{cast one or both operands to int to silence this warning}} + b = foo() bitand bar(); // Ok, no warning expected + b = foo() My_BITAND bar(); // Ok, no warning expected + #endif if (foo() & bar()) // expected-warning {{use of bitwise '&' with boolean operands}} @@ -60,4 +65,5 @@ void test(boolean a, boolean b, int *p, volatile int *q, int i) { int n = i + 10; b = (n & (n - 1)); + } diff --git a/clang/test/Sema/warn-bitwise-or-bool.c b/clang/test/Sema/warn-bitwise-or-bool.c index ae86790901aac53a0581434385c17949ca190e11..e45ef28da0a70da0b9425075f4953d365d07a102 100644 --- a/clang/test/Sema/warn-bitwise-or-bool.c +++ b/clang/test/Sema/warn-bitwise-or-bool.c @@ -19,6 +19,8 @@ boolean baz(void) __attribute__((const)); void sink(boolean); #define FOO foo() +#define MY_OR | +#define My_BITOR bitor void test(boolean a, boolean b, int *p, volatile int *q, int i) { b = a | b; @@ -44,9 +46,11 @@ void test(boolean a, boolean b, int *p, volatile int *q, int i) { b = b | foo(); b = bar() | (i > 4); b = (i == 7) | foo(); + b = b MY_OR foo(); // OK, no warning expected #ifdef __cplusplus - b = foo() bitor bar(); // expected-warning {{use of bitwise '|' with boolean operands}} - // expected-note@-1 {{cast one or both operands to int to silence this warning}} + b = foo() bitor bar(); //Ok, no warning expected + b = foo() My_BITOR bar(); // Ok, no warning expected + #endif if (foo() | bar()) // expected-warning {{use of bitwise '|' with boolean operands}} diff --git a/clang/test/Sema/warn-cast-function-type-strict.c b/clang/test/Sema/warn-cast-function-type-strict.c index 5233680796e972b27526f8ab7fe173dbbe119139..b0a70cf324b711b65c29616b0d266a67450690dc 100644 --- a/clang/test/Sema/warn-cast-function-type-strict.c +++ b/clang/test/Sema/warn-cast-function-type-strict.c @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 %s -fsyntax-only -Wcast-function-type -verify -// RUN: %clang_cc1 %s -fsyntax-only -Wcast-function-type-strict -verify - +// RUN: %clang_cc1 %s -fsyntax-only -Wcast-function-type -verify=expected,strict +// RUN: %clang_cc1 %s -fsyntax-only -Wcast-function-type-strict -verify=expected,strict +// RUN: %clang_cc1 %s -fsyntax-only -Wextra -Wno-ignored-qualifiers -verify int t(int array[static 12]); int u(int i); @@ -32,12 +32,13 @@ f10 *j; void foo(void) { a = (f1 *)x; b = (f2 *)x; /* expected-warning {{cast from 'int (*)(long)' to 'f2 *' (aka 'int (*)(void *)') converts to incompatible function type}} */ - c = (f3 *)x; /* expected-warning {{cast from 'int (*)(long)' to 'f3 *' (aka 'int (*)()') converts to incompatible function type}} */ + c = (f3 *)x; /* strict-warning {{cast from 'int (*)(long)' to 'f3 *' (aka 'int (*)()') converts to incompatible function type}} */ d = (f4 *)x; /* expected-warning {{cast from 'int (*)(long)' to 'f4 *' (aka 'void (*)()') converts to incompatible function type}} */ - e = (f5 *)x; /* expected-warning {{cast from 'int (*)(long)' to 'f5 *' (aka 'void (*)(void)') converts to incompatible function type}} */ + e = (f5 *)x; /* strict-warning {{cast from 'int (*)(long)' to 'f5 *' (aka 'void (*)(void)') converts to incompatible function type}} */ f = (f6 *)x; /* expected-warning {{cast from 'int (*)(long)' to 'f6 *' (aka 'int (*)(long, int)') converts to incompatible function type}} */ - g = (f7 *)x; /* expected-warning {{cast from 'int (*)(long)' to 'f7 *' (aka 'int (*)(long, ...)') converts to incompatible function type}} */ + g = (f7 *)x; /* strict-warning {{cast from 'int (*)(long)' to 'f7 *' (aka 'int (*)(long, ...)') converts to incompatible function type}} */ h = (f8 *)t; i = (f9 *)u; - j = (f10 *)v; /* expected-warning {{cast from 'const int (*)(int)' to 'f10 *' (aka 'int (*)(int)') converts to incompatible function type}} */ + // FIXME: return type qualifier should not be included in the function type . Warning should be absent after this issue is fixed. https://github.com/llvm/llvm-project/issues/39494 . + j = (f10 *)v; /* strict-warning {{cast from 'const int (*)(int)' to 'f10 *' (aka 'int (*)(int)') converts to incompatible function type}} */ } diff --git a/clang/test/Sema/warn-cast-function-type.c b/clang/test/Sema/warn-cast-function-type.c index d7ddcdb73725c03328b9b202e81cb8f8383af37e..09d169026b1c8625c900146779201011196af65f 100644 --- a/clang/test/Sema/warn-cast-function-type.c +++ b/clang/test/Sema/warn-cast-function-type.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -fsyntax-only -Wcast-function-type -Wno-cast-function-type-strict -verify +// RUN: %clang_cc1 %s -fsyntax-only -Wextra -Wno-cast-function-type-strict -verify int x(long); diff --git a/clang/test/SemaCXX/attr-target-version.cpp b/clang/test/SemaCXX/attr-target-version.cpp index 0bd710c4e282ad3d4d850143f7fdce454c2a8f3f..b3385f043590f84ca7574992bc92abb27ba5e06b 100644 --- a/clang/test/SemaCXX/attr-target-version.cpp +++ b/clang/test/SemaCXX/attr-target-version.cpp @@ -9,7 +9,6 @@ void __attribute__((target_version("rcpc3"))) no_def(void); void __attribute__((target_version("mops"))) no_def(void); void __attribute__((target_version("rdma"))) no_def(void); -// expected-error@+1 {{no matching function for call to 'no_def'}} void foo(void) { no_def(); } constexpr int __attribute__((target_version("sve2"))) diff_const(void) { return 1; } @@ -41,6 +40,7 @@ inline int __attribute__((target_version("sme"))) diff_inline(void) { return 1; int __attribute__((target_version("fp16"))) diff_inline(void) { return 2; } inline int __attribute__((target_version("sme"))) diff_inline1(void) { return 1; } +//expected-error@+1 {{multiversioned function declaration has a different inline specification}} int __attribute__((target_version("default"))) diff_inline1(void) { return 2; } int __attribute__((target_version("fcma"))) diff_type1(void) { return 1; } @@ -59,8 +59,7 @@ int __attribute__((target_version("sve2-sha3"))) diff_type3(void) noexcept(true) template <typename T> int __attribute__((target_version("default"))) temp(T) { return 1; } template <typename T> int __attribute__((target_version("simd"))) temp1(T) { return 1; } -// expected-error@+1 {{attribute 'target_version' multiversioned functions do not yet support function templates}} -template <typename T> int __attribute__((target_version("sha3"))) temp1(T) { return 2; } +// expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support function templates}} extern "C" { int __attribute__((target_version("aes"))) extc(void) { return 1; } @@ -70,17 +69,23 @@ int __attribute__((target_version("lse"))) extc(void) { return 1; } auto __attribute__((target_version("default"))) ret1(void) { return 1; } auto __attribute__((target_version("dpb"))) ret2(void) { return 1; } +// expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support deduced return types}} auto __attribute__((target_version("dpb2"))) ret3(void) -> int { return 1; } class Cls { __attribute__((target_version("rng"))) Cls(); + // expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support constructors}} __attribute__((target_version("sve-i8mm"))) ~Cls(); + // expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support destructors}} Cls &__attribute__((target_version("f32mm"))) operator=(const Cls &) = default; + // expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support defaulted functions}} Cls &__attribute__((target_version("ssbs"))) operator=(Cls &&) = delete; + // expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support deleted functions}} virtual void __attribute__((target_version("default"))) vfunc(); virtual void __attribute__((target_version("sm4"))) vfunc1(); + // expected-error@-1 {{attribute 'target_version' multiversioned functions do not yet support virtual functions}} }; __attribute__((target_version("sha3"))) void Decl(); diff --git a/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp b/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp index c5b8032f40b131a9940a4c78534d2e567a8d34a0..7520b43a194aba6860febbac01f0ad2858abbaa0 100644 --- a/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp +++ b/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp @@ -90,7 +90,8 @@ void test_record() { struct tuple4 { unsigned x, y, z, doublez; - constexpr bool operator==(tuple4 const &other) const { + bool operator==(tuple4 const &other) const = default; + constexpr bool operator==(bases const &other) const { return x == other.x && y == other.y && z == other.z && doublez == other.doublez; } @@ -99,6 +100,9 @@ void test_record() { constexpr tuple4 t4 = bit_cast<tuple4>(b); static_assert(t4 == tuple4{1, 2, 3, 4}); static_assert(round_trip<tuple4>(b)); + + constexpr auto b2 = bit_cast<bases>(t4); + static_assert(t4 == b2); } void test_partially_initialized() { diff --git a/clang/test/SemaCXX/constexpr-explicit-object-lambda.cpp b/clang/test/SemaCXX/constexpr-explicit-object-lambda.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4e8e94d428d071f8a738bbb352b4592ea67eeff3 --- /dev/null +++ b/clang/test/SemaCXX/constexpr-explicit-object-lambda.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++23 -verify %s +// expected-no-diagnostics + +struct S { + int i = 42; + constexpr auto f1() { + return [this](this auto) { + return this->i; + }(); + }; + + constexpr auto f2() { + return [this](this auto&&) { + return this->i; + }(); + }; + + constexpr auto f3() { + return [i = this->i](this auto) { + return i; + }(); + }; + + constexpr auto f4() { + return [i = this->i](this auto&&) { + return i; + }(); + }; +}; + +static_assert(S().f1() == 42); +static_assert(S().f2() == 42); +static_assert(S().f3() == 42); +static_assert(S().f4() == 42); diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index 794496ed418489ecb3440a2246a61f6f926fb51f..b71cd46f884d6375b0597280280e726835d08a36 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -230,3 +230,52 @@ using AFoo = Foo<U>*; // expected-note {{template is declared here}} AFoo s = {1}; // expected-error {{alias template 'AFoo' requires template arguments; argument deduction only allowed for}} } // namespace test17 + +namespace test18 { +template<typename T> +concept False = false; // expected-note {{because 'false' evaluated to false}} + +template <typename T> struct Foo { T t; }; + +template<typename T> requires False<T> // expected-note {{because 'int' does not satisfy 'False'}} +Foo(T) -> Foo<int>; + +template <typename U> +using Bar = Foo<U>; // expected-note {{could not match 'Foo<type-parameter-0-0>' against 'int'}} \ + // expected-note {{candidate template ignored: constraints not satisfied}} \ + // expected-note {{candidate function template not viable}} + +Bar s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments}} +} // namespace test18 + +// GH85406, verify no crash on invalid alias templates. +namespace test19 { +template <typename T> +class Foo {}; + +template <typename T> +template <typename K> +using Bar2 = Foo<K>; // expected-error {{extraneous template parameter list in alias template declaration}} + +Bar2 b = 1; // expected-error {{no viable constructor or deduction guide for deduction of template arguments}} +} // namespace test19 + +// GH85385 +namespace test20 { +template <template <typename> typename T> +struct K {}; + +template <typename U> +class Foo {}; + +// Verify that template template type parameter TTP is referenced/used in the +// template arguments of the RHS. +template <template<typename> typename TTP> +using Bar = Foo<K<TTP>>; // expected-note {{candidate template ignored: could not match 'Foo<K<>>' against 'int'}} + +template <class T> +class Container {}; +Bar t = Foo<K<Container>>(); + +Bar s = 1; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of}} +} // namespace test20 diff --git a/clang/test/SemaCXX/cxx23-assume.cpp b/clang/test/SemaCXX/cxx23-assume.cpp index 2d7c9b174d901934fb38d45ce120c003f4ec72ea..478da092471affa037b12dcf0d6441281e2d4e3e 100644 --- a/clang/test/SemaCXX/cxx23-assume.cpp +++ b/clang/test/SemaCXX/cxx23-assume.cpp @@ -126,3 +126,13 @@ static_assert(f5<D>() == 1); // expected-note 3 {{while checking constraint sati static_assert(f5<double>() == 2); static_assert(f5<E>() == 1); // expected-note {{while checking constraint satisfaction}} expected-note {{in instantiation of}} static_assert(f5<F>() == 2); // expected-note {{while checking constraint satisfaction}} expected-note {{in instantiation of}} + +// Do not validate assumptions whose evaluation would have side-effects. +constexpr int foo() { + int a = 0; + [[assume(a++)]] [[assume(++a)]]; // expected-warning 2 {{has side effects that will be discarded}} ext-warning 2 {{C++23 extension}} + [[assume((a+=1))]]; // expected-warning {{has side effects that will be discarded}} ext-warning {{C++23 extension}} + return a; +} + +static_assert(foo() == 0); diff --git a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp index 7ac48136989146f71fa9be8f0fcdbb3f6f8a5654..fff524e77d3bf468650395a266e8c217b3e5fab2 100644 --- a/clang/test/SemaCXX/cxx2a-template-lambdas.cpp +++ b/clang/test/SemaCXX/cxx2a-template-lambdas.cpp @@ -1,10 +1,14 @@ -// RUN: %clang_cc1 -std=c++2a -verify %s +// RUN: %clang_cc1 -std=c++03 -verify -Dstatic_assert=_Static_assert -Wno-c++11-extensions -Wno-c++14-extensions -Wno-c++17-extensions -Wno-c++20-extensions %s +// RUN: %clang_cc1 -std=c++11 -verify=expected,cxx11,cxx11-cxx14 -Wno-c++20-extensions -Wno-c++17-extensions -Wno-c++14-extensions %s +// RUN: %clang_cc1 -std=c++14 -verify=expected,cxx11-cxx14,cxx14 -Wno-c++20-extensions -Wno-c++17-extensions %s +// RUN: %clang_cc1 -std=c++17 -verify -Wno-c++20-extensions %s +// RUN: %clang_cc1 -std=c++20 -verify %s template<typename, typename> -constexpr bool is_same = false; +inline const bool is_same = false; template<typename T> -constexpr bool is_same<T, T> = true; +inline const bool is_same<T, T> = true; template<typename T> struct DummyTemplate { }; @@ -23,7 +27,7 @@ void func() { L1.operator()<6>(); // expected-note {{in instantiation}} auto L2 = []<template<typename> class T, class U>(T<U> &&arg) { - static_assert(is_same<T<U>, DummyTemplate<float>>); // // expected-error {{static assertion failed}} + static_assert(is_same<T<U>, DummyTemplate<float> >); // // expected-error {{static assertion failed}} }; L2(DummyTemplate<float>()); L2(DummyTemplate<double>()); // expected-note {{in instantiation}} @@ -36,15 +40,20 @@ struct ShadowMe { } }; +#if __cplusplus >= 201102L template<typename T> constexpr T outer() { - return []<T x>() { return x; }.template operator()<123>(); // expected-error {{no matching member function}} \ - expected-note {{candidate template ignored}} + // FIXME: The C++11 error seems wrong + return []<T x>() { return x; }.template operator()<123>(); // expected-error {{no matching member function}} \ + expected-note {{candidate template ignored}} \ + cxx11-note {{non-literal type '<dependent type>' cannot be used in a constant expression}} \ + cxx14-note {{non-literal type}} } -static_assert(outer<int>() == 123); +static_assert(outer<int>() == 123); // cxx11-cxx14-error {{not an integral constant expression}} cxx11-cxx14-note {{in call}} template int *outer<int *>(); // expected-note {{in instantiation}} +#endif - +#if __cplusplus >= 202002L namespace GH62611 { template <auto A = [](auto x){}> struct C { @@ -87,3 +96,4 @@ void foo() { } } +#endif diff --git a/clang/test/SemaCXX/datasizeof.cpp b/clang/test/SemaCXX/datasizeof.cpp index 5baf2ecb24ed7a8405f43c3265ce2bcd2e25ecae..43135c00496638148b6d17dd46ba51223a56fcf8 100644 --- a/clang/test/SemaCXX/datasizeof.cpp +++ b/clang/test/SemaCXX/datasizeof.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -triple x86_64-linux-gnu -verify %s +// RUN: %clang_cc1 -fsyntax-only -triple x86_64-linux-gnu -verify %s -fexperimental-new-constant-interpreter #if !__has_extension(datasizeof) # error "Expected datasizeof extension" diff --git a/clang/test/SemaCXX/decomposed-condition.cpp b/clang/test/SemaCXX/decomposed-condition.cpp index ab011f6ae4ba437caddcc89c193e4315e2160b70..e55bbee3134ca205c98c6bda4d186ed8b8c321cc 100644 --- a/clang/test/SemaCXX/decomposed-condition.cpp +++ b/clang/test/SemaCXX/decomposed-condition.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++1z -Wno-binding-in-condition -verify %s +// RUN: %clang_cc1 -std=c++1z -Wno-binding-in-condition -verify %s -fexperimental-new-constant-interpreter struct X { bool flag; diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp index 431d77ca785b8e930b5090d64ac6a2bd4da7dae1..c33e07088ba32f652f13d88e0945d553d367ddf2 100644 --- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp +++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp @@ -237,6 +237,24 @@ namespace Templates { int (S::*(*p)())(double) = f; int (S::*(*q)())(double) = f<S, double>; } + + template<typename T> + struct MemberSpecialization { + auto f(); + template<typename U> auto f(U); + template<typename U> auto *f(U); + }; + + template<> + auto MemberSpecialization<int>::f(); + + template<> + template<typename U> + auto MemberSpecialization<int>::f(U); + + template<> + template<typename U> + auto *MemberSpecialization<int>::f(U); } auto fwd_decl_using(); diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp index 0516a5da31ae9a94f7c2da454f15189daf2a8b6f..151d74f21d64dc8bf1c22f46bc2a550434eaf6fd 100644 --- a/clang/test/SemaCXX/lambda-expressions.cpp +++ b/clang/test/SemaCXX/lambda-expressions.cpp @@ -1,5 +1,7 @@ -// RUN: %clang_cc1 -std=c++14 -Wno-unused-value -fsyntax-only -verify -verify=expected-cxx14 -fblocks %s -// RUN: %clang_cc1 -std=c++17 -Wno-unused-value -verify -ast-dump -fblocks %s | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -Wno-unused-value -fsyntax-only -verify=expected,not-cxx03,cxx03-cxx11,cxx11,expected-cxx14 -fblocks %s +// RUN: %clang_cc1 -std=c++03 -Wno-unused-value -fsyntax-only -verify=expected,cxx03,cxx03-cxx11,expected-cxx14 -fblocks %s -Ddecltype=__decltype -Dstatic_assert=_Static_assert -Wno-c++11-extensions +// RUN: %clang_cc1 -std=c++14 -Wno-unused-value -fsyntax-only -verify=expected,not-cxx03,expected-cxx14 -fblocks %s +// RUN: %clang_cc1 -std=c++17 -Wno-unused-value -verify=expected,not-cxx03 -ast-dump -fblocks %s | FileCheck %s namespace std { class type_info; }; @@ -92,14 +94,14 @@ namespace ImplicitCapture { [] { return ref_i; }; // expected-error {{variable 'ref_i' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} expected-note 2 {{capture 'ref_i' by}} expected-note 2 {{default capture by}} static int j; - int &ref_j = j; - [] { return ref_j; }; // ok + int &ref_j = j; // cxx03-note {{declared here}} + [] { return ref_j; }; // cxx03-error {{variable 'ref_j' cannot be implicitly captured in a lambda with no capture-default specified}} cxx03-note 4 {{capture}} cxx03-note {{lambda expression begins here}} } } namespace SpecialMembers { void f() { - auto a = []{}; // expected-note 2{{here}} expected-note 2{{candidate}} + auto a = []{}; // expected-note 2{{here}} expected-note {{candidate}} not-cxx03-note {{candidate}} decltype(a) b; // expected-error {{no matching constructor}} decltype(a) c = a; decltype(a) d = static_cast<decltype(a)&&>(a); @@ -212,7 +214,7 @@ namespace VariadicPackExpansion { }; template<typename...Ts> void local_class() { - sink { + sink s( [] (Ts t) { struct S : Ts { void f(Ts t) { @@ -225,7 +227,7 @@ namespace VariadicPackExpansion { s.f(t); return s; } (Ts()).g() ... - }; + ); }; struct X {}; struct Y {}; template void local_class<X, Y>(); @@ -295,7 +297,7 @@ namespace PR16708 { namespace TypeDeduction { struct S {}; void f() { - const S s {}; + const S s = S(); S &&t = [&] { return s; } (); #if __cplusplus > 201103L S &&u = [&] () -> auto { return s; } (); @@ -307,7 +309,7 @@ namespace TypeDeduction { namespace lambdas_in_NSDMIs { template<class T> struct L { - T t{}; + T t = T(); T t2 = ([](int a) { return [](int b) { return b; };})(t)(t); }; L<int> l; @@ -344,6 +346,7 @@ namespace CaptureIncomplete { } } +#if __cplusplus >= 201103L namespace CaptureAbstract { struct S { virtual void f() = 0; // expected-note {{unimplemented}} @@ -361,6 +364,7 @@ namespace CaptureAbstract { [=] { return s.n; }; // expected-error {{abstract}} } } +#endif namespace PR18128 { auto l = [=]{}; // expected-error {{non-local lambda expression cannot have a capture-default}} @@ -371,6 +375,8 @@ namespace PR18128 { // expected-error@-1 {{non-local lambda expression cannot have a capture-default}} // expected-error@-2 {{invalid use of non-static data member 'n'}} // expected-cxx14-error@-3 {{a lambda expression may not appear inside of a constant expression}} + // cxx03-error@-4 {{function declaration cannot have variably modified type}} + // cxx03-warning@-5 {{variable length arrays in C++ are a Clang extension}} int g(int k = ([=]{ return n; }(), 0)); // expected-error@-1 {{non-local lambda expression cannot have a capture-default}} // expected-error@-2 {{invalid use of non-static data member 'n'}} @@ -433,13 +439,13 @@ struct A { template <typename F> void g(F f) { - auto a = A<decltype(f())>{}; + auto a = A<decltype(f())>(); // expected-note@-1 {{in instantiation of template class 'PR20731::A<void>' requested here}} auto xf = [a, f]() {}; int x = sizeof(xf); }; void f() { - g([] {}); + g([] {}); // cxx03-warning {{template argument uses local type}} // expected-note-re@-1 {{in instantiation of function template specialization 'PR20731::g<(lambda at {{.*}}>' requested here}} } @@ -490,8 +496,8 @@ namespace PR21857 { fun() = default; using Fn::operator(); }; - template<typename Fn> fun<Fn> wrap(Fn fn); - auto x = wrap([](){}); + template<typename Fn> fun<Fn> wrap(Fn fn); // cxx03-warning {{template argument uses unnamed type}} + auto x = wrap([](){}); // cxx03-warning {{template argument uses unnamed type}} cxx03-note 2 {{unnamed type used in template argument was declared here}} } namespace PR13987 { @@ -558,8 +564,8 @@ struct B { int x; A a = [&] { int y = x; }; A b = [&] { [&] { [&] { int y = x; }; }; }; - A d = [&](auto param) { int y = x; }; - A e = [&](auto param) { [&] { [&](auto param2) { int y = x; }; }; }; + A d = [&](auto param) { int y = x; }; // cxx03-cxx11-error {{'auto' not allowed in lambda parameter}} + A e = [&](auto param) { [&] { [&](auto param2) { int y = x; }; }; }; // cxx03-cxx11-error 2 {{'auto' not allowed in lambda parameter}} }; B<int> b; @@ -587,8 +593,9 @@ struct S1 { }; void foo1() { - auto s0 = S1{[name=]() {}}; // expected-error 2 {{expected expression}} - auto s1 = S1{[name=name]() {}}; // expected-error {{use of undeclared identifier 'name'; did you mean 'name1'?}} + auto s0 = S1([name=]() {}); // expected-error {{expected expression}} + auto s1 = S1([name=name]() {}); // expected-error {{use of undeclared identifier 'name'; did you mean 'name1'?}} + // cxx03-cxx11-warning@-1 {{initialized lambda captures are a C++14 extension}} } } @@ -604,7 +611,7 @@ namespace PR25627_dont_odr_use_local_consts { namespace ConversionOperatorDoesNotHaveDeducedReturnType { auto x = [](int){}; - auto y = [](auto &v) -> void { v.n = 0; }; + auto y = [](auto &v) -> void { v.n = 0; }; // cxx03-cxx11-error {{'auto' not allowed in lambda parameter}} cxx03-cxx11-note {{candidate function not viable}} cxx03-cxx11-note {{conversion candidate}} using T = decltype(x); using U = decltype(y); using ExpectedTypeT = void (*)(int); @@ -624,22 +631,23 @@ namespace ConversionOperatorDoesNotHaveDeducedReturnType { template<typename T> friend constexpr U::operator ExpectedTypeU<T>() const noexcept; #else - friend auto T::operator()(int) const; + friend auto T::operator()(int) const; // cxx11-error {{'auto' return without trailing return type; deduced return types are a C++14 extension}} \ + cxx03-error {{'auto' not allowed in function return type}} friend T::operator ExpectedTypeT() const; template<typename T> - friend void U::operator()(T&) const; + friend void U::operator()(T&) const; // cxx03-cxx11-error {{friend declaration of 'operator()' does not match any declaration}} // FIXME: This should not match, as above. template<typename T> - friend U::operator ExpectedTypeU<T>() const; + friend U::operator ExpectedTypeU<T>() const; // cxx03-cxx11-error {{friend declaration of 'operator void (*)(type-parameter-0-0 &)' does not match any declaration}} #endif private: int n; }; - // Should be OK: lambda's call operator is a friend. - void use(X &x) { y(x); } + // Should be OK in C++14 and later: lambda's call operator is a friend. + void use(X &x) { y(x); } // cxx03-cxx11-error {{no matching function for call to object}} // This used to crash in return type deduction for the conversion opreator. struct A { int n; void f() { +[](decltype(n)) {}; } }; @@ -680,8 +688,8 @@ namespace GH60518 { // function parameters that are used in enable_if struct StringLiteral { template <int N> -StringLiteral(const char (&array)[N]) - __attribute__((enable_if(__builtin_strlen(array) == 2, +StringLiteral(const char (&array)[N]) // cxx03-note {{declared here}} + __attribute__((enable_if(__builtin_strlen(array) == 2, // cxx03-error {{'enable_if' attribute expression never produces a constant expression}} cxx03-note {{read of variable}} "invalid string literal"))); }; @@ -693,7 +701,7 @@ StringLiteral(const char (&array)[N]) [[clang::annotate_type("test", array)]]; } void Func1() { - [[maybe_unused]] auto y = [&](decltype(StringLiteral("xx"))) {}; + [[maybe_unused]] auto y = [&](decltype(StringLiteral("xx"))) {}; // cxx03-note {{in instantiation of function template specialization}} [[maybe_unused]] auto z = [&](decltype(cpp_attribute::StringLiteral("xx"))) {}; } @@ -716,6 +724,7 @@ static_assert([]() constexpr { // Call operator attributes refering to a variable should // be properly handled after D124351 +#if __cplusplus >= 201103L constexpr int i = 2; void foo() { (void)[=][[gnu::aligned(i)]] () {}; // expected-warning{{C++23 extension}} @@ -723,16 +732,21 @@ void foo() { // CHECK-NEXT: ConstantExpr // CHECK-NEXT: value: Int 2 } +#endif void GH48527() { auto a = []()__attribute__((b(({ return 0; })))){}; // expected-warning {{unknown attribute 'b' ignored}} } +#if __cplusplus >= 201103L void GH67492() { constexpr auto test = 42; auto lambda = (test, []() noexcept(true) {}); } +#endif +// FIXME: This currently causes clang to crash in C++11 mode. +#if __cplusplus >= 201402L namespace GH83267 { auto l = [](auto a) { return 1; }; using type = decltype(l); @@ -747,3 +761,4 @@ using t = decltype(ll); template auto t::operator()<int>(int a) const; // expected-note {{in instantiation}} } +#endif diff --git a/clang/test/SemaCXX/lambda-implicit-this-capture.cpp b/clang/test/SemaCXX/lambda-implicit-this-capture.cpp index 7e0e347a8fee794d4fb7d04921191239e4c3dced..eb1f9e880aec0f42bff911458f43843baab12510 100644 --- a/clang/test/SemaCXX/lambda-implicit-this-capture.cpp +++ b/clang/test/SemaCXX/lambda-implicit-this-capture.cpp @@ -1,3 +1,4 @@ +// RUN: %clang_cc1 -std=c++03 -verify=cxx11 %s -Wno-c++11-extensions // RUN: %clang_cc1 -std=c++11 -verify=cxx11 %s // RUN: %clang_cc1 -std=c++2a -verify=cxx2a %s // RUN: %clang_cc1 -std=c++2a -verify=cxx2a-no-deprecated %s -Wno-deprecated diff --git a/clang/test/SemaCXX/lambda-invalid-capture.cpp b/clang/test/SemaCXX/lambda-invalid-capture.cpp index 236753871d7018b74db0ac178717b8ae7969e8fc..5be8c8c5078f2690f5142e6e1ec404959ffd9669 100644 --- a/clang/test/SemaCXX/lambda-invalid-capture.cpp +++ b/clang/test/SemaCXX/lambda-invalid-capture.cpp @@ -1,3 +1,4 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++03 -Wno-c++11-extensions %s // RUN: %clang_cc1 -fsyntax-only -verify %s // Don't crash. diff --git a/clang/test/SemaCXX/namespace-alias.cpp b/clang/test/SemaCXX/namespace-alias.cpp index 281ee9962e8b52e3457ee0f6565f17efab624d06..591957a657c03a9bdb8777501df4791359893b0a 100644 --- a/clang/test/SemaCXX/namespace-alias.cpp +++ b/clang/test/SemaCXX/namespace-alias.cpp @@ -47,6 +47,8 @@ namespace I { namespace A1 { int i; } namespace A2 = A1; + + namespace A3::extra::specifiers = A2; // expected-error {{alias must be a single identifier}} } int f() { diff --git a/clang/test/SemaCXX/new-delete.cpp b/clang/test/SemaCXX/new-delete.cpp index 4f78b7c71a91c5ddaad091d5f376cffe6a48bc39..1a99c6aac604f590cfe2e2a34705758107d18fb4 100644 --- a/clang/test/SemaCXX/new-delete.cpp +++ b/clang/test/SemaCXX/new-delete.cpp @@ -171,12 +171,7 @@ void good_deletes() void bad_deletes() { delete 0; // expected-error {{cannot delete expression of type 'int'}} - delete [0] (int*)0; -#if __cplusplus <= 199711L - // expected-error@-2 {{expected expression}} -#else - // expected-error@-4 {{expected variable name or 'this' in lambda capture list}} -#endif + delete [0] (int*)0; // expected-error {{expected variable name or 'this' in lambda capture list}} delete (void*)0; // expected-warning {{cannot delete expression with pointer-to-'void' type 'void *'}} delete (T*)0; // expected-warning {{deleting pointer to incomplete type}} ::S::delete (int*)0; // expected-error {{expected unqualified-id}} diff --git a/clang/test/SemaCXX/nullability.cpp b/clang/test/SemaCXX/nullability.cpp index 8d0c4dc195a6bd66b2843095015945688629193a..d52ba4efaccdbd01ff1ebd85ab37e8c92f7709d5 100644 --- a/clang/test/SemaCXX/nullability.cpp +++ b/clang/test/SemaCXX/nullability.cpp @@ -4,6 +4,10 @@ #else # error nullability feature should be defined #endif +#if __has_feature(nullability_on_classes) +#else +# error smart-pointer feature should be defined +#endif #include "nullability-completeness.h" @@ -27,6 +31,7 @@ template<typename T> struct AddNonNull { typedef _Nonnull T type; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int'}} // expected-error@-1{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'std::nullptr_t'}} + // expected-error@-2{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'NotPtr'}} }; typedef AddNonNull<int *>::type nonnull_int_ptr_1; @@ -35,6 +40,33 @@ typedef AddNonNull<nullptr_t>::type nonnull_int_ptr_3; // expected-note{{in inst typedef AddNonNull<int>::type nonnull_non_pointer_1; // expected-note{{in instantiation of template class 'AddNonNull<int>' requested here}} +// Nullability on C++ class types (smart pointers). +struct NotPtr{}; +typedef AddNonNull<NotPtr>::type nonnull_non_pointer_2; // expected-note{{in instantiation}} +struct _Nullable SmartPtr{ + SmartPtr(); + SmartPtr(nullptr_t); + SmartPtr(const SmartPtr&); + SmartPtr(SmartPtr&&); + SmartPtr &operator=(const SmartPtr&); + SmartPtr &operator=(SmartPtr&&); +}; +typedef AddNonNull<SmartPtr>::type nonnull_smart_pointer_1; +template<class> struct _Nullable SmartPtrTemplate{}; +typedef AddNonNull<SmartPtrTemplate<int>>::type nonnull_smart_pointer_2; +namespace std { inline namespace __1 { + template <class> class unique_ptr {}; + template <class> class function; + template <class Ret, class... Args> class function<Ret(Args...)> {}; +} } +typedef AddNonNull<std::unique_ptr<int>>::type nonnull_smart_pointer_3; +typedef AddNonNull<std::function<int()>>::type nonnull_smart_pointer_4; + +class Derived : public SmartPtr {}; +Derived _Nullable x; // expected-error {{'_Nullable' cannot be applied}} +class DerivedPrivate : private SmartPtr {}; +DerivedPrivate _Nullable y; // expected-error {{'_Nullable' cannot be applied}} + // Non-null checking within a template. template<typename T> struct AddNonNull2 { @@ -54,6 +86,7 @@ void (*& accepts_nonnull_2)(_Nonnull int *ptr) = accepts_nonnull_1; void (X::* accepts_nonnull_3)(_Nonnull int *ptr); void accepts_nonnull_4(_Nonnull int *ptr); void (&accepts_nonnull_5)(_Nonnull int *ptr) = accepts_nonnull_4; +void accepts_nonnull_6(SmartPtr _Nonnull); void test_accepts_nonnull_null_pointer_literal(X *x) { accepts_nonnull_1(0); // expected-warning{{null passed to a callee that requires a non-null argument}} @@ -61,6 +94,8 @@ void test_accepts_nonnull_null_pointer_literal(X *x) { (x->*accepts_nonnull_3)(0); // expected-warning{{null passed to a callee that requires a non-null argument}} accepts_nonnull_4(0); // expected-warning{{null passed to a callee that requires a non-null argument}} accepts_nonnull_5(0); // expected-warning{{null passed to a callee that requires a non-null argument}} + + accepts_nonnull_6(nullptr); // expected-warning{{null passed to a callee that requires a non-null argument}} } template<void FP(_Nonnull int*)> @@ -71,6 +106,7 @@ void test_accepts_nonnull_null_pointer_literal_template() { template void test_accepts_nonnull_null_pointer_literal_template<&accepts_nonnull_4>(); // expected-note{{instantiation of function template specialization}} void TakeNonnull(void *_Nonnull); +void TakeSmartNonnull(SmartPtr _Nonnull); // Check different forms of assignment to a nonull type from a nullable one. void AssignAndInitNonNull() { void *_Nullable nullable; @@ -81,12 +117,26 @@ void AssignAndInitNonNull() { void *_Nonnull nonnull; nonnull = nullable; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} nonnull = {nullable}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} - TakeNonnull(nullable); //expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull}} TakeNonnull(nonnull); // OK + nonnull = (void *_Nonnull)nullable; // explicit cast OK + + SmartPtr _Nullable s_nullable; + SmartPtr _Nonnull s(s_nullable); // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} + SmartPtr _Nonnull s2{s_nullable}; // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} + SmartPtr _Nonnull s3 = {s_nullable}; // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} + SmartPtr _Nonnull s4 = s_nullable; // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} + SmartPtr _Nonnull s_nonnull; + s_nonnull = s_nullable; // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} + s_nonnull = {s_nullable}; // no warning here - might be nice? + TakeSmartNonnull(s_nullable); //expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull}} + TakeSmartNonnull(s_nonnull); // OK + s_nonnull = (SmartPtr _Nonnull)s_nullable; // explicit cast OK + s_nonnull = static_cast<SmartPtr _Nonnull>(s_nullable); // explicit cast OK } void *_Nullable ReturnNullable(); +SmartPtr _Nullable ReturnSmartNullable(); void AssignAndInitNonNullFromFn() { void *_Nonnull p(ReturnNullable()); // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} @@ -96,8 +146,16 @@ void AssignAndInitNonNullFromFn() { void *_Nonnull nonnull; nonnull = ReturnNullable(); // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} nonnull = {ReturnNullable()}; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}} - TakeNonnull(ReturnNullable()); //expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull}} + + SmartPtr _Nonnull s(ReturnSmartNullable()); // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} + SmartPtr _Nonnull s2{ReturnSmartNullable()}; // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} + SmartPtr _Nonnull s3 = {ReturnSmartNullable()}; // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} + SmartPtr _Nonnull s4 = ReturnSmartNullable(); // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} + SmartPtr _Nonnull s_nonnull; + s_nonnull = ReturnSmartNullable(); // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} + s_nonnull = {ReturnSmartNullable()}; + TakeSmartNonnull(ReturnSmartNullable()); // expected-warning{{implicit conversion from nullable pointer 'SmartPtr _Nullable' to non-nullable pointer type 'SmartPtr _Nonnull'}} } void ConditionalExpr(bool c) { diff --git a/clang/test/SemaCXX/source_location.cpp b/clang/test/SemaCXX/source_location.cpp index b151fc45fdad62b79c1a79b64e973478e60b702e..63157cfacdd98bf39440a0cc904e3ea25a516787 100644 --- a/clang/test/SemaCXX/source_location.cpp +++ b/clang/test/SemaCXX/source_location.cpp @@ -1,14 +1,14 @@ // RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fexceptions -verify %s // RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -DUSE_CONSTEVAL -fexceptions -verify %s // RUN: %clang_cc1 -std=c++2b -fcxx-exceptions -DUSE_CONSTEVAL -DPAREN_INIT -fexceptions -verify %s -// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fms-extensions -DMS -fexceptions -verify %s -// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fms-extensions -DMS -DUSE_CONSTEVAL -fexceptions -verify %s +// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fms-extensions -DMS -fexceptions -fms-compatibility -verify %s +// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fms-extensions -DMS -DUSE_CONSTEVAL -fexceptions -fms-compatibility -verify %s // // RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s // RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -DUSE_CONSTEVAL -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s // RUN: %clang_cc1 -std=c++2b -fcxx-exceptions -DUSE_CONSTEVAL -DPAREN_INIT -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s -// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fms-extensions -DMS -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s -// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fms-extensions -DMS -DUSE_CONSTEVAL -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s +// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fms-extensions -DMS -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -fms-compatibility -verify %s +// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fms-extensions -DMS -DUSE_CONSTEVAL -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify -fms-compatibility %s // expected-no-diagnostics #define assert(...) ((__VA_ARGS__) ? ((void)0) : throw 42) @@ -463,8 +463,70 @@ void ctor_tests() { constexpr SL global_sl = SL::current(); static_assert(is_equal(global_sl.function(), "")); +template <class T> +class TestBI { +public: + TestBI() { +#ifdef MS + static_assert(is_equal(__FUNCTION__, "test_func::TestBI<int>::TestBI")); +#else + static_assert(is_equal(__FUNCTION__, "TestBI")); +#endif + static_assert(is_equal(__func__, "TestBI")); + } +}; + +template <class T> +class TestClass { +public: + TestClass() { +#ifdef MS + static_assert(is_equal(__FUNCTION__, "test_func::TestClass<class test_func::C>::TestClass")); +#else + static_assert(is_equal(__FUNCTION__, "TestClass")); +#endif + static_assert(is_equal(__func__, "TestClass")); + } +}; + +template <class T> +class TestStruct { +public: + TestStruct() { +#ifdef MS + static_assert(is_equal(__FUNCTION__, "test_func::TestStruct<struct test_func::S>::TestStruct")); +#else + static_assert(is_equal(__FUNCTION__, "TestStruct")); +#endif + static_assert(is_equal(__func__, "TestStruct")); + } +}; + +template <class T> +class TestEnum { +public: + TestEnum() { +#ifdef MS + static_assert(is_equal(__FUNCTION__, "test_func::TestEnum<enum test_func::E>::TestEnum")); +#else + static_assert(is_equal(__FUNCTION__, "TestEnum")); +#endif + static_assert(is_equal(__func__, "TestEnum")); + } +}; + +class C {}; +struct S {}; +enum E {}; + +TestBI<int> t1; +TestClass<test_func::C> t2; +TestStruct<test_func::S> t3; +TestEnum<test_func::E> t4; + } // namespace test_func + //===----------------------------------------------------------------------===// // __builtin_FUNCSIG() //===----------------------------------------------------------------------===// diff --git a/clang/test/SemaCXX/warn-cast-function-type-strict.cpp b/clang/test/SemaCXX/warn-cast-function-type-strict.cpp index f7ee55f84ac2807e77216ca3115df50a8b54bcea..8887b3c4c5d535df9338aa1cd7ebd18a1f6da635 100644 --- a/clang/test/SemaCXX/warn-cast-function-type-strict.cpp +++ b/clang/test/SemaCXX/warn-cast-function-type-strict.cpp @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 %s -fblocks -fsyntax-only -Wcast-function-type -verify -// RUN: %clang_cc1 %s -fblocks -fsyntax-only -Wcast-function-type-strict -verify +// RUN: %clang_cc1 %s -fblocks -fsyntax-only -Wcast-function-type -verify=expected,strict +// RUN: %clang_cc1 %s -fblocks -fsyntax-only -Wcast-function-type-strict -verify=expected,strict +// RUN: %clang_cc1 %s -fblocks -fsyntax-only -Wextra -verify int x(long); @@ -32,11 +33,11 @@ void foo() { a = (f1 *)x; b = (f2 *)x; // expected-warning {{cast from 'int (*)(long)' to 'f2 *' (aka 'int (*)(void *)') converts to incompatible function type}} b = reinterpret_cast<f2 *>(x); // expected-warning {{cast from 'int (*)(long)' to 'f2 *' (aka 'int (*)(void *)') converts to incompatible function type}} - c = (f3 *)x; // expected-warning {{cast from 'int (*)(long)' to 'f3 *' (aka 'int (*)(...)') converts to incompatible function type}} + c = (f3 *)x; // strict-warning {{cast from 'int (*)(long)' to 'f3 *' (aka 'int (*)(...)') converts to incompatible function type}} d = (f4 *)x; // expected-warning {{cast from 'int (*)(long)' to 'f4 *' (aka 'void (*)(...)') converts to incompatible function type}} - e = (f5 *)x; // expected-warning {{cast from 'int (*)(long)' to 'f5 *' (aka 'void (*)()') converts to incompatible function type}} + e = (f5 *)x; // strict-warning {{cast from 'int (*)(long)' to 'f5 *' (aka 'void (*)()') converts to incompatible function type}} f = (f6 *)x; // expected-warning {{cast from 'int (*)(long)' to 'f6 *' (aka 'int (*)(long, int)') converts to incompatible function type}} - g = (f7 *)x; // expected-warning {{cast from 'int (*)(long)' to 'f7 *' (aka 'int (*)(long, ...)') converts to incompatible function type}} + g = (f7 *)x; // strict-warning {{cast from 'int (*)(long)' to 'f7 *' (aka 'int (*)(long, ...)') converts to incompatible function type}} mf p1 = (mf)&S::foo; // expected-warning {{cast from 'void (S::*)(int *)' to 'mf' (aka 'void (S::*)(int)') converts to incompatible function type}} diff --git a/clang/test/SemaCXX/warn-cast-function-type.cpp b/clang/test/SemaCXX/warn-cast-function-type.cpp index c613aaea1e33f266474fa85f35104c548faf54b8..db2ee030fcbfc95e0bbf10cb627037a2f99274bf 100644 --- a/clang/test/SemaCXX/warn-cast-function-type.cpp +++ b/clang/test/SemaCXX/warn-cast-function-type.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -fblocks -fsyntax-only -Wcast-function-type -Wno-cast-function-type-strict -verify +// RUN: %clang_cc1 %s -fblocks -fsyntax-only -Wextra -Wno-cast-function-type-strict -verify int x(long); diff --git a/clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp b/clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp index 35dc69cccb3a2e299d72386610c9fb2257bf0278..fa40c13971118da4564c7d3c1691183b5deb701b 100644 --- a/clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp +++ b/clang/test/SemaCXX/warn-constant-evaluated-constexpr.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++2a -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++2a -fsyntax-only -verify %s -fexperimental-new-constant-interpreter namespace std { constexpr bool is_constant_evaluated() noexcept { diff --git a/clang/test/SemaCXX/warn-exit-time-destructors.cpp b/clang/test/SemaCXX/warn-exit-time-destructors.cpp index 2f14243cb48c470ad86a2124eda1c7e37c09d598..55ae37d7368f884f6ce1a54a95f0d8f76927dc36 100644 --- a/clang/test/SemaCXX/warn-exit-time-destructors.cpp +++ b/clang/test/SemaCXX/warn-exit-time-destructors.cpp @@ -51,6 +51,15 @@ struct A { ~A(); }; } namespace test5 { + struct A { ~A(); }; + [[clang::always_destroy]] A a; // no warning + + void func() { + [[clang::always_destroy]] static A a; // no warning + } +} + +namespace test6 { #if __cplusplus >= 202002L #define CPP20_CONSTEXPR constexpr #else @@ -68,3 +77,4 @@ namespace test5 { T t; // expected-warning {{exit-time destructor}} #undef CPP20_CONSTEXPR } + diff --git a/clang/test/SemaHLSL/ArrayParams.hlsl b/clang/test/SemaHLSL/ArrayParams.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..75af9d775206e6a48eaf8c0ddbe072f67bc6a18c --- /dev/null +++ b/clang/test/SemaHLSL/ArrayParams.hlsl @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library %s -verify + +void fn(int I[5]); // #fn +void fn2(int I[3][3]); // #fn2 + +void call() { + float F[5]; + double D[4]; + int Long[9]; + int Short[4]; + int Same[5]; + + fn(F); // expected-error{{no matching function for call to 'fn'}} + // expected-note@#fn{{candidate function not viable: no known conversion from 'float[5]' to 'int[5]' for 1st argument}} + + fn(D); // expected-error{{no matching function for call to 'fn'}} + // expected-note@#fn{{candidate function not viable: no known conversion from 'double[4]' to 'int[5]' for 1st argument}} + + fn(Long); // expected-error{{no matching function for call to 'fn'}} + // expected-note@#fn{{candidate function not viable: no known conversion from 'int[9]' to 'int[5]' for 1st argument}} + + fn(Short); // expected-error{{no matching function for call to 'fn'}} + // expected-note@#fn{{candidate function not viable: no known conversion from 'int[4]' to 'int[5]' for 1st argument}} + + fn(Same); // totally fine, nothing to see here. + + fn2(Long); // expected-error{{no matching function for call to 'fn2'}} + // expected-note@#fn2{{candidate function not viable: no known conversion from 'int[9]' to 'int[3][3]' for 1st argument}} +} diff --git a/clang/test/SemaHLSL/ArrayTemporary.hlsl b/clang/test/SemaHLSL/ArrayTemporary.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..dff9aff7d9b2998cc7ddb86b6e3d85f8d886e7f9 --- /dev/null +++ b/clang/test/SemaHLSL/ArrayTemporary.hlsl @@ -0,0 +1,95 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -ast-dump %s | FileCheck %s + +void fn(float x[2]) { } + +// CHECK: CallExpr {{.*}} 'void' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float[2])' <FunctionToPointerDecay> +// CHECK-NEXT: DeclRefExpr {{.*}} 'void (float[2])' lvalue Function {{.*}} 'fn' 'void (float[2])' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float[2]' <HLSLArrayRValue> + +void call() { + float Arr[2] = {0, 0}; + fn(Arr); +} + +struct Obj { + float V; + int X; +}; + +void fn2(Obj O[4]) { } + +// CHECK: CallExpr {{.*}} 'void' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(Obj[4])' <FunctionToPointerDecay> +// CHECK-NEXT: DeclRefExpr {{.*}} 'void (Obj[4])' lvalue Function {{.*}} 'fn2' 'void (Obj[4])' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'Obj[4]' <HLSLArrayRValue> + +void call2() { + Obj Arr[4] = {}; + fn2(Arr); +} + + +void fn3(float x[2][2]) { } + +// CHECK: CallExpr {{.*}} 'void' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float[2][2])' <FunctionToPointerDecay> +// CHECK-NEXT: DeclRefExpr {{.*}} 'void (float[2][2])' lvalue Function {{.*}} 'fn3' 'void (float[2][2])' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float[2][2]' <HLSLArrayRValue> + +void call3() { + float Arr[2][2] = {{0, 0}, {1,1}}; + fn3(Arr); +} + +// This template function should be instantiated 3 times for the different array +// types and lengths. + +// CHECK: FunctionTemplateDecl {{.*}} template_fn +// CHECK-NEXT: TemplateTypeParmDecl {{.*}} referenced typename depth 0 index 0 T +// CHECK-NEXT: FunctionDecl {{.*}} template_fn 'void (T)' +// CHECK-NEXT: ParmVarDecl {{.*}} Val 'T' + +// CHECK: FunctionDecl {{.*}} used template_fn 'void (float[2])' implicit_instantiation +// CHECK-NEXT: TemplateArgument type 'float[2]' +// CHECK-NEXT: ArrayParameterType {{.*}} 'float[2]' 2 +// CHECK-NEXT: BuiltinType {{.*}} 'float' +// CHECK-NEXT: ParmVarDecl {{.*}} Val 'float[2]' + +// CHECK: FunctionDecl {{.*}} used template_fn 'void (float[4])' implicit_instantiation +// CHECK-NEXT: TemplateArgument type 'float[4]' +// CHECK-NEXT: ArrayParameterType {{.*}} 'float[4]' 4 +// CHECK-NEXT: BuiltinType {{.*}} 'float' +// CHECK-NEXT: ParmVarDecl {{.*}} Val 'float[4]' + +// CHECK: FunctionDecl {{.*}} used template_fn 'void (int[3])' implicit_instantiation +// CHECK-NEXT: TemplateArgument type 'int[3]' +// CHECK-NEXT: ArrayParameterType {{.*}} 'int[3]' 3 +// CHECK-NEXT: BuiltinType {{.*}} 'int' +// CHECK-NEXT: ParmVarDecl {{.*}} Val 'int[3]' + +template<typename T> +void template_fn(T Val) {} + +// CHECK: FunctionDecl {{.*}} call 'void (float[2], float[4], int[3])' +// CHECK: CallExpr {{.*}} 'void' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float[2])' <FunctionToPointerDecay> +// CHECK-NEXT: DeclRefExpr {{.*}} 'void (float[2])' lvalue Function {{.*}} 'template_fn' 'void (float[2])' (FunctionTemplate {{.*}} 'template_fn') +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float[2]' <LValueToRValue> +// CHECK-NEXT: DeclRefExpr {{.*}} 'float[2]' lvalue ParmVar {{.*}} 'FA2' 'float[2]' +// CHECK-NEXT: CallExpr {{.*}} 'void' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float[4])' <FunctionToPointerDecay> +// CHECK-NEXT: DeclRefExpr {{.*}} 'void (float[4])' lvalue Function {{.*}} 'template_fn' 'void (float[4])' (FunctionTemplate {{.*}} 'template_fn') +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float[4]' <LValueToRValue> +// CHECK-NEXT: DeclRefExpr {{.*}} 'float[4]' lvalue ParmVar {{.*}} 'FA4' 'float[4]' +// CHECK-NEXT: CallExpr {{.*}} 'void' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(int[3])' <FunctionToPointerDecay> +// CHECK-NEXT: DeclRefExpr {{.*}} 'void (int[3])' lvalue Function {{.*}} 'template_fn' 'void (int[3])' (FunctionTemplate {{.*}} 'template_fn') +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int[3]' <LValueToRValue> +// CHECK-NEXT: DeclRefExpr {{.*}} 'int[3]' lvalue ParmVar {{.*}} 'IA3' 'int[3]' + +void call(float FA2[2], float FA4[4], int IA3[3]) { + template_fn(FA2); + template_fn(FA4); + template_fn(IA3); +} diff --git a/clang/test/SemaHLSL/ArrayTemporary.ll b/clang/test/SemaHLSL/ArrayTemporary.ll new file mode 100644 index 0000000000000000000000000000000000000000..5eec0094865bae8b862c68062cf9c06e4da2d67d --- /dev/null +++ b/clang/test/SemaHLSL/ArrayTemporary.ll @@ -0,0 +1,76 @@ +; ModuleID = '/Users/cbieneman/dev/llvm-project/clang/test/SemaHLSL/ArrayTemporary.hlsl' +source_filename = "/Users/cbieneman/dev/llvm-project/clang/test/SemaHLSL/ArrayTemporary.hlsl" +target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-pc-shadermodel6.3-library" + +%struct.Obj = type { float, i32 } + +@"__const.?call3@@YAXXZ.Arr" = private unnamed_addr constant [2 x [2 x float]] [[2 x float] zeroinitializer, [2 x float] [float 1.000000e+00, float 1.000000e+00]], align 4 + +; Function Attrs: noinline nounwind optnone +define void @"?fn@@YAXY01M@Z"(ptr noundef byval([2 x float]) align 4 %x) #0 { +entry: + ret void +} + +; Function Attrs: noinline nounwind optnone +define void @"?call@@YAXXZ"() #0 { +entry: + %Arr = alloca [2 x float], align 4 + %agg.tmp = alloca [2 x float], align 4 + call void @llvm.memset.p0.i32(ptr align 4 %Arr, i8 0, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %agg.tmp, ptr align 4 %Arr, i32 8, i1 false) + call void @"?fn@@YAXY01M@Z"(ptr noundef byval([2 x float]) align 4 %agg.tmp) + ret void +} + +; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write) +declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) #1 + +; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite) +declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) #2 + +; Function Attrs: noinline nounwind optnone +define void @"?fn2@@YAXY03UObj@@@Z"(ptr noundef byval([4 x %struct.Obj]) align 4 %O) #0 { +entry: + ret void +} + +; Function Attrs: noinline nounwind optnone +define void @"?call2@@YAXXZ"() #0 { +entry: + %Arr = alloca [4 x %struct.Obj], align 4 + %agg.tmp = alloca [4 x %struct.Obj], align 4 + call void @llvm.memset.p0.i32(ptr align 4 %Arr, i8 0, i32 32, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %agg.tmp, ptr align 4 %Arr, i32 32, i1 false) + call void @"?fn2@@YAXY03UObj@@@Z"(ptr noundef byval([4 x %struct.Obj]) align 4 %agg.tmp) + ret void +} + +; Function Attrs: noinline nounwind optnone +define void @"?fn3@@YAXY111M@Z"(ptr noundef byval([2 x [2 x float]]) align 4 %x) #0 { +entry: + ret void +} + +; Function Attrs: noinline nounwind optnone +define void @"?call3@@YAXXZ"() #0 { +entry: + %Arr = alloca [2 x [2 x float]], align 4 + %agg.tmp = alloca [2 x [2 x float]], align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %Arr, ptr align 4 @"__const.?call3@@YAXXZ.Arr", i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %agg.tmp, ptr align 4 %Arr, i32 16, i1 false) + call void @"?fn3@@YAXY111M@Z"(ptr noundef byval([2 x [2 x float]]) align 4 %agg.tmp) + ret void +} + +attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: write) } +attributes #2 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } + +!llvm.module.flags = !{!0, !1} +!llvm.ident = !{!2} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 4, !"dx.disable_optimizations", i32 1} +!2 = !{!"clang version 19.0.0git (git@github.com:llvm/llvm-project.git 64e1c15c520cf11114ef2ddd887e76560903db2b)"} diff --git a/clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..4c0e5315ce532e14360d5ca899a6e559d899e640 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/clamp-errors.hlsl @@ -0,0 +1,91 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected + +float2 test_no_second_arg(float2 p0) { + return __builtin_hlsl_elementwise_clamp(p0); + // expected-error@-1 {{too few arguments to function call, expected 3, have 1}} +} + +float2 test_no_third_arg(float2 p0) { + return __builtin_hlsl_elementwise_clamp(p0, p0); + // expected-error@-1 {{too few arguments to function call, expected 3, have 2}} +} + +float2 test_too_many_arg(float2 p0) { + return __builtin_hlsl_elementwise_clamp(p0, p0, p0, p0); + // expected-error@-1 {{too many arguments to function call, expected 3, have 4}} +} + +float2 test_clamp_no_second_arg(float2 p0) { + return clamp(p0); + // expected-error@-1 {{no matching function for call to 'clamp'}} +} + +float2 test_clamp_vector_size_mismatch(float3 p0, float2 p1) { + return clamp(p0, p0, p1); + // expected-warning@-1 {{implicit conversion truncates vector: 'float3' (aka 'vector<float, 3>') to 'float __attribute__((ext_vector_type(2)))' (vector of 2 'float' values)}} +} + +float2 test_clamp_builtin_vector_size_mismatch(float3 p0, float2 p1) { + return __builtin_hlsl_elementwise_clamp(p0, p1, p1); + // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must have the same type}} +} + +float test_clamp_scalar_mismatch(float p0, half p1) { + return clamp(p1, p0, p1); + // expected-error@-1 {{call to 'clamp' is ambiguous}} +} + +float2 test_clamp_element_type_mismatch(half2 p0, float2 p1) { + return clamp(p1, p0, p1); + // expected-error@-1 {{call to 'clamp' is ambiguous}} +} + +float2 test_builtin_clamp_float2_splat(float p0, float2 p1) { + return __builtin_hlsl_elementwise_clamp(p0, p1, p1); + // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must be vectors}} +} + +float3 test_builtin_clamp_float3_splat(float p0, float3 p1) { + return __builtin_hlsl_elementwise_clamp(p0, p1, p1); + // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must be vectors}} +} + +float4 test_builtin_clamp_float4_splat(float p0, float4 p1) { + return __builtin_hlsl_elementwise_clamp(p0, p1, p1); + // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must be vectors}} +} + +float2 test_clamp_float2_int_splat(float2 p0, int p1) { + return __builtin_hlsl_elementwise_clamp(p0, p1, p1); + // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must be vectors}} +} + +float3 test_clamp_float3_int_splat(float3 p0, int p1) { + return __builtin_hlsl_elementwise_clamp(p0, p1, p1); + // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must be vectors}} +} + +float2 test_builtin_clamp_int_vect_to_float_vec_promotion(int2 p0, float p1) { + return __builtin_hlsl_elementwise_clamp(p0, p1, p1); + // expected-error@-1 {{all arguments to '__builtin_hlsl_elementwise_clamp' must be vectors}} +} + +float test_builtin_clamp_bool_type_promotion(bool p0) { + return __builtin_hlsl_elementwise_clamp(p0, p0, p0); + // expected-error@-1 {{1st argument must be a vector, integer or floating point type (was 'bool')}} +} + +float builtin_bool_to_float_type_promotion(float p0, bool p1) { + return __builtin_hlsl_elementwise_clamp(p0, p0, p1); + // expected-error@-1 {{3rd argument must be a floating point type (was 'bool')}} +} + +float builtin_bool_to_float_type_promotion2(bool p0, float p1) { + return __builtin_hlsl_elementwise_clamp(p1, p0, p1); + // expected-error@-1 {{2nd argument must be a floating point type (was 'bool')}} +} + +float builtin_clamp_int_to_float_promotion(float p0, int p1) { + return __builtin_hlsl_elementwise_clamp(p0, p0, p1); + // expected-error@-1 {{3rd argument must be a floating point type (was 'int')}} +} diff --git a/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl index 59eb9482b9ef921ff9561d1d1f617901bbc65a2e..ba7ffc20484ae01b511f370e1fa25e254606527a 100644 --- a/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl @@ -108,3 +108,12 @@ int test_builtin_dot_bool_type_promotion(bool p0, bool p1) { return __builtin_hlsl_dot(p0, p1); // expected-error@-1 {{1st argument must be a vector, integer or floating point type (was 'bool')}} } + +double test_dot_double(double2 p0, double2 p1) { + return dot(p0, p1); + // expected-error@-1 {{call to 'dot' is ambiguous}} +} +double test_dot_double_builtin(double2 p0, double2 p1) { + return __builtin_hlsl_dot(p0, p1); + // expected-error@-1 {{passing 'double2' (aka 'vector<double, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} +} diff --git a/clang/test/SemaHLSL/BuiltIns/frac-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/frac-errors.hlsl index 06dbdf0a68dfc1cb0cad471b36008d2472a53a47..f82b5942fd46b6112f153e7538dd4d9cd362b7d6 100644 --- a/clang/test/SemaHLSL/BuiltIns/frac-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/frac-errors.hlsl @@ -13,7 +13,7 @@ float2 test_too_many_arg(float2 p0) { float builtin_bool_to_float_type_promotion(bool p1) { return __builtin_hlsl_elementwise_frac(p1); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type (was 'bool')}} + // expected-error@-1 {{passing 'bool' to parameter of incompatible type 'float'}} } float builtin_frac_int_to_float_promotion(int p1) { @@ -25,3 +25,15 @@ float2 builtin_frac_int2_to_float2_promotion(int2 p1) { return __builtin_hlsl_elementwise_frac(p1); // expected-error@-1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} } + +// builtins are variadic functions and so are subject to DefaultVariadicArgumentPromotion +half builtin_frac_half_scalar (half p0) { + return __builtin_hlsl_elementwise_frac (p0); + // expected-error@-1 {{passing 'double' to parameter of incompatible type 'float'}} +} + +float builtin_frac_float_scalar ( float p0) { + return __builtin_hlsl_elementwise_frac (p0); + // expected-error@-1 {{passing 'double' to parameter of incompatible type 'float'}} +} + diff --git a/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..98c02c38675f4e13989e3fef87bf6168641abe68 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_ceil +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_cos +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_exp +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_exp2 +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_floor +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log2 +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log10 +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_sin +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_sqrt +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_roundeven +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_trunc + +double2 test_double_builtin(double2 p0) { + return TEST_FUNC(p0); + // expected-error@-1 {{passing 'double2' (aka 'vector<double, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} +} diff --git a/clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..7ddfd56638273bdf0aecf1fef9dd5bf4cd4ab036 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/isinf-errors.hlsl @@ -0,0 +1,38 @@ + +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected + +bool test_too_few_arg() { + return __builtin_hlsl_elementwise_isinf(); + // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} +} + +bool2 test_too_many_arg(float2 p0) { + return __builtin_hlsl_elementwise_isinf(p0, p0); + // expected-error@-1 {{too many arguments to function call, expected 1, have 2}} +} + +bool builtin_bool_to_float_type_promotion(bool p1) { + return __builtin_hlsl_elementwise_isinf(p1); + // expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}} +} + +bool builtin_isinf_int_to_float_promotion(int p1) { + return __builtin_hlsl_elementwise_isinf(p1); + // expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}} +} + +bool2 builtin_isinf_int2_to_float2_promotion(int2 p1) { + return __builtin_hlsl_elementwise_isinf(p1); + // expected-error@-1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} +} + +// builtins are variadic functions and so are subject to DefaultVariadicArgumentPromotion +half builtin_isinf_half_scalar (half p0) { + return __builtin_hlsl_elementwise_isinf (p0); + // expected-error@-1 {{passing 'double' to parameter of incompatible type 'float'}} +} + +float builtin_isinf_float_scalar ( float p0) { + return __builtin_hlsl_elementwise_isinf (p0); + // expected-error@-1 {{passing 'double' to parameter of incompatible type 'float'}} +} diff --git a/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl index f6ce87e7c33e3eca3eef74f21d07fb7ebc92d545..83751f68357edf36c3135107353c07061fd8fede 100644 --- a/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl @@ -92,5 +92,18 @@ float builtin_lerp_int_to_float_promotion(float p0, int p1) { float4 test_lerp_int4(int4 p0, int4 p1, int4 p2) { return __builtin_hlsl_lerp(p0, p1, p2); - // expected-error@-1 {{1st argument must be a floating point type (was 'int4' (aka 'vector<int, 4>'))}} -} \ No newline at end of file + // expected-error@-1 {{1st argument must be a floating point type (was 'int4' (aka 'vector<int, 4>'))}} +} + +// note: DefaultVariadicArgumentPromotion --> DefaultArgumentPromotion has already promoted to double +// we don't know anymore that the input was half when __builtin_hlsl_lerp is called so we default to float +// for expected type +half builtin_lerp_half_scalar (half p0) { + return __builtin_hlsl_lerp ( p0, p0, p0 ); + // expected-error@-1 {{passing 'double' to parameter of incompatible type 'float'}} +} + +float builtin_lerp_float_scalar ( float p0) { + return __builtin_hlsl_lerp ( p0, p0, p0 ); + // expected-error@-1 {{passing 'double' to parameter of incompatible type 'float'}} +} diff --git a/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl index 0b6843591455bd3ff89e58456aa26a89079b5db2..97ce931bf1b5b591de99c91609829462e8a27ea2 100644 --- a/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl @@ -72,15 +72,15 @@ float2 test_builtin_mad_int_vect_to_float_vec_promotion(int2 p0, float p1) { float builtin_bool_to_float_type_promotion(float p0, bool p1) { return __builtin_hlsl_mad(p0, p0, p1); - // expected-error@-1 {{3rd argument must be a vector, integer or floating point type (was 'bool')}} + // expected-error@-1 {{3rd argument must be a floating point type (was 'bool')}} } float builtin_bool_to_float_type_promotion2(bool p0, float p1) { return __builtin_hlsl_mad(p1, p0, p1); - // expected-error@-1 {{2nd argument must be a vector, integer or floating point type (was 'bool')}} + // expected-error@-1 {{2nd argument must be a floating point type (was 'bool')}} } float builtin_mad_int_to_float_promotion(float p0, int p1) { return __builtin_hlsl_mad(p0, p0, p1); - // expected-error@-1 {{arguments are of different types ('double' vs 'int')}} + // expected-error@-1 {{3rd argument must be a floating point type (was 'int')}} } diff --git a/clang/test/SemaHLSL/BuiltIns/pow-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/pow-errors.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..949028aacf24b610c7932f75f8a544190395d9f0 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/pow-errors.hlsl @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify + +double2 test_double_builtin(double2 p0, double2 p1) { + return __builtin_elementwise_pow(p0,p1); + // expected-error@-1 {{passing 'double2' (aka 'vector<double, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} +} diff --git a/clang/test/SemaHLSL/BuiltIns/rcp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/rcp-errors.hlsl index dc4501dbd6d15a48e56ba8d7207d77348b23f19b..fa6fd813f19e64e6b13b5eda1717385d101bce96 100644 --- a/clang/test/SemaHLSL/BuiltIns/rcp-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/rcp-errors.hlsl @@ -13,7 +13,7 @@ float2 test_too_many_arg(float2 p0) { float builtin_bool_to_float_type_promotion(bool p1) { return __builtin_hlsl_elementwise_rcp(p1); - // expected-error@-1 {{1st argument must be a vector, integer or floating point type (was 'bool')}} + // expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}} } float builtin_rcp_int_to_float_promotion(int p1) { diff --git a/clang/test/SemaHLSL/BuiltIns/reversebits-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/reversebits-errors.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..6e66db6d1cca9e2f110980cbd88ba47d3d375e14 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/reversebits-errors.hlsl @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify + + +double2 test_int_builtin(double2 p0) { + return __builtin_elementwise_bitreverse(p0); + // expected-error@-1 {{1st argument must be a vector of integers (was 'double2' (aka 'vector<double, 2>'))}} +} + +int2 test_int_builtin(int2 p0) { + return __builtin_elementwise_bitreverse(p0); + // expected-error@-1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(unsigned int)))) unsigned int' (vector of 2 'unsigned int' values)}} +} diff --git a/clang/test/SemaHLSL/BuiltIns/rsqrt-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/rsqrt-errors.hlsl new file mode 100644 index 0000000000000000000000000000000000000000..c027a698c5e58fd576f19e0cc6604519110a9eca --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/rsqrt-errors.hlsl @@ -0,0 +1,38 @@ + +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected + +float test_too_few_arg() { + return __builtin_hlsl_elementwise_rsqrt(); + // expected-error@-1 {{too few arguments to function call, expected 1, have 0}} +} + +float2 test_too_many_arg(float2 p0) { + return __builtin_hlsl_elementwise_rsqrt(p0, p0); + // expected-error@-1 {{too many arguments to function call, expected 1, have 2}} +} + +float builtin_bool_to_float_type_promotion(bool p1) { + return __builtin_hlsl_elementwise_rsqrt(p1); + // expected-error@-1 {{passing 'bool' to parameter of incompatible type 'float'}} +} + +float builtin_rsqrt_int_to_float_promotion(int p1) { + return __builtin_hlsl_elementwise_rsqrt(p1); + // expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}} +} + +float2 builtin_rsqrt_int2_to_float2_promotion(int2 p1) { + return __builtin_hlsl_elementwise_rsqrt(p1); + // expected-error@-1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} +} + +// builtins are variadic functions and so are subject to DefaultVariadicArgumentPromotion +half builtin_rsqrt_half_scalar (half p0) { + return __builtin_hlsl_elementwise_rsqrt (p0); + // expected-error@-1 {{passing 'double' to parameter of incompatible type 'float'}} +} + +float builtin_rsqrt_float_scalar ( float p0) { + return __builtin_hlsl_elementwise_rsqrt (p0); + // expected-error@-1 {{passing 'double' to parameter of incompatible type 'float'}} +} diff --git a/clang/test/SemaObjC/attr-objc-NSObject.m b/clang/test/SemaObjC/attr-objc-NSObject.m new file mode 100644 index 0000000000000000000000000000000000000000..76a01dcef01637f597bcdfd450f3d03b7b49d417 --- /dev/null +++ b/clang/test/SemaObjC/attr-objc-NSObject.m @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -verify -Wno-objc-root-class -fsyntax-only %s + +@interface NSArray<__covariant ObjectType> +- (void)containsObject:(ObjectType)anObject; // expected-note {{passing argument to parameter 'anObject' here}} +- (void)description; +@end + +typedef __attribute__((NSObject)) struct Foo *FooRef; +typedef struct Bar *BarRef; + +void good() { + FooRef object; + NSArray<FooRef> *array; + [array containsObject:object]; + [object description]; +} + +void bad() { + BarRef object; + NSArray<BarRef> *array; // expected-error {{type argument 'BarRef' (aka 'struct Bar *') is neither an Objective-C object nor a block type}} + [array containsObject:object]; // expected-warning {{incompatible pointer types sending 'BarRef' (aka 'struct Bar *') to parameter of type 'id'}} + [object description]; // expected-warning {{receiver type 'BarRef' (aka 'struct Bar *') is not 'id' or interface pointer, consider casting it to 'id'}} +} diff --git a/clang/test/SemaObjCXX/Inputs/nullability-consistency-smart.h b/clang/test/SemaObjCXX/Inputs/nullability-consistency-smart.h new file mode 100644 index 0000000000000000000000000000000000000000..a28532e5d71668f5f88354ba4c5df6200859e332 --- /dev/null +++ b/clang/test/SemaObjCXX/Inputs/nullability-consistency-smart.h @@ -0,0 +1,7 @@ +class _Nullable Smart; + +void f1(int * _Nonnull); + +void f2(Smart); // OK, not required on smart-pointer types +using Alias = Smart; +void f3(Alias); diff --git a/clang/test/SemaObjCXX/nullability-consistency.mm b/clang/test/SemaObjCXX/nullability-consistency.mm index 6921d8b9d3dd5b00717b54606bb7a8ed8b439b79..09c9a84475a93916868727a9a36678b9b919ec70 100644 --- a/clang/test/SemaObjCXX/nullability-consistency.mm +++ b/clang/test/SemaObjCXX/nullability-consistency.mm @@ -9,6 +9,7 @@ #include "nullability-consistency-6.h" #include "nullability-consistency-7.h" #include "nullability-consistency-8.h" +#include "nullability-consistency-smart.h" #include "nullability-consistency-system.h" void h1(int *ptr) { } // don't warn diff --git a/clang/test/SemaTemplate/concepts-GH86757.cpp b/clang/test/SemaTemplate/concepts-GH86757.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3122381b20359e3d9dd25306214af48171c5edde --- /dev/null +++ b/clang/test/SemaTemplate/concepts-GH86757.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++20 -Wfatal-errors -verify %s + +template <typename> int a; +template <typename... b> concept c = a<b...>; +template <typename> concept e = c<>; + +// must be a fatal error to trigger the crash +undefined; // expected-error {{a type specifier is required for all declarations}} + +template <typename d> concept g = e<d>; +template <g> struct h +template <g d> +struct h<d>; diff --git a/clang/test/SemaTemplate/concepts-friends.cpp b/clang/test/SemaTemplate/concepts-friends.cpp index 255b0858917fb6fdad51b7b50dde446e2e3b01a7..91b797034ed6cf040b2fdbba066a36112d4a4ab8 100644 --- a/clang/test/SemaTemplate/concepts-friends.cpp +++ b/clang/test/SemaTemplate/concepts-friends.cpp @@ -478,3 +478,29 @@ template <Concept> class Foo { }; } // namespace FriendOfFriend + +namespace GH86769 { + +template <typename T> +concept X = true; + +template <X T> struct Y { + Y(T) {} + template <X U> friend struct Y; + template <X U> friend struct Y; + template <X U> friend struct Y; +}; + +template <class T> +struct Z { + // FIXME: This is ill-formed per C++11 N3337 [temp.param]p12: + // A default template argument shall not be specified in a friend class + // template declaration. + template <X U = void> friend struct Y; +}; + +template struct Y<int>; +template struct Z<int>; +Y y(1); + +} diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index bac209a28da912e1e14f29f9313710cf1f749c87..787cc809e253534a3f8bfab4246920fc001ffe9c 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++20 -verify %s +// RUN: %clang_cc1 -std=c++20 -ferror-limit 0 -verify %s namespace PR47043 { template<typename T> concept True = true; @@ -1085,3 +1085,40 @@ template void Struct<void>::bar<>(); template int Struct<void>::field<1, 2>; } + +namespace GH64808 { + +template <class T> struct basic_sender { + T func; + basic_sender(T) : func(T()) {} +}; + +auto a = basic_sender{[](auto... __captures) { + return []() // #note-a-1 + requires((__captures, ...), false) // #note-a-2 + {}; +}()}; + +auto b = basic_sender{[](auto... __captures) { + return []() + requires([](int, double) { return true; }(decltype(__captures)()...)) + {}; +}(1, 2.33)}; + +void foo() { + a.func(); + // expected-error@-1{{no matching function for call}} + // expected-note@#note-a-1{{constraints not satisfied}} + // expected-note@#note-a-2{{evaluated to false}} + b.func(); +} + +} // namespace GH64808 + +namespace GH86757_1 { +template <typename...> concept b = false; +template <typename> concept c = b<>; +template <typename d> concept f = c< d >; +template <f> struct e; // expected-note {{}} +template <f d> struct e<d>; // expected-error {{class template partial specialization is not more specialized than the primary template}} +} diff --git a/clang/test/SemaTemplate/ctad.cpp b/clang/test/SemaTemplate/ctad.cpp index 388ed7d4cced18fb1a698d20983335d18481253b..ec144d4f44ba8c3b71c5609d8be79ab785efeaff 100644 --- a/clang/test/SemaTemplate/ctad.cpp +++ b/clang/test/SemaTemplate/ctad.cpp @@ -53,4 +53,4 @@ X x; template<class T, class B> struct Y { Y(T); }; template<class T, class B=void> struct Y ; Y y(1); -}; +} diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp index 16c7083df29d0c81275bea5221a6db906911a69f..0caef78fedbfd9c9a849025115e4332ba3615468 100644 --- a/clang/test/SemaTemplate/deduction-guide.cpp +++ b/clang/test/SemaTemplate/deduction-guide.cpp @@ -239,3 +239,12 @@ F s(0); // CHECK: |-InjectedClassNameType {{.*}} 'F<>' dependent // CHECK: | `-CXXRecord {{.*}} 'F' // CHECK: `-TemplateTypeParmType {{.*}} 'type-parameter-0-1' dependent depth 0 index 1 + +template<typename T> +struct G { T t; }; + +G g = {1}; +// CHECK-LABEL: Dumping <deduction guide for G>: +// CHECK: FunctionTemplateDecl +// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for G> 'auto (T) -> G<T>' aggregate +// CHECK: `-CXXDeductionGuideDecl {{.*}} implicit used <deduction guide for G> 'auto (int) -> G<int>' implicit_instantiation aggregate diff --git a/clang/test/SemaTemplate/instantiation-depth-default.cpp b/clang/test/SemaTemplate/instantiation-depth-default.cpp index 430d042d7e0f494f10ebf1b005175b750fdbb4fa..f5835b86b3a3854ff107abd00fb996c6b0486844 100644 --- a/clang/test/SemaTemplate/instantiation-depth-default.cpp +++ b/clang/test/SemaTemplate/instantiation-depth-default.cpp @@ -1,12 +1,18 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -ftemplate-backtrace-limit=2 %if {{asan|ubsan}} %{ -Wno-stack-exhausted %} %s +// RUN: %clang_cc1 -fsyntax-only -verify -ftemplate-backtrace-limit=2 %s +// +// FIXME: Disable this test when Clang was built with ASan, because ASan +// increases our per-frame stack usage enough that this test no longer fits +// within our normal stack space allocation. +// UNSUPPORTED: asan +// // The default stack size on NetBSD is too small for this test. // UNSUPPORTED: system-netbsd template<int N, typename T> struct X : X<N+1, T*> {}; -// expected-error-re@5 {{recursive template instantiation exceeded maximum depth of 1024{{$}}}} -// expected-note@5 {{instantiation of template class}} -// expected-note@5 {{skipping 1023 contexts in backtrace}} -// expected-note@5 {{use -ftemplate-depth=N to increase recursive template instantiation depth}} +// expected-error-re@11 {{recursive template instantiation exceeded maximum depth of 1024{{$}}}} +// expected-note@11 {{instantiation of template class}} +// expected-note@11 {{skipping 1023 contexts in backtrace}} +// expected-note@11 {{use -ftemplate-depth=N to increase recursive template instantiation depth}} X<0, int> x; // expected-note {{in instantiation of}} diff --git a/clang/tools/clang-format/.clang-format b/clang/tools/clang-format/.clang-format index f95602cab0f7fcdf5d34c485d52b65993dbb83d9..d7331b3c8cf02ef7944e83a4280476627e33b31d 100644 --- a/clang/tools/clang-format/.clang-format +++ b/clang/tools/clang-format/.clang-format @@ -1,6 +1 @@ -BasedOnStyle: LLVM -InsertBraces: true -InsertNewlineAtEOF: true -LineEnding: LF -RemoveBracesLLVM: true -RemoveParentheses: ReturnStatement +BasedOnStyle: clang-format diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp index e122cea50f7268c9aa50961a37f95fc1af22bd23..ed401135ad8433252bedfb280505dacf92f536eb 100644 --- a/clang/tools/clang-format/ClangFormat.cpp +++ b/clang/tools/clang-format/ClangFormat.cpp @@ -205,6 +205,11 @@ static cl::list<std::string> FileNames(cl::Positional, cl::desc("[@<file>] [<file> ...]"), cl::cat(ClangFormatCategory)); +static cl::opt<bool> FailOnIncompleteFormat( + "fail-on-incomplete-format", + cl::desc("If set, fail with exit code 1 on incomplete format."), + cl::init(false), cl::cat(ClangFormatCategory)); + namespace clang { namespace format { @@ -399,7 +404,7 @@ class ClangFormatDiagConsumer : public DiagnosticConsumer { }; // Returns true on error. -static bool format(StringRef FileName) { +static bool format(StringRef FileName, bool ErrorOnIncompleteFormat = false) { const bool IsSTDIN = FileName == "-"; if (!OutputXML && Inplace && IsSTDIN) { errs() << "error: cannot use -i when reading from stdin.\n"; @@ -535,7 +540,7 @@ static bool format(StringRef FileName) { Rewrite.getEditBuffer(ID).write(outs()); } } - return false; + return ErrorOnIncompleteFormat && !Status.FormatComplete; } } // namespace format @@ -699,7 +704,7 @@ int main(int argc, const char **argv) { } if (FileNames.empty()) - return clang::format::format("-"); + return clang::format::format("-", FailOnIncompleteFormat); if (FileNames.size() > 1 && (!Offsets.empty() || !Lengths.empty() || !LineRanges.empty())) { @@ -717,7 +722,7 @@ int main(int argc, const char **argv) { errs() << "Formatting [" << FileNo++ << "/" << FileNames.size() << "] " << FileName << "\n"; } - Error |= clang::format::format(FileName); + Error |= clang::format::format(FileName, FailOnIncompleteFormat); } return Error ? 1 : 0; } diff --git a/clang/tools/clang-format/clang-format-diff.py b/clang/tools/clang-format/clang-format-diff.py index 0a2c24743678d0d9928f2a020942901720061372..3a74b90e731578cad6796b9895db563a6512728e 100755 --- a/clang/tools/clang-format/clang-format-diff.py +++ b/clang/tools/clang-format/clang-format-diff.py @@ -138,6 +138,7 @@ def main(): ) # Reformat files containing changes in place. + has_diff = False for filename, lines in lines_by_file.items(): if args.i and args.verbose: print("Formatting {}".format(filename)) @@ -169,7 +170,7 @@ def main(): stdout, stderr = p.communicate() if p.returncode != 0: - sys.exit(p.returncode) + return p.returncode if not args.i: with open(filename) as f: @@ -185,9 +186,12 @@ def main(): ) diff_string = "".join(diff) if len(diff_string) > 0: + has_diff = True sys.stdout.write(diff_string) - sys.exit(1) + + if has_diff: + return 1 if __name__ == "__main__": - main() + sys.exit(main()) diff --git a/clang/tools/clang-installapi/CMakeLists.txt b/clang/tools/clang-installapi/CMakeLists.txt index e05f4eac3ad198358f96f053ab990f8fe35aef4f..b90ffc847b155829189ae524a415b35bb04603fc 100644 --- a/clang/tools/clang-installapi/CMakeLists.txt +++ b/clang/tools/clang-installapi/CMakeLists.txt @@ -2,13 +2,20 @@ set(LLVM_LINK_COMPONENTS Support TargetParser TextAPI + TextAPIBinaryReader Option ) +set(LLVM_TARGET_DEFINITIONS InstallAPIOpts.td) +tablegen(LLVM InstallAPIOpts.inc -gen-opt-parser-defs) +add_public_tablegen_target(InstallAPIDriverOptions) + add_clang_tool(clang-installapi ClangInstallAPI.cpp Options.cpp + DEPENDS + InstallAPIDriverOptions GENERATE_DRIVER ) @@ -22,3 +29,4 @@ clang_target_link_libraries(clang-installapi clangTooling clangSerialization ) + diff --git a/clang/tools/clang-installapi/ClangInstallAPI.cpp b/clang/tools/clang-installapi/ClangInstallAPI.cpp index 15b0baee88bc3472c1d651d4c938382fa470dcc6..13061cfa36eeb0a7ea8b2ed992965500cdcb4309 100644 --- a/clang/tools/clang-installapi/ClangInstallAPI.cpp +++ b/clang/tools/clang-installapi/ClangInstallAPI.cpp @@ -14,12 +14,12 @@ #include "Options.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticFrontend.h" -#include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Tool.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/InstallAPI/Frontend.h" #include "clang/InstallAPI/FrontendRecords.h" +#include "clang/InstallAPI/InstallAPIDiagnostic.h" #include "clang/InstallAPI/MachO.h" #include "clang/Tooling/Tooling.h" #include "llvm/ADT/ArrayRef.h" @@ -92,22 +92,8 @@ static bool run(ArrayRef<const char *> Args, const char *ProgName) { IntrusiveRefCntPtr<clang::FileManager> FM( new FileManager(clang::FileSystemOptions(), OverlayFileSystem)); - // Set up driver to parse input arguments. - auto DriverArgs = llvm::ArrayRef(Args).slice(1); - clang::driver::Driver Driver(ProgName, llvm::sys::getDefaultTargetTriple(), - *Diag, "clang installapi tool"); - auto TargetAndMode = - clang::driver::ToolChain::getTargetAndModeFromProgramName(ProgName); - Driver.setTargetAndMode(TargetAndMode); - bool HasError = false; - llvm::opt::InputArgList ArgList = - Driver.ParseArgStrings(DriverArgs, /*UseDriverMode=*/true, HasError); - if (HasError) - return EXIT_FAILURE; - Driver.setCheckInputsExist(false); - - // Capture InstallAPI specific options and diagnose any option errors. - Options Opts(*Diag, FM.get(), ArgList); + // Capture all options and diagnose any errors. + Options Opts(*Diag, FM.get(), Args, ProgName); if (Diag->hasErrorOccurred()) return EXIT_FAILURE; @@ -125,19 +111,21 @@ static bool run(ArrayRef<const char *> Args, const char *ProgName) { // Execute and gather AST results. // An invocation is ran for each unique target triple and for each header // access level. - Records FrontendResults; for (const auto &[Targ, Trip] : Opts.DriverOpts.Targets) { + Ctx.Verifier->setTarget(Targ); + Ctx.Slice = std::make_shared<FrontendRecordsSlice>(Trip); for (const HeaderType Type : {HeaderType::Public, HeaderType::Private, HeaderType::Project}) { - Ctx.Slice = std::make_shared<FrontendRecordsSlice>(Trip); Ctx.Type = Type; if (!runFrontend(ProgName, Opts.DriverOpts.Verbose, Ctx, InMemoryFileSystem.get(), Opts.getClangFrontendArgs())) return EXIT_FAILURE; - FrontendResults.emplace_back(std::move(Ctx.Slice)); } } + if (Ctx.Verifier->verifyRemainingSymbols() == DylibVerifier::Result::Invalid) + return EXIT_FAILURE; + // After symbols have been collected, prepare to write output. auto Out = CI->createOutputFile(Ctx.OutputLoc, /*Binary=*/false, /*RemoveFileOnSignal=*/false, @@ -147,13 +135,7 @@ static bool run(ArrayRef<const char *> Args, const char *ProgName) { return EXIT_FAILURE; // Assign attributes for serialization. - auto Symbols = std::make_unique<SymbolSet>(); - for (const auto &FR : FrontendResults) { - SymbolConverter Converter(Symbols.get(), FR->getTarget()); - FR->visit(Converter); - } - - InterfaceFile IF(std::move(Symbols)); + InterfaceFile IF(Ctx.Verifier->getExports()); for (const auto &TargetInfo : Opts.DriverOpts.Targets) { IF.addTarget(TargetInfo.first); IF.setFromBinaryAttrs(Ctx.BA, TargetInfo.first); @@ -161,7 +143,8 @@ static bool run(ArrayRef<const char *> Args, const char *ProgName) { // Write output file and perform CI cleanup. if (auto Err = TextAPIWriter::writeToStream(*Out, IF, Ctx.FT)) { - Diag->Report(diag::err_cannot_open_file) << Ctx.OutputLoc; + Diag->Report(diag::err_cannot_write_file) + << Ctx.OutputLoc << std::move(Err); CI->clearOutputFiles(/*EraseFiles=*/true); return EXIT_FAILURE; } diff --git a/clang/tools/clang-installapi/InstallAPIOpts.td b/clang/tools/clang-installapi/InstallAPIOpts.td new file mode 100644 index 0000000000000000000000000000000000000000..010f2507a1d1f38557ff64f2383b0bd54980c625 --- /dev/null +++ b/clang/tools/clang-installapi/InstallAPIOpts.td @@ -0,0 +1,77 @@ +//===--- InstallAPIOpts.td ------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the specific options for InstallAPI. +// +//===----------------------------------------------------------------------===// + +// Include the common option parsing interfaces. +include "llvm/Option/OptParser.td" + + +///////// +// Options + +// TextAPI options. +def filetype : Joined<["--"], "filetype=">, + HelpText<"Specify the output file type (tbd-v4 or tbd-v5)">; + +// Verification options. +def verify_against : Separate<["-"], "verify-against">, + HelpText<"Verify the specified dynamic library/framework against the headers">; +def verify_against_EQ : Joined<["--"], "verify-against=">, Alias<verify_against>; +def verify_mode_EQ : Joined<["--"], "verify-mode=">, + HelpText<"Specify the severity and extend of the validation. Valid modes are ErrorsOnly, ErrorsAndWarnings, and Pedantic.">; +def demangle : Flag<["--", "-"], "demangle">, + HelpText<"Demangle symbols when printing warnings and errors">; +def dsym: Joined<["--"], "dsym=">, + MetaVarName<"<path>">, HelpText<"Specify dSYM path for enriched diagnostics.">; + +// Additional input options. +def extra_project_header : Separate<["-"], "extra-project-header">, + MetaVarName<"<path>">, + HelpText<"Add additional project header location for parsing">; +def extra_project_header_EQ : Joined<["--"], "extra-project-header=">, + Alias<extra_project_header>; +def exclude_project_header : Separate<["-"], "exclude-project-header">, + MetaVarName<"<glob>">, + HelpText<"Exclude project header from parsing">; +def exclude_project_header_EQ : Joined<["--"], "exclude-project-header=">, + Alias<exclude_project_header>; +def extra_public_header : Separate<["-"], "extra-public-header">, + MetaVarName<"<path>">, + HelpText<"Add additional public header location for parsing">; +def extra_public_header_EQ : Joined<["--"], "extra-public-header=">, + Alias<extra_public_header>; +def extra_private_header : Separate<["-"], "extra-private-header">, + MetaVarName<"<path>">, + HelpText<"Add additional private header location for parsing">; +def extra_private_header_EQ : Joined<["--"], "extra-private-header=">, + Alias<extra_private_header>; +def exclude_public_header : Separate<["-"], "exclude-public-header">, + MetaVarName<"<glob>">, + HelpText<"Exclude public header from parsing">; +def exclude_public_header_EQ : Joined<["--"], "exclude-public-header=">, + Alias<exclude_public_header>; +def exclude_private_header : Separate<["-"], "exclude-private-header">, + MetaVarName<"<glob>">, + HelpText<"Exclude private header from parsing">; +def exclude_private_header_EQ : Joined<["--"], "exclude-private-header=">, + Alias<exclude_private_header>; +def public_umbrella_header : Separate<["-"], "public-umbrella-header">, + MetaVarName<"<path>">, HelpText<"Specify the public umbrella header location">; +def public_umbrella_header_EQ : Joined<["--"], "public-umbrella-header=">, + Alias<public_umbrella_header>; +def private_umbrella_header : Separate<["-"], "private-umbrella-header">, + MetaVarName<"<path>">, HelpText<"Specify the private umbrella header location">; +def private_umbrella_header_EQ : Joined<["--"], "private-umbrella-header=">, + Alias<private_umbrella_header>; +def project_umbrella_header : Separate<["-"], "project-umbrella-header">, + MetaVarName<"<path>">, HelpText<"Specify the project umbrella header location">; +def project_umbrella_header_EQ : Joined<["--"], "project-umbrella-header=">, + Alias<project_umbrella_header>; diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp index 701ab81c57c3d0e1b6249aaea043bc2771e9cd9a..c4f39b7c841742df0a3b85f342187963bdc011ff 100644 --- a/clang/tools/clang-installapi/Options.cpp +++ b/clang/tools/clang-installapi/Options.cpp @@ -10,35 +10,86 @@ #include "clang/Driver/Driver.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/InstallAPI/FileList.h" +#include "clang/InstallAPI/HeaderFile.h" +#include "clang/InstallAPI/InstallAPIDiagnostic.h" #include "llvm/Support/Program.h" #include "llvm/TargetParser/Host.h" +#include "llvm/TextAPI/DylibReader.h" +#include "llvm/TextAPI/TextAPIWriter.h" -using namespace clang::driver; -using namespace clang::driver::options; +using namespace llvm; using namespace llvm::opt; using namespace llvm::MachO; +namespace drv = clang::driver::options; + namespace clang { namespace installapi { +/// Create prefix string literals used in InstallAPIOpts.td. +#define PREFIX(NAME, VALUE) \ + static constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ + static constexpr llvm::ArrayRef<llvm::StringLiteral> NAME( \ + NAME##_init, std::size(NAME##_init) - 1); +#include "InstallAPIOpts.inc" +#undef PREFIX + +static constexpr const llvm::StringLiteral PrefixTable_init[] = +#define PREFIX_UNION(VALUES) VALUES +#include "InstallAPIOpts.inc" +#undef PREFIX_UNION + ; +static constexpr const ArrayRef<StringLiteral> + PrefixTable(PrefixTable_init, std::size(PrefixTable_init) - 1); + +/// Create table mapping all options defined in InstallAPIOpts.td. +static constexpr OptTable::Info InfoTable[] = { +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \ + VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES) \ + {PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, \ + PARAM, FLAGS, VISIBILITY, OPT_##GROUP, OPT_##ALIAS, ALIASARGS, \ + VALUES}, +#include "InstallAPIOpts.inc" +#undef OPTION +}; + +namespace { + +/// \brief Create OptTable class for parsing actual command line arguments. +class DriverOptTable : public opt::PrecomputedOptTable { +public: + DriverOptTable() : PrecomputedOptTable(InfoTable, PrefixTable) {} +}; + +} // end anonymous namespace. + +static llvm::opt::OptTable *createDriverOptTable() { + return new DriverOptTable(); +} + bool Options::processDriverOptions(InputArgList &Args) { // Handle inputs. - llvm::append_range(DriverOpts.FileLists, Args.getAllArgValues(OPT_INPUT)); + llvm::append_range(DriverOpts.FileLists, + Args.getAllArgValues(drv::OPT_INPUT)); // Handle output. SmallString<PATH_MAX> OutputPath; - if (auto *Arg = Args.getLastArg(OPT_o)) { + if (auto *Arg = Args.getLastArg(drv::OPT_o)) { OutputPath = Arg->getValue(); if (OutputPath != "-") FM->makeAbsolutePath(OutputPath); DriverOpts.OutputPath = std::string(OutputPath); } + if (DriverOpts.OutputPath.empty()) { + Diags->Report(diag::err_no_output_file); + return false; + } // Do basic error checking first for mixing -target and -arch options. - auto *ArgArch = Args.getLastArgNoClaim(OPT_arch); - auto *ArgTarget = Args.getLastArgNoClaim(OPT_target); + auto *ArgArch = Args.getLastArgNoClaim(drv::OPT_arch); + auto *ArgTarget = Args.getLastArgNoClaim(drv::OPT_target); auto *ArgTargetVariant = - Args.getLastArgNoClaim(OPT_darwin_target_variant_triple); + Args.getLastArgNoClaim(drv::OPT_darwin_target_variant_triple); if (ArgArch && (ArgTarget || ArgTargetVariant)) { Diags->Report(clang::diag::err_drv_argument_not_allowed_with) << ArgArch->getAsString(Args) @@ -46,7 +97,7 @@ bool Options::processDriverOptions(InputArgList &Args) { return false; } - auto *ArgMinTargetOS = Args.getLastArgNoClaim(OPT_mtargetos_EQ); + auto *ArgMinTargetOS = Args.getLastArgNoClaim(drv::OPT_mtargetos_EQ); if ((ArgTarget || ArgTargetVariant) && ArgMinTargetOS) { Diags->Report(clang::diag::err_drv_cannot_mix_options) << ArgTarget->getAsString(Args) << ArgMinTargetOS->getAsString(Args); @@ -55,7 +106,7 @@ bool Options::processDriverOptions(InputArgList &Args) { // Capture target triples first. if (ArgTarget) { - for (const Arg *A : Args.filtered(OPT_target)) { + for (const Arg *A : Args.filtered(drv::OPT_target)) { A->claim(); llvm::Triple TargetTriple(A->getValue()); Target TAPITarget = Target(TargetTriple); @@ -69,27 +120,32 @@ bool Options::processDriverOptions(InputArgList &Args) { } } - DriverOpts.Verbose = Args.hasArgNoClaim(OPT_v); + DriverOpts.Verbose = Args.hasArgNoClaim(drv::OPT_v); return true; } bool Options::processLinkerOptions(InputArgList &Args) { - // TODO: add error handling. - - // Required arguments. - if (const Arg *A = Args.getLastArg(options::OPT_install__name)) + // Handle required arguments. + if (const Arg *A = Args.getLastArg(drv::OPT_install__name)) LinkerOpts.InstallName = A->getValue(); + if (LinkerOpts.InstallName.empty()) { + Diags->Report(diag::err_no_install_name); + return false; + } // Defaulted or optional arguments. - if (auto *Arg = Args.getLastArg(OPT_current__version)) + if (auto *Arg = Args.getLastArg(drv::OPT_current__version)) LinkerOpts.CurrentVersion.parse64(Arg->getValue()); - LinkerOpts.IsDylib = Args.hasArg(OPT_dynamiclib); + if (auto *Arg = Args.getLastArg(drv::OPT_compatibility__version)) + LinkerOpts.CompatVersion.parse64(Arg->getValue()); - LinkerOpts.AppExtensionSafe = - Args.hasFlag(OPT_fapplication_extension, OPT_fno_application_extension, - /*Default=*/LinkerOpts.AppExtensionSafe); + LinkerOpts.IsDylib = Args.hasArg(drv::OPT_dynamiclib); + + LinkerOpts.AppExtensionSafe = Args.hasFlag( + drv::OPT_fapplication_extension, drv::OPT_fno_application_extension, + /*Default=*/LinkerOpts.AppExtensionSafe); if (::getenv("LD_NO_ENCRYPT") != nullptr) LinkerOpts.AppExtensionSafe = true; @@ -102,7 +158,7 @@ bool Options::processLinkerOptions(InputArgList &Args) { bool Options::processFrontendOptions(InputArgList &Args) { // Do not claim any arguments, as they will be passed along for CC1 // invocations. - if (auto *A = Args.getLastArgNoClaim(OPT_x)) { + if (auto *A = Args.getLastArgNoClaim(drv::OPT_x)) { FEOpts.LangMode = llvm::StringSwitch<clang::Language>(A->getValue()) .Case("c", clang::Language::C) .Case("c++", clang::Language::CXX) @@ -116,8 +172,8 @@ bool Options::processFrontendOptions(InputArgList &Args) { return false; } } - for (auto *A : Args.filtered(OPT_ObjC, OPT_ObjCXX)) { - if (A->getOption().matches(OPT_ObjC)) + for (auto *A : Args.filtered(drv::OPT_ObjC, drv::OPT_ObjCXX)) { + if (A->getOption().matches(drv::OPT_ObjC)) FEOpts.LangMode = clang::Language::ObjC; else FEOpts.LangMode = clang::Language::ObjCXX; @@ -126,9 +182,139 @@ bool Options::processFrontendOptions(InputArgList &Args) { return true; } +bool Options::addFilePaths(InputArgList &Args, PathSeq &Headers, + OptSpecifier ID) { + for (const StringRef Path : Args.getAllArgValues(ID)) { + if ((bool)FM->getDirectory(Path, /*CacheFailure=*/false)) { + auto InputHeadersOrErr = enumerateFiles(*FM, Path); + if (!InputHeadersOrErr) { + Diags->Report(diag::err_cannot_open_file) + << Path << toString(InputHeadersOrErr.takeError()); + return false; + } + // Sort headers to ensure deterministic behavior. + sort(*InputHeadersOrErr); + for (std::string &H : *InputHeadersOrErr) + Headers.emplace_back(std::move(H)); + } else + Headers.emplace_back(Path); + } + return true; +} + +std::vector<const char *> +Options::processAndFilterOutInstallAPIOptions(ArrayRef<const char *> Args) { + std::unique_ptr<llvm::opt::OptTable> Table; + Table.reset(createDriverOptTable()); + + unsigned MissingArgIndex, MissingArgCount; + auto ParsedArgs = Table->ParseArgs(Args.slice(1), MissingArgIndex, + MissingArgCount, Visibility()); + + // Capture InstallAPI only driver options. + DriverOpts.Demangle = ParsedArgs.hasArg(OPT_demangle); + + if (auto *A = ParsedArgs.getLastArg(OPT_filetype)) { + DriverOpts.OutFT = TextAPIWriter::parseFileType(A->getValue()); + if (DriverOpts.OutFT == FileType::Invalid) { + Diags->Report(clang::diag::err_drv_invalid_value) + << A->getAsString(ParsedArgs) << A->getValue(); + return {}; + } + } + + if (const Arg *A = ParsedArgs.getLastArg(OPT_verify_mode_EQ)) { + DriverOpts.VerifyMode = + StringSwitch<VerificationMode>(A->getValue()) + .Case("ErrorsOnly", VerificationMode::ErrorsOnly) + .Case("ErrorsAndWarnings", VerificationMode::ErrorsAndWarnings) + .Case("Pedantic", VerificationMode::Pedantic) + .Default(VerificationMode::Invalid); + + if (DriverOpts.VerifyMode == VerificationMode::Invalid) { + Diags->Report(clang::diag::err_drv_invalid_value) + << A->getAsString(ParsedArgs) << A->getValue(); + return {}; + } + } + + if (const Arg *A = ParsedArgs.getLastArg(OPT_verify_against)) + DriverOpts.DylibToVerify = A->getValue(); + + if (const Arg *A = ParsedArgs.getLastArg(OPT_dsym)) + DriverOpts.DSYMPath = A->getValue(); + + // Handle exclude & extra header directories or files. + auto handleAdditionalInputArgs = [&](PathSeq &Headers, + clang::installapi::ID OptID) { + if (ParsedArgs.hasArgNoClaim(OptID)) + Headers.clear(); + return addFilePaths(ParsedArgs, Headers, OptID); + }; + + if (!handleAdditionalInputArgs(DriverOpts.ExtraPublicHeaders, + OPT_extra_public_header)) + return {}; + + if (!handleAdditionalInputArgs(DriverOpts.ExtraPrivateHeaders, + OPT_extra_private_header)) + return {}; + if (!handleAdditionalInputArgs(DriverOpts.ExtraProjectHeaders, + OPT_extra_project_header)) + return {}; + + if (!handleAdditionalInputArgs(DriverOpts.ExcludePublicHeaders, + OPT_exclude_public_header)) + return {}; + if (!handleAdditionalInputArgs(DriverOpts.ExcludePrivateHeaders, + OPT_exclude_private_header)) + return {}; + if (!handleAdditionalInputArgs(DriverOpts.ExcludeProjectHeaders, + OPT_exclude_project_header)) + return {}; + + // Handle umbrella headers. + if (const Arg *A = ParsedArgs.getLastArg(OPT_public_umbrella_header)) + DriverOpts.PublicUmbrellaHeader = A->getValue(); + + if (const Arg *A = ParsedArgs.getLastArg(OPT_private_umbrella_header)) + DriverOpts.PrivateUmbrellaHeader = A->getValue(); + + if (const Arg *A = ParsedArgs.getLastArg(OPT_project_umbrella_header)) + DriverOpts.ProjectUmbrellaHeader = A->getValue(); + + /// Any unclaimed arguments should be forwarded to the clang driver. + std::vector<const char *> ClangDriverArgs(ParsedArgs.size()); + for (const Arg *A : ParsedArgs) { + if (A->isClaimed()) + continue; + llvm::copy(A->getValues(), std::back_inserter(ClangDriverArgs)); + } + return ClangDriverArgs; +} + Options::Options(DiagnosticsEngine &Diag, FileManager *FM, - InputArgList &ArgList) + ArrayRef<const char *> Args, const StringRef ProgName) : Diags(&Diag), FM(FM) { + + // First process InstallAPI specific options. + auto DriverArgs = processAndFilterOutInstallAPIOptions(Args); + if (Diags->hasErrorOccurred()) + return; + + // Set up driver to parse remaining input arguments. + clang::driver::Driver Driver(ProgName, llvm::sys::getDefaultTargetTriple(), + *Diags, "clang installapi tool"); + auto TargetAndMode = + clang::driver::ToolChain::getTargetAndModeFromProgramName(ProgName); + Driver.setTargetAndMode(TargetAndMode); + bool HasError = false; + llvm::opt::InputArgList ArgList = + Driver.ParseArgStrings(DriverArgs, /*UseDriverMode=*/true, HasError); + if (HasError) + return; + Driver.setCheckInputsExist(false); + if (!processDriverOptions(ArgList)) return; @@ -138,15 +324,25 @@ Options::Options(DiagnosticsEngine &Diag, FileManager *FM, if (!processFrontendOptions(ArgList)) return; + /// Force cc1 options that should always be on. + FrontendArgs = {"-fsyntax-only", "-Wprivate-extern"}; + /// Any unclaimed arguments should be handled by invoking the clang frontend. for (const Arg *A : ArgList) { if (A->isClaimed()) continue; - FrontendArgs.emplace_back(A->getSpelling()); llvm::copy(A->getValues(), std::back_inserter(FrontendArgs)); } - FrontendArgs.push_back("-fsyntax-only"); +} + +static const Regex Rule("(.+)/(.+)\\.framework/"); +static StringRef getFrameworkNameFromInstallName(StringRef InstallName) { + SmallVector<StringRef, 3> Match; + Rule.match(InstallName, &Match); + if (Match.empty()) + return ""; + return Match.back(); } InstallAPIContext Options::createContext() { @@ -159,25 +355,178 @@ InstallAPIContext Options::createContext() { Ctx.BA.InstallName = LinkerOpts.InstallName; Ctx.BA.CurrentVersion = LinkerOpts.CurrentVersion; + Ctx.BA.CompatVersion = LinkerOpts.CompatVersion; Ctx.BA.AppExtensionSafe = LinkerOpts.AppExtensionSafe; Ctx.FT = DriverOpts.OutFT; Ctx.OutputLoc = DriverOpts.OutputPath; Ctx.LangMode = FEOpts.LangMode; + // Attempt to find umbrella headers by capturing framework name. + StringRef FrameworkName; + if (!LinkerOpts.IsDylib) + FrameworkName = getFrameworkNameFromInstallName(LinkerOpts.InstallName); + // Process inputs. for (const std::string &ListPath : DriverOpts.FileLists) { auto Buffer = FM->getBufferForFile(ListPath); if (auto Err = Buffer.getError()) { - Diags->Report(diag::err_cannot_open_file) << ListPath; + Diags->Report(diag::err_cannot_open_file) << ListPath << Err.message(); return Ctx; } if (auto Err = FileListReader::loadHeaders(std::move(Buffer.get()), Ctx.InputHeaders)) { - Diags->Report(diag::err_cannot_open_file) << ListPath; + Diags->Report(diag::err_cannot_open_file) << ListPath << std::move(Err); return Ctx; } } + // After initial input has been processed, add any extra headers. + auto HandleExtraHeaders = [&](PathSeq &Headers, HeaderType Type) -> bool { + assert(Type != HeaderType::Unknown && "Missing header type."); + for (const StringRef Path : Headers) { + if (!FM->getOptionalFileRef(Path)) { + Diags->Report(diag::err_no_such_header_file) << Path << (unsigned)Type; + return false; + } + SmallString<PATH_MAX> FullPath(Path); + FM->makeAbsolutePath(FullPath); + + auto IncludeName = createIncludeHeaderName(FullPath); + Ctx.InputHeaders.emplace_back( + FullPath, Type, IncludeName.has_value() ? *IncludeName : ""); + Ctx.InputHeaders.back().setExtra(); + } + return true; + }; + + if (!HandleExtraHeaders(DriverOpts.ExtraPublicHeaders, HeaderType::Public) || + !HandleExtraHeaders(DriverOpts.ExtraPrivateHeaders, + HeaderType::Private) || + !HandleExtraHeaders(DriverOpts.ExtraProjectHeaders, HeaderType::Project)) + return Ctx; + + // After all headers have been added, consider excluded headers. + std::vector<std::unique_ptr<HeaderGlob>> ExcludedHeaderGlobs; + std::set<FileEntryRef> ExcludedHeaderFiles; + auto ParseGlobs = [&](const PathSeq &Paths, HeaderType Type) { + assert(Type != HeaderType::Unknown && "Missing header type."); + for (const StringRef Path : Paths) { + auto Glob = HeaderGlob::create(Path, Type); + if (Glob) + ExcludedHeaderGlobs.emplace_back(std::move(Glob.get())); + else { + consumeError(Glob.takeError()); + if (auto File = FM->getFileRef(Path)) + ExcludedHeaderFiles.emplace(*File); + else { + Diags->Report(diag::err_no_such_header_file) + << Path << (unsigned)Type; + return false; + } + } + } + return true; + }; + + if (!ParseGlobs(DriverOpts.ExcludePublicHeaders, HeaderType::Public) || + !ParseGlobs(DriverOpts.ExcludePrivateHeaders, HeaderType::Private) || + !ParseGlobs(DriverOpts.ExcludeProjectHeaders, HeaderType::Project)) + return Ctx; + + for (HeaderFile &Header : Ctx.InputHeaders) { + for (auto &Glob : ExcludedHeaderGlobs) + if (Glob->match(Header)) + Header.setExcluded(); + } + if (!ExcludedHeaderFiles.empty()) { + for (HeaderFile &Header : Ctx.InputHeaders) { + auto FileRef = FM->getFileRef(Header.getPath()); + if (!FileRef) + continue; + if (ExcludedHeaderFiles.count(*FileRef)) + Header.setExcluded(); + } + } + // Report if glob was ignored. + for (const auto &Glob : ExcludedHeaderGlobs) + if (!Glob->didMatch()) + Diags->Report(diag::warn_glob_did_not_match) << Glob->str(); + + // Mark any explicit or inferred umbrella headers. If one exists, move + // that to the beginning of the input headers. + auto MarkandMoveUmbrellaInHeaders = [&](llvm::Regex &Regex, + HeaderType Type) -> bool { + auto It = find_if(Ctx.InputHeaders, [&Regex, Type](const HeaderFile &H) { + return (H.getType() == Type) && Regex.match(H.getPath()); + }); + + if (It == Ctx.InputHeaders.end()) + return false; + It->setUmbrellaHeader(); + + // Because there can be an umbrella header per header type, + // find the first non umbrella header to swap position with. + auto BeginPos = find_if(Ctx.InputHeaders, [](const HeaderFile &H) { + return !H.isUmbrellaHeader(); + }); + if (BeginPos != Ctx.InputHeaders.end() && BeginPos < It) + std::swap(*BeginPos, *It); + return true; + }; + + auto FindUmbrellaHeader = [&](StringRef HeaderPath, HeaderType Type) -> bool { + assert(Type != HeaderType::Unknown && "Missing header type."); + if (!HeaderPath.empty()) { + auto EscapedString = Regex::escape(HeaderPath); + Regex UmbrellaRegex(EscapedString); + if (!MarkandMoveUmbrellaInHeaders(UmbrellaRegex, Type)) { + Diags->Report(diag::err_no_such_umbrella_header_file) + << HeaderPath << (unsigned)Type; + return false; + } + } else if (!FrameworkName.empty() && (Type != HeaderType::Project)) { + auto UmbrellaName = "/" + Regex::escape(FrameworkName); + if (Type == HeaderType::Public) + UmbrellaName += "\\.h"; + else + UmbrellaName += "[_]?Private\\.h"; + Regex UmbrellaRegex(UmbrellaName); + MarkandMoveUmbrellaInHeaders(UmbrellaRegex, Type); + } + return true; + }; + if (!FindUmbrellaHeader(DriverOpts.PublicUmbrellaHeader, + HeaderType::Public) || + !FindUmbrellaHeader(DriverOpts.PrivateUmbrellaHeader, + HeaderType::Private) || + !FindUmbrellaHeader(DriverOpts.ProjectUmbrellaHeader, + HeaderType::Project)) + return Ctx; + + // Parse binary dylib and initialize verifier. + if (DriverOpts.DylibToVerify.empty()) { + Ctx.Verifier = std::make_unique<DylibVerifier>(); + return Ctx; + } + + auto Buffer = FM->getBufferForFile(DriverOpts.DylibToVerify); + if (auto Err = Buffer.getError()) { + Diags->Report(diag::err_cannot_open_file) + << DriverOpts.DylibToVerify << Err.message(); + return Ctx; + } + + DylibReader::ParseOption PO; + PO.Undefineds = false; + Expected<Records> Slices = + DylibReader::readFile((*Buffer)->getMemBufferRef(), PO); + if (auto Err = Slices.takeError()) { + Diags->Report(diag::err_cannot_open_file) << DriverOpts.DylibToVerify; + return Ctx; + } + Ctx.Verifier = std::make_unique<DylibVerifier>( + std::move(*Slices), Diags, DriverOpts.VerifyMode, DriverOpts.Demangle, + DriverOpts.DSYMPath); return Ctx; } diff --git a/clang/tools/clang-installapi/Options.h b/clang/tools/clang-installapi/Options.h index 06f79b62c531ec04d607b34176e5997a19fec5af..82e04b49d125962a8ba7de0d8ee73d38ab8f7147 100644 --- a/clang/tools/clang-installapi/Options.h +++ b/clang/tools/clang-installapi/Options.h @@ -11,8 +11,10 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" +#include "clang/Driver/Driver.h" #include "clang/Frontend/FrontendOptions.h" #include "clang/InstallAPI/Context.h" +#include "clang/InstallAPI/DylibVerifier.h" #include "clang/InstallAPI/MachO.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" @@ -29,15 +31,54 @@ struct DriverOptions { /// \brief Path to input file lists (JSON). llvm::MachO::PathSeq FileLists; + /// \brief Path to public umbrella header. + std::string PublicUmbrellaHeader; + + /// \brief Path to private umbrella header. + std::string PrivateUmbrellaHeader; + + /// \brief Path to project umbrella header. + std::string ProjectUmbrellaHeader; + + /// \brief Paths of extra public headers. + PathSeq ExtraPublicHeaders; + + /// \brief Paths of extra private headers. + PathSeq ExtraPrivateHeaders; + + /// \brief Paths of extra project headers. + PathSeq ExtraProjectHeaders; + + /// \brief List of excluded public headers. + PathSeq ExcludePublicHeaders; + + /// \brief List of excluded private headers. + PathSeq ExcludePrivateHeaders; + + /// \brief List of excluded project headers. + PathSeq ExcludeProjectHeaders; + /// \brief Mappings of target triples & tapi targets to build for. std::map<llvm::MachO::Target, llvm::Triple> Targets; + /// \brief Path to binary dylib for comparing. + std::string DylibToVerify; + /// \brief Output path. std::string OutputPath; + /// \brief DSYM path. + std::string DSYMPath; + /// \brief File encoding to print. FileType OutFT = FileType::TBD_V5; + /// \brief Verification mode for comparing symbols. + VerificationMode VerifyMode = VerificationMode::Pedantic; + + /// \brief Print demangled symbols when reporting errors. + bool Demangle = false; + /// \brief Print verbose output. bool Verbose = false; }; @@ -49,6 +90,9 @@ struct LinkerOptions { /// \brief The current version to use for the dynamic library. PackedVersion CurrentVersion; + /// \brief The compatibility version to use for the dynamic library. + PackedVersion CompatVersion; + /// \brief Is application extension safe. bool AppExtensionSafe = false; @@ -66,6 +110,8 @@ private: bool processDriverOptions(llvm::opt::InputArgList &Args); bool processLinkerOptions(llvm::opt::InputArgList &Args); bool processFrontendOptions(llvm::opt::InputArgList &Args); + std::vector<const char *> + processAndFilterOutInstallAPIOptions(ArrayRef<const char *> Args); public: /// The various options grouped together. @@ -80,18 +126,31 @@ public: /// \brief Constructor for options. Options(clang::DiagnosticsEngine &Diag, FileManager *FM, - llvm::opt::InputArgList &Args); + ArrayRef<const char *> Args, const StringRef ProgName); /// \brief Get CC1 arguments after extracting out the irrelevant /// ones. std::vector<std::string> &getClangFrontendArgs() { return FrontendArgs; } private: + bool addFilePaths(llvm::opt::InputArgList &Args, PathSeq &Headers, + llvm::opt::OptSpecifier ID); + DiagnosticsEngine *Diags; FileManager *FM; std::vector<std::string> FrontendArgs; }; +enum ID { + OPT_INVALID = 0, // This is not an option ID. +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, \ + VISIBILITY, PARAM, HELPTEXT, METAVAR, VALUES) \ + OPT_##ID, +#include "InstallAPIOpts.inc" + LastOption +#undef OPTION +}; + } // namespace installapi } // namespace clang #endif diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index 535ef42c78c46317976c29be80b3a83f0eeef75b..c60be2789bd61e9c09258a795536ed8e505ed64f 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -562,6 +562,7 @@ Expected<StringRef> linkDevice(ArrayRef<StringRef> InputFiles, case Triple::aarch64_be: case Triple::ppc64: case Triple::ppc64le: + case Triple::systemz: return generic::clang(InputFiles, Args); default: return createStringError(inconvertibleErrorCode(), diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp index d042fecc3dbe63af73ebedf3930c24888f3f4b47..eaa76dd43e41dd8856a8495613754aad82e7966e 100644 --- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp +++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp @@ -867,13 +867,6 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) { // Print out the dependency results to STDOUT by default. SharedStream DependencyOS(llvm::outs()); - DependencyScanningService Service(ScanMode, Format, OptimizeArgs, - EagerLoadModules); - llvm::DefaultThreadPool Pool(llvm::hardware_concurrency(NumThreads)); - std::vector<std::unique_ptr<DependencyScanningTool>> WorkerTools; - for (unsigned I = 0; I < Pool.getMaxConcurrency(); ++I) - WorkerTools.push_back(std::make_unique<DependencyScanningTool>(Service)); - std::vector<tooling::CompileCommand> Inputs = AdjustingCompilations->getAllCompileCommands(); @@ -893,102 +886,114 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) { if (Format == ScanningOutputFormat::Full) FD.emplace(ModuleName.empty() ? Inputs.size() : 0); - if (Verbose) { - llvm::outs() << "Running clang-scan-deps on " << Inputs.size() - << " files using " << Pool.getMaxConcurrency() << " workers\n"; - } + auto ScanningTask = [&](DependencyScanningService &Service) { + DependencyScanningTool WorkerTool(Service); + + llvm::DenseSet<ModuleID> AlreadySeenModules; + while (auto MaybeInputIndex = GetNextInputIndex()) { + size_t LocalIndex = *MaybeInputIndex; + const tooling::CompileCommand *Input = &Inputs[LocalIndex]; + std::string Filename = std::move(Input->Filename); + std::string CWD = std::move(Input->Directory); + + std::optional<StringRef> MaybeModuleName; + if (!ModuleName.empty()) + MaybeModuleName = ModuleName; + + std::string OutputDir(ModuleFilesDir); + if (OutputDir.empty()) + OutputDir = getModuleCachePath(Input->CommandLine); + auto LookupOutput = [&](const ModuleID &MID, ModuleOutputKind MOK) { + return ::lookupModuleOutput(MID, MOK, OutputDir); + }; + + // Run the tool on it. + if (Format == ScanningOutputFormat::Make) { + auto MaybeFile = WorkerTool.getDependencyFile(Input->CommandLine, CWD); + if (handleMakeDependencyToolResult(Filename, MaybeFile, DependencyOS, + Errs)) + HadErrors = true; + } else if (Format == ScanningOutputFormat::P1689) { + // It is useful to generate the make-format dependency output during + // the scanning for P1689. Otherwise the users need to scan again for + // it. We will generate the make-format dependency output if we find + // `-MF` in the command lines. + std::string MakeformatOutputPath; + std::string MakeformatOutput; + + auto MaybeRule = WorkerTool.getP1689ModuleDependencyFile( + *Input, CWD, MakeformatOutput, MakeformatOutputPath); + + if (handleP1689DependencyToolResult(Filename, MaybeRule, PD, Errs)) + HadErrors = true; + + if (!MakeformatOutputPath.empty() && !MakeformatOutput.empty() && + !HadErrors) { + static std::mutex Lock; + // With compilation database, we may open different files + // concurrently or we may write the same file concurrently. So we + // use a map here to allow multiple compile commands to write to the + // same file. Also we need a lock here to avoid data race. + static llvm::StringMap<llvm::raw_fd_ostream> OSs; + std::unique_lock<std::mutex> LockGuard(Lock); + + auto OSIter = OSs.find(MakeformatOutputPath); + if (OSIter == OSs.end()) { + std::error_code EC; + OSIter = + OSs.try_emplace(MakeformatOutputPath, MakeformatOutputPath, EC) + .first; + if (EC) + llvm::errs() << "Failed to open P1689 make format output file \"" + << MakeformatOutputPath << "\" for " << EC.message() + << "\n"; + } + + SharedStream MakeformatOS(OSIter->second); + llvm::Expected<std::string> MaybeOutput(MakeformatOutput); + if (handleMakeDependencyToolResult(Filename, MaybeOutput, + MakeformatOS, Errs)) + HadErrors = true; + } + } else if (MaybeModuleName) { + auto MaybeModuleDepsGraph = WorkerTool.getModuleDependencies( + *MaybeModuleName, Input->CommandLine, CWD, AlreadySeenModules, + LookupOutput); + if (handleModuleResult(*MaybeModuleName, MaybeModuleDepsGraph, *FD, + LocalIndex, DependencyOS, Errs)) + HadErrors = true; + } else { + auto MaybeTUDeps = WorkerTool.getTranslationUnitDependencies( + Input->CommandLine, CWD, AlreadySeenModules, LookupOutput); + if (handleTranslationUnitResult(Filename, MaybeTUDeps, *FD, LocalIndex, + DependencyOS, Errs)) + HadErrors = true; + } + } + }; + + DependencyScanningService Service(ScanMode, Format, OptimizeArgs, + EagerLoadModules); llvm::Timer T; T.startTimer(); - for (unsigned I = 0; I < Pool.getMaxConcurrency(); ++I) { - Pool.async([&, I]() { - llvm::DenseSet<ModuleID> AlreadySeenModules; - while (auto MaybeInputIndex = GetNextInputIndex()) { - size_t LocalIndex = *MaybeInputIndex; - const tooling::CompileCommand *Input = &Inputs[LocalIndex]; - std::string Filename = std::move(Input->Filename); - std::string CWD = std::move(Input->Directory); - - std::optional<StringRef> MaybeModuleName; - if (!ModuleName.empty()) - MaybeModuleName = ModuleName; - - std::string OutputDir(ModuleFilesDir); - if (OutputDir.empty()) - OutputDir = getModuleCachePath(Input->CommandLine); - auto LookupOutput = [&](const ModuleID &MID, ModuleOutputKind MOK) { - return ::lookupModuleOutput(MID, MOK, OutputDir); - }; + if (Inputs.size() == 1) { + ScanningTask(Service); + } else { + llvm::DefaultThreadPool Pool(llvm::hardware_concurrency(NumThreads)); - // Run the tool on it. - if (Format == ScanningOutputFormat::Make) { - auto MaybeFile = - WorkerTools[I]->getDependencyFile(Input->CommandLine, CWD); - if (handleMakeDependencyToolResult(Filename, MaybeFile, DependencyOS, - Errs)) - HadErrors = true; - } else if (Format == ScanningOutputFormat::P1689) { - // It is useful to generate the make-format dependency output during - // the scanning for P1689. Otherwise the users need to scan again for - // it. We will generate the make-format dependency output if we find - // `-MF` in the command lines. - std::string MakeformatOutputPath; - std::string MakeformatOutput; - - auto MaybeRule = WorkerTools[I]->getP1689ModuleDependencyFile( - *Input, CWD, MakeformatOutput, MakeformatOutputPath); - - if (handleP1689DependencyToolResult(Filename, MaybeRule, PD, Errs)) - HadErrors = true; + if (Verbose) { + llvm::outs() << "Running clang-scan-deps on " << Inputs.size() + << " files using " << Pool.getMaxConcurrency() + << " workers\n"; + } - if (!MakeformatOutputPath.empty() && !MakeformatOutput.empty() && - !HadErrors) { - static std::mutex Lock; - // With compilation database, we may open different files - // concurrently or we may write the same file concurrently. So we - // use a map here to allow multiple compile commands to write to the - // same file. Also we need a lock here to avoid data race. - static llvm::StringMap<llvm::raw_fd_ostream> OSs; - std::unique_lock<std::mutex> LockGuard(Lock); - - auto OSIter = OSs.find(MakeformatOutputPath); - if (OSIter == OSs.end()) { - std::error_code EC; - OSIter = OSs.try_emplace(MakeformatOutputPath, - MakeformatOutputPath, EC) - .first; - if (EC) - llvm::errs() - << "Failed to open P1689 make format output file \"" - << MakeformatOutputPath << "\" for " << EC.message() - << "\n"; - } + for (unsigned I = 0; I < Pool.getMaxConcurrency(); ++I) + Pool.async([ScanningTask, &Service]() { ScanningTask(Service); }); - SharedStream MakeformatOS(OSIter->second); - llvm::Expected<std::string> MaybeOutput(MakeformatOutput); - if (handleMakeDependencyToolResult(Filename, MaybeOutput, - MakeformatOS, Errs)) - HadErrors = true; - } - } else if (MaybeModuleName) { - auto MaybeModuleDepsGraph = WorkerTools[I]->getModuleDependencies( - *MaybeModuleName, Input->CommandLine, CWD, AlreadySeenModules, - LookupOutput); - if (handleModuleResult(*MaybeModuleName, MaybeModuleDepsGraph, *FD, - LocalIndex, DependencyOS, Errs)) - HadErrors = true; - } else { - auto MaybeTUDeps = WorkerTools[I]->getTranslationUnitDependencies( - Input->CommandLine, CWD, AlreadySeenModules, LookupOutput); - if (handleTranslationUnitResult(Filename, MaybeTUDeps, *FD, - LocalIndex, DependencyOS, Errs)) - HadErrors = true; - } - } - }); + Pool.wait(); } - Pool.wait(); T.stopTimer(); if (PrintTiming) diff --git a/clang/tools/diagtool/DiagnosticNames.cpp b/clang/tools/diagtool/DiagnosticNames.cpp index 852b8c226e88595b31e930d0b13e4104ed854004..eb90f082437b3378a1525dfa98e9f6b581466d00 100644 --- a/clang/tools/diagtool/DiagnosticNames.cpp +++ b/clang/tools/diagtool/DiagnosticNames.cpp @@ -42,6 +42,7 @@ static const DiagnosticRecord BuiltinDiagnosticsByID[] = { #include "clang/Basic/DiagnosticSemaKinds.inc" #include "clang/Basic/DiagnosticAnalysisKinds.inc" #include "clang/Basic/DiagnosticRefactoringKinds.inc" +#include "clang/Basic/DiagnosticInstallAPIKinds.inc" #undef DIAG }; diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp index 376025e3605be897c5478b44e1e049c5d2cce572..83b5bbb71f5212375170085b6bb0f29a0ecaff85 100644 --- a/clang/tools/driver/driver.cpp +++ b/clang/tools/driver/driver.cpp @@ -28,6 +28,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSet.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/OptTable.h" #include "llvm/Option/Option.h" @@ -41,7 +42,6 @@ #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Process.h" #include "llvm/Support/Program.h" -#include "llvm/Support/Regex.h" #include "llvm/Support/Signals.h" #include "llvm/Support/StringSaver.h" #include "llvm/Support/TargetSelect.h" @@ -73,136 +73,8 @@ std::string GetExecutablePath(const char *Argv0, bool CanonicalPrefixes) { return llvm::sys::fs::getMainExecutable(Argv0, P); } -static const char *GetStableCStr(std::set<std::string> &SavedStrings, - StringRef S) { - return SavedStrings.insert(std::string(S)).first->c_str(); -} - -/// ApplyOneQAOverride - Apply a list of edits to the input argument lists. -/// -/// The input string is a space separated list of edits to perform, -/// they are applied in order to the input argument lists. Edits -/// should be one of the following forms: -/// -/// '#': Silence information about the changes to the command line arguments. -/// -/// '^': Add FOO as a new argument at the beginning of the command line. -/// -/// '+': Add FOO as a new argument at the end of the command line. -/// -/// 's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command -/// line. -/// -/// 'xOPTION': Removes all instances of the literal argument OPTION. -/// -/// 'XOPTION': Removes all instances of the literal argument OPTION, -/// and the following argument. -/// -/// 'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox' -/// at the end of the command line. -/// -/// \param OS - The stream to write edit information to. -/// \param Args - The vector of command line arguments. -/// \param Edit - The override command to perform. -/// \param SavedStrings - Set to use for storing string representations. -static void ApplyOneQAOverride(raw_ostream &OS, - SmallVectorImpl<const char*> &Args, - StringRef Edit, - std::set<std::string> &SavedStrings) { - // This does not need to be efficient. - - if (Edit[0] == '^') { - const char *Str = - GetStableCStr(SavedStrings, Edit.substr(1)); - OS << "### Adding argument " << Str << " at beginning\n"; - Args.insert(Args.begin() + 1, Str); - } else if (Edit[0] == '+') { - const char *Str = - GetStableCStr(SavedStrings, Edit.substr(1)); - OS << "### Adding argument " << Str << " at end\n"; - Args.push_back(Str); - } else if (Edit[0] == 's' && Edit[1] == '/' && Edit.ends_with("/") && - Edit.slice(2, Edit.size() - 1).contains('/')) { - StringRef MatchPattern = Edit.substr(2).split('/').first; - StringRef ReplPattern = Edit.substr(2).split('/').second; - ReplPattern = ReplPattern.slice(0, ReplPattern.size()-1); - - for (unsigned i = 1, e = Args.size(); i != e; ++i) { - // Ignore end-of-line response file markers - if (Args[i] == nullptr) - continue; - std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]); - - if (Repl != Args[i]) { - OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n"; - Args[i] = GetStableCStr(SavedStrings, Repl); - } - } - } else if (Edit[0] == 'x' || Edit[0] == 'X') { - auto Option = Edit.substr(1); - for (unsigned i = 1; i < Args.size();) { - if (Option == Args[i]) { - OS << "### Deleting argument " << Args[i] << '\n'; - Args.erase(Args.begin() + i); - if (Edit[0] == 'X') { - if (i < Args.size()) { - OS << "### Deleting argument " << Args[i] << '\n'; - Args.erase(Args.begin() + i); - } else - OS << "### Invalid X edit, end of command line!\n"; - } - } else - ++i; - } - } else if (Edit[0] == 'O') { - for (unsigned i = 1; i < Args.size();) { - const char *A = Args[i]; - // Ignore end-of-line response file markers - if (A == nullptr) - continue; - if (A[0] == '-' && A[1] == 'O' && - (A[2] == '\0' || - (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' || - ('0' <= A[2] && A[2] <= '9'))))) { - OS << "### Deleting argument " << Args[i] << '\n'; - Args.erase(Args.begin() + i); - } else - ++i; - } - OS << "### Adding argument " << Edit << " at end\n"; - Args.push_back(GetStableCStr(SavedStrings, '-' + Edit.str())); - } else { - OS << "### Unrecognized edit: " << Edit << "\n"; - } -} - -/// ApplyQAOverride - Apply a space separated list of edits to the -/// input argument lists. See ApplyOneQAOverride. -static void ApplyQAOverride(SmallVectorImpl<const char*> &Args, - const char *OverrideStr, - std::set<std::string> &SavedStrings) { - raw_ostream *OS = &llvm::errs(); - - if (OverrideStr[0] == '#') { - ++OverrideStr; - OS = &llvm::nulls(); - } - - *OS << "### CCC_OVERRIDE_OPTIONS: " << OverrideStr << "\n"; - - // This does not need to be efficient. - - const char *S = OverrideStr; - while (*S) { - const char *End = ::strchr(S, ' '); - if (!End) - End = S + strlen(S); - if (End != S) - ApplyOneQAOverride(*OS, Args, std::string(S, End), SavedStrings); - S = End; - if (*S != '\0') - ++S; - } +static const char *GetStableCStr(llvm::StringSet<> &SavedStrings, StringRef S) { + return SavedStrings.insert(S).first->getKeyData(); } extern int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, @@ -215,7 +87,7 @@ extern int cc1gen_reproducer_main(ArrayRef<const char *> Argv, static void insertTargetAndModeArgs(const ParsedClangName &NameParts, SmallVectorImpl<const char *> &ArgVector, - std::set<std::string> &SavedStrings) { + llvm::StringSet<> &SavedStrings) { // Put target and mode arguments at the start of argument list so that // arguments specified in command line could override them. Avoid putting // them at index 0, as an option like '-cc1' must remain the first. @@ -419,12 +291,13 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) { } } - std::set<std::string> SavedStrings; + llvm::StringSet<> SavedStrings; // Handle CCC_OVERRIDE_OPTIONS, used for editing a command line behind the // scenes. if (const char *OverrideStr = ::getenv("CCC_OVERRIDE_OPTIONS")) { // FIXME: Driver shouldn't take extra initial argument. - ApplyQAOverride(Args, OverrideStr, SavedStrings); + driver::applyOverrideOptions(Args, OverrideStr, SavedStrings, + &llvm::errs()); } std::string Path = GetExecutablePath(ToolContext.Path, CanonicalPrefixes); diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 418b152ba4a13f3809995b46906ff5361804c776..00ddc4f24500fd4f05868199db1de88eef270829 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1778,6 +1778,10 @@ bool CursorVisitor::VisitAttributedTypeLoc(AttributedTypeLoc TL) { return Visit(TL.getModifiedLoc()); } +bool CursorVisitor::VisitCountAttributedTypeLoc(CountAttributedTypeLoc TL) { + return Visit(TL.getInnerLoc()); +} + bool CursorVisitor::VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) { return Visit(TL.getWrappedLoc()); } @@ -1919,6 +1923,7 @@ DEFAULT_TYPELOC_IMPL(ConstantArray, ArrayType) DEFAULT_TYPELOC_IMPL(IncompleteArray, ArrayType) DEFAULT_TYPELOC_IMPL(VariableArray, ArrayType) DEFAULT_TYPELOC_IMPL(DependentSizedArray, ArrayType) +DEFAULT_TYPELOC_IMPL(ArrayParameter, ConstantArrayType) DEFAULT_TYPELOC_IMPL(DependentAddressSpace, Type) DEFAULT_TYPELOC_IMPL(DependentVector, Type) DEFAULT_TYPELOC_IMPL(DependentSizedExtVector, Type) diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp index 292d524f00abd697bf1aec0822965a1c2ec00b0f..991767dc4c49c67e91e27ae474e9f6ce956c93a0 100644 --- a/clang/tools/libclang/CXType.cpp +++ b/clang/tools/libclang/CXType.cpp @@ -680,6 +680,7 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) { TCALLINGCONV(PreserveAll); TCALLINGCONV(M68kRTD); TCALLINGCONV(PreserveNone); + TCALLINGCONV(RISCVVectorCall); case CC_SpirFunction: return CXCallingConv_Unexposed; case CC_AMDGPUKernelCall: return CXCallingConv_Unexposed; case CC_OpenCLKernel: return CXCallingConv_Unexposed; diff --git a/clang/unittests/AST/DeclPrinterTest.cpp b/clang/unittests/AST/DeclPrinterTest.cpp index 0e09ab2a7bba88be1a3288dadf3ccc1219d87667..f2b027a25621ce9d2a131bd5f7ecae642cbe43c9 100644 --- a/clang/unittests/AST/DeclPrinterTest.cpp +++ b/clang/unittests/AST/DeclPrinterTest.cpp @@ -358,6 +358,59 @@ TEST(DeclPrinter, TestCXXRecordDecl11) { "class A : virtual public Z, private Y {}")); } +TEST(DeclPrinter, TestCXXRecordDecl12) { + ASSERT_TRUE( + PrintedDeclCXX98Matches("struct S { int x; };" + "namespace NS { class C {};}" + "void foo() {using namespace NS; C c;}", + "foo", + "void foo() {\nusing namespace NS;\nclass " + "NS::C c;\n}\n", + [](PrintingPolicy &Policy) { + Policy.SuppressTagKeyword = false; + Policy.SuppressScope = true; + Policy.TerseOutput = false; + })); +} + +TEST(DeclPrinter, TestCXXRecordDecl13) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "struct S { int x; };" + "S s1;" + "S foo() {return s1;}", + "foo", "struct S foo() {\nreturn s1;\n}\n", [](PrintingPolicy &Policy) { + Policy.SuppressTagKeyword = false; + Policy.SuppressScope = true; + Policy.TerseOutput = false; + })); +} + +TEST(DeclPrinter, TestCXXRecordDecl14) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "struct S { int x; };" + "S foo(S s1) {return s1;}", + "foo", "struct S foo(struct S s1) {\nreturn s1;\n}\n", + [](PrintingPolicy &Policy) { + Policy.SuppressTagKeyword = false; + Policy.SuppressScope = true; + Policy.TerseOutput = false; + })); +} +TEST(DeclPrinter, TestCXXRecordDecl15) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "struct S { int x; };" + "namespace NS { class C {};}" + "S foo(S s1, NS::C c1) {using namespace NS; C c; return s1;}", + "foo", + "struct S foo(struct S s1, class NS::C c1) {\nusing namespace NS;\nclass " + "NS::C c;\nreturn s1;\n}\n", + [](PrintingPolicy &Policy) { + Policy.SuppressTagKeyword = false; + Policy.SuppressScope = true; + Policy.TerseOutput = false; + })); +} + TEST(DeclPrinter, TestFunctionDecl1) { ASSERT_TRUE(PrintedDeclCXX98Matches( "void A();", @@ -1333,6 +1386,79 @@ TEST(DeclPrinter, TestTemplateArgumentList16) { ASSERT_TRUE(PrintedDeclCXX11Matches(Code, "NT2", "int NT2 = 5")); } +TEST(DeclPrinter, TestCXXRecordDecl17) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "template<typename T> struct Z {};" + "struct X {};" + "Z<X> A;", + "A", "Z<X> A", + [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = false; })); +} + +TEST(DeclPrinter, TestCXXRecordDecl18) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "template<typename T> struct Z {};" + "struct X {};" + "Z<X> A;" + "template <typename T1, int>" + "struct Y{};" + "Y<Z<X>, 2> B;", + "B", "Y<Z<X>, 2> B", + [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = false; })); +} + +TEST(DeclPrinter, TestCXXRecordDecl19) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "template<typename T> struct Z {};" + "struct X {};" + "Z<X> A;" + "template <typename T1, int>" + "struct Y{};" + "Y<Z<X>, 2> B;", + "B", "Y<Z<X>, 2> B", + [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = true; })); +} + +TEST(DeclPrinter, TestCXXRecordDecl20) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "template <typename T, int N> class Inner;" + "template <typename T, int N>" + "class Inner{Inner(T val){}};" + "template <class InnerClass, int N> class Outer {" + "public:" + "struct NestedStruct {" + "int nestedValue;" + "NestedStruct(int val) : nestedValue(val) {}" + "};" + "InnerClass innerInstance;" + "Outer(const InnerClass &inner) : innerInstance(inner) {}" + "};" + "Outer<Inner<int, 10>, 5>::NestedStruct nestedInstance(100);", + "nestedInstance", + "Outer<Inner<int, 10>, 5>::NestedStruct nestedInstance(100)", + [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = false; })); +} + +TEST(DeclPrinter, TestCXXRecordDecl21) { + ASSERT_TRUE(PrintedDeclCXX98Matches( + "template <typename T, int N> class Inner;" + "template <typename T, int N>" + "class Inner{Inner(T val){}};" + "template <class InnerClass, int N> class Outer {" + "public:" + "struct NestedStruct {" + "int nestedValue;" + "NestedStruct(int val) : nestedValue(val) {}" + "};" + "InnerClass innerInstance;" + "Outer(const InnerClass &inner) : innerInstance(inner) {}" + "};" + "Outer<Inner<int, 10>, 5>::NestedStruct nestedInstance(100);", + "nestedInstance", + "Outer<Inner<int, 10>, 5>::NestedStruct nestedInstance(100)", + [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = true; })); +} + TEST(DeclPrinter, TestFunctionParamUglified) { llvm::StringLiteral Code = R"cpp( class __c; diff --git a/clang/unittests/AST/DeclTest.cpp b/clang/unittests/AST/DeclTest.cpp index cef0f8711416b699f8decc04d4402e0b68731683..2530ce74eb6a37623e4d71bda419e8a3c1ae0acb 100644 --- a/clang/unittests/AST/DeclTest.cpp +++ b/clang/unittests/AST/DeclTest.cpp @@ -429,7 +429,7 @@ TEST(Decl, ImplicitlyDeclaredAllocationFunctionsInModules) { .bind("operator new"), Ctx)); ASSERT_TRUE(SizedOperatorNew->getOwningModule()); - EXPECT_TRUE(SizedOperatorNew->getOwningModule()->isGlobalModule()); + EXPECT_TRUE(SizedOperatorNew->isFromExplicitGlobalModule()); // void* operator new(std::size_t, std::align_val_t); auto *SizedAlignedOperatorNew = selectFirst<FunctionDecl>( @@ -441,7 +441,7 @@ TEST(Decl, ImplicitlyDeclaredAllocationFunctionsInModules) { .bind("operator new"), Ctx)); ASSERT_TRUE(SizedAlignedOperatorNew->getOwningModule()); - EXPECT_TRUE(SizedAlignedOperatorNew->getOwningModule()->isGlobalModule()); + EXPECT_TRUE(SizedAlignedOperatorNew->isFromExplicitGlobalModule()); // void* operator new[](std::size_t); auto *SizedArrayOperatorNew = selectFirst<FunctionDecl>( @@ -451,7 +451,7 @@ TEST(Decl, ImplicitlyDeclaredAllocationFunctionsInModules) { .bind("operator new[]"), Ctx)); ASSERT_TRUE(SizedArrayOperatorNew->getOwningModule()); - EXPECT_TRUE(SizedArrayOperatorNew->getOwningModule()->isGlobalModule()); + EXPECT_TRUE(SizedArrayOperatorNew->isFromExplicitGlobalModule()); // void* operator new[](std::size_t, std::align_val_t); auto *SizedAlignedArrayOperatorNew = selectFirst<FunctionDecl>( @@ -464,7 +464,7 @@ TEST(Decl, ImplicitlyDeclaredAllocationFunctionsInModules) { Ctx)); ASSERT_TRUE(SizedAlignedArrayOperatorNew->getOwningModule()); EXPECT_TRUE( - SizedAlignedArrayOperatorNew->getOwningModule()->isGlobalModule()); + SizedAlignedArrayOperatorNew->isFromExplicitGlobalModule()); // void operator delete(void*) noexcept; auto *Delete = selectFirst<FunctionDecl>( @@ -475,7 +475,7 @@ TEST(Decl, ImplicitlyDeclaredAllocationFunctionsInModules) { .bind("operator delete"), Ctx)); ASSERT_TRUE(Delete->getOwningModule()); - EXPECT_TRUE(Delete->getOwningModule()->isGlobalModule()); + EXPECT_TRUE(Delete->isFromExplicitGlobalModule()); // void operator delete(void*, std::align_val_t) noexcept; auto *AlignedDelete = selectFirst<FunctionDecl>( @@ -487,7 +487,7 @@ TEST(Decl, ImplicitlyDeclaredAllocationFunctionsInModules) { .bind("operator delete"), Ctx)); ASSERT_TRUE(AlignedDelete->getOwningModule()); - EXPECT_TRUE(AlignedDelete->getOwningModule()->isGlobalModule()); + EXPECT_TRUE(AlignedDelete->isFromExplicitGlobalModule()); // Sized deallocation is not enabled by default. So we skip it here. @@ -500,7 +500,7 @@ TEST(Decl, ImplicitlyDeclaredAllocationFunctionsInModules) { .bind("operator delete[]"), Ctx)); ASSERT_TRUE(ArrayDelete->getOwningModule()); - EXPECT_TRUE(ArrayDelete->getOwningModule()->isGlobalModule()); + EXPECT_TRUE(ArrayDelete->isFromExplicitGlobalModule()); // void operator delete[](void*, std::align_val_t) noexcept; auto *AlignedArrayDelete = selectFirst<FunctionDecl>( @@ -512,7 +512,7 @@ TEST(Decl, ImplicitlyDeclaredAllocationFunctionsInModules) { .bind("operator delete[]"), Ctx)); ASSERT_TRUE(AlignedArrayDelete->getOwningModule()); - EXPECT_TRUE(AlignedArrayDelete->getOwningModule()->isGlobalModule()); + EXPECT_TRUE(AlignedArrayDelete->isFromExplicitGlobalModule()); } TEST(Decl, TemplateArgumentDefaulted) { diff --git a/clang/unittests/AST/TypePrinterTest.cpp b/clang/unittests/AST/TypePrinterTest.cpp index f0a6eb7e9fd8c90073500150b7234475ea5fb02f..494085a2ebca6b88d5a743e2dbc9c6d3eafef2ee 100644 --- a/clang/unittests/AST/TypePrinterTest.cpp +++ b/clang/unittests/AST/TypePrinterTest.cpp @@ -155,6 +155,22 @@ TEST(TypePrinter, TemplateIdWithNTTP) { })); } +TEST(TypePrinter, TemplateArgumentsSubstitution) { + constexpr char Code[] = R"cpp( + template <typename Y> class X {}; + typedef X<int> A; + int foo() { + return sizeof(A); + } + )cpp"; + auto Matcher = typedefNameDecl(hasName("A"), hasType(qualType().bind("id"))); + ASSERT_TRUE(PrintedTypeMatches(Code, {}, Matcher, "X<int>", + [](PrintingPolicy &Policy) { + Policy.SuppressTagKeyword = false; + Policy.SuppressScope = true; + })); +} + TEST(TypePrinter, TemplateArgumentsSubstitution_Expressions) { /// Tests clang::isSubstitutedDefaultArgument on TemplateArguments /// that are of kind TemplateArgument::Expression diff --git a/clang/unittests/Analysis/FlowSensitive/DeterminismTest.cpp b/clang/unittests/Analysis/FlowSensitive/DeterminismTest.cpp index 5ba26a08320364e1fb637d6494618b2d932b0048..a2cbfb1ff5826baa194826f7f52a45e16b9e660b 100644 --- a/clang/unittests/Analysis/FlowSensitive/DeterminismTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/DeterminismTest.cpp @@ -8,7 +8,7 @@ #include "TestingSupport.h" #include "clang/AST/Decl.h" -#include "clang/Analysis/FlowSensitive/ControlFlowContext.h" +#include "clang/Analysis/FlowSensitive/AdornedCFG.h" #include "clang/Analysis/FlowSensitive/DataflowAnalysis.h" #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" @@ -30,18 +30,20 @@ namespace clang::dataflow { // flow-condition at function exit. std::string analyzeAndPrintExitCondition(llvm::StringRef Code) { DataflowAnalysisContext DACtx(std::make_unique<WatchedLiteralsSolver>()); - clang::TestAST AST(Code); + TestInputs Inputs(Code); + Inputs.Language = TestLanguage::Lang_CXX17; + clang::TestAST AST(Inputs); const auto *Target = cast<FunctionDecl>(test::findValueDecl(AST.context(), "target")); Environment InitEnv(DACtx, *Target); - auto CFCtx = cantFail(ControlFlowContext::build(*Target)); + auto ACFG = cantFail(AdornedCFG::build(*Target)); NoopAnalysis Analysis(AST.context(), DataflowAnalysisOptions{}); - auto Result = runDataflowAnalysis(CFCtx, Analysis, InitEnv); + auto Result = runDataflowAnalysis(ACFG, Analysis, InitEnv); EXPECT_FALSE(!Result) << Result.takeError(); - Atom FinalFC = (*Result)[CFCtx.getCFG().getExit().getBlockID()] + Atom FinalFC = (*Result)[ACFG.getCFG().getExit().getBlockID()] ->Env.getFlowConditionToken(); std::string Textual; llvm::raw_string_ostream OS(Textual); diff --git a/clang/unittests/Analysis/FlowSensitive/LoggerTest.cpp b/clang/unittests/Analysis/FlowSensitive/LoggerTest.cpp index 57920c49a7d3ddc12869fc0e5650e126069e6b07..88630119ba8a1a406ea7762dfd71193072604032 100644 --- a/clang/unittests/Analysis/FlowSensitive/LoggerTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/LoggerTest.cpp @@ -57,7 +57,7 @@ public: private: llvm::raw_string_ostream OS; - void beginAnalysis(const ControlFlowContext &, + void beginAnalysis(const AdornedCFG &, TypeErasedDataflowAnalysis &) override { logText("beginAnalysis()"); } diff --git a/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp b/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp index cd6a37d370e854fd0f7344e3413642ddb3d7cf8f..55baa4e2a537757bbef087cf515553e8c4409af5 100644 --- a/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/RecordOpsTest.cpp @@ -198,7 +198,7 @@ TEST(RecordOpsTest, RecordsEqual) { }); } -TEST(TransferTest, CopyRecordFromDerivedToBase) { +TEST(TransferTest, CopyRecordBetweenDerivedAndBase) { std::string Code = R"( struct A { int i; @@ -212,8 +212,23 @@ TEST(TransferTest, CopyRecordFromDerivedToBase) { // [[p]] } )"; + auto SyntheticFieldCallback = [](QualType Ty) -> llvm::StringMap<QualType> { + CXXRecordDecl *ADecl = nullptr; + if (Ty.getAsString() == "A") + ADecl = Ty->getAsCXXRecordDecl(); + else if (Ty.getAsString() == "B") + ADecl = Ty->getAsCXXRecordDecl() + ->bases_begin() + ->getType() + ->getAsCXXRecordDecl(); + else + return {}; + QualType IntTy = getFieldNamed(ADecl, "i")->getType(); + return {{"synth_int", IntTy}}; + }; + // Test copying derived to base class. runDataflow( - Code, /*SyntheticFieldCallback=*/{}, + Code, SyntheticFieldCallback, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, ASTContext &ASTCtx) { Environment Env = getEnvironmentAtAnnotation(Results, "p").fork(); @@ -224,11 +239,38 @@ TEST(TransferTest, CopyRecordFromDerivedToBase) { EXPECT_NE(Env.getValue(*A.getChild(*IDecl)), Env.getValue(*B.getChild(*IDecl))); + EXPECT_NE(Env.getValue(A.getSyntheticField("synth_int")), + Env.getValue(B.getSyntheticField("synth_int"))); copyRecord(B, A, Env); EXPECT_EQ(Env.getValue(*A.getChild(*IDecl)), Env.getValue(*B.getChild(*IDecl))); + EXPECT_EQ(Env.getValue(A.getSyntheticField("synth_int")), + Env.getValue(B.getSyntheticField("synth_int"))); + }); + // Test copying base to derived class. + runDataflow( + Code, SyntheticFieldCallback, + [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, + ASTContext &ASTCtx) { + Environment Env = getEnvironmentAtAnnotation(Results, "p").fork(); + + const ValueDecl *IDecl = findValueDecl(ASTCtx, "i"); + auto &A = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "a"); + auto &B = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "b"); + + EXPECT_NE(Env.getValue(*A.getChild(*IDecl)), + Env.getValue(*B.getChild(*IDecl))); + EXPECT_NE(Env.getValue(A.getSyntheticField("synth_int")), + Env.getValue(B.getSyntheticField("synth_int"))); + + copyRecord(A, B, Env); + + EXPECT_EQ(Env.getValue(*A.getChild(*IDecl)), + Env.getValue(*B.getChild(*IDecl))); + EXPECT_EQ(Env.getValue(A.getSyntheticField("synth_int")), + Env.getValue(B.getSyntheticField("synth_int"))); }); } diff --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h index b7cf6cc966edb082f33ebfcfc87f34982bcf4df9..e3c7ff685f5724bf92b8a4da10a189868077d7c5 100644 --- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h +++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h @@ -28,7 +28,7 @@ #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/ASTMatchers/ASTMatchersInternal.h" #include "clang/Analysis/CFG.h" -#include "clang/Analysis/FlowSensitive/ControlFlowContext.h" +#include "clang/Analysis/FlowSensitive/AdornedCFG.h" #include "clang/Analysis/FlowSensitive/DataflowAnalysis.h" #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" @@ -100,7 +100,7 @@ struct AnalysisOutputs { const FunctionDecl *Target; /// Contains the control flow graph built from the body of the `Target` /// function and is analyzed. - const ControlFlowContext &CFCtx; + const AdornedCFG &ACFG; /// The analysis to be run. TypeErasedDataflowAnalysis &Analysis; /// Initial state to start the analysis. @@ -261,9 +261,10 @@ checkDataflow(AnalysisInputs<AnalysisT> AI, llvm::errc::invalid_argument, "Could not find the target function."); // Build the control flow graph for the target function. - auto MaybeCFCtx = ControlFlowContext::build(*Target); - if (!MaybeCFCtx) return MaybeCFCtx.takeError(); - auto &CFCtx = *MaybeCFCtx; + auto MaybeACFG = AdornedCFG::build(*Target); + if (!MaybeACFG) + return MaybeACFG.takeError(); + auto &ACFG = *MaybeACFG; // Initialize states for running dataflow analysis. DataflowAnalysisContext DACtx(AI.SolverFactory(), @@ -271,7 +272,7 @@ checkDataflow(AnalysisInputs<AnalysisT> AI, Environment InitEnv(DACtx, *Target); auto Analysis = AI.MakeAnalysis(Context, InitEnv); - AnalysisOutputs AO{AnnotatedCode, Context, Target, CFCtx, + AnalysisOutputs AO{AnnotatedCode, Context, Target, ACFG, Analysis, InitEnv, {}}; // Additional test setup. @@ -283,7 +284,7 @@ checkDataflow(AnalysisInputs<AnalysisT> AI, // the post-analysis states for the CFG blocks that have been evaluated. llvm::Expected<std::vector<std::optional<TypeErasedDataflowAnalysisState>>> MaybeBlockStates = - runTypeErasedDataflowAnalysis(CFCtx, Analysis, InitEnv, + runTypeErasedDataflowAnalysis(ACFG, Analysis, InitEnv, TypeErasedPostVisitCFG, MaxBlockVisitsInAnalysis); if (!MaybeBlockStates) return MaybeBlockStates.takeError(); diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index a8c282f140b4cd01b2de0cc2af030537f2c2965f..ca055a462a28660e61025738b8e8a727f717827e 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -17,6 +17,7 @@ #include "clang/Analysis/FlowSensitive/StorageLocation.h" #include "clang/Analysis/FlowSensitive/Value.h" #include "clang/Basic/LangStandard.h" +#include "clang/Testing/TestAST.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Testing/Support/Error.h" @@ -37,6 +38,40 @@ using ::testing::Ne; using ::testing::NotNull; using ::testing::UnorderedElementsAre; +// Declares a minimal coroutine library. +constexpr llvm::StringRef CoroutineLibrary = R"cc( +struct promise; +struct task; + +namespace std { +template <class, class...> +struct coroutine_traits {}; +template <> +struct coroutine_traits<task> { + using promise_type = promise; +}; + +template <class Promise = void> +struct coroutine_handle { + static constexpr coroutine_handle from_address(void *addr) { return {}; } +}; +} // namespace std + +struct awaitable { + bool await_ready() const noexcept; + void await_suspend(std::coroutine_handle<promise>) const noexcept; + void await_resume() const noexcept; +}; +struct task {}; +struct promise { + task get_return_object(); + awaitable initial_suspend(); + awaitable final_suspend() noexcept; + void unhandled_exception(); + void return_void(); +}; +)cc"; + void runDataflow( llvm::StringRef Code, std::function< @@ -101,12 +136,32 @@ const Formula &getFormula(const ValueDecl &D, const Environment &Env) { } TEST(TransferTest, CNotSupported) { - std::string Code = R"( - void target() {} - )"; - ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis( - Code, [](const auto &, auto &) {}, {BuiltinOptions{}}, - LangStandard::lang_c89), + TestInputs Inputs("void target() {}"); + Inputs.Language = TestLanguage::Lang_C89; + clang::TestAST AST(Inputs); + const auto *Target = + cast<FunctionDecl>(test::findValueDecl(AST.context(), "target")); + ASSERT_THAT_ERROR(AdornedCFG::build(*Target).takeError(), + llvm::FailedWithMessage("Can only analyze C++")); +} + +TEST(TransferTest, ObjectiveCNotSupported) { + TestInputs Inputs("void target() {}"); + Inputs.Language = TestLanguage::Lang_OBJC; + clang::TestAST AST(Inputs); + const auto *Target = + cast<FunctionDecl>(test::findValueDecl(AST.context(), "target")); + ASSERT_THAT_ERROR(AdornedCFG::build(*Target).takeError(), + llvm::FailedWithMessage("Can only analyze C++")); +} + +TEST(TransferTest, ObjectiveCXXNotSupported) { + TestInputs Inputs("void target() {}"); + Inputs.Language = TestLanguage::Lang_OBJCXX; + clang::TestAST AST(Inputs); + const auto *Target = + cast<FunctionDecl>(test::findValueDecl(AST.context(), "target")); + ASSERT_THAT_ERROR(AdornedCFG::build(*Target).takeError(), llvm::FailedWithMessage("Can only analyze C++")); } @@ -2313,8 +2368,6 @@ TEST(TransferTest, AssignmentOperator_ArgByValue) { } TEST(TransferTest, AssignmentOperatorFromBase) { - // This is a crash repro. We don't model the copy this case, so no - // expectations on the copied field of the base class are checked. std::string Code = R"( struct Base { int base; @@ -2326,14 +2379,33 @@ TEST(TransferTest, AssignmentOperatorFromBase) { void target(Base B, Derived D) { D.base = 1; D.derived = 1; + // [[before]] D = B; - // [[p]] + // [[after]] } )"; runDataflow( Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, - ASTContext &ASTCtx) {}); + ASTContext &ASTCtx) { + const Environment &EnvBefore = + getEnvironmentAtAnnotation(Results, "before"); + const Environment &EnvAfter = + getEnvironmentAtAnnotation(Results, "after"); + + auto &BLoc = + getLocForDecl<RecordStorageLocation>(ASTCtx, EnvBefore, "B"); + auto &DLoc = + getLocForDecl<RecordStorageLocation>(ASTCtx, EnvBefore, "D"); + + EXPECT_NE(getFieldValue(&BLoc, "base", ASTCtx, EnvBefore), + getFieldValue(&DLoc, "base", ASTCtx, EnvBefore)); + EXPECT_EQ(getFieldValue(&BLoc, "base", ASTCtx, EnvAfter), + getFieldValue(&DLoc, "base", ASTCtx, EnvAfter)); + + EXPECT_EQ(getFieldValue(&DLoc, "derived", ASTCtx, EnvBefore), + getFieldValue(&DLoc, "derived", ASTCtx, EnvAfter)); + }); } TEST(TransferTest, AssignmentOperatorFromCallResult) { @@ -2924,6 +2996,36 @@ TEST(TransferTest, ResultObjectLocation) { }); } +TEST(TransferTest, ResultObjectLocationForDefaultArgExpr) { + std::string Code = R"( + struct S {}; + void funcWithDefaultArg(S s = S()); + void target() { + funcWithDefaultArg(); + // [[p]] + } + )"; + + using ast_matchers::cxxDefaultArgExpr; + using ast_matchers::match; + using ast_matchers::selectFirst; + runDataflow( + Code, + [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, + ASTContext &ASTCtx) { + const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); + + auto *DefaultArg = selectFirst<CXXDefaultArgExpr>( + "default_arg", + match(cxxDefaultArgExpr().bind("default_arg"), ASTCtx)); + ASSERT_NE(DefaultArg, nullptr); + + // The values for default arguments aren't modeled; we merely verify + // that we can get a result object location for a default arg. + Env.getResultObjectLocation(*DefaultArg); + }); +} + TEST(TransferTest, ResultObjectLocationForDefaultInitExpr) { std::string Code = R"( struct S {}; @@ -4560,7 +4662,7 @@ TEST(TransferTest, LoopCanProveInvariantForBoolean) { } TEST(TransferTest, DoesNotCrashOnUnionThisExpr) { - std::string Code = R"( + std::string Code = R"cc( union Union { int A; float B; @@ -4571,7 +4673,7 @@ TEST(TransferTest, DoesNotCrashOnUnionThisExpr) { Union B; A = B; } - )"; + )cc"; // This is a crash regression test when calling the transfer function on a // `CXXThisExpr` that refers to a union. runDataflow( @@ -4581,6 +4683,22 @@ TEST(TransferTest, DoesNotCrashOnUnionThisExpr) { LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator="); } +TEST(TransferTest, DoesNotCrashOnNullChildren) { + std::string Code = (CoroutineLibrary + R"cc( + task target() noexcept { + co_return; + } + )cc") + .str(); + // This is a crash regression test when calling `AdornedCFG::build` on a + // statement (in this case, the `CoroutineBodyStmt`) with null children. + runDataflow( + Code, + [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &, + ASTContext &) {}, + LangStandard::lang_cxx20, /*ApplyBuiltinTransfer=*/true); +} + TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) { std::string Code = R"( struct A { diff --git a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp index 9d05a0d6ca4010bc3d34fcf56663328b0441c338..bea00ab1a1f0622be7e91e26d6dd605baf1e78ef 100644 --- a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp @@ -66,20 +66,20 @@ protected: AST->getASTContext())); assert(Func != nullptr); - CFCtx = std::make_unique<ControlFlowContext>( - llvm::cantFail(ControlFlowContext::build(*Func))); + ACFG = + std::make_unique<AdornedCFG>(llvm::cantFail(AdornedCFG::build(*Func))); AnalysisT Analysis = MakeAnalysis(AST->getASTContext()); DACtx = std::make_unique<DataflowAnalysisContext>( std::make_unique<WatchedLiteralsSolver>()); Environment Env(*DACtx, *Func); - return runDataflowAnalysis(*CFCtx, Analysis, Env); + return runDataflowAnalysis(*ACFG, Analysis, Env); } /// Returns the `CFGBlock` containing `S` (and asserts that it exists). const CFGBlock *blockForStmt(const Stmt &S) { - const CFGBlock *Block = CFCtx->getStmtToBlock().lookup(&S); + const CFGBlock *Block = ACFG->getStmtToBlock().lookup(&S); assert(Block != nullptr); return Block; } @@ -105,7 +105,7 @@ protected: } std::unique_ptr<ASTUnit> AST; - std::unique_ptr<ControlFlowContext> CFCtx; + std::unique_ptr<AdornedCFG> ACFG; std::unique_ptr<DataflowAnalysisContext> DACtx; }; diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp index b6e4973fd7cb2b1a524c84e4d6043a2e96a96e60..f16472ef17141cfea492cf2b302bf8b2e9c37c83 100644 --- a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp @@ -2798,6 +2798,59 @@ TEST_P(UncheckedOptionalAccessTest, OptionalValueOptional) { )"); } +TEST_P(UncheckedOptionalAccessTest, NestedOptionalAssignValue) { + ExpectDiagnosticsFor( + R"( + #include "unchecked_optional_access_test.h" + + using OptionalInt = $ns::$optional<int>; + + void target($ns::$optional<OptionalInt> opt) { + if (!opt) return; + + // Accessing the outer optional is OK now. + *opt; + + // But accessing the nested optional is still unsafe because we haven't + // checked it. + **opt; // [[unsafe]] + + *opt = 1; + + // Accessing the nested optional is safe after assigning a value to it. + **opt; + } + )"); +} + +TEST_P(UncheckedOptionalAccessTest, NestedOptionalAssignOptional) { + ExpectDiagnosticsFor( + R"( + #include "unchecked_optional_access_test.h" + + using OptionalInt = $ns::$optional<int>; + + void target($ns::$optional<OptionalInt> opt) { + if (!opt) return; + + // Accessing the outer optional is OK now. + *opt; + + // But accessing the nested optional is still unsafe because we haven't + // checked it. + **opt; // [[unsafe]] + + // Assign from `optional<short>` so that we trigger conversion assignment + // instead of move assignment. + *opt = $ns::$optional<short>(); + + // Accessing the nested optional is still unsafe after assigning an empty + // optional to it. + **opt; // [[unsafe]] + } + )"); +} + // Tests that structs can be nested. We use an optional field because its easy // to use in a test, but the type of the field shouldn't matter. TEST_P(UncheckedOptionalAccessTest, OptionalValueStruct) { @@ -3383,6 +3436,82 @@ TEST_P(UncheckedOptionalAccessTest, LambdaCaptureStateNotPropagated) { } )"); } + +TEST_P(UncheckedOptionalAccessTest, ClassDerivedFromOptional) { + ExpectDiagnosticsFor(R"( + #include "unchecked_optional_access_test.h" + + struct Derived : public $ns::$optional<int> {}; + + void target(Derived opt) { + *opt; // [[unsafe]] + if (opt.has_value()) + *opt; + + // The same thing, but with a pointer receiver. + Derived *popt = &opt; + **popt; // [[unsafe]] + if (popt->has_value()) + **popt; + } + )"); +} + +TEST_P(UncheckedOptionalAccessTest, ClassTemplateDerivedFromOptional) { + ExpectDiagnosticsFor(R"( + #include "unchecked_optional_access_test.h" + + template <class T> + struct Derived : public $ns::$optional<T> {}; + + void target(Derived<int> opt) { + *opt; // [[unsafe]] + if (opt.has_value()) + *opt; + + // The same thing, but with a pointer receiver. + Derived<int> *popt = &opt; + **popt; // [[unsafe]] + if (popt->has_value()) + **popt; + } + )"); +} + +TEST_P(UncheckedOptionalAccessTest, ClassDerivedPrivatelyFromOptional) { + // Classes that derive privately from optional can themselves still call + // member functions of optional. Check that we model the optional correctly + // in this situation. + ExpectDiagnosticsFor(R"( + #include "unchecked_optional_access_test.h" + + struct Derived : private $ns::$optional<int> { + void Method() { + **this; // [[unsafe]] + if (this->has_value()) + **this; + } + }; + )", + ast_matchers::hasName("Method")); +} + +TEST_P(UncheckedOptionalAccessTest, ClassDerivedFromOptionalValueConstructor) { + ExpectDiagnosticsFor(R"( + #include "unchecked_optional_access_test.h" + + struct Derived : public $ns::$optional<int> { + Derived(int); + }; + + void target(Derived opt) { + *opt; // [[unsafe]] + opt = 1; + *opt; + } + )"); +} + // FIXME: Add support for: // - constructors (copy, move) // - assignment operators (default, copy, move) diff --git a/clang/unittests/Format/.clang-format b/clang/unittests/Format/.clang-format index f95602cab0f7fcdf5d34c485d52b65993dbb83d9..d7331b3c8cf02ef7944e83a4280476627e33b31d 100644 --- a/clang/unittests/Format/.clang-format +++ b/clang/unittests/Format/.clang-format @@ -1,6 +1 @@ -BasedOnStyle: LLVM -InsertBraces: true -InsertNewlineAtEOF: true -LineEnding: LF -RemoveBracesLLVM: true -RemoveParentheses: ReturnStatement +BasedOnStyle: clang-format diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index fc367a7a5a8981d99426bf9f29209170e57ff944..ec0267da468ab2a513398d4e86ce80bc0bcf0423 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -3621,8 +3621,8 @@ TEST_F(FormatTest, FormatsClasses) { " : public aaaaaaaaaaaaaaaaaaa<aaaaaaaaaaaaaaaaaaaaa,\n" " aaaaaaaaaaaaaaaaaaaaaa> {};"); verifyFormat("template <class R, class C>\n" - "struct Aaaaaaaaaaaaaaaaa<R (C::*)(int) const>\n" - " : Aaaaaaaaaaaaaaaaa<R (C::*)(int)> {};"); + "struct Aaaaaaaaaaaaaaaaa<R (C:: *)(int) const>\n" + " : Aaaaaaaaaaaaaaaaa<R (C:: *)(int)> {};"); verifyFormat("class ::A::B {};"); } @@ -3802,6 +3802,27 @@ TEST_F(FormatTest, FormatsEnum) { " // Comment 2\n" " TWO,\n" "};"); + verifyFormat("enum [[clang::enum_extensibility(open)]] E {\n" + " // Comment 1\n" + " ONE,\n" + " // Comment 2\n" + " TWO\n" + "};"); + verifyFormat("enum [[nodiscard]] [[clang::enum_extensibility(open)]] E {\n" + " // Comment 1\n" + " ONE,\n" + " // Comment 2\n" + " TWO\n" + "};"); + verifyFormat("enum [[clang::enum_extensibility(open)]] E { // foo\n" + " A,\n" + " // bar\n" + " B\n" + "};", + "enum [[clang::enum_extensibility(open)]] E{// foo\n" + " A,\n" + " // bar\n" + " B};"); // Not enums. verifyFormat("enum X f() {\n" @@ -6938,6 +6959,10 @@ TEST_F(FormatTest, PutEmptyBlocksIntoOneLine) { "else if (b) { }\n" "else { }", Style); + + Style = getLLVMStyle(FormatStyle::LK_CSharp); + Style.SpaceInEmptyBlock = true; + verifyFormat("Event += () => { };", Style); } TEST_F(FormatTest, FormatBeginBlockEndMacros) { @@ -7951,6 +7976,43 @@ TEST_F(FormatTest, AllowAllArgumentsOnNextLineDontAlign) { Input, Style); } +TEST_F(FormatTest, BreakFunctionDefinitionParameters) { + FormatStyle Style = getLLVMStyle(); + EXPECT_FALSE(Style.BreakFunctionDefinitionParameters); + StringRef Input = "void functionDecl(paramA, paramB, paramC);\n" + "void emptyFunctionDefinition() {}\n" + "void functionDefinition(int A, int B, int C) {}\n" + "Class::Class(int A, int B) : m_A(A), m_B(B) {}\n"; + verifyFormat(StringRef("void functionDecl(paramA, paramB, paramC);\n" + "void emptyFunctionDefinition() {}\n" + "void functionDefinition(int A, int B, int C) {}\n" + "Class::Class(int A, int B) : m_A(A), m_B(B) {}\n"), + Input, Style); + Style.BreakFunctionDefinitionParameters = true; + verifyFormat(StringRef("void functionDecl(paramA, paramB, paramC);\n" + "void emptyFunctionDefinition() {}\n" + "void functionDefinition(\n" + " int A, int B, int C) {}\n" + "Class::Class(\n" + " int A, int B)\n" + " : m_A(A), m_B(B) {}\n"), + Input, Style); + // Test the style where all parameters are on their own lines + Style.AllowAllParametersOfDeclarationOnNextLine = false; + Style.BinPackParameters = false; + verifyFormat(StringRef("void functionDecl(paramA, paramB, paramC);\n" + "void emptyFunctionDefinition() {}\n" + "void functionDefinition(\n" + " int A,\n" + " int B,\n" + " int C) {}\n" + "Class::Class(\n" + " int A,\n" + " int B)\n" + " : m_A(A), m_B(B) {}\n"), + Input, Style); +} + TEST_F(FormatTest, BreakBeforeInlineASMColon) { FormatStyle Style = getLLVMStyle(); Style.BreakBeforeInlineASMColon = FormatStyle::BBIAS_Never; @@ -11009,10 +11071,10 @@ TEST_F(FormatTest, UnderstandsBinaryOperators) { } TEST_F(FormatTest, UnderstandsPointersToMembers) { - verifyFormat("int A::*x;"); - verifyFormat("int (S::*func)(void *);"); - verifyFormat("void f() { int (S::*func)(void *); }"); - verifyFormat("typedef bool *(Class::*Member)() const;"); + verifyFormat("int A:: *x;"); + verifyFormat("int (S:: *func)(void *);"); + verifyFormat("void f() { int (S:: *func)(void *); }"); + verifyFormat("typedef bool *(Class:: *Member)() const;"); verifyFormat("void f() {\n" " (a->*f)();\n" " a->*x;\n" @@ -11027,9 +11089,19 @@ TEST_F(FormatTest, UnderstandsPointersToMembers) { verifyFormat( "(aaaaaaaaaa->*bbbbbbb)(\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaa));"); + FormatStyle Style = getLLVMStyle(); + EXPECT_EQ(Style.PointerAlignment, FormatStyle::PAS_Right); + verifyFormat("typedef bool *(Class:: *Member)() const;", Style); + verifyFormat("void f(int A:: *p) { int A:: *v = &A::B; }", Style); + Style.PointerAlignment = FormatStyle::PAS_Left; - verifyFormat("typedef bool* (Class::*Member)() const;", Style); + verifyFormat("typedef bool* (Class::* Member)() const;", Style); + verifyFormat("void f(int A::* p) { int A::* v = &A::B; }", Style); + + Style.PointerAlignment = FormatStyle::PAS_Middle; + verifyFormat("typedef bool * (Class:: * Member)() const;", Style); + verifyFormat("void f(int A:: * p) { int A:: * v = &A::B; }", Style); } TEST_F(FormatTest, UnderstandsUnaryOperators) { @@ -11450,6 +11522,11 @@ TEST_F(FormatTest, UnderstandsNewAndDelete) { "void new (link p);\n" "void delete (link p);"); + verifyFormat("{ p->new(); }\n" + "{ p->delete(); }", + "{ p->new (); }\n" + "{ p->delete (); }"); + FormatStyle AfterPlacementOperator = getLLVMStyle(); AfterPlacementOperator.SpaceBeforeParens = FormatStyle::SBPO_Custom; EXPECT_TRUE( @@ -12035,6 +12112,7 @@ TEST_F(FormatTest, UnderstandsSquareAttributes) { verifyFormat("SomeType s [[gnu::unused]] (InitValue);"); verifyFormat("SomeType s [[using gnu: unused]] (InitValue);"); verifyFormat("[[gsl::suppress(\"clang-tidy-check-name\")]] void f() {}"); + verifyFormat("[[suppress(type.5)]] int uninitialized_on_purpose;"); verifyFormat("void f() [[deprecated(\"so sorry\")]];"); verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" " [[unused]] aaaaaaaaaaaaaaaaaaaaaaa(int i);"); @@ -12356,7 +12434,7 @@ TEST_F(FormatTest, FormatsFunctionTypes) { verifyFormat("int (*func)(void *);"); verifyFormat("void f() { int (*func)(void *); }"); verifyFormat("template <class CallbackClass>\n" - "using MyCallback = void (CallbackClass::*)(SomeObject *Data);"); + "using Callback = void (CallbackClass:: *)(SomeObject *Data);"); verifyGoogleFormat("A<void*(int*, SomeType*)>;"); verifyGoogleFormat("void* (*a)(int);"); @@ -19026,6 +19104,11 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) { verifyFormat("int a(int x);\n" "double b();", Alignment); + verifyFormat("int a(const Test & = Test());\n" + "int a1(int &foo, const Test & = Test());\n" + "int a2(int &foo, const Test &name = Test());\n" + "double b();", + Alignment); verifyFormat("struct Test {\n" " Test(const Test &) = default;\n" " ~Test() = default;\n" @@ -19062,6 +19145,13 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) { " int x,\n" " bool y);", Alignment); + // Set ColumnLimit low so that we break the argument list in multiple lines. + Alignment.ColumnLimit = 35; + verifyFormat("int a3(SomeTypeName1 &x,\n" + " SomeTypeName2 &y,\n" + " const Test & = Test());\n" + "double b();", + Alignment); Alignment.ColumnLimit = OldColumnLimit; // Ensure function pointers don't screw up recursive alignment verifyFormat("int a(int x, void (*fp)(int y));\n" @@ -19119,13 +19209,13 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) { "int bbbbbbb = 0;", Alignment); // http://llvm.org/PR68079 - verifyFormat("using Fn = int (A::*)();\n" - "using RFn = int (A::*)() &;\n" - "using RRFn = int (A::*)() &&;", + verifyFormat("using Fn = int (A:: *)();\n" + "using RFn = int (A:: *)() &;\n" + "using RRFn = int (A:: *)() &&;", Alignment); - verifyFormat("using Fn = int (A::*)();\n" - "using RFn = int *(A::*)() &;\n" - "using RRFn = double (A::*)() &&;", + verifyFormat("using Fn = int (A:: *)();\n" + "using RFn = int *(A:: *)() &;\n" + "using RRFn = double (A:: *)() &&;", Alignment); // PAS_Right @@ -19247,6 +19337,10 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) { "int foobar;", AlignmentLeft); + verifyFormat("int a(SomeType& foo, const Test& = Test());\n" + "double b();", + AlignmentLeft); + // PAS_Middle FormatStyle AlignmentMiddle = Alignment; AlignmentMiddle.PointerAlignment = FormatStyle::PAS_Middle; @@ -19307,6 +19401,10 @@ TEST_F(FormatTest, AlignConsecutiveDeclarations) { "int foobar;", AlignmentMiddle); + verifyFormat("int a(SomeType & foo, const Test & = Test());\n" + "double b();", + AlignmentMiddle); + Alignment.AlignConsecutiveAssignments.Enabled = false; Alignment.AlignEscapedNewlines = FormatStyle::ENAS_DontAlign; verifyFormat("#define A \\\n" @@ -21060,7 +21158,14 @@ TEST_F(FormatTest, CatchAlignArrayOfStructuresRightAlignment) { " [0] = {1, 1},\n" " [1] { 1, 1, },\n" " [2] { 1, 1, },\n" - "};"); + "};", + Style); + verifyNoCrash("test arr[] = {\n" + "#define FOO(i) {i, i},\n" + "SOME_GENERATOR(FOO)\n" + "{2, 2}\n" + "};", + Style); verifyFormat("return GradForUnaryCwise(g, {\n" " {{\"sign\"}, \"Sign\", " @@ -21313,7 +21418,14 @@ TEST_F(FormatTest, CatchAlignArrayOfStructuresLeftAlignment) { " [0] = {1, 1},\n" " [1] { 1, 1, },\n" " [2] { 1, 1, },\n" - "};"); + "};", + Style); + verifyNoCrash("test arr[] = {\n" + "#define FOO(i) {i, i},\n" + "SOME_GENERATOR(FOO)\n" + "{2, 2}\n" + "};", + Style); verifyFormat("return GradForUnaryCwise(g, {\n" " {{\"sign\"}, \"Sign\", {\"x\", " diff --git a/clang/unittests/Format/FormatTestTableGen.cpp b/clang/unittests/Format/FormatTestTableGen.cpp index 76b871e2e1a522b332230423a6e496c798780ba7..8ca6bf97e5a6b1dbfefc03ebbba75fd0fccd60c3 100644 --- a/clang/unittests/Format/FormatTestTableGen.cpp +++ b/clang/unittests/Format/FormatTestTableGen.cpp @@ -332,6 +332,117 @@ TEST_F(FormatTestTableGen, Assert) { verifyFormat("assert !le(DefVar1, 0), \"Assert1\";\n"); } +TEST_F(FormatTestTableGen, DAGArgBreakElements) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen); + Style.ColumnLimit = 60; + // By default, the DAGArg does not have a break inside. + ASSERT_EQ(Style.TableGenBreakInsideDAGArg, FormatStyle::DAS_DontBreak); + verifyFormat("def Def : Parent {\n" + " let dagarg = (ins a:$src1, aa:$src2, aaa:$src3)\n" + "}\n", + Style); + // This option forces to break inside the DAGArg. + Style.TableGenBreakInsideDAGArg = FormatStyle::DAS_BreakElements; + verifyFormat("def Def : Parent {\n" + " let dagarg = (ins a:$src1,\n" + " aa:$src2,\n" + " aaa:$src3);\n" + "}\n", + Style); + verifyFormat("def Def : Parent {\n" + " let dagarg = (other a:$src1,\n" + " aa:$src2,\n" + " aaa:$src3);\n" + "}\n", + Style); + // Then, limit the DAGArg operator only to "ins". + Style.TableGenBreakingDAGArgOperators = {"ins"}; + verifyFormat("def Def : Parent {\n" + " let dagarg = (ins a:$src1,\n" + " aa:$src2,\n" + " aaa:$src3);\n" + "}\n", + Style); + verifyFormat("def Def : Parent {\n" + " let dagarg = (other a:$src1, aa:$src2, aaa:$src3)\n" + "}\n", + Style); +} + +TEST_F(FormatTestTableGen, DAGArgBreakAll) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen); + Style.ColumnLimit = 60; + // By default, the DAGArg does not have a break inside. + verifyFormat("def Def : Parent {\n" + " let dagarg = (ins a:$src1, aa:$src2, aaa:$src3)\n" + "}\n", + Style); + // This option forces to break inside the DAGArg. + Style.TableGenBreakInsideDAGArg = FormatStyle::DAS_BreakAll; + verifyFormat("def Def : Parent {\n" + " let dagarg = (ins\n" + " a:$src1,\n" + " aa:$src2,\n" + " aaa:$src3\n" + " );\n" + "}\n", + Style); + verifyFormat("def Def : Parent {\n" + " let dagarg = (other\n" + " a:$src1,\n" + " aa:$src2,\n" + " aaa:$src3\n" + " );\n" + "}\n", + Style); + // Then, limit the DAGArg operator only to "ins". + Style.TableGenBreakingDAGArgOperators = {"ins"}; + verifyFormat("def Def : Parent {\n" + " let dagarg = (ins\n" + " a:$src1,\n" + " aa:$src2,\n" + " aaa:$src3\n" + " );\n" + "}\n", + Style); + verifyFormat("def Def : Parent {\n" + " let dagarg = (other a:$src1, aa:$src2, aaa:$src3);\n" + "}\n", + Style); +} + +TEST_F(FormatTestTableGen, DAGArgAlignment) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen); + Style.ColumnLimit = 60; + Style.TableGenBreakInsideDAGArg = FormatStyle::DAS_BreakAll; + Style.TableGenBreakingDAGArgOperators = {"ins", "outs"}; + verifyFormat("def Def : Parent {\n" + " let dagarg = (ins\n" + " a:$src1,\n" + " aa:$src2,\n" + " aaa:$src3\n" + " )\n" + "}\n", + Style); + verifyFormat("def Def : Parent {\n" + " let dagarg = (not a:$src1, aa:$src2, aaa:$src2)\n" + "}\n", + Style); + Style.AlignConsecutiveTableGenBreakingDAGArgColons.Enabled = true; + verifyFormat("def Def : Parent {\n" + " let dagarg = (ins\n" + " a :$src1,\n" + " aa :$src2,\n" + " aaa:$src3\n" + " )\n" + "}\n", + Style); + verifyFormat("def Def : Parent {\n" + " let dagarg = (not a:$src1, aa:$src2, aaa:$src2)\n" + "}\n", + Style); +} + TEST_F(FormatTestTableGen, CondOperatorAlignment) { FormatStyle Style = getGoogleStyle(FormatStyle::LK_TableGen); Style.ColumnLimit = 60; diff --git a/clang/unittests/Format/QualifierFixerTest.cpp b/clang/unittests/Format/QualifierFixerTest.cpp index 43476aea66337b19afd2517b21db7189d7536455..792d8f3c3a98258b008b939271bef93475e81100 100644 --- a/clang/unittests/Format/QualifierFixerTest.cpp +++ b/clang/unittests/Format/QualifierFixerTest.cpp @@ -305,7 +305,7 @@ TEST_F(QualifierFixerTest, RightQualifier) { verifyFormat("Foo inline static const;", "Foo inline const static;", Style); verifyFormat("Foo inline static const;", Style); - verifyFormat("Foo<T volatile>::Bar<Type const, 5> const volatile A::*;", + verifyFormat("Foo<T volatile>::Bar<Type const, 5> const volatile A:: *;", "volatile const Foo<volatile T>::Bar<const Type, 5> A::*;", Style); @@ -523,14 +523,15 @@ TEST_F(QualifierFixerTest, RightQualifier) { verifyFormat("const INTPTR a;", Style); // Pointers to members - verifyFormat("int S::*a;", Style); - verifyFormat("int const S::*a;", "const int S:: *a;", Style); - verifyFormat("int const S::*const a;", "const int S::* const a;", Style); - verifyFormat("int A::*const A::*p1;", Style); - verifyFormat("float (C::*p)(int);", Style); - verifyFormat("float (C::*const p)(int);", Style); - verifyFormat("float (C::*p)(int) const;", Style); - verifyFormat("float const (C::*p)(int);", "const float (C::*p)(int);", Style); + verifyFormat("int S:: *a;", Style); + verifyFormat("int const S:: *a;", "const int S:: *a;", Style); + verifyFormat("int const S:: *const a;", "const int S::* const a;", Style); + verifyFormat("int A:: *const A:: *p1;", Style); + verifyFormat("float (C:: *p)(int);", Style); + verifyFormat("float (C:: *const p)(int);", Style); + verifyFormat("float (C:: *p)(int) const;", Style); + verifyFormat("float const (C:: *p)(int);", "const float (C::*p)(int);", + Style); } TEST_F(QualifierFixerTest, LeftQualifier) { @@ -830,14 +831,15 @@ TEST_F(QualifierFixerTest, LeftQualifier) { verifyFormat("INTPTR const a;", Style); // Pointers to members - verifyFormat("int S::*a;", Style); - verifyFormat("const int S::*a;", "int const S:: *a;", Style); - verifyFormat("const int S::*const a;", "int const S::* const a;", Style); - verifyFormat("int A::*const A::*p1;", Style); - verifyFormat("float (C::*p)(int);", Style); - verifyFormat("float (C::*const p)(int);", Style); - verifyFormat("float (C::*p)(int) const;", Style); - verifyFormat("const float (C::*p)(int);", "float const (C::*p)(int);", Style); + verifyFormat("int S:: *a;", Style); + verifyFormat("const int S:: *a;", "int const S:: *a;", Style); + verifyFormat("const int S:: *const a;", "int const S::* const a;", Style); + verifyFormat("int A:: *const A:: *p1;", Style); + verifyFormat("float (C:: *p)(int);", Style); + verifyFormat("float (C:: *const p)(int);", Style); + verifyFormat("float (C:: *p)(int) const;", Style); + verifyFormat("const float (C:: *p)(int);", "float const (C::*p)(int);", + Style); } TEST_F(QualifierFixerTest, ConstVolatileQualifiersOrder) { diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index fcba0e63c7825497a79b4d4ce810d8b2613c8af5..2539d3d76ef019eeff37aed1d633b98c81431b3f 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -2354,6 +2354,92 @@ TEST_F(TokenAnnotatorTest, UnderstandTableGenTokens) { EXPECT_TOKEN(Tokens[4], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[6], tok::greater, TT_TemplateCloser); EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_FunctionLBrace); + + // DAGArg breaking options. They use different token types depending on what + // is specified. + Style.TableGenBreakInsideDAGArg = FormatStyle::DAS_BreakElements; + + // When TableGenBreakInsideDAGArg is DAS_BreakElements and + // TableGenBreakingDAGArgOperators is not specified, it makes all the DAGArg + // elements to have line break. + Tokens = AnnotateValue("(ins type1:$src1, type2:$src2)"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::l_paren, TT_TableGenDAGArgOpenerToBreak); + EXPECT_TOKEN(Tokens[1], tok::identifier, + TT_TableGenDAGArgOperatorID); // ins + EXPECT_TOKEN(Tokens[5], tok::comma, TT_TableGenDAGArgListCommaToBreak); + EXPECT_TOKEN(Tokens[9], tok::r_paren, TT_TableGenDAGArgCloser); + + Tokens = AnnotateValue("(other type1:$src1, type2:$src2)"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::l_paren, TT_TableGenDAGArgOpenerToBreak); + EXPECT_TOKEN(Tokens[1], tok::identifier, + TT_TableGenDAGArgOperatorID); // other + EXPECT_TOKEN(Tokens[5], tok::comma, TT_TableGenDAGArgListCommaToBreak); + EXPECT_TOKEN(Tokens[9], tok::r_paren, TT_TableGenDAGArgCloser); + + // For non-identifier operators, breaks after the operator. + Tokens = AnnotateValue("(!cast<Type>(\"Name\") type1:$src1, type2:$src2)"); + ASSERT_EQ(Tokens.size(), 16u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::l_paren, TT_TableGenDAGArgOpenerToBreak); + EXPECT_TOKEN(Tokens[7], tok::r_paren, TT_TableGenDAGArgOperatorToBreak); + EXPECT_TOKEN(Tokens[11], tok::comma, TT_TableGenDAGArgListCommaToBreak); + EXPECT_TOKEN(Tokens[15], tok::r_paren, TT_TableGenDAGArgCloser); + + Style.TableGenBreakInsideDAGArg = FormatStyle::DAS_BreakAll; + + // When TableGenBreakInsideDAGArg is DAS_BreakAll and + // TableGenBreakingDAGArgOperators is not specified, it makes all the DAGArg + // to have line break inside it. + Tokens = AnnotateValue("(ins type1:$src1, type2:$src2)"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::l_paren, TT_TableGenDAGArgOpenerToBreak); + EXPECT_TOKEN(Tokens[1], tok::identifier, + TT_TableGenDAGArgOperatorToBreak); // ins + EXPECT_TOKEN(Tokens[5], tok::comma, TT_TableGenDAGArgListCommaToBreak); + EXPECT_TOKEN(Tokens[9], tok::r_paren, TT_TableGenDAGArgCloser); + + Tokens = AnnotateValue("(other type1:$src1, type2:$src2)"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::l_paren, TT_TableGenDAGArgOpenerToBreak); + EXPECT_TOKEN(Tokens[1], tok::identifier, + TT_TableGenDAGArgOperatorToBreak); // other + EXPECT_TOKEN(Tokens[5], tok::comma, TT_TableGenDAGArgListCommaToBreak); + EXPECT_TOKEN(Tokens[9], tok::r_paren, TT_TableGenDAGArgCloser); + + // If TableGenBreakingDAGArgOperators is specified, it is limited to the + // specified operators. + Style.TableGenBreakingDAGArgOperators = {"ins", "outs"}; + Tokens = AnnotateValue("(ins type1:$src1, type2:$src2)"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::l_paren, TT_TableGenDAGArgOpenerToBreak); + EXPECT_TOKEN(Tokens[1], tok::identifier, + TT_TableGenDAGArgOperatorToBreak); // ins + EXPECT_TOKEN(Tokens[5], tok::comma, TT_TableGenDAGArgListCommaToBreak); + EXPECT_TOKEN(Tokens[9], tok::r_paren, TT_TableGenDAGArgCloser); + + Tokens = AnnotateValue("(other type1:$src1, type2:$src2)"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::l_paren, TT_TableGenDAGArgOpener); + EXPECT_TOKEN(Tokens[1], tok::identifier, TT_Unknown); // other + EXPECT_TOKEN(Tokens[5], tok::comma, TT_TableGenDAGArgListComma); + EXPECT_TOKEN(Tokens[9], tok::r_paren, TT_TableGenDAGArgCloser); + + // If TableGenBreakingDAGArgOperators is enabled, it uses + // TT_TableGenDAGArgListColonToAlign to annotate the colon to align. + Style.AlignConsecutiveTableGenBreakingDAGArgColons.Enabled = true; + Tokens = AnnotateValue("(ins type1:$src1, type2:$src2)"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[1], tok::identifier, + TT_TableGenDAGArgOperatorToBreak); // ins + EXPECT_TOKEN(Tokens[3], tok::colon, TT_TableGenDAGArgListColonToAlign); + EXPECT_TOKEN(Tokens[7], tok::colon, TT_TableGenDAGArgListColonToAlign); + + Tokens = AnnotateValue("(other type1:$src1, type2:$src2)"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[1], tok::identifier, TT_Unknown); // other + EXPECT_TOKEN(Tokens[3], tok::colon, TT_TableGenDAGArgListColon); + EXPECT_TOKEN(Tokens[7], tok::colon, TT_TableGenDAGArgListColon); } TEST_F(TokenAnnotatorTest, UnderstandConstructors) { @@ -2632,6 +2718,11 @@ TEST_F(TokenAnnotatorTest, StartOfName) { EXPECT_TOKEN(Tokens[2], tok::identifier, TT_Unknown); EXPECT_TOKEN(Tokens[3], tok::identifier, TT_Unknown); EXPECT_TOKEN(Tokens[4], tok::identifier, TT_StartOfName); + + Tokens = annotate("@interface NSCoder (TestCoder)"); + ASSERT_EQ(Tokens.size(), 7u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::at, TT_ObjCDecl); + EXPECT_TOKEN(Tokens[2], tok::identifier, TT_StartOfName); } TEST_F(TokenAnnotatorTest, BraceKind) { diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt index b56e1e21015db91a85e6aa8a0a51b604eb057327..e5a77e77de75cdbafd99f878e0dbdd51f1e3e391 100644 --- a/clang/unittests/Interpreter/CMakeLists.txt +++ b/clang/unittests/Interpreter/CMakeLists.txt @@ -1,6 +1,7 @@ set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} Core + MC OrcJIT Support TargetParser diff --git a/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp b/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp index 77fd1b4e19816c66395773203de7b99b74094c21..1ba865a79ed778cf161383e43a47112536a90ccd 100644 --- a/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp +++ b/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp @@ -18,14 +18,22 @@ #include "clang/Sema/Sema.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" +#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Support/Error.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Support/Threading.h" #include "llvm/Testing/Support/Error.h" #include "gmock/gmock.h" #include "gtest/gtest.h" + #include <system_error> +#if defined(_AIX) +#define CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT +#endif + using namespace clang; namespace { @@ -37,10 +45,23 @@ static bool HostSupportsJit() { return false; } +// Some tests require a arm-registered-target +static bool IsARMTargetRegistered() { + llvm::Triple TT; + TT.setArch(llvm::Triple::arm); + TT.setVendor(llvm::Triple::UnknownVendor); + TT.setOS(llvm::Triple::UnknownOS); + + std::string UnusedErr; + return llvm::TargetRegistry::lookupTarget(TT.str(), UnusedErr); +} + struct LLVMInitRAII { LLVMInitRAII() { - llvm::InitializeNativeTarget(); - llvm::InitializeNativeTargetAsmPrinter(); + llvm::InitializeAllTargets(); + llvm::InitializeAllTargetInfos(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllAsmPrinters(); } ~LLVMInitRAII() { llvm::llvm_shutdown(); } } LLVMInit; @@ -51,12 +72,34 @@ public: llvm::Error &Err) : Interpreter(std::move(CI), Err) {} - llvm::Error testCreateExecutor() { return Interpreter::CreateExecutor(); } + llvm::Error testCreateJITBuilderError() { + JB = nullptr; + return Interpreter::CreateExecutor(); + } + + llvm::Error testCreateExecutor() { + JB = std::make_unique<llvm::orc::LLJITBuilder>(); + return Interpreter::CreateExecutor(); + } void resetExecutor() { Interpreter::ResetExecutor(); } + +private: + llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> + CreateJITBuilder(CompilerInstance &CI) override { + if (JB) + return std::move(JB); + return llvm::make_error<llvm::StringError>("TestError", std::error_code()); + } + + std::unique_ptr<llvm::orc::LLJITBuilder> JB; }; +#ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT +TEST(InterpreterExtensionsTest, DISABLED_ExecutorCreateReset) { +#else TEST(InterpreterExtensionsTest, ExecutorCreateReset) { +#endif // Make sure we can create the executer on the platform. if (!HostSupportsJit()) GTEST_SKIP(); @@ -65,6 +108,8 @@ TEST(InterpreterExtensionsTest, ExecutorCreateReset) { llvm::Error ErrOut = llvm::Error::success(); TestCreateResetExecutor Interp(cantFail(CB.CreateCpp()), ErrOut); cantFail(std::move(ErrOut)); + EXPECT_THAT_ERROR(Interp.testCreateJITBuilderError(), + llvm::FailedWithMessage("TestError")); cantFail(Interp.testCreateExecutor()); Interp.resetExecutor(); cantFail(Interp.testCreateExecutor()); @@ -122,4 +167,96 @@ TEST(InterpreterExtensionsTest, FindRuntimeInterface) { EXPECT_EQ(1U, Interp.RuntimeIBPtr->TransformerQueries); } +class CustomJBInterpreter : public Interpreter { + using CustomJITBuilderCreatorFunction = + std::function<llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>()>; + CustomJITBuilderCreatorFunction JBCreator = nullptr; + +public: + CustomJBInterpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &ErrOut) + : Interpreter(std::move(CI), ErrOut) {} + + ~CustomJBInterpreter() override { + // Skip cleanUp() because it would trigger LLJIT default dtors + Interpreter::ResetExecutor(); + } + + void setCustomJITBuilderCreator(CustomJITBuilderCreatorFunction Fn) { + JBCreator = std::move(Fn); + } + + llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>> + CreateJITBuilder(CompilerInstance &CI) override { + if (JBCreator) + return JBCreator(); + return Interpreter::CreateJITBuilder(CI); + } + + llvm::Error CreateExecutor() { return Interpreter::CreateExecutor(); } +}; + +#ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT +TEST(InterpreterExtensionsTest, DISABLED_DefaultCrossJIT) { +#else +TEST(InterpreterExtensionsTest, DefaultCrossJIT) { +#endif + if (!IsARMTargetRegistered()) + GTEST_SKIP(); + + IncrementalCompilerBuilder CB; + CB.SetTargetTriple("armv6-none-eabi"); + auto CI = cantFail(CB.CreateCpp()); + llvm::Error ErrOut = llvm::Error::success(); + CustomJBInterpreter Interp(std::move(CI), ErrOut); + cantFail(std::move(ErrOut)); + cantFail(Interp.CreateExecutor()); +} + +#ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT +TEST(InterpreterExtensionsTest, DISABLED_CustomCrossJIT) { +#else +TEST(InterpreterExtensionsTest, CustomCrossJIT) { +#endif + if (!IsARMTargetRegistered()) + GTEST_SKIP(); + + std::string TargetTriple = "armv6-none-eabi"; + + IncrementalCompilerBuilder CB; + CB.SetTargetTriple(TargetTriple); + auto CI = cantFail(CB.CreateCpp()); + llvm::Error ErrOut = llvm::Error::success(); + CustomJBInterpreter Interp(std::move(CI), ErrOut); + cantFail(std::move(ErrOut)); + + using namespace llvm::orc; + LLJIT *JIT = nullptr; + std::vector<std::unique_ptr<llvm::MemoryBuffer>> Objs; + Interp.setCustomJITBuilderCreator([&]() { + auto JTMB = JITTargetMachineBuilder(llvm::Triple(TargetTriple)); + JTMB.setCPU("cortex-m0plus"); + auto JB = std::make_unique<LLJITBuilder>(); + JB->setJITTargetMachineBuilder(JTMB); + JB->setPlatformSetUp(setUpInactivePlatform); + JB->setNotifyCreatedCallback([&](LLJIT &J) { + ObjectLayer &ObjLayer = J.getObjLinkingLayer(); + auto *JITLinkObjLayer = llvm::dyn_cast<ObjectLinkingLayer>(&ObjLayer); + JITLinkObjLayer->setReturnObjectBuffer( + [&Objs](std::unique_ptr<llvm::MemoryBuffer> MB) { + Objs.push_back(std::move(MB)); + }); + JIT = &J; + return llvm::Error::success(); + }); + return JB; + }); + + EXPECT_EQ(0U, Objs.size()); + cantFail(Interp.CreateExecutor()); + cantFail(Interp.ParseAndExecute("int a = 1;")); + ExecutorAddr Addr = cantFail(JIT->lookup("a")); + EXPECT_NE(0U, Addr.getValue()); + EXPECT_EQ(1U, Objs.size()); +} + } // end anonymous namespace diff --git a/clang/unittests/Interpreter/InterpreterTest.cpp b/clang/unittests/Interpreter/InterpreterTest.cpp index e76c0677db5ead160c35376f8c357221d26037cf..69bc2da242884e81c5e37db640b81c77b59cd69c 100644 --- a/clang/unittests/Interpreter/InterpreterTest.cpp +++ b/clang/unittests/Interpreter/InterpreterTest.cpp @@ -340,6 +340,12 @@ TEST(InterpreterTest, Value) { EXPECT_EQ(V1.getKind(), Value::K_Int); EXPECT_FALSE(V1.isManuallyAlloc()); + Value V1b; + llvm::cantFail(Interp->ParseAndExecute("char c = 42;")); + llvm::cantFail(Interp->ParseAndExecute("c", &V1b)); + EXPECT_TRUE(V1b.getKind() == Value::K_Char_S || + V1b.getKind() == Value::K_Char_U); + Value V2; llvm::cantFail(Interp->ParseAndExecute("double y = 3.14;")); llvm::cantFail(Interp->ParseAndExecute("y", &V2)); diff --git a/clang/unittests/Lex/PPDependencyDirectivesTest.cpp b/clang/unittests/Lex/PPDependencyDirectivesTest.cpp index 6ff87f720a559fd6276fd79eb3a2414efbed5cda..0c396720ece66d552436f15a311533f4764cd317 100644 --- a/clang/unittests/Lex/PPDependencyDirectivesTest.cpp +++ b/clang/unittests/Lex/PPDependencyDirectivesTest.cpp @@ -117,11 +117,6 @@ TEST_F(PPDependencyDirectivesTest, MacroGuard) { }; auto PPOpts = std::make_shared<PreprocessorOptions>(); - PPOpts->DependencyDirectivesForFile = [&](FileEntryRef File) - -> std::optional<ArrayRef<dependency_directives_scan::Directive>> { - return getDependencyDirectives(File); - }; - TrivialModuleLoader ModLoader; HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr, Diags, LangOpts, Target.get()); @@ -130,6 +125,12 @@ TEST_F(PPDependencyDirectivesTest, MacroGuard) { /*OwnsHeaderSearch =*/false); PP.Initialize(*Target); + PP.setDependencyDirectivesFn( + [&](FileEntryRef File) + -> std::optional<ArrayRef<dependency_directives_scan::Directive>> { + return getDependencyDirectives(File); + }); + SmallVector<StringRef> IncludedFiles; PP.addPPCallbacks(std::make_unique<IncludeCollector>(PP, IncludedFiles)); PP.EnterMainSourceFile(); diff --git a/clang/unittests/StaticAnalyzer/CMakeLists.txt b/clang/unittests/StaticAnalyzer/CMakeLists.txt index 775f0f8486b8f9f78fa87fe8c852f75234a1ecbb..ff34d5747cc81b31aa891576a523ea5edecfa21e 100644 --- a/clang/unittests/StaticAnalyzer/CMakeLists.txt +++ b/clang/unittests/StaticAnalyzer/CMakeLists.txt @@ -11,6 +11,8 @@ add_clang_unittest(StaticAnalysisTests CallEventTest.cpp ConflictingEvalCallsTest.cpp FalsePositiveRefutationBRVisitorTest.cpp + IsCLibraryFunctionTest.cpp + MemRegionDescriptiveNameTest.cpp NoStateChangeFuncVisitorTest.cpp ParamRegionTest.cpp RangeSetTest.cpp diff --git a/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp b/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d6dfcaac6f3bdc41bd97f7f23af81a6f70bba45f --- /dev/null +++ b/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp @@ -0,0 +1,84 @@ +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/Frontend/ASTUnit.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/Tooling/Tooling.h" +#include "gtest/gtest.h" + +#include <memory> + +using namespace clang; +using namespace ento; +using namespace ast_matchers; + +class IsCLibraryFunctionTest : public testing::Test { + std::unique_ptr<ASTUnit> ASTUnitP; + const FunctionDecl *Result = nullptr; + +public: + const FunctionDecl *getFunctionDecl() const { return Result; } + + testing::AssertionResult buildAST(StringRef Code) { + ASTUnitP = tooling::buildASTFromCode(Code); + if (!ASTUnitP) + return testing::AssertionFailure() << "AST construction failed"; + + ASTContext &Context = ASTUnitP->getASTContext(); + if (Context.getDiagnostics().hasErrorOccurred()) + return testing::AssertionFailure() << "Compilation error"; + + auto Matches = ast_matchers::match(functionDecl().bind("fn"), Context); + if (Matches.empty()) + return testing::AssertionFailure() << "No function declaration found"; + + if (Matches.size() > 1) + return testing::AssertionFailure() + << "Multiple function declarations found"; + + Result = Matches[0].getNodeAs<FunctionDecl>("fn"); + return testing::AssertionSuccess(); + } +}; + +TEST_F(IsCLibraryFunctionTest, AcceptsGlobal) { + ASSERT_TRUE(buildAST(R"cpp(void fun();)cpp")); + EXPECT_TRUE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, AcceptsExternCGlobal) { + ASSERT_TRUE(buildAST(R"cpp(extern "C" { void fun(); })cpp")); + EXPECT_TRUE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, RejectsNoInlineNoExternalLinkage) { + // Functions that are neither inlined nor externally visible cannot be C + // library functions. + ASSERT_TRUE(buildAST(R"cpp(static void fun();)cpp")); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, RejectsAnonymousNamespace) { + ASSERT_TRUE(buildAST(R"cpp(namespace { void fun(); })cpp")); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, AcceptsStdNamespace) { + ASSERT_TRUE(buildAST(R"cpp(namespace std { void fun(); })cpp")); + EXPECT_TRUE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, RejectsOtherNamespaces) { + ASSERT_TRUE(buildAST(R"cpp(namespace stdx { void fun(); })cpp")); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, RejectsClassStatic) { + ASSERT_TRUE(buildAST(R"cpp(class A { static void fun(); };)cpp")); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} + +TEST_F(IsCLibraryFunctionTest, RejectsClassMember) { + ASSERT_TRUE(buildAST(R"cpp(class A { void fun(); };)cpp")); + EXPECT_FALSE(CheckerContext::isCLibraryFunction(getFunctionDecl())); +} diff --git a/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ba0c4d25e13b4d0fa2b52432eb1b28968ddd7cb4 --- /dev/null +++ b/clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp @@ -0,0 +1,145 @@ +//===- MemRegionDescriptiveNameTest.cpp -----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CheckerRegistration.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" +#include "gtest/gtest.h" +#include <fstream> + +using namespace clang; +using namespace ento; + +namespace { + +class DescriptiveNameChecker : public Checker<check::PreCall> { +public: + void checkPreCall(const CallEvent &Call, CheckerContext &C) const { + if (!HandlerFn.matches(Call)) + return; + + const MemRegion *ArgReg = Call.getArgSVal(0).getAsRegion(); + assert(ArgReg && "expecting a location as the first argument"); + + auto DescriptiveName = ArgReg->getDescriptiveName(/*UseQuotes=*/false); + if (ExplodedNode *Node = C.generateNonFatalErrorNode(C.getState())) { + auto Report = + std::make_unique<PathSensitiveBugReport>(Bug, DescriptiveName, Node); + C.emitReport(std::move(Report)); + } + } + +private: + const BugType Bug{this, "DescriptiveNameBug"}; + const CallDescription HandlerFn = {{"reportDescriptiveName"}, 1}; +}; + +void addDescriptiveNameChecker(AnalysisASTConsumer &AnalysisConsumer, + AnalyzerOptions &AnOpts) { + AnOpts.CheckersAndPackages = {{"DescriptiveNameChecker", true}}; + AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { + Registry.addChecker<DescriptiveNameChecker>("DescriptiveNameChecker", + "Desc", "DocsURI"); + }); +} + +bool runChecker(StringRef Code, std::string &Output) { + return runCheckerOnCode<addDescriptiveNameChecker>(Code.str(), Output, + /*OnlyEmitWarnings=*/true); +} + +TEST(MemRegionDescriptiveNameTest, ConcreteIntElementRegionIndex) { + StringRef Code = R"cpp( +void reportDescriptiveName(int *p); +const unsigned int index = 1; +extern int array[3]; +void top() { + reportDescriptiveName(&array[index]); +})cpp"; + + std::string Output; + ASSERT_TRUE(runChecker(Code, Output)); + EXPECT_EQ(Output, "DescriptiveNameChecker: array[1]\n"); +} + +TEST(MemRegionDescriptiveNameTest, SymbolicElementRegionIndex) { + StringRef Code = R"cpp( +void reportDescriptiveName(int *p); +extern unsigned int index; +extern int array[3]; +void top() { + reportDescriptiveName(&array[index]); +})cpp"; + + std::string Output; + ASSERT_TRUE(runChecker(Code, Output)); + EXPECT_EQ(Output, "DescriptiveNameChecker: array[index]\n"); +} + +TEST(MemRegionDescriptiveNameTest, SymbolicElementRegionIndexSymbolValFails) { + StringRef Code = R"cpp( +void reportDescriptiveName(int *p); +extern int* ptr; +extern int array[3]; +void top() { + reportDescriptiveName(&array[(long)ptr]); +})cpp"; + + std::string Output; + ASSERT_TRUE(runChecker(Code, Output)); + EXPECT_EQ(Output, "DescriptiveNameChecker: \n"); +} + +TEST(MemRegionDescriptiveNameTest, SymbolicElementRegionIndexOrigRegionFails) { + StringRef Code = R"cpp( +void reportDescriptiveName(int *p); +extern int getInt(void); +extern int array[3]; +void top() { + reportDescriptiveName(&array[getInt()]); +})cpp"; + + std::string Output; + ASSERT_TRUE(runChecker(Code, Output)); + EXPECT_EQ(Output, "DescriptiveNameChecker: \n"); +} + +TEST(MemRegionDescriptiveNameTest, SymbolicElementRegionIndexDescrNameFails) { + StringRef Code = R"cpp( +void reportDescriptiveName(int *p); +extern int *ptr; +extern int array[3]; +void top() { + reportDescriptiveName(&array[*ptr]); +})cpp"; + + std::string Output; + ASSERT_TRUE(runChecker(Code, Output)); + EXPECT_EQ(Output, "DescriptiveNameChecker: \n"); +} + +TEST(MemRegionDescriptiveNameTest, + SymbolicElementRegionIndexIncorrectSymbolName) { + StringRef Code = R"cpp( +void reportDescriptiveName(int *p); +extern int x, y; +extern int array[3]; +void top() { + y = x; + reportDescriptiveName(&array[y]); +})cpp"; + + std::string Output; + ASSERT_TRUE(runChecker(Code, Output)); + // FIXME: Should return array[y], but returns array[x] (OriginRegion). + EXPECT_EQ(Output, "DescriptiveNameChecker: array[x]\n"); +} + +} // namespace diff --git a/clang/unittests/Tooling/StandardLibraryTest.cpp b/clang/unittests/Tooling/StandardLibraryTest.cpp index edca31649accfabc3d3affc9ddb609a7ec8abbc9..e4c109f3d580d11627ccf79635aca9a8bde46369 100644 --- a/clang/unittests/Tooling/StandardLibraryTest.cpp +++ b/clang/unittests/Tooling/StandardLibraryTest.cpp @@ -185,6 +185,19 @@ TEST(StdlibTest, RecognizerForC99) { stdlib::Symbol::named("", "uint8_t", stdlib::Lang::C)); } +TEST(StdlibTest, SpecialCMappings) { + TestInputs Input("typedef char size_t;"); + Input.Language = TestLanguage::Lang_C99; + TestAST AST(Input); + + auto &SizeT = lookup(AST, "size_t"); + stdlib::Recognizer Recognizer; + auto ActualSym = Recognizer(&SizeT); + assert(ActualSym); + EXPECT_EQ(ActualSym, stdlib::Symbol::named("", "size_t", stdlib::Lang::C)); + EXPECT_EQ(ActualSym->header()->name(), "<stddef.h>"); +} + } // namespace } // namespace tooling } // namespace clang diff --git a/clang/utils/TableGen/MveEmitter.cpp b/clang/utils/TableGen/MveEmitter.cpp index 3a90eee5f1c92108387b01a04bc9d8e82f4b6056..aa20c758d84a60d90160d1c995e6647c02c4044f 100644 --- a/clang/utils/TableGen/MveEmitter.cpp +++ b/clang/utils/TableGen/MveEmitter.cpp @@ -575,7 +575,7 @@ public: // Emit code to generate this result as a Value *. std::string asValue() override { if (AddressType) - return "(" + varname() + ".getPointer())"; + return "(" + varname() + ".emitRawPointer(*this))"; return Result::asValue(); } bool hasIntegerValue() const override { return Immediate; } diff --git a/clang/utils/TableGen/RISCVVEmitter.cpp b/clang/utils/TableGen/RISCVVEmitter.cpp index 8513174c88bfc3242635774806bc1fcc37293523..5e41ef9f9d2684037988014b79d87755847959d7 100644 --- a/clang/utils/TableGen/RISCVVEmitter.cpp +++ b/clang/utils/TableGen/RISCVVEmitter.cpp @@ -334,10 +334,6 @@ void RVVEmitter::createHeader(raw_ostream &OS) { OS << "#include <stdint.h>\n"; OS << "#include <stddef.h>\n\n"; - OS << "#ifndef __riscv_vector\n"; - OS << "#error \"Vector intrinsics require the vector extension.\"\n"; - OS << "#endif\n\n"; - OS << "#ifdef __cplusplus\n"; OS << "extern \"C\" {\n"; OS << "#endif\n\n"; diff --git a/clang/utils/TableGen/SveEmitter.cpp b/clang/utils/TableGen/SveEmitter.cpp index 131397e3825b025de1b650f58293758d681008ca..3ddfd3277b68749142f45b6cb94614583f5c765c 100644 --- a/clang/utils/TableGen/SveEmitter.cpp +++ b/clang/utils/TableGen/SveEmitter.cpp @@ -99,7 +99,7 @@ public: bool isScalableVector() const { return isVector() && IsScalable; } bool isFixedLengthVector() const { return isVector() && !IsScalable; } bool isChar() const { return ElementBitwidth == 8; } - bool isVoid() const { return Void & !Pointer; } + bool isVoid() const { return Void && !Pointer; } bool isDefault() const { return DefaultType; } bool isFloat() const { return Float && !BFloat; } bool isBFloat() const { return BFloat && !Float; } diff --git a/clang/utils/analyzer/exploded-graph-rewriter.py b/clang/utils/analyzer/exploded-graph-rewriter.py index c7c6315a0a27d1912144bf8dac2a6232056bd117..5eaa7738103f795059fa5b9f913ac3cf16ef2b09 100755 --- a/clang/utils/analyzer/exploded-graph-rewriter.py +++ b/clang/utils/analyzer/exploded-graph-rewriter.py @@ -479,11 +479,19 @@ class ExplodedGraph: # A visitor that dumps the ExplodedGraph into a DOT file with fancy HTML-based # syntax highlighing. class DotDumpVisitor: - def __init__(self, do_diffs, dark_mode, gray_mode, topo_mode, dump_dot_only): + def __init__( + self, do_diffs, dark_mode, gray_mode, topo_mode, dump_html_only, dump_dot_only + ): + assert not (dump_html_only and dump_dot_only), ( + "Option dump_html_only and dump_dot_only are conflict, " + "they cannot be true at the same time." + ) + self._do_diffs = do_diffs self._dark_mode = dark_mode self._gray_mode = gray_mode self._topo_mode = topo_mode + self._dump_html_only = dump_html_only self._dump_dot_only = dump_dot_only self._output = [] @@ -998,6 +1006,8 @@ class DotDumpVisitor: '<html><body bgcolor="%s">%s</body></html>' % ("#1a1a1a" if self._dark_mode else "white", svg), ) + if self._dump_html_only: + return if sys.platform == "win32": os.startfile(filename) elif sys.platform == "darwin": @@ -1176,7 +1186,17 @@ def main(): default=False, help="black-and-white mode", ) - parser.add_argument( + dump_conflict = parser.add_mutually_exclusive_group() + dump_conflict.add_argument( + "--dump-html-only", + action="store_const", + dest="dump_html_only", + const=True, + default=False, + help="dump the rewritten egraph to a temporary HTML file, " + "but do not open it immediately as by default", + ) + dump_conflict.add_argument( "--dump-dot-only", action="store_const", dest="dump_dot_only", @@ -1206,7 +1226,12 @@ def main(): explorer = BasicExplorer() visitor = DotDumpVisitor( - args.diff, args.dark, args.gray, args.topology, args.dump_dot_only + args.diff, + args.dark, + args.gray, + args.topology, + args.dump_html_only, + args.dump_dot_only, ) for trimmer in trimmers: diff --git a/clang/www/analyzer/alpha_checks.html b/clang/www/analyzer/alpha_checks.html index 7bbe4a20288f23e0dd73125653971abb9f01825e..f040d1957b0f98bad4d5dbc428ae9ac80e56379d 100644 --- a/clang/www/analyzer/alpha_checks.html +++ b/clang/www/analyzer/alpha_checks.html @@ -307,26 +307,6 @@ void test(int x) { <tbody> -<tr><td><a id="alpha.cplusplus.ArrayDelete"><div class="namedescr expandable"><span class="name"> -alpha.cplusplus.ArrayDelete</span><span class="lang"> -(C++)</span><div class="descr"> -Reports destructions of arrays of polymorphic objects that are destructed as -their base class -</div></div></a></td> -<td><div class="exampleContainer expandable"> -<div class="example"><pre> -Base *create() { - Base *x = new Derived[10]; // note: Casting from 'Derived' to 'Base' here - return x; -} - -void sink(Base *x) { - delete[] x; // warn: Deleting an array of 'Derived' objects as their base class 'Base' undefined -} - -</pre></div></div></td></tr> - - <tr><td><a id="alpha.cplusplus.DeleteWithNonVirtualDtor"><div class="namedescr expandable"><span class="name"> alpha.cplusplus.DeleteWithNonVirtualDtor</span><span class="lang"> (C++)</span><div class="descr"> diff --git a/clang/www/analyzer/available_checks.html b/clang/www/analyzer/available_checks.html index 501a2b306dfaddf399739d580096ff06940be109..c23865e57e87d35452764a4442a1a08ba6b349e4 100644 --- a/clang/www/analyzer/available_checks.html +++ b/clang/www/analyzer/available_checks.html @@ -369,6 +369,33 @@ int test() { <thead><tr><td>Name, Description</td><td>Example</td></tr></thead> <tbody> + +<tr><td><a id="cplusplus.ArrayDelete"><div class="namedescr expandable"><span class="name"> +cplusplus.ArrayDelete</span><span class="lang"> +(C++)</span><div class="descr"> +Reports destructions of arrays of polymorphic objects that are destructed as +their base class. If the type of an array-pointer is different from the type of +its underlying objects, calling <code>delete[]</code> is undefined. +</div></div></a></td> +<td><div class="exampleContainer expandable"> +<div class="example"><pre> +class Base { +public: + virtual ~Base() {} +}; +class Derived : public Base {}; + +Base *create() { + Base *x = new Derived[10]; // note: Casting from 'Derived' to 'Base' here + return x; +} + +void sink(Base *x) { + delete[] x; // warn: Deleting an array of 'Derived' objects as their base class 'Base' undefined +} +</pre></div></div></td></tr> + + <tr><td><a id="cplusplus.NewDelete"><div class="namedescr expandable"><span class="name"> cplusplus.NewDelete</span><span class="lang"> (C++)</span><div class="descr"> diff --git a/clang/www/c_dr_status.html b/clang/www/c_dr_status.html index fa2ceb1be58bdc469006940ee74c949e37806ae0..a41c4f71706769a3fbe2d863c5e2591d83ef38c6 100644 --- a/clang/www/c_dr_status.html +++ b/clang/www/c_dr_status.html @@ -577,7 +577,7 @@ conformance.</p> <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_087.html">87</a></td> <td>NAD</td> <td>Order of evaluation</td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Yes</td> </tr> <tr id="88"> <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_088.html">88</a></td> @@ -1686,7 +1686,7 @@ conformance.</p> <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_290.htm">290</a></td> <td>C99</td> <td>FLT_EVAL_METHOD and extra precision and/or range</td> - <td class="unknown" align="center">Unknown</td> + <td class="none" align="center">No</td> </tr> <tr id="291"> <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_291.htm">291</a></td> diff --git a/clang/www/c_status.html b/clang/www/c_status.html index 9e4600b3e66acb17cbd1c1f590757ebebfd4df5b..370d99b55b1312a29d0daadd7f721273b8419e2d 100644 --- a/clang/www/c_status.html +++ b/clang/www/c_status.html @@ -105,7 +105,7 @@ conformance.</p> <tr> <td>restricted character set support via digraphs and <iso646.h></td> <td>Unknown</td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Yes</td> </tr> <tr> <td>more precise aliasing rules via effective type</td> @@ -132,11 +132,6 @@ conformance.</p> <td>Unknown</td> <td class="full" align="center">Yes</td> </tr> - <tr> - <td>more precise aliasing rules via effective type</td> - <td>Unknown</td> - <td class="unknown" align="center">Unknown</td> - </tr> <tr id="complex"> <td rowspan="6">complex and imaginary support in <complex.h></td> </tr> @@ -173,12 +168,12 @@ conformance.</p> <tr> <td>increase minimum translation limits</td> <td>N590</td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Clang 3.2</td> </tr> <tr> <td>additional floating-point characteristics in <float.h></td> <td>Unknown</td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Clang 16</td> </tr> <tr id="implicit int"> <td rowspan="4">remove implicit int</td> @@ -260,7 +255,7 @@ conformance.</p> <tr> <td>new block scopes for selection and iteration statements</td> <td>Unknown</td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Yes</td> </tr> <tr> <td>integer constant type rules</td> @@ -305,7 +300,7 @@ conformance.</p> <tr> <td>empty macro arguments</td> <td>N570</td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Yes</td> </tr> <tr> <td>new structure type compatibility (tag compatibility)</td> @@ -315,7 +310,13 @@ conformance.</p> <tr> <td>additional predefined macro names</td> <td>Unknown</td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Yes</td> + <!-- It is unknown which paper brought in this change, which was listed in + the C99 front matter. After hunting around for what these changes are, + I found a mention in the C99 rationale document that implementers who + wish to add their own predefined macros must not start them with + __STDC_, which was a new restriction in C99. As best I can tell, that + is what this particular feature is about. --> </tr> <tr> <td>_Pragma preprocessing operator</td> @@ -330,11 +331,11 @@ conformance.</p> </tr> <tr> <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n631.htm">N631</a></td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Yes</td> </tr> <tr> <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n696.ps">N696</a></td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Yes</td> </tr> <tr> <td>__func__ predefined identifier</td> @@ -346,30 +347,25 @@ conformance.</p> <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n671.htm">N671</a></td> <td class="full" align="center">Yes</td> </tr> - <tr> - <td>LIA compatibility annex</td> - <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n792.htm">N792</a></td> - <td class="none" align="center">No</td> - </tr> <tr> <td>remove deprecation of aliased array parameters</td> <td>Unknown</td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Yes</td> </tr> <tr> <td>conversion of array to pointer not limited to lvalues</td> - <td>Unknown</td> - <td class="unknown" align="center">Unknown</td> + <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n835.pdf">N835</a></td> + <td class="full" align="center">Yes</td> </tr> <tr> <td>relaxed constraints on aggregate and union initialization</td> - <td>Unknown</td> - <td class="unknown" align="center">Unknown</td> + <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n782.htm">N782</a></td> + <td class="full" align="center">Clang 3.4</td> </tr> <tr> <td>relaxed restrictions on portable header names</td> <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n772.htm">N772</a></td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Yes</td> </tr> <tr> <td>return without an expression not permitted in function that returns a value</td> @@ -401,7 +397,7 @@ conformance.</p> <tr> <td>Clarification of expressions</td> <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1282.pdf">N1282</a></td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Yes</td> </tr> <tr> <td>Extending the lifetime of temporary objects (factored approach)</td> @@ -411,7 +407,7 @@ conformance.</p> <tr> <td>Requiring signed char to have no padding bits</td> <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1310.htm">N1310</a></td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Yes</td> </tr> <tr> <td>Initializing static or external variables</td> @@ -471,7 +467,7 @@ conformance.</p> <tr> <td>Constant expressions</td> <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1365.htm">N1365</a></td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Clang 16</td> </tr> <tr> <td>Contractions and expression evaluation methods</td> @@ -552,7 +548,7 @@ conformance.</p> <tr> <td>Explicit initializers for atomics</td> <td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1482.htm">N1482</a></td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Clang 4</td> </tr> <tr> <td>Atomics proposal (minus ternary op)</td> diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index c20a5d021e9d95871e4355868a86cd00c25dad16..5e1e03dec1d484a704ace7277081bbf666f82d65 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -9444,7 +9444,7 @@ and <I>POD class</I></td> <td><a href="https://cplusplus.github.io/CWG/issues/1606.html">1606</a></td> <td>NAD</td> <td><TT>sizeof</TT> closure class</td> - <td class="unknown" align="center">Unknown</td> + <td class="full" align="center">Clang 3.1</td> </tr> <tr id="1607"> <td><a href="https://cplusplus.github.io/CWG/issues/1607.html">1607</a></td> diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 1e36b90356c3e1abbb042b95fff95f0868c07b85..c1d95dadbb27e20734aae28e8f79808bc1368bbe 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -163,7 +163,47 @@ C++23, informally referred to as C++26.</p> <td><a href="https://wg21.link/P2864R2">P2864R2</a></td> <td class="full" align="center">Clang 18</td> </tr> - + <!-- Winter 2024 papers (Tokyo) --> + <tr> + <td>Disallow Binding a Returned Glvalue to a Temporary</td> + <td><a href="https://wg21.link/P2748R5">P2748R5</a></td> + <td class="none" align="center">No</td> + </tr> + <tr> + <td>Clarifying rules for brace elision in aggregate initialization</td> + <td><a href="https://wg21.link/P3106R1">P3106R1</a> (<a href="#dr">DR</a>)</td> + <td class="none" align="center">No</td> + </tr> + <tr> + <td>Attributes for Structured Bindings</td> + <td><a href="https://wg21.link/P0609R3">P0609R3</a></td> + <td class="none" align="center">No</td> + </tr> + <tr> + <td>Module Declarations Shouldn’t be Macros</td> + <td><a href="https://wg21.link/P3034R1">P3034R1</a> (<a href="#dr">DR</a>)</td> + <td class="none" align="center">No</td> + </tr> + <tr> + <td>Trivial infinite loops are not Undefined Behavior</td> + <td><a href="https://wg21.link/P2809R3">P2809R3</a> (<a href="#dr">DR</a>)</td> + <td class="none" align="center">No</td> + </tr> + <tr> + <td>Erroneous behaviour for uninitialized reads</td> + <td><a href="https://wg21.link/P2795R5">P2795R5</a></td> + <td class="none" align="center">No</td> + </tr> + <tr> + <td><tt>= delete("should have a reason");</tt></td> + <td><a href="https://wg21.link/P2573R2">P2573R2</a></td> + <td class="none" align="center">No</td> + </tr> + <tr> + <td>Variadic friends</td> + <td><a href="https://wg21.link/P2893R3">P2893R3</a></td> + <td class="none" align="center">No</td> + </tr> </table> </details> diff --git a/clang/www/get_started.html b/clang/www/get_started.html index dda914a46904e835e41bbc548b4c14a29f16f8e2..8e4d36640be7357a97d0923fd3964bd872658ba7 100755 --- a/clang/www/get_started.html +++ b/clang/www/get_started.html @@ -86,13 +86,16 @@ follows:</p> </ul> </li> - <li>If you intend to use Clang's C++ support, you may need to tell it how - to find your C++ standard library headers. In general, Clang will detect - the best version of libstdc++ headers available and use them - it will - look both for system installations of libstdc++ as well as installations - adjacent to Clang itself. If your configuration fits neither of these - scenarios, you can use the <tt>-DGCC_INSTALL_PREFIX</tt> cmake option - to tell Clang where the gcc containing the desired libstdc++ is installed. + <li>On Linux, you may need GCC runtime libraries (e.g. <tt>crtbeginS.o, + libstdc++.so</tt>) and libstdc++ headers. In general, Clang will detect + well-known GCC installation paths matching the target triple (configured at + build time (see <tt>clang --version</tt>); overriden by + <tt>--target=</tt>) and use the largest version. If your configuration fits + none of the standard scenarios, you can set <tt>--gcc-install-dir=</tt> to + the GCC installation directory (something like + <tt>/usr/lib/gcc/$triple/$major</tt>). If your GCC installation is under + <tt>/usr/lib/gcc</tt> but uses a different triple, you can set + <tt>--gcc-triple=$triple</tt>. </li> <li>Try it out (assuming you add llvm/build/bin to your path): <ul> diff --git a/cmake/Modules/GetDarwinLinkerVersion.cmake b/cmake/Modules/GetDarwinLinkerVersion.cmake new file mode 100644 index 0000000000000000000000000000000000000000..c27e50128586dbe7e9d3ff480593ed8626c58a0a --- /dev/null +++ b/cmake/Modules/GetDarwinLinkerVersion.cmake @@ -0,0 +1,19 @@ +# Get the linker version on Darwin +function(get_darwin_linker_version variable) + set(LINK_VERSION) + set(LD_V_OUTPUT) + execute_process( + COMMAND sh -c "${CMAKE_LINKER} -v 2>&1 | head -1" + RESULT_VARIABLE HAD_ERROR + OUTPUT_VARIABLE LD_V_OUTPUT + ) + if (HAD_ERROR) + message(FATAL_ERROR "${CMAKE_LINKER} failed with status ${HAD_ERROR}") + endif() + if ("${LD_V_OUTPUT}" MATCHES ".*ld64-([0-9.]+).*") + string(REGEX REPLACE ".*ld64-([0-9.]+).*" "\\1" LINK_VERSION ${LD_V_OUTPUT}) + elseif ("${LD_V_OUTPUT}" MATCHES "[^0-9]*([0-9.]+).*") + string(REGEX REPLACE "[^0-9]*([0-9.]+).*" "\\1" LINK_VERSION ${LD_V_OUTPUT}) + endif() + set(${variable} ${LINK_VERSION} PARENT_SCOPE) +endfunction() diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt index d562a6206c00e7edd72ee6b559e5bd0a78338f73..f4e92f14db85703fc7e91de89feee46d5145f0cf 100644 --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -36,6 +36,7 @@ include(SetPlatformToolchainTools) include(base-config-ix) include(CompilerRTUtils) include(CMakeDependentOption) +include(GetDarwinLinkerVersion) option(COMPILER_RT_BUILD_BUILTINS "Build builtins" ON) mark_as_advanced(COMPILER_RT_BUILD_BUILTINS) @@ -444,6 +445,15 @@ else() set(SANITIZER_USE_SYMBOLS FALSE) endif() +# Get the linker version while configuring compiler-rt and explicitly pass it +# in cflags during testing. This fixes the compiler/linker version mismatch +# issue when running a clang built with a newer Xcode in an older Xcode +set(COMPILER_RT_DARWIN_LINKER_VERSION) +if (APPLE AND NOT CMAKE_LINKER MATCHES ".*lld.*") + get_darwin_linker_version(COMPILER_RT_DARWIN_LINKER_VERSION) + message(STATUS "Host linker version: ${COMPILER_RT_DARWIN_LINKER_VERSION}") +endif() + # Build sanitizer runtimes with debug info. if(MSVC) # Use /Z7 instead of /Zi for the asan runtime. This avoids the LNK4099 diff --git a/compiler-rt/cmake/Modules/CompilerRTCompile.cmake b/compiler-rt/cmake/Modules/CompilerRTCompile.cmake index 2bf115973a49b381cce37d26e81d9cb3958e08d4..1629db18f1c2d98eb34833f28270bfaba1f3bc46 100644 --- a/compiler-rt/cmake/Modules/CompilerRTCompile.cmake +++ b/compiler-rt/cmake/Modules/CompilerRTCompile.cmake @@ -46,7 +46,7 @@ function(sanitizer_test_compile obj_list source arch) # Write out architecture-specific flags into TARGET_CFLAGS variable. get_target_flags_for_arch(${arch} TARGET_CFLAGS) set(COMPILE_DEPS ${TEST_COMPILE_DEPS}) - if(NOT COMPILER_RT_STANDALONE_BUILD) + if(NOT COMPILER_RT_STANDALONE_BUILD OR COMPILER_RT_TEST_STANDALONE_BUILD_LIBS) list(APPEND COMPILE_DEPS ${TEST_DEPS}) endif() clang_compile(${output_obj} ${source} @@ -65,8 +65,9 @@ function(clang_compile object_file source) cmake_parse_arguments(SOURCE "" "" "CFLAGS;DEPS" ${ARGN}) get_filename_component(source_rpath ${source} REALPATH) if(NOT COMPILER_RT_STANDALONE_BUILD) - list(APPEND SOURCE_DEPS clang compiler-rt-headers) + list(APPEND SOURCE_DEPS clang) endif() + list(APPEND SOURCE_DEPS compiler-rt-headers) if (TARGET CompilerRTUnitTestCheckCxx) list(APPEND SOURCE_DEPS CompilerRTUnitTestCheckCxx) endif() diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index 4f47142850a55eab870d3dfe6f01ff52d695f0a9..46a6fdf8728ff8fcdb8ef103dcfb918d8560a410 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -461,7 +461,7 @@ if(APPLE) set(ORC_SUPPORTED_OS osx) endif() - set(DEFAULT_SANITIZER_MIN_OSX_VERSION 10.10) + set(DEFAULT_SANITIZER_MIN_OSX_VERSION 10.13) set(DARWIN_osx_MIN_VER_FLAG "-mmacosx-version-min") if(NOT SANITIZER_MIN_OSX_VERSION) string(REGEX MATCH "${DARWIN_osx_MIN_VER_FLAG}=([.0-9]+)" diff --git a/compiler-rt/include/sanitizer/linux_syscall_hooks.h b/compiler-rt/include/sanitizer/linux_syscall_hooks.h index 3f3f1e78dfb8594835935aa0473ad459adc808bc..5f262455cb9466f976a14a103f8cab0354fd7cea 100644 --- a/compiler-rt/include/sanitizer/linux_syscall_hooks.h +++ b/compiler-rt/include/sanitizer/linux_syscall_hooks.h @@ -1856,6 +1856,15 @@ __sanitizer_syscall_pre_impl_sigaltstack((long)ss, (long)oss) #define __sanitizer_syscall_post_sigaltstack(res, ss, oss) \ __sanitizer_syscall_post_impl_sigaltstack(res, (long)ss, (long)oss) +#define __sanitizer_syscall_pre_futex(uaddr, futex_op, val, timeout, uaddr2, \ + val3) \ + __sanitizer_syscall_pre_impl_futex((long)uaddr, (long)futex_op, (long)val, \ + (long)timeout, (long)uaddr2, (long)val3) +#define __sanitizer_syscall_post_futex(res, uaddr, futex_op, val, timeout, \ + uaddr2, val3) \ + __sanitizer_syscall_post_impl_futex(res, (long)uaddr, (long)futex_op, \ + (long)val, (long)timeout, (long)uaddr2, \ + (long)val3) // And now a few syscalls we don't handle yet. #define __sanitizer_syscall_pre_afs_syscall(...) @@ -1875,7 +1884,6 @@ #define __sanitizer_syscall_pre_fchown32(...) #define __sanitizer_syscall_pre_ftime(...) #define __sanitizer_syscall_pre_ftruncate64(...) -#define __sanitizer_syscall_pre_futex(...) #define __sanitizer_syscall_pre_getegid32(...) #define __sanitizer_syscall_pre_geteuid32(...) #define __sanitizer_syscall_pre_getgid32(...) @@ -1954,7 +1962,6 @@ #define __sanitizer_syscall_post_fchown32(res, ...) #define __sanitizer_syscall_post_ftime(res, ...) #define __sanitizer_syscall_post_ftruncate64(res, ...) -#define __sanitizer_syscall_post_futex(res, ...) #define __sanitizer_syscall_post_getegid32(res, ...) #define __sanitizer_syscall_post_geteuid32(res, ...) #define __sanitizer_syscall_post_getgid32(res, ...) @@ -3093,6 +3100,11 @@ void __sanitizer_syscall_post_impl_rt_sigaction(long res, long signum, long act, long oldact, long sz); void __sanitizer_syscall_pre_impl_sigaltstack(long ss, long oss); void __sanitizer_syscall_post_impl_sigaltstack(long res, long ss, long oss); +void __sanitizer_syscall_pre_impl_futex(long uaddr, long futex_op, long val, + long timeout, long uaddr2, long val3); +void __sanitizer_syscall_post_impl_futex(long res, long uaddr, long futex_op, + long val, long timeout, long uaddr2, + long val3); #ifdef __cplusplus } // extern "C" #endif diff --git a/compiler-rt/lib/asan/CMakeLists.txt b/compiler-rt/lib/asan/CMakeLists.txt index f83ae82d42935a106cceead6dcba83a83fa642dd..601750f72175d6fbb708adf02a5f59e85b804cb0 100644 --- a/compiler-rt/lib/asan/CMakeLists.txt +++ b/compiler-rt/lib/asan/CMakeLists.txt @@ -85,6 +85,9 @@ SET(ASAN_HEADERS include_directories(..) set(ASAN_CFLAGS ${SANITIZER_COMMON_CFLAGS}) + +append_list_if(MSVC /Zl ASAN_CFLAGS) + set(ASAN_COMMON_DEFINITIONS ${COMPILER_RT_ASAN_SHADOW_SCALE_DEFINITION}) append_rtti_flag(OFF ASAN_CFLAGS) diff --git a/compiler-rt/lib/asan/asan_interceptors.cpp b/compiler-rt/lib/asan/asan_interceptors.cpp index 9d383b9d37c4a1a686896aa2af2633389c48e915..6d1360e104975faa2a9a54c46c88b799bc477e41 100644 --- a/compiler-rt/lib/asan/asan_interceptors.cpp +++ b/compiler-rt/lib/asan/asan_interceptors.cpp @@ -570,6 +570,17 @@ INTERCEPTOR(char *, strcpy, char *to, const char *from) { return REAL(strcpy)(to, from); } +// Windows doesn't always define the strdup identifier, +// and when it does it's a macro defined to either _strdup +// or _strdup_dbg, _strdup_dbg ends up calling _strdup, so +// we want to intercept that. push/pop_macro are used to avoid problems +// if this file ends up including <string.h> in the future. +# if SANITIZER_WINDOWS +# pragma push_macro("strdup") +# undef strdup +# define strdup _strdup +# endif + INTERCEPTOR(char*, strdup, const char *s) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strdup); @@ -587,7 +598,7 @@ INTERCEPTOR(char*, strdup, const char *s) { return reinterpret_cast<char*>(new_mem); } -#if ASAN_INTERCEPT___STRDUP +# if ASAN_INTERCEPT___STRDUP INTERCEPTOR(char*, __strdup, const char *s) { void *ctx; ASAN_INTERCEPTOR_ENTER(ctx, strdup); @@ -750,8 +761,8 @@ INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(), #endif #if ASAN_INTERCEPT_VFORK -DEFINE_REAL(int, vfork) -DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork) +DEFINE_REAL(int, vfork,) +DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork,) #endif // ---------------------- InitializeAsanInterceptors ---------------- {{{1 @@ -770,7 +781,7 @@ void InitializeAsanInterceptors() { ASAN_INTERCEPT_FUNC(strncat); ASAN_INTERCEPT_FUNC(strncpy); ASAN_INTERCEPT_FUNC(strdup); -#if ASAN_INTERCEPT___STRDUP +# if ASAN_INTERCEPT___STRDUP ASAN_INTERCEPT_FUNC(__strdup); #endif #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX @@ -866,6 +877,10 @@ void InitializeAsanInterceptors() { VReport(1, "AddressSanitizer: libc interceptors initialized\n"); } +# if SANITIZER_WINDOWS +# pragma pop_macro("strdup") +# endif + } // namespace __asan #endif // !SANITIZER_FUCHSIA diff --git a/compiler-rt/lib/asan/asan_win_dll_thunk.cpp b/compiler-rt/lib/asan/asan_win_dll_thunk.cpp index 0fa636bec0d001af2da51608f1d580014318fa9c..35871a942a7a126d086d5b56e09bff20dbfe75b5 100644 --- a/compiler-rt/lib/asan/asan_win_dll_thunk.cpp +++ b/compiler-rt/lib/asan/asan_win_dll_thunk.cpp @@ -80,7 +80,7 @@ INTERCEPT_LIBRARY_FUNCTION(strchr); INTERCEPT_LIBRARY_FUNCTION(strcmp); INTERCEPT_LIBRARY_FUNCTION(strcpy); INTERCEPT_LIBRARY_FUNCTION(strcspn); -INTERCEPT_LIBRARY_FUNCTION(strdup); +INTERCEPT_LIBRARY_FUNCTION(_strdup); INTERCEPT_LIBRARY_FUNCTION(strlen); INTERCEPT_LIBRARY_FUNCTION(strncat); INTERCEPT_LIBRARY_FUNCTION(strncmp); diff --git a/compiler-rt/lib/asan/tests/CMakeLists.txt b/compiler-rt/lib/asan/tests/CMakeLists.txt index 6ee2fb01c0df4936422be24ea518d69993060e7c..bda47bd7fd6a2236c3ded87f0ce9b74d8d442946 100644 --- a/compiler-rt/lib/asan/tests/CMakeLists.txt +++ b/compiler-rt/lib/asan/tests/CMakeLists.txt @@ -172,7 +172,7 @@ function(add_asan_tests arch test_runtime) function(generate_asan_tests test_objects test_suite testname) generate_compiler_rt_tests(${test_objects} ${test_suite} ${testname} ${arch} COMPILE_DEPS ${ASAN_UNITTEST_HEADERS} ${ASAN_IGNORELIST_FILE} - DEPS llvm_gtest asan + DEPS asan KIND ${TEST_KIND} ${ARGN} ) diff --git a/compiler-rt/lib/asan/tests/asan_noinst_test.cpp b/compiler-rt/lib/asan/tests/asan_noinst_test.cpp index 4c103609c83bfdfc0da86eb3cf66b371fbaef164..df7de2d7d15ed7add520fccf7dd4b2e2cef8b586 100644 --- a/compiler-rt/lib/asan/tests/asan_noinst_test.cpp +++ b/compiler-rt/lib/asan/tests/asan_noinst_test.cpp @@ -45,7 +45,8 @@ TEST(AddressSanitizer, InternalSimpleDeathTest) { EXPECT_DEATH(exit(1), ""); } -static void MallocStress(size_t n) { +static void *MallocStress(void *NumOfItrPtr) { + size_t n = *((size_t *)NumOfItrPtr); u32 seed = my_rand(); BufferedStackTrace stack1; stack1.trace_buffer[0] = 0xa123; @@ -90,20 +91,21 @@ static void MallocStress(size_t n) { } for (size_t i = 0; i < vec.size(); i++) __asan::asan_free(vec[i], &stack3, __asan::FROM_MALLOC); + return nullptr; } - TEST(AddressSanitizer, NoInstMallocTest) { - MallocStress(ASAN_LOW_MEMORY ? 300000 : 1000000); + const size_t kNumIterations = (ASAN_LOW_MEMORY) ? 300000 : 1000000; + MallocStress((void *)&kNumIterations); } TEST(AddressSanitizer, ThreadedMallocStressTest) { const int kNumThreads = 4; - const int kNumIterations = (ASAN_LOW_MEMORY) ? 10000 : 100000; + const size_t kNumIterations = (ASAN_LOW_MEMORY) ? 10000 : 100000; pthread_t t[kNumThreads]; for (int i = 0; i < kNumThreads; i++) { - PTHREAD_CREATE(&t[i], 0, (void* (*)(void *x))MallocStress, - (void*)kNumIterations); + PTHREAD_CREATE(&t[i], 0, (void *(*)(void *x))MallocStress, + (void *)&kNumIterations); } for (int i = 0; i < kNumThreads; i++) { PTHREAD_JOIN(t[i], 0); diff --git a/compiler-rt/lib/dfsan/dfsan.cpp b/compiler-rt/lib/dfsan/dfsan.cpp index 5e85c8fda3e230fde0695bd213d45b97b671a164..302e3c3032ac599a23e2d36540da7358eeb05350 100644 --- a/compiler-rt/lib/dfsan/dfsan.cpp +++ b/compiler-rt/lib/dfsan/dfsan.cpp @@ -33,6 +33,9 @@ #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_report_decorator.h" #include "sanitizer_common/sanitizer_stacktrace.h" +#if SANITIZER_LINUX +# include <sys/personality.h> +#endif using namespace __dfsan; @@ -1127,11 +1130,12 @@ static void CheckMemoryLayoutSanity() { // TODO: CheckMemoryRangeAvailability is based on msan. // Consider refactoring these into a shared implementation. -static bool CheckMemoryRangeAvailability(uptr beg, uptr size) { +static bool CheckMemoryRangeAvailability(uptr beg, uptr size, bool verbose) { if (size > 0) { uptr end = beg + size - 1; if (!MemoryRangeIsAvailable(beg, end)) { - Printf("FATAL: Memory range %p - %p is not available.\n", beg, end); + if (verbose) + Printf("FATAL: Memory range %p - %p is not available.\n", beg, end); return false; } } @@ -1163,7 +1167,7 @@ static bool ProtectMemoryRange(uptr beg, uptr size, const char *name) { // TODO: InitShadow is based on msan. // Consider refactoring these into a shared implementation. -bool InitShadow(bool init_origins) { +bool InitShadow(bool init_origins, bool dry_run) { // Let user know mapping parameters first. VPrintf(1, "dfsan_init %p\n", (void *)&__dfsan::dfsan_init); for (unsigned i = 0; i < kMemoryLayoutSize; ++i) @@ -1173,8 +1177,9 @@ bool InitShadow(bool init_origins) { CheckMemoryLayoutSanity(); if (!MEM_IS_APP(&__dfsan::dfsan_init)) { - Printf("FATAL: Code %p is out of application range. Non-PIE build?\n", - (uptr)&__dfsan::dfsan_init); + if (!dry_run) + Printf("FATAL: Code %p is out of application range. Non-PIE build?\n", + (uptr)&__dfsan::dfsan_init); return false; } @@ -1195,20 +1200,26 @@ bool InitShadow(bool init_origins) { bool protect = type == MappingDesc::INVALID || (!init_origins && type == MappingDesc::ORIGIN); CHECK(!(map && protect)); - if (!map && !protect) - CHECK(type == MappingDesc::APP); + if (!map && !protect) { + CHECK(type == MappingDesc::APP || type == MappingDesc::ALLOCATOR); + + if (dry_run && type == MappingDesc::ALLOCATOR && + !CheckMemoryRangeAvailability(start, size, !dry_run)) + return false; + } if (map) { - if (!CheckMemoryRangeAvailability(start, size)) + if (dry_run && !CheckMemoryRangeAvailability(start, size, !dry_run)) return false; - if (!MmapFixedSuperNoReserve(start, size, kMemoryLayout[i].name)) + if (!dry_run && + !MmapFixedSuperNoReserve(start, size, kMemoryLayout[i].name)) return false; - if (common_flags()->use_madv_dontdump) + if (!dry_run && common_flags()->use_madv_dontdump) DontDumpShadowMemory(start, size); } if (protect) { - if (!CheckMemoryRangeAvailability(start, size)) + if (dry_run && !CheckMemoryRangeAvailability(start, size, !dry_run)) return false; - if (!ProtectMemoryRange(start, size, kMemoryLayout[i].name)) + if (!dry_run && !ProtectMemoryRange(start, size, kMemoryLayout[i].name)) return false; } } @@ -1216,6 +1227,35 @@ bool InitShadow(bool init_origins) { return true; } +bool InitShadowWithReExec(bool init_origins) { + // Start with dry run: check layout is ok, but don't print warnings because + // warning messages will cause tests to fail (even if we successfully re-exec + // after the warning). + bool success = InitShadow(init_origins, true); + if (!success) { +#if SANITIZER_LINUX + // Perhaps ASLR entropy is too high. If ASLR is enabled, re-exec without it. + int old_personality = personality(0xffffffff); + bool aslr_on = + (old_personality != -1) && ((old_personality & ADDR_NO_RANDOMIZE) == 0); + + if (aslr_on) { + VReport(1, + "WARNING: DataflowSanitizer: memory layout is incompatible, " + "possibly due to high-entropy ASLR.\n" + "Re-execing with fixed virtual address space.\n" + "N.B. reducing ASLR entropy is preferable.\n"); + CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1); + ReExec(); + } +#endif + } + + // The earlier dry run didn't actually map or protect anything. Run again in + // non-dry run mode. + return success && InitShadow(init_origins, false); +} + static void DFsanInit(int argc, char **argv, char **envp) { CHECK(!dfsan_init_is_running); if (dfsan_inited) @@ -1229,7 +1269,11 @@ static void DFsanInit(int argc, char **argv, char **envp) { CheckASLR(); - InitShadow(dfsan_get_track_origins()); + if (!InitShadowWithReExec(dfsan_get_track_origins())) { + Printf("FATAL: DataflowSanitizer can not mmap the shadow memory.\n"); + DumpProcessMap(); + Die(); + } initialize_interceptors(); diff --git a/compiler-rt/lib/dfsan/dfsan_allocator.cpp b/compiler-rt/lib/dfsan/dfsan_allocator.cpp index df8be2cf5ae04c2207772f0d4def636c65b38906..63475f434cd1007580af8522504364be8081b91b 100644 --- a/compiler-rt/lib/dfsan/dfsan_allocator.cpp +++ b/compiler-rt/lib/dfsan/dfsan_allocator.cpp @@ -37,6 +37,9 @@ struct DFsanMapUnmapCallback { void OnUnmap(uptr p, uptr size) const { dfsan_set_label(0, (void *)p, size); } }; +// Note: to ensure that the allocator is compatible with the application memory +// layout (especially with high-entropy ASLR), kSpaceBeg and kSpaceSize must be +// duplicated as MappingDesc::ALLOCATOR in dfsan_platform.h. #if defined(__aarch64__) const uptr kAllocatorSpace = 0xE00000000000ULL; #else diff --git a/compiler-rt/lib/dfsan/dfsan_platform.h b/compiler-rt/lib/dfsan/dfsan_platform.h index b849b4b528ad292f91a205bce6c8e615ab9666b2..01f0de47d960d351512c816c38ecccb441527904 100644 --- a/compiler-rt/lib/dfsan/dfsan_platform.h +++ b/compiler-rt/lib/dfsan/dfsan_platform.h @@ -27,10 +27,19 @@ using __sanitizer::uptr; struct MappingDesc { uptr start; uptr end; - enum Type { INVALID, APP, SHADOW, ORIGIN } type; + enum Type { + INVALID = 1, + ALLOCATOR = 2, + APP = 4, + SHADOW = 8, + ORIGIN = 16, + } type; const char *name; }; +// Note: MappingDesc::ALLOCATOR entries are only used to check for memory +// layout compatibility. The actual allocation settings are in +// dfsan_allocator.cpp, which need to be kept in sync. #if SANITIZER_LINUX && SANITIZER_WORDSIZE == 64 # if defined(__aarch64__) @@ -53,7 +62,8 @@ const MappingDesc kMemoryLayout[] = { {0X0B00000000000, 0X0C00000000000, MappingDesc::SHADOW, "shadow-10-13"}, {0X0C00000000000, 0X0D00000000000, MappingDesc::INVALID, "invalid"}, {0X0D00000000000, 0X0E00000000000, MappingDesc::ORIGIN, "origin-10-13"}, - {0X0E00000000000, 0X1000000000000, MappingDesc::APP, "app-15"}, + {0X0E00000000000, 0X0E40000000000, MappingDesc::ALLOCATOR, "allocator"}, + {0X0E40000000000, 0X1000000000000, MappingDesc::APP, "app-15"}, }; # define MEM_TO_SHADOW(mem) ((uptr)mem ^ 0xB00000000000ULL) # define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x200000000000ULL) @@ -76,7 +86,8 @@ const MappingDesc kMemoryLayout[] = { {0x510000000000ULL, 0x600000000000ULL, MappingDesc::APP, "app-2"}, {0x600000000000ULL, 0x610000000000ULL, MappingDesc::ORIGIN, "origin-1"}, {0x610000000000ULL, 0x700000000000ULL, MappingDesc::INVALID, "invalid"}, - {0x700000000000ULL, 0x800000000000ULL, MappingDesc::APP, "app-3"}}; + {0x700000000000ULL, 0x740000000000ULL, MappingDesc::ALLOCATOR, "allocator"}, + {0x740000000000ULL, 0x800000000000ULL, MappingDesc::APP, "app-3"}}; # define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x500000000000ULL) # define SHADOW_TO_ORIGIN(mem) (((uptr)(mem)) + 0x100000000000ULL) # endif @@ -93,20 +104,21 @@ const uptr kMemoryLayoutSize = sizeof(kMemoryLayout) / sizeof(kMemoryLayout[0]); __attribute__((optimize("unroll-loops"))) #endif inline bool -addr_is_type(uptr addr, MappingDesc::Type mapping_type) { +addr_is_type(uptr addr, int mapping_types) { // It is critical for performance that this loop is unrolled (because then it is // simplified into just a few constant comparisons). #ifdef __clang__ # pragma unroll #endif for (unsigned i = 0; i < kMemoryLayoutSize; ++i) - if (kMemoryLayout[i].type == mapping_type && + if ((kMemoryLayout[i].type & mapping_types) && addr >= kMemoryLayout[i].start && addr < kMemoryLayout[i].end) return true; return false; } -#define MEM_IS_APP(mem) addr_is_type((uptr)(mem), MappingDesc::APP) +#define MEM_IS_APP(mem) \ + (addr_is_type((uptr)(mem), MappingDesc::APP | MappingDesc::ALLOCATOR)) #define MEM_IS_SHADOW(mem) addr_is_type((uptr)(mem), MappingDesc::SHADOW) #define MEM_IS_ORIGIN(mem) addr_is_type((uptr)(mem), MappingDesc::ORIGIN) diff --git a/compiler-rt/lib/fuzzer/FuzzerUtilLinux.cpp b/compiler-rt/lib/fuzzer/FuzzerUtilLinux.cpp index 5729448b0beb13f7fda6f9be57f9c06d9c7522cb..e5409f22f0e3a2c98911c2bb5a15589af7288da3 100644 --- a/compiler-rt/lib/fuzzer/FuzzerUtilLinux.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerUtilLinux.cpp @@ -44,7 +44,7 @@ void SetThreadName(std::thread &thread, const std::string &name) { #if LIBFUZZER_LINUX || LIBFUZZER_FREEBSD (void)pthread_setname_np(thread.native_handle(), name.c_str()); #elif LIBFUZZER_NETBSD - (void)pthread_set_name_np(thread.native_handle(), "%s", name.c_str()); + (void)pthread_setname_np(thread.native_handle(), "%s", const_cast<char *>(name.c_str())); #endif } diff --git a/compiler-rt/lib/fuzzer/tests/CMakeLists.txt b/compiler-rt/lib/fuzzer/tests/CMakeLists.txt index dd82c492e83a4567eb2936ac85f43e1de3c0cfd9..8f5707c687ac50329c7a18fd1b50fe32e645b617 100644 --- a/compiler-rt/lib/fuzzer/tests/CMakeLists.txt +++ b/compiler-rt/lib/fuzzer/tests/CMakeLists.txt @@ -74,7 +74,7 @@ if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST FUZZER_SUPPORTED_ARCH) FuzzerUnitTests "Fuzzer-${arch}-Test" ${arch} SOURCES FuzzerUnittest.cpp ${COMPILER_RT_GTEST_SOURCE} RUNTIME ${LIBFUZZER_TEST_RUNTIME} - DEPS llvm_gtest ${LIBFUZZER_TEST_RUNTIME_DEPS} + DEPS ${LIBFUZZER_TEST_RUNTIME_DEPS} CFLAGS ${LIBFUZZER_UNITTEST_CFLAGS} ${LIBFUZZER_TEST_RUNTIME_CFLAGS} LINK_FLAGS ${LIBFUZZER_UNITTEST_LINK_FLAGS} ${LIBFUZZER_TEST_RUNTIME_LINK_FLAGS}) set_target_properties(FuzzerUnitTests PROPERTIES @@ -84,7 +84,7 @@ if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST FUZZER_SUPPORTED_ARCH) generate_compiler_rt_tests(FuzzedDataProviderTestObjects FuzzedDataProviderUnitTests "FuzzerUtils-${arch}-Test" ${arch} SOURCES FuzzedDataProviderUnittest.cpp ${COMPILER_RT_GTEST_SOURCE} - DEPS llvm_gtest ${LIBFUZZER_TEST_RUNTIME_DEPS} ${COMPILER_RT_SOURCE_DIR}/include/fuzzer/FuzzedDataProvider.h + DEPS ${LIBFUZZER_TEST_RUNTIME_DEPS} ${COMPILER_RT_SOURCE_DIR}/include/fuzzer/FuzzedDataProvider.h CFLAGS ${LIBFUZZER_UNITTEST_CFLAGS} ${LIBFUZZER_TEST_RUNTIME_CFLAGS} LINK_FLAGS ${LIBFUZZER_UNITTEST_LINK_FLAGS} ${LIBFUZZER_TEST_RUNTIME_LINK_FLAGS}) set_target_properties(FuzzedDataProviderUnitTests PROPERTIES diff --git a/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt b/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt index 4915c83d49ca9e31416d3f7d2e5f3d5e089aee0c..2ec332ea74c1370daefe75e9b1cc9b846dd3b42a 100644 --- a/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt +++ b/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt @@ -74,7 +74,7 @@ if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST GWP_ASAN_SUPPORTED_ARCH) GwpAsanUnitTests "GwpAsan-${arch}-Test" ${arch} SOURCES ${GWP_ASAN_UNITTESTS} ${COMPILER_RT_GTEST_SOURCE} RUNTIME ${GWP_ASAN_TEST_RUNTIME} - DEPS llvm_gtest ${GWP_ASAN_UNIT_TEST_HEADERS} + DEPS ${GWP_ASAN_UNIT_TEST_HEADERS} CFLAGS ${GWP_ASAN_UNITTEST_CFLAGS} LINK_FLAGS ${GWP_ASAN_UNITTEST_LINK_FLAGS}) set_target_properties(GwpAsanUnitTests PROPERTIES diff --git a/compiler-rt/lib/hwasan/hwasan_allocation_functions.cpp b/compiler-rt/lib/hwasan/hwasan_allocation_functions.cpp index 75d91ed09ce1b442fb1acbf8aabf87f10dd5ac71..9af09e2a4bedd46efa7176e59d1cd5953246eb98 100644 --- a/compiler-rt/lib/hwasan/hwasan_allocation_functions.cpp +++ b/compiler-rt/lib/hwasan/hwasan_allocation_functions.cpp @@ -184,7 +184,7 @@ INTERCEPTOR_ALIAS(void *, malloc, SIZE_T size); INTERCEPTOR_ALIAS(void *, memalign, SIZE_T alignment, SIZE_T size); INTERCEPTOR_ALIAS(void *, pvalloc, SIZE_T size); INTERCEPTOR_ALIAS(void, cfree, void *ptr); -INTERCEPTOR_ALIAS(__sanitizer_struct_mallinfo, mallinfo); +INTERCEPTOR_ALIAS(__sanitizer_struct_mallinfo, mallinfo,); INTERCEPTOR_ALIAS(int, mallopt, int cmd, int value); INTERCEPTOR_ALIAS(void, malloc_stats, void); # endif diff --git a/compiler-rt/lib/hwasan/hwasan_checks.h b/compiler-rt/lib/hwasan/hwasan_checks.h index 0911af30dcb8fc4fba11b383fe689521d7cd2dbe..735d21a5db774687ce81058b4beddaf0cdaf5e11 100644 --- a/compiler-rt/lib/hwasan/hwasan_checks.h +++ b/compiler-rt/lib/hwasan/hwasan_checks.h @@ -140,7 +140,6 @@ __attribute__((always_inline, nodebug)) static inline uptr ShortTagSize( __attribute__((always_inline, nodebug)) static inline bool PossiblyShortTagMatches(tag_t mem_tag, uptr ptr, uptr sz) { - DCHECK(IsAligned(ptr, kShadowAlignment)); tag_t ptr_tag = GetTagFromPointer(ptr); if (ptr_tag == mem_tag) return true; diff --git a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp index 96df4dd0c24d7d3db28fa2557cf63da0f295e33f..08ae435b8214ae345441fb145833194f54db56a1 100644 --- a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp +++ b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp @@ -336,8 +336,8 @@ INTERCEPTOR(int, pthread_timedjoin_np, void *thread, void **ret, DEFINE_REAL_PTHREAD_FUNCTIONS -DEFINE_REAL(int, vfork) -DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork) +DEFINE_REAL(int, vfork,) +DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork,) // Get and/or change the set of blocked signals. extern "C" int sigprocmask(int __how, const __hw_sigset_t *__restrict __set, @@ -520,6 +520,7 @@ void InitializeInterceptors() { CHECK_EQ(inited, 0); # if HWASAN_WITH_INTERCEPTORS + __interception::DoesNotSupportStaticLinking(); InitializeCommonInterceptors(); (void)(read_iovec); diff --git a/compiler-rt/lib/interception/interception.h b/compiler-rt/lib/interception/interception.h index 00bcd979638b537bdafb63140d0c9f1c8713a329..38c152952e323269af485ee386d621288d93f145 100644 --- a/compiler-rt/lib/interception/interception.h +++ b/compiler-rt/lib/interception/interception.h @@ -204,11 +204,11 @@ const interpose_substitution substitution_##func_name[] \ ".type " SANITIZER_STRINGIFY(TRAMPOLINE(func)) ", " \ ASM_TYPE_FUNCTION_STR "\n" \ SANITIZER_STRINGIFY(TRAMPOLINE(func)) ":\n" \ - SANITIZER_STRINGIFY(CFI_STARTPROC) "\n" \ + C_ASM_STARTPROC "\n" \ C_ASM_TAIL_CALL(SANITIZER_STRINGIFY(TRAMPOLINE(func)), \ "__interceptor_" \ SANITIZER_STRINGIFY(ASM_PREEMPTIBLE_SYM(func))) "\n" \ - SANITIZER_STRINGIFY(CFI_ENDPROC) "\n" \ + C_ASM_ENDPROC "\n" \ ".size " SANITIZER_STRINGIFY(TRAMPOLINE(func)) ", " \ ".-" SANITIZER_STRINGIFY(TRAMPOLINE(func)) "\n" \ ); diff --git a/compiler-rt/lib/interception/interception_win.cpp b/compiler-rt/lib/interception/interception_win.cpp index 1829358705fe82290ee97388d9e1dcb5c37a27e7..a638e66eccee58f13c5d052f1d8f11c588290d66 100644 --- a/compiler-rt/lib/interception/interception_win.cpp +++ b/compiler-rt/lib/interception/interception_win.cpp @@ -339,7 +339,7 @@ struct TrampolineMemoryRegion { uptr max_size; }; -UNUSED static const uptr kTrampolineScanLimitRange = 1 << 31; // 2 gig +UNUSED static const uptr kTrampolineScanLimitRange = 1ull << 31; // 2 gig static const int kMaxTrampolineRegion = 1024; static TrampolineMemoryRegion TrampolineRegions[kMaxTrampolineRegion]; @@ -479,6 +479,8 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { switch (*(u8*)address) { case 0x90: // 90 : nop + case 0xC3: // C3 : ret (for small/empty function interception + case 0xCC: // CC : int 3 i.e. registering weak functions) return 1; case 0x50: // push eax / rax @@ -502,7 +504,6 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { // Cannot overwrite control-instruction. Return 0 to indicate failure. case 0xE9: // E9 XX XX XX XX : jmp <label> case 0xE8: // E8 XX XX XX XX : call <func> - case 0xC3: // C3 : ret case 0xEB: // EB XX : jmp XX (short jump) case 0x70: // 7Y YY : jy XX (short conditional jump) case 0x71: @@ -545,6 +546,11 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { return 7; } + switch (0x000000FF & *(u32 *)address) { + case 0xc2: // C2 XX XX : ret XX (needed for registering weak functions) + return 3; + } + # if SANITIZER_WINDOWS_x64 switch (*(u8*)address) { case 0xA1: // A1 XX XX XX XX XX XX XX XX : @@ -605,6 +611,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0xc18b4c: // 4C 8B C1 : mov r8, rcx case 0xd2b60f: // 0f b6 d2 : movzx edx, dl case 0xca2b48: // 48 2b ca : sub rcx, rdx + case 0xca3b48: // 48 3b ca : cmp rcx, rdx case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax] case 0xc00b4d: // 3d 0b c0 : or r8, r8 case 0xc08b41: // 41 8b c0 : mov eax, r8d @@ -624,6 +631,8 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0x058b48: // 48 8b 05 XX XX XX XX : // mov rax, QWORD PTR [rip + XXXXXXXX] + case 0x058d48: // 48 8d 05 XX XX XX XX : + // lea rax, QWORD PTR [rip + XXXXXXXX] case 0x25ff48: // 48 ff 25 XX XX XX XX : // rex.W jmp QWORD PTR [rip + XXXXXXXX] case 0x158D4C: // 4c 8d 15 XX XX XX XX : lea r10, [rip + XX] diff --git a/compiler-rt/lib/interception/tests/CMakeLists.txt b/compiler-rt/lib/interception/tests/CMakeLists.txt index 644a57664cc490dc7757907470a5380248ae5e05..0a235c662af3b055e56fbc0b680d5be17a603fd5 100644 --- a/compiler-rt/lib/interception/tests/CMakeLists.txt +++ b/compiler-rt/lib/interception/tests/CMakeLists.txt @@ -107,7 +107,6 @@ macro(add_interception_tests_for_arch arch) RUNTIME ${INTERCEPTION_COMMON_LIB} SOURCES ${INTERCEPTION_UNITTESTS} ${COMPILER_RT_GTEST_SOURCE} COMPILE_DEPS ${INTERCEPTION_TEST_HEADERS} - DEPS llvm_gtest CFLAGS ${INTERCEPTION_TEST_CFLAGS_COMMON} LINK_FLAGS ${INTERCEPTION_TEST_LINK_FLAGS_COMMON}) endmacro() diff --git a/compiler-rt/lib/lsan/lsan_interceptors.cpp b/compiler-rt/lib/lsan/lsan_interceptors.cpp index 885f7ad5ddba96178fdf3d55df40922dab072cc5..1fd0010f9ea936002b034e5344f3704fd51a8e15 100644 --- a/compiler-rt/lib/lsan/lsan_interceptors.cpp +++ b/compiler-rt/lib/lsan/lsan_interceptors.cpp @@ -543,6 +543,7 @@ namespace __lsan { void InitializeInterceptors() { // Fuchsia doesn't use interceptors that require any setup. #if !SANITIZER_FUCHSIA + __interception::DoesNotSupportStaticLinking(); InitializeSignalInterceptors(); INTERCEPT_FUNCTION(malloc); diff --git a/compiler-rt/lib/memprof/memprof_allocator.h b/compiler-rt/lib/memprof/memprof_allocator.h index f583cee020e4ffd866e587d9dc01e9be88b9b5a2..89e924f80d41ad5f983907f93240c54394e92088 100644 --- a/compiler-rt/lib/memprof/memprof_allocator.h +++ b/compiler-rt/lib/memprof/memprof_allocator.h @@ -46,7 +46,11 @@ struct MemprofMapUnmapCallback { void OnUnmap(uptr p, uptr size) const; }; +#if SANITIZER_APPLE constexpr uptr kAllocatorSpace = 0x600000000000ULL; +#else +constexpr uptr kAllocatorSpace = 0x500000000000ULL; +#endif constexpr uptr kAllocatorSize = 0x40000000000ULL; // 4T. typedef DefaultSizeClassMap SizeClassMap; template <typename AddressSpaceViewTy> diff --git a/compiler-rt/lib/msan/msan.cpp b/compiler-rt/lib/msan/msan.cpp index 3cdf10c149902c276282ff684fb1e864290dd3bd..a2fc27de1901b42ef596f084bb58a1239341d339 100644 --- a/compiler-rt/lib/msan/msan.cpp +++ b/compiler-rt/lib/msan/msan.cpp @@ -467,7 +467,7 @@ void __msan_init() { __msan_clear_on_return(); if (__msan_get_track_origins()) VPrintf(1, "msan_track_origins\n"); - if (!InitShadow(__msan_get_track_origins())) { + if (!InitShadowWithReExec(__msan_get_track_origins())) { Printf("FATAL: MemorySanitizer can not mmap the shadow memory.\n"); Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n"); Printf("FATAL: Disabling ASLR is known to cause this error.\n"); diff --git a/compiler-rt/lib/msan/msan.h b/compiler-rt/lib/msan/msan.h index 710447a3e1a35709a6bb325836c78d8a7c6429e3..7fb58be67a02cdaed5173f196506e04fcb3669d6 100644 --- a/compiler-rt/lib/msan/msan.h +++ b/compiler-rt/lib/msan/msan.h @@ -33,12 +33,18 @@ struct MappingDesc { uptr start; uptr end; enum Type { - INVALID, APP, SHADOW, ORIGIN + INVALID = 1, + ALLOCATOR = 2, + APP = 4, + SHADOW = 8, + ORIGIN = 16, } type; const char *name; }; - +// Note: MappingDesc::ALLOCATOR entries are only used to check for memory +// layout compatibility. The actual allocation settings are in +// msan_allocator.cpp, which need to be kept in sync. #if SANITIZER_LINUX && defined(__mips64) // MIPS64 maps: @@ -84,7 +90,8 @@ const MappingDesc kMemoryLayout[] = { {0X0B00000000000, 0X0C00000000000, MappingDesc::SHADOW, "shadow-10-13"}, {0X0C00000000000, 0X0D00000000000, MappingDesc::INVALID, "invalid"}, {0X0D00000000000, 0X0E00000000000, MappingDesc::ORIGIN, "origin-10-13"}, - {0X0E00000000000, 0X1000000000000, MappingDesc::APP, "app-15"}, + {0x0E00000000000, 0x0E40000000000, MappingDesc::ALLOCATOR, "allocator"}, + {0X0E40000000000, 0X1000000000000, MappingDesc::APP, "app-15"}, }; # define MEM_TO_SHADOW(mem) ((uptr)mem ^ 0xB00000000000ULL) # define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x200000000000ULL) @@ -106,7 +113,8 @@ const MappingDesc kMemoryLayout[] = { {0x510000000000ULL, 0x600000000000ULL, MappingDesc::APP, "app-2"}, {0x600000000000ULL, 0x610000000000ULL, MappingDesc::ORIGIN, "origin-1"}, {0x610000000000ULL, 0x700000000000ULL, MappingDesc::INVALID, "invalid"}, - {0x700000000000ULL, 0x800000000000ULL, MappingDesc::APP, "app-3"}}; + {0x700000000000ULL, 0x740000000000ULL, MappingDesc::ALLOCATOR, "allocator"}, + {0x740000000000ULL, 0x800000000000ULL, MappingDesc::APP, "app-3"}}; # define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x500000000000ULL) # define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x100000000000ULL) @@ -118,7 +126,8 @@ const MappingDesc kMemoryLayout[] = { {0x180200000000ULL, 0x1C0000000000ULL, MappingDesc::INVALID, "invalid"}, {0x1C0000000000ULL, 0x2C0200000000ULL, MappingDesc::ORIGIN, "origin"}, {0x2C0200000000ULL, 0x300000000000ULL, MappingDesc::INVALID, "invalid"}, - {0x300000000000ULL, 0x800000000000ULL, MappingDesc::APP, "high memory"}}; + {0x300000000000ULL, 0x320000000000ULL, MappingDesc::ALLOCATOR, "allocator"}, + {0x320000000000ULL, 0x800000000000ULL, MappingDesc::APP, "high memory"}}; // Various kernels use different low end ranges but we can combine them into one // big range. They also use different high end ranges but we can map them all to @@ -141,7 +150,8 @@ const MappingDesc kMemoryLayout[] = { {0x180000000000ULL, 0x1C0000000000ULL, MappingDesc::INVALID, "invalid"}, {0x1C0000000000ULL, 0x2C0000000000ULL, MappingDesc::ORIGIN, "origin"}, {0x2C0000000000ULL, 0x440000000000ULL, MappingDesc::INVALID, "invalid"}, - {0x440000000000ULL, 0x500000000000ULL, MappingDesc::APP, "high memory"}}; + {0x440000000000ULL, 0x460000000000ULL, MappingDesc::ALLOCATOR, "allocator"}, + {0x460000000000ULL, 0x500000000000ULL, MappingDesc::APP, "high memory"}}; #define MEM_TO_SHADOW(mem) \ ((((uptr)(mem)) & ~0xC00000000000ULL) + 0x080000000000ULL) @@ -208,7 +218,8 @@ const MappingDesc kMemoryLayout[] = { {0x510000000000ULL, 0x600000000000ULL, MappingDesc::APP, "app-2"}, {0x600000000000ULL, 0x610000000000ULL, MappingDesc::ORIGIN, "origin-1"}, {0x610000000000ULL, 0x700000000000ULL, MappingDesc::INVALID, "invalid"}, - {0x700000000000ULL, 0x800000000000ULL, MappingDesc::APP, "app-3"}}; + {0x700000000000ULL, 0x740000000000ULL, MappingDesc::ALLOCATOR, "allocator"}, + {0x740000000000ULL, 0x800000000000ULL, MappingDesc::APP, "app-3"}}; #define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x500000000000ULL) #define SHADOW_TO_ORIGIN(mem) (((uptr)(mem)) + 0x100000000000ULL) @@ -223,20 +234,22 @@ const uptr kMemoryLayoutSize = sizeof(kMemoryLayout) / sizeof(kMemoryLayout[0]); #ifndef __clang__ __attribute__((optimize("unroll-loops"))) #endif -inline bool addr_is_type(uptr addr, MappingDesc::Type mapping_type) { +inline bool +addr_is_type(uptr addr, int mapping_types) { // It is critical for performance that this loop is unrolled (because then it is // simplified into just a few constant comparisons). #ifdef __clang__ #pragma unroll #endif for (unsigned i = 0; i < kMemoryLayoutSize; ++i) - if (kMemoryLayout[i].type == mapping_type && + if ((kMemoryLayout[i].type & mapping_types) && addr >= kMemoryLayout[i].start && addr < kMemoryLayout[i].end) return true; return false; } -#define MEM_IS_APP(mem) addr_is_type((uptr)(mem), MappingDesc::APP) +#define MEM_IS_APP(mem) \ + (addr_is_type((uptr)(mem), MappingDesc::APP | MappingDesc::ALLOCATOR)) #define MEM_IS_SHADOW(mem) addr_is_type((uptr)(mem), MappingDesc::SHADOW) #define MEM_IS_ORIGIN(mem) addr_is_type((uptr)(mem), MappingDesc::ORIGIN) @@ -250,7 +263,7 @@ extern bool msan_init_is_running; extern int msan_report_count; bool ProtectRange(uptr beg, uptr end); -bool InitShadow(bool init_origins); +bool InitShadowWithReExec(bool init_origins); char *GetProcSelfMaps(); void InitializeInterceptors(); diff --git a/compiler-rt/lib/msan/msan_allocator.cpp b/compiler-rt/lib/msan/msan_allocator.cpp index 0b2dd2b2f1883d7f235b66645267cc39134fd4b7..b1bc5b9390f75b5a70e2ac34e6ad7988552f9b5d 100644 --- a/compiler-rt/lib/msan/msan_allocator.cpp +++ b/compiler-rt/lib/msan/msan_allocator.cpp @@ -48,6 +48,9 @@ struct MsanMapUnmapCallback { } }; +// Note: to ensure that the allocator is compatible with the application memory +// layout (especially with high-entropy ASLR), kSpaceBeg and kSpaceSize must be +// duplicated as MappingDesc::ALLOCATOR in msan.h. #if defined(__mips64) static const uptr kMaxAllowedMallocSize = 2UL << 30; diff --git a/compiler-rt/lib/msan/msan_interceptors.cpp b/compiler-rt/lib/msan/msan_interceptors.cpp index 2c9f2c01e14b061be12e4effabfeb266d91bc875..9abf2406332588a814c49436018e8d951c7cf906 100644 --- a/compiler-rt/lib/msan/msan_interceptors.cpp +++ b/compiler-rt/lib/msan/msan_interceptors.cpp @@ -255,7 +255,7 @@ static NOINLINE void clear_mallinfo(T *sret) { #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD // Interceptors use NRVO and assume that sret will be pre-allocated in // caller frame. -INTERCEPTOR(__sanitizer_struct_mallinfo, mallinfo) { +INTERCEPTOR(__sanitizer_struct_mallinfo, mallinfo,) { __sanitizer_struct_mallinfo sret; clear_mallinfo(&sret); return sret; @@ -1762,6 +1762,8 @@ void InitializeInterceptors() { static int inited = 0; CHECK_EQ(inited, 0); + __interception::DoesNotSupportStaticLinking(); + new(interceptor_ctx()) InterceptorContext(); InitializeCommonInterceptors(); diff --git a/compiler-rt/lib/msan/msan_linux.cpp b/compiler-rt/lib/msan/msan_linux.cpp index c7ecb7cad56661901df0d9a30ba3bbf49b0cba3b..c68aec60ae13ea36bc3abaf3a89fc7447dc82a03 100644 --- a/compiler-rt/lib/msan/msan_linux.cpp +++ b/compiler-rt/lib/msan/msan_linux.cpp @@ -20,6 +20,9 @@ # include <signal.h> # include <stdio.h> # include <stdlib.h> +# if SANITIZER_LINUX +# include <sys/personality.h> +# endif # include <sys/resource.h> # include <sys/time.h> # include <unistd.h> @@ -43,11 +46,13 @@ void ReportMapRange(const char *descr, uptr beg, uptr size) { } } -static bool CheckMemoryRangeAvailability(uptr beg, uptr size) { +static bool CheckMemoryRangeAvailability(uptr beg, uptr size, bool verbose) { if (size > 0) { uptr end = beg + size - 1; if (!MemoryRangeIsAvailable(beg, end)) { - Printf("FATAL: Memory range 0x%zx - 0x%zx is not available.\n", beg, end); + if (verbose) + Printf("FATAL: Memory range 0x%zx - 0x%zx is not available.\n", beg, + end); return false; } } @@ -86,7 +91,7 @@ static void CheckMemoryLayoutSanity() { CHECK(addr_is_type(start, type)); CHECK(addr_is_type((start + end) / 2, type)); CHECK(addr_is_type(end - 1, type)); - if (type == MappingDesc::APP) { + if (type == MappingDesc::APP || type == MappingDesc::ALLOCATOR) { uptr addr = start; CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr))); CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr))); @@ -106,7 +111,7 @@ static void CheckMemoryLayoutSanity() { } } -bool InitShadow(bool init_origins) { +static bool InitShadow(bool init_origins, bool dry_run) { // Let user know mapping parameters first. VPrintf(1, "__msan_init %p\n", reinterpret_cast<void *>(&__msan_init)); for (unsigned i = 0; i < kMemoryLayoutSize; ++i) @@ -116,8 +121,9 @@ bool InitShadow(bool init_origins) { CheckMemoryLayoutSanity(); if (!MEM_IS_APP(&__msan_init)) { - Printf("FATAL: Code %p is out of application range. Non-PIE build?\n", - reinterpret_cast<void *>(&__msan_init)); + if (!dry_run) + Printf("FATAL: Code %p is out of application range. Non-PIE build?\n", + reinterpret_cast<void *>(&__msan_init)); return false; } @@ -138,20 +144,26 @@ bool InitShadow(bool init_origins) { bool protect = type == MappingDesc::INVALID || (!init_origins && type == MappingDesc::ORIGIN); CHECK(!(map && protect)); - if (!map && !protect) - CHECK(type == MappingDesc::APP); + if (!map && !protect) { + CHECK(type == MappingDesc::APP || type == MappingDesc::ALLOCATOR); + + if (dry_run && type == MappingDesc::ALLOCATOR && + !CheckMemoryRangeAvailability(start, size, !dry_run)) + return false; + } if (map) { - if (!CheckMemoryRangeAvailability(start, size)) + if (dry_run && !CheckMemoryRangeAvailability(start, size, !dry_run)) return false; - if (!MmapFixedSuperNoReserve(start, size, kMemoryLayout[i].name)) + if (!dry_run && + !MmapFixedSuperNoReserve(start, size, kMemoryLayout[i].name)) return false; - if (common_flags()->use_madv_dontdump) + if (!dry_run && common_flags()->use_madv_dontdump) DontDumpShadowMemory(start, size); } if (protect) { - if (!CheckMemoryRangeAvailability(start, size)) + if (dry_run && !CheckMemoryRangeAvailability(start, size, !dry_run)) return false; - if (!ProtectMemoryRange(start, size, kMemoryLayout[i].name)) + if (!dry_run && !ProtectMemoryRange(start, size, kMemoryLayout[i].name)) return false; } } @@ -159,6 +171,35 @@ bool InitShadow(bool init_origins) { return true; } +bool InitShadowWithReExec(bool init_origins) { + // Start with dry run: check layout is ok, but don't print warnings because + // warning messages will cause tests to fail (even if we successfully re-exec + // after the warning). + bool success = InitShadow(init_origins, true); + if (!success) { +# if SANITIZER_LINUX + // Perhaps ASLR entropy is too high. If ASLR is enabled, re-exec without it. + int old_personality = personality(0xffffffff); + bool aslr_on = + (old_personality != -1) && ((old_personality & ADDR_NO_RANDOMIZE) == 0); + + if (aslr_on) { + VReport(1, + "WARNING: MemorySanitizer: memory layout is incompatible, " + "possibly due to high-entropy ASLR.\n" + "Re-execing with fixed virtual address space.\n" + "N.B. reducing ASLR entropy is preferable.\n"); + CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1); + ReExec(); + } +# endif + } + + // The earlier dry run didn't actually map or protect anything. Run again in + // non-dry run mode. + return success && InitShadow(init_origins, false); +} + static void MsanAtExit(void) { if (flags()->print_stats && (flags()->atexit || msan_report_count > 0)) ReportStats(); diff --git a/compiler-rt/lib/msan/tests/CMakeLists.txt b/compiler-rt/lib/msan/tests/CMakeLists.txt index 412a0f6b3de7f20d979bb26d4489b5343b2878a3..e0771dd5a1a7e197074defb0f1300899030e24ae 100644 --- a/compiler-rt/lib/msan/tests/CMakeLists.txt +++ b/compiler-rt/lib/msan/tests/CMakeLists.txt @@ -69,9 +69,9 @@ macro(msan_compile obj_list source arch kind cflags) sanitizer_test_compile( ${obj_list} ${source} ${arch} KIND ${kind} - COMPILE_DEPS ${MSAN_UNITTEST_HEADERS} - DEPS llvm_gtest msan - CFLAGS -isystem ${CMAKE_CURRENT_BINARY_DIR}/../libcxx_msan_${arch}/include/c++/v1 + COMPILE_DEPS ${MSAN_UNITTEST_HEADERS} libcxx_msan_${arch}-build + DEPS msan + CFLAGS -isystem ${MSAN_LIBCXX_DIR}/../include/c++/v1 ${MSAN_UNITTEST_INSTRUMENTED_CFLAGS} ${cflags} ) endmacro() @@ -120,9 +120,7 @@ macro(add_msan_tests_for_arch arch kind cflags) set(MSAN_TEST_DEPS ${MSAN_TEST_OBJECTS} libcxx_msan_${arch}-build ${MSAN_LOADABLE_SO} "${MSAN_LIBCXX_DIR}/libc++.a" "${MSAN_LIBCXX_DIR}/libc++abi.a") - if(NOT COMPILER_RT_STANDALONE_BUILD) - list(APPEND MSAN_TEST_DEPS msan) - endif() + list(APPEND MSAN_TEST_DEPS msan libcxx_msan_${arch}-build) get_target_flags_for_arch(${arch} TARGET_LINK_FLAGS) add_compiler_rt_test(MsanUnitTests "Msan-${arch}${kind}-Test" ${arch} OBJECTS ${MSAN_TEST_OBJECTS} "${MSAN_LIBCXX_DIR}/libc++.a" "${MSAN_LIBCXX_DIR}/libc++abi.a" diff --git a/compiler-rt/lib/orc/tests/CMakeLists.txt b/compiler-rt/lib/orc/tests/CMakeLists.txt index 2f1cb7657c2818b1e6f3290c7caa5c6a53fba187..e8f4c95b8a65775e7bf409740a5988a1e54a2afa 100644 --- a/compiler-rt/lib/orc/tests/CMakeLists.txt +++ b/compiler-rt/lib/orc/tests/CMakeLists.txt @@ -73,7 +73,7 @@ macro(add_orc_unittest testname) SOURCES ${TEST_SOURCES} ${COMPILER_RT_GTEST_SOURCE} RUNTIME "${ORC_RUNTIME_LIBS}" COMPILE_DEPS ${TEST_HEADERS} ${ORC_HEADERS} - DEPS llvm_gtest ${ORC_DEPS} + DEPS ${ORC_DEPS} CFLAGS ${ORC_UNITTEST_CFLAGS} ${COMPILER_RT_GTEST_CFLAGS} LINK_FLAGS ${ORC_UNITTEST_LINK_FLAGS}) endif() diff --git a/compiler-rt/lib/sanitizer_common/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/CMakeLists.txt index f762524c333acf27624bc349b8d8e77ee8f0d5f6..f2b4ac72ae157384305a5cb36937505760263d3d 100644 --- a/compiler-rt/lib/sanitizer_common/CMakeLists.txt +++ b/compiler-rt/lib/sanitizer_common/CMakeLists.txt @@ -218,6 +218,8 @@ include_directories(..) set(SANITIZER_COMMON_DEFINITIONS HAVE_RPC_XDR_H=${HAVE_RPC_XDR_H}) +# note: L not I, this is nodefaultlibs for msvc +append_list_if(MSVC /Zl SANITIZER_COMMON_CFLAGS) set(SANITIZER_CFLAGS ${SANITIZER_COMMON_CFLAGS}) # Too many existing bugs, needs cleanup. diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h index 34a64f26478fd5e5f1bff8912ced9cf340761e9f..6e73065d7f53c532aa6b93a4ba71e8c9d48671f9 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h @@ -639,7 +639,8 @@ class SizeClassAllocator64 { static_assert(kRegionSize >= SizeClassMap::kMaxSize, "Region size exceed largest size"); // kRegionSize must be <= 2^36, see CompactPtrT. - COMPILER_CHECK((kRegionSize) <= (1ULL << (SANITIZER_WORDSIZE / 2 + 4))); + COMPILER_CHECK((kRegionSize) <= + (1ULL << (sizeof(CompactPtrT) * 8 + kCompactPtrScale))); // Call mmap for user memory with at least this size. static const uptr kUserMapSize = 1 << 18; // Call mmap for metadata memory with at least this size. diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_asm.h b/compiler-rt/lib/sanitizer_common/sanitizer_asm.h index 3af66a4e44998822dc300e308c53f9582cbd4088..30e9d15184e5d55690576306ec8eadde93424d80 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_asm.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_asm.h @@ -42,6 +42,16 @@ # define CFI_RESTORE(reg) #endif +#if defined(__aarch64__) && defined(__ARM_FEATURE_BTI_DEFAULT) +# define ASM_STARTPROC CFI_STARTPROC; hint #34 +# define C_ASM_STARTPROC SANITIZER_STRINGIFY(CFI_STARTPROC) "\nhint #34" +#else +# define ASM_STARTPROC CFI_STARTPROC +# define C_ASM_STARTPROC SANITIZER_STRINGIFY(CFI_STARTPROC) +#endif +#define ASM_ENDPROC CFI_ENDPROC +#define C_ASM_ENDPROC SANITIZER_STRINGIFY(CFI_ENDPROC) + #if defined(__x86_64__) || defined(__i386__) || defined(__sparc__) # define ASM_TAIL_CALL jmp #elif defined(__arm__) || defined(__aarch64__) || defined(__mips__) || \ @@ -114,9 +124,9 @@ .globl __interceptor_trampoline_##name; \ ASM_TYPE_FUNCTION(__interceptor_trampoline_##name); \ __interceptor_trampoline_##name: \ - CFI_STARTPROC; \ + ASM_STARTPROC; \ ASM_TAIL_CALL ASM_PREEMPTIBLE_SYM(__interceptor_##name); \ - CFI_ENDPROC; \ + ASM_ENDPROC; \ ASM_SIZE(__interceptor_trampoline_##name) # define ASM_INTERCEPTOR_TRAMPOLINE_SUPPORT 1 # endif // Architecture supports interceptor trampoline diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index a1be676730a78688d12a2383837eb2fad9b9ba9f..1df61e79f7d84abc36722245e9eb58a81a6df593 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -7650,9 +7650,9 @@ static void write_protoent(void *ctx, struct __sanitizer_protoent *p) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->p_aliases, pp_size * sizeof(char *)); } -INTERCEPTOR(struct __sanitizer_protoent *, getprotoent) { +INTERCEPTOR(struct __sanitizer_protoent *, getprotoent,) { void *ctx; - COMMON_INTERCEPTOR_ENTER(ctx, getprotoent); + COMMON_INTERCEPTOR_ENTER(ctx, getprotoent,); struct __sanitizer_protoent *p = REAL(getprotoent)(); if (p) write_protoent(ctx, p); @@ -7739,9 +7739,9 @@ INTERCEPTOR(int, getprotobynumber_r, int num, #endif #if SANITIZER_INTERCEPT_NETENT -INTERCEPTOR(struct __sanitizer_netent *, getnetent) { +INTERCEPTOR(struct __sanitizer_netent *, getnetent,) { void *ctx; - COMMON_INTERCEPTOR_ENTER(ctx, getnetent); + COMMON_INTERCEPTOR_ENTER(ctx, getnetent,); struct __sanitizer_netent *n = REAL(getnetent)(); if (n) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n)); @@ -9903,9 +9903,9 @@ INTERCEPTOR(char *, fdevname_r, int fd, char *buf, SIZE_T len) { #endif #if SANITIZER_INTERCEPT_GETUSERSHELL -INTERCEPTOR(char *, getusershell) { +INTERCEPTOR(char *, getusershell,) { void *ctx; - COMMON_INTERCEPTOR_ENTER(ctx, getusershell); + COMMON_INTERCEPTOR_ENTER(ctx, getusershell,); char *res = REAL(getusershell)(); if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, internal_strlen(res) + 1); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc index b3161690f3ce8a74168aa6b7d84e27dae124f091..14615f9668dea647937e1712dc0d5f19cdd03442 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc @@ -38,6 +38,10 @@ // Called before fork syscall. // COMMON_SYSCALL_POST_FORK(long res) // Called after fork syscall. +// COMMON_SYSCALL_BLOCKING_START() +// Called before blocking syscall. +// COMMON_SYSCALL_BLOCKING_END() +// Called after blocking syscall. //===----------------------------------------------------------------------===// #include "sanitizer_platform.h" @@ -85,6 +89,16 @@ {} # endif +# ifndef COMMON_SYSCALL_BLOCKING_START +# define COMMON_SYSCALL_BLOCKING_START() \ + {} +# endif + +# ifndef COMMON_SYSCALL_BLOCKING_END +# define COMMON_SYSCALL_BLOCKING_END() \ + {} +# endif + // FIXME: do some kind of PRE_READ for all syscall arguments (int(s) and such). extern "C" { @@ -3176,6 +3190,18 @@ POST_SYSCALL(sigaltstack)(long res, void *ss, void *oss) { } } } + +PRE_SYSCALL(futex) +(void *uaddr, long futex_op, long val, void *timeout, void *uaddr2, long val3) { + COMMON_SYSCALL_BLOCKING_START(); +} + +POST_SYSCALL(futex) +(long res, void *uaddr, long futex_op, long val, void *timeout, void *uaddr2, + long val3) { + COMMON_SYSCALL_BLOCKING_END(); +} + } // extern "C" # undef PRE_SYSCALL diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp index ef1fc35497439602ed469e13b23224ed437d5a9f..ece2d7d63dd6197741a4afa39f08c873520d9e91 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp @@ -104,7 +104,27 @@ static void setlim(int res, rlim_t lim) { void DisableCoreDumperIfNecessary() { if (common_flags()->disable_coredump) { - setlim(RLIMIT_CORE, 0); + rlimit rlim; + CHECK_EQ(0, getrlimit(RLIMIT_CORE, &rlim)); + // On Linux, if the kernel.core_pattern sysctl starts with a '|' (i.e. it + // is being piped to a coredump handler such as systemd-coredumpd), the + // kernel ignores RLIMIT_CORE (since we aren't creating a file in the file + // system) except for the magic value of 1, which disables coredumps when + // piping. 1 byte is too small for any kind of valid core dump, so it + // also disables coredumps if kernel.core_pattern creates files directly. + // While most piped coredump handlers do respect the crashing processes' + // RLIMIT_CORE, this is notable not the case for Debian's systemd-coredump + // due to a local patch that changes sysctl.d/50-coredump.conf to ignore + // the specified limit and instead use RLIM_INFINITY. + // + // The alternative to using RLIMIT_CORE=1 would be to use prctl() with the + // PR_SET_DUMPABLE flag, however that also prevents ptrace(), so makes it + // impossible to attach a debugger. + // + // Note: we use rlim_max in the Min() call here since that is the upper + // limit for what can be set without getting an EINVAL error. + rlim.rlim_cur = Min<rlim_t>(SANITIZER_LINUX ? 1 : 0, rlim.rlim_max); + CHECK_EQ(0, setrlimit(RLIMIT_CORE, &rlim)); } } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_printf.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_printf.cpp index 62c1cf4abe4256bfe743e0f16f62eae09181e3f2..24511720bd99fadd74a7204b51dae8b50f347251 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_printf.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_printf.cpp @@ -54,7 +54,7 @@ static int AppendNumber(char **buff, const char *buff_end, u64 absolute_value, uptr num_buffer[kMaxLen]; int pos = 0; do { - RAW_CHECK_MSG((uptr)pos < kMaxLen, "AppendNumber buffer overflow"); + RAW_CHECK_MSG((uptr)pos < kMaxLen, "AppendNumber buffer overflow",); num_buffer[pos++] = absolute_value % base; absolute_value /= base; } while (absolute_value > 0); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_bsd.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_bsd.cpp index 7c2d8e6f1731311a3c3b2ea9781180ecc0188414..7d7c009f644426775b7c5805d4a1ab6daf5e369c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_bsd.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_bsd.cpp @@ -42,6 +42,19 @@ void GetMemoryProfile(fill_profile_f cb, uptr *stats) { cb(0, InfoProc->ki_rssize * GetPageSizeCached(), false, stats); UnmapOrDie(InfoProc, Size, true); } +#elif SANITIZER_NETBSD +void GetMemoryProfile(fill_profile_f cb, uptr *stats) { + struct kinfo_proc2 *InfoProc; + uptr Len = sizeof(*InfoProc); + uptr Size = Len; + const int Mib[] = {CTL_KERN, KERN_PROC2, KERN_PROC_PID, getpid(), Size, 1}; + InfoProc = (struct kinfo_proc2 *)MmapOrDie(Size, "GetMemoryProfile()"); + CHECK_EQ( + internal_sysctl(Mib, ARRAY_SIZE(Mib), nullptr, (uptr *)InfoProc, &Len, 0), + 0); + cb(0, InfoProc->p_vm_rssize * GetPageSizeCached(), false, stats); + UnmapOrDie(InfoProc, Size, true); +} #endif void ReadProcMaps(ProcSelfMapsBuff *proc_maps) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cpp index a7805ad1b083b0b5bb75056a339332675d75eb94..7214a2b9ea4681aaf007b20c6bb6636e7f4e3a05 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_common.cpp @@ -145,7 +145,7 @@ void MemoryMappingLayout::DumpListOfModules( } } -#if SANITIZER_LINUX || SANITIZER_ANDROID || SANITIZER_SOLARIS || SANITIZER_NETBSD +#if SANITIZER_LINUX || SANITIZER_ANDROID || SANITIZER_SOLARIS void GetMemoryProfile(fill_profile_f cb, uptr *stats) { char *smaps = nullptr; uptr smaps_cap = 0; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.h b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.h index 10361a32034452e7306012db2a4affa5dcf10abd..e39cb891575e4c862a455057665717a052bc76c9 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace_printer.h @@ -30,10 +30,15 @@ class StackTracePrinter { virtual void RenderFrame(InternalScopedString *buffer, const char *format, int frame_no, uptr address, const AddressInfo *info, - bool vs_style, - const char *strip_path_prefix = "") = 0; + bool vs_style, const char *strip_path_prefix = "") { + // Should be pure virtual, but we can't depend on __cxa_pure_virtual. + UNIMPLEMENTED(); + } - virtual bool RenderNeedsSymbolization(const char *format) = 0; + virtual bool RenderNeedsSymbolization(const char *format) { + // Should be pure virtual, but we can't depend on __cxa_pure_virtual. + UNIMPLEMENTED(); + } void RenderSourceLocation(InternalScopedString *buffer, const char *file, int line, int column, bool vs_style, @@ -44,7 +49,10 @@ class StackTracePrinter { const char *strip_path_prefix); virtual void RenderData(InternalScopedString *buffer, const char *format, const DataInfo *DI, - const char *strip_path_prefix = "") = 0; + const char *strip_path_prefix = "") { + // Should be pure virtual, but we can't depend on __cxa_pure_virtual. + UNIMPLEMENTED(); + } private: // To be called from StackTracePrinter::GetOrInit diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp index f6b157c07c6557c3ad17d294adf3d57925acdd6b..ffbaf1468ec8ff1a896548bbf2ff381d7033aec1 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_report.cpp @@ -39,8 +39,12 @@ static bool FrameIsInternal(const SymbolizedStack *frame) { internal_strstr(file, "/include/c++/") || internal_strstr(file, "/include/g++"))) return true; + if (file && internal_strstr(file, "\\compiler-rt\\lib\\")) + return true; if (module && (internal_strstr(module, "libclang_rt."))) return true; + if (module && (internal_strstr(module, "clang_rt."))) + return true; return false; } 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 7f4082a6cd190e2b5f0dcdd0231a63ce23d9a109..005bd6d584c59307f3db36fd279eb5d5b67b7efe 100755 --- a/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh +++ b/compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh @@ -144,7 +144,7 @@ if [[ ! -f ${LLVM_BUILD}/build.ninja ]]; then $LLVM_SRC fi cd ${LLVM_BUILD} -ninja LLVMSymbolize LLVMObject LLVMBinaryFormat LLVMDebugInfoDWARF LLVMSupport LLVMDebugInfoPDB LLVMDebuginfod LLVMMC LLVMDemangle LLVMTextAPI LLVMTargetParser +ninja LLVMSymbolize LLVMObject LLVMBinaryFormat LLVMDebugInfoDWARF LLVMSupport LLVMDebugInfoPDB LLVMDebuginfod LLVMMC LLVMDemangle LLVMTextAPI LLVMTargetParser LLVMCore cd ${BUILD_DIR} rm -rf ${SYMBOLIZER_BUILD} @@ -182,6 +182,7 @@ $LINK $LIBCXX_ARCHIVE_DIR/libc++.a \ $LLVM_BUILD/lib/libLLVMMC.a \ $LLVM_BUILD/lib/libLLVMTextAPI.a \ $LLVM_BUILD/lib/libLLVMTargetParser.a \ + $LLVM_BUILD/lib/libLLVMCore.a \ $ZLIB_BUILD/libz.a \ symbolizer.a \ -ignore-non-bitcode -o all.bc diff --git a/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt index 3c709e411e48be2dc90dd1ad62278ac0ad5a52b7..a3efe68715082301de774cb9308cbd10de4cd1ce 100644 --- a/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt +++ b/compiler-rt/lib/sanitizer_common/tests/CMakeLists.txt @@ -176,7 +176,6 @@ macro(add_sanitizer_tests_for_arch arch) RUNTIME "${SANITIZER_COMMON_LIB}" SOURCES ${SANITIZER_UNITTESTS} ${COMPILER_RT_GTEST_SOURCE} ${COMPILER_RT_GMOCK_SOURCE} COMPILE_DEPS ${SANITIZER_TEST_HEADERS} - DEPS llvm_gtest CFLAGS ${SANITIZER_TEST_CFLAGS_COMMON} ${extra_flags} LINK_FLAGS ${SANITIZER_TEST_LINK_FLAGS_COMMON} ${TARGET_LINK_FLAGS} ${extra_flags}) diff --git a/compiler-rt/lib/scudo/standalone/CMakeLists.txt b/compiler-rt/lib/scudo/standalone/CMakeLists.txt index 60092005cc33bbf2abefd5cea1f6dfe361e920f8..6fb4e88de3155f6b4a063a03c6ae5da42d5a2f38 100644 --- a/compiler-rt/lib/scudo/standalone/CMakeLists.txt +++ b/compiler-rt/lib/scudo/standalone/CMakeLists.txt @@ -58,6 +58,7 @@ endif() set(SCUDO_HEADERS allocator_common.h allocator_config.h + allocator_config_wrapper.h atomic_helpers.h bytemap.h checksum.h diff --git a/compiler-rt/lib/scudo/standalone/allocator_config.def b/compiler-rt/lib/scudo/standalone/allocator_config.def new file mode 100644 index 0000000000000000000000000000000000000000..c50aadad2d637aa58b0580cce7c93ed41ee59e3d --- /dev/null +++ b/compiler-rt/lib/scudo/standalone/allocator_config.def @@ -0,0 +1,124 @@ +//===-- allocator_config.def ------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines all the flags and types supported in Scudo. For optional +// flags and types, only explicitly define them when interested (i.e., unused +// optional flags or types can be skipped). + +#ifndef BASE_REQUIRED_TEMPLATE_TYPE +#define BASE_REQUIRED_TEMPLATE_TYPE(...) +#endif +#ifndef BASE_OPTIONAL +#define BASE_OPTIONAL(...) +#endif +#ifndef PRIMARY_REQUIRED_TYPE +#define PRIMARY_REQUIRED_TYPE(...) +#endif +#ifndef PRIMARY_REQUIRED +#define PRIMARY_REQUIRED(...) +#endif +#ifndef PRIMARY_OPTIONAL +#define PRIMARY_OPTIONAL(...) +#endif +#ifndef PRIMARY_OPTIONAL_TYPE +#define PRIMARY_OPTIONAL_TYPE(...) +#endif +#ifndef SECONDARY_REQUIRED_TEMPLATE_TYPE +#define SECONDARY_REQUIRED_TEMPLATE_TYPE(...) +#endif +#ifndef SECONDARY_CACHE_OPTIONAL +#define SECONDARY_CACHE_OPTIONAL(...) +#endif + +// BASE_REQUIRED_TEMPLATE_TYPE(NAME) +// +// Thread-Specific Data Registry used, shared or exclusive. +BASE_REQUIRED_TEMPLATE_TYPE(TSDRegistryT) + +// Defines the type of Primary allocator to use. +BASE_REQUIRED_TEMPLATE_TYPE(PrimaryT) + +// Defines the type of Secondary allocator to use. +BASE_REQUIRED_TEMPLATE_TYPE(SecondaryT) + +// BASE_OPTIONAL(TYPE, NAME, DEFAULT) +// +// Indicates possible support for Memory Tagging. +BASE_OPTIONAL(const bool, MaySupportMemoryTagging, false) + +// PRIMARY_REQUIRED_TYPE(NAME) +// +// SizeClassMap to use with the Primary. +PRIMARY_REQUIRED_TYPE(SizeClassMap) + +// Defines the type and scale of a compact pointer. A compact pointer can +// be understood as the offset of a pointer within the region it belongs +// to, in increments of a power-of-2 scale. See `CompactPtrScale` also. +PRIMARY_REQUIRED_TYPE(CompactPtrT) + +// PRIMARY_REQUIRED(TYPE, NAME) +// +// The scale of a compact pointer. E.g., Ptr = Base + (CompactPtr << Scale). +PRIMARY_REQUIRED(const uptr, CompactPtrScale) + +// Log2 of the size of a size class region, as used by the Primary. +PRIMARY_REQUIRED(const uptr, RegionSizeLog) + +// Conceptually, a region will be divided into groups based on the address +// range. Each allocation consumes blocks in the same group until exhaustion +// then it pops out blocks in a new group. Therefore, `GroupSizeLog` is always +// smaller or equal to `RegionSizeLog`. Note that `GroupSizeLog` needs to be +// equal to `RegionSizeLog` for SizeClassAllocator32 because of certain +// constraints. +PRIMARY_REQUIRED(const uptr, GroupSizeLog) + +// Call map for user memory with at least this size. Only used with primary64. +PRIMARY_REQUIRED(const uptr, MapSizeIncrement) + +// Defines the minimal & maximal release interval that can be set. +PRIMARY_REQUIRED(const s32, MinReleaseToOsIntervalMs) +PRIMARY_REQUIRED(const s32, MaxReleaseToOsIntervalMs) + +// PRIMARY_OPTIONAL(TYPE, NAME, DEFAULT) +// +// Indicates support for offsetting the start of a region by a random number of +// pages. Only used with primary64. +PRIMARY_OPTIONAL(const bool, EnableRandomOffset, false) + +// PRIMARY_OPTIONAL_TYPE(NAME, DEFAULT) +// +// Use condition variable to shorten the waiting time of refillment of +// freelist. Note that this depends on the implementation of condition +// variable on each platform and the performance may vary so that it does not +// guarantee a performance benefit. +PRIMARY_OPTIONAL_TYPE(ConditionVariableT, ConditionVariableDummy) + +// SECONDARY_REQUIRED_TEMPLATE_TYPE(NAME) +// +// Defines the type of Secondary Cache to use. +SECONDARY_REQUIRED_TEMPLATE_TYPE(CacheT) + +// SECONDARY_CACHE_OPTIONAL(TYPE, NAME, DEFAULT) +// +// Defines the type of cache used by the Secondary. Some additional +// configuration entries can be necessary depending on the Cache. +SECONDARY_CACHE_OPTIONAL(const u32, EntriesArraySize, 0) +SECONDARY_CACHE_OPTIONAL(const u32, QuarantineSize, 0) +SECONDARY_CACHE_OPTIONAL(const u32, DefaultMaxEntriesCount, 0) +SECONDARY_CACHE_OPTIONAL(const uptr, DefaultMaxEntrySize, 0) +SECONDARY_CACHE_OPTIONAL(const s32, MinReleaseToOsIntervalMs, INT32_MIN) +SECONDARY_CACHE_OPTIONAL(const s32, MaxReleaseToOsIntervalMs, INT32_MAX) + +#undef SECONDARY_CACHE_OPTIONAL +#undef SECONDARY_REQUIRED_TEMPLATE_TYPE +#undef PRIMARY_OPTIONAL_TYPE +#undef PRIMARY_OPTIONAL +#undef PRIMARY_REQUIRED +#undef PRIMARY_REQUIRED_TYPE +#undef BASE_OPTIONAL +#undef BASE_REQUIRED_TEMPLATE_TYPE diff --git a/compiler-rt/lib/scudo/standalone/allocator_config.h b/compiler-rt/lib/scudo/standalone/allocator_config.h index 3c6aa3acb0e45b4487f59538636622285eadc094..1e0cf1015ba67e8d9a40be609b21efdccbe22949 100644 --- a/compiler-rt/lib/scudo/standalone/allocator_config.h +++ b/compiler-rt/lib/scudo/standalone/allocator_config.h @@ -38,80 +38,10 @@ namespace scudo { -// The combined allocator uses a structure as a template argument that -// specifies the configuration options for the various subcomponents of the -// allocator. -// -// struct ExampleConfig { -// // Indicates possible support for Memory Tagging. -// static const bool MaySupportMemoryTagging = false; -// -// // Thread-Specific Data Registry used, shared or exclusive. -// template <class A> using TSDRegistryT = TSDRegistrySharedT<A, 8U, 4U>; -// -// struct Primary { -// // SizeClassMap to use with the Primary. -// using SizeClassMap = DefaultSizeClassMap; -// -// // Log2 of the size of a size class region, as used by the Primary. -// static const uptr RegionSizeLog = 30U; -// -// // Log2 of the size of block group, as used by the Primary. Each group -// // contains a range of memory addresses, blocks in the range will belong -// // to the same group. In general, single region may have 1 or 2MB group -// // size. Multiple regions will have the group size equal to the region -// // size because the region size is usually smaller than 1 MB. -// // Smaller value gives fine-grained control of memory usage but the -// // trade-off is that it may take longer time of deallocation. -// static const uptr GroupSizeLog = 20U; -// -// // Defines the type and scale of a compact pointer. A compact pointer can -// // be understood as the offset of a pointer within the region it belongs -// // to, in increments of a power-of-2 scale. -// // eg: Ptr = Base + (CompactPtr << Scale). -// typedef u32 CompactPtrT; -// static const uptr CompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG; -// -// // Indicates support for offsetting the start of a region by -// // a random number of pages. Only used with primary64. -// static const bool EnableRandomOffset = true; -// -// // Call map for user memory with at least this size. Only used with -// // primary64. -// static const uptr MapSizeIncrement = 1UL << 18; -// -// // Defines the minimal & maximal release interval that can be set. -// static const s32 MinReleaseToOsIntervalMs = INT32_MIN; -// static const s32 MaxReleaseToOsIntervalMs = INT32_MAX; -// -// // Use condition variable to shorten the waiting time of refillment of -// // freelist. Note that this depends on the implementation of condition -// // variable on each platform and the performance may vary so that it -// // doesn't guarantee a performance benefit. -// // Note that both variables have to be defined to enable it. -// static const bool UseConditionVariable = true; -// using ConditionVariableT = ConditionVariableLinux; -// }; -// // Defines the type of Primary allocator to use. -// template <typename Config> using PrimaryT = SizeClassAllocator64<Config>; -// -// // Defines the type of cache used by the Secondary. Some additional -// // configuration entries can be necessary depending on the Cache. -// struct Secondary { -// struct Cache { -// static const u32 EntriesArraySize = 32U; -// static const u32 QuarantineSize = 0U; -// static const u32 DefaultMaxEntriesCount = 32U; -// static const uptr DefaultMaxEntrySize = 1UL << 19; -// static const s32 MinReleaseToOsIntervalMs = INT32_MIN; -// static const s32 MaxReleaseToOsIntervalMs = INT32_MAX; -// }; -// // Defines the type of Secondary Cache to use. -// template <typename Config> using CacheT = MapAllocatorCache<Config>; -// }; -// // Defines the type of Secondary allocator to use. -// template <typename Config> using SecondaryT = MapAllocator<Config>; -// }; +// Scudo uses a structure as a template argument that specifies the +// configuration options for the various subcomponents of the allocator. See the +// following configs as examples and check `allocator_config.def` for all the +// available options. #ifndef SCUDO_USE_CUSTOM_CONFIG diff --git a/compiler-rt/lib/scudo/standalone/allocator_config_wrapper.h b/compiler-rt/lib/scudo/standalone/allocator_config_wrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..5477236ac1f3976eb9c18d12934ba9f83bf23713 --- /dev/null +++ b/compiler-rt/lib/scudo/standalone/allocator_config_wrapper.h @@ -0,0 +1,149 @@ +//===-- allocator_config_wrapper.h ------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_ +#define SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_ + +#include "condition_variable.h" +#include "internal_defs.h" +#include "secondary.h" + +namespace { + +template <typename T> struct removeConst { + using type = T; +}; +template <typename T> struct removeConst<const T> { + using type = T; +}; + +// This is only used for SFINAE when detecting if a type is defined. +template <typename T> struct voidAdaptor { + using type = void; +}; + +// This is used for detecting the case that defines the flag with wrong type and +// it'll be viewed as undefined optional flag. +template <typename L, typename R> struct assertSameType { + template <typename, typename> struct isSame { + static constexpr bool value = false; + }; + template <typename T> struct isSame<T, T> { + static constexpr bool value = true; + }; + static_assert(isSame<L, R>::value, "Flag type mismatches"); + using type = R; +}; + +} // namespace + +namespace scudo { + +#define OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, MEMBER) \ + template <typename Config, typename = TYPE> struct NAME##State { \ + static constexpr removeConst<TYPE>::type getValue() { return DEFAULT; } \ + }; \ + template <typename Config> \ + struct NAME##State< \ + Config, typename assertSameType<decltype(Config::MEMBER), TYPE>::type> { \ + static constexpr removeConst<TYPE>::type getValue() { \ + return Config::MEMBER; \ + } \ + }; + +#define OPTIONAL_TYPE_TEMPLATE(NAME, DEFAULT, MEMBER) \ + template <typename Config, typename Void = void> struct NAME##Type { \ + static constexpr bool enabled() { return false; } \ + using NAME = DEFAULT; \ + }; \ + template <typename Config> \ + struct NAME##Type<Config, \ + typename voidAdaptor<typename Config::MEMBER>::type> { \ + static constexpr bool enabled() { return true; } \ + using NAME = typename Config::MEMBER; \ + }; + +template <typename AllocatorConfig> struct BaseConfig { +#define BASE_REQUIRED_TEMPLATE_TYPE(NAME) \ + template <typename T> using NAME = typename AllocatorConfig::template NAME<T>; + +#define BASE_OPTIONAL(TYPE, NAME, DEFAULT) \ + OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, NAME) \ + static constexpr removeConst<TYPE>::type get##NAME() { \ + return NAME##State<AllocatorConfig>::getValue(); \ + } + +#include "allocator_config.def" +}; // BaseConfig + +template <typename AllocatorConfig> struct PrimaryConfig { + // TODO: Pass this flag through template argument to remove this hard-coded + // function. + static constexpr bool getMaySupportMemoryTagging() { + return BaseConfig<AllocatorConfig>::getMaySupportMemoryTagging(); + } + +#define PRIMARY_REQUIRED_TYPE(NAME) \ + using NAME = typename AllocatorConfig::Primary::NAME; + +#define PRIMARY_REQUIRED(TYPE, NAME) \ + static constexpr removeConst<TYPE>::type get##NAME() { \ + return AllocatorConfig::Primary::NAME; \ + } + +#define PRIMARY_OPTIONAL(TYPE, NAME, DEFAULT) \ + OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, NAME) \ + static constexpr removeConst<TYPE>::type get##NAME() { \ + return NAME##State<typename AllocatorConfig::Primary>::getValue(); \ + } + +#define PRIMARY_OPTIONAL_TYPE(NAME, DEFAULT) \ + OPTIONAL_TYPE_TEMPLATE(NAME, DEFAULT, NAME) \ + static constexpr bool has##NAME() { \ + return NAME##Type<typename AllocatorConfig::Primary>::enabled(); \ + } \ + using NAME = typename NAME##Type<typename AllocatorConfig::Primary>::NAME; + +#include "allocator_config.def" + +}; // PrimaryConfig + +template <typename AllocatorConfig> struct SecondaryConfig { + // TODO: Pass this flag through template argument to remove this hard-coded + // function. + static constexpr bool getMaySupportMemoryTagging() { + return BaseConfig<AllocatorConfig>::getMaySupportMemoryTagging(); + } + +#define SECONDARY_REQUIRED_TEMPLATE_TYPE(NAME) \ + template <typename T> \ + using NAME = typename AllocatorConfig::Secondary::template NAME<T>; +#include "allocator_config.def" + + struct CacheConfig { + // TODO: Pass this flag through template argument to remove this hard-coded + // function. + static constexpr bool getMaySupportMemoryTagging() { + return BaseConfig<AllocatorConfig>::getMaySupportMemoryTagging(); + } + +#define SECONDARY_CACHE_OPTIONAL(TYPE, NAME, DEFAULT) \ + OPTIONAL_TEMPLATE(TYPE, NAME, DEFAULT, Cache::NAME) \ + static constexpr removeConst<TYPE>::type get##NAME() { \ + return NAME##State<typename AllocatorConfig::Secondary>::getValue(); \ + } +#include "allocator_config.def" + }; // CacheConfig +}; // SecondaryConfig + +#undef OPTIONAL_TEMPLATE +#undef OPTIONAL_TEMPLATE_TYPE + +} // namespace scudo + +#endif // SCUDO_ALLOCATOR_CONFIG_WRAPPER_H_ diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h index 9e1fd6d6dca3c6301013cb2a73a57bc311f89b20..e7bc90cd0960edb8e55c47fa70938e2e06c2ded9 100644 --- a/compiler-rt/lib/scudo/standalone/combined.h +++ b/compiler-rt/lib/scudo/standalone/combined.h @@ -9,6 +9,7 @@ #ifndef SCUDO_COMBINED_H_ #define SCUDO_COMBINED_H_ +#include "allocator_config_wrapper.h" #include "atomic_helpers.h" #include "chunk.h" #include "common.h" @@ -17,6 +18,7 @@ #include "local_cache.h" #include "mem_map.h" #include "memtag.h" +#include "mutex.h" #include "options.h" #include "quarantine.h" #include "report.h" @@ -47,11 +49,14 @@ namespace scudo { template <class Config, void (*PostInitCallback)(void) = EmptyCallback> class Allocator { public: - using PrimaryT = typename Config::template PrimaryT<Config>; - using SecondaryT = typename Config::template SecondaryT<Config>; + using AllocatorConfig = BaseConfig<Config>; + using PrimaryT = + typename AllocatorConfig::template PrimaryT<PrimaryConfig<Config>>; + using SecondaryT = + typename AllocatorConfig::template SecondaryT<SecondaryConfig<Config>>; using CacheT = typename PrimaryT::CacheT; typedef Allocator<Config, PostInitCallback> ThisT; - typedef typename Config::template TSDRegistryT<ThisT> TSDRegistryT; + typedef typename AllocatorConfig::template TSDRegistryT<ThisT> TSDRegistryT; void callPostInitCallback() { pthread_once(&PostInitNonce, PostInitCallback); @@ -72,7 +77,7 @@ public: Header.State = Chunk::State::Available; Chunk::storeHeader(Allocator.Cookie, Ptr, &Header); - if (allocatorSupportsMemoryTagging<Config>()) + if (allocatorSupportsMemoryTagging<AllocatorConfig>()) Ptr = untagPointer(Ptr); void *BlockBegin = Allocator::getBlockBegin(Ptr, &Header); Cache.deallocate(Header.ClassId, BlockBegin); @@ -99,7 +104,8 @@ public: // Reset tag to 0 as this chunk may have been previously used for a tagged // user allocation. - if (UNLIKELY(useMemoryTagging<Config>(Allocator.Primary.Options.load()))) + if (UNLIKELY(useMemoryTagging<AllocatorConfig>( + Allocator.Primary.Options.load()))) storeTags(reinterpret_cast<uptr>(Ptr), reinterpret_cast<uptr>(Ptr) + sizeof(QuarantineBatch)); @@ -159,7 +165,7 @@ public: Primary.Options.set(OptionBit::DeallocTypeMismatch); if (getFlags()->delete_size_mismatch) Primary.Options.set(OptionBit::DeleteSizeMismatch); - if (allocatorSupportsMemoryTagging<Config>() && + if (allocatorSupportsMemoryTagging<AllocatorConfig>() && systemSupportsMemoryTagging()) Primary.Options.set(OptionBit::UseMemoryTagging); @@ -173,17 +179,17 @@ public: Quarantine.init( static_cast<uptr>(getFlags()->quarantine_size_kb << 10), static_cast<uptr>(getFlags()->thread_local_quarantine_size_kb << 10)); - - mapAndInitializeRingBuffer(); } - void enableRingBuffer() { + void enableRingBuffer() NO_THREAD_SAFETY_ANALYSIS { AllocationRingBuffer *RB = getRingBuffer(); if (RB) RB->Depot->enable(); + RingBufferInitLock.unlock(); } - void disableRingBuffer() { + void disableRingBuffer() NO_THREAD_SAFETY_ANALYSIS { + RingBufferInitLock.lock(); AllocationRingBuffer *RB = getRingBuffer(); if (RB) RB->Depot->disable(); @@ -274,7 +280,7 @@ public: void drainCaches() { TSDRegistry.drainCaches(this); } ALWAYS_INLINE void *getHeaderTaggedPointer(void *Ptr) { - if (!allocatorSupportsMemoryTagging<Config>()) + if (!allocatorSupportsMemoryTagging<AllocatorConfig>()) return Ptr; auto UntaggedPtr = untagPointer(Ptr); if (UntaggedPtr != Ptr) @@ -286,7 +292,7 @@ public: } ALWAYS_INLINE uptr addHeaderTag(uptr Ptr) { - if (!allocatorSupportsMemoryTagging<Config>()) + if (!allocatorSupportsMemoryTagging<AllocatorConfig>()) return Ptr; return addFixedTag(Ptr, 2); } @@ -419,7 +425,7 @@ public: // // When memory tagging is enabled, zeroing the contents is done as part of // setting the tag. - if (UNLIKELY(useMemoryTagging<Config>(Options))) { + if (UNLIKELY(useMemoryTagging<AllocatorConfig>(Options))) { uptr PrevUserPtr; Chunk::UnpackedHeader Header; const uptr BlockSize = PrimaryT::getSizeByClassId(ClassId); @@ -501,7 +507,7 @@ public: } else { Block = addHeaderTag(Block); Ptr = addHeaderTag(Ptr); - if (UNLIKELY(useMemoryTagging<Config>(Options))) { + if (UNLIKELY(useMemoryTagging<AllocatorConfig>(Options))) { storeTags(reinterpret_cast<uptr>(Block), reinterpret_cast<uptr>(Ptr)); storeSecondaryAllocationStackMaybe(Options, Ptr, Size); } @@ -661,7 +667,7 @@ public: (reinterpret_cast<uptr>(OldTaggedPtr) + NewSize)) & Chunk::SizeOrUnusedBytesMask; Chunk::storeHeader(Cookie, OldPtr, &Header); - if (UNLIKELY(useMemoryTagging<Config>(Options))) { + if (UNLIKELY(useMemoryTagging<AllocatorConfig>(Options))) { if (ClassId) { resizeTaggedChunk(reinterpret_cast<uptr>(OldTaggedPtr) + OldSize, reinterpret_cast<uptr>(OldTaggedPtr) + NewSize, @@ -764,8 +770,9 @@ public: Base = untagPointer(Base); const uptr From = Base; const uptr To = Base + Size; - bool MayHaveTaggedPrimary = allocatorSupportsMemoryTagging<Config>() && - systemSupportsMemoryTagging(); + bool MayHaveTaggedPrimary = + allocatorSupportsMemoryTagging<AllocatorConfig>() && + systemSupportsMemoryTagging(); auto Lambda = [this, From, To, MayHaveTaggedPrimary, Callback, Arg](uptr Block) { if (Block < From || Block >= To) @@ -786,9 +793,9 @@ public: } if (Header.State == Chunk::State::Allocated) { uptr TaggedChunk = Chunk; - if (allocatorSupportsMemoryTagging<Config>()) + if (allocatorSupportsMemoryTagging<AllocatorConfig>()) TaggedChunk = untagPointer(TaggedChunk); - if (useMemoryTagging<Config>(Primary.Options.load())) + if (useMemoryTagging<AllocatorConfig>(Primary.Options.load())) TaggedChunk = loadTag(Chunk); Callback(TaggedChunk, getSize(reinterpret_cast<void *>(Chunk), &Header), Arg); @@ -887,7 +894,7 @@ public: } bool useMemoryTaggingTestOnly() const { - return useMemoryTagging<Config>(Primary.Options.load()); + return useMemoryTagging<AllocatorConfig>(Primary.Options.load()); } void disableMemoryTagging() { // If we haven't been initialized yet, we need to initialize now in order to @@ -897,7 +904,7 @@ public: // callback), which may cause mappings to be created with memory tagging // enabled. TSDRegistry.initOnceMaybe(this); - if (allocatorSupportsMemoryTagging<Config>()) { + if (allocatorSupportsMemoryTagging<AllocatorConfig>()) { Secondary.disableMemoryTagging(); Primary.Options.clear(OptionBit::UseMemoryTagging); } @@ -909,9 +916,11 @@ public: DCHECK(!Primary.Options.load().get(OptionBit::TrackAllocationStacks)); return; } - if (Track) + + if (Track) { + initRingBufferMaybe(); Primary.Options.set(OptionBit::TrackAllocationStacks); - else + } else Primary.Options.clear(OptionBit::TrackAllocationStacks); } @@ -983,7 +992,7 @@ public: // should not be able to crash the crash dumper (crash_dump on Android). // See also the get_error_info_fuzzer. *ErrorInfo = {}; - if (!allocatorSupportsMemoryTagging<Config>() || + if (!allocatorSupportsMemoryTagging<AllocatorConfig>() || MemoryAddr + MemorySize < MemoryAddr) return; @@ -1032,7 +1041,7 @@ private: static_assert(MinAlignment >= sizeof(Chunk::PackedHeader), "Minimal alignment must at least cover a chunk header."); - static_assert(!allocatorSupportsMemoryTagging<Config>() || + static_assert(!allocatorSupportsMemoryTagging<AllocatorConfig>() || MinAlignment >= archMemoryTagGranuleSize(), ""); @@ -1086,6 +1095,9 @@ private: 0, "invalid alignment"); + // Lock to initialize the RingBuffer + HybridMutex RingBufferInitLock; + // Pointer to memory mapped area starting with AllocationRingBuffer struct, // and immediately followed by Size elements of type Entry. atomic_uptr RingBufferAddress = {}; @@ -1142,7 +1154,7 @@ private: const uptr SizeOrUnusedBytes = Header->SizeOrUnusedBytes; if (LIKELY(Header->ClassId)) return SizeOrUnusedBytes; - if (allocatorSupportsMemoryTagging<Config>()) + if (allocatorSupportsMemoryTagging<AllocatorConfig>()) Ptr = untagPointer(const_cast<void *>(Ptr)); return SecondaryT::getBlockEnd(getBlockBegin(Ptr, Header)) - reinterpret_cast<uptr>(Ptr) - SizeOrUnusedBytes; @@ -1162,12 +1174,12 @@ private: Header->State = Chunk::State::Available; else Header->State = Chunk::State::Quarantined; - Header->OriginOrWasZeroed = useMemoryTagging<Config>(Options) && + Header->OriginOrWasZeroed = useMemoryTagging<AllocatorConfig>(Options) && Header->ClassId && !TSDRegistry.getDisableMemInit(); Chunk::storeHeader(Cookie, Ptr, Header); - if (UNLIKELY(useMemoryTagging<Config>(Options))) { + if (UNLIKELY(useMemoryTagging<AllocatorConfig>(Options))) { u8 PrevTag = extractTag(reinterpret_cast<uptr>(TaggedPtr)); storeDeallocationStackMaybe(Options, Ptr, PrevTag, Size); if (Header->ClassId) { @@ -1184,7 +1196,7 @@ private: } } if (BypassQuarantine) { - if (allocatorSupportsMemoryTagging<Config>()) + if (allocatorSupportsMemoryTagging<AllocatorConfig>()) Ptr = untagPointer(Ptr); void *BlockBegin = getBlockBegin(Ptr, Header); const uptr ClassId = Header->ClassId; @@ -1201,7 +1213,7 @@ private: if (CacheDrained) Primary.tryReleaseToOS(ClassId, ReleaseToOS::Normal); } else { - if (UNLIKELY(useMemoryTagging<Config>(Options))) + if (UNLIKELY(useMemoryTagging<AllocatorConfig>(Options))) storeTags(reinterpret_cast<uptr>(BlockBegin), reinterpret_cast<uptr>(Ptr)); Secondary.deallocate(Options, BlockBegin); @@ -1540,11 +1552,16 @@ private: RBEntryStart)[N]; } - void mapAndInitializeRingBuffer() { - if (getFlags()->allocation_ring_buffer_size <= 0) + void initRingBufferMaybe() { + ScopedLock L(RingBufferInitLock); + if (getRingBuffer() != nullptr) return; - u32 AllocationRingBufferSize = - static_cast<u32>(getFlags()->allocation_ring_buffer_size); + + int ring_buffer_size = getFlags()->allocation_ring_buffer_size; + if (ring_buffer_size <= 0) + return; + + u32 AllocationRingBufferSize = static_cast<u32>(ring_buffer_size); // We store alloc and free stacks for each entry. constexpr u32 kStacksPerRingBufferEntry = 2; diff --git a/compiler-rt/lib/scudo/standalone/common.h b/compiler-rt/lib/scudo/standalone/common.h index ae45683f1ee38179f18d4eecd1dab185f4ae78aa..151fbd317e74d303d3cb9d92e80af0c4e8160f0d 100644 --- a/compiler-rt/lib/scudo/standalone/common.h +++ b/compiler-rt/lib/scudo/standalone/common.h @@ -28,7 +28,11 @@ template <class Dest, class Source> inline Dest bit_cast(const Source &S) { return D; } -inline constexpr bool isPowerOfTwo(uptr X) { return (X & (X - 1)) == 0; } +inline constexpr bool isPowerOfTwo(uptr X) { + if (X == 0) + return false; + return (X & (X - 1)) == 0; +} inline constexpr uptr roundUp(uptr X, uptr Boundary) { DCHECK(isPowerOfTwo(Boundary)); diff --git a/compiler-rt/lib/scudo/standalone/condition_variable.h b/compiler-rt/lib/scudo/standalone/condition_variable.h index 4afebdc9d04c2cf75f098e2638612c089315bd57..3f16c86651e7364cb9449c8f9bbf17227082e7d7 100644 --- a/compiler-rt/lib/scudo/standalone/condition_variable.h +++ b/compiler-rt/lib/scudo/standalone/condition_variable.h @@ -39,22 +39,6 @@ public: } }; -template <typename Config, typename = const bool> -struct ConditionVariableState { - static constexpr bool enabled() { return false; } - // This is only used for compilation purpose so that we won't end up having - // many conditional compilations. If you want to use `ConditionVariableDummy`, - // define `ConditionVariableT` in your allocator configuration. See - // allocator_config.h for more details. - using ConditionVariableT = ConditionVariableDummy; -}; - -template <typename Config> -struct ConditionVariableState<Config, decltype(Config::UseConditionVariable)> { - static constexpr bool enabled() { return Config::UseConditionVariable; } - using ConditionVariableT = typename Config::ConditionVariableT; -}; - } // namespace scudo #endif // SCUDO_CONDITION_VARIABLE_H_ diff --git a/compiler-rt/lib/scudo/standalone/fuchsia.cpp b/compiler-rt/lib/scudo/standalone/fuchsia.cpp index 0788c4198e53ce189d044cb2a922965aae33dd4d..2144f1b63f89401fa343dfb815253ae5cec8d7da 100644 --- a/compiler-rt/lib/scudo/standalone/fuchsia.cpp +++ b/compiler-rt/lib/scudo/standalone/fuchsia.cpp @@ -34,11 +34,10 @@ static_assert(ZX_HANDLE_INVALID == 0, ""); static void NORETURN dieOnError(zx_status_t Status, const char *FnName, uptr Size) { - char Error[128]; - formatString(Error, sizeof(Error), - "SCUDO ERROR: %s failed with size %zuKB (%s)", FnName, + ScopedString Error; + Error.append("SCUDO ERROR: %s failed with size %zuKB (%s)", FnName, Size >> 10, zx_status_get_string(Status)); - outputRaw(Error); + outputRaw(Error.data()); die(); } diff --git a/compiler-rt/lib/scudo/standalone/mem_map_fuchsia.cpp b/compiler-rt/lib/scudo/standalone/mem_map_fuchsia.cpp index 0566ab0655263ee55552fcfb4b7131ab66d1769b..28e5a11a37f257318fc4fad94d0add526f3c1338 100644 --- a/compiler-rt/lib/scudo/standalone/mem_map_fuchsia.cpp +++ b/compiler-rt/lib/scudo/standalone/mem_map_fuchsia.cpp @@ -22,11 +22,10 @@ namespace scudo { static void NORETURN dieOnError(zx_status_t Status, const char *FnName, uptr Size) { - char Error[128]; - formatString(Error, sizeof(Error), - "SCUDO ERROR: %s failed with size %zuKB (%s)", FnName, + ScopedString Error; + Error.append("SCUDO ERROR: %s failed with size %zuKB (%s)", FnName, Size >> 10, _zx_status_get_string(Status)); - outputRaw(Error); + outputRaw(Error.data()); die(); } diff --git a/compiler-rt/lib/scudo/standalone/memtag.h b/compiler-rt/lib/scudo/standalone/memtag.h index aaed2192ad7521a683a7236aca9cf56097b44646..1f6983e99404a2cbd520b3cd2b0597e683234dd9 100644 --- a/compiler-rt/lib/scudo/standalone/memtag.h +++ b/compiler-rt/lib/scudo/standalone/memtag.h @@ -326,7 +326,7 @@ inline void *addFixedTag(void *Ptr, uptr Tag) { template <typename Config> inline constexpr bool allocatorSupportsMemoryTagging() { - return archSupportsMemoryTagging() && Config::MaySupportMemoryTagging && + return archSupportsMemoryTagging() && Config::getMaySupportMemoryTagging() && (1 << SCUDO_MIN_ALIGNMENT_LOG) >= archMemoryTagGranuleSize(); } diff --git a/compiler-rt/lib/scudo/standalone/primary32.h b/compiler-rt/lib/scudo/standalone/primary32.h index c86e75b8fd66a8fcf2902ea8de87eb5fc7c4cf76..1d8a77b73e5c27b287760f7f62701765aa8ba8cf 100644 --- a/compiler-rt/lib/scudo/standalone/primary32.h +++ b/compiler-rt/lib/scudo/standalone/primary32.h @@ -43,14 +43,13 @@ namespace scudo { template <typename Config> class SizeClassAllocator32 { public: - typedef typename Config::Primary::CompactPtrT CompactPtrT; - typedef typename Config::Primary::SizeClassMap SizeClassMap; - static const uptr GroupSizeLog = Config::Primary::GroupSizeLog; + typedef typename Config::CompactPtrT CompactPtrT; + typedef typename Config::SizeClassMap SizeClassMap; + static const uptr GroupSizeLog = Config::getGroupSizeLog(); // The bytemap can only track UINT8_MAX - 1 classes. static_assert(SizeClassMap::LargestClassId <= (UINT8_MAX - 1), ""); // Regions should be large enough to hold the largest Block. - static_assert((1UL << Config::Primary::RegionSizeLog) >= - SizeClassMap::MaxSize, + static_assert((1UL << Config::getRegionSizeLog()) >= SizeClassMap::MaxSize, ""); typedef SizeClassAllocator32<Config> ThisT; typedef SizeClassAllocatorLocalCache<ThisT> CacheT; @@ -331,9 +330,9 @@ public: bool setOption(Option O, sptr Value) { if (O == Option::ReleaseInterval) { - const s32 Interval = Max(Min(static_cast<s32>(Value), - Config::Primary::MaxReleaseToOsIntervalMs), - Config::Primary::MinReleaseToOsIntervalMs); + const s32 Interval = Max( + Min(static_cast<s32>(Value), Config::getMaxReleaseToOsIntervalMs()), + Config::getMinReleaseToOsIntervalMs()); atomic_store_relaxed(&ReleaseToOsIntervalMs, Interval); return true; } @@ -373,9 +372,9 @@ public: private: static const uptr NumClasses = SizeClassMap::NumClasses; - static const uptr RegionSize = 1UL << Config::Primary::RegionSizeLog; - static const uptr NumRegions = - SCUDO_MMAP_RANGE_SIZE >> Config::Primary::RegionSizeLog; + static const uptr RegionSize = 1UL << Config::getRegionSizeLog(); + static const uptr NumRegions = SCUDO_MMAP_RANGE_SIZE >> + Config::getRegionSizeLog(); static const u32 MaxNumBatches = SCUDO_ANDROID ? 4U : 8U; typedef FlatByteMap<NumRegions> ByteMap; @@ -408,7 +407,7 @@ private: static_assert(sizeof(SizeClassInfo) % SCUDO_CACHE_LINE_SIZE == 0, ""); uptr computeRegionId(uptr Mem) { - const uptr Id = Mem >> Config::Primary::RegionSizeLog; + const uptr Id = Mem >> Config::getRegionSizeLog(); CHECK_LT(Id, NumRegions); return Id; } @@ -437,7 +436,7 @@ private: unmap(reinterpret_cast<void *>(End), MapEnd - End); DCHECK_EQ(Region % RegionSize, 0U); - static_assert(Config::Primary::RegionSizeLog == GroupSizeLog, + static_assert(Config::getRegionSizeLog() == GroupSizeLog, "Memory group should be the same size as Region"); return Region; diff --git a/compiler-rt/lib/scudo/standalone/primary64.h b/compiler-rt/lib/scudo/standalone/primary64.h index d89a2e6a4e5c8dff0f4a2ad6d6766d0dec05320b..abce4bff321cb19945c4381907a76a6f43d3f666 100644 --- a/compiler-rt/lib/scudo/standalone/primary64.h +++ b/compiler-rt/lib/scudo/standalone/primary64.h @@ -47,13 +47,12 @@ namespace scudo { template <typename Config> class SizeClassAllocator64 { public: - typedef typename Config::Primary::CompactPtrT CompactPtrT; - typedef typename Config::Primary::SizeClassMap SizeClassMap; - typedef typename ConditionVariableState< - typename Config::Primary>::ConditionVariableT ConditionVariableT; - static const uptr CompactPtrScale = Config::Primary::CompactPtrScale; - static const uptr RegionSizeLog = Config::Primary::RegionSizeLog; - static const uptr GroupSizeLog = Config::Primary::GroupSizeLog; + typedef typename Config::CompactPtrT CompactPtrT; + typedef typename Config::SizeClassMap SizeClassMap; + typedef typename Config::ConditionVariableT ConditionVariableT; + static const uptr CompactPtrScale = Config::getCompactPtrScale(); + static const uptr RegionSizeLog = Config::getRegionSizeLog(); + static const uptr GroupSizeLog = Config::getGroupSizeLog(); static_assert(RegionSizeLog >= GroupSizeLog, "Group size shouldn't be greater than the region size"); static const uptr GroupScale = GroupSizeLog - CompactPtrScale; @@ -74,7 +73,7 @@ public: static bool canAllocate(uptr Size) { return Size <= SizeClassMap::MaxSize; } static bool conditionVariableEnabled() { - return ConditionVariableState<typename Config::Primary>::enabled(); + return Config::hasConditionVariableT(); } void init(s32 ReleaseToOsInterval) NO_THREAD_SAFETY_ANALYSIS { @@ -135,7 +134,7 @@ public: // The actual start of a region is offset by a random number of pages // when PrimaryEnableRandomOffset is set. Region->RegionBeg = (PrimaryBase + (I << RegionSizeLog)) + - (Config::Primary::EnableRandomOffset + (Config::getEnableRandomOffset() ? ((getRandomModN(&Seed, 16) + 1) * PageSize) : 0); Region->RandState = getRandomU32(&Seed); @@ -373,10 +372,11 @@ public: PushedBlocks += Region->FreeListInfo.PushedBlocks; } } + const s32 IntervalMs = atomic_load_relaxed(&ReleaseToOsIntervalMs); Str->append("Stats: SizeClassAllocator64: %zuM mapped (%uM rss) in %zu " - "allocations; remains %zu\n", + "allocations; remains %zu; ReleaseToOsIntervalMs = %d\n", TotalMapped >> 20, 0U, PoppedBlocks, - PoppedBlocks - PushedBlocks); + PoppedBlocks - PushedBlocks, IntervalMs >= 0 ? IntervalMs : -1); for (uptr I = 0; I < NumClasses; I++) { RegionInfo *Region = getRegionInfo(I); @@ -400,9 +400,9 @@ public: bool setOption(Option O, sptr Value) { if (O == Option::ReleaseInterval) { - const s32 Interval = Max(Min(static_cast<s32>(Value), - Config::Primary::MaxReleaseToOsIntervalMs), - Config::Primary::MinReleaseToOsIntervalMs); + const s32 Interval = Max( + Min(static_cast<s32>(Value), Config::getMaxReleaseToOsIntervalMs()), + Config::getMinReleaseToOsIntervalMs()); atomic_store_relaxed(&ReleaseToOsIntervalMs, Interval); return true; } @@ -516,7 +516,7 @@ private: static const uptr NumClasses = SizeClassMap::NumClasses; static const uptr PrimarySize = RegionSize * NumClasses; - static const uptr MapSizeIncrement = Config::Primary::MapSizeIncrement; + static const uptr MapSizeIncrement = Config::getMapSizeIncrement(); // Fill at most this number of batches from the newly map'd memory. static const u32 MaxNumBatches = SCUDO_ANDROID ? 4U : 8U; diff --git a/compiler-rt/lib/scudo/standalone/report_linux.cpp b/compiler-rt/lib/scudo/standalone/report_linux.cpp index 6a983036e6cd9f705cad3d038818d1f27ae6927a..dfddef3324bd61d7e836d906b2dc62f546cf2dc1 100644 --- a/compiler-rt/lib/scudo/standalone/report_linux.cpp +++ b/compiler-rt/lib/scudo/standalone/report_linux.cpp @@ -24,33 +24,30 @@ namespace scudo { // Fatal internal map() error (potentially OOM related). void NORETURN reportMapError(uptr SizeIfOOM) { - char Error[128] = "Scudo ERROR: internal map failure\n"; + ScopedString Error; + Error.append("Scudo ERROR: internal map failure"); if (SizeIfOOM) { - formatString( - Error, sizeof(Error), - "Scudo ERROR: internal map failure (NO MEMORY) requesting %zuKB\n", - SizeIfOOM >> 10); + Error.append(" (NO MEMORY) requesting %zuKB", SizeIfOOM >> 10); } - reportRawError(Error); + Error.append("\n"); + reportRawError(Error.data()); } void NORETURN reportUnmapError(uptr Addr, uptr Size) { - char Error[128]; - formatString(Error, sizeof(Error), - "Scudo ERROR: internal unmap failure (error desc=%s) Addr 0x%zx " + ScopedString Error; + Error.append("Scudo ERROR: internal unmap failure (error desc=%s) Addr 0x%zx " "Size %zu\n", strerror(errno), Addr, Size); - reportRawError(Error); + reportRawError(Error.data()); } void NORETURN reportProtectError(uptr Addr, uptr Size, int Prot) { - char Error[128]; - formatString( - Error, sizeof(Error), + ScopedString Error; + Error.append( "Scudo ERROR: internal protect failure (error desc=%s) Addr 0x%zx " "Size %zu Prot %x\n", strerror(errno), Addr, Size, Prot); - reportRawError(Error); + reportRawError(Error.data()); } } // namespace scudo diff --git a/compiler-rt/lib/scudo/standalone/secondary.h b/compiler-rt/lib/scudo/standalone/secondary.h index 732fd307ed2f434f02cc4bb17c2334b3ae8a8779..674af5071775866b353533ec84ce38c3d3108233 100644 --- a/compiler-rt/lib/scudo/standalone/secondary.h +++ b/compiler-rt/lib/scudo/standalone/secondary.h @@ -173,18 +173,18 @@ public: template <typename Config> class MapAllocatorCache { public: - using CacheConfig = typename Config::Secondary::Cache; - void getStats(ScopedString *Str) { ScopedLock L(Mutex); uptr Integral; uptr Fractional; computePercentage(SuccessfulRetrieves, CallsToRetrieve, &Integral, &Fractional); - Str->append("Stats: MapAllocatorCache: EntriesCount: %d, " - "MaxEntriesCount: %u, MaxEntrySize: %zu\n", - EntriesCount, atomic_load_relaxed(&MaxEntriesCount), - atomic_load_relaxed(&MaxEntrySize)); + const s32 Interval = atomic_load_relaxed(&ReleaseToOsIntervalMs); + Str->append( + "Stats: MapAllocatorCache: EntriesCount: %d, " + "MaxEntriesCount: %u, MaxEntrySize: %zu, ReleaseToOsIntervalMs = %d\n", + EntriesCount, atomic_load_relaxed(&MaxEntriesCount), + atomic_load_relaxed(&MaxEntrySize), Interval >= 0 ? Interval : -1); Str->append("Stats: CacheRetrievalStats: SuccessRate: %u/%u " "(%zu.%02zu%%)\n", SuccessfulRetrieves, CallsToRetrieve, Integral, Fractional); @@ -199,16 +199,16 @@ public: } // Ensure the default maximum specified fits the array. - static_assert(CacheConfig::DefaultMaxEntriesCount <= - CacheConfig::EntriesArraySize, + static_assert(Config::getDefaultMaxEntriesCount() <= + Config::getEntriesArraySize(), ""); void init(s32 ReleaseToOsInterval) NO_THREAD_SAFETY_ANALYSIS { DCHECK_EQ(EntriesCount, 0U); setOption(Option::MaxCacheEntriesCount, - static_cast<sptr>(CacheConfig::DefaultMaxEntriesCount)); + static_cast<sptr>(Config::getDefaultMaxEntriesCount())); setOption(Option::MaxCacheEntrySize, - static_cast<sptr>(CacheConfig::DefaultMaxEntrySize)); + static_cast<sptr>(Config::getDefaultMaxEntrySize())); setOption(Option::ReleaseInterval, static_cast<sptr>(ReleaseToOsInterval)); } @@ -253,9 +253,9 @@ public: // just unmap it. break; } - if (CacheConfig::QuarantineSize && useMemoryTagging<Config>(Options)) { + if (Config::getQuarantineSize() && useMemoryTagging<Config>(Options)) { QuarantinePos = - (QuarantinePos + 1) % Max(CacheConfig::QuarantineSize, 1u); + (QuarantinePos + 1) % Max(Config::getQuarantineSize(), 1u); if (!Quarantine[QuarantinePos].isValid()) { Quarantine[QuarantinePos] = Entry; return; @@ -382,14 +382,14 @@ public: bool setOption(Option O, sptr Value) { if (O == Option::ReleaseInterval) { const s32 Interval = Max( - Min(static_cast<s32>(Value), CacheConfig::MaxReleaseToOsIntervalMs), - CacheConfig::MinReleaseToOsIntervalMs); + Min(static_cast<s32>(Value), Config::getMaxReleaseToOsIntervalMs()), + Config::getMinReleaseToOsIntervalMs()); atomic_store_relaxed(&ReleaseToOsIntervalMs, Interval); return true; } if (O == Option::MaxCacheEntriesCount) { const u32 MaxCount = static_cast<u32>(Value); - if (MaxCount > CacheConfig::EntriesArraySize) + if (MaxCount > Config::getEntriesArraySize()) return false; atomic_store_relaxed(&MaxEntriesCount, MaxCount); return true; @@ -406,7 +406,7 @@ public: void disableMemoryTagging() EXCLUDES(Mutex) { ScopedLock L(Mutex); - for (u32 I = 0; I != CacheConfig::QuarantineSize; ++I) { + for (u32 I = 0; I != Config::getQuarantineSize(); ++I) { if (Quarantine[I].isValid()) { MemMapT &MemMap = Quarantine[I].MemMap; MemMap.unmap(MemMap.getBase(), MemMap.getCapacity()); @@ -431,11 +431,11 @@ public: private: void empty() { - MemMapT MapInfo[CacheConfig::EntriesArraySize]; + MemMapT MapInfo[Config::getEntriesArraySize()]; uptr N = 0; { ScopedLock L(Mutex); - for (uptr I = 0; I < CacheConfig::EntriesArraySize; I++) { + for (uptr I = 0; I < Config::getEntriesArraySize(); I++) { if (!Entries[I].isValid()) continue; MapInfo[N] = Entries[I].MemMap; @@ -468,9 +468,9 @@ private: if (!EntriesCount || OldestTime == 0 || OldestTime > Time) return; OldestTime = 0; - for (uptr I = 0; I < CacheConfig::QuarantineSize; I++) + for (uptr I = 0; I < Config::getQuarantineSize(); I++) releaseIfOlderThan(Quarantine[I], Time); - for (uptr I = 0; I < CacheConfig::EntriesArraySize; I++) + for (uptr I = 0; I < Config::getEntriesArraySize(); I++) releaseIfOlderThan(Entries[I], Time); } @@ -485,8 +485,8 @@ private: u32 CallsToRetrieve GUARDED_BY(Mutex) = 0; u32 SuccessfulRetrieves GUARDED_BY(Mutex) = 0; - CachedBlock Entries[CacheConfig::EntriesArraySize] GUARDED_BY(Mutex) = {}; - NonZeroLengthArray<CachedBlock, CacheConfig::QuarantineSize> + CachedBlock Entries[Config::getEntriesArraySize()] GUARDED_BY(Mutex) = {}; + NonZeroLengthArray<CachedBlock, Config::getQuarantineSize()> Quarantine GUARDED_BY(Mutex) = {}; }; @@ -555,7 +555,7 @@ public: void getStats(ScopedString *Str); private: - typename Config::Secondary::template CacheT<Config> Cache; + typename Config::template CacheT<typename Config::CacheConfig> Cache; mutable HybridMutex Mutex; DoublyLinkedList<LargeBlock::Header> InUseBlocks GUARDED_BY(Mutex); diff --git a/compiler-rt/lib/scudo/standalone/stack_depot.h b/compiler-rt/lib/scudo/standalone/stack_depot.h index cf3cabf7085b6034bc4ed4fb96bd76536e245a4c..0176c40aa899df38bd7101492817e5c3dad0fda7 100644 --- a/compiler-rt/lib/scudo/standalone/stack_depot.h +++ b/compiler-rt/lib/scudo/standalone/stack_depot.h @@ -103,7 +103,7 @@ public: // Ensure that RingSize, RingMask and TabMask are set up in a way that // all accesses are within range of BufSize. bool isValid(uptr BufSize) const { - if (RingSize == 0 || !isPowerOfTwo(RingSize)) + if (!isPowerOfTwo(RingSize)) return false; uptr RingBytes = sizeof(atomic_u64) * RingSize; if (RingMask + 1 != RingSize) diff --git a/compiler-rt/lib/scudo/standalone/string_utils.cpp b/compiler-rt/lib/scudo/standalone/string_utils.cpp index d4e4e3becd0e1afca6aac57657fd7104a72f7cea..e584bd806e579418a0875b790be2e306577a3acb 100644 --- a/compiler-rt/lib/scudo/standalone/string_utils.cpp +++ b/compiler-rt/lib/scudo/standalone/string_utils.cpp @@ -14,30 +14,21 @@ namespace scudo { -static int appendChar(char **Buffer, const char *BufferEnd, char C) { - if (*Buffer < BufferEnd) { - **Buffer = C; - (*Buffer)++; - } - return 1; -} - // Appends number in a given Base to buffer. If its length is less than // |MinNumberLength|, it is padded with leading zeroes or spaces, depending // on the value of |PadWithZero|. -static int appendNumber(char **Buffer, const char *BufferEnd, u64 AbsoluteValue, - u8 Base, u8 MinNumberLength, bool PadWithZero, - bool Negative, bool Upper) { +void ScopedString::appendNumber(u64 AbsoluteValue, u8 Base, u8 MinNumberLength, + bool PadWithZero, bool Negative, bool Upper) { constexpr uptr MaxLen = 30; RAW_CHECK(Base == 10 || Base == 16); RAW_CHECK(Base == 10 || !Negative); RAW_CHECK(AbsoluteValue || !Negative); RAW_CHECK(MinNumberLength < MaxLen); - int Res = 0; if (Negative && MinNumberLength) --MinNumberLength; - if (Negative && PadWithZero) - Res += appendChar(Buffer, BufferEnd, '-'); + if (Negative && PadWithZero) { + String.push_back('-'); + } uptr NumBuffer[MaxLen]; int Pos = 0; do { @@ -55,34 +46,32 @@ static int appendNumber(char **Buffer, const char *BufferEnd, u64 AbsoluteValue, Pos--; for (; Pos >= 0 && NumBuffer[Pos] == 0; Pos--) { char c = (PadWithZero || Pos == 0) ? '0' : ' '; - Res += appendChar(Buffer, BufferEnd, c); + String.push_back(c); } if (Negative && !PadWithZero) - Res += appendChar(Buffer, BufferEnd, '-'); + String.push_back('-'); for (; Pos >= 0; Pos--) { char Digit = static_cast<char>(NumBuffer[Pos]); Digit = static_cast<char>((Digit < 10) ? '0' + Digit : (Upper ? 'A' : 'a') + Digit - 10); - Res += appendChar(Buffer, BufferEnd, Digit); + String.push_back(Digit); } - return Res; } -static int appendUnsigned(char **Buffer, const char *BufferEnd, u64 Num, - u8 Base, u8 MinNumberLength, bool PadWithZero, - bool Upper) { - return appendNumber(Buffer, BufferEnd, Num, Base, MinNumberLength, - PadWithZero, /*Negative=*/false, Upper); +void ScopedString::appendUnsigned(u64 Num, u8 Base, u8 MinNumberLength, + bool PadWithZero, bool Upper) { + appendNumber(Num, Base, MinNumberLength, PadWithZero, /*Negative=*/false, + Upper); } -static int appendSignedDecimal(char **Buffer, const char *BufferEnd, s64 Num, - u8 MinNumberLength, bool PadWithZero) { +void ScopedString::appendSignedDecimal(s64 Num, u8 MinNumberLength, + bool PadWithZero) { const bool Negative = (Num < 0); const u64 UnsignedNum = (Num == INT64_MIN) ? static_cast<u64>(INT64_MAX) + 1 : static_cast<u64>(Negative ? -Num : Num); - return appendNumber(Buffer, BufferEnd, UnsignedNum, 10, MinNumberLength, - PadWithZero, Negative, /*Upper=*/false); + appendNumber(UnsignedNum, 10, MinNumberLength, PadWithZero, Negative, + /*Upper=*/false); } // Use the fact that explicitly requesting 0 Width (%0s) results in UB and @@ -90,44 +79,45 @@ static int appendSignedDecimal(char **Buffer, const char *BufferEnd, s64 Num, // Width == 0 - no Width requested // Width < 0 - left-justify S within and pad it to -Width chars, if necessary // Width > 0 - right-justify S, not implemented yet -static int appendString(char **Buffer, const char *BufferEnd, int Width, - int MaxChars, const char *S) { +void ScopedString::appendString(int Width, int MaxChars, const char *S) { if (!S) S = "<null>"; - int Res = 0; + int NumChars = 0; for (; *S; S++) { - if (MaxChars >= 0 && Res >= MaxChars) + if (MaxChars >= 0 && NumChars >= MaxChars) break; - Res += appendChar(Buffer, BufferEnd, *S); + String.push_back(*S); + NumChars++; + } + if (Width < 0) { + // Only left justification supported. + Width = -Width - NumChars; + while (Width-- > 0) + String.push_back(' '); } - // Only the left justified strings are supported. - while (Width < -Res) - Res += appendChar(Buffer, BufferEnd, ' '); - return Res; } -static int appendPointer(char **Buffer, const char *BufferEnd, u64 ptr_value) { - int Res = 0; - Res += appendString(Buffer, BufferEnd, 0, -1, "0x"); - Res += appendUnsigned(Buffer, BufferEnd, ptr_value, 16, - SCUDO_POINTER_FORMAT_LENGTH, /*PadWithZero=*/true, - /*Upper=*/false); - return Res; +void ScopedString::appendPointer(u64 ptr_value) { + appendString(0, -1, "0x"); + appendUnsigned(ptr_value, 16, SCUDO_POINTER_FORMAT_LENGTH, + /*PadWithZero=*/true, + /*Upper=*/false); } -static int formatString(char *Buffer, uptr BufferLength, const char *Format, - va_list Args) { +void ScopedString::vappend(const char *Format, va_list &Args) { + // Since the string contains the '\0' terminator, put our size before it + // so that push_back calls work correctly. + DCHECK(String.size() > 0); + String.resize(String.size() - 1); + static const char *PrintfFormatsHelp = - "Supported formatString formats: %([0-9]*)?(z|ll)?{d,u,x,X}; %p; " + "Supported formats: %([0-9]*)?(z|ll)?{d,u,x,X}; %p; " "%[-]([0-9]*)?(\\.\\*)?s; %c\n"; RAW_CHECK(Format); - RAW_CHECK(BufferLength > 0); - const char *BufferEnd = &Buffer[BufferLength - 1]; const char *Cur = Format; - int Res = 0; for (; *Cur; Cur++) { if (*Cur != '%') { - Res += appendChar(&Buffer, BufferEnd, *Cur); + String.push_back(*Cur); continue; } Cur++; @@ -162,7 +152,7 @@ static int formatString(char *Buffer, uptr BufferLength, const char *Format, DVal = HaveLL ? va_arg(Args, s64) : HaveZ ? va_arg(Args, sptr) : va_arg(Args, int); - Res += appendSignedDecimal(&Buffer, BufferEnd, DVal, Width, PadWithZero); + appendSignedDecimal(DVal, Width, PadWithZero); break; } case 'u': @@ -172,27 +162,25 @@ static int formatString(char *Buffer, uptr BufferLength, const char *Format, : HaveZ ? va_arg(Args, uptr) : va_arg(Args, unsigned); const bool Upper = (*Cur == 'X'); - Res += appendUnsigned(&Buffer, BufferEnd, UVal, (*Cur == 'u') ? 10 : 16, - Width, PadWithZero, Upper); + appendUnsigned(UVal, (*Cur == 'u') ? 10 : 16, Width, PadWithZero, Upper); break; } case 'p': { RAW_CHECK_MSG(!HaveFlags, PrintfFormatsHelp); - Res += appendPointer(&Buffer, BufferEnd, va_arg(Args, uptr)); + appendPointer(va_arg(Args, uptr)); break; } case 's': { RAW_CHECK_MSG(!HaveLength, PrintfFormatsHelp); // Only left-justified Width is supported. CHECK(!HaveWidth || LeftJustified); - Res += appendString(&Buffer, BufferEnd, LeftJustified ? -Width : Width, - Precision, va_arg(Args, char *)); + appendString(LeftJustified ? -Width : Width, Precision, + va_arg(Args, char *)); break; } case 'c': { RAW_CHECK_MSG(!HaveFlags, PrintfFormatsHelp); - Res += - appendChar(&Buffer, BufferEnd, static_cast<char>(va_arg(Args, int))); + String.push_back(static_cast<char>(va_arg(Args, int))); break; } // In Scudo, `s64`/`u64` are supposed to use `lld` and `llu` respectively. @@ -207,19 +195,17 @@ static int formatString(char *Buffer, uptr BufferLength, const char *Format, if (*Cur == 'd') { DVal = va_arg(Args, s64); - Res += - appendSignedDecimal(&Buffer, BufferEnd, DVal, Width, PadWithZero); + appendSignedDecimal(DVal, Width, PadWithZero); } else { UVal = va_arg(Args, u64); - Res += appendUnsigned(&Buffer, BufferEnd, UVal, 10, Width, PadWithZero, - false); + appendUnsigned(UVal, 10, Width, PadWithZero, false); } break; } case '%': { RAW_CHECK_MSG(!HaveFlags, PrintfFormatsHelp); - Res += appendChar(&Buffer, BufferEnd, '%'); + String.push_back('%'); break; } default: { @@ -227,35 +213,13 @@ static int formatString(char *Buffer, uptr BufferLength, const char *Format, } } } - RAW_CHECK(Buffer <= BufferEnd); - appendChar(&Buffer, BufferEnd + 1, '\0'); - return Res; -} - -int formatString(char *Buffer, uptr BufferLength, const char *Format, ...) { - va_list Args; - va_start(Args, Format); - int Res = formatString(Buffer, BufferLength, Format, Args); - va_end(Args); - return Res; -} - -void ScopedString::vappend(const char *Format, va_list Args) { - va_list ArgsCopy; - va_copy(ArgsCopy, Args); - // formatString doesn't currently support a null buffer or zero buffer length, - // so in order to get the resulting formatted string length, we use a one-char - // buffer. - char C[1]; - const uptr AdditionalLength = - static_cast<uptr>(formatString(C, sizeof(C), Format, Args)) + 1; - const uptr Length = length(); - String.resize(Length + AdditionalLength); - const uptr FormattedLength = static_cast<uptr>(formatString( - String.data() + Length, String.size() - Length, Format, ArgsCopy)); - RAW_CHECK(data()[length()] == '\0'); - RAW_CHECK(FormattedLength + 1 == AdditionalLength); - va_end(ArgsCopy); + String.push_back('\0'); + if (String.back() != '\0') { + // String truncated, make sure the string is terminated properly. + // This can happen if there is no more memory when trying to resize + // the string. + String.back() = '\0'; + } } void ScopedString::append(const char *Format, ...) { diff --git a/compiler-rt/lib/scudo/standalone/string_utils.h b/compiler-rt/lib/scudo/standalone/string_utils.h index a4cab5268ede4a63c2c3510bb162e24634a7b009..6e00b637797374a66f6c24f17d4c6148eb9c8287 100644 --- a/compiler-rt/lib/scudo/standalone/string_utils.h +++ b/compiler-rt/lib/scudo/standalone/string_utils.h @@ -25,17 +25,24 @@ public: String.clear(); String.push_back('\0'); } - void vappend(const char *Format, va_list Args); + void vappend(const char *Format, va_list &Args); void append(const char *Format, ...) FORMAT(2, 3); void output() const { outputRaw(String.data()); } void reserve(size_t Size) { String.reserve(Size + 1); } + uptr capacity() { return String.capacity() - 1; } private: + void appendNumber(u64 AbsoluteValue, u8 Base, u8 MinNumberLength, + bool PadWithZero, bool Negative, bool Upper); + void appendUnsigned(u64 Num, u8 Base, u8 MinNumberLength, bool PadWithZero, + bool Upper); + void appendSignedDecimal(s64 Num, u8 MinNumberLength, bool PadWithZero); + void appendString(int Width, int MaxChars, const char *S); + void appendPointer(u64 ptr_value); + Vector<char> String; }; -int formatString(char *Buffer, uptr BufferLength, const char *Format, ...) - FORMAT(3, 4); void Printf(const char *Format, ...) FORMAT(1, 2); } // namespace scudo diff --git a/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt b/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt index c6b6a1cb57ceea68d55ac6c9181c88028d2630f2..1786756fa5ea6855761ecc180c0ea0f7c855486f 100644 --- a/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt +++ b/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt @@ -81,7 +81,7 @@ macro(add_scudo_unittest testname) "${testname}-${arch}-Test" ${arch} SOURCES ${TEST_SOURCES} ${COMPILER_RT_GTEST_SOURCE} COMPILE_DEPS ${SCUDO_TEST_HEADERS} - DEPS llvm_gtest scudo_standalone + DEPS scudo_standalone RUNTIME ${RUNTIME} CFLAGS ${SCUDO_UNITTEST_CFLAGS} LINK_FLAGS ${SCUDO_UNITTEST_LINK_FLAGS}) @@ -90,6 +90,7 @@ macro(add_scudo_unittest testname) endmacro() set(SCUDO_UNIT_TEST_SOURCES + allocator_config_test.cpp atomic_test.cpp bytemap_test.cpp checksum_test.cpp diff --git a/compiler-rt/lib/scudo/standalone/tests/allocator_config_test.cpp b/compiler-rt/lib/scudo/standalone/tests/allocator_config_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4c4ceb832e27b11f32fc433cfeade8882dfd5fb7 --- /dev/null +++ b/compiler-rt/lib/scudo/standalone/tests/allocator_config_test.cpp @@ -0,0 +1,119 @@ +//===-- allocator_config_test.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 "tests/scudo_unit_test.h" + +#include "allocator_config.h" +#include "allocator_config_wrapper.h" +#include "common.h" +#include "secondary.h" + +#include <type_traits> + +struct TestBaseConfig { + template <typename> using TSDRegistryT = void; + template <typename> using PrimaryT = void; + template <typename> using SecondaryT = void; +}; + +struct TestBaseConfigEnableOptionalFlag : public TestBaseConfig { + static const bool MaySupportMemoryTagging = true; + // Use the getter to avoid the test to `use` the address of static const + // variable (which requires additional explicit definition). + static bool getMaySupportMemoryTagging() { return MaySupportMemoryTagging; } +}; + +struct TestBasePrimaryConfig { + using SizeClassMap = void; + static const scudo::uptr RegionSizeLog = 18U; + static const scudo::uptr GroupSizeLog = 18U; + static const scudo::s32 MinReleaseToOsIntervalMs = INT32_MIN; + static const scudo::s32 MaxReleaseToOsIntervalMs = INT32_MAX; + typedef scudo::uptr CompactPtrT; + static const scudo::uptr CompactPtrScale = 0; + static const scudo::uptr MapSizeIncrement = 1UL << 18; +}; + +struct TestPrimaryConfig : public TestBaseConfig { + struct Primary : TestBasePrimaryConfig {}; +}; + +struct TestPrimaryConfigEnableOptionalFlag : public TestBaseConfig { + struct Primary : TestBasePrimaryConfig { + static const bool EnableRandomOffset = true; + static bool getEnableRandomOffset() { return EnableRandomOffset; } + }; +}; + +struct TestPrimaryConfigEnableOptionalType : public TestBaseConfig { + struct DummyConditionVariable {}; + + struct Primary : TestBasePrimaryConfig { + using ConditionVariableT = DummyConditionVariable; + }; +}; + +struct TestSecondaryConfig : public TestPrimaryConfig { + struct Secondary { + template <typename Config> + using CacheT = scudo::MapAllocatorNoCache<Config>; + }; +}; + +struct TestSecondaryCacheConfigEnableOptionalFlag : public TestPrimaryConfig { + struct Secondary { + struct Cache { + static const scudo::u32 EntriesArraySize = 256U; + static scudo::u32 getEntriesArraySize() { return EntriesArraySize; } + }; + template <typename T> using CacheT = scudo::MapAllocatorCache<T>; + }; +}; + +TEST(ScudoAllocatorConfigTest, VerifyOptionalFlags) { + // Test the top level allocator optional config. + // + // `MaySupportMemoryTagging` is default off. + EXPECT_FALSE(scudo::BaseConfig<TestBaseConfig>::getMaySupportMemoryTagging()); + EXPECT_EQ(scudo::BaseConfig< + TestBaseConfigEnableOptionalFlag>::getMaySupportMemoryTagging(), + TestBaseConfigEnableOptionalFlag::getMaySupportMemoryTagging()); + + // Test primary optional config. + // + // `EnableRandomeOffset` is default off. + EXPECT_FALSE( + scudo::PrimaryConfig<TestPrimaryConfig>::getEnableRandomOffset()); + EXPECT_EQ( + scudo::PrimaryConfig< + TestPrimaryConfigEnableOptionalFlag>::getEnableRandomOffset(), + TestPrimaryConfigEnableOptionalFlag::Primary::getEnableRandomOffset()); + + // `ConditionVariableT` is default off. + EXPECT_FALSE( + scudo::PrimaryConfig<TestPrimaryConfig>::hasConditionVariableT()); + EXPECT_TRUE(scudo::PrimaryConfig< + TestPrimaryConfigEnableOptionalType>::hasConditionVariableT()); + EXPECT_TRUE((std::is_same_v< + typename scudo::PrimaryConfig< + TestPrimaryConfigEnableOptionalType>::ConditionVariableT, + typename TestPrimaryConfigEnableOptionalType::Primary:: + ConditionVariableT>)); + + // Test secondary cache optional config. + using NoCacheConfig = + scudo::SecondaryConfig<TestSecondaryConfig>::CacheConfig; + // `EntriesArraySize` is default 0. + EXPECT_EQ(NoCacheConfig::getEntriesArraySize(), 0U); + + using CacheConfig = scudo::SecondaryConfig< + TestSecondaryCacheConfigEnableOptionalFlag>::CacheConfig; + EXPECT_EQ(CacheConfig::getEntriesArraySize(), + TestSecondaryCacheConfigEnableOptionalFlag::Secondary::Cache:: + getEntriesArraySize()); +} diff --git a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp index 13d627b116809b371de5a28666e14cc62797e2b1..1a36155bcd423a05139074546e0e506cc14aa0dc 100644 --- a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp @@ -190,7 +190,6 @@ struct TestConditionVariableConfig { #endif static const scudo::s32 MinReleaseToOsIntervalMs = 1000; static const scudo::s32 MaxReleaseToOsIntervalMs = 1000; - static const bool UseConditionVariable = true; #if SCUDO_LINUX using ConditionVariableT = scudo::ConditionVariableLinux; #else @@ -868,32 +867,86 @@ SCUDO_TYPED_TEST(ScudoCombinedTest, ReallocateInPlaceStress) { } } +SCUDO_TYPED_TEST(ScudoCombinedTest, RingBufferDefaultDisabled) { + // The RingBuffer is not initialized until tracking is enabled for the + // first time. + auto *Allocator = this->Allocator.get(); + EXPECT_EQ(0u, Allocator->getRingBufferSize()); + EXPECT_EQ(nullptr, Allocator->getRingBufferAddress()); +} + +SCUDO_TYPED_TEST(ScudoCombinedTest, RingBufferInitOnce) { + auto *Allocator = this->Allocator.get(); + Allocator->setTrackAllocationStacks(true); + + auto RingBufferSize = Allocator->getRingBufferSize(); + ASSERT_GT(RingBufferSize, 0u); + auto *RingBufferAddress = Allocator->getRingBufferAddress(); + EXPECT_NE(nullptr, RingBufferAddress); + + // Enable tracking again to verify that the initialization only happens once. + Allocator->setTrackAllocationStacks(true); + ASSERT_EQ(RingBufferSize, Allocator->getRingBufferSize()); + EXPECT_EQ(RingBufferAddress, Allocator->getRingBufferAddress()); +} + SCUDO_TYPED_TEST(ScudoCombinedTest, RingBufferSize) { auto *Allocator = this->Allocator.get(); - auto Size = Allocator->getRingBufferSize(); - ASSERT_GT(Size, 0u); - EXPECT_EQ(Allocator->getRingBufferAddress()[Size - 1], '\0'); + Allocator->setTrackAllocationStacks(true); + + auto RingBufferSize = Allocator->getRingBufferSize(); + ASSERT_GT(RingBufferSize, 0u); + EXPECT_EQ(Allocator->getRingBufferAddress()[RingBufferSize - 1], '\0'); } SCUDO_TYPED_TEST(ScudoCombinedTest, RingBufferAddress) { auto *Allocator = this->Allocator.get(); - auto *Addr = Allocator->getRingBufferAddress(); - EXPECT_NE(Addr, nullptr); - EXPECT_EQ(Addr, Allocator->getRingBufferAddress()); + Allocator->setTrackAllocationStacks(true); + + auto *RingBufferAddress = Allocator->getRingBufferAddress(); + EXPECT_NE(RingBufferAddress, nullptr); + EXPECT_EQ(RingBufferAddress, Allocator->getRingBufferAddress()); +} + +SCUDO_TYPED_TEST(ScudoCombinedTest, StackDepotDefaultDisabled) { + // The StackDepot is not initialized until tracking is enabled for the + // first time. + auto *Allocator = this->Allocator.get(); + EXPECT_EQ(0u, Allocator->getStackDepotSize()); + EXPECT_EQ(nullptr, Allocator->getStackDepotAddress()); +} + +SCUDO_TYPED_TEST(ScudoCombinedTest, StackDepotInitOnce) { + auto *Allocator = this->Allocator.get(); + Allocator->setTrackAllocationStacks(true); + + auto StackDepotSize = Allocator->getStackDepotSize(); + EXPECT_GT(StackDepotSize, 0u); + auto *StackDepotAddress = Allocator->getStackDepotAddress(); + EXPECT_NE(nullptr, StackDepotAddress); + + // Enable tracking again to verify that the initialization only happens once. + Allocator->setTrackAllocationStacks(true); + EXPECT_EQ(StackDepotSize, Allocator->getStackDepotSize()); + EXPECT_EQ(StackDepotAddress, Allocator->getStackDepotAddress()); } SCUDO_TYPED_TEST(ScudoCombinedTest, StackDepotSize) { auto *Allocator = this->Allocator.get(); - auto Size = Allocator->getStackDepotSize(); - ASSERT_GT(Size, 0u); - EXPECT_EQ(Allocator->getStackDepotAddress()[Size - 1], '\0'); + Allocator->setTrackAllocationStacks(true); + + auto StackDepotSize = Allocator->getStackDepotSize(); + EXPECT_GT(StackDepotSize, 0u); + EXPECT_EQ(Allocator->getStackDepotAddress()[StackDepotSize - 1], '\0'); } SCUDO_TYPED_TEST(ScudoCombinedTest, StackDepotAddress) { auto *Allocator = this->Allocator.get(); - auto *Addr = Allocator->getStackDepotAddress(); - EXPECT_NE(Addr, nullptr); - EXPECT_EQ(Addr, Allocator->getStackDepotAddress()); + Allocator->setTrackAllocationStacks(true); + + auto *StackDepotAddress = Allocator->getStackDepotAddress(); + EXPECT_NE(StackDepotAddress, nullptr); + EXPECT_EQ(StackDepotAddress, Allocator->getStackDepotAddress()); } SCUDO_TYPED_TEST(ScudoCombinedTest, StackDepot) { diff --git a/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp b/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp index f64a5143b30d4649b70dbd5820c28f8803eff45f..683ce3e596596d4dad6d9eb96228157ad3227395 100644 --- a/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp @@ -9,6 +9,7 @@ #include "tests/scudo_unit_test.h" #include "allocator_config.h" +#include "allocator_config_wrapper.h" #include "condition_variable.h" #include "primary32.h" #include "primary64.h" @@ -29,6 +30,9 @@ template <typename SizeClassMapT> struct TestConfig1 { static const bool MaySupportMemoryTagging = false; + template <typename> using TSDRegistryT = void; + template <typename> using PrimaryT = void; + template <typename> using SecondaryT = void; struct Primary { using SizeClassMap = SizeClassMapT; @@ -45,6 +49,9 @@ template <typename SizeClassMapT> struct TestConfig1 { template <typename SizeClassMapT> struct TestConfig2 { static const bool MaySupportMemoryTagging = false; + template <typename> using TSDRegistryT = void; + template <typename> using PrimaryT = void; + template <typename> using SecondaryT = void; struct Primary { using SizeClassMap = SizeClassMapT; @@ -66,6 +73,9 @@ template <typename SizeClassMapT> struct TestConfig2 { template <typename SizeClassMapT> struct TestConfig3 { static const bool MaySupportMemoryTagging = true; + template <typename> using TSDRegistryT = void; + template <typename> using PrimaryT = void; + template <typename> using SecondaryT = void; struct Primary { using SizeClassMap = SizeClassMapT; @@ -87,6 +97,9 @@ template <typename SizeClassMapT> struct TestConfig3 { template <typename SizeClassMapT> struct TestConfig4 { static const bool MaySupportMemoryTagging = true; + template <typename> using TSDRegistryT = void; + template <typename> using PrimaryT = void; + template <typename> using SecondaryT = void; struct Primary { using SizeClassMap = SizeClassMapT; @@ -109,6 +122,9 @@ template <typename SizeClassMapT> struct TestConfig4 { // This is the only test config that enables the condition variable. template <typename SizeClassMapT> struct TestConfig5 { static const bool MaySupportMemoryTagging = true; + template <typename> using TSDRegistryT = void; + template <typename> using PrimaryT = void; + template <typename> using SecondaryT = void; struct Primary { using SizeClassMap = SizeClassMapT; @@ -125,7 +141,6 @@ template <typename SizeClassMapT> struct TestConfig5 { typedef scudo::u32 CompactPtrT; static const bool EnableRandomOffset = true; static const scudo::uptr MapSizeIncrement = 1UL << 18; - static const bool UseConditionVariable = true; #if SCUDO_LINUX using ConditionVariableT = scudo::ConditionVariableLinux; #else @@ -139,10 +154,12 @@ struct Config : public BaseConfig<SizeClassMapT> {}; template <template <typename> class BaseConfig, typename SizeClassMapT> struct SizeClassAllocator - : public scudo::SizeClassAllocator64<Config<BaseConfig, SizeClassMapT>> {}; + : public scudo::SizeClassAllocator64< + scudo::PrimaryConfig<Config<BaseConfig, SizeClassMapT>>> {}; template <typename SizeClassMapT> struct SizeClassAllocator<TestConfig1, SizeClassMapT> - : public scudo::SizeClassAllocator32<Config<TestConfig1, SizeClassMapT>> {}; + : public scudo::SizeClassAllocator32< + scudo::PrimaryConfig<Config<TestConfig1, SizeClassMapT>>> {}; template <template <typename> class BaseConfig, typename SizeClassMapT> struct TestAllocator : public SizeClassAllocator<BaseConfig, SizeClassMapT> { @@ -219,6 +236,9 @@ SCUDO_TYPED_TEST(ScudoPrimaryTest, BasicPrimary) { struct SmallRegionsConfig { static const bool MaySupportMemoryTagging = false; + template <typename> using TSDRegistryT = void; + template <typename> using PrimaryT = void; + template <typename> using SecondaryT = void; struct Primary { using SizeClassMap = scudo::DefaultSizeClassMap; @@ -236,7 +256,8 @@ struct SmallRegionsConfig { // The 64-bit SizeClassAllocator can be easily OOM'd with small region sizes. // For the 32-bit one, it requires actually exhausting memory, so we skip it. TEST(ScudoPrimaryTest, Primary64OOM) { - using Primary = scudo::SizeClassAllocator64<SmallRegionsConfig>; + using Primary = + scudo::SizeClassAllocator64<scudo::PrimaryConfig<SmallRegionsConfig>>; Primary Allocator; Allocator.init(/*ReleaseToOsInterval=*/-1); typename Primary::CacheT Cache; diff --git a/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp b/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp index 18d2e187fa3ce25448f85a6e77ee40625c31cd48..8f0250e88ebf3a6e6b11f17c84398808eca192ac 100644 --- a/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp @@ -10,6 +10,7 @@ #include "tests/scudo_unit_test.h" #include "allocator_config.h" +#include "allocator_config_wrapper.h" #include "secondary.h" #include <algorithm> @@ -22,7 +23,8 @@ #include <vector> template <typename Config> static scudo::Options getOptionsForConfig() { - if (!Config::MaySupportMemoryTagging || !scudo::archSupportsMemoryTagging() || + if (!Config::getMaySupportMemoryTagging() || + !scudo::archSupportsMemoryTagging() || !scudo::systemSupportsMemoryTagging()) return {}; scudo::AtomicOptions AO; @@ -31,8 +33,9 @@ template <typename Config> static scudo::Options getOptionsForConfig() { } template <typename Config> static void testSecondaryBasic(void) { - using SecondaryT = scudo::MapAllocator<Config>; - scudo::Options Options = getOptionsForConfig<Config>(); + using SecondaryT = scudo::MapAllocator<scudo::SecondaryConfig<Config>>; + scudo::Options Options = + getOptionsForConfig<scudo::SecondaryConfig<Config>>(); scudo::GlobalStats S; S.init(); @@ -84,6 +87,10 @@ template <typename Config> static void testSecondaryBasic(void) { struct NoCacheConfig { static const bool MaySupportMemoryTagging = false; + template <typename> using TSDRegistryT = void; + template <typename> using PrimaryT = void; + template <typename Config> using SecondaryT = scudo::MapAllocator<Config>; + struct Secondary { template <typename Config> using CacheT = scudo::MapAllocatorNoCache<Config>; @@ -92,6 +99,10 @@ struct NoCacheConfig { struct TestConfig { static const bool MaySupportMemoryTagging = false; + template <typename> using TSDRegistryT = void; + template <typename> using PrimaryT = void; + template <typename> using SecondaryT = void; + struct Secondary { struct Cache { static const scudo::u32 EntriesArraySize = 128U; @@ -114,7 +125,7 @@ TEST(ScudoSecondaryTest, SecondaryBasic) { struct MapAllocatorTest : public Test { using Config = scudo::DefaultConfig; - using LargeAllocator = scudo::MapAllocator<Config>; + using LargeAllocator = scudo::MapAllocator<scudo::SecondaryConfig<Config>>; void SetUp() override { Allocator->init(nullptr); } @@ -122,7 +133,8 @@ struct MapAllocatorTest : public Test { std::unique_ptr<LargeAllocator> Allocator = std::make_unique<LargeAllocator>(); - scudo::Options Options = getOptionsForConfig<Config>(); + scudo::Options Options = + getOptionsForConfig<scudo::SecondaryConfig<Config>>(); }; // This exercises a variety of combinations of size and alignment for the diff --git a/compiler-rt/lib/scudo/standalone/tests/strings_test.cpp b/compiler-rt/lib/scudo/standalone/tests/strings_test.cpp index 7a69ffd9762c52ceea16e6a8cc66b1996de6b75e..abb81803f65ee136beb3d529031ccd576a0ca750 100644 --- a/compiler-rt/lib/scudo/standalone/tests/strings_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/strings_test.cpp @@ -66,6 +66,10 @@ TEST(ScudoStringsTest, Precision) { Str.append("%-6s", "12345"); EXPECT_EQ(Str.length(), strlen(Str.data())); EXPECT_STREQ("12345 ", Str.data()); + Str.clear(); + Str.append("%-8s", "12345"); + EXPECT_EQ(Str.length(), strlen(Str.data())); + EXPECT_STREQ("12345 ", Str.data()); } static void fillString(scudo::ScopedString &Str, scudo::uptr Size) { @@ -123,3 +127,42 @@ TEST(ScudoStringsTest, Padding) { testAgainstLibc<int>("%03d - %03d", 12, 1234); testAgainstLibc<int>("%03d - %03d", -12, -1234); } + +#if defined(__linux__) + +#include <sys/resource.h> + +TEST(ScudoStringsTest, CapacityIncreaseFails) { + scudo::ScopedString Str; + + rlimit Limit = {}; + EXPECT_EQ(0, getrlimit(RLIMIT_AS, &Limit)); + + rlimit EmptyLimit = {.rlim_cur = 0, .rlim_max = Limit.rlim_max}; + EXPECT_EQ(0, setrlimit(RLIMIT_AS, &EmptyLimit)); + + // qemu does not honor the setrlimit, so verify before proceeding. + scudo::MemMapT MemMap; + if (MemMap.map(/*Addr=*/0U, scudo::getPageSizeCached(), "scudo:test", + MAP_ALLOWNOMEM)) { + MemMap.unmap(MemMap.getBase(), MemMap.getCapacity()); + setrlimit(RLIMIT_AS, &Limit); + GTEST_SKIP() << "Limiting address space does not prevent mmap."; + } + + // Test requires that the default length is at least 6 characters. + scudo::uptr MaxSize = Str.capacity(); + EXPECT_LE(6u, MaxSize); + + for (size_t i = 0; i < MaxSize - 5; i++) { + Str.append("B"); + } + + // Attempt to append past the end of the current capacity. + Str.append("%d", 12345678); + EXPECT_EQ(MaxSize, Str.capacity()); + EXPECT_STREQ("B12345", &Str.data()[MaxSize - 6]); + + EXPECT_EQ(0, setrlimit(RLIMIT_AS, &Limit)); +} +#endif diff --git a/compiler-rt/lib/scudo/standalone/tests/vector_test.cpp b/compiler-rt/lib/scudo/standalone/tests/vector_test.cpp index dc23c2a3471310f7bdbdcc165e43e07e2635f7eb..b612676b7bd79766c20dbad3059379fa1e75d53b 100644 --- a/compiler-rt/lib/scudo/standalone/tests/vector_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/vector_test.cpp @@ -41,3 +41,47 @@ TEST(ScudoVectorTest, ResizeReduction) { V.resize(1); EXPECT_EQ(V.size(), 1U); } + +#if defined(__linux__) + +#include <sys/resource.h> + +// Verify that if the reallocate fails, nothing new is added. +TEST(ScudoVectorTest, ReallocateFails) { + scudo::Vector<char> V; + scudo::uptr capacity = V.capacity(); + + // Get the current address space size. + rlimit Limit = {}; + EXPECT_EQ(0, getrlimit(RLIMIT_AS, &Limit)); + + rlimit EmptyLimit = {.rlim_cur = 0, .rlim_max = Limit.rlim_max}; + EXPECT_EQ(0, setrlimit(RLIMIT_AS, &EmptyLimit)); + + // qemu does not honor the setrlimit, so verify before proceeding. + scudo::MemMapT MemMap; + if (MemMap.map(/*Addr=*/0U, scudo::getPageSizeCached(), "scudo:test", + MAP_ALLOWNOMEM)) { + MemMap.unmap(MemMap.getBase(), MemMap.getCapacity()); + setrlimit(RLIMIT_AS, &Limit); + GTEST_SKIP() << "Limiting address space does not prevent mmap."; + } + + V.resize(capacity); + // Set the last element so we can check it later. + V.back() = '\0'; + + // The reallocate should fail, so the capacity should not change. + V.reserve(capacity + 1000); + EXPECT_EQ(capacity, V.capacity()); + + // Now try to do a push back and verify that the size does not change. + scudo::uptr Size = V.size(); + V.push_back('2'); + EXPECT_EQ(Size, V.size()); + // Verify that the last element in the vector did not change. + EXPECT_EQ('\0', V.back()); + + EXPECT_EQ(0, setrlimit(RLIMIT_AS, &Limit)); +} +#endif diff --git a/compiler-rt/lib/scudo/standalone/tsd.h b/compiler-rt/lib/scudo/standalone/tsd.h index b2108a01900bcce5b20d1c2615eb4168865f4457..72773f2f72b1163ad8f9864fb56a28256760b1bd 100644 --- a/compiler-rt/lib/scudo/standalone/tsd.h +++ b/compiler-rt/lib/scudo/standalone/tsd.h @@ -41,9 +41,9 @@ template <class Allocator> struct alignas(SCUDO_CACHE_LINE_SIZE) TSD { return true; } if (atomic_load_relaxed(&Precedence) == 0) - atomic_store_relaxed(&Precedence, - static_cast<uptr>(getMonotonicTimeFast() >> - FIRST_32_SECOND_64(16, 0))); + atomic_store_relaxed( + &Precedence, + static_cast<uptr>(getMonotonicTime() >> FIRST_32_SECOND_64(16, 0))); return false; } inline void lock() NO_THREAD_SAFETY_ANALYSIS { diff --git a/compiler-rt/lib/scudo/standalone/vector.h b/compiler-rt/lib/scudo/standalone/vector.h index c0f1ba0eddfa91e90458c692d27ee785903d68b6..ca10cc281d770100c657cff879e63a06f61fe8c8 100644 --- a/compiler-rt/lib/scudo/standalone/vector.h +++ b/compiler-rt/lib/scudo/standalone/vector.h @@ -35,7 +35,9 @@ public: DCHECK_LE(Size, capacity()); if (Size == capacity()) { const uptr NewCapacity = roundUpPowerOfTwo(Size + 1); - reallocate(NewCapacity); + if (!reallocate(NewCapacity)) { + return; + } } memcpy(&Data[Size++], &Element, sizeof(T)); } @@ -51,14 +53,17 @@ public: const T *data() const { return Data; } T *data() { return Data; } constexpr uptr capacity() const { return CapacityBytes / sizeof(T); } - void reserve(uptr NewSize) { + bool reserve(uptr NewSize) { // Never downsize internal buffer. if (NewSize > capacity()) - reallocate(NewSize); + return reallocate(NewSize); + return true; } void resize(uptr NewSize) { if (NewSize > Size) { - reserve(NewSize); + if (!reserve(NewSize)) { + return; + } memset(&Data[Size], 0, sizeof(T) * (NewSize - Size)); } Size = NewSize; @@ -86,13 +91,16 @@ protected: } private: - void reallocate(uptr NewCapacity) { + bool reallocate(uptr NewCapacity) { DCHECK_GT(NewCapacity, 0); DCHECK_LE(Size, NewCapacity); MemMapT NewExternalBuffer; NewCapacity = roundUp(NewCapacity * sizeof(T), getPageSizeCached()); - NewExternalBuffer.map(/*Addr=*/0U, NewCapacity, "scudo:vector"); + if (!NewExternalBuffer.map(/*Addr=*/0U, NewCapacity, "scudo:vector", + MAP_ALLOWNOMEM)) { + return false; + } T *NewExternalData = reinterpret_cast<T *>(NewExternalBuffer.getBase()); memcpy(NewExternalData, Data, Size * sizeof(T)); @@ -101,6 +109,7 @@ private: Data = NewExternalData; CapacityBytes = NewCapacity; ExternalBuffer = NewExternalBuffer; + return true; } T *Data = nullptr; diff --git a/compiler-rt/lib/scudo/standalone/wrappers_c.inc b/compiler-rt/lib/scudo/standalone/wrappers_c.inc index 56d8ef20156e2877ea81255972d43d0a6a1421c7..21d5b7add51275835bb6707f12169c79366f493b 100644 --- a/compiler-rt/lib/scudo/standalone/wrappers_c.inc +++ b/compiler-rt/lib/scudo/standalone/wrappers_c.inc @@ -247,6 +247,11 @@ void SCUDO_PREFIX(malloc_postinit)() { INTERFACE WEAK int SCUDO_PREFIX(mallopt)(int param, int value) { if (param == M_DECAY_TIME) { if (SCUDO_ANDROID) { + // Before changing the interval, reset the memory usage status by doing a + // M_PURGE call so that we can minimize the impact of any unreleased pages + // introduced by interval transition. + SCUDO_ALLOCATOR.releaseToOS(scudo::ReleaseToOS::Force); + if (value == 0) { // Will set the release values to their minimum values. value = INT32_MIN; diff --git a/compiler-rt/lib/scudo/standalone/wrappers_c_checks.h b/compiler-rt/lib/scudo/standalone/wrappers_c_checks.h index 9cd48e82792e0d54f7caa34828555e0fd6c774bb..d0288699cf1b1fd186927d9e857d72644da61023 100644 --- a/compiler-rt/lib/scudo/standalone/wrappers_c_checks.h +++ b/compiler-rt/lib/scudo/standalone/wrappers_c_checks.h @@ -31,15 +31,13 @@ inline void *setErrnoOnNull(void *Ptr) { // Checks aligned_alloc() parameters, verifies that the alignment is a power of // two and that the size is a multiple of alignment. inline bool checkAlignedAllocAlignmentAndSize(uptr Alignment, uptr Size) { - return Alignment == 0 || !isPowerOfTwo(Alignment) || - !isAligned(Size, Alignment); + return !isPowerOfTwo(Alignment) || !isAligned(Size, Alignment); } // Checks posix_memalign() parameters, verifies that alignment is a power of two // and a multiple of sizeof(void *). inline bool checkPosixMemalignAlignment(uptr Alignment) { - return Alignment == 0 || !isPowerOfTwo(Alignment) || - !isAligned(Alignment, sizeof(void *)); + return !isPowerOfTwo(Alignment) || !isAligned(Alignment, sizeof(void *)); } // Returns true if calloc(Size, N) overflows on Size*N calculation. Use a diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp index 24309ab66b2e671ad3917b168055d411a1e79330..94adea777cafd9e792bc80d8b25d82fb08faff8d 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -14,6 +14,7 @@ #include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_errno.h" +#include "sanitizer_common/sanitizer_glibc_version.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_linux.h" #include "sanitizer_common/sanitizer_platform_limits_netbsd.h" @@ -1340,7 +1341,7 @@ TSAN_INTERCEPTOR(int, pthread_mutex_destroy, void *m) { TSAN_INTERCEPTOR(int, pthread_mutex_lock, void *m) { SCOPED_TSAN_INTERCEPTOR(pthread_mutex_lock, m); MutexPreLock(thr, pc, (uptr)m); - int res = REAL(pthread_mutex_lock)(m); + int res = BLOCK_REAL(pthread_mutex_lock)(m); if (res == errno_EOWNERDEAD) MutexRepair(thr, pc, (uptr)m); if (res == 0 || res == errno_EOWNERDEAD) @@ -1385,7 +1386,7 @@ TSAN_INTERCEPTOR(int, pthread_mutex_clocklock, void *m, __sanitizer_clockid_t clock, void *abstime) { SCOPED_TSAN_INTERCEPTOR(pthread_mutex_clocklock, m, clock, abstime); MutexPreLock(thr, pc, (uptr)m); - int res = REAL(pthread_mutex_clocklock)(m, clock, abstime); + int res = BLOCK_REAL(pthread_mutex_clocklock)(m, clock, abstime); if (res == errno_EOWNERDEAD) MutexRepair(thr, pc, (uptr)m); if (res == 0 || res == errno_EOWNERDEAD) @@ -1403,7 +1404,7 @@ TSAN_INTERCEPTOR(int, pthread_mutex_clocklock, void *m, TSAN_INTERCEPTOR(int, __pthread_mutex_lock, void *m) { SCOPED_TSAN_INTERCEPTOR(__pthread_mutex_lock, m); MutexPreLock(thr, pc, (uptr)m); - int res = REAL(__pthread_mutex_lock)(m); + int res = BLOCK_REAL(__pthread_mutex_lock)(m); if (res == errno_EOWNERDEAD) MutexRepair(thr, pc, (uptr)m); if (res == 0 || res == errno_EOWNERDEAD) @@ -1446,7 +1447,7 @@ TSAN_INTERCEPTOR(int, pthread_spin_destroy, void *m) { TSAN_INTERCEPTOR(int, pthread_spin_lock, void *m) { SCOPED_TSAN_INTERCEPTOR(pthread_spin_lock, m); MutexPreLock(thr, pc, (uptr)m); - int res = REAL(pthread_spin_lock)(m); + int res = BLOCK_REAL(pthread_spin_lock)(m); if (res == 0) { MutexPostLock(thr, pc, (uptr)m); } @@ -1521,7 +1522,7 @@ TSAN_INTERCEPTOR(int, pthread_rwlock_timedrdlock, void *m, void *abstime) { TSAN_INTERCEPTOR(int, pthread_rwlock_wrlock, void *m) { SCOPED_TSAN_INTERCEPTOR(pthread_rwlock_wrlock, m); MutexPreLock(thr, pc, (uptr)m); - int res = REAL(pthread_rwlock_wrlock)(m); + int res = BLOCK_REAL(pthread_rwlock_wrlock)(m); if (res == 0) { MutexPostLock(thr, pc, (uptr)m); } @@ -1613,47 +1614,40 @@ TSAN_INTERCEPTOR(int, __fxstat, int version, int fd, void *buf) { FdAccess(thr, pc, fd); return REAL(__fxstat)(version, fd, buf); } -#define TSAN_MAYBE_INTERCEPT___FXSTAT TSAN_INTERCEPT(__fxstat) + +TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { + SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf); + if (fd > 0) + FdAccess(thr, pc, fd); + return REAL(__fxstat64)(version, fd, buf); +} +#define TSAN_MAYBE_INTERCEPT___FXSTAT TSAN_INTERCEPT(__fxstat); TSAN_INTERCEPT(__fxstat64) #else #define TSAN_MAYBE_INTERCEPT___FXSTAT #endif +#if !SANITIZER_GLIBC || __GLIBC_PREREQ(2, 33) TSAN_INTERCEPTOR(int, fstat, int fd, void *buf) { -#if SANITIZER_GLIBC - SCOPED_TSAN_INTERCEPTOR(__fxstat, 0, fd, buf); - if (fd > 0) - FdAccess(thr, pc, fd); - return REAL(__fxstat)(0, fd, buf); -#else SCOPED_TSAN_INTERCEPTOR(fstat, fd, buf); if (fd > 0) FdAccess(thr, pc, fd); return REAL(fstat)(fd, buf); -#endif } - -#if SANITIZER_GLIBC -TSAN_INTERCEPTOR(int, __fxstat64, int version, int fd, void *buf) { - SCOPED_TSAN_INTERCEPTOR(__fxstat64, version, fd, buf); - if (fd > 0) - FdAccess(thr, pc, fd); - return REAL(__fxstat64)(version, fd, buf); -} -#define TSAN_MAYBE_INTERCEPT___FXSTAT64 TSAN_INTERCEPT(__fxstat64) +# define TSAN_MAYBE_INTERCEPT_FSTAT TSAN_INTERCEPT(fstat) #else -#define TSAN_MAYBE_INTERCEPT___FXSTAT64 +# define TSAN_MAYBE_INTERCEPT_FSTAT #endif -#if SANITIZER_GLIBC +#if __GLIBC_PREREQ(2, 33) TSAN_INTERCEPTOR(int, fstat64, int fd, void *buf) { - SCOPED_TSAN_INTERCEPTOR(__fxstat64, 0, fd, buf); + SCOPED_TSAN_INTERCEPTOR(fstat64, fd, buf); if (fd > 0) FdAccess(thr, pc, fd); - return REAL(__fxstat64)(0, fd, buf); + return REAL(fstat64)(fd, buf); } -#define TSAN_MAYBE_INTERCEPT_FSTAT64 TSAN_INTERCEPT(fstat64) +# define TSAN_MAYBE_INTERCEPT_FSTAT64 TSAN_INTERCEPT(fstat64) #else -#define TSAN_MAYBE_INTERCEPT_FSTAT64 +# define TSAN_MAYBE_INTERCEPT_FSTAT64 #endif TSAN_INTERCEPTOR(int, open, const char *name, int oflag, ...) { @@ -2673,6 +2667,25 @@ static USED void syscall_fd_release(uptr pc, int fd) { FdRelease(thr, pc, fd); } +static USED void sycall_blocking_start() { + DPrintf("sycall_blocking_start()\n"); + ThreadState *thr = cur_thread(); + EnterBlockingFunc(thr); + // When we are in a "blocking call", we process signals asynchronously + // (right when they arrive). In this context we do not expect to be + // executing any user/runtime code. The known interceptor sequence when + // this is not true is: pthread_join -> munmap(stack). It's fine + // to ignore munmap in this case -- we handle stack shadow separately. + thr->ignore_interceptors++; +} + +static USED void sycall_blocking_end() { + DPrintf("sycall_blocking_end()\n"); + ThreadState *thr = cur_thread(); + thr->ignore_interceptors--; + atomic_store(&thr->in_blocking_func, 0, memory_order_relaxed); +} + static void syscall_pre_fork(uptr pc) { ForkBefore(cur_thread(), pc); } static void syscall_post_fork(uptr pc, int pid) { @@ -2727,6 +2740,9 @@ static void syscall_post_fork(uptr pc, int pid) { #define COMMON_SYSCALL_POST_FORK(res) \ syscall_post_fork(GET_CALLER_PC(), res) +#define COMMON_SYSCALL_BLOCKING_START() sycall_blocking_start() +#define COMMON_SYSCALL_BLOCKING_END() sycall_blocking_end() + #include "sanitizer_common/sanitizer_common_syscalls.inc" #include "sanitizer_common/sanitizer_syscalls_netbsd.inc" @@ -2861,6 +2877,8 @@ void InitializeInterceptors() { REAL(memcpy) = internal_memcpy; #endif + __interception::DoesNotSupportStaticLinking(); + new(interceptor_ctx()) InterceptorContext(); // Interpose __tls_get_addr before the common interposers. This is needed @@ -2961,10 +2979,9 @@ void InitializeInterceptors() { TSAN_INTERCEPT(pthread_once); - TSAN_INTERCEPT(fstat); TSAN_MAYBE_INTERCEPT___FXSTAT; + TSAN_MAYBE_INTERCEPT_FSTAT; TSAN_MAYBE_INTERCEPT_FSTAT64; - TSAN_MAYBE_INTERCEPT___FXSTAT64; TSAN_INTERCEPT(open); TSAN_MAYBE_INTERCEPT_OPEN64; TSAN_INTERCEPT(creat); diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp index 77488f8432854235476ef9a7301e61e612ae4caa..5316a7862e449ca45e0b4c2bfc2c97cdabace0fb 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp @@ -160,6 +160,10 @@ void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id, } Free(thr->tctx->sync); +#if !SANITIZER_GO + thr->is_inited = true; +#endif + uptr stk_addr = 0; uptr stk_size = 0; uptr tls_addr = 0; @@ -200,15 +204,11 @@ void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id, } void ThreadContext::OnStarted(void *arg) { - thr = static_cast<ThreadState *>(arg); DPrintf("#%d: ThreadStart\n", tid); - new (thr) ThreadState(tid); + thr = new (arg) ThreadState(tid); if (common_flags()->detect_deadlocks) thr->dd_lt = ctx->dd->CreateLogicalThread(tid); thr->tctx = this; -#if !SANITIZER_GO - thr->is_inited = true; -#endif } void ThreadFinish(ThreadState *thr) { diff --git a/compiler-rt/lib/tsan/tests/CMakeLists.txt b/compiler-rt/lib/tsan/tests/CMakeLists.txt index c02c2279583bd15fa05c100832b04af47136ee20..1bc08bbf7450c817ba4523680cadd5ddb6b759e9 100644 --- a/compiler-rt/lib/tsan/tests/CMakeLists.txt +++ b/compiler-rt/lib/tsan/tests/CMakeLists.txt @@ -64,10 +64,10 @@ foreach (header ${TSAN_HEADERS}) list(APPEND TSAN_RTL_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../${header}) endforeach() -set(TSAN_DEPS llvm_gtest tsan) +set(TSAN_DEPS tsan) # TSan uses C++ standard library headers. if (TARGET cxx-headers OR HAVE_LIBCXX) - set(TSAN_DEPS cxx-headers) + list(APPEND TSAN_DEPS cxx-headers) endif() # add_tsan_unittest(<name> diff --git a/compiler-rt/lib/ubsan/CMakeLists.txt b/compiler-rt/lib/ubsan/CMakeLists.txt index 3f1e12ed9ac66fc453e9553b478eb809268bd287..db0b33f1276ef2ea64de74fbed84c3de8ff0a5fe 100644 --- a/compiler-rt/lib/ubsan/CMakeLists.txt +++ b/compiler-rt/lib/ubsan/CMakeLists.txt @@ -41,6 +41,7 @@ set(UBSAN_HEADERS include_directories(..) set(UBSAN_CFLAGS ${SANITIZER_COMMON_CFLAGS}) +append_list_if(MSVC /Zl UBSAN_CFLAGS) append_rtti_flag(OFF UBSAN_CFLAGS) append_list_if(SANITIZER_CAN_USE_CXXABI -DUBSAN_CAN_USE_CXXABI UBSAN_CFLAGS) diff --git a/compiler-rt/lib/xray/tests/CMakeLists.txt b/compiler-rt/lib/xray/tests/CMakeLists.txt index 732f982c932f04f16c59f9f8b2f2287989454be9..0a428b9a30b18b17f7db906957c93f6918e973be 100644 --- a/compiler-rt/lib/xray/tests/CMakeLists.txt +++ b/compiler-rt/lib/xray/tests/CMakeLists.txt @@ -109,7 +109,7 @@ macro(add_xray_unittest testname) ${XRAY_HEADERS} ${XRAY_ALL_SOURCE_FILES_ABS_PATHS} "test_helpers.h" RUNTIME "${XRAY_RUNTIME_LIBS}" - DEPS llvm_gtest xray llvm-xray LLVMXRay LLVMTestingSupport + DEPS xray llvm-xray LLVMXRay LLVMTestingSupport CFLAGS ${XRAY_UNITTEST_CFLAGS} LINK_FLAGS ${TARGET_LINK_FLAGS} ${XRAY_UNITTEST_LINK_FLAGS} ) diff --git a/compiler-rt/test/asan/TestCases/Windows/bitfield_uaf.cpp b/compiler-rt/test/asan/TestCases/Windows/bitfield_uaf.cpp index 8e1a2ae1491486e3cba7de93f5eebc6c5abe74e1..12ed505883e277dfe9a488b0bddaf231c7fa43af 100644 --- a/compiler-rt/test/asan/TestCases/Windows/bitfield_uaf.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/bitfield_uaf.cpp @@ -21,13 +21,13 @@ void make_access(S *s) { int main(void) { S *s = (S*)malloc(sizeof(S)); free(s); -// CHECK: [[ADDR]] is located 0 bytes inside of 4-byte region -// CHECK-LABEL: freed by thread T0 here: -// CHECK: {{#0 .* free }} -// CHECK: {{#1 .* main .*bitfield_uaf.cpp}}:[[@LINE-4]] -// CHECK-LABEL: previously allocated by thread T0 here: -// CHECK: {{#0 .* malloc }} -// CHECK: {{#1 .* main .*bitfield_uaf.cpp}}:[[@LINE-8]] + // CHECK: [[ADDR]] is located 0 bytes inside of 4-byte region + // CHECK-LABEL: freed by thread T0 here: + // CHECK: {{#0 .* free }} + // CHECK: {{ #[1-2] .* main .*bitfield_uaf.cpp}}:[[@LINE-4]] + // CHECK-LABEL: previously allocated by thread T0 here: + // CHECK: {{#0 .* malloc }} + // CHECK: {{ #[1-2] .* main .*bitfield_uaf.cpp}}:[[@LINE-8]] make_access(s); return 0; } diff --git a/compiler-rt/test/asan/TestCases/Windows/calloc_left_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/calloc_left_oob.cpp index b22c359b3dc42f0b6233f8ffd7e1e1346e087fdb..e96fb6190f5a8590dfc4daaa88e0952ab49cc65c 100644 --- a/compiler-rt/test/asan/TestCases/Windows/calloc_left_oob.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/calloc_left_oob.cpp @@ -6,12 +6,12 @@ int main() { int *buffer = (int*)calloc(42, sizeof(int)); buffer[-1] = 42; -// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] -// CHECK: WRITE of size 4 at [[ADDR]] thread T0 -// CHECK-NEXT: {{#0 .* main .*calloc_left_oob.cpp}}:[[@LINE-3]] -// CHECK: [[ADDR]] is located 4 bytes before 168-byte region -// CHECK: allocated by thread T0 here: -// CHECK-NEXT: {{#0 .* calloc }} -// CHECK-NEXT: {{#1 .* main .*calloc_left_oob.cpp}}:[[@LINE-8]] + // CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] + // CHECK: WRITE of size 4 at [[ADDR]] thread T0 + // CHECK-NEXT: {{#0 .* main .*calloc_left_oob.cpp}}:[[@LINE-3]] + // CHECK: [[ADDR]] is located 4 bytes before 168-byte region + // CHECK: allocated by thread T0 here: + // CHECK: {{#0 .* calloc }} + // CHECK: {{ #[1-2] .* main .*calloc_left_oob.cpp}}:[[@LINE-8]] free(buffer); } diff --git a/compiler-rt/test/asan/TestCases/Windows/calloc_right_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/calloc_right_oob.cpp index 9e12f9cf653e09aae009b58137cf8e6941a3c2a7..fe0fc20e1919030eac9b931750b6880e51bd8fc0 100644 --- a/compiler-rt/test/asan/TestCases/Windows/calloc_right_oob.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/calloc_right_oob.cpp @@ -6,12 +6,12 @@ int main() { int *buffer = (int*)calloc(42, sizeof(int)); buffer[42] = 42; -// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] -// CHECK: WRITE of size 4 at [[ADDR]] thread T0 -// CHECK-NEXT: {{#0 .* main .*calloc_right_oob.cpp}}:[[@LINE-3]] -// CHECK: [[ADDR]] is located 0 bytes after 168-byte region -// CHECK: allocated by thread T0 here: -// CHECK-NEXT: {{#0 .* calloc }} -// CHECK-NEXT: {{#1 .* main .*calloc_right_oob.cpp}}:[[@LINE-8]] + // CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] + // CHECK: WRITE of size 4 at [[ADDR]] thread T0 + // CHECK-NEXT: {{#0 .* main .*calloc_right_oob.cpp}}:[[@LINE-3]] + // CHECK: [[ADDR]] is located 0 bytes after 168-byte region + // CHECK: allocated by thread T0 here: + // CHECK-NEXT: {{#0 .* calloc }} + // CHECK: {{ #[1-2] .* main .*calloc_right_oob.cpp}}:[[@LINE-8]] free(buffer); } diff --git a/compiler-rt/test/asan/TestCases/Windows/calloc_uaf.cpp b/compiler-rt/test/asan/TestCases/Windows/calloc_uaf.cpp index 6c225d4c676d08cc6be7117e0ef73d481996295b..bf13f7d3eb662aa06ad094247e6246211fc22b7f 100644 --- a/compiler-rt/test/asan/TestCases/Windows/calloc_uaf.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/calloc_uaf.cpp @@ -7,14 +7,14 @@ int main() { int *buffer = (int*)calloc(42, sizeof(int)); free(buffer); buffer[0] = 42; -// CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]] -// CHECK: WRITE of size 4 at [[ADDR]] thread T0 -// CHECK-NEXT: {{#0 .* main .*calloc_uaf.cpp}}:[[@LINE-3]] -// CHECK: [[ADDR]] is located 0 bytes inside of 168-byte region -// CHECK: freed by thread T0 here: -// CHECK-NEXT: {{#0 .* free }} -// CHECK-NEXT: {{#1 .* main .*calloc_uaf.cpp}}:[[@LINE-8]] -// CHECK: previously allocated by thread T0 here: -// CHECK-NEXT: {{#0 .* calloc }} -// CHECK-NEXT: {{#1 .* main .*calloc_uaf.cpp}}:[[@LINE-12]] + // CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]] + // CHECK: WRITE of size 4 at [[ADDR]] thread T0 + // CHECK-NEXT: {{#0 .* main .*calloc_uaf.cpp}}:[[@LINE-3]] + // CHECK: [[ADDR]] is located 0 bytes inside of 168-byte region + // CHECK: freed by thread T0 here: + // CHECK-NEXT: {{#0 .* free }} + // CHECK: {{ #[1-2] .* main .*calloc_uaf.cpp}}:[[@LINE-8]] + // CHECK: previously allocated by thread T0 here: + // CHECK-NEXT: {{#0 .* calloc }} + // CHECK: {{ #[1-2] .* main .*calloc_uaf.cpp}}:[[@LINE-12]] } diff --git a/compiler-rt/test/asan/TestCases/Windows/dll_heap_allocation.cpp b/compiler-rt/test/asan/TestCases/Windows/dll_heap_allocation.cpp index b8c2c1a24d4ce07eef920eb44f5ccfb5706fb4bb..3606b1c81631717a79a2266fccbd79d3e3897c47 100644 --- a/compiler-rt/test/asan/TestCases/Windows/dll_heap_allocation.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/dll_heap_allocation.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cl %LD %s %Fe%t.dll -DHEAP_LIBRARY %MD \ // RUN: %if target={{.*-windows-gnu}} %{ -Wl,--out-implib,%t.lib %} -// RUN: %clang_cl %s %t.lib %Fe%t -fsanitize=address %MT +// RUN: %clang_cl_asan %s %t.lib %Fe%t // RUN: %run %t 2>&1 | FileCheck %s // Check that ASan does not fail when releasing allocations that occurred within diff --git a/compiler-rt/test/asan/TestCases/Windows/dll_host.cpp b/compiler-rt/test/asan/TestCases/Windows/dll_host.cpp index 0757af90d211c32ca03bf05c9ace6936ba305f78..85b7967e86b5108ffe3764153874b30be0bbdf3a 100644 --- a/compiler-rt/test/asan/TestCases/Windows/dll_host.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/dll_host.cpp @@ -5,48 +5,6 @@ // Just make sure we can compile this. // The actual compile&run sequence is to be done by the DLL tests. // RUN: %clang_cl_asan -Od %s -Fe%t -// -// Get the list of ASan wrappers exported by the main module RTL: -// note: The mangling decoration (i.e. @4 )is removed because calling convention -// differ from 32-bit and 64-bit. -// RUN: dumpbin /EXPORTS %t | grep -o "__asan_wrap[^ ]*" | sed -e s/@.*// > %t.exports1 -// -// The exception handlers differ in 32-bit and 64-bit, so we ignore them: -// RUN: grep '[E]XPORT:' %s | sed -e 's/.*[E]XPORT: //' > %t.exports2 -// EXPORT: __asan_wrap__except_handler3 -// EXPORT: __asan_wrap__except_handler4 -// EXPORT: __asan_wrap___C_specific_handler -// -// Get the list of ASan wrappers imported by the DLL RTL: -// [BEWARE: be really careful with the sed commands, as this test can be run -// from different environments with different shells and seds] -// RUN: grep INTERCEPT_LIBRARY_FUNCTION %p/../../../../lib/asan/asan_win_dll_thunk.cpp \ -// RUN: | grep -v define | sed -e s/.*(/__asan_wrap_/ -e s/).*// \ -// RUN: > %t.imports1 -// -// Add functions interecepted in asan_malloc.win.cpp and asan_win.cpp. -// RUN: grep '[I]MPORT:' %s | sed -e 's/.*[I]MPORT: //' > %t.imports2 -// IMPORT: __asan_wrap_HeapAlloc -// IMPORT: __asan_wrap_HeapFree -// IMPORT: __asan_wrap_HeapReAlloc -// IMPORT: __asan_wrap_HeapSize -// IMPORT: __asan_wrap_CreateThread -// IMPORT: __asan_wrap_RaiseException -// IMPORT: __asan_wrap_RtlRaiseException -// IMPORT: __asan_wrap_SetUnhandledExceptionFilter -// IMPORT: __asan_wrap_RtlSizeHeap -// IMPORT: __asan_wrap_RtlAllocateHeap -// IMPORT: __asan_wrap_RtlReAllocateHeap -// IMPORT: __asan_wrap_RtlFreeHeap -// -// RUN: cat %t.imports1 %t.imports2 | sort | uniq > %t.imports-sorted -// RUN: cat %t.exports1 %t.exports2 | sort | uniq > %t.exports-sorted -// -// Now make sure the DLL thunk imports everything: -// RUN: echo -// RUN: echo "=== NOTE === If you see a mismatch below, please update asan_win_dll_thunk.cpp" -// RUN: diff %t.imports-sorted %t.exports-sorted -// REQUIRES: asan-static-runtime #include <stdio.h> #include <windows.h> diff --git a/compiler-rt/test/asan/TestCases/Windows/dll_malloc_left_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/dll_malloc_left_oob.cpp index 6d550eb966cda3194a8d1bb42d3d3823602ef37a..5ca48fbd68384030153a19278b7187db2c9b0d56 100644 --- a/compiler-rt/test/asan/TestCases/Windows/dll_malloc_left_oob.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/dll_malloc_left_oob.cpp @@ -7,17 +7,17 @@ extern "C" __declspec(dllexport) int test_function() { char *buffer = (char*)malloc(42); buffer[-1] = 42; -// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] -// CHECK: WRITE of size 1 at [[ADDR]] thread T0 -// CHECK-NEXT: test_function {{.*}}dll_malloc_left_oob.cpp:[[@LINE-3]] -// CHECK-NEXT: main {{.*}}dll_host.cpp -// -// CHECK: [[ADDR]] is located 1 bytes before 42-byte region -// CHECK-LABEL: allocated by thread T0 here: -// CHECK-NEXT: malloc -// CHECK-NEXT: test_function {{.*}}dll_malloc_left_oob.cpp:[[@LINE-10]] -// CHECK-NEXT: main {{.*}}dll_host.cpp -// CHECK-LABEL: SUMMARY + // CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] + // CHECK: WRITE of size 1 at [[ADDR]] thread T0 + // CHECK-NEXT: test_function {{.*}}dll_malloc_left_oob.cpp:[[@LINE-3]] + // CHECK-NEXT: main {{.*}}dll_host.cpp + // + // CHECK: [[ADDR]] is located 1 bytes before 42-byte region + // CHECK-LABEL: allocated by thread T0 here: + // CHECK-NEXT: malloc + // CHECK: test_function {{.*}}dll_malloc_left_oob.cpp:[[@LINE-10]] + // CHECK-NEXT: main {{.*}}dll_host.cpp + // CHECK-LABEL: SUMMARY free(buffer); return 0; } diff --git a/compiler-rt/test/asan/TestCases/Windows/dll_malloc_uaf.cpp b/compiler-rt/test/asan/TestCases/Windows/dll_malloc_uaf.cpp index bc701e92961c99e9b7e55ebb15897c5a6462d96b..ae23f86d7ddf4969f86e013deaf5b235be12816b 100644 --- a/compiler-rt/test/asan/TestCases/Windows/dll_malloc_uaf.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/dll_malloc_uaf.cpp @@ -9,20 +9,20 @@ int test_function() { int *buffer = (int*)malloc(42); free(buffer); buffer[0] = 42; -// CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]] -// CHECK: WRITE of size 4 at [[ADDR]] thread T0 -// CHECK-NEXT: test_function {{.*}}dll_malloc_uaf.cpp:[[@LINE-3]] -// CHECK-NEXT: main {{.*}}dll_host -// -// CHECK: [[ADDR]] is located 0 bytes inside of 42-byte region -// CHECK-LABEL: freed by thread T0 here: -// CHECK-NEXT: free -// CHECK-NEXT: test_function {{.*}}dll_malloc_uaf.cpp:[[@LINE-10]] -// CHECK-NEXT: main {{.*}}dll_host -// -// CHECK-LABEL: previously allocated by thread T0 here: -// CHECK-NEXT: malloc -// CHECK-NEXT: test_function {{.*}}dll_malloc_uaf.cpp:[[@LINE-16]] -// CHECK-NEXT: main {{.*}}dll_host + // CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]] + // CHECK: WRITE of size 4 at [[ADDR]] thread T0 + // CHECK-NEXT: test_function {{.*}}dll_malloc_uaf.cpp:[[@LINE-3]] + // CHECK-NEXT: main {{.*}}dll_host + // + // CHECK: [[ADDR]] is located 0 bytes inside of 42-byte region + // CHECK-LABEL: freed by thread T0 here: + // CHECK-NEXT: free + // CHECK: test_function {{.*}}dll_malloc_uaf.cpp:[[@LINE-10]] + // CHECK-NEXT: main {{.*}}dll_host + // + // CHECK-LABEL: previously allocated by thread T0 here: + // CHECK-NEXT: malloc + // CHECK: test_function {{.*}}dll_malloc_uaf.cpp:[[@LINE-16]] + // CHECK-NEXT: main {{.*}}dll_host return 0; } diff --git a/compiler-rt/test/asan/TestCases/Windows/double_free.cpp b/compiler-rt/test/asan/TestCases/Windows/double_free.cpp index 45568e50d0c824d6d5b35b4695a8188bfa851c7e..e288b40fac47a38acfb42d6e6d148c70a55511dd 100644 --- a/compiler-rt/test/asan/TestCases/Windows/double_free.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/double_free.cpp @@ -7,15 +7,15 @@ int main() { int *x = (int*)malloc(42 * sizeof(int)); free(x); free(x); -// CHECK: AddressSanitizer: attempting double-free on [[ADDR:0x[0-9a-f]+]] -// CHECK-NEXT: {{#0 .* free }} -// CHECK-NEXT: {{#1 .* main .*double_free.cpp}}:[[@LINE-3]] -// CHECK: [[ADDR]] is located 0 bytes inside of 168-byte region -// CHECK-LABEL: freed by thread T0 here: -// CHECK-NEXT: {{#0 .* free }} -// CHECK-NEXT: {{#1 .* main .*double_free.cpp}}:[[@LINE-8]] -// CHECK-LABEL: previously allocated by thread T0 here: -// CHECK-NEXT: {{#0 .* malloc }} -// CHECK-NEXT: {{#1 .* main .*double_free.cpp}}:[[@LINE-12]] + // CHECK: AddressSanitizer: attempting double-free on [[ADDR:0x[0-9a-f]+]] + // CHECK-NEXT: {{#0 .* free }} + // CHECK: {{ #[1-2] .* main .*double_free.cpp}}:[[@LINE-3]] + // CHECK: [[ADDR]] is located 0 bytes inside of 168-byte region + // CHECK-LABEL: freed by thread T0 here: + // CHECK-NEXT: {{#0 .* free }} + // CHECK: {{ #[1-2] .* main .*double_free.cpp}}:[[@LINE-8]] + // CHECK-LABEL: previously allocated by thread T0 here: + // CHECK-NEXT: {{#0 .* malloc }} + // CHECK: {{ #[1-2] .* main .*double_free.cpp}}:[[@LINE-12]] return 0; } diff --git a/compiler-rt/test/asan/TestCases/Windows/intercept_strdup.cpp b/compiler-rt/test/asan/TestCases/Windows/intercept_strdup.cpp index b519f53fe426984f9da723b8dc9b9f963c0150f5..fec4d1ec35597c486f241febe09f1594f2896205 100644 --- a/compiler-rt/test/asan/TestCases/Windows/intercept_strdup.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/intercept_strdup.cpp @@ -15,18 +15,18 @@ int main() { subscript = -1; ptr[subscript] = 42; -// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] -// CHECK: WRITE of size 1 at [[ADDR]] thread T0 -// CHECK: {{#0 .* main .*}}intercept_strdup.cpp:[[@LINE-3]] -// CHECK: [[ADDR]] is located 1 bytes before 6-byte region -// CHECK: allocated by thread T0 here: -// -// The first frame is our wrapper normally but will be malloc in the dynamic -// config. -// CHECK: #0 {{.*}} in {{malloc|strdup}} -// -// The local call to _strdup above may be the second or third frame depending -// on whether we're using the dynamic config. -// CHECK: #{{[12]}} {{.*}} in main {{.*}}intercept_strdup.cpp:[[@LINE-21]] + // CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] + // CHECK: WRITE of size 1 at [[ADDR]] thread T0 + // CHECK: {{#0 .* main .*}}intercept_strdup.cpp:[[@LINE-3]] + // CHECK: [[ADDR]] is located 1 bytes before 6-byte region + // CHECK: allocated by thread T0 here: + // + // The first frame is our wrapper normally but will be malloc in the dynamic + // config. + // CHECK: #0 {{.*}} in {{malloc|_strdup}} + // + // The local call to _strdup above may be the second or third frame depending + // on whether we're using the dynamic config. + // CHECK: #{{[12]}} {{.*}} in main {{.*}}intercept_strdup.cpp:[[@LINE-21]] free(ptr); } diff --git a/compiler-rt/test/asan/TestCases/Windows/interface_symbols_windows.cpp b/compiler-rt/test/asan/TestCases/Windows/interface_symbols_windows.cpp deleted file mode 100644 index 1803911a43a9b08f0664b5489f5beb13928eef24..0000000000000000000000000000000000000000 --- a/compiler-rt/test/asan/TestCases/Windows/interface_symbols_windows.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// UNSUPPORTED: target={{.*-windows-gnu}} - -// Check that the interface exported by asan static lib matches the list of -// functions mentioned in sanitizer_interface.inc. -// -// Just make sure we can compile this. -// RUN: %clang_cl_asan -Od %s -Fe%t -// -// note: The mangling decoration (i.e. @4 )is removed because calling convention -// differ from 32-bit and 64-bit. -// -// RUN: dumpbin /EXPORTS %t | sed "s/=.*//" \ -// RUN: | grep -o "\(__asan_\|__ubsan_\|__sanitizer_\|__sancov_\)[^ ]*" \ -// RUN: | grep -v "__asan_wrap" \ -// RUN: | sed -e s/@.*// > %t.exports -// -// [BEWARE: be really careful with the sed commands, as this test can be run -// from different environments with different shells and seds] -// -// RUN: sed ':a;N;$!ba;s/([\n ]*/(/g' \ -// RUN: %p/../../../../lib/asan/asan_interface.inc \ -// RUN: %p/../../../../lib/ubsan/ubsan_interface.inc \ -// RUN: %p/../../../../lib/sanitizer_common/sanitizer_common_interface.inc \ -// RUN: %p/../../../../lib/sanitizer_common/sanitizer_coverage_interface.inc \ -// RUN: | grep -e "^INTERFACE_FUNCTION" \ -// RUN: | sed -e "s/.*(//" -e "s/).*//" > %t.imports1 -// -// RUN: sed ':a;N;$!ba;s/([\n ]*/(/g' \ -// RUN: %p/../../../../lib/asan/asan_interface.inc \ -// RUN: %p/../../../../lib/ubsan/ubsan_interface.inc \ -// RUN: %p/../../../../lib/sanitizer_common/sanitizer_common_interface.inc \ -// RUN: %p/../../../../lib/sanitizer_common/sanitizer_coverage_interface.inc \ -// RUN: | grep -e "^INTERFACE_WEAK_FUNCTION" \ -// RUN: | sed -e "s/.*(//" -e "s/).*/__dll/" > %t.imports2 -// -// Add functions not included in the interface lists: -// RUN: grep '[I]MPORT:' %s | sed -e 's/.*[I]MPORT: //' > %t.imports3 -// IMPORT: __asan_shadow_memory_dynamic_address -// IMPORT: __asan_get_shadow_memory_dynamic_address -// IMPORT: __asan_option_detect_stack_use_after_return -// IMPORT: __asan_should_detect_stack_use_after_return -// IMPORT: __asan_set_seh_filter -// IMPORT: __asan_unhandled_exception_filter -// IMPORT: __asan_test_only_reported_buggy_pointer -// IMPORT: __ubsan_vptr_type_cache -// -// RUN: cat %t.imports1 %t.imports2 %t.imports3 | sort | uniq > %t.imports-sorted -// RUN: cat %t.exports | sort | uniq > %t.exports-sorted -// -// Now make sure the DLL thunk imports everything: -// RUN: echo -// RUN: echo "=== NOTE === If you see a mismatch below, please update interface.inc files." -// RUN: diff %t.imports-sorted %t.exports-sorted -// REQUIRES: asan-static-runtime - -int main() { return 0; } diff --git a/compiler-rt/test/asan/TestCases/Windows/issue64990.cpp b/compiler-rt/test/asan/TestCases/Windows/issue64990.cpp index aab66502bd16fc64f01c10071b737d101aabaaec..b1b6e42148cb6821dab8a58816ce35ada04fd055 100644 --- a/compiler-rt/test/asan/TestCases/Windows/issue64990.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/issue64990.cpp @@ -16,5 +16,5 @@ int main(int argc, char **argv) { } return 0; } - -// CHECK: SUMMARY: AddressSanitizer: global-buffer-overflow {{.*}} in __asan_memcpy +// CHECK: #0 {{.*}} in __asan_memcpy +// CHECK: SUMMARY: AddressSanitizer: global-buffer-overflow {{.*}} in main diff --git a/compiler-rt/test/asan/TestCases/Windows/malloc_left_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/malloc_left_oob.cpp index 2ee5fdc7abee2fe4cebeba41c51addbe5c15c62e..7ea95d2b2184a09048a54b8f6140499d60b42186 100644 --- a/compiler-rt/test/asan/TestCases/Windows/malloc_left_oob.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/malloc_left_oob.cpp @@ -6,12 +6,12 @@ int main() { char *buffer = (char*)malloc(42); buffer[-1] = 42; -// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] -// CHECK: WRITE of size 1 at [[ADDR]] thread T0 -// CHECK-NEXT: {{#0 .* main .*malloc_left_oob.cpp}}:[[@LINE-3]] -// CHECK: [[ADDR]] is located 1 bytes before 42-byte region -// CHECK: allocated by thread T0 here: -// CHECK-NEXT: {{#0 .* malloc }} -// CHECK-NEXT: {{#1 .* main .*malloc_left_oob.cpp}}:[[@LINE-8]] + // CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] + // CHECK: WRITE of size 1 at [[ADDR]] thread T0 + // CHECK-NEXT: {{#0 .* main .*malloc_left_oob.cpp}}:[[@LINE-3]] + // CHECK: [[ADDR]] is located 1 bytes before 42-byte region + // CHECK: allocated by thread T0 here: + // CHECK-NEXT: {{#0 .* malloc }} + // CHECK: {{ #[1-2] .* main .*malloc_left_oob.cpp}}:[[@LINE-8]] free(buffer); } diff --git a/compiler-rt/test/asan/TestCases/Windows/malloc_right_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/malloc_right_oob.cpp index dafca74b4812da14951fdc02259d0aa94bc50fd4..1495632456e081970137589c9c8292e93d6b64b8 100644 --- a/compiler-rt/test/asan/TestCases/Windows/malloc_right_oob.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/malloc_right_oob.cpp @@ -6,12 +6,12 @@ int main() { char *buffer = (char*)malloc(42); buffer[42] = 42; -// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] -// CHECK: WRITE of size 1 at [[ADDR]] thread T0 -// CHECK-NEXT: {{#0 .* main .*malloc_right_oob.cpp}}:[[@LINE-3]] -// CHECK: [[ADDR]] is located 0 bytes after 42-byte region -// CHECK: allocated by thread T0 here: -// CHECK-NEXT: {{#0 .* malloc }} -// CHECK-NEXT: {{#1 .* main .*malloc_right_oob.cpp}}:[[@LINE-8]] + // CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] + // CHECK: WRITE of size 1 at [[ADDR]] thread T0 + // CHECK-NEXT: {{#0 .* main .*malloc_right_oob.cpp}}:[[@LINE-3]] + // CHECK: [[ADDR]] is located 0 bytes after 42-byte region + // CHECK: allocated by thread T0 here: + // CHECK-NEXT: {{#0 .* malloc }} + // CHECK: {{ #[1-2] .* main .*malloc_right_oob.cpp}}:[[@LINE-8]] free(buffer); } diff --git a/compiler-rt/test/asan/TestCases/Windows/malloc_uaf.cpp b/compiler-rt/test/asan/TestCases/Windows/malloc_uaf.cpp index 256582deefe46e2f0d913d2c9fe6d9161ca42d45..d1eac7e55f60108169f006d3de99a183c14984e5 100644 --- a/compiler-rt/test/asan/TestCases/Windows/malloc_uaf.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/malloc_uaf.cpp @@ -7,14 +7,14 @@ int main() { char *buffer = (char*)malloc(42); free(buffer); buffer[0] = 42; -// CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]] -// CHECK: WRITE of size 1 at [[ADDR]] thread T0 -// CHECK-NEXT: {{#0 .* main .*malloc_uaf.cpp}}:[[@LINE-3]] -// CHECK: [[ADDR]] is located 0 bytes inside of 42-byte region -// CHECK: freed by thread T0 here: -// CHECK-NEXT: {{#0 .* free }} -// CHECK-NEXT: {{#1 .* main .*malloc_uaf.cpp}}:[[@LINE-8]] -// CHECK: previously allocated by thread T0 here: -// CHECK-NEXT: {{#0 .* malloc }} -// CHECK-NEXT: {{#1 .* main .*malloc_uaf.cpp}}:[[@LINE-12]] + // CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]] + // CHECK: WRITE of size 1 at [[ADDR]] thread T0 + // CHECK-NEXT: {{#0 .* main .*malloc_uaf.cpp}}:[[@LINE-3]] + // CHECK: [[ADDR]] is located 0 bytes inside of 42-byte region + // CHECK: freed by thread T0 here: + // CHECK-NEXT: {{#0 .* free }} + // CHECK: {{ #[1-2] .* main .*malloc_uaf.cpp}}:[[@LINE-8]] + // CHECK: previously allocated by thread T0 here: + // CHECK-NEXT: {{#0 .* malloc }} + // CHECK: {{ #[1-2] .* main .*malloc_uaf.cpp}}:[[@LINE-12]] } diff --git a/compiler-rt/test/asan/TestCases/Windows/realloc_left_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/realloc_left_oob.cpp index 4a5a7ab8ecfdfb952159780d4a0a67ac53029aa1..ebde5f159ae3832d6905277cef53809903e0b442 100644 --- a/compiler-rt/test/asan/TestCases/Windows/realloc_left_oob.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/realloc_left_oob.cpp @@ -6,12 +6,12 @@ int main() { char *buffer = (char*)realloc(0, 42); buffer[-1] = 42; -// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] -// CHECK: WRITE of size 1 at [[ADDR]] thread T0 -// CHECK-NEXT: {{#0 .* main .*realloc_left_oob.cpp}}:[[@LINE-3]] -// CHECK: [[ADDR]] is located 1 bytes before 42-byte region -// CHECK: allocated by thread T0 here: -// CHECK-NEXT: {{#0 .* realloc }} -// CHECK-NEXT: {{#1 .* main .*realloc_left_oob.cpp}}:[[@LINE-8]] + // CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] + // CHECK: WRITE of size 1 at [[ADDR]] thread T0 + // CHECK-NEXT: {{#0 .* main .*realloc_left_oob.cpp}}:[[@LINE-3]] + // CHECK: [[ADDR]] is located 1 bytes before 42-byte region + // CHECK: allocated by thread T0 here: + // CHECK-NEXT: {{#0 .* realloc }} + // CHECK: {{ #[1-2] .* main .*realloc_left_oob.cpp}}:[[@LINE-8]] free(buffer); } diff --git a/compiler-rt/test/asan/TestCases/Windows/realloc_right_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/realloc_right_oob.cpp index 8f3109eed2d0794760a449a7e7d2c9684d3f8bc7..281efed5d307405a6d05d7bda9290ff7c76f4ca2 100644 --- a/compiler-rt/test/asan/TestCases/Windows/realloc_right_oob.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/realloc_right_oob.cpp @@ -6,12 +6,12 @@ int main() { char *buffer = (char*)realloc(0, 42); buffer[42] = 42; -// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] -// CHECK: WRITE of size 1 at [[ADDR]] thread T0 -// CHECK-NEXT: {{#0 .* main .*realloc_right_oob.cpp}}:[[@LINE-3]] -// CHECK: [[ADDR]] is located 0 bytes after 42-byte region -// CHECK: allocated by thread T0 here: -// CHECK-NEXT: {{#0 .* realloc }} -// CHECK-NEXT: {{#1 .* main .*realloc_right_oob.cpp}}:[[@LINE-8]] + // CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] + // CHECK: WRITE of size 1 at [[ADDR]] thread T0 + // CHECK-NEXT: {{#0 .* main .*realloc_right_oob.cpp}}:[[@LINE-3]] + // CHECK: [[ADDR]] is located 0 bytes after 42-byte region + // CHECK: allocated by thread T0 here: + // CHECK-NEXT: {{#0 .* realloc }} + // CHECK: {{ #[1-2] .* main .*realloc_right_oob.cpp}}:[[@LINE-8]] free(buffer); } diff --git a/compiler-rt/test/asan/TestCases/Windows/realloc_uaf.cpp b/compiler-rt/test/asan/TestCases/Windows/realloc_uaf.cpp index 074ac270f13f5c104ea01b84180e6b2f1e858700..6ff2217b11a25703174bf072a031ce5f745f461a 100644 --- a/compiler-rt/test/asan/TestCases/Windows/realloc_uaf.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/realloc_uaf.cpp @@ -7,14 +7,14 @@ int main() { char *buffer = (char*)realloc(0, 42); free(buffer); buffer[0] = 42; -// CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]] -// CHECK: WRITE of size 1 at [[ADDR]] thread T0 -// CHECK-NEXT: {{#0 .* main .*realloc_uaf.cpp}}:[[@LINE-3]] -// CHECK: [[ADDR]] is located 0 bytes inside of 42-byte region -// CHECK: freed by thread T0 here: -// CHECK-NEXT: {{#0 .* free }} -// CHECK-NEXT: {{#1 .* main .*realloc_uaf.cpp}}:[[@LINE-8]] -// CHECK: previously allocated by thread T0 here: -// CHECK-NEXT: {{#0 .* realloc }} -// CHECK-NEXT: {{#1 .* main .*realloc_uaf.cpp}}:[[@LINE-12]] + // CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]] + // CHECK: WRITE of size 1 at [[ADDR]] thread T0 + // CHECK-NEXT: {{#0 .* main .*realloc_uaf.cpp}}:[[@LINE-3]] + // CHECK: [[ADDR]] is located 0 bytes inside of 42-byte region + // CHECK: freed by thread T0 here: + // CHECK-NEXT: {{#0 .* free }} + // CHECK: {{ #[1-2] .* main .*realloc_uaf.cpp}}:[[@LINE-8]] + // CHECK: previously allocated by thread T0 here: + // CHECK-NEXT: {{#0 .* realloc }} + // CHECK: {{ #[1-2] .* main .*realloc_uaf.cpp}}:[[@LINE-12]] } diff --git a/compiler-rt/test/asan/TestCases/Windows/symbols_path.cpp b/compiler-rt/test/asan/TestCases/Windows/symbols_path.cpp index d896da482f2ebc760fd49729551ee8f24899af72..be99c89e7083ef219f31a81441af4a19073c42aa 100644 --- a/compiler-rt/test/asan/TestCases/Windows/symbols_path.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/symbols_path.cpp @@ -11,12 +11,12 @@ int main() { char *buffer = (char*)malloc(42); buffer[-1] = 42; -// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] -// CHECK: WRITE of size 1 at [[ADDR]] thread T0 -// CHECK-NEXT: {{#0 .* main .*symbols_path.cpp}}:[[@LINE-3]] -// CHECK: [[ADDR]] is located 1 bytes before 42-byte region -// CHECK: allocated by thread T0 here: -// CHECK-NEXT: {{#0 .* malloc}} -// CHECK-NEXT: {{#1 .* main .*symbols_path.cpp}}:[[@LINE-8]] + // CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]] + // CHECK: WRITE of size 1 at [[ADDR]] thread T0 + // CHECK-NEXT: {{#0 .* main .*symbols_path.cpp}}:[[@LINE-3]] + // CHECK: [[ADDR]] is located 1 bytes before 42-byte region + // CHECK: allocated by thread T0 here: + // CHECK-NEXT: {{#0 .* malloc}} + // CHECK: {{ #[1-2] .* main .*symbols_path.cpp}}:[[@LINE-8]] free(buffer); } diff --git a/compiler-rt/test/asan/TestCases/Windows/use_after_realloc.cpp b/compiler-rt/test/asan/TestCases/Windows/use_after_realloc.cpp index dfd25cebb6bfefea779fee22a12d0671c5977566..4c32c63c38fa1f7c37c451c3f78999ed908c53db 100644 --- a/compiler-rt/test/asan/TestCases/Windows/use_after_realloc.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/use_after_realloc.cpp @@ -9,15 +9,15 @@ int main() { buffer = (char*)realloc(buffer, 64); // The 'stale' may now point to a free'd memory. stale[0] = 42; -// CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]] -// CHECK: WRITE of size 1 at [[ADDR]] thread T0 -// CHECK-NEXT: {{#0 .* main .*use_after_realloc.cpp}}:[[@LINE-3]] -// CHECK: [[ADDR]] is located 0 bytes inside of 32-byte region -// CHECK: freed by thread T0 here: -// CHECK-NEXT: {{#0 .* realloc }} -// CHECK-NEXT: {{#1 .* main .*use_after_realloc.cpp}}:[[@LINE-9]] -// CHECK: previously allocated by thread T0 here: -// CHECK-NEXT: {{#0 .* realloc }} -// CHECK-NEXT: {{#1 .* main .*use_after_realloc.cpp}}:[[@LINE-14]] + // CHECK: AddressSanitizer: heap-use-after-free on address [[ADDR:0x[0-9a-f]+]] + // CHECK: WRITE of size 1 at [[ADDR]] thread T0 + // CHECK-NEXT: {{#0 .* main .*use_after_realloc.cpp}}:[[@LINE-3]] + // CHECK: [[ADDR]] is located 0 bytes inside of 32-byte region + // CHECK: freed by thread T0 here: + // CHECK-NEXT: {{#0 .* realloc }} + // CHECK: {{ #[1-2] .* main .*use_after_realloc.cpp}}:[[@LINE-9]] + // CHECK: previously allocated by thread T0 here: + // CHECK-NEXT: {{#0 .* realloc }} + // CHECK: {{ #[1-2] .* main .*use_after_realloc.cpp}}:[[@LINE-14]] free(buffer); } diff --git a/compiler-rt/test/asan/TestCases/calloc-overflow.cpp b/compiler-rt/test/asan/TestCases/calloc-overflow.cpp index 9a0d41ff8260187790c87d3a27b8bbc91ef04ade..b930b65cd8c3b0793f94900640d2e265de8ca1ef 100644 --- a/compiler-rt/test/asan/TestCases/calloc-overflow.cpp +++ b/compiler-rt/test/asan/TestCases/calloc-overflow.cpp @@ -11,7 +11,7 @@ int main() { void *p = calloc(-1, 1000); // CHECK: {{ERROR: AddressSanitizer: calloc parameters overflow: count \* size \(.* \* 1000\) cannot be represented in type size_t}} // CHECK: {{#0 0x.* in .*calloc}} - // CHECK: {{#1 0x.* in main .*calloc-overflow.cpp:}}[[@LINE-3]] + // CHECK: {{#[1-3] 0x.* in main .*calloc-overflow.cpp:}}[[@LINE-3]] // CHECK: SUMMARY: AddressSanitizer: calloc-overflow printf("calloc returned: %zu\n", (size_t)p); diff --git a/compiler-rt/test/asan/TestCases/deep_stack_uaf.cpp b/compiler-rt/test/asan/TestCases/deep_stack_uaf.cpp index bdf0dbdb4a4bd0547929825c454a06d442ff0ce3..7d8a09220689f5cf6b20b1b827e2e1db97178562 100644 --- a/compiler-rt/test/asan/TestCases/deep_stack_uaf.cpp +++ b/compiler-rt/test/asan/TestCases/deep_stack_uaf.cpp @@ -1,7 +1,7 @@ // Check that we can store lots of stack frames if asked to. // RUN: %clangxx_asan -O0 %s -o %t 2>&1 -// RUN: %env_asan_opts=malloc_context_size=120:redzone=512 not %run %t 2>&1 | FileCheck %s +// RUN: %env_asan_opts=malloc_context_size=125:redzone=512 not %run %t 2>&1 | FileCheck %s // REQUIRES: stable-runtime #include <stdlib.h> #include <stdio.h> diff --git a/compiler-rt/test/asan/TestCases/double-free.cpp b/compiler-rt/test/asan/TestCases/double-free.cpp index b01e41005a27a382312b17999efde27c2cbaacbb..7b61df0715afafbdd749e189971befb52f64cd6f 100644 --- a/compiler-rt/test/asan/TestCases/double-free.cpp +++ b/compiler-rt/test/asan/TestCases/double-free.cpp @@ -19,10 +19,10 @@ int main(int argc, char **argv) { free(x + argc - 1); // BOOM // CHECK: AddressSanitizer: attempting double-free{{.*}}in thread T0 // CHECK: #0 0x{{.*}} in {{.*}}free - // CHECK: #1 0x{{.*}} in main {{.*}}double-free.cpp:[[@LINE-3]] + // CHECK: #{{[1-3]}} 0x{{.*}} in main {{.*}}double-free.cpp:[[@LINE-3]] // CHECK: freed by thread T0 here: // MALLOC-CTX: #0 0x{{.*}} in {{.*}}free - // MALLOC-CTX: #1 0x{{.*}} in main {{.*}}double-free.cpp:[[@LINE-7]] + // MALLOC-CTX: #{{[1-3]}} 0x{{.*}} in main {{.*}}double-free.cpp:[[@LINE-7]] // CHECK: allocated by thread T0 here: // MALLOC-CTX: double-free.cpp:[[@LINE-12]] // CHECK-RECOVER: AddressSanitizer: attempting double-free{{.*}}in thread T0 diff --git a/compiler-rt/test/asan/TestCases/malloc-size-too-big.cpp b/compiler-rt/test/asan/TestCases/malloc-size-too-big.cpp index 71d6a3e7148a3e3f0ce9cd1dfeb9576ff3a9d6c1..771640a4ac08d16c1fc175cfd714da40a5ffd167 100644 --- a/compiler-rt/test/asan/TestCases/malloc-size-too-big.cpp +++ b/compiler-rt/test/asan/TestCases/malloc-size-too-big.cpp @@ -18,7 +18,7 @@ int main() { void *p = malloc(kMaxAllowedMallocSizePlusOne); // CHECK: {{ERROR: AddressSanitizer: requested allocation size .* \(.* after adjustments for alignment, red zones etc\.\) exceeds maximum supported size}} // CHECK: {{#0 0x.* in .*malloc}} - // CHECK: {{#1 0x.* in main .*malloc-size-too-big.cpp:}}[[@LINE-3]] + // CHECK: {{#[1-3] 0x.* in main .*malloc-size-too-big.cpp:}}[[@LINE-3]] // CHECK: SUMMARY: AddressSanitizer: allocation-size-too-big printf("malloc returned: %zu\n", (size_t)p); diff --git a/compiler-rt/test/asan/TestCases/strncpy-overflow.cpp b/compiler-rt/test/asan/TestCases/strncpy-overflow.cpp index d852ccebd9a7789cce7ac87d2388567499e50e91..ff84052a94987a362ded02702e5180b752c2cc89 100644 --- a/compiler-rt/test/asan/TestCases/strncpy-overflow.cpp +++ b/compiler-rt/test/asan/TestCases/strncpy-overflow.cpp @@ -33,6 +33,6 @@ int main(int argc, char **argv) { // CHECK: {{0x.* is located 0 bytes after 9-byte region}} // CHECK: {{allocated by thread T0 here:}} // CHECK: {{ #0 0x.* in .*malloc}} - // CHECK: {{ #1 0x.* in main .*strncpy-overflow.cpp:}}[[@LINE-8]] + // CHECK: {{ #[1-3] 0x.* in main .*strncpy-overflow.cpp:}}[[@LINE-8]] return rval + sink_memory(9, short_buffer); } diff --git a/compiler-rt/test/asan/TestCases/use-after-free-right.cpp b/compiler-rt/test/asan/TestCases/use-after-free-right.cpp index 10dbe5b90568487af7269e1c73195b8183e62745..11011e4b4fb1aa5d4e48b6702c3260df8ebda285 100644 --- a/compiler-rt/test/asan/TestCases/use-after-free-right.cpp +++ b/compiler-rt/test/asan/TestCases/use-after-free-right.cpp @@ -19,9 +19,9 @@ int main() { // CHECK: {{0x.* is located 0 bytes inside of 1-byte region .0x.*,0x.*}} // CHECK: {{freed by thread T0 here:}} // CHECK: {{ #0 0x.* in .*free}} - // CHECK: {{ #1 0x.* in main .*use-after-free-right.cpp:}}[[@LINE-9]] + // CHECK: {{ #[1-3] 0x.* in main .*use-after-free-right.cpp:}}[[@LINE-9]] // CHECK: {{previously allocated by thread T0 here:}} // CHECK: {{ #0 0x.* in .*malloc}} - // CHECK: {{ #1 0x.* in main .*use-after-free-right.cpp:}}[[@LINE-14]] + // CHECK: {{ #[1-3] 0x.* in main .*use-after-free-right.cpp:}}[[@LINE-14]] } diff --git a/compiler-rt/test/asan/TestCases/use-after-free.cpp b/compiler-rt/test/asan/TestCases/use-after-free.cpp index 4b20ee25500c0671cad8acafb89a72c35703cd76..f19c461960d36ab51a6e994b27147e42dd082ed1 100644 --- a/compiler-rt/test/asan/TestCases/use-after-free.cpp +++ b/compiler-rt/test/asan/TestCases/use-after-free.cpp @@ -16,11 +16,11 @@ int main() { // CHECK: {{0x.* is located 5 bytes inside of 10-byte region .0x.*,0x.*}} // CHECK: {{freed by thread T0 here:}} // CHECK: {{ #0 0x.* in .*free}} - // CHECK: {{ #1 0x.* in main .*use-after-free.cpp:}}[[@LINE-9]] + // CHECK: {{ #[1-3] 0x.* in main .*use-after-free.cpp:}}[[@LINE-9]] // CHECK: {{previously allocated by thread T0 here:}} // CHECK: {{ #0 0x.* in .*malloc}} - // CHECK: {{ #1 0x.* in main .*use-after-free.cpp:}}[[@LINE-14]] + // CHECK: {{ #[1-3] 0x.* in main .*use-after-free.cpp:}}[[@LINE-14]] // CHECK: Shadow byte legend (one shadow byte represents {{[0-9]+}} application bytes): // CHECK: Global redzone: // CHECK: ASan internal: diff --git a/compiler-rt/test/asan_abi/CMakeLists.txt b/compiler-rt/test/asan_abi/CMakeLists.txt index f28cf6cd1da6eaa55788dd57d13abfd35d95a332..1114ed1b82793dc8a0b17f6a53c7a55caec342c5 100644 --- a/compiler-rt/test/asan_abi/CMakeLists.txt +++ b/compiler-rt/test/asan_abi/CMakeLists.txt @@ -9,10 +9,7 @@ macro(get_bits_for_arch arch bits) endif() endmacro() -set(ASAN_ABI_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) -if(NOT COMPILER_RT_STANDALONE_BUILD) - list(APPEND ASAN_ABI_TEST_DEPS asan_abi) -endif() +set(ASAN_ABI_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS} asan_abi) set(ASAN_ABI_TEST_ARCH ${ASAN_ABI_SUPPORTED_ARCH}) if(APPLE) diff --git a/compiler-rt/test/dfsan/custom.cpp b/compiler-rt/test/dfsan/custom.cpp index 4bb818813cf7c8af6d974ac9e97ac47ead50a6d0..f544e481b726114dcb5f0641e241afc7cc9936f1 100644 --- a/compiler-rt/test/dfsan/custom.cpp +++ b/compiler-rt/test/dfsan/custom.cpp @@ -175,7 +175,7 @@ void test_stat() { s.st_dev = i; SAVE_ORIGINS(s) - ret = stat("/nonexistent", &s); + ret = stat("/nonexistent_581cb021aba7", &s); assert(-1 == ret); ASSERT_ZERO_LABEL(ret); ASSERT_LABEL(s.st_dev, i_label); diff --git a/compiler-rt/test/dfsan/mmap_at_init.c b/compiler-rt/test/dfsan/mmap_at_init.c index a8d7535df4a6c4e2a3bdbe9c590d5448d83cd44c..9129dc7d39031cb39f39366ad3645179b7737f54 100644 --- a/compiler-rt/test/dfsan/mmap_at_init.c +++ b/compiler-rt/test/dfsan/mmap_at_init.c @@ -4,6 +4,9 @@ // // Tests that calling mmap() during during dfsan initialization works. +// `internal_symbolizer` can not use `realloc` on memory from the test `calloc`. +// UNSUPPORTED: internal_symbolizer + #include <sanitizer/dfsan_interface.h> #include <sys/mman.h> #include <unistd.h> diff --git a/compiler-rt/test/fuzzer/CMakeLists.txt b/compiler-rt/test/fuzzer/CMakeLists.txt index f0ba087a1b3260365df754489f89b9e8e3d3c850..5bcb44757bae461932cfd443fea21097548a5bd3 100644 --- a/compiler-rt/test/fuzzer/CMakeLists.txt +++ b/compiler-rt/test/fuzzer/CMakeLists.txt @@ -1,12 +1,17 @@ -set(LIBFUZZER_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) +set(LIBFUZZER_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS} fuzzer) +if (COMPILER_RT_HAS_UBSAN) + list(APPEND LIBFUZZER_TEST_DEPS ubsan) +endif() +if (COMPILER_RT_HAS_ASAN) + list(APPEND LIBFUZZER_TEST_DEPS asan) +endif() +if (COMPILER_RT_HAS_MSAN) + list(APPEND LIBFUZZER_TEST_DEPS msan) +endif() +if (COMPILER_RT_HAS_DFSAN) + list(APPEND LIBFUZZER_TEST_DEPS dfsan) +endif() if (NOT COMPILER_RT_STANDALONE_BUILD) - list(APPEND LIBFUZZER_TEST_DEPS fuzzer asan ubsan) - if (COMPILER_RT_HAS_MSAN) - list(APPEND LIBFUZZER_TEST_DEPS msan) - endif() - if (COMPILER_RT_HAS_DFSAN) - list(APPEND LIBFUZZER_TEST_DEPS dfsan) - endif() if(NOT APPLE AND COMPILER_RT_HAS_LLD AND "lld" IN_LIST LLVM_ENABLE_PROJECTS) list(APPEND LIBFUZZER_TEST_DEPS lld) endif() diff --git a/compiler-rt/test/lit.common.cfg.py b/compiler-rt/test/lit.common.cfg.py index ae28681915afb3e35b4b29ebb6babe908034dd8a..0ac20a9831d95020e5965dfcbb7c50200af5cdb4 100644 --- a/compiler-rt/test/lit.common.cfg.py +++ b/compiler-rt/test/lit.common.cfg.py @@ -632,7 +632,7 @@ if config.host_os == "Linux": ver = LooseVersion(ver_string) any_glibc = False - for required in ["2.19", "2.27", "2.30", "2.33", "2.34", "2.37"]: + for required in ["2.19", "2.27", "2.30", "2.33", "2.34", "2.37", "2.38"]: if ver >= LooseVersion(required): config.available_features.add("glibc-" + required) any_glibc = True @@ -882,6 +882,10 @@ if config.use_lld and config.has_lld and not config.use_lto: elif config.use_lld and (not config.has_lld): config.unsupported = True +if config.host_os == "Darwin": + if getattr(config, "darwin_linker_version", None): + extra_cflags += ["-mlinker-version=" + config.darwin_linker_version] + # Append any extra flags passed in lit_config append_target_cflags = lit_config.params.get("append_target_cflags", None) if append_target_cflags: diff --git a/compiler-rt/test/lit.common.configured.in b/compiler-rt/test/lit.common.configured.in index db5d7c598b7310628a72cd1876787889a78c0880..fff5dc6cc75094e390f381015e83d1cae5fd9192 100644 --- a/compiler-rt/test/lit.common.configured.in +++ b/compiler-rt/test/lit.common.configured.in @@ -51,6 +51,7 @@ set_default("expensive_checks", @LLVM_ENABLE_EXPENSIVE_CHECKS_PYBOOL@) set_default("test_standalone_build_libs", @COMPILER_RT_TEST_STANDALONE_BUILD_LIBS_PYBOOL@) set_default("has_compiler_rt_libatomic", @COMPILER_RT_BUILD_STANDALONE_LIBATOMIC_PYBOOL@) set_default("aarch64_sme", @COMPILER_RT_HAS_AARCH64_SME_PYBOOL@) +set_default("darwin_linker_version", "@COMPILER_RT_DARWIN_LINKER_VERSION@") # True iff the test suite supports ignoring the test compiler's runtime library path # and using `config.compiler_rt_libdir` instead. This only matters when the runtime # library paths differ. diff --git a/compiler-rt/test/lsan/TestCases/recoverable_leak_check.cpp b/compiler-rt/test/lsan/TestCases/recoverable_leak_check.cpp index 296f5a0a5915fb3572c0e33042718c8e7942ceff..dbad784f85528c5af45051a7553deef7595d9155 100644 --- a/compiler-rt/test/lsan/TestCases/recoverable_leak_check.cpp +++ b/compiler-rt/test/lsan/TestCases/recoverable_leak_check.cpp @@ -1,13 +1,10 @@ // Test for on-demand leak checking. // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=use_stacks=0:use_registers=0 %run %t foo 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=use_stacks=0:use_registers=0 %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts=use_stacks=0:use_registers=0:symbolize=0 %run %t foo 2>&1 | FileCheck %s +// RUN: %env_lsan_opts=use_stacks=0:use_registers=0:symbolize=0 %run %t 2>&1 | FileCheck %s // UNSUPPORTED: darwin -// FIXME: Investigate. -// XFAIL: internal_symbolizer && lsan-standalone && i386-linux - #include <assert.h> #include <stdio.h> #include <stdlib.h> diff --git a/compiler-rt/test/memprof/CMakeLists.txt b/compiler-rt/test/memprof/CMakeLists.txt index 8a29919b177024d8a280b1bbec49d585350f4661..3f0ba3812485d2042a942937e5e4737c8732abe0 100644 --- a/compiler-rt/test/memprof/CMakeLists.txt +++ b/compiler-rt/test/memprof/CMakeLists.txt @@ -11,12 +11,9 @@ macro(get_bits_for_arch arch bits) endif() endmacro() -set(MEMPROF_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) -if(NOT COMPILER_RT_STANDALONE_BUILD) - list(APPEND MEMPROF_TEST_DEPS memprof) - if(COMPILER_RT_HAS_LLD AND TARGET lld) - list(APPEND MEMPROF_TEST_DEPS lld) - endif() +set(MEMPROF_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS} memprof) +if(NOT COMPILER_RT_STANDALONE_BUILD AND COMPILER_RT_HAS_LLD AND TARGET lld) + list(APPEND MEMPROF_TEST_DEPS lld) endif() set(MEMPROF_DYNAMIC_TEST_DEPS ${MEMPROF_TEST_DEPS}) diff --git a/compiler-rt/test/msan/CMakeLists.txt b/compiler-rt/test/msan/CMakeLists.txt index 01b832b5ae3f9d0692dc83090af11e6924ced299..9f784507c4ee1c094162c4e8e0cbc00c032f3c6f 100644 --- a/compiler-rt/test/msan/CMakeLists.txt +++ b/compiler-rt/test/msan/CMakeLists.txt @@ -1,7 +1,7 @@ set(MSAN_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(MSAN_TESTSUITES) -set(MSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) +set(MSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS} msan) set(MSAN_TEST_ARCH ${MSAN_SUPPORTED_ARCH}) if(APPLE) @@ -41,10 +41,6 @@ foreach(arch ${MSAN_TEST_ARCH}) endif() endforeach() -if(NOT COMPILER_RT_STANDALONE_BUILD) - list(APPEND MSAN_TEST_DEPS msan) -endif() - if(COMPILER_RT_INCLUDE_TESTS AND COMPILER_RT_LIBCXX_PATH AND COMPILER_RT_LIBCXXABI_PATH) diff --git a/compiler-rt/test/profile/Linux/instrprof-vtable-value-prof.cpp b/compiler-rt/test/profile/Linux/instrprof-vtable-value-prof.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e51805bdf923cbbb07e5a59c578d54a097738707 --- /dev/null +++ b/compiler-rt/test/profile/Linux/instrprof-vtable-value-prof.cpp @@ -0,0 +1,147 @@ +// REQUIRES: lld-available + +// Building the instrumented binary will fail because lld doesn't support +// big-endian ELF for PPC (aka ABI 1). +// ld.lld: error: /lib/../lib64/Scrt1.o: ABI version 1 is not supported +// UNSUPPORTED: ppc && host-byteorder-big-endian + +// RUN: %clangxx_pgogen -fuse-ld=lld -O2 -g -fprofile-generate=. -mllvm -enable-vtable-value-profiling %s -o %t-test +// RUN: env LLVM_PROFILE_FILE=%t-test.profraw %t-test + +// Show vtable profiles from raw profile. +// RUN: llvm-profdata show --function=main --ic-targets --show-vtables %t-test.profraw | FileCheck %s --check-prefixes=COMMON,RAW + +// Generate indexed profile from raw profile and show the data. +// RUN: llvm-profdata merge %t-test.profraw -o %t-test.profdata +// RUN: llvm-profdata show --function=main --ic-targets --show-vtables %t-test.profdata | FileCheck %s --check-prefixes=COMMON,INDEXED + +// Generate text profile from raw and indexed profiles respectively and show the data. +// RUN: llvm-profdata merge --text %t-test.profraw -o %t-raw.proftext +// RUN: llvm-profdata show --function=main --ic-targets --show-vtables --text %t-raw.proftext | FileCheck %s --check-prefix=ICTEXT +// RUN: llvm-profdata merge --text %t-test.profdata -o %t-indexed.proftext +// RUN: llvm-profdata show --function=main --ic-targets --show-vtables --text %t-indexed.proftext | FileCheck %s --check-prefix=ICTEXT + +// Generate indexed profile from text profiles and show the data +// RUN: llvm-profdata merge --binary %t-raw.proftext -o %t-text.profraw +// RUN: llvm-profdata show --function=main --ic-targets --show-vtables %t-text.profraw | FileCheck %s --check-prefixes=COMMON,INDEXED +// RUN: llvm-profdata merge --binary %t-indexed.proftext -o %t-text.profdata +// RUN: llvm-profdata show --function=main --ic-targets --show-vtables %t-text.profdata | FileCheck %s --check-prefixes=COMMON,INDEXED + +// COMMON: Counters: +// COMMON-NEXT: main: +// COMMON-NEXT: Hash: 0x0f9a16fe6d398548 +// COMMON-NEXT: Counters: 2 +// COMMON-NEXT: Indirect Call Site Count: 2 +// COMMON-NEXT: Number of instrumented vtables: 2 +// RAW: Indirect Target Results: +// RAW-NEXT: [ 0, _ZN8Derived15func1Eii, 250 ] (25.00%) +// RAW-NEXT: [ 0, {{.*}}instrprof-vtable-value-prof.cpp;_ZN12_GLOBAL__N_18Derived25func1Eii, 750 ] (75.00%) +// RAW-NEXT: [ 1, _ZN8Derived15func2Eii, 250 ] (25.00%) +// RAW-NEXT: [ 1, {{.*}}instrprof-vtable-value-prof.cpp;_ZN12_GLOBAL__N_18Derived25func2Eii, 750 ] (75.00%) +// RAW-NEXT: VTable Results: +// RAW-NEXT: [ 0, _ZTV8Derived1, 250 ] (25.00%) +// RAW-NEXT: [ 0, {{.*}}instrprof-vtable-value-prof.cpp;_ZTVN12_GLOBAL__N_18Derived2E, 750 ] (75.00%) +// RAW-NEXT: [ 1, _ZTV8Derived1, 250 ] (25.00%) +// RAW-NEXT: [ 1, {{.*}}instrprof-vtable-value-prof.cpp;_ZTVN12_GLOBAL__N_18Derived2E, 750 ] (75.00%) +// INDEXED: Indirect Target Results: +// INDEXED-NEXT: [ 0, {{.*}}instrprof-vtable-value-prof.cpp;_ZN12_GLOBAL__N_18Derived25func1Eii, 750 ] (75.00%) +// INDEXED-NEXT: [ 0, _ZN8Derived15func1Eii, 250 ] (25.00%) +// INDEXED-NEXT: [ 1, {{.*}}instrprof-vtable-value-prof.cpp;_ZN12_GLOBAL__N_18Derived25func2Eii, 750 ] (75.00%) +// INDEXED-NEXT: [ 1, _ZN8Derived15func2Eii, 250 ] (25.00%) +// INDEXED-NEXT: VTable Results: +// INDEXED-NEXT: [ 0, {{.*}}instrprof-vtable-value-prof.cpp;_ZTVN12_GLOBAL__N_18Derived2E, 750 ] (75.00%) +// INDEXED-NEXT: [ 0, _ZTV8Derived1, 250 ] (25.00%) +// INDEXED-NEXT: [ 1, {{.*}}instrprof-vtable-value-prof.cpp;_ZTVN12_GLOBAL__N_18Derived2E, 750 ] (75.00%) +// INDEXED-NEXT: [ 1, _ZTV8Derived1, 250 ] (25.00%) +// COMMON: Instrumentation level: IR entry_first = 0 +// COMMON-NEXT: Functions shown: 1 +// COMMON-NEXT: Total functions: 6 +// COMMON-NEXT: Maximum function count: 1000 +// COMMON-NEXT: Maximum internal block count: 250 +// COMMON-NEXT: Statistics for indirect call sites profile: +// COMMON-NEXT: Total number of sites: 2 +// COMMON-NEXT: Total number of sites with values: 2 +// COMMON-NEXT: Total number of profiled values: 4 +// COMMON-NEXT: Value sites histogram: +// COMMON-NEXT: NumTargets, SiteCount +// COMMON-NEXT: 2, 2 +// COMMON-NEXT: Statistics for vtable profile: +// COMMON-NEXT: Total number of sites: 2 +// COMMON-NEXT: Total number of sites with values: 2 +// COMMON-NEXT: Total number of profiled values: 4 +// COMMON-NEXT: Value sites histogram: +// COMMON-NEXT: NumTargets, SiteCount +// COMMON-NEXT: 2, 2 + +// ICTEXT: :ir +// ICTEXT: main +// ICTEXT: # Func Hash: +// ICTEXT: 1124236338992350536 +// ICTEXT: # Num Counters: +// ICTEXT: 2 +// ICTEXT: # Counter Values: +// ICTEXT: 1000 +// ICTEXT: 1 +// ICTEXT: # Num Value Kinds: +// ICTEXT: 2 +// ICTEXT: # ValueKind = IPVK_IndirectCallTarget: +// ICTEXT: 0 +// ICTEXT: # NumValueSites: +// ICTEXT: 2 +// ICTEXT: 2 +// ICTEXT: {{.*}}instrprof-vtable-value-prof.cpp;_ZN12_GLOBAL__N_18Derived25func1Eii:750 +// ICTEXT: _ZN8Derived15func1Eii:250 +// ICTEXT: 2 +// ICTEXT: {{.*}}instrprof-vtable-value-prof.cpp;_ZN12_GLOBAL__N_18Derived25func2Eii:750 +// ICTEXT: _ZN8Derived15func2Eii:250 +// ICTEXT: # ValueKind = IPVK_VTableTarget: +// ICTEXT: 2 +// ICTEXT: # NumValueSites: +// ICTEXT: 2 +// ICTEXT: 2 +// ICTEXT: {{.*}}instrprof-vtable-value-prof.cpp;_ZTVN12_GLOBAL__N_18Derived2E:750 +// ICTEXT: _ZTV8Derived1:250 +// ICTEXT: 2 +// ICTEXT: {{.*}}instrprof-vtable-value-prof.cpp;_ZTVN12_GLOBAL__N_18Derived2E:750 +// ICTEXT: _ZTV8Derived1:250 + +#include <cstdio> +#include <cstdlib> +class Base { +public: + virtual int func1(int a, int b) = 0; + virtual int func2(int a, int b) = 0; +}; +class Derived1 : public Base { +public: + int func1(int a, int b) override { return a + b; } + + int func2(int a, int b) override { return a * b; } +}; +namespace { +class Derived2 : public Base { +public: + int func1(int a, int b) override { return a - b; } + + int func2(int a, int b) override { return a * (a - b); } +}; +} // namespace +__attribute__((noinline)) Base *createType(int a) { + Base *base = nullptr; + if (a % 4 == 0) + base = new Derived1(); + else + base = new Derived2(); + return base; +} +int main(int argc, char **argv) { + int sum = 0; + for (int i = 0; i < 1000; i++) { + int a = rand(); + int b = rand(); + Base *ptr = createType(i); + sum += ptr->func1(a, b) + ptr->func2(b, a); + } + printf("sum is %d\n", sum); + return 0; +} diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/static-link.c b/compiler-rt/test/sanitizer_common/TestCases/Linux/static-link.c new file mode 100644 index 0000000000000000000000000000000000000000..f45f718cb08d34de1a4969aff398a63195551bc9 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/static-link.c @@ -0,0 +1,2 @@ +// UNSUPPORTED: hwasan, ubsan +// RUN: not %clangxx -static %s -o /dev/null diff --git a/compiler-rt/test/sanitizer_common/TestCases/corelimit.cpp b/compiler-rt/test/sanitizer_common/TestCases/corelimit.cpp index 2378a4cfdced12a29dc4ef7c67f992e1c0bccde1..9b56471905aaf4d731c3794d50cec7fa0291ba79 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/corelimit.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/corelimit.cpp @@ -10,7 +10,9 @@ int main() { getrlimit(RLIMIT_CORE, &lim_core); void *p; if (sizeof(p) == 8) { - assert(0 == lim_core.rlim_cur); + // rlim_cur will be set to zero or one depending on the target OS and + // initial core limits. See comments in DisableCoreDumperIfNecessary(). + assert(lim_core.rlim_cur <= 1u); } return 0; } diff --git a/compiler-rt/test/tsan/Linux/signal_in_futex_wait.cpp b/compiler-rt/test/tsan/Linux/signal_in_futex_wait.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3c8804aae3d09cb3a8fa6ef42977248c9f356df2 --- /dev/null +++ b/compiler-rt/test/tsan/Linux/signal_in_futex_wait.cpp @@ -0,0 +1,113 @@ +// RUN: %clang_tsan %s -lstdc++ -o %t && %run %t 2>&1 | FileCheck %s + +#include "../test.h" +#include <errno.h> +#include <linux/futex.h> +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <sys/syscall.h> + +#include <cassert> +#include <stdexcept> +#include <thread> + +#include <sanitizer/linux_syscall_hooks.h> + +int futex(int *uaddr, int futex_op, int val, const struct timespec *timeout, + int *uaddr2, int val3) { + __sanitizer_syscall_pre_futex(uaddr, futex_op, val, timeout, uaddr2, val3); + int result = syscall(SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3); + __sanitizer_syscall_post_futex(result, uaddr, futex_op, val, timeout, uaddr2, + val3); + return result; +} + +// Simple mutex implementation using futex. +class Mutex { +public: + Mutex() : value(0) {} + + void lock() { + int c; + while ((c = __sync_val_compare_and_swap(&value, 0, 1)) != 0) { + if (c != 1) + continue; + int r = futex(&value, FUTEX_WAIT_PRIVATE, 1, nullptr, nullptr, 0); + if (r == -1 && errno != EAGAIN) { + fprintf(stderr, "futex wait error\n"); + abort(); + } + } + } + + void unlock() { + value = 0; + int r = futex(&value, FUTEX_WAKE_PRIVATE, 1, nullptr, nullptr, 0); + if (r == -1) { + fprintf(stderr, "futex wake error\n"); + abort(); + } + } + +private: + int value; +}; + +Mutex mutex; + +void *Thread(void *x) { + // Waiting for the futex. + mutex.lock(); + // Finished waiting. + return nullptr; +} + +static void SigprofHandler(int signal, siginfo_t *info, void *context) { + // Unlock the futex. + mutex.unlock(); +} + +void InstallSignalHandler() { + struct sigaction sa; + sa.sa_sigaction = SigprofHandler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART | SA_SIGINFO; + if (sigaction(SIGPROF, &sa, 0) != 0) { + fprintf(stderr, "failed to install signal handler\n"); + abort(); + } +} + +int main() { + alarm(60); // Kill the test if it hangs. + + // Install the signal handler + InstallSignalHandler(); + + // Lock the futex at first so the other thread will wait for it. + mutex.lock(); + + // Create the thread to wait for the futex. + pthread_t thread; + pthread_create(&thread, NULL, Thread, NULL); + + // Just waiting a bit to make sure the thead is at the FUTEX_WAIT_PRIVATE + // syscall. + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + // Send the signal to the other thread, which will send the futex wake + // syscall. + int r = pthread_kill(thread, SIGPROF); + assert(r == 0); + + // Futex should be notified and the thread should be able to continue. + pthread_join(thread, NULL); + + // Exiting successfully. + fprintf(stderr, "PASS\n"); + return 0; +} + +// CHECK-NOT: WARNING: ThreadSanitizer: +// CHECK: PASS diff --git a/compiler-rt/test/tsan/getline_nohang.cpp b/compiler-rt/test/tsan/getline_nohang.cpp index d1bb279a450f554b272bb478c1a2eddd9150d4ef..c0762da96abb90ab1f82477bcc4d0ebc0af49f3b 100644 --- a/compiler-rt/test/tsan/getline_nohang.cpp +++ b/compiler-rt/test/tsan/getline_nohang.cpp @@ -5,6 +5,10 @@ // Make sure TSan doesn't deadlock on a file stream lock at program shutdown. // See https://github.com/google/sanitizers/issues/454 + +// https://github.com/google/sanitizers/issues/1733 +// UNSUPPORTED: glibc-2.38 + #ifdef __FreeBSD__ #define _WITH_GETLINE // to declare getline() #endif diff --git a/compiler-rt/test/tsan/signal_in_mutex_lock.cpp b/compiler-rt/test/tsan/signal_in_mutex_lock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ec99e23198400fccd02e6296e28332a73e8193ee --- /dev/null +++ b/compiler-rt/test/tsan/signal_in_mutex_lock.cpp @@ -0,0 +1,71 @@ +// RUN: %clang_tsan %s -lstdc++ -o %t && %run %t 2>&1 | FileCheck %s + +#include "test.h" +#include <pthread.h> +#include <signal.h> +#include <stdio.h> + +#include <cassert> +#include <condition_variable> +#include <mutex> + +std::mutex sampler_mutex; //dummy mutex to lock in the thread we spawn. +std::mutex done_mutex; // guards the cv and done variables. +std::condition_variable cv; +bool done = false; + +void *ThreadFunc(void *x) { + while (true) { + // Lock the mutex + std::lock_guard<std::mutex> guard(sampler_mutex); + // Mutex is released at the end + } + + return nullptr; +} + +static void SigprofHandler(int signal, siginfo_t *info, void *context) { + // Assuming we did some work, change the variable to let the main thread + // know that we are done. + { + std::unique_lock<std::mutex> lck(done_mutex); + done = true; + cv.notify_one(); + } +} + +int main() { + alarm(60); // Kill the test if it hangs. + + // Install the signal handler + struct sigaction sa; + sa.sa_sigaction = SigprofHandler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART | SA_SIGINFO; + if (sigaction(SIGPROF, &sa, 0) != 0) { + fprintf(stderr, "failed to install signal handler\n"); + abort(); + } + + // Spawn a thread that will just loop and get the mutex lock: + pthread_t thread; + pthread_create(&thread, NULL, ThreadFunc, NULL); + + // Lock the mutex before sending the signal + std::lock_guard<std::mutex> guard(sampler_mutex); + // From now on thread 1 will be waiting for the lock + + // Send the SIGPROF signal to thread. + int r = pthread_kill(thread, SIGPROF); + assert(r == 0); + + // Wait until signal handler sends the data. + std::unique_lock lk(done_mutex); + cv.wait(lk, [] { return done; }); + + // We got the done variable from the signal handler. Exiting successfully. + fprintf(stderr, "PASS\n"); +} + +// CHECK-NOT: WARNING: ThreadSanitizer: +// CHECK: PASS diff --git a/compiler-rt/test/ubsan/CMakeLists.txt b/compiler-rt/test/ubsan/CMakeLists.txt index b5040f79e607ba5cf85ea500f47b431da52505cc..52052c80960c24e0d95b94e0fb0ca4e2174b71d1 100644 --- a/compiler-rt/test/ubsan/CMakeLists.txt +++ b/compiler-rt/test/ubsan/CMakeLists.txt @@ -23,9 +23,7 @@ macro(add_ubsan_testsuite test_mode sanitizer arch lld thinlto) ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg.py) list(APPEND UBSAN_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}) - if(NOT COMPILER_RT_STANDALONE_BUILD) - list(APPEND UBSAN_TEST_DEPS ${sanitizer}) - endif() + list(APPEND UBSAN_TEST_DEPS ${sanitizer}) endmacro() macro(add_ubsan_testsuites test_mode sanitizer arch) diff --git a/compiler-rt/test/xray/CMakeLists.txt b/compiler-rt/test/xray/CMakeLists.txt index b97659ae08f9bd71b53f113d5cd411f65bea8ca8..0c008b6ea5577bb977981dfb0ee16e05b1dbe32f 100644 --- a/compiler-rt/test/xray/CMakeLists.txt +++ b/compiler-rt/test/xray/CMakeLists.txt @@ -3,12 +3,11 @@ set(XRAY_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(XRAY_TESTSUITES) set(XRAY_FDR_TESTSUITES) -set(XRAY_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) -set(XRAY_FDR_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) +set(XRAY_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS} xray) if(NOT COMPILER_RT_STANDALONE_BUILD AND COMPILER_RT_BUILD_XRAY AND COMPILER_RT_HAS_XRAY) - list(APPEND XRAY_TEST_DEPS xray llvm-xray) + list(APPEND XRAY_TEST_DEPS llvm-xray) endif() set(XRAY_TEST_ARCH ${XRAY_SUPPORTED_ARCH}) diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/Debuggers.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/Debuggers.py index b251f1a0538ce3abbdce11cb87d45f85b7b1c65a..1b0d4d5871cbeb5a76efb88d8499af645c8e1bf6 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/Debuggers.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/Debuggers.py @@ -28,6 +28,7 @@ from dex.debugger.lldb.LLDB import LLDB from dex.debugger.visualstudio.VisualStudio2015 import VisualStudio2015 from dex.debugger.visualstudio.VisualStudio2017 import VisualStudio2017 from dex.debugger.visualstudio.VisualStudio2019 import VisualStudio2019 +from dex.debugger.visualstudio.VisualStudio2022 import VisualStudio2022 def _get_potential_debuggers(): # noqa @@ -41,6 +42,7 @@ def _get_potential_debuggers(): # noqa VisualStudio2015.get_option_name(): VisualStudio2015, VisualStudio2017.get_option_name(): VisualStudio2017, VisualStudio2019.get_option_name(): VisualStudio2019, + VisualStudio2022.get_option_name(): VisualStudio2022, } diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio2022.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio2022.py new file mode 100644 index 0000000000000000000000000000000000000000..6fcf8af4acabc1782fcca866991ff5a12a42e578 --- /dev/null +++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio2022.py @@ -0,0 +1,23 @@ +# DExTer : Debugging Experience Tester +# ~~~~~~ ~ ~~ ~ ~~ +# +# 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 +"""Specializations for the Visual Studio 2022 interface.""" + +from dex.debugger.visualstudio.VisualStudio import VisualStudio + + +class VisualStudio2022(VisualStudio): + @classmethod + def get_name(cls): + return "Visual Studio 2022" + + @classmethod + def get_option_name(cls): + return "vs2022" + + @property + def _dte_version(self): + return "VisualStudio.DTE.17.0" diff --git a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/list-debuggers/list-debuggers.test b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/list-debuggers/list-debuggers.test index bbc9dd501b00498b0c469a52833c53608a1ae4d5..2bce540ced1813424aa9fb01e4163f8e53d0eb3c 100644 --- a/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/list-debuggers/list-debuggers.test +++ b/cross-project-tests/debuginfo-tests/dexter/feature_tests/subtools/list-debuggers/list-debuggers.test @@ -5,3 +5,5 @@ RUN: %dexter_base list-debuggers | FileCheck %s CHECK: lldb CHECK: vs2015 CHECK: vs2017 +CHECK: vs2019 +CHECK: vs2022 diff --git a/cross-project-tests/debuginfo-tests/llgdb-tests/forward-declare-class.cpp b/cross-project-tests/debuginfo-tests/llgdb-tests/forward-declare-class.cpp index 850eed6ad95d98b6a74b6c365b47936598da6104..130c439faec8cdd98765c7820f81614bd85fda65 100644 --- a/cross-project-tests/debuginfo-tests/llgdb-tests/forward-declare-class.cpp +++ b/cross-project-tests/debuginfo-tests/llgdb-tests/forward-declare-class.cpp @@ -1,6 +1,7 @@ // RUN: %clangxx %target_itanium_abi_host_triple -O0 -g %s -c -o %t.o // RUN: %test_debuginfo %s %t.o // Radar 9168773 +// XFAIL: !system-darwin && gdb-clang-incompatibility // DEBUGGER: ptype A // Work around a gdb bug where it believes that a class is a diff --git a/flang/docs/OpenMP-descriptor-management.md b/flang/docs/OpenMP-descriptor-management.md index 90a20282e0512647c9bf6631a561e6ce131249c7..368ff3e911fcb223392e87e0e644a1b62b6cd1d6 100644 --- a/flang/docs/OpenMP-descriptor-management.md +++ b/flang/docs/OpenMP-descriptor-management.md @@ -49,15 +49,16 @@ the lowering to FIR/HLFIR has been performed an OpenMP dialect specific pass for mappings, with one extra per pointer member in the descriptor that is supported on top of the original descriptor map operation. These pointers members are linked to the parent descriptor by adding them to the member field of the original descriptor map operation, they are then inserted into the relevant map -owning operation's (`omp.TargetOp`, `omp.DataOp` etc.) map operand list and in cases where the owning operation -is `IsolatedFromAbove`, it also inserts them as `BlockArgs` to canonicalize the mappings and simplify lowering. +owning operation's (`omp.TargetOp`, `omp.TargetDataOp` etc.) map operand list and in cases where the owning +operation is `IsolatedFromAbove`, it also inserts them as `BlockArgs` to canonicalize the mappings and +simplify lowering. An example transformation by the `OMPDescriptorMapInfoGenPass`: ``` ... -%12 = omp.map_info var_ptr(%1#1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.box<!fir.ptr<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) bounds(%11) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {name = "arg_alloc"} +%12 = omp.map.info var_ptr(%1#1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.box<!fir.ptr<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) bounds(%11) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {name = "arg_alloc"} ... omp.target map_entries(%12 -> %arg1, %13 -> %arg2 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<i32>) { ^bb0(%arg1: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, %arg2: !fir.ref<i32>): @@ -67,8 +68,8 @@ omp.target map_entries(%12 -> %arg1, %13 -> %arg2 : !fir.ref<!fir.box<!fir.ptr<! ... %12 = fir.box_offset %1#1 base_addr : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> -%13 = omp.map_info var_ptr(%1#1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.array<?xi32>) var_ptr_ptr(%12 : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) bounds(%11) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -%14 = omp.map_info var_ptr(%1#1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.box<!fir.ptr<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) members(%13 : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {name = "arg_alloc"} +%13 = omp.map.info var_ptr(%1#1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.array<?xi32>) var_ptr_ptr(%12 : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) bounds(%11) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} +%14 = omp.map.info var_ptr(%1#1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.box<!fir.ptr<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) members(%13 : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {name = "arg_alloc"} ... omp.target map_entries(%13 -> %arg1, %14 -> %arg2, %15 -> %arg3 : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<i32>) { ^bb0(%arg1: !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, %arg2: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, %arg3: !fir.ref<i32>): diff --git a/flang/docs/RuntimeEnvironment.md b/flang/docs/RuntimeEnvironment.md new file mode 100644 index 0000000000000000000000000000000000000000..c7a3dfbb2af1dd9be26388dce36926a2c84da2a0 --- /dev/null +++ b/flang/docs/RuntimeEnvironment.md @@ -0,0 +1,57 @@ +<!--===- docs/RuntimeEnvironment.md + + 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 + +--> + +```{contents} +--- +local: +--- +``` + +# Environment variables of significance to Fortran execution + +A few environment variables are queried by the Fortran runtime support +library. + +The following environment variables can affect the behavior of +Fortran programs during execution. + +## `DEFAULT_UTF8=1` + +Set `DEFAULT_UTF8` to cause formatted external input to assume UTF-8 +encoding on input and use UTF-8 encoding on formatted external output. + +## `FORT_CONVERT` + +Determines data conversions applied to unformatted I/O. + +* `NATIVE`: no conversions (default) +* `LITTLE_ENDIAN`: assume input is little-endian; emit little-endian output +* `BIG_ENDIAN`: assume input is big-endian; emit big-endian output +* `SWAP`: reverse endianness (always convert) + +## `FORT_CHECK_POINTER_DEALLOCATION` + +Fortran requires that a pointer that appears in a `DEALLOCATE` statement +must have been allocated in an `ALLOCATE` statement with the same declared +type. +The runtime support library validates this requirement by checking the +size of the allocated data, and will fail with an error message if +the deallocated pointer is not valid. +Set `FORT_CHECK_POINTER_DEALLOCATION=0` to disable this check. + +## `FORT_FMT_RECL` + +Set to an integer value to specify the record length for list-directed +and `NAMELIST` output. +The default is 72. + +## `NO_STOP_MESSAGE` + +Set `NO_STOP_MESSAGE=1` to disable the extra information about +IEEE floating-point exception flags that the Fortran language +standard requires for `STOP` and `ERROR STOP` statements. diff --git a/flang/docs/index.md b/flang/docs/index.md index b4dbdc87fdf685fadd60168b4ab95c2745b892b7..ed749f565ff1b8cfbde896e957f67d9fbea633f1 100644 --- a/flang/docs/index.md +++ b/flang/docs/index.md @@ -80,6 +80,7 @@ on how to get in touch with us and to learn more about the current status. Preprocessing ProcedurePointer RuntimeDescriptor + RuntimeEnvironment RuntimeTypeInfo Semantics f2018-grammar.md diff --git a/flang/include/flang/Common/Version.h b/flang/include/flang/Common/Version.h index b1bd2416a618409aed87993563bdc1a712b3c40a..3257d4a4f6459393807aa21e77aabaf3cf1a72ef 100644 --- a/flang/include/flang/Common/Version.h +++ b/flang/include/flang/Common/Version.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_FLANG_COMMON_VERSION_H -#define LLVM_FLANG_COMMON_VERSION_H +#ifndef FORTRAN_COMMON_VERSION_H +#define FORTRAN_COMMON_VERSION_H #include "flang/Version.inc" #include "llvm/ADT/StringRef.h" @@ -53,4 +53,4 @@ std::string getFlangFullVersion(); std::string getFlangToolFullVersion(llvm::StringRef ToolName); } // namespace Fortran::common -#endif // LLVM_FLANG_COMMON_VERSION_H +#endif // FORTRAN_COMMON_VERSION_H diff --git a/flang/include/flang/Runtime/api-attrs.h b/flang/include/flang/Common/api-attrs.h similarity index 91% rename from flang/include/flang/Runtime/api-attrs.h rename to flang/include/flang/Common/api-attrs.h index 9c8a67ffc34a82fb08a837b5d04e8f148c715517..4d069c6097ddfe91614339518041827cb8646b83 100644 --- a/flang/include/flang/Runtime/api-attrs.h +++ b/flang/include/flang/Common/api-attrs.h @@ -1,4 +1,4 @@ -/*===-- include/flang/Runtime/api-attrs.h ---------------------------*- C -*-=// +/*===-- include/flang/Common/api-attrs.h ---------------------------*- C -*-=// * * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. * See https://llvm.org/LICENSE.txt for license information. @@ -102,13 +102,25 @@ * to appear as part of a C++ decl-specifier. */ #ifndef RT_CONST_VAR_ATTRS -#if defined(__CUDACC__) || defined(__CUDA__) +#if (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) #define RT_CONST_VAR_ATTRS __constant__ #else #define RT_CONST_VAR_ATTRS #endif #endif /* !defined(RT_CONST_VAR_ATTRS) */ +/* + * RT_VAR_ATTRS is marking non-const/constexpr module scope variables + * referenced by Flang runtime. + */ +#ifndef RT_VAR_ATTRS +#if (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) +#define RT_VAR_ATTRS __device__ +#else +#define RT_VAR_ATTRS +#endif +#endif /* !defined(RT_VAR_ATTRS) */ + /* * RT_DEVICE_COMPILATION is defined for any device compilation. * Note that it can only be used reliably with compilers that perform diff --git a/flang/include/flang/Common/idioms.h b/flang/include/flang/Common/idioms.h index f6c9cbbc0f7cd0cc5abac353389cadf8c8813d6d..99f383ec75b9995d143d0aa18a0cbb4238225d9a 100644 --- a/flang/include/flang/Common/idioms.h +++ b/flang/include/flang/Common/idioms.h @@ -24,6 +24,7 @@ #endif #include "enum-class.h" +#include "variant.h" #include "visit.h" #include <array> #include <functional> @@ -33,7 +34,6 @@ #include <string> #include <tuple> #include <type_traits> -#include <variant> #if __GNUC__ == 7 // Avoid a deduction bug in GNU 7.x headers by forcing the answer. @@ -87,6 +87,8 @@ template <typename... LAMBDAS> visitors(LAMBDAS... x) -> visitors<LAMBDAS...>; // To disable, compile with '-DCHECK=(void)' #ifndef CHECK #define CHECK(x) ((x) || (DIE("CHECK(" #x ") failed"), false)) +// Same as above, but with a custom error message. +#define CHECK_MSG(x, y) ((x) || (DIE("CHECK(" #x ") failed: " #y), false)) #endif // User-defined type traits that default to false: diff --git a/flang/include/flang/Common/optional.h b/flang/include/flang/Common/optional.h new file mode 100644 index 0000000000000000000000000000000000000000..c0f4278009f40a8b8ea9d879422ad4fe50e42768 --- /dev/null +++ b/flang/include/flang/Common/optional.h @@ -0,0 +1,243 @@ +//===-- include/flang/Common/optional.h -------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Implementation of std::optional borrowed from LLVM's +// libc/src/__support/CPP/optional.h with modifications (e.g. value_or, emplace +// methods were added). +// +// The implementation defines optional in Fortran::common namespace. +// This standalone implementation may be used if the target +// does not support std::optional implementation (e.g. CUDA device env), +// otherwise, Fortran::common::optional is an alias for std::optional. +// +// TODO: using libcu++ is the best option for CUDA, but there is a couple +// of issues: +// * Older CUDA toolkits' libcu++ implementations do not support optional. +// * The include paths need to be set up such that all STD header files +// are taken from libcu++. +// * cuda:: namespace need to be forced for all std:: references. +// +//===----------------------------------------------------------------------===// +#ifndef FORTRAN_COMMON_OPTIONAL_H +#define FORTRAN_COMMON_OPTIONAL_H + +#include "flang/Common/api-attrs.h" +#include <optional> +#include <type_traits> + +#if !defined(STD_OPTIONAL_UNSUPPORTED) && \ + (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) +#define STD_OPTIONAL_UNSUPPORTED 1 +#endif + +#define FORTRAN_OPTIONAL_INLINE_WITH_ATTRS inline RT_API_ATTRS +#define FORTRAN_OPTIONAL_INLINE inline +#define FORTRAN_OPTIONAL_INLINE_VAR inline + +namespace Fortran::common { + +#if STD_OPTIONAL_UNSUPPORTED +// Trivial nullopt_t struct. +struct nullopt_t { + constexpr explicit nullopt_t() = default; +}; + +// nullopt that can be used and returned. +FORTRAN_OPTIONAL_INLINE_VAR constexpr nullopt_t nullopt{}; + +// This is very simple implementation of the std::optional class. It makes +// several assumptions that the underlying type is trivially constructible, +// copyable, or movable. +template <typename T> class optional { + template <typename U, bool = !std::is_trivially_destructible<U>::value> + struct OptionalStorage { + union { + char empty; + U stored_value; + }; + + bool in_use = false; + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS ~OptionalStorage() { reset(); } + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr OptionalStorage() : empty() {} + + template <typename... Args> + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr explicit OptionalStorage( + std::in_place_t, Args &&...args) + : stored_value(std::forward<Args>(args)...) {} + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr void reset() { + if (in_use) + stored_value.~U(); + in_use = false; + } + }; + + // The only difference is that this type U doesn't have a nontrivial + // destructor. + template <typename U> struct OptionalStorage<U, false> { + union { + char empty; + U stored_value; + }; + + bool in_use = false; + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr OptionalStorage() : empty() {} + + template <typename... Args> + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr explicit OptionalStorage( + std::in_place_t, Args &&...args) + : stored_value(std::forward<Args>(args)...) {} + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr void reset() { + in_use = false; + } + }; + + OptionalStorage<T> storage; + +public: + // The default methods do not use RT_API_ATTRS, which causes + // warnings in CUDA compilation of form: + // __device__/__host__ annotation is ignored on a function .* that is + // explicitly defaulted on its first declaration + FORTRAN_OPTIONAL_INLINE constexpr optional() = default; + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr optional(nullopt_t) {} + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr optional(const T &t) + : storage(std::in_place, t) { + storage.in_use = true; + } + FORTRAN_OPTIONAL_INLINE constexpr optional(const optional &) = default; + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr optional(T &&t) + : storage(std::in_place, std::move(t)) { + storage.in_use = true; + } + FORTRAN_OPTIONAL_INLINE constexpr optional(optional &&O) = default; + + template <typename... ArgTypes> + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr optional( + std::in_place_t, ArgTypes &&...Args) + : storage(std::in_place, std::forward<ArgTypes>(Args)...) { + storage.in_use = true; + } + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr optional &operator=(T &&t) { + storage.stored_value = std::move(t); + storage.in_use = true; + return *this; + } + + FORTRAN_OPTIONAL_INLINE constexpr optional &operator=(optional &&) = default; + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr optional &operator=(const T &t) { + storage.stored_value = t; + storage.in_use = true; + return *this; + } + + FORTRAN_OPTIONAL_INLINE constexpr optional &operator=( + const optional &) = default; + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr void reset() { storage.reset(); } + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr const T &value() const & { + return storage.stored_value; + } + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr T &value() & { + return storage.stored_value; + } + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr explicit operator bool() const { + return storage.in_use; + } + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr bool has_value() const { + return storage.in_use; + } + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr const T *operator->() const { + return &storage.stored_value; + } + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr T *operator->() { + return &storage.stored_value; + } + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr const T &operator*() const & { + return storage.stored_value; + } + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr T &operator*() & { + return storage.stored_value; + } + + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr T &&value() && { + return std::move(storage.stored_value); + } + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr T &&operator*() && { + return std::move(storage.stored_value); + } + + template <typename VT> + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr T value_or( + VT &&default_value) const & { + return storage.in_use ? storage.stored_value + : static_cast<T>(std::forward<VT>(default_value)); + } + + template <typename VT> + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr T value_or( + VT &&default_value) && { + return storage.in_use ? std::move(storage.stored_value) + : static_cast<T>(std::forward<VT>(default_value)); + } + + template <typename... ArgTypes> + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS + std::enable_if_t<std::is_constructible_v<T, ArgTypes &&...>, T &> + emplace(ArgTypes &&...args) { + reset(); + new (reinterpret_cast<void *>(std::addressof(storage.stored_value))) + T(std::forward<ArgTypes>(args)...); + storage.in_use = true; + return value(); + } + + template <typename U = T, + std::enable_if_t<(std::is_constructible_v<T, U &&> && + !std::is_same_v<std::decay_t<U>, std::in_place_t> && + !std::is_same_v<std::decay_t<U>, optional> && + std::is_convertible_v<U &&, T>), + bool> = true> + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS constexpr optional(U &&value) { + new (reinterpret_cast<void *>(std::addressof(storage.stored_value))) + T(std::forward<U>(value)); + storage.in_use = true; + } + + template <typename U = T, + std::enable_if_t<(std::is_constructible_v<T, U &&> && + !std::is_same_v<std::decay_t<U>, std::in_place_t> && + !std::is_same_v<std::decay_t<U>, optional> && + !std::is_convertible_v<U &&, T>), + bool> = false> + FORTRAN_OPTIONAL_INLINE_WITH_ATTRS explicit constexpr optional(U &&value) { + new (reinterpret_cast<void *>(std::addressof(storage.stored_value))) + T(std::forward<U>(value)); + storage.in_use = true; + } +}; +#else // !STD_OPTIONAL_UNSUPPORTED +using std::nullopt; +using std::nullopt_t; +using std::optional; +#endif // !STD_OPTIONAL_UNSUPPORTED + +} // namespace Fortran::common + +#endif // FORTRAN_COMMON_OPTIONAL_H diff --git a/flang/include/flang/Common/real.h b/flang/include/flang/Common/real.h index 50aab7d89a597ef8ea321f8631130e960f160139..49c400b368a2c190b1dfce18424d3115320070e8 100644 --- a/flang/include/flang/Common/real.h +++ b/flang/include/flang/Common/real.h @@ -13,6 +13,7 @@ // The various representations are distinguished by their binary precisions // (number of explicit significand bits and any implicit MSB in the fraction). +#include "flang/Common/api-attrs.h" #include <cinttypes> namespace Fortran::common { @@ -119,6 +120,7 @@ private: } public: + RT_OFFLOAD_VAR_GROUP_BEGIN static constexpr int binaryPrecision{BINARY_PRECISION}; static constexpr int bits{BitsForBinaryPrecision(binaryPrecision)}; static constexpr bool isImplicitMSB{binaryPrecision != 64 /*x87*/}; @@ -138,6 +140,7 @@ public: static constexpr int maxHexadecimalConversionDigits{ MaxHexadecimalConversionDigits(binaryPrecision)}; + RT_OFFLOAD_VAR_GROUP_END static_assert(binaryPrecision > 0); static_assert(exponentBits > 1); diff --git a/flang/include/flang/Common/reference-wrapper.h b/flang/include/flang/Common/reference-wrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..2983754108f95a7f5c48b2a4c9d5e6f72bc7e2c9 --- /dev/null +++ b/flang/include/flang/Common/reference-wrapper.h @@ -0,0 +1,114 @@ +//===-- include/flang/Common/reference-wrapper.h ----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// clang-format off +// +// Implementation of std::reference_wrapper borrowed from libcu++ +// https://github.com/NVIDIA/libcudacxx/blob/f7e6cd07ed5ba826aeac0b742feafddfedc1e400/include/cuda/std/detail/libcxx/include/__functional/reference_wrapper.h#L1 +// with modifications. +// +// The original source code is distributed under the Apache License v2.0 +// with LLVM Exceptions. +// +// TODO: using libcu++ is the best option for CUDA, but there is a couple +// of issues: +// * The include paths need to be set up such that all STD header files +// are taken from libcu++. +// * cuda:: namespace need to be forced for all std:: references. +// +// clang-format on + +#ifndef FORTRAN_COMMON_REFERENCE_WRAPPER_H +#define FORTRAN_COMMON_REFERENCE_WRAPPER_H + +#include "flang/Common/api-attrs.h" +#include <functional> +#include <type_traits> + +#if !defined(STD_REFERENCE_WRAPPER_UNSUPPORTED) && \ + (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) +#define STD_REFERENCE_WRAPPER_UNSUPPORTED 1 +#endif + +namespace Fortran::common { + +template <class _Tp> +using __remove_cvref_t = std::remove_cv_t<std::remove_reference_t<_Tp>>; +template <class _Tp, class _Up> +struct __is_same_uncvref + : std::is_same<__remove_cvref_t<_Tp>, __remove_cvref_t<_Up>> {}; + +#if STD_REFERENCE_WRAPPER_UNSUPPORTED +template <class _Tp> class reference_wrapper { +public: + // types + typedef _Tp type; + +private: + type *__f_; + + static RT_API_ATTRS void __fun(_Tp &); + static void __fun(_Tp &&) = delete; + +public: + template <class _Up, + class = + std::enable_if_t<!__is_same_uncvref<_Up, reference_wrapper>::value, + decltype(__fun(std::declval<_Up>()))>> + constexpr RT_API_ATTRS reference_wrapper(_Up &&__u) { + type &__f = static_cast<_Up &&>(__u); + __f_ = std::addressof(__f); + } + + // access + constexpr RT_API_ATTRS operator type &() const { return *__f_; } + constexpr RT_API_ATTRS type &get() const { return *__f_; } + + // invoke + template <class... _ArgTypes> + constexpr RT_API_ATTRS typename std::invoke_result_t<type &, _ArgTypes...> + operator()(_ArgTypes &&...__args) const { + return std::invoke(get(), std::forward<_ArgTypes>(__args)...); + } +}; + +template <class _Tp> reference_wrapper(_Tp &) -> reference_wrapper<_Tp>; + +template <class _Tp> +inline constexpr RT_API_ATTRS reference_wrapper<_Tp> ref(_Tp &__t) { + return reference_wrapper<_Tp>(__t); +} + +template <class _Tp> +inline constexpr RT_API_ATTRS reference_wrapper<_Tp> ref( + reference_wrapper<_Tp> __t) { + return __t; +} + +template <class _Tp> +inline constexpr RT_API_ATTRS reference_wrapper<const _Tp> cref( + const _Tp &__t) { + return reference_wrapper<const _Tp>(__t); +} + +template <class _Tp> +inline constexpr RT_API_ATTRS reference_wrapper<const _Tp> cref( + reference_wrapper<_Tp> __t) { + return __t; +} + +template <class _Tp> void ref(const _Tp &&) = delete; +template <class _Tp> void cref(const _Tp &&) = delete; +#else // !STD_REFERENCE_WRAPPER_UNSUPPORTED +using std::cref; +using std::ref; +using std::reference_wrapper; +#endif // !STD_REFERENCE_WRAPPER_UNSUPPORTED + +} // namespace Fortran::common + +#endif // FORTRAN_COMMON_REFERENCE_WRAPPER_H diff --git a/flang/include/flang/Common/restorer.h b/flang/include/flang/Common/restorer.h index 4d5f5e4e2c818de6d4ae327e21ba8e2101818be0..0f1bc48620d37e879f10ac867468fa2233347658 100644 --- a/flang/include/flang/Common/restorer.h +++ b/flang/include/flang/Common/restorer.h @@ -19,11 +19,13 @@ #ifndef FORTRAN_COMMON_RESTORER_H_ #define FORTRAN_COMMON_RESTORER_H_ #include "idioms.h" +#include "flang/Common/api-attrs.h" namespace Fortran::common { template <typename A> class Restorer { public: - explicit Restorer(A &p, A original) : p_{p}, original_{std::move(original)} {} - ~Restorer() { p_ = std::move(original_); } + explicit RT_API_ATTRS Restorer(A &p, A original) + : p_{p}, original_{std::move(original)} {} + RT_API_ATTRS ~Restorer() { p_ = std::move(original_); } // Inhibit any recreation of this restorer that would result in two restorers // trying to restore the same reference. @@ -38,13 +40,14 @@ private: }; template <typename A, typename B> -common::IfNoLvalue<Restorer<A>, B> ScopedSet(A &to, B &&from) { +RT_API_ATTRS common::IfNoLvalue<Restorer<A>, B> ScopedSet(A &to, B &&from) { A original{std::move(to)}; to = std::move(from); return Restorer<A>{to, std::move(original)}; } template <typename A, typename B> -common::IfNoLvalue<Restorer<A>, B> ScopedSet(A &to, const B &from) { +RT_API_ATTRS common::IfNoLvalue<Restorer<A>, B> ScopedSet( + A &to, const B &from) { A original{std::move(to)}; to = from; return Restorer<A>{to, std::move(original)}; diff --git a/flang/include/flang/Common/template.h b/flang/include/flang/Common/template.h index 2ab3b8bce1df922872d296b97731cbcefae5494b..51d09fb42ce368424a21beb3728c0acf80f0260c 100644 --- a/flang/include/flang/Common/template.h +++ b/flang/include/flang/Common/template.h @@ -9,12 +9,12 @@ #ifndef FORTRAN_COMMON_TEMPLATE_H_ #define FORTRAN_COMMON_TEMPLATE_H_ +#include "variant.h" #include "flang/Common/idioms.h" #include <functional> #include <optional> #include <tuple> #include <type_traits> -#include <variant> #include <vector> // Utility templates for metaprogramming and for composing the diff --git a/flang/include/flang/Common/uint128.h b/flang/include/flang/Common/uint128.h index 03e44eb6997d5bdbaf9193c4790e413b6dcee81a..821c8c3b08a52fb055135162ed57cded7e74ef41 100644 --- a/flang/include/flang/Common/uint128.h +++ b/flang/include/flang/Common/uint128.h @@ -20,6 +20,7 @@ #endif #include "leading-zero-bit-count.h" +#include "flang/Common/api-attrs.h" #include <cstdint> #include <type_traits> @@ -260,7 +261,9 @@ private: return LeadingZeroBitCount(high_); } } + RT_VAR_GROUP_BEGIN static constexpr std::uint64_t topBit{std::uint64_t{1} << 63}; + RT_VAR_GROUP_END #if FLANG_LITTLE_ENDIAN std::uint64_t low_{0}, high_{0}; #elif FLANG_BIG_ENDIAN diff --git a/flang/include/flang/Common/unwrap.h b/flang/include/flang/Common/unwrap.h index edb343d77b53748a40e044dcd453b0168bde2714..84582174e4b30066243acb070c151ae6de79336a 100644 --- a/flang/include/flang/Common/unwrap.h +++ b/flang/include/flang/Common/unwrap.h @@ -12,11 +12,11 @@ #include "indirection.h" #include "reference-counted.h" #include "reference.h" +#include "variant.h" #include "visit.h" #include <memory> #include <optional> #include <type_traits> -#include <variant> // Given a nest of variants, optionals, &/or pointers, Unwrap<>() isolates // a packaged value of a specific type if it is present and returns a pointer diff --git a/flang/include/flang/Common/variant.h b/flang/include/flang/Common/variant.h new file mode 100644 index 0000000000000000000000000000000000000000..1af85876afac0037401cd4038b95a48982006a79 --- /dev/null +++ b/flang/include/flang/Common/variant.h @@ -0,0 +1,30 @@ +//===-- include/flang/Common/variant.h --------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// A single way to expose C++ variant class in files that can be used +// in F18 runtime build. With inclusion of this file std::variant +// and the related names become available, though, they may correspond +// to alternative definitions (e.g. from cuda::std namespace). + +#ifndef FORTRAN_COMMON_VARIANT_H +#define FORTRAN_COMMON_VARIANT_H + +#if RT_USE_LIBCUDACXX +#include <cuda/std/variant> +namespace std { +using cuda::std::get; +using cuda::std::monostate; +using cuda::std::variant; +using cuda::std::variant_size_v; +using cuda::std::visit; +} // namespace std +#else // !RT_USE_LIBCUDACXX +#include <variant> +#endif // !RT_USE_LIBCUDACXX + +#endif // FORTRAN_COMMON_VARIANT_H diff --git a/flang/include/flang/Common/visit.h b/flang/include/flang/Common/visit.h index d3136be3f6a1f0f8e6ccd7c8212b59945651e8d1..4d0897301e01db71dabf40dd58fb17ba5e45bad9 100644 --- a/flang/include/flang/Common/visit.h +++ b/flang/include/flang/Common/visit.h @@ -17,42 +17,37 @@ // // Define FLANG_USE_STD_VISIT to avoid this code and make common::visit() an // alias for ::std::visit(). -// -// -// With GCC 9.3.0 on a Haswell x86 Ubuntu system, doing out-of-tree builds: -// Before: -// build: -// 6948.53user 212.48system 27:32.92elapsed 433%CPU -// (0avgtext+0avgdata 6429568maxresident)k -// 36181912inputs+8943720outputs (3613684major+97908699minor)pagefaults 0swaps -// execution of tests: -// 205.99user 26.05system 1:08.87elapsed 336%CPU -// (0avgtext+0avgdata 2671452maxresident)k -// 244432inputs+355464outputs (422major+8746468minor)pagefaults 0swaps -// After: -// build: -// 6651.91user 182.57system 25:15.73elapsed 450%CPU -// (0avgtext+0avgdata 6209296maxresident)k -// 17413480inputs+6376360outputs (1567210major+93068230minor)pagefaults 0swaps -// execution of tests: -// 201.42user 25.91system 1:04.68elapsed 351%CPU -// (0avgtext+0avgdata 2661424maxresident)k -// 238840inputs+295912outputs (428major+8489300minor)pagefaults 0swaps #ifndef FORTRAN_COMMON_VISIT_H_ #define FORTRAN_COMMON_VISIT_H_ +#include "variant.h" +#include "flang/Common/api-attrs.h" #include <type_traits> -#include <variant> namespace Fortran::common { namespace log2visit { template <std::size_t LOW, std::size_t HIGH, typename RESULT, typename VISITOR, typename... VARIANT> -inline RESULT Log2VisitHelper( +inline RT_API_ATTRS RESULT Log2VisitHelper( VISITOR &&visitor, std::size_t which, VARIANT &&...u) { - if constexpr (LOW == HIGH) { + if constexpr (LOW + 7 >= HIGH) { + switch (which - LOW) { +#define VISIT_CASE_N(N) \ + case N: \ + if constexpr (LOW + N <= HIGH) { \ + return visitor(std::get<(LOW + N)>(std::forward<VARIANT>(u))...); \ + } + VISIT_CASE_N(1) + VISIT_CASE_N(2) + VISIT_CASE_N(3) + VISIT_CASE_N(4) + VISIT_CASE_N(5) + VISIT_CASE_N(6) + VISIT_CASE_N(7) +#undef VISIT_CASE_N + } return visitor(std::get<LOW>(std::forward<VARIANT>(u))...); } else { static constexpr std::size_t mid{(HIGH + LOW) / 2}; @@ -67,7 +62,7 @@ inline RESULT Log2VisitHelper( } template <typename VISITOR, typename... VARIANT> -inline auto visit(VISITOR &&visitor, VARIANT &&...u) +inline RT_API_ATTRS auto visit(VISITOR &&visitor, VARIANT &&...u) -> decltype(visitor(std::get<0>(std::forward<VARIANT>(u))...)) { using Result = decltype(visitor(std::get<0>(std::forward<VARIANT>(u))...)); if constexpr (sizeof...(u) == 1) { diff --git a/flang/include/flang/Decimal/binary-floating-point.h b/flang/include/flang/Decimal/binary-floating-point.h index d1992819f85aa610b9aa671bed1f905ca1f441fb..4919c1f9d240f4cfbc2a41f084f0e579912509c8 100644 --- a/flang/include/flang/Decimal/binary-floating-point.h +++ b/flang/include/flang/Decimal/binary-floating-point.h @@ -12,6 +12,7 @@ // Access and manipulate the fields of an IEEE-754 binary // floating-point value via a generalized template. +#include "flang/Common/api-attrs.h" #include "flang/Common/real.h" #include "flang/Common/uint128.h" #include <cinttypes> @@ -47,9 +48,11 @@ public: using RawType = common::HostUnsignedIntType<bits>; static_assert(CHAR_BIT * sizeof(RawType) >= bits); + RT_OFFLOAD_VAR_GROUP_BEGIN static constexpr RawType significandMask{(RawType{1} << significandBits) - 1}; - constexpr BinaryFloatingPointNumber() {} // zero + constexpr RT_API_ATTRS BinaryFloatingPointNumber() {} // zero + RT_OFFLOAD_VAR_GROUP_END constexpr BinaryFloatingPointNumber( const BinaryFloatingPointNumber &that) = default; constexpr BinaryFloatingPointNumber( @@ -58,26 +61,30 @@ public: const BinaryFloatingPointNumber &that) = default; constexpr BinaryFloatingPointNumber &operator=( BinaryFloatingPointNumber &&that) = default; - constexpr explicit BinaryFloatingPointNumber(RawType raw) : raw_{raw} {} + constexpr explicit RT_API_ATTRS BinaryFloatingPointNumber(RawType raw) + : raw_{raw} {} - RawType raw() const { return raw_; } + RT_API_ATTRS RawType raw() const { return raw_; } - template <typename A> explicit constexpr BinaryFloatingPointNumber(A x) { + template <typename A> + explicit constexpr RT_API_ATTRS BinaryFloatingPointNumber(A x) { static_assert(sizeof raw_ <= sizeof x); std::memcpy(reinterpret_cast<void *>(&raw_), reinterpret_cast<const void *>(&x), sizeof raw_); } - constexpr int BiasedExponent() const { + constexpr RT_API_ATTRS int BiasedExponent() const { return static_cast<int>( (raw_ >> significandBits) & ((1 << exponentBits) - 1)); } - constexpr int UnbiasedExponent() const { + constexpr RT_API_ATTRS int UnbiasedExponent() const { int biased{BiasedExponent()}; return biased - exponentBias + (biased == 0); } - constexpr RawType Significand() const { return raw_ & significandMask; } - constexpr RawType Fraction() const { + constexpr RT_API_ATTRS RawType Significand() const { + return raw_ & significandMask; + } + constexpr RT_API_ATTRS RawType Fraction() const { RawType sig{Significand()}; if (isImplicitMSB && BiasedExponent() > 0) { sig |= RawType{1} << significandBits; @@ -85,10 +92,10 @@ public: return sig; } - constexpr bool IsZero() const { + constexpr RT_API_ATTRS bool IsZero() const { return (raw_ & ((RawType{1} << (bits - 1)) - 1)) == 0; } - constexpr bool IsNaN() const { + constexpr RT_API_ATTRS bool IsNaN() const { auto expo{BiasedExponent()}; auto sig{Significand()}; if constexpr (bits == 80) { // x87 @@ -102,7 +109,7 @@ public: return expo == maxExponent && sig != 0; } } - constexpr bool IsInfinite() const { + constexpr RT_API_ATTRS bool IsInfinite() const { if constexpr (bits == 80) { // x87 return BiasedExponent() == maxExponent && Significand() == ((significandMask >> 1) + 1); @@ -110,27 +117,30 @@ public: return BiasedExponent() == maxExponent && Significand() == 0; } } - constexpr bool IsMaximalFiniteMagnitude() const { + constexpr RT_API_ATTRS bool IsMaximalFiniteMagnitude() const { return BiasedExponent() == maxExponent - 1 && Significand() == significandMask; } - constexpr bool IsNegative() const { return ((raw_ >> (bits - 1)) & 1) != 0; } + constexpr RT_API_ATTRS bool IsNegative() const { + return ((raw_ >> (bits - 1)) & 1) != 0; + } - constexpr void Negate() { raw_ ^= RawType{1} << (bits - 1); } + constexpr RT_API_ATTRS void Negate() { raw_ ^= RawType{1} << (bits - 1); } // For calculating the nearest neighbors of a floating-point value - constexpr void Previous() { + constexpr RT_API_ATTRS void Previous() { RemoveExplicitMSB(); --raw_; InsertExplicitMSB(); } - constexpr void Next() { + constexpr RT_API_ATTRS void Next() { RemoveExplicitMSB(); ++raw_; InsertExplicitMSB(); } - static constexpr BinaryFloatingPointNumber Infinity(bool isNegative) { + static constexpr RT_API_ATTRS BinaryFloatingPointNumber Infinity( + bool isNegative) { RawType result{RawType{maxExponent} << significandBits}; if (isNegative) { result |= RawType{1} << (bits - 1); @@ -139,7 +149,8 @@ public: } // Returns true when the result is exact - constexpr bool RoundToBits(int keepBits, enum FortranRounding mode) { + constexpr RT_API_ATTRS bool RoundToBits( + int keepBits, enum FortranRounding mode) { if (IsNaN() || IsInfinite() || keepBits >= binaryPrecision) { return true; } @@ -180,12 +191,12 @@ public: } private: - constexpr void RemoveExplicitMSB() { + constexpr RT_API_ATTRS void RemoveExplicitMSB() { if constexpr (!isImplicitMSB) { raw_ = (raw_ & (significandMask >> 1)) | ((raw_ & ~significandMask) >> 1); } } - constexpr void InsertExplicitMSB() { + constexpr RT_API_ATTRS void InsertExplicitMSB() { if constexpr (!isImplicitMSB) { constexpr RawType mask{significandMask >> 1}; raw_ = (raw_ & mask) | ((raw_ & ~mask) << 1); diff --git a/flang/include/flang/Decimal/decimal.h b/flang/include/flang/Decimal/decimal.h index f0997fb63df0185cfeaccc9bf83a76688f997d8d..443163d058e28bd03bb3d30dfb59c1d09a232659 100644 --- a/flang/include/flang/Decimal/decimal.h +++ b/flang/include/flang/Decimal/decimal.h @@ -12,6 +12,7 @@ #ifndef FORTRAN_DECIMAL_DECIMAL_H_ #define FORTRAN_DECIMAL_DECIMAL_H_ +#include "flang/Common/api-attrs.h" #include <stddef.h> #ifdef __cplusplus @@ -65,27 +66,27 @@ enum DecimalConversionFlags { #ifdef __cplusplus template <int PREC> -ConversionToDecimalResult ConvertToDecimal(char *, size_t, +RT_API_ATTRS ConversionToDecimalResult ConvertToDecimal(char *, size_t, DecimalConversionFlags, int digits, enum FortranRounding rounding, BinaryFloatingPointNumber<PREC> x); -extern template ConversionToDecimalResult ConvertToDecimal<8>(char *, size_t, - enum DecimalConversionFlags, int, enum FortranRounding, +extern template RT_API_ATTRS ConversionToDecimalResult ConvertToDecimal<8>( + char *, size_t, enum DecimalConversionFlags, int, enum FortranRounding, BinaryFloatingPointNumber<8>); -extern template ConversionToDecimalResult ConvertToDecimal<11>(char *, size_t, - enum DecimalConversionFlags, int, enum FortranRounding, +extern template RT_API_ATTRS ConversionToDecimalResult ConvertToDecimal<11>( + char *, size_t, enum DecimalConversionFlags, int, enum FortranRounding, BinaryFloatingPointNumber<11>); -extern template ConversionToDecimalResult ConvertToDecimal<24>(char *, size_t, - enum DecimalConversionFlags, int, enum FortranRounding, +extern template RT_API_ATTRS ConversionToDecimalResult ConvertToDecimal<24>( + char *, size_t, enum DecimalConversionFlags, int, enum FortranRounding, BinaryFloatingPointNumber<24>); -extern template ConversionToDecimalResult ConvertToDecimal<53>(char *, size_t, - enum DecimalConversionFlags, int, enum FortranRounding, +extern template RT_API_ATTRS ConversionToDecimalResult ConvertToDecimal<53>( + char *, size_t, enum DecimalConversionFlags, int, enum FortranRounding, BinaryFloatingPointNumber<53>); -extern template ConversionToDecimalResult ConvertToDecimal<64>(char *, size_t, - enum DecimalConversionFlags, int, enum FortranRounding, +extern template RT_API_ATTRS ConversionToDecimalResult ConvertToDecimal<64>( + char *, size_t, enum DecimalConversionFlags, int, enum FortranRounding, BinaryFloatingPointNumber<64>); -extern template ConversionToDecimalResult ConvertToDecimal<113>(char *, size_t, - enum DecimalConversionFlags, int, enum FortranRounding, +extern template RT_API_ATTRS ConversionToDecimalResult ConvertToDecimal<113>( + char *, size_t, enum DecimalConversionFlags, int, enum FortranRounding, BinaryFloatingPointNumber<113>); template <int PREC> struct ConversionToBinaryResult { @@ -94,20 +95,20 @@ template <int PREC> struct ConversionToBinaryResult { }; template <int PREC> -ConversionToBinaryResult<PREC> ConvertToBinary(const char *&, +RT_API_ATTRS ConversionToBinaryResult<PREC> ConvertToBinary(const char *&, enum FortranRounding = RoundNearest, const char *end = nullptr); -extern template ConversionToBinaryResult<8> ConvertToBinary<8>( +extern template RT_API_ATTRS ConversionToBinaryResult<8> ConvertToBinary<8>( const char *&, enum FortranRounding, const char *end); -extern template ConversionToBinaryResult<11> ConvertToBinary<11>( +extern template RT_API_ATTRS ConversionToBinaryResult<11> ConvertToBinary<11>( const char *&, enum FortranRounding, const char *end); -extern template ConversionToBinaryResult<24> ConvertToBinary<24>( +extern template RT_API_ATTRS ConversionToBinaryResult<24> ConvertToBinary<24>( const char *&, enum FortranRounding, const char *end); -extern template ConversionToBinaryResult<53> ConvertToBinary<53>( +extern template RT_API_ATTRS ConversionToBinaryResult<53> ConvertToBinary<53>( const char *&, enum FortranRounding, const char *end); -extern template ConversionToBinaryResult<64> ConvertToBinary<64>( +extern template RT_API_ATTRS ConversionToBinaryResult<64> ConvertToBinary<64>( const char *&, enum FortranRounding, const char *end); -extern template ConversionToBinaryResult<113> ConvertToBinary<113>( +extern template RT_API_ATTRS ConversionToBinaryResult<113> ConvertToBinary<113>( const char *&, enum FortranRounding, const char *end); } // namespace Fortran::decimal extern "C" { @@ -116,21 +117,21 @@ extern "C" { #define NS(x) x #endif /* C++ */ -struct NS(ConversionToDecimalResult) +RT_API_ATTRS struct NS(ConversionToDecimalResult) ConvertFloatToDecimal(char *, size_t, enum NS(DecimalConversionFlags), int digits, enum NS(FortranRounding), float); -struct NS(ConversionToDecimalResult) +RT_API_ATTRS struct NS(ConversionToDecimalResult) ConvertDoubleToDecimal(char *, size_t, enum NS(DecimalConversionFlags), int digits, enum NS(FortranRounding), double); -struct NS(ConversionToDecimalResult) +RT_API_ATTRS struct NS(ConversionToDecimalResult) ConvertLongDoubleToDecimal(char *, size_t, enum NS(DecimalConversionFlags), int digits, enum NS(FortranRounding), long double); -enum NS(ConversionResultFlags) +RT_API_ATTRS enum NS(ConversionResultFlags) ConvertDecimalToFloat(const char **, float *, enum NS(FortranRounding)); -enum NS(ConversionResultFlags) +RT_API_ATTRS enum NS(ConversionResultFlags) ConvertDecimalToDouble(const char **, double *, enum NS(FortranRounding)); -enum NS(ConversionResultFlags) ConvertDecimalToLongDouble( +RT_API_ATTRS enum NS(ConversionResultFlags) ConvertDecimalToLongDouble( const char **, long double *, enum NS(FortranRounding)); #undef NS #ifdef __cplusplus diff --git a/flang/include/flang/Evaluate/characteristics.h b/flang/include/flang/Evaluate/characteristics.h index f2f37866ecde8619362a9430143c65236507192e..82c31c0c4043011de61e445c826d6c01fb88472a 100644 --- a/flang/include/flang/Evaluate/characteristics.h +++ b/flang/include/flang/Evaluate/characteristics.h @@ -177,6 +177,14 @@ public: int corank() const { return corank_; } int Rank() const { return GetRank(shape_); } + + // Can sequence association apply to this argument? + bool CanBeSequenceAssociated() const { + constexpr Attrs notAssumedOrExplicitShape{ + ~Attrs{Attr::AssumedSize, Attr::Coarray}}; + return Rank() > 0 && (attrs() & notAssumedOrExplicitShape).none(); + } + bool IsCompatibleWith(parser::ContextualMessages &, const TypeAndShape &that, const char *thisIs = "pointer", const char *thatIs = "target", bool omitShapeConformanceCheck = false, diff --git a/flang/include/flang/Evaluate/constant.h b/flang/include/flang/Evaluate/constant.h index ee83d9fc04f3b913adfe8b40c2fffa667c93b732..71be7906d2fe2ad4100b87daac660859f91cedd7 100644 --- a/flang/include/flang/Evaluate/constant.h +++ b/flang/include/flang/Evaluate/constant.h @@ -186,6 +186,8 @@ public: const Scalar<Result> &values() const { return values_; } ConstantSubscript LEN() const { return length_; } + bool wasHollerith() const { return wasHollerith_; } + void set_wasHollerith(bool yes = true) { wasHollerith_ = yes; } std::optional<Scalar<Result>> GetScalarValue() const { if (Rank() == 0) { @@ -210,6 +212,7 @@ public: private: Scalar<Result> values_; // one contiguous string ConstantSubscript length_; + bool wasHollerith_{false}; }; class StructureConstructor; diff --git a/flang/include/flang/Evaluate/real.h b/flang/include/flang/Evaluate/real.h index d0da9634651f36254f22c28b2773893c0ac20abd..b7af0ff6b431c8cbc3aafa0e3e2e66feabae0ed4 100644 --- a/flang/include/flang/Evaluate/real.h +++ b/flang/include/flang/Evaluate/real.h @@ -221,20 +221,33 @@ public: // Normalize a fraction with just its LSB set and then multiply. // (Set the LSB, not the MSB, in case the scale factor needs to // be subnormal.) - auto adjust{exponentBias + binaryPrecision - 1}; + constexpr auto adjust{exponentBias + binaryPrecision - 1}; + constexpr auto maxCoeffExpo{maxExponent + binaryPrecision - 1}; auto expo{adjust + by.ToInt64()}; - Real twoPow; RealFlags flags; int rMask{1}; if (IsZero()) { expo = exponentBias; // ignore by, don't overflow - } else if (by > INT{maxExponent}) { - expo = maxExponent + binaryPrecision - 1; - } else if (by < INT{-adjust}) { // underflow - expo = 0; - rMask = 0; - flags.set(RealFlag::Underflow); + } else if (expo > maxCoeffExpo) { + if (Exponent() < exponentBias) { + // Must implement with two multiplications + return SCALE(INT{exponentBias}) + .value.SCALE(by.SubtractSigned(INT{exponentBias}).value, rounding); + } else { // overflow + expo = maxCoeffExpo; + } + } else if (expo < 0) { + if (Exponent() > exponentBias) { + // Must implement with two multiplications + return SCALE(INT{-exponentBias}) + .value.SCALE(by.AddSigned(INT{exponentBias}).value, rounding); + } else { // underflow to zero + expo = 0; + rMask = 0; + flags.set(RealFlag::Underflow); + } } + Real twoPow; flags |= twoPow.Normalize(false, static_cast<int>(expo), Fraction::MASKR(rMask)); ValueWithRealFlags<Real> result{Multiply(twoPow, rounding)}; diff --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h index 53896072675abca5dde9aa05473248414e9938a2..8c872a0579c8edb7d525d7cd879118042c7fc3d1 100644 --- a/flang/include/flang/Evaluate/tools.h +++ b/flang/include/flang/Evaluate/tools.h @@ -148,6 +148,14 @@ inline Expr<SomeType> AsGenericExpr(Expr<SomeType> &&x) { return std::move(x); } std::optional<Expr<SomeType>> AsGenericExpr(DataRef &&); std::optional<Expr<SomeType>> AsGenericExpr(const Symbol &); +// Propagate std::optional from input to output. +template <typename A> +std::optional<Expr<SomeType>> AsGenericExpr(std::optional<A> &&x) { + if (!x) + return std::nullopt; + return AsGenericExpr(std::move(*x)); +} + template <typename A> common::IfNoLvalue<Expr<SomeKind<ResultType<A>::category>>, A> AsCategoryExpr( A &&x) { @@ -430,6 +438,28 @@ template <typename A> std::optional<CoarrayRef> ExtractCoarrayRef(const A &x) { } } +struct ExtractSubstringHelper { + template <typename T> static std::optional<Substring> visit(T &&) { + return std::nullopt; + } + + static std::optional<Substring> visit(const Substring &e) { return e; } + + template <typename T> + static std::optional<Substring> visit(const Designator<T> &e) { + return std::visit([](auto &&s) { return visit(s); }, e.u); + } + + template <typename T> + static std::optional<Substring> visit(const Expr<T> &e) { + return std::visit([](auto &&s) { return visit(s); }, e.u); + } +}; + +template <typename A> std::optional<Substring> ExtractSubstring(const A &x) { + return ExtractSubstringHelper::visit(x); +} + // If an expression is simply a whole symbol data designator, // extract and return that symbol, else null. template <typename A> const Symbol *UnwrapWholeSymbolDataRef(const A &x) { @@ -1196,6 +1226,20 @@ bool CheckForCoindexedObject(parser::ContextualMessages &, const std::optional<ActualArgument> &, const std::string &procName, const std::string &argName); +/// Check if any of the symbols part of the expression has a cuda data +/// attribute. +inline bool HasCUDAAttrs(const Expr<SomeType> &expr) { + for (const Symbol &sym : CollectSymbols(expr)) { + if (const auto *details = + sym.GetUltimate().detailsIf<semantics::ObjectEntityDetails>()) { + if (details->cudaDataAttr()) { + return true; + } + } + } + return false; +} + } // namespace Fortran::evaluate namespace Fortran::semantics { diff --git a/flang/include/flang/Frontend/CodeGenOptions.h b/flang/include/flang/Frontend/CodeGenOptions.h index 0c318e4023af435ce9754db21861a8095f273700..b0bbace82c049345a5b302df143e63abf4a846af 100644 --- a/flang/include/flang/Frontend/CodeGenOptions.h +++ b/flang/include/flang/Frontend/CodeGenOptions.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_BASIC_CODEGENOPTIONS_H -#define LLVM_CLANG_BASIC_CODEGENOPTIONS_H +#ifndef FORTRAN_FRONTEND_CODEGENOPTIONS_H +#define FORTRAN_FRONTEND_CODEGENOPTIONS_H #include "llvm/Frontend/Debug/Options.h" #include "llvm/Frontend/Driver/CodeGenOptions.h" @@ -141,4 +141,4 @@ public: } // end namespace Fortran::frontend -#endif +#endif // FORTRAN_FRONTEND_CODEGENOPTIONS_H diff --git a/flang/include/flang/Frontend/LangOptions.h b/flang/include/flang/Frontend/LangOptions.h index 7adf2eec9ca3dcb49e942c4f0de6f87bddecf3c7..7ab2195818863dd1f3489bbab108259124028f0b 100644 --- a/flang/include/flang/Frontend/LangOptions.h +++ b/flang/include/flang/Frontend/LangOptions.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_FLANG_FRONTEND_LANGOPTIONS_H -#define LLVM_FLANG_FRONTEND_LANGOPTIONS_H +#ifndef FORTRAN_FRONTEND_LANGOPTIONS_H +#define FORTRAN_FRONTEND_LANGOPTIONS_H #include <string> @@ -63,4 +63,4 @@ public: } // end namespace Fortran::frontend -#endif +#endif // FORTRAN_FRONTEND_LANGOPTIONS_H diff --git a/flang/include/flang/ISO_Fortran_binding.h b/flang/include/flang/ISO_Fortran_binding.h index 3f74a7e56f175544b671d2268c8a1cac23946dd0..757d7f2b10cba1d07ca214a691668861fc1f193d 100644 --- a/flang/include/flang/ISO_Fortran_binding.h +++ b/flang/include/flang/ISO_Fortran_binding.h @@ -127,7 +127,7 @@ namespace cfi_internal { // because a struct cannot be empty. extern "C++" template <typename T> struct FlexibleArray : T { RT_API_ATTRS T &operator[](int index) { return *(this + index); } - const RT_API_ATTRS T &operator[](int index) const { return *(this + index); } + RT_API_ATTRS const T &operator[](int index) const { return *(this + index); } RT_API_ATTRS operator T *() { return this; } RT_API_ATTRS operator const T *() const { return this; } }; diff --git a/flang/include/flang/ISO_Fortran_binding_wrapper.h b/flang/include/flang/ISO_Fortran_binding_wrapper.h index 83c974365e3439e3bea5039f9a58cb53f973507b..37289bdbabd03c5c9aa5395df7a27056f53f379a 100644 --- a/flang/include/flang/ISO_Fortran_binding_wrapper.h +++ b/flang/include/flang/ISO_Fortran_binding_wrapper.h @@ -13,7 +13,7 @@ /* A thin wrapper around flang/include/ISO_Fortran_binding.h * This header file must be included when ISO_Fortran_binding.h * definitions/declarations are needed in Flang compiler/runtime - * sources. The inclusion of Runtime/api-attrs.h below sets up + * sources. The inclusion of Common/api-attrs.h below sets up * proper values for the macros used in ISO_Fortran_binding.h * for the device offload builds. * flang/include/ISO_Fortran_binding.h is made a standalone @@ -23,7 +23,7 @@ /* clang-format off */ #include <stddef.h> -#include "Runtime/api-attrs.h" +#include "Common/api-attrs.h" #ifdef __cplusplus namespace Fortran { namespace ISO { diff --git a/flang/include/flang/Lower/AbstractConverter.h b/flang/include/flang/Lower/AbstractConverter.h index 32e7a5e2b04061575cde4fcd57c79a252b0a7d16..d5dab9040d22bd9b97db3c32461c8ea0296e451a 100644 --- a/flang/include/flang/Lower/AbstractConverter.h +++ b/flang/include/flang/Lower/AbstractConverter.h @@ -23,6 +23,10 @@ #include "mlir/IR/Operation.h" #include "llvm/ADT/ArrayRef.h" +namespace mlir { +class SymbolTable; +} + namespace fir { class KindMapping; class FirOpBuilder; @@ -305,6 +309,15 @@ public: virtual Fortran::lower::SymbolBox lookupOneLevelUpSymbol(const Fortran::semantics::Symbol &sym) = 0; + /// Return the mlir::SymbolTable associated to the ModuleOp. + /// Look-ups are faster using it than using module.lookup<>, + /// but the module op should be queried in case of failure + /// because this symbol table is not guaranteed to contain + /// all the symbols from the ModuleOp (the symbol table should + /// always be provided to the builder helper creating globals and + /// functions in order to be in sync). + virtual mlir::SymbolTable *getMLIRSymbolTable() = 0; + private: /// Options controlling lowering behavior. const Fortran::lower::LoweringOptions &loweringOptions; diff --git a/flang/include/flang/Lower/CallInterface.h b/flang/include/flang/Lower/CallInterface.h index e77ac4e179ba861a8a2a63902871e9b29bc0b7b7..80b0576425377837c2e4aabe1c478ff220cb020c 100644 --- a/flang/include/flang/Lower/CallInterface.h +++ b/flang/include/flang/Lower/CallInterface.h @@ -174,6 +174,12 @@ public: /// May the dummy argument require INTENT(OUT) finalization /// on entry to the invoked procedure? Provides conservative answer. bool mayRequireIntentoutFinalization() const; + /// Is the dummy argument an explicit-shape or assumed-size array that + /// must be passed by descriptor? Sequence association imply the actual + /// argument shape/rank may differ with the dummy shape/rank (see F'2023 + /// section 15.5.2.12), so care is needed when creating the descriptor + /// for the dummy argument. + bool isSequenceAssociatedDescriptor() const; /// How entity is passed by. PassEntityBy passBy; /// What is the entity (SymbolRef for callee/ActualArgument* for caller) @@ -273,8 +279,6 @@ public: actualInputs.resize(getNumFIRArguments()); } - using ExprVisitor = std::function<void(evaluate::Expr<evaluate::SomeType>)>; - /// CRTP callbacks bool hasAlternateReturns() const; std::string getMangledName() const; @@ -312,12 +316,21 @@ public: /// procedure. const Fortran::semantics::Symbol *getProcedureSymbol() const; + /// Return the dummy argument symbol if this is a call to a user + /// defined procedure with explicit interface. Returns nullptr if there + /// is no user defined explicit interface. + const Fortran::semantics::Symbol * + getDummySymbol(const PassedEntity &entity) const; + /// Helpers to place the lowered arguments at the right place once they /// have been lowered. void placeInput(const PassedEntity &passedEntity, mlir::Value arg); void placeAddressAndLengthInput(const PassedEntity &passedEntity, mlir::Value addr, mlir::Value len); + /// Get lowered FIR argument given the Fortran argument. + mlir::Value getInput(const PassedEntity &passedEntity); + /// If this is a call to a procedure pointer or dummy, returns the related /// procedure designator. Nullptr otherwise. const Fortran::evaluate::ProcedureDesignator *getIfIndirectCall() const; @@ -333,13 +346,27 @@ public: /// the result specification expressions (extents and lengths) ? If needed, /// this mapping must be done after argument lowering, and before the call /// itself. - bool mustMapInterfaceSymbols() const; + bool mustMapInterfaceSymbolsForResult() const; + /// Must the caller map function interface symbols in order to evaluate + /// the specification expressions of a given dummy argument? + bool mustMapInterfaceSymbolsForDummyArgument(const PassedEntity &) const; + + /// Visitor for specification expression. Boolean indicate the specification + /// expression is for the last extent of an assumed size array. + using ExprVisitor = + std::function<void(evaluate::Expr<evaluate::SomeType>, bool)>; /// Walk the result non-deferred extent specification expressions. - void walkResultExtents(ExprVisitor) const; + void walkResultExtents(const ExprVisitor &) const; /// Walk the result non-deferred length specification expressions. - void walkResultLengths(ExprVisitor) const; + void walkResultLengths(const ExprVisitor &) const; + /// Walk non-deferred extent specification expressions of a dummy argument. + void walkDummyArgumentExtents(const PassedEntity &, + const ExprVisitor &) const; + /// Walk non-deferred length specification expressions of a dummy argument. + void walkDummyArgumentLengths(const PassedEntity &, + const ExprVisitor &) const; /// Get the mlir::Value that is passed as argument \p sym of the function /// being called. The arguments must have been placed before calling this @@ -355,6 +382,9 @@ public: /// returns the storage type. mlir::Type getResultStorageType() const; + /// Return FIR type of argument. + mlir::Type getDummyArgumentType(const PassedEntity &) const; + // Copy of base implementation. static constexpr bool hasHostAssociated() { return false; } mlir::Type getHostAssociatedTy() const { diff --git a/flang/include/flang/Lower/ConvertVariable.h b/flang/include/flang/Lower/ConvertVariable.h index b13bb412f0f3e7cea8877edcb33f267fe9d99bad..d70d3268acac13dcfa3d48c8fc1dc6954368c26a 100644 --- a/flang/include/flang/Lower/ConvertVariable.h +++ b/flang/include/flang/Lower/ConvertVariable.h @@ -93,9 +93,16 @@ void mapSymbolAttributes(AbstractConverter &, const semantics::SymbolRef &, /// Instantiate the variables that appear in the specification expressions /// of the result of a function call. The instantiated variables are added /// to \p symMap. -void mapCallInterfaceSymbols(AbstractConverter &, - const Fortran::lower::CallerInterface &caller, - SymMap &symMap); +void mapCallInterfaceSymbolsForResult( + AbstractConverter &, const Fortran::lower::CallerInterface &caller, + SymMap &symMap); + +/// Instantiate the variables that appear in the specification expressions +/// of a dummy argument of a procedure call. The instantiated variables are +/// added to \p symMap. +void mapCallInterfaceSymbolsForDummyArgument( + AbstractConverter &, const Fortran::lower::CallerInterface &caller, + SymMap &symMap, const Fortran::semantics::Symbol &dummySymbol); // TODO: consider saving the initial expression symbol dependence analysis in // in the PFT variable and dealing with the dependent symbols instantiation in @@ -154,9 +161,9 @@ void genDeclareSymbol(Fortran::lower::AbstractConverter &converter, fir::FortranVariableFlagsEnum::None, bool force = false); -/// For the given Cray pointee symbol return the corresponding -/// Cray pointer symbol. Assert if the pointer symbol cannot be found. -Fortran::semantics::SymbolRef getCrayPointer(Fortran::semantics::SymbolRef sym); +/// Given the Fortran type of a Cray pointee, return the fir.box type used to +/// track the cray pointee as Fortran pointer. +mlir::Type getCrayPointeeBoxType(mlir::Type); } // namespace lower } // namespace Fortran diff --git a/flang/include/flang/Lower/LoweringOptions.def b/flang/include/flang/Lower/LoweringOptions.def index 9de69ac5c80f52eb0e352918b35e22d47462be6a..be080a4d29d73d49cd81d320d5e01850e2f40f3b 100644 --- a/flang/include/flang/Lower/LoweringOptions.def +++ b/flang/include/flang/Lower/LoweringOptions.def @@ -24,9 +24,6 @@ LOWERINGOPT(Name, Bits, Default) /// If true, lower transpose without a runtime call. ENUM_LOWERINGOPT(OptimizeTranspose, unsigned, 1, 1) -/// If true, enable polymorphic type lowering feature. On by default. -ENUM_LOWERINGOPT(PolymorphicTypeImpl, unsigned, 1, 1) - /// If true, lower to High level FIR before lowering to FIR. On by default. ENUM_LOWERINGOPT(LowerToHighLevelFIR, unsigned, 1, 1) diff --git a/flang/include/flang/Lower/OpenMP.h b/flang/include/flang/Lower/OpenMP.h index 3b22a652d1fc1e6a6ef656f6813732faa65879f3..6e150ef4e8e82fbdc9e5eeb7f57750ff696c5507 100644 --- a/flang/include/flang/Lower/OpenMP.h +++ b/flang/include/flang/Lower/OpenMP.h @@ -19,7 +19,6 @@ #include <utility> namespace mlir { -class Value; class Operation; class Location; namespace omp { @@ -30,7 +29,6 @@ enum class DeclareTargetCaptureClause : uint32_t; namespace fir { class FirOpBuilder; -class ConvertOp; } // namespace fir namespace Fortran { @@ -84,16 +82,6 @@ void genOpenMPSymbolProperties(AbstractConverter &converter, int64_t getCollapseValue(const Fortran::parser::OmpClauseList &clauseList); void genThreadprivateOp(AbstractConverter &, const pft::Variable &); void genDeclareTargetIntGlobal(AbstractConverter &, const pft::Variable &); -void genOpenMPReduction(AbstractConverter &, - Fortran::semantics::SemanticsContext &, - const Fortran::parser::OmpClauseList &clauseList); - -mlir::Operation *findReductionChain(mlir::Value, mlir::Value * = nullptr); -fir::ConvertOp getConvertFromReductionOp(mlir::Operation *, mlir::Value); -void updateReduction(mlir::Operation *, fir::FirOpBuilder &, mlir::Value, - mlir::Value, fir::ConvertOp * = nullptr); -void removeStoreOp(mlir::Operation *, mlir::Value); - bool isOpenMPTargetConstruct(const parser::OpenMPConstruct &); bool isOpenMPDeviceDeclareTarget(Fortran::lower::AbstractConverter &, Fortran::semantics::SemanticsContext &, diff --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h index d61bf681be61941f63553bd25581954ae483d349..940866b25d2fe8f45c5fd43d2d5ff45264cc9881 100644 --- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h +++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h @@ -28,6 +28,10 @@ #include <optional> #include <utility> +namespace mlir { +class SymbolTable; +} + namespace fir { class AbstractArrayBox; class ExtendedValue; @@ -42,8 +46,10 @@ class BoxValue; /// patterns. class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener { public: - explicit FirOpBuilder(mlir::Operation *op, fir::KindMapping kindMap) - : OpBuilder{op, /*listener=*/this}, kindMap{std::move(kindMap)} {} + explicit FirOpBuilder(mlir::Operation *op, fir::KindMapping kindMap, + mlir::SymbolTable *symbolTable = nullptr) + : OpBuilder{op, /*listener=*/this}, kindMap{std::move(kindMap)}, + symbolTable{symbolTable} {} explicit FirOpBuilder(mlir::OpBuilder &builder, fir::KindMapping kindMap) : OpBuilder(builder), OpBuilder::Listener(), kindMap{std::move(kindMap)} { setListener(this); @@ -69,13 +75,14 @@ public: // The listener self-reference has to be updated in case of copy-construction. FirOpBuilder(const FirOpBuilder &other) : OpBuilder(other), OpBuilder::Listener(), kindMap{other.kindMap}, - fastMathFlags{other.fastMathFlags} { + fastMathFlags{other.fastMathFlags}, symbolTable{other.symbolTable} { setListener(this); } FirOpBuilder(FirOpBuilder &&other) : OpBuilder(other), OpBuilder::Listener(), - kindMap{std::move(other.kindMap)}, fastMathFlags{other.fastMathFlags} { + kindMap{std::move(other.kindMap)}, fastMathFlags{other.fastMathFlags}, + symbolTable{other.symbolTable} { setListener(this); } @@ -95,6 +102,9 @@ public: /// Get a reference to the kind map. const fir::KindMapping &getKindMap() { return kindMap; } + /// Get func.func/fir.global symbol table attached to this builder if any. + mlir::SymbolTable *getMLIRSymbolTable() { return symbolTable; } + /// Get the default integer type [[maybe_unused]] mlir::IntegerType getDefaultIntegerType() { return getIntegerType( @@ -280,24 +290,27 @@ public: /// Get a function by name. If the function exists in the current module, it /// is returned. Otherwise, a null FuncOp is returned. mlir::func::FuncOp getNamedFunction(llvm::StringRef name) { - return getNamedFunction(getModule(), name); + return getNamedFunction(getModule(), getMLIRSymbolTable(), name); } - static mlir::func::FuncOp getNamedFunction(mlir::ModuleOp module, - llvm::StringRef name); + static mlir::func::FuncOp + getNamedFunction(mlir::ModuleOp module, const mlir::SymbolTable *symbolTable, + llvm::StringRef name); /// Get a function by symbol name. The result will be null if there is no /// function with the given symbol in the module. mlir::func::FuncOp getNamedFunction(mlir::SymbolRefAttr symbol) { - return getNamedFunction(getModule(), symbol); + return getNamedFunction(getModule(), getMLIRSymbolTable(), symbol); } - static mlir::func::FuncOp getNamedFunction(mlir::ModuleOp module, - mlir::SymbolRefAttr symbol); + static mlir::func::FuncOp + getNamedFunction(mlir::ModuleOp module, const mlir::SymbolTable *symbolTable, + mlir::SymbolRefAttr symbol); fir::GlobalOp getNamedGlobal(llvm::StringRef name) { - return getNamedGlobal(getModule(), name); + return getNamedGlobal(getModule(), getMLIRSymbolTable(), name); } static fir::GlobalOp getNamedGlobal(mlir::ModuleOp module, + const mlir::SymbolTable *symbolTable, llvm::StringRef name); /// Lazy creation of fir.convert op. @@ -313,35 +326,18 @@ public: /// result of the load if it was created, otherwise return \p val mlir::Value loadIfRef(mlir::Location loc, mlir::Value val); - /// Create a new FuncOp. If the function may have already been created, use - /// `addNamedFunction` instead. + /// Determine if the named function is already in the module. Return the + /// instance if found, otherwise add a new named function to the module. mlir::func::FuncOp createFunction(mlir::Location loc, llvm::StringRef name, mlir::FunctionType ty) { - return createFunction(loc, getModule(), name, ty); + return createFunction(loc, getModule(), name, ty, getMLIRSymbolTable()); } static mlir::func::FuncOp createFunction(mlir::Location loc, mlir::ModuleOp module, llvm::StringRef name, - mlir::FunctionType ty); - - /// Determine if the named function is already in the module. Return the - /// instance if found, otherwise add a new named function to the module. - mlir::func::FuncOp addNamedFunction(mlir::Location loc, llvm::StringRef name, - mlir::FunctionType ty) { - if (auto func = getNamedFunction(name)) - return func; - return createFunction(loc, name, ty); - } - - static mlir::func::FuncOp addNamedFunction(mlir::Location loc, - mlir::ModuleOp module, - llvm::StringRef name, - mlir::FunctionType ty) { - if (auto func = getNamedFunction(module, name)) - return func; - return createFunction(loc, module, name, ty); - } + mlir::FunctionType ty, + mlir::SymbolTable *); /// Cast the input value to IndexType. mlir::Value convertToIndexType(mlir::Location loc, mlir::Value val) { @@ -515,6 +511,10 @@ private: /// FastMathFlags that need to be set for operations that support /// mlir::arith::FastMathAttr. mlir::arith::FastMathFlags fastMathFlags{}; + + /// fir::GlobalOp and func::FuncOp symbol table to speed-up + /// lookups. + mlir::SymbolTable *symbolTable = nullptr; }; } // namespace fir diff --git a/flang/include/flang/Optimizer/Builder/HLFIRTools.h b/flang/include/flang/Optimizer/Builder/HLFIRTools.h index ce87941d5382caf50a01d86bb9d521113c2a8e22..035035601e2f25d3e45b3076c3bafca550b4d4e0 100644 --- a/flang/include/flang/Optimizer/Builder/HLFIRTools.h +++ b/flang/include/flang/Optimizer/Builder/HLFIRTools.h @@ -434,6 +434,11 @@ std::pair<hlfir::Entity, mlir::Value> createTempFromMold(mlir::Location loc, fir::FirOpBuilder &builder, hlfir::Entity mold); +// TODO: this does not support polymorphic molds +hlfir::Entity createStackTempFromMold(mlir::Location loc, + fir::FirOpBuilder &builder, + hlfir::Entity mold); + hlfir::EntityWithAttributes convertCharacterKind(mlir::Location loc, fir::FirOpBuilder &builder, hlfir::Entity scalarChar, diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h index ca15b4bc34b29eecc6d8b4bfdeb9d300163fb050..6927488517e63b8775354ad117dd9982e0856219 100644 --- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h +++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h @@ -208,6 +208,9 @@ struct IntrinsicLibrary { void genCFProcPointer(llvm::ArrayRef<fir::ExtendedValue>); fir::ExtendedValue genCFunLoc(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); fir::ExtendedValue genCLoc(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>); + template <mlir::arith::CmpIPredicate pred> + fir::ExtendedValue genCPtrCompare(mlir::Type, + llvm::ArrayRef<fir::ExtendedValue>); mlir::Value genCosd(mlir::Type, llvm::ArrayRef<mlir::Value>); void genDateAndTime(llvm::ArrayRef<fir::ExtendedValue>); mlir::Value genDim(mlir::Type, llvm::ArrayRef<mlir::Value>); diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Numeric.h b/flang/include/flang/Optimizer/Builder/Runtime/Numeric.h index c1a72478e224c77bd17c9e6760b3391c2fcf7f64..fec8c9906effed70aa66d4f9654b42b664727fbf 100644 --- a/flang/include/flang/Optimizer/Builder/Runtime/Numeric.h +++ b/flang/include/flang/Optimizer/Builder/Runtime/Numeric.h @@ -30,6 +30,10 @@ mlir::Value genFraction(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value genMod(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value a, mlir::Value p); +/// Generate call to Modulo intrinsic runtime routine. +mlir::Value genModulo(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value a, mlir::Value p); + /// Generate call to Nearest intrinsic runtime routine. mlir::Value genNearest(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value x, mlir::Value s); diff --git a/flang/include/flang/Optimizer/CodeGen/CodeGen.h b/flang/include/flang/Optimizer/CodeGen/CodeGen.h index cbf02ec3912363e4de33bdb1774638374d532b9d..26097dabf56c451801ac9c7272e54f669161372d 100644 --- a/flang/include/flang/Optimizer/CodeGen/CodeGen.h +++ b/flang/include/flang/Optimizer/CodeGen/CodeGen.h @@ -87,6 +87,9 @@ void populateFIRToLLVMConversionPatterns(fir::LLVMTypeConverter &converter, mlir::RewritePatternSet &patterns, fir::FIRToLLVMPassOptions &options); +/// Populate the pattern set with the PreCGRewrite patterns. +void populatePreCGRewritePatterns(mlir::RewritePatternSet &patterns); + // declarative passes #define GEN_PASS_REGISTRATION #include "flang/Optimizer/CodeGen/CGPasses.h.inc" diff --git a/flang/include/flang/Optimizer/CodeGen/FIROpPatterns.h b/flang/include/flang/Optimizer/CodeGen/FIROpPatterns.h new file mode 100644 index 0000000000000000000000000000000000000000..06a44f1885656f5c8800f59c0228352f5e2136b7 --- /dev/null +++ b/flang/include/flang/Optimizer/CodeGen/FIROpPatterns.h @@ -0,0 +1,248 @@ +//===-- FIROpPatterns.h -- FIR operation conversion patterns ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef FORTRAN_OPTIMIZER_CODEGEN_FIROPPATTERNS_H +#define FORTRAN_OPTIMIZER_CODEGEN_FIROPPATTERNS_H + +#include "flang/Optimizer/CodeGen/TypeConverter.h" +#include "mlir/Conversion/LLVMCommon/Pattern.h" +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" + +namespace fir { + +struct FIRToLLVMPassOptions; + +static constexpr unsigned defaultAddressSpace = 0u; + +class ConvertFIRToLLVMPattern : public mlir::ConvertToLLVMPattern { +public: + ConvertFIRToLLVMPattern(llvm::StringRef rootOpName, + mlir::MLIRContext *context, + const fir::LLVMTypeConverter &typeConverter, + const fir::FIRToLLVMPassOptions &options, + mlir::PatternBenefit benefit = 1); + +protected: + mlir::Type convertType(mlir::Type ty) const { + return lowerTy().convertType(ty); + } + + // Convert FIR type to LLVM without turning fir.box<T> into memory + // reference. + mlir::Type convertObjectType(mlir::Type firType) const; + + mlir::LLVM::ConstantOp + genI32Constant(mlir::Location loc, mlir::ConversionPatternRewriter &rewriter, + int value) const; + + mlir::LLVM::ConstantOp + genConstantOffset(mlir::Location loc, + mlir::ConversionPatternRewriter &rewriter, + int offset) const; + + /// Perform an extension or truncation as needed on an integer value. Lowering + /// to the specific target may involve some sign-extending or truncation of + /// values, particularly to fit them from abstract box types to the + /// appropriate reified structures. + mlir::Value integerCast(mlir::Location loc, + mlir::ConversionPatternRewriter &rewriter, + mlir::Type ty, mlir::Value val) const; + struct TypePair { + mlir::Type fir; + mlir::Type llvm; + }; + + TypePair getBoxTypePair(mlir::Type firBoxTy) const; + + /// Construct code sequence to extract the specific value from a `fir.box`. + mlir::Value getValueFromBox(mlir::Location loc, TypePair boxTy, + mlir::Value box, mlir::Type resultTy, + mlir::ConversionPatternRewriter &rewriter, + int boxValue) const; + + /// Method to construct code sequence to get the triple for dimension `dim` + /// from a box. + llvm::SmallVector<mlir::Value, 3> + getDimsFromBox(mlir::Location loc, llvm::ArrayRef<mlir::Type> retTys, + TypePair boxTy, mlir::Value box, mlir::Value dim, + mlir::ConversionPatternRewriter &rewriter) const; + + llvm::SmallVector<mlir::Value, 3> + getDimsFromBox(mlir::Location loc, llvm::ArrayRef<mlir::Type> retTys, + TypePair boxTy, mlir::Value box, int dim, + mlir::ConversionPatternRewriter &rewriter) const; + + mlir::Value + loadDimFieldFromBox(mlir::Location loc, TypePair boxTy, mlir::Value box, + mlir::Value dim, int off, mlir::Type ty, + mlir::ConversionPatternRewriter &rewriter) const; + + mlir::Value + getDimFieldFromBox(mlir::Location loc, TypePair boxTy, mlir::Value box, + int dim, int off, mlir::Type ty, + mlir::ConversionPatternRewriter &rewriter) const; + + mlir::Value getStrideFromBox(mlir::Location loc, TypePair boxTy, + mlir::Value box, unsigned dim, + mlir::ConversionPatternRewriter &rewriter) const; + + /// Read base address from a fir.box. Returned address has type ty. + mlir::Value + getBaseAddrFromBox(mlir::Location loc, TypePair boxTy, mlir::Value box, + mlir::ConversionPatternRewriter &rewriter) const; + + mlir::Value + getElementSizeFromBox(mlir::Location loc, mlir::Type resultTy, TypePair boxTy, + mlir::Value box, + mlir::ConversionPatternRewriter &rewriter) const; + + // Get the element type given an LLVM type that is of the form + // (array|struct|vector)+ and the provided indexes. + mlir::Type getBoxEleTy(mlir::Type type, + llvm::ArrayRef<std::int64_t> indexes) const; + + // Return LLVM type of the object described by a fir.box of \p boxType. + mlir::Type getLlvmObjectTypeFromBoxType(mlir::Type boxType) const; + + /// Read the address of the type descriptor from a box. + mlir::Value + loadTypeDescAddress(mlir::Location loc, TypePair boxTy, mlir::Value box, + mlir::ConversionPatternRewriter &rewriter) const; + + // Load the attribute from the \p box and perform a check against \p maskValue + // The final comparison is implemented as `(attribute & maskValue) != 0`. + mlir::Value genBoxAttributeCheck(mlir::Location loc, TypePair boxTy, + mlir::Value box, + mlir::ConversionPatternRewriter &rewriter, + unsigned maskValue) const; + + template <typename... ARGS> + mlir::LLVM::GEPOp genGEP(mlir::Location loc, mlir::Type ty, + mlir::ConversionPatternRewriter &rewriter, + mlir::Value base, ARGS... args) const { + llvm::SmallVector<mlir::LLVM::GEPArg> cv = {args...}; + auto llvmPtrTy = + mlir::LLVM::LLVMPointerType::get(ty.getContext(), /*addressSpace=*/0); + return rewriter.create<mlir::LLVM::GEPOp>(loc, llvmPtrTy, ty, base, cv); + } + + // Find the Block in which the alloca should be inserted. + // The order to recursively find the proper block: + // 1. An OpenMP Op that will be outlined. + // 2. A LLVMFuncOp + // 3. The first ancestor that is an OpenMP Op or a LLVMFuncOp + mlir::Block *getBlockForAllocaInsert(mlir::Operation *op) const; + + // Generate an alloca of size 1 for an object of type \p llvmObjectTy in the + // allocation address space provided for the architecture in the DataLayout + // specification. If the address space is different from the devices + // program address space we perform a cast. In the case of most architectures + // the program and allocation address space will be the default of 0 and no + // cast will be emitted. + mlir::Value + genAllocaAndAddrCastWithType(mlir::Location loc, mlir::Type llvmObjectTy, + unsigned alignment, + mlir::ConversionPatternRewriter &rewriter) const; + + const fir::LLVMTypeConverter &lowerTy() const { + return *static_cast<const fir::LLVMTypeConverter *>( + this->getTypeConverter()); + } + + void attachTBAATag(mlir::LLVM::AliasAnalysisOpInterface op, + mlir::Type baseFIRType, mlir::Type accessFIRType, + mlir::LLVM::GEPOp gep) const { + lowerTy().attachTBAATag(op, baseFIRType, accessFIRType, gep); + } + + unsigned + getAllocaAddressSpace(mlir::ConversionPatternRewriter &rewriter) const; + + unsigned + getProgramAddressSpace(mlir::ConversionPatternRewriter &rewriter) const; + + const fir::FIRToLLVMPassOptions &options; + + using ConvertToLLVMPattern::match; + using ConvertToLLVMPattern::matchAndRewrite; +}; + +template <typename SourceOp> +class FIROpConversion : public ConvertFIRToLLVMPattern { +public: + using OpAdaptor = typename SourceOp::Adaptor; + + explicit FIROpConversion(const LLVMTypeConverter &typeConverter, + const fir::FIRToLLVMPassOptions &options, + mlir::PatternBenefit benefit = 1) + : ConvertFIRToLLVMPattern(SourceOp::getOperationName(), + &typeConverter.getContext(), typeConverter, + options, benefit) {} + + /// Wrappers around the RewritePattern methods that pass the derived op type. + void rewrite(mlir::Operation *op, mlir::ArrayRef<mlir::Value> operands, + mlir::ConversionPatternRewriter &rewriter) const final { + rewrite(mlir::cast<SourceOp>(op), + OpAdaptor(operands, mlir::cast<SourceOp>(op)), rewriter); + } + mlir::LogicalResult match(mlir::Operation *op) const final { + return match(mlir::cast<SourceOp>(op)); + } + mlir::LogicalResult + matchAndRewrite(mlir::Operation *op, mlir::ArrayRef<mlir::Value> operands, + mlir::ConversionPatternRewriter &rewriter) const final { + return matchAndRewrite(mlir::cast<SourceOp>(op), + OpAdaptor(operands, mlir::cast<SourceOp>(op)), + rewriter); + } + + /// Rewrite and Match methods that operate on the SourceOp type. These must be + /// overridden by the derived pattern class. + virtual mlir::LogicalResult match(SourceOp op) const { + llvm_unreachable("must override match or matchAndRewrite"); + } + virtual void rewrite(SourceOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + llvm_unreachable("must override rewrite or matchAndRewrite"); + } + virtual mlir::LogicalResult + matchAndRewrite(SourceOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + if (mlir::failed(match(op))) + return mlir::failure(); + rewrite(op, adaptor, rewriter); + return mlir::success(); + } + +private: + using ConvertFIRToLLVMPattern::matchAndRewrite; + using ConvertToLLVMPattern::match; +}; + +/// FIR conversion pattern template +template <typename FromOp> +class FIROpAndTypeConversion : public FIROpConversion<FromOp> { +public: + using FIROpConversion<FromOp>::FIROpConversion; + using OpAdaptor = typename FromOp::Adaptor; + + mlir::LogicalResult + matchAndRewrite(FromOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const final { + mlir::Type ty = this->convertType(op.getType()); + return doRewrite(op, ty, adaptor, rewriter); + } + + virtual mlir::LogicalResult + doRewrite(FromOp addr, mlir::Type ty, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const = 0; +}; + +} // namespace fir + +#endif // FORTRAN_OPTIMIZER_CODEGEN_FIROPPATTERNS_H diff --git a/flang/include/flang/Optimizer/CodeGen/TypeConverter.h b/flang/include/flang/Optimizer/CodeGen/TypeConverter.h index 396c13639255546f9916b5bcdf82f9fd7eabd948..79b3bfe4e80e09cc78facac22a021c6af7dbe1fd 100644 --- a/flang/include/flang/Optimizer/CodeGen/TypeConverter.h +++ b/flang/include/flang/Optimizer/CodeGen/TypeConverter.h @@ -94,8 +94,8 @@ public: // to LLVM IR dialect here. // // fir.complex<T> | std.complex<T> --> llvm<"{t,t}"> - template <typename C> mlir::Type convertComplexType(C cmplx) const { - LLVM_DEBUG(llvm::dbgs() << "type convert: " << cmplx << '\n'); + template <typename C> + mlir::Type convertComplexType(C cmplx) const { auto eleTy = cmplx.getElementType(); return convertType(specifics->complexMemoryType(eleTy)); } diff --git a/flang/include/flang/Optimizer/Dialect/FIRAttr.td b/flang/include/flang/Optimizer/Dialect/FIRAttr.td index 2ac4af9e66aa80891eb5796fa85a73e5f41bc057..f8b3fb861cc62f51804eefa96e56f8ea75ebb24f 100644 --- a/flang/include/flang/Optimizer/Dialect/FIRAttr.td +++ b/flang/include/flang/Optimizer/Dialect/FIRAttr.td @@ -137,4 +137,20 @@ def fir_CUDAClusterDimsAttr : fir_Attr<"CUDAClusterDims"> { let assemblyFormat = "`<` struct(params) `>`"; } +def fir_CUDADataTransferKind : I32EnumAttr< + "CUDADataTransferKind", "CUDA Fortran data transfer kind", + [ + I32EnumAttrCase<"DeviceHost", 0, "device_host">, + I32EnumAttrCase<"HostDevice", 1, "host_device">, + I32EnumAttrCase<"DeviceDevice", 2, "device_device">, + ]> { + let genSpecializedAttr = 0; + let cppNamespace = "::fir"; +} + +def fir_CUDADataTransferKindAttr : + EnumAttr<FIROpsDialect, fir_CUDADataTransferKind, "cuda_transfer"> { + let assemblyFormat = [{ ```<` $value `>` }]; +} + #endif // FIR_DIALECT_FIR_ATTRS diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td index 65a86d25333b5ddd0c5206edbdecfbfa61f1bb91..dff1cdb20cbfefcf451e9c782ccec1bd62172326 100644 --- a/flang/include/flang/Optimizer/Dialect/FIROps.td +++ b/flang/include/flang/Optimizer/Dialect/FIROps.td @@ -2454,6 +2454,7 @@ def fir_CUDAKernelLaunch : fir_Op<"cuda_kernel_launch", [CallOpInterface, SymbolRefAttr:$callee, I32:$grid_x, I32:$grid_y, + I32:$grid_z, I32:$block_x, I32:$block_y, I32:$block_z, @@ -2463,9 +2464,9 @@ def fir_CUDAKernelLaunch : fir_Op<"cuda_kernel_launch", [CallOpInterface, ); let assemblyFormat = [{ - $callee `<` `<` `<` $grid_x `,` $grid_y `,` $block_x `,` $block_y `,` - $block_z ( `,` $bytes^ ( `,` $stream^ )? )? `>` `>` `>` - `` `(` ( $args^ `:` type($args) )? `)` attr-dict + $callee `<` `<` `<` $grid_x `,` $grid_y `,` $grid_z `,`$block_x `,` + $block_y `,` $block_z ( `,` $bytes^ ( `,` $stream^ )? )? `>` `>` `>` + `` `(` $args `)` ( `:` `(` type($args)^ `)` )? attr-dict }]; let extraClassDeclaration = [{ @@ -3130,6 +3131,16 @@ def fir_BoxOffsetOp : fir_Op<"box_offset", [NoMemoryEffect]> { def fir_CUDAKernelOp : fir_Op<"cuda_kernel", [AttrSizedOperandSegments, DeclareOpInterfaceMethods<LoopLikeOpInterface>]> { + let description = [{ + Represent the CUDA Fortran kernel directive. The operation is a loop like + operation that represents the iteration range of the embedded loop nest. + + When grid or block variadic operands are empty, a `*` only syntax was used + in the Fortran code. + If the `*` is mixed with values for either grid or block, these are + represented by a 0 constant value. + }]; + let arguments = (ins Variadic<I32>:$grid, // empty means `*` Variadic<I32>:$block, // empty means `*` @@ -3154,4 +3165,29 @@ def fir_CUDAKernelOp : fir_Op<"cuda_kernel", [AttrSizedOperandSegments, let hasVerifier = 1; } +def fir_CUDADataTransferOp : fir_Op<"cuda_data_transfer", []> { + let summary = "Represent a data transfer between host and device memory"; + + let description = [{ + CUDA Fortran allows data transfer to be done via intrinsic assignment + between a host and a device variable. This operation is used to materialized + the data transfer between the lhs and rhs memory references. + The kind of transfer is specified in the attribute. + + ``` + adev = a ! transfer host to device + a = adev ! transfer device to host + bdev = adev ! transfer device to device + ``` + }]; + + let arguments = (ins Arg<AnyReferenceLike, "", [MemWrite]>:$src, + Arg<AnyReferenceLike, "", [MemRead]>:$dst, + fir_CUDADataTransferKindAttr:$transfer_kind); + + let assemblyFormat = [{ + $src `to` $dst attr-dict `:` type(operands) + }]; +} + #endif diff --git a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h index e8226b6df58ca2db5a83bee375ecb1102915619b..f29e44504acb63470ae80dd0681cbb79541efc2e 100644 --- a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h +++ b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h @@ -52,16 +52,19 @@ inline bool pureCall(mlir::Operation *op) { /// Get or create a FuncOp in a module. /// /// If `module` already contains FuncOp `name`, it is returned. Otherwise, a new -/// FuncOp is created, and that new FuncOp is returned. -mlir::func::FuncOp -createFuncOp(mlir::Location loc, mlir::ModuleOp module, llvm::StringRef name, - mlir::FunctionType type, - llvm::ArrayRef<mlir::NamedAttribute> attrs = {}); - -/// Get or create a GlobalOp in a module. +/// FuncOp is created, and that new FuncOp is returned. A symbol table can +/// be provided to speed-up the lookups. +mlir::func::FuncOp createFuncOp(mlir::Location loc, mlir::ModuleOp module, + llvm::StringRef name, mlir::FunctionType type, + llvm::ArrayRef<mlir::NamedAttribute> attrs = {}, + const mlir::SymbolTable *symbolTable = nullptr); + +/// Get or create a GlobalOp in a module. A symbol table can be provided to +/// speed-up the lookups. fir::GlobalOp createGlobalOp(mlir::Location loc, mlir::ModuleOp module, llvm::StringRef name, mlir::Type type, - llvm::ArrayRef<mlir::NamedAttribute> attrs = {}); + llvm::ArrayRef<mlir::NamedAttribute> attrs = {}, + const mlir::SymbolTable *symbolTable = nullptr); /// Attribute to mark Fortran entities with the CONTIGUOUS attribute. constexpr llvm::StringRef getContiguousAttrName() { return "fir.contiguous"; } diff --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h index a526b4ddf3b98cbf128c8813a52dc9ebd45aa2dc..7fcd9c1babf24f3eb62ba40c92da78bef56b25d3 100644 --- a/flang/include/flang/Optimizer/Dialect/FIRType.h +++ b/flang/include/flang/Optimizer/Dialect/FIRType.h @@ -237,6 +237,9 @@ inline mlir::Type unwrapSequenceType(mlir::Type t) { return t; } +/// Return the nested sequence type if any. +mlir::Type extractSequenceType(mlir::Type ty); + inline mlir::Type unwrapRefType(mlir::Type t) { if (auto eleTy = dyn_cast_ptrEleTy(t)) return eleTy; diff --git a/flang/include/flang/Optimizer/Transforms/Passes.h b/flang/include/flang/Optimizer/Transforms/Passes.h index e1d22c8c986da7222753352ced49eeac08384251..a60d39c8df08d859f3ea2725df878ed1903fa0f8 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.h +++ b/flang/include/flang/Optimizer/Transforms/Passes.h @@ -11,6 +11,7 @@ #include "flang/Optimizer/Dialect/FIROps.h" #include "mlir/Dialect/LLVMIR/LLVMAttrs.h" +#include "mlir/Dialect/OpenMP/OpenMPDialect.h" #include "mlir/Pass/Pass.h" #include "mlir/Pass/PassRegistry.h" #include <memory> @@ -37,7 +38,8 @@ namespace fir { #define GEN_PASS_DECL_ANNOTATECONSTANTOPERANDS #define GEN_PASS_DECL_ARRAYVALUECOPY #define GEN_PASS_DECL_CHARACTERCONVERSION -#define GEN_PASS_DECL_CFGCONVERSION +#define GEN_PASS_DECL_CFGCONVERSIONONFUNC +#define GEN_PASS_DECL_CFGCONVERSIONONREDUCTION #define GEN_PASS_DECL_EXTERNALNAMECONVERSION #define GEN_PASS_DECL_MEMREFDATAFLOWOPT #define GEN_PASS_DECL_SIMPLIFYINTRINSICS @@ -53,7 +55,8 @@ std::unique_ptr<mlir::Pass> createAbstractResultOnGlobalOptPass(); std::unique_ptr<mlir::Pass> createAffineDemotionPass(); std::unique_ptr<mlir::Pass> createArrayValueCopyPass(fir::ArrayValueCopyOptions options = {}); -std::unique_ptr<mlir::Pass> createFirToCfgPass(); +std::unique_ptr<mlir::Pass> createFirToCfgOnFuncPass(); +std::unique_ptr<mlir::Pass> createFirToCfgOnReductionPass(); std::unique_ptr<mlir::Pass> createCharacterConversionPass(); std::unique_ptr<mlir::Pass> createExternalNameConversionPass(); std::unique_ptr<mlir::Pass> @@ -96,6 +99,9 @@ createFunctionAttrPass(FunctionAttrTypes &functionAttr, bool noInfsFPMath, bool noNaNsFPMath, bool approxFuncFPMath, bool noSignedZerosFPMath, bool unsafeFPMath); +void populateCfgConversionRewrites(mlir::RewritePatternSet &patterns, + bool forceLoopToExecuteOnce = false); + // declarative passes #define GEN_PASS_REGISTRATION #include "flang/Optimizer/Transforms/Passes.h.inc" diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td index 5fb576fd8762545054e71a6468357944923505b4..978911c21794c78be5ad2951e2d8b7db6e3b4a8b 100644 --- a/flang/include/flang/Optimizer/Transforms/Passes.td +++ b/flang/include/flang/Optimizer/Transforms/Passes.td @@ -145,7 +145,8 @@ def CharacterConversion : Pass<"character-conversion"> { ]; } -def CFGConversion : Pass<"cfg-conversion", "::mlir::func::FuncOp"> { +class CFGConversionBase<string optExt, string operation> + : Pass<"cfg-conversion-on-" # optExt # "-opt", operation> { let summary = "Convert FIR structured control flow ops to CFG ops."; let description = [{ Transform the `fir.do_loop`, `fir.if`, `fir.iterate_while` and @@ -154,7 +155,6 @@ def CFGConversion : Pass<"cfg-conversion", "::mlir::func::FuncOp"> { This pass is required before code gen to the LLVM IR dialect. }]; - let constructor = "::fir::createFirToCfgPass()"; let dependentDialects = [ "fir::FIROpsDialect", "mlir::func::FuncDialect" ]; @@ -165,6 +165,14 @@ def CFGConversion : Pass<"cfg-conversion", "::mlir::func::FuncOp"> { ]; } +def CFGConversionOnFunc : CFGConversionBase<"func", "mlir::func::FuncOp"> { + let constructor = "::fir::createFirToCfgOnFuncPass()"; +} + +def CFGConversionOnReduction : CFGConversionBase<"reduce", "mlir::omp::DeclareReductionOp"> { + let constructor = "::fir::createFirToCfgOnReductionPass()"; +} + def ExternalNameConversion : Pass<"external-name-interop", "mlir::ModuleOp"> { let summary = "Convert name for external interoperability"; let description = [{ diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 048008a8d80c79cc52b9b5e98014cf4247187a79..06c168a5de612cd2e735a3a6a994bb120569604e 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -207,6 +207,7 @@ public: NODE(CompilerDirective, LoopCount) NODE(CompilerDirective, AssumeAligned) NODE(CompilerDirective, NameValue) + NODE(CompilerDirective, Unrecognized) NODE(parser, ComplexLiteralConstant) NODE(parser, ComplexPart) NODE(parser, ComponentArraySpec) @@ -233,6 +234,7 @@ public: NODE(parser, CriticalStmt) NODE(parser, CUDAAttributesStmt) NODE(parser, CUFKernelDoConstruct) + NODE(CUFKernelDoConstruct, StarOrExpr) NODE(CUFKernelDoConstruct, Directive) NODE(parser, CycleStmt) NODE(parser, DataComponentDefStmt) diff --git a/flang/include/flang/Parser/parse-tree-visitor.h b/flang/include/flang/Parser/parse-tree-visitor.h index 79ea29f4b7f325cbb0a80e1d09eec2b11e751b21..81d01dbdd65cc9f0bd3780e52abf85b22595d1ec 100644 --- a/flang/include/flang/Parser/parse-tree-visitor.h +++ b/flang/include/flang/Parser/parse-tree-visitor.h @@ -861,6 +861,18 @@ template <typename M> void Walk(CompilerDirective &x, M &mutator) { } } template <typename V> +void Walk(const CompilerDirective::Unrecognized &x, V &visitor) { + if (visitor.Pre(x)) { + visitor.Post(x); + } +} +template <typename M> +void Walk(CompilerDirective::Unrecognized &x, M &mutator) { + if (mutator.Pre(x)) { + mutator.Post(x); + } +} +template <typename V> void Walk(const OmpLinearClause::WithModifier &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.modifier, visitor); diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index f7b72c3af091647507defd51624aaa403584c4c4..26b2e5f4e34b0614a6a8933e88054d7555047bca 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3298,7 +3298,8 @@ struct StmtFunctionStmt { // Compiler directives // !DIR$ IGNORE_TKR [ [(tkrdmac...)] name ]... // !DIR$ LOOP COUNT (n1[, n2]...) -// !DIR$ name... +// !DIR$ name[=value] [, name[=value]]... = can be : +// !DIR$ <anything else> struct CompilerDirective { UNION_CLASS_BOILERPLATE(CompilerDirective); struct IgnoreTKR { @@ -3316,9 +3317,10 @@ struct CompilerDirective { TUPLE_CLASS_BOILERPLATE(NameValue); std::tuple<Name, std::optional<std::uint64_t>> t; }; + EMPTY_CLASS(Unrecognized); CharBlock source; std::variant<std::list<IgnoreTKR>, LoopCount, std::list<AssumeAligned>, - std::list<NameValue>> + std::list<NameValue>, Unrecognized> u; }; @@ -4297,16 +4299,18 @@ struct OpenACCConstruct { // CUF-kernel-do-construct -> // !$CUF KERNEL DO [ (scalar-int-constant-expr) ] <<< grid, block [, stream] // >>> do-construct -// grid -> * | scalar-int-expr | ( scalar-int-expr-list ) -// block -> * | scalar-int-expr | ( scalar-int-expr-list ) +// star-or-expr -> * | scalar-int-expr +// grid -> * | scalar-int-expr | ( star-or-expr-list ) +// block -> * | scalar-int-expr | ( star-or-expr-list ) // stream -> 0, scalar-int-expr | STREAM = scalar-int-expr struct CUFKernelDoConstruct { TUPLE_CLASS_BOILERPLATE(CUFKernelDoConstruct); + WRAPPER_CLASS(StarOrExpr, std::optional<ScalarIntExpr>); struct Directive { TUPLE_CLASS_BOILERPLATE(Directive); CharBlock source; - std::tuple<std::optional<ScalarIntConstantExpr>, std::list<ScalarIntExpr>, - std::list<ScalarIntExpr>, std::optional<ScalarIntExpr>> + std::tuple<std::optional<ScalarIntConstantExpr>, std::list<StarOrExpr>, + std::list<StarOrExpr>, std::optional<ScalarIntExpr>> t; }; std::tuple<Directive, std::optional<DoConstruct>> t; diff --git a/flang/include/flang/Parser/tools.h b/flang/include/flang/Parser/tools.h index 1e347fab6461a33a52b46e200299a9dbc70e9beb..f1ead11734fa0d40d27af09fc949fe5af26aa1e4 100644 --- a/flang/include/flang/Parser/tools.h +++ b/flang/include/flang/Parser/tools.h @@ -40,6 +40,7 @@ const Name &GetFirstName(const ProcedureDesignator &); const Name &GetFirstName(const Call &); const Name &GetFirstName(const FunctionReference &); const Name &GetFirstName(const Variable &); +const Name &GetFirstName(const EntityDecl &); // When a parse tree node is an instance of a specific type wrapped in // layers of packaging, return a pointer to that object. diff --git a/flang/include/flang/Runtime/descriptor.h b/flang/include/flang/Runtime/descriptor.h index 7ad548d6c72b442a037cd3e8d7fe04f2d00ebb90..96d56d9b43a62ba982e2c0883598541130c14fd4 100644 --- a/flang/include/flang/Runtime/descriptor.h +++ b/flang/include/flang/Runtime/descriptor.h @@ -102,7 +102,7 @@ public: : derivedType_{dt}, len_{0} {} RT_API_ATTRS DescriptorAddendum &operator=(const DescriptorAddendum &); - const RT_API_ATTRS typeInfo::DerivedType *derivedType() const { + RT_API_ATTRS const typeInfo::DerivedType *derivedType() const { return derivedType_; } RT_API_ATTRS DescriptorAddendum &set_derivedType( @@ -204,7 +204,7 @@ public: ISO::CFI_attribute_t attribute = CFI_attribute_other); RT_API_ATTRS ISO::CFI_cdesc_t &raw() { return raw_; } - const RT_API_ATTRS ISO::CFI_cdesc_t &raw() const { return raw_; } + RT_API_ATTRS const ISO::CFI_cdesc_t &raw() const { return raw_; } RT_API_ATTRS std::size_t ElementBytes() const { return raw_.elem_len; } RT_API_ATTRS int rank() const { return raw_.rank; } RT_API_ATTRS TypeCode type() const { return TypeCode{raw_.type}; } @@ -225,7 +225,7 @@ public: RT_API_ATTRS Dimension &GetDimension(int dim) { return *reinterpret_cast<Dimension *>(&raw_.dim[dim]); } - const RT_API_ATTRS Dimension &GetDimension(int dim) const { + RT_API_ATTRS const Dimension &GetDimension(int dim) const { return *reinterpret_cast<const Dimension *>(&raw_.dim[dim]); } @@ -345,7 +345,7 @@ public: return nullptr; } } - const RT_API_ATTRS DescriptorAddendum *Addendum() const { + RT_API_ATTRS const DescriptorAddendum *Addendum() const { if (raw_.f18Addendum != 0) { return reinterpret_cast<const DescriptorAddendum *>( &GetDimension(rank())); @@ -448,7 +448,7 @@ public: RT_API_ATTRS Descriptor &descriptor() { return *reinterpret_cast<Descriptor *>(storage_); } - const RT_API_ATTRS Descriptor &descriptor() const { + RT_API_ATTRS const Descriptor &descriptor() const { return *reinterpret_cast<const Descriptor *>(storage_); } diff --git a/flang/include/flang/Runtime/entry-names.h b/flang/include/flang/Runtime/entry-names.h index a233edf8e987dcbb98c1b040ac662c460f561f59..68582b92b54941750e71dc5f7c82ad90408c0863 100644 --- a/flang/include/flang/Runtime/entry-names.h +++ b/flang/include/flang/Runtime/entry-names.h @@ -19,7 +19,7 @@ #ifndef FORTRAN_RUNTIME_ENTRY_NAMES_H #define FORTRAN_RUNTIME_ENTRY_NAMES_H -#include "flang/Runtime/api-attrs.h" +#include "flang/Common/api-attrs.h" #ifndef RTNAME #define NAME_WITH_PREFIX_AND_REVISION(prefix, revision, name) \ diff --git a/flang/include/flang/Runtime/io-api.h b/flang/include/flang/Runtime/io-api.h index 556cc20c5a121e37ab282b97d296758946f23523..1b6c4f5d6a65cad64508a3618daa757ac3cfa4d9 100644 --- a/flang/include/flang/Runtime/io-api.h +++ b/flang/include/flang/Runtime/io-api.h @@ -51,13 +51,21 @@ constexpr InquiryKeywordHash HashInquiryKeyword(const char *p) { return hash; } -const char *InquiryKeywordHashDecode( +RT_API_ATTRS const char *InquiryKeywordHashDecode( char *buffer, std::size_t, InquiryKeywordHash); extern "C" { #define IONAME(name) RTNAME(io##name) +#ifndef IODECL +#define IODECL(name) RT_API_ATTRS IONAME(name) +#endif + +#ifndef IODEF +#define IODEF(name) RT_API_ATTRS IONAME(name) +#endif + // These functions initiate data transfer statements (READ, WRITE, PRINT). // Example: PRINT *, 666 is implemented as the series of calls: // Cookie cookie{BeginExternalListOutput(DefaultOutputUnit, @@ -139,7 +147,7 @@ enum Iostat IONAME(CheckUnitNumberInRange128)(common::int128_t unit, const char *sourceFile = nullptr, int sourceLine = 0); // External synchronous I/O initiation -Cookie IONAME(BeginExternalListOutput)(ExternalUnit = DefaultOutputUnit, +Cookie IODECL(BeginExternalListOutput)(ExternalUnit = DefaultOutputUnit, const char *sourceFile = nullptr, int sourceLine = 0); Cookie IONAME(BeginExternalListInput)(ExternalUnit = DefaultInputUnit, const char *sourceFile = nullptr, int sourceLine = 0); @@ -253,7 +261,7 @@ bool IONAME(InputDescriptor)(Cookie, const Descriptor &); // Formatted (including list directed) I/O data items bool IONAME(OutputInteger8)(Cookie, std::int8_t); bool IONAME(OutputInteger16)(Cookie, std::int16_t); -bool IONAME(OutputInteger32)(Cookie, std::int32_t); +bool IODECL(OutputInteger32)(Cookie, std::int32_t); bool IONAME(OutputInteger64)(Cookie, std::int64_t); bool IONAME(OutputInteger128)(Cookie, common::int128_t); bool IONAME(InputInteger)(Cookie, std::int64_t &, int kind = 8); @@ -357,7 +365,7 @@ bool IONAME(InquireInteger64)( // returned is guaranteed to only be one of the problems that the // EnableHandlers() call has indicated should be handled in compiled code // rather than by terminating the image. -enum Iostat IONAME(EndIoStatement)(Cookie); +enum Iostat IODECL(EndIoStatement)(Cookie); } // extern "C" } // namespace Fortran::runtime::io diff --git a/flang/include/flang/Runtime/iostat.h b/flang/include/flang/Runtime/iostat.h index afce509cf1f564043596326edfb257903a699ec1..6ce7c82b424eb70d448330843303161c2a1f73a0 100644 --- a/flang/include/flang/Runtime/iostat.h +++ b/flang/include/flang/Runtime/iostat.h @@ -11,6 +11,7 @@ #ifndef FORTRAN_RUNTIME_IOSTAT_H_ #define FORTRAN_RUNTIME_IOSTAT_H_ +#include "flang/Common/api-attrs.h" #include "flang/Runtime/magic-numbers.h" namespace Fortran::runtime::io { @@ -88,7 +89,7 @@ enum Iostat { IostatNonExternalDefinedUnformattedIo, }; -const char *IostatErrorString(int); +RT_API_ATTRS const char *IostatErrorString(int); } // namespace Fortran::runtime::io #endif // FORTRAN_RUNTIME_IOSTAT_H_ diff --git a/flang/include/flang/Runtime/memory.h b/flang/include/flang/Runtime/memory.h index e24c509f4e90cbe23998bec73cd4bd4368ecf29a..98412a989f890b5f4a92c8e09e7588999b1b8c1a 100644 --- a/flang/include/flang/Runtime/memory.h +++ b/flang/include/flang/Runtime/memory.h @@ -12,7 +12,7 @@ #ifndef FORTRAN_RUNTIME_MEMORY_H_ #define FORTRAN_RUNTIME_MEMORY_H_ -#include "flang/Runtime/api-attrs.h" +#include "flang/Common/api-attrs.h" #include <cassert> #include <memory> #include <type_traits> @@ -79,6 +79,8 @@ public: return p; } + RT_DIAG_PUSH + RT_DIAG_DISABLE_CALL_HOST_FROM_DEVICE_WARN // Replace the pointer. RT_API_ATTRS void reset(pointer_type p = pointer_type{}) { std::swap(ptr_, p); @@ -90,6 +92,7 @@ public: // Exchange the pointer with another object. RT_API_ATTRS void swap(OwningPtr &other) { std::swap(ptr_, other.ptr_); } + RT_DIAG_POP // Get the stored pointer. RT_API_ATTRS pointer_type get() const { return ptr_; } @@ -128,9 +131,12 @@ inline RT_API_ATTRS bool operator!=(std::nullptr_t, const OwningPtr<X> &x) { template <typename A> class SizedNew { public: - explicit SizedNew(const Terminator &terminator) : terminator_{terminator} {} + explicit RT_API_ATTRS SizedNew(const Terminator &terminator) + : terminator_{terminator} {} + template <typename... X> - [[nodiscard]] OwningPtr<A> operator()(std::size_t bytes, X &&...x) { + [[nodiscard]] RT_API_ATTRS OwningPtr<A> operator()( + std::size_t bytes, X &&...x) { return OwningPtr<A>{new (AllocateMemoryOrCrash(terminator_, bytes)) A{std::forward<X>(x)...}}; } @@ -141,7 +147,8 @@ private: template <typename A> struct New : public SizedNew<A> { using SizedNew<A>::SizedNew; - template <typename... X> [[nodiscard]] OwningPtr<A> operator()(X &&...x) { + template <typename... X> + [[nodiscard]] RT_API_ATTRS OwningPtr<A> operator()(X &&...x) { return SizedNew<A>::operator()(sizeof(A), std::forward<X>(x)...); } }; diff --git a/flang/include/flang/Runtime/reduce.h b/flang/include/flang/Runtime/reduce.h new file mode 100644 index 0000000000000000000000000000000000000000..975aa6dea305f5248b3b9af1822e033b642abbea --- /dev/null +++ b/flang/include/flang/Runtime/reduce.h @@ -0,0 +1,257 @@ +//===-- include/flang/Runtime/reduce.h --------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Defines the API for implementations of the transformational intrinsic +// function REDUCE(); see F'2023 16.9.173. +// +// Similar to the definition of the APIs for SUM(), &c., in reduction.h, +// there are typed functions here like ReduceInteger4() for total reductions +// to scalars and void functions like ReduceInteger4Dim() for partial +// reductions to smaller arrays. + +#ifndef FORTRAN_RUNTIME_REDUCE_H_ +#define FORTRAN_RUNTIME_REDUCE_H_ + +#include "flang/Common/float128.h" +#include "flang/Common/uint128.h" +#include "flang/Runtime/cpp-type.h" +#include "flang/Runtime/entry-names.h" +#include <complex> +#include <cstdint> + +namespace Fortran::runtime { + +class Descriptor; + +template <typename T> using ReductionOperation = T (*)(const T *, const T *); +template <typename CHAR> +using ReductionCharOperation = void (*)(CHAR *hiddenResult, + std::size_t resultLen, const CHAR *x, const CHAR *y, std::size_t xLen, + std::size_t yLen); +using ReductionDerivedTypeOperation = void (*)( + void *hiddenResult, const void *x, const void *y); + +extern "C" { + +std::int8_t RTDECL(ReduceInteger1)(const Descriptor &, + ReductionOperation<std::int8_t>, const char *source, int line, int dim = 0, + const Descriptor *mask = nullptr, const std::int8_t *identity = nullptr, + bool ordered = true); +void RTDECL(ReduceInteger1Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::int8_t>, const char *source, int line, int dim, + const Descriptor *mask = nullptr, const std::int8_t *identity = nullptr, + bool ordered = true); +std::int16_t RTDECL(ReduceInteger2)(const Descriptor &, + ReductionOperation<std::int16_t>, const char *source, int line, int dim = 0, + const Descriptor *mask = nullptr, const std::int16_t *identity = nullptr, + bool ordered = true); +void RTDECL(ReduceInteger2Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::int16_t>, const char *source, int line, int dim, + const Descriptor *mask = nullptr, const std::int16_t *identity = nullptr, + bool ordered = true); +std::int32_t RTDECL(ReduceInteger4)(const Descriptor &, + ReductionOperation<std::int32_t>, const char *source, int line, int dim = 0, + const Descriptor *mask = nullptr, const std::int32_t *identity = nullptr, + bool ordered = true); +void RTDECL(ReduceInteger4Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::int32_t>, const char *source, int line, int dim, + const Descriptor *mask = nullptr, const std::int32_t *identity = nullptr, + bool ordered = true); +std::int64_t RTDECL(ReduceInteger8)(const Descriptor &, + ReductionOperation<std::int64_t>, const char *source, int line, int dim = 0, + const Descriptor *mask = nullptr, const std::int64_t *identity = nullptr, + bool ordered = true); +void RTDECL(ReduceInteger8Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::int64_t>, const char *source, int line, int dim, + const Descriptor *mask = nullptr, const std::int64_t *identity = nullptr, + bool ordered = true); +#ifdef __SIZEOF_INT128__ +common::int128_t RTDECL(ReduceInteger16)(const Descriptor &, + ReductionOperation<common::int128_t>, const char *source, int line, + int dim = 0, const Descriptor *mask = nullptr, + const common::int128_t *identity = nullptr, bool ordered = true); +void RTDECL(ReduceInteger16Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<common::int128_t>, const char *source, int line, int dim, + const Descriptor *mask = nullptr, + const common::int128_t *identity = nullptr, bool ordered = true); +#endif + +// REAL/COMPLEX(2 & 3) return 32-bit float results for the caller to downconvert +float RTDECL(ReduceReal2)(const Descriptor &, ReductionOperation<float>, + const char *source, int line, int dim = 0, const Descriptor *mask = nullptr, + const float *identity = nullptr, bool ordered = true); +void RTDECL(ReduceReal2Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<float>, const char *source, int line, int dim, + const Descriptor *mask = nullptr, const float *identity = nullptr, + bool ordered = true); +float RTDECL(ReduceReal3)(const Descriptor &, ReductionOperation<float>, + const char *source, int line, int dim = 0, const Descriptor *mask = nullptr, + const float *identity = nullptr, bool ordered = true); +void RTDECL(ReduceReal3Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<float>, const char *source, int line, int dim, + const Descriptor *mask = nullptr, const float *identity = nullptr, + bool ordered = true); +float RTDECL(ReduceReal4)(const Descriptor &, ReductionOperation<float>, + const char *source, int line, int dim = 0, const Descriptor *mask = nullptr, + const float *identity = nullptr, bool ordered = true); +void RTDECL(ReduceReal4Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<float>, const char *source, int line, int dim, + const Descriptor *mask = nullptr, const float *identity = nullptr, + bool ordered = true); +double RTDECL(ReduceReal8)(const Descriptor &, ReductionOperation<double>, + const char *source, int line, int dim = 0, const Descriptor *mask = nullptr, + const double *identity = nullptr, bool ordered = true); +void RTDECL(ReduceReal8Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<double>, const char *source, int line, int dim, + const Descriptor *mask = nullptr, const double *identity = nullptr, + bool ordered = true); +#if LDBL_MANT_DIG == 64 +long double RTDECL(ReduceReal10)(const Descriptor &, + ReductionOperation<long double>, const char *source, int line, int dim = 0, + const Descriptor *mask = nullptr, const long double *identity = nullptr, + bool ordered = true); +void RTDECL(ReduceReal10Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<long double>, const char *source, int line, int dim, + const Descriptor *mask = nullptr, const long double *identity = nullptr, + bool ordered = true); +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +CppFloat128Type RTDECL(ReduceReal16)(const Descriptor &, + ReductionOperation<CppFloat128Type>, const char *source, int line, + int dim = 0, const Descriptor *mask = nullptr, + const CppFloat128Type *identity = nullptr, bool ordered = true); +void RTDECL(ReduceReal16Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<CppFloat128Type>, const char *source, int line, int dim, + const Descriptor *mask = nullptr, const CppFloat128Type *identity = nullptr, + bool ordered = true); +#endif + +void RTDECL(CppReduceComplex2)(std::complex<float> &, const Descriptor &, + ReductionOperation<std::complex<float>>, const char *source, int line, + int dim = 0, const Descriptor *mask = nullptr, + const std::complex<float> *identity = nullptr, bool ordered = true); +void RTDECL(CppReduceComplex2Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::complex<float>>, const char *source, int line, + int dim, const Descriptor *mask = nullptr, + const std::complex<float> *identity = nullptr, bool ordered = true); +void RTDECL(CppReduceComplex3)(std::complex<float> &, const Descriptor &, + ReductionOperation<std::complex<float>>, const char *source, int line, + int dim = 0, const Descriptor *mask = nullptr, + const std::complex<float> *identity = nullptr, bool ordered = true); +void RTDECL(CppReduceComplex3Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::complex<float>>, const char *source, int line, + int dim, const Descriptor *mask = nullptr, + const std::complex<float> *identity = nullptr, bool ordered = true); +void RTDECL(CppReduceComplex4)(std::complex<float> &, const Descriptor &, + ReductionOperation<std::complex<float>>, const char *source, int line, + int dim = 0, const Descriptor *mask = nullptr, + const std::complex<float> *identity = nullptr, bool ordered = true); +void RTDECL(CppReduceComplex4Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::complex<float>>, const char *source, int line, + int dim, const Descriptor *mask = nullptr, + const std::complex<float> *identity = nullptr, bool ordered = true); +void RTDECL(CppReduceComplex8)(std::complex<double> &, const Descriptor &, + ReductionOperation<std::complex<double>>, const char *source, int line, + int dim = 0, const Descriptor *mask = nullptr, + const std::complex<double> *identity = nullptr, bool ordered = true); +void RTDECL(CppReduceComplex8Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::complex<double>>, const char *source, int line, + int dim, const Descriptor *mask = nullptr, + const std::complex<double> *identity = nullptr, bool ordered = true); +#if LDBL_MANT_DIG == 64 +void RTDECL(CppReduceComplex10)(std::complex<long double> &, const Descriptor &, + ReductionOperation<std::complex<long double>>, const char *source, int line, + int dim = 0, const Descriptor *mask = nullptr, + const std::complex<long double> *identity = nullptr, bool ordered = true); +void RTDECL(CppReduceComplex10Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::complex<long double>>, const char *source, int line, + int dim, const Descriptor *mask = nullptr, + const std::complex<long double> *identity = nullptr, bool ordered = true); +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +void RTDECL(CppReduceComplex16)(std::complex<CppFloat128Type> &, + const Descriptor &, ReductionOperation<std::complex<CppFloat128Type>>, + const char *source, int line, int dim = 0, const Descriptor *mask = nullptr, + const std::complex<CppFloat128Type> *identity = nullptr, + bool ordered = true); +void RTDECL(CppReduceComplex16Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::complex<CppFloat128Type>>, const char *source, + int line, int dim, const Descriptor *mask = nullptr, + const std::complex<CppFloat128Type> *identity = nullptr, + bool ordered = true); +#endif + +bool RTDECL(ReduceLogical1)(const Descriptor &, ReductionOperation<std::int8_t>, + const char *source, int line, int dim = 0, const Descriptor *mask = nullptr, + const std::int8_t *identity = nullptr, bool ordered = true); +void RTDECL(ReduceLogical1Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::int8_t>, const char *source, int line, int dim, + const Descriptor *mask = nullptr, const std::int8_t *identity = nullptr, + bool ordered = true); +bool RTDECL(ReduceLogical2)(const Descriptor &, + ReductionOperation<std::int16_t>, const char *source, int line, int dim = 0, + const Descriptor *mask = nullptr, const std::int16_t *identity = nullptr, + bool ordered = true); +void RTDECL(ReduceLogical2Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::int16_t>, const char *source, int line, int dim, + const Descriptor *mask = nullptr, const std::int16_t *identity = nullptr, + bool ordered = true); +bool RTDECL(ReduceLogical4)(const Descriptor &, + ReductionOperation<std::int32_t>, const char *source, int line, int dim = 0, + const Descriptor *mask = nullptr, const std::int32_t *identity = nullptr, + bool ordered = true); +void RTDECL(ReduceLogical4Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::int32_t>, const char *source, int line, int dim, + const Descriptor *mask = nullptr, const std::int32_t *identity = nullptr, + bool ordered = true); +bool RTDECL(ReduceLogical8)(const Descriptor &, + ReductionOperation<std::int64_t>, const char *source, int line, int dim = 0, + const Descriptor *mask = nullptr, const std::int64_t *identity = nullptr, + bool ordered = true); +void RTDECL(ReduceLogical8Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::int64_t>, const char *source, int line, int dim, + const Descriptor *mask = nullptr, const std::int64_t *identity = nullptr, + bool ordered = true); + +void RTDECL(ReduceChar1)(char *result, const Descriptor &array, + ReductionCharOperation<char>, const char *source, int line, int dim = 0, + const Descriptor *mask = nullptr, const char *identity = nullptr, + bool ordered = true); +void RTDECL(ReduceCharacter1Dim)(Descriptor &result, const Descriptor &array, + ReductionCharOperation<char>, const char *source, int line, int dim, + const Descriptor *mask = nullptr, const char *identity = nullptr, + bool ordered = true); +void RTDECL(ReduceChar2)(char16_t *result, const Descriptor &array, + ReductionCharOperation<char16_t>, const char *source, int line, int dim = 0, + const Descriptor *mask = nullptr, const char16_t *identity = nullptr, + bool ordered = true); +void RTDECL(ReduceCharacter2Dim)(Descriptor &result, const Descriptor &array, + ReductionCharOperation<char16_t>, const char *source, int line, int dim, + const Descriptor *mask = nullptr, const char16_t *identity = nullptr, + bool ordered = true); +void RTDECL(ReduceChar4)(char32_t *result, const Descriptor &array, + ReductionCharOperation<char32_t>, const char *source, int line, int dim = 0, + const Descriptor *mask = nullptr, const char32_t *identity = nullptr, + bool ordered = true); +void RTDECL(ReduceCharacter4Dim)(Descriptor &result, const Descriptor &array, + ReductionCharOperation<char32_t>, const char *source, int line, int dim, + const Descriptor *mask = nullptr, const char32_t *identity = nullptr, + bool ordered = true); + +void RTDECL(ReduceDerivedType)(char *result, const Descriptor &array, + ReductionDerivedTypeOperation, const char *source, int line, int dim = 0, + const Descriptor *mask = nullptr, const char *identity = nullptr, + bool ordered = true); +void RTDECL(ReduceDerivedTypeDim)(Descriptor &result, const Descriptor &array, + ReductionDerivedTypeOperation, const char *source, int line, int dim, + const Descriptor *mask = nullptr, const char *identity = nullptr, + bool ordered = true); + +} // extern "C" +} // namespace Fortran::runtime +#endif // FORTRAN_RUNTIME_REDUCE_H_ diff --git a/flang/include/flang/Runtime/reduction.h b/flang/include/flang/Runtime/reduction.h index 5b607765857523aedf4c8924ea8f650c2ceb419e..97986c12e8a10e022e0b1e88e948155e5b1fcab7 100644 --- a/flang/include/flang/Runtime/reduction.h +++ b/flang/include/flang/Runtime/reduction.h @@ -89,9 +89,11 @@ void RTDECL(CppSumComplex4)(std::complex<float> &, const Descriptor &, void RTDECL(CppSumComplex8)(std::complex<double> &, const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); +#if LDBL_MANT_DIG == 64 void RTDECL(CppSumComplex10)(std::complex<long double> &, const Descriptor &, const char *source, int line, int dim = 0, const Descriptor *mask = nullptr); +#endif #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 void RTDECL(CppSumComplex16)(std::complex<CppFloat128Type> &, const Descriptor &, const char *source, int line, int dim = 0, diff --git a/flang/include/flang/Runtime/type-code.h b/flang/include/flang/Runtime/type-code.h index 3757840cfdef963c337b9ab3a5b68d9f10a9ba9e..8e7314e0af1efcdf468ce7107f6d06a0f58b0ae8 100644 --- a/flang/include/flang/Runtime/type-code.h +++ b/flang/include/flang/Runtime/type-code.h @@ -10,8 +10,8 @@ #define FORTRAN_RUNTIME_TYPE_CODE_H_ #include "flang/Common/Fortran.h" +#include "flang/Common/optional.h" #include "flang/ISO_Fortran_binding_wrapper.h" -#include <optional> #include <utility> namespace Fortran::runtime { @@ -54,7 +54,7 @@ public: return IsValid() && !IsDerived(); } - RT_API_ATTRS std::optional<std::pair<TypeCategory, int>> + RT_API_ATTRS Fortran::common::optional<std::pair<TypeCategory, int>> GetCategoryAndKind() const; RT_API_ATTRS bool operator==(TypeCode that) const { diff --git a/flang/include/flang/Semantics/module-dependences.h b/flang/include/flang/Semantics/module-dependences.h index 29813a19a4b1bce3f0b96bb976a48c42a8cdf299..3401d64c95938ebb957b8563ff873f715a0b23c7 100644 --- a/flang/include/flang/Semantics/module-dependences.h +++ b/flang/include/flang/Semantics/module-dependences.h @@ -23,9 +23,9 @@ public: void AddDependence( std::string &&name, bool intrinsic, ModuleCheckSumType hash) { if (intrinsic) { - intrinsicMap_.emplace(std::move(name), hash); + intrinsicMap_.insert_or_assign(std::move(name), hash); } else { - nonIntrinsicMap_.emplace(std::move(name), hash); + nonIntrinsicMap_.insert_or_assign(std::move(name), hash); } } std::optional<ModuleCheckSumType> GetRequiredHash( diff --git a/flang/include/flang/Semantics/openmp-directive-sets.h b/flang/include/flang/Semantics/openmp-directive-sets.h index a4f27b00152e26b0d73b0ab2b613795f1351204a..91773ae3ea9a3e85b758ad1388b965b62c665563 100644 --- a/flang/include/flang/Semantics/openmp-directive-sets.h +++ b/flang/include/flang/Semantics/openmp-directive-sets.h @@ -20,32 +20,27 @@ namespace llvm::omp { // Directive sets for single directives //===----------------------------------------------------------------------===// // - top<Directive>Set: The directive appears alone or as the first in a -// combined construct. -// - all<Directive>Set: All standalone or combined uses of the directive. +// compound construct. +// - all<Directive>Set: All standalone or compound uses of the directive. -static const OmpDirectiveSet topParallelSet{ - Directive::OMPD_parallel, - Directive::OMPD_parallel_do, - Directive::OMPD_parallel_do_simd, - Directive::OMPD_parallel_sections, - Directive::OMPD_parallel_workshare, -}; - -static const OmpDirectiveSet allParallelSet{ +static const OmpDirectiveSet topDistributeSet{ + Directive::OMPD_distribute, Directive::OMPD_distribute_parallel_do, Directive::OMPD_distribute_parallel_do_simd, - Directive::OMPD_parallel, - Directive::OMPD_parallel_do, - Directive::OMPD_parallel_do_simd, - Directive::OMPD_parallel_sections, - Directive::OMPD_parallel_workshare, - Directive::OMPD_target_parallel, - Directive::OMPD_target_parallel_do, - Directive::OMPD_target_parallel_do_simd, - Directive::OMPD_target_teams_distribute_parallel_do, - Directive::OMPD_target_teams_distribute_parallel_do_simd, - Directive::OMPD_teams_distribute_parallel_do, - Directive::OMPD_teams_distribute_parallel_do_simd, + Directive::OMPD_distribute_simd, +}; + +static const OmpDirectiveSet allDistributeSet{ + OmpDirectiveSet{ + llvm::omp::OMPD_target_teams_distribute, + llvm::omp::OMPD_target_teams_distribute_parallel_do, + llvm::omp::OMPD_target_teams_distribute_parallel_do_simd, + llvm::omp::OMPD_target_teams_distribute_simd, + llvm::omp::OMPD_teams_distribute, + llvm::omp::OMPD_teams_distribute_parallel_do, + llvm::omp::OMPD_teams_distribute_parallel_do_simd, + llvm::omp::OMPD_teams_distribute_simd, + } | topDistributeSet, }; static const OmpDirectiveSet topDoSet{ @@ -54,26 +49,69 @@ static const OmpDirectiveSet topDoSet{ }; static const OmpDirectiveSet allDoSet{ - Directive::OMPD_distribute_parallel_do, - Directive::OMPD_distribute_parallel_do_simd, + OmpDirectiveSet{ + Directive::OMPD_distribute_parallel_do, + Directive::OMPD_distribute_parallel_do_simd, + Directive::OMPD_parallel_do, + Directive::OMPD_parallel_do_simd, + Directive::OMPD_target_parallel_do, + Directive::OMPD_target_parallel_do_simd, + Directive::OMPD_target_teams_distribute_parallel_do, + Directive::OMPD_target_teams_distribute_parallel_do_simd, + Directive::OMPD_teams_distribute_parallel_do, + Directive::OMPD_teams_distribute_parallel_do_simd, + } | topDoSet, +}; + +static const OmpDirectiveSet topParallelSet{ + Directive::OMPD_parallel, Directive::OMPD_parallel_do, Directive::OMPD_parallel_do_simd, - Directive::OMPD_do, - Directive::OMPD_do_simd, - Directive::OMPD_target_parallel_do, - Directive::OMPD_target_parallel_do_simd, - Directive::OMPD_target_teams_distribute_parallel_do, - Directive::OMPD_target_teams_distribute_parallel_do_simd, - Directive::OMPD_teams_distribute_parallel_do, - Directive::OMPD_teams_distribute_parallel_do_simd, + Directive::OMPD_parallel_masked_taskloop, + Directive::OMPD_parallel_masked_taskloop_simd, + Directive::OMPD_parallel_master_taskloop, + Directive::OMPD_parallel_master_taskloop_simd, + Directive::OMPD_parallel_sections, + Directive::OMPD_parallel_workshare, }; -static const OmpDirectiveSet topTaskloopSet{ - Directive::OMPD_taskloop, - Directive::OMPD_taskloop_simd, +static const OmpDirectiveSet allParallelSet{ + OmpDirectiveSet{ + Directive::OMPD_distribute_parallel_do, + Directive::OMPD_distribute_parallel_do_simd, + Directive::OMPD_target_parallel, + Directive::OMPD_target_parallel_do, + Directive::OMPD_target_parallel_do_simd, + Directive::OMPD_target_teams_distribute_parallel_do, + Directive::OMPD_target_teams_distribute_parallel_do_simd, + Directive::OMPD_teams_distribute_parallel_do, + Directive::OMPD_teams_distribute_parallel_do_simd, + } | topParallelSet, +}; + +static const OmpDirectiveSet topSimdSet{ + Directive::OMPD_simd, }; -static const OmpDirectiveSet allTaskloopSet{topTaskloopSet}; +static const OmpDirectiveSet allSimdSet{ + OmpDirectiveSet{ + Directive::OMPD_distribute_parallel_do_simd, + Directive::OMPD_distribute_simd, + Directive::OMPD_do_simd, + Directive::OMPD_masked_taskloop_simd, + Directive::OMPD_master_taskloop_simd, + Directive::OMPD_parallel_do_simd, + Directive::OMPD_parallel_masked_taskloop_simd, + Directive::OMPD_parallel_master_taskloop_simd, + Directive::OMPD_target_parallel_do_simd, + Directive::OMPD_target_simd, + Directive::OMPD_target_teams_distribute_parallel_do_simd, + Directive::OMPD_target_teams_distribute_simd, + Directive::OMPD_taskloop_simd, + Directive::OMPD_teams_distribute_parallel_do_simd, + Directive::OMPD_teams_distribute_simd, + } | topSimdSet, +}; static const OmpDirectiveSet topTargetSet{ Directive::OMPD_target, @@ -90,23 +128,22 @@ static const OmpDirectiveSet topTargetSet{ static const OmpDirectiveSet allTargetSet{topTargetSet}; -static const OmpDirectiveSet topSimdSet{ - Directive::OMPD_simd, +static const OmpDirectiveSet topTaskloopSet{ + Directive::OMPD_taskloop, + Directive::OMPD_taskloop_simd, }; -static const OmpDirectiveSet allSimdSet{ - Directive::OMPD_distribute_parallel_do_simd, - Directive::OMPD_distribute_simd, - Directive::OMPD_do_simd, - Directive::OMPD_parallel_do_simd, - Directive::OMPD_simd, - Directive::OMPD_target_parallel_do_simd, - Directive::OMPD_target_simd, - Directive::OMPD_target_teams_distribute_parallel_do_simd, - Directive::OMPD_target_teams_distribute_simd, - Directive::OMPD_taskloop_simd, - Directive::OMPD_teams_distribute_parallel_do_simd, - Directive::OMPD_teams_distribute_simd, +static const OmpDirectiveSet allTaskloopSet{ + OmpDirectiveSet{ + Directive::OMPD_masked_taskloop, + Directive::OMPD_masked_taskloop_simd, + Directive::OMPD_master_taskloop, + Directive::OMPD_master_taskloop_simd, + Directive::OMPD_parallel_masked_taskloop, + Directive::OMPD_parallel_masked_taskloop_simd, + Directive::OMPD_parallel_master_taskloop, + Directive::OMPD_parallel_master_taskloop_simd, + } | topTaskloopSet, }; static const OmpDirectiveSet topTeamsSet{ @@ -118,178 +155,134 @@ static const OmpDirectiveSet topTeamsSet{ }; static const OmpDirectiveSet allTeamsSet{ - llvm::omp::OMPD_target_teams, - llvm::omp::OMPD_target_teams_distribute, - llvm::omp::OMPD_target_teams_distribute_parallel_do, - llvm::omp::OMPD_target_teams_distribute_parallel_do_simd, - llvm::omp::OMPD_target_teams_distribute_simd, - llvm::omp::OMPD_teams, - llvm::omp::OMPD_teams_distribute, - llvm::omp::OMPD_teams_distribute_parallel_do, - llvm::omp::OMPD_teams_distribute_parallel_do_simd, - llvm::omp::OMPD_teams_distribute_simd, -}; - -static const OmpDirectiveSet topDistributeSet{ - Directive::OMPD_distribute, - Directive::OMPD_distribute_parallel_do, - Directive::OMPD_distribute_parallel_do_simd, - Directive::OMPD_distribute_simd, -}; - -static const OmpDirectiveSet allDistributeSet{ - llvm::omp::OMPD_distribute, - llvm::omp::OMPD_distribute_parallel_do, - llvm::omp::OMPD_distribute_parallel_do_simd, - llvm::omp::OMPD_distribute_simd, - llvm::omp::OMPD_target_teams_distribute, - llvm::omp::OMPD_target_teams_distribute_parallel_do, - llvm::omp::OMPD_target_teams_distribute_parallel_do_simd, - llvm::omp::OMPD_target_teams_distribute_simd, - llvm::omp::OMPD_teams_distribute, - llvm::omp::OMPD_teams_distribute_parallel_do, - llvm::omp::OMPD_teams_distribute_parallel_do_simd, - llvm::omp::OMPD_teams_distribute_simd, + OmpDirectiveSet{ + llvm::omp::OMPD_target_teams, + llvm::omp::OMPD_target_teams_distribute, + llvm::omp::OMPD_target_teams_distribute_parallel_do, + llvm::omp::OMPD_target_teams_distribute_parallel_do_simd, + llvm::omp::OMPD_target_teams_distribute_simd, + } | topTeamsSet, }; //===----------------------------------------------------------------------===// // Directive sets for groups of multiple directives //===----------------------------------------------------------------------===// +// Composite constructs +static const OmpDirectiveSet allDistributeParallelDoSet{ + allDistributeSet & allParallelSet & allDoSet}; +static const OmpDirectiveSet allDistributeParallelDoSimdSet{ + allDistributeSet & allParallelSet & allDoSet & allSimdSet}; +static const OmpDirectiveSet allDistributeSimdSet{ + allDistributeSet & allSimdSet}; static const OmpDirectiveSet allDoSimdSet{allDoSet & allSimdSet}; +static const OmpDirectiveSet allTaskloopSimdSet{allTaskloopSet & allSimdSet}; -static const OmpDirectiveSet workShareSet{ - OmpDirectiveSet{ - Directive::OMPD_workshare, - Directive::OMPD_parallel_workshare, - Directive::OMPD_parallel_sections, - Directive::OMPD_sections, - Directive::OMPD_single, - } | allDoSet, -}; - -static const OmpDirectiveSet taskGeneratingSet{ - OmpDirectiveSet{ - Directive::OMPD_task, - } | allTaskloopSet, -}; - -static const OmpDirectiveSet nonPartialVarSet{ - Directive::OMPD_allocate, - Directive::OMPD_allocators, - Directive::OMPD_threadprivate, - Directive::OMPD_declare_target, +static const OmpDirectiveSet blockConstructSet{ + Directive::OMPD_master, + Directive::OMPD_ordered, + Directive::OMPD_parallel, + Directive::OMPD_parallel_workshare, + Directive::OMPD_single, + Directive::OMPD_target, + Directive::OMPD_target_data, + Directive::OMPD_target_parallel, + Directive::OMPD_target_teams, + Directive::OMPD_task, + Directive::OMPD_taskgroup, + Directive::OMPD_teams, + Directive::OMPD_workshare, }; static const OmpDirectiveSet loopConstructSet{ - Directive::OMPD_distribute_parallel_do_simd, + Directive::OMPD_distribute, Directive::OMPD_distribute_parallel_do, + Directive::OMPD_distribute_parallel_do_simd, Directive::OMPD_distribute_simd, - Directive::OMPD_distribute, - Directive::OMPD_do_simd, Directive::OMPD_do, - Directive::OMPD_parallel_do_simd, + Directive::OMPD_do_simd, + Directive::OMPD_masked_taskloop, + Directive::OMPD_masked_taskloop_simd, + Directive::OMPD_master_taskloop, + Directive::OMPD_master_taskloop_simd, Directive::OMPD_parallel_do, + Directive::OMPD_parallel_do_simd, + Directive::OMPD_parallel_masked_taskloop, + Directive::OMPD_parallel_masked_taskloop_simd, + Directive::OMPD_parallel_master_taskloop, + Directive::OMPD_parallel_master_taskloop_simd, Directive::OMPD_simd, - Directive::OMPD_target_parallel_do_simd, Directive::OMPD_target_parallel_do, + Directive::OMPD_target_parallel_do_simd, Directive::OMPD_target_simd, - Directive::OMPD_target_teams_distribute_parallel_do_simd, + Directive::OMPD_target_teams_distribute, Directive::OMPD_target_teams_distribute_parallel_do, + Directive::OMPD_target_teams_distribute_parallel_do_simd, Directive::OMPD_target_teams_distribute_simd, - Directive::OMPD_target_teams_distribute, - Directive::OMPD_taskloop_simd, Directive::OMPD_taskloop, - Directive::OMPD_teams_distribute_parallel_do_simd, + Directive::OMPD_taskloop_simd, + Directive::OMPD_teams_distribute, Directive::OMPD_teams_distribute_parallel_do, + Directive::OMPD_teams_distribute_parallel_do_simd, Directive::OMPD_teams_distribute_simd, - Directive::OMPD_teams_distribute, Directive::OMPD_tile, Directive::OMPD_unroll, }; -static const OmpDirectiveSet blockConstructSet{ - Directive::OMPD_master, - Directive::OMPD_ordered, - Directive::OMPD_parallel_workshare, - Directive::OMPD_parallel, - Directive::OMPD_single, - Directive::OMPD_target_data, - Directive::OMPD_target_parallel, - Directive::OMPD_target_teams, - Directive::OMPD_target, - Directive::OMPD_task, - Directive::OMPD_taskgroup, - Directive::OMPD_teams, - Directive::OMPD_workshare, -}; - -//===----------------------------------------------------------------------===// -// Directive sets for allowed/not allowed nested directives -//===----------------------------------------------------------------------===// - -static const OmpDirectiveSet nestedOrderedErrSet{ - Directive::OMPD_critical, - Directive::OMPD_ordered, - Directive::OMPD_atomic, - Directive::OMPD_task, - Directive::OMPD_taskloop, +static const OmpDirectiveSet nonPartialVarSet{ + Directive::OMPD_allocate, + Directive::OMPD_allocators, + Directive::OMPD_threadprivate, + Directive::OMPD_declare_target, }; -static const OmpDirectiveSet nestedWorkshareErrSet{ +static const OmpDirectiveSet taskGeneratingSet{ OmpDirectiveSet{ Directive::OMPD_task, - Directive::OMPD_taskloop, - Directive::OMPD_critical, - Directive::OMPD_ordered, - Directive::OMPD_atomic, - Directive::OMPD_master, - } | workShareSet, + } | allTaskloopSet, }; -static const OmpDirectiveSet nestedMasterErrSet{ +static const OmpDirectiveSet workShareSet{ OmpDirectiveSet{ - Directive::OMPD_atomic, - } | taskGeneratingSet | - workShareSet, + Directive::OMPD_workshare, + Directive::OMPD_parallel_workshare, + Directive::OMPD_parallel_sections, + Directive::OMPD_sections, + Directive::OMPD_single, + } | allDoSet, }; +//===----------------------------------------------------------------------===// +// Directive sets for allowed/not allowed nested directives +//===----------------------------------------------------------------------===// + static const OmpDirectiveSet nestedBarrierErrSet{ OmpDirectiveSet{ - Directive::OMPD_critical, - Directive::OMPD_ordered, Directive::OMPD_atomic, + Directive::OMPD_critical, Directive::OMPD_master, + Directive::OMPD_ordered, } | taskGeneratingSet | workShareSet, }; -static const OmpDirectiveSet nestedTeamsAllowedSet{ - Directive::OMPD_parallel, - Directive::OMPD_parallel_do, - Directive::OMPD_parallel_do_simd, - Directive::OMPD_parallel_master, - Directive::OMPD_parallel_master_taskloop, - Directive::OMPD_parallel_master_taskloop_simd, - Directive::OMPD_parallel_sections, - Directive::OMPD_parallel_workshare, - Directive::OMPD_distribute, +static const OmpDirectiveSet nestedCancelDoAllowedSet{ Directive::OMPD_distribute_parallel_do, - Directive::OMPD_distribute_parallel_do_simd, - Directive::OMPD_distribute_simd, + Directive::OMPD_do, + Directive::OMPD_parallel_do, + Directive::OMPD_target_parallel_do, + Directive::OMPD_target_teams_distribute_parallel_do, + Directive::OMPD_teams_distribute_parallel_do, }; -static const OmpDirectiveSet nestedOrderedParallelErrSet{ +static const OmpDirectiveSet nestedCancelParallelAllowedSet{ Directive::OMPD_parallel, Directive::OMPD_target_parallel, - Directive::OMPD_parallel_sections, - Directive::OMPD_parallel_workshare, }; -static const OmpDirectiveSet nestedOrderedDoAllowedSet{ - Directive::OMPD_do, - Directive::OMPD_parallel_do, - Directive::OMPD_target_parallel_do, +static const OmpDirectiveSet nestedCancelSectionsAllowedSet{ + Directive::OMPD_parallel_sections, + Directive::OMPD_sections, }; static const OmpDirectiveSet nestedCancelTaskgroupAllowedSet{ @@ -297,29 +290,64 @@ static const OmpDirectiveSet nestedCancelTaskgroupAllowedSet{ Directive::OMPD_taskloop, }; -static const OmpDirectiveSet nestedCancelSectionsAllowedSet{ - Directive::OMPD_sections, - Directive::OMPD_parallel_sections, +static const OmpDirectiveSet nestedMasterErrSet{ + OmpDirectiveSet{ + Directive::OMPD_atomic, + } | taskGeneratingSet | + workShareSet, }; -static const OmpDirectiveSet nestedCancelDoAllowedSet{ +static const OmpDirectiveSet nestedOrderedDoAllowedSet{ Directive::OMPD_do, - Directive::OMPD_distribute_parallel_do, Directive::OMPD_parallel_do, Directive::OMPD_target_parallel_do, - Directive::OMPD_target_teams_distribute_parallel_do, - Directive::OMPD_teams_distribute_parallel_do, }; -static const OmpDirectiveSet nestedCancelParallelAllowedSet{ +static const OmpDirectiveSet nestedOrderedErrSet{ + Directive::OMPD_atomic, + Directive::OMPD_critical, + Directive::OMPD_ordered, + Directive::OMPD_task, + Directive::OMPD_taskloop, +}; + +static const OmpDirectiveSet nestedOrderedParallelErrSet{ Directive::OMPD_parallel, + Directive::OMPD_parallel_sections, + Directive::OMPD_parallel_workshare, Directive::OMPD_target_parallel, }; static const OmpDirectiveSet nestedReduceWorkshareAllowedSet{ Directive::OMPD_do, - Directive::OMPD_sections, Directive::OMPD_do_simd, + Directive::OMPD_sections, +}; + +static const OmpDirectiveSet nestedTeamsAllowedSet{ + Directive::OMPD_distribute, + Directive::OMPD_distribute_parallel_do, + Directive::OMPD_distribute_parallel_do_simd, + Directive::OMPD_distribute_simd, + Directive::OMPD_parallel, + Directive::OMPD_parallel_do, + Directive::OMPD_parallel_do_simd, + Directive::OMPD_parallel_master, + Directive::OMPD_parallel_master_taskloop, + Directive::OMPD_parallel_master_taskloop_simd, + Directive::OMPD_parallel_sections, + Directive::OMPD_parallel_workshare, +}; + +static const OmpDirectiveSet nestedWorkshareErrSet{ + OmpDirectiveSet{ + Directive::OMPD_atomic, + Directive::OMPD_critical, + Directive::OMPD_master, + Directive::OMPD_ordered, + Directive::OMPD_task, + Directive::OMPD_taskloop, + } | workShareSet, }; } // namespace llvm::omp diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h index c3175a5d1a111d3e0f177dfad3c709e296ba0dcb..67153ffb3be9f6eac7440cff37214427c87ebbcc 100644 --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -91,12 +91,15 @@ public: return moduleFileHash_; } void set_moduleFileHash(ModuleCheckSumType x) { moduleFileHash_ = x; } + const Symbol *previous() const { return previous_; } + void set_previous(const Symbol *p) { previous_ = p; } private: bool isSubmodule_; bool isDefaultPrivate_{false}; const Scope *scope_{nullptr}; std::optional<ModuleCheckSumType> moduleFileHash_; + const Symbol *previous_{nullptr}; // same name, different module file hash }; class MainProgramDetails : public WithOmpDeclarative { diff --git a/flang/include/flang/Semantics/tools.h b/flang/include/flang/Semantics/tools.h index df66e1adb550233279fdde19797a712a812c1a5f..f0eb82eebefa318a83ba4a46e0e798c638f739ee 100644 --- a/flang/include/flang/Semantics/tools.h +++ b/flang/include/flang/Semantics/tools.h @@ -53,7 +53,8 @@ const Symbol *FindPointerComponent(const Symbol &); const Symbol *FindInterface(const Symbol &); const Symbol *FindSubprogram(const Symbol &); const Symbol *FindFunctionResult(const Symbol &); -const Symbol *FindOverriddenBinding(const Symbol &); +const Symbol *FindOverriddenBinding( + const Symbol &, bool &isInaccessibleDeferred); const Symbol *FindGlobal(const Symbol &); const DeclTypeSpec *FindParentTypeSpec(const DerivedTypeSpec &); @@ -180,7 +181,8 @@ const Symbol *IsFinalizable(const Symbol &, const Symbol *IsFinalizable(const DerivedTypeSpec &, std::set<const DerivedTypeSpec *> * = nullptr, bool withImpureFinalizer = false, std::optional<int> rank = std::nullopt); -const Symbol *HasImpureFinal(const Symbol &); +const Symbol *HasImpureFinal( + const Symbol &, std::optional<int> rank = std::nullopt); // Is this type finalizable or does it contain any polymorphic allocatable // ultimate components? bool MayRequireFinalization(const DerivedTypeSpec &derived); @@ -281,6 +283,9 @@ const Symbol *FindExternallyVisibleObject( // specific procedure of the same name, return it instead. const Symbol &BypassGeneric(const Symbol &); +// Given a cray pointee symbol, returns the related cray pointer symbol. +const Symbol &GetCrayPointer(const Symbol &crayPointee); + using SomeExpr = evaluate::Expr<evaluate::SomeType>; bool ExprHasTypeCategory( diff --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc index 68e504d0ccb51292954038104f398e994f22c8e4..bc6df2c830696f622055f1308100a1b1c60a3cc6 100644 --- a/flang/include/flang/Tools/CLOptions.inc +++ b/flang/include/flang/Tools/CLOptions.inc @@ -123,7 +123,9 @@ static void addCanonicalizerPassWithoutRegionSimplification( inline void addCfgConversionPass(mlir::PassManager &pm) { addNestedPassConditionally<mlir::func::FuncOp>( - pm, disableCfgConversion, fir::createFirToCfgPass); + pm, disableCfgConversion, fir::createFirToCfgOnFuncPass); + addNestedPassConditionally<mlir::omp::DeclareReductionOp>( + pm, disableCfgConversion, fir::createFirToCfgOnReductionPass); } inline void addAVC( diff --git a/flang/lib/Evaluate/check-expression.cpp b/flang/lib/Evaluate/check-expression.cpp index 0e7d97900328bb2e637660ebaee4514c20051f88..7d721399072caea831e6ee52e8b772d2bad6c6af 100644 --- a/flang/lib/Evaluate/check-expression.cpp +++ b/flang/lib/Evaluate/check-expression.cpp @@ -358,10 +358,14 @@ bool IsInitialProcedureTarget(const semantics::Symbol &symbol) { const auto &ultimate{symbol.GetUltimate()}; return common::visit( common::visitors{ - [](const semantics::SubprogramDetails &subp) { - return !subp.isDummy(); + [&](const semantics::SubprogramDetails &subp) { + return !subp.isDummy() && !subp.stmtFunction() && + symbol.owner().kind() != semantics::Scope::Kind::MainProgram && + symbol.owner().kind() != semantics::Scope::Kind::Subprogram; + }, + [](const semantics::SubprogramNameDetails &x) { + return x.kind() != semantics::SubprogramKind::Internal; }, - [](const semantics::SubprogramNameDetails &) { return true; }, [&](const semantics::ProcEntityDetails &proc) { return !semantics::IsPointer(ultimate) && !proc.isDummy(); }, diff --git a/flang/lib/Evaluate/constant.cpp b/flang/lib/Evaluate/constant.cpp index a3bdefb76a414c0c7d84aa97344d45cd0ef43631..990339958399eabea23b8cbc591ae95026e25108 100644 --- a/flang/lib/Evaluate/constant.cpp +++ b/flang/lib/Evaluate/constant.cpp @@ -160,7 +160,7 @@ template <typename RESULT, typename ELEMENT> auto ConstantBase<RESULT, ELEMENT>::Reshape( const ConstantSubscripts &dims) const -> std::vector<Element> { std::optional<uint64_t> optN{TotalElementCount(dims)}; - CHECK(optN); + CHECK_MSG(optN, "Overflow in TotalElementCount"); uint64_t n{*optN}; CHECK(!empty() || n == 0); std::vector<Element> elements; diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index 4707de0e976ca7fd61414def9562dc639428fede..c830c7af2462c969e3fdb48e89fdfe897d52bcec 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -581,6 +581,8 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args, // pre-processed inputs. .Case("f95", Language::Fortran) .Case("f95-cpp-input", Language::Fortran) + // CUDA Fortran + .Case("cuda", Language::Fortran) .Default(Language::Unknown); // Flang's intermediate representations. @@ -877,6 +879,13 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args, if (args.hasArg(clang::driver::options::OPT_flarge_sizes)) res.getDefaultKinds().set_sizeIntegerKind(8); + // -x cuda + auto language = args.getLastArgValue(clang::driver::options::OPT_x); + if (language.equals("cuda")) { + res.getFrontendOpts().features.Enable( + Fortran::common::LanguageFeature::CUDA); + } + // -fopenmp and -fopenacc if (args.hasArg(clang::driver::options::OPT_fopenacc)) { res.getFrontendOpts().features.Enable( @@ -1182,11 +1191,6 @@ bool CompilerInvocation::createFromArgs( invoc.loweringOpts.setLowerToHighLevelFIR(false); } - if (args.hasArg( - clang::driver::options::OPT_flang_experimental_polymorphism)) { - invoc.loweringOpts.setPolymorphicTypeImpl(true); - } - // -fno-ppc-native-vector-element-order if (args.hasArg(clang::driver::options::OPT_fno_ppc_native_vec_elem_order)) { invoc.loweringOpts.setNoPPCNativeVecElemOrder(true); diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp index 599b4e11f0cfbd19a05923054575d454432af2a4..bb1c239540d9f5c15f91ad22aa7750b87fc447e7 100644 --- a/flang/lib/Frontend/FrontendAction.cpp +++ b/flang/lib/Frontend/FrontendAction.cpp @@ -86,9 +86,14 @@ bool FrontendAction::beginSourceFile(CompilerInstance &ci, invoc.collectMacroDefinitions(); } - // Enable CUDA Fortran if source file is *.cuf/*.CUF. - invoc.getFortranOpts().features.Enable(Fortran::common::LanguageFeature::CUDA, - getCurrentInput().getIsCUDAFortran()); + if (!invoc.getFortranOpts().features.IsEnabled( + Fortran::common::LanguageFeature::CUDA)) { + // Enable CUDA Fortran if source file is *.cuf/*.CUF and not already + // enabled. + invoc.getFortranOpts().features.Enable( + Fortran::common::LanguageFeature::CUDA, + getCurrentInput().getIsCUDAFortran()); + } // Decide between fixed and free form (if the user didn't express any // preference, use the file extension to decide) diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index a668ba4116faab5f443a4a668426dd7dd0c55af1..5bba0978617c79ddb807023d5fd68df27ca77b10 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -273,7 +273,8 @@ class FirConverter : public Fortran::lower::AbstractConverter { public: explicit FirConverter(Fortran::lower::LoweringBridge &bridge) : Fortran::lower::AbstractConverter(bridge.getLoweringOptions()), - bridge{bridge}, foldingContext{bridge.createFoldingContext()} {} + bridge{bridge}, foldingContext{bridge.createFoldingContext()}, + mlirSymbolTable{bridge.getModule()} {} virtual ~FirConverter() = default; /// Convert the PFT to FIR. @@ -329,8 +330,8 @@ public: [&](Fortran::lower::pft::BlockDataUnit &b) {}, [&](Fortran::lower::pft::CompilerDirectiveUnit &d) {}, [&](Fortran::lower::pft::OpenACCDirectiveUnit &d) { - builder = new fir::FirOpBuilder(bridge.getModule(), - bridge.getKindMap()); + builder = new fir::FirOpBuilder( + bridge.getModule(), bridge.getKindMap(), &mlirSymbolTable); Fortran::lower::genOpenACCRoutineConstruct( *this, bridge.getSemanticsContext(), bridge.getModule(), d.routine, accRoutineInfos); @@ -748,7 +749,8 @@ public: void copyVar(mlir::Location loc, mlir::Value dst, mlir::Value src) override final { - copyVarHLFIR(loc, dst, src); + copyVarHLFIR(loc, Fortran::lower::SymbolBox::Intrinsic{dst}, + Fortran::lower::SymbolBox::Intrinsic{src}); } void copyHostAssociateVar( @@ -1009,10 +1011,7 @@ private: // `omp.private`'s `alloc` block. If this is the case, we return this // `SymbolBox::Intrinsic` value. if (Fortran::lower::SymbolBox v = symMap->lookupSymbol(sym)) - return v.match( - [&](const Fortran::lower::SymbolBox::Intrinsic &) - -> Fortran::lower::SymbolBox { return v; }, - [](const auto &) -> Fortran::lower::SymbolBox { return {}; }); + return v; return {}; } @@ -1038,6 +1037,8 @@ private: return {}; } + mlir::SymbolTable *getMLIRSymbolTable() override { return &mlirSymbolTable; } + /// Add the symbol to the local map and return `true`. If the symbol is /// already in the map and \p forced is `false`, the map is not updated. /// Instead the value `false` is returned. @@ -1060,15 +1061,16 @@ private: const Fortran::lower::SymbolBox &rhs_sb) { mlir::Location loc = genLocation(sym.name()); if (lowerToHighLevelFIR()) - copyVarHLFIR(loc, lhs_sb.getAddr(), rhs_sb.getAddr()); + copyVarHLFIR(loc, lhs_sb, rhs_sb); else copyVarFIR(loc, sym, lhs_sb, rhs_sb); } - void copyVarHLFIR(mlir::Location loc, mlir::Value dst, mlir::Value src) { + void copyVarHLFIR(mlir::Location loc, Fortran::lower::SymbolBox dst, + Fortran::lower::SymbolBox src) { assert(lowerToHighLevelFIR()); - hlfir::Entity lhs{dst}; - hlfir::Entity rhs{src}; + hlfir::Entity lhs{dst.getAddr()}; + hlfir::Entity rhs{src.getAddr()}; // Temporary_lhs is set to true in hlfir.assign below to avoid user // assignment to be used and finalization to be called on the LHS. // This may or may not be correct but mimics the current behaviour @@ -1082,7 +1084,22 @@ private: /*keepLhsLengthInAllocatableAssignment=*/false, /*temporary_lhs=*/true); }; - if (lhs.isAllocatable()) { + + bool isBoxAllocatable = dst.match( + [](const fir::MutableBoxValue &box) { return box.isAllocatable(); }, + [](const fir::FortranVariableOpInterface &box) { + return fir::FortranVariableOpInterface(box).isAllocatable(); + }, + [](const auto &box) { return false; }); + + bool isBoxPointer = dst.match( + [](const fir::MutableBoxValue &box) { return box.isPointer(); }, + [](const fir::FortranVariableOpInterface &box) { + return fir::FortranVariableOpInterface(box).isPointer(); + }, + [](const auto &box) { return false; }); + + if (isBoxAllocatable) { // Deep copy allocatable if it is allocated. // Note that when allocated, the RHS is already allocated with the LHS // shape for copy on entry in createHostAssociateVarClone. @@ -1097,7 +1114,7 @@ private: copyData(lhs, rhs); }) .end(); - } else if (lhs.isPointer()) { + } else if (isBoxPointer) { // Set LHS target to the target of RHS (do not copy the RHS // target data into the LHS target storage). auto loadVal = builder->create<fir::LoadOp>(loc, rhs); @@ -2508,19 +2525,51 @@ private: if (nestedLoops > 1) n = builder->getIntegerAttr(builder->getI64Type(), nestedLoops); - const std::list<Fortran::parser::ScalarIntExpr> &grid = std::get<1>(dir.t); - const std::list<Fortran::parser::ScalarIntExpr> &block = std::get<2>(dir.t); + const std::list<Fortran::parser::CUFKernelDoConstruct::StarOrExpr> &grid = + std::get<1>(dir.t); + const std::list<Fortran::parser::CUFKernelDoConstruct::StarOrExpr> &block = + std::get<2>(dir.t); const std::optional<Fortran::parser::ScalarIntExpr> &stream = std::get<3>(dir.t); + auto isOnlyStars = + [&](const std::list<Fortran::parser::CUFKernelDoConstruct::StarOrExpr> + &list) -> bool { + for (const Fortran::parser::CUFKernelDoConstruct::StarOrExpr &expr : + list) { + if (expr.v) + return false; + } + return true; + }; + + mlir::Value zero = + builder->createIntegerConstant(loc, builder->getI32Type(), 0); + llvm::SmallVector<mlir::Value> gridValues; - for (const Fortran::parser::ScalarIntExpr &expr : grid) - gridValues.push_back(fir::getBase( - genExprValue(*Fortran::semantics::GetExpr(expr), stmtCtx))); + if (!isOnlyStars(grid)) { + for (const Fortran::parser::CUFKernelDoConstruct::StarOrExpr &expr : + grid) { + if (expr.v) { + gridValues.push_back(fir::getBase( + genExprValue(*Fortran::semantics::GetExpr(*expr.v), stmtCtx))); + } else { + gridValues.push_back(zero); + } + } + } llvm::SmallVector<mlir::Value> blockValues; - for (const Fortran::parser::ScalarIntExpr &expr : block) - blockValues.push_back(fir::getBase( - genExprValue(*Fortran::semantics::GetExpr(expr), stmtCtx))); + if (!isOnlyStars(block)) { + for (const Fortran::parser::CUFKernelDoConstruct::StarOrExpr &expr : + block) { + if (expr.v) { + blockValues.push_back(fir::getBase( + genExprValue(*Fortran::semantics::GetExpr(*expr.v), stmtCtx))); + } else { + blockValues.push_back(zero); + } + } + } mlir::Value streamValue; if (stream) streamValue = fir::getBase( @@ -3444,7 +3493,8 @@ private: if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>( assign.rhs)) { // rhs is null(). rhs being null(pptr) is handled in genNull. - auto boxTy{Fortran::lower::getUntypedBoxProcType(&getMLIRContext())}; + auto boxTy{ + Fortran::lower::getUntypedBoxProcType(builder->getContext())}; hlfir::Entity rhs( fir::factory::createNullBoxProc(*builder, loc, boxTy)); builder->createStoreWithConvert(loc, rhs, lhs); @@ -3660,11 +3710,40 @@ private: return false; } + static void genCUDADataTransfer(fir::FirOpBuilder &builder, + mlir::Location loc, bool lhsIsDevice, + hlfir::Entity &lhs, bool rhsIsDevice, + hlfir::Entity &rhs) { + if (rhs.isBoxAddressOrValue() || lhs.isBoxAddressOrValue()) + TODO(loc, "CUDA data transfler with descriptors"); + if (lhsIsDevice && !rhsIsDevice) { + auto transferKindAttr = fir::CUDADataTransferKindAttr::get( + builder.getContext(), fir::CUDADataTransferKind::HostDevice); + // device = host + if (!rhs.isVariable()) { + auto associate = hlfir::genAssociateExpr( + loc, builder, rhs, rhs.getType(), ".cuf_host_tmp"); + builder.create<fir::CUDADataTransferOp>(loc, associate.getBase(), lhs, + transferKindAttr); + builder.create<hlfir::EndAssociateOp>(loc, associate); + } else { + builder.create<fir::CUDADataTransferOp>(loc, rhs, lhs, + transferKindAttr); + } + return; + } + TODO(loc, "Assignement with CUDA Fortran variables"); + } + void genDataAssignment( const Fortran::evaluate::Assignment &assign, const Fortran::evaluate::ProcedureRef *userDefinedAssignment) { mlir::Location loc = getCurrentLocation(); fir::FirOpBuilder &builder = getFirOpBuilder(); + + bool lhsIsDevice = Fortran::evaluate::HasCUDAAttrs(assign.lhs); + bool rhsIsDevice = Fortran::evaluate::HasCUDAAttrs(assign.rhs); + // Gather some information about the assignment that will impact how it is // lowered. const bool isWholeAllocatableAssignment = @@ -3721,9 +3800,13 @@ private: Fortran::lower::StatementContext localStmtCtx; hlfir::Entity rhs = evaluateRhs(localStmtCtx); hlfir::Entity lhs = evaluateLhs(localStmtCtx); - builder.create<hlfir::AssignOp>(loc, rhs, lhs, - isWholeAllocatableAssignment, - keepLhsLengthInAllocatableAssignment); + if (lhsIsDevice || rhsIsDevice) { + genCUDADataTransfer(builder, loc, lhsIsDevice, lhs, rhsIsDevice, rhs); + } else { + builder.create<hlfir::AssignOp>(loc, rhs, lhs, + isWholeAllocatableAssignment, + keepLhsLengthInAllocatableAssignment); + } return; } // Assignments inside Forall, Where, or assignments to a vector subscripted @@ -3944,11 +4027,12 @@ private: sym->Rank() == 0) { // get the corresponding Cray pointer - auto ptrSym = Fortran::lower::getCrayPointer(*sym); + const Fortran::semantics::Symbol &ptrSym = + Fortran::semantics::GetCrayPointer(*sym); fir::ExtendedValue ptr = getSymbolExtendedValue(ptrSym, nullptr); mlir::Value ptrVal = fir::getBase(ptr); - mlir::Type ptrTy = genType(*ptrSym); + mlir::Type ptrTy = genType(ptrSym); fir::ExtendedValue pte = getSymbolExtendedValue(*sym, nullptr); @@ -4490,7 +4574,8 @@ private: llvm::dbgs() << "\n"); Fortran::lower::CalleeInterface callee(funit, *this); mlir::func::FuncOp func = callee.addEntryBlockAndMapArguments(); - builder = new fir::FirOpBuilder(func, bridge.getKindMap()); + builder = + new fir::FirOpBuilder(func, bridge.getKindMap(), &mlirSymbolTable); assert(builder && "FirOpBuilder did not instantiate"); builder->setFastMathFlags(bridge.getLoweringOptions().getMathOptions()); builder->setInsertionPointToStart(&func.front()); @@ -4758,12 +4843,14 @@ private: // FIXME: get rid of the bogus function context and instantiate the // globals directly into the module. mlir::MLIRContext *context = &getMLIRContext(); + mlir::SymbolTable *symbolTable = getMLIRSymbolTable(); mlir::func::FuncOp func = fir::FirOpBuilder::createFunction( mlir::UnknownLoc::get(context), getModuleOp(), fir::NameUniquer::doGenerated("Sham"), - mlir::FunctionType::get(context, std::nullopt, std::nullopt)); + mlir::FunctionType::get(context, std::nullopt, std::nullopt), + symbolTable); func.addEntryBlock(); - builder = new fir::FirOpBuilder(func, bridge.getKindMap()); + builder = new fir::FirOpBuilder(func, bridge.getKindMap(), symbolTable); assert(builder && "FirOpBuilder did not instantiate"); builder->setFastMathFlags(bridge.getLoweringOptions().getMathOptions()); createGlobals(); @@ -5255,6 +5342,11 @@ private: /// utilities to deal with procedure pointer components whose arguments have /// the type of the containing derived type. Fortran::lower::TypeConstructionStack typeConstructionStack; + /// MLIR symbol table of the fir.global/func.func operations. Note that it is + /// not guaranteed to contain all operations of the ModuleOp with Symbol + /// attribute since mlirSymbolTable must pro-actively be maintained when + /// new Symbol operations are created. + mlir::SymbolTable mlirSymbolTable; }; } // namespace diff --git a/flang/lib/Lower/CMakeLists.txt b/flang/lib/Lower/CMakeLists.txt index 5577a60f1daeac980838fd544ef6fdf411b2f5a8..f92d1a2bc7de185af65dc825e8c0660327071877 100644 --- a/flang/lib/Lower/CMakeLists.txt +++ b/flang/lib/Lower/CMakeLists.txt @@ -25,6 +25,7 @@ add_flang_library(FortranLower Mangler.cpp OpenACC.cpp OpenMP/ClauseProcessor.cpp + OpenMP/Clauses.cpp OpenMP/DataSharingProcessor.cpp OpenMP/OpenMP.cpp OpenMP/ReductionProcessor.cpp diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp index 6b71aabf7fdc89ce7aa30f387d27794929f566e6..29cdb3cff589ba614cb3cdf0405e39d1a74c4dbc 100644 --- a/flang/lib/Lower/CallInterface.cpp +++ b/flang/lib/Lower/CallInterface.cpp @@ -310,21 +310,22 @@ bool Fortran::lower::CallerInterface::verifyActualInputs() const { return true; } -void Fortran::lower::CallerInterface::walkResultLengths( - ExprVisitor visitor) const { - assert(characteristic && "characteristic was not computed"); - const Fortran::evaluate::characteristics::FunctionResult &result = - characteristic->functionResult.value(); - const Fortran::evaluate::characteristics::TypeAndShape *typeAndShape = - result.GetTypeAndShape(); - assert(typeAndShape && "no result type"); - Fortran::evaluate::DynamicType dynamicType = typeAndShape->type(); - // Visit result length specification expressions that are explicit. +mlir::Value +Fortran::lower::CallerInterface::getInput(const PassedEntity &passedEntity) { + return actualInputs[passedEntity.firArgument]; +} + +static void walkLengths( + const Fortran::evaluate::characteristics::TypeAndShape &typeAndShape, + const Fortran::lower::CallerInterface::ExprVisitor &visitor, + Fortran::lower::AbstractConverter &converter) { + Fortran::evaluate::DynamicType dynamicType = typeAndShape.type(); + // Visit length specification expressions that are explicit. if (dynamicType.category() == Fortran::common::TypeCategory::Character) { if (std::optional<Fortran::evaluate::ExtentExpr> length = dynamicType.GetCharLength()) - visitor(toEvExpr(*length)); - } else if (dynamicType.category() == common::TypeCategory::Derived && + visitor(toEvExpr(*length), /*assumedSize=*/false); + } else if (dynamicType.category() == Fortran::common::TypeCategory::Derived && !dynamicType.IsUnlimitedPolymorphic()) { const Fortran::semantics::DerivedTypeSpec &derivedTypeSpec = dynamicType.GetDerivedTypeSpec(); @@ -334,11 +335,33 @@ void Fortran::lower::CallerInterface::walkResultLengths( } } +void Fortran::lower::CallerInterface::walkResultLengths( + const ExprVisitor &visitor) const { + assert(characteristic && "characteristic was not computed"); + const Fortran::evaluate::characteristics::FunctionResult &result = + characteristic->functionResult.value(); + const Fortran::evaluate::characteristics::TypeAndShape *typeAndShape = + result.GetTypeAndShape(); + assert(typeAndShape && "no result type"); + return walkLengths(*typeAndShape, visitor, converter); +} + +void Fortran::lower::CallerInterface::walkDummyArgumentLengths( + const PassedEntity &passedEntity, const ExprVisitor &visitor) const { + if (!passedEntity.characteristics) + return; + if (const auto *dummy = + std::get_if<Fortran::evaluate::characteristics::DummyDataObject>( + &passedEntity.characteristics->u)) + walkLengths(dummy->type, visitor, converter); +} + // Compute extent expr from shapeSpec of an explicit shape. -// TODO: Allow evaluate shape analysis to work in a mode where it disregards -// the non-constant aspects when building the shape to avoid having this here. static Fortran::evaluate::ExtentExpr getExtentExpr(const Fortran::semantics::ShapeSpec &shapeSpec) { + if (shapeSpec.ubound().isStar()) + // F'2023 18.5.3 point 5. + return Fortran::evaluate::ExtentExpr{-1}; const auto &ubound = shapeSpec.ubound().GetExplicit(); const auto &lbound = shapeSpec.lbound().GetExplicit(); assert(lbound && ubound && "shape must be explicit"); @@ -346,20 +369,27 @@ getExtentExpr(const Fortran::semantics::ShapeSpec &shapeSpec) { Fortran::evaluate::ExtentExpr{1}; } +static void +walkExtents(const Fortran::semantics::Symbol &symbol, + const Fortran::lower::CallerInterface::ExprVisitor &visitor) { + if (const auto *objectDetails = + symbol.detailsIf<Fortran::semantics::ObjectEntityDetails>()) + if (objectDetails->shape().IsExplicitShape() || + Fortran::semantics::IsAssumedSizeArray(symbol)) + for (const Fortran::semantics::ShapeSpec &shapeSpec : + objectDetails->shape()) + visitor(Fortran::evaluate::AsGenericExpr(getExtentExpr(shapeSpec)), + /*assumedSize=*/shapeSpec.ubound().isStar()); +} + void Fortran::lower::CallerInterface::walkResultExtents( - ExprVisitor visitor) const { + const ExprVisitor &visitor) const { // Walk directly the result symbol shape (the characteristic shape may contain // descriptor inquiries to it that would fail to lower on the caller side). const Fortran::semantics::SubprogramDetails *interfaceDetails = getInterfaceDetails(); if (interfaceDetails) { - const Fortran::semantics::Symbol &result = interfaceDetails->result(); - if (const auto *objectDetails = - result.detailsIf<Fortran::semantics::ObjectEntityDetails>()) - if (objectDetails->shape().IsExplicitShape()) - for (const Fortran::semantics::ShapeSpec &shapeSpec : - objectDetails->shape()) - visitor(Fortran::evaluate::AsGenericExpr(getExtentExpr(shapeSpec))); + walkExtents(interfaceDetails->result(), visitor); } else { if (procRef.Rank() != 0) fir::emitFatalError( @@ -368,7 +398,18 @@ void Fortran::lower::CallerInterface::walkResultExtents( } } -bool Fortran::lower::CallerInterface::mustMapInterfaceSymbols() const { +void Fortran::lower::CallerInterface::walkDummyArgumentExtents( + const PassedEntity &passedEntity, const ExprVisitor &visitor) const { + const Fortran::semantics::SubprogramDetails *interfaceDetails = + getInterfaceDetails(); + if (!interfaceDetails) + return; + const Fortran::semantics::Symbol *dummy = getDummySymbol(passedEntity); + assert(dummy && "dummy symbol was not set"); + walkExtents(*dummy, visitor); +} + +bool Fortran::lower::CallerInterface::mustMapInterfaceSymbolsForResult() const { assert(characteristic && "characteristic was not computed"); const std::optional<Fortran::evaluate::characteristics::FunctionResult> &result = characteristic->functionResult; @@ -376,7 +417,7 @@ bool Fortran::lower::CallerInterface::mustMapInterfaceSymbols() const { !getInterfaceDetails() || result->IsProcedurePointer()) return false; bool allResultSpecExprConstant = true; - auto visitor = [&](const Fortran::lower::SomeExpr &e) { + auto visitor = [&](const Fortran::lower::SomeExpr &e, bool) { allResultSpecExprConstant &= Fortran::evaluate::IsConstantExpr(e); }; walkResultLengths(visitor); @@ -384,6 +425,17 @@ bool Fortran::lower::CallerInterface::mustMapInterfaceSymbols() const { return !allResultSpecExprConstant; } +bool Fortran::lower::CallerInterface::mustMapInterfaceSymbolsForDummyArgument( + const PassedEntity &arg) const { + bool allResultSpecExprConstant = true; + auto visitor = [&](const Fortran::lower::SomeExpr &e, bool) { + allResultSpecExprConstant &= Fortran::evaluate::IsConstantExpr(e); + }; + walkDummyArgumentLengths(arg, visitor); + walkDummyArgumentExtents(arg, visitor); + return !allResultSpecExprConstant; +} + mlir::Value Fortran::lower::CallerInterface::getArgumentValue( const semantics::Symbol &sym) const { mlir::Location loc = converter.getCurrentLocation(); @@ -401,6 +453,24 @@ mlir::Value Fortran::lower::CallerInterface::getArgumentValue( return actualInputs[mlirArgIndex]; } +const Fortran::semantics::Symbol * +Fortran::lower::CallerInterface::getDummySymbol( + const PassedEntity &passedEntity) const { + const Fortran::semantics::SubprogramDetails *ifaceDetails = + getInterfaceDetails(); + if (!ifaceDetails) + return nullptr; + std::size_t argPosition = 0; + for (const auto &arg : getPassedArguments()) { + if (&arg == &passedEntity) + break; + ++argPosition; + } + if (argPosition >= ifaceDetails->dummyArgs().size()) + return nullptr; + return ifaceDetails->dummyArgs()[argPosition]; +} + mlir::Type Fortran::lower::CallerInterface::getResultStorageType() const { if (passedResult) return fir::dyn_cast_ptrEleTy(inputs[passedResult->firArgument].type); @@ -408,6 +478,11 @@ mlir::Type Fortran::lower::CallerInterface::getResultStorageType() const { return outputs[0].type; } +mlir::Type Fortran::lower::CallerInterface::getDummyArgumentType( + const PassedEntity &passedEntity) const { + return inputs[passedEntity.firArgument].type; +} + const Fortran::semantics::Symbol & Fortran::lower::CallerInterface::getResultSymbol() const { mlir::Location loc = converter.getCurrentLocation(); @@ -592,11 +667,13 @@ void Fortran::lower::CallInterface<T>::declare() { if (!side().isIndirectCall()) { std::string name = side().getMangledName(); mlir::ModuleOp module = converter.getModuleOp(); - func = fir::FirOpBuilder::getNamedFunction(module, name); + mlir::SymbolTable *symbolTable = converter.getMLIRSymbolTable(); + func = fir::FirOpBuilder::getNamedFunction(module, symbolTable, name); if (!func) { mlir::Location loc = side().getCalleeLocation(); mlir::FunctionType ty = genFunctionType(); - func = fir::FirOpBuilder::createFunction(loc, module, name, ty); + func = + fir::FirOpBuilder::createFunction(loc, module, name, ty, symbolTable); if (const Fortran::semantics::Symbol *sym = side().getProcedureSymbol()) { if (side().isMainProgram()) { func->setAttr(fir::getSymbolAttrName(), @@ -975,12 +1052,6 @@ private: Fortran::common::TypeCategory cat = dynamicType.category(); // DERIVED if (cat == Fortran::common::TypeCategory::Derived) { - // TODO is kept under experimental flag until feature is complete. - if (dynamicType.IsPolymorphic() && - !getConverter().getLoweringOptions().getPolymorphicTypeImpl()) - TODO(interface.converter.getCurrentLocation(), - "support for polymorphic types"); - if (dynamicType.IsUnlimitedPolymorphic()) return mlir::NoneType::get(&mlirContext); return getConverter().genType(dynamicType.GetDerivedTypeSpec()); @@ -1387,6 +1458,17 @@ bool Fortran::lower::CallInterface< return Fortran::semantics::IsFinalizable(*derived); } +template <typename T> +bool Fortran::lower::CallInterface< + T>::PassedEntity::isSequenceAssociatedDescriptor() const { + if (!characteristics || passBy != PassEntityBy::Box) + return false; + const auto *dummy = + std::get_if<Fortran::evaluate::characteristics::DummyDataObject>( + &characteristics->u); + return dummy && dummy->type.CanBeSequenceAssociated(); +} + template <typename T> void Fortran::lower::CallInterface<T>::determineInterface( bool isImplicit, @@ -1564,7 +1646,8 @@ mlir::func::FuncOp Fortran::lower::getOrDeclareFunction( Fortran::lower::AbstractConverter &converter) { mlir::ModuleOp module = converter.getModuleOp(); std::string name = getProcMangledName(proc, converter); - mlir::func::FuncOp func = fir::FirOpBuilder::getNamedFunction(module, name); + mlir::func::FuncOp func = fir::FirOpBuilder::getNamedFunction( + module, converter.getMLIRSymbolTable(), name); if (func) return func; diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp index 6e3ce101ef1af95102279569e5a3b13c5c6a087f..6eba243c237cf2a371b6b6d18cad9432b4ebe4bc 100644 --- a/flang/lib/Lower/ConvertCall.cpp +++ b/flang/lib/Lower/ConvertCall.cpp @@ -164,6 +164,125 @@ static mlir::Value readDim3Value(fir::FirOpBuilder &builder, mlir::Location loc, return hlfir::loadTrivialScalar(loc, builder, hlfir::Entity{designate}); } +static mlir::Value remapActualToDummyDescriptor( + mlir::Location loc, Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symMap, + const Fortran::lower::CallerInterface::PassedEntity &arg, + Fortran::lower::CallerInterface &caller, bool isBindcCall) { + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + mlir::IndexType idxTy = builder.getIndexType(); + mlir::Value zero = builder.createIntegerConstant(loc, idxTy, 0); + Fortran::lower::StatementContext localStmtCtx; + auto lowerSpecExpr = [&](const auto &expr, + bool isAssumedSizeExtent) -> mlir::Value { + mlir::Value convertExpr = builder.createConvert( + loc, idxTy, fir::getBase(converter.genExprValue(expr, localStmtCtx))); + if (isAssumedSizeExtent) + return convertExpr; + return fir::factory::genMaxWithZero(builder, loc, convertExpr); + }; + bool mapSymbols = caller.mustMapInterfaceSymbolsForDummyArgument(arg); + if (mapSymbols) { + symMap.pushScope(); + const Fortran::semantics::Symbol *sym = caller.getDummySymbol(arg); + assert(sym && "call must have explicit interface to map interface symbols"); + Fortran::lower::mapCallInterfaceSymbolsForDummyArgument(converter, caller, + symMap, *sym); + } + llvm::SmallVector<mlir::Value> extents; + llvm::SmallVector<mlir::Value> lengths; + mlir::Type dummyBoxType = caller.getDummyArgumentType(arg); + mlir::Type dummyBaseType = fir::unwrapPassByRefType(dummyBoxType); + if (dummyBaseType.isa<fir::SequenceType>()) + caller.walkDummyArgumentExtents( + arg, [&](const Fortran::lower::SomeExpr &e, bool isAssumedSizeExtent) { + extents.emplace_back(lowerSpecExpr(e, isAssumedSizeExtent)); + }); + mlir::Value shape; + if (!extents.empty()) { + if (isBindcCall) { + // Preserve zero lower bounds (see F'2023 18.5.3). + llvm::SmallVector<mlir::Value> lowerBounds(extents.size(), zero); + shape = builder.genShape(loc, lowerBounds, extents); + } else { + shape = builder.genShape(loc, extents); + } + } + + hlfir::Entity explicitArgument = hlfir::Entity{caller.getInput(arg)}; + mlir::Type dummyElementType = fir::unwrapSequenceType(dummyBaseType); + if (auto recType = llvm::dyn_cast<fir::RecordType>(dummyElementType)) + if (recType.getNumLenParams() > 0) + TODO(loc, "sequence association of length parameterized derived type " + "dummy arguments"); + if (fir::isa_char(dummyElementType)) + lengths.emplace_back(hlfir::genCharLength(loc, builder, explicitArgument)); + mlir::Value baseAddr = + hlfir::genVariableRawAddress(loc, builder, explicitArgument); + baseAddr = builder.createConvert(loc, fir::ReferenceType::get(dummyBaseType), + baseAddr); + mlir::Value mold; + if (fir::isPolymorphicType(dummyBoxType)) + mold = explicitArgument; + mlir::Value remapped = + builder.create<fir::EmboxOp>(loc, dummyBoxType, baseAddr, shape, + /*slice=*/mlir::Value{}, lengths, mold); + if (mapSymbols) + symMap.popScope(); + return remapped; +} + +/// Create a descriptor for sequenced associated descriptor that are passed +/// by descriptor. Sequence association (F'2023 15.5.2.12) implies that the +/// dummy shape and rank need to not be the same as the actual argument. This +/// helper creates a descriptor based on the dummy shape and rank (sequence +/// association can only happen with explicit and assumed-size array) so that it +/// is safe to assume the rank of the incoming descriptor inside the callee. +/// This helper must be called once all the actual arguments have been lowered +/// and placed inside "caller". Copy-in/copy-out must already have been +/// generated if needed using the actual argument shape (the dummy shape may be +/// assumed-size). +static void remapActualToDummyDescriptors( + mlir::Location loc, Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symMap, + const Fortran::lower::PreparedActualArguments &loweredActuals, + Fortran::lower::CallerInterface &caller, bool isBindcCall) { + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + for (auto [preparedActual, arg] : + llvm::zip(loweredActuals, caller.getPassedArguments())) { + if (arg.isSequenceAssociatedDescriptor()) { + if (!preparedActual.value().handleDynamicOptional()) { + mlir::Value remapped = remapActualToDummyDescriptor( + loc, converter, symMap, arg, caller, isBindcCall); + caller.placeInput(arg, remapped); + } else { + // Absent optional actual argument descriptor cannot be read and + // remapped unconditionally. + mlir::Type dummyType = caller.getDummyArgumentType(arg); + mlir::Value isPresent = preparedActual.value().getIsPresent(); + auto &argLambdaCapture = arg; + mlir::Value remapped = + builder + .genIfOp(loc, {dummyType}, isPresent, + /*withElseRegion=*/true) + .genThen([&]() { + mlir::Value newBox = remapActualToDummyDescriptor( + loc, converter, symMap, argLambdaCapture, caller, + isBindcCall); + builder.create<fir::ResultOp>(loc, newBox); + }) + .genElse([&]() { + mlir::Value absent = + builder.create<fir::AbsentOp>(loc, dummyType); + builder.create<fir::ResultOp>(loc, absent); + }) + .getResults()[0]; + caller.placeInput(arg, remapped); + } + } + } +} + std::pair<fir::ExtendedValue, bool> Fortran::lower::genCallOpAndResult( mlir::Location loc, Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx, @@ -171,12 +290,11 @@ std::pair<fir::ExtendedValue, bool> Fortran::lower::genCallOpAndResult( std::optional<mlir::Type> resultType, bool isElemental) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); using PassBy = Fortran::lower::CallerInterface::PassEntityBy; - // Handle cases where caller must allocate the result or a fir.box for it. bool mustPopSymMap = false; - if (caller.mustMapInterfaceSymbols()) { + if (caller.mustMapInterfaceSymbolsForResult()) { symMap.pushScope(); mustPopSymMap = true; - Fortran::lower::mapCallInterfaceSymbols(converter, caller, symMap); + Fortran::lower::mapCallInterfaceSymbolsForResult(converter, caller, symMap); } // If this is an indirect call, retrieve the function address. Also retrieve // the result length if this is a character function (note that this length @@ -221,12 +339,16 @@ std::pair<fir::ExtendedValue, bool> Fortran::lower::genCallOpAndResult( return {}; mlir::Type type = caller.getResultStorageType(); if (type.isa<fir::SequenceType>()) - caller.walkResultExtents([&](const Fortran::lower::SomeExpr &e) { - extents.emplace_back(lowerSpecExpr(e)); - }); - caller.walkResultLengths([&](const Fortran::lower::SomeExpr &e) { - lengths.emplace_back(lowerSpecExpr(e)); - }); + caller.walkResultExtents( + [&](const Fortran::lower::SomeExpr &e, bool isAssumedSizeExtent) { + assert(!isAssumedSizeExtent && "result cannot be assumed-size"); + extents.emplace_back(lowerSpecExpr(e)); + }); + caller.walkResultLengths( + [&](const Fortran::lower::SomeExpr &e, bool isAssumedSizeExtent) { + assert(!isAssumedSizeExtent && "result cannot be assumed-size"); + lengths.emplace_back(lowerSpecExpr(e)); + }); // Result length parameters should not be provided to box storage // allocation and save_results, but they are still useful information to @@ -416,7 +538,7 @@ std::pair<fir::ExtendedValue, bool> Fortran::lower::genCallOpAndResult( mlir::Type i32Ty = builder.getI32Type(); mlir::Value one = builder.createIntegerConstant(loc, i32Ty, 1); - mlir::Value grid_x, grid_y; + mlir::Value grid_x, grid_y, grid_z; if (caller.getCallDescription().chevrons()[0].GetType()->category() == Fortran::common::TypeCategory::Integer) { // If grid is an integer, it is converted to dim3(grid,1,1). Since z is @@ -426,11 +548,13 @@ std::pair<fir::ExtendedValue, bool> Fortran::lower::genCallOpAndResult( fir::getBase(converter.genExprValue( caller.getCallDescription().chevrons()[0], stmtCtx))); grid_y = one; + grid_z = one; } else { auto dim3Addr = converter.genExprAddr( caller.getCallDescription().chevrons()[0], stmtCtx); grid_x = readDim3Value(builder, loc, fir::getBase(dim3Addr), "x"); grid_y = readDim3Value(builder, loc, fir::getBase(dim3Addr), "y"); + grid_z = readDim3Value(builder, loc, fir::getBase(dim3Addr), "z"); } mlir::Value block_x, block_y, block_z; @@ -466,8 +590,8 @@ std::pair<fir::ExtendedValue, bool> Fortran::lower::genCallOpAndResult( caller.getCallDescription().chevrons()[3], stmtCtx))); builder.create<fir::CUDAKernelLaunch>( - loc, funcType.getResults(), funcSymbolAttr, grid_x, grid_y, block_x, - block_y, block_z, bytes, stream, operands); + loc, funcType.getResults(), funcSymbolAttr, grid_x, grid_y, grid_z, + block_x, block_y, block_z, bytes, stream, operands); callNumResults = 0; } else if (caller.requireDispatchCall()) { // Procedure call requiring a dynamic dispatch. Call is created with @@ -1054,10 +1178,16 @@ static PreparedDummyArgument preparePresentUserCallActualArgument( // Create dummy type with actual argument rank when the dummy is an assumed // rank. That way, all the operation to create dummy descriptors are ranked if // the actual argument is ranked, which allows simple code generation. + // Also do the same when the dummy is a sequence associated descriptor + // because the actual shape/rank may mismatch with the dummy, and the dummy + // may be an assumed-size array, so any descriptor manipulation should use the + // actual argument shape information. A descriptor with the dummy shape + // information will be created later when all actual arguments are ready. mlir::Type dummyTypeWithActualRank = dummyType; if (auto baseBoxDummy = mlir::dyn_cast<fir::BaseBoxType>(dummyType)) if (baseBoxDummy.isAssumedRank() || - arg.testTKR(Fortran::common::IgnoreTKR::Rank)) + arg.testTKR(Fortran::common::IgnoreTKR::Rank) || + arg.isSequenceAssociatedDescriptor()) dummyTypeWithActualRank = baseBoxDummy.getBoxTypeWithNewShape(actual.getType()); // Preserve the actual type in the argument preparation in case IgnoreTKR(t) @@ -1340,6 +1470,7 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals, mlir::FunctionType callSiteType, CallContext &callContext) { using PassBy = Fortran::lower::CallerInterface::PassEntityBy; mlir::Location loc = callContext.loc; + bool mustRemapActualToDummyDescriptors = false; fir::FirOpBuilder &builder = callContext.getBuilder(); llvm::SmallVector<CallCleanUp> callCleanUps; for (auto [preparedActual, arg] : @@ -1396,6 +1527,9 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals, callCleanUps.append(preparedDummy.cleanups.rbegin(), preparedDummy.cleanups.rend()); caller.placeInput(arg, preparedDummy.dummy); + if (arg.passBy == PassBy::Box) + mustRemapActualToDummyDescriptors |= + arg.isSequenceAssociatedDescriptor(); } break; case PassBy::BoxProcRef: { PreparedDummyArgument preparedDummy = @@ -1488,6 +1622,12 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals, } break; } } + // Handle cases where caller must allocate the result or a fir.box for it. + if (mustRemapActualToDummyDescriptors) + remapActualToDummyDescriptors(loc, callContext.converter, + callContext.symMap, loweredActuals, caller, + callContext.isBindcCall()); + // Prepare lowered arguments according to the interface // and map the lowered values to the dummy // arguments. diff --git a/flang/lib/Lower/ConvertConstant.cpp b/flang/lib/Lower/ConvertConstant.cpp index 336944d35b7e4a44e5a1a103fda90a22bbb48983..ed389bbe4ae5edbf76d6db059699a235b96396e0 100644 --- a/flang/lib/Lower/ConvertConstant.cpp +++ b/flang/lib/Lower/ConvertConstant.cpp @@ -14,9 +14,12 @@ #include "flang/Evaluate/expression.h" #include "flang/Lower/AbstractConverter.h" #include "flang/Lower/BuiltinModules.h" +#include "flang/Lower/ConvertExprToHLFIR.h" #include "flang/Lower/ConvertType.h" #include "flang/Lower/ConvertVariable.h" #include "flang/Lower/Mangler.h" +#include "flang/Lower/StatementContext.h" +#include "flang/Lower/SymbolMap.h" #include "flang/Optimizer/Builder/Complex.h" #include "flang/Optimizer/Builder/MutableBox.h" #include "flang/Optimizer/Builder/Todo.h" @@ -380,10 +383,21 @@ static mlir::Value genStructureComponentInit( } if (Fortran::semantics::IsPointer(sym)) { - if (Fortran::semantics::IsProcedure(sym)) - TODO(loc, "procedure pointer component initial value"); - mlir::Value initialTarget = - Fortran::lower::genInitialDataTarget(converter, loc, componentTy, expr); + mlir::Value initialTarget; + if (Fortran::semantics::IsProcedure(sym)) { + if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>(expr)) + initialTarget = + fir::factory::createNullBoxProc(builder, loc, componentTy); + else { + Fortran::lower::SymMap globalOpSymMap; + Fortran::lower::StatementContext stmtCtx; + auto box{getBase(Fortran::lower::convertExprToAddress( + loc, converter, expr, globalOpSymMap, stmtCtx))}; + initialTarget = builder.createConvert(loc, componentTy, box); + } + } else + initialTarget = Fortran::lower::genInitialDataTarget(converter, loc, + componentTy, expr); res = builder.create<fir::InsertValueOp>( loc, recTy, res, initialTarget, builder.getArrayAttr(field.getAttributes())); diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp index d157db2cde49612e3049a266bb40b3bd9b6aa83d..fb7807718ff888a005affda6d354d701d774bbd6 100644 --- a/flang/lib/Lower/ConvertExpr.cpp +++ b/flang/lib/Lower/ConvertExpr.cpp @@ -862,7 +862,8 @@ public: addr); } else if (sym->test(Fortran::semantics::Symbol::Flag::CrayPointee)) { // get the corresponding Cray pointer - auto ptrSym = Fortran::lower::getCrayPointer(sym); + Fortran::semantics::SymbolRef ptrSym{ + Fortran::semantics::GetCrayPointer(sym)}; ExtValue ptr = gen(ptrSym); mlir::Value ptrVal = fir::getBase(ptr); mlir::Type ptrTy = converter.genType(*ptrSym); @@ -1537,8 +1538,8 @@ public: auto baseSym = getFirstSym(aref); if (baseSym.test(Fortran::semantics::Symbol::Flag::CrayPointee)) { // get the corresponding Cray pointer - auto ptrSym = Fortran::lower::getCrayPointer(baseSym); - + Fortran::semantics::SymbolRef ptrSym{ + Fortran::semantics::GetCrayPointer(baseSym)}; fir::ExtendedValue ptr = gen(ptrSym); mlir::Value ptrVal = fir::getBase(ptr); mlir::Type ptrTy = ptrVal.getType(); @@ -6946,7 +6947,8 @@ private: ComponentPath &components) { mlir::Value ptrVal = nullptr; if (x.test(Fortran::semantics::Symbol::Flag::CrayPointee)) { - auto ptrSym = Fortran::lower::getCrayPointer(x); + Fortran::semantics::SymbolRef ptrSym{ + Fortran::semantics::GetCrayPointer(x)}; ExtValue ptr = converter.getSymbolExtendedValue(ptrSym); ptrVal = fir::getBase(ptr); } diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp index c5bfbdf6b8c115a5e1cc4ce0effbf5d6e07cea8d..6e57b31d022b0b16ddf08e5fc2cf33d94425a3b5 100644 --- a/flang/lib/Lower/ConvertExprToHLFIR.cpp +++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp @@ -130,7 +130,8 @@ public: // shape is deferred and should not be loaded now to preserve // pointer/allocatable aspects. if (componentSym.Rank() == 0 || - Fortran::semantics::IsAllocatableOrObjectPointer(&componentSym)) + Fortran::semantics::IsAllocatableOrObjectPointer(&componentSym) || + Fortran::semantics::IsProcedurePointer(&componentSym)) return mlir::Value{}; fir::FirOpBuilder &builder = getBuilder(); @@ -284,7 +285,7 @@ private: // value of the Cray pointer variable. fir::FirOpBuilder &builder = getBuilder(); fir::FortranVariableOpInterface ptrVar = - gen(Fortran::lower::getCrayPointer(symbolRef)); + gen(Fortran::semantics::GetCrayPointer(symbolRef)); mlir::Value ptrAddr = ptrVar.getBase(); // Reinterpret the reference to a Cray pointer so that @@ -306,9 +307,16 @@ private: } return *varDef; } + llvm::errs() << *symbolRef << "\n"; TODO(getLoc(), "lowering symbol to HLFIR"); } + fir::FortranVariableOpInterface + gen(const Fortran::semantics::Symbol &symbol) { + Fortran::evaluate::SymbolRef symref{symbol}; + return gen(symref); + } + fir::FortranVariableOpInterface gen(const Fortran::evaluate::Component &component) { if (Fortran::semantics::IsAllocatableOrPointer(component.GetLastSymbol())) @@ -1760,8 +1768,22 @@ private: if (attrs && bitEnumContainsAny(attrs.getFlags(), fir::FortranVariableFlagsEnum::pointer)) { - if (Fortran::semantics::IsProcedure(sym)) - TODO(loc, "procedure pointer component in structure constructor"); + if (Fortran::semantics::IsProcedure(sym)) { + // Procedure pointer components. + if (Fortran::evaluate::UnwrapExpr<Fortran::evaluate::NullPointer>( + expr)) { + auto boxTy{ + Fortran::lower::getUntypedBoxProcType(builder.getContext())}; + hlfir::Entity rhs( + fir::factory::createNullBoxProc(builder, loc, boxTy)); + builder.createStoreWithConvert(loc, rhs, lhs); + continue; + } + hlfir::Entity rhs(getBase(Fortran::lower::convertExprToAddress( + loc, converter, expr, symMap, stmtCtx))); + builder.createStoreWithConvert(loc, rhs, lhs); + continue; + } // Pointer component construction is just a copy of the box contents. fir::ExtendedValue lhsExv = hlfir::translateToExtendedValue(loc, builder, lhs); diff --git a/flang/lib/Lower/ConvertType.cpp b/flang/lib/Lower/ConvertType.cpp index 21564e8b81d70ab548c6c6761f5af36ff0e9d995..e6557d7f0b7675de7ea94763acf60b159631123b 100644 --- a/flang/lib/Lower/ConvertType.cpp +++ b/flang/lib/Lower/ConvertType.cpp @@ -263,10 +263,6 @@ struct TypeBuilderImpl { llvm::SmallVector<Fortran::lower::LenParameterTy> params; translateLenParameters(params, tySpec->category(), ultimate); ty = genFIRType(context, tySpec->category(), kind, params); - } else if (type->IsPolymorphic() && - !converter.getLoweringOptions().getPolymorphicTypeImpl()) { - // TODO is kept under experimental flag until feature is complete. - TODO(loc, "support for polymorphic types"); } else if (type->IsUnlimitedPolymorphic()) { ty = mlir::NoneType::get(context); } else if (const Fortran::semantics::DerivedTypeSpec *tySpec = diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp index a673a18cd20d911c4a555b48af08253737d0c8bd..e07ae42dc7497339c86732e140e412c396ad2de1 100644 --- a/flang/lib/Lower/ConvertVariable.cpp +++ b/flang/lib/Lower/ConvertVariable.cpp @@ -1554,6 +1554,11 @@ fir::FortranVariableFlagsAttr Fortran::lower::translateSymbolAttributes( mlir::MLIRContext *mlirContext, const Fortran::semantics::Symbol &sym, fir::FortranVariableFlagsEnum extraFlags) { fir::FortranVariableFlagsEnum flags = extraFlags; + if (sym.test(Fortran::semantics::Symbol::Flag::CrayPointee)) { + // CrayPointee are represented as pointers. + flags = flags | fir::FortranVariableFlagsEnum::pointer; + return fir::FortranVariableFlagsAttr::get(mlirContext, flags); + } const auto &attrs = sym.attrs(); if (attrs.test(Fortran::semantics::Attr::ALLOCATABLE)) flags = flags | fir::FortranVariableFlagsEnum::allocatable; @@ -1615,8 +1620,6 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter, (!Fortran::semantics::IsProcedure(sym) || Fortran::semantics::IsPointer(sym)) && !sym.detailsIf<Fortran::semantics::CommonBlockDetails>()) { - bool isCrayPointee = - sym.test(Fortran::semantics::Symbol::Flag::CrayPointee); fir::FirOpBuilder &builder = converter.getFirOpBuilder(); const mlir::Location loc = genLocation(converter, sym); mlir::Value shapeOrShift; @@ -1636,31 +1639,21 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter, Fortran::lower::translateSymbolCUDADataAttribute(builder.getContext(), sym); - if (isCrayPointee) { - mlir::Type baseType = - hlfir::getFortranElementOrSequenceType(base.getType()); - if (auto seqType = mlir::dyn_cast<fir::SequenceType>(baseType)) { - // The pointer box's sequence type must be with unknown shape. - llvm::SmallVector<int64_t> shape(seqType.getDimension(), - fir::SequenceType::getUnknownExtent()); - baseType = fir::SequenceType::get(shape, seqType.getEleTy()); - } - fir::BoxType ptrBoxType = - fir::BoxType::get(fir::PointerType::get(baseType)); + if (sym.test(Fortran::semantics::Symbol::Flag::CrayPointee)) { + mlir::Type ptrBoxType = + Fortran::lower::getCrayPointeeBoxType(base.getType()); mlir::Value boxAlloc = builder.createTemporary(loc, ptrBoxType); // Declare a local pointer variable. - attributes = fir::FortranVariableFlagsAttr::get( - builder.getContext(), fir::FortranVariableFlagsEnum::pointer); auto newBase = builder.create<hlfir::DeclareOp>( loc, boxAlloc, name, /*shape=*/nullptr, lenParams, attributes); - mlir::Value nullAddr = - builder.createNullConstant(loc, ptrBoxType.getEleTy()); + mlir::Value nullAddr = builder.createNullConstant( + loc, llvm::cast<fir::BaseBoxType>(ptrBoxType).getEleTy()); // If the element type is known-length character, then // EmboxOp does not need the length parameters. if (auto charType = mlir::dyn_cast<fir::CharacterType>( - fir::unwrapSequenceType(baseType))) + hlfir::getFortranElementType(base.getType()))) if (!charType.hasDynamicLen()) lenParams.clear(); @@ -2260,19 +2253,20 @@ void Fortran::lower::instantiateVariable(AbstractConverter &converter, instantiateLocal(converter, var, symMap); } -void Fortran::lower::mapCallInterfaceSymbols( - AbstractConverter &converter, const Fortran::lower::CallerInterface &caller, - SymMap &symMap) { +static void +mapCallInterfaceSymbol(const Fortran::semantics::Symbol &interfaceSymbol, + Fortran::lower::AbstractConverter &converter, + const Fortran::lower::CallerInterface &caller, + Fortran::lower::SymMap &symMap) { Fortran::lower::AggregateStoreMap storeMap; - const Fortran::semantics::Symbol &result = caller.getResultSymbol(); for (Fortran::lower::pft::Variable var : - Fortran::lower::pft::getDependentVariableList(result)) { + Fortran::lower::pft::getDependentVariableList(interfaceSymbol)) { if (var.isAggregateStore()) { instantiateVariable(converter, var, symMap, storeMap); continue; } const Fortran::semantics::Symbol &sym = var.getSymbol(); - if (&sym == &result) + if (&sym == &interfaceSymbol) continue; const auto *hostDetails = sym.detailsIf<Fortran::semantics::HostAssocDetails>(); @@ -2293,7 +2287,8 @@ void Fortran::lower::mapCallInterfaceSymbols( // instantiateVariable that would try to allocate a new storage. continue; } - if (Fortran::semantics::IsDummy(sym) && sym.owner() == result.owner()) { + if (Fortran::semantics::IsDummy(sym) && + sym.owner() == interfaceSymbol.owner()) { // Get the argument for the dummy argument symbols of the current call. symMap.addSymbol(sym, caller.getArgumentValue(sym)); // All the properties of the dummy variable may not come from the actual @@ -2307,6 +2302,19 @@ void Fortran::lower::mapCallInterfaceSymbols( } } +void Fortran::lower::mapCallInterfaceSymbolsForResult( + AbstractConverter &converter, const Fortran::lower::CallerInterface &caller, + SymMap &symMap) { + const Fortran::semantics::Symbol &result = caller.getResultSymbol(); + mapCallInterfaceSymbol(result, converter, caller, symMap); +} + +void Fortran::lower::mapCallInterfaceSymbolsForDummyArgument( + AbstractConverter &converter, const Fortran::lower::CallerInterface &caller, + SymMap &symMap, const Fortran::semantics::Symbol &dummySymbol) { + mapCallInterfaceSymbol(dummySymbol, converter, caller, symMap); +} + void Fortran::lower::mapSymbolAttributes( AbstractConverter &converter, const Fortran::semantics::SymbolRef &symbol, Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx, @@ -2331,16 +2339,13 @@ void Fortran::lower::createRuntimeTypeInfoGlobal( defineGlobal(converter, var, globalName, linkage); } -Fortran::semantics::SymbolRef -Fortran::lower::getCrayPointer(Fortran::semantics::SymbolRef sym) { - assert(!sym->GetUltimate().owner().crayPointers().empty() && - "empty Cray pointer/pointee map"); - for (const auto &[pointee, pointer] : - sym->GetUltimate().owner().crayPointers()) { - if (pointee == sym->name()) { - Fortran::semantics::SymbolRef v{pointer.get()}; - return v; - } +mlir::Type Fortran::lower::getCrayPointeeBoxType(mlir::Type fortranType) { + mlir::Type baseType = hlfir::getFortranElementOrSequenceType(fortranType); + if (auto seqType = mlir::dyn_cast<fir::SequenceType>(baseType)) { + // The pointer box's sequence type must be with unknown shape. + llvm::SmallVector<int64_t> shape(seqType.getDimension(), + fir::SequenceType::getUnknownExtent()); + baseType = fir::SequenceType::get(shape, seqType.getEleTy()); } - llvm_unreachable("corresponding Cray pointer cannot be found"); + return fir::BoxType::get(fir::PointerType::get(baseType)); } diff --git a/flang/lib/Lower/DirectivesCommon.h b/flang/lib/Lower/DirectivesCommon.h index 8d560db34e05bf817213a2649c2a6e20ecdc6a0a..6daa72b84d90d496157d078833c0d8dfa26720d6 100644 --- a/flang/lib/Lower/DirectivesCommon.h +++ b/flang/lib/Lower/DirectivesCommon.h @@ -808,6 +808,75 @@ genBaseBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc, return bounds; } +namespace detail { +template <typename T> // +static T &&AsRvalueRef(T &&t) { + return std::move(t); +} +template <typename T> // +static T AsRvalueRef(T &t) { + return t; +} +template <typename T> // +static T AsRvalueRef(const T &t) { + return t; +} + +// Helper class for stripping enclosing parentheses and a conversion that +// preserves type category. This is used for triplet elements, which are +// always of type integer(kind=8). The lower/upper bounds are converted to +// an "index" type, which is 64-bit, so the explicit conversion to kind=8 +// (if present) is not needed. When it's present, though, it causes generated +// names to contain "int(..., kind=8)". +struct PeelConvert { + template <Fortran::common::TypeCategory Category, int Kind> + static Fortran::semantics::MaybeExpr visit_with_category( + const Fortran::evaluate::Expr<Fortran::evaluate::Type<Category, Kind>> + &expr) { + return std::visit( + [](auto &&s) { return visit_with_category<Category, Kind>(s); }, + expr.u); + } + template <Fortran::common::TypeCategory Category, int Kind> + static Fortran::semantics::MaybeExpr visit_with_category( + const Fortran::evaluate::Convert<Fortran::evaluate::Type<Category, Kind>, + Category> &expr) { + return AsGenericExpr(AsRvalueRef(expr.left())); + } + template <Fortran::common::TypeCategory Category, int Kind, typename T> + static Fortran::semantics::MaybeExpr visit_with_category(const T &) { + return std::nullopt; // + } + template <Fortran::common::TypeCategory Category, typename T> + static Fortran::semantics::MaybeExpr visit_with_category(const T &) { + return std::nullopt; // + } + + template <Fortran::common::TypeCategory Category> + static Fortran::semantics::MaybeExpr + visit(const Fortran::evaluate::Expr<Fortran::evaluate::SomeKind<Category>> + &expr) { + return std::visit([](auto &&s) { return visit_with_category<Category>(s); }, + expr.u); + } + static Fortran::semantics::MaybeExpr + visit(const Fortran::evaluate::Expr<Fortran::evaluate::SomeType> &expr) { + return std::visit([](auto &&s) { return visit(s); }, expr.u); + } + template <typename T> // + static Fortran::semantics::MaybeExpr visit(const T &) { + return std::nullopt; + } +}; + +static Fortran::semantics::SomeExpr +peelOuterConvert(Fortran::semantics::SomeExpr &expr) { + if (auto peeled = PeelConvert::visit(expr)) + return *peeled; + return expr; +} +} // namespace detail + /// Generate bounds operations for an array section when subscripts are /// provided. template <typename BoundsOp, typename BoundsType> @@ -815,7 +884,7 @@ llvm::SmallVector<mlir::Value> genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc, Fortran::lower::AbstractConverter &converter, Fortran::lower::StatementContext &stmtCtx, - const std::list<Fortran::parser::SectionSubscript> &subscripts, + const std::vector<Fortran::evaluate::Subscript> &subscripts, std::stringstream &asFortran, fir::ExtendedValue &dataExv, bool dataExvIsAssumedSize, AddrAndBoundsInfo &info, bool treatIndexAsSection = false) { @@ -828,8 +897,7 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1); const int dataExvRank = static_cast<int>(dataExv.rank()); for (const auto &subscript : subscripts) { - const auto *triplet{ - std::get_if<Fortran::parser::SubscriptTriplet>(&subscript.u)}; + const auto *triplet{std::get_if<Fortran::evaluate::Triplet>(&subscript.u)}; if (triplet || treatIndexAsSection) { if (dimension != 0) asFortran << ','; @@ -868,13 +936,17 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc, strideInBytes = true; } - const Fortran::lower::SomeExpr *lower{nullptr}; + Fortran::semantics::MaybeExpr lower; if (triplet) { - if (const auto &tripletLb{std::get<0>(triplet->t)}) - lower = Fortran::semantics::GetExpr(*tripletLb); + lower = Fortran::evaluate::AsGenericExpr(triplet->lower()); } else { - const auto &index{std::get<Fortran::parser::IntExpr>(subscript.u)}; - lower = Fortran::semantics::GetExpr(index); + // Case of IndirectSubscriptIntegerExpr + using IndirectSubscriptIntegerExpr = + Fortran::evaluate::IndirectSubscriptIntegerExpr; + using SubscriptInteger = Fortran::evaluate::SubscriptInteger; + Fortran::evaluate::Expr<SubscriptInteger> oneInt = + std::get<IndirectSubscriptIntegerExpr>(subscript.u).value(); + lower = Fortran::evaluate::AsGenericExpr(std::move(oneInt)); if (lower->Rank() > 0) { mlir::emitError( loc, "vector subscript cannot be used for an array section"); @@ -896,7 +968,7 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc, fir::getBase(converter.genExprValue(loc, *lower, stmtCtx)); lb = builder.createConvert(loc, baseLb.getType(), lb); lbound = builder.create<mlir::arith::SubIOp>(loc, lb, baseLb); - asFortran << lower->AsFortran(); + asFortran << detail::peelOuterConvert(*lower).AsFortran(); } } else { // If the lower bound is not specified, then the section @@ -912,10 +984,11 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc, extent = one; } else { asFortran << ':'; - const auto &upper{std::get<1>(triplet->t)}; + Fortran::semantics::MaybeExpr upper = + Fortran::evaluate::AsGenericExpr(triplet->upper()); if (upper) { - uval = Fortran::semantics::GetIntValue(upper); + uval = Fortran::evaluate::ToInt64(*upper); if (uval) { if (defaultLb) { ubound = builder.createIntegerConstant(loc, idxTy, *uval - 1); @@ -925,22 +998,21 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc, } asFortran << *uval; } else { - const Fortran::lower::SomeExpr *uexpr = - Fortran::semantics::GetExpr(*upper); mlir::Value ub = - fir::getBase(converter.genExprValue(loc, *uexpr, stmtCtx)); + fir::getBase(converter.genExprValue(loc, *upper, stmtCtx)); ub = builder.createConvert(loc, baseLb.getType(), ub); ubound = builder.create<mlir::arith::SubIOp>(loc, ub, baseLb); - asFortran << uexpr->AsFortran(); + asFortran << detail::peelOuterConvert(*upper).AsFortran(); } } if (lower && upper) { if (lval && uval && *uval < *lval) { mlir::emitError(loc, "zero sized array section"); break; - } else if (std::get<2>(triplet->t)) { - const auto &strideExpr{std::get<2>(triplet->t)}; - if (strideExpr) { + } else { + // Stride is mandatory in evaluate::Triplet. Make sure it's 1. + auto val = Fortran::evaluate::ToInt64(triplet->GetStride()); + if (!val || *val != 1) { mlir::emitError(loc, "stride cannot be specified on " "an array section"); break; @@ -993,150 +1065,157 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc, return bounds; } -template <typename ObjectType, typename BoundsOp, typename BoundsType> +namespace detail { +template <typename Ref, typename Expr> // +std::optional<Ref> getRef(Expr &&expr) { + if constexpr (std::is_same_v<llvm::remove_cvref_t<Expr>, + Fortran::evaluate::DataRef>) { + if (auto *ref = std::get_if<Ref>(&expr.u)) + return *ref; + return std::nullopt; + } else { + auto maybeRef = Fortran::evaluate::ExtractDataRef(expr); + if (!maybeRef || !std::holds_alternative<Ref>(maybeRef->u)) + return std::nullopt; + return std::get<Ref>(maybeRef->u); + } +} +} // namespace detail + +template <typename BoundsOp, typename BoundsType> AddrAndBoundsInfo gatherDataOperandAddrAndBounds( Fortran::lower::AbstractConverter &converter, fir::FirOpBuilder &builder, - Fortran::semantics::SemanticsContext &semanticsContext, - Fortran::lower::StatementContext &stmtCtx, const ObjectType &object, + semantics::SemanticsContext &semaCtx, + Fortran::lower::StatementContext &stmtCtx, + Fortran::semantics::SymbolRef symbol, + const Fortran::semantics::MaybeExpr &maybeDesignator, mlir::Location operandLocation, std::stringstream &asFortran, llvm::SmallVector<mlir::Value> &bounds, bool treatIndexAsSection = false) { + using namespace Fortran; + AddrAndBoundsInfo info; - std::visit( - Fortran::common::visitors{ - [&](const Fortran::parser::Designator &designator) { - if (auto expr{Fortran::semantics::AnalyzeExpr(semanticsContext, - designator)}) { - if (((*expr).Rank() > 0 || treatIndexAsSection) && - Fortran::parser::Unwrap<Fortran::parser::ArrayElement>( - designator)) { - const auto *arrayElement = - Fortran::parser::Unwrap<Fortran::parser::ArrayElement>( - designator); - const auto *dataRef = - std::get_if<Fortran::parser::DataRef>(&designator.u); - fir::ExtendedValue dataExv; - bool dataExvIsAssumedSize = false; - if (Fortran::parser::Unwrap< - Fortran::parser::StructureComponent>( - arrayElement->base)) { - auto exprBase = Fortran::semantics::AnalyzeExpr( - semanticsContext, arrayElement->base); - dataExv = converter.genExprAddr(operandLocation, *exprBase, - stmtCtx); - info.addr = fir::getBase(dataExv); - info.rawInput = info.addr; - asFortran << (*exprBase).AsFortran(); - } else { - const Fortran::parser::Name &name = - Fortran::parser::GetLastName(*dataRef); - dataExvIsAssumedSize = Fortran::semantics::IsAssumedSizeArray( - name.symbol->GetUltimate()); - info = getDataOperandBaseAddr(converter, builder, - *name.symbol, operandLocation); - dataExv = converter.getSymbolExtendedValue(*name.symbol); - asFortran << name.ToString(); - } - - if (!arrayElement->subscripts.empty()) { - asFortran << '('; - bounds = genBoundsOps<BoundsOp, BoundsType>( - builder, operandLocation, converter, stmtCtx, - arrayElement->subscripts, asFortran, dataExv, - dataExvIsAssumedSize, info, treatIndexAsSection); - } - asFortran << ')'; - } else if (auto structComp = Fortran::parser::Unwrap< - Fortran::parser::StructureComponent>(designator)) { - fir::ExtendedValue compExv = - converter.genExprAddr(operandLocation, *expr, stmtCtx); - info.addr = fir::getBase(compExv); - info.rawInput = info.addr; - if (fir::unwrapRefType(info.addr.getType()) - .isa<fir::SequenceType>()) - bounds = genBaseBoundsOps<BoundsOp, BoundsType>( - builder, operandLocation, converter, compExv, - /*isAssumedSize=*/false); - asFortran << (*expr).AsFortran(); - - bool isOptional = Fortran::semantics::IsOptional( - *Fortran::parser::GetLastName(*structComp).symbol); - if (isOptional) - info.isPresent = builder.create<fir::IsPresentOp>( - operandLocation, builder.getI1Type(), info.rawInput); - - if (auto loadOp = mlir::dyn_cast_or_null<fir::LoadOp>( - info.addr.getDefiningOp())) { - if (fir::isAllocatableType(loadOp.getType()) || - fir::isPointerType(loadOp.getType())) - info.addr = builder.create<fir::BoxAddrOp>(operandLocation, - info.addr); - info.rawInput = info.addr; - } - - // If the component is an allocatable or pointer the result of - // genExprAddr will be the result of a fir.box_addr operation or - // a fir.box_addr has been inserted just before. - // Retrieve the box so we handle it like other descriptor. - if (auto boxAddrOp = mlir::dyn_cast_or_null<fir::BoxAddrOp>( - info.addr.getDefiningOp())) { - info.addr = boxAddrOp.getVal(); - info.rawInput = info.addr; - bounds = genBoundsOpsFromBox<BoundsOp, BoundsType>( - builder, operandLocation, converter, compExv, info); - } - } else { - if (Fortran::parser::Unwrap<Fortran::parser::ArrayElement>( - designator)) { - // Single array element. - const auto *arrayElement = - Fortran::parser::Unwrap<Fortran::parser::ArrayElement>( - designator); - (void)arrayElement; - fir::ExtendedValue compExv = - converter.genExprAddr(operandLocation, *expr, stmtCtx); - info.addr = fir::getBase(compExv); - info.rawInput = info.addr; - asFortran << (*expr).AsFortran(); - } else if (const auto *dataRef{ - std::get_if<Fortran::parser::DataRef>( - &designator.u)}) { - // Scalar or full array. - const Fortran::parser::Name &name = - Fortran::parser::GetLastName(*dataRef); - fir::ExtendedValue dataExv = - converter.getSymbolExtendedValue(*name.symbol); - info = getDataOperandBaseAddr(converter, builder, - *name.symbol, operandLocation); - if (fir::unwrapRefType(info.addr.getType()) - .isa<fir::BaseBoxType>()) { - bounds = genBoundsOpsFromBox<BoundsOp, BoundsType>( - builder, operandLocation, converter, dataExv, info); - } - bool dataExvIsAssumedSize = - Fortran::semantics::IsAssumedSizeArray( - name.symbol->GetUltimate()); - if (fir::unwrapRefType(info.addr.getType()) - .isa<fir::SequenceType>()) - bounds = genBaseBoundsOps<BoundsOp, BoundsType>( - builder, operandLocation, converter, dataExv, - dataExvIsAssumedSize); - asFortran << name.ToString(); - } else { // Unsupported - llvm::report_fatal_error( - "Unsupported type of OpenACC operand"); - } - } - } - }, - [&](const Fortran::parser::Name &name) { - info = getDataOperandBaseAddr(converter, builder, *name.symbol, - operandLocation); - asFortran << name.ToString(); - }}, - object.u); + + if (!maybeDesignator) { + info = getDataOperandBaseAddr(converter, builder, symbol, operandLocation); + asFortran << symbol->name().ToString(); + return info; + } + + semantics::SomeExpr designator = *maybeDesignator; + + if ((designator.Rank() > 0 || treatIndexAsSection) && + IsArrayElement(designator)) { + auto arrayRef = detail::getRef<evaluate::ArrayRef>(designator); + // This shouldn't fail after IsArrayElement(designator). + assert(arrayRef && "Expecting ArrayRef"); + + fir::ExtendedValue dataExv; + bool dataExvIsAssumedSize = false; + + auto toMaybeExpr = [&](auto &&base) { + using BaseType = llvm::remove_cvref_t<decltype(base)>; + evaluate::ExpressionAnalyzer ea{semaCtx}; + + if constexpr (std::is_same_v<evaluate::NamedEntity, BaseType>) { + if (auto *ref = base.UnwrapSymbolRef()) + return ea.Designate(evaluate::DataRef{*ref}); + if (auto *ref = base.UnwrapComponent()) + return ea.Designate(evaluate::DataRef{*ref}); + llvm_unreachable("Unexpected NamedEntity"); + } else { + static_assert(std::is_same_v<semantics::SymbolRef, BaseType>); + return ea.Designate(evaluate::DataRef{base}); + } + }; + + auto arrayBase = toMaybeExpr(arrayRef->base()); + assert(arrayBase); + + if (detail::getRef<evaluate::Component>(*arrayBase)) { + dataExv = converter.genExprAddr(operandLocation, *arrayBase, stmtCtx); + info.addr = fir::getBase(dataExv); + info.rawInput = info.addr; + asFortran << arrayBase->AsFortran(); + } else { + const semantics::Symbol &sym = arrayRef->GetLastSymbol(); + dataExvIsAssumedSize = + Fortran::semantics::IsAssumedSizeArray(sym.GetUltimate()); + info = getDataOperandBaseAddr(converter, builder, sym, operandLocation); + dataExv = converter.getSymbolExtendedValue(sym); + asFortran << sym.name().ToString(); + } + + if (!arrayRef->subscript().empty()) { + asFortran << '('; + bounds = genBoundsOps<BoundsOp, BoundsType>( + builder, operandLocation, converter, stmtCtx, arrayRef->subscript(), + asFortran, dataExv, dataExvIsAssumedSize, info, treatIndexAsSection); + } + asFortran << ')'; + } else if (auto compRef = detail::getRef<evaluate::Component>(designator)) { + fir::ExtendedValue compExv = + converter.genExprAddr(operandLocation, designator, stmtCtx); + info.addr = fir::getBase(compExv); + info.rawInput = info.addr; + if (fir::unwrapRefType(info.addr.getType()).isa<fir::SequenceType>()) + bounds = genBaseBoundsOps<BoundsOp, BoundsType>(builder, operandLocation, + converter, compExv, + /*isAssumedSize=*/false); + asFortran << designator.AsFortran(); + + if (semantics::IsOptional(compRef->GetLastSymbol())) { + info.isPresent = builder.create<fir::IsPresentOp>( + operandLocation, builder.getI1Type(), info.rawInput); + } + + if (auto loadOp = + mlir::dyn_cast_or_null<fir::LoadOp>(info.addr.getDefiningOp())) { + if (fir::isAllocatableType(loadOp.getType()) || + fir::isPointerType(loadOp.getType())) + info.addr = builder.create<fir::BoxAddrOp>(operandLocation, info.addr); + info.rawInput = info.addr; + } + + // If the component is an allocatable or pointer the result of + // genExprAddr will be the result of a fir.box_addr operation or + // a fir.box_addr has been inserted just before. + // Retrieve the box so we handle it like other descriptor. + if (auto boxAddrOp = + mlir::dyn_cast_or_null<fir::BoxAddrOp>(info.addr.getDefiningOp())) { + info.addr = boxAddrOp.getVal(); + info.rawInput = info.addr; + bounds = genBoundsOpsFromBox<BoundsOp, BoundsType>( + builder, operandLocation, converter, compExv, info); + } + } else { + if (detail::getRef<evaluate::ArrayRef>(designator)) { + fir::ExtendedValue compExv = + converter.genExprAddr(operandLocation, designator, stmtCtx); + info.addr = fir::getBase(compExv); + info.rawInput = info.addr; + asFortran << designator.AsFortran(); + } else if (auto symRef = detail::getRef<semantics::SymbolRef>(designator)) { + // Scalar or full array. + fir::ExtendedValue dataExv = converter.getSymbolExtendedValue(*symRef); + info = + getDataOperandBaseAddr(converter, builder, *symRef, operandLocation); + if (fir::unwrapRefType(info.addr.getType()).isa<fir::BaseBoxType>()) { + bounds = genBoundsOpsFromBox<BoundsOp, BoundsType>( + builder, operandLocation, converter, dataExv, info); + } + bool dataExvIsAssumedSize = + Fortran::semantics::IsAssumedSizeArray(symRef->get().GetUltimate()); + if (fir::unwrapRefType(info.addr.getType()).isa<fir::SequenceType>()) + bounds = genBaseBoundsOps<BoundsOp, BoundsType>( + builder, operandLocation, converter, dataExv, dataExvIsAssumedSize); + asFortran << symRef->get().name().ToString(); + } else { // Unsupported + llvm::report_fatal_error("Unsupported type of OpenACC operand"); + } + } + return info; } - } // namespace lower } // namespace Fortran diff --git a/flang/lib/Lower/HostAssociations.cpp b/flang/lib/Lower/HostAssociations.cpp index 414673b00f44ca1a9ba9da5a7953dda924882932..8eb548eb2bd5fe488900fcc4ea907eadd98b2da2 100644 --- a/flang/lib/Lower/HostAssociations.cpp +++ b/flang/lib/Lower/HostAssociations.cpp @@ -315,7 +315,11 @@ class CapturedAllocatableAndPointer public: static mlir::Type getType(Fortran::lower::AbstractConverter &converter, const Fortran::semantics::Symbol &sym) { - return fir::ReferenceType::get(converter.genType(sym)); + mlir::Type baseType = converter.genType(sym); + if (sym.GetUltimate().test(Fortran::semantics::Symbol::Flag::CrayPointee)) + return fir::ReferenceType::get( + Fortran::lower::getCrayPointeeBoxType(baseType)); + return fir::ReferenceType::get(baseType); } static void instantiateHostTuple(const InstantiateHostTuple &args, Fortran::lower::AbstractConverter &converter, @@ -507,7 +511,8 @@ walkCaptureCategories(T visitor, Fortran::lower::AbstractConverter &converter, if (Fortran::semantics::IsProcedure(sym)) return CapturedProcedure::visit(visitor, converter, sym, ba); ba.analyze(sym); - if (Fortran::semantics::IsAllocatableOrPointer(sym)) + if (Fortran::semantics::IsAllocatableOrPointer(sym) || + sym.GetUltimate().test(Fortran::semantics::Symbol::Flag::CrayPointee)) return CapturedAllocatableAndPointer::visit(visitor, converter, sym, ba); if (ba.isArray()) return CapturedArrays::visit(visitor, converter, sym, ba); diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index d2c6006ecf914a9b38b3e72451e12d146e959d6d..d933c07aba0e0c05c2392db9d8bbcd79e9e0d0dd 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -269,6 +269,11 @@ getSymbolFromAccObject(const Fortran::parser::AccObject &accObject) { Fortran::parser::GetLastName(arrayElement->base); return *name.symbol; } + if (const auto *component = + Fortran::parser::Unwrap<Fortran::parser::StructureComponent>( + *designator)) { + return *component->component.symbol; + } } else if (const auto *name = std::get_if<Fortran::parser::Name>(&accObject.u)) { return *name->symbol; @@ -286,17 +291,20 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList, mlir::acc::DataClause dataClause, bool structured, bool implicit, bool setDeclareAttr = false) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext}; for (const auto &accObject : objectList.v) { llvm::SmallVector<mlir::Value> bounds; std::stringstream asFortran; mlir::Location operandLocation = genOperandLocation(converter, accObject); + Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject); + Fortran::semantics::MaybeExpr designator = + std::visit([&](auto &&s) { return ea.Analyze(s); }, accObject.u); Fortran::lower::AddrAndBoundsInfo info = Fortran::lower::gatherDataOperandAddrAndBounds< - Fortran::parser::AccObject, mlir::acc::DataBoundsOp, - mlir::acc::DataBoundsType>(converter, builder, semanticsContext, - stmtCtx, accObject, operandLocation, - asFortran, bounds, - /*treatIndexAsSection=*/true); + mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>( + converter, builder, semanticsContext, stmtCtx, symbol, designator, + operandLocation, asFortran, bounds, + /*treatIndexAsSection=*/true); // If the input value is optional and is not a descriptor, we use the // rawInput directly. @@ -321,16 +329,19 @@ static void genDeclareDataOperandOperations( llvm::SmallVectorImpl<mlir::Value> &dataOperands, mlir::acc::DataClause dataClause, bool structured, bool implicit) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext}; for (const auto &accObject : objectList.v) { llvm::SmallVector<mlir::Value> bounds; std::stringstream asFortran; mlir::Location operandLocation = genOperandLocation(converter, accObject); + Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject); + Fortran::semantics::MaybeExpr designator = + std::visit([&](auto &&s) { return ea.Analyze(s); }, accObject.u); Fortran::lower::AddrAndBoundsInfo info = Fortran::lower::gatherDataOperandAddrAndBounds< - Fortran::parser::AccObject, mlir::acc::DataBoundsOp, - mlir::acc::DataBoundsType>(converter, builder, semanticsContext, - stmtCtx, accObject, operandLocation, - asFortran, bounds); + mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>( + converter, builder, semanticsContext, stmtCtx, symbol, designator, + operandLocation, asFortran, bounds); EntryOp op = createDataEntryOp<EntryOp>( builder, operandLocation, info.addr, asFortran, bounds, structured, implicit, dataClause, info.addr.getType()); @@ -339,8 +350,7 @@ static void genDeclareDataOperandOperations( if (mlir::isa<fir::BaseBoxType>(fir::unwrapRefType(info.addr.getType()))) { mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion()); modBuilder.setInsertionPointAfter(builder.getFunction()); - std::string prefix = - converter.mangleName(getSymbolFromAccObject(accObject)); + std::string prefix = converter.mangleName(symbol); createDeclareAllocFuncWithArg<EntryOp>( modBuilder, builder, operandLocation, info.addr.getType(), prefix, asFortran, dataClause); @@ -406,19 +416,6 @@ fir::ShapeOp genShapeOp(mlir::OpBuilder &builder, fir::SequenceType seqTy, return builder.create<fir::ShapeOp>(loc, extents); } -/// Return the nested sequence type if any. -static mlir::Type extractSequenceType(mlir::Type ty) { - if (mlir::isa<fir::SequenceType>(ty)) - return ty; - if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(ty)) - return extractSequenceType(boxTy.getEleTy()); - if (auto heapTy = mlir::dyn_cast<fir::HeapType>(ty)) - return extractSequenceType(heapTy.getEleTy()); - if (auto ptrTy = mlir::dyn_cast<fir::PointerType>(ty)) - return extractSequenceType(ptrTy.getEleTy()); - return mlir::Type{}; -} - template <typename RecipeOp> static void genPrivateLikeInitRegion(mlir::OpBuilder &builder, RecipeOp recipe, mlir::Type ty, mlir::Location loc) { @@ -454,7 +451,7 @@ static void genPrivateLikeInitRegion(mlir::OpBuilder &builder, RecipeOp recipe, } } } else if (auto boxTy = mlir::dyn_cast_or_null<fir::BaseBoxType>(ty)) { - mlir::Type innerTy = extractSequenceType(boxTy); + mlir::Type innerTy = fir::extractSequenceType(boxTy); if (!innerTy) TODO(loc, "Unsupported boxed type in OpenACC privatization"); fir::FirOpBuilder firBuilder{builder, recipe.getOperation()}; @@ -688,7 +685,7 @@ mlir::acc::FirstprivateRecipeOp Fortran::lower::createOrGetFirstprivateRecipe( } else if (auto boxTy = mlir::dyn_cast_or_null<fir::BaseBoxType>(ty)) { fir::FirOpBuilder firBuilder{builder, recipe.getOperation()}; llvm::SmallVector<mlir::Value> tripletArgs; - mlir::Type innerTy = extractSequenceType(boxTy); + mlir::Type innerTy = fir::extractSequenceType(boxTy); fir::SequenceType seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(innerTy); if (!seqTy) @@ -783,16 +780,19 @@ genPrivatizations(const Fortran::parser::AccObjectList &objectList, llvm::SmallVectorImpl<mlir::Value> &dataOperands, llvm::SmallVector<mlir::Attribute> &privatizations) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext}; for (const auto &accObject : objectList.v) { llvm::SmallVector<mlir::Value> bounds; std::stringstream asFortran; mlir::Location operandLocation = genOperandLocation(converter, accObject); + Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject); + Fortran::semantics::MaybeExpr designator = + std::visit([&](auto &&s) { return ea.Analyze(s); }, accObject.u); Fortran::lower::AddrAndBoundsInfo info = Fortran::lower::gatherDataOperandAddrAndBounds< - Fortran::parser::AccObject, mlir::acc::DataBoundsOp, - mlir::acc::DataBoundsType>(converter, builder, semanticsContext, - stmtCtx, accObject, operandLocation, - asFortran, bounds); + mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>( + converter, builder, semanticsContext, stmtCtx, symbol, designator, + operandLocation, asFortran, bounds); RecipeOp recipe; mlir::Type retTy = getTypeFromBounds(bounds, info.addr.getType()); if constexpr (std::is_same_v<RecipeOp, mlir::acc::PrivateRecipeOp>) { @@ -1018,7 +1018,7 @@ static mlir::Value genReductionInitRegion(fir::FirOpBuilder &builder, return declareOp.getBase(); } } else if (auto boxTy = mlir::dyn_cast_or_null<fir::BaseBoxType>(ty)) { - mlir::Type innerTy = extractSequenceType(boxTy); + mlir::Type innerTy = fir::extractSequenceType(boxTy); if (!mlir::isa<fir::SequenceType>(innerTy)) TODO(loc, "Unsupported boxed type for reduction"); // Create the private copy from the initial fir.box. @@ -1230,7 +1230,7 @@ static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc, builder.create<fir::StoreOp>(loc, res, addr1); builder.setInsertionPointAfter(loops[0]); } else if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(ty)) { - mlir::Type innerTy = extractSequenceType(boxTy); + mlir::Type innerTy = fir::extractSequenceType(boxTy); fir::SequenceType seqTy = mlir::dyn_cast_or_null<fir::SequenceType>(innerTy); if (!seqTy) @@ -1353,16 +1353,19 @@ genReductions(const Fortran::parser::AccObjectListWithReduction &objectList, const auto &op = std::get<Fortran::parser::AccReductionOperator>(objectList.t); mlir::acc::ReductionOperator mlirOp = getReductionOperator(op); + Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext}; for (const auto &accObject : objects.v) { llvm::SmallVector<mlir::Value> bounds; std::stringstream asFortran; mlir::Location operandLocation = genOperandLocation(converter, accObject); + Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject); + Fortran::semantics::MaybeExpr designator = + std::visit([&](auto &&s) { return ea.Analyze(s); }, accObject.u); Fortran::lower::AddrAndBoundsInfo info = Fortran::lower::gatherDataOperandAddrAndBounds< - Fortran::parser::AccObject, mlir::acc::DataBoundsOp, - mlir::acc::DataBoundsType>(converter, builder, semanticsContext, - stmtCtx, accObject, operandLocation, - asFortran, bounds); + mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>( + converter, builder, semanticsContext, stmtCtx, symbol, designator, + operandLocation, asFortran, bounds); mlir::Type reductionTy = fir::unwrapRefType(info.addr.getType()); if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(reductionTy)) @@ -1664,15 +1667,17 @@ static void privatizeIv(Fortran::lower::AbstractConverter &converter, ivPrivate.push_back(privateValue); } -static mlir::acc::LoopOp -createLoopOp(Fortran::lower::AbstractConverter &converter, - mlir::Location currentLocation, - Fortran::semantics::SemanticsContext &semanticsContext, - Fortran::lower::StatementContext &stmtCtx, - const Fortran::parser::DoConstruct &outerDoConstruct, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::AccClauseList &accClauseList, - bool needEarlyReturnHandling = false) { +static mlir::acc::LoopOp createLoopOp( + Fortran::lower::AbstractConverter &converter, + mlir::Location currentLocation, + Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &stmtCtx, + const Fortran::parser::DoConstruct &outerDoConstruct, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::AccClauseList &accClauseList, + std::optional<mlir::acc::CombinedConstructsType> combinedConstructs = + std::nullopt, + bool needEarlyReturnHandling = false) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); llvm::SmallVector<mlir::Value> tileOperands, privateOperands, ivPrivate, reductionOperands, cacheOperands, vectorOperands, workerNumOperands, @@ -2012,6 +2017,10 @@ createLoopOp(Fortran::lower::AbstractConverter &converter, if (!collapseDeviceTypes.empty()) loopOp.setCollapseDeviceTypeAttr(builder.getArrayAttr(collapseDeviceTypes)); + if (combinedConstructs) + loopOp.setCombinedAttr(mlir::acc::CombinedConstructsTypeAttr::get( + builder.getContext(), *combinedConstructs)); + return loopOp; } @@ -2057,7 +2066,7 @@ genACC(Fortran::lower::AbstractConverter &converter, std::get<std::optional<Fortran::parser::DoConstruct>>(loopConstruct.t); auto loopOp = createLoopOp(converter, currentLocation, semanticsContext, stmtCtx, *outerDoConstruct, eval, accClauseList, - needEarlyExitHandling); + /*combinedConstructs=*/{}, needEarlyExitHandling); if (needEarlyExitHandling) return loopOp.getResult(0); @@ -2089,14 +2098,14 @@ static void genDataOperandOperationsWithModifier( } template <typename Op> -static Op -createComputeOp(Fortran::lower::AbstractConverter &converter, - mlir::Location currentLocation, - Fortran::lower::pft::Evaluation &eval, - Fortran::semantics::SemanticsContext &semanticsContext, - Fortran::lower::StatementContext &stmtCtx, - const Fortran::parser::AccClauseList &accClauseList, - bool outerCombined = false) { +static Op createComputeOp( + Fortran::lower::AbstractConverter &converter, + mlir::Location currentLocation, Fortran::lower::pft::Evaluation &eval, + Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &stmtCtx, + const Fortran::parser::AccClauseList &accClauseList, + std::optional<mlir::acc::CombinedConstructsType> combinedConstructs = + std::nullopt) { // Parallel operation operands mlir::Value ifCond; @@ -2289,7 +2298,7 @@ createComputeOp(Fortran::lower::AbstractConverter &converter, } else if (const auto *privateClause = std::get_if<Fortran::parser::AccClause::Private>( &clause.u)) { - if (!outerCombined) + if (!combinedConstructs) genPrivatizations<mlir::acc::PrivateRecipeOp>( privateClause->v, converter, semanticsContext, stmtCtx, privateOperands, privatizations); @@ -2307,7 +2316,7 @@ createComputeOp(Fortran::lower::AbstractConverter &converter, // combined - delay it to the loop. However, a reduction clause on a // combined construct implies a copy clause so issue an implicit copy // instead. - if (!outerCombined) { + if (!combinedConstructs) { genReductions(reductionClause->v, converter, semanticsContext, stmtCtx, reductionOperands, reductionRecipes); } else { @@ -2359,11 +2368,11 @@ createComputeOp(Fortran::lower::AbstractConverter &converter, if constexpr (std::is_same_v<Op, mlir::acc::KernelsOp>) computeOp = createRegionOp<Op, mlir::acc::TerminatorOp>( builder, currentLocation, currentLocation, eval, operands, - operandSegments, outerCombined); + operandSegments, /*outerCombined=*/combinedConstructs.has_value()); else computeOp = createRegionOp<Op, mlir::acc::YieldOp>( builder, currentLocation, currentLocation, eval, operands, - operandSegments, outerCombined); + operandSegments, /*outerCombined=*/combinedConstructs.has_value()); if (addSelfAttr) computeOp.setSelfAttrAttr(builder.getUnitAttr()); @@ -2416,6 +2425,9 @@ createComputeOp(Fortran::lower::AbstractConverter &converter, mlir::ArrayAttr::get(builder.getContext(), firstPrivatizations)); } + if (combinedConstructs) + computeOp.setCombinedAttr(builder.getUnitAttr()); + auto insPt = builder.saveInsertionPoint(); builder.setInsertionPointAfter(computeOp); @@ -2731,21 +2743,24 @@ genACC(Fortran::lower::AbstractConverter &converter, if (combinedDirective.v == llvm::acc::ACCD_kernels_loop) { createComputeOp<mlir::acc::KernelsOp>( converter, currentLocation, eval, semanticsContext, stmtCtx, - accClauseList, /*outerCombined=*/true); + accClauseList, mlir::acc::CombinedConstructsType::KernelsLoop); createLoopOp(converter, currentLocation, semanticsContext, stmtCtx, - *outerDoConstruct, eval, accClauseList); + *outerDoConstruct, eval, accClauseList, + mlir::acc::CombinedConstructsType::KernelsLoop); } else if (combinedDirective.v == llvm::acc::ACCD_parallel_loop) { createComputeOp<mlir::acc::ParallelOp>( converter, currentLocation, eval, semanticsContext, stmtCtx, - accClauseList, /*outerCombined=*/true); + accClauseList, mlir::acc::CombinedConstructsType::ParallelLoop); createLoopOp(converter, currentLocation, semanticsContext, stmtCtx, - *outerDoConstruct, eval, accClauseList); + *outerDoConstruct, eval, accClauseList, + mlir::acc::CombinedConstructsType::ParallelLoop); } else if (combinedDirective.v == llvm::acc::ACCD_serial_loop) { - createComputeOp<mlir::acc::SerialOp>(converter, currentLocation, eval, - semanticsContext, stmtCtx, - accClauseList, /*outerCombined=*/true); + createComputeOp<mlir::acc::SerialOp>( + converter, currentLocation, eval, semanticsContext, stmtCtx, + accClauseList, mlir::acc::CombinedConstructsType::SerialLoop); createLoopOp(converter, currentLocation, semanticsContext, stmtCtx, - *outerDoConstruct, eval, accClauseList); + *outerDoConstruct, eval, accClauseList, + mlir::acc::CombinedConstructsType::SerialLoop); } else { llvm::report_fatal_error("Unknown combined construct encountered"); } @@ -3806,7 +3821,8 @@ void Fortran::lower::genOpenACCRoutineConstruct( std::string funcName; if (name) { funcName = converter.mangleName(*name->symbol); - funcOp = builder.getNamedFunction(mod, funcName); + funcOp = + builder.getNamedFunction(mod, builder.getMLIRSymbolTable(), funcName); } else { Fortran::semantics::Scope &scope = semanticsContext.FindScope(routineConstruct.source); @@ -3818,7 +3834,8 @@ void Fortran::lower::genOpenACCRoutineConstruct( : nullptr}; if (subpDetails && subpDetails->isInterface()) { funcName = converter.mangleName(*progUnit.symbol()); - funcOp = builder.getNamedFunction(mod, funcName); + funcOp = + builder.getNamedFunction(mod, builder.getMLIRSymbolTable(), funcName); } else { funcOp = builder.getFunction(); funcName = funcOp.getName(); diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp index a41f8312a28c9e850de221bca393dcaf0d46d41c..0a57a1496289f4da0d509b49b2a581b0ed097a65 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "ClauseProcessor.h" +#include "Clauses.h" #include "flang/Lower/PFTBuilder.h" #include "flang/Parser/tools.h" @@ -30,132 +31,87 @@ static void checkMapType(mlir::Location location, mlir::Type type) { } static mlir::omp::ScheduleModifier -translateScheduleModifier(const Fortran::parser::OmpScheduleModifierType &m) { - switch (m.v) { - case Fortran::parser::OmpScheduleModifierType::ModType::Monotonic: +translateScheduleModifier(const omp::clause::Schedule::OrderingModifier &m) { + switch (m) { + case omp::clause::Schedule::OrderingModifier::Monotonic: return mlir::omp::ScheduleModifier::monotonic; - case Fortran::parser::OmpScheduleModifierType::ModType::Nonmonotonic: + case omp::clause::Schedule::OrderingModifier::Nonmonotonic: return mlir::omp::ScheduleModifier::nonmonotonic; - case Fortran::parser::OmpScheduleModifierType::ModType::Simd: - return mlir::omp::ScheduleModifier::simd; } return mlir::omp::ScheduleModifier::none; } static mlir::omp::ScheduleModifier -getScheduleModifier(const Fortran::parser::OmpScheduleClause &x) { +getScheduleModifier(const omp::clause::Schedule &clause) { + using Schedule = omp::clause::Schedule; const auto &modifier = - std::get<std::optional<Fortran::parser::OmpScheduleModifier>>(x.t); - // The input may have the modifier any order, so we look for one that isn't - // SIMD. If modifier is not set at all, fall down to the bottom and return - // "none". - if (modifier) { - const auto &modType1 = - std::get<Fortran::parser::OmpScheduleModifier::Modifier1>(modifier->t); - if (modType1.v.v == - Fortran::parser::OmpScheduleModifierType::ModType::Simd) { - const auto &modType2 = std::get< - std::optional<Fortran::parser::OmpScheduleModifier::Modifier2>>( - modifier->t); - if (modType2 && - modType2->v.v != - Fortran::parser::OmpScheduleModifierType::ModType::Simd) - return translateScheduleModifier(modType2->v); - - return mlir::omp::ScheduleModifier::none; - } - - return translateScheduleModifier(modType1.v); - } + std::get<std::optional<Schedule::OrderingModifier>>(clause.t); + if (modifier) + return translateScheduleModifier(*modifier); return mlir::omp::ScheduleModifier::none; } static mlir::omp::ScheduleModifier -getSimdModifier(const Fortran::parser::OmpScheduleClause &x) { +getSimdModifier(const omp::clause::Schedule &clause) { + using Schedule = omp::clause::Schedule; const auto &modifier = - std::get<std::optional<Fortran::parser::OmpScheduleModifier>>(x.t); - // Either of the two possible modifiers in the input can be the SIMD modifier, - // so look in either one, and return simd if we find one. Not found = return - // "none". - if (modifier) { - const auto &modType1 = - std::get<Fortran::parser::OmpScheduleModifier::Modifier1>(modifier->t); - if (modType1.v.v == Fortran::parser::OmpScheduleModifierType::ModType::Simd) - return mlir::omp::ScheduleModifier::simd; - - const auto &modType2 = std::get< - std::optional<Fortran::parser::OmpScheduleModifier::Modifier2>>( - modifier->t); - if (modType2 && modType2->v.v == - Fortran::parser::OmpScheduleModifierType::ModType::Simd) - return mlir::omp::ScheduleModifier::simd; - } + std::get<std::optional<Schedule::ChunkModifier>>(clause.t); + if (modifier && *modifier == Schedule::ChunkModifier::Simd) + return mlir::omp::ScheduleModifier::simd; return mlir::omp::ScheduleModifier::none; } static void genAllocateClause(Fortran::lower::AbstractConverter &converter, - const Fortran::parser::OmpAllocateClause &ompAllocateClause, + const omp::clause::Allocate &clause, llvm::SmallVectorImpl<mlir::Value> &allocatorOperands, llvm::SmallVectorImpl<mlir::Value> &allocateOperands) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::Location currentLocation = converter.getCurrentLocation(); Fortran::lower::StatementContext stmtCtx; - mlir::Value allocatorOperand; - const Fortran::parser::OmpObjectList &ompObjectList = - std::get<Fortran::parser::OmpObjectList>(ompAllocateClause.t); - const auto &allocateModifier = std::get< - std::optional<Fortran::parser::OmpAllocateClause::AllocateModifier>>( - ompAllocateClause.t); - - // If the allocate modifier is present, check if we only use the allocator - // submodifier. ALIGN in this context is unimplemented - const bool onlyAllocator = - allocateModifier && - std::holds_alternative< - Fortran::parser::OmpAllocateClause::AllocateModifier::Allocator>( - allocateModifier->u); - - if (allocateModifier && !onlyAllocator) { + auto &objects = std::get<omp::ObjectList>(clause.t); + + using Allocate = omp::clause::Allocate; + // ALIGN in this context is unimplemented + if (std::get<std::optional<Allocate::AlignModifier>>(clause.t)) TODO(currentLocation, "OmpAllocateClause ALIGN modifier"); - } // Check if allocate clause has allocator specified. If so, add it // to list of allocators, otherwise, add default allocator to // list of allocators. - if (onlyAllocator) { - const auto &allocatorValue = std::get< - Fortran::parser::OmpAllocateClause::AllocateModifier::Allocator>( - allocateModifier->u); - allocatorOperand = fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(allocatorValue.v), stmtCtx)); - allocatorOperands.insert(allocatorOperands.end(), ompObjectList.v.size(), - allocatorOperand); + using SimpleModifier = Allocate::AllocatorSimpleModifier; + using ComplexModifier = Allocate::AllocatorComplexModifier; + if (auto &mod = std::get<std::optional<SimpleModifier>>(clause.t)) { + mlir::Value operand = fir::getBase(converter.genExprValue(*mod, stmtCtx)); + allocatorOperands.append(objects.size(), operand); + } else if (auto &mod = std::get<std::optional<ComplexModifier>>(clause.t)) { + mlir::Value operand = fir::getBase(converter.genExprValue(mod->v, stmtCtx)); + allocatorOperands.append(objects.size(), operand); } else { - allocatorOperand = firOpBuilder.createIntegerConstant( + mlir::Value operand = firOpBuilder.createIntegerConstant( currentLocation, firOpBuilder.getI32Type(), 1); - allocatorOperands.insert(allocatorOperands.end(), ompObjectList.v.size(), - allocatorOperand); + allocatorOperands.append(objects.size(), operand); } - genObjectList(ompObjectList, converter, allocateOperands); + + genObjectList(objects, converter, allocateOperands); } -static mlir::omp::ClauseProcBindKindAttr genProcBindKindAttr( - fir::FirOpBuilder &firOpBuilder, - const Fortran::parser::OmpClause::ProcBind *procBindClause) { +static mlir::omp::ClauseProcBindKindAttr +genProcBindKindAttr(fir::FirOpBuilder &firOpBuilder, + const omp::clause::ProcBind &clause) { mlir::omp::ClauseProcBindKind procBindKind; - switch (procBindClause->v.v) { - case Fortran::parser::OmpProcBindClause::Type::Master: + switch (clause.v) { + case omp::clause::ProcBind::AffinityPolicy::Master: procBindKind = mlir::omp::ClauseProcBindKind::Master; break; - case Fortran::parser::OmpProcBindClause::Type::Close: + case omp::clause::ProcBind::AffinityPolicy::Close: procBindKind = mlir::omp::ClauseProcBindKind::Close; break; - case Fortran::parser::OmpProcBindClause::Type::Spread: + case omp::clause::ProcBind::AffinityPolicy::Spread: procBindKind = mlir::omp::ClauseProcBindKind::Spread; break; - case Fortran::parser::OmpProcBindClause::Type::Primary: + case omp::clause::ProcBind::AffinityPolicy::Primary: procBindKind = mlir::omp::ClauseProcBindKind::Primary; break; } @@ -165,68 +121,81 @@ static mlir::omp::ClauseProcBindKindAttr genProcBindKindAttr( static mlir::omp::ClauseTaskDependAttr genDependKindAttr(fir::FirOpBuilder &firOpBuilder, - const Fortran::parser::OmpClause::Depend *dependClause) { + const omp::clause::Depend::TaskDependenceType kind) { mlir::omp::ClauseTaskDepend pbKind; - switch ( - std::get<Fortran::parser::OmpDependenceType>( - std::get<Fortran::parser::OmpDependClause::InOut>(dependClause->v.u) - .t) - .v) { - case Fortran::parser::OmpDependenceType::Type::In: + switch (kind) { + case omp::clause::Depend::TaskDependenceType::In: pbKind = mlir::omp::ClauseTaskDepend::taskdependin; break; - case Fortran::parser::OmpDependenceType::Type::Out: + case omp::clause::Depend::TaskDependenceType::Out: pbKind = mlir::omp::ClauseTaskDepend::taskdependout; break; - case Fortran::parser::OmpDependenceType::Type::Inout: + case omp::clause::Depend::TaskDependenceType::Inout: pbKind = mlir::omp::ClauseTaskDepend::taskdependinout; break; - default: - llvm_unreachable("unknown parser task dependence type"); + case omp::clause::Depend::TaskDependenceType::Mutexinoutset: + case omp::clause::Depend::TaskDependenceType::Inoutset: + case omp::clause::Depend::TaskDependenceType::Depobj: + llvm_unreachable("unhandled parser task dependence type"); break; } return mlir::omp::ClauseTaskDependAttr::get(firOpBuilder.getContext(), pbKind); } -static mlir::Value getIfClauseOperand( - Fortran::lower::AbstractConverter &converter, - const Fortran::parser::OmpClause::If *ifClause, - Fortran::parser::OmpIfClause::DirectiveNameModifier directiveName, - mlir::Location clauseLocation) { +static mlir::Value +getIfClauseOperand(Fortran::lower::AbstractConverter &converter, + const omp::clause::If &clause, + omp::clause::If::DirectiveNameModifier directiveName, + mlir::Location clauseLocation) { // Only consider the clause if it's intended for the given directive. - auto &directive = std::get< - std::optional<Fortran::parser::OmpIfClause::DirectiveNameModifier>>( - ifClause->v.t); + auto &directive = + std::get<std::optional<omp::clause::If::DirectiveNameModifier>>(clause.t); if (directive && directive.value() != directiveName) return nullptr; Fortran::lower::StatementContext stmtCtx; fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - auto &expr = std::get<Fortran::parser::ScalarLogicalExpr>(ifClause->v.t); mlir::Value ifVal = fir::getBase( - converter.genExprValue(*Fortran::semantics::GetExpr(expr), stmtCtx)); + converter.genExprValue(std::get<omp::SomeExpr>(clause.t), stmtCtx)); return firOpBuilder.createConvert(clauseLocation, firOpBuilder.getI1Type(), ifVal); } static void addUseDeviceClause(Fortran::lower::AbstractConverter &converter, - const Fortran::parser::OmpObjectList &useDeviceClause, + const omp::ObjectList &objects, llvm::SmallVectorImpl<mlir::Value> &operands, llvm::SmallVectorImpl<mlir::Type> &useDeviceTypes, llvm::SmallVectorImpl<mlir::Location> &useDeviceLocs, llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> &useDeviceSymbols) { - genObjectList(useDeviceClause, converter, operands); + genObjectList(objects, converter, operands); for (mlir::Value &operand : operands) { checkMapType(operand.getLoc(), operand.getType()); useDeviceTypes.push_back(operand.getType()); useDeviceLocs.push_back(operand.getLoc()); } - for (const Fortran::parser::OmpObject &ompObject : useDeviceClause.v) { - Fortran::semantics::Symbol *sym = getOmpObjectSymbol(ompObject); - useDeviceSymbols.push_back(sym); + for (const omp::Object &object : objects) + useDeviceSymbols.push_back(object.id()); +} + +static void convertLoopBounds(Fortran::lower::AbstractConverter &converter, + mlir::Location loc, + llvm::SmallVectorImpl<mlir::Value> &lowerBound, + llvm::SmallVectorImpl<mlir::Value> &upperBound, + llvm::SmallVectorImpl<mlir::Value> &step, + std::size_t loopVarTypeSize) { + fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); + // The types of lower bound, upper bound, and step are converted into the + // type of the loop variable if necessary. + mlir::Type loopVarType = getLoopVarType(converter, loopVarTypeSize); + for (unsigned it = 0; it < (unsigned)lowerBound.size(); it++) { + lowerBound[it] = + firOpBuilder.createConvert(loc, loopVarType, lowerBound[it]); + upperBound[it] = + firOpBuilder.createConvert(loc, loopVarType, upperBound[it]); + step[it] = firOpBuilder.createConvert(loc, loopVarType, step[it]); } } @@ -239,8 +208,7 @@ bool ClauseProcessor::processCollapse( llvm::SmallVectorImpl<mlir::Value> &lowerBound, llvm::SmallVectorImpl<mlir::Value> &upperBound, llvm::SmallVectorImpl<mlir::Value> &step, - llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> &iv, - std::size_t &loopVarTypeSize) const { + llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> &iv) const { bool found = false; fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); @@ -253,13 +221,12 @@ bool ClauseProcessor::processCollapse( } std::int64_t collapseValue = 1l; - if (auto *collapseClause = findUniqueClause<ClauseTy::Collapse>()) { - const auto *expr = Fortran::semantics::GetExpr(collapseClause->v); - collapseValue = Fortran::evaluate::ToInt64(*expr).value(); + if (auto *clause = findUniqueClause<omp::clause::Collapse>()) { + collapseValue = Fortran::evaluate::ToInt64(clause->v).value(); found = true; } - loopVarTypeSize = 0; + std::size_t loopVarTypeSize = 0; do { Fortran::lower::pft::Evaluation *doLoop = &doConstructEval->getFirstNestedEvaluation(); @@ -290,23 +257,26 @@ bool ClauseProcessor::processCollapse( &*std::next(doConstructEval->getNestedEvaluations().begin()); } while (collapseValue > 0); + convertLoopBounds(converter, currentLocation, lowerBound, upperBound, step, + loopVarTypeSize); + return found; } bool ClauseProcessor::processDefault() const { - if (auto *defaultClause = findUniqueClause<ClauseTy::Default>()) { + if (auto *clause = findUniqueClause<omp::clause::Default>()) { // Private, Firstprivate, Shared, None - switch (defaultClause->v.v) { - case Fortran::parser::OmpDefaultClause::Type::Shared: - case Fortran::parser::OmpDefaultClause::Type::None: + switch (clause->v) { + case omp::clause::Default::DataSharingAttribute::Shared: + case omp::clause::Default::DataSharingAttribute::None: // Default clause with shared or none do not require any handling since // Shared is the default behavior in the IR and None is only required // for semantic checks. break; - case Fortran::parser::OmpDefaultClause::Type::Private: + case omp::clause::Default::DataSharingAttribute::Private: // TODO Support default(private) break; - case Fortran::parser::OmpDefaultClause::Type::Firstprivate: + case omp::clause::Default::DataSharingAttribute::Firstprivate: // TODO Support default(firstprivate) break; } @@ -318,20 +288,17 @@ bool ClauseProcessor::processDefault() const { bool ClauseProcessor::processDevice(Fortran::lower::StatementContext &stmtCtx, mlir::Value &result) const { const Fortran::parser::CharBlock *source = nullptr; - if (auto *deviceClause = findUniqueClause<ClauseTy::Device>(&source)) { + if (auto *clause = findUniqueClause<omp::clause::Device>(&source)) { mlir::Location clauseLocation = converter.genLocation(*source); - if (auto deviceModifier = std::get< - std::optional<Fortran::parser::OmpDeviceClause::DeviceModifier>>( - deviceClause->v.t)) { - if (deviceModifier == - Fortran::parser::OmpDeviceClause::DeviceModifier::Ancestor) { + if (auto deviceModifier = + std::get<std::optional<omp::clause::Device::DeviceModifier>>( + clause->t)) { + if (deviceModifier == omp::clause::Device::DeviceModifier::Ancestor) { TODO(clauseLocation, "OMPD_target Device Modifier Ancestor"); } } - if (const auto *deviceExpr = Fortran::semantics::GetExpr( - std::get<Fortran::parser::ScalarIntExpr>(deviceClause->v.t))) { - result = fir::getBase(converter.genExprValue(*deviceExpr, stmtCtx)); - } + const auto &deviceExpr = std::get<omp::SomeExpr>(clause->t); + result = fir::getBase(converter.genExprValue(deviceExpr, stmtCtx)); return true; } return false; @@ -339,16 +306,16 @@ bool ClauseProcessor::processDevice(Fortran::lower::StatementContext &stmtCtx, bool ClauseProcessor::processDeviceType( mlir::omp::DeclareTargetDeviceType &result) const { - if (auto *deviceTypeClause = findUniqueClause<ClauseTy::DeviceType>()) { + if (auto *clause = findUniqueClause<omp::clause::DeviceType>()) { // Case: declare target ... device_type(any | host | nohost) - switch (deviceTypeClause->v.v) { - case Fortran::parser::OmpDeviceTypeClause::Type::Nohost: + switch (clause->v) { + case omp::clause::DeviceType::DeviceTypeDescription::Nohost: result = mlir::omp::DeclareTargetDeviceType::nohost; break; - case Fortran::parser::OmpDeviceTypeClause::Type::Host: + case omp::clause::DeviceType::DeviceTypeDescription::Host: result = mlir::omp::DeclareTargetDeviceType::host; break; - case Fortran::parser::OmpDeviceTypeClause::Type::Any: + case omp::clause::DeviceType::DeviceTypeDescription::Any: result = mlir::omp::DeclareTargetDeviceType::any; break; } @@ -360,12 +327,12 @@ bool ClauseProcessor::processDeviceType( bool ClauseProcessor::processFinal(Fortran::lower::StatementContext &stmtCtx, mlir::Value &result) const { const Fortran::parser::CharBlock *source = nullptr; - if (auto *finalClause = findUniqueClause<ClauseTy::Final>(&source)) { + if (auto *clause = findUniqueClause<omp::clause::Final>(&source)) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::Location clauseLocation = converter.genLocation(*source); - mlir::Value finalVal = fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(finalClause->v), stmtCtx)); + mlir::Value finalVal = + fir::getBase(converter.genExprValue(clause->v, stmtCtx)); result = firOpBuilder.createConvert(clauseLocation, firOpBuilder.getI1Type(), finalVal); return true; @@ -374,10 +341,9 @@ bool ClauseProcessor::processFinal(Fortran::lower::StatementContext &stmtCtx, } bool ClauseProcessor::processHint(mlir::IntegerAttr &result) const { - if (auto *hintClause = findUniqueClause<ClauseTy::Hint>()) { + if (auto *clause = findUniqueClause<omp::clause::Hint>()) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - const auto *expr = Fortran::semantics::GetExpr(hintClause->v); - int64_t hintValue = *Fortran::evaluate::ToInt64(*expr); + int64_t hintValue = *Fortran::evaluate::ToInt64(clause->v); result = firOpBuilder.getI64IntegerAttr(hintValue); return true; } @@ -385,20 +351,21 @@ bool ClauseProcessor::processHint(mlir::IntegerAttr &result) const { } bool ClauseProcessor::processMergeable(mlir::UnitAttr &result) const { - return markClauseOccurrence<ClauseTy::Mergeable>(result); + return markClauseOccurrence<omp::clause::Mergeable>(result); } bool ClauseProcessor::processNowait(mlir::UnitAttr &result) const { - return markClauseOccurrence<ClauseTy::Nowait>(result); + return markClauseOccurrence<omp::clause::Nowait>(result); } bool ClauseProcessor::processNumTeams(Fortran::lower::StatementContext &stmtCtx, mlir::Value &result) const { // TODO Get lower and upper bounds for num_teams when parser is updated to // accept both. - if (auto *numTeamsClause = findUniqueClause<ClauseTy::NumTeams>()) { - result = fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(numTeamsClause->v), stmtCtx)); + if (auto *clause = findUniqueClause<omp::clause::NumTeams>()) { + // auto lowerBound = std::get<std::optional<ExprTy>>(clause->t); + auto &upperBound = std::get<ExprTy>(clause->t); + result = fir::getBase(converter.genExprValue(upperBound, stmtCtx)); return true; } return false; @@ -406,23 +373,20 @@ bool ClauseProcessor::processNumTeams(Fortran::lower::StatementContext &stmtCtx, bool ClauseProcessor::processNumThreads( Fortran::lower::StatementContext &stmtCtx, mlir::Value &result) const { - if (auto *numThreadsClause = findUniqueClause<ClauseTy::NumThreads>()) { + if (auto *clause = findUniqueClause<omp::clause::NumThreads>()) { // OMPIRBuilder expects `NUM_THREADS` clause as a `Value`. - result = fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(numThreadsClause->v), stmtCtx)); + result = fir::getBase(converter.genExprValue(clause->v, stmtCtx)); return true; } return false; } bool ClauseProcessor::processOrdered(mlir::IntegerAttr &result) const { - if (auto *orderedClause = findUniqueClause<ClauseTy::Ordered>()) { + if (auto *clause = findUniqueClause<omp::clause::Ordered>()) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); int64_t orderedClauseValue = 0l; - if (orderedClause->v.has_value()) { - const auto *expr = Fortran::semantics::GetExpr(orderedClause->v); - orderedClauseValue = *Fortran::evaluate::ToInt64(*expr); - } + if (clause->v.has_value()) + orderedClauseValue = *Fortran::evaluate::ToInt64(*clause->v); result = firOpBuilder.getI64IntegerAttr(orderedClauseValue); return true; } @@ -431,9 +395,8 @@ bool ClauseProcessor::processOrdered(mlir::IntegerAttr &result) const { bool ClauseProcessor::processPriority(Fortran::lower::StatementContext &stmtCtx, mlir::Value &result) const { - if (auto *priorityClause = findUniqueClause<ClauseTy::Priority>()) { - result = fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(priorityClause->v), stmtCtx)); + if (auto *clause = findUniqueClause<omp::clause::Priority>()) { + result = fir::getBase(converter.genExprValue(clause->v, stmtCtx)); return true; } return false; @@ -441,20 +404,19 @@ bool ClauseProcessor::processPriority(Fortran::lower::StatementContext &stmtCtx, bool ClauseProcessor::processProcBind( mlir::omp::ClauseProcBindKindAttr &result) const { - if (auto *procBindClause = findUniqueClause<ClauseTy::ProcBind>()) { + if (auto *clause = findUniqueClause<omp::clause::ProcBind>()) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - result = genProcBindKindAttr(firOpBuilder, procBindClause); + result = genProcBindKindAttr(firOpBuilder, *clause); return true; } return false; } bool ClauseProcessor::processSafelen(mlir::IntegerAttr &result) const { - if (auto *safelenClause = findUniqueClause<ClauseTy::Safelen>()) { + if (auto *clause = findUniqueClause<omp::clause::Safelen>()) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - const auto *expr = Fortran::semantics::GetExpr(safelenClause->v); const std::optional<std::int64_t> safelenVal = - Fortran::evaluate::ToInt64(*expr); + Fortran::evaluate::ToInt64(clause->v); result = firOpBuilder.getI64IntegerAttr(*safelenVal); return true; } @@ -465,41 +427,37 @@ bool ClauseProcessor::processSchedule( mlir::omp::ClauseScheduleKindAttr &valAttr, mlir::omp::ScheduleModifierAttr &modifierAttr, mlir::UnitAttr &simdModifierAttr) const { - if (auto *scheduleClause = findUniqueClause<ClauseTy::Schedule>()) { + if (auto *clause = findUniqueClause<omp::clause::Schedule>()) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::MLIRContext *context = firOpBuilder.getContext(); - const Fortran::parser::OmpScheduleClause &scheduleType = scheduleClause->v; - const auto &scheduleClauseKind = - std::get<Fortran::parser::OmpScheduleClause::ScheduleType>( - scheduleType.t); + const auto &scheduleType = std::get<omp::clause::Schedule::Kind>(clause->t); mlir::omp::ClauseScheduleKind scheduleKind; - switch (scheduleClauseKind) { - case Fortran::parser::OmpScheduleClause::ScheduleType::Static: + switch (scheduleType) { + case omp::clause::Schedule::Kind::Static: scheduleKind = mlir::omp::ClauseScheduleKind::Static; break; - case Fortran::parser::OmpScheduleClause::ScheduleType::Dynamic: + case omp::clause::Schedule::Kind::Dynamic: scheduleKind = mlir::omp::ClauseScheduleKind::Dynamic; break; - case Fortran::parser::OmpScheduleClause::ScheduleType::Guided: + case omp::clause::Schedule::Kind::Guided: scheduleKind = mlir::omp::ClauseScheduleKind::Guided; break; - case Fortran::parser::OmpScheduleClause::ScheduleType::Auto: + case omp::clause::Schedule::Kind::Auto: scheduleKind = mlir::omp::ClauseScheduleKind::Auto; break; - case Fortran::parser::OmpScheduleClause::ScheduleType::Runtime: + case omp::clause::Schedule::Kind::Runtime: scheduleKind = mlir::omp::ClauseScheduleKind::Runtime; break; } - mlir::omp::ScheduleModifier scheduleModifier = - getScheduleModifier(scheduleClause->v); + mlir::omp::ScheduleModifier scheduleModifier = getScheduleModifier(*clause); if (scheduleModifier != mlir::omp::ScheduleModifier::none) modifierAttr = mlir::omp::ScheduleModifierAttr::get(context, scheduleModifier); - if (getSimdModifier(scheduleClause->v) != mlir::omp::ScheduleModifier::none) + if (getSimdModifier(*clause) != mlir::omp::ScheduleModifier::none) simdModifierAttr = firOpBuilder.getUnitAttr(); valAttr = mlir::omp::ClauseScheduleKindAttr::get(context, scheduleKind); @@ -510,25 +468,19 @@ bool ClauseProcessor::processSchedule( bool ClauseProcessor::processScheduleChunk( Fortran::lower::StatementContext &stmtCtx, mlir::Value &result) const { - if (auto *scheduleClause = findUniqueClause<ClauseTy::Schedule>()) { - if (const auto &chunkExpr = - std::get<std::optional<Fortran::parser::ScalarIntExpr>>( - scheduleClause->v.t)) { - if (const auto *expr = Fortran::semantics::GetExpr(*chunkExpr)) { - result = fir::getBase(converter.genExprValue(*expr, stmtCtx)); - } - } + if (auto *clause = findUniqueClause<omp::clause::Schedule>()) { + if (const auto &chunkExpr = std::get<omp::MaybeExpr>(clause->t)) + result = fir::getBase(converter.genExprValue(*chunkExpr, stmtCtx)); return true; } return false; } bool ClauseProcessor::processSimdlen(mlir::IntegerAttr &result) const { - if (auto *simdlenClause = findUniqueClause<ClauseTy::Simdlen>()) { + if (auto *clause = findUniqueClause<omp::clause::Simdlen>()) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - const auto *expr = Fortran::semantics::GetExpr(simdlenClause->v); const std::optional<std::int64_t> simdlenVal = - Fortran::evaluate::ToInt64(*expr); + Fortran::evaluate::ToInt64(clause->v); result = firOpBuilder.getI64IntegerAttr(*simdlenVal); return true; } @@ -537,16 +489,15 @@ bool ClauseProcessor::processSimdlen(mlir::IntegerAttr &result) const { bool ClauseProcessor::processThreadLimit( Fortran::lower::StatementContext &stmtCtx, mlir::Value &result) const { - if (auto *threadLmtClause = findUniqueClause<ClauseTy::ThreadLimit>()) { - result = fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(threadLmtClause->v), stmtCtx)); + if (auto *clause = findUniqueClause<omp::clause::ThreadLimit>()) { + result = fir::getBase(converter.genExprValue(clause->v, stmtCtx)); return true; } return false; } bool ClauseProcessor::processUntied(mlir::UnitAttr &result) const { - return markClauseOccurrence<ClauseTy::Untied>(result); + return markClauseOccurrence<omp::clause::Untied>(result); } //===----------------------------------------------------------------------===// @@ -556,10 +507,10 @@ bool ClauseProcessor::processUntied(mlir::UnitAttr &result) const { bool ClauseProcessor::processAllocate( llvm::SmallVectorImpl<mlir::Value> &allocatorOperands, llvm::SmallVectorImpl<mlir::Value> &allocateOperands) const { - return findRepeatableClause<ClauseTy::Allocate>( - [&](const ClauseTy::Allocate *allocateClause, + return findRepeatableClause<omp::clause::Allocate>( + [&](const omp::clause::Allocate &clause, const Fortran::parser::CharBlock &) { - genAllocateClause(converter, allocateClause->v, allocatorOperands, + genAllocateClause(converter, clause, allocatorOperands, allocateOperands); }); } @@ -576,12 +527,12 @@ bool ClauseProcessor::processCopyin() const { if (converter.isPresentShallowLookup(*sym)) converter.copyHostAssociateVar(*sym, copyAssignIP); }; - bool hasCopyin = findRepeatableClause<ClauseTy::Copyin>( - [&](const ClauseTy::Copyin *copyinClause, + bool hasCopyin = findRepeatableClause<omp::clause::Copyin>( + [&](const omp::clause::Copyin &clause, const Fortran::parser::CharBlock &) { - const Fortran::parser::OmpObjectList &ompObjectList = copyinClause->v; - for (const Fortran::parser::OmpObject &ompObject : ompObjectList.v) { - Fortran::semantics::Symbol *sym = getOmpObjectSymbol(ompObject); + for (const omp::Object &object : clause.v) { + Fortran::semantics::Symbol *sym = object.id(); + assert(sym && "Expecting symbol"); if (const auto *commonDetails = sym->detailsIf<Fortran::semantics::CommonBlockDetails>()) { for (const auto &mem : commonDetails->objects()) @@ -620,7 +571,7 @@ public: } // Returns the shape of array types. - const llvm::SmallVector<int64_t> &getShape() const { return shape; } + llvm::ArrayRef<int64_t> getShape() const { return shape; } // Is the type inside a box? bool isBox() const { return inBox; } @@ -745,13 +696,11 @@ bool ClauseProcessor::processCopyPrivate( copyPrivateFuncs.push_back(mlir::SymbolRefAttr::get(funcOp)); }; - bool hasCopyPrivate = findRepeatableClause<ClauseTy::Copyprivate>( - [&](const ClauseTy::Copyprivate *copyPrivateClause, + bool hasCopyPrivate = findRepeatableClause<clause::Copyprivate>( + [&](const clause::Copyprivate &clause, const Fortran::parser::CharBlock &) { - const Fortran::parser::OmpObjectList &ompObjectList = - copyPrivateClause->v; - for (const Fortran::parser::OmpObject &ompObject : ompObjectList.v) { - Fortran::semantics::Symbol *sym = getOmpObjectSymbol(ompObject); + for (const Object &object : clause.v) { + Fortran::semantics::Symbol *sym = object.id(); if (const auto *commonDetails = sym->detailsIf<Fortran::semantics::CommonBlockDetails>()) { for (const auto &mem : commonDetails->objects()) @@ -770,38 +719,32 @@ bool ClauseProcessor::processDepend( llvm::SmallVectorImpl<mlir::Value> &dependOperands) const { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - return findRepeatableClause<ClauseTy::Depend>( - [&](const ClauseTy::Depend *dependClause, + return findRepeatableClause<omp::clause::Depend>( + [&](const omp::clause::Depend &clause, const Fortran::parser::CharBlock &) { - const std::list<Fortran::parser::Designator> &depVal = - std::get<std::list<Fortran::parser::Designator>>( - std::get<Fortran::parser::OmpDependClause::InOut>( - dependClause->v.u) - .t); + using Depend = omp::clause::Depend; + assert(std::holds_alternative<Depend::WithLocators>(clause.u) && + "Only the modern form is handled at the moment"); + auto &modern = std::get<Depend::WithLocators>(clause.u); + auto kind = std::get<Depend::TaskDependenceType>(modern.t); + auto &objects = std::get<omp::ObjectList>(modern.t); + mlir::omp::ClauseTaskDependAttr dependTypeOperand = - genDependKindAttr(firOpBuilder, dependClause); - dependTypeOperands.insert(dependTypeOperands.end(), depVal.size(), - dependTypeOperand); - for (const Fortran::parser::Designator &ompObject : depVal) { - Fortran::semantics::Symbol *sym = nullptr; - std::visit( - Fortran::common::visitors{ - [&](const Fortran::parser::DataRef &designator) { - if (const Fortran::parser::Name *name = - std::get_if<Fortran::parser::Name>(&designator.u)) { - sym = name->symbol; - } else if (std::get_if<Fortran::common::Indirection< - Fortran::parser::ArrayElement>>( - &designator.u)) { - TODO(converter.getCurrentLocation(), - "array sections not supported for task depend"); - } - }, - [&](const Fortran::parser::Substring &designator) { - TODO(converter.getCurrentLocation(), - "substring not supported for task depend"); - }}, - (ompObject).u); + genDependKindAttr(firOpBuilder, kind); + dependTypeOperands.append(objects.size(), dependTypeOperand); + + for (const omp::Object &object : objects) { + assert(object.ref() && "Expecting designator"); + + if (Fortran::evaluate::ExtractSubstring(*object.ref())) { + TODO(converter.getCurrentLocation(), + "substring not supported for task depend"); + } else if (Fortran::evaluate::IsArrayElement(*object.ref())) { + TODO(converter.getCurrentLocation(), + "array sections not supported for task depend"); + } + + Fortran::semantics::Symbol *sym = object.id(); const mlir::Value variable = converter.getSymbolAddress(*sym); dependOperands.push_back(variable); } @@ -809,14 +752,14 @@ bool ClauseProcessor::processDepend( } bool ClauseProcessor::processIf( - Fortran::parser::OmpIfClause::DirectiveNameModifier directiveName, + omp::clause::If::DirectiveNameModifier directiveName, mlir::Value &result) const { bool found = false; - findRepeatableClause<ClauseTy::If>( - [&](const ClauseTy::If *ifClause, + findRepeatableClause<omp::clause::If>( + [&](const omp::clause::If &clause, const Fortran::parser::CharBlock &source) { mlir::Location clauseLocation = converter.genLocation(source); - mlir::Value operand = getIfClauseOperand(converter, ifClause, + mlir::Value operand = getIfClauseOperand(converter, clause, directiveName, clauseLocation); // Assume that, at most, a single 'if' clause will be applicable to the // given directive. @@ -830,20 +773,19 @@ bool ClauseProcessor::processIf( bool ClauseProcessor::processLink( llvm::SmallVectorImpl<DeclareTargetCapturePair> &result) const { - return findRepeatableClause<ClauseTy::Link>( - [&](const ClauseTy::Link *linkClause, - const Fortran::parser::CharBlock &) { + return findRepeatableClause<omp::clause::Link>( + [&](const omp::clause::Link &clause, const Fortran::parser::CharBlock &) { // Case: declare target link(var1, var2)... gatherFuncAndVarSyms( - linkClause->v, mlir::omp::DeclareTargetCaptureClause::link, result); + clause.v, mlir::omp::DeclareTargetCaptureClause::link, result); }); } mlir::omp::MapInfoOp createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value baseAddr, mlir::Value varPtrPtr, std::string name, - mlir::SmallVector<mlir::Value> bounds, - mlir::SmallVector<mlir::Value> members, uint64_t mapType, + llvm::ArrayRef<mlir::Value> bounds, + llvm::ArrayRef<mlir::Value> members, uint64_t mapType, mlir::omp::VariableCaptureKind mapCaptureType, mlir::Type retTy, bool isVal) { if (auto boxTy = baseAddr.getType().dyn_cast<fir::BaseBoxType>()) { @@ -872,65 +814,64 @@ bool ClauseProcessor::processMap( llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *mapSymbols) const { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - return findRepeatableClause<ClauseTy::Map>( - [&](const ClauseTy::Map *mapClause, + return findRepeatableClause<omp::clause::Map>( + [&](const omp::clause::Map &clause, const Fortran::parser::CharBlock &source) { + using Map = omp::clause::Map; mlir::Location clauseLocation = converter.genLocation(source); - const auto &oMapType = - std::get<std::optional<Fortran::parser::OmpMapType>>( - mapClause->v.t); + const auto &mapType = std::get<std::optional<Map::MapType>>(clause.t); llvm::omp::OpenMPOffloadMappingFlags mapTypeBits = llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE; // If the map type is specified, then process it else Tofrom is the // default. - if (oMapType) { - const Fortran::parser::OmpMapType::Type &mapType = - std::get<Fortran::parser::OmpMapType::Type>(oMapType->t); - switch (mapType) { - case Fortran::parser::OmpMapType::Type::To: + if (mapType) { + switch (*mapType) { + case Map::MapType::To: mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO; break; - case Fortran::parser::OmpMapType::Type::From: + case Map::MapType::From: mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM; break; - case Fortran::parser::OmpMapType::Type::Tofrom: + case Map::MapType::Tofrom: mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO | llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM; break; - case Fortran::parser::OmpMapType::Type::Alloc: - case Fortran::parser::OmpMapType::Type::Release: + case Map::MapType::Alloc: + case Map::MapType::Release: // 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. break; - case Fortran::parser::OmpMapType::Type::Delete: + case Map::MapType::Delete: mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE; } - if (std::get<std::optional<Fortran::parser::OmpMapType::Always>>( - oMapType->t)) - mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS; + auto &modTypeMods = + std::get<std::optional<Map::MapTypeModifiers>>(clause.t); + if (modTypeMods) { + if (llvm::is_contained(*modTypeMods, Map::MapTypeModifier::Always)) + mapTypeBits |= + llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS; + } } else { mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO | llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM; } - for (const Fortran::parser::OmpObject &ompObject : - std::get<Fortran::parser::OmpObjectList>(mapClause->v.t).v) { + for (const omp::Object &object : std::get<omp::ObjectList>(clause.t)) { llvm::SmallVector<mlir::Value> bounds; std::stringstream asFortran; Fortran::lower::AddrAndBoundsInfo info = Fortran::lower::gatherDataOperandAddrAndBounds< - Fortran::parser::OmpObject, mlir::omp::DataBoundsOp, - mlir::omp::DataBoundsType>( - converter, firOpBuilder, semaCtx, stmtCtx, ompObject, - clauseLocation, asFortran, bounds, treatIndexAsSection); + mlir::omp::MapBoundsOp, mlir::omp::MapBoundsType>( + converter, firOpBuilder, semaCtx, stmtCtx, *object.id(), + object.ref(), clauseLocation, asFortran, bounds, + treatIndexAsSection); - auto origSymbol = - converter.getSymbolAddress(*getOmpObjectSymbol(ompObject)); + auto origSymbol = converter.getSymbolAddress(*object.id()); mlir::Value symAddr = info.addr; if (origSymbol && fir::isTypeWithDescriptor(origSymbol.getType())) symAddr = origSymbol; @@ -953,54 +894,75 @@ bool ClauseProcessor::processMap( mapSymLocs->push_back(symAddr.getLoc()); if (mapSymbols) - mapSymbols->push_back(getOmpObjectSymbol(ompObject)); + mapSymbols->push_back(object.id()); } }); } bool ClauseProcessor::processReduction( mlir::Location currentLocation, - llvm::SmallVectorImpl<mlir::Value> &reductionVars, - llvm::SmallVectorImpl<mlir::Attribute> &reductionDeclSymbols, - llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *reductionSymbols) - const { - return findRepeatableClause<ClauseTy::Reduction>( - [&](const ClauseTy::Reduction *reductionClause, + llvm::SmallVectorImpl<mlir::Value> &outReductionVars, + llvm::SmallVectorImpl<mlir::Type> &outReductionTypes, + llvm::SmallVectorImpl<mlir::Attribute> &outReductionDeclSymbols, + llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> + *outReductionSymbols) const { + return findRepeatableClause<omp::clause::Reduction>( + [&](const omp::clause::Reduction &clause, const Fortran::parser::CharBlock &) { + // Use local lists of reductions to prevent variables from other + // already-processed reduction clauses from impacting this reduction. + // For example, the whole `reductionVars` array is queried to decide + // whether to do the reduction byref. + llvm::SmallVector<mlir::Value> reductionVars; + llvm::SmallVector<mlir::Attribute> reductionDeclSymbols; + llvm::SmallVector<const Fortran::semantics::Symbol *> reductionSymbols; ReductionProcessor rp; - rp.addReductionDecl(currentLocation, converter, reductionClause->v, - reductionVars, reductionDeclSymbols, - reductionSymbols); + rp.addDeclareReduction(currentLocation, converter, clause, + reductionVars, reductionDeclSymbols, + outReductionSymbols ? &reductionSymbols + : nullptr); + + // Copy local lists into the output. + llvm::copy(reductionVars, std::back_inserter(outReductionVars)); + llvm::copy(reductionDeclSymbols, + std::back_inserter(outReductionDeclSymbols)); + if (outReductionSymbols) + llvm::copy(reductionSymbols, + std::back_inserter(*outReductionSymbols)); + + outReductionTypes.reserve(outReductionTypes.size() + + reductionVars.size()); + llvm::transform(reductionVars, std::back_inserter(outReductionTypes), + [](mlir::Value v) { return v.getType(); }); }); } bool ClauseProcessor::processSectionsReduction( mlir::Location currentLocation) const { - return findRepeatableClause<ClauseTy::Reduction>( - [&](const ClauseTy::Reduction *, const Fortran::parser::CharBlock &) { + return findRepeatableClause<omp::clause::Reduction>( + [&](const omp::clause::Reduction &, const Fortran::parser::CharBlock &) { TODO(currentLocation, "OMPC_Reduction"); }); } bool ClauseProcessor::processTo( llvm::SmallVectorImpl<DeclareTargetCapturePair> &result) const { - return findRepeatableClause<ClauseTy::To>( - [&](const ClauseTy::To *toClause, const Fortran::parser::CharBlock &) { + return findRepeatableClause<omp::clause::To>( + [&](const omp::clause::To &clause, const Fortran::parser::CharBlock &) { // Case: declare target to(func, var1, var2)... - gatherFuncAndVarSyms(toClause->v, + gatherFuncAndVarSyms(std::get<ObjectList>(clause.t), mlir::omp::DeclareTargetCaptureClause::to, result); }); } bool ClauseProcessor::processEnter( llvm::SmallVectorImpl<DeclareTargetCapturePair> &result) const { - return findRepeatableClause<ClauseTy::Enter>( - [&](const ClauseTy::Enter *enterClause, + return findRepeatableClause<omp::clause::Enter>( + [&](const omp::clause::Enter &clause, const Fortran::parser::CharBlock &) { // Case: declare target enter(func, var1, var2)... - gatherFuncAndVarSyms(enterClause->v, - mlir::omp::DeclareTargetCaptureClause::enter, - result); + gatherFuncAndVarSyms( + clause.v, mlir::omp::DeclareTargetCaptureClause::enter, result); }); } @@ -1010,11 +972,11 @@ bool ClauseProcessor::processUseDeviceAddr( llvm::SmallVectorImpl<mlir::Location> &useDeviceLocs, llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> &useDeviceSymbols) const { - return findRepeatableClause<ClauseTy::UseDeviceAddr>( - [&](const ClauseTy::UseDeviceAddr *devAddrClause, + return findRepeatableClause<omp::clause::UseDeviceAddr>( + [&](const omp::clause::UseDeviceAddr &clause, const Fortran::parser::CharBlock &) { - addUseDeviceClause(converter, devAddrClause->v, operands, - useDeviceTypes, useDeviceLocs, useDeviceSymbols); + addUseDeviceClause(converter, clause.v, operands, useDeviceTypes, + useDeviceLocs, useDeviceSymbols); }); } @@ -1024,10 +986,10 @@ bool ClauseProcessor::processUseDevicePtr( llvm::SmallVectorImpl<mlir::Location> &useDeviceLocs, llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> &useDeviceSymbols) const { - return findRepeatableClause<ClauseTy::UseDevicePtr>( - [&](const ClauseTy::UseDevicePtr *devPtrClause, + return findRepeatableClause<omp::clause::UseDevicePtr>( + [&](const omp::clause::UseDevicePtr &clause, const Fortran::parser::CharBlock &) { - addUseDeviceClause(converter, devPtrClause->v, operands, useDeviceTypes, + addUseDeviceClause(converter, clause.v, operands, useDeviceTypes, useDeviceLocs, useDeviceSymbols); }); } diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.h b/flang/lib/Lower/OpenMP/ClauseProcessor.h index 11aff0be25053dbc8e458e1ccdb8667fd8bb54c6..d31d6a5c20623af7597a03af8b721b2a47213f64 100644 --- a/flang/lib/Lower/OpenMP/ClauseProcessor.h +++ b/flang/lib/Lower/OpenMP/ClauseProcessor.h @@ -12,6 +12,7 @@ #ifndef FORTRAN_LOWER_CLAUASEPROCESSOR_H #define FORTRAN_LOWER_CLAUASEPROCESSOR_H +#include "Clauses.h" #include "DirectivesCommon.h" #include "ReductionProcessor.h" #include "Utils.h" @@ -45,23 +46,20 @@ namespace omp { /// methods that relate to clauses that can impact the lowering of that /// construct. class ClauseProcessor { - using ClauseTy = Fortran::parser::OmpClause; - public: ClauseProcessor(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, const Fortran::parser::OmpClauseList &clauses) - : converter(converter), semaCtx(semaCtx), clauses(clauses) {} + : converter(converter), semaCtx(semaCtx), + clauses(makeClauses(clauses, semaCtx)) {} // 'Unique' clauses: They can appear at most once in the clause list. - bool - processCollapse(mlir::Location currentLocation, - Fortran::lower::pft::Evaluation &eval, - llvm::SmallVectorImpl<mlir::Value> &lowerBound, - llvm::SmallVectorImpl<mlir::Value> &upperBound, - llvm::SmallVectorImpl<mlir::Value> &step, - llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> &iv, - std::size_t &loopVarTypeSize) const; + bool processCollapse( + mlir::Location currentLocation, Fortran::lower::pft::Evaluation &eval, + llvm::SmallVectorImpl<mlir::Value> &lowerBound, + llvm::SmallVectorImpl<mlir::Value> &upperBound, + llvm::SmallVectorImpl<mlir::Value> &step, + llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> &iv) const; bool processDefault() const; bool processDevice(Fortran::lower::StatementContext &stmtCtx, mlir::Value &result) const; @@ -103,9 +101,8 @@ public: llvm::SmallVectorImpl<mlir::Value> &dependOperands) const; bool processEnter(llvm::SmallVectorImpl<DeclareTargetCapturePair> &result) const; - bool - processIf(Fortran::parser::OmpIfClause::DirectiveNameModifier directiveName, - mlir::Value &result) const; + bool processIf(omp::clause::If::DirectiveNameModifier directiveName, + mlir::Value &result) const; bool processLink(llvm::SmallVectorImpl<DeclareTargetCapturePair> &result) const; @@ -125,6 +122,7 @@ public: bool processReduction(mlir::Location currentLocation, llvm::SmallVectorImpl<mlir::Value> &reductionVars, + llvm::SmallVectorImpl<mlir::Type> &reductionTypes, llvm::SmallVectorImpl<mlir::Attribute> &reductionDeclSymbols, llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *reductionSymbols = nullptr) const; @@ -155,7 +153,7 @@ public: llvm::omp::Directive directive) const; private: - using ClauseIterator = std::list<ClauseTy>::const_iterator; + using ClauseIterator = List<Clause>::const_iterator; /// Utility to find a clause within a range in the clause list. template <typename T> @@ -172,7 +170,7 @@ private: /// if at least one instance was found. template <typename T> bool findRepeatableClause( - std::function<void(const T *, const Fortran::parser::CharBlock &source)> + std::function<void(const T &, const Fortran::parser::CharBlock &source)> callbackFn) const; /// Set the `result` to a new `mlir::UnitAttr` if the clause is present. @@ -181,7 +179,7 @@ private: Fortran::lower::AbstractConverter &converter; Fortran::semantics::SemanticsContext &semaCtx; - const Fortran::parser::OmpClauseList &clauses; + List<Clause> clauses; }; template <typename T> @@ -189,31 +187,31 @@ bool ClauseProcessor::processMotionClauses( Fortran::lower::StatementContext &stmtCtx, llvm::SmallVectorImpl<mlir::Value> &mapOperands) { return findRepeatableClause<T>( - [&](const T *motionClause, const Fortran::parser::CharBlock &source) { + [&](const T &clause, const Fortran::parser::CharBlock &source) { mlir::Location clauseLocation = converter.genLocation(source); fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - static_assert(std::is_same_v<T, ClauseProcessor::ClauseTy::To> || - std::is_same_v<T, ClauseProcessor::ClauseTy::From>); + static_assert(std::is_same_v<T, omp::clause::To> || + std::is_same_v<T, omp::clause::From>); // TODO Support motion modifiers: present, mapper, iterator. constexpr llvm::omp::OpenMPOffloadMappingFlags mapTypeBits = - std::is_same_v<T, ClauseProcessor::ClauseTy::To> + std::is_same_v<T, omp::clause::To> ? llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO : llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM; - for (const Fortran::parser::OmpObject &ompObject : motionClause->v.v) { + auto &objects = std::get<ObjectList>(clause.t); + for (const omp::Object &object : objects) { llvm::SmallVector<mlir::Value> bounds; std::stringstream asFortran; Fortran::lower::AddrAndBoundsInfo info = Fortran::lower::gatherDataOperandAddrAndBounds< - Fortran::parser::OmpObject, mlir::omp::DataBoundsOp, - mlir::omp::DataBoundsType>( - converter, firOpBuilder, semaCtx, stmtCtx, ompObject, - clauseLocation, asFortran, bounds, treatIndexAsSection); + mlir::omp::MapBoundsOp, mlir::omp::MapBoundsType>( + converter, firOpBuilder, semaCtx, stmtCtx, *object.id(), + object.ref(), clauseLocation, asFortran, bounds, + treatIndexAsSection); - auto origSymbol = - converter.getSymbolAddress(*getOmpObjectSymbol(ompObject)); + auto origSymbol = converter.getSymbolAddress(*object.id()); mlir::Value symAddr = info.addr; if (origSymbol && fir::isTypeWithDescriptor(origSymbol.getType())) symAddr = origSymbol; @@ -237,19 +235,17 @@ bool ClauseProcessor::processMotionClauses( template <typename... Ts> void ClauseProcessor::processTODO(mlir::Location currentLocation, llvm::omp::Directive directive) const { - auto checkUnhandledClause = [&](const auto *x) { + auto checkUnhandledClause = [&](llvm::omp::Clause id, const auto *x) { if (!x) return; TODO(currentLocation, - "Unhandled clause " + - llvm::StringRef(Fortran::parser::ParseTreeDumper::GetNodeName(*x)) - .upper() + + "Unhandled clause " + llvm::omp::getOpenMPClauseName(id).upper() + " in " + llvm::omp::getOpenMPDirectiveName(directive).upper() + " construct"); }; - for (ClauseIterator it = clauses.v.begin(); it != clauses.v.end(); ++it) - (checkUnhandledClause(std::get_if<Ts>(&it->u)), ...); + for (ClauseIterator it = clauses.begin(); it != clauses.end(); ++it) + (checkUnhandledClause(it->id, std::get_if<Ts>(&it->u)), ...); } template <typename T> @@ -266,8 +262,8 @@ ClauseProcessor::findClause(ClauseIterator begin, ClauseIterator end) { template <typename T> const T *ClauseProcessor::findUniqueClause( const Fortran::parser::CharBlock **source) const { - ClauseIterator it = findClause<T>(clauses.v.begin(), clauses.v.end()); - if (it != clauses.v.end()) { + ClauseIterator it = findClause<T>(clauses.begin(), clauses.end()); + if (it != clauses.end()) { if (source) *source = &it->source; return &std::get<T>(it->u); @@ -277,15 +273,15 @@ const T *ClauseProcessor::findUniqueClause( template <typename T> bool ClauseProcessor::findRepeatableClause( - std::function<void(const T *, const Fortran::parser::CharBlock &source)> + std::function<void(const T &, const Fortran::parser::CharBlock &source)> callbackFn) const { bool found = false; - ClauseIterator nextIt, endIt = clauses.v.end(); - for (ClauseIterator it = clauses.v.begin(); it != endIt; it = nextIt) { + ClauseIterator nextIt, endIt = clauses.end(); + for (ClauseIterator it = clauses.begin(); it != endIt; it = nextIt) { nextIt = findClause<T>(it, endIt); if (nextIt != endIt) { - callbackFn(&std::get<T>(nextIt->u), nextIt->source); + callbackFn(std::get<T>(nextIt->u), nextIt->source); found = true; ++nextIt; } diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp new file mode 100644 index 0000000000000000000000000000000000000000..40da71c8b55f80d19d3982ddce79de14cc2a1d12 --- /dev/null +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -0,0 +1,1214 @@ +//===-- Clauses.cpp -- OpenMP clause handling -----------------------------===// +// +// 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 "Clauses.h" + +#include "flang/Common/idioms.h" +#include "flang/Evaluate/expression.h" +#include "flang/Parser/parse-tree.h" +#include "flang/Semantics/expression.h" +#include "flang/Semantics/symbol.h" + +#include "llvm/Frontend/OpenMP/OMPConstants.h" + +#include <list> +#include <optional> +#include <tuple> +#include <utility> +#include <variant> + +namespace detail { +template <typename C> +llvm::omp::Clause getClauseIdForClass(C &&) { + using namespace Fortran; + using A = llvm::remove_cvref_t<C>; // A is referenced in OMP.inc + // The code included below contains a sequence of checks like the following + // for each OpenMP clause + // if constexpr (std::is_same_v<A, parser::OmpClause::AcqRel>) + // return llvm::omp::Clause::OMPC_acq_rel; + // [...] +#define GEN_FLANG_CLAUSE_PARSER_KIND_MAP +#include "llvm/Frontend/OpenMP/OMP.inc" +} +} // namespace detail + +static llvm::omp::Clause getClauseId(const Fortran::parser::OmpClause &clause) { + return std::visit([](auto &&s) { return detail::getClauseIdForClass(s); }, + clause.u); +} + +namespace Fortran::lower::omp { +using SymbolWithDesignator = std::tuple<semantics::Symbol *, MaybeExpr>; + +struct SymbolAndDesignatorExtractor { + template <typename T> + static T &&AsRvalueRef(T &&t) { + return std::move(t); + } + template <typename T> + static T AsRvalueRef(const T &t) { + return t; + } + + static semantics::Symbol *symbol_addr(const evaluate::SymbolRef &ref) { + // Symbols cannot be created after semantic checks, so all symbol + // pointers that are non-null must point to one of those pre-existing + // objects. Throughout the code, symbols are often pointed to by + // non-const pointers, so there is no harm in casting the constness + // away. + return const_cast<semantics::Symbol *>(&ref.get()); + } + + template <typename T> + static SymbolWithDesignator visit(T &&) { + // Use this to see missing overloads: + // llvm::errs() << "NULL: " << __PRETTY_FUNCTION__ << '\n'; + return SymbolWithDesignator{}; + } + + template <typename T> + static SymbolWithDesignator visit(const evaluate::Designator<T> &e) { + return std::make_tuple(symbol_addr(*e.GetLastSymbol()), + evaluate::AsGenericExpr(AsRvalueRef(e))); + } + + static SymbolWithDesignator visit(const evaluate::ProcedureDesignator &e) { + return std::make_tuple(symbol_addr(*e.GetSymbol()), std::nullopt); + } + + template <typename T> + static SymbolWithDesignator visit(const evaluate::Expr<T> &e) { + return std::visit([](auto &&s) { return visit(s); }, e.u); + } + + static void verify(const SymbolWithDesignator &sd) { + const semantics::Symbol *symbol = std::get<0>(sd); + assert(symbol && "Expecting symbol"); + auto &maybeDsg = std::get<1>(sd); + if (!maybeDsg) + return; // Symbol with no designator -> OK + std::optional<evaluate::DataRef> maybeRef = + evaluate::ExtractDataRef(*maybeDsg); + if (maybeRef) { + if (&maybeRef->GetLastSymbol() == symbol) + return; // Symbol with a designator for it -> OK + llvm_unreachable("Expecting designator for given symbol"); + } else { + // This could still be a Substring or ComplexPart, but at least Substring + // is not allowed in OpenMP. +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + maybeDsg->dump(); +#endif + llvm_unreachable("Expecting DataRef designator"); + } + } +}; + +SymbolWithDesignator getSymbolAndDesignator(const MaybeExpr &expr) { + if (!expr) + return SymbolWithDesignator{}; + return std::visit( + [](auto &&s) { return SymbolAndDesignatorExtractor::visit(s); }, expr->u); +} + +Object makeObject(const parser::Name &name, + semantics::SemanticsContext &semaCtx) { + assert(name.symbol && "Expecting Symbol"); + return Object{name.symbol, std::nullopt}; +} + +Object makeObject(const parser::Designator &dsg, + semantics::SemanticsContext &semaCtx) { + evaluate::ExpressionAnalyzer ea{semaCtx}; + SymbolWithDesignator sd = getSymbolAndDesignator(ea.Analyze(dsg)); + SymbolAndDesignatorExtractor::verify(sd); + return Object{std::get<0>(sd), std::move(std::get<1>(sd))}; +} + +Object makeObject(const parser::StructureComponent &comp, + semantics::SemanticsContext &semaCtx) { + evaluate::ExpressionAnalyzer ea{semaCtx}; + SymbolWithDesignator sd = getSymbolAndDesignator(ea.Analyze(comp)); + SymbolAndDesignatorExtractor::verify(sd); + return Object{std::get<0>(sd), std::move(std::get<1>(sd))}; +} + +Object makeObject(const parser::OmpObject &object, + semantics::SemanticsContext &semaCtx) { + // If object is a common block, expression analyzer won't be able to + // do anything. + if (const auto *name = std::get_if<parser::Name>(&object.u)) { + assert(name->symbol && "Expecting Symbol"); + return Object{name->symbol, std::nullopt}; + } + // OmpObject is std::variant<Designator, /*common block*/ Name>; + return makeObject(std::get<parser::Designator>(object.u), semaCtx); +} + +std::optional<Object> +getBaseObject(const Object &object, + Fortran::semantics::SemanticsContext &semaCtx) { + // If it's just the symbol, then there is no base. + if (!object.id()) + return std::nullopt; + + auto maybeRef = evaluate::ExtractDataRef(*object.ref()); + if (!maybeRef) + return std::nullopt; + + evaluate::DataRef ref = *maybeRef; + + if (std::get_if<evaluate::SymbolRef>(&ref.u)) { + return std::nullopt; + } else if (auto *comp = std::get_if<evaluate::Component>(&ref.u)) { + const evaluate::DataRef &base = comp->base(); + return Object{ + SymbolAndDesignatorExtractor::symbol_addr(base.GetLastSymbol()), + evaluate::AsGenericExpr( + SymbolAndDesignatorExtractor::AsRvalueRef(base))}; + } else if (auto *arr = std::get_if<evaluate::ArrayRef>(&ref.u)) { + const evaluate::NamedEntity &base = arr->base(); + evaluate::ExpressionAnalyzer ea{semaCtx}; + if (auto *comp = base.UnwrapComponent()) { + return Object{SymbolAndDesignatorExtractor::symbol_addr(comp->symbol()), + ea.Designate(evaluate::DataRef{ + SymbolAndDesignatorExtractor::AsRvalueRef(*comp)})}; + } else if (base.UnwrapSymbolRef()) { + return std::nullopt; + } + } else { + assert(std::holds_alternative<evaluate::CoarrayRef>(ref.u) && + "Unexpected variant alternative"); + llvm_unreachable("Coarray reference not supported at the moment"); + } + return std::nullopt; +} + +// Helper macros +#define MAKE_EMPTY_CLASS(cls, from_cls) \ + cls make(const parser::OmpClause::from_cls &, \ + semantics::SemanticsContext &) { \ + static_assert(cls::EmptyTrait::value); \ + return cls{}; \ + } \ + [[maybe_unused]] extern int xyzzy_semicolon_absorber + +#define MAKE_INCOMPLETE_CLASS(cls, from_cls) \ + cls make(const parser::OmpClause::from_cls &, \ + semantics::SemanticsContext &) { \ + static_assert(cls::IncompleteTrait::value); \ + return cls{}; \ + } \ + [[maybe_unused]] extern int xyzzy_semicolon_absorber + +#define MS(x, y) CLAUSET_SCOPED_ENUM_MEMBER_CONVERT(x, y) +#define MU(x, y) CLAUSET_UNSCOPED_ENUM_MEMBER_CONVERT(x, y) + +namespace clause { +MAKE_EMPTY_CLASS(AcqRel, AcqRel); +MAKE_EMPTY_CLASS(Acquire, Acquire); +MAKE_EMPTY_CLASS(Capture, Capture); +MAKE_EMPTY_CLASS(Compare, Compare); +MAKE_EMPTY_CLASS(DynamicAllocators, DynamicAllocators); +MAKE_EMPTY_CLASS(Full, Full); +MAKE_EMPTY_CLASS(Inbranch, Inbranch); +MAKE_EMPTY_CLASS(Mergeable, Mergeable); +MAKE_EMPTY_CLASS(Nogroup, Nogroup); +// MAKE_EMPTY_CLASS(NoOpenmp, ); // missing-in-parser +// MAKE_EMPTY_CLASS(NoOpenmpRoutines, ); // missing-in-parser +// MAKE_EMPTY_CLASS(NoParallelism, ); // missing-in-parser +MAKE_EMPTY_CLASS(Notinbranch, Notinbranch); +MAKE_EMPTY_CLASS(Nowait, Nowait); +MAKE_EMPTY_CLASS(OmpxAttribute, OmpxAttribute); +MAKE_EMPTY_CLASS(OmpxBare, OmpxBare); +MAKE_EMPTY_CLASS(Read, Read); +MAKE_EMPTY_CLASS(Relaxed, Relaxed); +MAKE_EMPTY_CLASS(Release, Release); +MAKE_EMPTY_CLASS(ReverseOffload, ReverseOffload); +MAKE_EMPTY_CLASS(SeqCst, SeqCst); +MAKE_EMPTY_CLASS(Simd, Simd); +MAKE_EMPTY_CLASS(Threads, Threads); +MAKE_EMPTY_CLASS(UnifiedAddress, UnifiedAddress); +MAKE_EMPTY_CLASS(UnifiedSharedMemory, UnifiedSharedMemory); +MAKE_EMPTY_CLASS(Unknown, Unknown); +MAKE_EMPTY_CLASS(Untied, Untied); +MAKE_EMPTY_CLASS(Weak, Weak); +MAKE_EMPTY_CLASS(Write, Write); + +// Artificial clauses +MAKE_EMPTY_CLASS(CancellationConstructType, CancellationConstructType); +MAKE_EMPTY_CLASS(Depobj, Depobj); +MAKE_EMPTY_CLASS(Flush, Flush); +MAKE_EMPTY_CLASS(MemoryOrder, MemoryOrder); +MAKE_EMPTY_CLASS(Threadprivate, Threadprivate); + +MAKE_INCOMPLETE_CLASS(AdjustArgs, AdjustArgs); +MAKE_INCOMPLETE_CLASS(AppendArgs, AppendArgs); +MAKE_INCOMPLETE_CLASS(Match, Match); +// MAKE_INCOMPLETE_CLASS(Otherwise, ); // missing-in-parser +MAKE_INCOMPLETE_CLASS(When, When); + +DefinedOperator makeDefinedOperator(const parser::DefinedOperator &inp, + semantics::SemanticsContext &semaCtx) { + CLAUSET_ENUM_CONVERT( // + convert, parser::DefinedOperator::IntrinsicOperator, + DefinedOperator::IntrinsicOperator, + // clang-format off + MS(Add, Add) + MS(AND, AND) + MS(Concat, Concat) + MS(Divide, Divide) + MS(EQ, EQ) + MS(EQV, EQV) + MS(GE, GE) + MS(GT, GT) + MS(NOT, NOT) + MS(LE, LE) + MS(LT, LT) + MS(Multiply, Multiply) + MS(NE, NE) + MS(NEQV, NEQV) + MS(OR, OR) + MS(Power, Power) + MS(Subtract, Subtract) + // clang-format on + ); + + return std::visit( + common::visitors{ + [&](const parser::DefinedOpName &s) { + return DefinedOperator{ + DefinedOperator::DefinedOpName{makeObject(s.v, semaCtx)}}; + }, + [&](const parser::DefinedOperator::IntrinsicOperator &s) { + return DefinedOperator{convert(s)}; + }, + }, + inp.u); +} + +ProcedureDesignator +makeProcedureDesignator(const parser::ProcedureDesignator &inp, + semantics::SemanticsContext &semaCtx) { + return ProcedureDesignator{std::visit( + common::visitors{ + [&](const parser::Name &t) { return makeObject(t, semaCtx); }, + [&](const parser::ProcComponentRef &t) { + return makeObject(t.v.thing, semaCtx); + }, + }, + inp.u)}; +} + +ReductionOperator makeReductionOperator(const parser::OmpReductionOperator &inp, + semantics::SemanticsContext &semaCtx) { + return std::visit( + common::visitors{ + [&](const parser::DefinedOperator &s) { + return ReductionOperator{makeDefinedOperator(s, semaCtx)}; + }, + [&](const parser::ProcedureDesignator &s) { + return ReductionOperator{makeProcedureDesignator(s, semaCtx)}; + }, + }, + inp.u); +} + +// -------------------------------------------------------------------- +// Actual clauses. Each T (where tomp::T exists in ClauseT) has its "make". + +// Absent: missing-in-parser +// AcqRel: empty +// Acquire: empty +// AdjustArgs: incomplete + +Affinity make(const parser::OmpClause::Affinity &inp, + semantics::SemanticsContext &semaCtx) { + // inp -> empty + llvm_unreachable("Empty: affinity"); +} + +Align make(const parser::OmpClause::Align &inp, + semantics::SemanticsContext &semaCtx) { + // inp -> empty + llvm_unreachable("Empty: align"); +} + +Aligned make(const parser::OmpClause::Aligned &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpAlignedClause + auto &t0 = std::get<parser::OmpObjectList>(inp.v.t); + auto &t1 = std::get<std::optional<parser::ScalarIntConstantExpr>>(inp.v.t); + + return Aligned{{ + /*Alignment=*/maybeApply(makeExprFn(semaCtx), t1), + /*List=*/makeObjects(t0, semaCtx), + }}; +} + +Allocate make(const parser::OmpClause::Allocate &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpAllocateClause + using wrapped = parser::OmpAllocateClause; + auto &t0 = std::get<std::optional<wrapped::AllocateModifier>>(inp.v.t); + auto &t1 = std::get<parser::OmpObjectList>(inp.v.t); + + if (!t0) { + return Allocate{{/*AllocatorSimpleModifier=*/std::nullopt, + /*AllocatorComplexModifier=*/std::nullopt, + /*AlignModifier=*/std::nullopt, + /*List=*/makeObjects(t1, semaCtx)}}; + } + + using Tuple = decltype(Allocate::t); + + return Allocate{std::visit( + common::visitors{ + // simple-modifier + [&](const wrapped::AllocateModifier::Allocator &v) -> Tuple { + return {/*AllocatorSimpleModifier=*/makeExpr(v.v, semaCtx), + /*AllocatorComplexModifier=*/std::nullopt, + /*AlignModifier=*/std::nullopt, + /*List=*/makeObjects(t1, semaCtx)}; + }, + // complex-modifier + align-modifier + [&](const wrapped::AllocateModifier::ComplexModifier &v) -> Tuple { + auto &s0 = std::get<wrapped::AllocateModifier::Allocator>(v.t); + auto &s1 = std::get<wrapped::AllocateModifier::Align>(v.t); + return { + /*AllocatorSimpleModifier=*/std::nullopt, + /*AllocatorComplexModifier=*/Allocator{makeExpr(s0.v, semaCtx)}, + /*AlignModifier=*/Align{makeExpr(s1.v, semaCtx)}, + /*List=*/makeObjects(t1, semaCtx)}; + }, + // align-modifier + [&](const wrapped::AllocateModifier::Align &v) -> Tuple { + return {/*AllocatorSimpleModifier=*/std::nullopt, + /*AllocatorComplexModifier=*/std::nullopt, + /*AlignModifier=*/Align{makeExpr(v.v, semaCtx)}, + /*List=*/makeObjects(t1, semaCtx)}; + }, + }, + t0->u)}; +} + +Allocator make(const parser::OmpClause::Allocator &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntExpr + return Allocator{/*Allocator=*/makeExpr(inp.v, semaCtx)}; +} + +// AppendArgs: incomplete + +At make(const parser::OmpClause::At &inp, + semantics::SemanticsContext &semaCtx) { + // inp -> empty + llvm_unreachable("Empty: at"); +} + +// Never called, but needed for using "make" as a Clause visitor. +// See comment about "requires" clauses in Clauses.h. +AtomicDefaultMemOrder make(const parser::OmpClause::AtomicDefaultMemOrder &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpAtomicDefaultMemOrderClause + CLAUSET_ENUM_CONVERT( // + convert, common::OmpAtomicDefaultMemOrderType, + AtomicDefaultMemOrder::MemoryOrder, + // clang-format off + MS(AcqRel, AcqRel) + MS(Relaxed, Relaxed) + MS(SeqCst, SeqCst) + // clang-format on + ); + + return AtomicDefaultMemOrder{/*MemoryOrder=*/convert(inp.v.v)}; +} + +Bind make(const parser::OmpClause::Bind &inp, + semantics::SemanticsContext &semaCtx) { + // inp -> empty + llvm_unreachable("Empty: bind"); +} + +// CancellationConstructType: empty +// Capture: empty + +Collapse make(const parser::OmpClause::Collapse &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntConstantExpr + return Collapse{/*N=*/makeExpr(inp.v, semaCtx)}; +} + +// Compare: empty +// Contains: missing-in-parser + +Copyin make(const parser::OmpClause::Copyin &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return Copyin{/*List=*/makeObjects(inp.v, semaCtx)}; +} + +Copyprivate make(const parser::OmpClause::Copyprivate &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return Copyprivate{/*List=*/makeObjects(inp.v, semaCtx)}; +} + +Default make(const parser::OmpClause::Default &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpDefaultClause + using wrapped = parser::OmpDefaultClause; + + CLAUSET_ENUM_CONVERT( // + convert, wrapped::Type, Default::DataSharingAttribute, + // clang-format off + MS(Firstprivate, Firstprivate) + MS(None, None) + MS(Private, Private) + MS(Shared, Shared) + // clang-format on + ); + + return Default{/*DataSharingAttribute=*/convert(inp.v.v)}; +} + +Defaultmap make(const parser::OmpClause::Defaultmap &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpDefaultmapClause + using wrapped = parser::OmpDefaultmapClause; + + CLAUSET_ENUM_CONVERT( // + convert1, wrapped::ImplicitBehavior, Defaultmap::ImplicitBehavior, + // clang-format off + MS(Alloc, Alloc) + MS(To, To) + MS(From, From) + MS(Tofrom, Tofrom) + MS(Firstprivate, Firstprivate) + MS(None, None) + MS(Default, Default) + // MS(, Present) missing-in-parser + // clang-format on + ); + + CLAUSET_ENUM_CONVERT( // + convert2, wrapped::VariableCategory, Defaultmap::VariableCategory, + // clang-format off + MS(Scalar, Scalar) + MS(Aggregate, Aggregate) + MS(Pointer, Pointer) + MS(Allocatable, Allocatable) + // clang-format on + ); + + auto &t0 = std::get<wrapped::ImplicitBehavior>(inp.v.t); + auto &t1 = std::get<std::optional<wrapped::VariableCategory>>(inp.v.t); + return Defaultmap{{/*ImplicitBehavior=*/convert1(t0), + /*VariableCategory=*/maybeApply(convert2, t1)}}; +} + +Depend make(const parser::OmpClause::Depend &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpDependClause + using wrapped = parser::OmpDependClause; + using Variant = decltype(Depend::u); + // Iteration is the equivalent of parser::OmpDependSinkVec + using Iteration = Doacross::Vector::value_type; // LoopIterationT + + CLAUSET_ENUM_CONVERT( // + convert1, parser::OmpDependenceType::Type, Depend::TaskDependenceType, + // clang-format off + MS(In, In) + MS(Out, Out) + MS(Inout, Inout) + // MS(, Mutexinoutset) // missing-in-parser + // MS(, Inputset) // missing-in-parser + // MS(, Depobj) // missing-in-parser + // clang-format on + ); + + return Depend{std::visit( // + common::visitors{ + // Doacross + [&](const wrapped::Source &s) -> Variant { + return Doacross{ + {/*DependenceType=*/Doacross::DependenceType::Source, + /*Vector=*/{}}}; + }, + // Doacross + [&](const wrapped::Sink &s) -> Variant { + using DependLength = parser::OmpDependSinkVecLength; + auto convert2 = [&](const parser::OmpDependSinkVec &v) { + auto &t0 = std::get<parser::Name>(v.t); + auto &t1 = std::get<std::optional<DependLength>>(v.t); + + auto convert3 = [&](const DependLength &u) { + auto &s0 = std::get<parser::DefinedOperator>(u.t); + auto &s1 = std::get<parser::ScalarIntConstantExpr>(u.t); + return Iteration::Distance{ + {makeDefinedOperator(s0, semaCtx), makeExpr(s1, semaCtx)}}; + }; + return Iteration{ + {makeObject(t0, semaCtx), maybeApply(convert3, t1)}}; + }; + return Doacross{{/*DependenceType=*/Doacross::DependenceType::Sink, + /*Vector=*/makeList(s.v, convert2)}}; + }, + // Depend::WithLocators + [&](const wrapped::InOut &s) -> Variant { + auto &t0 = std::get<parser::OmpDependenceType>(s.t); + auto &t1 = std::get<std::list<parser::Designator>>(s.t); + auto convert4 = [&](const parser::Designator &t) { + return makeObject(t, semaCtx); + }; + return Depend::WithLocators{ + {/*TaskDependenceType=*/convert1(t0.v), + /*Iterator=*/std::nullopt, + /*LocatorList=*/makeList(t1, convert4)}}; + }, + }, + inp.v.u)}; +} + +// Depobj: empty + +Destroy make(const parser::OmpClause::Destroy &inp, + semantics::SemanticsContext &semaCtx) { + // inp -> empty + llvm_unreachable("Empty: destroy"); +} + +Detach make(const parser::OmpClause::Detach &inp, + semantics::SemanticsContext &semaCtx) { + // inp -> empty + llvm_unreachable("Empty: detach"); +} + +Device make(const parser::OmpClause::Device &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpDeviceClause + using wrapped = parser::OmpDeviceClause; + + CLAUSET_ENUM_CONVERT( // + convert, parser::OmpDeviceClause::DeviceModifier, Device::DeviceModifier, + // clang-format off + MS(Ancestor, Ancestor) + MS(Device_Num, DeviceNum) + // clang-format on + ); + auto &t0 = std::get<std::optional<wrapped::DeviceModifier>>(inp.v.t); + auto &t1 = std::get<parser::ScalarIntExpr>(inp.v.t); + return Device{{/*DeviceModifier=*/maybeApply(convert, t0), + /*DeviceDescription=*/makeExpr(t1, semaCtx)}}; +} + +DeviceType make(const parser::OmpClause::DeviceType &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpDeviceTypeClause + using wrapped = parser::OmpDeviceTypeClause; + + CLAUSET_ENUM_CONVERT( // + convert, wrapped::Type, DeviceType::DeviceTypeDescription, + // clang-format off + MS(Any, Any) + MS(Host, Host) + MS(Nohost, Nohost) + // clang-format om + ); + return DeviceType{/*DeviceTypeDescription=*/convert(inp.v.v)}; +} + +DistSchedule make(const parser::OmpClause::DistSchedule &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> std::optional<parser::ScalarIntExpr> + return DistSchedule{{/*Kind=*/DistSchedule::Kind::Static, + /*ChunkSize=*/maybeApply(makeExprFn(semaCtx), inp.v)}}; +} + +Doacross make(const parser::OmpClause::Doacross &inp, + semantics::SemanticsContext &semaCtx) { + // inp -> empty + llvm_unreachable("Empty: doacross"); +} + +// DynamicAllocators: empty + +Enter make(const parser::OmpClause::Enter &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return Enter{makeObjects(/*List=*/inp.v, semaCtx)}; +} + +Exclusive make(const parser::OmpClause::Exclusive &inp, + semantics::SemanticsContext &semaCtx) { + // inp -> empty + llvm_unreachable("Empty: exclusive"); +} + +Fail make(const parser::OmpClause::Fail &inp, + semantics::SemanticsContext &semaCtx) { + // inp -> empty + llvm_unreachable("Empty: fail"); +} + +Filter make(const parser::OmpClause::Filter &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntExpr + return Filter{/*ThreadNum=*/makeExpr(inp.v, semaCtx)}; +} + +Final make(const parser::OmpClause::Final &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarLogicalExpr + return Final{/*Finalize=*/makeExpr(inp.v, semaCtx)}; +} + +Firstprivate make(const parser::OmpClause::Firstprivate &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return Firstprivate{/*List=*/makeObjects(inp.v, semaCtx)}; +} + +// Flush: empty + +From make(const parser::OmpClause::From &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return From{{/*Expectation=*/std::nullopt, /*Mapper=*/std::nullopt, + /*Iterator=*/std::nullopt, + /*LocatorList=*/makeObjects(inp.v, semaCtx)}}; +} + +// Full: empty + +Grainsize make(const parser::OmpClause::Grainsize &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntExpr + return Grainsize{{/*Prescriptiveness=*/std::nullopt, + /*GrainSize=*/makeExpr(inp.v, semaCtx)}}; +} + +HasDeviceAddr make(const parser::OmpClause::HasDeviceAddr &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return HasDeviceAddr{/*List=*/makeObjects(inp.v, semaCtx)}; +} + +Hint make(const parser::OmpClause::Hint &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ConstantExpr + return Hint{/*HintExpr=*/makeExpr(inp.v, semaCtx)}; +} + +// Holds: missing-in-parser + +If make(const parser::OmpClause::If &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpIfClause + using wrapped = parser::OmpIfClause; + + CLAUSET_ENUM_CONVERT( // + convert, wrapped::DirectiveNameModifier, llvm::omp::Directive, + // clang-format off + MS(Parallel, OMPD_parallel) + MS(Simd, OMPD_simd) + MS(Target, OMPD_target) + MS(TargetData, OMPD_target_data) + MS(TargetEnterData, OMPD_target_enter_data) + MS(TargetExitData, OMPD_target_exit_data) + MS(TargetUpdate, OMPD_target_update) + MS(Task, OMPD_task) + MS(Taskloop, OMPD_taskloop) + MS(Teams, OMPD_teams) + // clang-format on + ); + auto &t0 = std::get<std::optional<wrapped::DirectiveNameModifier>>(inp.v.t); + auto &t1 = std::get<parser::ScalarLogicalExpr>(inp.v.t); + return If{{/*DirectiveNameModifier=*/maybeApply(convert, t0), + /*IfExpression=*/makeExpr(t1, semaCtx)}}; +} + +// Inbranch: empty + +Inclusive make(const parser::OmpClause::Inclusive &inp, + semantics::SemanticsContext &semaCtx) { + // inp -> empty + llvm_unreachable("Empty: inclusive"); +} + +Indirect make(const parser::OmpClause::Indirect &inp, + semantics::SemanticsContext &semaCtx) { + // inp -> empty + llvm_unreachable("Empty: indirect"); +} + +Init make(const parser::OmpClause::Init &inp, + semantics::SemanticsContext &semaCtx) { + // inp -> empty + llvm_unreachable("Empty: init"); +} + +// Initializer: missing-in-parser + +InReduction make(const parser::OmpClause::InReduction &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpInReductionClause + auto &t0 = std::get<parser::OmpReductionOperator>(inp.v.t); + auto &t1 = std::get<parser::OmpObjectList>(inp.v.t); + return InReduction{ + {/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)}, + /*List=*/makeObjects(t1, semaCtx)}}; +} + +IsDevicePtr make(const parser::OmpClause::IsDevicePtr &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return IsDevicePtr{/*List=*/makeObjects(inp.v, semaCtx)}; +} + +Lastprivate make(const parser::OmpClause::Lastprivate &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return Lastprivate{{/*LastprivateModifier=*/std::nullopt, + /*List=*/makeObjects(inp.v, semaCtx)}}; +} + +Linear make(const parser::OmpClause::Linear &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpLinearClause + using wrapped = parser::OmpLinearClause; + + CLAUSET_ENUM_CONVERT( // + convert, parser::OmpLinearModifier::Type, Linear::LinearModifier, + // clang-format off + MS(Ref, Ref) + MS(Val, Val) + MS(Uval, Uval) + // clang-format on + ); + + using Tuple = decltype(Linear::t); + + return Linear{std::visit( + common::visitors{ + [&](const wrapped::WithModifier &s) -> Tuple { + return { + /*StepSimpleModifier=*/std::nullopt, + /*StepComplexModifier=*/maybeApply(makeExprFn(semaCtx), s.step), + /*LinearModifier=*/convert(s.modifier.v), + /*List=*/makeList(s.names, makeObjectFn(semaCtx))}; + }, + [&](const wrapped::WithoutModifier &s) -> Tuple { + return { + /*StepSimpleModifier=*/maybeApply(makeExprFn(semaCtx), s.step), + /*StepComplexModifier=*/std::nullopt, + /*LinearModifier=*/std::nullopt, + /*List=*/makeList(s.names, makeObjectFn(semaCtx))}; + }, + }, + inp.v.u)}; +} + +Link make(const parser::OmpClause::Link &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return Link{/*List=*/makeObjects(inp.v, semaCtx)}; +} + +Map make(const parser::OmpClause::Map &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpMapClause + + CLAUSET_ENUM_CONVERT( // + convert1, parser::OmpMapType::Type, Map::MapType, + // clang-format off + MS(To, To) + MS(From, From) + MS(Tofrom, Tofrom) + MS(Alloc, Alloc) + MS(Release, Release) + MS(Delete, Delete) + // clang-format on + ); + + // No convert2: MapTypeModifier is not an enum in parser. + + auto &t0 = std::get<std::optional<parser::OmpMapType>>(inp.v.t); + auto &t1 = std::get<parser::OmpObjectList>(inp.v.t); + + if (!t0) { + return Map{{/*MapType=*/std::nullopt, /*MapTypeModifiers=*/std::nullopt, + /*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt, + /*LocatorList=*/makeObjects(t1, semaCtx)}}; + } + + auto &s0 = std::get<std::optional<parser::OmpMapType::Always>>(t0->t); + auto &s1 = std::get<parser::OmpMapType::Type>(t0->t); + + std::optional<Map::MapTypeModifiers> maybeList; + if (s0) + maybeList = Map::MapTypeModifiers{Map::MapTypeModifier::Always}; + + return Map{{/*MapType=*/convert1(s1), + /*MapTypeModifiers=*/maybeList, + /*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt, + /*LocatorList=*/makeObjects(t1, semaCtx)}}; +} + +// Match: incomplete +// MemoryOrder: empty +// Mergeable: empty + +Message make(const parser::OmpClause::Message &inp, + semantics::SemanticsContext &semaCtx) { + // inp -> empty + llvm_unreachable("Empty: message"); +} + +Nocontext make(const parser::OmpClause::Nocontext &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarLogicalExpr + return Nocontext{/*DoNotUpdateContext=*/makeExpr(inp.v, semaCtx)}; +} + +// Nogroup: empty + +Nontemporal make(const parser::OmpClause::Nontemporal &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> std::list<parser::Name> + return Nontemporal{/*List=*/makeList(inp.v, makeObjectFn(semaCtx))}; +} + +// NoOpenmp: missing-in-parser +// NoOpenmpRoutines: missing-in-parser +// NoParallelism: missing-in-parser +// Notinbranch: empty + +Novariants make(const parser::OmpClause::Novariants &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarLogicalExpr + return Novariants{/*DoNotUseVariant=*/makeExpr(inp.v, semaCtx)}; +} + +// Nowait: empty + +NumTasks make(const parser::OmpClause::NumTasks &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntExpr + return NumTasks{{/*Prescriptiveness=*/std::nullopt, + /*NumTasks=*/makeExpr(inp.v, semaCtx)}}; +} + +NumTeams make(const parser::OmpClause::NumTeams &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntExpr + return NumTeams{{/*LowerBound=*/std::nullopt, + /*UpperBound=*/makeExpr(inp.v, semaCtx)}}; +} + +NumThreads make(const parser::OmpClause::NumThreads &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntExpr + return NumThreads{/*Nthreads=*/makeExpr(inp.v, semaCtx)}; +} + +// OmpxAttribute: empty +// OmpxBare: empty + +OmpxDynCgroupMem make(const parser::OmpClause::OmpxDynCgroupMem &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntExpr + return OmpxDynCgroupMem{makeExpr(inp.v, semaCtx)}; +} + +Order make(const parser::OmpClause::Order &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpOrderClause + using wrapped = parser::OmpOrderClause; + + CLAUSET_ENUM_CONVERT( // + convert1, parser::OmpOrderModifier::Kind, Order::OrderModifier, + // clang-format off + MS(Reproducible, Reproducible) + MS(Unconstrained, Unconstrained) + // clang-format on + ); + + CLAUSET_ENUM_CONVERT( // + convert2, wrapped::Type, Order::Ordering, + // clang-format off + MS(Concurrent, Concurrent) + // clang-format on + ); + + auto &t0 = std::get<std::optional<parser::OmpOrderModifier>>(inp.v.t); + auto &t1 = std::get<wrapped::Type>(inp.v.t); + + auto convert3 = [&](const parser::OmpOrderModifier &s) { + return std::visit( + [&](parser::OmpOrderModifier::Kind k) { return convert1(k); }, s.u); + }; + return Order{ + {/*OrderModifier=*/maybeApply(convert3, t0), /*Ordering=*/convert2(t1)}}; +} + +Ordered make(const parser::OmpClause::Ordered &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> std::optional<parser::ScalarIntConstantExpr> + return Ordered{/*N=*/maybeApply(makeExprFn(semaCtx), inp.v)}; +} + +// Otherwise: incomplete, missing-in-parser + +Partial make(const parser::OmpClause::Partial &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> std::optional<parser::ScalarIntConstantExpr> + return Partial{/*UnrollFactor=*/maybeApply(makeExprFn(semaCtx), inp.v)}; +} + +Priority make(const parser::OmpClause::Priority &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntExpr + return Priority{/*PriorityValue=*/makeExpr(inp.v, semaCtx)}; +} + +Private make(const parser::OmpClause::Private &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return Private{/*List=*/makeObjects(inp.v, semaCtx)}; +} + +ProcBind make(const parser::OmpClause::ProcBind &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpProcBindClause + using wrapped = parser::OmpProcBindClause; + + CLAUSET_ENUM_CONVERT( // + convert, wrapped::Type, ProcBind::AffinityPolicy, + // clang-format off + MS(Close, Close) + MS(Master, Master) + MS(Spread, Spread) + MS(Primary, Primary) + // clang-format on + ); + return ProcBind{/*AffinityPolicy=*/convert(inp.v.v)}; +} + +// Read: empty + +Reduction make(const parser::OmpClause::Reduction &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpReductionClause + auto &t0 = std::get<parser::OmpReductionOperator>(inp.v.t); + auto &t1 = std::get<parser::OmpObjectList>(inp.v.t); + return Reduction{ + {/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)}, + /*ReductionModifier=*/std::nullopt, + /*List=*/makeObjects(t1, semaCtx)}}; +} + +// Relaxed: empty +// Release: empty +// ReverseOffload: empty + +Safelen make(const parser::OmpClause::Safelen &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntConstantExpr + return Safelen{/*Length=*/makeExpr(inp.v, semaCtx)}; +} + +Schedule make(const parser::OmpClause::Schedule &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpScheduleClause + using wrapped = parser::OmpScheduleClause; + + CLAUSET_ENUM_CONVERT( // + convert1, wrapped::ScheduleType, Schedule::Kind, + // clang-format off + MS(Static, Static) + MS(Dynamic, Dynamic) + MS(Guided, Guided) + MS(Auto, Auto) + MS(Runtime, Runtime) + // clang-format on + ); + + CLAUSET_ENUM_CONVERT( // + convert2, parser::OmpScheduleModifierType::ModType, + Schedule::OrderingModifier, + // clang-format off + MS(Monotonic, Monotonic) + MS(Nonmonotonic, Nonmonotonic) + // clang-format on + ); + + CLAUSET_ENUM_CONVERT( // + convert3, parser::OmpScheduleModifierType::ModType, + Schedule::ChunkModifier, + // clang-format off + MS(Simd, Simd) + // clang-format on + ); + + auto &t0 = std::get<std::optional<parser::OmpScheduleModifier>>(inp.v.t); + auto &t1 = std::get<wrapped::ScheduleType>(inp.v.t); + auto &t2 = std::get<std::optional<parser::ScalarIntExpr>>(inp.v.t); + + if (!t0) { + return Schedule{{/*Kind=*/convert1(t1), /*OrderingModifier=*/std::nullopt, + /*ChunkModifier=*/std::nullopt, + /*ChunkSize=*/maybeApply(makeExprFn(semaCtx), t2)}}; + } + + // The members of parser::OmpScheduleModifier correspond to OrderingModifier, + // and ChunkModifier, but they can appear in any order. + auto &m1 = std::get<parser::OmpScheduleModifier::Modifier1>(t0->t); + auto &m2 = + std::get<std::optional<parser::OmpScheduleModifier::Modifier2>>(t0->t); + + std::optional<Schedule::OrderingModifier> omod; + std::optional<Schedule::ChunkModifier> cmod; + + if (m1.v.v == parser::OmpScheduleModifierType::ModType::Simd) { + // m1 is chunk-modifier + cmod = convert3(m1.v.v); + if (m2) + omod = convert2(m2->v.v); + } else { + // m1 is ordering-modifier + omod = convert2(m1.v.v); + if (m2) + cmod = convert3(m2->v.v); + } + + return Schedule{{/*Kind=*/convert1(t1), + /*OrderingModifier=*/omod, + /*ChunkModifier=*/cmod, + /*ChunkSize=*/maybeApply(makeExprFn(semaCtx), t2)}}; +} + +// SeqCst: empty + +Severity make(const parser::OmpClause::Severity &inp, + semantics::SemanticsContext &semaCtx) { + // inp -> empty + llvm_unreachable("Empty: severity"); +} + +Shared make(const parser::OmpClause::Shared &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return Shared{/*List=*/makeObjects(inp.v, semaCtx)}; +} + +// Simd: empty + +Simdlen make(const parser::OmpClause::Simdlen &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntConstantExpr + return Simdlen{/*Length=*/makeExpr(inp.v, semaCtx)}; +} + +Sizes make(const parser::OmpClause::Sizes &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> std::list<parser::ScalarIntExpr> + return Sizes{/*SizeList=*/makeList(inp.v, makeExprFn(semaCtx))}; +} + +TaskReduction make(const parser::OmpClause::TaskReduction &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpReductionClause + auto &t0 = std::get<parser::OmpReductionOperator>(inp.v.t); + auto &t1 = std::get<parser::OmpObjectList>(inp.v.t); + return TaskReduction{ + {/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)}, + /*List=*/makeObjects(t1, semaCtx)}}; +} + +ThreadLimit make(const parser::OmpClause::ThreadLimit &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::ScalarIntExpr + return ThreadLimit{/*Threadlim=*/makeExpr(inp.v, semaCtx)}; +} + +// Threadprivate: empty +// Threads: empty + +To make(const parser::OmpClause::To &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return To{{/*Expectation=*/std::nullopt, /*Mapper=*/std::nullopt, + /*Iterator=*/std::nullopt, + /*LocatorList=*/makeObjects(inp.v, semaCtx)}}; +} + +// UnifiedAddress: empty +// UnifiedSharedMemory: empty + +Uniform make(const parser::OmpClause::Uniform &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> std::list<parser::Name> + return Uniform{/*ParameterList=*/makeList(inp.v, makeObjectFn(semaCtx))}; +} + +// Unknown: empty +// Untied: empty + +Update make(const parser::OmpClause::Update &inp, + semantics::SemanticsContext &semaCtx) { + // inp -> empty + return Update{/*TaskDependenceType=*/std::nullopt}; +} + +Use make(const parser::OmpClause::Use &inp, + semantics::SemanticsContext &semaCtx) { + // inp -> empty + llvm_unreachable("Empty: use"); +} + +UseDeviceAddr make(const parser::OmpClause::UseDeviceAddr &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return UseDeviceAddr{/*List=*/makeObjects(inp.v, semaCtx)}; +} + +UseDevicePtr make(const parser::OmpClause::UseDevicePtr &inp, + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpObjectList + return UseDevicePtr{/*List=*/makeObjects(inp.v, semaCtx)}; +} + +UsesAllocators make(const parser::OmpClause::UsesAllocators &inp, + semantics::SemanticsContext &semaCtx) { + // inp -> empty + llvm_unreachable("Empty: uses_allocators"); +} + +// Weak: empty +// When: incomplete +// Write: empty +} // namespace clause + +Clause makeClause(const Fortran::parser::OmpClause &cls, + semantics::SemanticsContext &semaCtx) { + return std::visit( + [&](auto &&s) { + return makeClause(getClauseId(cls), clause::make(s, semaCtx), + cls.source); + }, + cls.u); +} + +List<Clause> makeClauses(const parser::OmpClauseList &clauses, + semantics::SemanticsContext &semaCtx) { + return makeList(clauses.v, [&](const parser::OmpClause &s) { + return makeClause(s, semaCtx); + }); +} +} // namespace Fortran::lower::omp diff --git a/flang/lib/Lower/OpenMP/Clauses.h b/flang/lib/Lower/OpenMP/Clauses.h new file mode 100644 index 0000000000000000000000000000000000000000..3e776425c733e05ed577603dbd0aeaf4e9826acb --- /dev/null +++ b/flang/lib/Lower/OpenMP/Clauses.h @@ -0,0 +1,263 @@ +//===-- Clauses.h -- OpenMP clause handling -------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef FORTRAN_LOWER_OPENMP_CLAUSES_H +#define FORTRAN_LOWER_OPENMP_CLAUSES_H + +#include "flang/Evaluate/expression.h" +#include "flang/Parser/parse-tree.h" +#include "flang/Semantics/expression.h" +#include "flang/Semantics/semantics.h" +#include "flang/Semantics/symbol.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/Frontend/OpenMP/ClauseT.h" + +#include <optional> +#include <type_traits> +#include <utility> + +namespace Fortran::lower::omp { +using namespace Fortran; +using SomeType = evaluate::SomeType; +using SomeExpr = semantics::SomeExpr; +using MaybeExpr = semantics::MaybeExpr; + +using TypeTy = SomeType; +using IdTy = semantics::Symbol *; +using ExprTy = SomeExpr; + +template <typename T> +using List = tomp::ListT<T>; +} // namespace Fortran::lower::omp + +namespace tomp::type { +template <> +struct ObjectT<Fortran::lower::omp::IdTy, Fortran::lower::omp::ExprTy> { + using IdTy = Fortran::lower::omp::IdTy; + using ExprTy = Fortran::lower::omp::ExprTy; + + const IdTy &id() const { return symbol; } + const std::optional<ExprTy> &ref() const { return designator; } + + IdTy symbol; + std::optional<ExprTy> designator; +}; +} // namespace tomp::type + +namespace Fortran::lower::omp { + +using Object = tomp::ObjectT<IdTy, ExprTy>; +using ObjectList = tomp::ObjectListT<IdTy, ExprTy>; + +Object makeObject(const parser::OmpObject &object, + semantics::SemanticsContext &semaCtx); +Object makeObject(const parser::Name &name, + semantics::SemanticsContext &semaCtx); +Object makeObject(const parser::Designator &dsg, + semantics::SemanticsContext &semaCtx); +Object makeObject(const parser::StructureComponent &comp, + semantics::SemanticsContext &semaCtx); + +inline auto makeObjectFn(semantics::SemanticsContext &semaCtx) { + return [&](auto &&s) { return makeObject(s, semaCtx); }; +} + +template <typename T> +SomeExpr makeExpr(T &&pftExpr, semantics::SemanticsContext &semaCtx) { + auto maybeExpr = evaluate::ExpressionAnalyzer(semaCtx).Analyze(pftExpr); + assert(maybeExpr); + return std::move(*maybeExpr); +} + +inline auto makeExprFn(semantics::SemanticsContext &semaCtx) { + return [&](auto &&s) { return makeExpr(s, semaCtx); }; +} + +template < + typename ContainerTy, typename FunctionTy, + typename ElemTy = typename llvm::remove_cvref_t<ContainerTy>::value_type, + typename ResultTy = std::invoke_result_t<FunctionTy, ElemTy>> +List<ResultTy> makeList(ContainerTy &&container, FunctionTy &&func) { + List<ResultTy> v; + llvm::transform(container, std::back_inserter(v), func); + return v; +} + +inline ObjectList makeObjects(const parser::OmpObjectList &objects, + semantics::SemanticsContext &semaCtx) { + return makeList(objects.v, makeObjectFn(semaCtx)); +} + +template <typename FuncTy, // + typename ArgTy, // + typename ResultTy = std::invoke_result_t<FuncTy, ArgTy>> +std::optional<ResultTy> maybeApply(FuncTy &&func, + const std::optional<ArgTy> &arg) { + if (!arg) + return std::nullopt; + return std::move(func(*arg)); +} + +std::optional<Object> +getBaseObject(const Object &object, + Fortran::semantics::SemanticsContext &semaCtx); + +namespace clause { +using DefinedOperator = tomp::type::DefinedOperatorT<IdTy, ExprTy>; +using ProcedureDesignator = tomp::type::ProcedureDesignatorT<IdTy, ExprTy>; +using ReductionOperator = tomp::type::ReductionIdentifierT<IdTy, ExprTy>; + +// "Requires" clauses are handled early on, and the aggregated information +// is stored in the Symbol details of modules, programs, and subprograms. +// These clauses are still handled here to cover all alternatives in the +// main clause variant. + +using AcqRel = tomp::clause::AcqRelT<TypeTy, IdTy, ExprTy>; +using Acquire = tomp::clause::AcquireT<TypeTy, IdTy, ExprTy>; +using AdjustArgs = tomp::clause::AdjustArgsT<TypeTy, IdTy, ExprTy>; +using Affinity = tomp::clause::AffinityT<TypeTy, IdTy, ExprTy>; +using Aligned = tomp::clause::AlignedT<TypeTy, IdTy, ExprTy>; +using Align = tomp::clause::AlignT<TypeTy, IdTy, ExprTy>; +using Allocate = tomp::clause::AllocateT<TypeTy, IdTy, ExprTy>; +using Allocator = tomp::clause::AllocatorT<TypeTy, IdTy, ExprTy>; +using AppendArgs = tomp::clause::AppendArgsT<TypeTy, IdTy, ExprTy>; +using AtomicDefaultMemOrder = + tomp::clause::AtomicDefaultMemOrderT<TypeTy, IdTy, ExprTy>; +using At = tomp::clause::AtT<TypeTy, IdTy, ExprTy>; +using Bind = tomp::clause::BindT<TypeTy, IdTy, ExprTy>; +using Capture = tomp::clause::CaptureT<TypeTy, IdTy, ExprTy>; +using Collapse = tomp::clause::CollapseT<TypeTy, IdTy, ExprTy>; +using Compare = tomp::clause::CompareT<TypeTy, IdTy, ExprTy>; +using Copyin = tomp::clause::CopyinT<TypeTy, IdTy, ExprTy>; +using Copyprivate = tomp::clause::CopyprivateT<TypeTy, IdTy, ExprTy>; +using Defaultmap = tomp::clause::DefaultmapT<TypeTy, IdTy, ExprTy>; +using Default = tomp::clause::DefaultT<TypeTy, IdTy, ExprTy>; +using Depend = tomp::clause::DependT<TypeTy, IdTy, ExprTy>; +using Destroy = tomp::clause::DestroyT<TypeTy, IdTy, ExprTy>; +using Detach = tomp::clause::DetachT<TypeTy, IdTy, ExprTy>; +using Device = tomp::clause::DeviceT<TypeTy, IdTy, ExprTy>; +using DeviceType = tomp::clause::DeviceTypeT<TypeTy, IdTy, ExprTy>; +using DistSchedule = tomp::clause::DistScheduleT<TypeTy, IdTy, ExprTy>; +using Doacross = tomp::clause::DoacrossT<TypeTy, IdTy, ExprTy>; +using DynamicAllocators = + tomp::clause::DynamicAllocatorsT<TypeTy, IdTy, ExprTy>; +using Enter = tomp::clause::EnterT<TypeTy, IdTy, ExprTy>; +using Exclusive = tomp::clause::ExclusiveT<TypeTy, IdTy, ExprTy>; +using Fail = tomp::clause::FailT<TypeTy, IdTy, ExprTy>; +using Filter = tomp::clause::FilterT<TypeTy, IdTy, ExprTy>; +using Final = tomp::clause::FinalT<TypeTy, IdTy, ExprTy>; +using Firstprivate = tomp::clause::FirstprivateT<TypeTy, IdTy, ExprTy>; +using From = tomp::clause::FromT<TypeTy, IdTy, ExprTy>; +using Full = tomp::clause::FullT<TypeTy, IdTy, ExprTy>; +using Grainsize = tomp::clause::GrainsizeT<TypeTy, IdTy, ExprTy>; +using HasDeviceAddr = tomp::clause::HasDeviceAddrT<TypeTy, IdTy, ExprTy>; +using Hint = tomp::clause::HintT<TypeTy, IdTy, ExprTy>; +using If = tomp::clause::IfT<TypeTy, IdTy, ExprTy>; +using Inbranch = tomp::clause::InbranchT<TypeTy, IdTy, ExprTy>; +using Inclusive = tomp::clause::InclusiveT<TypeTy, IdTy, ExprTy>; +using Indirect = tomp::clause::IndirectT<TypeTy, IdTy, ExprTy>; +using Init = tomp::clause::InitT<TypeTy, IdTy, ExprTy>; +using InReduction = tomp::clause::InReductionT<TypeTy, IdTy, ExprTy>; +using IsDevicePtr = tomp::clause::IsDevicePtrT<TypeTy, IdTy, ExprTy>; +using Lastprivate = tomp::clause::LastprivateT<TypeTy, IdTy, ExprTy>; +using Linear = tomp::clause::LinearT<TypeTy, IdTy, ExprTy>; +using Link = tomp::clause::LinkT<TypeTy, IdTy, ExprTy>; +using Map = tomp::clause::MapT<TypeTy, IdTy, ExprTy>; +using Match = tomp::clause::MatchT<TypeTy, IdTy, ExprTy>; +using Mergeable = tomp::clause::MergeableT<TypeTy, IdTy, ExprTy>; +using Message = tomp::clause::MessageT<TypeTy, IdTy, ExprTy>; +using Nocontext = tomp::clause::NocontextT<TypeTy, IdTy, ExprTy>; +using Nogroup = tomp::clause::NogroupT<TypeTy, IdTy, ExprTy>; +using Nontemporal = tomp::clause::NontemporalT<TypeTy, IdTy, ExprTy>; +using Notinbranch = tomp::clause::NotinbranchT<TypeTy, IdTy, ExprTy>; +using Novariants = tomp::clause::NovariantsT<TypeTy, IdTy, ExprTy>; +using Nowait = tomp::clause::NowaitT<TypeTy, IdTy, ExprTy>; +using NumTasks = tomp::clause::NumTasksT<TypeTy, IdTy, ExprTy>; +using NumTeams = tomp::clause::NumTeamsT<TypeTy, IdTy, ExprTy>; +using NumThreads = tomp::clause::NumThreadsT<TypeTy, IdTy, ExprTy>; +using OmpxAttribute = tomp::clause::OmpxAttributeT<TypeTy, IdTy, ExprTy>; +using OmpxBare = tomp::clause::OmpxBareT<TypeTy, IdTy, ExprTy>; +using OmpxDynCgroupMem = tomp::clause::OmpxDynCgroupMemT<TypeTy, IdTy, ExprTy>; +using Ordered = tomp::clause::OrderedT<TypeTy, IdTy, ExprTy>; +using Order = tomp::clause::OrderT<TypeTy, IdTy, ExprTy>; +using Partial = tomp::clause::PartialT<TypeTy, IdTy, ExprTy>; +using Priority = tomp::clause::PriorityT<TypeTy, IdTy, ExprTy>; +using Private = tomp::clause::PrivateT<TypeTy, IdTy, ExprTy>; +using ProcBind = tomp::clause::ProcBindT<TypeTy, IdTy, ExprTy>; +using Read = tomp::clause::ReadT<TypeTy, IdTy, ExprTy>; +using Reduction = tomp::clause::ReductionT<TypeTy, IdTy, ExprTy>; +using Relaxed = tomp::clause::RelaxedT<TypeTy, IdTy, ExprTy>; +using Release = tomp::clause::ReleaseT<TypeTy, IdTy, ExprTy>; +using ReverseOffload = tomp::clause::ReverseOffloadT<TypeTy, IdTy, ExprTy>; +using Safelen = tomp::clause::SafelenT<TypeTy, IdTy, ExprTy>; +using Schedule = tomp::clause::ScheduleT<TypeTy, IdTy, ExprTy>; +using SeqCst = tomp::clause::SeqCstT<TypeTy, IdTy, ExprTy>; +using Severity = tomp::clause::SeverityT<TypeTy, IdTy, ExprTy>; +using Shared = tomp::clause::SharedT<TypeTy, IdTy, ExprTy>; +using Simdlen = tomp::clause::SimdlenT<TypeTy, IdTy, ExprTy>; +using Simd = tomp::clause::SimdT<TypeTy, IdTy, ExprTy>; +using Sizes = tomp::clause::SizesT<TypeTy, IdTy, ExprTy>; +using TaskReduction = tomp::clause::TaskReductionT<TypeTy, IdTy, ExprTy>; +using ThreadLimit = tomp::clause::ThreadLimitT<TypeTy, IdTy, ExprTy>; +using Threads = tomp::clause::ThreadsT<TypeTy, IdTy, ExprTy>; +using To = tomp::clause::ToT<TypeTy, IdTy, ExprTy>; +using UnifiedAddress = tomp::clause::UnifiedAddressT<TypeTy, IdTy, ExprTy>; +using UnifiedSharedMemory = + tomp::clause::UnifiedSharedMemoryT<TypeTy, IdTy, ExprTy>; +using Uniform = tomp::clause::UniformT<TypeTy, IdTy, ExprTy>; +using Unknown = tomp::clause::UnknownT<TypeTy, IdTy, ExprTy>; +using Untied = tomp::clause::UntiedT<TypeTy, IdTy, ExprTy>; +using Update = tomp::clause::UpdateT<TypeTy, IdTy, ExprTy>; +using UseDeviceAddr = tomp::clause::UseDeviceAddrT<TypeTy, IdTy, ExprTy>; +using UseDevicePtr = tomp::clause::UseDevicePtrT<TypeTy, IdTy, ExprTy>; +using UsesAllocators = tomp::clause::UsesAllocatorsT<TypeTy, IdTy, ExprTy>; +using Use = tomp::clause::UseT<TypeTy, IdTy, ExprTy>; +using Weak = tomp::clause::WeakT<TypeTy, IdTy, ExprTy>; +using When = tomp::clause::WhenT<TypeTy, IdTy, ExprTy>; +using Write = tomp::clause::WriteT<TypeTy, IdTy, ExprTy>; +} // namespace clause + +struct CancellationConstructType { + using EmptyTrait = std::true_type; +}; +struct Depobj { + using EmptyTrait = std::true_type; +}; +struct Flush { + using EmptyTrait = std::true_type; +}; +struct MemoryOrder { + using EmptyTrait = std::true_type; +}; +struct Threadprivate { + using EmptyTrait = std::true_type; +}; + +using ClauseBase = tomp::ClauseT<TypeTy, IdTy, ExprTy, + // Extras... + CancellationConstructType, Depobj, Flush, + MemoryOrder, Threadprivate>; + +struct Clause : public ClauseBase { + parser::CharBlock source; +}; + +template <typename Specific> +Clause makeClause(llvm::omp::Clause id, Specific &&specific, + parser::CharBlock source = {}) { + return Clause{{id, specific}, source}; +} + +Clause makeClause(const Fortran::parser::OmpClause &cls, + semantics::SemanticsContext &semaCtx); + +List<Clause> makeClauses(const parser::OmpClauseList &clauses, + semantics::SemanticsContext &semaCtx); +} // namespace Fortran::lower::omp + +#endif // FORTRAN_LOWER_OPENMP_CLAUSES_H diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp index 717b8cc0276a3045feab84fb25774da5ef09b524..e114ab9f4548abd887a8e1d434f706edb36c47d4 100644 --- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp +++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp @@ -50,6 +50,7 @@ void DataSharingProcessor::processStep2(mlir::Operation *op, bool isLoop) { } void DataSharingProcessor::insertDeallocs() { + // TODO Extend delayed privatization to include a `dealloc` region. for (const Fortran::semantics::Symbol *sym : privatizedSymbols) if (Fortran::semantics::IsAllocatable(sym->GetUltimate())) { converter.createHostAssociateVarCloneDealloc(*sym); @@ -81,30 +82,27 @@ void DataSharingProcessor::copyLastPrivateSymbol( } void DataSharingProcessor::collectOmpObjectListSymbol( - const Fortran::parser::OmpObjectList &ompObjectList, + const omp::ObjectList &objects, llvm::SetVector<const Fortran::semantics::Symbol *> &symbolSet) { - for (const Fortran::parser::OmpObject &ompObject : ompObjectList.v) { - Fortran::semantics::Symbol *sym = getOmpObjectSymbol(ompObject); - symbolSet.insert(sym); - } + for (const omp::Object &object : objects) + symbolSet.insert(object.id()); } void DataSharingProcessor::collectSymbolsForPrivatization() { bool hasCollapse = false; - for (const Fortran::parser::OmpClause &clause : opClauseList.v) { + for (const omp::Clause &clause : clauses) { if (const auto &privateClause = - std::get_if<Fortran::parser::OmpClause::Private>(&clause.u)) { + std::get_if<omp::clause::Private>(&clause.u)) { collectOmpObjectListSymbol(privateClause->v, privatizedSymbols); } else if (const auto &firstPrivateClause = - std::get_if<Fortran::parser::OmpClause::Firstprivate>( - &clause.u)) { + std::get_if<omp::clause::Firstprivate>(&clause.u)) { collectOmpObjectListSymbol(firstPrivateClause->v, privatizedSymbols); } else if (const auto &lastPrivateClause = - std::get_if<Fortran::parser::OmpClause::Lastprivate>( - &clause.u)) { - collectOmpObjectListSymbol(lastPrivateClause->v, privatizedSymbols); + std::get_if<omp::clause::Lastprivate>(&clause.u)) { + const ObjectList &objects = std::get<ObjectList>(lastPrivateClause->t); + collectOmpObjectListSymbol(objects, privatizedSymbols); hasLastPrivateOp = true; - } else if (std::get_if<Fortran::parser::OmpClause::Collapse>(&clause.u)) { + } else if (std::get_if<omp::clause::Collapse>(&clause.u)) { hasCollapse = true; } } @@ -137,138 +135,135 @@ void DataSharingProcessor::insertBarrier() { void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) { bool cmpCreated = false; mlir::OpBuilder::InsertPoint localInsPt = firOpBuilder.saveInsertionPoint(); - for (const Fortran::parser::OmpClause &clause : opClauseList.v) { - if (std::get_if<Fortran::parser::OmpClause::Lastprivate>(&clause.u)) { - // TODO: Add lastprivate support for simd construct - if (mlir::isa<mlir::omp::SectionOp>(op)) { - if (&eval == &eval.parentConstruct->getLastNestedEvaluation()) { - // For `omp.sections`, lastprivatized variables occur in - // lexically final `omp.section` operation. The following FIR - // shall be generated for the same: - // - // omp.sections lastprivate(...) { - // omp.section {...} - // omp.section {...} - // omp.section { - // fir.allocate for `private`/`firstprivate` - // <More operations here> - // fir.if %true { - // ^%lpv_update_blk - // } - // } - // } - // - // To keep code consistency while handling privatization - // through this control flow, add a `fir.if` operation - // that always evaluates to true, in order to create - // a dedicated sub-region in `omp.section` where - // lastprivate FIR can reside. Later canonicalizations - // will optimize away this operation. - if (!eval.lowerAsUnstructured()) { - auto ifOp = firOpBuilder.create<fir::IfOp>( - op->getLoc(), - firOpBuilder.createIntegerConstant( - op->getLoc(), firOpBuilder.getIntegerType(1), 0x1), - /*else*/ false); - firOpBuilder.setInsertionPointToStart( - &ifOp.getThenRegion().front()); - - const Fortran::parser::OpenMPConstruct *parentOmpConstruct = - eval.parentConstruct->getIf<Fortran::parser::OpenMPConstruct>(); - assert(parentOmpConstruct && - "Expected a valid enclosing OpenMP construct"); - const Fortran::parser::OpenMPSectionsConstruct *sectionsConstruct = - std::get_if<Fortran::parser::OpenMPSectionsConstruct>( - &parentOmpConstruct->u); - assert(sectionsConstruct && - "Expected an enclosing omp.sections construct"); - const Fortran::parser::OmpClauseList §ionsEndClauseList = - std::get<Fortran::parser::OmpClauseList>( - std::get<Fortran::parser::OmpEndSectionsDirective>( - sectionsConstruct->t) - .t); - for (const Fortran::parser::OmpClause &otherClause : - sectionsEndClauseList.v) - if (std::get_if<Fortran::parser::OmpClause::Nowait>( - &otherClause.u)) - // Emit implicit barrier to synchronize threads and avoid data - // races on post-update of lastprivate variables when `nowait` - // clause is present. - firOpBuilder.create<mlir::omp::BarrierOp>( - converter.getCurrentLocation()); - firOpBuilder.setInsertionPointToStart( - &ifOp.getThenRegion().front()); - lastPrivIP = firOpBuilder.saveInsertionPoint(); - firOpBuilder.setInsertionPoint(ifOp); - insPt = firOpBuilder.saveInsertionPoint(); - } else { - // Lastprivate operation is inserted at the end - // of the lexically last section in the sections - // construct - mlir::OpBuilder::InsertPoint unstructuredSectionsIP = - firOpBuilder.saveInsertionPoint(); - mlir::Operation *lastOper = op->getRegion(0).back().getTerminator(); - firOpBuilder.setInsertionPoint(lastOper); - lastPrivIP = firOpBuilder.saveInsertionPoint(); - firOpBuilder.restoreInsertionPoint(unstructuredSectionsIP); - } - } - } else if (mlir::isa<mlir::omp::WsLoopOp>(op)) { - // Update the original variable just before exiting the worksharing - // loop. Conversion as follows: + for (const omp::Clause &clause : clauses) { + if (clause.id != llvm::omp::OMPC_lastprivate) + continue; + // TODO: Add lastprivate support for simd construct + if (mlir::isa<mlir::omp::SectionOp>(op)) { + if (&eval == &eval.parentConstruct->getLastNestedEvaluation()) { + // For `omp.sections`, lastprivatized variables occur in + // lexically final `omp.section` operation. The following FIR + // shall be generated for the same: // - // omp.wsloop { - // omp.wsloop { ... - // ... store - // store ===> %v = arith.addi %iv, %step - // omp.yield %cmp = %step < 0 ? %v < %ub : %v > %ub - // } fir.if %cmp { - // fir.store %v to %loopIV - // ^%lpv_update_blk: - // } - // omp.yield - // } + // omp.sections lastprivate(...) { + // omp.section {...} + // omp.section {...} + // omp.section { + // fir.allocate for `private`/`firstprivate` + // <More operations here> + // fir.if %true { + // ^%lpv_update_blk + // } + // } + // } // - - // Only generate the compare once in presence of multiple LastPrivate - // clauses. - if (cmpCreated) - continue; - cmpCreated = true; - - mlir::Location loc = op->getLoc(); - mlir::Operation *lastOper = op->getRegion(0).back().getTerminator(); - firOpBuilder.setInsertionPoint(lastOper); - - mlir::Value iv = op->getRegion(0).front().getArguments()[0]; - mlir::Value ub = - mlir::dyn_cast<mlir::omp::WsLoopOp>(op).getUpperBound()[0]; - mlir::Value step = mlir::dyn_cast<mlir::omp::WsLoopOp>(op).getStep()[0]; - - // v = iv + step - // cmp = step < 0 ? v < ub : v > ub - mlir::Value v = firOpBuilder.create<mlir::arith::AddIOp>(loc, iv, step); - mlir::Value zero = - firOpBuilder.createIntegerConstant(loc, step.getType(), 0); - mlir::Value negativeStep = firOpBuilder.create<mlir::arith::CmpIOp>( - loc, mlir::arith::CmpIPredicate::slt, step, zero); - mlir::Value vLT = firOpBuilder.create<mlir::arith::CmpIOp>( - loc, mlir::arith::CmpIPredicate::slt, v, ub); - mlir::Value vGT = firOpBuilder.create<mlir::arith::CmpIOp>( - loc, mlir::arith::CmpIPredicate::sgt, v, ub); - mlir::Value cmpOp = firOpBuilder.create<mlir::arith::SelectOp>( - loc, negativeStep, vLT, vGT); - - auto ifOp = firOpBuilder.create<fir::IfOp>(loc, cmpOp, /*else*/ false); - firOpBuilder.setInsertionPointToStart(&ifOp.getThenRegion().front()); - assert(loopIV && "loopIV was not set"); - firOpBuilder.create<fir::StoreOp>(op->getLoc(), v, loopIV); - lastPrivIP = firOpBuilder.saveInsertionPoint(); - } else { - TODO(converter.getCurrentLocation(), - "lastprivate clause in constructs other than " - "simd/worksharing-loop"); + // To keep code consistency while handling privatization + // through this control flow, add a `fir.if` operation + // that always evaluates to true, in order to create + // a dedicated sub-region in `omp.section` where + // lastprivate FIR can reside. Later canonicalizations + // will optimize away this operation. + if (!eval.lowerAsUnstructured()) { + auto ifOp = firOpBuilder.create<fir::IfOp>( + op->getLoc(), + firOpBuilder.createIntegerConstant( + op->getLoc(), firOpBuilder.getIntegerType(1), 0x1), + /*else*/ false); + firOpBuilder.setInsertionPointToStart(&ifOp.getThenRegion().front()); + + const Fortran::parser::OpenMPConstruct *parentOmpConstruct = + eval.parentConstruct->getIf<Fortran::parser::OpenMPConstruct>(); + assert(parentOmpConstruct && + "Expected a valid enclosing OpenMP construct"); + const Fortran::parser::OpenMPSectionsConstruct *sectionsConstruct = + std::get_if<Fortran::parser::OpenMPSectionsConstruct>( + &parentOmpConstruct->u); + assert(sectionsConstruct && + "Expected an enclosing omp.sections construct"); + const Fortran::parser::OmpClauseList §ionsEndClauseList = + std::get<Fortran::parser::OmpClauseList>( + std::get<Fortran::parser::OmpEndSectionsDirective>( + sectionsConstruct->t) + .t); + for (const Fortran::parser::OmpClause &otherClause : + sectionsEndClauseList.v) + if (std::get_if<Fortran::parser::OmpClause::Nowait>(&otherClause.u)) + // Emit implicit barrier to synchronize threads and avoid data + // races on post-update of lastprivate variables when `nowait` + // clause is present. + firOpBuilder.create<mlir::omp::BarrierOp>( + converter.getCurrentLocation()); + firOpBuilder.setInsertionPointToStart(&ifOp.getThenRegion().front()); + lastPrivIP = firOpBuilder.saveInsertionPoint(); + firOpBuilder.setInsertionPoint(ifOp); + insPt = firOpBuilder.saveInsertionPoint(); + } else { + // Lastprivate operation is inserted at the end + // of the lexically last section in the sections + // construct + mlir::OpBuilder::InsertPoint unstructuredSectionsIP = + firOpBuilder.saveInsertionPoint(); + mlir::Operation *lastOper = op->getRegion(0).back().getTerminator(); + firOpBuilder.setInsertionPoint(lastOper); + lastPrivIP = firOpBuilder.saveInsertionPoint(); + firOpBuilder.restoreInsertionPoint(unstructuredSectionsIP); + } } + } else if (mlir::isa<mlir::omp::WsloopOp>(op)) { + // Update the original variable just before exiting the worksharing + // loop. Conversion as follows: + // + // omp.wsloop { + // omp.wsloop { ... + // ... store + // store ===> %v = arith.addi %iv, %step + // omp.yield %cmp = %step < 0 ? %v < %ub : %v > %ub + // } fir.if %cmp { + // fir.store %v to %loopIV + // ^%lpv_update_blk: + // } + // omp.yield + // } + // + + // Only generate the compare once in presence of multiple LastPrivate + // clauses. + if (cmpCreated) + continue; + cmpCreated = true; + + mlir::Location loc = op->getLoc(); + mlir::Operation *lastOper = op->getRegion(0).back().getTerminator(); + firOpBuilder.setInsertionPoint(lastOper); + + mlir::Value iv = op->getRegion(0).front().getArguments()[0]; + mlir::Value ub = + mlir::dyn_cast<mlir::omp::WsloopOp>(op).getUpperBound()[0]; + mlir::Value step = mlir::dyn_cast<mlir::omp::WsloopOp>(op).getStep()[0]; + + // v = iv + step + // cmp = step < 0 ? v < ub : v > ub + mlir::Value v = firOpBuilder.create<mlir::arith::AddIOp>(loc, iv, step); + mlir::Value zero = + firOpBuilder.createIntegerConstant(loc, step.getType(), 0); + mlir::Value negativeStep = firOpBuilder.create<mlir::arith::CmpIOp>( + loc, mlir::arith::CmpIPredicate::slt, step, zero); + mlir::Value vLT = firOpBuilder.create<mlir::arith::CmpIOp>( + loc, mlir::arith::CmpIPredicate::slt, v, ub); + mlir::Value vGT = firOpBuilder.create<mlir::arith::CmpIOp>( + loc, mlir::arith::CmpIPredicate::sgt, v, ub); + mlir::Value cmpOp = firOpBuilder.create<mlir::arith::SelectOp>( + loc, negativeStep, vLT, vGT); + + auto ifOp = firOpBuilder.create<fir::IfOp>(loc, cmpOp, /*else*/ false); + firOpBuilder.setInsertionPointToStart(&ifOp.getThenRegion().front()); + assert(loopIV && "loopIV was not set"); + firOpBuilder.create<fir::StoreOp>(op->getLoc(), v, loopIV); + lastPrivIP = firOpBuilder.saveInsertionPoint(); + } else { + TODO(converter.getCurrentLocation(), + "lastprivate clause in constructs other than " + "simd/worksharing-loop"); } } firOpBuilder.restoreInsertionPoint(localInsPt); @@ -292,14 +287,13 @@ void DataSharingProcessor::collectSymbols( } void DataSharingProcessor::collectDefaultSymbols() { - for (const Fortran::parser::OmpClause &clause : opClauseList.v) { - if (const auto &defaultClause = - std::get_if<Fortran::parser::OmpClause::Default>(&clause.u)) { - if (defaultClause->v.v == - Fortran::parser::OmpDefaultClause::Type::Private) + using DataSharingAttribute = omp::clause::Default::DataSharingAttribute; + for (const omp::Clause &clause : clauses) { + if (const auto *defaultClause = + std::get_if<omp::clause::Default>(&clause.u)) { + if (defaultClause->v == DataSharingAttribute::Private) collectSymbols(Fortran::semantics::Symbol::Flag::OmpPrivate); - else if (defaultClause->v.v == - Fortran::parser::OmpDefaultClause::Type::Firstprivate) + else if (defaultClause->v == DataSharingAttribute::Firstprivate) collectSymbols(Fortran::semantics::Symbol::Flag::OmpFirstPrivate); } } @@ -376,6 +370,7 @@ void DataSharingProcessor::doPrivatize(const Fortran::semantics::Symbol *sym) { symLoc, uniquePrivatizerName, symType, isFirstPrivate ? mlir::omp::DataSharingClauseType::FirstPrivate : mlir::omp::DataSharingClauseType::Private); + fir::ExtendedValue symExV = converter.getSymbolExtendedValue(*sym); symTable->pushScope(); @@ -386,7 +381,8 @@ void DataSharingProcessor::doPrivatize(const Fortran::semantics::Symbol *sym) { &allocRegion, /*insertPt=*/{}, symType, symLoc); firOpBuilder.setInsertionPointToEnd(allocEntryBlock); - symTable->addSymbol(*sym, allocRegion.getArgument(0)); + symTable->addSymbol(*sym, + fir::substBase(symExV, allocRegion.getArgument(0))); symTable->pushScope(); cloneSymbol(sym); firOpBuilder.create<mlir::omp::YieldOp>( @@ -403,10 +399,12 @@ void DataSharingProcessor::doPrivatize(const Fortran::semantics::Symbol *sym) { mlir::Block *copyEntryBlock = firOpBuilder.createBlock( ©Region, /*insertPt=*/{}, {symType, symType}, {symLoc, symLoc}); firOpBuilder.setInsertionPointToEnd(copyEntryBlock); - symTable->addSymbol(*sym, copyRegion.getArgument(0), + symTable->addSymbol(*sym, + fir::substBase(symExV, copyRegion.getArgument(0)), /*force=*/true); symTable->pushScope(); - symTable->addSymbol(*sym, copyRegion.getArgument(1)); + symTable->addSymbol(*sym, + fir::substBase(symExV, copyRegion.getArgument(1))); auto ip = firOpBuilder.saveInsertionPoint(); copyFirstPrivateSymbol(sym, &ip); diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.h b/flang/lib/Lower/OpenMP/DataSharingProcessor.h index 9f7301df07598f47c6af73ef37fbc8659c1978de..1cbc825fd5e11b224ee101ff37cbac1528586f61 100644 --- a/flang/lib/Lower/OpenMP/DataSharingProcessor.h +++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.h @@ -12,6 +12,7 @@ #ifndef FORTRAN_LOWER_DATASHARINGPROCESSOR_H #define FORTRAN_LOWER_DATASHARINGPROCESSOR_H +#include "Clauses.h" #include "flang/Lower/AbstractConverter.h" #include "flang/Lower/OpenMP.h" #include "flang/Optimizer/Builder/FIRBuilder.h" @@ -52,7 +53,7 @@ private: llvm::SetVector<const Fortran::semantics::Symbol *> symbolsInParentRegions; Fortran::lower::AbstractConverter &converter; fir::FirOpBuilder &firOpBuilder; - const Fortran::parser::OmpClauseList &opClauseList; + omp::List<omp::Clause> clauses; Fortran::lower::pft::Evaluation &eval; bool useDelayedPrivatization; Fortran::lower::SymMap *symTable; @@ -61,7 +62,7 @@ private: bool needBarrier(); void collectSymbols(Fortran::semantics::Symbol::Flag flag); void collectOmpObjectListSymbol( - const Fortran::parser::OmpObjectList &ompObjectList, + const omp::ObjectList &objects, llvm::SetVector<const Fortran::semantics::Symbol *> &symbolSet); void collectSymbolsForPrivatization(); void insertBarrier(); @@ -81,14 +82,15 @@ private: public: DataSharingProcessor(Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semaCtx, const Fortran::parser::OmpClauseList &opClauseList, Fortran::lower::pft::Evaluation &eval, bool useDelayedPrivatization = false, Fortran::lower::SymMap *symTable = nullptr) : hasLastPrivateOp(false), converter(converter), - firOpBuilder(converter.getFirOpBuilder()), opClauseList(opClauseList), - eval(eval), useDelayedPrivatization(useDelayedPrivatization), - symTable(symTable) {} + firOpBuilder(converter.getFirOpBuilder()), + clauses(omp::makeClauses(opClauseList, semaCtx)), eval(eval), + useDelayedPrivatization(useDelayedPrivatization), symTable(symTable) {} // Privatisation is split into two steps. // Step1 performs cloning of all privatisation clauses and copying for diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 4f0bb80cd7fdf651710ee7f0802c8af15e493ad3..340921c867246c741206d8953a94b14b1d1b447a 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -13,6 +13,7 @@ #include "flang/Lower/OpenMP.h" #include "ClauseProcessor.h" +#include "Clauses.h" #include "DataSharingProcessor.h" #include "DirectivesCommon.h" #include "ReductionProcessor.h" @@ -214,24 +215,6 @@ static void threadPrivatizeVars(Fortran::lower::AbstractConverter &converter, firOpBuilder.restoreInsertionPoint(insPt); } -static mlir::Type getLoopVarType(Fortran::lower::AbstractConverter &converter, - std::size_t loopVarTypeSize) { - // OpenMP runtime requires 32-bit or 64-bit loop variables. - loopVarTypeSize = loopVarTypeSize * 8; - if (loopVarTypeSize < 32) { - loopVarTypeSize = 32; - } else if (loopVarTypeSize > 64) { - loopVarTypeSize = 64; - mlir::emitWarning(converter.getCurrentLocation(), - "OpenMP loop iteration variable cannot have more than 64 " - "bits size and will be narrowed into 64 bits."); - } - assert((loopVarTypeSize == 32 || loopVarTypeSize == 64) && - "OpenMP loop iteration variable size must be transformed into 32-bit " - "or 64-bit"); - return converter.getFirOpBuilder().getIntegerType(loopVarTypeSize); -} - static mlir::Operation * createAndSetPrivatizedLoopVar(Fortran::lower::AbstractConverter &converter, mlir::Location loc, mlir::Value indexVal, @@ -254,6 +237,213 @@ createAndSetPrivatizedLoopVar(Fortran::lower::AbstractConverter &converter, return storeOp; } +static mlir::Operation * +findReductionChain(mlir::Value loadVal, mlir::Value *reductionVal = nullptr) { + for (mlir::OpOperand &loadOperand : loadVal.getUses()) { + if (mlir::Operation *reductionOp = loadOperand.getOwner()) { + if (auto convertOp = mlir::dyn_cast<fir::ConvertOp>(reductionOp)) { + for (mlir::OpOperand &convertOperand : convertOp.getRes().getUses()) { + if (mlir::Operation *reductionOp = convertOperand.getOwner()) + return reductionOp; + } + } + for (mlir::OpOperand &reductionOperand : reductionOp->getUses()) { + if (auto store = + mlir::dyn_cast<fir::StoreOp>(reductionOperand.getOwner())) { + if (store.getMemref() == *reductionVal) { + store.erase(); + return reductionOp; + } + } + if (auto assign = + mlir::dyn_cast<hlfir::AssignOp>(reductionOperand.getOwner())) { + if (assign.getLhs() == *reductionVal) { + assign.erase(); + return reductionOp; + } + } + } + } + } + return nullptr; +} + +// for a logical operator 'op' reduction X = X op Y +// This function returns the operation responsible for converting Y from +// fir.logical<4> to i1 +static fir::ConvertOp getConvertFromReductionOp(mlir::Operation *reductionOp, + mlir::Value loadVal) { + for (mlir::Value reductionOperand : reductionOp->getOperands()) { + if (auto convertOp = + mlir::dyn_cast<fir::ConvertOp>(reductionOperand.getDefiningOp())) { + if (convertOp.getOperand() == loadVal) + continue; + return convertOp; + } + } + return nullptr; +} + +static void updateReduction(mlir::Operation *op, + fir::FirOpBuilder &firOpBuilder, + mlir::Value loadVal, mlir::Value reductionVal, + fir::ConvertOp *convertOp = nullptr) { + mlir::OpBuilder::InsertPoint insertPtDel = firOpBuilder.saveInsertionPoint(); + firOpBuilder.setInsertionPoint(op); + + mlir::Value reductionOp; + if (convertOp) + reductionOp = convertOp->getOperand(); + else if (op->getOperand(0) == loadVal) + reductionOp = op->getOperand(1); + else + reductionOp = op->getOperand(0); + + firOpBuilder.create<mlir::omp::ReductionOp>(op->getLoc(), reductionOp, + reductionVal); + firOpBuilder.restoreInsertionPoint(insertPtDel); +} + +static void removeStoreOp(mlir::Operation *reductionOp, mlir::Value symVal) { + for (mlir::Operation *reductionOpUse : reductionOp->getUsers()) { + if (auto convertReduction = + mlir::dyn_cast<fir::ConvertOp>(reductionOpUse)) { + for (mlir::Operation *convertReductionUse : + convertReduction.getRes().getUsers()) { + if (auto storeOp = mlir::dyn_cast<fir::StoreOp>(convertReductionUse)) { + if (storeOp.getMemref() == symVal) + storeOp.erase(); + } + if (auto assignOp = + mlir::dyn_cast<hlfir::AssignOp>(convertReductionUse)) { + if (assignOp.getLhs() == symVal) + assignOp.erase(); + } + } + } + } +} + +// Generate an OpenMP reduction operation. +// TODO: Currently assumes it is either an integer addition/multiplication +// reduction, or a logical and reduction. Generalize this for various reduction +// operation types. +// TODO: Generate the reduction operation during lowering instead of creating +// and removing operations since this is not a robust approach. Also, removing +// ops in the builder (instead of a rewriter) is probably not the best approach. +static void +genOpenMPReduction(Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semaCtx, + const Fortran::parser::OmpClauseList &clauseList) { + fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); + + List<Clause> clauses{makeClauses(clauseList, semaCtx)}; + + for (const Clause &clause : clauses) { + if (const auto &reductionClause = + std::get_if<clause::Reduction>(&clause.u)) { + const auto &redOperatorList{ + std::get<clause::Reduction::ReductionIdentifiers>( + reductionClause->t)}; + assert(redOperatorList.size() == 1 && "Expecting single operator"); + const auto &redOperator = redOperatorList.front(); + const auto &objects{std::get<ObjectList>(reductionClause->t)}; + if (const auto *reductionOp = + std::get_if<clause::DefinedOperator>(&redOperator.u)) { + const auto &intrinsicOp{ + std::get<clause::DefinedOperator::IntrinsicOperator>( + reductionOp->u)}; + + switch (intrinsicOp) { + case clause::DefinedOperator::IntrinsicOperator::Add: + case clause::DefinedOperator::IntrinsicOperator::Multiply: + case clause::DefinedOperator::IntrinsicOperator::AND: + case clause::DefinedOperator::IntrinsicOperator::EQV: + case clause::DefinedOperator::IntrinsicOperator::OR: + case clause::DefinedOperator::IntrinsicOperator::NEQV: + break; + default: + continue; + } + for (const Object &object : objects) { + if (const Fortran::semantics::Symbol *symbol = object.id()) { + mlir::Value reductionVal = converter.getSymbolAddress(*symbol); + if (auto declOp = reductionVal.getDefiningOp<hlfir::DeclareOp>()) + reductionVal = declOp.getBase(); + mlir::Type reductionType = + reductionVal.getType().cast<fir::ReferenceType>().getEleTy(); + if (!reductionType.isa<fir::LogicalType>()) { + if (!reductionType.isIntOrIndexOrFloat()) + continue; + } + for (mlir::OpOperand &reductionValUse : reductionVal.getUses()) { + if (auto loadOp = + mlir::dyn_cast<fir::LoadOp>(reductionValUse.getOwner())) { + mlir::Value loadVal = loadOp.getRes(); + if (reductionType.isa<fir::LogicalType>()) { + mlir::Operation *reductionOp = findReductionChain(loadVal); + fir::ConvertOp convertOp = + getConvertFromReductionOp(reductionOp, loadVal); + updateReduction(reductionOp, firOpBuilder, loadVal, + reductionVal, &convertOp); + removeStoreOp(reductionOp, reductionVal); + } else if (mlir::Operation *reductionOp = + findReductionChain(loadVal, &reductionVal)) { + updateReduction(reductionOp, firOpBuilder, loadVal, + reductionVal); + } + } + } + } + } + } else if (const auto *reductionIntrinsic = + std::get_if<clause::ProcedureDesignator>(&redOperator.u)) { + if (!ReductionProcessor::supportedIntrinsicProcReduction( + *reductionIntrinsic)) + continue; + ReductionProcessor::ReductionIdentifier redId = + ReductionProcessor::getReductionType(*reductionIntrinsic); + for (const Object &object : objects) { + if (const Fortran::semantics::Symbol *symbol = object.id()) { + mlir::Value reductionVal = converter.getSymbolAddress(*symbol); + if (auto declOp = reductionVal.getDefiningOp<hlfir::DeclareOp>()) + reductionVal = declOp.getBase(); + for (const mlir::OpOperand &reductionValUse : + reductionVal.getUses()) { + if (auto loadOp = + mlir::dyn_cast<fir::LoadOp>(reductionValUse.getOwner())) { + mlir::Value loadVal = loadOp.getRes(); + // Max is lowered as a compare -> select. + // Match the pattern here. + mlir::Operation *reductionOp = + findReductionChain(loadVal, &reductionVal); + if (reductionOp == nullptr) + continue; + + if (redId == ReductionProcessor::ReductionIdentifier::MAX || + redId == ReductionProcessor::ReductionIdentifier::MIN) { + assert(mlir::isa<mlir::arith::SelectOp>(reductionOp) && + "Selection Op not found in reduction intrinsic"); + mlir::Operation *compareOp = + getCompareFromReductionOp(reductionOp, loadVal); + updateReduction(compareOp, firOpBuilder, loadVal, + reductionVal); + } + if (redId == ReductionProcessor::ReductionIdentifier::IOR || + redId == ReductionProcessor::ReductionIdentifier::IEOR || + redId == ReductionProcessor::ReductionIdentifier::IAND) { + updateReduction(reductionOp, firOpBuilder, loadVal, + reductionVal); + } + } + } + } + } + } + } + } +} + struct OpWithBodyGenInfo { /// A type for a code-gen callback function. This takes as argument the op for /// which the code is being generated and returns the arguments of the op's @@ -287,9 +477,9 @@ struct OpWithBodyGenInfo { return *this; } - OpWithBodyGenInfo & - setReductions(llvm::SmallVector<const Fortran::semantics::Symbol *> *value1, - llvm::SmallVector<mlir::Type> *value2) { + OpWithBodyGenInfo &setReductions( + llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *value1, + llvm::SmallVectorImpl<mlir::Type> *value2) { reductionSymbols = value1; reductionTypes = value2; return *this; @@ -317,10 +507,10 @@ struct OpWithBodyGenInfo { /// [in] if provided, processes the construct's data-sharing attributes. DataSharingProcessor *dsp = nullptr; /// [in] if provided, list of reduction symbols - llvm::SmallVector<const Fortran::semantics::Symbol *> *reductionSymbols = + llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *reductionSymbols = nullptr; /// [in] if provided, list of reduction types - llvm::SmallVector<mlir::Type> *reductionTypes = nullptr; + llvm::SmallVectorImpl<mlir::Type> *reductionTypes = nullptr; /// [in] if provided, emits the op's region entry. Otherwise, an emtpy block /// is created in the region. GenOMPRegionEntryCBFn genRegionEntryCB = nullptr; @@ -365,7 +555,7 @@ static void createBodyOfOp(Op &op, OpWithBodyGenInfo &info) { // Start with privatization, so that the lowering of the nested // code will use the right symbols. - constexpr bool isLoop = std::is_same_v<Op, mlir::omp::WsLoopOp> || + constexpr bool isLoop = std::is_same_v<Op, mlir::omp::WsloopOp> || std::is_same_v<Op, mlir::omp::SimdLoopOp>; bool privatize = info.clauses && !info.outerCombined; @@ -373,7 +563,7 @@ static void createBodyOfOp(Op &op, OpWithBodyGenInfo &info) { std::optional<DataSharingProcessor> tempDsp; if (privatize) { if (!info.dsp) { - tempDsp.emplace(info.converter, *info.clauses, info.eval); + tempDsp.emplace(info.converter, info.semaCtx, *info.clauses, info.eval); tempDsp->processStep1(); } } @@ -465,11 +655,9 @@ static void genBodyOfTargetDataOp( Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::omp::DataOp &dataOp, - const llvm::SmallVector<mlir::Type> &useDeviceTypes, - const llvm::SmallVector<mlir::Location> &useDeviceLocs, - const llvm::SmallVector<const Fortran::semantics::Symbol *> - &useDeviceSymbols, + mlir::omp::TargetDataOp &dataOp, llvm::ArrayRef<mlir::Type> useDeviceTypes, + llvm::ArrayRef<mlir::Location> useDeviceLocs, + llvm::ArrayRef<const Fortran::semantics::Symbol *> useDeviceSymbols, const mlir::Location ¤tLocation) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); mlir::Region ®ion = dataOp.getRegion(); @@ -570,24 +758,19 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, mlir::omp::ClauseProcBindKindAttr procBindKindAttr; llvm::SmallVector<mlir::Value> allocateOperands, allocatorOperands, reductionVars; + llvm::SmallVector<mlir::Type> reductionTypes; llvm::SmallVector<mlir::Attribute> reductionDeclSymbols; llvm::SmallVector<const Fortran::semantics::Symbol *> reductionSymbols; ClauseProcessor cp(converter, semaCtx, clauseList); - cp.processIf(Fortran::parser::OmpIfClause::DirectiveNameModifier::Parallel, - ifClauseOperand); + cp.processIf(llvm::omp::Directive::OMPD_parallel, ifClauseOperand); cp.processNumThreads(stmtCtx, numThreadsClauseOperand); cp.processProcBind(procBindKindAttr); cp.processDefault(); cp.processAllocate(allocatorOperands, allocateOperands); if (!outerCombined) - cp.processReduction(currentLocation, reductionVars, reductionDeclSymbols, - &reductionSymbols); - - llvm::SmallVector<mlir::Type> reductionTypes; - reductionTypes.reserve(reductionVars.size()); - llvm::transform(reductionVars, std::back_inserter(reductionTypes), - [](mlir::Value v) { return v.getType(); }); + cp.processReduction(currentLocation, reductionVars, reductionTypes, + reductionDeclSymbols, &reductionSymbols); auto reductionCallback = [&](mlir::Operation *op) { llvm::SmallVector<mlir::Location> locs(reductionVars.size(), @@ -601,6 +784,10 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, return reductionSymbols; }; + mlir::UnitAttr byrefAttr; + if (ReductionProcessor::doReductionByRef(reductionVars)) + byrefAttr = converter.getFirOpBuilder().getUnitAttr(); + OpWithBodyGenInfo genInfo = OpWithBodyGenInfo(converter, semaCtx, currentLocation, eval) .setGenNested(genNested) @@ -620,11 +807,11 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, : mlir::ArrayAttr::get(converter.getFirOpBuilder().getContext(), reductionDeclSymbols), procBindKindAttr, /*private_vars=*/llvm::SmallVector<mlir::Value>{}, - /*privatizers=*/nullptr); + /*privatizers=*/nullptr, byrefAttr); } bool privatize = !outerCombined; - DataSharingProcessor dsp(converter, clauseList, eval, + DataSharingProcessor dsp(converter, semaCtx, clauseList, eval, /*useDelayedPrivatization=*/true, &symTable); if (privatize) @@ -684,7 +871,8 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, delayedPrivatizationInfo.privatizers.empty() ? nullptr : mlir::ArrayAttr::get(converter.getFirOpBuilder().getContext(), - privatizers)); + privatizers), + byrefAttr); } static mlir::omp::SectionOp @@ -746,8 +934,7 @@ genTaskOp(Fortran::lower::AbstractConverter &converter, dependOperands; ClauseProcessor cp(converter, semaCtx, clauseList); - cp.processIf(Fortran::parser::OmpIfClause::DirectiveNameModifier::Task, - ifClauseOperand); + cp.processIf(llvm::omp::Directive::OMPD_task, ifClauseOperand); cp.processAllocate(allocatorOperands, allocateOperands); cp.processDefault(); cp.processFinal(stmtCtx, finalClauseOperand); @@ -755,9 +942,7 @@ genTaskOp(Fortran::lower::AbstractConverter &converter, cp.processMergeable(mergeableAttr); cp.processPriority(stmtCtx, priorityClauseOperand); cp.processDepend(dependTypeOperands, dependOperands); - cp.processTODO<Fortran::parser::OmpClause::InReduction, - Fortran::parser::OmpClause::Detach, - Fortran::parser::OmpClause::Affinity>( + cp.processTODO<clause::InReduction, clause::Detach, clause::Affinity>( currentLocation, llvm::omp::Directive::OMPD_task); return genOpWithBody<mlir::omp::TaskOp>( @@ -774,8 +959,8 @@ genTaskOp(Fortran::lower::AbstractConverter &converter, dependOperands, allocateOperands, allocatorOperands); } -static mlir::omp::TaskGroupOp -genTaskGroupOp(Fortran::lower::AbstractConverter &converter, +static mlir::omp::TaskgroupOp +genTaskgroupOp(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, bool genNested, mlir::Location currentLocation, @@ -783,9 +968,9 @@ genTaskGroupOp(Fortran::lower::AbstractConverter &converter, llvm::SmallVector<mlir::Value> allocateOperands, allocatorOperands; ClauseProcessor cp(converter, semaCtx, clauseList); cp.processAllocate(allocatorOperands, allocateOperands); - cp.processTODO<Fortran::parser::OmpClause::TaskReduction>( - currentLocation, llvm::omp::Directive::OMPD_taskgroup); - return genOpWithBody<mlir::omp::TaskGroupOp>( + cp.processTODO<clause::TaskReduction>(currentLocation, + llvm::omp::Directive::OMPD_taskgroup); + return genOpWithBody<mlir::omp::TaskgroupOp>( OpWithBodyGenInfo(converter, semaCtx, currentLocation, eval) .setGenNested(genNested) .setClauses(&clauseList), @@ -793,12 +978,65 @@ genTaskGroupOp(Fortran::lower::AbstractConverter &converter, /*task_reductions=*/nullptr, allocateOperands, allocatorOperands); } -static mlir::omp::DataOp -genDataOp(Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::Location currentLocation, - const Fortran::parser::OmpClauseList &clauseList) { +// This helper function implements the functionality of "promoting" +// non-CPTR arguments of use_device_ptr to use_device_addr +// arguments (automagic conversion of use_device_ptr -> +// use_device_addr in these cases). The way we do so currently is +// through the shuffling of operands from the devicePtrOperands to +// deviceAddrOperands where neccesary and re-organizing the types, +// locations and symbols to maintain the correct ordering of ptr/addr +// input -> BlockArg. +// +// This effectively implements some deprecated OpenMP functionality +// that some legacy applications unfortunately depend on +// (deprecated in specification version 5.2): +// +// "If a list item in a use_device_ptr clause is not of type C_PTR, +// the behavior is as if the list item appeared in a use_device_addr +// clause. Support for such list items in a use_device_ptr clause +// is deprecated." +static void promoteNonCPtrUseDevicePtrArgsToUseDeviceAddr( + llvm::SmallVectorImpl<mlir::Value> &devicePtrOperands, + llvm::SmallVectorImpl<mlir::Value> &deviceAddrOperands, + llvm::SmallVectorImpl<mlir::Type> &useDeviceTypes, + llvm::SmallVectorImpl<mlir::Location> &useDeviceLocs, + llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> + &useDeviceSymbols) { + auto moveElementToBack = [](size_t idx, auto &vector) { + auto *iter = std::next(vector.begin(), idx); + vector.push_back(*iter); + vector.erase(iter); + }; + + // Iterate over our use_device_ptr list and shift all non-cptr arguments into + // use_device_addr. + for (auto *it = devicePtrOperands.begin(); it != devicePtrOperands.end();) { + if (!fir::isa_builtin_cptr_type(fir::unwrapRefType(it->getType()))) { + deviceAddrOperands.push_back(*it); + // We have to shuffle the symbols around as well, to maintain + // the correct Input -> BlockArg for use_device_ptr/use_device_addr. + // NOTE: However, as map's do not seem to be included currently + // this isn't as pertinent, but we must try to maintain for + // future alterations. I believe the reason they are not currently + // is that the BlockArg assign/lowering needs to be extended + // to a greater set of types. + auto idx = std::distance(devicePtrOperands.begin(), it); + moveElementToBack(idx, useDeviceTypes); + moveElementToBack(idx, useDeviceLocs); + moveElementToBack(idx, useDeviceSymbols); + it = devicePtrOperands.erase(it); + continue; + } + ++it; + } +} + +static mlir::omp::TargetDataOp +genTargetDataOp(Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, bool genNested, + mlir::Location currentLocation, + const Fortran::parser::OmpClauseList &clauseList) { Fortran::lower::StatementContext stmtCtx; mlir::Value ifClauseOperand, deviceOperand; llvm::SmallVector<mlir::Value> mapOperands, devicePtrOperands, @@ -808,17 +1046,30 @@ genDataOp(Fortran::lower::AbstractConverter &converter, llvm::SmallVector<const Fortran::semantics::Symbol *> useDeviceSymbols; ClauseProcessor cp(converter, semaCtx, clauseList); - cp.processIf(Fortran::parser::OmpIfClause::DirectiveNameModifier::TargetData, - ifClauseOperand); + cp.processIf(llvm::omp::Directive::OMPD_target_data, ifClauseOperand); cp.processDevice(stmtCtx, deviceOperand); cp.processUseDevicePtr(devicePtrOperands, useDeviceTypes, useDeviceLocs, useDeviceSymbols); cp.processUseDeviceAddr(deviceAddrOperands, useDeviceTypes, useDeviceLocs, useDeviceSymbols); + // This function implements the deprecated functionality of use_device_ptr + // that allows users to provide non-CPTR arguments to it with the caveat + // that the compiler will treat them as use_device_addr. A lot of legacy + // code may still depend on this functionality, so we should support it + // in some manner. We do so currently by simply shifting non-cptr operands + // from the use_device_ptr list into the front of the use_device_addr list + // whilst maintaining the ordering of useDeviceLocs, useDeviceSymbols and + // useDeviceTypes to use_device_ptr/use_device_addr input for BlockArg + // ordering. + // TODO: Perhaps create a user provideable compiler option that will + // re-introduce a hard-error rather than a warning in these cases. + promoteNonCPtrUseDevicePtrArgsToUseDeviceAddr( + devicePtrOperands, deviceAddrOperands, useDeviceTypes, useDeviceLocs, + useDeviceSymbols); cp.processMap(currentLocation, llvm::omp::Directive::OMPD_target_data, stmtCtx, mapOperands); - auto dataOp = converter.getFirOpBuilder().create<mlir::omp::DataOp>( + auto dataOp = converter.getFirOpBuilder().create<mlir::omp::TargetDataOp>( currentLocation, ifClauseOperand, deviceOperand, devicePtrOperands, deviceAddrOperands, mapOperands); genBodyOfTargetDataOp(converter, semaCtx, eval, genNested, dataOp, @@ -828,11 +1079,11 @@ genDataOp(Fortran::lower::AbstractConverter &converter, } template <typename OpTy> -static OpTy -genEnterExitUpdateDataOp(Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - mlir::Location currentLocation, - const Fortran::parser::OmpClauseList &clauseList) { +static OpTy genTargetEnterExitDataUpdateOp( + Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semaCtx, + mlir::Location currentLocation, + const Fortran::parser::OmpClauseList &clauseList) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); Fortran::lower::StatementContext stmtCtx; mlir::Value ifClauseOperand, deviceOperand; @@ -840,37 +1091,27 @@ genEnterExitUpdateDataOp(Fortran::lower::AbstractConverter &converter, llvm::SmallVector<mlir::Value> mapOperands, dependOperands; llvm::SmallVector<mlir::Attribute> dependTypeOperands; - Fortran::parser::OmpIfClause::DirectiveNameModifier directiveName; // GCC 9.3.0 emits a (probably) bogus warning about an unused variable. [[maybe_unused]] llvm::omp::Directive directive; - if constexpr (std::is_same_v<OpTy, mlir::omp::EnterDataOp>) { - directiveName = - Fortran::parser::OmpIfClause::DirectiveNameModifier::TargetEnterData; + if constexpr (std::is_same_v<OpTy, mlir::omp::TargetEnterDataOp>) { directive = llvm::omp::Directive::OMPD_target_enter_data; - } else if constexpr (std::is_same_v<OpTy, mlir::omp::ExitDataOp>) { - directiveName = - Fortran::parser::OmpIfClause::DirectiveNameModifier::TargetExitData; + } else if constexpr (std::is_same_v<OpTy, mlir::omp::TargetExitDataOp>) { directive = llvm::omp::Directive::OMPD_target_exit_data; - } else if constexpr (std::is_same_v<OpTy, mlir::omp::UpdateDataOp>) { - directiveName = - Fortran::parser::OmpIfClause::DirectiveNameModifier::TargetUpdate; + } else if constexpr (std::is_same_v<OpTy, mlir::omp::TargetUpdateOp>) { directive = llvm::omp::Directive::OMPD_target_update; } else { return nullptr; } ClauseProcessor cp(converter, semaCtx, clauseList); - cp.processIf(directiveName, ifClauseOperand); + cp.processIf(directive, ifClauseOperand); cp.processDevice(stmtCtx, deviceOperand); cp.processDepend(dependTypeOperands, dependOperands); cp.processNowait(nowaitAttr); - if constexpr (std::is_same_v<OpTy, mlir::omp::UpdateDataOp>) { - cp.processMotionClauses<Fortran::parser::OmpClause::To>(stmtCtx, - mapOperands); - cp.processMotionClauses<Fortran::parser::OmpClause::From>(stmtCtx, - mapOperands); - + if constexpr (std::is_same_v<OpTy, mlir::omp::TargetUpdateOp>) { + cp.processMotionClauses<clause::To>(stmtCtx, mapOperands); + cp.processMotionClauses<clause::From>(stmtCtx, mapOperands); } else { cp.processMap(currentLocation, directive, stmtCtx, mapOperands); } @@ -886,15 +1127,15 @@ genEnterExitUpdateDataOp(Fortran::lower::AbstractConverter &converter, // This functions creates a block for the body of the targetOp's region. It adds // all the symbols present in mapSymbols as block arguments to this block. -static void genBodyOfTargetOp( - Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, bool genNested, - mlir::omp::TargetOp &targetOp, - const llvm::SmallVector<mlir::Type> &mapSymTypes, - const llvm::SmallVector<mlir::Location> &mapSymLocs, - const llvm::SmallVector<const Fortran::semantics::Symbol *> &mapSymbols, - const mlir::Location ¤tLocation) { +static void +genBodyOfTargetOp(Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, bool genNested, + mlir::omp::TargetOp &targetOp, + llvm::ArrayRef<mlir::Type> mapSymTypes, + llvm::ArrayRef<mlir::Location> mapSymLocs, + llvm::ArrayRef<const Fortran::semantics::Symbol *> mapSymbols, + const mlir::Location ¤tLocation) { assert(mapSymTypes.size() == mapSymLocs.size()); fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); @@ -1055,8 +1296,7 @@ genTargetOp(Fortran::lower::AbstractConverter &converter, llvm::SmallVector<const Fortran::semantics::Symbol *> mapSymbols; ClauseProcessor cp(converter, semaCtx, clauseList); - cp.processIf(Fortran::parser::OmpIfClause::DirectiveNameModifier::Target, - ifClauseOperand); + cp.processIf(llvm::omp::Directive::OMPD_target, ifClauseOperand); cp.processDevice(stmtCtx, deviceOperand); cp.processThreadLimit(stmtCtx, threadLimitOperand); cp.processDepend(dependTypeOperands, dependOperands); @@ -1064,16 +1304,11 @@ genTargetOp(Fortran::lower::AbstractConverter &converter, cp.processMap(currentLocation, directive, stmtCtx, mapOperands, &mapSymTypes, &mapSymLocs, &mapSymbols); - cp.processTODO<Fortran::parser::OmpClause::Private, - Fortran::parser::OmpClause::Firstprivate, - Fortran::parser::OmpClause::IsDevicePtr, - Fortran::parser::OmpClause::HasDeviceAddr, - Fortran::parser::OmpClause::Reduction, - Fortran::parser::OmpClause::InReduction, - Fortran::parser::OmpClause::Allocate, - Fortran::parser::OmpClause::UsesAllocators, - Fortran::parser::OmpClause::Defaultmap>( + cp.processTODO<clause::Private, clause::Firstprivate, clause::IsDevicePtr, + clause::HasDeviceAddr, clause::Reduction, clause::InReduction, + clause::Allocate, clause::UsesAllocators, clause::Defaultmap>( currentLocation, llvm::omp::Directive::OMPD_target); + // 5.8.1 Implicit Data-Mapping Attribute Rules // The following code follows the implicit data-mapping rules to map all the // symbols used inside the region that have not been explicitly mapped using @@ -1099,15 +1334,15 @@ genTargetOp(Fortran::lower::AbstractConverter &converter, converter.getCurrentLocation()); if (fir::unwrapRefType(info.addr.getType()).isa<fir::BaseBoxType>()) bounds = - Fortran::lower::genBoundsOpsFromBox<mlir::omp::DataBoundsOp, - mlir::omp::DataBoundsType>( + Fortran::lower::genBoundsOpsFromBox<mlir::omp::MapBoundsOp, + mlir::omp::MapBoundsType>( converter.getFirOpBuilder(), converter.getCurrentLocation(), converter, dataExv, info); if (fir::unwrapRefType(info.addr.getType()).isa<fir::SequenceType>()) { bool dataExvIsAssumedSize = Fortran::semantics::IsAssumedSizeArray(sym.GetUltimate()); - bounds = Fortran::lower::genBaseBoundsOps<mlir::omp::DataBoundsOp, - mlir::omp::DataBoundsType>( + bounds = Fortran::lower::genBaseBoundsOps<mlir::omp::MapBoundsOp, + mlir::omp::MapBoundsType>( converter.getFirOpBuilder(), converter.getCurrentLocation(), converter, dataExv, dataExvIsAssumedSize); } @@ -1187,14 +1422,13 @@ genTeamsOp(Fortran::lower::AbstractConverter &converter, llvm::SmallVector<mlir::Attribute> reductionDeclSymbols; ClauseProcessor cp(converter, semaCtx, clauseList); - cp.processIf(Fortran::parser::OmpIfClause::DirectiveNameModifier::Teams, - ifClauseOperand); + cp.processIf(llvm::omp::Directive::OMPD_teams, ifClauseOperand); cp.processAllocate(allocatorOperands, allocateOperands); cp.processDefault(); cp.processNumTeams(stmtCtx, numTeamsClauseOperand); cp.processThreadLimit(stmtCtx, threadLimitClauseOperand); - cp.processTODO<Fortran::parser::OmpClause::Reduction>( - currentLocation, llvm::omp::Directive::OMPD_teams); + cp.processTODO<clause::Reduction>(currentLocation, + llvm::omp::Directive::OMPD_teams); return genOpWithBody<mlir::omp::TeamsOp>( OpWithBodyGenInfo(converter, semaCtx, currentLocation, eval) @@ -1227,8 +1461,9 @@ static mlir::omp::DeclareTargetDeviceType getDeclareTargetInfo( if (const auto *objectList{ Fortran::parser::Unwrap<Fortran::parser::OmpObjectList>(spec.u)}) { + ObjectList objects{makeObjects(*objectList, semaCtx)}; // Case: declare target(func, var1, var2) - gatherFuncAndVarSyms(*objectList, mlir::omp::DeclareTargetCaptureClause::to, + gatherFuncAndVarSyms(objects, mlir::omp::DeclareTargetCaptureClause::to, symbolAndClause); } else if (const auto *clauseList{ Fortran::parser::Unwrap<Fortran::parser::OmpClauseList>( @@ -1245,9 +1480,8 @@ static mlir::omp::DeclareTargetDeviceType getDeclareTargetInfo( cp.processEnter(symbolAndClause); cp.processLink(symbolAndClause); cp.processDeviceType(deviceType); - cp.processTODO<Fortran::parser::OmpClause::Indirect>( - converter.getCurrentLocation(), - llvm::omp::Directive::OMPD_declare_target); + cp.processTODO<clause::Indirect>(converter.getCurrentLocation(), + llvm::omp::Directive::OMPD_declare_target); } return deviceType; @@ -1329,8 +1563,7 @@ genOmpSimpleStandalone(Fortran::lower::AbstractConverter &converter, break; case llvm::omp::Directive::OMPD_taskwait: ClauseProcessor(converter, semaCtx, opClauseList) - .processTODO<Fortran::parser::OmpClause::Depend, - Fortran::parser::OmpClause::Nowait>( + .processTODO<clause::Depend, clause::Nowait>( currentLocation, llvm::omp::Directive::OMPD_taskwait); firOpBuilder.create<mlir::omp::TaskwaitOp>(currentLocation); break; @@ -1338,19 +1571,19 @@ genOmpSimpleStandalone(Fortran::lower::AbstractConverter &converter, firOpBuilder.create<mlir::omp::TaskyieldOp>(currentLocation); break; case llvm::omp::Directive::OMPD_target_data: - genDataOp(converter, semaCtx, eval, genNested, currentLocation, - opClauseList); + genTargetDataOp(converter, semaCtx, eval, genNested, currentLocation, + opClauseList); break; case llvm::omp::Directive::OMPD_target_enter_data: - genEnterExitUpdateDataOp<mlir::omp::EnterDataOp>( + genTargetEnterExitDataUpdateOp<mlir::omp::TargetEnterDataOp>( converter, semaCtx, currentLocation, opClauseList); break; case llvm::omp::Directive::OMPD_target_exit_data: - genEnterExitUpdateDataOp<mlir::omp::ExitDataOp>( + genTargetEnterExitDataUpdateOp<mlir::omp::TargetExitDataOp>( converter, semaCtx, currentLocation, opClauseList); break; case llvm::omp::Directive::OMPD_target_update: - genEnterExitUpdateDataOp<mlir::omp::UpdateDataOp>( + genTargetEnterExitDataUpdateOp<mlir::omp::TargetUpdateOp>( converter, semaCtx, currentLocation, opClauseList); break; case llvm::omp::Directive::OMPD_ordered: @@ -1367,7 +1600,7 @@ genOmpFlush(Fortran::lower::AbstractConverter &converter, if (const auto &ompObjectList = std::get<std::optional<Fortran::parser::OmpObjectList>>( flushConstruct.t)) - genObjectList(*ompObjectList, converter, operandRange); + genObjectList2(*ompObjectList, converter, operandRange); const auto &memOrderClause = std::get<std::optional<std::list<Fortran::parser::OmpMemoryOrderClause>>>( flushConstruct.t); @@ -1377,57 +1610,10 @@ genOmpFlush(Fortran::lower::AbstractConverter &converter, converter.getCurrentLocation(), operandRange); } -static void -genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPStandaloneConstruct &standaloneConstruct) { - std::visit( - Fortran::common::visitors{ - [&](const Fortran::parser::OpenMPSimpleStandaloneConstruct - &simpleStandaloneConstruct) { - genOmpSimpleStandalone(converter, semaCtx, eval, - /*genNested=*/true, - simpleStandaloneConstruct); - }, - [&](const Fortran::parser::OpenMPFlushConstruct &flushConstruct) { - genOmpFlush(converter, semaCtx, eval, flushConstruct); - }, - [&](const Fortran::parser::OpenMPCancelConstruct &cancelConstruct) { - TODO(converter.getCurrentLocation(), "OpenMPCancelConstruct"); - }, - [&](const Fortran::parser::OpenMPCancellationPointConstruct - &cancellationPointConstruct) { - TODO(converter.getCurrentLocation(), "OpenMPCancelConstruct"); - }, - }, - standaloneConstruct.u); -} - -static void convertLoopBounds(Fortran::lower::AbstractConverter &converter, - mlir::Location loc, - llvm::SmallVectorImpl<mlir::Value> &lowerBound, - llvm::SmallVectorImpl<mlir::Value> &upperBound, - llvm::SmallVectorImpl<mlir::Value> &step, - std::size_t loopVarTypeSize) { - fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - // The types of lower bound, upper bound, and step are converted into the - // type of the loop variable if necessary. - mlir::Type loopVarType = getLoopVarType(converter, loopVarTypeSize); - for (unsigned it = 0; it < (unsigned)lowerBound.size(); it++) { - lowerBound[it] = - firOpBuilder.createConvert(loc, loopVarType, lowerBound[it]); - upperBound[it] = - firOpBuilder.createConvert(loc, loopVarType, upperBound[it]); - step[it] = firOpBuilder.createConvert(loc, loopVarType, step[it]); - } -} - static llvm::SmallVector<const Fortran::semantics::Symbol *> genLoopVars(mlir::Operation *op, Fortran::lower::AbstractConverter &converter, mlir::Location &loc, - const llvm::SmallVector<const Fortran::semantics::Symbol *> &args) { + llvm::ArrayRef<const Fortran::semantics::Symbol *> args) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); auto ®ion = op->getRegion(0); @@ -1448,16 +1634,16 @@ genLoopVars(mlir::Operation *op, Fortran::lower::AbstractConverter &converter, } firOpBuilder.setInsertionPointAfter(storeOp); - return args; + return llvm::SmallVector<const Fortran::semantics::Symbol *>(args); } static llvm::SmallVector<const Fortran::semantics::Symbol *> genLoopAndReductionVars( mlir::Operation *op, Fortran::lower::AbstractConverter &converter, mlir::Location &loc, - const llvm::SmallVector<const Fortran::semantics::Symbol *> &loopArgs, - const llvm::SmallVector<const Fortran::semantics::Symbol *> &reductionArgs, - llvm::SmallVector<mlir::Type> &reductionTypes) { + llvm::ArrayRef<const Fortran::semantics::Symbol *> loopArgs, + llvm::ArrayRef<const Fortran::semantics::Symbol *> reductionArgs, + llvm::ArrayRef<mlir::Type> reductionTypes) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); llvm::SmallVector<mlir::Type> blockArgTypes; @@ -1500,7 +1686,7 @@ genLoopAndReductionVars( converter.bindSymbol(*arg, prv); } - return loopArgs; + return llvm::SmallVector<const Fortran::semantics::Symbol *>(loopArgs); } static void @@ -1511,7 +1697,7 @@ createSimdLoop(Fortran::lower::AbstractConverter &converter, const Fortran::parser::OmpClauseList &loopOpClauseList, mlir::Location loc) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - DataSharingProcessor dsp(converter, loopOpClauseList, eval); + DataSharingProcessor dsp(converter, semaCtx, loopOpClauseList, eval); dsp.processStep1(); Fortran::lower::StatementContext stmtCtx; @@ -1519,28 +1705,20 @@ createSimdLoop(Fortran::lower::AbstractConverter &converter, llvm::SmallVector<mlir::Value> lowerBound, upperBound, step, reductionVars; llvm::SmallVector<mlir::Value> alignedVars, nontemporalVars; llvm::SmallVector<const Fortran::semantics::Symbol *> iv; + llvm::SmallVector<mlir::Type> reductionTypes; llvm::SmallVector<mlir::Attribute> reductionDeclSymbols; mlir::omp::ClauseOrderKindAttr orderClauseOperand; mlir::IntegerAttr simdlenClauseOperand, safelenClauseOperand; - std::size_t loopVarTypeSize; ClauseProcessor cp(converter, semaCtx, loopOpClauseList); - cp.processCollapse(loc, eval, lowerBound, upperBound, step, iv, - loopVarTypeSize); + cp.processCollapse(loc, eval, lowerBound, upperBound, step, iv); cp.processScheduleChunk(stmtCtx, scheduleChunkClauseOperand); - cp.processReduction(loc, reductionVars, reductionDeclSymbols); - cp.processIf(Fortran::parser::OmpIfClause::DirectiveNameModifier::Simd, - ifClauseOperand); + cp.processReduction(loc, reductionVars, reductionTypes, reductionDeclSymbols); + cp.processIf(llvm::omp::Directive::OMPD_simd, ifClauseOperand); cp.processSimdlen(simdlenClauseOperand); cp.processSafelen(safelenClauseOperand); - cp.processTODO<Fortran::parser::OmpClause::Aligned, - Fortran::parser::OmpClause::Allocate, - Fortran::parser::OmpClause::Linear, - Fortran::parser::OmpClause::Nontemporal, - Fortran::parser::OmpClause::Order>(loc, ompDirective); - - convertLoopBounds(converter, loc, lowerBound, upperBound, step, - loopVarTypeSize); + cp.processTODO<clause::Aligned, clause::Allocate, clause::Linear, + clause::Nontemporal, clause::Order>(loc, ompDirective); mlir::TypeRange resultType; auto simdLoopOp = firOpBuilder.create<mlir::omp::SimdLoopOp>( @@ -1563,7 +1741,7 @@ createSimdLoop(Fortran::lower::AbstractConverter &converter, .setGenRegionEntryCb(ivCallback)); } -static void createWsLoop(Fortran::lower::AbstractConverter &converter, +static void createWsloop(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, llvm::omp::Directive ompDirective, @@ -1571,7 +1749,7 @@ static void createWsLoop(Fortran::lower::AbstractConverter &converter, const Fortran::parser::OmpClauseList *endClauseList, mlir::Location loc) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - DataSharingProcessor dsp(converter, beginClauseList, eval); + DataSharingProcessor dsp(converter, semaCtx, beginClauseList, eval); dsp.processStep1(); Fortran::lower::StatementContext stmtCtx; @@ -1579,28 +1757,26 @@ static void createWsLoop(Fortran::lower::AbstractConverter &converter, llvm::SmallVector<mlir::Value> lowerBound, upperBound, step, reductionVars; llvm::SmallVector<mlir::Value> linearVars, linearStepVars; llvm::SmallVector<const Fortran::semantics::Symbol *> iv; + llvm::SmallVector<mlir::Type> reductionTypes; llvm::SmallVector<mlir::Attribute> reductionDeclSymbols; llvm::SmallVector<const Fortran::semantics::Symbol *> reductionSymbols; mlir::omp::ClauseOrderKindAttr orderClauseOperand; mlir::omp::ClauseScheduleKindAttr scheduleValClauseOperand; - mlir::UnitAttr nowaitClauseOperand, scheduleSimdClauseOperand; + mlir::UnitAttr nowaitClauseOperand, byrefOperand, scheduleSimdClauseOperand; mlir::IntegerAttr orderedClauseOperand; mlir::omp::ScheduleModifierAttr scheduleModClauseOperand; - std::size_t loopVarTypeSize; ClauseProcessor cp(converter, semaCtx, beginClauseList); - cp.processCollapse(loc, eval, lowerBound, upperBound, step, iv, - loopVarTypeSize); + cp.processCollapse(loc, eval, lowerBound, upperBound, step, iv); cp.processScheduleChunk(stmtCtx, scheduleChunkClauseOperand); - cp.processReduction(loc, reductionVars, reductionDeclSymbols, + cp.processReduction(loc, reductionVars, reductionTypes, reductionDeclSymbols, &reductionSymbols); - cp.processTODO<Fortran::parser::OmpClause::Linear, - Fortran::parser::OmpClause::Order>(loc, ompDirective); + cp.processTODO<clause::Linear, clause::Order>(loc, ompDirective); - convertLoopBounds(converter, loc, lowerBound, upperBound, step, - loopVarTypeSize); + if (ReductionProcessor::doReductionByRef(reductionVars)) + byrefOperand = firOpBuilder.getUnitAttr(); - auto wsLoopOp = firOpBuilder.create<mlir::omp::WsLoopOp>( + auto wsLoopOp = firOpBuilder.create<mlir::omp::WsloopOp>( loc, lowerBound, upperBound, step, linearVars, linearStepVars, reductionVars, reductionDeclSymbols.empty() @@ -1609,8 +1785,8 @@ static void createWsLoop(Fortran::lower::AbstractConverter &converter, reductionDeclSymbols), scheduleValClauseOperand, scheduleChunkClauseOperand, /*schedule_modifiers=*/nullptr, - /*simd_modifier=*/nullptr, nowaitClauseOperand, orderedClauseOperand, - orderClauseOperand, + /*simd_modifier=*/nullptr, nowaitClauseOperand, byrefOperand, + orderedClauseOperand, orderClauseOperand, /*inclusive=*/firOpBuilder.getUnitAttr()); // Handle attribute based clauses. @@ -1637,17 +1813,12 @@ static void createWsLoop(Fortran::lower::AbstractConverter &converter, auto *nestedEval = getCollapsedLoopEval( eval, Fortran::lower::getCollapseValue(beginClauseList)); - llvm::SmallVector<mlir::Type> reductionTypes; - reductionTypes.reserve(reductionVars.size()); - llvm::transform(reductionVars, std::back_inserter(reductionTypes), - [](mlir::Value v) { return v.getType(); }); - auto ivCallback = [&](mlir::Operation *op) { return genLoopAndReductionVars(op, converter, loc, iv, reductionSymbols, reductionTypes); }; - createBodyOfOp<mlir::omp::WsLoopOp>( + createBodyOfOp<mlir::omp::WsloopOp>( wsLoopOp, OpWithBodyGenInfo(converter, semaCtx, loc, *nestedEval) .setClauses(&beginClauseList) .setDataSharingProcessor(&dsp) @@ -1655,18 +1826,16 @@ static void createWsLoop(Fortran::lower::AbstractConverter &converter, .setGenRegionEntryCb(ivCallback)); } -static void createSimdWsLoop( +static void createSimdWsloop( Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, llvm::omp::Directive ompDirective, const Fortran::parser::OmpClauseList &beginClauseList, const Fortran::parser::OmpClauseList *endClauseList, mlir::Location loc) { ClauseProcessor cp(converter, semaCtx, beginClauseList); - cp.processTODO< - Fortran::parser::OmpClause::Aligned, Fortran::parser::OmpClause::Allocate, - Fortran::parser::OmpClause::Linear, Fortran::parser::OmpClause::Safelen, - Fortran::parser::OmpClause::Simdlen, Fortran::parser::OmpClause::Order>( - loc, ompDirective); + cp.processTODO<clause::Aligned, clause::Allocate, clause::Linear, + clause::Safelen, clause::Simdlen, clause::Order>(loc, + ompDirective); // TODO: Add support for vectorization - add vectorization hints inside loop // body. // OpenMP standard does not specify the length of vector instructions. @@ -1675,92 +1844,185 @@ static void createSimdWsLoop( // When support for vectorization is enabled, then we need to add handling of // if clause. Currently if clause can be skipped because we always assume // SIMD length = 1. - createWsLoop(converter, semaCtx, eval, ompDirective, beginClauseList, + createWsloop(converter, semaCtx, eval, ompDirective, beginClauseList, endClauseList, loc); } +static void +markDeclareTarget(mlir::Operation *op, + Fortran::lower::AbstractConverter &converter, + mlir::omp::DeclareTargetCaptureClause captureClause, + mlir::omp::DeclareTargetDeviceType deviceType) { + // TODO: Add support for program local variables with declare target applied + auto declareTargetOp = llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(op); + if (!declareTargetOp) + fir::emitFatalError( + converter.getCurrentLocation(), + "Attempt to apply declare target on unsupported operation"); + + // The function or global already has a declare target applied to it, very + // likely through implicit capture (usage in another declare target + // function/subroutine). It should be marked as any if it has been assigned + // both host and nohost, else we skip, as there is no change + if (declareTargetOp.isDeclareTarget()) { + if (declareTargetOp.getDeclareTargetDeviceType() != deviceType) + declareTargetOp.setDeclareTarget(mlir::omp::DeclareTargetDeviceType::any, + captureClause); + return; + } + + declareTargetOp.setDeclareTarget(deviceType, captureClause); +} + +//===----------------------------------------------------------------------===// +// OpenMPDeclarativeConstruct visitors +//===----------------------------------------------------------------------===// + +static void +genOMP(Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPDeclarativeAllocate &declarativeAllocate) { + TODO(converter.getCurrentLocation(), "OpenMPDeclarativeAllocate"); +} + static void genOMP(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPLoopConstruct &loopConstruct) { - const auto &beginLoopDirective = - std::get<Fortran::parser::OmpBeginLoopDirective>(loopConstruct.t); - const auto &loopOpClauseList = - std::get<Fortran::parser::OmpClauseList>(beginLoopDirective.t); - mlir::Location currentLocation = - converter.genLocation(beginLoopDirective.source); - const auto ompDirective = - std::get<Fortran::parser::OmpLoopDirective>(beginLoopDirective.t).v; - - const auto *endClauseList = [&]() { - using RetTy = const Fortran::parser::OmpClauseList *; - if (auto &endLoopDirective = - std::get<std::optional<Fortran::parser::OmpEndLoopDirective>>( - loopConstruct.t)) { - return RetTy( - &std::get<Fortran::parser::OmpClauseList>((*endLoopDirective).t)); - } - return RetTy(); - }(); + const Fortran::parser::OpenMPDeclareReductionConstruct + &declareReductionConstruct) { + TODO(converter.getCurrentLocation(), "OpenMPDeclareReductionConstruct"); +} - bool validDirective = false; - if (llvm::omp::topTaskloopSet.test(ompDirective)) { - validDirective = true; - TODO(currentLocation, "Taskloop construct"); - } else { - // Create omp.{target, teams, distribute, parallel} nested operations - if ((llvm::omp::allTargetSet & llvm::omp::loopConstructSet) - .test(ompDirective)) { - validDirective = true; - genTargetOp(converter, semaCtx, eval, /*genNested=*/false, - currentLocation, loopOpClauseList, ompDirective, - /*outerCombined=*/true); - } - if ((llvm::omp::allTeamsSet & llvm::omp::loopConstructSet) - .test(ompDirective)) { - validDirective = true; - genTeamsOp(converter, semaCtx, eval, /*genNested=*/false, currentLocation, - loopOpClauseList, - /*outerCombined=*/true); - } - if (llvm::omp::allDistributeSet.test(ompDirective)) { - validDirective = true; - TODO(currentLocation, "Distribute construct"); - } - if ((llvm::omp::allParallelSet & llvm::omp::loopConstructSet) - .test(ompDirective)) { - validDirective = true; - genParallelOp(converter, symTable, semaCtx, eval, /*genNested=*/false, - currentLocation, loopOpClauseList, - /*outerCombined=*/true); - } - } - if ((llvm::omp::allDoSet | llvm::omp::allSimdSet).test(ompDirective)) - validDirective = true; +static void genOMP( + Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPDeclareSimdConstruct &declareSimdConstruct) { + TODO(converter.getCurrentLocation(), "OpenMPDeclareSimdConstruct"); +} - if (!validDirective) { - TODO(currentLocation, "Unhandled loop directive (" + - llvm::omp::getOpenMPDirectiveName(ompDirective) + - ")"); - } +static void genOMP(Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPDeclareTargetConstruct + &declareTargetConstruct) { + llvm::SmallVector<DeclareTargetCapturePair> symbolAndClause; + mlir::ModuleOp mod = converter.getFirOpBuilder().getModule(); + mlir::omp::DeclareTargetDeviceType deviceType = getDeclareTargetInfo( + converter, semaCtx, eval, declareTargetConstruct, symbolAndClause); - if (llvm::omp::allDoSimdSet.test(ompDirective)) { - // 2.9.3.2 Workshare SIMD construct - createSimdWsLoop(converter, semaCtx, eval, ompDirective, loopOpClauseList, - endClauseList, currentLocation); + for (const DeclareTargetCapturePair &symClause : symbolAndClause) { + mlir::Operation *op = mod.lookupSymbol(converter.mangleName( + std::get<const Fortran::semantics::Symbol &>(symClause))); - } else if (llvm::omp::allSimdSet.test(ompDirective)) { - // 2.9.3.1 SIMD construct - createSimdLoop(converter, semaCtx, eval, ompDirective, loopOpClauseList, - currentLocation); - genOpenMPReduction(converter, semaCtx, loopOpClauseList); - } else { - createWsLoop(converter, semaCtx, eval, ompDirective, loopOpClauseList, - endClauseList, currentLocation); + // Some symbols are deferred until later in the module, these are handled + // upon finalization of the module for OpenMP inside of Bridge, so we simply + // skip for now. + if (!op) + continue; + + markDeclareTarget( + op, converter, + std::get<mlir::omp::DeclareTargetCaptureClause>(symClause), deviceType); } } +static void +genOMP(Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPRequiresConstruct &requiresConstruct) { + // Requires directives are gathered and processed in semantics and + // then combined in the lowering bridge before triggering codegen + // just once. Hence, there is no need to lower each individual + // occurrence here. +} + +static void genOMP(Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPThreadprivate &threadprivate) { + // The directive is lowered when instantiating the variable to + // support the case of threadprivate variable declared in module. +} + +static void +genOMP(Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPDeclarativeConstruct &ompDeclConstruct) { + std::visit( + [&](auto &&s) { return genOMP(converter, symTable, semaCtx, eval, s); }, + ompDeclConstruct.u); +} + +//===----------------------------------------------------------------------===// +// OpenMPConstruct visitors +//===----------------------------------------------------------------------===// + +static void +genOMP(Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPAllocatorsConstruct &allocsConstruct) { + TODO(converter.getCurrentLocation(), "OpenMPAllocatorsConstruct"); +} + +static void +genOMP(Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPAtomicConstruct &atomicConstruct) { + std::visit( + Fortran::common::visitors{ + [&](const Fortran::parser::OmpAtomicRead &atomicRead) { + mlir::Location loc = converter.genLocation(atomicRead.source); + Fortran::lower::genOmpAccAtomicRead< + Fortran::parser::OmpAtomicRead, + Fortran::parser::OmpAtomicClauseList>(converter, atomicRead, + loc); + }, + [&](const Fortran::parser::OmpAtomicWrite &atomicWrite) { + mlir::Location loc = converter.genLocation(atomicWrite.source); + Fortran::lower::genOmpAccAtomicWrite< + Fortran::parser::OmpAtomicWrite, + Fortran::parser::OmpAtomicClauseList>(converter, atomicWrite, + loc); + }, + [&](const Fortran::parser::OmpAtomic &atomicConstruct) { + mlir::Location loc = converter.genLocation(atomicConstruct.source); + Fortran::lower::genOmpAtomic<Fortran::parser::OmpAtomic, + Fortran::parser::OmpAtomicClauseList>( + converter, atomicConstruct, loc); + }, + [&](const Fortran::parser::OmpAtomicUpdate &atomicUpdate) { + mlir::Location loc = converter.genLocation(atomicUpdate.source); + Fortran::lower::genOmpAccAtomicUpdate< + Fortran::parser::OmpAtomicUpdate, + Fortran::parser::OmpAtomicClauseList>(converter, atomicUpdate, + loc); + }, + [&](const Fortran::parser::OmpAtomicCapture &atomicCapture) { + mlir::Location loc = converter.genLocation(atomicCapture.source); + Fortran::lower::genOmpAccAtomicCapture< + Fortran::parser::OmpAtomicCapture, + Fortran::parser::OmpAtomicClauseList>(converter, atomicCapture, + loc); + }, + }, + atomicConstruct.u); +} + static void genOMP(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, @@ -1833,15 +2095,15 @@ genOMP(Fortran::lower::AbstractConverter &converter, beginClauseList, directive.v); break; case llvm::omp::Directive::OMPD_target_data: - genDataOp(converter, semaCtx, eval, /*genNested=*/true, currentLocation, - beginClauseList); + genTargetDataOp(converter, semaCtx, eval, /*genNested=*/true, + currentLocation, beginClauseList); break; case llvm::omp::Directive::OMPD_task: genTaskOp(converter, semaCtx, eval, /*genNested=*/true, currentLocation, beginClauseList); break; case llvm::omp::Directive::OMPD_taskgroup: - genTaskGroupOp(converter, semaCtx, eval, /*genNested=*/true, + genTaskgroupOp(converter, semaCtx, eval, /*genNested=*/true, currentLocation, beginClauseList); break; case llvm::omp::Directive::OMPD_teams: @@ -1941,6 +2203,107 @@ genOMP(Fortran::lower::AbstractConverter &converter, createBodyOfOp<mlir::omp::CriticalOp>(criticalOp, genInfo); } +static void +genOMP(Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPExecutableAllocate &execAllocConstruct) { + TODO(converter.getCurrentLocation(), "OpenMPExecutableAllocate"); +} + +static void genOMP(Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPLoopConstruct &loopConstruct) { + const auto &beginLoopDirective = + std::get<Fortran::parser::OmpBeginLoopDirective>(loopConstruct.t); + const auto &loopOpClauseList = + std::get<Fortran::parser::OmpClauseList>(beginLoopDirective.t); + mlir::Location currentLocation = + converter.genLocation(beginLoopDirective.source); + const auto ompDirective = + std::get<Fortran::parser::OmpLoopDirective>(beginLoopDirective.t).v; + + const auto *endClauseList = [&]() { + using RetTy = const Fortran::parser::OmpClauseList *; + if (auto &endLoopDirective = + std::get<std::optional<Fortran::parser::OmpEndLoopDirective>>( + loopConstruct.t)) { + return RetTy( + &std::get<Fortran::parser::OmpClauseList>((*endLoopDirective).t)); + } + return RetTy(); + }(); + + bool validDirective = false; + if (llvm::omp::topTaskloopSet.test(ompDirective)) { + validDirective = true; + TODO(currentLocation, "Taskloop construct"); + } else { + // Create omp.{target, teams, distribute, parallel} nested operations + if ((llvm::omp::allTargetSet & llvm::omp::loopConstructSet) + .test(ompDirective)) { + validDirective = true; + genTargetOp(converter, semaCtx, eval, /*genNested=*/false, + currentLocation, loopOpClauseList, ompDirective, + /*outerCombined=*/true); + } + if ((llvm::omp::allTeamsSet & llvm::omp::loopConstructSet) + .test(ompDirective)) { + validDirective = true; + genTeamsOp(converter, semaCtx, eval, /*genNested=*/false, currentLocation, + loopOpClauseList, + /*outerCombined=*/true); + } + if (llvm::omp::allDistributeSet.test(ompDirective)) { + validDirective = true; + TODO(currentLocation, "Distribute construct"); + } + if ((llvm::omp::allParallelSet & llvm::omp::loopConstructSet) + .test(ompDirective)) { + validDirective = true; + genParallelOp(converter, symTable, semaCtx, eval, /*genNested=*/false, + currentLocation, loopOpClauseList, + /*outerCombined=*/true); + } + } + if ((llvm::omp::allDoSet | llvm::omp::allSimdSet).test(ompDirective)) + validDirective = true; + + if (!validDirective) { + TODO(currentLocation, "Unhandled loop directive (" + + llvm::omp::getOpenMPDirectiveName(ompDirective) + + ")"); + } + + if (llvm::omp::allDoSimdSet.test(ompDirective)) { + // 2.9.3.2 Workshare SIMD construct + createSimdWsloop(converter, semaCtx, eval, ompDirective, loopOpClauseList, + endClauseList, currentLocation); + + } else if (llvm::omp::allSimdSet.test(ompDirective)) { + // 2.9.3.1 SIMD construct + createSimdLoop(converter, semaCtx, eval, ompDirective, loopOpClauseList, + currentLocation); + genOpenMPReduction(converter, semaCtx, loopOpClauseList); + } else { + createWsloop(converter, semaCtx, eval, ompDirective, loopOpClauseList, + endClauseList, currentLocation); + } +} + +static void +genOMP(Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPSectionConstruct §ionConstruct) { + // SECTION constructs are handled as a part of SECTIONS. + llvm_unreachable("Unexpected standalone OMP SECTION"); +} + static void genOMP(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, @@ -2006,98 +2369,27 @@ genOMP(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPAtomicConstruct &atomicConstruct) { + const Fortran::parser::OpenMPStandaloneConstruct &standaloneConstruct) { std::visit( Fortran::common::visitors{ - [&](const Fortran::parser::OmpAtomicRead &atomicRead) { - mlir::Location loc = converter.genLocation(atomicRead.source); - Fortran::lower::genOmpAccAtomicRead< - Fortran::parser::OmpAtomicRead, - Fortran::parser::OmpAtomicClauseList>(converter, atomicRead, - loc); - }, - [&](const Fortran::parser::OmpAtomicWrite &atomicWrite) { - mlir::Location loc = converter.genLocation(atomicWrite.source); - Fortran::lower::genOmpAccAtomicWrite< - Fortran::parser::OmpAtomicWrite, - Fortran::parser::OmpAtomicClauseList>(converter, atomicWrite, - loc); + [&](const Fortran::parser::OpenMPSimpleStandaloneConstruct + &simpleStandaloneConstruct) { + genOmpSimpleStandalone(converter, semaCtx, eval, + /*genNested=*/true, + simpleStandaloneConstruct); }, - [&](const Fortran::parser::OmpAtomic &atomicConstruct) { - mlir::Location loc = converter.genLocation(atomicConstruct.source); - Fortran::lower::genOmpAtomic<Fortran::parser::OmpAtomic, - Fortran::parser::OmpAtomicClauseList>( - converter, atomicConstruct, loc); + [&](const Fortran::parser::OpenMPFlushConstruct &flushConstruct) { + genOmpFlush(converter, semaCtx, eval, flushConstruct); }, - [&](const Fortran::parser::OmpAtomicUpdate &atomicUpdate) { - mlir::Location loc = converter.genLocation(atomicUpdate.source); - Fortran::lower::genOmpAccAtomicUpdate< - Fortran::parser::OmpAtomicUpdate, - Fortran::parser::OmpAtomicClauseList>(converter, atomicUpdate, - loc); + [&](const Fortran::parser::OpenMPCancelConstruct &cancelConstruct) { + TODO(converter.getCurrentLocation(), "OpenMPCancelConstruct"); }, - [&](const Fortran::parser::OmpAtomicCapture &atomicCapture) { - mlir::Location loc = converter.genLocation(atomicCapture.source); - Fortran::lower::genOmpAccAtomicCapture< - Fortran::parser::OmpAtomicCapture, - Fortran::parser::OmpAtomicClauseList>(converter, atomicCapture, - loc); + [&](const Fortran::parser::OpenMPCancellationPointConstruct + &cancellationPointConstruct) { + TODO(converter.getCurrentLocation(), "OpenMPCancelConstruct"); }, }, - atomicConstruct.u); -} - -static void -markDeclareTarget(mlir::Operation *op, - Fortran::lower::AbstractConverter &converter, - mlir::omp::DeclareTargetCaptureClause captureClause, - mlir::omp::DeclareTargetDeviceType deviceType) { - // TODO: Add support for program local variables with declare target applied - auto declareTargetOp = llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(op); - if (!declareTargetOp) - fir::emitFatalError( - converter.getCurrentLocation(), - "Attempt to apply declare target on unsupported operation"); - - // The function or global already has a declare target applied to it, very - // likely through implicit capture (usage in another declare target - // function/subroutine). It should be marked as any if it has been assigned - // both host and nohost, else we skip, as there is no change - if (declareTargetOp.isDeclareTarget()) { - if (declareTargetOp.getDeclareTargetDeviceType() != deviceType) - declareTargetOp.setDeclareTarget(mlir::omp::DeclareTargetDeviceType::any, - captureClause); - return; - } - - declareTargetOp.setDeclareTarget(deviceType, captureClause); -} - -static void genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPDeclareTargetConstruct - &declareTargetConstruct) { - llvm::SmallVector<DeclareTargetCapturePair> symbolAndClause; - mlir::ModuleOp mod = converter.getFirOpBuilder().getModule(); - mlir::omp::DeclareTargetDeviceType deviceType = getDeclareTargetInfo( - converter, semaCtx, eval, declareTargetConstruct, symbolAndClause); - - for (const DeclareTargetCapturePair &symClause : symbolAndClause) { - mlir::Operation *op = mod.lookupSymbol(converter.mangleName( - std::get<const Fortran::semantics::Symbol &>(symClause))); - - // Some symbols are deferred until later in the module, these are handled - // upon finalization of the module for OpenMP inside of Bridge, so we simply - // skip for now. - if (!op) - continue; - - markDeclareTarget( - op, converter, - std::get<mlir::omp::DeclareTargetCaptureClause>(symClause), deviceType); - } + standaloneConstruct.u); } static void genOMP(Fortran::lower::AbstractConverter &converter, @@ -2106,88 +2398,10 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenMPConstruct &ompConstruct) { std::visit( - Fortran::common::visitors{ - [&](const Fortran::parser::OpenMPStandaloneConstruct - &standaloneConstruct) { - genOMP(converter, symTable, semaCtx, eval, standaloneConstruct); - }, - [&](const Fortran::parser::OpenMPSectionsConstruct - §ionsConstruct) { - genOMP(converter, symTable, semaCtx, eval, sectionsConstruct); - }, - [&](const Fortran::parser::OpenMPSectionConstruct §ionConstruct) { - // SECTION constructs are handled as a part of SECTIONS. - llvm_unreachable("Unexpected standalone OMP SECTION"); - }, - [&](const Fortran::parser::OpenMPLoopConstruct &loopConstruct) { - genOMP(converter, symTable, semaCtx, eval, loopConstruct); - }, - [&](const Fortran::parser::OpenMPDeclarativeAllocate - &execAllocConstruct) { - TODO(converter.getCurrentLocation(), "OpenMPDeclarativeAllocate"); - }, - [&](const Fortran::parser::OpenMPExecutableAllocate - &execAllocConstruct) { - TODO(converter.getCurrentLocation(), "OpenMPExecutableAllocate"); - }, - [&](const Fortran::parser::OpenMPAllocatorsConstruct - &allocsConstruct) { - TODO(converter.getCurrentLocation(), "OpenMPAllocatorsConstruct"); - }, - [&](const Fortran::parser::OpenMPBlockConstruct &blockConstruct) { - genOMP(converter, symTable, semaCtx, eval, blockConstruct); - }, - [&](const Fortran::parser::OpenMPAtomicConstruct &atomicConstruct) { - genOMP(converter, symTable, semaCtx, eval, atomicConstruct); - }, - [&](const Fortran::parser::OpenMPCriticalConstruct - &criticalConstruct) { - genOMP(converter, symTable, semaCtx, eval, criticalConstruct); - }, - }, + [&](auto &&s) { return genOMP(converter, symTable, semaCtx, eval, s); }, ompConstruct.u); } -static void -genOMP(Fortran::lower::AbstractConverter &converter, - Fortran::lower::SymMap &symTable, - Fortran::semantics::SemanticsContext &semaCtx, - Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPDeclarativeConstruct &ompDeclConstruct) { - std::visit( - Fortran::common::visitors{ - [&](const Fortran::parser::OpenMPDeclarativeAllocate - &declarativeAllocate) { - TODO(converter.getCurrentLocation(), "OpenMPDeclarativeAllocate"); - }, - [&](const Fortran::parser::OpenMPDeclareReductionConstruct - &declareReductionConstruct) { - TODO(converter.getCurrentLocation(), - "OpenMPDeclareReductionConstruct"); - }, - [&](const Fortran::parser::OpenMPDeclareSimdConstruct - &declareSimdConstruct) { - TODO(converter.getCurrentLocation(), "OpenMPDeclareSimdConstruct"); - }, - [&](const Fortran::parser::OpenMPDeclareTargetConstruct - &declareTargetConstruct) { - genOMP(converter, symTable, semaCtx, eval, declareTargetConstruct); - }, - [&](const Fortran::parser::OpenMPRequiresConstruct - &requiresConstruct) { - // Requires directives are gathered and processed in semantics and - // then combined in the lowering bridge before triggering codegen - // just once. Hence, there is no need to lower each individual - // occurrence here. - }, - [&](const Fortran::parser::OpenMPThreadprivate &threadprivate) { - // The directive is lowered when instantiating the variable to - // support the case of threadprivate variable declared in module. - }, - }, - ompDeclConstruct.u); -} - //===----------------------------------------------------------------------===// // Public functions //===----------------------------------------------------------------------===// @@ -2195,7 +2409,7 @@ genOMP(Fortran::lower::AbstractConverter &converter, mlir::Operation *Fortran::lower::genOpenMPTerminator(fir::FirOpBuilder &builder, mlir::Operation *op, mlir::Location loc) { - if (mlir::isa<mlir::omp::WsLoopOp, mlir::omp::ReductionDeclareOp, + if (mlir::isa<mlir::omp::WsloopOp, mlir::omp::DeclareReductionOp, mlir::omp::AtomicUpdateOp, mlir::omp::SimdLoopOp>(op)) return builder.create<mlir::omp::YieldOp>(loc); else @@ -2332,219 +2546,6 @@ void Fortran::lower::genDeclareTargetIntGlobal( } } -// Generate an OpenMP reduction operation. -// TODO: Currently assumes it is either an integer addition/multiplication -// reduction, or a logical and reduction. Generalize this for various reduction -// operation types. -// TODO: Generate the reduction operation during lowering instead of creating -// and removing operations since this is not a robust approach. Also, removing -// ops in the builder (instead of a rewriter) is probably not the best approach. -void Fortran::lower::genOpenMPReduction( - Fortran::lower::AbstractConverter &converter, - Fortran::semantics::SemanticsContext &semaCtx, - const Fortran::parser::OmpClauseList &clauseList) { - fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - - for (const Fortran::parser::OmpClause &clause : clauseList.v) { - if (const auto &reductionClause = - std::get_if<Fortran::parser::OmpClause::Reduction>(&clause.u)) { - const auto &redOperator{std::get<Fortran::parser::OmpReductionOperator>( - reductionClause->v.t)}; - const auto &objectList{ - std::get<Fortran::parser::OmpObjectList>(reductionClause->v.t)}; - if (const auto *reductionOp = - std::get_if<Fortran::parser::DefinedOperator>(&redOperator.u)) { - const auto &intrinsicOp{ - std::get<Fortran::parser::DefinedOperator::IntrinsicOperator>( - reductionOp->u)}; - - switch (intrinsicOp) { - case Fortran::parser::DefinedOperator::IntrinsicOperator::Add: - case Fortran::parser::DefinedOperator::IntrinsicOperator::Multiply: - case Fortran::parser::DefinedOperator::IntrinsicOperator::AND: - case Fortran::parser::DefinedOperator::IntrinsicOperator::EQV: - case Fortran::parser::DefinedOperator::IntrinsicOperator::OR: - case Fortran::parser::DefinedOperator::IntrinsicOperator::NEQV: - break; - default: - continue; - } - for (const Fortran::parser::OmpObject &ompObject : objectList.v) { - if (const auto *name{ - Fortran::parser::Unwrap<Fortran::parser::Name>(ompObject)}) { - if (const Fortran::semantics::Symbol * symbol{name->symbol}) { - mlir::Value reductionVal = converter.getSymbolAddress(*symbol); - if (auto declOp = reductionVal.getDefiningOp<hlfir::DeclareOp>()) - reductionVal = declOp.getBase(); - mlir::Type reductionType = - reductionVal.getType().cast<fir::ReferenceType>().getEleTy(); - if (!reductionType.isa<fir::LogicalType>()) { - if (!reductionType.isIntOrIndexOrFloat()) - continue; - } - for (mlir::OpOperand &reductionValUse : reductionVal.getUses()) { - if (auto loadOp = mlir::dyn_cast<fir::LoadOp>( - reductionValUse.getOwner())) { - mlir::Value loadVal = loadOp.getRes(); - if (reductionType.isa<fir::LogicalType>()) { - mlir::Operation *reductionOp = findReductionChain(loadVal); - fir::ConvertOp convertOp = - getConvertFromReductionOp(reductionOp, loadVal); - updateReduction(reductionOp, firOpBuilder, loadVal, - reductionVal, &convertOp); - removeStoreOp(reductionOp, reductionVal); - } else if (mlir::Operation *reductionOp = - findReductionChain(loadVal, &reductionVal)) { - updateReduction(reductionOp, firOpBuilder, loadVal, - reductionVal); - } - } - } - } - } - } - } else if (const auto *reductionIntrinsic = - std::get_if<Fortran::parser::ProcedureDesignator>( - &redOperator.u)) { - if (!ReductionProcessor::supportedIntrinsicProcReduction( - *reductionIntrinsic)) - continue; - ReductionProcessor::ReductionIdentifier redId = - ReductionProcessor::getReductionType(*reductionIntrinsic); - for (const Fortran::parser::OmpObject &ompObject : objectList.v) { - if (const auto *name{ - Fortran::parser::Unwrap<Fortran::parser::Name>(ompObject)}) { - if (const Fortran::semantics::Symbol * symbol{name->symbol}) { - mlir::Value reductionVal = converter.getSymbolAddress(*symbol); - if (auto declOp = reductionVal.getDefiningOp<hlfir::DeclareOp>()) - reductionVal = declOp.getBase(); - for (const mlir::OpOperand &reductionValUse : - reductionVal.getUses()) { - if (auto loadOp = mlir::dyn_cast<fir::LoadOp>( - reductionValUse.getOwner())) { - mlir::Value loadVal = loadOp.getRes(); - // Max is lowered as a compare -> select. - // Match the pattern here. - mlir::Operation *reductionOp = - findReductionChain(loadVal, &reductionVal); - if (reductionOp == nullptr) - continue; - - if (redId == ReductionProcessor::ReductionIdentifier::MAX || - redId == ReductionProcessor::ReductionIdentifier::MIN) { - assert(mlir::isa<mlir::arith::SelectOp>(reductionOp) && - "Selection Op not found in reduction intrinsic"); - mlir::Operation *compareOp = - getCompareFromReductionOp(reductionOp, loadVal); - updateReduction(compareOp, firOpBuilder, loadVal, - reductionVal); - } - if (redId == ReductionProcessor::ReductionIdentifier::IOR || - redId == ReductionProcessor::ReductionIdentifier::IEOR || - redId == ReductionProcessor::ReductionIdentifier::IAND) { - updateReduction(reductionOp, firOpBuilder, loadVal, - reductionVal); - } - } - } - } - } - } - } - } - } -} - -mlir::Operation *Fortran::lower::findReductionChain(mlir::Value loadVal, - mlir::Value *reductionVal) { - for (mlir::OpOperand &loadOperand : loadVal.getUses()) { - if (mlir::Operation *reductionOp = loadOperand.getOwner()) { - if (auto convertOp = mlir::dyn_cast<fir::ConvertOp>(reductionOp)) { - for (mlir::OpOperand &convertOperand : convertOp.getRes().getUses()) { - if (mlir::Operation *reductionOp = convertOperand.getOwner()) - return reductionOp; - } - } - for (mlir::OpOperand &reductionOperand : reductionOp->getUses()) { - if (auto store = - mlir::dyn_cast<fir::StoreOp>(reductionOperand.getOwner())) { - if (store.getMemref() == *reductionVal) { - store.erase(); - return reductionOp; - } - } - if (auto assign = - mlir::dyn_cast<hlfir::AssignOp>(reductionOperand.getOwner())) { - if (assign.getLhs() == *reductionVal) { - assign.erase(); - return reductionOp; - } - } - } - } - } - return nullptr; -} - -// for a logical operator 'op' reduction X = X op Y -// This function returns the operation responsible for converting Y from -// fir.logical<4> to i1 -fir::ConvertOp -Fortran::lower::getConvertFromReductionOp(mlir::Operation *reductionOp, - mlir::Value loadVal) { - for (mlir::Value reductionOperand : reductionOp->getOperands()) { - if (auto convertOp = - mlir::dyn_cast<fir::ConvertOp>(reductionOperand.getDefiningOp())) { - if (convertOp.getOperand() == loadVal) - continue; - return convertOp; - } - } - return nullptr; -} - -void Fortran::lower::updateReduction(mlir::Operation *op, - fir::FirOpBuilder &firOpBuilder, - mlir::Value loadVal, - mlir::Value reductionVal, - fir::ConvertOp *convertOp) { - mlir::OpBuilder::InsertPoint insertPtDel = firOpBuilder.saveInsertionPoint(); - firOpBuilder.setInsertionPoint(op); - - mlir::Value reductionOp; - if (convertOp) - reductionOp = convertOp->getOperand(); - else if (op->getOperand(0) == loadVal) - reductionOp = op->getOperand(1); - else - reductionOp = op->getOperand(0); - - firOpBuilder.create<mlir::omp::ReductionOp>(op->getLoc(), reductionOp, - reductionVal); - firOpBuilder.restoreInsertionPoint(insertPtDel); -} - -void Fortran::lower::removeStoreOp(mlir::Operation *reductionOp, - mlir::Value symVal) { - for (mlir::Operation *reductionOpUse : reductionOp->getUsers()) { - if (auto convertReduction = - mlir::dyn_cast<fir::ConvertOp>(reductionOpUse)) { - for (mlir::Operation *convertReductionUse : - convertReduction.getRes().getUsers()) { - if (auto storeOp = mlir::dyn_cast<fir::StoreOp>(convertReductionUse)) { - if (storeOp.getMemref() == symVal) - storeOp.erase(); - } - if (auto assignOp = - mlir::dyn_cast<hlfir::AssignOp>(convertReductionUse)) { - if (assignOp.getLhs() == symVal) - assignOp.erase(); - } - } - } - } -} - bool Fortran::lower::isOpenMPTargetConstruct( const Fortran::parser::OpenMPConstruct &omp) { llvm::omp::Directive dir = llvm::omp::Directive::OMPD_unknown; diff --git a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp index a8b98f3f567249a249ae8e0f6383392319d76745..0d05ca5aee658bd2b6d2f6250a97bf0e4a3745ea 100644 --- a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp @@ -13,19 +13,27 @@ #include "ReductionProcessor.h" #include "flang/Lower/AbstractConverter.h" +#include "flang/Optimizer/Builder/HLFIRTools.h" #include "flang/Optimizer/Builder/Todo.h" +#include "flang/Optimizer/Dialect/FIRType.h" #include "flang/Optimizer/HLFIR/HLFIROps.h" #include "flang/Parser/tools.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" +#include "llvm/Support/CommandLine.h" + +static llvm::cl::opt<bool> forceByrefReduction( + "force-byref-reduction", + llvm::cl::desc("Pass all reduction arguments by reference"), + llvm::cl::Hidden); namespace Fortran { namespace lower { namespace omp { ReductionProcessor::ReductionIdentifier ReductionProcessor::getReductionType( - const Fortran::parser::ProcedureDesignator &pd) { + const omp::clause::ProcedureDesignator &pd) { auto redType = llvm::StringSwitch<std::optional<ReductionIdentifier>>( - ReductionProcessor::getRealName(pd).ToString()) + getRealName(pd.v.id()).ToString()) .Case("max", ReductionIdentifier::MAX) .Case("min", ReductionIdentifier::MIN) .Case("iand", ReductionIdentifier::IAND) @@ -37,21 +45,21 @@ ReductionProcessor::ReductionIdentifier ReductionProcessor::getReductionType( } ReductionProcessor::ReductionIdentifier ReductionProcessor::getReductionType( - Fortran::parser::DefinedOperator::IntrinsicOperator intrinsicOp) { + omp::clause::DefinedOperator::IntrinsicOperator intrinsicOp) { switch (intrinsicOp) { - case Fortran::parser::DefinedOperator::IntrinsicOperator::Add: + case omp::clause::DefinedOperator::IntrinsicOperator::Add: return ReductionIdentifier::ADD; - case Fortran::parser::DefinedOperator::IntrinsicOperator::Subtract: + case omp::clause::DefinedOperator::IntrinsicOperator::Subtract: return ReductionIdentifier::SUBTRACT; - case Fortran::parser::DefinedOperator::IntrinsicOperator::Multiply: + case omp::clause::DefinedOperator::IntrinsicOperator::Multiply: return ReductionIdentifier::MULTIPLY; - case Fortran::parser::DefinedOperator::IntrinsicOperator::AND: + case omp::clause::DefinedOperator::IntrinsicOperator::AND: return ReductionIdentifier::AND; - case Fortran::parser::DefinedOperator::IntrinsicOperator::EQV: + case omp::clause::DefinedOperator::IntrinsicOperator::EQV: return ReductionIdentifier::EQV; - case Fortran::parser::DefinedOperator::IntrinsicOperator::OR: + case omp::clause::DefinedOperator::IntrinsicOperator::OR: return ReductionIdentifier::OR; - case Fortran::parser::DefinedOperator::IntrinsicOperator::NEQV: + case omp::clause::DefinedOperator::IntrinsicOperator::NEQV: return ReductionIdentifier::NEQV; default: llvm_unreachable("unexpected intrinsic operator in reduction"); @@ -59,13 +67,11 @@ ReductionProcessor::ReductionIdentifier ReductionProcessor::getReductionType( } bool ReductionProcessor::supportedIntrinsicProcReduction( - const Fortran::parser::ProcedureDesignator &pd) { - const auto *name{Fortran::parser::Unwrap<Fortran::parser::Name>(pd)}; - assert(name && "Invalid Reduction Intrinsic."); - if (!name->symbol->GetUltimate().attrs().test( - Fortran::semantics::Attr::INTRINSIC)) + const omp::clause::ProcedureDesignator &pd) { + Fortran::semantics::Symbol *sym = pd.v.id(); + if (!sym->GetUltimate().attrs().test(Fortran::semantics::Attr::INTRINSIC)) return false; - auto redType = llvm::StringSwitch<bool>(getRealName(name).ToString()) + auto redType = llvm::StringSwitch<bool>(getRealName(sym).ToString()) .Case("max", true) .Case("min", true) .Case("iand", true) @@ -75,49 +81,57 @@ bool ReductionProcessor::supportedIntrinsicProcReduction( return redType; } -std::string ReductionProcessor::getReductionName(llvm::StringRef name, - mlir::Type ty) { - return (llvm::Twine(name) + - (ty.isIntOrIndex() ? llvm::Twine("_i_") : llvm::Twine("_f_")) + - llvm::Twine(ty.getIntOrFloatBitWidth())) - .str(); +std::string +ReductionProcessor::getReductionName(llvm::StringRef name, + const fir::KindMapping &kindMap, + mlir::Type ty, bool isByRef) { + ty = fir::unwrapRefType(ty); + + // extra string to distinguish reduction functions for variables passed by + // reference + llvm::StringRef byrefAddition{""}; + if (isByRef) + byrefAddition = "_byref"; + + return fir::getTypeAsString(ty, kindMap, (name + byrefAddition).str()); } std::string ReductionProcessor::getReductionName( - Fortran::parser::DefinedOperator::IntrinsicOperator intrinsicOp, - mlir::Type ty) { + omp::clause::DefinedOperator::IntrinsicOperator intrinsicOp, + const fir::KindMapping &kindMap, mlir::Type ty, bool isByRef) { std::string reductionName; switch (intrinsicOp) { - case Fortran::parser::DefinedOperator::IntrinsicOperator::Add: + case omp::clause::DefinedOperator::IntrinsicOperator::Add: reductionName = "add_reduction"; break; - case Fortran::parser::DefinedOperator::IntrinsicOperator::Multiply: + case omp::clause::DefinedOperator::IntrinsicOperator::Multiply: reductionName = "multiply_reduction"; break; - case Fortran::parser::DefinedOperator::IntrinsicOperator::AND: + case omp::clause::DefinedOperator::IntrinsicOperator::AND: return "and_reduction"; - case Fortran::parser::DefinedOperator::IntrinsicOperator::EQV: + case omp::clause::DefinedOperator::IntrinsicOperator::EQV: return "eqv_reduction"; - case Fortran::parser::DefinedOperator::IntrinsicOperator::OR: + case omp::clause::DefinedOperator::IntrinsicOperator::OR: return "or_reduction"; - case Fortran::parser::DefinedOperator::IntrinsicOperator::NEQV: + case omp::clause::DefinedOperator::IntrinsicOperator::NEQV: return "neqv_reduction"; default: reductionName = "other_reduction"; break; } - return getReductionName(reductionName, ty); + return getReductionName(reductionName, kindMap, ty, isByRef); } mlir::Value ReductionProcessor::getReductionInitValue(mlir::Location loc, mlir::Type type, ReductionIdentifier redId, fir::FirOpBuilder &builder) { - assert((fir::isa_integer(type) || fir::isa_real(type) || - type.isa<fir::LogicalType>()) && - "only integer, logical and real types are currently supported"); + type = fir::unwrapRefType(type); + if (!fir::isa_integer(type) && !fir::isa_real(type) && + !mlir::isa<fir::LogicalType>(type)) + TODO(loc, "Reduction of some types is not supported"); switch (redId) { case ReductionIdentifier::MAX: { if (auto ty = type.dyn_cast<mlir::FloatType>()) { @@ -188,6 +202,7 @@ mlir::Value ReductionProcessor::createScalarCombiner( fir::FirOpBuilder &builder, mlir::Location loc, ReductionIdentifier redId, mlir::Type type, mlir::Value op1, mlir::Value op2) { mlir::Value reductionOp; + type = fir::unwrapRefType(type); switch (redId) { case ReductionIdentifier::MAX: reductionOp = @@ -266,25 +281,175 @@ mlir::Value ReductionProcessor::createScalarCombiner( return reductionOp; } -mlir::omp::ReductionDeclareOp ReductionProcessor::createReductionDecl( +/// Create reduction combiner region for reduction variables which are boxed +/// arrays +static void genBoxCombiner(fir::FirOpBuilder &builder, mlir::Location loc, + ReductionProcessor::ReductionIdentifier redId, + fir::BaseBoxType boxTy, mlir::Value lhs, + mlir::Value rhs) { + fir::SequenceType seqTy = + mlir::dyn_cast_or_null<fir::SequenceType>(boxTy.getEleTy()); + // TODO: support allocatable arrays: !fir.box<!fir.heap<!fir.array<...>>> + if (!seqTy || seqTy.hasUnknownShape()) + TODO(loc, "Unsupported boxed type in OpenMP reduction"); + + // load fir.ref<fir.box<...>> + mlir::Value lhsAddr = lhs; + lhs = builder.create<fir::LoadOp>(loc, lhs); + rhs = builder.create<fir::LoadOp>(loc, rhs); + + const unsigned rank = seqTy.getDimension(); + llvm::SmallVector<mlir::Value> extents; + extents.reserve(rank); + llvm::SmallVector<mlir::Value> lbAndExtents; + lbAndExtents.reserve(rank * 2); + + // Get box lowerbounds and extents: + mlir::Type idxTy = builder.getIndexType(); + for (unsigned i = 0; i < rank; ++i) { + // TODO: ideally we want to hoist box reads out of the critical section. + // We could do this by having box dimensions in block arguments like + // OpenACC does + mlir::Value dim = builder.createIntegerConstant(loc, idxTy, i); + auto dimInfo = + builder.create<fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, lhs, dim); + extents.push_back(dimInfo.getExtent()); + lbAndExtents.push_back(dimInfo.getLowerBound()); + lbAndExtents.push_back(dimInfo.getExtent()); + } + + auto shapeShiftTy = fir::ShapeShiftType::get(builder.getContext(), rank); + auto shapeShift = + builder.create<fir::ShapeShiftOp>(loc, shapeShiftTy, lbAndExtents); + + // Iterate over array elements, applying the equivalent scalar reduction: + + // A hlfir::elemental here gets inlined with a temporary so create the + // loop nest directly. + // This function already controls all of the code in this region so we + // know this won't miss any opportuinties for clever elemental inlining + hlfir::LoopNest nest = + hlfir::genLoopNest(loc, builder, extents, /*isUnordered=*/true); + builder.setInsertionPointToStart(nest.innerLoop.getBody()); + mlir::Type refTy = fir::ReferenceType::get(seqTy.getEleTy()); + auto lhsEleAddr = builder.create<fir::ArrayCoorOp>( + loc, refTy, lhs, shapeShift, /*slice=*/mlir::Value{}, + nest.oneBasedIndices, /*typeparms=*/mlir::ValueRange{}); + auto rhsEleAddr = builder.create<fir::ArrayCoorOp>( + loc, refTy, rhs, shapeShift, /*slice=*/mlir::Value{}, + nest.oneBasedIndices, /*typeparms=*/mlir::ValueRange{}); + auto lhsEle = builder.create<fir::LoadOp>(loc, lhsEleAddr); + auto rhsEle = builder.create<fir::LoadOp>(loc, rhsEleAddr); + mlir::Value scalarReduction = ReductionProcessor::createScalarCombiner( + builder, loc, redId, refTy, lhsEle, rhsEle); + builder.create<fir::StoreOp>(loc, scalarReduction, lhsEleAddr); + + builder.setInsertionPointAfter(nest.outerLoop); + builder.create<mlir::omp::YieldOp>(loc, lhsAddr); +} + +// generate combiner region for reduction operations +static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc, + ReductionProcessor::ReductionIdentifier redId, + mlir::Type ty, mlir::Value lhs, mlir::Value rhs, + bool isByRef) { + ty = fir::unwrapRefType(ty); + + if (fir::isa_trivial(ty)) { + mlir::Value lhsLoaded = builder.loadIfRef(loc, lhs); + mlir::Value rhsLoaded = builder.loadIfRef(loc, rhs); + + mlir::Value result = ReductionProcessor::createScalarCombiner( + builder, loc, redId, ty, lhsLoaded, rhsLoaded); + if (isByRef) { + builder.create<fir::StoreOp>(loc, result, lhs); + builder.create<mlir::omp::YieldOp>(loc, lhs); + } else { + builder.create<mlir::omp::YieldOp>(loc, result); + } + return; + } + // all arrays should have been boxed + if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(ty)) { + genBoxCombiner(builder, loc, redId, boxTy, lhs, rhs); + return; + } + + TODO(loc, "OpenMP genCombiner for unsupported reduction variable type"); +} + +static mlir::Value +createReductionInitRegion(fir::FirOpBuilder &builder, mlir::Location loc, + const ReductionProcessor::ReductionIdentifier redId, + mlir::Type type, bool isByRef) { + mlir::Type ty = fir::unwrapRefType(type); + mlir::Value initValue = ReductionProcessor::getReductionInitValue( + loc, fir::unwrapSeqOrBoxedSeqType(ty), redId, builder); + + if (fir::isa_trivial(ty)) { + if (isByRef) { + mlir::Value alloca = builder.create<fir::AllocaOp>(loc, ty); + builder.createStoreWithConvert(loc, initValue, alloca); + return alloca; + } + // by val + return initValue; + } + + // all arrays are boxed + if (auto boxTy = mlir::dyn_cast_or_null<fir::BaseBoxType>(ty)) { + assert(isByRef && "passing arrays by value is unsupported"); + // TODO: support allocatable arrays: !fir.box<!fir.heap<!fir.array<...>>> + mlir::Type innerTy = fir::extractSequenceType(boxTy); + if (!mlir::isa<fir::SequenceType>(innerTy)) + TODO(loc, "Unsupported boxed type for reduction"); + // Create the private copy from the initial fir.box: + hlfir::Entity source = hlfir::Entity{builder.getBlock()->getArgument(0)}; + + // TODO: if the whole reduction is nested inside of a loop, this alloca + // could lead to a stack overflow (the memory is only freed at the end of + // the stack frame). The reduction declare operation needs a deallocation + // region to undo the init region. + hlfir::Entity temp = createStackTempFromMold(loc, builder, source); + + // Put the temporary inside of a box: + hlfir::Entity box = hlfir::genVariableBox(loc, builder, temp); + builder.create<hlfir::AssignOp>(loc, initValue, box); + mlir::Value boxAlloca = builder.create<fir::AllocaOp>(loc, ty); + builder.create<fir::StoreOp>(loc, box, boxAlloca); + return boxAlloca; + } + + TODO(loc, "createReductionInitRegion for unsupported type"); +} + +mlir::omp::DeclareReductionOp ReductionProcessor::createDeclareReduction( fir::FirOpBuilder &builder, llvm::StringRef reductionOpName, - const ReductionIdentifier redId, mlir::Type type, mlir::Location loc) { + const ReductionIdentifier redId, mlir::Type type, mlir::Location loc, + bool isByRef) { mlir::OpBuilder::InsertionGuard guard(builder); mlir::ModuleOp module = builder.getModule(); + assert(!reductionOpName.empty()); + auto decl = - module.lookupSymbol<mlir::omp::ReductionDeclareOp>(reductionOpName); + module.lookupSymbol<mlir::omp::DeclareReductionOp>(reductionOpName); if (decl) return decl; mlir::OpBuilder modBuilder(module.getBodyRegion()); + mlir::Type valTy = fir::unwrapRefType(type); + if (!isByRef) + type = valTy; - decl = modBuilder.create<mlir::omp::ReductionDeclareOp>(loc, reductionOpName, + decl = modBuilder.create<mlir::omp::DeclareReductionOp>(loc, reductionOpName, type); builder.createBlock(&decl.getInitializerRegion(), decl.getInitializerRegion().end(), {type}, {loc}); builder.setInsertionPointToEnd(&decl.getInitializerRegion().back()); - mlir::Value init = getReductionInitValue(loc, type, redId, builder); + + mlir::Value init = + createReductionInitRegion(builder, loc, redId, type, isByRef); builder.create<mlir::omp::YieldOp>(loc, init); builder.createBlock(&decl.getReductionRegion(), @@ -294,31 +459,98 @@ mlir::omp::ReductionDeclareOp ReductionProcessor::createReductionDecl( builder.setInsertionPointToEnd(&decl.getReductionRegion().back()); mlir::Value op1 = decl.getReductionRegion().front().getArgument(0); mlir::Value op2 = decl.getReductionRegion().front().getArgument(1); - - mlir::Value reductionOp = - createScalarCombiner(builder, loc, redId, type, op1, op2); - builder.create<mlir::omp::YieldOp>(loc, reductionOp); + genCombiner(builder, loc, redId, type, op1, op2, isByRef); return decl; } -void ReductionProcessor::addReductionDecl( +// TODO: By-ref vs by-val reductions are currently toggled for the whole +// operation (possibly effecting multiple reduction variables). +// This could cause a problem with openmp target reductions because +// by-ref trivial types may not be supported. +bool ReductionProcessor::doReductionByRef( + const llvm::SmallVectorImpl<mlir::Value> &reductionVars) { + if (reductionVars.empty()) + return false; + if (forceByrefReduction) + return true; + + for (mlir::Value reductionVar : reductionVars) { + if (auto declare = + mlir::dyn_cast<hlfir::DeclareOp>(reductionVar.getDefiningOp())) + reductionVar = declare.getMemref(); + + if (!fir::isa_trivial(fir::unwrapRefType(reductionVar.getType()))) + return true; + } + return false; +} + +void ReductionProcessor::addDeclareReduction( mlir::Location currentLocation, Fortran::lower::AbstractConverter &converter, - const Fortran::parser::OmpReductionClause &reduction, + const omp::clause::Reduction &reduction, llvm::SmallVectorImpl<mlir::Value> &reductionVars, llvm::SmallVectorImpl<mlir::Attribute> &reductionDeclSymbols, llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *reductionSymbols) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); - mlir::omp::ReductionDeclareOp decl; - const auto &redOperator{ - std::get<Fortran::parser::OmpReductionOperator>(reduction.t)}; - const auto &objectList{std::get<Fortran::parser::OmpObjectList>(reduction.t)}; + mlir::omp::DeclareReductionOp decl; + const auto &redOperatorList{ + std::get<omp::clause::Reduction::ReductionIdentifiers>(reduction.t)}; + assert(redOperatorList.size() == 1 && "Expecting single operator"); + const auto &redOperator = redOperatorList.front(); + const auto &objectList{std::get<omp::ObjectList>(reduction.t)}; + + if (!std::holds_alternative<omp::clause::DefinedOperator>(redOperator.u)) { + if (const auto *reductionIntrinsic = + std::get_if<omp::clause::ProcedureDesignator>(&redOperator.u)) { + if (!ReductionProcessor::supportedIntrinsicProcReduction( + *reductionIntrinsic)) { + return; + } + } else { + return; + } + } + + // initial pass to collect all reduction vars so we can figure out if this + // should happen byref + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + for (const Object &object : objectList) { + const Fortran::semantics::Symbol *symbol = object.id(); + if (reductionSymbols) + reductionSymbols->push_back(symbol); + mlir::Value symVal = converter.getSymbolAddress(*symbol); + auto redType = mlir::cast<fir::ReferenceType>(symVal.getType()); + + // all arrays must be boxed so that we have convenient access to all the + // information needed to iterate over the array + if (mlir::isa<fir::SequenceType>(redType.getEleTy())) { + hlfir::Entity entity{symVal}; + entity = genVariableBox(currentLocation, builder, entity); + mlir::Value box = entity.getBase(); + + // 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<fir::AllocaOp>(currentLocation, box.getType()); + builder.create<fir::StoreOp>(currentLocation, box, alloca); + + symVal = alloca; + redType = mlir::cast<fir::ReferenceType>(symVal.getType()); + } else if (auto declOp = symVal.getDefiningOp<hlfir::DeclareOp>()) { + symVal = declOp.getBase(); + } + + reductionVars.push_back(symVal); + } + const bool isByRef = doReductionByRef(reductionVars); + if (const auto &redDefinedOp = - std::get_if<Fortran::parser::DefinedOperator>(&redOperator.u)) { + std::get_if<omp::clause::DefinedOperator>(&redOperator.u)) { const auto &intrinsicOp{ - std::get<Fortran::parser::DefinedOperator::IntrinsicOperator>( + std::get<omp::clause::DefinedOperator::IntrinsicOperator>( redDefinedOp->u)}; ReductionIdentifier redId = getReductionType(intrinsicOp); switch (redId) { @@ -334,80 +566,59 @@ void ReductionProcessor::addReductionDecl( "Reduction of some intrinsic operators is not supported"); break; } - for (const Fortran::parser::OmpObject &ompObject : objectList.v) { - if (const auto *name{ - Fortran::parser::Unwrap<Fortran::parser::Name>(ompObject)}) { - if (const Fortran::semantics::Symbol * symbol{name->symbol}) { - if (reductionSymbols) - reductionSymbols->push_back(symbol); - mlir::Value symVal = converter.getSymbolAddress(*symbol); - if (auto declOp = symVal.getDefiningOp<hlfir::DeclareOp>()) - symVal = declOp.getBase(); - mlir::Type redType = - symVal.getType().cast<fir::ReferenceType>().getEleTy(); - reductionVars.push_back(symVal); - if (redType.isa<fir::LogicalType>()) - decl = createReductionDecl( - firOpBuilder, - getReductionName(intrinsicOp, firOpBuilder.getI1Type()), redId, - redType, currentLocation); - else if (redType.isIntOrIndexOrFloat()) { - decl = createReductionDecl(firOpBuilder, - getReductionName(intrinsicOp, redType), - redId, redType, currentLocation); - } else { - TODO(currentLocation, "Reduction of some types is not supported"); - } - reductionDeclSymbols.push_back(mlir::SymbolRefAttr::get( - firOpBuilder.getContext(), decl.getSymName())); - } - } + + for (mlir::Value symVal : reductionVars) { + auto redType = mlir::cast<fir::ReferenceType>(symVal.getType()); + const auto &kindMap = firOpBuilder.getKindMap(); + if (redType.getEleTy().isa<fir::LogicalType>()) + decl = createDeclareReduction(firOpBuilder, + getReductionName(intrinsicOp, kindMap, + firOpBuilder.getI1Type(), + isByRef), + redId, redType, currentLocation, isByRef); + else + decl = createDeclareReduction( + firOpBuilder, + getReductionName(intrinsicOp, kindMap, redType, isByRef), redId, + redType, currentLocation, isByRef); + reductionDeclSymbols.push_back(mlir::SymbolRefAttr::get( + firOpBuilder.getContext(), decl.getSymName())); } } else if (const auto *reductionIntrinsic = - std::get_if<Fortran::parser::ProcedureDesignator>( + std::get_if<omp::clause::ProcedureDesignator>( &redOperator.u)) { if (ReductionProcessor::supportedIntrinsicProcReduction( *reductionIntrinsic)) { ReductionProcessor::ReductionIdentifier redId = ReductionProcessor::getReductionType(*reductionIntrinsic); - for (const Fortran::parser::OmpObject &ompObject : objectList.v) { - if (const auto *name{ - Fortran::parser::Unwrap<Fortran::parser::Name>(ompObject)}) { - if (const Fortran::semantics::Symbol * symbol{name->symbol}) { - if (reductionSymbols) - reductionSymbols->push_back(symbol); - mlir::Value symVal = converter.getSymbolAddress(*symbol); - if (auto declOp = symVal.getDefiningOp<hlfir::DeclareOp>()) - symVal = declOp.getBase(); - mlir::Type redType = - symVal.getType().cast<fir::ReferenceType>().getEleTy(); - reductionVars.push_back(symVal); - assert(redType.isIntOrIndexOrFloat() && - "Unsupported reduction type"); - decl = createReductionDecl( - firOpBuilder, - getReductionName(getRealName(*reductionIntrinsic).ToString(), - redType), - redId, redType, currentLocation); - reductionDeclSymbols.push_back(mlir::SymbolRefAttr::get( - firOpBuilder.getContext(), decl.getSymName())); - } - } + for (const Object &object : objectList) { + const Fortran::semantics::Symbol *symbol = object.id(); + mlir::Value symVal = converter.getSymbolAddress(*symbol); + if (auto declOp = symVal.getDefiningOp<hlfir::DeclareOp>()) + symVal = declOp.getBase(); + auto redType = symVal.getType().cast<fir::ReferenceType>(); + if (!redType.getEleTy().isIntOrIndexOrFloat()) + TODO(currentLocation, "User Defined Reduction on non-trivial type"); + decl = createDeclareReduction( + firOpBuilder, + getReductionName(getRealName(*reductionIntrinsic).ToString(), + firOpBuilder.getKindMap(), redType, isByRef), + redId, redType, currentLocation, isByRef); + reductionDeclSymbols.push_back(mlir::SymbolRefAttr::get( + firOpBuilder.getContext(), decl.getSymName())); } } } } const Fortran::semantics::SourceName -ReductionProcessor::getRealName(const Fortran::parser::Name *name) { - return name->symbol->GetUltimate().name(); +ReductionProcessor::getRealName(const Fortran::semantics::Symbol *symbol) { + return symbol->GetUltimate().name(); } -const Fortran::semantics::SourceName ReductionProcessor::getRealName( - const Fortran::parser::ProcedureDesignator &pd) { - const auto *name{Fortran::parser::Unwrap<Fortran::parser::Name>(pd)}; - assert(name && "Invalid Reduction Intrinsic."); - return getRealName(name); +const Fortran::semantics::SourceName +ReductionProcessor::getRealName(const omp::clause::ProcedureDesignator &pd) { + return getRealName(pd.v.id()); } int ReductionProcessor::getOperationIdentity(ReductionIdentifier redId, diff --git a/flang/lib/Lower/OpenMP/ReductionProcessor.h b/flang/lib/Lower/OpenMP/ReductionProcessor.h index 00770fe81d1ef69ed0ed21bde5d87850ace67e70..ee2732547fc288ad587322defdf9e042375566d7 100644 --- a/flang/lib/Lower/OpenMP/ReductionProcessor.h +++ b/flang/lib/Lower/OpenMP/ReductionProcessor.h @@ -13,7 +13,9 @@ #ifndef FORTRAN_LOWER_REDUCTIONPROCESSOR_H #define FORTRAN_LOWER_REDUCTIONPROCESSOR_H +#include "Clauses.h" #include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Dialect/FIRType.h" #include "flang/Parser/parse-tree.h" #include "flang/Semantics/symbol.h" #include "flang/Semantics/type.h" @@ -22,7 +24,7 @@ namespace mlir { namespace omp { -class ReductionDeclareOp; +class DeclareReductionOp; } // namespace omp } // namespace mlir @@ -57,25 +59,31 @@ public: }; static ReductionIdentifier - getReductionType(const Fortran::parser::ProcedureDesignator &pd); + getReductionType(const omp::clause::ProcedureDesignator &pd); - static ReductionIdentifier getReductionType( - Fortran::parser::DefinedOperator::IntrinsicOperator intrinsicOp); + static ReductionIdentifier + getReductionType(omp::clause::DefinedOperator::IntrinsicOperator intrinsicOp); - static bool supportedIntrinsicProcReduction( - const Fortran::parser::ProcedureDesignator &pd); + static bool + supportedIntrinsicProcReduction(const omp::clause::ProcedureDesignator &pd); static const Fortran::semantics::SourceName - getRealName(const Fortran::parser::Name *name); + getRealName(const Fortran::semantics::Symbol *symbol); static const Fortran::semantics::SourceName - getRealName(const Fortran::parser::ProcedureDesignator &pd); + getRealName(const omp::clause::ProcedureDesignator &pd); + + static bool + doReductionByRef(const llvm::SmallVectorImpl<mlir::Value> &reductionVars); - static std::string getReductionName(llvm::StringRef name, mlir::Type ty); + static std::string getReductionName(llvm::StringRef name, + const fir::KindMapping &kindMap, + mlir::Type ty, bool isByRef); - static std::string getReductionName( - Fortran::parser::DefinedOperator::IntrinsicOperator intrinsicOp, - mlir::Type ty); + static std::string + getReductionName(omp::clause::DefinedOperator::IntrinsicOperator intrinsicOp, + const fir::KindMapping &kindMap, mlir::Type ty, + bool isByRef); /// This function returns the identity value of the operator \p /// reductionOpName. For example: @@ -102,21 +110,23 @@ public: /// Creates an OpenMP reduction declaration and inserts it into the provided /// symbol table. The declaration has a constant initializer with the neutral /// value `initValue`, and the reduction combiner carried over from `reduce`. - /// TODO: Generalize this for non-integer types, add atomic region. - static mlir::omp::ReductionDeclareOp createReductionDecl( - fir::FirOpBuilder &builder, llvm::StringRef reductionOpName, - const ReductionIdentifier redId, mlir::Type type, mlir::Location loc); + /// TODO: add atomic region. + static mlir::omp::DeclareReductionOp + createDeclareReduction(fir::FirOpBuilder &builder, + llvm::StringRef reductionOpName, + const ReductionIdentifier redId, mlir::Type type, + mlir::Location loc, bool isByRef); /// Creates a reduction declaration and associates it with an OpenMP block /// directive. - static void - addReductionDecl(mlir::Location currentLocation, - Fortran::lower::AbstractConverter &converter, - const Fortran::parser::OmpReductionClause &reduction, - llvm::SmallVectorImpl<mlir::Value> &reductionVars, - llvm::SmallVectorImpl<mlir::Attribute> &reductionDeclSymbols, - llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> - *reductionSymbols = nullptr); + static void addDeclareReduction( + mlir::Location currentLocation, + Fortran::lower::AbstractConverter &converter, + const omp::clause::Reduction &reduction, + llvm::SmallVectorImpl<mlir::Value> &reductionVars, + llvm::SmallVectorImpl<mlir::Attribute> &reductionDeclSymbols, + llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> + *reductionSymbols = nullptr); }; template <typename FloatOp, typename IntegerOp> @@ -124,6 +134,7 @@ mlir::Value ReductionProcessor::getReductionOperation(fir::FirOpBuilder &builder, mlir::Type type, mlir::Location loc, mlir::Value op1, mlir::Value op2) { + type = fir::unwrapRefType(type); assert(type.isIntOrIndexOrFloat() && "only integer and float types are currently supported"); if (type.isIntOrIndex()) diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp index 49517f62895dfe7d10fb2dc6e0468def19662665..b9c0660aa4da8e352b83a31d567371fd461652b1 100644 --- a/flang/lib/Lower/OpenMP/Utils.cpp +++ b/flang/lib/Lower/OpenMP/Utils.cpp @@ -11,9 +11,11 @@ //===----------------------------------------------------------------------===// #include "Utils.h" +#include "Clauses.h" #include <flang/Lower/AbstractConverter.h> #include <flang/Lower/ConvertType.h> +#include <flang/Optimizer/Builder/FIRBuilder.h> #include <flang/Parser/parse-tree.h> #include <flang/Parser/tools.h> #include <flang/Semantics/tools.h> @@ -34,19 +36,33 @@ namespace Fortran { namespace lower { namespace omp { -void genObjectList(const Fortran::parser::OmpObjectList &objectList, +void genObjectList(const ObjectList &objects, Fortran::lower::AbstractConverter &converter, llvm::SmallVectorImpl<mlir::Value> &operands) { + for (const Object &object : objects) { + const Fortran::semantics::Symbol *sym = object.id(); + assert(sym && "Expected Symbol"); + if (mlir::Value variable = converter.getSymbolAddress(*sym)) { + operands.push_back(variable); + } else if (const auto *details = + sym->detailsIf<Fortran::semantics::HostAssocDetails>()) { + operands.push_back(converter.getSymbolAddress(details->symbol())); + converter.copySymbolBinding(details->symbol(), *sym); + } + } +} + +void genObjectList2(const Fortran::parser::OmpObjectList &objectList, + Fortran::lower::AbstractConverter &converter, + llvm::SmallVectorImpl<mlir::Value> &operands) { auto addOperands = [&](Fortran::lower::SymbolRef sym) { const mlir::Value variable = converter.getSymbolAddress(sym); if (variable) { operands.push_back(variable); - } else { - if (const auto *details = - sym->detailsIf<Fortran::semantics::HostAssocDetails>()) { - operands.push_back(converter.getSymbolAddress(details->symbol())); - converter.copySymbolBinding(details->symbol(), sym); - } + } else if (const auto *details = + sym->detailsIf<Fortran::semantics::HostAssocDetails>()) { + operands.push_back(converter.getSymbolAddress(details->symbol())); + converter.copySymbolBinding(details->symbol(), sym); } }; for (const Fortran::parser::OmpObject &ompObject : objectList.v) { @@ -55,25 +71,29 @@ void genObjectList(const Fortran::parser::OmpObjectList &objectList, } } +mlir::Type getLoopVarType(Fortran::lower::AbstractConverter &converter, + std::size_t loopVarTypeSize) { + // OpenMP runtime requires 32-bit or 64-bit loop variables. + loopVarTypeSize = loopVarTypeSize * 8; + if (loopVarTypeSize < 32) { + loopVarTypeSize = 32; + } else if (loopVarTypeSize > 64) { + loopVarTypeSize = 64; + mlir::emitWarning(converter.getCurrentLocation(), + "OpenMP loop iteration variable cannot have more than 64 " + "bits size and will be narrowed into 64 bits."); + } + assert((loopVarTypeSize == 32 || loopVarTypeSize == 64) && + "OpenMP loop iteration variable size must be transformed into 32-bit " + "or 64-bit"); + return converter.getFirOpBuilder().getIntegerType(loopVarTypeSize); +} + void gatherFuncAndVarSyms( - const Fortran::parser::OmpObjectList &objList, - mlir::omp::DeclareTargetCaptureClause clause, + const ObjectList &objects, mlir::omp::DeclareTargetCaptureClause clause, llvm::SmallVectorImpl<DeclareTargetCapturePair> &symbolAndClause) { - for (const Fortran::parser::OmpObject &ompObject : objList.v) { - Fortran::common::visit( - Fortran::common::visitors{ - [&](const Fortran::parser::Designator &designator) { - if (const Fortran::parser::Name *name = - Fortran::semantics::getDesignatorNameIfDataRef( - designator)) { - symbolAndClause.emplace_back(clause, *name->symbol); - } - }, - [&](const Fortran::parser::Name &name) { - symbolAndClause.emplace_back(clause, *name.symbol); - }}, - ompObject.u); - } + for (const Object &object : objects) + symbolAndClause.emplace_back(clause, *object.id()); } Fortran::semantics::Symbol * diff --git a/flang/lib/Lower/OpenMP/Utils.h b/flang/lib/Lower/OpenMP/Utils.h index 76a15e8bcaab9bf03840bc5b7ae54bb8c236b7fe..4074bf73987d5b7e15fa016f5e08b8fa365a3843 100644 --- a/flang/lib/Lower/OpenMP/Utils.h +++ b/flang/lib/Lower/OpenMP/Utils.h @@ -9,6 +9,7 @@ #ifndef FORTRAN_LOWER_OPENMPUTILS_H #define FORTRAN_LOWER_OPENMPUTILS_H +#include "Clauses.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" #include "mlir/IR/Location.h" #include "mlir/IR/Value.h" @@ -45,23 +46,29 @@ using DeclareTargetCapturePair = mlir::omp::MapInfoOp createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value baseAddr, mlir::Value varPtrPtr, std::string name, - mlir::SmallVector<mlir::Value> bounds, - mlir::SmallVector<mlir::Value> members, uint64_t mapType, + mlir::ArrayRef<mlir::Value> bounds, + mlir::ArrayRef<mlir::Value> members, uint64_t mapType, mlir::omp::VariableCaptureKind mapCaptureType, mlir::Type retTy, bool isVal = false); +mlir::Type getLoopVarType(Fortran::lower::AbstractConverter &converter, + std::size_t loopVarTypeSize); + void gatherFuncAndVarSyms( - const Fortran::parser::OmpObjectList &objList, - mlir::omp::DeclareTargetCaptureClause clause, + const ObjectList &objects, mlir::omp::DeclareTargetCaptureClause clause, llvm::SmallVectorImpl<DeclareTargetCapturePair> &symbolAndClause); Fortran::semantics::Symbol * getOmpObjectSymbol(const Fortran::parser::OmpObject &ompObject); -void genObjectList(const Fortran::parser::OmpObjectList &objectList, +void genObjectList(const ObjectList &objects, Fortran::lower::AbstractConverter &converter, llvm::SmallVectorImpl<mlir::Value> &operands); +void genObjectList2(const Fortran::parser::OmpObjectList &objectList, + Fortran::lower::AbstractConverter &converter, + llvm::SmallVectorImpl<mlir::Value> &operands); + } // namespace omp } // namespace lower } // namespace Fortran diff --git a/flang/lib/Lower/PFTBuilder.cpp b/flang/lib/Lower/PFTBuilder.cpp index 1dacd5cf64cd9913720689646124313ee28af5cf..f196b9c5a0cbcc27550d4c5397912b27e3daa01d 100644 --- a/flang/lib/Lower/PFTBuilder.cpp +++ b/flang/lib/Lower/PFTBuilder.cpp @@ -1594,6 +1594,11 @@ private: if (!s->has<semantics::DerivedTypeDetails>()) depth = std::max(analyze(s) + 1, depth); } + + // Make sure cray pointer is instantiated even if it is not visible. + if (ultimate.test(Fortran::semantics::Symbol::Flag::CrayPointee)) + depth = std::max( + analyze(Fortran::semantics::GetCrayPointer(ultimate)) + 1, depth); adjustSize(depth + 1); bool global = lower::symbolIsGlobal(sym); layeredVarList[depth].emplace_back(sym, global, depth); @@ -2002,6 +2007,10 @@ struct SymbolVisitor { } } } + // - CrayPointer needs to be available whenever a CrayPointee is used. + if (symbol.GetUltimate().test( + Fortran::semantics::Symbol::Flag::CrayPointee)) + visitSymbol(Fortran::semantics::GetCrayPointer(symbol)); } template <typename A> diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp index 12da7412888a3b1935f539e6f8dffb4a08015137..e4362b2f9e6945bdcd9f4b6b55234a531a198d3d 100644 --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -36,26 +36,56 @@ static llvm::cl::opt<std::size_t> "name"), llvm::cl::init(32)); -mlir::func::FuncOp fir::FirOpBuilder::createFunction(mlir::Location loc, - mlir::ModuleOp module, - llvm::StringRef name, - mlir::FunctionType ty) { - return fir::createFuncOp(loc, module, name, ty); +mlir::func::FuncOp +fir::FirOpBuilder::createFunction(mlir::Location loc, mlir::ModuleOp module, + llvm::StringRef name, mlir::FunctionType ty, + mlir::SymbolTable *symbolTable) { + return fir::createFuncOp(loc, module, name, ty, /*attrs*/ {}, symbolTable); } -mlir::func::FuncOp fir::FirOpBuilder::getNamedFunction(mlir::ModuleOp modOp, - llvm::StringRef name) { +mlir::func::FuncOp +fir::FirOpBuilder::getNamedFunction(mlir::ModuleOp modOp, + const mlir::SymbolTable *symbolTable, + llvm::StringRef name) { + if (symbolTable) + if (auto func = symbolTable->lookup<mlir::func::FuncOp>(name)) { +#ifdef EXPENSIVE_CHECKS + assert(func == modOp.lookupSymbol<mlir::func::FuncOp>(name) && + "symbolTable and module out of sync"); +#endif + return func; + } return modOp.lookupSymbol<mlir::func::FuncOp>(name); } mlir::func::FuncOp fir::FirOpBuilder::getNamedFunction(mlir::ModuleOp modOp, + const mlir::SymbolTable *symbolTable, mlir::SymbolRefAttr symbol) { + if (symbolTable) + if (auto func = symbolTable->lookup<mlir::func::FuncOp>( + symbol.getLeafReference())) { +#ifdef EXPENSIVE_CHECKS + assert(func == modOp.lookupSymbol<mlir::func::FuncOp>(symbol) && + "symbolTable and module out of sync"); +#endif + return func; + } return modOp.lookupSymbol<mlir::func::FuncOp>(symbol); } -fir::GlobalOp fir::FirOpBuilder::getNamedGlobal(mlir::ModuleOp modOp, - llvm::StringRef name) { +fir::GlobalOp +fir::FirOpBuilder::getNamedGlobal(mlir::ModuleOp modOp, + const mlir::SymbolTable *symbolTable, + llvm::StringRef name) { + if (symbolTable) + if (auto global = symbolTable->lookup<fir::GlobalOp>(name)) { +#ifdef EXPENSIVE_CHECKS + assert(global == modOp.lookupSymbol<fir::GlobalOp>(name) && + "symbolTable and module out of sync"); +#endif + return global; + } return modOp.lookupSymbol<fir::GlobalOp>(name); } @@ -208,6 +238,8 @@ mlir::Block *fir::FirOpBuilder::getAllocaBlock() { .getParentOfType<mlir::omp::OutlineableOpenMPOpInterface>()) { return ompOutlineableIface.getAllocaBlock(); } + if (mlir::isa<mlir::omp::DeclareReductionOp>(getRegion().getParentOp())) + return &getRegion().front(); if (auto accRecipeIface = getRegion().getParentOfType<mlir::acc::RecipeInterface>()) { return accRecipeIface.getAllocaBlock(getRegion()); @@ -277,10 +309,10 @@ fir::GlobalOp fir::FirOpBuilder::createGlobal( mlir::Location loc, mlir::Type type, llvm::StringRef name, mlir::StringAttr linkage, mlir::Attribute value, bool isConst, bool isTarget, fir::CUDADataAttributeAttr cudaAttr) { + if (auto global = getNamedGlobal(name)) + return global; auto module = getModule(); auto insertPt = saveInsertionPoint(); - if (auto glob = module.lookupSymbol<fir::GlobalOp>(name)) - return glob; setInsertionPoint(module.getBody(), module.getBody()->end()); llvm::SmallVector<mlir::NamedAttribute> attrs; if (cudaAttr) { @@ -292,6 +324,8 @@ fir::GlobalOp fir::FirOpBuilder::createGlobal( auto glob = create<fir::GlobalOp>(loc, name, isConst, isTarget, type, value, linkage, attrs); restoreInsertionPoint(insertPt); + if (symbolTable) + symbolTable->insert(glob); return glob; } @@ -299,10 +333,10 @@ fir::GlobalOp fir::FirOpBuilder::createGlobal( mlir::Location loc, mlir::Type type, llvm::StringRef name, bool isConst, bool isTarget, std::function<void(FirOpBuilder &)> bodyBuilder, mlir::StringAttr linkage, fir::CUDADataAttributeAttr cudaAttr) { + if (auto global = getNamedGlobal(name)) + return global; auto module = getModule(); auto insertPt = saveInsertionPoint(); - if (auto glob = module.lookupSymbol<fir::GlobalOp>(name)) - return glob; setInsertionPoint(module.getBody(), module.getBody()->end()); auto glob = create<fir::GlobalOp>(loc, name, isConst, isTarget, type, mlir::Attribute{}, linkage); @@ -312,6 +346,8 @@ fir::GlobalOp fir::FirOpBuilder::createGlobal( setInsertionPointToStart(&block); bodyBuilder(*this); restoreInsertionPoint(insertPt); + if (symbolTable) + symbolTable->insert(glob); return glob; } diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp index c7a550814e1d588356c9950cba4f5d3bb1299743..db638ceb40700bac4d036f54ba5d08aef297d9e2 100644 --- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp +++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp @@ -1111,6 +1111,35 @@ hlfir::createTempFromMold(mlir::Location loc, fir::FirOpBuilder &builder, return {hlfir::Entity{declareOp.getBase()}, isHeapAlloc}; } +hlfir::Entity hlfir::createStackTempFromMold(mlir::Location loc, + fir::FirOpBuilder &builder, + hlfir::Entity mold) { + llvm::SmallVector<mlir::Value> lenParams; + hlfir::genLengthParameters(loc, builder, mold, lenParams); + llvm::StringRef tmpName{".tmp"}; + mlir::Value alloc; + mlir::Value shape{}; + fir::FortranVariableFlagsAttr declAttrs; + + if (mold.isPolymorphic()) { + // genAllocatableApplyMold does heap allocation + TODO(loc, "createStackTempFromMold for polymorphic type"); + } else if (mold.isArray()) { + mlir::Type sequenceType = + hlfir::getFortranElementOrSequenceType(mold.getType()); + shape = hlfir::genShape(loc, builder, mold); + auto extents = hlfir::getIndexExtents(loc, builder, shape); + alloc = + builder.createTemporary(loc, sequenceType, tmpName, extents, lenParams); + } else { + alloc = builder.createTemporary(loc, mold.getFortranElementType(), tmpName, + /*shape=*/std::nullopt, lenParams); + } + auto declareOp = builder.create<hlfir::DeclareOp>(loc, alloc, tmpName, shape, + lenParams, declAttrs); + return hlfir::Entity{declareOp.getBase()}; +} + hlfir::EntityWithAttributes hlfir::convertCharacterKind(mlir::Location loc, fir::FirOpBuilder &builder, hlfir::Entity scalarChar, int toKind) { diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index ca5ab6fcea342a09eefd1d82854ecbd27448f20f..069ba81cfe96ab9d25226ee9ecd846577ffca2cd 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -177,6 +177,8 @@ static constexpr IntrinsicHandler handlers[]{ /*isElemental=*/false}, {"c_funloc", &I::genCFunLoc, {{{"x", asBox}}}, /*isElemental=*/false}, {"c_loc", &I::genCLoc, {{{"x", asBox}}}, /*isElemental=*/false}, + {"c_ptr_eq", &I::genCPtrCompare<mlir::arith::CmpIPredicate::eq>}, + {"c_ptr_ne", &I::genCPtrCompare<mlir::arith::CmpIPredicate::ne>}, {"ceiling", &I::genCeiling}, {"char", &I::genChar}, {"cmplx", @@ -722,7 +724,7 @@ mlir::Value genLibCall(fir::FirOpBuilder &builder, mlir::Location loc, mlir::func::FuncOp funcOp = builder.getNamedFunction(libFuncName); if (!funcOp) { - funcOp = builder.addNamedFunction(loc, libFuncName, libFuncType); + funcOp = builder.createFunction(loc, libFuncName, libFuncType); // C-interoperability rules apply to these library functions. funcOp->setAttr(fir::getSymbolAttrName(), mlir::StringAttr::get(builder.getContext(), libFuncName)); @@ -922,6 +924,8 @@ mlir::Value genComplexMathOp(fir::FirOpBuilder &builder, mlir::Location loc, constexpr auto FuncTypeReal16Real16 = genFuncType<Ty::Real<16>, Ty::Real<16>>; constexpr auto FuncTypeReal16Real16Real16 = genFuncType<Ty::Real<16>, Ty::Real<16>, Ty::Real<16>>; +constexpr auto FuncTypeReal16Real16Real16Real16 = + genFuncType<Ty::Real<16>, Ty::Real<16>, Ty::Real<16>, Ty::Real<16>>; constexpr auto FuncTypeReal16Integer4Real16 = genFuncType<Ty::Real<16>, Ty::Integer<4>, Ty::Real<16>>; constexpr auto FuncTypeInteger4Real16 = @@ -1143,6 +1147,8 @@ static constexpr MathOperation mathOperations[] = { {"fma", "llvm.fma.f64", genFuncType<Ty::Real<8>, Ty::Real<8>, Ty::Real<8>, Ty::Real<8>>, genMathOp<mlir::math::FmaOp>}, + {"fma", RTNAME_STRING(FmaF128), FuncTypeReal16Real16Real16Real16, + genLibF128Call}, {"gamma", "tgammaf", genFuncType<Ty::Real<4>, Ty::Real<4>>, genLibCall}, {"gamma", "tgamma", genFuncType<Ty::Real<8>, Ty::Real<8>>, genLibCall}, {"gamma", RTNAME_STRING(TgammaF128), FuncTypeReal16Real16, genLibF128Call}, @@ -1888,8 +1894,8 @@ mlir::func::FuncOp IntrinsicLibrary::getWrapper(GeneratorType generator, // Create local context to emit code into the newly created function // This new function is not linked to a source file location, only // its calls will be. - auto localBuilder = - std::make_unique<fir::FirOpBuilder>(function, builder.getKindMap()); + auto localBuilder = std::make_unique<fir::FirOpBuilder>( + function, builder.getKindMap(), builder.getMLIRSymbolTable()); localBuilder->setFastMathFlags(builder.getFastMathFlags()); localBuilder->setInsertionPointToStart(&function.front()); // Location of code inside wrapper of the wrapper is independent from @@ -2793,6 +2799,23 @@ IntrinsicLibrary::genCLoc(mlir::Type resultType, return genCLocOrCFunLoc(builder, loc, resultType, args); } +// C_PTR_EQ and C_PTR_NE +template <mlir::arith::CmpIPredicate pred> +fir::ExtendedValue +IntrinsicLibrary::genCPtrCompare(mlir::Type resultType, + llvm::ArrayRef<fir::ExtendedValue> args) { + assert(args.size() == 2); + mlir::Value cPtr1 = fir::getBase(args[0]); + mlir::Value cPtrVal1 = + fir::factory::genCPtrOrCFunptrValue(builder, loc, cPtr1); + mlir::Value cPtr2 = fir::getBase(args[1]); + mlir::Value cPtrVal2 = + fir::factory::genCPtrOrCFunptrValue(builder, loc, cPtr2); + mlir::Value cmp = + builder.create<mlir::arith::CmpIOp>(loc, pred, cPtrVal1, cPtrVal2); + return builder.createConvert(loc, resultType, cmp); +} + // CEILING mlir::Value IntrinsicLibrary::genCeiling(mlir::Type resultType, llvm::ArrayRef<mlir::Value> args) { @@ -3860,7 +3883,7 @@ mlir::Value IntrinsicLibrary::genIeeeClass(mlir::Type resultType, int pos = 3 + highSignificandSize; mlir::Value index = builder.create<mlir::arith::AndIOp>( loc, builder.create<mlir::arith::ShRUIOp>(loc, intVal, signShift), - createIntegerConstant(1 << pos)); + createIntegerConstant(1ULL << pos)); // [e] exponent != 0 mlir::Value exponent = @@ -3872,7 +3895,7 @@ mlir::Value IntrinsicLibrary::genIeeeClass(mlir::Type resultType, loc, builder.create<mlir::arith::CmpIOp>( loc, mlir::arith::CmpIPredicate::ne, exponent, zero), - createIntegerConstant(1 << --pos), zero)); + createIntegerConstant(1ULL << --pos), zero)); // [m] exponent == 1..1 (max exponent) index = builder.create<mlir::arith::OrIOp>( @@ -3881,7 +3904,7 @@ mlir::Value IntrinsicLibrary::genIeeeClass(mlir::Type resultType, loc, builder.create<mlir::arith::CmpIOp>( loc, mlir::arith::CmpIPredicate::eq, exponent, exponentMask), - createIntegerConstant(1 << --pos), zero)); + createIntegerConstant(1ULL << --pos), zero)); // [l] low-order significand != 0 index = builder.create<mlir::arith::OrIOp>( @@ -3893,7 +3916,7 @@ mlir::Value IntrinsicLibrary::genIeeeClass(mlir::Type resultType, builder.create<mlir::arith::AndIOp>(loc, intVal, lowSignificandMask), zero), - createIntegerConstant(1 << --pos), zero)); + createIntegerConstant(1ULL << --pos), zero)); // [h] high-order significand (1 or 2 bits) index = builder.create<mlir::arith::OrIOp>( @@ -5208,6 +5231,8 @@ mlir::Value IntrinsicLibrary::genMod(mlir::Type resultType, // MODULO mlir::Value IntrinsicLibrary::genModulo(mlir::Type resultType, llvm::ArrayRef<mlir::Value> args) { + // TODO: we'd better generate a runtime call here, when runtime error + // checking is needed (to detect 0 divisor) or when precise math is requested. assert(args.size() == 2); // No floored modulo op in LLVM/MLIR yet. TODO: add one to MLIR. // In the meantime, use a simple inlined implementation based on truncated @@ -5233,10 +5258,14 @@ mlir::Value IntrinsicLibrary::genModulo(mlir::Type resultType, return builder.create<mlir::arith::SelectOp>(loc, mustAddP, remPlusP, remainder); } - // Real case + + // F128 arith::RemFOp may be lowered to a runtime call that may be unsupported + // on the target, so generate a call to Fortran Runtime's ModuloReal16. if (resultType == mlir::FloatType::getF128(builder.getContext())) + return builder.createConvert( + loc, resultType, + fir::runtime::genModulo(builder, loc, args[0], args[1])); - TODO(loc, "REAL(KIND=16): in MODULO intrinsic"); auto remainder = builder.create<mlir::arith::RemFOp>(loc, args[0], args[1]); mlir::Value zero = builder.createRealZeroConstant(loc, remainder.getType()); auto remainderIsNotZero = builder.create<mlir::arith::CmpFOp>( diff --git a/flang/lib/Optimizer/Builder/LowLevelIntrinsics.cpp b/flang/lib/Optimizer/Builder/LowLevelIntrinsics.cpp index 1d07b1e724d745b477412843d4f7753e4969de07..bb5f77d5d4d1dec4c1dd7fa82ecdce61d8ba353c 100644 --- a/flang/lib/Optimizer/Builder/LowLevelIntrinsics.cpp +++ b/flang/lib/Optimizer/Builder/LowLevelIntrinsics.cpp @@ -27,8 +27,8 @@ mlir::func::FuncOp fir::factory::getLlvmMemcpy(fir::FirOpBuilder &builder) { builder.getI1Type()}; auto memcpyTy = mlir::FunctionType::get(builder.getContext(), args, std::nullopt); - return builder.addNamedFunction(builder.getUnknownLoc(), - "llvm.memcpy.p0.p0.i64", memcpyTy); + return builder.createFunction(builder.getUnknownLoc(), + "llvm.memcpy.p0.p0.i64", memcpyTy); } mlir::func::FuncOp fir::factory::getLlvmMemmove(fir::FirOpBuilder &builder) { @@ -37,8 +37,8 @@ mlir::func::FuncOp fir::factory::getLlvmMemmove(fir::FirOpBuilder &builder) { builder.getI1Type()}; auto memmoveTy = mlir::FunctionType::get(builder.getContext(), args, std::nullopt); - return builder.addNamedFunction(builder.getUnknownLoc(), - "llvm.memmove.p0.p0.i64", memmoveTy); + return builder.createFunction(builder.getUnknownLoc(), + "llvm.memmove.p0.p0.i64", memmoveTy); } mlir::func::FuncOp fir::factory::getLlvmMemset(fir::FirOpBuilder &builder) { @@ -47,16 +47,15 @@ mlir::func::FuncOp fir::factory::getLlvmMemset(fir::FirOpBuilder &builder) { builder.getI1Type()}; auto memsetTy = mlir::FunctionType::get(builder.getContext(), args, std::nullopt); - return builder.addNamedFunction(builder.getUnknownLoc(), - "llvm.memset.p0.p0.i64", memsetTy); + return builder.createFunction(builder.getUnknownLoc(), + "llvm.memset.p0.p0.i64", memsetTy); } mlir::func::FuncOp fir::factory::getRealloc(fir::FirOpBuilder &builder) { auto ptrTy = builder.getRefType(builder.getIntegerType(8)); llvm::SmallVector<mlir::Type> args = {ptrTy, builder.getI64Type()}; auto reallocTy = mlir::FunctionType::get(builder.getContext(), args, {ptrTy}); - return builder.addNamedFunction(builder.getUnknownLoc(), "realloc", - reallocTy); + return builder.createFunction(builder.getUnknownLoc(), "realloc", reallocTy); } mlir::func::FuncOp @@ -64,8 +63,8 @@ fir::factory::getLlvmGetRounding(fir::FirOpBuilder &builder) { auto int32Ty = builder.getIntegerType(32); auto funcTy = mlir::FunctionType::get(builder.getContext(), std::nullopt, {int32Ty}); - return builder.addNamedFunction(builder.getUnknownLoc(), "llvm.get.rounding", - funcTy); + return builder.createFunction(builder.getUnknownLoc(), "llvm.get.rounding", + funcTy); } mlir::func::FuncOp @@ -73,8 +72,8 @@ fir::factory::getLlvmSetRounding(fir::FirOpBuilder &builder) { auto int32Ty = builder.getIntegerType(32); auto funcTy = mlir::FunctionType::get(builder.getContext(), {int32Ty}, std::nullopt); - return builder.addNamedFunction(builder.getUnknownLoc(), "llvm.set.rounding", - funcTy); + return builder.createFunction(builder.getUnknownLoc(), "llvm.set.rounding", + funcTy); } mlir::func::FuncOp fir::factory::getLlvmStackSave(fir::FirOpBuilder &builder) { @@ -82,8 +81,8 @@ mlir::func::FuncOp fir::factory::getLlvmStackSave(fir::FirOpBuilder &builder) { auto ptrTy = builder.getRefType(builder.getIntegerType(8)); auto funcTy = mlir::FunctionType::get(builder.getContext(), std::nullopt, {ptrTy}); - return builder.addNamedFunction(builder.getUnknownLoc(), "llvm.stacksave.p0", - funcTy); + return builder.createFunction(builder.getUnknownLoc(), "llvm.stacksave.p0", + funcTy); } mlir::func::FuncOp @@ -92,8 +91,8 @@ fir::factory::getLlvmStackRestore(fir::FirOpBuilder &builder) { auto ptrTy = builder.getRefType(builder.getIntegerType(8)); auto funcTy = mlir::FunctionType::get(builder.getContext(), {ptrTy}, std::nullopt); - return builder.addNamedFunction(builder.getUnknownLoc(), - "llvm.stackrestore.p0", funcTy); + return builder.createFunction(builder.getUnknownLoc(), "llvm.stackrestore.p0", + funcTy); } mlir::func::FuncOp @@ -101,24 +100,24 @@ 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); - return builder.addNamedFunction(builder.getUnknownLoc(), - "llvm.init.trampoline", funcTy); + return builder.createFunction(builder.getUnknownLoc(), "llvm.init.trampoline", + funcTy); } mlir::func::FuncOp fir::factory::getLlvmAdjustTrampoline(fir::FirOpBuilder &builder) { auto ptrTy = builder.getRefType(builder.getIntegerType(8)); auto funcTy = mlir::FunctionType::get(builder.getContext(), {ptrTy}, {ptrTy}); - return builder.addNamedFunction(builder.getUnknownLoc(), - "llvm.adjust.trampoline", funcTy); + return builder.createFunction(builder.getUnknownLoc(), + "llvm.adjust.trampoline", funcTy); } mlir::func::FuncOp fir::factory::getFeclearexcept(fir::FirOpBuilder &builder) { auto int32Ty = builder.getIntegerType(32); auto funcTy = mlir::FunctionType::get(builder.getContext(), {int32Ty}, {int32Ty}); - return builder.addNamedFunction(builder.getUnknownLoc(), "feclearexcept", - funcTy); + return builder.createFunction(builder.getUnknownLoc(), "feclearexcept", + funcTy); } mlir::func::FuncOp @@ -126,38 +125,37 @@ fir::factory::getFedisableexcept(fir::FirOpBuilder &builder) { auto int32Ty = builder.getIntegerType(32); auto funcTy = mlir::FunctionType::get(builder.getContext(), {int32Ty}, {int32Ty}); - return builder.addNamedFunction(builder.getUnknownLoc(), "fedisableexcept", - funcTy); + return builder.createFunction(builder.getUnknownLoc(), "fedisableexcept", + funcTy); } mlir::func::FuncOp fir::factory::getFeenableexcept(fir::FirOpBuilder &builder) { auto int32Ty = builder.getIntegerType(32); auto funcTy = mlir::FunctionType::get(builder.getContext(), {int32Ty}, {int32Ty}); - return builder.addNamedFunction(builder.getUnknownLoc(), "feenableexcept", - funcTy); + return builder.createFunction(builder.getUnknownLoc(), "feenableexcept", + funcTy); } mlir::func::FuncOp fir::factory::getFegetexcept(fir::FirOpBuilder &builder) { auto int32Ty = builder.getIntegerType(32); auto funcTy = mlir::FunctionType::get(builder.getContext(), std::nullopt, {int32Ty}); - return builder.addNamedFunction(builder.getUnknownLoc(), "fegetexcept", - funcTy); + return builder.createFunction(builder.getUnknownLoc(), "fegetexcept", funcTy); } mlir::func::FuncOp fir::factory::getFeraiseexcept(fir::FirOpBuilder &builder) { auto int32Ty = builder.getIntegerType(32); auto funcTy = mlir::FunctionType::get(builder.getContext(), {int32Ty}, {int32Ty}); - return builder.addNamedFunction(builder.getUnknownLoc(), "feraiseexcept", - funcTy); + return builder.createFunction(builder.getUnknownLoc(), "feraiseexcept", + funcTy); } mlir::func::FuncOp fir::factory::getFetestexcept(fir::FirOpBuilder &builder) { auto int32Ty = builder.getIntegerType(32); auto funcTy = mlir::FunctionType::get(builder.getContext(), {int32Ty}, {int32Ty}); - return builder.addNamedFunction(builder.getUnknownLoc(), "fetestexcept", - funcTy); + return builder.createFunction(builder.getUnknownLoc(), "fetestexcept", + funcTy); } diff --git a/flang/lib/Optimizer/Builder/PPCIntrinsicCall.cpp b/flang/lib/Optimizer/Builder/PPCIntrinsicCall.cpp index ab0d5079d8afe0f719f7b150747d0065b2a2c986..e588b19dded4f1f218a079a286388661fa4a2fa5 100644 --- a/flang/lib/Optimizer/Builder/PPCIntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/PPCIntrinsicCall.cpp @@ -1084,11 +1084,11 @@ void PPCIntrinsicLibrary::genMtfsf(llvm::ArrayRef<fir::ExtendedValue> args) { if (isImm) { libFuncType = genFuncType<Ty::Void, Ty::Integer<4>, Ty::Integer<4>>( builder.getContext(), builder); - funcOp = builder.addNamedFunction(loc, "llvm.ppc.mtfsfi", libFuncType); + funcOp = builder.createFunction(loc, "llvm.ppc.mtfsfi", libFuncType); } else { libFuncType = genFuncType<Ty::Void, Ty::Integer<4>, Ty::Real<8>>( builder.getContext(), builder); - funcOp = builder.addNamedFunction(loc, "llvm.ppc.mtfsf", libFuncType); + funcOp = builder.createFunction(loc, "llvm.ppc.mtfsf", libFuncType); } builder.create<fir::CallOp>(loc, funcOp, scalarArgs); } @@ -1116,7 +1116,7 @@ PPCIntrinsicLibrary::genVecAbs(mlir::Type resultType, genFuncType<Ty::RealVector<8>, Ty::RealVector<8>>(context, builder); } - funcOp = builder.addNamedFunction(loc, fname, ftype); + funcOp = builder.createFunction(loc, fname, ftype); auto callOp{builder.create<fir::CallOp>(loc, funcOp, argBases[0])}; return callOp.getResult(0); } else if (auto eleTy = vTypeInfo.eleTy.dyn_cast<mlir::IntegerType>()) { @@ -1155,7 +1155,7 @@ PPCIntrinsicLibrary::genVecAbs(mlir::Type resultType, default: llvm_unreachable("invalid integer size"); } - funcOp = builder.addNamedFunction(loc, fname, ftype); + funcOp = builder.createFunction(loc, fname, ftype); mlir::Value args[] = {zeroSubVarg1, varg1}; auto callOp{builder.create<fir::CallOp>(loc, funcOp, args)}; @@ -1339,7 +1339,7 @@ PPCIntrinsicLibrary::genVecAnyCompare(mlir::Type resultType, } assert((!fname.empty() && ftype) && "invalid type"); - mlir::func::FuncOp funcOp{builder.addNamedFunction(loc, fname, ftype)}; + mlir::func::FuncOp funcOp{builder.createFunction(loc, fname, ftype)}; auto callOp{builder.create<fir::CallOp>(loc, funcOp, cmpArgs)}; return callOp.getResult(0); } @@ -1445,7 +1445,7 @@ PPCIntrinsicLibrary::genVecCmp(mlir::Type resultType, std::pair<llvm::StringRef, mlir::FunctionType> funcTyNam{ getVecCmpFuncTypeAndName(vecTyInfo, vop, builder)}; - mlir::func::FuncOp funcOp = builder.addNamedFunction( + mlir::func::FuncOp funcOp = builder.createFunction( loc, std::get<0>(funcTyNam), std::get<1>(funcTyNam)); mlir::Value res{nullptr}; @@ -1572,7 +1572,7 @@ PPCIntrinsicLibrary::genVecConvert(mlir::Type resultType, Ty::Integer<4>>(context, builder)}; const llvm::StringRef fname{(isUnsigned) ? "llvm.ppc.altivec.vcfux" : "llvm.ppc.altivec.vcfsx"}; - auto funcOp{builder.addNamedFunction(loc, fname, ftype)}; + auto funcOp{builder.createFunction(loc, fname, ftype)}; mlir::Value newArgs[] = {argBases[0], convArg}; auto callOp{builder.create<fir::CallOp>(loc, funcOp, newArgs)}; @@ -1627,7 +1627,7 @@ PPCIntrinsicLibrary::genVecConvert(mlir::Type resultType, const llvm::StringRef fname{"llvm.ppc.vsx.xvcvspdp"}; auto ftype{ genFuncType<Ty::RealVector<8>, Ty::RealVector<4>>(context, builder)}; - auto funcOp{builder.addNamedFunction(loc, fname, ftype)}; + auto funcOp{builder.createFunction(loc, fname, ftype)}; auto callOp{builder.create<fir::CallOp>(loc, funcOp, newArgs)}; return callOp.getResult(0); @@ -1635,7 +1635,7 @@ PPCIntrinsicLibrary::genVecConvert(mlir::Type resultType, const llvm::StringRef fname{"llvm.ppc.vsx.xvcvdpsp"}; auto ftype{ genFuncType<Ty::RealVector<4>, Ty::RealVector<8>>(context, builder)}; - auto funcOp{builder.addNamedFunction(loc, fname, ftype)}; + auto funcOp{builder.createFunction(loc, fname, ftype)}; newArgs[0] = builder.create<fir::CallOp>(loc, funcOp, newArgs).getResult(0); auto fvf32Ty{newArgs[0].getType()}; @@ -1963,7 +1963,7 @@ PPCIntrinsicLibrary::genVecLdCallGrp(mlir::Type resultType, auto funcType{ mlir::FunctionType::get(context, {addr.getType()}, {intrinResTy})}; - auto funcOp{builder.addNamedFunction(loc, fname, funcType)}; + auto funcOp{builder.createFunction(loc, fname, funcType)}; auto result{ builder.create<fir::CallOp>(loc, funcOp, parsedArgs).getResult(0)}; @@ -2022,7 +2022,7 @@ PPCIntrinsicLibrary::genVecLvsGrp(mlir::Type resultType, llvm_unreachable("invalid vector operation for generator"); } auto funcType{mlir::FunctionType::get(context, {addr.getType()}, {mlirTy})}; - auto funcOp{builder.addNamedFunction(loc, fname, funcType)}; + auto funcOp{builder.createFunction(loc, fname, funcType)}; auto result{ builder.create<fir::CallOp>(loc, funcOp, parsedArgs).getResult(0)}; @@ -2057,8 +2057,8 @@ PPCIntrinsicLibrary::genVecNmaddMsub(mlir::Type resultType, genFuncType<Ty::RealVector<8>, Ty::RealVector<8>, Ty::RealVector<8>>( context, builder))}}; - auto funcOp{builder.addNamedFunction(loc, std::get<0>(fmaMap[width]), - std::get<1>(fmaMap[width]))}; + auto funcOp{builder.createFunction(loc, std::get<0>(fmaMap[width]), + std::get<1>(fmaMap[width]))}; if (vop == VecOp::Nmadd) { // vec_nmadd(arg1, arg2, arg3) = -fma(arg1, arg2, arg3) auto callOp{builder.create<fir::CallOp>(loc, funcOp, newArgs)}; @@ -2110,7 +2110,7 @@ PPCIntrinsicLibrary::genVecPerm(mlir::Type resultType, builder.create<mlir::LLVM::BitcastOp>(loc, vi32Ty, mArg1).getResult(); } - auto funcOp{builder.addNamedFunction( + auto funcOp{builder.createFunction( loc, "llvm.ppc.altivec.vperm", genFuncType<Ty::IntegerVector<4>, Ty::IntegerVector<4>, Ty::IntegerVector<4>, Ty::IntegerVector<1>>(context, @@ -2307,7 +2307,7 @@ PPCIntrinsicLibrary::genVecShift(mlir::Type resultType, } auto funcTy{genFuncType<Ty::IntegerVector<4>, Ty::IntegerVector<4>, Ty::IntegerVector<4>>(context, builder)}; - mlir::func::FuncOp funcOp{builder.addNamedFunction(loc, funcName, funcTy)}; + mlir::func::FuncOp funcOp{builder.createFunction(loc, funcName, funcTy)}; auto callOp{builder.create<fir::CallOp>(loc, funcOp, mlirVecArgs)}; // If the result vector type is different from the original type, need @@ -2755,7 +2755,7 @@ void PPCIntrinsicLibrary::genMmaIntr(llvm::ArrayRef<fir::ExtendedValue> args) { auto context{builder.getContext()}; mlir::FunctionType intrFuncType{getMmaIrFuncType(context, IntrId)}; mlir::func::FuncOp funcOp{ - builder.addNamedFunction(loc, getMmaIrIntrName(IntrId), intrFuncType)}; + builder.createFunction(loc, getMmaIrIntrName(IntrId), intrFuncType)}; llvm::SmallVector<mlir::Value> intrArgs; // Depending on SubToFunc, change the subroutine call to a function call. @@ -2892,7 +2892,7 @@ void PPCIntrinsicLibrary::genVecStore(llvm::ArrayRef<fir::ExtendedValue> args) { auto funcType{ mlir::FunctionType::get(context, {stTy, addr.getType()}, std::nullopt)}; - mlir::func::FuncOp funcOp = builder.addNamedFunction(loc, fname, funcType); + mlir::func::FuncOp funcOp = builder.createFunction(loc, fname, funcType); llvm::SmallVector<mlir::Value, 4> biArgs; diff --git a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp index 638bfd60a246a644497a5837aac34bf358c39ccc..57c47da0f3f85c46d28f8efb6706d99a221d5126 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Intrinsics.cpp @@ -27,6 +27,24 @@ using namespace Fortran::runtime; +namespace { +/// Placeholder for real*16 version of RandomNumber Intrinsic +struct ForcedRandomNumberReal16 { + static constexpr const char *name = ExpandAndQuoteKey(RTNAME(RandomNumber16)); + static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { + return [](mlir::MLIRContext *ctx) { + auto boxTy = + fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx); + auto strTy = fir::runtime::getModel<const char *>()(ctx); + auto intTy = fir::runtime::getModel<int>()(ctx); + ; + return mlir::FunctionType::get(ctx, {boxTy, strTy, intTy}, + mlir::NoneType::get(ctx)); + }; + } +}; +} // namespace + mlir::Value fir::runtime::genAssociated(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value pointer, mlir::Value target) { @@ -100,8 +118,15 @@ void fir::runtime::genRandomInit(fir::FirOpBuilder &builder, mlir::Location loc, void fir::runtime::genRandomNumber(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value harvest) { - mlir::func::FuncOp func = - fir::runtime::getRuntimeFunc<mkRTKey(RandomNumber)>(loc, builder); + mlir::func::FuncOp func; + auto boxEleTy = fir::dyn_cast_ptrOrBoxEleTy(harvest.getType()); + auto eleTy = fir::unwrapSequenceType(boxEleTy); + if (eleTy.isF128()) { + func = fir::runtime::getRuntimeFunc<ForcedRandomNumberReal16>(loc, builder); + } else { + func = fir::runtime::getRuntimeFunc<mkRTKey(RandomNumber)>(loc, builder); + } + mlir::FunctionType funcTy = func.getFunctionType(); mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc); mlir::Value sourceLine = diff --git a/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp b/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp index b958a30eb6e5b55f82f3db94be7326acc27950bc..4dcbd13cb319f58bfcf75d158de1bfa7632ce7a7 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp @@ -118,6 +118,20 @@ struct ForcedMod16 { } }; +/// Placeholder for real*16 version of Modulo Intrinsic +struct ForcedModulo16 { + static constexpr const char *name = ExpandAndQuoteKey(RTNAME(ModuloReal16)); + static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { + return [](mlir::MLIRContext *ctx) { + auto fltTy = mlir::FloatType::getF128(ctx); + auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); + auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); + return mlir::FunctionType::get(ctx, {fltTy, fltTy, strTy, intTy}, + {fltTy}); + }; + } +}; + /// Placeholder for real*10 version of Nearest Intrinsic struct ForcedNearest10 { static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Nearest10)); @@ -323,6 +337,33 @@ mlir::Value fir::runtime::genMod(fir::FirOpBuilder &builder, mlir::Location loc, return builder.create<fir::CallOp>(loc, func, args).getResult(0); } +/// Generate call to Modulo intrinsic runtime routine. +mlir::Value fir::runtime::genModulo(fir::FirOpBuilder &builder, + mlir::Location loc, mlir::Value a, + mlir::Value p) { + mlir::func::FuncOp func; + mlir::Type fltTy = a.getType(); + + if (fltTy != p.getType()) + fir::emitFatalError(loc, "arguments type mismatch in MOD"); + + // MODULO is lowered into math operations in intrinsics lowering, + // so genModulo() should only be used for F128 data type now. + if (fltTy.isF128()) + func = fir::runtime::getRuntimeFunc<ForcedModulo16>(loc, builder); + else + fir::intrinsicTypeTODO(builder, fltTy, loc, "MODULO"); + + auto funcTy = func.getFunctionType(); + auto sourceFile = fir::factory::locationToFilename(builder, loc); + auto sourceLine = + fir::factory::locationToLineNo(builder, loc, funcTy.getInput(3)); + auto args = fir::runtime::createArguments(builder, loc, funcTy, a, p, + sourceFile, sourceLine); + + return builder.create<fir::CallOp>(loc, func, args).getResult(0); +} + /// Generate call to Nearest intrinsic runtime routine. mlir::Value fir::runtime::genNearest(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value x, diff --git a/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp b/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp index 746c275f37eaca2dfd52c2bdbeebd313792052f3..48173033ecbe20e3d5921998b077af2d0b3ec0f6 100644 --- a/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp +++ b/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp @@ -69,17 +69,32 @@ public: return false; } if (auto recTy = ty.dyn_cast<RecordType>()) { - if (llvm::is_contained(visitedTypes, recTy)) - return false; + auto visited = visitedTypes.find(ty); + if (visited != visitedTypes.end()) + return visited->second; + [[maybe_unused]] auto newIt = visitedTypes.try_emplace(ty, false); + assert(newIt.second && "expected ty to not be in the map"); + bool wasAlreadyVisitingRecordType = needConversionIsVisitingRecordType; + needConversionIsVisitingRecordType = true; bool result = false; - visitedTypes.push_back(recTy); for (auto t : recTy.getTypeList()) { if (needsConversion(t.second)) { result = true; break; } } - visitedTypes.pop_back(); + // Only keep the result cached if the fir.type visited was a "top-level + // type". Nested types with a recursive reference to the "top-level type" + // may incorrectly have been resolved as not needed conversions because it + // had not been determined yet if the "top-level type" needed conversion. + // This is not an issue to determine the "top-level type" need of + // conversion, but the result should not be kept and later used in other + // contexts. + needConversionIsVisitingRecordType = wasAlreadyVisitingRecordType; + if (needConversionIsVisitingRecordType) + visitedTypes.erase(ty); + else + visitedTypes.find(ty)->second = result; return result; } if (auto boxTy = ty.dyn_cast<BaseBoxType>()) @@ -139,10 +154,8 @@ public: ty.getName().str() + boxprocSuffix.str()); if (rec.isFinalized()) return rec; - auto it = convertedTypes.try_emplace(ty, rec); - if (!it.second) { - llvm::errs() << "failed\n" << ty << "\n"; - } + [[maybe_unused]] auto it = convertedTypes.try_emplace(ty, rec); + assert(it.second && "expected ty to not be in the map"); std::vector<RecordType::TypePair> ps = ty.getLenParamList(); std::vector<RecordType::TypePair> cs; for (auto t : ty.getTypeList()) { @@ -171,11 +184,12 @@ public: void setLocation(mlir::Location location) { loc = location; } private: - llvm::SmallVector<mlir::Type> visitedTypes; - // Map to deal with recursive derived types (avoid infinite loops). + // Maps to deal with recursive derived types (avoid infinite loops). // Caching is also beneficial for apps with big types (dozens of // components and or parent types), so the lifetime of the cache // is the whole pass. + llvm::DenseMap<mlir::Type, bool> visitedTypes; + bool needConversionIsVisitingRecordType = false; llvm::DenseMap<mlir::Type, mlir::Type> convertedTypes; mlir::Location loc; }; diff --git a/flang/lib/Optimizer/CodeGen/CMakeLists.txt b/flang/lib/Optimizer/CodeGen/CMakeLists.txt index 175ab9fefda2ae09a6a769ccdfc819d62ed74457..879bc28d017a35ce704025524d7586ef10d5a817 100644 --- a/flang/lib/Optimizer/CodeGen/CMakeLists.txt +++ b/flang/lib/Optimizer/CodeGen/CMakeLists.txt @@ -3,6 +3,7 @@ add_flang_library(FIRCodeGen CGOps.cpp CodeGen.cpp CodeGenOpenMP.cpp + FIROpPatterns.cpp PreCGRewrite.cpp TBAABuilder.cpp Target.cpp diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index f81a08388da72254bf1c2b8b47a9974ebaafd9f6..06ce84f1543a3ff1a63a957b98ff138e467eb75e 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -14,6 +14,8 @@ #include "CGOps.h" #include "flang/Optimizer/CodeGen/CodeGenOpenMP.h" +#include "flang/Optimizer/CodeGen/FIROpPatterns.h" +#include "flang/Optimizer/CodeGen/TypeConverter.h" #include "flang/Optimizer/Dialect/FIRAttr.h" #include "flang/Optimizer/Dialect/FIROps.h" #include "flang/Optimizer/Dialect/FIRType.h" @@ -37,6 +39,7 @@ #include "mlir/Conversion/VectorToLLVM/ConvertVectorToLLVM.h" #include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/DLTI/DLTI.h" +#include "mlir/Dialect/LLVMIR/LLVMAttrs.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/LLVMIR/Transforms/AddComdats.h" #include "mlir/Dialect/OpenACC/OpenACC.h" @@ -49,7 +52,6 @@ #include "mlir/Target/LLVMIR/ModuleTranslation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/TypeSwitch.h" -#include <mlir/Dialect/LLVMIR/LLVMAttrs.h> namespace fir { #define GEN_PASS_DEF_FIRTOLLVMLOWERING @@ -58,42 +60,14 @@ namespace fir { #define DEBUG_TYPE "flang-codegen" -// fir::LLVMTypeConverter for converting to LLVM IR dialect types. -#include "flang/Optimizer/CodeGen/TypeConverter.h" - // TODO: This should really be recovered from the specified target. static constexpr unsigned defaultAlign = 8; -static constexpr unsigned defaultAddressSpace = 0u; /// `fir.box` attribute values as defined for CFI_attribute_t in /// flang/ISO_Fortran_binding.h. static constexpr unsigned kAttrPointer = CFI_attribute_pointer; static constexpr unsigned kAttrAllocatable = CFI_attribute_allocatable; -static inline unsigned -getAllocaAddressSpace(mlir::ConversionPatternRewriter &rewriter) { - mlir::Operation *parentOp = rewriter.getInsertionBlock()->getParentOp(); - assert(parentOp != nullptr && - "expected insertion block to have parent operation"); - if (auto module = parentOp->getParentOfType<mlir::ModuleOp>()) - if (mlir::Attribute addrSpace = - mlir::DataLayout(module).getAllocaMemorySpace()) - return llvm::cast<mlir::IntegerAttr>(addrSpace).getUInt(); - return defaultAddressSpace; -} - -static inline unsigned -getProgramAddressSpace(mlir::ConversionPatternRewriter &rewriter) { - mlir::Operation *parentOp = rewriter.getInsertionBlock()->getParentOp(); - assert(parentOp != nullptr && - "expected insertion block to have parent operation"); - if (auto module = parentOp->getParentOfType<mlir::ModuleOp>()) - if (mlir::Attribute addrSpace = - mlir::DataLayout(module).getProgramMemorySpace()) - return llvm::cast<mlir::IntegerAttr>(addrSpace).getUInt(); - return defaultAddressSpace; -} - static inline mlir::Type getLlvmPtrType(mlir::MLIRContext *context, unsigned addressSpace = 0) { return mlir::LLVM::LLVMPointerType::get(context, addressSpace); @@ -151,326 +125,9 @@ static unsigned getLenParamFieldId(mlir::Type ty) { return getTypeDescFieldId(ty) + 1; } -namespace { -/// FIR conversion pattern template -template <typename FromOp> -class FIROpConversion : public mlir::ConvertOpToLLVMPattern<FromOp> { -public: - explicit FIROpConversion(const fir::LLVMTypeConverter &lowering, - const fir::FIRToLLVMPassOptions &options) - : mlir::ConvertOpToLLVMPattern<FromOp>(lowering), options(options) {} - -protected: - mlir::Type convertType(mlir::Type ty) const { - return lowerTy().convertType(ty); - } - - // Convert FIR type to LLVM without turning fir.box<T> into memory - // reference. - mlir::Type convertObjectType(mlir::Type firType) const { - if (auto boxTy = firType.dyn_cast<fir::BaseBoxType>()) - return lowerTy().convertBoxTypeAsStruct(boxTy); - return lowerTy().convertType(firType); - } - - mlir::LLVM::ConstantOp - genI32Constant(mlir::Location loc, mlir::ConversionPatternRewriter &rewriter, - int value) const { - mlir::Type i32Ty = rewriter.getI32Type(); - mlir::IntegerAttr attr = rewriter.getI32IntegerAttr(value); - return rewriter.create<mlir::LLVM::ConstantOp>(loc, i32Ty, attr); - } - - mlir::LLVM::ConstantOp - genConstantOffset(mlir::Location loc, - mlir::ConversionPatternRewriter &rewriter, - int offset) const { - mlir::Type ity = lowerTy().offsetType(); - mlir::IntegerAttr cattr = rewriter.getI32IntegerAttr(offset); - return rewriter.create<mlir::LLVM::ConstantOp>(loc, ity, cattr); - } - - /// Perform an extension or truncation as needed on an integer value. Lowering - /// to the specific target may involve some sign-extending or truncation of - /// values, particularly to fit them from abstract box types to the - /// appropriate reified structures. - mlir::Value integerCast(mlir::Location loc, - mlir::ConversionPatternRewriter &rewriter, - mlir::Type ty, mlir::Value val) const { - auto valTy = val.getType(); - // If the value was not yet lowered, lower its type so that it can - // be used in getPrimitiveTypeSizeInBits. - if (!valTy.isa<mlir::IntegerType>()) - valTy = convertType(valTy); - auto toSize = mlir::LLVM::getPrimitiveTypeSizeInBits(ty); - auto fromSize = mlir::LLVM::getPrimitiveTypeSizeInBits(valTy); - if (toSize < fromSize) - return rewriter.create<mlir::LLVM::TruncOp>(loc, ty, val); - if (toSize > fromSize) - return rewriter.create<mlir::LLVM::SExtOp>(loc, ty, val); - return val; - } - - struct TypePair { - mlir::Type fir; - mlir::Type llvm; - }; - - TypePair getBoxTypePair(mlir::Type firBoxTy) const { - mlir::Type llvmBoxTy = lowerTy().convertBoxTypeAsStruct( - mlir::cast<fir::BaseBoxType>(firBoxTy)); - return TypePair{firBoxTy, llvmBoxTy}; - } - - /// Construct code sequence to extract the specific value from a `fir.box`. - mlir::Value getValueFromBox(mlir::Location loc, TypePair boxTy, - mlir::Value box, mlir::Type resultTy, - mlir::ConversionPatternRewriter &rewriter, - int boxValue) const { - if (box.getType().isa<mlir::LLVM::LLVMPointerType>()) { - auto pty = ::getLlvmPtrType(resultTy.getContext()); - auto p = rewriter.create<mlir::LLVM::GEPOp>( - loc, pty, boxTy.llvm, box, - llvm::ArrayRef<mlir::LLVM::GEPArg>{0, boxValue}); - auto loadOp = rewriter.create<mlir::LLVM::LoadOp>(loc, resultTy, p); - attachTBAATag(loadOp, boxTy.fir, nullptr, p); - return loadOp; - } - return rewriter.create<mlir::LLVM::ExtractValueOp>(loc, box, boxValue); - } - - /// Method to construct code sequence to get the triple for dimension `dim` - /// from a box. - llvm::SmallVector<mlir::Value, 3> - getDimsFromBox(mlir::Location loc, llvm::ArrayRef<mlir::Type> retTys, - TypePair boxTy, mlir::Value box, mlir::Value dim, - mlir::ConversionPatternRewriter &rewriter) const { - mlir::Value l0 = - loadDimFieldFromBox(loc, boxTy, box, dim, 0, retTys[0], rewriter); - mlir::Value l1 = - loadDimFieldFromBox(loc, boxTy, box, dim, 1, retTys[1], rewriter); - mlir::Value l2 = - loadDimFieldFromBox(loc, boxTy, box, dim, 2, retTys[2], rewriter); - return {l0, l1, l2}; - } - - llvm::SmallVector<mlir::Value, 3> - getDimsFromBox(mlir::Location loc, llvm::ArrayRef<mlir::Type> retTys, - TypePair boxTy, mlir::Value box, int dim, - mlir::ConversionPatternRewriter &rewriter) const { - mlir::Value l0 = - getDimFieldFromBox(loc, boxTy, box, dim, 0, retTys[0], rewriter); - mlir::Value l1 = - getDimFieldFromBox(loc, boxTy, box, dim, 1, retTys[1], rewriter); - mlir::Value l2 = - getDimFieldFromBox(loc, boxTy, box, dim, 2, retTys[2], rewriter); - return {l0, l1, l2}; - } - - mlir::Value - loadDimFieldFromBox(mlir::Location loc, TypePair boxTy, mlir::Value box, - mlir::Value dim, int off, mlir::Type ty, - mlir::ConversionPatternRewriter &rewriter) const { - assert(box.getType().isa<mlir::LLVM::LLVMPointerType>() && - "descriptor inquiry with runtime dim can only be done on descriptor " - "in memory"); - mlir::LLVM::GEPOp p = genGEP(loc, boxTy.llvm, rewriter, box, 0, - static_cast<int>(kDimsPosInBox), dim, off); - auto loadOp = rewriter.create<mlir::LLVM::LoadOp>(loc, ty, p); - attachTBAATag(loadOp, boxTy.fir, nullptr, p); - return loadOp; - } - - mlir::Value - getDimFieldFromBox(mlir::Location loc, TypePair boxTy, mlir::Value box, - int dim, int off, mlir::Type ty, - mlir::ConversionPatternRewriter &rewriter) const { - if (box.getType().isa<mlir::LLVM::LLVMPointerType>()) { - mlir::LLVM::GEPOp p = genGEP(loc, boxTy.llvm, rewriter, box, 0, - static_cast<int>(kDimsPosInBox), dim, off); - auto loadOp = rewriter.create<mlir::LLVM::LoadOp>(loc, ty, p); - attachTBAATag(loadOp, boxTy.fir, nullptr, p); - return loadOp; - } - return rewriter.create<mlir::LLVM::ExtractValueOp>( - loc, box, llvm::ArrayRef<std::int64_t>{kDimsPosInBox, dim, off}); - } - - mlir::Value - getStrideFromBox(mlir::Location loc, TypePair boxTy, mlir::Value box, - unsigned dim, - mlir::ConversionPatternRewriter &rewriter) const { - auto idxTy = lowerTy().indexType(); - return getDimFieldFromBox(loc, boxTy, box, dim, kDimStridePos, idxTy, - rewriter); - } - - /// Read base address from a fir.box. Returned address has type ty. - mlir::Value - getBaseAddrFromBox(mlir::Location loc, TypePair boxTy, mlir::Value box, - mlir::ConversionPatternRewriter &rewriter) const { - mlir::Type resultTy = ::getLlvmPtrType(boxTy.llvm.getContext()); - return getValueFromBox(loc, boxTy, box, resultTy, rewriter, kAddrPosInBox); - } - - mlir::Value - getElementSizeFromBox(mlir::Location loc, mlir::Type resultTy, TypePair boxTy, - mlir::Value box, - mlir::ConversionPatternRewriter &rewriter) const { - return getValueFromBox(loc, boxTy, box, resultTy, rewriter, - kElemLenPosInBox); - } - - // Get the element type given an LLVM type that is of the form - // (array|struct|vector)+ and the provided indexes. - static mlir::Type getBoxEleTy(mlir::Type type, - llvm::ArrayRef<std::int64_t> indexes) { - for (unsigned i : indexes) { - if (auto t = type.dyn_cast<mlir::LLVM::LLVMStructType>()) { - assert(!t.isOpaque() && i < t.getBody().size()); - type = t.getBody()[i]; - } else if (auto t = type.dyn_cast<mlir::LLVM::LLVMArrayType>()) { - type = t.getElementType(); - } else if (auto t = type.dyn_cast<mlir::VectorType>()) { - type = t.getElementType(); - } else { - fir::emitFatalError(mlir::UnknownLoc::get(type.getContext()), - "request for invalid box element type"); - } - } - return type; - } - - // Return LLVM type of the object described by a fir.box of \p boxType. - mlir::Type getLlvmObjectTypeFromBoxType(mlir::Type boxType) const { - mlir::Type objectType = fir::dyn_cast_ptrOrBoxEleTy(boxType); - assert(objectType && "boxType must be a box type"); - return this->convertType(objectType); - } - - /// Read the address of the type descriptor from a box. - mlir::Value - loadTypeDescAddress(mlir::Location loc, TypePair boxTy, mlir::Value box, - mlir::ConversionPatternRewriter &rewriter) const { - unsigned typeDescFieldId = getTypeDescFieldId(boxTy.fir); - mlir::Type tdescType = lowerTy().convertTypeDescType(rewriter.getContext()); - return getValueFromBox(loc, boxTy, box, tdescType, rewriter, - typeDescFieldId); - } - - // Load the attribute from the \p box and perform a check against \p maskValue - // The final comparison is implemented as `(attribute & maskValue) != 0`. - mlir::Value genBoxAttributeCheck(mlir::Location loc, TypePair boxTy, - mlir::Value box, - mlir::ConversionPatternRewriter &rewriter, - unsigned maskValue) const { - mlir::Type attrTy = rewriter.getI32Type(); - mlir::Value attribute = - getValueFromBox(loc, boxTy, box, attrTy, rewriter, kAttributePosInBox); - mlir::LLVM::ConstantOp attrMask = - genConstantOffset(loc, rewriter, maskValue); - auto maskRes = - rewriter.create<mlir::LLVM::AndOp>(loc, attrTy, attribute, attrMask); - mlir::LLVM::ConstantOp c0 = genConstantOffset(loc, rewriter, 0); - return rewriter.create<mlir::LLVM::ICmpOp>( - loc, mlir::LLVM::ICmpPredicate::ne, maskRes, c0); - } - - template <typename... ARGS> - mlir::LLVM::GEPOp genGEP(mlir::Location loc, mlir::Type ty, - mlir::ConversionPatternRewriter &rewriter, - mlir::Value base, ARGS... args) const { - llvm::SmallVector<mlir::LLVM::GEPArg> cv = {args...}; - auto llvmPtrTy = ::getLlvmPtrType(ty.getContext()); - return rewriter.create<mlir::LLVM::GEPOp>(loc, llvmPtrTy, ty, base, cv); - } - - // Find the Block in which the alloca should be inserted. - // The order to recursively find the proper block: - // 1. An OpenMP Op that will be outlined. - // 2. A LLVMFuncOp - // 3. The first ancestor that is an OpenMP Op or a LLVMFuncOp - static mlir::Block *getBlockForAllocaInsert(mlir::Operation *op) { - if (auto iface = - mlir::dyn_cast<mlir::omp::OutlineableOpenMPOpInterface>(op)) - return iface.getAllocaBlock(); - if (auto llvmFuncOp = mlir::dyn_cast<mlir::LLVM::LLVMFuncOp>(op)) - return &llvmFuncOp.front(); - return getBlockForAllocaInsert(op->getParentOp()); - } - - // Generate an alloca of size 1 for an object of type \p llvmObjectTy in the - // allocation address space provided for the architecture in the DataLayout - // specification. If the address space is different from the devices - // program address space we perform a cast. In the case of most architectures - // the program and allocation address space will be the default of 0 and no - // cast will be emitted. - mlir::Value genAllocaAndAddrCastWithType( - mlir::Location loc, mlir::Type llvmObjectTy, unsigned alignment, - mlir::ConversionPatternRewriter &rewriter) const { - auto thisPt = rewriter.saveInsertionPoint(); - mlir::Operation *parentOp = rewriter.getInsertionBlock()->getParentOp(); - mlir::Block *insertBlock = getBlockForAllocaInsert(parentOp); - rewriter.setInsertionPointToStart(insertBlock); - auto size = genI32Constant(loc, rewriter, 1); - unsigned allocaAs = getAllocaAddressSpace(rewriter); - unsigned programAs = getProgramAddressSpace(rewriter); - - mlir::Value al = rewriter.create<mlir::LLVM::AllocaOp>( - loc, ::getLlvmPtrType(llvmObjectTy.getContext(), allocaAs), - llvmObjectTy, size, alignment); - - // if our allocation address space, is not the same as the program address - // space, then we must emit a cast to the program address space before use. - // An example case would be on AMDGPU, where the allocation address space is - // the numeric value 5 (private), and the program address space is 0 - // (generic). - if (allocaAs != programAs) { - al = rewriter.create<mlir::LLVM::AddrSpaceCastOp>( - loc, ::getLlvmPtrType(llvmObjectTy.getContext(), programAs), al); - } - - rewriter.restoreInsertionPoint(thisPt); - return al; - } - - const fir::LLVMTypeConverter &lowerTy() const { - return *static_cast<const fir::LLVMTypeConverter *>( - this->getTypeConverter()); - } - - void attachTBAATag(mlir::LLVM::AliasAnalysisOpInterface op, - mlir::Type baseFIRType, mlir::Type accessFIRType, - mlir::LLVM::GEPOp gep) const { - lowerTy().attachTBAATag(op, baseFIRType, accessFIRType, gep); - } - - const fir::FIRToLLVMPassOptions &options; -}; - -/// FIR conversion pattern template -template <typename FromOp> -class FIROpAndTypeConversion : public FIROpConversion<FromOp> { -public: - using FIROpConversion<FromOp>::FIROpConversion; - using OpAdaptor = typename FromOp::Adaptor; - - mlir::LogicalResult - matchAndRewrite(FromOp op, OpAdaptor adaptor, - mlir::ConversionPatternRewriter &rewriter) const final { - mlir::Type ty = this->convertType(op.getType()); - return doRewrite(op, ty, adaptor, rewriter); - } - - virtual mlir::LogicalResult - doRewrite(FromOp addr, mlir::Type ty, OpAdaptor adaptor, - mlir::ConversionPatternRewriter &rewriter) const = 0; -}; -} // namespace - namespace { /// Lower `fir.address_of` operation to `llvm.address_of` operation. -struct AddrOfOpConversion : public FIROpConversion<fir::AddrOfOp> { +struct AddrOfOpConversion : public fir::FIROpConversion<fir::AddrOfOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -532,7 +189,7 @@ genAllocationScaleSize(OP op, mlir::Type ity, namespace { /// convert to LLVM IR dialect `alloca` -struct AllocaOpConversion : public FIROpConversion<fir::AllocaOp> { +struct AllocaOpConversion : public fir::FIROpConversion<fir::AllocaOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -617,7 +274,7 @@ struct AllocaOpConversion : public FIROpConversion<fir::AllocaOp> { namespace { /// Lower `fir.box_addr` to the sequence of operations to extract the first /// element of the box. -struct BoxAddrOpConversion : public FIROpConversion<fir::BoxAddrOp> { +struct BoxAddrOpConversion : public fir::FIROpConversion<fir::BoxAddrOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -638,7 +295,7 @@ struct BoxAddrOpConversion : public FIROpConversion<fir::BoxAddrOp> { /// Convert `!fir.boxchar_len` to `!llvm.extractvalue` for the 2nd part of the /// boxchar. -struct BoxCharLenOpConversion : public FIROpConversion<fir::BoxCharLenOp> { +struct BoxCharLenOpConversion : public fir::FIROpConversion<fir::BoxCharLenOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -661,7 +318,7 @@ struct BoxCharLenOpConversion : public FIROpConversion<fir::BoxCharLenOp> { /// Lower `fir.box_dims` to a sequence of operations to extract the requested /// dimension information from the boxed value. /// Result in a triple set of GEPs and loads. -struct BoxDimsOpConversion : public FIROpConversion<fir::BoxDimsOp> { +struct BoxDimsOpConversion : public fir::FIROpConversion<fir::BoxDimsOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -683,7 +340,7 @@ struct BoxDimsOpConversion : public FIROpConversion<fir::BoxDimsOp> { /// Lower `fir.box_elesize` to a sequence of operations ro extract the size of /// an element in the boxed value. -struct BoxEleSizeOpConversion : public FIROpConversion<fir::BoxEleSizeOp> { +struct BoxEleSizeOpConversion : public fir::FIROpConversion<fir::BoxEleSizeOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -701,7 +358,7 @@ struct BoxEleSizeOpConversion : public FIROpConversion<fir::BoxEleSizeOp> { /// Lower `fir.box_isalloc` to a sequence of operations to determine if the /// boxed value was from an ALLOCATABLE entity. -struct BoxIsAllocOpConversion : public FIROpConversion<fir::BoxIsAllocOp> { +struct BoxIsAllocOpConversion : public fir::FIROpConversion<fir::BoxIsAllocOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -719,7 +376,7 @@ struct BoxIsAllocOpConversion : public FIROpConversion<fir::BoxIsAllocOp> { /// Lower `fir.box_isarray` to a sequence of operations to determine if the /// boxed is an array. -struct BoxIsArrayOpConversion : public FIROpConversion<fir::BoxIsArrayOp> { +struct BoxIsArrayOpConversion : public fir::FIROpConversion<fir::BoxIsArrayOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -739,7 +396,7 @@ struct BoxIsArrayOpConversion : public FIROpConversion<fir::BoxIsArrayOp> { /// Lower `fir.box_isptr` to a sequence of operations to determined if the /// boxed value was from a POINTER entity. -struct BoxIsPtrOpConversion : public FIROpConversion<fir::BoxIsPtrOp> { +struct BoxIsPtrOpConversion : public fir::FIROpConversion<fir::BoxIsPtrOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -757,7 +414,7 @@ struct BoxIsPtrOpConversion : public FIROpConversion<fir::BoxIsPtrOp> { /// Lower `fir.box_rank` to the sequence of operation to extract the rank from /// the box. -struct BoxRankOpConversion : public FIROpConversion<fir::BoxRankOp> { +struct BoxRankOpConversion : public fir::FIROpConversion<fir::BoxRankOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -777,7 +434,8 @@ struct BoxRankOpConversion : public FIROpConversion<fir::BoxRankOp> { /// Lower `fir.boxproc_host` operation. Extracts the host pointer from the /// boxproc. /// TODO: Part of supporting Fortran 2003 procedure pointers. -struct BoxProcHostOpConversion : public FIROpConversion<fir::BoxProcHostOp> { +struct BoxProcHostOpConversion + : public fir::FIROpConversion<fir::BoxProcHostOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -790,7 +448,8 @@ struct BoxProcHostOpConversion : public FIROpConversion<fir::BoxProcHostOp> { /// Lower `fir.box_tdesc` to the sequence of operations to extract the type /// descriptor from the box. -struct BoxTypeDescOpConversion : public FIROpConversion<fir::BoxTypeDescOp> { +struct BoxTypeDescOpConversion + : public fir::FIROpConversion<fir::BoxTypeDescOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -807,7 +466,8 @@ struct BoxTypeDescOpConversion : public FIROpConversion<fir::BoxTypeDescOp> { /// Lower `fir.box_typecode` to a sequence of operations to extract the type /// code in the boxed value. -struct BoxTypeCodeOpConversion : public FIROpConversion<fir::BoxTypeCodeOp> { +struct BoxTypeCodeOpConversion + : public fir::FIROpConversion<fir::BoxTypeCodeOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -825,7 +485,7 @@ struct BoxTypeCodeOpConversion : public FIROpConversion<fir::BoxTypeCodeOp> { }; /// Lower `fir.string_lit` to LLVM IR dialect operation. -struct StringLitOpConversion : public FIROpConversion<fir::StringLitOp> { +struct StringLitOpConversion : public fir::FIROpConversion<fir::StringLitOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -865,7 +525,7 @@ struct StringLitOpConversion : public FIROpConversion<fir::StringLitOp> { }; /// `fir.call` -> `llvm.call` -struct CallOpConversion : public FIROpConversion<fir::CallOp> { +struct CallOpConversion : public fir::FIROpConversion<fir::CallOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -896,7 +556,7 @@ namespace { /// Per 10.1, the only comparisons available are .EQ. (oeq) and .NE. (une). /// /// For completeness, all other comparison are done on the real component only. -struct CmpcOpConversion : public FIROpConversion<fir::CmpcOp> { +struct CmpcOpConversion : public fir::FIROpConversion<fir::CmpcOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -934,7 +594,7 @@ struct CmpcOpConversion : public FIROpConversion<fir::CmpcOp> { }; /// Lower complex constants -struct ConstcOpConversion : public FIROpConversion<fir::ConstcOp> { +struct ConstcOpConversion : public fir::FIROpConversion<fir::ConstcOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -961,7 +621,7 @@ struct ConstcOpConversion : public FIROpConversion<fir::ConstcOp> { }; /// convert value of from-type to value of to-type -struct ConvertOpConversion : public FIROpConversion<fir::ConvertOp> { +struct ConvertOpConversion : public fir::FIROpConversion<fir::ConvertOp> { using FIROpConversion::FIROpConversion; static bool isFloatingPointTy(mlir::Type ty) { @@ -1130,7 +790,7 @@ struct ConvertOpConversion : public FIROpConversion<fir::ConvertOp> { /// only used to carry information during FIR to FIR passes. It may be used /// in the future to generate the runtime type info data structures instead /// of generating them in lowering. -struct TypeInfoOpConversion : public FIROpConversion<fir::TypeInfoOp> { +struct TypeInfoOpConversion : public fir::FIROpConversion<fir::TypeInfoOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -1143,7 +803,7 @@ struct TypeInfoOpConversion : public FIROpConversion<fir::TypeInfoOp> { /// `fir.dt_entry` operation has no specific CodeGen. The operation is only used /// to carry information during FIR to FIR passes. -struct DTEntryOpConversion : public FIROpConversion<fir::DTEntryOp> { +struct DTEntryOpConversion : public fir::FIROpConversion<fir::DTEntryOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -1155,7 +815,7 @@ struct DTEntryOpConversion : public FIROpConversion<fir::DTEntryOp> { }; /// Lower `fir.global_len` operation. -struct GlobalLenOpConversion : public FIROpConversion<fir::GlobalLenOp> { +struct GlobalLenOpConversion : public fir::FIROpConversion<fir::GlobalLenOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -1168,7 +828,7 @@ struct GlobalLenOpConversion : public FIROpConversion<fir::GlobalLenOp> { /// Lower fir.len_param_index struct LenParamIndexOpConversion - : public FIROpConversion<fir::LenParamIndexOp> { + : public fir::FIROpConversion<fir::LenParamIndexOp> { using FIROpConversion::FIROpConversion; // FIXME: this should be specialized by the runtime target @@ -1183,7 +843,7 @@ struct LenParamIndexOpConversion /// instructions that generate `!llvm.struct<(ptr<ik>, i64)>`. The 1st element /// in this struct is a pointer. Its type is determined from `KIND`. The 2nd /// element is the length of the character buffer (`#n`). -struct EmboxCharOpConversion : public FIROpConversion<fir::EmboxCharOp> { +struct EmboxCharOpConversion : public fir::FIROpConversion<fir::EmboxCharOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -1276,7 +936,7 @@ genTypeStrideInBytes(mlir::Location loc, mlir::Type idxTy, namespace { /// Lower a `fir.allocmem` instruction into `llvm.call @malloc` -struct AllocMemOpConversion : public FIROpConversion<fir::AllocMemOp> { +struct AllocMemOpConversion : public fir::FIROpConversion<fir::AllocMemOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -1345,7 +1005,7 @@ static unsigned getDimension(mlir::LLVM::LLVMArrayType ty) { namespace { /// Lower a `fir.freemem` instruction into `llvm.call @free` -struct FreeMemOpConversion : public FIROpConversion<fir::FreeMemOp> { +struct FreeMemOpConversion : public fir::FIROpConversion<fir::FreeMemOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -1403,9 +1063,9 @@ convertSubcomponentIndices(mlir::Location loc, mlir::Type eleTy, /// Common base class for embox to descriptor conversion. template <typename OP> -struct EmboxCommonConversion : public FIROpConversion<OP> { - using FIROpConversion<OP>::FIROpConversion; - using TypePair = typename FIROpConversion<OP>::TypePair; +struct EmboxCommonConversion : public fir::FIROpConversion<OP> { + using fir::FIROpConversion<OP>::FIROpConversion; + using TypePair = typename fir::FIROpConversion<OP>::TypePair; static int getCFIAttr(fir::BaseBoxType boxTy) { auto eleTy = boxTy.getEleTy(); @@ -1427,8 +1087,8 @@ struct EmboxCommonConversion : public FIROpConversion<OP> { return size; // Length accounted for in the genTypeStrideInBytes GEP. // Otherwise, multiply the single character size by the length. assert(!lenParams.empty()); - auto len64 = FIROpConversion<OP>::integerCast(loc, rewriter, i64Ty, - lenParams.back()); + auto len64 = fir::FIROpConversion<OP>::integerCast(loc, rewriter, i64Ty, + lenParams.back()); return rewriter.create<mlir::LLVM::MulOp>(loc, i64Ty, size, len64); } @@ -2273,7 +1933,7 @@ private: /// Lower `fir.emboxproc` operation. Creates a procedure box. /// TODO: Part of supporting Fortran 2003 procedure pointers. -struct EmboxProcOpConversion : public FIROpConversion<fir::EmboxProcOp> { +struct EmboxProcOpConversion : public fir::FIROpConversion<fir::EmboxProcOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -2339,7 +1999,7 @@ private: namespace { /// Extract a subobject value from an ssa-value of aggregate type struct ExtractValueOpConversion - : public FIROpAndTypeConversion<fir::ExtractValueOp>, + : public fir::FIROpAndTypeConversion<fir::ExtractValueOp>, public ValueOpCommon { using FIROpAndTypeConversion::FIROpAndTypeConversion; @@ -2358,7 +2018,7 @@ struct ExtractValueOpConversion /// InsertValue is the generalized instruction for the composition of new /// aggregate type values. struct InsertValueOpConversion - : public FIROpAndTypeConversion<fir::InsertValueOp>, + : public fir::FIROpAndTypeConversion<fir::InsertValueOp>, public ValueOpCommon { using FIROpAndTypeConversion::FIROpAndTypeConversion; @@ -2376,7 +2036,7 @@ struct InsertValueOpConversion /// InsertOnRange inserts a value into a sequence over a range of offsets. struct InsertOnRangeOpConversion - : public FIROpAndTypeConversion<fir::InsertOnRangeOp> { + : public fir::FIROpAndTypeConversion<fir::InsertOnRangeOp> { using FIROpAndTypeConversion::FIROpAndTypeConversion; // Increments an array of subscripts in a row major fasion. @@ -2440,7 +2100,7 @@ namespace { /// (See the static restriction on coordinate_of.) array_coor determines the /// coordinate (location) of a specific element. struct XArrayCoorOpConversion - : public FIROpAndTypeConversion<fir::cg::XArrayCoorOp> { + : public fir::FIROpAndTypeConversion<fir::cg::XArrayCoorOp> { using FIROpAndTypeConversion::FIROpAndTypeConversion; mlir::LogicalResult @@ -2608,7 +2268,7 @@ struct XArrayCoorOpConversion /// With unboxed arrays, there is the restriction that the array have a static /// shape in all but the last column. struct CoordinateOpConversion - : public FIROpAndTypeConversion<fir::CoordinateOp> { + : public fir::FIROpAndTypeConversion<fir::CoordinateOp> { using FIROpAndTypeConversion::FIROpAndTypeConversion; mlir::LogicalResult @@ -2903,7 +2563,7 @@ private: /// Convert `fir.field_index`. The conversion depends on whether the size of /// the record is static or dynamic. -struct FieldIndexOpConversion : public FIROpConversion<fir::FieldIndexOp> { +struct FieldIndexOpConversion : public fir::FIROpConversion<fir::FieldIndexOp> { using FIROpConversion::FIROpConversion; // NB: most field references should be resolved by this point @@ -2944,7 +2604,7 @@ struct FieldIndexOpConversion : public FIROpConversion<fir::FieldIndexOp> { }; /// Convert `fir.end` -struct FirEndOpConversion : public FIROpConversion<fir::FirEndOp> { +struct FirEndOpConversion : public fir::FIROpConversion<fir::FirEndOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -2956,7 +2616,7 @@ struct FirEndOpConversion : public FIROpConversion<fir::FirEndOp> { }; /// Lower `fir.type_desc` to a global addr. -struct TypeDescOpConversion : public FIROpConversion<fir::TypeDescOp> { +struct TypeDescOpConversion : public fir::FIROpConversion<fir::TypeDescOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -2983,7 +2643,7 @@ struct TypeDescOpConversion : public FIROpConversion<fir::TypeDescOp> { }; /// Lower `fir.has_value` operation to `llvm.return` operation. -struct HasValueOpConversion : public FIROpConversion<fir::HasValueOp> { +struct HasValueOpConversion : public fir::FIROpConversion<fir::HasValueOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3036,7 +2696,7 @@ static inline bool attributeTypeIsCompatible(mlir::MLIRContext *ctx, /// Lower `fir.global` operation to `llvm.global` operation. /// `fir.insert_on_range` operations are replaced with constant dense attribute /// if they are applied on the full range. -struct GlobalOpConversion : public FIROpConversion<fir::GlobalOp> { +struct GlobalOpConversion : public fir::FIROpConversion<fir::GlobalOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3160,7 +2820,7 @@ private: }; /// `fir.load` --> `llvm.load` -struct LoadOpConversion : public FIROpConversion<fir::LoadOp> { +struct LoadOpConversion : public fir::FIROpConversion<fir::LoadOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3209,7 +2869,7 @@ struct LoadOpConversion : public FIROpConversion<fir::LoadOp> { /// Lower `fir.no_reassoc` to LLVM IR dialect. /// TODO: how do we want to enforce this in LLVM-IR? Can we manipulate the fast /// math flags? -struct NoReassocOpConversion : public FIROpConversion<fir::NoReassocOp> { +struct NoReassocOpConversion : public fir::FIROpConversion<fir::NoReassocOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3270,7 +2930,7 @@ static void genCaseLadderStep(mlir::Location loc, mlir::Value cmp, /// upper bound in the same case condition. /// /// TODO: lowering of CHARACTER type cases is not handled yet. -struct SelectCaseOpConversion : public FIROpConversion<fir::SelectCaseOp> { +struct SelectCaseOpConversion : public fir::FIROpConversion<fir::SelectCaseOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3384,7 +3044,7 @@ static void selectMatchAndRewrite(const fir::LLVMTypeConverter &lowering, } /// conversion of fir::SelectOp to an if-then-else ladder -struct SelectOpConversion : public FIROpConversion<fir::SelectOp> { +struct SelectOpConversion : public fir::FIROpConversion<fir::SelectOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3396,7 +3056,7 @@ struct SelectOpConversion : public FIROpConversion<fir::SelectOp> { }; /// conversion of fir::SelectRankOp to an if-then-else ladder -struct SelectRankOpConversion : public FIROpConversion<fir::SelectRankOp> { +struct SelectRankOpConversion : public fir::FIROpConversion<fir::SelectRankOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3408,7 +3068,7 @@ struct SelectRankOpConversion : public FIROpConversion<fir::SelectRankOp> { }; /// Lower `fir.select_type` to LLVM IR dialect. -struct SelectTypeOpConversion : public FIROpConversion<fir::SelectTypeOp> { +struct SelectTypeOpConversion : public fir::FIROpConversion<fir::SelectTypeOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3421,7 +3081,7 @@ struct SelectTypeOpConversion : public FIROpConversion<fir::SelectTypeOp> { }; /// `fir.store` --> `llvm.store` -struct StoreOpConversion : public FIROpConversion<fir::StoreOp> { +struct StoreOpConversion : public fir::FIROpConversion<fir::StoreOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3455,7 +3115,7 @@ namespace { /// Convert `fir.unboxchar` into two `llvm.extractvalue` instructions. One for /// the character buffer and one for the buffer length. -struct UnboxCharOpConversion : public FIROpConversion<fir::UnboxCharOp> { +struct UnboxCharOpConversion : public fir::FIROpConversion<fir::UnboxCharOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3480,7 +3140,7 @@ struct UnboxCharOpConversion : public FIROpConversion<fir::UnboxCharOp> { /// Lower `fir.unboxproc` operation. Unbox a procedure box value, yielding its /// components. /// TODO: Part of supporting Fortran 2003 procedure pointers. -struct UnboxProcOpConversion : public FIROpConversion<fir::UnboxProcOp> { +struct UnboxProcOpConversion : public fir::FIROpConversion<fir::UnboxProcOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3492,7 +3152,7 @@ struct UnboxProcOpConversion : public FIROpConversion<fir::UnboxProcOp> { }; /// convert to LLVM IR dialect `undef` -struct UndefOpConversion : public FIROpConversion<fir::UndefOp> { +struct UndefOpConversion : public fir::FIROpConversion<fir::UndefOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3504,7 +3164,7 @@ struct UndefOpConversion : public FIROpConversion<fir::UndefOp> { } }; -struct ZeroOpConversion : public FIROpConversion<fir::ZeroOp> { +struct ZeroOpConversion : public fir::FIROpConversion<fir::ZeroOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3517,7 +3177,8 @@ struct ZeroOpConversion : public FIROpConversion<fir::ZeroOp> { }; /// `fir.unreachable` --> `llvm.unreachable` -struct UnreachableOpConversion : public FIROpConversion<fir::UnreachableOp> { +struct UnreachableOpConversion + : public fir::FIROpConversion<fir::UnreachableOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3534,7 +3195,7 @@ struct UnreachableOpConversion : public FIROpConversion<fir::UnreachableOp> { /// %1 = llvm.ptrtoint %0 /// %2 = llvm.icmp "ne" %1, %0 : i64 /// ``` -struct IsPresentOpConversion : public FIROpConversion<fir::IsPresentOp> { +struct IsPresentOpConversion : public fir::FIROpConversion<fir::IsPresentOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3563,7 +3224,7 @@ struct IsPresentOpConversion : public FIROpConversion<fir::IsPresentOp> { /// Create value signaling an absent optional argument in a call, e.g. /// `fir.absent !fir.ref<i64>` --> `llvm.mlir.zero : !llvm.ptr<i64>` -struct AbsentOpConversion : public FIROpConversion<fir::AbsentOp> { +struct AbsentOpConversion : public fir::FIROpConversion<fir::AbsentOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3623,7 +3284,7 @@ complexSum(OPTY sumop, mlir::ValueRange opnds, } // namespace namespace { -struct AddcOpConversion : public FIROpConversion<fir::AddcOp> { +struct AddcOpConversion : public fir::FIROpConversion<fir::AddcOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3638,7 +3299,7 @@ struct AddcOpConversion : public FIROpConversion<fir::AddcOp> { } }; -struct SubcOpConversion : public FIROpConversion<fir::SubcOp> { +struct SubcOpConversion : public fir::FIROpConversion<fir::SubcOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3654,7 +3315,7 @@ struct SubcOpConversion : public FIROpConversion<fir::SubcOp> { }; /// Inlined complex multiply -struct MulcOpConversion : public FIROpConversion<fir::MulcOp> { +struct MulcOpConversion : public fir::FIROpConversion<fir::MulcOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3688,7 +3349,7 @@ struct MulcOpConversion : public FIROpConversion<fir::MulcOp> { }; /// Inlined complex division -struct DivcOpConversion : public FIROpConversion<fir::DivcOp> { +struct DivcOpConversion : public fir::FIROpConversion<fir::DivcOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3728,7 +3389,7 @@ struct DivcOpConversion : public FIROpConversion<fir::DivcOp> { }; /// Inlined complex negation -struct NegcOpConversion : public FIROpConversion<fir::NegcOp> { +struct NegcOpConversion : public fir::FIROpConversion<fir::NegcOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3749,7 +3410,7 @@ struct NegcOpConversion : public FIROpConversion<fir::NegcOp> { } }; -struct BoxOffsetOpConversion : public FIROpConversion<fir::BoxOffsetOp> { +struct BoxOffsetOpConversion : public fir::FIROpConversion<fir::BoxOffsetOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult @@ -3775,10 +3436,10 @@ struct BoxOffsetOpConversion : public FIROpConversion<fir::BoxOffsetOp> { /// anymore uses. /// These operations are normally dead after the pre-codegen pass. template <typename FromOp> -struct MustBeDeadConversion : public FIROpConversion<FromOp> { +struct MustBeDeadConversion : public fir::FIROpConversion<FromOp> { explicit MustBeDeadConversion(const fir::LLVMTypeConverter &lowering, const fir::FIRToLLVMPassOptions &options) - : FIROpConversion<FromOp>(lowering, options) {} + : fir::FIROpConversion<FromOp>(lowering, options) {} using OpAdaptor = typename FromOp::Adaptor; mlir::LogicalResult @@ -3792,7 +3453,7 @@ struct MustBeDeadConversion : public FIROpConversion<FromOp> { }; struct UnrealizedConversionCastOpConversion - : public FIROpConversion<mlir::UnrealizedConversionCastOp> { + : public fir::FIROpConversion<mlir::UnrealizedConversionCastOp> { using FIROpConversion::FIROpConversion; mlir::LogicalResult diff --git a/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp b/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp new file mode 100644 index 0000000000000000000000000000000000000000..26871d888815555f7c1e30f676b5535554042269 --- /dev/null +++ b/flang/lib/Optimizer/CodeGen/FIROpPatterns.cpp @@ -0,0 +1,315 @@ +//===-- CodeGen.cpp -- bridge to lower to LLVM ----------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ +// +//===----------------------------------------------------------------------===// + +#include "flang/Optimizer/CodeGen/FIROpPatterns.h" +#include "mlir/Dialect/OpenMP/OpenMPDialect.h" +#include "llvm/Support/Debug.h" + +static inline mlir::Type getLlvmPtrType(mlir::MLIRContext *context, + unsigned addressSpace = 0) { + return mlir::LLVM::LLVMPointerType::get(context, addressSpace); +} + +static unsigned getTypeDescFieldId(mlir::Type ty) { + auto isArray = fir::dyn_cast_ptrOrBoxEleTy(ty).isa<fir::SequenceType>(); + return isArray ? kOptTypePtrPosInBox : kDimsPosInBox; +} + +namespace fir { + +ConvertFIRToLLVMPattern::ConvertFIRToLLVMPattern( + llvm::StringRef rootOpName, mlir::MLIRContext *context, + const fir::LLVMTypeConverter &typeConverter, + const fir::FIRToLLVMPassOptions &options, mlir::PatternBenefit benefit) + : ConvertToLLVMPattern(rootOpName, context, typeConverter, benefit), + options(options) {} + +// Convert FIR type to LLVM without turning fir.box<T> into memory +// reference. +mlir::Type +ConvertFIRToLLVMPattern::convertObjectType(mlir::Type firType) const { + if (auto boxTy = firType.dyn_cast<fir::BaseBoxType>()) + return lowerTy().convertBoxTypeAsStruct(boxTy); + return lowerTy().convertType(firType); +} + +mlir::LLVM::ConstantOp ConvertFIRToLLVMPattern::genI32Constant( + mlir::Location loc, mlir::ConversionPatternRewriter &rewriter, + int value) const { + mlir::Type i32Ty = rewriter.getI32Type(); + mlir::IntegerAttr attr = rewriter.getI32IntegerAttr(value); + return rewriter.create<mlir::LLVM::ConstantOp>(loc, i32Ty, attr); +} + +mlir::LLVM::ConstantOp ConvertFIRToLLVMPattern::genConstantOffset( + mlir::Location loc, mlir::ConversionPatternRewriter &rewriter, + int offset) const { + mlir::Type ity = lowerTy().offsetType(); + mlir::IntegerAttr cattr = rewriter.getI32IntegerAttr(offset); + return rewriter.create<mlir::LLVM::ConstantOp>(loc, ity, cattr); +} + +/// Perform an extension or truncation as needed on an integer value. Lowering +/// to the specific target may involve some sign-extending or truncation of +/// values, particularly to fit them from abstract box types to the +/// appropriate reified structures. +mlir::Value +ConvertFIRToLLVMPattern::integerCast(mlir::Location loc, + mlir::ConversionPatternRewriter &rewriter, + mlir::Type ty, mlir::Value val) const { + auto valTy = val.getType(); + // If the value was not yet lowered, lower its type so that it can + // be used in getPrimitiveTypeSizeInBits. + if (!valTy.isa<mlir::IntegerType>()) + valTy = convertType(valTy); + auto toSize = mlir::LLVM::getPrimitiveTypeSizeInBits(ty); + auto fromSize = mlir::LLVM::getPrimitiveTypeSizeInBits(valTy); + if (toSize < fromSize) + return rewriter.create<mlir::LLVM::TruncOp>(loc, ty, val); + if (toSize > fromSize) + return rewriter.create<mlir::LLVM::SExtOp>(loc, ty, val); + return val; +} + +fir::ConvertFIRToLLVMPattern::TypePair +ConvertFIRToLLVMPattern::getBoxTypePair(mlir::Type firBoxTy) const { + mlir::Type llvmBoxTy = + lowerTy().convertBoxTypeAsStruct(mlir::cast<fir::BaseBoxType>(firBoxTy)); + return TypePair{firBoxTy, llvmBoxTy}; +} + +/// Construct code sequence to extract the specific value from a `fir.box`. +mlir::Value ConvertFIRToLLVMPattern::getValueFromBox( + mlir::Location loc, TypePair boxTy, mlir::Value box, mlir::Type resultTy, + mlir::ConversionPatternRewriter &rewriter, int boxValue) const { + if (box.getType().isa<mlir::LLVM::LLVMPointerType>()) { + auto pty = getLlvmPtrType(resultTy.getContext()); + auto p = rewriter.create<mlir::LLVM::GEPOp>( + loc, pty, boxTy.llvm, box, + llvm::ArrayRef<mlir::LLVM::GEPArg>{0, boxValue}); + auto loadOp = rewriter.create<mlir::LLVM::LoadOp>(loc, resultTy, p); + attachTBAATag(loadOp, boxTy.fir, nullptr, p); + return loadOp; + } + return rewriter.create<mlir::LLVM::ExtractValueOp>(loc, box, boxValue); +} + +/// Method to construct code sequence to get the triple for dimension `dim` +/// from a box. +llvm::SmallVector<mlir::Value, 3> ConvertFIRToLLVMPattern::getDimsFromBox( + mlir::Location loc, llvm::ArrayRef<mlir::Type> retTys, TypePair boxTy, + mlir::Value box, mlir::Value dim, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Value l0 = + loadDimFieldFromBox(loc, boxTy, box, dim, 0, retTys[0], rewriter); + mlir::Value l1 = + loadDimFieldFromBox(loc, boxTy, box, dim, 1, retTys[1], rewriter); + mlir::Value l2 = + loadDimFieldFromBox(loc, boxTy, box, dim, 2, retTys[2], rewriter); + return {l0, l1, l2}; +} + +llvm::SmallVector<mlir::Value, 3> ConvertFIRToLLVMPattern::getDimsFromBox( + mlir::Location loc, llvm::ArrayRef<mlir::Type> retTys, TypePair boxTy, + mlir::Value box, int dim, mlir::ConversionPatternRewriter &rewriter) const { + mlir::Value l0 = + getDimFieldFromBox(loc, boxTy, box, dim, 0, retTys[0], rewriter); + mlir::Value l1 = + getDimFieldFromBox(loc, boxTy, box, dim, 1, retTys[1], rewriter); + mlir::Value l2 = + getDimFieldFromBox(loc, boxTy, box, dim, 2, retTys[2], rewriter); + return {l0, l1, l2}; +} + +mlir::Value ConvertFIRToLLVMPattern::loadDimFieldFromBox( + mlir::Location loc, TypePair boxTy, mlir::Value box, mlir::Value dim, + int off, mlir::Type ty, mlir::ConversionPatternRewriter &rewriter) const { + assert(box.getType().isa<mlir::LLVM::LLVMPointerType>() && + "descriptor inquiry with runtime dim can only be done on descriptor " + "in memory"); + mlir::LLVM::GEPOp p = genGEP(loc, boxTy.llvm, rewriter, box, 0, + static_cast<int>(kDimsPosInBox), dim, off); + auto loadOp = rewriter.create<mlir::LLVM::LoadOp>(loc, ty, p); + attachTBAATag(loadOp, boxTy.fir, nullptr, p); + return loadOp; +} + +mlir::Value ConvertFIRToLLVMPattern::getDimFieldFromBox( + mlir::Location loc, TypePair boxTy, mlir::Value box, int dim, int off, + mlir::Type ty, mlir::ConversionPatternRewriter &rewriter) const { + if (box.getType().isa<mlir::LLVM::LLVMPointerType>()) { + mlir::LLVM::GEPOp p = genGEP(loc, boxTy.llvm, rewriter, box, 0, + static_cast<int>(kDimsPosInBox), dim, off); + auto loadOp = rewriter.create<mlir::LLVM::LoadOp>(loc, ty, p); + attachTBAATag(loadOp, boxTy.fir, nullptr, p); + return loadOp; + } + return rewriter.create<mlir::LLVM::ExtractValueOp>( + loc, box, llvm::ArrayRef<std::int64_t>{kDimsPosInBox, dim, off}); +} + +mlir::Value ConvertFIRToLLVMPattern::getStrideFromBox( + mlir::Location loc, TypePair boxTy, mlir::Value box, unsigned dim, + mlir::ConversionPatternRewriter &rewriter) const { + auto idxTy = lowerTy().indexType(); + return getDimFieldFromBox(loc, boxTy, box, dim, kDimStridePos, idxTy, + rewriter); +} + +/// Read base address from a fir.box. Returned address has type ty. +mlir::Value ConvertFIRToLLVMPattern::getBaseAddrFromBox( + mlir::Location loc, TypePair boxTy, mlir::Value box, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Type resultTy = ::getLlvmPtrType(boxTy.llvm.getContext()); + return getValueFromBox(loc, boxTy, box, resultTy, rewriter, kAddrPosInBox); +} + +mlir::Value ConvertFIRToLLVMPattern::getElementSizeFromBox( + mlir::Location loc, mlir::Type resultTy, TypePair boxTy, mlir::Value box, + mlir::ConversionPatternRewriter &rewriter) const { + return getValueFromBox(loc, boxTy, box, resultTy, rewriter, kElemLenPosInBox); +} + +// Get the element type given an LLVM type that is of the form +// (array|struct|vector)+ and the provided indexes. +mlir::Type ConvertFIRToLLVMPattern::getBoxEleTy( + mlir::Type type, llvm::ArrayRef<std::int64_t> indexes) const { + for (unsigned i : indexes) { + if (auto t = type.dyn_cast<mlir::LLVM::LLVMStructType>()) { + assert(!t.isOpaque() && i < t.getBody().size()); + type = t.getBody()[i]; + } else if (auto t = type.dyn_cast<mlir::LLVM::LLVMArrayType>()) { + type = t.getElementType(); + } else if (auto t = type.dyn_cast<mlir::VectorType>()) { + type = t.getElementType(); + } else { + fir::emitFatalError(mlir::UnknownLoc::get(type.getContext()), + "request for invalid box element type"); + } + } + return type; +} + +// Return LLVM type of the object described by a fir.box of \p boxType. +mlir::Type ConvertFIRToLLVMPattern::getLlvmObjectTypeFromBoxType( + mlir::Type boxType) const { + mlir::Type objectType = fir::dyn_cast_ptrOrBoxEleTy(boxType); + assert(objectType && "boxType must be a box type"); + return this->convertType(objectType); +} + +/// Read the address of the type descriptor from a box. +mlir::Value ConvertFIRToLLVMPattern::loadTypeDescAddress( + mlir::Location loc, TypePair boxTy, mlir::Value box, + mlir::ConversionPatternRewriter &rewriter) const { + unsigned typeDescFieldId = getTypeDescFieldId(boxTy.fir); + mlir::Type tdescType = lowerTy().convertTypeDescType(rewriter.getContext()); + return getValueFromBox(loc, boxTy, box, tdescType, rewriter, typeDescFieldId); +} + +// Load the attribute from the \p box and perform a check against \p maskValue +// The final comparison is implemented as `(attribute & maskValue) != 0`. +mlir::Value ConvertFIRToLLVMPattern::genBoxAttributeCheck( + mlir::Location loc, TypePair boxTy, mlir::Value box, + mlir::ConversionPatternRewriter &rewriter, unsigned maskValue) const { + mlir::Type attrTy = rewriter.getI32Type(); + mlir::Value attribute = + getValueFromBox(loc, boxTy, box, attrTy, rewriter, kAttributePosInBox); + mlir::LLVM::ConstantOp attrMask = genConstantOffset(loc, rewriter, maskValue); + auto maskRes = + rewriter.create<mlir::LLVM::AndOp>(loc, attrTy, attribute, attrMask); + mlir::LLVM::ConstantOp c0 = genConstantOffset(loc, rewriter, 0); + return rewriter.create<mlir::LLVM::ICmpOp>(loc, mlir::LLVM::ICmpPredicate::ne, + maskRes, c0); +} + +// Find the Block in which the alloca should be inserted. +// The order to recursively find the proper block: +// 1. An OpenMP Op that will be outlined. +// 2. A LLVMFuncOp +// 3. The first ancestor that is an OpenMP Op or a LLVMFuncOp +mlir::Block * +ConvertFIRToLLVMPattern::getBlockForAllocaInsert(mlir::Operation *op) const { + if (auto iface = mlir::dyn_cast<mlir::omp::OutlineableOpenMPOpInterface>(op)) + return iface.getAllocaBlock(); + if (auto llvmFuncOp = mlir::dyn_cast<mlir::LLVM::LLVMFuncOp>(op)) + return &llvmFuncOp.front(); + return getBlockForAllocaInsert(op->getParentOp()); +} + +// Generate an alloca of size 1 for an object of type \p llvmObjectTy in the +// allocation address space provided for the architecture in the DataLayout +// specification. If the address space is different from the devices +// program address space we perform a cast. In the case of most architectures +// the program and allocation address space will be the default of 0 and no +// cast will be emitted. +mlir::Value ConvertFIRToLLVMPattern::genAllocaAndAddrCastWithType( + mlir::Location loc, mlir::Type llvmObjectTy, unsigned alignment, + mlir::ConversionPatternRewriter &rewriter) const { + auto thisPt = rewriter.saveInsertionPoint(); + mlir::Operation *parentOp = rewriter.getInsertionBlock()->getParentOp(); + if (mlir::isa<mlir::omp::DeclareReductionOp>(parentOp)) { + // DeclareReductionOp has multiple child regions. We want to get the first + // block of whichever of those regions we are currently in + mlir::Region *parentRegion = rewriter.getInsertionBlock()->getParent(); + rewriter.setInsertionPointToStart(&parentRegion->front()); + } else { + mlir::Block *insertBlock = getBlockForAllocaInsert(parentOp); + rewriter.setInsertionPointToStart(insertBlock); + } + auto size = genI32Constant(loc, rewriter, 1); + unsigned allocaAs = getAllocaAddressSpace(rewriter); + unsigned programAs = getProgramAddressSpace(rewriter); + + mlir::Value al = rewriter.create<mlir::LLVM::AllocaOp>( + loc, ::getLlvmPtrType(llvmObjectTy.getContext(), allocaAs), llvmObjectTy, + size, alignment); + + // if our allocation address space, is not the same as the program address + // space, then we must emit a cast to the program address space before use. + // An example case would be on AMDGPU, where the allocation address space is + // the numeric value 5 (private), and the program address space is 0 + // (generic). + if (allocaAs != programAs) { + al = rewriter.create<mlir::LLVM::AddrSpaceCastOp>( + loc, ::getLlvmPtrType(llvmObjectTy.getContext(), programAs), al); + } + + rewriter.restoreInsertionPoint(thisPt); + return al; +} + +unsigned ConvertFIRToLLVMPattern::getAllocaAddressSpace( + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Operation *parentOp = rewriter.getInsertionBlock()->getParentOp(); + assert(parentOp != nullptr && + "expected insertion block to have parent operation"); + if (auto module = parentOp->getParentOfType<mlir::ModuleOp>()) + if (mlir::Attribute addrSpace = + mlir::DataLayout(module).getAllocaMemorySpace()) + return llvm::cast<mlir::IntegerAttr>(addrSpace).getUInt(); + return defaultAddressSpace; +} + +unsigned ConvertFIRToLLVMPattern::getProgramAddressSpace( + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Operation *parentOp = rewriter.getInsertionBlock()->getParentOp(); + assert(parentOp != nullptr && + "expected insertion block to have parent operation"); + if (auto module = parentOp->getParentOfType<mlir::ModuleOp>()) + if (mlir::Attribute addrSpace = + mlir::DataLayout(module).getProgramMemorySpace()) + return llvm::cast<mlir::IntegerAttr>(addrSpace).getUInt(); + return defaultAddressSpace; +} + +} // namespace fir diff --git a/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp b/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp index 0170b56367cf3cd02cf4af32f158fd652104ec61..665bf09b8fc33bdfd99d5f1f1f5d79099afae0c2 100644 --- a/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp +++ b/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp @@ -283,7 +283,9 @@ public: class CodeGenRewrite : public fir::impl::CodeGenRewriteBase<CodeGenRewrite> { public: - void runOn(mlir::Operation *op, mlir::Region ®ion) { + void runOnOperation() override final { + mlir::ModuleOp mod = getOperation(); + auto &context = getContext(); mlir::ConversionTarget target(context); target.addLegalDialect<mlir::arith::ArithDialect, fir::FIROpsDialect, @@ -298,10 +300,9 @@ public: .isa<fir::SequenceType>()); }); mlir::RewritePatternSet patterns(&context); - patterns.insert<EmboxConversion, ArrayCoorConversion, ReboxConversion, - DeclareOpConversion>(&context); + fir::populatePreCGRewritePatterns(patterns); if (mlir::failed( - mlir::applyPartialConversion(op, target, std::move(patterns)))) { + mlir::applyPartialConversion(mod, target, std::move(patterns)))) { mlir::emitError(mlir::UnknownLoc::get(&context), "error in running the pre-codegen conversions"); signalPassFailure(); @@ -309,16 +310,7 @@ public: } // Erase any residual (fir.shape, fir.slice...). mlir::IRRewriter rewriter(&context); - (void)mlir::runRegionDCE(rewriter, op->getRegions()); - } - - void runOnOperation() override final { - // Call runOn on all top level regions that may contain emboxOp/arrayCoorOp. - auto mod = getOperation(); - for (auto func : mod.getOps<mlir::func::FuncOp>()) - runOn(func, func.getBody()); - for (auto global : mod.getOps<fir::GlobalOp>()) - runOn(global, global.getRegion()); + (void)mlir::runRegionDCE(rewriter, mod->getRegions()); } }; @@ -327,3 +319,8 @@ public: std::unique_ptr<mlir::Pass> fir::createFirCodeGenRewritePass() { return std::make_unique<CodeGenRewrite>(); } + +void fir::populatePreCGRewritePatterns(mlir::RewritePatternSet &patterns) { + patterns.insert<EmboxConversion, ArrayCoorConversion, ReboxConversion, + DeclareOpConversion>(patterns.getContext()); +} diff --git a/flang/lib/Optimizer/Dialect/FIRAttr.cpp b/flang/lib/Optimizer/Dialect/FIRAttr.cpp index 0cf8dfb9f784c3df7984c184a61d988663b4715a..e43710f5627ee062674f1e3166ce56f2aaf7b45f 100644 --- a/flang/lib/Optimizer/Dialect/FIRAttr.cpp +++ b/flang/lib/Optimizer/Dialect/FIRAttr.cpp @@ -299,5 +299,6 @@ void FIROpsDialect::registerAttributes() { addAttributes<ClosedIntervalAttr, ExactTypeAttr, FortranVariableFlagsAttr, LowerBoundAttr, PointIntervalAttr, RealAttr, SubclassAttr, UpperBoundAttr, CUDADataAttributeAttr, CUDAProcAttributeAttr, - CUDALaunchBoundsAttr, CUDAClusterDimsAttr>(); + CUDALaunchBoundsAttr, CUDAClusterDimsAttr, + CUDADataTransferKindAttr>(); } diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp index 9bb10a42a3997c092ffa81b54c1eb2224453ea67..dba2c30d1851bf09de8280a1b0dc09fbbb2393fe 100644 --- a/flang/lib/Optimizer/Dialect/FIROps.cpp +++ b/flang/lib/Optimizer/Dialect/FIROps.cpp @@ -3677,10 +3677,19 @@ fir::parseSelector(mlir::OpAsmParser &parser, mlir::OperationState &result, return mlir::success(); } -mlir::func::FuncOp -fir::createFuncOp(mlir::Location loc, mlir::ModuleOp module, - llvm::StringRef name, mlir::FunctionType type, - llvm::ArrayRef<mlir::NamedAttribute> attrs) { +mlir::func::FuncOp fir::createFuncOp(mlir::Location loc, mlir::ModuleOp module, + llvm::StringRef name, + mlir::FunctionType type, + llvm::ArrayRef<mlir::NamedAttribute> attrs, + const mlir::SymbolTable *symbolTable) { + if (symbolTable) + if (auto f = symbolTable->lookup<mlir::func::FuncOp>(name)) { +#ifdef EXPENSIVE_CHECKS + assert(f == module.lookupSymbol<mlir::func::FuncOp>(name) && + "symbolTable and module out of sync"); +#endif + return f; + } if (auto f = module.lookupSymbol<mlir::func::FuncOp>(name)) return f; mlir::OpBuilder modBuilder(module.getBodyRegion()); @@ -3692,7 +3701,16 @@ fir::createFuncOp(mlir::Location loc, mlir::ModuleOp module, fir::GlobalOp fir::createGlobalOp(mlir::Location loc, mlir::ModuleOp module, llvm::StringRef name, mlir::Type type, - llvm::ArrayRef<mlir::NamedAttribute> attrs) { + llvm::ArrayRef<mlir::NamedAttribute> attrs, + const mlir::SymbolTable *symbolTable) { + if (symbolTable) + if (auto g = symbolTable->lookup<fir::GlobalOp>(name)) { +#ifdef EXPENSIVE_CHECKS + assert(g == module.lookupSymbol<fir::GlobalOp>(name) && + "symbolTable and module out of sync"); +#endif + return g; + } if (auto g = module.lookupSymbol<fir::GlobalOp>(name)) return g; mlir::OpBuilder modBuilder(module.getBodyRegion()); diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp index 8a2c681d95860961a9aa70f31ab7e7e304e8c2f8..5c4cad6d20834469ccfb36393c2a2f81b6f93919 100644 --- a/flang/lib/Optimizer/Dialect/FIRType.cpp +++ b/flang/lib/Optimizer/Dialect/FIRType.cpp @@ -254,6 +254,18 @@ bool hasDynamicSize(mlir::Type t) { return false; } +mlir::Type extractSequenceType(mlir::Type ty) { + if (mlir::isa<fir::SequenceType>(ty)) + return ty; + if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(ty)) + return extractSequenceType(boxTy.getEleTy()); + if (auto heapTy = mlir::dyn_cast<fir::HeapType>(ty)) + return extractSequenceType(heapTy.getEleTy()); + if (auto ptrTy = mlir::dyn_cast<fir::PointerType>(ty)) + return extractSequenceType(ptrTy.getEleTy()); + return mlir::Type{}; +} + bool isPointerType(mlir::Type ty) { if (auto refTy = fir::dyn_cast_ptrEleTy(ty)) ty = refTy; diff --git a/flang/lib/Optimizer/Transforms/ControlFlowConverter.cpp b/flang/lib/Optimizer/Transforms/ControlFlowConverter.cpp index 0944b184ca0d4e7cde1dd4e63587765be6060876..45609a99995d0a03ed65550cbc9a708388cb9dc8 100644 --- a/flang/lib/Optimizer/Transforms/ControlFlowConverter.cpp +++ b/flang/lib/Optimizer/Transforms/ControlFlowConverter.cpp @@ -24,7 +24,8 @@ #include "llvm/Support/CommandLine.h" namespace fir { -#define GEN_PASS_DEF_CFGCONVERSION +#define GEN_PASS_DEF_CFGCONVERSIONONFUNC +#define GEN_PASS_DEF_CFGCONVERSIONONREDUCTION #include "flang/Optimizer/Transforms/Passes.h.inc" } // namespace fir @@ -308,13 +309,13 @@ public: }; /// Convert FIR structured control flow ops to CFG ops. -class CfgConversion : public fir::impl::CFGConversionBase<CfgConversion> { +template <typename Pass, template <typename> class PassBase> +class CfgConversionTemplate : public PassBase<Pass> { public: void runOnOperation() override { - auto *context = &getContext(); + auto *context = &this->getContext(); mlir::RewritePatternSet patterns(context); - patterns.insert<CfgLoopConv, CfgIfConv, CfgIterWhileConv>( - context, forceLoopToExecuteOnce); + fir::populateCfgConversionRewrites(patterns, this->forceLoopToExecuteOnce); mlir::ConversionTarget target(*context); target.addLegalDialect<mlir::affine::AffineDialect, mlir::cf::ControlFlowDialect, FIROpsDialect, @@ -323,19 +324,38 @@ public: // apply the patterns target.addIllegalOp<ResultOp, DoLoopOp, IfOp, IterWhileOp>(); target.markUnknownOpDynamicallyLegal([](Operation *) { return true; }); - if (mlir::failed(mlir::applyPartialConversion(getOperation(), target, + if (mlir::failed(mlir::applyPartialConversion(this->getOperation(), target, std::move(patterns)))) { mlir::emitError(mlir::UnknownLoc::get(context), "error in converting to CFG\n"); - signalPassFailure(); + this->signalPassFailure(); } } }; + +class CfgConversionOnFunc + : public CfgConversionTemplate<CfgConversionOnFunc, + ::fir::impl::CFGConversionOnFuncBase> {}; + +class CfgConversionOnReduction + : public CfgConversionTemplate<CfgConversionOnReduction, + ::fir::impl::CFGConversionOnReductionBase> { +}; } // namespace +/// Expose conversion rewriters to other passes +void fir::populateCfgConversionRewrites(mlir::RewritePatternSet &patterns, + bool forceLoopToExecuteOnce) { + patterns.insert<CfgLoopConv, CfgIfConv, CfgIterWhileConv>( + patterns.getContext(), forceLoopToExecuteOnce); +} + /// Convert FIR's structured control flow ops to CFG ops. This /// conversion enables the `createLowerToCFGPass` to transform these to CFG /// form. -std::unique_ptr<mlir::Pass> fir::createFirToCfgPass() { - return std::make_unique<CfgConversion>(); +std::unique_ptr<mlir::Pass> fir::createFirToCfgOnFuncPass() { + return std::make_unique<CfgConversionOnFunc>(); +} +std::unique_ptr<mlir::Pass> fir::createFirToCfgOnReductionPass() { + return std::make_unique<CfgConversionOnReduction>(); } diff --git a/flang/lib/Optimizer/Transforms/ExternalNameConversion.cpp b/flang/lib/Optimizer/Transforms/ExternalNameConversion.cpp index 3a9686418c2eae03ce828805ef0e68758c283499..b265c74c33dd5eb13b90cefd369da58f579846da 100644 --- a/flang/lib/Optimizer/Transforms/ExternalNameConversion.cpp +++ b/flang/lib/Optimizer/Transforms/ExternalNameConversion.cpp @@ -12,13 +12,9 @@ #include "flang/Optimizer/Dialect/FIROpsSupport.h" #include "flang/Optimizer/Support/InternalNames.h" #include "flang/Optimizer/Transforms/Passes.h" -#include "mlir/Dialect/LLVMIR/LLVMDialect.h" -#include "mlir/Dialect/OpenACC/OpenACC.h" -#include "mlir/Dialect/OpenMP/OpenMPDialect.h" #include "mlir/IR/Attributes.h" #include "mlir/IR/SymbolTable.h" #include "mlir/Pass/Pass.h" -#include "mlir/Transforms/DialectConversion.h" namespace fir { #define GEN_PASS_DEF_EXTERNALNAMECONVERSION @@ -44,102 +40,8 @@ mangleExternalName(const std::pair<fir::NameUniquer::NameKind, appendUnderscore); } -//===----------------------------------------------------------------------===// -// Rewrite patterns -//===----------------------------------------------------------------------===// - namespace { -struct MangleNameOnFuncOp : public mlir::OpRewritePattern<mlir::func::FuncOp> { -public: - using OpRewritePattern::OpRewritePattern; - - MangleNameOnFuncOp(mlir::MLIRContext *ctx, bool appendUnderscore) - : mlir::OpRewritePattern<mlir::func::FuncOp>(ctx), - appendUnderscore(appendUnderscore) {} - - mlir::LogicalResult - matchAndRewrite(mlir::func::FuncOp op, - mlir::PatternRewriter &rewriter) const override { - mlir::LogicalResult ret = success(); - rewriter.startOpModification(op); - llvm::StringRef oldName = op.getSymName(); - auto result = fir::NameUniquer::deconstruct(oldName); - if (fir::NameUniquer::isExternalFacingUniquedName(result)) { - auto newSymbol = - rewriter.getStringAttr(mangleExternalName(result, appendUnderscore)); - - // Try to update all SymbolRef's in the module that match the current op - if (mlir::ModuleOp mod = op->getParentOfType<mlir::ModuleOp>()) - ret = op.replaceAllSymbolUses(newSymbol, mod); - - op.setSymNameAttr(newSymbol); - mlir::SymbolTable::setSymbolName(op, newSymbol); - - op->setAttr(fir::getInternalFuncNameAttrName(), - mlir::StringAttr::get(op->getContext(), oldName)); - } - rewriter.finalizeOpModification(op); - return ret; - } - -private: - bool appendUnderscore; -}; - -struct MangleNameForCommonBlock : public mlir::OpRewritePattern<fir::GlobalOp> { -public: - using OpRewritePattern::OpRewritePattern; - - MangleNameForCommonBlock(mlir::MLIRContext *ctx, bool appendUnderscore) - : mlir::OpRewritePattern<fir::GlobalOp>(ctx), - appendUnderscore(appendUnderscore) {} - - mlir::LogicalResult - matchAndRewrite(fir::GlobalOp op, - mlir::PatternRewriter &rewriter) const override { - rewriter.startOpModification(op); - auto result = fir::NameUniquer::deconstruct( - op.getSymref().getRootReference().getValue()); - if (fir::NameUniquer::isExternalFacingUniquedName(result)) { - auto newName = mangleExternalName(result, appendUnderscore); - op.setSymrefAttr(mlir::SymbolRefAttr::get(op.getContext(), newName)); - SymbolTable::setSymbolName(op, newName); - } - rewriter.finalizeOpModification(op); - return success(); - } - -private: - bool appendUnderscore; -}; - -struct MangleNameOnAddrOfOp : public mlir::OpRewritePattern<fir::AddrOfOp> { -public: - using OpRewritePattern::OpRewritePattern; - - MangleNameOnAddrOfOp(mlir::MLIRContext *ctx, bool appendUnderscore) - : mlir::OpRewritePattern<fir::AddrOfOp>(ctx), - appendUnderscore(appendUnderscore) {} - - mlir::LogicalResult - matchAndRewrite(fir::AddrOfOp op, - mlir::PatternRewriter &rewriter) const override { - auto result = fir::NameUniquer::deconstruct( - op.getSymbol().getRootReference().getValue()); - if (fir::NameUniquer::isExternalFacingUniquedName(result)) { - auto newName = SymbolRefAttr::get( - op.getContext(), mangleExternalName(result, appendUnderscore)); - rewriter.replaceOpWithNewOp<fir::AddrOfOp>(op, op.getResTy().getType(), - newName); - } - return success(); - } - -private: - bool appendUnderscore; -}; - class ExternalNameConversionPass : public fir::impl::ExternalNameConversionBase<ExternalNameConversionPass> { public: @@ -162,31 +64,42 @@ void ExternalNameConversionPass::runOnOperation() { auto *context = &getContext(); appendUnderscores = (usePassOpt) ? appendUnderscoreOpt : appendUnderscores; + llvm::DenseMap<mlir::StringAttr, mlir::FlatSymbolRefAttr> remappings; + // Update names of external Fortran functions and names of Common Block + // globals. + for (auto &funcOrGlobal : op->getRegion(0).front()) { + if (llvm::isa<mlir::func::FuncOp>(funcOrGlobal) || + llvm::isa<fir::GlobalOp>(funcOrGlobal)) { + auto symName = funcOrGlobal.getAttrOfType<mlir::StringAttr>( + mlir::SymbolTable::getSymbolAttrName()); + auto deconstructedName = fir::NameUniquer::deconstruct(symName); + if (fir::NameUniquer::isExternalFacingUniquedName(deconstructedName)) { + auto newName = mangleExternalName(deconstructedName, appendUnderscores); + auto newAttr = mlir::StringAttr::get(context, newName); + mlir::SymbolTable::setSymbolName(&funcOrGlobal, newAttr); + auto newSymRef = mlir::FlatSymbolRefAttr::get(newAttr); + remappings.try_emplace(symName, newSymRef); + if (llvm::isa<mlir::func::FuncOp>(funcOrGlobal)) + funcOrGlobal.setAttr(fir::getInternalFuncNameAttrName(), symName); + } + } + } - mlir::RewritePatternSet patterns(context); - patterns.insert<MangleNameOnFuncOp, MangleNameForCommonBlock, - MangleNameOnAddrOfOp>(context, appendUnderscores); - - ConversionTarget target(*context); - target.addLegalDialect<fir::FIROpsDialect, LLVM::LLVMDialect, - acc::OpenACCDialect, omp::OpenMPDialect>(); - - target.addDynamicallyLegalOp<mlir::func::FuncOp>([](mlir::func::FuncOp op) { - return !fir::NameUniquer::needExternalNameMangling(op.getSymName()); - }); - - target.addDynamicallyLegalOp<fir::GlobalOp>([](fir::GlobalOp op) { - return !fir::NameUniquer::needExternalNameMangling( - op.getSymref().getRootReference().getValue()); - }); - - target.addDynamicallyLegalOp<fir::AddrOfOp>([](fir::AddrOfOp op) { - return !fir::NameUniquer::needExternalNameMangling( - op.getSymbol().getRootReference().getValue()); + if (remappings.empty()) + return; + + // Update all uses of the functions and globals that have been renamed. + op.walk([&remappings](mlir::Operation *nestedOp) { + llvm::SmallVector<std::pair<mlir::StringAttr, mlir::SymbolRefAttr>> updates; + for (const mlir::NamedAttribute &attr : nestedOp->getAttrDictionary()) + if (auto symRef = llvm::dyn_cast<mlir::SymbolRefAttr>(attr.getValue())) + if (auto remap = remappings.find(symRef.getRootReference()); + remap != remappings.end()) + updates.emplace_back(std::pair<mlir::StringAttr, mlir::SymbolRefAttr>{ + attr.getName(), mlir::SymbolRefAttr(remap->second)}); + for (auto update : updates) + nestedOp->setAttr(update.first, update.second); }); - - if (failed(applyPartialConversion(op, target, std::move(patterns)))) - signalPassFailure(); } std::unique_ptr<mlir::Pass> fir::createExternalNameConversionPass() { diff --git a/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp b/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp index a11aa38c771bd14b8894e369b5e3812f06986bd8..f7820b6b8170ba075bd15ed1af6a202ee3da466d 100644 --- a/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp +++ b/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp @@ -1004,10 +1004,8 @@ mlir::func::FuncOp SimplifyIntrinsicsPass::getOrCreateFunction( // We can also avoid this by using internal linkage, but // this may increase the size of final executable/shared library. std::string replacementName = mlir::Twine{baseName, "_simplified"}.str(); - mlir::ModuleOp module = builder.getModule(); // If we already have a function, just return it. - mlir::func::FuncOp newFunc = - fir::FirOpBuilder::getNamedFunction(module, replacementName); + mlir::func::FuncOp newFunc = builder.getNamedFunction(replacementName); mlir::FunctionType fType = typeGenerator(builder); if (newFunc) { assert(newFunc.getFunctionType() == fType && @@ -1017,8 +1015,7 @@ mlir::func::FuncOp SimplifyIntrinsicsPass::getOrCreateFunction( // Need to build the function! auto loc = mlir::UnknownLoc::get(builder.getContext()); - newFunc = - fir::FirOpBuilder::createFunction(loc, module, replacementName, fType); + newFunc = builder.createFunction(loc, replacementName, fType); auto inlineLinkage = mlir::LLVM::linkage::Linkage::LinkonceODR; auto linkage = mlir::LLVM::LinkageAttr::get(builder.getContext(), inlineLinkage); diff --git a/flang/lib/Parser/Fortran-parsers.cpp b/flang/lib/Parser/Fortran-parsers.cpp index fc81a477897a3cd33725602090ce4220c25cc470..21185694227d98d88c31a0ae2076b6cdec58925d 100644 --- a/flang/lib/Parser/Fortran-parsers.cpp +++ b/flang/lib/Parser/Fortran-parsers.cpp @@ -1261,24 +1261,27 @@ TYPE_PARSER(construct<StatOrErrmsg>("STAT =" >> statVariable) || // Directives, extensions, and deprecated statements // !DIR$ IGNORE_TKR [ [(tkrdmac...)] name ]... // !DIR$ LOOP COUNT (n1[, n2]...) -// !DIR$ name... +// !DIR$ name[=value] [, name[=value]]... +// !DIR$ <anything else> constexpr auto ignore_tkr{ - "DIR$ IGNORE_TKR" >> optionalList(construct<CompilerDirective::IgnoreTKR>( - maybe(parenthesized(many(letter))), name))}; + "IGNORE_TKR" >> optionalList(construct<CompilerDirective::IgnoreTKR>( + maybe(parenthesized(many(letter))), name))}; constexpr auto loopCount{ - "DIR$ LOOP COUNT" >> construct<CompilerDirective::LoopCount>( - parenthesized(nonemptyList(digitString64)))}; -constexpr auto assumeAligned{"DIR$ ASSUME_ALIGNED" >> + "LOOP COUNT" >> construct<CompilerDirective::LoopCount>( + parenthesized(nonemptyList(digitString64)))}; +constexpr auto assumeAligned{"ASSUME_ALIGNED" >> optionalList(construct<CompilerDirective::AssumeAligned>( indirect(designator), ":"_tok >> digitString64))}; -TYPE_PARSER(beginDirective >> - sourced(construct<CompilerDirective>(ignore_tkr) || - construct<CompilerDirective>(loopCount) || - construct<CompilerDirective>(assumeAligned) || - construct<CompilerDirective>( - "DIR$" >> many(construct<CompilerDirective::NameValue>(name, - maybe(("="_tok || ":"_tok) >> digitString64))))) / - endOfStmt) +TYPE_PARSER(beginDirective >> "DIR$ "_tok >> + sourced((construct<CompilerDirective>(ignore_tkr) || + construct<CompilerDirective>(loopCount) || + construct<CompilerDirective>(assumeAligned) || + construct<CompilerDirective>( + many(construct<CompilerDirective::NameValue>( + name, maybe(("="_tok || ":"_tok) >> digitString64))))) / + endOfStmt || + construct<CompilerDirective>(pure<CompilerDirective::Unrecognized>()) / + SkipTo<'\n'>{})) TYPE_PARSER(extension<LanguageFeature::CrayPointer>( "nonstandard usage: based POINTER"_port_en_US, diff --git a/flang/lib/Parser/executable-parsers.cpp b/flang/lib/Parser/executable-parsers.cpp index de2be017508c370b07b038ca27f32a0bef81023f..07a570bd61e9909e42c6319b417ddfe6e9140f7b 100644 --- a/flang/lib/Parser/executable-parsers.cpp +++ b/flang/lib/Parser/executable-parsers.cpp @@ -542,19 +542,19 @@ TYPE_CONTEXT_PARSER("UNLOCK statement"_en_US, // CUF-kernel-do-directive -> // !$CUF KERNEL DO [ (scalar-int-constant-expr) ] <<< grid, block [, stream] // >>> do-construct -// grid -> * | scalar-int-expr | ( scalar-int-expr-list ) -// block -> * | scalar-int-expr | ( scalar-int-expr-list ) +// star-or-expr -> * | scalar-int-expr +// grid -> * | scalar-int-expr | ( star-or-expr-list ) +// block -> * | scalar-int-expr | ( star-or-expr-list ) // stream -> ( 0, | STREAM = ) scalar-int-expr +constexpr auto starOrExpr{construct<CUFKernelDoConstruct::StarOrExpr>( + "*" >> pure<std::optional<ScalarIntExpr>>() || + applyFunction(presentOptional<ScalarIntExpr>, scalarIntExpr))}; +constexpr auto gridOrBlock{parenthesized(nonemptyList(starOrExpr)) || + applyFunction(singletonList<CUFKernelDoConstruct::StarOrExpr>, starOrExpr)}; TYPE_PARSER(sourced(beginDirective >> "$CUF KERNEL DO"_tok >> construct<CUFKernelDoConstruct::Directive>( - maybe(parenthesized(scalarIntConstantExpr)), - "<<<" >> - ("*" >> pure<std::list<ScalarIntExpr>>() || - parenthesized(nonemptyList(scalarIntExpr)) || - applyFunction(singletonList<ScalarIntExpr>, scalarIntExpr)), - "," >> ("*" >> pure<std::list<ScalarIntExpr>>() || - parenthesized(nonemptyList(scalarIntExpr)) || - applyFunction(singletonList<ScalarIntExpr>, scalarIntExpr)), + maybe(parenthesized(scalarIntConstantExpr)), "<<<" >> gridOrBlock, + "," >> gridOrBlock, maybe((", 0 ,"_tok || ", STREAM ="_tok) >> scalarIntExpr) / ">>>" / endDirective))) TYPE_CONTEXT_PARSER("!$CUF KERNEL DO construct"_en_US, diff --git a/flang/lib/Parser/misc-parsers.h b/flang/lib/Parser/misc-parsers.h index e9b52b7d0fcd0fa6d53ed446c1f5ab88cc91e8c4..4a318e05bb4b8ccfa7e41440a52a8e3f68ae6de4 100644 --- a/flang/lib/Parser/misc-parsers.h +++ b/flang/lib/Parser/misc-parsers.h @@ -57,5 +57,10 @@ template <typename A> common::IfNoLvalue<std::list<A>, A> singletonList(A &&x) { result.emplace_back(std::move(x)); return result; } + +template <typename A> +common::IfNoLvalue<std::optional<A>, A> presentOptional(A &&x) { + return std::make_optional(std::move(x)); +} } // namespace Fortran::parser #endif diff --git a/flang/lib/Parser/tools.cpp b/flang/lib/Parser/tools.cpp index 899fb0f069a93589eb46f96aa69396e3a97146a2..6e5f1ed2fc66f035ca65c306a604408303149788 100644 --- a/flang/lib/Parser/tools.cpp +++ b/flang/lib/Parser/tools.cpp @@ -123,6 +123,10 @@ const Name &GetFirstName(const Variable &x) { x.u); } +const Name &GetFirstName(const EntityDecl &x) { + return std::get<ObjectName>(x.t); +} + const CoindexedNamedObject *GetCoindexedNamedObject(const DataRef &base) { return common::visit( common::visitors{ diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 600aa01999dab79e0bb49ee855e9f1a1887e2671..c06458833f0729f6a1ea3944d3e4a47b637bc1f9 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -1827,6 +1827,10 @@ public: [&](const std::list<CompilerDirective::NameValue> &names) { Walk("!DIR$ ", names, " "); }, + [&](const CompilerDirective::Unrecognized &) { + Word("!DIR$ "); + Word(x.source.ToString()); + }, }, x.u); Put('\n'); @@ -2729,6 +2733,13 @@ public: WALK_NESTED_ENUM(OmpOrderModifier, Kind) // OMP order-modifier #undef WALK_NESTED_ENUM + void Unparse(const CUFKernelDoConstruct::StarOrExpr &x) { + if (x.v) { + Walk(*x.v); + } else { + Word("*"); + } + } void Unparse(const CUFKernelDoConstruct::Directive &x) { Word("!$CUF KERNEL DO"); Walk(" (", std::get<std::optional<ScalarIntConstantExpr>>(x.t), ")"); diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp index 3adbd7cc41774d3d6dd2f0eda1a72beb039ad7f9..51a16ee155fabbad99c54fab1c5e04d057102065 100644 --- a/flang/lib/Semantics/check-call.cpp +++ b/flang/lib/Semantics/check-call.cpp @@ -332,7 +332,15 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, bool typesCompatible{typesCompatibleWithIgnoreTKR || dummy.type.type().IsTkCompatibleWith(actualType.type())}; int dummyRank{dummy.type.Rank()}; - if (!typesCompatible && dummyRank == 0 && allowActualArgumentConversions) { + if (typesCompatible) { + if (const auto *constantChar{ + evaluate::UnwrapConstantValue<evaluate::Ascii>(actual)}; + constantChar && constantChar->wasHollerith() && + dummy.type.type().IsUnlimitedPolymorphic()) { + messages.Say( + "passing Hollerith to unlimited polymorphic as if it were CHARACTER"_port_en_US); + } + } else if (dummyRank == 0 && allowActualArgumentConversions) { // Extension: pass Hollerith literal to scalar as if it had been BOZ if (auto converted{evaluate::HollerithToBOZ( foldingContext, actual, dummy.type.type())}) { @@ -1580,6 +1588,9 @@ static void CheckReduce( procChars->dummyArguments.size() != 2 || !procChars->functionResult) { messages.Say( "OPERATION= argument of REDUCE() must be a pure function of two data arguments"_err_en_US); + } else if (procChars->attrs.test(characteristics::Procedure::Attr::BindC)) { + messages.Say( + "A BIND(C) OPERATION= argument of REDUCE() is not supported"_err_en_US); } else if (!result || result->Rank() != 0) { messages.Say( "OPERATION= argument of REDUCE() must be a scalar function"_err_en_US); diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index 431cef207935085e79b73705c9ae696e49da190f..dec8fee774c5beb88412e258d0d8653e450c1fad 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -632,6 +632,11 @@ void CheckHelper::CheckObjectEntity( const Symbol &symbol, const ObjectEntityDetails &details) { CheckSymbolType(symbol); CheckArraySpec(symbol, details.shape()); + CheckConflicting(symbol, Attr::ALLOCATABLE, Attr::PARAMETER); + CheckConflicting(symbol, Attr::ASYNCHRONOUS, Attr::PARAMETER); + CheckConflicting(symbol, Attr::SAVE, Attr::PARAMETER); + CheckConflicting(symbol, Attr::TARGET, Attr::PARAMETER); + CheckConflicting(symbol, Attr::VOLATILE, Attr::PARAMETER); Check(details.shape()); Check(details.coshape()); if (details.shape().Rank() > common::maxRank) { @@ -2341,7 +2346,14 @@ void CheckHelper::CheckProcBinding( "Intrinsic procedure '%s' is not a specific intrinsic permitted for use in the definition of binding '%s'"_err_en_US, binding.symbol().name(), symbol.name()); } - if (const Symbol *overridden{FindOverriddenBinding(symbol)}) { + bool isInaccessibleDeferred{false}; + if (const Symbol * + overridden{FindOverriddenBinding(symbol, isInaccessibleDeferred)}) { + if (isInaccessibleDeferred) { + SayWithDeclaration(*overridden, + "Override of PRIVATE DEFERRED '%s' must appear in its module"_err_en_US, + symbol.name()); + } if (overridden->attrs().test(Attr::NON_OVERRIDABLE)) { SayWithDeclaration(*overridden, "Override of NON_OVERRIDABLE '%s' is not permitted"_err_en_US, diff --git a/flang/lib/Semantics/check-do-forall.cpp b/flang/lib/Semantics/check-do-forall.cpp index 4e8578d0e1daff72d8051cf17034e3a654d4d388..51f536f3d77231e26e8ce0a143faca47fb7aaf55 100644 --- a/flang/lib/Semantics/check-do-forall.cpp +++ b/flang/lib/Semantics/check-do-forall.cpp @@ -220,8 +220,11 @@ public: if (MightDeallocatePolymorphic(*entity, DeallocateNonCoarray)) { SayDeallocateOfPolymorph(variable.GetSource(), *entity, reason); } - if (const Symbol * impure{HasImpureFinal(*entity)}) { - SayDeallocateWithImpureFinal(*entity, reason, *impure); + if (const auto *assignment{GetAssignment(stmt)}) { + const auto &lhs{assignment->lhs}; + if (const Symbol * impure{HasImpureFinal(*entity, lhs.Rank())}) { + SayDeallocateWithImpureFinal(*entity, reason, *impure); + } } } if (const auto *assignment{GetAssignment(stmt)}) { @@ -435,6 +438,18 @@ public: CheckForallIndexesUsed(*assignment); CheckForImpureCall(assignment->lhs); CheckForImpureCall(assignment->rhs); + + if (IsVariable(assignment->lhs)) { + if (const Symbol * symbol{GetLastSymbol(assignment->lhs)}) { + if (auto impureFinal{ + HasImpureFinal(*symbol, assignment->lhs.Rank())}) { + context_.SayWithDecl(*symbol, parser::FindSourceLocation(stmt), + "Impure procedure '%s' is referenced by finalization in a %s"_err_en_US, + impureFinal->name(), LoopKindName()); + } + } + } + if (const auto *proc{ std::get_if<evaluate::ProcedureRef>(&assignment->u)}) { CheckForImpureCall(*proc); diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 54101ab8a42bbf319e5ffd3e896b2af483ed2a89..bf4debee1df34cb6c716ad4dfb755feffce27f46 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -2948,7 +2948,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::UseDevicePtr &x) { if (name->symbol) { if (!(IsBuiltinCPtr(*(name->symbol)))) { context_.Say(itr->second->source, - "'%s' in USE_DEVICE_PTR clause must be of type C_PTR"_err_en_US, + "Use of non-C_PTR type '%s' in USE_DEVICE_PTR is deprecated, use USE_DEVICE_ADDR instead"_warn_en_US, name->ToString()); } else { useDevicePtrNameList.push_back(*name); diff --git a/flang/lib/Semantics/data-to-inits.cpp b/flang/lib/Semantics/data-to-inits.cpp index fa22d4986790534fede6851d1d9dc5f698b382e4..2ebc4e561a339a930728c1177b06a2b955932f4c 100644 --- a/flang/lib/Semantics/data-to-inits.cpp +++ b/flang/lib/Semantics/data-to-inits.cpp @@ -118,9 +118,10 @@ private: bool Scan(const parser::DataIDoObject &); // Initializes all elements of a designator, which can be an array or section. - bool InitDesignator(const SomeExpr &); + bool InitDesignator(const SomeExpr &, const Scope &); // Initializes a single scalar object. - bool InitElement(const evaluate::OffsetSymbol &, const SomeExpr &designator); + bool InitElement(const evaluate::OffsetSymbol &, const SomeExpr &designator, + const Scope &); // If the returned flag is true, emit a warning about CHARACTER misusage. std::optional<std::pair<SomeExpr, bool>> ConvertElement( const SomeExpr &, const evaluate::DynamicType &); @@ -128,7 +129,6 @@ private: DataInitializations &inits_; evaluate::ExpressionAnalyzer &exprAnalyzer_; ValueListIterator<DSV> values_; - const Scope *scope_{nullptr}; }; template <typename DSV> @@ -149,8 +149,7 @@ bool DataInitializationCompiler<DSV>::Scan(const parser::Variable &var) { if (const auto *expr{GetExpr(exprAnalyzer_.context(), var)}) { parser::CharBlock at{var.GetSource()}; exprAnalyzer_.GetFoldingContext().messages().SetLocation(at); - scope_ = &exprAnalyzer_.context().FindScope(at); - if (InitDesignator(*expr)) { + if (InitDesignator(*expr, exprAnalyzer_.context().FindScope(at))) { return true; } } @@ -170,8 +169,7 @@ bool DataInitializationCompiler<DSV>::Scan( if (expr) { parser::CharBlock at{parser::FindSourceLocation(designator)}; exprAnalyzer_.GetFoldingContext().messages().SetLocation(at); - scope_ = &exprAnalyzer_.context().FindScope(at); - if (InitDesignator(*expr)) { + if (InitDesignator(*expr, exprAnalyzer_.context().FindScope(at))) { return true; } } @@ -254,12 +252,12 @@ template <typename DSV> bool DataInitializationCompiler<DSV>::Scan(const Symbol &symbol) { auto designator{exprAnalyzer_.Designate(evaluate::DataRef{symbol})}; CHECK(designator.has_value()); - return InitDesignator(*designator); + return InitDesignator(*designator, symbol.owner()); } template <typename DSV> bool DataInitializationCompiler<DSV>::InitDesignator( - const SomeExpr &designator) { + const SomeExpr &designator, const Scope &scope) { evaluate::FoldingContext &context{exprAnalyzer_.GetFoldingContext()}; evaluate::DesignatorFolder folder{context}; while (auto offsetSymbol{folder.FoldDesignator(designator)}) { @@ -274,7 +272,7 @@ bool DataInitializationCompiler<DSV>::InitDesignator( designator.AsFortran()); } return false; - } else if (!InitElement(*offsetSymbol, designator)) { + } else if (!InitElement(*offsetSymbol, designator, scope)) { return false; } else { ++values_; @@ -314,7 +312,8 @@ DataInitializationCompiler<DSV>::ConvertElement( template <typename DSV> bool DataInitializationCompiler<DSV>::InitElement( - const evaluate::OffsetSymbol &offsetSymbol, const SomeExpr &designator) { + const evaluate::OffsetSymbol &offsetSymbol, const SomeExpr &designator, + const Scope &scope) { const Symbol &symbol{offsetSymbol.symbol()}; const Symbol *lastSymbol{GetLastSymbol(designator)}; bool isPointer{lastSymbol && IsPointer(*lastSymbol)}; @@ -390,7 +389,7 @@ bool DataInitializationCompiler<DSV>::InitElement( } else if (isProcPointer) { if (evaluate::IsProcedure(*expr)) { if (CheckPointerAssignment(exprAnalyzer_.context(), designator, *expr, - DEREF(scope_), + scope, /*isBoundsRemapping=*/false, /*isAssumedRank=*/false)) { if (lastSymbol->has<ProcEntityDetails>()) { GetImage().AddPointer(offsetSymbol.offset(), *expr); @@ -413,7 +412,7 @@ bool DataInitializationCompiler<DSV>::InitElement( "Procedure '%s' may not be used to initialize '%s', which is not a procedure pointer"_err_en_US, expr->AsFortran(), DescribeElement()); } else if (CheckInitialDataPointerTarget( - exprAnalyzer_.context(), designator, *expr, DEREF(scope_))) { + exprAnalyzer_.context(), designator, *expr, scope)) { GetImage().AddPointer(offsetSymbol.offset(), *expr); return true; } diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index 54bfe0f2e1563db9485e671d8dd177f17f78368e..6af86de9dd81cbd0f7936a52828649c962bb7cf6 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -875,8 +875,11 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::CharLiteralConstant &x) { MaybeExpr ExpressionAnalyzer::Analyze( const parser::HollerithLiteralConstant &x) { int kind{GetDefaultKind(TypeCategory::Character)}; - auto value{x.v}; - return AnalyzeString(std::move(value), kind); + auto result{AnalyzeString(std::string{x.v}, kind)}; + if (auto *constant{UnwrapConstantValue<Ascii>(result)}) { + constant->set_wasHollerith(true); + } + return result; } // .TRUE. and .FALSE. of various kinds @@ -1299,7 +1302,8 @@ static NamedEntity IgnoreAnySubscripts(Designator<SomeDerived> &&designator) { std::move(designator.u)); } -// Components of parent derived types are explicitly represented as such. +// Components, but not bindings, of parent derived types are explicitly +// represented as such. std::optional<Component> ExpressionAnalyzer::CreateComponent(DataRef &&base, const Symbol &component, const semantics::Scope &scope, bool C919bAlreadyEnforced) { @@ -1307,7 +1311,8 @@ std::optional<Component> ExpressionAnalyzer::CreateComponent(DataRef &&base, base.Rank() > 0) { // C919b Say("An allocatable or pointer component reference must be applied to a scalar base"_err_en_US); } - if (&component.owner() == &scope) { + if (&component.owner() == &scope || + component.has<semantics::ProcBindingDetails>()) { return Component{std::move(base), component}; } if (const Symbol *typeSymbol{scope.GetSymbol()}) { diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp index b4df7216a33e207024f3a35849f65be438c22314..5d0d210fa3487d3452befbf218db570aeb8f068a 100644 --- a/flang/lib/Semantics/mod-file.cpp +++ b/flang/lib/Semantics/mod-file.cpp @@ -1242,7 +1242,7 @@ static void GetModuleDependences( std::size_t limit{content.size()}; std::string_view str{content.data(), limit}; for (std::size_t j{ModHeader::len}; - str.substr(j, ModHeader::needLen) == ModHeader::need;) { + str.substr(j, ModHeader::needLen) == ModHeader::need; ++j) { j += 7; auto checkSum{ExtractCheckSum(str.substr(j, ModHeader::sumLen))}; if (!checkSum) { @@ -1260,8 +1260,8 @@ static void GetModuleDependences( for (; j < limit && str.at(j) != '\n'; ++j) { } if (j > start && j < limit && str.at(j) == '\n') { - dependences.AddDependence( - std::string{str.substr(start, j - start)}, intrinsic, *checkSum); + std::string depModName{str.substr(start, j - start)}; + dependences.AddDependence(std::move(depModName), intrinsic, *checkSum); } else { break; } @@ -1271,7 +1271,7 @@ static void GetModuleDependences( Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic, Scope *ancestor, bool silent) { std::string ancestorName; // empty for module - Symbol *notAModule{nullptr}; + const Symbol *notAModule{nullptr}; bool fatalError{false}; if (ancestor) { if (auto *scope{ancestor->FindSubmodule(name)}) { @@ -1287,26 +1287,28 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic, if (it != context_.globalScope().end()) { Scope *scope{it->second->scope()}; if (scope->kind() == Scope::Kind::Module) { - if (requiredHash) { - if (const Symbol * foundModule{scope->symbol()}) { - if (const auto *module{foundModule->detailsIf<ModuleDetails>()}; - module && module->moduleFileHash() && - *requiredHash != *module->moduleFileHash()) { - Say(name, ancestorName, - "Multiple versions of the module '%s' cannot be required by the same compilation"_err_en_US, - name.ToString()); - return nullptr; + for (const Symbol *found{scope->symbol()}; found;) { + if (const auto *module{found->detailsIf<ModuleDetails>()}) { + if (!requiredHash || + *requiredHash == + module->moduleFileHash().value_or(*requiredHash)) { + return const_cast<Scope *>(found->scope()); } + found = module->previous(); // same name, distinct hash + } else { + notAModule = found; + break; } } - return scope; } else { notAModule = scope->symbol(); - // USE, NON_INTRINSIC global name isn't a module? - fatalError = isIntrinsic.has_value(); } } } + if (notAModule) { + // USE, NON_INTRINSIC global name isn't a module? + fatalError = isIntrinsic.has_value(); + } auto path{ModFileName(name, ancestorName, context_.moduleFileSuffix())}; parser::Parsing parsing{context_.allCookedSources()}; parser::Options options; @@ -1360,42 +1362,18 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic, // Look for the right module file if its hash is known if (requiredHash && !fatalError) { - std::vector<std::string> misses; for (const std::string &maybe : parser::LocateSourceFileAll(path, options.searchDirectories)) { if (const auto *srcFile{context_.allCookedSources().allSources().OpenPath( maybe, llvm::errs())}) { - if (auto checkSum{VerifyHeader(srcFile->content())}) { - if (*checkSum == *requiredHash) { - path = maybe; - if (!misses.empty()) { - auto &msg{context_.Say(name, - "Module file for '%s' appears later in the module search path than conflicting modules with different checksums"_warn_en_US, - name.ToString())}; - for (const std::string &m : misses) { - msg.Attach( - name, "Module file with a conflicting name: '%s'"_en_US, m); - } - } - misses.clear(); - break; - } else { - misses.emplace_back(maybe); - } + if (auto checkSum{VerifyHeader(srcFile->content())}; + checkSum && *checkSum == *requiredHash) { + path = maybe; + break; } } } - if (!misses.empty()) { - auto &msg{Say(name, ancestorName, - "Could not find a module file for '%s' in the module search path with the expected checksum"_err_en_US, - name.ToString())}; - for (const std::string &m : misses) { - msg.Attach(name, "Module file with different checksum: '%s'"_en_US, m); - } - return nullptr; - } } - const auto *sourceFile{fatalError ? nullptr : parsing.Prescan(path, options)}; if (fatalError || parsing.messages().AnyFatalError()) { if (!silent) { @@ -1451,11 +1429,24 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic, Scope &topScope{isIntrinsic.value_or(false) ? context_.intrinsicModulesScope() : context_.globalScope()}; Symbol *moduleSymbol{nullptr}; + const Symbol *previousModuleSymbol{nullptr}; if (!ancestor) { // module, not submodule parentScope = &topScope; auto pair{parentScope->try_emplace(name, UnknownDetails{})}; if (!pair.second) { - return nullptr; + // There is already a global symbol or intrinsic module of the same name. + previousModuleSymbol = &*pair.first->second; + if (const auto *details{ + previousModuleSymbol->detailsIf<ModuleDetails>()}) { + if (!details->moduleFileHash().has_value()) { + return nullptr; + } + } else { + return nullptr; + } + CHECK(parentScope->erase(name) != 0); + pair = parentScope->try_emplace(name, UnknownDetails{}); + CHECK(pair.second); } moduleSymbol = &*pair.first->second; moduleSymbol->set(Symbol::Flag::ModFile); @@ -1486,7 +1477,9 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic, } if (moduleSymbol) { CHECK(moduleSymbol->test(Symbol::Flag::ModFile)); - moduleSymbol->get<ModuleDetails>().set_moduleFileHash(checkSum.value()); + auto &details{moduleSymbol->get<ModuleDetails>()}; + details.set_moduleFileHash(checkSum.value()); + details.set_previous(previousModuleSymbol); if (isIntrinsic.value_or(false)) { moduleSymbol->attrs().set(Attr::INTRINSIC); } diff --git a/flang/lib/Semantics/pointer-assignment.cpp b/flang/lib/Semantics/pointer-assignment.cpp index 58155a29da1ee53840b6b16b9d39d5ed7285d8e6..4b4ce153084d8e7157028a9c8494d1eb9763aeb3 100644 --- a/flang/lib/Semantics/pointer-assignment.cpp +++ b/flang/lib/Semantics/pointer-assignment.cpp @@ -266,7 +266,7 @@ bool PointerAssignmentChecker::Check(const evaluate::FunctionRef<T> &f) { } else if (isContiguous_ && !funcResult->attrs.test(FunctionResult::Attr::Contiguous)) { msg = "CONTIGUOUS %s is associated with the result of reference to" - " function '%s' that is not contiguous"_err_en_US; + " function '%s' that is not known to be contiguous"_warn_en_US; } else if (lhsType_) { const auto *frTypeAndShape{funcResult->GetTypeAndShape()}; CHECK(frTypeAndShape); diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 215a3c9060a241a001ebad18141286eda7d50665..27af192f606be9ef8743cb940c4f68409622e119 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -487,6 +487,9 @@ public: const auto namePair{ currScope().try_emplace(name->source, Attrs{}, ProcEntityDetails{})}; auto &newSymbol{*namePair.first->second}; + if (context_.intrinsics().IsIntrinsic(name->ToString())) { + newSymbol.attrs().set(Attr::INTRINSIC); + } name->symbol = &newSymbol; }; if (const auto *procD{parser::Unwrap<parser::ProcedureDesignator>(opr.u)}) { @@ -1646,6 +1649,15 @@ void OmpAttributeVisitor::ResolveSeqLoopIndexInParallelOrTaskConstruct( break; } } + // If this symbol already has a data-sharing attribute then there is nothing + // to do here. + if (const Symbol * symbol{iv.symbol}) { + for (auto symMap : targetIt->objectWithDSA) { + if (symMap.first->name() == symbol->name()) { + return; + } + } + } // If this symbol is already Private or Firstprivate in the enclosing // OpenMP parallel or task then there is nothing to do here. if (auto *symbol{targetIt->scope.FindSymbol(iv.source)}) { diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 67392a02cf1862e0c225d1b69cb4890653ed63e6..2e88a2daff2c0823c70504bbba6ec6e46b5ada15 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -955,7 +955,7 @@ public: void Post(const parser::TargetStmt &) { objectDeclAttr_ = std::nullopt; } void Post(const parser::DimensionStmt::Declaration &); void Post(const parser::CodimensionDecl &); - bool Pre(const parser::TypeDeclarationStmt &) { return BeginDecl(); } + bool Pre(const parser::TypeDeclarationStmt &); void Post(const parser::TypeDeclarationStmt &); void Post(const parser::IntegerTypeSpec &); void Post(const parser::IntrinsicTypeSpec::Real &); @@ -1202,6 +1202,7 @@ private: bool MustBeScalar(const Symbol &symbol) const { return mustBeScalar_.find(symbol) != mustBeScalar_.end(); } + void DeclareIntrinsic(const parser::Name &); }; // Resolve construct entities and statement entities. @@ -3391,12 +3392,25 @@ void ModuleVisitor::ApplyDefaultAccess() { const auto *moduleDetails{ DEREF(currScope().symbol()).detailsIf<ModuleDetails>()}; CHECK(moduleDetails); + Attr defaultAttr{ + DEREF(moduleDetails).isDefaultPrivate() ? Attr::PRIVATE : Attr::PUBLIC}; for (auto &pair : currScope()) { Symbol &symbol{*pair.second}; if (!symbol.attrs().HasAny({Attr::PUBLIC, Attr::PRIVATE})) { - SetImplicitAttr(symbol, - DEREF(moduleDetails).isDefaultPrivate() ? Attr::PRIVATE - : Attr::PUBLIC); + Attr attr{defaultAttr}; + if (auto *generic{symbol.detailsIf<GenericDetails>()}) { + if (generic->derivedType()) { + // If a generic interface has a derived type of the same + // name that has an explicit accessibility attribute, then + // the generic must have the same accessibility. + if (generic->derivedType()->attrs().test(Attr::PUBLIC)) { + attr = Attr::PUBLIC; + } else if (generic->derivedType()->attrs().test(Attr::PRIVATE)) { + attr = Attr::PRIVATE; + } + } + } + SetImplicitAttr(symbol, attr); } } } @@ -4419,7 +4433,7 @@ Symbol &SubprogramVisitor::PushSubprogramScope(const parser::Name &name, CHECK(context().HasError(genericSymbol)); } } - set_inheritFromParent(false); + set_inheritFromParent(hasModulePrefix); } if (Symbol * found{FindSymbol(name)}; found && found->has<HostAssocDetails>()) { @@ -4537,6 +4551,20 @@ void DeclarationVisitor::CheckAccessibility( } } +bool DeclarationVisitor::Pre(const parser::TypeDeclarationStmt &x) { + BeginDecl(); + // If INTRINSIC appears as an attr-spec, handle it now as if the + // names had appeared on an INTRINSIC attribute statement beforehand. + for (const auto &attr : std::get<std::list<parser::AttrSpec>>(x.t)) { + if (std::holds_alternative<parser::Intrinsic>(attr.u)) { + for (const auto &decl : std::get<std::list<parser::EntityDecl>>(x.t)) { + DeclareIntrinsic(parser::GetFirstName(decl)); + } + break; + } + } + return true; +} void DeclarationVisitor::Post(const parser::TypeDeclarationStmt &) { EndDecl(); } @@ -4558,6 +4586,7 @@ bool DeclarationVisitor::Pre(const parser::Initialization &) { void DeclarationVisitor::Post(const parser::EntityDecl &x) { const auto &name{std::get<parser::ObjectName>(x.t)}; Attrs attrs{attrs_ ? HandleSaveName(name.source, *attrs_) : Attrs{}}; + attrs.set(Attr::INTRINSIC, false); // dealt with in Pre(TypeDeclarationStmt) Symbol &symbol{DeclareUnknownEntity(name, attrs)}; symbol.ReplaceName(name.source); SetCUDADataAttr(name.source, symbol, cudaDataAttr()); @@ -4633,23 +4662,23 @@ bool DeclarationVisitor::Pre(const parser::OldParameterStmt &x) { bool DeclarationVisitor::Pre(const parser::NamedConstantDef &x) { auto &name{std::get<parser::NamedConstant>(x.t).v}; auto &symbol{HandleAttributeStmt(Attr::PARAMETER, name)}; - if (!ConvertToObjectEntity(symbol) || - symbol.test(Symbol::Flag::CrayPointer) || + ConvertToObjectEntity(symbol); + auto *details{symbol.detailsIf<ObjectEntityDetails>()}; + if (!details || symbol.test(Symbol::Flag::CrayPointer) || symbol.test(Symbol::Flag::CrayPointee)) { SayWithDecl( name, symbol, "PARAMETER attribute not allowed on '%s'"_err_en_US); return false; } const auto &expr{std::get<parser::ConstantExpr>(x.t)}; - auto &details{symbol.get<ObjectEntityDetails>()}; - if (details.init() || symbol.test(Symbol::Flag::InDataStmt)) { + if (details->init() || symbol.test(Symbol::Flag::InDataStmt)) { Say(name, "Named constant '%s' already has a value"_err_en_US); } if (inOldStyleParameterStmt_) { // non-standard extension PARAMETER statement (no parentheses) Walk(expr); auto folded{EvaluateExpr(expr)}; - if (details.type()) { + if (details->type()) { SayWithDecl(name, symbol, "Alternative style PARAMETER '%s' must not already have an explicit type"_err_en_US); } else if (folded) { @@ -4661,9 +4690,9 @@ bool DeclarationVisitor::Pre(const parser::NamedConstantDef &x) { } else if (auto shape{ToArraySpec( GetFoldingContext(), evaluate::GetShape(*folded))}) { // The type of the named constant is assumed from the expression. - details.set_type(*type); - details.set_init(std::move(*folded)); - details.set_shape(std::move(*shape)); + details->set_type(*type); + details->set_init(std::move(*folded)); + details->set_shape(std::move(*shape)); } else { Say(at, "The expression must have constant shape"_err_en_US); } @@ -4680,7 +4709,7 @@ bool DeclarationVisitor::Pre(const parser::NamedConstantDef &x) { Walk(expr); if (auto converted{EvaluateNonPointerInitializer( symbol, expr, expr.thing.value().source)}) { - details.set_init(std::move(*converted)); + details->set_init(std::move(*converted)); } } return false; @@ -4798,45 +4827,47 @@ bool DeclarationVisitor::Pre(const parser::IntentStmt &x) { HandleAttributeStmt(IntentSpecToAttr(intentSpec), names); } bool DeclarationVisitor::Pre(const parser::IntrinsicStmt &x) { - HandleAttributeStmt(Attr::INTRINSIC, x.v); for (const auto &name : x.v) { - if (!IsIntrinsic(name.source, std::nullopt)) { - Say(name.source, "'%s' is not a known intrinsic procedure"_err_en_US); - } - auto &symbol{DEREF(FindSymbol(name))}; - if (symbol.has<GenericDetails>()) { - // Generic interface is extending intrinsic; ok - } else if (!ConvertToProcEntity(symbol)) { - SayWithDecl( - name, symbol, "INTRINSIC attribute not allowed on '%s'"_err_en_US); - } else if (symbol.attrs().test(Attr::EXTERNAL)) { // C840 + DeclareIntrinsic(name); + } + return false; +} +void DeclarationVisitor::DeclareIntrinsic(const parser::Name &name) { + HandleAttributeStmt(Attr::INTRINSIC, name); + if (!IsIntrinsic(name.source, std::nullopt)) { + Say(name.source, "'%s' is not a known intrinsic procedure"_err_en_US); + } + auto &symbol{DEREF(FindSymbol(name))}; + if (symbol.has<GenericDetails>()) { + // Generic interface is extending intrinsic; ok + } else if (!ConvertToProcEntity(symbol)) { + SayWithDecl( + name, symbol, "INTRINSIC attribute not allowed on '%s'"_err_en_US); + } else if (symbol.attrs().test(Attr::EXTERNAL)) { // C840 + Say(symbol.name(), + "Symbol '%s' cannot have both EXTERNAL and INTRINSIC attributes"_err_en_US, + symbol.name()); + } else { + if (symbol.GetType()) { + // These warnings are worded so that they should make sense in either + // order. Say(symbol.name(), - "Symbol '%s' cannot have both EXTERNAL and INTRINSIC attributes"_err_en_US, - symbol.name()); - } else { - if (symbol.GetType()) { - // These warnings are worded so that they should make sense in either - // order. - Say(symbol.name(), - "Explicit type declaration ignored for intrinsic function '%s'"_warn_en_US, - symbol.name()) - .Attach(name.source, - "INTRINSIC statement for explicitly-typed '%s'"_en_US, - name.source); - } - if (!symbol.test(Symbol::Flag::Function) && - !symbol.test(Symbol::Flag::Subroutine)) { - if (context().intrinsics().IsIntrinsicFunction( - name.source.ToString())) { - symbol.set(Symbol::Flag::Function); - } else if (context().intrinsics().IsIntrinsicSubroutine( - name.source.ToString())) { - symbol.set(Symbol::Flag::Subroutine); - } + "Explicit type declaration ignored for intrinsic function '%s'"_warn_en_US, + symbol.name()) + .Attach(name.source, + "INTRINSIC statement for explicitly-typed '%s'"_en_US, + name.source); + } + if (!symbol.test(Symbol::Flag::Function) && + !symbol.test(Symbol::Flag::Subroutine)) { + if (context().intrinsics().IsIntrinsicFunction(name.source.ToString())) { + symbol.set(Symbol::Flag::Function); + } else if (context().intrinsics().IsIntrinsicSubroutine( + name.source.ToString())) { + symbol.set(Symbol::Flag::Subroutine); } } } - return false; } bool DeclarationVisitor::Pre(const parser::OptionalStmt &x) { return CheckNotInBlock("OPTIONAL") && // C1107 diff --git a/flang/lib/Semantics/runtime-type-info.cpp b/flang/lib/Semantics/runtime-type-info.cpp index 9845a190bc756cd545fbdfffac5e5f2c51bcc71d..15ea34c66dba52921dea013f0460195ba381a39a 100644 --- a/flang/lib/Semantics/runtime-type-info.cpp +++ b/flang/lib/Semantics/runtime-type-info.cpp @@ -1239,6 +1239,16 @@ void RuntimeTableBuilder::IncorporateDefinedIoGenericInterfaces( RuntimeDerivedTypeTables BuildRuntimeDerivedTypeTables( SemanticsContext &context) { RuntimeDerivedTypeTables result; + // Do not attempt to read __fortran_type_info.mod when compiling + // the module on which it depends. + const auto &allSources{context.allCookedSources().allSources()}; + if (auto firstProv{allSources.GetFirstFileProvenance()}) { + if (const auto *srcFile{allSources.GetSourceFile(firstProv->start())}) { + if (srcFile->path().find("__fortran_builtins.f90") != std::string::npos) { + return result; + } + } + } result.schemata = context.GetBuiltinModule(typeInfoBuiltinModule); if (result.schemata) { RuntimeTableBuilder builder{context, result}; diff --git a/flang/lib/Semantics/tools.cpp b/flang/lib/Semantics/tools.cpp index bf999b090419c631ad2247445913e8970789edc4..df435906af68d00e1542a16f1e4630515631a4c8 100644 --- a/flang/lib/Semantics/tools.cpp +++ b/flang/lib/Semantics/tools.cpp @@ -403,6 +403,18 @@ const Symbol &BypassGeneric(const Symbol &symbol) { return symbol; } +const Symbol &GetCrayPointer(const Symbol &crayPointee) { + const Symbol *found{nullptr}; + for (const auto &[pointee, pointer] : + crayPointee.GetUltimate().owner().crayPointers()) { + if (pointee == crayPointee.name()) { + found = &pointer.get(); + break; + } + } + return DEREF(found); +} + bool ExprHasTypeCategory( const SomeExpr &expr, const common::TypeCategory &type) { auto dynamicType{expr.GetType()}; @@ -516,7 +528,9 @@ const Symbol *FindSubprogram(const Symbol &symbol) { symbol.details()); } -const Symbol *FindOverriddenBinding(const Symbol &symbol) { +const Symbol *FindOverriddenBinding( + const Symbol &symbol, bool &isInaccessibleDeferred) { + isInaccessibleDeferred = false; if (symbol.has<ProcBindingDetails>()) { if (const DeclTypeSpec * parentType{FindParentTypeSpec(symbol.owner())}) { if (const DerivedTypeSpec * parentDerived{parentType->AsDerived()}) { @@ -525,8 +539,11 @@ const Symbol *FindOverriddenBinding(const Symbol &symbol) { overridden{parentScope->FindComponent(symbol.name())}) { // 7.5.7.3 p1: only accessible bindings are overridden if (!overridden->attrs().test(Attr::PRIVATE) || - (FindModuleContaining(overridden->owner()) == - FindModuleContaining(symbol.owner()))) { + FindModuleContaining(overridden->owner()) == + FindModuleContaining(symbol.owner())) { + return overridden; + } else if (overridden->attrs().test(Attr::DEFERRED)) { + isInaccessibleDeferred = true; return overridden; } } @@ -827,15 +844,18 @@ static const Symbol *HasImpureFinal( return IsFinalizable(derived, nullptr, /*withImpureFinalizer=*/true, rank); } -const Symbol *HasImpureFinal(const Symbol &original) { +const Symbol *HasImpureFinal(const Symbol &original, std::optional<int> rank) { const Symbol &symbol{ResolveAssociations(original)}; if (symbol.has<ObjectEntityDetails>()) { if (const DeclTypeSpec * symType{symbol.GetType()}) { if (const DerivedTypeSpec * derived{symType->AsDerived()}) { - // finalizable assumed-rank not allowed (C839) - return evaluate::IsAssumedRank(symbol) - ? nullptr - : HasImpureFinal(*derived, symbol.Rank()); + if (evaluate::IsAssumedRank(symbol)) { + // finalizable assumed-rank not allowed (C839) + return nullptr; + } else { + int actualRank{rank.value_or(symbol.Rank())}; + return HasImpureFinal(*derived, actualRank); + } } } } @@ -1272,6 +1292,8 @@ static bool StopAtComponentPre(const Symbol &component) { return !IsPointer(component); } else if constexpr (componentKind == ComponentKind::PotentialAndPointer) { return true; + } else { + DIE("unexpected ComponentKind"); } } diff --git a/flang/module/__fortran_builtins.f90 b/flang/module/__fortran_builtins.f90 index 62b20103221ade2240021a7800dfde85049e77d4..3d3dbef6d018aa9b3ddfd8dccbc92ff7417fc434 100644 --- a/flang/module/__fortran_builtins.f90 +++ b/flang/module/__fortran_builtins.f90 @@ -110,7 +110,7 @@ module __fortran_builtins public :: operator(==) interface operator(/=) - module procedure __builtin_c_ptr_eq + module procedure __builtin_c_ptr_ne end interface public :: operator(/=) diff --git a/flang/module/omp_lib.f90 b/flang/module/omp_lib.f90 deleted file mode 100644 index 2ca15da6891591bb3115be2c1a3d8d324b73f020..0000000000000000000000000000000000000000 --- a/flang/module/omp_lib.f90 +++ /dev/null @@ -1,13 +0,0 @@ -!===-- module/omp_lib.f90 --------------------------------------------------===! -! -! 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 -! -!===------------------------------------------------------------------------===! - -module omp_lib - -include "omp_lib.h" - -end module omp_lib diff --git a/flang/module/omp_lib.h b/flang/module/omp_lib.h deleted file mode 100644 index efc9ceb16968bbf3ef67ab7555466b3e81c50069..0000000000000000000000000000000000000000 --- a/flang/module/omp_lib.h +++ /dev/null @@ -1,454 +0,0 @@ -!===-- module/omp_lib.h ------------------------------------------*- F90 -*-===! -! -! 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 -! -!===------------------------------------------------------------------------===! - -!dir$ free - - integer, parameter :: omp_integer_kind = selected_int_kind(9) ! 32-bit int - integer, parameter :: omp_logical_kind = 1 ! C_BOOL - - integer, parameter :: omp_sched_kind = omp_integer_kind - integer, parameter :: omp_proc_bind_kind = omp_integer_kind - integer, parameter :: omp_pause_resource_kind = omp_integer_kind - integer, parameter :: omp_sync_hint_kind = omp_integer_kind - integer, parameter :: omp_lock_hint_kind = omp_sync_hint_kind - integer, parameter :: omp_event_handle_kind = omp_integer_kind - integer, parameter :: omp_alloctrait_key_kind = omp_integer_kind - integer, parameter :: omp_alloctrait_val_kind = omp_integer_kind - integer, parameter :: omp_allocator_handle_kind = omp_integer_kind - integer, parameter :: omp_memspace_handle_kind = omp_integer_kind - integer, parameter :: omp_lock_kind = int_ptr_kind() - integer, parameter :: omp_nest_lock_kind = int_ptr_kind() - integer, parameter :: omp_depend_kind = omp_integer_kind - - integer(kind=omp_sched_kind), parameter :: & - omp_sched_static = 1, & - omp_sched_dynamic = 2, & - omp_sched_guided = 3, & - omp_sched_auto = 4 - - integer(kind=omp_proc_bind_kind), parameter :: & - omp_proc_bind_false = 0, & - omp_proc_bind_true = 1, & - omp_proc_bind_master = 2, & - omp_proc_bind_close = 3, & - omp_proc_bind_spread = 4 - - integer(kind=omp_pause_resource_kind), parameter :: & - omp_pause_soft = 1, & - omp_pause_hard = 2 - - integer(kind=omp_sync_hint_kind), parameter :: & - omp_sync_hint_none = 0, & - omp_sync_hint_uncontended = 1, & - omp_sync_hint_contended = 2, & - omp_sync_hint_nonspeculative = 4, & - omp_sync_hint_speculative = 8 - integer(kind=omp_lock_hint_kind), parameter :: & - omp_lock_hint_none = omp_sync_hint_none, & - omp_lock_hint_uncontended = omp_sync_hint_uncontended, & - omp_lock_hint_contended = omp_sync_hint_contended, & - omp_lock_hint_nonspeculative = omp_sync_hint_nonspeculative, & - omp_lock_hint_speculative = omp_sync_hint_speculative - - integer(kind=omp_event_handle_kind), parameter :: & - omp_allow_completion_event = 0, & - omp_task_fulfill_event = 1 - - integer(kind=omp_alloctrait_key_kind), parameter :: & - omp_atk_sync_hint = 1, & - omp_atk_alignment = 2, & - omp_atk_access = 3, & - omp_atk_pool_size = 4, & - omp_atk_fallback = 5, & - omp_atk_fb_data = 6, & - omp_atk_pinned = 7, & - omp_atk_partition = 8 - - integer(kind=omp_alloctrait_val_kind), parameter :: & - omp_atv_false = 0, & - omp_atv_true = 1, & - omp_atv_default = 2, & - omp_atv_contended = 3, & - omp_atv_uncontended = 4, & - omp_atv_sequential = 5, & - omp_atv_private = 6, & - omp_atv_all = 7, & - omp_atv_thread = 8, & - omp_atv_pteam = 9, & - omp_atv_cgroup = 10, & - omp_atv_default_mem_fb = 11, & - omp_atv_null_fb = 12, & - omp_atv_abort_fb = 13, & - omp_atv_allocator_fb = 14, & - omp_atv_environment = 15, & - omp_atv_nearest = 16, & - omp_atv_blocked = 17, & - omp_atv_interleaved = 18 - - type, bind(c) :: omp_alloctrait - integer(kind=omp_alloctrait_key_kind) :: key, value - end type omp_alloctrait - - integer(kind=omp_allocator_handle_kind), parameter :: omp_null_allocator = 0 - - integer(kind=omp_memspace_handle_kind), parameter :: & - omp_default_mem_space = 0, & - omp_large_cap_mem_space = 0, & - omp_const_mem_space = 0, & - omp_high_bw_mem_space = 0, & - omp_low_lat_mem_space = 0, & - omp_default_mem_alloc = 1, & - omp_large_cap_mem_alloc = omp_default_mem_alloc, & - omp_const_mem_alloc = 1, & - omp_high_bw_mem_alloc = 1, & - omp_low_lat_mem_alloc = 1, & - omp_thread_mem_alloc = omp_atv_thread, & - omp_pteam_mem_alloc = omp_atv_pteam, & - omp_cgroup_mem_alloc = omp_atv_cgroup - - integer(kind=omp_integer_kind), parameter :: openmp_version = 200805 - - interface - - subroutine omp_set_num_threads(nthreads) bind(c) - import - integer(kind=omp_integer_kind), value :: nthreads - end subroutine omp_set_num_threads - - function omp_get_num_threads() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_num_threads - end function omp_get_num_threads - - function omp_get_max_threads() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_max_threads - end function omp_get_max_threads - - function omp_get_thread_num() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_thread_num - end function omp_get_thread_num - - function omp_get_num_procs() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_num_procs - end function omp_get_num_procs - - function omp_in_parallel() bind(c) - import - logical(kind=omp_logical_kind) :: omp_in_parallel - end function omp_in_parallel - - subroutine omp_set_dynamic(enable) bind(c) - import - logical(kind=omp_logical_kind), value :: enable - end subroutine omp_set_dynamic - - function omp_get_dynamic() bind(c) - import - logical(kind=omp_logical_kind) :: omp_get_dynamic - end function omp_get_dynamic - - function omp_get_cancelation() bind(c) - import - logical(kind=omp_logical_kind) :: omp_get_cancelation - end function omp_get_cancelation - - subroutine omp_set_nested(enable) bind(c) - import - logical(kind=omp_logical_kind), value :: enable - end subroutine omp_set_nested - - function omp_get_nested() bind(c) - import - logical(kind=omp_logical_kind) ::omp_get_nested - end function omp_get_nested - - subroutine omp_set_schedule(kind, modifier) bind(c) - import - integer(kind=omp_integer_kind), value :: kind, modifier - end subroutine omp_set_schedule - - subroutine omp_get_schedule(kind, modifier) bind(c) - import - integer(kind=omp_integer_kind), intent(out) :: kind, modifier - end subroutine omp_get_schedule - - function omp_get_thread_limit() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_thread_limit - end function omp_get_thread_limit - - function omp_get_supported_active_levels() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_supported_active_levels - end function omp_get_supported_active_levels - - subroutine omp_set_max_active_levels(max_levels) bind(c) - import - integer(kind=omp_integer_kind), value :: max_levels - end subroutine omp_set_max_active_levels - - function omp_get_max_active_levels() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_max_active_levels - end function omp_get_max_active_levels - - function omp_get_level() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_level - end function omp_get_level - - function omp_get_ancestor_thread_num(level) bind(c) - import - integer(kind=omp_integer_kind), value :: level - integer(kind=omp_integer_kind) :: omp_get_ancestor_thread_num - end function omp_get_ancestor_thread_num - - function omp_get_team_size(level) bind(c) - import - integer(kind=omp_integer_kind), value :: level - integer(kind=omp_integer_kind) :: omp_get_team_size - end function omp_get_team_size - - function omp_get_active_level() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_active_level - end function omp_get_active_level - - function omp_in_final() bind(c) - import - logical(kind=omp_logical_kind) :: omp_in_final - end function omp_in_final - - function omp_get_proc_bind() bind(c) - import - integer(kind=omp_proc_bind_kind) :: omp_get_proc_bind - end function omp_get_proc_bind - - function omp_get_num_places() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_num_places - end function omp_get_num_places - - function omp_get_place_num_procs(place_num) bind(c) - import - integer(kind=omp_integer_kind), value :: place_num - integer(kind=omp_integer_kind) omp_get_place_num_procs - end function omp_get_place_num_procs - - subroutine omp_get_place_proc_ids(place_num, ids) bind(c) - import - integer(kind=omp_integer_kind), value :: place_num - integer(kind=omp_integer_kind), intent(out) :: ids(*) - end subroutine omp_get_place_proc_ids - - function omp_get_place_num() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_place_num - end function omp_get_place_num - - function omp_get_partition_num_places() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_partition_num_places - end function omp_get_partition_num_places - - subroutine omp_get_partition_place_nums(place_nums) bind(c) - import - integer(kind=omp_integer_kind), intent(out) :: place_nums(*) - end subroutine omp_get_partition_place_nums - - subroutine omp_set_affinity_format(format) bind(c) - import - character(len=*), intent(in) :: format - end subroutine omp_set_affinity_format - - function omp_get_affinity_format(buffer) bind(c) - import - character(len=*), intent(out) :: buffer - integer(kind=omp_integer_kind) :: omp_get_affinity_format - end function omp_get_affinity_format - - subroutine omp_display_affinity(format) bind(c) - import - character(len=*), intent(in) :: format - end subroutine omp_display_affinity - - function omp_capture_affinity(buffer, format) bind(c) - import - character(len=*), intent(out) :: buffer - character(len=*), intent(in) :: format - integer(kind=omp_integer_kind) omp_capture_affinity - end function omp_capture_affinity - - subroutine omp_set_default_device(device_num) bind(c) - import - integer(kind=omp_integer_kind), value :: device_num - end subroutine omp_set_default_device - - function omp_get_default_device() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_default_device - end function omp_get_default_device - - function omp_get_num_devices() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_num_devices - end function omp_get_num_devices - - function omp_get_device_num() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_device_num - end function omp_get_device_num - - function omp_get_num_teams() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_num_teams - end function omp_get_num_teams - - function omp_get_team_num() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_team_num - end function omp_get_team_num - - function omp_is_initial_device() bind(c) - import - integer(kind=omp_logical_kind) :: omp_is_initial_device ! TODO: should this be LOGICAL? - end function omp_is_initial_device - - function omp_get_initial_device() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_initial_device - end function omp_get_initial_device - - function omp_get_max_task_priority() bind(c) - import - integer(kind=omp_integer_kind) :: omp_get_max_task_priority - end function omp_get_max_task_priority - - function omp_pause_resource(kind, device_num) bind(c) - import - integer(kind=omp_pause_resource_kind), value :: kind - integer(kind=omp_integer_kind), value :: device_num - integer(kind=omp_integer_kind) :: omp_pause_resource - end function omp_pause_resource - - function omp_pause_resource_all(kind) bind(c) - import - integer(kind=omp_pause_resource_kind), value :: kind - integer(kind=omp_integer_kind) :: omp_pause_resource_all - end function omp_pause_resource_all - -! Lock routines - subroutine omp_init_lock(lockvar) bind(c, name="omp_init_lock_") - import - integer(kind=omp_lock_kind), intent(out) :: lockvar - end subroutine omp_init_lock - - subroutine omp_init_lock_with_hint(lockvar, hint) bind(c, name="omp_init_lock_with_hint_") - import - integer(kind=omp_lock_kind), intent(out) :: lockvar - integer(kind=omp_sync_hint_kind), value :: hint - end subroutine omp_init_lock_with_hint - - subroutine omp_destroy_lock(lockvar) bind(c, name="omp_destroy_lock_") - import - integer(kind=omp_lock_kind), intent(inout) :: lockvar - end subroutine omp_destroy_lock - - subroutine omp_set_lock(lockvar) bind(c, name="omp_set_lock_") - import - integer(kind=omp_lock_kind), intent(inout) :: lockvar - end subroutine omp_set_lock - - subroutine omp_unset_lock(lockvar) bind(c, name="omp_unset_lock_") - import - integer(kind=omp_lock_kind), intent(inout) :: lockvar - end subroutine omp_unset_lock - - function omp_test_lock(lockvar) bind(c, name="omp_test_lock_") - import - integer(kind=omp_lock_kind), intent(inout) :: lockvar - logical(kind=omp_logical_kind) :: omp_test_lock - end function omp_test_lock - - subroutine omp_init_nest_lock(lockvar) bind(c, name="omp_init_nest_lock_") - import - integer(kind=omp_nest_lock_kind), intent(out) :: lockvar - end subroutine omp_init_nest_lock - - subroutine omp_init_nest_lock_with_hint(lockvar, hint) bind(c, name="omp_init_nest_lock_with_hint_") - import - integer(kind=omp_nest_lock_kind), intent(out) :: lockvar - integer(kind=omp_sync_hint_kind), value :: hint - end subroutine omp_init_nest_lock_with_hint - - subroutine omp_destroy_nest_lock(lockvar) bind(c, name="omp_destroy_nest_lock_") - import - integer(kind=omp_nest_lock_kind), intent(inout) :: lockvar - end subroutine omp_destroy_nest_lock - - subroutine omp_set_nest_lock(lockvar) bind(c, name="omp_set_nest_lock_") - import - integer(kind=omp_nest_lock_kind), intent(inout) :: lockvar - end subroutine omp_set_nest_lock - - subroutine omp_unset_nest_lock(lockvar) bind(c, name="omp_unset_nest_lock_") - import - integer(kind=omp_nest_lock_kind), intent(inout) :: lockvar - end subroutine omp_unset_nest_lock - - function omp_test_nest_lock(lockvar) bind(c, name="omp_test_nest_lock_") - import - integer(kind=omp_integer_kind) :: omp_test_nest_lock - integer(kind=omp_nest_lock_kind), intent(inout) :: lockvar - end function omp_test_nest_lock - -! Timing routines - function omp_get_wtime() bind(c) - double precision omp_get_wtime - end function omp_get_wtime - - function omp_get_wtick() bind(c) - double precision omp_get_wtick - end function omp_get_wtick - -! Event routine - subroutine omp_fullfill_event(event) bind(c) ! TODO: is this the correct spelling? - import - integer(kind=omp_event_handle_kind) :: event - end subroutine omp_fullfill_event - -! Device Memory Routines - -! Memory Management Routines - function omp_init_allocator(memspace, ntraits, traits) bind(c) - import - integer(kind=omp_memspace_handle_kind), value :: memspace - integer, value :: ntraits - type(omp_alloctrait), intent(in) :: traits(*) - integer(kind=omp_allocator_handle_kind) :: omp_init_allocator - end function omp_init_allocator - - subroutine omp_destroy_allocator(allocator) bind(c) - import - integer(kind=omp_allocator_handle_kind), value :: allocator - end subroutine omp_destroy_allocator - - subroutine omp_set_default_allocator(allocator) bind(c) - import - integer(kind=omp_allocator_handle_kind), value :: allocator - end subroutine omp_set_default_allocator - - function omp_get_default_allocator() bind(c) - import - integer(kind=omp_allocator_handle_kind) :: omp_get_default_allocator - end function omp_get_default_allocator - - end interface diff --git a/flang/runtime/CMakeLists.txt b/flang/runtime/CMakeLists.txt index 7dd60b5edcd5fbc09dec4713626affd5e01e9ccd..c0e4cff698e3cb1df9d609160873f8ca54a51f0e 100644 --- a/flang/runtime/CMakeLists.txt +++ b/flang/runtime/CMakeLists.txt @@ -129,6 +129,7 @@ set(sources exceptions.cpp execute.cpp extensions.cpp + external-unit.cpp extrema.cpp file.cpp findloc.cpp @@ -149,8 +150,10 @@ set(sources numeric.cpp pointer.cpp product.cpp + pseudo-unit.cpp ragged.cpp random.cpp + reduce.cpp reduction.cpp stat.cpp stop.cpp @@ -171,6 +174,7 @@ set(sources option(FLANG_EXPERIMENTAL_CUDA_RUNTIME "Compile Fortran runtime as CUDA sources (experimental)" OFF ) +set(FLANG_LIBCUDACXX_PATH "" CACHE PATH "Path to libcu++ package installation") # List of files that are buildable for all devices. set(supported_files @@ -178,22 +182,38 @@ set(supported_files allocatable.cpp array-constructor.cpp assign.cpp + buffer.cpp character.cpp + connection.cpp copy.cpp derived-api.cpp derived.cpp descriptor.cpp + descriptor-io.cpp dot-product.cpp + edit-input.cpp + edit-output.cpp + environment.cpp extrema.cpp + external-unit.cpp findloc.cpp + format.cpp inquiry.cpp + internal-unit.cpp + io-api.cpp + io-error.cpp + io-stmt.cpp + iostat.cpp matmul-transpose.cpp matmul.cpp memory.cpp misc-intrinsic.cpp + namelist.cpp + non-tbp-dio.cpp numeric.cpp pointer.cpp product.cpp + pseudo-unit.cpp ragged.cpp stat.cpp sum.cpp @@ -203,6 +223,8 @@ set(supported_files transformational.cpp type-code.cpp type-info.cpp + unit.cpp + utf.cpp ) if (FLANG_EXPERIMENTAL_CUDA_RUNTIME) @@ -239,6 +261,13 @@ if (FLANG_EXPERIMENTAL_CUDA_RUNTIME) set_source_files_properties(${supported_files} PROPERTIES COMPILE_OPTIONS "${CUDA_COMPILE_OPTIONS}" ) + + if (EXISTS "${FLANG_LIBCUDACXX_PATH}/include") + # When using libcudacxx headers files, we have to use them + # for all files of F18 runtime. + include_directories(AFTER ${FLANG_LIBCUDACXX_PATH}/include) + add_compile_definitions(RT_USE_LIBCUDACXX=1) + endif() endif() set(FLANG_EXPERIMENTAL_OMP_OFFLOAD_BUILD "off" CACHE STRING diff --git a/flang/runtime/Float128Math/CMakeLists.txt b/flang/runtime/Float128Math/CMakeLists.txt index 980356131b680e9f391a977ba6149347f863c4c2..a5f5bec1e7e4b84fee8f83bf2c01e489d54b3a47 100644 --- a/flang/runtime/Float128Math/CMakeLists.txt +++ b/flang/runtime/Float128Math/CMakeLists.txt @@ -33,6 +33,7 @@ set(sources exp.cpp exponent.cpp floor.cpp + fma.cpp fraction.cpp hypot.cpp j0.cpp @@ -48,6 +49,7 @@ set(sources nearest.cpp norm2.cpp pow.cpp + random.cpp round.cpp rrspacing.cpp scale.cpp diff --git a/flang/runtime/Float128Math/fma.cpp b/flang/runtime/Float128Math/fma.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ec67e8e6fba22b37c08a38154d1a13c7d0319f58 --- /dev/null +++ b/flang/runtime/Float128Math/fma.cpp @@ -0,0 +1,23 @@ +//===-- runtime/Float128Math/fma.cpp --------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "math-entries.h" + +namespace Fortran::runtime { +extern "C" { + +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +CppTypeFor<TypeCategory::Real, 16> RTDEF(FmaF128)( + CppTypeFor<TypeCategory::Real, 16> x, CppTypeFor<TypeCategory::Real, 16> y, + CppTypeFor<TypeCategory::Real, 16> z) { + return Fma<true>::invoke(x, y, z); +} +#endif + +} // extern "C" +} // namespace Fortran::runtime diff --git a/flang/runtime/Float128Math/math-entries.h b/flang/runtime/Float128Math/math-entries.h index 1eab7c86f2ed765df95a66c051267f336b626ddf..13fdab264700380eb053af8be50c6f979da5e67c 100644 --- a/flang/runtime/Float128Math/math-entries.h +++ b/flang/runtime/Float128Math/math-entries.h @@ -77,6 +77,7 @@ DEFINE_FALLBACK_F128(Erf) DEFINE_FALLBACK_F128(Erfc) DEFINE_FALLBACK_F128(Exp) DEFINE_FALLBACK_F128(Floor) +DEFINE_FALLBACK_F128(Fma) DEFINE_FALLBACK_F128(Frexp) DEFINE_FALLBACK_F128(Hypot) DEFINE_FALLBACK_I32(Ilogb) @@ -124,6 +125,7 @@ DEFINE_SIMPLE_ALIAS(Erf, erfq) DEFINE_SIMPLE_ALIAS(Erfc, erfcq) DEFINE_SIMPLE_ALIAS(Exp, expq) DEFINE_SIMPLE_ALIAS(Floor, floorq) +DEFINE_SIMPLE_ALIAS(Fma, fmaq) DEFINE_SIMPLE_ALIAS(Frexp, frexpq) DEFINE_SIMPLE_ALIAS(Hypot, hypotq) DEFINE_SIMPLE_ALIAS(Ilogb, ilogbq) @@ -177,6 +179,7 @@ DEFINE_SIMPLE_ALIAS(Erf, std::erf) DEFINE_SIMPLE_ALIAS(Erfc, std::erfc) DEFINE_SIMPLE_ALIAS(Exp, std::exp) DEFINE_SIMPLE_ALIAS(Floor, std::floor) +DEFINE_SIMPLE_ALIAS(Fma, std::fma) DEFINE_SIMPLE_ALIAS(Frexp, std::frexp) DEFINE_SIMPLE_ALIAS(Hypot, std::hypot) DEFINE_SIMPLE_ALIAS(Ilogb, std::ilogb) diff --git a/flang/runtime/Float128Math/random.cpp b/flang/runtime/Float128Math/random.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cda962b416144e573960012643bf8df30ae6a311 --- /dev/null +++ b/flang/runtime/Float128Math/random.cpp @@ -0,0 +1,23 @@ +//===-- runtime/Float128Math/random.cpp -----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "math-entries.h" +#include "numeric-template-specs.h" +#include "random-templates.h" + +using namespace Fortran::runtime::random; +extern "C" { + +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +void RTDEF(RandomNumber16)( + const Descriptor &harvest, const char *source, int line) { + return Generate<CppTypeFor<TypeCategory::Real, 16>, 113>(harvest); +} +#endif + +} // extern "C" diff --git a/flang/runtime/buffer.cpp b/flang/runtime/buffer.cpp index 15c83bfd249232d55fcaa46159521b4739820610..7b4869d69c2e5136b736e25f18339d306dd1b2ce 100644 --- a/flang/runtime/buffer.cpp +++ b/flang/runtime/buffer.cpp @@ -10,14 +10,20 @@ #include <algorithm> namespace Fortran::runtime::io { +RT_OFFLOAD_API_GROUP_BEGIN // Here's a very old trick for shifting circular buffer data cheaply // without a need for a temporary array. void LeftShiftBufferCircularly( char *buffer, std::size_t bytes, std::size_t shift) { // Assume that we start with "efgabcd" and the left shift is 3. + RT_DIAG_PUSH + RT_DIAG_DISABLE_CALL_HOST_FROM_DEVICE_WARN std::reverse(buffer, buffer + shift); // "gfeabcd" std::reverse(buffer, buffer + bytes); // "dcbaefg" std::reverse(buffer, buffer + bytes - shift); // "abcdefg" + RT_DIAG_POP } + +RT_OFFLOAD_API_GROUP_END } // namespace Fortran::runtime::io diff --git a/flang/runtime/buffer.h b/flang/runtime/buffer.h index 93fda36f500d31d076fd69434eef16c09e1b8e4f..ca1baea12efafa68a13f9772706e3033ad6a6954 100644 --- a/flang/runtime/buffer.h +++ b/flang/runtime/buffer.h @@ -11,6 +11,7 @@ #ifndef FORTRAN_RUNTIME_BUFFER_H_ #define FORTRAN_RUNTIME_BUFFER_H_ +#include "freestanding-tools.h" #include "io-error.h" #include "flang/Runtime/memory.h" #include <algorithm> @@ -19,7 +20,8 @@ namespace Fortran::runtime::io { -void LeftShiftBufferCircularly(char *, std::size_t bytes, std::size_t shift); +RT_API_ATTRS void LeftShiftBufferCircularly( + char *, std::size_t bytes, std::size_t shift); // Maintains a view of a contiguous region of a file in a memory buffer. // The valid data in the buffer may be circular, but any active frame @@ -48,22 +50,24 @@ template <typename STORE, std::size_t minBuffer = 65536> class FileFrame { public: using FileOffset = std::int64_t; - ~FileFrame() { FreeMemoryAndNullify(buffer_); } + RT_API_ATTRS ~FileFrame() { FreeMemoryAndNullify(buffer_); } // The valid data in the buffer begins at buffer_[start_] and proceeds // with possible wrap-around for length_ bytes. The current frame // is offset by frame_ bytes into that region and is guaranteed to // be contiguous for at least as many bytes as were requested. - FileOffset FrameAt() const { return fileOffset_ + frame_; } - char *Frame() const { return buffer_ + start_ + frame_; } - std::size_t FrameLength() const { + RT_API_ATTRS FileOffset FrameAt() const { return fileOffset_ + frame_; } + RT_API_ATTRS char *Frame() const { return buffer_ + start_ + frame_; } + RT_API_ATTRS std::size_t FrameLength() const { return std::min<std::size_t>(length_ - frame_, size_ - (start_ + frame_)); } - std::size_t BytesBufferedBeforeFrame() const { return frame_ - start_; } + RT_API_ATTRS std::size_t BytesBufferedBeforeFrame() const { + return frame_ - start_; + } // Returns a short frame at a non-fatal EOF. Can return a long frame as well. - std::size_t ReadFrame( + RT_API_ATTRS std::size_t ReadFrame( FileOffset at, std::size_t bytes, IoErrorHandler &handler) { Flush(handler); Reallocate(bytes, handler); @@ -92,7 +96,8 @@ public: return FrameLength(); } - void WriteFrame(FileOffset at, std::size_t bytes, IoErrorHandler &handler) { + RT_API_ATTRS void WriteFrame( + FileOffset at, std::size_t bytes, IoErrorHandler &handler) { Reallocate(bytes, handler); std::int64_t newFrame{at - fileOffset_}; if (!dirty_ || newFrame < 0 || newFrame > length_) { @@ -110,7 +115,7 @@ public: length_ = std::max<std::int64_t>(length_, frame_ + bytes); } - void Flush(IoErrorHandler &handler, std::int64_t keep = 0) { + RT_API_ATTRS void Flush(IoErrorHandler &handler, std::int64_t keep = 0) { if (dirty_) { while (length_ > keep) { std::size_t chunk{ @@ -128,7 +133,7 @@ public: } } - void TruncateFrame(std::int64_t at, IoErrorHandler &handler) { + RT_API_ATTRS void TruncateFrame(std::int64_t at, IoErrorHandler &handler) { RUNTIME_CHECK(handler, !dirty_); if (at <= fileOffset_) { Reset(at); @@ -138,9 +143,10 @@ public: } private: - STORE &Store() { return static_cast<STORE &>(*this); } + RT_API_ATTRS STORE &Store() { return static_cast<STORE &>(*this); } - void Reallocate(std::int64_t bytes, const Terminator &terminator) { + RT_API_ATTRS void Reallocate( + std::int64_t bytes, const Terminator &terminator) { if (bytes > size_) { char *old{buffer_}; auto oldSize{size_}; @@ -160,13 +166,14 @@ private: } } - void Reset(FileOffset at) { + RT_API_ATTRS void Reset(FileOffset at) { start_ = length_ = frame_ = 0; fileOffset_ = at; dirty_ = false; } - void DiscardLeadingBytes(std::int64_t n, const Terminator &terminator) { + RT_API_ATTRS void DiscardLeadingBytes( + std::int64_t n, const Terminator &terminator) { RUNTIME_CHECK(terminator, length_ >= n); length_ -= n; if (length_ == 0) { @@ -185,19 +192,20 @@ private: fileOffset_ += n; } - void MakeDataContiguous(IoErrorHandler &handler, std::size_t bytes) { + RT_API_ATTRS void MakeDataContiguous( + IoErrorHandler &handler, std::size_t bytes) { if (static_cast<std::int64_t>(start_ + bytes) > size_) { // Frame would wrap around; shift current data (if any) to force // contiguity. RUNTIME_CHECK(handler, length_ < size_); if (start_ + length_ <= size_) { // [......abcde..] -> [abcde........] - std::memmove(buffer_, buffer_ + start_, length_); + runtime::memmove(buffer_, buffer_ + start_, length_); } else { // [cde........ab] -> [abcde........] auto n{start_ + length_ - size_}; // 3 for cde RUNTIME_CHECK(handler, length_ >= n); - std::memmove(buffer_ + n, buffer_ + start_, length_ - n); // cdeab + runtime::memmove(buffer_ + n, buffer_ + start_, length_ - n); // cdeab LeftShiftBufferCircularly(buffer_, length_, n); // abcde } start_ = 0; diff --git a/flang/runtime/complex-reduction.c b/flang/runtime/complex-reduction.c index c91d12539911766d8aadf6ff87e4607f0216a812..7654de8080a152a9208e5e5be5a90420558bb8bc 100644 --- a/flang/runtime/complex-reduction.c +++ b/flang/runtime/complex-reduction.c @@ -155,3 +155,25 @@ ADAPT_REDUCTION(DotProductComplex10, long_double_Complex_t, ADAPT_REDUCTION(DotProductComplex16, CFloat128ComplexType, CppComplexFloat128, CMPLXF128, DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES) #endif + +/* REDUCE() */ +#define RARGS REDUCE_ARGS(float_Complex_t) +ADAPT_REDUCTION(ReduceComplex4, float_Complex_t, CppComplexFloat, CMPLXF, RARGS, + REDUCE_ARG_NAMES) +#undef RARGS +#define RARGS REDUCE_ARGS(double_Complex_t) +ADAPT_REDUCTION(ReduceComplex8, double_Complex_t, CppComplexDouble, CMPLX, + RARGS, REDUCE_ARG_NAMES) +#undef RARGS +#if LDBL_MANT_DIG == 64 +#define RARGS REDUCE_ARGS(long_double_Complex_t) +ADAPT_REDUCTION(ReduceComplex10, long_double_Complex_t, CppComplexLongDouble, + CMPLXL, RARGS, REDUCE_ARG_NAMES) +#undef RARGS +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +#define RARGS REDUCE_ARGS(CFloat128ComplexType) +ADAPT_REDUCTION(ReduceComplex16, CFloat128ComplexType, CppComplexFloat128, + CMPLXF128, RARGS, REDUCE_ARG_NAMES) +#undef RARGS +#endif diff --git a/flang/runtime/complex-reduction.h b/flang/runtime/complex-reduction.h index 1d37b235d5194b5479a6bacff600042e034d885f..98b20d1e592be8ad59392a807b625d7e8022e9e6 100644 --- a/flang/runtime/complex-reduction.h +++ b/flang/runtime/complex-reduction.h @@ -69,4 +69,49 @@ long_double_Complex_t RTNAME(DotProductComplex10)(DOT_PRODUCT_ARGS); CFloat128ComplexType RTNAME(DotProductComplex16)(DOT_PRODUCT_ARGS); #endif +#define REDUCE_ARGS(T) \ + T##_op operation, const struct CppDescriptor *x, \ + const struct CppDescriptor *y, const char *source, int line, \ + int dim /*=0*/, const struct CppDescriptor *mask /*=NULL*/, \ + const T *identity /*=NULL*/, _Bool ordered /*=true*/ +#define REDUCE_ARG_NAMES \ + operation, x, y, source, line, dim, mask, identity, ordered + +typedef float_Complex_t (*float_Complex_t_op)( + const float_Complex_t *, const float_Complex_t *); +typedef double_Complex_t (*double_Complex_t_op)( + const double_Complex_t *, const double_Complex_t *); +typedef long_double_Complex_t (*long_double_Complex_t_op)( + const long_double_Complex_t *, const long_double_Complex_t *); + +float_Complex_t RTNAME(ReduceComplex2)(REDUCE_ARGS(float_Complex_t)); +float_Complex_t RTNAME(ReduceComplex3)(REDUCE_ARGS(float_Complex_t)); +float_Complex_t RTNAME(ReduceComplex4)(REDUCE_ARGS(float_Complex_t)); +double_Complex_t RTNAME(ReduceComplex8)(REDUCE_ARGS(double_Complex_t)); +long_double_Complex_t RTNAME(ReduceComplex10)( + REDUCE_ARGS(long_double_Complex_t)); +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +typedef CFloat128ComplexType (*CFloat128ComplexType_op)( + const CFloat128ComplexType *, const CFloat128ComplexType *); +CFloat128ComplexType RTNAME(ReduceComplex16)(REDUCE_ARGS(CFloat128ComplexType)); +#endif + +#define REDUCE_DIM_ARGS(T) \ + struct CppDescriptor *result, T##_op operation, \ + const struct CppDescriptor *x, const struct CppDescriptor *y, \ + const char *source, int line, int dim, \ + const struct CppDescriptor *mask /*=NULL*/, const T *identity /*=NULL*/, \ + _Bool ordered /*=true*/ +#define REDUCE_DIM_ARG_NAMES \ + result, operation, x, y, source, line, dim, mask, identity, ordered + +void RTNAME(ReduceComplex2Dim)(REDUCE_DIM_ARGS(float_Complex_t)); +void RTNAME(ReduceComplex3Dim)(REDUCE_DIM_ARGS(float_Complex_t)); +void RTNAME(ReduceComplex4Dim)(REDUCE_DIM_ARGS(float_Complex_t)); +void RTNAME(ReduceComplex8Dim)(REDUCE_DIM_ARGS(double_Complex_t)); +void RTNAME(ReduceComplex10Dim)(REDUCE_DIM_ARGS(long_double_Complex_t)); +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +void RTNAME(ReduceComplex16Dim)(REDUCE_DIM_ARGS(CFloat128ComplexType)); +#endif + #endif // FORTRAN_RUNTIME_COMPLEX_REDUCTION_H_ diff --git a/flang/runtime/connection.cpp b/flang/runtime/connection.cpp index 91ac9a0e14e47bed0c32f6105a95614d16a5e123..f24f0e832eb484c36af17ca93d63e7130b9683bc 100644 --- a/flang/runtime/connection.cpp +++ b/flang/runtime/connection.cpp @@ -12,30 +12,31 @@ #include <algorithm> namespace Fortran::runtime::io { +RT_OFFLOAD_API_GROUP_BEGIN -std::size_t ConnectionState::RemainingSpaceInRecord() const { +RT_API_ATTRS std::size_t ConnectionState::RemainingSpaceInRecord() const { auto recl{recordLength.value_or(openRecl.value_or( executionEnvironment.listDirectedOutputLineLengthLimit))}; return positionInRecord >= recl ? 0 : recl - positionInRecord; } -bool ConnectionState::NeedAdvance(std::size_t width) const { +RT_API_ATTRS bool ConnectionState::NeedAdvance(std::size_t width) const { return positionInRecord > 0 && width > RemainingSpaceInRecord(); } -bool ConnectionState::IsAtEOF() const { +RT_API_ATTRS bool ConnectionState::IsAtEOF() const { return endfileRecordNumber && currentRecordNumber >= *endfileRecordNumber; } -bool ConnectionState::IsAfterEndfile() const { +RT_API_ATTRS bool ConnectionState::IsAfterEndfile() const { return endfileRecordNumber && currentRecordNumber > *endfileRecordNumber; } -void ConnectionState::HandleAbsolutePosition(std::int64_t n) { +RT_API_ATTRS void ConnectionState::HandleAbsolutePosition(std::int64_t n) { positionInRecord = std::max(n, std::int64_t{0}) + leftTabLimit.value_or(0); } -void ConnectionState::HandleRelativePosition(std::int64_t n) { +RT_API_ATTRS void ConnectionState::HandleRelativePosition(std::int64_t n) { positionInRecord = std::max(leftTabLimit.value_or(0), positionInRecord + n); } @@ -57,4 +58,6 @@ SavedPosition::~SavedPosition() { conn.pinnedFrame = saved_.pinnedFrame; } } + +RT_OFFLOAD_API_GROUP_END } // namespace Fortran::runtime::io diff --git a/flang/runtime/connection.h b/flang/runtime/connection.h index c9a7566f209881c0b8824143adc6336d030175c5..6f1ea90a160e5e71dcab2da9471744933437f7d1 100644 --- a/flang/runtime/connection.h +++ b/flang/runtime/connection.h @@ -12,8 +12,8 @@ #define FORTRAN_RUNTIME_IO_CONNECTION_H_ #include "format.h" +#include "flang/Common/optional.h" #include <cinttypes> -#include <optional> namespace Fortran::runtime::io { @@ -26,17 +26,17 @@ enum class Access { Sequential, Direct, Stream }; // established in an OPEN statement. struct ConnectionAttributes { Access access{Access::Sequential}; // ACCESS='SEQUENTIAL', 'DIRECT', 'STREAM' - std::optional<bool> isUnformatted; // FORM='UNFORMATTED' if true + Fortran::common::optional<bool> isUnformatted; // FORM='UNFORMATTED' if true bool isUTF8{false}; // ENCODING='UTF-8' unsigned char internalIoCharKind{0}; // 0->external, 1/2/4->internal - std::optional<std::int64_t> openRecl; // RECL= on OPEN + Fortran::common::optional<std::int64_t> openRecl; // RECL= on OPEN - bool IsRecordFile() const { + RT_API_ATTRS bool IsRecordFile() const { // Formatted stream files are viewed as having records, at least on input return access != Access::Stream || !isUnformatted.value_or(true); } - template <typename CHAR = char> constexpr bool useUTF8() const { + template <typename CHAR = char> constexpr RT_API_ATTRS bool useUTF8() const { // For wide CHARACTER kinds, always use UTF-8 for formatted I/O. // For single-byte CHARACTER, encode characters >= 0x80 with // UTF-8 iff the mode is set. @@ -45,32 +45,35 @@ struct ConnectionAttributes { }; struct ConnectionState : public ConnectionAttributes { - bool IsAtEOF() const; // true when read has hit EOF or endfile record - bool IsAfterEndfile() const; // true after ENDFILE until repositioned + RT_API_ATTRS bool + IsAtEOF() const; // true when read has hit EOF or endfile record + RT_API_ATTRS bool + IsAfterEndfile() const; // true after ENDFILE until repositioned // All positions and measurements are always in units of bytes, // not characters. Multi-byte character encodings are possible in // both internal I/O (when the character kind of the variable is 2 or 4) // and external formatted I/O (when the encoding is UTF-8). - std::size_t RemainingSpaceInRecord() const; - bool NeedAdvance(std::size_t) const; - void HandleAbsolutePosition(std::int64_t); - void HandleRelativePosition(std::int64_t); + RT_API_ATTRS std::size_t RemainingSpaceInRecord() const; + RT_API_ATTRS bool NeedAdvance(std::size_t) const; + RT_API_ATTRS void HandleAbsolutePosition(std::int64_t); + RT_API_ATTRS void HandleRelativePosition(std::int64_t); - void BeginRecord() { + RT_API_ATTRS void BeginRecord() { positionInRecord = 0; furthestPositionInRecord = 0; unterminatedRecord = false; } - std::optional<std::int64_t> EffectiveRecordLength() const { + RT_API_ATTRS Fortran::common::optional<std::int64_t> + EffectiveRecordLength() const { // When an input record is longer than an explicit RECL= from OPEN // it is effectively truncated on input. return openRecl && recordLength && *openRecl < *recordLength ? openRecl : recordLength; } - std::optional<std::int64_t> recordLength; + Fortran::common::optional<std::int64_t> recordLength; std::int64_t currentRecordNumber{1}; // 1 is first @@ -86,11 +89,12 @@ struct ConnectionState : public ConnectionAttributes { std::int64_t furthestPositionInRecord{0}; // max(position+bytes) // Set at end of non-advancing I/O data transfer - std::optional<std::int64_t> leftTabLimit; // offset in current record + Fortran::common::optional<std::int64_t> + leftTabLimit; // offset in current record // currentRecordNumber value captured after ENDFILE/REWIND/BACKSPACE statement // or an end-of-file READ condition on a sequential access file - std::optional<std::int64_t> endfileRecordNumber; + Fortran::common::optional<std::int64_t> endfileRecordNumber; // Mutable modes set at OPEN() that can be overridden in READ/WRITE & FORMAT MutableModes modes; // BLANK=, DECIMAL=, SIGN=, ROUND=, PAD=, DELIM=, kP @@ -109,9 +113,9 @@ struct ConnectionState : public ConnectionAttributes { // Utility class for capturing and restoring a position in an input stream. class SavedPosition { public: - explicit SavedPosition(IoStatementState &); - ~SavedPosition(); - void Cancel() { cancelled_ = true; } + explicit RT_API_ATTRS SavedPosition(IoStatementState &); + RT_API_ATTRS ~SavedPosition(); + RT_API_ATTRS void Cancel() { cancelled_ = true; } private: IoStatementState &io_; diff --git a/flang/runtime/derived-api.cpp b/flang/runtime/derived-api.cpp index 321f50a1edfcfe8f03b420ff256850fa846bf22c..eca784be208d10c55e83320d6cc873211f87fc45 100644 --- a/flang/runtime/derived-api.cpp +++ b/flang/runtime/derived-api.cpp @@ -95,7 +95,7 @@ inline RT_API_ATTRS bool CompareDerivedType( return a == b || CompareDerivedTypeNames(a->name(), b->name()); } -static const RT_API_ATTRS typeInfo::DerivedType *GetDerivedType( +static RT_API_ATTRS const typeInfo::DerivedType *GetDerivedType( const Descriptor &desc) { if (const DescriptorAddendum * addendum{desc.Addendum()}) { if (const auto *derived{addendum->derivedType()}) { diff --git a/flang/runtime/derived.h b/flang/runtime/derived.h index e43ecc34a31d1b097bb5660dd6b7557ac6528e81..b4863df8db417c2abdfaaa7b5165ebdad5be7dfe 100644 --- a/flang/runtime/derived.h +++ b/flang/runtime/derived.h @@ -11,7 +11,7 @@ #ifndef FORTRAN_RUNTIME_DERIVED_H_ #define FORTRAN_RUNTIME_DERIVED_H_ -#include "flang/Runtime/api-attrs.h" +#include "flang/Common/api-attrs.h" namespace Fortran::runtime::typeInfo { class DerivedType; diff --git a/flang/runtime/descriptor-io.cpp b/flang/runtime/descriptor-io.cpp index 6041104773cc490e492b5c58fab019bff94a6e49..93df51cf22d3f4b66195e866bb4de7463d0746e2 100644 --- a/flang/runtime/descriptor-io.cpp +++ b/flang/runtime/descriptor-io.cpp @@ -7,16 +7,19 @@ //===----------------------------------------------------------------------===// #include "descriptor-io.h" +#include "freestanding-tools.h" #include "flang/Common/restorer.h" namespace Fortran::runtime::io::descr { +RT_OFFLOAD_API_GROUP_BEGIN // Defined formatted I/O (maybe) -std::optional<bool> DefinedFormattedIo(IoStatementState &io, +Fortran::common::optional<bool> DefinedFormattedIo(IoStatementState &io, const Descriptor &descriptor, const typeInfo::DerivedType &derived, const typeInfo::SpecialBinding &special, const SubscriptValue subscripts[]) { - std::optional<DataEdit> peek{io.GetNextDataEdit(0 /*to peek at it*/)}; + Fortran::common::optional<DataEdit> peek{ + io.GetNextDataEdit(0 /*to peek at it*/)}; if (peek && (peek->descriptor == DataEdit::DefinedDerivedType || peek->descriptor == DataEdit::ListDirected)) { @@ -31,9 +34,9 @@ std::optional<bool> DefinedFormattedIo(IoStatementState &io, ioType[1] = 'T'; std::memcpy(ioType + 2, edit.ioType, edit.ioTypeChars); } else { - std::strcpy( + runtime::strcpy( ioType, io.mutableModes().inNamelist ? "NAMELIST" : "LISTDIRECTED"); - ioTypeLen = std::strlen(ioType); + ioTypeLen = runtime::strlen(ioType); } StaticDescriptor<1, true> vListStatDesc; Descriptor &vListDesc{vListStatDesc.descriptor()}; @@ -55,7 +58,7 @@ std::optional<bool> DefinedFormattedIo(IoStatementState &io, int unit{external->unitNumber()}; int ioStat{IostatOk}; char ioMsg[100]; - std::optional<std::int64_t> startPos; + Fortran::common::optional<std::int64_t> startPos; if (edit.descriptor == DataEdit::DefinedDerivedType && special.which() == typeInfo::SpecialBinding::Which::ReadFormatted) { // DT is an edit descriptor so everything that the child @@ -96,7 +99,7 @@ std::optional<bool> DefinedFormattedIo(IoStatementState &io, // There's a defined I/O subroutine, but there's a FORMAT present and // it does not have a DT data edit descriptor, so apply default formatting // to the components of the derived type as usual. - return std::nullopt; + return Fortran::common::nullopt; } } @@ -149,4 +152,5 @@ bool DefinedUnformattedIo(IoStatementState &io, const Descriptor &descriptor, return handler.GetIoStat() == IostatOk; } +RT_OFFLOAD_API_GROUP_END } // namespace Fortran::runtime::io::descr diff --git a/flang/runtime/descriptor-io.h b/flang/runtime/descriptor-io.h index 394578796faa7928b5bfd7b54fc74c3dd1586fd6..7063858d6191968577afa0614a0a6d7f1c81aecf 100644 --- a/flang/runtime/descriptor-io.h +++ b/flang/runtime/descriptor-io.h @@ -21,14 +21,15 @@ #include "terminator.h" #include "type-info.h" #include "unit.h" +#include "flang/Common/optional.h" #include "flang/Common/uint128.h" #include "flang/Runtime/cpp-type.h" #include "flang/Runtime/descriptor.h" namespace Fortran::runtime::io::descr { template <typename A> -inline A &ExtractElement(IoStatementState &io, const Descriptor &descriptor, - const SubscriptValue subscripts[]) { +inline RT_API_ATTRS A &ExtractElement(IoStatementState &io, + const Descriptor &descriptor, const SubscriptValue subscripts[]) { A *p{descriptor.Element<A>(subscripts)}; if (!p) { io.GetIoErrorHandler().Crash("Bad address for I/O item -- null base " @@ -44,7 +45,7 @@ inline A &ExtractElement(IoStatementState &io, const Descriptor &descriptor, // NAMELIST array output. template <int KIND, Direction DIR> -inline bool FormattedIntegerIO( +inline RT_API_ATTRS bool FormattedIntegerIO( IoStatementState &io, const Descriptor &descriptor) { std::size_t numElements{descriptor.Elements()}; SubscriptValue subscripts[maxRank]; @@ -77,7 +78,7 @@ inline bool FormattedIntegerIO( } template <int KIND, Direction DIR> -inline bool FormattedRealIO( +inline RT_API_ATTRS bool FormattedRealIO( IoStatementState &io, const Descriptor &descriptor) { std::size_t numElements{descriptor.Elements()}; SubscriptValue subscripts[maxRank]; @@ -110,7 +111,7 @@ inline bool FormattedRealIO( } template <int KIND, Direction DIR> -inline bool FormattedComplexIO( +inline RT_API_ATTRS bool FormattedComplexIO( IoStatementState &io, const Descriptor &descriptor) { std::size_t numElements{descriptor.Elements()}; SubscriptValue subscripts[maxRank]; @@ -158,7 +159,7 @@ inline bool FormattedComplexIO( } template <typename A, Direction DIR> -inline bool FormattedCharacterIO( +inline RT_API_ATTRS bool FormattedCharacterIO( IoStatementState &io, const Descriptor &descriptor) { std::size_t numElements{descriptor.Elements()}; SubscriptValue subscripts[maxRank]; @@ -198,7 +199,7 @@ inline bool FormattedCharacterIO( } template <int KIND, Direction DIR> -inline bool FormattedLogicalIO( +inline RT_API_ATTRS bool FormattedLogicalIO( IoStatementState &io, const Descriptor &descriptor) { std::size_t numElements{descriptor.Elements()}; SubscriptValue subscripts[maxRank]; @@ -240,12 +241,12 @@ inline bool FormattedLogicalIO( } template <Direction DIR> -static bool DescriptorIO(IoStatementState &, const Descriptor &, +static RT_API_ATTRS bool DescriptorIO(IoStatementState &, const Descriptor &, const NonTbpDefinedIoTable * = nullptr); // For intrinsic (not defined) derived type I/O, formatted & unformatted template <Direction DIR> -static bool DefaultComponentIO(IoStatementState &io, +static RT_API_ATTRS bool DefaultComponentIO(IoStatementState &io, const typeInfo::Component &component, const Descriptor &origDescriptor, const SubscriptValue origSubscripts[], Terminator &terminator, const NonTbpDefinedIoTable *table) { @@ -268,7 +269,7 @@ static bool DefaultComponentIO(IoStatementState &io, } template <Direction DIR> -static bool DefaultComponentwiseFormattedIO(IoStatementState &io, +static RT_API_ATTRS bool DefaultComponentwiseFormattedIO(IoStatementState &io, const Descriptor &descriptor, const typeInfo::DerivedType &type, const NonTbpDefinedIoTable *table, const SubscriptValue subscripts[]) { IoErrorHandler &handler{io.GetIoErrorHandler()}; @@ -294,7 +295,7 @@ static bool DefaultComponentwiseFormattedIO(IoStatementState &io, } template <Direction DIR> -static bool DefaultComponentwiseUnformattedIO(IoStatementState &io, +static RT_API_ATTRS bool DefaultComponentwiseUnformattedIO(IoStatementState &io, const Descriptor &descriptor, const typeInfo::DerivedType &type, const NonTbpDefinedIoTable *table) { IoErrorHandler &handler{io.GetIoErrorHandler()}; @@ -321,12 +322,12 @@ static bool DefaultComponentwiseUnformattedIO(IoStatementState &io, return true; } -std::optional<bool> DefinedFormattedIo(IoStatementState &, const Descriptor &, - const typeInfo::DerivedType &, const typeInfo::SpecialBinding &, - const SubscriptValue[]); +RT_API_ATTRS Fortran::common::optional<bool> DefinedFormattedIo( + IoStatementState &, const Descriptor &, const typeInfo::DerivedType &, + const typeInfo::SpecialBinding &, const SubscriptValue[]); template <Direction DIR> -static bool FormattedDerivedTypeIO(IoStatementState &io, +static RT_API_ATTRS bool FormattedDerivedTypeIO(IoStatementState &io, const Descriptor &descriptor, const NonTbpDefinedIoTable *table) { IoErrorHandler &handler{io.GetIoErrorHandler()}; // Derived type information must be present for formatted I/O. @@ -334,7 +335,7 @@ static bool FormattedDerivedTypeIO(IoStatementState &io, RUNTIME_CHECK(handler, addendum != nullptr); const typeInfo::DerivedType *type{addendum->derivedType()}; RUNTIME_CHECK(handler, type != nullptr); - std::optional<typeInfo::SpecialBinding> nonTbpSpecial; + Fortran::common::optional<typeInfo::SpecialBinding> nonTbpSpecial; const typeInfo::SpecialBinding *special{nullptr}; if (table) { if (const auto *definedIo{table->Find(*type, @@ -365,7 +366,7 @@ static bool FormattedDerivedTypeIO(IoStatementState &io, std::size_t numElements{descriptor.Elements()}; for (std::size_t j{0}; j < numElements; ++j, descriptor.IncrementSubscripts(subscripts)) { - std::optional<bool> result; + Fortran::common::optional<bool> result; if (special) { result = DefinedFormattedIo(io, descriptor, *type, *special, subscripts); } @@ -384,12 +385,12 @@ static bool FormattedDerivedTypeIO(IoStatementState &io, return true; } -bool DefinedUnformattedIo(IoStatementState &, const Descriptor &, +RT_API_ATTRS bool DefinedUnformattedIo(IoStatementState &, const Descriptor &, const typeInfo::DerivedType &, const typeInfo::SpecialBinding &); // Unformatted I/O template <Direction DIR> -static bool UnformattedDescriptorIO(IoStatementState &io, +static RT_API_ATTRS bool UnformattedDescriptorIO(IoStatementState &io, const Descriptor &descriptor, const NonTbpDefinedIoTable *table = nullptr) { IoErrorHandler &handler{io.GetIoErrorHandler()}; const DescriptorAddendum *addendum{descriptor.Addendum()}; @@ -406,7 +407,7 @@ static bool UnformattedDescriptorIO(IoStatementState &io, : typeInfo::SpecialBinding::Which::WriteUnformatted, definedIo->subroutine, definedIo->isDtvArgPolymorphic, false, false}; - if (std::optional<bool> wasDefined{ + if (Fortran::common::optional<bool> wasDefined{ DefinedUnformattedIo(io, descriptor, *type, special)}) { return *wasDefined; } @@ -487,8 +488,8 @@ static bool UnformattedDescriptorIO(IoStatementState &io, } template <Direction DIR> -static bool DescriptorIO(IoStatementState &io, const Descriptor &descriptor, - const NonTbpDefinedIoTable *table) { +static RT_API_ATTRS bool DescriptorIO(IoStatementState &io, + const Descriptor &descriptor, const NonTbpDefinedIoTable *table) { IoErrorHandler &handler{io.GetIoErrorHandler()}; if (handler.InError()) { return false; diff --git a/flang/runtime/edit-input.cpp b/flang/runtime/edit-input.cpp index 85cce2f1a16623ccef09f88905b9ace1687775d6..935b7c299b25642e698fac25c3a2c6240941b0e8 100644 --- a/flang/runtime/edit-input.cpp +++ b/flang/runtime/edit-input.cpp @@ -7,25 +7,29 @@ //===----------------------------------------------------------------------===// #include "edit-input.h" +#include "freestanding-tools.h" #include "namelist.h" #include "utf.h" +#include "flang/Common/optional.h" #include "flang/Common/real.h" #include "flang/Common/uint128.h" #include <algorithm> #include <cfenv> 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. -static inline bool IsCharValueSeparator(const DataEdit &edit, char32_t ch) { +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 == '/' || (edit.IsNamelist() && (ch == '&' || ch == '$')); } -static bool CheckCompleteListDirectedField( +static RT_API_ATTRS bool CheckCompleteListDirectedField( IoStatementState &io, const DataEdit &edit) { if (edit.IsListDirected()) { std::size_t byteCount; @@ -51,12 +55,12 @@ static bool CheckCompleteListDirectedField( } template <int LOG2_BASE> -static bool EditBOZInput( +static RT_API_ATTRS bool EditBOZInput( IoStatementState &io, const DataEdit &edit, void *n, std::size_t bytes) { // Skip leading white space & zeroes - std::optional<int> remaining{io.CueUpInput(edit)}; + Fortran::common::optional<int> remaining{io.CueUpInput(edit)}; auto start{io.GetConnectionState().positionInRecord}; - std::optional<char32_t> next{io.NextInField(remaining, edit)}; + Fortran::common::optional<char32_t> next{io.NextInField(remaining, edit)}; if (next.value_or('?') == '0') { do { start = io.GetConnectionState().positionInRecord; @@ -150,13 +154,14 @@ static bool EditBOZInput( return CheckCompleteListDirectedField(io, edit); } -static inline char32_t GetRadixPointChar(const DataEdit &edit) { +static inline RT_API_ATTRS char32_t GetRadixPointChar(const DataEdit &edit) { return edit.modes.editingFlags & decimalComma ? char32_t{','} : char32_t{'.'}; } // Prepares input from a field, and returns the sign, if any, else '\0'. -static char ScanNumericPrefix(IoStatementState &io, const DataEdit &edit, - std::optional<char32_t> &next, std::optional<int> &remaining) { +static RT_API_ATTRS char ScanNumericPrefix(IoStatementState &io, + const DataEdit &edit, Fortran::common::optional<char32_t> &next, + Fortran::common::optional<int> &remaining) { remaining = io.CueUpInput(edit); next = io.NextInField(remaining, edit); char sign{'\0'}; @@ -172,7 +177,7 @@ static char ScanNumericPrefix(IoStatementState &io, const DataEdit &edit, return sign; } -bool EditIntegerInput( +RT_API_ATTRS bool EditIntegerInput( IoStatementState &io, const DataEdit &edit, void *n, int kind) { RUNTIME_CHECK(io.GetIoErrorHandler(), kind >= 1 && !(kind & (kind - 1))); switch (edit.descriptor) { @@ -198,8 +203,8 @@ bool EditIntegerInput( edit.descriptor); return false; } - std::optional<int> remaining; - std::optional<char32_t> next; + Fortran::common::optional<int> remaining; + Fortran::common::optional<char32_t> next; char sign{ScanNumericPrefix(io, edit, next, remaining)}; common::UnsignedInt128 value{0}; bool any{!!sign}; @@ -277,18 +282,20 @@ struct ScannedRealInput { int exponent{0}; // adjusted as necessary; binary if isHexadecimal bool isHexadecimal{false}; // 0X... }; -static ScannedRealInput ScanRealInput( +static RT_API_ATTRS ScannedRealInput ScanRealInput( char *buffer, int bufferSize, IoStatementState &io, const DataEdit &edit) { - std::optional<int> remaining; - std::optional<char32_t> next; + Fortran::common::optional<int> remaining; + Fortran::common::optional<char32_t> next; int got{0}; - std::optional<int> radixPointOffset; - auto Put{[&](char ch) -> void { + Fortran::common::optional<int> radixPointOffset; + // The following lambda definition violates the conding style, + // but cuda-11.8 nvcc hits an internal error with the brace initialization. + auto Put = [&](char ch) -> void { if (got < bufferSize) { buffer[got] = ch; } ++got; - }}; + }; char sign{ScanNumericPrefix(io, edit, next, remaining)}; if (sign == '-') { Put('-'); @@ -485,13 +492,21 @@ static ScannedRealInput ScanRealInput( return {got, exponent, isHexadecimal}; } -static void RaiseFPExceptions(decimal::ConversionResultFlags flags) { +static RT_API_ATTRS void RaiseFPExceptions( + decimal::ConversionResultFlags flags) { #undef RAISE +#if defined(RT_DEVICE_COMPILATION) + Terminator terminator(__FILE__, __LINE__); +#define RAISE(e) \ + terminator.Crash( \ + "not implemented yet: raising FP exception in device code: %s", #e); +#else // !defined(RT_DEVICE_COMPILATION) #ifdef feraisexcept // a macro in some environments; omit std:: #define RAISE feraiseexcept #else #define RAISE std::feraiseexcept #endif +#endif // !defined(RT_DEVICE_COMPILATION) if (flags & decimal::ConversionResultFlags::Overflow) { RAISE(FE_OVERFLOW); } @@ -512,7 +527,7 @@ static void RaiseFPExceptions(decimal::ConversionResultFlags flags) { // converter without modification, this fast path for real input // saves time by avoiding memory copies and reformatting of the exponent. template <int PRECISION> -static bool TryFastPathRealDecimalInput( +static RT_API_ATTRS bool TryFastPathRealDecimalInput( IoStatementState &io, const DataEdit &edit, void *n) { if (edit.modes.editingFlags & (blankZero | decimalComma)) { return false; @@ -584,7 +599,8 @@ static bool TryFastPathRealDecimalInput( } template <int binaryPrecision> -decimal::ConversionToBinaryResult<binaryPrecision> ConvertHexadecimal( +RT_API_ATTRS decimal::ConversionToBinaryResult<binaryPrecision> +ConvertHexadecimal( const char *&p, enum decimal::FortranRounding rounding, int expo) { using RealType = decimal::BinaryFloatingPointNumber<binaryPrecision>; using RawType = typename RealType::RawType; @@ -612,11 +628,23 @@ decimal::ConversionToBinaryResult<binaryPrecision> ConvertHexadecimal( } else { break; } - while (fraction >> binaryPrecision) { - guardBit |= roundingBit; - roundingBit = (int)fraction & 1; - fraction >>= 1; - ++expo; + if (fraction >> binaryPrecision) { + while (fraction >> binaryPrecision) { + guardBit |= roundingBit; + roundingBit = (int)fraction & 1; + fraction >>= 1; + ++expo; + } + // Consume excess digits + while (*++p) { + if (*p == '0') { + } else if ((*p >= '1' && *p <= '9') || (*p >= 'A' && *p <= 'F')) { + guardBit = 1; + } else { + break; + } + } + break; } } if (fraction) { @@ -631,31 +659,32 @@ decimal::ConversionToBinaryResult<binaryPrecision> ConvertHexadecimal( while (expo > 1 && !(fraction >> (binaryPrecision - 1))) { fraction <<= 1; --expo; + guardBit = roundingBit = 0; } - // Rounding - bool increase{false}; - switch (rounding) { - case decimal::RoundNearest: // RN & RP - increase = roundingBit && (guardBit | ((int)fraction & 1)); - break; - case decimal::RoundUp: // RU - increase = !isNegative && (roundingBit | guardBit); - break; - case decimal::RoundDown: // RD - increase = isNegative && (roundingBit | guardBit); - break; - case decimal::RoundToZero: // RZ - break; - case decimal::RoundCompatible: // RC - increase = roundingBit != 0; - break; - } - if (increase) { - ++fraction; - if (fraction >> binaryPrecision) { - fraction >>= 1; - ++expo; - } + } + // Rounding + bool increase{false}; + switch (rounding) { + case decimal::RoundNearest: // RN & RP + increase = roundingBit && (guardBit | ((int)fraction & 1)); + break; + case decimal::RoundUp: // RU + increase = !isNegative && (roundingBit | guardBit); + break; + case decimal::RoundDown: // RD + increase = isNegative && (roundingBit | guardBit); + break; + case decimal::RoundToZero: // RZ + break; + case decimal::RoundCompatible: // RC + increase = roundingBit != 0; + break; + } + if (increase) { + ++fraction; + if (fraction >> binaryPrecision) { + fraction >>= 1; + ++expo; } } // Package & return result @@ -687,7 +716,8 @@ decimal::ConversionToBinaryResult<binaryPrecision> ConvertHexadecimal( } template <int KIND> -bool EditCommonRealInput(IoStatementState &io, const DataEdit &edit, void *n) { +RT_API_ATTRS bool EditCommonRealInput( + IoStatementState &io, const DataEdit &edit, void *n) { constexpr int binaryPrecision{common::PrecisionOfRealKind(KIND)}; if (TryFastPathRealDecimalInput<binaryPrecision>(io, edit, n)) { return CheckCompleteListDirectedField(io, edit); @@ -783,7 +813,8 @@ bool EditCommonRealInput(IoStatementState &io, const DataEdit &edit, void *n) { } template <int KIND> -bool EditRealInput(IoStatementState &io, const DataEdit &edit, void *n) { +RT_API_ATTRS bool EditRealInput( + IoStatementState &io, const DataEdit &edit, void *n) { switch (edit.descriptor) { case DataEdit::ListDirected: if (IsNamelistNameOrSlash(io)) { @@ -817,7 +848,8 @@ bool EditRealInput(IoStatementState &io, const DataEdit &edit, void *n) { } // 13.7.3 in Fortran 2018 -bool EditLogicalInput(IoStatementState &io, const DataEdit &edit, bool &x) { +RT_API_ATTRS bool EditLogicalInput( + IoStatementState &io, const DataEdit &edit, bool &x) { switch (edit.descriptor) { case DataEdit::ListDirected: if (IsNamelistNameOrSlash(io)) { @@ -833,8 +865,8 @@ bool EditLogicalInput(IoStatementState &io, const DataEdit &edit, bool &x) { edit.descriptor); return false; } - std::optional<int> remaining{io.CueUpInput(edit)}; - std::optional<char32_t> next{io.NextInField(remaining, edit)}; + Fortran::common::optional<int> remaining{io.CueUpInput(edit)}; + Fortran::common::optional<char32_t> next{io.NextInField(remaining, edit)}; if (next && *next == '.') { // skip optional period next = io.NextInField(remaining, edit); } @@ -867,7 +899,7 @@ bool EditLogicalInput(IoStatementState &io, const DataEdit &edit, bool &x) { // See 13.10.3.1 paragraphs 7-9 in Fortran 2018 template <typename CHAR> -static bool EditDelimitedCharacterInput( +static RT_API_ATTRS bool EditDelimitedCharacterInput( IoStatementState &io, CHAR *x, std::size_t length, char32_t delimiter) { bool result{true}; while (true) { @@ -896,12 +928,12 @@ static bool EditDelimitedCharacterInput( --length; } } - std::fill_n(x, length, ' '); + Fortran::runtime::fill_n(x, length, ' '); return result; } template <typename CHAR> -static bool EditListDirectedCharacterInput( +static RT_API_ATTRS bool EditListDirectedCharacterInput( IoStatementState &io, CHAR *x, std::size_t length, const DataEdit &edit) { std::size_t byteCount{0}; auto ch{io.GetCurrentChar(byteCount)}; @@ -916,8 +948,9 @@ static bool EditListDirectedCharacterInput( // or the end of the current record. Subtlety: the "remaining" count // here is a dummy that's used to avoid the interpretation of separators // in NextInField. - std::optional<int> remaining{length > 0 ? maxUTF8Bytes : 0}; - while (std::optional<char32_t> next{io.NextInField(remaining, edit)}) { + Fortran::common::optional<int> remaining{length > 0 ? maxUTF8Bytes : 0}; + while (Fortran::common::optional<char32_t> next{ + io.NextInField(remaining, edit)}) { bool isSep{false}; switch (*next) { case ' ': @@ -945,13 +978,13 @@ static bool EditListDirectedCharacterInput( remaining = --length > 0 ? maxUTF8Bytes : 0; } } - std::fill_n(x, length, ' '); + Fortran::runtime::fill_n(x, length, ' '); return true; } template <typename CHAR> -bool EditCharacterInput(IoStatementState &io, const DataEdit &edit, CHAR *x, - std::size_t lengthChars) { +RT_API_ATTRS bool EditCharacterInput(IoStatementState &io, const DataEdit &edit, + CHAR *x, std::size_t lengthChars) { switch (edit.descriptor) { case DataEdit::ListDirected: return EditListDirectedCharacterInput(io, x, lengthChars, edit); @@ -995,7 +1028,7 @@ bool EditCharacterInput(IoStatementState &io, const DataEdit &edit, CHAR *x, if (io.CheckForEndOfRecord(readyBytes)) { if (readyBytes == 0) { // PAD='YES' and no more data - std::fill_n(x, lengthChars, ' '); + Fortran::runtime::fill_n(x, lengthChars, ' '); return !io.GetIoErrorHandler().InError(); } else { // Do partial read(s) then pad on last iteration @@ -1072,23 +1105,30 @@ bool EditCharacterInput(IoStatementState &io, const DataEdit &edit, CHAR *x, readyBytes -= chunkBytes; } // Pad the remainder of the input variable, if any. - std::fill_n(x, lengthChars, ' '); + Fortran::runtime::fill_n(x, lengthChars, ' '); return CheckCompleteListDirectedField(io, edit); } -template bool EditRealInput<2>(IoStatementState &, const DataEdit &, void *); -template bool EditRealInput<3>(IoStatementState &, const DataEdit &, void *); -template bool EditRealInput<4>(IoStatementState &, const DataEdit &, void *); -template bool EditRealInput<8>(IoStatementState &, const DataEdit &, void *); -template bool EditRealInput<10>(IoStatementState &, const DataEdit &, void *); +template RT_API_ATTRS bool EditRealInput<2>( + IoStatementState &, const DataEdit &, void *); +template RT_API_ATTRS bool EditRealInput<3>( + IoStatementState &, const DataEdit &, void *); +template RT_API_ATTRS bool EditRealInput<4>( + IoStatementState &, const DataEdit &, void *); +template RT_API_ATTRS bool EditRealInput<8>( + IoStatementState &, const DataEdit &, void *); +template RT_API_ATTRS bool EditRealInput<10>( + IoStatementState &, const DataEdit &, void *); // TODO: double/double -template bool EditRealInput<16>(IoStatementState &, const DataEdit &, void *); +template RT_API_ATTRS bool EditRealInput<16>( + IoStatementState &, const DataEdit &, void *); -template bool EditCharacterInput( +template RT_API_ATTRS bool EditCharacterInput( IoStatementState &, const DataEdit &, char *, std::size_t); -template bool EditCharacterInput( +template RT_API_ATTRS bool EditCharacterInput( IoStatementState &, const DataEdit &, char16_t *, std::size_t); -template bool EditCharacterInput( +template RT_API_ATTRS bool EditCharacterInput( IoStatementState &, const DataEdit &, char32_t *, std::size_t); +RT_OFFLOAD_API_GROUP_END } // namespace Fortran::runtime::io diff --git a/flang/runtime/edit-input.h b/flang/runtime/edit-input.h index 61844a1199a748ebe74e873197826f987a212584..a90180b8ee2ebd5c57a8d0556fade7cc1bc2535d 100644 --- a/flang/runtime/edit-input.h +++ b/flang/runtime/edit-input.h @@ -15,36 +15,38 @@ namespace Fortran::runtime::io { -bool EditIntegerInput(IoStatementState &, const DataEdit &, void *, int kind); +RT_API_ATTRS bool EditIntegerInput( + IoStatementState &, const DataEdit &, void *, int kind); template <int KIND> -bool EditRealInput(IoStatementState &, const DataEdit &, void *); +RT_API_ATTRS bool EditRealInput(IoStatementState &, const DataEdit &, void *); -bool EditLogicalInput(IoStatementState &, const DataEdit &, bool &); +RT_API_ATTRS bool EditLogicalInput( + IoStatementState &, const DataEdit &, bool &); template <typename CHAR> -bool EditCharacterInput( +RT_API_ATTRS bool EditCharacterInput( IoStatementState &, const DataEdit &, CHAR *, std::size_t); -extern template bool EditRealInput<2>( +extern template RT_API_ATTRS bool EditRealInput<2>( IoStatementState &, const DataEdit &, void *); -extern template bool EditRealInput<3>( +extern template RT_API_ATTRS bool EditRealInput<3>( IoStatementState &, const DataEdit &, void *); -extern template bool EditRealInput<4>( +extern template RT_API_ATTRS bool EditRealInput<4>( IoStatementState &, const DataEdit &, void *); -extern template bool EditRealInput<8>( +extern template RT_API_ATTRS bool EditRealInput<8>( IoStatementState &, const DataEdit &, void *); -extern template bool EditRealInput<10>( +extern template RT_API_ATTRS bool EditRealInput<10>( IoStatementState &, const DataEdit &, void *); // TODO: double/double -extern template bool EditRealInput<16>( +extern template RT_API_ATTRS bool EditRealInput<16>( IoStatementState &, const DataEdit &, void *); -extern template bool EditCharacterInput( +extern template RT_API_ATTRS bool EditCharacterInput( IoStatementState &, const DataEdit &, char *, std::size_t); -extern template bool EditCharacterInput( +extern template RT_API_ATTRS bool EditCharacterInput( IoStatementState &, const DataEdit &, char16_t *, std::size_t); -extern template bool EditCharacterInput( +extern template RT_API_ATTRS bool EditCharacterInput( IoStatementState &, const DataEdit &, char32_t *, std::size_t); } // namespace Fortran::runtime::io diff --git a/flang/runtime/edit-output.cpp b/flang/runtime/edit-output.cpp index b474c8cd91bae4208747bf1434d22c5436db8302..b710c298babebf9cb28b7ad2725a264177f6508f 100644 --- a/flang/runtime/edit-output.cpp +++ b/flang/runtime/edit-output.cpp @@ -9,13 +9,15 @@ #include "edit-output.h" #include "emit-encoded.h" #include "utf.h" +#include "flang/Common/real.h" #include "flang/Common/uint128.h" #include <algorithm> namespace Fortran::runtime::io { +RT_OFFLOAD_API_GROUP_BEGIN // In output statement, add a space between numbers and characters. -static void addSpaceBeforeCharacter(IoStatementState &io) { +static RT_API_ATTRS void addSpaceBeforeCharacter(IoStatementState &io) { if (auto *list{io.get_if<ListDirectedStatementState<Direction::Output>>()}) { list->set_lastWasUndelimitedCharacter(false); } @@ -25,8 +27,8 @@ static void addSpaceBeforeCharacter(IoStatementState &io) { // representation of what is interpreted to be a single unsigned integer value. // When used with character data, endianness is exposed. template <int LOG2_BASE> -static bool EditBOZOutput(IoStatementState &io, const DataEdit &edit, - const unsigned char *data0, std::size_t bytes) { +static RT_API_ATTRS bool EditBOZOutput(IoStatementState &io, + const DataEdit &edit, const unsigned char *data0, std::size_t bytes) { addSpaceBeforeCharacter(io); int digits{static_cast<int>((bytes * 8) / LOG2_BASE)}; int get{static_cast<int>(bytes * 8) - digits * LOG2_BASE}; @@ -106,7 +108,7 @@ static bool EditBOZOutput(IoStatementState &io, const DataEdit &edit, } template <int KIND> -bool EditIntegerOutput(IoStatementState &io, const DataEdit &edit, +bool RT_API_ATTRS EditIntegerOutput(IoStatementState &io, const DataEdit &edit, common::HostSignedIntType<8 * KIND> n) { addSpaceBeforeCharacter(io); char buffer[130], *end{&buffer[sizeof buffer]}, *p{end}; @@ -186,7 +188,7 @@ bool EditIntegerOutput(IoStatementState &io, const DataEdit &edit, } // Formats the exponent (see table 13.1 for all the cases) -const char *RealOutputEditingBase::FormatExponent( +RT_API_ATTRS const char *RealOutputEditingBase::FormatExponent( int expo, const DataEdit &edit, int &length) { char *eEnd{&exponent_[sizeof exponent_]}; char *exponent{eEnd}; @@ -225,7 +227,7 @@ const char *RealOutputEditingBase::FormatExponent( return overflow ? nullptr : exponent; } -bool RealOutputEditingBase::EmitPrefix( +RT_API_ATTRS bool RealOutputEditingBase::EmitPrefix( const DataEdit &edit, std::size_t length, std::size_t width) { if (edit.IsListDirected()) { int prefixLength{edit.descriptor == DataEdit::ListDirectedRealPart ? 2 @@ -246,7 +248,7 @@ bool RealOutputEditingBase::EmitPrefix( } } -bool RealOutputEditingBase::EmitSuffix(const DataEdit &edit) { +RT_API_ATTRS bool RealOutputEditingBase::EmitSuffix(const DataEdit &edit) { if (edit.descriptor == DataEdit::ListDirectedRealPart) { return EmitAscii( io_, edit.modes.editingFlags & decimalComma ? ";" : ",", 1); @@ -258,8 +260,10 @@ bool RealOutputEditingBase::EmitSuffix(const DataEdit &edit) { } template <int KIND> -decimal::ConversionToDecimalResult RealOutputEditing<KIND>::ConvertToDecimal( +RT_API_ATTRS decimal::ConversionToDecimalResult +RealOutputEditing<KIND>::ConvertToDecimal( int significantDigits, enum decimal::FortranRounding rounding, int flags) { +#if !defined(RT_DEVICE_COMPILATION) auto converted{decimal::ConvertToDecimal<binaryPrecision>(buffer_, sizeof buffer_, static_cast<enum decimal::DecimalConversionFlags>(flags), significantDigits, rounding, x_)}; @@ -269,9 +273,13 @@ decimal::ConversionToDecimalResult RealOutputEditing<KIND>::ConvertToDecimal( sizeof buffer_); } return converted; +#else // defined(RT_DEVICE_COMPILATION) + // TODO: enable Decimal library build for the device. + io_.GetIoErrorHandler().Crash("not implemented yet: decimal conversion"); +#endif // defined(RT_DEVICE_COMPILATION) } -static bool IsInfOrNaN(const char *p, int length) { +static RT_API_ATTRS bool IsInfOrNaN(const char *p, int length) { if (!p || length < 1) { return false; } @@ -286,7 +294,8 @@ static bool IsInfOrNaN(const char *p, int length) { // 13.7.2.3.3 in F'2018 template <int KIND> -bool RealOutputEditing<KIND>::EditEorDOutput(const DataEdit &edit) { +RT_API_ATTRS bool RealOutputEditing<KIND>::EditEorDOutput( + const DataEdit &edit) { addSpaceBeforeCharacter(io_); int editDigits{edit.digits.value_or(0)}; // 'd' field int editWidth{edit.width.value_or(0)}; // 'w' field @@ -422,7 +431,7 @@ bool RealOutputEditing<KIND>::EditEorDOutput(const DataEdit &edit) { // 13.7.2.3.2 in F'2018 template <int KIND> -bool RealOutputEditing<KIND>::EditFOutput(const DataEdit &edit) { +RT_API_ATTRS bool RealOutputEditing<KIND>::EditFOutput(const DataEdit &edit) { addSpaceBeforeCharacter(io_); int fracDigits{edit.digits.value_or(0)}; // 'd' field const int editWidth{edit.width.value_or(0)}; // 'w' field @@ -552,12 +561,12 @@ bool RealOutputEditing<KIND>::EditFOutput(const DataEdit &edit) { // 13.7.5.2.3 in F'2018 template <int KIND> -DataEdit RealOutputEditing<KIND>::EditForGOutput(DataEdit edit) { +RT_API_ATTRS DataEdit RealOutputEditing<KIND>::EditForGOutput(DataEdit edit) { edit.descriptor = 'E'; edit.variation = 'G'; // to suppress error for Ew.0 int editWidth{edit.width.value_or(0)}; - int significantDigits{ - edit.digits.value_or(BinaryFloatingPoint::decimalPrecision)}; // 'd' + int significantDigits{edit.digits.value_or( + static_cast<int>(BinaryFloatingPoint::decimalPrecision))}; // 'd' if (editWidth > 0 && significantDigits == 0) { return edit; // Gw.0Ee -> Ew.0Ee for w > 0 } @@ -596,7 +605,8 @@ DataEdit RealOutputEditing<KIND>::EditForGOutput(DataEdit edit) { // 13.10.4 in F'2018 template <int KIND> -bool RealOutputEditing<KIND>::EditListDirectedOutput(const DataEdit &edit) { +RT_API_ATTRS bool RealOutputEditing<KIND>::EditListDirectedOutput( + const DataEdit &edit) { decimal::ConversionToDecimalResult converted{ ConvertToDecimal(1, edit.modes.round)}; if (IsInfOrNaN(converted.str, static_cast<int>(converted.length))) { @@ -630,9 +640,9 @@ bool RealOutputEditing<KIND>::EditListDirectedOutput(const DataEdit &edit) { // E.g., 2. is edited into 0X8.0P-2 rather than 0X2.0P0. This implementation // follows that precedent so as to avoid a gratuitous incompatibility. template <int KIND> -auto RealOutputEditing<KIND>::ConvertToHexadecimal( - int significantDigits, enum decimal::FortranRounding rounding, int flags) - -> ConvertToHexadecimalResult { +RT_API_ATTRS auto RealOutputEditing<KIND>::ConvertToHexadecimal( + int significantDigits, enum decimal::FortranRounding rounding, + int flags) -> ConvertToHexadecimalResult { if (x_.IsNaN() || x_.IsInfinite()) { auto converted{ConvertToDecimal(significantDigits, rounding, flags)}; return {converted.str, static_cast<int>(converted.length), 0}; @@ -688,7 +698,7 @@ auto RealOutputEditing<KIND>::ConvertToHexadecimal( } template <int KIND> -bool RealOutputEditing<KIND>::EditEXOutput(const DataEdit &edit) { +RT_API_ATTRS bool RealOutputEditing<KIND>::EditEXOutput(const DataEdit &edit) { addSpaceBeforeCharacter(io_); int editDigits{edit.digits.value_or(0)}; // 'd' field int significantDigits{editDigits + 1}; @@ -700,7 +710,9 @@ bool RealOutputEditing<KIND>::EditEXOutput(const DataEdit &edit) { if ((editWidth == 0 && !edit.digits) || editDigits == 0) { // EX0 or EXw.0 flags |= decimal::Minimize; - significantDigits = 28; // enough for 128-bit F.P. + static constexpr int maxSigHexDigits{ + (common::PrecisionOfRealKind(16) + 3) / 4}; + significantDigits = maxSigHexDigits; } auto converted{ ConvertToHexadecimal(significantDigits, edit.modes.round, flags)}; @@ -737,7 +749,8 @@ bool RealOutputEditing<KIND>::EditEXOutput(const DataEdit &edit) { EmitAscii(io_, exponent, expoLength); } -template <int KIND> bool RealOutputEditing<KIND>::Edit(const DataEdit &edit) { +template <int KIND> +RT_API_ATTRS bool RealOutputEditing<KIND>::Edit(const DataEdit &edit) { switch (edit.descriptor) { case 'D': return EditEorDOutput(edit); @@ -780,13 +793,14 @@ template <int KIND> bool RealOutputEditing<KIND>::Edit(const DataEdit &edit) { return false; } -bool ListDirectedLogicalOutput(IoStatementState &io, +RT_API_ATTRS bool ListDirectedLogicalOutput(IoStatementState &io, ListDirectedStatementState<Direction::Output> &list, bool truth) { return list.EmitLeadingSpaceOrAdvance(io) && EmitAscii(io, truth ? "T" : "F", 1); } -bool EditLogicalOutput(IoStatementState &io, const DataEdit &edit, bool truth) { +RT_API_ATTRS bool EditLogicalOutput( + IoStatementState &io, const DataEdit &edit, bool truth) { switch (edit.descriptor) { case 'L': case 'G': @@ -810,7 +824,7 @@ bool EditLogicalOutput(IoStatementState &io, const DataEdit &edit, bool truth) { } template <typename CHAR> -bool ListDirectedCharacterOutput(IoStatementState &io, +RT_API_ATTRS bool ListDirectedCharacterOutput(IoStatementState &io, ListDirectedStatementState<Direction::Output> &list, const CHAR *x, std::size_t length) { bool ok{true}; @@ -867,8 +881,8 @@ bool ListDirectedCharacterOutput(IoStatementState &io, } template <typename CHAR> -bool EditCharacterOutput(IoStatementState &io, const DataEdit &edit, - const CHAR *x, std::size_t length) { +RT_API_ATTRS bool EditCharacterOutput(IoStatementState &io, + const DataEdit &edit, const CHAR *x, std::size_t length) { int len{static_cast<int>(length)}; int width{edit.width.value_or(len)}; switch (edit.descriptor) { @@ -900,15 +914,15 @@ bool EditCharacterOutput(IoStatementState &io, const DataEdit &edit, EmitEncoded(io, x, std::min(width, len)); } -template bool EditIntegerOutput<1>( +template RT_API_ATTRS bool EditIntegerOutput<1>( IoStatementState &, const DataEdit &, std::int8_t); -template bool EditIntegerOutput<2>( +template RT_API_ATTRS bool EditIntegerOutput<2>( IoStatementState &, const DataEdit &, std::int16_t); -template bool EditIntegerOutput<4>( +template RT_API_ATTRS bool EditIntegerOutput<4>( IoStatementState &, const DataEdit &, std::int32_t); -template bool EditIntegerOutput<8>( +template RT_API_ATTRS bool EditIntegerOutput<8>( IoStatementState &, const DataEdit &, std::int64_t); -template bool EditIntegerOutput<16>( +template RT_API_ATTRS bool EditIntegerOutput<16>( IoStatementState &, const DataEdit &, common::int128_t); template class RealOutputEditing<2>; @@ -919,21 +933,22 @@ template class RealOutputEditing<10>; // TODO: double/double template class RealOutputEditing<16>; -template bool ListDirectedCharacterOutput(IoStatementState &, +template RT_API_ATTRS bool ListDirectedCharacterOutput(IoStatementState &, ListDirectedStatementState<Direction::Output> &, const char *, std::size_t chars); -template bool ListDirectedCharacterOutput(IoStatementState &, +template RT_API_ATTRS bool ListDirectedCharacterOutput(IoStatementState &, ListDirectedStatementState<Direction::Output> &, const char16_t *, std::size_t chars); -template bool ListDirectedCharacterOutput(IoStatementState &, +template RT_API_ATTRS bool ListDirectedCharacterOutput(IoStatementState &, ListDirectedStatementState<Direction::Output> &, const char32_t *, std::size_t chars); -template bool EditCharacterOutput( +template RT_API_ATTRS bool EditCharacterOutput( IoStatementState &, const DataEdit &, const char *, std::size_t chars); -template bool EditCharacterOutput( +template RT_API_ATTRS bool EditCharacterOutput( IoStatementState &, const DataEdit &, const char16_t *, std::size_t chars); -template bool EditCharacterOutput( +template RT_API_ATTRS bool EditCharacterOutput( IoStatementState &, const DataEdit &, const char32_t *, std::size_t chars); +RT_OFFLOAD_API_GROUP_END } // namespace Fortran::runtime::io diff --git a/flang/runtime/edit-output.h b/flang/runtime/edit-output.h index 4e6d6b25b4dd2d385ca414570f5dd7ec2894fc3d..365bc2e2a4d10b11cb6c4de88d69d16799d86944 100644 --- a/flang/runtime/edit-output.h +++ b/flang/runtime/edit-output.h @@ -30,18 +30,20 @@ namespace Fortran::runtime::io { // one edit descriptor with a repeat factor may safely serve to edit // multiple elements of an array. template <int KIND> -bool EditIntegerOutput( +RT_API_ATTRS bool EditIntegerOutput( IoStatementState &, const DataEdit &, common::HostSignedIntType<8 * KIND>); // Encapsulates the state of a REAL output conversion. class RealOutputEditingBase { protected: - explicit RealOutputEditingBase(IoStatementState &io) : io_{io} {} + explicit RT_API_ATTRS RealOutputEditingBase(IoStatementState &io) : io_{io} {} // Returns null when the exponent overflows a fixed-size output field. - const char *FormatExponent(int, const DataEdit &edit, int &length); - bool EmitPrefix(const DataEdit &, std::size_t length, std::size_t width); - bool EmitSuffix(const DataEdit &); + RT_API_ATTRS const char *FormatExponent( + int, const DataEdit &edit, int &length); + RT_API_ATTRS bool EmitPrefix( + const DataEdit &, std::size_t length, std::size_t width); + RT_API_ATTRS bool EmitSuffix(const DataEdit &); IoStatementState &io_; int trailingBlanks_{0}; // created when Gw editing maps to Fw @@ -50,27 +52,29 @@ protected: template <int KIND> class RealOutputEditing : public RealOutputEditingBase { public: + RT_VAR_GROUP_BEGIN static constexpr int binaryPrecision{common::PrecisionOfRealKind(KIND)}; + RT_VAR_GROUP_END using BinaryFloatingPoint = decimal::BinaryFloatingPointNumber<binaryPrecision>; template <typename A> - RealOutputEditing(IoStatementState &io, A x) + RT_API_ATTRS RealOutputEditing(IoStatementState &io, A x) : RealOutputEditingBase{io}, x_{x} {} - bool Edit(const DataEdit &); + RT_API_ATTRS bool Edit(const DataEdit &); private: // The DataEdit arguments here are const references or copies so that // the original DataEdit can safely serve multiple array elements when // it has a repeat count. - bool EditEorDOutput(const DataEdit &); - bool EditFOutput(const DataEdit &); - DataEdit EditForGOutput(DataEdit); // returns an E or F edit - bool EditEXOutput(const DataEdit &); - bool EditListDirectedOutput(const DataEdit &); + RT_API_ATTRS bool EditEorDOutput(const DataEdit &); + RT_API_ATTRS bool EditFOutput(const DataEdit &); + RT_API_ATTRS DataEdit EditForGOutput(DataEdit); // returns an E or F edit + RT_API_ATTRS bool EditEXOutput(const DataEdit &); + RT_API_ATTRS bool EditListDirectedOutput(const DataEdit &); - bool IsZero() const { return x_.IsZero(); } + RT_API_ATTRS bool IsZero() const { return x_.IsZero(); } - decimal::ConversionToDecimalResult ConvertToDecimal( + RT_API_ATTRS decimal::ConversionToDecimalResult ConvertToDecimal( int significantDigits, enum decimal::FortranRounding, int flags = 0); struct ConvertToHexadecimalResult { @@ -78,7 +82,7 @@ private: int length; int exponent; }; - ConvertToHexadecimalResult ConvertToHexadecimal( + RT_API_ATTRS ConvertToHexadecimalResult ConvertToHexadecimal( int significantDigits, enum decimal::FortranRounding, int flags = 0); BinaryFloatingPoint x_; @@ -86,43 +90,43 @@ private: EXTRA_DECIMAL_CONVERSION_SPACE]; }; -bool ListDirectedLogicalOutput( +RT_API_ATTRS bool ListDirectedLogicalOutput( IoStatementState &, ListDirectedStatementState<Direction::Output> &, bool); -bool EditLogicalOutput(IoStatementState &, const DataEdit &, bool); +RT_API_ATTRS bool EditLogicalOutput(IoStatementState &, const DataEdit &, bool); template <typename CHAR> -bool ListDirectedCharacterOutput(IoStatementState &, +RT_API_ATTRS bool ListDirectedCharacterOutput(IoStatementState &, ListDirectedStatementState<Direction::Output> &, const CHAR *, std::size_t chars); -extern template bool ListDirectedCharacterOutput(IoStatementState &, - ListDirectedStatementState<Direction::Output> &, const char *, - std::size_t chars); -extern template bool ListDirectedCharacterOutput(IoStatementState &, - ListDirectedStatementState<Direction::Output> &, const char16_t *, - std::size_t chars); -extern template bool ListDirectedCharacterOutput(IoStatementState &, - ListDirectedStatementState<Direction::Output> &, const char32_t *, - std::size_t chars); +extern template RT_API_ATTRS bool ListDirectedCharacterOutput( + IoStatementState &, ListDirectedStatementState<Direction::Output> &, + const char *, std::size_t chars); +extern template RT_API_ATTRS bool ListDirectedCharacterOutput( + IoStatementState &, ListDirectedStatementState<Direction::Output> &, + const char16_t *, std::size_t chars); +extern template RT_API_ATTRS bool ListDirectedCharacterOutput( + IoStatementState &, ListDirectedStatementState<Direction::Output> &, + const char32_t *, std::size_t chars); template <typename CHAR> -bool EditCharacterOutput( +RT_API_ATTRS bool EditCharacterOutput( IoStatementState &, const DataEdit &, const CHAR *, std::size_t chars); -extern template bool EditCharacterOutput( +extern template RT_API_ATTRS bool EditCharacterOutput( IoStatementState &, const DataEdit &, const char *, std::size_t chars); -extern template bool EditCharacterOutput( +extern template RT_API_ATTRS bool EditCharacterOutput( IoStatementState &, const DataEdit &, const char16_t *, std::size_t chars); -extern template bool EditCharacterOutput( +extern template RT_API_ATTRS bool EditCharacterOutput( IoStatementState &, const DataEdit &, const char32_t *, std::size_t chars); -extern template bool EditIntegerOutput<1>( +extern template RT_API_ATTRS bool EditIntegerOutput<1>( IoStatementState &, const DataEdit &, std::int8_t); -extern template bool EditIntegerOutput<2>( +extern template RT_API_ATTRS bool EditIntegerOutput<2>( IoStatementState &, const DataEdit &, std::int16_t); -extern template bool EditIntegerOutput<4>( +extern template RT_API_ATTRS bool EditIntegerOutput<4>( IoStatementState &, const DataEdit &, std::int32_t); -extern template bool EditIntegerOutput<8>( +extern template RT_API_ATTRS bool EditIntegerOutput<8>( IoStatementState &, const DataEdit &, std::int64_t); -extern template bool EditIntegerOutput<16>( +extern template RT_API_ATTRS bool EditIntegerOutput<16>( IoStatementState &, const DataEdit &, common::int128_t); extern template class RealOutputEditing<2>; diff --git a/flang/runtime/emit-encoded.h b/flang/runtime/emit-encoded.h index 864848c3b19c67ebda731be195a1c372553e3f91..ac8c7d758a0d00cdd0e16fe0bf347c4a32960021 100644 --- a/flang/runtime/emit-encoded.h +++ b/flang/runtime/emit-encoded.h @@ -19,7 +19,8 @@ namespace Fortran::runtime::io { template <typename CONTEXT, typename CHAR> -bool EmitEncoded(CONTEXT &to, const CHAR *data, std::size_t chars) { +RT_API_ATTRS bool EmitEncoded( + CONTEXT &to, const CHAR *data, std::size_t chars) { ConnectionState &connection{to.GetConnectionState()}; if (connection.access == Access::Stream && connection.internalIoCharKind == 0) { @@ -74,7 +75,7 @@ bool EmitEncoded(CONTEXT &to, const CHAR *data, std::size_t chars) { } template <typename CONTEXT> -bool EmitAscii(CONTEXT &to, const char *data, std::size_t chars) { +RT_API_ATTRS bool EmitAscii(CONTEXT &to, const char *data, std::size_t chars) { ConnectionState &connection{to.GetConnectionState()}; if (connection.internalIoCharKind <= 1 && connection.access != Access::Stream) { @@ -85,7 +86,7 @@ bool EmitAscii(CONTEXT &to, const char *data, std::size_t chars) { } template <typename CONTEXT> -bool EmitRepeated(CONTEXT &to, char ch, std::size_t n) { +RT_API_ATTRS bool EmitRepeated(CONTEXT &to, char ch, std::size_t n) { if (n <= 0) { return true; } diff --git a/flang/runtime/environment.cpp b/flang/runtime/environment.cpp index 62d9ee2afd1cebb59ee2725279661ce663169f9b..b74067a377774bee4144193276552be6c33a71cd 100644 --- a/flang/runtime/environment.cpp +++ b/flang/runtime/environment.cpp @@ -23,7 +23,9 @@ extern char **environ; namespace Fortran::runtime { -ExecutionEnvironment executionEnvironment; +RT_OFFLOAD_VAR_GROUP_BEGIN +RT_VAR_ATTRS ExecutionEnvironment executionEnvironment; +RT_OFFLOAD_VAR_GROUP_END static void SetEnvironmentDefaults(const EnvironmentDefaultList *envDefaults) { if (!envDefaults) { @@ -47,7 +49,8 @@ static void SetEnvironmentDefaults(const EnvironmentDefaultList *envDefaults) { } } -std::optional<Convert> GetConvertFromString(const char *x, std::size_t n) { +Fortran::common::optional<Convert> GetConvertFromString( + const char *x, std::size_t n) { static const char *keywords[]{ "UNKNOWN", "NATIVE", "LITTLE_ENDIAN", "BIG_ENDIAN", "SWAP", nullptr}; switch (IdentifyValue(x, n, keywords)) { @@ -62,7 +65,7 @@ std::optional<Convert> GetConvertFromString(const char *x, std::size_t n) { case 4: return Convert::Swap; default: - return std::nullopt; + return Fortran::common::nullopt; } } @@ -123,6 +126,19 @@ void ExecutionEnvironment::Configure(int ac, const char *av[], } } + if (auto *x{std::getenv("FORT_CHECK_POINTER_DEALLOCATION")}) { + char *end; + auto n{std::strtol(x, &end, 10)}; + if (n >= 0 && n <= 1 && *end == '\0') { + checkPointerDeallocation = n != 0; + } else { + std::fprintf(stderr, + "Fortran runtime: FORT_CHECK_POINTER_DEALLOCATION=%s is invalid; " + "ignored\n", + x); + } + } + // TODO: Set RP/ROUND='PROCESSOR_DEFINED' from environment } diff --git a/flang/runtime/environment.h b/flang/runtime/environment.h index 82a5ec8f4ebfb0681cedcd5a444af0326673eee6..6c56993fb1d6ec692a19112d6c243a7c2ea48c70 100644 --- a/flang/runtime/environment.h +++ b/flang/runtime/environment.h @@ -9,8 +9,8 @@ #ifndef FORTRAN_RUNTIME_ENVIRONMENT_H_ #define FORTRAN_RUNTIME_ENVIRONMENT_H_ +#include "flang/Common/optional.h" #include "flang/Decimal/decimal.h" -#include <optional> struct EnvironmentDefaultList; @@ -18,6 +18,7 @@ namespace Fortran::runtime { class Terminator; +RT_OFFLOAD_VAR_GROUP_BEGIN #if FLANG_BIG_ENDIAN constexpr bool isHostLittleEndian{false}; #elif FLANG_LITTLE_ENDIAN @@ -25,14 +26,20 @@ constexpr bool isHostLittleEndian{true}; #else #error host endianness is not known #endif +RT_OFFLOAD_VAR_GROUP_END // External unformatted I/O data conversions enum class Convert { Unknown, Native, LittleEndian, BigEndian, Swap }; -std::optional<Convert> GetConvertFromString(const char *, std::size_t); +Fortran::common::optional<Convert> GetConvertFromString( + const char *, std::size_t); struct ExecutionEnvironment { - constexpr ExecutionEnvironment(){}; +#if !defined(_OPENMP) + // FIXME: https://github.com/llvm/llvm-project/issues/84942 + constexpr +#endif + ExecutionEnvironment(){}; void Configure(int argc, const char *argv[], const char *envp[], const EnvironmentDefaultList *envDefaults); const char *GetEnv( @@ -48,9 +55,13 @@ struct ExecutionEnvironment { Convert conversion{Convert::Unknown}; // FORT_CONVERT bool noStopMessage{false}; // NO_STOP_MESSAGE=1 inhibits "Fortran STOP" bool defaultUTF8{false}; // DEFAULT_UTF8 + bool checkPointerDeallocation{true}; // FORT_CHECK_POINTER_DEALLOCATION }; -extern ExecutionEnvironment executionEnvironment; +RT_OFFLOAD_VAR_GROUP_BEGIN +extern RT_VAR_ATTRS ExecutionEnvironment executionEnvironment; +RT_OFFLOAD_VAR_GROUP_END + } // namespace Fortran::runtime #endif // FORTRAN_RUNTIME_ENVIRONMENT_H_ diff --git a/flang/runtime/external-unit.cpp b/flang/runtime/external-unit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b48549d54587eb63f1843890439005083517f291 --- /dev/null +++ b/flang/runtime/external-unit.cpp @@ -0,0 +1,336 @@ +//===-- runtime/external-unit.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 +// +//===----------------------------------------------------------------------===// +// +// Implemenation of ExternalFileUnit for RT_USE_PSEUDO_FILE_UNIT=0. +// +//===----------------------------------------------------------------------===// + +#include "io-error.h" +#include "lock.h" +#include "tools.h" +#include "unit-map.h" +#include "unit.h" + +// NOTE: the header files above may define OpenMP declare target +// variables, so they have to be included unconditionally +// so that the offload entries are consistent between host and device. +#if !defined(RT_USE_PSEUDO_FILE_UNIT) + +#include <cstdio> +#include <limits> + +namespace Fortran::runtime::io { + +// The per-unit data structures are created on demand so that Fortran I/O +// should work without a Fortran main program. +static Lock unitMapLock; +static Lock createOpenLock; +static UnitMap *unitMap{nullptr}; + +void FlushOutputOnCrash(const Terminator &terminator) { + if (!defaultOutput && !errorOutput) { + return; + } + IoErrorHandler handler{terminator}; + handler.HasIoStat(); // prevent nested crash if flush has error + CriticalSection critical{unitMapLock}; + if (defaultOutput) { + defaultOutput->FlushOutput(handler); + } + if (errorOutput) { + errorOutput->FlushOutput(handler); + } +} + +ExternalFileUnit *ExternalFileUnit::LookUp(int unit) { + return GetUnitMap().LookUp(unit); +} + +ExternalFileUnit *ExternalFileUnit::LookUpOrCreate( + int unit, const Terminator &terminator, bool &wasExtant) { + return GetUnitMap().LookUpOrCreate(unit, terminator, wasExtant); +} + +ExternalFileUnit *ExternalFileUnit::LookUpOrCreateAnonymous(int unit, + Direction dir, Fortran::common::optional<bool> isUnformatted, + const Terminator &terminator) { + // Make sure that the returned anonymous unit has been opened + // not just created in the unitMap. + CriticalSection critical{createOpenLock}; + bool exists{false}; + ExternalFileUnit *result{ + GetUnitMap().LookUpOrCreate(unit, terminator, exists)}; + if (result && !exists) { + IoErrorHandler handler{terminator}; + result->OpenAnonymousUnit( + dir == Direction::Input ? OpenStatus::Unknown : OpenStatus::Replace, + Action::ReadWrite, Position::Rewind, Convert::Unknown, handler); + result->isUnformatted = isUnformatted; + } + return result; +} + +ExternalFileUnit *ExternalFileUnit::LookUp( + const char *path, std::size_t pathLen) { + return GetUnitMap().LookUp(path, pathLen); +} + +ExternalFileUnit &ExternalFileUnit::CreateNew( + int unit, const Terminator &terminator) { + bool wasExtant{false}; + ExternalFileUnit *result{ + GetUnitMap().LookUpOrCreate(unit, terminator, wasExtant)}; + RUNTIME_CHECK(terminator, result && !wasExtant); + return *result; +} + +ExternalFileUnit *ExternalFileUnit::LookUpForClose(int unit) { + return GetUnitMap().LookUpForClose(unit); +} + +ExternalFileUnit &ExternalFileUnit::NewUnit( + const Terminator &terminator, bool forChildIo) { + ExternalFileUnit &unit{GetUnitMap().NewUnit(terminator)}; + unit.createdForInternalChildIo_ = forChildIo; + return unit; +} + +bool ExternalFileUnit::OpenUnit(Fortran::common::optional<OpenStatus> status, + Fortran::common::optional<Action> action, Position position, + OwningPtr<char> &&newPath, std::size_t newPathLength, Convert convert, + IoErrorHandler &handler) { + if (convert == Convert::Unknown) { + convert = executionEnvironment.conversion; + } + swapEndianness_ = convert == Convert::Swap || + (convert == Convert::LittleEndian && !isHostLittleEndian) || + (convert == Convert::BigEndian && isHostLittleEndian); + bool impliedClose{false}; + if (IsConnected()) { + bool isSamePath{newPath.get() && path() && pathLength() == newPathLength && + std::memcmp(path(), newPath.get(), newPathLength) == 0}; + if (status && *status != OpenStatus::Old && isSamePath) { + handler.SignalError("OPEN statement for connected unit may not have " + "explicit STATUS= other than 'OLD'"); + return impliedClose; + } + if (!newPath.get() || isSamePath) { + // OPEN of existing unit, STATUS='OLD' or unspecified, not new FILE= + newPath.reset(); + return impliedClose; + } + // Otherwise, OPEN on open unit with new FILE= implies CLOSE + DoImpliedEndfile(handler); + FlushOutput(handler); + TruncateFrame(0, handler); + Close(CloseStatus::Keep, handler); + impliedClose = true; + } + if (newPath.get() && newPathLength > 0) { + if (const auto *already{ + GetUnitMap().LookUp(newPath.get(), newPathLength)}) { + handler.SignalError(IostatOpenAlreadyConnected, + "OPEN(UNIT=%d,FILE='%.*s'): file is already connected to unit %d", + unitNumber_, static_cast<int>(newPathLength), newPath.get(), + already->unitNumber_); + return impliedClose; + } + } + set_path(std::move(newPath), newPathLength); + Open(status.value_or(OpenStatus::Unknown), action, position, handler); + auto totalBytes{knownSize()}; + if (access == Access::Direct) { + if (!openRecl) { + handler.SignalError(IostatOpenBadRecl, + "OPEN(UNIT=%d,ACCESS='DIRECT'): record length is not known", + unitNumber()); + } else if (*openRecl <= 0) { + handler.SignalError(IostatOpenBadRecl, + "OPEN(UNIT=%d,ACCESS='DIRECT',RECL=%jd): record length is invalid", + unitNumber(), static_cast<std::intmax_t>(*openRecl)); + } else if (totalBytes && (*totalBytes % *openRecl != 0)) { + handler.SignalError(IostatOpenBadRecl, + "OPEN(UNIT=%d,ACCESS='DIRECT',RECL=%jd): record length is not an " + "even divisor of the file size %jd", + unitNumber(), static_cast<std::intmax_t>(*openRecl), + static_cast<std::intmax_t>(*totalBytes)); + } + recordLength = openRecl; + } + endfileRecordNumber.reset(); + currentRecordNumber = 1; + if (totalBytes && access == Access::Direct && openRecl.value_or(0) > 0) { + endfileRecordNumber = 1 + (*totalBytes / *openRecl); + } + if (position == Position::Append) { + if (totalBytes) { + frameOffsetInFile_ = *totalBytes; + } + if (access != Access::Stream) { + if (!endfileRecordNumber) { + // Fake it so that we can backspace relative from the end + endfileRecordNumber = std::numeric_limits<std::int64_t>::max() - 2; + } + currentRecordNumber = *endfileRecordNumber; + } + } + return impliedClose; +} + +void ExternalFileUnit::OpenAnonymousUnit( + Fortran::common::optional<OpenStatus> status, + Fortran::common::optional<Action> action, Position position, + Convert convert, IoErrorHandler &handler) { + // I/O to an unconnected unit reads/creates a local file, e.g. fort.7 + std::size_t pathMaxLen{32}; + auto path{SizedNew<char>{handler}(pathMaxLen)}; + std::snprintf(path.get(), pathMaxLen, "fort.%d", unitNumber_); + OpenUnit(status, action, position, std::move(path), std::strlen(path.get()), + convert, handler); +} + +void ExternalFileUnit::CloseUnit(CloseStatus status, IoErrorHandler &handler) { + DoImpliedEndfile(handler); + FlushOutput(handler); + Close(status, handler); +} + +void ExternalFileUnit::DestroyClosed() { + GetUnitMap().DestroyClosed(*this); // destroys *this +} + +Iostat ExternalFileUnit::SetDirection(Direction direction) { + if (direction == Direction::Input) { + if (mayRead()) { + direction_ = Direction::Input; + return IostatOk; + } else { + return IostatReadFromWriteOnly; + } + } else { + if (mayWrite()) { + direction_ = Direction::Output; + return IostatOk; + } else { + return IostatWriteToReadOnly; + } + } +} + +UnitMap &ExternalFileUnit::CreateUnitMap() { + Terminator terminator{__FILE__, __LINE__}; + IoErrorHandler handler{terminator}; + UnitMap &newUnitMap{*New<UnitMap>{terminator}().release()}; + + bool wasExtant{false}; + ExternalFileUnit &out{*newUnitMap.LookUpOrCreate( + FORTRAN_DEFAULT_OUTPUT_UNIT, terminator, wasExtant)}; + RUNTIME_CHECK(terminator, !wasExtant); + out.Predefine(1); + handler.SignalError(out.SetDirection(Direction::Output)); + out.isUnformatted = false; + defaultOutput = &out; + + ExternalFileUnit &in{*newUnitMap.LookUpOrCreate( + FORTRAN_DEFAULT_INPUT_UNIT, terminator, wasExtant)}; + RUNTIME_CHECK(terminator, !wasExtant); + in.Predefine(0); + handler.SignalError(in.SetDirection(Direction::Input)); + in.isUnformatted = false; + defaultInput = ∈ + + ExternalFileUnit &error{ + *newUnitMap.LookUpOrCreate(FORTRAN_ERROR_UNIT, terminator, wasExtant)}; + RUNTIME_CHECK(terminator, !wasExtant); + error.Predefine(2); + handler.SignalError(error.SetDirection(Direction::Output)); + error.isUnformatted = false; + errorOutput = &error; + + return newUnitMap; +} + +// A back-up atexit() handler for programs that don't terminate with a main +// program END or a STOP statement or other Fortran-initiated program shutdown, +// such as programs with a C main() that terminate normally. It flushes all +// external I/O units. It is registered once the first time that any external +// I/O is attempted. +static void CloseAllExternalUnits() { + IoErrorHandler handler{"Fortran program termination"}; + ExternalFileUnit::CloseAll(handler); +} + +UnitMap &ExternalFileUnit::GetUnitMap() { + if (unitMap) { + return *unitMap; + } + { + CriticalSection critical{unitMapLock}; + if (unitMap) { + return *unitMap; + } + unitMap = &CreateUnitMap(); + } + std::atexit(CloseAllExternalUnits); + return *unitMap; +} + +void ExternalFileUnit::CloseAll(IoErrorHandler &handler) { + CriticalSection critical{unitMapLock}; + if (unitMap) { + unitMap->CloseAll(handler); + FreeMemoryAndNullify(unitMap); + } + defaultOutput = nullptr; + defaultInput = nullptr; + errorOutput = nullptr; +} + +void ExternalFileUnit::FlushAll(IoErrorHandler &handler) { + CriticalSection critical{unitMapLock}; + if (unitMap) { + unitMap->FlushAll(handler); + } +} + +int ExternalFileUnit::GetAsynchronousId(IoErrorHandler &handler) { + if (!mayAsynchronous()) { + handler.SignalError(IostatBadAsynchronous); + return -1; + } else { + for (int j{0}; 64 * j < maxAsyncIds; ++j) { + if (auto least{asyncIdAvailable_[j].LeastElement()}) { + asyncIdAvailable_[j].reset(*least); + return 64 * j + static_cast<int>(*least); + } + } + handler.SignalError(IostatTooManyAsyncOps); + return -1; + } +} + +bool ExternalFileUnit::Wait(int id) { + if (static_cast<std::size_t>(id) >= maxAsyncIds || + asyncIdAvailable_[id / 64].test(id % 64)) { + return false; + } else { + if (id == 0) { // means "all IDs" + for (int j{0}; 64 * j < maxAsyncIds; ++j) { + asyncIdAvailable_[j].set(); + } + asyncIdAvailable_[0].reset(0); + } else { + asyncIdAvailable_[id / 64].set(id % 64); + } + return true; + } +} + +} // namespace Fortran::runtime::io + +#endif // !defined(RT_USE_PSEUDO_FILE_UNIT) diff --git a/flang/runtime/extrema.cpp b/flang/runtime/extrema.cpp index 61afb0458430db8a4b45c0b9464a006e44883247..d6e9633372f5249d3100de6d390a96f5e0793b53 100644 --- a/flang/runtime/extrema.cpp +++ b/flang/runtime/extrema.cpp @@ -18,7 +18,6 @@ #include <cfloat> #include <cinttypes> #include <cmath> -#include <optional> #include <type_traits> namespace Fortran::runtime { diff --git a/flang/runtime/file.cpp b/flang/runtime/file.cpp index 5cf91b8d64c86361b3a0ad6e627ca51eb63ba999..67764f1f562624c6a0b19e0459866039c2d1bd24 100644 --- a/flang/runtime/file.cpp +++ b/flang/runtime/file.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "file.h" +#include "tools.h" #include "flang/Runtime/magic-numbers.h" #include "flang/Runtime/memory.h" #include <algorithm> @@ -60,7 +61,7 @@ static int openfile_mkstemp(IoErrorHandler &handler) { return fd; } -void OpenFile::Open(OpenStatus status, std::optional<Action> action, +void OpenFile::Open(OpenStatus status, Fortran::common::optional<Action> action, Position position, IoErrorHandler &handler) { if (fd_ >= 0 && (status == OpenStatus::Old || status == OpenStatus::Unknown)) { @@ -322,7 +323,7 @@ int OpenFile::WriteAsynchronously(FileOffset at, const char *buffer, } void OpenFile::Wait(int id, IoErrorHandler &handler) { - std::optional<int> ioStat; + Fortran::common::optional<int> ioStat; Pending *prev{nullptr}; for (Pending *p{pending_.get()}; p; p = (prev = p)->next.get()) { if (p->id == id) { @@ -424,6 +425,7 @@ void OpenFile::CloseFd(IoErrorHandler &handler) { } } +#if !defined(RT_DEVICE_COMPILATION) bool IsATerminal(int fd) { return ::isatty(fd); } #if defined(_WIN32) && !defined(F_OK) @@ -455,5 +457,25 @@ std::int64_t SizeInBytes(const char *path) { // No Fortran compiler signals an error return -1; } +#else // defined(RT_DEVICE_COMPILATION) +bool IsATerminal(int fd) { + Terminator{__FILE__, __LINE__}.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} +bool IsExtant(const char *path) { + Terminator{__FILE__, __LINE__}.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} +bool MayRead(const char *path) { + Terminator{__FILE__, __LINE__}.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} +bool MayWrite(const char *path) { + Terminator{__FILE__, __LINE__}.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} +bool MayReadAndWrite(const char *path) { + Terminator{__FILE__, __LINE__}.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} +std::int64_t SizeInBytes(const char *path) { + Terminator{__FILE__, __LINE__}.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} +#endif // defined(RT_DEVICE_COMPILATION) } // namespace Fortran::runtime::io diff --git a/flang/runtime/file.h b/flang/runtime/file.h index a0712136a7f3dfde1988daf511800a80cd8164b6..c06acbb9904cc1abf8adbd1dfb137c04686b48d5 100644 --- a/flang/runtime/file.h +++ b/flang/runtime/file.h @@ -12,9 +12,9 @@ #define FORTRAN_RUNTIME_FILE_H_ #include "io-error.h" +#include "flang/Common/optional.h" #include "flang/Runtime/memory.h" #include <cinttypes> -#include <optional> namespace Fortran::runtime::io { @@ -37,10 +37,11 @@ public: void set_mayAsynchronous(bool yes) { mayAsynchronous_ = yes; } bool isTerminal() const { return isTerminal_; } bool isWindowsTextFile() const { return isWindowsTextFile_; } - std::optional<FileOffset> knownSize() const { return knownSize_; } + Fortran::common::optional<FileOffset> knownSize() const { return knownSize_; } bool IsConnected() const { return fd_ >= 0; } - void Open(OpenStatus, std::optional<Action>, Position, IoErrorHandler &); + void Open(OpenStatus, Fortran::common::optional<Action>, Position, + IoErrorHandler &); void Predefine(int fd); void Close(CloseStatus, IoErrorHandler &); @@ -94,9 +95,10 @@ private: bool mayWrite_{false}; bool mayPosition_{false}; bool mayAsynchronous_{false}; - std::optional<Position> openPosition_; // from Open(); reset after positioning + Fortran::common::optional<Position> + openPosition_; // from Open(); reset after positioning FileOffset position_{0}; - std::optional<FileOffset> knownSize_; + Fortran::common::optional<FileOffset> knownSize_; bool isTerminal_{false}; bool isWindowsTextFile_{false}; // expands LF to CR+LF on write @@ -104,11 +106,11 @@ private: OwningPtr<Pending> pending_; }; -bool IsATerminal(int fd); -bool IsExtant(const char *path); -bool MayRead(const char *path); -bool MayWrite(const char *path); -bool MayReadAndWrite(const char *path); -std::int64_t SizeInBytes(const char *path); +RT_API_ATTRS bool IsATerminal(int fd); +RT_API_ATTRS bool IsExtant(const char *path); +RT_API_ATTRS bool MayRead(const char *path); +RT_API_ATTRS bool MayWrite(const char *path); +RT_API_ATTRS bool MayReadAndWrite(const char *path); +RT_API_ATTRS std::int64_t SizeInBytes(const char *path); } // namespace Fortran::runtime::io #endif // FORTRAN_RUNTIME_FILE_H_ diff --git a/flang/runtime/format-implementation.h b/flang/runtime/format-implementation.h index 9c342db2e19a24601fde9a59323e3e4da0fcf5be..45d4bd641f6f665a02bb4a2e5c8faebca2b3a7b3 100644 --- a/flang/runtime/format-implementation.h +++ b/flang/runtime/format-implementation.h @@ -25,7 +25,7 @@ namespace Fortran::runtime::io { template <typename CONTEXT> -FormatControl<CONTEXT>::FormatControl(const Terminator &terminator, +RT_API_ATTRS FormatControl<CONTEXT>::FormatControl(const Terminator &terminator, const CharType *format, std::size_t formatLength, const Descriptor *formatDescriptor, int maxHeight) : maxHeight_{static_cast<std::uint8_t>(maxHeight)}, format_{format}, @@ -63,18 +63,9 @@ FormatControl<CONTEXT>::FormatControl(const Terminator &terminator, } template <typename CONTEXT> -int FormatControl<CONTEXT>::GetIntField( +RT_API_ATTRS int FormatControl<CONTEXT>::GetIntField( IoErrorHandler &handler, CharType firstCh, bool *hadError) { CharType ch{firstCh ? firstCh : PeekNext()}; - if (ch != '-' && ch != '+' && (ch < '0' || ch > '9')) { - handler.SignalError(IostatErrorInFormat, - "Invalid FORMAT: integer expected at '%c'", static_cast<char>(ch)); - if (hadError) { - *hadError = true; - } - return 0; - } - int result{0}; bool negate{ch == '-'}; if (negate || ch == '+') { if (firstCh) { @@ -84,6 +75,15 @@ int FormatControl<CONTEXT>::GetIntField( } ch = PeekNext(); } + if (ch < '0' || ch > '9') { + handler.SignalError(IostatErrorInFormat, + "Invalid FORMAT: integer expected at '%c'", static_cast<char>(ch)); + if (hadError) { + *hadError = true; + } + return 0; + } + int result{0}; while (ch >= '0' && ch <= '9') { constexpr int tenth{std::numeric_limits<int>::max() / 10}; if (result > tenth || @@ -114,7 +114,8 @@ int FormatControl<CONTEXT>::GetIntField( } template <typename CONTEXT> -static void HandleControl(CONTEXT &context, char ch, char next, int n) { +static RT_API_ATTRS void HandleControl( + CONTEXT &context, char ch, char next, int n) { MutableModes &modes{context.mutableModes()}; switch (ch) { case 'B': @@ -221,7 +222,8 @@ static void HandleControl(CONTEXT &context, char ch, char next, int n) { // Generally assumes that the format string has survived the common // format validator gauntlet. template <typename CONTEXT> -int FormatControl<CONTEXT>::CueUpNextDataEdit(Context &context, bool stop) { +RT_API_ATTRS int FormatControl<CONTEXT>::CueUpNextDataEdit( + Context &context, bool stop) { bool hitUnlimitedLoopEnd{false}; // Do repetitions remain on an unparenthesized data edit? while (height_ > 1 && format_[stack_[height_ - 1].start] != '(') { @@ -233,7 +235,7 @@ int FormatControl<CONTEXT>::CueUpNextDataEdit(Context &context, bool stop) { } } while (true) { - std::optional<int> repeat; + Fortran::common::optional<int> repeat; bool unlimited{false}; auto maybeReversionPoint{offset_}; CharType ch{GetNextChar(context)}; @@ -246,8 +248,15 @@ int FormatControl<CONTEXT>::CueUpNextDataEdit(Context &context, bool stop) { ch = GetNextChar(context); } if (ch == '-' || ch == '+' || (ch >= '0' && ch <= '9')) { + bool hadSign{ch == '-' || ch == '+'}; repeat = GetIntField(context, ch); ch = GetNextChar(context); + if (hadSign && ch != 'p' && ch != 'P') { + ReportBadFormat(context, + "Invalid FORMAT: signed integer may appear only before 'P", + maybeReversionPoint); + return 0; + } } else if (ch == '*') { unlimited = true; ch = GetNextChar(context); @@ -297,11 +306,11 @@ int FormatControl<CONTEXT>::CueUpNextDataEdit(Context &context, bool stop) { return 0; } else if (ch == ')') { if (height_ == 1) { + hitEnd_ = true; if (stop) { return 0; // end of FORMAT and no data items remain } context.AdvanceRecord(); // implied / before rightmost ) - hitEnd_ = true; } auto restart{stack_[height_ - 1].start}; if (format_[restart] == '(') { @@ -412,8 +421,8 @@ int FormatControl<CONTEXT>::CueUpNextDataEdit(Context &context, bool stop) { // Returns the next data edit descriptor template <typename CONTEXT> -std::optional<DataEdit> FormatControl<CONTEXT>::GetNextDataEdit( - Context &context, int maxRepeat) { +RT_API_ATTRS Fortran::common::optional<DataEdit> +FormatControl<CONTEXT>::GetNextDataEdit(Context &context, int maxRepeat) { int repeat{CueUpNextDataEdit(context)}; auto start{offset_}; DataEdit edit; @@ -444,7 +453,7 @@ std::optional<DataEdit> FormatControl<CONTEXT>::GetNextDataEdit( } if (edit.ioTypeChars >= edit.maxIoTypeChars) { ReportBadFormat(context, "Excessive DT'iotype' in FORMAT", start); - return std::nullopt; + return Fortran::common::nullopt; } edit.ioType[edit.ioTypeChars++] = ch; if (ch == quote) { @@ -453,7 +462,7 @@ std::optional<DataEdit> FormatControl<CONTEXT>::GetNextDataEdit( } if (!ok) { ReportBadFormat(context, "Unclosed DT'iotype' in FORMAT", start); - return std::nullopt; + return Fortran::common::nullopt; } } if (PeekNext() == '(') { @@ -468,7 +477,7 @@ std::optional<DataEdit> FormatControl<CONTEXT>::GetNextDataEdit( } if (edit.vListEntries >= edit.maxVListEntries) { ReportBadFormat(context, "Excessive DT(v_list) in FORMAT", start); - return std::nullopt; + return Fortran::common::nullopt; } edit.vList[edit.vListEntries++] = n; auto ch{static_cast<char>(GetNextChar(context))}; @@ -479,7 +488,7 @@ std::optional<DataEdit> FormatControl<CONTEXT>::GetNextDataEdit( } if (!ok) { ReportBadFormat(context, "Unclosed DT(v_list) in FORMAT", start); - return std::nullopt; + return Fortran::common::nullopt; } } } else { // not DT'iotype' @@ -517,7 +526,7 @@ std::optional<DataEdit> FormatControl<CONTEXT>::GetNextDataEdit( } template <typename CONTEXT> -void FormatControl<CONTEXT>::Finish(Context &context) { +RT_API_ATTRS void FormatControl<CONTEXT>::Finish(Context &context) { CueUpNextDataEdit(context, true /* stop at colon or end of FORMAT */); if (freeFormat_) { FreeMemory(const_cast<CharType *>(format_)); diff --git a/flang/runtime/format.cpp b/flang/runtime/format.cpp index f219c29aaed1422443086c56869c95b2185b4f16..433acce4b73739d0a80ae4f9799c7d4d79dd732d 100644 --- a/flang/runtime/format.cpp +++ b/flang/runtime/format.cpp @@ -9,6 +9,7 @@ #include "format-implementation.h" namespace Fortran::runtime::io { +RT_OFFLOAD_API_GROUP_BEGIN template class FormatControl< InternalFormattedIoStatementState<Direction::Output>>; template class FormatControl< @@ -19,4 +20,5 @@ template class FormatControl< ExternalFormattedIoStatementState<Direction::Input>>; template class FormatControl<ChildFormattedIoStatementState<Direction::Output>>; template class FormatControl<ChildFormattedIoStatementState<Direction::Input>>; +RT_OFFLOAD_API_GROUP_END } // namespace Fortran::runtime::io diff --git a/flang/runtime/format.h b/flang/runtime/format.h index 1fe0802ac43c6959d141ba554465c1f8db84ba74..f57cf920448712d7bcd685c02c86920e824252d0 100644 --- a/flang/runtime/format.h +++ b/flang/runtime/format.h @@ -12,11 +12,12 @@ #define FORTRAN_RUNTIME_FORMAT_H_ #include "environment.h" +#include "freestanding-tools.h" #include "io-error.h" #include "flang/Common/Fortran.h" +#include "flang/Common/optional.h" #include "flang/Decimal/decimal.h" #include <cinttypes> -#include <optional> namespace Fortran::runtime { class Descriptor; @@ -49,31 +50,34 @@ struct DataEdit { char descriptor; // capitalized: one of A, I, B, O, Z, F, E(N/S/X), D, G // Special internal data edit descriptors for list-directed & NAMELIST I/O + RT_OFFLOAD_VAR_GROUP_BEGIN static constexpr char ListDirected{'g'}; // non-COMPLEX list-directed static constexpr char ListDirectedRealPart{'r'}; // emit "(r," or "(r;" static constexpr char ListDirectedImaginaryPart{'z'}; // emit "z)" static constexpr char ListDirectedNullValue{'n'}; // see 13.10.3.2 - constexpr bool IsListDirected() const { + static constexpr char DefinedDerivedType{'d'}; // DT defined I/O + RT_OFFLOAD_VAR_GROUP_END + constexpr RT_API_ATTRS bool IsListDirected() const { return descriptor == ListDirected || descriptor == ListDirectedRealPart || descriptor == ListDirectedImaginaryPart; } - constexpr bool IsNamelist() const { + constexpr RT_API_ATTRS bool IsNamelist() const { return IsListDirected() && modes.inNamelist; } - static constexpr char DefinedDerivedType{'d'}; // DT defined I/O - char variation{'\0'}; // N, S, or X for EN, ES, EX; G/l for original G/list - std::optional<int> width; // the 'w' field; optional for A - std::optional<int> digits; // the 'm' or 'd' field - std::optional<int> expoDigits; // 'Ee' field + Fortran::common::optional<int> width; // the 'w' field; optional for A + Fortran::common::optional<int> digits; // the 'm' or 'd' field + Fortran::common::optional<int> expoDigits; // 'Ee' field MutableModes modes; int repeat{1}; // "iotype" &/or "v_list" values for a DT'iotype'(v_list) // defined I/O data edit descriptor + RT_OFFLOAD_VAR_GROUP_BEGIN static constexpr std::size_t maxIoTypeChars{32}; static constexpr std::size_t maxVListEntries{4}; + RT_OFFLOAD_VAR_GROUP_END std::uint8_t ioTypeChars{0}; std::uint8_t vListEntries{0}; char ioType[maxIoTypeChars]; @@ -88,13 +92,13 @@ public: using Context = CONTEXT; using CharType = char; // formats are always default kind CHARACTER - FormatControl() {} - FormatControl(const Terminator &, const CharType *format, + RT_API_ATTRS FormatControl() {} + RT_API_ATTRS FormatControl(const Terminator &, const CharType *format, std::size_t formatLength, const Descriptor *formatDescriptor = nullptr, int maxHeight = maxMaxHeight); // For attempting to allocate in a user-supplied stack area - static std::size_t GetNeededSize(int maxHeight) { + static RT_API_ATTRS std::size_t GetNeededSize(int maxHeight) { return sizeof(FormatControl) - sizeof(Iteration) * (maxMaxHeight - maxHeight); } @@ -102,13 +106,15 @@ public: // Extracts the next data edit descriptor, handling control edit descriptors // along the way. If maxRepeat==0, this is a peek at the next data edit // descriptor. - std::optional<DataEdit> GetNextDataEdit(Context &, int maxRepeat = 1); + RT_API_ATTRS Fortran::common::optional<DataEdit> GetNextDataEdit( + Context &, int maxRepeat = 1); // Emit any remaining character literals after the last data item (on output) // and perform remaining record positioning actions. - void Finish(Context &); + RT_API_ATTRS void Finish(Context &); private: + RT_OFFLOAD_VAR_GROUP_BEGIN static constexpr std::uint8_t maxMaxHeight{100}; struct Iteration { @@ -116,19 +122,20 @@ private: int start{0}; // offset in format_ of '(' or a repeated edit descriptor int remaining{0}; // while >0, decrement and iterate }; + RT_OFFLOAD_VAR_GROUP_END - void SkipBlanks() { + RT_API_ATTRS void SkipBlanks() { while (offset_ < formatLength_ && (format_[offset_] == ' ' || format_[offset_] == '\t' || format_[offset_] == '\v')) { ++offset_; } } - CharType PeekNext() { + RT_API_ATTRS CharType PeekNext() { SkipBlanks(); return offset_ < formatLength_ ? format_[offset_] : '\0'; } - CharType GetNextChar(IoErrorHandler &handler) { + RT_API_ATTRS CharType GetNextChar(IoErrorHandler &handler) { SkipBlanks(); if (offset_ >= formatLength_) { if (formatLength_ == 0) { @@ -142,7 +149,7 @@ private: } return format_[offset_++]; } - int GetIntField( + RT_API_ATTRS int GetIntField( IoErrorHandler &, CharType firstCh = '\0', bool *hadError = nullptr); // Advances through the FORMAT until the next data edit @@ -150,13 +157,14 @@ private: // along the way. Returns the repeat count that appeared // before the descriptor (defaulting to 1) and leaves offset_ // pointing to the data edit. - int CueUpNextDataEdit(Context &, bool stop = false); + RT_API_ATTRS int CueUpNextDataEdit(Context &, bool stop = false); - static constexpr CharType Capitalize(CharType ch) { + static constexpr RT_API_ATTRS CharType Capitalize(CharType ch) { return ch >= 'a' && ch <= 'z' ? ch + 'A' - 'a' : ch; } - void ReportBadFormat(Context &context, const char *msg, int offset) const { + RT_API_ATTRS void ReportBadFormat( + Context &context, const char *msg, int offset) const { if constexpr (std::is_same_v<CharType, char>) { // Echo the bad format in the error message, but trim any leading or // trailing spaces. diff --git a/flang/runtime/freestanding-tools.h b/flang/runtime/freestanding-tools.h index bdc11ae93ac9097066f09f928c439c04bbe21169..451bf13b9fa6da8c5bcde958d29efe757e5a2760 100644 --- a/flang/runtime/freestanding-tools.h +++ b/flang/runtime/freestanding-tools.h @@ -9,7 +9,7 @@ #ifndef FORTRAN_RUNTIME_FREESTANDING_TOOLS_H_ #define FORTRAN_RUNTIME_FREESTANDING_TOOLS_H_ -#include "flang/Runtime/api-attrs.h" +#include "flang/Common/api-attrs.h" #include "flang/Runtime/c-or-cpp.h" #include <algorithm> #include <cstring> @@ -42,14 +42,24 @@ #define STD_REALLOC_UNSUPPORTED 1 #endif +#if !defined(STD_MEMCHR_UNSUPPORTED) && \ + (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) +#define STD_MEMCHR_UNSUPPORTED 1 +#endif + +#if !defined(STD_STRCPY_UNSUPPORTED) && \ + (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) +#define STD_STRCPY_UNSUPPORTED 1 +#endif + namespace Fortran::runtime { #if STD_FILL_N_UNSUPPORTED // Provides alternative implementation for std::fill_n(), if // it is not supported. -template <typename A> -static inline RT_API_ATTRS void fill_n( - A *start, std::size_t count, const A &value) { +template <typename A, typename B> +static inline RT_API_ATTRS std::enable_if_t<std::is_convertible_v<B, A>, void> +fill_n(A *start, std::size_t count, const B &value) { for (std::size_t j{0}; j < count; ++j) { start[j] = value; } @@ -134,5 +144,37 @@ static inline RT_API_ATTRS void *realloc(void *ptr, std::size_t newByteSize) { using std::realloc; #endif // !STD_REALLOC_UNSUPPORTED +#if STD_MEMCHR_UNSUPPORTED +// Provides alternative implementation for std::memchr(), if +// it is not supported. +static inline RT_API_ATTRS const void *memchr( + const void *ptr, int ch, std::size_t count) { + auto buf{reinterpret_cast<const unsigned char *>(ptr)}; + auto c{static_cast<unsigned char>(ch)}; + for (; count--; ++buf) { + if (*buf == c) { + return buf; + } + } + return nullptr; +} +#else // !STD_MEMCMP_UNSUPPORTED +using std::memchr; +#endif // !STD_MEMCMP_UNSUPPORTED + +#if STD_STRCPY_UNSUPPORTED +// Provides alternative implementation for std::strcpy(), if +// it is not supported. +static inline RT_API_ATTRS char *strcpy(char *dest, const char *src) { + char *result{dest}; + do { + *dest++ = *src; + } while (*src++ != '\0'); + return result; +} +#else // !STD_STRCPY_UNSUPPORTED +using std::strcpy; +#endif // !STD_STRCPY_UNSUPPORTED + } // namespace Fortran::runtime #endif // FORTRAN_RUNTIME_FREESTANDING_TOOLS_H_ diff --git a/flang/runtime/internal-unit.cpp b/flang/runtime/internal-unit.cpp index e3fffaa6f378fffc2df658a57e2f2dfeae88e2f9..35766306ccefbe3405e95cf5f97d807b26fdd5bd 100644 --- a/flang/runtime/internal-unit.cpp +++ b/flang/runtime/internal-unit.cpp @@ -7,15 +7,17 @@ //===----------------------------------------------------------------------===// #include "internal-unit.h" +#include "freestanding-tools.h" #include "io-error.h" #include "flang/Runtime/descriptor.h" #include <algorithm> #include <type_traits> namespace Fortran::runtime::io { +RT_OFFLOAD_API_GROUP_BEGIN template <Direction DIR> -InternalDescriptorUnit<DIR>::InternalDescriptorUnit( +RT_API_ATTRS InternalDescriptorUnit<DIR>::InternalDescriptorUnit( Scalar scalar, std::size_t length, int kind) { internalIoCharKind = kind; recordLength = length; @@ -26,7 +28,7 @@ InternalDescriptorUnit<DIR>::InternalDescriptorUnit( } template <Direction DIR> -InternalDescriptorUnit<DIR>::InternalDescriptorUnit( +RT_API_ATTRS InternalDescriptorUnit<DIR>::InternalDescriptorUnit( const Descriptor &that, const Terminator &terminator) { auto thatType{that.type().GetCategoryAndKind()}; RUNTIME_CHECK(terminator, thatType.has_value()); @@ -41,18 +43,8 @@ InternalDescriptorUnit<DIR>::InternalDescriptorUnit( endfileRecordNumber = d.Elements() + 1; } -template <Direction DIR> void InternalDescriptorUnit<DIR>::EndIoStatement() { - if constexpr (DIR == Direction::Output) { - // Clear the remainder of the current record. - auto end{endfileRecordNumber.value_or(0)}; - if (currentRecordNumber < end) { - BlankFillOutputRecord(); - } - } -} - template <Direction DIR> -bool InternalDescriptorUnit<DIR>::Emit( +RT_API_ATTRS bool InternalDescriptorUnit<DIR>::Emit( const char *data, std::size_t bytes, IoErrorHandler &handler) { if constexpr (DIR == Direction::Input) { handler.Crash("InternalDescriptorUnit<Direction::Input>::Emit() called"); @@ -86,7 +78,7 @@ bool InternalDescriptorUnit<DIR>::Emit( } template <Direction DIR> -std::size_t InternalDescriptorUnit<DIR>::GetNextInputBytes( +RT_API_ATTRS std::size_t InternalDescriptorUnit<DIR>::GetNextInputBytes( const char *&p, IoErrorHandler &handler) { if constexpr (DIR == Direction::Output) { handler.Crash("InternalDescriptorUnit<Direction::Output>::" @@ -107,9 +99,14 @@ std::size_t InternalDescriptorUnit<DIR>::GetNextInputBytes( } template <Direction DIR> -bool InternalDescriptorUnit<DIR>::AdvanceRecord(IoErrorHandler &handler) { +RT_API_ATTRS bool InternalDescriptorUnit<DIR>::AdvanceRecord( + IoErrorHandler &handler) { if (currentRecordNumber >= endfileRecordNumber.value_or(0)) { - handler.SignalEnd(); + if constexpr (DIR == Direction::Input) { + handler.SignalEnd(); + } else { + handler.SignalError(IostatInternalWriteOverrun); + } return false; } if constexpr (DIR == Direction::Output) { @@ -121,24 +118,25 @@ bool InternalDescriptorUnit<DIR>::AdvanceRecord(IoErrorHandler &handler) { } template <Direction DIR> -void InternalDescriptorUnit<DIR>::BlankFill(char *at, std::size_t bytes) { +RT_API_ATTRS void InternalDescriptorUnit<DIR>::BlankFill( + char *at, std::size_t bytes) { switch (internalIoCharKind) { case 2: - std::fill_n(reinterpret_cast<char16_t *>(at), bytes / 2, + Fortran::runtime::fill_n(reinterpret_cast<char16_t *>(at), bytes / 2, static_cast<char16_t>(' ')); break; case 4: - std::fill_n(reinterpret_cast<char32_t *>(at), bytes / 4, + Fortran::runtime::fill_n(reinterpret_cast<char32_t *>(at), bytes / 4, static_cast<char32_t>(' ')); break; default: - std::fill_n(at, bytes, ' '); + Fortran::runtime::fill_n(at, bytes, ' '); break; } } template <Direction DIR> -void InternalDescriptorUnit<DIR>::BlankFillOutputRecord() { +RT_API_ATTRS void InternalDescriptorUnit<DIR>::BlankFillOutputRecord() { if constexpr (DIR == Direction::Output) { if (furthestPositionInRecord < recordLength.value_or(furthestPositionInRecord)) { @@ -149,18 +147,21 @@ void InternalDescriptorUnit<DIR>::BlankFillOutputRecord() { } template <Direction DIR> -void InternalDescriptorUnit<DIR>::BackspaceRecord(IoErrorHandler &handler) { +RT_API_ATTRS void InternalDescriptorUnit<DIR>::BackspaceRecord( + IoErrorHandler &handler) { RUNTIME_CHECK(handler, currentRecordNumber > 1); --currentRecordNumber; BeginRecord(); } template <Direction DIR> -std::int64_t InternalDescriptorUnit<DIR>::InquirePos() { +RT_API_ATTRS std::int64_t InternalDescriptorUnit<DIR>::InquirePos() { return (currentRecordNumber - 1) * recordLength.value_or(0) + positionInRecord + 1; } template class InternalDescriptorUnit<Direction::Output>; template class InternalDescriptorUnit<Direction::Input>; + +RT_OFFLOAD_API_GROUP_END } // namespace Fortran::runtime::io diff --git a/flang/runtime/internal-unit.h b/flang/runtime/internal-unit.h index f0c50aac98878f9af3ea7dbbc32b345af9596155..bcd38b62468af2a52168f2a7decb0e4e561f7b36 100644 --- a/flang/runtime/internal-unit.h +++ b/flang/runtime/internal-unit.h @@ -26,27 +26,28 @@ template <Direction DIR> class InternalDescriptorUnit : public ConnectionState { public: using Scalar = std::conditional_t<DIR == Direction::Input, const char *, char *>; - InternalDescriptorUnit(Scalar, std::size_t chars, int kind); - InternalDescriptorUnit(const Descriptor &, const Terminator &); - void EndIoStatement(); + RT_API_ATTRS InternalDescriptorUnit(Scalar, std::size_t chars, int kind); + RT_API_ATTRS InternalDescriptorUnit(const Descriptor &, const Terminator &); - bool Emit(const char *, std::size_t, IoErrorHandler &); - std::size_t GetNextInputBytes(const char *&, IoErrorHandler &); - bool AdvanceRecord(IoErrorHandler &); - void BackspaceRecord(IoErrorHandler &); - std::int64_t InquirePos(); + RT_API_ATTRS bool Emit(const char *, std::size_t, IoErrorHandler &); + RT_API_ATTRS std::size_t GetNextInputBytes(const char *&, IoErrorHandler &); + RT_API_ATTRS bool AdvanceRecord(IoErrorHandler &); + RT_API_ATTRS void BackspaceRecord(IoErrorHandler &); + RT_API_ATTRS std::int64_t InquirePos(); private: - Descriptor &descriptor() { return staticDescriptor_.descriptor(); } - const Descriptor &descriptor() const { + RT_API_ATTRS Descriptor &descriptor() { return staticDescriptor_.descriptor(); } - Scalar CurrentRecord() const { + RT_API_ATTRS const Descriptor &descriptor() const { + return staticDescriptor_.descriptor(); + } + RT_API_ATTRS Scalar CurrentRecord() const { return descriptor().template ZeroBasedIndexedElement<char>( currentRecordNumber - 1); } - void BlankFill(char *, std::size_t); - void BlankFillOutputRecord(); + RT_API_ATTRS void BlankFill(char *, std::size_t); + RT_API_ATTRS void BlankFillOutputRecord(); StaticDescriptor<maxRank, true /*addendum*/> staticDescriptor_; }; diff --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp index 0ac20d3346dd5b3c65cf4e05f2e02526dd448a92..3a86c9fa7375e14380ff4a869dd198c155b5873c 100644 --- a/flang/runtime/io-api.cpp +++ b/flang/runtime/io-api.cpp @@ -18,6 +18,7 @@ #include "terminator.h" #include "tools.h" #include "unit.h" +#include "flang/Common/optional.h" #include "flang/Runtime/descriptor.h" #include "flang/Runtime/memory.h" #include <cstdlib> @@ -98,7 +99,7 @@ Cookie IONAME(BeginInternalArrayFormattedInput)(const Descriptor &descriptor, } template <Direction DIR> -Cookie BeginInternalListIO( +RT_API_ATTRS Cookie BeginInternalListIO( std::conditional_t<DIR == Direction::Input, const char, char> *internal, std::size_t internalLength, void ** /*scratchArea*/, std::size_t /*scratchBytes*/, const char *sourceFile, int sourceLine) { @@ -155,8 +156,8 @@ Cookie IONAME(BeginInternalFormattedInput)(const char *internal, sourceFile, sourceLine); } -static Cookie NoopUnit(const Terminator &terminator, int unitNumber, - enum Iostat iostat = IostatOk) { +static RT_API_ATTRS Cookie NoopUnit(const Terminator &terminator, + int unitNumber, enum Iostat iostat = IostatOk) { Cookie cookie{&New<NoopStatementState>{terminator}( terminator.sourceFileName(), terminator.sourceLine(), unitNumber) .release() @@ -167,9 +168,9 @@ static Cookie NoopUnit(const Terminator &terminator, int unitNumber, return cookie; } -static ExternalFileUnit *GetOrCreateUnit(int unitNumber, Direction direction, - std::optional<bool> isUnformatted, const Terminator &terminator, - Cookie &errorCookie) { +static RT_API_ATTRS ExternalFileUnit *GetOrCreateUnit(int unitNumber, + Direction direction, Fortran::common::optional<bool> isUnformatted, + const Terminator &terminator, Cookie &errorCookie) { if (ExternalFileUnit * unit{ExternalFileUnit::LookUpOrCreateAnonymous( unitNumber, direction, isUnformatted, terminator)}) { @@ -182,7 +183,7 @@ static ExternalFileUnit *GetOrCreateUnit(int unitNumber, Direction direction, } template <Direction DIR, template <Direction> class STATE, typename... A> -Cookie BeginExternalListIO( +RT_API_ATTRS Cookie BeginExternalListIO( int unitNumber, const char *sourceFile, int sourceLine, A &&...xs) { Terminator terminator{sourceFile, sourceLine}; Cookie errorCookie{nullptr}; @@ -226,11 +227,13 @@ Cookie BeginExternalListIO( } } -Cookie IONAME(BeginExternalListOutput)( +RT_EXT_API_GROUP_BEGIN +Cookie IODEF(BeginExternalListOutput)( ExternalUnit unitNumber, const char *sourceFile, int sourceLine) { return BeginExternalListIO<Direction::Output, ExternalListIoStatementState>( unitNumber, sourceFile, sourceLine); } +RT_EXT_API_GROUP_END Cookie IONAME(BeginExternalListInput)( ExternalUnit unitNumber, const char *sourceFile, int sourceLine) { @@ -472,8 +475,8 @@ Cookie IONAME(BeginEndfile)( Terminator terminator{sourceFile, sourceLine}; Cookie errorCookie{nullptr}; if (ExternalFileUnit * - unit{GetOrCreateUnit(unitNumber, Direction::Output, std::nullopt, - terminator, errorCookie)}) { + unit{GetOrCreateUnit(unitNumber, Direction::Output, + Fortran::common::nullopt, terminator, errorCookie)}) { if (ChildIo * child{unit->GetChildIo()}) { return &child->BeginIoStatement<ErroneousIoStatementState>( IostatBadOpOnChildUnit, nullptr /* no unit */, sourceFile, @@ -492,8 +495,8 @@ Cookie IONAME(BeginRewind)( Terminator terminator{sourceFile, sourceLine}; Cookie errorCookie{nullptr}; if (ExternalFileUnit * - unit{GetOrCreateUnit(unitNumber, Direction::Input, std::nullopt, - terminator, errorCookie)}) { + unit{GetOrCreateUnit(unitNumber, Direction::Input, + Fortran::common::nullopt, terminator, errorCookie)}) { if (ChildIo * child{unit->GetChildIo()}) { return &child->BeginIoStatement<ErroneousIoStatementState>( IostatBadOpOnChildUnit, nullptr /* no unit */, sourceFile, @@ -801,7 +804,7 @@ bool IONAME(SetAction)(Cookie cookie, const char *keyword, std::size_t length) { io.GetIoErrorHandler().Crash( "SetAction() called after GetNewUnit() for an OPEN statement"); } - std::optional<Action> action; + Fortran::common::optional<Action> action; static const char *keywords[]{"READ", "WRITE", "READWRITE", nullptr}; switch (IdentifyValue(keyword, length, keywords)) { case 0: @@ -1144,7 +1147,7 @@ bool IONAME(OutputInteger8)(Cookie cookie, std::int8_t n) { if (!cookie->CheckFormattedStmtType<Direction::Output>("OutputInteger8")) { return false; } - StaticDescriptor staticDescriptor; + StaticDescriptor<0> staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( TypeCategory::Integer, 1, reinterpret_cast<void *>(&n), 0); @@ -1155,29 +1158,31 @@ bool IONAME(OutputInteger16)(Cookie cookie, std::int16_t n) { if (!cookie->CheckFormattedStmtType<Direction::Output>("OutputInteger16")) { return false; } - StaticDescriptor staticDescriptor; + StaticDescriptor<0> staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( TypeCategory::Integer, 2, reinterpret_cast<void *>(&n), 0); return descr::DescriptorIO<Direction::Output>(*cookie, descriptor); } -bool IONAME(OutputInteger32)(Cookie cookie, std::int32_t n) { +RT_EXT_API_GROUP_BEGIN +bool IODEF(OutputInteger32)(Cookie cookie, std::int32_t n) { if (!cookie->CheckFormattedStmtType<Direction::Output>("OutputInteger32")) { return false; } - StaticDescriptor staticDescriptor; + StaticDescriptor<0> staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( TypeCategory::Integer, 4, reinterpret_cast<void *>(&n), 0); return descr::DescriptorIO<Direction::Output>(*cookie, descriptor); } +RT_EXT_API_GROUP_END bool IONAME(OutputInteger64)(Cookie cookie, std::int64_t n) { if (!cookie->CheckFormattedStmtType<Direction::Output>("OutputInteger64")) { return false; } - StaticDescriptor staticDescriptor; + StaticDescriptor<0> staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( TypeCategory::Integer, 8, reinterpret_cast<void *>(&n), 0); @@ -1189,7 +1194,7 @@ bool IONAME(OutputInteger128)(Cookie cookie, common::int128_t n) { if (!cookie->CheckFormattedStmtType<Direction::Output>("OutputInteger128")) { return false; } - StaticDescriptor staticDescriptor; + StaticDescriptor<0> staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( TypeCategory::Integer, 16, reinterpret_cast<void *>(&n), 0); @@ -1201,7 +1206,7 @@ bool IONAME(InputInteger)(Cookie cookie, std::int64_t &n, int kind) { if (!cookie->CheckFormattedStmtType<Direction::Input>("InputInteger")) { return false; } - StaticDescriptor staticDescriptor; + StaticDescriptor<0> staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( TypeCategory::Integer, kind, reinterpret_cast<void *>(&n), 0); @@ -1212,7 +1217,7 @@ bool IONAME(OutputReal32)(Cookie cookie, float x) { if (!cookie->CheckFormattedStmtType<Direction::Output>("OutputReal32")) { return false; } - StaticDescriptor staticDescriptor; + StaticDescriptor<0> staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish(TypeCategory::Real, 4, reinterpret_cast<void *>(&x), 0); return descr::DescriptorIO<Direction::Output>(*cookie, descriptor); @@ -1222,7 +1227,7 @@ bool IONAME(OutputReal64)(Cookie cookie, double x) { if (!cookie->CheckFormattedStmtType<Direction::Output>("OutputReal64")) { return false; } - StaticDescriptor staticDescriptor; + StaticDescriptor<0> staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish(TypeCategory::Real, 8, reinterpret_cast<void *>(&x), 0); return descr::DescriptorIO<Direction::Output>(*cookie, descriptor); @@ -1232,7 +1237,7 @@ bool IONAME(InputReal32)(Cookie cookie, float &x) { if (!cookie->CheckFormattedStmtType<Direction::Input>("InputReal32")) { return false; } - StaticDescriptor staticDescriptor; + StaticDescriptor<0> staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish(TypeCategory::Real, 4, reinterpret_cast<void *>(&x), 0); return descr::DescriptorIO<Direction::Input>(*cookie, descriptor); @@ -1242,7 +1247,7 @@ bool IONAME(InputReal64)(Cookie cookie, double &x) { if (!cookie->CheckFormattedStmtType<Direction::Input>("InputReal64")) { return false; } - StaticDescriptor staticDescriptor; + StaticDescriptor<0> staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish(TypeCategory::Real, 8, reinterpret_cast<void *>(&x), 0); return descr::DescriptorIO<Direction::Input>(*cookie, descriptor); @@ -1253,7 +1258,7 @@ bool IONAME(OutputComplex32)(Cookie cookie, float r, float i) { return false; } float z[2]{r, i}; - StaticDescriptor staticDescriptor; + StaticDescriptor<0> staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( TypeCategory::Complex, 4, reinterpret_cast<void *>(&z), 0); @@ -1265,7 +1270,7 @@ bool IONAME(OutputComplex64)(Cookie cookie, double r, double i) { return false; } double z[2]{r, i}; - StaticDescriptor staticDescriptor; + StaticDescriptor<0> staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( TypeCategory::Complex, 8, reinterpret_cast<void *>(&z), 0); @@ -1276,7 +1281,7 @@ bool IONAME(InputComplex32)(Cookie cookie, float z[2]) { if (!cookie->CheckFormattedStmtType<Direction::Input>("InputComplex32")) { return false; } - StaticDescriptor staticDescriptor; + StaticDescriptor<0> staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( TypeCategory::Complex, 4, reinterpret_cast<void *>(z), 0); @@ -1287,7 +1292,7 @@ bool IONAME(InputComplex64)(Cookie cookie, double z[2]) { if (!cookie->CheckFormattedStmtType<Direction::Input>("InputComplex64")) { return false; } - StaticDescriptor staticDescriptor; + StaticDescriptor<0> staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( TypeCategory::Complex, 8, reinterpret_cast<void *>(z), 0); @@ -1299,7 +1304,7 @@ bool IONAME(OutputCharacter)( if (!cookie->CheckFormattedStmtType<Direction::Output>("OutputCharacter")) { return false; } - StaticDescriptor staticDescriptor; + StaticDescriptor<0> staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( kind, length, reinterpret_cast<void *>(const_cast<char *>(x)), 0); @@ -1315,7 +1320,7 @@ bool IONAME(InputCharacter)( if (!cookie->CheckFormattedStmtType<Direction::Input>("InputCharacter")) { return false; } - StaticDescriptor staticDescriptor; + StaticDescriptor<0> staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish(kind, length, reinterpret_cast<void *>(x), 0); return descr::DescriptorIO<Direction::Input>(*cookie, descriptor); @@ -1329,7 +1334,7 @@ bool IONAME(OutputLogical)(Cookie cookie, bool truth) { if (!cookie->CheckFormattedStmtType<Direction::Output>("OutputLogical")) { return false; } - StaticDescriptor staticDescriptor; + StaticDescriptor<0> staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( TypeCategory::Logical, sizeof truth, reinterpret_cast<void *>(&truth), 0); @@ -1340,7 +1345,7 @@ bool IONAME(InputLogical)(Cookie cookie, bool &truth) { if (!cookie->CheckFormattedStmtType<Direction::Input>("InputLogical")) { return false; } - StaticDescriptor staticDescriptor; + StaticDescriptor<0> staticDescriptor; Descriptor &descriptor{staticDescriptor.descriptor()}; descriptor.Establish( TypeCategory::Logical, sizeof truth, reinterpret_cast<void *>(&truth), 0); @@ -1447,10 +1452,12 @@ bool IONAME(InquireInteger64)( return false; } -enum Iostat IONAME(EndIoStatement)(Cookie cookie) { +RT_EXT_API_GROUP_BEGIN +enum Iostat IODEF(EndIoStatement)(Cookie cookie) { IoStatementState &io{*cookie}; return static_cast<enum Iostat>(io.EndIoStatement()); } +RT_EXT_API_GROUP_END template <typename INT> static enum Iostat CheckUnitNumberInRangeImpl(INT unit, bool handleError, diff --git a/flang/runtime/io-error.cpp b/flang/runtime/io-error.cpp index c8f6675c60a6c8dc1c820c48db8c3c6eb9ede06f..b006b82f6224919c50c09aa0382ab1ba9ac8c014 100644 --- a/flang/runtime/io-error.cpp +++ b/flang/runtime/io-error.cpp @@ -16,6 +16,7 @@ #include <cstring> namespace Fortran::runtime::io { +RT_OFFLOAD_API_GROUP_BEGIN void IoErrorHandler::SignalError(int iostatOrErrno, const char *msg, ...) { // Note that IOMSG= alone without IOSTAT=/END=/EOR=/ERR= does not suffice @@ -44,12 +45,17 @@ void IoErrorHandler::SignalError(int iostatOrErrno, const char *msg, ...) { if (ioStat_ <= 0) { ioStat_ = iostatOrErrno; // priority over END=/EOR= if (msg && (flags_ & hasIoMsg)) { +#if !defined(RT_DEVICE_COMPILATION) char buffer[256]; va_list ap; va_start(ap, msg); std::vsnprintf(buffer, sizeof buffer, msg, ap); - ioMsg_ = SaveDefaultCharacter(buffer, std::strlen(buffer) + 1, *this); va_end(ap); +#else + const char *buffer = "not implemented yet: IOSTAT with varargs"; +#endif + ioMsg_ = SaveDefaultCharacter( + buffer, Fortran::runtime::strlen(buffer) + 1, *this); } } return; @@ -58,15 +64,23 @@ void IoErrorHandler::SignalError(int iostatOrErrno, const char *msg, ...) { } // I/O error not caught! if (msg) { +#if !defined(RT_DEVICE_COMPILATION) va_list ap; va_start(ap, msg); CrashArgs(msg, ap); va_end(ap); +#else + Crash("not implemented yet: IOSTAT with varargs"); +#endif } else if (const char *errstr{IostatErrorString(iostatOrErrno)}) { Crash(errstr); } else { +#if !defined(RT_DEVICE_COMPILATION) Crash("I/O error (errno=%d): %s", iostatOrErrno, std::strerror(iostatOrErrno)); +#else + Crash("I/O error (errno=%d)", iostatOrErrno); +#endif } } @@ -85,8 +99,6 @@ void IoErrorHandler::Forward( } } -void IoErrorHandler::SignalErrno() { SignalError(errno); } - void IoErrorHandler::SignalEnd() { SignalError(IostatEnd); } void IoErrorHandler::SignalEor() { SignalError(IostatEor); } @@ -97,6 +109,10 @@ void IoErrorHandler::SignalPendingError() { SignalError(error); } +RT_OFFLOAD_API_GROUP_END + +void IoErrorHandler::SignalErrno() { SignalError(errno); } + bool IoErrorHandler::GetIoMsg(char *buffer, std::size_t bufferLength) { const char *msg{ioMsg_.get()}; if (!msg) { @@ -132,7 +148,7 @@ bool IoErrorHandler::GetIoMsg(char *buffer, std::size_t bufferLength) { ToFortranDefaultCharacter(buffer, bufferLength, msg); return true; } else if (ok) { - std::size_t copied{std::strlen(buffer)}; + std::size_t copied{Fortran::runtime::strlen(buffer)}; if (copied < bufferLength) { std::memset(buffer + copied, ' ', bufferLength - copied); } diff --git a/flang/runtime/io-error.h b/flang/runtime/io-error.h index 565e7153351e7e32736069c164ed7f3b5d23829c..0fe11c9185c0a9e60aa6902bc67a0e7a767636b9 100644 --- a/flang/runtime/io-error.h +++ b/flang/runtime/io-error.h @@ -26,14 +26,15 @@ namespace Fortran::runtime::io { class IoErrorHandler : public Terminator { public: using Terminator::Terminator; - explicit IoErrorHandler(const Terminator &that) : Terminator{that} {} - void HasIoStat() { flags_ |= hasIoStat; } - void HasErrLabel() { flags_ |= hasErr; } - void HasEndLabel() { flags_ |= hasEnd; } - void HasEorLabel() { flags_ |= hasEor; } - void HasIoMsg() { flags_ |= hasIoMsg; } + explicit RT_API_ATTRS IoErrorHandler(const Terminator &that) + : Terminator{that} {} + RT_API_ATTRS void HasIoStat() { flags_ |= hasIoStat; } + RT_API_ATTRS void HasErrLabel() { flags_ |= hasErr; } + RT_API_ATTRS void HasEndLabel() { flags_ |= hasEnd; } + RT_API_ATTRS void HasEorLabel() { flags_ |= hasEor; } + RT_API_ATTRS void HasIoMsg() { flags_ |= hasIoMsg; } - bool InError() const { + RT_API_ATTRS bool InError() const { return ioStat_ != IostatOk || pendingError_ != IostatOk; } @@ -41,22 +42,25 @@ public: // Begin...() API routines before it is known whether they // have error handling control list items. Such statements // have an ErroneousIoStatementState with a pending error. - void SetPendingError(int iostat) { pendingError_ = iostat; } + RT_API_ATTRS void SetPendingError(int iostat) { pendingError_ = iostat; } - void SignalError(int iostatOrErrno, const char *msg, ...); - void SignalError(int iostatOrErrno); - template <typename... X> void SignalError(const char *msg, X &&...xs) { + RT_API_ATTRS void SignalError(int iostatOrErrno, const char *msg, ...); + RT_API_ATTRS void SignalError(int iostatOrErrno); + template <typename... X> + RT_API_ATTRS void SignalError(const char *msg, X &&...xs) { SignalError(IostatGenericError, msg, std::forward<X>(xs)...); } - void Forward(int iostatOrErrno, const char *, std::size_t); + RT_API_ATTRS void Forward(int iostatOrErrno, const char *, std::size_t); void SignalErrno(); // SignalError(errno) - void SignalEnd(); // input only; EOF on internal write is an error - void SignalEor(); // non-advancing input only; EOR on write is an error - void SignalPendingError(); + RT_API_ATTRS void + SignalEnd(); // input only; EOF on internal write is an error + RT_API_ATTRS void + SignalEor(); // non-advancing input only; EOR on write is an error + RT_API_ATTRS void SignalPendingError(); - int GetIoStat() const { return ioStat_; } + RT_API_ATTRS int GetIoStat() const { return ioStat_; } bool GetIoMsg(char *, std::size_t); private: diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp index 3ec01ffba9bf0658fafb29d213289dc9a1637052..022e4c806bf63bc28f7c1b272a2861b85d3f9c69 100644 --- a/flang/runtime/io-stmt.cpp +++ b/flang/runtime/io-stmt.cpp @@ -21,6 +21,7 @@ #include <type_traits> namespace Fortran::runtime::io { +RT_OFFLOAD_API_GROUP_BEGIN bool IoStatementBase::Emit(const char *, std::size_t, std::size_t) { return false; @@ -39,13 +40,9 @@ bool IoStatementBase::Receive(char *, std::size_t, std::size_t) { return false; } -std::optional<DataEdit> IoStatementBase::GetNextDataEdit( +Fortran::common::optional<DataEdit> IoStatementBase::GetNextDataEdit( IoStatementState &, int) { - return std::nullopt; -} - -ExternalFileUnit *IoStatementBase::GetExternalFileUnit() const { - return nullptr; + return Fortran::common::nullopt; } bool IoStatementBase::BeginReadingRecord() { return true; } @@ -56,6 +53,12 @@ void IoStatementBase::HandleAbsolutePosition(std::int64_t) {} void IoStatementBase::HandleRelativePosition(std::int64_t) {} +std::int64_t IoStatementBase::InquirePos() { return 0; } + +ExternalFileUnit *IoStatementBase::GetExternalFileUnit() const { + return nullptr; +} + bool IoStatementBase::Inquire(InquiryKeywordHash, char *, std::size_t) { return false; } @@ -70,8 +73,6 @@ bool IoStatementBase::Inquire(InquiryKeywordHash, std::int64_t &) { return false; } -std::int64_t IoStatementBase::InquirePos() { return 0; } - void IoStatementBase::BadInquiryKeywordHashCrash(InquiryKeywordHash inquiry) { char buffer[16]; const char *decode{InquiryKeywordHashDecode(buffer, sizeof buffer, inquiry)}; @@ -119,9 +120,6 @@ template <Direction DIR> void InternalIoStatementState<DIR>::BackspaceRecord() { } template <Direction DIR> int InternalIoStatementState<DIR>::EndIoStatement() { - if constexpr (DIR == Direction::Output) { - unit_.EndIoStatement(); // fill - } auto result{IoStatementBase::EndIoStatement()}; if (free_) { FreeMemory(this); @@ -145,27 +143,30 @@ std::int64_t InternalIoStatementState<DIR>::InquirePos() { } template <Direction DIR, typename CHAR> +RT_API_ATTRS InternalFormattedIoStatementState<DIR, CHAR>::InternalFormattedIoStatementState( Buffer buffer, std::size_t length, const CharType *format, std::size_t formatLength, const Descriptor *formatDescriptor, const char *sourceFile, int sourceLine) : InternalIoStatementState<DIR>{buffer, length, sourceFile, sourceLine}, - ioStatementState_{*this}, format_{*this, format, formatLength, - formatDescriptor} {} + ioStatementState_{*this}, + format_{*this, format, formatLength, formatDescriptor} {} template <Direction DIR, typename CHAR> +RT_API_ATTRS InternalFormattedIoStatementState<DIR, CHAR>::InternalFormattedIoStatementState( const Descriptor &d, const CharType *format, std::size_t formatLength, const Descriptor *formatDescriptor, const char *sourceFile, int sourceLine) : InternalIoStatementState<DIR>{d, sourceFile, sourceLine}, - ioStatementState_{*this}, format_{*this, format, formatLength, - formatDescriptor} {} + ioStatementState_{*this}, + format_{*this, format, formatLength, formatDescriptor} {} template <Direction DIR, typename CHAR> void InternalFormattedIoStatementState<DIR, CHAR>::CompleteOperation() { if (!this->completedOperation()) { if constexpr (DIR == Direction::Output) { - format_.Finish(*this); // ignore any remaining input positioning actions + format_.Finish(*this); + unit_.AdvanceRecord(*this); } IoStatementBase::CompleteOperation(); } @@ -189,8 +190,21 @@ InternalListIoStatementState<DIR>::InternalListIoStatementState( : InternalIoStatementState<DIR>{d, sourceFile, sourceLine}, ioStatementState_{*this} {} +template <Direction DIR> +void InternalListIoStatementState<DIR>::CompleteOperation() { + if (!this->completedOperation()) { + if constexpr (DIR == Direction::Output) { + if (unit_.furthestPositionInRecord > 0) { + unit_.AdvanceRecord(*this); + } + } + IoStatementBase::CompleteOperation(); + } +} + template <Direction DIR> int InternalListIoStatementState<DIR>::EndIoStatement() { + CompleteOperation(); if constexpr (DIR == Direction::Input) { if (int status{ListDirectedStatementState<DIR>::EndIoStatement()}; status != IostatOk) { @@ -216,7 +230,17 @@ ConnectionState &ExternalIoStatementBase::GetConnectionState() { return unit_; } int ExternalIoStatementBase::EndIoStatement() { CompleteOperation(); auto result{IoStatementBase::EndIoStatement()}; +#if !defined(RT_USE_PSEUDO_FILE_UNIT) unit_.EndIoStatement(); // annihilates *this in unit_.u_ +#else + // Fetch the unit pointer before *this disappears. + ExternalFileUnit *unitPtr{&unit_}; + // The pseudo file units are dynamically allocated + // and are not tracked in the unit map. + // They have to be destructed and deallocated here. + unitPtr->~ExternalFileUnit(); + FreeMemory(unitPtr); +#endif return result; } @@ -455,7 +479,7 @@ int ExternalFormattedIoStatementState<DIR, CHAR>::EndIoStatement() { return ExternalIoStatementState<DIR>::EndIoStatement(); } -std::optional<DataEdit> IoStatementState::GetNextDataEdit(int n) { +Fortran::common::optional<DataEdit> IoStatementState::GetNextDataEdit(int n) { return common::visit( [&](auto &x) { return x.get().GetNextDataEdit(*this, n); }, u_); } @@ -530,13 +554,13 @@ ExternalFileUnit *IoStatementState::GetExternalFileUnit() const { [](auto &x) { return x.get().GetExternalFileUnit(); }, u_); } -std::optional<char32_t> IoStatementState::GetCurrentChar( +Fortran::common::optional<char32_t> IoStatementState::GetCurrentChar( std::size_t &byteCount) { const char *p{nullptr}; std::size_t bytes{GetNextInputBytes(p)}; if (bytes == 0) { byteCount = 0; - return std::nullopt; + return Fortran::common::nullopt; } else { const ConnectionState &connection{GetConnectionState()}; if (connection.isUTF8) { @@ -562,8 +586,8 @@ std::optional<char32_t> IoStatementState::GetCurrentChar( } } -std::optional<char32_t> IoStatementState::NextInField( - std::optional<int> &remaining, const DataEdit &edit) { +Fortran::common::optional<char32_t> IoStatementState::NextInField( + Fortran::common::optional<int> &remaining, const DataEdit &edit) { std::size_t byteCount{0}; if (!remaining) { // Stream, list-directed, or NAMELIST if (auto next{GetCurrentChar(byteCount)}) { @@ -579,21 +603,21 @@ std::optional<char32_t> IoStatementState::NextInField( case '"': case '*': case '\n': // for stream access - return std::nullopt; + return Fortran::common::nullopt; case '&': case '$': if (edit.IsNamelist()) { - return std::nullopt; + return Fortran::common::nullopt; } break; case ',': if (!(edit.modes.editingFlags & decimalComma)) { - return std::nullopt; + return Fortran::common::nullopt; } break; case ';': if (edit.modes.editingFlags & decimalComma) { - return std::nullopt; + return Fortran::common::nullopt; } break; default: @@ -607,7 +631,7 @@ std::optional<char32_t> IoStatementState::NextInField( } else if (*remaining > 0) { if (auto next{GetCurrentChar(byteCount)}) { if (byteCount > static_cast<std::size_t>(*remaining)) { - return std::nullopt; + return Fortran::common::nullopt; } *remaining -= byteCount; HandleRelativePosition(byteCount); @@ -616,10 +640,10 @@ std::optional<char32_t> IoStatementState::NextInField( } if (CheckForEndOfRecord(0)) { // do padding --*remaining; - return std::optional<char32_t>{' '}; + return Fortran::common::optional<char32_t>{' '}; } } - return std::nullopt; + return Fortran::common::nullopt; } bool IoStatementState::CheckForEndOfRecord(std::size_t afterReading) { @@ -711,7 +735,7 @@ bool ListDirectedStatementState<Direction::Output>::EmitLeadingSpaceOrAdvance( return true; } -std::optional<DataEdit> +Fortran::common::optional<DataEdit> ListDirectedStatementState<Direction::Output>::GetNextDataEdit( IoStatementState &io, int maxRepeat) { DataEdit edit; @@ -728,7 +752,7 @@ int ListDirectedStatementState<Direction::Input>::EndIoStatement() { return IostatOk; } -std::optional<DataEdit> +Fortran::common::optional<DataEdit> ListDirectedStatementState<Direction::Input>::GetNextDataEdit( IoStatementState &io, int maxRepeat) { // N.B. list-directed transfers cannot be nonadvancing (C1221) @@ -784,7 +808,7 @@ ListDirectedStatementState<Direction::Input>::GetNextDataEdit( } eatComma_ = true; if (!ch) { - return std::nullopt; + return Fortran::common::nullopt; } if (*ch == '/') { hitSlash_ = true; @@ -983,7 +1007,9 @@ void ExternalMiscIoStatementState::CompleteOperation() { switch (which_) { case Flush: ext.FlushOutput(*this); +#if !defined(RT_DEVICE_COMPILATION) std::fflush(nullptr); // flushes C stdio output streams (12.9(2)) +#endif break; case Backspace: ext.BackspaceRecord(*this); @@ -1487,4 +1513,5 @@ int ErroneousIoStatementState::EndIoStatement() { return IoStatementBase::EndIoStatement(); } +RT_OFFLOAD_API_GROUP_END } // namespace Fortran::runtime::io diff --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h index 0b6bcbd9af025ae6af2768a128d31a8770de6837..8b5752311de5c316ef8411aeea797c180922ab79 100644 --- a/flang/runtime/io-stmt.h +++ b/flang/runtime/io-stmt.h @@ -16,12 +16,14 @@ #include "format.h" #include "internal-unit.h" #include "io-error.h" +#include "flang/Common/optional.h" +#include "flang/Common/reference-wrapper.h" #include "flang/Common/visit.h" #include "flang/Runtime/descriptor.h" #include "flang/Runtime/io-api.h" +#include <flang/Common/variant.h> #include <functional> #include <type_traits> -#include <variant> namespace Fortran::runtime::io { @@ -59,8 +61,8 @@ using IoDirectionState = std::conditional_t<D == Direction::Input, template <Direction D> class FormattedIoStatementState {}; template <> class FormattedIoStatementState<Direction::Input> { public: - std::size_t GetEditDescriptorChars() const; - void GotChar(int); + RT_API_ATTRS std::size_t GetEditDescriptorChars() const; + RT_API_ATTRS void GotChar(int); private: // Account of characters read for edit descriptors (i.e., formatted I/O @@ -71,7 +73,7 @@ private: // The Cookie type in the I/O API is a pointer (for C) to this class. class IoStatementState { public: - template <typename A> explicit IoStatementState(A &x) : u_{x} {} + template <typename A> explicit RT_API_ATTRS IoStatementState(A &x) : u_{x} {} // These member functions each project themselves into the active alternative. // They're used by per-data-item routines in the I/O API (e.g., OutputReal64) @@ -83,34 +85,39 @@ public: // It is called by EndIoStatement(), but it can be invoked earlier to // catch errors for (e.g.) GetIoMsg() and GetNewUnit(). If called // more than once, it is a no-op. - void CompleteOperation(); + RT_API_ATTRS void CompleteOperation(); // Completes an I/O statement and reclaims storage. - int EndIoStatement(); - - bool Emit(const char *, std::size_t bytes, std::size_t elementBytes = 0); - bool Receive(char *, std::size_t, std::size_t elementBytes = 0); - std::size_t GetNextInputBytes(const char *&); - bool AdvanceRecord(int = 1); - void BackspaceRecord(); - void HandleRelativePosition(std::int64_t byteOffset); - void HandleAbsolutePosition(std::int64_t byteOffset); // for r* in list I/O - std::optional<DataEdit> GetNextDataEdit(int maxRepeat = 1); - ExternalFileUnit *GetExternalFileUnit() const; // null if internal unit - bool BeginReadingRecord(); - void FinishReadingRecord(); - bool Inquire(InquiryKeywordHash, char *, std::size_t); - bool Inquire(InquiryKeywordHash, bool &); - bool Inquire(InquiryKeywordHash, std::int64_t, bool &); // PENDING= - bool Inquire(InquiryKeywordHash, std::int64_t &); - std::int64_t InquirePos(); - void GotChar(signed int = 1); // for READ(SIZE=); can be <0 - - MutableModes &mutableModes(); - ConnectionState &GetConnectionState(); - IoErrorHandler &GetIoErrorHandler() const; + RT_API_ATTRS int EndIoStatement(); + + RT_API_ATTRS bool Emit( + const char *, std::size_t bytes, std::size_t elementBytes = 0); + RT_API_ATTRS bool Receive(char *, std::size_t, std::size_t elementBytes = 0); + RT_API_ATTRS std::size_t GetNextInputBytes(const char *&); + RT_API_ATTRS bool AdvanceRecord(int = 1); + RT_API_ATTRS void BackspaceRecord(); + RT_API_ATTRS void HandleRelativePosition(std::int64_t byteOffset); + RT_API_ATTRS void HandleAbsolutePosition( + std::int64_t byteOffset); // for r* in list I/O + RT_API_ATTRS Fortran::common::optional<DataEdit> GetNextDataEdit( + int maxRepeat = 1); + RT_API_ATTRS ExternalFileUnit * + GetExternalFileUnit() const; // null if internal unit + RT_API_ATTRS bool BeginReadingRecord(); + RT_API_ATTRS void FinishReadingRecord(); + RT_API_ATTRS bool Inquire(InquiryKeywordHash, char *, std::size_t); + RT_API_ATTRS bool Inquire(InquiryKeywordHash, bool &); + RT_API_ATTRS bool Inquire( + InquiryKeywordHash, std::int64_t, bool &); // PENDING= + RT_API_ATTRS bool Inquire(InquiryKeywordHash, std::int64_t &); + RT_API_ATTRS std::int64_t InquirePos(); + RT_API_ATTRS void GotChar(signed int = 1); // for READ(SIZE=); can be <0 + + RT_API_ATTRS MutableModes &mutableModes(); + RT_API_ATTRS ConnectionState &GetConnectionState(); + RT_API_ATTRS IoErrorHandler &GetIoErrorHandler() const; // N.B.: this also works with base classes - template <typename A> A *get_if() const { + template <typename A> RT_API_ATTRS A *get_if() const { return common::visit( [](auto &x) -> A * { if constexpr (std::is_convertible_v<decltype(x.get()), A &>) { @@ -122,7 +129,8 @@ public: } // Vacant after the end of the current record - std::optional<char32_t> GetCurrentChar(std::size_t &byteCount); + RT_API_ATTRS Fortran::common::optional<char32_t> GetCurrentChar( + std::size_t &byteCount); // The "remaining" arguments to CueUpInput(), SkipSpaces(), & NextInField() // are always in units of bytes, not characters; the distinction matters @@ -130,8 +138,8 @@ public: // For fixed-width fields, return the number of remaining bytes. // Skip over leading blanks. - std::optional<int> CueUpInput(const DataEdit &edit) { - std::optional<int> remaining; + RT_API_ATTRS Fortran::common::optional<int> CueUpInput(const DataEdit &edit) { + Fortran::common::optional<int> remaining; if (edit.IsListDirected()) { std::size_t byteCount{0}; GetNextNonBlank(byteCount); @@ -148,7 +156,8 @@ public: return remaining; } - std::optional<char32_t> SkipSpaces(std::optional<int> &remaining) { + RT_API_ATTRS Fortran::common::optional<char32_t> SkipSpaces( + Fortran::common::optional<int> &remaining) { while (!remaining || *remaining > 0) { std::size_t byteCount{0}; if (auto ch{GetCurrentChar(byteCount)}) { @@ -167,34 +176,36 @@ public: break; } } - return std::nullopt; + return Fortran::common::nullopt; } // Acquires the next input character, respecting any applicable field width // or separator character. - std::optional<char32_t> NextInField( - std::optional<int> &remaining, const DataEdit &); + RT_API_ATTRS Fortran::common::optional<char32_t> NextInField( + Fortran::common::optional<int> &remaining, const DataEdit &); // Detect and signal any end-of-record condition after input. // Returns true if at EOR and remaining input should be padded with blanks. - bool CheckForEndOfRecord(std::size_t afterReading); + RT_API_ATTRS bool CheckForEndOfRecord(std::size_t afterReading); // Skips spaces, advances records, and ignores NAMELIST comments - std::optional<char32_t> GetNextNonBlank(std::size_t &byteCount) { + RT_API_ATTRS Fortran::common::optional<char32_t> GetNextNonBlank( + std::size_t &byteCount) { auto ch{GetCurrentChar(byteCount)}; bool inNamelist{mutableModes().inNamelist}; while (!ch || *ch == ' ' || *ch == '\t' || (inNamelist && *ch == '!')) { if (ch && (*ch == ' ' || *ch == '\t')) { HandleRelativePosition(byteCount); } else if (!AdvanceRecord()) { - return std::nullopt; + return Fortran::common::nullopt; } ch = GetCurrentChar(byteCount); } return ch; } - template <Direction D> bool CheckFormattedStmtType(const char *name) { + template <Direction D> + RT_API_ATTRS bool CheckFormattedStmtType(const char *name) { if (get_if<FormattedIoStatementState<D>>()) { return true; } else { @@ -208,39 +219,47 @@ public: } private: - std::variant<std::reference_wrapper<OpenStatementState>, - std::reference_wrapper<CloseStatementState>, - std::reference_wrapper<NoopStatementState>, - std::reference_wrapper< + std::variant<Fortran::common::reference_wrapper<OpenStatementState>, + Fortran::common::reference_wrapper<CloseStatementState>, + Fortran::common::reference_wrapper<NoopStatementState>, + Fortran::common::reference_wrapper< InternalFormattedIoStatementState<Direction::Output>>, - std::reference_wrapper< + Fortran::common::reference_wrapper< InternalFormattedIoStatementState<Direction::Input>>, - std::reference_wrapper<InternalListIoStatementState<Direction::Output>>, - std::reference_wrapper<InternalListIoStatementState<Direction::Input>>, - std::reference_wrapper< + Fortran::common::reference_wrapper< + InternalListIoStatementState<Direction::Output>>, + Fortran::common::reference_wrapper< + InternalListIoStatementState<Direction::Input>>, + Fortran::common::reference_wrapper< ExternalFormattedIoStatementState<Direction::Output>>, - std::reference_wrapper< + Fortran::common::reference_wrapper< ExternalFormattedIoStatementState<Direction::Input>>, - std::reference_wrapper<ExternalListIoStatementState<Direction::Output>>, - std::reference_wrapper<ExternalListIoStatementState<Direction::Input>>, - std::reference_wrapper< + Fortran::common::reference_wrapper< + ExternalListIoStatementState<Direction::Output>>, + Fortran::common::reference_wrapper< + ExternalListIoStatementState<Direction::Input>>, + Fortran::common::reference_wrapper< ExternalUnformattedIoStatementState<Direction::Output>>, - std::reference_wrapper< + Fortran::common::reference_wrapper< ExternalUnformattedIoStatementState<Direction::Input>>, - std::reference_wrapper<ChildFormattedIoStatementState<Direction::Output>>, - std::reference_wrapper<ChildFormattedIoStatementState<Direction::Input>>, - std::reference_wrapper<ChildListIoStatementState<Direction::Output>>, - std::reference_wrapper<ChildListIoStatementState<Direction::Input>>, - std::reference_wrapper< + Fortran::common::reference_wrapper< + ChildFormattedIoStatementState<Direction::Output>>, + Fortran::common::reference_wrapper< + ChildFormattedIoStatementState<Direction::Input>>, + Fortran::common::reference_wrapper< + ChildListIoStatementState<Direction::Output>>, + Fortran::common::reference_wrapper< + ChildListIoStatementState<Direction::Input>>, + Fortran::common::reference_wrapper< ChildUnformattedIoStatementState<Direction::Output>>, - std::reference_wrapper< + Fortran::common::reference_wrapper< ChildUnformattedIoStatementState<Direction::Input>>, - std::reference_wrapper<InquireUnitState>, - std::reference_wrapper<InquireNoUnitState>, - std::reference_wrapper<InquireUnconnectedFileState>, - std::reference_wrapper<InquireIOLengthState>, - std::reference_wrapper<ExternalMiscIoStatementState>, - std::reference_wrapper<ErroneousIoStatementState>> + Fortran::common::reference_wrapper<InquireUnitState>, + Fortran::common::reference_wrapper<InquireNoUnitState>, + Fortran::common::reference_wrapper<InquireUnconnectedFileState>, + Fortran::common::reference_wrapper<InquireIOLengthState>, + Fortran::common::reference_wrapper<ExternalMiscIoStatementState>, + Fortran::common::reference_wrapper<ErroneousIoStatementState>> u_; }; @@ -249,31 +268,33 @@ class IoStatementBase : public IoErrorHandler { public: using IoErrorHandler::IoErrorHandler; - bool completedOperation() const { return completedOperation_; } + RT_API_ATTRS bool completedOperation() const { return completedOperation_; } - void CompleteOperation() { completedOperation_ = true; } - int EndIoStatement() { return GetIoStat(); } + RT_API_ATTRS void CompleteOperation() { completedOperation_ = true; } + RT_API_ATTRS int EndIoStatement() { return GetIoStat(); } // These are default no-op backstops that can be overridden by descendants. - bool Emit(const char *, std::size_t bytes, std::size_t elementBytes = 0); - bool Receive(char *, std::size_t bytes, std::size_t elementBytes = 0); - std::size_t GetNextInputBytes(const char *&); - bool AdvanceRecord(int); - void BackspaceRecord(); - void HandleRelativePosition(std::int64_t); - void HandleAbsolutePosition(std::int64_t); - std::optional<DataEdit> GetNextDataEdit( + RT_API_ATTRS bool Emit( + const char *, std::size_t bytes, std::size_t elementBytes = 0); + RT_API_ATTRS bool Receive( + char *, std::size_t bytes, std::size_t elementBytes = 0); + RT_API_ATTRS std::size_t GetNextInputBytes(const char *&); + RT_API_ATTRS bool AdvanceRecord(int); + RT_API_ATTRS void BackspaceRecord(); + RT_API_ATTRS void HandleRelativePosition(std::int64_t); + RT_API_ATTRS void HandleAbsolutePosition(std::int64_t); + RT_API_ATTRS Fortran::common::optional<DataEdit> GetNextDataEdit( IoStatementState &, int maxRepeat = 1); - ExternalFileUnit *GetExternalFileUnit() const; - bool BeginReadingRecord(); - void FinishReadingRecord(); - bool Inquire(InquiryKeywordHash, char *, std::size_t); - bool Inquire(InquiryKeywordHash, bool &); - bool Inquire(InquiryKeywordHash, std::int64_t, bool &); - bool Inquire(InquiryKeywordHash, std::int64_t &); - std::int64_t InquirePos(); + RT_API_ATTRS ExternalFileUnit *GetExternalFileUnit() const; + RT_API_ATTRS bool BeginReadingRecord(); + RT_API_ATTRS void FinishReadingRecord(); + RT_API_ATTRS bool Inquire(InquiryKeywordHash, char *, std::size_t); + RT_API_ATTRS bool Inquire(InquiryKeywordHash, bool &); + RT_API_ATTRS bool Inquire(InquiryKeywordHash, std::int64_t, bool &); + RT_API_ATTRS bool Inquire(InquiryKeywordHash, std::int64_t &); + RT_API_ATTRS std::int64_t InquirePos(); - void BadInquiryKeywordHashCrash(InquiryKeywordHash); + RT_API_ATTRS void BadInquiryKeywordHashCrash(InquiryKeywordHash); protected: bool completedOperation_{false}; @@ -285,14 +306,14 @@ template <> class ListDirectedStatementState<Direction::Output> : public FormattedIoStatementState<Direction::Output> { public: - bool EmitLeadingSpaceOrAdvance( + RT_API_ATTRS bool EmitLeadingSpaceOrAdvance( IoStatementState &, std::size_t = 1, bool isCharacter = false); - std::optional<DataEdit> GetNextDataEdit( + RT_API_ATTRS Fortran::common::optional<DataEdit> GetNextDataEdit( IoStatementState &, int maxRepeat = 1); - bool lastWasUndelimitedCharacter() const { + RT_API_ATTRS bool lastWasUndelimitedCharacter() const { return lastWasUndelimitedCharacter_; } - void set_lastWasUndelimitedCharacter(bool yes = true) { + RT_API_ATTRS void set_lastWasUndelimitedCharacter(bool yes = true) { lastWasUndelimitedCharacter_ = yes; } @@ -303,20 +324,20 @@ template <> class ListDirectedStatementState<Direction::Input> : public FormattedIoStatementState<Direction::Input> { public: - bool inNamelistSequence() const { return inNamelistSequence_; } - int EndIoStatement(); + RT_API_ATTRS bool inNamelistSequence() const { return inNamelistSequence_; } + RT_API_ATTRS int EndIoStatement(); // Skips value separators, handles repetition and null values. // Vacant when '/' appears; present with descriptor == ListDirectedNullValue // when a null value appears. - std::optional<DataEdit> GetNextDataEdit( + RT_API_ATTRS Fortran::common::optional<DataEdit> GetNextDataEdit( IoStatementState &, int maxRepeat = 1); // Each NAMELIST input item is treated like a distinct list-directed // input statement. This member function resets some state so that // repetition and null values work correctly for each successive // NAMELIST input item. - void ResetForNextNamelistItem(bool inNamelistSequence) { + RT_API_ATTRS void ResetForNextNamelistItem(bool inNamelistSequence) { remaining_ = 0; if (repeatPosition_) { repeatPosition_->Cancel(); @@ -328,7 +349,7 @@ public: private: int remaining_{0}; // for "r*" repetition - std::optional<SavedPosition> repeatPosition_; + Fortran::common::optional<SavedPosition> repeatPosition_; bool eatComma_{false}; // consume comma after previously read item bool hitSlash_{false}; // once '/' is seen, nullify further items bool realPart_{false}; @@ -342,21 +363,22 @@ class InternalIoStatementState : public IoStatementBase, public: using Buffer = std::conditional_t<DIR == Direction::Input, const char *, char *>; - InternalIoStatementState(Buffer, std::size_t, + RT_API_ATTRS InternalIoStatementState(Buffer, std::size_t, const char *sourceFile = nullptr, int sourceLine = 0); - InternalIoStatementState( + RT_API_ATTRS InternalIoStatementState( const Descriptor &, const char *sourceFile = nullptr, int sourceLine = 0); - int EndIoStatement(); - - bool Emit(const char *data, std::size_t bytes, std::size_t elementBytes = 0); - std::size_t GetNextInputBytes(const char *&); - bool AdvanceRecord(int = 1); - void BackspaceRecord(); - ConnectionState &GetConnectionState() { return unit_; } - MutableModes &mutableModes() { return unit_.modes; } - void HandleRelativePosition(std::int64_t); - void HandleAbsolutePosition(std::int64_t); - std::int64_t InquirePos(); + RT_API_ATTRS int EndIoStatement(); + + RT_API_ATTRS bool Emit( + const char *data, std::size_t bytes, std::size_t elementBytes = 0); + RT_API_ATTRS std::size_t GetNextInputBytes(const char *&); + RT_API_ATTRS bool AdvanceRecord(int = 1); + RT_API_ATTRS void BackspaceRecord(); + RT_API_ATTRS ConnectionState &GetConnectionState() { return unit_; } + RT_API_ATTRS MutableModes &mutableModes() { return unit_.modes; } + RT_API_ATTRS void HandleRelativePosition(std::int64_t); + RT_API_ATTRS void HandleAbsolutePosition(std::int64_t); + RT_API_ATTRS std::int64_t InquirePos(); protected: bool free_{true}; @@ -370,17 +392,20 @@ class InternalFormattedIoStatementState public: using CharType = CHAR; using typename InternalIoStatementState<DIR>::Buffer; - InternalFormattedIoStatementState(Buffer internal, std::size_t internalLength, + RT_API_ATTRS InternalFormattedIoStatementState(Buffer internal, + std::size_t internalLength, const CharType *format, + std::size_t formatLength, const Descriptor *formatDescriptor = nullptr, + const char *sourceFile = nullptr, int sourceLine = 0); + RT_API_ATTRS InternalFormattedIoStatementState(const Descriptor &, const CharType *format, std::size_t formatLength, const Descriptor *formatDescriptor = nullptr, const char *sourceFile = nullptr, int sourceLine = 0); - InternalFormattedIoStatementState(const Descriptor &, const CharType *format, - std::size_t formatLength, const Descriptor *formatDescriptor = nullptr, - const char *sourceFile = nullptr, int sourceLine = 0); - IoStatementState &ioStatementState() { return ioStatementState_; } - void CompleteOperation(); - int EndIoStatement(); - std::optional<DataEdit> GetNextDataEdit( + RT_API_ATTRS IoStatementState &ioStatementState() { + return ioStatementState_; + } + RT_API_ATTRS void CompleteOperation(); + RT_API_ATTRS int EndIoStatement(); + RT_API_ATTRS Fortran::common::optional<DataEdit> GetNextDataEdit( IoStatementState &, int maxRepeat = 1) { return format_.GetNextDataEdit(*this, maxRepeat); } @@ -397,13 +422,17 @@ class InternalListIoStatementState : public InternalIoStatementState<DIR>, public ListDirectedStatementState<DIR> { public: using typename InternalIoStatementState<DIR>::Buffer; - InternalListIoStatementState(Buffer internal, std::size_t internalLength, - const char *sourceFile = nullptr, int sourceLine = 0); - InternalListIoStatementState( + RT_API_ATTRS InternalListIoStatementState(Buffer internal, + std::size_t internalLength, const char *sourceFile = nullptr, + int sourceLine = 0); + RT_API_ATTRS InternalListIoStatementState( const Descriptor &, const char *sourceFile = nullptr, int sourceLine = 0); - IoStatementState &ioStatementState() { return ioStatementState_; } + RT_API_ATTRS IoStatementState &ioStatementState() { + return ioStatementState_; + } using ListDirectedStatementState<DIR>::GetNextDataEdit; - int EndIoStatement(); + RT_API_ATTRS void CompleteOperation(); + RT_API_ATTRS int EndIoStatement(); private: IoStatementState ioStatementState_; // points to *this @@ -412,16 +441,16 @@ private: class ExternalIoStatementBase : public IoStatementBase { public: - ExternalIoStatementBase( + RT_API_ATTRS ExternalIoStatementBase( ExternalFileUnit &, const char *sourceFile = nullptr, int sourceLine = 0); - ExternalFileUnit &unit() { return unit_; } - MutableModes &mutableModes(); - ConnectionState &GetConnectionState(); - int asynchronousID() const { return asynchronousID_; } - int EndIoStatement(); - ExternalFileUnit *GetExternalFileUnit() const { return &unit_; } - void SetAsynchronous(); - std::int64_t InquirePos(); + RT_API_ATTRS ExternalFileUnit &unit() { return unit_; } + RT_API_ATTRS MutableModes &mutableModes(); + RT_API_ATTRS ConnectionState &GetConnectionState(); + RT_API_ATTRS int asynchronousID() const { return asynchronousID_; } + RT_API_ATTRS int EndIoStatement(); + RT_API_ATTRS ExternalFileUnit *GetExternalFileUnit() const { return &unit_; } + RT_API_ATTRS void SetAsynchronous(); + RT_API_ATTRS std::int64_t InquirePos(); private: ExternalFileUnit &unit_; @@ -432,19 +461,20 @@ template <Direction DIR> class ExternalIoStatementState : public ExternalIoStatementBase, public IoDirectionState<DIR> { public: - ExternalIoStatementState( + RT_API_ATTRS ExternalIoStatementState( ExternalFileUnit &, const char *sourceFile = nullptr, int sourceLine = 0); - MutableModes &mutableModes() { return mutableModes_; } - void CompleteOperation(); - int EndIoStatement(); - bool Emit(const char *, std::size_t bytes, std::size_t elementBytes = 0); - std::size_t GetNextInputBytes(const char *&); - bool AdvanceRecord(int = 1); - void BackspaceRecord(); - void HandleRelativePosition(std::int64_t); - void HandleAbsolutePosition(std::int64_t); - bool BeginReadingRecord(); - void FinishReadingRecord(); + RT_API_ATTRS MutableModes &mutableModes() { return mutableModes_; } + RT_API_ATTRS void CompleteOperation(); + RT_API_ATTRS int EndIoStatement(); + RT_API_ATTRS bool Emit( + const char *, std::size_t bytes, std::size_t elementBytes = 0); + RT_API_ATTRS std::size_t GetNextInputBytes(const char *&); + RT_API_ATTRS bool AdvanceRecord(int = 1); + RT_API_ATTRS void BackspaceRecord(); + RT_API_ATTRS void HandleRelativePosition(std::int64_t); + RT_API_ATTRS void HandleAbsolutePosition(std::int64_t); + RT_API_ATTRS bool BeginReadingRecord(); + RT_API_ATTRS void FinishReadingRecord(); private: // These are forked from ConnectionState's modes at the beginning @@ -459,12 +489,13 @@ class ExternalFormattedIoStatementState public FormattedIoStatementState<DIR> { public: using CharType = CHAR; - ExternalFormattedIoStatementState(ExternalFileUnit &, const CharType *format, - std::size_t formatLength, const Descriptor *formatDescriptor = nullptr, + RT_API_ATTRS ExternalFormattedIoStatementState(ExternalFileUnit &, + const CharType *format, std::size_t formatLength, + const Descriptor *formatDescriptor = nullptr, const char *sourceFile = nullptr, int sourceLine = 0); - void CompleteOperation(); - int EndIoStatement(); - std::optional<DataEdit> GetNextDataEdit( + RT_API_ATTRS void CompleteOperation(); + RT_API_ATTRS int EndIoStatement(); + RT_API_ATTRS Fortran::common::optional<DataEdit> GetNextDataEdit( IoStatementState &, int maxRepeat = 1) { return format_.GetNextDataEdit(*this, maxRepeat); } @@ -479,7 +510,7 @@ class ExternalListIoStatementState : public ExternalIoStatementState<DIR>, public: using ExternalIoStatementState<DIR>::ExternalIoStatementState; using ListDirectedStatementState<DIR>::GetNextDataEdit; - int EndIoStatement(); + RT_API_ATTRS int EndIoStatement(); }; template <Direction DIR> @@ -487,24 +518,25 @@ class ExternalUnformattedIoStatementState : public ExternalIoStatementState<DIR> { public: using ExternalIoStatementState<DIR>::ExternalIoStatementState; - bool Receive(char *, std::size_t, std::size_t elementBytes = 0); + RT_API_ATTRS bool Receive(char *, std::size_t, std::size_t elementBytes = 0); }; template <Direction DIR> class ChildIoStatementState : public IoStatementBase, public IoDirectionState<DIR> { public: - ChildIoStatementState( + RT_API_ATTRS ChildIoStatementState( ChildIo &, const char *sourceFile = nullptr, int sourceLine = 0); - ChildIo &child() { return child_; } - MutableModes &mutableModes(); - ConnectionState &GetConnectionState(); - ExternalFileUnit *GetExternalFileUnit() const; - int EndIoStatement(); - bool Emit(const char *, std::size_t bytes, std::size_t elementBytes = 0); - std::size_t GetNextInputBytes(const char *&); - void HandleRelativePosition(std::int64_t); - void HandleAbsolutePosition(std::int64_t); + RT_API_ATTRS ChildIo &child() { return child_; } + RT_API_ATTRS MutableModes &mutableModes(); + RT_API_ATTRS ConnectionState &GetConnectionState(); + RT_API_ATTRS ExternalFileUnit *GetExternalFileUnit() const; + RT_API_ATTRS int EndIoStatement(); + RT_API_ATTRS bool Emit( + const char *, std::size_t bytes, std::size_t elementBytes = 0); + RT_API_ATTRS std::size_t GetNextInputBytes(const char *&); + RT_API_ATTRS void HandleRelativePosition(std::int64_t); + RT_API_ATTRS void HandleAbsolutePosition(std::int64_t); private: ChildIo &child_; @@ -515,14 +547,14 @@ class ChildFormattedIoStatementState : public ChildIoStatementState<DIR>, public FormattedIoStatementState<DIR> { public: using CharType = CHAR; - ChildFormattedIoStatementState(ChildIo &, const CharType *format, + RT_API_ATTRS ChildFormattedIoStatementState(ChildIo &, const CharType *format, std::size_t formatLength, const Descriptor *formatDescriptor = nullptr, const char *sourceFile = nullptr, int sourceLine = 0); - MutableModes &mutableModes() { return mutableModes_; } - void CompleteOperation(); - int EndIoStatement(); - bool AdvanceRecord(int = 1); - std::optional<DataEdit> GetNextDataEdit( + RT_API_ATTRS MutableModes &mutableModes() { return mutableModes_; } + RT_API_ATTRS void CompleteOperation(); + RT_API_ATTRS int EndIoStatement(); + RT_API_ATTRS bool AdvanceRecord(int = 1); + RT_API_ATTRS Fortran::common::optional<DataEdit> GetNextDataEdit( IoStatementState &, int maxRepeat = 1) { return format_.GetNextDataEdit(*this, maxRepeat); } @@ -538,55 +570,63 @@ class ChildListIoStatementState : public ChildIoStatementState<DIR>, public: using ChildIoStatementState<DIR>::ChildIoStatementState; using ListDirectedStatementState<DIR>::GetNextDataEdit; - int EndIoStatement(); + RT_API_ATTRS int EndIoStatement(); }; template <Direction DIR> class ChildUnformattedIoStatementState : public ChildIoStatementState<DIR> { public: using ChildIoStatementState<DIR>::ChildIoStatementState; - bool Receive(char *, std::size_t, std::size_t elementBytes = 0); + RT_API_ATTRS bool Receive(char *, std::size_t, std::size_t elementBytes = 0); }; // OPEN class OpenStatementState : public ExternalIoStatementBase { public: - OpenStatementState(ExternalFileUnit &unit, bool wasExtant, bool isNewUnit, - const char *sourceFile = nullptr, int sourceLine = 0) + RT_API_ATTRS OpenStatementState(ExternalFileUnit &unit, bool wasExtant, + bool isNewUnit, const char *sourceFile = nullptr, int sourceLine = 0) : ExternalIoStatementBase{unit, sourceFile, sourceLine}, wasExtant_{wasExtant}, isNewUnit_{isNewUnit} {} - bool wasExtant() const { return wasExtant_; } - void set_status(OpenStatus status) { status_ = status; } // STATUS= - void set_path(const char *, std::size_t); // FILE= - void set_position(Position position) { position_ = position; } // POSITION= - void set_action(Action action) { action_ = action; } // ACTION= - void set_convert(Convert convert) { convert_ = convert; } // CONVERT= - void set_access(Access access) { access_ = access; } // ACCESS= - void set_isUnformatted(bool yes = true) { isUnformatted_ = yes; } // FORM= - - void CompleteOperation(); - int EndIoStatement(); + RT_API_ATTRS bool wasExtant() const { return wasExtant_; } + RT_API_ATTRS void set_status(OpenStatus status) { + status_ = status; + } // STATUS= + RT_API_ATTRS void set_path(const char *, std::size_t); // FILE= + RT_API_ATTRS void set_position(Position position) { + position_ = position; + } // POSITION= + RT_API_ATTRS void set_action(Action action) { action_ = action; } // ACTION= + RT_API_ATTRS void set_convert(Convert convert) { + convert_ = convert; + } // CONVERT= + RT_API_ATTRS void set_access(Access access) { access_ = access; } // ACCESS= + RT_API_ATTRS void set_isUnformatted(bool yes = true) { + isUnformatted_ = yes; + } // FORM= + + RT_API_ATTRS void CompleteOperation(); + RT_API_ATTRS int EndIoStatement(); private: bool wasExtant_; bool isNewUnit_; - std::optional<OpenStatus> status_; - std::optional<Position> position_; - std::optional<Action> action_; + Fortran::common::optional<OpenStatus> status_; + Fortran::common::optional<Position> position_; + Fortran::common::optional<Action> action_; Convert convert_{Convert::Unknown}; OwningPtr<char> path_; std::size_t pathLength_; - std::optional<bool> isUnformatted_; - std::optional<Access> access_; + Fortran::common::optional<bool> isUnformatted_; + Fortran::common::optional<Access> access_; }; class CloseStatementState : public ExternalIoStatementBase { public: - CloseStatementState(ExternalFileUnit &unit, const char *sourceFile = nullptr, - int sourceLine = 0) + RT_API_ATTRS CloseStatementState(ExternalFileUnit &unit, + const char *sourceFile = nullptr, int sourceLine = 0) : ExternalIoStatementBase{unit, sourceFile, sourceLine} {} - void set_status(CloseStatus status) { status_ = status; } - int EndIoStatement(); + RT_API_ATTRS void set_status(CloseStatus status) { status_ = status; } + RT_API_ATTRS int EndIoStatement(); private: CloseStatus status_{CloseStatus::Keep}; @@ -596,16 +636,18 @@ private: // and recoverable BACKSPACE(bad unit) class NoUnitIoStatementState : public IoStatementBase { public: - IoStatementState &ioStatementState() { return ioStatementState_; } - MutableModes &mutableModes() { return connection_.modes; } - ConnectionState &GetConnectionState() { return connection_; } - int badUnitNumber() const { return badUnitNumber_; } - void CompleteOperation(); - int EndIoStatement(); + RT_API_ATTRS IoStatementState &ioStatementState() { + return ioStatementState_; + } + RT_API_ATTRS MutableModes &mutableModes() { return connection_.modes; } + RT_API_ATTRS ConnectionState &GetConnectionState() { return connection_; } + RT_API_ATTRS int badUnitNumber() const { return badUnitNumber_; } + RT_API_ATTRS void CompleteOperation(); + RT_API_ATTRS int EndIoStatement(); protected: template <typename A> - NoUnitIoStatementState(A &stmt, const char *sourceFile = nullptr, + RT_API_ATTRS NoUnitIoStatementState(A &stmt, const char *sourceFile = nullptr, int sourceLine = 0, int badUnitNumber = -1) : IoStatementBase{sourceFile, sourceLine}, ioStatementState_{stmt}, badUnitNumber_{badUnitNumber} {} @@ -618,10 +660,10 @@ private: class NoopStatementState : public NoUnitIoStatementState { public: - NoopStatementState( + RT_API_ATTRS NoopStatementState( const char *sourceFile = nullptr, int sourceLine = 0, int unitNumber = -1) : NoUnitIoStatementState{*this, sourceFile, sourceLine, unitNumber} {} - void set_status(CloseStatus) {} // discards + RT_API_ATTRS void set_status(CloseStatus) {} // discards }; extern template class InternalIoStatementState<Direction::Output>; @@ -662,32 +704,32 @@ extern template class FormatControl< class InquireUnitState : public ExternalIoStatementBase { public: - InquireUnitState(ExternalFileUnit &unit, const char *sourceFile = nullptr, - int sourceLine = 0); - bool Inquire(InquiryKeywordHash, char *, std::size_t); - bool Inquire(InquiryKeywordHash, bool &); - bool Inquire(InquiryKeywordHash, std::int64_t, bool &); - bool Inquire(InquiryKeywordHash, std::int64_t &); + RT_API_ATTRS InquireUnitState(ExternalFileUnit &unit, + const char *sourceFile = nullptr, int sourceLine = 0); + RT_API_ATTRS bool Inquire(InquiryKeywordHash, char *, std::size_t); + RT_API_ATTRS bool Inquire(InquiryKeywordHash, bool &); + RT_API_ATTRS bool Inquire(InquiryKeywordHash, std::int64_t, bool &); + RT_API_ATTRS bool Inquire(InquiryKeywordHash, std::int64_t &); }; class InquireNoUnitState : public NoUnitIoStatementState { public: - InquireNoUnitState(const char *sourceFile = nullptr, int sourceLine = 0, - int badUnitNumber = -1); - bool Inquire(InquiryKeywordHash, char *, std::size_t); - bool Inquire(InquiryKeywordHash, bool &); - bool Inquire(InquiryKeywordHash, std::int64_t, bool &); - bool Inquire(InquiryKeywordHash, std::int64_t &); + RT_API_ATTRS InquireNoUnitState(const char *sourceFile = nullptr, + int sourceLine = 0, int badUnitNumber = -1); + RT_API_ATTRS bool Inquire(InquiryKeywordHash, char *, std::size_t); + RT_API_ATTRS bool Inquire(InquiryKeywordHash, bool &); + RT_API_ATTRS bool Inquire(InquiryKeywordHash, std::int64_t, bool &); + RT_API_ATTRS bool Inquire(InquiryKeywordHash, std::int64_t &); }; class InquireUnconnectedFileState : public NoUnitIoStatementState { public: - InquireUnconnectedFileState(OwningPtr<char> &&path, + RT_API_ATTRS InquireUnconnectedFileState(OwningPtr<char> &&path, const char *sourceFile = nullptr, int sourceLine = 0); - bool Inquire(InquiryKeywordHash, char *, std::size_t); - bool Inquire(InquiryKeywordHash, bool &); - bool Inquire(InquiryKeywordHash, std::int64_t, bool &); - bool Inquire(InquiryKeywordHash, std::int64_t &); + RT_API_ATTRS bool Inquire(InquiryKeywordHash, char *, std::size_t); + RT_API_ATTRS bool Inquire(InquiryKeywordHash, bool &); + RT_API_ATTRS bool Inquire(InquiryKeywordHash, std::int64_t, bool &); + RT_API_ATTRS bool Inquire(InquiryKeywordHash, std::int64_t &); private: OwningPtr<char> path_; // trimmed and NUL terminated @@ -696,9 +738,11 @@ private: class InquireIOLengthState : public NoUnitIoStatementState, public OutputStatementState { public: - InquireIOLengthState(const char *sourceFile = nullptr, int sourceLine = 0); - std::size_t bytes() const { return bytes_; } - bool Emit(const char *, std::size_t bytes, std::size_t elementBytes = 0); + RT_API_ATTRS InquireIOLengthState( + const char *sourceFile = nullptr, int sourceLine = 0); + RT_API_ATTRS std::size_t bytes() const { return bytes_; } + RT_API_ATTRS bool Emit( + const char *, std::size_t bytes, std::size_t elementBytes = 0); private: std::size_t bytes_{0}; @@ -707,11 +751,11 @@ private: class ExternalMiscIoStatementState : public ExternalIoStatementBase { public: enum Which { Flush, Backspace, Endfile, Rewind, Wait }; - ExternalMiscIoStatementState(ExternalFileUnit &unit, Which which, + RT_API_ATTRS ExternalMiscIoStatementState(ExternalFileUnit &unit, Which which, const char *sourceFile = nullptr, int sourceLine = 0) : ExternalIoStatementBase{unit, sourceFile, sourceLine}, which_{which} {} - void CompleteOperation(); - int EndIoStatement(); + RT_API_ATTRS void CompleteOperation(); + RT_API_ATTRS int EndIoStatement(); private: Which which_; @@ -719,15 +763,15 @@ private: class ErroneousIoStatementState : public IoStatementBase { public: - explicit ErroneousIoStatementState(Iostat iostat, + explicit RT_API_ATTRS ErroneousIoStatementState(Iostat iostat, ExternalFileUnit *unit = nullptr, const char *sourceFile = nullptr, int sourceLine = 0) : IoStatementBase{sourceFile, sourceLine}, unit_{unit} { SetPendingError(iostat); } - int EndIoStatement(); - ConnectionState &GetConnectionState() { return connection_; } - MutableModes &mutableModes() { return connection_.modes; } + RT_API_ATTRS int EndIoStatement(); + RT_API_ATTRS ConnectionState &GetConnectionState() { return connection_; } + RT_API_ATTRS MutableModes &mutableModes() { return connection_.modes; } private: ConnectionState connection_; diff --git a/flang/runtime/iostat.cpp b/flang/runtime/iostat.cpp index c993b778e9e1f8cbf40cf38da06f43701d4f5c37..39e224cb01286b305df10008a5f3b9822707d84a 100644 --- a/flang/runtime/iostat.cpp +++ b/flang/runtime/iostat.cpp @@ -9,6 +9,8 @@ #include "flang/Runtime/iostat.h" namespace Fortran::runtime::io { +RT_OFFLOAD_API_GROUP_BEGIN + const char *IostatErrorString(int iostat) { switch (iostat) { case IostatOk: @@ -122,4 +124,6 @@ const char *IostatErrorString(int iostat) { } } +RT_OFFLOAD_API_GROUP_END + } // namespace Fortran::runtime::io diff --git a/flang/runtime/lock.h b/flang/runtime/lock.h index 5fdcf4745c21c2f73e2651b764f97d5078a0eac7..9f27a8295c468b6bf735ef4fcc33b0dcbeb3c58d 100644 --- a/flang/runtime/lock.h +++ b/flang/runtime/lock.h @@ -12,6 +12,7 @@ #define FORTRAN_RUNTIME_LOCK_H_ #include "terminator.h" +#include "tools.h" // Avoid <mutex> if possible to avoid introduction of C++ runtime // library dependence. @@ -35,7 +36,17 @@ namespace Fortran::runtime { class Lock { public: -#if USE_PTHREADS +#if RT_USE_PSEUDO_LOCK + // No lock implementation, e.g. for using together + // with RT_USE_PSEUDO_FILE_UNIT. + // The users of Lock class may use it under + // USE_PTHREADS and otherwise, so it has to provide + // all the interfaces. + RT_API_ATTRS void Take() {} + RT_API_ATTRS bool Try() { return true; } + RT_API_ATTRS void Drop() {} + RT_API_ATTRS bool TakeIfNoDeadlock() { return true; } +#elif USE_PTHREADS Lock() { pthread_mutex_init(&mutex_, nullptr); } ~Lock() { pthread_mutex_destroy(&mutex_); } void Take() { @@ -79,7 +90,9 @@ public: } private: -#if USE_PTHREADS +#if RT_USE_PSEUDO_FILE_UNIT + // No state. +#elif USE_PTHREADS pthread_mutex_t mutex_{}; volatile bool isBusy_{false}; volatile pthread_t holder_; @@ -92,8 +105,10 @@ private: class CriticalSection { public: - explicit CriticalSection(Lock &lock) : lock_{lock} { lock_.Take(); } - ~CriticalSection() { lock_.Drop(); } + explicit RT_API_ATTRS CriticalSection(Lock &lock) : lock_{lock} { + lock_.Take(); + } + RT_API_ATTRS ~CriticalSection() { lock_.Drop(); } private: Lock &lock_; diff --git a/flang/runtime/matmul-transpose.cpp b/flang/runtime/matmul-transpose.cpp index ee5fcd842b025808e2ed3fc87f60d743c4397c9a..a12d188266f7c3d92edca10876cb8ef1321e4981 100644 --- a/flang/runtime/matmul-transpose.cpp +++ b/flang/runtime/matmul-transpose.cpp @@ -23,6 +23,7 @@ #include "flang/Runtime/matmul-transpose.h" #include "terminator.h" #include "tools.h" +#include "flang/Common/optional.h" #include "flang/Runtime/c-or-cpp.h" #include "flang/Runtime/cpp-type.h" #include "flang/Runtime/descriptor.h" @@ -96,8 +97,8 @@ template <TypeCategory RCAT, int RKIND, typename XT, typename YT> inline static RT_API_ATTRS void MatrixTransposedTimesMatrixHelper( CppTypeFor<RCAT, RKIND> *RESTRICT product, SubscriptValue rows, SubscriptValue cols, const XT *RESTRICT x, const YT *RESTRICT y, - SubscriptValue n, std::optional<std::size_t> xColumnByteStride, - std::optional<std::size_t> yColumnByteStride) { + SubscriptValue n, Fortran::common::optional<std::size_t> xColumnByteStride, + Fortran::common::optional<std::size_t> yColumnByteStride) { if (!xColumnByteStride) { if (!yColumnByteStride) { MatrixTransposedTimesMatrix<RCAT, RKIND, XT, YT, false, false>( @@ -163,7 +164,7 @@ template <TypeCategory RCAT, int RKIND, typename XT, typename YT> inline static RT_API_ATTRS void MatrixTransposedTimesVectorHelper( CppTypeFor<RCAT, RKIND> *RESTRICT product, SubscriptValue rows, SubscriptValue n, const XT *RESTRICT x, const YT *RESTRICT y, - std::optional<std::size_t> xColumnByteStride) { + Fortran::common::optional<std::size_t> xColumnByteStride) { if (!xColumnByteStride) { MatrixTransposedTimesVector<RCAT, RKIND, XT, YT, false>( product, rows, n, x, y); @@ -229,7 +230,7 @@ inline static RT_API_ATTRS void DoMatmulTranspose( (IS_ALLOCATING || result.IsContiguous())) { // Contiguous numeric matrices (maybe with columns // separated by a stride). - std::optional<std::size_t> xColumnByteStride; + Fortran::common::optional<std::size_t> xColumnByteStride; if (!x.IsContiguous()) { // X's columns are strided. SubscriptValue xAt[2]{}; @@ -237,7 +238,7 @@ inline static RT_API_ATTRS void DoMatmulTranspose( xAt[1]++; xColumnByteStride = x.SubscriptsToByteOffset(xAt); } - std::optional<std::size_t> yColumnByteStride; + Fortran::common::optional<std::size_t> yColumnByteStride; if (!y.IsContiguous()) { // Y's columns are strided. SubscriptValue yAt[2]{}; diff --git a/flang/runtime/matmul.cpp b/flang/runtime/matmul.cpp index e4595db779260f8dc61232f1daa717502c55683d..543284cb5c36335f3ddde4786e1d57111b84eaae 100644 --- a/flang/runtime/matmul.cpp +++ b/flang/runtime/matmul.cpp @@ -22,6 +22,7 @@ #include "flang/Runtime/matmul.h" #include "terminator.h" #include "tools.h" +#include "flang/Common/optional.h" #include "flang/Runtime/c-or-cpp.h" #include "flang/Runtime/cpp-type.h" #include "flang/Runtime/descriptor.h" @@ -116,8 +117,8 @@ template <TypeCategory RCAT, int RKIND, typename XT, typename YT> inline RT_API_ATTRS void MatrixTimesMatrixHelper( CppTypeFor<RCAT, RKIND> *RESTRICT product, SubscriptValue rows, SubscriptValue cols, const XT *RESTRICT x, const YT *RESTRICT y, - SubscriptValue n, std::optional<std::size_t> xColumnByteStride, - std::optional<std::size_t> yColumnByteStride) { + SubscriptValue n, Fortran::common::optional<std::size_t> xColumnByteStride, + Fortran::common::optional<std::size_t> yColumnByteStride) { if (!xColumnByteStride) { if (!yColumnByteStride) { MatrixTimesMatrix<RCAT, RKIND, XT, YT, false, false>( @@ -183,7 +184,7 @@ template <TypeCategory RCAT, int RKIND, typename XT, typename YT> inline RT_API_ATTRS void MatrixTimesVectorHelper( CppTypeFor<RCAT, RKIND> *RESTRICT product, SubscriptValue rows, SubscriptValue n, const XT *RESTRICT x, const YT *RESTRICT y, - std::optional<std::size_t> xColumnByteStride) { + Fortran::common::optional<std::size_t> xColumnByteStride) { if (!xColumnByteStride) { MatrixTimesVector<RCAT, RKIND, XT, YT, false>(product, rows, n, x, y); } else { @@ -240,7 +241,7 @@ template <TypeCategory RCAT, int RKIND, typename XT, typename YT, inline RT_API_ATTRS void VectorTimesMatrixHelper( CppTypeFor<RCAT, RKIND> *RESTRICT product, SubscriptValue n, SubscriptValue cols, const XT *RESTRICT x, const YT *RESTRICT y, - std::optional<std::size_t> yColumnByteStride) { + Fortran::common::optional<std::size_t> yColumnByteStride) { if (!yColumnByteStride) { VectorTimesMatrix<RCAT, RKIND, XT, YT, false>(product, n, cols, x, y); } else { @@ -301,7 +302,7 @@ static inline RT_API_ATTRS void DoMatmul( (IS_ALLOCATING || result.IsContiguous())) { // Contiguous numeric matrices (maybe with columns // separated by a stride). - std::optional<std::size_t> xColumnByteStride; + Fortran::common::optional<std::size_t> xColumnByteStride; if (!x.IsContiguous()) { // X's columns are strided. SubscriptValue xAt[2]{}; @@ -309,7 +310,7 @@ static inline RT_API_ATTRS void DoMatmul( xAt[1]++; xColumnByteStride = x.SubscriptsToByteOffset(xAt); } - std::optional<std::size_t> yColumnByteStride; + Fortran::common::optional<std::size_t> yColumnByteStride; if (!y.IsContiguous()) { // Y's columns are strided. SubscriptValue yAt[2]{}; diff --git a/flang/runtime/memory.cpp b/flang/runtime/memory.cpp index aa6ff9723d1a80696ca21d1400338ecd95c02bbd..de6c4c72fdac14ce38afc8eab272975f83493584 100644 --- a/flang/runtime/memory.cpp +++ b/flang/runtime/memory.cpp @@ -7,15 +7,15 @@ //===----------------------------------------------------------------------===// #include "flang/Runtime/memory.h" +#include "freestanding-tools.h" #include "terminator.h" #include "tools.h" #include <cstdlib> namespace Fortran::runtime { -RT_OFFLOAD_VAR_GROUP_BEGIN +RT_OFFLOAD_API_GROUP_BEGIN -RT_API_ATTRS void *AllocateMemoryOrCrash( - const Terminator &terminator, std::size_t bytes) { +void *AllocateMemoryOrCrash(const Terminator &terminator, std::size_t bytes) { if (void *p{std::malloc(bytes)}) { return p; } @@ -27,7 +27,7 @@ RT_API_ATTRS void *AllocateMemoryOrCrash( return nullptr; } -RT_API_ATTRS void *ReallocateMemoryOrCrash( +void *ReallocateMemoryOrCrash( const Terminator &terminator, void *ptr, std::size_t newByteSize) { if (void *p{Fortran::runtime::realloc(ptr, newByteSize)}) { return p; @@ -40,7 +40,7 @@ RT_API_ATTRS void *ReallocateMemoryOrCrash( return nullptr; } -RT_API_ATTRS void FreeMemory(void *p) { std::free(p); } +void FreeMemory(void *p) { std::free(p); } -RT_OFFLOAD_VAR_GROUP_END +RT_OFFLOAD_API_GROUP_END } // namespace Fortran::runtime diff --git a/flang/runtime/misc-intrinsic.cpp b/flang/runtime/misc-intrinsic.cpp index 56f2028c2ff02cad28a36e8350816831c78fcc29..f5b292a1f3d32ccdf0c16b693c2a94349638ba4a 100644 --- a/flang/runtime/misc-intrinsic.cpp +++ b/flang/runtime/misc-intrinsic.cpp @@ -9,16 +9,16 @@ #include "flang/Runtime/misc-intrinsic.h" #include "terminator.h" #include "tools.h" +#include "flang/Common/optional.h" #include "flang/Runtime/descriptor.h" #include <algorithm> #include <cstring> -#include <optional> namespace Fortran::runtime { static RT_API_ATTRS void TransferImpl(Descriptor &result, const Descriptor &source, const Descriptor &mold, const char *sourceFile, - int line, std::optional<std::int64_t> resultExtent) { + int line, Fortran::common::optional<std::int64_t> resultExtent) { int rank{resultExtent.has_value() ? 1 : 0}; std::size_t elementBytes{mold.ElementBytes()}; result.Establish(mold.type(), elementBytes, nullptr, rank, nullptr, @@ -57,7 +57,7 @@ RT_EXT_API_GROUP_BEGIN void RTDEF(Transfer)(Descriptor &result, const Descriptor &source, const Descriptor &mold, const char *sourceFile, int line) { - std::optional<std::int64_t> elements; + Fortran::common::optional<std::int64_t> elements; if (mold.rank() > 0) { if (std::size_t sourceElementBytes{ source.Elements() * source.ElementBytes()}) { diff --git a/flang/runtime/namelist.cpp b/flang/runtime/namelist.cpp index f5d7404fdcb86b7e72ee952b451e3d025da79a57..b502d41a8d5c89e68de93fc7cb563cede8cb8f4c 100644 --- a/flang/runtime/namelist.cpp +++ b/flang/runtime/namelist.cpp @@ -31,9 +31,12 @@ bool IONAME(OutputNamelist)(Cookie cookie, const NamelistGroup &group) { io.CheckFormattedStmtType<Direction::Output>("OutputNamelist"); io.mutableModes().inNamelist = true; ConnectionState &connection{io.GetConnectionState()}; + // The following lambda definition violates the conding style, + // but cuda-11.8 nvcc hits an internal error with the brace initialization. + // Internal function to advance records and convert case - const auto EmitUpperCase{[&](const char *prefix, std::size_t prefixLen, - const char *str, char suffix) -> bool { + const auto EmitUpperCase = [&](const char *prefix, std::size_t prefixLen, + const char *str, char suffix) -> bool { if ((connection.NeedAdvance(prefixLen) && !(io.AdvanceRecord() && EmitAscii(io, " ", 1))) || !EmitAscii(io, prefix, prefixLen) || @@ -49,7 +52,7 @@ bool IONAME(OutputNamelist)(Cookie cookie, const NamelistGroup &group) { } } return suffix == ' ' || EmitAscii(io, &suffix, 1); - }}; + }; // &GROUP if (!EmitUpperCase(" &", 2, group.groupName, ' ')) { return false; @@ -116,10 +119,11 @@ static bool GetLowerCaseName( return false; } -static std::optional<SubscriptValue> GetSubscriptValue(IoStatementState &io) { - std::optional<SubscriptValue> value; +static Fortran::common::optional<SubscriptValue> GetSubscriptValue( + IoStatementState &io) { + Fortran::common::optional<SubscriptValue> value; std::size_t byteCount{0}; - std::optional<char32_t> ch{io.GetCurrentChar(byteCount)}; + Fortran::common::optional<char32_t> ch{io.GetCurrentChar(byteCount)}; bool negate{ch && *ch == '-'}; if ((ch && *ch == '+') || negate) { io.HandleRelativePosition(byteCount); @@ -136,7 +140,7 @@ static std::optional<SubscriptValue> GetSubscriptValue(IoStatementState &io) { if (overflow) { io.GetIoErrorHandler().SignalError( "NAMELIST input subscript value overflow"); - return std::nullopt; + return Fortran::common::nullopt; } if (negate) { if (value) { @@ -158,7 +162,7 @@ static bool HandleSubscripts(IoStatementState &io, Descriptor &desc, std::size_t contiguousStride{source.ElementBytes()}; bool ok{true}; std::size_t byteCount{0}; - std::optional<char32_t> ch{io.GetNextNonBlank(byteCount)}; + Fortran::common::optional<char32_t> ch{io.GetNextNonBlank(byteCount)}; char32_t comma{GetComma(io)}; for (; ch && *ch != ')'; ++j) { SubscriptValue dimLower{0}, dimUpper{0}, dimStride{0}; @@ -282,9 +286,9 @@ static bool HandleSubstring( SubscriptValue chars{static_cast<SubscriptValue>(desc.ElementBytes()) / kind}; // Allow for blanks in substring bounds; they're nonstandard, but not // ambiguous within the parentheses. - std::optional<SubscriptValue> lower, upper; + Fortran::common::optional<SubscriptValue> lower, upper; std::size_t byteCount{0}; - std::optional<char32_t> ch{io.GetNextNonBlank(byteCount)}; + Fortran::common::optional<char32_t> ch{io.GetNextNonBlank(byteCount)}; if (ch) { if (*ch == ':') { lower = 1; @@ -293,7 +297,7 @@ static bool HandleSubstring( ch = io.GetNextNonBlank(byteCount); } } - if (ch && ch == ':') { + if (ch && *ch == ':') { io.HandleRelativePosition(byteCount); ch = io.GetNextNonBlank(byteCount); if (ch) { @@ -346,7 +350,8 @@ static bool HandleComponent(IoStatementState &io, Descriptor &desc, // If base and component are both arrays, the component name // must be followed by subscripts; process them now. std::size_t byteCount{0}; - if (std::optional<char32_t> next{io.GetNextNonBlank(byteCount)}; + if (Fortran::common::optional<char32_t> next{ + io.GetNextNonBlank(byteCount)}; next && *next == '(') { io.HandleRelativePosition(byteCount); // skip over '(' StaticDescriptor<maxRank, true, 16> staticDesc; @@ -435,7 +440,7 @@ bool IONAME(InputNamelist)(Cookie cookie, const NamelistGroup &group) { RUNTIME_CHECK(handler, listInput != nullptr); // Find this namelist group's header in the input io.BeginReadingRecord(); - std::optional<char32_t> next; + Fortran::common::optional<char32_t> next; char name[nameBufferSize]; RUNTIME_CHECK(handler, group.groupName != nullptr); char32_t comma{GetComma(io)}; @@ -585,6 +590,8 @@ bool IONAME(InputNamelist)(Cookie cookie, const NamelistGroup &group) { return true; } +RT_OFFLOAD_API_GROUP_BEGIN + bool IsNamelistNameOrSlash(IoStatementState &io) { if (auto *listInput{ io.get_if<ListDirectedStatementState<Direction::Input>>()}) { @@ -609,4 +616,6 @@ bool IsNamelistNameOrSlash(IoStatementState &io) { return false; } +RT_OFFLOAD_API_GROUP_END + } // namespace Fortran::runtime::io diff --git a/flang/runtime/namelist.h b/flang/runtime/namelist.h index 9a5da33a907e44e93f226522f81473c6bc021ad8..25216a75e9367df7a1fbf6112aaf94d11835dfb9 100644 --- a/flang/runtime/namelist.h +++ b/flang/runtime/namelist.h @@ -12,6 +12,7 @@ #define FORTRAN_RUNTIME_NAMELIST_H_ #include "non-tbp-dio.h" +#include "flang/Common/api-attrs.h" #include <cstddef> @@ -47,7 +48,7 @@ public: // character; for use in disambiguating a name-like value (e.g. F or T) from a // NAMELIST group item name and for coping with short arrays. Always false // when not reading a NAMELIST. -bool IsNamelistNameOrSlash(IoStatementState &); +RT_API_ATTRS bool IsNamelistNameOrSlash(IoStatementState &); } // namespace Fortran::runtime::io #endif // FORTRAN_RUNTIME_NAMELIST_H_ diff --git a/flang/runtime/non-tbp-dio.h b/flang/runtime/non-tbp-dio.h index a2030dbfdfe8d3b6ad6bca2fd66c5a64ae1aa4de..05038a264ed9929519d81d1bd9096ad28f109e2b 100644 --- a/flang/runtime/non-tbp-dio.h +++ b/flang/runtime/non-tbp-dio.h @@ -39,7 +39,7 @@ struct NonTbpDefinedIo { }; struct NonTbpDefinedIoTable { - const NonTbpDefinedIo *Find( + RT_API_ATTRS const NonTbpDefinedIo *Find( const typeInfo::DerivedType &, common::DefinedIo) const; std::size_t items{0}; const NonTbpDefinedIo *item{nullptr}; diff --git a/flang/runtime/numeric-templates.h b/flang/runtime/numeric-templates.h index ecc3b2654d9652ab46f52d2d98e2dd48a456d5c3..af552f9ddfc0bd3732917a69538c45d9384f6af3 100644 --- a/flang/runtime/numeric-templates.h +++ b/flang/runtime/numeric-templates.h @@ -20,8 +20,8 @@ #include "terminator.h" #include "tools.h" +#include "flang/Common/api-attrs.h" #include "flang/Common/float128.h" -#include "flang/Runtime/api-attrs.h" #include <cstdint> #include <limits> @@ -122,12 +122,19 @@ template <typename T> struct ABSTy { static constexpr RT_API_ATTRS T compute(T x) { return std::abs(x); } }; +// Suppress the warnings about calling __host__-only +// 'long double' std::frexp, from __device__ code. +RT_DIAG_PUSH +RT_DIAG_DISABLE_CALL_HOST_FROM_DEVICE_WARN + template <typename T> struct FREXPTy { static constexpr RT_API_ATTRS T compute(T x, int *e) { return std::frexp(x, e); } }; +RT_DIAG_POP + template <typename T> struct ILOGBTy { static constexpr RT_API_ATTRS int compute(T x) { return std::ilogb(x); } }; @@ -186,11 +193,6 @@ inline RT_API_ATTRS RESULT Exponent(ARG x) { } } -// Suppress the warnings about calling __host__-only std::frexp, -// defined in C++ STD header files, from __device__ code. -RT_DIAG_PUSH -RT_DIAG_DISABLE_CALL_HOST_FROM_DEVICE_WARN - // FRACTION (16.9.80) template <typename T> inline RT_API_ATTRS T Fraction(T x) { if (ISNANTy<T>::compute(x)) { @@ -205,8 +207,6 @@ template <typename T> inline RT_API_ATTRS T Fraction(T x) { } } -RT_DIAG_POP - // SET_EXPONENT (16.9.171) template <typename T> inline RT_API_ATTRS T SetExponent(T x, std::int64_t p) { if (ISNANTy<T>::compute(x)) { diff --git a/flang/runtime/pointer.cpp b/flang/runtime/pointer.cpp index fc9e0eeb7dac99e16f3ec8f5e0c7f832a3bafe37..08a1223764f3932f3bfab06b8a0dfb3635efee73 100644 --- a/flang/runtime/pointer.cpp +++ b/flang/runtime/pointer.cpp @@ -9,6 +9,7 @@ #include "flang/Runtime/pointer.h" #include "assign-impl.h" #include "derived.h" +#include "environment.h" #include "stat.h" #include "terminator.h" #include "tools.h" @@ -184,17 +185,20 @@ int RTDEF(PointerDeallocate)(Descriptor &pointer, bool hasStat, if (!pointer.IsAllocated()) { return ReturnError(terminator, StatBaseNull, errMsg, hasStat); } - // Validate the footer. This should fail if the pointer doesn't - // span the entire object, or the object was not allocated as a - // pointer. - std::size_t byteSize{pointer.Elements() * pointer.ElementBytes()}; - constexpr std::size_t align{sizeof(std::uintptr_t)}; - byteSize = ((byteSize + align - 1) / align) * align; - void *p{pointer.raw().base_addr}; - std::uintptr_t *footer{ - reinterpret_cast<std::uintptr_t *>(static_cast<char *>(p) + byteSize)}; - if (*footer != ~reinterpret_cast<std::uintptr_t>(p)) { - return ReturnError(terminator, StatBadPointerDeallocation, errMsg, hasStat); + if (executionEnvironment.checkPointerDeallocation) { + // Validate the footer. This should fail if the pointer doesn't + // span the entire object, or the object was not allocated as a + // pointer. + std::size_t byteSize{pointer.Elements() * pointer.ElementBytes()}; + constexpr std::size_t align{sizeof(std::uintptr_t)}; + byteSize = ((byteSize + align - 1) / align) * align; + void *p{pointer.raw().base_addr}; + std::uintptr_t *footer{ + reinterpret_cast<std::uintptr_t *>(static_cast<char *>(p) + byteSize)}; + if (*footer != ~reinterpret_cast<std::uintptr_t>(p)) { + return ReturnError( + terminator, StatBadPointerDeallocation, errMsg, hasStat); + } } return ReturnError(terminator, pointer.Destroy(/*finalize=*/true, /*destroyPointers=*/true, &terminator), diff --git a/flang/runtime/pseudo-unit.cpp b/flang/runtime/pseudo-unit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a57e3a59efa5fc65bdee533e67203e097672111b --- /dev/null +++ b/flang/runtime/pseudo-unit.cpp @@ -0,0 +1,169 @@ +//===-- runtime/pseudo-unit.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 +// +//===----------------------------------------------------------------------===// +// +// Implemenation of ExternalFileUnit and PseudoOpenFile for +// RT_USE_PSEUDO_FILE_UNIT=1. +// +//===----------------------------------------------------------------------===// + +#include "io-error.h" +#include "tools.h" +#include "unit.h" + +// NOTE: the header files above may define OpenMP declare target +// variables, so they have to be included unconditionally +// so that the offload entries are consistent between host and device. +#if defined(RT_USE_PSEUDO_FILE_UNIT) +#include <cstdio> + +namespace Fortran::runtime::io { + +void FlushOutputOnCrash(const Terminator &) {} + +ExternalFileUnit *ExternalFileUnit::LookUp(int) { + Terminator{__FILE__, __LINE__}.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +ExternalFileUnit *ExternalFileUnit::LookUpOrCreate( + int, const Terminator &, bool &) { + Terminator{__FILE__, __LINE__}.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +ExternalFileUnit *ExternalFileUnit::LookUpOrCreateAnonymous(int unit, + Direction direction, Fortran::common::optional<bool>, + const Terminator &terminator) { + if (direction != Direction::Output) { + terminator.Crash("ExternalFileUnit only supports output IO"); + } + return New<ExternalFileUnit>{terminator}(unit).release(); +} + +ExternalFileUnit *ExternalFileUnit::LookUp(const char *, std::size_t) { + Terminator{__FILE__, __LINE__}.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +ExternalFileUnit &ExternalFileUnit::CreateNew(int, const Terminator &) { + Terminator{__FILE__, __LINE__}.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +ExternalFileUnit *ExternalFileUnit::LookUpForClose(int) { + Terminator{__FILE__, __LINE__}.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +ExternalFileUnit &ExternalFileUnit::NewUnit(const Terminator &, bool) { + Terminator{__FILE__, __LINE__}.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +bool ExternalFileUnit::OpenUnit(Fortran::common::optional<OpenStatus> status, + Fortran::common::optional<Action>, Position, OwningPtr<char> &&, + std::size_t, Convert, IoErrorHandler &handler) { + handler.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +void ExternalFileUnit::OpenAnonymousUnit(Fortran::common::optional<OpenStatus>, + Fortran::common::optional<Action>, Position, Convert convert, + IoErrorHandler &handler) { + handler.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +void ExternalFileUnit::CloseUnit(CloseStatus, IoErrorHandler &handler) { + handler.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +void ExternalFileUnit::DestroyClosed() { + Terminator{__FILE__, __LINE__}.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +Iostat ExternalFileUnit::SetDirection(Direction direction) { + if (direction != Direction::Output) { + return IostatReadFromWriteOnly; + } + direction_ = direction; + return IostatOk; +} + +void ExternalFileUnit::CloseAll(IoErrorHandler &) {} + +void ExternalFileUnit::FlushAll(IoErrorHandler &) {} + +int ExternalFileUnit::GetAsynchronousId(IoErrorHandler &handler) { + handler.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +bool ExternalFileUnit::Wait(int) { + Terminator{__FILE__, __LINE__}.Crash("unsupported"); +} + +void PseudoOpenFile::set_mayAsynchronous(bool yes) { + if (yes) { + Terminator{__FILE__, __LINE__}.Crash("%s: unsupported", RT_PRETTY_FUNCTION); + } +} + +Fortran::common::optional<PseudoOpenFile::FileOffset> +PseudoOpenFile::knownSize() const { + Terminator{__FILE__, __LINE__}.Crash("unsupported"); +} + +void PseudoOpenFile::Open(OpenStatus, Fortran::common::optional<Action>, + Position, IoErrorHandler &handler) { + handler.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +void PseudoOpenFile::Close(CloseStatus, IoErrorHandler &handler) { + handler.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +std::size_t PseudoOpenFile::Read( + FileOffset, char *, std::size_t, std::size_t, IoErrorHandler &handler) { + handler.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +std::size_t PseudoOpenFile::Write(FileOffset at, const char *buffer, + std::size_t bytes, IoErrorHandler &handler) { + if (at) { + handler.Crash("%s: unsupported", RT_PRETTY_FUNCTION); + } + // TODO: use persistent string buffer that can be reallocated + // as needed, and only freed at destruction of *this. + auto string{SizedNew<char>{handler}(bytes + 1)}; + std::memcpy(string.get(), buffer, bytes); + string.get()[bytes] = '\0'; + std::printf("%s", string.get()); + return bytes; +} + +void PseudoOpenFile::Truncate(FileOffset, IoErrorHandler &handler) { + handler.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +int PseudoOpenFile::ReadAsynchronously( + FileOffset, char *, std::size_t, IoErrorHandler &handler) { + handler.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +int PseudoOpenFile::WriteAsynchronously( + FileOffset, const char *, std::size_t, IoErrorHandler &handler) { + handler.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +void PseudoOpenFile::Wait(int, IoErrorHandler &handler) { + handler.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +void PseudoOpenFile::WaitAll(IoErrorHandler &handler) { + handler.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +Position PseudoOpenFile::InquirePosition() const { + Terminator{__FILE__, __LINE__}.Crash("%s: unsupported", RT_PRETTY_FUNCTION); +} + +} // namespace Fortran::runtime::io + +#endif // defined(RT_USE_PSEUDO_FILE_UNIT) diff --git a/flang/runtime/random-templates.h b/flang/runtime/random-templates.h new file mode 100644 index 0000000000000000000000000000000000000000..f34422f6f5d9acce80f4a1319d1c935e068b4afe --- /dev/null +++ b/flang/runtime/random-templates.h @@ -0,0 +1,88 @@ +//===-- runtime/random-templates.h ------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef FORTRAN_RUNTIME_RANDOM_TEMPLATES_H_ +#define FORTRAN_RUNTIME_RANDOM_TEMPLATES_H_ + +#include "lock.h" +#include "numeric-templates.h" +#include "flang/Common/optional.h" +#include "flang/Runtime/descriptor.h" +#include <algorithm> +#include <random> + +namespace Fortran::runtime::random { + +// Newer "Minimum standard", recommended by Park, Miller, and Stockmeyer in +// 1993. Same as C++17 std::minstd_rand, but explicitly instantiated for +// permanence. +using Generator = + std::linear_congruential_engine<std::uint_fast32_t, 48271, 0, 2147483647>; + +using GeneratedWord = typename Generator::result_type; +static constexpr std::uint64_t range{ + static_cast<std::uint64_t>(Generator::max() - Generator::min() + 1)}; +static constexpr bool rangeIsPowerOfTwo{(range & (range - 1)) == 0}; +static constexpr int rangeBits{ + 64 - common::LeadingZeroBitCount(range) - !rangeIsPowerOfTwo}; + +extern Lock lock; +extern Generator generator; +extern Fortran::common::optional<GeneratedWord> nextValue; + +// Call only with lock held +static GeneratedWord GetNextValue() { + GeneratedWord result; + if (nextValue.has_value()) { + result = *nextValue; + nextValue.reset(); + } else { + result = generator(); + } + return result; +} + +template <typename REAL, int PREC> +inline void Generate(const Descriptor &harvest) { + static constexpr std::size_t minBits{ + std::max<std::size_t>(PREC, 8 * sizeof(GeneratedWord))}; + using Int = common::HostUnsignedIntType<minBits>; + static constexpr std::size_t words{ + static_cast<std::size_t>(PREC + rangeBits - 1) / rangeBits}; + std::size_t elements{harvest.Elements()}; + SubscriptValue at[maxRank]; + harvest.GetLowerBounds(at); + { + CriticalSection critical{lock}; + for (std::size_t j{0}; j < elements; ++j) { + while (true) { + Int fraction{GetNextValue()}; + if constexpr (words > 1) { + for (std::size_t k{1}; k < words; ++k) { + static constexpr auto rangeMask{ + (GeneratedWord{1} << rangeBits) - 1}; + GeneratedWord word{(GetNextValue() - generator.min()) & rangeMask}; + fraction = (fraction << rangeBits) | word; + } + } + fraction >>= words * rangeBits - PREC; + REAL next{ + LDEXPTy<REAL>::compute(static_cast<REAL>(fraction), -(PREC + 1))}; + if (next >= 0.0 && next < 1.0) { + *harvest.Element<REAL>(at) = next; + break; + } + } + harvest.IncrementSubscripts(at); + } + } +} + +} // namespace Fortran::runtime::random + +#endif // FORTRAN_RUNTIME_RANDOM_TEMPLATES_H_ diff --git a/flang/runtime/random.cpp b/flang/runtime/random.cpp index 642091a06aff552ae6bda0d1e421cf5eea28c381..e0a421fd2839622413e0fe96b0df1fffe44b62e7 100644 --- a/flang/runtime/random.cpp +++ b/flang/runtime/random.cpp @@ -11,85 +11,24 @@ #include "flang/Runtime/random.h" #include "lock.h" +#include "random-templates.h" #include "terminator.h" #include "flang/Common/float128.h" #include "flang/Common/leading-zero-bit-count.h" #include "flang/Common/uint128.h" #include "flang/Runtime/cpp-type.h" #include "flang/Runtime/descriptor.h" -#include <algorithm> #include <cmath> #include <cstdint> #include <limits> #include <memory> -#include <random> #include <time.h> -namespace Fortran::runtime { +namespace Fortran::runtime::random { -// Newer "Minimum standard", recommended by Park, Miller, and Stockmeyer in -// 1993. Same as C++17 std::minstd_rand, but explicitly instantiated for -// permanence. -using Generator = - std::linear_congruential_engine<std::uint_fast32_t, 48271, 0, 2147483647>; - -using GeneratedWord = typename Generator::result_type; -static constexpr std::uint64_t range{ - static_cast<std::uint64_t>(Generator::max() - Generator::min() + 1)}; -static constexpr bool rangeIsPowerOfTwo{(range & (range - 1)) == 0}; -static constexpr int rangeBits{ - 64 - common::LeadingZeroBitCount(range) - !rangeIsPowerOfTwo}; - -static Lock lock; -static Generator generator; -static std::optional<GeneratedWord> nextValue; - -// Call only with lock held -static GeneratedWord GetNextValue() { - GeneratedWord result; - if (nextValue.has_value()) { - result = *nextValue; - nextValue.reset(); - } else { - result = generator(); - } - return result; -} - -template <typename REAL, int PREC> -inline void Generate(const Descriptor &harvest) { - static constexpr std::size_t minBits{ - std::max<std::size_t>(PREC, 8 * sizeof(GeneratedWord))}; - using Int = common::HostUnsignedIntType<minBits>; - static constexpr std::size_t words{ - static_cast<std::size_t>(PREC + rangeBits - 1) / rangeBits}; - std::size_t elements{harvest.Elements()}; - SubscriptValue at[maxRank]; - harvest.GetLowerBounds(at); - { - CriticalSection critical{lock}; - for (std::size_t j{0}; j < elements; ++j) { - while (true) { - Int fraction{GetNextValue()}; - if constexpr (words > 1) { - for (std::size_t k{1}; k < words; ++k) { - static constexpr auto rangeMask{ - (GeneratedWord{1} << rangeBits) - 1}; - GeneratedWord word{(GetNextValue() - generator.min()) & rangeMask}; - fraction = (fraction << rangeBits) | word; - } - } - fraction >>= words * rangeBits - PREC; - REAL next{std::ldexp(static_cast<REAL>(fraction), -(PREC + 1))}; - if (next >= 0.0 && next < 1.0) { - *harvest.Element<REAL>(at) = next; - break; - } - } - harvest.IncrementSubscripts(at); - } - } -} +Lock lock; +Generator generator; +Fortran::common::optional<GeneratedWord> nextValue; extern "C" { @@ -130,14 +69,6 @@ void RTNAME(RandomNumber)( #if LDBL_MANT_DIG == 64 Generate<CppTypeFor<TypeCategory::Real, 10>, 64>(harvest); return; -#endif - } - break; - case 16: - if constexpr (HasCppTypeFor<TypeCategory::Real, 16>) { -#if LDBL_MANT_DIG == 113 - Generate<CppTypeFor<TypeCategory::Real, 16>, 113>(harvest); - return; #endif } break; @@ -263,4 +194,4 @@ void RTNAME(RandomSeed)(const Descriptor *size, const Descriptor *put, } } // extern "C" -} // namespace Fortran::runtime +} // namespace Fortran::runtime::random diff --git a/flang/runtime/reduce.cpp b/flang/runtime/reduce.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f8a5221a1ebf76f41d61264944ea79066b70298c --- /dev/null +++ b/flang/runtime/reduce.cpp @@ -0,0 +1,526 @@ +//===-- runtime/reduce.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 +// +//===----------------------------------------------------------------------===// + +// REDUCE() implementation + +#include "flang/Runtime/reduce.h" +#include "reduction-templates.h" +#include "terminator.h" +#include "tools.h" +#include "flang/Runtime/descriptor.h" + +namespace Fortran::runtime { + +template <typename T> class ReduceAccumulator { +public: + RT_API_ATTRS ReduceAccumulator(const Descriptor &array, + ReductionOperation<T> operation, const T *identity, + Terminator &terminator) + : array_{array}, operation_{operation}, identity_{identity}, + terminator_{terminator} {} + RT_API_ATTRS void Reinitialize() { result_.reset(); } + template <typename A> + RT_API_ATTRS bool AccumulateAt(const SubscriptValue at[]) { + const auto *operand{array_.Element<A>(at)}; + if (result_) { + result_ = operation_(&*result_, operand); + } else { + result_ = *operand; + } + return true; + } + template <typename A> + RT_API_ATTRS void GetResult(A *to, int /*zeroBasedDim*/ = -1) { + if (result_) { + *to = *result_; + } else if (identity_) { + *to = *identity_; + } else { + terminator_.Crash("REDUCE() without IDENTITY= has no result"); + } + } + +private: + const Descriptor &array_; + common::optional<T> result_; + ReductionOperation<T> operation_; + const T *identity_{nullptr}; + Terminator &terminator_; +}; + +template <typename T, typename OP, bool hasLength> +class BufferedReduceAccumulator { +public: + RT_API_ATTRS BufferedReduceAccumulator(const Descriptor &array, OP operation, + const T *identity, Terminator &terminator) + : array_{array}, operation_{operation}, identity_{identity}, + terminator_{terminator} {} + RT_API_ATTRS void Reinitialize() { activeTemp_ = -1; } + template <typename A> + RT_API_ATTRS bool AccumulateAt(const SubscriptValue at[]) { + const auto *operand{array_.Element<A>(at)}; + if (activeTemp_ >= 0) { + if constexpr (hasLength) { + operation_(&*temp_[1 - activeTemp_], length_, &*temp_[activeTemp_], + operand, length_, length_); + } else { + operation_(&*temp_[1 - activeTemp_], &*temp_[activeTemp_], operand); + } + activeTemp_ = 1 - activeTemp_; + } else { + activeTemp_ = 0; + std::memcpy(&*temp_[activeTemp_], operand, elementBytes_); + } + return true; + } + template <typename A> + RT_API_ATTRS void GetResult(A *to, int /*zeroBasedDim*/ = -1) { + if (activeTemp_ >= 0) { + std::memcpy(to, &*temp_[activeTemp_], elementBytes_); + } else if (identity_) { + std::memcpy(to, identity_, elementBytes_); + } else { + terminator_.Crash("REDUCE() without IDENTITY= has no result"); + } + } + +private: + const Descriptor &array_; + OP operation_; + const T *identity_{nullptr}; + Terminator &terminator_; + std::size_t elementBytes_{array_.ElementBytes()}; + OwningPtr<T> temp_[2]{SizedNew<T>{terminator_}(elementBytes_), + SizedNew<T>{terminator_}(elementBytes_)}; + int activeTemp_{-1}; + std::size_t length_{elementBytes_ / sizeof(T)}; +}; + +extern "C" { +RT_EXT_API_GROUP_BEGIN + +std::int8_t RTDEF(ReduceInteger1)(const Descriptor &array, + ReductionOperation<std::int8_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const std::int8_t *identity, + bool ordered) { + Terminator terminator{source, line}; + return GetTotalReduction<TypeCategory::Integer, 1>(array, source, line, dim, + mask, + ReduceAccumulator<std::int8_t>{array, operation, identity, terminator}, + "REDUCE"); +} +void RTDEF(ReduceInteger1Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::int8_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const std::int8_t *identity, + bool ordered) { + Terminator terminator{source, line}; + using Accumulator = ReduceAccumulator<std::int8_t>; + Accumulator accumulator{array, operation, identity, terminator}; + PartialReduction<Accumulator, TypeCategory::Integer, 1>(result, array, + array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator); +} +std::int16_t RTDEF(ReduceInteger2)(const Descriptor &array, + ReductionOperation<std::int16_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const std::int16_t *identity, + bool ordered) { + Terminator terminator{source, line}; + return GetTotalReduction<TypeCategory::Integer, 2>(array, source, line, dim, + mask, + ReduceAccumulator<std::int16_t>{array, operation, identity, terminator}, + "REDUCE"); +} +void RTDEF(ReduceInteger2Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::int16_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const std::int16_t *identity, + bool ordered) { + Terminator terminator{source, line}; + using Accumulator = ReduceAccumulator<std::int16_t>; + Accumulator accumulator{array, operation, identity, terminator}; + PartialReduction<Accumulator, TypeCategory::Integer, 2>(result, array, + array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator); +} +std::int32_t RTDEF(ReduceInteger4)(const Descriptor &array, + ReductionOperation<std::int32_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const std::int32_t *identity, + bool ordered) { + Terminator terminator{source, line}; + return GetTotalReduction<TypeCategory::Integer, 4>(array, source, line, dim, + mask, + ReduceAccumulator<std::int32_t>{array, operation, identity, terminator}, + "REDUCE"); +} +void RTDEF(ReduceInteger4Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::int32_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const std::int32_t *identity, + bool ordered) { + Terminator terminator{source, line}; + using Accumulator = ReduceAccumulator<std::int32_t>; + Accumulator accumulator{array, operation, identity, terminator}; + PartialReduction<Accumulator, TypeCategory::Integer, 4>(result, array, + array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator); +} +std::int64_t RTDEF(ReduceInteger8)(const Descriptor &array, + ReductionOperation<std::int64_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const std::int64_t *identity, + bool ordered) { + Terminator terminator{source, line}; + return GetTotalReduction<TypeCategory::Integer, 8>(array, source, line, dim, + mask, + ReduceAccumulator<std::int64_t>{array, operation, identity, terminator}, + "REDUCE"); +} +void RTDEF(ReduceInteger8Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::int64_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const std::int64_t *identity, + bool ordered) { + Terminator terminator{source, line}; + using Accumulator = ReduceAccumulator<std::int64_t>; + Accumulator accumulator{array, operation, identity, terminator}; + PartialReduction<Accumulator, TypeCategory::Integer, 8>(result, array, + array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator); +} +#ifdef __SIZEOF_INT128__ +common::int128_t RTDEF(ReduceInteger16)(const Descriptor &array, + ReductionOperation<common::int128_t> operation, const char *source, + int line, int dim, const Descriptor *mask, const common::int128_t *identity, + bool ordered) { + Terminator terminator{source, line}; + return GetTotalReduction<TypeCategory::Integer, 16>(array, source, line, dim, + mask, + ReduceAccumulator<common::int128_t>{ + array, operation, identity, terminator}, + "REDUCE"); +} +void RTDEF(ReduceInteger16Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<common::int128_t> operation, const char *source, + int line, int dim, const Descriptor *mask, const common::int128_t *identity, + bool ordered) { + Terminator terminator{source, line}; + using Accumulator = ReduceAccumulator<common::int128_t>; + Accumulator accumulator{array, operation, identity, terminator}; + PartialReduction<Accumulator, TypeCategory::Integer, 16>(result, array, + array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator); +} +#endif + +// TODO: real/complex(2 & 3) +float RTDEF(ReduceReal4)(const Descriptor &array, + ReductionOperation<float> operation, const char *source, int line, int dim, + const Descriptor *mask, const float *identity, bool ordered) { + Terminator terminator{source, line}; + return GetTotalReduction<TypeCategory::Real, 4>(array, source, line, dim, + mask, ReduceAccumulator<float>{array, operation, identity, terminator}, + "REDUCE"); +} +void RTDEF(ReduceReal4Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<float> operation, const char *source, int line, int dim, + const Descriptor *mask, const float *identity, bool ordered) { + Terminator terminator{source, line}; + using Accumulator = ReduceAccumulator<float>; + Accumulator accumulator{array, operation, identity, terminator}; + PartialReduction<Accumulator, TypeCategory::Real, 4>(result, array, + array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator); +} +double RTDEF(ReduceReal8)(const Descriptor &array, + ReductionOperation<double> operation, const char *source, int line, int dim, + const Descriptor *mask, const double *identity, bool ordered) { + Terminator terminator{source, line}; + return GetTotalReduction<TypeCategory::Real, 8>(array, source, line, dim, + mask, ReduceAccumulator<double>{array, operation, identity, terminator}, + "REDUCE"); +} +void RTDEF(ReduceReal8Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<double> operation, const char *source, int line, int dim, + const Descriptor *mask, const double *identity, bool ordered) { + Terminator terminator{source, line}; + using Accumulator = ReduceAccumulator<double>; + Accumulator accumulator{array, operation, identity, terminator}; + PartialReduction<Accumulator, TypeCategory::Real, 8>(result, array, + array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator); +} +#if LDBL_MANT_DIG == 64 +long double RTDEF(ReduceReal10)(const Descriptor &array, + ReductionOperation<long double> operation, const char *source, int line, + int dim, const Descriptor *mask, const long double *identity, + bool ordered) { + Terminator terminator{source, line}; + return GetTotalReduction<TypeCategory::Real, 10>(array, source, line, dim, + mask, + ReduceAccumulator<long double>{array, operation, identity, terminator}, + "REDUCE"); +} +void RTDEF(ReduceReal10Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<long double> operation, const char *source, int line, + int dim, const Descriptor *mask, const long double *identity, + bool ordered) { + Terminator terminator{source, line}; + using Accumulator = ReduceAccumulator<long double>; + Accumulator accumulator{array, operation, identity, terminator}; + PartialReduction<Accumulator, TypeCategory::Real, 10>(result, array, + array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator); +} +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +CppFloat128Type RTDEF(ReduceReal16)(const Descriptor &array, + ReductionOperation<CppFloat128Type> operation, const char *source, int line, + int dim, const Descriptor *mask, const CppFloat128Type *identity, + bool ordered) { + Terminator terminator{source, line}; + return GetTotalReduction<TypeCategory::Real, 16>(array, source, line, dim, + mask, + ReduceAccumulator<CppFloat128Type>{ + array, operation, identity, terminator}, + "REDUCE"); +} +void RTDEF(ReduceReal16Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<CppFloat128Type> operation, const char *source, int line, + int dim, const Descriptor *mask, const CppFloat128Type *identity, + bool ordered) { + Terminator terminator{source, line}; + using Accumulator = ReduceAccumulator<CppFloat128Type>; + Accumulator accumulator{array, operation, identity, terminator}; + PartialReduction<Accumulator, TypeCategory::Real, 16>(result, array, + array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator); +} +#endif + +void RTDEF(CppReduceComplex4)(std::complex<float> &result, + const Descriptor &array, ReductionOperation<std::complex<float>> operation, + const char *source, int line, int dim, const Descriptor *mask, + const std::complex<float> *identity, bool ordered) { + Terminator terminator{source, line}; + result = GetTotalReduction<TypeCategory::Complex, 4>(array, source, line, dim, + mask, + ReduceAccumulator<std::complex<float>>{ + array, operation, identity, terminator}, + "REDUCE"); +} +void RTDEF(CppReduceComplex4Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::complex<float>> operation, const char *source, + int line, int dim, const Descriptor *mask, + const std::complex<float> *identity, bool ordered) { + Terminator terminator{source, line}; + using Accumulator = ReduceAccumulator<std::complex<float>>; + Accumulator accumulator{array, operation, identity, terminator}; + PartialReduction<Accumulator, TypeCategory::Complex, 4>(result, array, + array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator); +} +void RTDEF(CppReduceComplex8)(std::complex<double> &result, + const Descriptor &array, ReductionOperation<std::complex<double>> operation, + const char *source, int line, int dim, const Descriptor *mask, + const std::complex<double> *identity, bool ordered) { + Terminator terminator{source, line}; + result = GetTotalReduction<TypeCategory::Complex, 8>(array, source, line, dim, + mask, + ReduceAccumulator<std::complex<double>>{ + array, operation, identity, terminator}, + "REDUCE"); +} +void RTDEF(CppReduceComplex8Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::complex<double>> operation, const char *source, + int line, int dim, const Descriptor *mask, + const std::complex<double> *identity, bool ordered) { + Terminator terminator{source, line}; + using Accumulator = ReduceAccumulator<std::complex<double>>; + Accumulator accumulator{array, operation, identity, terminator}; + PartialReduction<Accumulator, TypeCategory::Complex, 8>(result, array, + array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator); +} +#if LDBL_MANT_DIG == 64 +void RTDEF(CppReduceComplex10)(std::complex<long double> &result, + const Descriptor &array, + ReductionOperation<std::complex<long double>> operation, const char *source, + int line, int dim, const Descriptor *mask, + const std::complex<long double> *identity, bool ordered) { + Terminator terminator{source, line}; + result = GetTotalReduction<TypeCategory::Complex, 10>(array, source, line, + dim, mask, + ReduceAccumulator<std::complex<long double>>{ + array, operation, identity, terminator}, + "REDUCE"); +} +void RTDEF(CppReduceComplex10Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::complex<long double>> operation, const char *source, + int line, int dim, const Descriptor *mask, + const std::complex<long double> *identity, bool ordered) { + Terminator terminator{source, line}; + using Accumulator = ReduceAccumulator<std::complex<long double>>; + Accumulator accumulator{array, operation, identity, terminator}; + PartialReduction<Accumulator, TypeCategory::Complex, 10>(result, array, + array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator); +} +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +void RTDEF(CppReduceComplex16)(std::complex<CppFloat128Type> &result, + const Descriptor &array, + ReductionOperation<std::complex<CppFloat128Type>> operation, + const char *source, int line, int dim, const Descriptor *mask, + const std::complex<CppFloat128Type> *identity, bool ordered) { + Terminator terminator{source, line}; + result = GetTotalReduction<TypeCategory::Complex, 16>(array, source, line, + dim, mask, + ReduceAccumulator<std::complex<CppFloat128Type>>{ + array, operation, identity, terminator}, + "REDUCE"); +} +void RTDEF(CppReduceComplex16Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::complex<CppFloat128Type>> operation, + const char *source, int line, int dim, const Descriptor *mask, + const std::complex<CppFloat128Type> *identity, bool ordered) { + Terminator terminator{source, line}; + using Accumulator = ReduceAccumulator<std::complex<CppFloat128Type>>; + Accumulator accumulator{array, operation, identity, terminator}; + PartialReduction<Accumulator, TypeCategory::Complex, 16>(result, array, + array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator); +} +#endif + +bool RTDEF(ReduceLogical1)(const Descriptor &array, + ReductionOperation<std::int8_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const std::int8_t *identity, + bool ordered) { + return RTNAME(ReduceInteger1)( + array, operation, source, line, dim, mask, identity, ordered) != 0; +} +void RTDEF(ReduceLogical1Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::int8_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const std::int8_t *identity, + bool ordered) { + RTNAME(ReduceInteger1Dim) + (result, array, operation, source, line, dim, mask, identity, ordered); +} +bool RTDEF(ReduceLogical2)(const Descriptor &array, + ReductionOperation<std::int16_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const std::int16_t *identity, + bool ordered) { + return RTNAME(ReduceInteger2)( + array, operation, source, line, dim, mask, identity, ordered) != 0; +} +void RTDEF(ReduceLogical2Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::int16_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const std::int16_t *identity, + bool ordered) { + RTNAME(ReduceInteger2Dim) + (result, array, operation, source, line, dim, mask, identity, ordered); +} +bool RTDEF(ReduceLogical4)(const Descriptor &array, + ReductionOperation<std::int32_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const std::int32_t *identity, + bool ordered) { + return RTNAME(ReduceInteger4)( + array, operation, source, line, dim, mask, identity, ordered) != 0; +} +void RTDEF(ReduceLogical4Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::int32_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const std::int32_t *identity, + bool ordered) { + RTNAME(ReduceInteger4Dim) + (result, array, operation, source, line, dim, mask, identity, ordered); +} +bool RTDEF(ReduceLogical8)(const Descriptor &array, + ReductionOperation<std::int64_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const std::int64_t *identity, + bool ordered) { + return RTNAME(ReduceInteger8)( + array, operation, source, line, dim, mask, identity, ordered) != 0; +} +void RTDEF(ReduceLogical8Dim)(Descriptor &result, const Descriptor &array, + ReductionOperation<std::int64_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const std::int64_t *identity, + bool ordered) { + RTNAME(ReduceInteger8Dim) + (result, array, operation, source, line, dim, mask, identity, ordered); +} + +void RTDEF(ReduceChar1)(char *result, const Descriptor &array, + ReductionCharOperation<char> operation, const char *source, int line, + int dim, const Descriptor *mask, const char *identity, bool ordered) { + Terminator terminator{source, line}; + BufferedReduceAccumulator<char, ReductionCharOperation<char>, + /*hasLength=*/true> + accumulator{array, operation, identity, terminator}; + DoTotalReduction<char>(array, dim, mask, accumulator, "REDUCE", terminator); + accumulator.GetResult(result); +} +void RTDEF(ReduceCharacter1Dim)(Descriptor &result, const Descriptor &array, + ReductionCharOperation<char> operation, const char *source, int line, + int dim, const Descriptor *mask, const char *identity, bool ordered) { + Terminator terminator{source, line}; + using Accumulator = BufferedReduceAccumulator<char, + ReductionCharOperation<char>, /*hasLength=*/true>; + Accumulator accumulator{array, operation, identity, terminator}; + PartialReduction<Accumulator, TypeCategory::Character, 1>(result, array, + array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator); +} +void RTDEF(ReduceChar2)(char16_t *result, const Descriptor &array, + ReductionCharOperation<char16_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const char16_t *identity, bool ordered) { + Terminator terminator{source, line}; + BufferedReduceAccumulator<char16_t, ReductionCharOperation<char16_t>, + /*hasLength=*/true> + accumulator{array, operation, identity, terminator}; + DoTotalReduction<char16_t>( + array, dim, mask, accumulator, "REDUCE", terminator); + accumulator.GetResult(result); +} +void RTDEF(ReduceCharacter2Dim)(Descriptor &result, const Descriptor &array, + ReductionCharOperation<char16_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const char16_t *identity, bool ordered) { + Terminator terminator{source, line}; + using Accumulator = BufferedReduceAccumulator<char16_t, + ReductionCharOperation<char16_t>, /*hasLength=*/true>; + Accumulator accumulator{array, operation, identity, terminator}; + PartialReduction<Accumulator, TypeCategory::Character, 2>(result, array, + array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator); +} +void RTDEF(ReduceChar4)(char32_t *result, const Descriptor &array, + ReductionCharOperation<char32_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const char32_t *identity, bool ordered) { + Terminator terminator{source, line}; + BufferedReduceAccumulator<char32_t, ReductionCharOperation<char32_t>, + /*hasLength=*/true> + accumulator{array, operation, identity, terminator}; + DoTotalReduction<char32_t>( + array, dim, mask, accumulator, "REDUCE", terminator); + accumulator.GetResult(result); +} +void RTDEF(ReduceCharacter4Dim)(Descriptor &result, const Descriptor &array, + ReductionCharOperation<char32_t> operation, const char *source, int line, + int dim, const Descriptor *mask, const char32_t *identity, bool ordered) { + Terminator terminator{source, line}; + using Accumulator = BufferedReduceAccumulator<char32_t, + ReductionCharOperation<char32_t>, /*hasLength=*/true>; + Accumulator accumulator{array, operation, identity, terminator}; + PartialReduction<Accumulator, TypeCategory::Character, 4>(result, array, + array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator); +} + +void RTDEF(ReduceDerivedType)(char *result, const Descriptor &array, + ReductionDerivedTypeOperation operation, const char *source, int line, + int dim, const Descriptor *mask, const char *identity, bool ordered) { + Terminator terminator{source, line}; + BufferedReduceAccumulator<char, ReductionDerivedTypeOperation, + /*hasLength=*/false> + accumulator{array, operation, identity, terminator}; + DoTotalReduction<char>(array, dim, mask, accumulator, "REDUCE", terminator); + accumulator.GetResult(result); +} +void RTDEF(ReduceDerivedTypeDim)(Descriptor &result, const Descriptor &array, + ReductionDerivedTypeOperation operation, const char *source, int line, + int dim, const Descriptor *mask, const char *identity, bool ordered) { + Terminator terminator{source, line}; + using Accumulator = BufferedReduceAccumulator<char, + ReductionDerivedTypeOperation, /*hasLength=*/false>; + Accumulator accumulator{array, operation, identity, terminator}; + PartialReduction<Accumulator, TypeCategory::Derived, 0>(result, array, + array.ElementBytes(), dim, mask, terminator, "REDUCE", accumulator); +} + +RT_EXT_API_GROUP_END +} // extern "C" +} // namespace Fortran::runtime diff --git a/flang/runtime/reduction-templates.h b/flang/runtime/reduction-templates.h index 5b793deb2a123de519351ef09493c780a98fa13e..f8e6f6095509e6b215b33064a7d88c36adc59228 100644 --- a/flang/runtime/reduction-templates.h +++ b/flang/runtime/reduction-templates.h @@ -53,9 +53,9 @@ inline RT_API_ATTRS void DoTotalReduction(const Descriptor &x, int dim, x.GetLowerBounds(xAt); if (mask) { CheckConformability(x, *mask, terminator, intrinsic, "ARRAY", "MASK"); - SubscriptValue maskAt[maxRank]; - mask->GetLowerBounds(maskAt); if (mask->rank() > 0) { + SubscriptValue maskAt[maxRank]; + mask->GetLowerBounds(maskAt); for (auto elements{x.Elements()}; elements--; x.IncrementSubscripts(xAt), mask->IncrementSubscripts(maskAt)) { if (IsLogicalElementTrue(*mask, maskAt)) { @@ -65,7 +65,7 @@ inline RT_API_ATTRS void DoTotalReduction(const Descriptor &x, int dim, } } return; - } else if (!IsLogicalElementTrue(*mask, maskAt)) { + } else if (!IsLogicalScalarTrue(*mask)) { // scalar MASK=.FALSE.: return identity value return; } @@ -86,13 +86,22 @@ inline RT_API_ATTRS CppTypeFor<CAT, KIND> GetTotalReduction(const Descriptor &x, RUNTIME_CHECK(terminator, TypeCode(CAT, KIND) == x.type()); using CppType = CppTypeFor<CAT, KIND>; DoTotalReduction<CppType>(x, dim, mask, accumulator, intrinsic, terminator); - CppType result; + if constexpr (std::is_void_v<CppType>) { + // Result is returned from accumulator, as in REDUCE() for derived type #ifdef _MSC_VER // work around MSVC spurious error - accumulator.GetResult(&result); + accumulator.GetResult(); #else - accumulator.template GetResult(&result); + accumulator.template GetResult(); #endif - return result; + } else { + CppType result; +#ifdef _MSC_VER // work around MSVC spurious error + accumulator.GetResult(&result); +#else + accumulator.template GetResult(&result); +#endif + return result; + } } // For reductions on a dimension, e.g. SUM(array,DIM=2) where the shape @@ -164,35 +173,6 @@ inline RT_API_ATTRS void ReduceDimMaskToScalar(const Descriptor &x, #endif } -// Utility: establishes & allocates the result array for a partial -// reduction (i.e., one with DIM=). -static RT_API_ATTRS void CreatePartialReductionResult(Descriptor &result, - const Descriptor &x, std::size_t resultElementSize, int dim, - Terminator &terminator, const char *intrinsic, TypeCode typeCode) { - int xRank{x.rank()}; - if (dim < 1 || dim > xRank) { - terminator.Crash( - "%s: bad DIM=%d for ARRAY with rank %d", intrinsic, dim, xRank); - } - int zeroBasedDim{dim - 1}; - SubscriptValue resultExtent[maxRank]; - for (int j{0}; j < zeroBasedDim; ++j) { - resultExtent[j] = x.GetDimension(j).Extent(); - } - for (int j{zeroBasedDim + 1}; j < xRank; ++j) { - resultExtent[j - 1] = x.GetDimension(j).Extent(); - } - result.Establish(typeCode, resultElementSize, nullptr, xRank - 1, - resultExtent, CFI_attribute_allocatable); - for (int j{0}; j + 1 < xRank; ++j) { - result.GetDimension(j).SetBounds(1, resultExtent[j]); - } - if (int stat{result.Allocate()}) { - terminator.Crash( - "%s: could not allocate memory for result; STAT=%d", intrinsic, stat); - } -} - // Partial reductions with DIM= template <typename ACCUMULATOR, TypeCategory CAT, int KIND> @@ -208,7 +188,6 @@ inline RT_API_ATTRS void PartialReduction(Descriptor &result, using CppType = CppTypeFor<CAT, KIND>; if (mask) { CheckConformability(x, *mask, terminator, intrinsic, "ARRAY", "MASK"); - SubscriptValue maskAt[maxRank]; // contents unused if (mask->rank() > 0) { for (auto n{result.Elements()}; n-- > 0; result.IncrementSubscripts(at)) { accumulator.Reinitialize(); @@ -216,7 +195,7 @@ inline RT_API_ATTRS void PartialReduction(Descriptor &result, x, dim - 1, at, *mask, result.Element<CppType>(at), accumulator); } return; - } else if (!IsLogicalElementTrue(*mask, maskAt)) { + } else if (!IsLogicalScalarTrue(*mask)) { // scalar MASK=.FALSE. accumulator.Reinitialize(); for (auto n{result.Elements()}; n-- > 0; result.IncrementSubscripts(at)) { diff --git a/flang/runtime/stat.h b/flang/runtime/stat.h index 55cdac46eb3a5749da1b8023cf1c641d7636e3a5..4f46f52ecb29415ef1007bf7e93e5660acded48d 100644 --- a/flang/runtime/stat.h +++ b/flang/runtime/stat.h @@ -11,8 +11,8 @@ #ifndef FORTRAN_RUNTIME_STAT_H_ #define FORTRAN_RUNTIME_STAT_H_ +#include "flang/Common/api-attrs.h" #include "flang/ISO_Fortran_binding_wrapper.h" -#include "flang/Runtime/api-attrs.h" #include "flang/Runtime/magic-numbers.h" namespace Fortran::runtime { diff --git a/flang/runtime/terminator.h b/flang/runtime/terminator.h index 444c68d109eedf6def6ad6f6070ca587e799aa15..59a47ce93e7c9007cf78d4cc5780536e9b2458de 100644 --- a/flang/runtime/terminator.h +++ b/flang/runtime/terminator.h @@ -11,7 +11,7 @@ #ifndef FORTRAN_RUNTIME_TERMINATOR_H_ #define FORTRAN_RUNTIME_TERMINATOR_H_ -#include "flang/Runtime/api-attrs.h" +#include "flang/Common/api-attrs.h" #include <cstdarg> #include <cstdio> #include <cstdlib> @@ -67,7 +67,7 @@ public: template <typename... Args> RT_API_ATTRS void PrintCrashArgs(const char *message, Args... args) const { -#if RT_DEVICE_COMPILATION +#if defined(RT_DEVICE_COMPILATION) std::printf(message, args...); #else std::fprintf(stderr, message, args...); diff --git a/flang/runtime/tools.cpp b/flang/runtime/tools.cpp index e653323ed1de0379a590d9e49ce3ec74c3d3df86..73d6c2cf7e1d2b78e25d453f10e8fa15d5b31bb8 100644 --- a/flang/runtime/tools.cpp +++ b/flang/runtime/tools.cpp @@ -175,7 +175,7 @@ RT_API_ATTRS void ShallowCopy(const Descriptor &to, const Descriptor &from) { RT_API_ATTRS char *EnsureNullTerminated( char *str, std::size_t length, Terminator &terminator) { - if (std::memchr(str, '\0', length) == nullptr) { + if (runtime::memchr(str, '\0', length) == nullptr) { char *newCmd{(char *)AllocateMemoryOrCrash(terminator, length + 1)}; std::memcpy(newCmd, str, length); newCmd[length] = '\0'; @@ -238,5 +238,34 @@ template <int KIND> struct FitsInIntegerKind { } }; +// Utility: establishes & allocates the result array for a partial +// reduction (i.e., one with DIM=). +RT_API_ATTRS void CreatePartialReductionResult(Descriptor &result, + const Descriptor &x, std::size_t resultElementSize, int dim, + Terminator &terminator, const char *intrinsic, TypeCode typeCode) { + int xRank{x.rank()}; + if (dim < 1 || dim > xRank) { + terminator.Crash( + "%s: bad DIM=%d for ARRAY with rank %d", intrinsic, dim, xRank); + } + int zeroBasedDim{dim - 1}; + SubscriptValue resultExtent[maxRank]; + for (int j{0}; j < zeroBasedDim; ++j) { + resultExtent[j] = x.GetDimension(j).Extent(); + } + for (int j{zeroBasedDim + 1}; j < xRank; ++j) { + resultExtent[j - 1] = x.GetDimension(j).Extent(); + } + result.Establish(typeCode, resultElementSize, nullptr, xRank - 1, + resultExtent, CFI_attribute_allocatable); + for (int j{0}; j + 1 < xRank; ++j) { + result.GetDimension(j).SetBounds(1, resultExtent[j]); + } + if (int stat{result.Allocate()}) { + terminator.Crash( + "%s: could not allocate memory for result; STAT=%d", intrinsic, stat); + } +} + RT_OFFLOAD_API_GROUP_END } // namespace Fortran::runtime diff --git a/flang/runtime/tools.h b/flang/runtime/tools.h index c1f89cadca06e79d0ebf6051a6212a6f73f25adb..5d7d99c08179dd3d622a87ea1ff6534dcce418a7 100644 --- a/flang/runtime/tools.h +++ b/flang/runtime/tools.h @@ -12,6 +12,7 @@ #include "freestanding-tools.h" #include "stat.h" #include "terminator.h" +#include "flang/Common/optional.h" #include "flang/Runtime/cpp-type.h" #include "flang/Runtime/descriptor.h" #include "flang/Runtime/memory.h" @@ -20,6 +21,27 @@ #include <map> #include <type_traits> +/// \macro RT_PRETTY_FUNCTION +/// Gets a user-friendly looking function signature for the current scope +/// using the best available method on each platform. The exact format of the +/// resulting string is implementation specific and non-portable, so this should +/// only be used, for example, for logging or diagnostics. +/// Copy of LLVM_PRETTY_FUNCTION +#if defined(_MSC_VER) +#define RT_PRETTY_FUNCTION __FUNCSIG__ +#elif defined(__GNUC__) || defined(__clang__) +#define RT_PRETTY_FUNCTION __PRETTY_FUNCTION__ +#else +#define RT_PRETTY_FUNCTION __func__ +#endif + +#if defined(RT_DEVICE_COMPILATION) +// Use the pseudo lock and pseudo file unit implementations +// for the device. +#define RT_USE_PSEUDO_LOCK 1 +#define RT_USE_PSEUDO_FILE_UNIT 1 +#endif + namespace Fortran::runtime { class Terminator; @@ -40,7 +62,7 @@ RT_API_ATTRS int IdentifyValue( RT_API_ATTRS void ToFortranDefaultCharacter( char *to, std::size_t toLength, const char *from); -// Utility for dealing with elemental LOGICAL arguments +// Utilities for dealing with elemental LOGICAL arguments inline RT_API_ATTRS bool IsLogicalElementTrue( const Descriptor &logical, const SubscriptValue at[]) { // A LOGICAL value is false if and only if all of its bytes are zero. @@ -52,6 +74,16 @@ inline RT_API_ATTRS bool IsLogicalElementTrue( } return false; } +inline RT_API_ATTRS bool IsLogicalScalarTrue(const Descriptor &logical) { + // A LOGICAL value is false if and only if all of its bytes are zero. + const char *p{logical.OffsetElement<char>()}; + for (std::size_t j{logical.ElementBytes()}; j-- > 0; ++p) { + if (*p) { + return true; + } + } + return false; +} // Check array conformability; a scalar 'x' conforms. Crashes on error. RT_API_ATTRS void CheckConformability(const Descriptor &to, const Descriptor &x, @@ -95,7 +127,7 @@ static inline RT_API_ATTRS std::int64_t GetInt64( } } -static inline RT_API_ATTRS std::optional<std::int64_t> GetInt64Safe( +static inline RT_API_ATTRS Fortran::common::optional<std::int64_t> GetInt64Safe( const char *p, std::size_t bytes, Terminator &terminator) { switch (bytes) { case 1: @@ -113,7 +145,7 @@ static inline RT_API_ATTRS std::optional<std::int64_t> GetInt64Safe( if (static_cast<Int128>(result) == n) { return result; } - return std::nullopt; + return Fortran::common::nullopt; } default: terminator.Crash("GetInt64Safe: no case for %zd bytes", bytes); @@ -334,7 +366,8 @@ inline RT_API_ATTRS RESULT ApplyLogicalKind( } // Calculate result type of (X op Y) for *, //, DOT_PRODUCT, &c. -std::optional<std::pair<TypeCategory, int>> inline constexpr RT_API_ATTRS +Fortran::common::optional< + std::pair<TypeCategory, int>> inline constexpr RT_API_ATTRS GetResultType(TypeCategory xCat, int xKind, TypeCategory yCat, int yKind) { int maxKind{std::max(xKind, yKind)}; switch (xCat) { @@ -390,18 +423,18 @@ GetResultType(TypeCategory xCat, int xKind, TypeCategory yCat, int yKind) { if (yCat == TypeCategory::Character) { return std::make_pair(TypeCategory::Character, maxKind); } else { - return std::nullopt; + return Fortran::common::nullopt; } case TypeCategory::Logical: if (yCat == TypeCategory::Logical) { return std::make_pair(TypeCategory::Logical, maxKind); } else { - return std::nullopt; + return Fortran::common::nullopt; } default: break; } - return std::nullopt; + return Fortran::common::nullopt; } // Accumulate floating-point results in (at least) double precision @@ -428,7 +461,7 @@ template <> inline RT_API_ATTRS const char *FindCharacter( const char *data, char ch, std::size_t chars) { return reinterpret_cast<const char *>( - std::memchr(data, static_cast<int>(ch), chars)); + runtime::memchr(data, static_cast<int>(ch), chars)); } // Copy payload data from one allocated descriptor to another. @@ -488,5 +521,9 @@ RT_API_ATTRS void CopyAndPad( } } +RT_API_ATTRS void CreatePartialReductionResult(Descriptor &result, + const Descriptor &x, std::size_t resultElementSize, int dim, Terminator &, + const char *intrinsic, TypeCode); + } // namespace Fortran::runtime #endif // FORTRAN_RUNTIME_TOOLS_H_ diff --git a/flang/runtime/type-code.cpp b/flang/runtime/type-code.cpp index b9ef307835dfba3dbdcfa2bc25e4b7f71da2b677..cb1b944433aae59f93c34660d71da34dd8ee3358 100644 --- a/flang/runtime/type-code.cpp +++ b/flang/runtime/type-code.cpp @@ -112,7 +112,7 @@ RT_API_ATTRS TypeCode::TypeCode(TypeCategory f, int kind) { } } -RT_API_ATTRS std::optional<std::pair<TypeCategory, int>> +RT_API_ATTRS Fortran::common::optional<std::pair<TypeCategory, int>> TypeCode::GetCategoryAndKind() const { switch (raw_) { case CFI_type_signed_char: @@ -204,7 +204,7 @@ TypeCode::GetCategoryAndKind() const { case CFI_type_char32_t: return std::make_pair(TypeCategory::Character, 4); default: - return std::nullopt; + return Fortran::common::nullopt; } } diff --git a/flang/runtime/type-info.cpp b/flang/runtime/type-info.cpp index b30a2c832a13886afe0f560645747549ad857811..cb18c5669b5ffc92041667bb969bc9222849a36a 100644 --- a/flang/runtime/type-info.cpp +++ b/flang/runtime/type-info.cpp @@ -15,7 +15,7 @@ namespace Fortran::runtime::typeInfo { RT_OFFLOAD_API_GROUP_BEGIN -RT_API_ATTRS std::optional<TypeParameterValue> Value::GetValue( +RT_API_ATTRS Fortran::common::optional<TypeParameterValue> Value::GetValue( const Descriptor *descriptor) const { switch (genre_) { case Genre::Explicit: @@ -26,9 +26,9 @@ RT_API_ATTRS std::optional<TypeParameterValue> Value::GetValue( return addendum->LenParameterValue(value_); } } - return std::nullopt; + return Fortran::common::nullopt; default: - return std::nullopt; + return Fortran::common::nullopt; } } diff --git a/flang/runtime/type-info.h b/flang/runtime/type-info.h index bd8112d9d6d8c064b951bfeb05a3b76ff19a6e8b..c3f3595e32ef28ca0686a3d64bbb7c3eaf79a8b9 100644 --- a/flang/runtime/type-info.h +++ b/flang/runtime/type-info.h @@ -15,10 +15,10 @@ #include "terminator.h" #include "flang/Common/Fortran.h" #include "flang/Common/bit-population-count.h" +#include "flang/Common/optional.h" #include "flang/Runtime/descriptor.h" #include <cinttypes> #include <memory> -#include <optional> namespace Fortran::runtime::typeInfo { @@ -39,7 +39,7 @@ public: LenParameter = 3 }; RT_API_ATTRS Genre genre() const { return genre_; } - RT_API_ATTRS std::optional<TypeParameterValue> GetValue( + RT_API_ATTRS Fortran::common::optional<TypeParameterValue> GetValue( const Descriptor *) const; private: @@ -58,7 +58,7 @@ public: Automatic = 4 }; - const RT_API_ATTRS Descriptor &name() const { return name_.descriptor(); } + RT_API_ATTRS const Descriptor &name() const { return name_.descriptor(); } RT_API_ATTRS Genre genre() const { return genre_; } RT_API_ATTRS TypeCategory category() const { return static_cast<TypeCategory>(category_); @@ -66,17 +66,17 @@ public: RT_API_ATTRS int kind() const { return kind_; } RT_API_ATTRS int rank() const { return rank_; } RT_API_ATTRS std::uint64_t offset() const { return offset_; } - const RT_API_ATTRS Value &characterLen() const { return characterLen_; } - const RT_API_ATTRS DerivedType *derivedType() const { + RT_API_ATTRS const Value &characterLen() const { return characterLen_; } + RT_API_ATTRS const DerivedType *derivedType() const { return derivedType_.descriptor().OffsetElement<const DerivedType>(); } - const RT_API_ATTRS Value *lenValue() const { + RT_API_ATTRS const Value *lenValue() const { return lenValue_.descriptor().OffsetElement<const Value>(); } - const RT_API_ATTRS Value *bounds() const { + RT_API_ATTRS const Value *bounds() const { return bounds_.descriptor().OffsetElement<const Value>(); } - const RT_API_ATTRS char *initialization() const { return initialization_; } + RT_API_ATTRS const char *initialization() const { return initialization_; } RT_API_ATTRS std::size_t GetElementByteSize(const Descriptor &) const; RT_API_ATTRS std::size_t GetElements(const Descriptor &) const; @@ -205,27 +205,27 @@ class DerivedType { public: ~DerivedType(); // never defined - const RT_API_ATTRS Descriptor &binding() const { + RT_API_ATTRS const Descriptor &binding() const { return binding_.descriptor(); } - const RT_API_ATTRS Descriptor &name() const { return name_.descriptor(); } + RT_API_ATTRS const Descriptor &name() const { return name_.descriptor(); } RT_API_ATTRS std::uint64_t sizeInBytes() const { return sizeInBytes_; } - const RT_API_ATTRS Descriptor &uninstatiated() const { + RT_API_ATTRS const Descriptor &uninstatiated() const { return uninstantiated_.descriptor(); } - const RT_API_ATTRS Descriptor &kindParameter() const { + RT_API_ATTRS const Descriptor &kindParameter() const { return kindParameter_.descriptor(); } - const RT_API_ATTRS Descriptor &lenParameterKind() const { + RT_API_ATTRS const Descriptor &lenParameterKind() const { return lenParameterKind_.descriptor(); } - const RT_API_ATTRS Descriptor &component() const { + RT_API_ATTRS const Descriptor &component() const { return component_.descriptor(); } - const RT_API_ATTRS Descriptor &procPtr() const { + RT_API_ATTRS const Descriptor &procPtr() const { return procPtr_.descriptor(); } - const RT_API_ATTRS Descriptor &special() const { + RT_API_ATTRS const Descriptor &special() const { return special_.descriptor(); } RT_API_ATTRS bool hasParent() const { return hasParent_; } @@ -241,14 +241,14 @@ public: return lenParameterKind().Elements(); } - const RT_API_ATTRS DerivedType *GetParentType() const; + RT_API_ATTRS const DerivedType *GetParentType() const; // Finds a data component by name in this derived type or its ancestors. - const RT_API_ATTRS Component *FindDataComponent( + RT_API_ATTRS const Component *FindDataComponent( const char *name, std::size_t nameLen) const; // O(1) look-up of special procedure bindings - const RT_API_ATTRS SpecialBinding *FindSpecialBinding( + RT_API_ATTRS const SpecialBinding *FindSpecialBinding( SpecialBinding::Which which) const { auto bitIndex{static_cast<std::uint32_t>(which)}; auto bit{std::uint32_t{1} << bitIndex}; diff --git a/flang/runtime/unit-map.cpp b/flang/runtime/unit-map.cpp index 6ebda5c45f0870e4f81210a434abe340bf04a213..684a9b9e20b97aa833772a75fb71297373c6eeb7 100644 --- a/flang/runtime/unit-map.cpp +++ b/flang/runtime/unit-map.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "unit-map.h" +#include "flang/Common/optional.h" namespace Fortran::runtime::io { @@ -29,7 +30,7 @@ void UnitMap::Initialize() { ExternalFileUnit &UnitMap::NewUnit(const Terminator &terminator) { CriticalSection critical{lock_}; Initialize(); - std::optional<int> n{freeNewUnits_.PopValue()}; + Fortran::common::optional<int> n{freeNewUnits_.PopValue()}; if (!n) { n = emergencyNewUnit_++; } diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp index 09782d2f849278df74aa171f9a8ff63a30812b72..6c648d3bd834675e30bbcd12496cb0a5439557ed 100644 --- a/flang/runtime/unit.cpp +++ b/flang/runtime/unit.cpp @@ -5,299 +5,38 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// - +// +// Implementation of ExternalFileUnit common for both +// RT_USE_PSEUDO_FILE_UNIT=0 and RT_USE_PSEUDO_FILE_UNIT=1. +// +//===----------------------------------------------------------------------===// #include "unit.h" #include "io-error.h" #include "lock.h" #include "tools.h" -#include "unit-map.h" -#include "flang/Runtime/magic-numbers.h" -#include <cstdio> #include <limits> #include <utility> namespace Fortran::runtime::io { -// The per-unit data structures are created on demand so that Fortran I/O -// should work without a Fortran main program. -static Lock unitMapLock; -static Lock createOpenLock; -static UnitMap *unitMap{nullptr}; -static ExternalFileUnit *defaultInput{nullptr}; // unit 5 -static ExternalFileUnit *defaultOutput{nullptr}; // unit 6 -static ExternalFileUnit *errorOutput{nullptr}; // unit 0 extension - -void FlushOutputOnCrash(const Terminator &terminator) { - if (!defaultOutput && !errorOutput) { - return; - } - IoErrorHandler handler{terminator}; - handler.HasIoStat(); // prevent nested crash if flush has error - CriticalSection critical{unitMapLock}; - if (defaultOutput) { - defaultOutput->FlushOutput(handler); - } - if (errorOutput) { - errorOutput->FlushOutput(handler); - } -} - -ExternalFileUnit *ExternalFileUnit::LookUp(int unit) { - return GetUnitMap().LookUp(unit); -} - -ExternalFileUnit *ExternalFileUnit::LookUpOrCreate( - int unit, const Terminator &terminator, bool &wasExtant) { - return GetUnitMap().LookUpOrCreate(unit, terminator, wasExtant); -} - -ExternalFileUnit *ExternalFileUnit::LookUpOrCreateAnonymous(int unit, - Direction dir, std::optional<bool> isUnformatted, - const Terminator &terminator) { - // Make sure that the returned anonymous unit has been opened - // not just created in the unitMap. - CriticalSection critical{createOpenLock}; - bool exists{false}; - ExternalFileUnit *result{ - GetUnitMap().LookUpOrCreate(unit, terminator, exists)}; - if (result && !exists) { - IoErrorHandler handler{terminator}; - result->OpenAnonymousUnit( - dir == Direction::Input ? OpenStatus::Unknown : OpenStatus::Replace, - Action::ReadWrite, Position::Rewind, Convert::Unknown, handler); - result->isUnformatted = isUnformatted; - } - return result; -} - -ExternalFileUnit *ExternalFileUnit::LookUp( - const char *path, std::size_t pathLen) { - return GetUnitMap().LookUp(path, pathLen); -} - -ExternalFileUnit &ExternalFileUnit::CreateNew( - int unit, const Terminator &terminator) { - bool wasExtant{false}; - ExternalFileUnit *result{ - GetUnitMap().LookUpOrCreate(unit, terminator, wasExtant)}; - RUNTIME_CHECK(terminator, result && !wasExtant); - return *result; -} - -ExternalFileUnit *ExternalFileUnit::LookUpForClose(int unit) { - return GetUnitMap().LookUpForClose(unit); -} - -ExternalFileUnit &ExternalFileUnit::NewUnit( - const Terminator &terminator, bool forChildIo) { - ExternalFileUnit &unit{GetUnitMap().NewUnit(terminator)}; - unit.createdForInternalChildIo_ = forChildIo; - return unit; -} - -bool ExternalFileUnit::OpenUnit(std::optional<OpenStatus> status, - std::optional<Action> action, Position position, OwningPtr<char> &&newPath, - std::size_t newPathLength, Convert convert, IoErrorHandler &handler) { - if (convert == Convert::Unknown) { - convert = executionEnvironment.conversion; - } - swapEndianness_ = convert == Convert::Swap || - (convert == Convert::LittleEndian && !isHostLittleEndian) || - (convert == Convert::BigEndian && isHostLittleEndian); - bool impliedClose{false}; - if (IsConnected()) { - bool isSamePath{newPath.get() && path() && pathLength() == newPathLength && - std::memcmp(path(), newPath.get(), newPathLength) == 0}; - if (status && *status != OpenStatus::Old && isSamePath) { - handler.SignalError("OPEN statement for connected unit may not have " - "explicit STATUS= other than 'OLD'"); - return impliedClose; - } - if (!newPath.get() || isSamePath) { - // OPEN of existing unit, STATUS='OLD' or unspecified, not new FILE= - newPath.reset(); - return impliedClose; - } - // Otherwise, OPEN on open unit with new FILE= implies CLOSE - DoImpliedEndfile(handler); - FlushOutput(handler); - TruncateFrame(0, handler); - Close(CloseStatus::Keep, handler); - impliedClose = true; - } - if (newPath.get() && newPathLength > 0) { - if (const auto *already{ - GetUnitMap().LookUp(newPath.get(), newPathLength)}) { - handler.SignalError(IostatOpenAlreadyConnected, - "OPEN(UNIT=%d,FILE='%.*s'): file is already connected to unit %d", - unitNumber_, static_cast<int>(newPathLength), newPath.get(), - already->unitNumber_); - return impliedClose; - } - } - set_path(std::move(newPath), newPathLength); - Open(status.value_or(OpenStatus::Unknown), action, position, handler); - auto totalBytes{knownSize()}; - if (access == Access::Direct) { - if (!openRecl) { - handler.SignalError(IostatOpenBadRecl, - "OPEN(UNIT=%d,ACCESS='DIRECT'): record length is not known", - unitNumber()); - } else if (*openRecl <= 0) { - handler.SignalError(IostatOpenBadRecl, - "OPEN(UNIT=%d,ACCESS='DIRECT',RECL=%jd): record length is invalid", - unitNumber(), static_cast<std::intmax_t>(*openRecl)); - } else if (totalBytes && (*totalBytes % *openRecl != 0)) { - handler.SignalError(IostatOpenBadRecl, - "OPEN(UNIT=%d,ACCESS='DIRECT',RECL=%jd): record length is not an " - "even divisor of the file size %jd", - unitNumber(), static_cast<std::intmax_t>(*openRecl), - static_cast<std::intmax_t>(*totalBytes)); - } - recordLength = openRecl; - } - endfileRecordNumber.reset(); - currentRecordNumber = 1; - if (totalBytes && access == Access::Direct && openRecl.value_or(0) > 0) { - endfileRecordNumber = 1 + (*totalBytes / *openRecl); - } - if (position == Position::Append) { - if (totalBytes) { - frameOffsetInFile_ = *totalBytes; - } - if (access != Access::Stream) { - if (!endfileRecordNumber) { - // Fake it so that we can backspace relative from the end - endfileRecordNumber = std::numeric_limits<std::int64_t>::max() - 2; - } - currentRecordNumber = *endfileRecordNumber; - } - } - return impliedClose; -} - -void ExternalFileUnit::OpenAnonymousUnit(std::optional<OpenStatus> status, - std::optional<Action> action, Position position, Convert convert, - IoErrorHandler &handler) { - // I/O to an unconnected unit reads/creates a local file, e.g. fort.7 - std::size_t pathMaxLen{32}; - auto path{SizedNew<char>{handler}(pathMaxLen)}; - std::snprintf(path.get(), pathMaxLen, "fort.%d", unitNumber_); - OpenUnit(status, action, position, std::move(path), std::strlen(path.get()), - convert, handler); -} - -void ExternalFileUnit::CloseUnit(CloseStatus status, IoErrorHandler &handler) { - DoImpliedEndfile(handler); - FlushOutput(handler); - Close(status, handler); -} - -void ExternalFileUnit::DestroyClosed() { - GetUnitMap().DestroyClosed(*this); // destroys *this -} - -Iostat ExternalFileUnit::SetDirection(Direction direction) { - if (direction == Direction::Input) { - if (mayRead()) { - direction_ = Direction::Input; - return IostatOk; - } else { - return IostatReadFromWriteOnly; - } - } else { - if (mayWrite()) { - direction_ = Direction::Output; - return IostatOk; - } else { - return IostatWriteToReadOnly; - } - } -} - -UnitMap &ExternalFileUnit::CreateUnitMap() { - Terminator terminator{__FILE__, __LINE__}; - IoErrorHandler handler{terminator}; - UnitMap &newUnitMap{*New<UnitMap>{terminator}().release()}; - - bool wasExtant{false}; - ExternalFileUnit &out{*newUnitMap.LookUpOrCreate( - FORTRAN_DEFAULT_OUTPUT_UNIT, terminator, wasExtant)}; - RUNTIME_CHECK(terminator, !wasExtant); - out.Predefine(1); - handler.SignalError(out.SetDirection(Direction::Output)); - out.isUnformatted = false; - defaultOutput = &out; - - ExternalFileUnit &in{*newUnitMap.LookUpOrCreate( - FORTRAN_DEFAULT_INPUT_UNIT, terminator, wasExtant)}; - RUNTIME_CHECK(terminator, !wasExtant); - in.Predefine(0); - handler.SignalError(in.SetDirection(Direction::Input)); - in.isUnformatted = false; - defaultInput = ∈ - - ExternalFileUnit &error{ - *newUnitMap.LookUpOrCreate(FORTRAN_ERROR_UNIT, terminator, wasExtant)}; - RUNTIME_CHECK(terminator, !wasExtant); - error.Predefine(2); - handler.SignalError(error.SetDirection(Direction::Output)); - error.isUnformatted = false; - errorOutput = &error; +RT_OFFLOAD_VAR_GROUP_BEGIN +RT_VAR_ATTRS ExternalFileUnit *defaultInput{nullptr}; // unit 5 +RT_VAR_ATTRS ExternalFileUnit *defaultOutput{nullptr}; // unit 6 +RT_VAR_ATTRS ExternalFileUnit *errorOutput{nullptr}; // unit 0 extension +RT_OFFLOAD_VAR_GROUP_END - return newUnitMap; -} - -// A back-up atexit() handler for programs that don't terminate with a main -// program END or a STOP statement or other Fortran-initiated program shutdown, -// such as programs with a C main() that terminate normally. It flushes all -// external I/O units. It is registered once the first time that any external -// I/O is attempted. -static void CloseAllExternalUnits() { - IoErrorHandler handler{"Fortran program termination"}; - ExternalFileUnit::CloseAll(handler); -} +RT_OFFLOAD_API_GROUP_BEGIN -UnitMap &ExternalFileUnit::GetUnitMap() { - if (unitMap) { - return *unitMap; - } - { - CriticalSection critical{unitMapLock}; - if (unitMap) { - return *unitMap; - } - unitMap = &CreateUnitMap(); - } - std::atexit(CloseAllExternalUnits); - return *unitMap; -} - -void ExternalFileUnit::CloseAll(IoErrorHandler &handler) { - CriticalSection critical{unitMapLock}; - if (unitMap) { - unitMap->CloseAll(handler); - FreeMemoryAndNullify(unitMap); - } - defaultOutput = nullptr; - defaultInput = nullptr; - errorOutput = nullptr; -} - -void ExternalFileUnit::FlushAll(IoErrorHandler &handler) { - CriticalSection critical{unitMapLock}; - if (unitMap) { - unitMap->FlushAll(handler); - } -} - -static inline void SwapEndianness( +static inline RT_API_ATTRS void SwapEndianness( char *data, std::size_t bytes, std::size_t elementBytes) { if (elementBytes > 1) { auto half{elementBytes >> 1}; for (std::size_t j{0}; j + elementBytes <= bytes; j += elementBytes) { for (std::size_t k{0}; k < half; ++k) { + RT_DIAG_PUSH + RT_DIAG_DISABLE_CALL_HOST_FROM_DEVICE_WARN std::swap(data[j + k], data[j + elementBytes - 1 - k]); + RT_DIAG_POP } } } @@ -868,7 +607,8 @@ void ExternalFileUnit::BackspaceVariableUnformattedRecord( // There's no portable memrchr(), unfortunately, and strrchr() would // fail on a record with a NUL, so we have to do it the hard way. -static const char *FindLastNewline(const char *str, std::size_t length) { +static RT_API_ATTRS const char *FindLastNewline( + const char *str, std::size_t length) { for (const char *p{str + length}; p >= str; p--) { if (*p == '\n') { return p; @@ -997,39 +737,6 @@ void ExternalFileUnit::PopChildIo(ChildIo &child) { child_.reset(child.AcquirePrevious().release()); // deletes top child } -int ExternalFileUnit::GetAsynchronousId(IoErrorHandler &handler) { - if (!mayAsynchronous()) { - handler.SignalError(IostatBadAsynchronous); - return -1; - } else { - for (int j{0}; 64 * j < maxAsyncIds; ++j) { - if (auto least{asyncIdAvailable_[j].LeastElement()}) { - asyncIdAvailable_[j].reset(*least); - return 64 * j + static_cast<int>(*least); - } - } - handler.SignalError(IostatTooManyAsyncOps); - return -1; - } -} - -bool ExternalFileUnit::Wait(int id) { - if (static_cast<std::size_t>(id) >= maxAsyncIds || - asyncIdAvailable_[id / 64].test(id % 64)) { - return false; - } else { - if (id == 0) { // means "all IDs" - for (int j{0}; 64 * j < maxAsyncIds; ++j) { - asyncIdAvailable_[j].set(); - } - asyncIdAvailable_[0].reset(0); - } else { - asyncIdAvailable_[id / 64].set(id % 64); - } - return true; - } -} - std::int32_t ExternalFileUnit::ReadHeaderOrFooter(std::int64_t frameOffset) { std::int32_t word; char *wordPtr{reinterpret_cast<char *>(&word)}; @@ -1065,4 +772,5 @@ Iostat ChildIo::CheckFormattingAndDirection( } } +RT_OFFLOAD_API_GROUP_END } // namespace Fortran::runtime::io diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h index e3c8757645bb9e50d3b366278782568d8899eba8..a6ee5971a1652427ce09d7eb9fcd79fc29bda0be 100644 --- a/flang/runtime/unit.h +++ b/flang/runtime/unit.h @@ -21,61 +21,129 @@ #include "lock.h" #include "terminator.h" #include "flang/Common/constexpr-bitset.h" +#include "flang/Common/optional.h" #include "flang/Runtime/memory.h" #include <cstdlib> #include <cstring> -#include <optional> -#include <variant> +#include <flang/Common/variant.h> namespace Fortran::runtime::io { class UnitMap; class ChildIo; +class ExternalFileUnit; + +RT_OFFLOAD_VAR_GROUP_BEGIN +// Predefined file units. +extern RT_VAR_ATTRS ExternalFileUnit *defaultInput; // unit 5 +extern RT_VAR_ATTRS ExternalFileUnit *defaultOutput; // unit 6 +extern RT_VAR_ATTRS ExternalFileUnit *errorOutput; // unit 0 extension +RT_OFFLOAD_VAR_GROUP_END + +#if defined(RT_USE_PSEUDO_FILE_UNIT) +// A flavor of OpenFile class that pretends to be a terminal, +// and only provides basic buffering of the output +// in an internal buffer, and Write's the output +// using std::printf(). Since it does not rely on file system +// APIs, it can be used to implement external output +// for offload devices. +class PseudoOpenFile { +public: + using FileOffset = std::int64_t; + + RT_API_ATTRS const char *path() const { return nullptr; } + RT_API_ATTRS std::size_t pathLength() const { return 0; } + RT_API_ATTRS void set_path(OwningPtr<char> &&, std::size_t bytes) {} + RT_API_ATTRS bool mayRead() const { return false; } + RT_API_ATTRS bool mayWrite() const { return true; } + RT_API_ATTRS bool mayPosition() const { return false; } + RT_API_ATTRS bool mayAsynchronous() const { return false; } + RT_API_ATTRS void set_mayAsynchronous(bool yes); + // Pretend to be a terminal to force the output + // at the end of IO statement. + RT_API_ATTRS bool isTerminal() const { return true; } + RT_API_ATTRS bool isWindowsTextFile() const { return false; } + RT_API_ATTRS Fortran::common::optional<FileOffset> knownSize() const; + RT_API_ATTRS bool IsConnected() const { return false; } + RT_API_ATTRS void Open(OpenStatus, Fortran::common::optional<Action>, + Position, IoErrorHandler &); + RT_API_ATTRS void Predefine(int fd) {} + RT_API_ATTRS void Close(CloseStatus, IoErrorHandler &); + RT_API_ATTRS std::size_t Read(FileOffset, char *, std::size_t minBytes, + std::size_t maxBytes, IoErrorHandler &); + RT_API_ATTRS std::size_t Write( + FileOffset, const char *, std::size_t, IoErrorHandler &); + RT_API_ATTRS void Truncate(FileOffset, IoErrorHandler &); + RT_API_ATTRS int ReadAsynchronously( + FileOffset, char *, std::size_t, IoErrorHandler &); + RT_API_ATTRS int WriteAsynchronously( + FileOffset, const char *, std::size_t, IoErrorHandler &); + RT_API_ATTRS void Wait(int id, IoErrorHandler &); + RT_API_ATTRS void WaitAll(IoErrorHandler &); + RT_API_ATTRS Position InquirePosition() const; +}; +#endif // defined(RT_USE_PSEUDO_FILE_UNIT) + +#if !defined(RT_USE_PSEUDO_FILE_UNIT) +using OpenFileClass = OpenFile; +using FileFrameClass = FileFrame<ExternalFileUnit>; +#else // defined(RT_USE_PSEUDO_FILE_UNIT) +using OpenFileClass = PseudoOpenFile; +// Use not so big buffer for the pseudo file unit frame. +using FileFrameClass = FileFrame<ExternalFileUnit, 1024>; +#endif // defined(RT_USE_PSEUDO_FILE_UNIT) class ExternalFileUnit : public ConnectionState, - public OpenFile, - public FileFrame<ExternalFileUnit> { + public OpenFileClass, + public FileFrameClass { public: static constexpr int maxAsyncIds{64 * 16}; - explicit ExternalFileUnit(int unitNumber) : unitNumber_{unitNumber} { + explicit RT_API_ATTRS ExternalFileUnit(int unitNumber) + : unitNumber_{unitNumber} { isUTF8 = executionEnvironment.defaultUTF8; for (int j{0}; 64 * j < maxAsyncIds; ++j) { asyncIdAvailable_[j].set(); } asyncIdAvailable_[0].reset(0); } - ~ExternalFileUnit() {} + RT_API_ATTRS ~ExternalFileUnit() {} - int unitNumber() const { return unitNumber_; } - bool swapEndianness() const { return swapEndianness_; } - bool createdForInternalChildIo() const { return createdForInternalChildIo_; } + RT_API_ATTRS int unitNumber() const { return unitNumber_; } + RT_API_ATTRS bool swapEndianness() const { return swapEndianness_; } + RT_API_ATTRS bool createdForInternalChildIo() const { + return createdForInternalChildIo_; + } - static ExternalFileUnit *LookUp(int unit); - static ExternalFileUnit *LookUpOrCreate( + static RT_API_ATTRS ExternalFileUnit *LookUp(int unit); + static RT_API_ATTRS ExternalFileUnit *LookUpOrCreate( int unit, const Terminator &, bool &wasExtant); - static ExternalFileUnit *LookUpOrCreateAnonymous(int unit, Direction, - std::optional<bool> isUnformatted, const Terminator &); - static ExternalFileUnit *LookUp(const char *path, std::size_t pathLen); - static ExternalFileUnit &CreateNew(int unit, const Terminator &); - static ExternalFileUnit *LookUpForClose(int unit); - static ExternalFileUnit &NewUnit(const Terminator &, bool forChildIo); - static void CloseAll(IoErrorHandler &); - static void FlushAll(IoErrorHandler &); + static RT_API_ATTRS ExternalFileUnit *LookUpOrCreateAnonymous(int unit, + Direction, Fortran::common::optional<bool> isUnformatted, + const Terminator &); + static RT_API_ATTRS ExternalFileUnit *LookUp( + const char *path, std::size_t pathLen); + static RT_API_ATTRS ExternalFileUnit &CreateNew(int unit, const Terminator &); + static RT_API_ATTRS ExternalFileUnit *LookUpForClose(int unit); + static RT_API_ATTRS ExternalFileUnit &NewUnit( + const Terminator &, bool forChildIo); + static RT_API_ATTRS void CloseAll(IoErrorHandler &); + static RT_API_ATTRS void FlushAll(IoErrorHandler &); // Returns true if an existing unit was closed - bool OpenUnit(std::optional<OpenStatus>, std::optional<Action>, Position, - OwningPtr<char> &&path, std::size_t pathLength, Convert, - IoErrorHandler &); - void OpenAnonymousUnit(std::optional<OpenStatus>, std::optional<Action>, - Position, Convert, IoErrorHandler &); - void CloseUnit(CloseStatus, IoErrorHandler &); - void DestroyClosed(); + RT_API_ATTRS bool OpenUnit(Fortran::common::optional<OpenStatus>, + Fortran::common::optional<Action>, Position, OwningPtr<char> &&path, + std::size_t pathLength, Convert, IoErrorHandler &); + RT_API_ATTRS void OpenAnonymousUnit(Fortran::common::optional<OpenStatus>, + Fortran::common::optional<Action>, Position, Convert, IoErrorHandler &); + RT_API_ATTRS void CloseUnit(CloseStatus, IoErrorHandler &); + RT_API_ATTRS void DestroyClosed(); - Iostat SetDirection(Direction); + RT_API_ATTRS Iostat SetDirection(Direction); template <typename A, typename... X> - IoStatementState &BeginIoStatement(const Terminator &terminator, X &&...xs) { + RT_API_ATTRS IoStatementState &BeginIoStatement( + const Terminator &terminator, X &&...xs) { // Take lock_ and hold it until EndIoStatement(). #if USE_PTHREADS if (!lock_.TakeIfNoDeadlock()) { @@ -93,50 +161,54 @@ public: return *io_; } - bool Emit( + RT_API_ATTRS bool Emit( const char *, std::size_t, std::size_t elementBytes, IoErrorHandler &); - bool Receive(char *, std::size_t, std::size_t elementBytes, IoErrorHandler &); - std::size_t GetNextInputBytes(const char *&, IoErrorHandler &); - bool BeginReadingRecord(IoErrorHandler &); - void FinishReadingRecord(IoErrorHandler &); - bool AdvanceRecord(IoErrorHandler &); - void BackspaceRecord(IoErrorHandler &); - void FlushOutput(IoErrorHandler &); - void FlushIfTerminal(IoErrorHandler &); - void Endfile(IoErrorHandler &); - void Rewind(IoErrorHandler &); - void EndIoStatement(); - bool SetStreamPos(std::int64_t, IoErrorHandler &); // one-based, for POS= - bool SetDirectRec(std::int64_t, IoErrorHandler &); // one-based, for REC= - std::int64_t InquirePos() const { + RT_API_ATTRS bool Receive( + char *, std::size_t, std::size_t elementBytes, IoErrorHandler &); + RT_API_ATTRS std::size_t GetNextInputBytes(const char *&, IoErrorHandler &); + RT_API_ATTRS bool BeginReadingRecord(IoErrorHandler &); + RT_API_ATTRS void FinishReadingRecord(IoErrorHandler &); + RT_API_ATTRS bool AdvanceRecord(IoErrorHandler &); + RT_API_ATTRS void BackspaceRecord(IoErrorHandler &); + RT_API_ATTRS void FlushOutput(IoErrorHandler &); + RT_API_ATTRS void FlushIfTerminal(IoErrorHandler &); + RT_API_ATTRS void Endfile(IoErrorHandler &); + RT_API_ATTRS void Rewind(IoErrorHandler &); + RT_API_ATTRS void EndIoStatement(); + RT_API_ATTRS bool SetStreamPos( + std::int64_t, IoErrorHandler &); // one-based, for POS= + RT_API_ATTRS bool SetDirectRec( + std::int64_t, IoErrorHandler &); // one-based, for REC= + RT_API_ATTRS std::int64_t InquirePos() const { // 12.6.2.11 defines POS=1 as the beginning of file return frameOffsetInFile_ + recordOffsetInFrame_ + positionInRecord + 1; } - ChildIo *GetChildIo() { return child_.get(); } - ChildIo &PushChildIo(IoStatementState &); - void PopChildIo(ChildIo &); + RT_API_ATTRS ChildIo *GetChildIo() { return child_.get(); } + RT_API_ATTRS ChildIo &PushChildIo(IoStatementState &); + RT_API_ATTRS void PopChildIo(ChildIo &); - int GetAsynchronousId(IoErrorHandler &); - bool Wait(int); + RT_API_ATTRS int GetAsynchronousId(IoErrorHandler &); + RT_API_ATTRS bool Wait(int); private: - static UnitMap &CreateUnitMap(); - static UnitMap &GetUnitMap(); - const char *FrameNextInput(IoErrorHandler &, std::size_t); - void SetPosition(std::int64_t, IoErrorHandler &); // zero-based - void BeginSequentialVariableUnformattedInputRecord(IoErrorHandler &); - void BeginVariableFormattedInputRecord(IoErrorHandler &); - void BackspaceFixedRecord(IoErrorHandler &); - void BackspaceVariableUnformattedRecord(IoErrorHandler &); - void BackspaceVariableFormattedRecord(IoErrorHandler &); - bool SetVariableFormattedRecordLength(); - void DoImpliedEndfile(IoErrorHandler &); - void DoEndfile(IoErrorHandler &); - void CommitWrites(); - bool CheckDirectAccess(IoErrorHandler &); - void HitEndOnRead(IoErrorHandler &); - std::int32_t ReadHeaderOrFooter(std::int64_t frameOffset); + static RT_API_ATTRS UnitMap &CreateUnitMap(); + static RT_API_ATTRS UnitMap &GetUnitMap(); + RT_API_ATTRS const char *FrameNextInput(IoErrorHandler &, std::size_t); + RT_API_ATTRS void SetPosition(std::int64_t, IoErrorHandler &); // zero-based + RT_API_ATTRS void BeginSequentialVariableUnformattedInputRecord( + IoErrorHandler &); + RT_API_ATTRS void BeginVariableFormattedInputRecord(IoErrorHandler &); + RT_API_ATTRS void BackspaceFixedRecord(IoErrorHandler &); + RT_API_ATTRS void BackspaceVariableUnformattedRecord(IoErrorHandler &); + RT_API_ATTRS void BackspaceVariableFormattedRecord(IoErrorHandler &); + RT_API_ATTRS bool SetVariableFormattedRecordLength(); + RT_API_ATTRS void DoImpliedEndfile(IoErrorHandler &); + RT_API_ATTRS void DoEndfile(IoErrorHandler &); + RT_API_ATTRS void CommitWrites(); + RT_API_ATTRS bool CheckDirectAccess(IoErrorHandler &); + RT_API_ATTRS void HitEndOnRead(IoErrorHandler &); + RT_API_ATTRS std::int32_t ReadHeaderOrFooter(std::int64_t frameOffset); Lock lock_; @@ -169,7 +241,7 @@ private: u_; // Points to the active alternative (if any) in u_ for use as a Cookie - std::optional<IoStatementState> io_; + Fortran::common::optional<IoStatementState> io_; // A stack of child I/O pseudo-units for defined I/O that have this // unit number. @@ -181,23 +253,25 @@ private: // be a child I/O statement. class ChildIo { public: - ChildIo(IoStatementState &parent, OwningPtr<ChildIo> &&previous) + RT_API_ATTRS ChildIo(IoStatementState &parent, OwningPtr<ChildIo> &&previous) : parent_{parent}, previous_{std::move(previous)} {} - IoStatementState &parent() const { return parent_; } + RT_API_ATTRS IoStatementState &parent() const { return parent_; } - void EndIoStatement(); + RT_API_ATTRS void EndIoStatement(); template <typename A, typename... X> - IoStatementState &BeginIoStatement(X &&...xs) { + RT_API_ATTRS IoStatementState &BeginIoStatement(X &&...xs) { A &state{u_.emplace<A>(std::forward<X>(xs)...)}; io_.emplace(state); return *io_; } - OwningPtr<ChildIo> AcquirePrevious() { return std::move(previous_); } + RT_API_ATTRS OwningPtr<ChildIo> AcquirePrevious() { + return std::move(previous_); + } - Iostat CheckFormattingAndDirection(bool unformatted, Direction); + RT_API_ATTRS Iostat CheckFormattingAndDirection(bool unformatted, Direction); private: IoStatementState &parent_; @@ -211,7 +285,7 @@ private: ChildUnformattedIoStatementState<Direction::Input>, InquireUnitState, ErroneousIoStatementState, ExternalMiscIoStatementState> u_; - std::optional<IoStatementState> io_; + Fortran::common::optional<IoStatementState> io_; }; } // namespace Fortran::runtime::io diff --git a/flang/runtime/utf.cpp b/flang/runtime/utf.cpp index 8f59ddbb19663238ac7320bc7c5237be8f4aa5a8..9945dc6509ecbd6086f29c6186e03f6100e35402 100644 --- a/flang/runtime/utf.cpp +++ b/flang/runtime/utf.cpp @@ -11,7 +11,8 @@ namespace Fortran::runtime { // clang-format off -const std::uint8_t UTF8FirstByteTable[256]{ +RT_OFFLOAD_VAR_GROUP_BEGIN +const RT_CONST_VAR_ATTRS std::uint8_t UTF8FirstByteTable[256]{ /* 00 - 7F: 7 bit payload in single byte */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -37,10 +38,12 @@ const std::uint8_t UTF8FirstByteTable[256]{ /* FE: 32 bit payload */ 7, /* FF: invalid */ 0 }; +RT_OFFLOAD_VAR_GROUP_END // clang-format on +RT_OFFLOAD_API_GROUP_BEGIN // Non-minimal encodings are accepted. -std::optional<char32_t> DecodeUTF8(const char *p0) { +Fortran::common::optional<char32_t> DecodeUTF8(const char *p0) { const std::uint8_t *p{reinterpret_cast<const std::uint8_t *>(p0)}; std::size_t bytes{MeasureUTF8Bytes(*p0)}; if (bytes == 1) { @@ -50,7 +53,7 @@ std::optional<char32_t> DecodeUTF8(const char *p0) { for (std::size_t j{1}; j < bytes; ++j) { std::uint8_t next{p[j]}; if (next < 0x80 || next > 0xbf) { - return std::nullopt; + return Fortran::common::nullopt; } result = (result << 6) | (next & 0x3f); } @@ -58,7 +61,7 @@ std::optional<char32_t> DecodeUTF8(const char *p0) { return static_cast<char32_t>(result); } } - return std::nullopt; + return Fortran::common::nullopt; } std::size_t EncodeUTF8(char *p0, char32_t ucs) { @@ -107,5 +110,6 @@ std::size_t EncodeUTF8(char *p0, char32_t ucs) { return 7; } } +RT_OFFLOAD_API_GROUP_END } // namespace Fortran::runtime diff --git a/flang/runtime/utf.h b/flang/runtime/utf.h index 6d9943bb6b8a2f50af832c9a8df9c1e334feaf81..29670d54b3eb6f9bfe9f8ebb6142d22c3bc4c0a0 100644 --- a/flang/runtime/utf.h +++ b/flang/runtime/utf.h @@ -41,28 +41,30 @@ #ifndef FORTRAN_RUNTIME_UTF_H_ #define FORTRAN_RUNTIME_UTF_H_ +#include "flang/Common/optional.h" #include <cstddef> #include <cstdint> -#include <optional> namespace Fortran::runtime { // Derive the length of a UTF-8 character encoding from its first byte. // A zero result signifies an invalid encoding. -extern const std::uint8_t UTF8FirstByteTable[256]; -static inline std::size_t MeasureUTF8Bytes(char first) { +RT_OFFLOAD_VAR_GROUP_BEGIN +extern const RT_CONST_VAR_ATTRS std::uint8_t UTF8FirstByteTable[256]; +static constexpr std::size_t maxUTF8Bytes{7}; +RT_OFFLOAD_VAR_GROUP_END + +static inline RT_API_ATTRS std::size_t MeasureUTF8Bytes(char first) { return UTF8FirstByteTable[static_cast<std::uint8_t>(first)]; } -static constexpr std::size_t maxUTF8Bytes{7}; - // Ensure that all bytes are present in sequence in the input buffer // before calling; use MeasureUTF8Bytes(first byte) to count them. -std::optional<char32_t> DecodeUTF8(const char *); +RT_API_ATTRS Fortran::common::optional<char32_t> DecodeUTF8(const char *); // Ensure that at least maxUTF8Bytes remain in the output // buffer before calling. -std::size_t EncodeUTF8(char *, char32_t); +RT_API_ATTRS std::size_t EncodeUTF8(char *, char32_t); } // namespace Fortran::runtime #endif // FORTRAN_RUNTIME_UTF_H_ diff --git a/flang/test/Driver/bbc-mlir-pass-pipeline.f90 b/flang/test/Driver/bbc-mlir-pass-pipeline.f90 index 243a620a9fd003c0a5f642f27f928868e722183f..bd7facad1ce12fe6d00ca4f3db94894750981459 100644 --- a/flang/test/Driver/bbc-mlir-pass-pipeline.f90 +++ b/flang/test/Driver/bbc-mlir-pass-pipeline.f90 @@ -38,9 +38,12 @@ end program ! CHECK-NEXT: (S) 0 num-cse'd - Number of operations CSE'd ! CHECK-NEXT: (S) 0 num-dce'd - Number of operations DCE'd +! CHECK-NEXT: Pipeline Collection : ['func.func', 'omp.declare_reduction'] ! CHECK-NEXT: 'func.func' Pipeline ! CHECK-NEXT: PolymorphicOpConversion -! CHECK-NEXT: CFGConversion +! CHECK-NEXT: CFGConversionOnFunc +! CHECK-NEXT: 'omp.declare_reduction' Pipeline +! CHECK-NEXT: CFGConversionOnReduction ! CHECK-NEXT: SCFToControlFlow ! CHECK-NEXT: Canonicalizer diff --git a/flang/test/Driver/cuda-option.f90 b/flang/test/Driver/cuda-option.f90 new file mode 100644 index 0000000000000000000000000000000000000000..562f8683b0ff7d8b7e53064dce460c93ec81496c --- /dev/null +++ b/flang/test/Driver/cuda-option.f90 @@ -0,0 +1,15 @@ +! Test -fcuda option +! RUN: %flang_fc1 -cpp -x cuda -fdebug-unparse %s -o - | FileCheck %s +! RUN: not %flang_fc1 -cpp %s -o - 2>&1 | FileCheck %s --check-prefix=ERROR +program main +#if _CUDA + integer :: var = _CUDA +#endif + integer, device :: dvar +end program + +! CHECK-LABEL: PROGRAM main +! CHECK: INTEGER :: var = 1 +! CHECK: INTEGER, DEVICE :: dvar + +! ERROR: cuda-option.f90:8:19: error: expected end of statement diff --git a/flang/test/Driver/driver-help-hidden.f90 b/flang/test/Driver/driver-help-hidden.f90 index 44dbac44772b29932e67144b172c981c1b67adb6..bf3660d57cbb4fdbd5629a9a8fa814d8806ae5ec 100644 --- a/flang/test/Driver/driver-help-hidden.f90 +++ b/flang/test/Driver/driver-help-hidden.f90 @@ -52,8 +52,6 @@ ! CHECK-NEXT: Do not use HLFIR lowering (deprecated) ! CHECK-NEXT: -flang-experimental-hlfir ! CHECK-NEXT: Use HLFIR lowering (experimental) -! CHECK-NEXT: -flang-experimental-polymorphism -! CHECK-NEXT: Enable Fortran 2003 polymorphism (experimental) ! CHECK-NEXT: -flarge-sizes Use INTEGER(KIND=8) for the result type in size-related intrinsics ! CHECK-NEXT: -flogical-abbreviations Enable logical abbreviations ! CHECK-NEXT: -flto=auto Enable LTO in 'full' mode diff --git a/flang/test/Driver/flang-experimental-polymorphism-flag.f90 b/flang/test/Driver/flang-experimental-polymorphism-flag.f90 deleted file mode 100644 index 095c1cc929e67bf196ac47c917256f0ff8e797d2..0000000000000000000000000000000000000000 --- a/flang/test/Driver/flang-experimental-polymorphism-flag.f90 +++ /dev/null @@ -1,10 +0,0 @@ -! Test -flang-experimental-hlfir flag -! RUN: %flang_fc1 -flang-experimental-polymorphism -emit-fir -o - %s | FileCheck %s -! RUN: %flang_fc1 -emit-fir -o - %s 2>&1 | FileCheck %s --check-prefix NO-POLYMORPHISM - -! CHECK: func.func @_QPtest(%{{.*}}: !fir.class<none> {fir.bindc_name = "poly"}) -subroutine test(poly) - class(*) :: poly -end subroutine test - -! NO-POLYMORPHISM: func.func @_QPtest diff --git a/flang/test/Driver/frontend-forwarding.f90 b/flang/test/Driver/frontend-forwarding.f90 index 8e9c9b78c3c10a45cdbd1441cc77a251e69629c5..eac9773ce25c7707d6dc8933a3d7224c1208f5d8 100644 --- a/flang/test/Driver/frontend-forwarding.f90 +++ b/flang/test/Driver/frontend-forwarding.f90 @@ -17,7 +17,6 @@ ! RUN: -fomit-frame-pointer \ ! RUN: -fpass-plugin=Bye%pluginext \ ! RUN: -fversion-loops-for-stride \ -! RUN: -flang-experimental-polymorphism \ ! RUN: -flang-experimental-hlfir \ ! RUN: -flang-deprecated-no-hlfir \ ! RUN: -fno-ppc-native-vector-element-order \ @@ -49,7 +48,6 @@ ! CHECK: "-fconvert=little-endian" ! CHECK: "-fpass-plugin=Bye ! CHECK: "-fversion-loops-for-stride" -! CHECK: "-flang-experimental-polymorphism" ! CHECK: "-flang-experimental-hlfir" ! CHECK: "-flang-deprecated-no-hlfir" ! CHECK: "-fno-ppc-native-vector-element-order" diff --git a/flang/test/Driver/include-omp-header.f90 b/flang/test/Driver/include-omp-header.f90 index 4bf43bbc882bb4ff8ea4fed547d996a7eba7b62d..6ddc6f3da2a455b6152a9d34d4a82cb03fd17702 100644 --- a/flang/test/Driver/include-omp-header.f90 +++ b/flang/test/Driver/include-omp-header.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! Verify that the omp_lib.h header is found and included correctly. This header file should be available at a path: ! * relative to the driver, that's ! * known the driver. @@ -7,11 +9,11 @@ ! This should just work ! RUN: not rm omp_lib.h -! RUN: %flang -fsyntax-only -fopenmp %s 2>&1 +! RUN: %flang -cpp -fsyntax-only -fopenmp %s 2>&1 ! Create an empty omp_lib.h header that _does not_ define omp_default_mem_alloc - this should lead to semantic errors ! RUN: touch omp_lib.h -! RUN: not %flang -fsyntax-only -fopenmp %s 2>&1 | FileCheck %s +! RUN: not %flang -cpp -fsyntax-only -fopenmp %s 2>&1 | FileCheck %s ! RUN: rm omp_lib.h ! CHECK: error: Must have INTEGER type, but is REAL(4) diff --git a/flang/test/Driver/mlir-debug-pass-pipeline.f90 b/flang/test/Driver/mlir-debug-pass-pipeline.f90 index 45b1717d7187db2ec394ad6dfa21714d1a3a49a4..e714a66b85f336dc5e13ee5acbe4651a0132b415 100644 --- a/flang/test/Driver/mlir-debug-pass-pipeline.f90 +++ b/flang/test/Driver/mlir-debug-pass-pipeline.f90 @@ -58,10 +58,12 @@ end program ! ALL-NEXT: (S) 0 num-cse'd - Number of operations CSE'd ! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd -! ALL-NEXT: 'func.func' Pipeline -! ALL-NEXT: PolymorphicOpConversion -! ALL-NEXT: CFGConversion - +! ALL-NEXT: Pipeline Collection : ['func.func', 'omp.declare_reduction'] +! ALL-NEXT: 'func.func' Pipeline +! ALL-NEXT: PolymorphicOpConversion +! ALL-NEXT: CFGConversionOnFunc +! ALL-NEXT: 'omp.declare_reduction' Pipeline +! ALL-NEXT: CFGConversionOnReduction ! ALL-NEXT: SCFToControlFlow ! ALL-NEXT: Canonicalizer ! ALL-NEXT: SimplifyRegionLite @@ -72,9 +74,9 @@ end program ! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func'] ! ALL-NEXT: 'fir.global' Pipeline -! ALL-NEXT: AbstractResultOnGlobalOpt -! ALL-NEXT: 'func.func' Pipeline -! ALL-NEXT: AbstractResultOnFuncOpt +! ALL-NEXT: AbstractResultOnGlobalOpt +! ALL-NEXT: 'func.func' Pipeline +! ALL-NEXT: AbstractResultOnFuncOpt ! ALL-NEXT: CodeGenRewrite ! ALL-NEXT: (S) 0 num-dce'd - Number of operations eliminated diff --git a/flang/test/Driver/mlir-pass-pipeline.f90 b/flang/test/Driver/mlir-pass-pipeline.f90 index 3d8c42f123e2eb06cf6990b7cec5d3b23c5fcc69..cfa0de63cde5e819f8303a6319d03859680133a9 100644 --- a/flang/test/Driver/mlir-pass-pipeline.f90 +++ b/flang/test/Driver/mlir-pass-pipeline.f90 @@ -1,8 +1,8 @@ ! Test the MLIR pass pipeline -! RUN: %flang_fc1 -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline -o /dev/null %s 2>&1 | FileCheck --check-prefixes=ALL %s +! RUN: %flang_fc1 -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline -o /dev/null %s 2>&1 | FileCheck --check-prefixes=ALL,NOTO2 %s ! -O0 is the default: -! RUN: %flang_fc1 -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline %s -O0 -o /dev/null 2>&1 | FileCheck --check-prefixes=ALL %s +! RUN: %flang_fc1 -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline %s -O0 -o /dev/null 2>&1 | FileCheck --check-prefixes=ALL,NOTO2 %s ! RUN: %flang_fc1 -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline %s -O2 -o /dev/null 2>&1 | FileCheck --check-prefixes=ALL,O2 %s ! REQUIRES: asserts @@ -49,11 +49,15 @@ end program ! ALL-NEXT: (S) 0 num-cse'd - Number of operations CSE'd ! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd -! ALL-NEXT: 'func.func' Pipeline -! ALL-NEXT: PolymorphicOpConversion +! O2-NEXT: 'func.func' Pipeline +! O2-NEXT: PolymorphicOpConversion ! O2-NEXT: AddAliasTags -! O2-NEXT: 'func.func' Pipeline -! ALL-NEXT: CFGConversion +! ALL-NEXT: Pipeline Collection : ['func.func', 'omp.declare_reduction'] +! ALL-NEXT: 'func.func' Pipeline +! NOTO2-NEXT: PolymorphicOpConversion +! ALL-NEXT: CFGConversionOnFunc +! ALL-NEXT: 'omp.declare_reduction' Pipeline +! ALL-NEXT: CFGConversionOnReduction ! ALL-NEXT: SCFToControlFlow ! ALL-NEXT: Canonicalizer diff --git a/flang/test/Evaluate/fold-scale.f90 b/flang/test/Evaluate/fold-scale.f90 index a5c5f081668b163a0d1be8252ee3e9239789e3d8..6d767a9f4c9a3cb3b5f3260217173fe6b2224cfb 100644 --- a/flang/test/Evaluate/fold-scale.f90 +++ b/flang/test/Evaluate/fold-scale.f90 @@ -7,5 +7,6 @@ module m logical, parameter :: test_4 = sign(1.0, scale(0.0, 0)) == 1.0 logical, parameter :: test_5 = scale(1.0, -1) == 0.5 logical, parameter :: test_6 = scale(2.0, -1) == 1.0 + logical, parameter :: test_7 = scale(huge(0.d0), -1200) == 1.0440487148797638d-53 + logical, parameter :: test_8 = scale(tiny(0.d0), 1200) == 3.8312388521647221d053 end module - diff --git a/flang/test/Fir/array-value-copy-2.fir b/flang/test/Fir/array-value-copy-2.fir index 21b340af10c6b818ae82bb3b41a5ef7281aaf9f4..cb8d6ca2b05540ca49bd20c027f6b44a5570152e 100644 --- a/flang/test/Fir/array-value-copy-2.fir +++ b/flang/test/Fir/array-value-copy-2.fir @@ -1,5 +1,5 @@ -// RUN: fir-opt --array-value-copy --cfg-conversion %s | FileCheck %s -// RUN: fir-opt --array-value-copy="optimize-conflicts=true" --cfg-conversion %s | FileCheck %s +// RUN: fir-opt --array-value-copy --cfg-conversion-on-func-opt %s | FileCheck %s +// RUN: fir-opt --array-value-copy="optimize-conflicts=true" --cfg-conversion-on-func-opt %s | FileCheck %s // CHECK-LABEL: func @_QPslice1( // CHECK-NOT: fir.allocmem diff --git a/flang/test/Fir/basic-program.fir b/flang/test/Fir/basic-program.fir index d8a9e74c318ce186e76dbf68e2cca19fc21d5973..80d3520bc7f7d401bb3657bed82a4ec38848a3e0 100644 --- a/flang/test/Fir/basic-program.fir +++ b/flang/test/Fir/basic-program.fir @@ -60,8 +60,11 @@ func.func @_QQmain() { // PASSES-NEXT: AddAliasTags +// PASSES-NEXT: Pipeline Collection : ['func.func', 'omp.declare_reduction'] // PASSES-NEXT: 'func.func' Pipeline -// PASSES-NEXT: CFGConversion +// PASSES-NEXT: CFGConversionOnFunc +// PASSES-NEXT: 'omp.declare_reduction' Pipeline +// PASSES-NEXT: CFGConversionOnReduction // PASSES-NEXT: SCFToControlFlow // PASSES-NEXT: Canonicalizer diff --git a/flang/test/Fir/boxproc-2.fir b/flang/test/Fir/boxproc-2.fir index 3279bb9bed8a4c44e964f76f15b0d2f770c97443..84132f89afebb2c755310b532b4e54385ceef921 100644 --- a/flang/test/Fir/boxproc-2.fir +++ b/flang/test/Fir/boxproc-2.fir @@ -108,3 +108,10 @@ func.func @very_nested_type(%arg0: !fir.type<t0{t01:!fir.type<t01{t02:!fir.type< } // CHECK-LABEL: func.func @very_nested_type( // CHECK-SAME: !fir.type<t0UnboxProc{t01:!fir.type<t01UnboxProc{t02:!fir.type<t02UnboxProc{t3:!fir.type<t3UnboxProc{t4:!fir.type<t4UnboxProc{t5:!fir.type<t5UnboxProc{t6:!fir.type<t6UnboxProc{t7:!fir.type<t7UnboxProc{t8:!fir.type<t8UnboxProc{t9:!fir.type<t9UnboxProc{t10:!fir.type<t10UnboxProc{t11:!fir.type<t11UnboxProc{t12:!fir.type<t12UnboxProc{t13:!fir.type<t13UnboxProc{t14:!fir.type<t14UnboxProc{t15:!fir.type<t15UnboxProc{t16:!fir.type<t16UnboxProc{t17:!fir.type<t17UnboxProc{t18:!fir.type<t18UnboxProc{t19:!fir.type<t19UnboxProc{b:() -> ()}>}>}>}>}>}>}>}>}>}>}>}>}>}>}>}>}>}>}>}>) + +func.func @test_indirect_type_recursion() { + %0 = fir.zero_bits !fir.ptr<!fir.type<t001{x:!fir.ptr<!fir.type<t002{x:!fir.ptr<!fir.type<t001>>}>>,p:!fir.boxproc<() -> ()>}>> + return +} +// CHECK-LABEL: func.func @test_indirect_type_recursion( +// CHECK: fir.zero_bits !fir.ptr<!fir.type<t001UnboxProc{x:!fir.ptr<!fir.type<t002UnboxProc{x:!fir.ptr<!fir.type<t001UnboxProc>>}>>,p:() -> ()}>> diff --git a/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir b/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir index a1fc614334dbce90be110264333e208fb496d790..92628af37085a5d3957926859e6e6444a217872d 100644 --- a/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir +++ b/flang/test/Fir/convert-to-llvm-openmp-and-fir.fir @@ -1,4 +1,4 @@ -// RUN: fir-opt --split-input-file --cfg-conversion --fir-to-llvm-ir="target=aarch64-unknown-linux-gnu" %s | FileCheck %s +// RUN: fir-opt --split-input-file --cfg-conversion-on-func-opt --fir-to-llvm-ir="target=aarch64-unknown-linux-gnu" %s | FileCheck %s func.func @_QPsb1(%arg0: !fir.ref<i32> {fir.bindc_name = "n"}, %arg1: !fir.ref<!fir.array<?xi32>> {fir.bindc_name = "arr"}) { %c1_i64 = arith.constant 1 : i64 @@ -231,39 +231,39 @@ func.func @_QPomp_target_data() { %c1 = arith.constant 1 : index %c0 = arith.constant 0 : index %4 = arith.subi %c1024, %c1 : index - %5 = omp.bounds lower_bound(%c0 : index) upper_bound(%4 : index) extent(%c1024 : index) stride(%c1 : index) start_idx(%c1 : index) - %6 = omp.map_info var_ptr(%0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(to) capture(ByRef) bounds(%5) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + %5 = omp.map.bounds lower_bound(%c0 : index) upper_bound(%4 : index) extent(%c1024 : index) stride(%c1 : index) start_idx(%c1 : index) + %6 = omp.map.info var_ptr(%0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(to) capture(ByRef) bounds(%5) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} %c1_3 = arith.constant 1 : index %c0_4 = arith.constant 0 : index %7 = arith.subi %c1024_0, %c1_3 : index - %8 = omp.bounds lower_bound(%c0_4 : index) upper_bound(%7 : index) extent(%c1024_0 : index) stride(%c1_3 : index) start_idx(%c1_3 : index) - %9 = omp.map_info var_ptr(%1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(to) capture(ByRef) bounds(%8) -> !fir.ref<!fir.array<1024xi32>> {name = "b"} + %8 = omp.map.bounds lower_bound(%c0_4 : index) upper_bound(%7 : index) extent(%c1024_0 : index) stride(%c1_3 : index) start_idx(%c1_3 : index) + %9 = omp.map.info var_ptr(%1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(to) capture(ByRef) bounds(%8) -> !fir.ref<!fir.array<1024xi32>> {name = "b"} %c1_5 = arith.constant 1 : index %c0_6 = arith.constant 0 : index %10 = arith.subi %c1024_1, %c1_5 : index - %11 = omp.bounds lower_bound(%c0_6 : index) upper_bound(%10 : index) extent(%c1024_1 : index) stride(%c1_5 : index) start_idx(%c1_5 : index) - %12 = omp.map_info var_ptr(%2 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(always, exit_release_or_enter_alloc) capture(ByRef) bounds(%11) -> !fir.ref<!fir.array<1024xi32>> {name = "c"} + %11 = omp.map.bounds lower_bound(%c0_6 : index) upper_bound(%10 : index) extent(%c1024_1 : index) stride(%c1_5 : index) start_idx(%c1_5 : index) + %12 = omp.map.info var_ptr(%2 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(always, exit_release_or_enter_alloc) capture(ByRef) bounds(%11) -> !fir.ref<!fir.array<1024xi32>> {name = "c"} omp.target_enter_data map_entries(%6, %9, %12 : !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>) %c1_7 = arith.constant 1 : index %c0_8 = arith.constant 0 : index %13 = arith.subi %c1024, %c1_7 : index - %14 = omp.bounds lower_bound(%c0_8 : index) upper_bound(%13 : index) extent(%c1024 : index) stride(%c1_7 : index) start_idx(%c1_7 : index) - %15 = omp.map_info var_ptr(%0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(from) capture(ByRef) bounds(%14) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + %14 = omp.map.bounds lower_bound(%c0_8 : index) upper_bound(%13 : index) extent(%c1024 : index) stride(%c1_7 : index) start_idx(%c1_7 : index) + %15 = omp.map.info var_ptr(%0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(from) capture(ByRef) bounds(%14) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} %c1_9 = arith.constant 1 : index %c0_10 = arith.constant 0 : index %16 = arith.subi %c1024_0, %c1_9 : index - %17 = omp.bounds lower_bound(%c0_10 : index) upper_bound(%16 : index) extent(%c1024_0 : index) stride(%c1_9 : index) start_idx(%c1_9 : index) - %18 = omp.map_info var_ptr(%1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(from) capture(ByRef) bounds(%17) -> !fir.ref<!fir.array<1024xi32>> {name = "b"} + %17 = omp.map.bounds lower_bound(%c0_10 : index) upper_bound(%16 : index) extent(%c1024_0 : index) stride(%c1_9 : index) start_idx(%c1_9 : index) + %18 = omp.map.info var_ptr(%1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(from) capture(ByRef) bounds(%17) -> !fir.ref<!fir.array<1024xi32>> {name = "b"} %c1_11 = arith.constant 1 : index %c0_12 = arith.constant 0 : index %19 = arith.subi %c1024_1, %c1_11 : index - %20 = omp.bounds lower_bound(%c0_12 : index) upper_bound(%19 : index) extent(%c1024_1 : index) stride(%c1_11 : index) start_idx(%c1_11 : index) - %21 = omp.map_info var_ptr(%2 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%20) -> !fir.ref<!fir.array<1024xi32>> {name = "c"} + %20 = omp.map.bounds lower_bound(%c0_12 : index) upper_bound(%19 : index) extent(%c1024_1 : index) stride(%c1_11 : index) start_idx(%c1_11 : index) + %21 = omp.map.info var_ptr(%2 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%20) -> !fir.ref<!fir.array<1024xi32>> {name = "c"} %c1_13 = arith.constant 1 : index %c0_14 = arith.constant 0 : index %22 = arith.subi %c1024_2, %c1_13 : index - %23 = omp.bounds lower_bound(%c0_14 : index) upper_bound(%22 : index) extent(%c1024_2 : index) stride(%c1_13 : index) start_idx(%c1_13 : index) - %24 = omp.map_info var_ptr(%3 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(always, delete) capture(ByRef) bounds(%23) -> !fir.ref<!fir.array<1024xi32>> {name = "d"} + %23 = omp.map.bounds lower_bound(%c0_14 : index) upper_bound(%22 : index) extent(%c1024_2 : index) stride(%c1_13 : index) start_idx(%c1_13 : index) + %24 = omp.map.info var_ptr(%3 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(always, delete) capture(ByRef) bounds(%23) -> !fir.ref<!fir.array<1024xi32>> {name = "d"} omp.target_exit_data map_entries(%15, %18, %21, %24 : !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>) return } @@ -284,39 +284,39 @@ func.func @_QPomp_target_data() { // CHECK: %12 = llvm.mlir.constant(1 : index) : i64 // CHECK: %13 = llvm.mlir.constant(0 : index) : i64 // CHECK: %14 = llvm.mlir.constant(1023 : index) : i64 - // CHECK: %15 = omp.bounds lower_bound(%13 : i64) upper_bound(%14 : i64) extent(%0 : i64) stride(%12 : i64) start_idx(%12 : i64) - // CHECK: %16 = omp.map_info var_ptr(%[[VAL_1]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(to) capture(ByRef) bounds(%15) -> !llvm.ptr {name = "a"} + // CHECK: %15 = omp.map.bounds lower_bound(%13 : i64) upper_bound(%14 : i64) extent(%0 : i64) stride(%12 : i64) start_idx(%12 : i64) + // CHECK: %16 = omp.map.info var_ptr(%[[VAL_1]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(to) capture(ByRef) bounds(%15) -> !llvm.ptr {name = "a"} // CHECK: %17 = llvm.mlir.constant(1 : index) : i64 // CHECK: %18 = llvm.mlir.constant(0 : index) : i64 // CHECK: %19 = llvm.mlir.constant(1023 : index) : i64 - // CHECK: %20 = omp.bounds lower_bound(%18 : i64) upper_bound(%19 : i64) extent(%3 : i64) stride(%17 : i64) start_idx(%17 : i64) - // CHECK: %21 = omp.map_info var_ptr(%[[VAL_3]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(to) capture(ByRef) bounds(%20) -> !llvm.ptr {name = "b"} + // CHECK: %20 = omp.map.bounds lower_bound(%18 : i64) upper_bound(%19 : i64) extent(%3 : i64) stride(%17 : i64) start_idx(%17 : i64) + // CHECK: %21 = omp.map.info var_ptr(%[[VAL_3]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(to) capture(ByRef) bounds(%20) -> !llvm.ptr {name = "b"} // CHECK: %22 = llvm.mlir.constant(1 : index) : i64 // CHECK: %23 = llvm.mlir.constant(0 : index) : i64 // CHECK: %24 = llvm.mlir.constant(1023 : index) : i64 - // CHECK: %25 = omp.bounds lower_bound(%23 : i64) upper_bound(%24 : i64) extent(%6 : i64) stride(%22 : i64) start_idx(%22 : i64) - // CHECK: %26 = omp.map_info var_ptr(%[[VAL_5]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(always, exit_release_or_enter_alloc) capture(ByRef) bounds(%25) -> !llvm.ptr {name = "c"} + // CHECK: %25 = omp.map.bounds lower_bound(%23 : i64) upper_bound(%24 : i64) extent(%6 : i64) stride(%22 : i64) start_idx(%22 : i64) + // CHECK: %26 = omp.map.info var_ptr(%[[VAL_5]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(always, exit_release_or_enter_alloc) capture(ByRef) bounds(%25) -> !llvm.ptr {name = "c"} // CHECK: omp.target_enter_data map_entries(%16, %21, %26 : !llvm.ptr, !llvm.ptr, !llvm.ptr) // CHECK: %27 = llvm.mlir.constant(1 : index) : i64 // CHECK: %28 = llvm.mlir.constant(0 : index) : i64 // CHECK: %29 = llvm.mlir.constant(1023 : index) : i64 - // CHECK: %30 = omp.bounds lower_bound(%28 : i64) upper_bound(%29 : i64) extent(%0 : i64) stride(%27 : i64) start_idx(%27 : i64) - // CHECK: %31 = omp.map_info var_ptr(%[[VAL_1]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(from) capture(ByRef) bounds(%30) -> !llvm.ptr {name = "a"} + // CHECK: %30 = omp.map.bounds lower_bound(%28 : i64) upper_bound(%29 : i64) extent(%0 : i64) stride(%27 : i64) start_idx(%27 : i64) + // CHECK: %31 = omp.map.info var_ptr(%[[VAL_1]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(from) capture(ByRef) bounds(%30) -> !llvm.ptr {name = "a"} // CHECK: %32 = llvm.mlir.constant(1 : index) : i64 // CHECK: %33 = llvm.mlir.constant(0 : index) : i64 // CHECK: %34 = llvm.mlir.constant(1023 : index) : i64 - // CHECK: %35 = omp.bounds lower_bound(%33 : i64) upper_bound(%34 : i64) extent(%3 : i64) stride(%32 : i64) start_idx(%32 : i64) - // CHECK: %36 = omp.map_info var_ptr(%[[VAL_3]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(from) capture(ByRef) bounds(%35) -> !llvm.ptr {name = "b"} + // CHECK: %35 = omp.map.bounds lower_bound(%33 : i64) upper_bound(%34 : i64) extent(%3 : i64) stride(%32 : i64) start_idx(%32 : i64) + // CHECK: %36 = omp.map.info var_ptr(%[[VAL_3]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(from) capture(ByRef) bounds(%35) -> !llvm.ptr {name = "b"} // CHECK: %37 = llvm.mlir.constant(1 : index) : i64 // CHECK: %38 = llvm.mlir.constant(0 : index) : i64 // CHECK: %39 = llvm.mlir.constant(1023 : index) : i64 - // CHECK: %40 = omp.bounds lower_bound(%38 : i64) upper_bound(%39 : i64) extent(%6 : i64) stride(%37 : i64) start_idx(%37 : i64) - // CHECK: %41 = omp.map_info var_ptr(%[[VAL_5]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%40) -> !llvm.ptr {name = "c"} + // CHECK: %40 = omp.map.bounds lower_bound(%38 : i64) upper_bound(%39 : i64) extent(%6 : i64) stride(%37 : i64) start_idx(%37 : i64) + // CHECK: %41 = omp.map.info var_ptr(%[[VAL_5]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%40) -> !llvm.ptr {name = "c"} // CHECK: %42 = llvm.mlir.constant(1 : index) : i64 // CHECK: %43 = llvm.mlir.constant(0 : index) : i64 // CHECK: %44 = llvm.mlir.constant(1023 : index) : i64 - // CHECK: %45 = omp.bounds lower_bound(%43 : i64) upper_bound(%44 : i64) extent(%9 : i64) stride(%42 : i64) start_idx(%42 : i64) - // CHECK: %46 = omp.map_info var_ptr(%[[VAL_7]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(always, delete) capture(ByRef) bounds(%45) -> !llvm.ptr {name = "d"} + // CHECK: %45 = omp.map.bounds lower_bound(%43 : i64) upper_bound(%44 : i64) extent(%9 : i64) stride(%42 : i64) start_idx(%42 : i64) + // CHECK: %46 = omp.map.info var_ptr(%[[VAL_7]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(always, delete) capture(ByRef) bounds(%45) -> !llvm.ptr {name = "d"} // CHECK: omp.target_exit_data map_entries(%31, %36, %41, %46 : !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) // CHECK: llvm.return // CHECK: } @@ -330,8 +330,8 @@ func.func @_QPopenmp_target_data_region() { %c3 = arith.constant 1 : index %c0 = arith.constant 0 : index %c2 = arith.subi %c1024, %c3 : index - %bound = omp.bounds lower_bound(%c0 : index) upper_bound(%c2 : index) extent(%c1024 : index) stride(%c3 : index) start_idx(%c3 : index) - %entry = omp.map_info var_ptr(%0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%bound) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + %bound = omp.map.bounds lower_bound(%c0 : index) upper_bound(%c2 : index) extent(%c1024 : index) stride(%c3 : index) start_idx(%c3 : index) + %entry = omp.map.info var_ptr(%0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%bound) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} omp.target_data map_entries(%entry : !fir.ref<!fir.array<1024xi32>>) { %c1_i32 = arith.constant 1 : i32 %2 = fir.convert %c1_i32 : (i32) -> index @@ -369,8 +369,8 @@ func.func @_QPopenmp_target_data_region() { // CHECK: %[[VAL_ONE:.*]] = llvm.mlir.constant(1 : index) : i64 // CHECK: %[[VAL_ZERO:.*]] = llvm.mlir.constant(0 : index) : i64 // CHECK: %[[VAL_UPPER:.*]] = llvm.mlir.constant(1023 : index) : i64 -// CHECK: %[[VAL_BOUNDS:.*]] = omp.bounds lower_bound(%[[VAL_ZERO]] : i64) upper_bound(%[[VAL_UPPER]] : i64) extent(%[[VAL_MAX]] : i64) stride(%[[VAL_ONE]] : i64) start_idx(%[[VAL_ONE]] : i64) -// CHECK: %[[VAL_MAP:.*]] = omp.map_info var_ptr(%[[VAL_1]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%[[VAL_BOUNDS]]) -> !llvm.ptr {name = "a"} +// CHECK: %[[VAL_BOUNDS:.*]] = omp.map.bounds lower_bound(%[[VAL_ZERO]] : i64) upper_bound(%[[VAL_UPPER]] : i64) extent(%[[VAL_MAX]] : i64) stride(%[[VAL_ONE]] : i64) start_idx(%[[VAL_ONE]] : i64) +// CHECK: %[[VAL_MAP:.*]] = omp.map.info var_ptr(%[[VAL_1]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%[[VAL_BOUNDS]]) -> !llvm.ptr {name = "a"} // CHECK: omp.target_data map_entries(%[[VAL_MAP]] : !llvm.ptr) { // CHECK: %[[VAL_4:.*]] = llvm.mlir.constant(1 : i32) : i32 // CHECK: %[[VAL_5:.*]] = llvm.sext %[[VAL_4]] : i32 to i64 @@ -431,8 +431,8 @@ func.func @_QPomp_target() { %c1 = arith.constant 1 : index %c0 = arith.constant 0 : index %1 = arith.subi %c512, %c1 : index - %2 = omp.bounds lower_bound(%c0 : index) upper_bound(%1 : index) extent(%c512 : index) stride(%c1 : index) start_idx(%c1 : index) - %3 = omp.map_info var_ptr(%0 : !fir.ref<!fir.array<512xi32>>, !fir.array<512xi32>) map_clauses(tofrom) capture(ByRef) bounds(%2) -> !fir.ref<!fir.array<512xi32>> {name = "a"} + %2 = omp.map.bounds lower_bound(%c0 : index) upper_bound(%1 : index) extent(%c512 : index) stride(%c1 : index) start_idx(%c1 : index) + %3 = omp.map.info var_ptr(%0 : !fir.ref<!fir.array<512xi32>>, !fir.array<512xi32>) map_clauses(tofrom) capture(ByRef) bounds(%2) -> !fir.ref<!fir.array<512xi32>> {name = "a"} omp.target thread_limit(%c64_i32 : i32) map_entries(%3 -> %arg0 : !fir.ref<!fir.array<512xi32>>) { ^bb0(%arg0: !fir.ref<!fir.array<512xi32>>): %c10_i32 = arith.constant 10 : i32 @@ -454,8 +454,8 @@ func.func @_QPomp_target() { // CHECK: %[[STRIDE:.*]] = llvm.mlir.constant(1 : index) : i64 // CHECK: %[[LOWER:.*]] = llvm.mlir.constant(0 : index) : i64 // CHECK: %[[UPPER:.*]] = llvm.mlir.constant(511 : index) : i64 -// CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[LOWER]] : i64) upper_bound(%[[UPPER]] : i64) extent(%[[EXTENT]] : i64) stride(%[[STRIDE]] : i64) start_idx(%[[STRIDE]] : i64) -// CHECK: %[[MAP:.*]] = omp.map_info var_ptr(%2 : !llvm.ptr, !llvm.array<512 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !llvm.ptr {name = "a"} +// CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%[[LOWER]] : i64) upper_bound(%[[UPPER]] : i64) extent(%[[EXTENT]] : i64) stride(%[[STRIDE]] : i64) start_idx(%[[STRIDE]] : i64) +// CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%2 : !llvm.ptr, !llvm.array<512 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !llvm.ptr {name = "a"} // CHECK: omp.target thread_limit(%[[VAL_2]] : i32) map_entries(%[[MAP]] -> %[[ARG_0:.*]] : !llvm.ptr) { // CHECK: ^bb0(%[[ARG_0]]: !llvm.ptr): // CHECK: %[[VAL_3:.*]] = llvm.mlir.constant(10 : i32) : i32 @@ -683,7 +683,7 @@ func.func @_QPsb() { // ----- -// CHECK: omp.reduction.declare @[[EQV_REDUCTION:.*]] : i32 init { +// CHECK: omp.declare_reduction @[[EQV_REDUCTION:.*]] : i32 init { // CHECK: ^bb0(%{{.*}}: i32): // CHECK: %[[TRUE:.*]] = llvm.mlir.constant(1 : i64) : i32 // CHECK: omp.yield(%[[TRUE]] : i32) @@ -716,7 +716,7 @@ func.func @_QPsb() { // CHECK: omp.terminator // CHECK: llvm.return -omp.reduction.declare @eqv_reduction : !fir.logical<4> init { +omp.declare_reduction @eqv_reduction : !fir.logical<4> init { ^bb0(%arg0: !fir.logical<4>): %true = arith.constant true %0 = fir.convert %true : (i1) -> !fir.logical<4> @@ -820,8 +820,8 @@ func.func @sub_() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %0 = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsubEi"} -// CHECK: omp.ordered_region - omp.ordered_region { +// CHECK: omp.ordered.region + omp.ordered.region { %1 = fir.convert %c1 : (index) -> i32 cf.br ^bb1(%1, %c1 : i32, index) ^bb1(%2: i32, %3: index): // 2 preds: ^bb0, ^bb2 @@ -914,10 +914,10 @@ func.func @omp_critical_() { func.func @omp_map_info_descriptor_type_conversion(%arg0 : !fir.ref<!fir.box<!fir.heap<i32>>>) { // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ARG_0]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> %0 = fir.box_offset %arg0 base_addr : (!fir.ref<!fir.box<!fir.heap<i32>>>) -> !fir.llvm_ptr<!fir.ref<i32>> - // CHECK: %[[MEMBER_MAP:.*]] = omp.map_info var_ptr(%[[GEP]] : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} - %1 = omp.map_info var_ptr(%0 : !fir.llvm_ptr<!fir.ref<i32>>, i32) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""} - // CHECK: %[[DESC_MAP:.*]] = omp.map_info var_ptr(%[[ARG_0]] : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) map_clauses(always, delete) capture(ByRef) members(%[[MEMBER_MAP]] : !llvm.ptr) -> !llvm.ptr {name = ""} - %2 = omp.map_info var_ptr(%arg0 : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.box<!fir.heap<i32>>) map_clauses(always, delete) capture(ByRef) members(%1 : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.heap<i32>>> {name = ""} + // CHECK: %[[MEMBER_MAP:.*]] = omp.map.info var_ptr(%[[GEP]] : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %1 = omp.map.info var_ptr(%0 : !fir.llvm_ptr<!fir.ref<i32>>, i32) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""} + // CHECK: %[[DESC_MAP:.*]] = omp.map.info var_ptr(%[[ARG_0]] : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) map_clauses(always, delete) capture(ByRef) members(%[[MEMBER_MAP]] : !llvm.ptr) -> !llvm.ptr {name = ""} + %2 = omp.map.info var_ptr(%arg0 : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.box<!fir.heap<i32>>) map_clauses(always, delete) capture(ByRef) members(%1 : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.heap<i32>>> {name = ""} // CHECK: omp.target_exit_data map_entries(%[[DESC_MAP]] : !llvm.ptr) omp.target_exit_data map_entries(%2 : !fir.ref<!fir.box<!fir.heap<i32>>>) return diff --git a/flang/test/Fir/dispatch.f90 b/flang/test/Fir/dispatch.f90 index 1dc71038813d871ca555853406b39b46b58277ed..1479d611b986aad0a32eee3f7255da586cb5d4d3 100644 --- a/flang/test/Fir/dispatch.f90 +++ b/flang/test/Fir/dispatch.f90 @@ -1,5 +1,5 @@ -! RUN: bbc -polymorphic-type -emit-hlfir %s -o - | fir-opt --fir-polymorphic-op | FileCheck %s -! RUN: bbc -polymorphic-type -emit-hlfir %s -o - | FileCheck %s --check-prefix=BT +! RUN: bbc -emit-hlfir %s -o - | fir-opt --fir-polymorphic-op | FileCheck %s +! RUN: bbc -emit-hlfir %s -o - | FileCheck %s --check-prefix=BT ! Tests codegen of fir.dispatch operation. This test is intentionally run from ! Fortran through bbc and tco so we have all the binding tables lowered to FIR diff --git a/flang/test/Fir/loop01.fir b/flang/test/Fir/loop01.fir index 72ca1c3989e453d41f3605c14cb48bc657f8e654..c849797b969eba5bda1e38cce73b888c0c85efa4 100644 --- a/flang/test/Fir/loop01.fir +++ b/flang/test/Fir/loop01.fir @@ -1,4 +1,4 @@ -// RUN: fir-opt --split-input-file --cfg-conversion %s | FileCheck %s +// RUN: fir-opt --split-input-file --cfg-conversion-on-func-opt %s | FileCheck %s func.func @x(%lb : index, %ub : index, %step : index, %b : i1, %addr : !fir.ref<index>) { fir.do_loop %iv = %lb to %ub step %step unordered { diff --git a/flang/test/Fir/loop02.fir b/flang/test/Fir/loop02.fir index 50948e0e7aa6b53dcc40fafb74f112b401b29f89..8918666f0b3460d8b1982e83dd13de3b9f9cf557 100644 --- a/flang/test/Fir/loop02.fir +++ b/flang/test/Fir/loop02.fir @@ -1,5 +1,5 @@ -// RUN: fir-opt --cfg-conversion="always-execute-loop-body=true" %s | FileCheck %s -// RUN: fir-opt --cfg-conversion %s | FileCheck %s --check-prefix=NOOPT +// RUN: fir-opt --cfg-conversion-on-func-opt="always-execute-loop-body=true" %s | FileCheck %s +// RUN: fir-opt --cfg-conversion-on-func-opt %s | FileCheck %s --check-prefix=NOOPT func.func @x(%addr : !fir.ref<index>) { %bound = arith.constant 452 : index diff --git a/flang/test/Fir/omp-reduction-embox-codegen.fir b/flang/test/Fir/omp-reduction-embox-codegen.fir new file mode 100644 index 0000000000000000000000000000000000000000..7602012ebc5c9f989a006e0c63b94c65d0ae9088 --- /dev/null +++ b/flang/test/Fir/omp-reduction-embox-codegen.fir @@ -0,0 +1,36 @@ +// RUN: tco %s | FileCheck %s + +// the fir.embox in the init region is turned into an alloca for the box. Test +// that CodeGen.cpp knows where to place an alloca when it is inside of an +// omp.declare_reduction + +// regretably this has to be nonsense IR because we need the subsequent patches +// to process anything useful + +omp.declare_reduction @test_reduction : !fir.ref<!fir.box<i32>> init { +^bb0(%arg0: !fir.ref<!fir.box<i32>>): + %0 = fir.alloca !fir.box<i32> + %1 = fir.alloca i32 + %2 = fir.embox %1 : (!fir.ref<i32>) -> !fir.box<i32> + + // use the embox for something so it isn't removed + fir.store %2 to %0 : !fir.ref<!fir.box<i32>> + + omp.yield(%0 : !fir.ref<!fir.box<i32>>) +} combiner { +^bb0(%arg0: !fir.ref<!fir.box<i32>>, %arg1: !fir.ref<!fir.box<i32>>): + %0 = fir.undefined !fir.ref<!fir.box<i32>> + omp.yield(%0 : !fir.ref<!fir.box<i32>>) +} + +func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { + %4 = fir.alloca !fir.box<i32> + omp.parallel byref reduction(@test_reduction %4 -> %arg0 : !fir.ref<!fir.box<i32>>) { + omp.terminator + } + return +} + +// basically we are testing that there isn't a crash +// CHECK-LABEL: define void @_QQmain +// CHECK-NEXT: alloca { ptr, i64, i32, i8, i8, i8, i8 }, i64 1, align 8 diff --git a/flang/test/HLFIR/assumed-type-actual-args.f90 b/flang/test/HLFIR/assumed-type-actual-args.f90 index 58c282b6ab188472d81af45c29d330548d3336bd..dbdfc1785ce9d73853bb4f79325182e1d0a41fc2 100644 --- a/flang/test/HLFIR/assumed-type-actual-args.f90 +++ b/flang/test/HLFIR/assumed-type-actual-args.f90 @@ -1,6 +1,6 @@ ! Test lowering to FIR of actual arguments that are assumed type ! variables (Fortran 2018 7.3.2.2 point 3). -! RUN: bbc --polymorphic-type -emit-hlfir -o - %s | FileCheck %s +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s subroutine test1(x) interface diff --git a/flang/test/HLFIR/boxchar_emboxing.f90 b/flang/test/HLFIR/boxchar_emboxing.f90 index 3e9ccde6babab5ba4bebb42ddf184b363669fe8f..fbc41bbea72d8a4dcc858647c4d5174faf9772e4 100644 --- a/flang/test/HLFIR/boxchar_emboxing.f90 +++ b/flang/test/HLFIR/boxchar_emboxing.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -polymorphic-type -emit-hlfir %s -o - | FileCheck %s +! RUN: bbc -emit-hlfir %s -o - | FileCheck %s ! CHECK-LABEL: func.func @_QPtest1( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<none> {fir.bindc_name = "x"}) { diff --git a/flang/test/HLFIR/call_with_poly_dummy.f90 b/flang/test/HLFIR/call_with_poly_dummy.f90 index af6876e26603ed1e78c39f4c3782092aff76d9ed..00a795c5b1fbed3e46c8c42e7669baa7eff74e1b 100644 --- a/flang/test/HLFIR/call_with_poly_dummy.f90 +++ b/flang/test/HLFIR/call_with_poly_dummy.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -polymorphic-type -emit-hlfir %s -o - | FileCheck %s +! RUN: bbc -emit-hlfir %s -o - | FileCheck %s ! Test passing arguments to subprograms with polymorphic dummy arguments. diff --git a/flang/test/Lower/CUDA/cuda-data-transfer.cuf b/flang/test/Lower/CUDA/cuda-data-transfer.cuf new file mode 100644 index 0000000000000000000000000000000000000000..54226b8623e6a90664d3deaf504b7ce2d0535065 --- /dev/null +++ b/flang/test/Lower/CUDA/cuda-data-transfer.cuf @@ -0,0 +1,57 @@ +! RUN: bbc -emit-hlfir -fcuda %s -o - | FileCheck %s + +! Test CUDA Fortran data transfer using assignment statements. + +subroutine sub1() + integer, device :: m + integer, device :: adev(10) + integer :: i, ahost(10), bhost(10) + + m = 1 + i + + m = 1 + + adev = ahost + + adev = ahost + 1 + + adev(1:5) = ahost(1:5) + + adev = ahost + bhost + +end + +! CHECK-LABEL: func.func @_QPsub1() + +! CHECK: %[[ADEV:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {cuda_attr = #fir.cuda<device>, uniq_name = "_QFsub1Eadev"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[AHOST:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFsub1Eahost"} : (!fir.ref<!fir.array<10xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>) +! CHECK: %[[I:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFsub1Ei"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[M:.*]]:2 = hlfir.declare %{{.*}} {cuda_attr = #fir.cuda<device>, uniq_name = "_QFsub1Em"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) + +! CHECK: %[[C1:.*]] = arith.constant 1 : i32 +! CHECK: %[[LOADED_I:.*]] = fir.load %[[I]]#0 : !fir.ref<i32> +! CHECK: %[[ADD:.*]] = arith.addi %[[C1]], %[[LOADED_I]] : i32 +! CHECK: %[[ASSOC:.*]]:3 = hlfir.associate %[[ADD]] {uniq_name = ".cuf_host_tmp"} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1) +! CHECK: fir.cuda_data_transfer %[[ASSOC]]#0 to %[[M]]#0 {transfer_kind = #fir.cuda_transfer<host_device>} : !fir.ref<i32>, !fir.ref<i32> +! CHECK: hlfir.end_associate %[[ASSOC]]#1, %[[ASSOC]]#2 : !fir.ref<i32>, i1 + +! CHECK: %[[C1:.*]] = arith.constant 1 : i32 +! CHECK: %[[ASSOC:.*]]:3 = hlfir.associate %[[C1]] {uniq_name = ".cuf_host_tmp"} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1) +! CHECK: fir.cuda_data_transfer %[[ASSOC]]#0 to %[[M]]#0 {transfer_kind = #fir.cuda_transfer<host_device>} : !fir.ref<i32>, !fir.ref<i32> +! CHECK: hlfir.end_associate %[[ASSOC]]#1, %[[ASSOC]]#2 : !fir.ref<i32>, i1 + +! CHECK: fir.cuda_data_transfer %[[AHOST]]#0 to %[[ADEV]]#0 {transfer_kind = #fir.cuda_transfer<host_device>} : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>> + +! CHECK: %[[ELEMENTAL:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<10xi32> { +! CHECK: %[[ASSOC:.*]]:3 = hlfir.associate %[[ELEMENTAL]](%{{.*}}) {uniq_name = ".cuf_host_tmp"} : (!hlfir.expr<10xi32>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>, i1) +! CHECK: fir.cuda_data_transfer %[[ASSOC]]#0 to %[[ADEV]]#0 {transfer_kind = #fir.cuda_transfer<host_device>} : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>> +! CHECK: hlfir.end_associate %[[ASSOC]]#1, %[[ASSOC]]#2 : !fir.ref<!fir.array<10xi32>>, i1 + +! CHECK: %[[DES_AHOST:.*]] = hlfir.designate %[[AHOST]]#0 (%c1{{.*}}:%c5{{.*}}:%c1{{.*}}) shape %{{.*}} : (!fir.ref<!fir.array<10xi32>>, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<5xi32>> +! CHECK: %[[DES_ADEV:.*]] = hlfir.designate %[[ADEV]]#0 (%c1{{.*}}:%c5{{.*}}:%c1{{.*}}) shape %{{.*}} : (!fir.ref<!fir.array<10xi32>>, index, index, index, !fir.shape<1>) -> !fir.ref<!fir.array<5xi32>> +! CHECK: fir.cuda_data_transfer %[[DES_AHOST]] to %[[DES_ADEV]] {transfer_kind = #fir.cuda_transfer<host_device>} : !fir.ref<!fir.array<5xi32>>, !fir.ref<!fir.array<5xi32>> + +! CHECK: %[[ELEMENTAL:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<10xi32> +! CHECK: %[[ASSOC:.*]]:3 = hlfir.associate %[[ELEMENTAL]](%{{.*}}) {uniq_name = ".cuf_host_tmp"} : (!hlfir.expr<10xi32>, !fir.shape<1>) -> (!fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>, i1) +! CHECK: fir.cuda_data_transfer %[[ASSOC]]#0 to %[[ADEV]]#0 {transfer_kind = #fir.cuda_transfer<host_device>} : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>> +! CHECK: hlfir.end_associate %[[ASSOC]]#1, %[[ASSOC]]#2 : !fir.ref<!fir.array<10xi32>>, i1 diff --git a/flang/test/Lower/CUDA/cuda-kernel-calls.cuf b/flang/test/Lower/CUDA/cuda-kernel-calls.cuf index c1e89d1978e4c2dba0c6af3f3e96f45c81a2b264..7e28fbb2231a2dccccefa18f33ad07ac9e93bf9b 100644 --- a/flang/test/Lower/CUDA/cuda-kernel-calls.cuf +++ b/flang/test/Lower/CUDA/cuda-kernel-calls.cuf @@ -1,4 +1,5 @@ ! RUN: bbc -emit-hlfir -fcuda %s -o - | FileCheck %s +! RUN: bbc -emit-hlfir -fcuda %s -o - | fir-opt | FileCheck %s ! Test lowering of CUDA procedure calls. @@ -18,15 +19,17 @@ contains ! CHECK: %[[A:.*]]:2 = hlfir.declare %{{.*}} {cuda_attr = #fir.cuda<device>, uniq_name = "_QMtest_callFhostEa"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) call dev_kernel0<<<10, 20>>>() -! CHECK: fir.cuda_kernel_launch @_QMtest_callPdev_kernel0<<<%c10{{.*}}, %c1{{.*}}, %c20{{.*}}, %c1{{.*}}, %c1{{.*}}>>>() +! CHECK: fir.cuda_kernel_launch @_QMtest_callPdev_kernel0<<<%c10{{.*}}, %c1{{.*}}, %c1{{.*}}, %c20{{.*}}, %c1{{.*}}, %c1{{.*}}>>>() - call dev_kernel0<<< __builtin_dim3(1,1), __builtin_dim3(32,1,1) >>> + call dev_kernel0<<< __builtin_dim3(1,1,4), __builtin_dim3(32,1,1) >>> ! CHECK: %[[ADDR_DIM3_GRID:.*]] = fir.address_of(@_QQro._QM__fortran_builtinsT__builtin_dim3.{{.*}}) : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>> ! CHECK: %[[DIM3_GRID:.*]]:2 = hlfir.declare %[[ADDR_DIM3_GRID]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro._QM__fortran_builtinsT__builtin_dim3.0"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) ! CHECK: %[[GRID_X:.*]] = hlfir.designate %[[DIM3_GRID]]#1{"x"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> !fir.ref<i32> ! CHECK: %[[GRID_X_LOAD:.*]] = fir.load %[[GRID_X]] : !fir.ref<i32> ! CHECK: %[[GRID_Y:.*]] = hlfir.designate %[[DIM3_GRID]]#1{"y"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> !fir.ref<i32> ! CHECK: %[[GRID_Y_LOAD:.*]] = fir.load %[[GRID_Y]] : !fir.ref<i32> +! CHECK: %[[GRID_Z:.*]] = hlfir.designate %[[DIM3_GRID]]#1{"z"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> !fir.ref<i32> +! CHECK: %[[GRID_Z_LOAD:.*]] = fir.load %[[GRID_Z]] : !fir.ref<i32> ! CHECK: %[[ADDR_DIM3_BLOCK:.*]] = fir.address_of(@_QQro._QM__fortran_builtinsT__builtin_dim3.{{.*}}) : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>> ! CHECK: %[[DIM3_BLOCK:.*]]:2 = hlfir.declare %[[ADDR_DIM3_BLOCK]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro._QM__fortran_builtinsT__builtin_dim3.1"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) ! CHECK: %[[BLOCK_X:.*]] = hlfir.designate %[[DIM3_BLOCK]]#1{"x"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> !fir.ref<i32> @@ -35,16 +38,16 @@ contains ! CHECK: %[[BLOCK_Y_LOAD:.*]] = fir.load %[[BLOCK_Y]] : !fir.ref<i32> ! CHECK: %[[BLOCK_Z:.*]] = hlfir.designate %[[DIM3_BLOCK]]#1{"z"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_dim3{x:i32,y:i32,z:i32}>>) -> !fir.ref<i32> ! CHECK: %[[BLOCK_Z_LOAD:.*]] = fir.load %[[BLOCK_Z]] : !fir.ref<i32> -! CHECK: fir.cuda_kernel_launch @_QMtest_callPdev_kernel0<<<%[[GRID_X_LOAD]], %[[GRID_Y_LOAD]], %[[BLOCK_X_LOAD]], %[[BLOCK_Y_LOAD]], %[[BLOCK_Z_LOAD]]>>>() +! CHECK: fir.cuda_kernel_launch @_QMtest_callPdev_kernel0<<<%[[GRID_X_LOAD]], %[[GRID_Y_LOAD]], %[[GRID_Z_LOAD]], %[[BLOCK_X_LOAD]], %[[BLOCK_Y_LOAD]], %[[BLOCK_Z_LOAD]]>>>() call dev_kernel0<<<10, 20, 2>>>() -! CHECK: fir.cuda_kernel_launch @_QMtest_callPdev_kernel0<<<%c10{{.*}}, %c1{{.*}}, %c20{{.*}}, %c1{{.*}}, %c1{{.*}}, %c2{{.*}}>>>() +! CHECK: fir.cuda_kernel_launch @_QMtest_callPdev_kernel0<<<%c10{{.*}}, %c1{{.*}}, %c1{{.*}}, %c20{{.*}}, %c1{{.*}}, %c1{{.*}}, %c2{{.*}}>>>() call dev_kernel0<<<10, 20, 2, 0>>>() -! CHECK: fir.cuda_kernel_launch @_QMtest_callPdev_kernel0<<<%c10{{.*}}, %c1{{.*}}, %c20{{.*}}, %c1{{.*}}, %c1{{.*}}, %c2{{.*}}, %c0{{.*}}>>>() +! CHECK: fir.cuda_kernel_launch @_QMtest_callPdev_kernel0<<<%c10{{.*}}, %c1{{.*}}, %c1{{.*}}, %c20{{.*}}, %c1{{.*}}, %c1{{.*}}, %c2{{.*}}, %c0{{.*}}>>>() call dev_kernel1<<<1, 32>>>(a) -! CHECK: fir.cuda_kernel_launch @_QMtest_callPdev_kernel1<<<%c1{{.*}}, %c1{{.*}}, %c32{{.*}}, %c1{{.*}}, %c1{{.*}}>>>(%1#1 : !fir.ref<f32>) +! CHECK: fir.cuda_kernel_launch @_QMtest_callPdev_kernel1<<<%c1{{.*}}, %c1{{.*}}, %c1{{.*}}, %c32{{.*}}, %c1{{.*}}, %c1{{.*}}>>>(%1#1) : (!fir.ref<f32>) end end diff --git a/flang/test/Lower/CUDA/cuda-kernel-loop-directive.cuf b/flang/test/Lower/CUDA/cuda-kernel-loop-directive.cuf index db628fe756b952530eaff4421acaf191ad61c795..6179e609db383c6b6c1037e4d9435baf2f81f0d5 100644 --- a/flang/test/Lower/CUDA/cuda-kernel-loop-directive.cuf +++ b/flang/test/Lower/CUDA/cuda-kernel-loop-directive.cuf @@ -42,10 +42,20 @@ subroutine sub1() ! CHECK: fir.cuda_kernel<<<%c1{{.*}}, (%c256{{.*}}, %c1{{.*}})>>> (%{{.*}} : index, %{{.*}} : index) = (%{{.*}}, %{{.*}} : index, index) to (%{{.*}}, %{{.*}} : index, index) step (%{{.*}}, %{{.*}} : index, index) ! CHECK: {n = 2 : i64} -! TODO: currently these trigger error in the parser -! !$cuf kernel do(2) <<< (1,*), (256,1) >>> -! !$cuf kernel do(2) <<< (*,*), (32,4) >>> -end - + !$cuf kernel do(2) <<< (1,*), (256,1) >>> + do i = 1, n + do j = 1, n + c(i,j) = c(i,j) * d(i,j) + end do + end do +! CHECK: fir.cuda_kernel<<<(%c1{{.*}}, %c0{{.*}}), (%c256{{.*}}, %c1{{.*}})>>> (%{{.*}} : index, %{{.*}} : index) = (%{{.*}}, %{{.*}} : index, index) to (%{{.*}}, %{{.*}} : index, index) step (%{{.*}}, %{{.*}} : index, index) +!$cuf kernel do(2) <<< (*,*), (32,4) >>> + do i = 1, n + do j = 1, n + c(i,j) = c(i,j) * d(i,j) + end do + end do +! CHECK: fir.cuda_kernel<<<*, (%c32{{.*}}, %c4{{.*}})>>> (%{{.*}} : index, %{{.*}} : index) = (%{{.*}}, %{{.*}} : index, index) to (%{{.*}}, %{{.*}} : index, index) step (%{{.*}}, %{{.*}} : index, index) +end diff --git a/flang/test/Lower/CUDA/cuda-module-use.cuf b/flang/test/Lower/CUDA/cuda-module-use.cuf index f54083b026ee88a5c2c2466e48f9df8043be913c..47d3805065a5a7d8329fa705c52df0472ca98938 100644 --- a/flang/test/Lower/CUDA/cuda-module-use.cuf +++ b/flang/test/Lower/CUDA/cuda-module-use.cuf @@ -5,7 +5,7 @@ subroutine sub1() use cuf_mod - md = 1.0 +! md = 1.0 ! currently a TODO end ! CHECK-LABEL: func.func @_QPsub1() diff --git a/flang/test/Lower/HLFIR/actual_target_for_dummy_pointer.f90 b/flang/test/Lower/HLFIR/actual_target_for_dummy_pointer.f90 index 76ed237fb6720a11ea86b951547a0cc7026b7b0f..129aa49b811db092aed9a50ca2a180ea9e6e6c9f 100644 --- a/flang/test/Lower/HLFIR/actual_target_for_dummy_pointer.f90 +++ b/flang/test/Lower/HLFIR/actual_target_for_dummy_pointer.f90 @@ -1,5 +1,5 @@ ! Test actual TARGET argument association to dummy POINTER: -! RUN: bbc -emit-hlfir --polymorphic-type -o - -I nowhere %s 2>&1 | FileCheck %s +! RUN: bbc -emit-hlfir -o - -I nowhere %s 2>&1 | FileCheck %s module target_to_pointer_types type t1 diff --git a/flang/test/Lower/HLFIR/allocatable-return.f90 b/flang/test/Lower/HLFIR/allocatable-return.f90 index d652b2f9f767dc6af3ecc763f752a1415931f813..e1bac34ef1a0ad4bfd1ff435e15ff0d85ac7f1fa 100644 --- a/flang/test/Lower/HLFIR/allocatable-return.f90 +++ b/flang/test/Lower/HLFIR/allocatable-return.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -emit-hlfir --polymorphic-type -I nowhere %s -o - | FileCheck %s +! RUN: bbc -emit-hlfir -I nowhere %s -o - | FileCheck %s ! Test allocatable return. ! Allocatable arrays must have default runtime lbounds after the return. diff --git a/flang/test/Lower/HLFIR/array-ctor-derived.f90 b/flang/test/Lower/HLFIR/array-ctor-derived.f90 index 21a3eb78a19952642030562b3b986df6e146e9d2..111225462a4bbe681f539eed4ba00ef7d7a16fdf 100644 --- a/flang/test/Lower/HLFIR/array-ctor-derived.f90 +++ b/flang/test/Lower/HLFIR/array-ctor-derived.f90 @@ -1,5 +1,5 @@ ! Test lowering of derived type array constructors to HLFIR. -! RUN: bbc -emit-hlfir --polymorphic-type -o - %s | FileCheck %s +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s module types type simple diff --git a/flang/test/Lower/HLFIR/call-sequence-associated-descriptors.f90 b/flang/test/Lower/HLFIR/call-sequence-associated-descriptors.f90 new file mode 100644 index 0000000000000000000000000000000000000000..7a2ea5cc14b644cd7c58bb1dc783e85012d0405d --- /dev/null +++ b/flang/test/Lower/HLFIR/call-sequence-associated-descriptors.f90 @@ -0,0 +1,309 @@ +! Test lowering of sequence associated arguments (F'2023 15.5.2.12) passed +! by descriptor. The descriptor on the caller side is prepared according to +! the dummy argument shape. +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s + +module bindc_seq_assoc + interface + subroutine takes_char(x, n) bind(c) + integer :: n + character(*) :: x(n) + end subroutine + subroutine takes_char_assumed_size(x) bind(c) + character(*) :: x(10, *) + end subroutine + subroutine takes_optional_char(x, n) bind(c) + integer :: n + character(*), optional :: x(n) + end subroutine + end interface +contains + subroutine test_char_1(x) + character(*) :: x(10, 20) + call takes_char(x, 100) + end subroutine +! CHECK-LABEL: func.func @_QMbindc_seq_assocPtest_char_1( +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_2:.*]](%[[VAL_5:.*]]) typeparams %[[VAL_1:.*]]#1 {uniq_name = "_QMbindc_seq_assocFtest_char_1Ex"} : (!fir.ref<!fir.array<10x20x!fir.char<1,?>>>, !fir.shape<2>, index) -> (!fir.box<!fir.array<10x20x!fir.char<1,?>>>, !fir.ref<!fir.array<10x20x!fir.char<1,?>>>) +! CHECK: %[[VAL_7:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_9:.*]] = fir.shift %[[VAL_8]], %[[VAL_8]] : (index, index) -> !fir.shift<2> +! CHECK: %[[VAL_10:.*]] = fir.rebox %[[VAL_6]]#0(%[[VAL_9]]) : (!fir.box<!fir.array<10x20x!fir.char<1,?>>>, !fir.shift<2>) -> !fir.box<!fir.array<10x20x!fir.char<1,?>>> +! CHECK: %[[VAL_11:.*]]:3 = hlfir.associate %[[VAL_7]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1) +! CHECK: %[[VAL_12:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_11]]#1 {uniq_name = "_QMbindc_seq_assocFtakes_charEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_13]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i32) -> i64 +! CHECK: %[[VAL_16:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_17:.*]] = arith.subi %[[VAL_15]], %[[VAL_16]] : i64 +! CHECK: %[[VAL_18:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_19:.*]] = arith.addi %[[VAL_17]], %[[VAL_18]] : i64 +! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i64) -> index +! CHECK: %[[VAL_21:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_22:.*]] = arith.cmpi sgt, %[[VAL_20]], %[[VAL_21]] : index +! CHECK: %[[VAL_23:.*]] = arith.select %[[VAL_22]], %[[VAL_20]], %[[VAL_21]] : index +! CHECK: %[[VAL_24:.*]] = fir.shape_shift %[[VAL_12]], %[[VAL_23]] : (index, index) -> !fir.shapeshift<1> +! CHECK: %[[VAL_25:.*]] = fir.box_elesize %[[VAL_10]] : (!fir.box<!fir.array<10x20x!fir.char<1,?>>>) -> index +! CHECK: %[[VAL_26:.*]] = fir.box_addr %[[VAL_10]] : (!fir.box<!fir.array<10x20x!fir.char<1,?>>>) -> !fir.ref<!fir.array<10x20x!fir.char<1,?>>> +! CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_26]] : (!fir.ref<!fir.array<10x20x!fir.char<1,?>>>) -> !fir.ref<!fir.array<?x!fir.char<1,?>>> +! CHECK: %[[VAL_28:.*]] = fir.embox %[[VAL_27]](%[[VAL_24]]) typeparams %[[VAL_25]] : (!fir.ref<!fir.array<?x!fir.char<1,?>>>, !fir.shapeshift<1>, index) -> !fir.box<!fir.array<?x!fir.char<1,?>>> +! CHECK: fir.call @takes_char(%[[VAL_28]], %[[VAL_11]]#1) fastmath<contract> : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.ref<i32>) -> () +! CHECK: hlfir.end_associate %[[VAL_11]]#1, %[[VAL_11]]#2 : !fir.ref<i32>, i1 +! CHECK: return +! CHECK: } + + subroutine test_char_copy_in_copy_out(x) + character(*) :: x(:, :) + call takes_char(x, 100) + end subroutine +! CHECK-LABEL: func.func @_QMbindc_seq_assocPtest_char_copy_in_copy_out( +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:.*]] {uniq_name = "_QMbindc_seq_assocFtest_char_copy_in_copy_outEx"} : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>) -> (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.box<!fir.array<?x?x!fir.char<1,?>>>) +! CHECK: %[[VAL_2:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_3:.*]]:2 = hlfir.copy_in %[[VAL_1]]#0 : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>) -> (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, i1) +! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_5:.*]] = fir.shift %[[VAL_4]], %[[VAL_4]] : (index, index) -> !fir.shift<2> +! CHECK: %[[VAL_6:.*]] = fir.rebox %[[VAL_3]]#0(%[[VAL_5]]) : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.shift<2>) -> !fir.box<!fir.array<?x?x!fir.char<1,?>>> +! CHECK: %[[VAL_7:.*]]:3 = hlfir.associate %[[VAL_2]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1) +! CHECK: %[[VAL_8:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_7]]#1 {uniq_name = "_QMbindc_seq_assocFtakes_charEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_9]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_10]] : (i32) -> i64 +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_13:.*]] = arith.subi %[[VAL_11]], %[[VAL_12]] : i64 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_15:.*]] = arith.addi %[[VAL_13]], %[[VAL_14]] : i64 +! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i64) -> index +! CHECK: %[[VAL_17:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_18:.*]] = arith.cmpi sgt, %[[VAL_16]], %[[VAL_17]] : index +! CHECK: %[[VAL_19:.*]] = arith.select %[[VAL_18]], %[[VAL_16]], %[[VAL_17]] : index +! CHECK: %[[VAL_20:.*]] = fir.shape_shift %[[VAL_8]], %[[VAL_19]] : (index, index) -> !fir.shapeshift<1> +! CHECK: %[[VAL_21:.*]] = fir.box_elesize %[[VAL_6]] : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>) -> index +! CHECK: %[[VAL_22:.*]] = fir.box_addr %[[VAL_6]] : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>) -> !fir.ref<!fir.array<?x?x!fir.char<1,?>>> +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_22]] : (!fir.ref<!fir.array<?x?x!fir.char<1,?>>>) -> !fir.ref<!fir.array<?x!fir.char<1,?>>> +! CHECK: %[[VAL_24:.*]] = fir.embox %[[VAL_23]](%[[VAL_20]]) typeparams %[[VAL_21]] : (!fir.ref<!fir.array<?x!fir.char<1,?>>>, !fir.shapeshift<1>, index) -> !fir.box<!fir.array<?x!fir.char<1,?>>> +! CHECK: fir.call @takes_char(%[[VAL_24]], %[[VAL_7]]#1) fastmath<contract> : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.ref<i32>) -> () +! CHECK: hlfir.copy_out %[[VAL_3]]#0, %[[VAL_3]]#1 to %[[VAL_1]]#0 : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, i1, !fir.box<!fir.array<?x?x!fir.char<1,?>>>) -> () +! CHECK: hlfir.end_associate %[[VAL_7]]#1, %[[VAL_7]]#2 : !fir.ref<i32>, i1 +! CHECK: return +! CHECK: } + + subroutine test_char_assumed_size(x) + character(*) :: x(:, :) + call takes_char_assumed_size(x) + end subroutine +! CHECK-LABEL: func.func @_QMbindc_seq_assocPtest_char_assumed_size( +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:.*]] {uniq_name = "_QMbindc_seq_assocFtest_char_assumed_sizeEx"} : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>) -> (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.box<!fir.array<?x?x!fir.char<1,?>>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.copy_in %[[VAL_1]]#0 : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>) -> (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, i1) +! CHECK: %[[VAL_3:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_4:.*]] = fir.shift %[[VAL_3]], %[[VAL_3]] : (index, index) -> !fir.shift<2> +! CHECK: %[[VAL_5:.*]] = fir.rebox %[[VAL_2]]#0(%[[VAL_4]]) : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.shift<2>) -> !fir.box<!fir.array<?x?x!fir.char<1,?>>> +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_7:.*]] = arith.constant 10 : i64 +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_9:.*]] = arith.subi %[[VAL_7]], %[[VAL_8]] : i64 +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_11:.*]] = arith.addi %[[VAL_9]], %[[VAL_10]] : i64 +! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_11]] : (i64) -> index +! CHECK: %[[VAL_13:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_14:.*]] = arith.cmpi sgt, %[[VAL_12]], %[[VAL_13]] : index +! CHECK: %[[VAL_15:.*]] = arith.select %[[VAL_14]], %[[VAL_12]], %[[VAL_13]] : index +! CHECK: %[[VAL_16:.*]] = arith.constant -1 : i64 +! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_16]] : (i64) -> index +! CHECK: %[[VAL_18:.*]] = fir.shape_shift %[[VAL_6]], %[[VAL_15]], %[[VAL_6]], %[[VAL_17]] : (index, index, index, index) -> !fir.shapeshift<2> +! CHECK: %[[VAL_19:.*]] = fir.box_elesize %[[VAL_5]] : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>) -> index +! CHECK: %[[VAL_20:.*]] = fir.box_addr %[[VAL_5]] : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>) -> !fir.ref<!fir.array<?x?x!fir.char<1,?>>> +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (!fir.ref<!fir.array<?x?x!fir.char<1,?>>>) -> !fir.ref<!fir.array<10x?x!fir.char<1,?>>> +! CHECK: %[[VAL_22:.*]] = fir.embox %[[VAL_21]](%[[VAL_18]]) typeparams %[[VAL_19]] : (!fir.ref<!fir.array<10x?x!fir.char<1,?>>>, !fir.shapeshift<2>, index) -> !fir.box<!fir.array<10x?x!fir.char<1,?>>> +! CHECK: fir.call @takes_char_assumed_size(%[[VAL_22]]) fastmath<contract> : (!fir.box<!fir.array<10x?x!fir.char<1,?>>>) -> () +! CHECK: hlfir.copy_out %[[VAL_2]]#0, %[[VAL_2]]#1 to %[[VAL_1]]#0 : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, i1, !fir.box<!fir.array<?x?x!fir.char<1,?>>>) -> () +! CHECK: return +! CHECK: } + + subroutine test_optional_char(x) + character(*), optional :: x(10, 20) + call takes_optional_char(x, 100) + end subroutine +! CHECK-LABEL: func.func @_QMbindc_seq_assocPtest_optional_char( +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_2:.*]](%[[VAL_5:.*]]) typeparams %[[VAL_1:.*]]#1 {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMbindc_seq_assocFtest_optional_charEx"} : (!fir.ref<!fir.array<10x20x!fir.char<1,?>>>, !fir.shape<2>, index) -> (!fir.box<!fir.array<10x20x!fir.char<1,?>>>, !fir.ref<!fir.array<10x20x!fir.char<1,?>>>) +! CHECK: %[[VAL_7:.*]] = fir.is_present %[[VAL_6]]#0 : (!fir.box<!fir.array<10x20x!fir.char<1,?>>>) -> i1 +! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_9:.*]] = fir.if %[[VAL_7]] -> (!fir.box<!fir.array<10x20x!fir.char<1,?>>>) { +! CHECK: %[[VAL_10:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_11:.*]] = fir.shift %[[VAL_10]], %[[VAL_10]] : (index, index) -> !fir.shift<2> +! CHECK: %[[VAL_12:.*]] = fir.rebox %[[VAL_6]]#0(%[[VAL_11]]) : (!fir.box<!fir.array<10x20x!fir.char<1,?>>>, !fir.shift<2>) -> !fir.box<!fir.array<10x20x!fir.char<1,?>>> +! CHECK: fir.result %[[VAL_12]] : !fir.box<!fir.array<10x20x!fir.char<1,?>>> +! CHECK: } else { +! CHECK: %[[VAL_13:.*]] = fir.absent !fir.box<!fir.array<10x20x!fir.char<1,?>>> +! CHECK: fir.result %[[VAL_13]] : !fir.box<!fir.array<10x20x!fir.char<1,?>>> +! CHECK: } +! CHECK: %[[VAL_14:.*]]:3 = hlfir.associate %[[VAL_8]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1) +! CHECK: %[[VAL_15:.*]] = fir.if %[[VAL_7]] -> (!fir.box<!fir.array<?x!fir.char<1,?>>>) { +! CHECK: %[[VAL_16:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_14]]#1 {uniq_name = "_QMbindc_seq_assocFtakes_optional_charEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_18]] : (i32) -> i64 +! CHECK: %[[VAL_20:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_21:.*]] = arith.subi %[[VAL_19]], %[[VAL_20]] : i64 +! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_23:.*]] = arith.addi %[[VAL_21]], %[[VAL_22]] : i64 +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_23]] : (i64) -> index +! CHECK: %[[VAL_25:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_26:.*]] = arith.cmpi sgt, %[[VAL_24]], %[[VAL_25]] : index +! CHECK: %[[VAL_27:.*]] = arith.select %[[VAL_26]], %[[VAL_24]], %[[VAL_25]] : index +! CHECK: %[[VAL_28:.*]] = fir.shape_shift %[[VAL_16]], %[[VAL_27]] : (index, index) -> !fir.shapeshift<1> +! CHECK: %[[VAL_29:.*]] = fir.box_elesize %[[VAL_9]] : (!fir.box<!fir.array<10x20x!fir.char<1,?>>>) -> index +! CHECK: %[[VAL_30:.*]] = fir.box_addr %[[VAL_9]] : (!fir.box<!fir.array<10x20x!fir.char<1,?>>>) -> !fir.ref<!fir.array<10x20x!fir.char<1,?>>> +! CHECK: %[[VAL_31:.*]] = fir.convert %[[VAL_30]] : (!fir.ref<!fir.array<10x20x!fir.char<1,?>>>) -> !fir.ref<!fir.array<?x!fir.char<1,?>>> +! CHECK: %[[VAL_32:.*]] = fir.embox %[[VAL_31]](%[[VAL_28]]) typeparams %[[VAL_29]] : (!fir.ref<!fir.array<?x!fir.char<1,?>>>, !fir.shapeshift<1>, index) -> !fir.box<!fir.array<?x!fir.char<1,?>>> +! CHECK: fir.result %[[VAL_32]] : !fir.box<!fir.array<?x!fir.char<1,?>>> +! CHECK: } else { +! CHECK: %[[VAL_33:.*]] = fir.absent !fir.box<!fir.array<?x!fir.char<1,?>>> +! CHECK: fir.result %[[VAL_33]] : !fir.box<!fir.array<?x!fir.char<1,?>>> +! CHECK: } +! CHECK: fir.call @takes_optional_char(%[[VAL_15]], %[[VAL_14]]#1) fastmath<contract> : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.ref<i32>) -> () +! CHECK: hlfir.end_associate %[[VAL_14]]#1, %[[VAL_14]]#2 : !fir.ref<i32>, i1 +! CHECK: return +! CHECK: } +end module + +module poly_seq_assoc + interface + subroutine takes_poly(x, n) + integer :: n + class(*) :: x(n) + end subroutine + subroutine takes_poly_assumed_size(x) + class(*) :: x(10, *) + end subroutine + subroutine takes_optional_poly(x, n) + integer :: n + class(*), optional :: x(n) + end subroutine + end interface +contains + subroutine test_poly_1(x) + class(*) :: x(10, 20) + call takes_poly(x, 100) + end subroutine +! CHECK-LABEL: func.func @_QMpoly_seq_assocPtest_poly_1( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.array<10x20xnone>> {fir.bindc_name = "x"}) { +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:.*]] {uniq_name = "_QMpoly_seq_assocFtest_poly_1Ex"} : (!fir.class<!fir.array<10x20xnone>>) -> (!fir.class<!fir.array<10x20xnone>>, !fir.class<!fir.array<10x20xnone>>) +! CHECK: %[[VAL_2:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_3:.*]]:3 = hlfir.associate %[[VAL_2]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1) +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]]#1 {uniq_name = "_QMpoly_seq_assocFtakes_polyEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (i32) -> i64 +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_8:.*]] = arith.subi %[[VAL_6]], %[[VAL_7]] : i64 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_10:.*]] = arith.addi %[[VAL_8]], %[[VAL_9]] : i64 +! CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_10]] : (i64) -> index +! CHECK: %[[VAL_12:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_13:.*]] = arith.cmpi sgt, %[[VAL_11]], %[[VAL_12]] : index +! CHECK: %[[VAL_14:.*]] = arith.select %[[VAL_13]], %[[VAL_11]], %[[VAL_12]] : index +! CHECK: %[[VAL_15:.*]] = fir.shape %[[VAL_14]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_16:.*]] = fir.box_addr %[[VAL_1]]#1 : (!fir.class<!fir.array<10x20xnone>>) -> !fir.ref<!fir.array<10x20xnone>> +! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_16]] : (!fir.ref<!fir.array<10x20xnone>>) -> !fir.ref<!fir.array<?xnone>> +! CHECK: %[[VAL_18:.*]] = fir.embox %[[VAL_17]](%[[VAL_15]]) source_box %[[VAL_1]]#0 : (!fir.ref<!fir.array<?xnone>>, !fir.shape<1>, !fir.class<!fir.array<10x20xnone>>) -> !fir.class<!fir.array<?xnone>> +! CHECK: fir.call @_QPtakes_poly(%[[VAL_18]], %[[VAL_3]]#1) fastmath<contract> : (!fir.class<!fir.array<?xnone>>, !fir.ref<i32>) -> () +! CHECK: hlfir.end_associate %[[VAL_3]]#1, %[[VAL_3]]#2 : !fir.ref<i32>, i1 +! CHECK: return +! CHECK: } + + subroutine test_poly_copy_in_copy_out(x) + class(*) :: x(:, :) + call takes_poly(x, 100) + end subroutine +! CHECK-LABEL: func.func @_QMpoly_seq_assocPtest_poly_copy_in_copy_out( +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:.*]] {uniq_name = "_QMpoly_seq_assocFtest_poly_copy_in_copy_outEx"} : (!fir.class<!fir.array<?x?xnone>>) -> (!fir.class<!fir.array<?x?xnone>>, !fir.class<!fir.array<?x?xnone>>) +! CHECK: %[[VAL_2:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_3:.*]]:2 = hlfir.copy_in %[[VAL_1]]#0 : (!fir.class<!fir.array<?x?xnone>>) -> (!fir.class<!fir.array<?x?xnone>>, i1) +! CHECK: %[[VAL_4:.*]]:3 = hlfir.associate %[[VAL_2]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]]#1 {uniq_name = "_QMpoly_seq_assocFtakes_polyEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (i32) -> i64 +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_9:.*]] = arith.subi %[[VAL_7]], %[[VAL_8]] : i64 +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_11:.*]] = arith.addi %[[VAL_9]], %[[VAL_10]] : i64 +! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_11]] : (i64) -> index +! CHECK: %[[VAL_13:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_14:.*]] = arith.cmpi sgt, %[[VAL_12]], %[[VAL_13]] : index +! CHECK: %[[VAL_15:.*]] = arith.select %[[VAL_14]], %[[VAL_12]], %[[VAL_13]] : index +! CHECK: %[[VAL_16:.*]] = fir.shape %[[VAL_15]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_17:.*]] = fir.box_addr %[[VAL_3]]#0 : (!fir.class<!fir.array<?x?xnone>>) -> !fir.ref<!fir.array<?x?xnone>> +! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_17]] : (!fir.ref<!fir.array<?x?xnone>>) -> !fir.ref<!fir.array<?xnone>> +! CHECK: %[[VAL_19:.*]] = fir.embox %[[VAL_18]](%[[VAL_16]]) source_box %[[VAL_3]]#0 : (!fir.ref<!fir.array<?xnone>>, !fir.shape<1>, !fir.class<!fir.array<?x?xnone>>) -> !fir.class<!fir.array<?xnone>> +! CHECK: fir.call @_QPtakes_poly(%[[VAL_19]], %[[VAL_4]]#1) fastmath<contract> : (!fir.class<!fir.array<?xnone>>, !fir.ref<i32>) -> () +! CHECK: hlfir.copy_out %[[VAL_3]]#0, %[[VAL_3]]#1 to %[[VAL_1]]#0 : (!fir.class<!fir.array<?x?xnone>>, i1, !fir.class<!fir.array<?x?xnone>>) -> () +! CHECK: hlfir.end_associate %[[VAL_4]]#1, %[[VAL_4]]#2 : !fir.ref<i32>, i1 +! CHECK: return +! CHECK: } + + subroutine test_poly_assumed_size(x) + class(*) :: x(:, :) + call takes_poly_assumed_size(x) + end subroutine +! CHECK-LABEL: func.func @_QMpoly_seq_assocPtest_poly_assumed_size( +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:.*]] {uniq_name = "_QMpoly_seq_assocFtest_poly_assumed_sizeEx"} : (!fir.class<!fir.array<?x?xnone>>) -> (!fir.class<!fir.array<?x?xnone>>, !fir.class<!fir.array<?x?xnone>>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.copy_in %[[VAL_1]]#0 : (!fir.class<!fir.array<?x?xnone>>) -> (!fir.class<!fir.array<?x?xnone>>, i1) +! CHECK: %[[VAL_3:.*]] = arith.constant 10 : i64 +! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_5:.*]] = arith.subi %[[VAL_3]], %[[VAL_4]] : i64 +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_7:.*]] = arith.addi %[[VAL_5]], %[[VAL_6]] : i64 +! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i64) -> index +! CHECK: %[[VAL_9:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_10:.*]] = arith.cmpi sgt, %[[VAL_8]], %[[VAL_9]] : index +! CHECK: %[[VAL_11:.*]] = arith.select %[[VAL_10]], %[[VAL_8]], %[[VAL_9]] : index +! CHECK: %[[VAL_12:.*]] = arith.constant -1 : i64 +! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_12]] : (i64) -> index +! CHECK: %[[VAL_14:.*]] = fir.shape %[[VAL_11]], %[[VAL_13]] : (index, index) -> !fir.shape<2> +! CHECK: %[[VAL_15:.*]] = fir.box_addr %[[VAL_2]]#0 : (!fir.class<!fir.array<?x?xnone>>) -> !fir.ref<!fir.array<?x?xnone>> +! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (!fir.ref<!fir.array<?x?xnone>>) -> !fir.ref<!fir.array<10x?xnone>> +! CHECK: %[[VAL_17:.*]] = fir.embox %[[VAL_16]](%[[VAL_14]]) source_box %[[VAL_2]]#0 : (!fir.ref<!fir.array<10x?xnone>>, !fir.shape<2>, !fir.class<!fir.array<?x?xnone>>) -> !fir.class<!fir.array<10x?xnone>> +! CHECK: fir.call @_QPtakes_poly_assumed_size(%[[VAL_17]]) fastmath<contract> : (!fir.class<!fir.array<10x?xnone>>) -> () +! CHECK: hlfir.copy_out %[[VAL_2]]#0, %[[VAL_2]]#1 to %[[VAL_1]]#0 : (!fir.class<!fir.array<?x?xnone>>, i1, !fir.class<!fir.array<?x?xnone>>) -> () +! CHECK: return +! CHECK: } + + subroutine test_optional_poly(x) + class(*), optional :: x(10, 20) + call takes_optional_poly(x, 100) + end subroutine +! CHECK-LABEL: func.func @_QMpoly_seq_assocPtest_optional_poly( +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0:.*]] {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QMpoly_seq_assocFtest_optional_polyEx"} : (!fir.class<!fir.array<10x20xnone>>) -> (!fir.class<!fir.array<10x20xnone>>, !fir.class<!fir.array<10x20xnone>>) +! CHECK: %[[VAL_2:.*]] = fir.is_present %[[VAL_1]]#0 : (!fir.class<!fir.array<10x20xnone>>) -> i1 +! CHECK: %[[VAL_3:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_4:.*]] = fir.if %[[VAL_2]] -> (!fir.class<!fir.array<10x20xnone>>) { +! CHECK: fir.result %[[VAL_1]]#0 : !fir.class<!fir.array<10x20xnone>> +! CHECK: } else { +! CHECK: %[[VAL_5:.*]] = fir.absent !fir.class<!fir.array<10x20xnone>> +! CHECK: fir.result %[[VAL_5]] : !fir.class<!fir.array<10x20xnone>> +! CHECK: } +! CHECK: %[[VAL_6:.*]]:3 = hlfir.associate %[[VAL_3]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1) +! CHECK: %[[VAL_7:.*]] = fir.if %[[VAL_2]] -> (!fir.class<!fir.array<?xnone>>) { +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_6]]#1 {uniq_name = "_QMpoly_seq_assocFtakes_optional_polyEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i32) -> i64 +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_12:.*]] = arith.subi %[[VAL_10]], %[[VAL_11]] : i64 +! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_14:.*]] = arith.addi %[[VAL_12]], %[[VAL_13]] : i64 +! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i64) -> index +! CHECK: %[[VAL_16:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_17:.*]] = arith.cmpi sgt, %[[VAL_15]], %[[VAL_16]] : index +! CHECK: %[[VAL_18:.*]] = arith.select %[[VAL_17]], %[[VAL_15]], %[[VAL_16]] : index +! CHECK: %[[VAL_19:.*]] = fir.shape %[[VAL_18]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_20:.*]] = fir.box_addr %[[VAL_4]] : (!fir.class<!fir.array<10x20xnone>>) -> !fir.ref<!fir.array<10x20xnone>> +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (!fir.ref<!fir.array<10x20xnone>>) -> !fir.ref<!fir.array<?xnone>> +! CHECK: %[[VAL_22:.*]] = fir.embox %[[VAL_21]](%[[VAL_19]]) source_box %[[VAL_4]] : (!fir.ref<!fir.array<?xnone>>, !fir.shape<1>, !fir.class<!fir.array<10x20xnone>>) -> !fir.class<!fir.array<?xnone>> +! CHECK: fir.result %[[VAL_22]] : !fir.class<!fir.array<?xnone>> +! CHECK: } else { +! CHECK: %[[VAL_23:.*]] = fir.absent !fir.class<!fir.array<?xnone>> +! CHECK: fir.result %[[VAL_23]] : !fir.class<!fir.array<?xnone>> +! CHECK: } +! CHECK: fir.call @_QPtakes_optional_poly(%[[VAL_7]], %[[VAL_6]]#1) fastmath<contract> : (!fir.class<!fir.array<?xnone>>, !fir.ref<i32>) -> () +! CHECK: hlfir.end_associate %[[VAL_6]]#1, %[[VAL_6]]#2 : !fir.ref<i32>, i1 +! CHECK: return +! CHECK: } +end module diff --git a/flang/test/Lower/HLFIR/calls-assumed-shape.f90 b/flang/test/Lower/HLFIR/calls-assumed-shape.f90 index 92b87a6987a55848bf8a864b3d4c245e431d1618..a2094f1f1f0eb1307d32bd6e9c048e50e1c13d65 100644 --- a/flang/test/Lower/HLFIR/calls-assumed-shape.f90 +++ b/flang/test/Lower/HLFIR/calls-assumed-shape.f90 @@ -1,6 +1,6 @@ ! Test lowering of calls involving assumed shape arrays or arrays with ! VALUE attribute. -! RUN: bbc -emit-hlfir -polymorphic-type -o - %s | FileCheck %s +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s subroutine test_assumed_to_assumed(x) interface diff --git a/flang/test/Lower/HLFIR/calls-constant-expr-arg-polymorphic.f90 b/flang/test/Lower/HLFIR/calls-constant-expr-arg-polymorphic.f90 index a862033c0fefaf47ee8395bb506e6fa3a86db484..4ee70e55079dadc745a69d860e5d4d92fa811bab 100644 --- a/flang/test/Lower/HLFIR/calls-constant-expr-arg-polymorphic.f90 +++ b/flang/test/Lower/HLFIR/calls-constant-expr-arg-polymorphic.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -emit-hlfir --polymorphic-type -o - %s | FileCheck %s +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s ! Test when constant argument are copied in memory ! and passed to polymorphic arguments. diff --git a/flang/test/Lower/HLFIR/calls-optional.f90 b/flang/test/Lower/HLFIR/calls-optional.f90 index cf684981f80031cac23fbd36aa0b45a38adff470..df9519a24fb702f9d035e22b3b21cb5dc1f9bb54 100644 --- a/flang/test/Lower/HLFIR/calls-optional.f90 +++ b/flang/test/Lower/HLFIR/calls-optional.f90 @@ -2,7 +2,7 @@ ! that is syntactically present, but may be absent at runtime (is ! an optional or a pointer/allocatable). ! -! RUN: bbc -emit-hlfir -polymorphic-type -o - %s | FileCheck %s +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s subroutine optional_copy_in_out(x) interface diff --git a/flang/test/Lower/HLFIR/calls-poly-to-assumed-type.f90 b/flang/test/Lower/HLFIR/calls-poly-to-assumed-type.f90 index ffd21e01ef98dd30fe10e462b217958a82102e09..b14f1bb1f443b5624f952362adb6e43445290ffa 100644 --- a/flang/test/Lower/HLFIR/calls-poly-to-assumed-type.f90 +++ b/flang/test/Lower/HLFIR/calls-poly-to-assumed-type.f90 @@ -1,6 +1,6 @@ ! Test passing rank 2 CLASS(*) deferred shape to assumed size assumed type ! This requires copy-in/copy-out logic. -! RUN: bbc -emit-hlfir -polymorphic-type -o - %s | FileCheck %s +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s subroutine pass_poly_to_assumed_type_assumed_size(x) class(*), target :: x(:,:) diff --git a/flang/test/Lower/HLFIR/convert-mbox-to-value.f90 b/flang/test/Lower/HLFIR/convert-mbox-to-value.f90 index b943cd3225a564a0f39d4dbeef9fcce940876647..b9d55d3fde4f099209be12703dda33ab8ddae2aa 100644 --- a/flang/test/Lower/HLFIR/convert-mbox-to-value.f90 +++ b/flang/test/Lower/HLFIR/convert-mbox-to-value.f90 @@ -1,5 +1,5 @@ ! Test conversion of MutableBoxValue to value. -! RUN: bbc -emit-hlfir -polymorphic-type -I nowhere %s -o - | FileCheck %s +! RUN: bbc -emit-hlfir -I nowhere %s -o - | FileCheck %s subroutine test_int_allocatable(a) integer, allocatable :: a diff --git a/flang/test/Lower/HLFIR/cray-pointers.f90 b/flang/test/Lower/HLFIR/cray-pointers.f90 index d1f1a5647ff1ca89a0fd199922ed152e54709441..d969aa5d747a836d558284ea22009b8e52870f37 100644 --- a/flang/test/Lower/HLFIR/cray-pointers.f90 +++ b/flang/test/Lower/HLFIR/cray-pointers.f90 @@ -204,14 +204,14 @@ end subroutine test7 ! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.array<5xi32> {bindc_name = "arr", uniq_name = "_QFtest7Earr"} ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_3]](%[[VAL_4]]) {uniq_name = "_QFtest7Earr"} : (!fir.ref<!fir.array<5xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<5xi32>>, !fir.ref<!fir.array<5xi32>>) +! CHECK: %[[VAL_12:.*]] = fir.alloca i64 {bindc_name = "ptr", uniq_name = "_QFtest7Eptr"} +! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFtest7Eptr"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_6:.*]] = arith.constant 5 : index ! CHECK: %[[VAL_8:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1> ! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_1]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest7Epte"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) ! CHECK: %[[VAL_10:.*]] = fir.zero_bits !fir.ptr<!fir.array<?xi32>> ! CHECK: %[[VAL_11:.*]] = fir.embox %[[VAL_10]](%[[VAL_8]]) : (!fir.ptr<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>> ! CHECK: fir.store %[[VAL_11]] to %[[VAL_9]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> -! CHECK: %[[VAL_12:.*]] = fir.alloca i64 {bindc_name = "ptr", uniq_name = "_QFtest7Eptr"} -! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFtest7Eptr"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_13]]#0 : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<i64>> ! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_14]] : !fir.ref<!fir.ptr<i64>> ! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_9]]#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>> @@ -226,14 +226,14 @@ subroutine test8() end subroutine test8 ! CHECK-LABEL: func.func @_QPtest8( ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> +! CHECK: %[[VAL_8:.*]] = fir.alloca i64 {bindc_name = "ptr", uniq_name = "_QFtest8Eptr"} +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFtest8Eptr"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_2:.*]] = arith.constant 5 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest8Epte"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) ! CHECK: %[[VAL_6:.*]] = fir.zero_bits !fir.ptr<!fir.array<?xi32>> ! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_6]](%[[VAL_4]]) : (!fir.ptr<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>> ! CHECK: fir.store %[[VAL_7]] to %[[VAL_5]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> -! CHECK: %[[VAL_8:.*]] = fir.alloca i64 {bindc_name = "ptr", uniq_name = "_QFtest8Eptr"} -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFtest8Eptr"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]]#0 : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<i64>> ! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_10]] : !fir.ref<!fir.ptr<i64>> ! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_5]]#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>> @@ -256,14 +256,14 @@ subroutine test9() end subroutine test9 ! CHECK-LABEL: func.func @_QPtest9( ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?xi32>>> +! CHECK: %[[VAL_8:.*]] = fir.alloca i64 {bindc_name = "ptr", uniq_name = "_QFtest9Eptr"} +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFtest9Eptr"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_2:.*]] = arith.constant 5 : index ! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1> ! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_1]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest9Epte"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) ! CHECK: %[[VAL_6:.*]] = fir.zero_bits !fir.ptr<!fir.array<?xi32>> ! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_6]](%[[VAL_4]]) : (!fir.ptr<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xi32>>> ! CHECK: fir.store %[[VAL_7]] to %[[VAL_5]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> -! CHECK: %[[VAL_8:.*]] = fir.alloca i64 {bindc_name = "ptr", uniq_name = "_QFtest9Eptr"} -! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFtest9Eptr"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]]#0 : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<i64>> ! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_10]] : !fir.ref<!fir.ptr<i64>> ! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_5]]#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>> @@ -287,12 +287,12 @@ subroutine test10() end subroutine test10 ! CHECK-LABEL: func.func @_QPtest10( ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> +! CHECK: %[[VAL_6:.*]] = fir.alloca i64 {bindc_name = "ptr", uniq_name = "_QFtest10Eptr"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFtest10Eptr"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest10Epte"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) ! CHECK: %[[VAL_4:.*]] = fir.zero_bits !fir.ptr<i32> ! CHECK: %[[VAL_5:.*]] = fir.embox %[[VAL_4]] : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>> ! CHECK: fir.store %[[VAL_5]] to %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>> -! CHECK: %[[VAL_6:.*]] = fir.alloca i64 {bindc_name = "ptr", uniq_name = "_QFtest10Eptr"} -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFtest10Eptr"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]]#0 : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<i64>> ! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_8]] : !fir.ref<!fir.ptr<i64>> ! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_3]]#0 : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> !fir.ref<!fir.box<none>> @@ -315,12 +315,12 @@ subroutine test11() end subroutine test11 ! CHECK-LABEL: func.func @_QPtest11( ! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> +! CHECK: %[[VAL_6:.*]] = fir.alloca i64 {bindc_name = "ptr", uniq_name = "_QFtest11Eptr"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFtest11Eptr"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest11Epte"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) ! CHECK: %[[VAL_4:.*]] = fir.zero_bits !fir.ptr<i32> ! CHECK: %[[VAL_5:.*]] = fir.embox %[[VAL_4]] : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>> ! CHECK: fir.store %[[VAL_5]] to %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>> -! CHECK: %[[VAL_6:.*]] = fir.alloca i64 {bindc_name = "ptr", uniq_name = "_QFtest11Eptr"} -! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFtest11Eptr"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) ! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]]#0 : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<i64>> ! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_8]] : !fir.ref<!fir.ptr<i64>> ! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_3]]#0 : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> !fir.ref<!fir.box<none>> @@ -330,3 +330,97 @@ end subroutine test11 ! CHECK: %[[VAL_14:.*]] = fir.box_addr %[[VAL_13]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32> ! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_14]] : !fir.ptr<i32> ! CHECK: fir.call @_QPsub2(%[[VAL_15]]) fastmath<contract> : (i32) -> () + +module test_mod + integer(8) :: cray_pointer + real :: cray_pointee + pointer(cray_pointer, cray_pointee) +end module + +subroutine test_hidden_pointer + ! Only the pointee is accessed, yet the pointer is needed + ! for lowering. + use test_mod, only : cray_pointee + call takes_real(cray_pointee) +end +! CHECK-LABEL: func.func @_QPtest_hidden_pointer() { +! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.ptr<f32>> +! CHECK: %[[VAL_1:.*]] = fir.address_of(@_QMtest_modEcray_pointer) : !fir.ref<i64> +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QMtest_modEcray_pointer"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMtest_modEcray_pointee"} : (!fir.ref<!fir.box<!fir.ptr<f32>>>) -> (!fir.ref<!fir.box<!fir.ptr<f32>>>, !fir.ref<!fir.box<!fir.ptr<f32>>>) +! CHECK: %[[VAL_4:.*]] = fir.zero_bits !fir.ptr<f32> +! CHECK: %[[VAL_5:.*]] = fir.embox %[[VAL_4]] : (!fir.ptr<f32>) -> !fir.box<!fir.ptr<f32>> +! CHECK: fir.store %[[VAL_5]] to %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.ptr<f32>>> +! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_2]]#0 : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<i64>> +! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_6]] : !fir.ref<!fir.ptr<i64>> +! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_3]]#0 : (!fir.ref<!fir.box<!fir.ptr<f32>>>) -> !fir.ref<!fir.box<none>> +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_7]] : (!fir.ptr<i64>) -> !fir.llvm_ptr<i8> +! CHECK: %[[VAL_10:.*]] = fir.call @_FortranAPointerAssociateScalar(%[[VAL_8]], %[[VAL_9]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.llvm_ptr<i8>) -> none +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.ptr<f32>>> +! CHECK: %[[VAL_12:.*]] = fir.box_addr %[[VAL_11]] : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32> +! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_12]] : (!fir.ptr<f32>) -> !fir.ref<f32> +! CHECK: fir.call @_QPtakes_real(%[[VAL_13]]) fastmath<contract> : (!fir.ref<f32>) -> () +! CHECK: return +! CHECK: } + + + +subroutine test_craypointer_capture(n) + integer :: n + character(n) :: cray_pointee + integer(8) :: cray_pointer + pointer(cray_pointer, cray_pointee) + call internal() + contains +subroutine internal() + call takes_character(cray_pointee) +end subroutine +end subroutine +! CHECK-LABEL: func.func @_QPtest_craypointer_capture( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.char<1,?>>> +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest_craypointer_captureEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = fir.alloca i64 {bindc_name = "cray_pointer", uniq_name = "_QFtest_craypointer_captureEcray_pointer"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFtest_craypointer_captureEcray_pointer"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_5:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_7:.*]] = arith.cmpi sgt, %[[VAL_5]], %[[VAL_6]] : i32 +! CHECK: %[[VAL_8:.*]] = arith.select %[[VAL_7]], %[[VAL_5]], %[[VAL_6]] : i32 +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_1]] typeparams %[[VAL_8]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_craypointer_captureEcray_pointee"} : (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, i32) -> (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>) +! CHECK: %[[VAL_10:.*]] = fir.zero_bits !fir.ptr<!fir.char<1,?>> +! CHECK: %[[VAL_11:.*]] = fir.embox %[[VAL_10]] typeparams %[[VAL_8]] : (!fir.ptr<!fir.char<1,?>>, i32) -> !fir.box<!fir.ptr<!fir.char<1,?>>> +! CHECK: fir.store %[[VAL_11]] to %[[VAL_9]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> +! CHECK: %[[VAL_12:.*]] = fir.alloca tuple<!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<i64>> +! CHECK: %[[VAL_13:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_14:.*]] = fir.coordinate_of %[[VAL_12]], %[[VAL_13]] : (!fir.ref<tuple<!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<i64>>>, i32) -> !fir.llvm_ptr<!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>> +! CHECK: fir.store %[[VAL_9]]#1 to %[[VAL_14]] : !fir.llvm_ptr<!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>> +! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_16:.*]] = fir.coordinate_of %[[VAL_12]], %[[VAL_15]] : (!fir.ref<tuple<!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<i64>>>, i32) -> !fir.llvm_ptr<!fir.ref<i64>> +! CHECK: fir.store %[[VAL_4]]#1 to %[[VAL_16]] : !fir.llvm_ptr<!fir.ref<i64>> +! CHECK: fir.call @_QFtest_craypointer_capturePinternal(%[[VAL_12]]) fastmath<contract> : (!fir.ref<tuple<!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<i64>>>) -> () +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func private @_QFtest_craypointer_capturePinternal( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<tuple<!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<i64>>> {fir.host_assoc}) +! CHECK: %[[VAL_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_2:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_1]] : (!fir.ref<tuple<!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<i64>>>, i32) -> !fir.llvm_ptr<!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>> +! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_2]] : !fir.llvm_ptr<!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>> +! CHECK: %[[VAL_4:.*]] = fir.load %[[VAL_3]] : !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> +! CHECK: %[[VAL_5:.*]] = fir.box_elesize %[[VAL_4]] : (!fir.box<!fir.ptr<!fir.char<1,?>>>) -> index +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_3]] typeparams %[[VAL_5]] {fortran_attrs = #fir.var_attrs<pointer, host_assoc>, uniq_name = "_QFtest_craypointer_captureEcray_pointee"} : (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, index) -> (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_7]] : (!fir.ref<tuple<!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>, !fir.ref<i64>>>, i32) -> !fir.llvm_ptr<!fir.ref<i64>> +! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_8]] : !fir.llvm_ptr<!fir.ref<i64>> +! CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %[[VAL_9]] {fortran_attrs = #fir.var_attrs<host_assoc>, uniq_name = "_QFtest_craypointer_captureEcray_pointer"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_10]]#0 : (!fir.ref<i64>) -> !fir.ref<!fir.ptr<i64>> +! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_11]] : !fir.ref<!fir.ptr<i64>> +! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_6]]#0 : (!fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>>) -> !fir.ref<!fir.box<none>> +! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_12]] : (!fir.ptr<i64>) -> !fir.llvm_ptr<i8> +! CHECK: %[[VAL_15:.*]] = fir.call @_FortranAPointerAssociateScalar(%[[VAL_13]], %[[VAL_14]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.llvm_ptr<i8>) -> none +! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.char<1,?>>>> +! CHECK: %[[VAL_17:.*]] = fir.box_addr %[[VAL_16]] : (!fir.box<!fir.ptr<!fir.char<1,?>>>) -> !fir.ptr<!fir.char<1,?>> +! CHECK: %[[VAL_18:.*]] = fir.emboxchar %[[VAL_17]], %[[VAL_5]] : (!fir.ptr<!fir.char<1,?>>, index) -> !fir.boxchar<1> +! CHECK: fir.call @_QPtakes_character(%[[VAL_18]]) fastmath<contract> : (!fir.boxchar<1>) -> () +! CHECK: return +! CHECK: } diff --git a/flang/test/Lower/HLFIR/designators-component-ref.f90 b/flang/test/Lower/HLFIR/designators-component-ref.f90 index 3e9fa037040d52863227c27cefc431a3ad06b2ee..392eda66fd03c1b753b0c4cbecac0cd674c249a5 100644 --- a/flang/test/Lower/HLFIR/designators-component-ref.f90 +++ b/flang/test/Lower/HLFIR/designators-component-ref.f90 @@ -1,5 +1,5 @@ ! Test lowering of component reference to HLFIR -! RUN: bbc -emit-hlfir --polymorphic-type -o - %s | FileCheck %s +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s module comp_ref type t1 integer :: scalar_i diff --git a/flang/test/Lower/HLFIR/designators-parameter-array-slice.f90 b/flang/test/Lower/HLFIR/designators-parameter-array-slice.f90 index 3bf19923453352ec827d7e0f340b16d4509483ea..42e130ee3f49c303db78e43b27caaf84377ba7bb 100644 --- a/flang/test/Lower/HLFIR/designators-parameter-array-slice.f90 +++ b/flang/test/Lower/HLFIR/designators-parameter-array-slice.f90 @@ -1,5 +1,5 @@ ! Test non-contiguous slice of parameter array. -! RUN: bbc -emit-hlfir --polymorphic-type -o - %s | FileCheck %s +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s subroutine test2(i) integer, parameter :: a(*,*) = reshape( [ 1,2,3,4 ], [ 2,2 ]) integer :: x(2) diff --git a/flang/test/Lower/HLFIR/elemental-array-ops.f90 b/flang/test/Lower/HLFIR/elemental-array-ops.f90 index 6984e5ef74c697058064a6a9c33bf7fe1d81e588..9778adeb6179a07eb2408b18aafba48f57b28d05 100644 --- a/flang/test/Lower/HLFIR/elemental-array-ops.f90 +++ b/flang/test/Lower/HLFIR/elemental-array-ops.f90 @@ -1,5 +1,5 @@ ! Test lowering of elemental intrinsic operations with array arguments to HLFIR -! RUN: bbc -emit-hlfir --polymorphic-type -I nowhere -o - %s 2>&1 | FileCheck %s +! RUN: bbc -emit-hlfir -I nowhere -o - %s 2>&1 | FileCheck %s subroutine binary(x, y) integer :: x(100), y(100) diff --git a/flang/test/Lower/HLFIR/elemental-polymorphic-merge.f90 b/flang/test/Lower/HLFIR/elemental-polymorphic-merge.f90 index c2f97b6fccfeb98ab2651ce42a91db797e680ee4..eb93099b3890fba98b545fcbf97fabfdf62fb51c 100644 --- a/flang/test/Lower/HLFIR/elemental-polymorphic-merge.f90 +++ b/flang/test/Lower/HLFIR/elemental-polymorphic-merge.f90 @@ -1,5 +1,5 @@ ! Test that the produced hlfir.elemental had proper result type and the mold. -! RUN: bbc --emit-hlfir --polymorphic-type -I nowhere -o - %s | FileCheck %s +! RUN: bbc --emit-hlfir -I nowhere -o - %s | FileCheck %s subroutine test_polymorphic_merge(x, y, r, m) type t diff --git a/flang/test/Lower/HLFIR/elemental-user-procedure-ref-polymorphic.f90 b/flang/test/Lower/HLFIR/elemental-user-procedure-ref-polymorphic.f90 index 1cd5c5133bd961acdaea0b357aadc283ad31ea10..84bb7a55377b89aa2d176a7f55821edf8d884bfe 100644 --- a/flang/test/Lower/HLFIR/elemental-user-procedure-ref-polymorphic.f90 +++ b/flang/test/Lower/HLFIR/elemental-user-procedure-ref-polymorphic.f90 @@ -1,6 +1,6 @@ ! Test lowering of user defined elemental procedure reference to HLFIR ! With polymorphic arguments. -! RUN: bbc -emit-hlfir -I nw -polymorphic-type -o - %s 2>&1 | FileCheck %s +! RUN: bbc -emit-hlfir -I nw -o - %s 2>&1 | FileCheck %s module def_some_types type :: t integer :: i diff --git a/flang/test/Lower/HLFIR/function-return-as-expr.f90 b/flang/test/Lower/HLFIR/function-return-as-expr.f90 index ae4f679a0fe6022b2b0c47bf43f8e61aaf516eee..95a0c090ef0433ece60fcc118ccd1528e8f0a33f 100644 --- a/flang/test/Lower/HLFIR/function-return-as-expr.f90 +++ b/flang/test/Lower/HLFIR/function-return-as-expr.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -emit-hlfir --polymorphic-type -o - %s -I nowhere 2>&1 | FileCheck %s +! RUN: bbc -emit-hlfir -o - %s -I nowhere 2>&1 | FileCheck %s module types type t1 diff --git a/flang/test/Lower/HLFIR/function-return-destroy.f90 b/flang/test/Lower/HLFIR/function-return-destroy.f90 index 4663dc57e0457f5d562a56ee646d318d77c1d7a6..5bd014981c128d168da151388b017c943a5047cf 100644 --- a/flang/test/Lower/HLFIR/function-return-destroy.f90 +++ b/flang/test/Lower/HLFIR/function-return-destroy.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -emit-hlfir -polymorphic-type %s -o - -I nowhere | FileCheck %s +! RUN: bbc -emit-hlfir %s -o - -I nowhere | FileCheck %s module types type t1 diff --git a/flang/test/Lower/HLFIR/ignore-rank-unlimited-polymorphic.f90 b/flang/test/Lower/HLFIR/ignore-rank-unlimited-polymorphic.f90 index 952e8f565eb93a1863165b62e13b107837238098..43986c8198b94388e4c9724e39957fbf35f873c1 100644 --- a/flang/test/Lower/HLFIR/ignore-rank-unlimited-polymorphic.f90 +++ b/flang/test/Lower/HLFIR/ignore-rank-unlimited-polymorphic.f90 @@ -1,6 +1,6 @@ ! Test passing mismatching rank arguments to unlimited polymorphic ! dummy with IGNORE_TKR(R). -! RUN: bbc -emit-hlfir -polymorphic-type -o - -I nowhere %s 2>&1 | FileCheck %s +! RUN: bbc -emit-hlfir -o - -I nowhere %s 2>&1 | FileCheck %s module m interface diff --git a/flang/test/Lower/HLFIR/ignore-type-assumed-shape.f90 b/flang/test/Lower/HLFIR/ignore-type-assumed-shape.f90 index 3ad74ced61a3b9a121285969f0046e01efb96b1f..27747ff2ad943d8ae93added766fd41bebca9230 100644 --- a/flang/test/Lower/HLFIR/ignore-type-assumed-shape.f90 +++ b/flang/test/Lower/HLFIR/ignore-type-assumed-shape.f90 @@ -2,7 +2,7 @@ ! dummy has IGNORE_TKR(t). The descriptor should be prepared ! according to the actual argument type, but its bounds and ! attributes should still be set as expected for the dummy. -! RUN: bbc -emit-hlfir --polymorphic-type -o - %s | FileCheck %s +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s module tkr_ifaces interface diff --git a/flang/test/Lower/HLFIR/intentout-allocatable-components.f90 b/flang/test/Lower/HLFIR/intentout-allocatable-components.f90 index 932fafd322a3e3a65489e2de1298837250c8772c..797e4c89ae2396b74670fcea72c36c501a225613 100644 --- a/flang/test/Lower/HLFIR/intentout-allocatable-components.f90 +++ b/flang/test/Lower/HLFIR/intentout-allocatable-components.f90 @@ -1,6 +1,6 @@ ! Test that allocatable components of non pointer/non allocatable INTENT(OUT) ! dummy arguments are deallocated. -! RUN: bbc -emit-hlfir -polymorphic-type %s -o - -I nowhere | FileCheck %s +! RUN: bbc -emit-hlfir %s -o - -I nowhere | FileCheck %s subroutine test_intentout_component_deallocate(a) type :: t diff --git a/flang/test/Lower/HLFIR/internal-procedures-polymorphic.f90 b/flang/test/Lower/HLFIR/internal-procedures-polymorphic.f90 index 8645488290d715b9eb63a37ccc28dbc7a6a34835..5763d84cfd605a783197047988bb267cd3b536ae 100644 --- a/flang/test/Lower/HLFIR/internal-procedures-polymorphic.f90 +++ b/flang/test/Lower/HLFIR/internal-procedures-polymorphic.f90 @@ -1,6 +1,6 @@ ! Test lowering of internal procedure capturing OPTIONAL polymorphic ! objects. -! RUN: bbc -emit-hlfir --polymorphic-type -o - %s -I nw | FileCheck %s +! RUN: bbc -emit-hlfir -o - %s -I nw | FileCheck %s module captured_optional_polymorphic diff --git a/flang/test/Lower/HLFIR/intrinsic-assumed-type.f90 b/flang/test/Lower/HLFIR/intrinsic-assumed-type.f90 index d0381344c89314cf42928e88bf3881789603b6c8..e82bc342ff88f6155dbb7fc3e748daeb41f30394 100644 --- a/flang/test/Lower/HLFIR/intrinsic-assumed-type.f90 +++ b/flang/test/Lower/HLFIR/intrinsic-assumed-type.f90 @@ -2,7 +2,7 @@ ! arguments. These are a bit special because semantics do not represent ! assumed types actual arguments with an evaluate::Expr like for usual ! arguments. -! RUN: bbc -emit-hlfir --polymorphic-type -o - %s | FileCheck %s +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s subroutine assumed_type_to_intrinsic(a) type(*) :: a(:) diff --git a/flang/test/Lower/HLFIR/parent-component-ref.f90 b/flang/test/Lower/HLFIR/parent-component-ref.f90 index b08d8f450e6d714d60fb754d3a70aec124788c5b..7d04ef3b40a65079dd003d6cfbe2575e5613ac9e 100644 --- a/flang/test/Lower/HLFIR/parent-component-ref.f90 +++ b/flang/test/Lower/HLFIR/parent-component-ref.f90 @@ -1,5 +1,5 @@ ! Test lowering of parent component references to HLFIR. -! RUN: bbc -emit-hlfir -polymorphic-type -o - %s -I nw | FileCheck %s +! RUN: bbc -emit-hlfir -o - %s -I nw | FileCheck %s module pc_types type t diff --git a/flang/test/Lower/HLFIR/poly_expr_for_nonpoly_dummy.f90 b/flang/test/Lower/HLFIR/poly_expr_for_nonpoly_dummy.f90 index ec5be37f551529e40e171adfc62dcd08c8960858..f5ec7c35594bdc9f9b8be97e7389df44bfa62c8e 100644 --- a/flang/test/Lower/HLFIR/poly_expr_for_nonpoly_dummy.f90 +++ b/flang/test/Lower/HLFIR/poly_expr_for_nonpoly_dummy.f90 @@ -1,6 +1,6 @@ ! Test passing polymorphic expression for non-polymorphic contiguous ! dummy argument: -! RUN: bbc -emit-hlfir --polymorphic-type -o - -I nowhere %s | FileCheck %s +! RUN: bbc -emit-hlfir -o - -I nowhere %s | FileCheck %s module types type t diff --git a/flang/test/Lower/HLFIR/polymorphic-expressions.f90 b/flang/test/Lower/HLFIR/polymorphic-expressions.f90 index 37e602895db395f0435217e10e02cbcea971c2f4..d6934e6ae6bd412781e172d0860fcbdc8c715c2e 100644 --- a/flang/test/Lower/HLFIR/polymorphic-expressions.f90 +++ b/flang/test/Lower/HLFIR/polymorphic-expressions.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -emit-hlfir --polymorphic-type -o - %s -I nowhere | FileCheck %s +! RUN: bbc -emit-hlfir -o - %s -I nowhere | FileCheck %s module polymorphic_expressions_types type t diff --git a/flang/test/Lower/HLFIR/proc-pointer-comp-nopass.f90 b/flang/test/Lower/HLFIR/proc-pointer-comp-nopass.f90 index ebb310f581c101fedf2e134870385fbda29c25f0..6f41f678dd84a7a293fc01d2049f87d1799a18cf 100644 --- a/flang/test/Lower/HLFIR/proc-pointer-comp-nopass.f90 +++ b/flang/test/Lower/HLFIR/proc-pointer-comp-nopass.f90 @@ -1,5 +1,5 @@ ! Test lowering of NOPASS procedure pointers components. -! RUN: bbc -emit-hlfir -polymorphic-type -o - %s | FileCheck %s +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s module proc_comp_defs interface diff --git a/flang/test/Lower/HLFIR/proc-pointer-comp-pass.f90 b/flang/test/Lower/HLFIR/proc-pointer-comp-pass.f90 index 25e4393f9dac7caeb33861b0432fcf2fd7046de4..247008e3a93df26337d296a2e11b2a641f5c621f 100644 --- a/flang/test/Lower/HLFIR/proc-pointer-comp-pass.f90 +++ b/flang/test/Lower/HLFIR/proc-pointer-comp-pass.f90 @@ -1,5 +1,5 @@ ! Test lowering of PASS procedure pointers components. -! RUN: bbc -emit-hlfir -polymorphic-type -o - %s | FileCheck %s +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s module m type t diff --git a/flang/test/Lower/HLFIR/procedure-pointer-component-structure-constructor.f90 b/flang/test/Lower/HLFIR/procedure-pointer-component-structure-constructor.f90 new file mode 100644 index 0000000000000000000000000000000000000000..7b64634d10d4b09f1de7992ba5c3a17bea98f037 --- /dev/null +++ b/flang/test/Lower/HLFIR/procedure-pointer-component-structure-constructor.f90 @@ -0,0 +1,71 @@ +! Test passing +! 1. NULL(), +! 2. procedure, +! 3. procedure pointer, +! 4. reference to a function that returns a procedure pointer. +! to a derived type structure constructor. +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s + + MODULE M + TYPE :: DT + PROCEDURE(Fun), POINTER, NOPASS :: pp1 + END TYPE + + CONTAINS + + INTEGER FUNCTION Fun(Arg) + INTEGER :: Arg + Fun = Arg + END FUNCTION + + END MODULE + + PROGRAM MAIN + USE M + IMPLICIT NONE + TYPE (DT), PARAMETER :: v1 = DT(NULL()) + TYPE (DT) :: v2 + PROCEDURE(FUN), POINTER :: pp2 + v2 = DT(fun) + v2 = DT(pp2) + v2 = DT(bar()) + CONTAINS + FUNCTION BAR() RESULT(res) + PROCEDURE(FUN), POINTER :: res + END + END + +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "main"} { +! CHECK: %[[VAL_0:.*]] = fir.alloca !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}> +! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}> +! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.boxproc<(!fir.ref<i32>) -> i32> {bindc_name = "pp2", uniq_name = "_QFEpp2"} +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFEpp2"} : (!fir.ref<!fir.boxproc<(!fir.ref<i32>) -> i32>>) -> (!fir.ref<!fir.boxproc<(!fir.ref<i32>) -> i32>>, !fir.ref<!fir.boxproc<(!fir.ref<i32>) -> i32>>) +! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>>) -> (!fir.ref<!fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>>, !fir.ref<!fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>>) +! CHECK: %[[VAL_23:.*]] = hlfir.designate %[[VAL_17]]#0{"pp1"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>>) -> !fir.ref<!fir.boxproc<(!fir.ref<i32>) -> i32>> +! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<!fir.boxproc<(!fir.ref<i32>) -> i32>> +! CHECK: fir.store %[[VAL_24]] to %[[VAL_23]] : !fir.ref<!fir.boxproc<(!fir.ref<i32>) -> i32>> +! CHECK: %[[VAL_25:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "ctor.temp"} : (!fir.ref<!fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>>) -> (!fir.ref<!fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>>, !fir.ref<!fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>>) +! CHECK: %[[VAL_31:.*]] = hlfir.designate %[[VAL_25]]#0{"pp1"} {fortran_attrs = #fir.var_attrs<pointer>} : (!fir.ref<!fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>>) -> !fir.ref<!fir.boxproc<(!fir.ref<i32>) -> i32>> +! CHECK: %[[VAL_32:.*]] = fir.call @_QFPbar() fastmath<contract> : () -> !fir.boxproc<(!fir.ref<i32>) -> i32> +! CHECK: fir.store %[[VAL_32]] to %[[VAL_31]] : !fir.ref<!fir.boxproc<(!fir.ref<i32>) -> i32>> +! CHECK: return +! CHECK: } + +! CHECK-LABEL: fir.global internal @_QFECv1 constant : !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}> { +! CHECK: %[[VAL_0:.*]] = fir.undefined !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}> +! CHECK: %[[VAL_1:.*]] = fir.field_index pp1, !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}> +! CHECK: %[[VAL_2:.*]] = fir.zero_bits (!fir.ref<i32>) -> i32 +! CHECK: %[[VAL_3:.*]] = fir.emboxproc %[[VAL_2]] : ((!fir.ref<i32>) -> i32) -> !fir.boxproc<(!fir.ref<i32>) -> i32> +! CHECK: %[[VAL_4:.*]] = fir.insert_value %[[VAL_0]], %[[VAL_3]], ["pp1", !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>] : (!fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>, !fir.boxproc<(!fir.ref<i32>) -> i32>) -> !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}> +! CHECK: fir.has_value %[[VAL_4]] : !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}> +! CHECK: } + +! CHECK-LABEL: fir.global internal @_QQro._QMmTdt.0 constant : !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}> { +! CHECK: %[[VAL_0:.*]] = fir.undefined !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}> +! CHECK: %[[VAL_1:.*]] = fir.field_index pp1, !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}> +! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QMmPfun) : (!fir.ref<i32>) -> i32 +! CHECK: %[[VAL_3:.*]] = fir.emboxproc %[[VAL_2]] : ((!fir.ref<i32>) -> i32) -> !fir.boxproc<() -> ()> +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (!fir.boxproc<() -> ()>) -> !fir.boxproc<(!fir.ref<i32>) -> i32> +! CHECK: %[[VAL_5:.*]] = fir.insert_value %[[VAL_0]], %[[VAL_4]], ["pp1", !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>] : (!fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}>, !fir.boxproc<(!fir.ref<i32>) -> i32>) -> !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}> +! CHECK: fir.has_value %[[VAL_5]] : !fir.type<_QMmTdt{pp1:!fir.boxproc<(!fir.ref<i32>) -> i32>}> +! CHECK: } diff --git a/flang/test/Lower/HLFIR/select-type-selector.f90 b/flang/test/Lower/HLFIR/select-type-selector.f90 index a9536c9ccee692f23d58e5a5e829253a18d5c8a5..256f003dcbf697b5dc011b588b65cb3544e317a1 100644 --- a/flang/test/Lower/HLFIR/select-type-selector.f90 +++ b/flang/test/Lower/HLFIR/select-type-selector.f90 @@ -14,7 +14,7 @@ ! (16.9.109) applied to the corresponding dimension of selector. The upper bound of each dimension is one less ! than the sum of the lower bound and the extent. -! RUN: bbc -emit-hlfir -polymorphic-type -I nowhere -o - %s | FileCheck %s +! RUN: bbc -emit-hlfir -I nowhere -o - %s | FileCheck %s subroutine test() type t diff --git a/flang/test/Lower/HLFIR/transpose.f90 b/flang/test/Lower/HLFIR/transpose.f90 index e63e1ec1d6890da08acb3fae0f6cb71d55023d85..e37e83c7a50112bee2c2f1f948c930e893e72624 100644 --- a/flang/test/Lower/HLFIR/transpose.f90 +++ b/flang/test/Lower/HLFIR/transpose.f90 @@ -1,5 +1,5 @@ ! Test lowering of TRANSPOSE intrinsic to HLFIR -! RUN: bbc -emit-hlfir --polymorphic-type -o - %s 2>&1 | FileCheck %s +! RUN: bbc -emit-hlfir -o - %s 2>&1 | FileCheck %s subroutine transpose1(m, res) integer :: m(1,2), res(2, 1) diff --git a/flang/test/Lower/HLFIR/type-bound-call-mismatch.f90 b/flang/test/Lower/HLFIR/type-bound-call-mismatch.f90 index 6794d11ece42d2664a9430415c2ad56566adc8ef..2e0c72ccfe0484fa3c365d6a243db4f8f6760317 100644 --- a/flang/test/Lower/HLFIR/type-bound-call-mismatch.f90 +++ b/flang/test/Lower/HLFIR/type-bound-call-mismatch.f90 @@ -1,6 +1,6 @@ ! Test interface that lowering handles small interface mismatch with ! type bound procedures. -! RUN: bbc -emit-hlfir --polymorphic-type %s -o - -I nw | FileCheck %s +! RUN: bbc -emit-hlfir %s -o - -I nw | FileCheck %s module dispatch_mismatch type t diff --git a/flang/test/Lower/HLFIR/vector-subscript-as-value.f90 b/flang/test/Lower/HLFIR/vector-subscript-as-value.f90 index d4026a37720f7501a5c395117eb1fc0bd118baef..ee8ded197c959295504447198d41fb5f9c4e872d 100644 --- a/flang/test/Lower/HLFIR/vector-subscript-as-value.f90 +++ b/flang/test/Lower/HLFIR/vector-subscript-as-value.f90 @@ -1,6 +1,6 @@ ! Test lowering of vector subscript designators outside of the ! assignment left-and side and input IO context. -! RUN: bbc -emit-hlfir -o - -I nw %s --polymorphic-type 2>&1 | FileCheck %s +! RUN: bbc -emit-hlfir -o - -I nw %s 2>&1 | FileCheck %s subroutine foo(x, y) integer :: x(100) diff --git a/flang/test/Lower/Intrinsics/c_ptr_eq_ne.f90 b/flang/test/Lower/Intrinsics/c_ptr_eq_ne.f90 new file mode 100644 index 0000000000000000000000000000000000000000..38468739ead5263277331298ad6619ee3674f1bd --- /dev/null +++ b/flang/test/Lower/Intrinsics/c_ptr_eq_ne.f90 @@ -0,0 +1,56 @@ +! Test C_PTR_EQ and C_PTR_NE lowering. +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s + +function test_c_ptr_eq(ptr1, ptr2) + use, intrinsic :: iso_c_binding + type(c_ptr), intent(in) :: ptr1, ptr2 + logical :: test_c_ptr_eq + test_c_ptr_eq = (ptr1 .eq. ptr2) +end + +! CHECK-LABEL: func.func @_QPtest_c_ptr_eq( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>> {fir.bindc_name = "ptr1"}, %[[ARG1:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>> {fir.bindc_name = "ptr2"}) -> !fir.logical<4> { +! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_c_ptr_eqEptr1"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) +! CHECK: %[[DECL_ARG1:.*]]:2 = hlfir.declare %[[ARG1]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_c_ptr_eqEptr2"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.logical<4> {bindc_name = "test_c_ptr_eq", uniq_name = "_QFtest_c_ptr_eqEtest_c_ptr_eq"} +! CHECK: %[[DECL_RET:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "_QFtest_c_ptr_eqEtest_c_ptr_eq"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[FIELD_ADDRESS:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> +! CHECK: %[[COORD_ADDRESS0:.*]] = fir.coordinate_of %[[DECL_ARG0]]#1, %[[FIELD_ADDRESS]] : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.field) -> !fir.ref<i64> +! CHECK: %[[ADDRESS0:.*]] = fir.load %[[COORD_ADDRESS0]] : !fir.ref<i64> +! CHECK: %[[FIELD_ADDRESS:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> +! CHECK: %[[COORD_ADDRESS1:.*]] = fir.coordinate_of %[[DECL_ARG1]]#1, %[[FIELD_ADDRESS]] : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.field) -> !fir.ref<i64> +! CHECK: %[[ADDRESS1:.*]] = fir.load %[[COORD_ADDRESS1]] : !fir.ref<i64> +! CHECK: %[[CMP:.*]] = arith.cmpi eq, %[[ADDRESS0]], %[[ADDRESS1]] : i64 +! CHECK: %[[RES:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4> +! CHECK: %[[NO_REASSOC_RES:.*]] = hlfir.no_reassoc %[[RES]] : !fir.logical<4> +! CHECK: hlfir.assign %[[NO_REASSOC_RES]] to %[[DECL_RET]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: %[[LOAD_RET:.*]] = fir.load %[[DECL_RET]]#1 : !fir.ref<!fir.logical<4>> +! CHECK: return %[[LOAD_RET]] : !fir.logical<4> +! CHECK: } + +function test_c_ptr_ne(ptr1, ptr2) + use, intrinsic :: iso_c_binding + type(c_ptr), intent(in) :: ptr1, ptr2 + logical :: test_c_ptr_ne + test_c_ptr_ne = (ptr1 .ne. ptr2) +end + +! CHECK-LABEL: func.func @_QPtest_c_ptr_ne( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>> {fir.bindc_name = "ptr1"}, %[[ARG1:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>> {fir.bindc_name = "ptr2"}) -> !fir.logical<4> { +! CHECK: %[[DECL_ARG0:.*]]:2 = hlfir.declare %[[ARG0]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_c_ptr_neEptr1"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) +! CHECK: %[[DECL_ARG1:.*]]:2 = hlfir.declare %[[ARG1]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_c_ptr_neEptr2"} : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) -> (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.logical<4> {bindc_name = "test_c_ptr_ne", uniq_name = "_QFtest_c_ptr_neEtest_c_ptr_ne"} +! CHECK: %[[DECL_RET:.*]]:2 = hlfir.declare %[[ALLOCA]] {uniq_name = "_QFtest_c_ptr_neEtest_c_ptr_ne"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[FIELD_ADDRESS:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> +! CHECK: %[[COORD_ADDRESS0:.*]] = fir.coordinate_of %[[DECL_ARG0]]#1, %[[FIELD_ADDRESS]] : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.field) -> !fir.ref<i64> +! CHECK: %[[ADDRESS0:.*]] = fir.load %[[COORD_ADDRESS0]] : !fir.ref<i64> +! CHECK: %[[FIELD_ADDRESS:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> +! CHECK: %[[COORD_ADDRESS1:.*]] = fir.coordinate_of %[[DECL_ARG1]]#1, %[[FIELD_ADDRESS]] : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.field) -> !fir.ref<i64> +! CHECK: %[[ADDRESS1:.*]] = fir.load %[[COORD_ADDRESS1]] : !fir.ref<i64> +! CHECK: %[[CMP:.*]] = arith.cmpi ne, %[[ADDRESS0]], %[[ADDRESS1]] : i64 +! CHECK: %[[RES:.*]] = fir.convert %[[CMP]] : (i1) -> !fir.logical<4> +! CHECK: %[[NO_REASSOC_RES:.*]] = hlfir.no_reassoc %[[RES]] : !fir.logical<4> +! CHECK: hlfir.assign %[[NO_REASSOC_RES]] to %[[DECL_RET]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: %[[LOAD_RET:.*]] = fir.load %[[DECL_RET]]#1 : !fir.ref<!fir.logical<4>> +! CHECK: return %[[LOAD_RET]] : !fir.logical<4> +! CHECK: } diff --git a/flang/test/Lower/Intrinsics/extends_type_of.f90 b/flang/test/Lower/Intrinsics/extends_type_of.f90 index b36d4e8b7c0d4e35d10bd6df85ad75463dcf91ea..f99a63e30a552d6c2db2ec3dca156f7a54e02595 100644 --- a/flang/test/Lower/Intrinsics/extends_type_of.f90 +++ b/flang/test/Lower/Intrinsics/extends_type_of.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -emit-fir -hlfir=false -polymorphic-type %s -o - | FileCheck %s +! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s module extends_type_of_mod diff --git a/flang/test/Lower/Intrinsics/fma_real16.f90 b/flang/test/Lower/Intrinsics/fma_real16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..62cf2fbcefbf190e41a8f2a0b64caf6cf0826f1d --- /dev/null +++ b/flang/test/Lower/Intrinsics/fma_real16.f90 @@ -0,0 +1,9 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranAFmaF128({{.*}}){{.*}}: (f128, f128, f128) -> f128 + use ieee_arithmetic, only: ieee_fma + real(16) :: x, y, z + x = ieee_fma(x, y, z) +end diff --git a/flang/test/Lower/Intrinsics/modulo.f90 b/flang/test/Lower/Intrinsics/modulo.f90 index 64a6607a09ccd5cff58d369ed5354c653b55a927..383cb34f83c705044ec91d2f0840604197eccdcd 100644 --- a/flang/test/Lower/Intrinsics/modulo.f90 +++ b/flang/test/Lower/Intrinsics/modulo.f90 @@ -3,36 +3,43 @@ ! CHECK-LABEL: func @_QPmodulo_testr( ! CHECK-SAME: %[[arg0:.*]]: !fir.ref<f64>{{.*}}, %[[arg1:.*]]: !fir.ref<f64>{{.*}}, %[[arg2:.*]]: !fir.ref<f64>{{.*}}) { subroutine modulo_testr(r, a, p) - real(8) :: r, a, p - ! CHECK-DAG: %[[a:.*]] = fir.load %[[arg1]] : !fir.ref<f64> - ! CHECK-DAG: %[[p:.*]] = fir.load %[[arg2]] : !fir.ref<f64> - ! CHECK-DAG: %[[rem:.*]] = arith.remf %[[a]], %[[p]] {{.*}}: f64 - ! CHECK-DAG: %[[zero:.*]] = arith.constant 0.000000e+00 : f64 - ! CHECK-DAG: %[[remNotZero:.*]] = arith.cmpf une, %[[rem]], %[[zero]] {{.*}} : f64 - ! CHECK-DAG: %[[aNeg:.*]] = arith.cmpf olt, %[[a]], %[[zero]] {{.*}} : f64 - ! CHECK-DAG: %[[pNeg:.*]] = arith.cmpf olt, %[[p]], %[[zero]] {{.*}} : f64 - ! CHECK-DAG: %[[signDifferent:.*]] = arith.xori %[[aNeg]], %[[pNeg]] : i1 - ! CHECK-DAG: %[[mustAddP:.*]] = arith.andi %[[remNotZero]], %[[signDifferent]] : i1 - ! CHECK-DAG: %[[remPlusP:.*]] = arith.addf %[[rem]], %[[p]] {{.*}}: f64 - ! CHECK: %[[res:.*]] = arith.select %[[mustAddP]], %[[remPlusP]], %[[rem]] : f64 - ! CHECK: fir.store %[[res]] to %[[arg0]] : !fir.ref<f64> - r = modulo(a, p) - end subroutine - - ! CHECK-LABEL: func @_QPmodulo_testi( - ! CHECK-SAME: %[[arg0:.*]]: !fir.ref<i64>{{.*}}, %[[arg1:.*]]: !fir.ref<i64>{{.*}}, %[[arg2:.*]]: !fir.ref<i64>{{.*}}) { - subroutine modulo_testi(r, a, p) - integer(8) :: r, a, p - ! CHECK-DAG: %[[a:.*]] = fir.load %[[arg1]] : !fir.ref<i64> - ! CHECK-DAG: %[[p:.*]] = fir.load %[[arg2]] : !fir.ref<i64> - ! CHECK-DAG: %[[rem:.*]] = arith.remsi %[[a]], %[[p]] : i64 - ! CHECK-DAG: %[[argXor:.*]] = arith.xori %[[a]], %[[p]] : i64 - ! CHECK-DAG: %[[signDifferent:.*]] = arith.cmpi slt, %[[argXor]], %c0{{.*}} : i64 - ! CHECK-DAG: %[[remNotZero:.*]] = arith.cmpi ne, %[[rem]], %c0{{.*}} : i64 - ! CHECK-DAG: %[[mustAddP:.*]] = arith.andi %[[remNotZero]], %[[signDifferent]] : i1 - ! CHECK-DAG: %[[remPlusP:.*]] = arith.addi %[[rem]], %[[p]] : i64 - ! CHECK: %[[res:.*]] = arith.select %[[mustAddP]], %[[remPlusP]], %[[rem]] : i64 - ! CHECK: fir.store %[[res]] to %[[arg0]] : !fir.ref<i64> - r = modulo(a, p) - end subroutine + real(8) :: r, a, p + ! CHECK-DAG: %[[a:.*]] = fir.load %[[arg1]] : !fir.ref<f64> + ! CHECK-DAG: %[[p:.*]] = fir.load %[[arg2]] : !fir.ref<f64> + ! CHECK-DAG: %[[rem:.*]] = arith.remf %[[a]], %[[p]] {{.*}}: f64 + ! CHECK-DAG: %[[zero:.*]] = arith.constant 0.000000e+00 : f64 + ! CHECK-DAG: %[[remNotZero:.*]] = arith.cmpf une, %[[rem]], %[[zero]] {{.*}} : f64 + ! CHECK-DAG: %[[aNeg:.*]] = arith.cmpf olt, %[[a]], %[[zero]] {{.*}} : f64 + ! CHECK-DAG: %[[pNeg:.*]] = arith.cmpf olt, %[[p]], %[[zero]] {{.*}} : f64 + ! CHECK-DAG: %[[signDifferent:.*]] = arith.xori %[[aNeg]], %[[pNeg]] : i1 + ! CHECK-DAG: %[[mustAddP:.*]] = arith.andi %[[remNotZero]], %[[signDifferent]] : i1 + ! CHECK-DAG: %[[remPlusP:.*]] = arith.addf %[[rem]], %[[p]] {{.*}}: f64 + ! CHECK: %[[res:.*]] = arith.select %[[mustAddP]], %[[remPlusP]], %[[rem]] : f64 + ! CHECK: fir.store %[[res]] to %[[arg0]] : !fir.ref<f64> + r = modulo(a, p) +end subroutine +! CHECK-LABEL: func @_QPmodulo_testi( +! CHECK-SAME: %[[arg0:.*]]: !fir.ref<i64>{{.*}}, %[[arg1:.*]]: !fir.ref<i64>{{.*}}, %[[arg2:.*]]: !fir.ref<i64>{{.*}}) { +subroutine modulo_testi(r, a, p) + integer(8) :: r, a, p + ! CHECK-DAG: %[[a:.*]] = fir.load %[[arg1]] : !fir.ref<i64> + ! CHECK-DAG: %[[p:.*]] = fir.load %[[arg2]] : !fir.ref<i64> + ! CHECK-DAG: %[[rem:.*]] = arith.remsi %[[a]], %[[p]] : i64 + ! CHECK-DAG: %[[argXor:.*]] = arith.xori %[[a]], %[[p]] : i64 + ! CHECK-DAG: %[[signDifferent:.*]] = arith.cmpi slt, %[[argXor]], %c0{{.*}} : i64 + ! CHECK-DAG: %[[remNotZero:.*]] = arith.cmpi ne, %[[rem]], %c0{{.*}} : i64 + ! CHECK-DAG: %[[mustAddP:.*]] = arith.andi %[[remNotZero]], %[[signDifferent]] : i1 + ! CHECK-DAG: %[[remPlusP:.*]] = arith.addi %[[rem]], %[[p]] : i64 + ! CHECK: %[[res:.*]] = arith.select %[[mustAddP]], %[[remPlusP]], %[[rem]] : i64 + ! CHECK: fir.store %[[res]] to %[[arg0]] : !fir.ref<i64> + r = modulo(a, p) +end subroutine + +! CHECK-LABEL: func @_QPmodulo_testr16( +! CHECK-SAME: %[[arg0:.*]]: !fir.ref<f128>{{.*}}, %[[arg1:.*]]: !fir.ref<f128>{{.*}}, %[[arg2:.*]]: !fir.ref<f128>{{.*}}) { +subroutine modulo_testr16(r, a, p) + real(16) :: r, a, p + ! CHECK: fir.call @_FortranAModuloReal16({{.*}}){{.*}}: (f128, f128, !fir.ref<i8>, i32) -> f128 + r = modulo(a, p) +end subroutine diff --git a/flang/test/Lower/Intrinsics/random_number_real16.f90 b/flang/test/Lower/Intrinsics/random_number_real16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..76fed258d8afc85c62312ee345a7110c076730fe --- /dev/null +++ b/flang/test/Lower/Intrinsics/random_number_real16.f90 @@ -0,0 +1,16 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK-LABEL: func @_QPtest_scalar +! CHECK: fir.call @_FortranARandomNumber16({{.*}}){{.*}}: (!fir.box<none>, !fir.ref<i8>, i32) -> none +subroutine test_scalar + real(16) :: r + call random_number(r) +end + +! CHECK-LABEL: func @_QPtest_array +! CHECK: fir.call @_FortranARandomNumber16({{.*}}){{.*}}: (!fir.box<none>, !fir.ref<i8>, i32) -> none +subroutine test_array(r) + real(16) :: r(:) + call random_number(r) +end diff --git a/flang/test/Lower/Intrinsics/same_type_as.f90 b/flang/test/Lower/Intrinsics/same_type_as.f90 index e1333024927d546aaa1dd0dcc2cb403047865d9c..e0fda563f08bb13f9efa5fa823d42dd25cd08e7d 100644 --- a/flang/test/Lower/Intrinsics/same_type_as.f90 +++ b/flang/test/Lower/Intrinsics/same_type_as.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -emit-fir -hlfir=false -polymorphic-type %s -o - | FileCheck %s +! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s module same_type_as_mod diff --git a/flang/test/Lower/Intrinsics/sizeof.f90 b/flang/test/Lower/Intrinsics/sizeof.f90 index 959ca1692b5144cc892be6a73dcdf2d9a4a71f91..e10cb79981a6920786d8259b7604f3b9c9e3459c 100644 --- a/flang/test/Lower/Intrinsics/sizeof.f90 +++ b/flang/test/Lower/Intrinsics/sizeof.f90 @@ -1,5 +1,5 @@ ! Test SIZEOF lowering for polymorphic entities. -! RUN: bbc -emit-hlfir --polymorphic-type -o - %s | FileCheck %s +! RUN: bbc -emit-hlfir -o - %s | FileCheck %s integer(8) function test1(x) class(*) :: x diff --git a/flang/test/Lower/Intrinsics/spread.f90 b/flang/test/Lower/Intrinsics/spread.f90 index 4cd823d837453939eac5ebbe1afb280fbe84b54a..d58725aba698744248d77b069fbf467a83f6d6be 100644 --- a/flang/test/Lower/Intrinsics/spread.f90 +++ b/flang/test/Lower/Intrinsics/spread.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -emit-fir -hlfir=false -polymorphic-type %s -o - | FileCheck %s +! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s module spread_mod diff --git a/flang/test/Lower/Intrinsics/storage_size.f90 b/flang/test/Lower/Intrinsics/storage_size.f90 index 668322f45bd85121a54857bb242aa4259adfd41f..b0c9d51f953286b293762d6337afee2012b88b85 100644 --- a/flang/test/Lower/Intrinsics/storage_size.f90 +++ b/flang/test/Lower/Intrinsics/storage_size.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -emit-fir -hlfir=false -polymorphic-type %s -o - | FileCheck %s +! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s module storage_size_test type :: p1 diff --git a/flang/test/Lower/OpenACC/acc-bounds.f90 b/flang/test/Lower/OpenACC/acc-bounds.f90 index df97cbcd187d2b1fe49124d9afa210d727b9867e..c275d4f1b1d5f28a58db1a62edad6cafaf27f169 100644 --- a/flang/test/Lower/OpenACC/acc-bounds.f90 +++ b/flang/test/Lower/OpenACC/acc-bounds.f90 @@ -184,7 +184,7 @@ contains ! CHECK: fir.result %c0{{.*}} : index ! CHECK: } ! CHECK: %[[BOUNDS:.*]] = acc.bounds lowerbound(%c0{{.*}} : index) upperbound(%{{.*}} : index) extent(%{{.*}} : index) stride(%[[STRIDE]] : index) startIdx(%c1 : index) {strideInBytes = true} -! CHECK: %[[NOCREATE:.*]] = acc.nocreate varPtr(%[[DECL_A]]#1 : !fir.ref<!fir.array<?xf32>>) bounds(%14) -> !fir.ref<!fir.array<?xf32>> {name = "a(1:n)"} +! CHECK: %[[NOCREATE:.*]] = acc.nocreate varPtr(%[[DECL_A]]#1 : !fir.ref<!fir.array<?xf32>>) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<?xf32>> {name = "a(1:n)"} ! CHECK: acc.data dataOperands(%[[NOCREATE]] : !fir.ref<!fir.array<?xf32>>) { end module diff --git a/flang/test/Lower/OpenACC/acc-enter-data.f90 b/flang/test/Lower/OpenACC/acc-enter-data.f90 index 2cf50c1b62f19006ec3b28991ae5e5523f3250f4..251edbf9c2dd0ae47f118eb7448bde0b07fa94a9 100644 --- a/flang/test/Lower/OpenACC/acc-enter-data.f90 +++ b/flang/test/Lower/OpenACC/acc-enter-data.f90 @@ -234,11 +234,13 @@ subroutine acc_enter_data_dummy(a, b, n, m) !$acc enter data create(b(n:m)) !CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLB]]#0, %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) !CHECK: %[[LOAD_N:.*]] = fir.load %[[DECLN]]#0 : !fir.ref<i32> -!CHECK: %[[N_CONV:.*]] = fir.convert %[[LOAD_N]] : (i32) -> index -!CHECK: %[[LB:.*]] = arith.subi %[[N_CONV]], %[[N_IDX]] : index +!CHECK: %[[N_CONV1:.*]] = fir.convert %[[LOAD_N]] : (i32) -> i64 +!CHECK: %[[N_CONV2:.*]] = fir.convert %[[N_CONV1]] : (i64) -> index +!CHECK: %[[LB:.*]] = arith.subi %[[N_CONV2]], %[[N_IDX]] : index !CHECK: %[[LOAD_M:.*]] = fir.load %[[DECLM]]#0 : !fir.ref<i32> -!CHECK: %[[M_CONV:.*]] = fir.convert %[[LOAD_M]] : (i32) -> index -!CHECK: %[[UB:.*]] = arith.subi %[[M_CONV]], %[[N_IDX]] : index +!CHECK: %[[M_CONV1:.*]] = fir.convert %[[LOAD_M]] : (i32) -> i64 +!CHECK: %[[M_CONV2:.*]] = fir.convert %[[M_CONV1]] : (i64) -> index +!CHECK: %[[UB:.*]] = arith.subi %[[M_CONV2]], %[[N_IDX]] : index !CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[EXT_B]] : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[N_IDX]] : index) {strideInBytes = true} !CHECK: %[[ADDR:.*]] = fir.box_addr %[[DECLB]]#0 : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>> !CHECK: %[[CREATE1:.*]] = acc.create varPtr(%[[ADDR]] : !fir.ref<!fir.array<?xf32>>) bounds(%[[BOUND1]]) -> !fir.ref<!fir.array<?xf32>> {name = "b(n:m)", structured = false} @@ -248,8 +250,9 @@ subroutine acc_enter_data_dummy(a, b, n, m) !CHECK: %[[ONE:.*]] = arith.constant 1 : index !CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLB]]#0, %c0_8 : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) !CHECK: %[[LOAD_N:.*]] = fir.load %[[DECLN]]#0 : !fir.ref<i32> -!CHECK: %[[CONVERT_N:.*]] = fir.convert %[[LOAD_N]] : (i32) -> index -!CHECK: %[[LB:.*]] = arith.subi %[[CONVERT_N]], %[[N_IDX]] : index +!CHECK: %[[CONVERT1_N:.*]] = fir.convert %[[LOAD_N]] : (i32) -> i64 +!CHECK: %[[CONVERT2_N:.*]] = fir.convert %[[CONVERT1_N]] : (i64) -> index +!CHECK: %[[LB:.*]] = arith.subi %[[CONVERT2_N]], %[[N_IDX]] : index !CHECK: %[[UB:.*]] = arith.subi %[[EXT_B]], %c1{{.*}} : index !CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[EXT_B]] : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[N_IDX]] : index) {strideInBytes = true} !CHECK: %[[ADDR:.*]] = fir.box_addr %[[DECLB]]#0 : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>> @@ -424,8 +427,9 @@ subroutine acc_enter_data_assumed(a, b, n, m) !CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLA]]#0, %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) !CHECK: %[[LOAD_N:.*]] = fir.load %[[DECLN]]#0 : !fir.ref<i32> -!CHECK: %[[CONVERT_N:.*]] = fir.convert %[[LOAD_N]] : (i32) -> index -!CHECK: %[[LB:.*]] = arith.subi %[[CONVERT_N]], %[[ONE]] : index +!CHECK: %[[CONVERT1_N:.*]] = fir.convert %[[LOAD_N]] : (i32) -> i64 +!CHECK: %[[CONVERT2_N:.*]] = fir.convert %[[CONVERT1_N]] : (i64) -> index +!CHECK: %[[LB:.*]] = arith.subi %[[CONVERT2_N]], %[[ONE]] : index !CHECK: %[[C0:.*]] = arith.constant 0 : index !CHECK: %[[DIMS:.*]]:3 = fir.box_dims %[[DECLA]]#1, %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) @@ -444,8 +448,9 @@ subroutine acc_enter_data_assumed(a, b, n, m) !CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLA]]#0, %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) !CHECK: %[[LOAD_M:.*]] = fir.load %[[DECLM]]#0 : !fir.ref<i32> -!CHECK: %[[CONVERT_M:.*]] = fir.convert %[[LOAD_M]] : (i32) -> index -!CHECK: %[[UB:.*]] = arith.subi %[[CONVERT_M]], %[[ONE]] : index +!CHECK: %[[CONVERT1_M:.*]] = fir.convert %[[LOAD_M]] : (i32) -> i64 +!CHECK: %[[CONVERT2_M:.*]] = fir.convert %[[CONVERT1_M]] : (i64) -> index +!CHECK: %[[UB:.*]] = arith.subi %[[CONVERT2_M]], %[[ONE]] : index !CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[DECLA]]#1, %{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) !CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[BASELB]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[ONE]] : index) {strideInBytes = true} @@ -460,12 +465,14 @@ subroutine acc_enter_data_assumed(a, b, n, m) !CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLA]]#0, %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) !CHECK: %[[LOAD_N:.*]] = fir.load %[[DECLN]]#0 : !fir.ref<i32> -!CHECK: %[[CONVERT_N:.*]] = fir.convert %[[LOAD_N]] : (i32) -> index -!CHECK: %[[LB:.*]] = arith.subi %[[CONVERT_N]], %[[ONE]] : index +!CHECK: %[[CONVERT1_N:.*]] = fir.convert %[[LOAD_N]] : (i32) -> i64 +!CHECK: %[[CONVERT2_N:.*]] = fir.convert %[[CONVERT1_N]] : (i64) -> index +!CHECK: %[[LB:.*]] = arith.subi %[[CONVERT2_N]], %[[ONE]] : index !CHECK: %[[LOAD_M:.*]] = fir.load %[[DECLM]]#0 : !fir.ref<i32> -!CHECK: %[[CONVERT_M:.*]] = fir.convert %[[LOAD_M]] : (i32) -> index -!CHECK: %[[UB:.*]] = arith.subi %[[CONVERT_M]], %[[ONE]] : index +!CHECK: %[[CONVERT1_M:.*]] = fir.convert %[[LOAD_M]] : (i32) -> i64 +!CHECK: %[[CONVERT2_M:.*]] = fir.convert %[[CONVERT1_M]] : (i64) -> index +!CHECK: %[[UB:.*]] = arith.subi %[[CONVERT2_M]], %[[ONE]] : index !CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[DECLA]]#1, %{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) !CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[ONE]] : index) {strideInBytes = true} @@ -480,8 +487,9 @@ subroutine acc_enter_data_assumed(a, b, n, m) !CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLB]]#0, %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) !CHECK: %[[LOAD_M:.*]] = fir.load %[[DECLM]]#0 : !fir.ref<i32> -!CHECK: %[[CONVERT_M:.*]] = fir.convert %[[LOAD_M]] : (i32) -> index -!CHECK: %[[UB:.*]] = arith.subi %[[CONVERT_M]], %[[LB_C10_IDX]] : index +!CHECK: %[[CONVERT1_M:.*]] = fir.convert %[[LOAD_M]] : (i32) -> i64 +!CHECK: %[[CONVERT2_M:.*]] = fir.convert %[[CONVERT1_M]] : (i64) -> index +!CHECK: %[[UB:.*]] = arith.subi %[[CONVERT2_M]], %[[LB_C10_IDX]] : index !CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[DECLB]]#1, %{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index) !CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[ZERO]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[LB_C10_IDX]] : index) {strideInBytes = true} diff --git a/flang/test/Lower/OpenACC/acc-kernels-loop.f90 b/flang/test/Lower/OpenACC/acc-kernels-loop.f90 index e85065e54bc362a8540fe435a9b34db07e8fbe8a..e5791f0e5b3921b5017043c2f764c3fc1ad4f4d6 100644 --- a/flang/test/Lower/OpenACC/acc-kernels-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-kernels-loop.f90 @@ -37,13 +37,27 @@ subroutine acc_kernels_loop ! CHECK: %[[IFCONDITION:.*]] = fir.address_of(@{{.*}}ifcondition) : !fir.ref<!fir.logical<4>> ! CHECK: %[[DECLIFCONDITION:.*]]:2 = hlfir.declare %[[IFCONDITION]] - !$acc kernels loop + !$acc kernels + !$acc loop DO i = 1, n a(i) = b(i) END DO + !$acc end kernels ! CHECK: acc.kernels { -! CHECK: acc.loop {{.*}} { +! CHECK: acc.loop private{{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.terminator +! CHECK-NEXT: }{{$}} + + !$acc kernels loop + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.kernels combined(loop) { +! CHECK: acc.loop combined(kernels) private{{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.terminator @@ -55,7 +69,7 @@ subroutine acc_kernels_loop END DO !$acc end kernels loop -! CHECK: acc.kernels { +! CHECK: acc.kernels {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -68,7 +82,7 @@ subroutine acc_kernels_loop END DO ! CHECK: [[ASYNC1:%.*]] = arith.constant 1 : i32 -! CHECK: acc.kernels async([[ASYNC1]] : i32) { +! CHECK: acc.kernels {{.*}} async([[ASYNC1]] : i32) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -81,7 +95,7 @@ subroutine acc_kernels_loop END DO ! CHECK: [[ASYNC2:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK: acc.kernels async([[ASYNC2]] : i32) { +! CHECK: acc.kernels {{.*}} async([[ASYNC2]] : i32) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -93,7 +107,7 @@ subroutine acc_kernels_loop a(i) = b(i) END DO -! CHECK: acc.kernels wait { +! CHECK: acc.kernels {{.*}} wait { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -106,7 +120,7 @@ subroutine acc_kernels_loop END DO ! CHECK: [[WAIT1:%.*]] = arith.constant 1 : i32 -! CHECK: acc.kernels wait({[[WAIT1]] : i32}) { +! CHECK: acc.kernels {{.*}} wait({[[WAIT1]] : i32}) { ! CHECK: acc.loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -120,7 +134,7 @@ subroutine acc_kernels_loop ! CHECK: [[WAIT2:%.*]] = arith.constant 1 : i32 ! CHECK: [[WAIT3:%.*]] = arith.constant 2 : i32 -! CHECK: acc.kernels wait({[[WAIT2]] : i32, [[WAIT3]] : i32}) { +! CHECK: acc.kernels {{.*}} wait({[[WAIT2]] : i32, [[WAIT3]] : i32}) { ! CHECK: acc.loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -134,7 +148,7 @@ subroutine acc_kernels_loop ! CHECK: [[WAIT4:%.*]] = fir.load %{{.*}} : !fir.ref<i32> ! CHECK: [[WAIT5:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK: acc.kernels wait({[[WAIT4]] : i32, [[WAIT5]] : i32}) { +! CHECK: acc.kernels {{.*}} wait({[[WAIT4]] : i32, [[WAIT5]] : i32}) { ! CHECK: acc.loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -147,7 +161,7 @@ subroutine acc_kernels_loop END DO ! CHECK: [[NUMGANGS1:%.*]] = arith.constant 1 : i32 -! CHECK: acc.kernels num_gangs({[[NUMGANGS1]] : i32}) { +! CHECK: acc.kernels {{.*}} num_gangs({[[NUMGANGS1]] : i32}) { ! CHECK: acc.loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -160,7 +174,7 @@ subroutine acc_kernels_loop END DO ! CHECK: [[NUMGANGS2:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK: acc.kernels num_gangs({[[NUMGANGS2]] : i32}) { +! CHECK: acc.kernels {{.*}} num_gangs({[[NUMGANGS2]] : i32}) { ! CHECK: acc.loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -173,7 +187,7 @@ subroutine acc_kernels_loop END DO ! CHECK: [[NUMWORKERS1:%.*]] = arith.constant 10 : i32 -! CHECK: acc.kernels num_workers([[NUMWORKERS1]] : i32) { +! CHECK: acc.kernels {{.*}} num_workers([[NUMWORKERS1]] : i32) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -186,7 +200,7 @@ subroutine acc_kernels_loop END DO ! CHECK: [[NUMWORKERS2:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK: acc.kernels num_workers([[NUMWORKERS2]] : i32) { +! CHECK: acc.kernels {{.*}} num_workers([[NUMWORKERS2]] : i32) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -199,7 +213,7 @@ subroutine acc_kernels_loop END DO ! CHECK: [[VECTORLENGTH1:%.*]] = arith.constant 128 : i32 -! CHECK: acc.kernels vector_length([[VECTORLENGTH1]] : i32) { +! CHECK: acc.kernels {{.*}} vector_length([[VECTORLENGTH1]] : i32) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -212,7 +226,7 @@ subroutine acc_kernels_loop END DO ! CHECK: [[VECTORLENGTH2:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK: acc.kernels vector_length([[VECTORLENGTH2]] : i32) { +! CHECK: acc.kernels {{.*}} vector_length([[VECTORLENGTH2]] : i32) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -225,7 +239,7 @@ subroutine acc_kernels_loop END DO ! CHECK: [[IF1:%.*]] = arith.constant true -! CHECK: acc.kernels if([[IF1]]) { +! CHECK: acc.kernels {{.*}} if([[IF1]]) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -239,7 +253,7 @@ subroutine acc_kernels_loop ! CHECK: [[IFCOND:%.*]] = fir.load %{{.*}} : !fir.ref<!fir.logical<4>> ! CHECK: [[IF2:%.*]] = fir.convert [[IFCOND]] : (!fir.logical<4>) -> i1 -! CHECK: acc.kernels if([[IF2]]) { +! CHECK: acc.kernels {{.*}} if([[IF2]]) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -252,7 +266,7 @@ subroutine acc_kernels_loop END DO ! CHECK: [[SELF1:%.*]] = arith.constant true -! CHECK: acc.kernels self([[SELF1]]) { +! CHECK: acc.kernels {{.*}} self([[SELF1]]) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -264,7 +278,7 @@ subroutine acc_kernels_loop a(i) = b(i) END DO -! CHECK: acc.kernels { +! CHECK: acc.kernels {{.*}}{ ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -278,7 +292,7 @@ subroutine acc_kernels_loop ! CHECK: %[[SELF2:.*]] = fir.convert %[[DECLIFCONDITION]]#1 : (!fir.ref<!fir.logical<4>>) -> i1 -! CHECK: acc.kernels self(%[[SELF2]]) { +! CHECK: acc.kernels {{.*}} self(%[[SELF2]]) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -293,7 +307,7 @@ subroutine acc_kernels_loop ! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, name = "a"} ! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, name = "b"} -! CHECK: acc.kernels dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.kernels {{.*}} dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -309,7 +323,7 @@ subroutine acc_kernels_loop ! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, name = "a"} ! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, name = "b"} -! CHECK: acc.kernels dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.kernels {{.*}} dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -325,7 +339,7 @@ subroutine acc_kernels_loop ! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"} ! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copyin_readonly>, name = "b"} -! CHECK: acc.kernels dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.kernels {{.*}} dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -339,7 +353,7 @@ subroutine acc_kernels_loop ! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "a"} ! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "b"} -! CHECK: acc.kernels dataOperands(%[[CREATE_A]], %[[CREATE_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.kernels {{.*}} dataOperands(%[[CREATE_A]], %[[CREATE_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -355,7 +369,7 @@ subroutine acc_kernels_loop ! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"} ! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_create_zero>, name = "a"} -! CHECK: acc.kernels dataOperands(%[[CREATE_B]], %[[CREATE_A]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.kernels {{.*}} dataOperands(%[[CREATE_B]], %[[CREATE_A]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -371,7 +385,7 @@ subroutine acc_kernels_loop ! CHECK: %[[NOCREATE_A:.*]] = acc.nocreate varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"} ! CHECK: %[[NOCREATE_B:.*]] = acc.nocreate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"} -! CHECK: acc.kernels dataOperands(%[[NOCREATE_A]], %[[NOCREATE_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.kernels {{.*}} dataOperands(%[[NOCREATE_A]], %[[NOCREATE_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -385,7 +399,7 @@ subroutine acc_kernels_loop ! CHECK: %[[PRESENT_A:.*]] = acc.present varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"} ! CHECK: %[[PRESENT_B:.*]] = acc.present varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"} -! CHECK: acc.kernels dataOperands(%[[PRESENT_A]], %[[PRESENT_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.kernels {{.*}} dataOperands(%[[PRESENT_A]], %[[PRESENT_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -399,7 +413,7 @@ subroutine acc_kernels_loop ! CHECK: %[[DEVICEPTR_A:.*]] = acc.deviceptr varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"} ! CHECK: %[[DEVICEPTR_B:.*]] = acc.deviceptr varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"} -! CHECK: acc.kernels dataOperands(%[[DEVICEPTR_A]], %[[DEVICEPTR_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.kernels {{.*}} dataOperands(%[[DEVICEPTR_A]], %[[DEVICEPTR_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -417,7 +431,7 @@ subroutine acc_kernels_loop ! CHECK: %[[BOX_G:.*]] = fir.load %[[DECLG]]#0 : !fir.ref<!fir.box<!fir.ptr<f32>>> ! CHECK: %[[BOX_ADDR_G:.*]] = fir.box_addr %[[BOX_G]] : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32> ! CHECK: %[[ATTACH_G:.*]] = acc.attach varPtr(%[[BOX_ADDR_G]] : !fir.ptr<f32>) -> !fir.ptr<f32> {name = "g"} -! CHECK: acc.kernels dataOperands(%[[ATTACH_F]], %[[ATTACH_G]] : !fir.ptr<f32>, !fir.ptr<f32>) { +! CHECK: acc.kernels {{.*}} dataOperands(%[[ATTACH_F]], %[[ATTACH_G]] : !fir.ptr<f32>, !fir.ptr<f32>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -429,7 +443,7 @@ subroutine acc_kernels_loop a(i) = b(i) END DO -! CHECK: acc.kernels { +! CHECK: acc.kernels {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]} @@ -441,7 +455,7 @@ subroutine acc_kernels_loop a(i) = b(i) END DO -! CHECK: acc.kernels { +! CHECK: acc.kernels {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {auto_ = [#acc.device_type<none>], inclusiveUpperbound = array<i1: true>} @@ -453,7 +467,7 @@ subroutine acc_kernels_loop a(i) = b(i) END DO -! CHECK: acc.kernels { +! CHECK: acc.kernels {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} @@ -465,8 +479,8 @@ subroutine acc_kernels_loop a(i) = b(i) END DO -! CHECK: acc.kernels { -! CHECK: acc.loop gang {{.*}} { +! CHECK: acc.kernels {{.*}} { +! CHECK: acc.loop {{.*}} gang {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>}{{$}} ! CHECK: acc.terminator @@ -477,9 +491,9 @@ subroutine acc_kernels_loop a(i) = b(i) END DO -! CHECK: acc.kernels { +! CHECK: acc.kernels {{.*}} { ! CHECK: [[GANGNUM1:%.*]] = arith.constant 8 : i32 -! CHECK-NEXT: acc.loop gang({num=[[GANGNUM1]] : i32}) {{.*}} { +! CHECK-NEXT: acc.loop {{.*}} gang({num=[[GANGNUM1]] : i32}) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.terminator @@ -490,9 +504,9 @@ subroutine acc_kernels_loop a(i) = b(i) END DO -! CHECK: acc.kernels { +! CHECK: acc.kernels {{.*}} { ! CHECK: [[GANGNUM2:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK-NEXT: acc.loop gang({num=[[GANGNUM2]] : i32}) {{.*}} { +! CHECK-NEXT: acc.loop {{.*}} gang({num=[[GANGNUM2]] : i32}) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.terminator @@ -503,8 +517,8 @@ subroutine acc_kernels_loop a(i) = b(i) END DO -! CHECK: acc.kernels { -! CHECK: acc.loop gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) +! CHECK: acc.kernels {{.*}} { +! CHECK: acc.loop {{.*}} gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.terminator @@ -514,8 +528,9 @@ subroutine acc_kernels_loop DO i = 1, n a(i) = b(i) END DO -! CHECK: acc.kernels { -! CHECK: acc.loop vector {{.*}} { + +! CHECK: acc.kernels {{.*}} { +! CHECK: acc.loop {{.*}} vector {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>}{{$}} ! CHECK: acc.terminator @@ -526,9 +541,9 @@ subroutine acc_kernels_loop a(i) = b(i) END DO -! CHECK: acc.kernels { +! CHECK: acc.kernels {{.*}} { ! CHECK: [[CONSTANT128:%.*]] = arith.constant 128 : i32 -! CHECK: acc.loop vector([[CONSTANT128]] : i32) {{.*}} { +! CHECK: acc.loop {{.*}} vector([[CONSTANT128]] : i32) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.terminator @@ -539,9 +554,9 @@ subroutine acc_kernels_loop a(i) = b(i) END DO -! CHECK: acc.kernels { +! CHECK: acc.kernels {{.*}} { ! CHECK: [[VECTORLENGTH:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK: acc.loop vector([[VECTORLENGTH]] : i32) {{.*}} { +! CHECK: acc.loop {{.*}} vector([[VECTORLENGTH]] : i32) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.terminator @@ -552,8 +567,8 @@ subroutine acc_kernels_loop a(i) = b(i) END DO -! CHECK: acc.kernels { -! CHECK: acc.loop worker {{.*}} { +! CHECK: acc.kernels {{.*}} { +! CHECK: acc.loop {{.*}} worker {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>}{{$}} ! CHECK: acc.terminator @@ -564,9 +579,9 @@ subroutine acc_kernels_loop a(i) = b(i) END DO -! CHECK: acc.kernels { +! CHECK: acc.kernels {{.*}} { ! CHECK: [[WORKER128:%.*]] = arith.constant 128 : i32 -! CHECK: acc.loop worker([[WORKER128]] : i32) {{.*}} { +! CHECK: acc.loop {{.*}} worker([[WORKER128]] : i32) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.terminator @@ -579,7 +594,7 @@ subroutine acc_kernels_loop END DO END DO -! CHECK: acc.kernels { +! CHECK: acc.kernels {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {collapse = [2], collapseDeviceType = [#acc.device_type<none>], inclusiveUpperbound = array<i1: true, true>} @@ -594,7 +609,7 @@ subroutine acc_kernels_loop END DO END DO -! CHECK: acc.kernels { +! CHECK: acc.kernels {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield @@ -609,7 +624,7 @@ subroutine acc_kernels_loop a(i) = b(i) END DO -! CHECK: acc.kernels { +! CHECK: acc.kernels {{.*}} { ! CHECK: [[TILESIZE:%.*]] = arith.constant 2 : i32 ! CHECK: acc.loop {{.*}} tile({[[TILESIZE]] : i32}) {{.*}} { ! CHECK: acc.yield @@ -622,7 +637,7 @@ subroutine acc_kernels_loop a(i) = b(i) END DO -! CHECK: acc.kernels { +! CHECK: acc.kernels {{.*}} { ! CHECK: [[TILESIZEM1:%.*]] = arith.constant -1 : i32 ! CHECK: acc.loop {{.*}} tile({[[TILESIZEM1]] : i32}) {{.*}} { ! CHECK: acc.yield @@ -637,7 +652,7 @@ subroutine acc_kernels_loop END DO END DO -! CHECK: acc.kernels { +! CHECK: acc.kernels {{.*}} { ! CHECK: [[TILESIZE1:%.*]] = arith.constant 2 : i32 ! CHECK: [[TILESIZE2:%.*]] = arith.constant 2 : i32 ! CHECK: acc.loop {{.*}} tile({[[TILESIZE1]] : i32, [[TILESIZE2]] : i32}) {{.*}} { @@ -651,7 +666,7 @@ subroutine acc_kernels_loop a(i) = b(i) END DO -! CHECK: acc.kernels { +! CHECK: acc.kernels {{.*}} { ! CHECK: acc.loop {{.*}} tile({%{{.*}} : i32}) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -665,7 +680,7 @@ subroutine acc_kernels_loop END DO END DO -! CHECK: acc.kernels { +! CHECK: acc.kernels {{.*}} { ! CHECK: acc.loop {{.*}} tile({%{{.*}} : i32, %{{.*}} : i32}) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -680,7 +695,7 @@ subroutine acc_kernels_loop ! CHECK: %[[COPYINREDR:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_r"} ! CHECK: %[[COPYINREDI:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_i"} -! CHECK: acc.kernels dataOperands(%[[COPYINREDR]], %[[COPYINREDI]] : !fir.ref<f32>, !fir.ref<i32>) { +! CHECK: acc.kernels {{.*}} dataOperands(%[[COPYINREDR]], %[[COPYINREDI]] : !fir.ref<f32>, !fir.ref<i32>) { ! CHECK: acc.loop {{.*}} reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref<f32>, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref<i32>) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} diff --git a/flang/test/Lower/OpenACC/acc-loop.f90 b/flang/test/Lower/OpenACC/acc-loop.f90 index 1c64fab3536bb901601e0d0a4ee31261efdf17a5..fa910e79bd7663512a3a915e0eed9a60a843026c 100644 --- a/flang/test/Lower/OpenACC/acc-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-loop.f90 @@ -324,5 +324,5 @@ end subroutine ! CHECK: %[[P_I:.*]] = acc.private varPtr(%[[DC_I]] : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = ""} ! CHECK: %[[P_J:.*]] = acc.private varPtr(%[[DC_J]] : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = ""} ! CHECK: %[[P_K:.*]] = acc.private varPtr(%[[DC_K]] : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = ""} -! CHECK: acc.loop private(@privatization_ref_i32 -> %[[P_I]] : !fir.ref<i32>, @privatization_ref_i32 -> %[[P_J]] : !fir.ref<i32>, @privatization_ref_i32 -> %[[P_K]] : !fir.ref<i32>) 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: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[P_I]] : !fir.ref<i32>, @privatization_ref_i32 -> %[[P_J]] : !fir.ref<i32>, @privatization_ref_i32 -> %[[P_K]] : !fir.ref<i32>) 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<i1: true, true, true>} diff --git a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 index 39f18307486aa3cbc123d580ec0b9e997203437a..48ceda0710e8dba9547d5e0b4b75cd4cb5e5f1d3 100644 --- a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 @@ -39,13 +39,27 @@ subroutine acc_parallel_loop ! CHECK: %[[IFCONDITION:.*]] = fir.address_of(@{{.*}}ifcondition) : !fir.ref<!fir.logical<4>> ! CHECK: %[[DECLIFCONDITION:.*]]:2 = hlfir.declare %[[IFCONDITION]] - !$acc parallel loop + !$acc parallel + !$acc loop DO i = 1, n a(i) = b(i) END DO + !$acc end parallel ! CHECK: acc.parallel { -! CHECK: acc.loop {{.*}} { +! CHECK: acc.loop private{{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc parallel loop + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.parallel combined(loop) { +! CHECK: acc.loop combined(parallel) private{{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield @@ -57,7 +71,7 @@ subroutine acc_parallel_loop END DO !$acc end parallel loop -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -70,7 +84,7 @@ subroutine acc_parallel_loop END DO ! CHECK: [[ASYNC1:%.*]] = arith.constant 1 : i32 -! CHECK: acc.parallel async([[ASYNC1]] : i32) { +! CHECK: acc.parallel {{.*}} async([[ASYNC1]] : i32) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -83,7 +97,7 @@ subroutine acc_parallel_loop END DO ! CHECK: [[ASYNC2:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK: acc.parallel async([[ASYNC2]] : i32) { +! CHECK: acc.parallel {{.*}} async([[ASYNC2]] : i32) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -95,7 +109,7 @@ subroutine acc_parallel_loop a(i) = b(i) END DO -! CHECK: acc.parallel wait { +! CHECK: acc.parallel {{.*}} wait { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -108,7 +122,7 @@ subroutine acc_parallel_loop END DO ! CHECK: [[WAIT1:%.*]] = arith.constant 1 : i32 -! CHECK: acc.parallel wait({[[WAIT1]] : i32}) { +! CHECK: acc.parallel {{.*}} wait({[[WAIT1]] : i32}) { ! CHECK: acc.loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -122,7 +136,7 @@ subroutine acc_parallel_loop ! CHECK: [[WAIT2:%.*]] = arith.constant 1 : i32 ! CHECK: [[WAIT3:%.*]] = arith.constant 2 : i32 -! CHECK: acc.parallel wait({[[WAIT2]] : i32, [[WAIT3]] : i32}) { +! CHECK: acc.parallel {{.*}} wait({[[WAIT2]] : i32, [[WAIT3]] : i32}) { ! CHECK: acc.loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -136,7 +150,7 @@ subroutine acc_parallel_loop ! CHECK: [[WAIT4:%.*]] = fir.load %{{.*}} : !fir.ref<i32> ! CHECK: [[WAIT5:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK: acc.parallel wait({[[WAIT4]] : i32, [[WAIT5]] : i32}) { +! CHECK: acc.parallel {{.*}} wait({[[WAIT4]] : i32, [[WAIT5]] : i32}) { ! CHECK: acc.loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -149,7 +163,7 @@ subroutine acc_parallel_loop END DO ! CHECK: [[NUMGANGS1:%.*]] = arith.constant 1 : i32 -! CHECK: acc.parallel num_gangs({[[NUMGANGS1]] : i32}) { +! CHECK: acc.parallel {{.*}} num_gangs({[[NUMGANGS1]] : i32}) { ! CHECK: acc.loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -162,7 +176,7 @@ subroutine acc_parallel_loop END DO ! CHECK: [[NUMGANGS2:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK: acc.parallel num_gangs({[[NUMGANGS2]] : i32}) { +! CHECK: acc.parallel {{.*}} num_gangs({[[NUMGANGS2]] : i32}) { ! CHECK: acc.loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -175,7 +189,7 @@ subroutine acc_parallel_loop END DO ! CHECK: [[NUMWORKERS1:%.*]] = arith.constant 10 : i32 -! CHECK: acc.parallel num_workers([[NUMWORKERS1]] : i32) { +! CHECK: acc.parallel {{.*}} num_workers([[NUMWORKERS1]] : i32) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -188,7 +202,7 @@ subroutine acc_parallel_loop END DO ! CHECK: [[NUMWORKERS2:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK: acc.parallel num_workers([[NUMWORKERS2]] : i32) { +! CHECK: acc.parallel {{.*}} num_workers([[NUMWORKERS2]] : i32) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -201,7 +215,7 @@ subroutine acc_parallel_loop END DO ! CHECK: [[VECTORLENGTH1:%.*]] = arith.constant 128 : i32 -! CHECK: acc.parallel vector_length([[VECTORLENGTH1]] : i32) { +! CHECK: acc.parallel {{.*}} vector_length([[VECTORLENGTH1]] : i32) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -214,7 +228,7 @@ subroutine acc_parallel_loop END DO ! CHECK: [[VECTORLENGTH2:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK: acc.parallel vector_length([[VECTORLENGTH2]] : i32) { +! CHECK: acc.parallel {{.*}} vector_length([[VECTORLENGTH2]] : i32) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -227,7 +241,7 @@ subroutine acc_parallel_loop END DO ! CHECK: [[IF1:%.*]] = arith.constant true -! CHECK: acc.parallel if([[IF1]]) { +! CHECK: acc.parallel {{.*}} if([[IF1]]) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -241,7 +255,7 @@ subroutine acc_parallel_loop ! CHECK: [[IFCOND:%.*]] = fir.load %{{.*}} : !fir.ref<!fir.logical<4>> ! CHECK: [[IF2:%.*]] = fir.convert [[IFCOND]] : (!fir.logical<4>) -> i1 -! CHECK: acc.parallel if([[IF2]]) { +! CHECK: acc.parallel {{.*}} if([[IF2]]) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -254,7 +268,7 @@ subroutine acc_parallel_loop END DO ! CHECK: [[SELF1:%.*]] = arith.constant true -! CHECK: acc.parallel self([[SELF1]]) { +! CHECK: acc.parallel {{.*}} self([[SELF1]]) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -266,7 +280,7 @@ subroutine acc_parallel_loop a(i) = b(i) END DO -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -279,7 +293,7 @@ subroutine acc_parallel_loop END DO ! CHECK: %[[SELF2:.*]] = fir.convert %[[DECLIFCONDITION]]#1 : (!fir.ref<!fir.logical<4>>) -> i1 -! CHECK: acc.parallel self(%[[SELF2]]) { +! CHECK: acc.parallel {{.*}} self(%[[SELF2]]) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -293,7 +307,7 @@ subroutine acc_parallel_loop ! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, name = "a"} ! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, name = "b"} -! CHECK: acc.parallel dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.parallel {{.*}} dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -309,7 +323,7 @@ subroutine acc_parallel_loop ! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, name = "a"} ! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, name = "b"} -! CHECK: acc.parallel dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.parallel {{.*}} dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -325,7 +339,7 @@ subroutine acc_parallel_loop ! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"} ! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copyin_readonly>, name = "b"} -! CHECK: acc.parallel dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.parallel {{.*}} dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -339,7 +353,7 @@ subroutine acc_parallel_loop ! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "a"} ! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "b"} -! CHECK: acc.parallel dataOperands(%[[CREATE_A]], %[[CREATE_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.parallel {{.*}} dataOperands(%[[CREATE_A]], %[[CREATE_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -355,7 +369,7 @@ subroutine acc_parallel_loop ! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"} ! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_create_zero>, name = "a"} -! CHECK: acc.parallel dataOperands(%[[CREATE_B]], %[[CREATE_A]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.parallel {{.*}} dataOperands(%[[CREATE_B]], %[[CREATE_A]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -371,7 +385,7 @@ subroutine acc_parallel_loop ! CHECK: %[[NOCREATE_A:.*]] = acc.nocreate varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"} ! CHECK: %[[NOCREATE_B:.*]] = acc.nocreate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"} -! CHECK: acc.parallel dataOperands(%[[NOCREATE_A]], %[[NOCREATE_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.parallel {{.*}} dataOperands(%[[NOCREATE_A]], %[[NOCREATE_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -385,7 +399,7 @@ subroutine acc_parallel_loop ! CHECK: %[[PRESENT_A:.*]] = acc.present varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"} ! CHECK: %[[PRESENT_B:.*]] = acc.present varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"} -! CHECK: acc.parallel dataOperands(%[[PRESENT_A]], %[[PRESENT_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.parallel {{.*}} dataOperands(%[[PRESENT_A]], %[[PRESENT_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -399,7 +413,7 @@ subroutine acc_parallel_loop ! CHECK: %[[DEVICEPTR_A:.*]] = acc.deviceptr varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"} ! CHECK: %[[DEVICEPTR_B:.*]] = acc.deviceptr varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"} -! CHECK: acc.parallel dataOperands(%[[DEVICEPTR_A]], %[[DEVICEPTR_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.parallel {{.*}} dataOperands(%[[DEVICEPTR_A]], %[[DEVICEPTR_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -417,7 +431,7 @@ subroutine acc_parallel_loop ! CHECK: %[[BOX_G:.*]] = fir.load %[[DECLG]]#0 : !fir.ref<!fir.box<!fir.ptr<f32>>> ! CHECK: %[[BOX_ADDR_G:.*]] = fir.box_addr %[[BOX_G]] : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32> ! CHECK: %[[ATTACH_G:.*]] = acc.attach varPtr(%[[BOX_ADDR_G]] : !fir.ptr<f32>) -> !fir.ptr<f32> {name = "g"} -! CHECK: acc.parallel dataOperands(%[[ATTACH_F]], %[[ATTACH_G]] : !fir.ptr<f32>, !fir.ptr<f32>) { +! CHECK: acc.parallel {{.*}} dataOperands(%[[ATTACH_F]], %[[ATTACH_G]] : !fir.ptr<f32>, !fir.ptr<f32>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -430,9 +444,9 @@ subroutine acc_parallel_loop END DO ! CHECK: %[[ACC_PRIVATE_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"} -! CHECK: acc.parallel firstprivate(@firstprivatization_section_ext10_ref_10xf32 -> %[[ACC_PRIVATE_B]] : !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.parallel {{.*}} firstprivate(@firstprivatization_section_ext10_ref_10xf32 -> %[[ACC_PRIVATE_B]] : !fir.ref<!fir.array<10xf32>>) { ! CHECK: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"} -! CHECK: acc.loop private({{.*}}@privatization_ref_10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref<!fir.array<10xf32>>) +! CHECK: acc.loop {{.*}} private({{.*}}@privatization_ref_10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref<!fir.array<10xf32>>) ! CHECK-NOT: fir.do_loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -444,7 +458,7 @@ subroutine acc_parallel_loop a(i) = b(i) END DO -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]} @@ -456,7 +470,7 @@ subroutine acc_parallel_loop a(i) = b(i) END DO -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {auto_ = [#acc.device_type<none>], inclusiveUpperbound = array<i1: true>} @@ -468,7 +482,7 @@ subroutine acc_parallel_loop a(i) = b(i) END DO -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} @@ -480,8 +494,8 @@ subroutine acc_parallel_loop a(i) = b(i) END DO -! CHECK: acc.parallel { -! CHECK: acc.loop gang +! CHECK: acc.parallel {{.*}} { +! CHECK: acc.loop {{.*}} gang ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>}{{$}} ! CHECK: acc.yield @@ -492,9 +506,9 @@ subroutine acc_parallel_loop a(i) = b(i) END DO -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: [[GANGNUM1:%.*]] = arith.constant 8 : i32 -! CHECK-NEXT: acc.loop gang({num=[[GANGNUM1]] : i32}) +! CHECK-NEXT: acc.loop {{.*}} gang({num=[[GANGNUM1]] : i32}) ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield @@ -505,9 +519,9 @@ subroutine acc_parallel_loop a(i) = b(i) END DO -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: [[GANGNUM2:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK-NEXT: acc.loop gang({num=[[GANGNUM2]] : i32}) +! CHECK-NEXT: acc.loop {{.*}} gang({num=[[GANGNUM2]] : i32}) ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield @@ -518,8 +532,8 @@ subroutine acc_parallel_loop a(i) = b(i) END DO -! CHECK: acc.parallel { -! CHECK: acc.loop gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) +! CHECK: acc.parallel {{.*}} { +! CHECK: acc.loop {{.*}} gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield @@ -529,8 +543,9 @@ subroutine acc_parallel_loop DO i = 1, n a(i) = b(i) END DO -! CHECK: acc.parallel { -! CHECK: acc.loop vector + +! CHECK: acc.parallel {{.*}} { +! CHECK: acc.loop {{.*}} vector ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>}{{$}} ! CHECK: acc.yield @@ -541,9 +556,9 @@ subroutine acc_parallel_loop a(i) = b(i) END DO -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: [[CONSTANT128:%.*]] = arith.constant 128 : i32 -! CHECK: acc.loop vector([[CONSTANT128]] : i32) {{.*}} { +! CHECK: acc.loop {{.*}} vector([[CONSTANT128]] : i32) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield @@ -554,9 +569,9 @@ subroutine acc_parallel_loop a(i) = b(i) END DO -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: [[VECTORLENGTH:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK: acc.loop vector([[VECTORLENGTH]] : i32) {{.*}} { +! CHECK: acc.loop {{.*}} vector([[VECTORLENGTH]] : i32) {{.*}} { ! CHECK-NOT: fir.do_loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -568,8 +583,8 @@ subroutine acc_parallel_loop a(i) = b(i) END DO -! CHECK: acc.parallel { -! CHECK: acc.loop worker {{.*}} { +! CHECK: acc.parallel {{.*}} { +! CHECK: acc.loop {{.*}} worker {{.*}} { ! CHECK-NOT: fir.do_loop ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>}{{$}} @@ -581,9 +596,9 @@ subroutine acc_parallel_loop a(i) = b(i) END DO -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}}{ ! CHECK: [[WORKER128:%.*]] = arith.constant 128 : i32 -! CHECK: acc.loop worker([[WORKER128]] : i32) {{.*}} { +! CHECK: acc.loop {{.*}} worker([[WORKER128]] : i32) {{.*}} { ! CHECK-NOT: fir.do_loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -597,7 +612,7 @@ subroutine acc_parallel_loop END DO END DO -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {collapse = [2], collapseDeviceType = [#acc.device_type<none>], inclusiveUpperbound = array<i1: true, true>} @@ -612,7 +627,7 @@ subroutine acc_parallel_loop END DO END DO -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield @@ -627,7 +642,7 @@ subroutine acc_parallel_loop a(i) = b(i) END DO -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: [[TILESIZE:%.*]] = arith.constant 2 : i32 ! CHECK: acc.loop {{.*}} tile({[[TILESIZE]] : i32}) {{.*}} { ! CHECK: acc.yield @@ -640,7 +655,7 @@ subroutine acc_parallel_loop a(i) = b(i) END DO -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: [[TILESIZEM1:%.*]] = arith.constant -1 : i32 ! CHECK: acc.loop {{.*}} tile({[[TILESIZEM1]] : i32}) {{.*}} { ! CHECK: acc.yield @@ -655,7 +670,7 @@ subroutine acc_parallel_loop END DO END DO -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: [[TILESIZE1:%.*]] = arith.constant 2 : i32 ! CHECK: [[TILESIZE2:%.*]] = arith.constant 2 : i32 ! CHECK: acc.loop {{.*}} tile({[[TILESIZE1]] : i32, [[TILESIZE2]] : i32}) {{.*}} { @@ -669,7 +684,7 @@ subroutine acc_parallel_loop a(i) = b(i) END DO -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: acc.loop {{.*}} tile({%{{.*}} : i32}) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -683,7 +698,7 @@ subroutine acc_parallel_loop END DO END DO -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: acc.loop {{.*}} tile({%{{.*}} : i32, %{{.*}} : i32}) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -698,7 +713,7 @@ subroutine acc_parallel_loop ! CHECK: %[[COPYINREDR:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_r"} ! CHECK: %[[COPYINREDI:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_i"} -! CHECK: acc.parallel dataOperands(%[[COPYINREDR]], %[[COPYINREDI]] : !fir.ref<f32>, !fir.ref<i32>) { +! CHECK: acc.parallel {{.*}} dataOperands(%[[COPYINREDR]], %[[COPYINREDI]] : !fir.ref<f32>, !fir.ref<i32>) { ! CHECK: acc.loop {{.*}} reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref<f32>, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref<i32>) {{.*}} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} diff --git a/flang/test/Lower/OpenACC/acc-private.f90 b/flang/test/Lower/OpenACC/acc-private.f90 index ba582d40f0f51214469e856e3a140993f1684d7a..4d9f84b1fa749249feb17ee85577dc70175841b8 100644 --- a/flang/test/Lower/OpenACC/acc-private.f90 +++ b/flang/test/Lower/OpenACC/acc-private.f90 @@ -228,7 +228,7 @@ program acc_private END DO ! CHECK: %[[FP_C:.*]] = acc.firstprivate varPtr(%[[DECLC]]#0 : !fir.ref<i32>) -> !fir.ref<i32> {name = "c"} -! CHECK: acc.parallel firstprivate(@firstprivatization_ref_i32 -> %[[FP_C]] : !fir.ref<i32>) +! CHECK: acc.parallel {{.*}} firstprivate(@firstprivatization_ref_i32 -> %[[FP_C]] : !fir.ref<i32>) ! CHECK: acc.yield !$acc parallel loop firstprivate(b) @@ -242,7 +242,7 @@ program acc_private ! CHECK: %[[UB:.*]] = arith.subi %{{.*}}, %[[C1]] : index ! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%{{.*}} : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) ! CHECK: %[[FP_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<100xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<100xf32>> {name = "b"} -! CHECK: acc.parallel firstprivate(@firstprivatization_section_ext100_ref_100xf32 -> %[[FP_B]] : !fir.ref<!fir.array<100xf32>>) +! CHECK: acc.parallel {{.*}} firstprivate(@firstprivatization_section_ext100_ref_100xf32 -> %[[FP_B]] : !fir.ref<!fir.array<100xf32>>) ! CHECK: acc.yield !$acc parallel loop firstprivate(b(51:100)) @@ -256,7 +256,7 @@ program acc_private ! CHECK: %[[UB:.*]] = arith.constant 99 : index ! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%{{.*}} : index) stride(%[[C1]] : index) startIdx(%[[C1]] : index) ! CHECK: %[[FP_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<100xf32>>) bounds(%[[BOUND]]) -> !fir.ref<!fir.array<50xf32>> {name = "b(51:100)"} -! CHECK: acc.parallel firstprivate(@firstprivatization_section_lb50.ub99_ref_50xf32 -> %[[FP_B]] : !fir.ref<!fir.array<50xf32>>) +! CHECK: acc.parallel {{.*}} firstprivate(@firstprivatization_section_lb50.ub99_ref_50xf32 -> %[[FP_B]] : !fir.ref<!fir.array<50xf32>>) end program @@ -272,10 +272,10 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_private_assumed_shape( ! CHECK-SAME: %[[ARG0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "a"} ! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]] {uniq_name = "_QFacc_private_assumed_shapeEa"} : (!fir.box<!fir.array<?xi32>>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: %[[ADDR:.*]] = fir.box_addr %[[DECL_A]]#0 : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>> ! CHECK: %[[PRIVATE:.*]] = acc.private varPtr(%[[ADDR]] : !fir.ref<!fir.array<?xi32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<?xi32>> {name = "a"} -! CHECK: acc.loop private({{.*}}@privatization_box_Uxi32 -> %[[PRIVATE]] : !fir.ref<!fir.array<?xi32>>) +! CHECK: acc.loop {{.*}} private({{.*}}@privatization_box_Uxi32 -> %[[PRIVATE]] : !fir.ref<!fir.array<?xi32>>) subroutine acc_private_allocatable_array(a, n) integer, allocatable :: a(:) @@ -294,11 +294,11 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_private_allocatable_array( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {fir.bindc_name = "a"} ! CHECK: %[[DECLA_A:.*]]:2 = hlfir.declare %[[ARG0]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFacc_private_allocatable_arrayEa"} : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: %[[BOX:.*]] = fir.load %[[DECLA_A]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>> ! CHECK: %[[PRIVATE:.*]] = acc.private varPtr(%[[BOX_ADDR]] : !fir.heap<!fir.array<?xi32>>) bounds(%{{.*}}) -> !fir.heap<!fir.array<?xi32>> {name = "a"} -! CHECK: acc.loop private({{.*}}@privatization_box_heap_Uxi32 -> %[[PRIVATE]] : !fir.heap<!fir.array<?xi32>>) +! CHECK: acc.loop {{.*}} private({{.*}}@privatization_box_heap_Uxi32 -> %[[PRIVATE]] : !fir.heap<!fir.array<?xi32>>) ! CHECK: acc.serial private(@privatization_box_heap_Uxi32 -> %{{.*}} : !fir.heap<!fir.array<?xi32>>) subroutine acc_private_pointer_array(a, n) @@ -314,11 +314,11 @@ end subroutine ! CHECK-LABEL: func.func @_QPacc_private_pointer_array( ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> {fir.bindc_name = "a"}, %arg1: !fir.ref<i32> {fir.bindc_name = "n"}) { ! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %arg0 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFacc_private_pointer_arrayEa"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: %[[BOX:.*]] = fir.load %[[DECLA_A]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>> ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box<!fir.ptr<!fir.array<?xi32>>>) -> !fir.ptr<!fir.array<?xi32>> ! CHECK: %[[PRIVATE:.*]] = acc.private varPtr(%[[BOX_ADDR]] : !fir.ptr<!fir.array<?xi32>>) bounds(%{{.*}}) -> !fir.ptr<!fir.array<?xi32>> {name = "a"} -! CHECK: acc.loop private({{.*}}@privatization_box_ptr_Uxi32 -> %[[PRIVATE]] : !fir.ptr<!fir.array<?xi32>>) +! CHECK: acc.loop {{.*}} private({{.*}}@privatization_box_ptr_Uxi32 -> %[[PRIVATE]] : !fir.ptr<!fir.array<?xi32>>) subroutine acc_private_dynamic_extent(a, n) integer :: n, i @@ -334,10 +334,10 @@ end subroutine ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.array<?x?x2xi32>> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "n"}) { ! CHECK: %[[DECL_N:.*]]:2 = hlfir.declare %[[ARG1]] {uniq_name = "_QFacc_private_dynamic_extentEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) {uniq_name = "_QFacc_private_dynamic_extentEa"} : (!fir.ref<!fir.array<?x?x2xi32>>, !fir.shape<3>) -> (!fir.box<!fir.array<?x?x2xi32>>, !fir.ref<!fir.array<?x?x2xi32>>) -! CHECK: acc.parallel { +! CHECK: acc.parallel {{.*}} { ! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[DECL_A]]#0 : (!fir.box<!fir.array<?x?x2xi32>>) -> !fir.ref<!fir.array<?x?x2xi32>> ! CHECK: %[[PRIV:.*]] = acc.private varPtr(%[[BOX_ADDR]] : !fir.ref<!fir.array<?x?x2xi32>>) bounds(%{{.*}}, %{{.*}}, %{{.*}}) -> !fir.ref<!fir.array<?x?x2xi32>> {name = "a"} -! CHECK: acc.loop private({{.*}}@privatization_box_UxUx2xi32 -> %[[PRIV]] : !fir.ref<!fir.array<?x?x2xi32>>) +! CHECK: acc.loop {{.*}} private({{.*}}@privatization_box_UxUx2xi32 -> %[[PRIV]] : !fir.ref<!fir.array<?x?x2xi32>>) subroutine acc_firstprivate_assumed_shape(a, n) integer :: a(:), i, n @@ -367,7 +367,7 @@ subroutine acc_firstprivate_dynamic_extent(a, n) end do end subroutine -! CHECK: acc.parallel firstprivate(@firstprivatization_box_UxUx2xi32 -> %{{.*}} : !fir.ref<!fir.array<?x?x2xi32>>) +! CHECK: acc.parallel {{.*}} firstprivate(@firstprivatization_box_UxUx2xi32 -> %{{.*}} : !fir.ref<!fir.array<?x?x2xi32>>) module acc_declare_equivalent integer, parameter :: n = 10 @@ -398,6 +398,6 @@ end ! CHECK: acc.parallel ! CHECK: %[[PRIV_I:.*]] = acc.private varPtr(%[[DECL_I]]#1 : !fir.ref<i32>) -> !fir.ref<i32> {implicit = true, name = ""} ! CHECK: %[[DECL_PRIV_I:.*]]:2 = hlfir.declare %[[PRIV_I]] {uniq_name = "_QFacc_private_useEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: acc.loop private(@privatization_ref_i32 -> %[[PRIV_I]] : !fir.ref<i32>) control(%[[IV0:.*]] : i32) = (%c1{{.*}} : i32) to (%c10{{.*}} : i32) step (%c1{{.*}} : i32) +! CHECK: acc.loop {{.*}} private(@privatization_ref_i32 -> %[[PRIV_I]] : !fir.ref<i32>) control(%[[IV0:.*]] : i32) = (%c1{{.*}} : i32) to (%c10{{.*}} : i32) step (%c1{{.*}} : i32) ! CHECK: fir.store %[[IV0]] to %[[DECL_PRIV_I]]#0 : !fir.ref<i32> ! CHECK: %{{.*}} = fir.load %[[DECL_PRIV_I]]#0 : !fir.ref<i32> diff --git a/flang/test/Lower/OpenACC/acc-serial-loop.f90 b/flang/test/Lower/OpenACC/acc-serial-loop.f90 index 77f5e1eaa7c821193d60cc0725f90dea6c2afbd3..fa3b3f758908ced89084f3d5a64375e11d0045db 100644 --- a/flang/test/Lower/OpenACC/acc-serial-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-serial-loop.f90 @@ -58,13 +58,27 @@ subroutine acc_serial_loop ! CHECK: %[[IFCONDITION:.*]] = fir.address_of(@{{.*}}ifcondition) : !fir.ref<!fir.logical<4>> ! CHECK: %[[DECLIFCONDITION:.*]]:2 = hlfir.declare %[[IFCONDITION]] - !$acc serial loop + !$acc serial + !$acc loop DO i = 1, n a(i) = b(i) END DO + !$acc end serial ! CHECK: acc.serial { -! CHECK: acc.loop {{.*}} { +! CHECK: acc.loop private{{.*}} { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} + + !$acc serial loop + DO i = 1, n + a(i) = b(i) + END DO + +! CHECK: acc.serial combined(loop) { +! CHECK: acc.loop combined(serial) private{{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield @@ -76,7 +90,7 @@ subroutine acc_serial_loop END DO !$acc end serial loop -! CHECK: acc.serial { +! CHECK: acc.serial {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -89,7 +103,7 @@ subroutine acc_serial_loop END DO ! CHECK: [[ASYNC1:%.*]] = arith.constant 1 : i32 -! CHECK: acc.serial async([[ASYNC1]] : i32) { +! CHECK: acc.serial {{.*}} async([[ASYNC1]] : i32) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -102,7 +116,7 @@ subroutine acc_serial_loop END DO ! CHECK: [[ASYNC2:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK: acc.serial async([[ASYNC2]] : i32) { +! CHECK: acc.serial {{.*}} async([[ASYNC2]] : i32) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -114,7 +128,7 @@ subroutine acc_serial_loop a(i) = b(i) END DO -! CHECK: acc.serial wait { +! CHECK: acc.serial {{.*}} wait { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -127,7 +141,7 @@ subroutine acc_serial_loop END DO ! CHECK: [[WAIT1:%.*]] = arith.constant 1 : i32 -! CHECK: acc.serial wait({[[WAIT1]] : i32}) { +! CHECK: acc.serial {{.*}} wait({[[WAIT1]] : i32}) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -141,7 +155,7 @@ subroutine acc_serial_loop ! CHECK: [[WAIT2:%.*]] = arith.constant 1 : i32 ! CHECK: [[WAIT3:%.*]] = arith.constant 2 : i32 -! CHECK: acc.serial wait({[[WAIT2]] : i32, [[WAIT3]] : i32}) { +! CHECK: acc.serial {{.*}} wait({[[WAIT2]] : i32, [[WAIT3]] : i32}) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -155,7 +169,7 @@ subroutine acc_serial_loop ! CHECK: [[WAIT4:%.*]] = fir.load %{{.*}} : !fir.ref<i32> ! CHECK: [[WAIT5:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK: acc.serial wait({[[WAIT4]] : i32, [[WAIT5]] : i32}) { +! CHECK: acc.serial {{.*}} wait({[[WAIT4]] : i32, [[WAIT5]] : i32}) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -168,7 +182,7 @@ subroutine acc_serial_loop END DO ! CHECK: [[IF1:%.*]] = arith.constant true -! CHECK: acc.serial if([[IF1]]) { +! CHECK: acc.serial {{.*}} if([[IF1]]) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -182,7 +196,7 @@ subroutine acc_serial_loop ! CHECK: [[IFCOND:%.*]] = fir.load %{{.*}} : !fir.ref<!fir.logical<4>> ! CHECK: [[IF2:%.*]] = fir.convert [[IFCOND]] : (!fir.logical<4>) -> i1 -! CHECK: acc.serial if([[IF2]]) { +! CHECK: acc.serial {{.*}} if([[IF2]]) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -195,7 +209,7 @@ subroutine acc_serial_loop END DO ! CHECK: [[SELF1:%.*]] = arith.constant true -! CHECK: acc.serial self([[SELF1]]) { +! CHECK: acc.serial {{.*}} self([[SELF1]]) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -207,7 +221,7 @@ subroutine acc_serial_loop a(i) = b(i) END DO -! CHECK: acc.serial { +! CHECK: acc.serial {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -220,7 +234,7 @@ subroutine acc_serial_loop END DO ! CHECK: %[[SELF2:.*]] = fir.convert %[[DECLIFCONDITION]]#1 : (!fir.ref<!fir.logical<4>>) -> i1 -! CHECK: acc.serial self(%[[SELF2]]) { +! CHECK: acc.serial {{.*}} self(%[[SELF2]]) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -234,7 +248,7 @@ subroutine acc_serial_loop ! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, name = "a"} ! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, name = "b"} -! CHECK: acc.serial dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.serial {{.*}} dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -250,7 +264,7 @@ subroutine acc_serial_loop ! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, name = "a"} ! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copy>, name = "b"} -! CHECK: acc.serial dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.serial {{.*}} dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -266,7 +280,7 @@ subroutine acc_serial_loop ! CHECK: %[[COPYIN_A:.*]] = acc.copyin varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"} ! CHECK: %[[COPYIN_B:.*]] = acc.copyin varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copyin_readonly>, name = "b"} -! CHECK: acc.serial dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.serial {{.*}} dataOperands(%[[COPYIN_A]], %[[COPYIN_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -280,7 +294,7 @@ subroutine acc_serial_loop ! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "a"} ! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_copyout>, name = "b"} -! CHECK: acc.serial dataOperands(%[[CREATE_A]], %[[CREATE_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.serial {{.*}} dataOperands(%[[CREATE_A]], %[[CREATE_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -296,7 +310,7 @@ subroutine acc_serial_loop ! CHECK: %[[CREATE_B:.*]] = acc.create varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"} ! CHECK: %[[CREATE_A:.*]] = acc.create varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {dataClause = #acc<data_clause acc_create_zero>, name = "a"} -! CHECK: acc.serial dataOperands(%[[CREATE_B]], %[[CREATE_A]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.serial {{.*}} dataOperands(%[[CREATE_B]], %[[CREATE_A]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -312,7 +326,7 @@ subroutine acc_serial_loop ! CHECK: %[[NOCREATE_A:.*]] = acc.nocreate varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"} ! CHECK: %[[NOCREATE_B:.*]] = acc.nocreate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"} -! CHECK: acc.serial dataOperands(%[[NOCREATE_A]], %[[NOCREATE_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.serial {{.*}} dataOperands(%[[NOCREATE_A]], %[[NOCREATE_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -326,7 +340,7 @@ subroutine acc_serial_loop ! CHECK: %[[PRESENT_A:.*]] = acc.present varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"} ! CHECK: %[[PRESENT_B:.*]] = acc.present varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"} -! CHECK: acc.serial dataOperands(%[[PRESENT_A]], %[[PRESENT_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.serial {{.*}} dataOperands(%[[PRESENT_A]], %[[PRESENT_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -340,7 +354,7 @@ subroutine acc_serial_loop ! CHECK: %[[DEVICEPTR_A:.*]] = acc.deviceptr varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"} ! CHECK: %[[DEVICEPTR_B:.*]] = acc.deviceptr varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"} -! CHECK: acc.serial dataOperands(%[[DEVICEPTR_A]], %[[DEVICEPTR_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.serial {{.*}} dataOperands(%[[DEVICEPTR_A]], %[[DEVICEPTR_B]] : !fir.ref<!fir.array<10xf32>>, !fir.ref<!fir.array<10xf32>>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -358,7 +372,7 @@ subroutine acc_serial_loop ! CHECK: %[[BOX_G:.*]] = fir.load %[[DECLG]]#0 : !fir.ref<!fir.box<!fir.ptr<f32>>> ! CHECK: %[[BOX_ADDR_G:.*]] = fir.box_addr %[[BOX_G]] : (!fir.box<!fir.ptr<f32>>) -> !fir.ptr<f32> ! CHECK: %[[ATTACH_G:.*]] = acc.attach varPtr(%[[BOX_ADDR_G]] : !fir.ptr<f32>) -> !fir.ptr<f32> {name = "g"} -! CHECK: acc.serial dataOperands(%[[ATTACH_F]], %[[ATTACH_G]] : !fir.ptr<f32>, !fir.ptr<f32>) { +! CHECK: acc.serial {{.*}} dataOperands(%[[ATTACH_F]], %[[ATTACH_G]] : !fir.ptr<f32>, !fir.ptr<f32>) { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -371,9 +385,9 @@ subroutine acc_serial_loop END DO ! CHECK: %[[ACC_FPRIVATE_B:.*]] = acc.firstprivate varPtr(%[[DECLB]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "b"} -! CHECK: acc.serial firstprivate(@firstprivatization_section_ext10_ref_10xf32 -> %[[ACC_FPRIVATE_B]] : !fir.ref<!fir.array<10xf32>>) { +! CHECK: acc.serial {{.*}} firstprivate(@firstprivatization_section_ext10_ref_10xf32 -> %[[ACC_FPRIVATE_B]] : !fir.ref<!fir.array<10xf32>>) { ! CHECK: %[[ACC_PRIVATE_A:.*]] = acc.private varPtr(%[[DECLA]]#0 : !fir.ref<!fir.array<10xf32>>) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "a"} -! CHECK: acc.loop private({{.*}}@privatization_ref_10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref<!fir.array<10xf32>>) +! CHECK: acc.loop {{.*}} private({{.*}}@privatization_ref_10xf32 -> %[[ACC_PRIVATE_A]] : !fir.ref<!fir.array<10xf32>>) ! CHECK-NOT: fir.do_loop ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -385,7 +399,7 @@ subroutine acc_serial_loop a(i) = b(i) END DO -! CHECK: acc.serial { +! CHECK: acc.serial {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]} @@ -397,7 +411,7 @@ subroutine acc_serial_loop a(i) = b(i) END DO -! CHECK: acc.serial { +! CHECK: acc.serial {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {auto_ = [#acc.device_type<none>], inclusiveUpperbound = array<i1: true>} @@ -409,7 +423,7 @@ subroutine acc_serial_loop a(i) = b(i) END DO -! CHECK: acc.serial { +! CHECK: acc.serial {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>, independent = [#acc.device_type<none>]} @@ -421,8 +435,8 @@ subroutine acc_serial_loop a(i) = b(i) END DO -! CHECK: acc.serial { -! CHECK: acc.loop gang {{.*}} { +! CHECK: acc.serial {{.*}} { +! CHECK: acc.loop {{.*}} gang {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>}{{$}} ! CHECK: acc.yield @@ -433,9 +447,9 @@ subroutine acc_serial_loop a(i) = b(i) END DO -! CHECK: acc.serial { +! CHECK: acc.serial {{.*}} { ! CHECK: [[GANGNUM1:%.*]] = arith.constant 8 : i32 -! CHECK-NEXT: acc.loop gang({num=[[GANGNUM1]] : i32}) {{.*}} { +! CHECK-NEXT: acc.loop {{.*}} gang({num=[[GANGNUM1]] : i32}) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield @@ -446,9 +460,9 @@ subroutine acc_serial_loop a(i) = b(i) END DO -! CHECK: acc.serial { +! CHECK: acc.serial {{.*}} { ! CHECK: [[GANGNUM2:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK-NEXT: acc.loop gang({num=[[GANGNUM2]] : i32}) {{.*}} { +! CHECK-NEXT: acc.loop {{.*}} gang({num=[[GANGNUM2]] : i32}) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield @@ -459,8 +473,8 @@ subroutine acc_serial_loop a(i) = b(i) END DO -! CHECK: acc.serial { -! CHECK: acc.loop gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) {{.*}} { +! CHECK: acc.serial {{.*}} { +! CHECK: acc.loop {{.*}} gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield @@ -470,8 +484,9 @@ subroutine acc_serial_loop DO i = 1, n a(i) = b(i) END DO -! CHECK: acc.serial { -! CHECK: acc.loop vector {{.*}} { + +! CHECK: acc.serial {{.*}} { +! CHECK: acc.loop {{.*}} vector {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>}{{$}} ! CHECK: acc.yield @@ -482,9 +497,9 @@ subroutine acc_serial_loop a(i) = b(i) END DO -! CHECK: acc.serial { +! CHECK: acc.serial {{.*}} { ! CHECK: [[CONSTANT128:%.*]] = arith.constant 128 : i32 -! CHECK: acc.loop vector([[CONSTANT128]] : i32) {{.*}} { +! CHECK: acc.loop {{.*}} vector([[CONSTANT128]] : i32) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield @@ -495,9 +510,9 @@ subroutine acc_serial_loop a(i) = b(i) END DO -! CHECK: acc.serial { +! CHECK: acc.serial {{.*}} { ! CHECK: [[VECTORLENGTH:%.*]] = fir.load %{{.*}} : !fir.ref<i32> -! CHECK: acc.loop vector([[VECTORLENGTH]] : i32) {{.*}} { +! CHECK: acc.loop {{.*}} vector([[VECTORLENGTH]] : i32) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield @@ -508,8 +523,8 @@ subroutine acc_serial_loop a(i) = b(i) END DO -! CHECK: acc.serial { -! CHECK: acc.loop worker {{.*}} { +! CHECK: acc.serial {{.*}} { +! CHECK: acc.loop {{.*}} worker {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: } attributes {inclusiveUpperbound = array<i1: true>}{{$}} ! CHECK: acc.yield @@ -520,9 +535,9 @@ subroutine acc_serial_loop a(i) = b(i) END DO -! CHECK: acc.serial { +! CHECK: acc.serial {{.*}} { ! CHECK: [[WORKER128:%.*]] = arith.constant 128 : i32 -! CHECK: acc.loop worker([[WORKER128]] : i32) {{.*}} { +! CHECK: acc.loop {{.*}} worker([[WORKER128]] : i32) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield @@ -535,7 +550,7 @@ subroutine acc_serial_loop END DO END DO -! CHECK: acc.serial { +! CHECK: acc.serial {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK-NOT: fir.do_loop ! CHECK: acc.yield @@ -551,7 +566,7 @@ subroutine acc_serial_loop END DO END DO -! CHECK: acc.serial { +! CHECK: acc.serial {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.loop {{.*}} { ! CHECK: acc.yield @@ -566,7 +581,7 @@ subroutine acc_serial_loop a(i) = b(i) END DO -! CHECK: acc.serial { +! CHECK: acc.serial {{.*}} { ! CHECK: [[TILESIZE:%.*]] = arith.constant 2 : i32 ! CHECK: acc.loop {{.*}} tile({[[TILESIZE]] : i32}) {{.*}} { ! CHECK: acc.yield @@ -579,7 +594,7 @@ subroutine acc_serial_loop a(i) = b(i) END DO -! CHECK: acc.serial { +! CHECK: acc.serial {{.*}} { ! CHECK: [[TILESIZEM1:%.*]] = arith.constant -1 : i32 ! CHECK: acc.loop {{.*}} tile({[[TILESIZEM1]] : i32}) {{.*}} { ! CHECK: acc.yield @@ -594,7 +609,7 @@ subroutine acc_serial_loop END DO END DO -! CHECK: acc.serial { +! CHECK: acc.serial {{.*}} { ! CHECK: [[TILESIZE1:%.*]] = arith.constant 2 : i32 ! CHECK: [[TILESIZE2:%.*]] = arith.constant 2 : i32 ! CHECK: acc.loop {{.*}} tile({[[TILESIZE1]] : i32, [[TILESIZE2]] : i32}) {{.*}} { @@ -608,7 +623,7 @@ subroutine acc_serial_loop a(i) = b(i) END DO -! CHECK: acc.serial { +! CHECK: acc.serial {{.*}} { ! CHECK: acc.loop {{.*}} tile({%{{.*}} : i32}) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -622,7 +637,7 @@ subroutine acc_serial_loop END DO END DO -! CHECK: acc.serial { +! CHECK: acc.serial {{.*}} { ! CHECK: acc.loop {{.*}} tile({%{{.*}} : i32, %{{.*}} : i32}) {{.*}} { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} @@ -637,7 +652,7 @@ subroutine acc_serial_loop ! CHECK: %[[COPYINREDR:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_r"} ! CHECK: %[[COPYINREDI:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_i"} -! CHECK: acc.serial dataOperands(%[[COPYINREDR]], %[[COPYINREDI]] : !fir.ref<f32>, !fir.ref<i32>) { +! CHECK: acc.serial {{.*}} dataOperands(%[[COPYINREDR]], %[[COPYINREDI]] : !fir.ref<f32>, !fir.ref<i32>) { ! CHECK: acc.loop {{.*}} reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref<f32>, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref<i32>) ! CHECK-NOT: fir.do_loop ! CHECK: acc.yield diff --git a/flang/test/Lower/OpenMP/FIR/array-bounds.f90 b/flang/test/Lower/OpenMP/FIR/array-bounds.f90 index 3cd284c46e727de7686495781e16c3d75f2e6eaf..c2bb7a94712bd4bd88b55117f757c658aed26e3a 100644 --- a/flang/test/Lower/OpenMP/FIR/array-bounds.f90 +++ b/flang/test/Lower/OpenMP/FIR/array-bounds.f90 @@ -10,14 +10,14 @@ !ALL: %[[C1:.*]] = arith.constant 1 : index !ALL: %[[C2:.*]] = arith.constant 1 : index !ALL: %[[C3:.*]] = arith.constant 4 : index -!ALL: %[[BOUNDS0:.*]] = omp.bounds lower_bound(%[[C2]] : index) upper_bound(%[[C3]] : index) extent(%[[C10]] : index) stride(%[[C1]] : index) start_idx(%[[C1]] : index) -!ALL: %[[MAP0:.*]] = omp.map_info var_ptr(%[[READ]] : !fir.ref<!fir.array<10xi32>>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS0]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_read(2:5)"} +!ALL: %[[BOUNDS0:.*]] = omp.map.bounds lower_bound(%[[C2]] : index) upper_bound(%[[C3]] : index) extent(%[[C10]] : index) stride(%[[C1]] : index) start_idx(%[[C1]] : index) +!ALL: %[[MAP0:.*]] = omp.map.info var_ptr(%[[READ]] : !fir.ref<!fir.array<10xi32>>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS0]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_read(2:5)"} !ALL: %[[C4:.*]] = arith.constant 1 : index !ALL: %[[C5:.*]] = arith.constant 1 : index !ALL: %[[C6:.*]] = arith.constant 4 : index -!ALL: %[[BOUNDS1:.*]] = omp.bounds lower_bound(%[[C5]] : index) upper_bound(%[[C6]] : index) extent(%[[C10_0]] : index) stride(%[[C4]] : index) start_idx(%[[C4]] : index) -!ALL: %[[MAP1:.*]] = omp.map_info var_ptr(%[[WRITE]] : !fir.ref<!fir.array<10xi32>>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS1]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_write(2:5)"} -!ALL: %[[MAP2:.*]] = omp.map_info var_ptr(%[[ITER]] : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = "i"} +!ALL: %[[BOUNDS1:.*]] = omp.map.bounds lower_bound(%[[C5]] : index) upper_bound(%[[C6]] : index) extent(%[[C10_0]] : index) stride(%[[C4]] : index) start_idx(%[[C4]] : index) +!ALL: %[[MAP1:.*]] = omp.map.info var_ptr(%[[WRITE]] : !fir.ref<!fir.array<10xi32>>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS1]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_write(2:5)"} +!ALL: %[[MAP2:.*]] = omp.map.info var_ptr(%[[ITER]] : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = "i"} !ALL: omp.target map_entries(%[[MAP0]] -> %{{.*}}, %[[MAP1]] -> %{{.*}}, %[[MAP2]] -> %{{.*}} : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>, !fir.ref<i32>) { subroutine read_write_section() @@ -44,11 +44,11 @@ contains !ALL: %[[C4:.*]] = arith.constant 4 : index !ALL: %[[C0_1:.*]] = arith.constant 0 : index !ALL: %[[DIMS1:.*]]:3 = fir.box_dims %arg0, %[[C0_1]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) -!ALL: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C3]] : index) upper_bound(%[[C4]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) start_idx(%[[C0]] : index) {stride_in_bytes = true} +!ALL: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%[[C3]] : index) upper_bound(%[[C4]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) start_idx(%[[C0]] : index) {stride_in_bytes = true} !ALL: %[[BOXADDRADDR:.*]] = fir.box_offset %0 base_addr : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> -!ALL: %[[MAP_MEMBER:.*]] = omp.map_info var_ptr(%0 : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.array<?xi32>) var_ptr_ptr(%[[BOXADDRADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -!ALL: %[[MAP:.*]] = omp.map_info var_ptr(%0 : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBER]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"} -!ALL: %[[MAP2:.*]] = omp.map_info var_ptr(%[[ALLOCA]] : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = "i"} +!ALL: %[[MAP_MEMBER:.*]] = omp.map.info var_ptr(%0 : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.array<?xi32>) var_ptr_ptr(%[[BOXADDRADDR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} +!ALL: %[[MAP:.*]] = omp.map.info var_ptr(%0 : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBER]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"} +!ALL: %[[MAP2:.*]] = omp.map.info var_ptr(%[[ALLOCA]] : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = "i"} !ALL: omp.target map_entries(%[[MAP_MEMBER]] -> %{{.*}}, %[[MAP]] -> %{{.*}}, %[[MAP2]] -> %{{.*}} : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>) { subroutine assumed_shape_array(arr_read_write) integer, intent(inout) :: arr_read_write(:) @@ -68,9 +68,9 @@ contains !ALL: %[[C2:.*]] = arith.constant 4 : index !ALL: %[[DIFF:.*]] = arith.subi %[[C2]], %[[C1]] : index !ALL: %[[EXT:.*]] = arith.addi %[[DIFF]], %[[C0]] : index -!ALL: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C1]] : index) upper_bound(%[[C2]] : index) extent(%[[EXT]] : index) stride(%[[C0]] : index) start_idx(%[[C0]] : index) -!ALL: %[[MAP:.*]] = omp.map_info var_ptr(%[[ARG0]] : !fir.ref<!fir.array<?xi32>>, !fir.array<?xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"} -!ALL: %[[MAP2:.*]] = omp.map_info var_ptr(%[[ALLOCA]] : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = "i"} +!ALL: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%[[C1]] : index) upper_bound(%[[C2]] : index) extent(%[[EXT]] : index) stride(%[[C0]] : index) start_idx(%[[C0]] : index) +!ALL: %[[MAP:.*]] = omp.map.info var_ptr(%[[ARG0]] : !fir.ref<!fir.array<?xi32>>, !fir.array<?xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"} +!ALL: %[[MAP2:.*]] = omp.map.info var_ptr(%[[ALLOCA]] : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = "i"} !ALL: omp.target map_entries(%[[MAP]] -> %{{.*}}, %[[MAP2]] -> %{{.*}} : !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>) { subroutine assumed_size_array(arr_read_write) integer, intent(inout) :: arr_read_write(*) diff --git a/flang/test/Lower/OpenMP/FIR/atomic-capture.f90 b/flang/test/Lower/OpenMP/FIR/atomic-capture.f90 index 024400a9e84718d42757b140e0204727d0bbb357..9b94214b9da8bb3bb63db0de194c577f6f340d51 100644 --- a/flang/test/Lower/OpenMP/FIR/atomic-capture.f90 +++ b/flang/test/Lower/OpenMP/FIR/atomic-capture.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | FileCheck %s ! This test checks the lowering of atomic capture diff --git a/flang/test/Lower/OpenMP/FIR/atomic-read.f90 b/flang/test/Lower/OpenMP/FIR/atomic-read.f90 index 66be9e7139044c580b473e6539d86a811a549917..7698c3d7490fe964dd6239fdbcf9e85996e48c15 100644 --- a/flang/test/Lower/OpenMP/FIR/atomic-read.f90 +++ b/flang/test/Lower/OpenMP/FIR/atomic-read.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: bbc --use-desc-for-alloc=false -fopenmp -emit-fir -hlfir=false %s -o - | FileCheck %s ! This test checks the lowering of atomic read diff --git a/flang/test/Lower/OpenMP/FIR/atomic-update.f90 b/flang/test/Lower/OpenMP/FIR/atomic-update.f90 index bd3d4ace440ee800245a095973df9f79d904b64e..ae201807c337f01d8bf2233470c2250ce0d4b5c1 100644 --- a/flang/test/Lower/OpenMP/FIR/atomic-update.f90 +++ b/flang/test/Lower/OpenMP/FIR/atomic-update.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! This test checks lowering of atomic and atomic update constructs ! RUN: bbc --use-desc-for-alloc=false -fopenmp -emit-fir -hlfir=false %s -o - | FileCheck %s ! RUN: %flang_fc1 -mllvm --use-desc-for-alloc=false -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | FileCheck %s diff --git a/flang/test/Lower/OpenMP/FIR/atomic-write.f90 b/flang/test/Lower/OpenMP/FIR/atomic-write.f90 index 5d98176cc201ff7a418ce7df7f9b3ccef96a8b5e..142481b7a1d210fa1d503d5e9ac9ed2cef4b97d5 100644 --- a/flang/test/Lower/OpenMP/FIR/atomic-write.f90 +++ b/flang/test/Lower/OpenMP/FIR/atomic-write.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: bbc --use-desc-for-alloc=false -fopenmp -emit-fir -hlfir=false %s -o - | FileCheck %s ! This test checks the lowering of atomic write diff --git a/flang/test/Lower/OpenMP/FIR/critical.f90 b/flang/test/Lower/OpenMP/FIR/critical.f90 index e88178422a83475dab1832a95827ba202761f2a7..fa33fb0fe58bb001c6b637e29d35d9a9db8c894c 100644 --- a/flang/test/Lower/OpenMP/FIR/critical.f90 +++ b/flang/test/Lower/OpenMP/FIR/critical.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + !RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | FileCheck %s --check-prefixes="OMPDialect" !RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | fir-opt --fir-to-llvm-ir | FileCheck %s --check-prefix="OMPDialect" !RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | fir-opt --fir-to-llvm-ir | tco | FileCheck %s --check-prefix="LLVMIR" diff --git a/flang/test/Lower/OpenMP/FIR/flush.f90 b/flang/test/Lower/OpenMP/FIR/flush.f90 index 2c281632b85cb0460bf43436858cbe7f174d4021..2868367fbdba64176257b1623cbb539c69b2090a 100644 --- a/flang/test/Lower/OpenMP/FIR/flush.f90 +++ b/flang/test/Lower/OpenMP/FIR/flush.f90 @@ -1,7 +1,7 @@ ! This test checks lowering of OpenMP Flush Directive. !RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | FileCheck %s --check-prefixes="FIRDialect,OMPDialect" -!RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | fir-opt --cfg-conversion | fir-opt --fir-to-llvm-ir | FileCheck %s --check-prefixes="LLVMIRDialect,OMPDialect" +!RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | fir-opt --cfg-conversion-on-func-opt | fir-opt --fir-to-llvm-ir | FileCheck %s --check-prefixes="LLVMIRDialect,OMPDialect" subroutine flush_standalone(a, b, c) integer, intent(inout) :: a, b, c diff --git a/flang/test/Lower/OpenMP/FIR/map-component-ref.f90 b/flang/test/Lower/OpenMP/FIR/map-component-ref.f90 index af8c6fa3c5e877ee6f2402ba41c85ce733e5d697..6799941701f42ac01eeeddc871aefa7011886a1e 100644 --- a/flang/test/Lower/OpenMP/FIR/map-component-ref.f90 +++ b/flang/test/Lower/OpenMP/FIR/map-component-ref.f90 @@ -5,8 +5,8 @@ ! CHECK: %[[V1:[0-9]+]] = fir.declare %[[V0]] {uniq_name = "_QFfooEa"} : (!fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>) -> !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>> ! CHECK: %[[V2:[0-9]+]] = fir.field_index a1, !fir.type<_QFfooTt0{a0:i32,a1:i32}> ! CHECK: %[[V3:[0-9]+]] = fir.coordinate_of %[[V1]], %[[V2]] : (!fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>, !fir.field) -> !fir.ref<i32> -! CHECK: %[[V4:[0-9]+]] = omp.map_info var_ptr(%[[V3]] : !fir.ref<i32>, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref<i32> {name = "a%a1"} -! CHECK: %[[V5:[0-9]+]] = omp.map_info var_ptr(%[[V1]] : !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>, !fir.type<_QFfooTt0{a0:i32,a1:i32}>) map_clauses(implicit, tofrom) capture(ByRef) -> !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>> {name = "a"} +! CHECK: %[[V4:[0-9]+]] = omp.map.info var_ptr(%[[V3]] : !fir.ref<i32>, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref<i32> {name = "a%a1"} +! CHECK: %[[V5:[0-9]+]] = omp.map.info var_ptr(%[[V1]] : !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>, !fir.type<_QFfooTt0{a0:i32,a1:i32}>) map_clauses(implicit, tofrom) capture(ByRef) -> !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>> {name = "a"} ! CHECK: omp.target map_entries(%[[V4]] -> %arg0, %[[V5]] -> %arg1 : !fir.ref<i32>, !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>) { ! CHECK: ^bb0(%arg0: !fir.ref<i32>, %arg1: !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>): ! CHECK: %c0_i32 = arith.constant 0 : i32 diff --git a/flang/test/Lower/OpenMP/FIR/master.f90 b/flang/test/Lower/OpenMP/FIR/master.f90 index dd9910da2f419034749611f205e256e9b67db16e..3bac582c7725a889ae053102e0f8ca29d39fc623 100644 --- a/flang/test/Lower/OpenMP/FIR/master.f90 +++ b/flang/test/Lower/OpenMP/FIR/master.f90 @@ -1,5 +1,5 @@ !RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | FileCheck %s --check-prefixes="FIRDialect,OMPDialect" -!RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | fir-opt --cfg-conversion | fir-opt --fir-to-llvm-ir | FileCheck %s --check-prefixes="OMPDialect" +!RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | fir-opt --cfg-conversion-on-func-opt | fir-opt --fir-to-llvm-ir | FileCheck %s --check-prefixes="OMPDialect" !=============================================================================== ! parallel construct with function call which has master construct internally diff --git a/flang/test/Lower/OpenMP/FIR/ordered-threads.f90 b/flang/test/Lower/OpenMP/FIR/ordered-threads.f90 index 2e6afe2125b1a6a650f6c59146e502880801ae66..2dea4c857e877dc8d75c1f21a4ee58aa299ea349 100644 --- a/flang/test/Lower/OpenMP/FIR/ordered-threads.f90 +++ b/flang/test/Lower/OpenMP/FIR/ordered-threads.f90 @@ -10,8 +10,8 @@ subroutine ordered integer :: i integer :: a(20) -!FIRDialect: omp.ordered_region { -!LLVMIRDialect: omp.ordered_region { +!FIRDialect: omp.ordered.region { +!LLVMIRDialect: omp.ordered.region { !LLVMIR: [[TMP0:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB0:[0-9]+]]) !LLVMIR-NEXT: call void @__kmpc_ordered(ptr @[[GLOB0]], i32 [[TMP0]]) !$OMP ORDERED @@ -23,8 +23,8 @@ subroutine ordered !LLVMIR: call void @__kmpc_end_ordered(ptr @[[GLOB0]], i32 [[TMP0]]) !$OMP END ORDERED -!FIRDialect: omp.ordered_region { -!LLVMIRDialect: omp.ordered_region { +!FIRDialect: omp.ordered.region { +!LLVMIRDialect: omp.ordered.region { !LLVMIR: [[TMP1:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]]) !LLVMIR-NEXT: call void @__kmpc_ordered(ptr @[[GLOB1]], i32 [[TMP1]]) !$OMP ORDERED THREADS diff --git a/flang/test/Lower/OpenMP/FIR/parallel-reduction-add-byref.f90 b/flang/test/Lower/OpenMP/FIR/parallel-reduction-add-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..ea45e716ceaee18529b90cd1fe3905fd12b210be --- /dev/null +++ b/flang/test/Lower/OpenMP/FIR/parallel-reduction-add-byref.f90 @@ -0,0 +1,117 @@ +! RUN: bbc -emit-fir -hlfir=false -fopenmp --force-byref-reduction -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -mmlir --force-byref-reduction -o - %s 2>&1 | FileCheck %s + +!CHECK-LABEL: omp.declare_reduction +!CHECK-SAME: @[[RED_F32_NAME:.*]] : !fir.ref<f32> +!CHECK-SAME: init { +!CHECK: ^bb0(%{{.*}}: !fir.ref<f32>): +!CHECK: %[[C0_1:.*]] = arith.constant 0.000000e+00 : f32 +!CHECK: %[[REF:.*]] = fir.alloca f32 +!CHECKL fir.store [[%C0_1]] to %[[REF]] : !fir.ref<f32> +!CHECK: omp.yield(%[[REF]] : !fir.ref<f32>) +!CHECK: } combiner { +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<f32>, %[[ARG1:.*]]: !fir.ref<f32>): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<f32> +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<f32> +!CHECK: %[[RES:.*]] = arith.addf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<f32> +!CHECK: omp.yield(%[[ARG0]] : !fir.ref<f32>) +!CHECK: } + +!CHECK-LABEL: omp.declare_reduction +!CHECK-SAME: @[[RED_I32_NAME:.*]] : !fir.ref<i32> +!CHECK-SAME: init { +!CHECK: ^bb0(%{{.*}}: !fir.ref<i32>): +!CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +!CHECK: %[[REF:.*]] = fir.alloca i32 +!CHECKL fir.store [[%C0_1]] to %[[REF]] : !fir.ref<i32> +!CHECK: omp.yield(%[[REF]] : !fir.ref<i32>) +!CHECK: } combiner { +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> +!CHECK: %[[RES:.*]] = arith.addi %[[LD0]], %[[LD1]] : i32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i32> +!CHECK: omp.yield(%[[ARG0]] : !fir.ref<i32>) +!CHECK: } + +!CHECK-LABEL: func.func @_QPsimple_int_add +!CHECK: %[[IREF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_int_addEi"} +!CHECK: %[[I_START:.*]] = arith.constant 0 : i32 +!CHECK: fir.store %[[I_START]] to %[[IREF]] : !fir.ref<i32> +!CHECK: omp.parallel byref reduction(@[[RED_I32_NAME]] %[[IREF]] -> %[[PRV:.+]] : !fir.ref<i32>) { +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV]] : !fir.ref<i32> +!CHECK: %[[I_INCR:.+]] = arith.constant 1 : i32 +!CHECK: %[[RES:.+]] = arith.addi %[[LPRV]], %[[I_INCR]] +!CHECK: fir.store %[[RES]] to %[[PRV]] : !fir.ref<i32> +!CHECK: omp.terminator +!CHECK: } +!CHECK: return +subroutine simple_int_add + integer :: i + i = 0 + + !$omp parallel reduction(+:i) + i = i + 1 + !$omp end parallel + + print *, i +end subroutine + +!CHECK-LABEL: func.func @_QPsimple_real_add +!CHECK: %[[RREF:.*]] = fir.alloca f32 {bindc_name = "r", uniq_name = "_QFsimple_real_addEr"} +!CHECK: %[[R_START:.*]] = arith.constant 0.000000e+00 : f32 +!CHECK: fir.store %[[R_START]] to %[[RREF]] : !fir.ref<f32> +!CHECK: omp.parallel byref reduction(@[[RED_F32_NAME]] %[[RREF]] -> %[[PRV:.+]] : !fir.ref<f32>) { +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV]] : !fir.ref<f32> +!CHECK: %[[R_INCR:.+]] = arith.constant 1.500000e+00 : f32 +!CHECK: %[[RES]] = arith.addf %[[LPRV]], %[[R_INCR]] {{.*}} : f32 +!CHECK: fir.store %[[RES]] to %[[PRV]] : !fir.ref<f32> +!CHECK: omp.terminator +!CHECK: } +!CHECK: return +subroutine simple_real_add + real :: r + r = 0.0 + + !$omp parallel reduction(+:r) + r = r + 1.5 + !$omp end parallel + + print *, r +end subroutine + +!CHECK-LABEL: func.func @_QPint_real_add +!CHECK: %[[IREF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFint_real_addEi"} +!CHECK: %[[RREF:.*]] = fir.alloca f32 {bindc_name = "r", uniq_name = "_QFint_real_addEr"} +!CHECK: %[[R_START:.*]] = arith.constant 0.000000e+00 : f32 +!CHECK: fir.store %[[R_START]] to %[[RREF]] : !fir.ref<f32> +!CHECK: %[[I_START:.*]] = arith.constant 0 : i32 +!CHECK: fir.store %[[I_START]] to %[[IREF]] : !fir.ref<i32> +!CHECK: omp.parallel byref reduction(@[[RED_I32_NAME]] %[[IREF]] -> %[[PRV0:.+]] : !fir.ref<i32>, @[[RED_F32_NAME]] %[[RREF]] -> %[[PRV1:.+]] : !fir.ref<f32>) { +!CHECK: %[[R_INCR:.*]] = arith.constant 1.500000e+00 : f32 +!CHECK: %[[LPRV1:.+]] = fir.load %[[PRV1]] : !fir.ref<f32> +!CHECK: %[[RES1:.+]] = arith.addf %[[R_INCR]], %[[LPRV1]] {{.*}} : f32 +!CHECK: fir.store %[[RES1]] to %[[PRV1]] +!CHECK: %[[LPRV0:.+]] = fir.load %[[PRV0]] : !fir.ref<i32> +!CHECK: %[[I_INCR:.*]] = arith.constant 3 : i32 +!CHECK: %[[RES0:.+]] = arith.addi %[[LPRV0]], %[[I_INCR]] +!CHECK: fir.store %[[RES0]] to %[[PRV0]] +!CHECK: omp.terminator +!CHECK: } +!CHECK: return +subroutine int_real_add + real :: r + integer :: i + + r = 0.0 + i = 0 + + !$omp parallel reduction(+:i,r) + r = 1.5 + r + i = i + 3 + !$omp end parallel + + print *, r + print *, i +end subroutine diff --git a/flang/test/Lower/OpenMP/FIR/parallel-reduction-add.f90 b/flang/test/Lower/OpenMP/FIR/parallel-reduction-add.f90 index 4b223e822760a99268926a3befcfffc8e6bbef5a..3f6d9e647c9bdacb9da591623bed7b25d912d572 100644 --- a/flang/test/Lower/OpenMP/FIR/parallel-reduction-add.f90 +++ b/flang/test/Lower/OpenMP/FIR/parallel-reduction-add.f90 @@ -1,7 +1,7 @@ ! RUN: bbc -emit-fir -hlfir=false -fopenmp -o - %s 2>&1 | FileCheck %s ! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s -!CHECK-LABEL: omp.reduction.declare +!CHECK-LABEL: omp.declare_reduction !CHECK-SAME: @[[RED_F32_NAME:.*]] : f32 init { !CHECK: ^bb0(%{{.*}}: f32): !CHECK: %[[C0_1:.*]] = arith.constant 0.000000e+00 : f32 @@ -12,7 +12,7 @@ !CHECK: omp.yield(%[[RES]] : f32) !CHECK: } -!CHECK-LABEL: omp.reduction.declare +!CHECK-LABEL: omp.declare_reduction !CHECK-SAME: @[[RED_I32_NAME:.*]] : i32 init { !CHECK: ^bb0(%{{.*}}: i32): !CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 diff --git a/flang/test/Lower/OpenMP/FIR/parallel-sections.f90 b/flang/test/Lower/OpenMP/FIR/parallel-sections.f90 index 33fda178323f2b741d8417c2d97756ebb92512c4..0c0834cfafe9c3d8123f195f2064e7e57b7ea422 100644 --- a/flang/test/Lower/OpenMP/FIR/parallel-sections.f90 +++ b/flang/test/Lower/OpenMP/FIR/parallel-sections.f90 @@ -1,5 +1,7 @@ +! REQUIRES: openmp_runtime + !RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | FileCheck %s --check-prefixes="FIRDialect,OMPDialect" -!RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | fir-opt --cfg-conversion | fir-opt --fir-to-llvm-ir | FileCheck %s --check-prefixes="OMPDialect,LLVMDialect" +!RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | fir-opt --cfg-conversion-on-func-opt | fir-opt --fir-to-llvm-ir | FileCheck %s --check-prefixes="OMPDialect,LLVMDialect" !=============================================================================== ! Parallel sections construct @@ -38,16 +40,16 @@ end subroutine omp_parallel_sections subroutine omp_parallel_sections_allocate(x, y) use omp_lib integer, intent(inout) :: x, y - !FIRDialect: %[[allocator_1:.*]] = arith.constant 1 : i32 - !FIRDialect: %[[allocator_2:.*]] = arith.constant 1 : i32 - !LLVMDialect: %[[allocator_1:.*]] = llvm.mlir.constant(1 : i32) : i32 - !LLVMDialect: %[[allocator_2:.*]] = llvm.mlir.constant(1 : i32) : i32 + !FIRDialect: %[[allocator_1:.*]] = arith.constant 4 : i64 + !FIRDialect: %[[allocator_2:.*]] = arith.constant 4 : i64 + !LLVMDialect: %[[allocator_1:.*]] = llvm.mlir.constant(4 : i64) : i64 + !LLVMDialect: %[[allocator_2:.*]] = llvm.mlir.constant(4 : i64) : i64 !OMPDialect: omp.parallel allocate( - !FIRDialect: %[[allocator_2]] : i32 -> %{{.*}} : !fir.ref<i32>) { - !LLVMDialect: %[[allocator_2]] : i32 -> %{{.*}} : !llvm.ptr) { + !FIRDialect: %[[allocator_2]] : i64 -> %{{.*}} : !fir.ref<i32>) { + !LLVMDialect: %[[allocator_2]] : i64 -> %{{.*}} : !llvm.ptr) { !OMPDialect: omp.sections allocate( - !FIRDialect: %[[allocator_1]] : i32 -> %{{.*}} : !fir.ref<i32>) { - !LLVMDialect: %[[allocator_1]] : i32 -> %{{.*}} : !llvm.ptr) { + !FIRDialect: %[[allocator_1]] : i64 -> %{{.*}} : !fir.ref<i32>) { + !LLVMDialect: %[[allocator_1]] : i64 -> %{{.*}} : !llvm.ptr) { !$omp parallel sections allocate(omp_high_bw_mem_alloc: x) !OMPDialect: omp.section { !$omp section diff --git a/flang/test/Lower/OpenMP/FIR/parallel.f90 b/flang/test/Lower/OpenMP/FIR/parallel.f90 index b68551df23416118415afaa268c20403e56da9a6..a2ceb2d939f258600769b72dd0d2441cd48faa6a 100644 --- a/flang/test/Lower/OpenMP/FIR/parallel.f90 +++ b/flang/test/Lower/OpenMP/FIR/parallel.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + !RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | FileCheck %s --check-prefixes="FIRDialect,OMPDialect" !RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | fir-opt --fir-to-llvm-ir | FileCheck %s --check-prefixes="LLVMDialect,OMPDialect" @@ -153,8 +155,8 @@ subroutine parallel_allocate() use omp_lib integer :: x !OMPDialect: omp.parallel allocate( - !FIRDialect: %{{.+}} : i32 -> %{{.+}} : !fir.ref<i32> - !LLVMDialect: %{{.+}} : i32 -> %{{.+}} : !llvm.ptr + !FIRDialect: %{{.+}} : i64 -> %{{.+}} : !fir.ref<i32> + !LLVMDialect: %{{.+}} : i64 -> %{{.+}} : !llvm.ptr !OMPDialect: ) { !$omp parallel allocate(omp_high_bw_mem_alloc: x) private(x) !FIRDialect: arith.addi @@ -195,8 +197,8 @@ subroutine parallel_multiple_clauses(alpha, num_threads) !$omp end parallel !OMPDialect: omp.parallel if({{.*}} : i1) num_threads({{.*}} : i32) allocate( - !FIRDialect: %{{.+}} : i32 -> %{{.+}} : !fir.ref<i32> - !LLVMDialect: %{{.+}} : i32 -> %{{.+}} : !llvm.ptr + !FIRDialect: %{{.+}} : i64 -> %{{.+}} : !fir.ref<i32> + !LLVMDialect: %{{.+}} : i64 -> %{{.+}} : !llvm.ptr !OMPDialect: ) { !$omp parallel num_threads(num_threads) if(alpha .le. 0) allocate(omp_high_bw_mem_alloc: alpha) private(alpha) !FIRDialect: fir.call diff --git a/flang/test/Lower/OpenMP/FIR/sections.f90 b/flang/test/Lower/OpenMP/FIR/sections.f90 index 640ec34a05bc21bf83a3cce11631872d857ee118..7b313f3dc0b41fd2414045a0a29a6d0430a0d4e9 100644 --- a/flang/test/Lower/OpenMP/FIR/sections.f90 +++ b/flang/test/Lower/OpenMP/FIR/sections.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! This test checks the lowering of OpenMP sections construct with several clauses present ! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | FileCheck %s @@ -5,8 +7,8 @@ !CHECK: func @_QQmain() attributes {fir.bindc_name = "sample"} { !CHECK: %[[COUNT:.*]] = fir.address_of(@_QFEcount) : !fir.ref<i32> !CHECK: %[[ETA:.*]] = fir.alloca f32 {bindc_name = "eta", uniq_name = "_QFEeta"} -!CHECK: %[[CONST_1:.*]] = arith.constant 1 : i32 -!CHECK: omp.sections allocate(%[[CONST_1]] : i32 -> %0 : !fir.ref<i32>) { +!CHECK: %[[CONST_1:.*]] = arith.constant 4 : i64 +!CHECK: omp.sections allocate(%[[CONST_1]] : i64 -> %0 : !fir.ref<i32>) { !CHECK: omp.section { !CHECK: %[[PRIVATE_ETA:.*]] = fir.alloca f32 {bindc_name = "eta", pinned, uniq_name = "_QFEeta"} !CHECK: %[[PRIVATE_DOUBLE_COUNT:.*]] = fir.alloca i32 {bindc_name = "double_count", pinned, uniq_name = "_QFEdouble_count"} diff --git a/flang/test/Lower/OpenMP/FIR/single.f90 b/flang/test/Lower/OpenMP/FIR/single.f90 index 266f6d94c60db4383543526eaadc21eba37ec143..65ae07c2c28431f06c7a04ca8a0a6bcc864a267a 100644 --- a/flang/test/Lower/OpenMP/FIR/single.f90 +++ b/flang/test/Lower/OpenMP/FIR/single.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + !RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | FileCheck %s !RUN: bbc -emit-fir -hlfir=false -fopenmp %s -o - | FileCheck %s @@ -55,7 +57,7 @@ subroutine single_allocate() integer :: x !CHECK: omp.parallel { !$omp parallel - !CHECK: omp.single allocate(%{{.+}} : i32 -> %{{.+}} : !fir.ref<i32>) { + !CHECK: omp.single allocate(%{{.+}} : i64 -> %{{.+}} : !fir.ref<i32>) { !$omp single allocate(omp_high_bw_mem_alloc: x) private(x) !CHECK: arith.addi x = x + 12 diff --git a/flang/test/Lower/OpenMP/FIR/target.f90 b/flang/test/Lower/OpenMP/FIR/target.f90 index 06772771647de8bbce3ddd713df500cb897fd602..821196b83c3b999a89b946b2f2dd3724088c3ad8 100644 --- a/flang/test/Lower/OpenMP/FIR/target.f90 +++ b/flang/test/Lower/OpenMP/FIR/target.f90 @@ -7,8 +7,8 @@ !CHECK-LABEL: func.func @_QPomp_target_enter_simple() { subroutine omp_target_enter_simple integer :: a(1024) - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target_enter_data map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target enter data map(to: a) end subroutine omp_target_enter_simple @@ -23,14 +23,14 @@ subroutine omp_target_enter_mt integer :: b(1024) integer :: c(1024) integer :: d(1024) - !CHECK: %[[BOUNDS_0:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_0:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS_0]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} - !CHECK: %[[BOUNDS_1:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_1:.*]] = omp.map_info var_ptr(%{{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS_1]]) -> !fir.ref<!fir.array<1024xi32>> {name = "b"} - !CHECK: %[[BOUNDS_2:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_2:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(always, exit_release_or_enter_alloc) capture(ByRef) bounds(%[[BOUNDS_2]]) -> !fir.ref<!fir.array<1024xi32>> {name = "c"} - !CHECK: %[[BOUNDS_3:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_3:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS_3]]) -> !fir.ref<!fir.array<1024xi32>> {name = "d"} + !CHECK: %[[BOUNDS_0:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_0:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS_0]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS_1:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_1:.*]] = omp.map.info var_ptr(%{{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS_1]]) -> !fir.ref<!fir.array<1024xi32>> {name = "b"} + !CHECK: %[[BOUNDS_2:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_2:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(always, exit_release_or_enter_alloc) capture(ByRef) bounds(%[[BOUNDS_2]]) -> !fir.ref<!fir.array<1024xi32>> {name = "c"} + !CHECK: %[[BOUNDS_3:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_3:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS_3]]) -> !fir.ref<!fir.array<1024xi32>> {name = "d"} !CHECK: omp.target_enter_data map_entries(%[[MAP_0]], %[[MAP_1]], %[[MAP_2]], %[[MAP_3]] : !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>) !$omp target enter data map(to: a, b) map(always, alloc: c) map(to: d) end subroutine omp_target_enter_mt @@ -42,8 +42,8 @@ end subroutine omp_target_enter_mt !CHECK-LABEL: func.func @_QPomp_target_enter_nowait() { subroutine omp_target_enter_nowait integer :: a(1024) - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target_enter_data nowait map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target enter data map(to: a) nowait end subroutine omp_target_enter_nowait @@ -60,8 +60,8 @@ subroutine omp_target_enter_if !CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_1:.*]] : !fir.ref<i32> !CHECK: %[[VAL_4:.*]] = arith.constant 10 : i32 !CHECK: %[[VAL_5:.*]] = arith.cmpi slt, %[[VAL_3]], %[[VAL_4]] : i32 - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target_enter_data if(%[[VAL_5]] : i1) map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target enter data if(i<10) map(to: a) end subroutine omp_target_enter_if @@ -74,8 +74,8 @@ end subroutine omp_target_enter_if subroutine omp_target_enter_device integer :: a(1024) !CHECK: %[[VAL_1:.*]] = arith.constant 2 : i32 - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target_enter_data device(%[[VAL_1]] : i32) map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target enter data map(to: a) device(2) end subroutine omp_target_enter_device @@ -87,8 +87,8 @@ end subroutine omp_target_enter_device !CHECK-LABEL: func.func @_QPomp_target_exit_simple() { subroutine omp_target_exit_simple integer :: a(1024) - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target_exit_data map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target exit data map(from: a) end subroutine omp_target_exit_simple @@ -104,16 +104,16 @@ subroutine omp_target_exit_mt integer :: c(1024) integer :: d(1024) integer :: e(1024) - !CHECK: %[[BOUNDS_0:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_0:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS_0]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} - !CHECK: %[[BOUNDS_1:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_1:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS_1]]) -> !fir.ref<!fir.array<1024xi32>> {name = "b"} - !CHECK: %[[BOUNDS_2:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_2:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%[[BOUNDS_2]]) -> !fir.ref<!fir.array<1024xi32>> {name = "c"} - !CHECK: %[[BOUNDS_3:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_3:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(always, delete) capture(ByRef) bounds(%[[BOUNDS_3]]) -> !fir.ref<!fir.array<1024xi32>> {name = "d"} - !CHECK: %[[BOUNDS_4:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_4:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS_4]]) -> !fir.ref<!fir.array<1024xi32>> {name = "e"} + !CHECK: %[[BOUNDS_0:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_0:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS_0]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS_1:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_1:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS_1]]) -> !fir.ref<!fir.array<1024xi32>> {name = "b"} + !CHECK: %[[BOUNDS_2:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_2:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%[[BOUNDS_2]]) -> !fir.ref<!fir.array<1024xi32>> {name = "c"} + !CHECK: %[[BOUNDS_3:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_3:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(always, delete) capture(ByRef) bounds(%[[BOUNDS_3]]) -> !fir.ref<!fir.array<1024xi32>> {name = "d"} + !CHECK: %[[BOUNDS_4:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_4:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS_4]]) -> !fir.ref<!fir.array<1024xi32>> {name = "e"} !CHECK: omp.target_exit_data map_entries(%[[MAP_0]], %[[MAP_1]], %[[MAP_2]], %[[MAP_3]], %[[MAP_4]] : !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>) !$omp target exit data map(from: a,b) map(release: c) map(always, delete: d) map(from: e) end subroutine omp_target_exit_mt @@ -127,8 +127,8 @@ subroutine omp_target_exit_device integer :: a(1024) integer :: d !CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1:.*]] : !fir.ref<i32> - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target_exit_data device(%[[VAL_2]] : i32) map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target exit data map(from: a) device(d) end subroutine omp_target_exit_device @@ -141,13 +141,13 @@ subroutine omp_target_update_to integer :: a(1024) !CHECK-DAG: %[[A_ALLOC:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFomp_target_update_toEa"} - !CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds + !CHECK-DAG: %[[BOUNDS:.*]] = omp.map.bounds - !CHECK: %[[TO_MAP:.*]] = omp.map_info var_ptr(%[[A_ALLOC]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) + !CHECK: %[[TO_MAP:.*]] = omp.map.info var_ptr(%[[A_ALLOC]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) !CHECK-SAME: map_clauses(to) capture(ByRef) !CHECK-SAME: bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} - !CHECK: omp.target_update_data + !CHECK: omp.target_update !CHECK-SAME: motion_entries(%[[TO_MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target update to(a) end subroutine omp_target_update_to @@ -160,13 +160,13 @@ subroutine omp_target_update_from integer :: a(1024) !CHECK-DAG: %[[A_ALLOC:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFomp_target_update_fromEa"} - !CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds + !CHECK-DAG: %[[BOUNDS:.*]] = omp.map.bounds - !CHECK: %[[FROM_MAP:.*]] = omp.map_info var_ptr(%[[A_ALLOC]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) + !CHECK: %[[FROM_MAP:.*]] = omp.map.info var_ptr(%[[A_ALLOC]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) !CHECK-SAME: map_clauses(from) capture(ByRef) !CHECK-SAME: bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} - !CHECK: omp.target_update_data + !CHECK: omp.target_update !CHECK-SAME: motion_entries(%[[FROM_MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target update from(a) end subroutine omp_target_update_from @@ -180,12 +180,12 @@ subroutine omp_target_update_if logical :: i !CHECK-DAG: %[[A_ALLOC:.*]] = fir.alloca - !CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds + !CHECK-DAG: %[[BOUNDS:.*]] = omp.map.bounds !CHECK-DAG: %[[COND:.*]] = fir.convert %{{.*}} : (!fir.logical<4>) -> i1 - !CHECK: %[[TO_MAP:.*]] = omp.map_info + !CHECK: %[[TO_MAP:.*]] = omp.map.info - !CHECK: omp.target_update_data if(%[[COND]] : i1) + !CHECK: omp.target_update if(%[[COND]] : i1) !CHECK-SAME: motion_entries(%[[TO_MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target update to(a) if(i) end subroutine omp_target_update_if @@ -198,12 +198,12 @@ subroutine omp_target_update_device integer :: a(1024) !CHECK-DAG: %[[A_ALLOC:.*]] = fir.alloca - !CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds + !CHECK-DAG: %[[BOUNDS:.*]] = omp.map.bounds !CHECK-DAG: %[[DEVICE:.*]] = arith.constant 1 : i32 - !CHECK: %[[TO_MAP:.*]] = omp.map_info + !CHECK: %[[TO_MAP:.*]] = omp.map.info - !CHECK: omp.target_update_data + !CHECK: omp.target_update !CHECK-SAME: device(%[[DEVICE]] : i32) !CHECK-SAME: motion_entries(%[[TO_MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target update to(a) device(1) @@ -217,11 +217,11 @@ subroutine omp_target_update_nowait integer :: a(1024) !CHECK-DAG: %[[A_ALLOC:.*]] = fir.alloca - !CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds + !CHECK-DAG: %[[BOUNDS:.*]] = omp.map.bounds - !CHECK: %[[TO_MAP:.*]] = omp.map_info + !CHECK: %[[TO_MAP:.*]] = omp.map.info - !CHECK: omp.target_update_data + !CHECK: omp.target_update !CHECK-SAME: nowait !CHECK-SAME: motion_entries(%[[TO_MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target update to(a) nowait @@ -235,8 +235,8 @@ end subroutine omp_target_update_nowait subroutine omp_target_data !CHECK: %[[VAL_0:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFomp_target_dataEa"} integer :: a(1024) - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr(%[[VAL_0]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target_data map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) { !$omp target data map(tofrom: a) !CHECK: %[[VAL_1:.*]] = arith.constant 10 : i32 @@ -257,15 +257,15 @@ subroutine omp_target_data_mt integer :: b(1024) !CHECK: %[[VAR_A:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFomp_target_data_mtEa"} !CHECK: %[[VAR_B:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "b", uniq_name = "_QFomp_target_data_mtEb"} - !CHECK: %[[BOUNDS_A:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_A:.*]] = omp.map_info var_ptr(%[[VAR_A]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_A]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS_A:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAR_A]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_A]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target_data map_entries(%[[MAP_A]] : !fir.ref<!fir.array<1024xi32>>) { !$omp target data map(a) !CHECK: omp.terminator !$omp end target data !CHECK: } - !CHECK: %[[BOUNDS_B:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_B:.*]] = omp.map_info var_ptr(%[[VAR_B]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(always, from) capture(ByRef) bounds(%[[BOUNDS_B]]) -> !fir.ref<!fir.array<1024xi32>> {name = "b"} + !CHECK: %[[BOUNDS_B:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_B:.*]] = omp.map.info var_ptr(%[[VAR_B]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(always, from) capture(ByRef) bounds(%[[BOUNDS_B]]) -> !fir.ref<!fir.array<1024xi32>> {name = "b"} !CHECK: omp.target_data map_entries(%[[MAP_B]] : !fir.ref<!fir.array<1024xi32>>) { !$omp target data map(always, from : b) !CHECK: omp.terminator @@ -281,8 +281,8 @@ end subroutine omp_target_data_mt subroutine omp_target !CHECK: %[[VAL_0:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFomp_targetEa"} integer :: a(1024) - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr(%[[VAL_0]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target map_entries(%[[MAP]] -> %[[ARG_0:.*]] : !fir.ref<!fir.array<1024xi32>>) { !CHECK: ^bb0(%[[ARG_0]]: !fir.ref<!fir.array<1024xi32>>): !$omp target map(tofrom: a) @@ -306,7 +306,7 @@ end subroutine omp_target subroutine omp_target_implicit !CHECK: %[[VAL_0:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFomp_target_implicitEa"} integer :: a(1024) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr(%[[VAL_0]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds(%{{.*}}) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds(%{{.*}}) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target map_entries(%[[MAP]] -> %[[ARG_0:.*]] : !fir.ref<!fir.array<1024xi32>>) { !CHECK: ^bb0(%[[ARG_0]]: !fir.ref<!fir.array<1024xi32>>): !$omp target @@ -366,12 +366,12 @@ subroutine omp_target_implicit_bounds(n) !CHECK: %[[VAL_13:.*]] = arith.constant 1 : index !CHECK: %[[VAL_14:.*]] = arith.constant 0 : index !CHECK: %[[VAL_15:.*]] = arith.subi %[[VAL_6]], %[[VAL_13]] : index - !CHECK: %[[VAL_16:.*]] = omp.bounds lower_bound(%[[VAL_14]] : index) upper_bound(%[[VAL_15]] : index) extent(%[[VAL_6]] : index) stride(%[[VAL_13]] : index) start_idx(%[[VAL_13]] : index) + !CHECK: %[[VAL_16:.*]] = omp.map.bounds lower_bound(%[[VAL_14]] : index) upper_bound(%[[VAL_15]] : index) extent(%[[VAL_6]] : index) stride(%[[VAL_13]] : index) start_idx(%[[VAL_13]] : index) !CHECK: %[[VAL_17:.*]] = arith.constant 0 : index !CHECK: %[[VAL_18:.*]] = arith.subi %[[VAL_11]], %[[VAL_13]] : index - !CHECK: %[[VAL_19:.*]] = omp.bounds lower_bound(%[[VAL_17]] : index) upper_bound(%[[VAL_18]] : index) extent(%[[VAL_11]] : index) stride(%[[VAL_13]] : index) start_idx(%[[VAL_13]] : index) - !CHECK: %[[VAL_20:.*]] = omp.map_info var_ptr(%[[VAL_12]] : !fir.ref<!fir.array<?x1024xi32>>, !fir.array<?x1024xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds(%[[VAL_16]], %[[VAL_19]]) -> !fir.ref<!fir.array<?x1024xi32>> {name = "a"} - !CHECK: %[[VAL_21:.*]] = omp.map_info var_ptr(%[[VAL_COPY]] : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = ""} + !CHECK: %[[VAL_19:.*]] = omp.map.bounds lower_bound(%[[VAL_17]] : index) upper_bound(%[[VAL_18]] : index) extent(%[[VAL_11]] : index) stride(%[[VAL_13]] : index) start_idx(%[[VAL_13]] : index) + !CHECK: %[[VAL_20:.*]] = omp.map.info var_ptr(%[[VAL_12]] : !fir.ref<!fir.array<?x1024xi32>>, !fir.array<?x1024xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds(%[[VAL_16]], %[[VAL_19]]) -> !fir.ref<!fir.array<?x1024xi32>> {name = "a"} + !CHECK: %[[VAL_21:.*]] = omp.map.info var_ptr(%[[VAL_COPY]] : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = ""} !CHECK: omp.target map_entries(%[[VAL_20]] -> %[[VAL_22:.*]], %[[VAL_21]] -> %[[VAL_23:.*]] : !fir.ref<!fir.array<?x1024xi32>>, !fir.ref<i32>) { !CHECK: ^bb0(%[[VAL_22]]: !fir.ref<!fir.array<?x1024xi32>>, %[[VAL_23]]: !fir.ref<i32>): !$omp target @@ -412,7 +412,7 @@ end subroutine omp_target_implicit_bounds subroutine omp_target_thread_limit integer :: a !CHECK: %[[VAL_1:.*]] = arith.constant 64 : i32 - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(tofrom) capture(ByRef) -> !fir.ref<i32> {name = "a"} + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(tofrom) capture(ByRef) -> !fir.ref<i32> {name = "a"} !CHECK: omp.target thread_limit(%[[VAL_1]] : i32) map_entries(%[[MAP]] -> %[[ARG_0:.*]] : !fir.ref<i32>) { !CHECK: ^bb0(%[[ARG_0]]: !fir.ref<i32>): !$omp target map(tofrom: a) thread_limit(64) @@ -431,7 +431,7 @@ subroutine omp_target_device_ptr use iso_c_binding, only : c_ptr, c_loc type(c_ptr) :: a integer, target :: b - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(tofrom) capture(ByRef) -> {{.*}} {name = "a"} + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(tofrom) capture(ByRef) -> {{.*}} {name = "a"} !CHECK: omp.target_data map_entries(%[[MAP]]{{.*}} !$omp target data map(tofrom: a) use_device_ptr(a) !CHECK: ^bb0(%[[VAL_1:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>): @@ -450,8 +450,8 @@ end subroutine omp_target_device_ptr subroutine omp_target_device_addr integer, pointer :: a !CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "a", uniq_name = "_QFomp_target_device_addrEa"} - !CHECK: %[[MAP_MEMBERS:.*]] = omp.map_info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, i32) var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<i32>>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""} - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBERS]] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "a"} + !CHECK: %[[MAP_MEMBERS:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, i32) var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<i32>>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""} + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBERS]] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "a"} !CHECK: omp.target_data map_entries(%[[MAP_MEMBERS]], %[[MAP]] : {{.*}}) use_device_addr(%[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<i32>>>) { !$omp target data map(tofrom: a) use_device_addr(a) !CHECK: ^bb0(%[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.ptr<i32>>>): @@ -476,9 +476,9 @@ subroutine omp_target_parallel_do !CHECK: %[[C1:.*]] = arith.constant 1 : index !CHECK: %[[C0:.*]] = arith.constant 0 : index !CHECK: %[[SUB:.*]] = arith.subi %[[C1024]], %[[C1]] : index - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C0]] : index) upper_bound(%[[SUB]] : index) extent(%[[C1024]] : index) stride(%[[C1]] : index) start_idx(%[[C1]] : index) - !CHECK: %[[MAP1:.*]] = omp.map_info var_ptr(%[[VAL_0]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} - !CHECK: %[[MAP2:.*]] = omp.map_info var_ptr(%[[VAL_1]] : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = "i"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%[[C0]] : index) upper_bound(%[[SUB]] : index) extent(%[[C1024]] : index) stride(%[[C1]] : index) start_idx(%[[C1]] : index) + !CHECK: %[[MAP1:.*]] = omp.map.info var_ptr(%[[VAL_0]] : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[MAP2:.*]] = omp.map.info var_ptr(%[[VAL_1]] : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = "i"} !CHECK: omp.target map_entries(%[[MAP1]] -> %[[VAL_2:.*]], %[[MAP2]] -> %[[VAL_3:.*]] : !fir.ref<!fir.array<1024xi32>>, !fir.ref<i32>) { !CHECK: ^bb0(%[[VAL_2]]: !fir.ref<!fir.array<1024xi32>>, %[[VAL_3]]: !fir.ref<i32>): !CHECK-NEXT: omp.parallel diff --git a/flang/test/Lower/OpenMP/FIR/task.f90 b/flang/test/Lower/OpenMP/FIR/task.f90 index 4e7e54588c796f6e36799356159b7459008918cb..012ac757d304a8cdf6f2e4794016aa01cf9a427f 100644 --- a/flang/test/Lower/OpenMP/FIR/task.f90 +++ b/flang/test/Lower/OpenMP/FIR/task.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + !RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | FileCheck %s !CHECK-LABEL: func @_QPomp_task_simple() { @@ -63,7 +65,7 @@ end subroutine omp_task_priority subroutine task_allocate() use omp_lib integer :: x - !CHECK: omp.task allocate(%{{.+}} : i32 -> %{{.+}} : !fir.ref<i32>) { + !CHECK: omp.task allocate(%{{.+}} : i64 -> %{{.+}} : !fir.ref<i32>) { !$omp task allocate(omp_high_bw_mem_alloc: x) private(x) !CHECK: arith.addi x = x + 12 @@ -217,7 +219,7 @@ subroutine task_multiple_clauses() integer :: x, y, z logical :: buzz - !CHECK: omp.task if(%{{.+}}) final(%{{.+}}) priority(%{{.+}}) allocate(%{{.+}} : i32 -> %{{.+}} : !fir.ref<i32>) { + !CHECK: omp.task if(%{{.+}}) final(%{{.+}}) priority(%{{.+}}) allocate(%{{.+}} : i64 -> %{{.+}} : !fir.ref<i32>) { !$omp task if(buzz) final(buzz) priority(z) allocate(omp_high_bw_mem_alloc: x) private(x) firstprivate(y) !CHECK: %[[x_priv:.+]] = fir.alloca i32 diff --git a/flang/test/Lower/OpenMP/FIR/taskgroup.f90 b/flang/test/Lower/OpenMP/FIR/taskgroup.f90 index 55aba3ddb6c20c891b285ea60500ecee0ef85aef..78b9da8e9b098874c8160b2001554284154056b0 100644 --- a/flang/test/Lower/OpenMP/FIR/taskgroup.f90 +++ b/flang/test/Lower/OpenMP/FIR/taskgroup.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + !RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | FileCheck %s !CHECK-LABEL: @_QPomp_taskgroup @@ -5,9 +7,9 @@ subroutine omp_taskgroup use omp_lib integer :: allocated_x !CHECK-DAG: %{{.*}} = fir.alloca i32 {bindc_name = "allocated_x", uniq_name = "_QFomp_taskgroupEallocated_x"} -!CHECK-DAG: %{{.*}} = arith.constant 1 : i32 +!CHECK-DAG: %{{.*}} = arith.constant 4 : i64 -!CHECK: omp.taskgroup allocate(%{{.*}} : i32 -> %0 : !fir.ref<i32>) +!CHECK: omp.taskgroup allocate(%{{.*}} : i64 -> %0 : !fir.ref<i32>) !$omp taskgroup allocate(omp_high_bw_mem_alloc: allocated_x) !$omp task !CHECK: fir.call @_QPwork() {{.*}}: () -> () diff --git a/flang/test/Lower/OpenMP/FIR/teams.f90 b/flang/test/Lower/OpenMP/FIR/teams.f90 index 51f9087acb0b598935fc97e1a42681c22a7b03fb..9c0593a24f2df1c2041a23e6c3f602b80fd16fc8 100644 --- a/flang/test/Lower/OpenMP/FIR/teams.f90 +++ b/flang/test/Lower/OpenMP/FIR/teams.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s ! CHECK-LABEL: func @_QPteams_simple @@ -104,8 +106,9 @@ end subroutine teams_threadlimit subroutine teams_allocate() use omp_lib integer :: x + integer :: y ! CHECK: omp.teams - ! CHECK-SAME: allocate(%{{.+}} : i32 -> %{{.+}} : !fir.ref<i32>) + ! CHECK-SAME: allocate(%{{.+}} : i64 -> %{{.+}} : !fir.ref<i32>) !$omp teams allocate(omp_high_bw_mem_alloc: x) private(x) ! CHECK: arith.addi x = x + 12 diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-add-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-add-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..08f5a0fcdbae67068cdab5adba9c5ee178b91ad7 --- /dev/null +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-add-byref.f90 @@ -0,0 +1,392 @@ +! RUN: bbc -emit-fir -hlfir=false -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_f64 : !fir.ref<f64> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<f64>): +! CHECK: %[[C0_1:.*]] = arith.constant 0.000000e+00 : f64 +! CHECK: %[[REF:.*]] = fir.alloca f64 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref<f64> +! CHECK: omp.yield(%[[REF]] : !fir.ref<f64>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<f64>, %[[ARG1:.*]]: !fir.ref<f64>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<f64> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<f64> +! CHECK: %[[RES:.*]] = arith.addf %[[LD0]], %[[LD1]] fastmath<contract> : f64 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<f64> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<f64>) +! CHECK: } + +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_i64 : !fir.ref<i64> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i64>): +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i64 +! CHECK: %[[REF:.*]] = fir.alloca i64 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref<i64> +! CHECK: omp.yield(%[[REF]] : !fir.ref<i64>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i64>, %[[ARG1:.*]]: !fir.ref<i64>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i64> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i64> +! CHECK: %[[RES:.*]] = arith.addi %[[LD0]], %[[LD1]] : i64 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i64> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<i64>) +! CHECK: } + +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_f32 : !fir.ref<f32> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<f32>): +! CHECK: %[[C0_1:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: %[[REF:.*]] = fir.alloca f32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref<f32> +! CHECK: omp.yield(%[[REF]] : !fir.ref<f32>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<f32>, %[[ARG1:.*]]: !fir.ref<f32>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<f32> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<f32> +! CHECK: %[[RES:.*]] = arith.addf %[[LD0]], %[[LD1]] fastmath<contract> : f32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<f32> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<f32>) +! CHECK: } + +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_i32 : !fir.ref<i32> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref<i32> +! CHECK: omp.yield(%[[REF]] : !fir.ref<i32>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> +! CHECK: %[[RES:.*]] = arith.addi %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i32> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<i32>) +! CHECK: } + +! CHECK-LABEL: func.func @_QPsimple_int_reduction() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_int_reductionEi"} +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_int_reductionEx"} +! CHECK: %[[VAL_2:.*]] = arith.constant 0 : i32 +! CHECK: fir.store %[[VAL_2]] to %[[VAL_1]] : !fir.ref<i32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_1]] -> %[[VAL_7:.*]] : !fir.ref<i32>) for (%[[VAL_8:.*]]) : i32 = (%[[VAL_4]]) to (%[[VAL_5]]) inclusive step (%[[VAL_6]]) { +! CHECK: fir.store %[[VAL_8]] to %[[VAL_3]] : !fir.ref<i32> +! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_7]] : !fir.ref<i32> +! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_3]] : !fir.ref<i32> +! CHECK: %[[VAL_11:.*]] = arith.addi %[[VAL_9]], %[[VAL_10]] : i32 +! CHECK: fir.store %[[VAL_11]] to %[[VAL_7]] : !fir.ref<i32> +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine simple_int_reduction + integer :: x + x = 0 + !$omp parallel + !$omp do reduction(+:x) + do i=1, 100 + x = x + i + end do + !$omp end do + !$omp end parallel +end subroutine + + +! CHECK-LABEL: func.func @_QPsimple_real_reduction() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_real_reductionEi"} +! CHECK: %[[VAL_1:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFsimple_real_reductionEx"} +! CHECK: %[[VAL_2:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: fir.store %[[VAL_2]] to %[[VAL_1]] : !fir.ref<f32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_f32 %[[VAL_1]] -> %[[VAL_7:.*]] : !fir.ref<f32>) for (%[[VAL_8:.*]]) : i32 = (%[[VAL_4]]) to (%[[VAL_5]]) inclusive step (%[[VAL_6]]) { +! CHECK: fir.store %[[VAL_8]] to %[[VAL_3]] : !fir.ref<i32> +! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_7]] : !fir.ref<f32> +! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_3]] : !fir.ref<i32> +! CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_10]] : (i32) -> f32 +! CHECK: %[[VAL_12:.*]] = arith.addf %[[VAL_9]], %[[VAL_11]] fastmath<contract> : f32 +! CHECK: fir.store %[[VAL_12]] to %[[VAL_7]] : !fir.ref<f32> +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine simple_real_reduction + real :: x + x = 0.0 + !$omp parallel + !$omp do reduction(+:x) + do i=1, 100 + x = x + i + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_int_reduction_switch_order() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_int_reduction_switch_orderEi"} +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_int_reduction_switch_orderEx"} +! CHECK: %[[VAL_2:.*]] = arith.constant 0 : i32 +! CHECK: fir.store %[[VAL_2]] to %[[VAL_1]] : !fir.ref<i32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_1]] -> %[[VAL_7:.*]] : !fir.ref<i32>) for (%[[VAL_8:.*]]) : i32 = (%[[VAL_4]]) to (%[[VAL_5]]) inclusive step (%[[VAL_6]]) { +! CHECK: fir.store %[[VAL_8]] to %[[VAL_3]] : !fir.ref<i32> +! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_3]] : !fir.ref<i32> +! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_7]] : !fir.ref<i32> +! CHECK: %[[VAL_11:.*]] = arith.addi %[[VAL_9]], %[[VAL_10]] : i32 +! CHECK: fir.store %[[VAL_11]] to %[[VAL_7]] : !fir.ref<i32> +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine simple_int_reduction_switch_order + integer :: x + x = 0 + !$omp parallel + !$omp do reduction(+:x) + do i=1, 100 + x = i + x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_real_reduction_switch_order() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_real_reduction_switch_orderEi"} +! CHECK: %[[VAL_1:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFsimple_real_reduction_switch_orderEx"} +! CHECK: %[[VAL_2:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: fir.store %[[VAL_2]] to %[[VAL_1]] : !fir.ref<f32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_f32 %[[VAL_1]] -> %[[VAL_7:.*]] : !fir.ref<f32>) for (%[[VAL_8:.*]]) : i32 = (%[[VAL_4]]) to (%[[VAL_5]]) inclusive step (%[[VAL_6]]) { +! CHECK: fir.store %[[VAL_8]] to %[[VAL_3]] : !fir.ref<i32> +! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_3]] : !fir.ref<i32> +! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i32) -> f32 +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_7]] : !fir.ref<f32> +! CHECK: %[[VAL_12:.*]] = arith.addf %[[VAL_10]], %[[VAL_11]] fastmath<contract> : f32 +! CHECK: fir.store %[[VAL_12]] to %[[VAL_7]] : !fir.ref<f32> +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine simple_real_reduction_switch_order + real :: x + x = 0.0 + !$omp parallel + !$omp do reduction(+:x) + do i=1, 100 + x = i + x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_int_reductions_same_type() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_int_reductions_same_typeEi"} +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFmultiple_int_reductions_same_typeEx"} +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFmultiple_int_reductions_same_typeEy"} +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFmultiple_int_reductions_same_typeEz"} +! CHECK: %[[VAL_4:.*]] = arith.constant 0 : i32 +! CHECK: fir.store %[[VAL_4]] to %[[VAL_1]] : !fir.ref<i32> +! CHECK: %[[VAL_5:.*]] = arith.constant 0 : i32 +! CHECK: fir.store %[[VAL_5]] to %[[VAL_2]] : !fir.ref<i32> +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 +! CHECK: fir.store %[[VAL_6]] to %[[VAL_3]] : !fir.ref<i32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_1]] -> %[[VAL_11:.*]] : !fir.ref<i32>, @add_reduction_byref_i32 %[[VAL_2]] -> %[[VAL_12:.*]] : !fir.ref<i32>, @add_reduction_byref_i32 %[[VAL_3]] -> %[[VAL_13:.*]] : !fir.ref<i32>) for (%[[VAL_14:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) { +! CHECK: fir.store %[[VAL_14]] to %[[VAL_7]] : !fir.ref<i32> +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_11]] : !fir.ref<i32> +! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_7]] : !fir.ref<i32> +! CHECK: %[[VAL_17:.*]] = arith.addi %[[VAL_15]], %[[VAL_16]] : i32 +! CHECK: fir.store %[[VAL_17]] to %[[VAL_11]] : !fir.ref<i32> +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_12]] : !fir.ref<i32> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_7]] : !fir.ref<i32> +! CHECK: %[[VAL_20:.*]] = arith.addi %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: fir.store %[[VAL_20]] to %[[VAL_12]] : !fir.ref<i32> +! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_13]] : !fir.ref<i32> +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_7]] : !fir.ref<i32> +! CHECK: %[[VAL_23:.*]] = arith.addi %[[VAL_21]], %[[VAL_22]] : i32 +! CHECK: fir.store %[[VAL_23]] to %[[VAL_13]] : !fir.ref<i32> +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine multiple_int_reductions_same_type + integer :: x,y,z + x = 0 + y = 0 + z = 0 + !$omp parallel + !$omp do reduction(+:x,y,z) + do i=1, 100 + x = x + i + y = y + i + z = z + i + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_real_reductions_same_type() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_real_reductions_same_typeEi"} +! CHECK: %[[VAL_1:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFmultiple_real_reductions_same_typeEx"} +! CHECK: %[[VAL_2:.*]] = fir.alloca f32 {bindc_name = "y", uniq_name = "_QFmultiple_real_reductions_same_typeEy"} +! CHECK: %[[VAL_3:.*]] = fir.alloca f32 {bindc_name = "z", uniq_name = "_QFmultiple_real_reductions_same_typeEz"} +! CHECK: %[[VAL_4:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: fir.store %[[VAL_4]] to %[[VAL_1]] : !fir.ref<f32> +! CHECK: %[[VAL_5:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: fir.store %[[VAL_5]] to %[[VAL_2]] : !fir.ref<f32> +! CHECK: %[[VAL_6:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: fir.store %[[VAL_6]] to %[[VAL_3]] : !fir.ref<f32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_f32 %[[VAL_1]] -> %[[VAL_11:.*]] : !fir.ref<f32>, @add_reduction_byref_f32 %[[VAL_2]] -> %[[VAL_12:.*]] : !fir.ref<f32>, @add_reduction_byref_f32 %[[VAL_3]] -> %[[VAL_13:.*]] : !fir.ref<f32>) for (%[[VAL_14:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) { +! CHECK: fir.store %[[VAL_14]] to %[[VAL_7]] : !fir.ref<i32> +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_11]] : !fir.ref<f32> +! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_7]] : !fir.ref<i32> +! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_16]] : (i32) -> f32 +! CHECK: %[[VAL_18:.*]] = arith.addf %[[VAL_15]], %[[VAL_17]] fastmath<contract> : f32 +! CHECK: fir.store %[[VAL_18]] to %[[VAL_11]] : !fir.ref<f32> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_12]] : !fir.ref<f32> +! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_7]] : !fir.ref<i32> +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i32) -> f32 +! CHECK: %[[VAL_22:.*]] = arith.addf %[[VAL_19]], %[[VAL_21]] fastmath<contract> : f32 +! CHECK: fir.store %[[VAL_22]] to %[[VAL_12]] : !fir.ref<f32> +! CHECK: %[[VAL_23:.*]] = fir.load %[[VAL_13]] : !fir.ref<f32> +! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_7]] : !fir.ref<i32> +! CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_24]] : (i32) -> f32 +! CHECK: %[[VAL_26:.*]] = arith.addf %[[VAL_23]], %[[VAL_25]] fastmath<contract> : f32 +! CHECK: fir.store %[[VAL_26]] to %[[VAL_13]] : !fir.ref<f32> +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine multiple_real_reductions_same_type + real :: x,y,z + x = 0.0 + y = 0.0 + z = 0.0 + !$omp parallel + !$omp do reduction(+:x,y,z) + do i=1, 100 + x = x + i + y = y + i + z = z + i + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_reductions_different_type() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_reductions_different_typeEi"} +! CHECK: %[[VAL_1:.*]] = fir.alloca f64 {bindc_name = "w", uniq_name = "_QFmultiple_reductions_different_typeEw"} +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFmultiple_reductions_different_typeEx"} +! CHECK: %[[VAL_3:.*]] = fir.alloca i64 {bindc_name = "y", uniq_name = "_QFmultiple_reductions_different_typeEy"} +! CHECK: %[[VAL_4:.*]] = fir.alloca f32 {bindc_name = "z", uniq_name = "_QFmultiple_reductions_different_typeEz"} +! CHECK: %[[VAL_5:.*]] = arith.constant 0 : i32 +! CHECK: fir.store %[[VAL_5]] to %[[VAL_2]] : !fir.ref<i32> +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i64 +! CHECK: fir.store %[[VAL_6]] to %[[VAL_3]] : !fir.ref<i64> +! CHECK: %[[VAL_7:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: fir.store %[[VAL_7]] to %[[VAL_4]] : !fir.ref<f32> +! CHECK: %[[VAL_8:.*]] = arith.constant 0.000000e+00 : f64 +! CHECK: fir.store %[[VAL_8]] to %[[VAL_1]] : !fir.ref<f64> +! CHECK: omp.parallel { +! CHECK: %[[VAL_9:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_11:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_2]] -> %[[VAL_13:.*]] : !fir.ref<i32>, @add_reduction_byref_i64 %[[VAL_3]] -> %[[VAL_14:.*]] : !fir.ref<i64>, @add_reduction_byref_f32 %[[VAL_4]] -> %[[VAL_15:.*]] : !fir.ref<f32>, @add_reduction_byref_f64 %[[VAL_1]] -> %[[VAL_16:.*]] : !fir.ref<f64>) for (%[[VAL_17:.*]]) : i32 = (%[[VAL_10]]) to (%[[VAL_11]]) inclusive step (%[[VAL_12]]) { +! CHECK: fir.store %[[VAL_17]] to %[[VAL_9]] : !fir.ref<i32> +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_13]] : !fir.ref<i32> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_9]] : !fir.ref<i32> +! CHECK: %[[VAL_20:.*]] = arith.addi %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: fir.store %[[VAL_20]] to %[[VAL_13]] : !fir.ref<i32> +! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_14]] : !fir.ref<i64> +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_9]] : !fir.ref<i32> +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_22]] : (i32) -> i64 +! CHECK: %[[VAL_24:.*]] = arith.addi %[[VAL_21]], %[[VAL_23]] : i64 +! CHECK: fir.store %[[VAL_24]] to %[[VAL_14]] : !fir.ref<i64> +! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_15]] : !fir.ref<f32> +! CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_9]] : !fir.ref<i32> +! CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_26]] : (i32) -> f32 +! CHECK: %[[VAL_28:.*]] = arith.addf %[[VAL_25]], %[[VAL_27]] fastmath<contract> : f32 +! CHECK: fir.store %[[VAL_28]] to %[[VAL_15]] : !fir.ref<f32> +! CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_16]] : !fir.ref<f64> +! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_9]] : !fir.ref<i32> +! CHECK: %[[VAL_31:.*]] = fir.convert %[[VAL_30]] : (i32) -> f64 +! CHECK: %[[VAL_32:.*]] = arith.addf %[[VAL_29]], %[[VAL_31]] fastmath<contract> : f64 +! CHECK: fir.store %[[VAL_32]] to %[[VAL_16]] : !fir.ref<f64> +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + + +subroutine multiple_reductions_different_type + integer :: x + integer(kind=8) :: y + real :: z + real(kind=8) :: w + x = 0 + y = 0 + z = 0.0 + w = 0.0 + !$omp parallel + !$omp do reduction(+:x,y,z,w) + do i=1, 100 + x = x + i + y = y + i + z = z + i + w = w + i + end do + !$omp end do + !$omp end parallel +end subroutine diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-add.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-add.f90 index 5664529416fe87f9f94e7e91de816ed121ed0590..dc96b875f745f2d953e3f0fca22f326b9af42b2a 100644 --- a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-add.f90 +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-add.f90 @@ -1,13 +1,7 @@ ! RUN: bbc -emit-fir -hlfir=false -fopenmp %s -o - | FileCheck %s ! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | FileCheck %s -! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py -! The script is designed to make adding checks to -! a test case fast, it is *not* designed to be authoritative -! about what constitutes a good test! The CHECK should be -! minimized and named to reflect the test intent. - -! CHECK-LABEL: omp.reduction.declare @add_reduction_f_64 : f64 init { +! CHECK-LABEL: omp.declare_reduction @add_reduction_f64 : f64 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: f64): ! CHECK: %[[VAL_1:.*]] = arith.constant 0.000000e+00 : f64 ! CHECK: omp.yield(%[[VAL_1]] : f64) @@ -18,7 +12,7 @@ ! CHECK: omp.yield(%[[VAL_2]] : f64) ! CHECK: } -! CHECK-LABEL: omp.reduction.declare @add_reduction_i_64 : i64 init { +! CHECK-LABEL: omp.declare_reduction @add_reduction_i64 : i64 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: i64): ! CHECK: %[[VAL_1:.*]] = arith.constant 0 : i64 ! CHECK: omp.yield(%[[VAL_1]] : i64) @@ -29,7 +23,7 @@ ! CHECK: omp.yield(%[[VAL_2]] : i64) ! CHECK: } -! CHECK-LABEL: omp.reduction.declare @add_reduction_f_32 : f32 init { +! CHECK-LABEL: omp.declare_reduction @add_reduction_f32 : f32 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: f32): ! CHECK: %[[VAL_1:.*]] = arith.constant 0.000000e+00 : f32 ! CHECK: omp.yield(%[[VAL_1]] : f32) @@ -40,7 +34,7 @@ ! CHECK: omp.yield(%[[VAL_2]] : f32) ! CHECK: } -! CHECK-LABEL: omp.reduction.declare @add_reduction_i_32 : i32 init { +! CHECK-LABEL: omp.declare_reduction @add_reduction_i32 : i32 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: i32): ! CHECK: %[[VAL_1:.*]] = arith.constant 0 : i32 ! CHECK: omp.yield(%[[VAL_1]] : i32) @@ -61,7 +55,7 @@ ! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@add_reduction_i_32 %[[VAL_1]] -> %[[VAL_7:.*]] : !fir.ref<i32>) for (%[[VAL_8:.*]]) : i32 = (%[[VAL_4]]) to (%[[VAL_5]]) inclusive step (%[[VAL_6]]) { +! CHECK: omp.wsloop reduction(@add_reduction_i32 %[[VAL_1]] -> %[[VAL_7:.*]] : !fir.ref<i32>) for (%[[VAL_8:.*]]) : i32 = (%[[VAL_4]]) to (%[[VAL_5]]) inclusive step (%[[VAL_6]]) { ! CHECK: fir.store %[[VAL_8]] to %[[VAL_3]] : !fir.ref<i32> ! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_7]] : !fir.ref<i32> ! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_3]] : !fir.ref<i32> @@ -97,7 +91,7 @@ end subroutine ! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@add_reduction_f_32 %[[VAL_1]] -> %[[VAL_7:.*]] : !fir.ref<f32>) for (%[[VAL_8:.*]]) : i32 = (%[[VAL_4]]) to (%[[VAL_5]]) inclusive step (%[[VAL_6]]) { +! CHECK: omp.wsloop reduction(@add_reduction_f32 %[[VAL_1]] -> %[[VAL_7:.*]] : !fir.ref<f32>) for (%[[VAL_8:.*]]) : i32 = (%[[VAL_4]]) to (%[[VAL_5]]) inclusive step (%[[VAL_6]]) { ! CHECK: fir.store %[[VAL_8]] to %[[VAL_3]] : !fir.ref<i32> ! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_7]] : !fir.ref<f32> ! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_3]] : !fir.ref<i32> @@ -133,7 +127,7 @@ end subroutine ! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@add_reduction_i_32 %[[VAL_1]] -> %[[VAL_7:.*]] : !fir.ref<i32>) for (%[[VAL_8:.*]]) : i32 = (%[[VAL_4]]) to (%[[VAL_5]]) inclusive step (%[[VAL_6]]) { +! CHECK: omp.wsloop reduction(@add_reduction_i32 %[[VAL_1]] -> %[[VAL_7:.*]] : !fir.ref<i32>) for (%[[VAL_8:.*]]) : i32 = (%[[VAL_4]]) to (%[[VAL_5]]) inclusive step (%[[VAL_6]]) { ! CHECK: fir.store %[[VAL_8]] to %[[VAL_3]] : !fir.ref<i32> ! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_3]] : !fir.ref<i32> ! CHECK: %[[VAL_10:.*]] = fir.load %[[VAL_7]] : !fir.ref<i32> @@ -168,7 +162,7 @@ end subroutine ! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_5:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@add_reduction_f_32 %[[VAL_1]] -> %[[VAL_7:.*]] : !fir.ref<f32>) for (%[[VAL_8:.*]]) : i32 = (%[[VAL_4]]) to (%[[VAL_5]]) inclusive step (%[[VAL_6]]) { +! CHECK: omp.wsloop reduction(@add_reduction_f32 %[[VAL_1]] -> %[[VAL_7:.*]] : !fir.ref<f32>) for (%[[VAL_8:.*]]) : i32 = (%[[VAL_4]]) to (%[[VAL_5]]) inclusive step (%[[VAL_6]]) { ! CHECK: fir.store %[[VAL_8]] to %[[VAL_3]] : !fir.ref<i32> ! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_3]] : !fir.ref<i32> ! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i32) -> f32 @@ -210,7 +204,7 @@ end subroutine ! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@add_reduction_i_32 %[[VAL_1]] -> %[[VAL_11:.*]] : !fir.ref<i32>, @add_reduction_i_32 %[[VAL_2]] -> %[[VAL_12:.*]] : !fir.ref<i32>, @add_reduction_i_32 %[[VAL_3]] -> %[[VAL_13:.*]] : !fir.ref<i32>) for (%[[VAL_14:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) { +! CHECK: omp.wsloop reduction(@add_reduction_i32 %[[VAL_1]] -> %[[VAL_11:.*]] : !fir.ref<i32>, @add_reduction_i32 %[[VAL_2]] -> %[[VAL_12:.*]] : !fir.ref<i32>, @add_reduction_i32 %[[VAL_3]] -> %[[VAL_13:.*]] : !fir.ref<i32>) for (%[[VAL_14:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) { ! CHECK: fir.store %[[VAL_14]] to %[[VAL_7]] : !fir.ref<i32> ! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_11]] : !fir.ref<i32> ! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_7]] : !fir.ref<i32> @@ -263,7 +257,7 @@ end subroutine ! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@add_reduction_f_32 %[[VAL_1]] -> %[[VAL_11:.*]] : !fir.ref<f32>, @add_reduction_f_32 %[[VAL_2]] -> %[[VAL_12:.*]] : !fir.ref<f32>, @add_reduction_f_32 %[[VAL_3]] -> %[[VAL_13:.*]] : !fir.ref<f32>) for (%[[VAL_14:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) { +! CHECK: omp.wsloop reduction(@add_reduction_f32 %[[VAL_1]] -> %[[VAL_11:.*]] : !fir.ref<f32>, @add_reduction_f32 %[[VAL_2]] -> %[[VAL_12:.*]] : !fir.ref<f32>, @add_reduction_f32 %[[VAL_3]] -> %[[VAL_13:.*]] : !fir.ref<f32>) for (%[[VAL_14:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) { ! CHECK: fir.store %[[VAL_14]] to %[[VAL_7]] : !fir.ref<i32> ! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_11]] : !fir.ref<f32> ! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_7]] : !fir.ref<i32> @@ -322,7 +316,7 @@ end subroutine ! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_11:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@add_reduction_i_32 %[[VAL_2]] -> %[[VAL_13:.*]] : !fir.ref<i32>, @add_reduction_i_64 %[[VAL_3]] -> %[[VAL_14:.*]] : !fir.ref<i64>, @add_reduction_f_32 %[[VAL_4]] -> %[[VAL_15:.*]] : !fir.ref<f32>, @add_reduction_f_64 %[[VAL_1]] -> %[[VAL_16:.*]] : !fir.ref<f64>) for (%[[VAL_17:.*]]) : i32 = (%[[VAL_10]]) to (%[[VAL_11]]) inclusive step (%[[VAL_12]]) { +! CHECK: omp.wsloop reduction(@add_reduction_i32 %[[VAL_2]] -> %[[VAL_13:.*]] : !fir.ref<i32>, @add_reduction_i64 %[[VAL_3]] -> %[[VAL_14:.*]] : !fir.ref<i64>, @add_reduction_f32 %[[VAL_4]] -> %[[VAL_15:.*]] : !fir.ref<f32>, @add_reduction_f64 %[[VAL_1]] -> %[[VAL_16:.*]] : !fir.ref<f64>) for (%[[VAL_17:.*]]) : i32 = (%[[VAL_10]]) to (%[[VAL_11]]) inclusive step (%[[VAL_12]]) { ! CHECK: fir.store %[[VAL_17]] to %[[VAL_9]] : !fir.ref<i32> ! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_13]] : !fir.ref<i32> ! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_9]] : !fir.ref<i32> diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-iand-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-iand-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..6717597ff3b04d8f85c3b41b48d9145f848bb1fb --- /dev/null +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-iand-byref.f90 @@ -0,0 +1,46 @@ +! RUN: bbc -emit-fir -hlfir=false -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +!CHECK-LABEL: omp.declare_reduction @iand_byref_i32 : !fir.ref<i32> +!CHECK-SAME: init { +!CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +!CHECK: %[[C0_1:.*]] = arith.constant -1 : i32 +!CHECK: %[[REF:.*]] = fir.alloca i32 +!CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref<i32> +!CHECK: omp.yield(%[[REF]] : !fir.ref<i32>) + +!CHECK-LABEL: } combiner { +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> +!CHECK: %[[RES:.*]] = arith.andi %[[LD0]], %[[LD1]] : i32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i32> +!CHECK: omp.yield(%[[ARG0]] : !fir.ref<i32>) +!CHECK: } + + +!CHECK-LABEL: @_QPreduction_iand +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box<!fir.array<?xi32>> +!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_iandEx"} +!CHECK: omp.parallel +!CHECK: omp.wsloop byref reduction(@iand_byref_i32 %[[X_REF]] -> %[[PRV:.+]] : !fir.ref<i32>) for +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV]] : !fir.ref<i32> +!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]] +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref<i32> +!CHECK: %[[RES:.+]] = arith.andi %[[LPRV]], %[[Y_I]] : i32 +!CHECK: fir.store %[[RES]] to %[[PRV]] : !fir.ref<i32> +!CHECK: omp.yield +!CHECK: omp.terminator + +subroutine reduction_iand(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(iand:x) + do i=1, 100 + x = iand(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-iand.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-iand.f90 index 9ce1725dbab0462a186fa609014ecef59d625891..9bc45f9f3a0d870af97e7d72ddcdc6792f02cd89 100644 --- a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-iand.f90 +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-iand.f90 @@ -1,7 +1,7 @@ ! RUN: bbc -emit-fir -hlfir=false -fopenmp %s -o - | FileCheck %s ! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | FileCheck %s -!CHECK: omp.reduction.declare @[[IAND_DECLARE_I:.*]] : i32 init { +!CHECK: omp.declare_reduction @[[IAND_DECLARE_I:.*]] : i32 init { !CHECK: %[[ZERO_VAL_I:.*]] = arith.constant -1 : i32 !CHECK: omp.yield(%[[ZERO_VAL_I]] : i32) !CHECK: combiner diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ieor-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ieor-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..1baa59a510fa11cf3984a3617da30ba25f7ad075 --- /dev/null +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ieor-byref.f90 @@ -0,0 +1,45 @@ +! RUN: bbc -emit-fir -hlfir=false -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -mmlir --force-byref-reduction -fopenmp %s -o - | FileCheck %s + +! CHECK-LABEL: omp.declare_reduction @ieor_byref_i32 : !fir.ref<i32> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref<i32> +! CHECK: omp.yield(%[[REF]] : !fir.ref<i32>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> +! CHECK: %[[RES:.*]] = arith.xori %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i32> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<i32>) +! CHECK: } + +!CHECK-LABEL: @_QPreduction_ieor +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box<!fir.array<?xi32>> +!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_ieorEx"} +!CHECK: omp.parallel +!CHECK: omp.wsloop byref reduction(@ieor_byref_i32 %[[X_REF]] -> %[[PRV:.+]] : !fir.ref<i32>) for +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV]] : !fir.ref<i32> +!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]] +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref<i32> +!CHECK: %[[RES:.+]] = arith.xori %[[LPRV]], %[[Y_I]] : i32 +!CHECK: fir.store %[[RES]] to %[[PRV]] : !fir.ref<i32> +!CHECK: omp.yield +!CHECK: omp.terminator + +subroutine reduction_ieor(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(ieor:x) + do i=1, 100 + x = ieor(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ieor.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ieor.f90 index f6027416246af1c4c86297670baa6e390fa381cb..9c07d5ee20873b2a15f649f0d7854bc7cfeadfb1 100644 --- a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ieor.f90 +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ieor.f90 @@ -1,7 +1,7 @@ ! RUN: bbc -emit-fir -hlfir=false -fopenmp %s -o - | FileCheck %s ! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | FileCheck %s -!CHECK: omp.reduction.declare @[[IEOR_DECLARE_I:.*]] : i32 init { +!CHECK: omp.declare_reduction @[[IEOR_DECLARE_I:.*]] : i32 init { !CHECK: %[[ZERO_VAL_I:.*]] = arith.constant 0 : i32 !CHECK: omp.yield(%[[ZERO_VAL_I]] : i32) !CHECK: combiner diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ior-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ior-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..5482ef33fc8aa926c37e9c21bf11a58a00559b01 --- /dev/null +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ior-byref.f90 @@ -0,0 +1,45 @@ +! RUN: bbc -emit-fir -hlfir=false -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! CHECK-LABEL: omp.declare_reduction @ior_byref_i32 : !fir.ref<i32> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref<i32> +! CHECK: omp.yield(%[[REF]] : !fir.ref<i32>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> +! CHECK: %[[RES:.*]] = arith.ori %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i32> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<i32>) +! CHECK: } + +!CHECK-LABEL: @_QPreduction_ior +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box<!fir.array<?xi32>> +!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_iorEx"} +!CHECK: omp.parallel +!CHECK: omp.wsloop byref reduction(@ior_byref_i32 %[[X_REF]] -> %[[PRV:.+]] : !fir.ref<i32>) for +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV]] : !fir.ref<i32> +!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]] +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref<i32> +!CHECK: %[[RES:.+]] = arith.ori %[[LPRV]], %[[Y_I]] : i32 +!CHECK: fir.store %[[RES]] to %[[PRV]] : !fir.ref<i32> +!CHECK: omp.yield +!CHECK: omp.terminator + +subroutine reduction_ior(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(ior:x) + do i=1, 100 + x = ior(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ior.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ior.f90 index bc143611abe8d926e8d9bbc4862894f4a6e92c5a..79cc8b2d892275dac4c813eae8996c3fd270e732 100644 --- a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ior.f90 +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-ior.f90 @@ -1,7 +1,7 @@ ! RUN: bbc -emit-fir -hlfir=false -fopenmp %s -o - | FileCheck %s ! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp %s -o - | FileCheck %s -!CHECK: omp.reduction.declare @[[IOR_DECLARE_I:.*]] : i32 init { +!CHECK: omp.declare_reduction @[[IOR_DECLARE_I:.*]] : i32 init { !CHECK: %[[ZERO_VAL_I:.*]] = arith.constant 0 : i32 !CHECK: omp.yield(%[[ZERO_VAL_I]] : i32) !CHECK: combiner diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-eqv-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-eqv-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..696ff68b2059cd1b00d7e69657ecf9bf5368b848 --- /dev/null +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-eqv-byref.f90 @@ -0,0 +1,187 @@ +! RUN: bbc -emit-fir -hlfir=false -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.declare_reduction @eqv_reduction : !fir.ref<!fir.logical<4>> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[VAL_1:.*]] = arith.constant true +! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4> +! CHECK: %[[REF:.*]] = fir.alloca !fir.logical<4> +! CHECK: fir.store %[[VAL_2]] to %[[REF]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.yield(%[[REF]] : !fir.ref<!fir.logical<4>>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.logical<4>>, %[[ARG1:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_2:.*]] = fir.convert %[[LD0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_3:.*]] = fir.convert %[[LD1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[RES:.*]] = arith.cmpi eq, %[[VAL_2]], %[[VAL_3]] : i1 +! CHECK: %[[VAL_5:.*]] = fir.convert %[[RES]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_5]] to %[[ARG0]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<!fir.logical<4>>) +! CHECK: } + +! CHECK-LABEL: func.func @_QPsimple_reduction( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reductionEi"} +! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reductionEx"} +! CHECK: %[[VAL_3:.*]] = arith.constant true +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_4]] to %[[VAL_2]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_7:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@eqv_reduction %[[VAL_2]] -> %[[VAL_9:.*]] : !fir.ref<!fir.logical<4>>) for (%[[VAL_10:.*]]) : i32 = (%[[VAL_6]]) to (%[[VAL_7]]) inclusive step (%[[VAL_8]]) { +! CHECK: fir.store %[[VAL_10]] to %[[VAL_5]] : !fir.ref<i32> +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_9]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_5]] : !fir.ref<i32> +! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_12]] : (i32) -> i64 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_15:.*]] = arith.subi %[[VAL_13]], %[[VAL_14]] : i64 +! CHECK: %[[VAL_16:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_15]] : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_16]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_11]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_17]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_20:.*]] = arith.cmpi eq, %[[VAL_18]], %[[VAL_19]] : i1 +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_21]] to %[[VAL_9]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.eqv.:x) + do i=1, 100 + x = x .eqv. y(i) + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_reduction_switch_order( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reduction_switch_orderEi"} +! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reduction_switch_orderEx"} +! CHECK: %[[VAL_3:.*]] = arith.constant true +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_4]] to %[[VAL_2]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_7:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@eqv_reduction %[[VAL_2]] -> %[[VAL_9:.*]] : !fir.ref<!fir.logical<4>>) for (%[[VAL_10:.*]]) : i32 = (%[[VAL_6]]) to (%[[VAL_7]]) inclusive step (%[[VAL_8]]) { +! CHECK: fir.store %[[VAL_10]] to %[[VAL_5]] : !fir.ref<i32> +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_5]] : !fir.ref<i32> +! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_11]] : (i32) -> i64 +! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_14:.*]] = arith.subi %[[VAL_12]], %[[VAL_13]] : i64 +! CHECK: %[[VAL_15:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_14]] : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_15]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_9]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_16]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_17]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_20:.*]] = arith.cmpi eq, %[[VAL_18]], %[[VAL_19]] : i1 +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_21]] to %[[VAL_9]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction_switch_order(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.eqv.:x) + do i=1, 100 + x = y(i) .eqv. x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_reductions( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "w"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_reductionsEi"} +! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} +! CHECK: %[[VAL_4:.*]] = fir.alloca !fir.logical<4> {bindc_name = "z", uniq_name = "_QFmultiple_reductionsEz"} +! CHECK: %[[VAL_5:.*]] = arith.constant true +! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_6]] to %[[VAL_2]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_7:.*]] = arith.constant true +! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_8]] to %[[VAL_3]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_9:.*]] = arith.constant true +! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_10]] to %[[VAL_4]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_11:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@eqv_reduction %[[VAL_2]] -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>, @eqv_reduction %[[VAL_3]] -> %[[VAL_16:.*]] : !fir.ref<!fir.logical<4>>, @eqv_reduction %[[VAL_4]] -> %[[VAL_17:.*]] : !fir.ref<!fir.logical<4>>) for (%[[VAL_18:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_18]] to %[[VAL_11]] : !fir.ref<i32> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_15]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_11]] : !fir.ref<i32> +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i32) -> i64 +! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_23:.*]] = arith.subi %[[VAL_21]], %[[VAL_22]] : i64 +! CHECK: %[[VAL_24:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_23]] : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_24]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_19]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_25]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_28:.*]] = arith.cmpi eq, %[[VAL_26]], %[[VAL_27]] : i1 +! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_28]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_29]] to %[[VAL_15]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_16]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_11]] : !fir.ref<i32> +! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64 +! CHECK: %[[VAL_33:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_34:.*]] = arith.subi %[[VAL_32]], %[[VAL_33]] : i64 +! CHECK: %[[VAL_35:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_34]] : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_36:.*]] = fir.load %[[VAL_35]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_36]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_39:.*]] = arith.cmpi eq, %[[VAL_37]], %[[VAL_38]] : i1 +! CHECK: %[[VAL_40:.*]] = fir.convert %[[VAL_39]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_40]] to %[[VAL_16]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_41:.*]] = fir.load %[[VAL_17]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_42:.*]] = fir.load %[[VAL_11]] : !fir.ref<i32> +! CHECK: %[[VAL_43:.*]] = fir.convert %[[VAL_42]] : (i32) -> i64 +! CHECK: %[[VAL_44:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_45:.*]] = arith.subi %[[VAL_43]], %[[VAL_44]] : i64 +! CHECK: %[[VAL_46:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_45]] : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_47:.*]] = fir.load %[[VAL_46]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_48:.*]] = fir.convert %[[VAL_41]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_49:.*]] = fir.convert %[[VAL_47]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_50:.*]] = arith.cmpi eq, %[[VAL_48]], %[[VAL_49]] : i1 +! CHECK: %[[VAL_51:.*]] = fir.convert %[[VAL_50]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_51]] to %[[VAL_17]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine multiple_reductions(w) + logical :: x,y,z,w(100) + x = .true. + y = .true. + z = .true. + !$omp parallel + !$omp do reduction(.eqv.:x,y,z) + do i=1, 100 + x = x .eqv. w(i) + y = y .eqv. w(i) + z = z .eqv. w(i) + end do + !$omp end do + !$omp end parallel +end subroutine diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-eqv.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-eqv.f90 index d5aacd74d8b1052e0cfb03e77d197f1a85c28961..6dcb3952655eabd2c3a5be7815abfe63715a31a5 100644 --- a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-eqv.f90 +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-eqv.f90 @@ -3,7 +3,7 @@ ! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py -! CHECK-LABEL: omp.reduction.declare @eqv_reduction : !fir.logical<4> init { +! CHECK-LABEL: omp.declare_reduction @eqv_reduction : !fir.logical<4> init { ! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.logical<4>): ! CHECK: %[[VAL_1:.*]] = arith.constant true ! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4> diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-neqv-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-neqv-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..a31abd0def56e16da67efac729c9b6e985281ac2 --- /dev/null +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-neqv-byref.f90 @@ -0,0 +1,189 @@ +! RUN: bbc -emit-fir -hlfir=false -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + + +! CHECK-LABEL: omp.declare_reduction @neqv_reduction : !fir.ref<!fir.logical<4>> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[VAL_1:.*]] = arith.constant false +! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4> +! CHECK: %[[REF:.*]] = fir.alloca !fir.logical<4> +! CHECK: fir.store %[[VAL_2]] to %[[REF]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.yield(%[[REF]] : !fir.ref<!fir.logical<4>>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.logical<4>>, %[[ARG1:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_2:.*]] = fir.convert %[[LD0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_3:.*]] = fir.convert %[[LD1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[RES:.*]] = arith.cmpi ne, %[[VAL_2]], %[[VAL_3]] : i1 +! CHECK: %[[VAL_5:.*]] = fir.convert %[[RES]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_5]] to %[[ARG0]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<!fir.logical<4>>) +! CHECK: } + +! CHECK-LABEL: func.func @_QPsimple_reduction( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reductionEi"} +! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reductionEx"} +! CHECK: %[[VAL_3:.*]] = arith.constant true +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_4]] to %[[VAL_2]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_7:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@neqv_reduction %[[VAL_2]] -> %[[VAL_9:.*]] : !fir.ref<!fir.logical<4>>) for (%[[VAL_10:.*]]) : i32 = (%[[VAL_6]]) to (%[[VAL_7]]) inclusive step (%[[VAL_8]]) { +! CHECK: fir.store %[[VAL_10]] to %[[VAL_5]] : !fir.ref<i32> +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_9]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_5]] : !fir.ref<i32> +! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_12]] : (i32) -> i64 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_15:.*]] = arith.subi %[[VAL_13]], %[[VAL_14]] : i64 +! CHECK: %[[VAL_16:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_15]] : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_16]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_11]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_17]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_20:.*]] = arith.cmpi ne, %[[VAL_18]], %[[VAL_19]] : i1 +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_21]] to %[[VAL_9]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.neqv.:x) + do i=1, 100 + x = x .neqv. y(i) + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_reduction_switch_order( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reduction_switch_orderEi"} +! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reduction_switch_orderEx"} +! CHECK: %[[VAL_3:.*]] = arith.constant true +! CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_4]] to %[[VAL_2]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_7:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@neqv_reduction %[[VAL_2]] -> %[[VAL_9:.*]] : !fir.ref<!fir.logical<4>>) for (%[[VAL_10:.*]]) : i32 = (%[[VAL_6]]) to (%[[VAL_7]]) inclusive step (%[[VAL_8]]) { +! CHECK: fir.store %[[VAL_10]] to %[[VAL_5]] : !fir.ref<i32> +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_5]] : !fir.ref<i32> +! CHECK: %[[VAL_12:.*]] = fir.convert %[[VAL_11]] : (i32) -> i64 +! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_14:.*]] = arith.subi %[[VAL_12]], %[[VAL_13]] : i64 +! CHECK: %[[VAL_15:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_14]] : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_15]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_9]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_18:.*]] = fir.convert %[[VAL_16]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_17]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_20:.*]] = arith.cmpi ne, %[[VAL_18]], %[[VAL_19]] : i1 +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_21]] to %[[VAL_9]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction_switch_order(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.neqv.:x) + do i=1, 100 + x = y(i) .neqv. x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_reductions( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "w"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_reductionsEi"} +! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} +! CHECK: %[[VAL_4:.*]] = fir.alloca !fir.logical<4> {bindc_name = "z", uniq_name = "_QFmultiple_reductionsEz"} +! CHECK: %[[VAL_5:.*]] = arith.constant true +! CHECK: %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_6]] to %[[VAL_2]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_7:.*]] = arith.constant true +! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_8]] to %[[VAL_3]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_9:.*]] = arith.constant true +! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_10]] to %[[VAL_4]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_11:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@neqv_reduction %[[VAL_2]] -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>, @neqv_reduction %[[VAL_3]] -> %[[VAL_16:.*]] : !fir.ref<!fir.logical<4>>, @neqv_reduction %[[VAL_4]] -> %[[VAL_17:.*]] : !fir.ref<!fir.logical<4>>) for (%[[VAL_18:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_18]] to %[[VAL_11]] : !fir.ref<i32> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_15]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_11]] : !fir.ref<i32> +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_20]] : (i32) -> i64 +! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_23:.*]] = arith.subi %[[VAL_21]], %[[VAL_22]] : i64 +! CHECK: %[[VAL_24:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_23]] : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_24]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_19]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_25]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_28:.*]] = arith.cmpi ne, %[[VAL_26]], %[[VAL_27]] : i1 +! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_28]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_29]] to %[[VAL_15]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_16]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_11]] : !fir.ref<i32> +! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64 +! CHECK: %[[VAL_33:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_34:.*]] = arith.subi %[[VAL_32]], %[[VAL_33]] : i64 +! CHECK: %[[VAL_35:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_34]] : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_36:.*]] = fir.load %[[VAL_35]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_36]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_39:.*]] = arith.cmpi ne, %[[VAL_37]], %[[VAL_38]] : i1 +! CHECK: %[[VAL_40:.*]] = fir.convert %[[VAL_39]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_40]] to %[[VAL_16]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_41:.*]] = fir.load %[[VAL_17]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_42:.*]] = fir.load %[[VAL_11]] : !fir.ref<i32> +! CHECK: %[[VAL_43:.*]] = fir.convert %[[VAL_42]] : (i32) -> i64 +! CHECK: %[[VAL_44:.*]] = arith.constant 1 : i64 +! CHECK: %[[VAL_45:.*]] = arith.subi %[[VAL_43]], %[[VAL_44]] : i64 +! CHECK: %[[VAL_46:.*]] = fir.coordinate_of %[[VAL_0]], %[[VAL_45]] : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_47:.*]] = fir.load %[[VAL_46]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_48:.*]] = fir.convert %[[VAL_41]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_49:.*]] = fir.convert %[[VAL_47]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_50:.*]] = arith.cmpi ne, %[[VAL_48]], %[[VAL_49]] : i1 +! CHECK: %[[VAL_51:.*]] = fir.convert %[[VAL_50]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_51]] to %[[VAL_17]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + + +subroutine multiple_reductions(w) + logical :: x,y,z,w(100) + x = .true. + y = .true. + z = .true. + !$omp parallel + !$omp do reduction(.neqv.:x,y,z) + do i=1, 100 + x = x .neqv. w(i) + y = y .neqv. w(i) + z = z .neqv. w(i) + end do + !$omp end do + !$omp end parallel +end subroutine diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-neqv.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-neqv.f90 index 9f44e0e26d407376863b9ec566b9d9b87d0ad40f..702c185e25ee401c99f332448f7b0c80b00e9f86 100644 --- a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-neqv.f90 +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-logical-neqv.f90 @@ -4,7 +4,7 @@ ! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py -! CHECK-LABEL: omp.reduction.declare @neqv_reduction : !fir.logical<4> init { +! CHECK-LABEL: omp.declare_reduction @neqv_reduction : !fir.logical<4> init { ! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.logical<4>): ! CHECK: %[[VAL_1:.*]] = arith.constant false ! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4> diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..f0979ab95f568ad49bd20b216586e03e9e70996e --- /dev/null +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max-byref.f90 @@ -0,0 +1,90 @@ +! RUN: bbc -emit-fir -hlfir=false -fopenmp --force-byref-reduction -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -mmlir --force-byref-reduction -o - %s 2>&1 | FileCheck %s + +!CHECK: omp.declare_reduction @max_byref_f32 : !fir.ref<f32> +!CHECK-SAME: init { +!CHECK: %[[MINIMUM_VAL:.*]] = arith.constant -3.40282347E+38 : f32 +!CHECK: %[[REF:.*]] = fir.alloca f32 +!CHECK: fir.store %[[MINIMUM_VAL]] to %[[REF]] : !fir.ref<f32> +!CHECK: omp.yield(%[[REF]] : !fir.ref<f32>) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<f32>, %[[ARG1:.*]]: !fir.ref<f32>): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<f32> +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<f32> +!CHECK: %[[RES:.*]] = arith.maximumf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<f32> +!CHECK: omp.yield(%[[ARG0]] : !fir.ref<f32>) + +!CHECK-LABEL: omp.declare_reduction @max_byref_i32 : !fir.ref<i32> +!CHECK-SAME: init { +!CHECK: %[[MINIMUM_VAL:.*]] = arith.constant -2147483648 : i32 +!CHECK: fir.store %[[MINIMUM_VAL]] to %[[REF]] : !fir.ref<i32> +!CHECK: omp.yield(%[[REF]] : !fir.ref<i32>) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> +!CHECK: %[[RES:.*]] = arith.maxsi %[[LD0]], %[[LD1]] : i32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i32> +!CHECK: omp.yield(%[[ARG0]] : !fir.ref<i32>) + +!CHECK-LABEL: @_QPreduction_max_int +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box<!fir.array<?xi32>> +!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_max_intEx"} +!CHECK: omp.parallel +!CHECK: omp.wsloop byref reduction(@max_byref_i32 %[[X_REF]] -> %[[PRV:.+]] : !fir.ref<i32>) for +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV]] : !fir.ref<i32> +!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]] +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref<i32> +!CHECK: %[[RES:.+]] = arith.cmpi sgt, %[[LPRV]], %[[Y_I]] : i32 +!CHECK: %[[SEL:.+]] = arith.select %[[RES]], %[[LPRV]], %[[Y_I]] +!CHECK: fir.store %[[SEL]] to %[[PRV]] : !fir.ref<i32> +!CHECK: omp.terminator + +!CHECK-LABEL: @_QPreduction_max_real +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box<!fir.array<?xf32>> +!CHECK: %[[X_REF:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFreduction_max_realEx"} +!CHECK: omp.parallel +!CHECK: omp.wsloop byref reduction(@max_byref_f32 %[[X_REF]] -> %[[PRV:.+]] : !fir.ref<f32>) for +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV]] : !fir.ref<f32> +!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]] +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref<f32> +!CHECK: %[[RES:.+]] = arith.cmpf ogt, %[[Y_I]], %[[LPRV]] {{.*}} : f32 +!CHECK: omp.yield +!CHECK: omp.terminator + +subroutine reduction_max_int(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(max:x) + do i=1, 100 + x = max(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine + +subroutine reduction_max_real(y) + real :: x, y(:) + x = 0.0 + !$omp parallel + !$omp do reduction(max:x) + do i=1, 100 + x = max(y(i), x) + end do + !$omp end do + !$omp end parallel + print *, x + + !$omp parallel + !$omp do reduction(max:x) + do i=1, 100 + !CHECK-NOT: omp.reduction + if (y(i) .gt. x) x = y(i) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max.f90 index af79658491b5685c847cd9efbe10799b01d8800a..996296c2adc2b5b0e389d5e4ecc2841a6dec6b91 100644 --- a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max.f90 +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-max.f90 @@ -1,7 +1,7 @@ ! RUN: bbc -emit-fir -hlfir=false -fopenmp -o - %s 2>&1 | FileCheck %s ! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s -!CHECK: omp.reduction.declare @[[MAX_DECLARE_F:.*]] : f32 init { +!CHECK: omp.declare_reduction @[[MAX_DECLARE_F:.*]] : f32 init { !CHECK: %[[MINIMUM_VAL_F:.*]] = arith.constant -3.40282347E+38 : f32 !CHECK: omp.yield(%[[MINIMUM_VAL_F]] : f32) !CHECK: combiner @@ -9,7 +9,7 @@ !CHECK: %[[COMB_VAL_F:.*]] = arith.maximumf %[[ARG0_F]], %[[ARG1_F]] {{.*}}: f32 !CHECK: omp.yield(%[[COMB_VAL_F]] : f32) -!CHECK: omp.reduction.declare @[[MAX_DECLARE_I:.*]] : i32 init { +!CHECK: omp.declare_reduction @[[MAX_DECLARE_I:.*]] : i32 init { !CHECK: %[[MINIMUM_VAL_I:.*]] = arith.constant -2147483648 : i32 !CHECK: omp.yield(%[[MINIMUM_VAL_I]] : i32) !CHECK: combiner diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min-byref.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..24aa8e46e5bbbd91a62fa54ec2e8a6ba42cd6dd7 --- /dev/null +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min-byref.f90 @@ -0,0 +1,91 @@ +! RUN: bbc -emit-fir -hlfir=false -fopenmp --force-byref-reduction -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -mmlir --force-byref-reduction -fopenmp -o - %s 2>&1 | FileCheck %s + +!CHECK: omp.declare_reduction @min_byref_f32 : !fir.ref<f32> +!CHECK-SAME: init { +!CHECK: %[[MAXIMUM_VAL:.*]] = arith.constant 3.40282347E+38 : f32 +!CHECK: %[[REF:.*]] = fir.alloca f32 +!CHECK: fir.store %[[MAXIMUM_VAL]] to %[[REF]] : !fir.ref<f32> +!CHECK: omp.yield(%[[REF]] : !fir.ref<f32>) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<f32>, %[[ARG1:.*]]: !fir.ref<f32>): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<f32> +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<f32> +!CHECK: %[[RES:.*]] = arith.minimumf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<f32> +!CHECK: omp.yield(%[[ARG0]] : !fir.ref<f32>) + +!CHECK-LABEL: omp.declare_reduction @min_byref_i32 : !fir.ref<i32> +!CHECK-SAME: init { +!CHECK: %[[MAXIMUM_VAL:.*]] = arith.constant 2147483647 : i32 +!CHECK: fir.store %[[MAXIMUM_VAL]] to %[[REF]] : !fir.ref<i32> +!CHECK: omp.yield(%[[REF]] : !fir.ref<i32>) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> +!CHECK: %[[RES:.*]] = arith.minsi %[[LD0]], %[[LD1]] : i32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i32> +!CHECK: omp.yield(%[[ARG0]] : !fir.ref<i32>) + +!CHECK-LABEL: @_QPreduction_min_int +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box<!fir.array<?xi32>> +!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_min_intEx"} +!CHECK: omp.parallel +!CHECK: omp.wsloop byref reduction(@min_byref_i32 %[[X_REF]] -> %[[PRV:.+]] : !fir.ref<i32>) for +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV]] : !fir.ref<i32> +!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]] +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref<i32> +!CHECK: %[[RES:.+]] = arith.cmpi slt, %[[LPRV]], %[[Y_I]] : i32 +!CHECK: %[[SEL:.+]] = arith.select %[[RES]], %[[LPRV]], %[[Y_I]] +!CHECK: fir.store %[[SEL]] to %[[PRV]] : !fir.ref<i32> +!CHECK: omp.yield +!CHECK: omp.terminator + +!CHECK-LABEL: @_QPreduction_min_real +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box<!fir.array<?xf32>> +!CHECK: %[[X_REF:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFreduction_min_realEx"} +!CHECK: omp.parallel +!CHECK: omp.wsloop byref reduction(@min_byref_f32 %[[X_REF]] -> %[[PRV:.+]] : !fir.ref<f32>) for +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV]] : !fir.ref<f32> +!CHECK: %[[Y_I_REF:.*]] = fir.coordinate_of %[[Y_BOX]] +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref<f32> +!CHECK: %[[RES:.+]] = arith.cmpf ogt, %[[Y_I]], %[[LPRV]] {{.*}} : f32 +!CHECK: omp.yield +!CHECK: omp.terminator + +subroutine reduction_min_int(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(min:x) + do i=1, 100 + x = min(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine + +subroutine reduction_min_real(y) + real :: x, y(:) + x = 0.0 + !$omp parallel + !$omp do reduction(min:x) + do i=1, 100 + x = min(y(i), x) + end do + !$omp end do + !$omp end parallel + print *, x + + !$omp parallel + !$omp do reduction(min:x) + do i=1, 100 + !CHECK-NOT: omp.reduction + if (y(i) .gt. x) x = y(i) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min.f90 b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min.f90 index 1095718b4b13fd3bade92b1b25738bab06a49762..268f51c9dc9330c360014dad37a7a42bf2d73fb0 100644 --- a/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min.f90 +++ b/flang/test/Lower/OpenMP/FIR/wsloop-reduction-min.f90 @@ -1,7 +1,7 @@ ! RUN: bbc -emit-fir -hlfir=false -fopenmp -o - %s 2>&1 | FileCheck %s ! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s -!CHECK: omp.reduction.declare @[[MIN_DECLARE_F:.*]] : f32 init { +!CHECK: omp.declare_reduction @[[MIN_DECLARE_F:.*]] : f32 init { !CHECK: %[[MAXIMUM_VAL_F:.*]] = arith.constant 3.40282347E+38 : f32 !CHECK: omp.yield(%[[MAXIMUM_VAL_F]] : f32) !CHECK: combiner @@ -9,7 +9,7 @@ !CHECK: %[[COMB_VAL_F:.*]] = arith.minimumf %[[ARG0_F]], %[[ARG1_F]] {{.*}}: f32 !CHECK: omp.yield(%[[COMB_VAL_F]] : f32) -!CHECK: omp.reduction.declare @[[MIN_DECLARE_I:.*]] : i32 init { +!CHECK: omp.declare_reduction @[[MIN_DECLARE_I:.*]] : i32 init { !CHECK: %[[MAXIMUM_VAL_I:.*]] = arith.constant 2147483647 : i32 !CHECK: omp.yield(%[[MAXIMUM_VAL_I]] : i32) !CHECK: combiner diff --git a/flang/test/Lower/OpenMP/Todo/reduction-arrays.f90 b/flang/test/Lower/OpenMP/Todo/reduction-arrays.f90 deleted file mode 100644 index a21611faf248ca09aeb396034a718aad3a9df27f..0000000000000000000000000000000000000000 --- a/flang/test/Lower/OpenMP/Todo/reduction-arrays.f90 +++ /dev/null @@ -1,15 +0,0 @@ -! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s -! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s - -! CHECK: not yet implemented: Reduction of some types is not supported -subroutine reduction_array(y) - integer :: x(100), y(100,100) - !$omp parallel - !$omp do reduction(+:x) - do i=1, 100 - x = x + y(:,i) - end do - !$omp end do - !$omp end parallel - print *, x -end subroutine diff --git a/flang/test/Lower/OpenMP/allocatable-array-bounds.f90 b/flang/test/Lower/OpenMP/allocatable-array-bounds.f90 index adf74efa9b596ed262b61792234a0b04b37b287f..aeb56a0427e3bb94fe4d0cf9ad7df6fbe543dcb5 100644 --- a/flang/test/Lower/OpenMP/allocatable-array-bounds.f90 +++ b/flang/test/Lower/OpenMP/allocatable-array-bounds.f90 @@ -21,10 +21,10 @@ !HOST: %[[LOAD_3:.*]] = fir.load %[[DECLARE_1]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> !HOST: %[[CONSTANT_3:.*]] = arith.constant 0 : index !HOST: %[[BOX_3:.*]]:3 = fir.box_dims %[[LOAD_3]], %[[CONSTANT_3]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index) -!HOST: %[[BOUNDS_1:.*]] = omp.bounds lower_bound(%[[LB_1]] : index) upper_bound(%[[UB_1]] : index) extent(%[[BOX_3]]#1 : index) stride(%[[BOX_2]]#2 : index) start_idx(%[[BOX_1]]#0 : index) {stride_in_bytes = true} +!HOST: %[[BOUNDS_1:.*]] = omp.map.bounds lower_bound(%[[LB_1]] : index) upper_bound(%[[UB_1]] : index) extent(%[[BOX_3]]#1 : index) stride(%[[BOX_2]]#2 : index) start_idx(%[[BOX_1]]#0 : index) {stride_in_bytes = true} !HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %[[DECLARE_1]]#1 base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> -!HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map_info var_ptr(%[[DECLARE_1]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.array<?xi32>) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_1]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -!HOST: %[[MAP_INFO_1:.*]] = omp.map_info var_ptr(%[[DECLARE_1]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "sp_read(2:5)"} +!HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map.info var_ptr(%[[DECLARE_1]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.array<?xi32>) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_1]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} +!HOST: %[[MAP_INFO_1:.*]] = omp.map.info var_ptr(%[[DECLARE_1]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "sp_read(2:5)"} !HOST: %[[LOAD_3:.*]] = fir.load %[[DECLARE_2]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> !HOST: %[[LOAD_4:.*]] = fir.load %[[DECLARE_2]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> @@ -39,10 +39,10 @@ !HOST: %[[LOAD_5:.*]] = fir.load %[[DECLARE_2]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> !HOST: %[[CONSTANT_5:.*]] = arith.constant 0 : index !HOST: %[[BOX_5:.*]]:3 = fir.box_dims %[[LOAD_5]], %[[CONSTANT_5]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index) -!HOST: %[[BOUNDS_2:.*]] = omp.bounds lower_bound(%[[LB_2]] : index) upper_bound(%[[UB_2]] : index) extent(%[[BOX_5]]#1 : index) stride(%[[BOX_4]]#2 : index) start_idx(%[[BOX_3]]#0 : index) {stride_in_bytes = true} +!HOST: %[[BOUNDS_2:.*]] = omp.map.bounds lower_bound(%[[LB_2]] : index) upper_bound(%[[UB_2]] : index) extent(%[[BOX_5]]#1 : index) stride(%[[BOX_4]]#2 : index) start_idx(%[[BOX_3]]#0 : index) {stride_in_bytes = true} !HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %[[DECLARE_2]]#1 base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> -!HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map_info var_ptr(%[[DECLARE_2]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.array<?xi32>) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_2]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -!HOST: %[[MAP_INFO_2:.*]] = omp.map_info var_ptr(%[[DECLARE_2]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "sp_write(2:5)"} +!HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map.info var_ptr(%[[DECLARE_2]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.array<?xi32>) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_2]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} +!HOST: %[[MAP_INFO_2:.*]] = omp.map.info var_ptr(%[[DECLARE_2]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "sp_write(2:5)"} subroutine read_write_section() integer, allocatable :: sp_read(:) @@ -78,10 +78,10 @@ module assumed_allocatable_array_routines !HOST: %[[LOAD_3:.*]] = fir.load %[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> !HOST: %[[CONSTANT_3:.*]] = arith.constant 0 : index !HOST: %[[BOX_3:.*]]:3 = fir.box_dims %[[LOAD_3]], %[[CONSTANT_3]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>, index) -> (index, index, index) -!HOST: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[LB]] : index) upper_bound(%[[UB]] : index) extent(%[[BOX_3]]#1 : index) stride(%[[BOX_2]]#2 : index) start_idx(%[[BOX_1]]#0 : index) {stride_in_bytes = true} +!HOST: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%[[LB]] : index) upper_bound(%[[UB]] : index) extent(%[[BOX_3]]#1 : index) stride(%[[BOX_2]]#2 : index) start_idx(%[[BOX_1]]#0 : index) {stride_in_bytes = true} !HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %[[DECLARE]]#1 base_addr : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> -!HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map_info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.array<?xi32>) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -!HOST: %[[MAP_INFO:.*]] = omp.map_info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "arr_read_write(2:5)"} +!HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.array<?xi32>) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} +!HOST: %[[MAP_INFO:.*]] = omp.map.info var_ptr(%[[DECLARE]]#1 : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>, !fir.box<!fir.heap<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {name = "arr_read_write(2:5)"} subroutine assumed_shape_array(arr_read_write) integer, allocatable, intent(inout) :: arr_read_write(:) diff --git a/flang/test/Lower/OpenMP/allocatable-map.f90 b/flang/test/Lower/OpenMP/allocatable-map.f90 index ddc20b582b26e669d0ad5d52ac8f84c59a387530..396d45373b8486888424b334897dd01a8a785183 100644 --- a/flang/test/Lower/OpenMP/allocatable-map.f90 +++ b/flang/test/Lower/OpenMP/allocatable-map.f90 @@ -2,8 +2,8 @@ !HLFIRDIALECT: %[[POINTER:.*]]:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFpointer_routineEpoint"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) !HLFIRDIALECT: %[[BOX_OFF:.*]] = fir.box_offset %[[POINTER]]#1 base_addr : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> !fir.llvm_ptr<!fir.ref<i32>> -!HLFIRDIALECT: %[[POINTER_MAP_MEMBER:.*]] = omp.map_info var_ptr(%[[POINTER]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, i32) var_ptr_ptr(%[[BOX_OFF]] : !fir.llvm_ptr<!fir.ref<i32>>) map_clauses(implicit, tofrom) capture(ByRef) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""} -!HLFIRDIALECT: %[[POINTER_MAP:.*]] = omp.map_info var_ptr(%[[POINTER]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(implicit, tofrom) capture(ByRef) members(%[[POINTER_MAP_MEMBER]] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "point"} +!HLFIRDIALECT: %[[POINTER_MAP_MEMBER:.*]] = omp.map.info var_ptr(%[[POINTER]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, i32) var_ptr_ptr(%[[BOX_OFF]] : !fir.llvm_ptr<!fir.ref<i32>>) map_clauses(implicit, tofrom) capture(ByRef) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""} +!HLFIRDIALECT: %[[POINTER_MAP:.*]] = omp.map.info var_ptr(%[[POINTER]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(implicit, tofrom) capture(ByRef) members(%[[POINTER_MAP_MEMBER]] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "point"} !HLFIRDIALECT: omp.target map_entries({{.*}}, %[[POINTER_MAP_MEMBER]] -> {{.*}}, %[[POINTER_MAP]] -> {{.*}} : {{.*}}, !fir.llvm_ptr<!fir.ref<i32>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) { subroutine pointer_routine() integer, pointer :: point diff --git a/flang/test/Lower/OpenMP/array-bounds.f90 b/flang/test/Lower/OpenMP/array-bounds.f90 index 7d76ff4b106a0c033d16eaf7622a49c8a594b5ca..2c8a8999a2cce6fb7ba0f0f192cc130cba0c764e 100644 --- a/flang/test/Lower/OpenMP/array-bounds.f90 +++ b/flang/test/Lower/OpenMP/array-bounds.f90 @@ -14,13 +14,13 @@ !HOST: %[[C1:.*]] = arith.constant 1 : index !HOST: %[[C2:.*]] = arith.constant 1 : index !HOST: %[[C3:.*]] = arith.constant 4 : index -!HOST: %[[BOUNDS0:.*]] = omp.bounds lower_bound(%[[C2]] : index) upper_bound(%[[C3]] : index) extent(%[[C10]] : index) stride(%[[C1]] : index) start_idx(%[[C1]] : index) -!HOST: %[[MAP0:.*]] = omp.map_info var_ptr(%[[READ_DECL]]#0 : !fir.ref<!fir.array<10xi32>>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS0]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_read(2:5)"} +!HOST: %[[BOUNDS0:.*]] = omp.map.bounds lower_bound(%[[C2]] : index) upper_bound(%[[C3]] : index) extent(%[[C10]] : index) stride(%[[C1]] : index) start_idx(%[[C1]] : index) +!HOST: %[[MAP0:.*]] = omp.map.info var_ptr(%[[READ_DECL]]#0 : !fir.ref<!fir.array<10xi32>>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS0]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_read(2:5)"} !HOST: %[[C4:.*]] = arith.constant 1 : index !HOST: %[[C5:.*]] = arith.constant 1 : index !HOST: %[[C6:.*]] = arith.constant 4 : index -!HOST: %[[BOUNDS1:.*]] = omp.bounds lower_bound(%[[C5]] : index) upper_bound(%[[C6]] : index) extent(%[[C10_0]] : index) stride(%[[C4]] : index) start_idx(%[[C4]] : index) -!HOST: %[[MAP1:.*]] = omp.map_info var_ptr(%[[WRITE_DECL]]#0 : !fir.ref<!fir.array<10xi32>>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS1]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_write(2:5)"} +!HOST: %[[BOUNDS1:.*]] = omp.map.bounds lower_bound(%[[C5]] : index) upper_bound(%[[C6]] : index) extent(%[[C10_0]] : index) stride(%[[C4]] : index) start_idx(%[[C4]] : index) +!HOST: %[[MAP1:.*]] = omp.map.info var_ptr(%[[WRITE_DECL]]#0 : !fir.ref<!fir.array<10xi32>>, !fir.array<10xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS1]]) -> !fir.ref<!fir.array<10xi32>> {name = "sp_write(2:5)"} !HOST: omp.target map_entries(%[[MAP0]] -> %{{.*}}, %[[MAP1]] -> %{{.*}}, {{.*}} -> {{.*}} : !fir.ref<!fir.array<10xi32>>, !fir.ref<!fir.array<10xi32>>, !fir.ref<i32>) { subroutine read_write_section() @@ -49,10 +49,10 @@ module assumed_array_routines !HOST: %[[C4:.*]] = arith.constant 4 : index !HOST: %[[C0_1:.*]] = arith.constant 0 : index !HOST: %[[DIMS1:.*]]:3 = fir.box_dims %[[ARG0_DECL]]#1, %[[C0_1]] : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) -!HOST: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C3]] : index) upper_bound(%[[C4]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) start_idx(%[[C0]] : index) {stride_in_bytes = true} +!HOST: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%[[C3]] : index) upper_bound(%[[C4]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) start_idx(%[[C0]] : index) {stride_in_bytes = true} !HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %0 base_addr : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> -!HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map_info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.array<?xi32>) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -!HOST: %[[MAP:.*]] = omp.map_info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"} +!HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map.info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.array<?xi32>) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} +!HOST: %[[MAP:.*]] = omp.map.info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"} !HOST: omp.target map_entries(%[[MAP_INFO_MEMBER]] -> %{{.*}}, %[[MAP]] -> %{{.*}}, {{.*}} -> {{.*}} : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>) { subroutine assumed_shape_array(arr_read_write) integer, intent(inout) :: arr_read_write(:) @@ -74,10 +74,10 @@ module assumed_array_routines !HOST: %[[DIMS0:.*]]:3 = fir.box_dims %[[ARG0_DECL]]#0, %c0{{.*}} : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) !HOST: %[[C4_1:.*]] = arith.subi %c4, %c1{{.*}} : index !HOST: %[[EXT:.*]] = arith.addi %[[C4_1]], %c1{{.*}} : index -!HOST: %[[BOUNDS:.*]] = omp.bounds lower_bound(%c1{{.*}} : index) upper_bound(%c4{{.*}} : index) extent(%[[EXT]] : index) stride(%[[DIMS0]]#2 : index) start_idx(%c1{{.*}} : index) {stride_in_bytes = true} +!HOST: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%c1{{.*}} : index) upper_bound(%c4{{.*}} : index) extent(%[[EXT]] : index) stride(%[[DIMS0]]#2 : index) start_idx(%c1{{.*}} : index) {stride_in_bytes = true} !HOST: %[[VAR_PTR_PTR:.*]] = fir.box_offset %[[INTERMEDIATE_ALLOCA]] base_addr : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> -!HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map_info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.array<?xi32>) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -!HOST: %[[MAP:.*]] = omp.map_info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"} +!HOST: %[[MAP_INFO_MEMBER:.*]] = omp.map.info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.array<?xi32>) var_ptr_ptr(%[[VAR_PTR_PTR]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} +!HOST: %[[MAP:.*]] = omp.map.info var_ptr(%[[INTERMEDIATE_ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_INFO_MEMBER]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> {name = "arr_read_write(2:5)"} !HOST: omp.target map_entries(%[[MAP_INFO_MEMBER]] -> %{{.*}}, %[[MAP]] -> %{{.*}}, {{.*}} -> {{.*}} : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>) { subroutine assumed_size_array(arr_read_write) integer, intent(inout) :: arr_read_write(*) diff --git a/flang/test/Lower/OpenMP/atomic-capture.f90 b/flang/test/Lower/OpenMP/atomic-capture.f90 index cde0281dbdc8494240cec2896b058760e163c7ea..2587c24cedf3b548f37fb75b10b6df46ccadbdb0 100644 --- a/flang/test/Lower/OpenMP/atomic-capture.f90 +++ b/flang/test/Lower/OpenMP/atomic-capture.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! This test checks the lowering of atomic capture ! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s diff --git a/flang/test/Lower/OpenMP/atomic-read.f90 b/flang/test/Lower/OpenMP/atomic-read.f90 index 97a3777bd3dcad3d07f365665dc212eee603e729..366da21f53f8cf6b2f3741a7bfbd463580374299 100644 --- a/flang/test/Lower/OpenMP/atomic-read.f90 +++ b/flang/test/Lower/OpenMP/atomic-read.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s ! This test checks the lowering of atomic read diff --git a/flang/test/Lower/OpenMP/atomic-update.f90 b/flang/test/Lower/OpenMP/atomic-update.f90 index 10da97c68c24a175a710782a1a39c591a29c89b0..051779e40816fa7d918e0ea74c51df0471377fe2 100644 --- a/flang/test/Lower/OpenMP/atomic-update.f90 +++ b/flang/test/Lower/OpenMP/atomic-update.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! This test checks lowering of atomic and atomic update constructs ! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s ! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s diff --git a/flang/test/Lower/OpenMP/atomic-write.f90 b/flang/test/Lower/OpenMP/atomic-write.f90 index 119f60c1a92f563ca7b0a74c0d820423610beffe..85955af64bbe289b8d9a773c43748d004cf44a99 100644 --- a/flang/test/Lower/OpenMP/atomic-write.f90 +++ b/flang/test/Lower/OpenMP/atomic-write.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s ! This test checks the lowering of atomic write @@ -21,8 +23,8 @@ !CHECK: %[[Z_VAL:.*]] = fir.load %[[Z_DECL]]#0 : !fir.ref<i32> !CHECK: %[[C2:.*]] = arith.constant 2 : i32 !CHECK: %[[Z_DIV_2:.*]] = arith.divsi %[[Z_VAL]], %[[C2]] : i32 -!CHECK: %172 = arith.addi %[[TEN_X]], %[[Z_DIV_2]] : i32 -!CHECK: omp.atomic.write %163#1 = %172 hint(speculative) memory_order(release) : !fir.ref<i32>, i32 +!CHECK: %[[ADD_RES:.*]] = arith.addi %[[TEN_X]], %[[Z_DIV_2]] : i32 +!CHECK: omp.atomic.write %[[Y_DECL]]#1 = %[[ADD_RES]] hint(speculative) memory_order(release) : !fir.ref<i32>, i32 program OmpAtomicWrite use omp_lib diff --git a/flang/test/Lower/OpenMP/critical.f90 b/flang/test/Lower/OpenMP/critical.f90 index 5a4d2e4815df49e8abf483859b142df7b97dc035..38e6d0eac1cbdc3fceb9b9a6965e2f53fd2a8040 100644 --- a/flang/test/Lower/OpenMP/critical.f90 +++ b/flang/test/Lower/OpenMP/critical.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + !RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s !CHECK: omp.critical.declare @help2 diff --git a/flang/test/Lower/OpenMP/declare-target-link-tarop-cap.f90 b/flang/test/Lower/OpenMP/declare-target-link-tarop-cap.f90 index 7cd0597161578d4c2b388d60272de5c0ff0dbc58..3459be87fea2f0f50e1c8da10ab225e3e47e5e02 100644 --- a/flang/test/Lower/OpenMP/declare-target-link-tarop-cap.f90 +++ b/flang/test/Lower/OpenMP/declare-target-link-tarop-cap.f90 @@ -20,13 +20,13 @@ program test_link integer, pointer :: test_ptr2 !$omp declare target link(test_ptr2) - !CHECK-DAG: {{%.*}} = omp.map_info var_ptr({{%.*}} : !fir.ref<i32>, i32) map_clauses(implicit, tofrom) capture(ByRef) -> !fir.ref<i32> {name = "test_int"} + !CHECK-DAG: {{%.*}} = omp.map.info var_ptr({{%.*}} : !fir.ref<i32>, i32) map_clauses(implicit, tofrom) capture(ByRef) -> !fir.ref<i32> {name = "test_int"} !$omp target test_int = test_int + 1 !$omp end target - !CHECK-DAG: {{%.*}} = omp.map_info var_ptr({{%.*}} : !fir.ref<!fir.array<3xi32>>, !fir.array<3xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds({{%.*}}) -> !fir.ref<!fir.array<3xi32>> {name = "test_array_1d"} + !CHECK-DAG: {{%.*}} = omp.map.info var_ptr({{%.*}} : !fir.ref<!fir.array<3xi32>>, !fir.array<3xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds({{%.*}}) -> !fir.ref<!fir.array<3xi32>> {name = "test_array_1d"} !$omp target do i = 1,3 test_array_1d(i) = i * 2 @@ -35,18 +35,18 @@ program test_link allocate(test_ptr1) test_ptr1 = 1 - !CHECK-DAG: {{%.*}} = omp.map_info var_ptr({{%.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(implicit, tofrom) capture(ByRef) members({{%.*}} : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "test_ptr1"} + !CHECK-DAG: {{%.*}} = omp.map.info var_ptr({{%.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(implicit, tofrom) capture(ByRef) members({{%.*}} : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "test_ptr1"} !$omp target test_ptr1 = test_ptr1 + 1 !$omp end target - !CHECK-DAG: {{%.*}} = omp.map_info var_ptr({{%.*}} : !fir.ref<i32>, i32) map_clauses(implicit, tofrom) capture(ByRef) -> !fir.ref<i32> {name = "test_target"} + !CHECK-DAG: {{%.*}} = omp.map.info var_ptr({{%.*}} : !fir.ref<i32>, i32) map_clauses(implicit, tofrom) capture(ByRef) -> !fir.ref<i32> {name = "test_target"} !$omp target test_target = test_target + 1 !$omp end target - !CHECK-DAG: {{%.*}} = omp.map_info var_ptr({{%.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(implicit, tofrom) capture(ByRef) members({{%.*}} : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "test_ptr2"} + !CHECK-DAG: {{%.*}} = omp.map.info var_ptr({{%.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(implicit, tofrom) capture(ByRef) members({{%.*}} : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "test_ptr2"} test_ptr2 => test_target !$omp target test_ptr2 = test_ptr2 + 1 diff --git a/flang/test/Lower/OpenMP/default-clause-byref.f90 b/flang/test/Lower/OpenMP/default-clause-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..1167ba7e6ae0d47c14a6b6bf68a4c5d3fcda70eb --- /dev/null +++ b/flang/test/Lower/OpenMP/default-clause-byref.f90 @@ -0,0 +1,385 @@ +! This test checks lowering of OpenMP parallel directive +! with `DEFAULT` clause present. + +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s +! RUN: bbc -fopenmp -emit-hlfir --force-byref-reduction %s -o - | FileCheck %s + + +!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<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFEx"} +!CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[Y:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFEy"} +!CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y]] {uniq_name = "_QFEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[Z:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFEz"} +!CHECK: %[[Z_DECL:.*]]:2 = hlfir.declare %[[Z]] {uniq_name = "_QFEz"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFEx"} +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[CONST:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[CONST]] to %[[PRIVATE_X_DECL]]#0 temporary_lhs : i32, !fir.ref<i32> +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[PRIVATE_W:.*]] = fir.alloca i32 {bindc_name = "w", pinned, uniq_name = "_QFEw"} +!CHECK: %[[PRIVATE_W_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_W]] {uniq_name = "_QFEw"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[CONST:.*]] = arith.constant 2 : i32 +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_Y_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[RESULT:.*]] = arith.muli %[[CONST]], %[[TEMP]] : i32 +!CHECK: hlfir.assign %[[RESULT]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_W_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[CONST:.*]] = arith.constant 45 : i32 +!CHECK: %[[RESULT:.*]] = arith.addi %[[TEMP]], %[[CONST]] : i32 +!CHECK: hlfir.assign %[[RESULT]] to %[[Z_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.terminator +!CHECK: } + +program default_clause_lowering + integer :: x, y, z, w + + !$omp parallel default(private) firstprivate(x) shared(z) + x = y * 2 + z = w + 45 + !$omp end parallel + +!CHECK: omp.parallel { +!CHECK: %[[TEMP:.*]] = fir.load %[[Y_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[X_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.terminator +!CHECK: } + + !$omp parallel default(shared) + x = y + !$omp end parallel + +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFEx"} +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_Y_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.terminator +!CHECK: } + + !$omp parallel default(none) private(x, y) + x = y + !$omp end parallel + +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[TEMP:.*]] = fir.load %[[Y_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_Y_DECL]]#0 temporary_lhs : i32, !fir.ref<i32> +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFEx"} +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[TEMP:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 temporary_lhs : i32, !fir.ref<i32> +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_Y_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.terminator +!CHECK: } + + !$omp parallel default(firstprivate) firstprivate(y) + x = y + !$omp end parallel + +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFEx"} +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[TEMP:.*]] = fir.load %[[Y_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_Y_DECL]]#0 temporary_lhs : i32, !fir.ref<i32> +!CHECK: %[[PRIVATE_W:.*]] = fir.alloca i32 {bindc_name = "w", pinned, uniq_name = "_QFEw"} +!CHECK: %[[PRIVATE_W_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_W]] {uniq_name = "_QFEw"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[TEMP:.*]] = fir.load %[[W_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_W_DECL]]#0 temporary_lhs : i32, !fir.ref<i32> +!CHECK: %[[CONST:.*]] = arith.constant 2 : i32 +!CHECK: %[[RESULT:.*]] = fir.load %[[PRIVATE_Y_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[TEMP:.*]] = arith.muli %[[CONST]], %[[RESULT]] : i32 +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_W_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[CONST:.*]] = arith.constant 45 : i32 +!CHECK: %[[RESULT:.*]] = arith.addi %[[TEMP]], %[[CONST]] : i32 +!CHECK: hlfir.assign %[[RESULT]] to %[[Z_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.terminator +!CHECK: } + + !$omp parallel default(firstprivate) private(x) shared(z) + x = y * 2 + z = w + 45 + !$omp end parallel + +!CHECK: omp.parallel { +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFEx"} +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_Y_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.terminator +!CHECK: } +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_W:.*]] = fir.alloca i32 {bindc_name = "w", pinned, uniq_name = "_QFEw"} +!CHECK: %[[PRIVATE_W_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_W]] {uniq_name = "_QFEw"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[TEMP:.*]] = fir.load %[[W_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_W_DECL]]#0 temporary_lhs : i32, !fir.ref<i32> +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFEx"} +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[TEMP:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 temporary_lhs : i32, !fir.ref<i32> +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_W_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.terminator +!CHECK: } +!CHECK: omp.terminator +!CHECK: } + !$omp parallel + !$omp parallel default(private) + x = y + !$omp end parallel + + !$omp parallel default(firstprivate) + w = x + !$omp end parallel + !$omp end parallel + +end program default_clause_lowering + +subroutine nested_default_clause_tests + integer :: x, y, z, w, k, a +!CHECK: %[[K:.*]] = fir.alloca i32 {bindc_name = "k", uniq_name = "_QFnested_default_clause_testsEk"} +!CHECK: %[[K_DECL:.*]]:2 = hlfir.declare %[[K]] {uniq_name = "_QFnested_default_clause_testsEk"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[W:.*]] = fir.alloca i32 {bindc_name = "w", uniq_name = "_QFnested_default_clause_testsEw"} +!CHECK: %[[W_DECL:.*]]:2 = hlfir.declare %[[W]] {uniq_name = "_QFnested_default_clause_testsEw"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFnested_default_clause_testsEx"} +!CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[Y:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[Z:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFnested_default_clause_testsEz"} +!CHECK: %[[Z_DECL:.*]]:2 = hlfir.declare %[[Z]] {uniq_name = "_QFnested_default_clause_testsEz"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[TEMP:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 temporary_lhs : i32, !fir.ref<i32> +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[PRIVATE_Z:.*]] = fir.alloca i32 {bindc_name = "z", pinned, uniq_name = "_QFnested_default_clause_testsEz"} +!CHECK: %[[PRIVATE_Z_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Z]] {uniq_name = "_QFnested_default_clause_testsEz"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[PRIVATE_K:.*]] = fir.alloca i32 {bindc_name = "k", pinned, uniq_name = "_QFnested_default_clause_testsEk"} +!CHECK: %[[PRIVATE_K_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_K]] {uniq_name = "_QFnested_default_clause_testsEk"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: omp.parallel { +!CHECK: %[[INNER_PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[INNER_PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[INNER_PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[INNER_PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} +!CHECK: %[[INNER_PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[INNER_PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[CONST:.*]] = arith.constant 20 : i32 +!CHECK: hlfir.assign %[[CONST]] to %[[INNER_PRIVATE_Y_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: %[[CONST:.*]] = arith.constant 10 : i32 +!CHECK: hlfir.assign %[[CONST]] to %[[INNER_PRIVATE_X_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.terminator +!CHECK: } +!CHECK: omp.parallel { +!CHECK: %[[INNER_PRIVATE_W:.*]] = fir.alloca i32 {bindc_name = "w", pinned, uniq_name = "_QFnested_default_clause_testsEw"} +!CHECK: %[[INNER_PRIVATE_W_DECL:.*]]:2 = hlfir.declare %[[INNER_PRIVATE_W]] {uniq_name = "_QFnested_default_clause_testsEw"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[INNER_PRIVATE_Z:.*]] = fir.alloca i32 {bindc_name = "z", pinned, uniq_name = "_QFnested_default_clause_testsEz"} +!CHECK: %[[INNER_PRIVATE_Z_DECL:.*]]:2 = hlfir.declare %[[INNER_PRIVATE_Z]] {uniq_name = "_QFnested_default_clause_testsEz"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_Z_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[INNER_PRIVATE_Z_DECL]]#0 temporary_lhs : i32, !fir.ref<i32> +!CHECK: %[[INNER_PRIVATE_K:.*]] = fir.alloca i32 {bindc_name = "k", pinned, uniq_name = "_QFnested_default_clause_testsEk"} +!CHECK: %[[INNER_PRIVATE_K_DECL:.*]]:2 = hlfir.declare %[[INNER_PRIVATE_K]] {uniq_name = "_QFnested_default_clause_testsEk"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_K_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[INNER_PRIVATE_K_DECL]]#0 temporary_lhs : i32, !fir.ref<i32> +!CHECK: %[[CONST:.*]] = arith.constant 30 : i32 +!CHECK: hlfir.assign %[[CONST]] to %[[PRIVATE_Y_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: %[[CONST:.*]] = arith.constant 40 : i32 +!CHECK: hlfir.assign %[[CONST]] to %[[INNER_PRIVATE_W_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: %[[CONST:.*]] = arith.constant 50 : i32 +!CHECK: hlfir.assign %[[CONST]] to %[[INNER_PRIVATE_Z_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: %[[CONST:.*]] = arith.constant 40 : i32 +!CHECK: hlfir.assign %[[CONST]] to %[[INNER_PRIVATE_K_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.terminator +!CHECK: } +!CHECK: omp.terminator +!CHECK: } + !$omp parallel firstprivate(x) private(y) shared(w) default(private) + !$omp parallel default(private) + y = 20 + x = 10 + !$omp end parallel + + !$omp parallel default(firstprivate) shared(y) private(w) + y = 30 + w = 40 + z = 50 + k = 40 + !$omp end parallel + !$omp end parallel + + +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[PRIVATE_Z:.*]] = fir.alloca i32 {bindc_name = "z", pinned, uniq_name = "_QFnested_default_clause_testsEz"} +!CHECK: %[[PRIVATE_Z_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Z]] {uniq_name = "_QFnested_default_clause_testsEz"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[PRIVATE_W:.*]] = fir.alloca i32 {bindc_name = "w", pinned, uniq_name = "_QFnested_default_clause_testsEw"} +!CHECK: %[[PRIVATE_W_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_W]] {uniq_name = "_QFnested_default_clause_testsEw"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_INNER_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} +!CHECK: %[[PRIVATE_INNER_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_INNER_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_INNER_X_DECL]]#0 temporary_lhs : i32, !fir.ref<i32> +!CHECK: %[[INNER_PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[INNER_PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[INNER_PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_Y_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[INNER_PRIVATE_Y_DECL]]#0 temporary_lhs : i32, !fir.ref<i32> +!CHECK: %[[TEMP:.*]] = fir.load %[[INNER_PRIVATE_Y_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_INNER_X_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.terminator +!CHECK: } +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_INNER_W:.*]] = fir.alloca i32 {bindc_name = "w", pinned, uniq_name = "_QFnested_default_clause_testsEw"} +!CHECK: %[[PRIVATE_INNER_W_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_INNER_W]] {uniq_name = "_QFnested_default_clause_testsEw"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[PRIVATE_INNER_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} +!CHECK: %[[PRIVATE_INNER_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_INNER_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[TEMP_1:.*]] = fir.load %[[PRIVATE_INNER_X_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[TEMP_2:.*]] = fir.load %[[PRIVATE_Z_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[RESULT:.*]] = arith.addi %{{.*}}, %{{.*}} : i32 +!CHECK: hlfir.assign %[[RESULT]] to %[[PRIVATE_INNER_W_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.terminator +!CHECK: } + !$omp parallel default(private) + !$omp parallel default(firstprivate) + x = y + !$omp end parallel + + !$omp parallel default(private) shared(z) + w = x + z + !$omp end parallel + !$omp end parallel + +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[PRIVATE_W:.*]] = fir.alloca i32 {bindc_name = "w", pinned, uniq_name = "_QFnested_default_clause_testsEw"} +!CHECK: %[[PRIVATE_W_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_W]] {uniq_name = "_QFnested_default_clause_testsEw"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[PRIVATE_Z:.*]] = fir.alloca i32 {bindc_name = "z", pinned, uniq_name = "_QFnested_default_clause_testsEz"} +!CHECK: %[[PRIVATE_Z_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Z]] {uniq_name = "_QFnested_default_clause_testsEz"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: omp.parallel { +!CHECK: %[[INNER_PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} +!CHECK: %[[INNER_PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[INNER_PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[INNER_PRIVATE_X_DECL]]#0 temporary_lhs : i32, !fir.ref<i32> +!CHECK: %[[INNER_PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[INNER_PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[INNER_PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_Y_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[INNER_PRIVATE_Y_DECL]]#0 temporary_lhs : i32, !fir.ref<i32> +!CHECK: %[[TEMP:.*]] = fir.load %[[INNER_PRIVATE_Y_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[INNER_PRIVATE_X_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.terminator +!CHECK: } +!CHECK: omp.parallel { +!CHECK: %[[TEMP_1:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[TEMP_2:.*]] = fir.load %[[PRIVATE_Z_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[TEMP_3:.*]] = arith.addi %[[TEMP_1]], %[[TEMP_2]] : i32 +!CHECK: hlfir.assign %[[TEMP_3]] to %[[PRIVATE_W_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.terminator +!CHECK: } +!CHECK: } + !$omp parallel default(private) + !$omp parallel default(firstprivate) + x = y + !$omp end parallel + + !$omp parallel default(shared) + w = x + z + !$omp end parallel + !$omp end parallel + +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFnested_default_clause_testsEx"} +!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFnested_default_clause_testsEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[TEMP:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 temporary_lhs : i32, !fir.ref<i32> +!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFnested_default_clause_testsEy"} +!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFnested_default_clause_testsEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[TEMP:.*]] = fir.load %[[Y_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_Y_DECL]]#0 temporary_lhs : i32, !fir.ref<i32> +!CHECK: omp.single { +!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_Y_DECL]]#0 : !fir.ref<i32> +!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.terminator +!CHECK: } +!CHECK: omp.terminator +!CHECK: } +!CHECK: return +!CHECK: } + !$omp parallel default(firstprivate) + !$omp single + x = y + !$omp end single + !$omp end parallel +end subroutine + +!CHECK: func.func @_QPskipped_default_clause_checks() { +!CHECK: %[[TYPE_ADDR:.*]] = fir.address_of(@_QFskipped_default_clause_checksE.n.i1) : !fir.ref<!fir.char<1,2>> +!CHECK: %[[VAL_CONST_2:.*]] = arith.constant 2 : index +!CHECK: %[[VAL_I1_DECLARE:.*]]:2 = hlfir.declare %[[TYPE_ADDR]] typeparams %[[VAL_CONST_2]] {{.*}} +!CHECK: %[[TYPE_ADDR_IT:.*]] = fir.address_of(@_QFskipped_default_clause_checksE.n.it) : !fir.ref<!fir.char<1,2>> +!CHECK: %[[VAL_CONST_2_0:.*]] = arith.constant 2 : index +!CHECK: %[[VAL_IT_DECLARE:.*]]:2 = hlfir.declare %[[TYPE_ADDR_IT]] typeparams %[[VAL_CONST_2_0]] {{.*}} +!CHECK: %[[VAL_I_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFskipped_default_clause_checksEi"} +!CHECK: %[[VAL_I_DECLARE:.*]]:2 = hlfir.declare %[[VAL_I_ALLOCA]] {{.*}} +!CHECK: %[[VAL_III_ALLOCA:.*]] = fir.alloca !fir.type<_QFskipped_default_clause_checksTit{i1:i32}> {bindc_name = "iii", uniq_name = "_QFskipped_default_clause_checksEiii"} +!CHECK: %[[VAL_III_DECLARE:.*]]:2 = hlfir.declare %[[VAL_III_ALLOCA]] {{.*}} +!CHECK: %[[VAL_X_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFskipped_default_clause_checksEx"} +!CHECK: %[[VAL_X_DECLARE:.*]]:2 = hlfir.declare %[[VAL_X_ALLOCA]] {{.*}} +!CHECK: %[[VAL_Y_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFskipped_default_clause_checksEy"} +!CHECK: %[[VAL_Y_DECLARE:.*]]:2 = hlfir.declare %[[VAL_Y_ALLOCA]] {{.*}} +!CHECK: %[[VAL_Z_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFskipped_default_clause_checksEz"} +!CHECK: %[[VAL_Z_DECLARE:.*]]:2 = hlfir.declare %[[VAL_Z_ALLOCA]] {{.*}} +subroutine skipped_default_clause_checks() + integer :: x,y,z + type it + integer::i1 + end type + type(it)::iii + +!CHECK: omp.parallel { +!CHECK: omp.wsloop byref reduction(@min_byref_i32 %[[VAL_Z_DECLARE]]#0 -> %[[PRV:.+]] : !fir.ref<i32>) for (%[[ARG:.*]]) {{.*}} { +!CHECK: omp.yield +!CHECK: } +!CHECK: omp.terminator +!CHECK: } + !$omp parallel do default(private) REDUCTION(MIN:z) + do i = 1, 10 + x = x + MIN(y,x) + enddo + !$omp end parallel do + +!CHECK: omp.parallel { +!CHECK: omp.terminator +!CHECK: } + namelist /nam/i + !$omp parallel default(private) + write(1,nam ) + !$omp endparallel + +!CHECK: omp.parallel { +!CHECK: %[[PRIVATE_III_ALLOCA:.*]] = fir.alloca !fir.type<_QFskipped_default_clause_checksTit{i1:i32}> {{.*}} +!CHECK: %[[PRIVATE_III_DECLARE:.*]]:2 = hlfir.declare %[[PRIVATE_III_ALLOCA]] {{.*}} +!CHECK: %[[PRIVATE_ADDR:.*]] = fir.address_of(@_QQro._QFskipped_default_clause_checksTit.0) : !fir.ref<!fir.type<_QFskipped_default_clause_checksTit{i1:i32}>> +!CHECK: %[[PRIVATE_PARAM:.*]]:2 = hlfir.declare %[[PRIVATE_ADDR]] {{.*}} +!CHECK: hlfir.assign %[[PRIVATE_PARAM]]#0 to %[[PRIVATE_III_DECLARE]]#0 {{.*}} +!CHECK: omp.terminator +!CHECK: } + !$omp parallel default(private) + iii=it(11) + !$omp end parallel +end subroutine diff --git a/flang/test/Lower/OpenMP/default-clause.f90 b/flang/test/Lower/OpenMP/default-clause.f90 index 0e118742689d60b5e904630e6913be52839217bc..f86b51aef4e0262a5601be9042c000780af7645a 100644 --- a/flang/test/Lower/OpenMP/default-clause.f90 +++ b/flang/test/Lower/OpenMP/default-clause.f90 @@ -352,7 +352,7 @@ subroutine skipped_default_clause_checks() type(it)::iii !CHECK: omp.parallel { -!CHECK: omp.wsloop reduction(@min_i_32 %[[VAL_Z_DECLARE]]#0 -> %[[PRV:.+]] : !fir.ref<i32>) for (%[[ARG:.*]]) {{.*}} { +!CHECK: omp.wsloop reduction(@min_i32 %[[VAL_Z_DECLARE]]#0 -> %[[PRV:.+]] : !fir.ref<i32>) for (%[[ARG:.*]]) {{.*}} { !CHECK: omp.yield !CHECK: } !CHECK: omp.terminator diff --git a/flang/test/Lower/OpenMP/delayed-privatization-allocatable-firstprivate.f90 b/flang/test/Lower/OpenMP/delayed-privatization-allocatable-firstprivate.f90 new file mode 100644 index 0000000000000000000000000000000000000000..aa835f82b2730b2d4056be698a7cf702688e7bed --- /dev/null +++ b/flang/test/Lower/OpenMP/delayed-privatization-allocatable-firstprivate.f90 @@ -0,0 +1,36 @@ +! Test delayed privatization for allocatables: `firstprivate`. + +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --openmp-enable-delayed-privatization \ +! RUN: -o - %s 2>&1 | FileCheck %s +! RUN: bbc -emit-hlfir -fopenmp --openmp-enable-delayed-privatization -o - %s 2>&1 |\ +! RUN: FileCheck %s + +subroutine delayed_privatization_allocatable + implicit none + integer, allocatable :: var1 + +!$omp parallel firstprivate(var1) + var1 = 10 +!$omp end parallel +end subroutine + +! CHECK-LABEL: omp.private {type = firstprivate} +! CHECK-SAME: @[[PRIVATIZER_SYM:.*]] : [[TYPE:!fir.ref<!fir.box<!fir.heap<i32>>>]] alloc { + +! CHECK-NEXT: ^bb0(%[[PRIV_ARG:.*]]: [[TYPE]]): + +! CHECK: } copy { +! CHECK: ^bb0(%[[PRIV_ORIG_ARG:.*]]: [[TYPE]], %[[PRIV_PRIV_ARG:.*]]: [[TYPE]]): + +! CHECK-NEXT: %[[PRIV_BASE_VAL:.*]] = fir.load %[[PRIV_PRIV_ARG]] +! CHECK-NEXT: %[[PRIV_BASE_BOX:.*]] = fir.box_addr %[[PRIV_BASE_VAL]] +! CHECK-NEXT: %[[PRIV_BASE_ADDR:.*]] = fir.convert %[[PRIV_BASE_BOX]] +! CHECK-NEXT: %[[C0:.*]] = arith.constant 0 : i64 +! CHECK-NEXT: %[[COPY_COND:.*]] = arith.cmpi ne, %[[PRIV_BASE_ADDR]], %[[C0]] : i64 + +! CHECK-NEXT: fir.if %[[COPY_COND]] { +! CHECK-NEXT: %[[ORIG_BASE_VAL:.*]] = fir.load %[[PRIV_ORIG_ARG]] +! CHECK-NEXT: %[[ORIG_BASE_ADDR:.*]] = fir.box_addr %[[ORIG_BASE_VAL]] +! CHECK-NEXT: %[[ORIG_BASE_LD:.*]] = fir.load %[[ORIG_BASE_ADDR]] +! CHECK-NEXT: hlfir.assign %[[ORIG_BASE_LD]] to %[[PRIV_BASE_BOX]] temporary_lhs +! CHECK-NEXT: } diff --git a/flang/test/Lower/OpenMP/delayed-privatization-allocatable-private.f90 b/flang/test/Lower/OpenMP/delayed-privatization-allocatable-private.f90 new file mode 100644 index 0000000000000000000000000000000000000000..cc1818b00b809c90f939a9b16f34aada232872f2 --- /dev/null +++ b/flang/test/Lower/OpenMP/delayed-privatization-allocatable-private.f90 @@ -0,0 +1,43 @@ +! Test delayed privatization for allocatables: `private`. + +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --openmp-enable-delayed-privatization \ +! RUN: -o - %s 2>&1 | FileCheck %s +! RUN: bbc -emit-hlfir -fopenmp --openmp-enable-delayed-privatization -o - %s 2>&1 |\ +! RUN: FileCheck %s + +subroutine delayed_privatization_allocatable + implicit none + integer, allocatable :: var1 + +!$omp parallel private(var1) + var1 = 10 +!$omp end parallel +end subroutine + +! CHECK-LABEL: omp.private {type = private} +! CHECK-SAME: @[[PRIVATIZER_SYM:.*]] : [[TYPE:!fir.ref<!fir.box<!fir.heap<i32>>>]] alloc { + +! CHECK-NEXT: ^bb0(%[[PRIV_ARG:.*]]: [[TYPE]]): + +! CHECK-NEXT: %[[PRIV_ALLOC:.*]] = fir.alloca !fir.box<!fir.heap<i32>> {bindc_name = "var1", pinned, uniq_name = "_QFdelayed_privatization_allocatableEvar1"} + +! CHECK-NEXT: %[[PRIV_ARG_VAL:.*]] = fir.load %[[PRIV_ARG]] : !fir.ref<!fir.box<!fir.heap<i32>>> +! CHECK-NEXT: %[[PRIV_ARG_BOX:.*]] = fir.box_addr %[[PRIV_ARG_VAL]] : (!fir.box<!fir.heap<i32>>) -> !fir.heap<i32> +! CHECK-NEXT: %[[PRIV_ARG_ADDR:.*]] = fir.convert %[[PRIV_ARG_BOX]] : (!fir.heap<i32>) -> i64 +! CHECK-NEXT: %[[C0:.*]] = arith.constant 0 : i64 +! CHECK-NEXT: %[[ALLOC_COND:.*]] = arith.cmpi ne, %[[PRIV_ARG_ADDR]], %[[C0]] : i64 + +! CHECK-NEXT: fir.if %[[ALLOC_COND]] { +! CHECK-NEXT: %[[PRIV_ALLOCMEM:.*]] = fir.allocmem i32 {fir.must_be_heap = true, uniq_name = "_QFdelayed_privatization_allocatableEvar1.alloc"} +! CHECK-NEXT: %[[PRIV_ALLOCMEM_BOX:.*]] = fir.embox %[[PRIV_ALLOCMEM]] : (!fir.heap<i32>) -> !fir.box<!fir.heap<i32>> +! CHECK-NEXT: fir.store %[[PRIV_ALLOCMEM_BOX]] to %[[PRIV_ALLOC]] : !fir.ref<!fir.box<!fir.heap<i32>>> +! CHECK-NEXT: } else { +! CHECK-NEXT: %[[ZERO_BITS:.*]] = fir.zero_bits !fir.heap<i32> +! CHECK-NEXT: %[[ZERO_BOX:.*]] = fir.embox %[[ZERO_BITS]] : (!fir.heap<i32>) -> !fir.box<!fir.heap<i32>> +! CHECK-NEXT: fir.store %[[ZERO_BOX]] to %[[PRIV_ALLOC]] : !fir.ref<!fir.box<!fir.heap<i32>>> +! CHECK-NEXT: } + +! CHECK-NEXT: %[[PRIV_DECL:.*]]:2 = hlfir.declare %[[PRIV_ALLOC]] +! CHECK-NEXT: omp.yield(%[[PRIV_DECL]]#0 : [[TYPE]]) + +! CHECK-NEXT: } diff --git a/flang/test/Lower/OpenMP/delayed-privatization-pointer.f90 b/flang/test/Lower/OpenMP/delayed-privatization-pointer.f90 new file mode 100644 index 0000000000000000000000000000000000000000..796e4720c8c9547cc9d64df991d9172b206b0923 --- /dev/null +++ b/flang/test/Lower/OpenMP/delayed-privatization-pointer.f90 @@ -0,0 +1,31 @@ +! Test delayed privatization for pointers: `private`. + +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --openmp-enable-delayed-privatization \ +! RUN: -o - %s 2>&1 | FileCheck %s +! RUN: bbc -emit-hlfir -fopenmp --openmp-enable-delayed-privatization -o - %s 2>&1 |\ +! RUN: FileCheck %s + +subroutine delayed_privatization_pointer + implicit none + integer, pointer :: var1 + +!$omp parallel firstprivate(var1) + var1 = 10 +!$omp end parallel +end subroutine + +! CHECK-LABEL: omp.private {type = firstprivate} +! CHECK-SAME: @[[PRIVATIZER_SYM:.*]] : [[TYPE:!fir.ref<!fir.box<!fir.ptr<i32>>>]] alloc { + +! CHECK-NEXT: ^bb0(%[[PRIV_ARG:.*]]: [[TYPE]]): + +! CHECK-NEXT: %[[PRIV_ALLOC:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "var1", pinned, uniq_name = "_QFdelayed_privatization_pointerEvar1"} +! CHECK-NEXT: %[[PRIV_DECL:.*]]:2 = hlfir.declare %[[PRIV_ALLOC]] +! CHECK-NEXT: omp.yield(%[[PRIV_DECL]]#0 : [[TYPE]]) + +! CHECK-NEXT: } copy { +! CHECK: ^bb0(%[[PRIV_ORIG_ARG:.*]]: [[TYPE]], %[[PRIV_PRIV_ARG:.*]]: [[TYPE]]): +! CHECK-NEXT: %[[ORIG_BASE_VAL:.*]] = fir.load %[[PRIV_ORIG_ARG]] + ! CHECK-NEXT: fir.store %[[ORIG_BASE_VAL]] to %[[PRIV_PRIV_ARG]] : !fir.ref<!fir.box<!fir.ptr<i32>>> +! CHECK-NEXT: omp.yield(%[[PRIV_PRIV_ARG]] : [[TYPE]]) +! CHECK-NEXT: } diff --git a/flang/test/Lower/OpenMP/delayed-privatization-reduction-byref.f90 b/flang/test/Lower/OpenMP/delayed-privatization-reduction-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..49d1142ea4b6aa165be0e0961356c70b97fcd062 --- /dev/null +++ b/flang/test/Lower/OpenMP/delayed-privatization-reduction-byref.f90 @@ -0,0 +1,30 @@ +! Test that reductions and delayed privatization work properly togehter. Since +! both types of clauses add block arguments to the OpenMP region, we make sure +! that the block arguments are added in the proper order (reductions first and +! then delayed privatization. + +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction --openmp-enable-delayed-privatization -o - %s 2>&1 | FileCheck %s + +subroutine red_and_delayed_private + integer :: red + integer :: prv + + red = 0 + prv = 10 + + !$omp parallel reduction(+:red) private(prv) + red = red + 1 + prv = 20 + !$omp end parallel +end subroutine + +! CHECK-LABEL: omp.private {type = private} +! CHECK-SAME: @[[PRIVATIZER_SYM:.*]] : !fir.ref<i32> alloc { + +! CHECK-LABEL: omp.declare_reduction +! CHECK-SAME: @[[REDUCTION_SYM:.*]] : !fir.ref<i32> init + +! CHECK-LABEL: _QPred_and_delayed_private +! CHECK: omp.parallel +! CHECK-SAME: reduction(@[[REDUCTION_SYM]] %{{.*}} -> %arg0 : !fir.ref<i32>) +! CHECK-SAME: private(@[[PRIVATIZER_SYM]] %{{.*}} -> %arg1 : !fir.ref<i32>) { diff --git a/flang/test/Lower/OpenMP/delayed-privatization-reduction.f90 b/flang/test/Lower/OpenMP/delayed-privatization-reduction.f90 index a7eeb1faceadef85886920dad7b2420c7660f770..d814b2b0ff0f31a07ba07fcf44c279fe8a56fb89 100644 --- a/flang/test/Lower/OpenMP/delayed-privatization-reduction.f90 +++ b/flang/test/Lower/OpenMP/delayed-privatization-reduction.f90 @@ -24,7 +24,7 @@ end subroutine ! CHECK-LABEL: omp.private {type = private} ! CHECK-SAME: @[[PRIVATIZER_SYM:.*]] : !fir.ref<i32> alloc { -! CHECK-LABEL: omp.reduction.declare +! CHECK-LABEL: omp.declare_reduction ! CHECK-SAME: @[[REDUCTION_SYM:.*]] : i32 init ! CHECK-LABEL: _QPred_and_delayed_private diff --git a/flang/test/Lower/OpenMP/map-component-ref.f90 b/flang/test/Lower/OpenMP/map-component-ref.f90 index 1ed37e73158025b8af4c8049b9858a169b72ec7c..435bc8e6bd368ab9ddb9d79f1ed0808dfa24ff74 100644 --- a/flang/test/Lower/OpenMP/map-component-ref.f90 +++ b/flang/test/Lower/OpenMP/map-component-ref.f90 @@ -4,8 +4,8 @@ ! CHECK: %[[V0:[0-9]+]] = fir.alloca !fir.type<_QFfooTt0{a0:i32,a1:i32}> {bindc_name = "a", uniq_name = "_QFfooEa"} ! CHECK: %[[V1:[0-9]+]]:2 = hlfir.declare %[[V0]] {uniq_name = "_QFfooEa"} : (!fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>) -> (!fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>, !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>) ! CHECK: %[[V2:[0-9]+]] = hlfir.designate %[[V1]]#0{"a1"} : (!fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>) -> !fir.ref<i32> -! CHECK: %[[V3:[0-9]+]] = omp.map_info var_ptr(%[[V2]] : !fir.ref<i32>, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref<i32> {name = "a%a1"} -! CHECK: %[[V4:[0-9]+]] = omp.map_info var_ptr(%[[V1]]#1 : !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>, !fir.type<_QFfooTt0{a0:i32,a1:i32}>) map_clauses(implicit, tofrom) capture(ByRef) -> !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>> {name = "a"} +! CHECK: %[[V3:[0-9]+]] = omp.map.info var_ptr(%[[V2]] : !fir.ref<i32>, i32) map_clauses(tofrom) capture(ByRef) -> !fir.ref<i32> {name = "a%a1"} +! CHECK: %[[V4:[0-9]+]] = omp.map.info var_ptr(%[[V1]]#1 : !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>, !fir.type<_QFfooTt0{a0:i32,a1:i32}>) map_clauses(implicit, tofrom) capture(ByRef) -> !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>> {name = "a"} ! CHECK: omp.target map_entries(%[[V3]] -> %arg0, %[[V4]] -> %arg1 : !fir.ref<i32>, !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>) { ! CHECK: ^bb0(%arg0: !fir.ref<i32>, %arg1: !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>): ! CHECK: %[[V5:[0-9]+]]:2 = hlfir.declare %arg1 {uniq_name = "_QFfooEa"} : (!fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>) -> (!fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>, !fir.ref<!fir.type<_QFfooTt0{a0:i32,a1:i32}>>) diff --git a/flang/test/Lower/OpenMP/omp-lib-num-threads.f90 b/flang/test/Lower/OpenMP/omp-lib-num-threads.f90 index e1af7d375dfa5a8fe08d35703242de6a2063fc93..d2b558a886ebedb1e7944d242e6cda986e8b4a90 100644 --- a/flang/test/Lower/OpenMP/omp-lib-num-threads.f90 +++ b/flang/test/Lower/OpenMP/omp-lib-num-threads.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - 2>&1 | FileCheck %s ! RUN: bbc -fopenmp -emit-hlfir -o - %s 2>&1 | FileCheck %s ! RUN: %flang_fc1 -emit-fir -fopenmp %s -o - 2>&1 | FileCheck %s diff --git a/flang/test/Lower/OpenMP/ordered-threads.f90 b/flang/test/Lower/OpenMP/ordered-threads.f90 index a3f99129eba7ee14de47b23e99701c85025fde28..81f5c419b2368d6dfcc8036790dd62240783ccec 100644 --- a/flang/test/Lower/OpenMP/ordered-threads.f90 +++ b/flang/test/Lower/OpenMP/ordered-threads.f90 @@ -8,14 +8,14 @@ subroutine ordered integer :: i integer :: a(20) -!CHECK: omp.ordered_region { +!CHECK: omp.ordered.region { !$OMP ORDERED a(i) = a(i-1) + 1 !CHECK: omp.terminator !CHECK-NEXT: } !$OMP END ORDERED -!CHECK: omp.ordered_region { +!CHECK: omp.ordered.region { !$OMP ORDERED THREADS a(i) = a(i-1) + 1 !CHECK: omp.terminator diff --git a/flang/test/Lower/OpenMP/parallel-reduction-add-byref.f90 b/flang/test/Lower/OpenMP/parallel-reduction-add-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..2a1d26407b27e9ec0272ba57dc0117f05f94602a --- /dev/null +++ b/flang/test/Lower/OpenMP/parallel-reduction-add-byref.f90 @@ -0,0 +1,125 @@ +! RUN: bbc -emit-hlfir --force-byref-reduction -fopenmp -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction -o - %s 2>&1 | FileCheck %s + +!CHECK-LABEL: omp.declare_reduction +!CHECK-SAME: @[[RED_F32_NAME:.*]] : !fir.ref<f32> +!CHECK-SAME: init { +!CHECK: ^bb0(%{{.*}}: !fir.ref<f32>): +!CHECK: %[[C0_1:.*]] = arith.constant 0.000000e+00 : f32 +!CHECK: %[[REF:.*]] = fir.alloca f32 +!CHECKL fir.store [[%C0_1]] to %[[REF]] : !fir.ref<f32> +!CHECK: omp.yield(%[[REF]] : !fir.ref<f32>) +!CHECK: } combiner { +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<f32>, %[[ARG1:.*]]: !fir.ref<f32>): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<f32> +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<f32> +!CHECK: %[[RES:.*]] = arith.addf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<f32> +!CHECK: omp.yield(%[[ARG0]] : !fir.ref<f32>) +!CHECK: } + +!CHECK-LABEL: omp.declare_reduction +!CHECK-SAME: @[[RED_I32_NAME:.*]] : !fir.ref<i32> +!CHECK-SAME: init { +!CHECK: ^bb0(%{{.*}}: !fir.ref<i32>): +!CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +!CHECK: %[[REF:.*]] = fir.alloca i32 +!CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref<i32> +!CHECK: omp.yield(%[[REF]] : !fir.ref<i32>) +!CHECK: } combiner { +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> +!CHECK: %[[RES:.*]] = arith.addi %[[LD0]], %[[LD1]] : i32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i32> +!CHECK: omp.yield(%[[ARG0]] : !fir.ref<i32>) +!CHECK: } + +!CHECK-LABEL: func.func @_QPsimple_int_add +!CHECK: %[[IREF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_int_addEi"} +!CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[IREF]] {uniq_name = "_QFsimple_int_addEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[I_START:.*]] = arith.constant 0 : i32 +!CHECK: hlfir.assign %[[I_START]] to %[[I_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.parallel byref reduction(@[[RED_I32_NAME]] %[[I_DECL]]#0 -> %[[PRV:.+]] : !fir.ref<i32>) { +!CHECK: %[[P_DECL:.+]]:2 = hlfir.declare %[[PRV]] {{.*}} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[LPRV:.+]] = fir.load %[[P_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[I_INCR:.*]] = arith.constant 1 : i32 +!CHECK: %[[RES:.+]] = arith.addi %[[LPRV]], %[[I_INCR]] : i32 +!CHECK: hlfir.assign %[[RES]] to %[[P_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.terminator +!CHECK: } +!CHECK: return +subroutine simple_int_add + integer :: i + i = 0 + + !$omp parallel reduction(+:i) + i = i + 1 + !$omp end parallel + + print *, i +end subroutine + +!CHECK-LABEL: func.func @_QPsimple_real_add +!CHECK: %[[RREF:.*]] = fir.alloca f32 {bindc_name = "r", uniq_name = "_QFsimple_real_addEr"} +!CHECK: %[[R_DECL:.*]]:2 = hlfir.declare %[[RREF]] {uniq_name = "_QFsimple_real_addEr"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +!CHECK: %[[R_START:.*]] = arith.constant 0.000000e+00 : f32 +!CHECK: hlfir.assign %[[R_START]] to %[[R_DECL]]#0 : f32, !fir.ref<f32> +!CHECK: omp.parallel byref reduction(@[[RED_F32_NAME]] %[[R_DECL]]#0 -> %[[PRV:.+]] : !fir.ref<f32>) { +!CHECK: %[[P_DECL:.+]]:2 = hlfir.declare %[[PRV]] {{.*}} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +!CHECK: %[[LPRV:.+]] = fir.load %[[P_DECL]]#0 : !fir.ref<f32> +!CHECK: %[[R_INCR:.*]] = arith.constant 1.500000e+00 : f32 +!CHECK: %[[RES:.+]] = arith.addf %[[LPRV]], %[[R_INCR]] {{.*}} : f32 +!CHECK: hlfir.assign %[[RES]] to %[[P_DECL]]#0 : f32, !fir.ref<f32> +!CHECK: omp.terminator +!CHECK: } +!CHECK: return +subroutine simple_real_add + real :: r + r = 0.0 + + !$omp parallel reduction(+:r) + r = r + 1.5 + !$omp end parallel + + print *, r +end subroutine + +!CHECK-LABEL: func.func @_QPint_real_add +!CHECK: %[[IREF:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFint_real_addEi"} +!CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[IREF]] {uniq_name = "_QFint_real_addEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[RREF:.*]] = fir.alloca f32 {bindc_name = "r", uniq_name = "_QFint_real_addEr"} +!CHECK: %[[R_DECL:.*]]:2 = hlfir.declare %[[RREF]] {uniq_name = "_QFint_real_addEr"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +!CHECK: %[[R_START:.*]] = arith.constant 0.000000e+00 : f32 +!CHECK: hlfir.assign %[[R_START]] to %[[R_DECL]]#0 : f32, !fir.ref<f32> +!CHECK: %[[I_START:.*]] = arith.constant 0 : i32 +!CHECK: hlfir.assign %[[I_START]] to %[[I_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.parallel byref reduction(@[[RED_I32_NAME]] %[[I_DECL]]#0 -> %[[IPRV:.+]] : !fir.ref<i32>, @[[RED_F32_NAME]] %[[R_DECL]]#0 -> %[[RPRV:.+]] : !fir.ref<f32>) { +!CHECK: %[[IP_DECL:.+]]:2 = hlfir.declare %[[IPRV]] {{.*}} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[RP_DECL:.+]]:2 = hlfir.declare %[[RPRV]] {{.*}} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +!CHECK: %[[R_INCR:.*]] = arith.constant 1.500000e+00 : f32 +!CHECK: %[[R_LPRV:.+]] = fir.load %[[RP_DECL]]#0 : !fir.ref<f32> +!CHECK: %[[RES1:.+]] = arith.addf %[[R_INCR]], %[[R_LPRV]] {{.*}} : f32 +!CHECK: hlfir.assign %[[RES1]] to %[[RP_DECL]]#0 : f32, !fir.ref<f32> +!CHECK: %[[I_LPRV:.+]] = fir.load %[[IP_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[I_INCR:.*]] = arith.constant 3 : i32 +!CHECK: %[[RES0:.+]] = arith.addi %[[I_LPRV]], %[[I_INCR]] : i32 +!CHECK: hlfir.assign %[[RES0]] to %[[IP_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.terminator +!CHECK: } +!CHECK: return +subroutine int_real_add + real :: r + integer :: i + + r = 0.0 + i = 0 + + !$omp parallel reduction(+:i,r) + r = 1.5 + r + i = i + 3 + !$omp end parallel + + print *, r + print *, i +end subroutine diff --git a/flang/test/Lower/OpenMP/parallel-reduction-add.f90 b/flang/test/Lower/OpenMP/parallel-reduction-add.f90 index 8f3ac3dc357af44bf493be611ea1840270653913..213fc71cc3494bd1ada0a65dc4067b36ff56b913 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-add.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-add.f90 @@ -1,7 +1,7 @@ ! RUN: bbc -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s ! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s -!CHECK-LABEL: omp.reduction.declare +!CHECK-LABEL: omp.declare_reduction !CHECK-SAME: @[[RED_F32_NAME:.*]] : f32 init { !CHECK: ^bb0(%{{.*}}: f32): !CHECK: %[[C0_1:.*]] = arith.constant 0.000000e+00 : f32 @@ -12,7 +12,7 @@ !CHECK: omp.yield(%[[RES]] : f32) !CHECK: } -!CHECK-LABEL: omp.reduction.declare +!CHECK-LABEL: omp.declare_reduction !CHECK-SAME: @[[RED_I32_NAME:.*]] : i32 init { !CHECK: ^bb0(%{{.*}}: i32): !CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 diff --git a/flang/test/Lower/OpenMP/parallel-reduction-array.f90 b/flang/test/Lower/OpenMP/parallel-reduction-array.f90 new file mode 100644 index 0000000000000000000000000000000000000000..735a99854308cf222b9a458474c2ab922c6b4ec0 --- /dev/null +++ b/flang/test/Lower/OpenMP/parallel-reduction-array.f90 @@ -0,0 +1,74 @@ +! RUN: bbc -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s + +program reduce +integer, dimension(3) :: i = 0 + +!$omp parallel reduction(+:i) +i(1) = 1 +i(2) = 2 +i(3) = 3 +!$omp end parallel + +print *,i +end program + +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_3xi32 : !fir.ref<!fir.box<!fir.array<3xi32>>> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.array<3xi32>>>): +! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.array<3xi32> {bindc_name = ".tmp"} +! CHECK: %[[VAL_2:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: %[[VAL_4:.*]] = arith.constant 3 : index +! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_5]]) {uniq_name = ".tmp"} : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<3xi32>>, !fir.ref<!fir.array<3xi32>>) +! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_6]]#0(%[[VAL_5]]) : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<3xi32>> +! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_7]] : i32, !fir.box<!fir.array<3xi32>> +! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box<!fir.array<3xi32>> +! CHECK: fir.store %[[VAL_7]] to %[[VAL_8]] : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: omp.yield(%[[VAL_8]] : !fir.ref<!fir.box<!fir.array<3xi32>>>) +! CHECK: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.array<3xi32>>>, %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.array<3xi32>>>): +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_4]] : (!fir.box<!fir.array<3xi32>>, index) -> (index, index, index) +! CHECK: %[[VAL_6:.*]] = fir.shape_shift %[[VAL_5]]#0, %[[VAL_5]]#1 : (index, index) -> !fir.shapeshift<1> +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_8:.*]] = %[[VAL_7]] to %[[VAL_5]]#1 step %[[VAL_7]] unordered { +! CHECK: %[[VAL_9:.*]] = fir.array_coor %[[VAL_2]](%[[VAL_6]]) %[[VAL_8]] : (!fir.box<!fir.array<3xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32> +! CHECK: %[[VAL_10:.*]] = fir.array_coor %[[VAL_3]](%[[VAL_6]]) %[[VAL_8]] : (!fir.box<!fir.array<3xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32> +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_9]] : !fir.ref<i32> +! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_10]] : !fir.ref<i32> +! CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_11]], %[[VAL_12]] : i32 +! CHECK: fir.store %[[VAL_13]] to %[[VAL_9]] : !fir.ref<i32> +! CHECK: } +! CHECK: omp.yield(%[[VAL_0]] : !fir.ref<!fir.box<!fir.array<3xi32>>>) +! CHECK: } + +! CHECK-LABEL: func.func @_QQmain() +! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEi) : !fir.ref<!fir.array<3xi32>> +! CHECK: %[[VAL_1:.*]] = arith.constant 3 : index +! CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_2]]) {uniq_name = "_QFEi"} : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<3xi32>>, !fir.ref<!fir.array<3xi32>>) +! CHECK: %[[VAL_4:.*]] = fir.embox %[[VAL_3]]#1(%[[VAL_2]]) : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<3xi32>> +! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.box<!fir.array<3xi32>> +! CHECK: fir.store %[[VAL_4]] to %[[VAL_5]] : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: omp.parallel byref reduction(@add_reduction_byref_box_3xi32 %[[VAL_5]] -> %[[VAL_6:.*]] : !fir.ref<!fir.box<!fir.array<3xi32>>>) { +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFEi"} : (!fir.ref<!fir.box<!fir.array<3xi32>>>) -> (!fir.ref<!fir.box<!fir.array<3xi32>>>, !fir.ref<!fir.box<!fir.array<3xi32>>>) +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_9:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_11:.*]] = hlfir.designate %[[VAL_9]] (%[[VAL_10]]) : (!fir.box<!fir.array<3xi32>>, index) -> !fir.ref<i32> +! CHECK: hlfir.assign %[[VAL_8]] to %[[VAL_11]] : i32, !fir.ref<i32> +! CHECK: %[[VAL_12:.*]] = arith.constant 2 : i32 +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: %[[VAL_14:.*]] = arith.constant 2 : index +! CHECK: %[[VAL_15:.*]] = hlfir.designate %[[VAL_13]] (%[[VAL_14]]) : (!fir.box<!fir.array<3xi32>>, index) -> !fir.ref<i32> +! CHECK: hlfir.assign %[[VAL_12]] to %[[VAL_15]] : i32, !fir.ref<i32> +! CHECK: %[[VAL_16:.*]] = arith.constant 3 : i32 +! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: %[[VAL_18:.*]] = arith.constant 3 : index +! CHECK: %[[VAL_19:.*]] = hlfir.designate %[[VAL_17]] (%[[VAL_18]]) : (!fir.box<!fir.array<3xi32>>, index) -> !fir.ref<i32> +! CHECK: hlfir.assign %[[VAL_16]] to %[[VAL_19]] : i32, !fir.ref<i32> +! CHECK: omp.terminator +! CHECK: } diff --git a/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 b/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 new file mode 100644 index 0000000000000000000000000000000000000000..4834047a98a4a16ea3fb9c43a15b374adae79963 --- /dev/null +++ b/flang/test/Lower/OpenMP/parallel-reduction-array2.f90 @@ -0,0 +1,89 @@ +! RUN: bbc -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s + +program reduce +integer, dimension(3) :: i = 0 + +!$omp parallel reduction(+:i) +i(1) = i(1) + 1 +i(2) = i(2) + 2 +i(3) = i(3) + 3 +!$omp end parallel + +print *,i +end program + +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_box_3xi32 : !fir.ref<!fir.box<!fir.array<3xi32>>> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.array<3xi32>>>): +! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.array<3xi32> {bindc_name = ".tmp"} +! CHECK: %[[VAL_2:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: %[[VAL_4:.*]] = arith.constant 3 : index +! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_5]]) {uniq_name = ".tmp"} : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<3xi32>>, !fir.ref<!fir.array<3xi32>>) +! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_6]]#0(%[[VAL_5]]) : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<3xi32>> +! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_7]] : i32, !fir.box<!fir.array<3xi32>> +! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box<!fir.array<3xi32>> +! CHECK: fir.store %[[VAL_7]] to %[[VAL_8]] : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: omp.yield(%[[VAL_8]] : !fir.ref<!fir.box<!fir.array<3xi32>>>) +! CHECK: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.array<3xi32>>>, %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.array<3xi32>>>): +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_4]] : (!fir.box<!fir.array<3xi32>>, index) -> (index, index, index) +! CHECK: %[[VAL_6:.*]] = fir.shape_shift %[[VAL_5]]#0, %[[VAL_5]]#1 : (index, index) -> !fir.shapeshift<1> +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_8:.*]] = %[[VAL_7]] to %[[VAL_5]]#1 step %[[VAL_7]] unordered { +! CHECK: %[[VAL_9:.*]] = fir.array_coor %[[VAL_2]](%[[VAL_6]]) %[[VAL_8]] : (!fir.box<!fir.array<3xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32> +! CHECK: %[[VAL_10:.*]] = fir.array_coor %[[VAL_3]](%[[VAL_6]]) %[[VAL_8]] : (!fir.box<!fir.array<3xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32> +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_9]] : !fir.ref<i32> +! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_10]] : !fir.ref<i32> +! CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_11]], %[[VAL_12]] : i32 +! CHECK: fir.store %[[VAL_13]] to %[[VAL_9]] : !fir.ref<i32> +! CHECK: } +! CHECK: omp.yield(%[[VAL_0]] : !fir.ref<!fir.box<!fir.array<3xi32>>>) +! CHECK: } + +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { +! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEi) : !fir.ref<!fir.array<3xi32>> +! CHECK: %[[VAL_1:.*]] = arith.constant 3 : index +! CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_2]]) {uniq_name = "_QFEi"} : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<3xi32>>, !fir.ref<!fir.array<3xi32>>) +! CHECK: %[[VAL_4:.*]] = fir.embox %[[VAL_3]]#1(%[[VAL_2]]) : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<3xi32>> +! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.box<!fir.array<3xi32>> +! CHECK: fir.store %[[VAL_4]] to %[[VAL_5]] : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: omp.parallel byref reduction(@add_reduction_byref_box_3xi32 %[[VAL_5]] -> %[[VAL_6:.*]] : !fir.ref<!fir.box<!fir.array<3xi32>>>) { +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFEi"} : (!fir.ref<!fir.box<!fir.array<3xi32>>>) -> (!fir.ref<!fir.box<!fir.array<3xi32>>>, !fir.ref<!fir.box<!fir.array<3xi32>>>) +! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_10:.*]] = hlfir.designate %[[VAL_8]] (%[[VAL_9]]) : (!fir.box<!fir.array<3xi32>>, index) -> !fir.ref<i32> +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_10]] : !fir.ref<i32> +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_11]], %[[VAL_12]] : i32 +! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: %[[VAL_15:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_16:.*]] = hlfir.designate %[[VAL_14]] (%[[VAL_15]]) : (!fir.box<!fir.array<3xi32>>, index) -> !fir.ref<i32> +! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_16]] : i32, !fir.ref<i32> +! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: %[[VAL_18:.*]] = arith.constant 2 : index +! CHECK: %[[VAL_19:.*]] = hlfir.designate %[[VAL_17]] (%[[VAL_18]]) : (!fir.box<!fir.array<3xi32>>, index) -> !fir.ref<i32> +! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_19]] : !fir.ref<i32> +! CHECK: %[[VAL_21:.*]] = arith.constant 2 : i32 +! CHECK: %[[VAL_22:.*]] = arith.addi %[[VAL_20]], %[[VAL_21]] : i32 +! CHECK: %[[VAL_23:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: %[[VAL_24:.*]] = arith.constant 2 : index +! CHECK: %[[VAL_25:.*]] = hlfir.designate %[[VAL_23]] (%[[VAL_24]]) : (!fir.box<!fir.array<3xi32>>, index) -> !fir.ref<i32> +! CHECK: hlfir.assign %[[VAL_22]] to %[[VAL_25]] : i32, !fir.ref<i32> +! CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: %[[VAL_27:.*]] = arith.constant 3 : index +! CHECK: %[[VAL_28:.*]] = hlfir.designate %[[VAL_26]] (%[[VAL_27]]) : (!fir.box<!fir.array<3xi32>>, index) -> !fir.ref<i32> +! CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_28]] : !fir.ref<i32> +! CHECK: %[[VAL_30:.*]] = arith.constant 3 : i32 +! CHECK: %[[VAL_31:.*]] = arith.addi %[[VAL_29]], %[[VAL_30]] : i32 +! CHECK: %[[VAL_32:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.array<3xi32>>> +! CHECK: %[[VAL_33:.*]] = arith.constant 3 : index +! CHECK: %[[VAL_34:.*]] = hlfir.designate %[[VAL_32]] (%[[VAL_33]]) : (!fir.box<!fir.array<3xi32>>, index) -> !fir.ref<i32> +! CHECK: hlfir.assign %[[VAL_31]] to %[[VAL_34]] : i32, !fir.ref<i32> +! CHECK: omp.terminator +! CHECK: } diff --git a/flang/test/Lower/OpenMP/parallel-reduction-byref.f90 b/flang/test/Lower/OpenMP/parallel-reduction-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..fdcdf0c0b8d95535748e36c38d3f80790fe41d77 --- /dev/null +++ b/flang/test/Lower/OpenMP/parallel-reduction-byref.f90 @@ -0,0 +1,44 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction -o - %s 2>&1 | FileCheck %s + +!CHECK: omp.declare_reduction @[[REDUCTION_DECLARE:[_a-z0-9]+]] : !fir.ref<i32> +!CHECK-SAME: init { +!CHECK: ^bb0(%{{.*}}: !fir.ref<i32>): +!CHECK: %[[I0:[_a-z0-9]+]] = arith.constant 0 : i32 +!CHECK: %[[REF:.*]] = fir.alloca i32 +!CHECKL fir.store [[%I0]] to %[[REF]] : !fir.ref<i32> +!CHECK: omp.yield(%[[REF]] : !fir.ref<i32>) +!CHECK: } combiner { +!CHECK: ^bb0(%[[C0:[_a-z0-9]+]]: !fir.ref<i32>, %[[C1:[_a-z0-9]+]]: !fir.ref<i32>): +!CHECK: %[[LD0:.*]] = fir.load %[[C0]] : !fir.ref<i32> +!CHECK: %[[LD1:.*]] = fir.load %[[C1]] : !fir.ref<i32> +!CHECK: %[[CR:[_a-z0-9]+]] = arith.addi %[[LD0]], %[[LD1]] : i32 +!CHECK: fir.store %[[CR]] to %[[C0]] : !fir.ref<i32> +!CHECK: omp.yield(%[[C0]] : !fir.ref<i32>) +!CHECK: } +!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<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[C0:[_a-z0-9]+]] = arith.constant 0 : i32 +!CHECK: hlfir.assign %[[C0]] to %[[RED_ACCUM_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.parallel byref reduction(@[[REDUCTION_DECLARE]] %[[RED_ACCUM_DECL]]#0 -> %[[PRIVATE_RED:[a-z0-9]+]] : !fir.ref<i32>) { +!CHECK: %[[PRIVATE_DECL:[_a-z0-9]+]]:2 = hlfir.declare %[[PRIVATE_RED]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[C1:[_a-z0-9]+]] = arith.constant 1 : i32 +!CHECK: hlfir.assign %[[C1]] to %[[PRIVATE_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.terminator +!CHECK: } +!CHECK: %[[RED_ACCUM_VAL:[_a-z0-9]+]] = fir.load %[[RED_ACCUM_DECL]]#0 : !fir.ref<i32> +!CHECK: {{.*}} = fir.call @_FortranAioOutputInteger32(%{{.*}}, %[[RED_ACCUM_VAL]]) fastmath<contract> : (!fir.ref<i8>, i32) -> i1 +!CHECK: return +!CHECK: } + +program mn + integer :: i + i = 0 + + !$omp parallel reduction(+:i) + i = 1 + !$omp end parallel + + print *, i +end program diff --git a/flang/test/Lower/OpenMP/parallel-reduction-rename.f90 b/flang/test/Lower/OpenMP/parallel-reduction-rename.f90 new file mode 100644 index 0000000000000000000000000000000000000000..c06343e997bfd26abae9942d3282b541ef0a872d --- /dev/null +++ b/flang/test/Lower/OpenMP/parallel-reduction-rename.f90 @@ -0,0 +1,36 @@ +! RUN: bbc -emit-hlfir -fopenmp -o - %s | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s | FileCheck %s + +module m1 + intrinsic max +end module m1 +program main + use m1, ren=>max + n=0 + !$omp parallel reduction(ren:n) + print *, "par" + !$omp end parallel +end program main + +! test that we understood that this should be a max reduction + +! CHECK-LABEL: omp.declare_reduction @max_i32 : i32 init { +! CHECK: ^bb0(%[[VAL_0:.*]]: i32): +! CHECK: %[[VAL_1:.*]] = arith.constant -2147483648 : i32 +! CHECK: omp.yield(%[[VAL_1]] : i32) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32): +! CHECK: %[[VAL_2:.*]] = arith.maxsi %[[VAL_0]], %[[VAL_1]] : i32 +! CHECK: omp.yield(%[[VAL_2]] : i32) +! CHECK: } + +! 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<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_1]]#0 : i32, !fir.ref<i32> +! CHECK: omp.parallel reduction(@max_i32 %[[VAL_1]]#0 -> %[[VAL_3:.*]] : !fir.ref<i32>) { +! ... +! CHECK: omp.terminator + diff --git a/flang/test/Lower/OpenMP/parallel-reduction.f90 b/flang/test/Lower/OpenMP/parallel-reduction.f90 index a07d118b0ba19a3f3d39394cc74c2f5613304c83..612549fb32de501f2fb4855eb2ad0796d8ea5330 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction.f90 @@ -1,7 +1,7 @@ ! RUN: bbc -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s ! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s -!CHECK: omp.reduction.declare @[[REDUCTION_DECLARE:[_a-z0-9]+]] : i32 init { +!CHECK: omp.declare_reduction @[[REDUCTION_DECLARE:[_a-z0-9]+]] : i32 init { !CHECK: ^bb0(%{{.*}}: i32): !CHECK: %[[I0:[_a-z0-9]+]] = arith.constant 0 : i32 !CHECK: omp.yield(%[[I0]] : i32) diff --git a/flang/test/Lower/OpenMP/parallel-sections.f90 b/flang/test/Lower/OpenMP/parallel-sections.f90 index 77139e40ed8c0e3effd53756429685a35486aab0..2f78dd4562b0aede6a19f302d81a1ca357ea3e0e 100644 --- a/flang/test/Lower/OpenMP/parallel-sections.f90 +++ b/flang/test/Lower/OpenMP/parallel-sections.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + !RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s !=============================================================================== @@ -37,12 +39,12 @@ end subroutine omp_parallel_sections subroutine omp_parallel_sections_allocate(x, y) use omp_lib integer, intent(inout) :: x, y - !CHECK: %[[allocator_1:.*]] = arith.constant 1 : i32 - !CHECK: %[[allocator_2:.*]] = arith.constant 1 : i32 + !CHECK: %[[allocator_1:.*]] = arith.constant 4 : i64 + !CHECK: %[[allocator_2:.*]] = arith.constant 4 : i64 !CHECK: omp.parallel allocate( - !CHECK: %[[allocator_2]] : i32 -> %{{.*}} : !fir.ref<i32>) { + !CHECK: %[[allocator_2]] : i64 -> %{{.*}} : !fir.ref<i32>) { !CHECK: omp.sections allocate( - !CHECK: %[[allocator_1]] : i32 -> %{{.*}} : !fir.ref<i32>) { + !CHECK: %[[allocator_1]] : i64 -> %{{.*}} : !fir.ref<i32>) { !$omp parallel sections allocate(omp_high_bw_mem_alloc: x) !CHECK: omp.section { !$omp section diff --git a/flang/test/Lower/OpenMP/parallel-wsloop-reduction-byref.f90 b/flang/test/Lower/OpenMP/parallel-wsloop-reduction-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..66c80c31917ba874e4620117c7770db7c0887d73 --- /dev/null +++ b/flang/test/Lower/OpenMP/parallel-wsloop-reduction-byref.f90 @@ -0,0 +1,16 @@ +! Check that for parallel do, reduction is only processed for the loop + +! RUN: bbc -fopenmp --force-byref-reduction -emit-hlfir %s -o - | FileCheck %s +! RUN: flang-new -fc1 -fopenmp -mmlir --force-byref-reduction -emit-hlfir %s -o - | FileCheck %s + +! CHECK: omp.parallel { +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 +subroutine sb + integer :: x + x = 0 + !$omp parallel do reduction(+:x) + do i=1,100 + x = x + 1 + end do + !$omp end parallel do +end subroutine diff --git a/flang/test/Lower/OpenMP/parallel-wsloop-reduction.f90 b/flang/test/Lower/OpenMP/parallel-wsloop-reduction.f90 index c13ec2bc4aec82ad98c343b5bf02c6dffe3aad18..fdedbb061607611ffd98df7dbafac0f9155f26a9 100644 --- a/flang/test/Lower/OpenMP/parallel-wsloop-reduction.f90 +++ b/flang/test/Lower/OpenMP/parallel-wsloop-reduction.f90 @@ -4,7 +4,7 @@ ! RUN: flang-new -fc1 -fopenmp -emit-hlfir %s -o - | FileCheck %s ! CHECK: omp.parallel { -! CHECK: omp.wsloop reduction(@add_reduction_i_32 +! CHECK: omp.wsloop reduction(@add_reduction_i32 subroutine sb integer :: x x = 0 diff --git a/flang/test/Lower/OpenMP/parallel.f90 b/flang/test/Lower/OpenMP/parallel.f90 index 0e43244994cfdb291f2f9dc142b12f2fa6ffd7f2..6c062b706ed4314f47148357d41d3a6aadc1ffc3 100644 --- a/flang/test/Lower/OpenMP/parallel.f90 +++ b/flang/test/Lower/OpenMP/parallel.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + !RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s !CHECK-LABEL: func @_QPparallel_simple @@ -152,7 +154,7 @@ subroutine parallel_allocate() use omp_lib integer :: x !CHECK: omp.parallel allocate( - !CHECK: %{{.+}} : i32 -> %{{.+}} : !fir.ref<i32> + !CHECK: %{{.+}} : i64 -> %{{.+}} : !fir.ref<i32> !CHECK: ) { !$omp parallel allocate(omp_high_bw_mem_alloc: x) private(x) !CHECK: arith.addi @@ -193,7 +195,7 @@ subroutine parallel_multiple_clauses(alpha, num_threads) !$omp end parallel !CHECK: omp.parallel if({{.*}} : i1) num_threads({{.*}} : i32) allocate( - !CHECK: %{{.+}} : i32 -> %{{.+}} : !fir.ref<i32> + !CHECK: %{{.+}} : i64 -> %{{.+}} : !fir.ref<i32> !CHECK: ) { !$omp parallel num_threads(num_threads) if(alpha .le. 0) allocate(omp_high_bw_mem_alloc: alpha) private(alpha) !CHECK: fir.call diff --git a/flang/test/Lower/OpenMP/sections.f90 b/flang/test/Lower/OpenMP/sections.f90 index 6bad688058d28259dd15a37aca537384e57f93c4..018848e635733b8218cd0d502cee383e283957d4 100644 --- a/flang/test/Lower/OpenMP/sections.f90 +++ b/flang/test/Lower/OpenMP/sections.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! This test checks the lowering of OpenMP sections construct with several clauses present ! RUN: %flang_fc1 -flang-experimental-hlfir -emit-hlfir -fopenmp %s -o - | FileCheck %s @@ -7,8 +9,8 @@ !CHECK: %[[COUNT:.*]] = fir.address_of(@_QFEcount) : !fir.ref<i32> !CHECK: %[[COUNT_DECL:.*]]:2 = hlfir.declare %[[COUNT]] {uniq_name = "_QFEcount"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) !CHECK: %[[ETA:.*]] = fir.alloca f32 {bindc_name = "eta", uniq_name = "_QFEeta"} -!CHECK: %[[CONST_1:.*]] = arith.constant 1 : i32 -!CHECK: omp.sections allocate(%[[CONST_1]] : i32 -> %[[COUNT_DECL]]#1 : !fir.ref<i32>) { +!CHECK: %[[CONST_1:.*]] = arith.constant 4 : i64 +!CHECK: omp.sections allocate(%[[CONST_1]] : i64 -> %[[COUNT_DECL]]#1 : !fir.ref<i32>) { !CHECK: omp.section { !CHECK: %[[PRIVATE_ETA:.*]] = fir.alloca f32 {bindc_name = "eta", pinned, uniq_name = "_QFEeta"} !CHECK: %[[PRIVATE_ETA_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_ETA]] {uniq_name = "_QFEeta"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) diff --git a/flang/test/Lower/OpenMP/single.f90 b/flang/test/Lower/OpenMP/single.f90 index ffc41af84e3c2175a8e87a87c3b19164b358c324..10d537a0e18b2387765df7266b17b895802adb5c 100644 --- a/flang/test/Lower/OpenMP/single.f90 +++ b/flang/test/Lower/OpenMP/single.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + !RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s !RUN: bbc -emit-hlfir -fopenmp %s -o - | FileCheck %s @@ -57,7 +59,7 @@ subroutine single_allocate() integer :: x !CHECK: omp.parallel { !$omp parallel - !CHECK: omp.single allocate(%{{.+}} : i32 -> %{{.+}} : !fir.ref<i32>) { + !CHECK: omp.single allocate(%{{.+}} : i64 -> %{{.+}} : !fir.ref<i32>) { !$omp single allocate(omp_high_bw_mem_alloc: x) private(x) !CHECK: arith.addi x = x + 12 diff --git a/flang/test/Lower/OpenMP/target.f90 b/flang/test/Lower/OpenMP/target.f90 index 030533e1a045531c0039befb5771c5052cec58cf..6f72b5a34d069a1bb8951395afe04cbcbc82caa2 100644 --- a/flang/test/Lower/OpenMP/target.f90 +++ b/flang/test/Lower/OpenMP/target.f90 @@ -7,8 +7,8 @@ !CHECK-LABEL: func.func @_QPomp_target_enter_simple() { subroutine omp_target_enter_simple integer :: a(1024) - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target_enter_data map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target enter data map(to: a) return @@ -27,8 +27,8 @@ subroutine omp_target_enter_depend !$omp task depend(out: a) call foo(a) !$omp end task - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target_enter_data map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) depend(taskdependin -> %[[A]]#1 : !fir.ref<!fir.array<1024xi32>>) !$omp target enter data map(to: a) depend(in: a) return @@ -44,14 +44,14 @@ subroutine omp_target_enter_mt integer :: b(1024) integer :: c(1024) integer :: d(1024) - !CHECK: %[[BOUNDS_0:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_0:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS_0]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} - !CHECK: %[[BOUNDS_1:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_1:.*]] = omp.map_info var_ptr(%{{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS_1]]) -> !fir.ref<!fir.array<1024xi32>> {name = "b"} - !CHECK: %[[BOUNDS_2:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_2:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(always, exit_release_or_enter_alloc) capture(ByRef) bounds(%[[BOUNDS_2]]) -> !fir.ref<!fir.array<1024xi32>> {name = "c"} - !CHECK: %[[BOUNDS_3:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_3:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS_3]]) -> !fir.ref<!fir.array<1024xi32>> {name = "d"} + !CHECK: %[[BOUNDS_0:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_0:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS_0]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS_1:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_1:.*]] = omp.map.info var_ptr(%{{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS_1]]) -> !fir.ref<!fir.array<1024xi32>> {name = "b"} + !CHECK: %[[BOUNDS_2:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_2:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(always, exit_release_or_enter_alloc) capture(ByRef) bounds(%[[BOUNDS_2]]) -> !fir.ref<!fir.array<1024xi32>> {name = "c"} + !CHECK: %[[BOUNDS_3:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_3:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS_3]]) -> !fir.ref<!fir.array<1024xi32>> {name = "d"} !CHECK: omp.target_enter_data map_entries(%[[MAP_0]], %[[MAP_1]], %[[MAP_2]], %[[MAP_3]] : !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>) !$omp target enter data map(to: a, b) map(always, alloc: c) map(to: d) end subroutine omp_target_enter_mt @@ -63,8 +63,8 @@ end subroutine omp_target_enter_mt !CHECK-LABEL: func.func @_QPomp_target_enter_nowait() { subroutine omp_target_enter_nowait integer :: a(1024) - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target_enter_data nowait map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target enter data map(to: a) nowait end subroutine omp_target_enter_nowait @@ -81,8 +81,8 @@ subroutine omp_target_enter_if !CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_1:.*]] : !fir.ref<i32> !CHECK: %[[VAL_4:.*]] = arith.constant 10 : i32 !CHECK: %[[VAL_5:.*]] = arith.cmpi slt, %[[VAL_3]], %[[VAL_4]] : i32 - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target_enter_data if(%[[VAL_5]] : i1) map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target enter data if(i<10) map(to: a) end subroutine omp_target_enter_if @@ -95,8 +95,8 @@ end subroutine omp_target_enter_if subroutine omp_target_enter_device integer :: a(1024) !CHECK: %[[VAL_1:.*]] = arith.constant 2 : i32 - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target_enter_data device(%[[VAL_1]] : i32) map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target enter data map(to: a) device(2) end subroutine omp_target_enter_device @@ -108,8 +108,8 @@ end subroutine omp_target_enter_device !CHECK-LABEL: func.func @_QPomp_target_exit_simple() { subroutine omp_target_exit_simple integer :: a(1024) - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target_exit_data map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target exit data map(from: a) end subroutine omp_target_exit_simple @@ -125,16 +125,16 @@ subroutine omp_target_exit_mt integer :: c(1024) integer :: d(1024) integer :: e(1024) - !CHECK: %[[BOUNDS_0:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_0:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS_0]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} - !CHECK: %[[BOUNDS_1:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_1:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS_1]]) -> !fir.ref<!fir.array<1024xi32>> {name = "b"} - !CHECK: %[[BOUNDS_2:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_2:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%[[BOUNDS_2]]) -> !fir.ref<!fir.array<1024xi32>> {name = "c"} - !CHECK: %[[BOUNDS_3:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_3:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(always, delete) capture(ByRef) bounds(%[[BOUNDS_3]]) -> !fir.ref<!fir.array<1024xi32>> {name = "d"} - !CHECK: %[[BOUNDS_4:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_4:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS_4]]) -> !fir.ref<!fir.array<1024xi32>> {name = "e"} + !CHECK: %[[BOUNDS_0:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_0:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS_0]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS_1:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_1:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS_1]]) -> !fir.ref<!fir.array<1024xi32>> {name = "b"} + !CHECK: %[[BOUNDS_2:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_2:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%[[BOUNDS_2]]) -> !fir.ref<!fir.array<1024xi32>> {name = "c"} + !CHECK: %[[BOUNDS_3:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_3:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(always, delete) capture(ByRef) bounds(%[[BOUNDS_3]]) -> !fir.ref<!fir.array<1024xi32>> {name = "d"} + !CHECK: %[[BOUNDS_4:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_4:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS_4]]) -> !fir.ref<!fir.array<1024xi32>> {name = "e"} !CHECK: omp.target_exit_data map_entries(%[[MAP_0]], %[[MAP_1]], %[[MAP_2]], %[[MAP_3]], %[[MAP_4]] : !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>) !$omp target exit data map(from: a,b) map(release: c) map(always, delete: d) map(from: e) end subroutine omp_target_exit_mt @@ -148,8 +148,8 @@ subroutine omp_target_exit_device integer :: a(1024) integer :: d !CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_1:.*]] : !fir.ref<i32> - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target_exit_data device(%[[VAL_2]] : i32) map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target exit data map(from: a) device(d) end subroutine omp_target_exit_device @@ -166,8 +166,8 @@ subroutine omp_target_exit_depend !$omp task depend(out: a) call foo(a) !$omp end task - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target_exit_data map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) depend(taskdependout -> %[[A]]#1 : !fir.ref<!fir.array<1024xi32>>) !$omp target exit data map(from: a) depend(out: a) end subroutine omp_target_exit_depend @@ -187,9 +187,9 @@ subroutine omp_target_update_depend call foo(a) !$omp end task - !CHECK: %[[BOUNDS:.*]] = omp.bounds - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr(%[[A]]#0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} - !CHECK: omp.target_update_data motion_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) depend(taskdependin -> %[[A]]#1 : !fir.ref<!fir.array<1024xi32>>) + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[A]]#0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(to) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: omp.target_update motion_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) depend(taskdependin -> %[[A]]#1 : !fir.ref<!fir.array<1024xi32>>) !$omp target update to(a) depend(in:a) end subroutine omp_target_update_depend @@ -202,13 +202,13 @@ subroutine omp_target_update_to integer :: a(1024) !CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) - !CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds + !CHECK-DAG: %[[BOUNDS:.*]] = omp.map.bounds - !CHECK: %[[TO_MAP:.*]] = omp.map_info var_ptr(%[[A_DECL]]#0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) + !CHECK: %[[TO_MAP:.*]] = omp.map.info var_ptr(%[[A_DECL]]#0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) !CHECK-SAME: map_clauses(to) capture(ByRef) !CHECK-SAME: bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} - !CHECK: omp.target_update_data motion_entries(%[[TO_MAP]] : !fir.ref<!fir.array<1024xi32>>) + !CHECK: omp.target_update motion_entries(%[[TO_MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target update to(a) end subroutine omp_target_update_to @@ -221,13 +221,13 @@ subroutine omp_target_update_from integer :: a(1024) !CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) - !CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds + !CHECK-DAG: %[[BOUNDS:.*]] = omp.map.bounds - !CHECK: %[[FROM_MAP:.*]] = omp.map_info var_ptr(%[[A_DECL]]#0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) + !CHECK: %[[FROM_MAP:.*]] = omp.map.info var_ptr(%[[A_DECL]]#0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) !CHECK-SAME: map_clauses(from) capture(ByRef) !CHECK-SAME: bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} - !CHECK: omp.target_update_data motion_entries(%[[FROM_MAP]] : !fir.ref<!fir.array<1024xi32>>) + !CHECK: omp.target_update motion_entries(%[[FROM_MAP]] : !fir.ref<!fir.array<1024xi32>>) !$omp target update from(a) end subroutine omp_target_update_from @@ -241,10 +241,10 @@ subroutine omp_target_update_if logical :: i !CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) - !CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds + !CHECK-DAG: %[[BOUNDS:.*]] = omp.map.bounds !CHECK-DAG: %[[COND:.*]] = fir.convert %{{.*}} : (!fir.logical<4>) -> i1 - !CHECK: omp.target_update_data if(%[[COND]] : i1) motion_entries + !CHECK: omp.target_update if(%[[COND]] : i1) motion_entries !$omp target update from(a) if(i) end subroutine omp_target_update_if @@ -258,10 +258,10 @@ subroutine omp_target_update_device logical :: i !CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) - !CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds + !CHECK-DAG: %[[BOUNDS:.*]] = omp.map.bounds !CHECK-DAG: %[[DEVICE:.*]] = arith.constant 1 : i32 - !CHECK: omp.target_update_data device(%[[DEVICE]] : i32) motion_entries + !CHECK: omp.target_update device(%[[DEVICE]] : i32) motion_entries !$omp target update from(a) device(1) end subroutine omp_target_update_device @@ -275,9 +275,9 @@ subroutine omp_target_update_nowait logical :: i !CHECK-DAG: %[[A_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) - !CHECK-DAG: %[[BOUNDS:.*]] = omp.bounds + !CHECK-DAG: %[[BOUNDS:.*]] = omp.map.bounds - !CHECK: omp.target_update_data nowait motion_entries + !CHECK: omp.target_update nowait motion_entries !$omp target update from(a) nowait end subroutine omp_target_update_nowait @@ -290,8 +290,8 @@ subroutine omp_target_data !CHECK: %[[VAL_0:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "a", uniq_name = "_QFomp_target_dataEa"} !CHECK: %[[A_DECL:.*]]:2 = hlfir.declare %[[VAL_0]](%{{.*}}) {uniq_name = "_QFomp_target_dataEa"} : (!fir.ref<!fir.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>) integer :: a(1024) - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr(%[[A_DECL]]#0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[A_DECL]]#0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target_data map_entries(%[[MAP]] : !fir.ref<!fir.array<1024xi32>>) { !$omp target data map(tofrom: a) !CHECK: %[[C10:.*]] = arith.constant 10 : i32 @@ -312,15 +312,15 @@ subroutine omp_target_data_mt !CHECK: %[[VAR_A_DECL:.*]]:2 = hlfir.declare %[[VAR_A]](%{{.*}}) {uniq_name = "_QFomp_target_data_mtEa"} : (!fir.ref<!fir.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>) !CHECK: %[[VAR_B:.*]] = fir.alloca !fir.array<1024xi32> {bindc_name = "b", uniq_name = "_QFomp_target_data_mtEb"} !CHECK: %[[VAR_B_DECL:.*]]:2 = hlfir.declare %[[VAR_B]](%{{.*}}) {uniq_name = "_QFomp_target_data_mtEb"} : (!fir.ref<!fir.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>) - !CHECK: %[[BOUNDS_A:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_A:.*]] = omp.map_info var_ptr(%[[VAR_A_DECL]]#0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_A]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS_A:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAR_A_DECL]]#0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_A]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target_data map_entries(%[[MAP_A]] : !fir.ref<!fir.array<1024xi32>>) { !$omp target data map(a) !CHECK: omp.terminator !$omp end target data !CHECK: } - !CHECK: %[[BOUNDS_B:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP_B:.*]] = omp.map_info var_ptr(%[[VAR_B_DECL]]#0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(always, from) capture(ByRef) bounds(%[[BOUNDS_B]]) -> !fir.ref<!fir.array<1024xi32>> {name = "b"} + !CHECK: %[[BOUNDS_B:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP_B:.*]] = omp.map.info var_ptr(%[[VAR_B_DECL]]#0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(always, from) capture(ByRef) bounds(%[[BOUNDS_B]]) -> !fir.ref<!fir.array<1024xi32>> {name = "b"} !CHECK: omp.target_data map_entries(%[[MAP_B]] : !fir.ref<!fir.array<1024xi32>>) { !$omp target data map(always, from : b) !CHECK: omp.terminator @@ -336,8 +336,8 @@ end subroutine omp_target_data_mt subroutine omp_target !CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "_QFomp_targetEa"} : (!fir.ref<!fir.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>) integer :: a(1024) - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr(%[[VAL_1]]#0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound({{.*}}) upper_bound({{.*}}) extent({{.*}}) stride({{.*}}) start_idx({{.*}}) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[VAL_1]]#0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target map_entries(%[[MAP]] -> %[[ARG_0:.*]] : !fir.ref<!fir.array<1024xi32>>) { !CHECK: ^bb0(%[[ARG_0]]: !fir.ref<!fir.array<1024xi32>>): !$omp target map(tofrom: a) @@ -370,8 +370,8 @@ subroutine omp_target_depend !CHECK: %[[STRIDE_A:.*]] = arith.constant 1 : index !CHECK: %[[LBOUND_A:.*]] = arith.constant 0 : index !CHECK: %[[UBOUND_A:.*]] = arith.subi %c1024, %c1 : index - !CHECK: %[[BOUNDS_A:.*]] = omp.bounds lower_bound(%[[LBOUND_A]] : index) upper_bound(%[[UBOUND_A]] : index) extent(%[[EXTENT_A]] : index) stride(%[[STRIDE_A]] : index) start_idx(%[[STRIDE_A]] : index) - !CHECK: %[[MAP_A:.*]] = omp.map_info var_ptr(%[[A]]#0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_A]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS_A:.*]] = omp.map.bounds lower_bound(%[[LBOUND_A]] : index) upper_bound(%[[UBOUND_A]] : index) extent(%[[EXTENT_A]] : index) stride(%[[STRIDE_A]] : index) start_idx(%[[STRIDE_A]] : index) + !CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[A]]#0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS_A]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target map_entries(%[[MAP_A]] -> %[[BB0_ARG:.*]] : !fir.ref<!fir.array<1024xi32>>) depend(taskdependin -> %[[A]]#1 : !fir.ref<!fir.array<1024xi32>>) { !$omp target map(tofrom: a) depend(in: a) a(1) = 10 @@ -391,7 +391,7 @@ subroutine omp_target_implicit !CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_0]] : (index) -> !fir.shape<1> !CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_2]]) {uniq_name = "_QFomp_target_implicitEa"} : (!fir.ref<!fir.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>) integer :: a(1024) - !CHECK: %[[VAL_4:.*]] = omp.map_info var_ptr(%[[VAL_3]]#1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds(%{{.*}}) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[VAL_4:.*]] = omp.map.info var_ptr(%[[VAL_3]]#1 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds(%{{.*}}) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target map_entries(%[[VAL_4]] -> %[[VAL_6:.*]] : !fir.ref<!fir.array<1024xi32>>) { !CHECK: ^bb0(%[[VAL_6]]: !fir.ref<!fir.array<1024xi32>>): !$omp target @@ -459,9 +459,9 @@ subroutine omp_target_implicit_bounds(n) integer :: n integer :: a(n) - !CHECK: %[[VAL_14:.*]] = omp.bounds lower_bound(%c0{{.*}} : index) upper_bound(%[[UB]] : index) extent(%[[DIMS0]]#1 : index) stride(%[[DIMS0]]#2 : index) start_idx(%c1{{.*}} : index) {stride_in_bytes = true} - !CHECK: %[[VAL_15:.*]] = omp.map_info var_ptr(%[[VAL_10]]#1 : !fir.ref<!fir.array<?xi32>>, !fir.array<?xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds(%[[VAL_14]]) -> !fir.ref<!fir.array<?xi32>> {name = "a"} - !CHECK: %[[VAL_16:.*]] = omp.map_info var_ptr(%[[VAL_COPY]] : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = ""} + !CHECK: %[[VAL_14:.*]] = omp.map.bounds lower_bound(%c0{{.*}} : index) upper_bound(%[[UB]] : index) extent(%[[DIMS0]]#1 : index) stride(%[[DIMS0]]#2 : index) start_idx(%c1{{.*}} : index) {stride_in_bytes = true} + !CHECK: %[[VAL_15:.*]] = omp.map.info var_ptr(%[[VAL_10]]#1 : !fir.ref<!fir.array<?xi32>>, !fir.array<?xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds(%[[VAL_14]]) -> !fir.ref<!fir.array<?xi32>> {name = "a"} + !CHECK: %[[VAL_16:.*]] = omp.map.info var_ptr(%[[VAL_COPY]] : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = ""} !CHECK: omp.target map_entries(%[[VAL_15]] -> %[[VAL_17:.*]], %[[VAL_16]] -> %[[VAL_18:.*]] : !fir.ref<!fir.array<?xi32>>, !fir.ref<i32>) { !CHECK: ^bb0(%[[VAL_17]]: !fir.ref<!fir.array<?xi32>>, %[[VAL_18]]: !fir.ref<i32>): !$omp target @@ -491,7 +491,7 @@ end subroutine omp_target_implicit_bounds subroutine omp_target_thread_limit integer :: a !CHECK: %[[VAL_1:.*]] = arith.constant 64 : i32 - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(tofrom) capture(ByRef) -> !fir.ref<i32> {name = "a"} + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(tofrom) capture(ByRef) -> !fir.ref<i32> {name = "a"} !CHECK: omp.target thread_limit(%[[VAL_1]] : i32) map_entries(%[[MAP]] -> %{{.*}} : !fir.ref<i32>) { !CHECK: ^bb0(%{{.*}}: !fir.ref<i32>): !$omp target map(tofrom: a) thread_limit(64) @@ -510,7 +510,7 @@ subroutine omp_target_device_ptr use iso_c_binding, only : c_ptr, c_loc type(c_ptr) :: a integer, target :: b - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}}) map_clauses(tofrom) capture(ByRef) -> {{.*}} {name = "a"} + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(tofrom) capture(ByRef) -> {{.*}} {name = "a"} !CHECK: omp.target_data map_entries(%[[MAP]]{{.*}} !$omp target data map(tofrom: a) use_device_ptr(a) !CHECK: ^bb0(%[[VAL_1:.*]]: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>): @@ -530,8 +530,8 @@ end subroutine omp_target_device_ptr integer, pointer :: a !CHECK: %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "a", uniq_name = "_QFomp_target_device_addrEa"} !CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %0 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFomp_target_device_addrEa"} : (!fir.ref<!fir.box<!fir.ptr<i32>>>) -> (!fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.ref<!fir.box<!fir.ptr<i32>>>) - !CHECK: %[[MAP_MEMBERS:.*]] = omp.map_info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, i32) var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<i32>>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""} - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBERS]] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "a"} + !CHECK: %[[MAP_MEMBERS:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, i32) var_ptr_ptr({{.*}} : !fir.llvm_ptr<!fir.ref<i32>>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""} + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}} : !fir.ref<!fir.box<!fir.ptr<i32>>>, !fir.box<!fir.ptr<i32>>) map_clauses(tofrom) capture(ByRef) members(%[[MAP_MEMBERS]] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.ptr<i32>>> {name = "a"} !CHECK: omp.target_data map_entries(%[[MAP_MEMBERS]], %[[MAP]] : {{.*}}) use_device_addr(%[[VAL_0_DECL]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>) { !$omp target data map(tofrom: a) use_device_addr(a) !CHECK: ^bb0(%[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.ptr<i32>>>): @@ -585,8 +585,8 @@ subroutine omp_target_parallel_do !CHECK: %[[C1:.*]] = arith.constant 1 : index !CHECK: %[[C0:.*]] = arith.constant 0 : index !CHECK: %[[SUB:.*]] = arith.subi %[[C1024]], %[[C1]] : index - !CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound(%[[C0]] : index) upper_bound(%[[SUB]] : index) extent(%[[C1024]] : index) stride(%[[C1]] : index) start_idx(%[[C1]] : index) - !CHECK: %[[MAP:.*]] = omp.map_info var_ptr(%[[VAL_0_DECL]]#0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} + !CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%[[C0]] : index) upper_bound(%[[SUB]] : index) extent(%[[C1024]] : index) stride(%[[C1]] : index) start_idx(%[[C1]] : index) + !CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%[[VAL_0_DECL]]#0 : !fir.ref<!fir.array<1024xi32>>, !fir.array<1024xi32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<1024xi32>> {name = "a"} !CHECK: omp.target map_entries(%[[MAP]] -> %[[ARG_0:.*]], %{{.*}} -> %{{.*}} : !fir.ref<!fir.array<1024xi32>>, !fir.ref<i32>) { !CHECK: ^bb0(%[[ARG_0]]: !fir.ref<!fir.array<1024xi32>>, %{{.*}}: !fir.ref<i32>): !CHECK: %[[VAL_0_DECL:.*]]:2 = hlfir.declare %[[ARG_0]](%{{.*}}) {uniq_name = "_QFomp_target_parallel_doEa"} : (!fir.ref<!fir.array<1024xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<1024xi32>>, !fir.ref<!fir.array<1024xi32>>) @@ -623,8 +623,8 @@ subroutine target_unstructured integer :: i = 1 !CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFtarget_unstructuredEj"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) integer :: j = 11 - !CHECK: %[[VAL_4:.*]] = omp.map_info var_ptr(%[[VAL_1]]#1 : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = "i"} - !CHECK: %[[VAL_5:.*]] = omp.map_info var_ptr(%[[VAL_3]]#1 : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = "j"} + !CHECK: %[[VAL_4:.*]] = omp.map.info var_ptr(%[[VAL_1]]#1 : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = "i"} + !CHECK: %[[VAL_5:.*]] = omp.map.info var_ptr(%[[VAL_3]]#1 : !fir.ref<i32>, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !fir.ref<i32> {name = "j"} !CHECK: omp.target map_entries(%[[VAL_4]] -> %[[VAL_6:.*]], %[[VAL_5]] -> %[[VAL_7:.*]] : !fir.ref<i32>, !fir.ref<i32>) { !CHECK: ^bb0(%[[VAL_6]]: !fir.ref<i32>, %[[VAL_7]]: !fir.ref<i32>): !$omp target diff --git a/flang/test/Lower/OpenMP/task.f90 b/flang/test/Lower/OpenMP/task.f90 index 7d7a79af3185f52315f42f1d07b335a32de842f9..f3718b8829ccaf7db8642e436752f015dac82faf 100644 --- a/flang/test/Lower/OpenMP/task.f90 +++ b/flang/test/Lower/OpenMP/task.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + !RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s !CHECK-LABEL: func @_QPomp_task_simple() { @@ -63,7 +65,7 @@ end subroutine omp_task_priority subroutine task_allocate() use omp_lib integer :: x - !CHECK: omp.task allocate(%{{.+}} : i32 -> %{{.+}} : !fir.ref<i32>) { + !CHECK: omp.task allocate(%{{.+}} : i64 -> %{{.+}} : !fir.ref<i32>) { !$omp task allocate(omp_high_bw_mem_alloc: x) private(x) !CHECK: arith.addi x = x + 12 @@ -225,7 +227,7 @@ subroutine task_multiple_clauses() integer :: x, y, z logical :: buzz - !CHECK: omp.task if(%{{.+}}) final(%{{.+}}) priority(%{{.+}}) allocate(%{{.+}} : i32 -> %{{.+}} : !fir.ref<i32>) { + !CHECK: omp.task if(%{{.+}}) final(%{{.+}}) priority(%{{.+}}) allocate(%{{.+}} : i64 -> %{{.+}} : !fir.ref<i32>) { !$omp task if(buzz) final(buzz) priority(z) allocate(omp_high_bw_mem_alloc: x) private(x) firstprivate(y) !CHECK: %[[X_PRIV_ALLOCA:.+]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFtask_multiple_clausesEx"} diff --git a/flang/test/Lower/OpenMP/taskgroup.f90 b/flang/test/Lower/OpenMP/taskgroup.f90 index 85dc253b59d6593d1ede75bc52be125870c4fc1b..76458f1f1127f3439f7091c8a6bd1e39934db014 100644 --- a/flang/test/Lower/OpenMP/taskgroup.f90 +++ b/flang/test/Lower/OpenMP/taskgroup.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + !RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s !CHECK-LABEL: @_QPomp_taskgroup @@ -6,9 +8,9 @@ use omp_lib integer :: allocated_x !CHECK: %[[ALLOC_X_REF:.*]] = fir.alloca i32 {bindc_name = "allocated_x", uniq_name = "_QFomp_taskgroupEallocated_x"} !CHECK-NEXT: %[[ALLOC_X_DECL:.*]]:2 = hlfir.declare %[[ALLOC_X_REF]] {uniq_name = "_QFomp_taskgroupEallocated_x"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -!CHECK: %[[C1:.*]] = arith.constant 1 : i32 +!CHECK: %[[C4:.*]] = arith.constant 4 : i64 -!CHECK: omp.taskgroup allocate(%[[C1]] : i32 -> %[[ALLOC_X_DECL]]#1 : !fir.ref<i32>) +!CHECK: omp.taskgroup allocate(%[[C4]] : i64 -> %[[ALLOC_X_DECL]]#1 : !fir.ref<i32>) !$omp taskgroup allocate(omp_high_bw_mem_alloc: allocated_x) !$omp task !CHECK: fir.call @_QPwork() {{.*}}: () -> () diff --git a/flang/test/Lower/OpenMP/teams.f90 b/flang/test/Lower/OpenMP/teams.f90 index 2620d7752a4ed3c0c10240c273f8cb30c22a11ba..f122a578a6e160e1c790468889ef5e1fc65dbc27 100644 --- a/flang/test/Lower/OpenMP/teams.f90 +++ b/flang/test/Lower/OpenMP/teams.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s ! CHECK-LABEL: func @_QPteams_simple @@ -105,7 +107,7 @@ subroutine teams_allocate() use omp_lib integer :: x ! CHECK: omp.teams - ! CHECK-SAME: allocate(%{{.+}} : i32 -> %{{.+}} : !fir.ref<i32>) + ! CHECK-SAME: allocate(%{{.+}} : i64 -> %{{.+}} : !fir.ref<i32>) !$omp teams allocate(omp_high_bw_mem_alloc: x) private(x) ! CHECK: arith.addi x = x + 12 diff --git a/flang/test/Lower/OpenMP/threadprivate-default-clause.f90 b/flang/test/Lower/OpenMP/threadprivate-default-clause.f90 index be07aeca2d5c32a4b8adb8aba5ff1e4a7a94bec6..10beaf6fefde7f76e5db3f383bc521a98f5669f8 100644 --- a/flang/test/Lower/OpenMP/threadprivate-default-clause.f90 +++ b/flang/test/Lower/OpenMP/threadprivate-default-clause.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! Simple test for lowering of OpenMP Threadprivate Directive with HLFIR. !RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s diff --git a/flang/test/Lower/OpenMP/use-device-ptr-to-use-device-addr.f90 b/flang/test/Lower/OpenMP/use-device-ptr-to-use-device-addr.f90 new file mode 100644 index 0000000000000000000000000000000000000000..33b5971656010aa3df3ffad3ffce6ed33e766794 --- /dev/null +++ b/flang/test/Lower/OpenMP/use-device-ptr-to-use-device-addr.f90 @@ -0,0 +1,72 @@ +!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s +!RUN: bbc -emit-hlfir -fopenmp %s -o - | FileCheck %s + +! This tests primary goal is to check the promotion of +! non-CPTR arguments from use_device_ptr to +! use_device_addr works, without breaking any +! functionality + +!CHECK: func.func @{{.*}}only_use_device_ptr() +!CHECK: omp.target_data use_device_ptr(%{{.*}} : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) use_device_addr(%{{.*}}, %{{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) { +!CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>): +subroutine only_use_device_ptr + use iso_c_binding + integer, pointer, dimension(:) :: array + real, pointer :: pa(:) + type(c_ptr) :: cptr + + !$omp target data use_device_ptr(pa, cptr, array) + !$omp end target data +end subroutine + +!CHECK: func.func @{{.*}}mix_use_device_ptr_and_addr() +!CHECK: omp.target_data use_device_ptr({{.*}} : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) use_device_addr(%{{.*}}, %{{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) { +!CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>): +subroutine mix_use_device_ptr_and_addr + use iso_c_binding + integer, pointer, dimension(:) :: array + real, pointer :: pa(:) + type(c_ptr) :: cptr + + !$omp target data use_device_ptr(pa, cptr) use_device_addr(array) + !$omp end target data +end subroutine + +!CHECK: func.func @{{.*}}only_use_device_addr() +!CHECK: omp.target_data use_device_addr(%{{.*}}, %{{.*}}, %{{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) { +!CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, %{{.*}}: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>): +subroutine only_use_device_addr + use iso_c_binding + integer, pointer, dimension(:) :: array + real, pointer :: pa(:) + type(c_ptr) :: cptr + + !$omp target data use_device_addr(pa, cptr, array) + !$omp end target data +end subroutine + +!CHECK: func.func @{{.*}}mix_use_device_ptr_and_addr_and_map() +!CHECK: omp.target_data map_entries(%{{.*}}, %{{.*}} : !fir.ref<i32>, !fir.ref<i32>) use_device_ptr(%{{.*}} : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) use_device_addr(%{{.*}}, %{{.*}} : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) { +!CHECK: ^bb0(%{{.*}}: !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>, %{{.*}}: !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>): +subroutine mix_use_device_ptr_and_addr_and_map + use iso_c_binding + integer :: i, j + integer, pointer, dimension(:) :: array + real, pointer :: pa(:) + type(c_ptr) :: cptr + + !$omp target data use_device_ptr(pa, cptr) use_device_addr(array) map(tofrom: i, j) + !$omp end target data +end subroutine + +!CHECK: func.func @{{.*}}only_use_map() +!CHECK: omp.target_data map_entries(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : !fir.llvm_ptr<!fir.ref<!fir.array<?xf32>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>, !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>, !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?xi32>>>>) { +subroutine only_use_map + use iso_c_binding + integer, pointer, dimension(:) :: array + real, pointer :: pa(:) + type(c_ptr) :: cptr + + !$omp target data map(pa, cptr, array) + !$omp end target data +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-add-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-add-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..e63db33bbe2505530e8539f895cc74cc0f5e325b --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-add-byref.f90 @@ -0,0 +1,433 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_f64 : !fir.ref<f64> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<f64>): +! CHECK: %[[C0_1:.*]] = arith.constant 0.000000e+00 : f64 +! CHECK: %[[REF:.*]] = fir.alloca f64 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref<f64> +! CHECK: omp.yield(%[[REF]] : !fir.ref<f64>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<f64>, %[[ARG1:.*]]: !fir.ref<f64>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<f64> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<f64> +! CHECK: %[[RES:.*]] = arith.addf %[[LD0]], %[[LD1]] fastmath<contract> : f64 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<f64> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<f64>) +! CHECK: } + +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_i64 : !fir.ref<i64> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i64>): +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i64 +! CHECK: %[[REF:.*]] = fir.alloca i64 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref<i64> +! CHECK: omp.yield(%[[REF]] : !fir.ref<i64>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i64>, %[[ARG1:.*]]: !fir.ref<i64>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i64> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i64> +! CHECK: %[[RES:.*]] = arith.addi %[[LD0]], %[[LD1]] : i64 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i64> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<i64>) +! CHECK: } + +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_f32 : !fir.ref<f32> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<f32>): +! CHECK: %[[C0_1:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: %[[REF:.*]] = fir.alloca f32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref<f32> +! CHECK: omp.yield(%[[REF]] : !fir.ref<f32>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<f32>, %[[ARG1:.*]]: !fir.ref<f32>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<f32> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<f32> +! CHECK: %[[RES:.*]] = arith.addf %[[LD0]], %[[LD1]] fastmath<contract> : f32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<f32> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<f32>) +! CHECK: } + +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_i32 : !fir.ref<i32> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref<i32> +! CHECK: omp.yield(%[[REF]] : !fir.ref<i32>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> +! CHECK: %[[RES:.*]] = arith.addi %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i32> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<i32>) +! CHECK: } + +! CHECK-LABEL: func.func @_QPsimple_int_reduction() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_int_reductionEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsimple_int_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_int_reductionEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : i32, !fir.ref<i32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFsimple_int_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_15:.*]] = arith.addi %[[VAL_13]], %[[VAL_14]] : i32 +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_12]]#0 : i32, !fir.ref<i32> +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine simple_int_reduction + integer :: x + x = 0 + !$omp parallel + !$omp do reduction(+:x) + do i=1, 100 + x = x + i + end do + !$omp end do + !$omp end parallel +end subroutine + + +! CHECK-LABEL: func.func @_QPsimple_real_reduction() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_real_reductionEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsimple_real_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFsimple_real_reductionEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsimple_real_reductionEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_4:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : f32, !fir.ref<f32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFsimple_real_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<f32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_real_reductionEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<f32> +! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i32) -> f32 +! CHECK: %[[VAL_16:.*]] = arith.addf %[[VAL_13]], %[[VAL_15]] fastmath<contract> : f32 +! CHECK: hlfir.assign %[[VAL_16]] to %[[VAL_12]]#0 : f32, !fir.ref<f32> +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine simple_real_reduction + real :: x + x = 0.0 + !$omp parallel + !$omp do reduction(+:x) + do i=1, 100 + x = x + i + end do + !$omp end do + !$omp end parallel +end subroutine + + +! CHECK-LABEL: func.func @_QPsimple_int_reduction_switch_order() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_int_reduction_switch_orderEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsimple_int_reduction_switch_orderEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_int_reduction_switch_orderEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsimple_int_reduction_switch_orderEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : i32, !fir.ref<i32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFsimple_int_reduction_switch_orderEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reduction_switch_orderEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_15:.*]] = arith.addi %[[VAL_13]], %[[VAL_14]] : i32 +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_12]]#0 : i32, !fir.ref<i32> +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine simple_int_reduction_switch_order + integer :: x + x = 0 + !$omp parallel + !$omp do reduction(+:x) + do i=1, 100 + x = i + x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_real_reduction_switch_order() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_real_reduction_switch_orderEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsimple_real_reduction_switch_orderEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFsimple_real_reduction_switch_orderEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsimple_real_reduction_switch_orderEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_4:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : f32, !fir.ref<f32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFsimple_real_reduction_switch_orderEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<f32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_real_reduction_switch_orderEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (i32) -> f32 +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<f32> +! CHECK: %[[VAL_16:.*]] = arith.addf %[[VAL_14]], %[[VAL_15]] fastmath<contract> : f32 +! CHECK: hlfir.assign %[[VAL_16]] to %[[VAL_12]]#0 : f32, !fir.ref<f32> +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine simple_real_reduction_switch_order + real :: x + x = 0.0 + !$omp parallel + !$omp do reduction(+:x) + do i=1, 100 + x = i + x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_int_reductions_same_type() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_int_reductions_same_typeEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFmultiple_int_reductions_same_typeEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFmultiple_int_reductions_same_typeEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFmultiple_int_reductions_same_typeEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFmultiple_int_reductions_same_typeEy"} +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFmultiple_int_reductions_same_typeEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_6:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFmultiple_int_reductions_same_typeEz"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_int_reductions_same_typeEz"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_8:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_8]] to %[[VAL_3]]#0 : i32, !fir.ref<i32> +! CHECK: %[[VAL_9:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_5]]#0 : i32, !fir.ref<i32> +! CHECK: %[[VAL_10:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_7]]#0 : i32, !fir.ref<i32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_11:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QFmultiple_int_reductions_same_typeEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref<i32>, @add_reduction_byref_i32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref<i32>, @add_reduction_byref_i32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref<i32>) for (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { +! CHECK: fir.store %[[VAL_19]] to %[[VAL_12]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFmultiple_int_reductions_same_typeEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFmultiple_int_reductions_same_typeEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_22:.*]]:2 = hlfir.declare %[[VAL_18]] {uniq_name = "_QFmultiple_int_reductions_same_typeEz"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_23:.*]] = fir.load %[[VAL_20]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_25:.*]] = arith.addi %[[VAL_23]], %[[VAL_24]] : i32 +! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_20]]#0 : i32, !fir.ref<i32> +! CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_21]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_27:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_28:.*]] = arith.addi %[[VAL_26]], %[[VAL_27]] : i32 +! CHECK: hlfir.assign %[[VAL_28]] to %[[VAL_21]]#0 : i32, !fir.ref<i32> +! CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_22]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_31:.*]] = arith.addi %[[VAL_29]], %[[VAL_30]] : i32 +! CHECK: hlfir.assign %[[VAL_31]] to %[[VAL_22]]#0 : i32, !fir.ref<i32> +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine multiple_int_reductions_same_type + integer :: x,y,z + x = 0 + y = 0 + z = 0 + !$omp parallel + !$omp do reduction(+:x,y,z) + do i=1, 100 + x = x + i + y = y + i + z = z + i + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_real_reductions_same_type() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_real_reductions_same_typeEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFmultiple_real_reductions_same_typeEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFmultiple_real_reductions_same_typeEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFmultiple_real_reductions_same_typeEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_4:.*]] = fir.alloca f32 {bindc_name = "y", uniq_name = "_QFmultiple_real_reductions_same_typeEy"} +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFmultiple_real_reductions_same_typeEy"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_6:.*]] = fir.alloca f32 {bindc_name = "z", uniq_name = "_QFmultiple_real_reductions_same_typeEz"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_real_reductions_same_typeEz"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_8:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_8]] to %[[VAL_3]]#0 : f32, !fir.ref<f32> +! CHECK: %[[VAL_9:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_5]]#0 : f32, !fir.ref<f32> +! CHECK: %[[VAL_10:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_7]]#0 : f32, !fir.ref<f32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_11:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QFmultiple_real_reductions_same_typeEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref<f32>, @add_reduction_byref_f32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref<f32>, @add_reduction_byref_f32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref<f32>) for (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { +! CHECK: fir.store %[[VAL_19]] to %[[VAL_12]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFmultiple_real_reductions_same_typeEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFmultiple_real_reductions_same_typeEy"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_22:.*]]:2 = hlfir.declare %[[VAL_18]] {uniq_name = "_QFmultiple_real_reductions_same_typeEz"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_23:.*]] = fir.load %[[VAL_20]]#0 : !fir.ref<f32> +! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_24]] : (i32) -> f32 +! CHECK: %[[VAL_26:.*]] = arith.addf %[[VAL_23]], %[[VAL_25]] fastmath<contract> : f32 +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_20]]#0 : f32, !fir.ref<f32> +! CHECK: %[[VAL_27:.*]] = fir.load %[[VAL_21]]#0 : !fir.ref<f32> +! CHECK: %[[VAL_28:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_28]] : (i32) -> f32 +! CHECK: %[[VAL_30:.*]] = arith.addf %[[VAL_27]], %[[VAL_29]] fastmath<contract> : f32 +! CHECK: hlfir.assign %[[VAL_30]] to %[[VAL_21]]#0 : f32, !fir.ref<f32> +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_22]]#0 : !fir.ref<f32> +! CHECK: %[[VAL_32:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_33:.*]] = fir.convert %[[VAL_32]] : (i32) -> f32 +! CHECK: %[[VAL_34:.*]] = arith.addf %[[VAL_31]], %[[VAL_33]] fastmath<contract> : f32 +! CHECK: hlfir.assign %[[VAL_34]] to %[[VAL_22]]#0 : f32, !fir.ref<f32> +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine multiple_real_reductions_same_type + real :: x,y,z + x = 0.0 + y = 0.0 + z = 0.0 + !$omp parallel + !$omp do reduction(+:x,y,z) + do i=1, 100 + x = x + i + y = y + i + z = z + i + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_reductions_different_type() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_reductions_different_typeEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFmultiple_reductions_different_typeEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = fir.alloca f64 {bindc_name = "w", uniq_name = "_QFmultiple_reductions_different_typeEw"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFmultiple_reductions_different_typeEw"} : (!fir.ref<f64>) -> (!fir.ref<f64>, !fir.ref<f64>) +! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFmultiple_reductions_different_typeEx"} +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFmultiple_reductions_different_typeEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_6:.*]] = fir.alloca i64 {bindc_name = "y", uniq_name = "_QFmultiple_reductions_different_typeEy"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductions_different_typeEy"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_8:.*]] = fir.alloca f32 {bindc_name = "z", uniq_name = "_QFmultiple_reductions_different_typeEz"} +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFmultiple_reductions_different_typeEz"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_10:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_5]]#0 : i32, !fir.ref<i32> +! CHECK: %[[VAL_11:.*]] = arith.constant 0 : i64 +! CHECK: hlfir.assign %[[VAL_11]] to %[[VAL_7]]#0 : i64, !fir.ref<i64> +! CHECK: %[[VAL_12:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_12]] to %[[VAL_9]]#0 : f32, !fir.ref<f32> +! CHECK: %[[VAL_13:.*]] = arith.constant 0.000000e+00 : f64 +! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_3]]#0 : f64, !fir.ref<f64> +! CHECK: omp.parallel { +! CHECK: %[[VAL_14:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_14]] {uniq_name = "_QFmultiple_reductions_different_typeEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_16:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_17:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_18:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_5]]#0 -> %[[VAL_19:.*]] : !fir.ref<i32>, @add_reduction_byref_i64 %[[VAL_7]]#0 -> %[[VAL_20:.*]] : !fir.ref<i64>, @add_reduction_byref_f32 %[[VAL_9]]#0 -> %[[VAL_21:.*]] : !fir.ref<f32>, @add_reduction_byref_f64 %[[VAL_3]]#0 -> %[[VAL_22:.*]] : !fir.ref<f64>) for (%[[VAL_23:.*]]) : i32 = (%[[VAL_16]]) to (%[[VAL_17]]) inclusive step (%[[VAL_18]]) { +! CHECK: fir.store %[[VAL_23]] to %[[VAL_15]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_24:.*]]:2 = hlfir.declare %[[VAL_19]] {uniq_name = "_QFmultiple_reductions_different_typeEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_25:.*]]:2 = hlfir.declare %[[VAL_20]] {uniq_name = "_QFmultiple_reductions_different_typeEy"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_26:.*]]:2 = hlfir.declare %[[VAL_21]] {uniq_name = "_QFmultiple_reductions_different_typeEz"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_22]] {uniq_name = "_QFmultiple_reductions_different_typeEw"} : (!fir.ref<f64>) -> (!fir.ref<f64>, !fir.ref<f64>) +! CHECK: %[[VAL_28:.*]] = fir.load %[[VAL_24]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_30:.*]] = arith.addi %[[VAL_28]], %[[VAL_29]] : i32 +! CHECK: hlfir.assign %[[VAL_30]] to %[[VAL_24]]#0 : i32, !fir.ref<i32> +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_25]]#0 : !fir.ref<i64> +! CHECK: %[[VAL_32:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_33:.*]] = fir.convert %[[VAL_32]] : (i32) -> i64 +! CHECK: %[[VAL_34:.*]] = arith.addi %[[VAL_31]], %[[VAL_33]] : i64 +! CHECK: hlfir.assign %[[VAL_34]] to %[[VAL_25]]#0 : i64, !fir.ref<i64> +! CHECK: %[[VAL_35:.*]] = fir.load %[[VAL_26]]#0 : !fir.ref<f32> +! CHECK: %[[VAL_36:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_36]] : (i32) -> f32 +! CHECK: %[[VAL_38:.*]] = arith.addf %[[VAL_35]], %[[VAL_37]] fastmath<contract> : f32 +! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_26]]#0 : f32, !fir.ref<f32> +! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_27]]#0 : !fir.ref<f64> +! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> f64 +! CHECK: %[[VAL_42:.*]] = arith.addf %[[VAL_39]], %[[VAL_41]] fastmath<contract> : f64 +! CHECK: hlfir.assign %[[VAL_42]] to %[[VAL_27]]#0 : f64, !fir.ref<f64> +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: return +! CHECK: } + +subroutine multiple_reductions_different_type + integer :: x + integer(kind=8) :: y + real :: z + real(kind=8) :: w + x = 0 + y = 0 + z = 0.0 + w = 0.0 + !$omp parallel + !$omp do reduction(+:x,y,z,w) + do i=1, 100 + x = x + i + y = y + i + z = z + i + w = w + i + end do + !$omp end do + !$omp end parallel +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-add-hlfir-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-add-hlfir-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..3b4d9666c693733a9d4b8ea7cf5c8063678607ab --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-add-hlfir-byref.f90 @@ -0,0 +1,56 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! CHECK-LABEL: omp.declare_reduction @add_reduction_byref_i32 : !fir.ref<i32> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref<i32> +! CHECK: omp.yield(%[[REF]] : !fir.ref<i32>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> +! CHECK: %[[RES:.*]] = arith.addi %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i32> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<i32>) +! CHECK: } + +! CHECK-LABEL: func.func @_QPsimple_int_reduction() +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_int_reductionEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsimple_int_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_int_reductionEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : i32, !fir.ref<i32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFsimple_int_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) +! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_15:.*]] = arith.addi %[[VAL_13]], %[[VAL_14]] : i32 +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_12]]#0 : i32, !fir.ref<i32> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + + +subroutine simple_int_reduction + integer :: x + x = 0 + !$omp parallel + !$omp do reduction(+:x) + do i=1, 100 + x = x + i + end do + !$omp end do + !$omp end parallel +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-add-hlfir.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-add-hlfir.f90 index 4d30282fc8c21fcad50b41c61c9e52976394a6e2..7c9070592e468e1e3d14c35110b8b0ee95c17caf 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-add-hlfir.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-add-hlfir.f90 @@ -3,7 +3,7 @@ ! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py -! CHECK-LABEL: omp.reduction.declare @add_reduction_i_32 : i32 init { +! CHECK-LABEL: omp.declare_reduction @add_reduction_i32 : i32 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: i32): ! CHECK: %[[VAL_1:.*]] = arith.constant 0 : i32 ! CHECK: omp.yield(%[[VAL_1]] : i32) @@ -27,7 +27,7 @@ ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@add_reduction_i_32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) +! CHECK: omp.wsloop reduction(@add_reduction_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) ! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-add.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-add.f90 index 7df4f37b98df8c0aa3578ff6565c98191801720b..11e1ffb79f8e4ee4d45b1bdf22bdf9696216cc7f 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-add.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-add.f90 @@ -1,17 +1,7 @@ ! RUN: bbc -emit-hlfir -fopenmp %s -o - | FileCheck %s ! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s - -! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py - -! The script is designed to make adding checks to -! a test case fast, it is *not* designed to be authoritative -! about what constitutes a good test! The CHECK should be -! minimized and named to reflect the test intent. - - - -! CHECK-LABEL: omp.reduction.declare @add_reduction_f_64 : f64 init { +! CHECK-LABEL: omp.declare_reduction @add_reduction_f64 : f64 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: f64): ! CHECK: %[[VAL_1:.*]] = arith.constant 0.000000e+00 : f64 ! CHECK: omp.yield(%[[VAL_1]] : f64) @@ -22,7 +12,7 @@ ! CHECK: omp.yield(%[[VAL_2]] : f64) ! CHECK: } -! CHECK-LABEL: omp.reduction.declare @add_reduction_i_64 : i64 init { +! CHECK-LABEL: omp.declare_reduction @add_reduction_i64 : i64 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: i64): ! CHECK: %[[VAL_1:.*]] = arith.constant 0 : i64 ! CHECK: omp.yield(%[[VAL_1]] : i64) @@ -33,7 +23,7 @@ ! CHECK: omp.yield(%[[VAL_2]] : i64) ! CHECK: } -! CHECK-LABEL: omp.reduction.declare @add_reduction_f_32 : f32 init { +! CHECK-LABEL: omp.declare_reduction @add_reduction_f32 : f32 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: f32): ! CHECK: %[[VAL_1:.*]] = arith.constant 0.000000e+00 : f32 ! CHECK: omp.yield(%[[VAL_1]] : f32) @@ -44,7 +34,7 @@ ! CHECK: omp.yield(%[[VAL_2]] : f32) ! CHECK: } -! CHECK-LABEL: omp.reduction.declare @add_reduction_i_32 : i32 init { +! CHECK-LABEL: omp.declare_reduction @add_reduction_i32 : i32 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: i32): ! CHECK: %[[VAL_1:.*]] = arith.constant 0 : i32 ! CHECK: omp.yield(%[[VAL_1]] : i32) @@ -68,7 +58,7 @@ ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@add_reduction_i_32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: omp.wsloop reduction(@add_reduction_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { ! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> @@ -108,7 +98,7 @@ end subroutine ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@add_reduction_f_32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<f32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: omp.wsloop reduction(@add_reduction_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<f32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { ! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_real_reductionEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<f32> @@ -149,7 +139,7 @@ end subroutine ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@add_reduction_i_32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: omp.wsloop reduction(@add_reduction_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { ! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reduction_switch_orderEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32> @@ -188,7 +178,7 @@ end subroutine ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@add_reduction_f_32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<f32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: omp.wsloop reduction(@add_reduction_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<f32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { ! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_real_reduction_switch_orderEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32> @@ -236,7 +226,7 @@ end subroutine ! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_14:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@add_reduction_i_32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref<i32>, @add_reduction_i_32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref<i32>, @add_reduction_i_32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref<i32>) for (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { +! CHECK: omp.wsloop reduction(@add_reduction_i32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref<i32>, @add_reduction_i32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref<i32>, @add_reduction_i32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref<i32>) for (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { ! CHECK: fir.store %[[VAL_19]] to %[[VAL_12]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFmultiple_int_reductions_same_typeEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFmultiple_int_reductions_same_typeEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) @@ -297,7 +287,7 @@ end subroutine ! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_14:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@add_reduction_f_32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref<f32>, @add_reduction_f_32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref<f32>, @add_reduction_f_32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref<f32>) for (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { +! CHECK: omp.wsloop reduction(@add_reduction_f32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref<f32>, @add_reduction_f32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref<f32>, @add_reduction_f32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref<f32>) for (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { ! CHECK: fir.store %[[VAL_19]] to %[[VAL_12]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFmultiple_real_reductions_same_typeEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFmultiple_real_reductions_same_typeEy"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) @@ -365,7 +355,7 @@ end subroutine ! CHECK: %[[VAL_16:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_17:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_18:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@add_reduction_i_32 %[[VAL_5]]#0 -> %[[VAL_19:.*]] : !fir.ref<i32>, @add_reduction_i_64 %[[VAL_7]]#0 -> %[[VAL_20:.*]] : !fir.ref<i64>, @add_reduction_f_32 %[[VAL_9]]#0 -> %[[VAL_21:.*]] : !fir.ref<f32>, @add_reduction_f_64 %[[VAL_3]]#0 -> %[[VAL_22:.*]] : !fir.ref<f64>) for (%[[VAL_23:.*]]) : i32 = (%[[VAL_16]]) to (%[[VAL_17]]) inclusive step (%[[VAL_18]]) { +! CHECK: omp.wsloop reduction(@add_reduction_i32 %[[VAL_5]]#0 -> %[[VAL_19:.*]] : !fir.ref<i32>, @add_reduction_i64 %[[VAL_7]]#0 -> %[[VAL_20:.*]] : !fir.ref<i64>, @add_reduction_f32 %[[VAL_9]]#0 -> %[[VAL_21:.*]] : !fir.ref<f32>, @add_reduction_f64 %[[VAL_3]]#0 -> %[[VAL_22:.*]] : !fir.ref<f64>) for (%[[VAL_23:.*]]) : i32 = (%[[VAL_16]]) to (%[[VAL_17]]) inclusive step (%[[VAL_18]]) { ! CHECK: fir.store %[[VAL_23]] to %[[VAL_15]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_24:.*]]:2 = hlfir.declare %[[VAL_19]] {uniq_name = "_QFmultiple_reductions_different_typeEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_25:.*]]:2 = hlfir.declare %[[VAL_20]] {uniq_name = "_QFmultiple_reductions_different_typeEy"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 new file mode 100644 index 0000000000000000000000000000000000000000..a20ed1ca83ce2be70387aa8f8426cb85eea24aea --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-array.f90 @@ -0,0 +1,84 @@ +! RUN: bbc -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s +program reduce +integer :: i = 0 +integer, dimension(2) :: r = 0 + +!$omp parallel do reduction(+:r) +do i=0,10 + r(1) = i + r(2) = -i +enddo +!$omp end parallel do + +print *,r +end program + +! CHECK-LABEL omp.declare_reduction @add_reduction_byref_box_2xi32 : !fir.ref<!fir.box<!fir.array<2xi32>>> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.array<2xi32>>>): +! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.array<2xi32> {bindc_name = ".tmp"} +! CHECK: %[[VAL_2:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.array<2xi32>>> +! CHECK: %[[VAL_4:.*]] = arith.constant 2 : index +! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_5]]) {uniq_name = ".tmp"} : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<2xi32>>, !fir.ref<!fir.array<2xi32>>) +! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_6]]#0(%[[VAL_5]]) : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<2xi32>> +! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_7]] : i32, !fir.box<!fir.array<2xi32>> +! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box<!fir.array<2xi32>> +! CHECK: fir.store %[[VAL_7]] to %[[VAL_8]] : !fir.ref<!fir.box<!fir.array<2xi32>>> +! CHECK: omp.yield(%[[VAL_8]] : !fir.ref<!fir.box<!fir.array<2xi32>>>) + +! CHECK-LABEL } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.array<2xi32>>>, %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.array<2xi32>>>): +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.array<2xi32>>> +! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.array<2xi32>>> +! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_4]] : (!fir.box<!fir.array<2xi32>>, index) -> (index, index, index) +! CHECK: %[[VAL_6:.*]] = fir.shape_shift %[[VAL_5]]#0, %[[VAL_5]]#1 : (index, index) -> !fir.shapeshift<1> +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_8:.*]] = %[[VAL_7]] to %[[VAL_5]]#1 step %[[VAL_7]] unordered { +! CHECK: %[[VAL_9:.*]] = fir.array_coor %[[VAL_2]](%[[VAL_6]]) %[[VAL_8]] : (!fir.box<!fir.array<2xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32> +! CHECK: %[[VAL_10:.*]] = fir.array_coor %[[VAL_3]](%[[VAL_6]]) %[[VAL_8]] : (!fir.box<!fir.array<2xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32> +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_9]] : !fir.ref<i32> +! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_10]] : !fir.ref<i32> +! CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_11]], %[[VAL_12]] : i32 +! CHECK: fir.store %[[VAL_13]] to %[[VAL_9]] : !fir.ref<i32> +! CHECK: } +! CHECK: omp.yield(%[[VAL_0]] : !fir.ref<!fir.box<!fir.array<2xi32>>>) +! CHECK: } + +! CHECK-LABEL func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { +! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEi) : !fir.ref<i32> +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QFEr) : !fir.ref<!fir.array<2xi32>> +! CHECK: %[[VAL_3:.*]] = arith.constant 2 : index +! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]](%[[VAL_4]]) {uniq_name = "_QFEr"} : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<2xi32>>, !fir.ref<!fir.array<2xi32>>) +! CHECK: omp.parallel { +! CHECK: %[[VAL_6:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_8:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_11:.*]] = fir.embox %[[VAL_5]]#1(%[[VAL_4]]) : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<2xi32>> +! CHECK: %[[VAL_12:.*]] = fir.alloca !fir.box<!fir.array<2xi32>> +! CHECK: fir.store %[[VAL_11]] to %[[VAL_12]] : !fir.ref<!fir.box<!fir.array<2xi32>>> +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_box_2xi32 %[[VAL_12]] -> %[[VAL_13:.*]] : !fir.ref<!fir.box<!fir.array<2xi32>>>) for (%[[VAL_14:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) { +! CHECK: fir.store %[[VAL_14]] to %[[VAL_7]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_13]] {uniq_name = "_QFEr"} : (!fir.ref<!fir.box<!fir.array<2xi32>>>) -> (!fir.ref<!fir.box<!fir.array<2xi32>>>, !fir.ref<!fir.box<!fir.array<2xi32>>>) +! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<!fir.box<!fir.array<2xi32>>> +! CHECK: %[[VAL_18:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_19:.*]] = hlfir.designate %[[VAL_17]] (%[[VAL_18]]) : (!fir.box<!fir.array<2xi32>>, index) -> !fir.ref<i32> +! CHECK: hlfir.assign %[[VAL_16]] to %[[VAL_19]] : i32, !fir.ref<i32> +! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_21:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_22:.*]] = arith.subi %[[VAL_21]], %[[VAL_20]] : i32 +! CHECK: %[[VAL_23:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<!fir.box<!fir.array<2xi32>>> +! CHECK: %[[VAL_24:.*]] = arith.constant 2 : index +! CHECK: %[[VAL_25:.*]] = hlfir.designate %[[VAL_23]] (%[[VAL_24]]) : (!fir.box<!fir.array<2xi32>>, index) -> !fir.ref<i32> +! CHECK: hlfir.assign %[[VAL_22]] to %[[VAL_25]] : i32, !fir.ref<i32> +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 new file mode 100644 index 0000000000000000000000000000000000000000..61599876da8ea40fb5675bb7acb7a43ea84edf32 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-array2.f90 @@ -0,0 +1,92 @@ +! RUN: bbc -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s +program reduce +integer :: i = 0 +integer, dimension(2) :: r = 0 + +!$omp parallel do reduction(+:r) +do i=0,10 + r(1) = r(1) + i + r(2) = r(2) - i +enddo +!$omp end parallel do + +print *,r +end program + +! CHECK-LABEL omp.declare_reduction @add_reduction_byref_box_2xi32 : !fir.ref<!fir.box<!fir.array<2xi32>>> init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.array<2xi32>>>): +! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.array<2xi32> {bindc_name = ".tmp"} +! CHECK: %[[VAL_2:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.array<2xi32>>> +! CHECK: %[[VAL_4:.*]] = arith.constant 2 : index +! CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_1]](%[[VAL_5]]) {uniq_name = ".tmp"} : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<2xi32>>, !fir.ref<!fir.array<2xi32>>) +! CHECK: %[[VAL_7:.*]] = fir.embox %[[VAL_6]]#0(%[[VAL_5]]) : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<2xi32>> +! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_7]] : i32, !fir.box<!fir.array<2xi32>> +! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box<!fir.array<2xi32>> +! CHECK: fir.store %[[VAL_7]] to %[[VAL_8]] : !fir.ref<!fir.box<!fir.array<2xi32>>> +! CHECK: omp.yield(%[[VAL_8]] : !fir.ref<!fir.box<!fir.array<2xi32>>>) + +! CHECK-LABEL } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.array<2xi32>>>, %[[VAL_1:.*]]: !fir.ref<!fir.box<!fir.array<2xi32>>>): +! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.array<2xi32>>> +! CHECK: %[[VAL_3:.*]] = fir.load %[[VAL_1]] : !fir.ref<!fir.box<!fir.array<2xi32>>> +! CHECK: %[[VAL_4:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_5:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_4]] : (!fir.box<!fir.array<2xi32>>, index) -> (index, index, index) +! CHECK: %[[VAL_6:.*]] = fir.shape_shift %[[VAL_5]]#0, %[[VAL_5]]#1 : (index, index) -> !fir.shapeshift<1> +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : index +! CHECK: fir.do_loop %[[VAL_8:.*]] = %[[VAL_7]] to %[[VAL_5]]#1 step %[[VAL_7]] unordered { +! CHECK: %[[VAL_9:.*]] = fir.array_coor %[[VAL_2]](%[[VAL_6]]) %[[VAL_8]] : (!fir.box<!fir.array<2xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32> +! CHECK: %[[VAL_10:.*]] = fir.array_coor %[[VAL_3]](%[[VAL_6]]) %[[VAL_8]] : (!fir.box<!fir.array<2xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32> +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_9]] : !fir.ref<i32> +! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_10]] : !fir.ref<i32> +! CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_11]], %[[VAL_12]] : i32 +! CHECK: fir.store %[[VAL_13]] to %[[VAL_9]] : !fir.ref<i32> +! CHECK: } +! CHECK: omp.yield(%[[VAL_0]] : !fir.ref<!fir.box<!fir.array<2xi32>>>) +! CHECK: } + +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { +! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEi) : !fir.ref<i32> +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QFEr) : !fir.ref<!fir.array<2xi32>> +! CHECK: %[[VAL_3:.*]] = arith.constant 2 : index +! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]](%[[VAL_4]]) {uniq_name = "_QFEr"} : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>) -> (!fir.ref<!fir.array<2xi32>>, !fir.ref<!fir.array<2xi32>>) +! CHECK: omp.parallel { +! CHECK: %[[VAL_6:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_8:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_11:.*]] = fir.embox %[[VAL_5]]#1(%[[VAL_4]]) : (!fir.ref<!fir.array<2xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<2xi32>> +! CHECK: %[[VAL_12:.*]] = fir.alloca !fir.box<!fir.array<2xi32>> +! CHECK: fir.store %[[VAL_11]] to %[[VAL_12]] : !fir.ref<!fir.box<!fir.array<2xi32>>> +! CHECK: omp.wsloop byref reduction(@add_reduction_byref_box_2xi32 %[[VAL_12]] -> %[[VAL_13:.*]] : !fir.ref<!fir.box<!fir.array<2xi32>>>) for (%[[VAL_14:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) { +! CHECK: fir.store %[[VAL_14]] to %[[VAL_7]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_13]] {uniq_name = "_QFEr"} : (!fir.ref<!fir.box<!fir.array<2xi32>>>) -> (!fir.ref<!fir.box<!fir.array<2xi32>>>, !fir.ref<!fir.box<!fir.array<2xi32>>>) +! CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<!fir.box<!fir.array<2xi32>>> +! CHECK: %[[VAL_17:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_18:.*]] = hlfir.designate %[[VAL_16]] (%[[VAL_17]]) : (!fir.box<!fir.array<2xi32>>, index) -> !fir.ref<i32> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_18]] : !fir.ref<i32> +! CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_21:.*]] = arith.addi %[[VAL_19]], %[[VAL_20]] : i32 +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<!fir.box<!fir.array<2xi32>>> +! CHECK: %[[VAL_23:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_24:.*]] = hlfir.designate %[[VAL_22]] (%[[VAL_23]]) : (!fir.box<!fir.array<2xi32>>, index) -> !fir.ref<i32> +! CHECK: hlfir.assign %[[VAL_21]] to %[[VAL_24]] : i32, !fir.ref<i32> +! CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<!fir.box<!fir.array<2xi32>>> +! CHECK: %[[VAL_26:.*]] = arith.constant 2 : index +! CHECK: %[[VAL_27:.*]] = hlfir.designate %[[VAL_25]] (%[[VAL_26]]) : (!fir.box<!fir.array<2xi32>>, index) -> !fir.ref<i32> +! CHECK: %[[VAL_28:.*]] = fir.load %[[VAL_27]] : !fir.ref<i32> +! CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_30:.*]] = arith.subi %[[VAL_28]], %[[VAL_29]] : i32 +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<!fir.box<!fir.array<2xi32>>> +! CHECK: %[[VAL_32:.*]] = arith.constant 2 : index +! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_31]] (%[[VAL_32]]) : (!fir.box<!fir.array<2xi32>>, index) -> !fir.ref<i32> +! CHECK: hlfir.assign %[[VAL_30]] to %[[VAL_33]] : i32, !fir.ref<i32> +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-iand-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-iand-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..e3f06a446ed4c1aca20da314624f04fb24594132 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-iand-byref.f90 @@ -0,0 +1,64 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.declare_reduction @iand_byref_i32 : !fir.ref<i32> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +! CHECK: %[[C0_1:.*]] = arith.constant -1 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref<i32> +! CHECK: omp.yield(%[[REF]] : !fir.ref<i32>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> +! CHECK: %[[RES:.*]] = arith.andi %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i32> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<i32>) +! CHECK: } + +! CHECK-LABEL: func.func @_QPreduction_iand( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFreduction_iandEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_iandEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_iandEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_iandEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFreduction_iandEy"} : (!fir.box<!fir.array<?xi32>>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : i32, !fir.ref<i32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFreduction_iandEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@iand_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { +! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_iandEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64 +! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_16]]) : (!fir.box<!fir.array<?xi32>>, i64) -> !fir.ref<i32> +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_14]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_17]] : !fir.ref<i32> +! CHECK: %[[VAL_20:.*]] = arith.andi %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: hlfir.assign %[[VAL_20]] to %[[VAL_14]]#0 : i32, !fir.ref<i32> +! CHECK: omp.yield +! CHECK: omp.terminator + + + +subroutine reduction_iand(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(iand:x) + do i=1, 100 + x = iand(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-iand.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-iand.f90 index 9588531f6c909a5ab0ac00f74b35b0210888d6b7..746617e210624b666e48c57c5a061b53f425a73e 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-iand.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-iand.f90 @@ -3,7 +3,7 @@ ! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py -! CHECK-LABEL: omp.reduction.declare @iand_i_32 : i32 init { +! CHECK-LABEL: omp.declare_reduction @iand_i32 : i32 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: i32): ! CHECK: %[[VAL_1:.*]] = arith.constant -1 : i32 ! CHECK: omp.yield(%[[VAL_1]] : i32) @@ -29,7 +29,7 @@ ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@iand_i_32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { +! CHECK: omp.wsloop reduction(@iand_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { ! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_iandEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32> diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-ieor-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-ieor-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..7e3a283bf783c8f436765e317634cbab83aacef5 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-ieor-byref.f90 @@ -0,0 +1,55 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! CHECK-LABEL: omp.declare_reduction @ieor_byref_i32 : !fir.ref<i32> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref<i32> +! CHECK: omp.yield(%[[REF]] : !fir.ref<i32>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> +! CHECK: %[[RES:.*]] = arith.xori %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i32> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<i32>) +! CHECK: } + +!CHECK-LABEL: @_QPreduction_ieor +!CHECK-SAME: %[[Y_BOX:.*]]: !fir.box<!fir.array<?xi32>> +!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_ieorEx"} +!CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X_REF]] {uniq_name = "_QFreduction_ieorEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y_BOX]] {uniq_name = "_QFreduction_ieorEy"} : (!fir.box<!fir.array<?xi32>>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) + + +!CHECK: omp.parallel +!CHECK: %[[I_REF:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +!CHECK: %[[I_DECL:.*]]:2 = hlfir.declare %[[I_REF]] {uniq_name = "_QFreduction_ieorEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: omp.wsloop byref reduction(@ieor_byref_i32 %[[X_DECL]]#0 -> %[[PRV:.+]] : !fir.ref<i32>) for +!CHECK: fir.store %{{.*}} to %[[I_DECL]]#1 : !fir.ref<i32> +!CHECK: %[[PRV_DECL:.+]]:2 = hlfir.declare %[[PRV]] {{.*}} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[I_32:.*]] = fir.load %[[I_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[I_64:.*]] = fir.convert %[[I_32]] : (i32) -> i64 +!CHECK: %[[Y_I_REF:.*]] = hlfir.designate %[[Y_DECL]]#0 (%[[I_64]]) : (!fir.box<!fir.array<?xi32>>, i64) -> !fir.ref<i32> +!CHECK: %[[LPRV:.+]] = fir.load %[[PRV_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[Y_I:.*]] = fir.load %[[Y_I_REF]] : !fir.ref<i32> +!CHECK: %[[RES:.+]] = arith.xori %[[LPRV]], %[[Y_I]] : i32 +!CHECK: hlfir.assign %[[RES]] to %[[PRV_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.yield +!CHECK: omp.terminator + +subroutine reduction_ieor(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(ieor:x) + do i=1, 100 + x = ieor(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-ieor.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-ieor.f90 index a14a37101874c8dbba88edb0b3c3dc9ad9717663..11245c4ac95e034bed6488bf7222da9b36fd3973 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-ieor.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-ieor.f90 @@ -1,7 +1,7 @@ ! RUN: bbc -emit-hlfir -fopenmp %s -o - | FileCheck %s ! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s -!CHECK: omp.reduction.declare @[[IEOR_DECLARE_I:.*]] : i32 init { +!CHECK: omp.declare_reduction @[[IEOR_DECLARE_I:.*]] : i32 init { !CHECK: %[[ZERO_VAL_I:.*]] = arith.constant 0 : i32 !CHECK: omp.yield(%[[ZERO_VAL_I]] : i32) !CHECK: combiner diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-ior-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-ior-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..c7f8e8bdede5480d45d401dc04e8a3386824a87e --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-ior-byref.f90 @@ -0,0 +1,62 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! CHECK-LABEL: omp.declare_reduction @ior_byref_i32 : !fir.ref<i32> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +! CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[C0_1]] to %[[REF]] : !fir.ref<i32> +! CHECK: omp.yield(%[[REF]] : !fir.ref<i32>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> +! CHECK: %[[RES:.*]] = arith.ori %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i32> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<i32>) +! CHECK: } + +! CHECK-LABEL: func.func @_QPreduction_ior( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFreduction_iorEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_iorEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_iorEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_iorEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFreduction_iorEy"} : (!fir.box<!fir.array<?xi32>>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : i32, !fir.ref<i32> +! CHECK: omp.parallel +! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFreduction_iorEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@ior_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) +! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_iorEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64 +! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_16]]) : (!fir.box<!fir.array<?xi32>>, i64) -> !fir.ref<i32> +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_14]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_17]] : !fir.ref<i32> +! CHECK: %[[VAL_20:.*]] = arith.ori %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: hlfir.assign %[[VAL_20]] to %[[VAL_14]]#0 : i32, !fir.ref<i32> +! CHECK: omp.yield +! CHECK: omp.terminator + + + +subroutine reduction_ior(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(ior:x) + do i=1, 100 + x = ior(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-ior.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-ior.f90 index 3b5e327439358d46983b0c933fa4855a4b513691..dd0bbeb1a0761f097cf5e6916c872b20c5f71374 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-ior.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-ior.f90 @@ -3,7 +3,7 @@ ! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py -! CHECK-LABEL: omp.reduction.declare @ior_i_32 : i32 init { +! CHECK-LABEL: omp.declare_reduction @ior_i32 : i32 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: i32): ! CHECK: %[[VAL_1:.*]] = arith.constant 0 : i32 ! CHECK: omp.yield(%[[VAL_1]] : i32) @@ -29,7 +29,7 @@ ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@ior_i_32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) +! CHECK: omp.wsloop reduction(@ior_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) ! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_iorEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32> diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..59411534e4a5c074a25066a7c67901861c3fc668 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-and-byref.f90 @@ -0,0 +1,206 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.declare_reduction @and_reduction : !fir.ref<!fir.logical<4>> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[VAL_1:.*]] = arith.constant true +! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4> +! CHECK: %[[REF:.*]] = fir.alloca !fir.logical<4> +! CHECK: fir.store %[[VAL_2]] to %[[REF]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.yield(%[[REF]] : !fir.ref<!fir.logical<4>>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.logical<4>>, %[[ARG1:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_2:.*]] = fir.convert %[[LD0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_3:.*]] = fir.convert %[[LD1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[RES:.*]] = arith.andi %[[VAL_2]], %[[VAL_3]] : i1 +! CHECK: %[[VAL_5:.*]] = fir.convert %[[RES]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_5]] to %[[ARG0]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<!fir.logical<4>>) +! CHECK: } + +! CHECK-LABEL: func.func @_QPsimple_reduction( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reductionEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFsimple_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reductionEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_8:.*]] = arith.constant true +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@and_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) for (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64 +! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_20]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_18]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_25:.*]] = arith.andi %[[VAL_23]], %[[VAL_24]] : i1 +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.and.:x) + do i=1, 100 + x = x .and. y(i) + end do + !$omp end do + !$omp end parallel +end subroutine simple_reduction + + +! CHECK-LABEL: func.func @_QPsimple_reduction_switch_order( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reduction_switch_orderEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFsimple_reduction_switch_orderEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reduction_switch_orderEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_8:.*]] = arith.constant true +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_reduction_switch_orderEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@and_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) for (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_18]] : (i32) -> i64 +! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_19]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_20]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_25:.*]] = arith.andi %[[VAL_23]], %[[VAL_24]] : i1 +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction_switch_order(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.and.:x) + do i=1, 100 + x = y(i) .and. x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_reductions( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "w"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_reductionsEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_10:.*]] = fir.alloca !fir.logical<4> {bindc_name = "z", uniq_name = "_QFmultiple_reductionsEz"} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFmultiple_reductionsEz"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_12:.*]] = arith.constant true +! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_12]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_7]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_14:.*]] = arith.constant true +! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_9]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_16:.*]] = arith.constant true +! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_16]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_17]] to %[[VAL_11]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_18:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_18]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_20:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_21:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@and_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref<!fir.logical<4>>, @and_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref<!fir.logical<4>>, @and_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref<!fir.logical<4>>) for (%[[VAL_26:.*]]) : i32 = (%[[VAL_20]]) to (%[[VAL_21]]) inclusive step (%[[VAL_22]]) { +! CHECK: fir.store %[[VAL_26]] to %[[VAL_19]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_23]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_24]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_29:.*]]:2 = hlfir.declare %[[VAL_25]] {uniq_name = "_QFmultiple_reductionsEz"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_27]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64 +! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_32]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_33]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_34]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_37:.*]] = arith.andi %[[VAL_35]], %[[VAL_36]] : i1 +! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_28]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> i64 +! CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_41]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_42]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_39]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_43]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_46:.*]] = arith.andi %[[VAL_44]], %[[VAL_45]] : i1 +! CHECK: %[[VAL_47:.*]] = fir.convert %[[VAL_46]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_48:.*]] = fir.load %[[VAL_29]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_49:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_50:.*]] = fir.convert %[[VAL_49]] : (i32) -> i64 +! CHECK: %[[VAL_51:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_50]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_52:.*]] = fir.load %[[VAL_51]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_53:.*]] = fir.convert %[[VAL_48]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_54:.*]] = fir.convert %[[VAL_52]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_55:.*]] = arith.andi %[[VAL_53]], %[[VAL_54]] : i1 +! CHECK: %[[VAL_56:.*]] = fir.convert %[[VAL_55]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_56]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + + + +subroutine multiple_reductions(w) + logical :: x,y,z,w(100) + x = .true. + y = .true. + z = .true. + !$omp parallel + !$omp do reduction(.and.:x,y,z) + do i=1, 100 + x = x .and. w(i) + y = y .and. w(i) + z = z .and. w(i) + end do + !$omp end do + !$omp end parallel +end subroutine + diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-and.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-and.f90 index 17d321620cca8b1936f06dcf06cf2d026974d552..9ca733281c2f031376b9b2caa3a5945c4f2bcbec 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-and.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-and.f90 @@ -3,7 +3,7 @@ ! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py -! CHECK-LABEL: omp.reduction.declare @and_reduction : !fir.logical<4> init { +! CHECK-LABEL: omp.declare_reduction @and_reduction : !fir.logical<4> init { ! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.logical<4>): ! CHECK: %[[VAL_1:.*]] = arith.constant true ! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4> diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..1d6e1b0545c3bcffb96d7d47697d39b55d6e2845 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv-byref.f90 @@ -0,0 +1,202 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.declare_reduction @eqv_reduction : !fir.ref<!fir.logical<4>> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[VAL_1:.*]] = arith.constant true +! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4> +! CHECK: %[[REF:.*]] = fir.alloca !fir.logical<4> +! CHECK: fir.store %[[VAL_2]] to %[[REF]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.yield(%[[REF]] : !fir.ref<!fir.logical<4>>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.logical<4>>, %[[ARG1:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_2:.*]] = fir.convert %[[LD0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_3:.*]] = fir.convert %[[LD1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[RES:.*]] = arith.cmpi eq, %[[VAL_2]], %[[VAL_3]] : i1 +! CHECK: %[[VAL_5:.*]] = fir.convert %[[RES]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_5]] to %[[ARG0]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<!fir.logical<4>>) +! CHECK: } + +! CHECK-LABEL: func.func @_QPsimple_reduction( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reductionEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFsimple_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reductionEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_8:.*]] = arith.constant true +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@eqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) for (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64 +! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_20]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_18]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_25:.*]] = arith.cmpi eq, %[[VAL_23]], %[[VAL_24]] : i1 +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.eqv.:x) + do i=1, 100 + x = x .eqv. y(i) + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_reduction_switch_order( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reduction_switch_orderEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFsimple_reduction_switch_orderEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reduction_switch_orderEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_8:.*]] = arith.constant true +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_reduction_switch_orderEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@eqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) for (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_18]] : (i32) -> i64 +! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_19]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_20]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_25:.*]] = arith.cmpi eq, %[[VAL_23]], %[[VAL_24]] : i1 +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction_switch_order(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.eqv.:x) + do i=1, 100 + x = y(i) .eqv. x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_reductions( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "w"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_reductionsEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_10:.*]] = fir.alloca !fir.logical<4> {bindc_name = "z", uniq_name = "_QFmultiple_reductionsEz"} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFmultiple_reductionsEz"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_12:.*]] = arith.constant true +! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_12]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_7]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_14:.*]] = arith.constant true +! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_9]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_16:.*]] = arith.constant true +! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_16]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_17]] to %[[VAL_11]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_18:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_18]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_20:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_21:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@eqv_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref<!fir.logical<4>>, @eqv_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref<!fir.logical<4>>, @eqv_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref<!fir.logical<4>>) for (%[[VAL_26:.*]]) : i32 = (%[[VAL_20]]) to (%[[VAL_21]]) inclusive step (%[[VAL_22]]) { +! CHECK: fir.store %[[VAL_26]] to %[[VAL_19]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_23]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_24]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_29:.*]]:2 = hlfir.declare %[[VAL_25]] {uniq_name = "_QFmultiple_reductionsEz"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_27]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64 +! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_32]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_33]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_34]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_37:.*]] = arith.cmpi eq, %[[VAL_35]], %[[VAL_36]] : i1 +! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_28]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> i64 +! CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_41]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_42]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_39]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_43]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_46:.*]] = arith.cmpi eq, %[[VAL_44]], %[[VAL_45]] : i1 +! CHECK: %[[VAL_47:.*]] = fir.convert %[[VAL_46]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_48:.*]] = fir.load %[[VAL_29]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_49:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_50:.*]] = fir.convert %[[VAL_49]] : (i32) -> i64 +! CHECK: %[[VAL_51:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_50]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_52:.*]] = fir.load %[[VAL_51]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_53:.*]] = fir.convert %[[VAL_48]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_54:.*]] = fir.convert %[[VAL_52]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_55:.*]] = arith.cmpi eq, %[[VAL_53]], %[[VAL_54]] : i1 +! CHECK: %[[VAL_56:.*]] = fir.convert %[[VAL_55]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_56]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine multiple_reductions(w) + logical :: x,y,z,w(100) + x = .true. + y = .true. + z = .true. + !$omp parallel + !$omp do reduction(.eqv.:x,y,z) + do i=1, 100 + x = x .eqv. w(i) + y = y .eqv. w(i) + z = z .eqv. w(i) + end do + !$omp end do + !$omp end parallel +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv.f90 index 8204e4c878cb0459bcf5da8d11232c62db7f21b3..a1bfa462cd599ae4171e96b0c00ed37f0a384f40 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-eqv.f90 @@ -3,7 +3,7 @@ ! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py -! CHECK-LABEL: omp.reduction.declare @eqv_reduction : !fir.logical<4> init { +! CHECK-LABEL: omp.declare_reduction @eqv_reduction : !fir.logical<4> init { ! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.logical<4>): ! CHECK: %[[VAL_1:.*]] = arith.constant true ! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4> diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..a94b67a97832fc5aee066c09a4f84e1151c8aa9c --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv-byref.f90 @@ -0,0 +1,207 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.declare_reduction @neqv_reduction : !fir.ref<!fir.logical<4>> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[VAL_1:.*]] = arith.constant false +! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4> +! CHECK: %[[REF:.*]] = fir.alloca !fir.logical<4> +! CHECK: fir.store %[[VAL_2]] to %[[REF]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.yield(%[[REF]] : !fir.ref<!fir.logical<4>>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.logical<4>>, %[[ARG1:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_2:.*]] = fir.convert %[[LD0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_3:.*]] = fir.convert %[[LD1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[RES:.*]] = arith.cmpi ne, %[[VAL_2]], %[[VAL_3]] : i1 +! CHECK: %[[VAL_5:.*]] = fir.convert %[[RES]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_5]] to %[[ARG0]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<!fir.logical<4>>) +! CHECK: } + +! CHECK-LABEL: func.func @_QPsimple_reduction( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reductionEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFsimple_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reductionEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_8:.*]] = arith.constant true +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@neqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) for (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64 +! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_20]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_18]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_25:.*]] = arith.cmpi ne, %[[VAL_23]], %[[VAL_24]] : i1 +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.neqv.:x) + do i=1, 100 + x = x .neqv. y(i) + end do + !$omp end do + !$omp end parallel +end subroutine + + +! CHECK-LABEL: func.func @_QPsimple_reduction_switch_order( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reduction_switch_orderEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFsimple_reduction_switch_orderEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reduction_switch_orderEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_8:.*]] = arith.constant true +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_reduction_switch_orderEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@neqv_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) for (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_18]] : (i32) -> i64 +! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_19]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_20]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_25:.*]] = arith.cmpi ne, %[[VAL_23]], %[[VAL_24]] : i1 +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + + +subroutine simple_reduction_switch_order(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.neqv.:x) + do i=1, 100 + x = y(i) .neqv. x + end do + !$omp end do + !$omp end parallel +end subroutine + + +! CHECK-LABEL: func.func @_QPmultiple_reductions( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "w"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_reductionsEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_10:.*]] = fir.alloca !fir.logical<4> {bindc_name = "z", uniq_name = "_QFmultiple_reductionsEz"} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFmultiple_reductionsEz"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_12:.*]] = arith.constant true +! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_12]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_7]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_14:.*]] = arith.constant true +! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_9]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_16:.*]] = arith.constant true +! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_16]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_17]] to %[[VAL_11]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_18:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_18]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_20:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_21:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@neqv_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref<!fir.logical<4>>, @neqv_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref<!fir.logical<4>>, @neqv_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref<!fir.logical<4>>) for (%[[VAL_26:.*]]) : i32 = (%[[VAL_20]]) to (%[[VAL_21]]) inclusive step (%[[VAL_22]]) { +! CHECK: fir.store %[[VAL_26]] to %[[VAL_19]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_23]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_24]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_29:.*]]:2 = hlfir.declare %[[VAL_25]] {uniq_name = "_QFmultiple_reductionsEz"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_27]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64 +! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_32]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_33]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_34]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_37:.*]] = arith.cmpi ne, %[[VAL_35]], %[[VAL_36]] : i1 +! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_28]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> i64 +! CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_41]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_42]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_39]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_43]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_46:.*]] = arith.cmpi ne, %[[VAL_44]], %[[VAL_45]] : i1 +! CHECK: %[[VAL_47:.*]] = fir.convert %[[VAL_46]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_48:.*]] = fir.load %[[VAL_29]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_49:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_50:.*]] = fir.convert %[[VAL_49]] : (i32) -> i64 +! CHECK: %[[VAL_51:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_50]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_52:.*]] = fir.load %[[VAL_51]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_53:.*]] = fir.convert %[[VAL_48]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_54:.*]] = fir.convert %[[VAL_52]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_55:.*]] = arith.cmpi ne, %[[VAL_53]], %[[VAL_54]] : i1 +! CHECK: %[[VAL_56:.*]] = fir.convert %[[VAL_55]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_56]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return +! CHECK: } + + +subroutine multiple_reductions(w) + logical :: x,y,z,w(100) + x = .true. + y = .true. + z = .true. + !$omp parallel + !$omp do reduction(.neqv.:x,y,z) + do i=1, 100 + x = x .neqv. w(i) + y = y .neqv. w(i) + z = z .neqv. w(i) + end do + !$omp end do + !$omp end parallel +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv.f90 index 623368a50e86454870ba24fdabcdde1051c3e73f..08d6a2efd3993627cb6ea33977346d6452f60eef 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-neqv.f90 @@ -3,7 +3,7 @@ ! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py -! CHECK-LABEL: omp.reduction.declare @neqv_reduction : !fir.logical<4> init { +! CHECK-LABEL: omp.declare_reduction @neqv_reduction : !fir.logical<4> init { ! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.logical<4>): ! CHECK: %[[VAL_1:.*]] = arith.constant false ! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4> diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..ca69ccee4a38e34258475429de708a31cb7b6d8b --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-or-byref.f90 @@ -0,0 +1,204 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.declare_reduction @or_reduction : !fir.ref<!fir.logical<4>> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[VAL_1:.*]] = arith.constant false +! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4> +! CHECK: %[[REF:.*]] = fir.alloca !fir.logical<4> +! CHECK: fir.store %[[VAL_2]] to %[[REF]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.yield(%[[REF]] : !fir.ref<!fir.logical<4>>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<!fir.logical<4>>, %[[ARG1:.*]]: !fir.ref<!fir.logical<4>>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_2:.*]] = fir.convert %[[LD0]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_3:.*]] = fir.convert %[[LD1]] : (!fir.logical<4>) -> i1 +! CHECK: %[[RES:.*]] = arith.ori %[[VAL_2]], %[[VAL_3]] : i1 +! CHECK: %[[VAL_5:.*]] = fir.convert %[[RES]] : (i1) -> !fir.logical<4> +! CHECK: fir.store %[[VAL_5]] to %[[ARG0]] : !fir.ref<!fir.logical<4>> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<!fir.logical<4>>) + +! CHECK-LABEL: func.func @_QPsimple_reduction( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reductionEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFsimple_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reductionEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) {uniq_name = "_QFsimple_reductionEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_8:.*]] = arith.constant true +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@or_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) for (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reductionEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_19]] : (i32) -> i64 +! CHECK: %[[VAL_21:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_20]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_21]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_18]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_25:.*]] = arith.ori %[[VAL_23]], %[[VAL_24]] : i1 +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.or.:x) + do i=1, 100 + x = x .or. y(i) + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_reduction_switch_order( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_reduction_switch_orderEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFsimple_reduction_switch_orderEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFsimple_reduction_switch_orderEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_5:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_6:.*]] = fir.shape %[[VAL_5]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_6]]) {uniq_name = "_QFsimple_reduction_switch_orderEy"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_8:.*]] = arith.constant true +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_reduction_switch_orderEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_12:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_13:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@or_reduction %[[VAL_4]]#0 -> %[[VAL_15:.*]] : !fir.ref<!fir.logical<4>>) for (%[[VAL_16:.*]]) : i32 = (%[[VAL_12]]) to (%[[VAL_13]]) inclusive step (%[[VAL_14]]) { +! CHECK: fir.store %[[VAL_16]] to %[[VAL_11]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_17:.*]]:2 = hlfir.declare %[[VAL_15]] {uniq_name = "_QFsimple_reduction_switch_orderEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_11]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_18]] : (i32) -> i64 +! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_19]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_21:.*]] = fir.load %[[VAL_20]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_22:.*]] = fir.load %[[VAL_17]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_21]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_22]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_25:.*]] = arith.ori %[[VAL_23]], %[[VAL_24]] : i1 +! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_17]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_reduction_switch_order(y) + logical :: x, y(100) + x = .true. + !$omp parallel + !$omp do reduction(.or.:x) + do i=1, 100 + x = y(i) .or. x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_reductions( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<100x!fir.logical<4>>> {fir.bindc_name = "w"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_reductionsEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = arith.constant 100 : index +! CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_3]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_4]]) {uniq_name = "_QFmultiple_reductionsEw"} : (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.shape<1>) -> (!fir.ref<!fir.array<100x!fir.logical<4>>>, !fir.ref<!fir.array<100x!fir.logical<4>>>) +! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.logical<4> {bindc_name = "x", uniq_name = "_QFmultiple_reductionsEx"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.logical<4> {bindc_name = "y", uniq_name = "_QFmultiple_reductionsEy"} +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_10:.*]] = fir.alloca !fir.logical<4> {bindc_name = "z", uniq_name = "_QFmultiple_reductionsEz"} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFmultiple_reductionsEz"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_12:.*]] = arith.constant true +! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_12]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_7]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_14:.*]] = arith.constant true +! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_9]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_16:.*]] = arith.constant true +! CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_16]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_17]] to %[[VAL_11]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.parallel { +! CHECK: %[[VAL_18:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_19:.*]]:2 = hlfir.declare %[[VAL_18]] {uniq_name = "_QFmultiple_reductionsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_20:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_21:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_22:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@or_reduction %[[VAL_7]]#0 -> %[[VAL_23:.*]] : !fir.ref<!fir.logical<4>>, @or_reduction %[[VAL_9]]#0 -> %[[VAL_24:.*]] : !fir.ref<!fir.logical<4>>, @or_reduction %[[VAL_11]]#0 -> %[[VAL_25:.*]] : !fir.ref<!fir.logical<4>>) for (%[[VAL_26:.*]]) : i32 = (%[[VAL_20]]) to (%[[VAL_21]]) inclusive step (%[[VAL_22]]) { +! CHECK: fir.store %[[VAL_26]] to %[[VAL_19]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_23]] {uniq_name = "_QFmultiple_reductionsEx"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_28:.*]]:2 = hlfir.declare %[[VAL_24]] {uniq_name = "_QFmultiple_reductionsEy"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_29:.*]]:2 = hlfir.declare %[[VAL_25]] {uniq_name = "_QFmultiple_reductionsEz"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>) +! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_27]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_31]] : (i32) -> i64 +! CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_32]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_34:.*]] = fir.load %[[VAL_33]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_30]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_36:.*]] = fir.convert %[[VAL_34]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_37:.*]] = arith.ori %[[VAL_35]], %[[VAL_36]] : i1 +! CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_37]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_27]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_28]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> i64 +! CHECK: %[[VAL_42:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_41]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_42]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_39]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_43]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_46:.*]] = arith.ori %[[VAL_44]], %[[VAL_45]] : i1 +! CHECK: %[[VAL_47:.*]] = fir.convert %[[VAL_46]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_28]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_48:.*]] = fir.load %[[VAL_29]]#0 : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_49:.*]] = fir.load %[[VAL_19]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_50:.*]] = fir.convert %[[VAL_49]] : (i32) -> i64 +! CHECK: %[[VAL_51:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_50]]) : (!fir.ref<!fir.array<100x!fir.logical<4>>>, i64) -> !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_52:.*]] = fir.load %[[VAL_51]] : !fir.ref<!fir.logical<4>> +! CHECK: %[[VAL_53:.*]] = fir.convert %[[VAL_48]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_54:.*]] = fir.convert %[[VAL_52]] : (!fir.logical<4>) -> i1 +! CHECK: %[[VAL_55:.*]] = arith.ori %[[VAL_53]], %[[VAL_54]] : i1 +! CHECK: %[[VAL_56:.*]] = fir.convert %[[VAL_55]] : (i1) -> !fir.logical<4> +! CHECK: hlfir.assign %[[VAL_56]] to %[[VAL_29]]#0 : !fir.logical<4>, !fir.ref<!fir.logical<4>> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + + + +subroutine multiple_reductions(w) + logical :: x,y,z,w(100) + x = .true. + y = .true. + z = .true. + !$omp parallel + !$omp do reduction(.or.:x,y,z) + do i=1, 100 + x = x .or. w(i) + y = y .or. w(i) + z = z .or. w(i) + end do + !$omp end do + !$omp end parallel +end subroutine + diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-logical-or.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-logical-or.f90 index f1ae1bc687cd55972fd28968dd2b9ac80eb9f5dc..c4bf8e9d65ae7bc7d6a67d2c1443b6f54f794275 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-logical-or.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-logical-or.f90 @@ -3,7 +3,7 @@ ! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py -! CHECK-LABEL: omp.reduction.declare @or_reduction : !fir.logical<4> init { +! CHECK-LABEL: omp.declare_reduction @or_reduction : !fir.logical<4> init { ! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.logical<4>): ! CHECK: %[[VAL_1:.*]] = arith.constant false ! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]] : (i1) -> !fir.logical<4> diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-max-2-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-max-2-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..5358806cdcdec22991e6154a232201dc1eaf757f --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-max-2-byref.f90 @@ -0,0 +1,20 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction -o - %s 2>&1 | FileCheck %s + +! CHECK: omp.wsloop byref reduction(@max_byref_i32 +! CHECK: arith.cmpi sgt +! CHECK: arith.select + +module m1 + intrinsic max +end module m1 +program main + use m1, ren=>max + n=0 + !$omp parallel do reduction(ren:n) + do i=1,100 + n=max(n,i) + end do + if (n/=100) print *,101 + print *,'pass' +end program main diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-max-2.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-max-2.f90 index 1f4d61985689fc1401f81a5a93ae599f36ba26a3..abd7ca1ae555d85a4acaad882c1723b4eb7feef2 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-max-2.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-max-2.f90 @@ -1,7 +1,7 @@ ! RUN: bbc -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s ! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s -! CHECK: omp.wsloop reduction(@max_i_32 +! CHECK: omp.wsloop reduction(@max_i32 ! CHECK: arith.cmpi sgt ! CHECK: arith.select diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..ee562bbe15863e0476da7e20bb418516c3a28d9f --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-max-byref.f90 @@ -0,0 +1,152 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction -o - %s 2>&1 | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +!CHECK: omp.declare_reduction @max_byref_f32 : !fir.ref<f32> +!CHECK-SAME: init { +!CHECK: %[[MINIMUM_VAL:.*]] = arith.constant -3.40282347E+38 : f32 +!CHECK: %[[REF:.*]] = fir.alloca f32 +!CHECK: fir.store %[[MINIMUM_VAL]] to %[[REF]] : !fir.ref<f32> +!CHECK: omp.yield(%[[REF]] : !fir.ref<f32>) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<f32>, %[[ARG1:.*]]: !fir.ref<f32>): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<f32> +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<f32> +!CHECK: %[[RES:.*]] = arith.maximumf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<f32> +!CHECK: omp.yield(%[[ARG0]] : !fir.ref<f32>) + +!CHECK-LABEL: omp.declare_reduction @max_byref_i32 : !fir.ref<i32> +!CHECK-SAME: init { +!CHECK: %[[MINIMUM_VAL:.*]] = arith.constant -2147483648 : i32 +!CHECK: %[[REF:.*]] = fir.alloca i32 +!CHECK: fir.store %[[MINIMUM_VAL]] to %[[REF]] : !fir.ref<i32> +!CHECK: omp.yield(%[[REF]] : !fir.ref<i32>) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> +!CHECK: %[[RES:.*]] = arith.maxsi %[[LD0]], %[[LD1]] : i32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i32> +!CHECK: omp.yield(%[[ARG0]] : !fir.ref<i32>) + +! CHECK-LABEL: func.func @_QPreduction_max_int( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFreduction_max_intEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_max_intEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_max_intEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_max_intEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFreduction_max_intEy"} : (!fir.box<!fir.array<?xi32>>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : i32, !fir.ref<i32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFreduction_max_intEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@max_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { +! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_max_intEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64 +! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_16]]) : (!fir.box<!fir.array<?xi32>>, i64) -> !fir.ref<i32> +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_14]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_17]] : !fir.ref<i32> +! CHECK: %[[VAL_20:.*]] = arith.cmpi sgt, %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: %[[VAL_21:.*]] = arith.select %[[VAL_20]], %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: hlfir.assign %[[VAL_21]] to %[[VAL_14]]#0 : i32, !fir.ref<i32> +! CHECK: omp.yield +! CHECK: omp.terminator + +! CHECK-LABEL: func.func @_QPreduction_max_real( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFreduction_max_realEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_max_realEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFreduction_max_realEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_max_realEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFreduction_max_realEy"} : (!fir.box<!fir.array<?xf32>>) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_6:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : f32, !fir.ref<f32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFreduction_max_realEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@max_byref_f32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<f32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { +! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_max_realEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64 +! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_16]]) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32> +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]] : !fir.ref<f32> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_14]]#0 : !fir.ref<f32> +! CHECK: %[[VAL_20:.*]] = arith.cmpf ogt, %[[VAL_18]], %[[VAL_19]] fastmath<contract> : f32 +! CHECK: %[[VAL_21:.*]] = arith.select %[[VAL_20]], %[[VAL_18]], %[[VAL_19]] : f32 +! CHECK: hlfir.assign %[[VAL_21]] to %[[VAL_14]]#0 : f32, !fir.ref<f32> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: omp.parallel { +! CHECK: %[[VAL_30:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_31:.*]]:2 = hlfir.declare %[[VAL_30]] {uniq_name = "_QFreduction_max_realEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_32:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_33:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_34:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@max_byref_f32 %[[VAL_4]]#0 -> %[[VAL_35:.*]] : !fir.ref<f32>) for (%[[VAL_36:.*]]) : i32 = (%[[VAL_32]]) to (%[[VAL_33]]) inclusive step (%[[VAL_34]]) { +! CHECK: fir.store %[[VAL_36]] to %[[VAL_31]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_37:.*]]:2 = hlfir.declare %[[VAL_35]] {uniq_name = "_QFreduction_max_realEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_38:.*]] = fir.load %[[VAL_31]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_39:.*]] = fir.convert %[[VAL_38]] : (i32) -> i64 +! CHECK: %[[VAL_40:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_39]]) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32> +! CHECK: %[[VAL_41:.*]] = fir.load %[[VAL_40]] : !fir.ref<f32> +! CHECK: %[[VAL_42:.*]] = fir.load %[[VAL_37]]#0 : !fir.ref<f32> +! CHECK: %[[VAL_43:.*]] = arith.cmpf ogt, %[[VAL_41]], %[[VAL_42]] fastmath<contract> : f32 +! CHECK: fir.if %[[VAL_43]] { +! CHECK: %[[VAL_44:.*]] = fir.load %[[VAL_31]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_44]] : (i32) -> i64 +! CHECK: %[[VAL_46:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_45]]) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32> +! CHECK: %[[VAL_47:.*]] = fir.load %[[VAL_46]] : !fir.ref<f32> +! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_37]]#0 : f32, !fir.ref<f32> +! CHECK: } else { +! CHECK: } +! CHECK: omp.yield +! CHECK: omp.terminator + + + +subroutine reduction_max_int(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(max:x) + do i=1, 100 + x = max(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine + +subroutine reduction_max_real(y) + real :: x, y(:) + x = 0.0 + !$omp parallel + !$omp do reduction(max:x) + do i=1, 100 + x = max(y(i), x) + end do + !$omp end do + !$omp end parallel + print *, x + + !$omp parallel + !$omp do reduction(max:x) + do i=1, 100 + if (y(i) .gt. x) x = y(i) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-max-hlfir-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-max-hlfir-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..10bba6ac4b51bddb31ad4211103b2f2ef0ab6be2 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-max-hlfir-byref.f90 @@ -0,0 +1,62 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction -o - %s 2>&1 | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.declare_reduction @max_byref_i32 : !fir.ref<i32> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +! CHECK: %[[MINIMUM_VAL:.*]] = arith.constant -2147483648 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[MINIMUM_VAL]] to %[[REF]] : !fir.ref<i32> +! CHECK: omp.yield(%[[REF]] : !fir.ref<i32>) +! CHECK: combiner +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> +! CHECK: %[[RES:.*]] = arith.maxsi %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i32> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<i32>) + +! CHECK-LABEL: func.func @_QPreduction_max_int( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFreduction_max_intEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_max_intEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_max_intEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_max_intEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFreduction_max_intEy"} : (!fir.box<!fir.array<?xi32>>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : i32, !fir.ref<i32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFreduction_max_intEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@max_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { +! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_max_intEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64 +! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_16]]) : (!fir.box<!fir.array<?xi32>>, i64) -> !fir.ref<i32> +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_14]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_17]] : !fir.ref<i32> +! CHECK: %[[VAL_20:.*]] = arith.cmpi sgt, %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: %[[VAL_21:.*]] = arith.select %[[VAL_20]], %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: hlfir.assign %[[VAL_21]] to %[[VAL_14]]#0 : i32, !fir.ref<i32> +! CHECK: omp.yield +! CHECK: omp.terminator + + +subroutine reduction_max_int(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(max:x) + do i=1, 100 + x = max(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-max-hlfir.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-max-hlfir.f90 index ed25cedae90c62f603c533e61879d7b9f42b35c1..5ea5d6626f186d6e93f0f8e544aaab1d3163cf8b 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-max-hlfir.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-max-hlfir.f90 @@ -3,7 +3,7 @@ ! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py -! CHECK-LABEL: omp.reduction.declare @max_i_32 : i32 init { +! CHECK-LABEL: omp.declare_reduction @max_i32 : i32 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: i32): ! CHECK: %[[VAL_1:.*]] = arith.constant -2147483648 : i32 ! CHECK: omp.yield(%[[VAL_1]] : i32) @@ -29,7 +29,7 @@ ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@max_i_32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { +! CHECK: omp.wsloop reduction(@max_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { ! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_max_intEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32> diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-max.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-max.f90 index ea3b1bebce0388c39db967e570658ac4089cdf7f..6f11f0ec96a7d3536ebff20ee90401c61d03cb7d 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-max.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-max.f90 @@ -3,7 +3,7 @@ ! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py -! CHECK-LABEL: omp.reduction.declare @max_f_32 : f32 init { +! CHECK-LABEL: omp.declare_reduction @max_f32 : f32 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: f32): ! CHECK: %[[VAL_1:.*]] = arith.constant -3.40282347E+38 : f32 ! CHECK: omp.yield(%[[VAL_1]] : f32) @@ -14,7 +14,7 @@ ! CHECK: omp.yield(%[[VAL_2]] : f32) ! CHECK: } -! CHECK-LABEL: omp.reduction.declare @max_i_32 : i32 init { +! CHECK-LABEL: omp.declare_reduction @max_i32 : i32 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: i32): ! CHECK: %[[VAL_1:.*]] = arith.constant -2147483648 : i32 ! CHECK: omp.yield(%[[VAL_1]] : i32) @@ -40,7 +40,7 @@ ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@max_i_32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { +! CHECK: omp.wsloop reduction(@max_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { ! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_max_intEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32> @@ -69,7 +69,7 @@ ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@max_f_32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<f32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { +! CHECK: omp.wsloop reduction(@max_f32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<f32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { ! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_max_realEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32> @@ -88,7 +88,7 @@ ! CHECK: %[[VAL_32:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_33:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_34:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@max_f_32 %[[VAL_4]]#0 -> %[[VAL_35:.*]] : !fir.ref<f32>) for (%[[VAL_36:.*]]) : i32 = (%[[VAL_32]]) to (%[[VAL_33]]) inclusive step (%[[VAL_34]]) { +! CHECK: omp.wsloop reduction(@max_f32 %[[VAL_4]]#0 -> %[[VAL_35:.*]] : !fir.ref<f32>) for (%[[VAL_36:.*]]) : i32 = (%[[VAL_32]]) to (%[[VAL_33]]) inclusive step (%[[VAL_34]]) { ! CHECK: fir.store %[[VAL_36]] to %[[VAL_31]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_37:.*]]:2 = hlfir.declare %[[VAL_35]] {uniq_name = "_QFreduction_max_realEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_38:.*]] = fir.load %[[VAL_31]]#0 : !fir.ref<i32> diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..c0372117a03b9db5d93dd22bafbeb1323dc10a5c --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-min-byref.f90 @@ -0,0 +1,154 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction -o - %s 2>&1 | FileCheck %s + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +!CHECK: omp.declare_reduction @min_byref_f32 : !fir.ref<f32> +!CHECK-SAME: init { +!CHECK: %[[MAXIMUM_VAL:.*]] = arith.constant 3.40282347E+38 : f32 +!CHECK: %[[REF:.*]] = fir.alloca f32 +!CHECK: fir.store %[[MAXIMUM_VAL]] to %[[REF]] : !fir.ref<f32> +!CHECK: omp.yield(%[[REF]] : !fir.ref<f32>) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<f32>, %[[ARG1:.*]]: !fir.ref<f32>): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<f32> +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<f32> +!CHECK: %[[RES:.*]] = arith.minimumf %[[LD0]], %[[LD1]] {{.*}}: f32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<f32> +!CHECK: omp.yield(%[[ARG0]] : !fir.ref<f32>) + +!CHECK-LABEL: omp.declare_reduction @min_byref_i32 : !fir.ref<i32> +!CHECK-SAME: init { +!CHECK: %[[MAXIMUM_VAL:.*]] = arith.constant 2147483647 : i32 +!CHECK: %[[REF:.*]] = fir.alloca i32 +!CHECK: fir.store %[[MAXIMUM_VAL]] to %[[REF]] : !fir.ref<i32> +!CHECK: omp.yield(%[[REF]] : !fir.ref<i32>) +!CHECK: combiner +!CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): +!CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> +!CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> +!CHECK: %[[RES:.*]] = arith.minsi %[[LD0]], %[[LD1]] : i32 +!CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i32> +!CHECK: omp.yield(%[[ARG0]] : !fir.ref<i32>) + +! CHECK-LABEL: func.func @_QPreduction_min_int( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFreduction_min_intEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_min_intEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFreduction_min_intEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_min_intEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFreduction_min_intEy"} : (!fir.box<!fir.array<?xi32>>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 +! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : i32, !fir.ref<i32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFreduction_min_intEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@min_byref_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { +! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_min_intEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64 +! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_16]]) : (!fir.box<!fir.array<?xi32>>, i64) -> !fir.ref<i32> +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_14]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_17]] : !fir.ref<i32> +! CHECK: %[[VAL_20:.*]] = arith.cmpi slt, %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: %[[VAL_21:.*]] = arith.select %[[VAL_20]], %[[VAL_18]], %[[VAL_19]] : i32 +! CHECK: hlfir.assign %[[VAL_21]] to %[[VAL_14]]#0 : i32, !fir.ref<i32> +! CHECK: omp.yield +! CHECK: omp.terminator + +! CHECK-LABEL: func.func @_QPreduction_min_real( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "y"}) { +! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFreduction_min_realEi"} +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFreduction_min_realEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_3:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFreduction_min_realEx"} +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFreduction_min_realEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFreduction_min_realEy"} : (!fir.box<!fir.array<?xf32>>) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>) +! CHECK: %[[VAL_6:.*]] = arith.constant 0.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_6]] to %[[VAL_4]]#0 : f32, !fir.ref<f32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_7:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]] {uniq_name = "_QFreduction_min_realEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@min_byref_f32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<f32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { +! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_min_realEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64 +! CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_16]]) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32> +! CHECK: %[[VAL_18:.*]] = fir.load %[[VAL_17]] : !fir.ref<f32> +! CHECK: %[[VAL_19:.*]] = fir.load %[[VAL_14]]#0 : !fir.ref<f32> +! CHECK: %[[VAL_20:.*]] = arith.cmpf olt, %[[VAL_18]], %[[VAL_19]] fastmath<contract> : f32 +! CHECK: %[[VAL_21:.*]] = arith.select %[[VAL_20]], %[[VAL_18]], %[[VAL_19]] : f32 +! CHECK: hlfir.assign %[[VAL_21]] to %[[VAL_14]]#0 : f32, !fir.ref<f32> +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } +! CHECK: omp.parallel { +! CHECK: %[[VAL_30:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_31:.*]]:2 = hlfir.declare %[[VAL_30]] {uniq_name = "_QFreduction_min_realEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_32:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_33:.*]] = arith.constant 100 : i32 +! CHECK: %[[VAL_34:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@min_byref_f32 %[[VAL_4]]#0 -> %[[VAL_35:.*]] : !fir.ref<f32>) for (%[[VAL_36:.*]]) : i32 = (%[[VAL_32]]) to (%[[VAL_33]]) inclusive step (%[[VAL_34]]) { +! CHECK: fir.store %[[VAL_36]] to %[[VAL_31]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_37:.*]]:2 = hlfir.declare %[[VAL_35]] {uniq_name = "_QFreduction_min_realEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_38:.*]] = fir.load %[[VAL_31]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_39:.*]] = fir.convert %[[VAL_38]] : (i32) -> i64 +! CHECK: %[[VAL_40:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_39]]) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32> +! CHECK: %[[VAL_41:.*]] = fir.load %[[VAL_40]] : !fir.ref<f32> +! CHECK: %[[VAL_42:.*]] = fir.load %[[VAL_37]]#0 : !fir.ref<f32> +! CHECK: %[[VAL_43:.*]] = arith.cmpf ogt, %[[VAL_41]], %[[VAL_42]] fastmath<contract> : f32 +! CHECK: fir.if %[[VAL_43]] { +! CHECK: %[[VAL_44:.*]] = fir.load %[[VAL_31]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_45:.*]] = fir.convert %[[VAL_44]] : (i32) -> i64 +! CHECK: %[[VAL_46:.*]] = hlfir.designate %[[VAL_5]]#0 (%[[VAL_45]]) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32> +! CHECK: %[[VAL_47:.*]] = fir.load %[[VAL_46]] : !fir.ref<f32> +! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_37]]#0 : f32, !fir.ref<f32> +! CHECK: } else { +! CHECK: } +! CHECK: omp.yield +! CHECK: omp.terminator + + + +subroutine reduction_min_int(y) + integer :: x, y(:) + x = 0 + !$omp parallel + !$omp do reduction(min:x) + do i=1, 100 + x = min(x, y(i)) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine + +subroutine reduction_min_real(y) + real :: x, y(:) + x = 0.0 + !$omp parallel + !$omp do reduction(min:x) + do i=1, 100 + x = min(y(i), x) + end do + !$omp end do + !$omp end parallel + print *, x + + !$omp parallel + !$omp do reduction(min:x) + do i=1, 100 + if (y(i) .gt. x) x = y(i) + end do + !$omp end do + !$omp end parallel + print *, x +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-min.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-min.f90 index 3aa9001869dc5957bfbd10bbfe32667301c0ea4b..2c694f82e279a42689dcb3cfdd82952cfc9db19a 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-min.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-min.f90 @@ -3,7 +3,7 @@ ! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py -! CHECK-LABEL: omp.reduction.declare @min_f_32 : f32 init { +! CHECK-LABEL: omp.declare_reduction @min_f32 : f32 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: f32): ! CHECK: %[[VAL_1:.*]] = arith.constant 3.40282347E+38 : f32 ! CHECK: omp.yield(%[[VAL_1]] : f32) @@ -14,7 +14,7 @@ ! CHECK: omp.yield(%[[VAL_2]] : f32) ! CHECK: } -! CHECK-LABEL: omp.reduction.declare @min_i_32 : i32 init { +! CHECK-LABEL: omp.declare_reduction @min_i32 : i32 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: i32): ! CHECK: %[[VAL_1:.*]] = arith.constant 2147483647 : i32 ! CHECK: omp.yield(%[[VAL_1]] : i32) @@ -40,7 +40,7 @@ ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@min_i_32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { +! CHECK: omp.wsloop reduction(@min_i32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<i32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { ! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_min_intEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32> @@ -69,7 +69,7 @@ ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_10:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@min_f_32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<f32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { +! CHECK: omp.wsloop reduction(@min_f32 %[[VAL_4]]#0 -> %[[VAL_12:.*]] : !fir.ref<f32>) for (%[[VAL_13:.*]]) : i32 = (%[[VAL_9]]) to (%[[VAL_10]]) inclusive step (%[[VAL_11]]) { ! CHECK: fir.store %[[VAL_13]] to %[[VAL_8]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFreduction_min_realEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<i32> @@ -90,7 +90,7 @@ ! CHECK: %[[VAL_32:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_33:.*]] = arith.constant 100 : i32 ! CHECK: %[[VAL_34:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@min_f_32 %[[VAL_4]]#0 -> %[[VAL_35:.*]] : !fir.ref<f32>) for (%[[VAL_36:.*]]) : i32 = (%[[VAL_32]]) to (%[[VAL_33]]) inclusive step (%[[VAL_34]]) { +! CHECK: omp.wsloop reduction(@min_f32 %[[VAL_4]]#0 -> %[[VAL_35:.*]] : !fir.ref<f32>) for (%[[VAL_36:.*]]) : i32 = (%[[VAL_32]]) to (%[[VAL_33]]) inclusive step (%[[VAL_34]]) { ! CHECK: fir.store %[[VAL_36]] to %[[VAL_31]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_37:.*]]:2 = hlfir.declare %[[VAL_35]] {uniq_name = "_QFreduction_min_realEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_38:.*]] = fir.load %[[VAL_31]]#0 : !fir.ref<i32> diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-min2.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-min2.f90 new file mode 100644 index 0000000000000000000000000000000000000000..0138a9578206150567b90ef64afb9f8c59eaf122 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-min2.f90 @@ -0,0 +1,50 @@ +! RUN: bbc -emit-hlfir -fopenmp -o - %s | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s | FileCheck %s + +! regression test for crash + +program reduce +integer :: i = 0 +integer :: r = 0 + +!$omp parallel do reduction(min:r) +do i=0,10 + r = i +enddo +!$omp end parallel do + +print *,r + +end program + +! CHECK-LABEL: omp.declare_reduction @min_i32 : i32 init { +! CHECK: ^bb0(%[[VAL_0:.*]]: i32): +! CHECK: %[[VAL_1:.*]] = arith.constant 2147483647 : i32 +! CHECK: omp.yield(%[[VAL_1]] : i32) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32): +! CHECK: %[[VAL_2:.*]] = arith.minsi %[[VAL_0]], %[[VAL_1]] : i32 +! CHECK: omp.yield(%[[VAL_2]] : i32) +! CHECK: } + +! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce"} { +! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEi) : !fir.ref<i32> +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = fir.address_of(@_QFEr) : !fir.ref<i32> +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFEr"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: omp.parallel { +! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_6:.*]] = arith.constant 0 : i32 +! CHECK: %[[VAL_7:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop reduction(@min_i32 %[[VAL_3]]#0 -> %[[VAL_9:.*]] : !fir.ref<i32>) for (%[[VAL_10:.*]]) : i32 = (%[[VAL_6]]) to (%[[VAL_7]]) inclusive step (%[[VAL_8]]) { +! CHECK: fir.store %[[VAL_10]] to %[[VAL_5]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_9]] {uniq_name = "_QFEr"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32> +! CHECK: hlfir.assign %[[VAL_12]] to %[[VAL_11]]#0 : i32, !fir.ref<i32> +! CHECK: omp.yield +! CHECK: } +! CHECK: omp.terminator +! CHECK: } diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-mul-byref.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-mul-byref.f90 new file mode 100644 index 0000000000000000000000000000000000000000..a2829948d472a82a72a1d01d544016e82c98e57b --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-mul-byref.f90 @@ -0,0 +1,414 @@ +! RUN: bbc -emit-hlfir -fopenmp --force-byref-reduction %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --force-byref-reduction %s -o - | FileCheck %s + + +! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py + +! CHECK-LABEL: omp.declare_reduction @multiply_reduction_byref_f64 : !fir.ref<f64> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<f64>): +! CHECK: %[[VAL_1:.*]] = arith.constant 1.000000e+00 : f64 +! CHECK: %[[REF:.*]] = fir.alloca f64 +! CHECK: fir.store %[[VAL_1]] to %[[REF]] : !fir.ref<f64> +! CHECK: omp.yield(%[[REF]] : !fir.ref<f64>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<f64>, %[[ARG1:.*]]: !fir.ref<f64>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<f64> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<f64> +! CHECK: %[[RES:.*]] = arith.mulf %[[LD0]], %[[LD1]] fastmath<contract> : f64 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<f64> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<f64>) +! CHECK: } + +! CHECK-LABEL: omp.declare_reduction @multiply_reduction_byref_i64 : !fir.ref<i64> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i64>): +! CHECK: %[[VAL_1:.*]] = arith.constant 1 : i64 +! CHECK: %[[REF:.*]] = fir.alloca i64 +! CHECK: fir.store %[[VAL_1]] to %[[REF]] : !fir.ref<i64> +! CHECK: omp.yield(%[[REF]] : !fir.ref<i64>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i64>, %[[ARG1:.*]]: !fir.ref<i64>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i64> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i64> +! CHECK: %[[RES:.*]] = arith.muli %[[LD0]], %[[LD1]] : i64 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i64> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<i64>) +! CHECK: } + +! CHECK-LABEL: omp.declare_reduction @multiply_reduction_byref_f32 : !fir.ref<f32> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<f32>): +! CHECK: %[[VAL_1:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: %[[REF:.*]] = fir.alloca f32 +! CHECK: fir.store %[[VAL_1]] to %[[REF]] : !fir.ref<f32> +! CHECK: omp.yield(%[[REF]] : !fir.ref<f32>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<f32>, %[[ARG1:.*]]: !fir.ref<f32>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<f32> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<f32> +! CHECK: %[[RES:.*]] = arith.mulf %[[LD0]], %[[LD1]] fastmath<contract> : f32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<f32> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<f32>) +! CHECK: } + +! CHECK-LABEL: omp.declare_reduction @multiply_reduction_byref_i32 : !fir.ref<i32> +! CHECK-SAME: init { +! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>): +! CHECK: %[[VAL_1:.*]] = arith.constant 1 : i32 +! CHECK: %[[REF:.*]] = fir.alloca i32 +! CHECK: fir.store %[[VAL_1]] to %[[REF]] : !fir.ref<i32> +! CHECK: omp.yield(%[[REF]] : !fir.ref<i32>) + +! CHECK-LABEL: } combiner { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref<i32>, %[[ARG1:.*]]: !fir.ref<i32>): +! CHECK: %[[LD0:.*]] = fir.load %[[ARG0]] : !fir.ref<i32> +! CHECK: %[[LD1:.*]] = fir.load %[[ARG1]] : !fir.ref<i32> +! CHECK: %[[RES:.*]] = arith.muli %[[LD0]], %[[LD1]] : i32 +! CHECK: fir.store %[[RES]] to %[[ARG0]] : !fir.ref<i32> +! CHECK: omp.yield(%[[ARG0]] : !fir.ref<i32>) +! CHECK: } + +! CHECK-LABEL: func.func @_QPsimple_int_reduction() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_int_reductionEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsimple_int_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_int_reductionEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i32 +! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : i32, !fir.ref<i32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFsimple_int_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@multiply_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_15:.*]] = arith.muli %[[VAL_13]], %[[VAL_14]] : i32 +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_12]]#0 : i32, !fir.ref<i32> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_int_reduction + integer :: x + x = 1 + !$omp parallel + !$omp do reduction(*:x) + do i=1, 10 + x = x * i + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_real_reduction() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_real_reductionEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsimple_real_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFsimple_real_reductionEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsimple_real_reductionEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_4:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : f32, !fir.ref<f32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFsimple_real_reductionEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@multiply_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<f32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_real_reductionEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<f32> +! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (i32) -> f32 +! CHECK: %[[VAL_16:.*]] = arith.mulf %[[VAL_13]], %[[VAL_15]] fastmath<contract> : f32 +! CHECK: hlfir.assign %[[VAL_16]] to %[[VAL_12]]#0 : f32, !fir.ref<f32> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_real_reduction + real :: x + x = 1.0 + !$omp parallel + !$omp do reduction(*:x) + do i=1, 10 + x = x * i + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_int_reduction_switch_order() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_int_reduction_switch_orderEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsimple_int_reduction_switch_orderEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFsimple_int_reduction_switch_orderEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsimple_int_reduction_switch_orderEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]] = arith.constant 1 : i32 +! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : i32, !fir.ref<i32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFsimple_int_reduction_switch_orderEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@multiply_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reduction_switch_orderEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_15:.*]] = arith.muli %[[VAL_13]], %[[VAL_14]] : i32 +! CHECK: hlfir.assign %[[VAL_15]] to %[[VAL_12]]#0 : i32, !fir.ref<i32> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_int_reduction_switch_order + integer :: x + x = 1 + !$omp parallel + !$omp do reduction(*:x) + do i=1, 10 + x = i * x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPsimple_real_reduction_switch_order() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFsimple_real_reduction_switch_orderEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFsimple_real_reduction_switch_orderEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFsimple_real_reduction_switch_orderEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFsimple_real_reduction_switch_orderEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_4:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_3]]#0 : f32, !fir.ref<f32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFsimple_real_reduction_switch_orderEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_8:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@multiply_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<f32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_real_reduction_switch_orderEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (i32) -> f32 +! CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<f32> +! CHECK: %[[VAL_16:.*]] = arith.mulf %[[VAL_14]], %[[VAL_15]] fastmath<contract> : f32 +! CHECK: hlfir.assign %[[VAL_16]] to %[[VAL_12]]#0 : f32, !fir.ref<f32> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine simple_real_reduction_switch_order + real :: x + x = 1.0 + !$omp parallel + !$omp do reduction(*:x) + do i=1, 10 + x = i * x + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_int_reductions_same_type() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_int_reductions_same_typeEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFmultiple_int_reductions_same_typeEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFmultiple_int_reductions_same_typeEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFmultiple_int_reductions_same_typeEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFmultiple_int_reductions_same_typeEy"} +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFmultiple_int_reductions_same_typeEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_6:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFmultiple_int_reductions_same_typeEz"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_int_reductions_same_typeEz"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 +! CHECK: hlfir.assign %[[VAL_8]] to %[[VAL_3]]#0 : i32, !fir.ref<i32> +! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_5]]#0 : i32, !fir.ref<i32> +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 +! CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_7]]#0 : i32, !fir.ref<i32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_11:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QFmultiple_int_reductions_same_typeEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@multiply_reduction_byref_i32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref<i32>, @multiply_reduction_byref_i32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref<i32>, @multiply_reduction_byref_i32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref<i32>) for (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { +! CHECK: fir.store %[[VAL_19]] to %[[VAL_12]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFmultiple_int_reductions_same_typeEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFmultiple_int_reductions_same_typeEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_22:.*]]:2 = hlfir.declare %[[VAL_18]] {uniq_name = "_QFmultiple_int_reductions_same_typeEz"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_23:.*]] = fir.load %[[VAL_20]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_25:.*]] = arith.muli %[[VAL_23]], %[[VAL_24]] : i32 +! CHECK: hlfir.assign %[[VAL_25]] to %[[VAL_20]]#0 : i32, !fir.ref<i32> +! CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_21]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_27:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_28:.*]] = arith.muli %[[VAL_26]], %[[VAL_27]] : i32 +! CHECK: hlfir.assign %[[VAL_28]] to %[[VAL_21]]#0 : i32, !fir.ref<i32> +! CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_22]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_30:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_31:.*]] = arith.muli %[[VAL_29]], %[[VAL_30]] : i32 +! CHECK: hlfir.assign %[[VAL_31]] to %[[VAL_22]]#0 : i32, !fir.ref<i32> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine multiple_int_reductions_same_type + integer :: x,y,z + x = 1 + y = 1 + z = 1 + !$omp parallel + !$omp do reduction(*:x,y,z) + do i=1, 10 + x = x * i + y = y * i + z = z * i + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_real_reductions_same_type() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_real_reductions_same_typeEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFmultiple_real_reductions_same_typeEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFmultiple_real_reductions_same_typeEx"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFmultiple_real_reductions_same_typeEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_4:.*]] = fir.alloca f32 {bindc_name = "y", uniq_name = "_QFmultiple_real_reductions_same_typeEy"} +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFmultiple_real_reductions_same_typeEy"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_6:.*]] = fir.alloca f32 {bindc_name = "z", uniq_name = "_QFmultiple_real_reductions_same_typeEz"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_real_reductions_same_typeEz"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_8:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_8]] to %[[VAL_3]]#0 : f32, !fir.ref<f32> +! CHECK: %[[VAL_9:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_5]]#0 : f32, !fir.ref<f32> +! CHECK: %[[VAL_10:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_7]]#0 : f32, !fir.ref<f32> +! CHECK: omp.parallel { +! CHECK: %[[VAL_11:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_11]] {uniq_name = "_QFmultiple_real_reductions_same_typeEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_14:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@multiply_reduction_byref_f32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref<f32>, @multiply_reduction_byref_f32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref<f32>, @multiply_reduction_byref_f32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref<f32>) for (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { +! CHECK: fir.store %[[VAL_19]] to %[[VAL_12]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFmultiple_real_reductions_same_typeEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFmultiple_real_reductions_same_typeEy"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_22:.*]]:2 = hlfir.declare %[[VAL_18]] {uniq_name = "_QFmultiple_real_reductions_same_typeEz"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_23:.*]] = fir.load %[[VAL_20]]#0 : !fir.ref<f32> +! CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_24]] : (i32) -> f32 +! CHECK: %[[VAL_26:.*]] = arith.mulf %[[VAL_23]], %[[VAL_25]] fastmath<contract> : f32 +! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_20]]#0 : f32, !fir.ref<f32> +! CHECK: %[[VAL_27:.*]] = fir.load %[[VAL_21]]#0 : !fir.ref<f32> +! CHECK: %[[VAL_28:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_28]] : (i32) -> f32 +! CHECK: %[[VAL_30:.*]] = arith.mulf %[[VAL_27]], %[[VAL_29]] fastmath<contract> : f32 +! CHECK: hlfir.assign %[[VAL_30]] to %[[VAL_21]]#0 : f32, !fir.ref<f32> +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_22]]#0 : !fir.ref<f32> +! CHECK: %[[VAL_32:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_33:.*]] = fir.convert %[[VAL_32]] : (i32) -> f32 +! CHECK: %[[VAL_34:.*]] = arith.mulf %[[VAL_31]], %[[VAL_33]] fastmath<contract> : f32 +! CHECK: hlfir.assign %[[VAL_34]] to %[[VAL_22]]#0 : f32, !fir.ref<f32> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + +subroutine multiple_real_reductions_same_type + real :: x,y,z + x = 1 + y = 1 + z = 1 + !$omp parallel + !$omp do reduction(*:x,y,z) + do i=1, 10 + x = x * i + y = y * i + z = z * i + end do + !$omp end do + !$omp end parallel +end subroutine + +! CHECK-LABEL: func.func @_QPmultiple_reductions_different_type() { +! CHECK: %[[VAL_0:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFmultiple_reductions_different_typeEi"} +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFmultiple_reductions_different_typeEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_2:.*]] = fir.alloca f64 {bindc_name = "w", uniq_name = "_QFmultiple_reductions_different_typeEw"} +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] {uniq_name = "_QFmultiple_reductions_different_typeEw"} : (!fir.ref<f64>) -> (!fir.ref<f64>, !fir.ref<f64>) +! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFmultiple_reductions_different_typeEx"} +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]] {uniq_name = "_QFmultiple_reductions_different_typeEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_6:.*]] = fir.alloca i64 {bindc_name = "y", uniq_name = "_QFmultiple_reductions_different_typeEy"} +! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmultiple_reductions_different_typeEy"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_8:.*]] = fir.alloca f32 {bindc_name = "z", uniq_name = "_QFmultiple_reductions_different_typeEz"} +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFmultiple_reductions_different_typeEz"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 +! CHECK: hlfir.assign %[[VAL_10]] to %[[VAL_5]]#0 : i32, !fir.ref<i32> +! CHECK: %[[VAL_11:.*]] = arith.constant 1 : i64 +! CHECK: hlfir.assign %[[VAL_11]] to %[[VAL_7]]#0 : i64, !fir.ref<i64> +! CHECK: %[[VAL_12:.*]] = arith.constant 1.000000e+00 : f32 +! CHECK: hlfir.assign %[[VAL_12]] to %[[VAL_9]]#0 : f32, !fir.ref<f32> +! CHECK: %[[VAL_13:.*]] = arith.constant 1.000000e+00 : f64 +! CHECK: hlfir.assign %[[VAL_13]] to %[[VAL_3]]#0 : f64, !fir.ref<f64> +! CHECK: omp.parallel { +! CHECK: %[[VAL_14:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} +! CHECK: %[[VAL_15:.*]]:2 = hlfir.declare %[[VAL_14]] {uniq_name = "_QFmultiple_reductions_different_typeEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_16:.*]] = arith.constant 1 : i32 +! CHECK: %[[VAL_17:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_18:.*]] = arith.constant 1 : i32 +! CHECK: omp.wsloop byref reduction(@multiply_reduction_byref_i32 %[[VAL_5]]#0 -> %[[VAL_19:.*]] : !fir.ref<i32>, @multiply_reduction_byref_i64 %[[VAL_7]]#0 -> %[[VAL_20:.*]] : !fir.ref<i64>, @multiply_reduction_byref_f32 %[[VAL_9]]#0 -> %[[VAL_21:.*]] : !fir.ref<f32>, @multiply_reduction_byref_f64 %[[VAL_3]]#0 -> %[[VAL_22:.*]] : !fir.ref<f64>) for (%[[VAL_23:.*]]) : i32 = (%[[VAL_16]]) to (%[[VAL_17]]) inclusive step (%[[VAL_18]]) { +! CHECK: fir.store %[[VAL_23]] to %[[VAL_15]]#1 : !fir.ref<i32> +! CHECK: %[[VAL_24:.*]]:2 = hlfir.declare %[[VAL_19]] {uniq_name = "_QFmultiple_reductions_different_typeEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_25:.*]]:2 = hlfir.declare %[[VAL_20]] {uniq_name = "_QFmultiple_reductions_different_typeEy"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) +! CHECK: %[[VAL_26:.*]]:2 = hlfir.declare %[[VAL_21]] {uniq_name = "_QFmultiple_reductions_different_typeEz"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +! CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_22]] {uniq_name = "_QFmultiple_reductions_different_typeEw"} : (!fir.ref<f64>) -> (!fir.ref<f64>, !fir.ref<f64>) +! CHECK: %[[VAL_28:.*]] = fir.load %[[VAL_24]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_29:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_30:.*]] = arith.muli %[[VAL_28]], %[[VAL_29]] : i32 +! CHECK: hlfir.assign %[[VAL_30]] to %[[VAL_24]]#0 : i32, !fir.ref<i32> +! CHECK: %[[VAL_31:.*]] = fir.load %[[VAL_25]]#0 : !fir.ref<i64> +! CHECK: %[[VAL_32:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_33:.*]] = fir.convert %[[VAL_32]] : (i32) -> i64 +! CHECK: %[[VAL_34:.*]] = arith.muli %[[VAL_31]], %[[VAL_33]] : i64 +! CHECK: hlfir.assign %[[VAL_34]] to %[[VAL_25]]#0 : i64, !fir.ref<i64> +! CHECK: %[[VAL_35:.*]] = fir.load %[[VAL_26]]#0 : !fir.ref<f32> +! CHECK: %[[VAL_36:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_37:.*]] = fir.convert %[[VAL_36]] : (i32) -> f32 +! CHECK: %[[VAL_38:.*]] = arith.mulf %[[VAL_35]], %[[VAL_37]] fastmath<contract> : f32 +! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_26]]#0 : f32, !fir.ref<f32> +! CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_27]]#0 : !fir.ref<f64> +! CHECK: %[[VAL_40:.*]] = fir.load %[[VAL_15]]#0 : !fir.ref<i32> +! CHECK: %[[VAL_41:.*]] = fir.convert %[[VAL_40]] : (i32) -> f64 +! CHECK: %[[VAL_42:.*]] = arith.mulf %[[VAL_39]], %[[VAL_41]] fastmath<contract> : f64 +! CHECK: hlfir.assign %[[VAL_42]] to %[[VAL_27]]#0 : f64, !fir.ref<f64> +! CHECK: omp.yield +! CHECK: omp.terminator +! CHECK: return + + +subroutine multiple_reductions_different_type + integer :: x + integer(kind=8) :: y + real :: z + real(kind=8) :: w + x = 1 + y = 1 + z = 1 + w = 1 + !$omp parallel + !$omp do reduction(*:x,y,z,w) + do i=1, 10 + x = x * i + y = y * i + z = z * i + w = w * i + end do + !$omp end do + !$omp end parallel +end subroutine diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-mul.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-mul.f90 index 4774fba3f33e965ee4a7af15222039bc9a6a6b75..90d9aa5e839bde13001e2f388ea9728c67e935fb 100644 --- a/flang/test/Lower/OpenMP/wsloop-reduction-mul.f90 +++ b/flang/test/Lower/OpenMP/wsloop-reduction-mul.f90 @@ -4,8 +4,7 @@ ! NOTE: Assertions have been autogenerated by utils/generate-test-checks.py -! CHECK-LABEL: omp.reduction.declare @multiply_reduction_f_64 : f64 init { -! CHECK: ^bb0(%[[VAL_0:.*]]: f64): +! CHECK-LABEL: omp.declare_reduction @multiply_reduction_f64 : f64 init { ! CHECK: %[[VAL_1:.*]] = arith.constant 1.000000e+00 : f64 ! CHECK: omp.yield(%[[VAL_1]] : f64) @@ -15,7 +14,7 @@ ! CHECK: omp.yield(%[[VAL_2]] : f64) ! CHECK: } -! CHECK-LABEL: omp.reduction.declare @multiply_reduction_i_64 : i64 init { +! CHECK-LABEL: omp.declare_reduction @multiply_reduction_i64 : i64 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: i64): ! CHECK: %[[VAL_1:.*]] = arith.constant 1 : i64 ! CHECK: omp.yield(%[[VAL_1]] : i64) @@ -26,7 +25,7 @@ ! CHECK: omp.yield(%[[VAL_2]] : i64) ! CHECK: } -! CHECK-LABEL: omp.reduction.declare @multiply_reduction_f_32 : f32 init { +! CHECK-LABEL: omp.declare_reduction @multiply_reduction_f32 : f32 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: f32): ! CHECK: %[[VAL_1:.*]] = arith.constant 1.000000e+00 : f32 ! CHECK: omp.yield(%[[VAL_1]] : f32) @@ -37,7 +36,7 @@ ! CHECK: omp.yield(%[[VAL_2]] : f32) ! CHECK: } -! CHECK-LABEL: omp.reduction.declare @multiply_reduction_i_32 : i32 init { +! CHECK-LABEL: omp.declare_reduction @multiply_reduction_i32 : i32 init { ! CHECK: ^bb0(%[[VAL_0:.*]]: i32): ! CHECK: %[[VAL_1:.*]] = arith.constant 1 : i32 ! CHECK: omp.yield(%[[VAL_1]] : i32) @@ -61,7 +60,7 @@ ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 10 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@multiply_reduction_i_32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: omp.wsloop reduction(@multiply_reduction_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { ! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reductionEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<i32> @@ -97,7 +96,7 @@ end subroutine ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 10 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@multiply_reduction_f_32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<f32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: omp.wsloop reduction(@multiply_reduction_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<f32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { ! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_real_reductionEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_12]]#0 : !fir.ref<f32> @@ -134,7 +133,7 @@ end subroutine ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 10 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@multiply_reduction_i_32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: omp.wsloop reduction(@multiply_reduction_i32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<i32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { ! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_int_reduction_switch_orderEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32> @@ -170,7 +169,7 @@ end subroutine ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_8:.*]] = arith.constant 10 : i32 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@multiply_reduction_f_32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<f32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { +! CHECK: omp.wsloop reduction(@multiply_reduction_f32 %[[VAL_3]]#0 -> %[[VAL_10:.*]] : !fir.ref<f32>) for (%[[VAL_11:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { ! CHECK: fir.store %[[VAL_11]] to %[[VAL_6]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_12:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFsimple_real_reduction_switch_orderEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<i32> @@ -215,7 +214,7 @@ end subroutine ! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_14:.*]] = arith.constant 10 : i32 ! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@multiply_reduction_i_32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref<i32>, @multiply_reduction_i_32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref<i32>, @multiply_reduction_i_32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref<i32>) for (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { +! CHECK: omp.wsloop reduction(@multiply_reduction_i32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref<i32>, @multiply_reduction_i32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref<i32>, @multiply_reduction_i32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref<i32>) for (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { ! CHECK: fir.store %[[VAL_19]] to %[[VAL_12]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFmultiple_int_reductions_same_typeEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFmultiple_int_reductions_same_typeEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) @@ -273,7 +272,7 @@ end subroutine ! CHECK: %[[VAL_13:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_14:.*]] = arith.constant 10 : i32 ! CHECK: %[[VAL_15:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@multiply_reduction_f_32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref<f32>, @multiply_reduction_f_32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref<f32>, @multiply_reduction_f_32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref<f32>) for (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { +! CHECK: omp.wsloop reduction(@multiply_reduction_f32 %[[VAL_3]]#0 -> %[[VAL_16:.*]] : !fir.ref<f32>, @multiply_reduction_f32 %[[VAL_5]]#0 -> %[[VAL_17:.*]] : !fir.ref<f32>, @multiply_reduction_f32 %[[VAL_7]]#0 -> %[[VAL_18:.*]] : !fir.ref<f32>) for (%[[VAL_19:.*]]) : i32 = (%[[VAL_13]]) to (%[[VAL_14]]) inclusive step (%[[VAL_15]]) { ! CHECK: fir.store %[[VAL_19]] to %[[VAL_12]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_16]] {uniq_name = "_QFmultiple_real_reductions_same_typeEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) ! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = "_QFmultiple_real_reductions_same_typeEy"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) @@ -338,7 +337,7 @@ end subroutine ! CHECK: %[[VAL_16:.*]] = arith.constant 1 : i32 ! CHECK: %[[VAL_17:.*]] = arith.constant 10 : i32 ! CHECK: %[[VAL_18:.*]] = arith.constant 1 : i32 -! CHECK: omp.wsloop reduction(@multiply_reduction_i_32 %[[VAL_5]]#0 -> %[[VAL_19:.*]] : !fir.ref<i32>, @multiply_reduction_i_64 %[[VAL_7]]#0 -> %[[VAL_20:.*]] : !fir.ref<i64>, @multiply_reduction_f_32 %[[VAL_9]]#0 -> %[[VAL_21:.*]] : !fir.ref<f32>, @multiply_reduction_f_64 %[[VAL_3]]#0 -> %[[VAL_22:.*]] : !fir.ref<f64>) for (%[[VAL_23:.*]]) : i32 = (%[[VAL_16]]) to (%[[VAL_17]]) inclusive step (%[[VAL_18]]) { +! CHECK: omp.wsloop reduction(@multiply_reduction_i32 %[[VAL_5]]#0 -> %[[VAL_19:.*]] : !fir.ref<i32>, @multiply_reduction_i64 %[[VAL_7]]#0 -> %[[VAL_20:.*]] : !fir.ref<i64>, @multiply_reduction_f32 %[[VAL_9]]#0 -> %[[VAL_21:.*]] : !fir.ref<f32>, @multiply_reduction_f64 %[[VAL_3]]#0 -> %[[VAL_22:.*]] : !fir.ref<f64>) for (%[[VAL_23:.*]]) : i32 = (%[[VAL_16]]) to (%[[VAL_17]]) inclusive step (%[[VAL_18]]) { ! CHECK: fir.store %[[VAL_23]] to %[[VAL_15]]#1 : !fir.ref<i32> ! CHECK: %[[VAL_24:.*]]:2 = hlfir.declare %[[VAL_19]] {uniq_name = "_QFmultiple_reductions_different_typeEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) ! CHECK: %[[VAL_25:.*]]:2 = hlfir.declare %[[VAL_20]] {uniq_name = "_QFmultiple_reductions_different_typeEy"} : (!fir.ref<i64>) -> (!fir.ref<i64>, !fir.ref<i64>) diff --git a/flang/test/Lower/OpenMP/wsloop-reduction-multi.f90 b/flang/test/Lower/OpenMP/wsloop-reduction-multi.f90 new file mode 100644 index 0000000000000000000000000000000000000000..9e9951c399c9205e65278f0e8d514f8c7ad360b7 --- /dev/null +++ b/flang/test/Lower/OpenMP/wsloop-reduction-multi.f90 @@ -0,0 +1,81 @@ +! RUN: bbc -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s + +!CHECK-LABEL: omp.declare_reduction +!CHECK-SAME: @[[MIN_RED_I32_NAME:.*]] : i32 init { +!CHECK: ^bb0(%{{.*}}: i32): +!CHECK: %[[C0_1:.*]] = arith.constant 2147483647 : i32 +!CHECK: omp.yield(%[[C0_1]] : i32) +!CHECK: } combiner { +!CHECK: ^bb0(%[[ARG0:.*]]: i32, %[[ARG1:.*]]: i32): +!CHECK: %[[RES:.*]] = arith.minsi %[[ARG0]], %[[ARG1]] : i32 +!CHECK: omp.yield(%[[RES]] : i32) +!CHECK: } + +!CHECK-LABEL: omp.declare_reduction +!CHECK-SAME: @[[ADD_RED_F32_NAME:.*]] : f32 init { +!CHECK: ^bb0(%{{.*}}: f32): +!CHECK: %[[C0_1:.*]] = arith.constant 0.000000e+00 : f32 +!CHECK: omp.yield(%[[C0_1]] : f32) +!CHECK: } combiner { +!CHECK: ^bb0(%[[ARG0:.*]]: f32, %[[ARG1:.*]]: f32): +!CHECK: %[[RES:.*]] = arith.addf %[[ARG0]], %[[ARG1]] {{.*}} : f32 +!CHECK: omp.yield(%[[RES]] : f32) +!CHECK: } + +!CHECK-LABEL: omp.declare_reduction +!CHECK-SAME: @[[ADD_RED_I32_NAME:.*]] : i32 init { +!CHECK: ^bb0(%{{.*}}: i32): +!CHECK: %[[C0_1:.*]] = arith.constant 0 : i32 +!CHECK: omp.yield(%[[C0_1]] : i32) +!CHECK: } combiner { +!CHECK: ^bb0(%[[ARG0:.*]]: i32, %[[ARG1:.*]]: i32): +!CHECK: %[[RES:.*]] = arith.addi %[[ARG0]], %[[ARG1]] : i32 +!CHECK: omp.yield(%[[RES]] : i32) +!CHECK: } + +!CHECK-LABEL: func.func @_QPmultiple_reduction +!CHECK: %[[X_REF:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFmultiple_reductionEx"} +!CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X_REF]] {uniq_name = "_QFmultiple_reductionEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[Y_REF:.*]] = fir.alloca f32 {bindc_name = "y", uniq_name = "_QFmultiple_reductionEy"} +!CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y_REF]] {uniq_name = "_QFmultiple_reductionEy"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +!CHECK: %[[Z_REF:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFmultiple_reductionEz"} +!CHECK: %[[Z_DECL:.*]]:2 = hlfir.declare %[[Z_REF]] {uniq_name = "_QFmultiple_reductionEz"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: omp.wsloop reduction( +!CHECK-SAME: @[[ADD_RED_I32_NAME]] %[[X_DECL]]#0 -> %[[PRV_X:.+]] : !fir.ref<i32>, +!CHECK-SAME: @[[ADD_RED_F32_NAME]] %[[Y_DECL]]#0 -> %[[PRV_Y:.+]] : !fir.ref<f32>, +!CHECK-SAME: @[[MIN_RED_I32_NAME]] %[[Z_DECL]]#0 -> %[[PRV_Z:.+]] : !fir.ref<i32>) {{.*}}{ +!CHECK: %[[PRV_X_DECL:.+]]:2 = hlfir.declare %[[PRV_X]] {{.*}} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[PRV_Y_DECL:.+]]:2 = hlfir.declare %[[PRV_Y]] {{.*}} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>) +!CHECK: %[[PRV_Z_DECL:.+]]:2 = hlfir.declare %[[PRV_Z]] {{.*}} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +!CHECK: %[[LPRV_X:.+]] = fir.load %[[PRV_X_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[RES_X:.+]] = arith.addi %[[LPRV_X]], %{{.+}} : i32 +!CHECK: hlfir.assign %[[RES_X]] to %[[PRV_X_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: %[[LPRV_Y:.+]] = fir.load %[[PRV_Y_DECL]]#0 : !fir.ref<f32> +!CHECK: %[[RES_Y:.+]] = arith.addf %[[LPRV_Y]], %{{.+}} : f32 +!CHECK: hlfir.assign %[[RES_Y]] to %[[PRV_Y_DECL]]#0 : f32, !fir.ref<f32> +!CHECK: %[[LPRV_Z:.+]] = fir.load %[[PRV_Z_DECL]]#0 : !fir.ref<i32> +!CHECK: %[[RES_Z:.+]] = arith.select %{{.+}}, %[[LPRV_Z]], %{{.+}} : i32 +!CHECK: hlfir.assign %[[RES_Z]] to %[[PRV_Z_DECL]]#0 : i32, !fir.ref<i32> +!CHECK: omp.yield +!CHECK: } +!CHECK: return +subroutine multiple_reduction(v) + implicit none + integer, intent(in) :: v(:) + integer :: i + integer :: x + real :: y + integer:: z + x = 0 + y = 0.0 + z = 10 + + !$omp do reduction(+:x,y) reduction(min:z) + do i=1, 100 + x = x + v(i) + y = y + 1.5 * v(i) + z = min(z, v(i)) + end do + !$omp end do +end subroutine diff --git a/flang/test/Lower/allocatable-polymorphic.f90 b/flang/test/Lower/allocatable-polymorphic.f90 index 6ba0b13b24b6c483126e73849fc6fb91ae110553..10d7d957a257328172e7fbfd97cbb7079ade18e6 100644 --- a/flang/test/Lower/allocatable-polymorphic.f90 +++ b/flang/test/Lower/allocatable-polymorphic.f90 @@ -1,5 +1,5 @@ -! RUN: bbc --use-desc-for-alloc=false -polymorphic-type -emit-hlfir %s -o - | FileCheck %s -! RUN: bbc --use-desc-for-alloc=false -polymorphic-type -emit-hlfir %s -o - | tco | FileCheck %s --check-prefix=LLVM +! RUN: bbc --use-desc-for-alloc=false -emit-hlfir %s -o - | FileCheck %s +! RUN: bbc --use-desc-for-alloc=false -emit-hlfir %s -o - | tco | FileCheck %s --check-prefix=LLVM module poly type p1 diff --git a/flang/test/Lower/allocatable-return.f90 b/flang/test/Lower/allocatable-return.f90 index 92c5f8ad78d7cf59459fbc573b6555496a39931d..363d16237b9bfece687710e087fb9add7b889f38 100644 --- a/flang/test/Lower/allocatable-return.f90 +++ b/flang/test/Lower/allocatable-return.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -emit-fir -hlfir=false --polymorphic-type -I nowhere %s -o - | FileCheck %s +! RUN: bbc -emit-fir -hlfir=false -I nowhere %s -o - | FileCheck %s ! Test allocatable return. ! Allocatable arrays must have default runtime lbounds after the return. diff --git a/flang/test/Lower/assumed-type.f90 b/flang/test/Lower/assumed-type.f90 index 99472a255adb730dd6dabd7cc31bff72ca4bf646..44ce41d757379074cf3b529c2d11944d9911f1bf 100644 --- a/flang/test/Lower/assumed-type.f90 +++ b/flang/test/Lower/assumed-type.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -polymorphic-type -emit-fir -hlfir=false %s -o - | FileCheck %s +! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s module assumed_type_test diff --git a/flang/test/Lower/cray-pointer.f90 b/flang/test/Lower/cray-pointer.f90 index 4e9f49daab4e996b06567636fe86bbc47dff845a..06910bce35a144ab95e40d215e4e90e8270399b0 100644 --- a/flang/test/Lower/cray-pointer.f90 +++ b/flang/test/Lower/cray-pointer.f90 @@ -264,8 +264,8 @@ subroutine cray_array() ! CHECK: %[[data:.*]] = fir.alloca !fir.array<5xi32> {{.*}} ! CHECK: %[[c3:.*]] = arith.constant 3 : index ! CHECK: %[[k:.*]] = fir.alloca !fir.array<3xi32> {{.*}} -! CHECK: %[[c31:.*]] = arith.constant 3 : index ! CHECK: %[[ptr:.*]] = fir.alloca i64 {{.*}} +! CHECK: %[[c31:.*]] = arith.constant 3 : index ! CHECK: %[[c2:.*]] = arith.constant 2 : i64 ! CHECK: %[[c1:.*]] = arith.constant 1 : i64 ! CHECK: %[[sub:.*]] = arith.subi %[[c2]], %[[c1]] : i64 @@ -327,8 +327,8 @@ subroutine cray_arraySection() ! CHECK: %[[data:.*]] = fir.alloca !fir.array<5xi32> {{.*}} ! CHECK: %[[c2:.*]] = arith.constant 2 : index ! CHECK: %[[k:.*]] = fir.alloca !fir.array<2xi32> {{.*}} -! CHECK: %[[c3:.*]] = arith.constant 3 : index ! CHECK: %[[ptr:.*]] = fir.alloca i64 {{.*}} +! CHECK: %[[c3:.*]] = arith.constant 3 : index ! CHECK: %[[c1:.*]] = arith.constant 2 : i64 ! CHECK: %[[c0:.*]] = arith.constant 1 : i64 ! CHECK: %[[sub:.*]] = arith.subi %[[c1]], %[[c0]] : i64 diff --git a/flang/test/Lower/default-initialization.f90 b/flang/test/Lower/default-initialization.f90 index e692b9b08446ea5c186ca6d1c8df102b757c70f0..7a6133452b3a25756d9dcf1c919775a3683797bd 100644 --- a/flang/test/Lower/default-initialization.f90 +++ b/flang/test/Lower/default-initialization.f90 @@ -1,5 +1,5 @@ ! Test default initialization of local and dummy variables (dynamic initialization) -! RUN: bbc -emit-fir -hlfir=false -polymorphic-type %s -o - | FileCheck %s +! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s module test_dinit type t diff --git a/flang/test/Lower/derived-type-finalization.f90 b/flang/test/Lower/derived-type-finalization.f90 index 5c4531884213d23a4be756ed85c8a67ce8b0f41e..e7ade0d8145bb63ef48acebcd60d6d35f9808a14 100644 --- a/flang/test/Lower/derived-type-finalization.f90 +++ b/flang/test/Lower/derived-type-finalization.f90 @@ -1,5 +1,5 @@ ! Test derived type finalization -! RUN: bbc --use-desc-for-alloc=false -polymorphic-type -emit-fir -hlfir=false %s -o - | FileCheck %s +! RUN: bbc --use-desc-for-alloc=false -emit-fir -hlfir=false %s -o - | FileCheck %s ! Missing tests: ! - finalization within BLOCK construct diff --git a/flang/test/Lower/dispatch-table.f90 b/flang/test/Lower/dispatch-table.f90 index 0df4981b3eaf86fa0c15a99f5ce3535830c4b1f1..023dbcbedeaf490651978cdc1ec784e5522d72b7 100644 --- a/flang/test/Lower/dispatch-table.f90 +++ b/flang/test/Lower/dispatch-table.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -polymorphic-type -emit-fir %s -o - | FileCheck %s +! RUN: bbc -emit-fir %s -o - | FileCheck %s ! Tests the generation of fir.type_info operations. diff --git a/flang/test/Lower/dispatch.f90 b/flang/test/Lower/dispatch.f90 index 1aad4a4b8e46f5704a1624a7ee444713a2b520a2..60364076e633bf883125c5f970f30ba097df35b5 100644 --- a/flang/test/Lower/dispatch.f90 +++ b/flang/test/Lower/dispatch.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -polymorphic-type -emit-hlfir %s -o - | FileCheck %s +! RUN: bbc -emit-hlfir %s -o - | FileCheck %s ! Tests the different possible type involving polymorphic entities. diff --git a/flang/test/Lower/intentout-deallocate.f90 b/flang/test/Lower/intentout-deallocate.f90 index 30502fd5d722abbda1767bfca0f89ad87c46762e..8e7ccbcc9fdb9d119e0a06bc96a4c5d41b7ef6be 100644 --- a/flang/test/Lower/intentout-deallocate.f90 +++ b/flang/test/Lower/intentout-deallocate.f90 @@ -1,6 +1,6 @@ ! Test correct deallocation of intent(out) allocatables. -! RUN: bbc --use-desc-for-alloc=false -emit-fir -hlfir=false -polymorphic-type %s -o - | FileCheck %s --check-prefixes=CHECK,FIR -! RUN: bbc -emit-hlfir -polymorphic-type %s -o - -I nw | FileCheck %s --check-prefixes=CHECK,HLFIR +! RUN: bbc --use-desc-for-alloc=false -emit-fir -hlfir=false %s -o - | FileCheck %s --check-prefixes=CHECK,FIR +! RUN: bbc -emit-hlfir %s -o - -I nw | FileCheck %s --check-prefixes=CHECK,HLFIR module mod1 type, bind(c) :: t1 diff --git a/flang/test/Lower/io-derived-type-2.f90 b/flang/test/Lower/io-derived-type-2.f90 index c2f1ff1850725daf820f7de861ca366be3756ca6..eeea2ae156f945ca9a7f552b990ca3c22c62e80a 100644 --- a/flang/test/Lower/io-derived-type-2.f90 +++ b/flang/test/Lower/io-derived-type-2.f90 @@ -1,6 +1,6 @@ ! Check that InputDerivedType/OutputDeriverType APIs are used ! for io of derived types. -! RUN: bbc -polymorphic-type -emit-fir -o - %s | FileCheck %s +! RUN: bbc -emit-fir -o - %s | FileCheck %s module p type :: person diff --git a/flang/test/Lower/io-derived-type.f90 b/flang/test/Lower/io-derived-type.f90 index 84f57f46289bd9ed20ae0b8aaccede4fe7fed5b0..08b1207f55ad1ab94c8498c537484d882325dc30 100644 --- a/flang/test/Lower/io-derived-type.f90 +++ b/flang/test/Lower/io-derived-type.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -polymorphic-type -emit-fir -hlfir=false -o - %s | FileCheck %s +! RUN: bbc -emit-fir -hlfir=false -o - %s | FileCheck %s module m type t diff --git a/flang/test/Lower/nullify-polymorphic.f90 b/flang/test/Lower/nullify-polymorphic.f90 index ee271b815bdd52901223cf2b43c02b8789f0f1ca..5cb966810f1b9229b7624df6ca06ec06222fa66d 100644 --- a/flang/test/Lower/nullify-polymorphic.f90 +++ b/flang/test/Lower/nullify-polymorphic.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -polymorphic-type -emit-hlfir %s -o - | FileCheck %s +! RUN: bbc -emit-hlfir %s -o - | FileCheck %s module poly type p1 diff --git a/flang/test/Lower/pass-null-for-class-arg.f90 b/flang/test/Lower/pass-null-for-class-arg.f90 index d3d657f29a36cd31fa17d3af5bf292066e9ca915..f60cad30b1bf69ffaf6eeb27082b6935856f5c68 100644 --- a/flang/test/Lower/pass-null-for-class-arg.f90 +++ b/flang/test/Lower/pass-null-for-class-arg.f90 @@ -1,5 +1,5 @@ -! RUN: bbc -emit-fir -polymorphic-type %s -o - | FileCheck %s --check-prefix=FIR -! RUN: bbc -emit-fir -polymorphic-type -hlfir %s -o - | FileCheck %s --check-prefix=HLFIR +! RUN: bbc -emit-fir %s -o - | FileCheck %s --check-prefix=FIR +! RUN: bbc -emit-fir -hlfir %s -o - | FileCheck %s --check-prefix=HLFIR subroutine test interface diff --git a/flang/test/Lower/pointer-association-polymorphic.f90 b/flang/test/Lower/pointer-association-polymorphic.f90 index bde96429c0ee958181ae11dac9736e5c0cb445d0..6c56db892d1b8e4132f9351725f6453b7da60d50 100644 --- a/flang/test/Lower/pointer-association-polymorphic.f90 +++ b/flang/test/Lower/pointer-association-polymorphic.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -polymorphic-type -emit-fir -hlfir=false %s -o - | FileCheck %s +! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s module poly type p1 diff --git a/flang/test/Lower/pointer-disassociate.f90 b/flang/test/Lower/pointer-disassociate.f90 index 8d7190583165548b3e08850e5880f18dd1a8ec04..e341bca5cd89b3325dd008ff7479793a6b002950 100644 --- a/flang/test/Lower/pointer-disassociate.f90 +++ b/flang/test/Lower/pointer-disassociate.f90 @@ -1,5 +1,5 @@ ! Test lowering of pointer disassociation -! RUN: bbc -emit-fir -hlfir=false --polymorphic-type %s -o - | FileCheck %s +! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s ! ----------------------------------------------------------------------------- diff --git a/flang/test/Lower/polymorphic-temp.f90 b/flang/test/Lower/polymorphic-temp.f90 index 46cf14dcf93f4a1b6b640cf41c7927643012540e..8633620e8430e16c0e4d1b1738853921c24dbb2e 100644 --- a/flang/test/Lower/polymorphic-temp.f90 +++ b/flang/test/Lower/polymorphic-temp.f90 @@ -1,5 +1,5 @@ ! Test creation of temporary from polymorphic enities -! RUN: bbc -polymorphic-type -emit-fir -hlfir=false %s -o - | FileCheck %s +! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s module poly_tmp type p1 diff --git a/flang/test/Lower/polymorphic-types.f90 b/flang/test/Lower/polymorphic-types.f90 index 0288fea6eb38b7909d7e1dd7401fd82b2ca382c2..a06e0a29b6ae843fbcd2262bb66ca3b70d61fdad 100644 --- a/flang/test/Lower/polymorphic-types.f90 +++ b/flang/test/Lower/polymorphic-types.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -polymorphic-type -emit-fir -hlfir=false %s -o - | FileCheck %s +! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s ! Tests the different possible type involving polymorphic entities. diff --git a/flang/test/Lower/polymorphic.f90 b/flang/test/Lower/polymorphic.f90 index 15d8a86e4ef47cc66a9f4485206be7f9b9d6ae15..e031b4805dc5b1353460d111b71f818bbcf696a6 100644 --- a/flang/test/Lower/polymorphic.f90 +++ b/flang/test/Lower/polymorphic.f90 @@ -1,4 +1,4 @@ -! RUN: bbc --use-desc-for-alloc=false -polymorphic-type -emit-fir -hlfir=false %s -o - | FileCheck %s +! RUN: bbc --use-desc-for-alloc=false -emit-fir -hlfir=false %s -o - | FileCheck %s ! Tests various aspect of the lowering of polymorphic entities. diff --git a/flang/test/Lower/select-type-2.f90 b/flang/test/Lower/select-type-2.f90 index 3769132b01c1fb746717acad181a2890587f3bf0..7b4cf96069e53da8fe08803fa365ef52709c0592 100644 --- a/flang/test/Lower/select-type-2.f90 +++ b/flang/test/Lower/select-type-2.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -polymorphic-type -emit-fir -hlfir=false %s -o - | fir-opt --fir-polymorphic-op | FileCheck %s +! RUN: bbc -emit-fir -hlfir=false %s -o - | fir-opt --fir-polymorphic-op | FileCheck %s module select_type_2 type p1 integer :: a diff --git a/flang/test/Lower/select-type.f90 b/flang/test/Lower/select-type.f90 index ef91fb913a1c867d7fffe7fc10ea26f92b09d8b6..3243a813e9d59fc4334cdfcb5f6ba96e1179a621 100644 --- a/flang/test/Lower/select-type.f90 +++ b/flang/test/Lower/select-type.f90 @@ -1,5 +1,5 @@ -! RUN: bbc -polymorphic-type -emit-fir -hlfir=false %s -o - | FileCheck %s -! RUN: bbc -polymorphic-type -emit-fir -hlfir=false %s -o - | fir-opt --fir-polymorphic-op | FileCheck --check-prefix=CFG %s +! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s +! RUN: bbc -emit-fir -hlfir=false %s -o - | fir-opt --fir-polymorphic-op | FileCheck --check-prefix=CFG %s module select_type_lower_test type p1 integer :: a diff --git a/flang/test/Parser/OpenMP/allocate-tree-spec-part.f90 b/flang/test/Parser/OpenMP/allocate-tree-spec-part.f90 index 45a693d2cb0490dc825e87c474e2c1cea1640274..ab56b98b5783b35901429fb77eb26dfc26421431 100644 --- a/flang/test/Parser/OpenMP/allocate-tree-spec-part.f90 +++ b/flang/test/Parser/OpenMP/allocate-tree-spec-part.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %flang_fc1 -fopenmp -fdebug-dump-parse-tree %s | FileCheck %s ! Ensures associated declarative OMP allocations in the specification ! part are kept there diff --git a/flang/test/Parser/OpenMP/allocate-tree.f90 b/flang/test/Parser/OpenMP/allocate-tree.f90 index f04e431e74ae5d4d0fcd8375fe3f0e4350b529e4..02393a536cf47728a93c47c1a41468d552203172 100644 --- a/flang/test/Parser/OpenMP/allocate-tree.f90 +++ b/flang/test/Parser/OpenMP/allocate-tree.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %flang_fc1 -fopenmp -fdebug-dump-parse-tree %s | FileCheck %s ! RUN: %flang_fc1 -fopenmp -fdebug-unparse %s | FileCheck %s --check-prefix="UNPARSE" ! Ensures associated declarative OMP allocations are nested in their @@ -36,8 +38,8 @@ end program allocate_tree !CHECK-NEXT: | | | | | Designator -> DataRef -> Name = !CHECK-NEXT: | | | AllocateStmt -!UNPARSE: !$OMP ALLOCATE (w) ALLOCATOR(1_4) -!UNPARSE-NEXT: !$OMP ALLOCATE (xarray) ALLOCATOR(1_4) -!UNPARSE-NEXT: !$OMP ALLOCATE (zarray) ALLOCATOR(1_4) +!UNPARSE: !$OMP ALLOCATE (w) ALLOCATOR(3_8) +!UNPARSE-NEXT: !$OMP ALLOCATE (xarray) ALLOCATOR(2_8) +!UNPARSE-NEXT: !$OMP ALLOCATE (zarray) ALLOCATOR(1_8) !UNPARSE-NEXT: !$OMP ALLOCATE !UNPARSE-NEXT: ALLOCATE(w, xarray(4_4), zarray(t,z)) diff --git a/flang/test/Parser/OpenMP/target_device_parse.f90 b/flang/test/Parser/OpenMP/target_device_parse.f90 index 1867c2f2a86c6f6b82226ad122fdbfc7b7d5d1ed..dace34b6ec32f6f87fd3c3a33531faebd7c29e84 100644 --- a/flang/test/Parser/OpenMP/target_device_parse.f90 +++ b/flang/test/Parser/OpenMP/target_device_parse.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %flang_fc1 -fdebug-unparse-no-sema -fopenmp %s | FileCheck --ignore-case %s ! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s ! Checks the parsing of Openmp 5.0 Target Device constructs diff --git a/flang/test/Parser/cuf-sanity-tree.CUF b/flang/test/Parser/cuf-sanity-tree.CUF index f6cf9bbdd6b0ccdb5e842b8060d033a6d37e5224..dc12759d3ce52fa05dfd538e2fc6f09482538f3d 100644 --- a/flang/test/Parser/cuf-sanity-tree.CUF +++ b/flang/test/Parser/cuf-sanity-tree.CUF @@ -144,11 +144,11 @@ include "cuf-sanity-common" !CHECK: | | | | | | EndDoStmt -> !CHECK: | | | | ExecutionPartConstruct -> ExecutableConstruct -> CUFKernelDoConstruct !CHECK: | | | | | Directive -!CHECK: | | | | | | Scalar -> Integer -> Expr = '1_4' +!CHECK: | | | | | | StarOrExpr -> Scalar -> Integer -> Expr = '1_4' !CHECK: | | | | | | | LiteralConstant -> IntLiteralConstant = '1' -!CHECK: | | | | | | Scalar -> Integer -> Expr = '2_4' +!CHECK: | | | | | | StarOrExpr -> Scalar -> Integer -> Expr = '2_4' !CHECK: | | | | | | | LiteralConstant -> IntLiteralConstant = '2' -!CHECK: | | | | | | Scalar -> Integer -> Expr = '3_4' +!CHECK: | | | | | | StarOrExpr -> Scalar -> Integer -> Expr = '3_4' !CHECK: | | | | | | | LiteralConstant -> IntLiteralConstant = '3' !CHECK: | | | | | | Scalar -> Integer -> Expr = '1_4' !CHECK: | | | | | | | LiteralConstant -> IntLiteralConstant = '1' diff --git a/flang/test/Parser/unrecognized-dir.f90 b/flang/test/Parser/unrecognized-dir.f90 new file mode 100644 index 0000000000000000000000000000000000000000..ba6fff7562e2d52c28edf1e578f4dc3b5d08934b --- /dev/null +++ b/flang/test/Parser/unrecognized-dir.f90 @@ -0,0 +1,4 @@ +! RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s +!CHECK: warning: Compiler directive was ignored +!DIR$ Not a recognized directive +end diff --git a/flang/test/Semantics/OpenMP/allocate-clause01.f90 b/flang/test/Semantics/OpenMP/allocate-clause01.f90 index 7e2f64397f738dc24fb5ad23ab6e736472b993f0..e059a4a61a90f380e4d11d518c66d0dec136dd4e 100644 --- a/flang/test/Semantics/OpenMP/allocate-clause01.f90 +++ b/flang/test/Semantics/OpenMP/allocate-clause01.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.2 ! The allocate clause's allocator modifier must be of type allocator_handle diff --git a/flang/test/Semantics/OpenMP/allocate-directive.f90 b/flang/test/Semantics/OpenMP/allocate-directive.f90 index 254e5b617a7a90c24c465aed89adc24ed487d420..1db13df4193822c9e04a0637bcabef73a0f87fd6 100644 --- a/flang/test/Semantics/OpenMP/allocate-directive.f90 +++ b/flang/test/Semantics/OpenMP/allocate-directive.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! Check OpenMP Allocate directive use omp_lib diff --git a/flang/test/Semantics/OpenMP/allocate01.f90 b/flang/test/Semantics/OpenMP/allocate01.f90 index 4b290a5c2c749ba5aacd494f58e3d387de2014ea..a91076c80b1f93ccb570e2b0ea3b7dec3bcead3c 100644 --- a/flang/test/Semantics/OpenMP/allocate01.f90 +++ b/flang/test/Semantics/OpenMP/allocate01.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.0 ! 2.11.3 allocate Directive diff --git a/flang/test/Semantics/OpenMP/allocate02.f90 b/flang/test/Semantics/OpenMP/allocate02.f90 index d7da9ef575271ea1ba6588961b224063b8ba4301..dc4194aca7f127b1f06c83c176ea930a0b9ed997 100644 --- a/flang/test/Semantics/OpenMP/allocate02.f90 +++ b/flang/test/Semantics/OpenMP/allocate02.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.0 ! 2.11.3 allocate Directive diff --git a/flang/test/Semantics/OpenMP/allocate03.f90 b/flang/test/Semantics/OpenMP/allocate03.f90 index 320a9c9ea4122d2cd2ca4e70630ef8065853f050..30a015f26c31200a10012b4dd03ec63964f5cb3a 100644 --- a/flang/test/Semantics/OpenMP/allocate03.f90 +++ b/flang/test/Semantics/OpenMP/allocate03.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.0 ! 2.11.3 allocate Directive diff --git a/flang/test/Semantics/OpenMP/allocate04.f90 b/flang/test/Semantics/OpenMP/allocate04.f90 index 405781be4c2d27d2c17bb3bffbd5f8b9edd7f043..b8a87094116150a55349f951260d7930c46d7114 100644 --- a/flang/test/Semantics/OpenMP/allocate04.f90 +++ b/flang/test/Semantics/OpenMP/allocate04.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.0 ! 2.11.3 allocate Directive diff --git a/flang/test/Semantics/OpenMP/allocate05.f90 b/flang/test/Semantics/OpenMP/allocate05.f90 index 04bcf9119e0f883130d21f116e6da05ebe43cc20..92eeaf4222ac97c0c053d3a0eaf5884fed277d59 100644 --- a/flang/test/Semantics/OpenMP/allocate05.f90 +++ b/flang/test/Semantics/OpenMP/allocate05.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.0 ! 2.11.3 allocate Directive diff --git a/flang/test/Semantics/OpenMP/allocate06.f90 b/flang/test/Semantics/OpenMP/allocate06.f90 index 68a7e8857eb8978d4431beb020cf3becb249708a..c4474560bea39952aa084f8b7a55c9277ada9a60 100644 --- a/flang/test/Semantics/OpenMP/allocate06.f90 +++ b/flang/test/Semantics/OpenMP/allocate06.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.0 ! 2.11.3 allocate Directive diff --git a/flang/test/Semantics/OpenMP/allocate07.f90 b/flang/test/Semantics/OpenMP/allocate07.f90 index c01b35ab27400489c937a4d93d89920a238944cf..3211c0bf28b9df80e3cc0e4c1c1d0520ed829a99 100644 --- a/flang/test/Semantics/OpenMP/allocate07.f90 +++ b/flang/test/Semantics/OpenMP/allocate07.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.0 ! 2.11.3 allocate Directive diff --git a/flang/test/Semantics/OpenMP/allocate08.f90 b/flang/test/Semantics/OpenMP/allocate08.f90 index 65029d1ce0e5f696a9890ed46d1c59579b748a92..152ad07544ea46f8d52f08fe4dd4944c6e631b3f 100644 --- a/flang/test/Semantics/OpenMP/allocate08.f90 +++ b/flang/test/Semantics/OpenMP/allocate08.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.0 ! 2.11.3 allocate Directive diff --git a/flang/test/Semantics/OpenMP/allocate09.f90 b/flang/test/Semantics/OpenMP/allocate09.f90 index 26d6ff98c4a3f147b56d8c45effecf4e693a164c..639d23cd6d30ff29837c18d2f3ab721195677283 100644 --- a/flang/test/Semantics/OpenMP/allocate09.f90 +++ b/flang/test/Semantics/OpenMP/allocate09.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.0 ! 2.11.3 allocate Directive diff --git a/flang/test/Semantics/OpenMP/allocators01.f90 b/flang/test/Semantics/OpenMP/allocators01.f90 index d674438b2ab207024515386da0d76f0fe851d747..02d686b49716e03a0d0feab84341df62d3ec0c38 100644 --- a/flang/test/Semantics/OpenMP/allocators01.f90 +++ b/flang/test/Semantics/OpenMP/allocators01.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.2 ! 6.7 allocators construct diff --git a/flang/test/Semantics/OpenMP/allocators02.f90 b/flang/test/Semantics/OpenMP/allocators02.f90 index 32e7bc18ad99b066ee3bb3f4a635e102ee1654ba..9d8644bc30c614a504558501f8b9e1204634ae93 100644 --- a/flang/test/Semantics/OpenMP/allocators02.f90 +++ b/flang/test/Semantics/OpenMP/allocators02.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.2 ! 6.7 allocators construct diff --git a/flang/test/Semantics/OpenMP/allocators03.f90 b/flang/test/Semantics/OpenMP/allocators03.f90 index 533434c2ace0f1a3a1aa6836f5a960d0c1a126a9..85ab91fde5e01b2892ae163e2d46e1c0668c9738 100644 --- a/flang/test/Semantics/OpenMP/allocators03.f90 +++ b/flang/test/Semantics/OpenMP/allocators03.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.2 ! 6.7 allocators construct diff --git a/flang/test/Semantics/OpenMP/allocators04.f90 b/flang/test/Semantics/OpenMP/allocators04.f90 index d4467a2052a7dc38b581e42676a92dc41a166991..0c6e994e137ad475aeb9169ae2158502993a7957 100644 --- a/flang/test/Semantics/OpenMP/allocators04.f90 +++ b/flang/test/Semantics/OpenMP/allocators04.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.2 ! Inherited from 2.11.3 allocate Directive diff --git a/flang/test/Semantics/OpenMP/allocators05.f90 b/flang/test/Semantics/OpenMP/allocators05.f90 index 684eef695049518e40ed32daf6a335705cad7c10..07f1357b75b55ba63a1b90d3198ae96fa7d137de 100644 --- a/flang/test/Semantics/OpenMP/allocators05.f90 +++ b/flang/test/Semantics/OpenMP/allocators05.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.2 ! Inherited from 2.11.3 allocate directive diff --git a/flang/test/Semantics/OpenMP/allocators06.f90 b/flang/test/Semantics/OpenMP/allocators06.f90 index 17e168d4cfe0cbd4a997071876bbbc1c96d6b5f9..d3773c05a485d0927a4752b1252e1bfa643e17cb 100644 --- a/flang/test/Semantics/OpenMP/allocators06.f90 +++ b/flang/test/Semantics/OpenMP/allocators06.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.2 ! Inherited from 2.11.3 allocate directive diff --git a/flang/test/Semantics/OpenMP/atomic-hint-clause.f90 b/flang/test/Semantics/OpenMP/atomic-hint-clause.f90 index 5341fb2e7d2885e8ec8c6def3c56a06e8783ecca..3cbde3ab586caa2a26b680ae45b430cbc15c5382 100644 --- a/flang/test/Semantics/OpenMP/atomic-hint-clause.f90 +++ b/flang/test/Semantics/OpenMP/atomic-hint-clause.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! Semantic checks on hint clauses, as they appear on atomic constructs diff --git a/flang/test/Semantics/OpenMP/atomic01.f90 b/flang/test/Semantics/OpenMP/atomic01.f90 index 5469f82a0083cae2cd11ef22d326da25cfbfffe5..868c7623928aeeb3b1bc2b55bcfbdc0dbd03bc82 100644 --- a/flang/test/Semantics/OpenMP/atomic01.f90 +++ b/flang/test/Semantics/OpenMP/atomic01.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! Semantic checks for OpenMP 5.0 standard 2.17.7 atomic Construct. diff --git a/flang/test/Semantics/OpenMP/atomic02.f90 b/flang/test/Semantics/OpenMP/atomic02.f90 index c11622c87cbd35a2ca1d2aa44984124606fcb0f2..db67fa63dcdf5605b66b8fa418728fadabd2a37e 100644 --- a/flang/test/Semantics/OpenMP/atomic02.f90 +++ b/flang/test/Semantics/OpenMP/atomic02.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Atomic construct diff --git a/flang/test/Semantics/OpenMP/atomic03.f90 b/flang/test/Semantics/OpenMP/atomic03.f90 index 5fc642088ca56f8fc59dd5def523806edb2baf37..9bcbace10fb60287003e54af5fa0489196b20c4b 100644 --- a/flang/test/Semantics/OpenMP/atomic03.f90 +++ b/flang/test/Semantics/OpenMP/atomic03.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Atomic construct diff --git a/flang/test/Semantics/OpenMP/atomic04.f90 b/flang/test/Semantics/OpenMP/atomic04.f90 index ddf6b8bc2f5f6fdf93db4846de6262242c4e82a2..c0419a69d2dd76b5ead06f62a2c630090abe1302 100644 --- a/flang/test/Semantics/OpenMP/atomic04.f90 +++ b/flang/test/Semantics/OpenMP/atomic04.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Atomic construct diff --git a/flang/test/Semantics/OpenMP/atomic05.f90 b/flang/test/Semantics/OpenMP/atomic05.f90 index b3ff6e9b910f4f150624cfa9e0dcb03e9090bd0b..7b970dba8e49f12232e65b95e8bc26751f1efb1a 100644 --- a/flang/test/Semantics/OpenMP/atomic05.f90 +++ b/flang/test/Semantics/OpenMP/atomic05.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! This tests the various semantics related to the clauses of various OpenMP atomic constructs diff --git a/flang/test/Semantics/OpenMP/clause-validity01.f90 b/flang/test/Semantics/OpenMP/clause-validity01.f90 index d9573a81821f327bfaa9221550847d98be138d79..977a529864615fc1a94702901a9e10487da29bf3 100644 --- a/flang/test/Semantics/OpenMP/clause-validity01.f90 +++ b/flang/test/Semantics/OpenMP/clause-validity01.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp use omp_lib ! Check OpenMP clause validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/critical-hint-clause.f90 b/flang/test/Semantics/OpenMP/critical-hint-clause.f90 index 33088c6caf3598571444597a981e760a1a03531f..f35eea149135acd28f5dfcc3137b42d4d6005516 100644 --- a/flang/test/Semantics/OpenMP/critical-hint-clause.f90 +++ b/flang/test/Semantics/OpenMP/critical-hint-clause.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! Semantic checks on hint clauses, as they appear on critical construct diff --git a/flang/test/Semantics/OpenMP/declare-target01.f90 b/flang/test/Semantics/OpenMP/declare-target01.f90 index 3168781ba3839176023f597aa80d83f3943527f2..549f708b08f913d9fac8963e38f01100e47bd220 100644 --- a/flang/test/Semantics/OpenMP/declare-target01.f90 +++ b/flang/test/Semantics/OpenMP/declare-target01.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/do20.f90 b/flang/test/Semantics/OpenMP/do20.f90 new file mode 100644 index 0000000000000000000000000000000000000000..915d01e69edd74f66d0068af25ad75f843ed5e78 --- /dev/null +++ b/flang/test/Semantics/OpenMP/do20.f90 @@ -0,0 +1,18 @@ +! RUN: %python %S/../test_symbols.py %s %flang_fc1 -fopenmp + +! OpenMP 5.2 5.1.1 +! Iteration variables of non-associated loops may be listed in DSA clauses. + +!DEF: /shared_iv (Subroutine)Subprogram +subroutine shared_iv + !DEF: /shared_iv/i ObjectEntity INTEGER(4) + integer i + + !$omp parallel shared(i) + !$omp single + !REF: /shared_iv/i + do i = 0, 1 + end do + !$omp end single + !$omp end parallel +end subroutine diff --git a/flang/test/Semantics/OpenMP/flush02.f90 b/flang/test/Semantics/OpenMP/flush02.f90 index 7700954b1906176ad7b69c872c5ec554146d21cc..dbb57ac81450e504795c6272ec0e09ed25e9f5d6 100644 --- a/flang/test/Semantics/OpenMP/flush02.f90 +++ b/flang/test/Semantics/OpenMP/flush02.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! Check OpenMP 5.0 - 2.17.8 flush Construct diff --git a/flang/test/Semantics/OpenMP/omp-atomic-assignment-stmt.f90 b/flang/test/Semantics/OpenMP/omp-atomic-assignment-stmt.f90 index 7e2d508839ff60642a28700419e16686009a78c7..d9ced2cd795018e7627905b5a83a75e2633b406e 100644 --- a/flang/test/Semantics/OpenMP/omp-atomic-assignment-stmt.f90 +++ b/flang/test/Semantics/OpenMP/omp-atomic-assignment-stmt.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! Semantic checks for various assignments related to atomic constructs diff --git a/flang/test/Semantics/OpenMP/parallel-sections01.f90 b/flang/test/Semantics/OpenMP/parallel-sections01.f90 index c5bfbdfcb7b268e90ebc546e027c379d0bea3046..2bf58ea2cb295c6ee7c76ea854d125b92135d122 100644 --- a/flang/test/Semantics/OpenMP/parallel-sections01.f90 +++ b/flang/test/Semantics/OpenMP/parallel-sections01.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP version 5.0.0 ! 2.13.3 parallel sections Construct diff --git a/flang/test/Semantics/OpenMP/reduction11.f90 b/flang/test/Semantics/OpenMP/reduction11.f90 new file mode 100644 index 0000000000000000000000000000000000000000..3893fe70b407f43665372f1e6a0b350eae577537 --- /dev/null +++ b/flang/test/Semantics/OpenMP/reduction11.f90 @@ -0,0 +1,22 @@ +! 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 +program omp_reduction + ! CHECK: i size=4 offset=0: ObjectEntity type: INTEGER(4) + integer i + ! CHECK: k size=4 offset=4: ObjectEntity type: INTEGER(4) init:10_4 + integer :: k = 10 + ! CHECK: m size=4 offset=8: ObjectEntity type: INTEGER(4) init:12_4 + integer :: m = 12 + + ! CHECK: OtherConstruct scope + ! CHECK: i (OmpPrivate, OmpPreDetermined): HostAssoc + ! CHECK: k (OmpReduction): HostAssoc + ! CHECK: max, INTRINSIC: ProcEntity + !$omp parallel do reduction(max:k) + do i=1,10 + k = i + end do + !$omp end parallel do +end program omp_reduction diff --git a/flang/test/Semantics/OpenMP/resolve06.f90 b/flang/test/Semantics/OpenMP/resolve06.f90 index 1afc7408c0bc21948c16492e776e7e83b7341ca5..f9729050055958c4e05d4763ac6a52e081c02308 100644 --- a/flang/test/Semantics/OpenMP/resolve06.f90 +++ b/flang/test/Semantics/OpenMP/resolve06.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp use omp_lib !2.11.4 Allocate Clause diff --git a/flang/test/Semantics/OpenMP/sections02.f90 b/flang/test/Semantics/OpenMP/sections02.f90 index bcdeb05e5a171ca040f1aae1cf5ee1d98998dddc..b96455a960ef8e9f707cffffdd3ab6d27d8a1256 100644 --- a/flang/test/Semantics/OpenMP/sections02.f90 +++ b/flang/test/Semantics/OpenMP/sections02.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP version 5.0.0 ! 2.8.1 sections construct diff --git a/flang/test/Semantics/OpenMP/sync-critical02.f90 b/flang/test/Semantics/OpenMP/sync-critical02.f90 index dac031f4f8fc36f2585ebd5f34ef0183565689e6..fdd95fa76ad7c6a8fe4cfbaca0d373d2f55cca68 100644 --- a/flang/test/Semantics/OpenMP/sync-critical02.f90 +++ b/flang/test/Semantics/OpenMP/sync-critical02.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang -fopenmp ! OpenMP Version 5.0 diff --git a/flang/test/Semantics/OpenMP/taskgroup01.f90 b/flang/test/Semantics/OpenMP/taskgroup01.f90 index a2494129b580ac16964d354e5c913033beb1fb50..e3185552a44bb429a0e611e316cef44279f13194 100644 --- a/flang/test/Semantics/OpenMP/taskgroup01.f90 +++ b/flang/test/Semantics/OpenMP/taskgroup01.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang -fopenmp use omp_lib diff --git a/flang/test/Semantics/OpenMP/threadprivate01.f90 b/flang/test/Semantics/OpenMP/threadprivate01.f90 index 309d209a456727307190acc61b68d27f7aaaba89..5ba5f400eb203c02739484ca0d29a638eba96743 100644 --- a/flang/test/Semantics/OpenMP/threadprivate01.f90 +++ b/flang/test/Semantics/OpenMP/threadprivate01.f90 @@ -1,3 +1,5 @@ +! REQUIRES: openmp_runtime + ! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp ! OpenMP Version 5.1 ! Check OpenMP construct validity for the following directives: diff --git a/flang/test/Semantics/OpenMP/use_device_ptr1.f90 b/flang/test/Semantics/OpenMP/use_device_ptr1.f90 index af89698a5c5a994ee0b9f951ea34b9ed9496db2b..176fb5f35a84909cfbe23abd6a121aa20e3407e5 100644 --- a/flang/test/Semantics/OpenMP/use_device_ptr1.f90 +++ b/flang/test/Semantics/OpenMP/use_device_ptr1.f90 @@ -27,7 +27,7 @@ subroutine omp_target_data a = arrayB !$omp end target data - !ERROR: 'a' in USE_DEVICE_PTR clause must be of type C_PTR + !WARNING: Use of non-C_PTR type 'a' in USE_DEVICE_PTR is deprecated, use USE_DEVICE_ADDR instead !$omp target data map(tofrom: a) use_device_ptr(a) a = 2 !$omp end target data diff --git a/flang/test/Semantics/call41.f90 b/flang/test/Semantics/call41.f90 new file mode 100644 index 0000000000000000000000000000000000000000..a4c7514d99ba5ef75b3f85d70d7c379e2fde0a53 --- /dev/null +++ b/flang/test/Semantics/call41.f90 @@ -0,0 +1,12 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 -Werror +module m + contains + subroutine unlimited(x) + class(*), intent(in) :: x + end + subroutine test + !PORTABILITY: passing Hollerith to unlimited polymorphic as if it were CHARACTER + call unlimited(6HHERMAN) + call unlimited('abc') ! ok + end +end diff --git a/flang/test/Semantics/cuf09.cuf b/flang/test/Semantics/cuf09.cuf index dd70c3b1ff5efd97a9e30352020af1934c7f6d01..4bc93132044fdd496da159a8bfcd691b1d5d0ada 100644 --- a/flang/test/Semantics/cuf09.cuf +++ b/flang/test/Semantics/cuf09.cuf @@ -10,6 +10,15 @@ module m end program main + !$cuf kernel do <<< *, * >>> ! ok + do j = 1, 0 + end do + !$cuf kernel do <<< (*), (*) >>> ! ok + do j = 1, 0 + end do + !$cuf kernel do <<< (1,*), (2,*) >>> ! ok + do j = 1, 0 + end do !ERROR: !$CUF KERNEL DO (1) must be followed by a DO construct with tightly nested outer levels of counted DO loops !$cuf kernel do <<< 1, 2 >>> do while (.false.) diff --git a/flang/test/Semantics/declarations02.f90 b/flang/test/Semantics/declarations02.f90 index 439527a0edb6afa016ae6b38e07603c5944de335..f39c233c1c3a432cdbe5e39e9918af7eaf6d4d1e 100644 --- a/flang/test/Semantics/declarations02.f90 +++ b/flang/test/Semantics/declarations02.f90 @@ -10,6 +10,20 @@ module m integer, parameter :: x3 = 1 bind(c) :: x3 + !ERROR: 'x4' may not have both the ALLOCATABLE and PARAMETER attributes + !ERROR: 'x4' may not have both the ASYNCHRONOUS and PARAMETER attributes + !ERROR: 'x4' may not have both the SAVE and PARAMETER attributes + !ERROR: 'x4' may not have both the TARGET and PARAMETER attributes + !ERROR: 'x4' may not have both the VOLATILE and PARAMETER attributes + !ERROR: The entity 'x4' with an explicit SAVE attribute must be a variable, procedure pointer, or COMMON block + !ERROR: An entity may not have the ASYNCHRONOUS attribute unless it is a variable + integer, parameter :: x4 = 1 + allocatable x4 + asynchronous x4 + save x4 + target x4 + volatile x4 + type :: my_type1 integer :: x4 end type diff --git a/flang/test/Semantics/deferred01.f90 b/flang/test/Semantics/deferred01.f90 new file mode 100644 index 0000000000000000000000000000000000000000..87818c10bd399ec1bf333c960bbb15722b768e22 --- /dev/null +++ b/flang/test/Semantics/deferred01.f90 @@ -0,0 +1,28 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +! Deferred TBPs must be overridden, but when they are private, those +! overrides must appear in the same module. +module m1 + type, abstract :: absBase + contains + procedure(deferredInterface), deferred, private :: deferredTbp + end type + abstract interface + subroutine deferredInterface(x) + import absBase + class(absBase), intent(in) :: x + end + end interface +end + +module m2 + use m1 + type, extends(absBase) :: ext + contains + !ERROR: Override of PRIVATE DEFERRED 'deferredtbp' must appear in its module + procedure :: deferredTbp => implTbp + end type + contains + subroutine implTbp(x) + class(ext), intent(in) :: x + end +end diff --git a/flang/test/Semantics/doconcurrent08.f90 b/flang/test/Semantics/doconcurrent08.f90 index 41cd71e233d0d3e467550173d9b4e27327cf836c..52b382741d0731f252883ccc2e2984e64cc3d121 100644 --- a/flang/test/Semantics/doconcurrent08.f90 +++ b/flang/test/Semantics/doconcurrent08.f90 @@ -209,6 +209,8 @@ module m2 type :: impureFinal contains final :: impureSub + final :: impureSubRank1 + final :: impureSubRank2 end type type :: pureFinal @@ -222,16 +224,27 @@ module m2 type(impureFinal), intent(in) :: x end subroutine + impure subroutine impureSubRank1(x) + type(impureFinal), intent(in) :: x(:) + end subroutine + + impure subroutine impureSubRank2(x) + type(impureFinal), intent(in) :: x(:,:) + end subroutine + pure subroutine pureSub(x) type(pureFinal), intent(in) :: x end subroutine subroutine s4() type(impureFinal), allocatable :: ifVar, ifvar1 + type(impureFinal), allocatable :: ifArr1(:), ifArr2(:,:) + type(impureFinal) :: if0 type(pureFinal), allocatable :: pfVar allocate(ifVar) allocate(ifVar1) allocate(pfVar) + allocate(ifArr1(5), ifArr2(5,5)) ! OK for an ordinary DO loop do i = 1,10 @@ -239,11 +252,9 @@ module m2 end do ! OK to invoke a PURE FINAL procedure in a DO CONCURRENT - ! This case does not work currently because the compiler's test for - ! HasImpureFinal() in .../lib/Semantics/tools.cc doesn't work correctly -! do concurrent (i = 1:10) -! if (i .eq. 1) deallocate(pfVar) -! end do + do concurrent (i = 1:10) + if (i .eq. 1) deallocate(pfVar) + end do ! Error to invoke an IMPURE FINAL procedure in a DO CONCURRENT do concurrent (i = 1:10) @@ -271,6 +282,34 @@ module m2 ifvar = ifvar1 end if end do + + do concurrent (i = 1:5) + if (i .eq. 1) then + !ERROR: Deallocation of an entity with an IMPURE FINAL procedure 'impuresub' caused by assignment not allowed in DO CONCURRENT + ifArr1(i) = if0 + end if + end do + + do concurrent (i = 1:5) + if (i .eq. 1) then + !ERROR: Deallocation of an entity with an IMPURE FINAL procedure 'impuresubrank1' caused by assignment not allowed in DO CONCURRENT + ifArr1 = if0 + end if + end do + + do concurrent (i = 1:5) + if (i .eq. 1) then + !ERROR: Deallocation of an entity with an IMPURE FINAL procedure 'impuresubrank1' caused by assignment not allowed in DO CONCURRENT + ifArr2(i,:) = if0 + end if + end do + + do concurrent (i = 1:5) + if (i .eq. 1) then + !ERROR: Deallocation of an entity with an IMPURE FINAL procedure 'impuresubrank2' caused by assignment not allowed in DO CONCURRENT + ifArr2(:,:) = if0 + end if + end do end subroutine s4 end module m2 diff --git a/flang/test/Semantics/forall02.f90 b/flang/test/Semantics/forall02.f90 new file mode 100644 index 0000000000000000000000000000000000000000..c4f4311a175a3e7481adfc4142d9768c464921e5 --- /dev/null +++ b/flang/test/Semantics/forall02.f90 @@ -0,0 +1,67 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 + +module m1 + type :: impureFinal + contains + final :: impureSub + final :: impureSubRank1 + final :: impureSubRank2 + end type + + contains + + impure subroutine impureSub(x) + type(impureFinal), intent(in) :: x + end subroutine + + impure subroutine impureSubRank1(x) + type(impureFinal), intent(in) :: x(:) + end subroutine + + impure subroutine impureSubRank2(x) + type(impureFinal), intent(in) :: x(:,:) + end subroutine + + subroutine s1() + implicit none + integer :: i + type(impureFinal), allocatable :: ifVar, ifvar1 + type(impureFinal), allocatable :: ifArr1(:), ifArr2(:,:) + type(impureFinal) :: if0 + integer a(10) + allocate(ifVar) + allocate(ifVar1) + allocate(ifArr1(5), ifArr2(5,5)) + + ! Error to invoke an IMPURE FINAL procedure in a FORALL + forall (i = 1:10) + !WARNING: FORALL index variable 'i' not used on left-hand side of assignment + !ERROR: Impure procedure 'impuresub' is referenced by finalization in a FORALL + ifvar = ifvar1 + end forall + + forall (i = 1:5) + !ERROR: Impure procedure 'impuresub' is referenced by finalization in a FORALL + ifArr1(i) = if0 + end forall + + forall (i = 1:5) + !WARNING: FORALL index variable 'i' not used on left-hand side of assignment + !ERROR: Impure procedure 'impuresubrank1' is referenced by finalization in a FORALL + ifArr1 = if0 + end forall + + forall (i = 1:5) + !ERROR: Impure procedure 'impuresubrank1' is referenced by finalization in a FORALL + ifArr2(i,:) = if0 + end forall + + forall (i = 1:5) + !WARNING: FORALL index variable 'i' not used on left-hand side of assignment + !ERROR: Impure procedure 'impuresubrank2' is referenced by finalization in a FORALL + ifArr2(:,:) = if0 + end forall + end subroutine + +end module m1 + diff --git a/flang/test/Semantics/init01.f90 b/flang/test/Semantics/init01.f90 index f85feef097cdca5183b9e10f58eac48fbd6f34a7..65d524b16a23a2aa324282b88a9fbe5e8f0c6067 100644 --- a/flang/test/Semantics/init01.f90 +++ b/flang/test/Semantics/init01.f90 @@ -158,8 +158,10 @@ subroutine notObjects real, external :: x1 = 1. !ERROR: 'x2' is not a pointer but is initialized like one real, external :: x2 => sin +!ERROR: 'x3' is not a known intrinsic procedure !ERROR: 'x3' is not an object that can be initialized real, intrinsic :: x3 = 1. +!ERROR: 'x4' is not a known intrinsic procedure !ERROR: 'x4' is not a pointer but is initialized like one real, intrinsic :: x4 => cos end subroutine diff --git a/flang/test/Semantics/modfile63.f90 b/flang/test/Semantics/modfile63.f90 index aaf1f7beaa48fae1dfb6c31f75ff2f578afc560d..0783121017243ebae5a6aa43fab828211d10a5a9 100644 --- a/flang/test/Semantics/modfile63.f90 +++ b/flang/test/Semantics/modfile63.f90 @@ -1,12 +1,10 @@ ! RUN: %flang_fc1 -fsyntax-only -I%S/Inputs/dir1 %s ! RUN: not %flang_fc1 -fsyntax-only -I%S/Inputs/dir2 %s 2>&1 | FileCheck --check-prefix=ERROR %s ! RUN: %flang_fc1 -Werror -fsyntax-only -I%S/Inputs/dir1 -I%S/Inputs/dir2 %s -! RUN: not %flang_fc1 -Werror -fsyntax-only -I%S/Inputs/dir2 -I%S/Inputs/dir1 %s 2>&1 | FileCheck --check-prefix=WARNING %s ! Inputs/dir1 and Inputs/dir2 each have identical copies of modfile63b.mod. ! modfile63b.mod depends on Inputs/dir1/modfile63a.mod - the version in -! Inputs/dir2/modfile63a.mod has a distinct checksum and should be -! ignored with a warning. +! Inputs/dir2/modfile63a.mod has a distinct checksum. ! If it becomes necessary to recompile those modules, just use the ! module files as Fortran source. @@ -15,5 +13,4 @@ use modfile63b call s2 end -! ERROR: Could not find a module file for 'modfile63a' in the module search path with the expected checksum -! WARNING: Module file for 'modfile63a' appears later in the module search path than conflicting modules with different checksums +! ERROR: Cannot read module file for module 'modfile63a': File is not the right module file for 'modfile63a': diff --git a/flang/test/Semantics/resolve11.f90 b/flang/test/Semantics/resolve11.f90 index 33ce88342b49be599f7708d14454d663ccdc408d..db508f062d1d1c424df78c5d93ff10b0803ac15e 100644 --- a/flang/test/Semantics/resolve11.f90 +++ b/flang/test/Semantics/resolve11.f90 @@ -49,3 +49,40 @@ module m3 !ERROR: The accessibility of 'OPERATOR(.GT.)' has already been specified as PUBLIC private :: operator(.gt.) end + +module m4 + private + type, public :: foo + end type + interface foo + procedure fun + end interface + contains + function fun + end +end + +subroutine s4 + !ERROR: 'fun' is PRIVATE in 'm4' + use m4, only: foo, fun + type(foo) x ! ok + print *, foo() ! ok +end + +module m5 + public + type, private :: foo + end type + interface foo + procedure fun + end interface + contains + function fun + end +end + +subroutine s5 + !ERROR: 'foo' is PRIVATE in 'm5' + use m5, only: foo, fun + print *, fun() ! ok +end diff --git a/flang/test/Semantics/resolve61.f90 b/flang/test/Semantics/resolve61.f90 index 32bf9091a85651aa4d4b1d002070187ded927959..2a1f584ffaf08998074222534a02773aeb072090 100644 --- a/flang/test/Semantics/resolve61.f90 +++ b/flang/test/Semantics/resolve61.f90 @@ -126,3 +126,12 @@ subroutine p13 pointer(ip, x) ! ok, local declaration end end + +subroutine p14 + real :: r + block + asynchronous :: r + !ERROR: PARAMETER attribute not allowed on 'r' + parameter (r = 1.0) + end block +end diff --git a/flang/test/Semantics/resolve81.f90 b/flang/test/Semantics/resolve81.f90 index 2a0b961d48e5c39286c1b8b0c89e6dbda859e51b..87901fd7d2efcb19db1550e3b02e9dd140846938 100644 --- a/flang/test/Semantics/resolve81.f90 +++ b/flang/test/Semantics/resolve81.f90 @@ -28,6 +28,7 @@ module m !WARNING: Attribute 'EXTERNAL' cannot be used more than once real, external, external :: externFunc !WARNING: Attribute 'INTRINSIC' cannot be used more than once + !ERROR: An interface name with BIND attribute must be specified if the BIND attribute is specified in a procedure declaration statement real, intrinsic, bind(c), intrinsic :: cos !WARNING: Attribute 'BIND(C)' cannot be used more than once integer, bind(c), volatile, bind(c) :: bindVar diff --git a/flang/test/Semantics/separate-mp05.f90 b/flang/test/Semantics/separate-mp05.f90 index 5b7e2523a22866787d8440987a4c6802a7061b9f..ad002142fd285e0203e6f46080e36a810ae95eb0 100644 --- a/flang/test/Semantics/separate-mp05.f90 +++ b/flang/test/Semantics/separate-mp05.f90 @@ -7,8 +7,10 @@ module m !DEF: /m/smp MODULE, PUBLIC, PURE (Function) Subprogram REAL(4) !DEF: /m/smp/f EXTERNAL, PURE (Function) Subprogram REAL(4) !DEF: /m/smp/x INTENT(IN) ObjectEntity REAL(4) - !DEF: /m/smp/res (Implicit) ObjectEntity REAL(4) + !DEF: /m/smp/res ObjectEntity REAL(4) pure module function smp(f, x) result(res) + !REF: /m/smp/res + real res interface !REF: /m/smp/f !DEF: /m/smp/f/x INTENT(IN) ObjectEntity REAL(4) @@ -32,7 +34,7 @@ submodule (m)sm contains !DEF: /m/sm/smp MODULE, PUBLIC, PURE (Function) Subprogram REAL(4) module procedure smp - !DEF: /m/sm/smp/res (Implicit) ObjectEntity REAL(4) + !DEF: /m/sm/smp/res ObjectEntity REAL(4) !DEF: /m/sm/smp/f EXTERNAL, PURE (Function) Subprogram REAL(4) !DEF: /m/sm/smp/x INTENT(IN) ObjectEntity REAL(4) res = f(x) diff --git a/flang/test/Semantics/structconst09.f90 b/flang/test/Semantics/structconst09.f90 new file mode 100644 index 0000000000000000000000000000000000000000..c129f11606857e056a19f37260904652746dde05 --- /dev/null +++ b/flang/test/Semantics/structconst09.f90 @@ -0,0 +1,37 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic +! Structure constructors with bad pointer targets +module m + real, target, save :: x + type t + real, pointer :: rp => x + procedure(f), pointer, nopass :: pp => f + end type + contains + real function f() + f = 0. + end + subroutine test(da, dp) + real, target :: y, da + procedure(f) dp + procedure(f), pointer :: lpp + external ext + type(t) :: a1 = t() ! ok + type(t) :: a2 = t(rp=x) ! ok + type(t) :: a3 = t(pp=f) ! ok + type(t) :: a4 = t(pp=ext) ! ok + !ERROR: Must be a constant value + type(t) :: a5 = t(rp=y) + !ERROR: Must be a constant value + type(t) :: a6 = t(rp=da) + !ERROR: Must be a constant value + type(t) :: a7 = t(pp=lpp) + !ERROR: Must be a constant value + type(t) :: a8 = t(pp=internal) + !ERROR: Must be a constant value + type(t) :: a9 = t(pp=dp) + contains + real function internal() + internal = 666. + end + end +end diff --git a/flang/test/Transforms/omp-descriptor-map-info-gen.fir b/flang/test/Transforms/omp-descriptor-map-info-gen.fir index 22594ec88c9cb17792aae0532dbe445c23bc47e4..05d05b0ecb597b8eb73a9627fff0a58f50b22f11 100644 --- a/flang/test/Transforms/omp-descriptor-map-info-gen.fir +++ b/flang/test/Transforms/omp-descriptor-map-info-gen.fir @@ -15,10 +15,10 @@ module attributes {omp.is_target_device = false} { %c1 = arith.constant 0 : index %c2 = arith.constant 10 : index %dims:3 = fir.box_dims %2#1, %c1 : (!fir.box<!fir.array<?xi32>>, index) -> (index, index, index) - %bounds = omp.bounds lower_bound(%c1 : index) upper_bound(%c2 : index) extent(%dims#1 : index) stride(%dims#2 : index) start_idx(%c0 : index) {stride_in_bytes = true} + %bounds = omp.map.bounds lower_bound(%c1 : index) upper_bound(%c2 : index) extent(%dims#1 : index) stride(%dims#2 : index) start_idx(%c0 : index) {stride_in_bytes = true} %7 = fir.box_addr %2#1 : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>> - %8 = omp.map_info var_ptr(%4#1 : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.box<!fir.heap<i32>>) map_clauses(tofrom) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<i32>>> - %9 = omp.map_info var_ptr(%7 : !fir.ref<!fir.array<?xi32>>, !fir.array<?xi32>) map_clauses(from) capture(ByRef) bounds(%bounds) -> !fir.ref<!fir.array<?xi32>> + %8 = omp.map.info var_ptr(%4#1 : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.box<!fir.heap<i32>>) map_clauses(tofrom) capture(ByRef) -> !fir.ref<!fir.box<!fir.heap<i32>>> + %9 = omp.map.info var_ptr(%7 : !fir.ref<!fir.array<?xi32>>, !fir.array<?xi32>) map_clauses(from) capture(ByRef) bounds(%bounds) -> !fir.ref<!fir.array<?xi32>> omp.target map_entries(%8 -> %arg1, %9 -> %arg2 : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.array<?xi32>>) { ^bb0(%arg1: !fir.ref<!fir.box<!fir.heap<i32>>>, %arg2: !fir.ref<!fir.array<?xi32>>): omp.terminator @@ -32,13 +32,13 @@ module attributes {omp.is_target_device = false} { // CHECK: %[[ALLOCA2:.*]] = fir.alloca !fir.box<!fir.heap<i32>> // CHECK: %[[DECLARE1:.*]]:2 = hlfir.declare %[[ARG0]] {fortran_attrs = #fir.var_attrs<intent_out>, uniq_name = "test"} : (!fir.box<!fir.array<?xi32>>) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>) // CHECK: %[[DECLARE2:.*]]:2 = hlfir.declare %[[ALLOCA2]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "test2"} : (!fir.ref<!fir.box<!fir.heap<i32>>>) -> (!fir.ref<!fir.box<!fir.heap<i32>>>, !fir.ref<!fir.box<!fir.heap<i32>>>) -// CHECK: %[[BOUNDS:.*]] = omp.bounds lower_bound(%{{.*}} : index) upper_bound(%{{.*}} : index) extent(%{{.*}} : index) stride(%{{.*}} : index) start_idx(%{{.*}} : index) {stride_in_bytes = true} +// CHECK: %[[BOUNDS:.*]] = omp.map.bounds lower_bound(%{{.*}} : index) upper_bound(%{{.*}} : index) extent(%{{.*}} : index) stride(%{{.*}} : index) start_idx(%{{.*}} : index) {stride_in_bytes = true} // CHECK: %[[BASE_ADDR_OFF:.*]] = fir.box_offset %[[DECLARE2]]#1 base_addr : (!fir.ref<!fir.box<!fir.heap<i32>>>) -> !fir.llvm_ptr<!fir.ref<i32>> -// CHECK: %[[DESC_MEMBER_MAP:.*]] = omp.map_info var_ptr(%[[DECLARE2]]#1 : !fir.ref<!fir.box<!fir.heap<i32>>>, i32) var_ptr_ptr(%[[BASE_ADDR_OFF]] : !fir.llvm_ptr<!fir.ref<i32>>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""} -// CHECK: %[[DESC_PARENT_MAP:.*]] = omp.map_info var_ptr(%[[DECLARE2]]#1 : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.box<!fir.heap<i32>>) map_clauses(tofrom) capture(ByRef) members(%[[DESC_MEMBER_MAP]] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.heap<i32>>> +// CHECK: %[[DESC_MEMBER_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE2]]#1 : !fir.ref<!fir.box<!fir.heap<i32>>>, i32) var_ptr_ptr(%[[BASE_ADDR_OFF]] : !fir.llvm_ptr<!fir.ref<i32>>) map_clauses(tofrom) capture(ByRef) -> !fir.llvm_ptr<!fir.ref<i32>> {name = ""} +// CHECK: %[[DESC_PARENT_MAP:.*]] = omp.map.info var_ptr(%[[DECLARE2]]#1 : !fir.ref<!fir.box<!fir.heap<i32>>>, !fir.box<!fir.heap<i32>>) map_clauses(tofrom) capture(ByRef) members(%[[DESC_MEMBER_MAP]] : !fir.llvm_ptr<!fir.ref<i32>>) -> !fir.ref<!fir.box<!fir.heap<i32>>> // CHECK: fir.store %[[DECLARE1]]#1 to %[[ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>> // CHECK: %[[BASE_ADDR_OFF_2:.*]] = fir.box_offset %[[ALLOCA]] base_addr : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> -// CHECK: %[[DESC_MEMBER_MAP_2:.*]] = omp.map_info var_ptr(%[[ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.array<?xi32>) var_ptr_ptr(%[[BASE_ADDR_OFF_2]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} -// CHECK: %[[DESC_PARENT_MAP_2:.*]] = omp.map_info var_ptr(%[[ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(from) capture(ByRef) members(%15 : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> +// CHECK: %[[DESC_MEMBER_MAP_2:.*]] = omp.map.info var_ptr(%[[ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.array<?xi32>) var_ptr_ptr(%[[BASE_ADDR_OFF_2]] : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) map_clauses(from) capture(ByRef) bounds(%[[BOUNDS]]) -> !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>> {name = ""} +// CHECK: %[[DESC_PARENT_MAP_2:.*]] = omp.map.info var_ptr(%[[ALLOCA]] : !fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.box<!fir.array<?xi32>>) map_clauses(from) capture(ByRef) members(%15 : !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>) -> !fir.ref<!fir.array<?xi32>> // CHECK: omp.target map_entries(%[[DESC_MEMBER_MAP]] -> %[[ARG1:.*]], %[[DESC_PARENT_MAP]] -> %[[ARG2:.*]], %[[DESC_MEMBER_MAP_2]] -> %[[ARG3:.*]], %[[DESC_PARENT_MAP_2]] -> %[[ARG4:.*]] : {{.*}}) { // CHECK: ^bb0(%[[ARG1]]: !fir.llvm_ptr<!fir.ref<i32>>, %[[ARG2]]: !fir.ref<!fir.box<!fir.heap<i32>>>, %[[ARG3]]: !fir.llvm_ptr<!fir.ref<!fir.array<?xi32>>>, %[[ARG4]]: !fir.ref<!fir.array<?xi32>>): diff --git a/flang/test/Transforms/omp-reduction-cfg-conversion.fir b/flang/test/Transforms/omp-reduction-cfg-conversion.fir new file mode 100644 index 0000000000000000000000000000000000000000..3103c4456d72efdd7d94ab78f4598f7c562b1bc2 --- /dev/null +++ b/flang/test/Transforms/omp-reduction-cfg-conversion.fir @@ -0,0 +1,57 @@ +// RUN: fir-opt --cfg-conversion-on-reduce-opt %s | FileCheck %s + +omp.declare_reduction @add_reduction_i_32_box_3_byref : !fir.ref<!fir.box<!fir.array<3xi32>>> init { +^bb0(%arg0: !fir.ref<!fir.box<!fir.array<3xi32>>>): + %c4_i32 = arith.constant 4 : i32 + %c0_i32 = arith.constant 0 : i32 + %c3 = arith.constant 3 : index + %0 = fir.alloca !fir.box<!fir.array<3xi32>> + %1 = fir.alloca !fir.array<3xi32> {bindc_name = "omp.reduction.array.init"} + %2 = fir.shape %c3 : (index) -> !fir.shape<1> + %3 = fir.declare %1(%2) {uniq_name = "omp.reduction.array.init"} : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.ref<!fir.array<3xi32>> + %4 = fir.embox %3(%2) : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<3xi32>> + %5 = fir.alloca i32 + fir.store %c0_i32 to %5 : !fir.ref<i32> + %6 = fir.embox %5 : (!fir.ref<i32>) -> !fir.box<i32> + fir.store %4 to %0 : !fir.ref<!fir.box<!fir.array<3xi32>>> + %7 = fir.address_of(@_QQclX9a9fdf8c5fd329fbbf2b0c08e2ca9a1e) : !fir.ref<!fir.char<1,40>> + %8 = fir.convert %0 : (!fir.ref<!fir.box<!fir.array<3xi32>>>) -> !fir.ref<!fir.box<none>> + %9 = fir.convert %6 : (!fir.box<i32>) -> !fir.box<none> + %10 = fir.convert %7 : (!fir.ref<!fir.char<1,40>>) -> !fir.ref<i8> + %11 = fir.call @_FortranAAssign(%8, %9, %10, %c4_i32) : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> none + %12 = fir.alloca !fir.box<!fir.array<3xi32>> + fir.store %4 to %12 : !fir.ref<!fir.box<!fir.array<3xi32>>> + omp.yield(%12 : !fir.ref<!fir.box<!fir.array<3xi32>>>) +} combiner { +^bb0(%arg0: !fir.ref<!fir.box<!fir.array<3xi32>>>, %arg1: !fir.ref<!fir.box<!fir.array<3xi32>>>): + %c1 = arith.constant 1 : index + %c0 = arith.constant 0 : index + %0 = fir.load %arg0 : !fir.ref<!fir.box<!fir.array<3xi32>>> + %1 = fir.load %arg1 : !fir.ref<!fir.box<!fir.array<3xi32>>> + %2:3 = fir.box_dims %0, %c0 : (!fir.box<!fir.array<3xi32>>, index) -> (index, index, index) + %3 = fir.shape_shift %2#0, %2#1 : (index, index) -> !fir.shapeshift<1> + fir.do_loop %arg2 = %c1 to %2#1 step %c1 unordered { + %4 = fir.array_coor %0(%3) %arg2 : (!fir.box<!fir.array<3xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32> + %5 = fir.array_coor %1(%3) %arg2 : (!fir.box<!fir.array<3xi32>>, !fir.shapeshift<1>, index) -> !fir.ref<i32> + %6 = fir.load %4 : !fir.ref<i32> + %7 = fir.load %5 : !fir.ref<i32> + %8 = arith.addi %6, %7 : i32 + fir.store %8 to %4 : !fir.ref<i32> + } + omp.yield(%arg0 : !fir.ref<!fir.box<!fir.array<3xi32>>>) +} + +// ensure cfg conversion has run on the do loop +// CHECK: combiner { +// CHECK-NOT: fir.do_loop +// CHECK: ^bb0({{.*}}): +// ... +// CHECK: cf.br ^bb1 +// CHECK: ^bb1({{.*}}): +// ... +// CHECK: cf.cond_br %{{.*}} ^bb2, ^bb3 +// CHECK: ^bb2: +// ... +// CHECK: cf.br ^bb1 +// CHECK: ^bb3: + diff --git a/flang/test/Transforms/stack-arrays.fir b/flang/test/Transforms/stack-arrays.fir index f4fe737e88d78522b8d4470734c640960c92b15a..a2ffe555091ebcbb75ef451bdacb37dbed79b59f 100644 --- a/flang/test/Transforms/stack-arrays.fir +++ b/flang/test/Transforms/stack-arrays.fir @@ -127,9 +127,7 @@ func.func @placement1() { return } // CHECK: func.func @placement1() { -// CHECK-NEXT: %[[ONE:.*]] = arith.constant 1 : index -// CHECK-NEXT: %[[TWO:.*]] = arith.constant 2 : index -// CHECK-NEXT: %[[ARG:.*]] = arith.addi %[[ONE]], %[[TWO]] : index +// CHECK-NEXT: %[[ARG:.*]] = arith.constant 3 : index // CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[ARG]] // CHECK-NEXT: return // CHECK-NEXT: } @@ -204,13 +202,12 @@ func.func @placement4(%arg0 : i1) { // CHECK: func.func @placement4(%arg0: i1) { // CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index // CHECK-NEXT: %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32 -// CHECK-NEXT: %[[C2:.*]] = arith.constant 2 : index // CHECK-NEXT: %[[C10:.*]] = arith.constant 10 : index // CHECK-NEXT: cf.br ^bb1 // CHECK-NEXT: ^bb1: -// CHECK-NEXT: %[[SUM:.*]] = arith.addi %[[C1]], %[[C2]] : index +// CHECK-NEXT: %[[C3:.*]] = arith.constant 3 : index // CHECK-NEXT: %[[SP:.*]] = fir.call @llvm.stacksave.p0() : () -> !fir.ref<i8> -// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[SUM]] +// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[C3]] // CHECK-NEXT: fir.call @llvm.stackrestore.p0(%[[SP]]) : (!fir.ref<i8>) -> () // CHECK-NEXT: cf.cond_br %arg0, ^bb1, ^bb2 // CHECK-NEXT: ^bb2: diff --git a/flang/test/lit.cfg.py b/flang/test/lit.cfg.py index 65467f2d23f4ff2268d5019b893dc8d3385abcec..5eeada0e9ee3fb5ad47db991d908c2cdef5410c3 100644 --- a/flang/test/lit.cfg.py +++ b/flang/test/lit.cfg.py @@ -200,6 +200,10 @@ result = lit_config.params.get("LIBPGMATH") if result: config.environment["LIBPGMATH"] = True +# Determine if OpenMP runtime was built (enable OpenMP tests via REQUIRES in test file) +if config.have_openmp_rtl: + config.available_features.add("openmp_runtime") + # Add features and substitutions to test F128 math support. # %f128-lib substitution may be used to generate check prefixes # for LIT tests checking for F128 library support. diff --git a/flang/test/lit.site.cfg.py.in b/flang/test/lit.site.cfg.py.in index e66f1af794526eee22fe0872ff2bc2dc2c6eed8e..b9b7a7c5fd63cf16bb23111ff9dfefcd08480dd6 100644 --- a/flang/test/lit.site.cfg.py.in +++ b/flang/test/lit.site.cfg.py.in @@ -25,6 +25,7 @@ config.cc = "@CMAKE_C_COMPILER@" config.osx_sysroot = path(r"@CMAKE_OSX_SYSROOT@") config.targets_to_build = "@TARGETS_TO_BUILD@" config.default_sysroot = "@DEFAULT_SYSROOT@" +config.have_openmp_rtl = ("@LLVM_TOOL_OPENMP_BUILD@" == "TRUE") config.flang_runtime_f128_math_lib = "@FLANG_RUNTIME_F128_MATH_LIB@" import lit.llvm diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp index 73d740ff4394219648624253d0d4a88d40099db6..a0870d3649c2e4b6b89e42f84bbf7b37480de7cf 100644 --- a/flang/tools/bbc/bbc.cpp +++ b/flang/tools/bbc/bbc.cpp @@ -191,11 +191,6 @@ static llvm::cl::opt<bool> enableOpenACC("fopenacc", llvm::cl::desc("enable openacc"), llvm::cl::init(false)); -static llvm::cl::opt<bool> enablePolymorphic( - "polymorphic-type", - llvm::cl::desc("enable polymorphic type lowering (experimental)"), - llvm::cl::init(false)); - static llvm::cl::opt<bool> enableNoPPCNativeVecElemOrder( "fno-ppc-native-vector-element-order", llvm::cl::desc("no PowerPC native vector element order."), @@ -351,7 +346,6 @@ static mlir::LogicalResult convertFortranSourceToMLIR( std::string targetTriple = targetMachine.getTargetTriple().normalize(); // Use default lowering options for bbc. Fortran::lower::LoweringOptions loweringOptions{}; - loweringOptions.setPolymorphicTypeImpl(enablePolymorphic); loweringOptions.setNoPPCNativeVecElemOrder(enableNoPPCNativeVecElemOrder); loweringOptions.setLowerToHighLevelFIR(useHLFIR || emitHLFIR); std::vector<Fortran::lower::EnvironmentDefault> envDefaults = {}; diff --git a/flang/tools/f18/CMakeLists.txt b/flang/tools/f18/CMakeLists.txt index ba6c6642c0b62e28c7f0103dcaf3cd0119738f23..3a31f4df1607a914d9b013d9064d13edbe5cc762 100644 --- a/flang/tools/f18/CMakeLists.txt +++ b/flang/tools/f18/CMakeLists.txt @@ -17,7 +17,6 @@ set(MODULES "ieee_features" "iso_c_binding" "iso_fortran_env" - "omp_lib" "__fortran_builtins" "__fortran_type_info" ) @@ -59,11 +58,12 @@ if (NOT CMAKE_CROSSCOMPILING) endif() endif() + # TODO: We may need to flag this with conditional, in case Flang is built w/o OpenMP support add_custom_command(OUTPUT ${base}.mod COMMAND ${CMAKE_COMMAND} -E make_directory ${FLANG_INTRINSIC_MODULES_DIR} COMMAND flang-new -cpp -fsyntax-only ${opts} -module-dir ${FLANG_INTRINSIC_MODULES_DIR} ${FLANG_SOURCE_DIR}/module/${filename}.f90 - DEPENDS flang-new ${FLANG_SOURCE_DIR}/module/${filename}.f90 ${depends} + DEPENDS flang-new ${FLANG_SOURCE_DIR}/module/${filename}.f90 ${FLANG_SOURCE_DIR}/module/__fortran_builtins.f90 ${depends} ) add_custom_command(OUTPUT ${base}.f18.mod DEPENDS ${base}.mod @@ -71,6 +71,30 @@ if (NOT CMAKE_CROSSCOMPILING) list(APPEND MODULE_FILES ${base}.mod ${base}.f18.mod) install(FILES ${base}.mod ${base}.f18.mod DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/flang") endforeach() + + # Special case for omp_lib.mod, because its source comes from openmp/runtime/src/include. + # It also produces two module files: omp_lib.mod and omp_lib_kinds.mod. Compile these + # files only if OpenMP support has been configured. + if (LLVM_TOOL_OPENMP_BUILD) + message(STATUS "OpenMP runtime support enabled via LLVM_ENABLED_PROJECTS, building omp_lib.mod") + set(base ${FLANG_INTRINSIC_MODULES_DIR}/omp_lib) + add_custom_command(OUTPUT ${base}.mod ${base}_kinds.mod + COMMAND ${CMAKE_COMMAND} -E make_directory ${FLANG_INTRINSIC_MODULES_DIR} + COMMAND flang-new -cpp -fsyntax-only ${opts} -module-dir ${FLANG_INTRINSIC_MODULES_DIR} + ${CMAKE_BINARY_DIR}/projects/openmp/runtime/src/omp_lib.F90 + DEPENDS flang-new ${FLANG_INTRINSIC_MODULES_DIR}/iso_c_binding.mod ${CMAKE_BINARY_DIR}/projects/openmp/runtime/src/omp_lib.F90 ${depends} + ) + add_custom_command(OUTPUT ${base}.f18.mod + DEPENDS ${base}.mod + COMMAND ${CMAKE_COMMAND} -E copy ${base}.mod ${base}.f18.mod) + add_custom_command(OUTPUT ${base}_kinds.f18.mod + DEPENDS ${base}.mod + COMMAND ${CMAKE_COMMAND} -E copy ${base}_kinds.mod ${base}_kinds.f18.mod) + list(APPEND MODULE_FILES ${base}.mod ${base}.f18.mod ${base}_kinds.mod ${base}_kinds.f18.mod) + install(FILES ${base}.mod ${base}.f18.mod ${base}_kinds.mod ${base}_kinds.f18.mod DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/flang") + else() + message(STATUS "Not building omp_lib.mod, no OpenMP runtime in LLVM_ENABLED_PROJECTS") + endif() endif() add_custom_target(module_files ALL DEPENDS ${MODULE_FILES}) @@ -87,5 +111,11 @@ if (NOT WIN32) endif() # TODO Move this to a more suitable location -file(COPY ${FLANG_SOURCE_DIR}/module/omp_lib.h DESTINATION "${CMAKE_BINARY_DIR}/include/flang/OpenMP/" FILE_PERMISSIONS OWNER_READ OWNER_WRITE) -install(FILES ${CMAKE_BINARY_DIR}/include/flang/OpenMP/omp_lib.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/flang/OpenMP") +# Copy the generated omp_lib.h header file, if OpenMP support has been configured. +if (LLVM_TOOL_OPENMP_BUILD) + message(STATUS "OpenMP runtime support enabled via LLVM_ENABLED_PROJECTS, building omp_lib.h") + file(COPY ${CMAKE_BINARY_DIR}/projects/openmp/runtime/src/omp_lib.h DESTINATION "${CMAKE_BINARY_DIR}/include/flang/OpenMP/" FILE_PERMISSIONS OWNER_READ OWNER_WRITE) + install(FILES ${CMAKE_BINARY_DIR}/include/flang/OpenMP/omp_lib.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/flang/OpenMP") +else() + message(STATUS "Not copying omp_lib.h, no OpenMP runtime in LLVM_ENABLED_PROJECTS") +endif() diff --git a/flang/unittests/Runtime/NumericalFormatTest.cpp b/flang/unittests/Runtime/NumericalFormatTest.cpp index 37eecd7708a1eb5ad8f0d5346d87e38942bcc5ac..dee4dda4a22869cfd0508f5e197143cc993c6179 100644 --- a/flang/unittests/Runtime/NumericalFormatTest.cpp +++ b/flang/unittests/Runtime/NumericalFormatTest.cpp @@ -902,6 +902,14 @@ TEST(IOApiTests, EditDoubleInputValues) { 0}, // max finite {"(EX22.0)", "0X.8P1025 ", 0x7ff0000000000000, ovf}, // +Inf {"(EX22.0)", "-0X.8P1025 ", 0xfff0000000000000, ovf}, // -Inf + {"(RC,EX22.0)", "0X1.0000000000000P0 ", 0x3ff0000000000000, 0}, + {"(RC,EX22.0)", "0X1.00000000000008P0 ", 0x3ff0000000000001, 0}, + {"(RC,EX22.0)", "0X1.000000000000008P0 ", 0x3ff0000000000000, 0}, + {"(RC,EX22.0)", "0X1.00000000000004P0 ", 0x3ff0000000000000, 0}, + {"(RC,EX22.0)", "0X.80000000000000P1 ", 0x3ff0000000000000, 0}, + {"(RC,EX22.0)", "0X.80000000000004P1 ", 0x3ff0000000000001, 0}, + {"(RC,EX22.0)", "0X.800000000000004P1 ", 0x3ff0000000000000, 0}, + {"(RC,EX22.0)", "0X.80000000000002P1 ", 0x3ff0000000000000, 0}, {"(RZ,F7.0)", " 2.e308", 0x7fefffffffffffff, 0}, // +HUGE() {"(RD,F7.0)", " 2.e308", 0x7fefffffffffffff, 0}, // +HUGE() {"(RU,F7.0)", " 2.e308", 0x7ff0000000000000, ovf}, // +Inf diff --git a/flang/unittests/Runtime/Reduction.cpp b/flang/unittests/Runtime/Reduction.cpp index b17988bc17699d4e79e53bb07e4b056652efd3bb..b2661e78abdf584bc1f371146d59029ede342533 100644 --- a/flang/unittests/Runtime/Reduction.cpp +++ b/flang/unittests/Runtime/Reduction.cpp @@ -13,6 +13,7 @@ #include "flang/Runtime/allocatable.h" #include "flang/Runtime/cpp-type.h" #include "flang/Runtime/descriptor.h" +#include "flang/Runtime/reduce.h" #include "flang/Runtime/type-code.h" #include <cstdint> #include <cstring> @@ -634,3 +635,39 @@ TEST(Reductions, ExtremaReal16) { EXPECT_EQ(RTNAME(MaxvalReal16)(*maxArray, __FILE__, __LINE__), -1.0); } #endif // LDBL_MANT_DIG == 113 || HAS_FLOAT128 + +static std::int32_t IAdd(const std::int32_t *x, const std::int32_t *y) { + return *x + *y; +} + +static std::int32_t IMultiply(const std::int32_t *x, const std::int32_t *y) { + return *x * *y; +} + +TEST(Reductions, ReduceInt4) { + auto intVector{MakeArray<TypeCategory::Integer, 4>( + std::vector<int>{4}, std::vector<std::int32_t>{1, 2, 3, 4})}; + EXPECT_EQ(RTNAME(ReduceInteger4)(*intVector, IAdd, __FILE__, __LINE__), 10); + EXPECT_EQ( + RTNAME(ReduceInteger4)(*intVector, IMultiply, __FILE__, __LINE__), 24); +} +TEST(Reductions, ReduceInt4Dim) { + auto intMatrix{MakeArray<TypeCategory::Integer, 4>( + std::vector<int>{2, 2}, std::vector<std::int32_t>{1, 2, 3, 4})}; + StaticDescriptor<1, true> statDesc; + Descriptor &sums{statDesc.descriptor()}; + RTNAME(ReduceInteger4Dim)(sums, *intMatrix, IAdd, __FILE__, __LINE__, 1); + EXPECT_EQ(sums.rank(), 1); + EXPECT_EQ(sums.GetDimension(0).LowerBound(), 1); + EXPECT_EQ(sums.GetDimension(0).Extent(), 2); + EXPECT_EQ(*sums.ZeroBasedIndexedElement<std::int32_t>(0), 3); + EXPECT_EQ(*sums.ZeroBasedIndexedElement<std::int32_t>(1), 7); + sums.Destroy(); + RTNAME(ReduceInteger4Dim)(sums, *intMatrix, IAdd, __FILE__, __LINE__, 2); + EXPECT_EQ(sums.rank(), 1); + EXPECT_EQ(sums.GetDimension(0).LowerBound(), 1); + EXPECT_EQ(sums.GetDimension(0).Extent(), 2); + EXPECT_EQ(*sums.ZeroBasedIndexedElement<std::int32_t>(0), 4); + EXPECT_EQ(*sums.ZeroBasedIndexedElement<std::int32_t>(1), 6); + sums.Destroy(); +} diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index 6edf5c656193db378d87e7aa72f24fff2a3f56ff..a0d79858a896adcdbf8b3b0630259c46a6310b46 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -61,7 +61,8 @@ if(LLVM_LIBC_FULL_BUILD OR LLVM_LIBC_GPU_BUILD) endif() endif() # We will build the GPU utilities if we are not doing a runtimes build. -if(LLVM_LIBC_GPU_BUILD AND NOT LLVM_RUNTIMES_BUILD) +option(LIBC_BUILD_GPU_LOADER "Always build the GPU loader utilities" OFF) +if(LIBC_BUILD_GPU_LOADER OR (LLVM_LIBC_GPU_BUILD AND NOT LLVM_RUNTIMES_BUILD)) add_subdirectory(utils/gpu) endif() @@ -134,7 +135,6 @@ option(LLVM_LIBC_FULL_BUILD "Build and test LLVM libc as if it is the full libc" option(LLVM_LIBC_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR "Build LLVM libc tests assuming our implementation-defined behavior" ON) option(LLVM_LIBC_ENABLE_LINTING "Enables linting of libc source files" OFF) -option(LIBC_GPU_BUILD "Build libc for the GPU. All CPU build options will be ignored." OFF) set(LIBC_TARGET_TRIPLE "" CACHE STRING "The target triple for the libc build.") option(LIBC_CONFIG_PATH "The path to user provided folder that configures the build for the target system." OFF) diff --git a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake index 5bc0898298ce39ddcf4dd5b7ec0b59e21e2bb1aa..40a1cfda060e6f1eee78cdfc6661fbb1f26e04a2 100644 --- a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake +++ b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake @@ -60,6 +60,15 @@ function(_get_common_compile_options output_var flags) if (LIBC_CC_SUPPORTS_PATTERN_INIT) list(APPEND compile_options "-ftrivial-auto-var-init=pattern") endif() + if (LIBC_CONF_KEEP_FRAME_POINTER) + list(APPEND compile_options "-fno-omit-frame-pointer") + if (LIBC_TARGET_ARCHITECTURE_IS_X86) + list(APPEND compile_options "-mno-omit-leaf-frame-pointer") + endif() + endif() + if (LIBC_CONF_ENABLE_STACK_PROTECTOR) + list(APPEND compile_options "-fstack-protector-strong") + endif() list(APPEND compile_options "-Wall") list(APPEND compile_options "-Wextra") # -DLIBC_WNO_ERROR=ON if you can't build cleanly with -Werror. diff --git a/libc/cmake/modules/prepare_libc_gpu_build.cmake b/libc/cmake/modules/prepare_libc_gpu_build.cmake index bea6bb016491b6e8b8aff7a53134a03cc57ba457..20aca16990fc6328f3f698b320423b8a26dfe9bc 100644 --- a/libc/cmake/modules/prepare_libc_gpu_build.cmake +++ b/libc/cmake/modules/prepare_libc_gpu_build.cmake @@ -93,6 +93,11 @@ else() endif() set(LIBC_GPU_TARGET_ARCHITECTURE "${gpu_test_architecture}") +# The NVPTX backend cannot currently handle objects created in debug mode. +if(LIBC_TARGET_ARCHITECTURE_IS_NVPTX AND CMAKE_BUILD_TYPE STREQUAL "Debug") + set(LIBC_GPU_TESTS_DISABLED TRUE) +endif() + # Identify the GPU loader utility used to run tests. set(LIBC_GPU_LOADER_EXECUTABLE "" CACHE STRING "Executable for the GPU loader.") if(LIBC_GPU_LOADER_EXECUTABLE) diff --git a/libc/config/baremetal/api.td b/libc/config/baremetal/api.td index 33b3a03828e9c7427b18f5b7e059672e2bc458de..25aa06aacb642eec70398dc2070aae82e12da76d 100644 --- a/libc/config/baremetal/api.td +++ b/libc/config/baremetal/api.td @@ -2,6 +2,7 @@ include "config/public_api.td" include "spec/stdc.td" include "spec/stdc_ext.td" +include "spec/bsd_ext.td" include "spec/llvm_libc_stdfix_ext.td" def AssertMacro : MacroDef<"assert"> { @@ -51,6 +52,14 @@ def IntTypesAPI : PublicAPI<"inttypes.h"> { let Types = ["imaxdiv_t"]; } +def MathAPI : PublicAPI<"math.h"> { + let Types = ["double_t", "float_t"]; +} + +def StdIOAPI : PublicAPI<"stdio.h"> { + let Types = ["size_t"]; +} + def StdlibAPI : PublicAPI<"stdlib.h"> { let Types = [ "div_t", @@ -59,10 +68,22 @@ def StdlibAPI : PublicAPI<"stdlib.h"> { "size_t", "__bsearchcompare_t", "__qsortcompare_t", - "__atexithandler_t", ]; } def StringAPI : PublicAPI<"string.h"> { let Types = ["size_t"]; } + +def TimeAPI : PublicAPI<"time.h"> { + let Types = [ + "clock_t", + "time_t", + "struct tm", + "struct timespec", + ]; +} + +def UCharAPI : PublicAPI<"uchar.h"> { + let Types = ["mbstate_t"]; +} diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt index 6e4fdb0362643655f8d7053c5cd59dbca965c225..9e21f5c20d92073a745aa379207b305d70c83bc2 100644 --- a/libc/config/baremetal/arm/entrypoints.txt +++ b/libc/config/baremetal/arm/entrypoints.txt @@ -30,6 +30,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.bcmp libc.src.string.bcopy libc.src.string.bzero + libc.src.string.index libc.src.string.memccpy libc.src.string.memchr libc.src.string.memcmp @@ -39,6 +40,8 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.mempcpy libc.src.string.memrchr libc.src.string.memset + libc.src.string.memset_explicit + libc.src.string.rindex libc.src.string.stpcpy libc.src.string.stpncpy libc.src.string.strcasecmp @@ -47,8 +50,11 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strchr libc.src.string.strchrnul libc.src.string.strcmp + libc.src.string.strcoll libc.src.string.strcpy libc.src.string.strcspn + libc.src.string.strerror + libc.src.string.strerror_r libc.src.string.strlcat libc.src.string.strlcpy libc.src.string.strlen @@ -59,10 +65,12 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strnlen libc.src.string.strpbrk libc.src.string.strrchr + libc.src.string.strsep libc.src.string.strspn libc.src.string.strstr libc.src.string.strtok libc.src.string.strtok_r + libc.src.string.strxfrm # inttypes.h entrypoints libc.src.inttypes.imaxabs @@ -71,6 +79,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.inttypes.strtoumax # stdio.h entrypoints + libc.src.stdio.remove libc.src.stdio.sprintf libc.src.stdio.snprintf libc.src.stdio.vsprintf @@ -117,6 +126,36 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdbit.stdc_first_trailing_one_ui libc.src.stdbit.stdc_first_trailing_one_ul libc.src.stdbit.stdc_first_trailing_one_ull + libc.src.stdbit.stdc_count_zeros_uc + libc.src.stdbit.stdc_count_zeros_us + libc.src.stdbit.stdc_count_zeros_ui + libc.src.stdbit.stdc_count_zeros_ul + libc.src.stdbit.stdc_count_zeros_ull + libc.src.stdbit.stdc_count_ones_uc + libc.src.stdbit.stdc_count_ones_us + libc.src.stdbit.stdc_count_ones_ui + libc.src.stdbit.stdc_count_ones_ul + libc.src.stdbit.stdc_count_ones_ull + libc.src.stdbit.stdc_has_single_bit_uc + libc.src.stdbit.stdc_has_single_bit_us + libc.src.stdbit.stdc_has_single_bit_ui + libc.src.stdbit.stdc_has_single_bit_ul + libc.src.stdbit.stdc_has_single_bit_ull + libc.src.stdbit.stdc_bit_width_uc + libc.src.stdbit.stdc_bit_width_us + libc.src.stdbit.stdc_bit_width_ui + libc.src.stdbit.stdc_bit_width_ul + libc.src.stdbit.stdc_bit_width_ull + libc.src.stdbit.stdc_bit_floor_uc + libc.src.stdbit.stdc_bit_floor_us + libc.src.stdbit.stdc_bit_floor_ui + libc.src.stdbit.stdc_bit_floor_ul + libc.src.stdbit.stdc_bit_floor_ull + libc.src.stdbit.stdc_bit_ceil_uc + libc.src.stdbit.stdc_bit_ceil_us + libc.src.stdbit.stdc_bit_ceil_ui + libc.src.stdbit.stdc_bit_ceil_ul + libc.src.stdbit.stdc_bit_ceil_ull # stdlib.h entrypoints libc.src.stdlib.abort @@ -132,6 +171,8 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdlib.llabs libc.src.stdlib.lldiv libc.src.stdlib.qsort + libc.src.stdlib.rand + libc.src.stdlib.srand libc.src.stdlib.strtod libc.src.stdlib.strtof libc.src.stdlib.strtol @@ -139,6 +180,9 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdlib.strtoll libc.src.stdlib.strtoul libc.src.stdlib.strtoull + + # time.h entrypoints + libc.src.time.difftime ) set(TARGET_LIBM_ENTRYPOINTS @@ -163,6 +207,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.acoshf libc.src.math.asinf libc.src.math.asinhf + libc.src.math.atan2f libc.src.math.atanf libc.src.math.atanhf libc.src.math.ceil @@ -201,6 +246,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fminl libc.src.math.fmod libc.src.math.fmodf + libc.src.math.fmodl libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl @@ -212,6 +258,9 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.ldexp libc.src.math.ldexpf libc.src.math.ldexpl + libc.src.math.llogb + libc.src.math.llogbf + libc.src.math.llogbl libc.src.math.llrint libc.src.math.llrintf libc.src.math.llrintl diff --git a/libc/config/baremetal/arm/headers.txt b/libc/config/baremetal/arm/headers.txt index 68d7017fda8027bc1eef453ac6e40ed1dc0b45eb..3608364e45bdeb31f2caeae493755d357238efc0 100644 --- a/libc/config/baremetal/arm/headers.txt +++ b/libc/config/baremetal/arm/headers.txt @@ -13,4 +13,6 @@ set(TARGET_PUBLIC_HEADERS libc.include.string libc.include.strings libc.include.sys_queue + libc.include.time + libc.include.uchar ) diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt index 6e4fdb0362643655f8d7053c5cd59dbca965c225..7664937da0f6e0abba8ba347059e0cd4cf88d304 100644 --- a/libc/config/baremetal/riscv/entrypoints.txt +++ b/libc/config/baremetal/riscv/entrypoints.txt @@ -30,6 +30,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.bcmp libc.src.string.bcopy libc.src.string.bzero + libc.src.string.index libc.src.string.memccpy libc.src.string.memchr libc.src.string.memcmp @@ -39,6 +40,8 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.mempcpy libc.src.string.memrchr libc.src.string.memset + libc.src.string.memset_explicit + libc.src.string.rindex libc.src.string.stpcpy libc.src.string.stpncpy libc.src.string.strcasecmp @@ -47,8 +50,11 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strchr libc.src.string.strchrnul libc.src.string.strcmp + libc.src.string.strcoll libc.src.string.strcpy libc.src.string.strcspn + libc.src.string.strerror + libc.src.string.strerror_r libc.src.string.strlcat libc.src.string.strlcpy libc.src.string.strlen @@ -59,10 +65,12 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.strnlen libc.src.string.strpbrk libc.src.string.strrchr + libc.src.string.strsep libc.src.string.strspn libc.src.string.strstr libc.src.string.strtok libc.src.string.strtok_r + libc.src.string.strxfrm # inttypes.h entrypoints libc.src.inttypes.imaxabs @@ -71,6 +79,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.inttypes.strtoumax # stdio.h entrypoints + libc.src.stdio.remove libc.src.stdio.sprintf libc.src.stdio.snprintf libc.src.stdio.vsprintf @@ -117,6 +126,36 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdbit.stdc_first_trailing_one_ui libc.src.stdbit.stdc_first_trailing_one_ul libc.src.stdbit.stdc_first_trailing_one_ull + libc.src.stdbit.stdc_count_zeros_uc + libc.src.stdbit.stdc_count_zeros_us + libc.src.stdbit.stdc_count_zeros_ui + libc.src.stdbit.stdc_count_zeros_ul + libc.src.stdbit.stdc_count_zeros_ull + libc.src.stdbit.stdc_count_ones_uc + libc.src.stdbit.stdc_count_ones_us + libc.src.stdbit.stdc_count_ones_ui + libc.src.stdbit.stdc_count_ones_ul + libc.src.stdbit.stdc_count_ones_ull + libc.src.stdbit.stdc_has_single_bit_uc + libc.src.stdbit.stdc_has_single_bit_us + libc.src.stdbit.stdc_has_single_bit_ui + libc.src.stdbit.stdc_has_single_bit_ul + libc.src.stdbit.stdc_has_single_bit_ull + libc.src.stdbit.stdc_bit_width_uc + libc.src.stdbit.stdc_bit_width_us + libc.src.stdbit.stdc_bit_width_ui + libc.src.stdbit.stdc_bit_width_ul + libc.src.stdbit.stdc_bit_width_ull + libc.src.stdbit.stdc_bit_floor_uc + libc.src.stdbit.stdc_bit_floor_us + libc.src.stdbit.stdc_bit_floor_ui + libc.src.stdbit.stdc_bit_floor_ul + libc.src.stdbit.stdc_bit_floor_ull + libc.src.stdbit.stdc_bit_ceil_uc + libc.src.stdbit.stdc_bit_ceil_us + libc.src.stdbit.stdc_bit_ceil_ui + libc.src.stdbit.stdc_bit_ceil_ul + libc.src.stdbit.stdc_bit_ceil_ull # stdlib.h entrypoints libc.src.stdlib.abort @@ -132,6 +171,8 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdlib.llabs libc.src.stdlib.lldiv libc.src.stdlib.qsort + libc.src.stdlib.rand + libc.src.stdlib.srand libc.src.stdlib.strtod libc.src.stdlib.strtof libc.src.stdlib.strtol @@ -139,6 +180,9 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdlib.strtoll libc.src.stdlib.strtoul libc.src.stdlib.strtoull + + # time.h entrypoints + libc.src.time.difftime ) set(TARGET_LIBM_ENTRYPOINTS @@ -163,6 +207,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.acoshf libc.src.math.asinf libc.src.math.asinhf + libc.src.math.atan2f libc.src.math.atanf libc.src.math.atanhf libc.src.math.ceil @@ -212,6 +257,9 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.ldexp libc.src.math.ldexpf libc.src.math.ldexpl + libc.src.math.llogb + libc.src.math.llogbf + libc.src.math.llogbl libc.src.math.llrint libc.src.math.llrintf libc.src.math.llrintl diff --git a/libc/config/baremetal/riscv/headers.txt b/libc/config/baremetal/riscv/headers.txt index 68d7017fda8027bc1eef453ac6e40ed1dc0b45eb..3608364e45bdeb31f2caeae493755d357238efc0 100644 --- a/libc/config/baremetal/riscv/headers.txt +++ b/libc/config/baremetal/riscv/headers.txt @@ -13,4 +13,6 @@ set(TARGET_PUBLIC_HEADERS libc.include.string libc.include.strings libc.include.sys_queue + libc.include.time + libc.include.uchar ) diff --git a/libc/config/config.json b/libc/config/config.json index b73c47b1a14bc7e21adb157aabaae57cd9485c6f..d6ef891b9f260f03d3b65c72f356503eb5feb78e 100644 --- a/libc/config/config.json +++ b/libc/config/config.json @@ -30,5 +30,15 @@ "value": false, "doc": "Inserts prefetch for write instructions (PREFETCHW) for memset on x86 to recover performance when hardware prefetcher is disabled." } + }, + "codegen": { + "LIBC_CONF_KEEP_FRAME_POINTER": { + "value": true, + "doc": "Keep frame pointer in functions for better debugging experience." + }, + "LIBC_CONF_ENABLE_STRONG_STACK_PROTECTOR": { + "value": true, + "doc": "Enable -fstack-protector-strong to defend against stack smashing attack." + } } } diff --git a/libc/config/darwin/arm/entrypoints.txt b/libc/config/darwin/arm/entrypoints.txt index 02a09256606956b25fbabb61e97a36917bc610ac..6b89ce55d72b65fc5de24aa6ebaa45287b460bb1 100644 --- a/libc/config/darwin/arm/entrypoints.txt +++ b/libc/config/darwin/arm/entrypoints.txt @@ -118,6 +118,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.acoshf libc.src.math.asinf libc.src.math.asinhf + libc.src.math.atan2f libc.src.math.atanf libc.src.math.atanhf libc.src.math.copysign diff --git a/libc/config/gpu/api.td b/libc/config/gpu/api.td index 607b8b6d5900c8909437ffdbc2c9e25039db8230..adaf5bfd747ac72aa4b636283dc03eb6ce1ebf05 100644 --- a/libc/config/gpu/api.td +++ b/libc/config/gpu/api.td @@ -63,7 +63,6 @@ def StdIOAPI : PublicAPI<"stdio.h"> { SimpleMacroDef<"_IOFBF", "0">, SimpleMacroDef<"_IOLBF", "1">, SimpleMacroDef<"_IONBF", "2">, - SimpleMacroDef<"EOF", "-1">, ]; let Types = ["size_t", "FILE"]; } diff --git a/libc/config/gpu/entrypoints.txt b/libc/config/gpu/entrypoints.txt index fca5315fc4f0a8af68862f3664d1e0527828f078..4fb87cb9f5a33efbb1d878c9bfc3fd5a477f497c 100644 --- a/libc/config/gpu/entrypoints.txt +++ b/libc/config/gpu/entrypoints.txt @@ -106,6 +106,36 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdbit.stdc_first_trailing_one_ui libc.src.stdbit.stdc_first_trailing_one_ul libc.src.stdbit.stdc_first_trailing_one_ull + libc.src.stdbit.stdc_count_zeros_uc + libc.src.stdbit.stdc_count_zeros_us + libc.src.stdbit.stdc_count_zeros_ui + libc.src.stdbit.stdc_count_zeros_ul + libc.src.stdbit.stdc_count_zeros_ull + libc.src.stdbit.stdc_count_ones_uc + libc.src.stdbit.stdc_count_ones_us + libc.src.stdbit.stdc_count_ones_ui + libc.src.stdbit.stdc_count_ones_ul + libc.src.stdbit.stdc_count_ones_ull + libc.src.stdbit.stdc_has_single_bit_uc + libc.src.stdbit.stdc_has_single_bit_us + libc.src.stdbit.stdc_has_single_bit_ui + libc.src.stdbit.stdc_has_single_bit_ul + libc.src.stdbit.stdc_has_single_bit_ull + libc.src.stdbit.stdc_bit_width_uc + libc.src.stdbit.stdc_bit_width_us + libc.src.stdbit.stdc_bit_width_ui + libc.src.stdbit.stdc_bit_width_ul + libc.src.stdbit.stdc_bit_width_ull + libc.src.stdbit.stdc_bit_floor_uc + libc.src.stdbit.stdc_bit_floor_us + libc.src.stdbit.stdc_bit_floor_ui + libc.src.stdbit.stdc_bit_floor_ul + libc.src.stdbit.stdc_bit_floor_ull + libc.src.stdbit.stdc_bit_ceil_uc + libc.src.stdbit.stdc_bit_ceil_us + libc.src.stdbit.stdc_bit_ceil_ui + libc.src.stdbit.stdc_bit_ceil_ul + libc.src.stdbit.stdc_bit_ceil_ull # stdlib.h entrypoints libc.src.stdlib.abs diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 1656973cb27c8a01371bb45952d1d15863654144..8bf99459f7898de9fcc4be396e5015ca6fe2784d 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -131,6 +131,36 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdbit.stdc_first_trailing_one_ui libc.src.stdbit.stdc_first_trailing_one_ul libc.src.stdbit.stdc_first_trailing_one_ull + libc.src.stdbit.stdc_count_zeros_uc + libc.src.stdbit.stdc_count_zeros_us + libc.src.stdbit.stdc_count_zeros_ui + libc.src.stdbit.stdc_count_zeros_ul + libc.src.stdbit.stdc_count_zeros_ull + libc.src.stdbit.stdc_count_ones_uc + libc.src.stdbit.stdc_count_ones_us + libc.src.stdbit.stdc_count_ones_ui + libc.src.stdbit.stdc_count_ones_ul + libc.src.stdbit.stdc_count_ones_ull + libc.src.stdbit.stdc_has_single_bit_uc + libc.src.stdbit.stdc_has_single_bit_us + libc.src.stdbit.stdc_has_single_bit_ui + libc.src.stdbit.stdc_has_single_bit_ul + libc.src.stdbit.stdc_has_single_bit_ull + libc.src.stdbit.stdc_bit_width_uc + libc.src.stdbit.stdc_bit_width_us + libc.src.stdbit.stdc_bit_width_ui + libc.src.stdbit.stdc_bit_width_ul + libc.src.stdbit.stdc_bit_width_ull + libc.src.stdbit.stdc_bit_floor_uc + libc.src.stdbit.stdc_bit_floor_us + libc.src.stdbit.stdc_bit_floor_ui + libc.src.stdbit.stdc_bit_floor_ul + libc.src.stdbit.stdc_bit_floor_ull + libc.src.stdbit.stdc_bit_ceil_uc + libc.src.stdbit.stdc_bit_ceil_us + libc.src.stdbit.stdc_bit_ceil_ui + libc.src.stdbit.stdc_bit_ceil_ul + libc.src.stdbit.stdc_bit_ceil_ull # stdlib.h entrypoints libc.src.stdlib.abs @@ -165,6 +195,7 @@ set(TARGET_LIBC_ENTRYPOINTS # stdio.h entrypoints libc.src.stdio.remove + libc.src.stdio.rename libc.src.stdio.sprintf libc.src.stdio.snprintf libc.src.stdio.vsprintf @@ -186,6 +217,8 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.sys.mman.mlockall libc.src.sys.mman.munlockall libc.src.sys.mman.msync + libc.src.sys.mman.shm_open + libc.src.sys.mman.shm_unlink # sys/random.h entrypoints libc.src.sys.random.getrandom @@ -297,6 +330,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.acoshf libc.src.math.asinf libc.src.math.asinhf + libc.src.math.atan2f libc.src.math.atanf libc.src.math.atanhf libc.src.math.copysign @@ -333,6 +367,30 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fmin libc.src.math.fminf libc.src.math.fminl + libc.src.math.fmaximum + libc.src.math.fmaximumf + libc.src.math.fmaximuml + libc.src.math.fmaximum_num + libc.src.math.fmaximum_numf + libc.src.math.fmaximum_numl + libc.src.math.fmaximum_mag + libc.src.math.fmaximum_magf + libc.src.math.fmaximum_magl + libc.src.math.fmaximum_mag_num + libc.src.math.fmaximum_mag_numf + libc.src.math.fmaximum_mag_numl + libc.src.math.fminimum + libc.src.math.fminimumf + libc.src.math.fminimuml + libc.src.math.fminimum_num + libc.src.math.fminimum_numf + libc.src.math.fminimum_numl + libc.src.math.fminimum_mag + libc.src.math.fminimum_magf + libc.src.math.fminimum_magl + libc.src.math.fminimum_mag_num + libc.src.math.fminimum_mag_numf + libc.src.math.fminimum_mag_numl libc.src.math.fmod libc.src.math.fmodf libc.src.math.fmodl @@ -385,9 +443,15 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.nextafter libc.src.math.nextafterf libc.src.math.nextafterl + libc.src.math.nextdown + libc.src.math.nextdownf + libc.src.math.nextdownl libc.src.math.nexttoward libc.src.math.nexttowardf libc.src.math.nexttowardl + libc.src.math.nextup + libc.src.math.nextupf + libc.src.math.nextupl libc.src.math.powf libc.src.math.remainderf libc.src.math.remainder @@ -427,6 +491,14 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.floorf128 libc.src.math.fmaxf128 libc.src.math.fminf128 + libc.src.math.fmaximumf128 + libc.src.math.fmaximum_numf128 + libc.src.math.fmaximum_magf128 + libc.src.math.fmaximum_mag_numf128 + libc.src.math.fminimumf128 + libc.src.math.fminimum_numf128 + libc.src.math.fminimum_magf128 + libc.src.math.fminimum_mag_numf128 libc.src.math.fmodf128 libc.src.math.frexpf128 libc.src.math.ilogbf128 @@ -438,6 +510,10 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.lrintf128 libc.src.math.lroundf128 libc.src.math.modff128 + libc.src.math.nanf128 + libc.src.math.nextafterf128 + libc.src.math.nextdownf128 + libc.src.math.nextupf128 libc.src.math.rintf128 libc.src.math.roundf128 libc.src.math.sqrtf128 @@ -508,6 +584,7 @@ if(LLVM_LIBC_FULL_BUILD) libc.src.stdio.ferror_unlocked libc.src.stdio.fgetc libc.src.stdio.fflush + libc.src.stdio.fileno libc.src.stdio.fopen libc.src.stdio.fputc libc.src.stdio.fputs @@ -598,6 +675,7 @@ if(LLVM_LIBC_FULL_BUILD) # unistd.h entrypoints libc.src.unistd.__llvm_libc_syscall + libc.src.unistd._exit libc.src.unistd.environ libc.src.unistd.execv libc.src.unistd.getopt diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td index 75432a2a29865226ef98e9d45101bdd69a994076..eb5ed8089850e468c0c0ce2a96768c101783cbe1 100644 --- a/libc/config/linux/api.td +++ b/libc/config/linux/api.td @@ -76,7 +76,6 @@ def StdIOAPI : PublicAPI<"stdio.h"> { SimpleMacroDef<"_IOFBF", "0">, SimpleMacroDef<"_IOLBF", "1">, SimpleMacroDef<"_IONBF", "2">, - SimpleMacroDef<"EOF", "-1">, ]; let Types = ["size_t", "FILE", "cookie_io_functions_t"]; } @@ -118,7 +117,7 @@ def SchedAPI : PublicAPI<"sched.h"> { } def SysMManAPI : PublicAPI<"sys/mman.h"> { - let Types = ["off_t", "size_t"]; + let Types = ["off_t", "size_t", "mode_t"]; } def SignalAPI : PublicAPI<"signal.h"> { @@ -263,3 +262,7 @@ def SetJmpAPI : PublicAPI<"setjmp.h"> { def SearchAPI : PublicAPI<"search.h"> { let Types = ["ACTION", "ENTRY", "struct hsearch_data"]; } + +def SysStatvfsAPI : PublicAPI<"sys/statvfs.h"> { + let Types = ["fsblkcnt_t", "fsfilcnt_t", "struct statvfs"]; +} diff --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt index 2fca96c5601b08402674985e0073dab221008e0d..04baa4c1cf93ab526bc5cdbb8c8cdd5d1554f5fe 100644 --- a/libc/config/linux/arm/entrypoints.txt +++ b/libc/config/linux/arm/entrypoints.txt @@ -108,6 +108,36 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdbit.stdc_first_trailing_one_ui libc.src.stdbit.stdc_first_trailing_one_ul libc.src.stdbit.stdc_first_trailing_one_ull + libc.src.stdbit.stdc_count_zeros_uc + libc.src.stdbit.stdc_count_zeros_us + libc.src.stdbit.stdc_count_zeros_ui + libc.src.stdbit.stdc_count_zeros_ul + libc.src.stdbit.stdc_count_zeros_ull + libc.src.stdbit.stdc_count_ones_uc + libc.src.stdbit.stdc_count_ones_us + libc.src.stdbit.stdc_count_ones_ui + libc.src.stdbit.stdc_count_ones_ul + libc.src.stdbit.stdc_count_ones_ull + libc.src.stdbit.stdc_has_single_bit_uc + libc.src.stdbit.stdc_has_single_bit_us + libc.src.stdbit.stdc_has_single_bit_ui + libc.src.stdbit.stdc_has_single_bit_ul + libc.src.stdbit.stdc_has_single_bit_ull + libc.src.stdbit.stdc_bit_width_uc + libc.src.stdbit.stdc_bit_width_us + libc.src.stdbit.stdc_bit_width_ui + libc.src.stdbit.stdc_bit_width_ul + libc.src.stdbit.stdc_bit_width_ull + libc.src.stdbit.stdc_bit_floor_uc + libc.src.stdbit.stdc_bit_floor_us + libc.src.stdbit.stdc_bit_floor_ui + libc.src.stdbit.stdc_bit_floor_ul + libc.src.stdbit.stdc_bit_floor_ull + libc.src.stdbit.stdc_bit_ceil_uc + libc.src.stdbit.stdc_bit_ceil_us + libc.src.stdbit.stdc_bit_ceil_ui + libc.src.stdbit.stdc_bit_ceil_ul + libc.src.stdbit.stdc_bit_ceil_ull # stdlib.h entrypoints libc.src.stdlib.abs @@ -168,6 +198,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.acoshf libc.src.math.asinf libc.src.math.asinhf + libc.src.math.atan2f libc.src.math.atanf libc.src.math.atanhf libc.src.math.ceil @@ -204,6 +235,30 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fmin libc.src.math.fminf libc.src.math.fminl + libc.src.math.fmaximum + libc.src.math.fmaximumf + libc.src.math.fmaximuml + libc.src.math.fmaximum_num + libc.src.math.fmaximum_numf + libc.src.math.fmaximum_numl + libc.src.math.fmaximum_mag + libc.src.math.fmaximum_magf + libc.src.math.fmaximum_magl + libc.src.math.fmaximum_mag_num + libc.src.math.fmaximum_mag_numf + libc.src.math.fmaximum_mag_numl + libc.src.math.fminimum + libc.src.math.fminimumf + libc.src.math.fminimuml + libc.src.math.fminimum_num + libc.src.math.fminimum_numf + libc.src.math.fminimum_numl + libc.src.math.fminimum_mag + libc.src.math.fminimum_magf + libc.src.math.fminimum_magl + libc.src.math.fminimum_mag_num + libc.src.math.fminimum_mag_numf + libc.src.math.fminimum_mag_numl libc.src.math.fmod libc.src.math.fmodf libc.src.math.frexp @@ -255,9 +310,15 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.nextafter libc.src.math.nextafterf libc.src.math.nextafterl + libc.src.math.nextdown + libc.src.math.nextdownf + libc.src.math.nextdownl libc.src.math.nexttoward libc.src.math.nexttowardf libc.src.math.nexttowardl + libc.src.math.nextup + libc.src.math.nextupf + libc.src.math.nextupl libc.src.math.powf libc.src.math.remainder libc.src.math.remainderf diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 07d1acfcfe079d9ef36127681332666bb50a31b7..4dc5e9d33f0f84a188bad7b49a1a298d19a5da9c 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -132,6 +132,36 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdbit.stdc_first_trailing_one_ui libc.src.stdbit.stdc_first_trailing_one_ul libc.src.stdbit.stdc_first_trailing_one_ull + libc.src.stdbit.stdc_count_zeros_uc + libc.src.stdbit.stdc_count_zeros_us + libc.src.stdbit.stdc_count_zeros_ui + libc.src.stdbit.stdc_count_zeros_ul + libc.src.stdbit.stdc_count_zeros_ull + libc.src.stdbit.stdc_count_ones_uc + libc.src.stdbit.stdc_count_ones_us + libc.src.stdbit.stdc_count_ones_ui + libc.src.stdbit.stdc_count_ones_ul + libc.src.stdbit.stdc_count_ones_ull + libc.src.stdbit.stdc_has_single_bit_uc + libc.src.stdbit.stdc_has_single_bit_us + libc.src.stdbit.stdc_has_single_bit_ui + libc.src.stdbit.stdc_has_single_bit_ul + libc.src.stdbit.stdc_has_single_bit_ull + libc.src.stdbit.stdc_bit_width_uc + libc.src.stdbit.stdc_bit_width_us + libc.src.stdbit.stdc_bit_width_ui + libc.src.stdbit.stdc_bit_width_ul + libc.src.stdbit.stdc_bit_width_ull + libc.src.stdbit.stdc_bit_floor_uc + libc.src.stdbit.stdc_bit_floor_us + libc.src.stdbit.stdc_bit_floor_ui + libc.src.stdbit.stdc_bit_floor_ul + libc.src.stdbit.stdc_bit_floor_ull + libc.src.stdbit.stdc_bit_ceil_uc + libc.src.stdbit.stdc_bit_ceil_us + libc.src.stdbit.stdc_bit_ceil_ui + libc.src.stdbit.stdc_bit_ceil_ul + libc.src.stdbit.stdc_bit_ceil_ull # stdlib.h entrypoints libc.src.stdlib.abs @@ -166,6 +196,7 @@ set(TARGET_LIBC_ENTRYPOINTS # stdio.h entrypoints libc.src.stdio.remove + libc.src.stdio.rename libc.src.stdio.sprintf libc.src.stdio.snprintf libc.src.stdio.fprintf @@ -191,6 +222,8 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.sys.mman.mlockall libc.src.sys.mman.munlockall libc.src.sys.mman.msync + libc.src.sys.mman.shm_open + libc.src.sys.mman.shm_unlink # sys/random.h entrypoints libc.src.sys.random.getrandom @@ -305,6 +338,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.acoshf libc.src.math.asinf libc.src.math.asinhf + libc.src.math.atan2f libc.src.math.atanf libc.src.math.atanhf libc.src.math.copysign @@ -341,6 +375,30 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fmax libc.src.math.fmaxf libc.src.math.fmaxl + libc.src.math.fmaximum + libc.src.math.fmaximumf + libc.src.math.fmaximuml + libc.src.math.fmaximum_num + libc.src.math.fmaximum_numf + libc.src.math.fmaximum_numl + libc.src.math.fmaximum_mag + libc.src.math.fmaximum_magf + libc.src.math.fmaximum_magl + libc.src.math.fmaximum_mag_num + libc.src.math.fmaximum_mag_numf + libc.src.math.fmaximum_mag_numl + libc.src.math.fminimum + libc.src.math.fminimumf + libc.src.math.fminimuml + libc.src.math.fminimum_num + libc.src.math.fminimum_numf + libc.src.math.fminimum_numl + libc.src.math.fminimum_mag + libc.src.math.fminimum_magf + libc.src.math.fminimum_magl + libc.src.math.fminimum_mag_num + libc.src.math.fminimum_mag_numf + libc.src.math.fminimum_mag_numl libc.src.math.fmod libc.src.math.fmodf libc.src.math.fmodl @@ -393,9 +451,15 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.nextafter libc.src.math.nextafterf libc.src.math.nextafterl + libc.src.math.nextdown + libc.src.math.nextdownf + libc.src.math.nextdownl libc.src.math.nexttoward libc.src.math.nexttowardf libc.src.math.nexttowardl + libc.src.math.nextup + libc.src.math.nextupf + libc.src.math.nextupl libc.src.math.powf libc.src.math.remainderf libc.src.math.remainder @@ -435,6 +499,14 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.floorf128 libc.src.math.fmaxf128 libc.src.math.fminf128 + libc.src.math.fmaximumf128 + libc.src.math.fmaximum_numf128 + libc.src.math.fmaximum_magf128 + libc.src.math.fmaximum_mag_numf128 + libc.src.math.fminimumf128 + libc.src.math.fminimum_numf128 + libc.src.math.fminimum_magf128 + libc.src.math.fminimum_mag_numf128 libc.src.math.fmodf128 libc.src.math.frexpf128 libc.src.math.ilogbf128 @@ -446,6 +518,10 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.lrintf128 libc.src.math.lroundf128 libc.src.math.modff128 + libc.src.math.nanf128 + libc.src.math.nextafterf128 + libc.src.math.nextdownf128 + libc.src.math.nextupf128 libc.src.math.rintf128 libc.src.math.roundf128 libc.src.math.sqrtf128 @@ -531,6 +607,7 @@ if(LLVM_LIBC_FULL_BUILD) libc.src.stdio.fgetc_unlocked libc.src.stdio.fgets libc.src.stdio.fflush + libc.src.stdio.fileno libc.src.stdio.fopen libc.src.stdio.fputc libc.src.stdio.fputs @@ -629,6 +706,7 @@ if(LLVM_LIBC_FULL_BUILD) libc.src.time.time # unistd.h entrypoints + libc.src.unistd._exit libc.src.unistd.environ libc.src.unistd.execv libc.src.unistd.fork diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index e0324061a9c78c05e947007523858ea751f20173..cc7671cab08184dab3829cb6fb4dffbc29e1dd4c 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -180,6 +180,9 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdlib.qsort_r libc.src.stdlib.rand libc.src.stdlib.srand + libc.src.stdlib.strfromd + libc.src.stdlib.strfromf + libc.src.stdlib.strfroml libc.src.stdlib.strtod libc.src.stdlib.strtof libc.src.stdlib.strtol @@ -197,6 +200,7 @@ set(TARGET_LIBC_ENTRYPOINTS # stdio.h entrypoints libc.src.stdio.remove + libc.src.stdio.rename libc.src.stdio.sprintf libc.src.stdio.snprintf libc.src.stdio.fprintf @@ -208,6 +212,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdio.sscanf libc.src.stdio.scanf libc.src.stdio.fscanf + libc.src.stdio.fileno # sys/epoll.h entrypoints libc.src.sys.epoll.epoll_wait @@ -229,6 +234,8 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.sys.mman.mlockall libc.src.sys.mman.munlockall libc.src.sys.mman.msync + libc.src.sys.mman.shm_open + libc.src.sys.mman.shm_unlink # sys/random.h entrypoints libc.src.sys.random.getrandom @@ -250,6 +257,10 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.sys.stat.mkdirat libc.src.sys.stat.stat + # sys/statvfs.h + libc.src.sys.statvfs.statvfs + libc.src.sys.statvfs.fstatvfs + # sys/utsname.h entrypoints libc.src.sys.utsname.uname @@ -337,8 +348,12 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.acoshf libc.src.math.asinf libc.src.math.asinhf + libc.src.math.atan2f libc.src.math.atanf libc.src.math.atanhf + libc.src.math.canonicalize + libc.src.math.canonicalizef + libc.src.math.canonicalizel libc.src.math.copysign libc.src.math.copysignf libc.src.math.copysignl @@ -374,12 +389,42 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fmax libc.src.math.fmaxf libc.src.math.fmaxl + libc.src.math.fmaximum + libc.src.math.fmaximumf + libc.src.math.fmaximuml + libc.src.math.fmaximum_num + libc.src.math.fmaximum_numf + libc.src.math.fmaximum_numl + libc.src.math.fmaximum_mag + libc.src.math.fmaximum_magf + libc.src.math.fmaximum_magl + libc.src.math.fmaximum_mag_num + libc.src.math.fmaximum_mag_numf + libc.src.math.fmaximum_mag_numl + libc.src.math.fminimum + libc.src.math.fminimumf + libc.src.math.fminimuml + libc.src.math.fminimum_num + libc.src.math.fminimum_numf + libc.src.math.fminimum_numl + libc.src.math.fminimum_mag + libc.src.math.fminimum_magf + libc.src.math.fminimum_magl + libc.src.math.fminimum_mag_num + libc.src.math.fminimum_mag_numf + libc.src.math.fminimum_mag_numl libc.src.math.fmod libc.src.math.fmodf libc.src.math.fmodl libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl + libc.src.math.fromfp + libc.src.math.fromfpf + libc.src.math.fromfpl + libc.src.math.fromfpx + libc.src.math.fromfpxf + libc.src.math.fromfpxl libc.src.math.hypot libc.src.math.hypotf libc.src.math.ilogb @@ -426,9 +471,15 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.nextafter libc.src.math.nextafterf libc.src.math.nextafterl + libc.src.math.nextdown + libc.src.math.nextdownf + libc.src.math.nextdownl libc.src.math.nexttoward libc.src.math.nexttowardf libc.src.math.nexttowardl + libc.src.math.nextup + libc.src.math.nextupf + libc.src.math.nextupl libc.src.math.powf libc.src.math.remainderf libc.src.math.remainder @@ -458,11 +509,18 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.trunc libc.src.math.truncf libc.src.math.truncl + libc.src.math.ufromfp + libc.src.math.ufromfpf + libc.src.math.ufromfpl + libc.src.math.ufromfpx + libc.src.math.ufromfpxf + libc.src.math.ufromfpxl ) if(LIBC_TYPES_HAS_FLOAT128) list(APPEND TARGET_LIBM_ENTRYPOINTS # math.h C23 _Float128 entrypoints + libc.src.math.canonicalizef128 libc.src.math.ceilf128 libc.src.math.copysignf128 libc.src.math.fabsf128 @@ -470,8 +528,18 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.floorf128 libc.src.math.fmaxf128 libc.src.math.fminf128 + libc.src.math.fmaximumf128 + libc.src.math.fmaximum_numf128 + libc.src.math.fmaximum_magf128 + libc.src.math.fmaximum_mag_numf128 + libc.src.math.fminimumf128 + libc.src.math.fminimum_numf128 + libc.src.math.fminimum_magf128 + libc.src.math.fminimum_mag_numf128 libc.src.math.fmodf128 libc.src.math.frexpf128 + libc.src.math.fromfpf128 + libc.src.math.fromfpxf128 libc.src.math.ilogbf128 libc.src.math.ldexpf128 libc.src.math.llogbf128 @@ -481,10 +549,16 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.lrintf128 libc.src.math.lroundf128 libc.src.math.modff128 + libc.src.math.nanf128 + libc.src.math.nextafterf128 + libc.src.math.nextdownf128 + libc.src.math.nextupf128 libc.src.math.rintf128 libc.src.math.roundf128 libc.src.math.sqrtf128 libc.src.math.truncf128 + libc.src.math.ufromfpf128 + libc.src.math.ufromfpxf128 ) endif() @@ -608,6 +682,8 @@ if(LLVM_LIBC_FULL_BUILD) libc.src.stdio.fread_unlocked libc.src.stdio.fseek libc.src.stdio.ftell + libc.src.stdio.fseeko + libc.src.stdio.ftello libc.src.stdio.funlockfile libc.src.stdio.fwrite libc.src.stdio.fwrite_unlocked @@ -698,6 +774,7 @@ if(LLVM_LIBC_FULL_BUILD) libc.src.time.time # unistd.h entrypoints + libc.src.unistd._exit libc.src.unistd.environ libc.src.unistd.execv libc.src.unistd.fork diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt index d6227a427afe2b86860e3f4f9bbfea177f390edc..c38125a6462272991710a98f20e3d6f47808051d 100644 --- a/libc/config/windows/entrypoints.txt +++ b/libc/config/windows/entrypoints.txt @@ -116,6 +116,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.acoshf libc.src.math.asinf libc.src.math.asinhf + libc.src.math.atan2f libc.src.math.atanf libc.src.math.atanhf libc.src.math.copysign @@ -153,6 +154,30 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fmax libc.src.math.fmaxf libc.src.math.fmaxl + libc.src.math.fmaximum + libc.src.math.fmaximumf + libc.src.math.fmaximuml + libc.src.math.fmaximum_num + libc.src.math.fmaximum_numf + libc.src.math.fmaximum_numl + libc.src.math.fmaximum_mag + libc.src.math.fmaximum_magf + libc.src.math.fmaximum_magl + libc.src.math.fmaximum_mag_num + libc.src.math.fmaximum_mag_numf + libc.src.math.fmaximum_mag_numl + libc.src.math.fminimum + libc.src.math.fminimumf + libc.src.math.fminimuml + libc.src.math.fminimum_num + libc.src.math.fminimum_numf + libc.src.math.fminimum_numl + libc.src.math.fminimum_mag + libc.src.math.fminimum_magf + libc.src.math.fminimum_magl + libc.src.math.fminimum_mag_num + libc.src.math.fminimum_mag_numf + libc.src.math.fminimum_mag_numl libc.src.math.fmod libc.src.math.fmodf libc.src.math.fmodl diff --git a/libc/docs/configure.rst b/libc/docs/configure.rst index a177550647bd91d8415a7148e15c4b1d5a2be052..8f8c44caa115395d6755a85a025fa11fcbb468ff 100644 --- a/libc/docs/configure.rst +++ b/libc/docs/configure.rst @@ -25,6 +25,9 @@ See the main ``config/config.json``, and the platform and architecture specific overrides in ``config/<platform>/config.json`` and ``config/<platform>/<arch>/config.json,`` to learn about the defaults for your platform and target. +* **"codegen" options** + - ``LIBC_CONF_ENABLE_STRONG_STACK_PROTECTOR``: Enable -fstack-protector-strong to defend against stack smashing attack. + - ``LIBC_CONF_KEEP_FRAME_POINTER``: Keep frame pointer in functions for better debugging experience. * **"printf" options** - ``LIBC_CONF_PRINTF_DISABLE_FIXED_POINT``: Disable printing fixed point values in printf and friends. - ``LIBC_CONF_PRINTF_DISABLE_FLOAT``: Disable printing floating point values in printf and friends. diff --git a/libc/docs/dev/code_style.rst b/libc/docs/dev/code_style.rst index e6fc6df5a0f6b34f38f7df59cb5cabb375ef12df..22a18b7a4cc1dd028d9cee4d2daf66e3e0a49ac5 100644 --- a/libc/docs/dev/code_style.rst +++ b/libc/docs/dev/code_style.rst @@ -55,7 +55,7 @@ We define two kinds of macros: * ``src/__support/macros/config.h`` - Important compiler and platform features. Such macros can be used to produce portable code by parameterizing compilation based on the presence or lack of a given - feature. e.g., ``LIBC_HAS_BUILTIN`` + feature. e.g., ``LIBC_HAS_FEATURE`` * ``src/__support/macros/attributes.h`` - Attributes for functions, types, and variables. e.g., ``LIBC_UNUSED`` * ``src/__support/macros/optimization.h`` - Portable macros for performance diff --git a/libc/docs/dev/printf_behavior.rst b/libc/docs/dev/printf_behavior.rst index 00d6c83f4b0d3665cffe2ca1b113139106955edb..c8b8ad45e987defc61a8a9839be28f3949f04449 100644 --- a/libc/docs/dev/printf_behavior.rst +++ b/libc/docs/dev/printf_behavior.rst @@ -1,3 +1,5 @@ +.. _printf_behavior: + ==================================== Printf Behavior Under All Conditions ==================================== @@ -171,6 +173,10 @@ If a number passed as a min width or precision value is out of range for an int, then it will be treated as the largest or smallest value in the int range (e.g. "%-999999999999.999999999999s" is the same as "%-2147483648.2147483647s"). +If a number passed as a bit width is less than or equal to zero, the conversion +is considered invalid. If the provided bit width is larger than the width of +uintmax_t, it will be clamped to the width of uintmax_t. + ---------- Conversion ---------- diff --git a/libc/docs/dev/undefined_behavior.rst b/libc/docs/dev/undefined_behavior.rst index 6e73a305e8e054b591c6faa298c541eb81924b35..c97a539ca8da45525aac27c7d46f6717da5997c3 100644 --- a/libc/docs/dev/undefined_behavior.rst +++ b/libc/docs/dev/undefined_behavior.rst @@ -70,3 +70,22 @@ Design Decisions Resizable Tables for hsearch ---------------------------- The POSIX.1 standard does not delineate the behavior consequent to invoking hsearch or hdestroy without prior initialization of the hash table via hcreate. Furthermore, the standard does not specify the outcomes of successive invocations of hsearch absent intervening hdestroy calls. Libraries such as MUSL and Glibc do not apply checks to these scenarios, potentially leading to memory corruption or leakage. Conversely, FreeBSD's libc and Bionic automatically initialize the hash table to a minimal size if it is found uninitialized, and proceeding to destroy the table only if initialization has occurred. This approach also avoids redundant table allocation if an initialized hash table is already present. Given that the hash table starts with a minimal size, resizing becomes necessary to accommodate additional user insertions. LLVM's libc mirrors the approach of FreeBSD's libc and Bionic, owing to its enhanced robustness and user-friendliness. Notably, such resizing behavior itself aligns with POSIX.1 standards, which explicitly permit implementations to modify the capacity of the hash table. + +Path without Leading Slashs in shm_open +---------------------------------------- +POSIX.1 leaves that when the name of a shared memory object does not begin with a slash, the behavior is implementation defined. In such cases, the shm_open in LLVM libc is implemented to behave as if the name began with a slash. + +Handling of NULL arguments to the 's' format specifier +------------------------------------------------------ +The C standard does not specify behavior for ``printf("%s", NULL)``. We will +print the string literal ``(null)`` unless using the +``LIBC_COPT_PRINTF_NO_NULLPTR_CHECKS`` option described in :ref:`printf +behavior<printf_behavior>`. + +Unknown Math Rounding Direction +------------------------------- +The C23 standard states that if the value of the ``rnd`` argument of the +``fromfp``, ``ufromfp``, ``fromfpx`` and ``ufromfpx`` functions is not equal to +the value of a math rounding direction macro, the direction of rounding is +unspecified. LLVM's libc chooses to use the ``FP_INT_TONEAREST`` rounding +direction in this case. diff --git a/libc/docs/fullbuild_mode.rst b/libc/docs/fullbuild_mode.rst index 0af923de42f84da5bb83be20a1b1561e145a6527..b1151017fbc794440e6dd374ded789ef17be4bfb 100644 --- a/libc/docs/fullbuild_mode.rst +++ b/libc/docs/fullbuild_mode.rst @@ -6,7 +6,7 @@ Fullbuild Mode The *fullbuild* mode of LLVM's libc is the mode in which it is to be used as the only libc (as opposed to the :ref:`overlay_mode` in which it is used along -with the system libc.) In to order use it as the only libc, one will have to +with the system libc.) In order to use it as the only libc, one will have to build and install not only the static archives like ``libc.a`` from LLVM's libc, but also the start-up objects like ``crt1.o`` and the public headers. diff --git a/libc/docs/gpu/building.rst b/libc/docs/gpu/building.rst index dab21e1324d2817218e5fa3e6a8cf3a6bd287823..6d94134a407d34fa820732aed60bf8d90175ff93 100644 --- a/libc/docs/gpu/building.rst +++ b/libc/docs/gpu/building.rst @@ -220,11 +220,15 @@ targets. This section will briefly describe their purpose. be used to enable host services for anyone looking to interface with the :ref:`RPC client<libc_gpu_rpc>`. +.. _gpu_cmake_options: + CMake options ============= This section briefly lists a few of the CMake variables that specifically -control the GPU build of the C library. +control the GPU build of the C library. These options can be passed individually +to each target using ``-DRUNTIMES_<target>_<variable>=<value>`` when using a +standard runtime build. **LLVM_LIBC_FULL_BUILD**:BOOL This flag controls whether or not the libc build will generate its own diff --git a/libc/docs/gpu/rpc.rst b/libc/docs/gpu/rpc.rst index 9d6d8099db951c9366dbb46f5eac9e5f7a9b13ee..e13a377f305c06f41e49ec3a11506ae37c3ebac7 100644 --- a/libc/docs/gpu/rpc.rst +++ b/libc/docs/gpu/rpc.rst @@ -251,14 +251,10 @@ but the following example shows how it can be used by a standard user. __global__ void hello() { puts("Hello world!"); } int main() { - int device = 0; - // Initialize the RPC server to run on a single device. - if (rpc_status_t err = rpc_init(/*num_device=*/1)) - handle_error(err); - // Initialize the RPC server to run on the given device. + rpc_device_t device; if (rpc_status_t err = - rpc_server_init(device, RPC_MAXIMUM_PORT_COUNT, + rpc_server_init(&device, RPC_MAXIMUM_PORT_COUNT, /*warp_size=*/32, alloc_host, /*data=*/nullptr)) handle_error(err); @@ -277,6 +273,7 @@ but the following example shows how it can be used by a standard user. hello<<<1, 1, 0, stream>>>(); // While the kernel is executing, check the RPC server for work to do. + // Requires non-blocking CUDA kernels but avoids a separate thread. while (cudaStreamQuery(stream) == cudaErrorNotReady) if (rpc_status_t err = rpc_handle_server(device)) handle_error(err); @@ -286,10 +283,6 @@ but the following example shows how it can be used by a standard user. rpc_server_shutdown(device, free_host, /*data=*/nullptr)) handle_error(err); - // Shut down the entire RPC server interface. - if (rpc_status_t err = rpc_shutdown()) - handle_error(err); - return EXIT_SUCCESS; } @@ -300,7 +293,7 @@ associated with relocatable device code linking. .. code-block:: sh - $> clang++ -x cuda rpc.cpp --offload-arch=native -fgpu-rdc -lcudart -lcgpu \ + $> clang++ -x cuda rpc.cpp --offload-arch=native -fgpu-rdc -lcudart -lcgpu-nvptx \ -I<install-path>include -L<install-path>/lib -lllvmlibc_rpc_server \ -O3 -foffload-lto -o hello $> ./hello diff --git a/libc/docs/gpu/support.rst b/libc/docs/gpu/support.rst index 250f0a7794de3cf404159c98bb5fdb110a37a1e5..31bbdc41090be61cb3073e629eb9a991684e8508 100644 --- a/libc/docs/gpu/support.rst +++ b/libc/docs/gpu/support.rst @@ -89,6 +89,79 @@ strtok_r |check| strxfrm |check| ============= ========= ============ +stdbit.h +-------- + +============================ ========= ============ +Function Name Available RPC Required +============================ ========= ============ +stdc_leading_zeros_uc |check| +stdc_leading_zeros_us |check| +stdc_leading_zeros_ui |check| +stdc_leading_zeros_ul |check| +stdc_leading_zeros_ull |check| +stdc_trailing_zeros_uc |check| +stdc_trailing_zeros_us |check| +stdc_trailing_zeros_ui |check| +stdc_trailing_zeros_ul |check| +stdc_trailing_zeros_ull |check| +stdc_trailing_ones_uc |check| +stdc_trailing_ones_us |check| +stdc_trailing_ones_ui |check| +stdc_trailing_ones_ul |check| +stdc_trailing_ones_ull |check| +stdc_first_leading_zero_uc |check| +stdc_first_leading_zero_us |check| +stdc_first_leading_zero_ui |check| +stdc_first_leading_zero_ul |check| +stdc_first_leading_zero_ull |check| +stdc_first_leading_one_uc |check| +stdc_first_leading_one_us |check| +stdc_first_leading_one_ui |check| +stdc_first_leading_one_ul |check| +stdc_first_leading_one_ull |check| +stdc_first_trailing_zero_uc |check| +stdc_first_trailing_zero_us |check| +stdc_first_trailing_zero_ui |check| +stdc_first_trailing_zero_ul |check| +stdc_first_trailing_zero_ull |check| +stdc_first_trailing_one_uc |check| +stdc_first_trailing_one_us |check| +stdc_first_trailing_one_ui |check| +stdc_first_trailing_one_ul |check| +stdc_first_trailing_one_ull |check| +stdc_count_zeros_uc |check| +stdc_count_zeros_us |check| +stdc_count_zeros_ui |check| +stdc_count_zeros_ul |check| +stdc_count_zeros_ull |check| +stdc_count_ones_uc |check| +stdc_count_ones_us |check| +stdc_count_ones_ui |check| +stdc_count_ones_ul |check| +stdc_count_ones_ull |check| +stdc_has_single_bit_uc |check| +stdc_has_single_bit_us |check| +stdc_has_single_bit_ui |check| +stdc_has_single_bit_ul |check| +stdc_has_single_bit_ull |check| +stdc_bit_width_uc |check| +stdc_bit_width_us |check| +stdc_bit_width_ui |check| +stdc_bit_width_ul |check| +stdc_bit_width_ull |check| +stdc_bit_floor_uc |check| +stdc_bit_floor_us |check| +stdc_bit_floor_ui |check| +stdc_bit_floor_ul |check| +stdc_bit_floor_ull |check| +stdc_bit_ceil_uc |check| +stdc_bit_ceil_us |check| +stdc_bit_ceil_ui |check| +stdc_bit_ceil_ul |check| +stdc_bit_ceil_ull |check| +============================ ========= ============ + stdlib.h -------- diff --git a/libc/docs/gpu/testing.rst b/libc/docs/gpu/testing.rst index 9842a67528361940831b0e1cba5a409e4468f515..9f17159fb6d5eecbdc8a889e42c3e6bf7b7628a3 100644 --- a/libc/docs/gpu/testing.rst +++ b/libc/docs/gpu/testing.rst @@ -1,9 +1,9 @@ .. _libc_gpu_testing: -============================ -Testing the GPU libc library -============================ +========================= +Testing the GPU C library +========================= .. note:: Running GPU tests with high parallelism is likely to cause spurious failures, @@ -14,24 +14,134 @@ Testing the GPU libc library :depth: 4 :local: -Testing Infrastructure +Testing infrastructure ====================== -The testing support in LLVM's libc implementation for GPUs is designed to mimic -the standard unit tests as much as possible. We use the :ref:`libc_gpu_rpc` -support to provide the necessary utilities like printing from the GPU. Execution -is performed by emitting a ``_start`` kernel from the GPU -that is then called by an external loader utility. This is an example of how -this can be done manually: +The LLVM C library supports different kinds of :ref:`tests <build_and_test>` +depending on the build configuration. The GPU target is considered a full build +and therefore provides all of its own utilities to build and run the generated +tests. Currently the GPU supports two kinds of tests. + +#. **Hermetic tests** - These are unit tests built with a test suite similar to + Google's ``gtest`` infrastructure. These use the same infrastructure as unit + tests except that the entire environment is self-hosted. This allows us to + run them on the GPU using our custom utilities. These are used to test the + majority of functional implementations. + +#. **Integration tests** - These are lightweight tests that simply call a + ``main`` function and checks if it returns non-zero. These are primarily used + to test interfaces that are sensitive to threading. + +The GPU uses the same testing infrastructure as the other supported ``libc`` +targets. We do this by treating the GPU as a standard hosted environment capable +of launching a ``main`` function. Effectively, this means building our own +startup libraries and loader. + +Testing utilities +================= + +We provide two utilities to execute arbitrary programs on the GPU. That is the +``loader`` and the ``start`` object. + +Startup object +-------------- + +This object mimics the standard object used by existing C library +implementations. Its job is to perform the necessary setup prior to calling the +``main`` function. In the GPU case, this means exporting GPU kernels that will +perform the necessary operations. Here we use ``_begin`` and ``_end`` to handle +calling global constructors and destructors while ``_start`` begins the standard +execution. The following code block shows the implementation for AMDGPU +architectures. + +.. code-block:: c++ + + extern "C" [[gnu::visibility("protected"), clang::amdgpu_kernel]] void + _begin(int argc, char **argv, char **env) { + LIBC_NAMESPACE::atexit(&LIBC_NAMESPACE::call_fini_array_callbacks); + LIBC_NAMESPACE::call_init_array_callbacks(argc, argv, env); + } + + extern "C" [[gnu::visibility("protected"), clang::amdgpu_kernel]] void + _start(int argc, char **argv, char **envp, int *ret) { + __atomic_fetch_or(ret, main(argc, argv, envp), __ATOMIC_RELAXED); + } + + extern "C" [[gnu::visibility("protected"), clang::amdgpu_kernel]] void + _end(int retval) { + LIBC_NAMESPACE::exit(retval); + } + +Loader runtime +-------------- + +The startup object provides a GPU executable with callable kernels for the +respective runtime. We can then define a minimal runtime that will launch these +kernels on the given device. Currently we provide the ``amdhsa-loader`` and +``nvptx-loader`` targeting the AMD HSA runtime and CUDA driver runtime +respectively. By default these will launch with a single thread on the GPU. .. code-block:: sh - $> clang++ crt1.o test.cpp --target=amdgcn-amd-amdhsa -mcpu=gfx90a -flto - $> ./amdhsa_loader --threads 1 --blocks 1 a.out + $> clang++ crt1.o test.cpp --target=amdgcn-amd-amdhsa -mcpu=native -flto + $> amdhsa_loader --threads 1 --blocks 1 ./a.out Test Passed! -Unlike the exported ``libcgpu.a``, the testing architecture can only support a -single architecture at a time. This is either detected automatically, or set -manually by the user using ``LIBC_GPU_TEST_ARCHITECTURE``. The latter is useful -in cases where the user does not build LLVM's libc on machine with the GPU to -use for testing. +The loader utility will forward any arguments passed after the executable image +to the program on the GPU as well as any set environment variables. The number +of threads and blocks to be set can be controlled with ``--threads`` and +``--blocks``. These also accept additional ``x``, ``y``, ``z`` variants for +multidimensional grids. + +Running tests +============= + +Tests will only be built and run if a GPU target architecture is set and the +corresponding loader utility was built. These can be overridden with the +``LIBC_GPU_TEST_ARCHITECTURE`` and ``LIBC_GPU_LOADER_EXECUTABLE`` :ref:`CMake +options <gpu_cmake_options>`. Once built, they can be run like any other tests. +The CMake target depends on how the library was built. + +#. **Cross build** - If the C library was built using ``LLVM_ENABLE_PROJECTS`` + or a runtimes cross build, then the standard targets will be present in the + base CMake build directory. + + #. All tests - You can run all supported tests with the command: + + .. code-block:: sh + + $> ninja check-libc + + #. Hermetic tests - You can run hermetic with tests the command: + + .. code-block:: sh + + $> ninja libc-hermetic-tests + + #. Integration tests - You can run integration tests by the command: + + .. code-block:: sh + + $> ninja libc-integration-tests + +#. **Runtimes build** - If the library was built using ``LLVM_ENABLE_RUNTIMES`` + then the actual ``libc`` build will be in a separate directory. + + #. All tests - You can run all supported tests with the command: + + .. code-block:: sh + + $> ninja check-libc-amdgcn-amd-amdhsa + $> ninja check-libc-nvptx64-nvidia-cuda + + #. Specific tests - You can use the same targets as above by entering the + runtimes build directory. + + .. code-block:: sh + + $> ninja -C runtimes/runtimes-amdgcn-amd-amdhsa-bins check-libc + $> ninja -C runtimes/runtimes-nvptx64-nvidia-cuda-bins check-libc + $> cd runtimes/runtimes-amdgcn-amd-amdhsa-bins && ninja check-libc + $> cd runtimes/runtimes-nvptx64-nvidia-cuda-bins && ninja check-libc + +Tests can also be built and run manually using the respective loader utility. diff --git a/libc/docs/gpu/using.rst b/libc/docs/gpu/using.rst index 11a00cd620d8661789eba5c91384dd87a00dc3d1..1a9446eeb1130aa21bc36e8102847e11155d33df 100644 --- a/libc/docs/gpu/using.rst +++ b/libc/docs/gpu/using.rst @@ -159,17 +159,21 @@ GPUs. } We can then compile this for both NVPTX and AMDGPU into LLVM-IR using the -following commands. +following commands. This will yield valid LLVM-IR for the given target just like +if we were using CUDA, OpenCL, or OpenMP. .. code-block:: sh $> clang id.c --target=amdgcn-amd-amdhsa -mcpu=native -nogpulib -flto -c $> clang id.c --target=nvptx64-nvidia-cuda -march=native -nogpulib -flto -c -We use this support to treat the GPU as a hosted environment by providing a C -library and startup object just like a standard C library running on the host -machine. Then, in order to execute these programs, we provide a loader utility -to launch the executable on the GPU similar to a cross-compiling emulator. +We can also use this support to treat the GPU as a hosted environment by +providing a C library and startup object just like a standard C library running +on the host machine. Then, in order to execute these programs, we provide a +loader utility to launch the executable on the GPU similar to a cross-compiling +emulator. This is how we run :ref:`unit tests <libc_gpu_testing>` targeting the +GPU. This is clearly not the most efficient way to use a GPU, but it provides a +simple method to test execution on a GPU for debugging or development. Building for AMDGPU targets ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst index 6984b785125f1a25fb8584591cc3e184057d39db..b7f1b8739648ca107dc70488400b8440069df3c8 100644 --- a/libc/docs/math/index.rst +++ b/libc/docs/math/index.rst @@ -104,221 +104,282 @@ Implementation Status Basic Operations ---------------- -+--------------+---------------------------------------+-------------------+-------------------+-------------------+-------------------+ -| <Func> | Linux | Windows | MacOS | Embedded | GPU | -| +---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| | x86_64 | aarch64 | aarch32 | riscv64 | x86_64 | aarch64 | x86_64 | aarch64 | aarch32 | riscv32 | AMD | nVidia | -+==============+=========+=========+=========+=========+=========+=========+=========+=========+=========+=========+=========+=========+ -| ceil | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ceilf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ceill | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ceilf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| copysign | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| copysignf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| copysignl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| copysignf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fabs | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fabsf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fabsl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fabsf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fdim | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fdimf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fdiml | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fdimf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| floor | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| floorf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| floorl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| floorf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fmax | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fmaxf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fmaxf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fmaxl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fmin | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fminf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fminf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fminl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fmod | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fmodf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fmodl | |check| | |check| | | |check| | |check| | | | |check| | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fmodf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| frexp | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| frexpf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| frexpl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| frexpf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ilogb | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ilogbf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ilogbl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ilogf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ldexp | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ldexpf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ldexpl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| ldexpf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| llogb | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| llogbf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| llogbl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| llogf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| llrint | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| llrintf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| llrintl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| llrintf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| llround | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| llroundf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| llroundl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| llroundf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| logb | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| logbf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| logbl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| logf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| lrint | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| lrintf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| lrintl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| lrintf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| lround | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| lroundf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| lroundl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| lroundf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| modf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| modff | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| modfl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| modff128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| nan | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| nanf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| nanl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| nearbyint | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| nearbyintf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| nearbyintl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| nextafter | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| nextafterf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| nextafterl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| nexttoward | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| nexttowardf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| nexttowardl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| remainder | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| remainderf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| remainderl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| remquo | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| remquof | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| remquol | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| rint | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| rintf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| rintl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| rintf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| round | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| roundf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| roundl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| roundf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| scalbn | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| scalbnf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| scalbnl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| trunc | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| truncf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| truncl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| truncf128 | |check| | |check| | | |check| | | | | | | | | | -+--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ + ++------------------+---------------------------------------+-------------------+-------------------+-------------------+-------------------+ +| <Func> | Linux | Windows | MacOS | Embedded | GPU | +| +---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| | x86_64 | aarch64 | aarch32 | riscv64 | x86_64 | aarch64 | x86_64 | aarch64 | aarch32 | riscv32 | AMD | nVidia | ++==================+=========+=========+=========+=========+=========+=========+=========+=========+=========+=========+=========+=========+ +| ceil | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ceilf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ceill | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ceilf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| canoninicalize | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| canoninicalizef | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| canoninicalizel | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +|canoninicalizef128| |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| copysign | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| copysignf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| copysignl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| copysignf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fabs | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fabsf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fabsl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fabsf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fdim | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fdimf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fdiml | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fdimf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| floor | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| floorf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| floorl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| floorf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fmax | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fmaxf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fmaxf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fmaxl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fmin | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fminf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fminf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fminl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fmod | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fmodf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fmodl | |check| | |check| | | |check| | |check| | | | |check| | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fmodf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| frexp | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| frexpf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| frexpl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| frexpf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fromfp | |check| | | | | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fromfpf | |check| | | | | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fromfpl | |check| | | | | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fromfpf128 | |check| | | | | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fromfpx | |check| | | | | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fromfpxf | |check| | | | | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fromfpxl | |check| | | | | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fromfpxf128 | |check| | | | | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ilogb | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ilogbf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ilogbl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ilogf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ldexp | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ldexpf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ldexpl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ldexpf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| llogb | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| llogbf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| llogbl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| llogf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| llrint | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| llrintf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| llrintl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| llrintf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| llround | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| llroundf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| llroundl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| llroundf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| logb | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| logbf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| logbl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| logf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| lrint | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| lrintf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| lrintl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| lrintf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| lround | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| lroundf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| lroundl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| lroundf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| modf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| modff | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| modfl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| modff128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nan | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nanf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nanl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nanf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nearbyint | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nearbyintf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nearbyintl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nextafter | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nextafterf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nextafterl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nextafterf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nextdown | |check| | |check| | |check| | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nextdownf | |check| | |check| | |check| | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nextdownl | |check| | |check| | |check| | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nextdownf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nexttoward | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nexttowardf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nexttowardl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nextup | |check| | |check| | |check| | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nextupf | |check| | |check| | |check| | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nextupl | |check| | |check| | |check| | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| nextupf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| remainder | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| remainderf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| remainderl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| remquo | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| remquof | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| remquol | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| rint | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| rintf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| rintl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| rintf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| round | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| roundf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| roundl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| roundf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| scalbn | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| scalbnf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| scalbnl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| trunc | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| truncf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| truncl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| truncf128 | |check| | |check| | | |check| | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ufromfp | |check| | | | | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ufromfpf | |check| | | | | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ufromfpl | |check| | | | | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ufromfpf128 | |check| | | | | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ufromfpx | |check| | | | | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ufromfpxf | |check| | | | | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ufromfpxl | |check| | | | | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| ufromfpxf128 | |check| | | | | | | | | | | | | ++------------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ Higher Math Functions @@ -361,7 +422,7 @@ Higher Math Functions +------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | atan2 | | | | | | | | | | | | | +------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| atan2f | | | | | | | | | | | | | +| atan2f | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | atan2l | | | | | | | | | | | | | +------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ @@ -530,6 +591,7 @@ acosh |check| asin |check| asinh |check| atan |check| +atan2 |check| atanh |check| cos |check| large cosh |check| diff --git a/libc/docs/stdio.rst b/libc/docs/stdio.rst index 4fd6b71a09171ba1f69ba8fd3d3dd4b5fbb97a62..d17821562c255679ae79b777a972eb8766da502c 100644 --- a/libc/docs/stdio.rst +++ b/libc/docs/stdio.rst @@ -68,7 +68,7 @@ These functions operate on files on the host's system, without using the Function_Name Available ============= ========= remove |check| -rename +rename |check| tmpnam ============= ========= diff --git a/libc/fuzzing/CMakeLists.txt b/libc/fuzzing/CMakeLists.txt index a3ef888167ee3c202fe1d2e3ecf87d25fef88a67..82487688af116279cd942ff6392e6e16abba440f 100644 --- a/libc/fuzzing/CMakeLists.txt +++ b/libc/fuzzing/CMakeLists.txt @@ -1,7 +1,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=fuzzer") add_custom_target(libc-fuzzer) -add_subdirectory(math) +# TODO(#85680): Re-enable math fuzzing after headers are sorted out +# add_subdirectory(math) add_subdirectory(stdlib) add_subdirectory(stdio) add_subdirectory(string) diff --git a/libc/fuzzing/math/RemQuoDiff.h b/libc/fuzzing/math/RemQuoDiff.h index 2a96224961767372abfa7de42d6df3a4a1efcd39..95a9866f29dbbe410f29272a43d570b093965217 100644 --- a/libc/fuzzing/math/RemQuoDiff.h +++ b/libc/fuzzing/math/RemQuoDiff.h @@ -11,7 +11,7 @@ #include "src/__support/FPUtil/FPBits.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" #include <stddef.h> #include <stdint.h> diff --git a/libc/fuzzing/math/SingleInputSingleOutputDiff.h b/libc/fuzzing/math/SingleInputSingleOutputDiff.h index 8c1e4b0d0290ed5c7f1f99c4f4a60460f07f8ac4..bdf54ee9af6c4f9840bc694cf097a31515b58265 100644 --- a/libc/fuzzing/math/SingleInputSingleOutputDiff.h +++ b/libc/fuzzing/math/SingleInputSingleOutputDiff.h @@ -10,9 +10,7 @@ #define LLVM_LIBC_FUZZING_MATH_SINGLE_INPUT_SINGLE_OUTPUT_DIFF_H #include "fuzzing/math/Compare.h" -#include "src/__support/FPUtil/FPBits.h" -#include <math.h> #include <stddef.h> #include <stdint.h> diff --git a/libc/fuzzing/math/TwoInputSingleOutputDiff.h b/libc/fuzzing/math/TwoInputSingleOutputDiff.h index e3e3fe703b139ef6bc73c025a31863a0d5eb602c..f017dbd63f4af520c1999fa2bf9e901bfd34d6b3 100644 --- a/libc/fuzzing/math/TwoInputSingleOutputDiff.h +++ b/libc/fuzzing/math/TwoInputSingleOutputDiff.h @@ -10,9 +10,7 @@ #define LLVM_LIBC_FUZZING_MATH_TWO_INPUT_SINGLE_OUTPUT_DIFF_H #include "fuzzing/math/Compare.h" -#include "src/__support/FPUtil/FPBits.h" -#include <math.h> #include <stddef.h> #include <stdint.h> diff --git a/libc/fuzzing/stdlib/strtofloat_fuzz.cpp b/libc/fuzzing/stdlib/strtofloat_fuzz.cpp index b773043bda67d8a44edb76ecec9156551f4f4c97..b000321854d16d38e03c407a25284bf6d28ab2d5 100644 --- a/libc/fuzzing/stdlib/strtofloat_fuzz.cpp +++ b/libc/fuzzing/stdlib/strtofloat_fuzz.cpp @@ -16,7 +16,7 @@ #include "src/__support/FPUtil/FPBits.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" #include <stddef.h> #include <stdint.h> diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt index 34d6839fd789a9c6be503f971c2c8d084b895ae0..4203f0bc901b22f2d3e7cd6b92c9774223276af5 100644 --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -498,6 +498,15 @@ add_gen_header( .llvm-libc-types.struct_sockaddr_un ) +add_gen_header( + sys_statvfs + DEF_FILE sys/statvfs.h.def + GEN_HDR sys/statvfs.h + DEPENDS + .llvm_libc_common_h + .llvm-libc-types.struct_statvfs +) + add_gen_header( sys_syscall DEF_FILE sys/syscall.h.def @@ -582,6 +591,15 @@ add_gen_header( .llvm-libc-types.tcflag_t ) +add_gen_header( + uchar + DEF_FILE uchar.h.def + GEN_HDR uchar.h + DEPENDS + .llvm_libc_common_h + .llvm-libc-types.mbstate_t +) + add_gen_header( wchar DEF_FILE wchar.h.def @@ -589,6 +607,7 @@ add_gen_header( DEPENDS .llvm_libc_common_h .llvm-libc-macros.wchar_macros + .llvm-libc-types.mbstate_t .llvm-libc-types.size_t .llvm-libc-types.wint_t .llvm-libc-types.wchar_t diff --git a/libc/include/arpa/inet.h.def b/libc/include/arpa/inet.h.def index fdd5ae3e3f85ac15cf8619ebd9a46fdc05a29d4d..6a62b2c7be81b42ade0550469f38ed52aecc37df 100644 --- a/libc/include/arpa/inet.h.def +++ b/libc/include/arpa/inet.h.def @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_ARPA_INET_H #define LLVM_LIBC_ARPA_INET_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" #include <inttypes.h> diff --git a/libc/include/assert.h.def b/libc/include/assert.h.def index e5d7dfbffdbb6746e4f461ad14ff56e125312b5e..e006133a76542a6d9e31d4cd564ff998967ca7d4 100644 --- a/libc/include/assert.h.def +++ b/libc/include/assert.h.def @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" // This file may be usefully included multiple times to change assert()'s // definition based on NDEBUG. diff --git a/libc/include/ctype.h.def b/libc/include/ctype.h.def index ac52a36bf72f5dbf757081d2caedf8ef0df89a64..a9bb786931eadfee4312ab6db5bd4a9705feb1c7 100644 --- a/libc/include/ctype.h.def +++ b/libc/include/ctype.h.def @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_CTYPE_H #define LLVM_LIBC_CTYPE_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" %%public_api() diff --git a/libc/include/dirent.h.def b/libc/include/dirent.h.def index 3de8b1c6713f15fdc197f02dca9cf1adb8c47cf5..6786578fbd067d848c202351219230e76e0e6e58 100644 --- a/libc/include/dirent.h.def +++ b/libc/include/dirent.h.def @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_DIRENT_H #define LLVM_LIBC_DIRENT_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" %%public_api() diff --git a/libc/include/errno.h.def b/libc/include/errno.h.def index 90bd8bfecf2f13f795d2c85151d870847e4a837a..d7ae90ad45247d9db470250124b852d2b899d970 100644 --- a/libc/include/errno.h.def +++ b/libc/include/errno.h.def @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_ERRNO_H #define LLVM_LIBC_ERRNO_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" #ifdef __linux__ @@ -40,7 +40,7 @@ #endif // ENOTRECOVERABLE #else // __linux__ -#include <llvm-libc-macros/generic-error-number-macros.h> +#include "llvm-libc-macros/generic-error-number-macros.h" #endif #if !defined(__AMDGPU__) && !defined(__NVPTX__) diff --git a/libc/include/fcntl.h.def b/libc/include/fcntl.h.def index b11645d18c5bde7be860e0a4272cbb5025806938..4f608845ce1ed68f6c61a861004587ef57539069 100644 --- a/libc/include/fcntl.h.def +++ b/libc/include/fcntl.h.def @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_FCNTL_H #define LLVM_LIBC_FCNTL_H -#include <__llvm-libc-common.h> -#include <llvm-libc-macros/fcntl-macros.h> +#include "__llvm-libc-common.h" +#include "llvm-libc-macros/fcntl-macros.h" %%public_api() diff --git a/libc/include/features.h.def b/libc/include/features.h.def index 64205f57acb5d9b508f6132ad18b50a255da922f..238b88d4b90f57930c3915caf230901245997cd2 100644 --- a/libc/include/features.h.def +++ b/libc/include/features.h.def @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_FEATURES_H #define LLVM_LIBC_FEATURES_H -#include <__llvm-libc-common.h> -#include <llvm-libc-macros/features-macros.h> +#include "__llvm-libc-common.h" +#include "llvm-libc-macros/features-macros.h" %%public_api() diff --git a/libc/include/fenv.h.def b/libc/include/fenv.h.def index f131a44914abfd7630450027d94a4b4da0db1b94..c677b2a5930dc9fcce9af707b90fd8a15eba4ccb 100644 --- a/libc/include/fenv.h.def +++ b/libc/include/fenv.h.def @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_FENV_H #define LLVM_LIBC_FENV_H -#include <__llvm-libc-common.h> -#include <llvm-libc-macros/fenv-macros.h> +#include "__llvm-libc-common.h" +#include "llvm-libc-macros/fenv-macros.h" %%public_api() diff --git a/libc/include/float.h.def b/libc/include/float.h.def index 6d3599d78c69e36546bbfdeedc9422629c12ad7c..3bcd7f5e3f98aa3a6494764cfdb6a668d995d4ac 100644 --- a/libc/include/float.h.def +++ b/libc/include/float.h.def @@ -9,6 +9,6 @@ #ifndef LLVM_LIBC_FLOAT_H #define LLVM_LIBC_FLOAT_H -#include <llvm-libc-macros/float-macros.h> +#include "llvm-libc-macros/float-macros.h" #endif // LLVM_LIBC_FLOAT_H diff --git a/libc/include/gpu/rpc.h.def b/libc/include/gpu/rpc.h.def index 0438cd65e7be22e4a80b6af60b6ca88ce92427b0..72acf0c81422811371952e1d585aa12143e70d39 100644 --- a/libc/include/gpu/rpc.h.def +++ b/libc/include/gpu/rpc.h.def @@ -9,9 +9,9 @@ #ifndef LLVM_LIBC_GPU_RPC_H #define LLVM_LIBC_GPU_RPC_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" -#include <llvm-libc-types/rpc_opcodes_t.h> +#include "llvm-libc-types/rpc_opcodes_t.h" %%public_api() diff --git a/libc/include/inttypes.h.def b/libc/include/inttypes.h.def index a99d4e931f51458437065cf1cff92fcda999bc3c..5879d2d8e041050e3b9319278fb969abf2e50441 100644 --- a/libc/include/inttypes.h.def +++ b/libc/include/inttypes.h.def @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_INTTYPES_H #define LLVM_LIBC_INTTYPES_H -#include <__llvm-libc-common.h> -#include <llvm-libc-macros/inttypes-macros.h> +#include "__llvm-libc-common.h" +#include "llvm-libc-macros/inttypes-macros.h" #include <stdint.h> %%public_api() diff --git a/libc/include/limits.h.def b/libc/include/limits.h.def index de5f3490459ed8bf051183e6cc5d966a3dc331a7..c37c97c69a843fa59dba52d734a2185a16038c85 100644 --- a/libc/include/limits.h.def +++ b/libc/include/limits.h.def @@ -9,6 +9,6 @@ #ifndef LLVM_LIBC_LIMITS_H #define LLVM_LIBC_LIMITS_H -#include <llvm-libc-macros/limits-macros.h> +#include "llvm-libc-macros/limits-macros.h" #endif // LLVM_LIBC_LIMITS_H diff --git a/libc/include/llvm-libc-macros/containerof-macro.h b/libc/include/llvm-libc-macros/containerof-macro.h index 62724abd3b0f1163e8424af4bfebb55bbec6621d..592acd6e3aa98c9b424ea8f74618436b1f927b58 100644 --- a/libc/include/llvm-libc-macros/containerof-macro.h +++ b/libc/include/llvm-libc-macros/containerof-macro.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_MACROS_CONTAINEROF_MACRO_H #define LLVM_LIBC_MACROS_CONTAINEROF_MACRO_H -#include <llvm-libc-macros/offsetof-macro.h> +#include "llvm-libc-macros/offsetof-macro.h" #define __containerof(ptr, type, member) \ ({ \ diff --git a/libc/include/llvm-libc-macros/math-macros.h b/libc/include/llvm-libc-macros/math-macros.h index db8a4ea65bd69aa1e3b7742174b83d67f5545ef1..1497e32044e9759e92647dfc9814dda3dec6638b 100644 --- a/libc/include/llvm-libc-macros/math-macros.h +++ b/libc/include/llvm-libc-macros/math-macros.h @@ -17,6 +17,12 @@ #define FP_SUBNORMAL 3 #define FP_NORMAL 4 +#define FP_INT_UPWARD 0 +#define FP_INT_DOWNWARD 1 +#define FP_INT_TOWARDZERO 2 +#define FP_INT_TONEARESTFROMZERO 3 +#define FP_INT_TONEAREST 4 + #define MATH_ERRNO 1 #define MATH_ERREXCEPT 2 @@ -25,14 +31,15 @@ #define NAN __builtin_nanf("") #define FP_ILOGB0 (-INT_MAX - 1) -#define FP_ILOGBNAN INT_MAX - #define FP_LLOGB0 (-LONG_MAX - 1) -#define FP_LLOGBNAN LONG_MAX -#define isfinite(x) __builtin_isfinite(x) -#define isinf(x) __builtin_isinf(x) -#define isnan(x) __builtin_isnan(x) +#ifdef __FP_LOGBNAN_MIN +#define FP_ILOGBNAN (-INT_MAX - 1) +#define FP_LLOGBNAN (-LONG_MAX - 1) +#else +#define FP_ILOGBNAN INT_MAX +#define FP_LLOGBNAN LONG_MAX +#endif #ifdef __FAST_MATH__ #define math_errhandling 0 @@ -44,4 +51,32 @@ #define math_errhandling (MATH_ERRNO | MATH_ERREXCEPT) #endif +// These must be type-generic functions. The C standard specifies them as +// being macros rather than functions, in fact. However, in C++ it's important +// that there be function declarations that don't interfere with other uses of +// the identifier, even in places with parentheses where a function-like macro +// will be expanded (such as a function declaration in a C++ namespace). + +#ifdef __cplusplus + +template <typename T> inline constexpr bool isfinite(T x) { + return __builtin_isfinite(x); +} + +template <typename T> inline constexpr bool isinf(T x) { + return __builtin_isinf(x); +} + +template <typename T> inline constexpr bool isnan(T x) { + return __builtin_isnan(x); +} + +#else + +#define isfinite(x) __builtin_isfinite(x) +#define isinf(x) __builtin_isinf(x) +#define isnan(x) __builtin_isnan(x) + +#endif + #endif // LLVM_LIBC_MACROS_MATH_MACROS_H diff --git a/libc/include/llvm-libc-macros/stdio-macros.h b/libc/include/llvm-libc-macros/stdio-macros.h index db747c5d5d67555d3ae215f22caa3a9d58837e44..4664801c5731f0dac5866a27225fe9327015f914 100644 --- a/libc/include/llvm-libc-macros/stdio-macros.h +++ b/libc/include/llvm-libc-macros/stdio-macros.h @@ -9,6 +9,10 @@ #ifndef LLVM_LIBC_MACROS_STDIO_MACROS_H #define LLVM_LIBC_MACROS_STDIO_MACROS_H +#ifndef EOF +#define EOF (-1) +#endif + #define BUFSIZ 1024 #endif // LLVM_LIBC_MACROS_STDIO_MACROS_H diff --git a/libc/include/llvm-libc-macros/sys-queue-macros.h b/libc/include/llvm-libc-macros/sys-queue-macros.h index fcac265333fc8226076379c0db212405a526f10e..089b6abaa02409adaf30cd3e3ed3c025053f2e53 100644 --- a/libc/include/llvm-libc-macros/sys-queue-macros.h +++ b/libc/include/llvm-libc-macros/sys-queue-macros.h @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_MACROS_SYS_QUEUE_MACROS_H #define LLVM_LIBC_MACROS_SYS_QUEUE_MACROS_H -#include <llvm-libc-macros/containerof-macro.h> -#include <llvm-libc-macros/null-macro.h> +#include "llvm-libc-macros/containerof-macro.h" +#include "llvm-libc-macros/null-macro.h" #ifdef __cplusplus #define QUEUE_TYPEOF(type) type diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt index e4f23b2a78130588b51f755eae76ec9dc70c3327..93a79e1477b337906346308e3b868eeae29fa9c9 100644 --- a/libc/include/llvm-libc-types/CMakeLists.txt +++ b/libc/include/llvm-libc-types/CMakeLists.txt @@ -39,6 +39,7 @@ add_header(uid_t HDR uid_t.h) add_header(imaxdiv_t HDR imaxdiv_t.h) add_header(ino_t HDR ino_t.h) add_header(jmp_buf HDR jmp_buf.h) +add_header(mbstate_t HDR mbstate_t.h) add_header(mode_t HDR mode_t.h) add_header(mtx_t HDR mtx_t.h DEPENDS .__futex_word .__mutex_type) add_header(nlink_t HDR nlink_t.h) @@ -105,3 +106,13 @@ add_header( DEPENDS libc.include.llvm-libc-macros.float_macros ) +add_header(fsblkcnt_t HDR fsblkcnt_t.h) +add_header(fsfilcnt_t HDR fsfilcnt_t.h) +add_header( + struct_statvfs +HDR + struct_statvfs.h +DEPENDS + .fsblkcnt_t + .fsfilcnt_t +) diff --git a/libc/include/llvm-libc-types/__mutex_type.h b/libc/include/llvm-libc-types/__mutex_type.h index d27bf5db83776bb4868553cebfeb4e2eefa479ae..3779c78203ed8a98aeaa1e463d031fd2b96484d1 100644 --- a/libc/include/llvm-libc-types/__mutex_type.h +++ b/libc/include/llvm-libc-types/__mutex_type.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_TYPES___MUTEX_TYPE_H #define LLVM_LIBC_TYPES___MUTEX_TYPE_H -#include <llvm-libc-types/__futex_word.h> +#include "llvm-libc-types/__futex_word.h" typedef struct { unsigned char __timed; diff --git a/libc/include/llvm-libc-types/cookie_io_functions_t.h b/libc/include/llvm-libc-types/cookie_io_functions_t.h index f9fa1a2d50ed05c4e5d2d7ff47a952170155cb7e..a3e7c32a50966ae884e7e40ad885639a13dc2c59 100644 --- a/libc/include/llvm-libc-types/cookie_io_functions_t.h +++ b/libc/include/llvm-libc-types/cookie_io_functions_t.h @@ -9,9 +9,9 @@ #ifndef LLVM_LIBC_TYPES_COOKIE_IO_FUNCTIONS_T_H #define LLVM_LIBC_TYPES_COOKIE_IO_FUNCTIONS_T_H -#include <llvm-libc-types/off64_t.h> -#include <llvm-libc-types/size_t.h> -#include <llvm-libc-types/ssize_t.h> +#include "llvm-libc-types/off64_t.h" +#include "llvm-libc-types/size_t.h" +#include "llvm-libc-types/ssize_t.h" typedef ssize_t cookie_read_function_t(void *, char *, size_t); typedef ssize_t cookie_write_function_t(void *, const char *, size_t); diff --git a/libc/include/llvm-libc-types/fd_set.h b/libc/include/llvm-libc-types/fd_set.h index 58fc438bbdd2859b47261d1246b5fdedf33ecf5b..fd1bde24c90e8d6a6c9c4cd3b05f45dfc647ae40 100644 --- a/libc/include/llvm-libc-types/fd_set.h +++ b/libc/include/llvm-libc-types/fd_set.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_TYPES_FD_SET_H #define LLVM_LIBC_TYPES_FD_SET_H -#include <llvm-libc-macros/sys-select-macros.h> // FD_SETSIZE +#include "llvm-libc-macros/sys-select-macros.h" // FD_SETSIZE typedef struct { __FD_SET_WORD_TYPE __set[__FD_SET_ARRAYSIZE]; diff --git a/libc/include/llvm-libc-types/fsblkcnt_t.h b/libc/include/llvm-libc-types/fsblkcnt_t.h new file mode 100644 index 0000000000000000000000000000000000000000..88a53d38cb1b3ce8d50b7d2ebd99ec94a3addd24 --- /dev/null +++ b/libc/include/llvm-libc-types/fsblkcnt_t.h @@ -0,0 +1,14 @@ +//===-- Definition of fsblkcnt_t type -------------------------------------===// +// +// 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_TYPES_FSBLKCNT_T_H +#define LLVM_LIBC_TYPES_FSBLKCNT_T_H + +typedef __SIZE_TYPE__ fsblkcnt_t; + +#endif // LLVM_LIBC_TYPES_FSBLKCNT_T_H diff --git a/libc/include/llvm-libc-types/fsfilcnt_t.h b/libc/include/llvm-libc-types/fsfilcnt_t.h new file mode 100644 index 0000000000000000000000000000000000000000..c5693591907ab73d65368ae598bfdccb8ac8b996 --- /dev/null +++ b/libc/include/llvm-libc-types/fsfilcnt_t.h @@ -0,0 +1,14 @@ +//===-- Definition of fsfilcnt_t type -------------------------------------===// +// +// 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_TYPES_FSFILCNT_T_H +#define LLVM_LIBC_TYPES_FSFILCNT_T_H + +typedef __SIZE_TYPE__ fsfilcnt_t; + +#endif // LLVM_LIBC_TYPES_FSFILCNT_T_H diff --git a/libc/include/llvm-libc-types/mbstate_t.h b/libc/include/llvm-libc-types/mbstate_t.h new file mode 100644 index 0000000000000000000000000000000000000000..540d50975a264dbe34fb3d1f195dd7111e65a967 --- /dev/null +++ b/libc/include/llvm-libc-types/mbstate_t.h @@ -0,0 +1,16 @@ +//===-- Definition of mbstate_t type --------------------------------------===// +// +// 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_TYPES_MBSTATE_T_H +#define LLVM_LIBC_TYPES_MBSTATE_T_H + +// TODO: Complete this once we implement functions that operate on this type. +typedef struct { +} mbstate_t; + +#endif // LLVM_LIBC_TYPES_MBSTATE_T_H diff --git a/libc/include/llvm-libc-types/mtx_t.h b/libc/include/llvm-libc-types/mtx_t.h index 0f3882c26b6bc23af9a17b75a0b6928b134a2ac4..ebf79871c9357519cea1fb27fa0768ed8384793f 100644 --- a/libc/include/llvm-libc-types/mtx_t.h +++ b/libc/include/llvm-libc-types/mtx_t.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_TYPES_MTX_T_H #define LLVM_LIBC_TYPES_MTX_T_H -#include <llvm-libc-types/__mutex_type.h> +#include "llvm-libc-types/__mutex_type.h" typedef __mutex_type mtx_t; diff --git a/libc/include/llvm-libc-types/once_flag.h b/libc/include/llvm-libc-types/once_flag.h index cb8011284610233efd82790e90f477886ad4d682..f80d35e317e99ab3a014d8729f63eaad991fdf8b 100644 --- a/libc/include/llvm-libc-types/once_flag.h +++ b/libc/include/llvm-libc-types/once_flag.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_TYPES_ONCE_FLAG_H #define LLVM_LIBC_TYPES_ONCE_FLAG_H -#include <llvm-libc-types/__futex_word.h> +#include "llvm-libc-types/__futex_word.h" #ifdef __linux__ typedef __futex_word once_flag; diff --git a/libc/include/llvm-libc-types/pthread_attr_t.h b/libc/include/llvm-libc-types/pthread_attr_t.h index 66c04de04a99b26c1a0fd8a28179a3c51a8b6e75..7512193ef97be25a9fd2888b6f6f3fbe41363fd8 100644 --- a/libc/include/llvm-libc-types/pthread_attr_t.h +++ b/libc/include/llvm-libc-types/pthread_attr_t.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_TYPES_PTHREAD_ATTR_T_H #define LLVM_LIBC_TYPES_PTHREAD_ATTR_T_H -#include <llvm-libc-types/size_t.h> +#include "llvm-libc-types/size_t.h" typedef struct { int __detachstate; diff --git a/libc/include/llvm-libc-types/pthread_mutex_t.h b/libc/include/llvm-libc-types/pthread_mutex_t.h index b1eb21f24fac5239b11f08990dbc15b48fc6af3a..cf2194d719f354db9f4a722f55532a0774f71716 100644 --- a/libc/include/llvm-libc-types/pthread_mutex_t.h +++ b/libc/include/llvm-libc-types/pthread_mutex_t.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_TYPES_PTHREAD_MUTEX_T_H #define LLVM_LIBC_TYPES_PTHREAD_MUTEX_T_H -#include <llvm-libc-types/__mutex_type.h> +#include "llvm-libc-types/__mutex_type.h" typedef __mutex_type pthread_mutex_t; diff --git a/libc/include/llvm-libc-types/pthread_once_t.h b/libc/include/llvm-libc-types/pthread_once_t.h index 3fe78b7ddff662e93fee6b1b7636be315fc480c4..8ea926f4ee7dc45e996fcd149530feb6d3ff1646 100644 --- a/libc/include/llvm-libc-types/pthread_once_t.h +++ b/libc/include/llvm-libc-types/pthread_once_t.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_TYPES_PTHREAD_ONCE_T_H #define LLVM_LIBC_TYPES_PTHREAD_ONCE_T_H -#include <llvm-libc-types/__futex_word.h> +#include "llvm-libc-types/__futex_word.h" #ifdef __linux__ typedef __futex_word pthread_once_t; diff --git a/libc/include/llvm-libc-types/pthread_t.h b/libc/include/llvm-libc-types/pthread_t.h index 72c14e1c2eea8f3107e6a5ba360ed5485df0abfe..63cc0d7dd74cb4cb25fe27a1259cf7d26dac858d 100644 --- a/libc/include/llvm-libc-types/pthread_t.h +++ b/libc/include/llvm-libc-types/pthread_t.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_TYPES_PTHREAD_T_H #define LLVM_LIBC_TYPES_PTHREAD_T_H -#include <llvm-libc-types/__thread_type.h> +#include "llvm-libc-types/__thread_type.h" typedef __thread_type pthread_t; diff --git a/libc/include/llvm-libc-types/siginfo_t.h b/libc/include/llvm-libc-types/siginfo_t.h index 935ef4bbcb723b02c95428faf916848dc62548d0..dafe9c1b5f8ebf1de8c82850c8a41189a89c9a5a 100644 --- a/libc/include/llvm-libc-types/siginfo_t.h +++ b/libc/include/llvm-libc-types/siginfo_t.h @@ -9,10 +9,10 @@ #ifndef LLVM_LIBC_TYPES_SIGINFO_T_H #define LLVM_LIBC_TYPES_SIGINFO_T_H -#include <llvm-libc-types/clock_t.h> -#include <llvm-libc-types/pid_t.h> -#include <llvm-libc-types/uid_t.h> -#include <llvm-libc-types/union_sigval.h> +#include "llvm-libc-types/clock_t.h" +#include "llvm-libc-types/pid_t.h" +#include "llvm-libc-types/uid_t.h" +#include "llvm-libc-types/union_sigval.h" #define SI_MAX_SIZE 128 diff --git a/libc/include/llvm-libc-types/sigset_t.h b/libc/include/llvm-libc-types/sigset_t.h index f159c6c6c6435b82f8d17e31f4f73f02a9922133..311a92b823ff5e10a1f2a509d7bd7829879679ad 100644 --- a/libc/include/llvm-libc-types/sigset_t.h +++ b/libc/include/llvm-libc-types/sigset_t.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_TYPES_SIGSET_T_H #define LLVM_LIBC_TYPES_SIGSET_T_H -#include <llvm-libc-macros/signal-macros.h> +#include "llvm-libc-macros/signal-macros.h" // This definition can be adjusted/specialized for different targets and // platforms as necessary. This definition works for Linux on most targets. diff --git a/libc/include/llvm-libc-types/stack_t.h b/libc/include/llvm-libc-types/stack_t.h index 5fa4d3a6d3dc94a7acb88b7c5e66822a88c99e7a..9156425436e948cf8798ada5cb6446564c25c83b 100644 --- a/libc/include/llvm-libc-types/stack_t.h +++ b/libc/include/llvm-libc-types/stack_t.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_TYPES_STACK_T_H #define LLVM_LIBC_TYPES_STACK_T_H -#include <llvm-libc-types/size_t.h> +#include "llvm-libc-types/size_t.h" typedef struct { // The order of the fields declared here should match the kernel definition diff --git a/libc/include/llvm-libc-types/struct_dirent.h b/libc/include/llvm-libc-types/struct_dirent.h index 3c5b361c3cbcf5967b8c3caa74fb30db0f097708..0bb71b9f3b84c5d7190871eba3e37b450b473e2d 100644 --- a/libc/include/llvm-libc-types/struct_dirent.h +++ b/libc/include/llvm-libc-types/struct_dirent.h @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_TYPES_STRUCT_DIRENT_H #define LLVM_LIBC_TYPES_STRUCT_DIRENT_H -#include <llvm-libc-types/ino_t.h> -#include <llvm-libc-types/off_t.h> +#include "llvm-libc-types/ino_t.h" +#include "llvm-libc-types/off_t.h" struct dirent { ino_t d_ino; diff --git a/libc/include/llvm-libc-types/struct_epoll_event.h b/libc/include/llvm-libc-types/struct_epoll_event.h index 6fc5b410348a119bed6e8672920ae872b2f3c123..66cf86c1e2a006c472b41d2f349008415a0eb302 100644 --- a/libc/include/llvm-libc-types/struct_epoll_event.h +++ b/libc/include/llvm-libc-types/struct_epoll_event.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_TYPES_STRUCT_EPOLL_EVENT_H #define LLVM_LIBC_TYPES_STRUCT_EPOLL_EVENT_H -#include <llvm-libc-types/struct_epoll_data.h> +#include "llvm-libc-types/struct_epoll_data.h" typedef struct epoll_event { __UINT32_TYPE__ events; diff --git a/libc/include/llvm-libc-types/struct_rlimit.h b/libc/include/llvm-libc-types/struct_rlimit.h index e093d9f306c984f991329668c05fbcd9abfb89d7..11e6bee15f9d647402b7ca49ae59bd7fa8ed8771 100644 --- a/libc/include/llvm-libc-types/struct_rlimit.h +++ b/libc/include/llvm-libc-types/struct_rlimit.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_TYPES_STRUCT_RLIMIT_H #define LLVM_LIBC_TYPES_STRUCT_RLIMIT_H -#include <llvm-libc-types/rlim_t.h> +#include "llvm-libc-types/rlim_t.h" struct rlimit { rlim_t rlim_cur; diff --git a/libc/include/llvm-libc-types/struct_rusage.h b/libc/include/llvm-libc-types/struct_rusage.h index 21ea8b1061c2963a57d56055af9157432d26ffca..ed838d30ede3d34d93482b9ef14a78e535895461 100644 --- a/libc/include/llvm-libc-types/struct_rusage.h +++ b/libc/include/llvm-libc-types/struct_rusage.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_TYPES_STRUCT_RUSAGE_H #define LLVM_LIBC_TYPES_STRUCT_RUSAGE_H -#include <llvm-libc-types/struct_timeval.h> +#include "llvm-libc-types/struct_timeval.h" struct rusage { struct timeval ru_utime; diff --git a/libc/include/llvm-libc-types/struct_sched_param.h b/libc/include/llvm-libc-types/struct_sched_param.h index 0521a4df652f152b9be7241928d08966a02c4683..86209ac3a1816c16c041c9f133abe7465b970a0a 100644 --- a/libc/include/llvm-libc-types/struct_sched_param.h +++ b/libc/include/llvm-libc-types/struct_sched_param.h @@ -9,9 +9,9 @@ #ifndef LLVM_LIBC_TYPES_STRUCT_SCHED_PARAM_H #define LLVM_LIBC_TYPES_STRUCT_SCHED_PARAM_H -#include <llvm-libc-types/pid_t.h> -#include <llvm-libc-types/struct_timespec.h> -#include <llvm-libc-types/time_t.h> +#include "llvm-libc-types/pid_t.h" +#include "llvm-libc-types/struct_timespec.h" +#include "llvm-libc-types/time_t.h" struct sched_param { // Process or thread execution scheduling priority. diff --git a/libc/include/llvm-libc-types/struct_sigaction.h b/libc/include/llvm-libc-types/struct_sigaction.h index 54d2995f4ecd0820d8a785b9e0d8d49f8d31b213..ffce04d0f7e8cc6f9a2d2a0eb1159c508ce77077 100644 --- a/libc/include/llvm-libc-types/struct_sigaction.h +++ b/libc/include/llvm-libc-types/struct_sigaction.h @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_TYPES_STRUCT_SIGACTION_H #define LLVM_LIBC_TYPES_STRUCT_SIGACTION_H -#include <llvm-libc-types/siginfo_t.h> -#include <llvm-libc-types/sigset_t.h> +#include "llvm-libc-types/siginfo_t.h" +#include "llvm-libc-types/sigset_t.h" struct sigaction { union { diff --git a/libc/include/llvm-libc-types/struct_sockaddr.h b/libc/include/llvm-libc-types/struct_sockaddr.h index 074b1ae50ef073966677172abb8f57b9199dec1f..a98606323c52208f0709b48e74fc570f4b250ddd 100644 --- a/libc/include/llvm-libc-types/struct_sockaddr.h +++ b/libc/include/llvm-libc-types/struct_sockaddr.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_TYPES_STRUCT_SOCKADDR_H #define LLVM_LIBC_TYPES_STRUCT_SOCKADDR_H -#include <llvm-libc-types/sa_family_t.h> +#include "llvm-libc-types/sa_family_t.h" struct sockaddr { sa_family_t sa_family; diff --git a/libc/include/llvm-libc-types/struct_sockaddr_un.h b/libc/include/llvm-libc-types/struct_sockaddr_un.h index 4332419a5b71557d2c7ccc2ff3c3685f9723785d..3c0362ce24fba06b52cae162d9613940e153ed8b 100644 --- a/libc/include/llvm-libc-types/struct_sockaddr_un.h +++ b/libc/include/llvm-libc-types/struct_sockaddr_un.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_TYPES_STRUCT_SOCKADDR_UN_H #define LLVM_LIBC_TYPES_STRUCT_SOCKADDR_UN_H -#include <llvm-libc-types/sa_family_t.h> +#include "llvm-libc-types/sa_family_t.h" // This is the sockaddr specialization for AF_UNIX or AF_LOCAL sockets, as // defined by posix. diff --git a/libc/include/llvm-libc-types/struct_stat.h b/libc/include/llvm-libc-types/struct_stat.h index 3539fb5b920e3695c3455b480bb46dde2c8f4fc6..d8ae9dd6ffdcab0605a52a63e4eba426688cf197 100644 --- a/libc/include/llvm-libc-types/struct_stat.h +++ b/libc/include/llvm-libc-types/struct_stat.h @@ -9,16 +9,16 @@ #ifndef LLVM_LIBC_TYPES_STRUCT_STAT_H #define LLVM_LIBC_TYPES_STRUCT_STAT_H -#include <llvm-libc-types/blkcnt_t.h> -#include <llvm-libc-types/blksize_t.h> -#include <llvm-libc-types/dev_t.h> -#include <llvm-libc-types/gid_t.h> -#include <llvm-libc-types/ino_t.h> -#include <llvm-libc-types/mode_t.h> -#include <llvm-libc-types/nlink_t.h> -#include <llvm-libc-types/off_t.h> -#include <llvm-libc-types/struct_timespec.h> -#include <llvm-libc-types/uid_t.h> +#include "llvm-libc-types/blkcnt_t.h" +#include "llvm-libc-types/blksize_t.h" +#include "llvm-libc-types/dev_t.h" +#include "llvm-libc-types/gid_t.h" +#include "llvm-libc-types/ino_t.h" +#include "llvm-libc-types/mode_t.h" +#include "llvm-libc-types/nlink_t.h" +#include "llvm-libc-types/off_t.h" +#include "llvm-libc-types/struct_timespec.h" +#include "llvm-libc-types/uid_t.h" struct stat { dev_t st_dev; diff --git a/libc/include/llvm-libc-types/struct_statvfs.h b/libc/include/llvm-libc-types/struct_statvfs.h new file mode 100644 index 0000000000000000000000000000000000000000..f467cfd936bdb61a66143a21eb77eeaf6255dbb9 --- /dev/null +++ b/libc/include/llvm-libc-types/struct_statvfs.h @@ -0,0 +1,29 @@ +//===-- Definition of type struct statvfs ---------------------------------===// +// +// 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_TYPES_STRUCT_STATVFS_H +#define LLVM_LIBC_TYPES_STRUCT_STATVFS_H + +#include <llvm-libc-types/fsblkcnt_t.h> +#include <llvm-libc-types/fsfilcnt_t.h> + +struct statvfs { + unsigned long f_bsize; /* Filesystem block size */ + unsigned long f_frsize; /* Fragment size */ + fsblkcnt_t f_blocks; /* Size of fs in f_frsize units */ + fsblkcnt_t f_bfree; /* Number of free blocks */ + fsblkcnt_t f_bavail; /* Number of free blocks for unprivileged users */ + fsfilcnt_t f_files; /* Number of inodes */ + fsfilcnt_t f_ffree; /* Number of free inodes */ + fsfilcnt_t f_favail; /* Number of free inodes for unprivileged users */ + unsigned long f_fsid; /* Filesystem ID */ + unsigned long f_flag; /* Mount flags */ + unsigned long f_namemax; /* Maximum filename length */ +}; + +#endif // LLVM_LIBC_TYPES_STRUCT_STATVFS_H diff --git a/libc/include/llvm-libc-types/struct_termios.h b/libc/include/llvm-libc-types/struct_termios.h index 72aefe4f69267f31cdad00d5122f414358f74ad5..51241192f741f9b987332be02348fc0391f7df80 100644 --- a/libc/include/llvm-libc-types/struct_termios.h +++ b/libc/include/llvm-libc-types/struct_termios.h @@ -9,9 +9,9 @@ #ifndef __LLVM_LIBC_TYPES_STRUCT_TERMIOS_H__ #define __LLVM_LIBC_TYPES_STRUCT_TERMIOS_H__ -#include <llvm-libc-types/cc_t.h> -#include <llvm-libc-types/speed_t.h> -#include <llvm-libc-types/tcflag_t.h> +#include "llvm-libc-types/cc_t.h" +#include "llvm-libc-types/speed_t.h" +#include "llvm-libc-types/tcflag_t.h" struct termios { tcflag_t c_iflag; // Input mode flags diff --git a/libc/include/llvm-libc-types/struct_timespec.h b/libc/include/llvm-libc-types/struct_timespec.h index 5d56d9c9468b4fb9a27decfaa6fdc36833826bf6..4baab07c10f8531cc351484b119c0ba3dcebb826 100644 --- a/libc/include/llvm-libc-types/struct_timespec.h +++ b/libc/include/llvm-libc-types/struct_timespec.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_TYPES_STRUCT_TIMESPEC_H #define LLVM_LIBC_TYPES_STRUCT_TIMESPEC_H -#include <llvm-libc-types/time_t.h> +#include "llvm-libc-types/time_t.h" struct timespec { time_t tv_sec; /* Seconds. */ diff --git a/libc/include/llvm-libc-types/struct_timeval.h b/libc/include/llvm-libc-types/struct_timeval.h index 6a0b7bbaf8254dd6c26d8fdc199a5a2afb3ef49e..365b835d345dd33ecf1fe55850bafa2d13f8900a 100644 --- a/libc/include/llvm-libc-types/struct_timeval.h +++ b/libc/include/llvm-libc-types/struct_timeval.h @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_TYPES_STRUCT_TIMEVAL_H #define LLVM_LIBC_TYPES_STRUCT_TIMEVAL_H -#include <llvm-libc-types/suseconds_t.h> -#include <llvm-libc-types/time_t.h> +#include "llvm-libc-types/suseconds_t.h" +#include "llvm-libc-types/time_t.h" struct timeval { time_t tv_sec; // Seconds diff --git a/libc/include/llvm-libc-types/thrd_t.h b/libc/include/llvm-libc-types/thrd_t.h index 2e0f9a0d75ad7c692c001e8d38294db6fdf29287..751ea5b9e4c020d661cdeaf907c0a919c1e6857f 100644 --- a/libc/include/llvm-libc-types/thrd_t.h +++ b/libc/include/llvm-libc-types/thrd_t.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_TYPES_THRD_T_H #define LLVM_LIBC_TYPES_THRD_T_H -#include <llvm-libc-types/__thread_type.h> +#include "llvm-libc-types/__thread_type.h" typedef __thread_type thrd_t; diff --git a/libc/include/math.h.def b/libc/include/math.h.def index 927e2d6697c67d6b21b54cdba6043ffdd9a36301..cd2fe76f40bf2cf590f9d172910f489109d8d71e 100644 --- a/libc/include/math.h.def +++ b/libc/include/math.h.def @@ -9,9 +9,9 @@ #ifndef LLVM_LIBC_MATH_H #define LLVM_LIBC_MATH_H -#include <__llvm-libc-common.h> -#include <llvm-libc-macros/math-macros.h> -#include <llvm-libc-types/float128.h> +#include "__llvm-libc-common.h" +#include "llvm-libc-macros/math-macros.h" +#include "llvm-libc-types/float128.h" %%public_api() diff --git a/libc/include/pthread.h.def b/libc/include/pthread.h.def index 391ecd3c124f2b50cb04b3951f99a23588d41ef1..abeb839ee83d16e77cfdc53485a27e0e691f66b2 100644 --- a/libc/include/pthread.h.def +++ b/libc/include/pthread.h.def @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_PTHREAD_H #define LLVM_LIBC_PTHREAD_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" #define PTHREAD_STACK_MIN (1 << 14) // 16KB diff --git a/libc/include/sched.h.def b/libc/include/sched.h.def index 3b2d5e3308593fcea800ac17b761bc39904ff202..493028e8dcc476574b990841d675fc0d55273271 100644 --- a/libc/include/sched.h.def +++ b/libc/include/sched.h.def @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_SCHED_H #define LLVM_LIBC_SCHED_H -#include <__llvm-libc-common.h> -#include <llvm-libc-macros/sched-macros.h> +#include "__llvm-libc-common.h" +#include "llvm-libc-macros/sched-macros.h" %%public_api() diff --git a/libc/include/search.h.def b/libc/include/search.h.def index 3435c1f8ad048ea91884fd1e1ad842d1295d99b9..6301ba7b656cec555592fed217a8e415b78c8dc2 100644 --- a/libc/include/search.h.def +++ b/libc/include/search.h.def @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_SEARCH_H #define LLVM_LIBC_SEARCH_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" #define __need_size_t #include <stddef.h> diff --git a/libc/include/setjmp.h.def b/libc/include/setjmp.h.def index 7447be2415bd5c7d4b657bdfccbc85dfadff93e6..670bc1ac0fe245cf21b7a2a5c1be98b1a5eb904e 100644 --- a/libc/include/setjmp.h.def +++ b/libc/include/setjmp.h.def @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_SETJMP_H #define LLVM_LIBC_SETJMP_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" %%public_api() diff --git a/libc/include/signal.h.def b/libc/include/signal.h.def index 0e7033452715716440f86fb14cd2d20e06cf25fa..50a5f44c7337aa6e9a9d0b193a8e396971927914 100644 --- a/libc/include/signal.h.def +++ b/libc/include/signal.h.def @@ -9,12 +9,12 @@ #ifndef LLVM_LIBC_SIGNAL_H #define LLVM_LIBC_SIGNAL_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" #define __need_size_t #include <stddef.h> -#include <llvm-libc-macros/signal-macros.h> +#include "llvm-libc-macros/signal-macros.h" %%public_api() diff --git a/libc/include/spawn.h.def b/libc/include/spawn.h.def index 368ebff17ca12dc7a5257e28d7031ce9e4008588..a8d7015852868069e79f9fe7015cdd1f0f67d2b2 100644 --- a/libc/include/spawn.h.def +++ b/libc/include/spawn.h.def @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_SPAWN_H #define LLVM_LIBC_SPAWN_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" %%public_api() diff --git a/libc/include/stdbit.h.def b/libc/include/stdbit.h.def index c5a77329fbfe74717746a635f05be1d45d3befe3..28c147b01e22f9caf5dd12b850192ad05d3fab80 100644 --- a/libc/include/stdbit.h.def +++ b/libc/include/stdbit.h.def @@ -9,10 +9,10 @@ #ifndef LLVM_LIBC_STDBIT_H #define LLVM_LIBC_STDBIT_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" %%public_api() -#include <llvm-libc-macros/stdbit-macros.h> +#include "llvm-libc-macros/stdbit-macros.h" #endif // LLVM_LIBC_STDBIT_H diff --git a/libc/include/stdckdint.h.def b/libc/include/stdckdint.h.def index c82470911c33f301564fd2c0e0e00e0506106189..d4a9d829a3c9a05179b4ef47058e230dac0e7659 100644 --- a/libc/include/stdckdint.h.def +++ b/libc/include/stdckdint.h.def @@ -9,10 +9,10 @@ #ifndef LLVM_LIBC_STDCKDINT_H #define LLVM_LIBC_STDCKDINT_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" %%public_api() -#include <llvm-libc-macros/stdckdint-macros.h> +#include "llvm-libc-macros/stdckdint-macros.h" #endif // LLVM_LIBC_STDCKDINT_H diff --git a/libc/include/stdfix.h.def b/libc/include/stdfix.h.def index 368eeb33f2f0af9fe4a8aeecee072a1c083050b0..8ac49be45fbae99eea913a22a79fb351f5f06a64 100644 --- a/libc/include/stdfix.h.def +++ b/libc/include/stdfix.h.def @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_STDFIX_H #define LLVM_LIBC_STDFIX_H -#include <__llvm-libc-common.h> -#include <llvm-libc-macros/stdfix-macros.h> +#include "__llvm-libc-common.h" +#include "llvm-libc-macros/stdfix-macros.h" // From ISO/IEC TR 18037:2008 standard: // https://www.iso.org/standard/51126.html diff --git a/libc/include/stdint.h.def b/libc/include/stdint.h.def index 9e269101acd2fb3aeab01875adc1b59575467d8f..d7660860c91f8e8ee4b922378815d5c41ab2fa90 100644 --- a/libc/include/stdint.h.def +++ b/libc/include/stdint.h.def @@ -9,6 +9,6 @@ #ifndef LLVM_LIBC_STDINT_H #define LLVM_LIBC_STDINT_H -#include <llvm-libc-macros/stdint-macros.h> +#include "llvm-libc-macros/stdint-macros.h" #endif // LLVM_LIBC_STDINT_H diff --git a/libc/include/stdio.h.def b/libc/include/stdio.h.def index a28d009288d5a67d17388143fb7e16f0f6cd82f0..78d800c83b514296e67dbdc018c529e98847eb0a 100644 --- a/libc/include/stdio.h.def +++ b/libc/include/stdio.h.def @@ -9,9 +9,9 @@ #ifndef LLVM_LIBC_STDIO_H #define LLVM_LIBC_STDIO_H -#include <__llvm-libc-common.h> -#include <llvm-libc-macros/file-seek-macros.h> -#include <llvm-libc-macros/stdio-macros.h> +#include "__llvm-libc-common.h" +#include "llvm-libc-macros/file-seek-macros.h" +#include "llvm-libc-macros/stdio-macros.h" #include <stdarg.h> diff --git a/libc/include/stdlib.h.def b/libc/include/stdlib.h.def index 18df71a49a9b428f22841d595ef24452f88318b8..d523f7a53024aa647dc917dbdb25eef8424809c3 100644 --- a/libc/include/stdlib.h.def +++ b/libc/include/stdlib.h.def @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_STDLIB_H #define LLVM_LIBC_STDLIB_H -#include <__llvm-libc-common.h> -#include <llvm-libc-macros/stdlib-macros.h> +#include "__llvm-libc-common.h" +#include "llvm-libc-macros/stdlib-macros.h" %%public_api() diff --git a/libc/include/string.h.def b/libc/include/string.h.def index 26e6ef93d314d3f46f1349954295e42be1a7422f..1bd2687db2beac42d4a26dab1912fdf182646692 100644 --- a/libc/include/string.h.def +++ b/libc/include/string.h.def @@ -9,9 +9,9 @@ #ifndef LLVM_LIBC_STRING_H #define LLVM_LIBC_STRING_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" -#include <llvm-libc-macros/null-macro.h> +#include "llvm-libc-macros/null-macro.h" %%public_api() diff --git a/libc/include/strings.h.def b/libc/include/strings.h.def index f07ca30d5dbd03cb807d3c2a3475cf50a71db94b..9b016bf0bc50b7f600f58a9939162597873b490c 100644 --- a/libc/include/strings.h.def +++ b/libc/include/strings.h.def @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_STRINGS_H #define LLVM_LIBC_STRINGS_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" %%public_api() diff --git a/libc/include/sys/auxv.h.def b/libc/include/sys/auxv.h.def index 504c2f68cb1eb770343121e44debd8d9633224f7..11ab25bcfe2c256fd01d587b5881beca8308bc7e 100644 --- a/libc/include/sys/auxv.h.def +++ b/libc/include/sys/auxv.h.def @@ -9,9 +9,9 @@ #ifndef LLVM_LIBC_SYS_AUXV_H #define LLVM_LIBC_SYS_AUXV_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" -#include <llvm-libc-macros/sys-auxv-macros.h> +#include "llvm-libc-macros/sys-auxv-macros.h" %%public_api() diff --git a/libc/include/sys/epoll.h.def b/libc/include/sys/epoll.h.def index 490fad91db3c3a5939d24cb782c9fe77ca89d318..85f7d9ad6091f089c7c273e46a27e99fd014652d 100644 --- a/libc/include/sys/epoll.h.def +++ b/libc/include/sys/epoll.h.def @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_SYS_EPOLL_H #define LLVM_LIBC_SYS_EPOLL_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" %%public_api() diff --git a/libc/include/sys/ioctl.h.def b/libc/include/sys/ioctl.h.def index 90d91cf382913cd55c84c8bc11e93dd5c26ec855..2f37a1190ac11d1bbe3c08aafe79b12a5d819670 100644 --- a/libc/include/sys/ioctl.h.def +++ b/libc/include/sys/ioctl.h.def @@ -9,9 +9,9 @@ #ifndef LLVM_LIBC_SYS_IOCTL_H #define LLVM_LIBC_SYS_IOCTL_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" -#include <llvm-libc-macros/sys-ioctl-macros.h> +#include "llvm-libc-macros/sys-ioctl-macros.h" %%public_api() diff --git a/libc/include/sys/mman.h.def b/libc/include/sys/mman.h.def index ab9fde1bb9204be3153329b23652ec67a085ee51..2e2c2f1997b834396ac4651dcf8b1756ccbf6f79 100644 --- a/libc/include/sys/mman.h.def +++ b/libc/include/sys/mman.h.def @@ -9,9 +9,9 @@ #ifndef LLVM_LIBC_SYS_MMAN_H #define LLVM_LIBC_SYS_MMAN_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" -#include <llvm-libc-macros/sys-mman-macros.h> +#include "llvm-libc-macros/sys-mman-macros.h" %%public_api() diff --git a/libc/include/sys/prctl.h.def b/libc/include/sys/prctl.h.def index 0a11543d072967791f7568705e29d77d1f2c5cb3..08648c9f47922e8408832a8e1d09871d3e9816d0 100644 --- a/libc/include/sys/prctl.h.def +++ b/libc/include/sys/prctl.h.def @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_SYS_PRCTL_H #define LLVM_LIBC_SYS_PRCTL_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" // Process control is highly platform specific, so the platform usually defines // the macros itself. diff --git a/libc/include/sys/queue.h b/libc/include/sys/queue.h index 1cde35e77a04e3269ec55fac90d8bb639df50e88..cca53c16f0f3c929f7c495fec075bc5c20e98e4f 100644 --- a/libc/include/sys/queue.h +++ b/libc/include/sys/queue.h @@ -9,6 +9,6 @@ #ifndef SYS_QUEUE_H #define SYS_QUEUE_H -#include <llvm-libc-macros/sys-queue-macros.h> +#include "llvm-libc-macros/sys-queue-macros.h" #endif // SYS_QUEUE_H diff --git a/libc/include/sys/random.h.def b/libc/include/sys/random.h.def index b767f2479fc2d410e64d4c21190f489d35035ae8..d11431b2755d9a5c772d22b9c9c1cba0d1e03296 100644 --- a/libc/include/sys/random.h.def +++ b/libc/include/sys/random.h.def @@ -9,9 +9,9 @@ #ifndef LLVM_LIBC_SYS_RANDOM_H #define LLVM_LIBC_SYS_RANDOM_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" -#include <llvm-libc-macros/sys-random-macros.h> +#include "llvm-libc-macros/sys-random-macros.h" %%public_api() diff --git a/libc/include/sys/resource.h.def b/libc/include/sys/resource.h.def index 31132d3b26087fb6479b921fb45f78ea3c44fb0c..365d803cf7154f14d3b3db382e3be7191fb6fd5c 100644 --- a/libc/include/sys/resource.h.def +++ b/libc/include/sys/resource.h.def @@ -9,9 +9,9 @@ #ifndef LLVM_LIBC_SYS_RESOURCE_H #define LLVM_LIBC_SYS_RESOURCE_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" -#include <llvm-libc-macros/sys-resource-macros.h> +#include "llvm-libc-macros/sys-resource-macros.h" %%public_api() diff --git a/libc/include/sys/select.h.def b/libc/include/sys/select.h.def index 4f3cebaecbb939deecb79dd7134237bfb5692570..529be7158f262c0b1db1cfada0801222c6980ac9 100644 --- a/libc/include/sys/select.h.def +++ b/libc/include/sys/select.h.def @@ -9,9 +9,9 @@ #ifndef LLVM_LIBC_SYS_SELECT_H #define LLVM_LIBC_SYS_SELECT_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" -#include <llvm-libc-macros/sys-select-macros.h> +#include "llvm-libc-macros/sys-select-macros.h" %%public_api() diff --git a/libc/include/sys/sendfile.h.def b/libc/include/sys/sendfile.h.def index 947edc28e1ecf240fe9dcbbcce394072c5561c0d..d7f21f91f95edf3c2844765079eb803c5ce5383c 100644 --- a/libc/include/sys/sendfile.h.def +++ b/libc/include/sys/sendfile.h.def @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_SYS_SENDFILE_H #define LLVM_LIBC_SYS_SENDFILE_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" %%public_api() diff --git a/libc/include/sys/socket.h.def b/libc/include/sys/socket.h.def index 71654c64b9885db84008b71c5af498dd8de0675b..933ef1512e45475e45fd256568d7bd58df03f0ce 100644 --- a/libc/include/sys/socket.h.def +++ b/libc/include/sys/socket.h.def @@ -9,9 +9,9 @@ #ifndef LLVM_LIBC_SYS_SOCKET_H #define LLVM_LIBC_SYS_SOCKET_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" -#include <llvm-libc-macros/sys-socket-macros.h> +#include "llvm-libc-macros/sys-socket-macros.h" %%public_api() diff --git a/libc/include/sys/stat.h.def b/libc/include/sys/stat.h.def index ed37d010f497d3f4493fe16b0cf8e353b824bad2..06a98a4aa029c2eafd058e6e24f63549976e6dd5 100644 --- a/libc/include/sys/stat.h.def +++ b/libc/include/sys/stat.h.def @@ -9,9 +9,9 @@ #ifndef LLVM_LIBC_SYS_STAT_H #define LLVM_LIBC_SYS_STAT_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" -#include <llvm-libc-macros/sys-stat-macros.h> +#include "llvm-libc-macros/sys-stat-macros.h" %%public_api() diff --git a/libc/include/sys/statvfs.h.def b/libc/include/sys/statvfs.h.def new file mode 100644 index 0000000000000000000000000000000000000000..f23c9a3d5b1f93d7fcf96071fa2adcfb576ad9d1 --- /dev/null +++ b/libc/include/sys/statvfs.h.def @@ -0,0 +1,16 @@ +//===-- 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/time.h.def b/libc/include/sys/time.h.def index 9a3bd7bb49f8f56749d00c8a60671e302e66870a..5a87139aefc95e3c91474d3b1bd4007c78950a9f 100644 --- a/libc/include/sys/time.h.def +++ b/libc/include/sys/time.h.def @@ -9,11 +9,11 @@ #ifndef LLVM_LIBC_SYS_TIME_H #define LLVM_LIBC_SYS_TIME_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" -#include <llvm-libc-types/struct_timeval.h> +#include "llvm-libc-types/struct_timeval.h" -#include <llvm-libc-macros/sys-time-macros.h> +#include "llvm-libc-macros/sys-time-macros.h" %%public_api() diff --git a/libc/include/sys/types.h.def b/libc/include/sys/types.h.def index 689482973fc7a3751d8a06709cccad58d1051503..f5c3bb2c928bf0827a2beb5335c4c4cb098f4794 100644 --- a/libc/include/sys/types.h.def +++ b/libc/include/sys/types.h.def @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_SYS_TYPES_H #define LLVM_LIBC_SYS_TYPES_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" %%public_api() diff --git a/libc/include/sys/utsname.h.def b/libc/include/sys/utsname.h.def index 6d7daeb45f018fd8a562f7c0a4cadf800ea23549..08dbbfc0624539626d04c79c2c5a992b48841963 100644 --- a/libc/include/sys/utsname.h.def +++ b/libc/include/sys/utsname.h.def @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_SYS_UTSNAME_H #define LLVM_LIBC_SYS_UTSNAME_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" %%public_api() diff --git a/libc/include/sys/wait.h.def b/libc/include/sys/wait.h.def index b4fcce4d16529d69894035c51f95e5f0f49478ac..0a76da019fdce682d234881c7703dd766b357f53 100644 --- a/libc/include/sys/wait.h.def +++ b/libc/include/sys/wait.h.def @@ -9,9 +9,9 @@ #ifndef LLVM_LIBC_SYS_WAIT_H #define LLVM_LIBC_SYS_WAIT_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" -#include <llvm-libc-macros/sys-wait-macros.h> +#include "llvm-libc-macros/sys-wait-macros.h" %%public_api() diff --git a/libc/include/termios.h.def b/libc/include/termios.h.def index be1cd2bff526c117fc0ea226bed2b96fdbe75126..7538944c0985e7aa154796c80c928d86ad7122dc 100644 --- a/libc/include/termios.h.def +++ b/libc/include/termios.h.def @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_TERMIOS_H #define LLVM_LIBC_TERMIOS_H -#include <__llvm-libc-common.h> -#include <llvm-libc-macros/termios-macros.h> +#include "__llvm-libc-common.h" +#include "llvm-libc-macros/termios-macros.h" %%public_api() diff --git a/libc/include/threads.h.def b/libc/include/threads.h.def index 93541b8d3bac450c1f0e3cb60777c9ced587ed46..b114bea0ace3496a89710455d373c38f3545c3ad 100644 --- a/libc/include/threads.h.def +++ b/libc/include/threads.h.def @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_THREADS_H #define LLVM_LIBC_THREADS_H -#include <__llvm-libc-common.h> +#include "__llvm-libc-common.h" %%public_api() diff --git a/libc/include/time.h.def b/libc/include/time.h.def index d8988329a372b1a1817c07245b69a41c30dd891e..2355e8822fad7aee79173640e727d7e132cad7ed 100644 --- a/libc/include/time.h.def +++ b/libc/include/time.h.def @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_TIME_H #define LLVM_LIBC_TIME_H -#include <__llvm-libc-common.h> -#include <llvm-libc-macros/time-macros.h> +#include "__llvm-libc-common.h" +#include "llvm-libc-macros/time-macros.h" %%public_api() diff --git a/libc/include/uchar.h.def b/libc/include/uchar.h.def new file mode 100644 index 0000000000000000000000000000000000000000..31b7fcb73ded6a809afd2059dac57dafe4be6fda --- /dev/null +++ b/libc/include/uchar.h.def @@ -0,0 +1,16 @@ +//===-- 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. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_UCHAR_H +#define LLVM_LIBC_UCHAR_H + +#include "__llvm-libc-common.h" + +%%public_api() + +#endif // LLVM_LIBC_UCHAR_H diff --git a/libc/include/unistd.h.def b/libc/include/unistd.h.def index fa10af653fae27e13f2405eae7345aac88231e1c..6b9137e14623cc674106c48ec3c1a3ca7aa1e69b 100644 --- a/libc/include/unistd.h.def +++ b/libc/include/unistd.h.def @@ -9,9 +9,9 @@ #ifndef LLVM_LIBC_UNISTD_H #define LLVM_LIBC_UNISTD_H -#include <__llvm-libc-common.h> -#include <llvm-libc-macros/file-seek-macros.h> -#include <llvm-libc-macros/unistd-macros.h> +#include "__llvm-libc-common.h" +#include "llvm-libc-macros/file-seek-macros.h" +#include "llvm-libc-macros/unistd-macros.h" %%public_api() diff --git a/libc/include/wchar.h.def b/libc/include/wchar.h.def index ac72f80aa0833974261d2202a7ad40a7039ef0c4..4c25de700d6063dd6a7e5f84d0b1710a4f3ad3c6 100644 --- a/libc/include/wchar.h.def +++ b/libc/include/wchar.h.def @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_WCHAR_H #define LLVM_LIBC_WCHAR_H -#include <__llvm-libc-common.h> -#include <llvm-libc-macros/wchar-macros.h> +#include "__llvm-libc-common.h" +#include "llvm-libc-macros/wchar-macros.h" %%public_api() diff --git a/libc/spec/posix.td b/libc/spec/posix.td index d0f5a4584dd45b815e485edad1d4eb5a7690d56c..cfa8d3afedde3f17e661bb55ffcfa5b0a4bcee52 100644 --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -42,10 +42,6 @@ def StructDirentPtr : PtrType<StructDirent>; def StructDirentPtrPtr : PtrType<StructDirentPtr>; def ConstStructDirentPtrPtr : ConstType<StructDirentPtrPtr>; -def StructTimeSpec : NamedType<"struct timespec">; -def StructTimeSpecPtr : PtrType<StructTimeSpec>; -def ConstStructTimeSpecPtr : ConstType<StructTimeSpecPtr>; - def StructSchedParam : NamedType<"struct sched_param">; def StructSchedParamPtr : PtrType<StructSchedParam>; def ConstStructSchedParamPtr : ConstType<StructSchedParamPtr>; @@ -90,6 +86,10 @@ def ConstStructSockAddrPtr : ConstType<StructSockAddrPtr>; def StructSockAddrUn : NamedType<"struct sockaddr_un">; +def StructStatvfs : NamedType<"struct statvfs">; +def StructStatvfsPtr : PtrType<StructStatvfs>; +def RestrictedStructStatvfsPtr : RestrictedPtrType<StructStatvfs>; + def POSIX : StandardSpec<"POSIX"> { PtrType CharPtr = PtrType<CharType>; RestrictedPtrType RestrictedCharPtr = RestrictedPtrType<CharType>; @@ -250,6 +250,7 @@ def POSIX : StandardSpec<"POSIX"> { [ SizeTType, OffTType, + ModeTType, ], [], // Enumerations [ @@ -314,6 +315,16 @@ def POSIX : StandardSpec<"POSIX"> { RetValSpec<IntType>, [ArgSpec<VoidPtr>, ArgSpec<SizeTType>, ArgSpec<IntType>] >, + FunctionSpec< + "shm_open", + RetValSpec<IntType>, + [ArgSpec<ConstCharPtr>, ArgSpec<IntType>, ArgSpec<ModeTType>] + >, + FunctionSpec< + "shm_unlink", + RetValSpec<IntType>, + [ArgSpec<ConstCharPtr>] + >, ] >; @@ -393,6 +404,11 @@ def POSIX : StandardSpec<"POSIX"> { ], [], // Enumerations [ + FunctionSpec< + "_exit", + RetValSpec<NoReturn>, + [ArgSpec<IntType>] + >, FunctionSpec< "access", RetValSpec<IntType>, @@ -881,6 +897,31 @@ def POSIX : StandardSpec<"POSIX"> { ] >; + HeaderSpec SysStatvfs = HeaderSpec< + "sys/statvfs.h", + [], // Macros + [StructStatvfs], // Types + [], // Enumerations + [ + FunctionSpec< + "statvfs", + RetValSpec<IntType>, + [ + ArgSpec<ConstRestrictedCharPtr>, + ArgSpec<RestrictedStructStatvfsPtr> + ] + >, + FunctionSpec< + "fstatvfs", + RetValSpec<IntType>, + [ + ArgSpec<IntType>, + ArgSpec<StructStatvfsPtr> + ] + >, + ] // Functions + >; + NamedType StructUtsName = NamedType<"struct utsname">; PtrType StructUtsNamePtr = PtrType<StructUtsName>; HeaderSpec SysUtsName = HeaderSpec< @@ -1162,6 +1203,11 @@ def POSIX : StandardSpec<"POSIX"> { RetValSpec<IntType>, [ArgSpec<VoidType>] >, + FunctionSpec< + "fileno", + RetValSpec<IntType>, + [ArgSpec<FILEPtr>] + >, ] >; @@ -1493,6 +1539,7 @@ def POSIX : StandardSpec<"POSIX"> { SysSelect, SysSocket, SysStat, + SysStatvfs, SysTypes, SysUtsName, SysWait, diff --git a/libc/spec/spec.td b/libc/spec/spec.td index a44a7ae131b5d97b2a049914c5ee47dd294c6727..87bf4435e16724501b8ac5c4df1d5076cbbeb317 100644 --- a/libc/spec/spec.td +++ b/libc/spec/spec.td @@ -118,6 +118,10 @@ def SigHandlerT : NamedType<"__sighandler_t">; def TimeTType : NamedType<"time_t">; +def StructTimeSpec : NamedType<"struct timespec">; +def StructTimeSpecPtr : PtrType<StructTimeSpec>; +def ConstStructTimeSpecPtr : ConstType<StructTimeSpecPtr>; + def BSearchCompareT : NamedType<"__bsearchcompare_t">; def QSortCompareT : NamedType<"__qsortcompare_t">; @@ -149,6 +153,8 @@ def EntryType : NamedType<"ENTRY">; def EntryTypePtr : PtrType<EntryType>; def EntryTypePtrPtr : PtrType<EntryTypePtr>; +def MBStateTType : NamedType<"mbstate_t">; + class Macro<string name> { string Name = name; } diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index e012d0dee0898223833c79199033f4cf95d5f11c..719bb9aa18cb0acc5ad181eb61bba58034b81cde 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -352,6 +352,12 @@ def StdC : StandardSpec<"stdc"> { Macro<"INFINITY">, Macro<"NAN">, + Macro<"FP_INT_UPWARD">, + Macro<"FP_INT_DOWNWARD">, + Macro<"FP_INT_TOWARDZERO">, + Macro<"FP_INT_TONEARESTFROMZERO">, + Macro<"FP_INT_TONEAREST">, + Macro<"FP_ILOGB0">, Macro<"FP_ILOGBNAN">, @@ -400,6 +406,46 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"fmaxf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>, FunctionSpec<"fmaxl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>, GuardedFunctionSpec<"fmaxf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">, + + FunctionSpec<"fmaximum", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>, + FunctionSpec<"fmaximumf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>, + FunctionSpec<"fmaximuml", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>, + GuardedFunctionSpec<"fmaximumf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">, + + FunctionSpec<"fmaximum_num", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>, + FunctionSpec<"fmaximum_numf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>, + FunctionSpec<"fmaximum_numl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>, + GuardedFunctionSpec<"fmaximum_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">, + + FunctionSpec<"fmaximum_mag", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>, + FunctionSpec<"fmaximum_magf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>, + FunctionSpec<"fmaximum_magl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>, + GuardedFunctionSpec<"fmaximum_magf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">, + + FunctionSpec<"fmaximum_mag_num", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>, + FunctionSpec<"fmaximum_mag_numf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>, + FunctionSpec<"fmaximum_mag_numl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>, + GuardedFunctionSpec<"fmaximum_mag_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">, + + FunctionSpec<"fminimum", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>, + FunctionSpec<"fminimumf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>, + FunctionSpec<"fminimuml", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>, + GuardedFunctionSpec<"fminimumf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">, + + FunctionSpec<"fminimum_num", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>, + FunctionSpec<"fminimum_numf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>, + FunctionSpec<"fmaximum_numl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>, + GuardedFunctionSpec<"fminimum_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">, + + FunctionSpec<"fminimum_mag", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>, + FunctionSpec<"fminimum_magf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>, + FunctionSpec<"fminimum_magl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>, + GuardedFunctionSpec<"fminimum_magf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">, + + FunctionSpec<"fminimum_mag_num", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>, + FunctionSpec<"fminimum_mag_numf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>, + FunctionSpec<"fminimum_mag_numl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>, + GuardedFunctionSpec<"fminimum_mag_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">, FunctionSpec<"fma", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>, ArgSpec<DoubleType>]>, FunctionSpec<"fmaf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>, ArgSpec<FloatType>]>, @@ -414,6 +460,26 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"frexpl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntPtr>]>, GuardedFunctionSpec<"frexpf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<IntPtr>], "LIBC_TYPES_HAS_FLOAT128">, + FunctionSpec<"fromfp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>, + FunctionSpec<"fromfpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>, + FunctionSpec<"fromfpl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>, + GuardedFunctionSpec<"fromfpf128", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT128">, + + FunctionSpec<"fromfpx", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>, + FunctionSpec<"fromfpxf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>, + FunctionSpec<"fromfpxl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>, + GuardedFunctionSpec<"fromfpxf128", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT128">, + + FunctionSpec<"ufromfp", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>, + FunctionSpec<"ufromfpf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>, + FunctionSpec<"ufromfpl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>, + GuardedFunctionSpec<"ufromfpf128", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT128">, + + FunctionSpec<"ufromfpx", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>, + FunctionSpec<"ufromfpxf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>, + FunctionSpec<"ufromfpxl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>]>, + GuardedFunctionSpec<"ufromfpxf128", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<IntType>, ArgSpec<UnsignedIntType>], "LIBC_TYPES_HAS_FLOAT128">, + FunctionSpec<"hypot", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>, FunctionSpec<"hypotf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>, @@ -530,11 +596,22 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"nextafterf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>, FunctionSpec<"nextafter", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>, FunctionSpec<"nextafterl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>, + GuardedFunctionSpec<"nextafterf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">, FunctionSpec<"nexttowardf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<LongDoubleType>]>, FunctionSpec<"nexttoward", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<LongDoubleType>]>, FunctionSpec<"nexttowardl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>, + FunctionSpec<"nextdown", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>, + FunctionSpec<"nextdownf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>, + FunctionSpec<"nextdownl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>, + GuardedFunctionSpec<"nextdownf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">, + + FunctionSpec<"nextup", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>, + FunctionSpec<"nextupf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>, + FunctionSpec<"nextupl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>]>, + GuardedFunctionSpec<"nextupf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">, + FunctionSpec<"powf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>, FunctionSpec<"pow", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>, @@ -543,10 +620,14 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"tanhf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>, FunctionSpec<"acosf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>, + FunctionSpec<"asinf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>, FunctionSpec<"asin", RetValSpec<DoubleType>, [ArgSpec<DoubleType>]>, + FunctionSpec<"atanf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>, + FunctionSpec<"atan2f", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>, + FunctionSpec<"acoshf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>, FunctionSpec<"asinhf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>, FunctionSpec<"atanhf", RetValSpec<FloatType>, [ArgSpec<FloatType>]>, @@ -558,6 +639,12 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"nanf", RetValSpec<FloatType>, [ArgSpec<ConstCharPtr>]>, FunctionSpec<"nan", RetValSpec<DoubleType>, [ArgSpec<ConstCharPtr>]>, FunctionSpec<"nanl", RetValSpec<LongDoubleType>, [ArgSpec<ConstCharPtr>]>, + GuardedFunctionSpec<"nanf128", RetValSpec<Float128Type>, [ArgSpec<ConstCharPtr>], "LIBC_TYPES_HAS_FLOAT128">, + + FunctionSpec<"canonicalize", RetValSpec<IntType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>, + FunctionSpec<"canonicalizef", RetValSpec<IntType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>, + FunctionSpec<"canonicalizel", RetValSpec<IntType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>, + GuardedFunctionSpec<"canonicalizef128", RetValSpec<IntType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">, ] >; @@ -694,6 +781,11 @@ def StdC : StandardSpec<"stdc"> { RetValSpec<IntType>, [ArgSpec<ConstCharPtr>] >, + FunctionSpec< + "rename", + RetValSpec<IntType>, + [ArgSpec<ConstCharPtr>, ArgSpec<ConstCharPtr>] + >, FunctionSpec< "setbuf", RetValSpec<VoidType>, @@ -944,6 +1036,10 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"rand", RetValSpec<IntType>, [ArgSpec<VoidType>]>, FunctionSpec<"srand", RetValSpec<VoidType>, [ArgSpec<UnsignedIntType>]>, + FunctionSpec<"strfromf", RetValSpec<IntType>, [ArgSpec<CharRestrictedPtr>, ArgSpec<SizeTType>, ArgSpec<ConstCharRestrictedPtr>, ArgSpec<FloatType>]>, + FunctionSpec<"strfromd", RetValSpec<IntType>, [ArgSpec<CharRestrictedPtr>, ArgSpec<SizeTType>, ArgSpec<ConstCharRestrictedPtr>, ArgSpec<DoubleType>]>, + FunctionSpec<"strfroml", RetValSpec<IntType>, [ArgSpec<CharRestrictedPtr>, ArgSpec<SizeTType>, ArgSpec<ConstCharRestrictedPtr>, ArgSpec<LongDoubleType>]>, + FunctionSpec<"strtof", RetValSpec<FloatType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>, FunctionSpec<"strtod", RetValSpec<DoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>, FunctionSpec<"strtold", RetValSpec<LongDoubleType>, [ArgSpec<ConstCharRestrictedPtr>, ArgSpec<CharRestrictedPtrPtr>]>, @@ -1202,6 +1298,7 @@ def StdC : StandardSpec<"stdc"> { [ // Types ClockT, StructTmType, + StructTimeSpec, TimeTType, ], [], // Enumerations @@ -1282,12 +1379,23 @@ def StdC : StandardSpec<"stdc"> { ] >; + HeaderSpec UChar = HeaderSpec< + "uchar.h", + [], // Macros + [ //Types + MBStateTType, + ], + [], // Enumerations + [] + >; + HeaderSpec WChar = HeaderSpec< "wchar.h", [ // Macros Macro<"WEOF">, ], [ //Types + MBStateTType, SizeTType, WIntType, WCharType, @@ -1322,6 +1430,7 @@ def StdC : StandardSpec<"stdc"> { Signal, Threads, Time, + UChar, WChar, ]; } diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt index 4c1f271e1df43aea5cc039f564df3f321a946bbe..7b1820d9bf3538575346ea6926fb401f6447b875 100644 --- a/libc/src/__support/CMakeLists.txt +++ b/libc/src/__support/CMakeLists.txt @@ -41,6 +41,14 @@ add_header_library( libc.src.__support.macros.config ) +add_header_library( + sign + HDRS + sign.h + DEPENDS + libc.src.__support.macros.attributes +) + add_header_library( error_or HDRS diff --git a/libc/src/__support/CPP/CMakeLists.txt b/libc/src/__support/CPP/CMakeLists.txt index 6216505eae23a35ccbb5009d1609178075bc947d..84d01fe045160265e26251e1c58ed037b24fe45b 100644 --- a/libc/src/__support/CPP/CMakeLists.txt +++ b/libc/src/__support/CPP/CMakeLists.txt @@ -18,7 +18,6 @@ add_header_library( .limits .type_traits libc.src.__support.macros.attributes - libc.src.__support.macros.config libc.src.__support.macros.sanitizer ) @@ -103,23 +102,24 @@ add_header_library( type_traits HDRS type_traits.h - type_traits/always_false.h type_traits/add_lvalue_reference.h type_traits/add_pointer.h type_traits/add_rvalue_reference.h + type_traits/always_false.h type_traits/bool_constant.h type_traits/conditional.h type_traits/decay.h type_traits/enable_if.h type_traits/false_type.h type_traits/integral_constant.h - type_traits/invoke.h type_traits/invoke_result.h + type_traits/invoke.h type_traits/is_arithmetic.h type_traits/is_array.h type_traits/is_base_of.h type_traits/is_class.h type_traits/is_const.h + type_traits/is_constant_evaluated.h type_traits/is_convertible.h type_traits/is_destructible.h type_traits/is_enum.h @@ -156,7 +156,6 @@ add_header_library( DEPENDS libc.include.llvm-libc-macros.stdfix_macros libc.src.__support.macros.attributes - libc.src.__support.macros.config libc.src.__support.macros.properties.types ) diff --git a/libc/src/__support/CPP/array.h b/libc/src/__support/CPP/array.h index fb5a79225beb7d22dcf003b345fe9b9b61f25c63..4e69ba003e800bc24b1afb404ea8ab2750d2f733 100644 --- a/libc/src/__support/CPP/array.h +++ b/libc/src/__support/CPP/array.h @@ -9,6 +9,7 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_ARRAY_H #define LLVM_LIBC_SRC___SUPPORT_CPP_ARRAY_H +#include "src/__support/CPP/iterator.h" // reverse_iterator #include "src/__support/macros/attributes.h" #include <stddef.h> // For size_t. @@ -23,6 +24,8 @@ template <class T, size_t N> struct array { using value_type = T; using iterator = T *; using const_iterator = const T *; + using reverse_iterator = cpp::reverse_iterator<iterator>; + using const_reverse_iterator = cpp::reverse_iterator<const_iterator>; LIBC_INLINE constexpr T *data() { return Data; } LIBC_INLINE constexpr const T *data() const { return Data; } @@ -45,9 +48,29 @@ template <class T, size_t N> struct array { LIBC_INLINE constexpr iterator begin() { return Data; } LIBC_INLINE constexpr const_iterator begin() const { return Data; } + LIBC_INLINE constexpr const_iterator cbegin() const { return begin(); } LIBC_INLINE constexpr iterator end() { return Data + N; } LIBC_INLINE constexpr const_iterator end() const { return Data + N; } + LIBC_INLINE constexpr const_iterator cend() const { return end(); } + + LIBC_INLINE constexpr reverse_iterator rbegin() { + return reverse_iterator{end()}; + } + LIBC_INLINE constexpr const_reverse_iterator rbegin() const { + return const_reverse_iterator{end()}; + } + LIBC_INLINE constexpr const_reverse_iterator crbegin() const { + return rbegin(); + } + + LIBC_INLINE constexpr reverse_iterator rend() { + return reverse_iterator{begin()}; + } + LIBC_INLINE constexpr const_reverse_iterator rend() const { + return const_reverse_iterator{begin()}; + } + LIBC_INLINE constexpr const_reverse_iterator crend() const { return rend(); } }; } // namespace cpp diff --git a/libc/src/__support/CPP/atomic.h b/libc/src/__support/CPP/atomic.h index b74cb5981dbaf8ef80889aea7e9084ce894fe9b9..5e428940565b991f70914bdabeb4cf031489d50c 100644 --- a/libc/src/__support/CPP/atomic.h +++ b/libc/src/__support/CPP/atomic.h @@ -71,10 +71,11 @@ public: T load(MemoryOrder mem_ord = MemoryOrder::SEQ_CST, [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) { - if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_load_n)) - return __scoped_atomic_load_n(&val, int(mem_ord), (int)(mem_scope)); - else - return __atomic_load_n(&val, int(mem_ord)); +#if __has_builtin(__scoped_atomic_load_n) + return __scoped_atomic_load_n(&val, int(mem_ord), (int)(mem_scope)); +#else + return __atomic_load_n(&val, int(mem_ord)); +#endif } // Atomic store. @@ -85,10 +86,11 @@ public: void store(T rhs, MemoryOrder mem_ord = MemoryOrder::SEQ_CST, [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) { - if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_store_n)) - __scoped_atomic_store_n(&val, rhs, int(mem_ord), (int)(mem_scope)); - else - __atomic_store_n(&val, rhs, int(mem_ord)); +#if __has_builtin(__scoped_atomic_store_n) + __scoped_atomic_store_n(&val, rhs, int(mem_ord), (int)(mem_scope)); +#else + __atomic_store_n(&val, rhs, int(mem_ord)); +#endif } // Atomic compare exchange @@ -101,47 +103,51 @@ public: T exchange(T desired, MemoryOrder mem_ord = MemoryOrder::SEQ_CST, [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) { - if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_exchange_n)) - return __scoped_atomic_exchange_n(&val, desired, int(mem_ord), - (int)(mem_scope)); - else - return __atomic_exchange_n(&val, desired, int(mem_ord)); +#if __has_builtin(__scoped_atomic_exchange_n) + return __scoped_atomic_exchange_n(&val, desired, int(mem_ord), + (int)(mem_scope)); +#else + return __atomic_exchange_n(&val, desired, int(mem_ord)); +#endif } T fetch_add(T increment, MemoryOrder mem_ord = MemoryOrder::SEQ_CST, [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) { - if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_fetch_add)) - return __scoped_atomic_fetch_add(&val, increment, int(mem_ord), - (int)(mem_scope)); - else - return __atomic_fetch_add(&val, increment, int(mem_ord)); +#if __has_builtin(__scoped_atomic_fetch_add) + return __scoped_atomic_fetch_add(&val, increment, int(mem_ord), + (int)(mem_scope)); +#else + return __atomic_fetch_add(&val, increment, int(mem_ord)); +#endif } T fetch_or(T mask, MemoryOrder mem_ord = MemoryOrder::SEQ_CST, [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) { - if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_fetch_or)) - return __scoped_atomic_fetch_or(&val, mask, int(mem_ord), - (int)(mem_scope)); - else - return __atomic_fetch_or(&val, mask, int(mem_ord)); +#if __has_builtin(__scoped_atomic_fetch_or) + return __scoped_atomic_fetch_or(&val, mask, int(mem_ord), (int)(mem_scope)); +#else + return __atomic_fetch_or(&val, mask, int(mem_ord)); +#endif } T fetch_and(T mask, MemoryOrder mem_ord = MemoryOrder::SEQ_CST, [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) { - if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_fetch_and)) - return __scoped_atomic_fetch_and(&val, mask, int(mem_ord), - (int)(mem_scope)); - else - return __atomic_fetch_and(&val, mask, int(mem_ord)); +#if __has_builtin(__scoped_atomic_fetch_and) + return __scoped_atomic_fetch_and(&val, mask, int(mem_ord), + (int)(mem_scope)); +#else + return __atomic_fetch_and(&val, mask, int(mem_ord)); +#endif } T fetch_sub(T decrement, MemoryOrder mem_ord = MemoryOrder::SEQ_CST, [[maybe_unused]] MemoryScope mem_scope = MemoryScope::DEVICE) { - if constexpr (LIBC_HAS_BUILTIN(__scoped_atomic_fetch_sub)) - return __scoped_atomic_fetch_sub(&val, decrement, int(mem_ord), - (int)(mem_scope)); - else - return __atomic_fetch_sub(&val, decrement, int(mem_ord)); +#if __has_builtin(__scoped_atomic_fetch_sub) + return __scoped_atomic_fetch_sub(&val, decrement, int(mem_ord), + (int)(mem_scope)); +#else + return __atomic_fetch_sub(&val, decrement, int(mem_ord)); +#endif } // Set the value without using an atomic operation. This is useful @@ -166,7 +172,7 @@ LIBC_INLINE void atomic_thread_fence([[maybe_unused]] MemoryOrder mem_ord) { // except no instructions for memory ordering are issued. Only reordering of // the instructions by the compiler is suppressed as order instructs. LIBC_INLINE void atomic_signal_fence([[maybe_unused]] MemoryOrder mem_ord) { -#if LIBC_HAS_BUILTIN(__atomic_signal_fence) +#if __has_builtin(__atomic_signal_fence) __atomic_signal_fence(static_cast<int>(mem_ord)); #else // if the builtin is not ready, use asm as a full compiler barrier. diff --git a/libc/src/__support/CPP/bit.h b/libc/src/__support/CPP/bit.h index 3f2fbec944054cdb8ae2e144ed7c6d784c4e2083..80f50fd221efa7ed7352459228d14d943b50ffd1 100644 --- a/libc/src/__support/CPP/bit.h +++ b/libc/src/__support/CPP/bit.h @@ -14,14 +14,13 @@ #include "src/__support/CPP/limits.h" // numeric_limits #include "src/__support/CPP/type_traits.h" #include "src/__support/macros/attributes.h" -#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN #include "src/__support/macros/sanitizer.h" #include <stdint.h> namespace LIBC_NAMESPACE::cpp { -#if LIBC_HAS_BUILTIN(__builtin_memcpy_inline) +#if __has_builtin(__builtin_memcpy_inline) #define LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE #endif @@ -36,20 +35,20 @@ LIBC_INLINE constexpr cpp::enable_if_t< To> bit_cast(const From &from) { MSAN_UNPOISON(&from, sizeof(From)); -#if LIBC_HAS_BUILTIN(__builtin_bit_cast) +#if __has_builtin(__builtin_bit_cast) return __builtin_bit_cast(To, from); #else To to; char *dst = reinterpret_cast<char *>(&to); const char *src = reinterpret_cast<const char *>(&from); -#if LIBC_HAS_BUILTIN(__builtin_memcpy_inline) +#if __has_builtin(__builtin_memcpy_inline) __builtin_memcpy_inline(dst, src, sizeof(To)); #else for (unsigned i = 0; i < sizeof(To); ++i) dst[i] = src[i]; -#endif // LIBC_HAS_BUILTIN(__builtin_memcpy_inline) +#endif // __has_builtin(__builtin_memcpy_inline) return to; -#endif // LIBC_HAS_BUILTIN(__builtin_bit_cast) +#endif // __has_builtin(__builtin_bit_cast) } template <typename T> @@ -94,7 +93,7 @@ countr_zero(T value) { } return zero_bits; } -#if LIBC_HAS_BUILTIN(__builtin_ctzs) +#if __has_builtin(__builtin_ctzs) ADD_SPECIALIZATION(countr_zero, unsigned short, __builtin_ctzs) #endif ADD_SPECIALIZATION(countr_zero, unsigned int, __builtin_ctz) @@ -124,7 +123,7 @@ countl_zero(T value) { } return zero_bits; } -#if LIBC_HAS_BUILTIN(__builtin_clzs) +#if __has_builtin(__builtin_clzs) ADD_SPECIALIZATION(countl_zero, unsigned short, __builtin_clzs) #endif ADD_SPECIALIZATION(countl_zero, unsigned int, __builtin_clz) @@ -242,6 +241,14 @@ LIBC_INLINE constexpr To bit_or_static_cast(const From &from) { /// Count number of 1's aka population count or Hamming weight. /// /// Only unsigned integral types are allowed. +// clang-19+, gcc-14+ +#if __has_builtin(__builtin_popcountg) +template <typename T> +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> +popcount(T value) { + return __builtin_popcountg(value); +} +#else // !__has_builtin(__builtin_popcountg) template <typename T> [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> popcount(T value) { @@ -261,7 +268,7 @@ ADD_SPECIALIZATION(unsigned short, __builtin_popcount) ADD_SPECIALIZATION(unsigned, __builtin_popcount) ADD_SPECIALIZATION(unsigned long, __builtin_popcountl) ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll) -// TODO: 128b specializations? +#endif // __builtin_popcountg #undef ADD_SPECIALIZATION } // namespace LIBC_NAMESPACE::cpp diff --git a/libc/src/__support/CPP/iterator.h b/libc/src/__support/CPP/iterator.h new file mode 100644 index 0000000000000000000000000000000000000000..b0fd5c9f22ae01de6bf535167b621199e988dad9 --- /dev/null +++ b/libc/src/__support/CPP/iterator.h @@ -0,0 +1,98 @@ +//===-- Standalone implementation of iterator -------------------*- 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_CPP_ITERATOR_H +#define LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H + +#include "src/__support/CPP/type_traits/enable_if.h" +#include "src/__support/CPP/type_traits/is_convertible.h" +#include "src/__support/CPP/type_traits/is_same.h" +#include "src/__support/macros/attributes.h" + +namespace LIBC_NAMESPACE { +namespace cpp { + +template <typename T> struct iterator_traits; +template <typename T> struct iterator_traits<T *> { + using reference = T &; + using value_type = T; +}; + +template <typename Iter> class reverse_iterator { + Iter current; + +public: + using reference = typename iterator_traits<Iter>::reference; + using value_type = typename iterator_traits<Iter>::value_type; + using iterator_type = Iter; + + LIBC_INLINE reverse_iterator() : current() {} + LIBC_INLINE constexpr explicit reverse_iterator(Iter it) : current(it) {} + + template <typename Other, + cpp::enable_if_t<!cpp::is_same_v<Iter, Other> && + cpp::is_convertible_v<const Other &, Iter>, + int> = 0> + LIBC_INLINE constexpr explicit reverse_iterator(const Other &it) + : current(it) {} + + LIBC_INLINE friend constexpr bool operator==(const reverse_iterator &lhs, + const reverse_iterator &rhs) { + return lhs.base() == rhs.base(); + } + + LIBC_INLINE friend constexpr bool operator!=(const reverse_iterator &lhs, + const reverse_iterator &rhs) { + return lhs.base() != rhs.base(); + } + + LIBC_INLINE friend constexpr bool operator<(const reverse_iterator &lhs, + const reverse_iterator &rhs) { + return lhs.base() > rhs.base(); + } + + LIBC_INLINE friend constexpr bool operator<=(const reverse_iterator &lhs, + const reverse_iterator &rhs) { + return lhs.base() >= rhs.base(); + } + + LIBC_INLINE friend constexpr bool operator>(const reverse_iterator &lhs, + const reverse_iterator &rhs) { + return lhs.base() < rhs.base(); + } + + LIBC_INLINE friend constexpr bool operator>=(const reverse_iterator &lhs, + const reverse_iterator &rhs) { + return lhs.base() <= rhs.base(); + } + + LIBC_INLINE constexpr iterator_type base() const { return current; } + + LIBC_INLINE constexpr reference operator*() const { + Iter tmp = current; + return *--tmp; + } + LIBC_INLINE constexpr reverse_iterator operator--() { + ++current; + return *this; + } + LIBC_INLINE constexpr reverse_iterator &operator++() { + --current; + return *this; + } + LIBC_INLINE constexpr reverse_iterator operator++(int) { + reverse_iterator tmp(*this); + --current; + return tmp; + } +}; + +} // namespace cpp +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC___SUPPORT_CPP_ITERATOR_H diff --git a/libc/src/__support/CPP/string_view.h b/libc/src/__support/CPP/string_view.h index d23aa261ca061465d821cea885a7bc19ed255a07..8aa96fa87f69869555428bd8773450992173095f 100644 --- a/libc/src/__support/CPP/string_view.h +++ b/libc/src/__support/CPP/string_view.h @@ -179,7 +179,8 @@ public: LIBC_INLINE char back() const { return Data[Len - 1]; } // Finds the first occurence of c in this view, starting at position From. - LIBC_INLINE size_t find_first_of(const char c, size_t From = 0) const { + LIBC_INLINE constexpr size_t find_first_of(const char c, + size_t From = 0) const { for (size_t Pos = From; Pos < size(); ++Pos) if ((*this)[Pos] == c) return Pos; @@ -187,13 +188,29 @@ public: } // Finds the last occurence of c in this view, ending at position End. - LIBC_INLINE size_t find_last_of(const char c, size_t End = npos) const { + LIBC_INLINE constexpr size_t find_last_of(const char c, + size_t End = npos) const { End = End >= size() ? size() : End + 1; for (; End > 0; --End) if ((*this)[End - 1] == c) return End - 1; return npos; } + + // Finds the first character not equal to c in this view, starting at position + // From. + LIBC_INLINE constexpr size_t find_first_not_of(const char c, + size_t From = 0) const { + for (size_t Pos = From; Pos < size(); ++Pos) + if ((*this)[Pos] != c) + return Pos; + return npos; + } + + // Check if this view contains the given character. + LIBC_INLINE constexpr bool contains(char c) const { + return find_first_of(c) != npos; + } }; } // namespace cpp diff --git a/libc/src/__support/CPP/type_traits.h b/libc/src/__support/CPP/type_traits.h index 697cf79d6ccc59411db326cb719764488e9ffa2d..1494aeb905e0935af897236b04431352ed3db704 100644 --- a/libc/src/__support/CPP/type_traits.h +++ b/libc/src/__support/CPP/type_traits.h @@ -25,6 +25,7 @@ #include "src/__support/CPP/type_traits/is_base_of.h" #include "src/__support/CPP/type_traits/is_class.h" #include "src/__support/CPP/type_traits/is_const.h" +#include "src/__support/CPP/type_traits/is_constant_evaluated.h" #include "src/__support/CPP/type_traits/is_convertible.h" #include "src/__support/CPP/type_traits/is_destructible.h" #include "src/__support/CPP/type_traits/is_enum.h" diff --git a/libc/src/__support/CPP/type_traits/add_pointer.h b/libc/src/__support/CPP/type_traits/add_pointer.h index 72a764bb8ba60c1de4396e058e4f7dd77251c276..1257033ee80e2c2c33587ec8fe7078026399c0d4 100644 --- a/libc/src/__support/CPP/type_traits/add_pointer.h +++ b/libc/src/__support/CPP/type_traits/add_pointer.h @@ -10,7 +10,6 @@ #include "src/__support/CPP/type_traits/remove_reference.h" #include "src/__support/CPP/type_traits/type_identity.h" -#include "src/__support/macros/config.h" namespace LIBC_NAMESPACE::cpp { diff --git a/libc/src/__support/CPP/type_traits/decay.h b/libc/src/__support/CPP/type_traits/decay.h index a018286fddd8abbd05c13054a83a3aaebf575bf9..f1a1200ab2ba1dc0fc268609a5357384e25d1f32 100644 --- a/libc/src/__support/CPP/type_traits/decay.h +++ b/libc/src/__support/CPP/type_traits/decay.h @@ -9,7 +9,6 @@ #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_DECAY_H #include "src/__support/macros/attributes.h" -#include "src/__support/macros/config.h" #include "src/__support/CPP/type_traits/add_pointer.h" #include "src/__support/CPP/type_traits/conditional.h" diff --git a/libc/src/__support/CPP/type_traits/is_constant_evaluated.h b/libc/src/__support/CPP/type_traits/is_constant_evaluated.h new file mode 100644 index 0000000000000000000000000000000000000000..93cfd07b567f0859ffe9fc243602cb90fecf271f --- /dev/null +++ b/libc/src/__support/CPP/type_traits/is_constant_evaluated.h @@ -0,0 +1,21 @@ +//===-- is_constant_evaluated type_traits -----------------------*- 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_CPP_TYPE_TRAITS_IS_CONSTANT_EVALUATED_H +#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CONSTANT_EVALUATED_H + +#include "src/__support/macros/attributes.h" + +namespace LIBC_NAMESPACE::cpp { + +LIBC_INLINE constexpr bool is_constant_evaluated() { + return __builtin_is_constant_evaluated(); +} + +} // namespace LIBC_NAMESPACE::cpp + +#endif // LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_CONSTANT_EVALUATED_H diff --git a/libc/src/__support/CPP/type_traits/is_destructible.h b/libc/src/__support/CPP/type_traits/is_destructible.h index d47de1cc797b2912e5fcea70b20b953b06d9398b..f94fe309ac8f744181e319e20d4f9708b207e9d1 100644 --- a/libc/src/__support/CPP/type_traits/is_destructible.h +++ b/libc/src/__support/CPP/type_traits/is_destructible.h @@ -16,12 +16,11 @@ #include "src/__support/CPP/type_traits/true_type.h" #include "src/__support/CPP/type_traits/type_identity.h" #include "src/__support/macros/attributes.h" -#include "src/__support/macros/config.h" namespace LIBC_NAMESPACE::cpp { // is_destructible -#if LIBC_HAS_BUILTIN(__is_destructible) +#if __has_builtin(__is_destructible) template <typename T> struct is_destructible : bool_constant<__is_destructible(T)> {}; #else diff --git a/libc/src/__support/CPP/type_traits/is_function.h b/libc/src/__support/CPP/type_traits/is_function.h index 557b3224484bcadfa0b0f795ad349052dc5b8850..0eba5860ad607a11e6ec1b8e99ce652e0ae0b5f0 100644 --- a/libc/src/__support/CPP/type_traits/is_function.h +++ b/libc/src/__support/CPP/type_traits/is_function.h @@ -12,12 +12,11 @@ #include "src/__support/CPP/type_traits/is_const.h" #include "src/__support/CPP/type_traits/is_reference.h" #include "src/__support/macros/attributes.h" -#include "src/__support/macros/config.h" namespace LIBC_NAMESPACE::cpp { // is_function -#if LIBC_HAS_BUILTIN(__is_function) +#if __has_builtin(__is_function) template <typename T> struct is_function : integral_constant<bool, __is_function(T)> {}; #else diff --git a/libc/src/__support/CPP/type_traits/is_lvalue_reference.h b/libc/src/__support/CPP/type_traits/is_lvalue_reference.h index f52e303afad2a5f689a17d9768d676dc47e1fff6..1dff57f186a3a35442f0af0f4074decae0a9fcc4 100644 --- a/libc/src/__support/CPP/type_traits/is_lvalue_reference.h +++ b/libc/src/__support/CPP/type_traits/is_lvalue_reference.h @@ -12,12 +12,11 @@ #include "src/__support/CPP/type_traits/false_type.h" #include "src/__support/CPP/type_traits/true_type.h" #include "src/__support/macros/attributes.h" -#include "src/__support/macros/config.h" namespace LIBC_NAMESPACE::cpp { // is_lvalue_reference -#if LIBC_HAS_BUILTIN(__is_lvalue_reference) +#if __has_builtin(__is_lvalue_reference) template <typename T> struct is_lvalue_reference : bool_constant<__is_lvalue_reference(T)> {}; #else diff --git a/libc/src/__support/CPP/type_traits/is_reference.h b/libc/src/__support/CPP/type_traits/is_reference.h index c017028edf411f6cd947ca530cc3c3a6fce7afa8..bbfb2b7359c3e1349748ef1eb3451b6626a80cad 100644 --- a/libc/src/__support/CPP/type_traits/is_reference.h +++ b/libc/src/__support/CPP/type_traits/is_reference.h @@ -12,12 +12,11 @@ #include "src/__support/CPP/type_traits/false_type.h" #include "src/__support/CPP/type_traits/true_type.h" #include "src/__support/macros/attributes.h" -#include "src/__support/macros/config.h" namespace LIBC_NAMESPACE::cpp { // is_reference -#if LIBC_HAS_BUILTIN(__is_reference) +#if __has_builtin(__is_reference) template <typename T> struct is_reference : bool_constant<__is_reference(T)> {}; #else template <typename T> struct is_reference : public false_type {}; diff --git a/libc/src/__support/CPP/type_traits/is_rvalue_reference.h b/libc/src/__support/CPP/type_traits/is_rvalue_reference.h index f0487e41c998fefdcf17ae51cf40b9067476e132..3efbbe6b033a0fe2f3d88a21c26a3f7e67a3a494 100644 --- a/libc/src/__support/CPP/type_traits/is_rvalue_reference.h +++ b/libc/src/__support/CPP/type_traits/is_rvalue_reference.h @@ -12,12 +12,11 @@ #include "src/__support/CPP/type_traits/false_type.h" #include "src/__support/CPP/type_traits/true_type.h" #include "src/__support/macros/attributes.h" -#include "src/__support/macros/config.h" namespace LIBC_NAMESPACE::cpp { // is_rvalue_reference -#if LIBC_HAS_BUILTIN(__is_rvalue_reference) +#if __has_builtin(__is_rvalue_reference) template <typename T> struct is_rvalue_reference : bool_constant<__is_rvalue_reference(T)> {}; #else diff --git a/libc/src/__support/CPP/type_traits/is_trivially_copyable.h b/libc/src/__support/CPP/type_traits/is_trivially_copyable.h index 0c3fdcc711d57f69e43d93f107d9e0db75c81c49..b4c825d579619c9258f67f13b5a4d30b6f1f5f3b 100644 --- a/libc/src/__support/CPP/type_traits/is_trivially_copyable.h +++ b/libc/src/__support/CPP/type_traits/is_trivially_copyable.h @@ -9,7 +9,6 @@ #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_TRIVIALLY_COPYABLE_H #include "src/__support/CPP/type_traits/integral_constant.h" -#include "src/__support/macros/config.h" namespace LIBC_NAMESPACE::cpp { diff --git a/libc/src/__support/CPP/type_traits/is_trivially_destructible.h b/libc/src/__support/CPP/type_traits/is_trivially_destructible.h index 3345149433afc47e4476c29860158d89550c0e27..37e0e869266e1d1852ce3208078cf10add421ee0 100644 --- a/libc/src/__support/CPP/type_traits/is_trivially_destructible.h +++ b/libc/src/__support/CPP/type_traits/is_trivially_destructible.h @@ -11,12 +11,11 @@ #include "src/__support/CPP/type_traits/bool_constant.h" #include "src/__support/CPP/type_traits/is_destructible.h" #include "src/__support/macros/attributes.h" -#include "src/__support/macros/config.h" namespace LIBC_NAMESPACE::cpp { // is_trivially_destructible -#if LIBC_HAS_BUILTIN(__is_trivially_destructible) +#if __has_builtin(__is_trivially_destructible) template <typename T> struct is_trivially_destructible : public bool_constant<__is_trivially_destructible(T)> {}; @@ -25,7 +24,7 @@ template <typename T> struct is_trivially_destructible : public bool_constant<cpp::is_destructible_v<T> &&__has_trivial_destructor( T)> {}; -#endif // LIBC_HAS_BUILTIN(__is_trivially_destructible) +#endif // __has_builtin(__is_trivially_destructible) template <typename T> LIBC_INLINE_VAR constexpr bool is_trivially_destructible_v = is_trivially_destructible<T>::value; diff --git a/libc/src/__support/CPP/type_traits/remove_all_extents.h b/libc/src/__support/CPP/type_traits/remove_all_extents.h index bff6341d3e456010f40efd4db21ee355ecf94c5e..5941b82bbc1619841d3fd4a13044fae5a3c943cb 100644 --- a/libc/src/__support/CPP/type_traits/remove_all_extents.h +++ b/libc/src/__support/CPP/type_traits/remove_all_extents.h @@ -9,14 +9,13 @@ #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_REMOVE_ALL_EXTENTS_H #include "src/__support/CPP/type_traits/type_identity.h" -#include "src/__support/macros/config.h" #include <stddef.h> // size_t namespace LIBC_NAMESPACE::cpp { // remove_all_extents -#if LIBC_HAS_BUILTIN(__remove_all_extents) +#if __has_builtin(__remove_all_extents) template <typename T> using remove_all_extents_t = __remove_all_extents(T); template <typename T> struct remove_all_extents : cpp::type_identity<remove_all_extents_t<T>> {}; diff --git a/libc/src/__support/FPUtil/BasicOperations.h b/libc/src/__support/FPUtil/BasicOperations.h index a19d6d0bef08ff092cef38134727eb2c4f0f7bd9..6e4156497618e272090387d202673dbfe1bf0ecd 100644 --- a/libc/src/__support/FPUtil/BasicOperations.h +++ b/libc/src/__support/FPUtil/BasicOperations.h @@ -9,10 +9,14 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_BASICOPERATIONS_H #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_BASICOPERATIONS_H +#include "FEnvImpl.h" #include "FPBits.h" +#include "FEnvImpl.h" #include "src/__support/CPP/type_traits.h" +#include "src/__support/UInt128.h" #include "src/__support/common.h" +#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY namespace LIBC_NAMESPACE { namespace fputil { @@ -26,36 +30,136 @@ template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> LIBC_INLINE T fmin(T x, T y) { const FPBits<T> bitx(x), bity(y); - if (bitx.is_nan()) { + if (bitx.is_nan()) return y; - } else if (bity.is_nan()) { + if (bity.is_nan()) return x; - } else if (bitx.sign() != bity.sign()) { + if (bitx.sign() != bity.sign()) // To make sure that fmin(+0, -0) == -0 == fmin(-0, +0), whenever x and // y has different signs and both are not NaNs, we return the number // with negative sign. - return (bitx.is_neg()) ? x : y; - } else { - return (x < y ? x : y); - } + return bitx.is_neg() ? x : y; + return x < y ? x : y; } template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> LIBC_INLINE T fmax(T x, T y) { FPBits<T> bitx(x), bity(y); - if (bitx.is_nan()) { + if (bitx.is_nan()) return y; - } else if (bity.is_nan()) { + if (bity.is_nan()) return x; - } else if (bitx.sign() != bity.sign()) { + if (bitx.sign() != bity.sign()) // To make sure that fmax(+0, -0) == +0 == fmax(-0, +0), whenever x and // y has different signs and both are not NaNs, we return the number // with positive sign. + return bitx.is_neg() ? y : x; + return x > y ? x : y; +} + +template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> +LIBC_INLINE T fmaximum(T x, T y) { + FPBits<T> bitx(x), bity(y); + + if (bitx.is_nan()) + return x; + if (bity.is_nan()) + return y; + if (bitx.sign() != bity.sign()) + return (bitx.is_neg() ? y : x); + return x > y ? x : y; +} + +template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> +LIBC_INLINE T fminimum(T x, T y) { + const FPBits<T> bitx(x), bity(y); + + if (bitx.is_nan()) + return x; + if (bity.is_nan()) + return y; + if (bitx.sign() != bity.sign()) + return (bitx.is_neg()) ? x : y; + return x < y ? x : y; +} + +template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> +LIBC_INLINE T fmaximum_num(T x, T y) { + FPBits<T> bitx(x), bity(y); + if (bitx.is_signaling_nan() || bity.is_signaling_nan()) { + fputil::raise_except_if_required(FE_INVALID); + if (bitx.is_nan() && bity.is_nan()) + return FPBits<T>::quiet_nan().get_val(); + } + if (bitx.is_nan()) + return y; + if (bity.is_nan()) + return x; + if (bitx.sign() != bity.sign()) return (bitx.is_neg() ? y : x); - } else { - return (x > y ? x : y); + return x > y ? x : y; +} + +template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> +LIBC_INLINE T fminimum_num(T x, T y) { + FPBits<T> bitx(x), bity(y); + if (bitx.is_signaling_nan() || bity.is_signaling_nan()) { + fputil::raise_except_if_required(FE_INVALID); + if (bitx.is_nan() && bity.is_nan()) + return FPBits<T>::quiet_nan().get_val(); } + if (bitx.is_nan()) + return y; + if (bity.is_nan()) + return x; + if (bitx.sign() != bity.sign()) + return (bitx.is_neg() ? x : y); + return x < y ? x : y; +} + +template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> +LIBC_INLINE T fmaximum_mag(T x, T y) { + FPBits<T> bitx(x), bity(y); + + if (abs(x) > abs(y)) + return x; + if (abs(y) > abs(x)) + return y; + return fmaximum(x, y); +} + +template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> +LIBC_INLINE T fminimum_mag(T x, T y) { + FPBits<T> bitx(x), bity(y); + + if (abs(x) < abs(y)) + return x; + if (abs(y) < abs(x)) + return y; + return fminimum(x, y); +} + +template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> +LIBC_INLINE T fmaximum_mag_num(T x, T y) { + FPBits<T> bitx(x), bity(y); + + if (abs(x) > abs(y)) + return x; + if (abs(y) > abs(x)) + return y; + return fmaximum_num(x, y); +} + +template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> +LIBC_INLINE T fminimum_mag_num(T x, T y) { + FPBits<T> bitx(x), bity(y); + + if (abs(x) < abs(y)) + return x; + if (abs(y) < abs(x)) + return y; + return fminimum_num(x, y); } template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> @@ -73,6 +177,69 @@ LIBC_INLINE T fdim(T x, T y) { return (x > y ? x - y : 0); } +template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> +LIBC_INLINE int canonicalize(T &cx, const T &x) { + FPBits<T> sx(x); + if constexpr (get_fp_type<T>() == FPType::X86_Binary80) { + // All the pseudo and unnormal numbers are not canonical. + // More precisely : + // Exponent | Significand | Meaning + // | Bits 63-62 | Bits 61-0 | + // All Ones | 00 | Zero | Pseudo Infinity, Value = SNaN + // All Ones | 00 | Non-Zero | Pseudo NaN, Value = SNaN + // All Ones | 01 | Anything | Pseudo NaN, Value = SNaN + // | Bit 63 | Bits 62-0 | + // All zeroes | One | Anything | Pseudo Denormal, Value = + // | | | (−1)**s × m × 2**−16382 + // All Other | Zero | Anything | Unnormal, Value = SNaN + // Values | | | + bool bit63 = sx.get_implicit_bit(); + UInt128 mantissa = sx.get_explicit_mantissa(); + bool bit62 = static_cast<bool>((mantissa & (1ULL << 62)) >> 62); + int exponent = sx.get_biased_exponent(); + if (exponent == 0x7FFF) { + if (!bit63 && !bit62) { + if (mantissa == 0) { + cx = FPBits<T>::quiet_nan(sx.sign(), mantissa).get_val(); + raise_except_if_required(FE_INVALID); + return 1; + } + cx = FPBits<T>::quiet_nan(sx.sign(), mantissa).get_val(); + raise_except_if_required(FE_INVALID); + return 1; + } else if (!bit63 && bit62) { + cx = FPBits<T>::quiet_nan(sx.sign(), mantissa).get_val(); + raise_except_if_required(FE_INVALID); + return 1; + } else if (LIBC_UNLIKELY(sx.is_signaling_nan())) { + cx = FPBits<T>::quiet_nan(sx.sign(), sx.get_explicit_mantissa()) + .get_val(); + raise_except_if_required(FE_INVALID); + return 1; + } else + cx = x; + } else if (exponent == 0 && bit63) + cx = FPBits<T>::make_value(mantissa, 0).get_val(); + else if (exponent != 0 && !bit63) { + cx = FPBits<T>::quiet_nan(sx.sign(), mantissa).get_val(); + raise_except_if_required(FE_INVALID); + return 1; + } else if (LIBC_UNLIKELY(sx.is_signaling_nan())) { + cx = + FPBits<T>::quiet_nan(sx.sign(), sx.get_explicit_mantissa()).get_val(); + raise_except_if_required(FE_INVALID); + return 1; + } else + cx = x; + } else if (LIBC_UNLIKELY(sx.is_signaling_nan())) { + cx = FPBits<T>::quiet_nan(sx.sign(), sx.get_explicit_mantissa()).get_val(); + raise_except_if_required(FE_INVALID); + return 1; + } else + cx = x; + return 0; +} + } // namespace fputil } // namespace LIBC_NAMESPACE diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt index f1c6fba22856dd332896683777b24e610560f9e9..ff155a19758d20d1678ed8d598be08249798414e 100644 --- a/libc/src/__support/FPUtil/CMakeLists.txt +++ b/libc/src/__support/FPUtil/CMakeLists.txt @@ -6,7 +6,6 @@ add_header_library( libc.include.fenv libc.include.math libc.src.__support.macros.attributes - libc.src.__support.macros.config libc.src.errno.errno ) @@ -35,6 +34,7 @@ add_header_library( libc.src.__support.macros.attributes libc.src.__support.macros.properties.types libc.src.__support.math_extras + libc.src.__support.sign libc.src.__support.uint128 ) @@ -81,8 +81,11 @@ add_header_library( BasicOperations.h DEPENDS .fp_bits + .fenv_impl libc.src.__support.CPP.type_traits + libc.src.__support.uint128 libc.src.__support.common + libc.src.__support.macros.optimization ) add_header_library( diff --git a/libc/src/__support/FPUtil/FEnvImpl.h b/libc/src/__support/FPUtil/FEnvImpl.h index 6810659733de2c31b97e3061788ad1b634b76801..6086d5d3de2dcac9257955a83cf423c4d737aabf 100644 --- a/libc/src/__support/FPUtil/FEnvImpl.h +++ b/libc/src/__support/FPUtil/FEnvImpl.h @@ -9,13 +9,11 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_FENVIMPL_H #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_FENVIMPL_H +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/macros/attributes.h" // LIBC_INLINE -#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN #include "src/__support/macros/properties/architectures.h" #include "src/errno/libc_errno.h" - #include <fenv.h> -#include <math.h> #if defined(LIBC_TARGET_ARCH_IS_AARCH64) #if defined(__APPLE__) diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h index b06b3f7b73959a91fe89d88635c56d50947f77ea..155bff2f558102cca1c88ef17b5787f5ae4a1c71 100644 --- a/libc/src/__support/FPUtil/FPBits.h +++ b/libc/src/__support/FPUtil/FPBits.h @@ -17,6 +17,7 @@ #include "src/__support/macros/attributes.h" // LIBC_INLINE, LIBC_INLINE_VAR #include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_FLOAT128 #include "src/__support/math_extras.h" // mask_trailing_ones +#include "src/__support/sign.h" // Sign #include <stdint.h> @@ -32,32 +33,6 @@ enum class FPType { X86_Binary80, }; -// A type to interact with floating point type signs. -// This may be moved outside of 'fputil' if useful. -struct Sign { - LIBC_INLINE constexpr bool is_pos() const { return !is_negative; } - LIBC_INLINE constexpr bool is_neg() const { return is_negative; } - - LIBC_INLINE friend constexpr bool operator==(Sign a, Sign b) { - return a.is_negative == b.is_negative; - } - LIBC_INLINE friend constexpr bool operator!=(Sign a, Sign b) { - return !(a == b); - } - - static const Sign POS; - static const Sign NEG; - -private: - LIBC_INLINE constexpr explicit Sign(bool is_negative) - : is_negative(is_negative) {} - - bool is_negative; -}; - -LIBC_INLINE_VAR constexpr Sign Sign::NEG = Sign(true); -LIBC_INLINE_VAR constexpr Sign Sign::POS = Sign(false); - // The classes hierarchy is as follows: // // ┌───────────────────┐ diff --git a/libc/src/__support/FPUtil/ManipulationFunctions.h b/libc/src/__support/FPUtil/ManipulationFunctions.h index f148d984f5f35c0b73d0f87397817caa5149872f..2c90b4888c2e5d89fcdb3ca32feb4590578ac126 100644 --- a/libc/src/__support/FPUtil/ManipulationFunctions.h +++ b/libc/src/__support/FPUtil/ManipulationFunctions.h @@ -15,6 +15,7 @@ #include "dyadic_float.h" #include "rounding_mode.h" +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/CPP/bit.h" #include "src/__support/CPP/limits.h" // INT_MAX, INT_MIN #include "src/__support/CPP/type_traits.h" @@ -22,8 +23,6 @@ #include "src/__support/macros/attributes.h" #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY -#include <math.h> - namespace LIBC_NAMESPACE { namespace fputil { @@ -230,11 +229,36 @@ LIBC_INLINE T nextafter(T from, U to) { return from_bits.get_val(); } +template <bool IsDown, typename T, + cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> +LIBC_INLINE constexpr T nextupdown(T x) { + constexpr Sign sign = IsDown ? Sign::NEG : Sign::POS; + + FPBits<T> xbits(x); + if (xbits.is_nan() || xbits == FPBits<T>::max_normal(sign) || + xbits == FPBits<T>::inf(sign)) + return x; + + using StorageType = typename FPBits<T>::StorageType; + if (x != T(0)) { + if (xbits.sign() == sign) { + xbits = FPBits<T>(StorageType(xbits.uintval() + 1)); + } else { + xbits = FPBits<T>(StorageType(xbits.uintval() - 1)); + } + } else { + xbits = FPBits<T>::min_subnormal(sign); + } + + return xbits.get_val(); +} + } // namespace fputil } // namespace LIBC_NAMESPACE #ifdef LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80 #include "x86_64/NextAfterLongDouble.h" +#include "x86_64/NextUpDownLongDouble.h" #endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80 #endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_MANIPULATIONFUNCTIONS_H diff --git a/libc/src/__support/FPUtil/NearestIntegerOperations.h b/libc/src/__support/FPUtil/NearestIntegerOperations.h index 19ae75ea7889127eb9164793c25f2ab484ee2c4b..6b28e7ffb387b51a358b0c0e8124bac0eec2d544 100644 --- a/libc/src/__support/FPUtil/NearestIntegerOperations.h +++ b/libc/src/__support/FPUtil/NearestIntegerOperations.h @@ -13,11 +13,10 @@ #include "FPBits.h" #include "rounding_mode.h" +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/common.h" -#include <math.h> - namespace LIBC_NAMESPACE { namespace fputil { @@ -141,8 +140,9 @@ LIBC_INLINE T round(T x) { } } -template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0> -LIBC_INLINE T round_using_current_rounding_mode(T x) { +template <typename T> +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, T> +round_using_specific_rounding_mode(T x, int rnd) { using StorageType = typename FPBits<T>::StorageType; FPBits<T> bits(x); @@ -152,7 +152,6 @@ LIBC_INLINE T round_using_current_rounding_mode(T x) { bool is_neg = bits.is_neg(); int exponent = bits.get_exponent(); - int rounding_mode = quick_get_round(); // If the exponent is greater than the most negative mantissa // exponent, then x is already an integer. @@ -160,20 +159,23 @@ LIBC_INLINE T round_using_current_rounding_mode(T x) { return x; if (exponent <= -1) { - switch (rounding_mode) { - case FE_DOWNWARD: + switch (rnd) { + case FP_INT_DOWNWARD: return is_neg ? T(-1.0) : T(0.0); - case FE_UPWARD: + case FP_INT_UPWARD: return is_neg ? T(-0.0) : T(1.0); - case FE_TOWARDZERO: + case FP_INT_TOWARDZERO: return is_neg ? T(-0.0) : T(0.0); - case FE_TONEAREST: + case FP_INT_TONEARESTFROMZERO: + if (exponent < -1) + return is_neg ? T(-0.0) : T(0.0); // abs(x) < 0.5 + return is_neg ? T(-1.0) : T(1.0); // abs(x) >= 0.5 + case FP_INT_TONEAREST: + default: if (exponent <= -2 || bits.get_mantissa() == 0) return is_neg ? T(-0.0) : T(0.0); // abs(x) <= 0.5 else return is_neg ? T(-1.0) : T(1.0); // abs(x) > 0.5 - default: - __builtin_unreachable(); } } @@ -195,14 +197,19 @@ LIBC_INLINE T round_using_current_rounding_mode(T x) { StorageType trunc_is_odd = new_bits.get_mantissa() & (StorageType(1) << trim_size); - switch (rounding_mode) { - case FE_DOWNWARD: + switch (rnd) { + case FP_INT_DOWNWARD: return is_neg ? trunc_value - T(1.0) : trunc_value; - case FE_UPWARD: + case FP_INT_UPWARD: return is_neg ? trunc_value : trunc_value + T(1.0); - case FE_TOWARDZERO: + case FP_INT_TOWARDZERO: return trunc_value; - case FE_TONEAREST: + case FP_INT_TONEARESTFROMZERO: + if (trim_value >= half_value) + return is_neg ? trunc_value - T(1.0) : trunc_value + T(1.0); + return trunc_value; + case FP_INT_TONEAREST: + default: if (trim_value > half_value) { return is_neg ? trunc_value - T(1.0) : trunc_value + T(1.0); } else if (trim_value == half_value) { @@ -215,11 +222,109 @@ LIBC_INLINE T round_using_current_rounding_mode(T x) { } else { return trunc_value; } + } +} + +template <typename T> +LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> +round_using_current_rounding_mode(T x) { + int rounding_mode = quick_get_round(); + + switch (rounding_mode) { + case FE_DOWNWARD: + return round_using_specific_rounding_mode(x, FP_INT_DOWNWARD); + case FE_UPWARD: + return round_using_specific_rounding_mode(x, FP_INT_UPWARD); + case FE_TOWARDZERO: + return round_using_specific_rounding_mode(x, FP_INT_TOWARDZERO); + case FE_TONEAREST: + return round_using_specific_rounding_mode(x, FP_INT_TONEAREST); default: __builtin_unreachable(); } } +template <bool IsSigned, typename T> +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, T> +fromfp(T x, int rnd, unsigned int width) { + using StorageType = typename FPBits<T>::StorageType; + + constexpr StorageType EXPLICIT_BIT = + FPBits<T>::SIG_MASK - FPBits<T>::FRACTION_MASK; + + if (width == 0U) { + raise_except_if_required(FE_INVALID); + return FPBits<T>::quiet_nan().get_val(); + } + + FPBits<T> bits(x); + + if (bits.is_inf_or_nan()) { + raise_except_if_required(FE_INVALID); + return FPBits<T>::quiet_nan().get_val(); + } + + T rounded_value = round_using_specific_rounding_mode(x, rnd); + + if constexpr (IsSigned) { + // T can't hold a finite number >= 2.0 * 2^EXP_BIAS. + if (width - 1 > FPBits<T>::EXP_BIAS) + return rounded_value; + + StorageType range_exp = width - 1U + FPBits<T>::EXP_BIAS; + // rounded_value < -2^(width - 1) + T range_min = + FPBits<T>::create_value(Sign::NEG, range_exp, EXPLICIT_BIT).get_val(); + if (rounded_value < range_min) { + raise_except_if_required(FE_INVALID); + return FPBits<T>::quiet_nan().get_val(); + } + // rounded_value > 2^(width - 1) - 1 + T range_max = + FPBits<T>::create_value(Sign::POS, range_exp, EXPLICIT_BIT).get_val() - + T(1.0); + if (rounded_value > range_max) { + raise_except_if_required(FE_INVALID); + return FPBits<T>::quiet_nan().get_val(); + } + + return rounded_value; + } + + if (rounded_value < T(0.0)) { + raise_except_if_required(FE_INVALID); + return FPBits<T>::quiet_nan().get_val(); + } + + // T can't hold a finite number >= 2.0 * 2^EXP_BIAS. + if (width > FPBits<T>::EXP_BIAS) + return rounded_value; + + StorageType range_exp = width + FPBits<T>::EXP_BIAS; + // rounded_value > 2^width - 1 + T range_max = + FPBits<T>::create_value(Sign::POS, range_exp, EXPLICIT_BIT).get_val() - + T(1.0); + if (rounded_value > range_max) { + raise_except_if_required(FE_INVALID); + return FPBits<T>::quiet_nan().get_val(); + } + + return rounded_value; +} + +template <bool IsSigned, typename T> +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<T>, T> +fromfpx(T x, int rnd, unsigned int width) { + T rounded_value = fromfp<IsSigned>(x, rnd, width); + FPBits<T> bits(rounded_value); + + if (!bits.is_nan() && rounded_value != x) + raise_except_if_required(FE_INEXACT); + + return rounded_value; +} + namespace internal { template <typename F, typename I, diff --git a/libc/src/__support/FPUtil/fpbits_str.h b/libc/src/__support/FPUtil/fpbits_str.h index 212265bb9ad4a89127c14fa0606408e22d4c5f7b..97689867da4de43f2ed3c42a16762c3854eaf053 100644 --- a/libc/src/__support/FPUtil/fpbits_str.h +++ b/libc/src/__support/FPUtil/fpbits_str.h @@ -35,7 +35,6 @@ using ZeroPaddedHexFmt = IntegerToString< // floating encoding. template <typename T> LIBC_INLINE cpp::string str(fputil::FPBits<T> x) { using StorageType = typename fputil::FPBits<T>::StorageType; - using Sign = fputil::Sign; if (x.is_nan()) return "(NaN)"; diff --git a/libc/src/__support/FPUtil/gpu/FMA.h b/libc/src/__support/FPUtil/gpu/FMA.h index 86bc86031496112362231b78a549ed9853573b71..ef1cd26a72dd7c64b6ac65365c669b0351b90054 100644 --- a/libc/src/__support/FPUtil/gpu/FMA.h +++ b/libc/src/__support/FPUtil/gpu/FMA.h @@ -10,12 +10,12 @@ #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_GPU_FMA_H #include "src/__support/CPP/type_traits.h" -#include "src/__support/macros/config.h" -// These intrinsics map to the FMA instrunctions in the target ISA for the GPU. +// These intrinsics map to the FMA instructions in the target ISA for the GPU. // The default rounding mode generated from these will be to the nearest even. -static_assert(LIBC_HAS_BUILTIN(__builtin_fma), "FMA builtins must be defined"); -static_assert(LIBC_HAS_BUILTIN(__builtin_fmaf), "FMA builtins must be defined"); +#if !__has_builtin(__builtin_fma) || !__has_builtin(__builtin_fmaf) +#error "FMA builtins must be defined"); +#endif namespace LIBC_NAMESPACE { namespace fputil { diff --git a/libc/src/__support/FPUtil/x86_64/NextUpDownLongDouble.h b/libc/src/__support/FPUtil/x86_64/NextUpDownLongDouble.h new file mode 100644 index 0000000000000000000000000000000000000000..1bc849500be04803b722ffbd30661a85c299e6fd --- /dev/null +++ b/libc/src/__support/FPUtil/x86_64/NextUpDownLongDouble.h @@ -0,0 +1,60 @@ +//===-- nextupdown implementation for x86 long double 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_X86_64_NEXTUPDOWNLONGDOUBLE_H +#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_X86_64_NEXTUPDOWNLONGDOUBLE_H + +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/macros/attributes.h" +#include "src/__support/macros/properties/architectures.h" + +#if !defined(LIBC_TARGET_ARCH_IS_X86) +#error "Invalid include" +#endif + +namespace LIBC_NAMESPACE::fputil { + +template <bool IsDown> +LIBC_INLINE constexpr long double nextupdown(long double x) { + constexpr Sign sign = IsDown ? Sign::NEG : Sign::POS; + + using FPBits_t = FPBits<long double>; + FPBits_t xbits(x); + if (xbits.is_nan() || xbits == FPBits_t::max_normal(sign) || + xbits == FPBits_t::inf(sign)) + return x; + + if (x == 0.0l) + return FPBits_t::min_subnormal(sign).get_val(); + + using StorageType = typename FPBits_t::StorageType; + + if (xbits.sign() == sign) { + if (xbits.get_mantissa() == FPBits_t::FRACTION_MASK) { + xbits.set_mantissa(0); + xbits.set_biased_exponent(xbits.get_biased_exponent() + 1); + } else { + xbits = FPBits_t(StorageType(xbits.uintval() + 1)); + } + + return xbits.get_val(); + } + + if (xbits.get_mantissa() == 0) { + xbits.set_mantissa(FPBits_t::FRACTION_MASK); + xbits.set_biased_exponent(xbits.get_biased_exponent() - 1); + } else { + xbits = FPBits_t(StorageType(xbits.uintval() - 1)); + } + + return xbits.get_val(); +} + +} // namespace LIBC_NAMESPACE::fputil + +#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_X86_64_NEXTUPDOWNLONGDOUBLE_H diff --git a/libc/src/__support/File/file.h b/libc/src/__support/File/file.h index 2ea3843749ffe431e619122ec88eaeea69de089c..eafd3ab7d9107ba5f7fd8799d2edd68c09f07633 100644 --- a/libc/src/__support/File/file.h +++ b/libc/src/__support/File/file.h @@ -76,7 +76,7 @@ public: private: enum class FileOp : uint8_t { NONE, READ, WRITE, SEEK }; - // Platfrom specific functions which create new file objects should initialize + // Platform specific functions which create new file objects should initialize // these fields suitably via the constructor. Typically, they should be simple // syscall wrappers for the corresponding functionality. WriteFunc *platform_write; @@ -299,7 +299,7 @@ private: } }; -// The implementaiton of this function is provided by the platfrom_file +// The implementaiton of this function is provided by the platform_file // library. ErrorOr<File *> openfile(const char *path, const char *mode); diff --git a/libc/src/__support/GPU/utils.h b/libc/src/__support/GPU/utils.h index 93022e8de811f763c247417d935cd684cf3bf011..cb04a3562eb1c483105601ed1b253460473b07af 100644 --- a/libc/src/__support/GPU/utils.h +++ b/libc/src/__support/GPU/utils.h @@ -23,7 +23,7 @@ namespace LIBC_NAMESPACE { namespace gpu { /// Get the first active thread inside the lane. LIBC_INLINE uint64_t get_first_lane_id(uint64_t lane_mask) { - return __builtin_ffsl(lane_mask) - 1; + return __builtin_ffsll(lane_mask) - 1; } /// Conditional that is only true for a single thread in a lane. diff --git a/libc/src/__support/OSUtil/CMakeLists.txt b/libc/src/__support/OSUtil/CMakeLists.txt index ca3b3bf1263e0a55c6f555ff0d0b2b8e9a6c155b..94d1042ccbb4a0460d1b5e39f3ad84c17e33bce2 100644 --- a/libc/src/__support/OSUtil/CMakeLists.txt +++ b/libc/src/__support/OSUtil/CMakeLists.txt @@ -8,23 +8,10 @@ if(NOT TARGET ${target_os_util}) return() endif() -# The OSUtil is an object library in GPU mode. -if(NOT LIBC_TARGET_OS_IS_GPU) - add_header_library( - osutil - HDRS - io.h - quick_exit.h - syscall.h - DEPENDS - ${target_os_util} - ) -else() - add_object_library( - osutil - ALIAS - ${target_os_util} - DEPENDS - ${target_os_util} - ) -endif() +add_object_library( + osutil + ALIAS + ${target_os_util} + DEPENDS + ${target_os_util} +) diff --git a/libc/src/__support/OSUtil/baremetal/CMakeLists.txt b/libc/src/__support/OSUtil/baremetal/CMakeLists.txt index 280ff87cf1470db906f04ab4f4c2cf1f85ce773c..e78301d104c1f3833a05317ae87ea1893847b2c8 100644 --- a/libc/src/__support/OSUtil/baremetal/CMakeLists.txt +++ b/libc/src/__support/OSUtil/baremetal/CMakeLists.txt @@ -1,8 +1,10 @@ -add_header_library( +add_object_library( baremetal_util + SRCS + io.cpp + quick_exit.cpp HDRS io.h - quick_exit.h DEPENDS libc.src.__support.common libc.src.__support.CPP.string_view diff --git a/libc/src/__support/OSUtil/baremetal/io.cpp b/libc/src/__support/OSUtil/baremetal/io.cpp new file mode 100644 index 0000000000000000000000000000000000000000..347c7d405b0a9fddd0aea276b23c26e03cfc8a19 --- /dev/null +++ b/libc/src/__support/OSUtil/baremetal/io.cpp @@ -0,0 +1,22 @@ +//===---------- Baremetal implementation of IO 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 +// +//===----------------------------------------------------------------------===// + +#include "io.h" + +#include "src/__support/CPP/string_view.h" + +// This is intended to be provided by the vendor. +extern "C" void __llvm_libc_log_write(const char *msg, size_t len); + +namespace LIBC_NAMESPACE { + +void write_to_stderr(cpp::string_view msg) { + __llvm_libc_log_write(msg.data(), msg.size()); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/__support/OSUtil/baremetal/io.h b/libc/src/__support/OSUtil/baremetal/io.h index a50c11d4aea1230f0fbde5a9da66c175eb92fd6f..87534641b1fa4d87b667f14d3bb505f948eeaff1 100644 --- a/libc/src/__support/OSUtil/baremetal/io.h +++ b/libc/src/__support/OSUtil/baremetal/io.h @@ -13,12 +13,7 @@ namespace LIBC_NAMESPACE { -// This is intended to be provided by the vendor. -extern "C" void __llvm_libc_log_write(const char *msg, size_t len); - -void write_to_stderr(cpp::string_view msg) { - __llvm_libc_log_write(msg.data(), msg.size()); -} +void write_to_stderr(cpp::string_view msg); } // namespace LIBC_NAMESPACE diff --git a/libc/src/__support/OSUtil/baremetal/quick_exit.h b/libc/src/__support/OSUtil/baremetal/quick_exit.cpp similarity index 61% rename from libc/src/__support/OSUtil/baremetal/quick_exit.h rename to libc/src/__support/OSUtil/baremetal/quick_exit.cpp index 74f9142e21b81e2dabebc410443b48e994f7a500..5b6fcf42341ebbbd9a0c9de128c7e85198e72abe 100644 --- a/libc/src/__support/OSUtil/baremetal/quick_exit.h +++ b/libc/src/__support/OSUtil/baremetal/quick_exit.cpp @@ -6,16 +6,13 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_BAREMETAL_QUICK_EXIT_H -#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_BAREMETAL_QUICK_EXIT_H - -namespace LIBC_NAMESPACE { +#include "src/__support/OSUtil/quick_exit.h" // This is intended to be provided by the vendor. -extern "C" void __llvm_libc_quick_exit(int status); +extern "C" [[noreturn]] void __llvm_libc_quick_exit(int status); -void quick_exit(int status) { __llvm_libc_quick_exit(status); } +namespace LIBC_NAMESPACE { -} // namespace LIBC_NAMESPACE +[[noreturn]] void quick_exit(int status) { __llvm_libc_quick_exit(status); } -#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_BAREMETAL_QUICK_EXIT_H +} // namespace LIBC_NAMESPACE diff --git a/libc/src/__support/OSUtil/darwin/CMakeLists.txt b/libc/src/__support/OSUtil/darwin/CMakeLists.txt index a3e6b93c8e992550d12280924ccadf5f6aa696fb..4241bb37684f7c028c9cdeea3a92b870f2808679 100644 --- a/libc/src/__support/OSUtil/darwin/CMakeLists.txt +++ b/libc/src/__support/OSUtil/darwin/CMakeLists.txt @@ -8,7 +8,6 @@ add_header_library( darwin_util HDRS io.h - quick_exit.h syscall.h DEPENDS .${LIBC_TARGET_ARCHITECTURE}.darwin_util diff --git a/libc/src/__support/OSUtil/darwin/quick_exit.h b/libc/src/__support/OSUtil/darwin/quick_exit.h deleted file mode 100644 index 71647f50def5e2988a2fbd42af4257bfb7956202..0000000000000000000000000000000000000000 --- a/libc/src/__support/OSUtil/darwin/quick_exit.h +++ /dev/null @@ -1,26 +0,0 @@ -//===--------- Darwin implementation of a quick exit 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_OSUTIL_DARWIN_QUICK_EXIT_H -#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_DARWIN_QUICK_EXIT_H - -#include "syscall.h" // For internal syscall function. - -#include "src/__support/common.h" - -namespace LIBC_NAMESPACE { - -LIBC_INLINE void quick_exit(int status) { - for (;;) { - LIBC_NAMESPACE::syscall_impl<long>(1 /* SYS_exit */, status); - } -} - -} // namespace LIBC_NAMESPACE - -#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_DARWIN_QUICK_EXIT_H diff --git a/libc/src/__support/OSUtil/gpu/CMakeLists.txt b/libc/src/__support/OSUtil/gpu/CMakeLists.txt index 8e892a7000c9b3bdf9bc4e6838fa19c73138b963..0c89f9223678b1b0819cc91082cee530470161d1 100644 --- a/libc/src/__support/OSUtil/gpu/CMakeLists.txt +++ b/libc/src/__support/OSUtil/gpu/CMakeLists.txt @@ -4,7 +4,6 @@ add_object_library( quick_exit.cpp io.cpp HDRS - quick_exit.h io.h DEPENDS libc.src.__support.common diff --git a/libc/src/__support/OSUtil/gpu/quick_exit.cpp b/libc/src/__support/OSUtil/gpu/quick_exit.cpp index 1a03be0ace6728e06388423ad06540f6300eb920..af4795905e78689e1133d77986c6e7cbb73e77d4 100644 --- a/libc/src/__support/OSUtil/gpu/quick_exit.cpp +++ b/libc/src/__support/OSUtil/gpu/quick_exit.cpp @@ -6,17 +6,14 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_GPU_QUICK_EXIT_H -#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_GPU_QUICK_EXIT_H - -#include "quick_exit.h" +#include "src/__support/OSUtil/quick_exit.h" #include "src/__support/RPC/rpc_client.h" #include "src/__support/macros/properties/architectures.h" namespace LIBC_NAMESPACE { -void quick_exit(int status) { +[[noreturn]] void quick_exit(int status) { // We want to first make sure the server is listening before we exit. rpc::Client::Port port = rpc::client.open<RPC_EXIT>(); port.send_and_recv([](rpc::Buffer *) {}, [](rpc::Buffer *) {}); @@ -29,5 +26,3 @@ void quick_exit(int status) { } } // namespace LIBC_NAMESPACE - -#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_GPU_QUICK_EXIT_H diff --git a/libc/src/__support/OSUtil/linux/CMakeLists.txt b/libc/src/__support/OSUtil/linux/CMakeLists.txt index c27f9be746489439dd3f0cfa0fc9e16d245c5632..239d115704927bd9825ecd7544f91d108d85fb0b 100644 --- a/libc/src/__support/OSUtil/linux/CMakeLists.txt +++ b/libc/src/__support/OSUtil/linux/CMakeLists.txt @@ -4,11 +4,12 @@ endif() add_subdirectory(${LIBC_TARGET_ARCHITECTURE}) -add_header_library( +add_object_library( linux_util + SRCS + quick_exit.cpp HDRS io.h - quick_exit.h syscall.h DEPENDS .${LIBC_TARGET_ARCHITECTURE}.linux_${LIBC_TARGET_ARCHITECTURE}_util diff --git a/libc/src/__support/OSUtil/linux/quick_exit.h b/libc/src/__support/OSUtil/linux/quick_exit.cpp similarity index 78% rename from libc/src/__support/OSUtil/linux/quick_exit.h rename to libc/src/__support/OSUtil/linux/quick_exit.cpp index 432395584d8467797ef9e600939555ed9c4bdec2..51b3231d389f26d229adaf8bf9e97832a1996894 100644 --- a/libc/src/__support/OSUtil/linux/quick_exit.h +++ b/libc/src/__support/OSUtil/linux/quick_exit.cpp @@ -6,13 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_QUICK_EXIT_H -#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_QUICK_EXIT_H - -#include "syscall.h" // For internal syscall function. - #include "src/__support/common.h" - +#include "syscall.h" // For internal syscall function. #include <sys/syscall.h> // For syscall numbers. namespace LIBC_NAMESPACE { @@ -22,7 +17,7 @@ namespace LIBC_NAMESPACE { #ifdef LIBC_TARGET_ARCH_IS_X86 __attribute__((no_stack_protector)) #endif -LIBC_INLINE void +__attribute__((noreturn)) void quick_exit(int status) { for (;;) { LIBC_NAMESPACE::syscall_impl<long>(SYS_exit_group, status); @@ -31,5 +26,3 @@ quick_exit(int status) { } } // namespace LIBC_NAMESPACE - -#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_LINUX_QUICK_EXIT_H diff --git a/libc/src/__support/OSUtil/quick_exit.h b/libc/src/__support/OSUtil/quick_exit.h index 6c59c1afcda2548424bfd297a62e78adf8b7f087..e445917059c3e1ed9712ae606225050192f6cd22 100644 --- a/libc/src/__support/OSUtil/quick_exit.h +++ b/libc/src/__support/OSUtil/quick_exit.h @@ -9,17 +9,10 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_QUICK_EXIT_H #define LLVM_LIBC_SRC___SUPPORT_OSUTIL_QUICK_EXIT_H -#include "src/__support/macros/properties/architectures.h" +namespace LIBC_NAMESPACE { -#if defined(LIBC_TARGET_ARCH_IS_GPU) -#include "gpu/quick_exit.h" -#elif defined(__APPLE__) -#include "darwin/quick_exit.h" -#elif defined(__linux__) -#include "linux/quick_exit.h" -#elif defined(__ELF__) -// TODO: Ideally we would have LIBC_TARGET_OS_IS_BAREMETAL. -#include "baremetal/quick_exit.h" -#endif +[[noreturn]] void quick_exit(int status); + +} #endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_QUICK_EXIT_H diff --git a/libc/src/__support/UInt.h b/libc/src/__support/UInt.h index d92d61ed094ebe1a8eeca3a78b87df8211236d96..282efdba1c5f2b60595be2f8fe2b6ae75d57652c 100644 --- a/libc/src/__support/UInt.h +++ b/libc/src/__support/UInt.h @@ -993,6 +993,68 @@ struct is_big_int<BigInt<Bits, Signed, T>> : cpp::true_type {}; template <class T> LIBC_INLINE_VAR constexpr bool is_big_int_v = is_big_int<T>::value; +// extensions of type traits to include BigInt + +// is_integral_or_big_int +template <typename T> +struct is_integral_or_big_int + : cpp::bool_constant<(cpp::is_integral_v<T> || is_big_int_v<T>)> {}; + +template <typename T> +LIBC_INLINE_VAR constexpr bool is_integral_or_big_int_v = + is_integral_or_big_int<T>::value; + +// make_big_int_unsigned +template <typename T> struct make_big_int_unsigned; + +template <size_t Bits, bool Signed, typename T> +struct make_big_int_unsigned<BigInt<Bits, Signed, T>> + : cpp::type_identity<BigInt<Bits, false, T>> {}; + +template <typename T> +using make_big_int_unsigned_t = typename make_big_int_unsigned<T>::type; + +// make_big_int_signed +template <typename T> struct make_big_int_signed; + +template <size_t Bits, bool Signed, typename T> +struct make_big_int_signed<BigInt<Bits, Signed, T>> + : cpp::type_identity<BigInt<Bits, true, T>> {}; + +template <typename T> +using make_big_int_signed_t = typename make_big_int_signed<T>::type; + +// make_integral_or_big_int_unsigned +template <typename T, class = void> struct make_integral_or_big_int_unsigned; + +template <typename T> +struct make_integral_or_big_int_unsigned< + T, cpp::enable_if_t<cpp::is_integral_v<T>>> : cpp::make_unsigned<T> {}; + +template <typename T> +struct make_integral_or_big_int_unsigned<T, cpp::enable_if_t<is_big_int_v<T>>> + : make_big_int_unsigned<T> {}; + +template <typename T> +using make_integral_or_big_int_unsigned_t = + typename make_integral_or_big_int_unsigned<T>::type; + +// make_integral_or_big_int_signed +template <typename T, class = void> struct make_integral_or_big_int_signed; + +template <typename T> +struct make_integral_or_big_int_signed<T, + cpp::enable_if_t<cpp::is_integral_v<T>>> + : cpp::make_signed<T> {}; + +template <typename T> +struct make_integral_or_big_int_signed<T, cpp::enable_if_t<is_big_int_v<T>>> + : make_big_int_signed<T> {}; + +template <typename T> +using make_integral_or_big_int_signed_t = + typename make_integral_or_big_int_signed<T>::type; + namespace cpp { // Specialization of cpp::bit_cast ('bit.h') from T to BigInt. @@ -1020,6 +1082,17 @@ bit_cast(const UInt<Bits> &from) { return cpp::bit_cast<To>(from.val); } +// Specialization of cpp::popcount ('bit.h') for BigInt. +template <typename T> +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int> +popcount(T value) { + int bits = 0; + for (auto word : value.val) + if (word) + bits += popcount(word); + return bits; +} + // Specialization of cpp::has_single_bit ('bit.h') for BigInt. template <typename T> [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, bool> @@ -1156,6 +1229,49 @@ LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, T> mask_leading_ones() { return out; } +// Specialization of count_zeros ('math_extras.h') for BigInt. +template <typename T> +[[nodiscard]] +LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int> +count_zeros(T value) { + return cpp::popcount(~value); +} + +// Specialization of first_leading_zero ('math_extras.h') for BigInt. +template <typename T> +[[nodiscard]] +LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int> +first_leading_zero(T value) { + return value == cpp::numeric_limits<T>::max() ? 0 + : cpp::countl_one(value) + 1; +} + +// Specialization of first_leading_one ('math_extras.h') for BigInt. +template <typename T> +[[nodiscard]] +LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int> +first_leading_one(T value) { + return first_leading_zero(~value); +} + +// Specialization of first_trailing_zero ('math_extras.h') for BigInt. +template <typename T> +[[nodiscard]] +LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int> +first_trailing_zero(T value) { + return value == cpp::numeric_limits<T>::max() ? 0 + : cpp::countr_zero(~value) + 1; +} + +// Specialization of first_trailing_one ('math_extras.h') for BigInt. +template <typename T> +[[nodiscard]] +LIBC_INLINE constexpr cpp::enable_if_t<is_big_int_v<T>, int> +first_trailing_one(T value) { + return value == cpp::numeric_limits<T>::max() ? 0 + : cpp::countr_zero(value) + 1; +} + } // namespace LIBC_NAMESPACE #endif // LLVM_LIBC_SRC___SUPPORT_UINT_H diff --git a/libc/src/__support/blockstore.h b/libc/src/__support/blockstore.h index dc5fdd1b92fc29f1f79f125b99b4e57d58e50182..ac0eb22692b40c8fa017ae9bf442af9962513fb1 100644 --- a/libc/src/__support/blockstore.h +++ b/libc/src/__support/blockstore.h @@ -16,7 +16,6 @@ #include <stdint.h> namespace LIBC_NAMESPACE { -namespace cpp { // The difference between BlockStore a traditional vector types is that, // when more capacity is desired, a new block is added instead of allocating @@ -203,7 +202,6 @@ void BlockStore<T, BLOCK_SIZE, REVERSE_ORDER>::destroy( template <typename T, size_t BLOCK_SIZE> using ReverseOrderBlockStore = BlockStore<T, BLOCK_SIZE, true>; -} // namespace cpp } // namespace LIBC_NAMESPACE #endif // LLVM_LIBC_SRC___SUPPORT_BLOCKSTORE_H diff --git a/libc/src/__support/char_vector.h b/libc/src/__support/char_vector.h index 955abdc1fa5ae083d7c3c210d176145a7dd47492..d39310e09dd71ed9a8c742131893cba1fbb19855 100644 --- a/libc/src/__support/char_vector.h +++ b/libc/src/__support/char_vector.h @@ -11,8 +11,8 @@ #include "src/__support/common.h" // LIBC_INLINE -#include <stddef.h> -#include <stdlib.h> // For allocation. +#include <stddef.h> // size_t +#include <stdlib.h> // malloc, realloc, free namespace LIBC_NAMESPACE { @@ -46,7 +46,7 @@ public: if (cur_str == local_buffer) { char *new_str; new_str = reinterpret_cast<char *>(malloc(cur_buff_size)); - if (new_str == NULL) { + if (new_str == nullptr) { return false; } // TODO: replace with inline memcpy @@ -55,7 +55,7 @@ public: cur_str = new_str; } else { cur_str = reinterpret_cast<char *>(realloc(cur_str, cur_buff_size)); - if (cur_str == NULL) { + if (cur_str == nullptr) { return false; } } diff --git a/libc/src/__support/fixedvector.h b/libc/src/__support/fixedvector.h index fff905d8c6c4181919c55d3ee563f111bbf220c3..81747ee10067c4ebc28736fad0dba84b14f2c45e 100644 --- a/libc/src/__support/fixedvector.h +++ b/libc/src/__support/fixedvector.h @@ -11,6 +11,8 @@ #include "src/__support/CPP/array.h" +#include "src/__support/CPP/iterator.h" + namespace LIBC_NAMESPACE { // A fixed size data store backed by an underlying cpp::array data structure. It @@ -55,6 +57,12 @@ public: // matches the `destroy` API of those other data structures so that users // can easily swap one data structure for the other. static void destroy(FixedVector<T, CAPACITY> *store) { store->reset(); } + + using reverse_iterator = typename cpp::array<T, CAPACITY>::reverse_iterator; + LIBC_INLINE constexpr reverse_iterator rbegin() { + return reverse_iterator{&store[item_count]}; + } + LIBC_INLINE constexpr reverse_iterator rend() { return store.rend(); } }; } // namespace LIBC_NAMESPACE diff --git a/libc/src/__support/integer_to_string.h b/libc/src/__support/integer_to_string.h index ac0bdd688aeab222cd3cdfefc48c524547f64e9e..f72d00d1a7456d1cfc0d54b48c45f78dfa4f2b6b 100644 --- a/libc/src/__support/integer_to_string.h +++ b/libc/src/__support/integer_to_string.h @@ -67,7 +67,7 @@ #include "src/__support/CPP/span.h" #include "src/__support/CPP/string_view.h" #include "src/__support/CPP/type_traits.h" -#include "src/__support/UInt.h" // is_big_int +#include "src/__support/UInt.h" // make_integral_or_big_int_unsigned_t #include "src/__support/common.h" namespace LIBC_NAMESPACE { @@ -150,18 +150,6 @@ public: using StringBufferWriter = StringBufferWriterImpl<true>; using BackwardStringBufferWriter = StringBufferWriterImpl<false>; -template <typename T, class = void> struct IntegerWriterUnsigned {}; - -template <typename T> -struct IntegerWriterUnsigned<T, cpp::enable_if_t<cpp::is_integral_v<T>>> { - using type = cpp::make_unsigned_t<T>; -}; - -template <typename T> -struct IntegerWriterUnsigned<T, cpp::enable_if_t<is_big_int_v<T>>> { - using type = typename T::unsigned_type; -}; - } // namespace details namespace radix { @@ -222,7 +210,7 @@ template <typename T, typename Fmt = radix::Dec> class IntegerToString { // An internal stateless structure that handles the number formatting logic. struct IntegerWriter { static_assert(cpp::is_integral_v<T> || is_big_int_v<T>); - using UNSIGNED_T = typename details::IntegerWriterUnsigned<T>::type; + using UNSIGNED_T = make_integral_or_big_int_unsigned_t<T>; LIBC_INLINE static char digit_char(uint8_t digit) { if (digit < 10) diff --git a/libc/src/__support/macros/config.h b/libc/src/__support/macros/config.h index fcc8f551a783fe00b07fad25dfc3735f40a8cf78..3f200f0d62ba2663f5a8c6d4d269cf9e1435de4a 100644 --- a/libc/src/__support/macros/config.h +++ b/libc/src/__support/macros/config.h @@ -13,24 +13,6 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H #define LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H -// LIBC_HAS_BUILTIN() -// -// Checks whether the compiler supports a Clang Feature Checking Macro, and if -// so, checks whether it supports the provided builtin function "x" where x -// is one of the functions noted in -// https://clang.llvm.org/docs/LanguageExtensions.html -// -// Note: Use this macro to avoid an extra level of #ifdef __has_builtin check. -// http://releases.llvm.org/3.3/tools/clang/docs/LanguageExtensions.html - -// Compiler builtin-detection. -// clang.llvm.org/docs/LanguageExtensions.html#has-builtin -#ifdef __has_builtin -#define LIBC_HAS_BUILTIN(x) __has_builtin(x) -#else -#define LIBC_HAS_BUILTIN(x) 0 -#endif - // Compiler feature-detection. // clang.llvm.org/docs/LanguageExtensions.html#has-feature-and-has-extension #ifdef __has_feature @@ -39,12 +21,4 @@ #define LIBC_HAS_FEATURE(f) 0 #endif -// Compiler attribute-detection. -// https://clang.llvm.org/docs/LanguageExtensions.html#has-attribute -#ifdef __has_attribute -#define LIBC_HAS_ATTRIBUTE(f) __has_attribute(f) -#else -#define LIBC_HAS_ATTRIBUTE(f) 0 -#endif - #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_CONFIG_H diff --git a/libc/src/__support/macros/optimization.h b/libc/src/__support/macros/optimization.h index ae97efcaa41706df69e23f1be2246ec91f140904..59886ca44be12afee234376522410460dec2b08d 100644 --- a/libc/src/__support/macros/optimization.h +++ b/libc/src/__support/macros/optimization.h @@ -11,7 +11,6 @@ #define LLVM_LIBC_SRC___SUPPORT_MACROS_OPTIMIZATION_H #include "src/__support/macros/attributes.h" // LIBC_INLINE -#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN #include "src/__support/macros/properties/compiler.h" // LIBC_COMPILER_IS_CLANG // We use a template to implement likely/unlikely to make sure that we don't diff --git a/libc/src/__support/macros/sanitizer.h b/libc/src/__support/macros/sanitizer.h index fc66c2005c42de7216fa8f5a4f3f10d0bca5da06..bd9b62b7121a1468bce09a0060352e8187449e91 100644 --- a/libc/src/__support/macros/sanitizer.h +++ b/libc/src/__support/macros/sanitizer.h @@ -47,8 +47,7 @@ // Functions to unpoison memory //----------------------------------------------------------------------------- -#if defined(LIBC_HAVE_MEMORY_SANITIZER) && \ - LIBC_HAS_BUILTIN(__builtin_constant_p) +#if defined(LIBC_HAVE_MEMORY_SANITIZER) && __has_builtin(__builtin_constant_p) // Only perform MSAN unpoison in non-constexpr context. #include <sanitizer/msan_interface.h> #define MSAN_UNPOISON(addr, size) \ diff --git a/libc/src/__support/math_extras.h b/libc/src/__support/math_extras.h index 28ee1be8b99997b2b5dab712aa158669e8225569..70a8800b285d02064eac4c4ba1a881d298bffc96 100644 --- a/libc/src/__support/math_extras.h +++ b/libc/src/__support/math_extras.h @@ -14,7 +14,6 @@ #include "src/__support/CPP/limits.h" // CHAR_BIT, numeric_limits #include "src/__support/CPP/type_traits.h" // is_unsigned_v #include "src/__support/macros/attributes.h" // LIBC_INLINE -#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN namespace LIBC_NAMESPACE { @@ -61,7 +60,7 @@ add_with_carry(T a, T b, T carry_in) { return add_with_carry_const<T>(a, b, carry_in); } -#if LIBC_HAS_BUILTIN(__builtin_addc) +#if __has_builtin(__builtin_addc) // https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins template <> @@ -129,7 +128,7 @@ add_with_carry<unsigned long long>(unsigned long long a, unsigned long long b, } } -#endif // LIBC_HAS_BUILTIN(__builtin_addc) +#endif // __has_builtin(__builtin_addc) // Subtract with borrow template <typename T> struct DiffBorrow { @@ -157,7 +156,7 @@ sub_with_borrow(T a, T b, T borrow_in) { return sub_with_borrow_const<T>(a, b, borrow_in); } -#if LIBC_HAS_BUILTIN(__builtin_subc) +#if __has_builtin(__builtin_subc) // https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins template <> @@ -225,7 +224,7 @@ sub_with_borrow<unsigned long long>(unsigned long long a, unsigned long long b, } } -#endif // LIBC_HAS_BUILTIN(__builtin_subc) +#endif // __has_builtin(__builtin_subc) template <typename T> [[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, int> diff --git a/libc/src/__support/memory_size.h b/libc/src/__support/memory_size.h index 7bd16a1695be9a938e99f6399b8283d96edce27b..491123bbabf308236cea04865edc0cd4a4134dd8 100644 --- a/libc/src/__support/memory_size.h +++ b/libc/src/__support/memory_size.h @@ -19,7 +19,7 @@ namespace LIBC_NAMESPACE { namespace internal { template <class T> LIBC_INLINE bool mul_overflow(T a, T b, T *res) { -#if LIBC_HAS_BUILTIN(__builtin_mul_overflow) +#if __has_builtin(__builtin_mul_overflow) return __builtin_mul_overflow(a, b, res); #else T max = cpp::numeric_limits<T>::max(); diff --git a/libc/src/__support/sign.h b/libc/src/__support/sign.h new file mode 100644 index 0000000000000000000000000000000000000000..28cfae4bab1ded8e23e9317989f42412fb825f79 --- /dev/null +++ b/libc/src/__support/sign.h @@ -0,0 +1,40 @@ +//===-- A simple 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_SRC___SUPPORT_SIGN_H +#define LLVM_LIBC_SRC___SUPPORT_SIGN_H + +#include "src/__support/macros/attributes.h" // LIBC_INLINE, LIBC_INLINE_VAR + +// A type to interact with signed arithmetic types. +struct Sign { + LIBC_INLINE constexpr bool is_pos() const { return !is_negative; } + LIBC_INLINE constexpr bool is_neg() const { return is_negative; } + + LIBC_INLINE friend constexpr bool operator==(Sign a, Sign b) { + return a.is_negative == b.is_negative; + } + + LIBC_INLINE friend constexpr bool operator!=(Sign a, Sign b) { + return !(a == b); + } + + static const Sign POS; + static const Sign NEG; + +private: + LIBC_INLINE constexpr explicit Sign(bool is_negative) + : is_negative(is_negative) {} + + bool is_negative; +}; + +LIBC_INLINE_VAR constexpr Sign Sign::NEG = Sign(true); +LIBC_INLINE_VAR constexpr Sign Sign::POS = Sign(false); + +#endif // LLVM_LIBC_SRC___SUPPORT_SIGN_H diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h index 073e1dc672172376771b0badb5b1ee6f93355c89..f622b7edaa8a7283af0eb9ff0cd84528d1257c22 100644 --- a/libc/src/__support/str_to_float.h +++ b/libc/src/__support/str_to_float.h @@ -513,7 +513,6 @@ clinger_fast_path(ExpandedFloat<T> init_num, RoundDirection round = RoundDirection::Nearest) { using FPBits = typename fputil::FPBits<T>; using StorageType = typename FPBits::StorageType; - using Sign = fputil::Sign; StorageType mantissa = init_num.mantissa; int32_t exp10 = init_num.exponent; @@ -1056,17 +1055,17 @@ hexadecimal_string_to_float(const char *__restrict src, return output; } -LIBC_INLINE uint64_t +template <class T> +LIBC_INLINE typename fputil::FPBits<T>::StorageType nan_mantissa_from_ncharseq(const cpp::string_view ncharseq) { - uint64_t nan_mantissa = 0; + using FPBits = typename fputil::FPBits<T>; + using StorageType = typename FPBits::StorageType; + + StorageType nan_mantissa = 0; if (ncharseq.data() != nullptr && isdigit(ncharseq[0])) { - // This is to prevent errors when StorageType is larger than 64 - // bits, since strtointeger only supports up to 64 bits. This is - // actually more than is required by the specification, which says - // for the input type "NAN(n-char-sequence)" that "the meaning of - // the n-char sequence is implementation-defined." - auto strtoint_result = strtointeger<uint64_t>(ncharseq.data(), 0); + StrToNumResult<StorageType> strtoint_result = + strtointeger<StorageType>(ncharseq.data(), 0); if (!strtoint_result.has_error()) nan_mantissa = strtoint_result.value; @@ -1085,7 +1084,6 @@ template <class T> LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) { using FPBits = typename fputil::FPBits<T>; using StorageType = typename FPBits::StorageType; - using Sign = fputil::Sign; FPBits result = FPBits(); bool seen_digit = false; @@ -1172,9 +1170,8 @@ LIBC_INLINE StrToNumResult<T> strtofloatingpoint(const char *__restrict src) { ++index; if (src[index] == ')') { ++index; - auto nan_mantissa_result = nan_mantissa_from_ncharseq( + nan_mantissa = nan_mantissa_from_ncharseq<T>( cpp::string_view(src + (left_paren + 1), index - left_paren - 2)); - nan_mantissa = static_cast<StorageType>(nan_mantissa_result); } else { index = left_paren; } @@ -1221,13 +1218,10 @@ template <class T> LIBC_INLINE StrToNumResult<T> strtonan(const char *arg) { while (isalnum(arg[index]) || arg[index] == '_') ++index; - if (arg[index] == '\0') { - auto nan_mantissa_result = - nan_mantissa_from_ncharseq(cpp::string_view(arg, index)); - nan_mantissa = static_cast<StorageType>(nan_mantissa_result); - } + if (arg[index] == '\0') + nan_mantissa = nan_mantissa_from_ncharseq<T>(cpp::string_view(arg, index)); - result = FPBits::quiet_nan(fputil::Sign::POS, nan_mantissa); + result = FPBits::quiet_nan(Sign::POS, nan_mantissa); return {result.get_val(), 0, error}; } diff --git a/libc/src/__support/str_to_integer.h b/libc/src/__support/str_to_integer.h index b87808993fee500965a731a5abe08cb6734fad5d..02c71d40a1c0ada2d7db6d58135fe4eda2ae4476 100644 --- a/libc/src/__support/str_to_integer.h +++ b/libc/src/__support/str_to_integer.h @@ -11,6 +11,7 @@ #include "src/__support/CPP/limits.h" #include "src/__support/CPP/type_traits.h" +#include "src/__support/UInt128.h" #include "src/__support/common.h" #include "src/__support/ctype_utils.h" #include "src/__support/str_to_num_result.h" @@ -75,8 +76,12 @@ template <class T> LIBC_INLINE StrToNumResult<T> strtointeger(const char *__restrict src, int base, const size_t src_len = cpp::numeric_limits<size_t>::max()) { - // TODO: Rewrite to support numbers longer than long long - unsigned long long result = 0; + using ResultType = typename cpp::conditional_t<(cpp::is_same_v<T, UInt128> || + cpp::is_same_v<T, Int128>), + UInt128, unsigned long long>; + + ResultType result = 0; + bool is_number = false; size_t src_cur = 0; int error_val = 0; @@ -101,15 +106,16 @@ strtointeger(const char *__restrict src, int base, if (base == 16 && is_hex_start(src + src_cur, src_len - src_cur)) src_cur = src_cur + 2; - constexpr bool IS_UNSIGNED = (cpp::numeric_limits<T>::min() == 0); + constexpr bool IS_UNSIGNED = cpp::is_unsigned_v<T>; const bool is_positive = (result_sign == '+'); - unsigned long long constexpr NEGATIVE_MAX = - !IS_UNSIGNED - ? static_cast<unsigned long long>(cpp::numeric_limits<T>::max()) + 1 - : cpp::numeric_limits<T>::max(); - unsigned long long const abs_max = + + ResultType constexpr NEGATIVE_MAX = + !IS_UNSIGNED ? static_cast<ResultType>(cpp::numeric_limits<T>::max()) + 1 + : cpp::numeric_limits<T>::max(); + ResultType const abs_max = (is_positive ? cpp::numeric_limits<T>::max() : NEGATIVE_MAX); - unsigned long long const abs_max_div_by_base = abs_max / base; + ResultType const abs_max_div_by_base = abs_max / base; + while (src_cur < src_len && isalnum(src[src_cur])) { int cur_digit = b36_char_to_int(src[src_cur]); if (cur_digit >= base) @@ -149,10 +155,12 @@ strtointeger(const char *__restrict src, int base, return {cpp::numeric_limits<T>::min(), str_len, error_val}; } - return {is_positive - ? static_cast<T>(result) - : static_cast<T>(-static_cast<cpp::make_unsigned_t<T>>(result)), - str_len, error_val}; + return { + is_positive + ? static_cast<T>(result) + : static_cast<T>( + -static_cast<make_integral_or_big_int_unsigned_t<T>>(result)), + str_len, error_val}; } } // namespace internal diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt index bba02aa78a2313cc25874a45066910b2c4f4edc0..b67ee3a8e0dfbdd1cde8557889ffa5e77e18a608 100644 --- a/libc/src/math/CMakeLists.txt +++ b/libc/src/math/CMakeLists.txt @@ -59,6 +59,11 @@ add_math_entrypoint_object(atan2f) add_math_entrypoint_object(atanh) add_math_entrypoint_object(atanhf) +add_math_entrypoint_object(canonicalize) +add_math_entrypoint_object(canonicalizef) +add_math_entrypoint_object(canonicalizef128) +add_math_entrypoint_object(canonicalizel) + add_math_entrypoint_object(ceil) add_math_entrypoint_object(ceilf) add_math_entrypoint_object(ceill) @@ -117,6 +122,46 @@ add_math_entrypoint_object(fminf) add_math_entrypoint_object(fminl) add_math_entrypoint_object(fminf128) +add_math_entrypoint_object(fmaximum) +add_math_entrypoint_object(fmaximumf) +add_math_entrypoint_object(fmaximuml) +add_math_entrypoint_object(fmaximumf128) + +add_math_entrypoint_object(fmaximum_num) +add_math_entrypoint_object(fmaximum_numf) +add_math_entrypoint_object(fmaximum_numl) +add_math_entrypoint_object(fmaximum_numf128) + +add_math_entrypoint_object(fmaximum_mag) +add_math_entrypoint_object(fmaximum_magf) +add_math_entrypoint_object(fmaximum_magl) +add_math_entrypoint_object(fmaximum_magf128) + +add_math_entrypoint_object(fmaximum_mag_num) +add_math_entrypoint_object(fmaximum_mag_numf) +add_math_entrypoint_object(fmaximum_mag_numl) +add_math_entrypoint_object(fmaximum_mag_numf128) + +add_math_entrypoint_object(fminimum) +add_math_entrypoint_object(fminimumf) +add_math_entrypoint_object(fminimuml) +add_math_entrypoint_object(fminimumf128) + +add_math_entrypoint_object(fminimum_num) +add_math_entrypoint_object(fminimum_numf) +add_math_entrypoint_object(fminimum_numl) +add_math_entrypoint_object(fminimum_numf128) + +add_math_entrypoint_object(fminimum_mag) +add_math_entrypoint_object(fminimum_magf) +add_math_entrypoint_object(fminimum_magl) +add_math_entrypoint_object(fminimum_magf128) + +add_math_entrypoint_object(fminimum_mag_num) +add_math_entrypoint_object(fminimum_mag_numf) +add_math_entrypoint_object(fminimum_mag_numl) +add_math_entrypoint_object(fminimum_mag_numf128) + add_math_entrypoint_object(fmod) add_math_entrypoint_object(fmodf) add_math_entrypoint_object(fmodl) @@ -127,6 +172,16 @@ add_math_entrypoint_object(frexpf) add_math_entrypoint_object(frexpl) add_math_entrypoint_object(frexpf128) +add_math_entrypoint_object(fromfp) +add_math_entrypoint_object(fromfpf) +add_math_entrypoint_object(fromfpl) +add_math_entrypoint_object(fromfpf128) + +add_math_entrypoint_object(fromfpx) +add_math_entrypoint_object(fromfpxf) +add_math_entrypoint_object(fromfpxl) +add_math_entrypoint_object(fromfpxf128) + add_math_entrypoint_object(hypot) add_math_entrypoint_object(hypotf) @@ -190,6 +245,7 @@ add_math_entrypoint_object(modff128) add_math_entrypoint_object(nan) add_math_entrypoint_object(nanf) add_math_entrypoint_object(nanl) +add_math_entrypoint_object(nanf128) add_math_entrypoint_object(nearbyint) add_math_entrypoint_object(nearbyintf) @@ -198,11 +254,22 @@ add_math_entrypoint_object(nearbyintl) add_math_entrypoint_object(nextafter) add_math_entrypoint_object(nextafterf) add_math_entrypoint_object(nextafterl) +add_math_entrypoint_object(nextafterf128) add_math_entrypoint_object(nexttoward) add_math_entrypoint_object(nexttowardf) add_math_entrypoint_object(nexttowardl) +add_math_entrypoint_object(nextdown) +add_math_entrypoint_object(nextdownf) +add_math_entrypoint_object(nextdownl) +add_math_entrypoint_object(nextdownf128) + +add_math_entrypoint_object(nextup) +add_math_entrypoint_object(nextupf) +add_math_entrypoint_object(nextupl) +add_math_entrypoint_object(nextupf128) + add_math_entrypoint_object(pow) add_math_entrypoint_object(powf) @@ -255,3 +322,13 @@ add_math_entrypoint_object(trunc) add_math_entrypoint_object(truncf) add_math_entrypoint_object(truncl) add_math_entrypoint_object(truncf128) + +add_math_entrypoint_object(ufromfp) +add_math_entrypoint_object(ufromfpf) +add_math_entrypoint_object(ufromfpl) +add_math_entrypoint_object(ufromfpf128) + +add_math_entrypoint_object(ufromfpx) +add_math_entrypoint_object(ufromfpxf) +add_math_entrypoint_object(ufromfpxl) +add_math_entrypoint_object(ufromfpxf128) diff --git a/libc/src/math/canonicalize.h b/libc/src/math/canonicalize.h new file mode 100644 index 0000000000000000000000000000000000000000..b7b5959fb667cf8b0ced9afd13b15a7498bf30b2 --- /dev/null +++ b/libc/src/math/canonicalize.h @@ -0,0 +1,18 @@ +//===-- Implementation header for canonicalize -------------------*- 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_MATH_CANONICALIZE_H +#define LLVM_LIBC_SRC_MATH_CANONICALIZE_H + +namespace LIBC_NAMESPACE { + +int canonicalize(double *cx, const double *x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_CANONICALIZE_H diff --git a/libc/src/math/canonicalizef.h b/libc/src/math/canonicalizef.h new file mode 100644 index 0000000000000000000000000000000000000000..556607f1334967b6d5c69a2a586803a455d4e952 --- /dev/null +++ b/libc/src/math/canonicalizef.h @@ -0,0 +1,18 @@ +//===-- Implementation header for canonicalizef ------------------*- 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_MATH_CANONICALIZEF_H +#define LLVM_LIBC_SRC_MATH_CANONICALIZEF_H + +namespace LIBC_NAMESPACE { + +int canonicalizef(float *cx, const float *x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_CANONICALIZEF_H diff --git a/libc/src/math/canonicalizef128.h b/libc/src/math/canonicalizef128.h new file mode 100644 index 0000000000000000000000000000000000000000..6db80094753767109254b6529ff3fa7dd07e723f --- /dev/null +++ b/libc/src/math/canonicalizef128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for canonicalizef128 ---------------*-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_MATH_CANONICALIZEF128_H +#define LLVM_LIBC_SRC_MATH_CANONICALIZEF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +int canonicalizef128(float128 *cx, const float128 *x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_CANONICALIZEF128_H diff --git a/libc/src/math/canonicalizel.h b/libc/src/math/canonicalizel.h new file mode 100644 index 0000000000000000000000000000000000000000..1cab29e8e8b1c9c25ac71c32f8bf229457d44d37 --- /dev/null +++ b/libc/src/math/canonicalizel.h @@ -0,0 +1,18 @@ +//===-- Implementation header for canonicalizel ------------------*- 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_MATH_CANONICALIZEL_H +#define LLVM_LIBC_SRC_MATH_CANONICALIZEL_H + +namespace LIBC_NAMESPACE { + +int canonicalizel(long double *cx, const long double *x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_CANONICALIZEL_H diff --git a/libc/src/math/docs/add_math_function.md b/libc/src/math/docs/add_math_function.md index f8bc8a3bdd8b1d3cc8567eabea86b7602928008e..d1bca222b4286b889bfca19372f4cc8a53348b8e 100644 --- a/libc/src/math/docs/add_math_function.md +++ b/libc/src/math/docs/add_math_function.md @@ -177,7 +177,7 @@ implementation (which is very often glibc). - Build and Run a specific unit test: ``` - $ ninja libc.test.src.math.<func>_test + $ ninja libc.test.src.math.<func>_test.__unit__ $ projects/libc/test/src/math/libc.test.src.math.<func>_test ``` diff --git a/libc/src/math/fmaximum.h b/libc/src/math/fmaximum.h new file mode 100644 index 0000000000000000000000000000000000000000..8eac02b17b79ab584b79f7db3ba6a8239a262624 --- /dev/null +++ b/libc/src/math/fmaximum.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fmaximum --------------------------*- 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_MATH_FMAXIMUM_H +#define LLVM_LIBC_SRC_MATH_FMAXIMUM_H + +namespace LIBC_NAMESPACE { + +double fmaximum(double x, double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMAXIMUM_H diff --git a/libc/src/math/fmaximum_mag.h b/libc/src/math/fmaximum_mag.h new file mode 100644 index 0000000000000000000000000000000000000000..31b7c0fcf7ee3e60dcfd8a810bbd9c7bf2396c85 --- /dev/null +++ b/libc/src/math/fmaximum_mag.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fmaximum_mag------------------------*- 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_MATH_FMAXIMUM_MAG_H +#define LLVM_LIBC_SRC_MATH_FMAXIMUM_MAG_H + +namespace LIBC_NAMESPACE { + +double fmaximum_mag(double x, double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMAXIMUM_MAG_H diff --git a/libc/src/__support/OSUtil/gpu/quick_exit.h b/libc/src/math/fmaximum_mag_num.h similarity index 58% rename from libc/src/__support/OSUtil/gpu/quick_exit.h rename to libc/src/math/fmaximum_mag_num.h index b51385defbc0dee2631f2df15828c50bc65b6f12..c4ff243846e037fbdc8ab5ba2efcfd3bdde751c2 100644 --- a/libc/src/__support/OSUtil/gpu/quick_exit.h +++ b/libc/src/math/fmaximum_mag_num.h @@ -1,4 +1,4 @@ -//===---------- GPU implementation of a quick exit function -----*- C++ -*-===// +//===-- Implementation header for fmaximum_mag_num---------------*- 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,13 +6,13 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_GPU_QUICK_EXIT_H -#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_GPU_QUICK_EXIT_H +#ifndef LLVM_LIBC_SRC_MATH_FMAXIMUM_MAG_NUM_H +#define LLVM_LIBC_SRC_MATH_FMAXIMUM_MAG_NUM_H namespace LIBC_NAMESPACE { -void quick_exit(int status); +double fmaximum_mag_num(double x, double y); } // namespace LIBC_NAMESPACE -#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_GPU_QUICK_EXIT_H +#endif // LLVM_LIBC_SRC_MATH_FMAXIMUM_MAG_NUM_H diff --git a/libc/src/math/fmaximum_mag_numf.h b/libc/src/math/fmaximum_mag_numf.h new file mode 100644 index 0000000000000000000000000000000000000000..702903ab8bcfe384a3b71e2d2c97e07e88865164 --- /dev/null +++ b/libc/src/math/fmaximum_mag_numf.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fmaximum_mag_numf ----------------------*- 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_MATH_FMAXIMUM_MAG_NUMF_H +#define LLVM_LIBC_SRC_MATH_FMAXIMUM_MAG_NUMF_H + +namespace LIBC_NAMESPACE { + +float fmaximum_mag_numf(float x, float y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMAXIMUM_MAG_NUMF_H diff --git a/libc/src/math/fmaximum_mag_numf128.h b/libc/src/math/fmaximum_mag_numf128.h new file mode 100644 index 0000000000000000000000000000000000000000..2afae7fc37c46a2f123a28372d77683b10783f53 --- /dev/null +++ b/libc/src/math/fmaximum_mag_numf128.h @@ -0,0 +1,21 @@ +//===-- Implementation header for fmaximum_mag_numf128 -------------------*- 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_MATH_FMAXIMUM_MAG_NUMF128_H +#define LLVM_LIBC_SRC_MATH_FMAXIMUM_MAG_NUMF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 fmaximum_mag_numf128(float128 x, float128 y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMAXIMUM_MAG_NUMF128_H diff --git a/libc/src/math/fmaximum_mag_numl.h b/libc/src/math/fmaximum_mag_numl.h new file mode 100644 index 0000000000000000000000000000000000000000..32f9ae9708a6554e27891b127027782eb354efa5 --- /dev/null +++ b/libc/src/math/fmaximum_mag_numl.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fmaximum_mag_numl ----------------------*- 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_MATH_FMAXIMUM_MAG_NUML_H +#define LLVM_LIBC_SRC_MATH_FMAXIMUM_MAG_NUML_H + +namespace LIBC_NAMESPACE { + +long double fmaximum_mag_numl(long double x, long double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMAXIMUM_MAG_NUML_H diff --git a/libc/src/math/fmaximum_magf.h b/libc/src/math/fmaximum_magf.h new file mode 100644 index 0000000000000000000000000000000000000000..1bfcc795f8f81ce10dec104027be4c2aa2a12c3b --- /dev/null +++ b/libc/src/math/fmaximum_magf.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fmaximum_magf -------------------------*- 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_MATH_FMAXIMUM_MAGF_H +#define LLVM_LIBC_SRC_MATH_FMAXIMUM_MAGF_H + +namespace LIBC_NAMESPACE { + +float fmaximum_magf(float x, float y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMAXIMUM_MAGF_H diff --git a/libc/src/math/fmaximum_magf128.h b/libc/src/math/fmaximum_magf128.h new file mode 100644 index 0000000000000000000000000000000000000000..23c466b74cce89e25df8cc5d4dd7845da816a9ec --- /dev/null +++ b/libc/src/math/fmaximum_magf128.h @@ -0,0 +1,21 @@ +//===-- Implementation header for fmaximum_magf128 ----------------------*- 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_MATH_FMAXIMUM_MAGF128_H +#define LLVM_LIBC_SRC_MATH_FMAXIMUM_MAGF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 fmaximum_magf128(float128 x, float128 y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMAXIMUM_MAGF128_H diff --git a/libc/src/math/fmaximum_magl.h b/libc/src/math/fmaximum_magl.h new file mode 100644 index 0000000000000000000000000000000000000000..23b283cb5dbc248f88ee0ed22eca57df18a73420 --- /dev/null +++ b/libc/src/math/fmaximum_magl.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fmaximum_magl -------------------------*- 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_MATH_FMAXIMUM_MAGL_H +#define LLVM_LIBC_SRC_MATH_FMAXIMUM_MAGL_H + +namespace LIBC_NAMESPACE { + +long double fmaximum_magl(long double x, long double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMAXIMUM_MAGL_H diff --git a/libc/src/math/fmaximum_num.h b/libc/src/math/fmaximum_num.h new file mode 100644 index 0000000000000000000000000000000000000000..ce3ce12ca64b4c9ea27b028f6ff0c982cf310351 --- /dev/null +++ b/libc/src/math/fmaximum_num.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fmaximum_num--------------------------*- 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_MATH_FMAXIMUM_NUM_H +#define LLVM_LIBC_SRC_MATH_FMAXIMUM_NUM_H + +namespace LIBC_NAMESPACE { + +double fmaximum_num(double x, double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMAXIMUM_NUM_H diff --git a/libc/src/math/fmaximum_numf.h b/libc/src/math/fmaximum_numf.h new file mode 100644 index 0000000000000000000000000000000000000000..b3243ed16be9f09efe5319c87590f5fb0fefed56 --- /dev/null +++ b/libc/src/math/fmaximum_numf.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fmaximum_numf -------------------------*- 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_MATH_FMAXIMUM_NUMF_H +#define LLVM_LIBC_SRC_MATH_FMAXIMUM_NUMF_H + +namespace LIBC_NAMESPACE { + +float fmaximum_numf(float x, float y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMAXIMUM_NUMF_H diff --git a/libc/src/math/fmaximum_numf128.h b/libc/src/math/fmaximum_numf128.h new file mode 100644 index 0000000000000000000000000000000000000000..d55183ce88cc617fc9c23647b53d98d760cd2de8 --- /dev/null +++ b/libc/src/math/fmaximum_numf128.h @@ -0,0 +1,21 @@ +//===-- Implementation header for fmaximum_numf128 ----------------------*- 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_MATH_FMAXIMUM_NUMF128_H +#define LLVM_LIBC_SRC_MATH_FMAXIMUM_NUMF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 fmaximum_numf128(float128 x, float128 y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMAXIMUM_NUMF128_H diff --git a/libc/src/math/fmaximum_numl.h b/libc/src/math/fmaximum_numl.h new file mode 100644 index 0000000000000000000000000000000000000000..f668cbdf73151be3119d9e1059867faba6dc3c8d --- /dev/null +++ b/libc/src/math/fmaximum_numl.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fmaximum_numl -------------------------*- 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_MATH_FMAXIMUM_NUML_H +#define LLVM_LIBC_SRC_MATH_FMAXIMUM_NUML_H + +namespace LIBC_NAMESPACE { + +long double fmaximum_numl(long double x, long double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMAXIMUM_NUML_H diff --git a/libc/src/math/fmaximumf.h b/libc/src/math/fmaximumf.h new file mode 100644 index 0000000000000000000000000000000000000000..4eee696ce15217791add76b5a9befcc6f176639c --- /dev/null +++ b/libc/src/math/fmaximumf.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fmaximumf -------------------------*- 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_MATH_FMAXIMUMF_H +#define LLVM_LIBC_SRC_MATH_FMAXIMUMF_H + +namespace LIBC_NAMESPACE { + +float fmaximumf(float x, float y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMAXIMUMF_H diff --git a/libc/src/math/fmaximumf128.h b/libc/src/math/fmaximumf128.h new file mode 100644 index 0000000000000000000000000000000000000000..4a214ef096e10e9689cb128e5413e9aae9d40405 --- /dev/null +++ b/libc/src/math/fmaximumf128.h @@ -0,0 +1,21 @@ +//===-- Implementation header for fmaximumf128 ----------------------*- 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_MATH_FMAXIMUMF128_H +#define LLVM_LIBC_SRC_MATH_FMAXIMUMF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 fmaximumf128(float128 x, float128 y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMAXIMUMF128_H diff --git a/libc/src/math/fmaximuml.h b/libc/src/math/fmaximuml.h new file mode 100644 index 0000000000000000000000000000000000000000..ba8a8b12110c701ac0a9333d44b7e81b2b18c43a --- /dev/null +++ b/libc/src/math/fmaximuml.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fmaximuml -------------------------*- 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_MATH_FMAXIMUML_H +#define LLVM_LIBC_SRC_MATH_FMAXIMUML_H + +namespace LIBC_NAMESPACE { + +long double fmaximuml(long double x, long double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMAXIMUML_H diff --git a/libc/src/math/fminimum.h b/libc/src/math/fminimum.h new file mode 100644 index 0000000000000000000000000000000000000000..9d39b1bdd3db2d2f26eb9d3f25570cc83cf8572f --- /dev/null +++ b/libc/src/math/fminimum.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fminimum -------------------------*- 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_MATH_FMINIMUM_H +#define LLVM_LIBC_SRC_MATH_FMINIMUM_H + +namespace LIBC_NAMESPACE { + +double fminimum(double x, double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMINIMUM_H diff --git a/libc/src/math/fminimum_mag.h b/libc/src/math/fminimum_mag.h new file mode 100644 index 0000000000000000000000000000000000000000..10b242e6026e836b0f3e4ca28a0125ba816ca380 --- /dev/null +++ b/libc/src/math/fminimum_mag.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fminimum_mag--------------------------*- 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_MATH_FMINIMUM_MAG_H +#define LLVM_LIBC_SRC_MATH_FMINIMUM_MAG_H + +namespace LIBC_NAMESPACE { + +double fminimum_mag(double x, double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMINIMUM_MAG_H diff --git a/libc/src/math/fminimum_mag_num.h b/libc/src/math/fminimum_mag_num.h new file mode 100644 index 0000000000000000000000000000000000000000..eb1823018851c15175325919677f0b09fa919afe --- /dev/null +++ b/libc/src/math/fminimum_mag_num.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fminimum_mag_num------------------------*- 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_MATH_FMINIMUM_MAG_NUM_H +#define LLVM_LIBC_SRC_MATH_FMINIMUM_MAG_NUM_H + +namespace LIBC_NAMESPACE { + +double fminimum_mag_num(double x, double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMINIMUM_MAG_NUMH diff --git a/libc/src/math/fminimum_mag_numf.h b/libc/src/math/fminimum_mag_numf.h new file mode 100644 index 0000000000000000000000000000000000000000..809199091139992fb3bbe31b96b3b26aec5c7530 --- /dev/null +++ b/libc/src/math/fminimum_mag_numf.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fminimum_mag_numf ----------------------*- 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_MATH_FMINIMUM_MAG_NUMF_H +#define LLVM_LIBC_SRC_MATH_FMINIMUM_MAG_NUMF_H + +namespace LIBC_NAMESPACE { + +float fminimum_mag_numf(float x, float y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMINIMUM_MAG_NUMF_H diff --git a/libc/src/math/fminimum_mag_numf128.h b/libc/src/math/fminimum_mag_numf128.h new file mode 100644 index 0000000000000000000000000000000000000000..803c5e641d170cc482359a3d4587404fed9ae99a --- /dev/null +++ b/libc/src/math/fminimum_mag_numf128.h @@ -0,0 +1,21 @@ +//===-- Implementation header for fminimum_mag_numf128 -------------------*- 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_MATH_FMINIMUM_MAG_NUMF128_H +#define LLVM_LIBC_SRC_MATH_FMINIMUM_MAG_NUMF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 fminimum_mag_numf128(float128 x, float128 y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMINIMUM_MAG_NUMF128_H diff --git a/libc/src/math/fminimum_mag_numl.h b/libc/src/math/fminimum_mag_numl.h new file mode 100644 index 0000000000000000000000000000000000000000..fdbb183280692ab41c7cc38260a07c270b1b945d --- /dev/null +++ b/libc/src/math/fminimum_mag_numl.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fminimum_mag_numl ----------------------*- 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_MATH_FMINIMUM_MAG_NUML_H +#define LLVM_LIBC_SRC_MATH_FMINIMUM_MAG_NUML_H + +namespace LIBC_NAMESPACE { + +long double fminimum_mag_numl(long double x, long double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMINIMUM_MAG_NUML_H diff --git a/libc/src/math/fminimum_magf.h b/libc/src/math/fminimum_magf.h new file mode 100644 index 0000000000000000000000000000000000000000..6209340074d2dcd89a438fc1df197a58f57acf80 --- /dev/null +++ b/libc/src/math/fminimum_magf.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fminimum_magf -------------------------*- 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_MATH_FMINIMUM_MAGF_H +#define LLVM_LIBC_SRC_MATH_FMINIMUM_MAGF_H + +namespace LIBC_NAMESPACE { + +float fminimum_magf(float x, float y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMINIMUM_MAGF_H diff --git a/libc/src/math/fminimum_magf128.h b/libc/src/math/fminimum_magf128.h new file mode 100644 index 0000000000000000000000000000000000000000..05bd163be97c816b28bfcc24c2dcfb204a89931d --- /dev/null +++ b/libc/src/math/fminimum_magf128.h @@ -0,0 +1,21 @@ +//===-- Implementation header for fminimum_magf128 ----------------------*- 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_MATH_FMINIMUM_MAGF128_H +#define LLVM_LIBC_SRC_MATH_FMINIMUM_MAGF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 fminimum_magf128(float128 x, float128 y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMINIMUM_MAGF128_H diff --git a/libc/src/math/fminimum_magl.h b/libc/src/math/fminimum_magl.h new file mode 100644 index 0000000000000000000000000000000000000000..bcda35ce3bd2a3d26769a855554a783875c0c51c --- /dev/null +++ b/libc/src/math/fminimum_magl.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fminimum_magl -------------------------*- 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_MATH_FMINIMUM_MAGL_H +#define LLVM_LIBC_SRC_MATH_FMINIMUM_MAGL_H + +namespace LIBC_NAMESPACE { + +long double fminimum_magl(long double x, long double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMINIMUM_MAGL_H diff --git a/libc/src/math/fminimum_num.h b/libc/src/math/fminimum_num.h new file mode 100644 index 0000000000000000000000000000000000000000..4c864cba84872e89cc50751be1e5f2b88006747e --- /dev/null +++ b/libc/src/math/fminimum_num.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fminimum_num--------------------------*- 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_MATH_FMINIMUM_NUM_H +#define LLVM_LIBC_SRC_MATH_FMINIMUM_NUM_H + +namespace LIBC_NAMESPACE { + +double fminimum_num(double x, double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMINIMUM_NUM_H diff --git a/libc/src/math/fminimum_numf.h b/libc/src/math/fminimum_numf.h new file mode 100644 index 0000000000000000000000000000000000000000..ac4b08b292be82f3f0f98574a7e090f4f545af2d --- /dev/null +++ b/libc/src/math/fminimum_numf.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fminimum_numf -------------------------*- 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_MATH_FMINIMUM_NUMF_H +#define LLVM_LIBC_SRC_MATH_FMINIMUM_NUMF_H + +namespace LIBC_NAMESPACE { + +float fminimum_numf(float x, float y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMINIMUM_NUMF_H diff --git a/libc/src/math/fminimum_numf128.h b/libc/src/math/fminimum_numf128.h new file mode 100644 index 0000000000000000000000000000000000000000..00f8960ff12797e7fb785b519c6977499544f230 --- /dev/null +++ b/libc/src/math/fminimum_numf128.h @@ -0,0 +1,21 @@ +//===-- Implementation header for fminimum_numf128 ----------------------*- 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_MATH_FMINIMUM_NUMF128_H +#define LLVM_LIBC_SRC_MATH_FMINIMUM_NUMF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 fminimum_numf128(float128 x, float128 y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMINIMUM_NUMF128_H diff --git a/libc/src/math/fminimum_numl.h b/libc/src/math/fminimum_numl.h new file mode 100644 index 0000000000000000000000000000000000000000..0da204e72c74d4276a9d2b7d89e9c79b7a018c32 --- /dev/null +++ b/libc/src/math/fminimum_numl.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fminimum_numl -------------------------*- 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_MATH_FMINIMUM_NUML_H +#define LLVM_LIBC_SRC_MATH_FMINIMUM_NUML_H + +namespace LIBC_NAMESPACE { + +long double fminimum_numl(long double x, long double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMINIMUM_NUML_H diff --git a/libc/src/math/fminimumf.h b/libc/src/math/fminimumf.h new file mode 100644 index 0000000000000000000000000000000000000000..424309f3a5313e73e83058401bb605908b9ac007 --- /dev/null +++ b/libc/src/math/fminimumf.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fminimumf -------------------------*- 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_MATH_FMINIMUMF_H +#define LLVM_LIBC_SRC_MATH_FMINIMUMF_H + +namespace LIBC_NAMESPACE { + +float fminimumf(float x, float y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMINIMUMF_H diff --git a/libc/src/math/fminimumf128.h b/libc/src/math/fminimumf128.h new file mode 100644 index 0000000000000000000000000000000000000000..7ff0190727379a8c79febdd1a0aa8e36b1b572b6 --- /dev/null +++ b/libc/src/math/fminimumf128.h @@ -0,0 +1,21 @@ +//===-- Implementation header for fminimumf128 ----------------------*- 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_MATH_FMINIMUMF128_H +#define LLVM_LIBC_SRC_MATH_FMINIMUMF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 fminimumf128(float128 x, float128 y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMINIMUMF128_H diff --git a/libc/src/math/fminimuml.h b/libc/src/math/fminimuml.h new file mode 100644 index 0000000000000000000000000000000000000000..b9cc321354a2831293848bf612d42df85384cbbe --- /dev/null +++ b/libc/src/math/fminimuml.h @@ -0,0 +1,19 @@ +//===-- Implementation header for fminimuml -------------------------*- 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_MATH_FMINIMUML_H +#define LLVM_LIBC_SRC_MATH_FMINIMUML_H + +namespace LIBC_NAMESPACE { + +long double fminimuml(long double x, long double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMINIMUML_H diff --git a/libc/src/math/fromfp.h b/libc/src/math/fromfp.h new file mode 100644 index 0000000000000000000000000000000000000000..d3de2dd3460832ecd77ec4554b4ca7ff4e9d015c --- /dev/null +++ b/libc/src/math/fromfp.h @@ -0,0 +1,18 @@ +//===-- Implementation header for fromfp ------------------------*- 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_MATH_FROMFP_H +#define LLVM_LIBC_SRC_MATH_FROMFP_H + +namespace LIBC_NAMESPACE { + +double fromfp(double x, int rnd, unsigned int width); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FROMFP_H diff --git a/libc/src/math/fromfpf.h b/libc/src/math/fromfpf.h new file mode 100644 index 0000000000000000000000000000000000000000..11d432148d018917a2d01bef282b1c021e642826 --- /dev/null +++ b/libc/src/math/fromfpf.h @@ -0,0 +1,18 @@ +//===-- Implementation header for fromfpf -----------------------*- 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_MATH_FROMFPF_H +#define LLVM_LIBC_SRC_MATH_FROMFPF_H + +namespace LIBC_NAMESPACE { + +float fromfpf(float x, int rnd, unsigned int width); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FROMFPF_H diff --git a/libc/src/math/fromfpf128.h b/libc/src/math/fromfpf128.h new file mode 100644 index 0000000000000000000000000000000000000000..5f85fde570a0fb42b68fbd5a8e6e8eb8f75a2d2c --- /dev/null +++ b/libc/src/math/fromfpf128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for fromfpf128 --------------------*- 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_MATH_FROMFPF128_H +#define LLVM_LIBC_SRC_MATH_FROMFPF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 fromfpf128(float128 x, int rnd, unsigned int width); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FROMFPF128_H diff --git a/libc/src/math/fromfpl.h b/libc/src/math/fromfpl.h new file mode 100644 index 0000000000000000000000000000000000000000..dd8e1eebdea994d1381a62b423f484550f8c2ac0 --- /dev/null +++ b/libc/src/math/fromfpl.h @@ -0,0 +1,18 @@ +//===-- Implementation header for fromfpl -----------------------*- 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_MATH_FROMFPL_H +#define LLVM_LIBC_SRC_MATH_FROMFPL_H + +namespace LIBC_NAMESPACE { + +long double fromfpl(long double x, int rnd, unsigned int width); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FROMFPL_H diff --git a/libc/src/math/fromfpx.h b/libc/src/math/fromfpx.h new file mode 100644 index 0000000000000000000000000000000000000000..3fc96e1e648b9366260b9e029993e917d5da9e39 --- /dev/null +++ b/libc/src/math/fromfpx.h @@ -0,0 +1,18 @@ +//===-- Implementation header for fromfpx -----------------------*- 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_MATH_FROMFPX_H +#define LLVM_LIBC_SRC_MATH_FROMFPX_H + +namespace LIBC_NAMESPACE { + +double fromfpx(double x, int rnd, unsigned int width); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FROMFPX_H diff --git a/libc/src/math/fromfpxf.h b/libc/src/math/fromfpxf.h new file mode 100644 index 0000000000000000000000000000000000000000..b55bc4c7513951880cd5d3dd7a87dbbd38e8b630 --- /dev/null +++ b/libc/src/math/fromfpxf.h @@ -0,0 +1,18 @@ +//===-- Implementation header for fromfpxf ----------------------*- 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_MATH_FROMFPXF_H +#define LLVM_LIBC_SRC_MATH_FROMFPXF_H + +namespace LIBC_NAMESPACE { + +float fromfpxf(float x, int rnd, unsigned int width); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FROMFPXF_H diff --git a/libc/src/math/fromfpxf128.h b/libc/src/math/fromfpxf128.h new file mode 100644 index 0000000000000000000000000000000000000000..88932646cdcc9f6fffa39c535774b195ac5dfbfe --- /dev/null +++ b/libc/src/math/fromfpxf128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for fromfpxf128 -------------------*- 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_MATH_FROMFPXF128_H +#define LLVM_LIBC_SRC_MATH_FROMFPXF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 fromfpxf128(float128 x, int rnd, unsigned int width); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FROMFPXF128_H diff --git a/libc/src/math/fromfpxl.h b/libc/src/math/fromfpxl.h new file mode 100644 index 0000000000000000000000000000000000000000..545288834b8f33b9b5e2e163a95505e09b25ab99 --- /dev/null +++ b/libc/src/math/fromfpxl.h @@ -0,0 +1,18 @@ +//===-- Implementation header for fromfpxl ----------------------*- 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_MATH_FROMFPXL_H +#define LLVM_LIBC_SRC_MATH_FROMFPXL_H + +namespace LIBC_NAMESPACE { + +long double fromfpxl(long double x, int rnd, unsigned int width); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FROMFPXL_H diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index bc4e9b34cfc2f6fceff617d8fb6f346167923d2e..b164d33e204b1a88ed300419d39b66a4c6238936 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -1,3 +1,51 @@ +add_entrypoint_object( + canonicalize + SRCS + canonicalize.cpp + HDRS + ../canonicalize.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.FPUtil.basic_operations +) + +add_entrypoint_object( + canonicalizef + SRCS + canonicalizef.cpp + HDRS + ../canonicalizef.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.FPUtil.basic_operations +) + +add_entrypoint_object( + canonicalizef128 + SRCS + canonicalizef128.cpp + HDRS + ../canonicalizef128.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.FPUtil.basic_operations +) + +add_entrypoint_object( + canonicalizel + SRCS + canonicalizel.cpp + HDRS + ../canonicalizel.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.FPUtil.basic_operations +) + add_entrypoint_object( ceil SRCS @@ -1546,385 +1594,1100 @@ add_entrypoint_object( ) add_entrypoint_object( - sqrt + fmaximum SRCS - sqrt.cpp + fmaximum.cpp HDRS - ../sqrt.h + ../fmaximum.h DEPENDS - libc.src.__support.FPUtil.sqrt + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS - -O3 + -O2 ) add_entrypoint_object( - sqrtf + fmaximumf SRCS - sqrtf.cpp + fmaximumf.cpp HDRS - ../sqrtf.h + ../fmaximumf.h DEPENDS - libc.src.__support.FPUtil.sqrt + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS - -O3 + -O2 ) add_entrypoint_object( - sqrtl + fmaximuml SRCS - sqrtl.cpp + fmaximuml.cpp HDRS - ../sqrtl.h + ../fmaximuml.h DEPENDS - libc.src.__support.FPUtil.sqrt + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS - -O3 + -O2 ) add_entrypoint_object( - sqrtf128 + fmaximumf128 SRCS - sqrtf128.cpp + fmaximumf128.cpp HDRS - ../sqrtf128.h + ../fmaximumf128.h DEPENDS libc.src.__support.macros.properties.types - libc.src.__support.FPUtil.sqrt + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS -O3 - ) +) add_entrypoint_object( - remquof + fmaximum_num SRCS - remquof.cpp + fmaximum_num.cpp HDRS - ../remquof.h + ../fmaximum_num.h DEPENDS - libc.src.__support.FPUtil.division_and_remainder_operations + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS -O2 ) add_entrypoint_object( - remquo + fmaximum_numf SRCS - remquo.cpp + fmaximum_numf.cpp HDRS - ../remquo.h + ../fmaximum_numf.h DEPENDS - libc.src.__support.FPUtil.division_and_remainder_operations + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS -O2 ) add_entrypoint_object( - remquol + fmaximum_numl SRCS - remquol.cpp + fmaximum_numl.cpp HDRS - ../remquol.h + ../fmaximum_numl.h DEPENDS - libc.src.__support.FPUtil.division_and_remainder_operations + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS -O2 ) add_entrypoint_object( - remainderf + fmaximum_numf128 SRCS - remainderf.cpp + fmaximum_numf128.cpp HDRS - ../remainderf.h + ../fmaximum_numf128.h DEPENDS - libc.src.__support.FPUtil.division_and_remainder_operations + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS - -O2 + -O3 ) add_entrypoint_object( - remainder + fmaximum_mag SRCS - remainder.cpp + fmaximum_mag.cpp HDRS - ../remainder.h + ../fmaximum_mag.h DEPENDS - libc.src.__support.FPUtil.division_and_remainder_operations + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS -O2 ) add_entrypoint_object( - remainderl + fmaximum_magf SRCS - remainderl.cpp + fmaximum_magf.cpp HDRS - ../remainderl.h + ../fmaximum_magf.h DEPENDS - libc.src.__support.FPUtil.division_and_remainder_operations + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS -O2 ) add_entrypoint_object( - hypotf + fmaximum_magl SRCS - hypotf.cpp + fmaximum_magl.cpp HDRS - ../hypotf.h + ../fmaximum_magl.h DEPENDS libc.src.__support.FPUtil.basic_operations - libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.sqrt COMPILE_OPTIONS - -O3 + -O2 ) add_entrypoint_object( - fdim + fmaximum_magf128 SRCS - fdim.cpp + fmaximum_magf128.cpp HDRS - ../fdim.h + ../fmaximum_magf128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS -O3 +) + + +add_entrypoint_object( + fmaximum_mag_num + SRCS + fmaximum_mag_num.cpp + HDRS + ../fmaximum_mag_num.h DEPENDS libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 ) add_entrypoint_object( - fdimf + fmaximum_mag_numf SRCS - fdimf.cpp + fmaximum_mag_numf.cpp HDRS - ../fdimf.h - COMPILE_OPTIONS - -O3 + ../fmaximum_mag_numf.h DEPENDS libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 ) add_entrypoint_object( - fdiml + fmaximum_mag_numl SRCS - fdiml.cpp + fmaximum_mag_numl.cpp HDRS - ../fdiml.h - COMPILE_OPTIONS - -O3 + ../fmaximum_mag_numl.h DEPENDS libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O2 ) add_entrypoint_object( - fdimf128 + fmaximum_mag_numf128 SRCS - fdimf128.cpp + fmaximum_mag_numf128.cpp HDRS - ../fdimf128.h - COMPILE_OPTIONS - -O3 + ../fmaximum_mag_numf128.h DEPENDS libc.src.__support.macros.properties.types libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O3 ) add_entrypoint_object( - hypot + fminimum SRCS - hypot.cpp + fminimum.cpp HDRS - ../hypot.h + ../fminimum.h DEPENDS - libc.src.__support.FPUtil.hypot + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS - -O3 + -O2 ) add_entrypoint_object( - nan + fminimumf SRCS - nan.cpp + fminimumf.cpp HDRS - ../nan.h + ../fminimumf.h DEPENDS - libc.src.__support.str_to_float - libc.src.errno.errno + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS - -O3 + -O2 ) add_entrypoint_object( - nanf + fminimuml SRCS - nanf.cpp + fminimuml.cpp HDRS - ../nanf.h + ../fminimuml.h DEPENDS - libc.src.__support.str_to_float - libc.src.errno.errno + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS - -O3 + -O2 ) add_entrypoint_object( - nanl + fminimumf128 SRCS - nanl.cpp + fminimumf128.cpp HDRS - ../nanl.h + ../fminimumf128.h DEPENDS - libc.src.__support.str_to_float - libc.src.errno.errno + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS -O3 ) add_entrypoint_object( - nextafter + fminimum_num SRCS - nextafter.cpp + fminimum_num.cpp HDRS - ../nextafter.h + ../fminimum_num.h DEPENDS - libc.src.__support.FPUtil.manipulation_functions + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS -O2 ) add_entrypoint_object( - nextafterf + fminimum_numf SRCS - nextafterf.cpp + fminimum_numf.cpp HDRS - ../nextafterf.h + ../fminimum_numf.h DEPENDS - libc.src.__support.FPUtil.manipulation_functions + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS -O2 ) add_entrypoint_object( - nextafterl + fminimum_numl SRCS - nextafterl.cpp + fminimum_numl.cpp HDRS - ../nextafterl.h + ../fminimum_numl.h DEPENDS - libc.src.__support.FPUtil.manipulation_functions + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS -O2 ) add_entrypoint_object( - nexttoward + fminimum_numf128 SRCS - nexttoward.cpp + fminimum_numf128.cpp HDRS - ../nexttoward.h + ../fminimum_numf128.h DEPENDS - libc.src.__support.FPUtil.manipulation_functions + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS -O3 ) add_entrypoint_object( - nexttowardf + fminimum_mag SRCS - nexttowardf.cpp + fminimum_mag.cpp HDRS - ../nexttowardf.h + ../fminimum_mag.h DEPENDS - libc.src.__support.FPUtil.manipulation_functions + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS - -O3 + -O2 ) add_entrypoint_object( - nexttowardl + fminimum_magf SRCS - nexttowardl.cpp + fminimum_magf.cpp HDRS - ../nexttowardl.h + ../fminimum_magf.h DEPENDS - libc.src.__support.FPUtil.manipulation_functions + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS - -O3 + -O2 ) add_entrypoint_object( - fmod + fminimum_magl SRCS - fmod.cpp + fminimum_magl.cpp HDRS - ../fmod.h + ../fminimum_magl.h DEPENDS - libc.src.__support.FPUtil.generic.fmod + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS - -O3 + -O2 ) add_entrypoint_object( - fmodf + fminimum_magf128 SRCS - fmodf.cpp + fminimum_magf128.cpp HDRS - ../fmodf.h + ../fminimum_magf128.h DEPENDS - libc.src.__support.FPUtil.generic.fmod + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS -O3 ) + add_entrypoint_object( - fmodl + fminimum_mag_num SRCS - fmodl.cpp + fminimum_mag_num.cpp HDRS - ../fmodl.h + ../fminimum_mag_num.h DEPENDS - libc.src.__support.FPUtil.generic.fmod + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS - -O3 + -O2 ) add_entrypoint_object( - fmodf128 + fminimum_mag_numf SRCS - fmodf128.cpp + fminimum_mag_numf.cpp HDRS - ../fmodf128.h + ../fminimum_mag_numf.h DEPENDS - libc.src.__support.macros.properties.types - libc.src.__support.FPUtil.generic.fmod + libc.src.__support.FPUtil.basic_operations COMPILE_OPTIONS - -O3 + -O2 ) -#TODO: Add errno include to the hyperbolic functions. -add_object_library( - explogxf - HDRS - explogxf.h +add_entrypoint_object( + fminimum_mag_numl SRCS - explogxf.cpp + fminimum_mag_numl.cpp + HDRS + ../fminimum_mag_numl.h DEPENDS - .common_constants - libc.src.__support.CPP.bit - libc.src.__support.CPP.optional libc.src.__support.FPUtil.basic_operations - libc.src.__support.FPUtil.basic_operations - 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.common - libc.include.errno - libc.src.errno.errno - libc.include.math COMPILE_OPTIONS - -O3 + -O2 +) + +add_entrypoint_object( + fminimum_mag_numf128 + SRCS + fminimum_mag_numf128.cpp + HDRS + ../fminimum_mag_numf128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + sqrt + SRCS + sqrt.cpp + HDRS + ../sqrt.h + DEPENDS + libc.src.__support.FPUtil.sqrt + COMPILE_OPTIONS + -O3 +) + + +add_entrypoint_object( + sqrtf + SRCS + sqrtf.cpp + HDRS + ../sqrtf.h + DEPENDS + libc.src.__support.FPUtil.sqrt + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + sqrtl + SRCS + sqrtl.cpp + HDRS + ../sqrtl.h + DEPENDS + libc.src.__support.FPUtil.sqrt + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + sqrtf128 + SRCS + sqrtf128.cpp + HDRS + ../sqrtf128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.sqrt + COMPILE_OPTIONS + -O3 + ) + +add_entrypoint_object( + remquof + SRCS + remquof.cpp + HDRS + ../remquof.h + DEPENDS + libc.src.__support.FPUtil.division_and_remainder_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + remquo + SRCS + remquo.cpp + HDRS + ../remquo.h + DEPENDS + libc.src.__support.FPUtil.division_and_remainder_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + remquol + SRCS + remquol.cpp + HDRS + ../remquol.h + DEPENDS + libc.src.__support.FPUtil.division_and_remainder_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + remainderf + SRCS + remainderf.cpp + HDRS + ../remainderf.h + DEPENDS + libc.src.__support.FPUtil.division_and_remainder_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + remainder + SRCS + remainder.cpp + HDRS + ../remainder.h + DEPENDS + libc.src.__support.FPUtil.division_and_remainder_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + remainderl + SRCS + remainderl.cpp + HDRS + ../remainderl.h + DEPENDS + libc.src.__support.FPUtil.division_and_remainder_operations + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + hypotf + SRCS + hypotf.cpp + HDRS + ../hypotf.h + DEPENDS + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.sqrt + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fdim + SRCS + fdim.cpp + HDRS + ../fdim.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.FPUtil.basic_operations +) + +add_entrypoint_object( + fdimf + SRCS + fdimf.cpp + HDRS + ../fdimf.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.FPUtil.basic_operations +) + +add_entrypoint_object( + fdiml + SRCS + fdiml.cpp + HDRS + ../fdiml.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.FPUtil.basic_operations +) + +add_entrypoint_object( + fdimf128 + SRCS + fdimf128.cpp + HDRS + ../fdimf128.h + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.basic_operations +) + +add_entrypoint_object( + hypot + SRCS + hypot.cpp + HDRS + ../hypot.h + DEPENDS + libc.src.__support.FPUtil.hypot + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nan + SRCS + nan.cpp + HDRS + ../nan.h + DEPENDS + libc.src.__support.str_to_float + libc.src.errno.errno + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nanf + SRCS + nanf.cpp + HDRS + ../nanf.h + DEPENDS + libc.src.__support.str_to_float + libc.src.errno.errno + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nanl + SRCS + nanl.cpp + HDRS + ../nanl.h + DEPENDS + libc.src.__support.str_to_float + libc.src.errno.errno + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nanf128 + SRCS + nanf128.cpp + HDRS + ../nanf128.h + DEPENDS + libc.src.__support.str_to_float + libc.src.errno.errno + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nextafter + SRCS + nextafter.cpp + HDRS + ../nextafter.h + DEPENDS + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nextafterf + SRCS + nextafterf.cpp + HDRS + ../nextafterf.h + DEPENDS + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nextafterl + SRCS + nextafterl.cpp + HDRS + ../nextafterl.h + DEPENDS + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nextafterf128 + SRCS + nextafterf128.cpp + HDRS + ../nextafterf128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nexttoward + SRCS + nexttoward.cpp + HDRS + ../nexttoward.h + DEPENDS + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nexttowardf + SRCS + nexttowardf.cpp + HDRS + ../nexttowardf.h + DEPENDS + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nexttowardl + SRCS + nexttowardl.cpp + HDRS + ../nexttowardl.h + DEPENDS + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nextdown + SRCS + nextdown.cpp + HDRS + ../nextdown.h + DEPENDS + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nextdownl + SRCS + nextdownl.cpp + HDRS + ../nextdownl.h + DEPENDS + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nextdownf + SRCS + nextdownf.cpp + HDRS + ../nextdownf.h + DEPENDS + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nextdownf128 + SRCS + nextdownf128.cpp + HDRS + ../nextdownf128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nextup + SRCS + nextup.cpp + HDRS + ../nextup.h + DEPENDS + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nextupl + SRCS + nextupl.cpp + HDRS + ../nextupl.h + DEPENDS + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nextupf + SRCS + nextupf.cpp + HDRS + ../nextupf.h + DEPENDS + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + nextupf128 + SRCS + nextupf128.cpp + HDRS + ../nextupf128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fmod + SRCS + fmod.cpp + HDRS + ../fmod.h + DEPENDS + libc.src.__support.FPUtil.generic.fmod + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fmodf + SRCS + fmodf.cpp + HDRS + ../fmodf.h + DEPENDS + libc.src.__support.FPUtil.generic.fmod + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fmodl + SRCS + fmodl.cpp + HDRS + ../fmodl.h + DEPENDS + libc.src.__support.FPUtil.generic.fmod + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fmodf128 + SRCS + fmodf128.cpp + HDRS + ../fmodf128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.generic.fmod + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fromfp + SRCS + fromfp.cpp + HDRS + ../fromfp.h + DEPENDS + libc.src.__support.FPUtil.nearest_integer + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fromfpf + SRCS + fromfpf.cpp + HDRS + ../fromfpf.h + DEPENDS + libc.src.__support.FPUtil.nearest_integer + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fromfpl + SRCS + fromfpl.cpp + HDRS + ../fromfpl.h + DEPENDS + libc.src.__support.FPUtil.nearest_integer + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fromfpf128 + SRCS + fromfpf128.cpp + HDRS + ../fromfpf128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.nearest_integer + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fromfpx + SRCS + fromfpx.cpp + HDRS + ../fromfpx.h + DEPENDS + libc.src.__support.FPUtil.nearest_integer + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fromfpxf + SRCS + fromfpxf.cpp + HDRS + ../fromfpxf.h + DEPENDS + libc.src.__support.FPUtil.nearest_integer + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fromfpxl + SRCS + fromfpxl.cpp + HDRS + ../fromfpxl.h + DEPENDS + libc.src.__support.FPUtil.nearest_integer + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fromfpxf128 + SRCS + fromfpxf128.cpp + HDRS + ../fromfpxf128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.nearest_integer + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + ufromfp + SRCS + ufromfp.cpp + HDRS + ../ufromfp.h + DEPENDS + libc.src.__support.FPUtil.nearest_integer + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + ufromfpf + SRCS + ufromfpf.cpp + HDRS + ../ufromfpf.h + DEPENDS + libc.src.__support.FPUtil.nearest_integer + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + ufromfpl + SRCS + ufromfpl.cpp + HDRS + ../ufromfpl.h + DEPENDS + libc.src.__support.FPUtil.nearest_integer + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + ufromfpf128 + SRCS + ufromfpf128.cpp + HDRS + ../ufromfpf128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.nearest_integer + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + ufromfpx + SRCS + ufromfpx.cpp + HDRS + ../ufromfpx.h + DEPENDS + libc.src.__support.FPUtil.nearest_integer + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + ufromfpxf + SRCS + ufromfpxf.cpp + HDRS + ../ufromfpxf.h + DEPENDS + libc.src.__support.FPUtil.nearest_integer + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + ufromfpxl + SRCS + ufromfpxl.cpp + HDRS + ../ufromfpxl.h + DEPENDS + libc.src.__support.FPUtil.nearest_integer + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + ufromfpxf128 + SRCS + ufromfpxf128.cpp + HDRS + ../ufromfpxf128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.nearest_integer + COMPILE_OPTIONS + -O3 +) + +#TODO: Add errno include to the hyperbolic functions. +add_object_library( + explogxf + HDRS + explogxf.h + SRCS + explogxf.cpp + DEPENDS + .common_constants + libc.src.__support.CPP.bit + libc.src.__support.CPP.optional + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.basic_operations + 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.common + libc.include.errno + libc.src.errno.errno + libc.include.math + COMPILE_OPTIONS + -O3 ) add_entrypoint_object( @@ -2031,16 +2794,9 @@ add_object_library( SRCS inv_trigf_utils.cpp DEPENDS - .math_utils - libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.fenv_impl - libc.src.__support.FPUtil.nearest_integer - libc.src.__support.FPUtil.nearest_integer_operations + libc.src.__support.FPUtil.multiply_add libc.src.__support.FPUtil.polyeval libc.src.__support.common - libc.include.errno - libc.src.errno.errno - libc.include.math ) add_entrypoint_object( @@ -2087,14 +2843,35 @@ add_entrypoint_object( ../atanf.h DEPENDS .inv_trigf_utils - .math_utils + libc.src.__support.FPUtil.except_value_utils 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 COMPILE_OPTIONS -O3 ) +add_entrypoint_object( + atan2f + SRCS + atan2f.cpp + HDRS + ../atan2f.h + COMPILE_OPTIONS + -O3 + DEPENDS + .inv_trigf_utils + 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 +) + add_entrypoint_object( scalbn SRCS diff --git a/libc/src/math/generic/acosf.cpp b/libc/src/math/generic/acosf.cpp index 0c1fdbc68693023c5cb9f719083dd4307cd963ed..e6e28d43ef61f585c69a93ac5321bff9f7f7f69c 100644 --- a/libc/src/math/generic/acosf.cpp +++ b/libc/src/math/generic/acosf.cpp @@ -38,7 +38,7 @@ static constexpr fputil::ExceptValues<float, N_EXCEPTS> ACOSF_EXCEPTS = {{ LLVM_LIBC_FUNCTION(float, acosf, (float x)) { using FPBits = typename fputil::FPBits<float>; - using Sign = fputil::Sign; + FPBits xbits(x); uint32_t x_uint = xbits.uintval(); uint32_t x_abs = xbits.uintval() & 0x7fff'ffffU; diff --git a/libc/src/math/generic/asinf.cpp b/libc/src/math/generic/asinf.cpp index 6e3a27238ac998be82539196d2c8411d59dd8b1c..d9133333d2561aad8714a427ec29ccb988b936ea 100644 --- a/libc/src/math/generic/asinf.cpp +++ b/libc/src/math/generic/asinf.cpp @@ -44,7 +44,7 @@ static constexpr fputil::ExceptValues<float, N_EXCEPTS> ASINF_EXCEPTS_HI = {{ LLVM_LIBC_FUNCTION(float, asinf, (float x)) { using FPBits = typename fputil::FPBits<float>; - using Sign = fputil::Sign; + FPBits xbits(x); uint32_t x_uint = xbits.uintval(); uint32_t x_abs = xbits.uintval() & 0x7fff'ffffU; diff --git a/libc/src/math/generic/atan2f.cpp b/libc/src/math/generic/atan2f.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b79410dbf66ee6e601d4ae7f770b7c949a883f21 --- /dev/null +++ b/libc/src/math/generic/atan2f.cpp @@ -0,0 +1,306 @@ +//===-- Single-precision atan2f function ----------------------------------===// +// +// 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/math/atan2f.h" +#include "inv_trigf_utils.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/PolyEval.h" +#include "src/__support/FPUtil/double_double.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/macros/optimization.h" // LIBC_UNLIKELY + +namespace LIBC_NAMESPACE { + +namespace { + +// Look up tables for accurate pass: + +// atan(i/16) with i = 0..16, generated by Sollya with: +// > for i from 0 to 16 do { +// a = round(atan(i/16), D, RN); +// b = round(atan(i/16) - a, D, RN); +// print("{", b, ",", a, "},"); +// }; +constexpr fputil::DoubleDouble ATAN_I[17] = { + {0.0, 0.0}, + {-0x1.c934d86d23f1dp-60, 0x1.ff55bb72cfdeap-5}, + {-0x1.cd37686760c17p-59, 0x1.fd5ba9aac2f6ep-4}, + {0x1.347b0b4f881cap-58, 0x1.7b97b4bce5b02p-3}, + {0x1.8ab6e3cf7afbdp-57, 0x1.f5b75f92c80ddp-3}, + {-0x1.963a544b672d8p-57, 0x1.362773707ebccp-2}, + {-0x1.c63aae6f6e918p-56, 0x1.6f61941e4def1p-2}, + {-0x1.24dec1b50b7ffp-56, 0x1.a64eec3cc23fdp-2}, + {0x1.a2b7f222f65e2p-56, 0x1.dac670561bb4fp-2}, + {-0x1.d5b495f6349e6p-56, 0x1.0657e94db30dp-1}, + {-0x1.928df287a668fp-58, 0x1.1e00babdefeb4p-1}, + {0x1.1021137c71102p-55, 0x1.345f01cce37bbp-1}, + {0x1.2419a87f2a458p-56, 0x1.4978fa3269ee1p-1}, + {0x1.0028e4bc5e7cap-57, 0x1.5d58987169b18p-1}, + {-0x1.8c34d25aadef6p-56, 0x1.700a7c5784634p-1}, + {-0x1.bf76229d3b917p-56, 0x1.819d0b7158a4dp-1}, + {0x1.1a62633145c07p-55, 0x1.921fb54442d18p-1}, +}; + +// Taylor polynomial, generated by Sollya with: +// > for i from 0 to 8 do { +// j = (-1)^(i + 1)/(2*i + 1); +// a = round(j, D, RN); +// b = round(j - a, D, RN); +// print("{", b, ",", a, "},"); +// }; +constexpr fputil::DoubleDouble COEFFS[9] = { + {0.0, 1.0}, // 1 + {-0x1.5555555555555p-56, -0x1.5555555555555p-2}, // -1/3 + {-0x1.999999999999ap-57, 0x1.999999999999ap-3}, // 1/5 + {-0x1.2492492492492p-57, -0x1.2492492492492p-3}, // -1/7 + {0x1.c71c71c71c71cp-58, 0x1.c71c71c71c71cp-4}, // 1/9 + {0x1.745d1745d1746p-59, -0x1.745d1745d1746p-4}, // -1/11 + {-0x1.3b13b13b13b14p-58, 0x1.3b13b13b13b14p-4}, // 1/13 + {-0x1.1111111111111p-60, -0x1.1111111111111p-4}, // -1/15 + {0x1.e1e1e1e1e1e1ep-61, 0x1.e1e1e1e1e1e1ep-5}, // 1/17 +}; + +// Veltkamp's splitting of a double precision into hi + lo, where the hi part is +// slightly smaller than an even split, so that the product of +// hi * (s1 * k + s2) is exact, +// where: +// s1, s2 are single precsion, +// 1/16 <= s1/s2 <= 1 +// 1/16 <= k <= 1 is an integer. +// So the maximal precision of (s1 * k + s2) is: +// prec(s1 * k + s2) = 2 + log2(msb(s2)) - log2(lsb(k_d * s1)) +// = 2 + log2(msb(s1)) + 4 - log2(lsb(k_d)) - log2(lsb(s1)) +// = 2 + log2(lsb(s1)) + 23 + 4 - (-4) - log2(lsb(s1)) +// = 33. +// Thus, the Veltkamp splitting constant is C = 2^33 + 1. +// This is used when FMA instruction is not available. +[[maybe_unused]] constexpr fputil::DoubleDouble split_d(double a) { + fputil::DoubleDouble r{0.0, 0.0}; + constexpr double C = 0x1.0p33 + 1.0; + double t1 = C * a; + double t2 = a - t1; + r.hi = t1 + t2; + r.lo = a - r.hi; + return r; +} + +// Compute atan( num_d / den_d ) in double-double precision. +// num_d = min(|x|, |y|) +// den_d = max(|x|, |y|) +// q_d = num_d / den_d +// idx, k_d = round( 2^4 * num_d / den_d ) +// final_sign = sign of the final result +// const_term = the constant term in the final expression. +float atan2f_double_double(double num_d, double den_d, double q_d, int idx, + double k_d, double final_sign, + const fputil::DoubleDouble &const_term) { + fputil::DoubleDouble q; + double num_r, den_r; + + if (idx != 0) { + // The following range reduction is accurate even without fma for + // 1/16 <= n/d <= 1. + // atan(n/d) - atan(idx/16) = atan((n/d - idx/16) / (1 + (n/d) * (idx/16))) + // = atan((n - d*(idx/16)) / (d + n*idx/16)) + k_d *= 0x1.0p-4; + num_r = fputil::multiply_add(k_d, -den_d, num_d); // Exact + den_r = fputil::multiply_add(k_d, num_d, den_d); // Exact + q.hi = num_r / den_r; + } else { + // For 0 < n/d < 1/16, we just need to calculate the lower part of their + // quotient. + q.hi = q_d; + num_r = num_d; + den_r = den_d; + } +#ifdef LIBC_TARGET_CPU_HAS_FMA + q.lo = fputil::multiply_add(q.hi, -den_r, num_r) / den_r; +#else + // Compute `(num_r - q.hi * den_r) / den_r` accurately without FMA + // instructions. + fputil::DoubleDouble q_hi_dd = split_d(q.hi); + double t1 = fputil::multiply_add(q_hi_dd.hi, -den_r, num_r); // Exact + double t2 = fputil::multiply_add(q_hi_dd.lo, -den_r, t1); + q.lo = t2 / den_r; +#endif // LIBC_TARGET_CPU_HAS_FMA + + // Taylor polynomial, evaluating using Horner's scheme: + // P = x - x^3/3 + x^5/5 -x^7/7 + x^9/9 - x^11/11 + x^13/13 - x^15/15 + // + x^17/17 + // = x*(1 + x^2*(-1/3 + x^2*(1/5 + x^2*(-1/7 + x^2*(1/9 + x^2* + // *(-1/11 + x^2*(1/13 + x^2*(-1/15 + x^2 * 1/17)))))))) + fputil::DoubleDouble q2 = fputil::quick_mult(q, q); + fputil::DoubleDouble p_dd = + fputil::polyeval(q2, COEFFS[0], COEFFS[1], COEFFS[2], COEFFS[3], + COEFFS[4], COEFFS[5], COEFFS[6], COEFFS[7], COEFFS[8]); + fputil::DoubleDouble r_dd = + fputil::add(const_term, fputil::multiply_add(q, p_dd, ATAN_I[idx])); + r_dd.hi *= final_sign; + r_dd.lo *= final_sign; + + // Make sure the sum is normalized: + fputil::DoubleDouble rr = fputil::exact_add(r_dd.hi, r_dd.lo); + // Round to odd. + uint64_t rr_bits = cpp::bit_cast<uint64_t>(rr.hi); + if (LIBC_UNLIKELY(((rr_bits & 0xfff'ffff) == 0) && (rr.lo != 0.0))) { + Sign hi_sign = fputil::FPBits<double>(rr.hi).sign(); + Sign lo_sign = fputil::FPBits<double>(rr.lo).sign(); + if (hi_sign == lo_sign) { + ++rr_bits; + } else if ((rr_bits & fputil::FPBits<double>::FRACTION_MASK) > 0) { + --rr_bits; + } + } + + return static_cast<float>(cpp::bit_cast<double>(rr_bits)); +} + +} // anonymous namespace + +// There are several range reduction steps we can take for atan2(y, x) as +// follow: + +// * Range reduction 1: signness +// atan2(y, x) will return a number between -PI and PI representing the angle +// forming by the 0x axis and the vector (x, y) on the 0xy-plane. +// In particular, we have that: +// atan2(y, x) = atan( y/x ) if x >= 0 and y >= 0 (I-quadrant) +// = pi + atan( y/x ) if x < 0 and y >= 0 (II-quadrant) +// = -pi + atan( y/x ) if x < 0 and y < 0 (III-quadrant) +// = atan( y/x ) if x >= 0 and y < 0 (IV-quadrant) +// Since atan function is odd, we can use the formula: +// atan(-u) = -atan(u) +// to adjust the above conditions a bit further: +// atan2(y, x) = atan( |y|/|x| ) if x >= 0 and y >= 0 (I-quadrant) +// = pi - atan( |y|/|x| ) if x < 0 and y >= 0 (II-quadrant) +// = -pi + atan( |y|/|x| ) if x < 0 and y < 0 (III-quadrant) +// = -atan( |y|/|x| ) if x >= 0 and y < 0 (IV-quadrant) +// Which can be simplified to: +// atan2(y, x) = sign(y) * atan( |y|/|x| ) if x >= 0 +// = sign(y) * (pi - atan( |y|/|x| )) if x < 0 + +// * Range reduction 2: reciprocal +// Now that the argument inside atan is positive, we can use the formula: +// atan(1/x) = pi/2 - atan(x) +// to make the argument inside atan <= 1 as follow: +// atan2(y, x) = sign(y) * atan( |y|/|x|) if 0 <= |y| <= x +// = sign(y) * (pi/2 - atan( |x|/|y| ) if 0 <= x < |y| +// = sign(y) * (pi - atan( |y|/|x| )) if 0 <= |y| <= -x +// = sign(y) * (pi/2 + atan( |x|/|y| )) if 0 <= -x < |y| + +// * Range reduction 3: look up table. +// After the previous two range reduction steps, we reduce the problem to +// compute atan(u) with 0 <= u <= 1, or to be precise: +// atan( n / d ) where n = min(|x|, |y|) and d = max(|x|, |y|). +// An accurate polynomial approximation for the whole [0, 1] input range will +// require a very large degree. To make it more efficient, we reduce the input +// range further by finding an integer idx such that: +// | n/d - idx/16 | <= 1/32. +// In particular, +// idx := 2^-4 * round(2^4 * n/d) +// Then for the fast pass, we find a polynomial approximation for: +// atan( n/d ) ~ atan( idx/16 ) + (n/d - idx/16) * Q(n/d - idx/16) +// For the accurate pass, we use the addition formula: +// atan( n/d ) - atan( idx/16 ) = atan( (n/d - idx/16)/(1 + (n*idx)/(16*d)) ) +// = atan( (n - d * idx/16)/(d + n * idx/16) ) +// And finally we use Taylor polynomial to compute the RHS in the accurate pass: +// atan(u) ~ P(u) = u - u^3/3 + u^5/5 - u^7/7 + u^9/9 - u^11/11 + u^13/13 - +// - u^15/15 + u^17/17 +// It's error in double-double precision is estimated in Sollya to be: +// > P = x - x^3/3 + x^5/5 -x^7/7 + x^9/9 - x^11/11 + x^13/13 - x^15/15 +// + x^17/17; +// > dirtyinfnorm(atan(x) - P, [-2^-5, 2^-5]); +// 0x1.aec6f...p-100 +// which is about rounding errors of double-double (2^-104). + +LLVM_LIBC_FUNCTION(float, atan2f, (float y, float x)) { + using FPBits = typename fputil::FPBits<float>; + constexpr double IS_NEG[2] = {1.0, -1.0}; + constexpr double PI = 0x1.921fb54442d18p1; + constexpr double PI_LO = 0x1.1a62633145c07p-53; + constexpr double PI_OVER_4 = 0x1.921fb54442d18p-1; + constexpr double PI_OVER_2 = 0x1.921fb54442d18p0; + constexpr double THREE_PI_OVER_4 = 0x1.2d97c7f3321d2p+1; + // Adjustment for constant term: + // CONST_ADJ[x_sign][y_sign][recip] + constexpr fputil::DoubleDouble CONST_ADJ[2][2][2] = { + {{{0.0, 0.0}, {-PI_LO / 2, -PI_OVER_2}}, + {{-0.0, -0.0}, {-PI_LO / 2, -PI_OVER_2}}}, + {{{-PI_LO, -PI}, {PI_LO / 2, PI_OVER_2}}, + {{-PI_LO, -PI}, {PI_LO / 2, PI_OVER_2}}}}; + + FPBits x_bits(x), y_bits(y); + bool x_sign = x_bits.sign().is_neg(); + bool y_sign = y_bits.sign().is_neg(); + x_bits.set_sign(Sign::POS); + y_bits.set_sign(Sign::POS); + uint32_t x_abs = x_bits.uintval(); + uint32_t y_abs = y_bits.uintval(); + uint32_t max_abs = x_abs > y_abs ? x_abs : y_abs; + uint32_t min_abs = x_abs <= y_abs ? x_abs : y_abs; + + if (LIBC_UNLIKELY(max_abs >= 0x7f80'0000U || min_abs == 0U)) { + if (x_bits.is_nan() || y_bits.is_nan()) + return FPBits::quiet_nan().get_val(); + size_t x_except = x_abs == 0 ? 0 : (x_abs == 0x7f80'0000 ? 2 : 1); + size_t y_except = y_abs == 0 ? 0 : (y_abs == 0x7f80'0000 ? 2 : 1); + + // Exceptional cases: + // EXCEPT[y_except][x_except][x_is_neg] + // with x_except & y_except: + // 0: zero + // 1: finite, non-zero + // 2: infinity + constexpr double EXCEPTS[3][3][2] = { + {{0.0, PI}, {0.0, PI}, {0.0, PI}}, + {{PI_OVER_2, PI_OVER_2}, {0.0, 0.0}, {0.0, PI}}, + {{PI_OVER_2, PI_OVER_2}, + {PI_OVER_2, PI_OVER_2}, + {PI_OVER_4, THREE_PI_OVER_4}}, + }; + + double r = IS_NEG[y_sign] * EXCEPTS[y_except][x_except][x_sign]; + + return static_cast<float>(r); + } + + bool recip = x_abs < y_abs; + double final_sign = IS_NEG[(x_sign != y_sign) != recip]; + fputil::DoubleDouble const_term = CONST_ADJ[x_sign][y_sign][recip]; + double num_d = static_cast<double>(FPBits(min_abs).get_val()); + double den_d = static_cast<double>(FPBits(max_abs).get_val()); + double q_d = num_d / den_d; + + double k_d = fputil::nearest_integer(q_d * 0x1.0p4f); + int idx = static_cast<int>(k_d); + q_d = fputil::multiply_add(k_d, -0x1.0p-4, q_d); + + double p = atan_eval(q_d, idx); + double r = final_sign * + fputil::multiply_add(q_d, p, const_term.hi + ATAN_COEFFS[idx][0]); + + constexpr uint32_t LOWER_ERR = 4; + // Mask sticky bits in double precision before rounding to single precision. + constexpr uint32_t MASK = + mask_trailing_ones<uint32_t, fputil::FPBits<double>::SIG_LEN - + FPBits::SIG_LEN - 1>(); + constexpr uint32_t UPPER_ERR = MASK - LOWER_ERR; + + uint32_t r_bits = static_cast<uint32_t>(cpp::bit_cast<uint64_t>(r)) & MASK; + + // Ziv's rounding test. + if (LIBC_LIKELY(r_bits > LOWER_ERR && r_bits < UPPER_ERR)) + return static_cast<float>(r); + + return atan2f_double_double(num_d, den_d, q_d, idx, k_d, final_sign, + const_term); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/atanf.cpp b/libc/src/math/generic/atanf.cpp index e0f8a1bfc2ecc9d0bba73d167b0a26f211c71731..9fa1a331c9c038dd077bdf8dec075824d84b3cdf 100644 --- a/libc/src/math/generic/atanf.cpp +++ b/libc/src/math/generic/atanf.cpp @@ -7,60 +7,114 @@ //===----------------------------------------------------------------------===// #include "src/math/atanf.h" -#include "math_utils.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" +#include "src/__support/FPUtil/multiply_add.h" +#include "src/__support/FPUtil/nearest_integer.h" #include "src/__support/FPUtil/rounding_mode.h" #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY -#include "src/math/generic/inv_trigf_utils.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(float, atanf, (float x)) { using FPBits = typename fputil::FPBits<float>; - using Sign = fputil::Sign; - // x == 0.0 - if (LIBC_UNLIKELY(x == 0.0f)) - return x; + constexpr double FINAL_SIGN[2] = {1.0, -1.0}; + constexpr double SIGNED_PI_OVER_2[2] = {0x1.921fb54442d18p0, + -0x1.921fb54442d18p0}; - FPBits xbits(x); - Sign sign = xbits.sign(); - xbits.set_sign(Sign::POS); + FPBits x_bits(x); + Sign sign = x_bits.sign(); + x_bits.set_sign(Sign::POS); + uint32_t x_abs = x_bits.uintval(); - if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) { - if (xbits.is_inf()) - return static_cast<float>( - opt_barrier(sign.is_neg() ? -M_MATH_PI_2 : M_MATH_PI_2)); - else + // x is inf or nan, |x| < 2^-4 or |x|= > 16. + if (LIBC_UNLIKELY(x_abs <= 0x3d80'0000U || x_abs >= 0x4180'0000U)) { + double x_d = static_cast<double>(x); + double const_term = 0.0; + if (LIBC_UNLIKELY(x_abs >= 0x4180'0000)) { + // atan(+-Inf) = +-pi/2. + if (x_bits.is_inf()) { + volatile double sign_pi_over_2 = SIGNED_PI_OVER_2[sign.is_neg()]; + return static_cast<float>(sign_pi_over_2); + } + if (x_bits.is_nan()) + return x; + // x >= 16 + x_d = -1.0 / x_d; + const_term = SIGNED_PI_OVER_2[sign.is_neg()]; + } + // 0 <= x < 1/16; + if (LIBC_UNLIKELY(x_bits.is_zero())) return x; - } - // |x| == 0.06905200332403183 - if (LIBC_UNLIKELY(xbits.uintval() == 0x3d8d6b23U)) { - if (fputil::fenv_is_round_to_nearest()) { - // 0.06894256919622421 - FPBits br(0x3d8d31c3U); - br.set_sign(sign); - return br.get_val(); + // x <= 2^-12; + if (LIBC_UNLIKELY(x_abs < 0x3980'0000)) { +#if defined(LIBC_TARGET_CPU_HAS_FMA) + return fputil::multiply_add(x, -0x1.0p-25f, x); +#else + double x_d = static_cast<double>(x); + return static_cast<float>(fputil::multiply_add(x_d, -0x1.0p-25, x_d)); +#endif // LIBC_TARGET_CPU_HAS_FMA } + // Use Taylor polynomial: + // atan(x) ~ x * (1 - x^2 / 3 + x^4 / 5 - x^6 / 7 + x^8 / 9 - x^10 / 11). + constexpr double ATAN_TAYLOR[6] = { + 0x1.0000000000000p+0, -0x1.5555555555555p-2, 0x1.999999999999ap-3, + -0x1.2492492492492p-3, 0x1.c71c71c71c71cp-4, -0x1.745d1745d1746p-4, + }; + double x2 = x_d * x_d; + double x4 = x2 * x2; + double c0 = fputil::multiply_add(x2, ATAN_TAYLOR[1], ATAN_TAYLOR[0]); + double c1 = fputil::multiply_add(x2, ATAN_TAYLOR[3], ATAN_TAYLOR[2]); + double c2 = fputil::multiply_add(x2, ATAN_TAYLOR[5], ATAN_TAYLOR[4]); + double p = fputil::polyeval(x4, c0, c1, c2); + double r = fputil::multiply_add(x_d, p, const_term); + return static_cast<float>(r); } - // |x| == 1.8670953512191772 - if (LIBC_UNLIKELY(xbits.uintval() == 0x3feefcfbU)) { - int rounding_mode = fputil::quick_get_round(); - if (sign.is_neg()) { - if (rounding_mode == FE_DOWNWARD) { - // -1.0790828466415405 - return FPBits(0xbf8a1f63U).get_val(); - } - } else { - if (rounding_mode == FE_UPWARD) { - // 1.0790828466415405 - return FPBits(0x3f8a1f63U).get_val(); - } + // Range reduction steps: + // 1) atan(x) = sign(x) * atan(|x|) + // 2) If |x| > 1, atan(|x|) = pi/2 - atan(1/|x|) + // 3) For 1/16 < x <= 1, we find k such that: |x - k/16| <= 1/32. + // 4) Then we use polynomial approximation: + // atan(x) ~ atan((k/16) + (x - (k/16)) * Q(x - k/16) + // = P(x - k/16) + double x_d, const_term, final_sign; + int idx; + + if (x_abs > 0x3f80'0000U) { + // |x| > 1, we need to invert x, so we will perform range reduction in + // double precision. + x_d = 1.0 / static_cast<double>(x_bits.get_val()); + double k_d = fputil::nearest_integer(x_d * 0x1.0p4); + x_d = fputil::multiply_add(k_d, -0x1.0p-4, x_d); + idx = static_cast<int>(k_d); + final_sign = FINAL_SIGN[sign.is_pos()]; + // Adjust constant term of the polynomial by +- pi/2. + const_term = fputil::multiply_add(final_sign, ATAN_COEFFS[idx][0], + SIGNED_PI_OVER_2[sign.is_neg()]); + } else { + // Exceptional value: + if (LIBC_UNLIKELY(x_abs == 0x3d8d'6b23U)) { // |x| = 0x1.1ad646p-4 + return sign.is_pos() ? fputil::round_result_slightly_down(0x1.1a6386p-4f) + : fputil::round_result_slightly_up(-0x1.1a6386p-4f); } + // Perform range reduction in single precision. + float x_f = x_bits.get_val(); + float k_f = fputil::nearest_integer(x_f * 0x1.0p4f); + x_f = fputil::multiply_add(k_f, -0x1.0p-4f, x_f); + x_d = static_cast<double>(x_f); + idx = static_cast<int>(k_f); + final_sign = FINAL_SIGN[sign.is_neg()]; + const_term = final_sign * ATAN_COEFFS[idx][0]; } - return static_cast<float>(atan_eval(x)); + double p = atan_eval(x_d, idx); + double r = fputil::multiply_add(final_sign * x_d, p, const_term); + + return static_cast<float>(r); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/atanhf.cpp b/libc/src/math/generic/atanhf.cpp index fe2c36494a72f8b3fcb8910a6a806dd7ff97c099..97fd1b2336006704f15d12e8010453c4fec138f4 100644 --- a/libc/src/math/generic/atanhf.cpp +++ b/libc/src/math/generic/atanhf.cpp @@ -15,7 +15,7 @@ namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(float, atanhf, (float x)) { using FPBits = typename fputil::FPBits<float>; - using Sign = fputil::Sign; + FPBits xbits(x); Sign sign = xbits.sign(); uint32_t x_abs = xbits.abs().uintval(); diff --git a/libc/src/math/generic/canonicalize.cpp b/libc/src/math/generic/canonicalize.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f38ca01e157f888f4d7839efc969841d68d3225a --- /dev/null +++ b/libc/src/math/generic/canonicalize.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of canonicalize function----------------------------===// +// +// 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/math/canonicalize.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, canonicalize, (double *cx, const double *x)) { + return fputil::canonicalize(*cx, *x); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/canonicalizef.cpp b/libc/src/math/generic/canonicalizef.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dce601de14914099eb2f714531f9ebada89a6a81 --- /dev/null +++ b/libc/src/math/generic/canonicalizef.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of canonicalizef function---------------------------===// +// +// 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/math/canonicalizef.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, canonicalizef, (float *cx, const float *x)) { + return fputil::canonicalize(*cx, *x); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/canonicalizef128.cpp b/libc/src/math/generic/canonicalizef128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0078b478238cb7ba988ba96ef398f9c11152a24e --- /dev/null +++ b/libc/src/math/generic/canonicalizef128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of canonicalizef128 function------------------------===// +// +// 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/math/canonicalizef128.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, canonicalizef128, (float128 * cx, const float128 *x)) { + return fputil::canonicalize(*cx, *x); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/canonicalizel.cpp b/libc/src/math/generic/canonicalizel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5310a316acdd3fb565191404836c99d3ce680a46 --- /dev/null +++ b/libc/src/math/generic/canonicalizel.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of canonicalizel function---------------------------===// +// +// 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/math/canonicalizel.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, canonicalizel, + (long double *cx, const long double *x)) { + return fputil::canonicalize(*cx, *x); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/cosf.cpp b/libc/src/math/generic/cosf.cpp index d59304933d60d89d15d8e3757f96cd64b0e2b7d9..180a44e947eaffd2c8da337830d584fd03fe23b1 100644 --- a/libc/src/math/generic/cosf.cpp +++ b/libc/src/math/generic/cosf.cpp @@ -42,7 +42,7 @@ static constexpr fputil::ExceptValues<float, N_EXCEPTS> COSF_EXCEPTS{{ LLVM_LIBC_FUNCTION(float, cosf, (float x)) { using FPBits = typename fputil::FPBits<float>; - using Sign = fputil::Sign; + FPBits xbits(x); xbits.set_sign(Sign::POS); diff --git a/libc/src/math/generic/coshf.cpp b/libc/src/math/generic/coshf.cpp index a618056a64dc8a3494eb8a51f726c1374550b1e7..a8ea324c950528869a555265bbac0b9022bbe029 100644 --- a/libc/src/math/generic/coshf.cpp +++ b/libc/src/math/generic/coshf.cpp @@ -17,7 +17,7 @@ namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(float, coshf, (float x)) { using FPBits = typename fputil::FPBits<float>; - using Sign = fputil::Sign; + FPBits xbits(x); xbits.set_sign(Sign::POS); x = xbits.get_val(); diff --git a/libc/src/math/generic/exp.cpp b/libc/src/math/generic/exp.cpp index 42a4491131a04ed5016a93de982495b2643c6838..3d060bcbd3be30fcc58d7c1e4ee34a7c35e9ffdf 100644 --- a/libc/src/math/generic/exp.cpp +++ b/libc/src/math/generic/exp.cpp @@ -31,7 +31,7 @@ namespace LIBC_NAMESPACE { using fputil::DoubleDouble; using fputil::TripleDouble; using Float128 = typename fputil::DyadicFloat<128>; -using Sign = fputil::Sign; + using LIBC_NAMESPACE::operator""_u128; // log2(e) diff --git a/libc/src/math/generic/exp10.cpp b/libc/src/math/generic/exp10.cpp index 72ece6697656886fbbfebaba6cb2a69354af8871..a4ae41407112bd8c619edfe31f2c93bdf903f06a 100644 --- a/libc/src/math/generic/exp10.cpp +++ b/libc/src/math/generic/exp10.cpp @@ -31,7 +31,7 @@ namespace LIBC_NAMESPACE { using fputil::DoubleDouble; using fputil::TripleDouble; using Float128 = typename fputil::DyadicFloat<128>; -using Sign = fputil::Sign; + using LIBC_NAMESPACE::operator""_u128; // log2(10) diff --git a/libc/src/math/generic/exp2.cpp b/libc/src/math/generic/exp2.cpp index 83f545eb116bd3972cf6e0aa5ed5384914ac742f..1a2fa3feb83e54b45d8432f64285fa6c473c06cc 100644 --- a/libc/src/math/generic/exp2.cpp +++ b/libc/src/math/generic/exp2.cpp @@ -31,7 +31,7 @@ namespace LIBC_NAMESPACE { using fputil::DoubleDouble; using fputil::TripleDouble; using Float128 = typename fputil::DyadicFloat<128>; -using Sign = fputil::Sign; + using LIBC_NAMESPACE::operator""_u128; // Error bounds: diff --git a/libc/src/math/generic/expm1.cpp b/libc/src/math/generic/expm1.cpp index 9f14a8c2068ec1924f2577b418180b1d8019302b..574c4b9aaf39f7df9e4e1eed4a36de096602e392 100644 --- a/libc/src/math/generic/expm1.cpp +++ b/libc/src/math/generic/expm1.cpp @@ -39,7 +39,7 @@ namespace LIBC_NAMESPACE { using fputil::DoubleDouble; using fputil::TripleDouble; using Float128 = typename fputil::DyadicFloat<128>; -using Sign = fputil::Sign; + using LIBC_NAMESPACE::operator""_u128; // log2(e) @@ -276,7 +276,7 @@ double set_exceptional(double x) { LLVM_LIBC_FUNCTION(double, expm1, (double x)) { using FPBits = typename fputil::FPBits<double>; - using Sign = fputil::Sign; + FPBits xbits(x); bool x_is_neg = xbits.is_neg(); diff --git a/libc/src/math/generic/fmaximum.cpp b/libc/src/math/generic/fmaximum.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac9593b325d4bf1108bd97c014705e1f389a074b --- /dev/null +++ b/libc/src/math/generic/fmaximum.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fmaximum function--------------------------------===// +// +// 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/math/fmaximum.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(double, fmaximum, (double x, double y)) { + return fputil::fmaximum(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmaximum_mag.cpp b/libc/src/math/generic/fmaximum_mag.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0deb0c2835f932bdd4503497493456e1c9e49f13 --- /dev/null +++ b/libc/src/math/generic/fmaximum_mag.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fmaximum_mag function----------------------------===// +// +// 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/math/fmaximum_mag.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(double, fmaximum_mag, (double x, double y)) { + return fputil::fmaximum_mag(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmaximum_mag_num.cpp b/libc/src/math/generic/fmaximum_mag_num.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d0b1096b88bc66e9e5b831f9db89c8c96856afae --- /dev/null +++ b/libc/src/math/generic/fmaximum_mag_num.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fmaximum_mag_num function------------------------===// +// +// 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/math/fmaximum_mag_num.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(double, fmaximum_mag_num, (double x, double y)) { + return fputil::fmaximum_mag_num(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmaximum_mag_numf.cpp b/libc/src/math/generic/fmaximum_mag_numf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..672d3fd3b263a4d6dd42d27d655c6fb4e8e13405 --- /dev/null +++ b/libc/src/math/generic/fmaximum_mag_numf.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fmaximum_mag_numf function-----------------------===// +// +// 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/math/fmaximum_mag_numf.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float, fmaximum_mag_numf, (float x, float y)) { + return fputil::fmaximum_mag_num(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmaximum_mag_numf128.cpp b/libc/src/math/generic/fmaximum_mag_numf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e7d13f13a098261ddc9126f27408a84417ac23e3 --- /dev/null +++ b/libc/src/math/generic/fmaximum_mag_numf128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fmaximum_mag_numf128 function--------------------===// +// +// 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/math/fmaximum_mag_numf128.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, fmaximum_mag_numf128, (float128 x, float128 y)) { + return fputil::fmaximum_mag_num(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmaximum_mag_numl.cpp b/libc/src/math/generic/fmaximum_mag_numl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a8499ca473b36560c2bd250bfaeeff91cc4980c8 --- /dev/null +++ b/libc/src/math/generic/fmaximum_mag_numl.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of fmaximum_mag_numl function-----------------------===// +// +// 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/math/fmaximum_mag_numl.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long double, fmaximum_mag_numl, + (long double x, long double y)) { + return fputil::fmaximum_mag_num(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmaximum_magf.cpp b/libc/src/math/generic/fmaximum_magf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..380aca05a5255cc3ddd5ae7b53bfc5d83421e4cc --- /dev/null +++ b/libc/src/math/generic/fmaximum_magf.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fmaximum_magf function---------------------------===// +// +// 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/math/fmaximum_magf.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float, fmaximum_magf, (float x, float y)) { + return fputil::fmaximum_mag(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmaximum_magf128.cpp b/libc/src/math/generic/fmaximum_magf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..301938fb7ffd3efec941c25b48184ca7772c04dd --- /dev/null +++ b/libc/src/math/generic/fmaximum_magf128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fmaximum_magf128 function------------------------===// +// +// 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/math/fmaximum_magf128.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, fmaximum_magf128, (float128 x, float128 y)) { + return fputil::fmaximum_mag(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmaximum_magl.cpp b/libc/src/math/generic/fmaximum_magl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..283a11eda9aab615b847e0f7c3387b6db670715b --- /dev/null +++ b/libc/src/math/generic/fmaximum_magl.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fmaximum_magl function---------------------------===// +// +// 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/math/fmaximum_magl.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long double, fmaximum_magl, (long double x, long double y)) { + return fputil::fmaximum_mag(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmaximum_num.cpp b/libc/src/math/generic/fmaximum_num.cpp new file mode 100644 index 0000000000000000000000000000000000000000..23553dbcae7edbec7f8c67a45f6ba30f13925a7a --- /dev/null +++ b/libc/src/math/generic/fmaximum_num.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fmaximum_num function----------------------------===// +// +// 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/math/fmaximum_num.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(double, fmaximum_num, (double x, double y)) { + return fputil::fmaximum_num(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmaximum_numf.cpp b/libc/src/math/generic/fmaximum_numf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f946ff43f543cab3dcc3e56fa7de6aaeb6d25f13 --- /dev/null +++ b/libc/src/math/generic/fmaximum_numf.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fmaximum_numf function---------------------------===// +// +// 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/math/fmaximum_numf.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float, fmaximum_numf, (float x, float y)) { + return fputil::fmaximum_num(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmaximum_numf128.cpp b/libc/src/math/generic/fmaximum_numf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f33a5e195bf25ff9352f2283ba16a9d551692b09 --- /dev/null +++ b/libc/src/math/generic/fmaximum_numf128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fmaximum_numf128 function------------------------===// +// +// 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/math/fmaximum_numf128.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, fmaximum_numf128, (float128 x, float128 y)) { + return fputil::fmaximum_num(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmaximum_numl.cpp b/libc/src/math/generic/fmaximum_numl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..503fc41409f683f24d5ab5bb940badad55d445c2 --- /dev/null +++ b/libc/src/math/generic/fmaximum_numl.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fmaximum_numl function---------------------------===// +// +// 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/math/fmaximum_numl.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long double, fmaximum_numl, (long double x, long double y)) { + return fputil::fmaximum_num(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmaximumf.cpp b/libc/src/math/generic/fmaximumf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3b2a60931bf630f5d8a850ba4f6972a7eff97d39 --- /dev/null +++ b/libc/src/math/generic/fmaximumf.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fmaximumf function-------------------------------===// +// +// 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/math/fmaximumf.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float, fmaximumf, (float x, float y)) { + return fputil::fmaximum(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmaximumf128.cpp b/libc/src/math/generic/fmaximumf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0099c913b05261cf4dd4d99f74c0eee969a3f461 --- /dev/null +++ b/libc/src/math/generic/fmaximumf128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fmaximumf128 function----------------------------===// +// +// 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/math/fmaximumf128.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, fmaximumf128, (float128 x, float128 y)) { + return fputil::fmaximum(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmaximuml.cpp b/libc/src/math/generic/fmaximuml.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ecd698300458f1084a7258b2a08612fd412ff74b --- /dev/null +++ b/libc/src/math/generic/fmaximuml.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fmaximuml function-------------------------------===// +// +// 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/math/fmaximuml.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long double, fmaximuml, (long double x, long double y)) { + return fputil::fmaximum(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fminimum.cpp b/libc/src/math/generic/fminimum.cpp new file mode 100644 index 0000000000000000000000000000000000000000..28b257d950f4393d42a1857278628ed651d5f9b6 --- /dev/null +++ b/libc/src/math/generic/fminimum.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fminimum function--------------------------------===// +// +// 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/math/fminimum.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(double, fminimum, (double x, double y)) { + return fputil::fminimum(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fminimum_mag.cpp b/libc/src/math/generic/fminimum_mag.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6af99570e1ea4e3f8ab24a62eeaeb3876efb782f --- /dev/null +++ b/libc/src/math/generic/fminimum_mag.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fminimum_mag function----------------------------===// +// +// 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/math/fminimum_mag.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(double, fminimum_mag, (double x, double y)) { + return fputil::fminimum_mag(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fminimum_mag_num.cpp b/libc/src/math/generic/fminimum_mag_num.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fc5431ae27994294cc2bb3c1a03f66dbdc2d5f28 --- /dev/null +++ b/libc/src/math/generic/fminimum_mag_num.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fminimum_mag_num function------------------------===// +// +// 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/math/fminimum_mag_num.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(double, fminimum_mag_num, (double x, double y)) { + return fputil::fminimum_mag_num(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fminimum_mag_numf.cpp b/libc/src/math/generic/fminimum_mag_numf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..71179a6f03c2131410cf753d5753db6e8d65ab2c --- /dev/null +++ b/libc/src/math/generic/fminimum_mag_numf.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fminimum_mag_numf function-----------------------===// +// +// 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/math/fminimum_mag_numf.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float, fminimum_mag_numf, (float x, float y)) { + return fputil::fminimum_mag_num(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fminimum_mag_numf128.cpp b/libc/src/math/generic/fminimum_mag_numf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..109ce7e4e0111b018602878ebac365d0979fce6c --- /dev/null +++ b/libc/src/math/generic/fminimum_mag_numf128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fminimum_mag_numf128 function--------------------===// +// +// 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/math/fminimum_mag_numf128.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, fminimum_mag_numf128, (float128 x, float128 y)) { + return fputil::fminimum_mag_num(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fminimum_mag_numl.cpp b/libc/src/math/generic/fminimum_mag_numl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c97ce6ead0425b2873a1403bcd046b0ab434b27c --- /dev/null +++ b/libc/src/math/generic/fminimum_mag_numl.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of fminimum_mag_numl function-----------------------===// +// +// 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/math/fminimum_mag_numl.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long double, fminimum_mag_numl, + (long double x, long double y)) { + return fputil::fminimum_mag_num(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fminimum_magf.cpp b/libc/src/math/generic/fminimum_magf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..834f6a4a97101a57ac0c2fc52c6e3a86426a8791 --- /dev/null +++ b/libc/src/math/generic/fminimum_magf.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fminimum_magf function---------------------------===// +// +// 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/math/fminimum_magf.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float, fminimum_magf, (float x, float y)) { + return fputil::fminimum_mag(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fminimum_magf128.cpp b/libc/src/math/generic/fminimum_magf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2828e28bb0a4012f0445123ff5005866b433dd9f --- /dev/null +++ b/libc/src/math/generic/fminimum_magf128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fminimum_magf128 function------------------------===// +// +// 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/math/fminimum_magf128.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, fminimum_magf128, (float128 x, float128 y)) { + return fputil::fminimum_mag(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fminimum_magl.cpp b/libc/src/math/generic/fminimum_magl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..50e328fd92d1f9aef36701d053006704eb7d0cad --- /dev/null +++ b/libc/src/math/generic/fminimum_magl.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fminimum_magl function---------------------------===// +// +// 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/math/fminimum_magl.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long double, fminimum_magl, (long double x, long double y)) { + return fputil::fminimum_mag(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fminimum_num.cpp b/libc/src/math/generic/fminimum_num.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e89c7f5acf9b18dd5e6ececae8600ffa4747e47c --- /dev/null +++ b/libc/src/math/generic/fminimum_num.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fminimum_num function----------------------------===// +// +// 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/math/fminimum_num.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(double, fminimum_num, (double x, double y)) { + return fputil::fminimum_num(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fminimum_numf.cpp b/libc/src/math/generic/fminimum_numf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c37c8bd423a1a6986a8ff44d30c0e8ee2124d7ea --- /dev/null +++ b/libc/src/math/generic/fminimum_numf.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fminimum_numf function---------------------------===// +// +// 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/math/fminimum_numf.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float, fminimum_numf, (float x, float y)) { + return fputil::fminimum_num(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fminimum_numf128.cpp b/libc/src/math/generic/fminimum_numf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6b1f77bb447cf8669393c760a9fe8a4a2cf289c1 --- /dev/null +++ b/libc/src/math/generic/fminimum_numf128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fminimum_numf128 function------------------------===// +// +// 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/math/fminimum_numf128.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, fminimum_numf128, (float128 x, float128 y)) { + return fputil::fminimum_num(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fminimum_numl.cpp b/libc/src/math/generic/fminimum_numl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..22045f83f2a733f1d2205b892ded695cd36afe60 --- /dev/null +++ b/libc/src/math/generic/fminimum_numl.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fminimum_numl function---------------------------===// +// +// 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/math/fminimum_numl.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long double, fminimum_numl, (long double x, long double y)) { + return fputil::fminimum_num(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fminimumf.cpp b/libc/src/math/generic/fminimumf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c937fb0ea01d0d9cbf4bc99c3804cae7f70a7cf2 --- /dev/null +++ b/libc/src/math/generic/fminimumf.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fminimumf function-------------------------------===// +// +// 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/math/fminimumf.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float, fminimumf, (float x, float y)) { + return fputil::fminimum(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fminimumf128.cpp b/libc/src/math/generic/fminimumf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..24e02b8ff537f05f4c147970574b6dbde71cd9ab --- /dev/null +++ b/libc/src/math/generic/fminimumf128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fminimumf128 function----------------------------===// +// +// 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/math/fminimumf128.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, fminimumf128, (float128 x, float128 y)) { + return fputil::fminimum(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fminimuml.cpp b/libc/src/math/generic/fminimuml.cpp new file mode 100644 index 0000000000000000000000000000000000000000..43319503661aae7c1eeabd316a16d96816a9f405 --- /dev/null +++ b/libc/src/math/generic/fminimuml.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fminimuml function-------------------------------===// +// +// 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/math/fminimuml.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long double, fminimuml, (long double x, long double y)) { + return fputil::fminimum(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fromfp.cpp b/libc/src/math/generic/fromfp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ba3f0a133cbcb9cf081c5b0b101757bbea63463a --- /dev/null +++ b/libc/src/math/generic/fromfp.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fromfp function ---------------------------------===// +// +// 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/math/fromfp.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(double, fromfp, (double x, int rnd, unsigned int width)) { + return fputil::fromfp</*IsSigned=*/true>(x, rnd, width); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fromfpf.cpp b/libc/src/math/generic/fromfpf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fd058a13201c90c0c8dd3a11b83271208af06516 --- /dev/null +++ b/libc/src/math/generic/fromfpf.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fromfpf function --------------------------------===// +// +// 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/math/fromfpf.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float, fromfpf, (float x, int rnd, unsigned int width)) { + return fputil::fromfp</*IsSigned=*/true>(x, rnd, width); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fromfpf128.cpp b/libc/src/math/generic/fromfpf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..440a5da756932b8f9218cb4cebd5c89cfc28e041 --- /dev/null +++ b/libc/src/math/generic/fromfpf128.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of fromfpf128 function -----------------------------===// +// +// 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/math/fromfpf128.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, fromfpf128, + (float128 x, int rnd, unsigned int width)) { + return fputil::fromfp</*IsSigned=*/true>(x, rnd, width); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fromfpl.cpp b/libc/src/math/generic/fromfpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee3abeaf98f8560c5ecda8f6c0527bc77defedcd --- /dev/null +++ b/libc/src/math/generic/fromfpl.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of fromfpl function --------------------------------===// +// +// 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/math/fromfpl.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long double, fromfpl, + (long double x, int rnd, unsigned int width)) { + return fputil::fromfp</*IsSigned=*/true>(x, rnd, width); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fromfpx.cpp b/libc/src/math/generic/fromfpx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b9e7e4a7aa12621f23c77506888d5ee0a71286e7 --- /dev/null +++ b/libc/src/math/generic/fromfpx.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fromfpx function --------------------------------===// +// +// 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/math/fromfpx.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(double, fromfpx, (double x, int rnd, unsigned int width)) { + return fputil::fromfpx</*IsSigned=*/true>(x, rnd, width); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fromfpxf.cpp b/libc/src/math/generic/fromfpxf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1473499244d318cbed06e08bd0544c95469b911b --- /dev/null +++ b/libc/src/math/generic/fromfpxf.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of fromfpxf function -------------------------------===// +// +// 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/math/fromfpxf.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float, fromfpxf, (float x, int rnd, unsigned int width)) { + return fputil::fromfpx</*IsSigned=*/true>(x, rnd, width); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fromfpxf128.cpp b/libc/src/math/generic/fromfpxf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5d930d22ae5eb1770b5933ef9d3318b7068595ef --- /dev/null +++ b/libc/src/math/generic/fromfpxf128.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of fromfpxf128 function ----------------------------===// +// +// 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/math/fromfpxf128.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, fromfpxf128, + (float128 x, int rnd, unsigned int width)) { + return fputil::fromfpx</*IsSigned=*/true>(x, rnd, width); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fromfpxl.cpp b/libc/src/math/generic/fromfpxl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c3db055246f227e9d28e96424c81ba24bb54fcc5 --- /dev/null +++ b/libc/src/math/generic/fromfpxl.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of fromfpxl function -------------------------------===// +// +// 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/math/fromfpxl.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long double, fromfpxl, + (long double x, int rnd, unsigned int width)) { + return fputil::fromfpx</*IsSigned=*/true>(x, rnd, width); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/inv_trigf_utils.cpp b/libc/src/math/generic/inv_trigf_utils.cpp index 8013c0470affb16dfbcc844602265e30de46b17b..19c8b997dc4ed5455effb21e9416c06077270459 100644 --- a/libc/src/math/generic/inv_trigf_utils.cpp +++ b/libc/src/math/generic/inv_trigf_utils.cpp @@ -10,19 +10,76 @@ namespace LIBC_NAMESPACE { -// N[Table[ArcTan[x], {x, 1/16, 16/16, 1/16}], 40] -alignas(64) const double ATAN_T[ATAN_T_SIZE] = { - 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.0657e94db30d0p-1, - 0x1.1e00babdefeb4p-1, 0x1.345f01cce37bbp-1, 0x1.4978fa3269ee1p-1, - 0x1.5d58987169b18p-1, 0x1.700a7c5784634p-1, 0x1.819d0b7158a4dp-1, - 0x1.921fb54442d18p-1}; - -// for(int i = 0; i < 5; i++) -// printf("%.13a,\n", (-2 * (i % 2) + 1) * 1.0 / (2 * i + 1)); -alignas(64) const double ATAN_K[5] = { - 0x1.0000000000000p+0, -0x1.5555555555555p-2, 0x1.999999999999ap-3, - -0x1.2492492492492p-3, 0x1.c71c71c71c71cp-4}; +// Polynomial approximation for 0 <= x <= 1: +// atan(x) ~ atan((i/16) + (x - (i/16)) * Q(x - i/16) +// = P(x - i/16) +// Generated by Sollya with: +// > for i from 1 to 16 do { +// mid_point = i/16; +// P = fpminimax(atan(mid_point + x), 8, [|D...|], [-1/32, 1/32]); +// print("{", coeff(P, 0), ",", coeff(P, 1), ",", coeff(P, 2), ",", +// coeff(P, 3), ",", coeff(P, 4), ",", coeff(P, 5), ",", coeff(P, 6), +// ",", coeff(P, 7), ",", coeff(P, 8), "},"); +// }; +// For i = 0, the polynomial is generated by: +// > P = fpminimax(atan(x)/x, 7, [|1, D...|], [0, 1/32]); +// > dirtyinfnorm((atan(x) - x*P)/x, [0, 1/32]); +// 0x1.feb2fcdba66447ccbe28a1a0f935b51678a718fb1p-59 +// 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] = { + {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}, + {0x1.ff55bb72cfde9p-5, 0x1.fe01fe01fe007p-1, -0x1.fc05f809ed8dap-5, + -0x1.4d69303afe04ep-2, 0x1.f61bc3e8349cp-5, 0x1.820839278756bp-3, + -0x1.eda4de1c6bf3fp-5, -0x1.0514d42d64a63p-3, 0x1.db3746a442dcbp-5}, + {0x1.fd5ba9aac2f6ep-4, 0x1.f81f81f81f813p-1, -0x1.f05e09d0dc378p-4, + -0x1.368c3aa719215p-2, 0x1.d9b16b33ff9c9p-4, 0x1.40488f9c6262ap-3, + -0x1.ba55933e62ea5p-4, -0x1.64c6a15cd9116p-4, 0x1.9273d5939a75ap-4}, + {0x1.7b97b4bce5b02p-3, 0x1.ee9c7f8458e05p-1, -0x1.665c226d6961p-3, + -0x1.1344bb7391703p-2, 0x1.42aca8b0081b9p-3, 0x1.c32d9381d7c03p-4, + -0x1.13e970672e246p-3, -0x1.181ed934dd733p-5, 0x1.bad81ea190c08p-4}, + {0x1.f5b75f92c80ddp-3, 0x1.e1e1e1e1e1e2cp-1, -0x1.c5894d10d363dp-3, + -0x1.ce6de025f9f5ep-3, 0x1.78a3a07c8dd7fp-3, 0x1.dd5f5180f386ep-5, + -0x1.1b1f513c4536bp-3, 0x1.0df852e58c43cp-6, 0x1.722e7a7e42505p-4}, + {0x1.362773707ebccp-2, 0x1.d272ca3fc5b2ep-1, -0x1.0997e8aeca8fbp-2, + -0x1.6cf6666e5e693p-3, 0x1.8dd1e907e88adp-3, 0x1.24849ac0caa5dp-7, + -0x1.f496be486229dp-4, 0x1.b7d54b8e759ecp-5, 0x1.d39c0d39c3922p-5}, + {0x1.6f61941e4def1p-2, 0x1.c0e070381c0f2p-1, -0x1.2726dd135d9eep-2, + -0x1.09f37b39b70e4p-3, 0x1.85eacdaadd712p-3, -0x1.04d66340d5b9p-5, + -0x1.8056b15a22b98p-4, 0x1.29baf494ad3ddp-4, 0x1.52d5881322a7ap-6}, + {0x1.a64eec3cc23fdp-2, 0x1.adbe87f94906ap-1, -0x1.3b9d8eab55addp-2, + -0x1.57c09646eb7p-4, 0x1.6795319e3b8dfp-3, -0x1.f2d89b5ef31bep-5, + -0x1.f38aac26203cap-5, 0x1.3262802235e3fp-4, -0x1.2afd6b9a57d66p-7}, + {0x1.dac670561bb4fp-2, 0x1.99999999999ap-1, -0x1.47ae147adff11p-2, + -0x1.5d867c40188b7p-5, 0x1.3a92a2df85e7ap-3, -0x1.3ec457c46e851p-4, + -0x1.ec1b9777e2e5bp-6, 0x1.0a542992a821ep-4, -0x1.ccffbe2f0d945p-6}, + {0x1.0657e94db30dp-1, 0x1.84f00c2780615p-1, -0x1.4c62cb562defap-2, + -0x1.e6495b3c14e03p-8, 0x1.063c2fa617bfcp-3, -0x1.58b782d9907aap-4, + -0x1.41e6ff524b7fp-8, 0x1.937dfff3205a7p-5, -0x1.0fb1fd1c729dp-5}, + {0x1.1e00babdefeb4p-1, 0x1.702e05c0b816ep-1, -0x1.4af2b78215fbep-2, + 0x1.5d0b7e9f36997p-6, 0x1.a1247cb978debp-4, -0x1.519e1457734cap-4, + 0x1.a755cf86b5bfbp-7, 0x1.096d174284564p-5, -0x1.081adf539ad58p-5}, + {0x1.345f01cce37bbp-1, 0x1.5babcc647fa8ep-1, -0x1.449db09426a6dp-2, + 0x1.655caac5896dap-5, 0x1.3bbbd22d05a61p-4, -0x1.34a2febee042fp-4, + 0x1.84df9c8269e34p-6, 0x1.200e8176c899ap-6, -0x1.c00b23c3ce222p-6}, + {0x1.4978fa3269ee1p-1, 0x1.47ae147ae1477p-1, -0x1.3a92a3055231ap-2, + 0x1.ec21b515a4a2p-5, 0x1.c2f8b81f9a0d2p-5, -0x1.0ba9964125453p-4, + 0x1.d7b5614777a05p-6, 0x1.971e91ed73595p-8, -0x1.3fc375a78dc74p-6}, + {0x1.5d58987169b18p-1, 0x1.34679ace01343p-1, -0x1.2ddfb039136e5p-2, + 0x1.2491307b9fb73p-4, 0x1.29c7e4886dc22p-5, -0x1.bca78bcca83ap-5, + 0x1.e63efd7cbe1ddp-6, -0x1.8ea6c4f03b42dp-10, -0x1.9385b5c3a6997p-7}, + {0x1.700a7c5784634p-1, 0x1.21fb78121fb76p-1, -0x1.1f6a8499e5d1ap-2, + 0x1.41b15e5e29423p-4, 0x1.59bc953163345p-6, -0x1.63b54b13184ddp-5, + 0x1.c9086666d213p-6, -0x1.90c3b4ad8d4bcp-8, -0x1.80f08ed9f6f57p-8}, + {0x1.819d0b7158a4dp-1, 0x1.107fbbe01107ep-1, -0x1.0feeb4089670ep-2, + 0x1.50e5afb93f5cbp-4, 0x1.2a7c2adffeffbp-7, -0x1.12bd29b4f1b43p-5, + 0x1.93f71f0eb00eap-6, -0x1.10ece5ad30e28p-7, -0x1.db1a76bcd2b9cp-10}, + {0x1.921fb54442d18p-1, 0x1.ffffffffffffep-2, -0x1.fffffffffc51cp-3, + 0x1.555555557002ep-4, -0x1.a88260c338e75p-30, -0x1.99999f9a7614fp-6, + 0x1.555e31a1e15e9p-6, -0x1.245240d65e629p-7, -0x1.fa9ba66478903p-11}, +}; } // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/inv_trigf_utils.h b/libc/src/math/generic/inv_trigf_utils.h index 20f912de2ac008768b2889a5c422a75ed9cf7128..e60c367d7b46b8e45d6a5419b175568f053cb53e 100644 --- a/libc/src/math/generic/inv_trigf_utils.h +++ b/libc/src/math/generic/inv_trigf_utils.h @@ -9,85 +9,33 @@ #ifndef LLVM_LIBC_SRC_MATH_GENERIC_INV_TRIGF_UTILS_H #define LLVM_LIBC_SRC_MATH_GENERIC_INV_TRIGF_UTILS_H -#include "math_utils.h" -#include "src/__support/FPUtil/FEnvImpl.h" -#include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/PolyEval.h" -#include "src/__support/FPUtil/nearest_integer.h" +#include "src/__support/FPUtil/multiply_add.h" #include "src/__support/common.h" -#include <errno.h> - namespace LIBC_NAMESPACE { // PI and PI / 2 constexpr double M_MATH_PI = 0x1.921fb54442d18p+1; constexpr double M_MATH_PI_2 = 0x1.921fb54442d18p+0; -// atan table size -constexpr int ATAN_T_BITS = 4; -constexpr int ATAN_T_SIZE = 1 << ATAN_T_BITS; - -// N[Table[ArcTan[x], {x, 1/8, 8/8, 1/8}], 40] -extern const double ATAN_T[ATAN_T_SIZE]; -extern const double ATAN_K[5]; - -// The main idea of the function is to use formula -// atan(u) + atan(v) = atan((u+v)/(1-uv)) - -// x should be positive, normal finite value -LIBC_INLINE double atan_eval(double x) { - using FPB = fputil::FPBits<double>; - using Sign = fputil::Sign; - // Added some small value to umin and umax mantissa to avoid possible rounding - // errors. - FPB::StorageType umin = - FPB::create_value(Sign::POS, FPB::EXP_BIAS - ATAN_T_BITS - 1, - 0x100000000000UL) - .uintval(); - FPB::StorageType umax = - FPB::create_value(Sign::POS, FPB::EXP_BIAS + ATAN_T_BITS, - 0xF000000000000UL) - .uintval(); - - FPB bs(x); - auto x_abs = bs.abs().uintval(); - - if (x_abs <= umin) { - double pe = LIBC_NAMESPACE::fputil::polyeval( - x * x, 0.0, ATAN_K[1], ATAN_K[2], ATAN_K[3], ATAN_K[4]); - return fputil::multiply_add(pe, x, x); - } - - if (x_abs >= umax) { - double one_over_x_m = -1.0 / x; - double one_over_x2 = one_over_x_m * one_over_x_m; - double pe = LIBC_NAMESPACE::fputil::polyeval( - one_over_x2, ATAN_K[0], ATAN_K[1], ATAN_K[2], ATAN_K[3]); - return fputil::multiply_add(pe, one_over_x_m, - bs.is_neg() ? (-M_MATH_PI_2) : (M_MATH_PI_2)); - } +extern double ATAN_COEFFS[17][9]; - double pos_x = FPB(x_abs).get_val(); - bool one_over_x = pos_x > 1.0; - if (one_over_x) { - pos_x = 1.0 / pos_x; - } +// 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 double atan_eval(double x, int i) { + double x2 = x * x; - double near_x = fputil::nearest_integer(pos_x * ATAN_T_SIZE); - int val = static_cast<int>(near_x); - near_x *= 1.0 / ATAN_T_SIZE; + 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 v = (pos_x - near_x) / fputil::multiply_add(near_x, pos_x, 1.0); - double v2 = v * v; - double pe = LIBC_NAMESPACE::fputil::polyeval(v2, ATAN_K[0], ATAN_K[1], - ATAN_K[2], ATAN_K[3], ATAN_K[4]); - double result; - if (one_over_x) - result = M_MATH_PI_2 - fputil::multiply_add(pe, v, ATAN_T[val - 1]); - else - result = fputil::multiply_add(pe, v, ATAN_T[val - 1]); - return bs.is_neg() ? -result : result; + 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; } // > Q = fpminimax(asin(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20|], diff --git a/libc/src/math/generic/log.cpp b/libc/src/math/generic/log.cpp index 339e0297560f799145a73b8ff7d92fc07b474c75..6de0d90be80e1133c8059c39c5e20cd63272c53c 100644 --- a/libc/src/math/generic/log.cpp +++ b/libc/src/math/generic/log.cpp @@ -24,7 +24,7 @@ namespace LIBC_NAMESPACE { // 128-bit precision dyadic floating point numbers. using Float128 = typename fputil::DyadicFloat<128>; -using Sign = fputil::Sign; + using LIBC_NAMESPACE::operator""_u128; namespace { @@ -735,7 +735,7 @@ double log_accurate(int e_x, int index, double m_x) { LLVM_LIBC_FUNCTION(double, log, (double x)) { using FPBits_t = typename fputil::FPBits<double>; - using Sign = fputil::Sign; + FPBits_t xbits(x); uint64_t x_u = xbits.uintval(); diff --git a/libc/src/math/generic/log10.cpp b/libc/src/math/generic/log10.cpp index c690ca287040759ac7dec62ef8f6529f87821398..fb839c111e6a0f134533465585006ec6a4c950e5 100644 --- a/libc/src/math/generic/log10.cpp +++ b/libc/src/math/generic/log10.cpp @@ -24,7 +24,7 @@ namespace LIBC_NAMESPACE { // 128-bit precision dyadic floating point numbers. using Float128 = typename fputil::DyadicFloat<128>; -using Sign = fputil::Sign; + using LIBC_NAMESPACE::operator""_u128; namespace { @@ -737,7 +737,7 @@ double log10_accurate(int e_x, int index, double m_x) { LLVM_LIBC_FUNCTION(double, log10, (double x)) { using FPBits_t = typename fputil::FPBits<double>; - using Sign = fputil::Sign; + FPBits_t xbits(x); uint64_t x_u = xbits.uintval(); diff --git a/libc/src/math/generic/log10f.cpp b/libc/src/math/generic/log10f.cpp index 0216bb2133f1bb34466a02dab325bac703fac226..1b6979d4414a9e98641e08f4cfa1864adbcec136 100644 --- a/libc/src/math/generic/log10f.cpp +++ b/libc/src/math/generic/log10f.cpp @@ -106,7 +106,7 @@ LLVM_LIBC_FUNCTION(float, log10f, (float x)) { constexpr double LOG10_2 = 0x1.34413509f79ffp-2; using FPBits = typename fputil::FPBits<float>; - using Sign = fputil::Sign; + FPBits xbits(x); uint32_t x_u = xbits.uintval(); diff --git a/libc/src/math/generic/log1p.cpp b/libc/src/math/generic/log1p.cpp index 26bb4d369278af26aa06a7348d29d7cef203dfa7..83bd753cde5da8dfb308a33c2e43bc512fc673dc 100644 --- a/libc/src/math/generic/log1p.cpp +++ b/libc/src/math/generic/log1p.cpp @@ -23,7 +23,7 @@ namespace LIBC_NAMESPACE { // 128-bit precision dyadic floating point numbers. using Float128 = typename fputil::DyadicFloat<128>; -using Sign = fputil::Sign; + using LIBC_NAMESPACE::operator""_u128; namespace { @@ -877,7 +877,7 @@ LIBC_INLINE double log1p_accurate(int e_x, int index, LLVM_LIBC_FUNCTION(double, log1p, (double x)) { using FPBits_t = typename fputil::FPBits<double>; - using Sign = fputil::Sign; + constexpr int EXP_BIAS = FPBits_t::EXP_BIAS; constexpr int FRACTION_LEN = FPBits_t::FRACTION_LEN; constexpr uint64_t FRACTION_MASK = FPBits_t::FRACTION_MASK; diff --git a/libc/src/math/generic/log1pf.cpp b/libc/src/math/generic/log1pf.cpp index 28426a88e64902d9de8cc646f016fef737ec5749..e3c7d95418b1fc76419f4c7a79cfa89bb921dbc1 100644 --- a/libc/src/math/generic/log1pf.cpp +++ b/libc/src/math/generic/log1pf.cpp @@ -106,7 +106,7 @@ LLVM_LIBC_FUNCTION(float, log1pf, (float x)) { case 0xbf800000U: // x = -1.0 fputil::set_errno_if_required(ERANGE); fputil::raise_except_if_required(FE_DIVBYZERO); - return FPBits::inf(fputil::Sign::NEG).get_val(); + return FPBits::inf(Sign::NEG).get_val(); #ifndef LIBC_TARGET_CPU_HAS_FMA case 0x4cc1c80bU: // x = 0x1.839016p+26f return fputil::round_result_slightly_down(0x1.26fc04p+4f); diff --git a/libc/src/math/generic/log2.cpp b/libc/src/math/generic/log2.cpp index 648850b80b046eb7ee6e2b72cf204aad9fd25896..c68bc60e8468bb72a41f8d5a8949bb4af4fe361e 100644 --- a/libc/src/math/generic/log2.cpp +++ b/libc/src/math/generic/log2.cpp @@ -24,7 +24,7 @@ namespace LIBC_NAMESPACE { // 128-bit precision dyadic floating point numbers. using Float128 = typename fputil::DyadicFloat<128>; -using Sign = fputil::Sign; + using LIBC_NAMESPACE::operator""_u128; namespace { @@ -857,7 +857,7 @@ double log2_accurate(int e_x, int index, double m_x) { LLVM_LIBC_FUNCTION(double, log2, (double x)) { using FPBits_t = typename fputil::FPBits<double>; - using Sign = fputil::Sign; + FPBits_t xbits(x); uint64_t x_u = xbits.uintval(); diff --git a/libc/src/math/generic/log2f.cpp b/libc/src/math/generic/log2f.cpp index 8651316d282cab0f7e0f8eb39f62f3b2908c0419..c9f7b2121519df21928ef989615477c0a1d261d8 100644 --- a/libc/src/math/generic/log2f.cpp +++ b/libc/src/math/generic/log2f.cpp @@ -55,7 +55,7 @@ namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(float, log2f, (float x)) { using FPBits = typename fputil::FPBits<float>; - using Sign = fputil::Sign; + FPBits xbits(x); uint32_t x_u = xbits.uintval(); diff --git a/libc/src/math/generic/log_range_reduction.h b/libc/src/math/generic/log_range_reduction.h index 8c9b7d2eabebef33a4ef5de18820f8bdc9db55a7..64c0fc3aa4f539a5c71930e0616a54062a83f00c 100644 --- a/libc/src/math/generic/log_range_reduction.h +++ b/libc/src/math/generic/log_range_reduction.h @@ -37,7 +37,6 @@ log_range_reduction(double m_x, const LogRR &log_table, fputil::DyadicFloat<128> &sum) { using Float128 = typename fputil::DyadicFloat<128>; using MType = typename Float128::MantissaType; - using Sign = fputil::Sign; int64_t v = static_cast<int64_t>(m_x * 0x1.0p60); // ulp = 2^-60 diff --git a/libc/src/math/generic/logf.cpp b/libc/src/math/generic/logf.cpp index 49d258ecc1334256d98e31b906f9dda3304c4827..5296ba6bc13cf6249ec6437b71da7348b75ae099 100644 --- a/libc/src/math/generic/logf.cpp +++ b/libc/src/math/generic/logf.cpp @@ -54,7 +54,7 @@ namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(float, logf, (float x)) { constexpr double LOG_2 = 0x1.62e42fefa39efp-1; using FPBits = typename fputil::FPBits<float>; - using Sign = fputil::Sign; + FPBits xbits(x); uint32_t x_u = xbits.uintval(); diff --git a/libc/src/math/generic/math_utils.h b/libc/src/math/generic/math_utils.h index e884fe2deae2843496b35b55441133ec056fcbf9..cced761fc8c822c0e95d3992e0aaf7109d186df4 100644 --- a/libc/src/math/generic/math_utils.h +++ b/libc/src/math/generic/math_utils.h @@ -9,13 +9,12 @@ #ifndef LLVM_LIBC_SRC_MATH_GENERIC_MATH_UTILS_H #define LLVM_LIBC_SRC_MATH_GENERIC_MATH_UTILS_H +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/CPP/bit.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/common.h" #include "src/errno/libc_errno.h" -#include <math.h> - #include <stdint.h> // TODO: evaluate which functions from this file are actually used. diff --git a/libc/src/math/generic/nanf128.cpp b/libc/src/math/generic/nanf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f087c9f074fde8c0f059b6bfd0839028c022c1c4 --- /dev/null +++ b/libc/src/math/generic/nanf128.cpp @@ -0,0 +1,23 @@ +//===-- Implementation of nanf128 function --------------------------------===// +// +// 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/math/nanf128.h" +#include "src/__support/common.h" +#include "src/__support/str_to_float.h" +#include "src/errno/libc_errno.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, nanf128, (const char *arg)) { + auto result = internal::strtonan<float128>(arg); + if (result.has_error()) + libc_errno = result.error; + return result.value; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/nextafterf128.cpp b/libc/src/math/generic/nextafterf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..905c89022ba1080e5b6c8b45b75d27c1c0b47d66 --- /dev/null +++ b/libc/src/math/generic/nextafterf128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of nextafterf128 function --------------------------===// +// +// 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/math/nextafterf128.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, nextafterf128, (float128 x, float128 y)) { + return fputil::nextafter(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/nextdown.cpp b/libc/src/math/generic/nextdown.cpp new file mode 100644 index 0000000000000000000000000000000000000000..51dee483b70e62bf4e662d58edecd299046f3b7a --- /dev/null +++ b/libc/src/math/generic/nextdown.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of nextdown function -------------------------------===// +// +// 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/math/nextdown.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(double, nextdown, (double x)) { + return fputil::nextupdown</*IsDown=*/true>(x); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/nextdownf.cpp b/libc/src/math/generic/nextdownf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..857b412d64c3c4e05d1955357b74d88b237f732d --- /dev/null +++ b/libc/src/math/generic/nextdownf.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of nextdownf function ------------------------------===// +// +// 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/math/nextdownf.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float, nextdownf, (float x)) { + return fputil::nextupdown</*IsDown=*/true>(x); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/nextdownf128.cpp b/libc/src/math/generic/nextdownf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2585a13df3a3c2c8401e3074f35c744459ffdf03 --- /dev/null +++ b/libc/src/math/generic/nextdownf128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of nextdownf128 function ---------------------------===// +// +// 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/math/nextdownf128.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, nextdownf128, (float128 x)) { + return fputil::nextupdown</*IsDown=*/true>(x); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/nextdownl.cpp b/libc/src/math/generic/nextdownl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..06a09c9daea595dc753326ebfc9b1070e3cad2d3 --- /dev/null +++ b/libc/src/math/generic/nextdownl.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of nextdownl function ------------------------------===// +// +// 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/math/nextdownl.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long double, nextdownl, (long double x)) { + return fputil::nextupdown</*IsDown=*/true>(x); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/nextup.cpp b/libc/src/math/generic/nextup.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d75a336eefcc8a5b6b01dfcf6b64aec4abd8bf8e --- /dev/null +++ b/libc/src/math/generic/nextup.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of nextup function ---------------------------------===// +// +// 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/math/nextup.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(double, nextup, (double x)) { + return fputil::nextupdown</*IsDown=*/false>(x); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/nextupf.cpp b/libc/src/math/generic/nextupf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3b18dae4488d4de388a0b70f82b51c18c0ac7349 --- /dev/null +++ b/libc/src/math/generic/nextupf.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of nextupf function --------------------------------===// +// +// 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/math/nextupf.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float, nextupf, (float x)) { + return fputil::nextupdown</*IsDown=*/false>(x); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/nextupf128.cpp b/libc/src/math/generic/nextupf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d862c30976cb4e001f1618f8670fca42c8ac7f3 --- /dev/null +++ b/libc/src/math/generic/nextupf128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of nextupf128 function -----------------------------===// +// +// 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/math/nextupf128.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, nextupf128, (float128 x)) { + return fputil::nextupdown</*IsDown=*/false>(x); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/nextupl.cpp b/libc/src/math/generic/nextupl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ccc52445eec5c13792fb5fdbc4a0b02538140880 --- /dev/null +++ b/libc/src/math/generic/nextupl.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of nextupl function --------------------------------===// +// +// 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/math/nextupl.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long double, nextupl, (long double x)) { + return fputil::nextupdown</*IsDown=*/false>(x); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/powf.cpp b/libc/src/math/generic/powf.cpp index 2c666bab6d628fe1f9714e0323f01a2708aa9f45..0450ffd711fff10e17da234aa2ea49c9352647d6 100644 --- a/libc/src/math/generic/powf.cpp +++ b/libc/src/math/generic/powf.cpp @@ -424,7 +424,7 @@ LIBC_INLINE bool larger_exponent(double a, double b) { double powf_double_double(int idx_x, double dx, double y6, double lo6_hi, const DoubleDouble &exp2_hi_mid) { using DoubleBits = typename fputil::FPBits<double>; - using Sign = fputil::Sign; + // Perform a second range reduction step: // idx2 = round(2^14 * (dx + 2^-8)) = round ( dx * 2^14 + 2^6) // dx2 = (1 + dx) * r2 - 1 @@ -513,7 +513,7 @@ double powf_double_double(int idx_x, double dx, double y6, double lo6_hi, LLVM_LIBC_FUNCTION(float, powf, (float x, float y)) { using FloatBits = typename fputil::FPBits<float>; using DoubleBits = typename fputil::FPBits<double>; - using Sign = fputil::Sign; + FloatBits xbits(x), ybits(y); uint32_t x_u = xbits.uintval(); diff --git a/libc/src/math/generic/ufromfp.cpp b/libc/src/math/generic/ufromfp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..15800d67fd8d38b78e5d5319031ac127eaae1019 --- /dev/null +++ b/libc/src/math/generic/ufromfp.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of ufromfp function --------------------------------===// +// +// 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/math/ufromfp.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(double, ufromfp, (double x, int rnd, unsigned int width)) { + return fputil::fromfp</*IsSigned=*/false>(x, rnd, width); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/ufromfpf.cpp b/libc/src/math/generic/ufromfpf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..898446ec45aa21b03e62cfad0ab8a6b07ffbdb97 --- /dev/null +++ b/libc/src/math/generic/ufromfpf.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of ufromfpf function -------------------------------===// +// +// 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/math/ufromfpf.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float, ufromfpf, (float x, int rnd, unsigned int width)) { + return fputil::fromfp</*IsSigned=*/false>(x, rnd, width); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/ufromfpf128.cpp b/libc/src/math/generic/ufromfpf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cc728f35551ca6092cfa95fc0407c89af1cbe935 --- /dev/null +++ b/libc/src/math/generic/ufromfpf128.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of ufromfpf128 function ----------------------------===// +// +// 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/math/ufromfpf128.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, ufromfpf128, + (float128 x, int rnd, unsigned int width)) { + return fputil::fromfp</*IsSigned=*/false>(x, rnd, width); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/ufromfpl.cpp b/libc/src/math/generic/ufromfpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bd353e9ebbb566c0a85ff6ac2525823e5e5e2b83 --- /dev/null +++ b/libc/src/math/generic/ufromfpl.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of ufromfpl function -------------------------------===// +// +// 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/math/ufromfpl.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long double, ufromfpl, + (long double x, int rnd, unsigned int width)) { + return fputil::fromfp</*IsSigned=*/false>(x, rnd, width); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/ufromfpx.cpp b/libc/src/math/generic/ufromfpx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ad95ff3061ebd2f3e86ad64458de0471a5f0a04 --- /dev/null +++ b/libc/src/math/generic/ufromfpx.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of ufromfpx function -------------------------------===// +// +// 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/math/ufromfpx.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(double, ufromfpx, (double x, int rnd, unsigned int width)) { + return fputil::fromfpx</*IsSigned=*/false>(x, rnd, width); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/ufromfpxf.cpp b/libc/src/math/generic/ufromfpxf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7c878489e8d254867d036f929b3a2ddeb68ce39b --- /dev/null +++ b/libc/src/math/generic/ufromfpxf.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of ufromfpxf function ------------------------------===// +// +// 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/math/ufromfpxf.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float, ufromfpxf, (float x, int rnd, unsigned int width)) { + return fputil::fromfpx</*IsSigned=*/false>(x, rnd, width); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/ufromfpxf128.cpp b/libc/src/math/generic/ufromfpxf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..57c290365e693b3926c938e1348015bfd79befff --- /dev/null +++ b/libc/src/math/generic/ufromfpxf128.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of ufromfpxf128 function ---------------------------===// +// +// 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/math/ufromfpxf128.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, ufromfpxf128, + (float128 x, int rnd, unsigned int width)) { + return fputil::fromfpx</*IsSigned=*/false>(x, rnd, width); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/ufromfpxl.cpp b/libc/src/math/generic/ufromfpxl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9a8ba7aa5b91dea8756132e262a9d0d2997badb3 --- /dev/null +++ b/libc/src/math/generic/ufromfpxl.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of ufromfpxl function ------------------------------===// +// +// 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/math/ufromfpxl.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long double, ufromfpxl, + (long double x, int rnd, unsigned int width)) { + return fputil::fromfpx</*IsSigned=*/false>(x, rnd, width); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/nanf128.h b/libc/src/math/nanf128.h new file mode 100644 index 0000000000000000000000000000000000000000..b06d14e2f945e1a62ee6e6fa4cdb59e5b9fe8eeb --- /dev/null +++ b/libc/src/math/nanf128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for nanf128 -----------------------*- 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_MATH_NANF128_H +#define LLVM_LIBC_SRC_MATH_NANF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 nanf128(const char *arg); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_NANF128_H diff --git a/libc/src/math/nextafterf128.h b/libc/src/math/nextafterf128.h new file mode 100644 index 0000000000000000000000000000000000000000..a404d33810ec2dd6a0885b95b489b251c2bfdc84 --- /dev/null +++ b/libc/src/math/nextafterf128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for nextafterf128 ------------------*- 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_MATH_NEXTAFTERF128_H +#define LLVM_LIBC_SRC_MATH_NEXTAFTERF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 nextafterf128(float128 x, float128 y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_NEXTAFTERF128_H diff --git a/libc/src/math/nextdown.h b/libc/src/math/nextdown.h new file mode 100644 index 0000000000000000000000000000000000000000..8049b170ee72118f474a33d56a8741bf7cf9390c --- /dev/null +++ b/libc/src/math/nextdown.h @@ -0,0 +1,18 @@ +//===-- Implementation header for nextdown ----------------------*- 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_MATH_NEXTDOWN_H +#define LLVM_LIBC_SRC_MATH_NEXTDOWN_H + +namespace LIBC_NAMESPACE { + +double nextdown(double x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_NEXTDOWN_H diff --git a/libc/src/math/nextdownf.h b/libc/src/math/nextdownf.h new file mode 100644 index 0000000000000000000000000000000000000000..0a2f23480574dc8347b6ad31f6cef18c8b3f0954 --- /dev/null +++ b/libc/src/math/nextdownf.h @@ -0,0 +1,18 @@ +//===-- Implementation header for nextdownf ---------------------*- 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_MATH_NEXTDOWNF_H +#define LLVM_LIBC_SRC_MATH_NEXTDOWNF_H + +namespace LIBC_NAMESPACE { + +float nextdownf(float x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_NEXTDOWNF_H diff --git a/libc/src/math/nextdownf128.h b/libc/src/math/nextdownf128.h new file mode 100644 index 0000000000000000000000000000000000000000..0a3043bb431d8223a326f8e409c99c0279ae6394 --- /dev/null +++ b/libc/src/math/nextdownf128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for nextdownf128 ------------------*- 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_MATH_NEXTDOWNF128_H +#define LLVM_LIBC_SRC_MATH_NEXTDOWNF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 nextdownf128(float128 x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_NEXTDOWNF128_H diff --git a/libc/src/math/nextdownl.h b/libc/src/math/nextdownl.h new file mode 100644 index 0000000000000000000000000000000000000000..9cb274a89b1c53a8c11102b7cc6171f0594d42ee --- /dev/null +++ b/libc/src/math/nextdownl.h @@ -0,0 +1,18 @@ +//===-- Implementation header for nextdownl ---------------------*- 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_MATH_NEXTDOWNL_H +#define LLVM_LIBC_SRC_MATH_NEXTDOWNL_H + +namespace LIBC_NAMESPACE { + +long double nextdownl(long double x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_NEXTDOWNL_H diff --git a/libc/src/math/nextup.h b/libc/src/math/nextup.h new file mode 100644 index 0000000000000000000000000000000000000000..97ae82270b06e458680960566df74e61c2390657 --- /dev/null +++ b/libc/src/math/nextup.h @@ -0,0 +1,18 @@ +//===-- Implementation header for nextup ------------------------*- 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_MATH_NEXTUP_H +#define LLVM_LIBC_SRC_MATH_NEXTUP_H + +namespace LIBC_NAMESPACE { + +double nextup(double x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_NEXTUP_H diff --git a/libc/src/math/nextupf.h b/libc/src/math/nextupf.h new file mode 100644 index 0000000000000000000000000000000000000000..ffc0fa168a10861094ee4d0847515acfb7c3a05c --- /dev/null +++ b/libc/src/math/nextupf.h @@ -0,0 +1,18 @@ +//===-- Implementation header for nextupf -----------------------*- 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_MATH_NEXTUPF_H +#define LLVM_LIBC_SRC_MATH_NEXTUPF_H + +namespace LIBC_NAMESPACE { + +float nextupf(float x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_NEXTUPF_H diff --git a/libc/src/math/nextupf128.h b/libc/src/math/nextupf128.h new file mode 100644 index 0000000000000000000000000000000000000000..b4429922e4beb722d69427853af6ee1edb597315 --- /dev/null +++ b/libc/src/math/nextupf128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for nextupf128 --------------------*- 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_MATH_NEXTUPF128_H +#define LLVM_LIBC_SRC_MATH_NEXTUPF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 nextupf128(float128 x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_NEXTUPF128_H diff --git a/libc/src/math/nextupl.h b/libc/src/math/nextupl.h new file mode 100644 index 0000000000000000000000000000000000000000..cbc6a168e4bea2c26c091c46ef16f291a88fdc68 --- /dev/null +++ b/libc/src/math/nextupl.h @@ -0,0 +1,18 @@ +//===-- Implementation header for nextupl -----------------------*- 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_MATH_NEXTUPL_H +#define LLVM_LIBC_SRC_MATH_NEXTUPL_H + +namespace LIBC_NAMESPACE { + +long double nextupl(long double x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_NEXTUPL_H diff --git a/libc/src/math/ufromfp.h b/libc/src/math/ufromfp.h new file mode 100644 index 0000000000000000000000000000000000000000..f4667486440c2e779168fb113ce2999f84ad179e --- /dev/null +++ b/libc/src/math/ufromfp.h @@ -0,0 +1,18 @@ +//===-- Implementation header for ufromfp -----------------------*- 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_MATH_UFROMFP_H +#define LLVM_LIBC_SRC_MATH_UFROMFP_H + +namespace LIBC_NAMESPACE { + +double ufromfp(double x, int rnd, unsigned int width); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_UFROMFP_H diff --git a/libc/src/math/ufromfpf.h b/libc/src/math/ufromfpf.h new file mode 100644 index 0000000000000000000000000000000000000000..40c6773d143e8fca80dfd30c44576ce433c5502a --- /dev/null +++ b/libc/src/math/ufromfpf.h @@ -0,0 +1,18 @@ +//===-- Implementation header for ufromfpf ----------------------*- 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_MATH_UFROMFPF_H +#define LLVM_LIBC_SRC_MATH_UFROMFPF_H + +namespace LIBC_NAMESPACE { + +float ufromfpf(float x, int rnd, unsigned int width); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_UFROMFPF_H diff --git a/libc/src/math/ufromfpf128.h b/libc/src/math/ufromfpf128.h new file mode 100644 index 0000000000000000000000000000000000000000..785fa82becbcd52f0d5bbd8723eb7d561143bb72 --- /dev/null +++ b/libc/src/math/ufromfpf128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for ufromfpf128 -------------------*- 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_MATH_UFROMFPF128_H +#define LLVM_LIBC_SRC_MATH_UFROMFPF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 ufromfpf128(float128 x, int rnd, unsigned int width); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_UFROMFPF128_H diff --git a/libc/src/math/ufromfpl.h b/libc/src/math/ufromfpl.h new file mode 100644 index 0000000000000000000000000000000000000000..f05a77dc2f103ddc84fa32f32834f97f7f57c5e9 --- /dev/null +++ b/libc/src/math/ufromfpl.h @@ -0,0 +1,18 @@ +//===-- Implementation header for ufromfpl ----------------------*- 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_MATH_UFROMFPL_H +#define LLVM_LIBC_SRC_MATH_UFROMFPL_H + +namespace LIBC_NAMESPACE { + +long double ufromfpl(long double x, int rnd, unsigned int width); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_UFROMFPL_H diff --git a/libc/src/math/ufromfpx.h b/libc/src/math/ufromfpx.h new file mode 100644 index 0000000000000000000000000000000000000000..79c413af968a5f089eac210b3882484c9dfabc35 --- /dev/null +++ b/libc/src/math/ufromfpx.h @@ -0,0 +1,18 @@ +//===-- Implementation header for ufromfpx ----------------------*- 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_MATH_UFROMFPX_H +#define LLVM_LIBC_SRC_MATH_UFROMFPX_H + +namespace LIBC_NAMESPACE { + +double ufromfpx(double x, int rnd, unsigned int width); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_UFROMFPX_H diff --git a/libc/src/math/ufromfpxf.h b/libc/src/math/ufromfpxf.h new file mode 100644 index 0000000000000000000000000000000000000000..f6bd8f7d59959babc260acd3d9488973e8fc5050 --- /dev/null +++ b/libc/src/math/ufromfpxf.h @@ -0,0 +1,18 @@ +//===-- Implementation header for ufromfpxf ---------------------*- 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_MATH_UFROMFPXF_H +#define LLVM_LIBC_SRC_MATH_UFROMFPXF_H + +namespace LIBC_NAMESPACE { + +float ufromfpxf(float x, int rnd, unsigned int width); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_UFROMFPXF_H diff --git a/libc/src/math/ufromfpxf128.h b/libc/src/math/ufromfpxf128.h new file mode 100644 index 0000000000000000000000000000000000000000..f3b43ff54f37c765ea3ed9fa69728b732aed9840 --- /dev/null +++ b/libc/src/math/ufromfpxf128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for ufromfpxf128 ------------------*- 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_MATH_UFROMFPXF128_H +#define LLVM_LIBC_SRC_MATH_UFROMFPXF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 ufromfpxf128(float128 x, int rnd, unsigned int width); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_UFROMFPXF128_H diff --git a/libc/src/math/ufromfpxl.h b/libc/src/math/ufromfpxl.h new file mode 100644 index 0000000000000000000000000000000000000000..180b8f93d21876895a1cf6dbc205ecf61368d2ea --- /dev/null +++ b/libc/src/math/ufromfpxl.h @@ -0,0 +1,18 @@ +//===-- Implementation header for ufromfpxl ---------------------*- 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_MATH_UFROMFPXL_H +#define LLVM_LIBC_SRC_MATH_UFROMFPXL_H + +namespace LIBC_NAMESPACE { + +long double ufromfpxl(long double x, int rnd, unsigned int width); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_UFROMFPXL_H diff --git a/libc/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt index bb8e41606c5dfbe5c019f7850120d6f543501851..1056f38fc7513acdf3d15cc41d7c81d7040b3ee1 100644 --- a/libc/src/stdio/CMakeLists.txt +++ b/libc/src/stdio/CMakeLists.txt @@ -236,6 +236,16 @@ add_entrypoint_object( libc.src.stdio.printf_core.vfprintf_internal ) +add_stdio_entrypoint_object( + fileno + SRCS + fileno.cpp + HDRS + fileno.h + DEPENDS + libc.src.stdio.fileno +) + add_subdirectory(printf_core) add_subdirectory(scanf_core) @@ -246,6 +256,13 @@ add_entrypoint_object( .${LIBC_TARGET_OS}.remove ) +add_entrypoint_object( + rename + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.rename +) + # These entrypoints have multiple potential implementations. add_stdio_entrypoint_object(feof) add_stdio_entrypoint_object(feof_unlocked) @@ -253,6 +270,8 @@ add_stdio_entrypoint_object(ferror) add_stdio_entrypoint_object(ferror_unlocked) add_stdio_entrypoint_object(fseek) add_stdio_entrypoint_object(ftell) +add_stdio_entrypoint_object(fseeko) +add_stdio_entrypoint_object(ftello) add_stdio_entrypoint_object(fflush) add_stdio_entrypoint_object(clearerr) add_stdio_entrypoint_object(clearerr_unlocked) diff --git a/libc/src/stdio/baremetal/CMakeLists.txt b/libc/src/stdio/baremetal/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..65089274050bddff0d75bff7e4ab6687d0c3a8e0 --- /dev/null +++ b/libc/src/stdio/baremetal/CMakeLists.txt @@ -0,0 +1,9 @@ +add_entrypoint_object( + remove + SRCS + remove.cpp + HDRS + ../remove.h + DEPENDS + libc.include.stdio +) diff --git a/libc/src/stdio/baremetal/remove.cpp b/libc/src/stdio/baremetal/remove.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f4f2cdca7c69b583f6abb0260bea27ac9acb4b39 --- /dev/null +++ b/libc/src/stdio/baremetal/remove.cpp @@ -0,0 +1,19 @@ +//===-- Linux implementation of remove ------------------------------------===// +// +// 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/stdio/remove.h" + +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +// TODO: This is a temporary workaround for issue #85335. + +LLVM_LIBC_FUNCTION(int, remove, (const char *)) { return -1; } + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdio/fileno.h b/libc/src/stdio/fileno.h new file mode 100644 index 0000000000000000000000000000000000000000..d41f112226c512cc1dc3247cdbbebab9b816580c --- /dev/null +++ b/libc/src/stdio/fileno.h @@ -0,0 +1,21 @@ +//===-- Implementation header of fileno --------------------------*- 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_STDIO_FILENO_H +#define LLVM_LIBC_SRC_STDIO_FILENO_H + +#include "include/llvm-libc-types/FILE.h" + +namespace LIBC_NAMESPACE { + +int fileno(::FILE *f); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDIO_FILENO_H diff --git a/libc/src/stdio/fseeko.h b/libc/src/stdio/fseeko.h new file mode 100644 index 0000000000000000000000000000000000000000..3202ed2f97d0ef157894714b883dcaccd953ee46 --- /dev/null +++ b/libc/src/stdio/fseeko.h @@ -0,0 +1,21 @@ +//===-- Implementation header of fseeko -------------------------*- 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_STDIO_FSEEKO_H +#define LLVM_LIBC_SRC_STDIO_FSEEKO_H + +#include <stdio.h> +#include <unistd.h> + +namespace LIBC_NAMESPACE { + +int fseeko(::FILE *stream, off_t offset, int whence); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDIO_FSEEKO_H diff --git a/libc/src/stdio/ftello.h b/libc/src/stdio/ftello.h new file mode 100644 index 0000000000000000000000000000000000000000..0fdf13ab6bdbcd0334d1ae03300d4dbbc90edc16 --- /dev/null +++ b/libc/src/stdio/ftello.h @@ -0,0 +1,21 @@ +//===-- Implementation header of ftello -------------------------*- 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_STDIO_FTELLO_H +#define LLVM_LIBC_SRC_STDIO_FTELLO_H + +#include <stdio.h> +#include <unistd.h> + +namespace LIBC_NAMESPACE { + +off_t ftello(::FILE *f); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDIO_FTELLO_H diff --git a/libc/src/stdio/generic/CMakeLists.txt b/libc/src/stdio/generic/CMakeLists.txt index 4e4a709e94061b9b70ca9aee18c774f6e9f06084..ae255917adfe3ac82d65878c5435ca350ed8f32c 100644 --- a/libc/src/stdio/generic/CMakeLists.txt +++ b/libc/src/stdio/generic/CMakeLists.txt @@ -70,6 +70,18 @@ add_entrypoint_object( libc.src.__support.File.platform_file ) +add_entrypoint_object( + fileno + SRCS + fileno.cpp + HDRS + ../fileno.h + DEPENDS + libc.include.stdio + libc.src.__support.File.file + libc.src.__support.File.platform_file +) + add_entrypoint_object( fflush SRCS @@ -91,7 +103,6 @@ add_entrypoint_object( ../fseek.h DEPENDS libc.src.errno.errno - libc.include.stdio libc.src.__support.File.file libc.src.__support.File.platform_file ) @@ -104,7 +115,30 @@ add_entrypoint_object( ../ftell.h DEPENDS libc.src.errno.errno - libc.include.stdio + libc.src.__support.File.file + libc.src.__support.File.platform_file +) + +add_entrypoint_object( + fseeko + SRCS + fseeko.cpp + HDRS + ../fseeko.h + DEPENDS + libc.src.errno.errno + libc.src.__support.File.file + libc.src.__support.File.platform_file +) + +add_entrypoint_object( + ftello + SRCS + ftello.cpp + HDRS + ../ftello.h + DEPENDS + libc.src.errno.errno libc.src.__support.File.file libc.src.__support.File.platform_file ) diff --git a/libc/src/stdio/generic/fileno.cpp b/libc/src/stdio/generic/fileno.cpp new file mode 100644 index 0000000000000000000000000000000000000000..663ba92663762290ba11d96eb1ba913c6d7f099b --- /dev/null +++ b/libc/src/stdio/generic/fileno.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of fileno +//-------------------------------------------===// +// +// 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/stdio/fileno.h" + +#include "include/llvm-libc-types/FILE.h" +#include "src/__support/File/file.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, fileno, (::FILE * stream)) { + return get_fileno(reinterpret_cast<LIBC_NAMESPACE::File *>(stream)); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdio/generic/fseek.cpp b/libc/src/stdio/generic/fseek.cpp index 7666e71e699d563cfe4d23c30f4986743ea72b59..c5edc8d4198c74d7c822d0c0da8e37afd4d98a61 100644 --- a/libc/src/stdio/generic/fseek.cpp +++ b/libc/src/stdio/generic/fseek.cpp @@ -10,7 +10,6 @@ #include "src/__support/File/file.h" #include "src/errno/libc_errno.h" -#include <stdio.h> namespace LIBC_NAMESPACE { diff --git a/libc/src/stdio/generic/fseeko.cpp b/libc/src/stdio/generic/fseeko.cpp new file mode 100644 index 0000000000000000000000000000000000000000..215da759937f69662910f64205d44f9b050d8e22 --- /dev/null +++ b/libc/src/stdio/generic/fseeko.cpp @@ -0,0 +1,26 @@ +//===-- Implementation of fseeko ------------------------------------------===// +// +// 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/stdio/fseeko.h" +#include "src/__support/File/file.h" + +#include "src/errno/libc_errno.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, fseeko, (::FILE * stream, off_t offset, int whence)) { + auto result = + reinterpret_cast<LIBC_NAMESPACE::File *>(stream)->seek(offset, whence); + if (!result.has_value()) { + libc_errno = result.error(); + return -1; + } + return 0; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdio/generic/ftell.cpp b/libc/src/stdio/generic/ftell.cpp index 5f7803150534b316273a3ea3fac5a67ff5c794ce..d55bad2828541b51e61c68deb4052ac0357237a0 100644 --- a/libc/src/stdio/generic/ftell.cpp +++ b/libc/src/stdio/generic/ftell.cpp @@ -10,7 +10,6 @@ #include "src/__support/File/file.h" #include "src/errno/libc_errno.h" -#include <stdio.h> namespace LIBC_NAMESPACE { diff --git a/libc/src/stdio/generic/ftello.cpp b/libc/src/stdio/generic/ftello.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c72e56ea6eb1afbfba53054f3976152a67c5235b --- /dev/null +++ b/libc/src/stdio/generic/ftello.cpp @@ -0,0 +1,25 @@ +//===-- Implementation of ftello ------------------------------------------===// +// +// 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/stdio/ftello.h" +#include "src/__support/File/file.h" + +#include "src/errno/libc_errno.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(off_t, ftello, (::FILE * stream)) { + auto result = reinterpret_cast<LIBC_NAMESPACE::File *>(stream)->tell(); + if (!result.has_value()) { + libc_errno = result.error(); + return -1; + } + return result.value(); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdio/linux/CMakeLists.txt b/libc/src/stdio/linux/CMakeLists.txt index 3b5a9960dc125eb63d6ced2e097c7566ab8c8049..a08ff0ba4832ffe6c60df58fd84518d71f64ca5a 100644 --- a/libc/src/stdio/linux/CMakeLists.txt +++ b/libc/src/stdio/linux/CMakeLists.txt @@ -6,8 +6,21 @@ add_entrypoint_object( ../remove.h DEPENDS libc.include.fcntl + libc.include.stdio libc.include.unistd libc.include.sys_syscall libc.src.__support.OSUtil.osutil libc.src.errno.errno ) + +add_entrypoint_object( + rename + SRCS + rename.cpp + HDRS + ../rename.h + DEPENDS + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) diff --git a/libc/src/stdio/linux/rename.cpp b/libc/src/stdio/linux/rename.cpp new file mode 100644 index 0000000000000000000000000000000000000000..379a6ef3c0c8492c60840a0205e9946bd808eb48 --- /dev/null +++ b/libc/src/stdio/linux/rename.cpp @@ -0,0 +1,28 @@ +//===-- Linux implementation of rename ------------------------------------===// +// +// 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/stdio/rename.h" +#include "include/llvm-libc-macros/linux/fcntl-macros.h" +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" +#include "src/errno/libc_errno.h" +#include <sys/syscall.h> // For syscall numbers. + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, rename, (const char *oldpath, const char *newpath)) { + int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_renameat2, AT_FDCWD, oldpath, + AT_FDCWD, newpath, 0); + + if (ret >= 0) + return 0; + libc_errno = -ret; + return -1; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdio/printf_core/CMakeLists.txt b/libc/src/stdio/printf_core/CMakeLists.txt index 02819ea25ea055405f1a3af67b5c5c28b574f18e..7db79c54beb0aeef1b220746dc084198fef54aeb 100644 --- a/libc/src/stdio/printf_core/CMakeLists.txt +++ b/libc/src/stdio/printf_core/CMakeLists.txt @@ -42,6 +42,7 @@ add_header_library( libc.src.__support.arg_list libc.src.__support.ctype_utils libc.src.__support.str_to_integer + libc.src.__support.CPP.algorithm libc.src.__support.CPP.bit libc.src.__support.CPP.optional libc.src.__support.CPP.string_view diff --git a/libc/src/stdio/printf_core/converter_utils.h b/libc/src/stdio/printf_core/converter_utils.h index 948fe816e9b76de4a4f632271328614f7c657a83..a0e96a11be5bf4afc7d48b8136c8c7bede75746c 100644 --- a/libc/src/stdio/printf_core/converter_utils.h +++ b/libc/src/stdio/printf_core/converter_utils.h @@ -18,7 +18,9 @@ namespace LIBC_NAMESPACE { namespace printf_core { -LIBC_INLINE uintmax_t apply_length_modifier(uintmax_t num, LengthModifier lm) { +LIBC_INLINE uintmax_t apply_length_modifier(uintmax_t num, + LengthSpec length_spec) { + auto [lm, bw] = length_spec; switch (lm) { case LengthModifier::none: return num & cpp::numeric_limits<unsigned int>::max(); @@ -40,6 +42,18 @@ LIBC_INLINE uintmax_t apply_length_modifier(uintmax_t num, LengthModifier lm) { return num & cpp::numeric_limits<uintptr_t>::max(); case LengthModifier::j: return num; // j is intmax, so no mask is necessary. + case LengthModifier::w: + case LengthModifier::wf: { + uintmax_t mask; + if (bw == 0) { + mask = 0; + } else if (bw < sizeof(uintmax_t) * CHAR_BIT) { + mask = (static_cast<uintmax_t>(1) << bw) - 1; + } else { + mask = UINTMAX_MAX; + } + return num & mask; + } } __builtin_unreachable(); } diff --git a/libc/src/stdio/printf_core/core_structs.h b/libc/src/stdio/printf_core/core_structs.h index d3718b49d1b13a2210e94859e48bde51332f1523..1e78f195a75e89ed153a1feab4c733e3ec8425d1 100644 --- a/libc/src/stdio/printf_core/core_structs.h +++ b/libc/src/stdio/printf_core/core_structs.h @@ -22,7 +22,12 @@ namespace printf_core { // These length modifiers match the length modifiers in the format string, which // is why they are formatted differently from the rest of the file. -enum class LengthModifier { hh, h, l, ll, j, z, t, L, none }; +enum class LengthModifier { hh, h, l, ll, j, z, t, L, w, wf, none }; + +struct LengthSpec { + LengthModifier lm; + size_t bit_width; +}; enum FormatFlags : uint8_t { LEFT_JUSTIFIED = 0x01, // - @@ -44,6 +49,7 @@ struct FormatSection { // Format Specifier Values FormatFlags flags = FormatFlags(0); LengthModifier length_modifier = LengthModifier::none; + size_t bit_width = 0; int min_width = 0; int precision = -1; @@ -66,6 +72,7 @@ struct FormatSection { if (!((static_cast<uint8_t>(flags) == static_cast<uint8_t>(other.flags)) && (min_width == other.min_width) && (precision == other.precision) && + (bit_width == other.bit_width) && (length_modifier == other.length_modifier) && (conv_name == other.conv_name))) return false; diff --git a/libc/src/stdio/printf_core/float_dec_converter.h b/libc/src/stdio/printf_core/float_dec_converter.h index 5270fc9de037acee2f17d2804ba3e41862c6a60b..c4e8aaa2f0e2e97f454f4e284d88a4c68e9857d4 100644 --- a/libc/src/stdio/printf_core/float_dec_converter.h +++ b/libc/src/stdio/printf_core/float_dec_converter.h @@ -48,7 +48,7 @@ constexpr uint32_t MAX_BLOCK = 999999999; constexpr char DECIMAL_POINT = '.'; LIBC_INLINE RoundDirection get_round_direction(int last_digit, bool truncated, - fputil::Sign sign) { + Sign sign) { switch (fputil::quick_get_round()) { case FE_TONEAREST: // Round to nearest, if it's exactly halfway then round to even. diff --git a/libc/src/stdio/printf_core/int_converter.h b/libc/src/stdio/printf_core/int_converter.h index 2efbf53d4093821081d803083d302b4ea1d709f8..496e7bd1a56d94e4c9bad668255949d9c5d91e0d 100644 --- a/libc/src/stdio/printf_core/int_converter.h +++ b/libc/src/stdio/printf_core/int_converter.h @@ -71,7 +71,6 @@ LIBC_INLINE int convert_int(Writer *writer, const FormatSection &to_conv) { uintmax_t num = static_cast<uintmax_t>(to_conv.conv_val_raw); bool is_negative = false; FormatFlags flags = to_conv.flags; - const char a = is_lower(to_conv.conv_name) ? 'a' : 'A'; // If the conversion is signed, then handle negative values. @@ -89,8 +88,8 @@ LIBC_INLINE int convert_int(Writer *writer, const FormatSection &to_conv) { ~(FormatFlags::FORCE_SIGN | FormatFlags::SPACE_PREFIX)); } - num = apply_length_modifier(num, to_conv.length_modifier); - + num = + apply_length_modifier(num, {to_conv.length_modifier, to_conv.bit_width}); cpp::array<char, details::num_buf_size()> buf; auto str = details::num_to_strview(num, buf, to_conv.conv_name); if (!str) diff --git a/libc/src/stdio/printf_core/parser.h b/libc/src/stdio/printf_core/parser.h index 0876116a0bac866954f948a7da6e0404a96b5692..eda978a83ea8af82a22ae20935f0f5e0fa238379 100644 --- a/libc/src/stdio/printf_core/parser.h +++ b/libc/src/stdio/printf_core/parser.h @@ -10,6 +10,7 @@ #define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_PARSER_H #include "include/llvm-libc-macros/stdfix-macros.h" +#include "src/__support/CPP/algorithm.h" // max #include "src/__support/CPP/optional.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/str_to_integer.h" @@ -150,10 +151,10 @@ public: } } - LengthModifier lm = parse_length_modifier(&cur_pos); - + auto [lm, bw] = parse_length_modifier(&cur_pos); section.length_modifier = lm; section.conv_name = str[cur_pos]; + section.bit_width = bw; switch (str[cur_pos]) { case ('%'): // Regardless of options, a % conversion is always safe. The standard @@ -202,6 +203,21 @@ public: WRITE_ARG_VAL_SIMPLEST(section.conv_val_raw, ptrdiff_t, conv_index); break; + + case (LengthModifier::w): + case (LengthModifier::wf): + if (bw == 0) { + section.has_conv = false; + } else if (bw <= INT_WIDTH) { + WRITE_ARG_VAL_SIMPLEST(section.conv_val_raw, int, conv_index); + } else if (bw <= LONG_WIDTH) { + WRITE_ARG_VAL_SIMPLEST(section.conv_val_raw, long, conv_index); + } else if (bw <= LLONG_WIDTH) { + WRITE_ARG_VAL_SIMPLEST(section.conv_val_raw, long long, conv_index); + } else { + WRITE_ARG_VAL_SIMPLEST(section.conv_val_raw, intmax_t, conv_index); + } + break; } break; #ifndef LIBC_COPT_PRINTF_DISABLE_FLOAT @@ -306,38 +322,54 @@ private: // assumes that str[*local_pos] is inside a format specifier. It returns a // LengthModifier with the length modifier it found. It will advance local_pos // after the format specifier if one is found. - LIBC_INLINE LengthModifier parse_length_modifier(size_t *local_pos) { + LIBC_INLINE LengthSpec parse_length_modifier(size_t *local_pos) { switch (str[*local_pos]) { case ('l'): if (str[*local_pos + 1] == 'l') { *local_pos += 2; - return LengthModifier::ll; + return {LengthModifier::ll, 0}; + } else { + ++*local_pos; + return {LengthModifier::l, 0}; + } + case ('w'): { + LengthModifier lm; + if (str[*local_pos + 1] == 'f') { + *local_pos += 2; + lm = LengthModifier::wf; } else { ++*local_pos; - return LengthModifier::l; + lm = LengthModifier::w; } + if (internal::isdigit(str[*local_pos])) { + const auto result = internal::strtointeger<int>(str + *local_pos, 10); + *local_pos += result.parsed_len; + return {lm, static_cast<size_t>(cpp::max(0, result.value))}; + } + return {lm, 0}; + } case ('h'): if (str[*local_pos + 1] == 'h') { *local_pos += 2; - return LengthModifier::hh; + return {LengthModifier::hh, 0}; } else { ++*local_pos; - return LengthModifier::h; + return {LengthModifier::h, 0}; } case ('L'): ++*local_pos; - return LengthModifier::L; + return {LengthModifier::L, 0}; case ('j'): ++*local_pos; - return LengthModifier::j; + return {LengthModifier::j, 0}; case ('z'): ++*local_pos; - return LengthModifier::z; + return {LengthModifier::z, 0}; case ('t'): ++*local_pos; - return LengthModifier::t; + return {LengthModifier::t, 0}; default: - return LengthModifier::none; + return {LengthModifier::none, 0}; } } @@ -509,7 +541,7 @@ private: } } - LengthModifier lm = parse_length_modifier(&local_pos); + auto [lm, bw] = parse_length_modifier(&local_pos); // if we don't have an index for this conversion, then its position is // unknown and all this information is irrelevant. The rest of this @@ -560,6 +592,18 @@ private: case (LengthModifier::t): conv_size = type_desc_from_type<ptrdiff_t>(); break; + case (LengthModifier::w): + case (LengthModifier::wf): + if (bw <= INT_WIDTH) { + conv_size = type_desc_from_type<int>(); + } else if (bw <= LONG_WIDTH) { + conv_size = type_desc_from_type<long>(); + } else if (bw <= LLONG_WIDTH) { + conv_size = type_desc_from_type<long long>(); + } else { + conv_size = type_desc_from_type<intmax_t>(); + } + break; } break; #ifndef LIBC_COPT_PRINTF_DISABLE_FLOAT diff --git a/libc/src/stdio/printf_core/string_converter.h b/libc/src/stdio/printf_core/string_converter.h index 04dc5a06da2226599ee2bdc6e23ce79c508cf744..9e05591079faa4d601d347b1eb8c9d5cf0467566 100644 --- a/libc/src/stdio/printf_core/string_converter.h +++ b/libc/src/stdio/printf_core/string_converter.h @@ -25,7 +25,7 @@ LIBC_INLINE int convert_string(Writer *writer, const FormatSection &to_conv) { #ifndef LIBC_COPT_PRINTF_NO_NULLPTR_CHECKS if (str_ptr == nullptr) { - str_ptr = "null"; + str_ptr = "(null)"; } #endif // LIBC_COPT_PRINTF_NO_NULLPTR_CHECKS diff --git a/libc/src/stdio/printf_core/write_int_converter.h b/libc/src/stdio/printf_core/write_int_converter.h index 0310905f36f1464dc6a46d0a752ecd2e906a8451..18aa5c79897ec4d9f3a7d0d4b6294dce5b424e00 100644 --- a/libc/src/stdio/printf_core/write_int_converter.h +++ b/libc/src/stdio/printf_core/write_int_converter.h @@ -55,6 +55,8 @@ LIBC_INLINE int convert_write_int(Writer *writer, *reinterpret_cast<ptrdiff_t *>(to_conv.conv_val_ptr) = written; break; case LengthModifier::j: + case LengthModifier::w: + case LengthModifier::wf: *reinterpret_cast<uintmax_t *>(to_conv.conv_val_ptr) = written; break; } diff --git a/libc/src/stdio/rename.h b/libc/src/stdio/rename.h new file mode 100644 index 0000000000000000000000000000000000000000..eadda7c3eac9b635a4043419b7dc95d9aa5daef3 --- /dev/null +++ b/libc/src/stdio/rename.h @@ -0,0 +1,18 @@ +//===-- Implementation header of rename -------------------------*- 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_STDIO_RENAME_H +#define LLVM_LIBC_SRC_STDIO_RENAME_H + +namespace LIBC_NAMESPACE { + +int rename(const char *oldpath, const char *newpath); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDIO_RENAME_H diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt index bd0bcffe0045d1fdf5f14b028d0a06de73758f62..e526ba040befb7cae8d0327329778f5dc4d8cb5e 100644 --- a/libc/src/stdlib/CMakeLists.txt +++ b/libc/src/stdlib/CMakeLists.txt @@ -52,6 +52,48 @@ add_entrypoint_object( libc.config.linux.app_h ) +add_entrypoint_object( + strfromf + SRCS + strfromf.cpp + HDRS + strfromf.h + DEPENDS + .str_from_util +) + +add_entrypoint_object( + strfromd + SRCS + strfromd.cpp + HDRS + strfromd.h + DEPENDS + .str_from_util +) + +add_entrypoint_object( + strfroml + SRCS + strfroml.cpp + HDRS + strfroml.h + DEPENDS + .str_from_util +) + +add_header_library( + str_from_util + HDRS + str_from_util.h + DEPENDS + libc.src.stdio.printf_core.converter + libc.src.stdio.printf_core.core_structs + libc.src.stdio.printf_core.writer + libc.src.__support.str_to_integer + libc.src.__support.CPP.type_traits +) + add_entrypoint_object( strtof SRCS @@ -372,10 +414,11 @@ add_entrypoint_object( CXX_STANDARD 20 # For constinit of the atexit callback list. DEPENDS - libc.src.__support.fixedvector + libc.src.__support.CPP.new + libc.src.__support.OSUtil.osutil libc.src.__support.blockstore + libc.src.__support.fixedvector libc.src.__support.threads.mutex - libc.src.__support.CPP.new ) add_entrypoint_object( diff --git a/libc/src/stdlib/_Exit.cpp b/libc/src/stdlib/_Exit.cpp index 85684d1e90879ef52fe49b673b388ac429e18160..233af20973924486bbe64885ab48d077836d47d5 100644 --- a/libc/src/stdlib/_Exit.cpp +++ b/libc/src/stdlib/_Exit.cpp @@ -13,9 +13,8 @@ namespace LIBC_NAMESPACE { -LLVM_LIBC_FUNCTION(void, _Exit, (int status)) { +[[noreturn]] LLVM_LIBC_FUNCTION(void, _Exit, (int status)) { quick_exit(status); - __builtin_unreachable(); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdlib/atexit.cpp b/libc/src/stdlib/atexit.cpp index 1513b7969f0dbcb5a55782388a27948745ed717c..fa072b2fdf8d09a2c17fc04a01cee1d8e95b59ae 100644 --- a/libc/src/stdlib/atexit.cpp +++ b/libc/src/stdlib/atexit.cpp @@ -36,7 +36,7 @@ struct AtExitUnit { // mutexes simply passthrough. We will need a lock free stack. using ExitCallbackList = FixedVector<AtExitUnit, 64>; #elif defined(LIBC_COPT_PUBLIC_PACKAGING) -using ExitCallbackList = cpp::ReverseOrderBlockStore<AtExitUnit, 32>; +using ExitCallbackList = ReverseOrderBlockStore<AtExitUnit, 32>; #else // BlockStore uses dynamic memory allocation. To avoid dynamic memory // allocation in tests, we use a fixed size callback list when built for @@ -55,14 +55,10 @@ void stdc_at_exit_func(void *payload) { reinterpret_cast<StdCAtExitCallback *>(payload)(); } -} // namespace - -namespace internal { - void call_exit_callbacks() { handler_list_mtx.lock(); while (!exit_callbacks.empty()) { - auto unit = exit_callbacks.back(); + AtExitUnit &unit = exit_callbacks.back(); exit_callbacks.pop_back(); handler_list_mtx.unlock(); unit.callback(unit.payload); @@ -71,20 +67,31 @@ void call_exit_callbacks() { ExitCallbackList::destroy(&exit_callbacks); } -} // namespace internal - -static int add_atexit_unit(const AtExitUnit &unit) { +int add_atexit_unit(const AtExitUnit &unit) { MutexLock lock(&handler_list_mtx); - if (!exit_callbacks.push_back(unit)) - return -1; - return 0; + if (exit_callbacks.push_back(unit)) + return 0; + return -1; } +} // namespace + +extern "C" { + // TODO: Handle the last dso handle argument. -extern "C" int __cxa_atexit(AtExitCallback *callback, void *payload, void *) { +int __cxa_atexit(AtExitCallback *callback, void *payload, void *) { return add_atexit_unit({callback, payload}); } +// TODO: Handle the dso handle argument. call_exit_callbacks should only invoke +// the callbacks from this DSO. Requires adding support for __dso_handle. +void __cxa_finalize(void *dso) { + if (!dso) + call_exit_callbacks(); +} + +} // extern "C" + LLVM_LIBC_FUNCTION(int, atexit, (StdCAtExitCallback * callback)) { return add_atexit_unit( {&stdc_at_exit_func, reinterpret_cast<void *>(callback)}); diff --git a/libc/src/stdlib/exit.cpp b/libc/src/stdlib/exit.cpp index cc5ae6648d11f234acd318689e57d05cbb7c5940..ba87bffaeb5419274c446a2ec4a6b841e2b4a38b 100644 --- a/libc/src/stdlib/exit.cpp +++ b/libc/src/stdlib/exit.cpp @@ -10,16 +10,13 @@ #include "src/__support/OSUtil/quick_exit.h" #include "src/__support/common.h" -namespace LIBC_NAMESPACE { +extern "C" void __cxa_finalize(void *); -namespace internal { -void call_exit_callbacks(); -} +namespace LIBC_NAMESPACE { -LLVM_LIBC_FUNCTION(void, exit, (int status)) { - internal::call_exit_callbacks(); +[[noreturn]] LLVM_LIBC_FUNCTION(void, exit, (int status)) { + __cxa_finalize(nullptr); quick_exit(status); - __builtin_unreachable(); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdlib/str_from_util.h b/libc/src/stdlib/str_from_util.h new file mode 100644 index 0000000000000000000000000000000000000000..58afa98afc08ed34463f984df94c28a6cbc9275f --- /dev/null +++ b/libc/src/stdlib/str_from_util.h @@ -0,0 +1,138 @@ +//===-- Implementation header for strfromx() utilitites -------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// According to the C23 standard, any input character sequences except a +// precision specifier and the usual floating point formats, namely +// %{a,A,e,E,f,F,g,G}, are not allowed and any code that does otherwise results +// in undefined behaviour(including use of a '%%' conversion specifier); which +// in this case is that the buffer string is simply populated with the format +// string. The case of the input being nullptr should be handled in the calling +// function (strfromf, strfromd, strfroml) itself. + +#ifndef LLVM_LIBC_SRC_STDLIB_STRFROM_UTIL_H +#define LLVM_LIBC_SRC_STDLIB_STRFROM_UTIL_H + +#include "src/__support/CPP/type_traits.h" +#include "src/__support/str_to_integer.h" +#include "src/stdio/printf_core/converter_atlas.h" +#include "src/stdio/printf_core/core_structs.h" +#include "src/stdio/printf_core/writer.h" + +#include <stddef.h> + +namespace LIBC_NAMESPACE::internal { + +template <typename T> +using storage_type = typename fputil::FPBits<T>::StorageType; + +template <typename T> +printf_core::FormatSection parse_format_string(const char *__restrict format, + T fp) { + printf_core::FormatSection section; + size_t cur_pos = 0; + + // There is no typed conversion function to convert single precision float + // to hex exponential format, and the function convert_float_hex_exp() + // requires a double or long double value to work correctly. + // To work around this, we convert fp to double if it is single precision, and + // then use that double precision value in the %{A, a} conversion specifiers. + [[maybe_unused]] double new_fp; + bool t_is_single_prec_type = cpp::is_same<T, float>::value; + if (t_is_single_prec_type) + new_fp = (double)fp; + + if (format[cur_pos] == '%') { + section.has_conv = true; + ++cur_pos; + + // handle precision + section.precision = -1; + if (format[cur_pos] == '.') { + ++cur_pos; + section.precision = 0; + + // The standard does not allow the '*' (asterisk) operator for strfromx() + // functions + if (internal::isdigit(format[cur_pos])) { + auto result = internal::strtointeger<int>(format + cur_pos, 10); + section.precision += result.value; + cur_pos += result.parsed_len; + } + } + + section.conv_name = format[cur_pos]; + switch (format[cur_pos]) { + case 'a': + case 'A': + if (t_is_single_prec_type) + section.conv_val_raw = cpp::bit_cast<storage_type<double>>(new_fp); + else + section.conv_val_raw = cpp::bit_cast<storage_type<T>>(fp); + break; + case 'e': + case 'E': + case 'f': + case 'F': + case 'g': + case 'G': + section.conv_val_raw = cpp::bit_cast<storage_type<T>>(fp); + break; + default: + section.has_conv = false; + while (format[cur_pos] != '\0') + ++cur_pos; + break; + } + + if (format[cur_pos] != '\0') + ++cur_pos; + } else { + section.has_conv = false; + // We are looking for exactly one section, so no more '%' + while (format[cur_pos] != '\0') + ++cur_pos; + } + + section.raw_string = {format, cur_pos}; + return section; +} + +template <typename T> +int strfromfloat_convert(printf_core::Writer *writer, + const printf_core::FormatSection §ion) { + if (!section.has_conv) + return writer->write(section.raw_string); + + auto res = static_cast<storage_type<T>>(section.conv_val_raw); + + fputil::FPBits<T> strfromfloat_bits(res); + if (strfromfloat_bits.is_inf_or_nan()) + return convert_inf_nan(writer, section); + + switch (section.conv_name) { + case 'f': + case 'F': + return convert_float_decimal_typed(writer, section, strfromfloat_bits); + case 'e': + case 'E': + return convert_float_dec_exp_typed(writer, section, strfromfloat_bits); + case 'a': + case 'A': + return convert_float_hex_exp(writer, section); + case 'g': + case 'G': + return convert_float_dec_auto_typed(writer, section, strfromfloat_bits); + default: + return writer->write(section.raw_string); + } + return -1; +} + +} // namespace LIBC_NAMESPACE::internal + +#endif // LLVM_LIBC_SRC_STDLIB_STRFROM_UTIL_H diff --git a/libc/src/stdlib/strfromd.cpp b/libc/src/stdlib/strfromd.cpp new file mode 100644 index 0000000000000000000000000000000000000000..329f6fdcaff73146a6b0a34e6b0ae01c2573e221 --- /dev/null +++ b/libc/src/stdlib/strfromd.cpp @@ -0,0 +1,39 @@ +//===-- Implementation of strfromd ------------------------------*- 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 "src/stdlib/strfromd.h" +#include "src/stdlib/str_from_util.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, strfromd, + (char *__restrict s, size_t n, const char *__restrict format, + double fp)) { + LIBC_ASSERT(s != nullptr); + + printf_core::FormatSection section = + internal::parse_format_string(format, fp); + printf_core::WriteBuffer wb(s, (n > 0 ? n - 1 : 0)); + printf_core::Writer writer(&wb); + + int result = 0; + if (section.has_conv) + result = internal::strfromfloat_convert<double>(&writer, section); + else + result = writer.write(section.raw_string); + + if (result < 0) + return result; + + if (n > 0) + wb.buff[wb.buff_cur] = '\0'; + + return writer.get_chars_written(); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdlib/strfromd.h b/libc/src/stdlib/strfromd.h new file mode 100644 index 0000000000000000000000000000000000000000..d2c3fefb6300dce57704ca338897cd0dce5d7af2 --- /dev/null +++ b/libc/src/stdlib/strfromd.h @@ -0,0 +1,21 @@ +//===-- Implementation header for strfromd ------------------------*- 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_STDLIB_STRFROMD_H +#define LLVM_LIBC_SRC_STDLIB_STRFROMD_H + +#include <stddef.h> + +namespace LIBC_NAMESPACE { + +int strfromd(char *__restrict s, size_t n, const char *__restrict format, + double fp); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDLIB_STRFROMD_H diff --git a/libc/src/stdlib/strfromf.cpp b/libc/src/stdlib/strfromf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..80e1d74797c80b787c7d03947c6c5fb181abea85 --- /dev/null +++ b/libc/src/stdlib/strfromf.cpp @@ -0,0 +1,39 @@ +//===-- Implementation of strfromf ------------------------------*- 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 "src/stdlib/strfromf.h" +#include "src/stdlib/str_from_util.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, strfromf, + (char *__restrict s, size_t n, const char *__restrict format, + float fp)) { + LIBC_ASSERT(s != nullptr); + + printf_core::FormatSection section = + internal::parse_format_string(format, fp); + printf_core::WriteBuffer wb(s, (n > 0 ? n - 1 : 0)); + printf_core::Writer writer(&wb); + + int result = 0; + if (section.has_conv) + result = internal::strfromfloat_convert<float>(&writer, section); + else + result = writer.write(section.raw_string); + + if (result < 0) + return result; + + if (n > 0) + wb.buff[wb.buff_cur] = '\0'; + + return writer.get_chars_written(); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdlib/strfromf.h b/libc/src/stdlib/strfromf.h new file mode 100644 index 0000000000000000000000000000000000000000..492c2c33cf080b0be31b5f44a4d86444cc772ca9 --- /dev/null +++ b/libc/src/stdlib/strfromf.h @@ -0,0 +1,21 @@ +//===-- Implementation header for strfromf ------------------------*- 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_STDLIB_STRFROMF_H +#define LLVM_LIBC_SRC_STDLIB_STRFROMF_H + +#include <stddef.h> + +namespace LIBC_NAMESPACE { + +int strfromf(char *__restrict s, size_t n, const char *__restrict format, + float fp); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDLIB_STRFROMF_H diff --git a/libc/src/stdlib/strfroml.cpp b/libc/src/stdlib/strfroml.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f0bc9354c7ad7647e1f14110416bbcfd2646d0af --- /dev/null +++ b/libc/src/stdlib/strfroml.cpp @@ -0,0 +1,44 @@ +//===-- Implementation of strfroml ------------------------------*- 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 "src/stdlib/strfroml.h" +#include "src/stdlib/str_from_util.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, strfroml, + (char *__restrict s, size_t n, const char *__restrict format, + long double fp)) { + LIBC_ASSERT(s != nullptr); + + printf_core::FormatSection section = + internal::parse_format_string(format, fp); + + // To ensure that the conversion function actually uses long double, + // the length modifier has to be set to LenghtModifier::L + section.length_modifier = printf_core::LengthModifier::L; + + printf_core::WriteBuffer wb(s, (n > 0 ? n - 1 : 0)); + printf_core::Writer writer(&wb); + + int result = 0; + if (section.has_conv) + result = internal::strfromfloat_convert<long double>(&writer, section); + else + result = writer.write(section.raw_string); + + if (result < 0) + return result; + + if (n > 0) + wb.buff[wb.buff_cur] = '\0'; + + return writer.get_chars_written(); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdlib/strfroml.h b/libc/src/stdlib/strfroml.h new file mode 100644 index 0000000000000000000000000000000000000000..e99d035e4da6011632f43b6dd2a71507e7ec3f3f --- /dev/null +++ b/libc/src/stdlib/strfroml.h @@ -0,0 +1,21 @@ +//===-- Implementation header for strfroml ------------------------*- 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_STDLIB_STRFROML_H +#define LLVM_LIBC_SRC_STDLIB_STRFROML_H + +#include <stddef.h> + +namespace LIBC_NAMESPACE { + +int strfroml(char *__restrict s, size_t n, const char *__restrict format, + long double fp); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDLIB_STRFROML_H diff --git a/libc/src/stdlib/strtod.cpp b/libc/src/stdlib/strtod.cpp index db5e0edefb5b381fc3468ba1694d7119a689694a..461f7feb5bf63d2389904260d24aa497fd7732fd 100644 --- a/libc/src/stdlib/strtod.cpp +++ b/libc/src/stdlib/strtod.cpp @@ -19,7 +19,7 @@ LLVM_LIBC_FUNCTION(double, strtod, if (result.has_error()) libc_errno = result.error; - if (str_end != NULL) + if (str_end != nullptr) *str_end = const_cast<char *>(str + result.parsed_len); return result.value; diff --git a/libc/src/stdlib/strtof.cpp b/libc/src/stdlib/strtof.cpp index 2cc8829f63d34cc9dadd6388519fefbbea69ed67..554d096879c593234c2096ef519cb655abab54f0 100644 --- a/libc/src/stdlib/strtof.cpp +++ b/libc/src/stdlib/strtof.cpp @@ -19,7 +19,7 @@ LLVM_LIBC_FUNCTION(float, strtof, if (result.has_error()) libc_errno = result.error; - if (str_end != NULL) + if (str_end != nullptr) *str_end = const_cast<char *>(str + result.parsed_len); return result.value; diff --git a/libc/src/stdlib/strtold.cpp b/libc/src/stdlib/strtold.cpp index 7378963f21b24030a87ebab56bd76e1ad258242d..9c3e1db900670a69300f0028b424cc0bddea1f15 100644 --- a/libc/src/stdlib/strtold.cpp +++ b/libc/src/stdlib/strtold.cpp @@ -19,7 +19,7 @@ LLVM_LIBC_FUNCTION(long double, strtold, if (result.has_error()) libc_errno = result.error; - if (str_end != NULL) + if (str_end != nullptr) *str_end = const_cast<char *>(str + result.parsed_len); return result.value; diff --git a/libc/src/string/memory_utils/generic/builtin.h b/libc/src/string/memory_utils/generic/builtin.h index 5239329f653b341ee9bacaa2c3b1dbe45dc7c3e3..ba4f4b89840889ebc7b1c7b9b90ca6d875e3dcd2 100644 --- a/libc/src/string/memory_utils/generic/builtin.h +++ b/libc/src/string/memory_utils/generic/builtin.h @@ -10,16 +10,16 @@ #define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_GENERIC_BUILTIN_H #include "src/__support/macros/attributes.h" // LIBC_INLINE -#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN #include "src/string/memory_utils/utils.h" // Ptr, CPtr #include <stddef.h> // size_t namespace LIBC_NAMESPACE { -static_assert(LIBC_HAS_BUILTIN(__builtin_memcpy), "Builtin not defined"); -static_assert(LIBC_HAS_BUILTIN(__builtin_memset), "Builtin not defined"); -static_assert(LIBC_HAS_BUILTIN(__builtin_memmove), "Builtin not defined"); +#if !__has_builtin(__builtin_memcpy) || !__has_builtin(__builtin_memset) || \ + !__has_builtin(__builtin_memmove) +#error "Builtin not defined"); +#endif [[maybe_unused]] LIBC_INLINE void inline_memcpy_builtin(Ptr dst, CPtr src, size_t count, size_t offset = 0) { diff --git a/libc/src/string/memory_utils/utils.h b/libc/src/string/memory_utils/utils.h index 79526d19c6b3dc10f6cd2fcfaad87a359702344a..b3e1a26ad99610ce463f6e5cfa7cb750bfe9524e 100644 --- a/libc/src/string/memory_utils/utils.h +++ b/libc/src/string/memory_utils/utils.h @@ -14,7 +14,6 @@ #include "src/__support/CPP/type_traits.h" #include "src/__support/endian.h" #include "src/__support/macros/attributes.h" // LIBC_INLINE -#include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN #include "src/__support/macros/properties/architectures.h" #include <stddef.h> // size_t @@ -71,11 +70,11 @@ LIBC_INLINE bool is_disjoint(const void *p1, const void *p2, size_t size) { return sdiff >= 0 ? size <= udiff : size <= neg_udiff; } -#if LIBC_HAS_BUILTIN(__builtin_memcpy_inline) +#if __has_builtin(__builtin_memcpy_inline) #define LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE #endif -#if LIBC_HAS_BUILTIN(__builtin_memset_inline) +#if __has_builtin(__builtin_memset_inline) #define LLVM_LIBC_HAS_BUILTIN_MEMSET_INLINE #endif diff --git a/libc/src/sys/CMakeLists.txt b/libc/src/sys/CMakeLists.txt index 57ea7b4beaca1bf7ba1db762225c41d86fa09369..adc666b94202f7d2530fe79da47bbbb5d8847eb8 100644 --- a/libc/src/sys/CMakeLists.txt +++ b/libc/src/sys/CMakeLists.txt @@ -7,6 +7,7 @@ add_subdirectory(select) add_subdirectory(socket) add_subdirectory(sendfile) add_subdirectory(stat) +add_subdirectory(statvfs) add_subdirectory(utsname) add_subdirectory(wait) add_subdirectory(prctl) diff --git a/libc/src/sys/mman/CMakeLists.txt b/libc/src/sys/mman/CMakeLists.txt index b49f73873c2006e2bfb32a6ad22088be5f0df8c2..9c74202a09f035e9e816630950362c9b93a62089 100644 --- a/libc/src/sys/mman/CMakeLists.txt +++ b/libc/src/sys/mman/CMakeLists.txt @@ -85,3 +85,17 @@ add_entrypoint_object( DEPENDS .${LIBC_TARGET_OS}.msync ) + +add_entrypoint_object( + shm_open + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.shm_open +) + +add_entrypoint_object( + shm_unlink + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.shm_unlink +) diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt index 04086ee5d332548b7272ef3cbc438011389a6307..00f4f0e64ec06bce190b87935f98a68b20d087ae 100644 --- a/libc/src/sys/mman/linux/CMakeLists.txt +++ b/libc/src/sys/mman/linux/CMakeLists.txt @@ -152,3 +152,40 @@ add_entrypoint_object( libc.src.__support.OSUtil.osutil libc.src.errno.errno ) + +add_header_library( + shm_common + HDRS + shm_common.h + DEPENDS + libc.src.__support.CPP.array + libc.src.__support.CPP.string_view + libc.src.__support.CPP.optional + libc.src.__support.common + libc.src.errno.errno + libc.src.string.memory_utils.inline_memcpy +) + +add_entrypoint_object( + shm_open + SRCS + shm_open.cpp + HDRS + ../shm_open.h + DEPENDS + libc.src.fcntl.open + libc.include.llvm-libc-macros.fcntl_macros + libc.include.llvm-libc-types.mode_t + .shm_common +) + +add_entrypoint_object( + shm_unlink + SRCS + shm_unlink.cpp + HDRS + ../shm_unlink.h + DEPENDS + libc.src.unistd.unlink + .shm_common +) diff --git a/libc/src/sys/mman/linux/shm_common.h b/libc/src/sys/mman/linux/shm_common.h new file mode 100644 index 0000000000000000000000000000000000000000..6f2a3fdc71b64751260666000d519e416cddc5ed --- /dev/null +++ b/libc/src/sys/mman/linux/shm_common.h @@ -0,0 +1,53 @@ +//===---------- Shared implementations for shm_open/shm_unlink ------------===// +// +// 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/array.h" +#include "src/__support/CPP/optional.h" +#include "src/__support/CPP/string_view.h" +#include "src/errno/libc_errno.h" +#include "src/string/memory_utils/inline_memcpy.h" + +// TODO: Get PATH_MAX via https://github.com/llvm/llvm-project/issues/85121 +#include <linux/limits.h> + +namespace LIBC_NAMESPACE { + +namespace shm_common { + +LIBC_INLINE_VAR constexpr cpp::string_view SHM_PREFIX = "/dev/shm/"; +using SHMPath = cpp::array<char, NAME_MAX + SHM_PREFIX.size() + 1>; + +LIBC_INLINE cpp::optional<SHMPath> translate_name(cpp::string_view name) { + // trim leading slashes + size_t offset = name.find_first_not_of('/'); + if (offset == cpp::string_view::npos) { + libc_errno = EINVAL; + return cpp::nullopt; + } + name = name.substr(offset); + + // check the name + if (name.size() > NAME_MAX) { + libc_errno = ENAMETOOLONG; + return cpp::nullopt; + } + if (name == "." || name == ".." || name.contains('/')) { + libc_errno = EINVAL; + return cpp::nullopt; + } + + // prepend the prefix + SHMPath buffer; + inline_memcpy(buffer.data(), SHM_PREFIX.data(), SHM_PREFIX.size()); + inline_memcpy(buffer.data() + SHM_PREFIX.size(), name.data(), name.size()); + buffer[SHM_PREFIX.size() + name.size()] = '\0'; + return buffer; +} +} // namespace shm_common + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/sys/mman/linux/shm_open.cpp b/libc/src/sys/mman/linux/shm_open.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d39b8b4e53dbff825dfac62cbda3fc9a179e456 --- /dev/null +++ b/libc/src/sys/mman/linux/shm_open.cpp @@ -0,0 +1,25 @@ +//===---------- Linux implementation of the shm_open function -------------===// +// +// 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/sys/mman/shm_open.h" +#include "llvm-libc-macros/fcntl-macros.h" +#include "src/fcntl/open.h" +#include "src/sys/mman/linux/shm_common.h" + +namespace LIBC_NAMESPACE { + +static constexpr int DEFAULT_OFLAGS = O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK; + +LLVM_LIBC_FUNCTION(int, shm_open, (const char *name, int oflags, mode_t mode)) { + using namespace shm_common; + if (cpp::optional<SHMPath> buffer = translate_name(name)) + return open(buffer->data(), oflags | DEFAULT_OFLAGS, mode); + return -1; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/sys/mman/linux/shm_unlink.cpp b/libc/src/sys/mman/linux/shm_unlink.cpp new file mode 100644 index 0000000000000000000000000000000000000000..32f48d3e3e71870052a97e4b8fa3e86dbc530ed8 --- /dev/null +++ b/libc/src/sys/mman/linux/shm_unlink.cpp @@ -0,0 +1,22 @@ +//===---------- Linux implementation of the shm_unlink function -----------===// +// +// 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/sys/mman/shm_unlink.h" +#include "src/sys/mman/linux/shm_common.h" +#include "src/unistd/unlink.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, shm_unlink, (const char *name)) { + using namespace shm_common; + if (cpp::optional<SHMPath> buffer = translate_name(name)) + return unlink(buffer->data()); + return -1; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/sys/mman/shm_open.h b/libc/src/sys/mman/shm_open.h new file mode 100644 index 0000000000000000000000000000000000000000..91796d7b5c05010721ae574169fb07976c3cb6d3 --- /dev/null +++ b/libc/src/sys/mman/shm_open.h @@ -0,0 +1,20 @@ +//===-- Implementation header for shm_open 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_SYS_MMAN_SHM_OPEN_H +#define LLVM_LIBC_SRC_SYS_MMAN_SHM_OPEN_H + +#include <llvm-libc-types/mode_t.h> + +namespace LIBC_NAMESPACE { + +int shm_open(const char *name, int oflag, mode_t mode); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_SYS_MMAN_SHM_OPEN_H diff --git a/libc/src/sys/mman/shm_unlink.h b/libc/src/sys/mman/shm_unlink.h new file mode 100644 index 0000000000000000000000000000000000000000..c38c06adbaa292eadb5b8c0e4dce70f84209988c --- /dev/null +++ b/libc/src/sys/mman/shm_unlink.h @@ -0,0 +1,18 @@ +//===-- Implementation header for shm_unlink 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_SYS_MMAN_SHM_UNLINK_H +#define LLVM_LIBC_SRC_SYS_MMAN_SHM_UNLINK_H + +namespace LIBC_NAMESPACE { + +int shm_unlink(const char *name); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_SYS_MMAN_SHM_UNLINK_H diff --git a/libc/src/sys/statvfs/CMakeLists.txt b/libc/src/sys/statvfs/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..6a10187a135a5c6733d579d5a016b04d360ffe71 --- /dev/null +++ b/libc/src/sys/statvfs/CMakeLists.txt @@ -0,0 +1,17 @@ +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) +endif() + +add_entrypoint_object( + statvfs + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.statvfs +) + +add_entrypoint_object( + fstatvfs + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.fstatvfs +) diff --git a/libc/src/sys/statvfs/fstatvfs.h b/libc/src/sys/statvfs/fstatvfs.h new file mode 100644 index 0000000000000000000000000000000000000000..6ca76a459ae5bc36a71dcb1187232e924452c225 --- /dev/null +++ b/libc/src/sys/statvfs/fstatvfs.h @@ -0,0 +1,20 @@ +//===-- Implementation header for fstatvfs ----------------------*- 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_SYS_STATVFS_FSTATVFS_H +#define LLVM_LIBC_SRC_SYS_STATVFS_FSTATVFS_H + +#include "llvm-libc-types/struct_statvfs.h" + +namespace LIBC_NAMESPACE { + +int fstatvfs(int fd, struct statvfs *buf); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_SYS_STATVFS_FSTATVFS_H diff --git a/libc/src/sys/statvfs/linux/CMakeLists.txt b/libc/src/sys/statvfs/linux/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f818863bb4707f474aaa439d53016580b4aef675 --- /dev/null +++ b/libc/src/sys/statvfs/linux/CMakeLists.txt @@ -0,0 +1,36 @@ +add_header_library( + statfs_utils + HDRS + statfs_utils.h + DEPENDS + libc.src.errno.errno + libc.src.__support.OSUtil.osutil + libc.src.__support.common + libc.src.__support.CPP.optional + libc.include.sys_syscall +) + +add_entrypoint_object( + statvfs + SRCS + statvfs.cpp + HDRS + ../statvfs.h + DEPENDS + libc.src.__support.libc_assert + libc.include.llvm-libc-types.struct_statvfs + .statfs_utils +) + +add_entrypoint_object( + fstatvfs + SRCS + fstatvfs.cpp + HDRS + ../fstatvfs.h + DEPENDS + libc.src.__support.libc_assert + libc.include.llvm-libc-types.struct_statvfs + .statfs_utils +) + diff --git a/libc/src/sys/statvfs/linux/fstatvfs.cpp b/libc/src/sys/statvfs/linux/fstatvfs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..488989abbad70e514664985218917971834e604f --- /dev/null +++ b/libc/src/sys/statvfs/linux/fstatvfs.cpp @@ -0,0 +1,26 @@ +//===-- Linux implementation of fstatvfs ----------------------------------===// +// +// 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/sys/statvfs/fstatvfs.h" +#include "src/__support/common.h" +#include "src/__support/libc_assert.h" +#include "src/sys/statvfs/linux/statfs_utils.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, fstatvfs, (int fd, struct statvfs *buf)) { + using namespace statfs_utils; + cpp::optional<LinuxStatFs> result = linux_fstatfs(fd); + if (result) { + LIBC_ASSERT(buf != nullptr); + *buf = statfs_to_statvfs(*result); + } + return result ? 0 : -1; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/sys/statvfs/linux/statfs_utils.h b/libc/src/sys/statvfs/linux/statfs_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..606786a5718381d5c5d31c0b6617347452a3d80e --- /dev/null +++ b/libc/src/sys/statvfs/linux/statfs_utils.h @@ -0,0 +1,95 @@ +//===-- Convert Statfs to Statvfs -------------------------------*- 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_SYS_STATVFS_LINUX_STATFS_TO_STATVFS_H +#define LLVM_LIBC_SRC_SYS_STATVFS_LINUX_STATFS_TO_STATVFS_H + +#include "llvm-libc-types/struct_statvfs.h" +#include "src/__support/CPP/optional.h" +#include "src/__support/OSUtil/syscall.h" +#include "src/__support/macros/attributes.h" +#include "src/errno/libc_errno.h" +#include <asm/statfs.h> +#include <sys/syscall.h> +namespace LIBC_NAMESPACE { + +namespace statfs_utils { +#ifdef SYS_statfs64 +using LinuxStatFs = statfs64; +#else +using LinuxStatFs = statfs; +#endif + +// Linux kernel set an additional flag to f_flags. Libc should mask it out. +LIBC_INLINE_VAR constexpr decltype(LinuxStatFs::f_flags) ST_VALID = 0x0020; + +LIBC_INLINE cpp::optional<LinuxStatFs> linux_statfs(const char *path) { + // The kernel syscall routine checks the validity of the path before filling + // the statfs structure. So, it is possible that the result is not initialized + // after the syscall. Since the struct is trvial, the compiler will generate + // pattern filling for the struct. + LinuxStatFs result; + // On 32-bit platforms, original statfs cannot handle large file systems. + // In such cases, SYS_statfs64 is defined and should be used. +#ifdef SYS_statfs64 + int ret = syscall_impl<int>(SYS_statfs64, path, sizeof(result), &result); +#else + int ret = syscall_impl<int>(SYS_statfs, path, &result); +#endif + if (ret < 0) { + libc_errno = -ret; + return cpp::nullopt; + } + result.f_flags &= ~ST_VALID; + return result; +} + +LIBC_INLINE cpp::optional<LinuxStatFs> linux_fstatfs(int fd) { + // The kernel syscall routine checks the validity of the path before filling + // the statfs structure. So, it is possible that the result is not initialized + // after the syscall. Since the struct is trvial, the compiler will generate + // pattern filling for the struct. + LinuxStatFs result; + // On 32-bit platforms, original fstatfs cannot handle large file systems. + // In such cases, SYS_fstatfs64 is defined and should be used. +#ifdef SYS_fstatfs64 + int ret = syscall_impl<int>(SYS_fstatfs64, fd, sizeof(result), &result); +#else + int ret = syscall_impl<int>(SYS_fstatfs, fd, &result); +#endif + if (ret < 0) { + libc_errno = -ret; + return cpp::nullopt; + } + result.f_flags &= ~ST_VALID; + return result; +} + +// must use 'struct' tag to refer to type 'statvfs' in this scope. There will be +// a function in the same namespace with the same name. For consistency, we use +// struct prefix for all statvfs/statfs related types. +LIBC_INLINE struct statvfs statfs_to_statvfs(const LinuxStatFs &in) { + struct statvfs out; + out.f_bsize = in.f_bsize; + out.f_frsize = in.f_frsize; + out.f_blocks = in.f_blocks; + out.f_bfree = in.f_bfree; + out.f_bavail = in.f_bavail; + out.f_files = in.f_files; + out.f_ffree = in.f_ffree; + out.f_favail = in.f_ffree; + out.f_fsid = in.f_fsid.val[0] | + static_cast<decltype(out.f_fsid)>(in.f_fsid.val[1]) << 32; + out.f_flag = in.f_flags; + out.f_namemax = in.f_namelen; + return out; +} +} // namespace statfs_utils +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_SYS_STATVFS_LINUX_STATFS_TO_STATVFS_H diff --git a/libc/src/sys/statvfs/linux/statvfs.cpp b/libc/src/sys/statvfs/linux/statvfs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a438ef1f0117e3c3f2d95fda7a5ebcc34c9a0857 --- /dev/null +++ b/libc/src/sys/statvfs/linux/statvfs.cpp @@ -0,0 +1,28 @@ +//===-- Linux implementation of statvfs -----------------------------------===// +// +// 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/sys/statvfs/statvfs.h" +#include "src/__support/common.h" +#include "src/__support/libc_assert.h" +#include "src/sys/statvfs/linux/statfs_utils.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(int, statvfs, + (const char *__restrict path, + struct statvfs *__restrict buf)) { + using namespace statfs_utils; + cpp::optional<LinuxStatFs> result = linux_statfs(path); + if (result) { + LIBC_ASSERT(buf != nullptr); + *buf = statfs_to_statvfs(*result); + } + return result ? 0 : -1; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/sys/statvfs/statvfs.h b/libc/src/sys/statvfs/statvfs.h new file mode 100644 index 0000000000000000000000000000000000000000..792c7ddd0164ec0bcc460a81b2f93d9862cbe0e4 --- /dev/null +++ b/libc/src/sys/statvfs/statvfs.h @@ -0,0 +1,20 @@ +//===-- Implementation header for statvfs -----------------------*- 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_SYS_STATVFS_STATVFS_H +#define LLVM_LIBC_SRC_SYS_STATVFS_STATVFS_H + +#include "llvm-libc-types/struct_statvfs.h" + +namespace LIBC_NAMESPACE { + +int statvfs(const char *__restrict path, struct statvfs *__restrict buf); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_SYS_STATVFS_STATVFS_H diff --git a/libc/src/unistd/CMakeLists.txt b/libc/src/unistd/CMakeLists.txt index e22b0e1872caa1b1f5f86663ad1a94589dac6d8e..58b44f5307ca7e9984883fd94ab6f1f4bf30d96e 100644 --- a/libc/src/unistd/CMakeLists.txt +++ b/libc/src/unistd/CMakeLists.txt @@ -2,6 +2,17 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) endif() +add_entrypoint_object( + _exit + SRCS + _exit.cpp + HDRS + _exit.h + DEPENDS + libc.include.unistd + libc.src.__support.OSUtil.osutil +) + add_entrypoint_object( access ALIAS diff --git a/libc/src/unistd/_exit.cpp b/libc/src/unistd/_exit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6fbf3a51d42f461e403c3a971f4503d12e9412d3 --- /dev/null +++ b/libc/src/unistd/_exit.cpp @@ -0,0 +1,19 @@ +//===------------------- Implementation of _exit --------------------------===// +// +// 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/unistd/_exit.h" +#include "src/__support/OSUtil/quick_exit.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +[[noreturn]] LLVM_LIBC_FUNCTION(void, _exit, (int status)) { + quick_exit(status); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/unistd/_exit.h b/libc/src/unistd/_exit.h new file mode 100644 index 0000000000000000000000000000000000000000..141b8753218915d78bc9489ca6187178ac7c05f6 --- /dev/null +++ b/libc/src/unistd/_exit.h @@ -0,0 +1,18 @@ +//===-- Implementation header for _exit -------------------------*- 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_UNISTD__EXIT_H +#define LLVM_LIBC_SRC_UNISTD__EXIT_H + +namespace LIBC_NAMESPACE { + +[[noreturn]] void _exit(int status); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_UNISTD__EXIT_H diff --git a/libc/test/UnitTest/CMakeLists.txt b/libc/test/UnitTest/CMakeLists.txt index f7a6f4a91fabcf41bdf4b7ec3d7418638ad13780..d830d22bb540e948370fab590d3c464815b0f90d 100644 --- a/libc/test/UnitTest/CMakeLists.txt +++ b/libc/test/UnitTest/CMakeLists.txt @@ -118,6 +118,7 @@ add_unittest_framework_library( DEPENDS LibcTest libc.test.UnitTest.string_utils + libc.src.__support.CPP.array libc.src.__support.FPUtil.fp_bits libc.src.__support.FPUtil.fpbits_str libc.src.__support.FPUtil.fenv_impl diff --git a/libc/test/UnitTest/FPMatcher.h b/libc/test/UnitTest/FPMatcher.h index 4525b9e830195e8e68ece3dfd187686ef4f265e0..f4553eac5c8a57e485daf5e11fcb50705df8e033 100644 --- a/libc/test/UnitTest/FPMatcher.h +++ b/libc/test/UnitTest/FPMatcher.h @@ -9,6 +9,7 @@ #ifndef LLVM_LIBC_TEST_UNITTEST_FPMATCHER_H #define LLVM_LIBC_TEST_UNITTEST_FPMATCHER_H +#include "src/__support/CPP/array.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/FPUtil/FEnvImpl.h" #include "src/__support/FPUtil/FPBits.h" @@ -17,7 +18,7 @@ #include "test/UnitTest/StringUtils.h" #include "test/UnitTest/Test.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" namespace LIBC_NAMESPACE { namespace testing { @@ -63,7 +64,6 @@ template <TestCond C, typename T> FPMatcher<T, C> getMatcher(T expectedValue) { template <typename T> struct FPTest : public Test { using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; using StorageType = typename FPBits::StorageType; - using Sign = LIBC_NAMESPACE::fputil::Sign; static constexpr StorageType STORAGE_MAX = LIBC_NAMESPACE::cpp::numeric_limits<StorageType>::max(); static constexpr T zero = FPBits::zero(Sign::POS).get_val(); @@ -92,7 +92,7 @@ template <typename T> struct FPTest : public Test { #define DECLARE_SPECIAL_CONSTANTS(T) \ using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; \ using StorageType = typename FPBits::StorageType; \ - using Sign = LIBC_NAMESPACE::fputil::Sign; \ + \ static constexpr StorageType STORAGE_MAX = \ LIBC_NAMESPACE::cpp::numeric_limits<StorageType>::max(); \ const T zero = FPBits::zero(Sign::POS).get_val(); \ @@ -102,9 +102,18 @@ template <typename T> struct FPTest : public Test { const T inf = FPBits::inf(Sign::POS).get_val(); \ const T neg_inf = FPBits::inf(Sign::NEG).get_val(); \ const T min_normal = FPBits::min_normal().get_val(); \ - const T max_normal = FPBits::max_normal().get_val(); \ - const T min_denormal = FPBits::min_subnormal().get_val(); \ - const T max_denormal = FPBits::max_subnormal().get_val(); + const T max_normal = FPBits::max_normal(Sign::POS).get_val(); \ + const T neg_max_normal = FPBits::max_normal(Sign::NEG).get_val(); \ + const T min_denormal = FPBits::min_subnormal(Sign::POS).get_val(); \ + const T neg_min_denormal = FPBits::min_subnormal(Sign::NEG).get_val(); \ + const T max_denormal = FPBits::max_subnormal().get_val(); \ + static constexpr int UNKNOWN_MATH_ROUNDING_DIRECTION = 99; \ + static constexpr LIBC_NAMESPACE::cpp::array<int, 6> \ + MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN = { \ + FP_INT_UPWARD, FP_INT_DOWNWARD, \ + FP_INT_TOWARDZERO, FP_INT_TONEARESTFROMZERO, \ + FP_INT_TONEAREST, UNKNOWN_MATH_ROUNDING_DIRECTION, \ + }; #define EXPECT_FP_EQ(expected, actual) \ EXPECT_THAT(actual, LIBC_NAMESPACE::testing::getMatcher< \ diff --git a/libc/test/UnitTest/PrintfMatcher.cpp b/libc/test/UnitTest/PrintfMatcher.cpp index 32f3be73307e3a54dde5850d4c4a224c30adc899..c8303815c9229645acd6c578dc4f19755d5a2b5a 100644 --- a/libc/test/UnitTest/PrintfMatcher.cpp +++ b/libc/test/UnitTest/PrintfMatcher.cpp @@ -39,6 +39,10 @@ namespace { case (LengthModifier::lm): \ tlog << #lm; \ break +#define CASE_LM_BIT_WIDTH(lm, bw) \ + case (LengthModifier::lm): \ + tlog << #lm << "\n\tbit width: :" << bw; \ + break static void display(FormatSection form) { tlog << "Raw String (len " << form.raw_string.size() << "): \""; @@ -67,6 +71,8 @@ static void display(FormatSection form) { CASE_LM(z); CASE_LM(t); CASE_LM(L); + CASE_LM_BIT_WIDTH(w, form.bit_width); + CASE_LM_BIT_WIDTH(wf, form.bit_width); } tlog << "\n"; tlog << "\tconversion name: " << form.conv_name << "\n"; diff --git a/libc/test/src/__support/CPP/CMakeLists.txt b/libc/test/src/__support/CPP/CMakeLists.txt index f94429e03b3cbc6f60dc9155448b8464753811a9..74aa0c705ec467b5d9ee8a5ae0b5ba9be7abf754 100644 --- a/libc/test/src/__support/CPP/CMakeLists.txt +++ b/libc/test/src/__support/CPP/CMakeLists.txt @@ -1,5 +1,15 @@ add_custom_target(libc-cpp-utils-tests) +add_libc_test( + array_test + SUITE + libc-cpp-utils-tests + SRCS + array_test.cpp + DEPENDS + libc.src.__support.CPP.array + ) + add_libc_test( bit_test SUITE diff --git a/libc/test/src/__support/CPP/array_test.cpp b/libc/test/src/__support/CPP/array_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f2d7bff636e42c1dbc0a4cc1db715398a6bbfb75 --- /dev/null +++ b/libc/test/src/__support/CPP/array_test.cpp @@ -0,0 +1,66 @@ +//===-- Unittests for Array -----------------------------------------------===// +// +// 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/array.h" +#include "test/UnitTest/Test.h" + +using LIBC_NAMESPACE::cpp::array; + +TEST(LlvmLibcArrayTest, Basic) { + array<int, 3> a = {0, 1, 2}; + + ASSERT_EQ(a.data(), &a.front()); + ASSERT_EQ(a.front(), 0); + ASSERT_EQ(a.back(), 2); + ASSERT_EQ(a.size(), size_t{3}); + ASSERT_EQ(a[1], 1); + ASSERT_FALSE(a.empty()); + ASSERT_NE(a.begin(), a.end()); + ASSERT_EQ(*a.begin(), a.front()); + + auto it = a.rbegin(); + ASSERT_EQ(*it, 2); + ASSERT_EQ(*(++it), 1); + ASSERT_EQ(*(++it), 0); + + for (int &x : a) + ASSERT_GE(x, 0); +} + +// Test const_iterator and const variant methods. +TEST(LlvmLibcArrayTest, Const) { + const array<int, 3> z = {3, 4, 5}; + + ASSERT_EQ(3, z.front()); + ASSERT_EQ(4, z[1]); + ASSERT_EQ(5, z.back()); + ASSERT_EQ(3, *z.data()); + + // begin, cbegin, end, cend + array<int, 3>::const_iterator it2 = z.begin(); + ASSERT_EQ(*it2, z.front()); + it2 = z.cbegin(); + ASSERT_EQ(*it2, z.front()); + it2 = z.end(); + ASSERT_NE(it2, z.begin()); + it2 = z.cend(); + ASSERT_NE(it2, z.begin()); + + // rbegin, crbegin, rend, crend + array<int, 3>::const_reverse_iterator it = z.rbegin(); + ASSERT_EQ(*it, z.back()); + it = z.crbegin(); + ASSERT_EQ(*it, z.back()); + it = z.rend(); + ASSERT_EQ(*--it, z.front()); + it = z.crend(); + ASSERT_EQ(*--it, z.front()); + + for (const int &x : z) + ASSERT_GE(x, 0); +} diff --git a/libc/test/src/__support/CPP/bit_test.cpp b/libc/test/src/__support/CPP/bit_test.cpp index cee5b90c8f4bdb4e31bf113120e22f6b8f7b8018..875b47e6a1980eb10a6fac2fdee9c46a4d2e3051 100644 --- a/libc/test/src/__support/CPP/bit_test.cpp +++ b/libc/test/src/__support/CPP/bit_test.cpp @@ -15,13 +15,6 @@ namespace LIBC_NAMESPACE::cpp { -using UnsignedTypesNoBigInt = testing::TypeList< -#if defined(LIBC_TYPES_HAS_INT128) - __uint128_t, -#endif // LIBC_TYPES_HAS_INT128 - unsigned char, unsigned short, unsigned int, unsigned long, - unsigned long long>; - using UnsignedTypes = testing::TypeList< #if defined(LIBC_TYPES_HAS_INT128) __uint128_t, @@ -228,7 +221,7 @@ TEST(LlvmLibcBitTest, Rotr) { rotr<uint64_t>(0x12345678deadbeefULL, -19)); } -TYPED_TEST(LlvmLibcBitTest, CountOnes, UnsignedTypesNoBigInt) { +TYPED_TEST(LlvmLibcBitTest, CountOnes, UnsignedTypes) { EXPECT_EQ(popcount(T(0)), 0); for (int i = 0; i != cpp::numeric_limits<T>::digits; ++i) EXPECT_EQ(popcount<T>(cpp::numeric_limits<T>::max() >> i), diff --git a/libc/test/src/__support/CPP/stringview_test.cpp b/libc/test/src/__support/CPP/stringview_test.cpp index 33eb8ab4765728af6a55c121d6e27a35ce7730a3..6b68f2a1c47a9d608bb4c031b0585f8826a7d56d 100644 --- a/libc/test/src/__support/CPP/stringview_test.cpp +++ b/libc/test/src/__support/CPP/stringview_test.cpp @@ -174,3 +174,111 @@ TEST(LlvmLibcStringViewTest, FindLastOf) { ASSERT_EQ(Empty1.find_last_of('a', 0), string_view::npos); ASSERT_EQ(Empty1.find_last_of('a', 123), string_view::npos); } + +TEST(LlvmLibcStringViewTest, FindFirstNotOf) { + string_view Tmp("abada"); + + EXPECT_EQ(Tmp.find_first_not_of('a'), size_t(1)); + EXPECT_EQ(Tmp.find_first_not_of('a', 123), string_view::npos); + EXPECT_EQ(Tmp.find_first_not_of('a', 5), string_view::npos); + EXPECT_EQ(Tmp.find_first_not_of('a', 4), string_view::npos); + EXPECT_EQ(Tmp.find_first_not_of('a', 3), size_t(3)); + EXPECT_EQ(Tmp.find_first_not_of('a', 2), size_t(3)); + EXPECT_EQ(Tmp.find_first_not_of('a', 1), size_t(1)); + EXPECT_EQ(Tmp.find_first_not_of('a', 0), size_t(1)); + + EXPECT_EQ(Tmp.find_first_not_of('b'), size_t(0)); + EXPECT_EQ(Tmp.find_first_not_of('b', 123), string_view::npos); + EXPECT_EQ(Tmp.find_first_not_of('b', 5), string_view::npos); + EXPECT_EQ(Tmp.find_first_not_of('b', 4), size_t(4)); + EXPECT_EQ(Tmp.find_first_not_of('b', 3), size_t(3)); + EXPECT_EQ(Tmp.find_first_not_of('b', 2), size_t(2)); + EXPECT_EQ(Tmp.find_first_not_of('b', 1), size_t(2)); + EXPECT_EQ(Tmp.find_first_not_of('b', 0), size_t(0)); + + EXPECT_EQ(Tmp.find_first_not_of('d'), size_t(0)); + EXPECT_EQ(Tmp.find_first_not_of('d', 123), string_view::npos); + EXPECT_EQ(Tmp.find_first_not_of('d', 5), string_view::npos); + EXPECT_EQ(Tmp.find_first_not_of('d', 4), size_t(4)); + EXPECT_EQ(Tmp.find_first_not_of('d', 3), size_t(4)); + EXPECT_EQ(Tmp.find_first_not_of('d', 2), size_t(2)); + EXPECT_EQ(Tmp.find_first_not_of('d', 1), size_t(1)); + EXPECT_EQ(Tmp.find_first_not_of('d', 0), size_t(0)); + + EXPECT_EQ(Tmp.find_first_not_of('e'), size_t(0)); + EXPECT_EQ(Tmp.find_first_not_of('e', 123), string_view::npos); + EXPECT_EQ(Tmp.find_first_not_of('e', 5), string_view::npos); + EXPECT_EQ(Tmp.find_first_not_of('e', 4), size_t(4)); + EXPECT_EQ(Tmp.find_first_not_of('e', 3), size_t(3)); + EXPECT_EQ(Tmp.find_first_not_of('e', 2), size_t(2)); + EXPECT_EQ(Tmp.find_first_not_of('e', 1), size_t(1)); + EXPECT_EQ(Tmp.find_first_not_of('e', 0), size_t(0)); + + string_view Empty; + EXPECT_EQ(Empty.find_first_not_of('a'), string_view::npos); + EXPECT_EQ(Empty.find_first_not_of('a', 0), string_view::npos); + EXPECT_EQ(Empty.find_first_not_of('a', 123), string_view::npos); + + string_view Empty1(""); + EXPECT_EQ(Empty1.find_first_not_of('a'), string_view::npos); + EXPECT_EQ(Empty1.find_first_not_of('a', 0), string_view::npos); + EXPECT_EQ(Empty1.find_first_not_of('a', 123), string_view::npos); + + string_view Full("aaaaaaa"); + EXPECT_EQ(Full.find_first_not_of('a'), string_view::npos); + EXPECT_EQ(Full.find_first_not_of('a', 0), string_view::npos); + EXPECT_EQ(Full.find_first_not_of('a', 123), string_view::npos); + + EXPECT_EQ(Full.find_first_not_of('b'), size_t(0)); + EXPECT_EQ(Full.find_first_not_of('b', 0), size_t(0)); + EXPECT_EQ(Full.find_first_not_of('b', 123), string_view::npos); +} + +TEST(LlvmLibcStringViewTest, Contains) { + string_view Empty; + for (char c = 'a'; c < 'z'; ++c) + EXPECT_FALSE(Empty.contains(c)); + + string_view Tmp("abada"); + EXPECT_TRUE(Tmp.contains('a')); + EXPECT_TRUE(Tmp.contains('b')); + EXPECT_FALSE(Tmp.contains('c')); + EXPECT_TRUE(Tmp.contains('d')); + EXPECT_FALSE(Tmp.contains('e')); + + EXPECT_TRUE(Tmp.substr(1).contains('a')); + EXPECT_TRUE(Tmp.substr(1).contains('b')); + EXPECT_FALSE(Tmp.substr(1).contains('c')); + EXPECT_TRUE(Tmp.substr(1).contains('d')); + EXPECT_FALSE(Tmp.substr(1).contains('e')); + + EXPECT_TRUE(Tmp.substr(2).contains('a')); + EXPECT_FALSE(Tmp.substr(2).contains('b')); + EXPECT_FALSE(Tmp.substr(2).contains('c')); + EXPECT_TRUE(Tmp.substr(2).contains('d')); + EXPECT_FALSE(Tmp.substr(2).contains('e')); + + EXPECT_TRUE(Tmp.substr(3).contains('a')); + EXPECT_FALSE(Tmp.substr(3).contains('b')); + EXPECT_FALSE(Tmp.substr(3).contains('c')); + EXPECT_TRUE(Tmp.substr(3).contains('d')); + EXPECT_FALSE(Tmp.substr(3).contains('e')); + + EXPECT_TRUE(Tmp.substr(4).contains('a')); + EXPECT_FALSE(Tmp.substr(4).contains('b')); + EXPECT_FALSE(Tmp.substr(4).contains('c')); + EXPECT_FALSE(Tmp.substr(4).contains('d')); + EXPECT_FALSE(Tmp.substr(4).contains('e')); + + EXPECT_FALSE(Tmp.substr(5).contains('a')); + EXPECT_FALSE(Tmp.substr(5).contains('b')); + EXPECT_FALSE(Tmp.substr(5).contains('c')); + EXPECT_FALSE(Tmp.substr(5).contains('d')); + EXPECT_FALSE(Tmp.substr(5).contains('e')); + + EXPECT_FALSE(Tmp.substr(6).contains('a')); + EXPECT_FALSE(Tmp.substr(6).contains('b')); + EXPECT_FALSE(Tmp.substr(6).contains('c')); + EXPECT_FALSE(Tmp.substr(6).contains('d')); + EXPECT_FALSE(Tmp.substr(6).contains('e')); +} diff --git a/libc/test/src/__support/FPUtil/CMakeLists.txt b/libc/test/src/__support/FPUtil/CMakeLists.txt index f1a027a514ba237ca39d1c3f6753de560d6d10e0..1cbeec0cc4eb0815a8d27d4a8e5535682b26f48c 100644 --- a/libc/test/src/__support/FPUtil/CMakeLists.txt +++ b/libc/test/src/__support/FPUtil/CMakeLists.txt @@ -24,6 +24,7 @@ add_libc_test( libc.src.__support.FPUtil.fp_bits libc.src.__support.FPUtil.fpbits_str libc.src.__support.integer_literals + libc.src.__support.sign ) add_fp_unittest( diff --git a/libc/test/src/__support/FPUtil/dyadic_float_test.cpp b/libc/test/src/__support/FPUtil/dyadic_float_test.cpp index 625aa70973b9f1b9511c3bc177e8490aa7137bba..5ee9aaad5638278433be371724e07c173b0119b1 100644 --- a/libc/test/src/__support/FPUtil/dyadic_float_test.cpp +++ b/libc/test/src/__support/FPUtil/dyadic_float_test.cpp @@ -15,7 +15,6 @@ using Float128 = LIBC_NAMESPACE::fputil::DyadicFloat<128>; using Float192 = LIBC_NAMESPACE::fputil::DyadicFloat<192>; using Float256 = LIBC_NAMESPACE::fputil::DyadicFloat<256>; -using Sign = LIBC_NAMESPACE::fputil::Sign; TEST(LlvmLibcDyadicFloatTest, BasicConversions) { Float128 x(Sign::POS, /*exponent*/ 0, diff --git a/libc/test/src/__support/FPUtil/fpbits_test.cpp b/libc/test/src/__support/FPUtil/fpbits_test.cpp index f5c27d4fc0302b4eedad8ab52da103a6ced71b34..af20b1a0bdc7efaffe113fb4e375dbb34bce0ea6 100644 --- a/libc/test/src/__support/FPUtil/fpbits_test.cpp +++ b/libc/test/src/__support/FPUtil/fpbits_test.cpp @@ -9,11 +9,11 @@ #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/fpbits_str.h" #include "src/__support/integer_literals.h" +#include "src/__support/sign.h" // Sign #include "test/UnitTest/Test.h" using LIBC_NAMESPACE::fputil::FPBits; using LIBC_NAMESPACE::fputil::FPType; -using LIBC_NAMESPACE::fputil::Sign; using LIBC_NAMESPACE::fputil::internal::FPRep; using LIBC_NAMESPACE::operator""_u16; diff --git a/libc/test/src/__support/arg_list_test.cpp b/libc/test/src/__support/arg_list_test.cpp index 1876cf7f70b4b8187ef78b988029efcf2753d186..4f229e2bfe69408bcbf012e5f3d12a1f4c81cffa 100644 --- a/libc/test/src/__support/arg_list_test.cpp +++ b/libc/test/src/__support/arg_list_test.cpp @@ -120,7 +120,7 @@ TEST(LlvmLibcArgListTest, TestStructTypes) { } // Test vector extensions from clang. -#if LIBC_HAS_ATTRIBUTE(ext_vector_type) +#if __has_attribute(ext_vector_type) using int1 = int __attribute__((ext_vector_type(1))); using int2 = int __attribute__((ext_vector_type(2))); diff --git a/libc/test/src/__support/blockstore_test.cpp b/libc/test/src/__support/blockstore_test.cpp index f62857275fe4c908137a49dd0e094879a5daa0fc..5fe8fef1b6edcca70a42e9eca13330ad1dbcd969 100644 --- a/libc/test/src/__support/blockstore_test.cpp +++ b/libc/test/src/__support/blockstore_test.cpp @@ -19,7 +19,7 @@ class LlvmLibcBlockStoreTest : public LIBC_NAMESPACE::testing::Test { public: template <size_t BLOCK_SIZE, size_t ELEMENT_COUNT, bool REVERSE> void populate_and_iterate() { - LIBC_NAMESPACE::cpp::BlockStore<Element, BLOCK_SIZE, REVERSE> block_store; + LIBC_NAMESPACE::BlockStore<Element, BLOCK_SIZE, REVERSE> block_store; for (int i = 0; i < int(ELEMENT_COUNT); ++i) ASSERT_TRUE(block_store.push_back({i, 2 * i, 3 * unsigned(i)})); auto end = block_store.end(); @@ -38,12 +38,12 @@ public: } } ASSERT_EQ(i, int(ELEMENT_COUNT)); - LIBC_NAMESPACE::cpp::BlockStore<Element, BLOCK_SIZE, REVERSE>::destroy( + LIBC_NAMESPACE::BlockStore<Element, BLOCK_SIZE, REVERSE>::destroy( &block_store); } template <bool REVERSE> void back_test() { - using LIBC_NAMESPACE::cpp::BlockStore; + using LIBC_NAMESPACE::BlockStore; BlockStore<int, 4, REVERSE> block_store; for (int i = 0; i < 20; i++) ASSERT_TRUE(block_store.push_back(i)); @@ -53,7 +53,7 @@ public: } template <bool REVERSE> void empty_test() { - using LIBC_NAMESPACE::cpp::BlockStore; + using LIBC_NAMESPACE::BlockStore; BlockStore<int, 2, REVERSE> block_store; ASSERT_TRUE(block_store.empty()); diff --git a/libc/test/src/__support/fixedvector_test.cpp b/libc/test/src/__support/fixedvector_test.cpp index a70ebfabed227009f9d4da30b133d6290a32f6d8..4e92081321de7ae1fe72e7910d78836d2f9341ef 100644 --- a/libc/test/src/__support/fixedvector_test.cpp +++ b/libc/test/src/__support/fixedvector_test.cpp @@ -43,3 +43,19 @@ TEST(LlvmLibcFixedVectorTest, Destroy) { LIBC_NAMESPACE::FixedVector<int, 20>::destroy(&fixed_vector); ASSERT_TRUE(fixed_vector.empty()); } + +TEST(LlvmLibcFixedVectorTest, Iteration) { + LIBC_NAMESPACE::FixedVector<int, 20> v; + for (int i = 0; i < 3; i++) + v.push_back(i); + auto it = v.rbegin(); + ASSERT_EQ(*it, 2); + ASSERT_EQ(*++it, 1); + ASSERT_EQ(*++it, 0); + // TODO: need an overload of Test::test for iterators? + // ASSERT_EQ(++it, v.rend()); + // ASSERT_EQ(v.rbegin(), v.rbegin()); + ASSERT_TRUE(++it == v.rend()); + for (auto it = v.rbegin(), e = v.rend(); it != e; ++it) + ASSERT_GT(*it, -1); +} diff --git a/libc/test/src/__support/math_extras_test.cpp b/libc/test/src/__support/math_extras_test.cpp index e642248881a41c29f6aad47a5a0bd14c8c656e9b..e88b3e1d6b687b1a1cd66426311f438dbd3b4565 100644 --- a/libc/test/src/__support/math_extras_test.cpp +++ b/libc/test/src/__support/math_extras_test.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "src/__support/UInt128.h" // UInt128 +#include "src/__support/UInt128.h" // UInt<128> #include "src/__support/integer_literals.h" #include "src/__support/math_extras.h" #include "test/UnitTest/Test.h" @@ -19,7 +19,7 @@ using UnsignedTypesNoBigInt = testing::TypeList< __uint128_t, #endif // LIBC_TYPES_HAS_INT128 unsigned char, unsigned short, unsigned int, unsigned long, - unsigned long long>; + unsigned long long, UInt<128>>; TEST(LlvmLibcBlockMathExtrasTest, mask_trailing_ones) { EXPECT_EQ(0_u8, (mask_leading_ones<uint8_t, 0>())); diff --git a/libc/test/src/__support/uint_test.cpp b/libc/test/src/__support/uint_test.cpp index 851656e9fcbbb036b65935724d103bfa014f8c45..5764324ca28815075e6970f09fc3fc92d270211f 100644 --- a/libc/test/src/__support/uint_test.cpp +++ b/libc/test/src/__support/uint_test.cpp @@ -10,8 +10,8 @@ #include "src/__support/UInt.h" #include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128 +#include "include/llvm-libc-macros/math-macros.h" // HUGE_VALF, HUGE_VALF #include "test/UnitTest/Test.h" -#include <math.h> // HUGE_VALF, HUGE_VALF namespace LIBC_NAMESPACE { diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt index b8a4aafcd97aa27e572666536bca2ac05f893f61..f8f0f8ba7b6f63879f149c59918db51ecb795c14 100644 --- a/libc/test/src/math/CMakeLists.txt +++ b/libc/test/src/math/CMakeLists.txt @@ -1273,6 +1273,21 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + nextafterf128_test + SUITE + libc-math-unittests + SRCS + nextafterf128_test.cpp + HDRS + NextAfterTest.h + DEPENDS + libc.include.math + libc.src.math.nextafterf128 + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.fp_bits +) + # TODO(lntue): The current implementation of fputil::general::fma<float> is only # correctly rounded for the default rounding mode round-to-nearest tie-to-even. add_fp_unittest( @@ -1503,6 +1518,8 @@ add_fp_unittest( DEPENDS libc.include.math libc.src.math.generic.explogxf + libc.src.math.fabs + libc.src.math.fabsf libc.src.__support.FPUtil.fp_bits ) @@ -1628,20 +1645,6 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) -add_fp_unittest( - inv_trigf_utils_test - NEED_MPFR - SUITE - libc-math-unittests - HDRS - in_float_range_test_helper.h - SRCS - inv_trigf_utils_test.cpp - DEPENDS - libc.src.math.generic.inv_trigf_utils - libc.src.__support.FPUtil.fp_bits -) - add_fp_unittest( scalbn_test NEED_MPFR @@ -1716,6 +1719,19 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + atan2f_test + NEED_MPFR + SUITE + libc-math-unittests + SRCS + atan2f_test.cpp + DEPENDS + libc.include.math + libc.src.math.atan2f + libc.src.__support.FPUtil.fp_bits +) + add_subdirectory(generic) add_subdirectory(smoke) diff --git a/libc/test/src/math/CeilTest.h b/libc/test/src/math/CeilTest.h index 5ea4f349d008b3dbb6b9537886404a7d1b0f619c..74cc90614dfc2ae17153f98cf0bcf3bc3026567e 100644 --- a/libc/test/src/math/CeilTest.h +++ b/libc/test/src/math/CeilTest.h @@ -10,7 +10,7 @@ #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" namespace mpfr = LIBC_NAMESPACE::testing::mpfr; diff --git a/libc/test/src/math/CopySignTest.h b/libc/test/src/math/CopySignTest.h index 8b81e8d7de25231b1411a39d7fd8ef3f367ae46a..206626d66f580683631b7b89523ba8e4178636d9 100644 --- a/libc/test/src/math/CopySignTest.h +++ b/libc/test/src/math/CopySignTest.h @@ -10,7 +10,7 @@ #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" namespace mpfr = LIBC_NAMESPACE::testing::mpfr; diff --git a/libc/test/src/math/FAbsTest.h b/libc/test/src/math/FAbsTest.h index 54f5f87e08e7e3903b52e42006add5cf5f57ace8..942991f23be1c6a7c8051a20c9f9dd9ae593ee03 100644 --- a/libc/test/src/math/FAbsTest.h +++ b/libc/test/src/math/FAbsTest.h @@ -13,7 +13,7 @@ #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" namespace mpfr = LIBC_NAMESPACE::testing::mpfr; diff --git a/libc/test/src/math/FDimTest.h b/libc/test/src/math/FDimTest.h index e00b4fd5c42ec0df7261af2619bd220961e51821..df8de91b429802e562981f1327a16bb169c13d7d 100644 --- a/libc/test/src/math/FDimTest.h +++ b/libc/test/src/math/FDimTest.h @@ -6,11 +6,11 @@ // //===---------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/BasicOperations.h" #include "src/__support/FPUtil/FPBits.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> template <typename T> class FDimTestTemplate : public LIBC_NAMESPACE::testing::Test { @@ -18,7 +18,6 @@ public: using FuncPtr = T (*)(T, T); using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; using StorageType = typename FPBits::StorageType; - using Sign = LIBC_NAMESPACE::fputil::Sign; const T inf = FPBits::inf(Sign::POS).get_val(); const T neg_inf = FPBits::inf(Sign::NEG).get_val(); diff --git a/libc/test/src/math/FMaxTest.h b/libc/test/src/math/FMaxTest.h index f8046f380f5fd5d722091a5e063ad7d5e8f5c2d2..2c7dc3dc13ec5a79ddc4f9ce56576523bba2e282 100644 --- a/libc/test/src/math/FMaxTest.h +++ b/libc/test/src/math/FMaxTest.h @@ -13,7 +13,7 @@ #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" namespace mpfr = LIBC_NAMESPACE::testing::mpfr; diff --git a/libc/test/src/math/FMinTest.h b/libc/test/src/math/FMinTest.h index 7a6534f320c92a85b422d70a03c59762b9fc56ff..a986d5240d0da75ba09398195b8a41ffd960a2c9 100644 --- a/libc/test/src/math/FMinTest.h +++ b/libc/test/src/math/FMinTest.h @@ -13,7 +13,7 @@ #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" namespace mpfr = LIBC_NAMESPACE::testing::mpfr; diff --git a/libc/test/src/math/FModTest.h b/libc/test/src/math/FModTest.h index 2b1442923268d9cab6ec8f8cc033df81bf8c10b2..96ad299258a176bbfc87db5ee8419a16895dd782 100644 --- a/libc/test/src/math/FModTest.h +++ b/libc/test/src/math/FModTest.h @@ -14,7 +14,7 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" #define TEST_SPECIAL(x, y, expected, dom_err, expected_exception) \ EXPECT_FP_EQ(expected, f(x, y)); \ diff --git a/libc/test/src/math/FloorTest.h b/libc/test/src/math/FloorTest.h index 66b37d69d7ba3db499159533c991426d6dfa99da..21ae291e61bc7e70b217a3960533d8538e32b37d 100644 --- a/libc/test/src/math/FloorTest.h +++ b/libc/test/src/math/FloorTest.h @@ -13,7 +13,7 @@ #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" namespace mpfr = LIBC_NAMESPACE::testing::mpfr; diff --git a/libc/test/src/math/FmaTest.h b/libc/test/src/math/FmaTest.h index 34c582c182421150b36522311e1b9e806ddde5ec..0c93ec858a12cd0789dc6add695c3738af725f9b 100644 --- a/libc/test/src/math/FmaTest.h +++ b/libc/test/src/math/FmaTest.h @@ -23,7 +23,6 @@ private: using Func = T (*)(T, T, T); using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; using StorageType = typename FPBits::StorageType; - using Sign = LIBC_NAMESPACE::fputil::Sign; const T min_subnormal = FPBits::min_subnormal(Sign::POS).get_val(); const T min_normal = FPBits::min_normal(Sign::POS).get_val(); diff --git a/libc/test/src/math/FrexpTest.h b/libc/test/src/math/FrexpTest.h index f3a64ce4aac31fb6a51a26f06d0652f8d83ea3d2..f971b45628f09f713e24afa934446a663a1c56ca 100644 --- a/libc/test/src/math/FrexpTest.h +++ b/libc/test/src/math/FrexpTest.h @@ -11,7 +11,7 @@ #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" namespace mpfr = LIBC_NAMESPACE::testing::mpfr; diff --git a/libc/test/src/math/HypotTest.h b/libc/test/src/math/HypotTest.h index 8f84024a6ee11797bc21138aa3d15709b25c8fcb..df69965d5dbcedb14dbbd1da85180309a4e15676 100644 --- a/libc/test/src/math/HypotTest.h +++ b/libc/test/src/math/HypotTest.h @@ -14,7 +14,7 @@ #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" namespace mpfr = LIBC_NAMESPACE::testing::mpfr; @@ -23,7 +23,7 @@ class HypotTestTemplate : public LIBC_NAMESPACE::testing::Test { private: using Func = T (*)(T, T); using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; - using Sign = LIBC_NAMESPACE::fputil::Sign; + using StorageType = typename FPBits::StorageType; const T nan = FPBits::quiet_nan().get_val(); const T inf = FPBits::inf().get_val(); diff --git a/libc/test/src/math/ILogbTest.h b/libc/test/src/math/ILogbTest.h index 3e2db33e2c052451c0e9659e1608193323239b06..ad47b9bb3961fd9be4bc2b5d811c1072591cea7c 100644 --- a/libc/test/src/math/ILogbTest.h +++ b/libc/test/src/math/ILogbTest.h @@ -9,11 +9,11 @@ #ifndef LLVM_LIBC_TEST_SRC_MATH_ILOGBTEST_H #define LLVM_LIBC_TEST_SRC_MATH_ILOGBTEST_H +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/CPP/limits.h" // INT_MAX #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/ManipulationFunctions.h" #include "test/UnitTest/Test.h" -#include <math.h> class LlvmLibcILogbTest : public LIBC_NAMESPACE::testing::Test { public: @@ -24,7 +24,7 @@ public: template <typename T> void test_special_numbers(typename ILogbFunc<T>::Func func) { using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; - using Sign = LIBC_NAMESPACE::fputil::Sign; + EXPECT_EQ(FP_ILOGB0, func(FPBits::zero(Sign::POS).get_val())); EXPECT_EQ(FP_ILOGB0, func(FPBits::zero(Sign::NEG).get_val())); EXPECT_EQ(FP_ILOGBNAN, func(FPBits::quiet_nan().get_val())); diff --git a/libc/test/src/math/LdExpTest.h b/libc/test/src/math/LdExpTest.h index fe84b5f4c192a448b77a1851b14d6c0908d40cc6..8bfd022973b44bd78ecab5ca83b60fd8db6d9175 100644 --- a/libc/test/src/math/LdExpTest.h +++ b/libc/test/src/math/LdExpTest.h @@ -15,7 +15,7 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" #include <stdint.h> template <typename T> @@ -23,7 +23,6 @@ class LdExpTestTemplate : public LIBC_NAMESPACE::testing::Test { using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; using NormalFloat = LIBC_NAMESPACE::fputil::NormalFloat<T>; using StorageType = typename FPBits::StorageType; - using Sign = LIBC_NAMESPACE::fputil::Sign; const T inf = FPBits::inf(Sign::POS).get_val(); const T neg_inf = FPBits::inf(Sign::NEG).get_val(); diff --git a/libc/test/src/math/LogbTest.h b/libc/test/src/math/LogbTest.h index d64c5c44e4281a5151cda7eb0ffab6113a1cde15..3859b56582e5e4372ea310cabf5850d937b7b3bd 100644 --- a/libc/test/src/math/LogbTest.h +++ b/libc/test/src/math/LogbTest.h @@ -11,7 +11,7 @@ #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" namespace mpfr = LIBC_NAMESPACE::testing::mpfr; diff --git a/libc/test/src/math/ModfTest.h b/libc/test/src/math/ModfTest.h index a7e5e8810611b1b16a25454cc96df50ce0e0f045..84e26db49695d54812a2fa0756ee1c9976d70e74 100644 --- a/libc/test/src/math/ModfTest.h +++ b/libc/test/src/math/ModfTest.h @@ -12,7 +12,7 @@ #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" namespace mpfr = LIBC_NAMESPACE::testing::mpfr; diff --git a/libc/test/src/math/NextAfterTest.h b/libc/test/src/math/NextAfterTest.h index 2f1450a16fd1e59ea32bb573e3a0de3ae8950aaa..05803fb45ee27e76090454ace9e4089d6dc6e64c 100644 --- a/libc/test/src/math/NextAfterTest.h +++ b/libc/test/src/math/NextAfterTest.h @@ -9,19 +9,18 @@ #ifndef LLVM_LIBC_TEST_SRC_MATH_NEXTAFTERTEST_H #define LLVM_LIBC_TEST_SRC_MATH_NEXTAFTERTEST_H +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/CPP/bit.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/FPUtil/BasicOperations.h" #include "src/__support/FPUtil/FPBits.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> template <typename T> class NextAfterTestTemplate : public LIBC_NAMESPACE::testing::Test { using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; using StorageType = typename FPBits::StorageType; - using Sign = LIBC_NAMESPACE::fputil::Sign; const T inf = FPBits::inf(Sign::POS).get_val(); const T neg_inf = FPBits::inf(Sign::NEG).get_val(); diff --git a/libc/test/src/math/RIntTest.h b/libc/test/src/math/RIntTest.h index 3b16b902bcf5d3c6d282faac47a97dda6cc70246..301655c64ed36307743757f693273c92f1772d54 100644 --- a/libc/test/src/math/RIntTest.h +++ b/libc/test/src/math/RIntTest.h @@ -15,8 +15,8 @@ #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" +#include "include/llvm-libc-macros/math-macros.h" #include <fenv.h> -#include <math.h> #include <stdio.h> namespace mpfr = LIBC_NAMESPACE::testing::mpfr; @@ -32,7 +32,6 @@ public: private: using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; using StorageType = typename FPBits::StorageType; - using Sign = LIBC_NAMESPACE::fputil::Sign; const T inf = FPBits::inf(Sign::POS).get_val(); const T neg_inf = FPBits::inf(Sign::NEG).get_val(); diff --git a/libc/test/src/math/RemQuoTest.h b/libc/test/src/math/RemQuoTest.h index 7b3011d23055d99f49aa173d45a68333871cd28a..1cb8cdbe81a2200628d2faba9ea706c01783a1a0 100644 --- a/libc/test/src/math/RemQuoTest.h +++ b/libc/test/src/math/RemQuoTest.h @@ -9,12 +9,12 @@ #ifndef LLVM_LIBC_TEST_SRC_MATH_REMQUOTEST_H #define LLVM_LIBC_TEST_SRC_MATH_REMQUOTEST_H +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/BasicOperations.h" #include "src/__support/FPUtil/FPBits.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> namespace mpfr = LIBC_NAMESPACE::testing::mpfr; @@ -22,7 +22,6 @@ template <typename T> class RemQuoTestTemplate : public LIBC_NAMESPACE::testing::Test { using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; using StorageType = typename FPBits::StorageType; - using Sign = LIBC_NAMESPACE::fputil::Sign; const T inf = FPBits::inf(Sign::POS).get_val(); const T neg_inf = FPBits::inf(Sign::NEG).get_val(); diff --git a/libc/test/src/math/RoundTest.h b/libc/test/src/math/RoundTest.h index b255ecc4fa84e83a46b0bde9f16b02557ba489f7..17da00f869d3b3b2eaca75808fdb4f347acceb1e 100644 --- a/libc/test/src/math/RoundTest.h +++ b/libc/test/src/math/RoundTest.h @@ -13,7 +13,7 @@ #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" namespace mpfr = LIBC_NAMESPACE::testing::mpfr; diff --git a/libc/test/src/math/RoundToIntegerTest.h b/libc/test/src/math/RoundToIntegerTest.h index 9bd4ba52f61ba80c1d5d6eb71f06d77f1b9174a7..d2fabd0b4c9c3bf5b732fc816d61608f93fa01b0 100644 --- a/libc/test/src/math/RoundToIntegerTest.h +++ b/libc/test/src/math/RoundToIntegerTest.h @@ -15,8 +15,8 @@ #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" +#include "include/llvm-libc-macros/math-macros.h" #include <errno.h> -#include <math.h> namespace mpfr = LIBC_NAMESPACE::testing::mpfr; @@ -31,7 +31,6 @@ public: private: using FPBits = LIBC_NAMESPACE::fputil::FPBits<F>; using StorageType = typename FPBits::StorageType; - using Sign = LIBC_NAMESPACE::fputil::Sign; const F zero = FPBits::zero().get_val(); const F neg_zero = FPBits::zero(Sign::NEG).get_val(); diff --git a/libc/test/src/math/SqrtTest.h b/libc/test/src/math/SqrtTest.h index 75eb411810f5ee9b3452bae062bdf0d62fee680e..9811b2767ee337fff31f7440de8ddb9e1579517d 100644 --- a/libc/test/src/math/SqrtTest.h +++ b/libc/test/src/math/SqrtTest.h @@ -11,7 +11,7 @@ #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" namespace mpfr = LIBC_NAMESPACE::testing::mpfr; diff --git a/libc/test/src/math/TruncTest.h b/libc/test/src/math/TruncTest.h index 6d0ea1182ec11b0ada14fd7a435220770754e1c8..c3a89dbb837b522c27efc5330939f2ddbdf1ed0f 100644 --- a/libc/test/src/math/TruncTest.h +++ b/libc/test/src/math/TruncTest.h @@ -13,7 +13,7 @@ #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" namespace mpfr = LIBC_NAMESPACE::testing::mpfr; diff --git a/libc/test/src/math/acosf_test.cpp b/libc/test/src/math/acosf_test.cpp index c273184d58f3e605c9d8a41b75f274377aaf8fc2..6f8321bd7182aef5abe6fa4f686b7cf7a03cda07 100644 --- a/libc/test/src/math/acosf_test.cpp +++ b/libc/test/src/math/acosf_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/acosf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/acoshf_test.cpp b/libc/test/src/math/acoshf_test.cpp index a0e845b2b247ee8eabfbce4389a5ccad7dfc9cb4..41d1166fb430db84c160d8492fbb19df5148b901 100644 --- a/libc/test/src/math/acoshf_test.cpp +++ b/libc/test/src/math/acoshf_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/acoshf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/asinf_test.cpp b/libc/test/src/math/asinf_test.cpp index a24fdcc36e140a867e32217be993df0dbf152ba5..4e36f03f489551fbe420a852e4d43af9f07fe3e2 100644 --- a/libc/test/src/math/asinf_test.cpp +++ b/libc/test/src/math/asinf_test.cpp @@ -7,13 +7,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/asinf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/asinhf_test.cpp b/libc/test/src/math/asinhf_test.cpp index 3127861c9a1be5963b126ef1e0eb34ca44616eb4..9a3bfbed1068d88f91c51664d35bfc6bcc263a8e 100644 --- a/libc/test/src/math/asinhf_test.cpp +++ b/libc/test/src/math/asinhf_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/asinhf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/atan2f_test.cpp b/libc/test/src/math/atan2f_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..343e7601b0392bf9ff1337f2d6f631fcada2c37c --- /dev/null +++ b/libc/test/src/math/atan2f_test.cpp @@ -0,0 +1,133 @@ +//===-- Unittests for atan2f ----------------------------------------------===// +// +// 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" +#include "src/__support/FPUtil/FPBits.h" +#include "src/math/atan2f.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" +#include "utils/MPFRWrapper/MPFRUtils.h" + +using LlvmLibcAtan2fTest = LIBC_NAMESPACE::testing::FPTest<float>; +using LIBC_NAMESPACE::testing::tlog; + +namespace mpfr = LIBC_NAMESPACE::testing::mpfr; + +TEST_F(LlvmLibcAtan2fTest, TrickyInputs) { + constexpr int N = 17; + mpfr::BinaryInput<float> INPUTS[N] = { + {0x1.0cb3a4p+20f, 0x1.4ebacp+22f}, {0x1.12215p+1f, 0x1.4fabfcp+22f}, + {-0x1.13baaep+41f, 0x1.5bd22ep+23f}, {0x1.1ff7dcp+41f, 0x1.aec0a6p+23f}, + {0x1.2bc794p+23f, 0x1.0bc0c6p+23f}, {0x1.2fba3ap+42f, 0x1.f99456p+23f}, + {0x1.5ea1f8p+27f, 0x1.f2a1aep+23f}, {0x1.7a931p+44f, 0x1.352ac4p+22f}, + {0x1.8802bcp+21f, 0x1.8f130ap+23f}, {0x1.658ef8p+17f, 0x1.3c00f4p+22f}, + {0x1.69fb0cp+21f, 0x1.39e4c4p+23f}, {0x1.8eb24cp+11f, 0x1.36518p+23f}, + {0x1.9e7ebp+30f, 0x1.d80522p+23f}, {0x1.b4bdeep+19f, 0x1.c19b4p+23f}, + {0x1.bc201p+43f, 0x1.617346p+23f}, {0x1.c96c3cp+20f, 0x1.c01d1ep+23f}, + {0x1.781fcp+28f, 0x1.dcb3cap+23f}, + }; + + for (int i = 0; i < N; ++i) { + float x = INPUTS[i].x; + float y = INPUTS[i].y; + ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Atan2, INPUTS[i], + LIBC_NAMESPACE::atan2f(x, y), 0.5); + INPUTS[i].x = -INPUTS[i].x; + ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Atan2, INPUTS[i], + LIBC_NAMESPACE::atan2f(-x, y), 0.5); + INPUTS[i].y = -INPUTS[i].y; + ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Atan2, INPUTS[i], + LIBC_NAMESPACE::atan2f(-x, -y), 0.5); + INPUTS[i].x = -INPUTS[i].x; + ASSERT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Atan2, INPUTS[i], + LIBC_NAMESPACE::atan2f(x, -y), 0.5); + } +} + +TEST_F(LlvmLibcAtan2fTest, InFloatRange) { + constexpr uint32_t X_COUNT = 1'23; + constexpr uint32_t X_START = FPBits(0.25f).uintval(); + constexpr uint32_t X_STOP = FPBits(4.0f).uintval(); + constexpr uint32_t X_STEP = (X_STOP - X_START) / X_COUNT; + + constexpr uint32_t Y_COUNT = 1'37; + constexpr uint32_t Y_START = FPBits(0.25f).uintval(); + constexpr uint32_t Y_STOP = FPBits(4.0f).uintval(); + constexpr uint32_t Y_STEP = (Y_STOP - Y_START) / Y_COUNT; + + auto test = [&](mpfr::RoundingMode rounding_mode) { + mpfr::ForceRoundingMode __r(rounding_mode); + if (!__r.success) + return; + + uint64_t fails = 0; + uint64_t finite_count = 0; + uint64_t total_count = 0; + float failed_x, failed_y, failed_r = 0.0; + double tol = 0.5; + + for (uint32_t i = 0, v = X_START; i <= X_COUNT; ++i, v += X_STEP) { + float x = FPBits(v).get_val(); + if (isnan(x) || isinf(x) || x < 0.0) + continue; + + for (uint32_t j = 0, w = Y_START; j <= Y_COUNT; ++j, w += Y_STEP) { + float y = FPBits(w).get_val(); + if (isnan(y) || isinf(y)) + continue; + + LIBC_NAMESPACE::libc_errno = 0; + float result = LIBC_NAMESPACE::atan2f(x, y); + ++total_count; + if (isnan(result) || isinf(result)) + continue; + + ++finite_count; + mpfr::BinaryInput<float> inputs{x, y}; + + if (!TEST_MPFR_MATCH_ROUNDING_SILENTLY(mpfr::Operation::Atan2, inputs, + result, 0.5, rounding_mode)) { + ++fails; + while (!TEST_MPFR_MATCH_ROUNDING_SILENTLY( + mpfr::Operation::Atan2, inputs, result, tol, rounding_mode)) { + failed_x = x; + failed_y = y; + failed_r = result; + + if (tol > 1000.0) + break; + + tol *= 2.0; + } + } + } + } + if (fails || (finite_count < total_count)) { + tlog << " Atan2f failed: " << fails << "/" << finite_count << "/" + << total_count << " tests.\n" + << " Max ULPs is at most: " << static_cast<uint64_t>(tol) << ".\n"; + } + if (fails) { + mpfr::BinaryInput<float> inputs{failed_x, failed_y}; + EXPECT_MPFR_MATCH(mpfr::Operation::Atan2, inputs, failed_r, 0.5, + rounding_mode); + } + }; + + tlog << " Test Rounding To Nearest...\n"; + test(mpfr::RoundingMode::Nearest); + + tlog << " Test Rounding Downward...\n"; + test(mpfr::RoundingMode::Downward); + + tlog << " Test Rounding Upward...\n"; + test(mpfr::RoundingMode::Upward); + + tlog << " Test Rounding Toward Zero...\n"; + test(mpfr::RoundingMode::TowardZero); +} diff --git a/libc/test/src/math/atanf_test.cpp b/libc/test/src/math/atanf_test.cpp index 1fa7165805c7d19d58a36f37bcc136cb79bf602e..58b0eadd63f8d6842be7d65d9f8c25e39252880f 100644 --- a/libc/test/src/math/atanf_test.cpp +++ b/libc/test/src/math/atanf_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/atanf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> @@ -53,8 +53,18 @@ TEST_F(LlvmLibcAtanfTest, InFloatRange) { // For small values, tanh(x) is x. TEST_F(LlvmLibcAtanfTest, SpecialValues) { - uint32_t val_arr[] = {0x3d8d6b23U, 0x3feefcfbU, 0xbd8d6b23U, - 0xbfeefcfbU, 0x7F800000U, 0xFF800000U}; + uint32_t val_arr[] = { + 0x3d8d6b23U, // x = 0x1.1ad646p-4f + 0x3dbb6ac7U, // x = 0x1.76d58ep-4f + 0x3feefcfbU, // x = 0x1.ddf9f6p+0f + 0x3ffe2ec1U, // x = 0x1.fc5d82p+0f + 0xbd8d6b23U, // x = -0x1.1ad646p-4f + 0xbdbb6ac7U, // x = -0x1.76d58ep-4f + 0xbfeefcfbU, // x = -0x1.ddf9f6p+0f + 0xbffe2ec1U, // x = -0x1.fc5d82p+0 + 0x7F800000U, // x = +Inf + 0xFF800000U, // x = -Inf + }; for (uint32_t v : val_arr) { float x = FPBits(v).get_val(); EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Atan, x, diff --git a/libc/test/src/math/atanhf_test.cpp b/libc/test/src/math/atanhf_test.cpp index 1b45436094da4420ff12ae6df49494a4e5496cd0..c659f17d13b0a48ce6492c3d695cbde07f7a5c0a 100644 --- a/libc/test/src/math/atanhf_test.cpp +++ b/libc/test/src/math/atanhf_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/atanhf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> @@ -22,7 +22,7 @@ using LlvmLibcAtanhfTest = LIBC_NAMESPACE::testing::FPTest<float>; namespace mpfr = LIBC_NAMESPACE::testing::mpfr; TEST_F(LlvmLibcAtanhfTest, SpecialNumbers) { - using Sign = LIBC_NAMESPACE::fputil::Sign; + LIBC_NAMESPACE::libc_errno = 0; LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanhf(aNaN)); diff --git a/libc/test/src/math/cos_test.cpp b/libc/test/src/math/cos_test.cpp index 1f55e9e9a149597dc0c5c5f59ac3a2f65c057f90..6a1122997c51a20293940bba59434324952375f0 100644 --- a/libc/test/src/math/cos_test.cpp +++ b/libc/test/src/math/cos_test.cpp @@ -11,7 +11,7 @@ #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" using LlvmLibcCosTest = LIBC_NAMESPACE::testing::FPTest<double>; diff --git a/libc/test/src/math/cosf_test.cpp b/libc/test/src/math/cosf_test.cpp index 93ab06dc80b261e6569e8c9d79e65349a14dd94d..8a5eb17fdcea50461e3c14bd5b6588f3622dbfb7 100644 --- a/libc/test/src/math/cosf_test.cpp +++ b/libc/test/src/math/cosf_test.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/cosf.h" @@ -13,7 +14,6 @@ #include "test/UnitTest/Test.h" #include "test/src/math/sdcomp26094.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/coshf_test.cpp b/libc/test/src/math/coshf_test.cpp index 3b8e14fb5f03429360e4c2411cbf2a782c939535..8792f56b03461a5a00bc9057984ed593de0410df 100644 --- a/libc/test/src/math/coshf_test.cpp +++ b/libc/test/src/math/coshf_test.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/CPP/array.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" @@ -13,7 +14,6 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/erff_test.cpp b/libc/test/src/math/erff_test.cpp index 8ebde4ec24fb55c8060ed7849daf266b31582c6a..1e43c206aef0da86386c474925231eb7e8879d1f 100644 --- a/libc/test/src/math/erff_test.cpp +++ b/libc/test/src/math/erff_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/math/erff.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt index 84a5ebc75ef04b514adb16fa9b372ca0e87b6684..df32dd4f943f30972a2d08dbc65382630195eb41 100644 --- a/libc/test/src/math/exhaustive/CMakeLists.txt +++ b/libc/test/src/math/exhaustive/CMakeLists.txt @@ -273,6 +273,7 @@ add_fp_unittest( fmod_generic_impl_test.cpp DEPENDS libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.manipulation_functions libc.src.__support.FPUtil.generic.fmod ) diff --git a/libc/test/src/math/exhaustive/atanf_test.cpp b/libc/test/src/math/exhaustive/atanf_test.cpp index 508c288b050c55ec1eda38882d174259218b6770..6f23231d426741806cf7c78d317867f49683431e 100644 --- a/libc/test/src/math/exhaustive/atanf_test.cpp +++ b/libc/test/src/math/exhaustive/atanf_test.cpp @@ -25,7 +25,7 @@ TEST_F(LlvmLibcAtanfExhaustiveTest, PostiveRange) { } // Range: [-Inf, 0]; -static constexpr uint32_t NEG_START = 0xb000'0000U; +static constexpr uint32_t NEG_START = 0x8000'0000U; static constexpr uint32_t NEG_STOP = 0xff80'0000U; TEST_F(LlvmLibcAtanfExhaustiveTest, NegativeRange) { diff --git a/libc/test/src/math/exhaustive/fmod_generic_impl_test.cpp b/libc/test/src/math/exhaustive/fmod_generic_impl_test.cpp index 25a5e3898599ae9862be54a990af387c120c21df..c7aec5b7bc21b4b18431ef16db9be267652d2d66 100644 --- a/libc/test/src/math/exhaustive/fmod_generic_impl_test.cpp +++ b/libc/test/src/math/exhaustive/fmod_generic_impl_test.cpp @@ -6,53 +6,55 @@ // //===----------------------------------------------------------------------===// #include "src/__support/CPP/type_traits.h" +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" // ldexp #include "src/__support/FPUtil/generic/FMod.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" #include <array> -#include <limits> namespace mpfr = LIBC_NAMESPACE::testing::mpfr; template <typename T, bool InverseMultiplication> class LlvmLibcFModTest : public LIBC_NAMESPACE::testing::Test { - using U = typename LIBC_NAMESPACE::fputil::FPBits<T>::StorageType; + using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; + using U = typename FPBits::StorageType; using DivisionHelper = LIBC_NAMESPACE::cpp::conditional_t< InverseMultiplication, LIBC_NAMESPACE::fputil::generic::FModDivisionInvMultHelper<U>, LIBC_NAMESPACE::fputil::generic::FModDivisionSimpleHelper<U>>; - static constexpr std::array<T, 11> test_bases = { + static constexpr std::array<T, 11> TEST_BASES = { T(0.0), T(1.0), T(3.0), T(27.0), T(11.0 / 8.0), T(2.764443), - T(1.0) - std::numeric_limits<T>::epsilon(), - T(1.0) + std::numeric_limits<T>::epsilon(), - T(M_PI), - T(M_SQRT2), - T(M_E)}; + T(1.0) - T(0x1.0p-23) - T(0x1.0p-52) - T(0x1.0p-112), + T(1.0) + T(0x1.0p-23) + T(0x1.0p-52) + T(0x1.0p-112), + T(3.14159265), + T(1.41421356), + T(2.71828183)}; public: void testExtensive() { using FMod = LIBC_NAMESPACE::fputil::generic::FMod<T, U, DivisionHelper>; - using nl = std::numeric_limits<T>; - int min2 = nl::min_exponent - nl::digits - 5; - int max2 = nl::max_exponent + 3; - for (T by : test_bases) { + int min2 = -(FPBits::MAX_BIASED_EXPONENT + FPBits::SIG_LEN) / 2; + int max2 = 3 + FPBits::MAX_BIASED_EXPONENT / 2; + for (T by : TEST_BASES) { for (int iy = min2; iy < max2; iy++) { - T y = by * std::ldexp(2, iy); - if (y == 0 || !std::isfinite(y)) + T y = by * LIBC_NAMESPACE::fputil::ldexp(2.0, iy); + FPBits y_bits(y); + if (y_bits.is_zero() || !y_bits.is_finite()) continue; - for (T bx : test_bases) { + for (T bx : TEST_BASES) { for (int ix = min2; ix < max2; ix++) { - T x = bx * std::ldexp(2, ix); - if (!std::isfinite(x)) + T x = bx * LIBC_NAMESPACE::fputil::ldexp(2.0, ix); + if (!FPBits(x).is_finite()) continue; T result = FMod::eval(x, y); mpfr::BinaryInput<T> input{x, y}; diff --git a/libc/test/src/math/exp10_test.cpp b/libc/test/src/math/exp10_test.cpp index d71b5a22303745d82e82253d52ccdc8e74869813..778189626a6179ea9cfab6b970c52b8eac4c6fba 100644 --- a/libc/test/src/math/exp10_test.cpp +++ b/libc/test/src/math/exp10_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/exp10.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/exp10f_test.cpp b/libc/test/src/math/exp10f_test.cpp index 4e2d065f1292ab12f6ea5dd7b146855ece4e1af3..9d44e8f65deccf12da6aa27734b9d34ebe5c801f 100644 --- a/libc/test/src/math/exp10f_test.cpp +++ b/libc/test/src/math/exp10f_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/exp10f.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <stdint.h> diff --git a/libc/test/src/math/exp2_test.cpp b/libc/test/src/math/exp2_test.cpp index 2f9d7b3a2a6c90b047cb5271c4c96a643c3388fc..845fda5451d4b7166e74cf7f920dea539c64f2b3 100644 --- a/libc/test/src/math/exp2_test.cpp +++ b/libc/test/src/math/exp2_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/exp2.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/exp2f_test.cpp b/libc/test/src/math/exp2f_test.cpp index f5ea8554be5c0fbf286ab78497a05b6b304ec6e2..f63f091eab9a8307cc8b829c12d393ade5fa2657 100644 --- a/libc/test/src/math/exp2f_test.cpp +++ b/libc/test/src/math/exp2f_test.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA #include "src/errno/libc_errno.h" @@ -13,7 +14,6 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <stdint.h> diff --git a/libc/test/src/math/exp_test.cpp b/libc/test/src/math/exp_test.cpp index 006db00b91949e52db3ce0781c96bd1060fb0b3b..42018e608ae45bdfc646fa8eb052c17913d4ff19 100644 --- a/libc/test/src/math/exp_test.cpp +++ b/libc/test/src/math/exp_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/exp.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/expf_test.cpp b/libc/test/src/math/expf_test.cpp index ffd9da500488b12678d353c02a06bd4c9e069c6d..634958bdc43e567354d9f495d722f1bfb4ed0595 100644 --- a/libc/test/src/math/expf_test.cpp +++ b/libc/test/src/math/expf_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/expf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <stdint.h> diff --git a/libc/test/src/math/explogxf_test.cpp b/libc/test/src/math/explogxf_test.cpp index 24f9f3c0f8e45e160e9923db5895dc5e24316eb5..a536a9f3ab8dea5ac97cbea7627e4c9d0eff70c2 100644 --- a/libc/test/src/math/explogxf_test.cpp +++ b/libc/test/src/math/explogxf_test.cpp @@ -7,12 +7,14 @@ //===----------------------------------------------------------------------===// #include "in_float_range_test_helper.h" +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" +#include "src/math/fabs.h" +#include "src/math/fabsf.h" #include "src/math/generic/explogxf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> using LlvmLibcExplogfTest = LIBC_NAMESPACE::testing::FPTest<float>; @@ -22,7 +24,7 @@ constexpr int def_count = 100003; constexpr float def_prec = 0.500001f; auto f_normal = [](float x) -> bool { - return !(isnan(x) || isinf(x) || fabs(x) < 2E-38); + return !(isnan(x) || isinf(x) || LIBC_NAMESPACE::fabs(x) < 2E-38); }; TEST_F(LlvmLibcExplogfTest, ExpInFloatRange) { @@ -32,8 +34,8 @@ TEST_F(LlvmLibcExplogfTest, ExpInFloatRange) { return static_cast<float>(result.mh * r); }; auto f_check = [](float x) -> bool { - return !( - (isnan(x) || isinf(x) || x < -70 || x > 70 || fabsf(x) < 0x1.0p-10)); + return !((isnan(x) || isinf(x) || x < -70 || x > 70 || + LIBC_NAMESPACE::fabsf(x) < 0x1.0p-10)); }; CHECK_DATA(0.0f, neg_inf, mpfr::Operation::Exp, fx, f_check, def_count, def_prec); diff --git a/libc/test/src/math/expm1_test.cpp b/libc/test/src/math/expm1_test.cpp index ccc6e36095481fdf11388e484a93222f65bb10e0..198e6d5cdd8ab279c1f082747e76f146af1660e6 100644 --- a/libc/test/src/math/expm1_test.cpp +++ b/libc/test/src/math/expm1_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/expm1.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/expm1f_test.cpp b/libc/test/src/math/expm1f_test.cpp index 94a9301f8eb2224b49bf064d5d0d4417307f01f7..c72815887ba8b30eee7d587e407b36b20386bea7 100644 --- a/libc/test/src/math/expm1f_test.cpp +++ b/libc/test/src/math/expm1f_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/expm1f.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <stdint.h> diff --git a/libc/test/src/math/fdim_test.cpp b/libc/test/src/math/fdim_test.cpp index 2f00a30ad1ee6f76e231ee525917916013f6bfe6..6c0c3e204c5f9d8a9a4be69cad633886c9fddf51 100644 --- a/libc/test/src/math/fdim_test.cpp +++ b/libc/test/src/math/fdim_test.cpp @@ -8,11 +8,11 @@ #include "FDimTest.h" +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/math/fdim.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> using LlvmLibcFDimTest = FDimTestTemplate<double>; diff --git a/libc/test/src/math/fdimf_test.cpp b/libc/test/src/math/fdimf_test.cpp index 27511baf25b6da8aef9cdc3e00a99e43bb2160e0..a74011b5a224982e681be05f885cda815f72a853 100644 --- a/libc/test/src/math/fdimf_test.cpp +++ b/libc/test/src/math/fdimf_test.cpp @@ -8,11 +8,11 @@ #include "FDimTest.h" +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/math/fdimf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> using LlvmLibcFDimTest = FDimTestTemplate<float>; diff --git a/libc/test/src/math/fdiml_test.cpp b/libc/test/src/math/fdiml_test.cpp index 45aedb0a1cdea61c050fe6a52eb47a4c4651c576..d3f2e68a7c1d79534103a1a5722099647ab192f4 100644 --- a/libc/test/src/math/fdiml_test.cpp +++ b/libc/test/src/math/fdiml_test.cpp @@ -8,11 +8,11 @@ #include "FDimTest.h" +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/math/fdiml.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> using LlvmLibcFDimTest = FDimTestTemplate<long double>; diff --git a/libc/test/src/math/ilogb_test.cpp b/libc/test/src/math/ilogb_test.cpp index 7011c43386e66a5ce52a3c03d48159f739ad96b8..45756ffa3d9a7cd4ebb243bdf5be9e0b61420b90 100644 --- a/libc/test/src/math/ilogb_test.cpp +++ b/libc/test/src/math/ilogb_test.cpp @@ -8,12 +8,12 @@ #include "ILogbTest.h" +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/ManipulationFunctions.h" #include "src/math/ilogb.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> TEST_F(LlvmLibcILogbTest, SpecialNumbers_ilogb) { test_special_numbers<double>(&LIBC_NAMESPACE::ilogb); diff --git a/libc/test/src/math/ilogbf_test.cpp b/libc/test/src/math/ilogbf_test.cpp index dcff8eeb1518059570a7ab4c15fa544286d4b3e1..ff19dd145a198d26a6d2fdb7dce1eef43926bab5 100644 --- a/libc/test/src/math/ilogbf_test.cpp +++ b/libc/test/src/math/ilogbf_test.cpp @@ -8,12 +8,12 @@ #include "ILogbTest.h" +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/ManipulationFunctions.h" #include "src/math/ilogbf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> TEST_F(LlvmLibcILogbTest, SpecialNumbers_ilogbf) { test_special_numbers<float>(&LIBC_NAMESPACE::ilogbf); diff --git a/libc/test/src/math/ilogbl_test.cpp b/libc/test/src/math/ilogbl_test.cpp index 29a221ad7f08f7af922f607d72460f071108b4d3..b2c5246669946a881320e59448c1eaeedde5ddb5 100644 --- a/libc/test/src/math/ilogbl_test.cpp +++ b/libc/test/src/math/ilogbl_test.cpp @@ -8,12 +8,12 @@ #include "ILogbTest.h" +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/ManipulationFunctions.h" #include "src/math/ilogbl.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> TEST_F(LlvmLibcILogbTest, SpecialNumbers_ilogbl) { test_special_numbers<long double>(&LIBC_NAMESPACE::ilogbl); diff --git a/libc/test/src/math/inv_trigf_utils_test.cpp b/libc/test/src/math/inv_trigf_utils_test.cpp deleted file mode 100644 index 23420edcd0ca1ab47b55f75c9569f8c7523bf3df..0000000000000000000000000000000000000000 --- a/libc/test/src/math/inv_trigf_utils_test.cpp +++ /dev/null @@ -1,34 +0,0 @@ -//===-- Unittests for supfuncf --------------------------------------------===// -// -// 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 "in_float_range_test_helper.h" -#include "src/__support/FPUtil/FPBits.h" -#include "src/math/generic/inv_trigf_utils.h" -#include "test/UnitTest/FPMatcher.h" -#include "test/UnitTest/Test.h" -#include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> - -using LlvmLibcAtanfTest = LIBC_NAMESPACE::testing::FPTest<float>; - -namespace mpfr = LIBC_NAMESPACE::testing::mpfr; - -constexpr int def_count = 100003; -constexpr float def_prec = 0.500001f; - -auto f_normal = [](float x) -> bool { return !(isnan(x) || isinf(x)); }; - -TEST_F(LlvmLibcAtanfTest, InPositiveRange) { - CHECK_DATA(0.0f, inf, mpfr::Operation::Atan, LIBC_NAMESPACE::atan_eval, - f_normal, def_count, def_prec); -} - -TEST_F(LlvmLibcAtanfTest, InNegativeRange) { - CHECK_DATA(-0.0f, neg_inf, mpfr::Operation::Atan, LIBC_NAMESPACE::atan_eval, - f_normal, def_count, def_prec); -} diff --git a/libc/test/src/math/log10_test.cpp b/libc/test/src/math/log10_test.cpp index ed4a24b95159517fa69effc0c8e556f658f01519..dc4ac895546c43fff18739bb674d392e079bf03f 100644 --- a/libc/test/src/math/log10_test.cpp +++ b/libc/test/src/math/log10_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/log10.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/log10f_test.cpp b/libc/test/src/math/log10f_test.cpp index c38a5159682cfd04371c936b959ff76acd90496e..f8a137e44c351e947f73297ad4b2320332d7cb8b 100644 --- a/libc/test/src/math/log10f_test.cpp +++ b/libc/test/src/math/log10f_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/math/log10f.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/log1p_test.cpp b/libc/test/src/math/log1p_test.cpp index d769659356c941a84638348caeba9c25dce1d0c4..975fb8e05c35eacd6b6fe2de07997d98bf7eeeb9 100644 --- a/libc/test/src/math/log1p_test.cpp +++ b/libc/test/src/math/log1p_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/log1p.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/log1pf_test.cpp b/libc/test/src/math/log1pf_test.cpp index 2f6330ee6ce631c97b44c3249239939b169bbeff..a1108fee48196f61931b375b56e579476ca5f0be 100644 --- a/libc/test/src/math/log1pf_test.cpp +++ b/libc/test/src/math/log1pf_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/log1pf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/log2_test.cpp b/libc/test/src/math/log2_test.cpp index f4ee0ff5185b4787f96791407cf16ac68eed8218..8765279005798a94afe5ed4c750ab001a883f0ae 100644 --- a/libc/test/src/math/log2_test.cpp +++ b/libc/test/src/math/log2_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/log2.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/log2f_test.cpp b/libc/test/src/math/log2f_test.cpp index d8b4808f5cda120b56b619ffa19379f9d8c1ae19..c05b6b93cff777ab1dbe1b04ca1efe68accb5e8a 100644 --- a/libc/test/src/math/log2f_test.cpp +++ b/libc/test/src/math/log2f_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/log2f.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <stdint.h> diff --git a/libc/test/src/math/log_test.cpp b/libc/test/src/math/log_test.cpp index b1f1ab775462b1fb7dd5938f60cdacbe2c5294f1..06a0dc574be51873fdb11b57c1cd13bbd9ac906a 100644 --- a/libc/test/src/math/log_test.cpp +++ b/libc/test/src/math/log_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/log.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/logf_test.cpp b/libc/test/src/math/logf_test.cpp index 3ab67ba807823b0d901395319cbeb368fbe6d3a8..1ab480744ba596a30b78524cc7ee27804a2f533e 100644 --- a/libc/test/src/math/logf_test.cpp +++ b/libc/test/src/math/logf_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/math/logf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <stdint.h> diff --git a/libc/test/src/math/nextafterf128_test.cpp b/libc/test/src/math/nextafterf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a8d000ff4de3874039ffb65197f826d33d4b479e --- /dev/null +++ b/libc/test/src/math/nextafterf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for nextafterf128 ---------------------------------------===// +// +// 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 "NextAfterTest.h" + +#include "src/math/nextafterf128.h" + +LIST_NEXTAFTER_TESTS(float128, LIBC_NAMESPACE::nextafterf128) diff --git a/libc/test/src/math/powf_test.cpp b/libc/test/src/math/powf_test.cpp index 3dffeb603499fe7b296e931300045a479ffd262e..cf674ecf8f99e71cdb2bfb1af9ec6e8679950842 100644 --- a/libc/test/src/math/powf_test.cpp +++ b/libc/test/src/math/powf_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/math/powf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/sin_test.cpp b/libc/test/src/math/sin_test.cpp index 69981ed22ee69f5935c83fc6db8c415cccb01a12..fa1c5370c30fbb11c87fcf9d828c4faff48b258d 100644 --- a/libc/test/src/math/sin_test.cpp +++ b/libc/test/src/math/sin_test.cpp @@ -12,7 +12,7 @@ #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" using LlvmLibcSinTest = LIBC_NAMESPACE::testing::FPTest<double>; diff --git a/libc/test/src/math/sincosf_test.cpp b/libc/test/src/math/sincosf_test.cpp index 2c0c7eaaa25f07f195b6673136877add77b93689..a7372fd53b319e98ba393a3d4597766b73250dab 100644 --- a/libc/test/src/math/sincosf_test.cpp +++ b/libc/test/src/math/sincosf_test.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/sincosf.h" @@ -13,7 +14,6 @@ #include "test/UnitTest/Test.h" #include "test/src/math/sdcomp26094.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/sinf_test.cpp b/libc/test/src/math/sinf_test.cpp index 94c1114e688984dc5f50d50367d617772912161a..a3c5384e3e626fafd70ddc3245577beac3a910b0 100644 --- a/libc/test/src/math/sinf_test.cpp +++ b/libc/test/src/math/sinf_test.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/sinf.h" @@ -13,7 +14,6 @@ #include "test/UnitTest/Test.h" #include "test/src/math/sdcomp26094.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/sinhf_test.cpp b/libc/test/src/math/sinhf_test.cpp index f14150bb04420eb286ec709e633226322e5ace7a..bea976055dbdff56b64d3cf0fb72c44a500ea3b2 100644 --- a/libc/test/src/math/sinhf_test.cpp +++ b/libc/test/src/math/sinhf_test.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/CPP/array.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" @@ -13,7 +14,6 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt index d9be172056a83387b124d3a8ac24a04f7d0a4fbc..5d269ddb229cfc3c565a9fb7cb1bfcba901197eb 100644 --- a/libc/test/src/math/smoke/CMakeLists.txt +++ b/libc/test/src/math/smoke/CMakeLists.txt @@ -165,6 +165,70 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + canonicalize_test + SUITE + libc-math-smoke-tests + SRCS + canonicalize_test.cpp + HDRS + CanonicalizeTest.h + DEPENDS + libc.include.math + libc.src.math.canonicalize + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.integer_literals +) + +add_fp_unittest( + canonicalizef_test + SUITE + libc-math-smoke-tests + SRCS + canonicalizef_test.cpp + HDRS + CanonicalizeTest.h + DEPENDS + libc.include.math + libc.src.math.canonicalizef + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.integer_literals +) + +add_fp_unittest( + canonicalizef128_test + SUITE + libc-math-smoke-tests + SRCS + canonicalizef128_test.cpp + HDRS + CanonicalizeTest.h + DEPENDS + libc.include.math + libc.src.math.canonicalizef128 + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.integer_literals +) + +add_fp_unittest( + canonicalizel_test + SUITE + libc-math-smoke-tests + SRCS + canonicalizel_test.cpp + HDRS + CanonicalizeTest.h + DEPENDS + libc.include.math + libc.src.math.canonicalizel + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.integer_literals +) + add_fp_unittest( ceil_test SUITE @@ -839,6 +903,198 @@ add_fp_unittest( libc.src.math.frexpf128 ) +add_fp_unittest( + fromfp_test + SUITE + libc-math-smoke-tests + SRCS + fromfp_test.cpp + HDRS + FromfpTest.h + DEPENDS + libc.src.math.fromfp +) + +add_fp_unittest( + fromfpf_test + SUITE + libc-math-smoke-tests + SRCS + fromfpf_test.cpp + HDRS + FromfpTest.h + DEPENDS + libc.src.math.fromfpf +) + +add_fp_unittest( + fromfpl_test + SUITE + libc-math-smoke-tests + SRCS + fromfpl_test.cpp + HDRS + FromfpTest.h + DEPENDS + libc.src.math.fromfpl +) + +add_fp_unittest( + fromfpf128_test + SUITE + libc-math-smoke-tests + SRCS + fromfpf128_test.cpp + HDRS + FromfpTest.h + DEPENDS + libc.src.math.fromfpf128 +) + +add_fp_unittest( + fromfpx_test + SUITE + libc-math-smoke-tests + SRCS + fromfpx_test.cpp + HDRS + FromfpxTest.h + DEPENDS + libc.src.math.fromfpx +) + +add_fp_unittest( + fromfpxf_test + SUITE + libc-math-smoke-tests + SRCS + fromfpxf_test.cpp + HDRS + FromfpxTest.h + DEPENDS + libc.src.math.fromfpxf +) + +add_fp_unittest( + fromfpxl_test + SUITE + libc-math-smoke-tests + SRCS + fromfpxl_test.cpp + HDRS + FromfpxTest.h + DEPENDS + libc.src.math.fromfpxl +) + +add_fp_unittest( + fromfpxf128_test + SUITE + libc-math-smoke-tests + SRCS + fromfpxf128_test.cpp + HDRS + FromfpxTest.h + DEPENDS + libc.src.math.fromfpxf128 +) + +add_fp_unittest( + ufromfp_test + SUITE + libc-math-smoke-tests + SRCS + ufromfp_test.cpp + HDRS + UfromfpTest.h + DEPENDS + libc.src.math.ufromfp +) + +add_fp_unittest( + ufromfpf_test + SUITE + libc-math-smoke-tests + SRCS + ufromfpf_test.cpp + HDRS + UfromfpTest.h + DEPENDS + libc.src.math.ufromfpf +) + +add_fp_unittest( + ufromfpl_test + SUITE + libc-math-smoke-tests + SRCS + ufromfpl_test.cpp + HDRS + UfromfpTest.h + DEPENDS + libc.src.math.ufromfpl +) + +add_fp_unittest( + ufromfpf128_test + SUITE + libc-math-smoke-tests + SRCS + ufromfpf128_test.cpp + HDRS + UfromfpTest.h + DEPENDS + libc.src.math.ufromfpf128 +) + +add_fp_unittest( + ufromfpx_test + SUITE + libc-math-smoke-tests + SRCS + ufromfpx_test.cpp + HDRS + UfromfpxTest.h + DEPENDS + libc.src.math.ufromfpx +) + +add_fp_unittest( + ufromfpxf_test + SUITE + libc-math-smoke-tests + SRCS + ufromfpxf_test.cpp + HDRS + UfromfpxTest.h + DEPENDS + libc.src.math.ufromfpxf +) + +add_fp_unittest( + ufromfpxl_test + SUITE + libc-math-smoke-tests + SRCS + ufromfpxl_test.cpp + HDRS + UfromfpxTest.h + DEPENDS + libc.src.math.ufromfpxl +) + +add_fp_unittest( + ufromfpxf128_test + SUITE + libc-math-smoke-tests + SRCS + ufromfpxf128_test.cpp + HDRS + UfromfpxTest.h + DEPENDS + libc.src.math.ufromfpxf128 +) + add_fp_unittest( ilogb_test SUITE @@ -1286,190 +1542,608 @@ add_fp_unittest( ) add_fp_unittest( - sqrtf_test + fmaximuml_test SUITE libc-math-smoke-tests SRCS - sqrtf_test.cpp + fmaximuml_test.cpp + HDRS + FMaximumTest.h DEPENDS - libc.include.math - libc.src.math.sqrtf + libc.src.math.fmaximuml libc.src.__support.FPUtil.fp_bits ) add_fp_unittest( - sqrt_test + fmaximumf128_test SUITE libc-math-smoke-tests SRCS - sqrt_test.cpp + fmaximumf128_test.cpp + HDRS + FMaximumTest.h DEPENDS - libc.include.math - libc.src.math.sqrt + libc.src.math.fmaximumf128 libc.src.__support.FPUtil.fp_bits ) add_fp_unittest( - sqrtl_test + fmaximum_test SUITE libc-math-smoke-tests SRCS - sqrtl_test.cpp + fmaximum_test.cpp + HDRS + FMaximumTest.h DEPENDS - libc.include.math - libc.src.math.sqrtl + libc.src.math.fmaximum libc.src.__support.FPUtil.fp_bits ) add_fp_unittest( - sqrtf128_test + fmaximumf_test SUITE libc-math-smoke-tests SRCS - sqrtf128_test.cpp + fmaximumf_test.cpp + HDRS + FMaximumTest.h DEPENDS - libc.include.math - libc.src.math.sqrtf128 + libc.src.math.fmaximumf libc.src.__support.FPUtil.fp_bits ) add_fp_unittest( - generic_sqrtf_test + fmaximum_numf_test SUITE libc-math-smoke-tests SRCS - generic_sqrtf_test.cpp + fmaximum_numf_test.cpp + HDRS + FMaximumNumTest.h DEPENDS - libc.src.math.sqrtf + libc.src.math.fmaximum_numf libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.generic.sqrt - COMPILE_OPTIONS - -O3 ) add_fp_unittest( - generic_sqrt_test + fmaximum_num_test SUITE libc-math-smoke-tests SRCS - generic_sqrt_test.cpp + fmaximum_num_test.cpp + HDRS + FMaximumNumTest.h DEPENDS - libc.src.math.sqrt + libc.src.math.fmaximum_num libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.generic.sqrt - COMPILE_OPTIONS - -O3 ) add_fp_unittest( - generic_sqrtl_test + fmaximum_numl_test SUITE libc-math-smoke-tests SRCS - generic_sqrtl_test.cpp + fmaximum_numl_test.cpp + HDRS + FMaximumNumTest.h DEPENDS - libc.src.math.sqrtl + libc.src.math.fmaximum_numl libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.generic.sqrt - COMPILE_OPTIONS - -O3 ) add_fp_unittest( - generic_sqrtf128_test + fmaximum_numf128_test SUITE libc-math-smoke-tests SRCS - generic_sqrtf128_test.cpp + fmaximum_numf128_test.cpp + HDRS + FMaximumNumTest.h DEPENDS - libc.src.math.sqrtf128 + libc.src.math.fmaximum_numf128 libc.src.__support.FPUtil.fp_bits - libc.src.__support.FPUtil.generic.sqrt - COMPILE_OPTIONS - -O3 ) add_fp_unittest( - remquof_test + fmaximum_magf_test SUITE libc-math-smoke-tests SRCS - remquof_test.cpp + fmaximum_magf_test.cpp HDRS - RemQuoTest.h + FMaximumMagTest.h DEPENDS - libc.include.math - libc.src.math.remquof - libc.src.__support.FPUtil.basic_operations + libc.src.math.fmaximum_magf libc.src.__support.FPUtil.fp_bits ) add_fp_unittest( - remquo_test + fmaximum_mag_test SUITE libc-math-smoke-tests SRCS - remquo_test.cpp + fmaximum_mag_test.cpp HDRS - RemQuoTest.h + FMaximumMagTest.h DEPENDS - libc.include.math - libc.src.math.remquo - libc.src.__support.FPUtil.basic_operations + libc.src.math.fmaximum_mag libc.src.__support.FPUtil.fp_bits ) add_fp_unittest( - remquol_test + fmaximum_magl_test SUITE libc-math-smoke-tests SRCS - remquol_test.cpp + fmaximum_magl_test.cpp HDRS - RemQuoTest.h + FMaximumMagTest.h DEPENDS - libc.include.math - libc.src.math.remquol - libc.src.__support.FPUtil.basic_operations + libc.src.math.fmaximum_magl libc.src.__support.FPUtil.fp_bits ) add_fp_unittest( - hypotf_test + fmaximum_magf128_test SUITE libc-math-smoke-tests SRCS - hypotf_test.cpp + fmaximum_magf128_test.cpp + HDRS + FMaximumMagTest.h DEPENDS - libc.include.math - libc.src.math.hypotf + libc.src.math.fmaximum_magf128 libc.src.__support.FPUtil.fp_bits ) + add_fp_unittest( - hypot_test + fmaximum_mag_numf_test SUITE libc-math-smoke-tests SRCS - hypot_test.cpp + fmaximum_mag_numf_test.cpp + HDRS + FMaximumMagNumTest.h DEPENDS - libc.include.math - libc.src.math.hypot + libc.src.math.fmaximum_mag_numf libc.src.__support.FPUtil.fp_bits ) add_fp_unittest( - nanf_test + fmaximum_mag_num_test SUITE libc-math-smoke-tests SRCS - nanf_test.cpp + fmaximum_mag_num_test.cpp + HDRS + FMaximumMagNumTest.h DEPENDS - libc.include.math - libc.include.signal - libc.src.math.nanf + libc.src.math.fmaximum_mag_num libc.src.__support.FPUtil.fp_bits - # FIXME: The nan tests currently have death tests, which aren't supported for +) + +add_fp_unittest( + fmaximum_mag_numl_test + SUITE + libc-math-smoke-tests + SRCS + fmaximum_mag_numl_test.cpp + HDRS + FMaximumMagNumTest.h + DEPENDS + libc.src.math.fmaximum_mag_numl + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + fmaximum_mag_numf128_test + SUITE + libc-math-smoke-tests + SRCS + fmaximum_mag_numf128_test.cpp + HDRS + FMaximumMagNumTest.h + DEPENDS + libc.src.math.fmaximum_mag_numf128 + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + fminimuml_test + SUITE + libc-math-smoke-tests + SRCS + fminimuml_test.cpp + HDRS + FMinimumTest.h + DEPENDS + libc.src.math.fminimuml + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + fminimumf128_test + SUITE + libc-math-smoke-tests + SRCS + fminimumf128_test.cpp + HDRS + FMinimumTest.h + DEPENDS + libc.src.math.fminimumf128 + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + fminimum_test + SUITE + libc-math-smoke-tests + SRCS + fminimum_test.cpp + HDRS + FMinimumTest.h + DEPENDS + libc.src.math.fminimum + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + fminimumf_test + SUITE + libc-math-smoke-tests + SRCS + fminimumf_test.cpp + HDRS + FMinimumTest.h + DEPENDS + libc.src.math.fminimumf + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + fminimum_numf_test + SUITE + libc-math-smoke-tests + SRCS + fminimum_numf_test.cpp + HDRS + FMinimumNumTest.h + DEPENDS + libc.src.math.fminimum_numf + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + fminimum_num_test + SUITE + libc-math-smoke-tests + SRCS + fminimum_num_test.cpp + HDRS + FMinimumNumTest.h + DEPENDS + libc.src.math.fminimum_num + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + fminimum_numl_test + SUITE + libc-math-smoke-tests + SRCS + fminimum_numl_test.cpp + HDRS + FMinimumNumTest.h + DEPENDS + libc.src.math.fminimum_numl + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + fminimum_numf128_test + SUITE + libc-math-smoke-tests + SRCS + fminimum_numf128_test.cpp + HDRS + FMinimumNumTest.h + DEPENDS + libc.src.math.fminimum_numf128 + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + fminimum_magf_test + SUITE + libc-math-smoke-tests + SRCS + fminimum_magf_test.cpp + HDRS + FMinimumMagTest.h + DEPENDS + libc.src.math.fminimum_magf + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + fminimum_mag_test + SUITE + libc-math-smoke-tests + SRCS + fminimum_mag_test.cpp + HDRS + FMinimumMagTest.h + DEPENDS + libc.src.math.fminimum_mag + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + fminimum_magl_test + SUITE + libc-math-smoke-tests + SRCS + fminimum_magl_test.cpp + HDRS + FMinimumMagTest.h + DEPENDS + libc.src.math.fminimum_magl + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + fminimum_magf128_test + SUITE + libc-math-smoke-tests + SRCS + fminimum_magf128_test.cpp + HDRS + FMinimumMagTest.h + DEPENDS + libc.src.math.fminimum_magf128 + libc.src.__support.FPUtil.fp_bits +) + + +add_fp_unittest( + fminimum_mag_numf_test + SUITE + libc-math-smoke-tests + SRCS + fminimum_mag_numf_test.cpp + HDRS + FMinimumMagNumTest.h + DEPENDS + libc.src.math.fminimum_mag_numf + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + fminimum_mag_num_test + SUITE + libc-math-smoke-tests + SRCS + fminimum_mag_num_test.cpp + HDRS + FMinimumMagNumTest.h + DEPENDS + libc.src.math.fminimum_mag_num + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + fminimum_mag_numl_test + SUITE + libc-math-smoke-tests + SRCS + fminimum_mag_numl_test.cpp + HDRS + FMinimumMagNumTest.h + DEPENDS + libc.src.math.fminimum_mag_numl + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + fminimum_mag_numf128_test + SUITE + libc-math-smoke-tests + SRCS + fminimum_mag_numf128_test.cpp + HDRS + FMinimumMagNumTest.h + DEPENDS + libc.src.math.fminimum_mag_numf128 + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + sqrtf_test + SUITE + libc-math-smoke-tests + SRCS + sqrtf_test.cpp + DEPENDS + libc.include.math + libc.src.math.sqrtf + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + sqrt_test + SUITE + libc-math-smoke-tests + SRCS + sqrt_test.cpp + DEPENDS + libc.include.math + libc.src.math.sqrt + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + sqrtl_test + SUITE + libc-math-smoke-tests + SRCS + sqrtl_test.cpp + DEPENDS + libc.include.math + libc.src.math.sqrtl + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + sqrtf128_test + SUITE + libc-math-smoke-tests + SRCS + sqrtf128_test.cpp + DEPENDS + libc.include.math + libc.src.math.sqrtf128 + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + generic_sqrtf_test + SUITE + libc-math-smoke-tests + SRCS + generic_sqrtf_test.cpp + DEPENDS + libc.src.math.sqrtf + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.generic.sqrt + COMPILE_OPTIONS + -O3 +) + +add_fp_unittest( + generic_sqrt_test + SUITE + libc-math-smoke-tests + SRCS + generic_sqrt_test.cpp + DEPENDS + libc.src.math.sqrt + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.generic.sqrt + COMPILE_OPTIONS + -O3 +) + +add_fp_unittest( + generic_sqrtl_test + SUITE + libc-math-smoke-tests + SRCS + generic_sqrtl_test.cpp + DEPENDS + libc.src.math.sqrtl + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.generic.sqrt + COMPILE_OPTIONS + -O3 +) + +add_fp_unittest( + generic_sqrtf128_test + SUITE + libc-math-smoke-tests + SRCS + generic_sqrtf128_test.cpp + DEPENDS + libc.src.math.sqrtf128 + libc.src.__support.FPUtil.fp_bits + libc.src.__support.FPUtil.generic.sqrt + COMPILE_OPTIONS + -O3 +) + +add_fp_unittest( + remquof_test + SUITE + libc-math-smoke-tests + SRCS + remquof_test.cpp + HDRS + RemQuoTest.h + DEPENDS + libc.include.math + libc.src.math.remquof + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + remquo_test + SUITE + libc-math-smoke-tests + SRCS + remquo_test.cpp + HDRS + RemQuoTest.h + DEPENDS + libc.include.math + libc.src.math.remquo + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + remquol_test + SUITE + libc-math-smoke-tests + SRCS + remquol_test.cpp + HDRS + RemQuoTest.h + DEPENDS + libc.include.math + libc.src.math.remquol + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + hypotf_test + SUITE + libc-math-smoke-tests + SRCS + hypotf_test.cpp + DEPENDS + libc.include.math + libc.src.math.hypotf + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + hypot_test + SUITE + libc-math-smoke-tests + SRCS + hypot_test.cpp + DEPENDS + libc.include.math + libc.src.math.hypot + libc.src.__support.FPUtil.fp_bits +) + +add_fp_unittest( + nanf_test + SUITE + libc-math-smoke-tests + SRCS + nanf_test.cpp + DEPENDS + libc.include.math + libc.include.signal + libc.src.math.nanf + libc.src.__support.FPUtil.fp_bits + # FIXME: The nan tests currently have death tests, which aren't supported for # hermetic tests. UNIT_TEST_ONLY ) @@ -1506,6 +2180,22 @@ add_fp_unittest( UNIT_TEST_ONLY ) +add_fp_unittest( + nanf128_test + SUITE + libc-math-smoke-tests + SRCS + nanf128_test.cpp + DEPENDS + libc.include.math + libc.include.signal + libc.src.math.nanf128 + libc.src.__support.FPUtil.fp_bits + # FIXME: The nan tests currently have death tests, which aren't supported for + # hermetic tests. + UNIT_TEST_ONLY +) + add_fp_unittest( nextafter_test SUITE @@ -1551,6 +2241,21 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + nextafterf128_test + SUITE + libc-math-smoke-tests + SRCS + nextafterf128_test.cpp + HDRS + NextAfterTest.h + DEPENDS + libc.include.math + libc.src.math.nextafterf128 + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.fp_bits +) + # FIXME: These tests are currently spurious for the GPU. if(NOT LIBC_TARGET_OS_IS_GPU) add_fp_unittest( @@ -1599,6 +2304,118 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + nextdown_test + SUITE + libc-math-smoke-tests + SRCS + nextdown_test.cpp + HDRS + NextDownTest.h + DEPENDS + libc.include.math + libc.src.math.nextdown + libc.src.__support.FPUtil.manipulation_functions +) + +add_fp_unittest( + nextdownf_test + SUITE + libc-math-smoke-tests + SRCS + nextdownf_test.cpp + HDRS + NextDownTest.h + DEPENDS + libc.include.math + libc.src.math.nextdownf + libc.src.__support.FPUtil.manipulation_functions +) + +add_fp_unittest( + nextdownl_test + SUITE + libc-math-smoke-tests + SRCS + nextdownl_test.cpp + HDRS + NextDownTest.h + DEPENDS + libc.include.math + libc.src.math.nextdownl + libc.src.__support.FPUtil.manipulation_functions +) + +add_fp_unittest( + nextdownf128_test + SUITE + libc-math-smoke-tests + SRCS + nextdownf128_test.cpp + HDRS + NextDownTest.h + DEPENDS + libc.include.math + libc.src.math.nextdownf128 + libc.src.__support.FPUtil.manipulation_functions +) + +add_fp_unittest( + nextup_test + SUITE + libc-math-smoke-tests + SRCS + nextup_test.cpp + HDRS + NextUpTest.h + DEPENDS + libc.include.math + libc.src.math.nextup + libc.src.__support.FPUtil.manipulation_functions +) + +add_fp_unittest( + nextupf_test + SUITE + libc-math-smoke-tests + SRCS + nextupf_test.cpp + HDRS + NextUpTest.h + DEPENDS + libc.include.math + libc.src.math.nextupf + libc.src.__support.FPUtil.manipulation_functions +) + +add_fp_unittest( + nextupl_test + SUITE + libc-math-smoke-tests + SRCS + nextupl_test.cpp + HDRS + NextUpTest.h + DEPENDS + libc.include.math + libc.src.math.nextupl + libc.src.__support.FPUtil.manipulation_functions +) + +add_fp_unittest( + nextupf128_test + SUITE + libc-math-smoke-tests + SRCS + nextupf128_test.cpp + HDRS + NextUpTest.h + DEPENDS + libc.include.math + libc.src.math.nextupf128 + libc.src.__support.FPUtil.manipulation_functions +) + # TODO(lntue): The current implementation of fputil::general::fma<float> is only # correctly rounded for the default rounding mode round-to-nearest tie-to-even. add_fp_unittest( @@ -1938,6 +2755,18 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + atan2f_test + SUITE + libc-math-smoke-tests + SRCS + atan2f_test.cpp + DEPENDS + libc.src.errno.errno + libc.src.math.atan2f + libc.src.__support.FPUtil.fp_bits +) + add_fp_unittest( scalbn_test SUITE diff --git a/libc/test/src/math/smoke/CanonicalizeTest.h b/libc/test/src/math/smoke/CanonicalizeTest.h new file mode 100644 index 0000000000000000000000000000000000000000..4361f7d8ac7ab17662d054f9ac995656d383762a --- /dev/null +++ b/libc/test/src/math/smoke/CanonicalizeTest.h @@ -0,0 +1,209 @@ +//===-- Utility class to test canonicalize[f|l] -----------------*- 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_TEST_SRC_MATH_SMOKE_CANONICALIZETEST_H +#define LLVM_LIBC_TEST_SRC_MATH_SMOKE_CANONICALIZETEST_H + +#include "src/__support/FPUtil/FPBits.h" +#include "src/__support/integer_literals.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +#include "include/llvm-libc-macros/math-macros.h" + +#define TEST_SPECIAL(x, y, expected, expected_exception) \ + EXPECT_EQ(expected, f(&x, &y)); \ + EXPECT_FP_EXCEPTION(expected_exception); \ + LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT) + +#define TEST_REGULAR(x, y, expected) TEST_SPECIAL(x, y, expected, 0) + +using LIBC_NAMESPACE::operator""_u128; + +template <typename T> +class CanonicalizeTest : public LIBC_NAMESPACE::testing::Test { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef int (*CanonicalizeFunc)(T *, const T *); + + void testSpecialNumbers(CanonicalizeFunc f) { + T cx; + + TEST_SPECIAL(cx, zero, 0, 0); + EXPECT_FP_EQ(cx, zero); + + TEST_SPECIAL(cx, neg_zero, 0, 0); + EXPECT_FP_EQ(cx, neg_zero); + + TEST_SPECIAL(cx, inf, 0, 0); + EXPECT_FP_EQ(cx, inf); + + TEST_SPECIAL(cx, neg_inf, 0, 0); + EXPECT_FP_EQ(cx, neg_inf); + + TEST_SPECIAL(cx, sNaN, 1, FE_INVALID); + EXPECT_FP_EQ(cx, aNaN); + } + + void testX64_80SpecialNumbers(CanonicalizeFunc f) { + if constexpr (LIBC_NAMESPACE::fputil::get_fp_type<T>() == + LIBC_NAMESPACE::fputil::FPType::X86_Binary80) { + T cx; + // Exponent | Significand | Meaning + // | Bits 63-62 | Bits 61-0 | + // All Ones | 00 | Zero | Pseudo Infinity, Value = SNaN + FPBits test1(0x00000000'00007FFF'00000000'00000000_u128); + const T test1_val = test1.get_val(); + TEST_SPECIAL(cx, test1_val, 1, FE_INVALID); + EXPECT_FP_EQ(cx, aNaN); + + // Exponent | Significand | Meaning + // | Bits 63-62 | Bits 61-0 | + // All Ones | 00 | Non-Zero | Pseudo NaN, Value = SNaN + FPBits test2_1(0x00000000'00007FFF'00000000'00000001_u128); + const T test2_1_val = test2_1.get_val(); + TEST_SPECIAL(cx, test2_1_val, 1, FE_INVALID); + EXPECT_FP_EQ(cx, aNaN); + + FPBits test2_2(0x00000000'00007FFF'00000042'70000001_u128); + const T test2_2_val = test2_2.get_val(); + TEST_SPECIAL(cx, test2_2_val, 1, FE_INVALID); + EXPECT_FP_EQ(cx, aNaN); + + FPBits test2_3(0x00000000'00007FFF'00000000'08261001_u128); + const T test2_3_val = test2_3.get_val(); + TEST_SPECIAL(cx, test2_3_val, 1, FE_INVALID); + EXPECT_FP_EQ(cx, aNaN); + + FPBits test2_4(0x00000000'00007FFF'00007800'08261001_u128); + const T test2_4_val = test2_4.get_val(); + TEST_SPECIAL(cx, test2_4_val, 1, FE_INVALID); + EXPECT_FP_EQ(cx, aNaN); + + // Exponent | Significand | Meaning + // | Bits 63-62 | Bits 61-0 | + // All Ones | 01 | Anything | Pseudo NaN, Value = SNaN + FPBits test3_1(0x00000000'00007FFF'40000000'00000000_u128); + const T test3_1_val = test3_1.get_val(); + TEST_SPECIAL(cx, test3_1_val, 1, FE_INVALID); + EXPECT_FP_EQ(cx, aNaN); + + FPBits test3_2(0x00000000'00007FFF'40000042'70000001_u128); + const T test3_2_val = test3_2.get_val(); + TEST_SPECIAL(cx, test3_2_val, 1, FE_INVALID); + EXPECT_FP_EQ(cx, aNaN); + + FPBits test3_3(0x00000000'00007FFF'40000000'08261001_u128); + const T test3_3_val = test3_3.get_val(); + TEST_SPECIAL(cx, test3_3_val, 1, FE_INVALID); + EXPECT_FP_EQ(cx, aNaN); + + FPBits test3_4(0x00000000'00007FFF'40007800'08261001_u128); + const T test3_4_val = test3_4.get_val(); + TEST_SPECIAL(cx, test3_4_val, 1, FE_INVALID); + EXPECT_FP_EQ(cx, aNaN); + + // Exponent | Significand | Meaning + // | Bit 63 | Bits 62-0 | + // All zeroes | One | Anything | Pseudo Denormal, Value = + // | | | (−1)**s × m × 2**−16382 + FPBits test4_1(0x00000000'00000000'80000000'00000000_u128); + const T test4_1_val = test4_1.get_val(); + TEST_SPECIAL(cx, test4_1_val, 0, 0); + EXPECT_FP_EQ( + cx, FPBits::make_value(test4_1.get_explicit_mantissa(), 0).get_val()); + + FPBits test4_2(0x00000000'00000000'80000042'70000001_u128); + const T test4_2_val = test4_2.get_val(); + TEST_SPECIAL(cx, test4_2_val, 0, 0); + EXPECT_FP_EQ( + cx, FPBits::make_value(test4_2.get_explicit_mantissa(), 0).get_val()); + + FPBits test4_3(0x00000000'00000000'80000000'08261001_u128); + const T test4_3_val = test4_3.get_val(); + TEST_SPECIAL(cx, test4_3_val, 0, 0); + EXPECT_FP_EQ( + cx, FPBits::make_value(test4_3.get_explicit_mantissa(), 0).get_val()); + + // Exponent | Significand | Meaning + // | Bit 63 | Bits 62-0 | + // All Other | Zero | Anything | Unnormal, Value = SNaN + // Values | | | + FPBits test5_1(0x00000000'00000040'00000000'00000001_u128); + const T test5_1_val = test5_1.get_val(); + TEST_SPECIAL(cx, test5_1_val, 1, FE_INVALID); + EXPECT_FP_EQ(cx, aNaN); + + FPBits test5_2(0x00000000'00000230'00000042'70000001_u128); + const T test5_2_val = test5_2.get_val(); + TEST_SPECIAL(cx, test5_2_val, 1, FE_INVALID); + EXPECT_FP_EQ(cx, aNaN); + + FPBits test5_3(0x00000000'00000560'00000000'08261001_u128); + const T test5_3_val = test5_3.get_val(); + TEST_SPECIAL(cx, test5_3_val, 1, FE_INVALID); + EXPECT_FP_EQ(cx, aNaN); + + FPBits test5_4(0x00000000'00000780'00000028'16000000_u128); + const T test5_4_val = test5_4.get_val(); + TEST_SPECIAL(cx, test5_4_val, 1, FE_INVALID); + EXPECT_FP_EQ(cx, aNaN); + + FPBits test5_5(0x00000000'00000900'00000042'70000001_u128); + const T test5_5_val = test5_5.get_val(); + TEST_SPECIAL(cx, test5_5_val, 1, FE_INVALID); + EXPECT_FP_EQ(cx, aNaN); + + FPBits test5_6(0x00000000'00000AB0'00000000'08261001_u128); + const T test5_6_val = test5_6.get_val(); + TEST_SPECIAL(cx, test5_6_val, 1, FE_INVALID); + EXPECT_FP_EQ(cx, aNaN); + } + } + + void testRegularNumbers(CanonicalizeFunc f) { + T cx; + const T test_var_1 = T(1.0); + TEST_REGULAR(cx, test_var_1, 0); + EXPECT_FP_EQ(cx, test_var_1); + const T test_var_2 = T(-1.0); + TEST_REGULAR(cx, test_var_2, 0); + EXPECT_FP_EQ(cx, test_var_2); + const T test_var_3 = T(10.0); + TEST_REGULAR(cx, test_var_3, 0); + EXPECT_FP_EQ(cx, test_var_3); + const T test_var_4 = T(-10.0); + TEST_REGULAR(cx, test_var_4, 0); + EXPECT_FP_EQ(cx, test_var_4); + const T test_var_5 = T(1234.0); + TEST_REGULAR(cx, test_var_5, 0); + EXPECT_FP_EQ(cx, test_var_5); + const T test_var_6 = T(-1234.0); + TEST_REGULAR(cx, test_var_6, 0); + EXPECT_FP_EQ(cx, test_var_6); + } +}; + +#define LIST_CANONICALIZE_TESTS(T, func) \ + using LlvmLibcCanonicalizeTest = CanonicalizeTest<T>; \ + TEST_F(LlvmLibcCanonicalizeTest, SpecialNumbers) { \ + testSpecialNumbers(&func); \ + } \ + TEST_F(LlvmLibcCanonicalizeTest, RegularNubmers) { \ + testRegularNumbers(&func); \ + } + +#define X86_80_SPECIAL_CANONICALIZE_TEST(T, func) \ + using LlvmLibcCanonicalizeTest = CanonicalizeTest<T>; \ + TEST_F(LlvmLibcCanonicalizeTest, X64_80SpecialNumbers) { \ + testX64_80SpecialNumbers(&func); \ + } + +#endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_CANONICALIZETEST_H diff --git a/libc/test/src/math/smoke/CeilTest.h b/libc/test/src/math/smoke/CeilTest.h index 5248dbca50370141e8df73630a81df8bfa2f4276..ec70258fddec151c1d39b1abd49b5f0016e55745 100644 --- a/libc/test/src/math/smoke/CeilTest.h +++ b/libc/test/src/math/smoke/CeilTest.h @@ -12,7 +12,7 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" template <typename T> class CeilTest : public LIBC_NAMESPACE::testing::Test { diff --git a/libc/test/src/math/smoke/CopySignTest.h b/libc/test/src/math/smoke/CopySignTest.h index 9ee34338ba8073ecb162b4cc09462a287a347e2e..70a6a419e0a03058900e9dd4b0b24779a885be6a 100644 --- a/libc/test/src/math/smoke/CopySignTest.h +++ b/libc/test/src/math/smoke/CopySignTest.h @@ -12,7 +12,7 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" template <typename T> class CopySignTest : public LIBC_NAMESPACE::testing::Test { diff --git a/libc/test/src/math/smoke/FAbsTest.h b/libc/test/src/math/smoke/FAbsTest.h index cf05882e22f97d8fe515368c9e98aabc7212af4a..9309c2ada4a11f6713052beb7ada5d48963a9e74 100644 --- a/libc/test/src/math/smoke/FAbsTest.h +++ b/libc/test/src/math/smoke/FAbsTest.h @@ -12,7 +12,7 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" template <typename T> class FAbsTest : public LIBC_NAMESPACE::testing::Test { diff --git a/libc/test/src/math/smoke/FDimTest.h b/libc/test/src/math/smoke/FDimTest.h index 5cb3dd117348480c6b7e7483c0145d55c615dfa3..e557b40d90efa1e43a10041442d3e1a456ec28fa 100644 --- a/libc/test/src/math/smoke/FDimTest.h +++ b/libc/test/src/math/smoke/FDimTest.h @@ -17,7 +17,6 @@ public: using FuncPtr = T (*)(T, T); using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; using StorageType = typename FPBits::StorageType; - using Sign = LIBC_NAMESPACE::fputil::Sign; const T inf = FPBits::inf(Sign::POS).get_val(); const T neg_inf = FPBits::inf(Sign::NEG).get_val(); diff --git a/libc/test/src/math/smoke/FMaxTest.h b/libc/test/src/math/smoke/FMaxTest.h index 98fae06ee2a0fdf58ee6d360693a7f7048c0886e..b8781a85d10f4f397a5ec0ae3bbdacd9ba9cd1b3 100644 --- a/libc/test/src/math/smoke/FMaxTest.h +++ b/libc/test/src/math/smoke/FMaxTest.h @@ -1,4 +1,4 @@ -//===-- Utility class to test fmin[f|l] -------------------------*- C++ -*-===// +//===-- Utility class to test fmax[f|l] -------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libc/test/src/math/smoke/FMaximumMagNumTest.h b/libc/test/src/math/smoke/FMaximumMagNumTest.h new file mode 100644 index 0000000000000000000000000000000000000000..715dd4ed913f838b817b71583e3af4665759c71c --- /dev/null +++ b/libc/test/src/math/smoke/FMaximumMagNumTest.h @@ -0,0 +1,101 @@ +//===-- Utility class to test fmaximum_mag_num[f|l] -------------*- 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_TEST_SRC_MATH_SMOKE_FMAXIMUMMAG_NUMTEST_H +#define LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMAXIMUMMAG_NUMTEST_H + +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/FPUtil/FPBits.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +template <typename T> +class FMaximumMagNumTest : public LIBC_NAMESPACE::testing::Test { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef T (*FMaximumMagNumFunc)(T, T); + + void testNaN(FMaximumMagNumFunc func) { + EXPECT_FP_EQ(inf, func(aNaN, inf)); + EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(sNaN, inf), FE_INVALID); + EXPECT_FP_EQ(neg_inf, func(neg_inf, aNaN)); + EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(neg_inf, sNaN), FE_INVALID); + EXPECT_EQ(FPBits(aNaN).uintval(), FPBits(func(aNaN, aNaN)).uintval()); + EXPECT_FP_EQ(0.0, func(aNaN, 0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, aNaN)); + EXPECT_FP_EQ_WITH_EXCEPTION(0.0, func(sNaN, 0.0), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(-0.0, func(-0.0, sNaN), FE_INVALID); + EXPECT_FP_EQ(T(-1.2345), func(aNaN, T(-1.2345))); + EXPECT_FP_EQ(T(1.2345), func(T(1.2345), aNaN)); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.2345), func(sNaN, T(-1.2345)), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.2345), func(T(1.2345), sNaN), FE_INVALID); + EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(aNaN, sNaN), FE_INVALID); + EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(sNaN, aNaN), FE_INVALID); + EXPECT_EQ(FPBits(aNaN).uintval(), FPBits(func(aNaN, sNaN)).uintval()); + EXPECT_EQ(FPBits(aNaN).uintval(), FPBits(func(sNaN, aNaN)).uintval()); + EXPECT_EQ(FPBits(aNaN).uintval(), FPBits(func(sNaN, sNaN)).uintval()); + } + + void testInfArg(FMaximumMagNumFunc func) { + EXPECT_FP_EQ(inf, func(neg_inf, inf)); + EXPECT_FP_EQ(inf, func(inf, 0.0)); + EXPECT_FP_EQ(inf, func(-0.0, inf)); + EXPECT_FP_EQ(inf, func(inf, T(1.2345))); + EXPECT_FP_EQ(inf, func(T(-1.2345), inf)); + } + + void testNegInfArg(FMaximumMagNumFunc func) { + EXPECT_FP_EQ(inf, func(inf, neg_inf)); + EXPECT_FP_EQ(neg_inf, func(neg_inf, 0.0)); + EXPECT_FP_EQ(neg_inf, func(-0.0, neg_inf)); + EXPECT_FP_EQ(neg_inf, func(neg_inf, T(-1.2345))); + EXPECT_FP_EQ(neg_inf, func(T(1.2345), neg_inf)); + } + + void testBothZero(FMaximumMagNumFunc func) { + EXPECT_FP_EQ(0.0, func(0.0, 0.0)); + EXPECT_FP_EQ(0.0, func(-0.0, 0.0)); + EXPECT_FP_EQ(0.0, func(0.0, -0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, -0.0)); + } + + void testRange(FMaximumMagNumFunc func) { + constexpr StorageType COUNT = 100'001; + constexpr StorageType STEP = STORAGE_MAX / COUNT; + for (StorageType i = 0, v = 0, w = STORAGE_MAX; i <= COUNT; + ++i, v += STEP, w -= STEP) { + FPBits xbits(v), ybits(w); + if (xbits.is_inf_or_nan()) + continue; + if (ybits.is_inf_or_nan()) + continue; + T x = xbits.get_val(); + T y = ybits.get_val(); + if ((x == 0) && (y == 0)) + continue; + + if (LIBC_NAMESPACE::fputil::abs(x) > LIBC_NAMESPACE::fputil::abs(y)) { + EXPECT_FP_EQ(x, func(x, y)); + } else { + EXPECT_FP_EQ(y, func(x, y)); + } + } + } +}; + +#define LIST_FMAXIMUM_MAG_NUM_TESTS(T, func) \ + using LlvmLibcFMaximumMagNumTest = FMaximumMagNumTest<T>; \ + TEST_F(LlvmLibcFMaximumMagNumTest, NaN) { testNaN(&func); } \ + TEST_F(LlvmLibcFMaximumMagNumTest, InfArg) { testInfArg(&func); } \ + TEST_F(LlvmLibcFMaximumMagNumTest, NegInfArg) { testNegInfArg(&func); } \ + TEST_F(LlvmLibcFMaximumMagNumTest, BothZero) { testBothZero(&func); } \ + TEST_F(LlvmLibcFMaximumMagNumTest, Range) { testRange(&func); } + +#endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMAXIMUMMAG_NUMTEST_H diff --git a/libc/test/src/math/smoke/FMaximumMagTest.h b/libc/test/src/math/smoke/FMaximumMagTest.h new file mode 100644 index 0000000000000000000000000000000000000000..38276e0fe2fdb0486daf62ffa15885c704df2d89 --- /dev/null +++ b/libc/test/src/math/smoke/FMaximumMagTest.h @@ -0,0 +1,89 @@ +//===-- Utility class to test fmaximum_mag[f|l] -----------------*- 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_TEST_SRC_MATH_SMOKE_FMAXIMUM_MAGTEST_H +#define LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMAXIMUM_MAGTEST_H + +#include "src/__support/FPUtil/BasicOperations.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +template <typename T> +class FMaximumMagTest : public LIBC_NAMESPACE::testing::Test { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef T (*FMaximumMagFunc)(T, T); + + void testNaN(FMaximumMagFunc func) { + EXPECT_FP_EQ(aNaN, func(aNaN, inf)); + EXPECT_FP_EQ(aNaN, func(neg_inf, aNaN)); + EXPECT_FP_EQ(aNaN, func(aNaN, 0.0)); + EXPECT_FP_EQ(aNaN, func(-0.0, aNaN)); + EXPECT_FP_EQ(aNaN, func(aNaN, T(-1.2345))); + EXPECT_FP_EQ(aNaN, func(T(1.2345), aNaN)); + EXPECT_FP_EQ(aNaN, func(aNaN, aNaN)); + } + + void testInfArg(FMaximumMagFunc func) { + EXPECT_FP_EQ(inf, func(neg_inf, inf)); + EXPECT_FP_EQ(inf, func(inf, 0.0)); + EXPECT_FP_EQ(inf, func(-0.0, inf)); + EXPECT_FP_EQ(inf, func(inf, T(1.2345))); + EXPECT_FP_EQ(inf, func(T(-1.2345), inf)); + } + + void testNegInfArg(FMaximumMagFunc func) { + EXPECT_FP_EQ(inf, func(inf, neg_inf)); + EXPECT_FP_EQ(neg_inf, func(neg_inf, 0.0)); + EXPECT_FP_EQ(neg_inf, func(-0.0, neg_inf)); + EXPECT_FP_EQ(neg_inf, func(neg_inf, T(-1.2345))); + EXPECT_FP_EQ(neg_inf, func(T(1.2345), neg_inf)); + } + + void testBothZero(FMaximumMagFunc func) { + EXPECT_FP_EQ(0.0, func(0.0, 0.0)); + EXPECT_FP_EQ(0.0, func(-0.0, 0.0)); + EXPECT_FP_EQ(0.0, func(0.0, -0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, -0.0)); + } + + void testRange(FMaximumMagFunc func) { + constexpr StorageType COUNT = 100'001; + constexpr StorageType STEP = STORAGE_MAX / COUNT; + for (StorageType i = 0, v = 0, w = STORAGE_MAX; i <= COUNT; + ++i, v += STEP, w -= STEP) { + FPBits xbits(v), ybits(w); + if (xbits.is_inf_or_nan()) + continue; + if (ybits.is_inf_or_nan()) + continue; + T x = xbits.get_val(); + T y = ybits.get_val(); + if ((x == 0) && (y == 0)) + continue; + + if (LIBC_NAMESPACE::fputil::abs(x) > LIBC_NAMESPACE::fputil::abs(y)) { + EXPECT_FP_EQ(x, func(x, y)); + } else { + EXPECT_FP_EQ(y, func(x, y)); + } + } + } +}; + +#define LIST_FMAXIMUM_MAG_TESTS(T, func) \ + using LlvmLibcFMaximumMagTest = FMaximumMagTest<T>; \ + TEST_F(LlvmLibcFMaximumMagTest, NaN) { testNaN(&func); } \ + TEST_F(LlvmLibcFMaximumMagTest, InfArg) { testInfArg(&func); } \ + TEST_F(LlvmLibcFMaximumMagTest, NegInfArg) { testNegInfArg(&func); } \ + TEST_F(LlvmLibcFMaximumMagTest, BothZero) { testBothZero(&func); } \ + TEST_F(LlvmLibcFMaximumMagTest, Range) { testRange(&func); } + +#endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMAXIMUM_MAGTEST_H diff --git a/libc/test/src/math/smoke/FMaximumNumTest.h b/libc/test/src/math/smoke/FMaximumNumTest.h new file mode 100644 index 0000000000000000000000000000000000000000..57096f6b614a2c8e093f7fb69a8c934b5bdb79a2 --- /dev/null +++ b/libc/test/src/math/smoke/FMaximumNumTest.h @@ -0,0 +1,100 @@ +//===-- Utility class to test fmaximum_num[f|l] -----------------*- 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_TEST_SRC_MATH_SMOKE_FMAXIMUMNUMTEST_H +#define LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMAXIMUMNUMTEST_H + +#include "src/__support/FPUtil/FPBits.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +template <typename T> +class FMaximumNumTest : public LIBC_NAMESPACE::testing::Test { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef T (*FMaximumNumFunc)(T, T); + + void testNaN(FMaximumNumFunc func) { + EXPECT_FP_EQ(inf, func(aNaN, inf)); + EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(sNaN, inf), FE_INVALID); + EXPECT_FP_EQ(neg_inf, func(neg_inf, aNaN)); + EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(neg_inf, sNaN), FE_INVALID); + EXPECT_EQ(FPBits(aNaN).uintval(), FPBits(func(aNaN, aNaN)).uintval()); + EXPECT_FP_EQ(0.0, func(aNaN, 0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, aNaN)); + EXPECT_FP_EQ_WITH_EXCEPTION(0.0, func(sNaN, 0.0), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(-0.0, func(-0.0, sNaN), FE_INVALID); + EXPECT_FP_EQ(T(-1.2345), func(aNaN, T(-1.2345))); + EXPECT_FP_EQ(T(1.2345), func(T(1.2345), aNaN)); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.2345), func(sNaN, T(-1.2345)), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.2345), func(T(1.2345), sNaN), FE_INVALID); + EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(aNaN, sNaN), FE_INVALID); + EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(sNaN, aNaN), FE_INVALID); + EXPECT_EQ(FPBits(aNaN).uintval(), FPBits(func(aNaN, sNaN)).uintval()); + EXPECT_EQ(FPBits(aNaN).uintval(), FPBits(func(sNaN, aNaN)).uintval()); + EXPECT_EQ(FPBits(aNaN).uintval(), FPBits(func(sNaN, sNaN)).uintval()); + } + + void testInfArg(FMaximumNumFunc func) { + EXPECT_FP_EQ(inf, func(neg_inf, inf)); + EXPECT_FP_EQ(inf, func(inf, 0.0)); + EXPECT_FP_EQ(inf, func(-0.0, inf)); + EXPECT_FP_EQ(inf, func(inf, T(1.2345))); + EXPECT_FP_EQ(inf, func(T(-1.2345), inf)); + } + + void testNegInfArg(FMaximumNumFunc func) { + EXPECT_FP_EQ(inf, func(inf, neg_inf)); + EXPECT_FP_EQ(0.0, func(neg_inf, 0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, neg_inf)); + EXPECT_FP_EQ(T(-1.2345), func(neg_inf, T(-1.2345))); + EXPECT_FP_EQ(T(1.2345), func(T(1.2345), neg_inf)); + } + + void testBothZero(FMaximumNumFunc func) { + EXPECT_FP_EQ(0.0, func(0.0, 0.0)); + EXPECT_FP_EQ(0.0, func(-0.0, 0.0)); + EXPECT_FP_EQ(0.0, func(0.0, -0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, -0.0)); + } + + void testRange(FMaximumNumFunc func) { + constexpr StorageType COUNT = 100'001; + constexpr StorageType STEP = STORAGE_MAX / COUNT; + for (StorageType i = 0, v = 0, w = STORAGE_MAX; i <= COUNT; + ++i, v += STEP, w -= STEP) { + FPBits xbits(v), ybits(w); + if (xbits.is_inf_or_nan()) + continue; + if (ybits.is_inf_or_nan()) + continue; + T x = xbits.get_val(); + T y = ybits.get_val(); + if ((x == 0) && (y == 0)) + continue; + + if (x > y) { + EXPECT_FP_EQ(x, func(x, y)); + } else { + EXPECT_FP_EQ(y, func(x, y)); + } + } + } +}; + +#define LIST_FMAXIMUM_NUM_TESTS(T, func) \ + using LlvmLibcFMaximumNumTest = FMaximumNumTest<T>; \ + TEST_F(LlvmLibcFMaximumNumTest, NaN) { testNaN(&func); } \ + TEST_F(LlvmLibcFMaximumNumTest, InfArg) { testInfArg(&func); } \ + TEST_F(LlvmLibcFMaximumNumTest, NegInfArg) { testNegInfArg(&func); } \ + TEST_F(LlvmLibcFMaximumNumTest, BothZero) { testBothZero(&func); } \ + TEST_F(LlvmLibcFMaximumNumTest, Range) { testRange(&func); } + +#endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMAXIMUMNUMTEST_H diff --git a/libc/test/src/math/smoke/FMaximumTest.h b/libc/test/src/math/smoke/FMaximumTest.h new file mode 100644 index 0000000000000000000000000000000000000000..4db8bb93baaeefbbd60f4a843af3ce5970641fef --- /dev/null +++ b/libc/test/src/math/smoke/FMaximumTest.h @@ -0,0 +1,88 @@ +//===-- Utility class to test fmaximum[f|l] ---------------------*- 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_TEST_SRC_MATH_SMOKE_FMAXIMUMTEST_H +#define LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMAXIMUMTEST_H + +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +template <typename T> +class FMaximumTest : public LIBC_NAMESPACE::testing::Test { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef T (*FMaximumFunc)(T, T); + + void testNaN(FMaximumFunc func) { + EXPECT_FP_EQ(aNaN, func(aNaN, inf)); + EXPECT_FP_EQ(aNaN, func(neg_inf, aNaN)); + EXPECT_FP_EQ(aNaN, func(aNaN, 0.0)); + EXPECT_FP_EQ(aNaN, func(-0.0, aNaN)); + EXPECT_FP_EQ(aNaN, func(aNaN, T(-1.2345))); + EXPECT_FP_EQ(aNaN, func(T(1.2345), aNaN)); + EXPECT_FP_EQ(aNaN, func(aNaN, aNaN)); + } + + void testInfArg(FMaximumFunc func) { + EXPECT_FP_EQ(inf, func(neg_inf, inf)); + EXPECT_FP_EQ(inf, func(inf, 0.0)); + EXPECT_FP_EQ(inf, func(-0.0, inf)); + EXPECT_FP_EQ(inf, func(inf, T(1.2345))); + EXPECT_FP_EQ(inf, func(T(-1.2345), inf)); + } + + void testNegInfArg(FMaximumFunc func) { + EXPECT_FP_EQ(inf, func(inf, neg_inf)); + EXPECT_FP_EQ(0.0, func(neg_inf, 0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, neg_inf)); + EXPECT_FP_EQ(T(-1.2345), func(neg_inf, T(-1.2345))); + EXPECT_FP_EQ(T(1.2345), func(T(1.2345), neg_inf)); + } + + void testBothZero(FMaximumFunc func) { + EXPECT_FP_EQ(0.0, func(0.0, 0.0)); + EXPECT_FP_EQ(0.0, func(-0.0, 0.0)); + EXPECT_FP_EQ(0.0, func(0.0, -0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, -0.0)); + } + + void testRange(FMaximumFunc func) { + constexpr StorageType COUNT = 100'001; + constexpr StorageType STEP = STORAGE_MAX / COUNT; + for (StorageType i = 0, v = 0, w = STORAGE_MAX; i <= COUNT; + ++i, v += STEP, w -= STEP) { + FPBits xbits(v), ybits(w); + if (xbits.is_inf_or_nan()) + continue; + if (ybits.is_inf_or_nan()) + continue; + T x = xbits.get_val(); + T y = ybits.get_val(); + if ((x == 0) && (y == 0)) + continue; + + if (x > y) { + EXPECT_FP_EQ(x, func(x, y)); + } else { + EXPECT_FP_EQ(y, func(x, y)); + } + } + } +}; + +#define LIST_FMAXIMUM_TESTS(T, func) \ + using LlvmLibcFMaximumTest = FMaximumTest<T>; \ + TEST_F(LlvmLibcFMaximumTest, NaN) { testNaN(&func); } \ + TEST_F(LlvmLibcFMaximumTest, InfArg) { testInfArg(&func); } \ + TEST_F(LlvmLibcFMaximumTest, NegInfArg) { testNegInfArg(&func); } \ + TEST_F(LlvmLibcFMaximumTest, BothZero) { testBothZero(&func); } \ + TEST_F(LlvmLibcFMaximumTest, Range) { testRange(&func); } + +#endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMAXIMUMTEST_H diff --git a/libc/test/src/math/smoke/FMinimumMagNumTest.h b/libc/test/src/math/smoke/FMinimumMagNumTest.h new file mode 100644 index 0000000000000000000000000000000000000000..dec8b70740ca593eebc27e6c6cb75b49afbe018f --- /dev/null +++ b/libc/test/src/math/smoke/FMinimumMagNumTest.h @@ -0,0 +1,101 @@ +//===-- Utility class to test fminimum_mag_num[f|l] -------------*- 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_TEST_SRC_MATH_SMOKE_FMINIMUMMAG_NUMTEST_H +#define LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMINIMUMMAG_NUMTEST_H + +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/FPUtil/FPBits.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +template <typename T> +class FMinimumMagNumTest : public LIBC_NAMESPACE::testing::Test { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef T (*FMinimumMagNumFunc)(T, T); + + void testNaN(FMinimumMagNumFunc func) { + EXPECT_FP_EQ(inf, func(aNaN, inf)); + EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(sNaN, inf), FE_INVALID); + EXPECT_FP_EQ(neg_inf, func(neg_inf, aNaN)); + EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(neg_inf, sNaN), FE_INVALID); + EXPECT_EQ(FPBits(aNaN).uintval(), FPBits(func(aNaN, aNaN)).uintval()); + EXPECT_FP_EQ(0.0, func(aNaN, 0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, aNaN)); + EXPECT_FP_EQ_WITH_EXCEPTION(0.0, func(sNaN, 0.0), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(-0.0, func(-0.0, sNaN), FE_INVALID); + EXPECT_FP_EQ(T(-1.2345), func(aNaN, T(-1.2345))); + EXPECT_FP_EQ(T(1.2345), func(T(1.2345), aNaN)); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.2345), func(sNaN, T(-1.2345)), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.2345), func(T(1.2345), sNaN), FE_INVALID); + EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(aNaN, sNaN), FE_INVALID); + EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(sNaN, aNaN), FE_INVALID); + EXPECT_EQ(FPBits(aNaN).uintval(), FPBits(func(aNaN, sNaN)).uintval()); + EXPECT_EQ(FPBits(aNaN).uintval(), FPBits(func(sNaN, aNaN)).uintval()); + EXPECT_EQ(FPBits(aNaN).uintval(), FPBits(func(sNaN, sNaN)).uintval()); + } + + void testInfArg(FMinimumMagNumFunc func) { + EXPECT_FP_EQ(neg_inf, func(neg_inf, inf)); + EXPECT_FP_EQ(0.0, func(inf, 0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, inf)); + EXPECT_FP_EQ(T(1.2345), func(inf, T(1.2345))); + EXPECT_FP_EQ(T(-1.2345), func(T(-1.2345), inf)); + } + + void testNegInfArg(FMinimumMagNumFunc func) { + EXPECT_FP_EQ(neg_inf, func(inf, neg_inf)); + EXPECT_FP_EQ(0.0, func(neg_inf, 0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, neg_inf)); + EXPECT_FP_EQ(T(-1.2345), func(neg_inf, T(-1.2345))); + EXPECT_FP_EQ(T(1.2345), func(T(1.2345), neg_inf)); + } + + void testBothZero(FMinimumMagNumFunc func) { + EXPECT_FP_EQ(0.0, func(0.0, 0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, 0.0)); + EXPECT_FP_EQ(-0.0, func(0.0, -0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, -0.0)); + } + + void testRange(FMinimumMagNumFunc func) { + constexpr StorageType COUNT = 100'001; + constexpr StorageType STEP = STORAGE_MAX / COUNT; + for (StorageType i = 0, v = 0, w = STORAGE_MAX; i <= COUNT; + ++i, v += STEP, w -= STEP) { + FPBits xbits(v), ybits(w); + if (xbits.is_inf_or_nan()) + continue; + if (ybits.is_inf_or_nan()) + continue; + T x = xbits.get_val(); + T y = ybits.get_val(); + if ((x == 0) && (y == 0)) + continue; + + if (LIBC_NAMESPACE::fputil::abs(x) > LIBC_NAMESPACE::fputil::abs(y)) { + EXPECT_FP_EQ(y, func(x, y)); + } else { + EXPECT_FP_EQ(x, func(x, y)); + } + } + } +}; + +#define LIST_FMINIMUM_MAG_NUM_TESTS(T, func) \ + using LlvmLibcFMinimumMagNumTest = FMinimumMagNumTest<T>; \ + TEST_F(LlvmLibcFMinimumMagNumTest, NaN) { testNaN(&func); } \ + TEST_F(LlvmLibcFMinimumMagNumTest, InfArg) { testInfArg(&func); } \ + TEST_F(LlvmLibcFMinimumMagNumTest, NegInfArg) { testNegInfArg(&func); } \ + TEST_F(LlvmLibcFMinimumMagNumTest, BothZero) { testBothZero(&func); } \ + TEST_F(LlvmLibcFMinimumMagNumTest, Range) { testRange(&func); } + +#endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMINIMUMMAG_NUMTEST_H diff --git a/libc/test/src/math/smoke/FMinimumMagTest.h b/libc/test/src/math/smoke/FMinimumMagTest.h new file mode 100644 index 0000000000000000000000000000000000000000..b11092e5379ba0abe80a579af68a82adfc8ae4f5 --- /dev/null +++ b/libc/test/src/math/smoke/FMinimumMagTest.h @@ -0,0 +1,89 @@ +//===-- Utility class to test fminimum_mag[f|l] -----------------*- 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_TEST_SRC_MATH_SMOKE_FMINIMUM_MAGTEST_H +#define LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMINIMUM_MAGTEST_H + +#include "src/__support/FPUtil/BasicOperations.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +template <typename T> +class FMinimumMagTest : public LIBC_NAMESPACE::testing::Test { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef T (*FMinimumMagFunc)(T, T); + + void testNaN(FMinimumMagFunc func) { + EXPECT_FP_EQ(aNaN, func(aNaN, inf)); + EXPECT_FP_EQ(aNaN, func(neg_inf, aNaN)); + EXPECT_FP_EQ(aNaN, func(aNaN, 0.0)); + EXPECT_FP_EQ(aNaN, func(-0.0, aNaN)); + EXPECT_FP_EQ(aNaN, func(aNaN, T(-1.2345))); + EXPECT_FP_EQ(aNaN, func(T(1.2345), aNaN)); + EXPECT_FP_EQ(aNaN, func(aNaN, aNaN)); + } + + void testInfArg(FMinimumMagFunc func) { + EXPECT_FP_EQ(neg_inf, func(neg_inf, inf)); + EXPECT_FP_EQ(0.0, func(inf, 0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, inf)); + EXPECT_FP_EQ(T(1.2345), func(inf, T(1.2345))); + EXPECT_FP_EQ(T(-1.2345), func(T(-1.2345), inf)); + } + + void testNegInfArg(FMinimumMagFunc func) { + EXPECT_FP_EQ(neg_inf, func(inf, neg_inf)); + EXPECT_FP_EQ(0.0, func(neg_inf, 0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, neg_inf)); + EXPECT_FP_EQ(T(-1.2345), func(neg_inf, T(-1.2345))); + EXPECT_FP_EQ(T(1.2345), func(T(1.2345), neg_inf)); + } + + void testBothZero(FMinimumMagFunc func) { + EXPECT_FP_EQ(0.0, func(0.0, 0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, 0.0)); + EXPECT_FP_EQ(-0.0, func(0.0, -0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, -0.0)); + } + + void testRange(FMinimumMagFunc func) { + constexpr StorageType COUNT = 100'001; + constexpr StorageType STEP = STORAGE_MAX / COUNT; + for (StorageType i = 0, v = 0, w = STORAGE_MAX; i <= COUNT; + ++i, v += STEP, w -= STEP) { + FPBits xbits(v), ybits(w); + if (xbits.is_inf_or_nan()) + continue; + if (ybits.is_inf_or_nan()) + continue; + T x = xbits.get_val(); + T y = ybits.get_val(); + if ((x == 0) && (y == 0)) + continue; + + if (LIBC_NAMESPACE::fputil::abs(x) < LIBC_NAMESPACE::fputil::abs(y)) { + EXPECT_FP_EQ(x, func(x, y)); + } else { + EXPECT_FP_EQ(y, func(x, y)); + } + } + } +}; + +#define LIST_FMINIMUM_MAG_TESTS(T, func) \ + using LlvmLibcFMinimumMagTest = FMinimumMagTest<T>; \ + TEST_F(LlvmLibcFMinimumMagTest, NaN) { testNaN(&func); } \ + TEST_F(LlvmLibcFMinimumMagTest, InfArg) { testInfArg(&func); } \ + TEST_F(LlvmLibcFMinimumMagTest, NegInfArg) { testNegInfArg(&func); } \ + TEST_F(LlvmLibcFMinimumMagTest, BothZero) { testBothZero(&func); } \ + TEST_F(LlvmLibcFMinimumMagTest, Range) { testRange(&func); } + +#endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMINIMUM_MAGTEST_H diff --git a/libc/test/src/math/smoke/FMinimumNumTest.h b/libc/test/src/math/smoke/FMinimumNumTest.h new file mode 100644 index 0000000000000000000000000000000000000000..7fcc291b4c00cd8ee9a046650dbf09e1c7f7a5c0 --- /dev/null +++ b/libc/test/src/math/smoke/FMinimumNumTest.h @@ -0,0 +1,100 @@ +//===-- Utility class to test fminimum_num[f|l] -----------------*- 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_TEST_SRC_MATH_SMOKE_FMINIMUMNUMTEST_H +#define LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMINIMUMNUMTEST_H + +#include "src/__support/FPUtil/FPBits.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +template <typename T> +class FMinimumNumTest : public LIBC_NAMESPACE::testing::Test { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef T (*FMinimumNumFunc)(T, T); + + void testNaN(FMinimumNumFunc func) { + EXPECT_FP_EQ(inf, func(aNaN, inf)); + EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(sNaN, inf), FE_INVALID); + EXPECT_FP_EQ(neg_inf, func(neg_inf, aNaN)); + EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(neg_inf, sNaN), FE_INVALID); + EXPECT_EQ(FPBits(aNaN).uintval(), FPBits(func(aNaN, aNaN)).uintval()); + EXPECT_FP_EQ(0.0, func(aNaN, 0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, aNaN)); + EXPECT_FP_EQ_WITH_EXCEPTION(0.0, func(sNaN, 0.0), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(-0.0, func(-0.0, sNaN), FE_INVALID); + EXPECT_FP_EQ(T(-1.2345), func(aNaN, T(-1.2345))); + EXPECT_FP_EQ(T(1.2345), func(T(1.2345), aNaN)); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.2345), func(sNaN, T(-1.2345)), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.2345), func(T(1.2345), sNaN), FE_INVALID); + EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(aNaN, sNaN), FE_INVALID); + EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(sNaN, aNaN), FE_INVALID); + EXPECT_EQ(FPBits(aNaN).uintval(), FPBits(func(aNaN, sNaN)).uintval()); + EXPECT_EQ(FPBits(aNaN).uintval(), FPBits(func(sNaN, aNaN)).uintval()); + EXPECT_EQ(FPBits(aNaN).uintval(), FPBits(func(sNaN, sNaN)).uintval()); + } + + void testInfArg(FMinimumNumFunc func) { + EXPECT_FP_EQ(neg_inf, func(neg_inf, inf)); + EXPECT_FP_EQ(0.0, func(inf, 0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, inf)); + EXPECT_FP_EQ(T(1.2345), func(inf, T(1.2345))); + EXPECT_FP_EQ(T(-1.2345), func(T(-1.2345), inf)); + } + + void testNegInfArg(FMinimumNumFunc func) { + EXPECT_FP_EQ(neg_inf, func(inf, neg_inf)); + EXPECT_FP_EQ(neg_inf, func(neg_inf, 0.0)); + EXPECT_FP_EQ(neg_inf, func(-0.0, neg_inf)); + EXPECT_FP_EQ(neg_inf, func(neg_inf, T(-1.2345))); + EXPECT_FP_EQ(neg_inf, func(T(1.2345), neg_inf)); + } + + void testBothZero(FMinimumNumFunc func) { + EXPECT_FP_EQ(0.0, func(0.0, 0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, 0.0)); + EXPECT_FP_EQ(-0.0, func(0.0, -0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, -0.0)); + } + + void testRange(FMinimumNumFunc func) { + constexpr StorageType COUNT = 100'001; + constexpr StorageType STEP = STORAGE_MAX / COUNT; + for (StorageType i = 0, v = 0, w = STORAGE_MAX; i <= COUNT; + ++i, v += STEP, w -= STEP) { + FPBits xbits(v), ybits(w); + if (xbits.is_inf_or_nan()) + continue; + if (ybits.is_inf_or_nan()) + continue; + T x = xbits.get_val(); + T y = ybits.get_val(); + if ((x == 0) && (y == 0)) + continue; + + if (x > y) { + EXPECT_FP_EQ(y, func(x, y)); + } else { + EXPECT_FP_EQ(x, func(x, y)); + } + } + } +}; + +#define LIST_FMINIMUM_NUM_TESTS(T, func) \ + using LlvmLibcFMinimumNumTest = FMinimumNumTest<T>; \ + TEST_F(LlvmLibcFMinimumNumTest, NaN) { testNaN(&func); } \ + TEST_F(LlvmLibcFMinimumNumTest, InfArg) { testInfArg(&func); } \ + TEST_F(LlvmLibcFMinimumNumTest, NegInfArg) { testNegInfArg(&func); } \ + TEST_F(LlvmLibcFMinimumNumTest, BothZero) { testBothZero(&func); } \ + TEST_F(LlvmLibcFMinimumNumTest, Range) { testRange(&func); } + +#endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMINIMUMNUMTEST_H diff --git a/libc/test/src/math/smoke/FMinimumTest.h b/libc/test/src/math/smoke/FMinimumTest.h new file mode 100644 index 0000000000000000000000000000000000000000..bc04a6d99356547ee0a2e44f6d6348c72ddb4c10 --- /dev/null +++ b/libc/test/src/math/smoke/FMinimumTest.h @@ -0,0 +1,88 @@ +//===-- Utility class to test fminimum[f|l] ---------------------*- 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_TEST_SRC_MATH_SMOKE_FMINIMUMTEST_H +#define LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMINIMUMTEST_H + +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +template <typename T> +class FMinimumTest : public LIBC_NAMESPACE::testing::Test { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef T (*FMinimumFunc)(T, T); + + void testNaN(FMinimumFunc func) { + EXPECT_FP_EQ(aNaN, func(aNaN, inf)); + EXPECT_FP_EQ(aNaN, func(neg_inf, aNaN)); + EXPECT_FP_EQ(aNaN, func(aNaN, 0.0)); + EXPECT_FP_EQ(aNaN, func(-0.0, aNaN)); + EXPECT_FP_EQ(aNaN, func(aNaN, T(-1.2345))); + EXPECT_FP_EQ(aNaN, func(T(1.2345), aNaN)); + EXPECT_FP_EQ(aNaN, func(aNaN, aNaN)); + } + + void testInfArg(FMinimumFunc func) { + EXPECT_FP_EQ(neg_inf, func(neg_inf, inf)); + EXPECT_FP_EQ(0.0, func(inf, 0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, inf)); + EXPECT_FP_EQ(T(1.2345), func(inf, T(1.2345))); + EXPECT_FP_EQ(T(1.2345), func(T(1.2345), inf)); + } + + void testNegInfArg(FMinimumFunc func) { + EXPECT_FP_EQ(neg_inf, func(inf, neg_inf)); + EXPECT_FP_EQ(neg_inf, func(neg_inf, 0.0)); + EXPECT_FP_EQ(neg_inf, func(-0.0, neg_inf)); + EXPECT_FP_EQ(neg_inf, func(neg_inf, T(-1.2345))); + EXPECT_FP_EQ(neg_inf, func(T(1.2345), neg_inf)); + } + + void testBothZero(FMinimumFunc func) { + EXPECT_FP_EQ(0.0, func(0.0, 0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, 0.0)); + EXPECT_FP_EQ(-0.0, func(0.0, -0.0)); + EXPECT_FP_EQ(-0.0, func(-0.0, -0.0)); + } + + void testRange(FMinimumFunc func) { + constexpr StorageType COUNT = 100'001; + constexpr StorageType STEP = STORAGE_MAX / COUNT; + for (StorageType i = 0, v = 0, w = STORAGE_MAX; i <= COUNT; + ++i, v += STEP, w -= STEP) { + FPBits xbits(v), ybits(w); + if (xbits.is_inf_or_nan()) + continue; + if (ybits.is_inf_or_nan()) + continue; + T x = xbits.get_val(); + T y = ybits.get_val(); + if ((x == 0) && (y == 0)) + continue; + + if (x > y) { + EXPECT_FP_EQ(y, func(x, y)); + } else { + EXPECT_FP_EQ(x, func(x, y)); + } + } + } +}; + +#define LIST_FMINIMUM_TESTS(T, func) \ + using LlvmLibcFMinimumTest = FMinimumTest<T>; \ + TEST_F(LlvmLibcFMinimumTest, NaN) { testNaN(&func); } \ + TEST_F(LlvmLibcFMinimumTest, InfArg) { testInfArg(&func); } \ + TEST_F(LlvmLibcFMinimumTest, NegInfArg) { testNegInfArg(&func); } \ + TEST_F(LlvmLibcFMinimumTest, BothZero) { testBothZero(&func); } \ + TEST_F(LlvmLibcFMinimumTest, Range) { testRange(&func); } + +#endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_FMINIMUMTEST_H diff --git a/libc/test/src/math/smoke/FModTest.h b/libc/test/src/math/smoke/FModTest.h index 2b1442923268d9cab6ec8f8cc033df81bf8c10b2..96ad299258a176bbfc87db5ee8419a16895dd782 100644 --- a/libc/test/src/math/smoke/FModTest.h +++ b/libc/test/src/math/smoke/FModTest.h @@ -14,7 +14,7 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" #define TEST_SPECIAL(x, y, expected, dom_err, expected_exception) \ EXPECT_FP_EQ(expected, f(x, y)); \ diff --git a/libc/test/src/math/smoke/FloorTest.h b/libc/test/src/math/smoke/FloorTest.h index 610f5c206ed3a07457a16cd4d774bcb751472f63..8886e8e7518368f38a1b085bc611d0aa02076218 100644 --- a/libc/test/src/math/smoke/FloorTest.h +++ b/libc/test/src/math/smoke/FloorTest.h @@ -12,7 +12,7 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" template <typename T> class FloorTest : public LIBC_NAMESPACE::testing::Test { diff --git a/libc/test/src/math/smoke/FmaTest.h b/libc/test/src/math/smoke/FmaTest.h index d04f648c2d7ddafd0d357079e086bd5b2d4dc94b..c66035927d9896599197d27a9e148000d9802dc7 100644 --- a/libc/test/src/math/smoke/FmaTest.h +++ b/libc/test/src/math/smoke/FmaTest.h @@ -19,7 +19,6 @@ private: using Func = T (*)(T, T, T); using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; using StorageType = typename FPBits::StorageType; - using Sign = LIBC_NAMESPACE::fputil::Sign; const T inf = FPBits::inf(Sign::POS).get_val(); const T neg_inf = FPBits::inf(Sign::NEG).get_val(); diff --git a/libc/test/src/math/smoke/FromfpTest.h b/libc/test/src/math/smoke/FromfpTest.h new file mode 100644 index 0000000000000000000000000000000000000000..d3a61baafda106c5a182168e003d3ce49415e8d6 --- /dev/null +++ b/libc/test/src/math/smoke/FromfpTest.h @@ -0,0 +1,528 @@ +//===-- Utility class to test different flavors of fromfp -------*- 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 LIBC_TEST_SRC_MATH_SMOKE_FROMFPTEST_H +#define LIBC_TEST_SRC_MATH_SMOKE_FROMFPTEST_H + +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +template <typename T> +class FromfpTestTemplate : public LIBC_NAMESPACE::testing::Test { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef T (*FromfpFunc)(T, int, unsigned int); + + void testSpecialNumbersNonzeroWidth(FromfpFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ(zero, func(zero, rnd, 32U)); + EXPECT_FP_EQ(neg_zero, func(neg_zero, rnd, 32U)); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(inf, rnd, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(neg_inf, rnd, 32U), FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(aNaN, rnd, 32U), FE_INVALID); + } + } + + void testSpecialNumbersZeroWidth(FromfpFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(zero, rnd, 0U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(neg_zero, rnd, 0U), FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(inf, rnd, 0U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(neg_inf, rnd, 0U), FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(aNaN, rnd, 0U), FE_INVALID); + } + } + + void testRoundedNumbersWithinRange(FromfpFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ(T(1.0), func(T(1.0), rnd, 2U)); + EXPECT_FP_EQ(T(-1.0), func(T(-1.0), rnd, 1U)); + EXPECT_FP_EQ(T(10.0), func(T(10.0), rnd, 5U)); + EXPECT_FP_EQ(T(-10.0), func(T(-10.0), rnd, 5U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.0), rnd, 12U)); + EXPECT_FP_EQ(T(-1234.0), func(T(-1234.0), rnd, 12U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.0), rnd, 65U)); + EXPECT_FP_EQ(T(-1234.0), func(T(-1234.0), rnd, 65U)); + } + } + + void testRoundedNumbersOutsideRange(FromfpFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.0), rnd, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.0), rnd, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.0), rnd, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.0), rnd, 11U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.0), rnd, 11U), FE_INVALID); + } + } + + void testFractionsUpwardWithinRange(FromfpFunc func) { + EXPECT_FP_EQ(T(1.0), func(T(0.5), FP_INT_UPWARD, 2U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.5), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(0.115), FP_INT_UPWARD, 2U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.115), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(0.715), FP_INT_UPWARD, 2U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.715), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(T(2.0), func(T(1.3), FP_INT_UPWARD, 3U)); + EXPECT_FP_EQ(T(-1.0), func(T(-1.3), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(T(2.0), func(T(1.5), FP_INT_UPWARD, 3U)); + EXPECT_FP_EQ(T(-1.0), func(T(-1.5), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(T(2.0), func(T(1.75), FP_INT_UPWARD, 3U)); + EXPECT_FP_EQ(T(-1.0), func(T(-1.75), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(T(11.0), func(T(10.32), FP_INT_UPWARD, 5U)); + EXPECT_FP_EQ(T(-10.0), func(T(-10.32), FP_INT_UPWARD, 5U)); + EXPECT_FP_EQ(T(11.0), func(T(10.65), FP_INT_UPWARD, 5U)); + EXPECT_FP_EQ(T(-10.0), func(T(-10.65), FP_INT_UPWARD, 5U)); + EXPECT_FP_EQ(T(1235.0), func(T(1234.38), FP_INT_UPWARD, 12U)); + EXPECT_FP_EQ(T(-1234.0), func(T(-1234.38), FP_INT_UPWARD, 12U)); + EXPECT_FP_EQ(T(1235.0), func(T(1234.96), FP_INT_UPWARD, 12U)); + EXPECT_FP_EQ(T(-1234.0), func(T(-1234.96), FP_INT_UPWARD, 12U)); + } + + void testFractionsUpwardOutsideRange(FromfpFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(0.5), FP_INT_UPWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(0.115), FP_INT_UPWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(0.715), FP_INT_UPWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.3), FP_INT_UPWARD, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.5), FP_INT_UPWARD, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.75), FP_INT_UPWARD, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.32), FP_INT_UPWARD, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.32), FP_INT_UPWARD, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.65), FP_INT_UPWARD, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.65), FP_INT_UPWARD, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.38), FP_INT_UPWARD, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.38), FP_INT_UPWARD, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.96), FP_INT_UPWARD, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.96), FP_INT_UPWARD, 11U), + FE_INVALID); + } + + void testFractionsDownwardWithinRange(FromfpFunc func) { + EXPECT_FP_EQ(T(0.0), func(T(0.5), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(T(-1.0), func(T(-0.5), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(T(0.0), func(T(0.115), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(T(-1.0), func(T(-0.115), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(T(0.0), func(T(0.715), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(T(-1.0), func(T(-0.715), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(1.3), FP_INT_DOWNWARD, 2U)); + EXPECT_FP_EQ(T(-2.0), func(T(-1.3), FP_INT_DOWNWARD, 2U)); + EXPECT_FP_EQ(T(1.0), func(T(1.5), FP_INT_DOWNWARD, 2U)); + EXPECT_FP_EQ(T(-2.0), func(T(-1.5), FP_INT_DOWNWARD, 2U)); + EXPECT_FP_EQ(T(1.0), func(T(1.75), FP_INT_DOWNWARD, 2U)); + EXPECT_FP_EQ(T(-2.0), func(T(-1.75), FP_INT_DOWNWARD, 2U)); + EXPECT_FP_EQ(T(10.0), func(T(10.32), FP_INT_DOWNWARD, 5U)); + EXPECT_FP_EQ(T(-11.0), func(T(-10.32), FP_INT_DOWNWARD, 5U)); + EXPECT_FP_EQ(T(10.0), func(T(10.65), FP_INT_DOWNWARD, 5U)); + EXPECT_FP_EQ(T(-11.0), func(T(-10.65), FP_INT_DOWNWARD, 5U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.38), FP_INT_DOWNWARD, 12U)); + EXPECT_FP_EQ(T(-1235.0), func(T(-1234.38), FP_INT_DOWNWARD, 12U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.96), FP_INT_DOWNWARD, 12U)); + EXPECT_FP_EQ(T(-1235.0), func(T(-1234.96), FP_INT_DOWNWARD, 12U)); + } + + void testFractionsDownwardOutsideRange(FromfpFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.3), FP_INT_DOWNWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.3), FP_INT_DOWNWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.5), FP_INT_DOWNWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.5), FP_INT_DOWNWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.75), FP_INT_DOWNWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.75), FP_INT_DOWNWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.32), FP_INT_DOWNWARD, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.32), FP_INT_DOWNWARD, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.65), FP_INT_DOWNWARD, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.65), FP_INT_DOWNWARD, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.38), FP_INT_DOWNWARD, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.38), FP_INT_DOWNWARD, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.96), FP_INT_DOWNWARD, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.96), FP_INT_DOWNWARD, 11U), + FE_INVALID); + } + + void testFractionsTowardZeroWithinRange(FromfpFunc func) { + EXPECT_FP_EQ(T(0.0), func(T(0.5), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.5), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(T(0.0), func(T(0.115), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.115), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(T(0.0), func(T(0.715), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.715), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(1.3), FP_INT_TOWARDZERO, 2U)); + EXPECT_FP_EQ(T(-1.0), func(T(-1.3), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(1.5), FP_INT_TOWARDZERO, 2U)); + EXPECT_FP_EQ(T(-1.0), func(T(-1.5), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(1.75), FP_INT_TOWARDZERO, 2U)); + EXPECT_FP_EQ(T(-1.0), func(T(-1.75), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(T(10.0), func(T(10.32), FP_INT_TOWARDZERO, 5U)); + EXPECT_FP_EQ(T(-10.0), func(T(-10.32), FP_INT_TOWARDZERO, 5U)); + EXPECT_FP_EQ(T(10.0), func(T(10.65), FP_INT_TOWARDZERO, 5U)); + EXPECT_FP_EQ(T(-10.0), func(T(-10.65), FP_INT_TOWARDZERO, 5U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.38), FP_INT_TOWARDZERO, 12U)); + EXPECT_FP_EQ(T(-1234.0), func(T(-1234.38), FP_INT_TOWARDZERO, 12U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.96), FP_INT_TOWARDZERO, 12U)); + EXPECT_FP_EQ(T(-1234.0), func(T(-1234.96), FP_INT_TOWARDZERO, 12U)); + } + + void testFractionsTowardZeroOutsideRange(FromfpFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.3), FP_INT_TOWARDZERO, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.5), FP_INT_TOWARDZERO, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.75), FP_INT_TOWARDZERO, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.32), FP_INT_TOWARDZERO, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.32), FP_INT_TOWARDZERO, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.65), FP_INT_TOWARDZERO, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.65), FP_INT_TOWARDZERO, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.38), FP_INT_TOWARDZERO, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.38), FP_INT_TOWARDZERO, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.96), FP_INT_TOWARDZERO, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.96), FP_INT_TOWARDZERO, 11U), + FE_INVALID); + } + + void testFractionsToNearestFromZeroWithinRange(FromfpFunc func) { + EXPECT_FP_EQ(T(1.0), func(T(0.5), FP_INT_TONEARESTFROMZERO, 2U)); + EXPECT_FP_EQ(T(-1.0), func(T(-0.5), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(T(0.0), func(T(0.115), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.115), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(0.715), FP_INT_TONEARESTFROMZERO, 2U)); + EXPECT_FP_EQ(T(-1.0), func(T(-0.715), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(1.3), FP_INT_TONEARESTFROMZERO, 2U)); + EXPECT_FP_EQ(T(-1.0), func(T(-1.3), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(T(2.0), func(T(1.5), FP_INT_TONEARESTFROMZERO, 3U)); + EXPECT_FP_EQ(T(-2.0), func(T(-1.5), FP_INT_TONEARESTFROMZERO, 2U)); + EXPECT_FP_EQ(T(2.0), func(T(1.75), FP_INT_TONEARESTFROMZERO, 3U)); + EXPECT_FP_EQ(T(-2.0), func(T(-1.75), FP_INT_TONEARESTFROMZERO, 2U)); + EXPECT_FP_EQ(T(10.0), func(T(10.32), FP_INT_TONEARESTFROMZERO, 5U)); + EXPECT_FP_EQ(T(-10.0), func(T(-10.32), FP_INT_TONEARESTFROMZERO, 5U)); + EXPECT_FP_EQ(T(11.0), func(T(10.65), FP_INT_TONEARESTFROMZERO, 5U)); + EXPECT_FP_EQ(T(-11.0), func(T(-10.65), FP_INT_TONEARESTFROMZERO, 5U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.38), FP_INT_TONEARESTFROMZERO, 12U)); + EXPECT_FP_EQ(T(-1234.0), func(T(-1234.38), FP_INT_TONEARESTFROMZERO, 12U)); + EXPECT_FP_EQ(T(1235.0), func(T(1234.96), FP_INT_TONEARESTFROMZERO, 12U)); + EXPECT_FP_EQ(T(-1235.0), func(T(-1234.96), FP_INT_TONEARESTFROMZERO, 12U)); + } + + void testFractionsToNearestFromZeroOutsideRange(FromfpFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(0.5), FP_INT_TONEARESTFROMZERO, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(0.715), FP_INT_TONEARESTFROMZERO, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.3), FP_INT_TONEARESTFROMZERO, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.5), FP_INT_TONEARESTFROMZERO, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.5), FP_INT_TONEARESTFROMZERO, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.75), FP_INT_TONEARESTFROMZERO, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.75), FP_INT_TONEARESTFROMZERO, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(10.32), FP_INT_TONEARESTFROMZERO, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-10.32), FP_INT_TONEARESTFROMZERO, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(10.65), FP_INT_TONEARESTFROMZERO, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-10.65), FP_INT_TONEARESTFROMZERO, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1234.38), FP_INT_TONEARESTFROMZERO, 11U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1234.38), FP_INT_TONEARESTFROMZERO, 11U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1234.96), FP_INT_TONEARESTFROMZERO, 11U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1234.96), FP_INT_TONEARESTFROMZERO, 11U), FE_INVALID); + } + + void testFractionsToNearestWithinRange(FromfpFunc func) { + EXPECT_FP_EQ(T(0.0), func(T(0.5), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.5), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(T(0.0), func(T(0.115), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.115), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(0.715), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(T(-1.0), func(T(-0.715), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(1.3), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(T(-1.0), func(T(-1.3), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(T(2.0), func(T(1.5), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(T(-2.0), func(T(-1.5), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(T(2.0), func(T(1.75), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(T(-2.0), func(T(-1.75), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(T(10.0), func(T(10.32), FP_INT_TONEAREST, 5U)); + EXPECT_FP_EQ(T(-10.0), func(T(-10.32), FP_INT_TONEAREST, 5U)); + EXPECT_FP_EQ(T(11.0), func(T(10.65), FP_INT_TONEAREST, 5U)); + EXPECT_FP_EQ(T(-11.0), func(T(-10.65), FP_INT_TONEAREST, 5U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.38), FP_INT_TONEAREST, 12U)); + EXPECT_FP_EQ(T(-1234.0), func(T(-1234.38), FP_INT_TONEAREST, 12U)); + EXPECT_FP_EQ(T(1235.0), func(T(1234.96), FP_INT_TONEAREST, 12U)); + EXPECT_FP_EQ(T(-1235.0), func(T(-1234.96), FP_INT_TONEAREST, 12U)); + + EXPECT_FP_EQ(T(2.0), func(T(2.3), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(T(-2.0), func(T(-2.3), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(T(2.0), func(T(2.5), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(T(-2.0), func(T(-2.5), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(T(3.0), func(T(2.75), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(T(-3.0), func(T(-2.75), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(T(5.0), func(T(5.3), FP_INT_TONEAREST, 4U)); + EXPECT_FP_EQ(T(-5.0), func(T(-5.3), FP_INT_TONEAREST, 4U)); + EXPECT_FP_EQ(T(6.0), func(T(5.5), FP_INT_TONEAREST, 4U)); + EXPECT_FP_EQ(T(-6.0), func(T(-5.5), FP_INT_TONEAREST, 4U)); + EXPECT_FP_EQ(T(6.0), func(T(5.75), FP_INT_TONEAREST, 4U)); + EXPECT_FP_EQ(T(-6.0), func(T(-5.75), FP_INT_TONEAREST, 4U)); + } + + void testFractionsToNearestOutsideRange(FromfpFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(0.715), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.3), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.5), FP_INT_TONEAREST, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.5), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.75), FP_INT_TONEAREST, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.75), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.32), FP_INT_TONEAREST, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.32), FP_INT_TONEAREST, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.65), FP_INT_TONEAREST, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.65), FP_INT_TONEAREST, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.38), FP_INT_TONEAREST, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.38), FP_INT_TONEAREST, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.96), FP_INT_TONEAREST, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.96), FP_INT_TONEAREST, 11U), + FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(2.3), FP_INT_TONEAREST, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-2.3), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(2.5), FP_INT_TONEAREST, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-2.5), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(2.75), FP_INT_TONEAREST, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-2.75), FP_INT_TONEAREST, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(5.3), FP_INT_TONEAREST, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-5.3), FP_INT_TONEAREST, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(5.5), FP_INT_TONEAREST, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-5.5), FP_INT_TONEAREST, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(5.75), FP_INT_TONEAREST, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-5.75), FP_INT_TONEAREST, 3U), + FE_INVALID); + } + + void testFractionsToNearestFallbackWithinRange(FromfpFunc func) { + EXPECT_FP_EQ(T(0.0), func(T(0.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(T(0.0), func(T(0.115), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.115), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(T(-1.0), func(T(-0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(T(-1.0), func(T(-1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(T(2.0), func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(T(-2.0), func(T(-1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(T(2.0), func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(T(-2.0), func(T(-1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(T(10.0), func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 5U)); + EXPECT_FP_EQ(T(-10.0), + func(T(-10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 5U)); + EXPECT_FP_EQ(T(11.0), func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 5U)); + EXPECT_FP_EQ(T(-11.0), + func(T(-10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 5U)); + EXPECT_FP_EQ(T(1234.0), + func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 12U)); + EXPECT_FP_EQ(T(-1234.0), + func(T(-1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 12U)); + EXPECT_FP_EQ(T(1235.0), + func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 12U)); + EXPECT_FP_EQ(T(-1235.0), + func(T(-1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 12U)); + + EXPECT_FP_EQ(T(2.0), func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(T(-2.0), func(T(-2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(T(2.0), func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(T(-2.0), func(T(-2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(T(3.0), func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(T(-3.0), func(T(-2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(T(5.0), func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U)); + EXPECT_FP_EQ(T(-5.0), func(T(-5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U)); + EXPECT_FP_EQ(T(6.0), func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U)); + EXPECT_FP_EQ(T(-6.0), func(T(-5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U)); + EXPECT_FP_EQ(T(6.0), func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U)); + EXPECT_FP_EQ(T(-6.0), func(T(-5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U)); + } + + void testFractionsToNearestFallbackOutsideRange(FromfpFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U), + FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INVALID); + } +}; + +#define LIST_FROMFP_TESTS(T, func) \ + using LlvmLibcFromfpTest = FromfpTestTemplate<T>; \ + TEST_F(LlvmLibcFromfpTest, SpecialNumbersNonzeroWidth) { \ + testSpecialNumbersNonzeroWidth(&func); \ + } \ + TEST_F(LlvmLibcFromfpTest, SpecialNumbersZeroWidth) { \ + testSpecialNumbersZeroWidth(&func); \ + } \ + TEST_F(LlvmLibcFromfpTest, RoundedNumbersWithinRange) { \ + testRoundedNumbersWithinRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpTest, RoundedNumbersOutsideRange) { \ + testRoundedNumbersOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpTest, FractionsUpwardWithinRange) { \ + testFractionsUpwardWithinRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpTest, FractionsUpwardOutsideRange) { \ + testFractionsUpwardOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpTest, FractionsDownwardWithinRange) { \ + testFractionsDownwardWithinRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpTest, FractionsDownwardOutsideRange) { \ + testFractionsDownwardOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpTest, FractionsTowardZeroWithinRange) { \ + testFractionsTowardZeroWithinRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpTest, FractionsTowardZeroOutsideRange) { \ + testFractionsTowardZeroOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpTest, FractionsToNearestFromZeroWithinRange) { \ + testFractionsToNearestFromZeroWithinRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpTest, FractionsToNearestFromZeroOutsideRange) { \ + testFractionsToNearestFromZeroOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpTest, FractionsToNearestWithinRange) { \ + testFractionsToNearestWithinRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpTest, FractionsToNearestOutsideRange) { \ + testFractionsToNearestOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpTest, FractionsToNearestFallbackWithinRange) { \ + testFractionsToNearestFallbackWithinRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpTest, FractionsToNearestFallbackOutsideRange) { \ + testFractionsToNearestFallbackOutsideRange(&func); \ + } + +#endif // LIBC_TEST_SRC_MATH_SMOKE_FROMFPTEST_H diff --git a/libc/test/src/math/smoke/FromfpxTest.h b/libc/test/src/math/smoke/FromfpxTest.h new file mode 100644 index 0000000000000000000000000000000000000000..f3a1680b05aafc15a565be2fecb55fba46a14255 --- /dev/null +++ b/libc/test/src/math/smoke/FromfpxTest.h @@ -0,0 +1,690 @@ +//===-- Utility class to test different flavors of fromfpx ------*- 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 LIBC_TEST_SRC_MATH_SMOKE_FROMFPXTEST_H +#define LIBC_TEST_SRC_MATH_SMOKE_FROMFPXTEST_H + +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +template <typename T> +class FromfpxTestTemplate : public LIBC_NAMESPACE::testing::Test { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef T (*FromfpxFunc)(T, int, unsigned int); + + void testSpecialNumbersNonzeroWidth(FromfpxFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ(zero, func(zero, rnd, 32U)); + EXPECT_FP_EQ(neg_zero, func(neg_zero, rnd, 32U)); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(inf, rnd, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(neg_inf, rnd, 32U), FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(aNaN, rnd, 32U), FE_INVALID); + } + } + + void testSpecialNumbersZeroWidth(FromfpxFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(zero, rnd, 0U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(neg_zero, rnd, 0U), FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(inf, rnd, 0U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(neg_inf, rnd, 0U), FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(aNaN, rnd, 0U), FE_INVALID); + } + } + + void testRoundedNumbersWithinRange(FromfpxFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ(T(1.0), func(T(1.0), rnd, 2U)); + EXPECT_FP_EQ(T(-1.0), func(T(-1.0), rnd, 1U)); + EXPECT_FP_EQ(T(10.0), func(T(10.0), rnd, 5U)); + EXPECT_FP_EQ(T(-10.0), func(T(-10.0), rnd, 5U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.0), rnd, 12U)); + EXPECT_FP_EQ(T(-1234.0), func(T(-1234.0), rnd, 12U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.0), rnd, 65U)); + EXPECT_FP_EQ(T(-1234.0), func(T(-1234.0), rnd, 65U)); + } + } + + void testRoundedNumbersOutsideRange(FromfpxFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.0), rnd, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.0), rnd, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.0), rnd, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.0), rnd, 11U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.0), rnd, 11U), FE_INVALID); + } + } + + void testFractionsUpwardWithinRange(FromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(0.5), FP_INT_UPWARD, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.5), FP_INT_UPWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(0.115), FP_INT_UPWARD, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.115), FP_INT_UPWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(0.715), FP_INT_UPWARD, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.715), FP_INT_UPWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.3), FP_INT_UPWARD, 3U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-1.3), FP_INT_UPWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.5), FP_INT_UPWARD, 3U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-1.5), FP_INT_UPWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.75), FP_INT_UPWARD, 3U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-1.75), FP_INT_UPWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(11.0), func(T(10.32), FP_INT_UPWARD, 5U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-10.0), func(T(-10.32), FP_INT_UPWARD, 5U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(11.0), func(T(10.65), FP_INT_UPWARD, 5U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-10.0), func(T(-10.65), FP_INT_UPWARD, 5U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1235.0), func(T(1234.38), FP_INT_UPWARD, 12U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-1234.0), func(T(-1234.38), FP_INT_UPWARD, 12U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1235.0), func(T(1234.96), FP_INT_UPWARD, 12U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-1234.0), func(T(-1234.96), FP_INT_UPWARD, 12U), FE_INEXACT); + } + + void testFractionsUpwardOutsideRange(FromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(0.5), FP_INT_UPWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(0.115), FP_INT_UPWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(0.715), FP_INT_UPWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.3), FP_INT_UPWARD, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.5), FP_INT_UPWARD, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.75), FP_INT_UPWARD, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.32), FP_INT_UPWARD, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.32), FP_INT_UPWARD, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.65), FP_INT_UPWARD, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.65), FP_INT_UPWARD, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.38), FP_INT_UPWARD, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.38), FP_INT_UPWARD, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.96), FP_INT_UPWARD, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.96), FP_INT_UPWARD, 11U), + FE_INVALID); + } + + void testFractionsDownwardWithinRange(FromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.5), FP_INT_DOWNWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-0.5), FP_INT_DOWNWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.115), FP_INT_DOWNWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-0.115), FP_INT_DOWNWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.715), FP_INT_DOWNWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-0.715), FP_INT_DOWNWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.3), FP_INT_DOWNWARD, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-2.0), func(T(-1.3), FP_INT_DOWNWARD, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.5), FP_INT_DOWNWARD, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-2.0), func(T(-1.5), FP_INT_DOWNWARD, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.75), FP_INT_DOWNWARD, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-2.0), func(T(-1.75), FP_INT_DOWNWARD, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.32), FP_INT_DOWNWARD, 5U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-11.0), func(T(-10.32), FP_INT_DOWNWARD, 5U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.65), FP_INT_DOWNWARD, 5U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-11.0), func(T(-10.65), FP_INT_DOWNWARD, 5U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1234.0), func(T(1234.38), FP_INT_DOWNWARD, 12U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-1235.0), func(T(-1234.38), FP_INT_DOWNWARD, 12U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1234.0), func(T(1234.96), FP_INT_DOWNWARD, 12U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-1235.0), func(T(-1234.96), FP_INT_DOWNWARD, 12U), FE_INEXACT); + } + + void testFractionsDownwardOutsideRange(FromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.3), FP_INT_DOWNWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.3), FP_INT_DOWNWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.5), FP_INT_DOWNWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.5), FP_INT_DOWNWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.75), FP_INT_DOWNWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.75), FP_INT_DOWNWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.32), FP_INT_DOWNWARD, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.32), FP_INT_DOWNWARD, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.65), FP_INT_DOWNWARD, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.65), FP_INT_DOWNWARD, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.38), FP_INT_DOWNWARD, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.38), FP_INT_DOWNWARD, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.96), FP_INT_DOWNWARD, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.96), FP_INT_DOWNWARD, 11U), + FE_INVALID); + } + + void testFractionsTowardZeroWithinRange(FromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.5), FP_INT_TOWARDZERO, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.5), FP_INT_TOWARDZERO, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.115), FP_INT_TOWARDZERO, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.115), FP_INT_TOWARDZERO, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.715), FP_INT_TOWARDZERO, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.715), FP_INT_TOWARDZERO, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.3), FP_INT_TOWARDZERO, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-1.3), FP_INT_TOWARDZERO, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.5), FP_INT_TOWARDZERO, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-1.5), FP_INT_TOWARDZERO, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.75), FP_INT_TOWARDZERO, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-1.75), FP_INT_TOWARDZERO, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.32), FP_INT_TOWARDZERO, 5U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-10.0), func(T(-10.32), FP_INT_TOWARDZERO, 5U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.65), FP_INT_TOWARDZERO, 5U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-10.0), func(T(-10.65), FP_INT_TOWARDZERO, 5U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1234.0), func(T(1234.38), FP_INT_TOWARDZERO, 12U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-1234.0), func(T(-1234.38), FP_INT_TOWARDZERO, 12U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1234.0), func(T(1234.96), FP_INT_TOWARDZERO, 12U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-1234.0), func(T(-1234.96), FP_INT_TOWARDZERO, 12U), FE_INEXACT); + } + + void testFractionsTowardZeroOutsideRange(FromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.3), FP_INT_TOWARDZERO, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.5), FP_INT_TOWARDZERO, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.75), FP_INT_TOWARDZERO, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.32), FP_INT_TOWARDZERO, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.32), FP_INT_TOWARDZERO, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.65), FP_INT_TOWARDZERO, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.65), FP_INT_TOWARDZERO, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.38), FP_INT_TOWARDZERO, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.38), FP_INT_TOWARDZERO, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.96), FP_INT_TOWARDZERO, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.96), FP_INT_TOWARDZERO, 11U), + FE_INVALID); + } + + void testFractionsToNearestFromZeroWithinRange(FromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1.0), func(T(0.5), FP_INT_TONEARESTFROMZERO, 2U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-1.0), func(T(-0.5), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(0.0), func(T(0.115), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-0.0), func(T(-0.115), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1.0), func(T(0.715), FP_INT_TONEARESTFROMZERO, 2U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-1.0), func(T(-0.715), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1.0), func(T(1.3), FP_INT_TONEARESTFROMZERO, 2U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-1.0), func(T(-1.3), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(2.0), func(T(1.5), FP_INT_TONEARESTFROMZERO, 3U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-2.0), func(T(-1.5), FP_INT_TONEARESTFROMZERO, 2U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(2.0), func(T(1.75), FP_INT_TONEARESTFROMZERO, 3U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-2.0), func(T(-1.75), FP_INT_TONEARESTFROMZERO, 2U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(10.0), func(T(10.32), FP_INT_TONEARESTFROMZERO, 5U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-10.0), func(T(-10.32), FP_INT_TONEARESTFROMZERO, 5U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(11.0), func(T(10.65), FP_INT_TONEARESTFROMZERO, 5U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-11.0), func(T(-10.65), FP_INT_TONEARESTFROMZERO, 5U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1234.0), func(T(1234.38), FP_INT_TONEARESTFROMZERO, 12U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-1234.0), func(T(-1234.38), FP_INT_TONEARESTFROMZERO, 12U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1235.0), func(T(1234.96), FP_INT_TONEARESTFROMZERO, 12U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-1235.0), func(T(-1234.96), FP_INT_TONEARESTFROMZERO, 12U), + FE_INEXACT); + } + + void testFractionsToNearestFromZeroOutsideRange(FromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(0.5), FP_INT_TONEARESTFROMZERO, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(0.715), FP_INT_TONEARESTFROMZERO, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.3), FP_INT_TONEARESTFROMZERO, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.5), FP_INT_TONEARESTFROMZERO, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.5), FP_INT_TONEARESTFROMZERO, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.75), FP_INT_TONEARESTFROMZERO, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.75), FP_INT_TONEARESTFROMZERO, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(10.32), FP_INT_TONEARESTFROMZERO, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-10.32), FP_INT_TONEARESTFROMZERO, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(10.65), FP_INT_TONEARESTFROMZERO, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-10.65), FP_INT_TONEARESTFROMZERO, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1234.38), FP_INT_TONEARESTFROMZERO, 11U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1234.38), FP_INT_TONEARESTFROMZERO, 11U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1234.96), FP_INT_TONEARESTFROMZERO, 11U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1234.96), FP_INT_TONEARESTFROMZERO, 11U), FE_INVALID); + } + + void testFractionsToNearestWithinRange(FromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.5), FP_INT_TONEAREST, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.5), FP_INT_TONEAREST, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.115), FP_INT_TONEAREST, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.115), FP_INT_TONEAREST, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(0.715), FP_INT_TONEAREST, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-0.715), FP_INT_TONEAREST, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.3), FP_INT_TONEAREST, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-1.0), func(T(-1.3), FP_INT_TONEAREST, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.5), FP_INT_TONEAREST, 3U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-2.0), func(T(-1.5), FP_INT_TONEAREST, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.75), FP_INT_TONEAREST, 3U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-2.0), func(T(-1.75), FP_INT_TONEAREST, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.32), FP_INT_TONEAREST, 5U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-10.0), func(T(-10.32), FP_INT_TONEAREST, 5U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(11.0), func(T(10.65), FP_INT_TONEAREST, 5U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-11.0), func(T(-10.65), FP_INT_TONEAREST, 5U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1234.0), func(T(1234.38), FP_INT_TONEAREST, 12U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-1234.0), func(T(-1234.38), FP_INT_TONEAREST, 12U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1235.0), func(T(1234.96), FP_INT_TONEAREST, 12U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-1235.0), func(T(-1234.96), FP_INT_TONEAREST, 12U), FE_INEXACT); + + EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(2.3), FP_INT_TONEAREST, 3U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-2.0), func(T(-2.3), FP_INT_TONEAREST, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(2.5), FP_INT_TONEAREST, 3U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-2.0), func(T(-2.5), FP_INT_TONEAREST, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(3.0), func(T(2.75), FP_INT_TONEAREST, 3U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-3.0), func(T(-2.75), FP_INT_TONEAREST, 3U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(5.0), func(T(5.3), FP_INT_TONEAREST, 4U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-5.0), func(T(-5.3), FP_INT_TONEAREST, 4U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(6.0), func(T(5.5), FP_INT_TONEAREST, 4U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-6.0), func(T(-5.5), FP_INT_TONEAREST, 4U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(6.0), func(T(5.75), FP_INT_TONEAREST, 4U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-6.0), func(T(-5.75), FP_INT_TONEAREST, 4U), + FE_INEXACT); + } + + void testFractionsToNearestOutsideRange(FromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(0.715), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.3), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.5), FP_INT_TONEAREST, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.5), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.75), FP_INT_TONEAREST, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.75), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.32), FP_INT_TONEAREST, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.32), FP_INT_TONEAREST, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.65), FP_INT_TONEAREST, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.65), FP_INT_TONEAREST, 4U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.38), FP_INT_TONEAREST, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.38), FP_INT_TONEAREST, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.96), FP_INT_TONEAREST, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.96), FP_INT_TONEAREST, 11U), + FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(2.3), FP_INT_TONEAREST, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-2.3), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(2.5), FP_INT_TONEAREST, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-2.5), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(2.75), FP_INT_TONEAREST, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-2.75), FP_INT_TONEAREST, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(5.3), FP_INT_TONEAREST, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-5.3), FP_INT_TONEAREST, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(5.5), FP_INT_TONEAREST, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-5.5), FP_INT_TONEAREST, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(5.75), FP_INT_TONEAREST, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-5.75), FP_INT_TONEAREST, 3U), + FE_INVALID); + } + + void testFractionsToNearestFallbackWithinRange(FromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION( + T(0.0), func(T(0.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-0.0), func(T(-0.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(0.0), func(T(0.115), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-0.0), func(T(-0.115), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1.0), func(T(0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-1.0), func(T(-0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1.0), func(T(1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-1.0), func(T(-1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(2.0), func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-2.0), func(T(-1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(2.0), func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-2.0), func(T(-1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(10.0), func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 5U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-10.0), func(T(-10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 5U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(11.0), func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 5U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-11.0), func(T(-10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 5U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1234.0), func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 12U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-1234.0), func(T(-1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 12U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1235.0), func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 12U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-1235.0), func(T(-1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 12U), + FE_INEXACT); + + EXPECT_FP_EQ_WITH_EXCEPTION( + T(2.0), func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-2.0), func(T(-2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(2.0), func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-2.0), func(T(-2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(3.0), func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-3.0), func(T(-2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(5.0), func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-5.0), func(T(-5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(6.0), func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-6.0), func(T(-5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(6.0), func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-6.0), func(T(-5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), + FE_INEXACT); + } + + void testFractionsToNearestFallbackOutsideRange(FromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U), + FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INVALID); + } +}; + +#define LIST_FROMFPX_TESTS(T, func) \ + using LlvmLibcFromfpxTest = FromfpxTestTemplate<T>; \ + TEST_F(LlvmLibcFromfpxTest, SpecialNumbersNonzeroWidth) { \ + testSpecialNumbersNonzeroWidth(&func); \ + } \ + TEST_F(LlvmLibcFromfpxTest, SpecialNumbersZeroWidth) { \ + testSpecialNumbersZeroWidth(&func); \ + } \ + TEST_F(LlvmLibcFromfpxTest, RoundedNumbersWithinRange) { \ + testRoundedNumbersWithinRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpxTest, RoundedNumbersOutsideRange) { \ + testRoundedNumbersOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpxTest, FractionsUpwardWithinRange) { \ + testFractionsUpwardWithinRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpxTest, FractionsUpwardOutsideRange) { \ + testFractionsUpwardOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpxTest, FractionsDownwardWithinRange) { \ + testFractionsDownwardWithinRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpxTest, FractionsDownwardOutsideRange) { \ + testFractionsDownwardOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpxTest, FractionsTowardZeroWithinRange) { \ + testFractionsTowardZeroWithinRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpxTest, FractionsTowardZeroOutsideRange) { \ + testFractionsTowardZeroOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpxTest, FractionsToNearestFromZeroWithinRange) { \ + testFractionsToNearestFromZeroWithinRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpxTest, FractionsToNearestFromZeroOutsideRange) { \ + testFractionsToNearestFromZeroOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpxTest, FractionsToNearestWithinRange) { \ + testFractionsToNearestWithinRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpxTest, FractionsToNearestOutsideRange) { \ + testFractionsToNearestOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpxTest, FractionsToNearestFallbackWithinRange) { \ + testFractionsToNearestFallbackWithinRange(&func); \ + } \ + TEST_F(LlvmLibcFromfpxTest, FractionsToNearestFallbackOutsideRange) { \ + testFractionsToNearestFallbackOutsideRange(&func); \ + } + +#endif // LIBC_TEST_SRC_MATH_SMOKE_FROMFPXTEST_H diff --git a/libc/test/src/math/smoke/HypotTest.h b/libc/test/src/math/smoke/HypotTest.h index 619879188a3b31d89720b887bdfb50efd435c874..80816033f28fe89b35a2e6d6361b5c5d84ad232f 100644 --- a/libc/test/src/math/smoke/HypotTest.h +++ b/libc/test/src/math/smoke/HypotTest.h @@ -13,7 +13,7 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" template <typename T> class HypotTestTemplate : public LIBC_NAMESPACE::testing::Test { @@ -21,7 +21,7 @@ private: using Func = T (*)(T, T); using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; using StorageType = typename FPBits::StorageType; - using Sign = LIBC_NAMESPACE::fputil::Sign; + const T nan = FPBits::quiet_nan().get_val(); const T inf = FPBits::inf(Sign::POS).get_val(); const T neg_inf = FPBits::inf(Sign::NEG).get_val(); diff --git a/libc/test/src/math/smoke/ILogbTest.h b/libc/test/src/math/smoke/ILogbTest.h index cbee25b139d488bda687df59132cf8289628c10c..bb5bc33b6b3a6dba27a31cedbcba5c0c6ee765d8 100644 --- a/libc/test/src/math/smoke/ILogbTest.h +++ b/libc/test/src/math/smoke/ILogbTest.h @@ -18,7 +18,6 @@ template <typename OutType, typename InType> class LlvmLibcILogbTest : public LIBC_NAMESPACE::testing::Test { using FPBits = LIBC_NAMESPACE::fputil::FPBits<InType>; using StorageType = typename FPBits::StorageType; - using Sign = LIBC_NAMESPACE::fputil::Sign; public: typedef OutType (*Func)(InType); diff --git a/libc/test/src/math/smoke/LdExpTest.h b/libc/test/src/math/smoke/LdExpTest.h index 7d17071f5b309c473c7266c2ab3c1249addcf14a..c3e852a2a473b1cca6c50aa7769e6c187733e06f 100644 --- a/libc/test/src/math/smoke/LdExpTest.h +++ b/libc/test/src/math/smoke/LdExpTest.h @@ -22,7 +22,6 @@ class LdExpTestTemplate : public LIBC_NAMESPACE::testing::Test { using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; using NormalFloat = LIBC_NAMESPACE::fputil::NormalFloat<T>; using StorageType = typename FPBits::StorageType; - using Sign = LIBC_NAMESPACE::fputil::Sign; const T inf = FPBits::inf(Sign::POS).get_val(); const T neg_inf = FPBits::inf(Sign::NEG).get_val(); diff --git a/libc/test/src/math/smoke/ModfTest.h b/libc/test/src/math/smoke/ModfTest.h index d7e15a7ed68206cba0c0cc347ee2002d9dd8a205..107963665b8357e5eb21d39323881d2931c41fbc 100644 --- a/libc/test/src/math/smoke/ModfTest.h +++ b/libc/test/src/math/smoke/ModfTest.h @@ -11,7 +11,7 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" template <typename T> class ModfTest : public LIBC_NAMESPACE::testing::Test { diff --git a/libc/test/src/math/smoke/NextAfterTest.h b/libc/test/src/math/smoke/NextAfterTest.h index dda86eeeb6e03c35f04986750de032bb8a1f30d4..403ea6bd8df68ade666454cfbf1805b19278b1d5 100644 --- a/libc/test/src/math/smoke/NextAfterTest.h +++ b/libc/test/src/math/smoke/NextAfterTest.h @@ -9,13 +9,13 @@ #ifndef LLVM_LIBC_TEST_SRC_MATH_NEXTAFTERTEST_H #define LLVM_LIBC_TEST_SRC_MATH_NEXTAFTERTEST_H +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/CPP/bit.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/FPUtil/BasicOperations.h" #include "src/__support/FPUtil/FPBits.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #define ASSERT_FP_EQ_WITH_EXCEPTION(result, expected, expected_exception) \ ASSERT_FP_EQ(result, expected); \ @@ -32,7 +32,6 @@ template <typename T> class NextAfterTestTemplate : public LIBC_NAMESPACE::testing::Test { using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; using StorageType = typename FPBits::StorageType; - using Sign = LIBC_NAMESPACE::fputil::Sign; const T inf = FPBits::inf(Sign::POS).get_val(); const T neg_inf = FPBits::inf(Sign::NEG).get_val(); diff --git a/libc/test/src/math/smoke/NextDownTest.h b/libc/test/src/math/smoke/NextDownTest.h new file mode 100644 index 0000000000000000000000000000000000000000..c678ab1db1deff75b73c9668e542c0888fe95375 --- /dev/null +++ b/libc/test/src/math/smoke/NextDownTest.h @@ -0,0 +1,43 @@ +//===-- Utility class to test different flavors of nextdown -----*- 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_TEST_SRC_MATH_NEXTDOWNTEST_H +#define LLVM_LIBC_TEST_SRC_MATH_NEXTDOWNTEST_H + +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +template <typename T> +class NextDownTestTemplate : public LIBC_NAMESPACE::testing::Test { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef T (*NextDownFunc)(T); + + void testNaN(NextDownFunc func) { ASSERT_FP_EQ(func(aNaN), aNaN); } + + void testBoundaries(NextDownFunc func) { + ASSERT_FP_EQ(zero, func(min_denormal)); + + ASSERT_FP_EQ(neg_min_denormal, func(zero)); + ASSERT_FP_EQ(neg_min_denormal, func(neg_zero)); + + ASSERT_FP_EQ(neg_max_normal, func(neg_max_normal)); + ASSERT_FP_EQ(neg_inf, func(neg_inf)); + + ASSERT_FP_EQ(max_normal, func(inf)); + } +}; + +#define LIST_NEXTDOWN_TESTS(T, func) \ + using LlvmLibcNextDownTest = NextDownTestTemplate<T>; \ + TEST_F(LlvmLibcNextDownTest, TestNaN) { testNaN(&func); } \ + TEST_F(LlvmLibcNextDownTest, TestBoundaries) { testBoundaries(&func); } + +#endif // LLVM_LIBC_TEST_SRC_MATH_NEXTDOWNTEST_H diff --git a/libc/test/src/math/smoke/NextTowardTest.h b/libc/test/src/math/smoke/NextTowardTest.h index 42a9a56aeb0a729d391bdd3c3d16dedada2a3163..0c2abf815c23904613b0a4f7dd90a2bc7958b101 100644 --- a/libc/test/src/math/smoke/NextTowardTest.h +++ b/libc/test/src/math/smoke/NextTowardTest.h @@ -9,6 +9,7 @@ #ifndef LLVM_LIBC_TEST_SRC_MATH_NEXTTOWARDTEST_H #define LLVM_LIBC_TEST_SRC_MATH_NEXTTOWARDTEST_H +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/CPP/bit.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/FPUtil/BasicOperations.h" @@ -16,7 +17,6 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include <fenv.h> -#include <math.h> #define ASSERT_FP_EQ_WITH_EXCEPTION(result, expected, expected_exception) \ ASSERT_FP_EQ(result, expected); \ @@ -34,7 +34,6 @@ class NextTowardTestTemplate : public LIBC_NAMESPACE::testing::Test { using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; using ToFPBits = LIBC_NAMESPACE::fputil::FPBits<long double>; using StorageType = typename FPBits::StorageType; - using Sign = LIBC_NAMESPACE::fputil::Sign; const T inf = FPBits::inf(Sign::POS).get_val(); const T neg_inf = FPBits::inf(Sign::NEG).get_val(); diff --git a/libc/test/src/math/smoke/NextUpTest.h b/libc/test/src/math/smoke/NextUpTest.h new file mode 100644 index 0000000000000000000000000000000000000000..ebbdb5c73def9e3e1fc1471740cfcaef31b5d093 --- /dev/null +++ b/libc/test/src/math/smoke/NextUpTest.h @@ -0,0 +1,43 @@ +//===-- Utility class to test different flavors of nextup -------*- 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_TEST_SRC_MATH_NEXTUPTEST_H +#define LLVM_LIBC_TEST_SRC_MATH_NEXTUPTEST_H + +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +template <typename T> +class NextUpTestTemplate : public LIBC_NAMESPACE::testing::Test { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef T (*NextUpFunc)(T); + + void testNaN(NextUpFunc func) { ASSERT_FP_EQ(func(aNaN), aNaN); } + + void testBoundaries(NextUpFunc func) { + ASSERT_FP_EQ(neg_zero, func(neg_min_denormal)); + + ASSERT_FP_EQ(min_denormal, func(zero)); + ASSERT_FP_EQ(min_denormal, func(neg_zero)); + + ASSERT_FP_EQ(max_normal, func(max_normal)); + ASSERT_FP_EQ(inf, func(inf)); + + ASSERT_FP_EQ(neg_max_normal, func(neg_inf)); + } +}; + +#define LIST_NEXTUP_TESTS(T, func) \ + using LlvmLibcNextUpTest = NextUpTestTemplate<T>; \ + TEST_F(LlvmLibcNextUpTest, TestNaN) { testNaN(&func); } \ + TEST_F(LlvmLibcNextUpTest, TestBoundaries) { testBoundaries(&func); } + +#endif // LLVM_LIBC_TEST_SRC_MATH_NEXTUPTEST_H diff --git a/libc/test/src/math/smoke/RIntTest.h b/libc/test/src/math/smoke/RIntTest.h index 4c90dffa39cb1515c2505d7d92440f5c1203eb83..5a283a8bc0b531c8bc4d37498f10b7bce0f59ec0 100644 --- a/libc/test/src/math/smoke/RIntTest.h +++ b/libc/test/src/math/smoke/RIntTest.h @@ -14,8 +14,8 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" +#include "include/llvm-libc-macros/math-macros.h" #include <fenv.h> -#include <math.h> #include <stdio.h> static constexpr int ROUNDING_MODES[4] = {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO, @@ -29,7 +29,6 @@ public: private: using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; using StorageType = typename FPBits::StorageType; - using Sign = LIBC_NAMESPACE::fputil::Sign; const T inf = FPBits::inf(Sign::POS).get_val(); const T neg_inf = FPBits::inf(Sign::NEG).get_val(); diff --git a/libc/test/src/math/smoke/RemQuoTest.h b/libc/test/src/math/smoke/RemQuoTest.h index 87551faeda9cf1ea9b4f97b5bdad44bbe1e43783..cf56b1d6460fe527792690544545300e089d03b2 100644 --- a/libc/test/src/math/smoke/RemQuoTest.h +++ b/libc/test/src/math/smoke/RemQuoTest.h @@ -9,17 +9,16 @@ #ifndef LLVM_LIBC_TEST_SRC_MATH_REMQUOTEST_H #define LLVM_LIBC_TEST_SRC_MATH_REMQUOTEST_H +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/BasicOperations.h" #include "src/__support/FPUtil/FPBits.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> template <typename T> class RemQuoTestTemplate : public LIBC_NAMESPACE::testing::Test { using FPBits = LIBC_NAMESPACE::fputil::FPBits<T>; using StorageType = typename FPBits::StorageType; - using Sign = LIBC_NAMESPACE::fputil::Sign; const T inf = FPBits::inf(Sign::POS).get_val(); const T neg_inf = FPBits::inf(Sign::NEG).get_val(); diff --git a/libc/test/src/math/smoke/RoundTest.h b/libc/test/src/math/smoke/RoundTest.h index d2a5906b1e29ead0f221450ca7c8ca4d3d0b6b88..8cf96f4569034abaf2f6868156ddb9fcf40a9208 100644 --- a/libc/test/src/math/smoke/RoundTest.h +++ b/libc/test/src/math/smoke/RoundTest.h @@ -12,7 +12,7 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" template <typename T> class RoundTest : public LIBC_NAMESPACE::testing::Test { diff --git a/libc/test/src/math/smoke/RoundToIntegerTest.h b/libc/test/src/math/smoke/RoundToIntegerTest.h index e86533ca09e1783e71f0e01d27485264db74af84..44b3f8996df5aaa83334b21b4c599ccfe1f4e76a 100644 --- a/libc/test/src/math/smoke/RoundToIntegerTest.h +++ b/libc/test/src/math/smoke/RoundToIntegerTest.h @@ -14,8 +14,8 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" +#include "include/llvm-libc-macros/math-macros.h" #include <errno.h> -#include <math.h> static constexpr int ROUNDING_MODES[4] = {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO, FE_TONEAREST}; @@ -28,7 +28,6 @@ public: private: using FPBits = LIBC_NAMESPACE::fputil::FPBits<F>; using StorageType = typename FPBits::StorageType; - using Sign = LIBC_NAMESPACE::fputil::Sign; const F zero = FPBits::zero(Sign::POS).get_val(); const F neg_zero = FPBits::zero(Sign::NEG).get_val(); diff --git a/libc/test/src/math/smoke/SqrtTest.h b/libc/test/src/math/smoke/SqrtTest.h index edb6e74236e3163d29902e5a79c91b2e5407ac2b..eea5dc1534e0bb8bbfc61b8023a096540c23f00f 100644 --- a/libc/test/src/math/smoke/SqrtTest.h +++ b/libc/test/src/math/smoke/SqrtTest.h @@ -10,7 +10,7 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" template <typename T> class SqrtTest : public LIBC_NAMESPACE::testing::Test { diff --git a/libc/test/src/math/smoke/TruncTest.h b/libc/test/src/math/smoke/TruncTest.h index 71b1ab9df3f08bdd82a19bb1a9ea7e228ea01a87..5612d27fef21d8a38e71c7e9d1ea29e8c189c416 100644 --- a/libc/test/src/math/smoke/TruncTest.h +++ b/libc/test/src/math/smoke/TruncTest.h @@ -12,7 +12,7 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" template <typename T> class TruncTest : public LIBC_NAMESPACE::testing::Test { diff --git a/libc/test/src/math/smoke/UfromfpTest.h b/libc/test/src/math/smoke/UfromfpTest.h new file mode 100644 index 0000000000000000000000000000000000000000..9ad1e6dce945967bc37d3d032522f9d4bf35351c --- /dev/null +++ b/libc/test/src/math/smoke/UfromfpTest.h @@ -0,0 +1,462 @@ +//===-- Utility class to test different flavors of ufromfp ------*- 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 LIBC_TEST_SRC_MATH_SMOKE_UFROMFPTEST_H +#define LIBC_TEST_SRC_MATH_SMOKE_UFROMFPTEST_H + +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +template <typename T> +class UfromfpTestTemplate : public LIBC_NAMESPACE::testing::Test { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef T (*UfromfpFunc)(T, int, unsigned int); + + void testSpecialNumbersNonzeroWidth(UfromfpFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ(zero, func(zero, rnd, 32U)); + EXPECT_FP_EQ(neg_zero, func(neg_zero, rnd, 32U)); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(inf, rnd, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(neg_inf, rnd, 32U), FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(aNaN, rnd, 32U), FE_INVALID); + } + } + + void testSpecialNumbersZeroWidth(UfromfpFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(zero, rnd, 0U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(neg_zero, rnd, 0U), FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(inf, rnd, 0U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(neg_inf, rnd, 0U), FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(aNaN, rnd, 0U), FE_INVALID); + } + } + + void testRoundedNumbersWithinRange(UfromfpFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ(T(1.0), func(T(1.0), rnd, 1U)); + EXPECT_FP_EQ(T(10.0), func(T(10.0), rnd, 4U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.0), rnd, 11U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.0), rnd, 64U)); + } + } + + void testRoundedNumbersOutsideRange(UfromfpFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.0), rnd, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.0), rnd, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.0), rnd, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.0), rnd, 10U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.0), rnd, 32U), FE_INVALID); + } + } + + void testFractionsUpwardWithinRange(UfromfpFunc func) { + EXPECT_FP_EQ(T(1.0), func(T(0.5), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.5), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(0.115), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.115), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(0.715), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.715), FP_INT_UPWARD, 1U)); + EXPECT_FP_EQ(T(2.0), func(T(1.3), FP_INT_UPWARD, 2U)); + EXPECT_FP_EQ(T(2.0), func(T(1.5), FP_INT_UPWARD, 2U)); + EXPECT_FP_EQ(T(2.0), func(T(1.75), FP_INT_UPWARD, 2U)); + EXPECT_FP_EQ(T(11.0), func(T(10.32), FP_INT_UPWARD, 4U)); + EXPECT_FP_EQ(T(11.0), func(T(10.65), FP_INT_UPWARD, 4U)); + EXPECT_FP_EQ(T(1235.0), func(T(1234.38), FP_INT_UPWARD, 11U)); + EXPECT_FP_EQ(T(1235.0), func(T(1234.96), FP_INT_UPWARD, 11U)); + } + + void testFractionsUpwardOutsideRange(UfromfpFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.3), FP_INT_UPWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.3), FP_INT_UPWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.5), FP_INT_UPWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.5), FP_INT_UPWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.75), FP_INT_UPWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.75), FP_INT_UPWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.32), FP_INT_UPWARD, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.32), FP_INT_UPWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.65), FP_INT_UPWARD, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.65), FP_INT_UPWARD, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.38), FP_INT_UPWARD, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.38), FP_INT_UPWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.96), FP_INT_UPWARD, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.96), FP_INT_UPWARD, 32U), + FE_INVALID); + } + + void testFractionsDownwardWithinRange(UfromfpFunc func) { + EXPECT_FP_EQ(T(0.0), func(T(0.5), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(T(0.0), func(T(0.115), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(T(0.0), func(T(0.715), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(1.3), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(1.5), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(1.75), FP_INT_DOWNWARD, 1U)); + EXPECT_FP_EQ(T(10.0), func(T(10.32), FP_INT_DOWNWARD, 4U)); + EXPECT_FP_EQ(T(10.0), func(T(10.65), FP_INT_DOWNWARD, 4U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.38), FP_INT_DOWNWARD, 11U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.96), FP_INT_DOWNWARD, 11U)); + } + + void testFractionsDownwardOutsideRange(UfromfpFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-0.5), FP_INT_DOWNWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-0.115), FP_INT_DOWNWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-0.715), FP_INT_DOWNWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.3), FP_INT_DOWNWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.5), FP_INT_DOWNWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.75), FP_INT_DOWNWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.32), FP_INT_DOWNWARD, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.32), FP_INT_DOWNWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.65), FP_INT_DOWNWARD, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.65), FP_INT_DOWNWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.38), FP_INT_DOWNWARD, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.38), FP_INT_DOWNWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.96), FP_INT_DOWNWARD, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.96), FP_INT_DOWNWARD, 32U), + FE_INVALID); + } + + void testFractionsTowardZeroWithinRange(UfromfpFunc func) { + EXPECT_FP_EQ(T(0.0), func(T(0.5), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.5), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(T(0.0), func(T(0.115), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.115), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(T(0.0), func(T(0.715), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.715), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(1.3), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(1.5), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(1.75), FP_INT_TOWARDZERO, 1U)); + EXPECT_FP_EQ(T(10.0), func(T(10.32), FP_INT_TOWARDZERO, 4U)); + EXPECT_FP_EQ(T(10.0), func(T(10.65), FP_INT_TOWARDZERO, 4U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.38), FP_INT_TOWARDZERO, 11U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.96), FP_INT_TOWARDZERO, 11U)); + } + + void testFractionsTowardZeroOutsideRange(UfromfpFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.3), FP_INT_TOWARDZERO, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.5), FP_INT_TOWARDZERO, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.75), FP_INT_TOWARDZERO, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.32), FP_INT_TOWARDZERO, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.32), FP_INT_TOWARDZERO, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.65), FP_INT_TOWARDZERO, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.65), FP_INT_TOWARDZERO, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.38), FP_INT_TOWARDZERO, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.38), FP_INT_TOWARDZERO, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.96), FP_INT_TOWARDZERO, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.96), FP_INT_TOWARDZERO, 32U), + FE_INVALID); + } + + void testFractionsToNearestFromZeroWithinRange(UfromfpFunc func) { + EXPECT_FP_EQ(T(1.0), func(T(0.5), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(T(0.0), func(T(0.115), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.115), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(0.715), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(1.3), FP_INT_TONEARESTFROMZERO, 1U)); + EXPECT_FP_EQ(T(2.0), func(T(1.5), FP_INT_TONEARESTFROMZERO, 2U)); + EXPECT_FP_EQ(T(2.0), func(T(1.75), FP_INT_TONEARESTFROMZERO, 2U)); + EXPECT_FP_EQ(T(10.0), func(T(10.32), FP_INT_TONEARESTFROMZERO, 4U)); + EXPECT_FP_EQ(T(11.0), func(T(10.65), FP_INT_TONEARESTFROMZERO, 4U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.38), FP_INT_TONEARESTFROMZERO, 11U)); + EXPECT_FP_EQ(T(1235.0), func(T(1234.96), FP_INT_TONEARESTFROMZERO, 11U)); + } + + void testFractionsToNearestFromZeroOutsideRange(UfromfpFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-0.5), FP_INT_TONEARESTFROMZERO, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-0.715), FP_INT_TONEARESTFROMZERO, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.3), FP_INT_TONEARESTFROMZERO, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.5), FP_INT_TONEARESTFROMZERO, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.5), FP_INT_TONEARESTFROMZERO, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.75), FP_INT_TONEARESTFROMZERO, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.75), FP_INT_TONEARESTFROMZERO, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(10.32), FP_INT_TONEARESTFROMZERO, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-10.32), FP_INT_TONEARESTFROMZERO, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(10.65), FP_INT_TONEARESTFROMZERO, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-10.65), FP_INT_TONEARESTFROMZERO, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1234.38), FP_INT_TONEARESTFROMZERO, 10U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1234.38), FP_INT_TONEARESTFROMZERO, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1234.96), FP_INT_TONEARESTFROMZERO, 10U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1234.96), FP_INT_TONEARESTFROMZERO, 32U), FE_INVALID); + } + + void testFractionsToNearestWithinRange(UfromfpFunc func) { + EXPECT_FP_EQ(T(0.0), func(T(0.5), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.5), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(T(0.0), func(T(0.115), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.115), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(0.715), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(1.3), FP_INT_TONEAREST, 1U)); + EXPECT_FP_EQ(T(2.0), func(T(1.5), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(T(2.0), func(T(1.75), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(T(10.0), func(T(10.32), FP_INT_TONEAREST, 4U)); + EXPECT_FP_EQ(T(11.0), func(T(10.65), FP_INT_TONEAREST, 4U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.38), FP_INT_TONEAREST, 11U)); + EXPECT_FP_EQ(T(1235.0), func(T(1234.96), FP_INT_TONEAREST, 11U)); + + EXPECT_FP_EQ(T(2.0), func(T(2.3), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(T(2.0), func(T(2.5), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(T(3.0), func(T(2.75), FP_INT_TONEAREST, 2U)); + EXPECT_FP_EQ(T(5.0), func(T(5.3), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(T(6.0), func(T(5.5), FP_INT_TONEAREST, 3U)); + EXPECT_FP_EQ(T(6.0), func(T(5.75), FP_INT_TONEAREST, 3U)); + } + + void testFractionsToNearestOutsideRange(UfromfpFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-0.715), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.3), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.5), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.5), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.75), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.75), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.32), FP_INT_TONEAREST, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.32), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.65), FP_INT_TONEAREST, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.65), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.38), FP_INT_TONEAREST, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.38), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.96), FP_INT_TONEAREST, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.96), FP_INT_TONEAREST, 32U), + FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(2.3), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-2.3), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(2.5), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-2.5), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(2.75), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-2.75), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(5.3), FP_INT_TONEAREST, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-5.3), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(5.5), FP_INT_TONEAREST, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-5.5), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(5.75), FP_INT_TONEAREST, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-5.75), FP_INT_TONEAREST, 32U), + FE_INVALID); + } + + void testFractionsToNearestFallbackWithinRange(UfromfpFunc func) { + EXPECT_FP_EQ(T(0.0), func(T(0.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(T(0.0), func(T(0.115), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(T(-0.0), func(T(-0.115), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(T(1.0), func(T(1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U)); + EXPECT_FP_EQ(T(2.0), func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(T(2.0), func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(T(10.0), func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U)); + EXPECT_FP_EQ(T(11.0), func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U)); + EXPECT_FP_EQ(T(1234.0), + func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U)); + EXPECT_FP_EQ(T(1235.0), + func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U)); + + EXPECT_FP_EQ(T(2.0), func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(T(2.0), func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(T(3.0), func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U)); + EXPECT_FP_EQ(T(5.0), func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(T(6.0), func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + EXPECT_FP_EQ(T(6.0), func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U)); + } + + void testFractionsToNearestFallbackOutsideRange(UfromfpFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), + FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), FE_INVALID); + } +}; + +#define LIST_UFROMFP_TESTS(T, func) \ + using LlvmLibcUfromfpTest = UfromfpTestTemplate<T>; \ + TEST_F(LlvmLibcUfromfpTest, SpecialNumbersNonzeroWidth) { \ + testSpecialNumbersNonzeroWidth(&func); \ + } \ + TEST_F(LlvmLibcUfromfpTest, SpecialNumbersZeroWidth) { \ + testSpecialNumbersZeroWidth(&func); \ + } \ + TEST_F(LlvmLibcUfromfpTest, RoundedNumbersWithinRange) { \ + testRoundedNumbersWithinRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpTest, RoundedNumbersOutsideRange) { \ + testRoundedNumbersOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpTest, FractionsUpwardWithinRange) { \ + testFractionsUpwardWithinRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpTest, FractionsUpwardOutsideRange) { \ + testFractionsUpwardOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpTest, FractionsDownwardWithinRange) { \ + testFractionsDownwardWithinRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpTest, FractionsDownwardOutsideRange) { \ + testFractionsDownwardOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpTest, FractionsTowardZeroWithinRange) { \ + testFractionsTowardZeroWithinRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpTest, FractionsTowardZeroOutsideRange) { \ + testFractionsTowardZeroOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpTest, FractionsToNearestFromZeroWithinRange) { \ + testFractionsToNearestFromZeroWithinRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpTest, FractionsToNearestFromZeroOutsideRange) { \ + testFractionsToNearestFromZeroOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpTest, FractionsToNearestWithinRange) { \ + testFractionsToNearestWithinRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpTest, FractionsToNearestOutsideRange) { \ + testFractionsToNearestOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpTest, FractionsToNearestFallbackWithinRange) { \ + testFractionsToNearestFallbackWithinRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpTest, FractionsToNearestFallbackOutsideRange) { \ + testFractionsToNearestFallbackOutsideRange(&func); \ + } + +#endif // LIBC_TEST_SRC_MATH_SMOKE_UFROMFPTEST_H diff --git a/libc/test/src/math/smoke/UfromfpxTest.h b/libc/test/src/math/smoke/UfromfpxTest.h new file mode 100644 index 0000000000000000000000000000000000000000..09163b8adfa5c0523dc4dbaddd1341396b4f0c44 --- /dev/null +++ b/libc/test/src/math/smoke/UfromfpxTest.h @@ -0,0 +1,551 @@ +//===-- Utility class to test different flavors of ufromfpx -----*- 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 LIBC_TEST_SRC_MATH_SMOKE_UFROMFPXTEST_H +#define LIBC_TEST_SRC_MATH_SMOKE_UFROMFPXTEST_H + +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +template <typename T> +class UfromfpxTestTemplate : public LIBC_NAMESPACE::testing::Test { + + DECLARE_SPECIAL_CONSTANTS(T) + +public: + typedef T (*UfromfpxFunc)(T, int, unsigned int); + + void testSpecialNumbersNonzeroWidth(UfromfpxFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ(zero, func(zero, rnd, 32U)); + EXPECT_FP_EQ(neg_zero, func(neg_zero, rnd, 32U)); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(inf, rnd, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(neg_inf, rnd, 32U), FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(aNaN, rnd, 32U), FE_INVALID); + } + } + + void testSpecialNumbersZeroWidth(UfromfpxFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(zero, rnd, 0U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(neg_zero, rnd, 0U), FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(inf, rnd, 0U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(neg_inf, rnd, 0U), FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(aNaN, rnd, 0U), FE_INVALID); + } + } + + void testRoundedNumbersWithinRange(UfromfpxFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ(T(1.0), func(T(1.0), rnd, 1U)); + EXPECT_FP_EQ(T(10.0), func(T(10.0), rnd, 4U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.0), rnd, 11U)); + EXPECT_FP_EQ(T(1234.0), func(T(1234.0), rnd, 64U)); + } + } + + void testRoundedNumbersOutsideRange(UfromfpxFunc func) { + for (int rnd : MATH_ROUNDING_DIRECTIONS_INCLUDING_UNKNOWN) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.0), rnd, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.0), rnd, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.0), rnd, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.0), rnd, 10U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.0), rnd, 32U), FE_INVALID); + } + } + + void testFractionsUpwardWithinRange(UfromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(0.5), FP_INT_UPWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.5), FP_INT_UPWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(0.115), FP_INT_UPWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.115), FP_INT_UPWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(0.715), FP_INT_UPWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.715), FP_INT_UPWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.3), FP_INT_UPWARD, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.5), FP_INT_UPWARD, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.75), FP_INT_UPWARD, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(11.0), func(T(10.32), FP_INT_UPWARD, 4U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(11.0), func(T(10.65), FP_INT_UPWARD, 4U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1235.0), func(T(1234.38), FP_INT_UPWARD, 11U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1235.0), func(T(1234.96), FP_INT_UPWARD, 11U), + FE_INEXACT); + } + + void testFractionsUpwardOutsideRange(UfromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.3), FP_INT_UPWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.3), FP_INT_UPWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.5), FP_INT_UPWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.5), FP_INT_UPWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.75), FP_INT_UPWARD, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.75), FP_INT_UPWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.32), FP_INT_UPWARD, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.32), FP_INT_UPWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.65), FP_INT_UPWARD, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.65), FP_INT_UPWARD, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.38), FP_INT_UPWARD, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.38), FP_INT_UPWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.96), FP_INT_UPWARD, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.96), FP_INT_UPWARD, 32U), + FE_INVALID); + } + + void testFractionsDownwardWithinRange(UfromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.5), FP_INT_DOWNWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.115), FP_INT_DOWNWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.715), FP_INT_DOWNWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.3), FP_INT_DOWNWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.5), FP_INT_DOWNWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.75), FP_INT_DOWNWARD, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.32), FP_INT_DOWNWARD, 4U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.65), FP_INT_DOWNWARD, 4U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1234.0), func(T(1234.38), FP_INT_DOWNWARD, 11U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1234.0), func(T(1234.96), FP_INT_DOWNWARD, 11U), FE_INEXACT); + } + + void testFractionsDownwardOutsideRange(UfromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-0.5), FP_INT_DOWNWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-0.115), FP_INT_DOWNWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-0.715), FP_INT_DOWNWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.3), FP_INT_DOWNWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.5), FP_INT_DOWNWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.75), FP_INT_DOWNWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.32), FP_INT_DOWNWARD, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.32), FP_INT_DOWNWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.65), FP_INT_DOWNWARD, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.65), FP_INT_DOWNWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.38), FP_INT_DOWNWARD, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.38), FP_INT_DOWNWARD, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.96), FP_INT_DOWNWARD, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.96), FP_INT_DOWNWARD, 32U), + FE_INVALID); + } + + void testFractionsTowardZeroWithinRange(UfromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.5), FP_INT_TOWARDZERO, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.5), FP_INT_TOWARDZERO, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.115), FP_INT_TOWARDZERO, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.115), FP_INT_TOWARDZERO, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.715), FP_INT_TOWARDZERO, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.715), FP_INT_TOWARDZERO, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.3), FP_INT_TOWARDZERO, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.5), FP_INT_TOWARDZERO, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.75), FP_INT_TOWARDZERO, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.32), FP_INT_TOWARDZERO, 4U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.65), FP_INT_TOWARDZERO, 4U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1234.0), func(T(1234.38), FP_INT_TOWARDZERO, 11U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1234.0), func(T(1234.96), FP_INT_TOWARDZERO, 11U), FE_INEXACT); + } + + void testFractionsTowardZeroOutsideRange(UfromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.3), FP_INT_TOWARDZERO, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.5), FP_INT_TOWARDZERO, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.75), FP_INT_TOWARDZERO, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.32), FP_INT_TOWARDZERO, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.32), FP_INT_TOWARDZERO, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.65), FP_INT_TOWARDZERO, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.65), FP_INT_TOWARDZERO, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.38), FP_INT_TOWARDZERO, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.38), FP_INT_TOWARDZERO, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.96), FP_INT_TOWARDZERO, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.96), FP_INT_TOWARDZERO, 32U), + FE_INVALID); + } + + void testFractionsToNearestFromZeroWithinRange(UfromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1.0), func(T(0.5), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(0.0), func(T(0.115), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-0.0), func(T(-0.115), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1.0), func(T(0.715), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1.0), func(T(1.3), FP_INT_TONEARESTFROMZERO, 1U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(2.0), func(T(1.5), FP_INT_TONEARESTFROMZERO, 2U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(2.0), func(T(1.75), FP_INT_TONEARESTFROMZERO, 2U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(10.0), func(T(10.32), FP_INT_TONEARESTFROMZERO, 4U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(11.0), func(T(10.65), FP_INT_TONEARESTFROMZERO, 4U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1234.0), func(T(1234.38), FP_INT_TONEARESTFROMZERO, 11U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1235.0), func(T(1234.96), FP_INT_TONEARESTFROMZERO, 11U), FE_INEXACT); + } + + void testFractionsToNearestFromZeroOutsideRange(UfromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-0.5), FP_INT_TONEARESTFROMZERO, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-0.715), FP_INT_TONEARESTFROMZERO, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.3), FP_INT_TONEARESTFROMZERO, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.5), FP_INT_TONEARESTFROMZERO, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.5), FP_INT_TONEARESTFROMZERO, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.75), FP_INT_TONEARESTFROMZERO, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.75), FP_INT_TONEARESTFROMZERO, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(10.32), FP_INT_TONEARESTFROMZERO, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-10.32), FP_INT_TONEARESTFROMZERO, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(10.65), FP_INT_TONEARESTFROMZERO, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-10.65), FP_INT_TONEARESTFROMZERO, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1234.38), FP_INT_TONEARESTFROMZERO, 10U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1234.38), FP_INT_TONEARESTFROMZERO, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1234.96), FP_INT_TONEARESTFROMZERO, 10U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1234.96), FP_INT_TONEARESTFROMZERO, 32U), FE_INVALID); + } + + void testFractionsToNearestWithinRange(UfromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.5), FP_INT_TONEAREST, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.5), FP_INT_TONEAREST, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(0.0), func(T(0.115), FP_INT_TONEAREST, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(-0.0), func(T(-0.115), FP_INT_TONEAREST, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(0.715), FP_INT_TONEAREST, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(1.0), func(T(1.3), FP_INT_TONEAREST, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.5), FP_INT_TONEAREST, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(1.75), FP_INT_TONEAREST, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(10.0), func(T(10.32), FP_INT_TONEAREST, 4U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(11.0), func(T(10.65), FP_INT_TONEAREST, 4U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1234.0), func(T(1234.38), FP_INT_TONEAREST, 11U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1235.0), func(T(1234.96), FP_INT_TONEAREST, 11U), FE_INEXACT); + + EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(2.3), FP_INT_TONEAREST, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(2.0), func(T(2.5), FP_INT_TONEAREST, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(3.0), func(T(2.75), FP_INT_TONEAREST, 2U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(5.0), func(T(5.3), FP_INT_TONEAREST, 3U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(6.0), func(T(5.5), FP_INT_TONEAREST, 3U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION(T(6.0), func(T(5.75), FP_INT_TONEAREST, 3U), + FE_INEXACT); + } + + void testFractionsToNearestOutsideRange(UfromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-0.715), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.3), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.5), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.5), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1.75), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1.75), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.32), FP_INT_TONEAREST, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.32), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(10.65), FP_INT_TONEAREST, 3U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-10.65), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.38), FP_INT_TONEAREST, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.38), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(1234.96), FP_INT_TONEAREST, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-1234.96), FP_INT_TONEAREST, 32U), + FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(2.3), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-2.3), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(2.5), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-2.5), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(2.75), FP_INT_TONEAREST, 1U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-2.75), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(5.3), FP_INT_TONEAREST, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-5.3), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(5.5), FP_INT_TONEAREST, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-5.5), FP_INT_TONEAREST, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(5.75), FP_INT_TONEAREST, 2U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION(aNaN, func(T(-5.75), FP_INT_TONEAREST, 32U), + FE_INVALID); + } + + void testFractionsToNearestFallbackWithinRange(UfromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION( + T(0.0), func(T(0.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-0.0), func(T(-0.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(0.0), func(T(0.115), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(-0.0), func(T(-0.115), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1.0), func(T(0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1.0), func(T(1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(2.0), func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(2.0), func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(10.0), func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(11.0), func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 4U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1234.0), func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U), + FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(1235.0), func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 11U), + FE_INEXACT); + + EXPECT_FP_EQ_WITH_EXCEPTION( + T(2.0), func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(2.0), func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(3.0), func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(5.0), func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(6.0), func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INEXACT); + EXPECT_FP_EQ_WITH_EXCEPTION( + T(6.0), func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INEXACT); + } + + void testFractionsToNearestFallbackOutsideRange(UfromfpxFunc func) { + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-0.715), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-10.32), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 3U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-10.65), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1234.38), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 10U), + FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-1234.96), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), + FE_INVALID); + + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-2.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-2.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 1U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-2.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-5.3), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-5.5), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 2U), FE_INVALID); + EXPECT_FP_EQ_WITH_EXCEPTION( + aNaN, func(T(-5.75), UNKNOWN_MATH_ROUNDING_DIRECTION, 32U), FE_INVALID); + } +}; + +#define LIST_UFROMFPX_TESTS(T, func) \ + using LlvmLibcUfromfpxTest = UfromfpxTestTemplate<T>; \ + TEST_F(LlvmLibcUfromfpxTest, SpecialNumbersNonzeroWidth) { \ + testSpecialNumbersNonzeroWidth(&func); \ + } \ + TEST_F(LlvmLibcUfromfpxTest, SpecialNumbersZeroWidth) { \ + testSpecialNumbersZeroWidth(&func); \ + } \ + TEST_F(LlvmLibcUfromfpxTest, RoundedNumbersWithinRange) { \ + testRoundedNumbersWithinRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpxTest, RoundedNumbersOutsideRange) { \ + testRoundedNumbersOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpxTest, FractionsUpwardWithinRange) { \ + testFractionsUpwardWithinRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpxTest, FractionsUpwardOutsideRange) { \ + testFractionsUpwardOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpxTest, FractionsDownwardWithinRange) { \ + testFractionsDownwardWithinRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpxTest, FractionsDownwardOutsideRange) { \ + testFractionsDownwardOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpxTest, FractionsTowardZeroWithinRange) { \ + testFractionsTowardZeroWithinRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpxTest, FractionsTowardZeroOutsideRange) { \ + testFractionsTowardZeroOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpxTest, FractionsToNearestFromZeroWithinRange) { \ + testFractionsToNearestFromZeroWithinRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpxTest, FractionsToNearestFromZeroOutsideRange) { \ + testFractionsToNearestFromZeroOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpxTest, FractionsToNearestWithinRange) { \ + testFractionsToNearestWithinRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpxTest, FractionsToNearestOutsideRange) { \ + testFractionsToNearestOutsideRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpxTest, FractionsToNearestFallbackWithinRange) { \ + testFractionsToNearestFallbackWithinRange(&func); \ + } \ + TEST_F(LlvmLibcUfromfpxTest, FractionsToNearestFallbackOutsideRange) { \ + testFractionsToNearestFallbackOutsideRange(&func); \ + } + +#endif // LIBC_TEST_SRC_MATH_SMOKE_UFROMFPXTEST_H diff --git a/libc/test/src/math/smoke/acosf_test.cpp b/libc/test/src/math/smoke/acosf_test.cpp index 864c9ea4d3175daf0a12ec0e536264c0242b035c..573a2c39492f0ca82e58556c0f1eb57f3c1b323c 100644 --- a/libc/test/src/math/smoke/acosf_test.cpp +++ b/libc/test/src/math/smoke/acosf_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/acosf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/acoshf_test.cpp b/libc/test/src/math/smoke/acoshf_test.cpp index b3ba740c2024d35528df006452defde6e9ea2e00..f561f23eb99ad346e61195901a7932ba0753046f 100644 --- a/libc/test/src/math/smoke/acoshf_test.cpp +++ b/libc/test/src/math/smoke/acoshf_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/acoshf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/asinf_test.cpp b/libc/test/src/math/smoke/asinf_test.cpp index e6afb23a397fe148e883fa2a88e3f8133bfa30da..39d25e72c143b9066c125f8a3b7eef9d16f69249 100644 --- a/libc/test/src/math/smoke/asinf_test.cpp +++ b/libc/test/src/math/smoke/asinf_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/asinf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/asinhf_test.cpp b/libc/test/src/math/smoke/asinhf_test.cpp index 7a520cdc050a227b540147469c5b71af4d9c9be2..9637bfa53948852e3947bb408ffd10563025d452 100644 --- a/libc/test/src/math/smoke/asinhf_test.cpp +++ b/libc/test/src/math/smoke/asinhf_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/asinhf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/atan2f_test.cpp b/libc/test/src/math/smoke/atan2f_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ecac36b3a8c01fdc669abcdd3e58395f548a30fa --- /dev/null +++ b/libc/test/src/math/smoke/atan2f_test.cpp @@ -0,0 +1,50 @@ +//===-- Unittests for atan2f ----------------------------------------------===// +// +// 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" +#include "src/__support/FPUtil/FPBits.h" +#include "src/errno/libc_errno.h" +#include "src/math/atan2f.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +using LlvmLibcAtan2fTest = LIBC_NAMESPACE::testing::FPTest<float>; + +TEST_F(LlvmLibcAtan2fTest, SpecialNumbers) { + LIBC_NAMESPACE::libc_errno = 0; + + LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atan2f(aNaN, zero)); + EXPECT_FP_EXCEPTION(0); + EXPECT_MATH_ERRNO(0); + + LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); + EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atan2f(1.0f, aNaN)); + EXPECT_FP_EXCEPTION(0); + EXPECT_MATH_ERRNO(0); + + LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); + EXPECT_FP_EQ_ALL_ROUNDING(0.0f, LIBC_NAMESPACE::atan2f(zero, zero)); + EXPECT_FP_EXCEPTION(0); + EXPECT_MATH_ERRNO(0); + + LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); + EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, LIBC_NAMESPACE::atan2f(-0.0f, zero)); + EXPECT_FP_EXCEPTION(0); + EXPECT_MATH_ERRNO(0); + + LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); + EXPECT_FP_EQ_ALL_ROUNDING(0.0f, LIBC_NAMESPACE::atan2f(1.0f, inf)); + EXPECT_FP_EXCEPTION(0); + EXPECT_MATH_ERRNO(0); + + LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); + EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, LIBC_NAMESPACE::atan2f(-1.0f, inf)); + EXPECT_FP_EXCEPTION(0); + EXPECT_MATH_ERRNO(0); +} diff --git a/libc/test/src/math/smoke/atanf_test.cpp b/libc/test/src/math/smoke/atanf_test.cpp index 8cc1b418f869c2c4baa94d0b8ded628b42bd3477..abd9835d38a057b1303ccaa85494a79956700b89 100644 --- a/libc/test/src/math/smoke/atanf_test.cpp +++ b/libc/test/src/math/smoke/atanf_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/atanf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/atanhf_test.cpp b/libc/test/src/math/smoke/atanhf_test.cpp index e1d6d2532d39e34df88feb2823afea41d410364b..590a7ab60f04f3a9a1c6f4728aa93bf0fea52662 100644 --- a/libc/test/src/math/smoke/atanhf_test.cpp +++ b/libc/test/src/math/smoke/atanhf_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/atanhf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> @@ -19,7 +19,7 @@ using LlvmLibcAtanhfTest = LIBC_NAMESPACE::testing::FPTest<float>; TEST_F(LlvmLibcAtanhfTest, SpecialNumbers) { - using Sign = LIBC_NAMESPACE::fputil::Sign; + LIBC_NAMESPACE::libc_errno = 0; LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); diff --git a/libc/test/src/math/smoke/canonicalize_test.cpp b/libc/test/src/math/smoke/canonicalize_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..54a1ddd49ca4baa3ac737e01eefd69fa0d33c592 --- /dev/null +++ b/libc/test/src/math/smoke/canonicalize_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for canonicalize ----------------------------------------===// +// +// 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 "CanonicalizeTest.h" + +#include "src/math/canonicalize.h" + +LIST_CANONICALIZE_TESTS(double, LIBC_NAMESPACE::canonicalize) diff --git a/libc/test/src/math/smoke/canonicalizef128_test.cpp b/libc/test/src/math/smoke/canonicalizef128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..242e2331a29eacc6b76e36268f17467efa13434f --- /dev/null +++ b/libc/test/src/math/smoke/canonicalizef128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for canonicalizef128 ------------------------------------===// +// +// 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 "CanonicalizeTest.h" + +#include "src/math/canonicalizef128.h" + +LIST_CANONICALIZE_TESTS(float128, LIBC_NAMESPACE::canonicalizef128) diff --git a/libc/test/src/math/smoke/canonicalizef_test.cpp b/libc/test/src/math/smoke/canonicalizef_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..17cf3c3639a4aa62d3131e09dc345d5b0ae44943 --- /dev/null +++ b/libc/test/src/math/smoke/canonicalizef_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for canonicalizef ---------------------------------------===// +// +// 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 "CanonicalizeTest.h" + +#include "src/math/canonicalizef.h" + +LIST_CANONICALIZE_TESTS(float, LIBC_NAMESPACE::canonicalizef) diff --git a/libc/test/src/math/smoke/canonicalizel_test.cpp b/libc/test/src/math/smoke/canonicalizel_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..23cb21dce84ea77b6060cf897717b670fa278f1e --- /dev/null +++ b/libc/test/src/math/smoke/canonicalizel_test.cpp @@ -0,0 +1,19 @@ +//===-- Unittests for canonicalizel ---------------------------------------===// +// +// 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 "CanonicalizeTest.h" + +#include "src/math/canonicalizel.h" + +LIST_CANONICALIZE_TESTS(long double, LIBC_NAMESPACE::canonicalizel) + +#ifdef LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80 + +X86_80_SPECIAL_CANONICALIZE_TEST(long double, LIBC_NAMESPACE::canonicalizel) + +#endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80 diff --git a/libc/test/src/math/smoke/cosf_test.cpp b/libc/test/src/math/smoke/cosf_test.cpp index 539c428eadf113f59df2337358486ae8c65ff4bc..62132990ed5473e7484a08a5265bef59fe515209 100644 --- a/libc/test/src/math/smoke/cosf_test.cpp +++ b/libc/test/src/math/smoke/cosf_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/cosf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/coshf_test.cpp b/libc/test/src/math/smoke/coshf_test.cpp index e38802f93647432fbf855afd533bd7ceef8cd968..9d7ef505ae74970e5be8b516e257da318333a1c0 100644 --- a/libc/test/src/math/smoke/coshf_test.cpp +++ b/libc/test/src/math/smoke/coshf_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/CPP/array.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/coshf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/erff_test.cpp b/libc/test/src/math/smoke/erff_test.cpp index 843cc7f4c8c04dee2f92c7e89a9b805ac062bf15..24778f8d653addde2b81a9e32fa04258dfecbcf0 100644 --- a/libc/test/src/math/smoke/erff_test.cpp +++ b/libc/test/src/math/smoke/erff_test.cpp @@ -6,11 +6,11 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/math/erff.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/exp10_test.cpp b/libc/test/src/math/smoke/exp10_test.cpp index daa7b5b48842bce3aa343aaaa61dd8d745a26525..fffffeb4c78abf6bc6e5e98013cc9a82da7ebf53 100644 --- a/libc/test/src/math/smoke/exp10_test.cpp +++ b/libc/test/src/math/smoke/exp10_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/exp10.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/exp10f_test.cpp b/libc/test/src/math/smoke/exp10f_test.cpp index f6533e983dacd8b13587390ac43e84e5fa547acd..c0dcc125033248c66293e0b8d4b9c3a29d702acb 100644 --- a/libc/test/src/math/smoke/exp10f_test.cpp +++ b/libc/test/src/math/smoke/exp10f_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/exp10f.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/exp2_test.cpp b/libc/test/src/math/smoke/exp2_test.cpp index 7bcc2a3cb6c74249d5de02252bd7dfa95992743c..d362d32f678b2571c0310cd1c52b8e57192089e9 100644 --- a/libc/test/src/math/smoke/exp2_test.cpp +++ b/libc/test/src/math/smoke/exp2_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/exp2.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/exp2f_test.cpp b/libc/test/src/math/smoke/exp2f_test.cpp index 7baab630a4cbc47a6b83ae743d85ce99d196f5b0..e2989a6ec4d8af9319e83e5cb1fc66d897635346 100644 --- a/libc/test/src/math/smoke/exp2f_test.cpp +++ b/libc/test/src/math/smoke/exp2f_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/macros/properties/cpu_features.h" // LIBC_TARGET_CPU_HAS_FMA #include "src/errno/libc_errno.h" #include "src/math/exp2f.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/exp_test.cpp b/libc/test/src/math/smoke/exp_test.cpp index 455cb2ea1353289bb6f10f0401feaf5319d820d0..a2becc74f526f9cbdc2439609d580aa748786d13 100644 --- a/libc/test/src/math/smoke/exp_test.cpp +++ b/libc/test/src/math/smoke/exp_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/exp.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/expf_test.cpp b/libc/test/src/math/smoke/expf_test.cpp index 2968704f83e355a0557eef6a05691a4d9be43b8c..42710c5fa404e94cef0f31ba34e82acac596b007 100644 --- a/libc/test/src/math/smoke/expf_test.cpp +++ b/libc/test/src/math/smoke/expf_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/expf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/expm1_test.cpp b/libc/test/src/math/smoke/expm1_test.cpp index 4581060075e32c9745699f5cc0c2567f0898ada0..07963ec2d34c8d850896bb023e4271cd0c148620 100644 --- a/libc/test/src/math/smoke/expm1_test.cpp +++ b/libc/test/src/math/smoke/expm1_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/expm1.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/expm1f_test.cpp b/libc/test/src/math/smoke/expm1f_test.cpp index 4ef8d50ba551a7bde4e30b15f927265303a5877b..82e0b1546350447aa109f0414813ddcf2ae049a8 100644 --- a/libc/test/src/math/smoke/expm1f_test.cpp +++ b/libc/test/src/math/smoke/expm1f_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/expm1f.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/fmaximum_mag_num_test.cpp b/libc/test/src/math/smoke/fmaximum_mag_num_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..16ec1b0ea3437eeb7e773a92f2240dfee704cab4 --- /dev/null +++ b/libc/test/src/math/smoke/fmaximum_mag_num_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmaximum_mag_num-------------------------------------===// +// +// 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 "FMaximumMagNumTest.h" + +#include "src/math/fmaximum_mag_num.h" + +LIST_FMAXIMUM_MAG_NUM_TESTS(double, LIBC_NAMESPACE::fmaximum_mag_num) diff --git a/libc/test/src/math/smoke/fmaximum_mag_numf128_test.cpp b/libc/test/src/math/smoke/fmaximum_mag_numf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..17f2a24f7fd04ea3b0af7e14e7858ead90b737b9 --- /dev/null +++ b/libc/test/src/math/smoke/fmaximum_mag_numf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmaximum_mag_numf128---------------------------------===// +// +// 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 "FMaximumMagNumTest.h" + +#include "src/math/fmaximum_mag_numf128.h" + +LIST_FMAXIMUM_MAG_NUM_TESTS(float128, LIBC_NAMESPACE::fmaximum_mag_numf128) diff --git a/libc/test/src/math/smoke/fmaximum_mag_numf_test.cpp b/libc/test/src/math/smoke/fmaximum_mag_numf_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a8a46f96970ed6b127433a8cd661f35ee945fe37 --- /dev/null +++ b/libc/test/src/math/smoke/fmaximum_mag_numf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmaximum_mag_numf------------------------------------===// +// +// 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 "FMaximumMagNumTest.h" + +#include "src/math/fmaximum_mag_numf.h" + +LIST_FMAXIMUM_MAG_NUM_TESTS(float, LIBC_NAMESPACE::fmaximum_mag_numf) diff --git a/libc/test/src/math/smoke/fmaximum_mag_numl_test.cpp b/libc/test/src/math/smoke/fmaximum_mag_numl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c03fa20bd367e7319d3822e34b3eeb81bcea8878 --- /dev/null +++ b/libc/test/src/math/smoke/fmaximum_mag_numl_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmaximum_mag_numl------------------------------------===// +// +// 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 "FMaximumMagNumTest.h" + +#include "src/math/fmaximum_mag_numl.h" + +LIST_FMAXIMUM_MAG_NUM_TESTS(long double, LIBC_NAMESPACE::fmaximum_mag_numl) diff --git a/libc/test/src/math/smoke/fmaximum_mag_test.cpp b/libc/test/src/math/smoke/fmaximum_mag_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e70602f044ec691e92bdbfcda87fe8db715ef9b2 --- /dev/null +++ b/libc/test/src/math/smoke/fmaximum_mag_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmaximum_mag-----------------------------------------===// +// +// 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 "FMaximumMagTest.h" + +#include "src/math/fmaximum_mag.h" + +LIST_FMAXIMUM_MAG_TESTS(double, LIBC_NAMESPACE::fmaximum_mag) diff --git a/libc/test/src/math/smoke/fmaximum_magf128_test.cpp b/libc/test/src/math/smoke/fmaximum_magf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d7ae8ec8d7a03fe15f59fb98fc2e286842fc4cef --- /dev/null +++ b/libc/test/src/math/smoke/fmaximum_magf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmaximum_magf128-------------------------------------===// +// +// 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 "FMaximumMagTest.h" + +#include "src/math/fmaximum_magf128.h" + +LIST_FMAXIMUM_MAG_TESTS(float128, LIBC_NAMESPACE::fmaximum_magf128) diff --git a/libc/test/src/math/smoke/fmaximum_magf_test.cpp b/libc/test/src/math/smoke/fmaximum_magf_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..efca320b2b373d2663348f682307f173f57da134 --- /dev/null +++ b/libc/test/src/math/smoke/fmaximum_magf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmaximum_magf----------------------------------------===// +// +// 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 "FMaximumMagTest.h" + +#include "src/math/fmaximum_magf.h" + +LIST_FMAXIMUM_MAG_TESTS(float, LIBC_NAMESPACE::fmaximum_magf) diff --git a/libc/test/src/math/smoke/fmaximum_magl_test.cpp b/libc/test/src/math/smoke/fmaximum_magl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..16b420b8714b07313bcec0b15823a0b2badfeb3d --- /dev/null +++ b/libc/test/src/math/smoke/fmaximum_magl_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmaximum_magl----------------------------------------===// +// +// 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 "FMaximumMagTest.h" + +#include "src/math/fmaximum_magl.h" + +LIST_FMAXIMUM_MAG_TESTS(long double, LIBC_NAMESPACE::fmaximum_magl) diff --git a/libc/test/src/math/smoke/fmaximum_num_test.cpp b/libc/test/src/math/smoke/fmaximum_num_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb9afdf78b83f5d827ca78db27e497944d29f1c4 --- /dev/null +++ b/libc/test/src/math/smoke/fmaximum_num_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmaximum_num-----------------------------------------===// +// +// 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 "FMaximumNumTest.h" + +#include "src/math/fmaximum_num.h" + +LIST_FMAXIMUM_NUM_TESTS(double, LIBC_NAMESPACE::fmaximum_num) diff --git a/libc/test/src/math/smoke/fmaximum_numf128_test.cpp b/libc/test/src/math/smoke/fmaximum_numf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6855ea3b39a9c3728c1b46b89c4fde81cbe61085 --- /dev/null +++ b/libc/test/src/math/smoke/fmaximum_numf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmaximum_numf128-------------------------------------===// +// +// 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 "FMaximumNumTest.h" + +#include "src/math/fmaximum_numf128.h" + +LIST_FMAXIMUM_NUM_TESTS(float128, LIBC_NAMESPACE::fmaximum_numf128) diff --git a/libc/test/src/math/smoke/fmaximum_numf_test.cpp b/libc/test/src/math/smoke/fmaximum_numf_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..053d18803e07f906600effa86fe2c6505fd202af --- /dev/null +++ b/libc/test/src/math/smoke/fmaximum_numf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmaximum_numf----------------------------------------===// +// +// 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 "FMaximumNumTest.h" + +#include "src/math/fmaximum_numf.h" + +LIST_FMAXIMUM_NUM_TESTS(float, LIBC_NAMESPACE::fmaximum_numf) diff --git a/libc/test/src/math/smoke/fmaximum_numl_test.cpp b/libc/test/src/math/smoke/fmaximum_numl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bf9612c4111da13b37a2f89db8d7f1b096d6c27c --- /dev/null +++ b/libc/test/src/math/smoke/fmaximum_numl_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmaximum_numl----------------------------------------===// +// +// 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 "FMaximumNumTest.h" + +#include "src/math/fmaximum_numl.h" + +LIST_FMAXIMUM_NUM_TESTS(long double, LIBC_NAMESPACE::fmaximum_numl) diff --git a/libc/test/src/math/smoke/fmaximum_test.cpp b/libc/test/src/math/smoke/fmaximum_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..990e0177d8689c2e9c3896aeb2118a5b7258e7d5 --- /dev/null +++ b/libc/test/src/math/smoke/fmaximum_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmaximum---------------------------------------------===// +// +// 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 "FMaximumTest.h" + +#include "src/math/fmaximum.h" + +LIST_FMAXIMUM_TESTS(double, LIBC_NAMESPACE::fmaximum) diff --git a/libc/test/src/math/smoke/fmaximumf128_test.cpp b/libc/test/src/math/smoke/fmaximumf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7e0b97bcdd4de1b247ce5cc916012c10bda1a95b --- /dev/null +++ b/libc/test/src/math/smoke/fmaximumf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmaximumf128-----------------------------------------===// +// +// 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 "FMaximumTest.h" + +#include "src/math/fmaximumf128.h" + +LIST_FMAXIMUM_TESTS(float128, LIBC_NAMESPACE::fmaximumf128) diff --git a/libc/test/src/math/smoke/fmaximumf_test.cpp b/libc/test/src/math/smoke/fmaximumf_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a92bbd1446e71a752c244945ec5e5bab91f8f999 --- /dev/null +++ b/libc/test/src/math/smoke/fmaximumf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmaximumf--------------------------------------------===// +// +// 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 "FMaximumTest.h" + +#include "src/math/fmaximumf.h" + +LIST_FMAXIMUM_TESTS(float, LIBC_NAMESPACE::fmaximumf) diff --git a/libc/test/src/math/smoke/fmaximuml_test.cpp b/libc/test/src/math/smoke/fmaximuml_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..080847b9f4de854275ea3938861e65de8d00e299 --- /dev/null +++ b/libc/test/src/math/smoke/fmaximuml_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmaximuml--------------------------------------------===// +// +// 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 "FMaximumTest.h" + +#include "src/math/fmaximuml.h" + +LIST_FMAXIMUM_TESTS(long double, LIBC_NAMESPACE::fmaximuml) diff --git a/libc/test/src/math/smoke/fminimum_mag_num_test.cpp b/libc/test/src/math/smoke/fminimum_mag_num_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..471f2ceb3c2cdc74e742a288d9f725ead17c53e1 --- /dev/null +++ b/libc/test/src/math/smoke/fminimum_mag_num_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fminimum_mag_num-------------------------------------===// +// +// 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 "FMinimumMagNumTest.h" + +#include "src/math/fminimum_mag_num.h" + +LIST_FMINIMUM_MAG_NUM_TESTS(double, LIBC_NAMESPACE::fminimum_mag_num) diff --git a/libc/test/src/math/smoke/fminimum_mag_numf128_test.cpp b/libc/test/src/math/smoke/fminimum_mag_numf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f1db025f48954052789d97e9c95474e6452dbc56 --- /dev/null +++ b/libc/test/src/math/smoke/fminimum_mag_numf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fminimum_mag_numf128---------------------------------===// +// +// 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 "FMinimumMagNumTest.h" + +#include "src/math/fminimum_mag_numf128.h" + +LIST_FMINIMUM_MAG_NUM_TESTS(float128, LIBC_NAMESPACE::fminimum_mag_numf128) diff --git a/libc/test/src/math/smoke/fminimum_mag_numf_test.cpp b/libc/test/src/math/smoke/fminimum_mag_numf_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..773ba806b99ecbb557a2101c2eb657c25284a02c --- /dev/null +++ b/libc/test/src/math/smoke/fminimum_mag_numf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fminimum_mag_numf------------------------------------===// +// +// 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 "FMinimumMagNumTest.h" + +#include "src/math/fminimum_mag_numf.h" + +LIST_FMINIMUM_MAG_NUM_TESTS(float, LIBC_NAMESPACE::fminimum_mag_numf) diff --git a/libc/test/src/math/smoke/fminimum_mag_numl_test.cpp b/libc/test/src/math/smoke/fminimum_mag_numl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b4152779db7301734356ae6f0e7254cb3bd92686 --- /dev/null +++ b/libc/test/src/math/smoke/fminimum_mag_numl_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fminimum_mag_numl------------------------------------===// +// +// 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 "FMinimumMagNumTest.h" + +#include "src/math/fminimum_mag_numl.h" + +LIST_FMINIMUM_MAG_NUM_TESTS(long double, LIBC_NAMESPACE::fminimum_mag_numl) diff --git a/libc/test/src/math/smoke/fminimum_mag_test.cpp b/libc/test/src/math/smoke/fminimum_mag_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f4138f3353d11c89dd3147b989992a0fc04676be --- /dev/null +++ b/libc/test/src/math/smoke/fminimum_mag_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fminimum_mag-----------------------------------------===// +// +// 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 "FMinimumMagTest.h" + +#include "src/math/fminimum_mag.h" + +LIST_FMINIMUM_MAG_TESTS(double, LIBC_NAMESPACE::fminimum_mag) diff --git a/libc/test/src/math/smoke/fminimum_magf128_test.cpp b/libc/test/src/math/smoke/fminimum_magf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..010ee6e73bee09efc24e2f77c07d2d2be1b05b56 --- /dev/null +++ b/libc/test/src/math/smoke/fminimum_magf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fminimum_magf128-------------------------------------===// +// +// 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 "FMinimumMagTest.h" + +#include "src/math/fminimum_magf128.h" + +LIST_FMINIMUM_MAG_TESTS(float128, LIBC_NAMESPACE::fminimum_magf128) diff --git a/libc/test/src/math/smoke/fminimum_magf_test.cpp b/libc/test/src/math/smoke/fminimum_magf_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aa27431489309b9a9b53ccb48adebe9cec858842 --- /dev/null +++ b/libc/test/src/math/smoke/fminimum_magf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fminimum_magf----------------------------------------===// +// +// 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 "FMinimumMagTest.h" + +#include "src/math/fminimum_magf.h" + +LIST_FMINIMUM_MAG_TESTS(float, LIBC_NAMESPACE::fminimum_magf) diff --git a/libc/test/src/math/smoke/fminimum_magl_test.cpp b/libc/test/src/math/smoke/fminimum_magl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c6fbf7df0e70a7341739d3734b8965d50eb283ab --- /dev/null +++ b/libc/test/src/math/smoke/fminimum_magl_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fminimum_magl----------------------------------------===// +// +// 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 "FMinimumMagTest.h" + +#include "src/math/fminimum_magl.h" + +LIST_FMINIMUM_MAG_TESTS(long double, LIBC_NAMESPACE::fminimum_magl) diff --git a/libc/test/src/math/smoke/fminimum_num_test.cpp b/libc/test/src/math/smoke/fminimum_num_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1be7ebb5fe8e9f7034f83cbf03881def60c3b7c3 --- /dev/null +++ b/libc/test/src/math/smoke/fminimum_num_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fminimum_num-----------------------------------------===// +// +// 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 "FMinimumNumTest.h" + +#include "src/math/fminimum_num.h" + +LIST_FMINIMUM_NUM_TESTS(double, LIBC_NAMESPACE::fminimum_num) diff --git a/libc/test/src/math/smoke/fminimum_numf128_test.cpp b/libc/test/src/math/smoke/fminimum_numf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d773d8973286e89b8c7cecee4b5a3397aa959a2e --- /dev/null +++ b/libc/test/src/math/smoke/fminimum_numf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fminimum_numf128-------------------------------------===// +// +// 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 "FMinimumNumTest.h" + +#include "src/math/fminimum_numf128.h" + +LIST_FMINIMUM_NUM_TESTS(float128, LIBC_NAMESPACE::fminimum_numf128) diff --git a/libc/test/src/math/smoke/fminimum_numf_test.cpp b/libc/test/src/math/smoke/fminimum_numf_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9b60f39d55a8d0e563464fb5b1beb27bbdec702c --- /dev/null +++ b/libc/test/src/math/smoke/fminimum_numf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fminimum_numf----------------------------------------===// +// +// 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 "FMinimumNumTest.h" + +#include "src/math/fminimum_numf.h" + +LIST_FMINIMUM_NUM_TESTS(float, LIBC_NAMESPACE::fminimum_numf) diff --git a/libc/test/src/math/smoke/fminimum_numl_test.cpp b/libc/test/src/math/smoke/fminimum_numl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8a72cd8adc5bf1c9811242461b71b17d38dc30fd --- /dev/null +++ b/libc/test/src/math/smoke/fminimum_numl_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fminimum_numl----------------------------------------===// +// +// 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 "FMinimumNumTest.h" + +#include "src/math/fminimum_numl.h" + +LIST_FMINIMUM_NUM_TESTS(long double, LIBC_NAMESPACE::fminimum_numl) diff --git a/libc/test/src/math/smoke/fminimum_test.cpp b/libc/test/src/math/smoke/fminimum_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7778f1c2311c00b5660b9daa3c5da979fde3ab42 --- /dev/null +++ b/libc/test/src/math/smoke/fminimum_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fminimum---------------------------------------------===// +// +// 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 "FMinimumTest.h" + +#include "src/math/fminimum.h" + +LIST_FMINIMUM_TESTS(double, LIBC_NAMESPACE::fminimum) diff --git a/libc/test/src/math/smoke/fminimumf128_test.cpp b/libc/test/src/math/smoke/fminimumf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..163090b8a9ec5c03f45610bd5b8a48349fe70b71 --- /dev/null +++ b/libc/test/src/math/smoke/fminimumf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fminimumf128-----------------------------------------===// +// +// 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 "FMinimumTest.h" + +#include "src/math/fminimumf128.h" + +LIST_FMINIMUM_TESTS(float128, LIBC_NAMESPACE::fminimumf128) diff --git a/libc/test/src/math/smoke/fminimumf_test.cpp b/libc/test/src/math/smoke/fminimumf_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2ca0f2f35a7ff3715cd30a3f3dbcf1213cf61651 --- /dev/null +++ b/libc/test/src/math/smoke/fminimumf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fminimumf--------------------------------------------===// +// +// 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 "FMinimumTest.h" + +#include "src/math/fminimumf.h" + +LIST_FMINIMUM_TESTS(float, LIBC_NAMESPACE::fminimumf) diff --git a/libc/test/src/math/smoke/fminimuml_test.cpp b/libc/test/src/math/smoke/fminimuml_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3c067ae23f45dcce1acab0c59d4d26cb1e19c4f5 --- /dev/null +++ b/libc/test/src/math/smoke/fminimuml_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fminimuml--------------------------------------------===// +// +// 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 "FMinimumTest.h" + +#include "src/math/fminimuml.h" + +LIST_FMINIMUM_TESTS(long double, LIBC_NAMESPACE::fminimuml) diff --git a/libc/test/src/math/smoke/fromfp_test.cpp b/libc/test/src/math/smoke/fromfp_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..147a9df9afcff9dbdf15deb4eebcb7545b9a3c8e --- /dev/null +++ b/libc/test/src/math/smoke/fromfp_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fromfp ----------------------------------------------===// +// +// 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 "FromfpTest.h" + +#include "src/math/fromfp.h" + +LIST_FROMFP_TESTS(double, LIBC_NAMESPACE::fromfp) diff --git a/libc/test/src/math/smoke/fromfpf128_test.cpp b/libc/test/src/math/smoke/fromfpf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..288aadb359bfe00ccd0589ff3c9696c71b0f8cb8 --- /dev/null +++ b/libc/test/src/math/smoke/fromfpf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fromfpf128 ------------------------------------------===// +// +// 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 "FromfpTest.h" + +#include "src/math/fromfpf128.h" + +LIST_FROMFP_TESTS(float128, LIBC_NAMESPACE::fromfpf128) diff --git a/libc/test/src/math/smoke/fromfpf_test.cpp b/libc/test/src/math/smoke/fromfpf_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63f3f624716e53757ad812e4e2a64f44d99a1564 --- /dev/null +++ b/libc/test/src/math/smoke/fromfpf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fromfpf ---------------------------------------------===// +// +// 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 "FromfpTest.h" + +#include "src/math/fromfpf.h" + +LIST_FROMFP_TESTS(float, LIBC_NAMESPACE::fromfpf) diff --git a/libc/test/src/math/smoke/fromfpl_test.cpp b/libc/test/src/math/smoke/fromfpl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c0072768870b71804fc6993af209914c972cf92c --- /dev/null +++ b/libc/test/src/math/smoke/fromfpl_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fromfpl ---------------------------------------------===// +// +// 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 "FromfpTest.h" + +#include "src/math/fromfpl.h" + +LIST_FROMFP_TESTS(long double, LIBC_NAMESPACE::fromfpl) diff --git a/libc/test/src/math/smoke/fromfpx_test.cpp b/libc/test/src/math/smoke/fromfpx_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..10b1eee726e1fec6548618f07b3a723b42707abf --- /dev/null +++ b/libc/test/src/math/smoke/fromfpx_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fromfpx ---------------------------------------------===// +// +// 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 "FromfpxTest.h" + +#include "src/math/fromfpx.h" + +LIST_FROMFPX_TESTS(double, LIBC_NAMESPACE::fromfpx) diff --git a/libc/test/src/math/smoke/fromfpxf128_test.cpp b/libc/test/src/math/smoke/fromfpxf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2839bed30cb7c765ef450305c1e48fffce24ba39 --- /dev/null +++ b/libc/test/src/math/smoke/fromfpxf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fromfpxf128 -----------------------------------------===// +// +// 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 "FromfpxTest.h" + +#include "src/math/fromfpxf128.h" + +LIST_FROMFPX_TESTS(float128, LIBC_NAMESPACE::fromfpxf128) diff --git a/libc/test/src/math/smoke/fromfpxf_test.cpp b/libc/test/src/math/smoke/fromfpxf_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42e47aba40ae7b890c90a071ddd425641675c038 --- /dev/null +++ b/libc/test/src/math/smoke/fromfpxf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fromfpxf --------------------------------------------===// +// +// 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 "FromfpxTest.h" + +#include "src/math/fromfpxf.h" + +LIST_FROMFPX_TESTS(float, LIBC_NAMESPACE::fromfpxf) diff --git a/libc/test/src/math/smoke/fromfpxl_test.cpp b/libc/test/src/math/smoke/fromfpxl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cbe8d750ff2a6fe2ce8cfa232750e89d26fb0417 --- /dev/null +++ b/libc/test/src/math/smoke/fromfpxl_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fromfpxl --------------------------------------------===// +// +// 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 "FromfpxTest.h" + +#include "src/math/fromfpxl.h" + +LIST_FROMFPX_TESTS(long double, LIBC_NAMESPACE::fromfpxl) diff --git a/libc/test/src/math/smoke/log10_test.cpp b/libc/test/src/math/smoke/log10_test.cpp index c1658a3d5c9653cd2e8a075af3b3a3b0c7fbc84c..36d7534197648264ed1dcd362369d9bb5808de12 100644 --- a/libc/test/src/math/smoke/log10_test.cpp +++ b/libc/test/src/math/smoke/log10_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/log10.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/log10f_test.cpp b/libc/test/src/math/smoke/log10f_test.cpp index 53950233cabf5bac7ae47f5dba0d63ce77d76f7d..53e699417fb7c082d68b7e5aa767b2b798e53ad5 100644 --- a/libc/test/src/math/smoke/log10f_test.cpp +++ b/libc/test/src/math/smoke/log10f_test.cpp @@ -6,11 +6,11 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/math/log10f.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/log1p_test.cpp b/libc/test/src/math/smoke/log1p_test.cpp index e1966c28397c086ccbbf3f084a6858d2a4ee3330..5fe9c60f90abffaf9e46ca4eef59222fb25adaa2 100644 --- a/libc/test/src/math/smoke/log1p_test.cpp +++ b/libc/test/src/math/smoke/log1p_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/log1p.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/log1pf_test.cpp b/libc/test/src/math/smoke/log1pf_test.cpp index 377a46adef9c792232c1cad3df7096de85e87705..e2fb2f057d2eb7a8dfea29498647af577bd5e25c 100644 --- a/libc/test/src/math/smoke/log1pf_test.cpp +++ b/libc/test/src/math/smoke/log1pf_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/log1pf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/log2_test.cpp b/libc/test/src/math/smoke/log2_test.cpp index 826c51eb8c1b091043da1919bd0c7581c0fc3057..fbeba9527bcb7b3255b8397c8a5ea5e11a95840e 100644 --- a/libc/test/src/math/smoke/log2_test.cpp +++ b/libc/test/src/math/smoke/log2_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/log2.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/log2f_test.cpp b/libc/test/src/math/smoke/log2f_test.cpp index 2387ff59d70d9e6f447d569c97ee715863a5f494..46906e78dcaf71ea59160bceaf56e981aa60eebd 100644 --- a/libc/test/src/math/smoke/log2f_test.cpp +++ b/libc/test/src/math/smoke/log2f_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/log2f.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/log_test.cpp b/libc/test/src/math/smoke/log_test.cpp index 423b9d8bb818a79d296515478ad28f571545f28e..b1e39059948001a52c75377f6cccd2e32439c560 100644 --- a/libc/test/src/math/smoke/log_test.cpp +++ b/libc/test/src/math/smoke/log_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/log.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/logf_test.cpp b/libc/test/src/math/smoke/logf_test.cpp index 21b39ee6896dd253c5ae9a80bb53785811b0c3c2..97b6bdde307b3d67a6bade3d1d80249aca53a15b 100644 --- a/libc/test/src/math/smoke/logf_test.cpp +++ b/libc/test/src/math/smoke/logf_test.cpp @@ -6,11 +6,11 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/math/logf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/nanf128_test.cpp b/libc/test/src/math/smoke/nanf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a9f57de5b43bc0add7356de8bef7be22ddd1b12 --- /dev/null +++ b/libc/test/src/math/smoke/nanf128_test.cpp @@ -0,0 +1,60 @@ +//===-- Unittests for nanf128 ---------------------------------------------===// +// +// 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/FPBits.h" +#include "src/__support/UInt128.h" +#include "src/math/nanf128.h" +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +class LlvmLibcNanf128Test : public LIBC_NAMESPACE::testing::Test { +public: + using FPBits128 = LIBC_NAMESPACE::fputil::FPBits<float128>; + using StorageType = FPBits128::StorageType; + + const UInt128 QUIET_NAN = FPBits128::quiet_nan().uintval(); + const UInt128 ONE = UInt128(1); + + void run_test(const char *input_str, StorageType bits) { + float128 result = LIBC_NAMESPACE::nanf128(input_str); + auto actual_fp = FPBits128(result); + auto expected_fp = FPBits128(bits); + EXPECT_EQ(actual_fp.uintval(), expected_fp.uintval()); + }; +}; + +TEST_F(LlvmLibcNanf128Test, NCharSeq) { + run_test("", QUIET_NAN); + run_test("1234", QUIET_NAN | 1234); + run_test("0x1234", QUIET_NAN | 0x1234); + run_test("2417851639229258349412352", QUIET_NAN | (ONE << 81)); + run_test("0x200000000000000000000", QUIET_NAN | (ONE << 81)); + run_test("10384593717069655257060992658440191", + QUIET_NAN | FPBits128::SIG_MASK); + run_test("0x1ffffffffffffffffffffffffffff", QUIET_NAN | FPBits128::SIG_MASK); + run_test("10384593717069655257060992658440192", QUIET_NAN); + run_test("0x20000000000000000000000000000", QUIET_NAN); + run_test("1a", QUIET_NAN); + run_test("10000000000000000000000000000000000000000000000000", QUIET_NAN); +} + +TEST_F(LlvmLibcNanf128Test, RandomString) { + run_test(" 1234", QUIET_NAN); + run_test("-1234", QUIET_NAN); + run_test("asd&f", QUIET_NAN); + run_test("123 ", QUIET_NAN); + run_test("1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_", + QUIET_NAN); +} + +#ifndef LIBC_HAVE_ADDRESS_SANITIZER +#include <signal.h> +TEST_F(LlvmLibcNanf128Test, InvalidInput) { + EXPECT_DEATH([] { LIBC_NAMESPACE::nanf128(nullptr); }, WITH_SIGNAL(SIGSEGV)); +} +#endif // LIBC_HAVE_ADDRESS_SANITIZER diff --git a/libc/test/src/math/smoke/nextafterf128_test.cpp b/libc/test/src/math/smoke/nextafterf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a8d000ff4de3874039ffb65197f826d33d4b479e --- /dev/null +++ b/libc/test/src/math/smoke/nextafterf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for nextafterf128 ---------------------------------------===// +// +// 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 "NextAfterTest.h" + +#include "src/math/nextafterf128.h" + +LIST_NEXTAFTER_TESTS(float128, LIBC_NAMESPACE::nextafterf128) diff --git a/libc/test/src/math/smoke/nextdown_test.cpp b/libc/test/src/math/smoke/nextdown_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6b0f5c6c5a6aa6f8a95c43b943ac5171735bf4b7 --- /dev/null +++ b/libc/test/src/math/smoke/nextdown_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for nextdown --------------------------------------------===// +// +// 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 "NextDownTest.h" + +#include "src/math/nextdown.h" + +LIST_NEXTDOWN_TESTS(double, LIBC_NAMESPACE::nextdown) diff --git a/libc/test/src/math/smoke/nextdownf128_test.cpp b/libc/test/src/math/smoke/nextdownf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..932a8b36a59e477a8a02e7dfbba87c4ebc62572d --- /dev/null +++ b/libc/test/src/math/smoke/nextdownf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for nextdownf128 ----------------------------------------===// +// +// 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 "NextDownTest.h" + +#include "src/math/nextdownf128.h" + +LIST_NEXTDOWN_TESTS(float128, LIBC_NAMESPACE::nextdownf128) diff --git a/libc/test/src/math/smoke/nextdownf_test.cpp b/libc/test/src/math/smoke/nextdownf_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3c05c22d82049fa230015ba87d850e6c469ba16e --- /dev/null +++ b/libc/test/src/math/smoke/nextdownf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for nextdownf -------------------------------------------===// +// +// 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 "NextDownTest.h" + +#include "src/math/nextdownf.h" + +LIST_NEXTDOWN_TESTS(float, LIBC_NAMESPACE::nextdownf) diff --git a/libc/test/src/math/smoke/nextdownl_test.cpp b/libc/test/src/math/smoke/nextdownl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f1785eb58ce512e1353979e1a3947304319a739e --- /dev/null +++ b/libc/test/src/math/smoke/nextdownl_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for nextdownl -------------------------------------------===// +// +// 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 "NextDownTest.h" + +#include "src/math/nextdownl.h" + +LIST_NEXTDOWN_TESTS(long double, LIBC_NAMESPACE::nextdownl) diff --git a/libc/test/src/math/smoke/nextup_test.cpp b/libc/test/src/math/smoke/nextup_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..04c73ac9492f342b426d53e0222327f40b7fadd7 --- /dev/null +++ b/libc/test/src/math/smoke/nextup_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for nextup ----------------------------------------------===// +// +// 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 "NextUpTest.h" + +#include "src/math/nextup.h" + +LIST_NEXTUP_TESTS(double, LIBC_NAMESPACE::nextup) diff --git a/libc/test/src/math/smoke/nextupf128_test.cpp b/libc/test/src/math/smoke/nextupf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ddd385a7b159b4e3d4f30a38ca70f00bf49d2ee5 --- /dev/null +++ b/libc/test/src/math/smoke/nextupf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for nextupf128 ------------------------------------------===// +// +// 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 "NextUpTest.h" + +#include "src/math/nextupf128.h" + +LIST_NEXTUP_TESTS(float128, LIBC_NAMESPACE::nextupf128) diff --git a/libc/test/src/math/smoke/nextupf_test.cpp b/libc/test/src/math/smoke/nextupf_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..df73bee0117111de36d1229dd18f58979cedfe52 --- /dev/null +++ b/libc/test/src/math/smoke/nextupf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for nextupf ---------------------------------------------===// +// +// 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 "NextUpTest.h" + +#include "src/math/nextupf.h" + +LIST_NEXTUP_TESTS(float, LIBC_NAMESPACE::nextupf) diff --git a/libc/test/src/math/smoke/nextupl_test.cpp b/libc/test/src/math/smoke/nextupl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..50f765633c2a50663c5c508dc619136adc7c1f0f --- /dev/null +++ b/libc/test/src/math/smoke/nextupl_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for nextupl ---------------------------------------------===// +// +// 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 "NextUpTest.h" + +#include "src/math/nextupl.h" + +LIST_NEXTUP_TESTS(long double, LIBC_NAMESPACE::nextupl) diff --git a/libc/test/src/math/smoke/powf_test.cpp b/libc/test/src/math/smoke/powf_test.cpp index 1867dde0ac3beab46b35f21ef0942421d29e2080..e9de1554ec614856490438f2376324cc3cecfad4 100644 --- a/libc/test/src/math/smoke/powf_test.cpp +++ b/libc/test/src/math/smoke/powf_test.cpp @@ -6,11 +6,11 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/math/powf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/sincosf_test.cpp b/libc/test/src/math/smoke/sincosf_test.cpp index a1447ad57e116225c41ac8386953dd6ea22e7827..5952b20fc5bff3c0700061417d6b7394be4e1be6 100644 --- a/libc/test/src/math/smoke/sincosf_test.cpp +++ b/libc/test/src/math/smoke/sincosf_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/sincosf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/sinf_test.cpp b/libc/test/src/math/smoke/sinf_test.cpp index e51726646bc6869f133c537c8949cbe6a435de3a..94508950418742b1e6dd0738394092c8a16f2972 100644 --- a/libc/test/src/math/smoke/sinf_test.cpp +++ b/libc/test/src/math/smoke/sinf_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/sinf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/sinhf_test.cpp b/libc/test/src/math/smoke/sinhf_test.cpp index 23334293b73fe4bbbe66cbaaac6b79bc98dc6187..0f005f752e6982588f62559c6900b6e3373a1eca 100644 --- a/libc/test/src/math/smoke/sinhf_test.cpp +++ b/libc/test/src/math/smoke/sinhf_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/CPP/array.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/sinhf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/tanf_test.cpp b/libc/test/src/math/smoke/tanf_test.cpp index 53a153254b3111fc8ff3fa46e132b5c5c2bef880..68bf493f7e82272a6f26e502c658fc859bbe6fa7 100644 --- a/libc/test/src/math/smoke/tanf_test.cpp +++ b/libc/test/src/math/smoke/tanf_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/tanf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/tanhf_test.cpp b/libc/test/src/math/smoke/tanhf_test.cpp index 7cb80dca7919eb52c3bf21e4767b7bbddce5303f..f1ce8b40d43ac266be51e8acdcf6329dc249268b 100644 --- a/libc/test/src/math/smoke/tanhf_test.cpp +++ b/libc/test/src/math/smoke/tanhf_test.cpp @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/tanhf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/smoke/ufromfp_test.cpp b/libc/test/src/math/smoke/ufromfp_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff47621124006a73dff476ddd2fd7ef5021f5132 --- /dev/null +++ b/libc/test/src/math/smoke/ufromfp_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for ufromfp ---------------------------------------------===// +// +// 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 "UfromfpTest.h" + +#include "src/math/ufromfp.h" + +LIST_UFROMFP_TESTS(double, LIBC_NAMESPACE::ufromfp) diff --git a/libc/test/src/math/smoke/ufromfpf128_test.cpp b/libc/test/src/math/smoke/ufromfpf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9ba3034f6e61fde7d4640d9e0761e9791962beed --- /dev/null +++ b/libc/test/src/math/smoke/ufromfpf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for ufromfpf128 -----------------------------------------===// +// +// 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 "UfromfpTest.h" + +#include "src/math/ufromfpf128.h" + +LIST_UFROMFP_TESTS(float128, LIBC_NAMESPACE::ufromfpf128) diff --git a/libc/test/src/math/smoke/ufromfpf_test.cpp b/libc/test/src/math/smoke/ufromfpf_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2913b31e20bda3baee8df63647598834b3f2cc40 --- /dev/null +++ b/libc/test/src/math/smoke/ufromfpf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for ufromfpf --------------------------------------------===// +// +// 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 "UfromfpTest.h" + +#include "src/math/ufromfpf.h" + +LIST_UFROMFP_TESTS(float, LIBC_NAMESPACE::ufromfpf) diff --git a/libc/test/src/math/smoke/ufromfpl_test.cpp b/libc/test/src/math/smoke/ufromfpl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8976056756e45f8dc94231a0ca833907cc3749ed --- /dev/null +++ b/libc/test/src/math/smoke/ufromfpl_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for ufromfpl --------------------------------------------===// +// +// 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 "UfromfpTest.h" + +#include "src/math/ufromfpl.h" + +LIST_UFROMFP_TESTS(long double, LIBC_NAMESPACE::ufromfpl) diff --git a/libc/test/src/math/smoke/ufromfpx_test.cpp b/libc/test/src/math/smoke/ufromfpx_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3bb45e428f28668fe7e8378736e984e03d1ddfc5 --- /dev/null +++ b/libc/test/src/math/smoke/ufromfpx_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for ufromfpx --------------------------------------------===// +// +// 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 "UfromfpxTest.h" + +#include "src/math/ufromfpx.h" + +LIST_UFROMFPX_TESTS(double, LIBC_NAMESPACE::ufromfpx) diff --git a/libc/test/src/math/smoke/ufromfpxf128_test.cpp b/libc/test/src/math/smoke/ufromfpxf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6defaf7fee3dd0da165fe1964e50aa5388da0e89 --- /dev/null +++ b/libc/test/src/math/smoke/ufromfpxf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for ufromfpxf128 ----------------------------------------===// +// +// 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 "UfromfpxTest.h" + +#include "src/math/ufromfpxf128.h" + +LIST_UFROMFPX_TESTS(float128, LIBC_NAMESPACE::ufromfpxf128) diff --git a/libc/test/src/math/smoke/ufromfpxf_test.cpp b/libc/test/src/math/smoke/ufromfpxf_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..862fd4c2cdac65f914310626519b07cb9661f40f --- /dev/null +++ b/libc/test/src/math/smoke/ufromfpxf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for ufromfpxf -------------------------------------------===// +// +// 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 "UfromfpxTest.h" + +#include "src/math/ufromfpxf.h" + +LIST_UFROMFPX_TESTS(float, LIBC_NAMESPACE::ufromfpxf) diff --git a/libc/test/src/math/smoke/ufromfpxl_test.cpp b/libc/test/src/math/smoke/ufromfpxl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b6b93b38e6be2c69972ccf4bb6ab873a04d14910 --- /dev/null +++ b/libc/test/src/math/smoke/ufromfpxl_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for ufromfpxl -------------------------------------------===// +// +// 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 "UfromfpxTest.h" + +#include "src/math/ufromfpxl.h" + +LIST_UFROMFPX_TESTS(long double, LIBC_NAMESPACE::ufromfpxl) diff --git a/libc/test/src/math/tan_test.cpp b/libc/test/src/math/tan_test.cpp index 9cdc7c4abd32cca0681b6a5cb57f92f3d3da2e72..85174db9364e362c83d8a0d76ba610dbabd0b68b 100644 --- a/libc/test/src/math/tan_test.cpp +++ b/libc/test/src/math/tan_test.cpp @@ -11,7 +11,7 @@ #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" using LlvmLibcTanTest = LIBC_NAMESPACE::testing::FPTest<double>; diff --git a/libc/test/src/math/tanf_test.cpp b/libc/test/src/math/tanf_test.cpp index c8d9d52e3f695446222175360cffeda8ab10f8be..d40bc44d6442f912df1d33b3553010028ffa2c00 100644 --- a/libc/test/src/math/tanf_test.cpp +++ b/libc/test/src/math/tanf_test.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/tanf.h" @@ -13,7 +14,6 @@ #include "test/UnitTest/Test.h" #include "test/src/math/sdcomp26094.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/math/tanhf_test.cpp b/libc/test/src/math/tanhf_test.cpp index 28da7ffbeddd1883869d62a0f98a0f37b5ed9a5e..ef272b17d68cad132881c46bece2594aeeb4a74c 100644 --- a/libc/test/src/math/tanhf_test.cpp +++ b/libc/test/src/math/tanhf_test.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "include/llvm-libc-macros/math-macros.h" #include "src/__support/FPUtil/FPBits.h" #include "src/errno/libc_errno.h" #include "src/math/tanhf.h" #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" #include "utils/MPFRWrapper/MPFRUtils.h" -#include <math.h> #include <errno.h> #include <stdint.h> diff --git a/libc/test/src/stdio/CMakeLists.txt b/libc/test/src/stdio/CMakeLists.txt index 6e1c86e070a8238914370cdd339e37a1811b8a1e..03c43eaefebe5e668fa93f834bd718805a44626d 100644 --- a/libc/test/src/stdio/CMakeLists.txt +++ b/libc/test/src/stdio/CMakeLists.txt @@ -14,6 +14,7 @@ add_libc_test( libc.src.stdio.feof libc.src.stdio.ferror libc.src.stdio.fflush + libc.src.stdio.fileno libc.src.stdio.fopen libc.src.stdio.fputs libc.src.stdio.fread @@ -353,6 +354,21 @@ if(${LIBC_TARGET_OS} STREQUAL "linux") libc.src.unistd.access libc.src.unistd.close ) + + add_libc_test( + rename_test + SUITE + libc_stdio_unittests + SRCS + rename_test.cpp + DEPENDS + libc.src.errno.errno + libc.src.fcntl.open + libc.src.stdio.rename + libc.src.unistd.access + libc.src.unistd.close + libc.test.UnitTest.ErrnoSetterMatcher + ) endif() add_libc_test( @@ -426,6 +442,8 @@ add_libc_test( libc.src.stdio.fread libc.src.stdio.fseek libc.src.stdio.ftell + libc.src.stdio.fseeko + libc.src.stdio.ftello libc.src.stdio.fwrite libc.src.stdio.setvbuf ) diff --git a/libc/test/src/stdio/fileop_test.cpp b/libc/test/src/stdio/fileop_test.cpp index f5dbc49818390d47f50df32ce7d7e9be723cb1e9..0fbe19cf08d837080252a06ce1a02c436c720546 100644 --- a/libc/test/src/stdio/fileop_test.cpp +++ b/libc/test/src/stdio/fileop_test.cpp @@ -11,6 +11,7 @@ #include "src/stdio/feof.h" #include "src/stdio/ferror.h" #include "src/stdio/fflush.h" +#include "src/stdio/fileno.h" #include "src/stdio/fopen.h" #include "src/stdio/fputs.h" #include "src/stdio/fread.h" @@ -30,6 +31,7 @@ TEST(LlvmLibcFILETest, SimpleFileOperations) { constexpr char FILENAME[] = "testdata/simple_operations.test"; ::FILE *file = LIBC_NAMESPACE::fopen(FILENAME, "w"); ASSERT_FALSE(file == nullptr); + ASSERT_EQ(LIBC_NAMESPACE::fileno(file), 3); constexpr char CONTENT[] = "1234567890987654321"; ASSERT_EQ(sizeof(CONTENT) - 1, LIBC_NAMESPACE::fwrite(CONTENT, 1, sizeof(CONTENT) - 1, file)); diff --git a/libc/test/src/stdio/ftell_test.cpp b/libc/test/src/stdio/ftell_test.cpp index 61b626f53cd26ec2aca6436743a2179ce4546bee..62745e2194be6d30b5715cbb743f98e73a2d5330 100644 --- a/libc/test/src/stdio/ftell_test.cpp +++ b/libc/test/src/stdio/ftell_test.cpp @@ -10,7 +10,9 @@ #include "src/stdio/fopen.h" #include "src/stdio/fread.h" #include "src/stdio/fseek.h" +#include "src/stdio/fseeko.h" #include "src/stdio/ftell.h" +#include "src/stdio/ftello.h" #include "src/stdio/fwrite.h" #include "src/stdio/setvbuf.h" #include "test/UnitTest/Test.h" @@ -37,6 +39,13 @@ protected: // still return the correct effective offset. ASSERT_EQ(size_t(LIBC_NAMESPACE::ftell(file)), WRITE_SIZE); + off_t offseto = 5; + ASSERT_EQ(0, LIBC_NAMESPACE::fseeko(file, offseto, SEEK_SET)); + ASSERT_EQ(LIBC_NAMESPACE::ftello(file), offseto); + ASSERT_EQ(0, LIBC_NAMESPACE::fseeko(file, -offseto, SEEK_END)); + ASSERT_EQ(size_t(LIBC_NAMESPACE::ftello(file)), + size_t(WRITE_SIZE - offseto)); + long offset = 5; ASSERT_EQ(0, LIBC_NAMESPACE::fseek(file, offset, SEEK_SET)); ASSERT_EQ(LIBC_NAMESPACE::ftell(file), offset); diff --git a/libc/test/src/stdio/printf_core/parser_test.cpp b/libc/test/src/stdio/printf_core/parser_test.cpp index 0134277c4a1b2dde9c7fbcea1fdb3e80bcaa9a1a..66d6dd0a86c422822b6d24e1dd85075e454d3ba2 100644 --- a/libc/test/src/stdio/printf_core/parser_test.cpp +++ b/libc/test/src/stdio/printf_core/parser_test.cpp @@ -223,6 +223,42 @@ TEST(LlvmLibcPrintfParserTest, EvalOneArgWithLongLengthModifier) { ASSERT_PFORMAT_EQ(expected, format_arr[0]); } +TEST(LlvmLibcPrintfParserTest, EvalOneArgWithBitWidthLengthModifier) { + LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; + const char *str = "%w32d"; + long long arg1 = 12345; + evaluate(format_arr, str, arg1); + + LIBC_NAMESPACE::printf_core::FormatSection expected; + expected.has_conv = true; + + expected.raw_string = {str, 5}; + expected.length_modifier = LIBC_NAMESPACE::printf_core::LengthModifier::w; + expected.bit_width = 32; + expected.conv_val_raw = arg1; + expected.conv_name = 'd'; + + ASSERT_PFORMAT_EQ(expected, format_arr[0]); +} + +TEST(LlvmLibcPrintfParserTest, EvalOneArgWithFastBitWidthLengthModifier) { + LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; + const char *str = "%wf32d"; + long long arg1 = 12345; + evaluate(format_arr, str, arg1); + + LIBC_NAMESPACE::printf_core::FormatSection expected; + expected.has_conv = true; + + expected.raw_string = {str, 6}; + expected.length_modifier = LIBC_NAMESPACE::printf_core::LengthModifier::wf; + expected.bit_width = 32; + expected.conv_val_raw = arg1; + expected.conv_name = 'd'; + + ASSERT_PFORMAT_EQ(expected, format_arr[0]); +} + TEST(LlvmLibcPrintfParserTest, EvalOneArgWithAllOptions) { LIBC_NAMESPACE::printf_core::FormatSection format_arr[10]; const char *str = "% -056.78jd"; diff --git a/libc/test/src/stdio/rename_test.cpp b/libc/test/src/stdio/rename_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a5dd734c63616950f2aff284a06360296d614188 --- /dev/null +++ b/libc/test/src/stdio/rename_test.cpp @@ -0,0 +1,51 @@ +//===-- Unittests for rename ----------------------------------------------===// +// +// 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/linux/sys-stat-macros.h" +#include "include/llvm-libc-macros/linux/unistd-macros.h" +#include "src/errno/libc_errno.h" +#include "src/fcntl/open.h" +#include "src/stdio/rename.h" +#include "src/unistd/access.h" +#include "src/unistd/close.h" +#include "test/UnitTest/ErrnoSetterMatcher.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcRenameTest, CreateAndRenameFile) { + // The test strategy is to create a file and rename it, and also verify that + // it was renamed. + LIBC_NAMESPACE::libc_errno = 0; + using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; + using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; + + constexpr const char *FILENAME0 = "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); + ASSERT_ERRNO_SUCCESS(); + ASSERT_GT(fd, 0); + 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"; + auto TEST_FILEPATH1 = libc_make_test_file_path(FILENAME1); + ASSERT_THAT(LIBC_NAMESPACE::rename(TEST_FILEPATH0, TEST_FILEPATH1), + Succeeds(0)); + ASSERT_THAT(LIBC_NAMESPACE::access(TEST_FILEPATH1, F_OK), Succeeds(0)); + ASSERT_THAT(LIBC_NAMESPACE::access(TEST_FILEPATH0, F_OK), Fails(ENOENT)); +} + +TEST(LlvmLibcRenameTest, RenameNonExistent) { + using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; + + constexpr const char *FILENAME1 = "rename.test.file1"; + auto TEST_FILEPATH1 = libc_make_test_file_path(FILENAME1); + + ASSERT_THAT(LIBC_NAMESPACE::rename("non-existent", TEST_FILEPATH1), + Fails(ENOENT)); +} diff --git a/libc/test/src/stdio/sprintf_test.cpp b/libc/test/src/stdio/sprintf_test.cpp index ab8bdb23b1187c30bf5c7277a543c92e95a26007..8e9870f71a95952796423f0f73855ac21a5ac56c 100644 --- a/libc/test/src/stdio/sprintf_test.cpp +++ b/libc/test/src/stdio/sprintf_test.cpp @@ -121,8 +121,8 @@ TEST(LlvmLibcSPrintfTest, StringConv) { #ifndef LIBC_COPT_PRINTF_NO_NULLPTR_CHECKS written = LIBC_NAMESPACE::sprintf(buff, "%s", nullptr); - EXPECT_EQ(written, 4); - ASSERT_STREQ(buff, "null"); + EXPECT_EQ(written, 6); + ASSERT_STREQ(buff, "(null)"); #endif // LIBC_COPT_PRINTF_NO_NULLPTR_CHECKS } @@ -169,6 +169,93 @@ TEST(LlvmLibcSPrintfTest, IntConv) { EXPECT_EQ(written, 20); ASSERT_STREQ(buff, "-9223372036854775808"); // ll min + written = LIBC_NAMESPACE::sprintf(buff, "%w3d", 5807); + EXPECT_EQ(written, 1); + ASSERT_STREQ(buff, "7"); + + written = LIBC_NAMESPACE::sprintf(buff, "%w3d", 1); + EXPECT_EQ(written, 1); + ASSERT_STREQ(buff, "1"); + + written = LIBC_NAMESPACE::sprintf(buff, "%w64d", 9223372036854775807ll); + EXPECT_EQ(written, 19); + ASSERT_STREQ(buff, "9223372036854775807"); + + written = LIBC_NAMESPACE::sprintf(buff, "%w-1d", 5807); + EXPECT_EQ(written, 5); + ASSERT_STREQ(buff, "%w-1d"); + + written = LIBC_NAMESPACE::sprintf(buff, "%w0d", 5807); + EXPECT_EQ(written, 4); + ASSERT_STREQ(buff, "%w0d"); + + written = LIBC_NAMESPACE::sprintf(buff, "%w999d", 9223372036854775807ll); + EXPECT_EQ(written, 19); + ASSERT_STREQ(buff, "9223372036854775807"); + + written = LIBC_NAMESPACE::sprintf(buff, "%winvalid%w1d", 5807, 5807); + EXPECT_EQ(written, 10); + ASSERT_STREQ(buff, "%winvalid1"); + + written = LIBC_NAMESPACE::sprintf(buff, "%w-1d%w1d", 5807, 5807); + EXPECT_EQ(written, 6); + ASSERT_STREQ(buff, "%w-1d1"); + + char format[64]; + char uintmax[128]; + LIBC_NAMESPACE::sprintf(format, "%%w%du", sizeof(uintmax_t) * CHAR_BIT); + const int uintmax_len = + LIBC_NAMESPACE::sprintf(uintmax, "%ju", sizeof(uintmax_t) * CHAR_BIT); + written = LIBC_NAMESPACE::sprintf(buff, format, sizeof(uintmax_t) * CHAR_BIT); + EXPECT_EQ(written, uintmax_len); + ASSERT_STREQ(buff, uintmax); + + written = LIBC_NAMESPACE::sprintf(buff, "%w64u", 18446744073709551615ull); + EXPECT_EQ(written, 20); + ASSERT_STREQ(buff, "18446744073709551615"); // ull max + + written = + LIBC_NAMESPACE::sprintf(buff, "%w64d", -9223372036854775807ll - 1ll); + EXPECT_EQ(written, 20); + ASSERT_STREQ(buff, "-9223372036854775808"); // ll min + + written = LIBC_NAMESPACE::sprintf(buff, "%wf3d", 5807); + EXPECT_EQ(written, 1); + ASSERT_STREQ(buff, "7"); + + written = LIBC_NAMESPACE::sprintf(buff, "%wf3d", 1); + EXPECT_EQ(written, 1); + ASSERT_STREQ(buff, "1"); + + written = LIBC_NAMESPACE::sprintf(buff, "%wf64u", 18446744073709551615ull); + EXPECT_EQ(written, 20); + ASSERT_STREQ(buff, "18446744073709551615"); // ull max + + written = + LIBC_NAMESPACE::sprintf(buff, "%wf64d", -9223372036854775807ll - 1ll); + EXPECT_EQ(written, 20); + ASSERT_STREQ(buff, "-9223372036854775808"); // ll min + + written = LIBC_NAMESPACE::sprintf(buff, "%wf0d", 5807); + EXPECT_EQ(written, 5); + ASSERT_STREQ(buff, "%wf0d"); + + written = LIBC_NAMESPACE::sprintf(buff, "%wf-1d", 5807); + EXPECT_EQ(written, 6); + ASSERT_STREQ(buff, "%wf-1d"); + + written = LIBC_NAMESPACE::sprintf(buff, "%wfinvalid%wf1d", 5807, 5807); + EXPECT_EQ(written, 11); + ASSERT_STREQ(buff, "%wfinvalid1"); + + written = LIBC_NAMESPACE::sprintf(buff, "%wf-1d%wf1d", 5807, 5807); + EXPECT_EQ(written, 7); + ASSERT_STREQ(buff, "%wf-1d1"); + + written = LIBC_NAMESPACE::sprintf(buff, "%wf999d", 9223372036854775807ll); + EXPECT_EQ(written, 19); + ASSERT_STREQ(buff, "9223372036854775807"); + // Min Width Tests. written = LIBC_NAMESPACE::sprintf(buff, "%4d", 789); diff --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt index 5488a61c4ef1879b93ceccb33feeeaa8c2a15fd9..28c5b566cc4772278795487a8eb74d9b575b59dc 100644 --- a/libc/test/src/stdlib/CMakeLists.txt +++ b/libc/test/src/stdlib/CMakeLists.txt @@ -168,6 +168,48 @@ add_libc_test( .strtol_test_support ) +add_header_library( + strfrom_test_support + HDRS + StrfromTest.h + DEPENDS + libc.src.__support.CPP.type_traits + libc.src.__support.FPUtil.fp_bits +) + +add_libc_test( + strfromf_test + SUITE + libc-stdlib-tests + SRCS + strfromf_test.cpp + DEPENDS + .strfrom_test_support + libc.src.stdlib.strfromf +) + +add_libc_test( + strfromd_test + SUITE + libc-stdlib-tests + SRCS + strfromd_test.cpp + DEPENDS + .strfrom_test_support + libc.src.stdlib.strfromd +) + +add_libc_test( + strfroml_test + SUITE + libc-stdlib-tests + SRCS + strfroml_test.cpp + DEPENDS + .strfrom_test_support + libc.src.stdlib.strfroml +) + add_libc_test( abs_test SUITE @@ -259,7 +301,6 @@ add_libc_test( libc.src.stdlib.qsort ) - add_libc_test( qsort_r_test SUITE diff --git a/libc/test/src/stdlib/StrfromTest.h b/libc/test/src/stdlib/StrfromTest.h new file mode 100644 index 0000000000000000000000000000000000000000..0db507ef0716e96a23e4b904352a436582abbd97 --- /dev/null +++ b/libc/test/src/stdlib/StrfromTest.h @@ -0,0 +1,500 @@ +//===-- A template class for testing strfrom functions ----------*- 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 "src/__support/CPP/type_traits.h" +#include "src/__support/FPUtil/FPBits.h" +#include "test/UnitTest/Test.h" + +#define ASSERT_STREQ_LEN(actual_written, actual_str, expected_str) \ + EXPECT_EQ(actual_written, static_cast<int>(sizeof(expected_str) - 1)); \ + EXPECT_STREQ(actual_str, expected_str); + +template <typename InputT> +class StrfromTest : public LIBC_NAMESPACE::testing::Test { + + static const bool is_single_prec = + LIBC_NAMESPACE::cpp::is_same<InputT, float>::value; + static const bool is_double_prec = + LIBC_NAMESPACE::cpp::is_same<InputT, double>::value; + + using FunctionT = int (*)(char *, size_t, const char *, InputT fp); + +public: + void floatDecimalFormat(FunctionT func) { + if (is_single_prec) + floatDecimalSinglePrec(func); + else if (is_double_prec) + floatDecimalDoublePrec(func); + else + floatDecimalLongDoublePrec(func); + } + + void floatHexExpFormat(FunctionT func) { + if (is_single_prec) + floatHexExpSinglePrec(func); + else if (is_double_prec) + floatHexExpDoublePrec(func); + else + floatHexExpLongDoublePrec(func); + } + + void floatDecimalExpFormat(FunctionT func) { + if (is_single_prec) + floatDecimalExpSinglePrec(func); + else if (is_double_prec) + floatDecimalExpDoublePrec(func); + else + floatDecimalExpLongDoublePrec(func); + } + + void floatDecimalAutoFormat(FunctionT func) { + if (is_single_prec) + floatDecimalAutoSinglePrec(func); + else if (is_double_prec) + floatDecimalAutoDoublePrec(func); + else + floatDecimalAutoLongDoublePrec(func); + } + + void improperFormatString(FunctionT func) { + char buff[100]; + int written; + const bool is_long_double = !is_single_prec && !is_double_prec; + + written = func(buff, 37, "A simple string with no conversions.", 1.0); + ASSERT_STREQ_LEN(written, buff, "A simple string with no conversions."); + + written = + func(buff, 37, + "%A simple string with one conversion, should overwrite.", 1.0); + if (is_long_double) { +#if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80) + ASSERT_STREQ_LEN(written, buff, "0X8P-3"); +#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64) + ASSERT_STREQ_LEN(written, buff, "0X1P+0"); +#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128) + ASSERT_STREQ_LEN(written, buff, "0X1P+0"); +#endif + } else { + // not long double + ASSERT_STREQ_LEN(written, buff, "0X1P+0"); + } + written = func(buff, 74, + "A simple string with one conversion in %A " + "between, writes string as it is", + 1.0); + ASSERT_STREQ_LEN(written, buff, + "A simple string with one conversion in %A between, " + "writes string as it is"); + + written = func(buff, 36, "A simple string with one conversion", 1.0); + ASSERT_STREQ_LEN(written, buff, "A simple string with one conversion"); + + written = func(buff, 20, "%1f", 1234567890.0); + ASSERT_STREQ_LEN(written, buff, "%1f"); + } + + void insufficentBufsize(FunctionT func) { + char buff[20]; + int written; + + written = func(buff, 5, "%f", 1234567890.0); + EXPECT_EQ(written, 17); + ASSERT_STREQ(buff, "1234"); + + written = func(buff, 5, "%.5f", 1.05); + EXPECT_EQ(written, 7); + ASSERT_STREQ(buff, "1.05"); + + written = func(buff, 0, "%g", 1.0); + EXPECT_EQ(written, 1); + ASSERT_STREQ(buff, "1.05"); // Make sure that buff has not changed + } + + void infNanValues(FunctionT func) { + if (is_double_prec) + doublePrecInfNan(func); + else if (!is_single_prec) + longDoublePrecInfNan(func); + } + + void floatDecimalSinglePrec(FunctionT func) { + char buff[70]; + int written; + + written = func(buff, 16, "%f", 1.0); + ASSERT_STREQ_LEN(written, buff, "1.000000"); + + written = func(buff, 20, "%f", 1234567890.0); + ASSERT_STREQ_LEN(written, buff, "1234567936.000000"); + + written = func(buff, 67, "%.3f", 1.0); + ASSERT_STREQ_LEN(written, buff, "1.000"); + } + + void floatDecimalDoublePrec(FunctionT func) { + char buff[500]; + int written; + + written = func(buff, 99, "%f", 1.0); + ASSERT_STREQ_LEN(written, buff, "1.000000"); + + written = func(buff, 99, "%F", -1.0); + ASSERT_STREQ_LEN(written, buff, "-1.000000"); + + written = func(buff, 99, "%f", -1.234567); + ASSERT_STREQ_LEN(written, buff, "-1.234567"); + + written = func(buff, 99, "%f", 0.0); + ASSERT_STREQ_LEN(written, buff, "0.000000"); + + written = func(buff, 99, "%f", 1.5); + ASSERT_STREQ_LEN(written, buff, "1.500000"); + + written = func(buff, 499, "%f", 1e300); + ASSERT_STREQ_LEN(written, buff, + "100000000000000005250476025520442024870446858110815915491" + "585411551180245" + "798890819578637137508044786404370444383288387817694252323" + "536043057564479" + "218478670698284838720092657580373783023379478809005936895" + "323497079994508" + "111903896764088007465274278014249457925878882005684283811" + "566947219638686" + "5459400540160.000000"); + + written = func(buff, 99, "%f", 0.1); + ASSERT_STREQ_LEN(written, buff, "0.100000"); + + written = func(buff, 99, "%f", 1234567890123456789.0); + ASSERT_STREQ_LEN(written, buff, "1234567890123456768.000000"); + + written = func(buff, 99, "%f", 9999999999999.99); + ASSERT_STREQ_LEN(written, buff, "9999999999999.990234"); + + written = func(buff, 99, "%f", 0.1); + ASSERT_STREQ_LEN(written, buff, "0.100000"); + + written = func(buff, 99, "%f", 1234567890123456789.0); + ASSERT_STREQ_LEN(written, buff, "1234567890123456768.000000"); + + written = func(buff, 99, "%f", 9999999999999.99); + ASSERT_STREQ_LEN(written, buff, "9999999999999.990234"); + + // Precision Tests + written = func(buff, 100, "%.2f", 9999999999999.99); + ASSERT_STREQ_LEN(written, buff, "9999999999999.99"); + + written = func(buff, 100, "%.1f", 9999999999999.99); + ASSERT_STREQ_LEN(written, buff, "10000000000000.0"); + + written = func(buff, 100, "%.5f", 1.25); + ASSERT_STREQ_LEN(written, buff, "1.25000"); + + written = func(buff, 100, "%.0f", 1.25); + ASSERT_STREQ_LEN(written, buff, "1"); + + written = func(buff, 100, "%.20f", 1.234e-10); + ASSERT_STREQ_LEN(written, buff, "0.00000000012340000000"); + } + + void floatDecimalLongDoublePrec(FunctionT func) { + char buff[45]; + int written; + + written = func(buff, 40, "%f", 1.0L); + ASSERT_STREQ_LEN(written, buff, "1.000000"); + + written = func(buff, 10, "%.f", -2.5L); + ASSERT_STREQ_LEN(written, buff, "-2"); + } + + void floatHexExpSinglePrec(FunctionT func) { + char buff[25]; + int written; + + written = func(buff, 0, "%a", 1234567890.0); + EXPECT_EQ(written, 14); + + written = func(buff, 20, "%a", 1234567890.0); + EXPECT_EQ(written, 14); + ASSERT_STREQ(buff, "0x1.26580cp+30"); + + written = func(buff, 20, "%A", 1234567890.0); + EXPECT_EQ(written, 14); + ASSERT_STREQ(buff, "0X1.26580CP+30"); + } + + void floatHexExpDoublePrec(FunctionT func) { + char buff[60]; + int written; + + written = func(buff, 10, "%a", 1.0); + ASSERT_STREQ_LEN(written, buff, "0x1p+0"); + + written = func(buff, 10, "%A", -1.0); + ASSERT_STREQ_LEN(written, buff, "-0X1P+0"); + + written = func(buff, 30, "%a", -0x1.abcdef12345p0); + ASSERT_STREQ_LEN(written, buff, "-0x1.abcdef12345p+0"); + + written = func(buff, 50, "%A", 0x1.abcdef12345p0); + ASSERT_STREQ_LEN(written, buff, "0X1.ABCDEF12345P+0"); + + written = func(buff, 10, "%a", 0.0); + ASSERT_STREQ_LEN(written, buff, "0x0p+0"); + + written = func(buff, 40, "%a", 1.0e100); + ASSERT_STREQ_LEN(written, buff, "0x1.249ad2594c37dp+332"); + + written = func(buff, 30, "%a", 0.1); + ASSERT_STREQ_LEN(written, buff, "0x1.999999999999ap-4"); + } + + void floatHexExpLongDoublePrec(FunctionT func) { + char buff[55]; + int written; + + written = func(buff, 50, "%a", 0.1L); +#if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80) + ASSERT_STREQ_LEN(written, buff, "0xc.ccccccccccccccdp-7"); +#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64) + ASSERT_STREQ_LEN(written, buff, "0x1.999999999999ap-4"); +#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128) + ASSERT_STREQ_LEN(written, buff, "0x1.999999999999999999999999999ap-4"); +#endif + + written = func(buff, 20, "%.1a", 0.1L); +#if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80) + ASSERT_STREQ_LEN(written, buff, "0xc.dp-7"); +#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64) + ASSERT_STREQ_LEN(written, buff, "0x1.ap-4"); +#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128) + ASSERT_STREQ_LEN(written, buff, "0x1.ap-4"); +#endif + + written = func(buff, 50, "%a", 1.0e1000L); +#if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80) + ASSERT_STREQ_LEN(written, buff, "0xf.38db1f9dd3dac05p+3318"); +#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64) + ASSERT_STREQ_LEN(written, buff, "inf"); +#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128) + ASSERT_STREQ_LEN(written, buff, "0x1.e71b63f3ba7b580af1a52d2a7379p+3321"); +#endif + + written = func(buff, 50, "%a", 1.0e-1000L); +#if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80) + ASSERT_STREQ_LEN(written, buff, "0x8.68a9188a89e1467p-3325"); +#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64) + ASSERT_STREQ_LEN(written, buff, "0x0p+0"); +#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128) + ASSERT_STREQ_LEN(written, buff, "0x1.0d152311513c28ce202627c06ec2p-3322"); +#endif + + written = func(buff, 50, "%.1a", 0xf.fffffffffffffffp16380L); +#if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80) + ASSERT_STREQ_LEN(written, buff, "0x1.0p+16384"); +#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64) + ASSERT_STREQ_LEN(written, buff, "inf"); +#elif defined(LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128) + ASSERT_STREQ_LEN(written, buff, "0x2.0p+16383"); +#endif + } + + void floatDecimalExpSinglePrec(FunctionT func) { + char buff[25]; + int written; + + written = func(buff, 20, "%.9e", 1234567890.0); + ASSERT_STREQ_LEN(written, buff, "1.234567936e+09"); + + written = func(buff, 20, "%.9E", 1234567890.0); + ASSERT_STREQ_LEN(written, buff, "1.234567936E+09"); + } + + void floatDecimalExpDoublePrec(FunctionT func) { + char buff[101]; + int written; + + written = func(buff, 100, "%e", 1.0); + ASSERT_STREQ_LEN(written, buff, "1.000000e+00"); + + written = func(buff, 100, "%E", -1.0); + ASSERT_STREQ_LEN(written, buff, "-1.000000E+00"); + + written = func(buff, 100, "%e", -1.234567); + ASSERT_STREQ_LEN(written, buff, "-1.234567e+00"); + + written = func(buff, 100, "%e", 0.0); + ASSERT_STREQ_LEN(written, buff, "0.000000e+00"); + + written = func(buff, 100, "%e", 1.5); + ASSERT_STREQ_LEN(written, buff, "1.500000e+00"); + + written = func(buff, 100, "%e", 1e300); + ASSERT_STREQ_LEN(written, buff, "1.000000e+300"); + + written = func(buff, 100, "%e", 1234567890123456789.0); + ASSERT_STREQ_LEN(written, buff, "1.234568e+18"); + + // Precision Tests + written = func(buff, 100, "%.1e", 1.0); + ASSERT_STREQ_LEN(written, buff, "1.0e+00"); + + written = func(buff, 100, "%.1e", 1.99); + ASSERT_STREQ_LEN(written, buff, "2.0e+00"); + + written = func(buff, 100, "%.1e", 9.99); + ASSERT_STREQ_LEN(written, buff, "1.0e+01"); + } + + void floatDecimalExpLongDoublePrec(FunctionT func) { + // Mark as maybe_unused to silence unused variable + // warning when long double is not 80-bit + [[maybe_unused]] char buff[100]; + [[maybe_unused]] int written; + +#if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80) + written = func(buff, 90, "%.9e", 1000000000500000000.1L); + ASSERT_STREQ_LEN(written, buff, "1.000000001e+18"); + + written = func(buff, 90, "%.9e", 1000000000500000000.0L); + ASSERT_STREQ_LEN(written, buff, "1.000000000e+18"); + + written = func(buff, 90, "%e", 0xf.fffffffffffffffp+16380L); + ASSERT_STREQ_LEN(written, buff, "1.189731e+4932"); +#endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80 + } + + void floatDecimalAutoSinglePrec(FunctionT func) { + char buff[25]; + int written; + + written = func(buff, 20, "%.9g", 1234567890.0); + ASSERT_STREQ_LEN(written, buff, "1.23456794e+09"); + + written = func(buff, 20, "%.9G", 1234567890.0); + ASSERT_STREQ_LEN(written, buff, "1.23456794E+09"); + } + + void floatDecimalAutoDoublePrec(FunctionT func) { + char buff[120]; + int written; + + written = func(buff, 100, "%g", 1234567890123456789.0); + ASSERT_STREQ_LEN(written, buff, "1.23457e+18"); + + written = func(buff, 100, "%g", 9999990000000.00); + ASSERT_STREQ_LEN(written, buff, "9.99999e+12"); + + written = func(buff, 100, "%g", 9999999000000.00); + ASSERT_STREQ_LEN(written, buff, "1e+13"); + + written = func(buff, 100, "%g", 0xa.aaaaaaaaaaaaaabp-7); + ASSERT_STREQ_LEN(written, buff, "0.0833333"); + + written = func(buff, 100, "%g", 0.00001); + ASSERT_STREQ_LEN(written, buff, "1e-05"); + + // Precision Tests + written = func(buff, 100, "%.0g", 0.0); + ASSERT_STREQ_LEN(written, buff, "0"); + + written = func(buff, 100, "%.2g", 0.1); + ASSERT_STREQ_LEN(written, buff, "0.1"); + + written = func(buff, 100, "%.2g", 1.09); + ASSERT_STREQ_LEN(written, buff, "1.1"); + + written = func(buff, 100, "%.15g", 22.25); + ASSERT_STREQ_LEN(written, buff, "22.25"); + + written = func(buff, 100, "%.20g", 1.234e-10); + ASSERT_STREQ_LEN(written, buff, "1.2340000000000000814e-10"); + } + + void floatDecimalAutoLongDoublePrec(FunctionT func) { + // Mark as maybe_unused to silence unused variable + // warning when long double is not 80-bit + [[maybe_unused]] char buff[100]; + [[maybe_unused]] int written; + +#if defined(LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80) + written = func(buff, 99, "%g", 0xf.fffffffffffffffp+16380L); + ASSERT_STREQ_LEN(written, buff, "1.18973e+4932"); + + written = func(buff, 99, "%g", 0xa.aaaaaaaaaaaaaabp-7L); + ASSERT_STREQ_LEN(written, buff, "0.0833333"); + + written = func(buff, 99, "%g", 9.99999999999e-100L); + ASSERT_STREQ_LEN(written, buff, "1e-99"); +#endif // LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80 + } + + void doublePrecInfNan(FunctionT func) { + char buff[15]; + int written; + + double inf = LIBC_NAMESPACE::fputil::FPBits<double>::inf().get_val(); + double nan = LIBC_NAMESPACE::fputil::FPBits<double>::quiet_nan().get_val(); + + written = func(buff, 10, "%f", inf); + ASSERT_STREQ_LEN(written, buff, "inf"); + + written = func(buff, 10, "%A", -inf); + ASSERT_STREQ_LEN(written, buff, "-INF"); + + written = func(buff, 10, "%f", nan); + ASSERT_STREQ_LEN(written, buff, "nan"); + + written = func(buff, 10, "%A", -nan); + ASSERT_STREQ_LEN(written, buff, "-NAN"); + } + + void longDoublePrecInfNan(FunctionT func) { + char buff[15]; + int written; + + long double ld_inf = + LIBC_NAMESPACE::fputil::FPBits<long double>::inf().get_val(); + long double ld_nan = + LIBC_NAMESPACE::fputil::FPBits<long double>::quiet_nan().get_val(); + + written = func(buff, 10, "%f", ld_inf); + ASSERT_STREQ_LEN(written, buff, "inf"); + + written = func(buff, 10, "%A", -ld_inf); + ASSERT_STREQ_LEN(written, buff, "-INF"); + + written = func(buff, 10, "%f", ld_nan); + ASSERT_STREQ_LEN(written, buff, "nan"); + + written = func(buff, 10, "%A", -ld_nan); + ASSERT_STREQ_LEN(written, buff, "-NAN"); + } +}; + +#define STRFROM_TEST(InputType, name, func) \ + using LlvmLibc##name##Test = StrfromTest<InputType>; \ + TEST_F(LlvmLibc##name##Test, FloatDecimalFormat) { \ + floatDecimalFormat(func); \ + } \ + TEST_F(LlvmLibc##name##Test, FloatHexExpFormat) { floatHexExpFormat(func); } \ + TEST_F(LlvmLibc##name##Test, FloatDecimalAutoFormat) { \ + floatDecimalAutoFormat(func); \ + } \ + TEST_F(LlvmLibc##name##Test, FloatDecimalExpFormat) { \ + floatDecimalExpFormat(func); \ + } \ + TEST_F(LlvmLibc##name##Test, ImproperFormatString) { \ + improperFormatString(func); \ + } \ + TEST_F(LlvmLibc##name##Test, InsufficientBufferSize) { \ + insufficentBufsize(func); \ + } \ + TEST_F(LlvmLibc##name##Test, InfAndNanValues) { infNanValues(func); } diff --git a/libc/test/src/stdlib/strfromd_test.cpp b/libc/test/src/stdlib/strfromd_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..55724d7e902b5c08eac096a491a23d469f980fff --- /dev/null +++ b/libc/test/src/stdlib/strfromd_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for strfromd --------------------------------------------===// +// +// 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 "StrfromTest.h" +#include "src/stdlib/strfromd.h" +#include "test/UnitTest/Test.h" + +STRFROM_TEST(double, Strfromd, LIBC_NAMESPACE::strfromd) diff --git a/libc/test/src/stdlib/strfromf_test.cpp b/libc/test/src/stdlib/strfromf_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b987fd434ac54542809195d52dedf8b2acf3aea --- /dev/null +++ b/libc/test/src/stdlib/strfromf_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for strfromf --------------------------------------------===// +// +// 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 "StrfromTest.h" +#include "src/stdlib/strfromf.h" +#include "test/UnitTest/Test.h" + +STRFROM_TEST(float, StrFromf, LIBC_NAMESPACE::strfromf) diff --git a/libc/test/src/stdlib/strfroml_test.cpp b/libc/test/src/stdlib/strfroml_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cf472a39a5bf88071efb727d637772cd38e2cedb --- /dev/null +++ b/libc/test/src/stdlib/strfroml_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for strfroml --------------------------------------------===// +// +// 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 "StrfromTest.h" +#include "src/stdlib/strfroml.h" +#include "test/UnitTest/Test.h" + +STRFROM_TEST(long double, Strfroml, LIBC_NAMESPACE::strfroml) diff --git a/libc/test/src/sys/CMakeLists.txt b/libc/test/src/sys/CMakeLists.txt index 7f228e709046d0aa71b101e3041a2ff57fde7659..dc0aa8bf7b75dc14bc29b8226b4798097c13ac5c 100644 --- a/libc/test/src/sys/CMakeLists.txt +++ b/libc/test/src/sys/CMakeLists.txt @@ -5,6 +5,7 @@ add_subdirectory(select) add_subdirectory(sendfile) add_subdirectory(socket) add_subdirectory(stat) +add_subdirectory(statvfs) add_subdirectory(utsname) add_subdirectory(wait) add_subdirectory(prctl) diff --git a/libc/test/src/sys/mman/linux/CMakeLists.txt b/libc/test/src/sys/mman/linux/CMakeLists.txt index 6f7fc34d8d3ce3ba344af1c7eeaddad030be98ba..0762a2d846a8e0a6a8b818b13cf987c3c59d02ee 100644 --- a/libc/test/src/sys/mman/linux/CMakeLists.txt +++ b/libc/test/src/sys/mman/linux/CMakeLists.txt @@ -127,3 +127,23 @@ add_libc_unittest( libc.src.unistd.sysconf libc.test.UnitTest.ErrnoSetterMatcher ) + +add_libc_unittest( + shm_test + SUITE + libc_sys_mman_unittests + SRCS + shm_test.cpp + DEPENDS + libc.include.sys_mman + libc.include.sys_syscall + libc.src.errno.errno + libc.src.sys.mman.shm_open + libc.src.sys.mman.shm_unlink + libc.src.sys.mman.mmap + libc.src.sys.mman.munmap + libc.src.unistd.ftruncate + libc.src.unistd.close + libc.src.__support.OSUtil.osutil + libc.test.UnitTest.ErrnoSetterMatcher +) diff --git a/libc/test/src/sys/mman/linux/shm_test.cpp b/libc/test/src/sys/mman/linux/shm_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3b1a2aa33b56adeeab0d523337add3c1cfe8f054 --- /dev/null +++ b/libc/test/src/sys/mman/linux/shm_test.cpp @@ -0,0 +1,77 @@ +//===-- Unittests for shm_open/shm_unlink ---------------------------------===// +// +// 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/OSUtil/syscall.h" +#include "src/sys/mman/mmap.h" +#include "src/sys/mman/munmap.h" +#include "src/sys/mman/shm_open.h" +#include "src/sys/mman/shm_unlink.h" +#include "src/unistd/close.h" +#include "src/unistd/ftruncate.h" +#include "test/UnitTest/ErrnoSetterMatcher.h" +#include "test/UnitTest/LibcTest.h" +#include <asm-generic/fcntl.h> +#include <sys/syscall.h> + +using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; +// since shm_open/shm_unlink are wrappers around open/unlink, we only focus on +// testing basic cases and name conversions. + +TEST(LlvmLibcShmTest, Basic) { + const char *name = "/test_shm_open"; + int fd; + ASSERT_THAT(fd = LIBC_NAMESPACE::shm_open(name, O_CREAT | O_RDWR, 0666), + returns(GE(0)).with_errno(EQ(0))); + + // check that FD_CLOEXEC is set by default. + // TODO: use fcntl when implemented. + // https://github.com/llvm/llvm-project/issues/84968 + long flag = LIBC_NAMESPACE::syscall_impl(SYS_fcntl, fd, F_GETFD); + ASSERT_GE(static_cast<int>(flag), 0); + EXPECT_NE(static_cast<int>(flag) & FD_CLOEXEC, 0); + + // allocate space using ftruncate + ASSERT_THAT(LIBC_NAMESPACE::ftruncate(fd, 4096), Succeeds()); + // map the shared memory + void *addr = LIBC_NAMESPACE::mmap(nullptr, 4096, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); + ASSERT_NE(addr, MAP_FAILED); + // just write random data to the shared memory + char data[] = "Despite its name, LLVM has little to do with traditional " + "virtual machines."; + for (size_t i = 0; i < sizeof(data); ++i) + static_cast<char *>(addr)[i] = data[i]; + + // close fd does not affect the mapping + ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds()); + for (size_t i = 0; i < sizeof(data); ++i) + EXPECT_EQ(static_cast<char *>(addr)[i], data[i]); + + // unmap the shared memory + ASSERT_THAT(LIBC_NAMESPACE::munmap(addr, 4096), Succeeds()); + // remove the shared memory + ASSERT_THAT(LIBC_NAMESPACE::shm_unlink(name), Succeeds()); +} + +TEST(LlvmLibcShmTest, NameConversion) { + const char *name = "////test_shm_open"; + int fd; + ASSERT_THAT(fd = LIBC_NAMESPACE::shm_open(name, O_CREAT | O_RDWR, 0666), + returns(GE(0)).with_errno(EQ(0))); + ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds()); + ASSERT_THAT(LIBC_NAMESPACE::shm_unlink(name), Succeeds()); + + ASSERT_THAT(LIBC_NAMESPACE::shm_open("/123/123", O_CREAT | O_RDWR, 0666), + Fails(EINVAL)); + + ASSERT_THAT(LIBC_NAMESPACE::shm_open("/.", O_CREAT | O_RDWR, 0666), + Fails(EINVAL)); + + ASSERT_THAT(LIBC_NAMESPACE::shm_open("/..", O_CREAT | O_RDWR, 0666), + Fails(EINVAL)); +} diff --git a/libc/test/src/sys/statvfs/CMakeLists.txt b/libc/test/src/sys/statvfs/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b4bbe81c92ff2ebe511e5102fe9f9f56f8f0093b --- /dev/null +++ b/libc/test/src/sys/statvfs/CMakeLists.txt @@ -0,0 +1,3 @@ +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) + add_subdirectory(${LIBC_TARGET_OS}) +endif() diff --git a/libc/test/src/sys/statvfs/linux/CMakeLists.txt b/libc/test/src/sys/statvfs/linux/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..1f8688868e0438ee7d1b16f1d140fd376373af11 --- /dev/null +++ b/libc/test/src/sys/statvfs/linux/CMakeLists.txt @@ -0,0 +1,29 @@ +add_custom_target(libc_sys_statvfs_unittests) + +add_libc_unittest( + statvfs_test + SUITE + libc_sys_statvfs_unittests + SRCS + statvfs_test.cpp + DEPENDS + libc.src.errno.errno + libc.src.sys.statvfs.linux.statfs_utils + libc.src.sys.statvfs.statvfs + libc.test.UnitTest.ErrnoSetterMatcher +) + +add_libc_unittest( + fstatvfs_test + SUITE + libc_sys_statvfs_unittests + SRCS + fstatvfs_test.cpp + DEPENDS + libc.src.errno.errno + libc.src.sys.statvfs.linux.statfs_utils + libc.src.sys.statvfs.fstatvfs + libc.src.fcntl.open + libc.src.unistd.close + libc.test.UnitTest.ErrnoSetterMatcher +) diff --git a/libc/test/src/sys/statvfs/linux/fstatvfs_test.cpp b/libc/test/src/sys/statvfs/linux/fstatvfs_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bd5195c7969bd85c90932e56454483d8e70dc978 --- /dev/null +++ b/libc/test/src/sys/statvfs/linux/fstatvfs_test.cpp @@ -0,0 +1,42 @@ +#include "llvm-libc-macros/linux/fcntl-macros.h" +#include "src/fcntl/open.h" +#include "src/sys/statvfs/fstatvfs.h" +#include "src/sys/statvfs/linux/statfs_utils.h" +#include "src/unistd/close.h" +#include "test/UnitTest/ErrnoSetterMatcher.h" +#include "test/UnitTest/LibcTest.h" +#include <linux/magic.h> +using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; + +namespace LIBC_NAMESPACE { +static int fstatfs(int fd, struct statfs *buf) { + using namespace statfs_utils; + if (cpp::optional<LinuxStatFs> result = linux_fstatfs(fd)) { + *buf = *result; + return 0; + } + return -1; +} +} // namespace LIBC_NAMESPACE + +struct PathFD { + int fd; + explicit PathFD(const char *path) + : fd(LIBC_NAMESPACE::open(path, O_CLOEXEC | O_PATH)) {} + ~PathFD() { LIBC_NAMESPACE::close(fd); } + operator int() const { return fd; } +}; + +TEST(LlvmLibcSysStatvfsTest, FstatfsBasic) { + struct statfs buf; + ASSERT_THAT(LIBC_NAMESPACE::fstatfs(PathFD("/"), &buf), Succeeds()); + ASSERT_THAT(LIBC_NAMESPACE::fstatfs(PathFD("/proc"), &buf), Succeeds()); + ASSERT_EQ(buf.f_type, static_cast<decltype(buf.f_type)>(PROC_SUPER_MAGIC)); + ASSERT_THAT(LIBC_NAMESPACE::fstatfs(PathFD("/sys"), &buf), Succeeds()); + ASSERT_EQ(buf.f_type, static_cast<decltype(buf.f_type)>(SYSFS_MAGIC)); +} + +TEST(LlvmLibcSysStatvfsTest, FstatvfsInvalidFD) { + struct statvfs buf; + ASSERT_THAT(LIBC_NAMESPACE::fstatvfs(-1, &buf), Fails(EBADF)); +} diff --git a/libc/test/src/sys/statvfs/linux/statvfs_test.cpp b/libc/test/src/sys/statvfs/linux/statvfs_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..695d2c0d5e98de88261a33fab6d3a47bdf1624f9 --- /dev/null +++ b/libc/test/src/sys/statvfs/linux/statvfs_test.cpp @@ -0,0 +1,47 @@ +#include "src/sys/statvfs/linux/statfs_utils.h" +#include "src/sys/statvfs/statvfs.h" +#include "test/UnitTest/ErrnoSetterMatcher.h" +#include "test/UnitTest/LibcTest.h" +#include <linux/magic.h> +using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; + +namespace LIBC_NAMESPACE { +static int statfs(const char *path, struct statfs *buf) { + using namespace statfs_utils; + if (cpp::optional<LinuxStatFs> result = linux_statfs(path)) { + *buf = *result; + return 0; + } + return -1; +} +} // namespace LIBC_NAMESPACE + +TEST(LlvmLibcSysStatfsTest, StatfsBasic) { + struct statfs buf; + ASSERT_THAT(LIBC_NAMESPACE::statfs("/", &buf), Succeeds()); + ASSERT_THAT(LIBC_NAMESPACE::statfs("/proc", &buf), Succeeds()); + ASSERT_EQ(buf.f_type, static_cast<decltype(buf.f_type)>(PROC_SUPER_MAGIC)); + ASSERT_THAT(LIBC_NAMESPACE::statfs("/sys", &buf), Succeeds()); + ASSERT_EQ(buf.f_type, static_cast<decltype(buf.f_type)>(SYSFS_MAGIC)); +} + +TEST(LlvmLibcSysStatfsTest, StatvfsInvalidPath) { + struct statvfs buf; + ASSERT_THAT(LIBC_NAMESPACE::statvfs("", &buf), Fails(ENOENT)); + ASSERT_THAT(LIBC_NAMESPACE::statvfs("/nonexistent", &buf), Fails(ENOENT)); + ASSERT_THAT(LIBC_NAMESPACE::statvfs("/dev/null/whatever", &buf), + Fails(ENOTDIR)); + ASSERT_THAT(LIBC_NAMESPACE::statvfs(nullptr, &buf), Fails(EFAULT)); +} + +TEST(LlvmLibcSysStatfsTest, StatvfsNameTooLong) { + struct statvfs buf; + ASSERT_THAT(LIBC_NAMESPACE::statvfs("/", &buf), Succeeds()); + char *name = static_cast<char *>(__builtin_alloca(buf.f_namemax + 3)); + name[0] = '/'; + name[buf.f_namemax + 2] = '\0'; + for (unsigned i = 1; i < buf.f_namemax + 2; ++i) { + name[i] = 'a'; + } + ASSERT_THAT(LIBC_NAMESPACE::statvfs(name, &buf), Fails(ENAMETOOLONG)); +} diff --git a/libc/test/src/unistd/CMakeLists.txt b/libc/test/src/unistd/CMakeLists.txt index 3a7fe6f45c0911eb423be3626510aa916d987746..9de5081f0094ea4bfc36e67409e5d7e1c36cd82a 100644 --- a/libc/test/src/unistd/CMakeLists.txt +++ b/libc/test/src/unistd/CMakeLists.txt @@ -444,3 +444,17 @@ add_libc_test( libc.src.stdio.fopencookie libc.src.stdio.fflush ) + +if(LLVM_LIBC_FULL_BUILD) + add_libc_test( + _exit_test + UNIT_TEST_ONLY + SUITE + libc_unistd_unittests + SRCS + _exit_test.cpp + DEPENDS + libc.include.unistd + libc.src.unistd._exit + ) +endif() diff --git a/libc/test/src/unistd/_exit_test.cpp b/libc/test/src/unistd/_exit_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6d0e4465dbba1dd7d2388f95478bc682872d923b --- /dev/null +++ b/libc/test/src/unistd/_exit_test.cpp @@ -0,0 +1,15 @@ +//===-- Unittests for _exit -----------------------------------------------===// +// +// 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/unistd/_exit.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcUniStd, _exit) { + EXPECT_EXITS([] { LIBC_NAMESPACE::_exit(1); }, 1); + EXPECT_EXITS([] { LIBC_NAMESPACE::_exit(65); }, 65); +} diff --git a/libc/test/utils/FPUtil/x86_long_double_test.cpp b/libc/test/utils/FPUtil/x86_long_double_test.cpp index bafbbe2a41075919aecbdb90ca780795187969d5..3b140c6c0266702323899f1d3530d49c2ed16d88 100644 --- a/libc/test/utils/FPUtil/x86_long_double_test.cpp +++ b/libc/test/utils/FPUtil/x86_long_double_test.cpp @@ -9,7 +9,7 @@ #include "src/__support/FPUtil/FPBits.h" #include "test/UnitTest/Test.h" -#include <math.h> +#include "include/llvm-libc-macros/math-macros.h" using FPBits = LIBC_NAMESPACE::fputil::FPBits<long double>; diff --git a/libc/utils/HdrGen/Generator.cpp b/libc/utils/HdrGen/Generator.cpp index 3bcf005adda74fc61e72ea85c3477e9353b6574b..d926d5d9ac3c8d5f1b20bd93fc180f3f8c568d76 100644 --- a/libc/utils/HdrGen/Generator.cpp +++ b/libc/utils/HdrGen/Generator.cpp @@ -84,11 +84,19 @@ void Generator::generate(llvm::raw_ostream &OS, llvm::RecordKeeper &Records) { Line = Line.drop_front(CommandPrefixSize); P = Line.split("("); + // It's possible that we have windows line endings, so strip off the extra + // CR. + P.second = P.second.trim(); if (P.second.empty() || P.second[P.second.size() - 1] != ')') { SrcMgr.PrintMessage(llvm::SMLoc::getFromPointer(P.second.data()), llvm::SourceMgr::DK_Error, "Command argument list should begin with '(' " "and end with ')'."); + SrcMgr.PrintMessage(llvm::SMLoc::getFromPointer(P.second.data()), + llvm::SourceMgr::DK_Error, P.second.data()); + SrcMgr.PrintMessage(llvm::SMLoc::getFromPointer(P.second.data()), + llvm::SourceMgr::DK_Error, + std::to_string(P.second.size())); std::exit(1); } llvm::StringRef CommandName = P.first; diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp index 7cc18cfb624389067be678be3607ca5512475a4a..a83f7a7ceb922c3bcab4743a9763acb877923b42 100644 --- a/libc/utils/MPFRWrapper/MPFRUtils.cpp +++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp @@ -14,7 +14,7 @@ #include "src/__support/FPUtil/fpbits_str.h" #include "test/UnitTest/FPMatcher.h" -#include <cmath> +#include "include/llvm-libc-macros/math-macros.h" #include <fenv.h> #include <memory> #include <stdint.h> @@ -181,6 +181,12 @@ public: return result; } + MPFRNumber atan2(const MPFRNumber &b) { + MPFRNumber result(*this); + mpfr_atan2(result.value, value, b.value, mpfr_rounding); + return result; + } + MPFRNumber atanh() const { MPFRNumber result(*this); mpfr_atanh(result.value, value, mpfr_rounding); @@ -623,6 +629,8 @@ binary_operation_one_output(Operation op, InputType x, InputType y, MPFRNumber inputX(x, precision, rounding); MPFRNumber inputY(y, precision, rounding); switch (op) { + case Operation::Atan2: + return inputX.atan2(inputY); case Operation::Fmod: return inputX.fmod(inputY); case Operation::Hypot: diff --git a/libc/utils/MPFRWrapper/MPFRUtils.h b/libc/utils/MPFRWrapper/MPFRUtils.h index 6164d78fa5adc47c3fd091ec88a0582b5558d06d..d5ff590cd7bb69bcae59bd0dfd231846cd5dc44f 100644 --- a/libc/utils/MPFRWrapper/MPFRUtils.h +++ b/libc/utils/MPFRWrapper/MPFRUtils.h @@ -68,6 +68,7 @@ enum class Operation : int { // input and produce a single floating point number of the same type as // output. BeginBinaryOperationsSingleOutput, + Atan2, Fmod, Hypot, Pow, diff --git a/libc/utils/gpu/loader/Loader.h b/libc/utils/gpu/loader/Loader.h index 93380383701978774e370211a7fa69214d8988af..9c7d328930c239687800a57019f2cea13b29363f 100644 --- a/libc/utils/gpu/loader/Loader.h +++ b/libc/utils/gpu/loader/Loader.h @@ -108,11 +108,11 @@ inline void handle_error(rpc_status_t) { } template <uint32_t lane_size> -inline void register_rpc_callbacks(uint32_t device_id) { +inline void register_rpc_callbacks(rpc_device_t device) { static_assert(lane_size == 32 || lane_size == 64, "Invalid Lane size"); // Register the ping test for the `libc` tests. rpc_register_callback( - device_id, static_cast<rpc_opcode_t>(RPC_TEST_INCREMENT), + device, static_cast<rpc_opcode_t>(RPC_TEST_INCREMENT), [](rpc_port_t port, void *data) { rpc_recv_and_send( port, @@ -125,7 +125,7 @@ inline void register_rpc_callbacks(uint32_t device_id) { // Register the interface test callbacks. rpc_register_callback( - device_id, static_cast<rpc_opcode_t>(RPC_TEST_INTERFACE), + device, static_cast<rpc_opcode_t>(RPC_TEST_INTERFACE), [](rpc_port_t port, void *data) { uint64_t cnt = 0; bool end_with_recv; @@ -207,7 +207,7 @@ inline void register_rpc_callbacks(uint32_t device_id) { // Register the stream test handler. rpc_register_callback( - device_id, static_cast<rpc_opcode_t>(RPC_TEST_STREAM), + device, static_cast<rpc_opcode_t>(RPC_TEST_STREAM), [](rpc_port_t port, void *data) { uint64_t sizes[lane_size] = {0}; void *dst[lane_size] = {nullptr}; diff --git a/libc/utils/gpu/loader/amdgpu/Loader.cpp b/libc/utils/gpu/loader/amdgpu/Loader.cpp index e3911eda2bd82ab0eb7e4413ce7cc295fafa17d2..35840c6910bd8e9930c72803c8a396799301d2e4 100644 --- a/libc/utils/gpu/loader/amdgpu/Loader.cpp +++ b/libc/utils/gpu/loader/amdgpu/Loader.cpp @@ -153,7 +153,8 @@ template <typename args_t> hsa_status_t launch_kernel(hsa_agent_t dev_agent, hsa_executable_t executable, hsa_amd_memory_pool_t kernargs_pool, hsa_amd_memory_pool_t coarsegrained_pool, - hsa_queue_t *queue, const LaunchParameters ¶ms, + hsa_queue_t *queue, rpc_device_t device, + const LaunchParameters ¶ms, const char *kernel_name, args_t kernel_args) { // Look up the '_start' kernel in the loaded executable. hsa_executable_symbol_t symbol; @@ -162,10 +163,9 @@ hsa_status_t launch_kernel(hsa_agent_t dev_agent, hsa_executable_t executable, return err; // Register RPC callbacks for the malloc and free functions on HSA. - uint32_t device_id = 0; auto tuple = std::make_tuple(dev_agent, coarsegrained_pool); rpc_register_callback( - device_id, RPC_MALLOC, + device, RPC_MALLOC, [](rpc_port_t port, void *data) { auto malloc_handler = [](rpc_buffer_t *buffer, void *data) -> void { auto &[dev_agent, pool] = *static_cast<decltype(tuple) *>(data); @@ -182,7 +182,7 @@ hsa_status_t launch_kernel(hsa_agent_t dev_agent, hsa_executable_t executable, }, &tuple); rpc_register_callback( - device_id, RPC_FREE, + device, RPC_FREE, [](rpc_port_t port, void *data) { auto free_handler = [](rpc_buffer_t *buffer, void *) { if (hsa_status_t err = hsa_amd_memory_pool_free( @@ -284,12 +284,12 @@ hsa_status_t launch_kernel(hsa_agent_t dev_agent, hsa_executable_t executable, while (hsa_signal_wait_scacquire( packet->completion_signal, HSA_SIGNAL_CONDITION_EQ, 0, /*timeout_hint=*/1024, HSA_WAIT_STATE_ACTIVE) != 0) - if (rpc_status_t err = rpc_handle_server(device_id)) + if (rpc_status_t err = rpc_handle_server(device)) handle_error(err); // Handle the server one more time in case the kernel exited with a pending // send still in flight. - if (rpc_status_t err = rpc_handle_server(device_id)) + if (rpc_status_t err = rpc_handle_server(device)) handle_error(err); // Destroy the resources acquired to launch the kernel and return. @@ -342,8 +342,6 @@ int load(int argc, char **argv, char **envp, void *image, size_t size, handle_error(err); // Obtain a single agent for the device and host to use the HSA memory model. - uint32_t num_devices = 1; - uint32_t device_id = 0; hsa_agent_t dev_agent; hsa_agent_t host_agent; if (hsa_status_t err = get_agent<HSA_DEVICE_TYPE_GPU>(&dev_agent)) @@ -433,8 +431,6 @@ int load(int argc, char **argv, char **envp, void *image, size_t size, handle_error(err); // Set up the RPC server. - if (rpc_status_t err = rpc_init(num_devices)) - handle_error(err); auto tuple = std::make_tuple(dev_agent, finegrained_pool); auto rpc_alloc = [](uint64_t size, void *data) { auto &[dev_agent, finegrained_pool] = *static_cast<decltype(tuple) *>(data); @@ -445,15 +441,16 @@ int load(int argc, char **argv, char **envp, void *image, size_t size, hsa_amd_agents_allow_access(1, &dev_agent, nullptr, dev_ptr); return dev_ptr; }; - if (rpc_status_t err = rpc_server_init(device_id, RPC_MAXIMUM_PORT_COUNT, + rpc_device_t device; + if (rpc_status_t err = rpc_server_init(&device, RPC_MAXIMUM_PORT_COUNT, wavefront_size, rpc_alloc, &tuple)) handle_error(err); // Register callbacks for the RPC unit tests. if (wavefront_size == 32) - register_rpc_callbacks<32>(device_id); + register_rpc_callbacks<32>(device); else if (wavefront_size == 64) - register_rpc_callbacks<64>(device_id); + register_rpc_callbacks<64>(device); else handle_error("Invalid wavefront size"); @@ -483,10 +480,10 @@ int load(int argc, char **argv, char **envp, void *image, size_t size, handle_error(err); void *rpc_client_buffer; - if (hsa_status_t err = hsa_amd_memory_lock( - const_cast<void *>(rpc_get_client_buffer(device_id)), - rpc_get_client_size(), - /*agents=*/nullptr, 0, &rpc_client_buffer)) + if (hsa_status_t err = + hsa_amd_memory_lock(const_cast<void *>(rpc_get_client_buffer(device)), + rpc_get_client_size(), + /*agents=*/nullptr, 0, &rpc_client_buffer)) handle_error(err); // Copy the RPC client buffer to the address pointed to by the symbol. @@ -496,7 +493,7 @@ int load(int argc, char **argv, char **envp, void *image, size_t size, handle_error(err); if (hsa_status_t err = hsa_amd_memory_unlock( - const_cast<void *>(rpc_get_client_buffer(device_id)))) + const_cast<void *>(rpc_get_client_buffer(device)))) handle_error(err); if (hsa_status_t err = hsa_amd_memory_pool_free(rpc_client_host)) handle_error(err); @@ -549,13 +546,13 @@ int load(int argc, char **argv, char **envp, void *image, size_t size, begin_args_t init_args = {argc, dev_argv, dev_envp}; if (hsa_status_t err = launch_kernel( dev_agent, executable, kernargs_pool, coarsegrained_pool, queue, - single_threaded_params, "_begin.kd", init_args)) + device, single_threaded_params, "_begin.kd", init_args)) handle_error(err); start_args_t args = {argc, dev_argv, dev_envp, dev_ret}; - if (hsa_status_t err = - launch_kernel(dev_agent, executable, kernargs_pool, - coarsegrained_pool, queue, params, "_start.kd", args)) + if (hsa_status_t err = launch_kernel(dev_agent, executable, kernargs_pool, + coarsegrained_pool, queue, device, + params, "_start.kd", args)) handle_error(err); void *host_ret; @@ -575,11 +572,11 @@ int load(int argc, char **argv, char **envp, void *image, size_t size, end_args_t fini_args = {ret}; if (hsa_status_t err = launch_kernel( dev_agent, executable, kernargs_pool, coarsegrained_pool, queue, - single_threaded_params, "_end.kd", fini_args)) + device, single_threaded_params, "_end.kd", fini_args)) handle_error(err); if (rpc_status_t err = rpc_server_shutdown( - device_id, [](void *ptr, void *) { hsa_amd_memory_pool_free(ptr); }, + device, [](void *ptr, void *) { hsa_amd_memory_pool_free(ptr); }, nullptr)) handle_error(err); @@ -600,8 +597,6 @@ int load(int argc, char **argv, char **envp, void *image, size_t size, if (hsa_status_t err = hsa_code_object_destroy(object)) handle_error(err); - if (rpc_status_t err = rpc_shutdown()) - handle_error(err); if (hsa_status_t err = hsa_shut_down()) handle_error(err); diff --git a/libc/utils/gpu/loader/nvptx/Loader.cpp b/libc/utils/gpu/loader/nvptx/Loader.cpp index 5388f287063b7f9ab6d2c4cbf865b46d4bc52e18..1818932f0a966b3f3d5c9d80f6fc1e7f019ecc18 100644 --- a/libc/utils/gpu/loader/nvptx/Loader.cpp +++ b/libc/utils/gpu/loader/nvptx/Loader.cpp @@ -154,8 +154,8 @@ Expected<void *> get_ctor_dtor_array(const void *image, const size_t size, template <typename args_t> CUresult launch_kernel(CUmodule binary, CUstream stream, - const LaunchParameters ¶ms, const char *kernel_name, - args_t kernel_args) { + rpc_device_t rpc_device, const LaunchParameters ¶ms, + const char *kernel_name, args_t kernel_args) { // look up the '_start' kernel in the loaded module. CUfunction function; if (CUresult err = cuModuleGetFunction(&function, binary, kernel_name)) @@ -175,11 +175,10 @@ CUresult launch_kernel(CUmodule binary, CUstream stream, handle_error(err); // Register RPC callbacks for the malloc and free functions on HSA. - uint32_t device_id = 0; - register_rpc_callbacks<32>(device_id); + register_rpc_callbacks<32>(rpc_device); rpc_register_callback( - device_id, RPC_MALLOC, + rpc_device, RPC_MALLOC, [](rpc_port_t port, void *data) { auto malloc_handler = [](rpc_buffer_t *buffer, void *data) -> void { CUstream memory_stream = *static_cast<CUstream *>(data); @@ -197,7 +196,7 @@ CUresult launch_kernel(CUmodule binary, CUstream stream, }, &memory_stream); rpc_register_callback( - device_id, RPC_FREE, + rpc_device, RPC_FREE, [](rpc_port_t port, void *data) { auto free_handler = [](rpc_buffer_t *buffer, void *data) { CUstream memory_stream = *static_cast<CUstream *>(data); @@ -219,12 +218,12 @@ CUresult launch_kernel(CUmodule binary, CUstream stream, // Wait until the kernel has completed execution on the device. Periodically // check the RPC client for work to be performed on the server. while (cuStreamQuery(stream) == CUDA_ERROR_NOT_READY) - if (rpc_status_t err = rpc_handle_server(device_id)) + if (rpc_status_t err = rpc_handle_server(rpc_device)) handle_error(err); // Handle the server one more time in case the kernel exited with a pending // send still in flight. - if (rpc_status_t err = rpc_handle_server(device_id)) + if (rpc_status_t err = rpc_handle_server(rpc_device)) handle_error(err); return CUDA_SUCCESS; @@ -235,7 +234,6 @@ int load(int argc, char **argv, char **envp, void *image, size_t size, if (CUresult err = cuInit(0)) handle_error(err); // Obtain the first device found on the system. - uint32_t num_devices = 1; uint32_t device_id = 0; CUdevice device; if (CUresult err = cuDeviceGet(&device, device_id)) @@ -294,9 +292,6 @@ int load(int argc, char **argv, char **envp, void *image, size_t size, if (CUresult err = cuMemsetD32(dev_ret, 0, 1)) handle_error(err); - if (rpc_status_t err = rpc_init(num_devices)) - handle_error(err); - uint32_t warp_size = 32; auto rpc_alloc = [](uint64_t size, void *) -> void * { void *dev_ptr; @@ -304,7 +299,8 @@ int load(int argc, char **argv, char **envp, void *image, size_t size, handle_error(err); return dev_ptr; }; - if (rpc_status_t err = rpc_server_init(device_id, RPC_MAXIMUM_PORT_COUNT, + rpc_device_t rpc_device; + if (rpc_status_t err = rpc_server_init(&rpc_device, RPC_MAXIMUM_PORT_COUNT, warp_size, rpc_alloc, nullptr)) handle_error(err); @@ -321,19 +317,20 @@ int load(int argc, char **argv, char **envp, void *image, size_t size, cuMemcpyDtoH(&rpc_client_host, rpc_client_dev, sizeof(void *))) handle_error(err); if (CUresult err = - cuMemcpyHtoD(rpc_client_host, rpc_get_client_buffer(device_id), + cuMemcpyHtoD(rpc_client_host, rpc_get_client_buffer(rpc_device), rpc_get_client_size())) handle_error(err); LaunchParameters single_threaded_params = {1, 1, 1, 1, 1, 1}; begin_args_t init_args = {argc, dev_argv, dev_envp}; - if (CUresult err = launch_kernel(binary, stream, single_threaded_params, - "_begin", init_args)) + if (CUresult err = launch_kernel(binary, stream, rpc_device, + single_threaded_params, "_begin", init_args)) handle_error(err); start_args_t args = {argc, dev_argv, dev_envp, reinterpret_cast<void *>(dev_ret)}; - if (CUresult err = launch_kernel(binary, stream, params, "_start", args)) + if (CUresult err = + launch_kernel(binary, stream, rpc_device, params, "_start", args)) handle_error(err); // Copy the return value back from the kernel and wait. @@ -345,8 +342,8 @@ int load(int argc, char **argv, char **envp, void *image, size_t size, handle_error(err); end_args_t fini_args = {host_ret}; - if (CUresult err = launch_kernel(binary, stream, single_threaded_params, - "_end", fini_args)) + if (CUresult err = launch_kernel(binary, stream, rpc_device, + single_threaded_params, "_end", fini_args)) handle_error(err); // Free the memory allocated for the device. @@ -357,7 +354,7 @@ int load(int argc, char **argv, char **envp, void *image, size_t size, if (CUresult err = cuMemFreeHost(dev_argv)) handle_error(err); if (rpc_status_t err = rpc_server_shutdown( - device_id, [](void *ptr, void *) { cuMemFreeHost(ptr); }, nullptr)) + rpc_device, [](void *ptr, void *) { cuMemFreeHost(ptr); }, nullptr)) handle_error(err); // Destroy the context and the loaded binary. @@ -365,7 +362,5 @@ int load(int argc, char **argv, char **envp, void *image, size_t size, handle_error(err); if (CUresult err = cuDevicePrimaryCtxRelease(device)) handle_error(err); - if (rpc_status_t err = rpc_shutdown()) - handle_error(err); return host_ret; } diff --git a/libc/utils/gpu/server/llvmlibc_rpc_server.h b/libc/utils/gpu/server/llvmlibc_rpc_server.h index b7f2a463b1f5c8aa38fe9a96f083af950012ca48..b0cf2f916b38568e5e35a6363aedf3cf23ed80f8 100644 --- a/libc/utils/gpu/server/llvmlibc_rpc_server.h +++ b/libc/utils/gpu/server/llvmlibc_rpc_server.h @@ -27,10 +27,8 @@ typedef enum { RPC_STATUS_SUCCESS = 0x0, RPC_STATUS_CONTINUE = 0x1, RPC_STATUS_ERROR = 0x1000, - RPC_STATUS_OUT_OF_RANGE = 0x1001, - RPC_STATUS_UNHANDLED_OPCODE = 0x1002, - RPC_STATUS_INVALID_LANE_SIZE = 0x1003, - RPC_STATUS_NOT_INITIALIZED = 0x1004, + RPC_STATUS_UNHANDLED_OPCODE = 0x1001, + RPC_STATUS_INVALID_LANE_SIZE = 0x1002, } rpc_status_t; /// A struct containing an opaque handle to an RPC port. This is what allows the @@ -45,6 +43,11 @@ typedef struct rpc_buffer_s { uint64_t data[8]; } rpc_buffer_t; +/// An opaque handle to an RPC server that can be attached to a device. +typedef struct rpc_device_s { + uintptr_t handle; +} rpc_device_t; + /// A function used to allocate \p bytes for use by the RPC server and client. /// The memory should support asynchronous and atomic access from both the /// client and server. @@ -60,34 +63,28 @@ typedef void (*rpc_opcode_callback_ty)(rpc_port_t port, void *data); /// A callback function to use the port to receive or send a \p buffer. typedef void (*rpc_port_callback_ty)(rpc_buffer_t *buffer, void *data); -/// Initialize the rpc library for general use on \p num_devices. -rpc_status_t rpc_init(uint32_t num_devices); - -/// Shut down the rpc interface. -rpc_status_t rpc_shutdown(void); - -/// Initialize the server for a given device. -rpc_status_t rpc_server_init(uint32_t device_id, uint64_t num_ports, +/// Initialize the server for a given device and return it in \p device. +rpc_status_t rpc_server_init(rpc_device_t *rpc_device, uint64_t num_ports, uint32_t lane_size, rpc_alloc_ty alloc, void *data); /// Shut down the server for a given device. -rpc_status_t rpc_server_shutdown(uint32_t device_id, rpc_free_ty dealloc, +rpc_status_t rpc_server_shutdown(rpc_device_t rpc_device, rpc_free_ty dealloc, void *data); /// Queries the RPC clients at least once and performs server-side work if there /// are any active requests. Runs until all work on the server is completed. -rpc_status_t rpc_handle_server(uint32_t device_id); +rpc_status_t rpc_handle_server(rpc_device_t rpc_device); /// Register a callback to handle an opcode from the RPC client. The associated /// data must remain accessible as long as the user intends to handle the server /// with this callback. -rpc_status_t rpc_register_callback(uint32_t device_id, uint16_t opcode, +rpc_status_t rpc_register_callback(rpc_device_t rpc_device, uint16_t opcode, rpc_opcode_callback_ty callback, void *data); /// Obtain a pointer to a local client buffer that can be copied directly to the /// other process using the address stored at the rpc client symbol name. -const void *rpc_get_client_buffer(uint32_t device_id); +const void *rpc_get_client_buffer(rpc_device_t device); /// Returns the size of the client in bytes to be used for a memory copy. uint64_t rpc_get_client_size(); diff --git a/libc/utils/gpu/server/rpc_server.cpp b/libc/utils/gpu/server/rpc_server.cpp index 90af1569c4c53b8ab435736e78250e833775a162..fd306642fdcc4cdf05e99ca09fef41e34606f269 100644 --- a/libc/utils/gpu/server/rpc_server.cpp +++ b/libc/utils/gpu/server/rpc_server.cpp @@ -6,6 +6,11 @@ // //===----------------------------------------------------------------------===// +// Workaround for missing __has_builtin in < GCC 10. +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + #include "llvmlibc_rpc_server.h" #include "src/__support/RPC/rpc.h" @@ -243,127 +248,75 @@ struct Device { std::unordered_map<uint16_t, void *> callback_data; }; -// A struct containing all the runtime state required to run the RPC server. -struct State { - State(uint32_t num_devices) - : num_devices(num_devices), devices(num_devices), reference_count(0u) {} - uint32_t num_devices; - std::vector<std::unique_ptr<Device>> devices; - std::atomic_uint32_t reference_count; -}; - -static std::mutex startup_mutex; - -static State *state; - -rpc_status_t rpc_init(uint32_t num_devices) { - std::scoped_lock<decltype(startup_mutex)> lock(startup_mutex); - if (!state) - state = new State(num_devices); - - if (state->reference_count == std::numeric_limits<uint32_t>::max()) - return RPC_STATUS_ERROR; - - state->reference_count++; - - return RPC_STATUS_SUCCESS; -} - -rpc_status_t rpc_shutdown(void) { - if (state && state->reference_count-- == 1) - delete state; - - return RPC_STATUS_SUCCESS; -} - -rpc_status_t rpc_server_init(uint32_t device_id, uint64_t num_ports, +rpc_status_t rpc_server_init(rpc_device_t *rpc_device, uint64_t num_ports, uint32_t lane_size, rpc_alloc_ty alloc, void *data) { - if (!state) - return RPC_STATUS_NOT_INITIALIZED; - if (device_id >= state->num_devices) - return RPC_STATUS_OUT_OF_RANGE; + if (!rpc_device) + return RPC_STATUS_ERROR; if (lane_size != 1 && lane_size != 32 && lane_size != 64) return RPC_STATUS_INVALID_LANE_SIZE; - if (!state->devices[device_id]) { - uint64_t size = rpc::Server::allocation_size(lane_size, num_ports); - void *buffer = alloc(size, data); + uint64_t size = rpc::Server::allocation_size(lane_size, num_ports); + void *buffer = alloc(size, data); - if (!buffer) - return RPC_STATUS_ERROR; + if (!buffer) + return RPC_STATUS_ERROR; - state->devices[device_id] = - std::make_unique<Device>(lane_size, num_ports, buffer); - if (!state->devices[device_id]) - return RPC_STATUS_ERROR; - } + Device *device = new Device(lane_size, num_ports, buffer); + if (!device) + return RPC_STATUS_ERROR; + rpc_device->handle = reinterpret_cast<uintptr_t>(device); return RPC_STATUS_SUCCESS; } -rpc_status_t rpc_server_shutdown(uint32_t device_id, rpc_free_ty dealloc, +rpc_status_t rpc_server_shutdown(rpc_device_t rpc_device, rpc_free_ty dealloc, void *data) { - if (!state) - return RPC_STATUS_NOT_INITIALIZED; - if (device_id >= state->num_devices) - return RPC_STATUS_OUT_OF_RANGE; - if (!state->devices[device_id]) + if (!rpc_device.handle) return RPC_STATUS_ERROR; - dealloc(state->devices[device_id]->buffer, data); - if (state->devices[device_id]) - state->devices[device_id].release(); + Device *device = reinterpret_cast<Device *>(rpc_device.handle); + dealloc(device->buffer, data); + delete device; return RPC_STATUS_SUCCESS; } -rpc_status_t rpc_handle_server(uint32_t device_id) { - if (!state) - return RPC_STATUS_NOT_INITIALIZED; - if (device_id >= state->num_devices) - return RPC_STATUS_OUT_OF_RANGE; - if (!state->devices[device_id]) +rpc_status_t rpc_handle_server(rpc_device_t rpc_device) { + if (!rpc_device.handle) return RPC_STATUS_ERROR; + Device *device = reinterpret_cast<Device *>(rpc_device.handle); uint32_t index = 0; for (;;) { - Device &device = *state->devices[device_id]; - rpc_status_t status = device.handle_server(index); + rpc_status_t status = device->handle_server(index); if (status != RPC_STATUS_CONTINUE) return status; } } -rpc_status_t rpc_register_callback(uint32_t device_id, uint16_t opcode, +rpc_status_t rpc_register_callback(rpc_device_t rpc_device, uint16_t opcode, rpc_opcode_callback_ty callback, void *data) { - if (!state) - return RPC_STATUS_NOT_INITIALIZED; - if (device_id >= state->num_devices) - return RPC_STATUS_OUT_OF_RANGE; - if (!state->devices[device_id]) + if (!rpc_device.handle) return RPC_STATUS_ERROR; - state->devices[device_id]->callbacks[opcode] = callback; - state->devices[device_id]->callback_data[opcode] = data; + Device *device = reinterpret_cast<Device *>(rpc_device.handle); + + device->callbacks[opcode] = callback; + device->callback_data[opcode] = data; return RPC_STATUS_SUCCESS; } -const void *rpc_get_client_buffer(uint32_t device_id) { - if (!state || device_id >= state->num_devices || !state->devices[device_id]) +const void *rpc_get_client_buffer(rpc_device_t rpc_device) { + if (!rpc_device.handle) return nullptr; - return &state->devices[device_id]->client; + Device *device = reinterpret_cast<Device *>(rpc_device.handle); + return &device->client; } uint64_t rpc_get_client_size() { return sizeof(rpc::Client); } -using ServerPort = std::variant<rpc::Server::Port *>; - -ServerPort get_port(rpc_port_t ref) { - return reinterpret_cast<rpc::Server::Port *>(ref.handle); -} - void rpc_send(rpc_port_t ref, rpc_port_callback_ty callback, void *data) { auto port = reinterpret_cast<rpc::Server::Port *>(ref.handle); port->send([=](rpc::Buffer *buffer) { diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt index fa1d8e4adbcc4fb380d7cf3c60e4726c0755b8f7..9236f09d366782fc25ee0e96c99765d6120019fd 100644 --- a/libclc/CMakeLists.txt +++ b/libclc/CMakeLists.txt @@ -40,25 +40,24 @@ set( LIBCLC_MIN_LLVM "3.9.0" ) set( LIBCLC_TARGETS_TO_BUILD "all" CACHE STRING "Semicolon-separated list of targets to build, or 'all'." ) -option( ENABLE_RUNTIME_SUBNORMAL "Enable runtime linking of subnormal support." -OFF ) +option( ENABLE_RUNTIME_SUBNORMAL "Enable runtime linking of subnormal support." OFF ) find_package(LLVM REQUIRED HINTS "${LLVM_CMAKE_DIR}") include(AddLLVM) -message( "LLVM version: ${LLVM_PACKAGE_VERSION}" ) +message( STATUS "libclc LLVM version: ${LLVM_PACKAGE_VERSION}" ) if( ${LLVM_PACKAGE_VERSION} VERSION_LESS ${LIBCLC_MIN_LLVM} ) - message( FATAL_ERROR "libclc needs at least LLVM ${LIBCLC_MIN_LLVM}" ) + message( FATAL_ERROR "libclc needs at least LLVM ${LIBCLC_MIN_LLVM}" ) endif() # mesa3d environment is only available since LLVM 4.0 if( ${LLVM_PACKAGE_VERSION} VERSION_GREATER "3.9.0" ) - set( LIBCLC_TARGETS_ALL ${LIBCLC_TARGETS_ALL} amdgcn-mesa-mesa3d ) + set( LIBCLC_TARGETS_ALL ${LIBCLC_TARGETS_ALL} amdgcn-mesa-mesa3d ) endif() if( LIBCLC_TARGETS_TO_BUILD STREQUAL "all" ) - set( LIBCLC_TARGETS_TO_BUILD ${LIBCLC_TARGETS_ALL} ) + set( LIBCLC_TARGETS_TO_BUILD ${LIBCLC_TARGETS_ALL} ) endif() find_program( LLVM_CLANG clang PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH ) @@ -68,22 +67,21 @@ find_program( LLVM_OPT opt PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH ) find_program( LLVM_SPIRV llvm-spirv PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH ) # Print toolchain -message( "clang: ${LLVM_CLANG}" ) -message( "llvm-as: ${LLVM_AS}" ) -message( "llvm-link: ${LLVM_LINK}" ) -message( "opt: ${LLVM_OPT}" ) -message( "llvm-spirv: ${LLVM_SPIRV}" ) -message( "" ) +message( STATUS "libclc toolchain - clang: ${LLVM_CLANG}" ) +message( STATUS "libclc toolchain - llvm-as: ${LLVM_AS}" ) +message( STATUS "libclc toolchain - llvm-link: ${LLVM_LINK}" ) +message( STATUS "libclc toolchain - opt: ${LLVM_OPT}" ) +message( STATUS "libclc toolchain - llvm-spirv: ${LLVM_SPIRV}" ) if( NOT LLVM_CLANG OR NOT LLVM_OPT OR NOT LLVM_AS OR NOT LLVM_LINK ) - message( FATAL_ERROR "toolchain incomplete!" ) + message( FATAL_ERROR "libclc toolchain incomplete!" ) endif() list( SORT LIBCLC_TARGETS_TO_BUILD ) if( "spirv-mesa3d-" IN_LIST LIBCLC_TARGETS_TO_BUILD OR "spirv64-mesa3d-" IN_LIST LIBCLC_TARGETS_TO_BUILD ) - if( NOT LLVM_SPIRV ) - message( FATAL_ERROR "SPIR-V targets requested, but spirv-tools is not installed" ) - endif() + if( NOT LLVM_SPIRV ) + message( FATAL_ERROR "SPIR-V targets requested, but spirv-tools is not installed" ) + endif() endif() set( CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ) @@ -99,8 +97,8 @@ set( LLVM_VERSION_DEFINE "-DHAVE_LLVM=0x${LLVM_VERSION_MAJOR}0${LLVM_VERSION_MIN # LLVM 13 enables standard includes by default if( ${LLVM_PACKAGE_VERSION} VERSION_GREATER "12.99.99" ) - set( CMAKE_LLAsm_FLAGS "${CMAKE_LLAsm_FLAGS} -cl-no-stdinc") - set( CMAKE_CLC_FLAGS "${CMAKE_CLC_FLAGS} -cl-no-stdinc") + set( CMAKE_LLAsm_FLAGS "${CMAKE_LLAsm_FLAGS} -cl-no-stdinc" ) + set( CMAKE_CLC_FLAGS "${CMAKE_CLC_FLAGS} -cl-no-stdinc" ) endif() enable_language( CLC LLAsm ) @@ -142,14 +140,14 @@ set( cypress_aliases hemlock ) set( barts_aliases turks caicos ) set( cayman_aliases aruba ) set( tahiti_aliases pitcairn verde oland hainan bonaire kabini kaveri hawaii - mullins tonga tongapro iceland carrizo fiji stoney polaris10 polaris11 - gfx602 gfx705 gfx805 - gfx900 gfx902 gfx904 gfx906 gfx908 gfx909 gfx90a gfx90c gfx940 gfx941 gfx942 - gfx1010 gfx1011 gfx1012 gfx1013 - gfx1030 gfx1031 gfx1032 gfx1033 gfx1034 gfx1035 gfx1036 - gfx1100 gfx1101 gfx1102 gfx1103 - gfx1150 gfx1151 - gfx1200 gfx1201 + mullins tonga tongapro iceland carrizo fiji stoney polaris10 polaris11 + gfx602 gfx705 gfx805 + gfx900 gfx902 gfx904 gfx906 gfx908 gfx909 gfx90a gfx90c gfx940 gfx941 gfx942 + gfx1010 gfx1011 gfx1012 gfx1013 + gfx1030 gfx1031 gfx1032 gfx1033 gfx1034 gfx1035 gfx1036 + gfx1100 gfx1101 gfx1102 gfx1103 + gfx1150 gfx1151 + gfx1200 gfx1201 ) # pkg-config file @@ -158,199 +156,195 @@ install( FILES ${CMAKE_CURRENT_BINARY_DIR}/libclc.pc DESTINATION "${CMAKE_INSTAL install( DIRECTORY generic/include/clc DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" ) if( ENABLE_RUNTIME_SUBNORMAL ) - add_library( subnormal_use_default STATIC - generic/lib/subnormal_use_default.ll ) - add_library( subnormal_disable STATIC - generic/lib/subnormal_disable.ll ) - install( TARGETS subnormal_use_default subnormal_disable ARCHIVE - DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" ) + add_library( subnormal_use_default STATIC + generic/lib/subnormal_use_default.ll ) + add_library( subnormal_disable STATIC + generic/lib/subnormal_disable.ll ) + install( TARGETS subnormal_use_default subnormal_disable ARCHIVE + DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" ) endif() find_package( Python3 REQUIRED COMPONENTS Interpreter ) file( TO_CMAKE_PATH ${CMAKE_SOURCE_DIR}/generic/lib/gen_convert.py script_loc ) add_custom_command( - OUTPUT convert.cl - COMMAND ${Python3_EXECUTABLE} ${script_loc} > convert.cl - DEPENDS ${script_loc} ) + OUTPUT convert.cl + COMMAND ${Python3_EXECUTABLE} ${script_loc} > convert.cl + DEPENDS ${script_loc} ) add_custom_target( "generate_convert.cl" DEPENDS convert.cl ) +add_custom_command( + OUTPUT clspv-convert.cl + COMMAND ${Python3_EXECUTABLE} ${script_loc} --clspv > clspv-convert.cl + DEPENDS ${script_loc} ) +add_custom_target( "clspv-generate_convert.cl" DEPENDS clspv-convert.cl ) + enable_testing() foreach( t ${LIBCLC_TARGETS_TO_BUILD} ) - message( "BUILDING ${t}" ) - string( REPLACE "-" ";" TRIPLE ${t} ) - list( GET TRIPLE 0 ARCH ) - list( GET TRIPLE 1 VENDOR ) - list( GET TRIPLE 2 OS ) - - set( dirs ) - - if ( NOT ${ARCH} STREQUAL spirv AND NOT ${ARCH} STREQUAL spirv64 AND - NOT ${ARCH} STREQUAL clspv AND NOT ${ARCH} STREQUAL clspv64) - LIST( APPEND dirs generic ) - endif() - - if( ${ARCH} STREQUAL r600 OR ${ARCH} STREQUAL amdgcn ) - list( APPEND dirs amdgpu ) - endif() - - #nvptx is special - if( ${ARCH} STREQUAL nvptx OR ${ARCH} STREQUAL nvptx64 ) - set( DARCH ptx ) - else() - set( DARCH ${ARCH} ) - endif() - - # Enumerate SOURCES* files - set( source_list ) - foreach( l ${dirs} ${DARCH} ${DARCH}-${OS} ${DARCH}-${VENDOR}-${OS} ) - foreach( s "SOURCES" "SOURCES_${LLVM_MAJOR}.${LLVM_MINOR}" ) - file( TO_CMAKE_PATH ${l}/lib/${s} file_loc ) - file( TO_CMAKE_PATH ${CMAKE_SOURCE_DIR}/${file_loc} loc ) - # Prepend the location to give higher priority to - # specialized implementation - if( EXISTS ${loc} ) - set( source_list ${file_loc} ${source_list} ) - endif() - endforeach() - endforeach() - - # Add the generated convert.cl here to prevent adding - # the one listed in SOURCES - if( NOT ${ARCH} STREQUAL "spirv" AND NOT ${ARCH} STREQUAL "spirv64" ) - set( rel_files convert.cl ) - set( objects convert.cl ) - if( NOT ENABLE_RUNTIME_SUBNORMAL AND NOT ${ARCH} STREQUAL "clspv" AND - NOT ${ARCH} STREQUAL "clspv64" ) - list( APPEND rel_files generic/lib/subnormal_use_default.ll ) - endif() - else() - set( rel_files ) - set( objects ) - endif() - - foreach( l ${source_list} ) - file( READ ${l} file_list ) - string( REPLACE "\n" ";" file_list ${file_list} ) - get_filename_component( dir ${l} DIRECTORY ) - foreach( f ${file_list} ) - list( FIND objects ${f} found ) - if( found EQUAL -1 ) - list( APPEND objects ${f} ) - list( APPEND rel_files ${dir}/${f} ) - # FIXME: This should really go away - file( TO_CMAKE_PATH ${CMAKE_SOURCE_DIR}/${dir}/${f} src_loc ) - get_filename_component( fdir ${src_loc} DIRECTORY ) - - set_source_files_properties( ${dir}/${f} - PROPERTIES COMPILE_FLAGS "-I ${fdir}" ) - endif() - endforeach() - endforeach() - - foreach( d ${${t}_devices} ) - # Some targets don't have a specific GPU to target - if( ${d} STREQUAL "none" OR ${ARCH} STREQUAL "spirv" OR ${ARCH} STREQUAL "spirv64" ) - set( mcpu ) - set( arch_suffix "${t}" ) - else() - set( mcpu "-mcpu=${d}" ) - set( arch_suffix "${d}-${t}" ) - endif() - message( " DEVICE: ${d} ( ${${d}_aliases} )" ) - - if ( ${ARCH} STREQUAL "spirv" OR ${ARCH} STREQUAL "spirv64" ) - if( ${ARCH} STREQUAL "spirv" ) - set( t "spir--" ) - else() - set( t "spir64--" ) - endif() - set( build_flags -O0 -finline-hint-functions ) - set( opt_flags ) - set( spvflags --spirv-max-version=1.1 ) - elseif( ${ARCH} STREQUAL "clspv" ) - set( t "spir--" ) - set( build_flags "-Wno-unknown-assumption") - set( opt_flags -O3 ) - elseif( ${ARCH} STREQUAL "clspv64" ) - set( t "spir64--" ) - set( build_flags "-Wno-unknown-assumption") - set( opt_flags -O3 ) - else() - set( build_flags ) - set( opt_flags -O3 ) - endif() - - add_library( builtins.link.${arch_suffix} STATIC ${rel_files} ) - # Make sure we depend on the pseudo target to prevent - # multiple invocations - add_dependencies( builtins.link.${arch_suffix} - generate_convert.cl ) - # CMake will turn this include into absolute path - target_include_directories( builtins.link.${arch_suffix} PRIVATE - "generic/include" ) - target_compile_definitions( builtins.link.${arch_suffix} PRIVATE - "__CLC_INTERNAL" ) - string( TOUPPER "-DCLC_${ARCH}" CLC_TARGET_DEFINE ) - target_compile_definitions( builtins.link.${arch_suffix} PRIVATE - ${CLC_TARGET_DEFINE} ) - target_compile_options( builtins.link.${arch_suffix} PRIVATE -target - ${t} ${mcpu} -fno-builtin -nostdlib ${build_flags} ) - set_target_properties( builtins.link.${arch_suffix} PROPERTIES - LINKER_LANGUAGE CLC ) - - set( obj_suffix ${arch_suffix}.bc ) - - # Add opt target - add_custom_command( OUTPUT "builtins.opt.${obj_suffix}" - COMMAND ${LLVM_OPT} ${opt_flags} -o - "builtins.opt.${obj_suffix}" - "builtins.link.${obj_suffix}" - DEPENDS "builtins.link.${arch_suffix}" ) - add_custom_target( "opt.${obj_suffix}" ALL - DEPENDS "builtins.opt.${obj_suffix}" ) - - if( ${ARCH} STREQUAL "spirv" OR ${ARCH} STREQUAL "spirv64" ) - set( spv_suffix ${arch_suffix}.spv ) - add_custom_command( OUTPUT "${spv_suffix}" - COMMAND ${LLVM_SPIRV} ${spvflags} - -o "${spv_suffix}" - "builtins.link.${obj_suffix}" - DEPENDS "builtins.link.${arch_suffix}" ) - add_custom_target( "prepare-${spv_suffix}" ALL - DEPENDS "${spv_suffix}" ) - install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${spv_suffix} - DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" ) - else() - - # Add prepare target - add_custom_command( OUTPUT "${obj_suffix}" - COMMAND prepare_builtins -o - "${obj_suffix}" - "builtins.opt.${obj_suffix}" - DEPENDS "opt.${obj_suffix}" - "builtins.opt.${obj_suffix}" - prepare_builtins ) - add_custom_target( "prepare-${obj_suffix}" ALL - DEPENDS "${obj_suffix}" ) - - # nvptx-- targets don't include workitem builtins - if( NOT ${t} MATCHES ".*ptx.*--$" ) - add_test( NAME external-calls-${obj_suffix} - COMMAND ./check_external_calls.sh ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} ${LLVM_TOOLS_BINARY_DIR} - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) - endif() - - install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" ) - foreach( a ${${d}_aliases} ) - set( alias_suffix "${a}-${t}.bc" ) - add_custom_target( ${alias_suffix} ALL - COMMAND ${CMAKE_COMMAND} -E - create_symlink ${obj_suffix} - ${alias_suffix} - DEPENDS "prepare-${obj_suffix}" ) - install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${alias_suffix} DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" ) - endforeach( a ) - endif() - endforeach( d ) + message( STATUS "libclc target '${t}' is enabled" ) + string( REPLACE "-" ";" TRIPLE ${t} ) + list( GET TRIPLE 0 ARCH ) + list( GET TRIPLE 1 VENDOR ) + list( GET TRIPLE 2 OS ) + + set( dirs ) + + if ( NOT ${ARCH} STREQUAL spirv AND NOT ${ARCH} STREQUAL spirv64 AND + NOT ${ARCH} STREQUAL clspv AND NOT ${ARCH} STREQUAL clspv64) + LIST( APPEND dirs generic ) + endif() + + if( ${ARCH} STREQUAL r600 OR ${ARCH} STREQUAL amdgcn ) + list( APPEND dirs amdgpu ) + endif() + + #nvptx is special + if( ${ARCH} STREQUAL nvptx OR ${ARCH} STREQUAL nvptx64 ) + set( DARCH ptx ) + else() + set( DARCH ${ARCH} ) + endif() + + # Enumerate SOURCES* files + set( source_list ) + foreach( l ${dirs} ${DARCH} ${DARCH}-${OS} ${DARCH}-${VENDOR}-${OS} ) + foreach( s "SOURCES" "SOURCES_${LLVM_MAJOR}.${LLVM_MINOR}" ) + file( TO_CMAKE_PATH ${l}/lib/${s} file_loc ) + file( TO_CMAKE_PATH ${CMAKE_SOURCE_DIR}/${file_loc} loc ) + # Prepend the location to give higher priority to + # specialized implementation + if( EXISTS ${loc} ) + set( source_list ${file_loc} ${source_list} ) + endif() + endforeach() + endforeach() + + # Add the generated convert.cl here to prevent adding + # the one listed in SOURCES + if( NOT ${ARCH} STREQUAL "spirv" AND NOT ${ARCH} STREQUAL "spirv64" ) + if( NOT ENABLE_RUNTIME_SUBNORMAL AND NOT ${ARCH} STREQUAL "clspv" AND + NOT ${ARCH} STREQUAL "clspv64" ) + set( rel_files convert.cl ) + set( objects convert.cl ) + list( APPEND rel_files generic/lib/subnormal_use_default.ll ) + elseif(${ARCH} STREQUAL "clspv" OR ${ARCH} STREQUAL "clspv64") + set( rel_files clspv-convert.cl ) + set( objects clspv-convert.cl ) + endif() + else() + set( rel_files ) + set( objects ) + endif() + + foreach( l ${source_list} ) + file( READ ${l} file_list ) + string( REPLACE "\n" ";" file_list ${file_list} ) + get_filename_component( dir ${l} DIRECTORY ) + foreach( f ${file_list} ) + list( FIND objects ${f} found ) + if( found EQUAL -1 ) + list( APPEND objects ${f} ) + list( APPEND rel_files ${dir}/${f} ) + # FIXME: This should really go away + file( TO_CMAKE_PATH ${CMAKE_SOURCE_DIR}/${dir}/${f} src_loc ) + get_filename_component( fdir ${src_loc} DIRECTORY ) + + set_source_files_properties( ${dir}/${f} + PROPERTIES COMPILE_FLAGS "-I ${fdir}" ) + endif() + endforeach() + endforeach() + + foreach( d ${${t}_devices} ) + # Some targets don't have a specific GPU to target + if( ${d} STREQUAL "none" OR ${ARCH} STREQUAL "spirv" OR ${ARCH} STREQUAL "spirv64" ) + set( mcpu ) + set( arch_suffix "${t}" ) + else() + set( mcpu "-mcpu=${d}" ) + set( arch_suffix "${d}-${t}" ) + endif() + message( STATUS " device: ${d} ( ${${d}_aliases} )" ) + + if ( ${ARCH} STREQUAL "spirv" OR ${ARCH} STREQUAL "spirv64" ) + if( ${ARCH} STREQUAL "spirv" ) + set( t "spir--" ) + else() + set( t "spir64--" ) + endif() + set( build_flags -O0 -finline-hint-functions ) + set( opt_flags ) + set( spvflags --spirv-max-version=1.1 ) + elseif( ${ARCH} STREQUAL "clspv" ) + set( t "spir--" ) + set( build_flags "-Wno-unknown-assumption") + set( opt_flags -O3 ) + elseif( ${ARCH} STREQUAL "clspv64" ) + set( t "spir64--" ) + set( build_flags "-Wno-unknown-assumption") + set( opt_flags -O3 ) + else() + set( build_flags ) + set( opt_flags -O3 ) + endif() + + add_library( builtins.link.${arch_suffix} STATIC ${rel_files} ) + # Make sure we depend on the pseudo target to prevent + # multiple invocations + add_dependencies( builtins.link.${arch_suffix} generate_convert.cl ) + add_dependencies( builtins.link.${arch_suffix} clspv-generate_convert.cl ) + # CMake will turn this include into absolute path + target_include_directories( builtins.link.${arch_suffix} PRIVATE + "generic/include" ) + target_compile_definitions( builtins.link.${arch_suffix} PRIVATE + "__CLC_INTERNAL" ) + string( TOUPPER "-DCLC_${ARCH}" CLC_TARGET_DEFINE ) + target_compile_definitions( builtins.link.${arch_suffix} PRIVATE + ${CLC_TARGET_DEFINE} ) + target_compile_options( builtins.link.${arch_suffix} PRIVATE -target + ${t} ${mcpu} -fno-builtin -nostdlib ${build_flags} ) + set_target_properties( builtins.link.${arch_suffix} PROPERTIES + LINKER_LANGUAGE CLC ) + + set( obj_suffix ${arch_suffix}.bc ) + + # Add opt target + add_custom_command( OUTPUT "builtins.opt.${obj_suffix}" + COMMAND ${LLVM_OPT} ${opt_flags} -o "builtins.opt.${obj_suffix}" "builtins.link.${obj_suffix}" + DEPENDS "builtins.link.${arch_suffix}" ) + add_custom_target( "opt.${obj_suffix}" ALL + DEPENDS "builtins.opt.${obj_suffix}" ) + + if( ${ARCH} STREQUAL "spirv" OR ${ARCH} STREQUAL "spirv64" ) + set( spv_suffix ${arch_suffix}.spv ) + add_custom_command( OUTPUT "${spv_suffix}" + COMMAND ${LLVM_SPIRV} ${spvflags} -o "${spv_suffix}" "builtins.link.${obj_suffix}" + DEPENDS "builtins.link.${arch_suffix}" ) + add_custom_target( "prepare-${spv_suffix}" ALL DEPENDS "${spv_suffix}" ) + install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${spv_suffix} + DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" ) + else() + # Add prepare target + add_custom_command( OUTPUT "${obj_suffix}" + COMMAND prepare_builtins -o "${obj_suffix}" "builtins.opt.${obj_suffix}" + DEPENDS "opt.${obj_suffix}" "builtins.opt.${obj_suffix}" prepare_builtins ) + add_custom_target( "prepare-${obj_suffix}" ALL DEPENDS "${obj_suffix}" ) + + # nvptx-- targets don't include workitem builtins + if( NOT ${t} MATCHES ".*ptx.*--$" ) + add_test( NAME external-calls-${obj_suffix} + COMMAND ./check_external_calls.sh ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} ${LLVM_TOOLS_BINARY_DIR} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) + endif() + + install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${obj_suffix} DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" ) + foreach( a ${${d}_aliases} ) + set( alias_suffix "${a}-${t}.bc" ) + add_custom_target( ${alias_suffix} ALL + COMMAND ${CMAKE_COMMAND} -E create_symlink ${obj_suffix} ${alias_suffix} + DEPENDS "prepare-${obj_suffix}" ) + install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${alias_suffix} DESTINATION "${CMAKE_INSTALL_DATADIR}/clc" ) + endforeach( a ) + endif() + endforeach( d ) endforeach( t ) diff --git a/libclc/check_external_calls.sh b/libclc/check_external_calls.sh index 4de31a220d070f53f1d67b47a169b5055453e380..25792e249d6b665671e4da5ffd987bcee3169175 100755 --- a/libclc/check_external_calls.sh +++ b/libclc/check_external_calls.sh @@ -3,15 +3,15 @@ FILE=$1 BIN_DIR=$2 if [ ! -f $FILE ]; then - echo "ERROR: Not a file: $FILE" - exit 3 + echo "ERROR: Not a file: $FILE" + exit 3 fi ret=0 DIS="$BIN_DIR/llvm-dis" if [ ! -x $DIS ]; then - echo "ERROR: Disassembler '$DIS' is not executable" - exit 3 + echo "ERROR: Disassembler '$DIS' is not executable" + exit 3 fi TMP_FILE=$(mktemp) @@ -21,10 +21,10 @@ $DIS < $FILE | grep ' call ' | grep -v '@llvm' > "$TMP_FILE" COUNT=$(wc -l < "$TMP_FILE") if [ "$COUNT" -ne "0" ]; then - echo "ERROR: $COUNT unresolved calls detected in $FILE" - cat $TMP_FILE - ret=1 + echo "ERROR: $COUNT unresolved calls detected in $FILE" + cat $TMP_FILE + ret=1 else - echo "File $FILE is OK" + echo "File $FILE is OK" fi exit $ret diff --git a/libclc/cmake/CMakeCLCInformation.cmake b/libclc/cmake/CMakeCLCInformation.cmake index 6eecf4edf0e7bbd81b96b5c34f8ed9b96ffffb59..95327e44397222a5adf056b9d64aed0a2d5679ce 100644 --- a/libclc/cmake/CMakeCLCInformation.cmake +++ b/libclc/cmake/CMakeCLCInformation.cmake @@ -9,3 +9,4 @@ if(NOT CMAKE_CLC_CREATE_STATIC_LIBRARY) endif() set(CMAKE_INCLUDE_FLAG_CLC "-I") +set(CMAKE_DEPFILE_FLAGS_CLC "-MD -MT <DEP_TARGET> -MF <DEP_FILE>") diff --git a/libclc/cmake/CMakeLLAsmInformation.cmake b/libclc/cmake/CMakeLLAsmInformation.cmake index 218e20a52fe8236ceb30de70ac4b0301c98a2bb1..35ec3081da0f7dffe27aa91af675af0a7f7ffb83 100644 --- a/libclc/cmake/CMakeLLAsmInformation.cmake +++ b/libclc/cmake/CMakeLLAsmInformation.cmake @@ -1,7 +1,7 @@ if(NOT CMAKE_LLAsm_COMPILE_OBJECT) set(CMAKE_LLAsm_COMPILE_OBJECT - "${CMAKE_LLAsm_PREPROCESSOR} -E -P <DEFINES> <INCLUDES> <FLAGS> -x cl <SOURCE> -o <OBJECT>.temp" - "<CMAKE_LLAsm_COMPILER> -o <OBJECT> <OBJECT>.temp") + "${CMAKE_LLAsm_PREPROCESSOR} -E -P <DEFINES> <INCLUDES> <FLAGS> -x cl <SOURCE> -o <OBJECT>.temp" + "<CMAKE_LLAsm_COMPILER> -o <OBJECT> <OBJECT>.temp") endif() if(NOT CMAKE_LLAsm_CREATE_STATIC_LIBRARY) diff --git a/libclc/generic/lib/gen_convert.py b/libclc/generic/lib/gen_convert.py index 612a9184f4b27194169f7be3eeb2d5a55244c315..21fc8ebc80d1562b82d70530ffbc1ccf485a1e1c 100644 --- a/libclc/generic/lib/gen_convert.py +++ b/libclc/generic/lib/gen_convert.py @@ -2,6 +2,7 @@ # # Copyright (c) 2013 Victor Oliveira <victormatheus@gmail.com> # Copyright (c) 2013 Jesse Towner <jessetowner@lavabit.com> +# Copyright (c) 2024 Romaric Jodin <rjodin@chromium.org> # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -26,6 +27,16 @@ # # convert_<destTypen><_sat><_roundingMode>(<sourceTypen>) +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument( + "--clspv", action="store_true", help="Generate the clspv variant of the code" +) +args = parser.parse_args() + +clspv = args.clspv + types = [ "char", "uchar", @@ -251,13 +262,19 @@ def generate_default_conversion(src, dst, mode): print("#endif") -for src in types: - for dst in types: - generate_default_conversion(src, dst, "") +# Do not generate default conversion for clspv as they are handled natively +if not clspv: + for src in types: + for dst in types: + generate_default_conversion(src, dst, "") for src in int_types: for dst in int_types: for mode in rounding_modes: + # Do not generate "_rte" conversion for clspv as they are handled + # natively + if clspv and mode == "_rte": + continue generate_default_conversion(src, dst, mode) # @@ -304,21 +321,38 @@ def generate_saturated_conversion(src, dst, size): elif src in float_types: - # Conversion from float to int - print( - """ {DST}{N} y = convert_{DST}{N}(x); - y = select(y, ({DST}{N}){DST_MIN}, {BP}(x < ({SRC}{N}){DST_MIN}){BS}); - y = select(y, ({DST}{N}){DST_MAX}, {BP}(x > ({SRC}{N}){DST_MAX}){BS}); - return y;""".format( - SRC=src, - DST=dst, - N=size, - DST_MIN=limit_min[dst], - DST_MAX=limit_max[dst], - BP=bool_prefix, - BS=bool_suffix, + if clspv: + # Conversion from float to int + print( + """ {DST}{N} y = convert_{DST}{N}(x); + y = select(y, ({DST}{N}){DST_MIN}, {BP}(x <= ({SRC}{N}){DST_MIN}){BS}); + y = select(y, ({DST}{N}){DST_MAX}, {BP}(x >= ({SRC}{N}){DST_MAX}){BS}); + return y;""".format( + SRC=src, + DST=dst, + N=size, + DST_MIN=limit_min[dst], + DST_MAX=limit_max[dst], + BP=bool_prefix, + BS=bool_suffix, + ) + ) + else: + # Conversion from float to int + print( + """ {DST}{N} y = convert_{DST}{N}(x); + y = select(y, ({DST}{N}){DST_MIN}, {BP}(x < ({SRC}{N}){DST_MIN}){BS}); + y = select(y, ({DST}{N}){DST_MAX}, {BP}(x > ({SRC}{N}){DST_MAX}){BS}); + return y;""".format( + SRC=src, + DST=dst, + N=size, + DST_MIN=limit_min[dst], + DST_MAX=limit_max[dst], + BP=bool_prefix, + BS=bool_suffix, + ) ) - ) else: @@ -432,7 +466,10 @@ def generate_float_conversion(src, dst, size, mode, sat): print(" return convert_{DST}{N}(x);".format(DST=dst, N=size)) else: print(" {DST}{N} r = convert_{DST}{N}(x);".format(DST=dst, N=size)) - print(" {SRC}{N} y = convert_{SRC}{N}(r);".format(SRC=src, N=size)) + if clspv: + print(" {SRC}{N} y = convert_{SRC}{N}_sat(r);".format(SRC=src, N=size)) + else: + print(" {SRC}{N} y = convert_{SRC}{N}(r);".format(SRC=src, N=size)) if mode == "_rtz": if src in int_types: print( @@ -448,11 +485,29 @@ def generate_float_conversion(src, dst, size, mode, sat): else: print(" {SRC}{N} abs_x = fabs(x);".format(SRC=src, N=size)) print(" {SRC}{N} abs_y = fabs(y);".format(SRC=src, N=size)) - print( - " return select(r, nextafter(r, sign(r) * ({DST}{N})-INFINITY), convert_{BOOL}{N}(abs_y > abs_x));".format( - DST=dst, N=size, BOOL=bool_type[dst] + if clspv: + print( + " {BOOL}{N} c = convert_{BOOL}{N}(abs_y > abs_x);".format( + BOOL=bool_type[dst], N=size + ) + ) + if sizeof_type[src] >= 4 and src in int_types: + print( + " c = c || convert_{BOOL}{N}(({SRC}{N}){SRC_MAX} == x);".format( + BOOL=bool_type[dst], N=size, SRC=src, SRC_MAX=limit_max[src] + ) + ) + print( + " return select(r, nextafter(r, sign(r) * ({DST}{N})-INFINITY), c);".format( + DST=dst, N=size, BOOL=bool_type[dst], SRC=src + ) + ) + else: + print( + " return select(r, nextafter(r, sign(r) * ({DST}{N})-INFINITY), convert_{BOOL}{N}(abs_y > abs_x));".format( + DST=dst, N=size, BOOL=bool_type[dst] + ) ) - ) if mode == "_rtp": print( " return select(r, nextafter(r, ({DST}{N})INFINITY), convert_{BOOL}{N}(y < x));".format( @@ -460,11 +515,29 @@ def generate_float_conversion(src, dst, size, mode, sat): ) ) if mode == "_rtn": - print( - " return select(r, nextafter(r, ({DST}{N})-INFINITY), convert_{BOOL}{N}(y > x));".format( - DST=dst, N=size, BOOL=bool_type[dst] + if clspv: + print( + " {BOOL}{N} c = convert_{BOOL}{N}(y > x);".format( + BOOL=bool_type[dst], N=size + ) + ) + if sizeof_type[src] >= 4 and src in int_types: + print( + " c = c || convert_{BOOL}{N}(({SRC}{N}){SRC_MAX} == x);".format( + BOOL=bool_type[dst], N=size, SRC=src, SRC_MAX=limit_max[src] + ) + ) + print( + " return select(r, nextafter(r, ({DST}{N})-INFINITY), c);".format( + DST=dst, N=size, BOOL=bool_type[dst], SRC=src + ) + ) + else: + print( + " return select(r, nextafter(r, ({DST}{N})-INFINITY), convert_{BOOL}{N}(y > x));".format( + DST=dst, N=size, BOOL=bool_type[dst] + ) ) - ) # Footer print("}") @@ -484,4 +557,8 @@ for src in types: for dst in float_types: for size in vector_sizes: for mode in rounding_modes: + # Do not generate "_rte" conversion for clspv as they are + # handled natively + if clspv and mode == "_rte": + continue generate_float_conversion(src, dst, size, mode, "") diff --git a/libcxx/benchmarks/CMakeLists.txt b/libcxx/benchmarks/CMakeLists.txt index b436e96f178b70711dc8ef59474920d2085fe8c6..387e013afeb6c4fca3c58f3c30dc60ea52c4c802 100644 --- a/libcxx/benchmarks/CMakeLists.txt +++ b/libcxx/benchmarks/CMakeLists.txt @@ -176,12 +176,14 @@ set(BENCHMARK_TESTS algorithms/count.bench.cpp algorithms/equal.bench.cpp algorithms/find.bench.cpp + algorithms/fill.bench.cpp algorithms/for_each.bench.cpp algorithms/lower_bound.bench.cpp algorithms/make_heap.bench.cpp algorithms/make_heap_then_sort_heap.bench.cpp algorithms/min.bench.cpp algorithms/min_max_element.bench.cpp + algorithms/mismatch.bench.cpp algorithms/pop_heap.bench.cpp algorithms/pstl.stable_sort.bench.cpp algorithms/push_heap.bench.cpp diff --git a/libcxx/benchmarks/algorithms/fill.bench.cpp b/libcxx/benchmarks/algorithms/fill.bench.cpp new file mode 100644 index 0000000000000000000000000000000000000000..40f37425c394cf0a1fd68df41aef6c12fb43ec81 --- /dev/null +++ b/libcxx/benchmarks/algorithms/fill.bench.cpp @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// 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 <algorithm> +#include <benchmark/benchmark.h> +#include <vector> + +static void bm_fill_n(benchmark::State& state) { + std::vector<bool> vec1(state.range()); + for (auto _ : state) { + benchmark::DoNotOptimize(vec1); + benchmark::DoNotOptimize(std::fill_n(vec1.begin(), vec1.size(), false)); + } +} +BENCHMARK(bm_fill_n)->DenseRange(1, 8)->Range(16, 1 << 20); + +static void bm_ranges_fill_n(benchmark::State& state) { + std::vector<bool> vec1(state.range()); + for (auto _ : state) { + benchmark::DoNotOptimize(vec1); + benchmark::DoNotOptimize(std::ranges::fill_n(vec1.begin(), vec1.size(), false)); + } +} +BENCHMARK(bm_ranges_fill_n)->DenseRange(1, 8)->Range(16, 1 << 20); + +static void bm_fill(benchmark::State& state) { + std::vector<bool> vec1(state.range()); + for (auto _ : state) { + benchmark::DoNotOptimize(vec1); + std::fill(vec1.begin(), vec1.end(), false); + } +} +BENCHMARK(bm_fill)->DenseRange(1, 8)->Range(16, 1 << 20); + +static void bm_ranges_fill(benchmark::State& state) { + std::vector<bool> vec1(state.range()); + for (auto _ : state) { + benchmark::DoNotOptimize(vec1); + benchmark::DoNotOptimize(std::ranges::fill(vec1, false)); + } +} +BENCHMARK(bm_ranges_fill)->DenseRange(1, 8)->Range(16, 1 << 20); + +BENCHMARK_MAIN(); diff --git a/libcxx/benchmarks/algorithms/mismatch.bench.cpp b/libcxx/benchmarks/algorithms/mismatch.bench.cpp new file mode 100644 index 0000000000000000000000000000000000000000..791782879011e258e98d8f686e304e52211c36ec --- /dev/null +++ b/libcxx/benchmarks/algorithms/mismatch.bench.cpp @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// 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 <algorithm> +#include <benchmark/benchmark.h> +#include <random> + +void BenchmarkSizes(benchmark::internal::Benchmark* Benchmark) { + Benchmark->DenseRange(1, 8); + for (size_t i = 16; i != 1 << 20; i *= 2) { + Benchmark->Arg(i - 1); + Benchmark->Arg(i); + Benchmark->Arg(i + 1); + } +} + +// TODO: Look into benchmarking aligned and unaligned memory explicitly +// (currently things happen to be aligned because they are malloced that way) +template <class T> +static void bm_mismatch(benchmark::State& state) { + std::vector<T> vec1(state.range(), '1'); + std::vector<T> vec2(state.range(), '1'); + std::mt19937_64 rng(std::random_device{}()); + + vec1.back() = '2'; + for (auto _ : state) { + benchmark::DoNotOptimize(vec1); + benchmark::DoNotOptimize(std::mismatch(vec1.begin(), vec1.end(), vec2.begin())); + } +} +BENCHMARK(bm_mismatch<char>)->Apply(BenchmarkSizes); +BENCHMARK(bm_mismatch<short>)->Apply(BenchmarkSizes); +BENCHMARK(bm_mismatch<int>)->Apply(BenchmarkSizes); + +template <class T> +static void bm_mismatch_two_range_overload(benchmark::State& state) { + std::vector<T> vec1(state.range(), '1'); + std::vector<T> vec2(state.range(), '1'); + std::mt19937_64 rng(std::random_device{}()); + + vec1.back() = '2'; + for (auto _ : state) { + benchmark::DoNotOptimize(vec1); + benchmark::DoNotOptimize(std::mismatch(vec1.begin(), vec1.end(), vec2.begin(), vec2.end())); + } +} +BENCHMARK(bm_mismatch_two_range_overload<char>)->DenseRange(1, 8)->Range(16, 1 << 20); +BENCHMARK(bm_mismatch_two_range_overload<short>)->DenseRange(1, 8)->Range(16, 1 << 20); +BENCHMARK(bm_mismatch_two_range_overload<int>)->DenseRange(1, 8)->Range(16, 1 << 20); + +BENCHMARK_MAIN(); diff --git a/libcxx/docs/DesignDocs/NodiscardPolicy.rst b/libcxx/docs/DesignDocs/NodiscardPolicy.rst new file mode 100644 index 0000000000000000000000000000000000000000..afbb18b0096d734b4d78043e2cc643e7e5e81760 --- /dev/null +++ b/libcxx/docs/DesignDocs/NodiscardPolicy.rst @@ -0,0 +1,42 @@ +=================================================== +Guidelines for applying ``[[nodiscard]]`` in libc++ +=================================================== + +Libc++ adds ``[[nodiscard]]`` to functions in a lot of places. The standards +committee has decided to not have a recommended practice where to put them, so +this document lists where ``[[nodiscard]]`` should be applied in libc++. + +When should ``[[nodiscard]]`` be added to functions? +==================================================== + +``[[nodiscard]]`` should be applied to functions + +- where discarding the return value is most likely a correctness issue. + For example a locking constructor in ``unique_lock``. + +- where discarding the return value likely points to the user wanting to do + something different. For example ``vector::empty()``, which probably should + have been ``vector::clear()``. + + This can help spotting bugs easily which otherwise may take a very long time + to find. + +- which return a constant. For example ``numeric_limits::min()``. +- which only observe a value. For example ``string::size()``. + + Code that discards values from these kinds of functions is dead code. It can + either be removed, or the programmer meant to do something different. + +- where discarding the value is most likely a misuse of the function. For + example ``find``. + + This protects programmers from assuming too much about how the internals of + a function work, making code more robust in the presence of future + optimizations. + +What should be done when adding ``[[nodiscard]]`` to a function? +================================================================ + +Applications of ``[[nodiscard]]`` are code like any other code, so we aim to +test them. This can be done with a ``.verify.cpp`` test. Many examples are +available. Just look for tests with the suffix ``.nodiscard.verify.cpp``. diff --git a/libcxx/docs/Modules.rst b/libcxx/docs/Modules.rst index ee2b81d3b9e7ca64efb3395a7989997076d0af66..5b027ed1bd0729a238bd91b2b1feb79430fa4c17 100644 --- a/libcxx/docs/Modules.rst +++ b/libcxx/docs/Modules.rst @@ -178,34 +178,13 @@ This is a small sample program that uses the module ``std``. It consists of a ) FetchContent_MakeAvailable(std) - # - # Adjust project compiler flags - # - - add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fprebuilt-module-path=${std_BINARY_DIR}/CMakeFiles/std.dir/>) - add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fprebuilt-module-path=${std_BINARY_DIR}/CMakeFiles/std.compat.dir/>) - add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-nostdinc++>) - # The include path needs to be set to be able to use macros from headers. - # For example from, the headers <cassert> and <version>. - add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-isystem>) - add_compile_options($<$<COMPILE_LANGUAGE:CXX>:${LIBCXX_BUILD}/include/c++/v1>) - - # - # Adjust project linker flags - # - - add_link_options($<$<COMPILE_LANGUAGE:CXX>:-nostdlib++>) - add_link_options($<$<COMPILE_LANGUAGE:CXX>:-L${LIBCXX_BUILD}/lib>) - add_link_options($<$<COMPILE_LANGUAGE:CXX>:-Wl,-rpath,${LIBCXX_BUILD}/lib>) - # Linking against the standard c++ library is required for CMake to get the proper dependencies. - link_libraries(std c++) - link_libraries(std.compat c++) - # # Add the project # add_executable(main) + add_dependencies(main std.compat) + target_link_libraries(main std.compat) target_sources(main PRIVATE main.cpp @@ -218,13 +197,9 @@ Building this project is done with the following steps, assuming the files $ mkdir build $ cmake -G Ninja -S . -B build -DCMAKE_CXX_COMPILER=<path-to-compiler> -DLIBCXX_BUILD=<build> - $ ninja -j1 std -C build $ ninja -C build $ build/main -.. note:: The ``std`` dependencies of ``std.compat`` is not always resolved when - building the ``std`` target using multiple jobs. - .. warning:: ``<path-to-compiler>`` should point point to the real binary and not to a symlink. diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst index 04f16610f8117ee6d8e7d0bd3ba02ec66a16f646..dd39c1bbbc78a31972a510f4ced8ed123c8e44a9 100644 --- a/libcxx/docs/ReleaseNotes/19.rst +++ b/libcxx/docs/ReleaseNotes/19.rst @@ -49,6 +49,10 @@ Improvements and New Features ----------------------------- - The performance of growing ``std::vector`` has been improved for trivially relocatable types. +- The performance of ``ranges::fill`` and ``ranges::fill_n`` has been improved for ``vector<bool>::iterator``\s, + resulting in a performance increase of up to 1400x. +- The ``std::mismatch`` algorithm has been optimized for integral types, which can lead up to 40x performance + improvements. Deprecations and Removals ------------------------- @@ -65,10 +69,11 @@ Deprecations and Removals provided, and such a base template is bound to be incorrect for some types, which could currently cause unexpected behavior while going undetected. -- TODO: The ``_LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT`` macro that changed the behavior for narrowing conversions +- The ``_LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT`` macro that changed the behavior for narrowing conversions in ``std::variant`` has been removed in LLVM 19. -- TODO: The ``_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS`` macro has been removed in LLVM 19. +- The ``_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS`` and ``_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_VOID_SPECIALIZATION`` + macros have been removed in LLVM 19. - TODO: The ``_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES`` and ``_LIBCPP_ENABLE_CXX20_REMOVED_FEATURES`` macros have been removed in LLVM 19. C++17 and C++20 removed features can still be re-enabled individually. diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv index e00345533b865d35ac2d32f4609e08a0ee330fb1..ebdc4a745c9f2ff7b45a00eb3e4ca02ea2169e1a 100644 --- a/libcxx/docs/Status/Cxx23Issues.csv +++ b/libcxx/docs/Status/Cxx23Issues.csv @@ -46,7 +46,7 @@ "`3473 <https://wg21.link/LWG3473>`__","Normative encouragement in non-normative note","November 2020","|Complete|","15.0","|format|" "`3474 <https://wg21.link/LWG3474>`__","Nesting ``join_views`` is broken because of CTAD","November 2020","|Complete|","15.0","|ranges|" "`3476 <https://wg21.link/LWG3476>`__","``thread`` and ``jthread`` constructors require that the parameters be move-constructible but never move construct the parameters","November 2020","","" -"`3477 <https://wg21.link/LWG3477>`__","Simplify constraints for ``semiregular-box``","November 2020","","","|ranges|" +"`3477 <https://wg21.link/LWG3477>`__","Simplify constraints for ``semiregular-box``","November 2020","|Complete|","13.0","|ranges|" "`3482 <https://wg21.link/LWG3482>`__","``drop_view``'s const begin should additionally require ``sized_range``","November 2020","|Complete|","14.0","|ranges|" "`3483 <https://wg21.link/LWG3483>`__","``transform_view::iterator``'s difference is overconstrained","November 2020","|Complete|","14.0","|ranges|" "","","","","","" @@ -77,7 +77,7 @@ `3523 <https://wg21.link/LWG3523>`__,"``iota_view::sentinel`` is not always ``iota_view``'s sentinel","June 2021","","","|ranges|" `3526 <https://wg21.link/LWG3526>`__,"Return types of ``uses_allocator_construction_args`` unspecified","June 2021","","" `3527 <https://wg21.link/LWG3527>`__,"``uses_allocator_construction_args`` handles rvalue pairs of rvalue references incorrectly","June 2021","","" -`3528 <https://wg21.link/LWG3528>`__,"``make_from_tuple`` can perform (the equivalent of) a C-style cast","June 2021","","" +`3528 <https://wg21.link/LWG3528>`__,"``make_from_tuple`` can perform (the equivalent of) a C-style cast","June 2021","|Complete|","19.0" `3529 <https://wg21.link/LWG3529>`__,"``priority_queue(first, last)`` should construct ``c`` with ``(first, last)``","June 2021","|Complete|","14.0" `3530 <https://wg21.link/LWG3530>`__,"``BUILTIN-PTR-MEOW`` should not opt the type out of syntactic checks","June 2021","","" `3532 <https://wg21.link/LWG3532>`__,"``split_view<V, P>::inner-iterator<true>::operator++(int)`` should depend on ``Base``","June 2021","","","|ranges|" @@ -181,7 +181,7 @@ "`3711 <https://wg21.link/LWG3711>`__","Missing preconditions for slide_view constructor","July 2022","","","|ranges|" "`3712 <https://wg21.link/LWG3712>`__","``chunk_view`` and ``slide_view`` should not be ``default_initializable``","July 2022","","","|ranges|" "`3713 <https://wg21.link/LWG3713>`__","Sorted with respect to comparator (only)","July 2022","","" -"`3715 <https://wg21.link/LWG3715>`__","``view_interface::empty`` is overconstrained","July 2022","","","|ranges|" +"`3715 <https://wg21.link/LWG3715>`__","``view_interface::empty`` is overconstrained","July 2022","|Complete|","19.0","|ranges|" "`3719 <https://wg21.link/LWG3719>`__","Directory iterators should be usable with default sentinel","July 2022","|Complete|","17.0","|ranges|" "`3721 <https://wg21.link/LWG3721>`__","Allow an ``arg-id`` with a value of zero for ``width`` in ``std-format-spec``","July 2022","|Complete|","16.0","|format|" "`3724 <https://wg21.link/LWG3724>`__","``decay-copy`` should be constrained","July 2022","|Complete|","14.0" @@ -283,7 +283,7 @@ "`3655 <https://wg21.link/LWG3655>`__","The ``INVOKE`` operation and union types","February 2023","|Complete|","18.0","" "`3723 <https://wg21.link/LWG3723>`__","``priority_queue::push_range`` needs to ``append_range``","February 2023","","","|ranges|" "`3734 <https://wg21.link/LWG3734>`__","Inconsistency in ``inout_ptr`` and ``out_ptr`` for empty case","February 2023","","","" -"`3772 <https://wg21.link/LWG3772>`__","``repeat_view``'s ``piecewise`` constructor is missing Postconditions","February 2023","","","|ranges|" +"`3772 <https://wg21.link/LWG3772>`__","``repeat_view``'s ``piecewise`` constructor is missing Postconditions","February 2023","|Complete|","17.0","|ranges|" "`3786 <https://wg21.link/LWG3786>`__","Flat maps' deduction guide needs to default ``Allocator`` to be useful","February 2023","","","" "`3803 <https://wg21.link/LWG3803>`__","``flat_foo`` constructors taking ``KeyContainer`` lack ``KeyCompare`` parameter","February 2023","","","" "`3810 <https://wg21.link/LWG3810>`__","CTAD for ``std::basic_format_args``","February 2023","|Complete|","17.0","|format|" @@ -295,7 +295,7 @@ "`3847 <https://wg21.link/LWG3847>`__","``ranges::to`` can still return views","February 2023","|Complete|","17.0","|ranges|" "`3862 <https://wg21.link/LWG3862>`__","``basic_const_iterator``'s ``common_type`` specialization is underconstrained","February 2023","","","" "`3865 <https://wg21.link/LWG3865>`__","Sorting a range of ``pairs``","February 2023","|Complete|","17.0","|ranges|" -"`3869 <https://wg21.link/LWG3869>`__","Deprecate ``std::errc`` constants related to UNIX STREAMS","February 2023","","","" +"`3869 <https://wg21.link/LWG3869>`__","Deprecate ``std::errc`` constants related to UNIX STREAMS","February 2023","|Complete|","19.0","" "`3870 <https://wg21.link/LWG3870>`__","Remove ``voidify``","February 2023","","","" "`3871 <https://wg21.link/LWG3871>`__","Adjust note about ``terminate``","February 2023","","","" "`3872 <https://wg21.link/LWG3872>`__","``basic_const_iterator`` should have custom ``iter_move``","February 2023","","","" diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv index 56e1468b4ca1a3f24d8ce5905c0466ba8b72b672..80547c5c1f3f57efc66243d13da944615a4e6f66 100644 --- a/libcxx/docs/Status/Cxx23Papers.csv +++ b/libcxx/docs/Status/Cxx23Papers.csv @@ -100,7 +100,7 @@ "`P2396R1 <https://wg21.link/P2396R1>`__","LWG", "Concurrency TS 2 fixes ", "November 2022","","","|concurrency TS|" "`P2505R5 <https://wg21.link/P2505R5>`__","LWG", "Monadic Functions for ``std::expected``", "November 2022","|Complete|","17.0","" "`P2539R4 <https://wg21.link/P2539R4>`__","LWG", "Should the output of ``std::print`` to a terminal be synchronized with the underlying stream?", "November 2022","|Complete|","18.0","|format|" -"`P2602R2 <https://wg21.link/P2602R2>`__","LWG", "Poison Pills are Too Toxic", "November 2022","","","|ranges|" +"`P2602R2 <https://wg21.link/P2602R2>`__","LWG", "Poison Pills are Too Toxic", "November 2022","|Complete|","19.0","|ranges|" "`P2708R1 <https://wg21.link/P2708R1>`__","LWG", "No Further Fundamentals TSes", "November 2022","|Nothing to do|","","" "","","","","","","" "`P0290R4 <https://wg21.link/P0290R4>`__","LWG", "``apply()`` for ``synchronized_value<T>``","February 2023","","","|concurrency TS|" diff --git a/libcxx/docs/UsingLibcxx.rst b/libcxx/docs/UsingLibcxx.rst index 3b1be286c16981b14703e175ca864878eb419d7f..ac12b0b96950796636af79b596102729f9708952 100644 --- a/libcxx/docs/UsingLibcxx.rst +++ b/libcxx/docs/UsingLibcxx.rst @@ -244,18 +244,6 @@ C++20 Specific Configuration Macros This macro is deprecated and will be removed in LLVM-19. Use the individual macros listed below. -**_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS**: - This macro is used to re-enable redundant members of `allocator<T>`, - including `pointer`, `reference`, `rebind`, `address`, `max_size`, - `construct`, `destroy`, and the two-argument overload of `allocate`. - This macro has been deprecated and will be removed in LLVM-19. - -**_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_VOID_SPECIALIZATION**: - This macro is used to re-enable the library-provided specializations of - `allocator<void>` and `allocator<const void>`. - Use it in conjunction with `_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS` - to ensure that removed members of `allocator<void>` can be accessed. - **_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS**: This macro is used to re-enable the `argument_type`, `result_type`, `first_argument_type`, and `second_argument_type` members of class diff --git a/libcxx/docs/index.rst b/libcxx/docs/index.rst index aa1bd4b83b265b8df354c8d543a4c39e56fc60bb..db55c6f02a3dc346ea3cec26be8635eee2695801 100644 --- a/libcxx/docs/index.rst +++ b/libcxx/docs/index.rst @@ -66,6 +66,25 @@ Getting Started with libc++ Current Status ============== +libc++ has become the default C++ Standard Library implementation for many major platforms, including Apple's macOS, +iOS, watchOS, and tvOS, Google Search, the Android operating system, and FreeBSD. As a result, libc++ has an estimated +user base of over 1 billion daily active users. + +Since its inception, libc++ has focused on delivering high performance, standards-conformance, and portability. It has +been extensively tested and optimized, making it robust and production ready. libc++ fully implements C++11 and C++14, +with C++17, C++20, C++23, and C++26 features being actively developed and making steady progress. + +libc++ is continuously integrated and tested on a wide range of platforms and configurations, ensuring its reliability +and compatibility across various systems. The library's extensive test suite and rigorous quality assurance process have +made it a top choice for platform providers looking to offer their users a robust and efficient C++ Standard Library. + +As an open-source project, libc++ benefits from a vibrant community of contributors who work together to improve the +library and add new features. This ongoing development and support ensure that libc++ remains at the forefront of +C++ standardization efforts and continues to meet the evolving needs of C++ developers worldwide. + + +History +------- After its initial introduction, many people have asked "why start a new library instead of contributing to an existing library?" (like Apache's libstdcxx, GNU's libstdc++, STLport, etc). There are many contributing @@ -189,6 +208,7 @@ Design Documents DesignDocs/FeatureTestMacros DesignDocs/FileTimeType DesignDocs/HeaderRemovalPolicy + DesignDocs/NodiscardPolicy DesignDocs/NoexceptPolicy DesignDocs/PSTLIntegration DesignDocs/ThreadingSupportAPI diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 63adc03fae2980ae792a66ce52f0004f73a8d4ea..b935e45151e9e17c44da5c3d481a065de5e9506c 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -217,6 +217,7 @@ set(files __algorithm/shift_right.h __algorithm/shuffle.h __algorithm/sift_down.h + __algorithm/simd_utils.h __algorithm/sort.h __algorithm/sort_heap.h __algorithm/stable_partition.h @@ -429,22 +430,27 @@ set(files __fwd/array.h __fwd/bit_reference.h __fwd/complex.h + __fwd/deque.h __fwd/format.h __fwd/fstream.h __fwd/functional.h __fwd/ios.h __fwd/istream.h __fwd/mdspan.h + __fwd/memory.h __fwd/memory_resource.h __fwd/ostream.h __fwd/pair.h + __fwd/queue.h __fwd/span.h __fwd/sstream.h + __fwd/stack.h __fwd/streambuf.h __fwd/string.h __fwd/string_view.h __fwd/subrange.h __fwd/tuple.h + __fwd/vector.h __hash_table __ios/fpos.h __iterator/access.h @@ -703,12 +709,12 @@ set(files __tree __tuple/find_index.h __tuple/make_tuple_types.h - __tuple/pair_like.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 __tuple/tuple_size.h __tuple/tuple_types.h __type_traits/add_const.h @@ -755,10 +761,7 @@ set(files __type_traits/is_constant_evaluated.h __type_traits/is_constructible.h __type_traits/is_convertible.h - __type_traits/is_copy_assignable.h - __type_traits/is_copy_constructible.h __type_traits/is_core_convertible.h - __type_traits/is_default_constructible.h __type_traits/is_destructible.h __type_traits/is_empty.h __type_traits/is_enum.h @@ -774,17 +777,10 @@ set(files __type_traits/is_member_function_pointer.h __type_traits/is_member_object_pointer.h __type_traits/is_member_pointer.h - __type_traits/is_move_assignable.h - __type_traits/is_move_constructible.h __type_traits/is_nothrow_assignable.h __type_traits/is_nothrow_constructible.h __type_traits/is_nothrow_convertible.h - __type_traits/is_nothrow_copy_assignable.h - __type_traits/is_nothrow_copy_constructible.h - __type_traits/is_nothrow_default_constructible.h __type_traits/is_nothrow_destructible.h - __type_traits/is_nothrow_move_assignable.h - __type_traits/is_nothrow_move_constructible.h __type_traits/is_null_pointer.h __type_traits/is_object.h __type_traits/is_pod.h @@ -805,14 +801,9 @@ set(files __type_traits/is_trivial.h __type_traits/is_trivially_assignable.h __type_traits/is_trivially_constructible.h - __type_traits/is_trivially_copy_assignable.h - __type_traits/is_trivially_copy_constructible.h __type_traits/is_trivially_copyable.h - __type_traits/is_trivially_default_constructible.h __type_traits/is_trivially_destructible.h __type_traits/is_trivially_lexicographically_comparable.h - __type_traits/is_trivially_move_assignable.h - __type_traits/is_trivially_move_constructible.h __type_traits/is_trivially_relocatable.h __type_traits/is_unbounded_array.h __type_traits/is_union.h diff --git a/libcxx/include/__algorithm/copy.h b/libcxx/include/__algorithm/copy.h index 4c3815405af0cf6168d608cf9edc7cbfb70c2fc2..0890b895f5409245b5244bd3f5a1d6b8d3b1fcda 100644 --- a/libcxx/include/__algorithm/copy.h +++ b/libcxx/include/__algorithm/copy.h @@ -32,7 +32,7 @@ template <class, class _InIter, class _Sent, class _OutIter> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __copy(_InIter, _Sent, _OutIter); template <class _AlgPolicy> -struct __copy_loop { +struct __copy_impl { template <class _InIter, class _Sent, class _OutIter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { @@ -94,9 +94,7 @@ struct __copy_loop { __local_first = _Traits::__begin(++__segment_iterator); } } -}; -struct __copy_trivial { // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. template <class _In, class _Out, __enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> @@ -108,7 +106,7 @@ struct __copy_trivial { template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter> pair<_InIter, _OutIter> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __copy(_InIter __first, _Sent __last, _OutIter __result) { - return std::__dispatch_copy_or_move<_AlgPolicy, __copy_loop<_AlgPolicy>, __copy_trivial>( + return std::__copy_move_unwrap_iters<__copy_impl<_AlgPolicy> >( std::move(__first), std::move(__last), std::move(__result)); } diff --git a/libcxx/include/__algorithm/copy_backward.h b/libcxx/include/__algorithm/copy_backward.h index 3ec88d8bd5cc3a6a6656c3cc0d6f3fc6f4919dac..73dc846a975a44d905bda90a5d5973fb06d34dac 100644 --- a/libcxx/include/__algorithm/copy_backward.h +++ b/libcxx/include/__algorithm/copy_backward.h @@ -15,7 +15,7 @@ #include <__config> #include <__iterator/segmented_iterator.h> #include <__type_traits/common_type.h> -#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_constructible.h> #include <__utility/move.h> #include <__utility/pair.h> @@ -33,7 +33,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InIter, _OutIter> __copy_backward(_InIter __first, _Sent __last, _OutIter __result); template <class _AlgPolicy> -struct __copy_backward_loop { +struct __copy_backward_impl { template <class _InIter, class _Sent, class _OutIter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { @@ -104,9 +104,7 @@ struct __copy_backward_loop { __local_last = _Traits::__end(__segment_iterator); } } -}; -struct __copy_backward_trivial { // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. template <class _In, class _Out, __enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> @@ -118,7 +116,7 @@ struct __copy_backward_trivial { template <class _AlgPolicy, class _BidirectionalIterator1, class _Sentinel, class _BidirectionalIterator2> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1, _BidirectionalIterator2> __copy_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result) { - return std::__dispatch_copy_or_move<_AlgPolicy, __copy_backward_loop<_AlgPolicy>, __copy_backward_trivial>( + return std::__copy_move_unwrap_iters<__copy_backward_impl<_AlgPolicy> >( std::move(__first), std::move(__last), std::move(__result)); } diff --git a/libcxx/include/__algorithm/copy_move_common.h b/libcxx/include/__algorithm/copy_move_common.h index 0fc7a5e3cee70095c2d1637fdd626a63b8f08f12..12a26c6d6a64ee770873e32cb50b4f10cbb20a35 100644 --- a/libcxx/include/__algorithm/copy_move_common.h +++ b/libcxx/include/__algorithm/copy_move_common.h @@ -19,7 +19,7 @@ #include <__type_traits/enable_if.h> #include <__type_traits/is_always_bitcastable.h> #include <__type_traits/is_constant_evaluated.h> -#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_constructible.h> #include <__type_traits/is_trivially_assignable.h> #include <__type_traits/is_trivially_copyable.h> #include <__type_traits/is_volatile.h> @@ -81,30 +81,17 @@ __copy_backward_trivial_impl(_In* __first, _In* __last, _Out* __result) { // Iterator unwrapping and dispatching to the correct overload. -template <class _F1, class _F2> -struct __overload : _F1, _F2 { - using _F1::operator(); - using _F2::operator(); -}; - -template <class _InIter, class _Sent, class _OutIter, class = void> -struct __can_rewrap : false_type {}; - -template <class _InIter, class _Sent, class _OutIter> -struct __can_rewrap<_InIter, - _Sent, - _OutIter, - // Note that sentinels are always copy-constructible. - __enable_if_t< is_copy_constructible<_InIter>::value && is_copy_constructible<_OutIter>::value > > - : true_type {}; +template <class _InIter, class _OutIter> +struct __can_rewrap + : integral_constant<bool, is_copy_constructible<_InIter>::value && is_copy_constructible<_OutIter>::value> {}; template <class _Algorithm, class _InIter, class _Sent, class _OutIter, - __enable_if_t<__can_rewrap<_InIter, _Sent, _OutIter>::value, int> = 0> + __enable_if_t<__can_rewrap<_InIter, _OutIter>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter> -__unwrap_and_dispatch(_InIter __first, _Sent __last, _OutIter __out_first) { +__copy_move_unwrap_iters(_InIter __first, _Sent __last, _OutIter __out_first) { auto __range = std::__unwrap_range(__first, std::move(__last)); auto __result = _Algorithm()(std::move(__range.first), std::move(__range.second), std::__unwrap_iter(__out_first)); return std::make_pair(std::__rewrap_range<_Sent>(std::move(__first), std::move(__result.first)), @@ -115,24 +102,12 @@ template <class _Algorithm, class _InIter, class _Sent, class _OutIter, - __enable_if_t<!__can_rewrap<_InIter, _Sent, _OutIter>::value, int> = 0> + __enable_if_t<!__can_rewrap<_InIter, _OutIter>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter> -__unwrap_and_dispatch(_InIter __first, _Sent __last, _OutIter __out_first) { +__copy_move_unwrap_iters(_InIter __first, _Sent __last, _OutIter __out_first) { return _Algorithm()(std::move(__first), std::move(__last), std::move(__out_first)); } -template <class _AlgPolicy, - class _NaiveAlgorithm, - class _OptimizedAlgorithm, - class _InIter, - class _Sent, - class _OutIter> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter> -__dispatch_copy_or_move(_InIter __first, _Sent __last, _OutIter __out_first) { - using _Algorithm = __overload<_NaiveAlgorithm, _OptimizedAlgorithm>; - return std::__unwrap_and_dispatch<_Algorithm>(std::move(__first), std::move(__last), std::move(__out_first)); -} - _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS diff --git a/libcxx/include/__algorithm/equal.h b/libcxx/include/__algorithm/equal.h index 3c0e3060e39a99f604b4a0c8237b9bab71954da5..c76a16b47f5da411620023ba0e9b1f545a06b36f 100644 --- a/libcxx/include/__algorithm/equal.h +++ b/libcxx/include/__algorithm/equal.h @@ -69,20 +69,6 @@ equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first } #if _LIBCPP_STD_VER >= 14 -template <class _BinaryPredicate, class _InputIterator1, class _InputIterator2> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool -__equal(_InputIterator1 __first1, - _InputIterator1 __last1, - _InputIterator2 __first2, - _InputIterator2 __last2, - _BinaryPredicate __pred, - input_iterator_tag, - input_iterator_tag) { - for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2) - if (!__pred(*__first1, *__first2)) - return false; - return __first1 == __last1 && __first2 == __last2; -} template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2> _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl( @@ -110,17 +96,18 @@ __equal_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&, return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1)); } -template <class _BinaryPredicate, class _RandomAccessIterator1, class _RandomAccessIterator2> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool -__equal(_RandomAccessIterator1 __first1, - _RandomAccessIterator1 __last1, - _RandomAccessIterator2 __first2, - _RandomAccessIterator2 __last2, - _BinaryPredicate __pred, - random_access_iterator_tag, - random_access_iterator_tag) { - if (std::distance(__first1, __last1) != std::distance(__first2, __last2)) - return false; +template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> +_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool +equal(_InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _BinaryPredicate __pred) { + if constexpr (__has_random_access_iterator_category<_InputIterator1>::value && + __has_random_access_iterator_category<_InputIterator2>::value) { + if (std::distance(__first1, __last1) != std::distance(__first2, __last2)) + return false; + } __identity __proj; return std::__equal_impl( std::__unwrap_iter(__first1), @@ -132,36 +119,13 @@ __equal(_RandomAccessIterator1 __first1, __proj); } -template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> -_LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool -equal(_InputIterator1 __first1, - _InputIterator1 __last1, - _InputIterator2 __first2, - _InputIterator2 __last2, - _BinaryPredicate __pred) { - return std::__equal<_BinaryPredicate&>( - __first1, - __last1, - __first2, - __last2, - __pred, - typename iterator_traits<_InputIterator1>::iterator_category(), - typename iterator_traits<_InputIterator2>::iterator_category()); -} - template <class _InputIterator1, class _InputIterator2> _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool equal(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _InputIterator2 __last2) { - return std::__equal( - __first1, - __last1, - __first2, - __last2, - __equal_to(), - typename iterator_traits<_InputIterator1>::iterator_category(), - typename iterator_traits<_InputIterator2>::iterator_category()); + return std::equal(__first1, __last1, __first2, __last2, __equal_to()); } -#endif + +#endif // _LIBCPP_STD_VER >= 14 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/equal_range.h b/libcxx/include/__algorithm/equal_range.h index a94290431971c41f116cb6c9e1ae9b8de48bd0cb..2b086abf1794fde469a65ef5bd584db620fc3fd3 100644 --- a/libcxx/include/__algorithm/equal_range.h +++ b/libcxx/include/__algorithm/equal_range.h @@ -23,7 +23,7 @@ #include <__iterator/iterator_traits.h> #include <__iterator/next.h> #include <__type_traits/is_callable.h> -#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_constructible.h> #include <__utility/move.h> #include <__utility/pair.h> diff --git a/libcxx/include/__algorithm/fill_n.h b/libcxx/include/__algorithm/fill_n.h index 36f3349d9e7a37d832cf6203afd76013ccd6a6e0..f29633f88087f01dbd83c78f42f7c3465d629b74 100644 --- a/libcxx/include/__algorithm/fill_n.h +++ b/libcxx/include/__algorithm/fill_n.h @@ -9,18 +9,74 @@ #ifndef _LIBCPP___ALGORITHM_FILL_N_H #define _LIBCPP___ALGORITHM_FILL_N_H +#include <__algorithm/min.h> #include <__config> +#include <__fwd/bit_reference.h> #include <__iterator/iterator_traits.h> +#include <__memory/pointer_traits.h> #include <__utility/convert_to_integral.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD // fill_n isn't specialized for std::memset, because the compiler already optimizes the loop to a call to std::memset. +template <class _OutputIterator, class _Size, class _Tp> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator +__fill_n(_OutputIterator __first, _Size __n, const _Tp& __value); + +template <bool _FillVal, class _Cp> +_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void +__fill_n_bool(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n) { + using _It = __bit_iterator<_Cp, false>; + using __storage_type = typename _It::__storage_type; + + const int __bits_per_word = _It::__bits_per_word; + // do first partial word + if (__first.__ctz_ != 0) { + __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_); + __storage_type __dn = std::min(__clz_f, __n); + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + if (_FillVal) + *__first.__seg_ |= __m; + else + *__first.__seg_ &= ~__m; + __n -= __dn; + ++__first.__seg_; + } + // do middle whole words + __storage_type __nw = __n / __bits_per_word; + std::__fill_n(std::__to_address(__first.__seg_), __nw, _FillVal ? static_cast<__storage_type>(-1) : 0); + __n -= __nw * __bits_per_word; + // do last partial word + if (__n > 0) { + __first.__seg_ += __nw; + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + if (_FillVal) + *__first.__seg_ |= __m; + else + *__first.__seg_ &= ~__m; + } +} + +template <class _Cp, class _Size> +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false> +__fill_n(__bit_iterator<_Cp, false> __first, _Size __n, const bool& __value) { + if (__n > 0) { + if (__value) + std::__fill_n_bool<true>(__first, __n); + else + std::__fill_n_bool<false>(__first, __n); + } + return __first + __n; +} + template <class _OutputIterator, class _Size, class _Tp> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator __fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) { @@ -37,4 +93,6 @@ fill_n(_OutputIterator __first, _Size __n, const _Tp& __value) { _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_FILL_N_H diff --git a/libcxx/include/__algorithm/inplace_merge.h b/libcxx/include/__algorithm/inplace_merge.h index eb3c0bdbc2db7f648ba3da678422f669e6ec634f..a6bcc66a2fa47ad51523265750b50db1d4b73d49 100644 --- a/libcxx/include/__algorithm/inplace_merge.h +++ b/libcxx/include/__algorithm/inplace_merge.h @@ -114,8 +114,8 @@ _LIBCPP_HIDE_FROM_ABI void __buffered_inplace_merge( for (_BidirectionalIterator __i = __middle; __i != __last; __d.template __incr<value_type>(), (void)++__i, (void)++__p) ::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i)); - typedef __unconstrained_reverse_iterator<_BidirectionalIterator> _RBi; - typedef __unconstrained_reverse_iterator<value_type*> _Rv; + typedef reverse_iterator<_BidirectionalIterator> _RBi; + typedef reverse_iterator<value_type*> _Rv; typedef __invert<_Compare> _Inverted; std::__half_inplace_merge<_AlgPolicy>( _Rv(__p), _Rv(__buff), _RBi(__middle), _RBi(__first), _RBi(__last), _Inverted(__comp)); diff --git a/libcxx/include/__algorithm/lexicographical_compare_three_way.h b/libcxx/include/__algorithm/lexicographical_compare_three_way.h index 32de97d07a13196cfe9bcfd145b52da57d218377..50ebdc647a97abbe05a9df3bb888325f39e86812 100644 --- a/libcxx/include/__algorithm/lexicographical_compare_three_way.h +++ b/libcxx/include/__algorithm/lexicographical_compare_three_way.h @@ -17,7 +17,7 @@ #include <__config> #include <__iterator/iterator_traits.h> #include <__type_traits/common_type.h> -#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_constructible.h> #include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__algorithm/mismatch.h b/libcxx/include/__algorithm/mismatch.h index d345b6048a7e9be1bb4b244099ea440aecae68b3..8abb273ac17822dc8b444489475086b33f4b29b0 100644 --- a/libcxx/include/__algorithm/mismatch.h +++ b/libcxx/include/__algorithm/mismatch.h @@ -11,23 +11,123 @@ #define _LIBCPP___ALGORITHM_MISMATCH_H #include <__algorithm/comp.h> +#include <__algorithm/min.h> +#include <__algorithm/simd_utils.h> +#include <__algorithm/unwrap_iter.h> #include <__config> -#include <__iterator/iterator_traits.h> +#include <__functional/identity.h> +#include <__type_traits/invoke.h> +#include <__type_traits/is_constant_evaluated.h> +#include <__type_traits/is_equality_comparable.h> +#include <__type_traits/is_integral.h> +#include <__type_traits/operation_traits.h> +#include <__utility/move.h> #include <__utility/pair.h> +#include <__utility/unreachable.h> +#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD +template <class _Iter1, class _Sent1, class _Iter2, class _Pred, class _Proj1, class _Proj2> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2> +__mismatch_loop(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { + while (__first1 != __last1) { + if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) + break; + ++__first1; + ++__first2; + } + return std::make_pair(std::move(__first1), std::move(__first2)); +} + +template <class _Iter1, class _Sent1, class _Iter2, class _Pred, class _Proj1, class _Proj2> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2> +__mismatch(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { + return std::__mismatch_loop(__first1, __last1, __first2, __pred, __proj1, __proj2); +} + +#if _LIBCPP_VECTORIZE_ALGORITHMS + +template <class _Tp, + class _Pred, + class _Proj1, + class _Proj2, + __enable_if_t<is_integral<_Tp>::value && __desugars_to<__equal_tag, _Pred, _Tp, _Tp>::value && + __is_identity<_Proj1>::value && __is_identity<_Proj2>::value, + int> = 0> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*> +__mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { + constexpr size_t __unroll_count = 4; + constexpr size_t __vec_size = __native_vector_size<_Tp>; + using __vec = __simd_vector<_Tp, __vec_size>; + + if (!__libcpp_is_constant_evaluated()) { + auto __orig_first1 = __first1; + auto __last2 = __first2 + (__last1 - __first1); + while (static_cast<size_t>(__last1 - __first1) >= __unroll_count * __vec_size) [[__unlikely__]] { + __vec __lhs[__unroll_count]; + __vec __rhs[__unroll_count]; + + for (size_t __i = 0; __i != __unroll_count; ++__i) { + __lhs[__i] = std::__load_vector<__vec>(__first1 + __i * __vec_size); + __rhs[__i] = std::__load_vector<__vec>(__first2 + __i * __vec_size); + } + + for (size_t __i = 0; __i != __unroll_count; ++__i) { + if (auto __cmp_res = __lhs[__i] == __rhs[__i]; !std::__all_of(__cmp_res)) { + auto __offset = __i * __vec_size + std::__find_first_not_set(__cmp_res); + return {__first1 + __offset, __first2 + __offset}; + } + } + + __first1 += __unroll_count * __vec_size; + __first2 += __unroll_count * __vec_size; + } + + // check the remaining 0-3 vectors + while (static_cast<size_t>(__last1 - __first1) >= __vec_size) { + if (auto __cmp_res = std::__load_vector<__vec>(__first1) == std::__load_vector<__vec>(__first2); + !std::__all_of(__cmp_res)) { + auto __offset = std::__find_first_not_set(__cmp_res); + return {__first1 + __offset, __first2 + __offset}; + } + __first1 += __vec_size; + __first2 += __vec_size; + } + + if (__last1 - __first1 == 0) + return {__first1, __first2}; + + // Check if we can load elements in front of the current pointer. If that's the case load a vector at + // (last - vector_size) to check the remaining elements + if (static_cast<size_t>(__first1 - __orig_first1) >= __vec_size) { + __first1 = __last1 - __vec_size; + __first2 = __last2 - __vec_size; + auto __offset = + std::__find_first_not_set(std::__load_vector<__vec>(__first1) == std::__load_vector<__vec>(__first2)); + return {__first1 + __offset, __first2 + __offset}; + } // else loop over the elements individually + } + + return std::__mismatch_loop(__first1, __last1, __first2, __pred, __proj1, __proj2); +} + +#endif // _LIBCPP_VECTORIZE_ALGORITHMS + template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __pred) { - for (; __first1 != __last1; ++__first1, (void)++__first2) - if (!__pred(*__first1, *__first2)) - break; - return pair<_InputIterator1, _InputIterator2>(__first1, __first2); + __identity __proj; + auto __res = std::__mismatch( + std::__unwrap_iter(__first1), std::__unwrap_iter(__last1), std::__unwrap_iter(__first2), __pred, __proj, __proj); + return std::make_pair(std::__rewrap_iter(__first1, __res.first), std::__rewrap_iter(__first2, __res.second)); } template <class _InputIterator1, class _InputIterator2> @@ -37,6 +137,25 @@ mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __fi } #if _LIBCPP_STD_VER >= 14 +template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2> +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Iter1, _Iter2> __mismatch( + _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { + while (__first1 != __last1 && __first2 != __last2) { + if (!std::__invoke(__pred, std::__invoke(__proj1, *__first1), std::__invoke(__proj2, *__first2))) + break; + ++__first1; + ++__first2; + } + return {std::move(__first1), std::move(__first2)}; +} + +template <class _Tp, class _Pred, class _Proj1, class _Proj2> +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_Tp*, _Tp*> +__mismatch(_Tp* __first1, _Tp* __last1, _Tp* __first2, _Tp* __last2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { + auto __len = std::min(__last1 - __first1, __last2 - __first2); + return std::__mismatch(__first1, __first1 + __len, __first2, __pred, __proj1, __proj2); +} + template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate> _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InputIterator1, _InputIterator2> mismatch(_InputIterator1 __first1, @@ -44,10 +163,16 @@ mismatch(_InputIterator1 __first1, _InputIterator2 __first2, _InputIterator2 __last2, _BinaryPredicate __pred) { - for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2) - if (!__pred(*__first1, *__first2)) - break; - return pair<_InputIterator1, _InputIterator2>(__first1, __first2); + __identity __proj; + auto __res = std::__mismatch( + std::__unwrap_iter(__first1), + std::__unwrap_iter(__last1), + std::__unwrap_iter(__first2), + std::__unwrap_iter(__last2), + __pred, + __proj, + __proj); + return {std::__rewrap_iter(__first1, __res.first), std::__rewrap_iter(__first2, __res.second)}; } template <class _InputIterator1, class _InputIterator2> @@ -59,4 +184,6 @@ mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __fi _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #endif // _LIBCPP___ALGORITHM_MISMATCH_H diff --git a/libcxx/include/__algorithm/move.h b/libcxx/include/__algorithm/move.h index dba6d487fff77ed7ece7fefe234d239822bf19fa..1716d43e2a613dd54fdf55e09263a671333b601c 100644 --- a/libcxx/include/__algorithm/move.h +++ b/libcxx/include/__algorithm/move.h @@ -16,7 +16,7 @@ #include <__config> #include <__iterator/segmented_iterator.h> #include <__type_traits/common_type.h> -#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_constructible.h> #include <__utility/move.h> #include <__utility/pair.h> @@ -34,7 +34,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIte __move(_InIter __first, _Sent __last, _OutIter __result); template <class _AlgPolicy> -struct __move_loop { +struct __move_impl { template <class _InIter, class _Sent, class _OutIter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { @@ -95,9 +95,7 @@ struct __move_loop { __local_first = _Traits::__begin(++__segment_iterator); } } -}; -struct __move_trivial { // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. template <class _In, class _Out, __enable_if_t<__can_lower_move_assignment_to_memmove<_In, _Out>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> @@ -109,7 +107,7 @@ struct __move_trivial { template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter> inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __move(_InIter __first, _Sent __last, _OutIter __result) { - return std::__dispatch_copy_or_move<_AlgPolicy, __move_loop<_AlgPolicy>, __move_trivial>( + return std::__copy_move_unwrap_iters<__move_impl<_AlgPolicy> >( std::move(__first), std::move(__last), std::move(__result)); } diff --git a/libcxx/include/__algorithm/move_backward.h b/libcxx/include/__algorithm/move_backward.h index aeedf4241dce9cbc4635a27fa228adb4d464db7a..4beb7bdbaac0d0dc542478f2a39636fd302f4bc6 100644 --- a/libcxx/include/__algorithm/move_backward.h +++ b/libcxx/include/__algorithm/move_backward.h @@ -15,7 +15,7 @@ #include <__config> #include <__iterator/segmented_iterator.h> #include <__type_traits/common_type.h> -#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_constructible.h> #include <__utility/move.h> #include <__utility/pair.h> @@ -33,7 +33,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_BidirectionalIterator1 __move_backward(_BidirectionalIterator1 __first, _Sentinel __last, _BidirectionalIterator2 __result); template <class _AlgPolicy> -struct __move_backward_loop { +struct __move_backward_impl { template <class _InIter, class _Sent, class _OutIter> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> operator()(_InIter __first, _Sent __last, _OutIter __result) const { @@ -104,9 +104,7 @@ struct __move_backward_loop { __local_last = _Traits::__end(--__segment_iterator); } } -}; -struct __move_backward_trivial { // At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer. template <class _In, class _Out, __enable_if_t<__can_lower_move_assignment_to_memmove<_In, _Out>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*> @@ -122,7 +120,7 @@ __move_backward(_BidirectionalIterator1 __first, _Sentinel __last, _Bidirectiona std::is_copy_constructible<_BidirectionalIterator1>::value, "Iterators must be copy constructible."); - return std::__dispatch_copy_or_move<_AlgPolicy, __move_backward_loop<_AlgPolicy>, __move_backward_trivial>( + return std::__copy_move_unwrap_iters<__move_backward_impl<_AlgPolicy> >( std::move(__first), std::move(__last), std::move(__result)); } diff --git a/libcxx/include/__algorithm/partial_sort.h b/libcxx/include/__algorithm/partial_sort.h index 85a8fdc77aa228b63c9ef691cdc2aadc178881d5..7f8d0c49147e3af2ee9d25f896f01cd762e7a5ae 100644 --- a/libcxx/include/__algorithm/partial_sort.h +++ b/libcxx/include/__algorithm/partial_sort.h @@ -18,8 +18,8 @@ #include <__config> #include <__debug_utils/randomize_range.h> #include <__iterator/iterator_traits.h> -#include <__type_traits/is_copy_assignable.h> -#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_constructible.h> #include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__algorithm/pop_heap.h b/libcxx/include/__algorithm/pop_heap.h index 798a1d09934bc3a0d48d39b0201d9a9f99185c7b..6d23830097ff96ca63f7adb1320eefe726a63a55 100644 --- a/libcxx/include/__algorithm/pop_heap.h +++ b/libcxx/include/__algorithm/pop_heap.h @@ -17,8 +17,8 @@ #include <__assert> #include <__config> #include <__iterator/iterator_traits.h> -#include <__type_traits/is_copy_assignable.h> -#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_constructible.h> #include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__algorithm/push_heap.h b/libcxx/include/__algorithm/push_heap.h index 7d8720e3a93d44855c89912e68ab696c79b53040..ec0b445f2b70f3dc9ab6a17234de75c487194e4b 100644 --- a/libcxx/include/__algorithm/push_heap.h +++ b/libcxx/include/__algorithm/push_heap.h @@ -14,8 +14,8 @@ #include <__algorithm/iterator_operations.h> #include <__config> #include <__iterator/iterator_traits.h> -#include <__type_traits/is_copy_assignable.h> -#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_constructible.h> #include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__algorithm/ranges_ends_with.h b/libcxx/include/__algorithm/ranges_ends_with.h index c2a3cae9f3b16afd506431d913d8ed17a2918305..bb01918326b8bc9496fa8cbc4b5ed19324400ab0 100644 --- a/libcxx/include/__algorithm/ranges_ends_with.h +++ b/libcxx/include/__algorithm/ranges_ends_with.h @@ -39,7 +39,7 @@ namespace ranges { namespace __ends_with { struct __fn { template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2> - static _LIBCPP_HIDE_FROM_ABI constexpr bool __ends_with_fn_impl_bidirectional( + _LIBCPP_HIDE_FROM_ABI static constexpr bool __ends_with_fn_impl_bidirectional( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -56,7 +56,7 @@ struct __fn { } template <class _Iter1, class _Sent1, class _Iter2, class _Sent2, class _Pred, class _Proj1, class _Proj2> - static _LIBCPP_HIDE_FROM_ABI constexpr bool __ends_with_fn_impl( + _LIBCPP_HIDE_FROM_ABI static constexpr bool __ends_with_fn_impl( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, @@ -65,7 +65,7 @@ struct __fn { _Proj1& __proj1, _Proj2& __proj2) { if constexpr (std::bidirectional_iterator<_Sent1> && std::bidirectional_iterator<_Sent2> && - (!std::random_access_iterator<_Sent1>)&&(!std::random_access_iterator<_Sent2>)) { + (!std::random_access_iterator<_Sent1>) && (!std::random_access_iterator<_Sent2>)) { return __ends_with_fn_impl_bidirectional(__first1, __last1, __first2, __last2, __pred, __proj1, __proj2); } else { diff --git a/libcxx/include/__algorithm/ranges_mismatch.h b/libcxx/include/__algorithm/ranges_mismatch.h index 037af39126230a12b784b3bbb9618542354d3a74..d8a7dd43af09d5da283dfb44cd2e6203d86e1589 100644 --- a/libcxx/include/__algorithm/ranges_mismatch.h +++ b/libcxx/include/__algorithm/ranges_mismatch.h @@ -10,6 +10,8 @@ #define _LIBCPP___ALGORITHM_RANGES_MISMATCH_H #include <__algorithm/in_in_result.h> +#include <__algorithm/mismatch.h> +#include <__algorithm/unwrap_range.h> #include <__config> #include <__functional/identity.h> #include <__functional/invoke.h> @@ -42,13 +44,17 @@ struct __fn { template <class _I1, class _S1, class _I2, class _S2, class _Pred, class _Proj1, class _Proj2> static _LIBCPP_HIDE_FROM_ABI constexpr mismatch_result<_I1, _I2> __go(_I1 __first1, _S1 __last1, _I2 __first2, _S2 __last2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) { - while (__first1 != __last1 && __first2 != __last2) { - if (!std::invoke(__pred, std::invoke(__proj1, *__first1), std::invoke(__proj2, *__first2))) - break; - ++__first1; - ++__first2; + if constexpr (forward_iterator<_I1> && forward_iterator<_I2>) { + auto __range1 = std::__unwrap_range(__first1, __last1); + auto __range2 = std::__unwrap_range(__first2, __last2); + auto __res = + std::__mismatch(__range1.first, __range1.second, __range2.first, __range2.second, __pred, __proj1, __proj2); + return {std::__rewrap_range<_S1>(__first1, __res.first), std::__rewrap_range<_S2>(__first2, __res.second)}; + } else { + auto __res = std::__mismatch( + std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), __pred, __proj1, __proj2); + return {std::move(__res.first), std::move(__res.second)}; } - return {std::move(__first1), std::move(__first2)}; } template <input_iterator _I1, @@ -71,8 +77,8 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<iterator_t<_R1>, iterator_t<_R2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr mismatch_result<borrowed_iterator_t<_R1>, - borrowed_iterator_t<_R2>> + _LIBCPP_NODISCARD_EXT + _LIBCPP_HIDE_FROM_ABI constexpr mismatch_result<borrowed_iterator_t<_R1>, borrowed_iterator_t<_R2>> operator()(_R1&& __r1, _R2&& __r2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { return __go( ranges::begin(__r1), ranges::end(__r1), ranges::begin(__r2), ranges::end(__r2), __pred, __proj1, __proj2); diff --git a/libcxx/include/__algorithm/ranges_starts_with.h b/libcxx/include/__algorithm/ranges_starts_with.h index 90e184aa9bccc2961e0f7f15a449cfb51fe6b7dc..7ba8af13a8d1c83084bcb227a8c145fbc7359875 100644 --- a/libcxx/include/__algorithm/ranges_starts_with.h +++ b/libcxx/include/__algorithm/ranges_starts_with.h @@ -42,14 +42,14 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr bool operator()( _Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, _Proj1 __proj1 = {}, - _Proj2 __proj2 = {}) const { + _Proj2 __proj2 = {}) { return __mismatch::__fn::__go( std::move(__first1), std::move(__last1), @@ -67,8 +67,8 @@ struct __fn { class _Proj1 = identity, class _Proj2 = identity> requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool operator()( - _Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr bool + operator()(_Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) { return __mismatch::__fn::__go( ranges::begin(__range1), ranges::end(__range1), diff --git a/libcxx/include/__algorithm/rotate.h b/libcxx/include/__algorithm/rotate.h index 9a4d07883e320f0259c7e3fc1a43a07e7074abd0..df4ca95aac95bc972a0644de68fdd5358df71a12 100644 --- a/libcxx/include/__algorithm/rotate.h +++ b/libcxx/include/__algorithm/rotate.h @@ -15,7 +15,7 @@ #include <__algorithm/swap_ranges.h> #include <__config> #include <__iterator/iterator_traits.h> -#include <__type_traits/is_trivially_move_assignable.h> +#include <__type_traits/is_trivially_assignable.h> #include <__utility/move.h> #include <__utility/pair.h> diff --git a/libcxx/include/__algorithm/simd_utils.h b/libcxx/include/__algorithm/simd_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..989a1957987e1e6c77f35ac63bdc4b2db45f8ae3 --- /dev/null +++ b/libcxx/include/__algorithm/simd_utils.h @@ -0,0 +1,130 @@ +//===----------------------------------------------------------------------===// +// +// 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___ALGORITHM_SIMD_UTILS_H +#define _LIBCPP___ALGORITHM_SIMD_UTILS_H + +#include <__algorithm/min.h> +#include <__bit/bit_cast.h> +#include <__bit/countr.h> +#include <__config> +#include <__type_traits/is_arithmetic.h> +#include <__type_traits/is_same.h> +#include <__utility/integer_sequence.h> +#include <cstddef> +#include <cstdint> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +// TODO: Find out how altivec changes things and allow vectorizations there too. +#if _LIBCPP_STD_VER >= 14 && defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 1700 && !defined(__ALTIVEC__) +# define _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS 1 +#else +# define _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS 0 +#endif + +#if _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS && !defined(__OPTIMIZE_SIZE__) +# define _LIBCPP_VECTORIZE_ALGORITHMS 1 +#else +# define _LIBCPP_VECTORIZE_ALGORITHMS 0 +#endif + +#if _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS + +_LIBCPP_BEGIN_NAMESPACE_STD + +// This isn't specialized for 64 byte vectors on purpose. They have the potential to significantly reduce performance +// in mixed simd/non-simd workloads and don't provide any performance improvement for currently vectorized algorithms +// as far as benchmarks are concerned. +# if defined(__AVX__) +template <class _Tp> +inline constexpr size_t __native_vector_size = 32 / sizeof(_Tp); +# elif defined(__SSE__) || defined(__ARM_NEON__) +template <class _Tp> +inline constexpr size_t __native_vector_size = 16 / sizeof(_Tp); +# elif defined(__MMX__) +template <class _Tp> +inline constexpr size_t __native_vector_size = 8 / sizeof(_Tp); +# else +template <class _Tp> +inline constexpr size_t __native_vector_size = 1; +# endif + +template <class _ArithmeticT, size_t _Np> +using __simd_vector __attribute__((__ext_vector_type__(_Np))) = _ArithmeticT; + +template <class _VecT> +inline constexpr size_t __simd_vector_size_v = []<bool _False = false>() -> size_t { + static_assert(_False, "Not a vector!"); +}(); + +template <class _Tp, size_t _Np> +inline constexpr size_t __simd_vector_size_v<__simd_vector<_Tp, _Np>> = _Np; + +template <class _Tp, size_t _Np> +_LIBCPP_HIDE_FROM_ABI _Tp __simd_vector_underlying_type_impl(__simd_vector<_Tp, _Np>) { + return _Tp{}; +} + +template <class _VecT> +using __simd_vector_underlying_type_t = decltype(std::__simd_vector_underlying_type_impl(_VecT{})); + +// This isn't inlined without always_inline when loading chars. +template <class _VecT, class _Tp> +_LIBCPP_NODISCARD _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _VecT __load_vector(const _Tp* __ptr) noexcept { + return [=]<size_t... _Indices>(index_sequence<_Indices...>) _LIBCPP_ALWAYS_INLINE noexcept { + return _VecT{__ptr[_Indices]...}; + }(make_index_sequence<__simd_vector_size_v<_VecT>>{}); +} + +template <class _Tp, size_t _Np> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI bool __all_of(__simd_vector<_Tp, _Np> __vec) noexcept { + return __builtin_reduce_and(__builtin_convertvector(__vec, __simd_vector<bool, _Np>)); +} + +template <class _Tp, size_t _Np> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI size_t __find_first_set(__simd_vector<_Tp, _Np> __vec) noexcept { + using __mask_vec = __simd_vector<bool, _Np>; + + // This has MSan disabled du to https://github.com/llvm/llvm-project/issues/85876 + auto __impl = [&]<class _MaskT>(_MaskT) _LIBCPP_NO_SANITIZE("memory") noexcept { + return std::min<size_t>( + _Np, std::__countr_zero(__builtin_bit_cast(_MaskT, __builtin_convertvector(__vec, __mask_vec)))); + }; + + if constexpr (sizeof(__mask_vec) == sizeof(uint8_t)) { + return __impl(uint8_t{}); + } else if constexpr (sizeof(__mask_vec) == sizeof(uint16_t)) { + return __impl(uint16_t{}); + } else if constexpr (sizeof(__mask_vec) == sizeof(uint32_t)) { + return __impl(uint32_t{}); + } else if constexpr (sizeof(__mask_vec) == sizeof(uint64_t)) { + return __impl(uint64_t{}); + } else { + static_assert(sizeof(__mask_vec) == 0, "unexpected required size for mask integer type"); + return 0; + } +} + +template <class _Tp, size_t _Np> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI size_t __find_first_not_set(__simd_vector<_Tp, _Np> __vec) noexcept { + return std::__find_first_set(~__vec); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_SIMD_UTILS_H diff --git a/libcxx/include/__algorithm/sort_heap.h b/libcxx/include/__algorithm/sort_heap.h index 060fc33c3c6e93f2f6f9970a2a3b866b4a916576..f20b110c7fd12e8d8a5cfb8e300b12b509fff4b5 100644 --- a/libcxx/include/__algorithm/sort_heap.h +++ b/libcxx/include/__algorithm/sort_heap.h @@ -16,8 +16,8 @@ #include <__config> #include <__debug_utils/strict_weak_ordering_check.h> #include <__iterator/iterator_traits.h> -#include <__type_traits/is_copy_assignable.h> -#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_constructible.h> #include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h index 9be192bd65a6efec68f6371b7b118a90a8bda4aa..726e7e16b3564a236a41e6dbddc7e597d1d13beb 100644 --- a/libcxx/include/__algorithm/stable_sort.h +++ b/libcxx/include/__algorithm/stable_sort.h @@ -20,7 +20,7 @@ #include <__memory/destruct_n.h> #include <__memory/temporary_buffer.h> #include <__memory/unique_ptr.h> -#include <__type_traits/is_trivially_copy_assignable.h> +#include <__type_traits/is_trivially_assignable.h> #include <__utility/move.h> #include <__utility/pair.h> #include <new> diff --git a/libcxx/include/__algorithm/unwrap_iter.h b/libcxx/include/__algorithm/unwrap_iter.h index 50d815c9708849ad0abd239473fdcdbfc488591c..8cc0d22d4fc21133c4c527726644925f836bb210 100644 --- a/libcxx/include/__algorithm/unwrap_iter.h +++ b/libcxx/include/__algorithm/unwrap_iter.h @@ -13,7 +13,7 @@ #include <__iterator/iterator_traits.h> #include <__memory/pointer_traits.h> #include <__type_traits/enable_if.h> -#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_constructible.h> #include <__utility/declval.h> #include <__utility/move.h> diff --git a/libcxx/include/__algorithm/upper_bound.h b/libcxx/include/__algorithm/upper_bound.h index f499f7a80aa6d9e9a78d632ef905e9723799ff35..9c7d8fbcde07b5ac6bb2f429bb47da236029cbcf 100644 --- a/libcxx/include/__algorithm/upper_bound.h +++ b/libcxx/include/__algorithm/upper_bound.h @@ -18,7 +18,7 @@ #include <__iterator/advance.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> -#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_constructible.h> #include <__utility/move.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__atomic/atomic_base.h b/libcxx/include/__atomic/atomic_base.h index 6ca01a7f1bf9b9a10ed1be10f0b1c196707fcb59..e9badccc25a6205f93b870c4e897aff9cb29837d 100644 --- a/libcxx/include/__atomic/atomic_base.h +++ b/libcxx/include/__atomic/atomic_base.h @@ -18,7 +18,7 @@ #include <__config> #include <__memory/addressof.h> #include <__type_traits/is_integral.h> -#include <__type_traits/is_nothrow_default_constructible.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_same.h> #include <version> diff --git a/libcxx/include/__bit/bit_cast.h b/libcxx/include/__bit/bit_cast.h index f20b39ae748b101d6f6ac935fd1974a9113db863..6298810f3733031fa45d23ca165a138cb21864b5 100644 --- a/libcxx/include/__bit/bit_cast.h +++ b/libcxx/include/__bit/bit_cast.h @@ -19,6 +19,15 @@ _LIBCPP_BEGIN_NAMESPACE_STD +#ifndef _LIBCPP_CXX03_LANG + +template <class _ToType, class _FromType> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI constexpr _ToType __bit_cast(const _FromType& __from) noexcept { + return __builtin_bit_cast(_ToType, __from); +} + +#endif // _LIBCPP_CXX03_LANG + #if _LIBCPP_STD_VER >= 20 template <class _ToType, class _FromType> diff --git a/libcxx/include/__bit/countr.h b/libcxx/include/__bit/countr.h index 0cc679f87a99d9754ce2f115d6cc5cd9d7bedef8..b6b3ac52ca4e471ff72018741ade2e4626039d45 100644 --- a/libcxx/include/__bit/countr.h +++ b/libcxx/include/__bit/countr.h @@ -35,10 +35,8 @@ _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_ct return __builtin_ctzll(__x); } -#if _LIBCPP_STD_VER >= 20 - -template <__libcpp_unsigned_integer _Tp> -_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { +template <class _Tp> +_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __countr_zero(_Tp __t) _NOEXCEPT { if (__t == 0) return numeric_limits<_Tp>::digits; @@ -59,6 +57,13 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) n } } +#if _LIBCPP_STD_VER >= 20 + +template <__libcpp_unsigned_integer _Tp> +_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept { + return std::__countr_zero(__t); +} + template <__libcpp_unsigned_integer _Tp> _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept { return __t != numeric_limits<_Tp>::max() ? std::countr_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits; diff --git a/libcxx/include/__bit_reference b/libcxx/include/__bit_reference index 3a5339b72ddc318e0c56359b9df1325a4b09c298..9579b9eaf70bbd98d190228ff62b5248e99f2a28 100644 --- a/libcxx/include/__bit_reference +++ b/libcxx/include/__bit_reference @@ -171,61 +171,6 @@ private: __bit_const_reference& operator=(const __bit_const_reference&) = delete; }; -// fill_n - -template <bool _FillVal, class _Cp> -_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void -__fill_n(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n) { - using _It = __bit_iterator<_Cp, false>; - using __storage_type = typename _It::__storage_type; - - const int __bits_per_word = _It::__bits_per_word; - // do first partial word - if (__first.__ctz_ != 0) { - __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_); - __storage_type __dn = std::min(__clz_f, __n); - __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); - if (_FillVal) - *__first.__seg_ |= __m; - else - *__first.__seg_ &= ~__m; - __n -= __dn; - ++__first.__seg_; - } - // do middle whole words - __storage_type __nw = __n / __bits_per_word; - std::fill_n(std::__to_address(__first.__seg_), __nw, _FillVal ? static_cast<__storage_type>(-1) : 0); - __n -= __nw * __bits_per_word; - // do last partial word - if (__n > 0) { - __first.__seg_ += __nw; - __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); - if (_FillVal) - *__first.__seg_ |= __m; - else - *__first.__seg_ &= ~__m; - } -} - -template <class _Cp> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void -fill_n(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n, bool __value) { - if (__n > 0) { - if (__value) - std::__fill_n<true>(__first, __n); - else - std::__fill_n<false>(__first, __n); - } -} - -// fill - -template <class _Cp> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void -fill(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __last, bool __value) { - std::fill_n(__first, static_cast<typename _Cp::size_type>(__last - __first), __value); -} - // copy template <class _Cp, bool _IsConst> @@ -1007,8 +952,10 @@ private: friend class __bit_iterator<_Cp, true>; template <class _Dp> friend struct __bit_array; + template <bool _FillVal, class _Dp> - _LIBCPP_CONSTEXPR_SINCE_CXX20 friend void __fill_n(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n); + _LIBCPP_CONSTEXPR_SINCE_CXX20 friend void + __fill_n_bool(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n); template <class _Dp, bool _IC> _LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_aligned( diff --git a/libcxx/include/__chrono/tzdb_list.h b/libcxx/include/__chrono/tzdb_list.h index 112e04ff2ee6ace9bd5c83764591a5bc8f8ac792..e8aaf31e36316cb77db95ed1d9ddf9b1a34d2246 100644 --- a/libcxx/include/__chrono/tzdb_list.h +++ b/libcxx/include/__chrono/tzdb_list.h @@ -52,19 +52,29 @@ public: using const_iterator = forward_list<tzdb>::const_iterator; - _LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI const tzdb& front() const noexcept; + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const tzdb& front() const noexcept { return __front(); } - _LIBCPP_EXPORTED_FROM_ABI const_iterator erase_after(const_iterator __p); + _LIBCPP_HIDE_FROM_ABI const_iterator erase_after(const_iterator __p) { return __erase_after(__p); } - _LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI const_iterator begin() const noexcept; - _LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI const_iterator end() const noexcept; + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { return __begin(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { return __end(); } - _LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI const_iterator cbegin() const noexcept; - _LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI const_iterator cend() const noexcept; + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return __cbegin(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return __cend(); } [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __impl& __implementation() { return *__impl_; } private: + [[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI const tzdb& __front() const noexcept; + + _LIBCPP_EXPORTED_FROM_ABI const_iterator __erase_after(const_iterator __p); + + [[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI const_iterator __begin() const noexcept; + [[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI const_iterator __end() const noexcept; + + [[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI const_iterator __cbegin() const noexcept; + [[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI const_iterator __cend() const noexcept; + __impl* __impl_; }; diff --git a/libcxx/include/__compare/partial_order.h b/libcxx/include/__compare/partial_order.h index f3ed4900fbff25288500511f5f9aebdcd82dd0eb..1d2fae63e5f248b83731ff3fd69495af0811630c 100644 --- a/libcxx/include/__compare/partial_order.h +++ b/libcxx/include/__compare/partial_order.h @@ -28,6 +28,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD // [cmp.alg] namespace __partial_order { +void partial_order() = delete; + struct __fn { // NOLINTBEGIN(libcpp-robust-against-adl) partial_order should use ADL, but only here template <class _Tp, class _Up> diff --git a/libcxx/include/__compare/strong_order.h b/libcxx/include/__compare/strong_order.h index 3dc819e642515c535888496d6f3175ed6eba1dbf..8c363b5638222180344e68807fe6bb5fae3f5826 100644 --- a/libcxx/include/__compare/strong_order.h +++ b/libcxx/include/__compare/strong_order.h @@ -37,6 +37,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD // [cmp.alg] namespace __strong_order { +void strong_order() = delete; + struct __fn { // NOLINTBEGIN(libcpp-robust-against-adl) strong_order should use ADL, but only here template <class _Tp, class _Up> diff --git a/libcxx/include/__compare/weak_order.h b/libcxx/include/__compare/weak_order.h index b82a708c29a146c047fce84627b8dc4674714e02..1a3e85feb233b3330f553b9efda1fc437954e683 100644 --- a/libcxx/include/__compare/weak_order.h +++ b/libcxx/include/__compare/weak_order.h @@ -30,6 +30,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD // [cmp.alg] namespace __weak_order { +void weak_order() = delete; + struct __fn { // NOLINTBEGIN(libcpp-robust-against-adl) weak_order should use ADL, but only here template <class _Tp, class _Up> diff --git a/libcxx/include/__concepts/class_or_enum.h b/libcxx/include/__concepts/class_or_enum.h index c1b4a8c258f3a5dd7566e57788d14504ebe51cc5..2739e31e14ba65f2073a04274681a7dfe93e2ee1 100644 --- a/libcxx/include/__concepts/class_or_enum.h +++ b/libcxx/include/__concepts/class_or_enum.h @@ -28,11 +28,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> concept __class_or_enum = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>; -// Work around Clang bug https://llvm.org/PR52970 -// TODO: remove this workaround once libc++ no longer has to support Clang 13 (it was fixed in Clang 14). -template <class _Tp> -concept __workaround_52970 = is_class_v<__remove_cvref_t<_Tp>> || is_union_v<__remove_cvref_t<_Tp>>; - #endif // _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__concepts/swappable.h b/libcxx/include/__concepts/swappable.h index 1337dc49d75b10fd55ca0c19b908eda0ca364a29..d339488a087a5c4157f9b338556102bde0207c27 100644 --- a/libcxx/include/__concepts/swappable.h +++ b/libcxx/include/__concepts/swappable.h @@ -15,8 +15,8 @@ #include <__concepts/constructible.h> #include <__config> #include <__type_traits/extent.h> -#include <__type_traits/is_nothrow_move_assignable.h> -#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_nothrow_assignable.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/remove_cvref.h> #include <__utility/exchange.h> #include <__utility/forward.h> diff --git a/libcxx/include/__config b/libcxx/include/__config index 11e13e0c24986a36589d4658b578d06287679aa7..8550b1da4a2787b629317e80cd31c1ed279032a9 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -805,6 +805,12 @@ typedef __char32_t char32_t; // the implementation of a virtual function in an ABI-incompatible way in the first place, // since that would be an ABI break anyway. Hence, the lack of ABI tag should not be noticeable. // +// The macro can be applied to record and enum types. When the tagged type is nested in +// a record this "parent" record needs to have the macro too. Another use case for applying +// this macro to records and unions is to apply an ABI tag to inline constexpr variables. +// This can be useful for inline variables that are implementation details which are expected +// to change in the future. +// // TODO: We provide a escape hatch with _LIBCPP_NO_ABI_TAG for folks who want to avoid increasing // the length of symbols with an ABI tag. In practice, we should remove the escape hatch and // use compression mangling instead, see https://github.com/itanium-cxx-abi/cxx-abi/issues/70. @@ -838,21 +844,33 @@ typedef __char32_t char32_t; # define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++2b-extensions") #endif +// Clang modules take a significant compile time hit when pushing and popping diagnostics. +// Since all the headers are marked as system headers in the modulemap, we can simply disable this +// pushing and popping when building with clang modules. +# if !__has_feature(modules) +# define _LIBCPP_PUSH_EXTENSION_DIAGNOSTICS \ + _LIBCPP_DIAGNOSTIC_PUSH \ + _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++11-extensions") \ + _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++14-extensions") \ + _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++17-extensions") \ + _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++20-extensions") \ + _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION \ + _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++14-extensions") \ + _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++17-extensions") \ + _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++20-extensions") \ + _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++23-extensions") +# define _LIBCPP_POP_EXTENSION_DIAGNOSTICS _LIBCPP_DIAGNOSTIC_POP +# else +# define _LIBCPP_PUSH_EXTENSION_DIAGNOSTICS +# define _LIBCPP_POP_EXTENSION_DIAGNOSTICS +# endif + // Inline namespaces are available in Clang/GCC/MSVC regardless of C++ dialect. // clang-format off -# define _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_DIAGNOSTIC_PUSH \ - _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++11-extensions") \ - _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++14-extensions") \ - _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++17-extensions") \ - _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++20-extensions") \ - _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION \ - _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++14-extensions") \ - _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++17-extensions") \ - _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++20-extensions") \ - _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++23-extensions") \ +# define _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_PUSH_EXTENSION_DIAGNOSTICS \ namespace _LIBCPP_TYPE_VISIBILITY_DEFAULT std { \ inline namespace _LIBCPP_ABI_NAMESPACE { -# define _LIBCPP_END_NAMESPACE_STD }} _LIBCPP_DIAGNOSTIC_POP +# define _LIBCPP_END_NAMESPACE_STD }} _LIBCPP_POP_EXTENSION_DIAGNOSTICS # define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM _LIBCPP_BEGIN_NAMESPACE_STD \ inline namespace __fs { namespace filesystem { @@ -1238,8 +1256,6 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c # endif // _LIBCPP_ENABLE_CXX17_REMOVED_FEATURES # if defined(_LIBCPP_ENABLE_CXX20_REMOVED_FEATURES) -# define _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS -# define _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_VOID_SPECIALIZATION # define _LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS # define _LIBCPP_ENABLE_CXX20_REMOVED_NEGATORS # define _LIBCPP_ENABLE_CXX20_REMOVED_RAW_STORAGE_ITERATOR diff --git a/libcxx/include/__exception/nested_exception.h b/libcxx/include/__exception/nested_exception.h index 417db54e6eaacd6285414890f5ccd53ef6ee2922..1bf2df939258a6a1a21d116218aa76517c735b71 100644 --- a/libcxx/include/__exception/nested_exception.h +++ b/libcxx/include/__exception/nested_exception.h @@ -15,8 +15,8 @@ #include <__type_traits/decay.h> #include <__type_traits/is_base_of.h> #include <__type_traits/is_class.h> +#include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> -#include <__type_traits/is_copy_constructible.h> #include <__type_traits/is_final.h> #include <__type_traits/is_polymorphic.h> #include <__utility/forward.h> diff --git a/libcxx/include/__exception/operations.h b/libcxx/include/__exception/operations.h index 8f374c0ccee50b5c719575bfd6be757bff96ac22..0a9c7a7c7f0d88784b7b414683c4b68fbb3a986d 100644 --- a/libcxx/include/__exception/operations.h +++ b/libcxx/include/__exception/operations.h @@ -9,7 +9,6 @@ #ifndef _LIBCPP___EXCEPTION_OPERATIONS_H #define _LIBCPP___EXCEPTION_OPERATIONS_H -#include <__availability> #include <__config> #include <cstddef> diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h index 443d9257dc598d12f10eb9f52f2260fc469ecb04..d7adaac7567b2fb9cd972944723529cacd7e2aa0 100644 --- a/libcxx/include/__expected/expected.h +++ b/libcxx/include/__expected/expected.h @@ -23,24 +23,14 @@ #include <__type_traits/is_assignable.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> -#include <__type_traits/is_copy_assignable.h> -#include <__type_traits/is_copy_constructible.h> -#include <__type_traits/is_default_constructible.h> #include <__type_traits/is_function.h> -#include <__type_traits/is_move_assignable.h> -#include <__type_traits/is_move_constructible.h> +#include <__type_traits/is_nothrow_assignable.h> #include <__type_traits/is_nothrow_constructible.h> -#include <__type_traits/is_nothrow_copy_assignable.h> -#include <__type_traits/is_nothrow_copy_constructible.h> -#include <__type_traits/is_nothrow_default_constructible.h> -#include <__type_traits/is_nothrow_move_assignable.h> -#include <__type_traits/is_nothrow_move_constructible.h> #include <__type_traits/is_reference.h> #include <__type_traits/is_same.h> #include <__type_traits/is_swappable.h> -#include <__type_traits/is_trivially_copy_constructible.h> +#include <__type_traits/is_trivially_constructible.h> #include <__type_traits/is_trivially_destructible.h> -#include <__type_traits/is_trivially_move_constructible.h> #include <__type_traits/is_void.h> #include <__type_traits/lazy.h> #include <__type_traits/negation.h> diff --git a/libcxx/include/__filesystem/copy_options.h b/libcxx/include/__filesystem/copy_options.h index 1bf71292c8a66b089dc19e2630b6137a61459561..097eebe61137d7826ae3291ab11a31eb3115ca65 100644 --- a/libcxx/include/__filesystem/copy_options.h +++ b/libcxx/include/__filesystem/copy_options.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FILESYSTEM_COPY_OPTIONS_H #define _LIBCPP___FILESYSTEM_COPY_OPTIONS_H -#include <__availability> #include <__config> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__filesystem/directory_options.h b/libcxx/include/__filesystem/directory_options.h index 683c4678e083bc85704813d711e499a1b535f9ab..d0cd3ebfdaa7ee798a123867142a89738a12a114 100644 --- a/libcxx/include/__filesystem/directory_options.h +++ b/libcxx/include/__filesystem/directory_options.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FILESYSTEM_DIRECTORY_OPTIONS_H #define _LIBCPP___FILESYSTEM_DIRECTORY_OPTIONS_H -#include <__availability> #include <__config> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__filesystem/file_status.h b/libcxx/include/__filesystem/file_status.h index 3e2b32eef82e024431230bf6ac9d4c5271a48ecf..da316c8b027464f086d5d31b2272106c5fb59c69 100644 --- a/libcxx/include/__filesystem/file_status.h +++ b/libcxx/include/__filesystem/file_status.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FILESYSTEM_FILE_STATUS_H #define _LIBCPP___FILESYSTEM_FILE_STATUS_H -#include <__availability> #include <__config> #include <__filesystem/file_type.h> #include <__filesystem/perms.h> diff --git a/libcxx/include/__filesystem/file_time_type.h b/libcxx/include/__filesystem/file_time_type.h index e086dbcc3f51df21c26efb5266f3ec9dc403df0e..63e4ae1578cfd9f8fbf88be261c22f27f712d5d3 100644 --- a/libcxx/include/__filesystem/file_time_type.h +++ b/libcxx/include/__filesystem/file_time_type.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FILESYSTEM_FILE_TIME_TYPE_H #define _LIBCPP___FILESYSTEM_FILE_TIME_TYPE_H -#include <__availability> #include <__chrono/file_clock.h> #include <__chrono/time_point.h> #include <__config> diff --git a/libcxx/include/__filesystem/file_type.h b/libcxx/include/__filesystem/file_type.h index c509085d90de0d3821bb6fc577713b243dcfd597..e4ac1dfee9ed9b6d8fb7a9c871885db4457a7340 100644 --- a/libcxx/include/__filesystem/file_type.h +++ b/libcxx/include/__filesystem/file_type.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FILESYSTEM_FILE_TYPE_H #define _LIBCPP___FILESYSTEM_FILE_TYPE_H -#include <__availability> #include <__config> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__filesystem/perm_options.h b/libcxx/include/__filesystem/perm_options.h index 529ef13558e97272ffe5cc9c9fd4aaf7df6aab8c..64c16ee60a17d0856388de91c067fb61ae3f7116 100644 --- a/libcxx/include/__filesystem/perm_options.h +++ b/libcxx/include/__filesystem/perm_options.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FILESYSTEM_PERM_OPTIONS_H #define _LIBCPP___FILESYSTEM_PERM_OPTIONS_H -#include <__availability> #include <__config> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__filesystem/perms.h b/libcxx/include/__filesystem/perms.h index 8f5f9a7e8248ef0d449fdf2b58b80fbffadd9e49..458f1e6e5348339ec0007f764458924669cdfe30 100644 --- a/libcxx/include/__filesystem/perms.h +++ b/libcxx/include/__filesystem/perms.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FILESYSTEM_PERMS_H #define _LIBCPP___FILESYSTEM_PERMS_H -#include <__availability> #include <__config> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__filesystem/space_info.h b/libcxx/include/__filesystem/space_info.h index 2e80ae3b2c1120359b69d5bb36c435f26f7c2809..3fa57d33096fc89daf95bd2f460c5be348a45fc7 100644 --- a/libcxx/include/__filesystem/space_info.h +++ b/libcxx/include/__filesystem/space_info.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FILESYSTEM_SPACE_INFO_H #define _LIBCPP___FILESYSTEM_SPACE_INFO_H -#include <__availability> #include <__config> #include <cstdint> diff --git a/libcxx/include/__format/concepts.h b/libcxx/include/__format/concepts.h index d7b5a9d16df70a99267d988b8d117652897439cd..13380e9b91aff85862d874607ee96f86fd0569f6 100644 --- a/libcxx/include/__format/concepts.h +++ b/libcxx/include/__format/concepts.h @@ -15,10 +15,12 @@ #include <__config> #include <__format/format_parse_context.h> #include <__fwd/format.h> +#include <__fwd/tuple.h> +#include <__tuple/tuple_size.h> #include <__type_traits/is_specialization.h> #include <__type_traits/remove_const.h> +#include <__type_traits/remove_reference.h> #include <__utility/pair.h> -#include <tuple> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__format/container_adaptor.h b/libcxx/include/__format/container_adaptor.h index ec806ef16bf5281179b91b2962c5ebd63b2236e2..9f49ca03bf4f50c332262bb257e52ed3f4ac3385 100644 --- a/libcxx/include/__format/container_adaptor.h +++ b/libcxx/include/__format/container_adaptor.h @@ -18,11 +18,11 @@ #include <__format/concepts.h> #include <__format/formatter.h> #include <__format/range_default_formatter.h> +#include <__fwd/queue.h> +#include <__fwd/stack.h> #include <__ranges/ref_view.h> #include <__type_traits/is_const.h> #include <__type_traits/maybe_const.h> -#include <queue> -#include <stack> _LIBCPP_BEGIN_NAMESPACE_STD diff --git a/libcxx/include/__format/escaped_output_table.h b/libcxx/include/__format/escaped_output_table.h index 495a2fbc7b034305de741dcdf6a93b09745a08fa..e9f4a6e4f63f567d7c9ba24fb885f38779ae7188 100644 --- a/libcxx/include/__format/escaped_output_table.h +++ b/libcxx/include/__format/escaped_output_table.h @@ -110,7 +110,7 @@ namespace __escaped_output_table { /// - bits [0, 10] The size of the range, allowing 2048 elements. /// - bits [11, 31] The lower bound code point of the range. The upper bound of /// the range is lower bound + size. -inline constexpr uint32_t __entries[893] = { +_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[893] = { 0x00000020, 0x0003f821, 0x00056800, diff --git a/libcxx/include/__format/extended_grapheme_cluster_table.h b/libcxx/include/__format/extended_grapheme_cluster_table.h index 9616dfecd6047fbb4b674e38e59bcd6a643c7d6f..48581d8a5dde3df96a5cf25610e4d5bef9413dd5 100644 --- a/libcxx/include/__format/extended_grapheme_cluster_table.h +++ b/libcxx/include/__format/extended_grapheme_cluster_table.h @@ -125,7 +125,7 @@ enum class __property : uint8_t { /// following benchmark. /// libcxx/benchmarks/std_format_spec_string_unicode.bench.cpp // clang-format off -inline constexpr uint32_t __entries[1496] = { +_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[1496] = { 0x00000091, 0x00005005, 0x00005811, diff --git a/libcxx/include/__format/format_arg_store.h b/libcxx/include/__format/format_arg_store.h index 066cd369eb8918c16d837ca6a32a144ec436e3d1..23a599e99575999dbed5a6a0f548d047f9f415f5 100644 --- a/libcxx/include/__format/format_arg_store.h +++ b/libcxx/include/__format/format_arg_store.h @@ -151,7 +151,7 @@ consteval __arg_t __determine_arg_t() { // The overload for not formattable types allows triggering the static // assertion below. template <class _Context, class _Tp> - requires(!__formattable<_Tp, typename _Context::char_type>) + requires(!__formattable_with<_Tp, _Context>) consteval __arg_t __determine_arg_t() { return __arg_t::__none; } @@ -165,7 +165,6 @@ _LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> __create_format_arg(_Tp& __valu using _Dp = remove_const_t<_Tp>; constexpr __arg_t __arg = __determine_arg_t<_Context, _Dp>(); static_assert(__arg != __arg_t::__none, "the supplied type is not formattable"); - static_assert(__formattable_with<_Tp, _Context>); // Not all types can be used to directly initialize the diff --git a/libcxx/include/__format/format_args.h b/libcxx/include/__format/format_args.h index 79fe51f96c6a5063fb572db42fd3b476cde51cd5..a5fde36a29817492757fe95e19afbf9ceb9728d9 100644 --- a/libcxx/include/__format/format_args.h +++ b/libcxx/include/__format/format_args.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FORMAT_FORMAT_ARGS_H #define _LIBCPP___FORMAT_FORMAT_ARGS_H -#include <__availability> #include <__config> #include <__format/format_arg.h> #include <__format/format_arg_store.h> diff --git a/libcxx/include/__format/format_context.h b/libcxx/include/__format/format_context.h index d131e942aca60b0042ba9e9cfc5bfbcf470d6169..087d4bf289b878df253a5eb7aad6bf48fe401e67 100644 --- a/libcxx/include/__format/format_context.h +++ b/libcxx/include/__format/format_context.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FORMAT_FORMAT_CONTEXT_H #define _LIBCPP___FORMAT_FORMAT_CONTEXT_H -#include <__availability> #include <__concepts/same_as.h> #include <__config> #include <__format/buffer.h> @@ -27,7 +26,7 @@ #include <cstddef> #ifndef _LIBCPP_HAS_NO_LOCALIZATION -# include <locale> +# include <__locale> # include <optional> #endif diff --git a/libcxx/include/__format/format_functions.h b/libcxx/include/__format/format_functions.h index 3ee53539f4ee6cb88c4841b43653b539fda69fc2..c7810140105a07225e522d9719e61a385815003f 100644 --- a/libcxx/include/__format/format_functions.h +++ b/libcxx/include/__format/format_functions.h @@ -41,7 +41,7 @@ #include <string_view> #ifndef _LIBCPP_HAS_NO_LOCALIZATION -# include <locale> +# include <__locale> #endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__format/formatter.h b/libcxx/include/__format/formatter.h index 47e35789b8175bc1baa7663e922f2cef9be48217..e2f418f936ee10e401d9c879729d1722fa1b1b34 100644 --- a/libcxx/include/__format/formatter.h +++ b/libcxx/include/__format/formatter.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FORMAT_FORMATTER_H #define _LIBCPP___FORMAT_FORMATTER_H -#include <__availability> #include <__config> #include <__fwd/format.h> diff --git a/libcxx/include/__format/formatter_bool.h b/libcxx/include/__format/formatter_bool.h index 5e3daff7b3dba6d591190714230e2bb85494f889..17dc69541e8fe1b1c6ebee117fdbed78873b00b6 100644 --- a/libcxx/include/__format/formatter_bool.h +++ b/libcxx/include/__format/formatter_bool.h @@ -12,7 +12,6 @@ #include <__algorithm/copy.h> #include <__assert> -#include <__availability> #include <__config> #include <__format/concepts.h> #include <__format/format_parse_context.h> diff --git a/libcxx/include/__format/formatter_char.h b/libcxx/include/__format/formatter_char.h index 3358d422252f43055f0a05599bee850aae07573a..d33e84368a7650d3c498b1af89bf6554175ddc01 100644 --- a/libcxx/include/__format/formatter_char.h +++ b/libcxx/include/__format/formatter_char.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FORMAT_FORMATTER_CHAR_H #define _LIBCPP___FORMAT_FORMATTER_CHAR_H -#include <__availability> #include <__concepts/same_as.h> #include <__config> #include <__format/concepts.h> diff --git a/libcxx/include/__format/formatter_floating_point.h b/libcxx/include/__format/formatter_floating_point.h index f01d323efff5fc6d52e62e829cfcddb9762cad4a..1d94cc349c0dd6828bd4d44a4ec461ab4b080680 100644 --- a/libcxx/include/__format/formatter_floating_point.h +++ b/libcxx/include/__format/formatter_floating_point.h @@ -39,7 +39,7 @@ #include <cstddef> #ifndef _LIBCPP_HAS_NO_LOCALIZATION -# include <locale> +# include <__locale> #endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__format/formatter_integer.h b/libcxx/include/__format/formatter_integer.h index d57082b3881baa282a04faddc18ce1bede6f5736..41400f00478eb474a31105a7e0a0c7301fbc7e11 100644 --- a/libcxx/include/__format/formatter_integer.h +++ b/libcxx/include/__format/formatter_integer.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FORMAT_FORMATTER_INTEGER_H #define _LIBCPP___FORMAT_FORMATTER_INTEGER_H -#include <__availability> #include <__concepts/arithmetic.h> #include <__config> #include <__format/concepts.h> diff --git a/libcxx/include/__format/formatter_pointer.h b/libcxx/include/__format/formatter_pointer.h index 3373996ec3d5fa234c073f47c1bd9c414383169a..6941343efd91f99b87338159e1bbeed89082f5e1 100644 --- a/libcxx/include/__format/formatter_pointer.h +++ b/libcxx/include/__format/formatter_pointer.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FORMAT_FORMATTER_POINTER_H #define _LIBCPP___FORMAT_FORMATTER_POINTER_H -#include <__availability> #include <__config> #include <__format/concepts.h> #include <__format/format_parse_context.h> diff --git a/libcxx/include/__format/formatter_string.h b/libcxx/include/__format/formatter_string.h index d1ccfb9b5f7dc95fd3c6dbb603c01b7734617b87..347439fc8dff13253f0b6adbab741b6b5e416209 100644 --- a/libcxx/include/__format/formatter_string.h +++ b/libcxx/include/__format/formatter_string.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FORMAT_FORMATTER_STRING_H #define _LIBCPP___FORMAT_FORMATTER_STRING_H -#include <__availability> #include <__config> #include <__format/concepts.h> #include <__format/format_parse_context.h> diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h index a4b47abff40dc5244b22adabc3646a8bc6bb4e4e..9818f37b518e80654f9f9d770f9f787e8759929b 100644 --- a/libcxx/include/__format/parser_std_format_spec.h +++ b/libcxx/include/__format/parser_std_format_spec.h @@ -129,8 +129,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr uint32_t __substitute_arg_id(basic_format_arg<_C /// /// They default to false so when a new field is added it needs to be opted in /// explicitly. -// TODO FMT Use an ABI tag for this struct. -struct __fields { +struct _LIBCPP_HIDE_FROM_ABI __fields { uint16_t __sign_ : 1 {false}; uint16_t __alternate_form_ : 1 {false}; uint16_t __zero_padding_ : 1 {false}; diff --git a/libcxx/include/__format/width_estimation_table.h b/libcxx/include/__format/width_estimation_table.h index cfb488975d5712732814c03b7a1e846b7d6b5e6a..6309483367f13d234172df6a1d58e65330f7be06 100644 --- a/libcxx/include/__format/width_estimation_table.h +++ b/libcxx/include/__format/width_estimation_table.h @@ -119,7 +119,7 @@ namespace __width_estimation_table { /// - bits [0, 13] The size of the range, allowing 16384 elements. /// - bits [14, 31] The lower bound code point of the range. The upper bound of /// the range is lower bound + size. -inline constexpr uint32_t __entries[108] = { +_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[108] = { 0x0440005f /* 00001100 - 0000115f [ 96] */, // 0x08c68001 /* 0000231a - 0000231b [ 2] */, // 0x08ca4001 /* 00002329 - 0000232a [ 2] */, // diff --git a/libcxx/include/__functional/bind_front.h b/libcxx/include/__functional/bind_front.h index 30dda533615b28006024bf7f403f353dcb4763b7..11d0bac3f839ceb6e92d056cb24df733cb7b8fec 100644 --- a/libcxx/include/__functional/bind_front.h +++ b/libcxx/include/__functional/bind_front.h @@ -17,7 +17,6 @@ #include <__type_traits/decay.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_constructible.h> -#include <__type_traits/is_move_constructible.h> #include <__utility/forward.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__functional/function.h b/libcxx/include/__functional/function.h index 416c26a0c73f2edf6194fc81e47aa4a609d37a5c..1faa9e92ebd63e2201054f46e6fd2b11210bbf61 100644 --- a/libcxx/include/__functional/function.h +++ b/libcxx/include/__functional/function.h @@ -28,7 +28,7 @@ #include <__type_traits/decay.h> #include <__type_traits/is_core_convertible.h> #include <__type_traits/is_scalar.h> -#include <__type_traits/is_trivially_copy_constructible.h> +#include <__type_traits/is_trivially_constructible.h> #include <__type_traits/is_trivially_destructible.h> #include <__type_traits/is_void.h> #include <__type_traits/strip_signature.h> @@ -768,7 +768,7 @@ public: { } - virtual __base<_Rp(_ArgTypes...)>* __clone() const { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual __base<_Rp(_ArgTypes...)>* __clone() const { _LIBCPP_ASSERT_INTERNAL( false, "Block pointers are just pointers, so they should always fit into " @@ -777,9 +777,11 @@ public: return nullptr; } - virtual void __clone(__base<_Rp(_ArgTypes...)>* __p) const { ::new ((void*)__p) __func(__f_); } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void __clone(__base<_Rp(_ArgTypes...)>* __p) const { + ::new ((void*)__p) __func(__f_); + } - virtual void destroy() _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy() _NOEXCEPT { # ifndef _LIBCPP_HAS_OBJC_ARC if (__f_) _Block_release(__f_); @@ -787,7 +789,7 @@ public: __f_ = 0; } - virtual void destroy_deallocate() _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual void destroy_deallocate() _NOEXCEPT { _LIBCPP_ASSERT_INTERNAL( false, "Block pointers are just pointers, so they should always fit into " @@ -795,16 +797,20 @@ public: "never be invoked."); } - virtual _Rp operator()(_ArgTypes&&... __arg) { return std::__invoke(__f_, std::forward<_ArgTypes>(__arg)...); } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual _Rp operator()(_ArgTypes&&... __arg) { + return std::__invoke(__f_, std::forward<_ArgTypes>(__arg)...); + } # ifndef _LIBCPP_HAS_NO_RTTI - virtual const void* target(type_info const& __ti) const _NOEXCEPT { + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual const void* target(type_info const& __ti) const _NOEXCEPT { if (__ti == typeid(__func::__block_type)) return &__f_; return (const void*)nullptr; } - virtual const std::type_info& target_type() const _NOEXCEPT { return typeid(__func::__block_type); } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual const std::type_info& target_type() const _NOEXCEPT { + return typeid(__func::__block_type); + } # endif // _LIBCPP_HAS_NO_RTTI }; diff --git a/libcxx/include/__functional/hash.h b/libcxx/include/__functional/hash.h index a466c837038f8da633cda44d66e06a48879563d5..a9e450edd39f5352146901d546254a19e1d5b0a5 100644 --- a/libcxx/include/__functional/hash.h +++ b/libcxx/include/__functional/hash.h @@ -10,23 +10,18 @@ #define _LIBCPP___FUNCTIONAL_HASH_H #include <__config> -#include <__functional/invoke.h> #include <__functional/unary_function.h> #include <__fwd/functional.h> -#include <__tuple/sfinae_helpers.h> -#include <__type_traits/is_copy_constructible.h> -#include <__type_traits/is_default_constructible.h> +#include <__type_traits/conjunction.h> +#include <__type_traits/invoke.h> +#include <__type_traits/is_constructible.h> #include <__type_traits/is_enum.h> -#include <__type_traits/is_move_constructible.h> #include <__type_traits/underlying_type.h> -#include <__utility/forward.h> -#include <__utility/move.h> #include <__utility/pair.h> #include <__utility/swap.h> #include <cstddef> #include <cstdint> #include <cstring> -#include <limits> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__functional/not_fn.h b/libcxx/include/__functional/not_fn.h index 23a491c135d79d2d0d8b81250255a24d991b140c..4b3ce5524a7434ec098ec677e83f6ef79099a8d1 100644 --- a/libcxx/include/__functional/not_fn.h +++ b/libcxx/include/__functional/not_fn.h @@ -16,7 +16,6 @@ #include <__type_traits/decay.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_constructible.h> -#include <__type_traits/is_move_constructible.h> #include <__utility/forward.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__fwd/deque.h b/libcxx/include/__fwd/deque.h new file mode 100644 index 0000000000000000000000000000000000000000..fd2fb5bb4b8e9273d4d2482d5fb2a06e461c8e03 --- /dev/null +++ b/libcxx/include/__fwd/deque.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 _LIBCPP___FWD_DEQUE_H +#define _LIBCPP___FWD_DEQUE_H + +#include <__config> +#include <__fwd/memory.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp, class _Allocator = allocator<_Tp> > +class _LIBCPP_TEMPLATE_VIS deque; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_DEQUE_H diff --git a/libcxx/include/__fwd/format.h b/libcxx/include/__fwd/format.h index 6f5c71243711fe9ce7dc6ebba84ef88cee5afaa3..b30c220f8a0435c95e4b2587ed572471aad05955 100644 --- a/libcxx/include/__fwd/format.h +++ b/libcxx/include/__fwd/format.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___FWD_FORMAT_H #define _LIBCPP___FWD_FORMAT_H -#include <__availability> #include <__config> #include <__iterator/concepts.h> diff --git a/libcxx/include/__tuple/pair_like.h b/libcxx/include/__fwd/memory.h similarity index 56% rename from libcxx/include/__tuple/pair_like.h rename to libcxx/include/__fwd/memory.h index 192682dc7eb5984299417f81bdae33695b8c3b8f..b9e151855ad7d8549a8d3b5ab9288cb4fff05853 100644 --- a/libcxx/include/__tuple/pair_like.h +++ b/libcxx/include/__fwd/memory.h @@ -1,18 +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 // -//===----------------------------------------------------------------------===// +//===---------------------------------------------------------------------===// -#ifndef _LIBCPP___TUPLE_PAIR_LIKE_H -#define _LIBCPP___TUPLE_PAIR_LIKE_H +#ifndef _LIBCPP___FWD_MEMORY_H +#define _LIBCPP___FWD_MEMORY_H #include <__config> -#include <__tuple/tuple_like.h> -#include <__tuple/tuple_size.h> -#include <__type_traits/remove_cvref.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -20,13 +17,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD -#if _LIBCPP_STD_VER >= 20 - template <class _Tp> -concept __pair_like = __tuple_like<_Tp> && tuple_size<remove_cvref_t<_Tp>>::value == 2; - -#endif // _LIBCPP_STD_VER >= 20 +class _LIBCPP_TEMPLATE_VIS allocator; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP___TUPLE_PAIR_LIKE_H +#endif // _LIBCPP___FWD_MEMORY_H diff --git a/libcxx/include/__fwd/queue.h b/libcxx/include/__fwd/queue.h new file mode 100644 index 0000000000000000000000000000000000000000..50d99ad9c29f4517cf978248c03aaa8964263d75 --- /dev/null +++ b/libcxx/include/__fwd/queue.h @@ -0,0 +1,31 @@ +//===---------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___FWD_QUEUE_H +#define _LIBCPP___FWD_QUEUE_H + +#include <__config> +#include <__functional/operations.h> +#include <__fwd/deque.h> +#include <__fwd/vector.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp, class _Container = deque<_Tp> > +class _LIBCPP_TEMPLATE_VIS queue; + +template <class _Tp, class _Container = vector<_Tp>, class _Compare = less<typename _Container::value_type> > +class _LIBCPP_TEMPLATE_VIS priority_queue; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_QUEUE_H diff --git a/libcxx/include/__fwd/sstream.h b/libcxx/include/__fwd/sstream.h index e2d46fbe1d9bb4de21d805db923e73208d7787fc..39a9c3faf1f800ca6373e8a94b08a943a5cacb30 100644 --- a/libcxx/include/__fwd/sstream.h +++ b/libcxx/include/__fwd/sstream.h @@ -10,6 +10,7 @@ #define _LIBCPP___FWD_SSTREAM_H #include <__config> +#include <__fwd/memory.h> #include <__fwd/string.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__fwd/stack.h b/libcxx/include/__fwd/stack.h new file mode 100644 index 0000000000000000000000000000000000000000..7dab6c1a4f4e2eaa3bb8ce0f0ca42813710b8862 --- /dev/null +++ b/libcxx/include/__fwd/stack.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 _LIBCPP___FWD_STACK_H +#define _LIBCPP___FWD_STACK_H + +#include <__config> +#include <__fwd/deque.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp, class _Container = deque<_Tp> > +class _LIBCPP_TEMPLATE_VIS stack; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_STACK_H diff --git a/libcxx/include/__fwd/string.h b/libcxx/include/__fwd/string.h index 032132374de5edfa62119458c826571d6ec9dc7a..320c4e4c81836103f606341efaf8348ae44f4732 100644 --- a/libcxx/include/__fwd/string.h +++ b/libcxx/include/__fwd/string.h @@ -11,6 +11,7 @@ #include <__availability> #include <__config> +#include <__fwd/memory.h> #include <__fwd/memory_resource.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -39,9 +40,6 @@ template <> struct char_traits<wchar_t>; #endif -template <class _Tp> -class _LIBCPP_TEMPLATE_VIS allocator; - template <class _CharT, class _Traits = char_traits<_CharT>, class _Allocator = allocator<_CharT> > class _LIBCPP_TEMPLATE_VIS basic_string; diff --git a/libcxx/include/__fwd/vector.h b/libcxx/include/__fwd/vector.h new file mode 100644 index 0000000000000000000000000000000000000000..c9cc96137449f8bd20bb197633d8907429134288 --- /dev/null +++ b/libcxx/include/__fwd/vector.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 _LIBCPP___FWD_VECTOR_H +#define _LIBCPP___FWD_VECTOR_H + +#include <__config> +#include <__fwd/memory.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp, class _Alloc = allocator<_Tp> > +class _LIBCPP_TEMPLATE_VIS vector; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_VECTOR_H diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index e6691e78a267f84002fa6c8232abdbf9cad5889f..a705117d0173f9facd7d4d48e439f7457d158a60 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -28,12 +28,9 @@ #include <__type_traits/can_extract_key.h> #include <__type_traits/conditional.h> #include <__type_traits/is_const.h> -#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_nothrow_assignable.h> #include <__type_traits/is_nothrow_constructible.h> -#include <__type_traits/is_nothrow_copy_constructible.h> -#include <__type_traits/is_nothrow_default_constructible.h> -#include <__type_traits/is_nothrow_move_assignable.h> -#include <__type_traits/is_nothrow_move_constructible.h> #include <__type_traits/is_pointer.h> #include <__type_traits/is_reference.h> #include <__type_traits/is_swappable.h> diff --git a/libcxx/include/__iterator/cpp17_iterator_concepts.h b/libcxx/include/__iterator/cpp17_iterator_concepts.h index d1ad2b4e28480843b94369f04ed6215c3a63d7b0..cdb561e68452af314dcd19f3007bd7a6f366c683 100644 --- a/libcxx/include/__iterator/cpp17_iterator_concepts.h +++ b/libcxx/include/__iterator/cpp17_iterator_concepts.h @@ -14,10 +14,8 @@ #include <__concepts/same_as.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> -#include <__type_traits/is_copy_constructible.h> -#include <__type_traits/is_default_constructible.h> -#include <__type_traits/is_move_constructible.h> #include <__type_traits/is_signed.h> #include <__type_traits/is_void.h> #include <__utility/as_const.h> diff --git a/libcxx/include/__iterator/iter_move.h b/libcxx/include/__iterator/iter_move.h index 202b94cccc5ac6557e5467be8f1925a05abbaa64..ba8aed3c0ffbbdc0383ddd878e735d5f94c09174 100644 --- a/libcxx/include/__iterator/iter_move.h +++ b/libcxx/include/__iterator/iter_move.h @@ -35,7 +35,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __iter_move { -void iter_move(); +void iter_move() = delete; template <class _Tp> concept __unqualified_iter_move = __class_or_enum<remove_cvref_t<_Tp>> && requires(_Tp&& __t) { diff --git a/libcxx/include/__iterator/iterator_traits.h b/libcxx/include/__iterator/iterator_traits.h index 2cd82525ba06392756829e42d6fad4b5748e9743..11af9e301842cf55fdf74d674e367b90f17e6c3c 100644 --- a/libcxx/include/__iterator/iterator_traits.h +++ b/libcxx/include/__iterator/iterator_traits.h @@ -21,7 +21,6 @@ #include <__fwd/pair.h> #include <__iterator/incrementable_traits.h> #include <__iterator/readable_traits.h> -#include <__type_traits/add_const.h> #include <__type_traits/common_reference.h> #include <__type_traits/conditional.h> #include <__type_traits/disjunction.h> @@ -493,8 +492,8 @@ using __iter_mapped_type = typename iterator_traits<_InputIterator>::value_type: template <class _InputIterator> using __iter_to_alloc_type = - pair< typename add_const<typename iterator_traits<_InputIterator>::value_type::first_type>::type, - typename iterator_traits<_InputIterator>::value_type::second_type>; + pair<const typename iterator_traits<_InputIterator>::value_type::first_type, + typename iterator_traits<_InputIterator>::value_type::second_type>; template <class _Iter> using __iterator_category_type = typename iterator_traits<_Iter>::iterator_category; diff --git a/libcxx/include/__iterator/ranges_iterator_traits.h b/libcxx/include/__iterator/ranges_iterator_traits.h index a30864199df76b8f1841bad712d775d1b9effb88..859e7082048ac1ed830deb682e6c8f78ab4cf4f1 100644 --- a/libcxx/include/__iterator/ranges_iterator_traits.h +++ b/libcxx/include/__iterator/ranges_iterator_traits.h @@ -13,7 +13,6 @@ #include <__config> #include <__fwd/pair.h> #include <__ranges/concepts.h> -#include <__type_traits/add_const.h> #include <__type_traits/remove_const.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -32,8 +31,7 @@ using __range_mapped_type = typename ranges::range_value_t<_Range>::second_type; template <ranges::input_range _Range> using __range_to_alloc_type = - pair<add_const_t<typename ranges::range_value_t<_Range>::first_type>, - typename ranges::range_value_t<_Range>::second_type>; + pair<const typename ranges::range_value_t<_Range>::first_type, typename ranges::range_value_t<_Range>::second_type>; #endif diff --git a/libcxx/include/__iterator/reverse_iterator.h b/libcxx/include/__iterator/reverse_iterator.h index 5900b1c5ac154ed1c238ea25eef5b2c0a2b72e64..2ae146193485365b20720fd544084f199b29ea23 100644 --- a/libcxx/include/__iterator/reverse_iterator.h +++ b/libcxx/include/__iterator/reverse_iterator.h @@ -34,7 +34,7 @@ #include <__type_traits/enable_if.h> #include <__type_traits/is_assignable.h> #include <__type_traits/is_convertible.h> -#include <__type_traits/is_nothrow_copy_constructible.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_pointer.h> #include <__type_traits/is_same.h> #include <__utility/declval.h> @@ -316,172 +316,6 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reverse_iterator<_Ite } #endif -#if _LIBCPP_STD_VER <= 17 -template <class _Iter> -using __unconstrained_reverse_iterator = reverse_iterator<_Iter>; -#else - -// __unconstrained_reverse_iterator allows us to use reverse iterators in the implementation of algorithms by working -// around a language issue in C++20. -// In C++20, when a reverse iterator wraps certain C++20-hostile iterators, calling comparison operators on it will -// result in a compilation error. However, calling comparison operators on the pristine hostile iterator is not -// an error. Thus, we cannot use reverse_iterators in the implementation of an algorithm that accepts a -// C++20-hostile iterator. This class is an internal workaround -- it is a copy of reverse_iterator with -// tweaks to make it support hostile iterators. -// -// A C++20-hostile iterator is one that defines a comparison operator where one of the arguments is an exact match -// and the other requires an implicit conversion, for example: -// friend bool operator==(const BaseIter&, const DerivedIter&); -// -// C++20 rules for rewriting equality operators create another overload of this function with parameters reversed: -// friend bool operator==(const DerivedIter&, const BaseIter&); -// -// This creates an ambiguity in overload resolution. -// -// Clang treats this ambiguity differently in different contexts. When operator== is actually called in the function -// body, the code is accepted with a warning. When a concept requires operator== to be a valid expression, however, -// it evaluates to false. Thus, the implementation of reverse_iterator::operator== can actually call operator== on its -// base iterators, but the constraints on reverse_iterator::operator== prevent it from being considered during overload -// resolution. This class simply removes the problematic constraints from comparison functions. -template <class _Iter> -class __unconstrained_reverse_iterator { - _Iter __iter_; - -public: - static_assert(__has_bidirectional_iterator_category<_Iter>::value || bidirectional_iterator<_Iter>); - - using iterator_type = _Iter; - using iterator_category = - _If<__has_random_access_iterator_category<_Iter>::value, - random_access_iterator_tag, - __iterator_category_type<_Iter>>; - using pointer = __iterator_pointer_type<_Iter>; - using value_type = iter_value_t<_Iter>; - using difference_type = iter_difference_t<_Iter>; - using reference = iter_reference_t<_Iter>; - - _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator() = default; - _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator(const __unconstrained_reverse_iterator&) = default; - _LIBCPP_HIDE_FROM_ABI constexpr explicit __unconstrained_reverse_iterator(_Iter __iter) : __iter_(__iter) {} - - _LIBCPP_HIDE_FROM_ABI constexpr _Iter base() const { return __iter_; } - _LIBCPP_HIDE_FROM_ABI constexpr reference operator*() const { - auto __tmp = __iter_; - return *--__tmp; - } - - _LIBCPP_HIDE_FROM_ABI constexpr pointer operator->() const { - if constexpr (is_pointer_v<_Iter>) { - return std::prev(__iter_); - } else { - return std::prev(__iter_).operator->(); - } - } - - _LIBCPP_HIDE_FROM_ABI friend constexpr iter_rvalue_reference_t<_Iter> - iter_move(const __unconstrained_reverse_iterator& __i) noexcept( - is_nothrow_copy_constructible_v<_Iter>&& noexcept(ranges::iter_move(--std::declval<_Iter&>()))) { - auto __tmp = __i.base(); - return ranges::iter_move(--__tmp); - } - - _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator& operator++() { - --__iter_; - return *this; - } - - _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator operator++(int) { - auto __tmp = *this; - --__iter_; - return __tmp; - } - - _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator& operator--() { - ++__iter_; - return *this; - } - - _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator operator--(int) { - auto __tmp = *this; - ++__iter_; - return __tmp; - } - - _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator& operator+=(difference_type __n) { - __iter_ -= __n; - return *this; - } - - _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator& operator-=(difference_type __n) { - __iter_ += __n; - return *this; - } - - _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator operator+(difference_type __n) const { - return __unconstrained_reverse_iterator(__iter_ - __n); - } - - _LIBCPP_HIDE_FROM_ABI constexpr __unconstrained_reverse_iterator operator-(difference_type __n) const { - return __unconstrained_reverse_iterator(__iter_ + __n); - } - - _LIBCPP_HIDE_FROM_ABI constexpr difference_type operator-(const __unconstrained_reverse_iterator& __other) const { - return __other.__iter_ - __iter_; - } - - _LIBCPP_HIDE_FROM_ABI constexpr auto operator[](difference_type __n) const { return *(*this + __n); } - - // Deliberately unconstrained unlike the comparison functions in `reverse_iterator` -- see the class comment for the - // rationale. - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator==(const __unconstrained_reverse_iterator& __lhs, const __unconstrained_reverse_iterator& __rhs) { - return __lhs.base() == __rhs.base(); - } - - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator!=(const __unconstrained_reverse_iterator& __lhs, const __unconstrained_reverse_iterator& __rhs) { - return __lhs.base() != __rhs.base(); - } - - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator<(const __unconstrained_reverse_iterator& __lhs, const __unconstrained_reverse_iterator& __rhs) { - return __lhs.base() > __rhs.base(); - } - - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator>(const __unconstrained_reverse_iterator& __lhs, const __unconstrained_reverse_iterator& __rhs) { - return __lhs.base() < __rhs.base(); - } - - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator<=(const __unconstrained_reverse_iterator& __lhs, const __unconstrained_reverse_iterator& __rhs) { - return __lhs.base() >= __rhs.base(); - } - - _LIBCPP_HIDE_FROM_ABI friend constexpr bool - operator>=(const __unconstrained_reverse_iterator& __lhs, const __unconstrained_reverse_iterator& __rhs) { - return __lhs.base() <= __rhs.base(); - } -}; - -#endif // _LIBCPP_STD_VER <= 17 - -template <template <class> class _RevIter1, template <class> class _RevIter2, class _Iter> -struct __unwrap_reverse_iter_impl { - using _UnwrappedIter = decltype(__unwrap_iter_impl<_Iter>::__unwrap(std::declval<_Iter>())); - using _ReverseWrapper = _RevIter1<_RevIter2<_Iter> >; - - static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ReverseWrapper - __rewrap(_ReverseWrapper __orig_iter, _UnwrappedIter __unwrapped_iter) { - return _ReverseWrapper( - _RevIter2<_Iter>(__unwrap_iter_impl<_Iter>::__rewrap(__orig_iter.base().base(), __unwrapped_iter))); - } - - static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _UnwrappedIter __unwrap(_ReverseWrapper __i) _NOEXCEPT { - return __unwrap_iter_impl<_Iter>::__unwrap(__i.base().base()); - } -}; - #if _LIBCPP_STD_VER >= 20 template <ranges::bidirectional_range _Range> _LIBCPP_HIDE_FROM_ABI constexpr ranges::subrange<reverse_iterator<ranges::iterator_t<_Range>>, @@ -493,24 +327,20 @@ __reverse_range(_Range&& __range) { #endif template <class _Iter, bool __b> -struct __unwrap_iter_impl<reverse_iterator<reverse_iterator<_Iter> >, __b> - : __unwrap_reverse_iter_impl<reverse_iterator, reverse_iterator, _Iter> {}; - -#if _LIBCPP_STD_VER >= 20 - -template <class _Iter, bool __b> -struct __unwrap_iter_impl<reverse_iterator<__unconstrained_reverse_iterator<_Iter>>, __b> - : __unwrap_reverse_iter_impl<reverse_iterator, __unconstrained_reverse_iterator, _Iter> {}; - -template <class _Iter, bool __b> -struct __unwrap_iter_impl<__unconstrained_reverse_iterator<reverse_iterator<_Iter>>, __b> - : __unwrap_reverse_iter_impl<__unconstrained_reverse_iterator, reverse_iterator, _Iter> {}; +struct __unwrap_iter_impl<reverse_iterator<reverse_iterator<_Iter> >, __b> { + using _UnwrappedIter = decltype(__unwrap_iter_impl<_Iter>::__unwrap(std::declval<_Iter>())); + using _ReverseWrapper = reverse_iterator<reverse_iterator<_Iter> >; -template <class _Iter, bool __b> -struct __unwrap_iter_impl<__unconstrained_reverse_iterator<__unconstrained_reverse_iterator<_Iter>>, __b> - : __unwrap_reverse_iter_impl<__unconstrained_reverse_iterator, __unconstrained_reverse_iterator, _Iter> {}; + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ReverseWrapper + __rewrap(_ReverseWrapper __orig_iter, _UnwrappedIter __unwrapped_iter) { + return _ReverseWrapper( + reverse_iterator<_Iter>(__unwrap_iter_impl<_Iter>::__rewrap(__orig_iter.base().base(), __unwrapped_iter))); + } -#endif // _LIBCPP_STD_VER >= 20 + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _UnwrappedIter __unwrap(_ReverseWrapper __i) _NOEXCEPT { + return __unwrap_iter_impl<_Iter>::__unwrap(__i.base().base()); + } +}; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__locale b/libcxx/include/__locale index 2186db84933103a4021ce3e30b2b7e54f16e51c0..fab87f0d6a279562faf55e1239bf81fee2acac9c 100644 --- a/libcxx/include/__locale +++ b/libcxx/include/__locale @@ -10,7 +10,6 @@ #ifndef _LIBCPP___LOCALE #define _LIBCPP___LOCALE -#include <__availability> #include <__config> #include <__locale_dir/locale_base_api.h> #include <__memory/shared_ptr.h> // __shared_count diff --git a/libcxx/include/__mdspan/mdspan.h b/libcxx/include/__mdspan/mdspan.h index 684828eb90ec7cd38dda303895d6c0992af8c202..d9a0108d6d3507069f7d4798cfe4f7cf2b71abea 100644 --- a/libcxx/include/__mdspan/mdspan.h +++ b/libcxx/include/__mdspan/mdspan.h @@ -27,7 +27,6 @@ #include <__type_traits/is_array.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> -#include <__type_traits/is_default_constructible.h> #include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_pointer.h> #include <__type_traits/is_same.h> diff --git a/libcxx/include/__memory/allocator.h b/libcxx/include/__memory/allocator.h index 4e6303914c38aa876a9a3372e26be503f9659570..26e5d4978b151e0830c6334935ce0e7e210b9280 100644 --- a/libcxx/include/__memory/allocator.h +++ b/libcxx/include/__memory/allocator.h @@ -31,18 +31,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD template <class _Tp> class allocator; -#if defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS) && !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS) -# pragma clang deprecated( \ - _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS, \ - "_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS is deprecated in LLVM 18 and will be removed in LLVM 19") -#endif - -#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_VOID_SPECIALIZATION) +#if _LIBCPP_STD_VER <= 17 // These specializations shouldn't be marked _LIBCPP_DEPRECATED_IN_CXX17. // Specializing allocator<void> is deprecated, but not using it. template <> class _LIBCPP_TEMPLATE_VIS allocator<void> { -# if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS) +# if _LIBCPP_STD_VER <= 17 public: _LIBCPP_DEPRECATED_IN_CXX17 typedef void* pointer; @@ -58,7 +52,7 @@ public: template <> class _LIBCPP_TEMPLATE_VIS allocator<const void> { -# if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS) +# if _LIBCPP_STD_VER <= 17 public: _LIBCPP_DEPRECATED_IN_CXX17 typedef const void* pointer; @@ -141,7 +135,7 @@ public: } // C++20 Removed members -#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS) +#if _LIBCPP_STD_VER <= 17 _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp* pointer; _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp* const_pointer; _LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp& reference; @@ -221,7 +215,7 @@ public: } // C++20 Removed members -#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS) +#if _LIBCPP_STD_VER <= 17 _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp* pointer; _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp* const_pointer; _LIBCPP_DEPRECATED_IN_CXX17 typedef const _Tp& reference; diff --git a/libcxx/include/__memory/allocator_traits.h b/libcxx/include/__memory/allocator_traits.h index e79512b2ed1468ba4a37ed723182b8093c62b843..efdaa5e4ed8a5ff04d3fd822ed3587125bfc808e 100644 --- a/libcxx/include/__memory/allocator_traits.h +++ b/libcxx/include/__memory/allocator_traits.h @@ -14,9 +14,8 @@ #include <__memory/construct_at.h> #include <__memory/pointer_traits.h> #include <__type_traits/enable_if.h> -#include <__type_traits/is_copy_constructible.h> +#include <__type_traits/is_constructible.h> #include <__type_traits/is_empty.h> -#include <__type_traits/is_move_constructible.h> #include <__type_traits/make_unsigned.h> #include <__type_traits/remove_reference.h> #include <__type_traits/void_t.h> diff --git a/libcxx/include/__memory/compressed_pair.h b/libcxx/include/__memory/compressed_pair.h index 373e131a7877daf7767072323cff74321cf0f6f7..328849d7cc12d89566ae65e7f7d0fa1676bafe93 100644 --- a/libcxx/include/__memory/compressed_pair.h +++ b/libcxx/include/__memory/compressed_pair.h @@ -16,7 +16,7 @@ #include <__type_traits/decay.h> #include <__type_traits/dependent_type.h> #include <__type_traits/enable_if.h> -#include <__type_traits/is_default_constructible.h> +#include <__type_traits/is_constructible.h> #include <__type_traits/is_empty.h> #include <__type_traits/is_final.h> #include <__type_traits/is_same.h> diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h index d90e1449678e5caab5608f0d1c03e5cabcf84008..a8ff189df2aa52569332938244e17e17569bb472 100644 --- a/libcxx/include/__memory/shared_ptr.h +++ b/libcxx/include/__memory/shared_ptr.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___MEMORY_SHARED_PTR_H #define _LIBCPP___MEMORY_SHARED_PTR_H -#include <__availability> #include <__compare/compare_three_way.h> #include <__compare/ordering.h> #include <__config> @@ -37,8 +36,8 @@ #include <__type_traits/disjunction.h> #include <__type_traits/is_array.h> #include <__type_traits/is_bounded_array.h> +#include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> -#include <__type_traits/is_move_constructible.h> #include <__type_traits/is_reference.h> #include <__type_traits/is_unbounded_array.h> #include <__type_traits/nat.h> diff --git a/libcxx/include/__memory/uninitialized_algorithms.h b/libcxx/include/__memory/uninitialized_algorithms.h index 52cce1cf7c7c6a4eef5f6e24715ac909a0b601d6..7475ef5cf85def425cf175b3e3d1b27495d2cf06 100644 --- a/libcxx/include/__memory/uninitialized_algorithms.h +++ b/libcxx/include/__memory/uninitialized_algorithms.h @@ -25,10 +25,8 @@ #include <__type_traits/extent.h> #include <__type_traits/is_array.h> #include <__type_traits/is_constant_evaluated.h> -#include <__type_traits/is_trivially_copy_assignable.h> -#include <__type_traits/is_trivially_copy_constructible.h> -#include <__type_traits/is_trivially_move_assignable.h> -#include <__type_traits/is_trivially_move_constructible.h> +#include <__type_traits/is_trivially_assignable.h> +#include <__type_traits/is_trivially_constructible.h> #include <__type_traits/is_trivially_relocatable.h> #include <__type_traits/is_unbounded_array.h> #include <__type_traits/negation.h> diff --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h index a505dab8dd7491dd6e1a672babaa9e84b05b21ea..46d9405e31596d670575603b411e3d487d229561 100644 --- a/libcxx/include/__memory/unique_ptr.h +++ b/libcxx/include/__memory/unique_ptr.h @@ -28,7 +28,6 @@ #include <__type_traits/is_assignable.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> -#include <__type_traits/is_default_constructible.h> #include <__type_traits/is_function.h> #include <__type_traits/is_pointer.h> #include <__type_traits/is_reference.h> diff --git a/libcxx/include/__memory/uses_allocator_construction.h b/libcxx/include/__memory/uses_allocator_construction.h index 71ae5bcd323315bf98cab86bd4a7f759b34248d7..9b7262bec5cf8bfe7a03515782ad8b6ceeec4c8f 100644 --- a/libcxx/include/__memory/uses_allocator_construction.h +++ b/libcxx/include/__memory/uses_allocator_construction.h @@ -12,7 +12,7 @@ #include <__config> #include <__memory/construct_at.h> #include <__memory/uses_allocator.h> -#include <__tuple/pair_like.h> +#include <__tuple/tuple_like_no_subrange.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_same.h> #include <__type_traits/remove_cv.h> @@ -128,11 +128,7 @@ __uses_allocator_construction_args(const _Alloc& __alloc, const pair<_Up, _Vp>&& std::forward_as_tuple(std::get<1>(std::move(__pair)))); } -template < class _Pair, - class _Alloc, - __pair_like _PairLike, - __enable_if_t<__is_cv_std_pair<_Pair> && !__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value, - int> = 0> +template <class _Pair, class _Alloc, __pair_like_no_subrange _PairLike, __enable_if_t<__is_cv_std_pair<_Pair>, int> = 0> _LIBCPP_HIDE_FROM_ABI constexpr auto __uses_allocator_construction_args(const _Alloc& __alloc, _PairLike&& __p) noexcept { return std::__uses_allocator_construction_args<_Pair>( @@ -161,9 +157,7 @@ inline constexpr bool __convertible_to_const_pair_ref = # if _LIBCPP_STD_VER >= 23 template <class _Tp, class _Up> inline constexpr bool __uses_allocator_constraints = - __is_cv_std_pair<_Tp> && - (__is_specialization_of_subrange<remove_cvref_t<_Up>>::value || - (!__pair_like<_Up> && !__convertible_to_const_pair_ref<_Up>)); + __is_cv_std_pair<_Tp> && !__pair_like_no_subrange<_Up> && !__convertible_to_const_pair_ref<_Up>; # else template <class _Tp, class _Up> inline constexpr bool __uses_allocator_constraints = __is_cv_std_pair<_Tp> && !__convertible_to_const_pair_ref<_Up>; diff --git a/libcxx/include/__memory_resource/polymorphic_allocator.h b/libcxx/include/__memory_resource/polymorphic_allocator.h index cfd07bc84fe8aa919c2f7797c4880f7a2be741ac..823c1503c22b65be76098614ee0cee2fc6fbff78 100644 --- a/libcxx/include/__memory_resource/polymorphic_allocator.h +++ b/libcxx/include/__memory_resource/polymorphic_allocator.h @@ -12,6 +12,7 @@ #include <__assert> #include <__availability> #include <__config> +#include <__fwd/pair.h> #include <__memory_resource/memory_resource.h> #include <__utility/exception_guard.h> #include <cstddef> diff --git a/libcxx/include/__mutex/mutex.h b/libcxx/include/__mutex/mutex.h index ddc85cf5a00d51d68d481d159991045e82b7e384..1ed01547126f48eae4446a325b93d8b12a113968 100644 --- a/libcxx/include/__mutex/mutex.h +++ b/libcxx/include/__mutex/mutex.h @@ -11,7 +11,7 @@ #include <__config> #include <__thread/support.h> -#include <__type_traits/is_nothrow_default_constructible.h> +#include <__type_traits/is_nothrow_constructible.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__ranges/access.h b/libcxx/include/__ranges/access.h index 263fdd637fd965a4cf9a192570915fc127b7c803..3db4f11b40f2d072327a98e421baa47576f9de60 100644 --- a/libcxx/include/__ranges/access.h +++ b/libcxx/include/__ranges/access.h @@ -41,12 +41,11 @@ concept __can_borrow = is_lvalue_reference_v<_Tp> || enable_borrowed_range<remov namespace ranges { namespace __begin { template <class _Tp> -concept __member_begin = __can_borrow<_Tp> && __workaround_52970<_Tp> && requires(_Tp&& __t) { +concept __member_begin = __can_borrow<_Tp> && requires(_Tp&& __t) { { _LIBCPP_AUTO_CAST(__t.begin()) } -> input_or_output_iterator; }; -void begin(auto&) = delete; -void begin(const auto&) = delete; +void begin() = delete; template <class _Tp> concept __unqualified_begin = @@ -104,13 +103,12 @@ using iterator_t = decltype(ranges::begin(std::declval<_Tp&>())); namespace ranges { namespace __end { template <class _Tp> -concept __member_end = __can_borrow<_Tp> && __workaround_52970<_Tp> && requires(_Tp&& __t) { +concept __member_end = __can_borrow<_Tp> && requires(_Tp&& __t) { typename iterator_t<_Tp>; { _LIBCPP_AUTO_CAST(__t.end()) } -> sentinel_for<iterator_t<_Tp>>; }; -void end(auto&) = delete; -void end(const auto&) = delete; +void end() = delete; template <class _Tp> concept __unqualified_end = diff --git a/libcxx/include/__ranges/as_rvalue_view.h b/libcxx/include/__ranges/as_rvalue_view.h index 295aa94ed9fe40bd5ea4e1d85f2ca30ea9740cda..2fc272e798d6e0a9be5f05c7885315fe2efaebf6 100644 --- a/libcxx/include/__ranges/as_rvalue_view.h +++ b/libcxx/include/__ranges/as_rvalue_view.h @@ -111,18 +111,18 @@ namespace views { namespace __as_rvalue { struct __fn : __range_adaptor_closure<__fn> { template <class _Range> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const - noexcept(noexcept(/**/ as_rvalue_view(std::forward<_Range>(__range)))) - -> decltype(/*--*/ as_rvalue_view(std::forward<_Range>(__range))) { - return /*-------------*/ as_rvalue_view(std::forward<_Range>(__range)); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto + operator()(_Range&& __range) noexcept(noexcept(as_rvalue_view(std::forward<_Range>(__range)))) + -> decltype(/*--------------------------*/ as_rvalue_view(std::forward<_Range>(__range))) { + return /*---------------------------------*/ as_rvalue_view(std::forward<_Range>(__range)); } template <class _Range> requires same_as<range_rvalue_reference_t<_Range>, range_reference_t<_Range>> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const - noexcept(noexcept(/**/ views::all(std::forward<_Range>(__range)))) - -> decltype(/*--*/ views::all(std::forward<_Range>(__range))) { - return /*-------------*/ views::all(std::forward<_Range>(__range)); + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto + operator()(_Range&& __range) noexcept(noexcept(views::all(std::forward<_Range>(__range)))) + -> decltype(/*--------------------------*/ views::all(std::forward<_Range>(__range))) { + return /*---------------------------------*/ views::all(std::forward<_Range>(__range)); } }; } // namespace __as_rvalue diff --git a/libcxx/include/__ranges/data.h b/libcxx/include/__ranges/data.h index 18002bb52cc8ce9c7cfae9dd115521cfcd0a8a40..131f6cdad8f21c82556d8efc52761777b7d5d3c6 100644 --- a/libcxx/include/__ranges/data.h +++ b/libcxx/include/__ranges/data.h @@ -40,7 +40,7 @@ template <class _Tp> concept __ptr_to_object = is_pointer_v<_Tp> && is_object_v<remove_pointer_t<_Tp>>; template <class _Tp> -concept __member_data = __can_borrow<_Tp> && __workaround_52970<_Tp> && requires(_Tp&& __t) { +concept __member_data = __can_borrow<_Tp> && requires(_Tp&& __t) { { _LIBCPP_AUTO_CAST(__t.data()) } -> __ptr_to_object; }; diff --git a/libcxx/include/__ranges/empty.h b/libcxx/include/__ranges/empty.h index acd55dae224ce737a199026749fabf6bdcd079e2..5c1004042aba5165cd1b94f5879ee3d54603c5b0 100644 --- a/libcxx/include/__ranges/empty.h +++ b/libcxx/include/__ranges/empty.h @@ -29,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __empty { template <class _Tp> -concept __member_empty = __workaround_52970<_Tp> && requires(_Tp&& __t) { bool(__t.empty()); }; +concept __member_empty = requires(_Tp&& __t) { bool(__t.empty()); }; template <class _Tp> concept __can_invoke_size = !__member_empty<_Tp> && requires(_Tp&& __t) { ranges::size(__t); }; diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h index c8314dd848b4473a6f69c746bb43ccac1b979638..9e6f724241ccf1e91661d828a7e2cd48be0f58e2 100644 --- a/libcxx/include/__ranges/iota_view.h +++ b/libcxx/include/__ranges/iota_view.h @@ -31,7 +31,7 @@ #include <__ranges/movable_box.h> #include <__ranges/view_interface.h> #include <__type_traits/conditional.h> -#include <__type_traits/is_nothrow_copy_constructible.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/make_unsigned.h> #include <__type_traits/type_identity.h> #include <__utility/forward.h> diff --git a/libcxx/include/__ranges/movable_box.h b/libcxx/include/__ranges/movable_box.h index 9b38877494eaa456c694de9d4dd3edebc31e659e..5a456cc3a1b66489b2665a8659b6db496ca6f0ba 100644 --- a/libcxx/include/__ranges/movable_box.h +++ b/libcxx/include/__ranges/movable_box.h @@ -17,8 +17,6 @@ #include <__memory/addressof.h> #include <__memory/construct_at.h> #include <__type_traits/is_nothrow_constructible.h> -#include <__type_traits/is_nothrow_copy_constructible.h> -#include <__type_traits/is_nothrow_default_constructible.h> #include <__utility/move.h> #include <optional> diff --git a/libcxx/include/__ranges/rbegin.h b/libcxx/include/__ranges/rbegin.h index 7111201ae7d6bb8670ce9cc58b4855d5bf45ad88..12e739e1a2b852436a7b320523e85f425ef07f97 100644 --- a/libcxx/include/__ranges/rbegin.h +++ b/libcxx/include/__ranges/rbegin.h @@ -36,12 +36,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __rbegin { template <class _Tp> -concept __member_rbegin = __can_borrow<_Tp> && __workaround_52970<_Tp> && requires(_Tp&& __t) { +concept __member_rbegin = __can_borrow<_Tp> && requires(_Tp&& __t) { { _LIBCPP_AUTO_CAST(__t.rbegin()) } -> input_or_output_iterator; }; -void rbegin(auto&) = delete; -void rbegin(const auto&) = delete; +void rbegin() = delete; template <class _Tp> concept __unqualified_rbegin = diff --git a/libcxx/include/__ranges/rend.h b/libcxx/include/__ranges/rend.h index 58d98aafd264b836fc62a40533d0e6b30b57b7a0..5edbc4e3160c5fb14611ad44a026a2ca14495a64 100644 --- a/libcxx/include/__ranges/rend.h +++ b/libcxx/include/__ranges/rend.h @@ -37,13 +37,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { namespace __rend { template <class _Tp> -concept __member_rend = __can_borrow<_Tp> && __workaround_52970<_Tp> && requires(_Tp&& __t) { +concept __member_rend = __can_borrow<_Tp> && requires(_Tp&& __t) { ranges::rbegin(__t); { _LIBCPP_AUTO_CAST(__t.rend()) } -> sentinel_for<decltype(ranges::rbegin(__t))>; }; -void rend(auto&) = delete; -void rend(const auto&) = delete; +void rend() = delete; template <class _Tp> concept __unqualified_rend = diff --git a/libcxx/include/__ranges/repeat_view.h b/libcxx/include/__ranges/repeat_view.h index 620a264549728582bbf8d2c00702e2aaca534cb2..5caea757a393141263f95ba0ecdf56cbd657ca26 100644 --- a/libcxx/include/__ranges/repeat_view.h +++ b/libcxx/include/__ranges/repeat_view.h @@ -229,14 +229,13 @@ namespace views { namespace __repeat { struct __fn { template <class _Tp> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __value) const + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Tp&& __value) noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value)))) -> decltype( ranges::repeat_view(std::forward<_Tp>(__value))) { return ranges::repeat_view(std::forward<_Tp>(__value)); } - template <class _Tp, class _Bound> - _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __value, _Bound&& __bound_sentinel) const + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Tp&& __value, _Bound&& __bound_sentinel) noexcept(noexcept(ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)))) -> decltype( ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel))) { return ranges::repeat_view(std::forward<_Tp>(__value), std::forward<_Bound>(__bound_sentinel)); } diff --git a/libcxx/include/__ranges/size.h b/libcxx/include/__ranges/size.h index 14e21aae6bf1d568537f48186930fd3847dd2752..40b0c6b6aad7a332403eb8e72717ef486edfc3ea 100644 --- a/libcxx/include/__ranges/size.h +++ b/libcxx/include/__ranges/size.h @@ -41,14 +41,13 @@ inline constexpr bool disable_sized_range = false; namespace ranges { namespace __size { -void size(auto&) = delete; -void size(const auto&) = delete; +void size() = delete; template <class _Tp> concept __size_enabled = !disable_sized_range<remove_cvref_t<_Tp>>; template <class _Tp> -concept __member_size = __size_enabled<_Tp> && __workaround_52970<_Tp> && requires(_Tp&& __t) { +concept __member_size = __size_enabled<_Tp> && requires(_Tp&& __t) { { _LIBCPP_AUTO_CAST(__t.size()) } -> __integer_like; }; diff --git a/libcxx/include/__ranges/subrange.h b/libcxx/include/__ranges/subrange.h index bb4411cf35549788d337dcea5ee641eee67b52e0..051bc3113901438480059d17abc414a9b1d2af24 100644 --- a/libcxx/include/__ranges/subrange.h +++ b/libcxx/include/__ranges/subrange.h @@ -28,8 +28,8 @@ #include <__ranges/enable_borrowed_range.h> #include <__ranges/size.h> #include <__ranges/view_interface.h> -#include <__tuple/pair_like.h> #include <__tuple/tuple_element.h> +#include <__tuple/tuple_like_no_subrange.h> #include <__tuple/tuple_size.h> #include <__type_traits/conditional.h> #include <__type_traits/decay.h> @@ -64,7 +64,7 @@ concept __convertible_to_non_slicing = template <class _Pair, class _Iter, class _Sent> concept __pair_like_convertible_from = - !range<_Pair> && __pair_like<_Pair> && constructible_from<_Pair, _Iter, _Sent> && + !range<_Pair> && __pair_like_no_subrange<_Pair> && constructible_from<_Pair, _Iter, _Sent> && __convertible_to_non_slicing<_Iter, tuple_element_t<0, _Pair>> && convertible_to<_Sent, tuple_element_t<1, _Pair>>; template <input_or_output_iterator _Iter, @@ -125,8 +125,7 @@ public: requires(_Kind == subrange_kind::sized) : subrange(ranges::begin(__range), ranges::end(__range), __n) {} - template <__different_from<subrange> _Pair> - requires __pair_like_convertible_from<_Pair, const _Iter&, const _Sent&> + template <__pair_like_convertible_from<const _Iter&, const _Sent&> _Pair> _LIBCPP_HIDE_FROM_ABI constexpr operator _Pair() const { return _Pair(__begin_, __end_); } diff --git a/libcxx/include/__ranges/to.h b/libcxx/include/__ranges/to.h index cf162100ee46b72426f5e9ee7c8d76f9c57bd844..67818c521b150006f48b8223c9507da6f3106156 100644 --- a/libcxx/include/__ranges/to.h +++ b/libcxx/include/__ranges/to.h @@ -207,7 +207,7 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto to(_Args&&... __args) static_assert( !is_volatile_v<_Container>, "The target container cannot be volatile-qualified, please remove the volatile"); - auto __to_func = []<input_range _Range, class... _Tail>(_Range&& __range, _Tail&&... __tail) + auto __to_func = []<input_range _Range, class... _Tail>(_Range&& __range, _Tail&&... __tail) static requires requires { // /**/ ranges::to<_Container>(std::forward<_Range>(__range), std::forward<_Tail>(__tail)...); } @@ -223,7 +223,7 @@ _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr auto to(_Args&&... __args) // clang-format off auto __to_func = []<input_range _Range, class... _Tail, class _DeducedExpr = typename _Deducer<_Container, _Range, _Tail...>::type> - (_Range&& __range, _Tail&& ... __tail) + (_Range&& __range, _Tail&& ... __tail) static requires requires { // /**/ ranges::to<_DeducedExpr>(std::forward<_Range>(__range), std::forward<_Tail>(__tail)...); } diff --git a/libcxx/include/__ranges/view_interface.h b/libcxx/include/__ranges/view_interface.h index 84dd1c316de379c509d5d9974ec51ae847fce6cf..3bcfbaf3a2f9ed6b2eff938c4b527f84a61ef666 100644 --- a/libcxx/include/__ranges/view_interface.h +++ b/libcxx/include/__ranges/view_interface.h @@ -21,6 +21,7 @@ #include <__ranges/access.h> #include <__ranges/concepts.h> #include <__ranges/empty.h> +#include <__ranges/size.h> #include <__type_traits/is_class.h> #include <__type_traits/make_unsigned.h> #include <__type_traits/remove_cv.h> @@ -51,16 +52,24 @@ class view_interface { public: template <class _D2 = _Derived> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() - requires forward_range<_D2> + requires sized_range<_D2> || forward_range<_D2> { - return ranges::begin(__derived()) == ranges::end(__derived()); + if constexpr (sized_range<_D2>) { + return ranges::size(__derived()) == 0; + } else { + return ranges::begin(__derived()) == ranges::end(__derived()); + } } template <class _D2 = _Derived> [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const - requires forward_range<const _D2> + requires sized_range<const _D2> || forward_range<const _D2> { - return ranges::begin(__derived()) == ranges::end(__derived()); + if constexpr (sized_range<const _D2>) { + return ranges::size(__derived()) == 0; + } else { + return ranges::begin(__derived()) == ranges::end(__derived()); + } } template <class _D2 = _Derived> diff --git a/libcxx/include/__ranges/zip_view.h b/libcxx/include/__ranges/zip_view.h index 4898c0afc87a6e74fcf8f5d9c7219fa5874ea91c..fe3c87a9306fe9fde38c6c8dea2149dbddb29e92 100644 --- a/libcxx/include/__ranges/zip_view.h +++ b/libcxx/include/__ranges/zip_view.h @@ -30,12 +30,13 @@ #include <__ranges/enable_borrowed_range.h> #include <__ranges/size.h> #include <__ranges/view_interface.h> -#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/make_unsigned.h> #include <__utility/declval.h> #include <__utility/forward.h> #include <__utility/integer_sequence.h> #include <__utility/move.h> +#include <__utility/pair.h> #include <tuple> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -489,12 +490,12 @@ namespace views { namespace __zip { struct __fn { - _LIBCPP_HIDE_FROM_ABI constexpr auto operator()() const noexcept { return empty_view<tuple<>>{}; } + _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()() noexcept { return empty_view<tuple<>>{}; } template <class... _Ranges> - _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Ranges&&... __rs) const - noexcept(noexcept(zip_view<all_t<_Ranges&&>...>(std::forward<_Ranges>(__rs)...))) - -> decltype(zip_view<all_t<_Ranges&&>...>(std::forward<_Ranges>(__rs)...)) { + _LIBCPP_HIDE_FROM_ABI static constexpr auto + operator()(_Ranges&&... __rs) noexcept(noexcept(zip_view<all_t<_Ranges&&>...>(std::forward<_Ranges>(__rs)...))) + -> decltype(zip_view<all_t<_Ranges&&>...>(std::forward<_Ranges>(__rs)...)) { return zip_view<all_t<_Ranges>...>(std::forward<_Ranges>(__rs)...); } }; diff --git a/libcxx/include/__split_buffer b/libcxx/include/__split_buffer index aaf955685d2d391787fab032e91e458293a96a44..c68349e0979c93737285bec3f7244dc324e3267f 100644 --- a/libcxx/include/__split_buffer +++ b/libcxx/include/__split_buffer @@ -26,9 +26,8 @@ #include <__type_traits/add_lvalue_reference.h> #include <__type_traits/enable_if.h> #include <__type_traits/integral_constant.h> -#include <__type_traits/is_nothrow_default_constructible.h> -#include <__type_traits/is_nothrow_move_assignable.h> -#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_nothrow_assignable.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_swappable.h> #include <__type_traits/is_trivially_destructible.h> #include <__type_traits/remove_reference.h> diff --git a/libcxx/include/__string/char_traits.h b/libcxx/include/__string/char_traits.h index 5880d3a22db2e7dcc2420ac05b67e2fa1bbc7b56..47ed1057caaab17d1b9cab7d93ae1d3bc95d8563 100644 --- a/libcxx/include/__string/char_traits.h +++ b/libcxx/include/__string/char_traits.h @@ -9,7 +9,6 @@ #ifndef _LIBCPP___STRING_CHAR_TRAITS_H #define _LIBCPP___STRING_CHAR_TRAITS_H -#include <__algorithm/copy_n.h> #include <__algorithm/fill_n.h> #include <__algorithm/find_end.h> #include <__algorithm/find_first_of.h> @@ -144,7 +143,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char> { copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2), "char_traits::copy: source and destination ranges overlap"); - std::copy_n(__s2, __n, __s1); + std::__constexpr_memmove(__s1, __s2, __element_count(__n)); return __s1; } @@ -221,7 +220,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t> { copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2), "char_traits::copy: source and destination ranges overlap"); - std::copy_n(__s2, __n, __s1); + std::__constexpr_memmove(__s1, __s2, __element_count(__n)); return __s1; } @@ -287,7 +286,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t> { copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2), "char_traits::copy: source and destination ranges overlap"); - std::copy_n(__s2, __n, __s1); + std::__constexpr_memmove(__s1, __s2, __element_count(__n)); return __s1; } @@ -366,7 +365,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t> { copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2), "char_traits::copy: source and destination ranges overlap"); - std::copy_n(__s2, __n, __s1); + std::__constexpr_memmove(__s1, __s2, __element_count(__n)); return __s1; } @@ -454,7 +453,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t> { _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { - std::copy_n(__s2, __n, __s1); + std::__constexpr_memmove(__s1, __s2, __element_count(__n)); return __s1; } diff --git a/libcxx/include/__system_error/errc.h b/libcxx/include/__system_error/errc.h index f87df86a71e15ab738b213c1bc1115a9a8995456..e9f3656b7b9c2b7c628d63e922812d2c517462a7 100644 --- a/libcxx/include/__system_error/errc.h +++ b/libcxx/include/__system_error/errc.h @@ -58,18 +58,18 @@ enum class errc no_child_process, // ECHILD no_link, // ENOLINK no_lock_available, // ENOLCK - no_message_available, // ENODATA + no_message_available, // ENODATA // deprecated no_message, // ENOMSG no_protocol_option, // ENOPROTOOPT no_space_on_device, // ENOSPC - no_stream_resources, // ENOSR + no_stream_resources, // ENOSR // deprecated no_such_device_or_address, // ENXIO no_such_device, // ENODEV no_such_file_or_directory, // ENOENT no_such_process, // ESRCH not_a_directory, // ENOTDIR not_a_socket, // ENOTSOCK - not_a_stream, // ENOSTR + not_a_stream, // ENOSTR // deprecated not_connected, // ENOTCONN not_enough_memory, // ENOMEM not_supported, // ENOTSUP @@ -87,7 +87,7 @@ enum class errc resource_unavailable_try_again, // EAGAIN result_out_of_range, // ERANGE state_not_recoverable, // ENOTRECOVERABLE - stream_timeout, // ETIME + stream_timeout, // ETIME // deprecated text_file_busy, // ETXTBSY timed_out, // ETIMEDOUT too_many_files_open_in_system, // ENFILE @@ -107,12 +107,34 @@ enum class errc # pragma GCC system_header #endif +// The method of pushing and popping the diagnostics fails for GCC. GCC does +// not recognize the pragma's used to generate deprecated diagnostics for +// macros. So GCC does not need the pushing and popping. +// +// TODO Remove this when the deprecated constants are removed. +#if defined(_LIBCPP_COMPILER_CLANG_BASED) +# define _LIBCPP_SUPPRESS_DEPRECATED_ERRC_PUSH _LIBCPP_SUPPRESS_DEPRECATED_PUSH +# define _LIBCPP_SUPPRESS_DEPRECATED_ERRC_POP _LIBCPP_SUPPRESS_DEPRECATED_POP +#else +# define _LIBCPP_SUPPRESS_DEPRECATED_ERRC_PUSH +# define _LIBCPP_SUPPRESS_DEPRECATED_ERRC_POP +#endif + _LIBCPP_BEGIN_NAMESPACE_STD // Some error codes are not present on all platforms, so we provide equivalents // for them: // enum class errc +// +// LWG3869 deprecates the UNIX STREAMS macros and enum values. +// This makes the code clumbersome: +// - the enum value is deprecated and should show a diagnostic, +// - the macro is deprecated and should _not_ show a diagnostic in this +// context, and +// - the macro is not always available. +// This leads to the odd pushing and popping of the deprecated +// diagnostic. _LIBCPP_DECLARE_STRONG_ENUM(errc){ address_family_not_supported = EAFNOSUPPORT, address_in_use = EADDRINUSE, @@ -154,30 +176,48 @@ _LIBCPP_DECLARE_STRONG_ENUM(errc){ no_child_process = ECHILD, no_link = ENOLINK, no_lock_available = ENOLCK, + // clang-format off + no_message_available _LIBCPP_DEPRECATED = + _LIBCPP_SUPPRESS_DEPRECATED_ERRC_PUSH #ifdef ENODATA - no_message_available = ENODATA, + ENODATA #else - no_message_available = ENOMSG, + ENOMSG #endif + _LIBCPP_SUPPRESS_DEPRECATED_ERRC_POP + , + // clang-format on no_message = ENOMSG, no_protocol_option = ENOPROTOOPT, no_space_on_device = ENOSPC, + // clang-format off + no_stream_resources _LIBCPP_DEPRECATED = + _LIBCPP_SUPPRESS_DEPRECATED_ERRC_PUSH #ifdef ENOSR - no_stream_resources = ENOSR, + ENOSR #else - no_stream_resources = ENOMEM, + ENOMEM #endif + _LIBCPP_SUPPRESS_DEPRECATED_ERRC_POP + , + // clang-format on no_such_device_or_address = ENXIO, no_such_device = ENODEV, no_such_file_or_directory = ENOENT, no_such_process = ESRCH, not_a_directory = ENOTDIR, not_a_socket = ENOTSOCK, + // clang-format off + not_a_stream _LIBCPP_DEPRECATED = + _LIBCPP_SUPPRESS_DEPRECATED_ERRC_PUSH #ifdef ENOSTR - not_a_stream = ENOSTR, + ENOSTR #else - not_a_stream = EINVAL, + EINVAL #endif + _LIBCPP_SUPPRESS_DEPRECATED_ERRC_POP + , + // clang-format on not_connected = ENOTCONN, not_enough_memory = ENOMEM, not_supported = ENOTSUP, @@ -195,11 +235,17 @@ _LIBCPP_DECLARE_STRONG_ENUM(errc){ resource_unavailable_try_again = EAGAIN, result_out_of_range = ERANGE, state_not_recoverable = ENOTRECOVERABLE, + // clang-format off + stream_timeout _LIBCPP_DEPRECATED = + _LIBCPP_SUPPRESS_DEPRECATED_ERRC_PUSH #ifdef ETIME - stream_timeout = ETIME, + ETIME #else - stream_timeout = ETIMEDOUT, + ETIMEDOUT #endif + _LIBCPP_SUPPRESS_DEPRECATED_ERRC_POP + , + // clang-format on text_file_busy = ETXTBSY, timed_out = ETIMEDOUT, too_many_files_open_in_system = ENFILE, diff --git a/libcxx/include/__thread/support/pthread.h b/libcxx/include/__thread/support/pthread.h index e194e5c68ad339e431aa94a773dd17bbf17360f0..531f3e71de8397a3da72fab8725f56e630455de4 100644 --- a/libcxx/include/__thread/support/pthread.h +++ b/libcxx/include/__thread/support/pthread.h @@ -10,7 +10,6 @@ #ifndef _LIBCPP___THREAD_SUPPORT_PTHREAD_H #define _LIBCPP___THREAD_SUPPORT_PTHREAD_H -#include <__availability> #include <__chrono/convert_to_timespec.h> #include <__chrono/duration.h> #include <__config> diff --git a/libcxx/include/__tree b/libcxx/include/__tree index 0d727ad5c9a72aea4212fddc4f515d4961f469db..5a0d8f42a69ceb628a0f0d1095b8d213df3579a7 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -26,11 +26,9 @@ #include <__type_traits/can_extract_key.h> #include <__type_traits/conditional.h> #include <__type_traits/is_const.h> -#include <__type_traits/is_copy_constructible.h> -#include <__type_traits/is_nothrow_copy_constructible.h> -#include <__type_traits/is_nothrow_default_constructible.h> -#include <__type_traits/is_nothrow_move_assignable.h> -#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_nothrow_assignable.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_pointer.h> #include <__type_traits/is_same.h> #include <__type_traits/is_swappable.h> diff --git a/libcxx/include/__tuple/sfinae_helpers.h b/libcxx/include/__tuple/sfinae_helpers.h index 90e9b1e5800478eca42a193ef68471d4eeabc797..35a57ff7765923c212f22ac0eb22bb5d77599bed 100644 --- a/libcxx/include/__tuple/sfinae_helpers.h +++ b/libcxx/include/__tuple/sfinae_helpers.h @@ -16,6 +16,7 @@ #include <__tuple/tuple_like_ext.h> #include <__tuple/tuple_size.h> #include <__tuple/tuple_types.h> +#include <__type_traits/conjunction.h> #include <__type_traits/enable_if.h> #include <__type_traits/integral_constant.h> #include <__type_traits/is_constructible.h> @@ -32,12 +33,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD #ifndef _LIBCPP_CXX03_LANG -template <bool... _Preds> -struct __all_dummy; - -template <bool... _Pred> -struct __all : _IsSame<__all_dummy<_Pred...>, __all_dummy<((void)_Pred, true)...>> {}; - struct __tuple_sfinae_base { template <template <class, class...> class _Trait, class... _LArgs, class... _RArgs> static auto __do_test(__tuple_types<_LArgs...>, __tuple_types<_RArgs...>) diff --git a/libcxx/include/__tuple/tuple_element.h b/libcxx/include/__tuple/tuple_element.h index 2b9ac6696ca412329026e82c303a94f4e092b1ec..55b3b47619f648d274cb758e8c246fa184a11522 100644 --- a/libcxx/include/__tuple/tuple_element.h +++ b/libcxx/include/__tuple/tuple_element.h @@ -12,9 +12,6 @@ #include <__config> #include <__tuple/tuple_indices.h> #include <__tuple/tuple_types.h> -#include <__type_traits/add_const.h> -#include <__type_traits/add_cv.h> -#include <__type_traits/add_volatile.h> #include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -28,17 +25,17 @@ struct _LIBCPP_TEMPLATE_VIS tuple_element; template <size_t _Ip, class _Tp> struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, const _Tp> { - typedef _LIBCPP_NODEBUG typename add_const<typename tuple_element<_Ip, _Tp>::type>::type type; + typedef _LIBCPP_NODEBUG const typename tuple_element<_Ip, _Tp>::type type; }; template <size_t _Ip, class _Tp> struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, volatile _Tp> { - typedef _LIBCPP_NODEBUG typename add_volatile<typename tuple_element<_Ip, _Tp>::type>::type type; + typedef _LIBCPP_NODEBUG volatile typename tuple_element<_Ip, _Tp>::type type; }; template <size_t _Ip, class _Tp> struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, const volatile _Tp> { - typedef _LIBCPP_NODEBUG typename add_cv<typename tuple_element<_Ip, _Tp>::type>::type type; + typedef _LIBCPP_NODEBUG const volatile typename tuple_element<_Ip, _Tp>::type type; }; #ifndef _LIBCPP_CXX03_LANG diff --git a/libcxx/include/__tuple/tuple_like.h b/libcxx/include/__tuple/tuple_like.h index 967e4a543c0318fbf0d22717969f9b586601a59b..c080a3dcf1e258a29d3b4a7c9293b12ca1642da3 100644 --- a/libcxx/include/__tuple/tuple_like.h +++ b/libcxx/include/__tuple/tuple_like.h @@ -10,12 +10,9 @@ #define _LIBCPP___TUPLE_TUPLE_LIKE_H #include <__config> -#include <__fwd/array.h> -#include <__fwd/complex.h> -#include <__fwd/pair.h> #include <__fwd/subrange.h> -#include <__fwd/tuple.h> -#include <__type_traits/integral_constant.h> +#include <__tuple/tuple_like_no_subrange.h> +#include <__tuple/tuple_size.h> #include <__type_traits/remove_cvref.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -27,29 +24,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template <class _Tp> -struct __tuple_like_impl : false_type {}; +inline constexpr bool __is_ranges_subrange_v = false; -template <class... _Tp> -struct __tuple_like_impl<tuple<_Tp...> > : true_type {}; - -template <class _T1, class _T2> -struct __tuple_like_impl<pair<_T1, _T2> > : true_type {}; - -template <class _Tp, size_t _Size> -struct __tuple_like_impl<array<_Tp, _Size> > : true_type {}; - -template <class _Ip, class _Sp, ranges::subrange_kind _Kp> -struct __tuple_like_impl<ranges::subrange<_Ip, _Sp, _Kp> > : true_type {}; - -# if _LIBCPP_STD_VER >= 26 +template <class _Iter, class _Sent, ranges::subrange_kind _Kind> +inline constexpr bool __is_ranges_subrange_v<ranges::subrange<_Iter, _Sent, _Kind>> = true; template <class _Tp> -struct __tuple_like_impl<complex<_Tp>> : true_type {}; - -# endif +concept __tuple_like = __tuple_like_no_subrange<_Tp> || __is_ranges_subrange_v<remove_cvref_t<_Tp>>; -template <class _Tp> -concept __tuple_like = __tuple_like_impl<remove_cvref_t<_Tp>>::value; +// As of writing this comment every use of `pair-like` in the standard excludes `ranges::subrange`, so +// you most likely want to use `__pair_like_no_subrange` if you're looking for `pair-like`. #endif // _LIBCPP_STD_VER >= 20 diff --git a/libcxx/include/__tuple/tuple_like_no_subrange.h b/libcxx/include/__tuple/tuple_like_no_subrange.h new file mode 100644 index 0000000000000000000000000000000000000000..274b0bf188e1f492c48bd06c3bb39f33f821d465 --- /dev/null +++ b/libcxx/include/__tuple/tuple_like_no_subrange.h @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// 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___TUPLE_TUPLE_LIKE_NO_SUBRANGE_H +#define _LIBCPP___TUPLE_TUPLE_LIKE_NO_SUBRANGE_H + +#include <__config> +#include <__fwd/array.h> +#include <__fwd/complex.h> +#include <__fwd/pair.h> +#include <__fwd/tuple.h> +#include <__tuple/tuple_size.h> +#include <__type_traits/remove_cvref.h> +#include <cstddef> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +template <class _Tp> +inline constexpr bool __tuple_like_no_subrange_impl = false; + +template <class... _Tp> +inline constexpr bool __tuple_like_no_subrange_impl<tuple<_Tp...>> = true; + +template <class _T1, class _T2> +inline constexpr bool __tuple_like_no_subrange_impl<pair<_T1, _T2>> = true; + +template <class _Tp, size_t _Size> +inline constexpr bool __tuple_like_no_subrange_impl<array<_Tp, _Size>> = true; + +# if _LIBCPP_STD_VER >= 26 + +template <class _Tp> +inline constexpr bool __tuple_like_no_subrange_impl<complex<_Tp>> = true; + +# endif + +template <class _Tp> +concept __tuple_like_no_subrange = __tuple_like_no_subrange_impl<remove_cvref_t<_Tp>>; + +// This is equivalent to the exposition-only type trait `pair-like`, except that it is false for specializations of +// `ranges::subrange`. This is more useful than the pair-like concept in the standard because every use of `pair-like` +// excludes `ranges::subrange`. +template <class _Tp> +concept __pair_like_no_subrange = __tuple_like_no_subrange<_Tp> && tuple_size<remove_cvref_t<_Tp>>::value == 2; + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___TUPLE_TUPLE_LIKE_NO_SUBRANGE_H diff --git a/libcxx/include/__tuple/tuple_size.h b/libcxx/include/__tuple/tuple_size.h index b8320106fb26941058c3c4a5c44e8e1fb95f880d..668be13a5c841fa64ba3d03f44587cdcc0a3f322 100644 --- a/libcxx/include/__tuple/tuple_size.h +++ b/libcxx/include/__tuple/tuple_size.h @@ -43,7 +43,7 @@ struct _LIBCPP_TEMPLATE_VIS tuple_size<__enable_if_tuple_size_imp< volatile _Tp, template <class _Tp> struct _LIBCPP_TEMPLATE_VIS - tuple_size<__enable_if_tuple_size_imp< const volatile _Tp, integral_constant<size_t, sizeof(tuple_size<_Tp>)>>> + tuple_size<__enable_if_tuple_size_imp<const volatile _Tp, integral_constant<size_t, sizeof(tuple_size<_Tp>)>>> : public integral_constant<size_t, tuple_size<_Tp>::value> {}; #else @@ -63,6 +63,11 @@ struct _LIBCPP_TEMPLATE_VIS tuple_size<tuple<_Tp...> > : public integral_constan template <class... _Tp> struct _LIBCPP_TEMPLATE_VIS tuple_size<__tuple_types<_Tp...> > : public integral_constant<size_t, sizeof...(_Tp)> {}; +# if _LIBCPP_STD_VER >= 17 +template <class _Tp> +inline constexpr size_t tuple_size_v = tuple_size<_Tp>::value; +# endif + #endif // _LIBCPP_CXX03_LANG _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/apply_cv.h b/libcxx/include/__type_traits/apply_cv.h index 7c6aabec8344b19f0d602ca0220e8a98d584c675..723af95b8d9280cf4eef2e64c80487f204044ca7 100644 --- a/libcxx/include/__type_traits/apply_cv.h +++ b/libcxx/include/__type_traits/apply_cv.h @@ -10,9 +10,7 @@ #define _LIBCPP___TYPE_TRAITS_APPLY_CV_H #include <__config> -#include <__type_traits/is_const.h> -#include <__type_traits/is_volatile.h> -#include <__type_traits/remove_reference.h> +#include <__type_traits/copy_cv.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -20,54 +18,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp, - bool = is_const<__libcpp_remove_reference_t<_Tp> >::value, - bool = is_volatile<__libcpp_remove_reference_t<_Tp> >::value> -struct __apply_cv_impl { - template <class _Up> - using __apply _LIBCPP_NODEBUG = _Up; -}; - template <class _Tp> -struct __apply_cv_impl<_Tp, true, false> { - template <class _Up> - using __apply _LIBCPP_NODEBUG = const _Up; -}; - -template <class _Tp> -struct __apply_cv_impl<_Tp, false, true> { - template <class _Up> - using __apply _LIBCPP_NODEBUG = volatile _Up; -}; - -template <class _Tp> -struct __apply_cv_impl<_Tp, true, true> { - template <class _Up> - using __apply _LIBCPP_NODEBUG = const volatile _Up; -}; - -template <class _Tp> -struct __apply_cv_impl<_Tp&, false, false> { - template <class _Up> - using __apply _LIBCPP_NODEBUG = _Up&; -}; - -template <class _Tp> -struct __apply_cv_impl<_Tp&, true, false> { - template <class _Up> - using __apply _LIBCPP_NODEBUG = const _Up&; -}; - -template <class _Tp> -struct __apply_cv_impl<_Tp&, false, true> { +struct __apply_cv_impl { template <class _Up> - using __apply _LIBCPP_NODEBUG = volatile _Up&; + using __apply _LIBCPP_NODEBUG = __copy_cv_t<_Tp, _Up>; }; template <class _Tp> -struct __apply_cv_impl<_Tp&, true, true> { +struct __apply_cv_impl<_Tp&> { template <class _Up> - using __apply _LIBCPP_NODEBUG = const volatile _Up&; + using __apply _LIBCPP_NODEBUG = __copy_cv_t<_Tp, _Up>&; }; template <class _Tp, class _Up> diff --git a/libcxx/include/__type_traits/conjunction.h b/libcxx/include/__type_traits/conjunction.h index 4bfa5a27300d1e1930433feca1312facab342b40..c2995591bbc28f0503e13f94d6a442edc790f0dd 100644 --- a/libcxx/include/__type_traits/conjunction.h +++ b/libcxx/include/__type_traits/conjunction.h @@ -13,6 +13,7 @@ #include <__type_traits/conditional.h> #include <__type_traits/enable_if.h> #include <__type_traits/integral_constant.h> +#include <__type_traits/is_same.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -37,6 +38,12 @@ false_type __and_helper(...); template <class... _Pred> using _And _LIBCPP_NODEBUG = decltype(std::__and_helper<_Pred...>(0)); +template <bool... _Preds> +struct __all_dummy; + +template <bool... _Pred> +struct __all : _IsSame<__all_dummy<_Pred...>, __all_dummy<((void)_Pred, true)...> > {}; + #if _LIBCPP_STD_VER >= 17 template <class...> diff --git a/libcxx/include/__type_traits/copy_cv.h b/libcxx/include/__type_traits/copy_cv.h index 3c4ee857f7bc7a008a637daa4a3eba6cf7bb8168..b1c057ff778b1ba039a60b6f785fb02a81498c00 100644 --- a/libcxx/include/__type_traits/copy_cv.h +++ b/libcxx/include/__type_traits/copy_cv.h @@ -10,9 +10,6 @@ #define _LIBCPP___TYPE_TRAITS_COPY_CV_H #include <__config> -#include <__type_traits/add_const.h> -#include <__type_traits/add_cv.h> -#include <__type_traits/add_volatile.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -29,17 +26,17 @@ struct __copy_cv { template <class _From, class _To> struct __copy_cv<const _From, _To> { - using type = typename add_const<_To>::type; + using type = const _To; }; template <class _From, class _To> struct __copy_cv<volatile _From, _To> { - using type = typename add_volatile<_To>::type; + using type = volatile _To; }; template <class _From, class _To> struct __copy_cv<const volatile _From, _To> { - using type = typename add_cv<_To>::type; + using type = const volatile _To; }; template <class _From, class _To> diff --git a/libcxx/include/__type_traits/is_assignable.h b/libcxx/include/__type_traits/is_assignable.h index 11134b1c1abaf981e26ded2680765bf9565d8f08..cfb46997778782a920acac6b21ba66362a5de73f 100644 --- a/libcxx/include/__type_traits/is_assignable.h +++ b/libcxx/include/__type_traits/is_assignable.h @@ -10,6 +10,8 @@ #define _LIBCPP___TYPE_TRAITS_IS_ASSIGNABLE_H #include <__config> +#include <__type_traits/add_lvalue_reference.h> +#include <__type_traits/add_rvalue_reference.h> #include <__type_traits/integral_constant.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -26,6 +28,25 @@ template <class _Tp, class _Arg> inline constexpr bool is_assignable_v = __is_assignable(_Tp, _Arg); #endif +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_copy_assignable + : public integral_constant<bool, + __is_assignable(__add_lvalue_reference_t<_Tp>, __add_lvalue_reference_t<const _Tp>)> {}; + +#if _LIBCPP_STD_VER >= 17 +template <class _Tp> +inline constexpr bool is_copy_assignable_v = is_copy_assignable<_Tp>::value; +#endif + +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_move_assignable + : public integral_constant<bool, __is_assignable(__add_lvalue_reference_t<_Tp>, __add_rvalue_reference_t<_Tp>)> {}; + +#if _LIBCPP_STD_VER >= 17 +template <class _Tp> +inline constexpr bool is_move_assignable_v = is_move_assignable<_Tp>::value; +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___TYPE_TRAITS_IS_ASSIGNABLE_H diff --git a/libcxx/include/__type_traits/is_constructible.h b/libcxx/include/__type_traits/is_constructible.h index 4e62eb061fd5931f5a5d039de0619058a2ce8ccc..567bd165c71520221a26161c48a6d6ee54984e7c 100644 --- a/libcxx/include/__type_traits/is_constructible.h +++ b/libcxx/include/__type_traits/is_constructible.h @@ -10,6 +10,8 @@ #define _LIBCPP___TYPE_IS_CONSTRUCTIBLE_H #include <__config> +#include <__type_traits/add_lvalue_reference.h> +#include <__type_traits/add_rvalue_reference.h> #include <__type_traits/integral_constant.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -26,6 +28,32 @@ template <class _Tp, class... _Args> inline constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...); #endif +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_copy_constructible + : public integral_constant<bool, __is_constructible(_Tp, __add_lvalue_reference_t<const _Tp>)> {}; + +#if _LIBCPP_STD_VER >= 17 +template <class _Tp> +inline constexpr bool is_copy_constructible_v = is_copy_constructible<_Tp>::value; +#endif + +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_move_constructible + : public integral_constant<bool, __is_constructible(_Tp, __add_rvalue_reference_t<_Tp>)> {}; + +#if _LIBCPP_STD_VER >= 17 +template <class _Tp> +inline constexpr bool is_move_constructible_v = is_move_constructible<_Tp>::value; +#endif + +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_default_constructible : public integral_constant<bool, __is_constructible(_Tp)> {}; + +#if _LIBCPP_STD_VER >= 17 +template <class _Tp> +inline constexpr bool is_default_constructible_v = __is_constructible(_Tp); +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___TYPE_IS_CONSTRUCTIBLE_H diff --git a/libcxx/include/__type_traits/is_copy_assignable.h b/libcxx/include/__type_traits/is_copy_assignable.h deleted file mode 100644 index e607ace54043726398125dd6641f924c09fbe77c..0000000000000000000000000000000000000000 --- a/libcxx/include/__type_traits/is_copy_assignable.h +++ /dev/null @@ -1,36 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___TYPE_TRAITS_IS_COPY_ASSIGNABLE_H -#define _LIBCPP___TYPE_TRAITS_IS_COPY_ASSIGNABLE_H - -#include <__config> -#include <__type_traits/add_const.h> -#include <__type_traits/add_lvalue_reference.h> -#include <__type_traits/integral_constant.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_copy_assignable - : public integral_constant< - bool, - __is_assignable(__add_lvalue_reference_t<_Tp>, __add_lvalue_reference_t<typename add_const<_Tp>::type>)> {}; - -#if _LIBCPP_STD_VER >= 17 -template <class _Tp> -inline constexpr bool is_copy_assignable_v = is_copy_assignable<_Tp>::value; -#endif - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___TYPE_TRAITS_IS_COPY_ASSIGNABLE_H diff --git a/libcxx/include/__type_traits/is_copy_constructible.h b/libcxx/include/__type_traits/is_copy_constructible.h deleted file mode 100644 index 402f2b89875bbe06fe9ddd2807fadc493bbaafa4..0000000000000000000000000000000000000000 --- a/libcxx/include/__type_traits/is_copy_constructible.h +++ /dev/null @@ -1,35 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___TYPE_TRAITS_IS_COPY_CONSTRUCTIBLE_H -#define _LIBCPP___TYPE_TRAITS_IS_COPY_CONSTRUCTIBLE_H - -#include <__config> -#include <__type_traits/add_const.h> -#include <__type_traits/add_lvalue_reference.h> -#include <__type_traits/integral_constant.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_copy_constructible - : public integral_constant<bool, __is_constructible(_Tp, __add_lvalue_reference_t<typename add_const<_Tp>::type>)> { -}; - -#if _LIBCPP_STD_VER >= 17 -template <class _Tp> -inline constexpr bool is_copy_constructible_v = is_copy_constructible<_Tp>::value; -#endif - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___TYPE_TRAITS_IS_COPY_CONSTRUCTIBLE_H diff --git a/libcxx/include/__type_traits/is_default_constructible.h b/libcxx/include/__type_traits/is_default_constructible.h deleted file mode 100644 index e73e9b98f5dca8ca45c1140f7282d05d30d1ef61..0000000000000000000000000000000000000000 --- a/libcxx/include/__type_traits/is_default_constructible.h +++ /dev/null @@ -1,31 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___TYPE_TRAITS_IS_DEFAULT_CONSTRUCTIBLE_H -#define _LIBCPP___TYPE_TRAITS_IS_DEFAULT_CONSTRUCTIBLE_H - -#include <__config> -#include <__type_traits/integral_constant.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_default_constructible : public integral_constant<bool, __is_constructible(_Tp)> {}; - -#if _LIBCPP_STD_VER >= 17 -template <class _Tp> -inline constexpr bool is_default_constructible_v = __is_constructible(_Tp); -#endif - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___TYPE_TRAITS_IS_DEFAULT_CONSTRUCTIBLE_H diff --git a/libcxx/include/__type_traits/is_implicitly_default_constructible.h b/libcxx/include/__type_traits/is_implicitly_default_constructible.h index 576166e52698a8e769e6d4e79abdc9046cf4dde4..d5dadd7b870dd9465181aa15a79be23028d62983 100644 --- a/libcxx/include/__type_traits/is_implicitly_default_constructible.h +++ b/libcxx/include/__type_traits/is_implicitly_default_constructible.h @@ -11,7 +11,7 @@ #include <__config> #include <__type_traits/integral_constant.h> -#include <__type_traits/is_default_constructible.h> +#include <__type_traits/is_constructible.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__type_traits/is_move_assignable.h b/libcxx/include/__type_traits/is_move_assignable.h deleted file mode 100644 index 867bc00d824ae3f1093f74074c4f8d9cec6d30e6..0000000000000000000000000000000000000000 --- a/libcxx/include/__type_traits/is_move_assignable.h +++ /dev/null @@ -1,34 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___TYPE_TRAITS_IS_MOVE_ASSIGNABLE_H -#define _LIBCPP___TYPE_TRAITS_IS_MOVE_ASSIGNABLE_H - -#include <__config> -#include <__type_traits/add_lvalue_reference.h> -#include <__type_traits/add_rvalue_reference.h> -#include <__type_traits/integral_constant.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_move_assignable - : public integral_constant<bool, __is_assignable(__add_lvalue_reference_t<_Tp>, __add_rvalue_reference_t<_Tp>)> {}; - -#if _LIBCPP_STD_VER >= 17 -template <class _Tp> -inline constexpr bool is_move_assignable_v = is_move_assignable<_Tp>::value; -#endif - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___TYPE_TRAITS_IS_MOVE_ASSIGNABLE_H diff --git a/libcxx/include/__type_traits/is_move_constructible.h b/libcxx/include/__type_traits/is_move_constructible.h deleted file mode 100644 index 40ec4a070816b504c445fcc30ed5cac2f1cf6711..0000000000000000000000000000000000000000 --- a/libcxx/include/__type_traits/is_move_constructible.h +++ /dev/null @@ -1,33 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___TYPE_TRAITS_IS_MOVE_CONSTRUCTIBLE_H -#define _LIBCPP___TYPE_TRAITS_IS_MOVE_CONSTRUCTIBLE_H - -#include <__config> -#include <__type_traits/add_rvalue_reference.h> -#include <__type_traits/integral_constant.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_move_constructible - : public integral_constant<bool, __is_constructible(_Tp, __add_rvalue_reference_t<_Tp>)> {}; - -#if _LIBCPP_STD_VER >= 17 -template <class _Tp> -inline constexpr bool is_move_constructible_v = is_move_constructible<_Tp>::value; -#endif - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___TYPE_TRAITS_IS_MOVE_CONSTRUCTIBLE_H diff --git a/libcxx/include/__type_traits/is_nothrow_assignable.h b/libcxx/include/__type_traits/is_nothrow_assignable.h index cc574933138592f690997bd68bfd9a6a6a242e40..7e00c741f83e3060733e4790e4dec33a668b96de 100644 --- a/libcxx/include/__type_traits/is_nothrow_assignable.h +++ b/libcxx/include/__type_traits/is_nothrow_assignable.h @@ -10,6 +10,8 @@ #define _LIBCPP___TYPE_TRAITS_IS_NOTHROW_ASSIGNABLE_H #include <__config> +#include <__type_traits/add_lvalue_reference.h> +#include <__type_traits/add_rvalue_reference.h> #include <__type_traits/integral_constant.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -27,6 +29,28 @@ template <class _Tp, class _Arg> inline constexpr bool is_nothrow_assignable_v = __is_nothrow_assignable(_Tp, _Arg); #endif +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_nothrow_copy_assignable + : public integral_constant< + bool, + __is_nothrow_assignable(__add_lvalue_reference_t<_Tp>, __add_lvalue_reference_t<const _Tp>)> {}; + +#if _LIBCPP_STD_VER >= 17 +template <class _Tp> +inline constexpr bool is_nothrow_copy_assignable_v = is_nothrow_copy_assignable<_Tp>::value; +#endif + +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_nothrow_move_assignable + : public integral_constant<bool, + __is_nothrow_assignable(__add_lvalue_reference_t<_Tp>, __add_rvalue_reference_t<_Tp>)> { +}; + +#if _LIBCPP_STD_VER >= 17 +template <class _Tp> +inline constexpr bool is_nothrow_move_assignable_v = is_nothrow_move_assignable<_Tp>::value; +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___TYPE_TRAITS_IS_NOTHROW_ASSIGNABLE_H diff --git a/libcxx/include/__type_traits/is_nothrow_constructible.h b/libcxx/include/__type_traits/is_nothrow_constructible.h index f56816b943c4cbc2836bef39982af4886afde1f0..2f7ed8487e76bb09be0f79e3cdeeeb7643cad90b 100644 --- a/libcxx/include/__type_traits/is_nothrow_constructible.h +++ b/libcxx/include/__type_traits/is_nothrow_constructible.h @@ -10,6 +10,8 @@ #define _LIBCPP___TYPE_TRAITS_IS_NOTHROW_CONSTRUCTIBLE_H #include <__config> +#include <__type_traits/add_lvalue_reference.h> +#include <__type_traits/add_rvalue_reference.h> #include <__type_traits/integral_constant.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_reference.h> @@ -66,6 +68,55 @@ template <class _Tp, class... _Args> inline constexpr bool is_nothrow_constructible_v = is_nothrow_constructible<_Tp, _Args...>::value; #endif +// TODO: remove this implementation once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106611 is fixed +#ifdef _LIBCPP_COMPILER_GCC + +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_nothrow_copy_constructible + : public is_nothrow_constructible<_Tp, __add_lvalue_reference_t<const _Tp> > {}; + +#else // _LIBCPP_COMPILER_GCC + +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_nothrow_copy_constructible + : public integral_constant< bool, __is_nothrow_constructible(_Tp, __add_lvalue_reference_t<const _Tp>)> {}; + +#endif // _LIBCPP_COMPILER_GCC + +#if _LIBCPP_STD_VER >= 17 +template <class _Tp> +inline constexpr bool is_nothrow_copy_constructible_v = is_nothrow_copy_constructible<_Tp>::value; +#endif + +// TODO: remove this implementation once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106611 is fixed +#ifndef _LIBCPP_COMPILER_GCC + +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_nothrow_move_constructible + : public integral_constant<bool, __is_nothrow_constructible(_Tp, __add_rvalue_reference_t<_Tp>)> {}; + +#else // _LIBCPP_COMPILER_GCC + +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_nothrow_move_constructible + : public is_nothrow_constructible<_Tp, __add_rvalue_reference_t<_Tp> > {}; + +#endif // _LIBCPP_COMPILER_GCC + +#if _LIBCPP_STD_VER >= 17 +template <class _Tp> +inline constexpr bool is_nothrow_move_constructible_v = is_nothrow_move_constructible<_Tp>::value; +#endif + +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_nothrow_default_constructible + : public integral_constant<bool, __is_nothrow_constructible(_Tp)> {}; + +#if _LIBCPP_STD_VER >= 17 +template <class _Tp> +inline constexpr bool is_nothrow_default_constructible_v = __is_nothrow_constructible(_Tp); +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___TYPE_TRAITS_IS_NOTHROW_CONSTRUCTIBLE_H diff --git a/libcxx/include/__type_traits/is_nothrow_copy_assignable.h b/libcxx/include/__type_traits/is_nothrow_copy_assignable.h deleted file mode 100644 index a97e962b308c8b8a62f41df474bfcf5f7ed23e47..0000000000000000000000000000000000000000 --- a/libcxx/include/__type_traits/is_nothrow_copy_assignable.h +++ /dev/null @@ -1,36 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___TYPE_TRAITS_IS_NOTHROW_COPY_ASSIGNABLE_H -#define _LIBCPP___TYPE_TRAITS_IS_NOTHROW_COPY_ASSIGNABLE_H - -#include <__config> -#include <__type_traits/add_const.h> -#include <__type_traits/add_lvalue_reference.h> -#include <__type_traits/integral_constant.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_nothrow_copy_assignable - : public integral_constant<bool, - __is_nothrow_assignable(__add_lvalue_reference_t<_Tp>, - __add_lvalue_reference_t<typename add_const<_Tp>::type>)> {}; - -#if _LIBCPP_STD_VER >= 17 -template <class _Tp> -inline constexpr bool is_nothrow_copy_assignable_v = is_nothrow_copy_assignable<_Tp>::value; -#endif - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___TYPE_TRAITS_IS_NOTHROW_COPY_ASSIGNABLE_H diff --git a/libcxx/include/__type_traits/is_nothrow_copy_constructible.h b/libcxx/include/__type_traits/is_nothrow_copy_constructible.h deleted file mode 100644 index dd7f1d5ef6276d68ed6a5cd49210b55fb9006890..0000000000000000000000000000000000000000 --- a/libcxx/include/__type_traits/is_nothrow_copy_constructible.h +++ /dev/null @@ -1,48 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___TYPE_TRAITS_IS_NOTHROW_COPY_CONSTRUCTIBLE_H -#define _LIBCPP___TYPE_TRAITS_IS_NOTHROW_COPY_CONSTRUCTIBLE_H - -#include <__config> -#include <__type_traits/add_const.h> -#include <__type_traits/add_lvalue_reference.h> -#include <__type_traits/integral_constant.h> -#include <__type_traits/is_nothrow_constructible.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -// TODO: remove this implementation once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106611 is fixed -#ifdef _LIBCPP_COMPILER_GCC - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_nothrow_copy_constructible - : public is_nothrow_constructible<_Tp, __add_lvalue_reference_t<typename add_const<_Tp>::type> > {}; - -#else // _LIBCPP_COMPILER_GCC - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_nothrow_copy_constructible - : public integral_constant< - bool, - __is_nothrow_constructible(_Tp, typename add_lvalue_reference<typename add_const<_Tp>::type>::type)> {}; - -#endif // _LIBCPP_COMPILER_GCC - -#if _LIBCPP_STD_VER >= 17 -template <class _Tp> -inline constexpr bool is_nothrow_copy_constructible_v = is_nothrow_copy_constructible<_Tp>::value; -#endif - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___TYPE_TRAITS_IS_NOTHROW_COPY_CONSTRUCTIBLE_H diff --git a/libcxx/include/__type_traits/is_nothrow_default_constructible.h b/libcxx/include/__type_traits/is_nothrow_default_constructible.h deleted file mode 100644 index 58f31f21b0267fe0ce863138112399bbb0a374c9..0000000000000000000000000000000000000000 --- a/libcxx/include/__type_traits/is_nothrow_default_constructible.h +++ /dev/null @@ -1,32 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___TYPE_TRAITS_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE_H -#define _LIBCPP___TYPE_TRAITS_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE_H - -#include <__config> -#include <__type_traits/integral_constant.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_nothrow_default_constructible - : public integral_constant<bool, __is_nothrow_constructible(_Tp)> {}; - -#if _LIBCPP_STD_VER >= 17 -template <class _Tp> -inline constexpr bool is_nothrow_default_constructible_v = __is_nothrow_constructible(_Tp); -#endif - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___TYPE_TRAITS_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE_H diff --git a/libcxx/include/__type_traits/is_nothrow_move_assignable.h b/libcxx/include/__type_traits/is_nothrow_move_assignable.h deleted file mode 100644 index aa87e369cd5d0176800efea2e5bcf51967ba9eda..0000000000000000000000000000000000000000 --- a/libcxx/include/__type_traits/is_nothrow_move_assignable.h +++ /dev/null @@ -1,36 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___TYPE_TRAITS_IS_NOTHROW_MOVE_ASSIGNABLE_H -#define _LIBCPP___TYPE_TRAITS_IS_NOTHROW_MOVE_ASSIGNABLE_H - -#include <__config> -#include <__type_traits/add_lvalue_reference.h> -#include <__type_traits/add_rvalue_reference.h> -#include <__type_traits/integral_constant.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_nothrow_move_assignable - : public integral_constant<bool, - __is_nothrow_assignable(__add_lvalue_reference_t<_Tp>, __add_rvalue_reference_t<_Tp>)> { -}; - -#if _LIBCPP_STD_VER >= 17 -template <class _Tp> -inline constexpr bool is_nothrow_move_assignable_v = is_nothrow_move_assignable<_Tp>::value; -#endif - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___TYPE_TRAITS_IS_NOTHROW_MOVE_ASSIGNABLE_H diff --git a/libcxx/include/__type_traits/is_nothrow_move_constructible.h b/libcxx/include/__type_traits/is_nothrow_move_constructible.h deleted file mode 100644 index dab5a019b33bf0c39f0c6b956637c88cd42939c7..0000000000000000000000000000000000000000 --- a/libcxx/include/__type_traits/is_nothrow_move_constructible.h +++ /dev/null @@ -1,45 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___TYPE_TRAITS_IS_NOTHROW_MOVE_CONSTRUCTIBLE_H -#define _LIBCPP___TYPE_TRAITS_IS_NOTHROW_MOVE_CONSTRUCTIBLE_H - -#include <__config> -#include <__type_traits/add_rvalue_reference.h> -#include <__type_traits/integral_constant.h> -#include <__type_traits/is_nothrow_constructible.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -// TODO: remove this implementation once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106611 is fixed -#ifndef _LIBCPP_COMPILER_GCC - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_nothrow_move_constructible - : public integral_constant<bool, __is_nothrow_constructible(_Tp, __add_rvalue_reference_t<_Tp>)> {}; - -#else // _LIBCPP_COMPILER_GCC - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_nothrow_move_constructible - : public is_nothrow_constructible<_Tp, __add_rvalue_reference_t<_Tp> > {}; - -#endif // _LIBCPP_COMPILER_GCC - -#if _LIBCPP_STD_VER >= 17 -template <class _Tp> -inline constexpr bool is_nothrow_move_constructible_v = is_nothrow_move_constructible<_Tp>::value; -#endif - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___TYPE_TRAITS_IS_NOTHROW_MOVE_CONSTRUCTIBLE_H diff --git a/libcxx/include/__type_traits/is_scoped_enum.h b/libcxx/include/__type_traits/is_scoped_enum.h index 43b3a6b66b1f5dc1fa715676417f56e272ec3ba6..1db88e13356e83fd48e33a1b051f814a0e3eafee 100644 --- a/libcxx/include/__type_traits/is_scoped_enum.h +++ b/libcxx/include/__type_traits/is_scoped_enum.h @@ -22,6 +22,18 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 23 + +// TODO: GCC and Clang both have this builtin. Remove the false case once we've updated to GCC 14. +# if __has_builtin(__is_scoped_enum) + +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_scoped_enum : bool_constant<__is_scoped_enum(_Tp)> {}; + +template <class _Tp> +inline constexpr bool is_scoped_enum_v = __is_scoped_enum(_Tp); + +# else + template <class _Tp, bool = is_enum_v<_Tp> > struct __is_scoped_enum_helper : false_type {}; @@ -33,7 +45,10 @@ struct _LIBCPP_TEMPLATE_VIS is_scoped_enum : public __is_scoped_enum_helper<_Tp> template <class _Tp> inline constexpr bool is_scoped_enum_v = is_scoped_enum<_Tp>::value; -#endif + +# endif // __has_builtin(__is_scoped_enum) + +#endif // _LIBCPP_STD_VER >= 23 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__type_traits/is_swappable.h b/libcxx/include/__type_traits/is_swappable.h index 06e092692df3d9bfbecfee21287424f9e64ee056..06b59e5c25d0451e3040444d40421def2bc54d9f 100644 --- a/libcxx/include/__type_traits/is_swappable.h +++ b/libcxx/include/__type_traits/is_swappable.h @@ -13,10 +13,10 @@ #include <__type_traits/add_lvalue_reference.h> #include <__type_traits/conditional.h> #include <__type_traits/enable_if.h> -#include <__type_traits/is_move_assignable.h> -#include <__type_traits/is_move_constructible.h> -#include <__type_traits/is_nothrow_move_assignable.h> -#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_nothrow_assignable.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_referenceable.h> #include <__type_traits/is_same.h> #include <__type_traits/is_void.h> diff --git a/libcxx/include/__type_traits/is_trivially_assignable.h b/libcxx/include/__type_traits/is_trivially_assignable.h index 19169d13d6d23708aeafe010dbfc331c017419b5..201333b0fa0b333646d9bd6b48561aef999e6ad2 100644 --- a/libcxx/include/__type_traits/is_trivially_assignable.h +++ b/libcxx/include/__type_traits/is_trivially_assignable.h @@ -10,6 +10,9 @@ #define _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_ASSIGNABLE_H #include <__config> +#include <__type_traits/add_const.h> +#include <__type_traits/add_lvalue_reference.h> +#include <__type_traits/add_rvalue_reference.h> #include <__type_traits/integral_constant.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -26,6 +29,28 @@ template <class _Tp, class _Arg> inline constexpr bool is_trivially_assignable_v = __is_trivially_assignable(_Tp, _Arg); #endif +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_trivially_copy_assignable + : public integral_constant< + bool, + __is_trivially_assignable(__add_lvalue_reference_t<_Tp>, __add_lvalue_reference_t<const _Tp>)> {}; + +#if _LIBCPP_STD_VER >= 17 +template <class _Tp> +inline constexpr bool is_trivially_copy_assignable_v = is_trivially_copy_assignable<_Tp>::value; +#endif + +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_trivially_move_assignable + : public integral_constant< + bool, + __is_trivially_assignable(__add_lvalue_reference_t<_Tp>, __add_rvalue_reference_t<_Tp>)> {}; + +#if _LIBCPP_STD_VER >= 17 +template <class _Tp> +inline constexpr bool is_trivially_move_assignable_v = is_trivially_move_assignable<_Tp>::value; +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_ASSIGNABLE_H diff --git a/libcxx/include/__type_traits/is_trivially_constructible.h b/libcxx/include/__type_traits/is_trivially_constructible.h index 4faaf9323cd5bbeac87bfe5eea0bde0d704df317..3a77e9fe164da10ff66f4de8709fdbdb1e9e25e6 100644 --- a/libcxx/include/__type_traits/is_trivially_constructible.h +++ b/libcxx/include/__type_traits/is_trivially_constructible.h @@ -10,6 +10,8 @@ #define _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_CONSTRUCTIBLE_H #include <__config> +#include <__type_traits/add_lvalue_reference.h> +#include <__type_traits/add_rvalue_reference.h> #include <__type_traits/integral_constant.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -27,6 +29,33 @@ template <class _Tp, class... _Args> inline constexpr bool is_trivially_constructible_v = __is_trivially_constructible(_Tp, _Args...); #endif +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_trivially_copy_constructible + : public integral_constant<bool, __is_trivially_constructible(_Tp, __add_lvalue_reference_t<const _Tp>)> {}; + +#if _LIBCPP_STD_VER >= 17 +template <class _Tp> +inline constexpr bool is_trivially_copy_constructible_v = is_trivially_copy_constructible<_Tp>::value; +#endif + +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_trivially_move_constructible + : public integral_constant<bool, __is_trivially_constructible(_Tp, __add_rvalue_reference_t<_Tp>)> {}; + +#if _LIBCPP_STD_VER >= 17 +template <class _Tp> +inline constexpr bool is_trivially_move_constructible_v = is_trivially_move_constructible<_Tp>::value; +#endif + +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS is_trivially_default_constructible + : public integral_constant<bool, __is_trivially_constructible(_Tp)> {}; + +#if _LIBCPP_STD_VER >= 17 +template <class _Tp> +inline constexpr bool is_trivially_default_constructible_v = __is_trivially_constructible(_Tp); +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_CONSTRUCTIBLE_H diff --git a/libcxx/include/__type_traits/is_trivially_copy_assignable.h b/libcxx/include/__type_traits/is_trivially_copy_assignable.h deleted file mode 100644 index b6b3c119746f5b4cf4009a4b8b95c1ed458aacf6..0000000000000000000000000000000000000000 --- a/libcxx/include/__type_traits/is_trivially_copy_assignable.h +++ /dev/null @@ -1,36 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_COPY_ASSIGNABLE_H -#define _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_COPY_ASSIGNABLE_H - -#include <__config> -#include <__type_traits/add_const.h> -#include <__type_traits/add_lvalue_reference.h> -#include <__type_traits/integral_constant.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_trivially_copy_assignable - : public integral_constant<bool, - __is_trivially_assignable(__add_lvalue_reference_t<_Tp>, - __add_lvalue_reference_t<typename add_const<_Tp>::type>)> {}; - -#if _LIBCPP_STD_VER >= 17 -template <class _Tp> -inline constexpr bool is_trivially_copy_assignable_v = is_trivially_copy_assignable<_Tp>::value; -#endif - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_COPY_ASSIGNABLE_H diff --git a/libcxx/include/__type_traits/is_trivially_copy_constructible.h b/libcxx/include/__type_traits/is_trivially_copy_constructible.h deleted file mode 100644 index 8e71fd1fbf8b3e3c248b347966dc5afdaf67d332..0000000000000000000000000000000000000000 --- a/libcxx/include/__type_traits/is_trivially_copy_constructible.h +++ /dev/null @@ -1,33 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_COPY_CONSTRUCTIBLE_H -#define _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_COPY_CONSTRUCTIBLE_H - -#include <__config> -#include <__type_traits/add_lvalue_reference.h> -#include <__type_traits/integral_constant.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_trivially_copy_constructible - : public integral_constant<bool, __is_trivially_constructible(_Tp, __add_lvalue_reference_t<const _Tp>)> {}; - -#if _LIBCPP_STD_VER >= 17 -template <class _Tp> -inline constexpr bool is_trivially_copy_constructible_v = is_trivially_copy_constructible<_Tp>::value; -#endif - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_COPY_CONSTRUCTIBLE_H diff --git a/libcxx/include/__type_traits/is_trivially_default_constructible.h b/libcxx/include/__type_traits/is_trivially_default_constructible.h deleted file mode 100644 index c3b6152a9fcad8e3c904bd6ed6ee35685b3a651f..0000000000000000000000000000000000000000 --- a/libcxx/include/__type_traits/is_trivially_default_constructible.h +++ /dev/null @@ -1,32 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE_H -#define _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE_H - -#include <__config> -#include <__type_traits/integral_constant.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_trivially_default_constructible - : public integral_constant<bool, __is_trivially_constructible(_Tp)> {}; - -#if _LIBCPP_STD_VER >= 17 -template <class _Tp> -inline constexpr bool is_trivially_default_constructible_v = __is_trivially_constructible(_Tp); -#endif - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE_H diff --git a/libcxx/include/__type_traits/is_trivially_move_assignable.h b/libcxx/include/__type_traits/is_trivially_move_assignable.h deleted file mode 100644 index daf890b26c74324e595f715ec74231d1ad7d4218..0000000000000000000000000000000000000000 --- a/libcxx/include/__type_traits/is_trivially_move_assignable.h +++ /dev/null @@ -1,36 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_MOVE_ASSIGNABLE_H -#define _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_MOVE_ASSIGNABLE_H - -#include <__config> -#include <__type_traits/add_lvalue_reference.h> -#include <__type_traits/add_rvalue_reference.h> -#include <__type_traits/integral_constant.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_trivially_move_assignable - : public integral_constant< - bool, - __is_trivially_assignable(__add_lvalue_reference_t<_Tp>, __add_rvalue_reference_t<_Tp>)> {}; - -#if _LIBCPP_STD_VER >= 17 -template <class _Tp> -inline constexpr bool is_trivially_move_assignable_v = is_trivially_move_assignable<_Tp>::value; -#endif - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_MOVE_ASSIGNABLE_H diff --git a/libcxx/include/__type_traits/is_trivially_move_constructible.h b/libcxx/include/__type_traits/is_trivially_move_constructible.h deleted file mode 100644 index 71e6f898fb3f38c41367fd70b3154c562d65a21f..0000000000000000000000000000000000000000 --- a/libcxx/include/__type_traits/is_trivially_move_constructible.h +++ /dev/null @@ -1,33 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE_H -#define _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE_H - -#include <__config> -#include <__type_traits/add_rvalue_reference.h> -#include <__type_traits/integral_constant.h> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -template <class _Tp> -struct _LIBCPP_TEMPLATE_VIS is_trivially_move_constructible - : public integral_constant<bool, __is_trivially_constructible(_Tp, __add_rvalue_reference_t<_Tp>)> {}; - -#if _LIBCPP_STD_VER >= 17 -template <class _Tp> -inline constexpr bool is_trivially_move_constructible_v = is_trivially_move_constructible<_Tp>::value; -#endif - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP___TYPE_TRAITS_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE_H diff --git a/libcxx/include/__type_traits/noexcept_move_assign_container.h b/libcxx/include/__type_traits/noexcept_move_assign_container.h index 1d6c07e8cf96d378190d86f77a999a4cdaf40180..baaf36d9980e94841b2f468f04b6cde8ad31313d 100644 --- a/libcxx/include/__type_traits/noexcept_move_assign_container.h +++ b/libcxx/include/__type_traits/noexcept_move_assign_container.h @@ -12,7 +12,7 @@ #include <__config> #include <__memory/allocator_traits.h> #include <__type_traits/integral_constant.h> -#include <__type_traits/is_nothrow_move_assignable.h> +#include <__type_traits/is_nothrow_assignable.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__type_traits/remove_reference.h b/libcxx/include/__type_traits/remove_reference.h index fd66417bd84fedb0149a0493a76b5c58925e2fea..ba67891758adcefd83512408a3b5d6173b32b2d9 100644 --- a/libcxx/include/__type_traits/remove_reference.h +++ b/libcxx/include/__type_traits/remove_reference.h @@ -10,7 +10,6 @@ #define _LIBCPP___TYPE_TRAITS_REMOVE_REFERENCE_H #include <__config> -#include <cstddef> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -26,15 +25,16 @@ struct remove_reference { template <class _Tp> using __libcpp_remove_reference_t = __remove_reference_t(_Tp); -#else -// clang-format off -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_reference {typedef _LIBCPP_NODEBUG _Tp type;}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_reference<_Tp&> {typedef _LIBCPP_NODEBUG _Tp type;}; -template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_reference<_Tp&&> {typedef _LIBCPP_NODEBUG _Tp type;}; -// clang-format on +#elif __has_builtin(__remove_reference) +template <class _Tp> +struct remove_reference { + using type _LIBCPP_NODEBUG = __remove_reference(_Tp); +}; template <class _Tp> using __libcpp_remove_reference_t = typename remove_reference<_Tp>::type; +#else +# error "remove_reference not implemented!" #endif // __has_builtin(__remove_reference_t) #if _LIBCPP_STD_VER >= 14 diff --git a/libcxx/include/__utility/exception_guard.h b/libcxx/include/__utility/exception_guard.h index 8d90dfd5f1907a820ff87c25a249542c6ab80e28..93290be40e7148ec0246eaa014e0ccb5b4b277b0 100644 --- a/libcxx/include/__utility/exception_guard.h +++ b/libcxx/include/__utility/exception_guard.h @@ -11,7 +11,7 @@ #include <__assert> #include <__config> -#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__utility/exchange.h> #include <__utility/move.h> diff --git a/libcxx/include/__utility/exchange.h b/libcxx/include/__utility/exchange.h index 72312c06b5886ddffca6c24d4c3a6ee9fbd07bb0..957e9d0acaa65ed81688760e7b422e7296a7cd26 100644 --- a/libcxx/include/__utility/exchange.h +++ b/libcxx/include/__utility/exchange.h @@ -11,7 +11,7 @@ #include <__config> #include <__type_traits/is_nothrow_assignable.h> -#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__utility/forward.h> #include <__utility/move.h> diff --git a/libcxx/include/__utility/move.h b/libcxx/include/__utility/move.h index 86d7fc88473bd28d77a1795e0dd114ed9bc47ece..626535c8b1ee3983d2fec0a0ee8cb634d77ec96f 100644 --- a/libcxx/include/__utility/move.h +++ b/libcxx/include/__utility/move.h @@ -12,8 +12,8 @@ #include <__config> #include <__type_traits/conditional.h> -#include <__type_traits/is_copy_constructible.h> -#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/remove_reference.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__utility/pair.h b/libcxx/include/__utility/pair.h index b488a9829c3849e9e8221c6a1a0cf527b4ae7f34..e05250ba05717f0e3d5235789aadaeae7740f0e4 100644 --- a/libcxx/include/__utility/pair.h +++ b/libcxx/include/__utility/pair.h @@ -15,12 +15,11 @@ #include <__config> #include <__fwd/array.h> #include <__fwd/pair.h> -#include <__fwd/subrange.h> #include <__fwd/tuple.h> -#include <__tuple/pair_like.h> #include <__tuple/sfinae_helpers.h> #include <__tuple/tuple_element.h> #include <__tuple/tuple_indices.h> +#include <__tuple/tuple_like_no_subrange.h> #include <__tuple/tuple_size.h> #include <__type_traits/common_reference.h> #include <__type_traits/common_type.h> @@ -30,16 +29,9 @@ #include <__type_traits/is_assignable.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> -#include <__type_traits/is_copy_assignable.h> -#include <__type_traits/is_default_constructible.h> #include <__type_traits/is_implicitly_default_constructible.h> -#include <__type_traits/is_move_assignable.h> #include <__type_traits/is_nothrow_assignable.h> #include <__type_traits/is_nothrow_constructible.h> -#include <__type_traits/is_nothrow_copy_assignable.h> -#include <__type_traits/is_nothrow_copy_constructible.h> -#include <__type_traits/is_nothrow_default_constructible.h> -#include <__type_traits/is_nothrow_move_assignable.h> #include <__type_traits/is_same.h> #include <__type_traits/is_swappable.h> #include <__type_traits/nat.h> @@ -67,14 +59,6 @@ struct __non_trivially_copyable_base { __non_trivially_copyable_base(__non_trivially_copyable_base const&) _NOEXCEPT {} }; -#if _LIBCPP_STD_VER >= 23 -template <class _Tp> -struct __is_specialization_of_subrange : false_type {}; - -template <class _Iter, class _Sent, ranges::subrange_kind _Kind> -struct __is_specialization_of_subrange<ranges::subrange<_Iter, _Sent, _Kind>> : true_type {}; -#endif - template <class _T1, class _T2> struct _LIBCPP_TEMPLATE_VIS pair #if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR) @@ -208,19 +192,19 @@ struct _LIBCPP_TEMPLATE_VIS pair # endif # if _LIBCPP_STD_VER >= 23 + // TODO: Remove this workaround in LLVM 20. The bug got fixed in Clang 18. // This is a workaround for http://llvm.org/PR60710. We should be able to remove it once Clang is fixed. template <class _PairLike> _LIBCPP_HIDE_FROM_ABI static constexpr bool __pair_like_explicit_wknd() { - if constexpr (__pair_like<_PairLike>) { + if constexpr (__pair_like_no_subrange<_PairLike>) { return !is_convertible_v<decltype(std::get<0>(std::declval<_PairLike&&>())), first_type> || !is_convertible_v<decltype(std::get<1>(std::declval<_PairLike&&>())), second_type>; } return false; } - template <__pair_like _PairLike> - requires(!__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value && - is_constructible_v<first_type, decltype(std::get<0>(std::declval<_PairLike &&>()))> && + template <__pair_like_no_subrange _PairLike> + requires(is_constructible_v<first_type, decltype(std::get<0>(std::declval<_PairLike &&>()))> && is_constructible_v<second_type, decltype(std::get<1>(std::declval<_PairLike &&>()))>) _LIBCPP_HIDE_FROM_ABI constexpr explicit(__pair_like_explicit_wknd<_PairLike>()) pair(_PairLike&& __p) : first(std::get<0>(std::forward<_PairLike>(__p))), second(std::get<1>(std::forward<_PairLike>(__p))) {} @@ -313,8 +297,8 @@ struct _LIBCPP_TEMPLATE_VIS pair return *this; } - template <__pair_like _PairLike> - requires(__different_from<_PairLike, pair> && !__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value && + template <__pair_like_no_subrange _PairLike> + requires(__different_from<_PairLike, pair> && is_assignable_v<first_type&, decltype(std::get<0>(std::declval<_PairLike>()))> && is_assignable_v<second_type&, decltype(std::get<1>(std::declval<_PairLike>()))>) _LIBCPP_HIDE_FROM_ABI constexpr pair& operator=(_PairLike&& __p) { @@ -323,8 +307,8 @@ struct _LIBCPP_TEMPLATE_VIS pair return *this; } - template <__pair_like _PairLike> - requires(__different_from<_PairLike, pair> && !__is_specialization_of_subrange<remove_cvref_t<_PairLike>>::value && + template <__pair_like_no_subrange _PairLike> + requires(__different_from<_PairLike, pair> && is_assignable_v<first_type const&, decltype(std::get<0>(std::declval<_PairLike>()))> && is_assignable_v<second_type const&, decltype(std::get<1>(std::declval<_PairLike>()))>) _LIBCPP_HIDE_FROM_ABI constexpr pair const& operator=(_PairLike&& __p) const { @@ -447,7 +431,9 @@ private: tuple<_Args1...>& __first_args, tuple<_Args2...>& __second_args, __tuple_indices<_I1...>, - __tuple_indices<_I2...>); + __tuple_indices<_I2...>) + : first(std::forward<_Args1>(std::get<_I1>(__first_args))...), + second(std::forward<_Args2>(std::get<_I2>(__second_args))...) {} #endif }; diff --git a/libcxx/include/__utility/small_buffer.h b/libcxx/include/__utility/small_buffer.h index f3415a5e50f9992d55fcb71df21b017b672cce2e..9e13797573d2d788dcb5250a7c8d2e7a9666ed44 100644 --- a/libcxx/include/__utility/small_buffer.h +++ b/libcxx/include/__utility/small_buffer.h @@ -12,8 +12,8 @@ #include <__config> #include <__memory/construct_at.h> #include <__type_traits/decay.h> +#include <__type_traits/is_trivially_constructible.h> #include <__type_traits/is_trivially_destructible.h> -#include <__type_traits/is_trivially_move_constructible.h> #include <__utility/exception_guard.h> #include <__utility/forward.h> #include <cstddef> diff --git a/libcxx/include/__utility/swap.h b/libcxx/include/__utility/swap.h index ca8280c729df1d6f3b236660f24c6fba8dd29e09..d678d2cba7dc9fb8d58ee3006dceb9311ab5ed90 100644 --- a/libcxx/include/__utility/swap.h +++ b/libcxx/include/__utility/swap.h @@ -10,10 +10,10 @@ #define _LIBCPP___UTILITY_SWAP_H #include <__config> -#include <__type_traits/is_move_assignable.h> -#include <__type_traits/is_move_constructible.h> -#include <__type_traits/is_nothrow_move_assignable.h> -#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_assignable.h> +#include <__type_traits/is_constructible.h> +#include <__type_traits/is_nothrow_assignable.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_swappable.h> #include <__utility/declval.h> #include <__utility/move.h> diff --git a/libcxx/include/any b/libcxx/include/any index ce54803cd91b5b2d6a34ff8c28cf8fa8381e7f48..0e66890593c389aa11952d33bdc50ce950ff500b 100644 --- a/libcxx/include/any +++ b/libcxx/include/any @@ -80,7 +80,6 @@ namespace std { */ -#include <__availability> #include <__config> #include <__memory/allocator.h> #include <__memory/allocator_destructor.h> @@ -92,9 +91,8 @@ namespace std { #include <__type_traits/conditional.h> #include <__type_traits/decay.h> #include <__type_traits/is_constructible.h> -#include <__type_traits/is_copy_constructible.h> #include <__type_traits/is_function.h> -#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_reference.h> #include <__type_traits/is_same.h> #include <__type_traits/is_void.h> diff --git a/libcxx/include/array b/libcxx/include/array index 7fa5dc1479349ef0ef710229ca41fc26fe262ada..977f913c3e748a8e541e141abf00cad64538215b 100644 --- a/libcxx/include/array +++ b/libcxx/include/array @@ -123,12 +123,11 @@ template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexce #include <__iterator/wrap_iter.h> #include <__tuple/sfinae_helpers.h> #include <__type_traits/conditional.h> +#include <__type_traits/conjunction.h> #include <__type_traits/is_array.h> #include <__type_traits/is_const.h> #include <__type_traits/is_constructible.h> -#include <__type_traits/is_move_constructible.h> #include <__type_traits/is_nothrow_constructible.h> -#include <__type_traits/is_nothrow_move_constructible.h> #include <__type_traits/is_same.h> #include <__type_traits/is_swappable.h> #include <__type_traits/remove_cv.h> diff --git a/libcxx/include/cerrno b/libcxx/include/cerrno index d488fa72a54b7a3cba63e4f8765cc1e7c572ca3a..6171ae31f18479e11fc2adcbca8e306501c7826b 100644 --- a/libcxx/include/cerrno +++ b/libcxx/include/cerrno @@ -38,4 +38,17 @@ Macros: # pragma GCC system_header #endif +#ifdef ENODATA +# pragma clang deprecated(ENODATA, "ENODATA is deprecated in ISO C++") +#endif +#ifdef ENOSR +# pragma clang deprecated(ENOSR, "ENOSR is deprecated in ISO C++") +#endif +#ifdef ENOSTR +# pragma clang deprecated(ENOSTR, "ENOSTR is deprecated in ISO C++") +#endif +#ifdef ETIME +# pragma clang deprecated(ETIME, "ETIME is deprecated in ISO C++") +#endif + #endif // _LIBCPP_CERRNO diff --git a/libcxx/include/chrono b/libcxx/include/chrono index b3b260c2a998e67eb6bc763b29f64169d0e63486..5bab3f8ad5cf0569687a94d9392c57e3104f923f 100644 --- a/libcxx/include/chrono +++ b/libcxx/include/chrono @@ -878,10 +878,12 @@ constexpr chrono::year operator ""y(unsigned lo # include <cstring> # include <forward_list> # include <string> +# include <tuple> #endif #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER == 20 # include <charconv> +# include <locale> #endif #endif // _LIBCPP_CHRONO diff --git a/libcxx/include/complex b/libcxx/include/complex index e996485a38ae678b0b12a4a4d4d978dccb54fe40..a81f968143c4cfbffb83bd574d2dfa2caeb8b31f 100644 --- a/libcxx/include/complex +++ b/libcxx/include/complex @@ -258,6 +258,7 @@ template<class T> complex<T> tanh (const complex<T>&); #include <__config> #include <__fwd/complex.h> +#include <__fwd/tuple.h> #include <__tuple/tuple_element.h> #include <__tuple/tuple_size.h> #include <__utility/move.h> @@ -1443,15 +1444,9 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const complex<_Tp>& __x) { // [complex.tuple], tuple interface -template <class _Tp> -struct tuple_size; - template <class _Tp> struct tuple_size<complex<_Tp>> : integral_constant<size_t, 2> {}; -template <size_t _Ip, class _Tp> -struct tuple_element; - template <size_t _Ip, class _Tp> struct tuple_element<_Ip, complex<_Tp>> { static_assert(_Ip < 2, "Index value is out of range."); diff --git a/libcxx/include/coroutine b/libcxx/include/coroutine index 4bd1d4e9c3103a4b0fe186a84d07a639dcc07ddd..b1ba83b541b4b7006c0af1e5cd809fec280ab4ee 100644 --- a/libcxx/include/coroutine +++ b/libcxx/include/coroutine @@ -56,6 +56,7 @@ struct suspend_always; #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include <iosfwd> +# include <limits> # include <type_traits> #endif diff --git a/libcxx/include/cwchar b/libcxx/include/cwchar index 7442438d8f447f86f24740eed7a0bc6b7ded2319..4cc6f56c389bfe929bb1a69ffa01c17a349eaf6d 100644 --- a/libcxx/include/cwchar +++ b/libcxx/include/cwchar @@ -254,4 +254,8 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* __constexpr_wmemchr(_Tp _LIBCPP_END_NAMESPACE_STD +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <cstddef> +#endif + #endif // _LIBCPP_CWCHAR diff --git a/libcxx/include/deque b/libcxx/include/deque index 85ea9c6f661ed69243ff393bbe9913c2e65d18c1..a6472e46d426c71bd75ef679c65afe07b573bfa4 100644 --- a/libcxx/include/deque +++ b/libcxx/include/deque @@ -192,6 +192,7 @@ template <class T, class Allocator, class Predicate> #include <__availability> #include <__config> #include <__format/enable_insertable.h> +#include <__fwd/deque.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> #include <__iterator/next.h> @@ -244,9 +245,6 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp, class _Allocator = allocator<_Tp> > -class _LIBCPP_TEMPLATE_VIS deque; - template <class _ValueType, class _DiffType> struct __deque_block_size { static const _DiffType value = sizeof(_ValueType) < 256 ? 4096 / sizeof(_ValueType) : 16; diff --git a/libcxx/include/execution b/libcxx/include/execution index 822ffa1fd3ebc469bf7f8b62fb122e6ef478cf90..94d434b2e4603ed0c540a0d87acfce7473cd1379 100644 --- a/libcxx/include/execution +++ b/libcxx/include/execution @@ -142,4 +142,8 @@ _LIBCPP_END_NAMESPACE_STD #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_PSTL) && _LIBCPP_STD_VER >= 17 +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <cstddef> +#endif + #endif // _LIBCPP_EXECUTION diff --git a/libcxx/include/experimental/memory b/libcxx/include/experimental/memory index 7e698fe9dee771cab5728e4f7253c2b30ba1a252..e9663d43a8ab73910f8e144ac40952d3553fea98 100644 --- a/libcxx/include/experimental/memory +++ b/libcxx/include/experimental/memory @@ -191,4 +191,8 @@ _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_ENABLE_EXPERIMENTAL +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <limits> +#endif + #endif /* _LIBCPP_EXPERIMENTAL_MEMORY */ diff --git a/libcxx/include/format b/libcxx/include/format index c0485c5a103596dea7dfe216bc3baa6da14884e0..f1e87de0f830158269350736e3b093300cf6a611 100644 --- a/libcxx/include/format +++ b/libcxx/include/format @@ -221,4 +221,10 @@ namespace std { # pragma GCC system_header #endif +#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include <locale> +# include <queue> +# include <stack> +#endif + #endif // _LIBCPP_FORMAT diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list index a62b171a46783ba64a2d09fe32f4e01be37aa396..1dcbe8f88b90db3067196eb325a8cdb9c4abaf37 100644 --- a/libcxx/include/forward_list +++ b/libcxx/include/forward_list @@ -221,9 +221,8 @@ template <class T, class Allocator, class Predicate> #include <__type_traits/conditional.h> #include <__type_traits/is_allocator.h> #include <__type_traits/is_const.h> -#include <__type_traits/is_nothrow_default_constructible.h> -#include <__type_traits/is_nothrow_move_assignable.h> -#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_nothrow_assignable.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_pointer.h> #include <__type_traits/is_same.h> #include <__type_traits/type_identity.h> diff --git a/libcxx/include/fstream b/libcxx/include/fstream index 776641b347e6c1760add5e09aeba4c5bf3111e4e..7a084d114b1855588a1849924c5643cd3a9991ad 100644 --- a/libcxx/include/fstream +++ b/libcxx/include/fstream @@ -308,6 +308,43 @@ private: state_type __st_; state_type __st_last_; ios_base::openmode __om_; + // There have been no file operations yet, which allows setting unbuffered + // I/O mode. + static const ios_base::openmode __no_io_operations = ios_base::trunc; + // Unbuffered I/O mode has been requested. + static const ios_base::openmode __use_unbuffered_io = ios_base::ate; + // Used to track the currently used mode and track whether the output should + // be unbuffered. + // [filebuf.virtuals]/12 + // If setbuf(0, 0) is called on a stream before any I/O has occurred on + // that stream, the stream becomes unbuffered. Otherwise the results are + // implementation-defined. + // This allows calling setbuf(0, 0) + // - before opening a file, + // - after opening a file, before + // - a read + // - a write + // - a seek. + // Note that opening a file with ios_base::ate does a seek operation. + // Normally underflow, overflow, and sync change this flag to ios_base::in, + // ios_base_out, or 0. + // + // The ios_base::trunc and ios_base::ate flags are not used in __cm_. They + // are used to track the state of the unbuffered request. For readability + // they have the aliases __no_io_operations and __use_unbuffered_io + // respectively. + // + // The __no_io_operations and __use_unbuffered_io flags are used in the + // following way: + // - __no_io_operations is set upon construction to indicate the unbuffered + // state can be set. + // - When requesting unbuffered output: + // - If the file is open it sets the mode. + // - Else places a request by adding the __use_unbuffered_io flag. + // - When a file is opened it checks whether both __no_io_operations and + // __use_unbuffered_io are set. If so switches to unbuffered mode. + // - All file I/O operations change the mode effectively clearing the + // __no_io_operations and __use_unbuffered_io flags. ios_base::openmode __cm_; bool __owns_eb_; bool __owns_ib_; @@ -327,7 +364,13 @@ private: return nullptr; __om_ = __mode; + if (__cm_ == (__no_io_operations | __use_unbuffered_io)) { + std::setbuf(__file_, nullptr); + __cm_ = 0; + } + if (__mode & ios_base::ate) { + __cm_ = 0; if (fseek(__file_, 0, SEEK_END)) { fclose(__file_); __file_ = nullptr; @@ -337,6 +380,20 @@ private: return this; } + + // If the file is already open, switch to unbuffered mode. Otherwise, record + // the request to use unbuffered mode so that we use that mode when we + // eventually open the file. + _LIBCPP_HIDE_FROM_ABI void __request_unbuffered_mode(char_type* __s, streamsize __n) { + if (__cm_ == __no_io_operations && __s == nullptr && __n == 0) { + if (__file_) { + std::setbuf(__file_, nullptr); + __cm_ = 0; + } else { + __cm_ = __no_io_operations | __use_unbuffered_io; + } + } + } }; template <class _CharT, class _Traits> @@ -352,7 +409,7 @@ basic_filebuf<_CharT, _Traits>::basic_filebuf() __st_(), __st_last_(), __om_(0), - __cm_(0), + __cm_(__no_io_operations), __owns_eb_(false), __owns_ib_(false), __always_noconv_(false) { @@ -810,6 +867,7 @@ template <class _CharT, class _Traits> basic_streambuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::setbuf(char_type* __s, streamsize __n) { this->setg(nullptr, nullptr, nullptr); this->setp(nullptr, nullptr); + __request_unbuffered_mode(__s, __n); if (__owns_eb_) delete[] __extbuf_; if (__owns_ib_) diff --git a/libcxx/include/future b/libcxx/include/future index fda1591818a667264f7ef00e8589d8026974b7b9..3c228686063e4a321c10c53892920217f5fbbca7 100644 --- a/libcxx/include/future +++ b/libcxx/include/future @@ -369,7 +369,6 @@ template <class R, class Alloc> struct uses_allocator<packaged_task<R>, Alloc>; #endif #include <__assert> -#include <__availability> #include <__chrono/duration.h> #include <__chrono/time_point.h> #include <__exception/exception_ptr.h> diff --git a/libcxx/include/iosfwd b/libcxx/include/iosfwd index f1c2cbd9669679256eaac3081baf744dcda7bd6b..9af5e05031850dfd18c605cab39b30c98ee9a566 100644 --- a/libcxx/include/iosfwd +++ b/libcxx/include/iosfwd @@ -110,6 +110,7 @@ using wosyncstream = basic_osyncstream<wchar_t>; // C++20 #include <__fwd/fstream.h> #include <__fwd/ios.h> #include <__fwd/istream.h> +#include <__fwd/memory.h> #include <__fwd/ostream.h> #include <__fwd/sstream.h> #include <__fwd/streambuf.h> @@ -162,10 +163,6 @@ using wosyncstream = basic_osyncstream<wchar_t>; #endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM) -// Include other forward declarations here -template <class _Tp, class _Alloc = allocator<_Tp> > -class _LIBCPP_TEMPLATE_VIS vector; - template <class _CharT, class _Traits> class __save_flags { typedef basic_ios<_CharT, _Traits> __stream_type; diff --git a/libcxx/include/libcxx.imp b/libcxx/include/libcxx.imp index b1e728cde868da1e8c91ae8e62b678a86ef490a3..ea0ba8c5471da44bcadbb42a04127b337fd60bc6 100644 --- a/libcxx/include/libcxx.imp +++ b/libcxx/include/libcxx.imp @@ -217,6 +217,7 @@ { include: [ "<__algorithm/shift_right.h>", "private", "<algorithm>", "public" ] }, { include: [ "<__algorithm/shuffle.h>", "private", "<algorithm>", "public" ] }, { include: [ "<__algorithm/sift_down.h>", "private", "<algorithm>", "public" ] }, + { include: [ "<__algorithm/simd_utils.h>", "private", "<algorithm>", "public" ] }, { include: [ "<__algorithm/sort.h>", "private", "<algorithm>", "public" ] }, { include: [ "<__algorithm/sort_heap.h>", "private", "<algorithm>", "public" ] }, { include: [ "<__algorithm/stable_partition.h>", "private", "<algorithm>", "public" ] }, @@ -424,22 +425,27 @@ { include: [ "<__fwd/bit_reference.h>", "private", "<bitset>", "public" ] }, { include: [ "<__fwd/bit_reference.h>", "private", "<vector>", "public" ] }, { include: [ "<__fwd/complex.h>", "private", "<complex>", "public" ] }, + { include: [ "<__fwd/deque.h>", "private", "<deque>", "public" ] }, { include: [ "<__fwd/format.h>", "private", "<format>", "public" ] }, { include: [ "<__fwd/fstream.h>", "private", "<iosfwd>", "public" ] }, { include: [ "<__fwd/functional.h>", "private", "<functional>", "public" ] }, { include: [ "<__fwd/ios.h>", "private", "<iosfwd>", "public" ] }, { include: [ "<__fwd/istream.h>", "private", "<iosfwd>", "public" ] }, { include: [ "<__fwd/mdspan.h>", "private", "<mdspan>", "public" ] }, + { include: [ "<__fwd/memory.h>", "private", "<memory>", "public" ] }, { include: [ "<__fwd/memory_resource.h>", "private", "<memory_resource>", "public" ] }, { include: [ "<__fwd/ostream.h>", "private", "<iosfwd>", "public" ] }, { include: [ "<__fwd/pair.h>", "private", "<utility>", "public" ] }, + { include: [ "<__fwd/queue.h>", "private", "<queue>", "public" ] }, { include: [ "<__fwd/span.h>", "private", "<span>", "public" ] }, { include: [ "<__fwd/sstream.h>", "private", "<iosfwd>", "public" ] }, + { include: [ "<__fwd/stack.h>", "private", "<stack>", "public" ] }, { include: [ "<__fwd/streambuf.h>", "private", "<iosfwd>", "public" ] }, { include: [ "<__fwd/string.h>", "private", "<string>", "public" ] }, { include: [ "<__fwd/string_view.h>", "private", "<string_view>", "public" ] }, { include: [ "<__fwd/subrange.h>", "private", "<ranges>", "public" ] }, { include: [ "<__fwd/tuple.h>", "private", "<tuple>", "public" ] }, + { include: [ "<__fwd/vector.h>", "private", "<vector>", "public" ] }, { include: [ "<__ios/fpos.h>", "private", "<ios>", "public" ] }, { include: [ "<__iterator/access.h>", "private", "<iterator>", "public" ] }, { include: [ "<__iterator/advance.h>", "private", "<iterator>", "public" ] }, @@ -699,12 +705,12 @@ { include: [ "<__thread/timed_backoff_policy.h>", "private", "<thread>", "public" ] }, { include: [ "<__tuple/find_index.h>", "private", "<tuple>", "public" ] }, { include: [ "<__tuple/make_tuple_types.h>", "private", "<tuple>", "public" ] }, - { include: [ "<__tuple/pair_like.h>", "private", "<tuple>", "public" ] }, { include: [ "<__tuple/sfinae_helpers.h>", "private", "<tuple>", "public" ] }, { include: [ "<__tuple/tuple_element.h>", "private", "<tuple>", "public" ] }, { include: [ "<__tuple/tuple_indices.h>", "private", "<tuple>", "public" ] }, { include: [ "<__tuple/tuple_like.h>", "private", "<tuple>", "public" ] }, { include: [ "<__tuple/tuple_like_ext.h>", "private", "<tuple>", "public" ] }, + { include: [ "<__tuple/tuple_like_no_subrange.h>", "private", "<tuple>", "public" ] }, { include: [ "<__tuple/tuple_size.h>", "private", "<tuple>", "public" ] }, { include: [ "<__tuple/tuple_types.h>", "private", "<tuple>", "public" ] }, { include: [ "<__type_traits/add_const.h>", "private", "<type_traits>", "public" ] }, @@ -751,10 +757,7 @@ { include: [ "<__type_traits/is_constant_evaluated.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_constructible.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_convertible.h>", "private", "<type_traits>", "public" ] }, - { include: [ "<__type_traits/is_copy_assignable.h>", "private", "<type_traits>", "public" ] }, - { include: [ "<__type_traits/is_copy_constructible.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_core_convertible.h>", "private", "<type_traits>", "public" ] }, - { include: [ "<__type_traits/is_default_constructible.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_destructible.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_empty.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_enum.h>", "private", "<type_traits>", "public" ] }, @@ -770,17 +773,10 @@ { include: [ "<__type_traits/is_member_function_pointer.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_member_object_pointer.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_member_pointer.h>", "private", "<type_traits>", "public" ] }, - { include: [ "<__type_traits/is_move_assignable.h>", "private", "<type_traits>", "public" ] }, - { include: [ "<__type_traits/is_move_constructible.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_nothrow_assignable.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_nothrow_constructible.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_nothrow_convertible.h>", "private", "<type_traits>", "public" ] }, - { include: [ "<__type_traits/is_nothrow_copy_assignable.h>", "private", "<type_traits>", "public" ] }, - { include: [ "<__type_traits/is_nothrow_copy_constructible.h>", "private", "<type_traits>", "public" ] }, - { include: [ "<__type_traits/is_nothrow_default_constructible.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_nothrow_destructible.h>", "private", "<type_traits>", "public" ] }, - { include: [ "<__type_traits/is_nothrow_move_assignable.h>", "private", "<type_traits>", "public" ] }, - { include: [ "<__type_traits/is_nothrow_move_constructible.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_null_pointer.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_object.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_pod.h>", "private", "<type_traits>", "public" ] }, @@ -801,14 +797,9 @@ { include: [ "<__type_traits/is_trivial.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_trivially_assignable.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_trivially_constructible.h>", "private", "<type_traits>", "public" ] }, - { include: [ "<__type_traits/is_trivially_copy_assignable.h>", "private", "<type_traits>", "public" ] }, - { include: [ "<__type_traits/is_trivially_copy_constructible.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_trivially_copyable.h>", "private", "<type_traits>", "public" ] }, - { include: [ "<__type_traits/is_trivially_default_constructible.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_trivially_destructible.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_trivially_lexicographically_comparable.h>", "private", "<type_traits>", "public" ] }, - { include: [ "<__type_traits/is_trivially_move_assignable.h>", "private", "<type_traits>", "public" ] }, - { include: [ "<__type_traits/is_trivially_move_constructible.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_trivially_relocatable.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_unbounded_array.h>", "private", "<type_traits>", "public" ] }, { include: [ "<__type_traits/is_union.h>", "private", "<type_traits>", "public" ] }, diff --git a/libcxx/include/limits b/libcxx/include/limits index f15b5b1ab1d52f85abe27199ac7bd28262ef696c..f022048cc26554ce7fbea43c0c74a0f0a1ba4734 100644 --- a/libcxx/include/limits +++ b/libcxx/include/limits @@ -137,9 +137,9 @@ protected: typedef _Tp type; static _LIBCPP_CONSTEXPR const bool is_specialized = false; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type min() _NOEXCEPT { return type(); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type max() _NOEXCEPT { return type(); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type lowest() _NOEXCEPT { return type(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type min() _NOEXCEPT { return type(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type max() _NOEXCEPT { return type(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type lowest() _NOEXCEPT { return type(); } static _LIBCPP_CONSTEXPR const int digits = 0; static _LIBCPP_CONSTEXPR const int digits10 = 0; @@ -148,8 +148,8 @@ protected: static _LIBCPP_CONSTEXPR const bool is_integer = false; static _LIBCPP_CONSTEXPR const bool is_exact = false; static _LIBCPP_CONSTEXPR const int radix = 0; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type epsilon() _NOEXCEPT { return type(); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type round_error() _NOEXCEPT { return type(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type epsilon() _NOEXCEPT { return type(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type round_error() _NOEXCEPT { return type(); } static _LIBCPP_CONSTEXPR const int min_exponent = 0; static _LIBCPP_CONSTEXPR const int min_exponent10 = 0; @@ -161,10 +161,10 @@ protected: static _LIBCPP_CONSTEXPR const bool has_signaling_NaN = false; static _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_CONSTEXPR const float_denorm_style has_denorm = denorm_absent; static _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_CONSTEXPR const bool has_denorm_loss = false; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type infinity() _NOEXCEPT { return type(); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type quiet_NaN() _NOEXCEPT { return type(); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type signaling_NaN() _NOEXCEPT { return type(); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type denorm_min() _NOEXCEPT { return type(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type infinity() _NOEXCEPT { return type(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type quiet_NaN() _NOEXCEPT { return type(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type signaling_NaN() _NOEXCEPT { return type(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type denorm_min() _NOEXCEPT { return type(); } static _LIBCPP_CONSTEXPR const bool is_iec559 = false; static _LIBCPP_CONSTEXPR const bool is_bounded = false; @@ -198,15 +198,15 @@ protected: static _LIBCPP_CONSTEXPR const int max_digits10 = 0; static _LIBCPP_CONSTEXPR const type __min = __libcpp_compute_min<type, digits, is_signed>::value; static _LIBCPP_CONSTEXPR const type __max = is_signed ? type(type(~0) ^ __min) : type(~0); - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type min() _NOEXCEPT { return __min; } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type max() _NOEXCEPT { return __max; } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type lowest() _NOEXCEPT { return min(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type min() _NOEXCEPT { return __min; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type max() _NOEXCEPT { return __max; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type lowest() _NOEXCEPT { return min(); } static _LIBCPP_CONSTEXPR const bool is_integer = true; static _LIBCPP_CONSTEXPR const bool is_exact = true; static _LIBCPP_CONSTEXPR const int radix = 2; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type epsilon() _NOEXCEPT { return type(0); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type round_error() _NOEXCEPT { return type(0); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type epsilon() _NOEXCEPT { return type(0); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type round_error() _NOEXCEPT { return type(0); } static _LIBCPP_CONSTEXPR const int min_exponent = 0; static _LIBCPP_CONSTEXPR const int min_exponent10 = 0; @@ -218,10 +218,10 @@ protected: static _LIBCPP_CONSTEXPR const bool has_signaling_NaN = false; static _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_CONSTEXPR const float_denorm_style has_denorm = denorm_absent; static _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_CONSTEXPR const bool has_denorm_loss = false; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type infinity() _NOEXCEPT { return type(0); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type quiet_NaN() _NOEXCEPT { return type(0); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type signaling_NaN() _NOEXCEPT { return type(0); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type denorm_min() _NOEXCEPT { return type(0); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type infinity() _NOEXCEPT { return type(0); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type quiet_NaN() _NOEXCEPT { return type(0); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type signaling_NaN() _NOEXCEPT { return type(0); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type denorm_min() _NOEXCEPT { return type(0); } static _LIBCPP_CONSTEXPR const bool is_iec559 = false; static _LIBCPP_CONSTEXPR const bool is_bounded = true; @@ -249,15 +249,15 @@ protected: static _LIBCPP_CONSTEXPR const int max_digits10 = 0; static _LIBCPP_CONSTEXPR const type __min = false; static _LIBCPP_CONSTEXPR const type __max = true; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type min() _NOEXCEPT { return __min; } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type max() _NOEXCEPT { return __max; } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type lowest() _NOEXCEPT { return min(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type min() _NOEXCEPT { return __min; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type max() _NOEXCEPT { return __max; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type lowest() _NOEXCEPT { return min(); } static _LIBCPP_CONSTEXPR const bool is_integer = true; static _LIBCPP_CONSTEXPR const bool is_exact = true; static _LIBCPP_CONSTEXPR const int radix = 2; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type epsilon() _NOEXCEPT { return type(0); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type round_error() _NOEXCEPT { return type(0); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type epsilon() _NOEXCEPT { return type(0); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type round_error() _NOEXCEPT { return type(0); } static _LIBCPP_CONSTEXPR const int min_exponent = 0; static _LIBCPP_CONSTEXPR const int min_exponent10 = 0; @@ -269,10 +269,10 @@ protected: static _LIBCPP_CONSTEXPR const bool has_signaling_NaN = false; static _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_CONSTEXPR const float_denorm_style has_denorm = denorm_absent; static _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_CONSTEXPR const bool has_denorm_loss = false; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type infinity() _NOEXCEPT { return type(0); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type quiet_NaN() _NOEXCEPT { return type(0); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type signaling_NaN() _NOEXCEPT { return type(0); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type denorm_min() _NOEXCEPT { return type(0); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type infinity() _NOEXCEPT { return type(0); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type quiet_NaN() _NOEXCEPT { return type(0); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type signaling_NaN() _NOEXCEPT { return type(0); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type denorm_min() _NOEXCEPT { return type(0); } static _LIBCPP_CONSTEXPR const bool is_iec559 = false; static _LIBCPP_CONSTEXPR const bool is_bounded = true; @@ -294,15 +294,15 @@ protected: static _LIBCPP_CONSTEXPR const int digits = __FLT_MANT_DIG__; static _LIBCPP_CONSTEXPR const int digits10 = __FLT_DIG__; static _LIBCPP_CONSTEXPR const int max_digits10 = 2 + (digits * 30103l) / 100000l; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type min() _NOEXCEPT { return __FLT_MIN__; } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type max() _NOEXCEPT { return __FLT_MAX__; } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type lowest() _NOEXCEPT { return -max(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type min() _NOEXCEPT { return __FLT_MIN__; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type max() _NOEXCEPT { return __FLT_MAX__; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type lowest() _NOEXCEPT { return -max(); } static _LIBCPP_CONSTEXPR const bool is_integer = false; static _LIBCPP_CONSTEXPR const bool is_exact = false; static _LIBCPP_CONSTEXPR const int radix = __FLT_RADIX__; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type epsilon() _NOEXCEPT { return __FLT_EPSILON__; } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type round_error() _NOEXCEPT { return 0.5F; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type epsilon() _NOEXCEPT { return __FLT_EPSILON__; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type round_error() _NOEXCEPT { return 0.5F; } static _LIBCPP_CONSTEXPR const int min_exponent = __FLT_MIN_EXP__; static _LIBCPP_CONSTEXPR const int min_exponent10 = __FLT_MIN_10_EXP__; @@ -314,10 +314,10 @@ protected: static _LIBCPP_CONSTEXPR const bool has_signaling_NaN = true; static _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_CONSTEXPR const float_denorm_style has_denorm = denorm_present; static _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_CONSTEXPR const bool has_denorm_loss = false; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type infinity() _NOEXCEPT { return __builtin_huge_valf(); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type quiet_NaN() _NOEXCEPT { return __builtin_nanf(""); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type signaling_NaN() _NOEXCEPT { return __builtin_nansf(""); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type denorm_min() _NOEXCEPT { return __FLT_DENORM_MIN__; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type infinity() _NOEXCEPT { return __builtin_huge_valf(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type quiet_NaN() _NOEXCEPT { return __builtin_nanf(""); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type signaling_NaN() _NOEXCEPT { return __builtin_nansf(""); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type denorm_min() _NOEXCEPT { return __FLT_DENORM_MIN__; } static _LIBCPP_CONSTEXPR const bool is_iec559 = true; static _LIBCPP_CONSTEXPR const bool is_bounded = true; @@ -343,15 +343,15 @@ protected: static _LIBCPP_CONSTEXPR const int digits = __DBL_MANT_DIG__; static _LIBCPP_CONSTEXPR const int digits10 = __DBL_DIG__; static _LIBCPP_CONSTEXPR const int max_digits10 = 2 + (digits * 30103l) / 100000l; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type min() _NOEXCEPT { return __DBL_MIN__; } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type max() _NOEXCEPT { return __DBL_MAX__; } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type lowest() _NOEXCEPT { return -max(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type min() _NOEXCEPT { return __DBL_MIN__; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type max() _NOEXCEPT { return __DBL_MAX__; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type lowest() _NOEXCEPT { return -max(); } static _LIBCPP_CONSTEXPR const bool is_integer = false; static _LIBCPP_CONSTEXPR const bool is_exact = false; static _LIBCPP_CONSTEXPR const int radix = __FLT_RADIX__; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type epsilon() _NOEXCEPT { return __DBL_EPSILON__; } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type round_error() _NOEXCEPT { return 0.5; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type epsilon() _NOEXCEPT { return __DBL_EPSILON__; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type round_error() _NOEXCEPT { return 0.5; } static _LIBCPP_CONSTEXPR const int min_exponent = __DBL_MIN_EXP__; static _LIBCPP_CONSTEXPR const int min_exponent10 = __DBL_MIN_10_EXP__; @@ -363,10 +363,10 @@ protected: static _LIBCPP_CONSTEXPR const bool has_signaling_NaN = true; static _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_CONSTEXPR const float_denorm_style has_denorm = denorm_present; static _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_CONSTEXPR const bool has_denorm_loss = false; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type infinity() _NOEXCEPT { return __builtin_huge_val(); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type quiet_NaN() _NOEXCEPT { return __builtin_nan(""); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type signaling_NaN() _NOEXCEPT { return __builtin_nans(""); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type denorm_min() _NOEXCEPT { return __DBL_DENORM_MIN__; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type infinity() _NOEXCEPT { return __builtin_huge_val(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type quiet_NaN() _NOEXCEPT { return __builtin_nan(""); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type signaling_NaN() _NOEXCEPT { return __builtin_nans(""); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type denorm_min() _NOEXCEPT { return __DBL_DENORM_MIN__; } static _LIBCPP_CONSTEXPR const bool is_iec559 = true; static _LIBCPP_CONSTEXPR const bool is_bounded = true; @@ -392,15 +392,15 @@ protected: static _LIBCPP_CONSTEXPR const int digits = __LDBL_MANT_DIG__; static _LIBCPP_CONSTEXPR const int digits10 = __LDBL_DIG__; static _LIBCPP_CONSTEXPR const int max_digits10 = 2 + (digits * 30103l) / 100000l; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type min() _NOEXCEPT { return __LDBL_MIN__; } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type max() _NOEXCEPT { return __LDBL_MAX__; } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type lowest() _NOEXCEPT { return -max(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type min() _NOEXCEPT { return __LDBL_MIN__; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type max() _NOEXCEPT { return __LDBL_MAX__; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type lowest() _NOEXCEPT { return -max(); } static _LIBCPP_CONSTEXPR const bool is_integer = false; static _LIBCPP_CONSTEXPR const bool is_exact = false; static _LIBCPP_CONSTEXPR const int radix = __FLT_RADIX__; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type epsilon() _NOEXCEPT { return __LDBL_EPSILON__; } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type round_error() _NOEXCEPT { return 0.5L; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type epsilon() _NOEXCEPT { return __LDBL_EPSILON__; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type round_error() _NOEXCEPT { return 0.5L; } static _LIBCPP_CONSTEXPR const int min_exponent = __LDBL_MIN_EXP__; static _LIBCPP_CONSTEXPR const int min_exponent10 = __LDBL_MIN_10_EXP__; @@ -412,10 +412,10 @@ protected: static _LIBCPP_CONSTEXPR const bool has_signaling_NaN = true; static _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_CONSTEXPR const float_denorm_style has_denorm = denorm_present; static _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_CONSTEXPR const bool has_denorm_loss = false; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type infinity() _NOEXCEPT { return __builtin_huge_vall(); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type quiet_NaN() _NOEXCEPT { return __builtin_nanl(""); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type signaling_NaN() _NOEXCEPT { return __builtin_nansl(""); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type denorm_min() _NOEXCEPT { return __LDBL_DENORM_MIN__; } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type infinity() _NOEXCEPT { return __builtin_huge_vall(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type quiet_NaN() _NOEXCEPT { return __builtin_nanl(""); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type signaling_NaN() _NOEXCEPT { return __builtin_nansl(""); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type denorm_min() _NOEXCEPT { return __LDBL_DENORM_MIN__; } #if defined(__powerpc__) && defined(__LONG_DOUBLE_IBM128__) static _LIBCPP_CONSTEXPR const bool is_iec559 = false; @@ -441,9 +441,9 @@ class _LIBCPP_TEMPLATE_VIS numeric_limits : private __libcpp_numeric_limits<_Tp> public: static _LIBCPP_CONSTEXPR const bool is_specialized = __base::is_specialized; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type min() _NOEXCEPT { return __base::min(); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type max() _NOEXCEPT { return __base::max(); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type lowest() _NOEXCEPT { return __base::lowest(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type min() _NOEXCEPT { return __base::min(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type max() _NOEXCEPT { return __base::max(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type lowest() _NOEXCEPT { return __base::lowest(); } static _LIBCPP_CONSTEXPR const int digits = __base::digits; static _LIBCPP_CONSTEXPR const int digits10 = __base::digits10; @@ -452,8 +452,8 @@ public: static _LIBCPP_CONSTEXPR const bool is_integer = __base::is_integer; static _LIBCPP_CONSTEXPR const bool is_exact = __base::is_exact; static _LIBCPP_CONSTEXPR const int radix = __base::radix; - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type epsilon() _NOEXCEPT { return __base::epsilon(); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type round_error() _NOEXCEPT { return __base::round_error(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type epsilon() _NOEXCEPT { return __base::epsilon(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type round_error() _NOEXCEPT { return __base::round_error(); } static _LIBCPP_CONSTEXPR const int min_exponent = __base::min_exponent; static _LIBCPP_CONSTEXPR const int min_exponent10 = __base::min_exponent10; @@ -467,10 +467,10 @@ public: static _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_CONSTEXPR const float_denorm_style has_denorm = __base::has_denorm; static _LIBCPP_DEPRECATED_IN_CXX23 _LIBCPP_CONSTEXPR const bool has_denorm_loss = __base::has_denorm_loss; _LIBCPP_SUPPRESS_DEPRECATED_POP - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type infinity() _NOEXCEPT { return __base::infinity(); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type quiet_NaN() _NOEXCEPT { return __base::quiet_NaN(); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type signaling_NaN() _NOEXCEPT { return __base::signaling_NaN(); } - _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type denorm_min() _NOEXCEPT { return __base::denorm_min(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type infinity() _NOEXCEPT { return __base::infinity(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type quiet_NaN() _NOEXCEPT { return __base::quiet_NaN(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type signaling_NaN() _NOEXCEPT { return __base::signaling_NaN(); } + _LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR type denorm_min() _NOEXCEPT { return __base::denorm_min(); } static _LIBCPP_CONSTEXPR const bool is_iec559 = __base::is_iec559; static _LIBCPP_CONSTEXPR const bool is_bounded = __base::is_bounded; diff --git a/libcxx/include/list b/libcxx/include/list index 8f0689268e2a5a14761a768edef9281f14ff6ad8..9de3d1f60a1f7904147ac9ec2beb1c67fad9b91f 100644 --- a/libcxx/include/list +++ b/libcxx/include/list @@ -227,9 +227,8 @@ template <class T, class Allocator, class Predicate> #include <__ranges/from_range.h> #include <__type_traits/conditional.h> #include <__type_traits/is_allocator.h> -#include <__type_traits/is_nothrow_default_constructible.h> -#include <__type_traits/is_nothrow_move_assignable.h> -#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_nothrow_assignable.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_pointer.h> #include <__type_traits/is_same.h> #include <__type_traits/type_identity.h> diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index 0bd2831b7f159c8041118f7ac3354524e2d8a15f..22c380327f157930f362745309b786bb1f4a2cc5 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -697,7 +697,10 @@ module std_private_algorithm_minmax [system export * } module std_private_algorithm_minmax_element [system] { header "__algorithm/minmax_element.h" } -module std_private_algorithm_mismatch [system] { header "__algorithm/mismatch.h" } +module std_private_algorithm_mismatch [system] { + header "__algorithm/mismatch.h" + export std_private_algorithm_simd_utils +} module std_private_algorithm_move [system] { header "__algorithm/move.h" } module std_private_algorithm_move_backward [system] { header "__algorithm/move_backward.h" } module std_private_algorithm_next_permutation [system] { header "__algorithm/next_permutation.h" } @@ -1048,6 +1051,7 @@ module std_private_algorithm_sort [system header "__algorithm/sort.h" export std_private_debug_utils_strict_weak_ordering_check } +module std_private_algorithm_simd_utils [system] { header "__algorithm/simd_utils.h" } module std_private_algorithm_sort_heap [system] { header "__algorithm/sort_heap.h" } module std_private_algorithm_stable_partition [system] { header "__algorithm/stable_partition.h" } module std_private_algorithm_stable_sort [system] { header "__algorithm/stable_sort.h" } @@ -1251,6 +1255,8 @@ module std_private_debug_utils_strict_weak_ordering_check [system] { export std_private_type_traits_is_constant_evaluated } +module std_private_deque_fwd [system] { header "__fwd/deque.h" } + module std_private_exception_exception [system] { header "__exception/exception.h" } module std_private_exception_exception_ptr [system] { header "__exception/exception_ptr.h" @@ -1531,6 +1537,7 @@ module std_private_memory_concepts [system] { } module std_private_memory_construct_at [system] { header "__memory/construct_at.h" } module std_private_memory_destruct_n [system] { header "__memory/destruct_n.h" } +module std_private_memory_fwd [system] { header "__fwd/memory.h" } module std_private_memory_pointer_traits [system] { header "__memory/pointer_traits.h" } module std_private_memory_ranges_construct_at [system] { header "__memory/ranges_construct_at.h" } module std_private_memory_ranges_uninitialized_algorithms [system] { @@ -1596,6 +1603,8 @@ module std_private_numeric_transform_exclusive_scan [system] { header "__numeric module std_private_numeric_transform_inclusive_scan [system] { header "__numeric/transform_inclusive_scan.h" } module std_private_numeric_transform_reduce [system] { header "__numeric/transform_reduce.h" } +module std_private_queue_fwd [system] { header "__fwd/queue.h" } + module std_private_random_bernoulli_distribution [system] { header "__random/bernoulli_distribution.h" } module std_private_random_binomial_distribution [system] { header "__random/binomial_distribution.h" } module std_private_random_cauchy_distribution [system] { header "__random/cauchy_distribution.h" } @@ -1729,10 +1738,15 @@ module std_private_ranges_transform_view [system] { } module std_private_ranges_view_interface [system] { header "__ranges/view_interface.h" } module std_private_ranges_views [system] { header "__ranges/views.h" } -module std_private_ranges_zip_view [system] { header "__ranges/zip_view.h" } +module std_private_ranges_zip_view [system] { + header "__ranges/zip_view.h" + export std_private_utility_pair +} module std_private_span_span_fwd [system] { header "__fwd/span.h" } +module std_private_stack_fwd [system] { header "__fwd/stack.h" } + module std_private_stop_token_atomic_unique_lock [system] { header "__stop_token/atomic_unique_lock.h" } module std_private_stop_token_intrusive_list_view [system] { header "__stop_token/intrusive_list_view.h" } module std_private_stop_token_intrusive_shared_ptr [system] { header "__stop_token/intrusive_shared_ptr.h" } @@ -1799,20 +1813,22 @@ module std_private_thread_thread [system] { } module std_private_thread_timed_backoff_policy [system] { header "__thread/timed_backoff_policy.h" } -module std_private_tuple_find_index [system] { header "__tuple/find_index.h" } -module std_private_tuple_make_tuple_types [system] { header "__tuple/make_tuple_types.h" } -module std_private_tuple_pair_like [system] { - header "__tuple/pair_like.h" - export std_private_tuple_tuple_like -} -module std_private_tuple_sfinae_helpers [system] { header "__tuple/sfinae_helpers.h" } -module std_private_tuple_tuple_element [system] { header "__tuple/tuple_element.h" } -module std_private_tuple_tuple_fwd [system] { header "__fwd/tuple.h" } -module std_private_tuple_tuple_indices [system] { header "__tuple/tuple_indices.h" } -module std_private_tuple_tuple_like [system] { header "__tuple/tuple_like.h" } -module std_private_tuple_tuple_like_ext [system] { header "__tuple/tuple_like_ext.h" } -module std_private_tuple_tuple_size [system] { header "__tuple/tuple_size.h" } -module std_private_tuple_tuple_types [system] { header "__tuple/tuple_types.h" } +module std_private_tuple_find_index [system] { header "__tuple/find_index.h" } +module std_private_tuple_make_tuple_types [system] { header "__tuple/make_tuple_types.h" } +module std_private_tuple_tuple_like_no_subrange [system] { + header "__tuple/tuple_like_no_subrange.h" +} +module std_private_tuple_sfinae_helpers [system] { header "__tuple/sfinae_helpers.h" } +module std_private_tuple_tuple_element [system] { header "__tuple/tuple_element.h" } +module std_private_tuple_tuple_fwd [system] { header "__fwd/tuple.h" } +module std_private_tuple_tuple_indices [system] { header "__tuple/tuple_indices.h" } +module std_private_tuple_tuple_like [system] { + header "__tuple/tuple_like.h" + export * +} +module std_private_tuple_tuple_like_ext [system] { header "__tuple/tuple_like_ext.h" } +module std_private_tuple_tuple_size [system] { header "__tuple/tuple_size.h" } +module std_private_tuple_tuple_types [system] { header "__tuple/tuple_types.h" } module std_private_type_traits_add_const [system] { header "__type_traits/add_const.h" } module std_private_type_traits_add_cv [system] { header "__type_traits/add_cv.h" } @@ -1902,7 +1918,6 @@ module std_private_type_traits_is_core_convertible [system header "__type_traits/is_core_convertible.h" export std_private_type_traits_integral_constant } -module std_private_type_traits_is_default_constructible [system] { header "__type_traits/is_default_constructible.h" } module std_private_type_traits_is_destructible [system] { header "__type_traits/is_destructible.h" } module std_private_type_traits_is_empty [system] { header "__type_traits/is_empty.h" } module std_private_type_traits_is_enum [system] { @@ -1927,26 +1942,16 @@ module std_private_type_traits_is_literal_type [system module std_private_type_traits_is_member_function_pointer [system] { header "__type_traits/is_member_function_pointer.h" } module std_private_type_traits_is_member_object_pointer [system] { header "__type_traits/is_member_object_pointer.h" } module std_private_type_traits_is_member_pointer [system] { header "__type_traits/is_member_pointer.h" } -module std_private_type_traits_is_move_assignable [system] { header "__type_traits/is_move_assignable.h" } -module std_private_type_traits_is_move_constructible [system] { header "__type_traits/is_move_constructible.h" } module std_private_type_traits_is_nothrow_assignable [system] { header "__type_traits/is_nothrow_assignable.h" } -module std_private_type_traits_is_nothrow_constructible [system] { header "__type_traits/is_nothrow_constructible.h" } -module std_private_type_traits_is_nothrow_convertible [system] { header "__type_traits/is_nothrow_convertible.h" } -module std_private_type_traits_is_nothrow_copy_assignable [system] { header "__type_traits/is_nothrow_copy_assignable.h" } -module std_private_type_traits_is_nothrow_copy_constructible [system] { header "__type_traits/is_nothrow_copy_constructible.h" } -module std_private_type_traits_is_nothrow_default_constructible [system] { - header "__type_traits/is_nothrow_default_constructible.h" +module std_private_type_traits_is_nothrow_constructible [system] { + header "__type_traits/is_nothrow_constructible.h" export std_private_type_traits_integral_constant } +module std_private_type_traits_is_nothrow_convertible [system] { header "__type_traits/is_nothrow_convertible.h" } module std_private_type_traits_is_nothrow_destructible [system] { header "__type_traits/is_nothrow_destructible.h" export std_private_type_traits_is_destructible } -module std_private_type_traits_is_nothrow_move_assignable [system] { header "__type_traits/is_nothrow_move_assignable.h" } -module std_private_type_traits_is_nothrow_move_constructible [system] { - header "__type_traits/is_nothrow_move_constructible.h" - export std_private_type_traits_is_nothrow_constructible -} module std_private_type_traits_is_null_pointer [system] { header "__type_traits/is_null_pointer.h" export std_cstddef @@ -1985,14 +1990,9 @@ module std_private_type_traits_is_swappable [system module std_private_type_traits_is_trivial [system] { header "__type_traits/is_trivial.h" } module std_private_type_traits_is_trivially_assignable [system] { header "__type_traits/is_trivially_assignable.h" } module std_private_type_traits_is_trivially_constructible [system] { header "__type_traits/is_trivially_constructible.h" } -module std_private_type_traits_is_trivially_copy_assignable [system] { header "__type_traits/is_trivially_copy_assignable.h" } -module std_private_type_traits_is_trivially_copy_constructible [system] { header "__type_traits/is_trivially_copy_constructible.h" } module std_private_type_traits_is_trivially_copyable [system] { header "__type_traits/is_trivially_copyable.h" } -module std_private_type_traits_is_trivially_default_constructible [system] { header "__type_traits/is_trivially_default_constructible.h" } module std_private_type_traits_is_trivially_destructible [system] { header "__type_traits/is_trivially_destructible.h" } module std_private_type_traits_is_trivially_lexicographically_comparable [system] { header "__type_traits/is_trivially_lexicographically_comparable.h" } -module std_private_type_traits_is_trivially_move_assignable [system] { header "__type_traits/is_trivially_move_assignable.h" } -module std_private_type_traits_is_trivially_move_constructible [system] { header "__type_traits/is_trivially_move_constructible.h" } module std_private_type_traits_is_trivially_relocatable [system] { header "__type_traits/is_trivially_relocatable.h" } module std_private_type_traits_is_unbounded_array [system] { header "__type_traits/is_unbounded_array.h" } module std_private_type_traits_is_union [system] { header "__type_traits/is_union.h" } @@ -2097,3 +2097,5 @@ module std_private_utility_to_underlying [system] { header "__utility/t module std_private_utility_unreachable [system] { header "__utility/unreachable.h" } module std_private_variant_monostate [system] { header "__variant/monostate.h" } + +module std_private_vector_fwd [system] { header "__fwd/vector.h" } diff --git a/libcxx/include/mutex b/libcxx/include/mutex index ea56e3051908a7142504c8238c6c87261370c8ae..12fae9a88b9d7ebf6a004d1afc5ff5cadf56f57e 100644 --- a/libcxx/include/mutex +++ b/libcxx/include/mutex @@ -418,24 +418,6 @@ inline _LIBCPP_HIDE_FROM_ABI void lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... std::__lock_first(0, __l0, __l1, __l2, __l3...); } -template <class _L0> -inline _LIBCPP_HIDE_FROM_ABI void __unlock(_L0& __l0) { - __l0.unlock(); -} - -template <class _L0, class _L1> -inline _LIBCPP_HIDE_FROM_ABI void __unlock(_L0& __l0, _L1& __l1) { - __l0.unlock(); - __l1.unlock(); -} - -template <class _L0, class _L1, class _L2, class... _L3> -inline _LIBCPP_HIDE_FROM_ABI void __unlock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) { - __l0.unlock(); - __l1.unlock(); - std::__unlock(__l2, __l3...); -} - # endif // _LIBCPP_CXX03_LANG # if _LIBCPP_STD_VER >= 17 @@ -498,7 +480,7 @@ public: private: template <size_t... _Indx> _LIBCPP_HIDE_FROM_ABI static void __unlock_unpack(__tuple_indices<_Indx...>, _MutexTuple& __mt) { - std::__unlock(std::get<_Indx>(__mt)...); + (std::get<_Indx>(__mt).unlock(), ...); } _MutexTuple __t_; diff --git a/libcxx/include/new b/libcxx/include/new index 988f7a84422c84b1bbb627ba785c4667d19de9a1..5a245dc5ef4596ec6d7d1e4102da8a71bb8fdef6 100644 --- a/libcxx/include/new +++ b/libcxx/include/new @@ -86,7 +86,6 @@ void operator delete[](void* ptr, void*) noexcept; */ -#include <__availability> #include <__config> #include <__exception/exception.h> #include <__type_traits/is_function.h> diff --git a/libcxx/include/optional b/libcxx/include/optional index 99bfd0dd900d3a75dc0c2b15b5086131e0fb4f3f..a16e48502e25098b170cabb0de435dcd91568761 100644 --- a/libcxx/include/optional +++ b/libcxx/include/optional @@ -200,22 +200,16 @@ namespace std { #include <__type_traits/is_assignable.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> -#include <__type_traits/is_copy_assignable.h> -#include <__type_traits/is_copy_constructible.h> #include <__type_traits/is_destructible.h> -#include <__type_traits/is_move_assignable.h> -#include <__type_traits/is_move_constructible.h> -#include <__type_traits/is_nothrow_move_assignable.h> -#include <__type_traits/is_nothrow_move_constructible.h> +#include <__type_traits/is_nothrow_assignable.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_object.h> #include <__type_traits/is_reference.h> #include <__type_traits/is_scalar.h> #include <__type_traits/is_swappable.h> -#include <__type_traits/is_trivially_copy_assignable.h> -#include <__type_traits/is_trivially_copy_constructible.h> +#include <__type_traits/is_trivially_assignable.h> +#include <__type_traits/is_trivially_constructible.h> #include <__type_traits/is_trivially_destructible.h> -#include <__type_traits/is_trivially_move_assignable.h> -#include <__type_traits/is_trivially_move_constructible.h> #include <__type_traits/negation.h> #include <__type_traits/remove_const.h> #include <__type_traits/remove_cvref.h> @@ -1291,6 +1285,7 @@ _LIBCPP_POP_MACROS # include <concepts> # include <ctime> # include <iterator> +# include <limits> # include <memory> # include <ratio> # include <stdexcept> diff --git a/libcxx/include/queue b/libcxx/include/queue index 521a465713cd22e00456947c72e2109456617bb3..f94cd7671863fd74df5ed428724c6cd3ee118697 100644 --- a/libcxx/include/queue +++ b/libcxx/include/queue @@ -260,6 +260,8 @@ template <class T, class Container, class Compare> #include <__algorithm/ranges_copy.h> #include <__config> #include <__functional/operations.h> +#include <__fwd/deque.h> +#include <__fwd/queue.h> #include <__iterator/back_insert_iterator.h> #include <__iterator/iterator_traits.h> #include <__memory/uses_allocator.h> @@ -287,9 +289,6 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp, class _Container = deque<_Tp> > -class _LIBCPP_TEMPLATE_VIS queue; - template <class _Tp, class _Container> _LIBCPP_HIDE_FROM_ABI bool operator==(const queue<_Tp, _Container>& __x, const queue<_Tp, _Container>& __y); @@ -511,7 +510,7 @@ template <class _Tp, class _Container, class _Alloc> struct _LIBCPP_TEMPLATE_VIS uses_allocator<queue<_Tp, _Container>, _Alloc> : public uses_allocator<_Container, _Alloc> { }; -template <class _Tp, class _Container = vector<_Tp>, class _Compare = less<typename _Container::value_type> > +template <class _Tp, class _Container, class _Compare> class _LIBCPP_TEMPLATE_VIS priority_queue { public: typedef _Container container_type; diff --git a/libcxx/include/shared_mutex b/libcxx/include/shared_mutex index 38b559e8930fc56186932921d5dcab4d3518076c..9cc391db6fc5d94ee1373bd544fcbf302df9717c 100644 --- a/libcxx/include/shared_mutex +++ b/libcxx/include/shared_mutex @@ -128,7 +128,6 @@ template <class Mutex> # error "<shared_mutex> is not supported since libc++ has been configured without support for threads." #endif -#include <__availability> #include <__chrono/duration.h> #include <__chrono/steady_clock.h> #include <__chrono/time_point.h> diff --git a/libcxx/include/stack b/libcxx/include/stack index 4003792600a0043f7a8dd3889677c96684958ecb..08a392da6848dd8e345bf6c1d67ce190b60b5b57 100644 --- a/libcxx/include/stack +++ b/libcxx/include/stack @@ -115,6 +115,7 @@ template <class T, class Container> #include <__algorithm/ranges_copy.h> #include <__config> +#include <__fwd/stack.h> #include <__iterator/back_insert_iterator.h> #include <__iterator/iterator_traits.h> #include <__memory/uses_allocator.h> @@ -142,9 +143,6 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp, class _Container = deque<_Tp> > -class _LIBCPP_TEMPLATE_VIS stack; - template <class _Tp, class _Container> _LIBCPP_HIDE_FROM_ABI bool operator==(const stack<_Tp, _Container>& __x, const stack<_Tp, _Container>& __y); diff --git a/libcxx/include/stddef.h b/libcxx/include/stddef.h index 887776b150e49d717f2990701278f68c933edf3f..470b5408336c6d8999abbd87dfa7cd962d84d315 100644 --- a/libcxx/include/stddef.h +++ b/libcxx/include/stddef.h @@ -7,18 +7,6 @@ // //===----------------------------------------------------------------------===// -#if defined(__need_ptrdiff_t) || defined(__need_size_t) || defined(__need_wchar_t) || defined(__need_NULL) || \ - defined(__need_wint_t) - -# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -# pragma GCC system_header -# endif - -# include_next <stddef.h> - -#elif !defined(_LIBCPP_STDDEF_H) -# define _LIBCPP_STDDEF_H - /* stddef.h synopsis @@ -36,16 +24,19 @@ Types: */ -# include <__config> +#include <__config> + +// Note: This include is outside of header guards because we sometimes get included multiple times +// with different defines and the underlying <stddef.h> will know how to deal with that. +#include_next <stddef.h> + +#ifndef _LIBCPP_STDDEF_H +# define _LIBCPP_STDDEF_H # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header # endif -# if __has_include_next(<stddef.h>) -# include_next <stddef.h> -# endif - # ifdef __cplusplus typedef decltype(nullptr) nullptr_t; # endif diff --git a/libcxx/include/string b/libcxx/include/string index ca5b3fa6a01472e1b407be921a34ab319a3fac95..a456f8cb80ee35b8e9b6d52a5992da21a2e3e106 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -603,8 +603,8 @@ basic_string<char32_t> operator""s( const char32_t *str, size_t len ); #include <__type_traits/is_allocator.h> #include <__type_traits/is_array.h> #include <__type_traits/is_convertible.h> -#include <__type_traits/is_nothrow_default_constructible.h> -#include <__type_traits/is_nothrow_move_assignable.h> +#include <__type_traits/is_nothrow_assignable.h> +#include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_same.h> #include <__type_traits/is_standard_layout.h> #include <__type_traits/is_trivial.h> diff --git a/libcxx/include/thread b/libcxx/include/thread index ed70bde76094aef49105cf7dba73ca8a6c1e0f88..68ce63bd0143df57e87d5c3a7ececa4aaa100a1f 100644 --- a/libcxx/include/thread +++ b/libcxx/include/thread @@ -92,7 +92,6 @@ void sleep_for(const chrono::duration<Rep, Period>& rel_time); # error "<thread> is not supported since libc++ has been configured without support for threads." #endif -#include <__availability> #include <__thread/formatter.h> #include <__thread/jthread.h> #include <__thread/support.h> diff --git a/libcxx/include/tuple b/libcxx/include/tuple index e63e4e25a7d2bd7ad9ea7276590d20f3ae5b9f88..c7fc5509a0f8087599affc7e0cb84eddf746d5c2 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -210,6 +210,7 @@ template <class... Types> #include <__config> #include <__functional/invoke.h> #include <__fwd/array.h> +#include <__fwd/pair.h> #include <__fwd/tuple.h> #include <__memory/allocator_arg_t.h> #include <__memory/uses_allocator.h> @@ -232,20 +233,11 @@ template <class... Types> #include <__type_traits/is_assignable.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> -#include <__type_traits/is_copy_assignable.h> -#include <__type_traits/is_copy_constructible.h> -#include <__type_traits/is_default_constructible.h> #include <__type_traits/is_empty.h> #include <__type_traits/is_final.h> #include <__type_traits/is_implicitly_default_constructible.h> -#include <__type_traits/is_move_assignable.h> -#include <__type_traits/is_move_constructible.h> #include <__type_traits/is_nothrow_assignable.h> #include <__type_traits/is_nothrow_constructible.h> -#include <__type_traits/is_nothrow_copy_assignable.h> -#include <__type_traits/is_nothrow_copy_constructible.h> -#include <__type_traits/is_nothrow_default_constructible.h> -#include <__type_traits/is_nothrow_move_assignable.h> #include <__type_traits/is_reference.h> #include <__type_traits/is_same.h> #include <__type_traits/is_swappable.h> @@ -259,7 +251,6 @@ template <class... Types> #include <__utility/forward.h> #include <__utility/integer_sequence.h> #include <__utility/move.h> -#include <__utility/pair.h> #include <__utility/piecewise_construct.h> #include <__utility/swap.h> #include <cstddef> @@ -1357,21 +1348,7 @@ tuple_cat(_Tuple0&& __t0, _Tuples&&... __tpls) { template <class... _Tp, class _Alloc> struct _LIBCPP_TEMPLATE_VIS uses_allocator<tuple<_Tp...>, _Alloc> : true_type {}; -template <class _T1, class _T2> -template <class... _Args1, class... _Args2, size_t... _I1, size_t... _I2> -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_T1, _T2>::pair( - piecewise_construct_t, - tuple<_Args1...>& __first_args, - tuple<_Args2...>& __second_args, - __tuple_indices<_I1...>, - __tuple_indices<_I2...>) - : first(std::forward<_Args1>(std::get<_I1>(__first_args))...), - second(std::forward<_Args2>(std::get<_I2>(__second_args))...) {} - # if _LIBCPP_STD_VER >= 17 -template <class _Tp> -inline constexpr size_t tuple_size_v = tuple_size<_Tp>::value; - # define _LIBCPP_NOEXCEPT_RETURN(...) \ noexcept(noexcept(__VA_ARGS__)) { return __VA_ARGS__; } @@ -1389,15 +1366,41 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) apply(_Fn&& __f, _Tuple&& std::forward<_Tuple>(__t), typename __make_tuple_indices<tuple_size_v<remove_reference_t<_Tuple>>>::type{})) +#if _LIBCPP_STD_VER >= 20 template <class _Tp, class _Tuple, size_t... _Idx> inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>) + noexcept(noexcept(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...))) + requires is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...> { + return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); +} +#else +template <class _Tp, class _Tuple, size_t... _Idx> +inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>, + enable_if_t<is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>> * = nullptr) _LIBCPP_NOEXCEPT_RETURN(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...)) +#endif // _LIBCPP_STD_VER >= 20 + +template <class _Tp, class _Tuple, + class _Seq = typename __make_tuple_indices<tuple_size_v<remove_reference_t<_Tuple>>>::type, class = void> +inline constexpr bool __can_make_from_tuple = false; +template <class _Tp, class _Tuple, size_t... _Idx> +inline constexpr bool __can_make_from_tuple<_Tp, _Tuple, __tuple_indices<_Idx...>, + enable_if_t<is_constructible_v<_Tp, decltype(std::get<_Idx>(std::declval<_Tuple>()))...>>> = true; + +// Based on LWG3528(https://wg21.link/LWG3528) and http://eel.is/c++draft/description#structure.requirements-9, +// the standard allows to impose requirements, we constraint std::make_from_tuple to make std::make_from_tuple +// SFINAE friendly and also avoid worse diagnostic messages. We still keep the constraints of std::__make_from_tuple_impl +// so that std::__make_from_tuple_impl will have the same advantages when used alone. +#if _LIBCPP_STD_VER >= 20 template <class _Tp, class _Tuple> + requires __can_make_from_tuple<_Tp, _Tuple> // strengthen +#else +template <class _Tp, class _Tuple, class = enable_if_t<__can_make_from_tuple<_Tp, _Tuple>>> // strengthen +#endif // _LIBCPP_STD_VER >= 20 inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp make_from_tuple(_Tuple&& __t) _LIBCPP_NOEXCEPT_RETURN(std::__make_from_tuple_impl<_Tp>( std::forward<_Tuple>(__t), typename __make_tuple_indices<tuple_size_v<remove_reference_t<_Tuple>>>::type{})) - # undef _LIBCPP_NOEXCEPT_RETURN # endif // _LIBCPP_STD_VER >= 17 diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits index 54c8abec340c4dc7f5cf74ebfe4100451f712f2f..10f9b881c0e4a3cc6487291c4cf88aeeed6575b0 100644 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -458,9 +458,6 @@ namespace std #include <__type_traits/is_constant_evaluated.h> #include <__type_traits/is_constructible.h> #include <__type_traits/is_convertible.h> -#include <__type_traits/is_copy_assignable.h> -#include <__type_traits/is_copy_constructible.h> -#include <__type_traits/is_default_constructible.h> #include <__type_traits/is_destructible.h> #include <__type_traits/is_empty.h> #include <__type_traits/is_enum.h> @@ -474,17 +471,10 @@ namespace std #include <__type_traits/is_member_function_pointer.h> #include <__type_traits/is_member_object_pointer.h> #include <__type_traits/is_member_pointer.h> -#include <__type_traits/is_move_assignable.h> -#include <__type_traits/is_move_constructible.h> #include <__type_traits/is_nothrow_assignable.h> #include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_nothrow_convertible.h> -#include <__type_traits/is_nothrow_copy_assignable.h> -#include <__type_traits/is_nothrow_copy_constructible.h> -#include <__type_traits/is_nothrow_default_constructible.h> #include <__type_traits/is_nothrow_destructible.h> -#include <__type_traits/is_nothrow_move_assignable.h> -#include <__type_traits/is_nothrow_move_constructible.h> #include <__type_traits/is_null_pointer.h> #include <__type_traits/is_object.h> #include <__type_traits/is_pod.h> @@ -503,13 +493,8 @@ namespace std #include <__type_traits/is_trivial.h> #include <__type_traits/is_trivially_assignable.h> #include <__type_traits/is_trivially_constructible.h> -#include <__type_traits/is_trivially_copy_assignable.h> -#include <__type_traits/is_trivially_copy_constructible.h> #include <__type_traits/is_trivially_copyable.h> -#include <__type_traits/is_trivially_default_constructible.h> #include <__type_traits/is_trivially_destructible.h> -#include <__type_traits/is_trivially_move_assignable.h> -#include <__type_traits/is_trivially_move_constructible.h> #include <__type_traits/is_unbounded_array.h> #include <__type_traits/is_union.h> #include <__type_traits/is_unsigned.h> diff --git a/libcxx/include/typeinfo b/libcxx/include/typeinfo index dafc7b89248eca489b94e87baa82801e1931e8b1..1ae075edd4b3c39175f966f2c8bf2317d5817e3f 100644 --- a/libcxx/include/typeinfo +++ b/libcxx/include/typeinfo @@ -56,7 +56,6 @@ public: */ -#include <__availability> #include <__config> #include <__exception/exception.h> #include <__type_traits/is_constant_evaluated.h> diff --git a/libcxx/include/variant b/libcxx/include/variant index d1eea52f0a93010c5abdb5bb12547d3c317b77ae..1b5e84e95479534de65e739a8106a1c169039ec3 100644 --- a/libcxx/include/variant +++ b/libcxx/include/variant @@ -228,19 +228,20 @@ namespace std { #include <__type_traits/add_pointer.h> #include <__type_traits/add_volatile.h> #include <__type_traits/common_type.h> +#include <__type_traits/conjunction.h> #include <__type_traits/dependent_type.h> #include <__type_traits/is_array.h> -#include <__type_traits/is_default_constructible.h> +#include <__type_traits/is_constructible.h> #include <__type_traits/is_destructible.h> #include <__type_traits/is_nothrow_assignable.h> -#include <__type_traits/is_nothrow_move_constructible.h> -#include <__type_traits/is_trivially_copy_assignable.h> -#include <__type_traits/is_trivially_copy_constructible.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_reference.h> +#include <__type_traits/is_trivially_assignable.h> +#include <__type_traits/is_trivially_constructible.h> #include <__type_traits/is_trivially_destructible.h> -#include <__type_traits/is_trivially_move_assignable.h> -#include <__type_traits/is_trivially_move_constructible.h> #include <__type_traits/is_void.h> #include <__type_traits/remove_const.h> +#include <__type_traits/remove_cvref.h> #include <__type_traits/type_identity.h> #include <__type_traits/void_t.h> #include <__utility/declval.h> @@ -347,13 +348,13 @@ inline constexpr size_t variant_npos = static_cast<size_t>(-1); template <size_t _NumAlternatives> _LIBCPP_HIDE_FROM_ABI constexpr auto __choose_index_type() { -#ifdef _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION +# ifdef _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION if constexpr (_NumAlternatives < numeric_limits<unsigned char>::max()) return static_cast<unsigned char>(0); else if constexpr (_NumAlternatives < numeric_limits<unsigned short>::max()) return static_cast<unsigned short>(0); else -#endif // _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION +# endif // _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION return static_cast<unsigned int>(0); } @@ -1085,13 +1086,9 @@ struct __narrowing_check { }; template <class _Dest, class _Source> -using __check_for_narrowing _LIBCPP_NODEBUG = typename _If< -# ifdef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT - false && -# endif - is_arithmetic<_Dest>::value, - __narrowing_check, - __no_narrowing_check >::template _Apply<_Dest, _Source>; +using __check_for_narrowing _LIBCPP_NODEBUG = + typename _If< is_arithmetic<_Dest>::value, __narrowing_check, __no_narrowing_check >::template _Apply<_Dest, + _Source>; template <class _Tp, size_t _Idx> struct __overload { @@ -1099,24 +1096,6 @@ struct __overload { auto operator()(_Tp, _Up&&) const -> __check_for_narrowing<_Tp, _Up>; }; -// TODO(LLVM-19): Remove all occurrences of this macro. -# ifdef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT -template <class _Tp, size_t> -struct __overload_bool { - template <class _Up, class _Ap = __remove_cvref_t<_Up>> - auto operator()(bool, _Up&&) const -> enable_if_t<is_same_v<_Ap, bool>, __type_identity<_Tp>>; -}; - -template <size_t _Idx> -struct __overload<bool, _Idx> : __overload_bool<bool, _Idx> {}; -template <size_t _Idx> -struct __overload<bool const, _Idx> : __overload_bool<bool const, _Idx> {}; -template <size_t _Idx> -struct __overload<bool volatile, _Idx> : __overload_bool<bool volatile, _Idx> {}; -template <size_t _Idx> -struct __overload<bool const volatile, _Idx> : __overload_bool<bool const volatile, _Idx> {}; -# endif - template <class... _Bases> struct __all_overloads : _Bases... { void operator()() const; diff --git a/libcxx/include/vector b/libcxx/include/vector index 89cbdf0b3ff74738cac98ef619433e0e765d29ff..1defc43a52478b79ce77b3b69119eb68eb9ddb17 100644 --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -325,6 +325,7 @@ template<class T, class charT> requires is-vector-bool-reference<T> // Since C++ #include <__format/formatter_bool.h> #include <__functional/hash.h> #include <__functional/unary_function.h> +#include <__fwd/vector.h> #include <__iterator/advance.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> @@ -346,7 +347,7 @@ template<class T, class charT> requires is-vector-bool-reference<T> // Since C++ #include <__split_buffer> #include <__type_traits/is_allocator.h> #include <__type_traits/is_constructible.h> -#include <__type_traits/is_nothrow_move_assignable.h> +#include <__type_traits/is_nothrow_assignable.h> #include <__type_traits/noexcept_move_assign_container.h> #include <__type_traits/type_identity.h> #include <__utility/exception_guard.h> @@ -357,7 +358,6 @@ template<class T, class charT> requires is-vector-bool-reference<T> // Since C++ #include <__utility/swap.h> #include <climits> #include <cstring> -#include <iosfwd> // for forward declaration of vector #include <limits> #include <stdexcept> #include <version> @@ -2989,7 +2989,9 @@ _LIBCPP_POP_MACROS # include <atomic> # include <concepts> # include <cstdlib> +# include <iosfwd> # include <locale> +# include <tuple> # include <type_traits> # include <typeinfo> # include <utility> diff --git a/libcxx/modules/CMakeLists.txt b/libcxx/modules/CMakeLists.txt index 0dea8cfca94ac3be7e35b76d8d8d9b6ee4fc0b59..d47d19a4755317628184c8dd68bfa1b234e06a22 100644 --- a/libcxx/modules/CMakeLists.txt +++ b/libcxx/modules/CMakeLists.txt @@ -206,9 +206,20 @@ add_custom_target(generate-cxx-modules # Configure the modules manifest. # Use the relative path between the installation and the module in the json # file. This allows moving the entire installation to a different location. +if("${CMAKE_INSTALL_PREFIX}" STREQUAL "") + set(BASE_DIRECTORY "/") +else() + set(BASE_DIRECTORY ${CMAKE_INSTALL_PREFIX}) +endif() +cmake_path(ABSOLUTE_PATH LIBCXX_INSTALL_LIBRARY_DIR + BASE_DIRECTORY ${BASE_DIRECTORY} + OUTPUT_VARIABLE ABS_LIBRARY_DIR) +cmake_path(ABSOLUTE_PATH LIBCXX_INSTALL_MODULES_DIR + BASE_DIRECTORY ${BASE_DIRECTORY} + OUTPUT_VARIABLE ABS_MODULES_DIR) file(RELATIVE_PATH LIBCXX_MODULE_RELATIVE_PATH - ${CMAKE_INSTALL_PREFIX}/${LIBCXX_INSTALL_LIBRARY_DIR} - ${CMAKE_INSTALL_PREFIX}/${LIBCXX_INSTALL_MODULES_DIR}) + ${ABS_LIBRARY_DIR} + ${ABS_MODULES_DIR}) configure_file( "modules.json.in" "${LIBCXX_LIBRARY_DIR}/libc++.modules.json" diff --git a/libcxx/modules/CMakeLists.txt.in b/libcxx/modules/CMakeLists.txt.in index e332d70cc163335fe6f010aa062f3fbe14149e74..c35f6fecb1fd760073fc1d0edee18c7f72dae90c 100644 --- a/libcxx/modules/CMakeLists.txt.in +++ b/libcxx/modules/CMakeLists.txt.in @@ -50,10 +50,15 @@ endif() target_compile_options(std PUBLIC -nostdinc++ + @LIBCXX_COMPILE_FLAGS@ +) +target_compile_options(std + PRIVATE -Wno-reserved-module-identifier -Wno-reserved-user-defined-literal - @LIBCXX_COMPILE_FLAGS@ ) +target_link_options(std PUBLIC -nostdlib++ -Wl,-rpath,@LIBCXX_LIBRARY_DIR@ -L@LIBCXX_LIBRARY_DIR@) +target_link_libraries(std c++) set_target_properties(std PROPERTIES OUTPUT_NAME "c++std" @@ -67,7 +72,7 @@ target_sources(std.compat std.compat.cppm ) -target_include_directories(std.compat SYSTEM PRIVATE @LIBCXX_CONFIGURED_INCLUDE_DIRS@) +target_include_directories(std.compat SYSTEM PUBLIC @LIBCXX_CONFIGURED_INCLUDE_DIRS@) if (NOT @LIBCXX_ENABLE_EXCEPTIONS@) target_compile_options(std.compat PUBLIC -fno-exceptions) @@ -76,13 +81,16 @@ endif() target_compile_options(std.compat PUBLIC -nostdinc++ + @LIBCXX_COMPILE_FLAGS@ +) +target_compile_options(std.compat + PRIVATE -Wno-reserved-module-identifier -Wno-reserved-user-defined-literal - -fmodule-file=std=${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/std.dir/std.pcm - @LIBCXX_COMPILE_FLAGS@ ) set_target_properties(std.compat PROPERTIES OUTPUT_NAME "c++std.compat" ) add_dependencies(std.compat std) +target_link_libraries(std.compat PUBLIC std c++) diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt index 07ffc8bfdaae3d690fa7c325272e8042d87c2f74..1110a79ddcacd511e32a7fd6913f195561a9d3a7 100644 --- a/libcxx/src/CMakeLists.txt +++ b/libcxx/src/CMakeLists.txt @@ -301,7 +301,10 @@ if (LIBCXX_ENABLE_STATIC) # then its code shouldn't declare them with hidden visibility. They might # actually be provided by a shared library at link time. if (LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS) - append_flags_if_supported(CXX_STATIC_LIBRARY_FLAGS -fvisibility-global-new-delete-hidden) + append_flags_if_supported(CXX_STATIC_LIBRARY_FLAGS -fvisibility-global-new-delete=force-hidden) + if (NOT CXX_SUPPORTS_FVISIBILITY_GLOBAL_NEW_DELETE_EQ_FORCE_HIDDEN_FLAG) + append_flags_if_supported(CXX_STATIC_LIBRARY_FLAGS -fvisibility-global-new-delete-hidden) + endif() endif() target_compile_options(cxx_static PRIVATE ${CXX_STATIC_LIBRARY_FLAGS}) # _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS can be defined in __config_site diff --git a/libcxx/src/include/tzdb/tzdb_list_private.h b/libcxx/src/include/tzdb/tzdb_list_private.h index f43d7d8ea772be9a4be9e6368bbb936259e3cd51..969b2b9f8a9f63ada123704c35dc7327af93f1e2 100644 --- a/libcxx/src/include/tzdb/tzdb_list_private.h +++ b/libcxx/src/include/tzdb/tzdb_list_private.h @@ -54,14 +54,14 @@ public: using const_iterator = tzdb_list::const_iterator; - const tzdb& front() const noexcept { + const tzdb& __front() const noexcept { #ifndef _LIBCPP_HAS_NO_THREADS shared_lock __lock{__mutex_}; #endif return __tzdb_.front(); } - const_iterator erase_after(const_iterator __p) { + const_iterator __erase_after(const_iterator __p) { #ifndef _LIBCPP_HAS_NO_THREADS unique_lock __lock{__mutex_}; #endif @@ -70,20 +70,17 @@ public: return __tzdb_.erase_after(__p); } - const_iterator begin() const noexcept { + const_iterator __begin() const noexcept { #ifndef _LIBCPP_HAS_NO_THREADS shared_lock __lock{__mutex_}; #endif return __tzdb_.begin(); } - const_iterator end() const noexcept { + const_iterator __end() const noexcept { // forward_list<T>::end does not access the list, so no need to take a lock. return __tzdb_.end(); } - const_iterator cbegin() const noexcept { return begin(); } - const_iterator cend() const noexcept { return end(); } - private: // Loads the tzdbs // pre: The caller ensures the locking, if needed, is done. diff --git a/libcxx/src/random.cpp b/libcxx/src/random.cpp index c7073c54da6b55b1e9379be3698a7ba224d10d6a..93590af310e51a9f9197e08ebd7b0723f53ffefe 100644 --- a/libcxx/src/random.cpp +++ b/libcxx/src/random.cpp @@ -79,8 +79,10 @@ unsigned random_device::operator()() { char* p = reinterpret_cast<char*>(&r); while (n > 0) { ssize_t s = read(__f_, p, n); + _LIBCPP_SUPPRESS_DEPRECATED_PUSH if (s == 0) - __throw_system_error(ENODATA, "random_device got EOF"); + __throw_system_error(ENODATA, "random_device got EOF"); // TODO ENODATA -> ENOMSG + _LIBCPP_SUPPRESS_DEPRECATED_POP if (s == -1) { if (errno != EINTR) __throw_system_error(errno, "random_device got an unexpected error"); diff --git a/libcxx/src/tzdb_list.cpp b/libcxx/src/tzdb_list.cpp index d3ee8b58f98bf2f06280f77f65bb783171e433c0..b99c30a9b9e6e9a22f3079cf7bd23c949f88244e 100644 --- a/libcxx/src/tzdb_list.cpp +++ b/libcxx/src/tzdb_list.cpp @@ -18,26 +18,24 @@ namespace chrono { _LIBCPP_EXPORTED_FROM_ABI tzdb_list::~tzdb_list() { delete __impl_; } -_LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI const tzdb& tzdb_list::front() const noexcept { - return __impl_->front(); -} +[[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI const tzdb& tzdb_list::__front() const noexcept { return __impl_->__front(); } -_LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::erase_after(const_iterator __p) { - return __impl_->erase_after(__p); +_LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::__erase_after(const_iterator __p) { + return __impl_->__erase_after(__p); } -_LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::begin() const noexcept { - return __impl_->begin(); +[[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::__begin() const noexcept { + return __impl_->__begin(); } -_LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::end() const noexcept { - return __impl_->end(); +[[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::__end() const noexcept { + return __impl_->__end(); } -_LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::cbegin() const noexcept { - return __impl_->cbegin(); +[[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::__cbegin() const noexcept { + return __impl_->__begin(); } -_LIBCPP_NODISCARD_EXT _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::cend() const noexcept { - return __impl_->cend(); +[[nodiscard]] _LIBCPP_EXPORTED_FROM_ABI tzdb_list::const_iterator tzdb_list::__cend() const noexcept { + return __impl_->__end(); } } // namespace chrono diff --git a/libcxx/test/libcxx/containers/sequences/vector/robust_against_adl.pass.cpp b/libcxx/test/libcxx/containers/sequences/vector/robust_against_adl.pass.cpp index 83f90ac4184bf179a3fbeb3f86f9a277a37be95d..9c780ae98d1e8409ab2528dc403d4e448904d388 100644 --- a/libcxx/test/libcxx/containers/sequences/vector/robust_against_adl.pass.cpp +++ b/libcxx/test/libcxx/containers/sequences/vector/robust_against_adl.pass.cpp @@ -31,7 +31,8 @@ struct MyAlloc { int main(int, char**) { std::vector<bool, MyAlloc<bool>> vb; - std::vector<bool, MyAlloc<bool>> wb(100); + // std::fill_n triggers ADL because __bit_iterator has the container type as a template argument + // std::vector<bool, MyAlloc<bool>> wb(100); std::vector<int, MyAlloc<int>> v; std::vector<int, MyAlloc<int>> w(100); diff --git a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/address.cxx2a.pass.cpp b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/address.cxx20.pass.cpp similarity index 52% rename from libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/address.cxx2a.pass.cpp rename to libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/address.cxx20.pass.cpp index 59657ca46a146d74fe0c67b6786d41e21bca6052..d9a65eee4c130b4383b8fe7d9eec0a5630f06180 100644 --- a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/address.cxx2a.pass.cpp +++ b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/address.cxx20.pass.cpp @@ -12,11 +12,9 @@ // pointer address(reference x) const; // const_pointer address(const_reference x) const; -// In C++20, parts of std::allocator<T> have been removed. -// However, for backwards compatibility, if _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS -// is defined before including <memory>, then removed members will be restored. +// Removed in C++20, deprecated in C++17. -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS +// REQUIRES: c++03 || c++11 || c++14 || c++17 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS #include <memory> @@ -25,25 +23,22 @@ #include "test_macros.h" template <class T> -void test_address() -{ - T* tp = new T(); - const T* ctp = tp; - const std::allocator<T> a; - assert(a.address(*tp) == tp); - assert(a.address(*ctp) == tp); - delete tp; +void test_address() { + T* tp = new T(); + const T* ctp = tp; + const std::allocator<T> a; + assert(a.address(*tp) == tp); + assert(a.address(*ctp) == tp); + delete tp; } -struct A -{ - void operator&() const {} +struct A { + void operator&() const {} }; -int main(int, char**) -{ - test_address<int>(); - test_address<A>(); +int main(int, char**) { + test_address<int>(); + test_address<A>(); return 0; } diff --git a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/address.cxx20.verify.cpp b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/address.cxx20.verify.cpp new file mode 100644 index 0000000000000000000000000000000000000000..21fd4d23449b519f72876de2674d66f8f8193994 --- /dev/null +++ b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/address.cxx20.verify.cpp @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// <memory> + +// allocator: +// pointer address(reference x) const; +// const_pointer address(const_reference x) const; + +// In C++20, parts of std::allocator<T> have been removed. +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +#include <memory> +#include <cassert> + +#include "test_macros.h" + +template <class T> +void test_address() { + T* tp = new T(); + const T* ctp = tp; + const std::allocator<T> a; + assert(a.address(*tp) == tp); // expected-error 2 {{no member}} + assert(a.address(*ctp) == tp); // expected-error 2 {{no member}} + delete tp; +} + +struct A { + void operator&() const {} +}; + +int main(int, char**) { + test_address<int>(); + test_address<A>(); + + return 0; +} diff --git a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/address.depr_in_cxx17.verify.cpp b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/address.depr_in_cxx17.verify.cpp index 83d059a838ffb7086af10e022c521c2b5200e1ea..4098bdb2ee9252127cd27211cf2fbe60b79c29af 100644 --- a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/address.depr_in_cxx17.verify.cpp +++ b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/address.depr_in_cxx17.verify.cpp @@ -14,9 +14,7 @@ // Deprecated in C++17 -// UNSUPPORTED: c++03, c++11, c++14 - -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS -Wno-deprecated-pragma +// REQUIRES: c++17 #include <memory> diff --git a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.cxx2a.pass.cpp b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.cxx20.pass.cpp similarity index 82% rename from libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.cxx2a.pass.cpp rename to libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.cxx20.pass.cpp index f2fb606ee6dbcc6e90eb5e931cda276ba72d0608..8fc6628ebfba2e776cd70ba12be52578e1139aa1 100644 --- a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.cxx2a.pass.cpp +++ b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.cxx20.pass.cpp @@ -11,17 +11,18 @@ // allocator: // T* allocate(size_t n, const void* hint); -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS +// Removed in C++20, deprecated in C++17. + +// REQUIRES: c++03 || c++11 || c++14 || c++17 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS #include <memory> #include <cassert> -#include <cstddef> // for std::max_align_t +#include <cstddef> // for std::max_align_t #include "test_macros.h" #include "count_new.h" - #ifdef TEST_HAS_NO_ALIGNED_ALLOCATION static const bool UsingAlignedNew = false; #else @@ -36,7 +37,6 @@ static const std::size_t MaxAligned = std::alignment_of<std::max_align_t>::value static const std::size_t OverAligned = MaxAligned * 2; - template <std::size_t Align> struct TEST_ALIGNAS(Align) AlignedType { char data; @@ -48,7 +48,6 @@ struct TEST_ALIGNAS(Align) AlignedType { template <std::size_t Align> int AlignedType<Align>::constructed = 0; - template <std::size_t Align> void test_aligned() { typedef AlignedType<Align> T; @@ -56,11 +55,11 @@ void test_aligned() { globalMemCounter.reset(); std::allocator<T> a; const bool IsOverAlignedType = Align > MaxAligned; - const bool ExpectAligned = IsOverAlignedType && UsingAlignedNew; + const bool ExpectAligned = IsOverAlignedType && UsingAlignedNew; { - globalMemCounter.last_new_size = 0; + globalMemCounter.last_new_size = 0; globalMemCounter.last_new_align = 0; - T* ap2 = a.allocate(11, (const void*)5); + T* ap2 = a.allocate(11, (const void*)5); DoNotOptimize(ap2); assert(globalMemCounter.checkOutstandingNewEq(1)); assert(globalMemCounter.checkNewCalledEq(1)); @@ -80,14 +79,14 @@ void test_aligned() { } int main(int, char**) { - test_aligned<1>(); - test_aligned<2>(); - test_aligned<4>(); - test_aligned<8>(); - test_aligned<16>(); - test_aligned<MaxAligned>(); - test_aligned<OverAligned>(); - test_aligned<OverAligned * 2>(); + test_aligned<1>(); + test_aligned<2>(); + test_aligned<4>(); + test_aligned<8>(); + test_aligned<16>(); + test_aligned<MaxAligned>(); + test_aligned<OverAligned>(); + test_aligned<OverAligned * 2>(); return 0; } diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cons/ctor.iter.explicit.verify.cpp b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.cxx20.verify.cpp similarity index 52% rename from libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cons/ctor.iter.explicit.verify.cpp rename to libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.cxx20.verify.cpp index 6440e284f6a016f8e7f9d1d6c0ac2910dff2fe6d..bf02c7570d39a2fbc699beb28e47e25cf8020971 100644 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cons/ctor.iter.explicit.verify.cpp +++ b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.cxx20.verify.cpp @@ -6,17 +6,18 @@ // //===----------------------------------------------------------------------===// -// <iterator> +// UNSUPPORTED: c++03, c++11, c++14, c++17 -// __unconstrained_reverse_iterator +// <memory> -// explicit __unconstrained_reverse_iterator(Iter x); +// allocator: +// T* allocate(size_t n, const void* hint); -// test explicitness +// Removed in C++20. -#include <iterator> +#include <memory> void f() { - char const* it = ""; - std::__unconstrained_reverse_iterator<char const*> r = it; // expected-error{{no viable conversion from 'const char *' to 'std::__unconstrained_reverse_iterator<const char *>'}} + std::allocator<int> a; + a.allocate(3, nullptr); // expected-error {{too many arguments to function call}} } diff --git a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.cxx2a.verify.cpp b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.cxx2a.verify.cpp deleted file mode 100644 index 2289cd6cd40448b5d22e9a7ce7075b2ca3f574bb..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.cxx2a.verify.cpp +++ /dev/null @@ -1,28 +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 -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14, c++17 - -// <memory> - -// allocator: -// T* allocate(size_t n, const void* hint); - -// In C++20, parts of std::allocator<T> have been removed. -// However, for backwards compatibility, if _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS -// is defined before including <memory>, then removed members will be restored. - -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS - -#include <memory> - -void f() { - std::allocator<int> a; - a.allocate(3, nullptr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} -} diff --git a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.depr_in_cxx17.verify.cpp b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.depr_in_cxx17.verify.cpp index 8b2e862e9503e958ffd160b3c34fbe93ab24e466..8629df3c41645bc733610ae4541b4e19fa9ede56 100644 --- a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.depr_in_cxx17.verify.cpp +++ b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.depr_in_cxx17.verify.cpp @@ -13,9 +13,7 @@ // Deprecated in C++17 -// UNSUPPORTED: c++03, c++11, c++14 - -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS -Wno-deprecated-pragma +// REQUIRES: c++17 #include <memory> diff --git a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/construct.cxx2a.pass.cpp b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/construct.cxx20.pass.cpp similarity index 75% rename from libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/construct.cxx2a.pass.cpp rename to libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/construct.cxx20.pass.cpp index d3a7dadbbe118c4b0f1f90c7cf87f10822dfab30..9a37cf8af8e69bb702fd9d5b5631ff35b4469c0a 100644 --- a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/construct.cxx2a.pass.cpp +++ b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/construct.cxx20.pass.cpp @@ -11,12 +11,10 @@ // allocator: // template <class... Args> void construct(pointer p, Args&&... args); -// In C++20, parts of std::allocator<T> have been removed. -// However, for backwards compatibility, if _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS -// is defined before including <memory>, then removed members will be restored. - -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS +// In C++20, parts of std::allocator<T> have been removed. +// In C++17, they were deprecated. // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS +// REQUIRES: c++03 || c++11 || c++14 || c++17 #include <memory> #include <cassert> @@ -26,42 +24,39 @@ int A_constructed = 0; -struct A -{ - int data; - A() {++A_constructed;} +struct A { + int data; + A() { ++A_constructed; } - A(const A&) {++A_constructed;} + A(const A&) { ++A_constructed; } - explicit A(int) {++A_constructed;} - A(int, int*) {++A_constructed;} + explicit A(int) { ++A_constructed; } + A(int, int*) { ++A_constructed; } - ~A() {--A_constructed;} + ~A() { --A_constructed; } }; int move_only_constructed = 0; #if TEST_STD_VER >= 11 -class move_only -{ - move_only(const move_only&) = delete; - move_only& operator=(const move_only&)= delete; +class move_only { + move_only(const move_only&) = delete; + move_only& operator=(const move_only&) = delete; public: - move_only(move_only&&) {++move_only_constructed;} - move_only& operator=(move_only&&) {return *this;} + move_only(move_only&&) { ++move_only_constructed; } + move_only& operator=(move_only&&) { return *this; } - move_only() {++move_only_constructed;} - ~move_only() {--move_only_constructed;} + move_only() { ++move_only_constructed; } + ~move_only() { --move_only_constructed; } public: - int data; // unused other than to make sizeof(move_only) == sizeof(int). - // but public to suppress "-Wunused-private-field" + int data; // unused other than to make sizeof(move_only) == sizeof(int). + // but public to suppress "-Wunused-private-field" }; #endif // TEST_STD_VER >= 11 -int main(int, char**) -{ +int main(int, char**) { globalMemCounter.reset(); { std::allocator<A> a; @@ -69,7 +64,7 @@ int main(int, char**) assert(A_constructed == 0); globalMemCounter.last_new_size = 0; - A* ap = a.allocate(3); + A* ap = a.allocate(3); DoNotOptimize(ap); assert(globalMemCounter.checkOutstandingNewEq(1)); assert(globalMemCounter.checkLastNewSizeEq(3 * sizeof(int))); @@ -113,13 +108,13 @@ int main(int, char**) assert(A_constructed == 0); } #if TEST_STD_VER >= 11 - { + { std::allocator<move_only> a; assert(globalMemCounter.checkOutstandingNewEq(0)); assert(move_only_constructed == 0); globalMemCounter.last_new_size = 0; - move_only* ap = a.allocate(3); + move_only* ap = a.allocate(3); DoNotOptimize(ap); assert(globalMemCounter.checkOutstandingNewEq(1)); assert(globalMemCounter.checkLastNewSizeEq(3 * sizeof(int))); @@ -145,7 +140,7 @@ int main(int, char**) DoNotOptimize(ap); assert(globalMemCounter.checkOutstandingNewEq(0)); assert(move_only_constructed == 0); - } + } #endif return 0; diff --git a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/construct.cxx20.verify.cpp b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/construct.cxx20.verify.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b39f9d918c959b650ac5a99617cbf9f67fdd12d4 --- /dev/null +++ b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/construct.cxx20.verify.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// <memory> + +// allocator: +// template <class... Args> void construct(pointer p, Args&&... args); + +// Removed in C++20. + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +#include <memory> +#include <cassert> + +int A_constructed = 0; + +struct A { + int data; + A() { ++A_constructed; } + + A(const A&) { ++A_constructed; } + + explicit A(int) { ++A_constructed; } + A(int, int*) { ++A_constructed; } + + ~A() { --A_constructed; } +}; + +int move_only_constructed = 0; + +class move_only { + move_only(const move_only&) = delete; + move_only& operator=(const move_only&) = delete; + +public: + move_only(move_only&&) { ++move_only_constructed; } + move_only& operator=(move_only&&) { return *this; } + + move_only() { ++move_only_constructed; } + ~move_only() { --move_only_constructed; } + +public: + int data; // unused other than to make sizeof(move_only) == sizeof(int). + // but public to suppress "-Wunused-private-field" +}; + +int main(int, char**) { + { + std::allocator<A> a; + A* ap = a.allocate(3); + a.construct(ap); // expected-error {{no member}} + a.destroy(ap); // expected-error {{no member}} + a.construct(ap, A()); // expected-error {{no member}} + a.destroy(ap); // expected-error {{no member}} + a.construct(ap, 5); // expected-error {{no member}} + a.destroy(ap); // expected-error {{no member}} + a.construct(ap, 5, (int*)0); // expected-error {{no member}} + a.destroy(ap); // expected-error {{no member}} + a.deallocate(ap, 3); + } + { + std::allocator<move_only> a; + move_only* ap = a.allocate(3); + a.construct(ap); // expected-error {{no member}} + a.destroy(ap); // expected-error {{no member}} + a.construct(ap, move_only()); // expected-error {{no member}} + a.destroy(ap); // expected-error {{no member}} + a.deallocate(ap, 3); + } + return 0; +} diff --git a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/max_size.cxx2a.pass.cpp b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/max_size.cxx20.pass.cpp similarity index 56% rename from libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/max_size.cxx2a.pass.cpp rename to libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/max_size.cxx20.pass.cpp index b07568355fee76d724c46f62e4b14e09bd7fe16f..92e3b919b0f7678592d1a7c9c6e2b71d44074f12 100644 --- a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/max_size.cxx2a.pass.cpp +++ b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/max_size.cxx20.pass.cpp @@ -11,11 +11,9 @@ // allocator: // size_type max_size() const throw(); -// In C++20, parts of std::allocator<T> have been removed. -// However, for backwards compatibility, if _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS -// is defined before including <memory>, then removed members will be restored. +// Removed in C++20, deprecated in C++17. -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS +// REQUIRES: c++03 || c++11 || c++14 || c++17 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS #include <memory> @@ -27,11 +25,10 @@ int new_called = 0; -int main(int, char**) -{ - const std::allocator<int> a; - std::size_t M = a.max_size(); - assert(M > 0xFFFF && M <= (std::numeric_limits<std::size_t>::max() / sizeof(int))); +int main(int, char**) { + const std::allocator<int> a; + std::size_t M = a.max_size(); + assert(M > 0xFFFF && M <= (std::numeric_limits<std::size_t>::max() / sizeof(int))); return 0; } diff --git a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/max_size.cxx20.verify.cpp b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/max_size.cxx20.verify.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0e0f3c3f4aa454b92f694fb6c03d74ad8cecaf4d --- /dev/null +++ b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/max_size.cxx20.verify.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// <memory> + +// allocator: +// size_type max_size() const throw(); + +// In C++20, parts of std::allocator<T> have been removed. +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +#include <memory> +#include <limits> +#include <cstddef> +#include <cassert> + +#include "test_macros.h" + +int new_called = 0; + +int main(int, char**) { + const std::allocator<int> a; + std::size_t M = a.max_size(); // expected-error {{no member}} + assert(M > 0xFFFF && M <= (std::numeric_limits<std::size_t>::max() / sizeof(int))); + + return 0; +} diff --git a/libcxx/test/libcxx/depr/depr.default.allocator/allocator_types.cxx2a.pass.cpp b/libcxx/test/libcxx/depr/depr.default.allocator/allocator_types.cxx20.pass.cpp similarity index 59% rename from libcxx/test/libcxx/depr/depr.default.allocator/allocator_types.cxx2a.pass.cpp rename to libcxx/test/libcxx/depr/depr.default.allocator/allocator_types.cxx20.pass.cpp index a6134b04a8f555ac254179bfcc915334da28916b..e462e07d896c5231911bb27067adc46742be97de 100644 --- a/libcxx/test/libcxx/depr/depr.default.allocator/allocator_types.cxx2a.pass.cpp +++ b/libcxx/test/libcxx/depr/depr.default.allocator/allocator_types.cxx20.pass.cpp @@ -26,7 +26,9 @@ // ... // }; -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS +// Removed in C++20, deprecated in C++17. + +// REQUIRES: c++03 || c++11 || c++14 || c++17 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS #include <memory> @@ -35,17 +37,17 @@ template <class T> void test() { - static_assert((std::is_same<typename std::allocator<T>::size_type, std::size_t>::value), ""); - static_assert((std::is_same<typename std::allocator<T>::difference_type, std::ptrdiff_t>::value), ""); - static_assert((std::is_same<typename std::allocator<T>::pointer, T*>::value), ""); - static_assert((std::is_same<typename std::allocator<T>::const_pointer, const T*>::value), ""); - static_assert((std::is_same<typename std::allocator<T>::reference, T&>::value), ""); - static_assert((std::is_same<typename std::allocator<T>::const_reference, const T&>::value), ""); - static_assert((std::is_same<typename std::allocator<T>::template rebind<int>::other, - std::allocator<int> >::value), ""); + static_assert((std::is_same<typename std::allocator<T>::size_type, std::size_t>::value), ""); + static_assert((std::is_same<typename std::allocator<T>::difference_type, std::ptrdiff_t>::value), ""); + static_assert((std::is_same<typename std::allocator<T>::pointer, T*>::value), ""); + static_assert((std::is_same<typename std::allocator<T>::const_pointer, const T*>::value), ""); + static_assert((std::is_same<typename std::allocator<T>::reference, T&>::value), ""); + static_assert((std::is_same<typename std::allocator<T>::const_reference, const T&>::value), ""); + static_assert( + (std::is_same<typename std::allocator<T>::template rebind<int>::other, std::allocator<int> >::value), ""); } int main(int, char**) { - test<char>(); - return 0; + test<char>(); + return 0; } diff --git a/libcxx/test/libcxx/depr/depr.default.allocator/enable_removed_allocator_members.deprecated.verify.cpp b/libcxx/test/libcxx/depr/depr.default.allocator/enable_removed_allocator_members.deprecated.verify.cpp deleted file mode 100644 index ab6495ea9db47cef395492c68fe9d70404cf2213..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/depr/depr.default.allocator/enable_removed_allocator_members.deprecated.verify.cpp +++ /dev/null @@ -1,20 +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 -// -//===----------------------------------------------------------------------===// - -// <memory> - -// Ensure that defining _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS yields a -// deprecation warning. We intend to issue a deprecation warning in LLVM 18 -// and remove the macro entirely in LLVM 19. As such, this test will be quite -// short lived. - -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS - -// UNSUPPORTED: clang-modules-build - -#include <memory> // expected-warning@* 1+ {{macro '_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS' has been marked as deprecated}} diff --git a/libcxx/test/libcxx/diagnostics/limits.nodiscard_extensions.compile.pass.cpp b/libcxx/test/libcxx/diagnostics/limits.nodiscard_extensions.compile.pass.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a93f55b888b95af617fa3df3641c3f8b55a5f59b --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/limits.nodiscard_extensions.compile.pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03 + +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_NODISCARD_EXT + +// Check that <limits> functions aren't marked [[nodiscard]] when +// _LIBCPP_DISABLE_NODISCARD_EXT is defined + +#include <limits> + +#include "test_macros.h" + +void func() { + // arithmetic + std::numeric_limits<int>::min(); + std::numeric_limits<int>::max(); + std::numeric_limits<int>::lowest(); + std::numeric_limits<int>::epsilon(); + std::numeric_limits<int>::round_error(); + std::numeric_limits<int>::infinity(); + std::numeric_limits<int>::quiet_NaN(); + std::numeric_limits<int>::signaling_NaN(); + std::numeric_limits<int>::denorm_min(); + // bool + std::numeric_limits<bool>::min(); + std::numeric_limits<bool>::max(); + std::numeric_limits<bool>::lowest(); + std::numeric_limits<bool>::epsilon(); + std::numeric_limits<bool>::round_error(); + std::numeric_limits<bool>::infinity(); + std::numeric_limits<bool>::quiet_NaN(); + std::numeric_limits<bool>::signaling_NaN(); + std::numeric_limits<bool>::denorm_min(); + // float + std::numeric_limits<float>::min(); + std::numeric_limits<float>::max(); + std::numeric_limits<float>::lowest(); + std::numeric_limits<float>::epsilon(); + std::numeric_limits<float>::round_error(); + std::numeric_limits<float>::infinity(); + std::numeric_limits<float>::quiet_NaN(); + std::numeric_limits<float>::signaling_NaN(); + std::numeric_limits<float>::denorm_min(); + // double + std::numeric_limits<double>::min(); + std::numeric_limits<double>::max(); + std::numeric_limits<double>::lowest(); + std::numeric_limits<double>::epsilon(); + std::numeric_limits<double>::round_error(); + std::numeric_limits<double>::infinity(); + std::numeric_limits<double>::quiet_NaN(); + std::numeric_limits<double>::signaling_NaN(); + std::numeric_limits<double>::denorm_min(); + // long double + std::numeric_limits<long double>::min(); + std::numeric_limits<long double>::max(); + std::numeric_limits<long double>::lowest(); + std::numeric_limits<long double>::epsilon(); + std::numeric_limits<long double>::round_error(); + std::numeric_limits<long double>::infinity(); + std::numeric_limits<long double>::quiet_NaN(); + std::numeric_limits<long double>::signaling_NaN(); + std::numeric_limits<long double>::denorm_min(); +} diff --git a/libcxx/test/libcxx/diagnostics/limits.nodiscard_extensions.verify.cpp b/libcxx/test/libcxx/diagnostics/limits.nodiscard_extensions.verify.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7a81b84378c52ef6c13ba8a3acb33392c4c22006 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/limits.nodiscard_extensions.verify.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03 + +// check that <limits> functions are marked [[nodiscard]] + +#include <limits> + +#include "test_macros.h" + +void func() { + // clang-format off + // arithmetic + std::numeric_limits<int>::min(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<int>::max(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<int>::lowest(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<int>::epsilon(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<int>::round_error(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<int>::infinity(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<int>::quiet_NaN(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<int>::signaling_NaN(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<int>::denorm_min(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + // bool + std::numeric_limits<bool>::min(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<bool>::max(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<bool>::lowest(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<bool>::epsilon(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<bool>::round_error(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<bool>::infinity(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<bool>::quiet_NaN(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<bool>::signaling_NaN(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<bool>::denorm_min(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + // float + std::numeric_limits<float>::min(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<float>::max(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<float>::lowest(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<float>::epsilon(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<float>::round_error(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<float>::infinity(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<float>::quiet_NaN(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<float>::signaling_NaN(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<float>::denorm_min(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + // double + std::numeric_limits<double>::min(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<double>::max(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<double>::lowest(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<double>::epsilon(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<double>::round_error(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<double>::infinity(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<double>::quiet_NaN(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<double>::signaling_NaN(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<double>::denorm_min(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + // long double + std::numeric_limits<long double>::min(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<long double>::max(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<long double>::lowest(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<long double>::epsilon(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<long double>::round_error(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<long double>::infinity(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<long double>::quiet_NaN(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<long double>::signaling_NaN(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::numeric_limits<long double>::denorm_min(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + // clang-format on +} diff --git a/libcxx/test/libcxx/input.output/filesystems/class.directory_entry/directory_entry.mods/last_write_time.pass.cpp b/libcxx/test/libcxx/input.output/filesystems/class.directory_entry/directory_entry.mods/last_write_time.pass.cpp index 26703f748d8745c77bb7bb10e24b89233b70e2b0..1acbed55d2b516c894d20ce1016f8ddb200c88d4 100644 --- a/libcxx/test/libcxx/input.output/filesystems/class.directory_entry/directory_entry.mods/last_write_time.pass.cpp +++ b/libcxx/test/libcxx/input.output/filesystems/class.directory_entry/directory_entry.mods/last_write_time.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: availability-filesystem-missing // UNSUPPORTED: no-filesystem -// ADDITIONAL_COMPILE_FLAGS: -I %S/../../../../../../src +// ADDITIONAL_COMPILE_FLAGS: -I %{libcxx-dir}/src // This test relies on calling functions from the libcxx internal headers // of <filesystem>; the Windows implementation uses different diff --git a/libcxx/test/libcxx/input.output/filesystems/convert_file_time.pass.cpp b/libcxx/test/libcxx/input.output/filesystems/convert_file_time.pass.cpp index 3c901c4e9f2e865e1c6591c4f57e1ed6f6306e62..699bbfb9e6dc8f994d53149753bf41593883a77d 100644 --- a/libcxx/test/libcxx/input.output/filesystems/convert_file_time.pass.cpp +++ b/libcxx/test/libcxx/input.output/filesystems/convert_file_time.pass.cpp @@ -13,7 +13,7 @@ // typedef TrivialClock file_time_type; -// ADDITIONAL_COMPILE_FLAGS: -I %S/../../../../src -Wno-macro-redefined +// ADDITIONAL_COMPILE_FLAGS: -I %{libcxx-dir}/src -Wno-macro-redefined #include <cassert> #include <chrono> diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cmp/equal.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cmp/equal.pass.cpp deleted file mode 100644 index 583e733c07cb0b439dfa3cb240aa7c8a786b5e6a..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cmp/equal.pass.cpp +++ /dev/null @@ -1,47 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// template <BidirectionalIterator Iter1, BidirectionalIterator Iter2> -// requires HasEqualTo<Iter1, Iter2> -// bool operator==(const __unconstrained_reverse_iterator<Iter1>& x, const __unconstrained_reverse_iterator<Iter2>& y); // constexpr since C++17 - -#include <iterator> -#include <cassert> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class It> -TEST_CONSTEXPR_CXX17 void test(It l, It r, bool x) { - const std::__unconstrained_reverse_iterator<It> r1(l); - const std::__unconstrained_reverse_iterator<It> r2(r); - assert((r1 == r2) == x); -} - -TEST_CONSTEXPR_CXX17 bool tests() { - const char* s = "1234567890"; - test(bidirectional_iterator<const char*>(s), bidirectional_iterator<const char*>(s), true); - test(bidirectional_iterator<const char*>(s), bidirectional_iterator<const char*>(s+1), false); - test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s), true); - test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s+1), false); - test(s, s, true); - test(s, s+1, false); - return true; -} - -int main(int, char**) { - tests(); -#if TEST_STD_VER > 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cmp/greater-equal.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cmp/greater-equal.pass.cpp deleted file mode 100644 index 9e908418d0756526636264683d8d702b59798881..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cmp/greater-equal.pass.cpp +++ /dev/null @@ -1,47 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// template <RandomAccessIterator Iter1, RandomAccessIterator Iter2> -// requires HasGreater<Iter1, Iter2> -// bool operator>=(const __unconstrained_reverse_iterator<Iter1>& x, const __unconstrained_reverse_iterator<Iter2>& y); // constexpr since C++17 - -#include <iterator> -#include <cassert> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class It> -TEST_CONSTEXPR_CXX17 void test(It l, It r, bool x) { - const std::__unconstrained_reverse_iterator<It> r1(l); - const std::__unconstrained_reverse_iterator<It> r2(r); - assert((r1 >= r2) == x); -} - -TEST_CONSTEXPR_CXX17 bool tests() { - const char* s = "1234567890"; - test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s), true); - test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s+1), true); - test(random_access_iterator<const char*>(s+1), random_access_iterator<const char*>(s), false); - test(s, s, true); - test(s, s+1, true); - test(s+1, s, false); - return true; -} - -int main(int, char**) { - tests(); -#if TEST_STD_VER > 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cmp/greater.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cmp/greater.pass.cpp deleted file mode 100644 index f1afd23bab13389cb7fb0ed2e93bdf8607d7da9b..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cmp/greater.pass.cpp +++ /dev/null @@ -1,47 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// template <RandomAccessIterator Iter1, RandomAccessIterator Iter2> -// requires HasGreater<Iter1, Iter2> -// bool operator>(const __unconstrained_reverse_iterator<Iter1>& x, const __unconstrained_reverse_iterator<Iter2>& y); // constexpr in C++17 - -#include <iterator> -#include <cassert> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class It> -TEST_CONSTEXPR_CXX17 void test(It l, It r, bool x) { - const std::__unconstrained_reverse_iterator<It> r1(l); - const std::__unconstrained_reverse_iterator<It> r2(r); - assert((r1 > r2) == x); -} - -TEST_CONSTEXPR_CXX17 bool tests() { - const char* s = "1234567890"; - test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s), false); - test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s+1), true); - test(random_access_iterator<const char*>(s+1), random_access_iterator<const char*>(s), false); - test(s, s, false); - test(s, s+1, true); - test(s+1, s, false); - return true; -} - -int main(int, char**) { - tests(); -#if TEST_STD_VER > 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cmp/less-equal.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cmp/less-equal.pass.cpp deleted file mode 100644 index c710212308fac7dabda15935f1d7b0331c259ad5..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cmp/less-equal.pass.cpp +++ /dev/null @@ -1,47 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// template <RandomAccessIterator Iter1, RandomAccessIterator Iter2> -// requires HasGreater<Iter1, Iter2> -// bool operator<=(const __unconstrained_reverse_iterator<Iter1>& x, const __unconstrained_reverse_iterator<Iter2>& y); // constexpr in C++17 - -#include <iterator> -#include <cassert> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class It> -TEST_CONSTEXPR_CXX17 void test(It l, It r, bool x) { - const std::__unconstrained_reverse_iterator<It> r1(l); - const std::__unconstrained_reverse_iterator<It> r2(r); - assert((r1 <= r2) == x); -} - -TEST_CONSTEXPR_CXX17 bool tests() { - const char* s = "1234567890"; - test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s), true); - test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s+1), false); - test(random_access_iterator<const char*>(s+1), random_access_iterator<const char*>(s), true); - test(s, s, true); - test(s, s+1, false); - test(s+1, s, true); - return true; -} - -int main(int, char**) { - tests(); -#if TEST_STD_VER > 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cmp/less.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cmp/less.pass.cpp deleted file mode 100644 index ffd3a0323373fb2bf6e8ddc0d13d77d6120e6a30..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cmp/less.pass.cpp +++ /dev/null @@ -1,47 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// template <RandomAccessIterator Iter1, RandomAccessIterator Iter2> -// requires HasGreater<Iter1, Iter2> -// bool operator<(const __unconstrained_reverse_iterator<Iter1>& x, const __unconstrained_reverse_iterator<Iter2>& y); // constexpr in C++17 - -#include <iterator> -#include <cassert> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class It> -TEST_CONSTEXPR_CXX17 void test(It l, It r, bool x) { - const std::__unconstrained_reverse_iterator<It> r1(l); - const std::__unconstrained_reverse_iterator<It> r2(r); - assert((r1 < r2) == x); -} - -TEST_CONSTEXPR_CXX17 bool tests() { - const char* s = "1234567890"; - test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s), false); - test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s+1), false); - test(random_access_iterator<const char*>(s+1), random_access_iterator<const char*>(s), true); - test(s, s, false); - test(s, s+1, false); - test(s+1, s, true); - return true; -} - -int main(int, char**) { - tests(); -#if TEST_STD_VER > 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cmp/not-equal.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cmp/not-equal.pass.cpp deleted file mode 100644 index 614f159cc80522412d8b7c0c34578f2bd7aff766..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cmp/not-equal.pass.cpp +++ /dev/null @@ -1,47 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// template <BidirectionalIterator Iter1, BidirectionalIterator Iter2> -// requires HasEqualTo<Iter1, Iter2> -// bool operator!=(const __unconstrained_reverse_iterator<Iter1>& x, const __unconstrained_reverse_iterator<Iter2>& y); // constexpr in C++17 - -#include <iterator> -#include <cassert> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class It> -TEST_CONSTEXPR_CXX17 void test(It l, It r, bool x) { - const std::__unconstrained_reverse_iterator<It> r1(l); - const std::__unconstrained_reverse_iterator<It> r2(r); - assert((r1 != r2) == x); -} - -TEST_CONSTEXPR_CXX17 bool tests() { - const char* s = "1234567890"; - test(bidirectional_iterator<const char*>(s), bidirectional_iterator<const char*>(s), false); - test(bidirectional_iterator<const char*>(s), bidirectional_iterator<const char*>(s+1), true); - test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s), false); - test(random_access_iterator<const char*>(s), random_access_iterator<const char*>(s+1), true); - test(s, s, false); - test(s, s+1, true); - return true; -} - -int main(int, char**) { - tests(); -#if TEST_STD_VER > 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cons/assign.LWG3435.verify.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cons/assign.LWG3435.verify.cpp deleted file mode 100644 index 835e2b65c19c20c193fc740cfde3eb757e427112..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cons/assign.LWG3435.verify.cpp +++ /dev/null @@ -1,26 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// template <class U> -// requires !same_as<U, Iter> && convertible_to<const U&, Iter> && assignable_from<Iter&, const U&> -// __unconstrained_reverse_iterator& operator=(const __unconstrained_reverse_iterator<U>& u); - -#include <iterator> - -struct Base { }; -struct Derived : Base { }; - -void test() { - std::__unconstrained_reverse_iterator<Base*> base; - std::__unconstrained_reverse_iterator<Derived*> derived; - derived = base; // expected-error {{no viable overloaded '='}} -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cons/ctor.default.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cons/ctor.default.pass.cpp deleted file mode 100644 index 66972d7243cc833856642634a66e53e68d0fd85b..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cons/ctor.default.pass.cpp +++ /dev/null @@ -1,40 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// __unconstrained_reverse_iterator(); // constexpr since C++17 - -#include <iterator> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class It> -TEST_CONSTEXPR_CXX17 void test() { - std::__unconstrained_reverse_iterator<It> r; - (void)r; -} - -TEST_CONSTEXPR_CXX17 bool tests() { - test<bidirectional_iterator<const char*> >(); - test<random_access_iterator<char*> >(); - test<char*>(); - test<const char*>(); - return true; -} - -int main(int, char**) { - tests(); -#if TEST_STD_VER > 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cons/ctor.iter.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cons/ctor.iter.pass.cpp deleted file mode 100644 index e4d0874d50b5e930ca6fb6812664e26d3e2c257a..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cons/ctor.iter.pass.cpp +++ /dev/null @@ -1,41 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// explicit __unconstrained_reverse_iterator(Iter x); // constexpr since C++17 - -#include <iterator> -#include <cassert> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class It> -TEST_CONSTEXPR_CXX17 void test(It i) { - std::__unconstrained_reverse_iterator<It> r(i); - assert(r.base() == i); -} - -TEST_CONSTEXPR_CXX17 bool tests() { - const char s[] = "123"; - test(bidirectional_iterator<const char*>(s)); - test(random_access_iterator<const char*>(s)); - test(s); - return true; -} - -int main(int, char**) { - tests(); -#if TEST_STD_VER > 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cons/ctor.reverse_iterator.LWG3435.verify.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cons/ctor.reverse_iterator.LWG3435.verify.cpp deleted file mode 100644 index 7ea4a61ce6602006987bedb456650b6cd7e2f043..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.cons/ctor.reverse_iterator.LWG3435.verify.cpp +++ /dev/null @@ -1,25 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// template <class U> -// requires !same_as<U, Iter> && convertible_to<const U&, Iter> -// __unconstrained_reverse_iterator(const __unconstrained_reverse_iterator<U> &); - -#include <iterator> - -struct Base { }; -struct Derived : Base { }; - -void test() { - std::__unconstrained_reverse_iterator<Base*> base; - std::__unconstrained_reverse_iterator<Derived*> derived(base); // expected-error {{no matching constructor for initialization of 'std::__unconstrained_reverse_iterator<Derived *>'}} -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.conv/base.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.conv/base.pass.cpp deleted file mode 100644 index 7fd85c92b32771e266b9b86bc1034031437984da..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.conv/base.pass.cpp +++ /dev/null @@ -1,37 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// iterator_type base() const; // constexpr since C++17 - -#include <iterator> -#include <cassert> - -#include "test_macros.h" -#include "test_iterators.h" - -TEST_CONSTEXPR_CXX17 bool test() { - typedef bidirectional_iterator<int*> Iter; - int i = 0; - Iter iter(&i); - std::__unconstrained_reverse_iterator<Iter> const reverse(iter); - std::__unconstrained_reverse_iterator<Iter>::iterator_type base = reverse.base(); - assert(base == Iter(&i)); - return true; -} - -int main(int, char**) { - test(); -#if TEST_STD_VER > 14 - static_assert(test(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.elem/arrow.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.elem/arrow.pass.cpp deleted file mode 100644 index f0a181bcba88f1f63255cead0a816a3bb2733aa9..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.elem/arrow.pass.cpp +++ /dev/null @@ -1,122 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// pointer operator->() const; // constexpr in C++17 - -// Be sure to respect LWG 198: -// http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#198 -// LWG 198 was superseded by LWG 2360 -// http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2360 - - -#include <iterator> -#include <list> -#include <cassert> - -#include "test_macros.h" - -class A -{ - int data_; -public: - A() : data_(1) {} - A(const A&) = default; - A& operator=(const A&) = default; - ~A() {data_ = -1;} - - int get() const {return data_;} - - friend bool operator==(const A& x, const A& y) - {return x.data_ == y.data_;} -}; - -template <class It> -void -test(It i, typename std::iterator_traits<It>::value_type x) -{ - std::__unconstrained_reverse_iterator<It> r(i); - assert(r->get() == x.get()); -} - -class B -{ - int data_; -public: - B(int d=1) : data_(d) {} - B(const B&) = default; - B& operator=(const B&) = default; - ~B() {data_ = -1;} - - int get() const {return data_;} - - friend bool operator==(const B& x, const B& y) - {return x.data_ == y.data_;} - const B *operator&() const { return nullptr; } - B *operator&() { return nullptr; } -}; - -class C -{ - int data_; -public: - TEST_CONSTEXPR C() : data_(1) {} - - TEST_CONSTEXPR int get() const {return data_;} - - friend TEST_CONSTEXPR bool operator==(const C& x, const C& y) - {return x.data_ == y.data_;} -}; - -TEST_CONSTEXPR C gC; - -int main(int, char**) -{ - A a; - test(&a+1, A()); - - { - std::list<B> l; - l.push_back(B(0)); - l.push_back(B(1)); - l.push_back(B(2)); - - { - std::list<B>::const_iterator i = l.begin(); - assert ( i->get() == 0 ); ++i; - assert ( i->get() == 1 ); ++i; - assert ( i->get() == 2 ); ++i; - assert ( i == l.end ()); - } - - { - std::list<B>::const_reverse_iterator ri = l.rbegin(); - assert ( ri->get() == 2 ); ++ri; - assert ( ri->get() == 1 ); ++ri; - assert ( ri->get() == 0 ); ++ri; - assert ( ri == l.rend ()); - } - } - -#if TEST_STD_VER > 14 - { - typedef std::__unconstrained_reverse_iterator<const C *> RI; - constexpr RI it1 = RI(&gC+1); - - static_assert(it1->get() == gC.get(), ""); - } -#endif - { - ((void)gC); - } - - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.elem/bracket.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.elem/bracket.pass.cpp deleted file mode 100644 index f9beada9e4e64b6b2cb45315f33cd12db509ea2a..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.elem/bracket.pass.cpp +++ /dev/null @@ -1,47 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// requires RandomAccessIterator<Iter> -// unspecified operator[](difference_type n) const; // constexpr since C++17 - -#include <iterator> -#include <cassert> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class It> -TEST_CONSTEXPR_CXX17 void test(It i, - typename std::iterator_traits<It>::difference_type n, - typename std::iterator_traits<It>::value_type x) { - typedef typename std::iterator_traits<It>::value_type value_type; - const std::__unconstrained_reverse_iterator<It> r(i); - value_type rr = r[n]; - assert(rr == x); -} - -TEST_CONSTEXPR_CXX17 bool tests() { - const char* s = "1234567890"; - test(random_access_iterator<const char*>(s+5), 4, '1'); - test(random_access_iterator<const char*>(s+5), 0, '5'); - test(s+5, 4, '1'); - test(s+5, 0, '5'); - return true; -} - -int main(int, char**) { - tests(); -#if TEST_STD_VER > 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.elem/dereference.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.elem/dereference.pass.cpp deleted file mode 100644 index bd6b6e0df038deb95586986ba11b5b5e2ce4a062..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.elem/dereference.pass.cpp +++ /dev/null @@ -1,63 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// reference operator*() const; // constexpr in C++17 - -// Be sure to respect LWG 198: -// http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#198 -// LWG 198 was superseded by LWG 2360 -// http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2360 - -#include <iterator> -#include <cassert> - -#include "test_macros.h" - -class A -{ - int data_; -public: - A() : data_(1) {} - A(const A&) = default; - A& operator=(const A&) = default; - ~A() {data_ = -1;} - - friend bool operator==(const A& x, const A& y) - {return x.data_ == y.data_;} -}; - -template <class It> -void -test(It i, typename std::iterator_traits<It>::value_type x) -{ - std::__unconstrained_reverse_iterator<It> r(i); - assert(*r == x); -} - -int main(int, char**) -{ - A a; - test(&a+1, A()); - -#if TEST_STD_VER > 14 - { - constexpr const char *p = "123456789"; - typedef std::__unconstrained_reverse_iterator<const char *> RI; - constexpr RI it1 = RI(p+1); - constexpr RI it2 = RI(p+2); - static_assert(*it1 == p[0], ""); - static_assert(*it2 == p[1], ""); - } -#endif - - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/decrement-assign.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/decrement-assign.pass.cpp deleted file mode 100644 index 48be8a7399e42769a67505df33e738c457b4173e..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/decrement-assign.pass.cpp +++ /dev/null @@ -1,43 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// requires RandomAccessIterator<Iter> -// __unconstrained_reverse_iterator& operator-=(difference_type n); // constexpr in C++17 - -#include <iterator> -#include <cassert> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class It> -TEST_CONSTEXPR_CXX17 void test(It i, typename std::iterator_traits<It>::difference_type n, It x) { - std::__unconstrained_reverse_iterator<It> r(i); - std::__unconstrained_reverse_iterator<It>& rr = r -= n; - assert(r.base() == x); - assert(&rr == &r); -} - -TEST_CONSTEXPR_CXX17 bool tests() { - const char* s = "1234567890"; - test(random_access_iterator<const char*>(s+5), 5, random_access_iterator<const char*>(s+10)); - test(s+5, 5, s+10); - return true; -} - -int main(int, char**) { - tests(); -#if TEST_STD_VER > 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/increment-assign.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/increment-assign.pass.cpp deleted file mode 100644 index 115d95e1485cdcf44f3e157a99cd94875ae959a5..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/increment-assign.pass.cpp +++ /dev/null @@ -1,43 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// requires RandomAccessIterator<Iter> -// __unconstrained_reverse_iterator& operator+=(difference_type n); // constexpr in C++17 - -#include <iterator> -#include <cassert> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class It> -TEST_CONSTEXPR_CXX17 void test(It i, typename std::iterator_traits<It>::difference_type n, It x) { - std::__unconstrained_reverse_iterator<It> r(i); - std::__unconstrained_reverse_iterator<It>& rr = r += n; - assert(r.base() == x); - assert(&rr == &r); -} - -TEST_CONSTEXPR_CXX17 bool tests() { - char const* s = "1234567890"; - test(random_access_iterator<const char*>(s+5), 5, random_access_iterator<const char*>(s)); - test(s+5, 5, s); - return true; -} - -int main(int, char**) { - tests(); -#if TEST_STD_VER > 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/minus.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/minus.pass.cpp deleted file mode 100644 index c3a4d1fd9e36fbf37d632062eb5c1a826055cc7d..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/minus.pass.cpp +++ /dev/null @@ -1,42 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// requires RandomAccessIterator<Iter> -// __unconstrained_reverse_iterator operator-(difference_type n) const; // constexpr in C++17 - -#include <iterator> -#include <cassert> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class It> -TEST_CONSTEXPR_CXX17 void test(It i, typename std::iterator_traits<It>::difference_type n, It x) { - const std::__unconstrained_reverse_iterator<It> r(i); - std::__unconstrained_reverse_iterator<It> rr = r - n; - assert(rr.base() == x); -} - -TEST_CONSTEXPR_CXX17 bool tests() { - const char* s = "1234567890"; - test(random_access_iterator<const char*>(s+5), 5, random_access_iterator<const char*>(s+10)); - test(s+5, 5, s+10); - return true; -} - -int main(int, char**) { - tests(); -#if TEST_STD_VER > 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/plus.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/plus.pass.cpp deleted file mode 100644 index 164c5abe8a3533ea8811fcb187f87b722fa4d183..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/plus.pass.cpp +++ /dev/null @@ -1,42 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// requires RandomAccessIterator<Iter> -// __unconstrained_reverse_iterator operator+(difference_type n) const; // constexpr in C++17 - -#include <iterator> -#include <cassert> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class It> -TEST_CONSTEXPR_CXX17 void test(It i, typename std::iterator_traits<It>::difference_type n, It x) { - const std::__unconstrained_reverse_iterator<It> r(i); - std::__unconstrained_reverse_iterator<It> rr = r + n; - assert(rr.base() == x); -} - -TEST_CONSTEXPR_CXX17 bool tests() { - const char* s = "1234567890"; - test(random_access_iterator<const char*>(s+5), 5, random_access_iterator<const char*>(s)); - test(s+5, 5, s); - return true; -} - -int main(int, char**) { - tests(); -#if TEST_STD_VER > 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/postdecrement.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/postdecrement.pass.cpp deleted file mode 100644 index 3220c1f9b1eb1de7112986e29d290463847f1220..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/postdecrement.pass.cpp +++ /dev/null @@ -1,43 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// __unconstrained_reverse_iterator operator--(int); // constexpr in C++17 - -#include <iterator> -#include <cassert> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class It> -TEST_CONSTEXPR_CXX17 void test(It i, It x) { - std::__unconstrained_reverse_iterator<It> r(i); - std::__unconstrained_reverse_iterator<It> rr = r--; - assert(r.base() == x); - assert(rr.base() == i); -} - -TEST_CONSTEXPR_CXX17 bool tests() { - const char* s = "123"; - test(bidirectional_iterator<const char*>(s+1), bidirectional_iterator<const char*>(s+2)); - test(random_access_iterator<const char*>(s+1), random_access_iterator<const char*>(s+2)); - test(s+1, s+2); - return true; -} - -int main(int, char**) { - tests(); -#if TEST_STD_VER > 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/postincrement.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/postincrement.pass.cpp deleted file mode 100644 index 47477fe89545b6aaf3beb8f03e947eee11511a7d..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/postincrement.pass.cpp +++ /dev/null @@ -1,43 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// __unconstrained_reverse_iterator operator++(int); // constexpr in C++17 - -#include <iterator> -#include <cassert> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class It> -TEST_CONSTEXPR_CXX17 void test(It i, It x) { - std::__unconstrained_reverse_iterator<It> r(i); - std::__unconstrained_reverse_iterator<It> rr = r++; - assert(r.base() == x); - assert(rr.base() == i); -} - -TEST_CONSTEXPR_CXX17 bool tests() { - const char* s = "123"; - test(bidirectional_iterator<const char*>(s+1), bidirectional_iterator<const char*>(s)); - test(random_access_iterator<const char*>(s+1), random_access_iterator<const char*>(s)); - test(s+1, s); - return true; -} - -int main(int, char**) { - tests(); -#if TEST_STD_VER > 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/predecrement.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/predecrement.pass.cpp deleted file mode 100644 index 6ad41aeaf17a283d9dade6dafb9a4333f387c1f7..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/predecrement.pass.cpp +++ /dev/null @@ -1,43 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// __unconstrained_reverse_iterator& operator--(); // constexpr in C++17 - -#include <iterator> -#include <cassert> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class It> -TEST_CONSTEXPR_CXX17 void test(It i, It x) { - std::__unconstrained_reverse_iterator<It> r(i); - std::__unconstrained_reverse_iterator<It>& rr = --r; - assert(r.base() == x); - assert(&rr == &r); -} - -TEST_CONSTEXPR_CXX17 bool tests() { - const char* s = "123"; - test(bidirectional_iterator<const char*>(s+1), bidirectional_iterator<const char*>(s+2)); - test(random_access_iterator<const char*>(s+1), random_access_iterator<const char*>(s+2)); - test(s+1, s+2); - return true; -} - -int main(int, char**) { - tests(); -#if TEST_STD_VER > 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/preincrement.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/preincrement.pass.cpp deleted file mode 100644 index 9c7e5b41738e9b7bf39c18f10b109c87486048f0..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nav/preincrement.pass.cpp +++ /dev/null @@ -1,43 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// __unconstrained_reverse_iterator& operator++(); // constexpr in C++17 - -#include <iterator> -#include <cassert> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class It> -TEST_CONSTEXPR_CXX17 void test(It i, It x) { - std::__unconstrained_reverse_iterator<It> r(i); - std::__unconstrained_reverse_iterator<It>& rr = ++r; - assert(r.base() == x); - assert(&rr == &r); -} - -TEST_CONSTEXPR_CXX17 bool tests() { - const char* s = "123"; - test(bidirectional_iterator<const char*>(s+1), bidirectional_iterator<const char*>(s)); - test(random_access_iterator<const char*>(s+1), random_access_iterator<const char*>(s)); - test(s+1, s); - return true; -} - -int main(int, char**) { - tests(); -#if TEST_STD_VER > 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nonmember/minus.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nonmember/minus.pass.cpp deleted file mode 100644 index 632e2655dea07fccd2e454db438bf5764ff06a0c..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/reverse.iter.nonmember/minus.pass.cpp +++ /dev/null @@ -1,59 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// template <RandomAccessIterator Iter1, RandomAccessIterator Iter2> -// requires HasMinus<Iter2, Iter1> -// auto operator-(const __unconstrained_reverse_iterator<Iter1>& x, const __unconstrained_reverse_iterator<Iter2>& y) // constexpr in C++17 -// -> decltype(y.base() - x.base()); - -#include <iterator> -#include <cstddef> -#include <cassert> -#include <type_traits> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class, class, class = void> struct HasMinus : std::false_type {}; -template <class R1, class R2> struct HasMinus<R1, R2, decltype((R1() - R2(), void()))> : std::true_type {}; - -template <class It1, class It2> -TEST_CONSTEXPR_CXX17 void test(It1 l, It2 r, std::ptrdiff_t x) { - const std::__unconstrained_reverse_iterator<It1> r1(l); - const std::__unconstrained_reverse_iterator<It2> r2(r); - assert((r1 - r2) == x); -} - -TEST_CONSTEXPR_CXX17 bool tests() { - char s[3] = {0}; - - // Test same base iterator type - test(s, s, 0); - test(s, s+1, 1); - test(s+1, s, -1); - - // Test non-subtractable base iterator types - static_assert( HasMinus<std::__unconstrained_reverse_iterator<int*>, std::__unconstrained_reverse_iterator<int*> >::value, ""); -#if TEST_STD_VER >= 11 - static_assert(!HasMinus<std::__unconstrained_reverse_iterator<int*>, std::__unconstrained_reverse_iterator<char*> >::value, ""); -#endif - - return true; -} - -int main(int, char**) { - tests(); -#if TEST_STD_VER > 14 - static_assert(tests(), ""); -#endif - return 0; -} diff --git a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/types.compile.pass.cpp b/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/types.compile.pass.cpp deleted file mode 100644 index f8ffef364f37a54eac5797756efdb3da691230fe..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/iterators/predef.iterators/__unconstrained_reverse_iterator/types.compile.pass.cpp +++ /dev/null @@ -1,106 +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 -// -//===----------------------------------------------------------------------===// - -// <iterator> - -// __unconstrained_reverse_iterator - -// Test nested types and data member: - -// template <BidirectionalIterator Iter> -// class __unconstrained_reverse_iterator { -// protected: -// Iter current; -// public: -// iterator<typename iterator_traits<Iterator>::iterator_category, -// typename iterator_traits<Iterator>::value_type, -// typename iterator_traits<Iterator>::difference_type, -// typename iterator_traits<Iterator>::pointer, -// typename iterator_traits<Iterator>::reference> { -// }; - -#include <iterator> -#include <type_traits> - -#include "test_macros.h" -#include "test_iterators.h" - -template <class It> -void test() { - typedef std::__unconstrained_reverse_iterator<It> R; - typedef std::iterator_traits<It> T; - static_assert((std::is_same<typename R::iterator_type, It>::value), ""); - static_assert((std::is_same<typename R::value_type, typename T::value_type>::value), ""); - static_assert((std::is_same<typename R::difference_type, typename T::difference_type>::value), ""); - static_assert((std::is_same<typename R::reference, typename T::reference>::value), ""); - static_assert((std::is_same<typename R::pointer, typename std::iterator_traits<It>::pointer>::value), ""); - -#if TEST_STD_VER <= 14 - typedef std::iterator<typename T::iterator_category, typename T::value_type> iterator_base; - static_assert((std::is_base_of<iterator_base, R>::value), ""); -#endif -#if TEST_STD_VER > 17 - if constexpr (std::is_same_v<typename T::iterator_category, std::contiguous_iterator_tag>) { - static_assert((std::is_same<typename R::iterator_category, std::random_access_iterator_tag>::value), ""); - } else { - static_assert((std::is_same<typename R::iterator_category, typename T::iterator_category>::value), ""); - } -#else - static_assert((std::is_same<typename R::iterator_category, typename T::iterator_category>::value), ""); -#endif -} - -#if TEST_STD_VER > 17 - -struct FooIter { - using iterator_category = std::bidirectional_iterator_tag; - using value_type = void*; - using difference_type = void*; - using pointer = void*; - using reference = int&; - int& operator*() const; -}; -template <> -struct std::indirectly_readable_traits<FooIter> { - using value_type = int; -}; -template <> -struct std::incrementable_traits<FooIter> { - using difference_type = char; -}; - -// Not using `FooIter::value_type`. -static_assert(std::is_same_v<typename std::__unconstrained_reverse_iterator<FooIter>::value_type, int>); -// Not using `FooIter::difference_type`. -static_assert(std::is_same_v<typename std::__unconstrained_reverse_iterator<FooIter>::difference_type, char>); - -#endif - -struct BarIter { - bool& operator*() const; -}; -template <> -struct std::iterator_traits<BarIter> { - using difference_type = char; - using value_type = char; - using pointer = char*; - using reference = char&; - using iterator_category = std::bidirectional_iterator_tag; -}; - -#if TEST_STD_VER > 17 - static_assert(std::is_same_v<typename std::__unconstrained_reverse_iterator<BarIter>::reference, bool&>); -#else - static_assert(std::is_same<typename std::__unconstrained_reverse_iterator<BarIter>::reference, char&>::value, ""); -#endif - -void test_all() { - test<bidirectional_iterator<char*> >(); - test<random_access_iterator<char*> >(); - test<char*>(); -} diff --git a/libcxx/test/libcxx/module_std.gen.py b/libcxx/test/libcxx/module_std.gen.py index 5acaa837d37e0a3ddab87a380c5ea09767b22630..fc23985caf30de46f144ff997b416600a0ef0785 100644 --- a/libcxx/test/libcxx/module_std.gen.py +++ b/libcxx/test/libcxx/module_std.gen.py @@ -16,11 +16,7 @@ # to be one monolitic test. Since the test doesn't take very long it's # not a huge issue. -# WARNING: Disabled at the bottom. Fix this test and remove the UNSUPPORTED line -# TODO: Re-enable this test once we understand why it keeps timing out. - # RUN: %{python} %s %{libcxx-dir}/utils -# END. import sys @@ -39,5 +35,4 @@ generator = module_test_generator( print("//--- module_std.sh.cpp") -print('// UNSUPPORTED: clang') generator.write_test("std") diff --git a/libcxx/test/libcxx/module_std_compat.gen.py b/libcxx/test/libcxx/module_std_compat.gen.py index a502276a1ccfc508db380b76962ac2ae02f2c141..000aa2998612202555a8e9113f870a8ed729ee68 100644 --- a/libcxx/test/libcxx/module_std_compat.gen.py +++ b/libcxx/test/libcxx/module_std_compat.gen.py @@ -16,11 +16,7 @@ # to be one monolitic test. Since the test doesn't take very long it's # not a huge issue. -# WARNING: Disabled at the bottom. Fix this test and remove the UNSUPPORTED line -# TODO: Re-enable this test once we understand why it keeps timing out. - # RUN: %{python} %s %{libcxx-dir}/utils -# END. import sys @@ -40,7 +36,6 @@ generator = module_test_generator( print("//--- module_std_compat.sh.cpp") -print("// UNSUPPORTED: clang") generator.write_test( "std.compat", module_c_headers, diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.db/rules.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.db/rules.pass.cpp index 4814f4aad87fbc04b013724f20b07dbf2d68d0bc..fcfc34625fbece55dee977ebf5d7b4eb92528677 100644 --- a/libcxx/test/libcxx/time/time.zone/time.zone.db/rules.pass.cpp +++ b/libcxx/test/libcxx/time/time.zone/time.zone.db/rules.pass.cpp @@ -17,7 +17,7 @@ // Tests the IANA database rules parsing and operations. // This is not part of the public tzdb interface. // The test uses private implementation headers. -// ADDITIONAL_COMPILE_FLAGS: -I %S/../../../../../src/include +// ADDITIONAL_COMPILE_FLAGS: -I %{libcxx-dir}/src/include #include <chrono> #include <fstream> diff --git a/libcxx/test/libcxx/time/time.zone/time.zone.db/zones.pass.cpp b/libcxx/test/libcxx/time/time.zone/time.zone.db/zones.pass.cpp index 8571e0d05ebbd658ee2dc49ebdd16e98ede0ac66..e97b36fca2bb62529603f16615e76b53a8a842cb 100644 --- a/libcxx/test/libcxx/time/time.zone/time.zone.db/zones.pass.cpp +++ b/libcxx/test/libcxx/time/time.zone/time.zone.db/zones.pass.cpp @@ -17,7 +17,7 @@ // Tests the IANA database zones parsing and operations. // This is not part of the public tzdb interface. // The test uses private implementation headers. -// ADDITIONAL_COMPILE_FLAGS: -I %S/../../../../../src/include +// ADDITIONAL_COMPILE_FLAGS: -I %{libcxx-dir}/src/include #include <cassert> #include <chrono> diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv index 678a986e522aa0945b5d167e837c1d5cb5ad98de..2e246644f626ccc3a1837727536cd9fdf52c2799 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx03.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv @@ -266,9 +266,15 @@ filesystem system_error filesystem type_traits filesystem version format array +format cctype +format cerrno +format clocale format cmath format cstddef format cstdint +format cstdlib +format cstring +format cwchar format initializer_list format limits format locale diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv index c3875fa2cfc06f1c6cd20376609562f4f1b5087e..e074bf1f7dcc8d145b2eab099d73e1d93cb36e6e 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx11.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv @@ -267,9 +267,15 @@ filesystem system_error filesystem type_traits filesystem version format array +format cctype +format cerrno +format clocale format cmath format cstddef format cstdint +format cstdlib +format cstring +format cwchar format initializer_list format limits format locale diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv index e28e0cd44fed95824be72b477d730bcef094dcab..88f9c24f086462ac97dc33b191dbb293a3374711 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx14.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv @@ -269,9 +269,15 @@ filesystem system_error filesystem type_traits filesystem version format array +format cctype +format cerrno +format clocale format cmath format cstddef format cstdint +format cstdlib +format cstring +format cwchar format initializer_list format limits format locale diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv index e28e0cd44fed95824be72b477d730bcef094dcab..88f9c24f086462ac97dc33b191dbb293a3374711 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx17.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv @@ -269,9 +269,15 @@ filesystem system_error filesystem type_traits filesystem version format array +format cctype +format cerrno +format clocale format cmath format cstddef format cstdint +format cstdlib +format cstring +format cwchar format initializer_list format limits format locale diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv index eec71f4fc6282e2284a087b5a0cfaec751409863..27f59660fb98dc9c8f3d94c3dc9c7b5c33687aa5 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx20.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv @@ -113,14 +113,19 @@ charconv type_traits charconv version chrono array chrono bit +chrono cctype +chrono cerrno chrono charconv +chrono clocale chrono cmath chrono compare chrono concepts chrono cstddef chrono cstdint +chrono cstdlib chrono cstring chrono ctime +chrono cwchar chrono forward_list chrono limits chrono locale @@ -275,9 +280,15 @@ filesystem system_error filesystem type_traits filesystem version format array +format cctype +format cerrno +format clocale format cmath format cstddef format cstdint +format cstdlib +format cstring +format cwchar format initializer_list format limits format locale diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv index daa3e17698bbed1c36bcf58e9be900df5d89ffaf..69429b5bce8250f4441b4a4db0b25391cf76dc9e 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx23.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv @@ -68,15 +68,20 @@ charconv limits charconv new charconv version chrono array +chrono cctype +chrono cerrno +chrono clocale chrono cmath chrono compare chrono cstddef chrono cstdint +chrono cstdlib +chrono cstring chrono ctime +chrono cwchar chrono forward_list chrono initializer_list chrono limits -chrono locale chrono new chrono optional chrono ostream @@ -86,6 +91,7 @@ chrono stdexcept chrono string chrono string_view chrono tuple +chrono typeinfo chrono vector chrono version cinttypes cstdint @@ -132,12 +138,10 @@ coroutine compare coroutine cstddef coroutine cstdint coroutine cstring -coroutine limits coroutine version cstddef version ctgmath ccomplex ctgmath cmath -cwchar cstddef cwchar cwctype cwctype cctype deque compare @@ -156,7 +160,6 @@ exception cstdlib exception new exception typeinfo exception version -execution cstddef execution version expected cstddef expected initializer_list @@ -167,7 +170,6 @@ experimental/iterator iterator experimental/memory cstddef experimental/memory cstdint experimental/memory cstring -experimental/memory limits experimental/propagate_const cstddef experimental/simd cstddef experimental/simd cstdint @@ -187,20 +189,24 @@ filesystem string filesystem string_view filesystem version format array +format cctype +format cerrno +format clocale format cmath format cstddef format cstdint +format cstdlib +format cstring +format cwchar format initializer_list format limits -format locale format new format optional -format queue -format stack format stdexcept format string format string_view format tuple +format typeinfo format version forward_list compare forward_list cstddef @@ -397,7 +403,6 @@ optional cstddef optional cstdint optional cstring optional initializer_list -optional limits optional new optional version ostream bitset @@ -447,6 +452,7 @@ random vector random version ranges compare ranges cstddef +ranges cstdint ranges cwchar ranges initializer_list ranges iterator @@ -674,7 +680,6 @@ vector cstdlib vector cstring vector cwchar vector initializer_list -vector iosfwd vector limits vector new vector stdexcept diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv index daa3e17698bbed1c36bcf58e9be900df5d89ffaf..69429b5bce8250f4441b4a4db0b25391cf76dc9e 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx26.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv @@ -68,15 +68,20 @@ charconv limits charconv new charconv version chrono array +chrono cctype +chrono cerrno +chrono clocale chrono cmath chrono compare chrono cstddef chrono cstdint +chrono cstdlib +chrono cstring chrono ctime +chrono cwchar chrono forward_list chrono initializer_list chrono limits -chrono locale chrono new chrono optional chrono ostream @@ -86,6 +91,7 @@ chrono stdexcept chrono string chrono string_view chrono tuple +chrono typeinfo chrono vector chrono version cinttypes cstdint @@ -132,12 +138,10 @@ coroutine compare coroutine cstddef coroutine cstdint coroutine cstring -coroutine limits coroutine version cstddef version ctgmath ccomplex ctgmath cmath -cwchar cstddef cwchar cwctype cwctype cctype deque compare @@ -156,7 +160,6 @@ exception cstdlib exception new exception typeinfo exception version -execution cstddef execution version expected cstddef expected initializer_list @@ -167,7 +170,6 @@ experimental/iterator iterator experimental/memory cstddef experimental/memory cstdint experimental/memory cstring -experimental/memory limits experimental/propagate_const cstddef experimental/simd cstddef experimental/simd cstdint @@ -187,20 +189,24 @@ filesystem string filesystem string_view filesystem version format array +format cctype +format cerrno +format clocale format cmath format cstddef format cstdint +format cstdlib +format cstring +format cwchar format initializer_list format limits -format locale format new format optional -format queue -format stack format stdexcept format string format string_view format tuple +format typeinfo format version forward_list compare forward_list cstddef @@ -397,7 +403,6 @@ optional cstddef optional cstdint optional cstring optional initializer_list -optional limits optional new optional version ostream bitset @@ -447,6 +452,7 @@ random vector random version ranges compare ranges cstddef +ranges cstdint ranges cwchar ranges initializer_list ranges iterator @@ -674,7 +680,6 @@ vector cstdlib vector cstring vector cwchar vector initializer_list -vector iosfwd vector limits vector new vector stdexcept diff --git a/libcxx/test/libcxx/utilities/memory/default.allocator/allocator_types.void.cxx20_allocator_void_no_members.verify.cpp b/libcxx/test/libcxx/utilities/memory/default.allocator/allocator_types.void.cxx20_allocator_void_no_members.verify.cpp deleted file mode 100644 index 8888683a044f27208f39eeb147c8b17fceec0e81..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/utilities/memory/default.allocator/allocator_types.void.cxx20_allocator_void_no_members.verify.cpp +++ /dev/null @@ -1,25 +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 -// -//===----------------------------------------------------------------------===// - -// Check that members of std::allocator<void> are not provided in C++20 -// with _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_VOID_SPECIALIZATION but without -// _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS. - -// UNSUPPORTED: c++03, c++11, c++14, c++17 -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_VOID_SPECIALIZATION -// -// Ignore any extra errors arising from typo correction. -// ADDITIONAL_COMPILE_FLAGS: -Xclang -verify-ignore-unexpected=error - -#include <memory> - -std::allocator<void>::pointer x; // expected-error-re {{no {{(type|template)}} named 'pointer'}} -std::allocator<void>::const_pointer y; // expected-error-re {{no {{(type|template)}} named 'const_pointer'}} -std::allocator<void>::value_type z; // expected-error-re {{no {{(type|template)}} named 'value_type'}} -std::allocator<void>::rebind<int>::other t; // expected-error-re {{no {{(type|template)}} named 'rebind'}} diff --git a/libcxx/test/libcxx/utilities/memory/default.allocator/allocator_types.void.cxx20_with_removed_members.compile.pass.cpp b/libcxx/test/libcxx/utilities/memory/default.allocator/allocator_types.void.cxx20_with_removed_members.compile.pass.cpp deleted file mode 100644 index 3f151edefe1cdc347544f7e0a738c296876c8cba..0000000000000000000000000000000000000000 --- a/libcxx/test/libcxx/utilities/memory/default.allocator/allocator_types.void.cxx20_with_removed_members.compile.pass.cpp +++ /dev/null @@ -1,22 +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 -// -//===----------------------------------------------------------------------===// - -// Check that the nested types of std::allocator<void> are provided in C++20 -// with a flag that keeps the removed members. - -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_VOID_SPECIALIZATION - -#include <memory> -#include <type_traits> - -static_assert((std::is_same<std::allocator<void>::pointer, void*>::value), ""); -static_assert((std::is_same<std::allocator<void>::const_pointer, const void*>::value), ""); -static_assert((std::is_same<std::allocator<void>::value_type, void>::value), ""); -static_assert((std::is_same<std::allocator<void>::rebind<int>::other, std::allocator<int> >::value), ""); diff --git a/libcxx/test/libcxx/utilities/tuple/__tuple_like.compile.pass.cpp b/libcxx/test/libcxx/utilities/tuple/__tuple_like.compile.pass.cpp index b1d199865decc136f71d4d4ff920c3d4b82bd5fc..2c54fb5a10e134a322848e09adf5531ee452eeb5 100644 --- a/libcxx/test/libcxx/utilities/tuple/__tuple_like.compile.pass.cpp +++ b/libcxx/test/libcxx/utilities/tuple/__tuple_like.compile.pass.cpp @@ -15,6 +15,7 @@ // template<class T> // concept tuple-like; // exposition only +#include <__tuple/tuple_like.h> #include <array> #include <complex> #include <ranges> diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill.pass.cpp index da56ec30f128b1b224bdc6ad67ca3efd32be1905..481d565961b2b5c14377395a4a8c4488fbd284e5 100644 --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill.pass.cpp @@ -14,62 +14,91 @@ // fill(Iter first, Iter last, const T& value); #include <algorithm> +#include <array> #include <cassert> +#include <vector> #include "test_macros.h" #include "test_iterators.h" -#if TEST_STD_VER > 17 -TEST_CONSTEXPR bool test_constexpr() { - int ia[] = {0, 1, 2, 3, 4}; - - std::fill(std::begin(ia), std::end(ia), 5); +template <class Iter, class Container> +TEST_CONSTEXPR_CXX20 void +test(Container in, size_t from, size_t to, typename Container::value_type value, Container expected) { + std::fill(Iter(in.data() + from), Iter(in.data() + to), value); + assert(in == expected); +} - return std::all_of(std::begin(ia), std::end(ia), [](int a) {return a == 5; }) - ; +template <class T> +struct Test { + template <class Iter> + TEST_CONSTEXPR_CXX20 void operator()() { + { + std::array<T, 4> in = {1, 2, 3, 4}; + std::array<T, 4> expected = {5, 5, 5, 5}; + test<Iter>(in, 0, 4, 5, expected); } -#endif - -template <class Iter> -void -test_char() -{ - const unsigned n = 4; - char ca[n] = {0}; - std::fill(Iter(ca), Iter(ca+n), char(1)); - assert(ca[0] == 1); - assert(ca[1] == 1); - assert(ca[2] == 1); - assert(ca[3] == 1); -} + { + std::array<T, 4> in = {1, 2, 3, 4}; + std::array<T, 4> expected = {1, 5, 5, 4}; + test<Iter>(in, 1, 3, 5, expected); + } + } +}; -template <class Iter> -void -test_int() -{ - const unsigned n = 4; - int ia[n] = {0}; - std::fill(Iter(ia), Iter(ia+n), 1); - assert(ia[0] == 1); - assert(ia[1] == 1); - assert(ia[2] == 1); - assert(ia[3] == 1); +TEST_CONSTEXPR_CXX20 bool test() { + types::for_each(types::forward_iterator_list<char*>(), Test<char>()); + types::for_each(types::forward_iterator_list<int*>(), Test<int>()); + { // test vector<bool>::iterator optimization + { // simple case + std::vector<bool> in(4, false); + std::vector<bool> expected(4, true); + std::fill(in.begin(), in.end(), true); + assert(in == expected); + } + { // partial byte in the front is not filled + std::vector<bool> in(8, false); + std::vector<bool> expected(8, true); + expected[0] = false; + expected[1] = false; + std::fill(in.begin() + 2, in.end(), true); + assert(in == expected); + } + { // partial byte in the back is not filled + std::vector<bool> in(8, false); + std::vector<bool> expected(8, true); + expected[6] = false; + expected[7] = false; + std::fill(in.begin(), in.end() - 2, true); + assert(in == expected); + } + { // partial byte in the front and back is not filled + std::vector<bool> in(16, false); + std::vector<bool> expected(16, true); + expected[0] = false; + expected[1] = false; + expected[14] = false; + expected[15] = false; + std::fill(in.begin() + 2, in.end() - 2, true); + assert(in == expected); + } + { // only a few bits of a byte are set + std::vector<bool> in(8, false); + std::vector<bool> expected(8, true); + expected[0] = false; + expected[1] = false; + expected[6] = false; + expected[7] = false; + std::fill(in.begin() + 2, in.end() - 2, true); + assert(in == expected); + } + } + return true; } -int main(int, char**) -{ - test_char<forward_iterator<char*> >(); - test_char<bidirectional_iterator<char*> >(); - test_char<random_access_iterator<char*> >(); - test_char<char*>(); - - test_int<forward_iterator<int*> >(); - test_int<bidirectional_iterator<int*> >(); - test_int<random_access_iterator<int*> >(); - test_int<int*>(); - -#if TEST_STD_VER > 17 - static_assert(test_constexpr()); +int main(int, char**) { + test(); +#if TEST_STD_VER >= 20 + static_assert(test()); #endif return 0; diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.count/count.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.count/count.pass.cpp index 904100c1cf0bb110eae7962ac0109eb6a7c3dcce..7654a4b0c7f007a5cc04157f3a184577daf5f405 100644 --- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.count/count.pass.cpp +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.count/count.pass.cpp @@ -14,7 +14,7 @@ // count(Iter first, Iter last, const T& value); // ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=20000000 -// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-ops-limit): -fconstexpr-ops-limit=70000000 +// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-ops-limit): -fconstexpr-ops-limit=80000000 #include <algorithm> #include <cassert> diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.count/ranges.count.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.count/ranges.count.pass.cpp index b17272ea90cdddcf4d65822334696bb2faf277d3..b6631add7e48a70a0f517e7419bd07c2caf0d32f 100644 --- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.count/ranges.count.pass.cpp +++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.count/ranges.count.pass.cpp @@ -11,7 +11,7 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=20000000 -// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-ops-limit): -fconstexpr-ops-limit=70000000 +// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-ops-limit): -fconstexpr-ops-limit=80000000 // template<input_iterator I, sentinel_for<I> S, class T, class Proj = identity> // requires indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*> diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/mismatch.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/mismatch.pass.cpp index cc588c095ccfb2f37895842ce10acd28fc21dbdc..eb5f7cacdde34b4bd18335ca00b8f2751a8dd99b 100644 --- a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/mismatch.pass.cpp +++ b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/mismatch.pass.cpp @@ -16,79 +16,201 @@ // template<InputIterator Iter1, InputIterator Iter2Pred> // constexpr pair<Iter1, Iter2> // constexpr after c++17 // mismatch(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2); // C++14 +// +// template<InputIterator Iter1, InputIterator Iter2, +// Predicate<auto, Iter1::value_type, Iter2::value_type> Pred> +// requires CopyConstructible<Pred> +// constexpr pair<Iter1, Iter2> // constexpr after c++17 +// mismatch(Iter1 first1, Iter1 last1, Iter2 first2, Pred pred); +// +// template<InputIterator Iter1, InputIterator Iter2, Predicate Pred> +// constexpr pair<Iter1, Iter2> // constexpr after c++17 +// mismatch(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2, Pred pred); // C++14 + +// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=50000000 +// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-ops-limit): -fconstexpr-ops-limit=100000000 #include <algorithm> +#include <array> #include <cassert> +#include <vector> #include "test_macros.h" #include "test_iterators.h" - -#if TEST_STD_VER > 17 -TEST_CONSTEXPR bool test_constexpr() { - int ia[] = {1, 3, 6, 7}; - int ib[] = {1, 3}; - int ic[] = {1, 3, 5, 7}; - typedef cpp17_input_iterator<int*> II; - typedef bidirectional_iterator<int*> BI; - - auto p1 = std::mismatch(std::begin(ia), std::end(ia), std::begin(ic)); - if (p1.first != ia+2 || p1.second != ic+2) - return false; - - auto p2 = std::mismatch(std::begin(ia), std::end(ia), std::begin(ic), std::end(ic)); - if (p2.first != ia+2 || p2.second != ic+2) - return false; - - auto p3 = std::mismatch(std::begin(ib), std::end(ib), std::begin(ic)); - if (p3.first != ib+2 || p3.second != ic+2) - return false; - - auto p4 = std::mismatch(std::begin(ib), std::end(ib), std::begin(ic), std::end(ic)); - if (p4.first != ib+2 || p4.second != ic+2) - return false; - - auto p5 = std::mismatch(II(std::begin(ib)), II(std::end(ib)), II(std::begin(ic))); - if (p5.first != II(ib+2) || p5.second != II(ic+2)) - return false; - auto p6 = std::mismatch(BI(std::begin(ib)), BI(std::end(ib)), BI(std::begin(ic)), BI(std::end(ic))); - if (p6.first != BI(ib+2) || p6.second != BI(ic+2)) - return false; - - return true; - } +#include "type_algorithms.h" + +template <class Iter, class Container1, class Container2> +TEST_CONSTEXPR_CXX20 void check(Container1 lhs, Container2 rhs, size_t offset) { + if (lhs.size() == rhs.size()) { + assert(std::mismatch(Iter(lhs.data()), Iter(lhs.data() + lhs.size()), Iter(rhs.data())) == + std::make_pair(Iter(lhs.data() + offset), Iter(rhs.data() + offset))); + + assert(std::mismatch(Iter(lhs.data()), + Iter(lhs.data() + lhs.size()), + Iter(rhs.data()), + std::equal_to<typename Container1::value_type>()) == + std::make_pair(Iter(lhs.data() + offset), Iter(rhs.data() + offset))); + } + +#if TEST_STD_VER >= 14 + assert( + std::mismatch(Iter(lhs.data()), Iter(lhs.data() + lhs.size()), Iter(rhs.data()), Iter(rhs.data() + rhs.size())) == + std::make_pair(Iter(lhs.data() + offset), Iter(rhs.data() + offset))); + + assert(std::mismatch(Iter(lhs.data()), + Iter(lhs.data() + lhs.size()), + Iter(rhs.data()), + Iter(rhs.data() + rhs.size()), + std::equal_to<typename Container1::value_type>()) == + std::make_pair(Iter(lhs.data() + offset), Iter(rhs.data() + offset))); #endif +} -int main(int, char**) -{ - int ia[] = {0, 1, 2, 2, 0, 1, 2, 3}; - const unsigned sa = sizeof(ia)/sizeof(ia[0]); - int ib[] = {0, 1, 2, 3, 0, 1, 2, 3}; - const unsigned sb = sizeof(ib)/sizeof(ib[0]); ((void)sb); // unused in C++11 - - typedef cpp17_input_iterator<const int*> II; - typedef random_access_iterator<const int*> RAI; - - assert(std::mismatch(II(ia), II(ia + sa), II(ib)) - == (std::pair<II, II>(II(ia+3), II(ib+3)))); - - assert(std::mismatch(RAI(ia), RAI(ia + sa), RAI(ib)) - == (std::pair<RAI, RAI>(RAI(ia+3), RAI(ib+3)))); - -#if TEST_STD_VER > 11 // We have the four iteration version - assert(std::mismatch(II(ia), II(ia + sa), II(ib), II(ib+sb)) - == (std::pair<II, II>(II(ia+3), II(ib+3)))); +struct NonTrivial { + int i_; + + TEST_CONSTEXPR_CXX20 NonTrivial(int i) : i_(i) {} + TEST_CONSTEXPR_CXX20 NonTrivial(NonTrivial&& other) : i_(other.i_) { other.i_ = 0; } + + TEST_CONSTEXPR_CXX20 friend bool operator==(const NonTrivial& lhs, const NonTrivial& rhs) { return lhs.i_ == rhs.i_; } +}; + +struct ModTwoComp { + TEST_CONSTEXPR_CXX20 bool operator()(int lhs, int rhs) { return lhs % 2 == rhs % 2; } +}; + +template <class Iter> +TEST_CONSTEXPR_CXX20 bool test() { + { // empty ranges + std::array<int, 0> lhs = {}; + std::array<int, 0> rhs = {}; + check<Iter>(lhs, rhs, 0); + } + + { // same range without mismatch + std::array<int, 8> lhs = {0, 1, 2, 3, 0, 1, 2, 3}; + std::array<int, 8> rhs = {0, 1, 2, 3, 0, 1, 2, 3}; + check<Iter>(lhs, rhs, 8); + } + + { // same range with mismatch + std::array<int, 8> lhs = {0, 1, 2, 2, 0, 1, 2, 3}; + std::array<int, 8> rhs = {0, 1, 2, 3, 0, 1, 2, 3}; + check<Iter>(lhs, rhs, 3); + } + + { // second range is smaller + std::array<int, 8> lhs = {0, 1, 2, 2, 0, 1, 2, 3}; + std::array<int, 2> rhs = {0, 1}; + check<Iter>(lhs, rhs, 2); + } + + { // first range is smaller + std::array<int, 2> lhs = {0, 1}; + std::array<int, 8> rhs = {0, 1, 2, 2, 0, 1, 2, 3}; + check<Iter>(lhs, rhs, 2); + } + + { // use a custom comparator + std::array<int, 4> lhs = {0, 2, 3, 4}; + std::array<int, 4> rhs = {0, 0, 4, 4}; + assert(std::mismatch(lhs.data(), lhs.data() + lhs.size(), rhs.data(), ModTwoComp()) == + std::make_pair(lhs.data() + 2, rhs.data() + 2)); +#if TEST_STD_VER >= 14 + assert(std::mismatch(lhs.data(), lhs.data() + lhs.size(), rhs.data(), rhs.data() + rhs.size(), ModTwoComp()) == + std::make_pair(lhs.data() + 2, rhs.data() + 2)); +#endif + } - assert(std::mismatch(RAI(ia), RAI(ia + sa), RAI(ib), RAI(ib+sb)) - == (std::pair<RAI, RAI>(RAI(ia+3), RAI(ib+3)))); + return true; +} +struct Test { + template <class Iter> + TEST_CONSTEXPR_CXX20 void operator()() { + test<Iter>(); + } +}; + +TEST_CONSTEXPR_CXX20 bool test() { + types::for_each(types::cpp17_input_iterator_list<int*>(), Test()); + + { // use a non-integer type to also test the general case - all elements match + std::array<NonTrivial, 8> lhs = {1, 2, 3, 4, 5, 6, 7, 8}; + std::array<NonTrivial, 8> rhs = {1, 2, 3, 4, 5, 6, 7, 8}; + check<NonTrivial*>(std::move(lhs), std::move(rhs), 8); + } + + { // use a non-integer type to also test the general case - not all elements match + std::array<NonTrivial, 8> lhs = {1, 2, 3, 4, 7, 6, 7, 8}; + std::array<NonTrivial, 8> rhs = {1, 2, 3, 4, 5, 6, 7, 8}; + check<NonTrivial*>(std::move(lhs), std::move(rhs), 4); + } + + return true; +} - assert(std::mismatch(II(ia), II(ia + sa), II(ib), II(ib+2)) - == (std::pair<II, II>(II(ia+2), II(ib+2)))); +int main(int, char**) { + test(); +#if TEST_STD_VER >= 20 + static_assert(test()); #endif -#if TEST_STD_VER > 17 - static_assert(test_constexpr()); -#endif + { // check with a lot of elements to test the vectorization optimization + { + std::vector<char> lhs(256); + std::vector<char> rhs(256); + for (size_t i = 0; i != lhs.size(); ++i) { + lhs[i] = 1; + check<char*>(lhs, rhs, i); + lhs[i] = 0; + rhs[i] = 1; + check<char*>(lhs, rhs, i); + rhs[i] = 0; + } + } + { + std::vector<int> lhs(256); + std::vector<int> rhs(256); + for (size_t i = 0; i != lhs.size(); ++i) { + lhs[i] = 1; + check<int*>(lhs, rhs, i); + lhs[i] = 0; + rhs[i] = 1; + check<int*>(lhs, rhs, i); + rhs[i] = 0; + } + } + } + + { // check the tail of the vectorized loop + for (size_t vec_size = 1; vec_size != 256; ++vec_size) { + { + std::vector<char> lhs(vec_size); + std::vector<char> rhs(vec_size); + + check<char*>(lhs, rhs, lhs.size()); + lhs.back() = 1; + check<char*>(lhs, rhs, lhs.size() - 1); + lhs.back() = 0; + rhs.back() = 1; + check<char*>(lhs, rhs, lhs.size() - 1); + rhs.back() = 0; + } + { + std::vector<int> lhs(vec_size); + std::vector<int> rhs(vec_size); + + check<int*>(lhs, rhs, lhs.size()); + lhs.back() = 1; + check<int*>(lhs, rhs, lhs.size() - 1); + lhs.back() = 0; + rhs.back() = 1; + check<int*>(lhs, rhs, lhs.size() - 1); + rhs.back() = 0; + } + } + } return 0; } diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/mismatch_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/mismatch_pred.pass.cpp deleted file mode 100644 index bda4ec7ba5ed60ead3896a5d1e3b13b5c44c5a16..0000000000000000000000000000000000000000 --- a/libcxx/test/std/algorithms/alg.nonmodifying/mismatch/mismatch_pred.pass.cpp +++ /dev/null @@ -1,119 +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 -// -//===----------------------------------------------------------------------===// - -// <algorithm> - -// template<InputIterator Iter1, InputIterator Iter2, -// Predicate<auto, Iter1::value_type, Iter2::value_type> Pred> -// requires CopyConstructible<Pred> -// constexpr pair<Iter1, Iter2> // constexpr after c++17 -// mismatch(Iter1 first1, Iter1 last1, Iter2 first2, Pred pred); -// -// template<InputIterator Iter1, InputIterator Iter2, Predicate Pred> -// constexpr pair<Iter1, Iter2> // constexpr after c++17 -// mismatch(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2, Pred pred); // C++14 - -#include <algorithm> -#include <functional> -#include <cassert> - -#include "test_macros.h" -#include "test_iterators.h" -#include "counting_predicates.h" - -#if TEST_STD_VER > 17 -TEST_CONSTEXPR bool eq(int a, int b) { return a == b; } - -TEST_CONSTEXPR bool test_constexpr() { - int ia[] = {1, 3, 6, 7}; - int ib[] = {1, 3}; - int ic[] = {1, 3, 5, 7}; - typedef cpp17_input_iterator<int*> II; - typedef bidirectional_iterator<int*> BI; - - auto p1 = std::mismatch(std::begin(ia), std::end(ia), std::begin(ic), eq); - if (p1.first != ia+2 || p1.second != ic+2) - return false; - - auto p2 = std::mismatch(std::begin(ia), std::end(ia), std::begin(ic), std::end(ic), eq); - if (p2.first != ia+2 || p2.second != ic+2) - return false; - - auto p3 = std::mismatch(std::begin(ib), std::end(ib), std::begin(ic), eq); - if (p3.first != ib+2 || p3.second != ic+2) - return false; - - auto p4 = std::mismatch(std::begin(ib), std::end(ib), std::begin(ic), std::end(ic), eq); - if (p4.first != ib+2 || p4.second != ic+2) - return false; - - auto p5 = std::mismatch(II(std::begin(ib)), II(std::end(ib)), II(std::begin(ic)), eq); - if (p5.first != II(ib+2) || p5.second != II(ic+2)) - return false; - auto p6 = std::mismatch(BI(std::begin(ib)), BI(std::end(ib)), BI(std::begin(ic)), BI(std::end(ic)), eq); - if (p6.first != BI(ib+2) || p6.second != BI(ic+2)) - return false; - - return true; - } -#endif - - -#if TEST_STD_VER > 11 -#define HAS_FOUR_ITERATOR_VERSION -#endif - -int main(int, char**) -{ - int ia[] = {0, 1, 2, 2, 0, 1, 2, 3}; - const unsigned sa = sizeof(ia)/sizeof(ia[0]); - int ib[] = {0, 1, 2, 3, 0, 1, 2, 3}; - const unsigned sb = sizeof(ib)/sizeof(ib[0]); ((void)sb); // unused in C++11 - - typedef cpp17_input_iterator<const int*> II; - typedef random_access_iterator<const int*> RAI; - typedef std::equal_to<int> EQ; - - assert(std::mismatch(II(ia), II(ia + sa), II(ib), EQ()) - == (std::pair<II, II>(II(ia+3), II(ib+3)))); - assert(std::mismatch(RAI(ia), RAI(ia + sa), RAI(ib), EQ()) - == (std::pair<RAI, RAI>(RAI(ia+3), RAI(ib+3)))); - - binary_counting_predicate<EQ, int> bcp((EQ())); - assert(std::mismatch(RAI(ia), RAI(ia + sa), RAI(ib), std::ref(bcp)) - == (std::pair<RAI, RAI>(RAI(ia+3), RAI(ib+3)))); - assert(bcp.count() > 0 && bcp.count() < sa); - bcp.reset(); - -#if TEST_STD_VER >= 14 - assert(std::mismatch(II(ia), II(ia + sa), II(ib), II(ib + sb), EQ()) - == (std::pair<II, II>(II(ia+3), II(ib+3)))); - assert(std::mismatch(RAI(ia), RAI(ia + sa), RAI(ib), RAI(ib + sb), EQ()) - == (std::pair<RAI, RAI>(RAI(ia+3), RAI(ib+3)))); - - assert(std::mismatch(II(ia), II(ia + sa), II(ib), II(ib + sb), std::ref(bcp)) - == (std::pair<II, II>(II(ia+3), II(ib+3)))); - assert(bcp.count() > 0 && bcp.count() < std::min(sa, sb)); -#endif - - assert(std::mismatch(ia, ia + sa, ib, EQ()) == - (std::pair<int*,int*>(ia+3,ib+3))); - -#if TEST_STD_VER >= 14 - assert(std::mismatch(ia, ia + sa, ib, ib + sb, EQ()) == - (std::pair<int*,int*>(ia+3,ib+3))); - assert(std::mismatch(ia, ia + sa, ib, ib + 2, EQ()) == - (std::pair<int*,int*>(ia+2,ib+2))); -#endif - -#if TEST_STD_VER > 17 - static_assert(test_constexpr()); -#endif - - return 0; -} diff --git a/libcxx/test/std/containers/sequences/deque/types.pass.cpp b/libcxx/test/std/containers/sequences/deque/types.pass.cpp index bfe4808f863d3ec10a7a69cb7925ef10abc4113d..8c14de0c77440a54f4d43af9846c7914a2fff511 100644 --- a/libcxx/test/std/containers/sequences/deque/types.pass.cpp +++ b/libcxx/test/std/containers/sequences/deque/types.pass.cpp @@ -28,9 +28,6 @@ // typedef std::reverse_iterator<const_iterator> const_reverse_iterator; // }; -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS - #include <deque> #include <iterator> #include <type_traits> @@ -47,14 +44,22 @@ test() typedef std::deque<T, Allocator> C; static_assert((std::is_same<typename C::value_type, T>::value), ""); - static_assert((std::is_same<typename C::value_type, typename Allocator::value_type>::value), ""); + static_assert( + (std::is_same<typename C::value_type, typename std::allocator_traits<Allocator>::value_type>::value), ""); static_assert((std::is_same<typename C::allocator_type, Allocator>::value), ""); - static_assert((std::is_same<typename C::size_type, typename Allocator::size_type>::value), ""); - static_assert((std::is_same<typename C::difference_type, typename Allocator::difference_type>::value), ""); - static_assert((std::is_same<typename C::reference, typename Allocator::reference>::value), ""); - static_assert((std::is_same<typename C::const_reference, typename Allocator::const_reference>::value), ""); - static_assert((std::is_same<typename C::pointer, typename Allocator::pointer>::value), ""); - static_assert((std::is_same<typename C::const_pointer, typename Allocator::const_pointer>::value), ""); + static_assert( + (std::is_same<typename C::size_type, typename std::allocator_traits<Allocator>::size_type>::value), ""); + static_assert( + (std::is_same<typename C::difference_type, typename std::allocator_traits<Allocator>::difference_type>::value), + ""); + static_assert( + (std::is_same<typename C::reference, typename std::allocator_traits<Allocator>::value_type&>::value), ""); + static_assert((std::is_same<typename C::const_reference, + const typename std::allocator_traits<Allocator>::value_type&>::value), + ""); + static_assert((std::is_same<typename C::pointer, typename std::allocator_traits<Allocator>::pointer>::value), ""); + static_assert( + (std::is_same<typename C::const_pointer, typename std::allocator_traits<Allocator>::const_pointer>::value), ""); static_assert((std::is_same< typename std::iterator_traits<typename C::iterator>::iterator_category, std::random_access_iterator_tag>::value), ""); diff --git a/libcxx/test/std/containers/sequences/list/types.pass.cpp b/libcxx/test/std/containers/sequences/list/types.pass.cpp index 0c1ca27745ce0ee953ceb5118918b5b29da417b1..8fe31e3949dec420647be9bf02205197f7a3269e 100644 --- a/libcxx/test/std/containers/sequences/list/types.pass.cpp +++ b/libcxx/test/std/containers/sequences/list/types.pass.cpp @@ -21,9 +21,6 @@ // typedef typename allocator_type::pointer pointer; // typedef typename allocator_type::const_pointer const_pointer; -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS - #include <list> #include <type_traits> @@ -38,10 +35,12 @@ int main(int, char**) typedef std::list<int> C; static_assert((std::is_same<C::value_type, int>::value), ""); static_assert((std::is_same<C::allocator_type, std::allocator<int> >::value), ""); - static_assert((std::is_same<C::reference, std::allocator<int>::reference>::value), ""); - static_assert((std::is_same<C::const_reference, std::allocator<int>::const_reference>::value), ""); - static_assert((std::is_same<C::pointer, std::allocator<int>::pointer>::value), ""); - static_assert((std::is_same<C::const_pointer, std::allocator<int>::const_pointer>::value), ""); + static_assert((std::is_same<C::reference, std::allocator_traits<std::allocator<int> >::value_type&>::value), ""); + static_assert( + (std::is_same<C::const_reference, const std::allocator_traits<std::allocator<int> >::value_type&>::value), ""); + static_assert((std::is_same<C::pointer, std::allocator_traits<std::allocator<int> >::pointer>::value), ""); + static_assert( + (std::is_same<C::const_pointer, std::allocator_traits<std::allocator<int> >::const_pointer>::value), ""); static_assert((std::is_signed<typename C::difference_type>::value), ""); static_assert((std::is_unsigned<typename C::size_type>::value), ""); diff --git a/libcxx/test/std/containers/sequences/vector/types.pass.cpp b/libcxx/test/std/containers/sequences/vector/types.pass.cpp index 4bcfbe7c3ea4d4dc1739db5773af4e21f51eb176..f4d7fa088842fca2ce5c143715fcf0039ef6b6d3 100644 --- a/libcxx/test/std/containers/sequences/vector/types.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/types.pass.cpp @@ -28,9 +28,6 @@ // typedef std::reverse_iterator<const_iterator> const_reverse_iterator; // }; -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS -// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS - #include <vector> #include <iterator> #include <type_traits> @@ -52,14 +49,22 @@ test() // blindly pulling typedefs out of the allocator. This is why we can't call // test<int, min_allocator<int>>() below. static_assert((std::is_same<typename C::value_type, T>::value), ""); - static_assert((std::is_same<typename C::value_type, typename Allocator::value_type>::value), ""); + static_assert( + (std::is_same<typename C::value_type, typename std::allocator_traits<Allocator>::value_type>::value), ""); static_assert((std::is_same<typename C::allocator_type, Allocator>::value), ""); - static_assert((std::is_same<typename C::size_type, typename Allocator::size_type>::value), ""); - static_assert((std::is_same<typename C::difference_type, typename Allocator::difference_type>::value), ""); - static_assert((std::is_same<typename C::reference, typename Allocator::reference>::value), ""); - static_assert((std::is_same<typename C::const_reference, typename Allocator::const_reference>::value), ""); - static_assert((std::is_same<typename C::pointer, typename Allocator::pointer>::value), ""); - static_assert((std::is_same<typename C::const_pointer, typename Allocator::const_pointer>::value), ""); + static_assert( + (std::is_same<typename C::size_type, typename std::allocator_traits<Allocator>::size_type>::value), ""); + static_assert( + (std::is_same<typename C::difference_type, typename std::allocator_traits<Allocator>::difference_type>::value), + ""); + static_assert( + (std::is_same<typename C::reference, typename std::allocator_traits<Allocator>::value_type&>::value), ""); + static_assert((std::is_same<typename C::const_reference, + const typename std::allocator_traits<Allocator>::value_type&>::value), + ""); + static_assert((std::is_same<typename C::pointer, typename std::allocator_traits<Allocator>::pointer>::value), ""); + static_assert( + (std::is_same<typename C::const_pointer, typename std::allocator_traits<Allocator>::const_pointer>::value), ""); static_assert((std::is_signed<typename C::difference_type>::value), ""); static_assert((std::is_unsigned<typename C::size_type>::value), ""); diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.verify.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.verify.cpp index 7ce00d70f8442b0f548178720dd5b34e24b4167c..2b2242e240a2cd70bb2688553354b3d22be29be9 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.verify.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/deduct.verify.cpp @@ -14,25 +14,20 @@ // -> vector<typename iterator_traits<InputIterator>::value_type, Allocator>; // -#include <deque> -#include <iterator> #include <cassert> #include <cstddef> - - -int main(int, char**) -{ -// Test the explicit deduction guides - -// Test the implicit deduction guides - { -// vector (allocator &) - std::vector vec((std::allocator<int>())); // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'vector'}} -// Note: The extra parens are necessary, since otherwise clang decides it is a function declaration. -// Also, we can't use {} instead of parens, because that constructs a -// deque<allocator<int>, allocator<allocator<int>>> - } - +#include <vector> + +int main(int, char**) { + // Test the explicit deduction guides + // TODO: Should there be tests for explicit deduction guides? + + // Test the implicit deduction guides + { + // vector (allocator &) + // expected-error@+1 {{no viable constructor or deduction guide for deduction of template arguments of 'vector'}} + std::vector vec(std::allocator< int>{}); + } return 0; } diff --git a/libcxx/test/std/depr.cerro/cerrno.syn.verify.cpp b/libcxx/test/std/depr.cerro/cerrno.syn.verify.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3a38605570dafbd6a9a8ec08a7b00307144a59ed --- /dev/null +++ b/libcxx/test/std/depr.cerro/cerrno.syn.verify.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: clang-modules-build +// UNSUPPORTED: apple-clang && c++03 + +// <cerrno> + +// tests LWG 3869 deprecated macros. +// +// Note the macros may not be defined. When they are not defined the +// ifdef XXX does not trigger a deprecated message. So use them in the +// ifdef and test for 2 deprecated messages. + +#include <cerrno> + +#ifdef ENODATA +[[maybe_unused]] int nodata = + ENODATA; // expected-warning@cerrno.syn.verify.cpp:* 2 {{macro 'ENODATA' has been marked as deprecated}} +#endif +#ifdef ENOSR +[[maybe_unused]] int nosr = + ENOSR; // expected-warning@cerrno.syn.verify.cpp:* 2 {{macro 'ENOSR' has been marked as deprecated}} +#endif +#ifdef ENOSTR +[[maybe_unused]] int nostr = + ENOSTR; // expected-warning@cerrno.syn.verify.cpp:* 2 {{macro 'ENOSTR' has been marked as deprecated}} +#endif +#ifdef ETIME +[[maybe_unused]] int timeout = + ETIME; // expected-warning@cerrno.syn.verify.cpp:* 2 {{macro 'ETIME' has been marked as deprecated}} +#endif diff --git a/libcxx/test/std/depr.cerro/system.error.syn.verify.cpp b/libcxx/test/std/depr.cerro/system.error.syn.verify.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fab5dd5b559350078c472229b9cac3ea7275f88c --- /dev/null +++ b/libcxx/test/std/depr.cerro/system.error.syn.verify.cpp @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// These macros do not seem to behave as expected on all Apple platforms. +// Since the macros are not provided newer POSIX versions it is expected the +// macros will be retroactively removed from C++. (The deprecation was +// retroactively.) +// UNSUPPORTED: apple-clang && (c++03 || clang-modules-build) + +// <system_error> + +// enum errc {...} + +// tests LWG 3869 deprecated enum members. + +#include <system_error> + +[[maybe_unused]] std::errc nodata = + std::errc::no_message_available; // expected-warning {{'no_message_available' is deprecated}} +[[maybe_unused]] std::errc nosr = + std::errc::no_stream_resources; // expected-warning {{'no_stream_resources' is deprecated}} +[[maybe_unused]] std::errc nostr = std::errc::not_a_stream; // expected-warning {{'not_a_stream' is deprecated}} +[[maybe_unused]] std::errc timeout = std::errc::stream_timeout; // expected-warning {{'stream_timeout' is deprecated}} diff --git a/libcxx/test/std/diagnostics/syserr/errc.pass.cpp b/libcxx/test/std/diagnostics/syserr/errc.pass.cpp index e44cb50102e3e15d827eb05321a2a06fb5e42a8b..4abee08ddc662904afe4f318ebf9a1a631706cf4 100644 --- a/libcxx/test/std/diagnostics/syserr/errc.pass.cpp +++ b/libcxx/test/std/diagnostics/syserr/errc.pass.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS + // <system_error> // enum errc {...} diff --git a/libcxx/test/std/experimental/simd/simd.class/simd_ctor_broadcast.pass.cpp b/libcxx/test/std/experimental/simd/simd.class/simd_ctor_broadcast.pass.cpp index 679cb1aa167c57a8e04eca75ca9db24800481839..8a291632a8ab1eb069f206307b98158389b9974d 100644 --- a/libcxx/test/std/experimental/simd/simd.class/simd_ctor_broadcast.pass.cpp +++ b/libcxx/test/std/experimental/simd/simd.class/simd_ctor_broadcast.pass.cpp @@ -41,7 +41,7 @@ struct CheckSimdBroadcastCtorFromVectorizedType { std::array<T, array_size> expected_value; std::fill(expected_value.begin(), expected_value.end(), 3); - types::for_each(arithmetic_no_bool_types(), BroadCastHelper<T, SimdAbi, array_size>(expected_value)); + types::for_each(simd_test_types(), BroadCastHelper<T, SimdAbi, array_size>(expected_value)); } }; @@ -110,7 +110,7 @@ template <class T, std::size_t> struct CheckBroadcastCtorTraits { template <class SimdAbi> void operator()() { - types::for_each(arithmetic_no_bool_types(), CheckBroadcastCtorTraitsHelper<T, SimdAbi>()); + types::for_each(simd_test_types(), CheckBroadcastCtorTraitsHelper<T, SimdAbi>()); static_assert(!has_broadcast_ctor<no_implicit_type<T>, T, SimdAbi>::value); static_assert(has_broadcast_ctor<implicit_type<T>, T, SimdAbi>::value); diff --git a/libcxx/test/std/experimental/simd/simd.class/simd_ctor_conversion.pass.cpp b/libcxx/test/std/experimental/simd/simd.class/simd_ctor_conversion.pass.cpp index 7ce4bed9c7db8ce58998980b81b4fda5567f815f..653704cd245af8b9b7f6361eb60801c3c50d698f 100644 --- a/libcxx/test/std/experimental/simd/simd.class/simd_ctor_conversion.pass.cpp +++ b/libcxx/test/std/experimental/simd/simd.class/simd_ctor_conversion.pass.cpp @@ -46,7 +46,7 @@ struct CheckConversionSimdCtor { for (size_t i = 0; i < array_size; ++i) expected_value[i] = static_cast<T>(i); - types::for_each(arithmetic_no_bool_types(), ConversionHelper<T, SimdAbi, array_size>(expected_value)); + types::for_each(simd_test_types(), ConversionHelper<T, SimdAbi, array_size>(expected_value)); } }; @@ -70,7 +70,7 @@ struct CheckConversionSimdCtorTraits { void operator()() { constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>; - types::for_each(arithmetic_no_bool_types(), CheckConversionSimdCtorTraitsHelper<T, SimdAbi, array_size>()); + types::for_each(simd_test_types(), CheckConversionSimdCtorTraitsHelper<T, SimdAbi, array_size>()); } }; diff --git a/libcxx/test/std/experimental/simd/simd.class/simd_ctor_load.pass.cpp b/libcxx/test/std/experimental/simd/simd.class/simd_ctor_load.pass.cpp index 3992f3e450cb2a7153bac298c0afabffe04bd91d..3f663d9c97355d3a92268559cf6fdf3836ba451a 100644 --- a/libcxx/test/std/experimental/simd/simd.class/simd_ctor_load.pass.cpp +++ b/libcxx/test/std/experimental/simd/simd.class/simd_ctor_load.pass.cpp @@ -59,9 +59,9 @@ struct CheckSimdLoadCtor { void operator()() { constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>; - types::for_each(arithmetic_no_bool_types(), ElementAlignedLoadCtorHelper<T, SimdAbi, array_size>()); - types::for_each(arithmetic_no_bool_types(), VectorAlignedLoadCtorHelper<T, SimdAbi, array_size>()); - types::for_each(arithmetic_no_bool_types(), OveralignedLoadCtorHelper<T, SimdAbi, array_size>()); + types::for_each(simd_test_types(), ElementAlignedLoadCtorHelper<T, SimdAbi, array_size>()); + types::for_each(simd_test_types(), VectorAlignedLoadCtorHelper<T, SimdAbi, array_size>()); + types::for_each(simd_test_types(), OveralignedLoadCtorHelper<T, SimdAbi, array_size>()); } }; diff --git a/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_ctor_conversion.pass.cpp b/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_ctor_conversion.pass.cpp index dc0764f937fc04a95cd942d70275f1360e9013ab..7910b2cc252204b90e2982b2a1e1de94a4142e72 100644 --- a/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_ctor_conversion.pass.cpp +++ b/libcxx/test/std/experimental/simd/simd.mask.class/simd_mask_ctor_conversion.pass.cpp @@ -42,7 +42,7 @@ struct CheckConversionMaskCtor { constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>; std::array<bool, array_size> expected_value{}; - types::for_each(arithmetic_no_bool_types(), ConversionHelper<T, SimdAbi, array_size>(expected_value)); + types::for_each(simd_test_types(), ConversionHelper<T, SimdAbi, array_size>(expected_value)); } }; @@ -65,7 +65,7 @@ struct CheckConversionMaskCtorTraits { void operator()() { constexpr std::size_t array_size = ex::simd_size_v<T, SimdAbi>; - types::for_each(arithmetic_no_bool_types(), CheckConversionMaskCtorTraitsHelper<T, SimdAbi, array_size>()); + types::for_each(simd_test_types(), CheckConversionMaskCtorTraitsHelper<T, SimdAbi, array_size>()); } }; diff --git a/libcxx/test/std/experimental/simd/simd.reference/reference_assignment.pass.cpp b/libcxx/test/std/experimental/simd/simd.reference/reference_assignment.pass.cpp index cfef55a868ba017804b4d80eb9c94c5b75122fd9..013adb3685935246c7038f1e4eb103589272f1cc 100644 --- a/libcxx/test/std/experimental/simd/simd.reference/reference_assignment.pass.cpp +++ b/libcxx/test/std/experimental/simd/simd.reference/reference_assignment.pass.cpp @@ -72,10 +72,10 @@ template <class T, std::size_t> struct CheckReferenceAssignment { template <class SimdAbi> void operator()() { - types::for_each(arithmetic_no_bool_types(), CheckSimdReferenceAssignmentHelper<T, SimdAbi>()); - types::for_each(arithmetic_no_bool_types(), CheckMaskReferenceAssignmentHelper<T, SimdAbi>()); + types::for_each(simd_test_types(), CheckSimdReferenceAssignmentHelper<T, SimdAbi>()); + types::for_each(simd_test_types(), CheckMaskReferenceAssignmentHelper<T, SimdAbi>()); - types::for_each(arithmetic_no_bool_types(), CheckReferenceAssignmentTraitsHelper<T, SimdAbi>()); + types::for_each(simd_test_types(), CheckReferenceAssignmentTraitsHelper<T, SimdAbi>()); } }; diff --git a/libcxx/test/std/experimental/simd/test_utils.h b/libcxx/test/std/experimental/simd/test_utils.h index b3679b51e50b503fbc2a4cd760a44da81064860d..9b4416085751380c7c9d08d4bdfe621d53758699 100644 --- a/libcxx/test/std/experimental/simd/test_utils.h +++ b/libcxx/test/std/experimental/simd/test_utils.h @@ -48,6 +48,18 @@ using arithmetic_no_bool_types = types::concatenate_t<types::integer_types, type using arithmetic_no_bool_types = types::concatenate_t<types::integer_types, types::floating_point_types>; #endif +// For interfaces with vectorizable type template parameters, we only use some common or boundary types +// as template parameters for testing to ensure that the compilation time of a single test does not exceed. +using simd_test_types = + types::type_list<char, + unsigned, + int, +#ifndef TEST_HAS_NO_INT128 + __int128_t, +#endif + float, + double>; + template <template <class T, std::size_t N> class Func> void test_all_simd_abi() { types::for_each(arithmetic_no_bool_types(), TestAllSimdAbiFunctor<Func>()); diff --git a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/setbuf.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/setbuf.pass.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8bcce2816203325ba482dcbe427e39e0b14465c2 --- /dev/null +++ b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/setbuf.pass.cpp @@ -0,0 +1,120 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// <fstream> + +// basic_streambuf<charT, traits>* setbuf(char_type* s, streamsize n) override; + +#include <fstream> +#include <cstddef> +#include <cassert> + +#include "test_macros.h" + +template <class CharT> +static std::size_t file_size(const char* filename) { + FILE* f = std::fopen(filename, "rb"); + std::fseek(f, 0, SEEK_END); + long result = std::ftell(f); + std::fclose(f); + return result; +} + +// Helper class to expose some protected std::basic_filebuf<CharT> members. +template <class CharT> +struct filebuf : public std::basic_filebuf<CharT> { + CharT* base() { return this->pbase(); } + CharT* ptr() { return this->pptr(); } +}; + +template <class CharT> +static void buffered_request() { + filebuf<CharT> buffer; + + CharT b[10] = {0}; + assert(buffer.pubsetbuf(b, 10) == &buffer); + + buffer.open("test.dat", std::ios_base::out); + buffer.sputc(CharT('a')); + assert(b[0] == 'a'); + + buffer.close(); + assert(file_size<CharT>("test.dat") == 1); +} + +template <class CharT> +static void unbuffered_request_before_open() { + filebuf<CharT> buffer; + + assert(buffer.pubsetbuf(nullptr, 0) == &buffer); + assert(buffer.base() == nullptr); + assert(buffer.ptr() == nullptr); + + buffer.open("test.dat", std::ios_base::out); + assert(buffer.base() == nullptr); + assert(buffer.ptr() == nullptr); + + buffer.sputc(CharT('a')); + assert(buffer.base() == nullptr); + assert(buffer.ptr() == nullptr); + + assert(file_size<CharT>("test.dat") == 1); +} + +template <class CharT> +static void unbuffered_request_after_open() { + filebuf<CharT> buffer; + + buffer.open("test.dat", std::ios_base::out); + + assert(buffer.pubsetbuf(nullptr, 0) == &buffer); + assert(buffer.base() == nullptr); + assert(buffer.ptr() == nullptr); + + buffer.sputc(CharT('a')); + assert(buffer.base() == nullptr); + assert(buffer.ptr() == nullptr); + + assert(file_size<CharT>("test.dat") == 1); +} + +template <class CharT> +static void unbuffered_request_after_open_ate() { + filebuf<CharT> buffer; + + buffer.open("test.dat", std::ios_base::out | std::ios_base::ate); + + assert(buffer.pubsetbuf(nullptr, 0) == &buffer); + + buffer.sputc(CharT('a')); + assert(file_size<CharT>("test.dat") <= 1); + // on libc++ buffering is used by default. + LIBCPP_ASSERT(file_size<CharT>("test.dat") == 0); + + buffer.close(); + assert(file_size<CharT>("test.dat") == 1); +} + +template <class CharT> +static void test() { + buffered_request<CharT>(); + + unbuffered_request_before_open<CharT>(); + unbuffered_request_after_open<CharT>(); + unbuffered_request_after_open_ate<CharT>(); +} + +int main(int, char**) { + test<char>(); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test<wchar_t>(); +#endif + + return 0; +} diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/copy.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/copy.pass.cpp index 842aece4121fbe81ec808fe5125ac9684514c763..719c231d33e75e8b7f165dde0faf93a4ef1df4d1 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/copy.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/copy.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // <filesystem> diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/copy_assign.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/copy_assign.pass.cpp index 4be769612dec6c8d9535d4ddd7c7ba243d705c72..e897676ec2bfe52ac2571e4e6feff87f855e1828 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/copy_assign.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/copy_assign.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // <filesystem> diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/move.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/move.pass.cpp index 8b41854fb4bdcca306bd9f10377b717247291599..1118ba23ab92f355516bc51f4125d2be4beddac8 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/move.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/move.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // <filesystem> diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/move_assign.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/move_assign.pass.cpp index f663f1aa536e0460409c6b3669b49ebda37ff89e..a71f8ce31479282cf969630e834040e6b6305fbb 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/move_assign.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/move_assign.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // <filesystem> diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp index 1476f29360fbbef2af793bdbd436224c7d7fffa2..a1a37012369d4cdbbf35a3b8cea11fb64fb8e2d9 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // <filesystem> diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/assign.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/assign.pass.cpp index c071d44de70c4b6fa2e95d75b609fedb32f7252f..ba14af1240d4b788dfaa1fd9ed241d6288fdafbf 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/assign.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/assign.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // <filesystem> diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/refresh.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/refresh.pass.cpp index 22f94def8529e2e95dea9a7a08f58f20da6368af..4f5002e068c19dab3a100e882582c04f350ad7f9 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/refresh.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/refresh.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // The string reported on errors changed, which makes those tests fail when run diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp index 62b6837f463235f8f240e873643d7d87de97ccbb..03e9de882ab0ab8c2f7fd1e78af0fcf811971f80 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // <filesystem> diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_size.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_size.pass.cpp index 5d25485479ea6d6540a18d631a74d1545f284527..e1407858f66ac56a17864d9e1c60242a7e0a4f10 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_size.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_size.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // The string reported on errors changed, which makes those tests fail when run diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp index 91d6017f76a9db301d2557b0011624e888f1f902..303a95a0128bc9bfe97b4c19e8d049f84375a549 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // Starting in Android N (API 24), SELinux policy prevents the shell user from diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp index 34e60c66357b5d0a79e7d9ff9e0640bd99147a18..514bbb27c2c47509d9418d6f271044a86f96c9f3 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // The string reported on errors changed, which makes those tests fail when run diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp index 75877bc0a2752af179108d4bfeac75705b3e7fcf..41e2ee668f525de44c3ba3c443df8b8dcf1aacc9 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // The string reported on errors changed, which makes those tests fail when run diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/status.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/status.pass.cpp index d28497395be6c04c2c1df372ba71a0d2f056e995..dd72232ee530af4333d4b42e4e2e8ea050cc7c14 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/status.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/status.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // <filesystem> diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp index bcb1f615986e9ad4982af5c12badf4bc4fb08e49..24e806950952762d4bb23005aeace5fc74f88a6f 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // <filesystem> diff --git a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/copy.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/copy.pass.cpp index 31dfd8dba0e73ae9b2a366a3635c8c6d9a461a68..b7100b22dcd4298db6698611ae70e692403d77b1 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/copy.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/copy.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/copy_assign.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/copy_assign.pass.cpp index ff47ad2d0a968739f5a78272998795f5c7194878..11748f942bc86018f0b108996bbbf67de576334e 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/copy_assign.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/copy_assign.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp index 780994f26386ac4c857667d0404b2c71c6258cf2..3e363ae9bceec2850dbf9c0679684027c881cea3 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/increment.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/increment.pass.cpp index d224b44aa0318e08e12791997159723f6ff5a53d..a7a4fd4c1df8bef5aeb31f022ce9e0ec930de347 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/increment.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/increment.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/move.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/move.pass.cpp index e6b779c7563f84fbb4a6a10c0684eed5b923f8a3..5dcd91d6c26dc4c57647b52314eec9b17675c076 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/move.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/move.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/move_assign.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/move_assign.pass.cpp index 943708a8336a9e7e30f1647ac805c0bd54c4097e..5a1750dcd1329d09272a9c739830b6bf05d5bbd2 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/move_assign.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/move_assign.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.nonmembers/begin_end.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.nonmembers/begin_end.pass.cpp index 80024b95b0e57956b58166dc829e81a49218a111..d110912c0a4b1022431659da988a17bf730ec468 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.nonmembers/begin_end.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.nonmembers/begin_end.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/copy.pass.cpp b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/copy.pass.cpp index 61dab710ce6405fb3ee3c1ed73d327deadf08c04..05346693f4bb6c02847b58203d8be6662ef39f8c 100644 --- a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/copy.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/copy.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/copy_assign.pass.cpp b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/copy_assign.pass.cpp index 3f1e2a3cc9dffe04980bde1e9f93d876d51d0634..e1452c365a38756ab4d01e05e5683c303fc6c5ee 100644 --- a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/copy_assign.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/copy_assign.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp index 4dd4a39a3d5d8ecda3f64c09e92edcb84de90557..f0cc8d9a25ffc014641886c0b4593728c213e5c9 100644 --- a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/depth.pass.cpp b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/depth.pass.cpp index e5d2c64731e43c37abeb108ba87649b41128bd8a..30804c0e54e54d3be115a5c7e1d736b9eba7f6bf 100644 --- a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/depth.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/depth.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/disable_recursion_pending.pass.cpp b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/disable_recursion_pending.pass.cpp index b0f6cbbbbdc73fc4e8e6b86b19f058c17717bfe5..26e24ad988bcdf6738ca0daee2b41b129dc9c42c 100644 --- a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/disable_recursion_pending.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/disable_recursion_pending.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp index 9b3a50fb62c72eb9e136135c94bb89a93a42b627..243bed0783dba7fb27cfd02d7e9b44ed91e2548a 100644 --- a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/move.pass.cpp b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/move.pass.cpp index e2969b7dc63b10276f5d6af3a320d89a6b4272d6..5fc3efee9cd06fc9c63581866b375f20db8f0d09 100644 --- a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/move.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/move.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/move_assign.pass.cpp b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/move_assign.pass.cpp index 4aa24dea475e60426aa050213080b98240e8e260..e4a32e0595c35bee5f199c0eb40fbe85df40442d 100644 --- a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/move_assign.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/move_assign.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/pop.pass.cpp b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/pop.pass.cpp index 9f8e5da5a9fa6cc77a9c0b64d0223fcb9933d95d..aa458a655ffc946195c2f05c1580ec0770a586aa 100644 --- a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/pop.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/pop.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/recursion_pending.pass.cpp b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/recursion_pending.pass.cpp index e0abd19dcd4e975eb25285e498e9130753e2b7ae..f54ee86d5ec0b54ef902f5f6cc5268efc3e01e2e 100644 --- a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/recursion_pending.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/recursion_pending.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.nonmembers/begin_end.pass.cpp b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.nonmembers/begin_end.pass.cpp index d0f3047bad51ae38a081aa5edd95189a8f939183..2dc9271fbe3b244891c6f5bb848dafad381b264c 100644 --- a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.nonmembers/begin_end.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.nonmembers/begin_end.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp index 0098fe8ee698ef90db032313310c36f80c9bbd01..279a856511b9983054b363af289bcb606685dfae 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy/copy.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy/copy.pass.cpp index cc801922578cccc2835c763969cba4b019663032..3f3effbf267520447f4a428e619ff36122dfafba 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy/copy.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy/copy.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_symlink/copy_symlink.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_symlink/copy_symlink.pass.cpp index 49eb30ebf39ce8ef46df4474b6114bcd3c67cdd9..7b27213d83b01daa835cee3e474c8b6571c2e053 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_symlink/copy_symlink.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_symlink/copy_symlink.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp index e0bb40c3943bf11942592d620c3b2b67489f0711..9955e08710c5675a241dc7531442f9eaef46d856 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp index dbb36e2889522e36a781e08105558a8b659d5db4..21f283cae86d59f000e0594ba468bcb10f811225 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp index 8e6194f8c9862979c7e56d20e9477a084302fa1c..a0ec52643e8c0141a2880c01ff61d2a612ba16a6 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory_symlink/create_directory_symlink.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory_symlink/create_directory_symlink.pass.cpp index 7faf90f038b9bf2eebedaab4b9af2a9f2a5e20e4..65bb9ee452fc3b9fd2cbdcd3860776aee2bcfff8 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory_symlink/create_directory_symlink.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory_symlink/create_directory_symlink.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_hard_link/create_hard_link.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_hard_link/create_hard_link.pass.cpp index 5e801e01f4f2aa4635c5ad8b98330e12520fd7da..bb8fd1c344a728b8105b4fda8e458fc9244a5997 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_hard_link/create_hard_link.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_hard_link/create_hard_link.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_symlink/create_symlink.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_symlink/create_symlink.pass.cpp index 2cee2469c838f1c7b25ecf3bc2a01d01281e745d..99d0a3b07ad2b8d3e715383a989415875b774933 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_symlink/create_symlink.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_symlink/create_symlink.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.current_path/current_path.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.current_path/current_path.pass.cpp index 5a48be10637e604505255205108de86ea2f2eab7..57df465bac18c38dae8c6dd3ab20cb31cff31ef6 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.current_path/current_path.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.current_path/current_path.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.equivalent/equivalent.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.equivalent/equivalent.pass.cpp index 710d1a60b64c8b262310239db72a968ff43df4e6..f9b00a28af2123a15f174be4f31a0a197d2f69a3 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.equivalent/equivalent.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.equivalent/equivalent.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp index 2bcdf0fda1b3f39230b9747a3940ba93661b43fb..50181cb8d76c84cca8854392351fa592f1403554 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.file_size/file_size.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.file_size/file_size.pass.cpp index 397617d489b63c5484f2641fe0676c1268b6bac0..99d303bc4244dc4a0a569fddc91b14db9de7fd84 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.file_size/file_size.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.file_size/file_size.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.hard_lk_ct/hard_link_count.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.hard_lk_ct/hard_link_count.pass.cpp index b2fa8e2b57c16c4a7cdf9364767d0ad12eb6568e..1890696c4bf19156c7a10a1e43245cf64b755797 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.hard_lk_ct/hard_link_count.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.hard_lk_ct/hard_link_count.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_block_file/is_block_file.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_block_file/is_block_file.pass.cpp index b9d15f521fa11dc48f39bc55ff14f70b0057b618..c16664c9a3f56e659888480d96051ea1d2005cfb 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_block_file/is_block_file.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_block_file/is_block_file.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_char_file/is_character_file.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_char_file/is_character_file.pass.cpp index f1bb81a22341d87d50eac9bbfe64df572014497c..79645b9c2cfded44219daa99f7be0c5b03d0f91b 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_char_file/is_character_file.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_char_file/is_character_file.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp index d493924f97e3ff062d3440af2dfe95d9d1f70250..70fc0122427eb446f2cbdeccca21bd3827828074 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp index a05054e226047c1b244dff614504ac64700e8988..647d2e6a255a95304476560c71ad216025302ed4 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_fifo/is_fifo.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_fifo/is_fifo.pass.cpp index 8a9b0225c133fdd7aa3c92d4bc58ead77265fa6a..76375d7b3b78c38323b5bbed6d4954db43acf303 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_fifo/is_fifo.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_fifo/is_fifo.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_other/is_other.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_other/is_other.pass.cpp index 16bd2912bbeb21d600d64e2c5e894fbd2ca501cd..ba3070e7bdc7d173d076526febf88b387a292e8f 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_other/is_other.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_other/is_other.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_regular_file/is_regular_file.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_regular_file/is_regular_file.pass.cpp index a3e12a7532d15928c567d399c973ddb253f5f01a..06a6fb4d22debba09332f7bd3775acd5c4feeb6d 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_regular_file/is_regular_file.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_regular_file/is_regular_file.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_socket/is_socket.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_socket/is_socket.pass.cpp index 2c4fe7d1bf6d351a5b21584b906d3a430e3a66d1..b6f92e47a67a2284981df86d01f85759c04a269c 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_socket/is_socket.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_socket/is_socket.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp index 1d70e64bb234ad8a27183db40559ff8cb1a0c378..a71361c84704939444007c75e2c77d3a55f4715f 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp index 0678b4d767d23e391c920daf28862b1149fcf5df..d43bc5eea51214d93e4fe1518361c8c925de9a2d 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.permissions/permissions.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.permissions/permissions.pass.cpp index f009befa49c379c4edcc23218161ef11aae05cbc..085fa65e3559f5d3267ef81dd997ebd4d2b28809 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.permissions/permissions.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.permissions/permissions.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.read_symlink/read_symlink.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.read_symlink/read_symlink.pass.cpp index ee0ba7284903da41d37678636d330a819d67c3f6..9bb102ab4da5c3d51f9a56d37c1cce0972f626cc 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.read_symlink/read_symlink.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.read_symlink/read_symlink.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.relative/relative.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.relative/relative.pass.cpp index 9bd4051f790218be91bd8d4fa7743114849da6ea..7bba86252498ecdde44056a783b4701b5d1f5b9a 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.relative/relative.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.relative/relative.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove/remove.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove/remove.pass.cpp index 3685bbf78d506423773532f23ba45e85111ff6da..c8a5d7f6aa10e42da6574df146230000e806ce86 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove/remove.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove/remove.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp index 5cdbd0878431652bf4e5af5895c1ad31a6de1d11..5513c18f00585ee069ddbc73e6e8ddc73acbe7bf 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.rename/rename.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.rename/rename.pass.cpp index 61a31543dd7adfc8fa82aec21820b81474996fad..972a2a024c2124af5bdca491f1c8f23ca98af1ff 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.rename/rename.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.rename/rename.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.resize_file/resize_file.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.resize_file/resize_file.pass.cpp index 8218504115d8548faf8c73d6dab4c3f9e6c6f96b..e21e6b9ddc1ffe8700404edcaca38dd6f1341cdd 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.resize_file/resize_file.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.resize_file/resize_file.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.space/space.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.space/space.pass.cpp index 9f7b5aa94b68d1359ba0bbfb1c1174a941c013f0..60e9ac778967ef75c023aed8778f2af2dcbad51d 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.space/space.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.space/space.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.status/status.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.status/status.pass.cpp index 02a68712dabdb4397808741516c70b094fb6ed40..75eae80194ba803730e194d15a7d4bbab41f4a9b 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.status/status.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.status/status.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp index 5c2078e4b48564319c13e188459a33bc787ab94e..7a4658756f0c30970da1393cd348e8c4104eb638 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp index 035e875e4ec83dba432347a452d6fd185e0334f4..053bddcad9b43ad7068fdcbe88040242033b3b7b 100644 --- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// REQUIRES: can-create-symlinks // UNSUPPORTED: c++03, c++11, c++14 // UNSUPPORTED: no-filesystem // UNSUPPORTED: availability-filesystem-missing diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.swap/iter_swap.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.swap/iter_swap.pass.cpp index dd78707f25409c4c4a8062f33b911d411c5055f3..e6507f7e77673512258e51ae34b9fcb9b299b41a 100644 --- a/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.swap/iter_swap.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.swap/iter_swap.pass.cpp @@ -47,6 +47,13 @@ static_assert( std::is_invocable_v<IterSwapT&&, HasIterSwap&, HasIterSwap&>); static_assert( std::is_invocable_v<IterSwapT&&, HasIterSwap&, int&>); static_assert(!std::is_invocable_v<IterSwapT&&, int&, HasIterSwap&>); +struct StructWithNotMoreSpecializedIterSwap { + friend void iter_swap(auto&, auto&); +}; + +static_assert( + !std::is_invocable_v<IterSwapT, StructWithNotMoreSpecializedIterSwap&, StructWithNotMoreSpecializedIterSwap&>); + struct NodiscardIterSwap { [[nodiscard]] friend int iter_swap(NodiscardIterSwap&, NodiscardIterSwap&) { return 0; } }; diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.pass.cpp index c06a9ed2d5cb42c06704e2d2a928175a971f81bf..cbca37e3a661392f8b086439b9627d5d8743d74c 100644 --- a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.pass.cpp +++ b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.pass.cpp @@ -329,7 +329,7 @@ constexpr bool test() { { [[maybe_unused]] std::same_as<unsigned long int> decltype(auto) _ = std::saturate_cast<unsigned long int>(sBigMax); } assert(std::saturate_cast<unsigned long int>( sBigMin) == 0UL); // saturated assert(std::saturate_cast<unsigned long int>( sZero) == 0UL); - assert(std::saturate_cast<unsigned long int>( sBigMax) == ULONG_MAX); // saturated + assert(std::saturate_cast<unsigned long int>( sBigMax) == (sizeof(UIntT) > sizeof(unsigned long int) ? ULONG_MAX : LONG_MAX)); // saturated depending on underlying types { [[maybe_unused]] std::same_as<unsigned long int> decltype(auto) _ = std::saturate_cast<unsigned long int>(uBigMax); } assert(std::saturate_cast<unsigned long int>( uZero) == 0UL); diff --git a/libcxx/test/std/ranges/range.access/begin.pass.cpp b/libcxx/test/std/ranges/range.access/begin.pass.cpp index ca25fc297a01191db7d1b3b3cc52d5c27219fb73..5ca3d59abb1407f39621d99f2edf1302529eddf9 100644 --- a/libcxx/test/std/ranges/range.access/begin.pass.cpp +++ b/libcxx/test/std/ranges/range.access/begin.pass.cpp @@ -192,7 +192,7 @@ struct BeginFunction { }; static_assert( std::is_invocable_v<RangeBeginT, BeginFunction const&>); static_assert(!std::is_invocable_v<RangeBeginT, BeginFunction &&>); -static_assert(!std::is_invocable_v<RangeBeginT, BeginFunction &>); +static_assert(std::is_invocable_v<RangeBeginT, BeginFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic static_assert( std::is_invocable_v<RangeCBeginT, BeginFunction const&>); static_assert( std::is_invocable_v<RangeCBeginT, BeginFunction &>); @@ -245,7 +245,7 @@ private: constexpr bool testBeginFunction() { BeginFunction a{}; const BeginFunction aa{}; - static_assert(!std::invocable<RangeBeginT, decltype((a))>); + assert(std::ranges::begin(a) == &a.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic assert(std::ranges::cbegin(a) == &a.x); assert(std::ranges::begin(aa) == &aa.x); assert(std::ranges::cbegin(aa) == &aa.x); @@ -266,21 +266,21 @@ constexpr bool testBeginFunction() { BeginFunctionReturnsEmptyPtr d{}; const BeginFunctionReturnsEmptyPtr dd{}; - static_assert(!std::invocable<RangeBeginT, decltype((d))>); + assert(std::ranges::begin(d) == &d.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic assert(std::ranges::cbegin(d) == &d.x); assert(std::ranges::begin(dd) == &dd.x); assert(std::ranges::cbegin(dd) == &dd.x); BeginFunctionWithDataMember e{}; const BeginFunctionWithDataMember ee{}; - static_assert(!std::invocable<RangeBeginT, decltype((e))>); + assert(std::ranges::begin(e) == &e.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic assert(std::ranges::begin(ee) == &ee.x); assert(std::ranges::cbegin(e) == &e.x); assert(std::ranges::cbegin(ee) == &ee.x); BeginFunctionWithPrivateBeginMember f{}; const BeginFunctionWithPrivateBeginMember ff{}; - static_assert(!std::invocable<RangeBeginT, decltype((f))>); + assert(std::ranges::begin(f) == &f.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic assert(std::ranges::cbegin(f) == &f.y); assert(std::ranges::begin(ff) == &ff.y); assert(std::ranges::cbegin(ff) == &ff.y); diff --git a/libcxx/test/std/ranges/range.access/end.pass.cpp b/libcxx/test/std/ranges/range.access/end.pass.cpp index 21d97354ef08d08c801105ef51b6e1e69ba42fb2..3e465b357e98513039a55cd67d4a83109efe2e8d 100644 --- a/libcxx/test/std/ranges/range.access/end.pass.cpp +++ b/libcxx/test/std/ranges/range.access/end.pass.cpp @@ -193,7 +193,7 @@ static_assert(!std::is_invocable_v<RangeEndT, EndFunction &&>); static_assert( std::is_invocable_v<RangeEndT, EndFunction const&>); static_assert(!std::is_invocable_v<RangeEndT, EndFunction &&>); -static_assert(!std::is_invocable_v<RangeEndT, EndFunction &>); +static_assert(std::is_invocable_v<RangeEndT, EndFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic static_assert( std::is_invocable_v<RangeCEndT, EndFunction const&>); static_assert( std::is_invocable_v<RangeCEndT, EndFunction &>); @@ -271,7 +271,7 @@ constexpr bool testEndFunction() { assert(std::ranges::end(a) == &a.x); assert(std::ranges::cend(a) == &a.x); EndFunction aa{}; - static_assert(!std::is_invocable_v<RangeEndT, decltype((aa))>); + assert(std::ranges::end(aa) == &aa.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic assert(std::ranges::cend(aa) == &aa.x); EndFunctionByValue b; @@ -286,28 +286,28 @@ constexpr bool testEndFunction() { assert(std::ranges::end(d) == &d.x); assert(std::ranges::cend(d) == &d.x); EndFunctionReturnsEmptyPtr dd{}; - static_assert(!std::is_invocable_v<RangeEndT, decltype((dd))>); + assert(std::ranges::end(dd) == &dd.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic assert(std::ranges::cend(dd) == &dd.x); const EndFunctionWithDataMember e{}; assert(std::ranges::end(e) == &e.x); assert(std::ranges::cend(e) == &e.x); EndFunctionWithDataMember ee{}; - static_assert(!std::is_invocable_v<RangeEndT, decltype((ee))>); + assert(std::ranges::end(ee) == &ee.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic assert(std::ranges::cend(ee) == &ee.x); const EndFunctionWithPrivateEndMember f{}; assert(std::ranges::end(f) == &f.y); assert(std::ranges::cend(f) == &f.y); EndFunctionWithPrivateEndMember ff{}; - static_assert(!std::is_invocable_v<RangeEndT, decltype((ff))>); + assert(std::ranges::end(ff) == &ff.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic assert(std::ranges::cend(ff) == &ff.y); const BeginMemberEndFunction g{}; assert(std::ranges::end(g) == &g.x); assert(std::ranges::cend(g) == &g.x); BeginMemberEndFunction gg{}; - static_assert(!std::is_invocable_v<RangeEndT, decltype((gg))>); + assert(std::ranges::end(gg) == &gg.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic assert(std::ranges::cend(gg) == &gg.x); return true; diff --git a/libcxx/test/std/ranges/range.access/rbegin.pass.cpp b/libcxx/test/std/ranges/range.access/rbegin.pass.cpp index e1a564c94ed9488b73fb8538c08fcefed7dbaff4..3997f38efd0298ce3d848a1793f1a9259b8741b0 100644 --- a/libcxx/test/std/ranges/range.access/rbegin.pass.cpp +++ b/libcxx/test/std/ranges/range.access/rbegin.pass.cpp @@ -187,7 +187,8 @@ struct RBeginFunction { }; static_assert( std::is_invocable_v<RangeRBeginT, RBeginFunction const&>); static_assert(!std::is_invocable_v<RangeRBeginT, RBeginFunction &&>); -static_assert(!std::is_invocable_v<RangeRBeginT, RBeginFunction &>); +static_assert( + std::is_invocable_v<RangeRBeginT, RBeginFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic static_assert( std::is_invocable_v<RangeCRBeginT, RBeginFunction const&>); static_assert( std::is_invocable_v<RangeCRBeginT, RBeginFunction &>); @@ -246,7 +247,7 @@ private: constexpr bool testRBeginFunction() { RBeginFunction a{}; const RBeginFunction aa{}; - static_assert(!std::invocable<RangeRBeginT, decltype((a))>); + assert(std::ranges::rbegin(a) == &a.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic assert(std::ranges::crbegin(a) == &a.x); assert(std::ranges::rbegin(aa) == &aa.x); assert(std::ranges::crbegin(aa) == &aa.x); @@ -267,21 +268,21 @@ constexpr bool testRBeginFunction() { RBeginFunctionReturnsEmptyPtr d{}; const RBeginFunctionReturnsEmptyPtr dd{}; - static_assert(!std::invocable<RangeRBeginT, decltype((d))>); + assert(std::ranges::rbegin(d) == &d.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic assert(std::ranges::crbegin(d) == &d.x); assert(std::ranges::rbegin(dd) == &dd.x); assert(std::ranges::crbegin(dd) == &dd.x); RBeginFunctionWithDataMember e{}; const RBeginFunctionWithDataMember ee{}; - static_assert(!std::invocable<RangeRBeginT, decltype((e))>); + assert(std::ranges::rbegin(e) == &e.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic assert(std::ranges::rbegin(ee) == &ee.x); assert(std::ranges::crbegin(e) == &e.x); assert(std::ranges::crbegin(ee) == &ee.x); RBeginFunctionWithPrivateBeginMember f{}; const RBeginFunctionWithPrivateBeginMember ff{}; - static_assert(!std::invocable<RangeRBeginT, decltype((f))>); + assert(std::ranges::rbegin(f) == &f.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic assert(std::ranges::crbegin(f) == &f.y); assert(std::ranges::rbegin(ff) == &ff.y); assert(std::ranges::crbegin(ff) == &ff.y); diff --git a/libcxx/test/std/ranges/range.access/rend.pass.cpp b/libcxx/test/std/ranges/range.access/rend.pass.cpp index 5ba244b6b18cfec14cd1241677eacf63595a80e2..f5f59edf19393fb123b84c515e373b87ac98a1f2 100644 --- a/libcxx/test/std/ranges/range.access/rend.pass.cpp +++ b/libcxx/test/std/ranges/range.access/rend.pass.cpp @@ -196,7 +196,7 @@ static_assert(!std::is_invocable_v<RangeREndT, REndFunction &&>); static_assert( std::is_invocable_v<RangeREndT, REndFunction const&>); static_assert(!std::is_invocable_v<RangeREndT, REndFunction &&>); -static_assert(!std::is_invocable_v<RangeREndT, REndFunction &>); +static_assert(std::is_invocable_v<RangeREndT, REndFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic static_assert( std::is_invocable_v<RangeCREndT, REndFunction const&>); static_assert( std::is_invocable_v<RangeCREndT, REndFunction &>); @@ -272,7 +272,7 @@ constexpr bool testREndFunction() { assert(std::ranges::rend(a) == &a.x); assert(std::ranges::crend(a) == &a.x); REndFunction aa{}; - static_assert(!std::is_invocable_v<RangeREndT, decltype((aa))>); + assert(std::ranges::rend(aa) == &aa.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic assert(std::ranges::crend(aa) == &aa.x); REndFunctionByValue b; @@ -287,28 +287,28 @@ constexpr bool testREndFunction() { assert(std::ranges::rend(d) == &d.x); assert(std::ranges::crend(d) == &d.x); REndFunctionReturnsEmptyPtr dd{}; - static_assert(!std::is_invocable_v<RangeREndT, decltype((dd))>); + assert(std::ranges::rend(dd) == &dd.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic assert(std::ranges::crend(dd) == &dd.x); const REndFunctionWithDataMember e{}; assert(std::ranges::rend(e) == &e.x); assert(std::ranges::crend(e) == &e.x); REndFunctionWithDataMember ee{}; - static_assert(!std::is_invocable_v<RangeREndT, decltype((ee))>); + assert(std::ranges::rend(ee) == &ee.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic assert(std::ranges::crend(ee) == &ee.x); const REndFunctionWithPrivateEndMember f{}; assert(std::ranges::rend(f) == &f.y); assert(std::ranges::crend(f) == &f.y); REndFunctionWithPrivateEndMember ff{}; - static_assert(!std::is_invocable_v<RangeREndT, decltype((ff))>); + assert(std::ranges::rend(ff) == &ff.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic assert(std::ranges::crend(ff) == &ff.y); const RBeginMemberEndFunction g{}; assert(std::ranges::rend(g) == &g.x); assert(std::ranges::crend(g) == &g.x); RBeginMemberEndFunction gg{}; - static_assert(!std::is_invocable_v<RangeREndT, decltype((gg))>); + assert(std::ranges::rend(gg) == &gg.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic assert(std::ranges::crend(gg) == &gg.x); return true; diff --git a/libcxx/test/std/ranges/range.access/size.pass.cpp b/libcxx/test/std/ranges/range.access/size.pass.cpp index fd7d0a8b9975225efcb14656038616718524c83e..ee44aa815ba993bc5d3c0ec7ef9e3e86303247c5 100644 --- a/libcxx/test/std/ranges/range.access/size.pass.cpp +++ b/libcxx/test/std/ranges/range.access/size.pass.cpp @@ -219,7 +219,8 @@ inline constexpr bool std::ranges::disable_sized_range<const ImproperlyDisabledF static_assert( std::is_invocable_v<RangeSizeT, ImproperlyDisabledMember&>); static_assert( std::is_invocable_v<RangeSizeT, const ImproperlyDisabledMember&>); -static_assert(!std::is_invocable_v<RangeSizeT, ImproperlyDisabledFunction&>); +static_assert(std::is_invocable_v<RangeSizeT, + ImproperlyDisabledFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic static_assert( std::is_invocable_v<RangeSizeT, const ImproperlyDisabledFunction&>); // No begin end. diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/range.concept.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/range.concept.compile.pass.cpp index 7de72ecc0a90c0bafb83f58078349093f7d1cd4f..a49e692d585da69cd2025942ee07fb7ae8cd71d0 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.elements/range.concept.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.elements/range.concept.compile.pass.cpp @@ -52,7 +52,6 @@ static_assert(!std::ranges::input_range<Range<cpp20_output_iterator<std::tuple<i static_assert(!HasElementsView<Range<cpp20_output_iterator<std::tuple<int>*>>, 0>); // !tuple-like -LIBCPP_STATIC_ASSERT(!std::__tuple_like<int>); static_assert(!HasElementsView<Range<int*>, 1>); // !(N < tuple_size_v<T>) diff --git a/libcxx/test/std/ranges/range.adaptors/range.zip/borrowing.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.zip/borrowing.compile.pass.cpp index 0ff51c24b7e96d93d6aa2aa6299b2b269f86bff2..1bf1d85a2ad7191ed3afe07cc8b5d40dc82e3bcd 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.zip/borrowing.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.zip/borrowing.compile.pass.cpp @@ -13,7 +13,6 @@ // (enable_borrowed_range<Views> && ...); #include <ranges> -#include <tuple> struct Borrowed : std::ranges::view_base { int* begin() const; diff --git a/libcxx/test/std/ranges/range.utility/range.subrange/operator.pair_like.pass.cpp b/libcxx/test/std/ranges/range.utility/range.subrange/operator.pair_like.pass.cpp index 2641a9ad94ea764f140db60d8820a5b04f2b8177..82f5dd801e51a11e2a9b7dee0575df28ca7ecdb2 100644 --- a/libcxx/test/std/ranges/range.utility/range.subrange/operator.pair_like.pass.cpp +++ b/libcxx/test/std/ranges/range.utility/range.subrange/operator.pair_like.pass.cpp @@ -17,6 +17,7 @@ #include <cassert> #include <concepts> #include <ranges> +#include <utility> #include "test_macros.h" diff --git a/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp b/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp index 2fc2fa8579996a07c3b201deee166793e39ddb16..3f7c174d3fe48a62de34c4075df69838ed06220b 100644 --- a/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp +++ b/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp @@ -39,6 +39,14 @@ struct InputRange : std::ranges::view_interface<InputRange> { constexpr InputIter end() const { return InputIter(buff + 8); } }; +struct SizedInputRange : std::ranges::view_interface<SizedInputRange> { + int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7}; + constexpr InputIter begin() const { return InputIter(buff); } + constexpr sentinel_wrapper<InputIter> end() const { return sentinel_wrapper(InputIter(buff + 8)); } + constexpr std::size_t size() const { return 8; } +}; +static_assert(std::ranges::sized_range<SizedInputRange>); + struct NotSizedSentinel { using value_type = int; using difference_type = std::ptrdiff_t; @@ -155,11 +163,24 @@ concept BoolOpInvocable = requires (T const& obj) { bool(obj); }; constexpr bool testEmpty() { static_assert(!EmptyInvocable<InputRange>); + // LWG 3715: `view_interface::empty` is overconstrained + static_assert(EmptyInvocable<SizedInputRange>); static_assert( EmptyInvocable<ForwardRange>); static_assert(!BoolOpInvocable<InputRange>); + static_assert(BoolOpInvocable<SizedInputRange>); static_assert( BoolOpInvocable<ForwardRange>); + SizedInputRange sizedInputRange; + assert(!sizedInputRange.empty()); + assert(!static_cast<SizedInputRange const&>(sizedInputRange).empty()); + + assert(sizedInputRange); + assert(static_cast<SizedInputRange const&>(sizedInputRange)); + + assert(!std::ranges::empty(sizedInputRange)); + assert(!std::ranges::empty(static_cast<SizedInputRange const&>(sizedInputRange))); + ForwardRange forwardRange; assert(!forwardRange.empty()); assert(!static_cast<ForwardRange const&>(forwardRange).empty()); diff --git a/libcxx/test/std/ranges/robust_against_poison_pills.compile.pass.cpp b/libcxx/test/std/ranges/robust_against_poison_pills.compile.pass.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1b3da814d08002743fe4c11d6983aca0759fcb9b --- /dev/null +++ b/libcxx/test/std/ranges/robust_against_poison_pills.compile.pass.cpp @@ -0,0 +1,102 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// <compare>, <iterator>, <ranges> + +// ADL should be performed. Ordinary unqualified lookup should not be performed. + +namespace ns { +struct StructWithGlobalFunctions {}; +} // namespace ns + +struct ConvertibleToCmpType; +ConvertibleToCmpType strong_order(const ns::StructWithGlobalFunctions&, const ns::StructWithGlobalFunctions&); +ConvertibleToCmpType weak_order(const ns::StructWithGlobalFunctions&, const ns::StructWithGlobalFunctions&); +ConvertibleToCmpType partial_order(const ns::StructWithGlobalFunctions&, const ns::StructWithGlobalFunctions&); + +int&& iter_move(const ns::StructWithGlobalFunctions&); +void iter_swap(const ns::StructWithGlobalFunctions&, const ns::StructWithGlobalFunctions&); + +int* begin(const ns::StructWithGlobalFunctions&); +int* end(const ns::StructWithGlobalFunctions&); +int* rbegin(const ns::StructWithGlobalFunctions&); +int* rend(const ns::StructWithGlobalFunctions&); +unsigned int size(const ns::StructWithGlobalFunctions&); + +#include <compare> +#include <ranges> +#include <type_traits> + +struct ConvertibleToCmpType { + operator std::strong_ordering() const; + operator std::weak_ordering() const; + operator std::partial_ordering() const; +}; + +struct StructWithHiddenFriends { + friend ConvertibleToCmpType strong_order(const StructWithHiddenFriends&, const StructWithHiddenFriends&); + friend ConvertibleToCmpType weak_order(const StructWithHiddenFriends&, const StructWithHiddenFriends&); + friend ConvertibleToCmpType partial_order(const StructWithHiddenFriends&, const StructWithHiddenFriends&); + + friend int&& iter_move(const StructWithHiddenFriends&); + friend void iter_swap(const StructWithHiddenFriends&, const StructWithHiddenFriends&); + + friend int* begin(const StructWithHiddenFriends&); + friend int* end(const StructWithHiddenFriends&); + friend int* rbegin(const StructWithHiddenFriends&); + friend int* rend(const StructWithHiddenFriends&); + friend unsigned int size(const StructWithHiddenFriends&); +}; + +// [cmp.alg] ADL should be performed. +static_assert(std::is_invocable_v<decltype(std::strong_order), StructWithHiddenFriends&, StructWithHiddenFriends&>); +static_assert(std::is_invocable_v<decltype(std::weak_order), StructWithHiddenFriends&, StructWithHiddenFriends&>); +static_assert(std::is_invocable_v<decltype(std::partial_order), StructWithHiddenFriends&, StructWithHiddenFriends&>); + +// [cmp.alg] Ordinary unqualified lookup should not be performed. +static_assert( + !std::is_invocable_v<decltype(std::strong_order), ns::StructWithGlobalFunctions&, ns::StructWithGlobalFunctions&>); +static_assert( + !std::is_invocable_v<decltype(std::weak_order), ns::StructWithGlobalFunctions&, ns::StructWithGlobalFunctions&>); +static_assert( + !std::is_invocable_v<decltype(std::partial_order), ns::StructWithGlobalFunctions&, ns::StructWithGlobalFunctions&>); + +// [iterator.cust] ADL should be performed. +static_assert(std::is_invocable_v<decltype(std::ranges::iter_move), StructWithHiddenFriends&>); +static_assert( + std::is_invocable_v<decltype(std::ranges::iter_swap), StructWithHiddenFriends&, StructWithHiddenFriends&>); + +// [iterator.cust] Ordinary unqualified lookup should not be performed. +static_assert(!std::is_invocable_v<decltype(std::ranges::iter_move), ns::StructWithGlobalFunctions&>); +static_assert(!std::is_invocable_v<decltype(std::ranges::iter_swap), + ns::StructWithGlobalFunctions&, + ns::StructWithGlobalFunctions&>); + +// [range.access] ADL should be performed. +static_assert(std::is_invocable_v<decltype(std::ranges::begin), StructWithHiddenFriends&>); +static_assert(std::is_invocable_v<decltype(std::ranges::cbegin), StructWithHiddenFriends&>); +static_assert(std::is_invocable_v<decltype(std::ranges::end), StructWithHiddenFriends&>); +static_assert(std::is_invocable_v<decltype(std::ranges::cend), StructWithHiddenFriends&>); +static_assert(std::is_invocable_v<decltype(std::ranges::rbegin), StructWithHiddenFriends&>); +static_assert(std::is_invocable_v<decltype(std::ranges::crbegin), StructWithHiddenFriends&>); +static_assert(std::is_invocable_v<decltype(std::ranges::rend), StructWithHiddenFriends&>); +static_assert(std::is_invocable_v<decltype(std::ranges::crend), StructWithHiddenFriends&>); +static_assert(std::is_invocable_v<decltype(std::ranges::size), StructWithHiddenFriends&>); + +// [range.access] Ordinary unqualified lookup should not be performed. +static_assert(!std::is_invocable_v<decltype(std::ranges::begin), ns::StructWithGlobalFunctions&>); +static_assert(!std::is_invocable_v<decltype(std::ranges::cbegin), ns::StructWithGlobalFunctions&>); +static_assert(!std::is_invocable_v<decltype(std::ranges::end), ns::StructWithGlobalFunctions&>); +static_assert(!std::is_invocable_v<decltype(std::ranges::cend), ns::StructWithGlobalFunctions&>); +static_assert(!std::is_invocable_v<decltype(std::ranges::rbegin), ns::StructWithGlobalFunctions&>); +static_assert(!std::is_invocable_v<decltype(std::ranges::crbegin), ns::StructWithGlobalFunctions&>); +static_assert(!std::is_invocable_v<decltype(std::ranges::rend), ns::StructWithGlobalFunctions&>); +static_assert(!std::is_invocable_v<decltype(std::ranges::crend), ns::StructWithGlobalFunctions&>); +static_assert(!std::is_invocable_v<decltype(std::ranges::size), ns::StructWithGlobalFunctions&>); diff --git a/libcxx/test/std/thread/thread.condition/thread.condition.condvarany/wait_for_token_pred.pass.cpp b/libcxx/test/std/thread/thread.condition/thread.condition.condvarany/wait_for_token_pred.pass.cpp index 4ea60557d9f88c53cf4f298cf1fd9f979392caaa..7a39d1253a33cfd00e74dc0711e1042c6a695774 100644 --- a/libcxx/test/std/thread/thread.condition/thread.condition.condvarany/wait_for_token_pred.pass.cpp +++ b/libcxx/test/std/thread/thread.condition/thread.condition.condvarany/wait_for_token_pred.pass.cpp @@ -119,7 +119,7 @@ void test() { bool flag = false; auto thread = support::make_test_thread([&]() { std::this_thread::sleep_for(2ms); - Lock lock2{mutex}; + std::unique_lock<Mutex> lock2{mutex}; flag = true; cv.notify_all(); }); diff --git a/libcxx/test/std/thread/thread.condition/thread.condition.condvarany/wait_token_pred.pass.cpp b/libcxx/test/std/thread/thread.condition/thread.condition.condvarany/wait_token_pred.pass.cpp index e96a3e8bd1bc0b484261953599bfc4704c31eebd..f322d8cfdc68fc3721c1c9452e085eb656edff41 100644 --- a/libcxx/test/std/thread/thread.condition/thread.condition.condvarany/wait_token_pred.pass.cpp +++ b/libcxx/test/std/thread/thread.condition/thread.condition.condvarany/wait_token_pred.pass.cpp @@ -63,7 +63,7 @@ void test() { bool flag = false; auto thread = support::make_test_thread([&]() { std::this_thread::sleep_for(std::chrono::milliseconds(2)); - Lock lock2{mutex}; + std::unique_lock<Mutex> lock2{mutex}; flag = true; cv.notify_all(); }); diff --git a/libcxx/test/std/thread/thread.condition/thread.condition.condvarany/wait_until_token_pred.pass.cpp b/libcxx/test/std/thread/thread.condition/thread.condition.condvarany/wait_until_token_pred.pass.cpp index d649db025d755dd3f010adfc6f48653cb5123df9..e7388b9ce0e17675b38c0a442c7fccd098a4e478 100644 --- a/libcxx/test/std/thread/thread.condition/thread.condition.condvarany/wait_until_token_pred.pass.cpp +++ b/libcxx/test/std/thread/thread.condition/thread.condition.condvarany/wait_until_token_pred.pass.cpp @@ -119,7 +119,7 @@ void test() { bool flag = false; auto thread = support::make_test_thread([&]() { std::this_thread::sleep_for(std::chrono::milliseconds(2)); - Lock lock2{mutex}; + std::unique_lock<Mutex> lock2{mutex}; flag = true; cv.notify_all(); }); diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/get_tzdb.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/get_tzdb.pass.cpp index 335e8d20c23910cb8bfb730df88d7b2f43353822..b6204c615d965e6c5da1b00671613cbd1070d284 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/get_tzdb.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/get_tzdb.pass.cpp @@ -12,9 +12,6 @@ // XFAIL: libcpp-has-no-incomplete-tzdb // XFAIL: availability-tzdb-missing -// TODO TZDB (#81654) Enable tests -// UNSUPPORTED: c++20, c++23, c++26 - // <chrono> // const tzdb& get_tzdb(); @@ -30,8 +27,6 @@ int main(int, const char**) { assert(!db.version.empty()); - LIBCPP_ASSERT(!db.__rules.empty()); - assert(!db.zones.empty()); assert(std::ranges::is_sorted(db.zones)); assert(std::ranges::adjacent_find(db.zones) == db.zones.end()); // is unique? diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/get_tzdb_list.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/get_tzdb_list.pass.cpp index 34af9b576361fa469255bf4a291b6b3a5d4b2ffc..a5579a3820b6ac4a71270e1e60797880d1daceaf 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/get_tzdb_list.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.access/get_tzdb_list.pass.cpp @@ -12,9 +12,6 @@ // XFAIL: libcpp-has-no-incomplete-tzdb // XFAIL: availability-tzdb-missing -// TODO TZDB (#81654) Enable tests -// UNSUPPORTED: c++20, c++23, c++26 - // <chrono> // const tzdb& get_tzdb_list(); diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/front.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/front.pass.cpp index ac5fee8183b9bcee29d861d3f36eaa2b893c7a08..12c5310772f6a9c0586e6b5dc27fc14b2a21b4b9 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/front.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/front.pass.cpp @@ -12,9 +12,6 @@ // XFAIL: libcpp-has-no-incomplete-tzdb // XFAIL: availability-tzdb-missing -// TODO TZDB (#81654) Enable tests -// UNSUPPORTED: c++20, c++23, c++26 - // <chrono> // // class tzdb_list; diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/iterators.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/iterators.pass.cpp index 8bd9b321b2a0fb0132b35febe9dc2f5b081107e7..b00b8b44188d0bb40508ade7248f156a066c238d 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/iterators.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.list/iterators.pass.cpp @@ -12,9 +12,6 @@ // XFAIL: libcpp-has-no-incomplete-tzdb // XFAIL: availability-tzdb-missing -// TODO TZDB (#81654) Enable tests -// UNSUPPORTED: c++20, c++23, c++26 - // <chrono> // // class tzdb_list; diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.remote/reload_tzdb.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.remote/reload_tzdb.pass.cpp index bbf9002c0430cacd484e60060055bd4034c2fc55..af38772ee3cb286e4dc3cd8fb2ddc51e1b82649f 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.remote/reload_tzdb.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.remote/reload_tzdb.pass.cpp @@ -12,9 +12,6 @@ // XFAIL: libcpp-has-no-incomplete-tzdb // XFAIL: availability-tzdb-missing -// TODO TZDB (#81654) Enable tests -// UNSUPPORTED: c++20, c++23, c++26 - // <chrono> // Note there is no Standard way to change the remote database used. diff --git a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.remote/remote_version.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.remote/remote_version.pass.cpp index 861075cd82aa60073c93fd0438166244513ba9b1..36b68cefc8d31a6c715039daa36ca66bee09b280 100644 --- a/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.remote/remote_version.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.db/time.zone.db.remote/remote_version.pass.cpp @@ -12,9 +12,6 @@ // XFAIL: libcpp-has-no-incomplete-tzdb // XFAIL: availability-tzdb-missing -// TODO TZDB (#81654) Enable tests -// UNSUPPORTED: c++20, c++23, c++26 - // <chrono> // const string remote_version(); diff --git a/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.members/name.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.members/name.pass.cpp index 95d86d586666eab77fc6edb6b125e88594920435..c2412bac461bc50ac2d66764f13276af6216a097 100644 --- a/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.members/name.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.members/name.pass.cpp @@ -12,9 +12,6 @@ // XFAIL: libcpp-has-no-incomplete-tzdb // XFAIL: availability-tzdb-missing -// TODO TZDB (#81654) Enable tests -// UNSUPPORTED: c++20, c++23, c++26 - // <chrono> // class time_zone_link; diff --git a/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.members/target.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.members/target.pass.cpp index 305fbd21f625b56027f25e7769187a21fe5d4002..2f8b5b9421d63c36d0bed7b8be9959f33ca3d87e 100644 --- a/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.members/target.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.members/target.pass.cpp @@ -12,9 +12,6 @@ // XFAIL: libcpp-has-no-incomplete-tzdb // XFAIL: availability-tzdb-missing -// TODO TZDB (#81654) Enable tests -// UNSUPPORTED: c++20, c++23, c++26 - // <chrono> // class time_zone_link; diff --git a/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.nonmembers/comparison.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.nonmembers/comparison.pass.cpp index e375d7e443ce499838c7c9de7e1e4f120032ea73..944818c1ad0c164e5e2f9c8c6e7677bd5f46b70e 100644 --- a/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.nonmembers/comparison.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.link/time.zone.link.nonmembers/comparison.pass.cpp @@ -12,9 +12,6 @@ // XFAIL: libcpp-has-no-incomplete-tzdb // XFAIL: availability-tzdb-missing -// TODO TZDB (#81654) Enable tests -// UNSUPPORTED: c++20, c++23, c++26 - // <chrono> // bool operator==(const time_zone_link& x, const time_zone_link& y) noexcept; diff --git a/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/name.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/name.pass.cpp index 2bbe714b71a683889d8ede39a94d7f6b2643071f..d1ff2fe683108c3448ef916e4fefab4ab79e629e 100644 --- a/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/name.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.members/name.pass.cpp @@ -12,9 +12,6 @@ // XFAIL: libcpp-has-no-incomplete-tzdb // XFAIL: availability-tzdb-missing -// TODO TZDB (#81654) Enable tests -// UNSUPPORTED: c++20, c++23, c++26 - // <chrono> // class time_zone; diff --git a/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.nonmembers/comparison.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.nonmembers/comparison.pass.cpp index 9eae91e80a42d9cb94440f028d9f678aeeb14819..7c680707bc518bb5f45d25ffe7bf3d027bcb2939 100644 --- a/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.nonmembers/comparison.pass.cpp +++ b/libcxx/test/std/time/time.zone/time.zone.timezone/time.zone.nonmembers/comparison.pass.cpp @@ -12,9 +12,6 @@ // XFAIL: libcpp-has-no-incomplete-tzdb // XFAIL: availability-tzdb-missing -// TODO TZDB (#81654) Enable tests -// UNSUPPORTED: c++20, c++23, c++26 - // <chrono> // bool operator==(const time_zone& x, const time_zone& y) noexcept; diff --git a/libcxx/test/std/utilities/format/format.functions/bug_81590.compile.pass.cpp b/libcxx/test/std/utilities/format/format.functions/bug_81590.compile.pass.cpp new file mode 100644 index 0000000000000000000000000000000000000000..127f6546ccbe71f911fe38d7fb6418543cd78898 --- /dev/null +++ b/libcxx/test/std/utilities/format/format.functions/bug_81590.compile.pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// XFAIL: availability-fp_to_chars-missing + +// The sample code is based on the bug report +// https://github.com/llvm/llvm-project/issues/81590 +// +// Tests whether this formatter does not fail to compile due to nested concept +// evaluation. + +#include <format> +#include <variant> + +struct X : std::variant<X*> { + X* p = nullptr; + constexpr const std::variant<X*>& decay() const noexcept { return *this; } +}; + +template <> +struct std::formatter<X, char> : std::formatter<std::string, char> { + static constexpr auto format(const X& x, auto ctx) { + if (!x.p) + return ctx.out(); + auto m = [&](const X* t) { return std::format_to(ctx.out(), "{}", *t); }; + return std::visit(m, x.decay()); + } +}; + +void bug_81590() { (void)std::format("{}", X{}); } diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp index e3a21149c21e4cfa504dedd1e50c3c0e80f9ddd6..d7374351afa8bf5aa72ff5271d672292a237d1b5 100644 --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp @@ -195,6 +195,94 @@ void test_noexcept() { } } +namespace LWG3528 { +template <class T, class Tuple> +auto test_make_from_tuple(T&&, Tuple&& t) -> decltype(std::make_from_tuple<T>(t), uint8_t()) { + return 0; +} +template <class T, class Tuple> +uint32_t test_make_from_tuple(...) { + return 0; +} + +template <class T, class Tuple> +static constexpr bool can_make_from_tuple = + std::is_same_v<decltype(test_make_from_tuple<T, Tuple>(T{}, Tuple{})), uint8_t>; + +template <class T, class Tuple> +auto test_make_from_tuple_impl(T&&, Tuple&& t) + -> decltype(std::__make_from_tuple_impl<T>( + t, typename std::__make_tuple_indices< std::tuple_size_v<std::remove_reference_t<Tuple>>>::type{}), + uint8_t()) { + return 0; +} +template <class T, class Tuple> +uint32_t test_make_from_tuple_impl(...) { + return 0; +} + +template <class T, class Tuple> +static constexpr bool can_make_from_tuple_impl = + std::is_same_v<decltype(test_make_from_tuple_impl<T, Tuple>(T{}, Tuple{})), uint8_t>; + +struct A { + int a; +}; +struct B : public A {}; + +struct C { + C(const B&) {} +}; + +enum class D { + ONE, + TWO, +}; + +// Test std::make_from_tuple constraints. + +// reinterpret_cast +static_assert(!can_make_from_tuple<int*, std::tuple<A*>>); +static_assert(can_make_from_tuple<A*, std::tuple<A*>>); + +// const_cast +static_assert(!can_make_from_tuple<char*, std::tuple<const char*>>); +static_assert(!can_make_from_tuple<volatile char*, std::tuple<const volatile char*>>); +static_assert(can_make_from_tuple<volatile char*, std::tuple<volatile char*>>); +static_assert(can_make_from_tuple<char*, std::tuple<char*>>); +static_assert(can_make_from_tuple<const char*, std::tuple<char*>>); +static_assert(can_make_from_tuple<const volatile char*, std::tuple<volatile char*>>); + +// static_cast +static_assert(!can_make_from_tuple<int, std::tuple<D>>); +static_assert(!can_make_from_tuple<D, std::tuple<int>>); +static_assert(can_make_from_tuple<long, std::tuple<int>>); +static_assert(can_make_from_tuple<double, std::tuple<float>>); +static_assert(can_make_from_tuple<float, std::tuple<double>>); + +// Test std::__make_from_tuple_impl constraints. + +// reinterpret_cast +static_assert(!can_make_from_tuple_impl<int*, std::tuple<A*>>); +static_assert(can_make_from_tuple_impl<A*, std::tuple<A*>>); + +// const_cast +static_assert(!can_make_from_tuple_impl<char*, std::tuple<const char*>>); +static_assert(!can_make_from_tuple_impl<volatile char*, std::tuple<const volatile char*>>); +static_assert(can_make_from_tuple_impl<volatile char*, std::tuple<volatile char*>>); +static_assert(can_make_from_tuple_impl<char*, std::tuple<char*>>); +static_assert(can_make_from_tuple_impl<const char*, std::tuple<char*>>); +static_assert(can_make_from_tuple_impl<const volatile char*, std::tuple<volatile char*>>); + +// static_cast +static_assert(!can_make_from_tuple_impl<int, std::tuple<D>>); +static_assert(!can_make_from_tuple_impl<D, std::tuple<int>>); +static_assert(can_make_from_tuple_impl<long, std::tuple<int>>); +static_assert(can_make_from_tuple_impl<double, std::tuple<float>>); +static_assert(can_make_from_tuple_impl<float, std::tuple<double>>); + +} // namespace LWG3528 + int main(int, char**) { test_constexpr_construction(); diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_incomplete.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_incomplete.pass.cpp index cb8d3e7bde512285fb3321ebe7d795815237a6e7..7585911e2e8d2c421d5485dd6d3f5d1440320f96 100644 --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_incomplete.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_incomplete.pass.cpp @@ -16,9 +16,10 @@ // UNSUPPORTED: c++03 -#include <tuple> #include <array> +#include <tuple> #include <type_traits> +#include <utility> #include "test_macros.h" diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_structured_bindings.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_structured_bindings.pass.cpp index 937d47a38792c6f57218b5cc88672cd75a25296d..2324da3ad5f3ca1e14da5fd88e45064ac94d06f9 100644 --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_structured_bindings.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_structured_bindings.pass.cpp @@ -16,10 +16,10 @@ // UNSUPPORTED: c++03, c++11, c++14 -#include <tuple> #include <array> -#include <type_traits> #include <cassert> +#include <tuple> +#include <utility> #include "test_macros.h" diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_v.verify.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_v.verify.cpp index 7570230b4b0748bdc5760a8520f4086b63b48f9a..149890499678d6d77232a77f52b9653df9c0b1ed 100644 --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_v.verify.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_v.verify.cpp @@ -17,8 +17,8 @@ #include <tuple> void f() { - (void)std::tuple_size_v<std::tuple<> &>; // expected-note {{requested here}} - (void)std::tuple_size_v<int>; // expected-note {{requested here}} - (void)std::tuple_size_v<std::tuple<>*>; // expected-note {{requested here}} - // expected-error@tuple:* 3 {{implicit instantiation of undefined template}} + (void)std::tuple_size_v<std::tuple<>&>; // expected-note {{requested here}} + (void)std::tuple_size_v<int>; // expected-note {{requested here}} + (void)std::tuple_size_v<std::tuple<>*>; // expected-note {{requested here}} + // expected-error@*:* 3 {{implicit instantiation of undefined template}} } diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_value_sfinae.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_value_sfinae.pass.cpp index 6ea92ea8563219ec9896fa2600fb896c9ff84b83..7574bd47e3b427c7d03933a2cee2f706bbd813a0 100644 --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_value_sfinae.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_value_sfinae.pass.cpp @@ -17,7 +17,7 @@ // UNSUPPORTED: c++03 #include <tuple> -#include <type_traits> +#include <utility> #include "test_macros.h" diff --git a/libcxx/test/std/utilities/variant/variant.get/get_if_index.pass.cpp b/libcxx/test/std/utilities/variant/variant.get/get_if_index.pass.cpp index 3333d2a993ec987d587d53807608ed9a4ab32b08..09e2e85abe6681311305ed68ac455daa60a3dc52 100644 --- a/libcxx/test/std/utilities/variant/variant.get/get_if_index.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.get/get_if_index.pass.cpp @@ -44,30 +44,6 @@ void test_const_get_if() { static_assert(*std::get_if<1>(&v) == 42, ""); static_assert(std::get_if<0>(&v) == nullptr, ""); } -// FIXME: Remove these once reference support is reinstated -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int &>; - int x = 42; - const V v(x); - ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), int *); - assert(std::get_if<0>(&v) == &x); - } - { - using V = std::variant<int &&>; - int x = 42; - const V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), int *); - assert(std::get_if<0>(&v) == &x); - } - { - using V = std::variant<const int &&>; - int x = 42; - const V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), const int *); - assert(std::get_if<0>(&v) == &x); - } -#endif } void test_get_if() { @@ -91,37 +67,6 @@ void test_get_if() { assert(*std::get_if<1>(&v) == 42); assert(std::get_if<0>(&v) == nullptr); } -// FIXME: Remove these once reference support is reinstated -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int &>; - int x = 42; - V v(x); - ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), int *); - assert(std::get_if<0>(&v) == &x); - } - { - using V = std::variant<const int &>; - int x = 42; - V v(x); - ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), const int *); - assert(std::get_if<0>(&v) == &x); - } - { - using V = std::variant<int &&>; - int x = 42; - V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), int *); - assert(std::get_if<0>(&v) == &x); - } - { - using V = std::variant<const int &&>; - int x = 42; - V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), const int *); - assert(std::get_if<0>(&v) == &x); - } -#endif } int main(int, char**) { diff --git a/libcxx/test/std/utilities/variant/variant.get/get_if_type.pass.cpp b/libcxx/test/std/utilities/variant/variant.get/get_if_type.pass.cpp index b81e000f5bf6c3ea184fe5348d6425e4bb71f0a9..c4fefc74e62a9c4e55e68c4bc8867b6af6f4bb14 100644 --- a/libcxx/test/std/utilities/variant/variant.get/get_if_type.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.get/get_if_type.pass.cpp @@ -42,30 +42,6 @@ void test_const_get_if() { static_assert(*std::get_if<const long>(&v) == 42, ""); static_assert(std::get_if<int>(&v) == nullptr, ""); } -// FIXME: Remove these once reference support is reinstated -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int &>; - int x = 42; - const V v(x); - ASSERT_SAME_TYPE(decltype(std::get_if<int &>(&v)), int *); - assert(std::get_if<int &>(&v) == &x); - } - { - using V = std::variant<int &&>; - int x = 42; - const V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get_if<int &&>(&v)), int *); - assert(std::get_if<int &&>(&v) == &x); - } - { - using V = std::variant<const int &&>; - int x = 42; - const V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get_if<const int &&>(&v)), const int *); - assert(std::get_if<const int &&>(&v) == &x); - } -#endif } void test_get_if() { @@ -89,37 +65,6 @@ void test_get_if() { assert(*std::get_if<const long>(&v) == 42); assert(std::get_if<int>(&v) == nullptr); } -// FIXME: Remove these once reference support is reinstated -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int &>; - int x = 42; - V v(x); - ASSERT_SAME_TYPE(decltype(std::get_if<int &>(&v)), int *); - assert(std::get_if<int &>(&v) == &x); - } - { - using V = std::variant<const int &>; - int x = 42; - V v(x); - ASSERT_SAME_TYPE(decltype(std::get_if<const int &>(&v)), const int *); - assert(std::get_if<const int &>(&v) == &x); - } - { - using V = std::variant<int &&>; - int x = 42; - V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get_if<int &&>(&v)), int *); - assert(std::get_if<int &&>(&v) == &x); - } - { - using V = std::variant<const int &&>; - int x = 42; - V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get_if<const int &&>(&v)), const int *); - assert(std::get_if<const int &&>(&v) == &x); - } -#endif } int main(int, char**) { diff --git a/libcxx/test/std/utilities/variant/variant.get/get_index.pass.cpp b/libcxx/test/std/utilities/variant/variant.get/get_index.pass.cpp index 97c7ff0ed095791988648b24e2e9bc89ef59e120..7ec9d8827f6b4b1acf1161d7c56b84dac376dddc 100644 --- a/libcxx/test/std/utilities/variant/variant.get/get_index.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.get/get_index.pass.cpp @@ -60,30 +60,6 @@ void test_const_lvalue_get() { ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &); assert(std::get<1>(v) == 42); } -// FIXME: Remove these once reference support is reinstated -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int &>; - int x = 42; - const V v(x); - ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &); - assert(&std::get<0>(v) == &x); - } - { - using V = std::variant<int &&>; - int x = 42; - const V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &); - assert(&std::get<0>(v) == &x); - } - { - using V = std::variant<const int &&>; - int x = 42; - const V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &); - assert(&std::get<0>(v) == &x); - } -#endif } void test_lvalue_get() { @@ -100,37 +76,6 @@ void test_lvalue_get() { ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &); assert(std::get<1>(v) == 42); } -// FIXME: Remove these once reference support is reinstated -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int &>; - int x = 42; - V v(x); - ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &); - assert(&std::get<0>(v) == &x); - } - { - using V = std::variant<const int &>; - int x = 42; - V v(x); - ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &); - assert(&std::get<0>(v) == &x); - } - { - using V = std::variant<int &&>; - int x = 42; - V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &); - assert(&std::get<0>(v) == &x); - } - { - using V = std::variant<const int &&>; - int x = 42; - V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &); - assert(&std::get<0>(v) == &x); - } -#endif } void test_rvalue_get() { @@ -147,39 +92,6 @@ void test_rvalue_get() { ASSERT_SAME_TYPE(decltype(std::get<1>(std::move(v))), const long &&); assert(std::get<1>(std::move(v)) == 42); } -// FIXME: Remove these once reference support is reinstated -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int &>; - int x = 42; - V v(x); - ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &); - assert(&std::get<0>(std::move(v)) == &x); - } - { - using V = std::variant<const int &>; - int x = 42; - V v(x); - ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &); - assert(&std::get<0>(std::move(v)) == &x); - } - { - using V = std::variant<int &&>; - int x = 42; - V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&); - int &&xref = std::get<0>(std::move(v)); - assert(&xref == &x); - } - { - using V = std::variant<const int &&>; - int x = 42; - V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&); - const int &&xref = std::get<0>(std::move(v)); - assert(&xref == &x); - } -#endif } void test_const_rvalue_get() { @@ -196,39 +108,6 @@ void test_const_rvalue_get() { ASSERT_SAME_TYPE(decltype(std::get<1>(std::move(v))), const long &&); assert(std::get<1>(std::move(v)) == 42); } -// FIXME: Remove these once reference support is reinstated -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int &>; - int x = 42; - const V v(x); - ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &); - assert(&std::get<0>(std::move(v)) == &x); - } - { - using V = std::variant<const int &>; - int x = 42; - const V v(x); - ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &); - assert(&std::get<0>(std::move(v)) == &x); - } - { - using V = std::variant<int &&>; - int x = 42; - const V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&); - int &&xref = std::get<0>(std::move(v)); - assert(&xref == &x); - } - { - using V = std::variant<const int &&>; - int x = 42; - const V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&); - const int &&xref = std::get<0>(std::move(v)); - assert(&xref == &x); - } -#endif } template <std::size_t I> using Idx = std::integral_constant<std::size_t, I>; diff --git a/libcxx/test/std/utilities/variant/variant.get/get_type.pass.cpp b/libcxx/test/std/utilities/variant/variant.get/get_type.pass.cpp index d5e54d41e2f7b4d34a9ec318479c856104da2e96..3485122c98f0b19ae5256071e4458ba9fa0e6519 100644 --- a/libcxx/test/std/utilities/variant/variant.get/get_type.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.get/get_type.pass.cpp @@ -54,30 +54,6 @@ void test_const_lvalue_get() { ASSERT_SAME_TYPE(decltype(std::get<const long>(v)), const long &); assert(std::get<const long>(v) == 42); } -// FIXME: Remove these once reference support is reinstated -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int &>; - int x = 42; - const V v(x); - ASSERT_SAME_TYPE(decltype(std::get<int &>(v)), int &); - assert(&std::get<int &>(v) == &x); - } - { - using V = std::variant<int &&>; - int x = 42; - const V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get<int &&>(v)), int &); - assert(&std::get<int &&>(v) == &x); - } - { - using V = std::variant<const int &&>; - int x = 42; - const V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get<const int &&>(v)), const int &); - assert(&std::get<const int &&>(v) == &x); - } -#endif } void test_lvalue_get() { @@ -94,37 +70,6 @@ void test_lvalue_get() { ASSERT_SAME_TYPE(decltype(std::get<const long>(v)), const long &); assert(std::get<const long>(v) == 42); } -// FIXME: Remove these once reference support is reinstated -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int &>; - int x = 42; - V v(x); - ASSERT_SAME_TYPE(decltype(std::get<int &>(v)), int &); - assert(&std::get<int &>(v) == &x); - } - { - using V = std::variant<const int &>; - int x = 42; - V v(x); - ASSERT_SAME_TYPE(decltype(std::get<const int &>(v)), const int &); - assert(&std::get<const int &>(v) == &x); - } - { - using V = std::variant<int &&>; - int x = 42; - V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get<int &&>(v)), int &); - assert(&std::get<int &&>(v) == &x); - } - { - using V = std::variant<const int &&>; - int x = 42; - V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get<const int &&>(v)), const int &); - assert(&std::get<const int &&>(v) == &x); - } -#endif } void test_rvalue_get() { @@ -142,41 +87,6 @@ void test_rvalue_get() { const long &&); assert(std::get<const long>(std::move(v)) == 42); } -// FIXME: Remove these once reference support is reinstated -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int &>; - int x = 42; - V v(x); - ASSERT_SAME_TYPE(decltype(std::get<int &>(std::move(v))), int &); - assert(&std::get<int &>(std::move(v)) == &x); - } - { - using V = std::variant<const int &>; - int x = 42; - V v(x); - ASSERT_SAME_TYPE(decltype(std::get<const int &>(std::move(v))), - const int &); - assert(&std::get<const int &>(std::move(v)) == &x); - } - { - using V = std::variant<int &&>; - int x = 42; - V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get<int &&>(std::move(v))), int &&); - int &&xref = std::get<int &&>(std::move(v)); - assert(&xref == &x); - } - { - using V = std::variant<const int &&>; - int x = 42; - V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get<const int &&>(std::move(v))), - const int &&); - const int &&xref = std::get<const int &&>(std::move(v)); - assert(&xref == &x); - } -#endif } void test_const_rvalue_get() { @@ -194,41 +104,6 @@ void test_const_rvalue_get() { const long &&); assert(std::get<const long>(std::move(v)) == 42); } -// FIXME: Remove these once reference support is reinstated -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int &>; - int x = 42; - const V v(x); - ASSERT_SAME_TYPE(decltype(std::get<int &>(std::move(v))), int &); - assert(&std::get<int &>(std::move(v)) == &x); - } - { - using V = std::variant<const int &>; - int x = 42; - const V v(x); - ASSERT_SAME_TYPE(decltype(std::get<const int &>(std::move(v))), - const int &); - assert(&std::get<const int &>(std::move(v)) == &x); - } - { - using V = std::variant<int &&>; - int x = 42; - const V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get<int &&>(std::move(v))), int &&); - int &&xref = std::get<int &&>(std::move(v)); - assert(&xref == &x); - } - { - using V = std::variant<const int &&>; - int x = 42; - const V v(std::move(x)); - ASSERT_SAME_TYPE(decltype(std::get<const int &&>(std::move(v))), - const int &&); - const int &&xref = std::get<const int &&>(std::move(v)); - assert(&xref == &x); - } -#endif } template <class Tp> struct identity { using type = Tp; }; diff --git a/libcxx/test/std/utilities/variant/variant.helpers/variant_alternative.pass.cpp b/libcxx/test/std/utilities/variant/variant.helpers/variant_alternative.pass.cpp index be1a0c960d1cee5eeb54fccbf71f9d2eecdd7916..31b9b76213c45cda4e4dce812f821cd8be3bc4fe 100644 --- a/libcxx/test/std/utilities/variant/variant.helpers/variant_alternative.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.helpers/variant_alternative.pass.cpp @@ -62,16 +62,6 @@ int main(int, char**) { test<V, 2, const void *>(); test<V, 3, long double>(); } -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int, int &, const int &, int &&, long double>; - test<V, 0, int>(); - test<V, 1, int &>(); - test<V, 2, const int &>(); - test<V, 3, int &&>(); - test<V, 4, long double>(); - } -#endif return 0; } diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp index b3fc2021a6b223761fbcd38be48bd3589eb0e0a6..4b9eaba2d2ba8191f2d6ac89b8b189b3a14bdd33 100644 --- a/libcxx/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp @@ -134,8 +134,7 @@ void test_T_assignment_sfinae() { } { using V = std::variant<std::string, float>; - static_assert(std::is_assignable<V, int>::value == VariantAllowsNarrowingConversions, - "no matching operator="); + static_assert(!std::is_assignable<V, int>::value, "no matching operator="); } { using V = std::variant<std::unique_ptr<int>, bool>; @@ -144,12 +143,8 @@ void test_T_assignment_sfinae() { struct X { operator void*(); }; - static_assert(!std::is_assignable<V, X>::value, - "no boolean conversion in operator="); -#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT - static_assert(std::is_assignable<V, std::false_type>::value, - "converted to bool in operator="); -#endif + static_assert(!std::is_assignable<V, X>::value, "no boolean conversion in operator="); + static_assert(std::is_assignable<V, std::false_type>::value, "converted to bool in operator="); } { struct X {}; @@ -160,16 +155,6 @@ void test_T_assignment_sfinae() { static_assert(std::is_assignable<V, Y>::value, "regression on user-defined conversions in operator="); } -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int, int &&>; - static_assert(!std::is_assignable<V, int>::value, "ambiguous"); - } - { - using V = std::variant<int, const int &>; - static_assert(!std::is_assignable<V, int>::value, "ambiguous"); - } -#endif // TEST_VARIANT_HAS_NO_REFERENCES } void test_T_assignment_basic() { @@ -188,7 +173,6 @@ void test_T_assignment_basic() { assert(v.index() == 1); assert(std::get<1>(v) == 43); } -#ifndef TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS { std::variant<unsigned, long> v; v = 42; @@ -198,7 +182,6 @@ void test_T_assignment_basic() { assert(v.index() == 0); assert(std::get<0>(v) == 43); } -#endif { std::variant<std::string, bool> v = true; v = "bar"; @@ -211,25 +194,6 @@ void test_T_assignment_basic() { assert(v.index() == 1); assert(std::get<1>(v) == nullptr); } -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int &, int &&, long>; - int x = 42; - V v(43l); - v = x; - assert(v.index() == 0); - assert(&std::get<0>(v) == &x); - v = std::move(x); - assert(v.index() == 1); - assert(&std::get<1>(v) == &x); - // 'long' is selected by FUN(const int &) since 'const int &' cannot bind - // to 'int&'. - const int &cx = x; - v = cx; - assert(v.index() == 2); - assert(std::get<2>(v) == 42); - } -#endif // TEST_VARIANT_HAS_NO_REFERENCES } void test_T_assignment_performs_construction() { @@ -299,13 +263,11 @@ void test_T_assignment_performs_assignment() { } void test_T_assignment_vector_bool() { -#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT std::vector<bool> vec = {true}; std::variant<bool, int> v; v = vec[0]; assert(v.index() == 0); assert(std::get<0>(v) == true); -#endif } int main(int, char**) { diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.assign/conv.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.assign/conv.pass.cpp index 246309c01b4d76bb8ecd28fe603479e504b56e5a..90e405d577500dc31b3a7a6e67d584a0d720fd42 100644 --- a/libcxx/test/std/utilities/variant/variant.variant/variant.assign/conv.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.assign/conv.pass.cpp @@ -25,18 +25,16 @@ int main(int, char**) { static_assert(!std::is_assignable<std::variant<int, int>, int>::value, ""); static_assert(!std::is_assignable<std::variant<long, long long>, int>::value, ""); - static_assert(std::is_assignable<std::variant<char>, int>::value == VariantAllowsNarrowingConversions, ""); + static_assert(!std::is_assignable<std::variant<char>, int>::value, ""); - static_assert(std::is_assignable<std::variant<std::string, float>, int>::value == VariantAllowsNarrowingConversions, ""); - static_assert(std::is_assignable<std::variant<std::string, double>, int>::value == VariantAllowsNarrowingConversions, ""); + static_assert(!std::is_assignable<std::variant<std::string, float>, int>::value, ""); + static_assert(!std::is_assignable<std::variant<std::string, double>, int>::value, ""); static_assert(!std::is_assignable<std::variant<std::string, bool>, int>::value, ""); static_assert(!std::is_assignable<std::variant<int, bool>, decltype("meow")>::value, ""); static_assert(!std::is_assignable<std::variant<int, const bool>, decltype("meow")>::value, ""); -#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT static_assert(std::is_assignable<std::variant<bool>, std::true_type>::value, ""); -#endif static_assert(!std::is_assignable<std::variant<bool>, std::unique_ptr<char> >::value, ""); static_assert(!std::is_assignable<std::variant<bool>, decltype(nullptr)>::value, ""); diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp index 89fd646878eeca527cba0f44c3719d7ada653a5d..142da1d820d9a75ad62a489bcc027d8d6441c1b1 100644 --- a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp @@ -36,10 +36,17 @@ struct NoThrowT { NoThrowT(int) noexcept(true) {} }; -struct AnyConstructible { template <typename T> AnyConstructible(T&&) {} }; -struct NoConstructible { NoConstructible() = delete; }; +struct AnyConstructible { + template <typename T> + AnyConstructible(T&&) {} +}; +struct NoConstructible { + NoConstructible() = delete; +}; template <class T> -struct RValueConvertibleFrom { RValueConvertibleFrom(T&&) {} }; +struct RValueConvertibleFrom { + RValueConvertibleFrom(T&&) {} +}; void test_T_ctor_noexcept() { { @@ -59,31 +66,24 @@ void test_T_ctor_sfinae() { } { using V = std::variant<std::string, std::string>; - static_assert(!std::is_constructible<V, const char *>::value, "ambiguous"); + static_assert(!std::is_constructible<V, const char*>::value, "ambiguous"); } { - using V = std::variant<std::string, void *>; - static_assert(!std::is_constructible<V, int>::value, - "no matching constructor"); + using V = std::variant<std::string, void*>; + static_assert(!std::is_constructible<V, int>::value, "no matching constructor"); } { using V = std::variant<std::string, float>; - static_assert(std::is_constructible<V, int>::value == VariantAllowsNarrowingConversions, - "no matching constructor"); + static_assert(!std::is_constructible<V, int>::value, "no matching constructor"); } { using V = std::variant<std::unique_ptr<int>, bool>; - static_assert(!std::is_constructible<V, std::unique_ptr<char>>::value, - "no explicit bool in constructor"); + static_assert(!std::is_constructible<V, std::unique_ptr<char>>::value, "no explicit bool in constructor"); struct X { operator void*(); }; - static_assert(!std::is_constructible<V, X>::value, - "no boolean conversion in constructor"); -#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT - static_assert(std::is_constructible<V, std::false_type>::value, - "converted to bool in constructor"); -#endif + static_assert(!std::is_constructible<V, X>::value, "no boolean conversion in constructor"); + static_assert(std::is_constructible<V, std::false_type>::value, "converted to bool in constructor"); } { struct X {}; @@ -91,30 +91,13 @@ void test_T_ctor_sfinae() { operator X(); }; using V = std::variant<X>; - static_assert(std::is_constructible<V, Y>::value, - "regression on user-defined conversions in constructor"); + static_assert(std::is_constructible<V, Y>::value, "regression on user-defined conversions in constructor"); } { using V = std::variant<AnyConstructible, NoConstructible>; - static_assert( - !std::is_constructible<V, std::in_place_type_t<NoConstructible>>::value, - "no matching constructor"); - static_assert(!std::is_constructible<V, std::in_place_index_t<1>>::value, - "no matching constructor"); - } - - - -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int, int &&>; - static_assert(!std::is_constructible<V, int>::value, "ambiguous"); + static_assert(!std::is_constructible<V, std::in_place_type_t<NoConstructible>>::value, "no matching constructor"); + static_assert(!std::is_constructible<V, std::in_place_index_t<1>>::value, "no matching constructor"); } - { - using V = std::variant<int, const int &>; - static_assert(!std::is_constructible<V, int>::value, "ambiguous"); - } -#endif } void test_T_ctor_basic() { @@ -128,13 +111,11 @@ void test_T_ctor_basic() { static_assert(v.index() == 1, ""); static_assert(std::get<1>(v) == 42, ""); } -#ifndef TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS { constexpr std::variant<unsigned, long> v(42); static_assert(v.index() == 1, ""); static_assert(std::get<1>(v) == 42, ""); } -#endif { std::variant<std::string, bool const> v = "foo"; assert(v.index() == 0); @@ -154,33 +135,17 @@ void test_T_ctor_basic() { std::variant<RValueConvertibleFrom<int>> v1 = 42; assert(v1.index() == 0); - int x = 42; + int x = 42; std::variant<RValueConvertibleFrom<int>, AnyConstructible> v2 = x; assert(v2.index() == 1); } -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<const int &, int &&, long>; - static_assert(std::is_convertible<int &, V>::value, "must be implicit"); - int x = 42; - V v(x); - assert(v.index() == 0); - assert(&std::get<0>(v) == &x); - } - { - using V = std::variant<const int &, int &&, long>; - static_assert(std::is_convertible<int, V>::value, "must be implicit"); - int x = 42; - V v(std::move(x)); - assert(v.index() == 1); - assert(&std::get<1>(v) == &x); - } -#endif } struct BoomOnAnything { template <class T> - constexpr BoomOnAnything(T) { static_assert(!std::is_same<T, T>::value, ""); } + constexpr BoomOnAnything(T) { + static_assert(!std::is_same<T, T>::value, ""); + } }; void test_no_narrowing_check_for_class_types() { @@ -202,12 +167,10 @@ void test_construction_with_repeated_types() { } void test_vector_bool() { -#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT std::vector<bool> vec = {true}; std::variant<bool, int> v = vec[0]; assert(v.index() == 0); assert(std::get<0>(v) == true); -#endif } int main(int, char**) { diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/conv.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/conv.pass.cpp index 7fb44ff407653ba7efe37894093bbe8aedb652f6..0b8eeed1eac86d3a20b3d7b0ae903f851851e540 100644 --- a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/conv.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/conv.pass.cpp @@ -24,18 +24,16 @@ int main(int, char**) { static_assert(!std::is_constructible<std::variant<int, int>, int>::value, ""); static_assert(!std::is_constructible<std::variant<long, long long>, int>::value, ""); - static_assert(std::is_constructible<std::variant<char>, int>::value == VariantAllowsNarrowingConversions, ""); + static_assert(!std::is_constructible<std::variant<char>, int>::value, ""); - static_assert(std::is_constructible<std::variant<std::string, float>, int>::value == VariantAllowsNarrowingConversions, ""); - static_assert(std::is_constructible<std::variant<std::string, double>, int>::value == VariantAllowsNarrowingConversions, ""); + static_assert(!std::is_constructible<std::variant<std::string, float>, int>::value, ""); + static_assert(!std::is_constructible<std::variant<std::string, double>, int>::value, ""); static_assert(!std::is_constructible<std::variant<std::string, bool>, int>::value, ""); static_assert(!std::is_constructible<std::variant<int, bool>, decltype("meow")>::value, ""); static_assert(!std::is_constructible<std::variant<int, const bool>, decltype("meow")>::value, ""); -#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT static_assert(std::is_constructible<std::variant<bool>, std::true_type>::value, ""); -#endif static_assert(!std::is_constructible<std::variant<bool>, std::unique_ptr<char> >::value, ""); static_assert(!std::is_constructible<std::variant<bool>, decltype(nullptr)>::value, ""); diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/default.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/default.pass.cpp index cc1a3fe8ff78af01b0520b9079b9c07f9abf91e3..40db038a0033663a16acfa6f4529d7d6fdfedd58 100644 --- a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/default.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/default.pass.cpp @@ -44,12 +44,6 @@ void test_default_ctor_sfinae() { using V = std::variant<NonDefaultConstructible, int>; static_assert(!std::is_default_constructible<V>::value, ""); } -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int &, int>; - static_assert(!std::is_default_constructible<V>::value, ""); - } -#endif } void test_default_ctor_noexcept() { diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_args.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_args.pass.cpp index 96fcd7e7bee4817e63dba9f4c03655ca379341ba..2fe9033dd8166f08251bd5382532b588ccce0f44 100644 --- a/libcxx/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_args.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.mod/emplace_index_args.pass.cpp @@ -55,29 +55,6 @@ void test_emplace_sfinae() { static_assert(emplace_exists<V, 2, int *>(), ""); static_assert(!emplace_exists<V, 3>(), "cannot construct"); } -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int, int &, const int &, int &&, TestTypes::NoCtors>; - static_assert(emplace_exists<V, 0>(), ""); - static_assert(emplace_exists<V, 0, int>(), ""); - static_assert(emplace_exists<V, 0, long long>(), ""); - static_assert(!emplace_exists<V, 0, int, int>(), "too many args"); - static_assert(emplace_exists<V, 1, int &>(), ""); - static_assert(!emplace_exists<V, 1>(), "cannot default construct ref"); - static_assert(!emplace_exists<V, 1, const int &>(), "cannot bind ref"); - static_assert(!emplace_exists<V, 1, int &&>(), "cannot bind ref"); - static_assert(emplace_exists<V, 2, int &>(), ""); - static_assert(emplace_exists<V, 2, const int &>(), ""); - static_assert(emplace_exists<V, 2, int &&>(), ""); - static_assert(!emplace_exists<V, 2, void *>(), - "not constructible from void*"); - static_assert(emplace_exists<V, 3, int>(), ""); - static_assert(!emplace_exists<V, 3, int &>(), "cannot bind ref"); - static_assert(!emplace_exists<V, 3, const int &>(), "cannot bind ref"); - static_assert(!emplace_exists<V, 3, const int &&>(), "cannot bind ref"); - static_assert(!emplace_exists<V, 4>(), "no ctors"); - } -#endif } void test_basic() { @@ -113,41 +90,6 @@ void test_basic() { assert(std::get<4>(v) == "aaa"); assert(&ref3 == &std::get<4>(v)); } -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int, long, const int &, int &&, TestTypes::NoCtors, - std::string>; - const int x = 100; - int y = 42; - int z = 43; - V v(std::in_place_index<0>, -1); - // default emplace a value - auto& ref1 = v.emplace<1>(); - static_assert(std::is_same_v<long&, decltype(ref1)>, ""); - assert(std::get<1>(v) == 0); - assert(&ref1 == &std::get<1>(v)); - // emplace a reference - auto& ref2 = v.emplace<2>(x); - static_assert(std::is_same_v<&, decltype(ref)>, ""); - assert(&std::get<2>(v) == &x); - assert(&ref2 == &std::get<2>(v)); - // emplace an rvalue reference - auto& ref3 = v.emplace<3>(std::move(y)); - static_assert(std::is_same_v<&, decltype(ref)>, ""); - assert(&std::get<3>(v) == &y); - assert(&ref3 == &std::get<3>(v)); - // re-emplace a new reference over the active member - auto& ref4 = v.emplace<3>(std::move(z)); - static_assert(std::is_same_v<&, decltype(ref)>, ""); - assert(&std::get<3>(v) == &z); - assert(&ref4 == &std::get<3>(v)); - // emplace with multiple args - auto& ref5 = v.emplace<5>(3u, 'a'); - static_assert(std::is_same_v<std::string&, decltype(ref5)>, ""); - assert(std::get<5>(v) == "aaa"); - assert(&ref5 == &std::get<5>(v)); - } -#endif } int main(int, char**) { diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_args.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_args.pass.cpp index 24305aa0a35daea625145eadcd096a3f9d9fc0d3..4e9f67775d10c49a11e82e7f429aaa2e2604d83d 100644 --- a/libcxx/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_args.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.mod/emplace_type_args.pass.cpp @@ -54,30 +54,6 @@ void test_emplace_sfinae() { static_assert(emplace_exists<V, const void *, int *>(), ""); static_assert(!emplace_exists<V, TestTypes::NoCtors>(), "cannot construct"); } -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - using V = std::variant<int, int &, const int &, int &&, long, long, - TestTypes::NoCtors>; - static_assert(emplace_exists<V, int>(), ""); - static_assert(emplace_exists<V, int, int>(), ""); - static_assert(emplace_exists<V, int, long long>(), ""); - static_assert(!emplace_exists<V, int, int, int>(), "too many args"); - static_assert(emplace_exists<V, int &, int &>(), ""); - static_assert(!emplace_exists<V, int &>(), "cannot default construct ref"); - static_assert(!emplace_exists<V, int &, const int &>(), "cannot bind ref"); - static_assert(!emplace_exists<V, int &, int &&>(), "cannot bind ref"); - static_assert(emplace_exists<V, const int &, int &>(), ""); - static_assert(emplace_exists<V, const int &, const int &>(), ""); - static_assert(emplace_exists<V, const int &, int &&>(), ""); - static_assert(!emplace_exists<V, const int &, void *>(), - "not constructible from void*"); - static_assert(emplace_exists<V, int &&, int>(), ""); - static_assert(!emplace_exists<V, int &&, int &>(), "cannot bind ref"); - static_assert(!emplace_exists<V, int &&, const int &>(), "cannot bind ref"); - static_assert(!emplace_exists<V, int &&, const int &&>(), "cannot bind ref"); - static_assert(!emplace_exists<V, long, long>(), "ambiguous"); - static_assert(!emplace_exists<V, TestTypes::NoCtors>(), - "cannot construct void"); -#endif } void test_basic() { @@ -113,41 +89,6 @@ void test_basic() { assert(std::get<4>(v) == "aaa"); assert(&ref3 == &std::get<4>(v)); } -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { - using V = std::variant<int, long, const int &, int &&, TestTypes::NoCtors, - std::string>; - const int x = 100; - int y = 42; - int z = 43; - V v(std::in_place_index<0>, -1); - // default emplace a value - auto& ref1 = v.emplace<long>(); - static_assert(std::is_same_v<long&, decltype(ref1)>, ""); - assert(std::get<long>(v) == 0); - assert(&ref1 == &std::get<long>(v)); - // emplace a reference - auto& ref2 = v.emplace<const int &>(x); - static_assert(std::is_same_v<const int&, decltype(ref2)>, ""); - assert(&std::get<const int &>(v) == &x); - assert(&ref2 == &std::get<const int &>(v)); - // emplace an rvalue reference - auto& ref3 = v.emplace<int &&>(std::move(y)); - static_assert(std::is_same_v<int &&, decltype(ref3)>, ""); - assert(&std::get<int &&>(v) == &y); - assert(&ref3 == &std::get<int &&>(v)); - // re-emplace a new reference over the active member - auto& ref4 = v.emplace<int &&>(std::move(z)); - static_assert(std::is_same_v<int &, decltype(ref4)>, ""); - assert(&std::get<int &&>(v) == &z); - assert(&ref4 == &std::get<int &&>(v)); - // emplace with multiple args - auto& ref5 = v.emplace<std::string>(3u, 'a'); - static_assert(std::is_same_v<std::string&, decltype(ref5)>, ""); - assert(std::get<std::string>(v) == "aaa"); - assert(&ref5 == &std::get<std::string>(v)); - } -#endif } int main(int, char**) { diff --git a/libcxx/test/std/utilities/variant/variant.visit.member/visit.pass.cpp b/libcxx/test/std/utilities/variant/variant.visit.member/visit.pass.cpp index 50e7fc81387abc59c24ac92dd1e7c36952dfcdb1..d0c909985bbb37452e14eb63e6e1f32ec87f8a44 100644 --- a/libcxx/test/std/utilities/variant/variant.visit.member/visit.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.visit.member/visit.pass.cpp @@ -82,39 +82,6 @@ void test_argument_forwarding() { std::move(cv).visit(obj); assert(Fn::check_call<const int&&>(val)); } -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { // single argument - lvalue reference - using V = std::variant<int&>; - int x = 42; - V v(x); - const V& cv = v; - - v.visit(obj); - assert(Fn::check_call<int&>(val)); - cv.visit(obj); - assert(Fn::check_call<int&>(val)); - std::move(v).visit(obj); - assert(Fn::check_call<int&>(val)); - std::move(cv).visit(obj); - assert(Fn::check_call<int&>(val)); - assert(false); - } - { // single argument - rvalue reference - using V = std::variant<int&&>; - int x = 42; - V v(std::move(x)); - const V& cv = v; - - v.visit(obj); - assert(Fn::check_call<int&>(val)); - cvstd::visit(obj); - assert(Fn::check_call<int&>(val)); - std::move(v).visit(obj); - assert(Fn::check_call<int&&>(val)); - std::move(cv).visit(obj); - assert(Fn::check_call<int&&>(val)); - } -#endif } void test_return_type() { diff --git a/libcxx/test/std/utilities/variant/variant.visit.member/visit_return_type.pass.cpp b/libcxx/test/std/utilities/variant/variant.visit.member/visit_return_type.pass.cpp index b005f303bc4b6cae555654d052f0de65c64531a3..3312197d8df9c3841a9c904ed265883383d3fa8b 100644 --- a/libcxx/test/std/utilities/variant/variant.visit.member/visit_return_type.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.visit.member/visit_return_type.pass.cpp @@ -110,38 +110,6 @@ void test_argument_forwarding() { std::move(cv).visit<ReturnType>(obj); assert(Fn::check_call<const int&&>(val)); } -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { // single argument - lvalue reference - using V = std::variant<int&>; - int x = 42; - V v(x); - const V& cv = v; - - v.visit<ReturnType>(obj); - assert(Fn::check_call<int&>(val)); - cv.visit<ReturnType>(obj); - assert(Fn::check_call<int&>(val)); - std::move(v).visit<ReturnType>(obj); - assert(Fn::check_call<int&>(val)); - std::move(cv).visit<ReturnType>(obj); - assert(Fn::check_call<int&>(val)); - } - { // single argument - rvalue reference - using V = std::variant<int&&>; - int x = 42; - V v(std::move(x)); - const V& cv = v; - - v.visit<ReturnType>(obj); - assert(Fn::check_call<int&>(val)); - cv.visit<ReturnType>(obj); - assert(Fn::check_call<int&>(val)); - std::move(v).visit<ReturnType>(obj); - assert(Fn::check_call<int&&>(val)); - std::move(cv).visit<ReturnType>(obj); - assert(Fn::check_call<int&&>(val)); - } -#endif } template <typename ReturnType> diff --git a/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp b/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp index 798ce7ded72a6075776620be8d8dd02eb8d1cc41..0caecbe875d55e369a451169c5bf8fb184bf2b9f 100644 --- a/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp @@ -118,36 +118,6 @@ void test_argument_forwarding() { std::visit(obj, std::move(cv)); assert(Fn::check_call<const int &&>(Val)); } -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { // single argument - lvalue reference - using V = std::variant<int &>; - int x = 42; - V v(x); - const V &cv = v; - std::visit(obj, v); - assert(Fn::check_call<int &>(Val)); - std::visit(obj, cv); - assert(Fn::check_call<int &>(Val)); - std::visit(obj, std::move(v)); - assert(Fn::check_call<int &>(Val)); - std::visit(obj, std::move(cv)); - assert(Fn::check_call<int &>(Val)); - } - { // single argument - rvalue reference - using V = std::variant<int &&>; - int x = 42; - V v(std::move(x)); - const V &cv = v; - std::visit(obj, v); - assert(Fn::check_call<int &>(Val)); - std::visit(obj, cv); - assert(Fn::check_call<int &>(Val)); - std::visit(obj, std::move(v)); - assert(Fn::check_call<int &&>(Val)); - std::visit(obj, std::move(cv)); - assert(Fn::check_call<int &&>(Val)); - } -#endif { // multi argument - multi variant using V = std::variant<int, std::string, long>; V v1(42), v2("hello"), v3(43l); diff --git a/libcxx/test/std/utilities/variant/variant.visit/visit_return_type.pass.cpp b/libcxx/test/std/utilities/variant/variant.visit/visit_return_type.pass.cpp index b1189dff656db4edd3fade6ef1811230d55ec02c..d26c785c03747723a07b6720cb7316967827dfb3 100644 --- a/libcxx/test/std/utilities/variant/variant.visit/visit_return_type.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.visit/visit_return_type.pass.cpp @@ -120,36 +120,6 @@ void test_argument_forwarding() { std::visit<ReturnType>(obj, std::move(cv)); assert(Fn::check_call<const int &&>(Val)); } -#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) - { // single argument - lvalue reference - using V = std::variant<int &>; - int x = 42; - V v(x); - const V &cv = v; - std::visit<ReturnType>(obj, v); - assert(Fn::check_call<int &>(Val)); - std::visit<ReturnType>(obj, cv); - assert(Fn::check_call<int &>(Val)); - std::visit<ReturnType>(obj, std::move(v)); - assert(Fn::check_call<int &>(Val)); - std::visit<ReturnType>(obj, std::move(cv)); - assert(Fn::check_call<int &>(Val)); - } - { // single argument - rvalue reference - using V = std::variant<int &&>; - int x = 42; - V v(std::move(x)); - const V &cv = v; - std::visit<ReturnType>(obj, v); - assert(Fn::check_call<int &>(Val)); - std::visit<ReturnType>(obj, cv); - assert(Fn::check_call<int &>(Val)); - std::visit<ReturnType>(obj, std::move(v)); - assert(Fn::check_call<int &&>(Val)); - std::visit<ReturnType>(obj, std::move(cv)); - assert(Fn::check_call<int &&>(Val)); - } -#endif { // multi argument - multi variant using V = std::variant<int, std::string, long>; V v1(42), v2("hello"), v3(43l); diff --git a/libcxx/test/support/deduction_guides_sfinae_checks.h b/libcxx/test/support/deduction_guides_sfinae_checks.h index 8b715da5a34e25f95414256dad021f53621adda3..0c32b3732413a9fef3f3075c6a15357c919a5a4d 100644 --- a/libcxx/test/support/deduction_guides_sfinae_checks.h +++ b/libcxx/test/support/deduction_guides_sfinae_checks.h @@ -16,6 +16,7 @@ #include <memory> #include <type_traits> #include <utility> +#include <vector> #include "test_macros.h" #if TEST_STD_VER >= 23 diff --git a/libcxx/test/support/variant_test_helpers.h b/libcxx/test/support/variant_test_helpers.h index c174cba3284019b4e9c346c5ab391ac655e4d6dc..d1bc36dea671ecafb5f311634dd3fa45a9d762b7 100644 --- a/libcxx/test/support/variant_test_helpers.h +++ b/libcxx/test/support/variant_test_helpers.h @@ -21,19 +21,6 @@ #error This file requires C++17 #endif -// FIXME: Currently the variant<T&> tests are disabled using this macro. -#define TEST_VARIANT_HAS_NO_REFERENCES - -// TODO(LLVM-19): Remove TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS -#ifdef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT -# define TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS -#endif -#ifdef TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS -constexpr bool VariantAllowsNarrowingConversions = true; -#else -constexpr bool VariantAllowsNarrowingConversions = false; -#endif - #ifndef TEST_HAS_NO_EXCEPTIONS struct CopyThrows { CopyThrows() = default; diff --git a/libcxx/utils/ci/Dockerfile b/libcxx/utils/ci/Dockerfile index 178cba415933883c361d9b322c329eb07f78e971..db88da20b977a885e57aa38ef296191bc02da400 100644 --- a/libcxx/utils/ci/Dockerfile +++ b/libcxx/utils/ci/Dockerfile @@ -7,15 +7,13 @@ #===----------------------------------------------------------------------===## # # This file defines the buildkite and github actions builder images. -# You can build & push both images using: +# You can build both images using: # # docker compose build -# docker compose push # -# Or you can select a single image to build & push using: +# Or you can select a single image to build # # docker compose build buildkite-builder -# docker compose push buildkite-builder # # The final images can be found at # @@ -23,7 +21,8 @@ # ghcr.io/libcxx/actions-builder # ghcr.io/libcxx/android-buildkite-builder # -# Members of the github.com/libcxx/ organizations have permissions required to push new images. +# Members of the github.com/libcxx/ organizations can push new images to the CI. +# This is done by GitHub actions in the https://github.com/libcxx/builders repo. # # ===----------------------------------------------------------------------===## # Running the buildkite image diff --git a/libcxx/utils/ci/buildkite-pipeline.yml b/libcxx/utils/ci/buildkite-pipeline.yml index e42262620d5fb0137d5648aa8e21db3f923d1888..c43e414418729a99f491f7cc79b9a0423cd42dc7 100644 --- a/libcxx/utils/ci/buildkite-pipeline.yml +++ b/libcxx/utils/ci/buildkite-pipeline.yml @@ -207,10 +207,10 @@ steps: - group: ':freebsd: FreeBSD' steps: - label: FreeBSD 13 amd64 - command: libcxx/utils/ci/run-buildbot generic-cxx23 + command: libcxx/utils/ci/run-buildbot generic-cxx26 env: - CC: clang16 - CXX: clang++16 + CC: clang17 + CXX: clang++17 agents: queue: libcxx-builders os: freebsd diff --git a/libcxx/utils/ci/docker-compose.yml b/libcxx/utils/ci/docker-compose.yml index 5cefcb28bd860c444d7d82a443f0db3f3880a40f..af9a48481e8b67bf47d4a8e8fd32454b9a8bba64 100644 --- a/libcxx/utils/ci/docker-compose.yml +++ b/libcxx/utils/ci/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.7' x-versions: &compiler_versions GCC_LATEST_VERSION: 13 - LLVM_HEAD_VERSION: 18 + LLVM_HEAD_VERSION: 19 services: buildkite-builder: diff --git a/libcxx/utils/ci/oss-fuzz.sh b/libcxx/utils/ci/oss-fuzz.sh index d5e7fcea6012e34b529aa9d9725d1c5795f08abb..e5723406a9ff3bdca88fa346e64cf2c03fa7b995 100755 --- a/libcxx/utils/ci/oss-fuzz.sh +++ b/libcxx/utils/ci/oss-fuzz.sh @@ -14,7 +14,7 @@ MONOREPO_ROOT=${PWD} mkdir ${BUILD} cmake -S ${MONOREPO_ROOT}/runtimes -B ${BUILD} \ - -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ + -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind" \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DCMAKE_INSTALL_PREFIX="${INSTALL}" cmake --build ${BUILD} --target install-cxx-headers diff --git a/libcxx/utils/ci/run-buildbot-container b/libcxx/utils/ci/run-buildbot-container index 7c00b88097f17b80c55765d41c84911e6423f438..74e7dab81d734d02db77065aec80251a3b5851bc 100755 --- a/libcxx/utils/ci/run-buildbot-container +++ b/libcxx/utils/ci/run-buildbot-container @@ -26,6 +26,6 @@ if [[ ! -d "${MONOREPO_ROOT}/libcxx/utils/ci" ]]; then echo "Was unable to find the root of the LLVM monorepo; are you running from within the monorepo?" exit 1 fi -docker pull ghcr.io/libcxx/libcxx-builder -docker run -it --volume "${MONOREPO_ROOT}:/llvm" --workdir "/llvm" --cap-add=SYS_PTRACE ghcr.io/libcxx/libcxx-builder \ +docker pull ghcr.io/libcxx/actions-builder +docker run -it --volume "${MONOREPO_ROOT}:/llvm" --workdir "/llvm" --cap-add=SYS_PTRACE ghcr.io/libcxx/actions-builder \ bash -c 'git config --global --add safe.directory /llvm ; exec bash' diff --git a/libcxx/utils/generate_escaped_output_table.py b/libcxx/utils/generate_escaped_output_table.py index 5816435c96ca52704c8af1f4613441da2f02c93e..c6bde8f2411cf6ccc882b522ccc0183fcb4fd997 100755 --- a/libcxx/utils/generate_escaped_output_table.py +++ b/libcxx/utils/generate_escaped_output_table.py @@ -124,7 +124,7 @@ DATA_ARRAY_TEMPLATE = """ /// - bits [0, 10] The size of the range, allowing 2048 elements. /// - bits [11, 31] The lower bound code point of the range. The upper bound of /// the range is lower bound + size. -inline constexpr uint32_t __entries[{size}] = {{ +_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[{size}] = {{ {entries}}}; /// At the end of the valid Unicode code points space a lot of code points are diff --git a/libcxx/utils/generate_extended_grapheme_cluster_table.py b/libcxx/utils/generate_extended_grapheme_cluster_table.py index b0074b58cd2001c470605c6d03fe4239a731dfad..6a598399ce4705b1578aad1f3e8c223af4a698f0 100755 --- a/libcxx/utils/generate_extended_grapheme_cluster_table.py +++ b/libcxx/utils/generate_extended_grapheme_cluster_table.py @@ -113,7 +113,7 @@ DATA_ARRAY_TEMPLATE = """ /// following benchmark. /// libcxx/benchmarks/std_format_spec_string_unicode.bench.cpp // clang-format off -inline constexpr uint32_t __entries[{size}] = {{ +_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[{size}] = {{ {entries}}}; // clang-format on diff --git a/libcxx/utils/generate_width_estimation_table.py b/libcxx/utils/generate_width_estimation_table.py index 76b70f121eabd7e040be48e399a12df164bf0122..918dae25fe49e518ed79ea0c1a47b3361a041a1f 100644 --- a/libcxx/utils/generate_width_estimation_table.py +++ b/libcxx/utils/generate_width_estimation_table.py @@ -143,7 +143,7 @@ DATA_ARRAY_TEMPLATE = """ /// - bits [0, 13] The size of the range, allowing 16384 elements. /// - bits [14, 31] The lower bound code point of the range. The upper bound of /// the range is lower bound + size. -inline constexpr uint32_t __entries[{size}] = {{ +_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[{size}] = {{ {entries}}}; /// The upper bound entry of EastAsianWidth.txt. diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py index 872bff372b3dbaa093d1959de3e05134ef0204cb..0793c34fd7f0bfbc6ca78e4b329a6707c1a7b51b 100644 --- a/libcxx/utils/libcxx/test/features.py +++ b/libcxx/utils/libcxx/test/features.py @@ -280,6 +280,7 @@ DEFAULT_FEATURES = [ # This is not allowed per C11 7.1.2 Standard headers/6 # Any declaration of a library function shall have external linkage. when=lambda cfg: "__ANDROID__" in compilerMacros(cfg) + or "__FreeBSD__" in compilerMacros(cfg) or "_WIN32" in compilerMacros(cfg) or platform.system().lower().startswith("aix") # Avoid building on platforms that don't support modules properly. @@ -421,6 +422,56 @@ DEFAULT_FEATURES += [ """, ), ), + Feature( + name="can-create-symlinks", + when=lambda cfg: "_WIN32" not in compilerMacros(cfg) + or programSucceeds( + cfg, + # Creation of symlinks require elevated privileges on Windows unless + # Windows developer mode is enabled. + """ + #include <stdio.h> + #include <windows.h> + int main() { + CHAR tempDirPath[MAX_PATH]; + DWORD tempPathRet = GetTempPathA(MAX_PATH, tempDirPath); + if (tempPathRet == 0 || tempPathRet > MAX_PATH) { + return 1; + } + + CHAR tempFilePath[MAX_PATH]; + UINT uRetVal = GetTempFileNameA( + tempDirPath, + "cxx", // Prefix + 0, // Unique=0 also implies file creation. + tempFilePath); + if (uRetVal == 0) { + return 1; + } + + CHAR symlinkFilePath[MAX_PATH]; + int ret = sprintf_s(symlinkFilePath, MAX_PATH, "%s_symlink", tempFilePath); + if (ret == -1) { + DeleteFileA(tempFilePath); + return 1; + } + + // Requires either administrator, or developer mode enabled. + BOOL bCreatedSymlink = CreateSymbolicLinkA(symlinkFilePath, + tempFilePath, + SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE); + if (!bCreatedSymlink) { + DeleteFileA(tempFilePath); + return 1; + } + + DeleteFileA(tempFilePath); + DeleteFileA(symlinkFilePath); + return 0; + } + """, + ), + ), ] # Add features representing the build host platform name. diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py index 695e01115aa4ba51d94bc85bb42a44a5d06508fe..5e42562ed5db5238c071389e41bbdff5742cdda3 100644 --- a/libcxx/utils/libcxx/test/params.py +++ b/libcxx/utils/libcxx/test/params.py @@ -407,6 +407,6 @@ DEFAULT_PARAMETERS = [ AddFeature('has-clang-tidy'), AddSubstitution('%{clang-tidy}', exe), ] - ), + ), ] # fmt: on diff --git a/libcxxabi/src/CMakeLists.txt b/libcxxabi/src/CMakeLists.txt index 0af4dc1448e91a21bb101f18ff82d1b919f987a7..c8cc93de50777bc3957354bdee903b54489bc2bd 100644 --- a/libcxxabi/src/CMakeLists.txt +++ b/libcxxabi/src/CMakeLists.txt @@ -268,7 +268,10 @@ if(LIBCXXABI_HERMETIC_STATIC_LIBRARY) # then its code shouldn't declare them with hidden visibility. They might # actually be provided by a shared library at link time. if (LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS) - target_add_compile_flags_if_supported(cxxabi_static_objects PRIVATE -fvisibility-global-new-delete-hidden) + target_add_compile_flags_if_supported(cxxabi_static_objects PRIVATE -fvisibility-global-new-delete=force-hidden) + if (NOT CXX_SUPPORTS_FVISIBILITY_GLOBAL_NEW_DELETE_EQ_FORCE_HIDDEN_FLAG) + target_add_compile_flags_if_supported(cxxabi_static_objects PRIVATE -fvisibility-global-new-delete-hidden) + endif() endif() # _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS can be defined in libcxx's # __config_site too. Define it in the same way here, to avoid redefinition diff --git a/libcxxabi/test/forced_unwind4.pass.cpp b/libcxxabi/test/forced_unwind4.pass.cpp index 2864426ca16dcd85667f3f5208ec496e6e9c9080..15efca8d931629b2d7d3589a84499ca684cf608a 100644 --- a/libcxxabi/test/forced_unwind4.pass.cpp +++ b/libcxxabi/test/forced_unwind4.pass.cpp @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// -// REQUIRES: linux && target={{aarch64-.+}} +// REQUIRES: linux && target=aarch64-{{.+}}-gnu // pthread_cancel in case of glibc calls _Unwind_ForcedUnwind from a signal on -// the child_thread. This test ensures sigretrun is handled correctly (see: +// the child_thread. This test ensures sigreturn is handled correctly (see: // UnwindCursor<A, R>::setInfoForSigReturn). #include <cstdlib> // defines __BIONIC__ diff --git a/libunwind/src/CMakeLists.txt b/libunwind/src/CMakeLists.txt index 9c6f5d908b0945485b1f426801a8af232ac851a6..780430ba70ba60f468c17858c1fca8637c8610b8 100644 --- a/libunwind/src/CMakeLists.txt +++ b/libunwind/src/CMakeLists.txt @@ -201,7 +201,10 @@ set_target_properties(unwind_static_objects if(LIBUNWIND_HIDE_SYMBOLS) target_add_compile_flags_if_supported(unwind_static_objects PRIVATE -fvisibility=hidden) - target_add_compile_flags_if_supported(unwind_static_objects PRIVATE -fvisibility-global-new-delete-hidden) + target_add_compile_flags_if_supported(unwind_static_objects PRIVATE -fvisibility-global-new-delete=force-hidden) + if (NOT CXX_SUPPORTS_FVISIBILITY_GLOBAL_NEW_DELETE_EQ_FORCE_HIDDEN_FLAG) + target_add_compile_flags_if_supported(unwind_static_objects PRIVATE -fvisibility-global-new-delete-hidden) + endif() target_compile_definitions(unwind_static_objects PRIVATE _LIBUNWIND_HIDE_SYMBOLS) endif() diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h index 018f03b211e422da2cbacb4f1e8fa68770ae30c8..917f88fc28280b32a4db59a022e2cbe81bc236d5 100644 --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -54,6 +54,7 @@ enum class EmitKind { Obj, LLVM, ASM }; struct Export { StringRef name; // N in /export:N or /export:E=N StringRef extName; // E in /export:E=N + StringRef exportAs; // E in /export:N,EXPORTAS,E StringRef aliasTarget; // GNU specific: N in "alias == N" Symbol *sym = nullptr; uint16_t ordinal = 0; @@ -73,10 +74,9 @@ struct Export { StringRef exportName; // Name in DLL bool operator==(const Export &e) const { - return (name == e.name && extName == e.extName && - aliasTarget == e.aliasTarget && - ordinal == e.ordinal && noname == e.noname && - data == e.data && isPrivate == e.isPrivate); + return (name == e.name && extName == e.extName && exportAs == e.exportAs && + aliasTarget == e.aliasTarget && ordinal == e.ordinal && + noname == e.noname && data == e.data && isPrivate == e.isPrivate); } }; @@ -263,6 +263,9 @@ struct Configuration { // Used for /lto-pgo-warn-mismatch: bool ltoPGOWarnMismatch = true; + // Used for /lto-sample-profile: + llvm::StringRef ltoSampleProfileName; + // Used for /call-graph-ordering-file: llvm::MapVector<std::pair<const SectionChunk *, const SectionChunk *>, uint64_t> diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 22ee2f133be98a229e4567cea1897d3fdb281b11..2b1d4abb6ed0d6613c97c17ee328c027df26a357 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -945,6 +945,7 @@ void LinkerDriver::createImportLibrary(bool asLib) { e2.Name = std::string(e1.name); e2.SymbolName = std::string(e1.symbolName); e2.ExtName = std::string(e1.extName); + e2.ExportAs = std::string(e1.exportAs); e2.AliasTarget = std::string(e1.aliasTarget); e2.Ordinal = e1.ordinal; e2.Noname = e1.noname; @@ -1032,19 +1033,19 @@ void LinkerDriver::parseModuleDefs(StringRef path) { for (COFFShortExport e1 : m.Exports) { Export e2; - // In simple cases, only Name is set. Renamed exports are parsed - // and set as "ExtName = Name". If Name has the form "OtherDll.Func", - // it shouldn't be a normal exported function but a forward to another - // DLL instead. This is supported by both MS and GNU linkers. + // Renamed exports are parsed and set as "ExtName = Name". If Name has + // the form "OtherDll.Func", it shouldn't be a normal exported + // function but a forward to another DLL instead. This is supported + // by both MS and GNU linkers. if (!e1.ExtName.empty() && e1.ExtName != e1.Name && StringRef(e1.Name).contains('.')) { e2.name = saver().save(e1.ExtName); e2.forwardTo = saver().save(e1.Name); - ctx.config.exports.push_back(e2); - continue; + } else { + e2.name = saver().save(e1.Name); + e2.extName = saver().save(e1.ExtName); } - e2.name = saver().save(e1.Name); - e2.extName = saver().save(e1.ExtName); + e2.exportAs = saver().save(e1.ExportAs); e2.aliasTarget = saver().save(e1.AliasTarget); e2.ordinal = e1.Ordinal; e2.noname = e1.Noname; @@ -2028,6 +2029,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) { config->ltoObjPath = args.getLastArgValue(OPT_lto_obj_path); config->ltoCSProfileGenerate = args.hasArg(OPT_lto_cs_profile_generate); config->ltoCSProfileFile = args.getLastArgValue(OPT_lto_cs_profile_file); + config->ltoSampleProfileName = args.getLastArgValue(OPT_lto_sample_profile); // Handle miscellaneous boolean flags. config->ltoPGOWarnMismatch = args.hasFlag(OPT_lto_pgo_warn_mismatch, OPT_lto_pgo_warn_mismatch_no, true); diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index fc8eb327be49bdd9739d884f8ad5b3b5136a01fa..b4ff31a606da5e5b4f100ae39c93d9cff9b35cea 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -577,16 +577,16 @@ Export LinkerDriver::parseExport(StringRef arg) { if (y.contains(".")) { e.name = x; e.forwardTo = y; - return e; + } else { + e.extName = x; + e.name = y; + if (e.name.empty()) + goto err; } - - e.extName = x; - e.name = y; - if (e.name.empty()) - goto err; } - // If "<name>=<internalname>[,@ordinal[,NONAME]][,DATA][,PRIVATE]" + // Optional parameters + // "[,@ordinal[,NONAME]][,DATA][,PRIVATE][,EXPORTAS,exportname]" while (!rest.empty()) { StringRef tok; std::tie(tok, rest) = rest.split(","); @@ -608,6 +608,13 @@ Export LinkerDriver::parseExport(StringRef arg) { e.isPrivate = true; continue; } + if (tok.equals_insensitive("exportas")) { + if (!rest.empty() && !rest.contains(',')) + e.exportAs = rest; + else + error("invalid EXPORTAS value: " + rest); + break; + } if (tok.starts_with("@")) { int32_t ord; if (tok.substr(1).getAsInteger(0, ord)) @@ -684,7 +691,9 @@ void LinkerDriver::fixupExports() { } for (Export &e : ctx.config.exports) { - if (!e.forwardTo.empty()) { + if (!e.exportAs.empty()) { + e.exportName = e.exportAs; + } else if (!e.forwardTo.empty()) { e.exportName = undecorate(ctx, e.name); } else { e.exportName = undecorate(ctx, e.extName.empty() ? e.name : e.extName); diff --git a/lld/COFF/LTO.cpp b/lld/COFF/LTO.cpp index 7df9319112136722aefde8e735502ee232dd8287..be49aa6e8bb3da440f710adee3bd0a786eea2d02 100644 --- a/lld/COFF/LTO.cpp +++ b/lld/COFF/LTO.cpp @@ -86,6 +86,7 @@ lto::Config BitcodeCompiler::createConfig() { c.CSIRProfile = std::string(ctx.config.ltoCSProfileFile); c.RunCSIRInstr = ctx.config.ltoCSProfileGenerate; c.PGOWarnMismatch = ctx.config.ltoPGOWarnMismatch; + c.SampleProfile = ctx.config.ltoSampleProfileName; c.TimeTraceEnabled = ctx.config.timeTraceEnabled; c.TimeTraceGranularity = ctx.config.timeTraceGranularity; diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td index 4dab4a20717392fb4c20beffdaeb5df685abdd0e..1e78a560bca86482a32f6061e9a63b88ce0623aa 100644 --- a/lld/COFF/Options.td +++ b/lld/COFF/Options.td @@ -79,6 +79,7 @@ def lldltocachepolicy : P<"lldltocachepolicy", "Pruning policy for the ThinLTO cache">; def lldsavetemps : F<"lldsavetemps">, HelpText<"Save intermediate LTO compilation results">; +def lto_sample_profile: P<"lto-sample-profile", "Sample profile file path">; def machine : P<"machine", "Specify target platform">; def merge : P<"merge", "Combine sections">; def mllvm : P<"mllvm", "Options to pass to LLVM">; diff --git a/lld/ELF/Arch/Mips.cpp b/lld/ELF/Arch/Mips.cpp index b02ad10649d901de7b1eb0e576506e7832645c3e..e36e9d59a7401cc2c40952fda61e5f9456b298b2 100644 --- a/lld/ELF/Arch/Mips.cpp +++ b/lld/ELF/Arch/Mips.cpp @@ -380,7 +380,7 @@ bool MIPS<ELFT>::needsThunk(RelExpr expr, RelType type, const InputFile *file, template <class ELFT> int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *buf, RelType type) const { - const endianness e = ELFT::TargetEndianness; + const endianness e = ELFT::Endianness; switch (type) { case R_MIPS_32: case R_MIPS_REL32: @@ -521,7 +521,7 @@ static uint64_t fixupCrossModeJump(uint8_t *loc, RelType type, uint64_t val) { // to a microMIPS target and vice versa. In that cases jump // instructions need to be replaced by their "cross-mode" // equivalents. - const endianness e = ELFT::TargetEndianness; + const endianness e = ELFT::Endianness; bool isMicroTgt = val & 0x1; bool isCrossJump = (isMicroTgt && isBranchReloc(type)) || (!isMicroTgt && isMicroBranchReloc(type)); @@ -567,7 +567,7 @@ static uint64_t fixupCrossModeJump(uint8_t *loc, RelType type, uint64_t val) { template <class ELFT> void MIPS<ELFT>::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { - const endianness e = ELFT::TargetEndianness; + const endianness e = ELFT::Endianness; RelType type = rel.type; if (ELFT::Is64Bits || config->mipsN32Abi) diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index 657332deebfde13af96f90bfc2850f3a9385b834..3188772f7c490423b314216741923581fe23a73c 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -286,7 +286,7 @@ static void writeSequence(MutableArrayRef<uint32_t> buf, const char *prefix, // The full section content has the extent of [begin, end). We drop unused // instructions and write [first,end). auto *sec = make<InputSection>( - nullptr, SHF_ALLOC, SHT_PROGBITS, 4, + ctx.internalFile, SHF_ALLOC, SHT_PROGBITS, 4, ArrayRef(reinterpret_cast<uint8_t *>(buf.data() + first), 4 * (buf.size() - first)), ".text"); diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp index de459013595fed86e25608c91f151a772faef250..a85bf3aa0c09d11ed39a0eb351321c8f839dd587 100644 --- a/lld/ELF/Arch/X86_64.cpp +++ b/lld/ELF/Arch/X86_64.cpp @@ -328,9 +328,10 @@ bool X86_64::relaxOnce(int pass) const { if (rel.expr != R_RELAX_GOT_PC) continue; - uint64_t v = sec->getRelocTargetVA( - sec->file, rel.type, rel.addend, - sec->getOutputSection()->addr + rel.offset, *rel.sym, rel.expr); + uint64_t v = sec->getRelocTargetVA(sec->file, rel.type, rel.addend, + sec->getOutputSection()->addr + + sec->outSecOff + rel.offset, + *rel.sym, rel.expr); if (isInt<32>(v)) continue; if (rel.sym->auxIdx == 0) { diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 9ae01eb90fa4a38e303499b56a403008850311c8..27274d69b7f1f70e49270df505524a9fa3c56083 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -126,7 +126,7 @@ public: private: void createFiles(llvm::opt::InputArgList &args); void inferMachineType(); - void link(llvm::opt::InputArgList &args); + template <class ELFT> void link(llvm::opt::InputArgList &args); template <class ELFT> void compileBitcodeFiles(bool skipLinkedOutput); bool tryAddFatLTOFile(MemoryBufferRef mb, StringRef archiveName, uint64_t offsetInArchive, bool lazy); @@ -138,7 +138,7 @@ private: std::unique_ptr<BitcodeCompiler> lto; std::vector<InputFile *> files; - std::optional<InputFile *> armCmseImpLib; + InputFile *armCmseImpLib = nullptr; public: SmallVector<std::pair<StringRef, unsigned>, 0> archiveFiles; @@ -273,6 +273,7 @@ struct Config { bool printGcSections; bool printIcfSections; bool printMemoryUsage; + bool rejectMismatch; bool relax; bool relaxGP; bool relocatable; diff --git a/lld/ELF/DWARF.h b/lld/ELF/DWARF.h index 1b9a3e3f77943b19c94cd84b19801a9772814c46..d56895277bcc915a7bcff750e6cadbcc05ac1e90 100644 --- a/lld/ELF/DWARF.h +++ b/lld/ELF/DWARF.h @@ -74,7 +74,7 @@ public: StringRef getLineStrSection() const override { return lineStrSection; } bool isLittleEndian() const override { - return ELFT::TargetEndianness == llvm::endianness::little; + return ELFT::Endianness == llvm::endianness::little; } std::optional<llvm::RelocAddrEntry> find(const llvm::DWARFSection &sec, diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 2439d141fb664347576e055ccdda7454f88c7d17..b43da7727e22aeb1f943a451149a5913ea26767c 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -650,7 +650,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) { if (errorCount()) return; - link(args); + invokeELFT(link, args); } if (config->timeTraceEnabled) { @@ -1348,6 +1348,7 @@ static void readConfigs(opt::InputArgList &args) { config->printArchiveStats = args.getLastArgValue(OPT_print_archive_stats); config->printSymbolOrder = args.getLastArgValue(OPT_print_symbol_order); + config->rejectMismatch = !args.hasArg(OPT_no_warn_mismatch); config->relax = args.hasFlag(OPT_relax, OPT_no_relax, true); config->relaxGP = args.hasFlag(OPT_relax_gp, OPT_no_relax_gp, false); config->rpath = getRpath(args); @@ -1799,6 +1800,37 @@ static void setConfigs(opt::InputArgList &args) { args.hasFlag(OPT_toc_optimize, OPT_no_toc_optimize, m == EM_PPC64); config->pcRelOptimize = args.hasFlag(OPT_pcrel_optimize, OPT_no_pcrel_optimize, m == EM_PPC64); + + if (!args.hasArg(OPT_hash_style)) { + if (config->emachine == EM_MIPS) + config->sysvHash = true; + else + config->sysvHash = config->gnuHash = true; + } + + // Set default entry point and output file if not specified by command line or + // linker scripts. + config->warnMissingEntry = + (!config->entry.empty() || (!config->shared && !config->relocatable)); + if (config->entry.empty() && !config->relocatable) + config->entry = config->emachine == EM_MIPS ? "__start" : "_start"; + if (config->outputFile.empty()) + config->outputFile = "a.out"; + + // Fail early if the output file or map file is not writable. If a user has a + // long link, e.g. due to a large LTO link, they do not wish to run it and + // find that it failed because there was a mistake in their command-line. + { + llvm::TimeTraceScope timeScope("Create output files"); + if (auto e = tryCreateFile(config->outputFile)) + error("cannot open output file " + config->outputFile + ": " + + e.message()); + if (auto e = tryCreateFile(config->mapFile)) + error("cannot open map file " + config->mapFile + ": " + e.message()); + if (auto e = tryCreateFile(config->whyExtract)) + error("cannot open --why-extract= file " + config->whyExtract + ": " + + e.message()); + } } static bool isFormatBinary(StringRef s) { @@ -2082,8 +2114,11 @@ static void handleUndefinedGlob(StringRef arg) { static void handleLibcall(StringRef name) { Symbol *sym = symtab.find(name); - if (sym && sym->isLazy() && isa<BitcodeFile>(sym->file)) + if (sym && sym->isLazy() && isa<BitcodeFile>(sym->file)) { + if (!config->whyExtract.empty()) + ctx.whyExtractRecords.emplace_back("<libcall>", sym->file, *sym); sym->extract(); + } } static void writeArchiveStats() { @@ -2361,12 +2396,6 @@ static void readSymbolPartitionSection(InputSectionBase *s) { sym->partition = newPart.getNumber(); } -static Symbol *addUnusedUndefined(StringRef name, - uint8_t binding = STB_GLOBAL) { - return symtab.addSymbol( - Undefined{ctx.internalFile, name, binding, STV_DEFAULT, 0}); -} - static void markBuffersAsDontNeed(bool skipLinkedOutput) { // With --thinlto-index-only, all buffers are nearly unused from now on // (except symbol/section names used by infrequent passes). Mark input file @@ -2453,15 +2482,15 @@ static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) { continue; Symbol *wrap = - addUnusedUndefined(saver().save("__wrap_" + name), sym->binding); + symtab.addUnusedUndefined(saver().save("__wrap_" + name), sym->binding); // If __real_ is referenced, pull in the symbol if it is lazy. Do this after // processing __wrap_ as that may have referenced __real_. StringRef realName = saver().save("__real_" + name); if (symtab.find(realName)) - addUnusedUndefined(name, sym->binding); + symtab.addUnusedUndefined(name, sym->binding); - Symbol *real = addUnusedUndefined(realName); + Symbol *real = symtab.addUnusedUndefined(realName); v.push_back({sym, real, wrap}); // We want to tell LTO not to inline symbols to be overwritten @@ -2679,45 +2708,8 @@ static void postParseObjectFile(ELFFileBase *file) { // Do actual linking. Note that when this function is called, // all linker scripts have already been parsed. -void LinkerDriver::link(opt::InputArgList &args) { +template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) { llvm::TimeTraceScope timeScope("Link", StringRef("LinkerDriver::Link")); - // If a --hash-style option was not given, set to a default value, - // which varies depending on the target. - if (!args.hasArg(OPT_hash_style)) { - if (config->emachine == EM_MIPS) - config->sysvHash = true; - else - config->sysvHash = config->gnuHash = true; - } - - // Default output filename is "a.out" by the Unix tradition. - if (config->outputFile.empty()) - config->outputFile = "a.out"; - - // Fail early if the output file or map file is not writable. If a user has a - // long link, e.g. due to a large LTO link, they do not wish to run it and - // find that it failed because there was a mistake in their command-line. - { - llvm::TimeTraceScope timeScope("Create output files"); - if (auto e = tryCreateFile(config->outputFile)) - error("cannot open output file " + config->outputFile + ": " + - e.message()); - if (auto e = tryCreateFile(config->mapFile)) - error("cannot open map file " + config->mapFile + ": " + e.message()); - if (auto e = tryCreateFile(config->whyExtract)) - error("cannot open --why-extract= file " + config->whyExtract + ": " + - e.message()); - } - if (errorCount()) - return; - - // Use default entry point name if no name was given via the command - // line nor linker scripts. For some reason, MIPS entry point name is - // different from others. - config->warnMissingEntry = - (!config->entry.empty() || (!config->shared && !config->relocatable)); - if (config->entry.empty() && !config->relocatable) - config->entry = (config->emachine == EM_MIPS) ? "__start" : "_start"; // Handle --trace-symbol. for (auto *arg : args.filtered(OPT_trace_symbol)) @@ -2728,38 +2720,14 @@ void LinkerDriver::link(opt::InputArgList &args) { // Handle -u/--undefined before input files. If both a.a and b.so define foo, // -u foo a.a b.so will extract a.a. for (StringRef name : config->undefined) - addUnusedUndefined(name)->referenced = true; + symtab.addUnusedUndefined(name)->referenced = true; - // Add all files to the symbol table. This will add almost all - // symbols that we need to the symbol table. This process might - // add files to the link, via autolinking, these files are always - // appended to the Files vector. - { - llvm::TimeTraceScope timeScope("Parse input files"); - for (size_t i = 0; i < files.size(); ++i) { - llvm::TimeTraceScope timeScope("Parse input files", files[i]->getName()); - parseFile(files[i]); - } - if (armCmseImpLib) - parseArmCMSEImportLib(*armCmseImpLib); - } - - // Now that we have every file, we can decide if we will need a - // dynamic symbol table. - // We need one if we were asked to export dynamic symbols or if we are - // producing a shared library. - // We also need one if any shared libraries are used and for pie executables - // (probably because the dynamic linker needs it). - config->hasDynSymTab = - !ctx.sharedFiles.empty() || config->isPic || config->exportDynamic; - - // Some symbols (such as __ehdr_start) are defined lazily only when there - // are undefined symbols for them, so we add these to trigger that logic. - for (StringRef name : script->referencedSymbols) { - Symbol *sym = addUnusedUndefined(name); - sym->isUsedInRegularObj = true; - sym->referenced = true; - } + parseFiles(files, armCmseImpLib); + + // Create dynamic sections for dynamic linking and static PIE. + config->hasDynSymTab = !ctx.sharedFiles.empty() || config->isPic; + + script->addScriptReferencedSymbolsToSymTable(); // Prevent LTO from removing any definition referenced by -u. for (StringRef name : config->undefined) @@ -2872,7 +2840,7 @@ void LinkerDriver::link(opt::InputArgList &args) { // Handle --lto-validate-all-vtables-have-type-infos. if (config->ltoValidateAllVtablesHaveTypeInfos) - invokeELFT(ltoValidateAllVtablesHaveTypeInfos, args); + ltoValidateAllVtablesHaveTypeInfos<ELFT>(args); // Do link-time optimization if given files are LLVM bitcode files. // This compiles bitcode files into real object files. @@ -2880,7 +2848,7 @@ void LinkerDriver::link(opt::InputArgList &args) { // With this the symbol table should be complete. After this, no new names // except a few linker-synthesized ones will be added to the symbol table. const size_t numObjsBeforeLTO = ctx.objectFiles.size(); - invokeELFT(compileBitcodeFiles, skipLinkedOutput); + compileBitcodeFiles<ELFT>(skipLinkedOutput); // Symbol resolution finished. Report backward reference problems, // --print-archive-stats=, and --why-extract=. @@ -2945,7 +2913,7 @@ void LinkerDriver::link(opt::InputArgList &args) { llvm::erase_if(ctx.inputSections, [](InputSectionBase *s) { if (s->type != SHT_LLVM_SYMPART) return false; - invokeELFT(readSymbolPartitionSection, s); + readSymbolPartitionSection<ELFT>(s); return true; }); } @@ -3003,10 +2971,10 @@ void LinkerDriver::link(opt::InputArgList &args) { ctx.inputSections.push_back(createCommentSection()); // Split SHF_MERGE and .eh_frame sections into pieces in preparation for garbage collection. - invokeELFT(splitSections,); + splitSections<ELFT>(); // Garbage collection and removal of shared symbols from unused shared objects. - invokeELFT(markLive,); + markLive<ELFT>(); // Make copies of any input sections that need to be copied into each // partition. @@ -3019,7 +2987,7 @@ void LinkerDriver::link(opt::InputArgList &args) { // Create synthesized sections such as .got and .plt. This is called before // processSectionCommands() so that they can be placed by SECTIONS commands. - invokeELFT(createSyntheticSections,); + createSyntheticSections<ELFT>(); // Some input sections that are used for exception handling need to be moved // into synthetic sections. Do that now so that they aren't assigned to @@ -3059,8 +3027,8 @@ void LinkerDriver::link(opt::InputArgList &args) { // Two input sections with different output sections should not be folded. // ICF runs after processSectionCommands() so that we know the output sections. if (config->icf != ICFLevel::None) { - invokeELFT(findKeepUniqueSections, args); - invokeELFT(doIcf,); + findKeepUniqueSections<ELFT>(args); + doIcf<ELFT>(); } // Read the callgraph now that we know what was gced or icfed @@ -3068,9 +3036,9 @@ void LinkerDriver::link(opt::InputArgList &args) { if (auto *arg = args.getLastArg(OPT_call_graph_ordering_file)) if (std::optional<MemoryBufferRef> buffer = readFile(arg->getValue())) readCallGraph(*buffer); - invokeELFT(readCallGraphsFromObjectFiles,); + readCallGraphsFromObjectFiles<ELFT>(); } // Write the result to the file. - invokeELFT(writeResult,); + writeResult<ELFT>(); } diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 00aebb47640e847cfb34f16281342ce7f30f6479..6529ea072fae2627b421e7990c2dac00a787f5e8 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -330,12 +330,24 @@ extern template void ObjFile<ELF32BE>::importCmseSymbols(); extern template void ObjFile<ELF64LE>::importCmseSymbols(); extern template void ObjFile<ELF64BE>::importCmseSymbols(); -template <class ELFT> static void doParseArmCMSEImportLib(InputFile *file) { - cast<ObjFile<ELFT>>(file)->importCmseSymbols(); +template <class ELFT> +static void doParseFiles(const std::vector<InputFile *> &files, + InputFile *armCmseImpLib) { + // Add all files to the symbol table. This will add almost all symbols that we + // need to the symbol table. This process might add files to the link due to + // addDependentLibrary. + for (size_t i = 0; i < files.size(); ++i) { + llvm::TimeTraceScope timeScope("Parse input files", files[i]->getName()); + doParseFile<ELFT>(files[i]); + } + if (armCmseImpLib) + cast<ObjFile<ELFT>>(*armCmseImpLib).importCmseSymbols(); } -void elf::parseArmCMSEImportLib(InputFile *file) { - invokeELFT(doParseArmCMSEImportLib, file); +void elf::parseFiles(const std::vector<InputFile *> &files, + InputFile *armCmseImpLib) { + llvm::TimeTraceScope timeScope("Parse input files"); + invokeELFT(doParseFiles, files, armCmseImpLib); } // Concatenates arguments to construct a string representing an error location. @@ -741,6 +753,15 @@ template <class ELFT> void ObjFile<ELFT>::initializeJustSymbols() { sections.resize(numELFShdrs); } +static bool isKnownSpecificSectionType(uint32_t t, uint32_t flags) { + if (SHT_LOUSER <= t && t <= SHT_HIUSER && !(flags & SHF_ALLOC)) + return true; + if (SHT_LOOS <= t && t <= SHT_HIOS && !(flags & SHF_OS_NONCONFORMING)) + return true; + // Allow all processor-specific types. This is different from GNU ld. + return SHT_LOPROC <= t && t <= SHT_HIPROC; +} + template <class ELFT> void ObjFile<ELFT>::initializeSections(bool ignoreComdats, const llvm::object::ELFFile<ELFT> &obj) { @@ -752,14 +773,15 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats, if (this->sections[i] == &InputSection::discarded) continue; const Elf_Shdr &sec = objSections[i]; + const uint32_t type = sec.sh_type; // SHF_EXCLUDE'ed sections are discarded by the linker. However, // if -r is given, we'll let the final link discard such sections. // This is compatible with GNU. if ((sec.sh_flags & SHF_EXCLUDE) && !config->relocatable) { - if (sec.sh_type == SHT_LLVM_CALL_GRAPH_PROFILE) + if (type == SHT_LLVM_CALL_GRAPH_PROFILE) cgProfileSectionIndex = i; - if (sec.sh_type == SHT_LLVM_ADDRSIG) { + if (type == SHT_LLVM_ADDRSIG) { // We ignore the address-significance table if we know that the object // file was created by objcopy or ld -r. This is because these tools // will reorder the symbols in the symbol table, invalidating the data @@ -778,7 +800,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats, continue; } - switch (sec.sh_type) { + switch (type) { case SHT_GROUP: { if (!config->relocatable) sections[i] = &InputSection::discarded; @@ -801,18 +823,31 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats, case SHT_RELA: case SHT_NULL: break; - case SHT_LLVM_SYMPART: - ctx.hasSympart.store(true, std::memory_order_relaxed); - [[fallthrough]]; + case SHT_PROGBITS: + case SHT_NOTE: + case SHT_NOBITS: + case SHT_INIT_ARRAY: + case SHT_FINI_ARRAY: + case SHT_PREINIT_ARRAY: + this->sections[i] = + createInputSection(i, sec, check(obj.getSectionName(sec, shstrtab))); + break; default: this->sections[i] = createInputSection(i, sec, check(obj.getSectionName(sec, shstrtab))); + if (type == SHT_LLVM_SYMPART) + ctx.hasSympart.store(true, std::memory_order_relaxed); + else if (config->rejectMismatch && + !isKnownSpecificSectionType(type, sec.sh_flags)) + errorOrWarn(toString(this->sections[i]) + ": unknown section type 0x" + + Twine::utohexstr(type)); + break; } } // We have a second loop. It is used to: // 1) handle SHF_LINK_ORDER sections. - // 2) create SHT_REL[A] sections. In some cases the section header index of a + // 2) create relocation sections. In some cases the section header index of a // relocation section may be smaller than that of the relocated section. In // such cases, the relocation section would attempt to reference a target // section that has not yet been created. For simplicity, delay creation of @@ -822,7 +857,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats, continue; const Elf_Shdr &sec = objSections[i]; - if (sec.sh_type == SHT_REL || sec.sh_type == SHT_RELA) { + if (isStaticRelSecType(sec.sh_type)) { // Find a relocation target section and associate this section with that. // Target may have been discarded if it is in a different section group // and the group is discarded, even though it's a violation of the spec. @@ -936,8 +971,8 @@ template <class ELFT> static uint32_t readAndFeatures(const InputSection &sec) { const uint8_t *place = desc.data(); if (desc.size() < 8) reportFatal(place, "program property is too short"); - uint32_t type = read32<ELFT::TargetEndianness>(desc.data()); - uint32_t size = read32<ELFT::TargetEndianness>(desc.data() + 4); + uint32_t type = read32<ELFT::Endianness>(desc.data()); + uint32_t size = read32<ELFT::Endianness>(desc.data() + 4); desc = desc.slice(8); if (desc.size() < size) reportFatal(place, "program property is too short"); @@ -948,7 +983,7 @@ template <class ELFT> static uint32_t readAndFeatures(const InputSection &sec) { // accumulate the bits set. if (size < 4) reportFatal(place, "FEATURE_1_AND entry is too short"); - featuresSet |= read32<ELFT::TargetEndianness>(desc.data()); + featuresSet |= read32<ELFT::Endianness>(desc.data()); } // Padding is present in the note descriptor, if necessary. @@ -1522,7 +1557,7 @@ template <class ELFT> void SharedFile::parse() { Symbol *s = symtab.addSymbol( Undefined{this, name, sym.getBinding(), sym.st_other, sym.getType()}); s->exportDynamic = true; - if (s->isUndefined() && sym.getBinding() != STB_WEAK && + if (sym.getBinding() != STB_WEAK && config->unresolvedSymbolsInShlib != UnresolvedPolicy::Ignore) requiredSymbols.push_back(s); continue; diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 54de842a81cf35858856ad37c7b323261cf3effd..95197599a2e10d7a7a00b8ca44788a8d809d8362 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -47,8 +47,8 @@ std::optional<MemoryBufferRef> readFile(StringRef path); // Add symbols in File to the symbol table. void parseFile(InputFile *file); - -void parseArmCMSEImportLib(InputFile *file); +void parseFiles(const std::vector<InputFile *> &files, + InputFile *armCmseImpLib); // The root class of input files. class InputFile { diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 7508a1336c91a44879b889c8d604f59f2b97cd1d..4f88313b868b24c6d264718f3502432102627fa7 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -316,7 +316,9 @@ InputSection::InputSection(InputFile *f, uint64_t flags, uint32_t type, StringRef name, Kind k) : InputSectionBase(f, flags, type, /*Entsize*/ 0, /*Link*/ 0, /*Info*/ 0, addralign, data, - name, k) {} + name, k) { + assert(f || this == &InputSection::discarded); +} template <class ELFT> InputSection::InputSection(ObjFile<ELFT> &f, const typename ELFT::Shdr &header, @@ -346,7 +348,7 @@ template <class ELFT> void InputSection::copyShtGroup(uint8_t *buf) { } InputSectionBase *InputSection::getRelocatedSection() const { - if (!file || file->isInternal() || (type != SHT_RELA && type != SHT_REL)) + if (file->isInternal() || !isStaticRelSecType(type)) return nullptr; ArrayRef<InputSectionBase *> sections = file->getSections(); return sections[info]; @@ -408,7 +410,7 @@ void InputSection::copyRelocations(uint8_t *buf, // Output section VA is zero for -r, so r_offset is an offset within the // section, but for --emit-relocs it is a virtual address. p->r_offset = sec->getVA(rel.offset); - p->setSymbolAndType(in.symTab->getSymbolIndex(&sym), type, + p->setSymbolAndType(in.symTab->getSymbolIndex(sym), type, config->isMips64EL); if (sym.type == STT_SECTION) { @@ -1256,10 +1258,10 @@ void EhInputSection::split(ArrayRef<RelTy> rels) { msg = "CIE/FDE too small"; break; } - uint64_t size = endian::read32<ELFT::TargetEndianness>(d.data()); + uint64_t size = endian::read32<ELFT::Endianness>(d.data()); if (size == 0) // ZERO terminator break; - uint32_t id = endian::read32<ELFT::TargetEndianness>(d.data() + 4); + uint32_t id = endian::read32<ELFT::Endianness>(d.data() + 4); size += 4; if (LLVM_UNLIKELY(size > d.size())) { // If it is 0xFFFFFFFF, the next 8 bytes contain the size instead, diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index b8af962877b4e92e71503691b1db57f3373729ba..1fb7077ca435bdca43faf64157c0c58a08d96fcb 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -448,6 +448,10 @@ public: } }; +inline bool isStaticRelSecType(uint32_t type) { + return type == llvm::ELF::SHT_RELA || type == llvm::ELF::SHT_REL; +} + inline bool isDebugSection(const InputSectionBase &sec) { return (sec.flags & llvm::ELF::SHF_ALLOC) == 0 && sec.name.starts_with(".debug"); diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 9e7647f63ca5ae91ba301be7b19895f5a62bd6be..f815b3ac6feeda00a86dd80ae42711e2d406a98a 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -198,15 +198,7 @@ static bool shouldDefineSym(SymbolAssignment *cmd) { if (cmd->name == ".") return false; - if (!cmd->provide) - return true; - - // If a symbol was in PROVIDE(), we need to define it only - // when it is a referenced undefined symbol. - Symbol *b = symtab.find(cmd->name); - if (b && !b->isDefined() && !b->isCommon()) - return true; - return false; + return !cmd->provide || LinkerScript::shouldAddProvideSym(cmd->name); } // Called by processSymbolAssignments() to assign definitions to @@ -740,13 +732,12 @@ static OutputDesc *addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map, // should combine these relocation sections into single output. // We skip synthetic sections because it can be .rela.dyn/.rela.plt or any // other REL[A] sections created by linker itself. - if (!isa<SyntheticSection>(isec) && - (isec->type == SHT_REL || isec->type == SHT_RELA)) { + if (!isa<SyntheticSection>(isec) && isStaticRelSecType(isec->type)) { auto *sec = cast<InputSection>(isec); OutputSection *out = sec->getRelocatedSection()->getOutputSection(); - if (out->relocationSection) { - out->relocationSection->recordSection(sec); + if (auto *relSec = out->relocationSection) { + relSec->recordSection(sec); return nullptr; } @@ -1518,3 +1509,41 @@ void LinkerScript::checkFinalScriptConditions() const { checkMemoryRegion(lmaRegion, sec, sec->getLMA()); } } + +void LinkerScript::addScriptReferencedSymbolsToSymTable() { + // Some symbols (such as __ehdr_start) are defined lazily only when there + // are undefined symbols for them, so we add these to trigger that logic. + auto reference = [](StringRef name) { + Symbol *sym = symtab.addUnusedUndefined(name); + sym->isUsedInRegularObj = true; + sym->referenced = true; + }; + for (StringRef name : referencedSymbols) + reference(name); + + // Keeps track of references from which PROVIDE symbols have been added to the + // symbol table. + DenseSet<StringRef> added; + SmallVector<const SmallVector<StringRef, 0> *, 0> symRefsVec; + for (const auto &[name, symRefs] : provideMap) + if (LinkerScript::shouldAddProvideSym(name) && added.insert(name).second) + symRefsVec.push_back(&symRefs); + while (symRefsVec.size()) { + for (StringRef name : *symRefsVec.pop_back_val()) { + reference(name); + // Prevent the symbol from being discarded by --gc-sections. + script->referencedSymbols.push_back(name); + auto it = script->provideMap.find(name); + if (it != script->provideMap.end() && + LinkerScript::shouldAddProvideSym(name) && + added.insert(name).second) { + symRefsVec.push_back(&it->second); + } + } + } +} + +bool LinkerScript::shouldAddProvideSym(StringRef symName) { + Symbol *sym = symtab.find(symName); + return sym && !sym->isDefined() && !sym->isCommon(); +} diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 18eaf58b785e370eaa9654952507f4daebc10372..fa7c6eb9c0d8f79f3042b5bda286d22625255b3a 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -16,6 +16,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include <cstddef> @@ -348,6 +349,18 @@ public: // Check backward location counter assignment and memory region/LMA overflows. void checkFinalScriptConditions() const; + // Add symbols that are referenced in the linker script to the symbol table. + // Symbols referenced in a PROVIDE command are only added to the symbol table + // if the PROVIDE command actually provides the symbol. + // It also adds the symbols referenced by the used PROVIDE symbols to the + // linker script referenced symbols list. + void addScriptReferencedSymbolsToSymTable(); + + // Returns true if the PROVIDE symbol should be added to the link. + // A PROVIDE symbol is added to the link only if it satisfies an + // undefined reference. + static bool shouldAddProvideSym(StringRef symName); + // SECTIONS command list. SmallVector<SectionCommand *, 0> sectionCommands; @@ -379,6 +392,14 @@ public: // Sections that will be warned/errored by --orphan-handling. SmallVector<const InputSectionBase *, 0> orphanSections; + + // Stores the mapping: PROVIDE symbol -> symbols referred in the PROVIDE + // expression. For example, if the PROVIDE command is: + // + // PROVIDE(v = a + b + c); + // + // then provideMap should contain the mapping: 'v' -> ['a', 'b', 'c'] + llvm::MapVector<StringRef, SmallVector<StringRef, 0>> provideMap; }; LLVM_LIBRARY_VISIBILITY extern std::unique_ptr<LinkerScript> script; diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp index 93c66e81d2fa91f828d6ee2b88161d012c9d056f..45431e44a6c8cc706dcc1776bcf50dd2adf526d0 100644 --- a/lld/ELF/MarkLive.cpp +++ b/lld/ELF/MarkLive.cpp @@ -276,8 +276,7 @@ template <class ELFT> void MarkLive<ELFT>::run() { // collection. // - Groups members are retained or discarded as a unit. if (!(sec->flags & SHF_ALLOC)) { - bool isRel = sec->type == SHT_REL || sec->type == SHT_RELA; - if (!isRel && !sec->nextInSectionGroup) { + if (!isStaticRelSecType(sec->type) && !sec->nextInSectionGroup) { sec->markLive(); for (InputSection *isec : sec->dependentSections) isec->markLive(); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index 3819b86238ea6425bba42abd497708d0c5fdfa92..c5e95d0d25c1aeb5388ca6d691c9b8fc1fcb785e 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -312,6 +312,9 @@ def no_dynamic_linker: F<"no-dynamic-linker">, def noinhibit_exec: F<"noinhibit-exec">, HelpText<"Retain the executable output file whenever it is still usable">; +def no_warn_mismatch: F<"no-warn-mismatch">, + HelpText<"Suppress errors for certain unknown seciton types">; + def no_nmagic: F<"no-nmagic">, MetaVarName<"<magic>">, HelpText<"Page align sections (default)">; @@ -753,7 +756,6 @@ def: FF<"no-add-needed">; def: F<"no-copy-dt-needed-entries">; def: F<"no-ctors-in-init-array">; def: F<"no-keep-memory">; -def: F<"no-warn-mismatch">; def: Separate<["--", "-"], "rpath-link">; def: J<"rpath-link=">; def: F<"secure-plt">; diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 55e6a14f103e025bdbc708c28a546d5f3c64b997..eadab9d745d6870a9e9c7a4141b17d9654ea35ef 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -583,7 +583,7 @@ static void finalizeShtGroup(OutputSection *os, InputSection *section) { // sh_info then contain index of an entry in symbol table section which // provides signature of the section group. ArrayRef<Symbol *> symbols = section->file->getSymbols(); - os->info = in.symTab->getSymbolIndex(symbols[section->info]); + os->info = in.symTab->getSymbolIndex(*symbols[section->info]); // Some group members may be combined or discarded, so we need to compute the // new size. The content will be rewritten in InputSection::copyShtGroup. @@ -615,7 +615,7 @@ void OutputSection::finalize() { return; } - if (!config->copyRelocs || (type != SHT_RELA && type != SHT_REL)) + if (!config->copyRelocs || !isStaticRelSecType(type)) return; // Skip if 'first' is synthetic, i.e. not a section created by --emit-relocs. @@ -750,7 +750,7 @@ std::array<uint8_t, 4> OutputSection::getFiller() { void OutputSection::checkDynRelAddends(const uint8_t *bufStart) { assert(config->writeAddends && config->checkDynamicRelocs); - assert(type == SHT_REL || type == SHT_RELA); + assert(isStaticRelSecType(type)); SmallVector<InputSection *, 0> storage; ArrayRef<InputSection *> sections = getInputSections(*this, storage); parallelFor(0, sections.size(), [&](size_t i) { diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 619fbaf5dc5452f3eb615b3178c45828289faa1e..92f2e200db1107596ea783ffff9a6676ce0ad21a 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1480,7 +1480,10 @@ template <class ELFT, class RelTy> void RelocationScanner::scanOne(RelTy *&i) { // Process TLS relocations, including TLS optimizations. Note that // R_TPREL and R_TPREL_NEG relocations are resolved in processAux. - if (sym.isTls()) { + // + // Some RISCV TLSDESC relocations reference a local NOTYPE symbol, + // but we need to process them in handleTlsRelocation. + if (sym.isTls() || oneof<R_TLSDESC_PC, R_TLSDESC_CALL>(expr)) { if (unsigned processed = handleTlsRelocation(type, sym, *sec, offset, addend, expr)) { i += processed - 1; @@ -1617,12 +1620,8 @@ static bool handleNonPreemptibleIfunc(Symbol &sym, uint16_t flags) { // relatively straightforward. We create a PLT entry in Iplt, which is // usually at the end of .plt, which makes an indirect call using a // matching GOT entry in igotPlt, which is usually at the end of .got.plt. - // The GOT entry is relocated using an IRELATIVE relocation in relaIplt, - // which is usually at the end of .rela.plt. Unlike most relocations in - // .rela.plt, which may be evaluated lazily without -z now, dynamic - // loaders evaluate IRELATIVE relocs eagerly, which means that for - // IRELATIVE relocs only, GOT-generating relocations can point directly to - // .got.plt without requiring a separate GOT entry. + // The GOT entry is relocated using an IRELATIVE relocation in relaDyn, + // which is usually at the end of .rela.dyn. // // - Despite the fact that an ifunc does not have a fixed value, compilers // that are not passed -fPIC will assume that they do, and will emit @@ -1660,10 +1659,17 @@ static bool handleNonPreemptibleIfunc(Symbol &sym, uint16_t flags) { // original section/value pairs. For non-GOT non-PLT relocation case below, we // may alter section/value, so create a copy of the symbol to make // section/value fixed. + // + // Prior to Android V, there was a bug that caused RELR relocations to be + // applied after packed relocations. This meant that resolvers referenced by + // IRELATIVE relocations in the packed relocation section would read + // unrelocated globals with RELR relocations when + // --pack-relative-relocs=android+relr is enabled. Work around this by placing + // IRELATIVE in .rela.plt. auto *directSym = makeDefined(cast<Defined>(sym)); directSym->allocateAux(); - addPltEntry(*in.iplt, *in.igotPlt, *in.relaIplt, target->iRelativeRel, - *directSym); + auto &dyn = config->androidPackDynRelocs ? *in.relaPlt : *mainPart->relaDyn; + addPltEntry(*in.iplt, *in.igotPlt, dyn, target->iRelativeRel, *directSym); sym.allocateAux(); symAux.back().pltIdx = symAux[directSym->auxIdx].pltIdx; diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp index 3bb1de99480f307562f861c6cfd13bfac40e765d..f90ce6fa740757de659eebf3563bc4856b44a583 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -36,6 +36,7 @@ #include "llvm/Support/TimeProfiler.h" #include <cassert> #include <limits> +#include <optional> #include <vector> using namespace llvm; @@ -138,6 +139,10 @@ private: // A set to detect an INCLUDE() cycle. StringSet<> seen; + + // If we are currently parsing a PROVIDE|PROVIDE_HIDDEN command, + // then this member is set to the PROVIDE symbol name. + std::optional<llvm::StringRef> activeProvideSym; }; } // namespace @@ -1055,6 +1060,9 @@ SymbolAssignment *ScriptParser::readProvideHidden(bool provide, bool hidden) { ; return nullptr; } + llvm::SaveAndRestore saveActiveProvideSym(activeProvideSym); + if (provide) + activeProvideSym = name; SymbolAssignment *cmd = readSymbolAssignment(name); cmd->provide = provide; cmd->hidden = hidden; @@ -1570,7 +1578,10 @@ Expr ScriptParser::readPrimary() { tok = unquote(tok); else if (!isValidSymbolName(tok)) setError("malformed number: " + tok); - script->referencedSymbols.push_back(tok); + if (activeProvideSym) + script->provideMap[*activeProvideSym].push_back(tok); + else + script->referencedSymbols.push_back(tok); return [=] { return script->getSymbolValue(tok, location); }; } diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index b3d97e4de779068ecf7e6b736527a20d92304693..258a78ab40bb578e6daa639e226074734f726452 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -333,3 +333,7 @@ void SymbolTable::scanVersionScript() { // --dynamic-list. handleDynamicList(); } + +Symbol *SymbolTable::addUnusedUndefined(StringRef name, uint8_t binding) { + return addSymbol(Undefined{ctx.internalFile, name, binding, STV_DEFAULT, 0}); +} diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h index 37e31d23729637b3180c135b36cbb6a870d56cdc..269f7f284bc734e189ac6bcf40b7f0e246f479c5 100644 --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -57,6 +57,9 @@ public: void handleDynamicList(); + Symbol *addUnusedUndefined(StringRef name, + uint8_t binding = llvm::ELF::STB_GLOBAL); + // Set of .so files to not link the same shared object file more than once. llvm::DenseMap<llvm::CachedHashStringRef, SharedFile *> soNames; diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index cd2b9e22ab322493fe8a0e10dcd6e9ccb2a824de..93653def328f8224b5e1b3e8d11e30423f5f561f 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -539,8 +539,8 @@ void elf::reportDuplicate(const Symbol &sym, const InputFile *newFile, if (!d->section && !errSec && errOffset && d->value == errOffset) return; if (!d->section || !errSec) { - error("duplicate symbol: " + toString(sym) + "\n>>> defined in " + - toString(sym.file) + "\n>>> defined in " + toString(newFile)); + errorOrWarn("duplicate symbol: " + toString(sym) + "\n>>> defined in " + + toString(sym.file) + "\n>>> defined in " + toString(newFile)); return; } @@ -564,7 +564,7 @@ void elf::reportDuplicate(const Symbol &sym, const InputFile *newFile, if (!src2.empty()) msg += src2 + "\n>>> "; msg += obj2; - error(msg); + errorOrWarn(msg); } void Symbol::checkDuplicate(const Defined &other) const { diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 206fb0f53766649eb036e330e2f726df06b91b5b..8708bfeef8fa9aba869509cfa9252773bebcb856 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -415,7 +415,7 @@ void EhFrameSection::addRecords(EhInputSection *sec, ArrayRef<RelTy> rels) { for (EhSectionPiece &cie : sec->cies) offsetToCie[cie.inputOff] = addCie<ELFT>(cie, rels); for (EhSectionPiece &fde : sec->fdes) { - uint32_t id = endian::read32<ELFT::TargetEndianness>(fde.data().data() + 4); + uint32_t id = endian::read32<ELFT::Endianness>(fde.data().data() + 4); CieRecord *rec = offsetToCie[fde.inputOff + 4 - id]; if (!rec) fatal(toString(sec) + ": invalid CIE reference"); @@ -448,7 +448,7 @@ void EhFrameSection::iterateFDEWithLSDAAux( if (hasLSDA(cie)) ciesWithLSDA.insert(cie.inputOff); for (EhSectionPiece &fde : sec.fdes) { - uint32_t id = endian::read32<ELFT::TargetEndianness>(fde.data().data() + 4); + uint32_t id = endian::read32<ELFT::Endianness>(fde.data().data() + 4); if (!ciesWithLSDA.contains(fde.inputOff + 4 - id)) continue; @@ -628,19 +628,19 @@ GotSection::GotSection() } void GotSection::addConstant(const Relocation &r) { relocations.push_back(r); } -void GotSection::addEntry(Symbol &sym) { +void GotSection::addEntry(const Symbol &sym) { assert(sym.auxIdx == symAux.size() - 1); symAux.back().gotIdx = numEntries++; } -bool GotSection::addTlsDescEntry(Symbol &sym) { +bool GotSection::addTlsDescEntry(const Symbol &sym) { assert(sym.auxIdx == symAux.size() - 1); symAux.back().tlsDescIdx = numEntries; numEntries += 2; return true; } -bool GotSection::addDynTlsEntry(Symbol &sym) { +bool GotSection::addDynTlsEntry(const Symbol &sym) { assert(sym.auxIdx == symAux.size() - 1); symAux.back().tlsGdIdx = numEntries; // Global Dynamic TLS entries take two GOT slots. @@ -1267,15 +1267,12 @@ DynamicSection<ELFT>::DynamicSection() // The output section .rela.dyn may include these synthetic sections: // // - part.relaDyn -// - in.relaIplt: this is included if in.relaIplt is named .rela.dyn // - in.relaPlt: this is included if a linker script places .rela.plt inside // .rela.dyn // // DT_RELASZ is the total size of the included sections. static uint64_t addRelaSz(const RelocationBaseSection &relaDyn) { size_t size = relaDyn.getSize(); - if (in.relaIplt->getParent() == relaDyn.getParent()) - size += in.relaIplt->getSize(); if (in.relaPlt->getParent() == relaDyn.getParent()) size += in.relaPlt->getSize(); return size; @@ -1285,13 +1282,7 @@ static uint64_t addRelaSz(const RelocationBaseSection &relaDyn) { // output section. When this occurs we cannot just use the OutputSection // Size. Moreover the [DT_JMPREL, DT_JMPREL + DT_PLTRELSZ) is permitted to // overlap with the [DT_RELA, DT_RELA + DT_RELASZ). -static uint64_t addPltRelSz() { - size_t size = in.relaPlt->getSize(); - if (in.relaIplt->getParent() == in.relaPlt->getParent() && - in.relaIplt->name == in.relaPlt->name) - size += in.relaIplt->getSize(); - return size; -} +static uint64_t addPltRelSz() { return in.relaPlt->getSize(); } // Add remaining entries to complete .dynamic contents. template <class ELFT> @@ -1378,9 +1369,7 @@ DynamicSection<ELFT>::computeContents() { if (!config->shared && !config->relocatable && !config->zRodynamic) addInt(DT_DEBUG, 0); - if (part.relaDyn->isNeeded() || - (in.relaIplt->isNeeded() && - part.relaDyn->getParent() == in.relaIplt->getParent())) { + if (part.relaDyn->isNeeded()) { addInSec(part.relaDyn->dynamicTag, *part.relaDyn); entries.emplace_back(part.relaDyn->sizeDynamicTag, addRelaSz(*part.relaDyn)); @@ -1407,13 +1396,7 @@ DynamicSection<ELFT>::computeContents() { addInt(config->useAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT, sizeof(Elf_Relr)); } - // .rel[a].plt section usually consists of two parts, containing plt and - // iplt relocations. It is possible to have only iplt relocations in the - // output. In that case relaPlt is empty and have zero offset, the same offset - // as relaIplt has. And we still want to emit proper dynamic tags for that - // case, so here we always use relaPlt as marker for the beginning of - // .rel[a].plt section. - if (isMain && (in.relaPlt->isNeeded() || in.relaIplt->isNeeded())) { + if (isMain && in.relaPlt->isNeeded()) { addInSec(DT_JMPREL, *in.relaPlt); entries.emplace_back(DT_PLTRELSZ, addPltRelSz()); switch (config->emachine) { @@ -1600,7 +1583,7 @@ uint32_t DynamicReloc::getSymIndex(SymbolTableBaseSection *symTab) const { if (!needsDynSymIndex()) return 0; - size_t index = symTab->getSymbolIndex(sym); + size_t index = symTab->getSymbolIndex(*sym); assert((index != 0 || (type != target->gotRel && type != target->pltRel) || !mainPart->dynSymTab->getParent()) && "GOT or PLT relocation must refer to symbol in dynamic symbol table"); @@ -1669,10 +1652,6 @@ void RelocationBaseSection::finalizeContents() { getParent()->flags |= ELF::SHF_INFO_LINK; getParent()->info = in.gotPlt->getParent()->sectionIndex; } - if (in.relaIplt.get() == this && in.igotPlt->getParent()) { - getParent()->flags |= ELF::SHF_INFO_LINK; - getParent()->info = in.igotPlt->getParent()->sectionIndex; - } } void DynamicReloc::computeRaw(SymbolTableBaseSection *symtab) { @@ -1686,6 +1665,11 @@ void RelocationBaseSection::computeRels() { SymbolTableBaseSection *symTab = getPartition().dynSymTab.get(); parallelForEach(relocs, [symTab](DynamicReloc &rel) { rel.computeRaw(symTab); }); + + auto irelative = std::partition( + relocs.begin() + numRelativeRelocs, relocs.end(), + [t = target->iRelativeRel](auto &r) { return r.type != t; }); + // Sort by (!IsRelative,SymIndex,r_offset). DT_REL[A]COUNT requires us to // place R_*_RELATIVE first. SymIndex is to improve locality, while r_offset // is to make results easier to read. @@ -1694,7 +1678,7 @@ void RelocationBaseSection::computeRels() { parallelSort(relocs.begin(), nonRelative, [&](auto &a, auto &b) { return a.r_offset < b.r_offset; }); // Non-relative relocations are few, so don't bother with parallelSort. - llvm::sort(nonRelative, relocs.end(), [&](auto &a, auto &b) { + llvm::sort(nonRelative, irelative, [&](auto &a, auto &b) { return std::tie(a.r_sym, a.r_offset) < std::tie(b.r_sym, b.r_offset); }); } @@ -2172,9 +2156,9 @@ void SymbolTableBaseSection::addSymbol(Symbol *b) { symbols.push_back({b, strTabSec.addString(b->getName(), false)}); } -size_t SymbolTableBaseSection::getSymbolIndex(Symbol *sym) { +size_t SymbolTableBaseSection::getSymbolIndex(const Symbol &sym) { if (this == mainPart->dynSymTab.get()) - return sym->dynsymIndex; + return sym.dynsymIndex; // Initializes symbol lookup tables lazily. This is used only for -r, // --emit-relocs and dynsyms in partitions other than the main one. @@ -2191,9 +2175,9 @@ size_t SymbolTableBaseSection::getSymbolIndex(Symbol *sym) { // Section symbols are mapped based on their output sections // to maintain their semantics. - if (sym->type == STT_SECTION) - return sectionIndexMap.lookup(sym->getOutputSection()); - return symbolIndexMap.lookup(sym); + if (sym.type == STT_SECTION) + return sectionIndexMap.lookup(sym.getOutputSection()); + return symbolIndexMap.lookup(&sym); } template <class ELFT> @@ -2427,7 +2411,7 @@ void GnuHashTableSection::writeTo(uint8_t *buf) { // Write a hash bucket. Hash buckets contain indices in the following hash // value table. write32(buckets + i->bucketIdx, - getPartition().dynSymTab->getSymbolIndex(i->sym)); + getPartition().dynSymTab->getSymbolIndex(*i->sym)); oldBucket = i->bucketIdx; } } @@ -3855,7 +3839,6 @@ void InStruct::reset() { ppc32Got2.reset(); ibtPlt.reset(); relaPlt.reset(); - relaIplt.reset(); shStrTab.reset(); strTab.reset(); symTab.reset(); diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 7882ad87c241d705924efba9d42d811db2f860ef..02a669b01d152264537ca1b36677a299292f278d 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -106,9 +106,9 @@ public: void writeTo(uint8_t *buf) override; void addConstant(const Relocation &r); - void addEntry(Symbol &sym); - bool addTlsDescEntry(Symbol &sym); - bool addDynTlsEntry(Symbol &sym); + void addEntry(const Symbol &sym); + bool addTlsDescEntry(const Symbol &sym); + bool addDynTlsEntry(const Symbol &sym); bool addTlsIndex(); uint32_t getTlsDescOffset(const Symbol &sym) const; uint64_t getTlsDescAddr(const Symbol &sym) const; @@ -641,7 +641,7 @@ public: size_t getSize() const override { return getNumSymbols() * entsize; } void addSymbol(Symbol *sym); unsigned getNumSymbols() const { return symbols.size() + 1; } - size_t getSymbolIndex(Symbol *sym); + size_t getSymbolIndex(const Symbol &sym); ArrayRef<SymbolTableEntry> getSymbols() const { return symbols; } protected: @@ -1358,7 +1358,6 @@ struct InStruct { std::unique_ptr<PPC32Got2Section> ppc32Got2; std::unique_ptr<IBTPltSection> ibtPlt; std::unique_ptr<RelocationBaseSection> relaPlt; - std::unique_ptr<RelocationBaseSection> relaIplt; std::unique_ptr<StringTableSection> shStrTab; std::unique_ptr<StringTableSection> strTab; std::unique_ptr<SymbolTableBaseSection> symTab; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index a9292b3b1a22419de9e4b790bb3c4fe5cdaa7c84..40d617b7fdf324a147c4bd0159f45849b107e8fa 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -261,6 +261,9 @@ static void demoteDefined(Defined &sym, DenseMap<SectionBase *, size_t> &map) { Undefined(sym.file, sym.getName(), binding, sym.stOther, sym.type, /*discardedSecIdx=*/map.lookup(sym.section)) .overwrite(sym); + // Eliminate from the symbol table, otherwise we would leave an undefined + // symbol if the symbol is unreferenced in the absence of GC. + sym.isUsedInRegularObj = false; } // If all references to a DSO happen to be weak, the DSO is not added to @@ -446,8 +449,8 @@ template <class ELFT> void elf::createSyntheticSections() { add(*part.dynamic); add(*part.dynStrTab); - add(*part.relaDyn); } + add(*part.relaDyn); if (config->relrPackDynRelocs) { part.relrDyn = std::make_unique<RelrSection<ELFT>>(threadCount); @@ -547,17 +550,6 @@ template <class ELFT> void elf::createSyntheticSections() { /*threadCount=*/1); add(*in.relaPlt); - // The relaIplt immediately follows .rel[a].dyn to ensure that the IRelative - // relocations are processed last by the dynamic loader. We cannot place the - // iplt section in .rel.dyn when Android relocation packing is enabled because - // that would cause a section type mismatch. However, because the Android - // dynamic loader reads .rel.plt after .rel.dyn, we can get the desired - // behaviour by placing the iplt section in .rel.plt. - in.relaIplt = std::make_unique<RelocationSection<ELFT>>( - config->androidPackDynRelocs ? in.relaPlt->name : relaDynName, - /*sort=*/false, /*threadCount=*/1); - add(*in.relaIplt); - if ((config->emachine == EM_386 || config->emachine == EM_X86_64) && (config->andFeatures & GNU_PROPERTY_X86_FEATURE_1_IBT)) { in.ibtPlt = std::make_unique<IBTPltSection>(); @@ -793,7 +785,7 @@ template <class ELFT> void Writer<ELFT>::addSectionSymbols() { continue; for (InputSectionBase *s : isd->sections) { // Relocations are not using REL[A] section symbols. - if (s->type == SHT_REL || s->type == SHT_RELA) + if (isStaticRelSecType(s->type)) continue; // Unlike other synthetic sections, mergeable output sections contain @@ -1068,20 +1060,18 @@ void PhdrEntry::add(OutputSection *sec) { sec->ptLoad = this; } -// The beginning and the ending of .rel[a].plt section are marked -// with __rel[a]_iplt_{start,end} symbols if it is a statically linked -// executable. The runtime needs these symbols in order to resolve -// all IRELATIVE relocs on startup. For dynamic executables, we don't -// need these symbols, since IRELATIVE relocs are resolved through GOT -// and PLT. For details, see http://www.airs.com/blog/archives/403. +// A statically linked position-dependent executable should only contain +// IRELATIVE relocations and no other dynamic relocations. Encapsulation symbols +// __rel[a]_iplt_{start,end} will be defined for .rel[a].dyn, to be +// processed by the libc runtime. Other executables or DSOs use dynamic tags +// instead. template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() { if (config->isPic) return; - // By default, __rela_iplt_{start,end} belong to a dummy section 0 - // because .rela.plt might be empty and thus removed from output. - // We'll override Out::elfHeader with In.relaIplt later when we are - // sure that .rela.plt exists in output. + // __rela_iplt_{start,end} are initially defined relative to dummy section 0. + // We'll override Out::elfHeader with relaDyn later when we are sure that + // .rela.dyn will be present in the output. ElfSym::relaIpltStart = addOptionalRegular( config->isRela ? "__rela_iplt_start" : "__rel_iplt_start", Out::elfHeader, 0, STV_HIDDEN); @@ -1107,11 +1097,11 @@ template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() { ElfSym::globalOffsetTable->section = sec; } - // .rela_iplt_{start,end} mark the start and the end of in.relaIplt. - if (ElfSym::relaIpltStart && in.relaIplt->isNeeded()) { - ElfSym::relaIpltStart->section = in.relaIplt.get(); - ElfSym::relaIpltEnd->section = in.relaIplt.get(); - ElfSym::relaIpltEnd->value = in.relaIplt->getSize(); + // .rela_iplt_{start,end} mark the start and the end of .rel[a].dyn. + if (ElfSym::relaIpltStart && mainPart->relaDyn->isNeeded()) { + ElfSym::relaIpltStart->section = mainPart->relaDyn.get(); + ElfSym::relaIpltEnd->section = mainPart->relaDyn.get(); + ElfSym::relaIpltEnd->value = mainPart->relaDyn->getSize(); } PhdrEntry *last = nullptr; @@ -1467,14 +1457,6 @@ static void sortSection(OutputSection &osec, if (name == ".init" || name == ".fini") return; - // IRelative relocations that usually live in the .rel[a].dyn section should - // be processed last by the dynamic loader. To achieve that we add synthetic - // sections in the required order from the beginning so that the in.relaIplt - // section is placed last in an output section. Here we just do not apply - // sorting for an output section which holds the in.relaIplt section. - if (in.relaIplt->getParent() == &osec) - return; - // Sort input sections by priority using the list provided by // --symbol-ordering-file or --shuffle-sections=. This is a least significant // digit radix sort. The sections may be sorted stably again by a more @@ -2193,7 +2175,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { finalizeSynthetic(in.mipsGot.get()); finalizeSynthetic(in.igotPlt.get()); finalizeSynthetic(in.gotPlt.get()); - finalizeSynthetic(in.relaIplt.get()); finalizeSynthetic(in.relaPlt.get()); finalizeSynthetic(in.plt.get()); finalizeSynthetic(in.iplt.get()); @@ -3042,20 +3023,20 @@ template <class ELFT> void Writer<ELFT>::writeSections() { // section while doing it. parallel::TaskGroup tg; for (OutputSection *sec : outputSections) - if (sec->type == SHT_REL || sec->type == SHT_RELA) + if (isStaticRelSecType(sec->type)) sec->writeTo<ELFT>(Out::bufferStart + sec->offset, tg); } { parallel::TaskGroup tg; for (OutputSection *sec : outputSections) - if (sec->type != SHT_REL && sec->type != SHT_RELA) + if (!isStaticRelSecType(sec->type)) sec->writeTo<ELFT>(Out::bufferStart + sec->offset, tg); } // Finally, check that all dynamic relocation addends were written correctly. if (config->checkDynamicRelocs && config->writeAddends) { for (OutputSection *sec : outputSections) - if (sec->type == SHT_REL || sec->type == SHT_RELA) + if (isStaticRelSecType(sec->type)) sec->checkDynRelAddends(Out::bufferStart); } } diff --git a/lld/MachO/ConcatOutputSection.cpp b/lld/MachO/ConcatOutputSection.cpp index c5c0c8a89e28791923950c8506587706c9bbd653..279423720be9d51b8036928c21b4b3cade386ed0 100644 --- a/lld/MachO/ConcatOutputSection.cpp +++ b/lld/MachO/ConcatOutputSection.cpp @@ -323,11 +323,7 @@ void TextOutputSection::finalize() { thunkInfo.isec = makeSyntheticInputSection(isec->getSegName(), isec->getName()); thunkInfo.isec->parent = this; - - // This code runs after dead code removal. Need to set the `live` bit - // on the thunk isec so that asserts that check that only live sections - // get written are happy. - thunkInfo.isec->live = true; + assert(thunkInfo.isec->live); StringRef thunkName = saver().save(funcSym->getName() + ".thunk." + std::to_string(thunkInfo.sequence++)); diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h index f820513a111ea3335b426eab4e29bef51cf79bde..7b45f7f4c39a1b8c95ea03a9705af82bb46a0548 100644 --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -135,6 +135,7 @@ struct Configuration { bool emitEncryptionInfo = false; bool emitInitOffsets = false; bool emitChainedFixups = false; + bool emitRelativeMethodLists = false; bool thinLTOEmitImportsFiles; bool thinLTOEmitIndexFiles; bool thinLTOIndexOnly; diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp index 9edb6b9c60a1fecba8828b620c2ee4da27475066..65de531db04b7518154617f7387cdaad1c00895b 100644 --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -612,7 +612,7 @@ static void replaceCommonSymbols() { if (!osec) osec = ConcatOutputSection::getOrCreateForInput(isec); isec->parent = osec; - inputSections.push_back(isec); + addInputSection(isec); // FIXME: CommonSymbol should store isReferencedDynamically, noDeadStrip // and pass them on here. @@ -1086,6 +1086,22 @@ static bool shouldEmitChainedFixups(const InputArgList &args) { return isRequested; } +static bool shouldEmitRelativeMethodLists(const InputArgList &args) { + const Arg *arg = args.getLastArg(OPT_objc_relative_method_lists, + OPT_no_objc_relative_method_lists); + if (arg && arg->getOption().getID() == OPT_objc_relative_method_lists) + return true; + if (arg && arg->getOption().getID() == OPT_no_objc_relative_method_lists) + return false; + + // TODO: If no flag is specified, don't default to false, but instead: + // - default false on < ios14 + // - default true on >= ios14 + // For now, until this feature is confirmed stable, default to false if no + // flag is explicitly specified + return false; +} + void SymbolPatterns::clear() { literals.clear(); globs.clear(); @@ -1220,53 +1236,18 @@ static void createFiles(const InputArgList &args) { static void gatherInputSections() { TimeTraceScope timeScope("Gathering input sections"); - int inputOrder = 0; for (const InputFile *file : inputFiles) { for (const Section *section : file->sections) { // Compact unwind entries require special handling elsewhere. (In // contrast, EH frames are handled like regular ConcatInputSections.) if (section->name == section_names::compactUnwind) continue; - ConcatOutputSection *osec = nullptr; - for (const Subsection &subsection : section->subsections) { - if (auto *isec = dyn_cast<ConcatInputSection>(subsection.isec)) { - if (isec->isCoalescedWeak()) - continue; - if (config->emitInitOffsets && - sectionType(isec->getFlags()) == S_MOD_INIT_FUNC_POINTERS) { - in.initOffsets->addInput(isec); - continue; - } - isec->outSecOff = inputOrder++; - if (!osec) - osec = ConcatOutputSection::getOrCreateForInput(isec); - isec->parent = osec; - inputSections.push_back(isec); - } else if (auto *isec = - dyn_cast<CStringInputSection>(subsection.isec)) { - if (isec->getName() == section_names::objcMethname) { - if (in.objcMethnameSection->inputOrder == UnspecifiedInputOrder) - in.objcMethnameSection->inputOrder = inputOrder++; - in.objcMethnameSection->addInput(isec); - } else { - if (in.cStringSection->inputOrder == UnspecifiedInputOrder) - in.cStringSection->inputOrder = inputOrder++; - in.cStringSection->addInput(isec); - } - } else if (auto *isec = - dyn_cast<WordLiteralInputSection>(subsection.isec)) { - if (in.wordLiteralSection->inputOrder == UnspecifiedInputOrder) - in.wordLiteralSection->inputOrder = inputOrder++; - in.wordLiteralSection->addInput(isec); - } else { - llvm_unreachable("unexpected input section kind"); - } - } + for (const Subsection &subsection : section->subsections) + addInputSection(subsection.isec); } if (!file->objCImageInfo.empty()) in.objCImageInfo->addFile(file); } - assert(inputOrder <= UnspecifiedInputOrder); } static void foldIdenticalLiterals() { @@ -1422,12 +1403,14 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS, concatOutputSections.clear(); inputFiles.clear(); inputSections.clear(); + inputSectionsOrder = 0; loadedArchives.clear(); loadedObjectFrameworks.clear(); missingAutolinkWarnings.clear(); syntheticSections.clear(); thunkMap.clear(); unprocessedLCLinkerOptions.clear(); + ObjCSelRefsHelper::cleanup(); firstTLVDataSection = nullptr; tar = nullptr; @@ -1437,6 +1420,8 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS, resetOutputSegments(); resetWriter(); InputFile::resetIdCount(); + + objc::doCleanup(); }; ctx->e.logName = args::getFilenameWithoutExe(argsArr[0]); @@ -1661,6 +1646,7 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS, config->emitChainedFixups = shouldEmitChainedFixups(args); config->emitInitOffsets = config->emitChainedFixups || args.hasArg(OPT_init_offsets); + config->emitRelativeMethodLists = shouldEmitRelativeMethodLists(args); config->icfLevel = getICFLevel(args); config->dedupStrings = args.hasFlag(OPT_deduplicate_strings, OPT_no_deduplicate_strings, true); @@ -1979,9 +1965,16 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS, if (config->deadStrip) markLive(); + // Categories are not subject to dead-strip. The __objc_catlist section is + // marked as NO_DEAD_STRIP and that propagates into all category data. if (args.hasArg(OPT_check_category_conflicts)) objc::checkCategories(); + // Category merging uses "->live = false" to erase old category data, so + // it has to run after dead-stripping (markLive). + if (args.hasArg(OPT_objc_category_merging, OPT_no_objc_category_merging)) + objc::mergeCategories(); + // ICF assumes that all literals have been folded already, so we must run // foldIdenticalLiterals before foldIdenticalSections. foldIdenticalLiterals(); diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp index 8f5affb1dc21d8a9e13766fa2a58473bdcaf1a75..5c1e07cd21b1fbbea172514858cb638864680f2a 100644 --- a/lld/MachO/InputSection.cpp +++ b/lld/MachO/InputSection.cpp @@ -37,6 +37,52 @@ static_assert(sizeof(void *) != 8 || "instances of it"); std::vector<ConcatInputSection *> macho::inputSections; +int macho::inputSectionsOrder = 0; + +// Call this function to add a new InputSection and have it routed to the +// appropriate container. Depending on its type and current config, it will +// either be added to 'inputSections' vector or to a synthetic section. +void lld::macho::addInputSection(InputSection *inputSection) { + if (auto *isec = dyn_cast<ConcatInputSection>(inputSection)) { + if (isec->isCoalescedWeak()) + return; + if (config->emitRelativeMethodLists && + ObjCMethListSection::isMethodList(isec)) { + if (in.objcMethList->inputOrder == UnspecifiedInputOrder) + in.objcMethList->inputOrder = inputSectionsOrder++; + in.objcMethList->addInput(isec); + isec->parent = in.objcMethList; + return; + } + if (config->emitInitOffsets && + sectionType(isec->getFlags()) == S_MOD_INIT_FUNC_POINTERS) { + in.initOffsets->addInput(isec); + return; + } + isec->outSecOff = inputSectionsOrder++; + auto *osec = ConcatOutputSection::getOrCreateForInput(isec); + isec->parent = osec; + inputSections.push_back(isec); + } else if (auto *isec = dyn_cast<CStringInputSection>(inputSection)) { + if (isec->getName() == section_names::objcMethname) { + if (in.objcMethnameSection->inputOrder == UnspecifiedInputOrder) + in.objcMethnameSection->inputOrder = inputSectionsOrder++; + in.objcMethnameSection->addInput(isec); + } else { + if (in.cStringSection->inputOrder == UnspecifiedInputOrder) + in.cStringSection->inputOrder = inputSectionsOrder++; + in.cStringSection->addInput(isec); + } + } else if (auto *isec = dyn_cast<WordLiteralInputSection>(inputSection)) { + if (in.wordLiteralSection->inputOrder == UnspecifiedInputOrder) + in.wordLiteralSection->inputOrder = inputSectionsOrder++; + in.wordLiteralSection->addInput(isec); + } else { + llvm_unreachable("unexpected input section kind"); + } + + assert(inputSectionsOrder <= UnspecifiedInputOrder); +} uint64_t InputSection::getFileSize() const { return isZeroFill(getFlags()) ? 0 : getSize(); @@ -235,6 +281,9 @@ ConcatInputSection *macho::makeSyntheticInputSection(StringRef segName, Section §ion = *make<Section>(/*file=*/nullptr, segName, sectName, flags, /*addr=*/0); auto isec = make<ConcatInputSection>(section, data, align); + // Since this is an explicitly created 'fake' input section, + // it should not be dead stripped. + isec->live = true; section.subsections.push_back({0, isec}); return isec; } diff --git a/lld/MachO/InputSection.h b/lld/MachO/InputSection.h index becb01017d633abd308a20012891fe03a858bea9..0f389e50425a32e330ae8049556424ce66395fa8 100644 --- a/lld/MachO/InputSection.h +++ b/lld/MachO/InputSection.h @@ -93,9 +93,9 @@ public: // .subsections_via_symbols, there is typically only one element here. llvm::TinyPtrVector<Defined *> symbols; -protected: const Section §ion; +protected: const Defined *getContainingSymbol(uint64_t off) const; }; @@ -149,6 +149,7 @@ public: }; // Initialize a fake InputSection that does not belong to any InputFile. +// The created ConcatInputSection will always have 'live=true' ConcatInputSection *makeSyntheticInputSection(StringRef segName, StringRef sectName, uint32_t flags = 0, @@ -302,6 +303,8 @@ bool isEhFrameSection(const InputSection *); bool isGccExceptTabSection(const InputSection *); extern std::vector<ConcatInputSection *> inputSections; +// This is used as a counter for specyfing input order for input sections +extern int inputSectionsOrder; namespace section_names { @@ -340,6 +343,7 @@ constexpr const char moduleTermFunc[] = "__mod_term_func"; constexpr const char nonLazySymbolPtr[] = "__nl_symbol_ptr"; constexpr const char objcCatList[] = "__objc_catlist"; constexpr const char objcClassList[] = "__objc_classlist"; +constexpr const char objcMethList[] = "__objc_methlist"; constexpr const char objcClassRefs[] = "__objc_classrefs"; constexpr const char objcConst[] = "__objc_const"; constexpr const char objCImageInfo[] = "__objc_imageinfo"; @@ -369,6 +373,7 @@ constexpr const char addrSig[] = "__llvm_addrsig"; } // namespace section_names +void addInputSection(InputSection *inputSection); } // namespace macho std::string toString(const macho::InputSection *); diff --git a/lld/MachO/MapFile.cpp b/lld/MachO/MapFile.cpp index f736360624ebd12f73749833b8ae14ed41766d9d..2a31a5c09cdd22e39e62dbd07f1a408498e4b7e3 100644 --- a/lld/MachO/MapFile.cpp +++ b/lld/MachO/MapFile.cpp @@ -197,18 +197,24 @@ void macho::writeMapFile() { seg->name.str().c_str(), osec->name.str().c_str()); } + // Shared function to print an array of symbols. + auto printIsecArrSyms = [&](const std::vector<ConcatInputSection *> &arr) { + for (const ConcatInputSection *isec : arr) { + for (Defined *sym : isec->symbols) { + if (!(isPrivateLabel(sym->getName()) && sym->size == 0)) + os << format("0x%08llX\t0x%08llX\t[%3u] %s\n", sym->getVA(), + sym->size, readerToFileOrdinal[sym->getFile()], + sym->getName().str().data()); + } + } + }; + os << "# Symbols:\n"; os << "# Address\tSize \tFile Name\n"; for (const OutputSegment *seg : outputSegments) { for (const OutputSection *osec : seg->getSections()) { if (auto *concatOsec = dyn_cast<ConcatOutputSection>(osec)) { - for (const InputSection *isec : concatOsec->inputs) { - for (Defined *sym : isec->symbols) - if (!(isPrivateLabel(sym->getName()) && sym->size == 0)) - os << format("0x%08llX\t0x%08llX\t[%3u] %s\n", sym->getVA(), - sym->size, readerToFileOrdinal[sym->getFile()], - sym->getName().str().data()); - } + printIsecArrSyms(concatOsec->inputs); } else if (osec == in.cStringSection || osec == in.objcMethnameSection) { const auto &liveCStrings = info.liveCStringsForSection.lookup(osec); uint64_t lastAddr = 0; // strings will never start at address 0, so this @@ -237,6 +243,8 @@ void macho::writeMapFile() { printNonLazyPointerSection(os, in.got); } else if (osec == in.tlvPointers) { printNonLazyPointerSection(os, in.tlvPointers); + } else if (osec == in.objcMethList) { + printIsecArrSyms(in.objcMethList->getInputs()); } // TODO print other synthetic sections } diff --git a/lld/MachO/ObjC.cpp b/lld/MachO/ObjC.cpp index 67254ec53a2145b9b208293d8fd3cd866efb283f..5902b82d30f556ca6651cdcec6d8fab3e478fceb 100644 --- a/lld/MachO/ObjC.cpp +++ b/lld/MachO/ObjC.cpp @@ -7,16 +7,19 @@ //===----------------------------------------------------------------------===// #include "ObjC.h" +#include "ConcatOutputSection.h" #include "InputFiles.h" #include "InputSection.h" #include "Layout.h" #include "OutputSegment.h" +#include "SyntheticSections.h" #include "Target.h" #include "lld/Common/ErrorHandler.h" #include "llvm/ADT/DenseMap.h" #include "llvm/BinaryFormat/MachO.h" #include "llvm/Bitcode/BitcodeReader.h" +#include "llvm/Support/TimeProfiler.h" using namespace llvm; using namespace llvm::MachO; @@ -78,7 +81,8 @@ namespace { DO(Ptr, classMethods) \ DO(Ptr, protocols) \ DO(Ptr, instanceProps) \ - DO(Ptr, classProps) + DO(Ptr, classProps) \ + DO(uint32_t, size) CREATE_LAYOUT_CLASS(Category, FOR_EACH_CATEGORY_FIELD); @@ -112,13 +116,19 @@ CREATE_LAYOUT_CLASS(ROClass, FOR_EACH_RO_CLASS_FIELD); #undef FOR_EACH_RO_CLASS_FIELD #define FOR_EACH_LIST_HEADER(DO) \ - DO(uint32_t, size) \ - DO(uint32_t, count) + DO(uint32_t, structSize) \ + DO(uint32_t, structCount) CREATE_LAYOUT_CLASS(ListHeader, FOR_EACH_LIST_HEADER); #undef FOR_EACH_LIST_HEADER +#define FOR_EACH_PROTOCOL_LIST_HEADER(DO) DO(Ptr, protocolCount) + +CREATE_LAYOUT_CLASS(ProtocolListHeader, FOR_EACH_PROTOCOL_LIST_HEADER); + +#undef FOR_EACH_PROTOCOL_LIST_HEADER + #define FOR_EACH_METHOD(DO) \ DO(Ptr, name) \ DO(Ptr, type) \ @@ -311,6 +321,8 @@ void ObjcCategoryChecker::parseClass(const Defined *classSym) { } void objc::checkCategories() { + TimeTraceScope timeScope("ObjcCategoryChecker"); + ObjcCategoryChecker checker; for (const InputSection *isec : inputSections) { if (isec->getName() == section_names::objcCatList) @@ -320,3 +332,916 @@ void objc::checkCategories() { } } } + +namespace { + +class ObjcCategoryMerger { + // Information about an input category + struct InfoInputCategory { + ConcatInputSection *catListIsec; + ConcatInputSection *catBodyIsec; + uint32_t offCatListIsec = 0; + + bool wasMerged = false; + }; + + // To write new (merged) categories or classes, we will try make limited + // assumptions about the alignment and the sections the various class/category + // info are stored in and . So we'll just reuse the same sections and + // alignment as already used in existing (input) categories. To do this we + // have InfoCategoryWriter which contains the various sections that the + // generated categories will be written to. + template <typename T> struct InfoWriteSection { + bool valid = false; // Data has been successfully collected from input + uint32_t align = 0; + Section *inputSection; + Reloc relocTemplate; + T *outputSection; + }; + + struct InfoCategoryWriter { + InfoWriteSection<ConcatOutputSection> catListInfo; + InfoWriteSection<ConcatOutputSection> catBodyInfo; + InfoWriteSection<CStringSection> catNameInfo; + InfoWriteSection<ConcatOutputSection> catPtrListInfo; + }; + + // Information about a pointer list in the original categories (method lists, + // protocol lists, etc) + struct PointerListInfo { + PointerListInfo(const char *_categoryPrefix, uint32_t _categoryOffset, + uint32_t _pointersPerStruct) + : categoryPrefix(_categoryPrefix), categoryOffset(_categoryOffset), + pointersPerStruct(_pointersPerStruct) {} + const char *categoryPrefix; + uint32_t categoryOffset = 0; + + uint32_t pointersPerStruct = 0; + + uint32_t structSize = 0; + uint32_t structCount = 0; + + std::vector<Symbol *> allPtrs; + }; + + // Full information about all the categories that extend a class. This will + // include all the additional methods, protocols, and properties that are + // contained in all the categories that extend a particular class. + struct ClassExtensionInfo { + ClassExtensionInfo(CategoryLayout &_catLayout) : catLayout(_catLayout){}; + + // Merged names of containers. Ex: base|firstCategory|secondCategory|... + std::string mergedContainerName; + std::string baseClassName; + Symbol *baseClass = nullptr; + CategoryLayout &catLayout; + + // In case we generate new data, mark the new data as belonging to this file + ObjFile *objFileForMergeData = nullptr; + + PointerListInfo instanceMethods = { + objc::symbol_names::categoryInstanceMethods, + /*_categoryOffset=*/catLayout.instanceMethodsOffset, + /*pointersPerStruct=*/3}; + PointerListInfo classMethods = { + objc::symbol_names::categoryClassMethods, + /*_categoryOffset=*/catLayout.classMethodsOffset, + /*pointersPerStruct=*/3}; + PointerListInfo protocols = {objc::symbol_names::categoryProtocols, + /*_categoryOffset=*/catLayout.protocolsOffset, + /*pointersPerStruct=*/0}; + PointerListInfo instanceProps = { + objc::symbol_names::listProprieties, + /*_categoryOffset=*/catLayout.instancePropsOffset, + /*pointersPerStruct=*/2}; + PointerListInfo classProps = { + objc::symbol_names::klassPropList, + /*_categoryOffset=*/catLayout.classPropsOffset, + /*pointersPerStruct=*/2}; + }; + +public: + ObjcCategoryMerger(std::vector<ConcatInputSection *> &_allInputSections); + void doMerge(); + static void doCleanup(); + +private: + void collectAndValidateCategoriesData(); + void + mergeCategoriesIntoSingleCategory(std::vector<InfoInputCategory> &categories); + + void eraseISec(ConcatInputSection *isec); + void eraseMergedCategories(); + + void generateCatListForNonErasedCategories( + std::map<ConcatInputSection *, std::set<uint64_t>> + catListToErasedOffsets); + template <typename T> + void collectSectionWriteInfoFromIsec(const InputSection *isec, + InfoWriteSection<T> &catWriteInfo); + void collectCategoryWriterInfoFromCategory(const InfoInputCategory &catInfo); + void parseCatInfoToExtInfo(const InfoInputCategory &catInfo, + ClassExtensionInfo &extInfo); + + void parseProtocolListInfo(const ConcatInputSection *isec, uint32_t secOffset, + PointerListInfo &ptrList); + + void parsePointerListInfo(const ConcatInputSection *isec, uint32_t secOffset, + PointerListInfo &ptrList); + + void emitAndLinkPointerList(Defined *parentSym, uint32_t linkAtOffset, + const ClassExtensionInfo &extInfo, + const PointerListInfo &ptrList); + + void emitAndLinkProtocolList(Defined *parentSym, uint32_t linkAtOffset, + const ClassExtensionInfo &extInfo, + const PointerListInfo &ptrList); + + Defined *emitCategory(const ClassExtensionInfo &extInfo); + Defined *emitCatListEntrySec(const std::string &forCateogryName, + const std::string &forBaseClassName, + ObjFile *objFile); + Defined *emitCategoryBody(const std::string &name, const Defined *nameSym, + const Symbol *baseClassSym, + const std::string &baseClassName, ObjFile *objFile); + Defined *emitCategoryName(const std::string &name, ObjFile *objFile); + void createSymbolReference(Defined *refFrom, const Symbol *refTo, + uint32_t offset, const Reloc &relocTemplate); + Symbol *tryGetSymbolAtIsecOffset(const ConcatInputSection *isec, + uint32_t offset); + Defined *tryGetDefinedAtIsecOffset(const ConcatInputSection *isec, + uint32_t offset); + void tryEraseDefinedAtIsecOffset(const ConcatInputSection *isec, + uint32_t offset); + + // Allocate a null-terminated StringRef backed by generatedSectionData + StringRef newStringData(const char *str); + // Allocate section data, backed by generatedSectionData + SmallVector<uint8_t> &newSectionData(uint32_t size); + + CategoryLayout catLayout; + ClassLayout classLayout; + ROClassLayout roClassLayout; + ListHeaderLayout listHeaderLayout; + MethodLayout methodLayout; + ProtocolListHeaderLayout protocolListHeaderLayout; + + InfoCategoryWriter infoCategoryWriter; + std::vector<ConcatInputSection *> &allInputSections; + // Map of base class Symbol to list of InfoInputCategory's for it + DenseMap<const Symbol *, std::vector<InfoInputCategory>> categoryMap; + + // Normally, the binary data comes from the input files, but since we're + // generating binary data ourselves, we use the below array to store it in. + // Need this to be 'static' so the data survives past the ObjcCategoryMerger + // object, as the data will be read by the Writer when the final binary is + // generated. + static SmallVector<std::unique_ptr<SmallVector<uint8_t>>> + generatedSectionData; +}; + +SmallVector<std::unique_ptr<SmallVector<uint8_t>>> + ObjcCategoryMerger::generatedSectionData; + +ObjcCategoryMerger::ObjcCategoryMerger( + std::vector<ConcatInputSection *> &_allInputSections) + : catLayout(target->wordSize), classLayout(target->wordSize), + roClassLayout(target->wordSize), listHeaderLayout(target->wordSize), + methodLayout(target->wordSize), + protocolListHeaderLayout(target->wordSize), + allInputSections(_allInputSections) {} + +// This is a template so that it can be used both for CStringSection and +// ConcatOutputSection +template <typename T> +void ObjcCategoryMerger::collectSectionWriteInfoFromIsec( + const InputSection *isec, InfoWriteSection<T> &catWriteInfo) { + + catWriteInfo.inputSection = const_cast<Section *>(&isec->section); + catWriteInfo.align = isec->align; + catWriteInfo.outputSection = dyn_cast_or_null<T>(isec->parent); + + assert(catWriteInfo.outputSection && + "outputSection may not be null in collectSectionWriteInfoFromIsec."); + + if (isec->relocs.size()) + catWriteInfo.relocTemplate = isec->relocs[0]; + + catWriteInfo.valid = true; +} + +Symbol * +ObjcCategoryMerger::tryGetSymbolAtIsecOffset(const ConcatInputSection *isec, + uint32_t offset) { + const Reloc *reloc = isec->getRelocAt(offset); + + if (!reloc) + return nullptr; + + return reloc->referent.get<Symbol *>(); +} + +Defined * +ObjcCategoryMerger::tryGetDefinedAtIsecOffset(const ConcatInputSection *isec, + uint32_t offset) { + Symbol *sym = tryGetSymbolAtIsecOffset(isec, offset); + return dyn_cast_or_null<Defined>(sym); +} + +// Given an ConcatInputSection or CStringInputSection and an offset, if there is +// a symbol(Defined) at that offset, then erase the symbol (mark it not live) +void ObjcCategoryMerger::tryEraseDefinedAtIsecOffset( + const ConcatInputSection *isec, uint32_t offset) { + const Reloc *reloc = isec->getRelocAt(offset); + + if (!reloc) + return; + + Defined *sym = dyn_cast_or_null<Defined>(reloc->referent.get<Symbol *>()); + if (!sym) + return; + + if (auto *cisec = dyn_cast_or_null<ConcatInputSection>(sym->isec)) + eraseISec(cisec); + else if (auto *csisec = dyn_cast_or_null<CStringInputSection>(sym->isec)) { + uint32_t totalOffset = sym->value + reloc->addend; + StringPiece &piece = csisec->getStringPiece(totalOffset); + piece.live = false; + } else { + llvm_unreachable("erased symbol has to be Defined or CStringInputSection"); + } +} + +void ObjcCategoryMerger::collectCategoryWriterInfoFromCategory( + const InfoInputCategory &catInfo) { + + if (!infoCategoryWriter.catListInfo.valid) + collectSectionWriteInfoFromIsec<ConcatOutputSection>( + catInfo.catListIsec, infoCategoryWriter.catListInfo); + if (!infoCategoryWriter.catBodyInfo.valid) + collectSectionWriteInfoFromIsec<ConcatOutputSection>( + catInfo.catBodyIsec, infoCategoryWriter.catBodyInfo); + + if (!infoCategoryWriter.catNameInfo.valid) { + lld::macho::Defined *catNameSym = + tryGetDefinedAtIsecOffset(catInfo.catBodyIsec, catLayout.nameOffset); + assert(catNameSym && "Category does not have a valid name Symbol"); + + collectSectionWriteInfoFromIsec<CStringSection>( + catNameSym->isec, infoCategoryWriter.catNameInfo); + } + + // Collect writer info from all the category lists (we're assuming they all + // would provide the same info) + if (!infoCategoryWriter.catPtrListInfo.valid) { + for (uint32_t off = catLayout.instanceMethodsOffset; + off <= catLayout.classPropsOffset; off += target->wordSize) { + if (Defined *ptrList = + tryGetDefinedAtIsecOffset(catInfo.catBodyIsec, off)) { + collectSectionWriteInfoFromIsec<ConcatOutputSection>( + ptrList->isec, infoCategoryWriter.catPtrListInfo); + // we've successfully collected data, so we can break + break; + } + } + } +} + +// Parse a protocol list that might be linked to ConcatInputSection at a given +// offset. The format of the protocol list is different than other lists (prop +// lists, method lists) so we need to parse it differently +void ObjcCategoryMerger::parseProtocolListInfo(const ConcatInputSection *isec, + uint32_t secOffset, + PointerListInfo &ptrList) { + assert((isec && (secOffset + target->wordSize <= isec->data.size())) && + "Tried to read pointer list beyond protocol section end"); + + const Reloc *reloc = isec->getRelocAt(secOffset); + if (!reloc) + return; + + auto *ptrListSym = dyn_cast_or_null<Defined>(reloc->referent.get<Symbol *>()); + assert(ptrListSym && "Protocol list reloc does not have a valid Defined"); + + // Theoretically protocol count can be either 32b or 64b, depending on + // platform pointer size, but to simplify implementation we always just read + // the lower 32b which should be good enough. + uint32_t protocolCount = *reinterpret_cast<const uint32_t *>( + ptrListSym->isec->data.data() + listHeaderLayout.structSizeOffset); + + ptrList.structCount += protocolCount; + ptrList.structSize = target->wordSize; + + uint32_t expectedListSize = + (protocolCount * target->wordSize) + + /*header(count)*/ protocolListHeaderLayout.totalSize + + /*extra null value*/ target->wordSize; + assert(expectedListSize == ptrListSym->isec->data.size() && + "Protocol list does not match expected size"); + + // Suppress unsuded var warning + (void)expectedListSize; + + uint32_t off = protocolListHeaderLayout.totalSize; + for (uint32_t inx = 0; inx < protocolCount; ++inx) { + const Reloc *reloc = ptrListSym->isec->getRelocAt(off); + assert(reloc && "No reloc found at protocol list offset"); + + auto *listSym = dyn_cast_or_null<Defined>(reloc->referent.get<Symbol *>()); + assert(listSym && "Protocol list reloc does not have a valid Defined"); + + ptrList.allPtrs.push_back(listSym); + off += target->wordSize; + } + assert((ptrListSym->isec->getRelocAt(off) == nullptr) && + "expected null terminating protocol"); + assert(off + /*extra null value*/ target->wordSize == expectedListSize && + "Protocol list end offset does not match expected size"); +} + +// Parse a pointer list that might be linked to ConcatInputSection at a given +// offset. This can be used for instance methods, class methods, instance props +// and class props since they have the same format. +void ObjcCategoryMerger::parsePointerListInfo(const ConcatInputSection *isec, + uint32_t secOffset, + PointerListInfo &ptrList) { + assert(ptrList.pointersPerStruct == 2 || ptrList.pointersPerStruct == 3); + assert(isec && "Trying to parse pointer list from null isec"); + assert(secOffset + target->wordSize <= isec->data.size() && + "Trying to read pointer list beyond section end"); + + const Reloc *reloc = isec->getRelocAt(secOffset); + if (!reloc) + return; + + auto *ptrListSym = dyn_cast_or_null<Defined>(reloc->referent.get<Symbol *>()); + assert(ptrListSym && "Reloc does not have a valid Defined"); + + uint32_t thisStructSize = *reinterpret_cast<const uint32_t *>( + ptrListSym->isec->data.data() + listHeaderLayout.structSizeOffset); + uint32_t thisStructCount = *reinterpret_cast<const uint32_t *>( + ptrListSym->isec->data.data() + listHeaderLayout.structCountOffset); + assert(thisStructSize == ptrList.pointersPerStruct * target->wordSize); + + assert(!ptrList.structSize || (thisStructSize == ptrList.structSize)); + + ptrList.structCount += thisStructCount; + ptrList.structSize = thisStructSize; + + uint32_t expectedListSize = + listHeaderLayout.totalSize + (thisStructSize * thisStructCount); + assert(expectedListSize == ptrListSym->isec->data.size() && + "Pointer list does not match expected size"); + + for (uint32_t off = listHeaderLayout.totalSize; off < expectedListSize; + off += target->wordSize) { + const Reloc *reloc = ptrListSym->isec->getRelocAt(off); + assert(reloc && "No reloc found at pointer list offset"); + + auto *listSym = dyn_cast_or_null<Defined>(reloc->referent.get<Symbol *>()); + assert(listSym && "Reloc does not have a valid Defined"); + + ptrList.allPtrs.push_back(listSym); + } +} + +// Here we parse all the information of an input category (catInfo) and +// append the parsed info into the structure which will contain all the +// information about how a class is extended (extInfo) +void ObjcCategoryMerger::parseCatInfoToExtInfo(const InfoInputCategory &catInfo, + ClassExtensionInfo &extInfo) { + const Reloc *catNameReloc = + catInfo.catBodyIsec->getRelocAt(catLayout.nameOffset); + + // Parse name + assert(catNameReloc && "Category does not have a reloc at 'nameOffset'"); + + // is this the first category we are parsing? + if (extInfo.mergedContainerName.empty()) + extInfo.objFileForMergeData = + dyn_cast_or_null<ObjFile>(catInfo.catBodyIsec->getFile()); + else + extInfo.mergedContainerName += "|"; + + assert(extInfo.objFileForMergeData && + "Expected to already have valid objextInfo.objFileForMergeData"); + + StringRef catName = getReferentString(*catNameReloc); + extInfo.mergedContainerName += catName.str(); + + // Parse base class + if (!extInfo.baseClass) { + Symbol *classSym = + tryGetSymbolAtIsecOffset(catInfo.catBodyIsec, catLayout.klassOffset); + assert(extInfo.baseClassName.empty()); + extInfo.baseClass = classSym; + llvm::StringRef classPrefix(objc::symbol_names::klass); + assert(classSym->getName().starts_with(classPrefix) && + "Base class symbol does not start with expected prefix"); + extInfo.baseClassName = classSym->getName().substr(classPrefix.size()); + } else { + assert((extInfo.baseClass == + tryGetSymbolAtIsecOffset(catInfo.catBodyIsec, + catLayout.klassOffset)) && + "Trying to parse category info into container with different base " + "class"); + } + + parsePointerListInfo(catInfo.catBodyIsec, catLayout.instanceMethodsOffset, + extInfo.instanceMethods); + + parsePointerListInfo(catInfo.catBodyIsec, catLayout.classMethodsOffset, + extInfo.classMethods); + + parseProtocolListInfo(catInfo.catBodyIsec, catLayout.protocolsOffset, + extInfo.protocols); + + parsePointerListInfo(catInfo.catBodyIsec, catLayout.instancePropsOffset, + extInfo.instanceProps); + + parsePointerListInfo(catInfo.catBodyIsec, catLayout.classPropsOffset, + extInfo.classProps); +} + +// Generate a protocol list (including header) and link it into the parent at +// the specified offset. +void ObjcCategoryMerger::emitAndLinkProtocolList( + Defined *parentSym, uint32_t linkAtOffset, + const ClassExtensionInfo &extInfo, const PointerListInfo &ptrList) { + if (ptrList.allPtrs.empty()) + return; + + assert(ptrList.allPtrs.size() == ptrList.structCount); + + uint32_t bodySize = (ptrList.structCount * target->wordSize) + + /*header(count)*/ protocolListHeaderLayout.totalSize + + /*extra null value*/ target->wordSize; + llvm::ArrayRef<uint8_t> bodyData = newSectionData(bodySize); + + // This theoretically can be either 32b or 64b, but writing just the first 32b + // is good enough + const uint32_t *ptrProtoCount = reinterpret_cast<const uint32_t *>( + bodyData.data() + protocolListHeaderLayout.protocolCountOffset); + + *const_cast<uint32_t *>(ptrProtoCount) = ptrList.allPtrs.size(); + + ConcatInputSection *listSec = make<ConcatInputSection>( + *infoCategoryWriter.catPtrListInfo.inputSection, bodyData, + infoCategoryWriter.catPtrListInfo.align); + listSec->parent = infoCategoryWriter.catPtrListInfo.outputSection; + listSec->live = true; + addInputSection(listSec); + + listSec->parent = infoCategoryWriter.catPtrListInfo.outputSection; + + std::string symName = ptrList.categoryPrefix; + symName += extInfo.baseClassName + "_$_(" + extInfo.mergedContainerName + ")"; + + Defined *ptrListSym = make<Defined>( + newStringData(symName.c_str()), /*file=*/parentSym->getObjectFile(), + listSec, /*value=*/0, bodyData.size(), /*isWeakDef=*/false, + /*isExternal=*/false, /*isPrivateExtern=*/false, /*includeInSymtab=*/true, + /*isReferencedDynamically=*/false, /*noDeadStrip=*/false, + /*isWeakDefCanBeHidden=*/false); + + ptrListSym->used = true; + parentSym->getObjectFile()->symbols.push_back(ptrListSym); + + createSymbolReference(parentSym, ptrListSym, linkAtOffset, + infoCategoryWriter.catBodyInfo.relocTemplate); + + uint32_t offset = protocolListHeaderLayout.totalSize; + for (Symbol *symbol : ptrList.allPtrs) { + createSymbolReference(ptrListSym, symbol, offset, + infoCategoryWriter.catPtrListInfo.relocTemplate); + offset += target->wordSize; + } +} + +// Generate a pointer list (including header) and link it into the parent at the +// specified offset. This is used for instance and class methods and +// proprieties. +void ObjcCategoryMerger::emitAndLinkPointerList( + Defined *parentSym, uint32_t linkAtOffset, + const ClassExtensionInfo &extInfo, const PointerListInfo &ptrList) { + if (ptrList.allPtrs.empty()) + return; + + assert(ptrList.allPtrs.size() * target->wordSize == + ptrList.structCount * ptrList.structSize); + + // Generate body + uint32_t bodySize = + listHeaderLayout.totalSize + (ptrList.structSize * ptrList.structCount); + llvm::ArrayRef<uint8_t> bodyData = newSectionData(bodySize); + + const uint32_t *ptrStructSize = reinterpret_cast<const uint32_t *>( + bodyData.data() + listHeaderLayout.structSizeOffset); + const uint32_t *ptrStructCount = reinterpret_cast<const uint32_t *>( + bodyData.data() + listHeaderLayout.structCountOffset); + + *const_cast<uint32_t *>(ptrStructSize) = ptrList.structSize; + *const_cast<uint32_t *>(ptrStructCount) = ptrList.structCount; + + ConcatInputSection *listSec = make<ConcatInputSection>( + *infoCategoryWriter.catPtrListInfo.inputSection, bodyData, + infoCategoryWriter.catPtrListInfo.align); + listSec->parent = infoCategoryWriter.catPtrListInfo.outputSection; + listSec->live = true; + addInputSection(listSec); + + listSec->parent = infoCategoryWriter.catPtrListInfo.outputSection; + + std::string symName = ptrList.categoryPrefix; + symName += extInfo.baseClassName + "_$_" + extInfo.mergedContainerName; + + Defined *ptrListSym = make<Defined>( + newStringData(symName.c_str()), /*file=*/parentSym->getObjectFile(), + listSec, /*value=*/0, bodyData.size(), /*isWeakDef=*/false, + /*isExternal=*/false, /*isPrivateExtern=*/false, /*includeInSymtab=*/true, + /*isReferencedDynamically=*/false, /*noDeadStrip=*/false, + /*isWeakDefCanBeHidden=*/false); + + ptrListSym->used = true; + parentSym->getObjectFile()->symbols.push_back(ptrListSym); + + createSymbolReference(parentSym, ptrListSym, linkAtOffset, + infoCategoryWriter.catBodyInfo.relocTemplate); + + uint32_t offset = listHeaderLayout.totalSize; + for (Symbol *symbol : ptrList.allPtrs) { + createSymbolReference(ptrListSym, symbol, offset, + infoCategoryWriter.catPtrListInfo.relocTemplate); + offset += target->wordSize; + } +} + +// This method creates an __objc_catlist ConcatInputSection with a single slot +Defined * +ObjcCategoryMerger::emitCatListEntrySec(const std::string &forCateogryName, + const std::string &forBaseClassName, + ObjFile *objFile) { + uint32_t sectionSize = target->wordSize; + llvm::ArrayRef<uint8_t> bodyData = newSectionData(sectionSize); + + ConcatInputSection *newCatList = + make<ConcatInputSection>(*infoCategoryWriter.catListInfo.inputSection, + bodyData, infoCategoryWriter.catListInfo.align); + newCatList->parent = infoCategoryWriter.catListInfo.outputSection; + newCatList->live = true; + addInputSection(newCatList); + + newCatList->parent = infoCategoryWriter.catListInfo.outputSection; + + std::string catSymName = "<__objc_catlist slot for merged category "; + catSymName += forBaseClassName + "(" + forCateogryName + ")>"; + + Defined *catListSym = make<Defined>( + newStringData(catSymName.c_str()), /*file=*/objFile, newCatList, + /*value=*/0, bodyData.size(), /*isWeakDef=*/false, /*isExternal=*/false, + /*isPrivateExtern=*/false, /*includeInSymtab=*/false, + /*isReferencedDynamically=*/false, /*noDeadStrip=*/false, + /*isWeakDefCanBeHidden=*/false); + + catListSym->used = true; + objFile->symbols.push_back(catListSym); + return catListSym; +} + +// Here we generate the main category body and link the name and base class into +// it. We don't link any other info yet like the protocol and class/instance +// methods/props. +Defined *ObjcCategoryMerger::emitCategoryBody(const std::string &name, + const Defined *nameSym, + const Symbol *baseClassSym, + const std::string &baseClassName, + ObjFile *objFile) { + llvm::ArrayRef<uint8_t> bodyData = newSectionData(catLayout.totalSize); + + uint32_t *ptrSize = (uint32_t *)(const_cast<uint8_t *>(bodyData.data()) + + catLayout.sizeOffset); + *ptrSize = catLayout.totalSize; + + ConcatInputSection *newBodySec = + make<ConcatInputSection>(*infoCategoryWriter.catBodyInfo.inputSection, + bodyData, infoCategoryWriter.catBodyInfo.align); + newBodySec->parent = infoCategoryWriter.catBodyInfo.outputSection; + newBodySec->live = true; + addInputSection(newBodySec); + + std::string symName = + objc::symbol_names::category + baseClassName + "_$_(" + name + ")"; + Defined *catBodySym = make<Defined>( + newStringData(symName.c_str()), /*file=*/objFile, newBodySec, + /*value=*/0, bodyData.size(), /*isWeakDef=*/false, /*isExternal=*/false, + /*isPrivateExtern=*/false, /*includeInSymtab=*/true, + /*isReferencedDynamically=*/false, /*noDeadStrip=*/false, + /*isWeakDefCanBeHidden=*/false); + + catBodySym->used = true; + objFile->symbols.push_back(catBodySym); + + createSymbolReference(catBodySym, nameSym, catLayout.nameOffset, + infoCategoryWriter.catBodyInfo.relocTemplate); + + // Create a reloc to the base class (either external or internal) + createSymbolReference(catBodySym, baseClassSym, catLayout.klassOffset, + infoCategoryWriter.catBodyInfo.relocTemplate); + + return catBodySym; +} + +// This writes the new category name (for the merged category) into the binary +// and returns the sybmol for it. +Defined *ObjcCategoryMerger::emitCategoryName(const std::string &name, + ObjFile *objFile) { + StringRef nameStrData = newStringData(name.c_str()); + // We use +1 below to include the null terminator + llvm::ArrayRef<uint8_t> nameData( + reinterpret_cast<const uint8_t *>(nameStrData.data()), + nameStrData.size() + 1); + + auto *parentSection = infoCategoryWriter.catNameInfo.inputSection; + CStringInputSection *newStringSec = make<CStringInputSection>( + *infoCategoryWriter.catNameInfo.inputSection, nameData, + infoCategoryWriter.catNameInfo.align, /*dedupLiterals=*/true); + + parentSection->subsections.push_back({0, newStringSec}); + + newStringSec->splitIntoPieces(); + newStringSec->pieces[0].live = true; + newStringSec->parent = infoCategoryWriter.catNameInfo.outputSection; + in.cStringSection->addInput(newStringSec); + assert(newStringSec->pieces.size() == 1); + + Defined *catNameSym = make<Defined>( + "<merged category name>", /*file=*/objFile, newStringSec, + /*value=*/0, nameData.size(), + /*isWeakDef=*/false, /*isExternal=*/false, /*isPrivateExtern=*/false, + /*includeInSymtab=*/false, /*isReferencedDynamically=*/false, + /*noDeadStrip=*/false, /*isWeakDefCanBeHidden=*/false); + + catNameSym->used = true; + objFile->symbols.push_back(catNameSym); + return catNameSym; +} + +// This method fully creates a new category from the given ClassExtensionInfo. +// It creates the category name, body and method/protocol/prop lists and links +// them all together. Then it creates a new __objc_catlist entry and adds the +// category to it. Calling this method will fully generate a category which will +// be available in the final binary. +Defined *ObjcCategoryMerger::emitCategory(const ClassExtensionInfo &extInfo) { + Defined *catNameSym = emitCategoryName(extInfo.mergedContainerName, + extInfo.objFileForMergeData); + + Defined *catBodySym = emitCategoryBody( + extInfo.mergedContainerName, catNameSym, extInfo.baseClass, + extInfo.baseClassName, extInfo.objFileForMergeData); + + Defined *catListSym = + emitCatListEntrySec(extInfo.mergedContainerName, extInfo.baseClassName, + extInfo.objFileForMergeData); + + // Add the single category body to the category list at the offset 0. + createSymbolReference(catListSym, catBodySym, /*offset=*/0, + infoCategoryWriter.catListInfo.relocTemplate); + + emitAndLinkPointerList(catBodySym, catLayout.instanceMethodsOffset, extInfo, + extInfo.instanceMethods); + + emitAndLinkPointerList(catBodySym, catLayout.classMethodsOffset, extInfo, + extInfo.classMethods); + + emitAndLinkProtocolList(catBodySym, catLayout.protocolsOffset, extInfo, + extInfo.protocols); + + emitAndLinkPointerList(catBodySym, catLayout.instancePropsOffset, extInfo, + extInfo.instanceProps); + + emitAndLinkPointerList(catBodySym, catLayout.classPropsOffset, extInfo, + extInfo.classProps); + + return catBodySym; +} + +// This method merges all the categories (sharing a base class) into a single +// category. +void ObjcCategoryMerger::mergeCategoriesIntoSingleCategory( + std::vector<InfoInputCategory> &categories) { + assert(categories.size() > 1 && "Expected at least 2 categories"); + + ClassExtensionInfo extInfo(catLayout); + + for (auto &catInfo : categories) + parseCatInfoToExtInfo(catInfo, extInfo); + + Defined *newCatDef = emitCategory(extInfo); + assert(newCatDef && "Failed to create a new category"); + + // Suppress unsuded var warning + (void)newCatDef; + + for (auto &catInfo : categories) + catInfo.wasMerged = true; +} + +void ObjcCategoryMerger::createSymbolReference(Defined *refFrom, + const Symbol *refTo, + uint32_t offset, + const Reloc &relocTemplate) { + Reloc r = relocTemplate; + r.offset = offset; + r.addend = 0; + r.referent = const_cast<Symbol *>(refTo); + refFrom->isec->relocs.push_back(r); +} + +void ObjcCategoryMerger::collectAndValidateCategoriesData() { + for (InputSection *sec : allInputSections) { + if (sec->getName() != section_names::objcCatList) + continue; + ConcatInputSection *catListCisec = dyn_cast<ConcatInputSection>(sec); + assert(catListCisec && + "__objc_catList InputSection is not a ConcatInputSection"); + + for (uint32_t off = 0; off < catListCisec->getSize(); + off += target->wordSize) { + Defined *categorySym = tryGetDefinedAtIsecOffset(catListCisec, off); + assert(categorySym && + "Failed to get a valid cateogry at __objc_catlit offset"); + + // We only support ObjC categories (no swift + @objc) + // TODO: Support swift + @objc categories also + if (!categorySym->getName().starts_with(objc::symbol_names::category)) + continue; + + auto *catBodyIsec = dyn_cast<ConcatInputSection>(categorySym->isec); + assert(catBodyIsec && + "Category data section is not an ConcatInputSection"); + + // Check that the category has a reloc at 'klassOffset' (which is + // a pointer to the class symbol) + + Symbol *classSym = + tryGetSymbolAtIsecOffset(catBodyIsec, catLayout.klassOffset); + assert(classSym && "Category does not have a valid base class"); + + InfoInputCategory catInputInfo{catListCisec, catBodyIsec, off}; + categoryMap[classSym].push_back(catInputInfo); + + collectCategoryWriterInfoFromCategory(catInputInfo); + } + } +} + +// In the input we have multiple __objc_catlist InputSection, each of which may +// contain links to multiple categories. Of these categories, we will merge (and +// erase) only some. There will be some categories that will remain untouched +// (not erased). For these not erased categories, we generate new __objc_catlist +// entries since the parent __objc_catlist entry will be erased +void ObjcCategoryMerger::generateCatListForNonErasedCategories( + const std::map<ConcatInputSection *, std::set<uint64_t>> + catListToErasedOffsets) { + + // Go through all offsets of all __objc_catlist's that we process and if there + // are categories that we didn't process - generate a new __objc_catlist for + // each. + for (auto &mapEntry : catListToErasedOffsets) { + ConcatInputSection *catListIsec = mapEntry.first; + for (uint32_t catListIsecOffset = 0; + catListIsecOffset < catListIsec->data.size(); + catListIsecOffset += target->wordSize) { + // This slot was erased, we can just skip it + if (mapEntry.second.count(catListIsecOffset)) + continue; + + Defined *nonErasedCatBody = + tryGetDefinedAtIsecOffset(catListIsec, catListIsecOffset); + assert(nonErasedCatBody && "Failed to relocate non-deleted category"); + + // Allocate data for the new __objc_catlist slot + auto bodyData = newSectionData(target->wordSize); + + // We mark the __objc_catlist slot as belonging to the same file as the + // category + ObjFile *objFile = dyn_cast<ObjFile>(nonErasedCatBody->getFile()); + + ConcatInputSection *listSec = make<ConcatInputSection>( + *infoCategoryWriter.catListInfo.inputSection, bodyData, + infoCategoryWriter.catListInfo.align); + listSec->parent = infoCategoryWriter.catListInfo.outputSection; + listSec->live = true; + addInputSection(listSec); + + std::string slotSymName = "<__objc_catlist slot for category "; + slotSymName += nonErasedCatBody->getName(); + slotSymName += ">"; + + Defined *catListSlotSym = make<Defined>( + newStringData(slotSymName.c_str()), /*file=*/objFile, listSec, + /*value=*/0, bodyData.size(), + /*isWeakDef=*/false, /*isExternal=*/false, /*isPrivateExtern=*/false, + /*includeInSymtab=*/false, /*isReferencedDynamically=*/false, + /*noDeadStrip=*/false, /*isWeakDefCanBeHidden=*/false); + + catListSlotSym->used = true; + objFile->symbols.push_back(catListSlotSym); + + // Now link the category body into the newly created slot + createSymbolReference(catListSlotSym, nonErasedCatBody, 0, + infoCategoryWriter.catListInfo.relocTemplate); + } + } +} + +void ObjcCategoryMerger::eraseISec(ConcatInputSection *isec) { + isec->live = false; + for (auto &sym : isec->symbols) + sym->used = false; +} + +// This fully erases the merged categories, including their body, their names, +// their method/protocol/prop lists and the __objc_catlist entries that link to +// them. +void ObjcCategoryMerger::eraseMergedCategories() { + // Map of InputSection to a set of offsets of the categories that were merged + std::map<ConcatInputSection *, std::set<uint64_t>> catListToErasedOffsets; + + for (auto &mapEntry : categoryMap) { + for (InfoInputCategory &catInfo : mapEntry.second) { + if (catInfo.wasMerged) { + eraseISec(catInfo.catListIsec); + catListToErasedOffsets[catInfo.catListIsec].insert( + catInfo.offCatListIsec); + } + } + } + + // If there were categories that we did not erase, we need to generate a new + // __objc_catList that contains only the un-merged categories, and get rid of + // the references to the ones we merged. + generateCatListForNonErasedCategories(catListToErasedOffsets); + + // Erase the old method lists & names of the categories that were merged + for (auto &mapEntry : categoryMap) { + for (InfoInputCategory &catInfo : mapEntry.second) { + if (!catInfo.wasMerged) + continue; + + eraseISec(catInfo.catBodyIsec); + tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec, catLayout.nameOffset); + tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec, + catLayout.instanceMethodsOffset); + tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec, + catLayout.classMethodsOffset); + tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec, + catLayout.protocolsOffset); + tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec, + catLayout.classPropsOffset); + tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec, + catLayout.instancePropsOffset); + } + } +} + +void ObjcCategoryMerger::doMerge() { + collectAndValidateCategoriesData(); + + for (auto &entry : categoryMap) + if (entry.second.size() > 1) + // Merge all categories into a new, single category + mergeCategoriesIntoSingleCategory(entry.second); + + // Erase all categories that were merged + eraseMergedCategories(); +} + +void ObjcCategoryMerger::doCleanup() { generatedSectionData.clear(); } + +StringRef ObjcCategoryMerger::newStringData(const char *str) { + uint32_t len = strlen(str); + uint32_t bufSize = len + 1; + auto &data = newSectionData(bufSize); + char *strData = reinterpret_cast<char *>(data.data()); + // Copy the string chars and null-terminator + memcpy(strData, str, bufSize); + return StringRef(strData, len); +} + +SmallVector<uint8_t> &ObjcCategoryMerger::newSectionData(uint32_t size) { + generatedSectionData.push_back( + std::make_unique<SmallVector<uint8_t>>(size, 0)); + return *generatedSectionData.back(); +} + +} // namespace + +void objc::mergeCategories() { + TimeTraceScope timeScope("ObjcCategoryMerger"); + + ObjcCategoryMerger merger(inputSections); + merger.doMerge(); +} + +void objc::doCleanup() { ObjcCategoryMerger::doCleanup(); } diff --git a/lld/MachO/ObjC.h b/lld/MachO/ObjC.h index 4c65f9a1f788123faaaab3464d3cf32fcd702e87..8081605670c5196db0421bbed749fa6858db597a 100644 --- a/lld/MachO/ObjC.h +++ b/lld/MachO/ObjC.h @@ -17,14 +17,28 @@ namespace objc { namespace symbol_names { constexpr const char klass[] = "_OBJC_CLASS_$_"; +constexpr const char klassPropList[] = "__OBJC_$_CLASS_PROP_LIST_"; + constexpr const char metaclass[] = "_OBJC_METACLASS_$_"; constexpr const char ehtype[] = "_OBJC_EHTYPE_$_"; constexpr const char ivar[] = "_OBJC_IVAR_$_"; +constexpr const char instanceMethods[] = "__OBJC_$_INSTANCE_METHODS_"; +constexpr const char classMethods[] = "__OBJC_$_CLASS_METHODS_"; +constexpr const char listProprieties[] = "__OBJC_$_PROP_LIST_"; + +constexpr const char category[] = "__OBJC_$_CATEGORY_"; +constexpr const char categoryInstanceMethods[] = + "__OBJC_$_CATEGORY_INSTANCE_METHODS_"; +constexpr const char categoryClassMethods[] = + "__OBJC_$_CATEGORY_CLASS_METHODS_"; +constexpr const char categoryProtocols[] = "__OBJC_CATEGORY_PROTOCOLS_$_"; } // namespace symbol_names // Check for duplicate method names within related categories / classes. void checkCategories(); +void mergeCategories(); +void doCleanup(); } // namespace objc bool hasObjCSection(llvm::MemoryBufferRef); diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td index a524e4a4c508412ade60a72d95738851501e72d1..11458d92b3abe0ea09313506126ecb4d02de0361 100644 --- a/lld/MachO/Options.td +++ b/lld/MachO/Options.td @@ -129,6 +129,12 @@ def strict_auto_link : Flag<["--"], "strict-auto-link">, def check_category_conflicts : Flag<["--"], "check-category-conflicts">, HelpText<"Check for conflicts between category & class methods">, Group<grp_lld>; +def objc_category_merging : Flag<["-"], "objc_category_merging">, + HelpText<"Merge Objective-C categories that share the same base class">, + Group<grp_lld>; +def no_objc_category_merging : Flag<["-"], "no_objc_category_merging">, + HelpText<"Do not merge Objective-C categories">, + Group<grp_lld>; def lto_debug_pass_manager: Flag<["--"], "lto-debug-pass-manager">, HelpText<"Debug new pass manager">, Group<grp_lld>; def cs_profile_generate: Flag<["--"], "cs-profile-generate">, @@ -966,10 +972,6 @@ def interposable_list : Separate<["-"], "interposable_list">, def no_function_starts : Flag<["-"], "no_function_starts">, HelpText<"Do not create table of function start addresses">, Group<grp_rare>; -def no_objc_category_merging : Flag<["-"], "no_objc_category_merging">, - HelpText<"Do not merge Objective-C categories into their classes">, - Flags<[HelpHidden]>, - Group<grp_rare>; def object_path_lto : Separate<["-"], "object_path_lto">, MetaVarName<"<path>">, HelpText<"Retain any temporary mach-o file in <path> that would otherwise be deleted during LTO">, @@ -1282,6 +1284,12 @@ def fixup_chains_section : Flag<["-"], "fixup_chains_section">, HelpText<"This option is undocumented in ld64">, Flags<[HelpHidden]>, Group<grp_undocumented>; +def objc_relative_method_lists : Flag<["-"], "objc_relative_method_lists">, + HelpText<"Emit relative method lists (more compact representation)">, + Group<grp_undocumented>; +def no_objc_relative_method_lists : Flag<["-"], "no_objc_relative_method_lists">, + HelpText<"Don't emit relative method lists (use traditional representation)">, + Group<grp_undocumented>; def flto_codegen_only : Flag<["-"], "flto-codegen-only">, HelpText<"This option is undocumented in ld64">, Flags<[HelpHidden]>, @@ -1405,3 +1413,9 @@ def debug_variant : Flag<["-"], "debug_variant">, HelpText<"Do not warn about issues that are only problems for binaries shipping to customers.">, Flags<[HelpHidden]>, Group<grp_ignored_silently>; + +// NOTE: This flag should be respected if -warn_duplicate_libraries is ever implemented. +def no_warn_duplicate_libraries : Flag<["-"], "no_warn_duplicate_libraries">, + HelpText<"Do not warn if the input contains duplicate library options.">, + Flags<[HelpHidden]>, + Group<grp_ignored_silently>; diff --git a/lld/MachO/SymbolTable.cpp b/lld/MachO/SymbolTable.cpp index 825242f2cc72ff62bec743aec105afcee79f9ed2..755ff270e2f7a9c47b80ba9b3c0d4310074c7a92 100644 --- a/lld/MachO/SymbolTable.cpp +++ b/lld/MachO/SymbolTable.cpp @@ -377,7 +377,7 @@ static void handleSectionBoundarySymbol(const Undefined &sym, StringRef segSect, // live. Marking the isec live ensures an OutputSection is created that the // start/end symbol can refer to. assert(sym.isLive()); - isec->live = true; + assert(isec->live); // This runs after gatherInputSections(), so need to explicitly set parent // and add to inputSections. diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp index 7ee3261ce3075f70f837dc001360f6f8e78335b8..6f6b66118b7a9445a7019169ef38704ba257e492 100644 --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -12,6 +12,7 @@ #include "ExportTrie.h" #include "InputFiles.h" #include "MachOStructs.h" +#include "ObjC.h" #include "OutputSegment.h" #include "SymbolTable.h" #include "Symbols.h" @@ -793,7 +794,7 @@ void StubHelperSection::setUp() { in.imageLoaderCache->parent = ConcatOutputSection::getOrCreateForInput(in.imageLoaderCache); - inputSections.push_back(in.imageLoaderCache); + addInputSection(in.imageLoaderCache); // Since this isn't in the symbol table or in any input file, the noDeadStrip // argument doesn't matter. dyldPrivate = @@ -806,10 +807,9 @@ void StubHelperSection::setUp() { dyldPrivate->used = true; } -ObjCSelRefsSection::ObjCSelRefsSection() - : SyntheticSection(segment_names::data, section_names::objcSelrefs) {} - -void ObjCSelRefsSection::initialize() { +llvm::DenseMap<llvm::CachedHashStringRef, ConcatInputSection *> + ObjCSelRefsHelper::methnameToSelref; +void ObjCSelRefsHelper::initialize() { // Do not fold selrefs without ICF. if (config->icfLevel == ICFLevel::none) return; @@ -836,7 +836,9 @@ void ObjCSelRefsSection::initialize() { } } -ConcatInputSection *ObjCSelRefsSection::makeSelRef(StringRef methname) { +void ObjCSelRefsHelper::cleanup() { methnameToSelref.clear(); } + +ConcatInputSection *ObjCSelRefsHelper::makeSelRef(StringRef methname) { auto methnameOffset = in.objcMethnameSection->getStringOffset(methname).outSecOff; @@ -848,20 +850,20 @@ ConcatInputSection *ObjCSelRefsSection::makeSelRef(StringRef methname) { S_LITERAL_POINTERS | S_ATTR_NO_DEAD_STRIP, ArrayRef<uint8_t>{selrefData, wordSize}, /*align=*/wordSize); - objcSelref->live = true; + assert(objcSelref->live); objcSelref->relocs.push_back({/*type=*/target->unsignedRelocType, /*pcrel=*/false, /*length=*/3, /*offset=*/0, /*addend=*/static_cast<int64_t>(methnameOffset), /*referent=*/in.objcMethnameSection->isec}); objcSelref->parent = ConcatOutputSection::getOrCreateForInput(objcSelref); - inputSections.push_back(objcSelref); + addInputSection(objcSelref); objcSelref->isFinal = true; methnameToSelref[CachedHashStringRef(methname)] = objcSelref; return objcSelref; } -ConcatInputSection *ObjCSelRefsSection::getSelRef(StringRef methname) { +ConcatInputSection *ObjCSelRefsHelper::getSelRef(StringRef methname) { auto it = methnameToSelref.find(CachedHashStringRef(methname)); if (it == methnameToSelref.end()) return nullptr; @@ -890,8 +892,8 @@ StringRef ObjCStubsSection::getMethname(Symbol *sym) { void ObjCStubsSection::addEntry(Symbol *sym) { StringRef methname = getMethname(sym); // We create a selref entry for each unique methname. - if (!in.objcSelRefs->getSelRef(methname)) - in.objcSelRefs->makeSelRef(methname); + if (!ObjCSelRefsHelper::getSelRef(methname)) + ObjCSelRefsHelper::makeSelRef(methname); auto stubSize = config->objcStubsMode == ObjCStubsMode::fast ? target->objcStubsFastSize @@ -940,7 +942,7 @@ void ObjCStubsSection::writeTo(uint8_t *buf) const { Defined *sym = symbols[i]; auto methname = getMethname(sym); - InputSection *selRef = in.objcSelRefs->getSelRef(methname); + InputSection *selRef = ObjCSelRefsHelper::getSelRef(methname); assert(selRef != nullptr && "no selref for methname"); auto selrefAddr = selRef->getVA(0); target->writeObjCMsgSendStub(buf + stubOffset, sym, in.objcStubs->addr, @@ -1974,6 +1976,241 @@ void InitOffsetsSection::setUp() { } } +ObjCMethListSection::ObjCMethListSection() + : SyntheticSection(segment_names::text, section_names::objcMethList) { + flags = S_ATTR_NO_DEAD_STRIP; + align = relativeOffsetSize; +} + +// Go through all input method lists and ensure that we have selrefs for all +// their method names. The selrefs will be needed later by ::writeTo. We need to +// create them early on here to ensure they are processed correctly by the lld +// pipeline. +void ObjCMethListSection::setUp() { + for (const ConcatInputSection *isec : inputs) { + uint32_t structSizeAndFlags = 0, structCount = 0; + readMethodListHeader(isec->data.data(), structSizeAndFlags, structCount); + uint32_t originalStructSize = structSizeAndFlags & structSizeMask; + // Method name is immediately after header + uint32_t methodNameOff = methodListHeaderSize; + + // Loop through all methods, and ensure a selref for each of them exists. + while (methodNameOff < isec->data.size()) { + const Reloc *reloc = isec->getRelocAt(methodNameOff); + assert(reloc && "Relocation expected at method list name slot"); + auto *def = dyn_cast_or_null<Defined>(reloc->referent.get<Symbol *>()); + assert(def && "Expected valid Defined at method list name slot"); + auto *cisec = cast<CStringInputSection>(def->isec); + assert(cisec && "Expected method name to be in a CStringInputSection"); + auto methname = cisec->getStringRefAtOffset(def->value); + if (!ObjCSelRefsHelper::getSelRef(methname)) + ObjCSelRefsHelper::makeSelRef(methname); + + // Jump to method name offset in next struct + methodNameOff += originalStructSize; + } + } +} + +// Calculate section size and final offsets for where InputSection's need to be +// written. +void ObjCMethListSection::finalize() { + // sectionSize will be the total size of the __objc_methlist section + sectionSize = 0; + for (ConcatInputSection *isec : inputs) { + // We can also use sectionSize as write offset for isec + assert(sectionSize == alignToPowerOf2(sectionSize, relativeOffsetSize) && + "expected __objc_methlist to be aligned by default with the " + "required section alignment"); + isec->outSecOff = sectionSize; + + isec->isFinal = true; + uint32_t relativeListSize = + computeRelativeMethodListSize(isec->data.size()); + sectionSize += relativeListSize; + + // If encoding the method list in relative offset format shrinks the size, + // then we also need to adjust symbol sizes to match the new size. Note that + // on 32bit platforms the size of the method list will remain the same when + // encoded in relative offset format. + if (relativeListSize != isec->data.size()) { + for (Symbol *sym : isec->symbols) { + assert(isa<Defined>(sym) && + "Unexpected undefined symbol in ObjC method list"); + auto *def = cast<Defined>(sym); + // There can be 0-size symbols, check if this is the case and ignore + // them. + if (def->size) { + assert( + def->size == isec->data.size() && + "Invalid ObjC method list symbol size: expected symbol size to " + "match isec size"); + def->size = relativeListSize; + } + } + } + } +} + +void ObjCMethListSection::writeTo(uint8_t *bufStart) const { + uint8_t *buf = bufStart; + for (const ConcatInputSection *isec : inputs) { + assert(buf - bufStart == long(isec->outSecOff) && + "Writing at unexpected offset"); + uint32_t writtenSize = writeRelativeMethodList(isec, buf); + buf += writtenSize; + } + assert(buf - bufStart == sectionSize && + "Written size does not match expected section size"); +} + +// Check if an InputSection is a method list. To do this we scan the +// InputSection for any symbols who's names match the patterns we expect clang +// to generate for method lists. +bool ObjCMethListSection::isMethodList(const ConcatInputSection *isec) { + const char *symPrefixes[] = {objc::symbol_names::classMethods, + objc::symbol_names::instanceMethods, + objc::symbol_names::categoryInstanceMethods, + objc::symbol_names::categoryClassMethods}; + if (!isec) + return false; + for (const Symbol *sym : isec->symbols) { + auto *def = dyn_cast_or_null<Defined>(sym); + if (!def) + continue; + for (const char *prefix : symPrefixes) { + if (def->getName().starts_with(prefix)) { + assert(def->size == isec->data.size() && + "Invalid ObjC method list symbol size: expected symbol size to " + "match isec size"); + assert(def->value == 0 && + "Offset of ObjC method list symbol must be 0"); + return true; + } + } + } + + return false; +} + +// Encode a single relative offset value. The input is the data/symbol at +// (&isec->data[inSecOff]). The output is written to (&buf[outSecOff]). +// 'createSelRef' indicates that we should not directly use the specified +// symbol, but instead get the selRef for the symbol and use that instead. +void ObjCMethListSection::writeRelativeOffsetForIsec( + const ConcatInputSection *isec, uint8_t *buf, uint32_t &inSecOff, + uint32_t &outSecOff, bool useSelRef) const { + const Reloc *reloc = isec->getRelocAt(inSecOff); + assert(reloc && "Relocation expected at __objc_methlist Offset"); + auto *def = dyn_cast_or_null<Defined>(reloc->referent.get<Symbol *>()); + assert(def && "Expected all syms in __objc_methlist to be defined"); + uint32_t symVA = def->getVA(); + + if (useSelRef) { + auto *cisec = cast<CStringInputSection>(def->isec); + auto methname = cisec->getStringRefAtOffset(def->value); + ConcatInputSection *selRef = ObjCSelRefsHelper::getSelRef(methname); + assert(selRef && "Expected all selector names to already be already be " + "present in __objc_selrefs"); + symVA = selRef->getVA(); + assert(selRef->data.size() == sizeof(target->wordSize) && + "Expected one selref per ConcatInputSection"); + } + + uint32_t currentVA = isec->getVA() + outSecOff; + uint32_t delta = symVA - currentVA; + write32le(buf + outSecOff, delta); + + // Move one pointer forward in the absolute method list + inSecOff += target->wordSize; + // Move one relative offset forward in the relative method list (32 bits) + outSecOff += relativeOffsetSize; +} + +// Write a relative method list to buf, return the size of the written +// information +uint32_t +ObjCMethListSection::writeRelativeMethodList(const ConcatInputSection *isec, + uint8_t *buf) const { + // Copy over the header, and add the "this is a relative method list" magic + // value flag + uint32_t structSizeAndFlags = 0, structCount = 0; + readMethodListHeader(isec->data.data(), structSizeAndFlags, structCount); + // Set the struct size for the relative method list + uint32_t relativeStructSizeAndFlags = + (relativeOffsetSize * pointersPerStruct) & structSizeMask; + // Carry over the old flags from the input struct + relativeStructSizeAndFlags |= structSizeAndFlags & structFlagsMask; + // Set the relative method list flag + relativeStructSizeAndFlags |= relMethodHeaderFlag; + + writeMethodListHeader(buf, relativeStructSizeAndFlags, structCount); + + assert(methodListHeaderSize + + (structCount * pointersPerStruct * target->wordSize) == + isec->data.size() && + "Invalid computed ObjC method list size"); + + uint32_t inSecOff = methodListHeaderSize; + uint32_t outSecOff = methodListHeaderSize; + + // Go through the method list and encode input absolute pointers as relative + // offsets. writeRelativeOffsetForIsec will be incrementing inSecOff and + // outSecOff + for (uint32_t i = 0; i < structCount; i++) { + // Write the name of the method + writeRelativeOffsetForIsec(isec, buf, inSecOff, outSecOff, true); + // Write the type of the method + writeRelativeOffsetForIsec(isec, buf, inSecOff, outSecOff, false); + // Write reference to the selector of the method + writeRelativeOffsetForIsec(isec, buf, inSecOff, outSecOff, false); + } + + // Expecting to have read all the data in the isec + assert(inSecOff == isec->data.size() && + "Invalid actual ObjC method list size"); + assert( + outSecOff == computeRelativeMethodListSize(inSecOff) && + "Mismatch between input & output size when writing relative method list"); + return outSecOff; +} + +// Given the size of an ObjC method list InputSection, return the size of the +// method list when encoded in relative offsets format. We can do this without +// decoding the actual data, as it can be directly inferred from the size of the +// isec. +uint32_t ObjCMethListSection::computeRelativeMethodListSize( + uint32_t absoluteMethodListSize) const { + uint32_t oldPointersSize = absoluteMethodListSize - methodListHeaderSize; + uint32_t pointerCount = oldPointersSize / target->wordSize; + assert(((pointerCount % pointersPerStruct) == 0) && + "__objc_methlist expects method lists to have multiple-of-3 pointers"); + + uint32_t newPointersSize = pointerCount * relativeOffsetSize; + uint32_t newTotalSize = methodListHeaderSize + newPointersSize; + + assert((newTotalSize <= absoluteMethodListSize) && + "Expected relative method list size to be smaller or equal than " + "original size"); + return newTotalSize; +} + +// Read a method list header from buf +void ObjCMethListSection::readMethodListHeader(const uint8_t *buf, + uint32_t &structSizeAndFlags, + uint32_t &structCount) const { + structSizeAndFlags = read32le(buf); + structCount = read32le(buf + sizeof(uint32_t)); +} + +// Write a method list header to buf +void ObjCMethListSection::writeMethodListHeader(uint8_t *buf, + uint32_t structSizeAndFlags, + uint32_t structCount) const { + write32le(buf, structSizeAndFlags); + write32le(buf + sizeof(structSizeAndFlags), structCount); +} + void macho::createSyntheticSymbols() { auto addHeaderSymbol = [](const char *name) { symtab->addSynthetic(name, in.header->isec, /*value=*/0, diff --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h index 6d85f0aea8e04ced71069a9e98b54ffdfd9f53b3..e8fadfef56d4b2a2342a4ea05bafc763792888aa 100644 --- a/lld/MachO/SyntheticSections.h +++ b/lld/MachO/SyntheticSections.h @@ -315,24 +315,16 @@ public: Defined *dyldPrivate = nullptr; }; -class ObjCSelRefsSection final : public SyntheticSection { +class ObjCSelRefsHelper { public: - ObjCSelRefsSection(); - void initialize(); - - // This SyntheticSection does not do directly write data to the output, it is - // just a placeholder for easily creating SyntheticInputSection's which will - // be inserted into inputSections and handeled by the default writing - // mechanism. - uint64_t getSize() const override { return 0; } - bool isNeeded() const override { return false; } - void writeTo(uint8_t *buf) const override {} + static void initialize(); + static void cleanup(); - ConcatInputSection *getSelRef(StringRef methname); - ConcatInputSection *makeSelRef(StringRef methname); + static ConcatInputSection *getSelRef(StringRef methname); + static ConcatInputSection *makeSelRef(StringRef methname); private: - llvm::DenseMap<llvm::CachedHashStringRef, ConcatInputSection *> + static llvm::DenseMap<llvm::CachedHashStringRef, ConcatInputSection *> methnameToSelref; }; @@ -692,6 +684,54 @@ private: std::vector<ConcatInputSection *> sections; }; +// This SyntheticSection is for the __objc_methlist section, which contains +// relative method lists if the -objc_relative_method_lists option is enabled. +class ObjCMethListSection final : public SyntheticSection { +public: + ObjCMethListSection(); + + static bool isMethodList(const ConcatInputSection *isec); + void addInput(ConcatInputSection *isec) { inputs.push_back(isec); } + std::vector<ConcatInputSection *> getInputs() { return inputs; } + + void setUp(); + void finalize() override; + bool isNeeded() const override { return !inputs.empty(); } + uint64_t getSize() const override { return sectionSize; } + void writeTo(uint8_t *bufStart) const override; + +private: + void readMethodListHeader(const uint8_t *buf, uint32_t &structSizeAndFlags, + uint32_t &structCount) const; + void writeMethodListHeader(uint8_t *buf, uint32_t structSizeAndFlags, + uint32_t structCount) const; + uint32_t computeRelativeMethodListSize(uint32_t absoluteMethodListSize) const; + void writeRelativeOffsetForIsec(const ConcatInputSection *isec, uint8_t *buf, + uint32_t &inSecOff, uint32_t &outSecOff, + bool useSelRef) const; + uint32_t writeRelativeMethodList(const ConcatInputSection *isec, + uint8_t *buf) const; + + static constexpr uint32_t methodListHeaderSize = + /*structSizeAndFlags*/ sizeof(uint32_t) + + /*structCount*/ sizeof(uint32_t); + // Relative method lists are supported only for 3-pointer method lists + static constexpr uint32_t pointersPerStruct = 3; + // The runtime identifies relative method lists via this magic value + static constexpr uint32_t relMethodHeaderFlag = 0x80000000; + // In the method list header, the first 2 bytes are the size of struct + static constexpr uint32_t structSizeMask = 0x0000FFFF; + // In the method list header, the last 2 bytes are the flags for the struct + static constexpr uint32_t structFlagsMask = 0xFFFF0000; + // Relative method lists have 4 byte alignment as all data in the InputSection + // is 4 byte + static constexpr uint32_t relativeOffsetSize = sizeof(uint32_t); + + // The output size of the __objc_methlist section, computed during finalize() + uint32_t sectionSize = 0; + std::vector<ConcatInputSection *> inputs; +}; + // Chained fixups are a replacement for classic dyld opcodes. In this format, // most of the metadata necessary for binding symbols and rebasing addresses is // stored directly in the memory location that will have the fixup applied. @@ -813,12 +853,12 @@ struct InStruct { LazyPointerSection *lazyPointers = nullptr; StubsSection *stubs = nullptr; StubHelperSection *stubHelper = nullptr; - ObjCSelRefsSection *objcSelRefs = nullptr; ObjCStubsSection *objcStubs = nullptr; UnwindInfoSection *unwindInfo = nullptr; ObjCImageInfoSection *objCImageInfo = nullptr; ConcatInputSection *imageLoaderCache = nullptr; InitOffsetsSection *initOffsets = nullptr; + ObjCMethListSection *objcMethList = nullptr; ChainedFixupsSection *chainedFixups = nullptr; }; diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp index 8f335188e12c7bf92c80edaeb30e8db7c0ec8fa3..1c054912551e3e1c0f9f9fbc43806fe8c7dacce2 100644 --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -720,7 +720,7 @@ static void addNonWeakDefinition(const Defined *defined) { void Writer::scanSymbols() { TimeTraceScope timeScope("Scan symbols"); - in.objcSelRefs->initialize(); + ObjCSelRefsHelper::initialize(); for (Symbol *sym : symtab->getSymbols()) { if (auto *defined = dyn_cast<Defined>(sym)) { if (!defined->isLive()) @@ -1292,6 +1292,8 @@ template <class LP> void Writer::run() { scanSymbols(); if (in.objcStubs->isNeeded()) in.objcStubs->setUp(); + if (in.objcMethList->isNeeded()) + in.objcMethList->setUp(); scanRelocations(); if (in.initOffsets->isNeeded()) in.initOffsets->setUp(); @@ -1359,11 +1361,11 @@ void macho::createSyntheticSections() { in.got = make<GotSection>(); in.tlvPointers = make<TlvPointerSection>(); in.stubs = make<StubsSection>(); - in.objcSelRefs = make<ObjCSelRefsSection>(); in.objcStubs = make<ObjCStubsSection>(); in.unwindInfo = makeUnwindInfoSection(); in.objCImageInfo = make<ObjCImageInfoSection>(); in.initOffsets = make<InitOffsetsSection>(); + in.objcMethList = make<ObjCMethListSection>(); // This section contains space for just a single word, and will be used by // dyld to cache an address to the image loader it uses. @@ -1373,9 +1375,7 @@ void macho::createSyntheticSections() { segment_names::data, section_names::data, S_REGULAR, ArrayRef<uint8_t>{arr, target->wordSize}, /*align=*/target->wordSize); - // References from dyld are not visible to us, so ensure this section is - // always treated as live. - in.imageLoaderCache->live = true; + assert(in.imageLoaderCache->live); } OutputSection *macho::firstTLVDataSection = nullptr; diff --git a/lld/MinGW/Driver.cpp b/lld/MinGW/Driver.cpp index efd643f9a32203cb9a1cfde1b162d27d7e1956c5..bb08c77b2e11d49fc479cd35452ceecd7de031cb 100644 --- a/lld/MinGW/Driver.cpp +++ b/lld/MinGW/Driver.cpp @@ -455,6 +455,8 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS, add("-lldemit:llvm"); if (args.hasArg(OPT_lto_emit_asm)) add("-lldemit:asm"); + if (auto *arg = args.getLastArg(OPT_lto_sample_profile)) + add("-lto-sample-profile:" + StringRef(arg->getValue())); if (auto *a = args.getLastArg(OPT_thinlto_cache_dir)) add("-lldltocache:" + StringRef(a->getValue())); diff --git a/lld/MinGW/Options.td b/lld/MinGW/Options.td index 9a0a96aac7f1c621657029dbaed79094f33b7dc5..56f67e3dd96c426a22b98af6f7068e85f2ea8efe 100644 --- a/lld/MinGW/Options.td +++ b/lld/MinGW/Options.td @@ -160,6 +160,8 @@ def lto_cs_profile_file: JJ<"lto-cs-profile-file=">, HelpText<"Context sensitive profile file path">; def lto_emit_asm: FF<"lto-emit-asm">, HelpText<"Emit assembly code">; +def lto_sample_profile: JJ<"lto-sample-profile=">, + HelpText<"Sample profile file path">; def thinlto_cache_dir: JJ<"thinlto-cache-dir=">, HelpText<"Path to ThinLTO cached object file directory">; diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1 index e759776c8d55a64673481eabbdf1f333f494ec7c..65e50e349c8cc004b5fd4cd9780edad66eab428a 100644 --- a/lld/docs/ld.lld.1 +++ b/lld/docs/ld.lld.1 @@ -378,6 +378,8 @@ Do not put read-only non-executable sections in their own segment. Do not report version scripts that refer to undefined symbols. .It Fl -no-undefined Report unresolved symbols even if the linker is creating a shared library. +.It Fl -no-warn-mismatch +Do not reject unknown section types. .It Fl -no-warn-symbol-ordering Do not warn about problems with the symbol ordering file or call graph profile. .It Fl -no-warnings , Fl w diff --git a/lld/test/COFF/Inputs/lto-sample-profile.prof b/lld/test/COFF/Inputs/lto-sample-profile.prof new file mode 100644 index 0000000000000000000000000000000000000000..0ccd747bd376f84e36ac197df3aaeacbc69e568b --- /dev/null +++ b/lld/test/COFF/Inputs/lto-sample-profile.prof @@ -0,0 +1 @@ +f:0:0 diff --git a/lld/test/COFF/export.test b/lld/test/COFF/export.test index d340e0174b563e9cefeaa9cd88f0c8e7f5f85c6a..041b328dec9ca79c5b825d525eefec0db919e653 100644 --- a/lld/test/COFF/export.test +++ b/lld/test/COFF/export.test @@ -76,18 +76,55 @@ SYMTAB: exportfn3 in export.test.tmp.DLL # RUN: lld-link /out:%t.dll /dll %t.obj /export:foo=kernel32.foobar # RUN: llvm-objdump -p %t.dll | FileCheck --check-prefix=FORWARDER %s +# RUN: llvm-nm -M %t.lib | FileCheck --check-prefix=SYMTAB-FWD %s # RUN: echo "EXPORTS foo=kernel32.foobar" > %t.def -# RUN: lld-link /out:%t.dll /dll %t.obj /def:%t.def -# RUN: llvm-objdump -p %t.dll | FileCheck --check-prefix=FORWARDER %s +# RUN: lld-link /out:%t-def.dll /dll %t.obj /def:%t.def +# RUN: llvm-objdump -p %t-def.dll | FileCheck --check-prefix=FORWARDER %s +# RUN: llvm-nm -M %t-def.lib | FileCheck --check-prefix=SYMTAB-FWD %s FORWARDER: Export Table: -FORWARDER: DLL name: export.test.tmp.dll +FORWARDER: DLL name: export.test.tmp FORWARDER: Ordinal base: 1 FORWARDER: Ordinal RVA Name FORWARDER: 1 0x1010 exportfn FORWARDER: 2 foo (forwarded to kernel32.foobar) +SYMTAB-FWD: __imp_exportfn3 in export.test.tmp +SYMTAB-FWD-NEXT: __imp_foo in export.test.tmp +SYMTAB-FWD-NEXT: exportfn3 in export.test.tmp +SYMTAB-FWD-NEXT: foo in export.test.tmp + +# RUN: lld-link /out:%t-fwd-priv.dll /dll %t.obj /export:foo=kernel32.foobar,DATA,PRIVATE +# RUN: llvm-objdump -p %t-fwd-priv.dll | FileCheck --check-prefix=FORWARDER %s +# RUN: llvm-nm -M %t-fwd-priv.lib | FileCheck --check-prefix=SYMTAB-FWD-PRIV %s + +SYMTAB-FWD-PRIV: __imp_exportfn3 in export.test.tmp-fwd-priv +SYMTAB-FWD-PRIV-NOT: __imp_foo +SYMTAB-FWD-PRIV-NEXT: exportfn3 in export.test.tmp-fwd-priv +SYMTAB-FWD-PRIV-NOT: foo + +# RUN: echo "EXPORTS foo=kernel32.foobar DATA PRIVATE" > %t-fwd-priv.def +# RUN: lld-link /out:%t-fwd-priv-def.dll /dll %t.obj /def:%t-fwd-priv.def +# RUN: llvm-objdump -p %t-fwd-priv-def.dll | FileCheck --check-prefix=FORWARDER %s +# RUN: llvm-nm -M %t-fwd-priv-def.lib | FileCheck --check-prefix=SYMTAB-FWD-PRIV %s + +# RUN: lld-link /out:%t-fwd-ord.dll /dll %t.obj /export:foo=kernel32.foobar,@3,NONAME +# RUN: llvm-objdump -p %t-fwd-ord.dll | FileCheck --check-prefix=FORWARDER-ORD %s +# RUN: llvm-nm -M %t-fwd-ord.lib | FileCheck --check-prefix=SYMTAB-FWD %s + +FORWARDER-ORD: Export Table: +FORWARDER-ORD-NEXT: DLL name: export.test.tmp-fwd-ord +FORWARDER-ORD-NEXT: Ordinal base: 3 +FORWARDER-ORD-NEXT: Ordinal RVA Name +FORWARDER-ORD-NEXT: 3 (forwarded to kernel32.foobar) +FORWARDER-ORD-NEXT: 4 0x1010 exportfn3 + +# RUN: echo "EXPORTS foo=kernel32.foobar @3 NONAME" > %t-fwd-ord.def +# RUN: lld-link /out:%t-fwd-ord-def.dll /dll %t.obj /def:%t-fwd-ord.def +# RUN: llvm-objdump -p %t-fwd-ord-def.dll | FileCheck --check-prefix=FORWARDER-ORD %s +# RUN: llvm-nm -M %t-fwd-ord-def.lib | FileCheck --check-prefix=SYMTAB-FWD %s + # RUN: lld-link /out:%t.dll /dll %t.obj /merge:.rdata=.text /export:exportfn1 /export:exportfn2 # RUN: llvm-objdump -p %t.dll | FileCheck --check-prefix=MERGE --match-full-lines %s diff --git a/lld/test/COFF/exportas.test b/lld/test/COFF/exportas.test index c0295c3d7fb76d1e03f57cfda6dc3f8c61244014..d70547c39b40b4b6d7a78128c04ec25104680662 100644 --- a/lld/test/COFF/exportas.test +++ b/lld/test/COFF/exportas.test @@ -9,6 +9,77 @@ RUN: lld-link -out:out1.dll -dll -noentry test.obj test.lib RUN: llvm-readobj --coff-imports out1.dll | FileCheck --check-prefix=IMPORT %s IMPORT: Symbol: expfunc +Pass -export argument with EXPORTAS. + +RUN: llvm-mc -filetype=obj -triple=x86_64-windows func.s -o func.obj +RUN: lld-link -out:out2.dll -dll -noentry func.obj -export:func,EXPORTAS,expfunc +RUN: llvm-readobj --coff-exports out2.dll | FileCheck --check-prefix=EXPORT %s +EXPORT: Name: expfunc + +RUN: llvm-readobj out2.lib | FileCheck --check-prefix=IMPLIB %s +IMPLIB: Name type: export as +IMPLIB-NEXT: Export name: expfunc +IMPLIB-NEXT: Symbol: __imp_func +IMPLIB-NEXT: Symbol: func + +Use .drectve section with EXPORTAS. + +RUN: llvm-mc -filetype=obj -triple=x86_64-windows drectve.s -o drectve.obj +RUN: lld-link -out:out3.dll -dll -noentry func.obj drectve.obj +RUN: llvm-readobj --coff-exports out3.dll | FileCheck --check-prefix=EXPORT %s +RUN: llvm-readobj out3.lib | FileCheck --check-prefix=IMPLIB %s + +Use a .def file with EXPORTAS. + +RUN: lld-link -out:out4.dll -dll -noentry func.obj -def:test.def +RUN: llvm-readobj --coff-exports out4.dll | FileCheck --check-prefix=EXPORT %s +RUN: llvm-readobj out4.lib | FileCheck --check-prefix=IMPLIB %s + +Use a .def file with EXPORTAS in a forwarding export. + +RUN: lld-link -out:out5.dll -dll -noentry func.obj -def:test2.def +RUN: llvm-readobj --coff-exports out5.dll | FileCheck --check-prefix=FORWARD-EXPORT %s +FORWARD-EXPORT: Export { +FORWARD-EXPORT-NEXT: Ordinal: 1 +FORWARD-EXPORT-NEXT: Name: expfunc +FORWARD-EXPORT-NEXT: ForwardedTo: otherdll.otherfunc +FORWARD-EXPORT-NEXT: } + +RUN: llvm-readobj out5.lib | FileCheck --check-prefix=FORWARD-IMPLIB %s +FORWARD-IMPLIB: Name type: export as +FORWARD-IMPLIB-NEXT: Export name: expfunc +FORWARD-IMPLIB-NEXT: Symbol: __imp_func +FORWARD-IMPLIB-NEXT: Symbol: func + +Pass -export argument with EXPORTAS in a forwarding export. + +RUN: lld-link -out:out6.dll -dll -noentry func.obj -export:func=otherdll.otherfunc,EXPORTAS,expfunc +RUN: llvm-readobj --coff-exports out6.dll | FileCheck --check-prefix=FORWARD-EXPORT %s +RUN: llvm-readobj out6.lib | FileCheck --check-prefix=FORWARD-IMPLIB %s + +Pass -export argument with EXPORTAS in a data export. + +RUN: lld-link -out:out7.dll -dll -noentry func.obj -export:func,DATA,@5,EXPORTAS,expfunc +RUN: llvm-readobj --coff-exports out7.dll | FileCheck --check-prefix=ORD %s +ORD: Ordinal: 5 +ORD-NEXT: Name: expfunc + +RUN: llvm-readobj out7.lib | FileCheck --check-prefix=ORD-IMPLIB %s +ORD-IMPLIB: Type: data +ORD-IMPLIB-NEXT: Name type: export as +ORD-IMPLIB-NEXT: Export name: expfunc +ORD-IMPLIB-NEXT: Symbol: __imp_func + +Check invalid EXPORTAS syntax. + +RUN: not lld-link -out:err1.dll -dll -noentry func.obj -export:func,EXPORTAS, 2>&1 | \ +RUN: FileCheck --check-prefix=ERR1 %s +ERR1: error: invalid EXPORTAS value: {{$}} + +RUN: not lld-link -out:err2.dll -dll -noentry func.obj -export:func,EXPORTAS,expfunc,DATA 2>&1 | \ +RUN: FileCheck --check-prefix=ERR2 %s +ERR2: error: invalid EXPORTAS value: expfunc,DATA + #--- test.s .section ".test", "rd" .rva __imp_func @@ -17,3 +88,20 @@ IMPORT: Symbol: expfunc LIBRARY test.dll EXPORTS func EXPORTAS expfunc + +#--- test2.def +LIBRARY test.dll +EXPORTS + func=otherdll.otherfunc EXPORTAS expfunc + +#--- func.s + .text + .globl func + .p2align 2, 0x0 +func: + movl $1, %eax + retq + +#--- drectve.s + .section .drectve, "yn" + .ascii " -export:func,EXPORTAS,expfunc" diff --git a/lld/test/COFF/lto-sample-profile.ll b/lld/test/COFF/lto-sample-profile.ll new file mode 100644 index 0000000000000000000000000000000000000000..64d4c8ab6328855edcad1a82baa4b50ff53813e9 --- /dev/null +++ b/lld/test/COFF/lto-sample-profile.ll @@ -0,0 +1,23 @@ +; REQUIRES: x86 +; RUN: opt -module-summary %s -o %t1.o +; RUN: opt -module-summary %p/Inputs/thinlto.ll -o %t2.o + +; RUN: rm -f %t1.o.4.opt.bc +; RUN: lld-link /lto-sample-profile:%p/Inputs/lto-sample-profile.prof /lldsavetemps /entry:f /subsystem:console %t1.o %t2.o /out:%t3.exe +; RUN: opt -S %t1.o.4.opt.bc | FileCheck %s + +target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc19.0.24215" + +; CHECK: ![[#]] = !{i32 1, !"ProfileSummary", ![[#]]} +declare void @g(...) + +define void @h() { + ret void +} +define void @f() { +entry: + call void (...) @g() + call void (...) @h() + ret void +} diff --git a/lld/test/ELF/aarch64-gnu-ifunc-nonpreemptable.s b/lld/test/ELF/aarch64-gnu-ifunc-nonpreemptable.s index 4f33dde9d1a9e58a4683abb3df8081d854090b2e..54a27a8cc0d9f5aa152b3cd4ef7b1ff847540450 100644 --- a/lld/test/ELF/aarch64-gnu-ifunc-nonpreemptable.s +++ b/lld/test/ELF/aarch64-gnu-ifunc-nonpreemptable.s @@ -65,14 +65,14 @@ main: # PIE-EMPTY: # PIE-NEXT: <myfunc>: # PIE-NEXT: 10270: adrp x16, 0x30000 -# PIE-NEXT: 10274: ldr x17, [x16, #896] -# PIE-NEXT: 10278: add x16, x16, #896 -# PIE-NEXT: 1027c: br x17 +# PIE-NEXT: ldr x17, [x16, #832] +# PIE-NEXT: add x16, x16, #832 +# PIE-NEXT: br x17 # PIE-RELOC: .rela.dyn { -# PIE-RELOC-NEXT: 0x30380 R_AARCH64_IRELATIVE - 0x10260 +# PIE-RELOC-NEXT: 0x30340 R_AARCH64_IRELATIVE - 0x10260 # PIE-RELOC-NEXT: } # PIE-RELOC: Hex dump of section '.got.plt': -# NO-APPLY: 0x00030380 00000000 00000000 -# APPLY: 0x00030380 60020100 00000000 +# NO-APPLY: 0x00030340 00000000 00000000 +# APPLY: 0x00030340 60020100 00000000 # PIE-RELOC-EMPTY: diff --git a/lld/test/ELF/aarch64-gnu-ifunc.s b/lld/test/ELF/aarch64-gnu-ifunc.s index dee24779d91360c34a778f75364ed3d918e89147..d76b54eabf8a4736d0dfd0147c638605576be21f 100644 --- a/lld/test/ELF/aarch64-gnu-ifunc.s +++ b/lld/test/ELF/aarch64-gnu-ifunc.s @@ -11,13 +11,12 @@ // CHECK-NEXT: Type: SHT_RELA // CHECK-NEXT: Flags [ // CHECK-NEXT: SHF_ALLOC -// CHECK-NEXT: SHF_INFO_LINK // CHECK-NEXT: ] // CHECK-NEXT: Address: [[RELA:.*]] // CHECK-NEXT: Offset: 0x158 // CHECK-NEXT: Size: 48 // CHECK-NEXT: Link: 0 -// CHECK-NEXT: Info: 4 +// CHECK-NEXT: Info: 0 // CHECK-NEXT: AddressAlignment: 8 // CHECK-NEXT: EntrySize: 24 // CHECK-NEXT: } diff --git a/lld/test/ELF/aarch64-tlsdesc-zrel.s b/lld/test/ELF/aarch64-tlsdesc-zrel.s index 1b35e0d29a26f80b55c1fabf5fbbdb21ed7d33e1..83e6894ddb3b5efe6714e5e6c1fd45e17cf71997 100644 --- a/lld/test/ELF/aarch64-tlsdesc-zrel.s +++ b/lld/test/ELF/aarch64-tlsdesc-zrel.s @@ -13,6 +13,7 @@ // RELA-NEXT: 0x[[#ADDR+16]] R_AARCH64_TLSDESC - 0x4 // RELA-NEXT: } // RELA-NEXT: ] +// RELA-EMPTY: // RELA-NEXT: Hex dump of section '.got': // RELA-NEXT: 0x000[[#ADDR]] 00000000 00000000 00000000 00000000 // RELA-NO-ADDENDS-NEXT: 0x000[[#ADDR+16]] 00000000 00000000 00000000 00000000 @@ -28,6 +29,7 @@ // REL-NEXT: 0x[[#ADDR+16]] R_AARCH64_TLSDESC -{{$}} // REL-NEXT: } // REL-NEXT: ] +// REL-EMPTY: // REL-NEXT: Hex dump of section '.got': // REL-NEXT: 0x000[[#ADDR]] 00000000 00000000 00000000 00000000 // REL-NEXT: 0x000[[#ADDR+16]] 00000000 00000000 04000000 00000000 diff --git a/lld/test/ELF/allow-multiple-definition.s b/lld/test/ELF/allow-multiple-definition.s index 492784a3601df18f18bc071d22262cd28fc521f3..96fa2627e1bf88c0624dc32cde179b53f5839627 100644 --- a/lld/test/ELF/allow-multiple-definition.s +++ b/lld/test/ELF/allow-multiple-definition.s @@ -9,6 +9,9 @@ # RUN: llvm-objdump --no-print-imm-hex -d %t3 | FileCheck %s # RUN: llvm-objdump --no-print-imm-hex -d %t4 | FileCheck --check-prefix=REVERT %s +# RUN: ld.lld --noinhibit-exec %t2 %t1 -o /dev/null 2>&1 | FileCheck %s --check-prefix=WARN +# WARN: warning: duplicate symbol: _bar + # RUN: ld.lld -z muldefs --fatal-warnings %t1 %t2 -o %t3 # RUN: ld.lld -z muldefs --fatal-warnings %t2 %t1 -o %t4 # RUN: llvm-objdump --no-print-imm-hex -d %t3 | FileCheck %s diff --git a/lld/test/ELF/allow-shlib-undefined.s b/lld/test/ELF/allow-shlib-undefined.s index 4b7151c8bc0d56f0aa4e79d1dc7910203b609053..c69c1ea20ce3b825dc6e1f8ea18aaab4088080d7 100644 --- a/lld/test/ELF/allow-shlib-undefined.s +++ b/lld/test/ELF/allow-shlib-undefined.s @@ -31,10 +31,12 @@ ## Test some cases when a relocatable object file provides a non-exported definition. # RUN: not ld.lld main.o a.so def-hidden.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=NONEXPORTED +# RUN: not ld.lld main.o def-hidden.o a.so -o /dev/null 2>&1 | FileCheck %s --check-prefix=NONEXPORTED # RUN: not ld.lld main.o a.so def-hidden.o -shared --no-allow-shlib-undefined -o /dev/null 2>&1 | FileCheck %s --check-prefix=NONEXPORTED # RUN: ld.lld main.o a.so def-hidden.o --allow-shlib-undefined --fatal-warnings -o /dev/null ## Test a relocatable object file definition that is converted to STB_LOCAL. # RUN: not ld.lld main.o a.so def-hidden.o --version-script=local.ver -o /dev/null 2>&1 | FileCheck %s --check-prefix=NONEXPORTED +# RUN: not ld.lld main.o def-hidden.o a.so --version-script=local.ver -o /dev/null 2>&1 | FileCheck %s --check-prefix=NONEXPORTED ## The section containing the definition is discarded, and we report an error. # RUN: not ld.lld --gc-sections main.o a.so def-hidden.o -o /dev/null 2>&1 | FileCheck %s diff --git a/lld/test/ELF/arm-gnu-ifunc.s b/lld/test/ELF/arm-gnu-ifunc.s index 562478256fd8e070ae08665403448d1905692964..d49ca18e991e1c149002c82f3c92dd329c90a4a8 100644 --- a/lld/test/ELF/arm-gnu-ifunc.s +++ b/lld/test/ELF/arm-gnu-ifunc.s @@ -30,13 +30,12 @@ _start: // CHECK-NEXT: Type: SHT_REL // CHECK-NEXT: Flags [ // CHECK-NEXT: SHF_ALLOC -// CHECK-NEXT: SHF_INFO_LINK // CHECK-NEXT: ] // CHECK-NEXT: Address: 0x100F4 // CHECK-NEXT: Offset: 0xF4 // CHECK-NEXT: Size: 16 // CHECK-NEXT: Link: -// CHECK-NEXT: Info: 4 +// CHECK-NEXT: Info: 0 // CHECK: Name: .iplt // CHECK-NEXT: Type: SHT_PROGBITS // CHECK-NEXT: Flags [ diff --git a/lld/test/ELF/common-gc2.s b/lld/test/ELF/common-gc2.s index fec1c4be86b5ee718babc0e62a05e886ea9f691f..1ecaef7d9af5aa600e49d6f2f3c645c5bf6a6d3a 100644 --- a/lld/test/ELF/common-gc2.s +++ b/lld/test/ELF/common-gc2.s @@ -1,7 +1,9 @@ # REQUIRES: x86 -# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t -# RUN: ld.lld -gc-sections -export-dynamic %t -o %t1 -# RUN: llvm-readobj --dyn-symbols %t1 | FileCheck %s +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o +# RUN: llvm-mc -filetype=obj -triple=x86_64 /dev/null -o %t2.o +# RUN: ld.lld -shared -soname=t2 %t2.o -o %t2.so +# RUN: ld.lld -gc-sections -export-dynamic %t.o %t2.so -o %t +# RUN: llvm-readobj --dyn-symbols %t | FileCheck %s # CHECK: Name: bar # CHECK: Name: foo diff --git a/lld/test/ELF/driver.test b/lld/test/ELF/driver.test index 260be8e8f883bbcb99d6405b158f2139ae78edcb..49deb902aa0fd87fd4d84a72544cda1cd9fd0ea0 100644 --- a/lld/test/ELF/driver.test +++ b/lld/test/ELF/driver.test @@ -3,62 +3,55 @@ # RUN: not ld.lld --unknown1 --unkn=own2 -m foo /no/such/file -lnosuchlib \ # RUN: 2>&1 | FileCheck -check-prefix=UNKNOWN %s -# UNKNOWN: unknown argument '--unknown1' -# UNKNOWN: unknown argument '--unkn=own2' -# UNKNOWN: unknown emulation: foo -# UNKNOWN: cannot open /no/such/file -# UNKNOWN: unable to find library -lnosuchlib +# UNKNOWN: error: unknown argument '--unknown1' +# UNKNOWN: error: unknown argument '--unkn=own2' +# UNKNOWN: error: unknown emulation: foo +# UNKNOWN: error: cannot open /no/such/file +# UNKNOWN: error: unable to find library -lnosuchlib # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t # RUN: not ld.lld %t -o /no/such/file 2>&1 | FileCheck -check-prefix=MISSING %s -# MISSING: cannot open output file /no/such/file +# MISSING: error: cannot open output file /no/such/file # RUN: ld.lld --help 2>&1 | FileCheck -check-prefix=HELP %s # HELP: USAGE: # HELP: : supported targets:{{.*}} elf # RUN: not ld.lld --versin 2>&1 | FileCheck -check-prefix=SPELLVERSION %s -# SPELLVERSION: unknown argument '--versin', did you mean '--version' +# SPELLVERSION: error: unknown argument '--versin', did you mean '--version' ## Attempt to link DSO with -r # RUN: ld.lld -shared %t -o %t.so # RUN: not ld.lld -r %t.so %t -o /dev/null 2>&1 | FileCheck -check-prefix=ERR %s -# ERR: attempted static link of dynamic object +# ERR: error: attempted static link of dynamic object -## Attempt to use -r and -shared together -# RUN: not ld.lld -r -shared %t -o /dev/null 2>&1 | FileCheck -check-prefix=ERR2 %s -# ERR2: -r and -shared may not be used together +# RUN: not ld.lld -r -shared -pie --export-dynamic %t -o /dev/null 2>&1 | FileCheck -check-prefix=ERR2 %s +# ERR2: error: -r and -shared may not be used together +# ERR2: error: -r and -pie may not be used together +# ERR2: error: -r and --export-dynamic may not be used together -## Attempt to use -r and --gdb-index together -# RUN: not ld.lld -r --gdb-index %t -o /dev/null 2>&1 | FileCheck -check-prefix=ERR4 %s -# ERR4: -r and --gdb-index may not be used together +# RUN: not ld.lld -r --icf=all --gdb-index %t -o /dev/null 2>&1 | FileCheck -check-prefix=ERR4 %s +# ERR4: error: -r and --gdb-index may not be used together +# ERR4: error: -r and --icf may not be used together -## Attempt to use -r and --icf together -# RUN: not ld.lld -r --icf=all %t -o /dev/null 2>&1 | FileCheck -check-prefix=ERR5 %s -# ERR5: -r and --icf may not be used together - -## Attempt to use -r and -pie together -# RUN: not ld.lld -r -pie %t -o /dev/null 2>&1 | FileCheck -check-prefix=ERR6 %s -# ERR6: -r and -pie may not be used together - -## Attempt to use -shared and -pie together # RUN: not ld.lld -shared -pie %t -o /dev/null 2>&1 | FileCheck -check-prefix=ERR7 %s -# ERR7: -shared and -pie may not be used together +# ERR7: error: -shared and -pie may not be used together ## "--output=foo" is equivalent to "-o foo". # RUN: not ld.lld %t --output=/no/such/file 2>&1 | FileCheck -check-prefix=ERR8 %s -# ERR8: cannot open output file /no/such/file +# ERR8: error: cannot open output file /no/such/file ## "-output=foo" is equivalent to "-o utput=foo". # RUN: not ld.lld %t -output=/no/such/file 2>&1 | FileCheck -check-prefix=ERR9 %s -# ERR9: cannot open output file utput=/no/such/file +# ERR9: error: cannot open output file utput=/no/such/file -# RUN: ld.lld %t -z foo -o /dev/null 2>&1 | FileCheck -check-prefix=ERR10 %s -# RUN: ld.lld %t -z foo -o /dev/null --version 2>&1 | FileCheck -check-prefix=ERR10 %s +# RUN: ld.lld %t -z foo -o /dev/null 2>&1 | FileCheck -check-prefix=ERR10 %s --implicit-check-not=warning: +# RUN: ld.lld %t -z foo -z rel -z rela -z max-page-size=1 -z common-page-size=1 -o /dev/null --version 2>&1 | \ +# RUN: FileCheck -check-prefix=ERR10 %s --implicit-check-not=warning: # ERR10: warning: unknown -z value: foo ## Check we report "unknown -z value" error even with -v. -# RUN: ld.lld %t -z foo -o /dev/null -v 2>&1 | FileCheck -check-prefix=ERR10 %s +# RUN: ld.lld %t -z foo -z rel -o /dev/null -v 2>&1 | FileCheck -check-prefix=ERR10 %s --implicit-check-not=warning: ## Note: in GNU ld, --fatal-warning still leads to a warning. # RUN: not ld.lld %t -z foo --fatal-warnings 2>&1 | FileCheck --check-prefix=ERR10-FATAL %s @@ -67,10 +60,6 @@ # RUN: not ld.lld %t -z max-page-size 2>&1 | FileCheck -check-prefix=ERR11 %s # ERR11: error: invalid max-page-size: -## Attempt to use -r and --export-dynamic together -# RUN: not ld.lld -r -export-dynamic %t -o /dev/null 2>&1 | FileCheck -check-prefix=ERR12 %s -# ERR12: -r and --export-dynamic may not be used together - .globl _start _start: nop diff --git a/lld/test/ELF/executable-undefined-ignoreall.s b/lld/test/ELF/executable-undefined-ignoreall.s index cc38e17cdf619b0154cc227ea5f21d16132aae4b..073b22bd84543a6cb3cff8dc95ce5ae70e4c72e3 100644 --- a/lld/test/ELF/executable-undefined-ignoreall.s +++ b/lld/test/ELF/executable-undefined-ignoreall.s @@ -7,8 +7,6 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o # RUN: ld.lld %t.o -o %t --unresolved-symbols=ignore-all -pie # RUN: llvm-readobj -r %t | FileCheck %s -# RUN: ld.lld %t.o -o %t --unresolved-symbols=ignore-all --export-dynamic -# RUN: llvm-readobj -r %t | FileCheck %s # CHECK: Relocations [ # CHECK-NEXT: Section ({{.*}}) .rela.plt { diff --git a/lld/test/ELF/gc-sections-with-provide.s b/lld/test/ELF/gc-sections-with-provide.s new file mode 100644 index 0000000000000000000000000000000000000000..3e5b1b1efe6ca84e4487630550173e2e9fa6af4f --- /dev/null +++ b/lld/test/ELF/gc-sections-with-provide.s @@ -0,0 +1,60 @@ +# REQUIRES: x86 + +# This test verifies that garbage-collection is correctly garbage collecting +# unused sections when the symbol of the unused section is only referred by +# an unused PROVIDE symbol. + +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o +# RUN: ld.lld -o a_nogc a.o -T script.t +# RUN: llvm-nm a_nogc | FileCheck -check-prefix=NOGC %s +# RUN: ld.lld -o a_gc a.o --gc-sections --print-gc-sections -T script.t | FileCheck --check-prefix=GC_LINK %s +# RUN: llvm-nm a_gc | FileCheck -check-prefix=GC %s + +NOGC-NOT: another_unused +NOGC: another_used +NOGC: bar +NOGC: baz +NOGC: baz_ref +NOGC: foo +NOGC-NOT: unused +NOGC: used + +GC_LINK: removing unused section a.o:(.text.bar) + +GC-NOT: another_unused +GC: another_used +GC-NOT: bar +GC: baz +GC: baz_ref +GC: foo +GC-NOT: unused +GC: used + +#--- a.s +.global _start +_start: + call foo + call used + +.section .text.foo,"ax",@progbits +foo: + nop + +.section .text.bar,"ax",@progbits +.global bar +bar: + nop + +.section .text.baz,"ax",@progbits +.global baz +baz: + nop + + +#--- script.t +PROVIDE(unused = bar + used); +PROVIDE(used = another_used); +PROVIDE(baz_ref = baz); +PROVIDE(another_used = baz_ref); +PROVIDE(another_unused = unused + bar + 0x1); diff --git a/lld/test/ELF/gnu-ifunc-dyntags.s b/lld/test/ELF/gnu-ifunc-dyntags.s index fd80dc24f2f8e8f01162e09d1bc15b57d6e51057..57a17245a3e8806225abb5238f0f2868955574d7 100644 --- a/lld/test/ELF/gnu-ifunc-dyntags.s +++ b/lld/test/ELF/gnu-ifunc-dyntags.s @@ -9,15 +9,13 @@ # CHECK: Name Size VMA # CHECK: .rela.dyn 00000030 0000000000000248 -# CHECK: .got.plt 00000010 00000000000033b0 +# CHECK: .got.plt 00000010 0000000000003370 # TAGS: Tag Type Name/Value # TAGS: 0x0000000000000007 RELA 0x248 # TAGS: 0x0000000000000008 RELASZ 48 (bytes) -# TAGS: 0x0000000000000017 JMPREL 0x0 -# TAGS: 0x0000000000000002 PLTRELSZ 0 (bytes) -# TAGS: 0x0000000000000003 PLTGOT 0x33B0 -# TAGS: 0x0000000000000014 PLTREL RELA +# TAGS-NOT: JMPREL +# TAGS-NOT: PLTREL # TAGS: Relocations [ # TAGS-NEXT: Section {{.*}} .rela.dyn { diff --git a/lld/test/ELF/gnu-ifunc-i386.s b/lld/test/ELF/gnu-ifunc-i386.s index b502fd6e9ae2d513315cd122a76f1ef90bf126b1..43b19b27ea4ec77f7b4f2c242322cac421c31092 100644 --- a/lld/test/ELF/gnu-ifunc-i386.s +++ b/lld/test/ELF/gnu-ifunc-i386.s @@ -11,13 +11,12 @@ // CHECK-NEXT: Type: SHT_REL // CHECK-NEXT: Flags [ // CHECK-NEXT: SHF_ALLOC -// CHECK-NEXT: SHF_INFO_LINK // CHECK-NEXT: ] // CHECK-NEXT: Address: [[RELA:.*]] // CHECK-NEXT: Offset: 0xD4 // CHECK-NEXT: Size: 16 // CHECK-NEXT: Link: 0 -// CHECK-NEXT: Info: 4 +// CHECK-NEXT: Info: 0 // CHECK-NEXT: AddressAlignment: 4 // CHECK-NEXT: EntrySize: 8 // CHECK-NEXT: } diff --git a/lld/test/ELF/incompatible-section-types2.s b/lld/test/ELF/incompatible-section-types2.s index 3e281ce6c5da383b4f53b2d07a30fb14f19f0521..919515fe37e39696045d2b7fb83212138a2dcc40 100644 --- a/lld/test/ELF/incompatible-section-types2.s +++ b/lld/test/ELF/incompatible-section-types2.s @@ -6,5 +6,5 @@ // CHECK-NEXT: >>> <internal>:(.shstrtab): SHT_STRTAB // CHECK-NEXT: >>> output section .shstrtab: Unknown -.section .shstrtab,"",@12345 +.section .shstrtab,"",@0x60000000 .short 20 diff --git a/lld/test/ELF/linkerscript/custom-section-type.s b/lld/test/ELF/linkerscript/custom-section-type.s index 68454f4df1c860dd417107b44b7b4c08617dffdd..8ca0a4db325bdad35a4ebe260d92ce261fcc2edf 100644 --- a/lld/test/ELF/linkerscript/custom-section-type.s +++ b/lld/test/ELF/linkerscript/custom-section-type.s @@ -76,7 +76,7 @@ SECTIONS { .section progbits,"a",@note .byte 0 -.section expr,"a",@12345 +.section expr,"a",@0x60000000 .byte 0 #--- unknown1.lds diff --git a/lld/test/ELF/linkerscript/discard-section.s b/lld/test/ELF/linkerscript/discard-section.s index 24f3b2b73e991f7dc6ef1d054a7efcd0e438a099..0bbebac59bb345b2c725a6cb0bd7022b29c7895a 100644 --- a/lld/test/ELF/linkerscript/discard-section.s +++ b/lld/test/ELF/linkerscript/discard-section.s @@ -9,6 +9,9 @@ # RUN: ld.lld -r -T a.lds a.o b.o -o a.ro 2>&1 | FileCheck %s --check-prefix=WARNING --implicit-check-not=warning: # RUN: llvm-readelf -r -s a.ro | FileCheck %s --check-prefix=RELOC +# RUN: ld.lld -r --gc-sections -T a.lds a.o b.o -o a.gc.ro --no-fatal-warnings +# RUN: llvm-readelf -r -s a.gc.ro | FileCheck %s --check-prefix=RELOC-GC + # LOCAL: error: relocation refers to a discarded section: .aaa # LOCAL-NEXT: >>> defined in a.o # LOCAL-NEXT: >>> referenced by a.o:(.bbb+0x0) @@ -32,16 +35,18 @@ # WARNING: warning: relocation refers to a discarded section: .aaa # WARNING-NEXT: >>> referenced by a.o:(.rela.bbb+0x0) +## GNU ld reports "defined in discarded secion" errors even in -r mode. +## We set the symbol index to 0. # RELOC: Relocation section '.rela.bbb' at offset {{.*}} contains 1 entries: # RELOC-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend # RELOC-NEXT: 0000000000000000 0000000000000000 R_X86_64_NONE 0 # RELOC-EMPTY: # RELOC-NEXT: Relocation section '.rela.data' at offset {{.*}} contains 4 entries: # RELOC-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend -# RELOC-NEXT: 0000000000000000 0000000500000001 R_X86_64_64 0000000000000000 global + 0 -# RELOC-NEXT: 0000000000000008 0000000700000001 R_X86_64_64 0000000000000000 weak + 0 -# RELOC-NEXT: 0000000000000010 0000000600000001 R_X86_64_64 0000000000000000 weakref1 + 0 -# RELOC-NEXT: 0000000000000018 0000000800000001 R_X86_64_64 0000000000000000 weakref2 + 0 +# RELOC-NEXT: 0000000000000000 0000000000000001 R_X86_64_64 0 +# RELOC-NEXT: 0000000000000008 0000000000000001 R_X86_64_64 0 +# RELOC-NEXT: 0000000000000010 0000000000000001 R_X86_64_64 0 +# RELOC-NEXT: 0000000000000018 0000000000000001 R_X86_64_64 0 # RELOC: Num: Value Size Type Bind Vis Ndx Name # RELOC-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND @@ -49,23 +54,25 @@ # RELOC-NEXT: 2: 0000000000000000 0 SECTION LOCAL DEFAULT 2 .bbb # RELOC-NEXT: 3: 0000000000000000 0 SECTION LOCAL DEFAULT 4 .data # RELOC-NEXT: 4: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 1 _start -# RELOC-NEXT: 5: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND global -# RELOC-NEXT: 6: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND weakref1 -# RELOC-NEXT: 7: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND weak -# RELOC-NEXT: 8: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND weakref2 # RELOC-EMPTY: +# RELOC-GC: There are no relocations in this file. + #--- a.s .globl _start _start: .section .aaa,"a" -.globl global, weakref1 +.globl global, weakref1, unused .weak weak, weakref2 global: weak: weakref1: weakref2: +## Eliminate `unused` just like GC discarded definitions. +## Linux kernel's CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y configuration expects +## that the unreferenced `unused` is not emitted to .symtab. +unused: .quad 0 .section .bbb,"aw" diff --git a/lld/test/ELF/linkerscript/symbolreferenced.s b/lld/test/ELF/linkerscript/symbolreferenced.s index ba7a7721ea969706725f35256d929c51ebf5751a..6f583d20e27641ddfec768a29a29ba9824ac969c 100644 --- a/lld/test/ELF/linkerscript/symbolreferenced.s +++ b/lld/test/ELF/linkerscript/symbolreferenced.s @@ -21,11 +21,31 @@ # RUN: ld.lld -o chain -T chain.t a.o # RUN: llvm-nm chain | FileCheck %s -# CHECK: 0000000000001000 a f1 -# CHECK-NEXT: 0000000000001000 A f2 -# CHECK-NEXT: 0000000000001000 a g1 -# CHECK-NEXT: 0000000000001000 A g2 -# CHECK-NEXT: 0000000000001000 A newsym +# CHECK-NOT: another_unused +# CHECK: 0000000000007000 a f1 +# CHECK-NEXT: 0000000000007000 A f2 +# CHECK-NEXT: 0000000000007000 A f3 +# CHECK-NEXT: 0000000000007000 A f4 +# CHECK-NEXT: 0000000000006000 A f5 +# CHECK-NEXT: 0000000000003000 A f6 +# CHECK-NEXT: 0000000000001000 A f7 +# CHECK-NOT: g1 +# CHECK-NOT: g2 +# CHECK-NEXT: 0000000000007500 A newsym +# CHECK: 0000000000002000 A u +# CHECK-NOT: unused +# CHECK-NEXT: 0000000000002000 A v +# CHECK-NEXT: 0000000000002000 A w + + +# RUN: ld.lld -o chain_with_cycle -T chain_with_cycle.t a.o +# RUN: llvm-nm chain_with_cycle | FileCheck %s --check-prefix=CHAIN_WITH_CYCLE + +# CHAIN_WITH_CYCLE: 000 A f1 +# CHAIN_WITH_CYCLE: 000 A f2 +# CHAIN_WITH_CYCLE: 000 A f3 +# CHAIN_WITH_CYCLE: 000 A f4 +# CHAIN_WITH_CYCLE: 000 A newsym # RUN: not ld.lld -T chain2.t a.o 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error: # ERR-COUNT-3: error: chain2.t:1: symbol not found: undef @@ -40,13 +60,30 @@ patatino: movl newsym, %eax #--- chain.t -PROVIDE(f2 = 0x1000); +PROVIDE(f7 = 0x1000); +PROVIDE(f5 = f6 + 0x3000); +PROVIDE(f6 = f7 + 0x2000); +PROVIDE(f4 = f5 + 0x1000); +PROVIDE(f3 = f4); +PROVIDE(f2 = f3); PROVIDE_HIDDEN(f1 = f2); -PROVIDE(newsym = f1); +PROVIDE(newsym = f1 + 0x500); + +u = v; +PROVIDE(w = 0x2000); +PROVIDE(v = w); PROVIDE(g2 = 0x1000); PROVIDE_HIDDEN(g1 = g2); PROVIDE(unused = g1); +PROVIDE_HIDDEN(another_unused = g1); + +#--- chain_with_cycle.t +PROVIDE(f1 = f2 + f3); +PROVIDE(f2 = f3 + f4); +PROVIDE(f3 = f4); +PROVIDE(f4 = f1); +PROVIDE(newsym = f1); #--- chain2.t PROVIDE(f2 = undef); diff --git a/lld/test/ELF/lto/Inputs/devirt_validate_vtable_typeinfos_ref.ll b/lld/test/ELF/lto/Inputs/devirt_validate_vtable_typeinfos_ref.ll index 43df8366aa2ae0c68e9a5531a0661f90e897ae2e..8219b8bea15754ea604caa84854c850b0bd00728 100644 --- a/lld/test/ELF/lto/Inputs/devirt_validate_vtable_typeinfos_ref.ll +++ b/lld/test/ELF/lto/Inputs/devirt_validate_vtable_typeinfos_ref.ll @@ -36,7 +36,7 @@ entry: store ptr %this, ptr %this.addr %this1 = load ptr, ptr %this.addr call void @_ZN1AC2Ev(ptr noundef nonnull align 8 dereferenceable(8) %this1) - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, inrange i32 0, i32 2), ptr %this1 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 2), ptr %this1 ret void } @@ -47,7 +47,7 @@ entry: %this.addr = alloca ptr store ptr %this, ptr %this.addr %this1 = load ptr, ptr %this.addr - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, inrange i32 0, i32 2), ptr %this1 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 2), ptr %this1 ret void } diff --git a/lld/test/ELF/lto/Inputs/devirt_validate_vtable_typeinfos_undef.ll b/lld/test/ELF/lto/Inputs/devirt_validate_vtable_typeinfos_undef.ll index 6cc55df82e2f2814b1717a0ad09c55a81030ed95..43230948116d3036f3ad0371917b7f882014ca25 100644 --- a/lld/test/ELF/lto/Inputs/devirt_validate_vtable_typeinfos_undef.ll +++ b/lld/test/ELF/lto/Inputs/devirt_validate_vtable_typeinfos_undef.ll @@ -9,7 +9,7 @@ define linkonce_odr void @_ZN1BC2Ev(ptr %this) #0 { %this.addr = alloca ptr, align 8 store ptr %this, ptr %this.addr, align 8 %this1 = load ptr, ptr %this.addr, align 8 - store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1B, i32 0, inrange i32 0, i32 2), ptr %this1, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [4 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 2), ptr %this1, align 8 ret void } diff --git a/lld/test/ELF/lto/devirt_split_unit_localize.ll b/lld/test/ELF/lto/devirt_split_unit_localize.ll index 04f30dcd76b46cd94249d01f457cf8ad7d4d7e16..fb3564b268863e34bc280f26a849d748b24b878b 100644 --- a/lld/test/ELF/lto/devirt_split_unit_localize.ll +++ b/lld/test/ELF/lto/devirt_split_unit_localize.ll @@ -91,7 +91,7 @@ declare dso_local void @_ZNK3Cat9makeNoiseEv(ptr nonnull dereferenceable(8)) unn define dso_local void @_Z17useDoThingWithCatv() local_unnamed_addr { entry: %call = tail call noalias nonnull dereferenceable(8) ptr @_Znwm(i64 8) - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV3Cat, i64 0, inrange i32 0, i64 2), ptr %call, align 8, !tbaa !4 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV3Cat, i64 0, i32 0, i64 2), ptr %call, align 8, !tbaa !4 tail call void @_Z14doThingWithCatP6Animal(ptr nonnull %call) ret void } diff --git a/lld/test/ELF/lto/devirt_validate_vtable_typeinfos_ref.ll b/lld/test/ELF/lto/devirt_validate_vtable_typeinfos_ref.ll index 2318af4b16ab46e87b30054bafb8913e093b32e1..2d6a30da572002573168b9cca6ffe25ddf2af0e0 100644 --- a/lld/test/ELF/lto/devirt_validate_vtable_typeinfos_ref.ll +++ b/lld/test/ELF/lto/devirt_validate_vtable_typeinfos_ref.ll @@ -117,7 +117,7 @@ entry: %this.addr = alloca ptr, align 8 store ptr %this, ptr %this.addr, align 8 %this1 = load ptr, ptr %this.addr, align 8 - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, inrange i32 0, i32 2), ptr %this1, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 2), ptr %this1, align 8 ret void } diff --git a/lld/test/ELF/lto/libcall-archive.ll b/lld/test/ELF/lto/libcall-archive.ll index bd91d0391dc2747d3782b43dc5e4bf305c8aa41d..0f3d9c37d7299269b5618f0dec92684425c59ae2 100644 --- a/lld/test/ELF/lto/libcall-archive.ll +++ b/lld/test/ELF/lto/libcall-archive.ll @@ -4,11 +4,15 @@ ; RUN: llvm-as -o %t2.o %S/Inputs/libcall-archive.ll ; RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux -o %t3.o %S/Inputs/libcall-archive.s ; RUN: llvm-ar rcs %t.a %t2.o %t3.o -; RUN: ld.lld -o %t %t.o %t.a +; RUN: ld.lld --why-extract=%t.why.txt -o %t %t.o %t.a +; RUN: FileCheck %s --input-file=%t.why.txt --check-prefix=CHECK-WHY ; RUN: llvm-nm %t | FileCheck %s ; RUN: ld.lld -o %t2 %t.o --start-lib %t2.o %t3.o --end-lib ; RUN: llvm-nm %t2 | FileCheck %s +; CHECK-WHY: reference extracted symbol +; CHECK-WHY-NEXT: <libcall> {{.*}}tmp.a({{.*}}tmp2.o) memcpy + ; CHECK-NOT: T __sync_val_compare_and_swap_8 ; CHECK: T _start ; CHECK: T memcpy diff --git a/lld/test/ELF/pack-dyn-relocs-arm2.s b/lld/test/ELF/pack-dyn-relocs-arm2.s index cf2cd8bb597ec2d6992501fe81897d236883125d..ed4fa52e7a5ab2e5cc7762bdfb9c4bd8bdc8b8cc 100644 --- a/lld/test/ELF/pack-dyn-relocs-arm2.s +++ b/lld/test/ELF/pack-dyn-relocs-arm2.s @@ -5,7 +5,7 @@ // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o // RUN: ld.lld -pie --pack-dyn-relocs=relr %t.o %t.so -o %t.exe -// RUN: llvm-readobj -r %t.exe | FileCheck %s +// RUN: llvm-readobj -r -x .data %t.exe | FileCheck %s // CHECK: Section (5) .relr.dyn { // CHECK-NEXT: 0x301E8 R_ARM_RELATIVE - @@ -43,6 +43,9 @@ // CHECK-NEXT: 0x30268 R_ARM_RELATIVE - // CHECK-NEXT: 0x3026C R_ARM_RELATIVE - // CHECK-NEXT: } +// CHECK: Hex dump of section '.data': +// CHECK-NEXT: 0x000301e8 00000000 01000000 02000000 ffffffff . +// CHECK-NEXT: 0x000301f8 00000080 00000000 00000000 00000000 . // RUN: llvm-readobj -S --dynamic-table %t.exe | FileCheck --check-prefix=HEADER %s // HEADER: 0x00000023 RELRSZ 12 (bytes) @@ -50,10 +53,10 @@ .data .align 2 .dc.a __ehdr_start -.dc.a __ehdr_start -.dc.a __ehdr_start -.dc.a __ehdr_start -.dc.a __ehdr_start +.dc.a __ehdr_start+1 +.dc.a __ehdr_start+2 +.dc.a __ehdr_start-1 +.dc.a __ehdr_start-0x80000000 .dc.a __ehdr_start .dc.a __ehdr_start .dc.a __ehdr_start diff --git a/lld/test/ELF/pack-dyn-relocs-ifunc.s b/lld/test/ELF/pack-dyn-relocs-ifunc.s new file mode 100644 index 0000000000000000000000000000000000000000..6168d06f99d9e94c1967d03c9be335e93fcd815a --- /dev/null +++ b/lld/test/ELF/pack-dyn-relocs-ifunc.s @@ -0,0 +1,49 @@ +# REQUIRES: aarch64 +## Prior to Android V, there was a bug that caused RELR relocations to be +## applied after packed relocations. This meant that resolvers referenced by +## IRELATIVE relocations in the packed relocation section would read unrelocated +## globals when --pack-relative-relocs=android+relr is enabled. Work around this +## by placing IRELATIVE in .rela.plt. + +# RUN: rm -rf %t && split-file %s %t && cd %t +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-android a.s -o a.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-android b.s -o b.o +# RUN: ld.lld -shared b.o -o b.so +# RUN: ld.lld -pie --pack-dyn-relocs=android+relr -z separate-loadable-segments a.o b.so -o a +# RUN: llvm-readobj -r a | FileCheck %s +# RUN: llvm-objdump -d a | FileCheck %s --check-prefix=ASM + +# CHECK: .relr.dyn { +# CHECK-NEXT: 0x30000 R_AARCH64_RELATIVE - +# CHECK-NEXT: } +# CHECK: .rela.plt { +# CHECK-NEXT: 0x30020 R_AARCH64_JUMP_SLOT bar 0x0 +# CHECK-NEXT: 0x30028 R_AARCH64_IRELATIVE - 0x10000 +# CHECK-NEXT: } + +# ASM: <.iplt>: +# ASM-NEXT: adrp x16, 0x30000 +# ASM-NEXT: ldr x17, [x16, #0x28] +# ASM-NEXT: add x16, x16, #0x28 +# ASM-NEXT: br x17 + +#--- a.s +.text +.type foo, %gnu_indirect_function +.globl foo +foo: + ret + +.globl _start +_start: + bl foo + bl bar + +.data +.balign 8 +.quad .data + +#--- b.s +.globl bar +bar: + ret diff --git a/lld/test/ELF/pack-dyn-relocs.s b/lld/test/ELF/pack-dyn-relocs.s index da97e388c3d0c5db7ba5cf33dc6b68abf82e054c..733ddd4ecad396504a0aa00120d955b0b24a6e78 100644 --- a/lld/test/ELF/pack-dyn-relocs.s +++ b/lld/test/ELF/pack-dyn-relocs.s @@ -198,11 +198,11 @@ // RUN: llvm-readobj -r %t2.a64 | FileCheck --check-prefix=UNPACKED64 %s // UNPACKED64: Section ({{.+}}) .rela.dyn { -// UNPACKED64-NEXT: 0x30690 R_AARCH64_RELATIVE - 0x1 -// UNPACKED64-NEXT: 0x30698 R_AARCH64_RELATIVE - 0x2 -// UNPACKED64-NEXT: 0x306A0 R_AARCH64_RELATIVE - 0x3 -// UNPACKED64-NEXT: 0x306A8 R_AARCH64_RELATIVE - 0x4 -// UNPACKED64-NEXT: 0x306B0 R_AARCH64_RELATIVE - 0x5 +// UNPACKED64-NEXT: 0x30690 R_AARCH64_RELATIVE - 0x0 +// UNPACKED64-NEXT: 0x30698 R_AARCH64_RELATIVE - 0x1 +// UNPACKED64-NEXT: 0x306A0 R_AARCH64_RELATIVE - 0x2 +// UNPACKED64-NEXT: 0x306A8 R_AARCH64_RELATIVE - 0xFFFFFFFFFFFFFFFF +// UNPACKED64-NEXT: 0x306B0 R_AARCH64_RELATIVE - 0x80000000 // UNPACKED64-NEXT: 0x306B8 R_AARCH64_RELATIVE - 0x6 // UNPACKED64-NEXT: 0x306C0 R_AARCH64_RELATIVE - 0x7 // UNPACKED64-NEXT: 0x306C8 R_AARCH64_RELATIVE - 0x8 @@ -238,91 +238,72 @@ // UNPACKED64-NEXT: } // RUN: ld.lld -pie --pack-dyn-relocs=android %t.a64.o %t.a64.so -o %t3.a64 -// RUN: llvm-readobj -S --dynamic-table %t3.a64 | FileCheck --check-prefix=ANDROID64-HEADERS %s -// RUN: llvm-readobj -r %t3.a64 | FileCheck --check-prefix=ANDROID64 %s - -// ANDROID64-HEADERS: Index: 1 -// ANDROID64-HEADERS-NEXT: Name: .dynsym - -// ANDROID64-HEADERS: Name: .rela.dyn -// ANDROID64-HEADERS-NEXT: Type: SHT_ANDROID_RELA -// ANDROID64-HEADERS-NEXT: Flags [ (0x2) -// ANDROID64-HEADERS-NEXT: SHF_ALLOC (0x2) -// ANDROID64-HEADERS-NEXT: ] -// ANDROID64-HEADERS-NEXT: Address: [[ADDR:.*]] -// ANDROID64-HEADERS-NEXT: Offset: [[ADDR]] -// ANDROID64-HEADERS-NEXT: Size: [[SIZE:.*]] -// ANDROID64-HEADERS-NEXT: Link: 1 -// ANDROID64-HEADERS-NEXT: Info: 0 -// ANDROID64-HEADERS-NEXT: AddressAlignment: 8 -// ANDROID64-HEADERS-NEXT: EntrySize: 1 +// RUN: llvm-readelf -S -d -r %t3.a64 | FileCheck --check-prefix=ANDROID64 %s + +// ANDROID64: Name Type Address Off Size ES Flg Lk Inf Al +// ANDROID64: .dynstr STRTAB {{.*}} 00 A 0 0 1 +// ANDROID64-NEXT: .rela.dyn ANDROID_RELA {{0*}}[[#%x,ANDROID:]] {{.*}} 01 A 1 0 8 +// ANDROID64-NEXT: .text PROGBITS {{.*}} 00 AX 0 0 4 + +// ANDROID64: (DEBUG) 0x0 +// ANDROID64-NEXT: (ANDROID_RELA) 0x[[#ANDROID]] +// ANDROID64-NEXT: (ANDROID_RELASZ) 122 (bytes) +// ANDROID64-NEXT: (RELAENT) 24 (bytes) // ANDROID64-HEADERS: 0x0000000060000011 ANDROID_RELA [[ADDR]] // ANDROID64-HEADERS: 0x0000000060000012 ANDROID_RELASZ [[SIZE]] -// ANDROID64: Section ({{.+}}) .rela.dyn { -// ANDROID64-NEXT: 0x303E0 R_AARCH64_RELATIVE - 0x1 -// ANDROID64-NEXT: 0x303E8 R_AARCH64_RELATIVE - 0x2 -// ANDROID64-NEXT: 0x303F0 R_AARCH64_RELATIVE - 0x3 -// ANDROID64-NEXT: 0x303F8 R_AARCH64_RELATIVE - 0x4 -// ANDROID64-NEXT: 0x30400 R_AARCH64_RELATIVE - 0x5 -// ANDROID64-NEXT: 0x30408 R_AARCH64_RELATIVE - 0x6 -// ANDROID64-NEXT: 0x30410 R_AARCH64_RELATIVE - 0x7 -// ANDROID64-NEXT: 0x30418 R_AARCH64_RELATIVE - 0x8 -// ANDROID64-NEXT: 0x30470 R_AARCH64_RELATIVE - 0x1 -// ANDROID64-NEXT: 0x30478 R_AARCH64_RELATIVE - 0x2 -// ANDROID64-NEXT: 0x30480 R_AARCH64_RELATIVE - 0x3 -// ANDROID64-NEXT: 0x30488 R_AARCH64_RELATIVE - 0x4 -// ANDROID64-NEXT: 0x30490 R_AARCH64_RELATIVE - 0x5 -// ANDROID64-NEXT: 0x30498 R_AARCH64_RELATIVE - 0x6 -// ANDROID64-NEXT: 0x304A0 R_AARCH64_RELATIVE - 0x7 -// ANDROID64-NEXT: 0x304A8 R_AARCH64_RELATIVE - 0x8 -// ANDROID64-NEXT: 0x304B0 R_AARCH64_RELATIVE - 0x9 - -// ANDROID64-NEXT: 0x30428 R_AARCH64_RELATIVE - 0x1 -// ANDROID64-NEXT: 0x30430 R_AARCH64_RELATIVE - 0x2 -// ANDROID64-NEXT: 0x30438 R_AARCH64_RELATIVE - 0x3 -// ANDROID64-NEXT: 0x30440 R_AARCH64_RELATIVE - 0x4 -// ANDROID64-NEXT: 0x30448 R_AARCH64_RELATIVE - 0x5 -// ANDROID64-NEXT: 0x30450 R_AARCH64_RELATIVE - 0x6 -// ANDROID64-NEXT: 0x30458 R_AARCH64_RELATIVE - 0x7 - -// ANDROID64-NEXT: 0x304B9 R_AARCH64_RELATIVE - 0xA - -// ANDROID64-NEXT: 0x30468 R_AARCH64_ABS64 bar2 0x0 -// ANDROID64-NEXT: 0x304C1 R_AARCH64_ABS64 bar2 0x0 -// ANDROID64-NEXT: 0x304C9 R_AARCH64_ABS64 bar2 0x0 -// ANDROID64-NEXT: 0x304E1 R_AARCH64_ABS64 bar2 0x0 -// ANDROID64-NEXT: 0x30420 R_AARCH64_ABS64 bar2 0x1 -// ANDROID64-NEXT: 0x30460 R_AARCH64_ABS64 zed2 0x0 -// ANDROID64-NEXT: 0x304D1 R_AARCH64_ABS64 bar2 0x1 -// ANDROID64-NEXT: 0x304D9 R_AARCH64_ABS64 bar2 0x1 -// ANDROID64-NEXT: } +// ANDROID64: Relocation section '.rela.dyn' at offset {{.*}} contains 33 entries: +// ANDROID64-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend +// ANDROID64-NEXT: 00000000000303e8 0000000000000403 R_AARCH64_RELATIVE 0 +// ANDROID64-NEXT: 00000000000303f0 0000000000000403 R_AARCH64_RELATIVE 1 +// ANDROID64-NEXT: 00000000000303f8 0000000000000403 R_AARCH64_RELATIVE 2 +// ANDROID64-NEXT: 0000000000030400 0000000000000403 R_AARCH64_RELATIVE ffffffffffffffff +// ANDROID64-NEXT: 0000000000030408 0000000000000403 R_AARCH64_RELATIVE 80000000 +// ANDROID64-NEXT: 0000000000030410 0000000000000403 R_AARCH64_RELATIVE 6 +// ANDROID64-NEXT: 0000000000030418 0000000000000403 R_AARCH64_RELATIVE 7 +// ANDROID64-NEXT: 0000000000030420 0000000000000403 R_AARCH64_RELATIVE 8 +// ANDROID64-NEXT: 0000000000030478 0000000000000403 R_AARCH64_RELATIVE 1 +// ANDROID64-NEXT: 0000000000030480 0000000000000403 R_AARCH64_RELATIVE 2 +// ANDROID64-NEXT: 0000000000030488 0000000000000403 R_AARCH64_RELATIVE 3 +// ANDROID64-NEXT: 0000000000030490 0000000000000403 R_AARCH64_RELATIVE 4 +// ANDROID64-NEXT: 0000000000030498 0000000000000403 R_AARCH64_RELATIVE 5 +// ANDROID64-NEXT: 00000000000304a0 0000000000000403 R_AARCH64_RELATIVE 6 +// ANDROID64-NEXT: 00000000000304a8 0000000000000403 R_AARCH64_RELATIVE 7 +// ANDROID64-NEXT: 00000000000304b0 0000000000000403 R_AARCH64_RELATIVE 8 +// ANDROID64-NEXT: 00000000000304b8 0000000000000403 R_AARCH64_RELATIVE 9 +// ANDROID64-NEXT: 0000000000030430 0000000000000403 R_AARCH64_RELATIVE 1 +// ANDROID64-NEXT: 0000000000030438 0000000000000403 R_AARCH64_RELATIVE 2 +// ANDROID64-NEXT: 0000000000030440 0000000000000403 R_AARCH64_RELATIVE 3 +// ANDROID64-NEXT: 0000000000030448 0000000000000403 R_AARCH64_RELATIVE 4 +// ANDROID64-NEXT: 0000000000030450 0000000000000403 R_AARCH64_RELATIVE 5 +// ANDROID64-NEXT: 0000000000030458 0000000000000403 R_AARCH64_RELATIVE 6 +// ANDROID64-NEXT: 0000000000030460 0000000000000403 R_AARCH64_RELATIVE 7 +// ANDROID64-NEXT: 00000000000304c1 0000000000000403 R_AARCH64_RELATIVE a +// ANDROID64-NEXT: 0000000000030470 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 0 +// ANDROID64-NEXT: 00000000000304c9 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 0 +// ANDROID64-NEXT: 00000000000304d1 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 0 +// ANDROID64-NEXT: 00000000000304e9 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 0 +// ANDROID64-NEXT: 0000000000030428 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 1 +// ANDROID64-NEXT: 0000000000030468 0000000200000101 R_AARCH64_ABS64 0000000000000000 zed2 + 0 +// ANDROID64-NEXT: 00000000000304d9 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 1 +// ANDROID64-NEXT: 00000000000304e1 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 1 +// ANDROID64-EMPTY: // RUN: ld.lld -pie --pack-dyn-relocs=relr %t.a64.o %t.a64.so -o %t4.a64 -// RUN: llvm-readobj -S --dynamic-table %t4.a64 | FileCheck --check-prefix=RELR64-HEADERS %s +// RUN: llvm-readelf -Sdr -x .data %t4.a64 | FileCheck --check-prefix=RELR64 %s // RUN: llvm-readobj -r --raw-relr %t4.a64 | FileCheck --check-prefix=RAW-RELR64 %s -// RUN: llvm-readobj -r %t4.a64 | FileCheck --check-prefix=RELR64 %s - -// RELR64-HEADERS: Index: 1 -// RELR64-HEADERS-NEXT: Name: .dynsym - -// RELR64-HEADERS: Name: .relr.dyn -// RELR64-HEADERS-NEXT: Type: SHT_RELR -// RELR64-HEADERS-NEXT: Flags [ (0x2) -// RELR64-HEADERS-NEXT: SHF_ALLOC (0x2) -// RELR64-HEADERS-NEXT: ] -// RELR64-HEADERS-NEXT: Address: [[ADDR:.*]] -// RELR64-HEADERS-NEXT: Offset: [[ADDR]] -// RELR64-HEADERS-NEXT: Size: 16 -// RELR64-HEADERS-NEXT: Link: 0 -// RELR64-HEADERS-NEXT: Info: 0 -// RELR64-HEADERS-NEXT: AddressAlignment: 8 -// RELR64-HEADERS-NEXT: EntrySize: 8 - -// RELR64-HEADERS: 0x0000000000000024 RELR [[ADDR]] -// RELR64-HEADERS: 0x0000000000000023 RELRSZ 16 (bytes) -// RELR64-HEADERS: 0x0000000000000025 RELRENT 8 (bytes) + +// RELR64: Name Type Address Off Size ES Flg Lk Inf Al +// RELR64: .dynstr STRTAB {{.*}} 00 A 0 0 1 +// RELR64-NEXT: .rela.dyn RELA {{.*}} 18 A 1 0 8 +// RELR64-NEXT: .relr.dyn RELR {{0*}}[[#%x,RELR:]] {{.*}} 08 A 0 0 8 +// RELR64-NEXT: .text PROGBITS 0000000000010380 000380 000000 00 AX 0 0 4 + +// RELR64: (RELACOUNT) 1 +// RELR64: (RELR) 0x[[#RELR]] +// RELR64-NEXT: (RELRSZ) 16 (bytes) +// RELR64-NEXT: (RELRENT) 8 (bytes) /// SHT_RELR section contains address/bitmap entries /// encoding the offsets for relative relocation. @@ -334,51 +315,57 @@ /// Decoded SHT_RELR section is same as UNPACKED, /// but contains only the relative relocations. /// Any relative relocations with odd offset stay in SHT_RELA. -// RELR64: Section ({{.+}}) .rela.dyn { -// RELR64-NEXT: 0x30569 R_AARCH64_RELATIVE - 0xA -// RELR64-NEXT: 0x304D0 R_AARCH64_ABS64 bar2 0x1 -// RELR64-NEXT: 0x30518 R_AARCH64_ABS64 bar2 0x0 -// RELR64-NEXT: 0x30571 R_AARCH64_ABS64 bar2 0x0 -// RELR64-NEXT: 0x30579 R_AARCH64_ABS64 bar2 0x0 -// RELR64-NEXT: 0x30581 R_AARCH64_ABS64 bar2 0x1 -// RELR64-NEXT: 0x30589 R_AARCH64_ABS64 bar2 0x1 -// RELR64-NEXT: 0x30591 R_AARCH64_ABS64 bar2 0x0 -// RELR64-NEXT: 0x30510 R_AARCH64_ABS64 zed2 0x0 -// RELR64-NEXT: } -// RELR64-NEXT: Section ({{.+}}) .relr.dyn { -// RELR64-NEXT: 0x30490 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x30498 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x304A0 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x304A8 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x304B0 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x304B8 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x304C0 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x304C8 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x304D8 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x304E0 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x304E8 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x304F0 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x304F8 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x30500 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x30508 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x30520 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x30528 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x30530 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x30538 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x30540 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x30548 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x30550 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x30558 R_AARCH64_RELATIVE - -// RELR64-NEXT: 0x30560 R_AARCH64_RELATIVE - -// RELR64-NEXT: } +// RELR64: Relocation section '.rela.dyn' at offset {{.*}} contains 9 entries: +// RELR64-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend +// RELR64-NEXT: 0000000000030569 0000000000000403 R_AARCH64_RELATIVE a +// RELR64-NEXT: 00000000000304d0 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 1 +// RELR64-NEXT: 0000000000030518 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 0 +// RELR64-NEXT: 0000000000030571 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 0 +// RELR64-NEXT: 0000000000030579 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 0 +// RELR64-NEXT: 0000000000030581 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 1 +// RELR64-NEXT: 0000000000030589 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 1 +// RELR64-NEXT: 0000000000030591 0000000100000101 R_AARCH64_ABS64 0000000000000000 bar2 + 0 +// RELR64-NEXT: 0000000000030510 0000000200000101 R_AARCH64_ABS64 0000000000000000 zed2 + 0 +// RELR64-EMPTY: +// RELR64-NEXT: Relocation section '.relr.dyn' at offset {{.*}} contains 24 entries: +// RELR64-NEXT: Offset Info Type Symbol's Value Symbol's Name +// RELR64-NEXT: 0000000000030490 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 0000000000030498 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 00000000000304a0 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 00000000000304a8 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 00000000000304b0 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 00000000000304b8 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 00000000000304c0 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 00000000000304c8 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 00000000000304d8 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 00000000000304e0 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 00000000000304e8 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 00000000000304f0 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 00000000000304f8 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 0000000000030500 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 0000000000030508 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 0000000000030520 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 0000000000030528 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 0000000000030530 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 0000000000030538 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 0000000000030540 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 0000000000030548 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 0000000000030550 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 0000000000030558 0000000000000403 R_AARCH64_RELATIVE +// RELR64-NEXT: 0000000000030560 0000000000000403 R_AARCH64_RELATIVE +// RELR64-EMPTY: +// RELR64-NEXT: Hex dump of section '.data': +// RELR64-NEXT: 0x00030490 00000000 00000000 01000000 00000000 . +// RELR64-NEXT: 0x000304a0 02000000 00000000 ffffffff ffffffff . +// RELR64-NEXT: 0x000304b0 00000080 00000000 06000000 00000000 . .data -.align 2 +.balign 2 +.dc.a __ehdr_start .dc.a __ehdr_start + 1 .dc.a __ehdr_start + 2 -.dc.a __ehdr_start + 3 -.dc.a __ehdr_start + 4 -.dc.a __ehdr_start + 5 +.dc.a __ehdr_start - 1 +.dc.a __ehdr_start + 0x80000000 .dc.a __ehdr_start + 6 .dc.a __ehdr_start + 7 .dc.a __ehdr_start + 8 diff --git a/lld/test/ELF/ppc32-ifunc-nonpreemptible-pic.s b/lld/test/ELF/ppc32-ifunc-nonpreemptible-pic.s index a93f3cecb0c6c1042e77468728471f1b2aac08d0..c9a0381b610a46cbc4c632beec4f811159819cb9 100644 --- a/lld/test/ELF/ppc32-ifunc-nonpreemptible-pic.s +++ b/lld/test/ELF/ppc32-ifunc-nonpreemptible-pic.s @@ -10,16 +10,16 @@ # RUN: llvm-readelf -x .got2 %t | FileCheck --check-prefix=HEX2 %s # RELOC: .rela.dyn { -# RELOC-NEXT: 0x3024C R_PPC_RELATIVE - 0x101A0 -# RELOC-NEXT: 0x30250 R_PPC_IRELATIVE - 0x10188 +# RELOC-NEXT: 0x3022C R_PPC_RELATIVE - 0x101A0 +# RELOC-NEXT: 0x30230 R_PPC_IRELATIVE - 0x10188 # RELOC-NEXT: } # SYM: 000101a0 0 FUNC GLOBAL DEFAULT {{.*}} func # HEX: Hex dump of section '.got2': -# HEX-NEXT: 0x0003024c 00000000 .... +# HEX-NEXT: 0x0003022c 00000000 .... # HEX2: Hex dump of section '.got2': -# HEX2-NEXT: 0x0003024c 000101a0 .... +# HEX2-NEXT: 0x0003022c 000101a0 .... .section .got2,"aw" .long func diff --git a/lld/test/ELF/relro-non-contiguous-script-data.s b/lld/test/ELF/relro-non-contiguous-script-data.s index fd485e89167fcce492eaa68cdd208e7dec4525c7..530fc7c84eb91eeecfa89e44eeb4b570aa949814 100644 --- a/lld/test/ELF/relro-non-contiguous-script-data.s +++ b/lld/test/ELF/relro-non-contiguous-script-data.s @@ -1,19 +1,21 @@ // REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=x86_64 /dev/null -o %t2.o +// RUN: ld.lld -shared -soname=t2 %t2.o -o %t2.so // RUN: echo "SECTIONS { \ // RUN: .dynamic : { *(.dynamic) } \ // RUN: .non_ro : { . += 1; } \ // RUN: .jcr : { *(.jcr) } \ // RUN: } " > %t.script // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o -// RUN: not ld.lld --export-dynamic %t.o -o /dev/null --script=%t.script 2>&1 | FileCheck %s +// RUN: not ld.lld %t.o %t2.so -o /dev/null --script=%t.script 2>&1 | FileCheck %s // RUN: echo "SECTIONS { \ // RUN: .dynamic : { *(.dynamic) } \ // RUN: .non_ro : { BYTE(1); } \ // RUN: .jcr : { *(.jcr) } \ // RUN: } " > %t2.script -// RUN: not ld.lld --export-dynamic %t.o -o /dev/null --script=%t2.script 2>&1 | FileCheck %s +// RUN: not ld.lld %t.o %t2.so -o /dev/null --script=%t2.script 2>&1 | FileCheck %s // CHECK: error: section: .jcr is not contiguous with other relro sections diff --git a/lld/test/ELF/riscv-ifunc-nonpreemptible.s b/lld/test/ELF/riscv-ifunc-nonpreemptible.s index 21c6075451104b62bf059c0bf1f65e0dd18339b5..eda5548eef8b99aa7a8aff03230ad503385dd3ec 100644 --- a/lld/test/ELF/riscv-ifunc-nonpreemptible.s +++ b/lld/test/ELF/riscv-ifunc-nonpreemptible.s @@ -16,11 +16,11 @@ # RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefix=DIS64 %s # RELOC32: .rela.dyn { -# RELOC32-NEXT: 0x3220 R_RISCV_IRELATIVE - 0x117C +# RELOC32-NEXT: 0x3200 R_RISCV_IRELATIVE - 0x117C # RELOC32-NEXT: } # RELOC32-LABEL: Hex dump of section '.got.plt': -# NO-APPLY-RELOC32: 0x00003220 00000000 -# APPLY-RELOC32: 0x00003220 7c110000 +# NO-APPLY-RELOC32: 0x00003200 00000000 +# APPLY-RELOC32: 0x00003200 7c110000 # RELOC32-EMPTY: # SYM32: 0001190 0 FUNC GLOBAL DEFAULT {{.*}} func @@ -30,18 +30,18 @@ # DIS32-NEXT: addi a0, a0, 0x10 # DIS32: Disassembly of section .iplt: # DIS32: <func>: -## 32-bit: &.got.plt[func]-. = 0x3220-0x1190 = 4096*2+144 +## 32-bit: &.got.plt[func]-. = 0x3200-0x1190 = 4096*2+0x70 # DIS32-NEXT: 1190: auipc t3, 0x2 -# DIS32-NEXT: lw t3, 0x90(t3) +# DIS32-NEXT: lw t3, 0x70(t3) # DIS32-NEXT: jalr t1, t3 # DIS32-NEXT: nop # RELOC64: .rela.dyn { -# RELOC64-NEXT: 0x3380 R_RISCV_IRELATIVE - 0x1260 +# RELOC64-NEXT: 0x3340 R_RISCV_IRELATIVE - 0x1260 # RELOC64-NEXT: } # RELOC64-LABEL: Hex dump of section '.got.plt': -# NO-APPLY-RELOC64: 0x00003380 00000000 00000000 -# APPLY-RELOC64: 0x00003380 60120000 00000000 +# NO-APPLY-RELOC64: 0x00003340 00000000 00000000 +# APPLY-RELOC64: 0x00003340 60120000 00000000 # RELOC64-EMPTY: # SYM64: 000000000001270 0 FUNC GLOBAL DEFAULT {{.*}} func @@ -51,9 +51,9 @@ # DIS64-NEXT: addi a0, a0, 0xc # DIS64: Disassembly of section .iplt: # DIS64: <func>: -## 64-bit: &.got.plt[func]-. = 0x3380-0x1270 = 4096*2+272 +## 64-bit: &.got.plt[func]-. = 0x3340-0x1270 = 4096*2+0xd0 # DIS64-NEXT: 1270: auipc t3, 0x2 -# DIS64-NEXT: ld t3, 0x110(t3) +# DIS64-NEXT: ld t3, 0xd0(t3) # DIS64-NEXT: jalr t1, t3 # DIS64-NEXT: nop diff --git a/lld/test/ELF/riscv-tlsdesc-relax.s b/lld/test/ELF/riscv-tlsdesc-relax.s index fb24317e6535cae2b424b80cbf5633c663c4eb2d..5718d4175be11360eae6a73749f91a5b5fc8dc4a 100644 --- a/lld/test/ELF/riscv-tlsdesc-relax.s +++ b/lld/test/ELF/riscv-tlsdesc-relax.s @@ -33,12 +33,14 @@ # GD64-NEXT: c.add a0, tp # GD64-NEXT: jal {{.*}} <foo> ## &.got[c]-. = 0x20c0+8 - 0x1020 = 0x10a8 +# GD64-LABEL: <.Ltlsdesc_hi1>: # GD64-NEXT: 1020: auipc a4, 0x1 # GD64-NEXT: ld a5, 0xa8(a4) # GD64-NEXT: addi a0, a4, 0xa8 # GD64-NEXT: jalr t0, 0x0(a5) # GD64-NEXT: c.add a0, tp ## &.got[c]-. = 0x20c0+8 - 0x1032 = 0x1096 +# GD64-LABEL: <.Ltlsdesc_hi2>: # GD64-NEXT: 1032: auipc a6, 0x1 # GD64-NEXT: ld a7, 0x96(a6) # GD64-NEXT: addi a0, a6, 0x96 @@ -64,6 +66,7 @@ # LE64-NEXT: jal {{.*}} <foo> # LE64-NEXT: R_RISCV_JAL foo # LE64-NEXT: R_RISCV_RELAX *ABS* +# LE64-LABEL: <.Ltlsdesc_hi1>: # LE64-NEXT: addi a0, zero, 0x7ff # LE64-NEXT: R_RISCV_TLSDESC_HI20 b # LE64-NEXT: R_RISCV_RELAX *ABS* @@ -71,6 +74,7 @@ # LE64-NEXT: R_RISCV_TLSDESC_ADD_LO12 .Ltlsdesc_hi1 # LE64-NEXT: R_RISCV_TLSDESC_CALL .Ltlsdesc_hi1 # LE64-NEXT: c.add a0, tp +# LE64-LABEL: <.Ltlsdesc_hi2>: # LE64-NEXT: addi zero, zero, 0x0 # LE64-NEXT: R_RISCV_TLSDESC_HI20 b # LE64-NEXT: addi zero, zero, 0x0 @@ -93,9 +97,11 @@ # LE64A-NEXT: addi a0, a0, -0x479 # LE64A-NEXT: c.add a0, tp # LE64A-NEXT: jal {{.*}} <foo> +# LE64A-LABEL: <.Ltlsdesc_hi1>: # LE64A-NEXT: lui a0, 0x2 # LE64A-NEXT: addi a0, a0, -0x479 # LE64A-NEXT: c.add a0, tp +# LE64A-LABEL: <.Ltlsdesc_hi2>: # LE64A-NEXT: addi zero, zero, 0x0 # LE64A-NEXT: addi zero, zero, 0x0 # LE64A-NEXT: lui a0, 0x2 @@ -115,10 +121,12 @@ # IE64-NEXT: c.add a0, tp # IE64-NEXT: jal {{.*}} <foo> ## &.got[c]-. = 0x120e0+8 - 0x11018 = 0x10d0 +# IE64-LABEL: <.Ltlsdesc_hi1>: # IE64-NEXT: 11018: auipc a0, 0x1 # IE64-NEXT: ld a0, 0xd0(a0) # IE64-NEXT: c.add a0, tp ## &.got[c]-. = 0x120e0+8 - 0x1102a = 0x10be +# IE64-LABEL: <.Ltlsdesc_hi2>: # IE64-NEXT: addi zero, zero, 0x0 # IE64-NEXT: addi zero, zero, 0x0 # IE64-NEXT: 1102a: auipc a0, 0x1 diff --git a/lld/test/ELF/riscv-tlsdesc.s b/lld/test/ELF/riscv-tlsdesc.s index 1738f86256caa6a9d101b4a20e8aa620ed84e3ba..935ecbddfbfffda6b2bc804a0f657926b1180b10 100644 --- a/lld/test/ELF/riscv-tlsdesc.s +++ b/lld/test/ELF/riscv-tlsdesc.s @@ -29,6 +29,14 @@ # RUN: ld.lld -e 0 -z now a.32.o c.32.so -o a.32.ie # RUN: llvm-objdump --no-show-raw-insn -M no-aliases -h -d a.32.ie | FileCheck %s --check-prefix=IE32 +## Prior to https://github.com/llvm/llvm-project/pull/85817 the local TLSDESC +## labels would be marked STT_TLS, resulting in an error "has an STT_TLS symbol but doesn't have an SHF_TLS section" + +# RUN: llvm-mc -triple=riscv64 -filetype=obj d.s -o d.64.o +# RUN: ld.lld -shared -soname=d.64.so -o d.64.so d.64.o --fatal-warnings +# RUN: llvm-mc -triple=riscv32 -filetype=obj d.s -o d.32.o --defsym ELF32=1 +# RUN: ld.lld -shared -soname=d.32.so -o d.32.so d.32.o --fatal-warnings + # GD64-RELA: .rela.dyn { # GD64-RELA-NEXT: 0x2408 R_RISCV_TLSDESC - 0x7FF # GD64-RELA-NEXT: 0x23E8 R_RISCV_TLSDESC a 0x0 @@ -68,14 +76,14 @@ # GD64-NEXT: add a0, a0, tp ## &.got[b]-. = 0x23e0+40 - 0x12f4 = 0x1114 -# GD64-NEXT: 12f4: auipc a2, 0x1 +# GD64: 12f4: auipc a2, 0x1 # GD64-NEXT: ld a3, 0x114(a2) # GD64-NEXT: addi a0, a2, 0x114 # GD64-NEXT: jalr t0, 0x0(a3) # GD64-NEXT: add a0, a0, tp ## &.got[c]-. = 0x23e0+24 - 0x1308 = 0x10f0 -# GD64-NEXT: 1308: auipc a4, 0x1 +# GD64: 1308: auipc a4, 0x1 # GD64-NEXT: ld a5, 0xf0(a4) # GD64-NEXT: addi a0, a4, 0xf0 # GD64-NEXT: jalr t0, 0x0(a5) @@ -83,7 +91,7 @@ # NOREL: no relocations -# LE64-LABEL: <.text>: +# LE64-LABEL: <.Ltlsdesc_hi0>: ## st_value(a) = 8 # LE64-NEXT: addi zero, zero, 0x0 # LE64-NEXT: addi zero, zero, 0x0 @@ -91,12 +99,14 @@ # LE64-NEXT: addi a0, zero, 0x8 # LE64-NEXT: add a0, a0, tp ## st_value(b) = 2047 +# LE64-LABEL: <.Ltlsdesc_hi1>: # LE64-NEXT: addi zero, zero, 0x0 # LE64-NEXT: addi zero, zero, 0x0 # LE64-NEXT: addi zero, zero, 0x0 # LE64-NEXT: addi a0, zero, 0x7ff # LE64-NEXT: add a0, a0, tp ## st_value(c) = 2048 +# LE64-LABEL: <.Ltlsdesc_hi2>: # LE64-NEXT: addi zero, zero, 0x0 # LE64-NEXT: addi zero, zero, 0x0 # LE64-NEXT: lui a0, 0x1 @@ -110,18 +120,20 @@ # IE64: .got 00000010 00000000000123a8 ## a and b are optimized to use LE. c is optimized to IE. -# IE64-LABEL: <.text>: +# IE64-LABEL: <.Ltlsdesc_hi0>: # IE64-NEXT: addi zero, zero, 0x0 # IE64-NEXT: addi zero, zero, 0x0 # IE64-NEXT: addi zero, zero, 0x0 # IE64-NEXT: addi a0, zero, 0x8 # IE64-NEXT: add a0, a0, tp +# IE64-LABEL: <.Ltlsdesc_hi1>: # IE64-NEXT: addi zero, zero, 0x0 # IE64-NEXT: addi zero, zero, 0x0 # IE64-NEXT: addi zero, zero, 0x0 # IE64-NEXT: addi a0, zero, 0x7ff # IE64-NEXT: add a0, a0, tp ## &.got[c]-. = 0x123a8+8 - 0x112b8 = 0x10f8 +# IE64-LABEL: <.Ltlsdesc_hi2>: # IE64-NEXT: addi zero, zero, 0x0 # IE64-NEXT: addi zero, zero, 0x0 # IE64-NEXT: 112b8: auipc a0, 0x1 @@ -130,7 +142,7 @@ # IE32: .got 00000008 00012248 -# IE32-LABEL: <.text>: +# IE32-LABEL: <.Ltlsdesc_hi0>: ## st_value(a) = 8 # IE32-NEXT: addi zero, zero, 0x0 # IE32-NEXT: addi zero, zero, 0x0 @@ -138,12 +150,14 @@ # IE32-NEXT: addi a0, zero, 0x8 # IE32-NEXT: add a0, a0, tp ## st_value(b) = 2047 +# IE32-LABEL: <.Ltlsdesc_hi1>: # IE32-NEXT: addi zero, zero, 0x0 # IE32-NEXT: addi zero, zero, 0x0 # IE32-NEXT: addi zero, zero, 0x0 # IE32-NEXT: addi a0, zero, 0x7ff # IE32-NEXT: add a0, a0, tp ## &.got[c]-. = 0x12248+4 - 0x111cc = 0x1080 +# IE32-LABEL: <.Ltlsdesc_hi2>: # IE32-NEXT: addi zero, zero, 0x0 # IE32-NEXT: addi zero, zero, 0x0 # IE32-NEXT: 111cc: auipc a0, 0x1 @@ -192,3 +206,19 @@ b: .tbss .globl c c: .zero 4 + +#--- d.s +.macro load dst, src +.ifdef ELF32 +lw \dst, \src +.else +ld \dst, \src +.endif +.endm + +.Ltlsdesc_hi0: + auipc a0, %tlsdesc_hi(foo) + load a1, %tlsdesc_load_lo(.Ltlsdesc_hi0)(a0) + addi a0, a0, %tlsdesc_add_lo(.Ltlsdesc_hi0) + jalr t0, 0(a1), %tlsdesc_call(.Ltlsdesc_hi0) + add a1, a0, tp diff --git a/lld/test/ELF/riscv-undefined-weak.s b/lld/test/ELF/riscv-undefined-weak.s index 303a27f920c57c918e1b49ef12ec53ebfbe106c9..8a78e1f83833863f78db781ab72bb60798c85021 100644 --- a/lld/test/ELF/riscv-undefined-weak.s +++ b/lld/test/ELF/riscv-undefined-weak.s @@ -1,4 +1,6 @@ # REQUIRES: riscv +# RUN: llvm-mc -filetype=obj -triple=riscv64 /dev/null -o %t2.o +# RUN: ld.lld -shared -soname=t2 %t2.o -o %t2.so # RUN: llvm-mc -filetype=obj -triple=riscv64 -riscv-asm-relax-branches=0 %s -o %t.o # RUN: llvm-readobj -r %t.o | FileCheck --check-prefix=RELOC %s @@ -6,7 +8,7 @@ # RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefixes=CHECK,PC %s # RUN: llvm-readelf -x .data %t | FileCheck --check-prefixes=HEX,HEX-WITHOUT-PLT %s -# RUN: ld.lld -e absolute %t.o -o %t --export-dynamic +# RUN: ld.lld -e absolute %t.o -o %t %t2.so # RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefixes=CHECK,PLT %s # RUN: llvm-readelf -x .data %t | FileCheck --check-prefixes=HEX,HEX-WITH-PLT %s @@ -34,11 +36,11 @@ absolute: # CHECK-LABEL: <relative>: # CHECK-NEXT: 11{{...}}: auipc a1, 0xfffef # PC-NEXT: addi a1, a1, -0x160 -# PLT-NEXT: addi a1, a1, -0x318 +# PLT-NEXT: addi a1, a1, -0x290 # CHECK-LABEL: <.Lpcrel_hi1>: # CHECK-NEXT: 11{{...}}: auipc t1, 0xfffef # PC-NEXT: sd a2, -0x166(t1) -# PLT-NEXT: sd a2, -0x31e(t1) +# PLT-NEXT: sd a2, -0x296(t1) relative: la a1, target sd a2, target+2, t1 @@ -62,7 +64,7 @@ relative: ## We create a PLT entry and redirect the reference to it. # PLT-LABEL: <branch>: # PLT-NEXT: auipc ra, 0x0 -# PLT-NEXT: jalr 0x38(ra) +# PLT-NEXT: jalr 0x30(ra) # PLT-NEXT: [[#%x,ADDR:]]: # PLT-SAME: j 0x[[#ADDR]] # PLT-NEXT: [[#%x,ADDR:]]: @@ -84,12 +86,8 @@ branch: ## A plt entry is created for target, so this is the offset between the ## plt entry and this address. ## -## S = 0x11360 (the address of the plt entry for target) -## A = 0 -## P = 0x1343c (the address of `.`) -## -## S - A + P = -0x0x20dc = 0xffffdf24 -# HEX-WITH-PLT-SAME: 24dfffff +## S - A + P = -0x0x20ec = 0xffffdf14 +# HEX-WITH-PLT-SAME: 14dfffff .data .p2align 3 diff --git a/lld/test/ELF/shlib-undefined-local.s b/lld/test/ELF/shlib-undefined-local.s index 8fceec1bf60ffa1d6150ab5529d786228121c911..6d3e8da34e291c37e0ca43b459c201c373176245 100644 --- a/lld/test/ELF/shlib-undefined-local.s +++ b/lld/test/ELF/shlib-undefined-local.s @@ -5,10 +5,9 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-linux-gnu -o %t2.o %s # RUN: echo "{ local: *; };" > %t.script -# RUN: ld.lld -version-script %t.script -o %t %t2.o %t.so -# RUN: llvm-nm -g %t | FileCheck -allow-empty %s +# RUN: not ld.lld -version-script %t.script %t2.o %t.so -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR -# CHECK-NOT: should_not_be_exported +# ERR: error: non-exported symbol 'should_not_be_exported' in '{{.*}}tmp2.o' is referenced by DSO '{{.*}}tmp.so' .globl should_not_be_exported should_not_be_exported: diff --git a/lld/test/ELF/static-with-export-dynamic.s b/lld/test/ELF/static-with-export-dynamic.s deleted file mode 100644 index b0349b85e30343837e4a8f996efa0aa8828cbd65..0000000000000000000000000000000000000000 --- a/lld/test/ELF/static-with-export-dynamic.s +++ /dev/null @@ -1,32 +0,0 @@ -// REQUIRES: x86 -// RUN: llvm-mc -filetype=obj -triple=i686-unknown-cloudabi %s -o %t.o -// RUN: ld.lld --export-dynamic %t.o -o %t -// RUN: llvm-readobj --dyn-syms %t | FileCheck %s - -// Ensure that a dynamic symbol table is present when --export-dynamic -// is passed in, even when creating statically linked executables. -// -// CHECK: DynamicSymbols [ -// CHECK-NEXT: Symbol { -// CHECK-NEXT: Name: -// CHECK-NEXT: Value: 0x0 -// CHECK-NEXT: Size: 0 -// CHECK-NEXT: Binding: Local -// CHECK-NEXT: Type: None -// CHECK-NEXT: Other: 0 -// CHECK-NEXT: Section: Undefined -// CHECK-NEXT: } -// CHECK-NEXT: Symbol { -// CHECK-NEXT: Name: _start -// CHECK-NEXT: Value: -// CHECK-NEXT: Size: 0 -// CHECK-NEXT: Binding: Global -// CHECK-NEXT: Type: None -// CHECK-NEXT: Other: 0 -// CHECK-NEXT: Section: .text -// CHECK-NEXT: } -// CHECK-NEXT: ] - -.global _start -_start: - ret diff --git a/lld/test/ELF/systemz-ifunc-nonpreemptible.s b/lld/test/ELF/systemz-ifunc-nonpreemptible.s index 5056db302ca1c7cbbc780d63ce8becd93f5a63ab..892bbde8d9c7810e1f68d6bb67b06d371b508743 100644 --- a/lld/test/ELF/systemz-ifunc-nonpreemptible.s +++ b/lld/test/ELF/systemz-ifunc-nonpreemptible.s @@ -10,7 +10,7 @@ # CHECK: Section Headers: # CHECK-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al # CHECK-NEXT: [ 0] NULL 0000000000000000 000000 000000 00 0 0 0 -# CHECK-NEXT: [ 1] .rela.dyn RELA 0000000001000158 000158 000030 18 AI 0 4 8 +# CHECK-NEXT: [ 1] .rela.dyn RELA 0000000001000158 000158 000030 18 A 0 0 8 # CHECK-NEXT: [ 2] .text PROGBITS 0000000001001188 000188 00001c 00 AX 0 0 4 # CHECK-NEXT: [ 3] .iplt PROGBITS 00000000010011b0 0001b0 000040 00 AX 0 0 16 # CHECK-NEXT: [ 4] .got.plt PROGBITS 00000000010021f0 0001f0 000010 00 WA 0 0 8 diff --git a/lld/test/ELF/unknown-section.test b/lld/test/ELF/unknown-section.test new file mode 100644 index 0000000000000000000000000000000000000000..f6ecca29a22aeddfc65699535f9b99281dc836a9 --- /dev/null +++ b/lld/test/ELF/unknown-section.test @@ -0,0 +1,48 @@ +# RUN: rm -rf %t && mkdir %t && cd %t +# RUN: yaml2obj %s -o a.o +# RUN: not ld.lld a.o -o /dev/null 2>&1 | FileCheck %s --implicit-check-not=error: + +# CHECK: error: a.o:(relr): unknown section type 0x13 +# CHECK-NEXT: error: a.o:(regular): unknown section type 0x15 +# CHECK-NEXT: error: a.o:(loos_nonconforming): unknown section type 0x60000000 +# CHECK-NEXT: error: a.o:(hios_nonconforming): unknown section type 0x6fffffff +# CHECK-NEXT: error: a.o:(louser_alloc): unknown section type 0x80000000 +# CHECK-NEXT: error: a.o:(hiuser_alloc): unknown section type 0xffffffff + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: relr + Type: 19 + - Name: regular + Type: 21 + - Name: loos + Type: 0x60000000 + - Name: hios + Type: 0x6fffffff + - Name: loos_nonconforming + Type: 0x60000000 + Flags: [ SHF_OS_NONCONFORMING ] + - Name: hios_nonconforming + Type: 0x6fffffff + Flags: [ SHF_OS_NONCONFORMING ] + + - Name: loproc + Type: 0x70000000 + - Name: hiproc + Type: 0x7fffffff + + - Name: louser + Type: 0x80000000 + - Name: hiuser + Type: 0xffffffff + - Name: louser_alloc + Type: 0x80000000 + Flags: [ SHF_ALLOC ] + - Name: hiuser_alloc + Type: 0xffffffff + Flags: [ SHF_ALLOC ] diff --git a/lld/test/ELF/weak-undef.s b/lld/test/ELF/weak-undef.s index 3a9d5f462c21b6ae937eeeb8872cf6ed455d0551..21488023a79e10bb5c253b501c211d50ddffaf78 100644 --- a/lld/test/ELF/weak-undef.s +++ b/lld/test/ELF/weak-undef.s @@ -16,10 +16,11 @@ # RELOC-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend # RELOC-NEXT: {{.*}} 0000000100000001 R_X86_64_64 0000000000000000 foo + 0 -# COMMON: Symbol table '.dynsym' contains 2 entries: -# COMMON-NEXT: Num: Value Size Type Bind Vis Ndx Name -# COMMON-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND -# COMMON-NEXT: 1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND foo +# NORELOC-NOT: Symbol table '.dynsym' +# RELOC: Symbol table '.dynsym' contains 2 entries: +# RELOC-NEXT: Num: Value Size Type Bind Vis Ndx Name +# RELOC-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND +# RELOC-NEXT: 1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND foo # COMMON: Hex dump of section '.data': # COMMON-NEXT: {{.*}} 00000000 00000000 # COMMON-EMPTY: diff --git a/lld/test/ELF/x86-64-dyn-rel-error.s b/lld/test/ELF/x86-64-dyn-rel-error.s index a03adf89072f31336047fe02268ec920742d426d..1590045312d4a34fa8db59a392d2d8ae27fb8734 100644 --- a/lld/test/ELF/x86-64-dyn-rel-error.s +++ b/lld/test/ELF/x86-64-dyn-rel-error.s @@ -19,7 +19,7 @@ # CHECK-NOT: error: # RUN: ld.lld --noinhibit-exec %t.o %t2.so -o /dev/null 2>&1 | FileCheck --check-prefix=WARN %s -# RUN: not ld.lld --export-dynamic --unresolved-symbols=ignore-all %t.o -o /dev/null 2>&1 | FileCheck --check-prefix=WARN %s +# RUN: not ld.lld --export-dynamic --unresolved-symbols=ignore-all %t.o %t2.so -o /dev/null 2>&1 | FileCheck --check-prefix=WARN %s # WARN: relocation R_X86_64_32 cannot be used against symbol 'zed'; recompile with -fPIC # WARN: relocation R_X86_64_PC32 cannot be used against symbol 'zed'; recompile with -fPIC diff --git a/lld/test/ELF/x86-64-gotpc-relax-too-far.s b/lld/test/ELF/x86-64-gotpc-relax-too-far.s index 74aa6d8f65a0d8de879db4bc042868c9b3016202..ba41faab67de5c551fb65e45dbf908715008e897 100644 --- a/lld/test/ELF/x86-64-gotpc-relax-too-far.s +++ b/lld/test/ELF/x86-64-gotpc-relax-too-far.s @@ -5,7 +5,10 @@ # RUN: llvm-objdump --no-print-imm-hex -d %t/bin | FileCheck --check-prefix=DISASM %s # RUN: llvm-readelf -S %t/bin | FileCheck --check-prefixes=GOT %s # RUN: ld.lld -T %t/lds2 %t/a.o -o %t/bin2 -# RUN: llvm-readelf -S %t/bin2 | FileCheck --check-prefixes=UNNECESSARY-GOT %s +# RUN: llvm-objdump --no-print-imm-hex -d %t/bin2 | FileCheck --check-prefix=DISASM %s +# RUN: llvm-readelf -S %t/bin2 | FileCheck --check-prefixes=GOT %s +# RUN: ld.lld -T %t/lds3 %t/a.o -o %t/bin3 +# RUN: llvm-readelf -S %t/bin3 | FileCheck --check-prefixes=UNNECESSARY-GOT %s # DISASM: <_foo>: # DISASM-NEXT: movl 2097146(%rip), %eax @@ -47,6 +50,13 @@ SECTIONS { data 0x80200000 : { *(data) } } #--- lds2 +SECTIONS { + .text.foo 0x100000 : { *(.text.foo) } + .text 0x1ff000 : { . = . + 0x1000 ; *(.text) } + .got 0x300000 : { *(.got) } + data 0x80200000 : { *(data) } +} +#--- lds3 SECTIONS { .text.foo 0x100000 : { *(.text.foo) } .text 0x200000 : { *(.text) } diff --git a/lld/test/MachO/objc-category-merging-complete-test.s b/lld/test/MachO/objc-category-merging-complete-test.s new file mode 100644 index 0000000000000000000000000000000000000000..3bc3ca26b6ae6c86de08d18b5a8522a9f91cec5d --- /dev/null +++ b/lld/test/MachO/objc-category-merging-complete-test.s @@ -0,0 +1,762 @@ +# REQUIRES: aarch64 +# RUN: rm -rf %t; split-file %s %t && cd %t + +## Create a dylib to link against(a64_file1.dylib) and merge categories in the main binary (file2_merge_a64.exe) +# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o a64_file1.o a64_file1.s +# RUN: %lld -arch arm64 a64_file1.o -o a64_file1.dylib -dylib + +# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o a64_file2.o a64_file2.s +# RUN: %lld -arch arm64 -o a64_file2_no_merge.exe a64_file1.dylib a64_file2.o +# RUN: %lld -arch arm64 -o a64_file2_merge.exe -objc_category_merging a64_file1.dylib a64_file2.o + +# RUN: llvm-objdump --objc-meta-data --macho a64_file2_no_merge.exe | FileCheck %s --check-prefixes=NO_MERGE_CATS +# RUN: llvm-objdump --objc-meta-data --macho a64_file2_merge.exe | FileCheck %s --check-prefixes=MERGE_CATS + + +MERGE_CATS: __OBJC_$_CATEGORY_MyBaseClass_$_(Category02|Category03) +MERGE_CATS-NEXT: name {{.*}} Category02|Category03 +MERGE_CATS: instanceMethods +MERGE_CATS-NEXT: entsize 24 +MERGE_CATS-NEXT: count 4 +MERGE_CATS-NEXT: name {{.*}} class02InstanceMethod +MERGE_CATS-NEXT: types {{.*}} v16@0:8 +MERGE_CATS-NEXT: imp -[MyBaseClass(Category02) class02InstanceMethod] +MERGE_CATS-NEXT: name {{.*}} myProtocol02Method +MERGE_CATS-NEXT: types {{.*}} v16@0:8 +MERGE_CATS-NEXT: imp -[MyBaseClass(Category02) myProtocol02Method] +MERGE_CATS-NEXT: name {{.*}} class03InstanceMethod +MERGE_CATS-NEXT: types {{.*}} v16@0:8 +MERGE_CATS-NEXT: imp -[MyBaseClass(Category03) class03InstanceMethod] +MERGE_CATS-NEXT: name {{.*}} myProtocol03Method +MERGE_CATS-NEXT: types {{.*}} v16@0:8 +MERGE_CATS-NEXT: imp -[MyBaseClass(Category03) myProtocol03Method] +MERGE_CATS-NEXT: classMethods {{.*}} +MERGE_CATS-NEXT: entsize 24 +MERGE_CATS-NEXT: count 4 +MERGE_CATS-NEXT: name {{.*}} class02ClassMethod +MERGE_CATS-NEXT: types {{.*}} v16@0:8 +MERGE_CATS-NEXT: imp +[MyBaseClass(Category02) class02ClassMethod] +MERGE_CATS-NEXT: name {{.*}} MyProtocol02Prop +MERGE_CATS-NEXT: types {{.*}} i16@0:8 +MERGE_CATS-NEXT: imp +[MyBaseClass(Category02) MyProtocol02Prop] +MERGE_CATS-NEXT: name {{.*}} class03ClassMethod +MERGE_CATS-NEXT: types {{.*}} v16@0:8 +MERGE_CATS-NEXT: imp +[MyBaseClass(Category03) class03ClassMethod] +MERGE_CATS-NEXT: name {{.*}} MyProtocol03Prop +MERGE_CATS-NEXT: types {{.*}} i16@0:8 +MERGE_CATS-NEXT: imp +[MyBaseClass(Category03) MyProtocol03Prop] +MERGE_CATS-NEXT: protocols +MERGE_CATS-NEXT: count 2 +MERGE_CATS-NEXT: list[0] {{.*}} (struct protocol_t *) +MERGE_CATS-NEXT: isa 0x0 +MERGE_CATS-NEXT: name {{.*}} MyProtocol02 +MERGE_CATS-NEXT: protocols 0x0 +MERGE_CATS-NEXT: instanceMethods +MERGE_CATS-NEXT: entsize 24 +MERGE_CATS-NEXT: count 2 +MERGE_CATS-NEXT: name {{.*}} myProtocol02Method +MERGE_CATS-NEXT: types {{.*}} v16@0:8 +MERGE_CATS-NEXT: imp 0x0 +MERGE_CATS-NEXT: name {{.*}} MyProtocol02Prop +MERGE_CATS-NEXT: types {{.*}} i16@0:8 +MERGE_CATS-NEXT: imp 0x0 +MERGE_CATS-NEXT: classMethods +MERGE_CATS-NEXT: optionalInstanceMethods 0x0 +MERGE_CATS-NEXT: optionalClassMethods 0x0 +MERGE_CATS-NEXT: instanceProperties {{.*}} +MERGE_CATS-NEXT: list[1] {{.*}} +MERGE_CATS-NEXT: isa 0x0 +MERGE_CATS-NEXT: name {{.*}} MyProtocol03 +MERGE_CATS-NEXT: protocols 0x0 +MERGE_CATS-NEXT: instanceMethods +MERGE_CATS-NEXT: entsize 24 +MERGE_CATS-NEXT: count 2 +MERGE_CATS-NEXT: name {{.*}} myProtocol03Method +MERGE_CATS-NEXT: types {{.*}} v16@0:8 +MERGE_CATS-NEXT: imp 0x0 +MERGE_CATS-NEXT: name {{.*}} MyProtocol03Prop +MERGE_CATS-NEXT: types {{.*}} i16@0:8 +MERGE_CATS-NEXT: imp 0x0 +MERGE_CATS-NEXT: classMethods 0x0 +MERGE_CATS-NEXT: optionalInstanceMethods 0x0 +MERGE_CATS-NEXT: optionalClassMethods 0x0 +MERGE_CATS-NEXT: instanceProperties {{.*}} +MERGE_CATS-NEXT: instanceProperties +MERGE_CATS-NEXT: entsize 16 +MERGE_CATS-NEXT: count 2 +MERGE_CATS-NEXT: name {{.*}} MyProtocol02Prop +MERGE_CATS-NEXT: attributes {{.*}} Ti,R,D +MERGE_CATS-NEXT: name {{.*}} MyProtocol03Prop +MERGE_CATS-NEXT: attributes {{.*}} Ti,R,D + + +NO_MERGE_CATS-NOT: __OBJC_$_CATEGORY_MyBaseClass_$_(Category02|Category03) +NO_MERGE_CATS: __OBJC_$_CATEGORY_MyBaseClass_$_Category02 +NO_MERGE_CATS: instanceMethods +NO_MERGE_CATS-NEXT: 24 +NO_MERGE_CATS-NEXT: 2 +NO_MERGE_CATS: classMethods +NO_MERGE_CATS-NEXT: 24 +NO_MERGE_CATS-NEXT: 2 + + +#--- a64_file1.s + +## @protocol MyProtocol01 +## - (void)myProtocol01Method; +## @property (nonatomic) int MyProtocol01Prop; +## @end +## +## __attribute__((objc_root_class)) +## @interface MyBaseClass<MyProtocol01> +## - (void)baseInstanceMethod; +## - (void)myProtocol01Method; +## + (void)baseClassMethod; +## @end +## +## @implementation MyBaseClass +## @synthesize MyProtocol01Prop; +## - (void)baseInstanceMethod {} +## - (void)myProtocol01Method {} +## + (void)baseClassMethod {} +## @end +## +## void *_objc_empty_cache; + + .section __TEXT,__text,regular,pure_instructions + .p2align 2 ; -- Begin function -[MyBaseClass baseInstanceMethod] +"-[MyBaseClass baseInstanceMethod]": ; @"\01-[MyBaseClass baseInstanceMethod]" + .cfi_startproc +; %bb.0: ; %entry + ret + .cfi_endproc + ; -- End function + .p2align 2 ; -- Begin function -[MyBaseClass myProtocol01Method] +"-[MyBaseClass myProtocol01Method]": ; @"\01-[MyBaseClass myProtocol01Method]" + .cfi_startproc +; %bb.0: ; %entry + ret + .cfi_endproc + ; -- End function + .p2align 2 ; -- Begin function +[MyBaseClass baseClassMethod] +"+[MyBaseClass baseClassMethod]": ; @"\01+[MyBaseClass baseClassMethod]" + .cfi_startproc +; %bb.0: ; %entry + ret + .cfi_endproc + ; -- End function + .p2align 2 ; -- Begin function -[MyBaseClass MyProtocol01Prop] +"-[MyBaseClass MyProtocol01Prop]": ; @"\01-[MyBaseClass MyProtocol01Prop]" + .cfi_startproc +; %bb.0: ; %entry +Lloh0: + adrp x8, _OBJC_IVAR_$_MyBaseClass.MyProtocol01Prop@PAGE +Lloh1: + ldrsw x8, [x8, _OBJC_IVAR_$_MyBaseClass.MyProtocol01Prop@PAGEOFF] + ldr w0, [x0, x8] + ret + .loh AdrpLdr Lloh0, Lloh1 + .cfi_endproc + ; -- End function + .p2align 2 ; -- Begin function -[MyBaseClass setMyProtocol01Prop:] +"-[MyBaseClass setMyProtocol01Prop:]": ; @"\01-[MyBaseClass setMyProtocol01Prop:]" + .cfi_startproc +; %bb.0: ; %entry +Lloh2: + adrp x8, _OBJC_IVAR_$_MyBaseClass.MyProtocol01Prop@PAGE +Lloh3: + ldrsw x8, [x8, _OBJC_IVAR_$_MyBaseClass.MyProtocol01Prop@PAGEOFF] + str w2, [x0, x8] + ret + .loh AdrpLdr Lloh2, Lloh3 + .cfi_endproc + ; -- End function + .private_extern _OBJC_IVAR_$_MyBaseClass.MyProtocol01Prop ; @"OBJC_IVAR_$_MyBaseClass.MyProtocol01Prop" + .section __DATA,__objc_ivar + .globl _OBJC_IVAR_$_MyBaseClass.MyProtocol01Prop + .p2align 2, 0x0 +_OBJC_IVAR_$_MyBaseClass.MyProtocol01Prop: + .long 0 ; 0x0 + .section __DATA,__objc_data + .globl _OBJC_CLASS_$_MyBaseClass ; @"OBJC_CLASS_$_MyBaseClass" + .p2align 3, 0x0 +_OBJC_CLASS_$_MyBaseClass: + .quad _OBJC_METACLASS_$_MyBaseClass + .quad 0 + .quad __objc_empty_cache + .quad 0 + .quad __OBJC_CLASS_RO_$_MyBaseClass + .globl _OBJC_METACLASS_$_MyBaseClass ; @"OBJC_METACLASS_$_MyBaseClass" + .p2align 3, 0x0 +_OBJC_METACLASS_$_MyBaseClass: + .quad _OBJC_METACLASS_$_MyBaseClass + .quad _OBJC_CLASS_$_MyBaseClass + .quad __objc_empty_cache + .quad 0 + .quad __OBJC_METACLASS_RO_$_MyBaseClass + .section __TEXT,__objc_classname,cstring_literals +l_OBJC_CLASS_NAME_: ; @OBJC_CLASS_NAME_ + .asciz "MyBaseClass" + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_METH_VAR_NAME_: ; @OBJC_METH_VAR_NAME_ + .asciz "baseClassMethod" + .section __TEXT,__objc_methtype,cstring_literals +l_OBJC_METH_VAR_TYPE_: ; @OBJC_METH_VAR_TYPE_ + .asciz "v16@0:8" + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_$_CLASS_METHODS_MyBaseClass" +__OBJC_$_CLASS_METHODS_MyBaseClass: + .long 24 ; 0x18 + .long 1 ; 0x1 + .quad l_OBJC_METH_VAR_NAME_ + .quad l_OBJC_METH_VAR_TYPE_ + .quad "+[MyBaseClass baseClassMethod]" + .section __TEXT,__objc_classname,cstring_literals +l_OBJC_CLASS_NAME_.1: ; @OBJC_CLASS_NAME_.1 + .asciz "MyProtocol01" + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_METH_VAR_NAME_.2: ; @OBJC_METH_VAR_NAME_.2 + .asciz "myProtocol01Method" +l_OBJC_METH_VAR_NAME_.3: ; @OBJC_METH_VAR_NAME_.3 + .asciz "MyProtocol01Prop" + .section __TEXT,__objc_methtype,cstring_literals +l_OBJC_METH_VAR_TYPE_.4: ; @OBJC_METH_VAR_TYPE_.4 + .asciz "i16@0:8" + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_METH_VAR_NAME_.5: ; @OBJC_METH_VAR_NAME_.5 + .asciz "setMyProtocol01Prop:" + .section __TEXT,__objc_methtype,cstring_literals +l_OBJC_METH_VAR_TYPE_.6: ; @OBJC_METH_VAR_TYPE_.6 + .asciz "v20@0:8i16" + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_$_PROTOCOL_INSTANCE_METHODS_MyProtocol01" +__OBJC_$_PROTOCOL_INSTANCE_METHODS_MyProtocol01: + .long 24 ; 0x18 + .long 3 ; 0x3 + .quad l_OBJC_METH_VAR_NAME_.2 + .quad l_OBJC_METH_VAR_TYPE_ + .quad 0 + .quad l_OBJC_METH_VAR_NAME_.3 + .quad l_OBJC_METH_VAR_TYPE_.4 + .quad 0 + .quad l_OBJC_METH_VAR_NAME_.5 + .quad l_OBJC_METH_VAR_TYPE_.6 + .quad 0 + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_PROP_NAME_ATTR_: ; @OBJC_PROP_NAME_ATTR_ + .asciz "MyProtocol01Prop" +l_OBJC_PROP_NAME_ATTR_.7: ; @OBJC_PROP_NAME_ATTR_.7 + .asciz "Ti,N" + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_$_PROP_LIST_MyProtocol01" +__OBJC_$_PROP_LIST_MyProtocol01: + .long 16 ; 0x10 + .long 1 ; 0x1 + .quad l_OBJC_PROP_NAME_ATTR_ + .quad l_OBJC_PROP_NAME_ATTR_.7 + .p2align 3, 0x0 ; @"_OBJC_$_PROTOCOL_METHOD_TYPES_MyProtocol01" +__OBJC_$_PROTOCOL_METHOD_TYPES_MyProtocol01: + .quad l_OBJC_METH_VAR_TYPE_ + .quad l_OBJC_METH_VAR_TYPE_.4 + .quad l_OBJC_METH_VAR_TYPE_.6 + .private_extern __OBJC_PROTOCOL_$_MyProtocol01 ; @"_OBJC_PROTOCOL_$_MyProtocol01" + .section __DATA,__data + .globl __OBJC_PROTOCOL_$_MyProtocol01 + .weak_definition __OBJC_PROTOCOL_$_MyProtocol01 + .p2align 3, 0x0 +__OBJC_PROTOCOL_$_MyProtocol01: + .quad 0 + .quad l_OBJC_CLASS_NAME_.1 + .quad 0 + .quad __OBJC_$_PROTOCOL_INSTANCE_METHODS_MyProtocol01 + .quad 0 + .quad 0 + .quad 0 + .quad __OBJC_$_PROP_LIST_MyProtocol01 + .long 96 ; 0x60 + .long 0 ; 0x0 + .quad __OBJC_$_PROTOCOL_METHOD_TYPES_MyProtocol01 + .quad 0 + .quad 0 + .private_extern __OBJC_LABEL_PROTOCOL_$_MyProtocol01 ; @"_OBJC_LABEL_PROTOCOL_$_MyProtocol01" + .section __DATA,__objc_protolist,coalesced,no_dead_strip + .globl __OBJC_LABEL_PROTOCOL_$_MyProtocol01 + .weak_definition __OBJC_LABEL_PROTOCOL_$_MyProtocol01 + .p2align 3, 0x0 +__OBJC_LABEL_PROTOCOL_$_MyProtocol01: + .quad __OBJC_PROTOCOL_$_MyProtocol01 + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_CLASS_PROTOCOLS_$_MyBaseClass" +__OBJC_CLASS_PROTOCOLS_$_MyBaseClass: + .quad 1 ; 0x1 + .quad __OBJC_PROTOCOL_$_MyProtocol01 + .quad 0 + .p2align 3, 0x0 ; @"_OBJC_METACLASS_RO_$_MyBaseClass" +__OBJC_METACLASS_RO_$_MyBaseClass: + .long 3 ; 0x3 + .long 40 ; 0x28 + .long 40 ; 0x28 + .space 4 + .quad 0 + .quad l_OBJC_CLASS_NAME_ + .quad __OBJC_$_CLASS_METHODS_MyBaseClass + .quad __OBJC_CLASS_PROTOCOLS_$_MyBaseClass + .quad 0 + .quad 0 + .quad 0 + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_METH_VAR_NAME_.8: ; @OBJC_METH_VAR_NAME_.8 + .asciz "baseInstanceMethod" + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_$_INSTANCE_METHODS_MyBaseClass" +__OBJC_$_INSTANCE_METHODS_MyBaseClass: + .long 24 ; 0x18 + .long 4 ; 0x4 + .quad l_OBJC_METH_VAR_NAME_.8 + .quad l_OBJC_METH_VAR_TYPE_ + .quad "-[MyBaseClass baseInstanceMethod]" + .quad l_OBJC_METH_VAR_NAME_.2 + .quad l_OBJC_METH_VAR_TYPE_ + .quad "-[MyBaseClass myProtocol01Method]" + .quad l_OBJC_METH_VAR_NAME_.3 + .quad l_OBJC_METH_VAR_TYPE_.4 + .quad "-[MyBaseClass MyProtocol01Prop]" + .quad l_OBJC_METH_VAR_NAME_.5 + .quad l_OBJC_METH_VAR_TYPE_.6 + .quad "-[MyBaseClass setMyProtocol01Prop:]" + .section __TEXT,__objc_methtype,cstring_literals +l_OBJC_METH_VAR_TYPE_.9: ; @OBJC_METH_VAR_TYPE_.9 + .asciz "i" + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_$_INSTANCE_VARIABLES_MyBaseClass" +__OBJC_$_INSTANCE_VARIABLES_MyBaseClass: + .long 32 ; 0x20 + .long 1 ; 0x1 + .quad _OBJC_IVAR_$_MyBaseClass.MyProtocol01Prop + .quad l_OBJC_METH_VAR_NAME_.3 + .quad l_OBJC_METH_VAR_TYPE_.9 + .long 2 ; 0x2 + .long 4 ; 0x4 + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_PROP_NAME_ATTR_.10: ; @OBJC_PROP_NAME_ATTR_.10 + .asciz "Ti,N,VMyProtocol01Prop" + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_$_PROP_LIST_MyBaseClass" +__OBJC_$_PROP_LIST_MyBaseClass: + .long 16 ; 0x10 + .long 1 ; 0x1 + .quad l_OBJC_PROP_NAME_ATTR_ + .quad l_OBJC_PROP_NAME_ATTR_.10 + .p2align 3, 0x0 ; @"_OBJC_CLASS_RO_$_MyBaseClass" +__OBJC_CLASS_RO_$_MyBaseClass: + .long 2 ; 0x2 + .long 0 ; 0x0 + .long 4 ; 0x4 + .space 4 + .quad 0 + .quad l_OBJC_CLASS_NAME_ + .quad __OBJC_$_INSTANCE_METHODS_MyBaseClass + .quad __OBJC_CLASS_PROTOCOLS_$_MyBaseClass + .quad __OBJC_$_INSTANCE_VARIABLES_MyBaseClass + .quad 0 + .quad __OBJC_$_PROP_LIST_MyBaseClass + .globl __objc_empty_cache ; @_objc_empty_cache +.zerofill __DATA,__common,__objc_empty_cache,8,3 + .section __DATA,__objc_classlist,regular,no_dead_strip + .p2align 3, 0x0 ; @"OBJC_LABEL_CLASS_$" +l_OBJC_LABEL_CLASS_$: + .quad _OBJC_CLASS_$_MyBaseClass + .no_dead_strip __OBJC_LABEL_PROTOCOL_$_MyProtocol01 + .no_dead_strip __OBJC_PROTOCOL_$_MyProtocol01 + .section __DATA,__objc_imageinfo,regular,no_dead_strip +L_OBJC_IMAGE_INFO: + .long 0 + .long 96 +.subsections_via_symbols + + +#--- a64_file2.s + +## @protocol MyProtocol01 +## - (void)myProtocol01Method; +## @end +## +## @protocol MyProtocol02 +## - (void)myProtocol02Method; +## @property(readonly) int MyProtocol02Prop; +## @end +## +## @protocol MyProtocol03 +## - (void)myProtocol03Method; +## @property(readonly) int MyProtocol03Prop; +## @end +## +## +## __attribute__((objc_root_class)) +## @interface MyBaseClass<MyProtocol01> +## - (void)baseInstanceMethod; +## - (void)myProtocol01Method; +## + (void)baseClassMethod; +## @end +## +## +## +## @interface MyBaseClass(Category02)<MyProtocol02> +## - (void)class02InstanceMethod; +## - (void)myProtocol02Method; +## + (void)class02ClassMethod; +## + (int)MyProtocol02Prop; +## @end +## +## @implementation MyBaseClass(Category02) +## - (void)class02InstanceMethod {} +## - (void)myProtocol02Method {} +## + (void)class02ClassMethod {} +## + (int)MyProtocol02Prop { return 0;} +## @dynamic MyProtocol02Prop; +## @end +## +## @interface MyBaseClass(Category03)<MyProtocol03> +## - (void)class03InstanceMethod; +## - (void)myProtocol03Method; +## + (void)class03ClassMethod; +## + (int)MyProtocol03Prop; +## @end +## +## @implementation MyBaseClass(Category03) +## - (void)class03InstanceMethod {} +## - (void)myProtocol03Method {} +## + (void)class03ClassMethod {} +## + (int)MyProtocol03Prop { return 0;} +## @dynamic MyProtocol03Prop; +## @end +## +## int main() { +## return 0; +## } + + + .section __TEXT,__text,regular,pure_instructions + .p2align 2 ; -- Begin function -[MyBaseClass(Category02) class02InstanceMethod] +"-[MyBaseClass(Category02) class02InstanceMethod]": ; @"\01-[MyBaseClass(Category02) class02InstanceMethod]" + .cfi_startproc +; %bb.0: ; %entry + ret + .cfi_endproc + ; -- End function + .p2align 2 ; -- Begin function -[MyBaseClass(Category02) myProtocol02Method] +"-[MyBaseClass(Category02) myProtocol02Method]": ; @"\01-[MyBaseClass(Category02) myProtocol02Method]" + .cfi_startproc +; %bb.0: ; %entry + ret + .cfi_endproc + ; -- End function + .p2align 2 ; -- Begin function +[MyBaseClass(Category02) class02ClassMethod] +"+[MyBaseClass(Category02) class02ClassMethod]": ; @"\01+[MyBaseClass(Category02) class02ClassMethod]" + .cfi_startproc +; %bb.0: ; %entry + ret + .cfi_endproc + ; -- End function + .p2align 2 ; -- Begin function +[MyBaseClass(Category02) MyProtocol02Prop] +"+[MyBaseClass(Category02) MyProtocol02Prop]": ; @"\01+[MyBaseClass(Category02) MyProtocol02Prop]" + .cfi_startproc +; %bb.0: ; %entry + b _OUTLINED_FUNCTION_0 + .cfi_endproc + ; -- End function + .p2align 2 ; -- Begin function -[MyBaseClass(Category03) class03InstanceMethod] +"-[MyBaseClass(Category03) class03InstanceMethod]": ; @"\01-[MyBaseClass(Category03) class03InstanceMethod]" + .cfi_startproc +; %bb.0: ; %entry + ret + .cfi_endproc + ; -- End function + .p2align 2 ; -- Begin function -[MyBaseClass(Category03) myProtocol03Method] +"-[MyBaseClass(Category03) myProtocol03Method]": ; @"\01-[MyBaseClass(Category03) myProtocol03Method]" + .cfi_startproc +; %bb.0: ; %entry + ret + .cfi_endproc + ; -- End function + .p2align 2 ; -- Begin function +[MyBaseClass(Category03) class03ClassMethod] +"+[MyBaseClass(Category03) class03ClassMethod]": ; @"\01+[MyBaseClass(Category03) class03ClassMethod]" + .cfi_startproc +; %bb.0: ; %entry + ret + .cfi_endproc + ; -- End function + .p2align 2 ; -- Begin function +[MyBaseClass(Category03) MyProtocol03Prop] +"+[MyBaseClass(Category03) MyProtocol03Prop]": ; @"\01+[MyBaseClass(Category03) MyProtocol03Prop]" + .cfi_startproc +; %bb.0: ; %entry + b _OUTLINED_FUNCTION_0 + .cfi_endproc + ; -- End function + .globl _main ; -- Begin function main + .p2align 2 +_main: ; @main + .cfi_startproc +; %bb.0: ; %entry + b _OUTLINED_FUNCTION_0 + .cfi_endproc + ; -- End function + .p2align 2 ; -- Begin function OUTLINED_FUNCTION_0 +_OUTLINED_FUNCTION_0: ; @OUTLINED_FUNCTION_0 Tail Call + .cfi_startproc +; %bb.0: + mov w0, #0 + ret + .cfi_endproc + ; -- End function + .section __TEXT,__objc_classname,cstring_literals +l_OBJC_CLASS_NAME_: ; @OBJC_CLASS_NAME_ + .asciz "Category02" + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_METH_VAR_NAME_: ; @OBJC_METH_VAR_NAME_ + .asciz "class02InstanceMethod" + .section __TEXT,__objc_methtype,cstring_literals +l_OBJC_METH_VAR_TYPE_: ; @OBJC_METH_VAR_TYPE_ + .asciz "v16@0:8" + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_METH_VAR_NAME_.1: ; @OBJC_METH_VAR_NAME_.1 + .asciz "myProtocol02Method" + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category02" +__OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category02: + .long 24 ; 0x18 + .long 2 ; 0x2 + .quad l_OBJC_METH_VAR_NAME_ + .quad l_OBJC_METH_VAR_TYPE_ + .quad "-[MyBaseClass(Category02) class02InstanceMethod]" + .quad l_OBJC_METH_VAR_NAME_.1 + .quad l_OBJC_METH_VAR_TYPE_ + .quad "-[MyBaseClass(Category02) myProtocol02Method]" + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_METH_VAR_NAME_.2: ; @OBJC_METH_VAR_NAME_.2 + .asciz "class02ClassMethod" +l_OBJC_METH_VAR_NAME_.3: ; @OBJC_METH_VAR_NAME_.3 + .asciz "MyProtocol02Prop" + .section __TEXT,__objc_methtype,cstring_literals +l_OBJC_METH_VAR_TYPE_.4: ; @OBJC_METH_VAR_TYPE_.4 + .asciz "i16@0:8" + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_CLASS_METHODS_MyBaseClass_$_Category02" +__OBJC_$_CATEGORY_CLASS_METHODS_MyBaseClass_$_Category02: + .long 24 ; 0x18 + .long 2 ; 0x2 + .quad l_OBJC_METH_VAR_NAME_.2 + .quad l_OBJC_METH_VAR_TYPE_ + .quad "+[MyBaseClass(Category02) class02ClassMethod]" + .quad l_OBJC_METH_VAR_NAME_.3 + .quad l_OBJC_METH_VAR_TYPE_.4 + .quad "+[MyBaseClass(Category02) MyProtocol02Prop]" + .section __TEXT,__objc_classname,cstring_literals +l_OBJC_CLASS_NAME_.5: ; @OBJC_CLASS_NAME_.5 + .asciz "MyProtocol02" + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_$_PROTOCOL_INSTANCE_METHODS_MyProtocol02" +__OBJC_$_PROTOCOL_INSTANCE_METHODS_MyProtocol02: + .long 24 ; 0x18 + .long 2 ; 0x2 + .quad l_OBJC_METH_VAR_NAME_.1 + .quad l_OBJC_METH_VAR_TYPE_ + .quad 0 + .quad l_OBJC_METH_VAR_NAME_.3 + .quad l_OBJC_METH_VAR_TYPE_.4 + .quad 0 + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_PROP_NAME_ATTR_: ; @OBJC_PROP_NAME_ATTR_ + .asciz "MyProtocol02Prop" +l_OBJC_PROP_NAME_ATTR_.6: ; @OBJC_PROP_NAME_ATTR_.6 + .asciz "Ti,R" + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_$_PROP_LIST_MyProtocol02" +__OBJC_$_PROP_LIST_MyProtocol02: + .long 16 ; 0x10 + .long 1 ; 0x1 + .quad l_OBJC_PROP_NAME_ATTR_ + .quad l_OBJC_PROP_NAME_ATTR_.6 + .p2align 3, 0x0 ; @"_OBJC_$_PROTOCOL_METHOD_TYPES_MyProtocol02" +__OBJC_$_PROTOCOL_METHOD_TYPES_MyProtocol02: + .quad l_OBJC_METH_VAR_TYPE_ + .quad l_OBJC_METH_VAR_TYPE_.4 + .private_extern __OBJC_PROTOCOL_$_MyProtocol02 ; @"_OBJC_PROTOCOL_$_MyProtocol02" + .section __DATA,__data + .globl __OBJC_PROTOCOL_$_MyProtocol02 + .weak_definition __OBJC_PROTOCOL_$_MyProtocol02 + .p2align 3, 0x0 +__OBJC_PROTOCOL_$_MyProtocol02: + .quad 0 + .quad l_OBJC_CLASS_NAME_.5 + .quad 0 + .quad __OBJC_$_PROTOCOL_INSTANCE_METHODS_MyProtocol02 + .quad 0 + .quad 0 + .quad 0 + .quad __OBJC_$_PROP_LIST_MyProtocol02 + .long 96 ; 0x60 + .long 0 ; 0x0 + .quad __OBJC_$_PROTOCOL_METHOD_TYPES_MyProtocol02 + .quad 0 + .quad 0 + .private_extern __OBJC_LABEL_PROTOCOL_$_MyProtocol02 ; @"_OBJC_LABEL_PROTOCOL_$_MyProtocol02" + .section __DATA,__objc_protolist,coalesced,no_dead_strip + .globl __OBJC_LABEL_PROTOCOL_$_MyProtocol02 + .weak_definition __OBJC_LABEL_PROTOCOL_$_MyProtocol02 + .p2align 3, 0x0 +__OBJC_LABEL_PROTOCOL_$_MyProtocol02: + .quad __OBJC_PROTOCOL_$_MyProtocol02 + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_CATEGORY_PROTOCOLS_$_MyBaseClass_$_Category02" +__OBJC_CATEGORY_PROTOCOLS_$_MyBaseClass_$_Category02: + .quad 1 ; 0x1 + .quad __OBJC_PROTOCOL_$_MyProtocol02 + .quad 0 + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_PROP_NAME_ATTR_.7: ; @OBJC_PROP_NAME_ATTR_.7 + .asciz "Ti,R,D" + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_$_PROP_LIST_MyBaseClass_$_Category02" +__OBJC_$_PROP_LIST_MyBaseClass_$_Category02: + .long 16 ; 0x10 + .long 1 ; 0x1 + .quad l_OBJC_PROP_NAME_ATTR_ + .quad l_OBJC_PROP_NAME_ATTR_.7 + .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_MyBaseClass_$_Category02" +__OBJC_$_CATEGORY_MyBaseClass_$_Category02: + .quad l_OBJC_CLASS_NAME_ + .quad _OBJC_CLASS_$_MyBaseClass + .quad __OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category02 + .quad __OBJC_$_CATEGORY_CLASS_METHODS_MyBaseClass_$_Category02 + .quad __OBJC_CATEGORY_PROTOCOLS_$_MyBaseClass_$_Category02 + .quad __OBJC_$_PROP_LIST_MyBaseClass_$_Category02 + .quad 0 + .long 64 ; 0x40 + .space 4 + .section __TEXT,__objc_classname,cstring_literals +l_OBJC_CLASS_NAME_.8: ; @OBJC_CLASS_NAME_.8 + .asciz "Category03" + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_METH_VAR_NAME_.9: ; @OBJC_METH_VAR_NAME_.9 + .asciz "class03InstanceMethod" +l_OBJC_METH_VAR_NAME_.10: ; @OBJC_METH_VAR_NAME_.10 + .asciz "myProtocol03Method" + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category03" +__OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category03: + .long 24 ; 0x18 + .long 2 ; 0x2 + .quad l_OBJC_METH_VAR_NAME_.9 + .quad l_OBJC_METH_VAR_TYPE_ + .quad "-[MyBaseClass(Category03) class03InstanceMethod]" + .quad l_OBJC_METH_VAR_NAME_.10 + .quad l_OBJC_METH_VAR_TYPE_ + .quad "-[MyBaseClass(Category03) myProtocol03Method]" + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_METH_VAR_NAME_.11: ; @OBJC_METH_VAR_NAME_.11 + .asciz "class03ClassMethod" +l_OBJC_METH_VAR_NAME_.12: ; @OBJC_METH_VAR_NAME_.12 + .asciz "MyProtocol03Prop" + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_CLASS_METHODS_MyBaseClass_$_Category03" +__OBJC_$_CATEGORY_CLASS_METHODS_MyBaseClass_$_Category03: + .long 24 ; 0x18 + .long 2 ; 0x2 + .quad l_OBJC_METH_VAR_NAME_.11 + .quad l_OBJC_METH_VAR_TYPE_ + .quad "+[MyBaseClass(Category03) class03ClassMethod]" + .quad l_OBJC_METH_VAR_NAME_.12 + .quad l_OBJC_METH_VAR_TYPE_.4 + .quad "+[MyBaseClass(Category03) MyProtocol03Prop]" + .section __TEXT,__objc_classname,cstring_literals +l_OBJC_CLASS_NAME_.13: ; @OBJC_CLASS_NAME_.13 + .asciz "MyProtocol03" + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_$_PROTOCOL_INSTANCE_METHODS_MyProtocol03" +__OBJC_$_PROTOCOL_INSTANCE_METHODS_MyProtocol03: + .long 24 ; 0x18 + .long 2 ; 0x2 + .quad l_OBJC_METH_VAR_NAME_.10 + .quad l_OBJC_METH_VAR_TYPE_ + .quad 0 + .quad l_OBJC_METH_VAR_NAME_.12 + .quad l_OBJC_METH_VAR_TYPE_.4 + .quad 0 + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_PROP_NAME_ATTR_.14: ; @OBJC_PROP_NAME_ATTR_.14 + .asciz "MyProtocol03Prop" + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_$_PROP_LIST_MyProtocol03" +__OBJC_$_PROP_LIST_MyProtocol03: + .long 16 ; 0x10 + .long 1 ; 0x1 + .quad l_OBJC_PROP_NAME_ATTR_.14 + .quad l_OBJC_PROP_NAME_ATTR_.6 + .p2align 3, 0x0 ; @"_OBJC_$_PROTOCOL_METHOD_TYPES_MyProtocol03" +__OBJC_$_PROTOCOL_METHOD_TYPES_MyProtocol03: + .quad l_OBJC_METH_VAR_TYPE_ + .quad l_OBJC_METH_VAR_TYPE_.4 + .private_extern __OBJC_PROTOCOL_$_MyProtocol03 ; @"_OBJC_PROTOCOL_$_MyProtocol03" + .section __DATA,__data + .globl __OBJC_PROTOCOL_$_MyProtocol03 + .weak_definition __OBJC_PROTOCOL_$_MyProtocol03 + .p2align 3, 0x0 +__OBJC_PROTOCOL_$_MyProtocol03: + .quad 0 + .quad l_OBJC_CLASS_NAME_.13 + .quad 0 + .quad __OBJC_$_PROTOCOL_INSTANCE_METHODS_MyProtocol03 + .quad 0 + .quad 0 + .quad 0 + .quad __OBJC_$_PROP_LIST_MyProtocol03 + .long 96 ; 0x60 + .long 0 ; 0x0 + .quad __OBJC_$_PROTOCOL_METHOD_TYPES_MyProtocol03 + .quad 0 + .quad 0 + .private_extern __OBJC_LABEL_PROTOCOL_$_MyProtocol03 ; @"_OBJC_LABEL_PROTOCOL_$_MyProtocol03" + .section __DATA,__objc_protolist,coalesced,no_dead_strip + .globl __OBJC_LABEL_PROTOCOL_$_MyProtocol03 + .weak_definition __OBJC_LABEL_PROTOCOL_$_MyProtocol03 + .p2align 3, 0x0 +__OBJC_LABEL_PROTOCOL_$_MyProtocol03: + .quad __OBJC_PROTOCOL_$_MyProtocol03 + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_CATEGORY_PROTOCOLS_$_MyBaseClass_$_Category03" +__OBJC_CATEGORY_PROTOCOLS_$_MyBaseClass_$_Category03: + .quad 1 ; 0x1 + .quad __OBJC_PROTOCOL_$_MyProtocol03 + .quad 0 + .p2align 3, 0x0 ; @"_OBJC_$_PROP_LIST_MyBaseClass_$_Category03" +__OBJC_$_PROP_LIST_MyBaseClass_$_Category03: + .long 16 ; 0x10 + .long 1 ; 0x1 + .quad l_OBJC_PROP_NAME_ATTR_.14 + .quad l_OBJC_PROP_NAME_ATTR_.7 + .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_MyBaseClass_$_Category03" +__OBJC_$_CATEGORY_MyBaseClass_$_Category03: + .quad l_OBJC_CLASS_NAME_.8 + .quad _OBJC_CLASS_$_MyBaseClass + .quad __OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category03 + .quad __OBJC_$_CATEGORY_CLASS_METHODS_MyBaseClass_$_Category03 + .quad __OBJC_CATEGORY_PROTOCOLS_$_MyBaseClass_$_Category03 + .quad __OBJC_$_PROP_LIST_MyBaseClass_$_Category03 + .quad 0 + .long 64 ; 0x40 + .space 4 + .section __DATA,__objc_catlist,regular,no_dead_strip + .p2align 3, 0x0 ; @"OBJC_LABEL_CATEGORY_$" +l_OBJC_LABEL_CATEGORY_$: + .quad __OBJC_$_CATEGORY_MyBaseClass_$_Category02 + .quad __OBJC_$_CATEGORY_MyBaseClass_$_Category03 + .no_dead_strip __OBJC_LABEL_PROTOCOL_$_MyProtocol02 + .no_dead_strip __OBJC_LABEL_PROTOCOL_$_MyProtocol03 + .no_dead_strip __OBJC_PROTOCOL_$_MyProtocol02 + .no_dead_strip __OBJC_PROTOCOL_$_MyProtocol03 + .section __DATA,__objc_imageinfo,regular,no_dead_strip +L_OBJC_IMAGE_INFO: + .long 0 + .long 96 +.subsections_via_symbols diff --git a/lld/test/MachO/objc-category-merging-extern-class-minimal.s b/lld/test/MachO/objc-category-merging-extern-class-minimal.s new file mode 100644 index 0000000000000000000000000000000000000000..ede7ef5d9c32d4586c74ebfd05f926ab4d244785 --- /dev/null +++ b/lld/test/MachO/objc-category-merging-extern-class-minimal.s @@ -0,0 +1,155 @@ +# REQUIRES: aarch64 +# RUN: rm -rf %t; split-file %s %t && cd %t + +## Create a dylib with a fake base class to link against +# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o a64_fakedylib.o a64_fakedylib.s +# RUN: %lld -arch arm64 a64_fakedylib.o -o a64_fakedylib.dylib -dylib + +## Create our main testing dylib - linking against the fake dylib above +# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o merge_cat_minimal.o merge_cat_minimal.s +# RUN: %lld -arch arm64 -dylib -o merge_cat_minimal_no_merge.dylib a64_fakedylib.dylib merge_cat_minimal.o +# RUN: %lld -arch arm64 -dylib -o merge_cat_minimal_merge.dylib -objc_category_merging a64_fakedylib.dylib merge_cat_minimal.o + +## Now verify that the flag caused category merging to happen appropriatelly +# RUN: llvm-objdump --objc-meta-data --macho merge_cat_minimal_no_merge.dylib | FileCheck %s --check-prefixes=NO_MERGE_CATS +# RUN: llvm-objdump --objc-meta-data --macho merge_cat_minimal_merge.dylib | FileCheck %s --check-prefixes=MERGE_CATS + +#### Check merge categories enabled ### +# Check that the original categories are not there +MERGE_CATS-NOT: __OBJC_$_CATEGORY_MyBaseClass_$_Category01 +MERGE_CATS-NOT: __OBJC_$_CATEGORY_MyBaseClass_$_Category02 + +# Check that the merged cateogry is there, in the correct format +MERGE_CATS: __OBJC_$_CATEGORY_MyBaseClass_$_(Category01|Category02) +MERGE_CATS-NEXT: name {{.*}} Category01|Category02 +MERGE_CATS: instanceMethods +MERGE_CATS-NEXT: 24 +MERGE_CATS-NEXT: 2 +MERGE_CATS-NEXT: name {{.*}} cat01_InstanceMethod +MERGE_CATS-NEXT: types {{.*}} v16@0:8 +MERGE_CATS-NEXT: imp -[MyBaseClass(Category01) cat01_InstanceMethod] +MERGE_CATS-NEXT: name {{.*}} cat02_InstanceMethod +MERGE_CATS-NEXT: types {{.*}} v16@0:8 +MERGE_CATS-NEXT: imp -[MyBaseClass(Category02) cat02_InstanceMethod] +MERGE_CATS-NEXT: classMethods 0x0 +MERGE_CATS-NEXT: protocols 0x0 +MERGE_CATS-NEXT: instanceProperties 0x0 + +#### Check merge categories disabled ### +# Check that the merged category is not there +NO_MERGE_CATS-NOT: __OBJC_$_CATEGORY_MyBaseClass_$_(Category01|Category02) + +# Check that the original categories are there +NO_MERGE_CATS: __OBJC_$_CATEGORY_MyBaseClass_$_Category01 +NO_MERGE_CATS: __OBJC_$_CATEGORY_MyBaseClass_$_Category02 + + + +#--- a64_fakedylib.s + + .section __DATA,__objc_data + .globl _OBJC_CLASS_$_MyBaseClass +_OBJC_CLASS_$_MyBaseClass: + .quad 0 + +#--- merge_cat_minimal.s + +; ================== Generated from ObjC: ================== +; __attribute__((objc_root_class)) +; @interface MyBaseClass +; - (void)baseInstanceMethod; +; @end +; +; @interface MyBaseClass(Category01) +; - (void)cat01_InstanceMethod; +; @end +; +; @implementation MyBaseClass(Category01) +; - (void)cat01_InstanceMethod {} +; @end +; +; @interface MyBaseClass(Category02) +; - (void)cat02_InstanceMethod; +; @end +; +; @implementation MyBaseClass(Category02) +; - (void)cat02_InstanceMethod {} +; @end +; ================== Generated from ObjC: ================== + + .section __TEXT,__text,regular,pure_instructions + .p2align 2 ; -- Begin function -[MyBaseClass(Category01) cat01_InstanceMethod] +"-[MyBaseClass(Category01) cat01_InstanceMethod]": ; @"\01-[MyBaseClass(Category01) cat01_InstanceMethod]" + .cfi_startproc + ret + .cfi_endproc + ; -- End function + .p2align 2 ; -- Begin function -[MyBaseClass(Category02) cat02_InstanceMethod] +"-[MyBaseClass(Category02) cat02_InstanceMethod]": ; @"\01-[MyBaseClass(Category02) cat02_InstanceMethod]" + .cfi_startproc + ret + .cfi_endproc + ; -- End function + .section __TEXT,__objc_classname,cstring_literals +l_OBJC_CLASS_NAME_: ; @OBJC_CLASS_NAME_ + .asciz "Category01" + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_METH_VAR_NAME_: ; @OBJC_METH_VAR_NAME_ + .asciz "cat01_InstanceMethod" + .section __TEXT,__objc_methtype,cstring_literals +l_OBJC_METH_VAR_TYPE_: ; @OBJC_METH_VAR_TYPE_ + .asciz "v16@0:8" + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category01" +__OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category01: + .long 24 ; 0x18 + .long 1 ; 0x1 + .quad l_OBJC_METH_VAR_NAME_ + .quad l_OBJC_METH_VAR_TYPE_ + .quad "-[MyBaseClass(Category01) cat01_InstanceMethod]" + .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_MyBaseClass_$_Category01" +__OBJC_$_CATEGORY_MyBaseClass_$_Category01: + .quad l_OBJC_CLASS_NAME_ + .quad _OBJC_CLASS_$_MyBaseClass + .quad __OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category01 + .quad 0 + .quad 0 + .quad 0 + .quad 0 + .long 64 ; 0x40 + .space 4 + .section __TEXT,__objc_classname,cstring_literals +l_OBJC_CLASS_NAME_.1: ; @OBJC_CLASS_NAME_.1 + .asciz "Category02" + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_METH_VAR_NAME_.2: ; @OBJC_METH_VAR_NAME_.2 + .asciz "cat02_InstanceMethod" + .section __DATA,__objc_const + .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category02" +__OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category02: + .long 24 ; 0x18 + .long 1 ; 0x1 + .quad l_OBJC_METH_VAR_NAME_.2 + .quad l_OBJC_METH_VAR_TYPE_ + .quad "-[MyBaseClass(Category02) cat02_InstanceMethod]" + .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_MyBaseClass_$_Category02" +__OBJC_$_CATEGORY_MyBaseClass_$_Category02: + .quad l_OBJC_CLASS_NAME_.1 + .quad _OBJC_CLASS_$_MyBaseClass + .quad __OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category02 + .quad 0 + .quad 0 + .quad 0 + .quad 0 + .long 64 ; 0x40 + .space 4 + .section __DATA,__objc_catlist,regular,no_dead_strip + .p2align 3, 0x0 ; @"OBJC_LABEL_CATEGORY_$" +l_OBJC_LABEL_CATEGORY_$: + .quad __OBJC_$_CATEGORY_MyBaseClass_$_Category01 + .quad __OBJC_$_CATEGORY_MyBaseClass_$_Category02 + .section __DATA,__objc_imageinfo,regular,no_dead_strip +L_OBJC_IMAGE_INFO: + .long 0 + .long 96 +.subsections_via_symbols diff --git a/lld/test/MachO/objc-relative-method-lists-simple.s b/lld/test/MachO/objc-relative-method-lists-simple.s new file mode 100644 index 0000000000000000000000000000000000000000..9f54b5ad828a076ebf1bca778b5b1efa3ccdb55a --- /dev/null +++ b/lld/test/MachO/objc-relative-method-lists-simple.s @@ -0,0 +1,250 @@ +# REQUIRES: aarch64 +# UNSUPPORTED: target=arm{{.*}}-unknown-linux-gnueabihf +# RUN: rm -rf %t; split-file %s %t && cd %t + +## Compile a64_rel_dylib.o +# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o a64_rel_dylib.o a64_simple_class.s + +## Test arm64 + relative method lists +# RUN: %no-lsystem-lld a64_rel_dylib.o -o a64_rel_dylib.dylib -map a64_rel_dylib.map -dylib -arch arm64 -objc_relative_method_lists +# RUN: llvm-objdump --macho --objc-meta-data a64_rel_dylib.dylib | FileCheck %s --check-prefix=CHK_REL + +## Test arm64 + relative method lists + dead-strip +# RUN: %no-lsystem-lld a64_rel_dylib.o -o a64_rel_dylib.dylib -map a64_rel_dylib.map -dylib -arch arm64 -objc_relative_method_lists -dead_strip +# RUN: llvm-objdump --macho --objc-meta-data a64_rel_dylib.dylib | FileCheck %s --check-prefix=CHK_REL + +## Test arm64 + traditional method lists (no relative offsets) +# RUN: %no-lsystem-lld a64_rel_dylib.o -o a64_rel_dylib.dylib -map a64_rel_dylib.map -dylib -arch arm64 -no_objc_relative_method_lists +# RUN: llvm-objdump --macho --objc-meta-data a64_rel_dylib.dylib | FileCheck %s --check-prefix=CHK_NO_REL + + +CHK_REL: Contents of (__DATA_CONST,__objc_classlist) section +CHK_REL-NEXT: _OBJC_CLASS_$_MyClass +CHK_REL: baseMethods +CHK_REL-NEXT: entsize 12 (relative) +CHK_REL-NEXT: count 3 +CHK_REL-NEXT: name 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) instance_method_00 +CHK_REL-NEXT: types 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) v16@0:8 +CHK_REL-NEXT: imp 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) -[MyClass instance_method_00] +CHK_REL-NEXT: name 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) instance_method_01 +CHK_REL-NEXT: types 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) v16@0:8 +CHK_REL-NEXT: imp 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) -[MyClass instance_method_01] +CHK_REL-NEXT: name 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) instance_method_02 +CHK_REL-NEXT: types 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) v16@0:8 +CHK_REL-NEXT: imp 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) -[MyClass instance_method_02] + +CHK_REL: Meta Class +CHK_REL-NEXT: isa 0x{{[0-9a-f]*}} _OBJC_METACLASS_$_MyClass +CHK_REL: baseMethods 0x{{[0-9a-f]*}} (struct method_list_t *) +CHK_REL-NEXT: entsize 12 (relative) +CHK_REL-NEXT: count 3 +CHK_REL-NEXT: name 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) class_method_00 +CHK_REL-NEXT: types 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) v16@0:8 +CHK_REL-NEXT: imp 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) +[MyClass class_method_00] +CHK_REL-NEXT: name 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) class_method_01 +CHK_REL-NEXT: types 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) v16@0:8 +CHK_REL-NEXT: imp 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) +[MyClass class_method_01] +CHK_REL-NEXT: name 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) class_method_02 +CHK_REL-NEXT: types 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) v16@0:8 +CHK_REL-NEXT: imp 0x{{[0-9a-f]*}} (0x{{[0-9a-f]*}}) +[MyClass class_method_02] + + +CHK_NO_REL-NOT: (relative) + +CHK_NO_REL: Contents of (__DATA_CONST,__objc_classlist) section +CHK_NO_REL-NEXT: _OBJC_CLASS_$_MyClass + +CHK_NO_REL: baseMethods 0x{{[0-9a-f]*}} (struct method_list_t *) +CHK_NO_REL-NEXT: entsize 24 +CHK_NO_REL-NEXT: count 3 +CHK_NO_REL-NEXT: name 0x{{[0-9a-f]*}} instance_method_00 +CHK_NO_REL-NEXT: types 0x{{[0-9a-f]*}} v16@0:8 +CHK_NO_REL-NEXT: imp -[MyClass instance_method_00] +CHK_NO_REL-NEXT: name 0x{{[0-9a-f]*}} instance_method_01 +CHK_NO_REL-NEXT: types 0x{{[0-9a-f]*}} v16@0:8 +CHK_NO_REL-NEXT: imp -[MyClass instance_method_01] +CHK_NO_REL-NEXT: name 0x{{[0-9a-f]*}} instance_method_02 +CHK_NO_REL-NEXT: types 0x{{[0-9a-f]*}} v16@0:8 +CHK_NO_REL-NEXT: imp -[MyClass instance_method_02] + + +CHK_NO_REL: Meta Class +CHK_NO_REL-NEXT: _OBJC_METACLASS_$_MyClass + +CHK_NO_REL: baseMethods 0x{{[0-9a-f]*}} (struct method_list_t *) +CHK_NO_REL-NEXT: entsize 24 +CHK_NO_REL-NEXT: count 3 +CHK_NO_REL-NEXT: name 0x{{[0-9a-f]*}} class_method_00 +CHK_NO_REL-NEXT: types 0x{{[0-9a-f]*}} v16@0:8 +CHK_NO_REL-NEXT: imp +[MyClass class_method_00] +CHK_NO_REL-NEXT: name 0x{{[0-9a-f]*}} class_method_01 +CHK_NO_REL-NEXT: types 0x{{[0-9a-f]*}} v16@0:8 +CHK_NO_REL-NEXT: imp +[MyClass class_method_01] +CHK_NO_REL-NEXT: name 0x{{[0-9a-f]*}} class_method_02 +CHK_NO_REL-NEXT: types 0x{{[0-9a-f]*}} v16@0:8 +CHK_NO_REL-NEXT: imp +[MyClass class_method_02] + + +######################## Generate a64_simple_class.s ######################### +# clang -c simple_class.mm -s -o a64_simple_class.s -target arm64-apple-macos -arch arm64 -Oz + +######################## simple_class.mm ######################## +# __attribute__((objc_root_class)) +# @interface MyClass +# - (void)instance_method_00; +# - (void)instance_method_01; +# - (void)instance_method_02; +# + (void)class_method_00; +# + (void)class_method_01; +# + (void)class_method_02; +# @end +# +# @implementation MyClass +# - (void)instance_method_00 {} +# - (void)instance_method_01 {} +# - (void)instance_method_02 {} +# + (void)class_method_00 {} +# + (void)class_method_01 {} +# + (void)class_method_02 {} +# @end +# +# void *_objc_empty_cache; +# void *_objc_empty_vtable; +# + +#--- objc-macros.s +.macro .objc_selector_def name + .p2align 2 +"\name": + .cfi_startproc + ret + .cfi_endproc +.endm + +#--- a64_simple_class.s +.include "objc-macros.s" + +.section __TEXT,__text,regular,pure_instructions +.build_version macos, 11, 0 + +.objc_selector_def "-[MyClass instance_method_00]" +.objc_selector_def "-[MyClass instance_method_01]" +.objc_selector_def "-[MyClass instance_method_02]" + +.objc_selector_def "+[MyClass class_method_00]" +.objc_selector_def "+[MyClass class_method_01]" +.objc_selector_def "+[MyClass class_method_02]" + +.globl __objc_empty_vtable +.zerofill __DATA,__common,__objc_empty_vtable,8,3 +.section __DATA,__objc_data +.globl _OBJC_CLASS_$_MyClass +.p2align 3, 0x0 + +_OBJC_CLASS_$_MyClass: + .quad _OBJC_METACLASS_$_MyClass + .quad 0 + .quad __objc_empty_cache + .quad __objc_empty_vtable + .quad __OBJC_CLASS_RO_$_MyClass + .globl _OBJC_METACLASS_$_MyClass + .p2align 3, 0x0 + +_OBJC_METACLASS_$_MyClass: + .quad _OBJC_METACLASS_$_MyClass + .quad _OBJC_CLASS_$_MyClass + .quad __objc_empty_cache + .quad __objc_empty_vtable + .quad __OBJC_METACLASS_RO_$_MyClass + + .section __TEXT,__objc_classname,cstring_literals +l_OBJC_CLASS_NAME_: + .asciz "MyClass" + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_METH_VAR_NAME_: + .asciz "class_method_00" + .section __TEXT,__objc_methtype,cstring_literals +l_OBJC_METH_VAR_TYPE_: + .asciz "v16@0:8" + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_METH_VAR_NAME_.1: + .asciz "class_method_01" +l_OBJC_METH_VAR_NAME_.2: + .asciz "class_method_02" + .section __DATA,__objc_const + .p2align 3, 0x0 +__OBJC_$_CLASS_METHODS_MyClass: + .long 24 + .long 3 + .quad l_OBJC_METH_VAR_NAME_ + .quad l_OBJC_METH_VAR_TYPE_ + .quad "+[MyClass class_method_00]" + .quad l_OBJC_METH_VAR_NAME_.1 + .quad l_OBJC_METH_VAR_TYPE_ + .quad "+[MyClass class_method_01]" + .quad l_OBJC_METH_VAR_NAME_.2 + .quad l_OBJC_METH_VAR_TYPE_ + .quad "+[MyClass class_method_02]" + .p2align 3, 0x0 + +__OBJC_METACLASS_RO_$_MyClass: + .long 3 + .long 40 + .long 40 + .space 4 + .quad 0 + .quad l_OBJC_CLASS_NAME_ + .quad __OBJC_$_CLASS_METHODS_MyClass + .quad 0 + .quad 0 + .quad 0 + .quad 0 + + .section __TEXT,__objc_methname,cstring_literals +l_OBJC_METH_VAR_NAME_.3: + .asciz "instance_method_00" +l_OBJC_METH_VAR_NAME_.4: + .asciz "instance_method_01" +l_OBJC_METH_VAR_NAME_.5: + .asciz "instance_method_02" + + .section __DATA,__objc_const + .p2align 3, 0x0 +__OBJC_$_INSTANCE_METHODS_MyClass: + .long 24 + .long 3 + .quad l_OBJC_METH_VAR_NAME_.3 + .quad l_OBJC_METH_VAR_TYPE_ + .quad "-[MyClass instance_method_00]" + .quad l_OBJC_METH_VAR_NAME_.4 + .quad l_OBJC_METH_VAR_TYPE_ + .quad "-[MyClass instance_method_01]" + .quad l_OBJC_METH_VAR_NAME_.5 + .quad l_OBJC_METH_VAR_TYPE_ + .quad "-[MyClass instance_method_02]" + .p2align 3, 0x0 + +__OBJC_CLASS_RO_$_MyClass: + .long 2 + .long 0 + .long 0 + .space 4 + .quad 0 + .quad l_OBJC_CLASS_NAME_ + .quad __OBJC_$_INSTANCE_METHODS_MyClass + .quad 0 + .quad 0 + .quad 0 + .quad 0 + .globl __objc_empty_cache + +.zerofill __DATA,__common,__objc_empty_cache,8,3 + .section __DATA,__objc_classlist,regular,no_dead_strip + .p2align 3, 0x0 +l_OBJC_LABEL_CLASS_$: + .quad _OBJC_CLASS_$_MyClass + .section __DATA,__objc_imageinfo,regular,no_dead_strip +L_OBJC_IMAGE_INFO: + .long 0 + .long 64 +.subsections_via_symbols diff --git a/lld/test/MachO/silent-ignore.s b/lld/test/MachO/silent-ignore.s index e57342c28a7a6b8fb4262098cb1b019c4d3fa080..58c3cc148f07b0603cb471ff138b3b8015c6a756 100644 --- a/lld/test/MachO/silent-ignore.s +++ b/lld/test/MachO/silent-ignore.s @@ -20,7 +20,7 @@ ## Check that we don't emit any warnings nor errors for these unimplemented flags. # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o -# RUN: %lld %t.o -o /dev/null -objc_abi_version 2 -debug_variant +# RUN: %lld %t.o -o /dev/null -objc_abi_version 2 -debug_variant -no_warn_duplicate_libraries .globl _main _main: diff --git a/lld/test/MachO/thinlto-split-unit-start-lib.ll b/lld/test/MachO/thinlto-split-unit-start-lib.ll index 8c643b7c594e89b07e4d75677d2c3fa9a5bacf61..1c4a2f68a8b47f48d9baaef9868d6c051737d660 100644 --- a/lld/test/MachO/thinlto-split-unit-start-lib.ll +++ b/lld/test/MachO/thinlto-split-unit-start-lib.ll @@ -57,14 +57,14 @@ target triple = "x86_64-apple-macosx11.0.0" ; Function Attrs: mustprogress nofree norecurse nosync nounwind ssp willreturn memory(argmem: write) uwtable define void @_ZN1SC2Ev(ptr nocapture noundef nonnull writeonly align 8 dereferenceable(8) %this) unnamed_addr align 2 { entry: - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1S, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1S, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } ; Function Attrs: mustprogress nofree norecurse nosync nounwind ssp willreturn memory(argmem: write) uwtable define void @_ZN1SC1Ev(ptr nocapture noundef nonnull writeonly align 8 dereferenceable(8) %this) unnamed_addr align 2 { entry: - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1S, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1S, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } diff --git a/lld/test/MinGW/driver.test b/lld/test/MinGW/driver.test index a4e9e5e1b19b456b69e28b7d831528a868e75839..619fee8dee7c1f0b094b83fcc4db23238c5a59ed 100644 --- a/lld/test/MinGW/driver.test +++ b/lld/test/MinGW/driver.test @@ -422,6 +422,9 @@ LTO_EMIT_ASM: -lldemit:asm RUN: ld.lld -### foo.o -m i386pe -plugin-opt=emit-llvm 2>&1 | FileCheck -check-prefix=LTO_EMIT_LLVM %s LTO_EMIT_LLVM: -lldemit:llvm +RUN: ld.lld -### foo.o -m i386pep --lto-sample-profile=foo 2>&1 | FileCheck -check-prefix=LTO_SAMPLE_PROFILE %s +LTO_SAMPLE_PROFILE: -lto-sample-profile:foo + Test GCC specific LTO options that GCC passes unconditionally, that we ignore. RUN: ld.lld -### foo.o -m i386pep -plugin /usr/lib/gcc/x86_64-w64-mingw32/10-posix/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-w64-mingw32/10-posix/lto-wrapper -plugin-opt=-fresolution=/tmp/ccM9d4fP.res -plugin-opt=-pass-through=-lmingw32 2> /dev/null diff --git a/lldb/cmake/caches/Apple-lldb-Linux.cmake b/lldb/cmake/caches/Apple-lldb-Linux.cmake index 13d3839f852f6112e834e4730d4772e6f4714558..b2d3cf595fe18d833cfd15bd55a16c0dc9708d3d 100644 --- a/lldb/cmake/caches/Apple-lldb-Linux.cmake +++ b/lldb/cmake/caches/Apple-lldb-Linux.cmake @@ -5,4 +5,5 @@ set(LLVM_DISTRIBUTION_COMPONENTS liblldb lldb-argdumper lldb-server + lldb-python-scripts CACHE STRING "") diff --git a/lldb/docs/use/python-reference.rst b/lldb/docs/use/python-reference.rst index e5195a2471d9af95a0b5644cfd2621dd404fec93..795e38fab3794b0626c0add6628ef451fa8b477d 100644 --- a/lldb/docs/use/python-reference.rst +++ b/lldb/docs/use/python-reference.rst @@ -491,14 +491,17 @@ which will work like all the natively defined lldb commands. This provides a very flexible and easy way to extend LLDB to meet your debugging requirements. To write a python function that implements a new LLDB command define the -function to take four arguments as follows: +function to take five arguments as follows: :: - def command_function(debugger, command, result, internal_dict): + def command_function(debugger, command, exe_ctx, result, internal_dict): # Your code goes here -Optionally, you can also provide a Python docstring, and LLDB will use it when providing help for your command, as in: +The meaning of the arguments is given in the table below. + +If you provide a Python docstring in your command function LLDB will use it +when providing "long help" for your command, as in: :: @@ -506,19 +509,24 @@ Optionally, you can also provide a Python docstring, and LLDB will use it when p """This command takes a lot of options and does many fancy things""" # Your code goes here -Since lldb 3.5.2, LLDB Python commands can also take an SBExecutionContext as an -argument. This is useful in cases where the command's notion of where to act is -independent of the currently-selected entities in the debugger. +though providing help can also be done programmatically (see below). -This feature is enabled if the command-implementing function can be recognized -as taking 5 arguments, or a variable number of arguments, and it alters the -signature as such: +Prior to lldb 3.5.2 (April 2015), LLDB Python command definitions didn't take the SBExecutionContext +argument. So you may still see commands where the command definition is: :: - def command_function(debugger, command, exe_ctx, result, internal_dict): + def command_function(debugger, command, result, internal_dict): # Your code goes here +Using this form is strongly discouraged because it can only operate on the "currently selected" +target, process, thread, frame. The command will behave as expected when run +directly on the command line. But if the command is used in a stop-hook, breakpoint +callback, etc. where the response to the callback determines whether we will select +this or that particular process/frame/thread, the global "currently selected" +entity is not necessarily the one the callback is meant to handle. In that case, this +command definition form can't do the right thing. + +-------------------+--------------------------------+----------------------------------------------------------------------------------------------------------------------------------+ | Argument | Type | Description | +-------------------+--------------------------------+----------------------------------------------------------------------------------------------------------------------------------+ diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h index f7bdd3093d2025daa433472212a621c349d35704..3644ac056da3dca07fd563acfea64b7f45cb5d7b 100644 --- a/lldb/include/lldb/API/SBTarget.h +++ b/lldb/include/lldb/API/SBTarget.h @@ -42,7 +42,8 @@ public: eBroadcastBitModulesLoaded = (1 << 1), eBroadcastBitModulesUnloaded = (1 << 2), eBroadcastBitWatchpointChanged = (1 << 3), - eBroadcastBitSymbolsLoaded = (1 << 4) + eBroadcastBitSymbolsLoaded = (1 << 4), + eBroadcastBitSymbolsChanged = (1 << 5), }; // Constructors diff --git a/lldb/include/lldb/Core/Disassembler.h b/lldb/include/lldb/Core/Disassembler.h index 885ac1bb4a7ef888cb5cede46793d1a01814ae4d..e037a49f152c7434d7f48007e8561ee07f34c571 100644 --- a/lldb/include/lldb/Core/Disassembler.h +++ b/lldb/include/lldb/Core/Disassembler.h @@ -538,7 +538,7 @@ protected: ElideMixedSourceAndDisassemblyLine(const ExecutionContext &exe_ctx, const SymbolContext &sc, LineEntry &line) { SourceLine sl; - sl.file = line.file; + sl.file = line.GetFile(); sl.line = line.line; sl.column = line.column; return ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, sl); diff --git a/lldb/include/lldb/Core/Progress.h b/lldb/include/lldb/Core/Progress.h index c38f6dd0a140ed4a96e21d00ecb398b7723ae58f..cd87be79c4f0e321c5bd391534ea7ad696e9c16a 100644 --- a/lldb/include/lldb/Core/Progress.h +++ b/lldb/include/lldb/Core/Progress.h @@ -9,6 +9,7 @@ #ifndef LLDB_CORE_PROGRESS_H #define LLDB_CORE_PROGRESS_H +#include "lldb/Host/Alarm.h" #include "lldb/lldb-forward.h" #include "lldb/lldb-types.h" #include "llvm/ADT/StringMap.h" @@ -66,7 +67,11 @@ public: /// @param [in] title The title of this progress activity. /// /// @param [in] details Specific information about what the progress report - /// is currently working on. + /// is currently working on. Although not required, if the progress report is + /// updated with Progress::Increment() then this field will be overwritten + /// with the new set of details passed into that function, and the details + /// passed initially will act as an "item 0" for the total set of + /// items being reported on. /// /// @param [in] total The total units of work to be done if specified, if /// set to std::nullopt then an indeterminate progress indicator should be @@ -146,9 +151,12 @@ public: void Increment(const Progress::ProgressData &); void Decrement(const Progress::ProgressData &); + static void Initialize(); + static void Terminate(); + static bool Enabled(); static ProgressManager &Instance(); -private: +protected: enum class EventType { Begin, End, @@ -156,9 +164,32 @@ private: static void ReportProgress(const Progress::ProgressData &progress_data, EventType type); - llvm::StringMap<std::pair<uint64_t, Progress::ProgressData>> - m_progress_category_map; - std::mutex m_progress_map_mutex; + static std::optional<ProgressManager> &InstanceImpl(); + + /// Helper function for reporting progress when the alarm in the corresponding + /// entry in the map expires. + void Expire(llvm::StringRef key); + + /// Entry used for bookkeeping. + struct Entry { + /// Reference count used for overlapping events. + uint64_t refcount = 0; + + /// Data used to emit progress events. + Progress::ProgressData data; + + /// Alarm handle used when the refcount reaches zero. + Alarm::Handle handle = Alarm::INVALID_HANDLE; + }; + + /// Map used for bookkeeping. + llvm::StringMap<Entry> m_entries; + + /// Mutex to provide the map. + std::mutex m_entries_mutex; + + /// Alarm instance to coalesce progress events. + Alarm m_alarm; }; } // namespace lldb_private diff --git a/lldb/include/lldb/Host/Alarm.h b/lldb/include/lldb/Host/Alarm.h new file mode 100644 index 0000000000000000000000000000000000000000..23b1ff1af56890f2b745e0415f8a2ef48baa1070 --- /dev/null +++ b/lldb/include/lldb/Host/Alarm.h @@ -0,0 +1,115 @@ +//===-- Alarm.h -------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_HOST_ALARM_H +#define LLDB_HOST_ALARM_H + +#include "lldb/Host/HostThread.h" +#include "lldb/lldb-types.h" +#include "llvm/Support/Chrono.h" + +#include <condition_variable> +#include <mutex> + +namespace lldb_private { + +/// \class Alarm abstraction that enables scheduling a callback function after a +/// specified timeout. Creating an alarm for a callback returns a Handle that +/// can be used to restart or cancel the alarm. +class Alarm { +public: + using Handle = uint64_t; + using Callback = std::function<void()>; + using TimePoint = llvm::sys::TimePoint<>; + using Duration = std::chrono::milliseconds; + + Alarm(Duration timeout, bool run_callback_on_exit = false); + ~Alarm(); + + /// Create an alarm for the given callback. The alarm will expire and the + /// callback will be called after the timeout. + /// + /// \returns + /// Handle which can be used to restart or cancel the alarm. + Handle Create(Callback callback); + + /// Restart the alarm for the given Handle. The alarm will expire and the + /// callback will be called after the timeout. + /// + /// \returns + /// True if the alarm was successfully restarted. False if there is no alarm + /// for the given Handle or the alarm already expired. + bool Restart(Handle handle); + + /// Cancel the alarm for the given Handle. The alarm and its handle will be + /// removed. + /// + /// \returns + /// True if the alarm was successfully canceled and the Handle removed. + /// False if there is no alarm for the given Handle or the alarm already + /// expired. + bool Cancel(Handle handle); + + static constexpr Handle INVALID_HANDLE = 0; + +private: + /// Helper functions to start, stop and check the status of the alarm thread. + /// @{ + void StartAlarmThread(); + void StopAlarmThread(); + bool AlarmThreadRunning(); + /// @} + + /// Return an unique, monotonically increasing handle. + static Handle GetNextUniqueHandle(); + + /// Helper to compute the next time the alarm thread needs to wake up. + TimePoint GetNextExpiration() const; + + /// Alarm entry. + struct Entry { + Handle handle; + Callback callback; + TimePoint expiration; + + Entry(Callback callback, TimePoint expiration); + bool operator==(const Entry &rhs) { return handle == rhs.handle; } + }; + + /// List of alarm entries. + std::vector<Entry> m_entries; + + /// Timeout between when an alarm is created and when it fires. + Duration m_timeout; + + /// The alarm thread. + /// @{ + HostThread m_alarm_thread; + lldb::thread_result_t AlarmThread(); + /// @} + + /// Synchronize access between the alarm thread and the main thread. + std::mutex m_alarm_mutex; + + /// Condition variable used to wake up the alarm thread. + std::condition_variable m_alarm_cv; + + /// Flag to signal the alarm thread that something changed and we need to + /// recompute the next alarm. + bool m_recompute_next_alarm = false; + + /// Flag to signal the alarm thread to exit. + bool m_exit = false; + + /// Flag to signal we should run all callbacks on exit. + bool m_run_callbacks_on_exit = false; +}; + +} // namespace lldb_private + +#endif // LLDB_HOST_ALARM_H diff --git a/lldb/include/lldb/Symbol/LineEntry.h b/lldb/include/lldb/Symbol/LineEntry.h index c2daba916e3f9861c41b5e0fa95dc4f0582d8099..8da59cf0bd24aa090ce04e9116bc9397e08b4240 100644 --- a/lldb/include/lldb/Symbol/LineEntry.h +++ b/lldb/include/lldb/Symbol/LineEntry.h @@ -130,31 +130,43 @@ struct LineEntry { /// Shared pointer to the target this LineEntry belongs to. void ApplyFileMappings(lldb::TargetSP target_sp); - // Member variables. - AddressRange range; ///< The section offset address range for this line entry. - FileSpec file; ///< The source file, possibly mapped by the target.source-map - ///setting - lldb::SupportFileSP - original_file_sp; ///< The original source file, from debug info. - uint32_t line = LLDB_INVALID_LINE_NUMBER; ///< The source line number, or zero - ///< if there is no line number - /// information. - uint16_t column = - 0; ///< The column number of the source line, or zero if there - /// is no column information. - uint16_t is_start_of_statement : 1, ///< Indicates this entry is the beginning - ///of a statement. - is_start_of_basic_block : 1, ///< Indicates this entry is the beginning of - ///a basic block. - is_prologue_end : 1, ///< Indicates this entry is one (of possibly many) - ///where execution should be suspended for an entry - ///breakpoint of a function. - is_epilogue_begin : 1, ///< Indicates this entry is one (of possibly many) - ///where execution should be suspended for an exit - ///breakpoint of a function. - is_terminal_entry : 1; ///< Indicates this entry is that of the first byte - ///after the end of a sequence of target machine - ///instructions. + /// Helper to access the file. + const FileSpec &GetFile() const { return file_sp->GetSpecOnly(); } + + /// The section offset address range for this line entry. + AddressRange range; + + /// The source file, possibly mapped by the target.source-map setting. + lldb::SupportFileSP file_sp; + + /// The original source file, from debug info. + lldb::SupportFileSP original_file_sp; + + /// The source line number, or LLDB_INVALID_LINE_NUMBER if there is no line + /// number information. + uint32_t line = LLDB_INVALID_LINE_NUMBER; + + /// The column number of the source line, or zero if there is no column + /// information. + uint16_t column = 0; + + /// Indicates this entry is the beginning of a statement. + uint16_t is_start_of_statement : 1; + + /// Indicates this entry is the beginning of a basic block. + uint16_t is_start_of_basic_block : 1; + + /// Indicates this entry is one (of possibly many) where execution should be + /// suspended for an entry breakpoint of a function. + uint16_t is_prologue_end : 1; + + /// Indicates this entry is one (of possibly many) where execution should be + /// suspended for an exit breakpoint of a function. + uint16_t is_epilogue_begin : 1; + + /// Indicates this entry is that of the first byte after the end of a sequence + /// of target machine instructions. + uint16_t is_terminal_entry : 1; }; /// Less than operator. diff --git a/lldb/include/lldb/Symbol/UnwindTable.h b/lldb/include/lldb/Symbol/UnwindTable.h index f0ce7047de2d1ed21986b30a5db7f087ec88326d..26826e5d1b497ca21afd7afeba2f9943ae1c1e21 100644 --- a/lldb/include/lldb/Symbol/UnwindTable.h +++ b/lldb/include/lldb/Symbol/UnwindTable.h @@ -57,6 +57,10 @@ public: ArchSpec GetArchitecture(); + /// Called after a SymbolFile has been added to a Module to add any new + /// unwind sections that may now be available. + void Update(); + private: void Dump(Stream &s); diff --git a/lldb/include/lldb/Target/Language.h b/lldb/include/lldb/Target/Language.h index 0cbd8a32dccd54e612ad4c0cb540985717fa285f..67714e6fdf942e9c7b06dcb33eaa0903c8adeeff 100644 --- a/lldb/include/lldb/Target/Language.h +++ b/lldb/include/lldb/Target/Language.h @@ -26,6 +26,15 @@ namespace lldb_private { +class LanguageProperties : public Properties { +public: + LanguageProperties(); + + static llvm::StringRef GetSettingName(); + + bool GetEnableFilterForLineBreakpoints() const; +}; + class Language : public PluginInterface { public: class TypeScavenger { @@ -324,6 +333,8 @@ public: static LanguageSet GetLanguagesSupportingTypeSystemsForExpressions(); static LanguageSet GetLanguagesSupportingREPLs(); + static LanguageProperties &GetGlobalLanguageProperties(); + // Given a mangled function name, calculates some alternative manglings since // the compiler mangling may not line up with the symbol we are expecting. virtual std::vector<ConstString> @@ -339,6 +350,15 @@ public: virtual llvm::StringRef GetInstanceVariableName() { return {}; } + /// Returns true if this SymbolContext should be ignored when setting + /// breakpoints by line (number or regex). Helpful for languages that create + /// artificial functions without meaningful user code associated with them + /// (e.g. code that gets expanded in late compilation stages, like by + /// CoroSplitter). + virtual bool IgnoreForLineBreakpoints(const SymbolContext &) const { + return false; + } + protected: // Classes that inherit from Language can see and modify these diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index e260e1b4b797bcb7359105e2b84fa32bb38cd119..2f3a3c22422efeca205c9a9ea33c7af5fb0fb15b 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -43,6 +43,7 @@ #include "lldb/Target/ThreadList.h" #include "lldb/Target/ThreadPlanStack.h" #include "lldb/Target/Trace.h" +#include "lldb/Utility/AddressableBits.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/Event.h" @@ -3219,6 +3220,8 @@ protected: void LoadOperatingSystemPlugin(bool flush); + void SetAddressableBitMasks(AddressableBits bit_masks); + private: Status DestroyImpl(bool force_kill); diff --git a/lldb/include/lldb/Utility/AddressableBits.h b/lldb/include/lldb/Utility/AddressableBits.h index 75752fcf840a446ffb31306c155c3b794856ffdf..0d27c3561ec2728d525c2aa530e207a64099a7eb 100644 --- a/lldb/include/lldb/Utility/AddressableBits.h +++ b/lldb/include/lldb/Utility/AddressableBits.h @@ -32,11 +32,13 @@ public: void SetLowmemAddressableBits(uint32_t lowmem_addressing_bits); + uint32_t GetLowmemAddressableBits() const; + void SetHighmemAddressableBits(uint32_t highmem_addressing_bits); - static lldb::addr_t AddressableBitToMask(uint32_t addressable_bits); + uint32_t GetHighmemAddressableBits() const; - void SetProcessMasks(lldb_private::Process &process); + static lldb::addr_t AddressableBitToMask(uint32_t addressable_bits); private: uint32_t m_low_memory_addr_bits; diff --git a/lldb/include/lldb/Utility/Scalar.h b/lldb/include/lldb/Utility/Scalar.h index 8e087a5ddeb85524a352855a6ca1291e973539e6..d7155884c6d1b81318411f46ea70e3cb828833f7 100644 --- a/lldb/include/lldb/Utility/Scalar.h +++ b/lldb/include/lldb/Utility/Scalar.h @@ -71,6 +71,7 @@ public: : m_type(e_int), m_integer(std::move(v), false), m_float(0.0f) {} Scalar(llvm::APSInt v) : m_type(e_int), m_integer(std::move(v)), m_float(0.0f) {} + Scalar(llvm::APFloat v) : m_type(e_float), m_integer(0), m_float(v) {} bool SignExtend(uint32_t bit_pos); @@ -186,6 +187,10 @@ public: Status SetValueFromData(const DataExtractor &data, lldb::Encoding encoding, size_t byte_size); + llvm::APFloat CreateAPFloatFromAPSInt(lldb::BasicType basic_type); + + llvm::APFloat CreateAPFloatFromAPFloat(lldb::BasicType basic_type); + protected: Scalar::Type m_type = e_void; llvm::APSInt m_integer; diff --git a/lldb/include/lldb/Utility/SupportFile.h b/lldb/include/lldb/Utility/SupportFile.h index 0ea0ca4e7c97a17e5126f260d312a84004e46a8f..7505d7f345c5dddcb25c8aefc46a4bf1c7c5c75d 100644 --- a/lldb/include/lldb/Utility/SupportFile.h +++ b/lldb/include/lldb/Utility/SupportFile.h @@ -45,6 +45,9 @@ public: /// Materialize the file to disk and return the path to that temporary file. virtual const FileSpec &Materialize() { return m_file_spec; } + /// Change the file name. + void Update(const FileSpec &file_spec) { m_file_spec = file_spec; } + protected: FileSpec m_file_spec; Checksum m_checksum; diff --git a/lldb/packages/Python/lldbsuite/test/decorators.py b/lldb/packages/Python/lldbsuite/test/decorators.py index b691f82b90652c9b168e38db23174a7b157bf4ab..8e13aa6a13882fc56cbc3a8f2f92affc7997c287 100644 --- a/lldb/packages/Python/lldbsuite/test/decorators.py +++ b/lldb/packages/Python/lldbsuite/test/decorators.py @@ -409,10 +409,6 @@ def add_test_categories(cat): cat = test_categories.validate(cat, True) def impl(func): - if isinstance(func, type) and issubclass(func, unittest.TestCase): - raise Exception( - "@add_test_categories can only be used to decorate a test method" - ) try: if hasattr(func, "categories"): cat.extend(func.categories) diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py index 291d7bad5c089702e8d8cdecfb709031e0f5a4fa..8c29145ecc527220f518db3b5bb0456a914e7306 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest.py +++ b/lldb/packages/Python/lldbsuite/test/dotest.py @@ -914,6 +914,18 @@ def checkForkVForkSupport(): configuration.skip_categories.append("fork") +def checkPexpectSupport(): + from lldbsuite.test import lldbplatformutil + + platform = lldbplatformutil.getPlatform() + + # llvm.org/pr22274: need a pexpect replacement for windows + if platform in ["windows"]: + if configuration.verbose: + print("pexpect tests will be skipped because of unsupported platform") + configuration.skip_categories.append("pexpect") + + def run_suite(): # On MacOS X, check to make sure that domain for com.apple.DebugSymbols defaults # does not exist before proceeding to running the test suite. @@ -1013,6 +1025,7 @@ def run_suite(): checkDebugServerSupport() checkObjcSupport() checkForkVForkSupport() + checkPexpectSupport() skipped_categories_list = ", ".join(configuration.skip_categories) print( diff --git a/lldb/packages/Python/lldbsuite/test/lldbpexpect.py b/lldb/packages/Python/lldbsuite/test/lldbpexpect.py index 9d216d903074737cb94bebec7b5cb0c987f9d1a5..998a080565b6b3f4f56d3223d3a6f67fd28fcef6 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbpexpect.py +++ b/lldb/packages/Python/lldbsuite/test/lldbpexpect.py @@ -10,7 +10,7 @@ from lldbsuite.test.decorators import * @skipIfRemote -@skipIfWindows # llvm.org/pr22274: need a pexpect replacement for windows +@add_test_categories(["pexpect"]) class PExpectTest(TestBase): NO_DEBUG_INFO_TESTCASE = True PROMPT = "(lldb) " diff --git a/lldb/packages/Python/lldbsuite/test/test_categories.py b/lldb/packages/Python/lldbsuite/test/test_categories.py index 3f8de175e29df3fe8282aa0e599c6ad23d5a17bb..036bda9c957d11df48ed84858b739f9adfd1e5e8 100644 --- a/lldb/packages/Python/lldbsuite/test/test_categories.py +++ b/lldb/packages/Python/lldbsuite/test/test_categories.py @@ -33,6 +33,7 @@ all_categories = { "lldb-server": "Tests related to lldb-server", "lldb-dap": "Tests for the Debug Adaptor Protocol with lldb-dap", "llgs": "Tests for the gdb-server functionality of lldb-server", + "pexpect": "Tests requiring the pexpect library to be available", "objc": "Tests related to the Objective-C programming language support", "pyapi": "Tests related to the Python API", "std-module": "Tests related to importing the std module", diff --git a/lldb/packages/Python/lldbsuite/test/test_result.py b/lldb/packages/Python/lldbsuite/test/test_result.py index 20365f53a67541f329f72db7735ddda89e6e9553..2d574b343b4134f0ca4386b8cf4f49fb7e5e98fb 100644 --- a/lldb/packages/Python/lldbsuite/test/test_result.py +++ b/lldb/packages/Python/lldbsuite/test/test_result.py @@ -148,9 +148,11 @@ class LLDBTestResult(unittest.TextTestResult): Gets all the categories for the currently running test method in test case """ test_categories = [] + test_categories.extend(getattr(test, "categories", [])) + test_method = getattr(test, test._testMethodName) - if test_method is not None and hasattr(test_method, "categories"): - test_categories.extend(test_method.categories) + if test_method is not None: + test_categories.extend(getattr(test_method, "categories", [])) test_categories.extend(self._getFileBasedCategories(test)) diff --git a/lldb/source/API/SBLineEntry.cpp b/lldb/source/API/SBLineEntry.cpp index 28d12e65fdaf8a7b6aae0531083b6f26c753e0f0..99a7b8fe644cb52e372a8f02915a112824eed1ee 100644 --- a/lldb/source/API/SBLineEntry.cpp +++ b/lldb/source/API/SBLineEntry.cpp @@ -81,8 +81,8 @@ SBFileSpec SBLineEntry::GetFileSpec() const { LLDB_INSTRUMENT_VA(this); SBFileSpec sb_file_spec; - if (m_opaque_up.get() && m_opaque_up->file) - sb_file_spec.SetFileSpec(m_opaque_up->file); + if (m_opaque_up.get() && m_opaque_up->GetFile()) + sb_file_spec.SetFileSpec(m_opaque_up->GetFile()); return sb_file_spec; } @@ -109,9 +109,9 @@ void SBLineEntry::SetFileSpec(lldb::SBFileSpec filespec) { LLDB_INSTRUMENT_VA(this, filespec); if (filespec.IsValid()) - ref().file = filespec.ref(); + ref().file_sp = std::make_shared<SupportFile>(filespec.ref()); else - ref().file.Clear(); + ref().file_sp = std::make_shared<SupportFile>(); } void SBLineEntry::SetLine(uint32_t line) { LLDB_INSTRUMENT_VA(this, line); @@ -168,7 +168,7 @@ bool SBLineEntry::GetDescription(SBStream &description) { if (m_opaque_up) { char file_path[PATH_MAX * 2]; - m_opaque_up->file.GetPath(file_path, sizeof(file_path)); + m_opaque_up->GetFile().GetPath(file_path, sizeof(file_path)); strm.Printf("%s:%u", file_path, GetLine()); if (GetColumn() > 0) strm.Printf(":%u", GetColumn()); diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp index fa4c80e59d973fa6252cfddbcef6fb3ecec53ad3..eb9cf063802cd47b7ec773faa5897ee06f76e195 100644 --- a/lldb/source/API/SBThread.cpp +++ b/lldb/source/API/SBThread.cpp @@ -819,7 +819,7 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame, step_file_spec = sb_file_spec.ref(); } else { if (frame_sc.line_entry.IsValid()) - step_file_spec = frame_sc.line_entry.file; + step_file_spec = frame_sc.line_entry.GetFile(); else { sb_error.SetErrorString("invalid file argument or no file for frame"); return sb_error; diff --git a/lldb/source/API/SystemInitializerFull.cpp b/lldb/source/API/SystemInitializerFull.cpp index c48466f25ede81b73aff786872667e300868c4b0..995d14f7c1fa1e7f0d0ca3701311d4d657af7e06 100644 --- a/lldb/source/API/SystemInitializerFull.cpp +++ b/lldb/source/API/SystemInitializerFull.cpp @@ -10,6 +10,7 @@ #include "lldb/API/SBCommandInterpreter.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Core/Progress.h" #include "lldb/Host/Config.h" #include "lldb/Host/Host.h" #include "lldb/Initialization/SystemInitializerCommon.h" @@ -57,6 +58,7 @@ llvm::Error SystemInitializerFull::Initialize() { llvm::InitializeAllAsmPrinters(); llvm::InitializeAllTargetMCs(); llvm::InitializeAllDisassemblers(); + // Initialize the command line parser in LLVM. This usually isn't necessary // as we aren't dealing with command line options here, but otherwise some // other code in Clang/LLVM might be tempted to call this function from a @@ -65,10 +67,13 @@ llvm::Error SystemInitializerFull::Initialize() { const char *arg0 = "lldb"; llvm::cl::ParseCommandLineOptions(1, &arg0); + // Initialize the progress manager. + ProgressManager::Initialize(); + #define LLDB_PLUGIN(p) LLDB_PLUGIN_INITIALIZE(p); #include "Plugins/Plugins.def" - // Scan for any system or user LLDB plug-ins + // Scan for any system or user LLDB plug-ins. PluginManager::Initialize(); // The process settings need to know about installed plug-ins, so the @@ -84,15 +89,18 @@ llvm::Error SystemInitializerFull::Initialize() { void SystemInitializerFull::Terminate() { Debugger::SettingsTerminate(); - // Terminate plug-ins in core LLDB + // Terminate plug-ins in core LLDB. ProcessTrace::Terminate(); - // Terminate and unload and loaded system or user LLDB plug-ins + // Terminate and unload and loaded system or user LLDB plug-ins. PluginManager::Terminate(); #define LLDB_PLUGIN(p) LLDB_PLUGIN_TERMINATE(p); #include "Plugins/Plugins.def" + // Terminate the progress manager. + ProgressManager::Terminate(); + // Now shutdown the common parts, in reverse order. SystemInitializerCommon::Terminate(); } diff --git a/lldb/source/Breakpoint/BreakpointIDList.cpp b/lldb/source/Breakpoint/BreakpointIDList.cpp index 851d074e7535880c10fe95961605ab97d1843ada..97af1d40eb7a5824b0dad6c9d4a8ebb610237ce8 100644 --- a/lldb/source/Breakpoint/BreakpointIDList.cpp +++ b/lldb/source/Breakpoint/BreakpointIDList.cpp @@ -16,6 +16,7 @@ #include "lldb/Utility/StreamString.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" using namespace lldb; using namespace lldb_private; @@ -111,32 +112,27 @@ llvm::Error BreakpointIDList::FindAndReplaceIDRanges( } else { // See if user has specified id.* llvm::StringRef tmp_str = old_args[i].ref(); - size_t pos = tmp_str.find('.'); - if (pos != llvm::StringRef::npos) { - llvm::StringRef bp_id_str = tmp_str.substr(0, pos); - if (BreakpointID::IsValidIDExpression(bp_id_str) && - tmp_str[pos + 1] == '*' && tmp_str.size() == (pos + 2)) { - - BreakpointSP breakpoint_sp; - auto bp_id = BreakpointID::ParseCanonicalReference(bp_id_str); - if (bp_id) - breakpoint_sp = target->GetBreakpointByID(bp_id->GetBreakpointID()); - if (!breakpoint_sp) { - new_args.Clear(); - return llvm::createStringError( - llvm::inconvertibleErrorCode(), - "'%d' is not a valid breakpoint ID.\n", - bp_id->GetBreakpointID()); - } - const size_t num_locations = breakpoint_sp->GetNumLocations(); - for (size_t j = 0; j < num_locations; ++j) { - BreakpointLocation *bp_loc = - breakpoint_sp->GetLocationAtIndex(j).get(); - StreamString canonical_id_str; - BreakpointID::GetCanonicalReference( - &canonical_id_str, bp_id->GetBreakpointID(), bp_loc->GetID()); - new_args.AppendArgument(canonical_id_str.GetString()); - } + auto [prefix, suffix] = tmp_str.split('.'); + if (suffix == "*" && BreakpointID::IsValidIDExpression(prefix)) { + + BreakpointSP breakpoint_sp; + auto bp_id = BreakpointID::ParseCanonicalReference(prefix); + if (bp_id) + breakpoint_sp = target->GetBreakpointByID(bp_id->GetBreakpointID()); + if (!breakpoint_sp) { + new_args.Clear(); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "'%d' is not a valid breakpoint ID.\n", + bp_id->GetBreakpointID()); + } + const size_t num_locations = breakpoint_sp->GetNumLocations(); + for (size_t j = 0; j < num_locations; ++j) { + BreakpointLocation *bp_loc = + breakpoint_sp->GetLocationAtIndex(j).get(); + StreamString canonical_id_str; + BreakpointID::GetCanonicalReference( + &canonical_id_str, bp_id->GetBreakpointID(), bp_loc->GetID()); + new_args.AppendArgument(canonical_id_str.GetString()); } } } diff --git a/lldb/source/Breakpoint/BreakpointResolver.cpp b/lldb/source/Breakpoint/BreakpointResolver.cpp index bc6348716ef418b210e7b812765cc8f59a0ccea4..ff4e2a9985197b148d392ec3fa1b499d82348e87 100644 --- a/lldb/source/Breakpoint/BreakpointResolver.cpp +++ b/lldb/source/Breakpoint/BreakpointResolver.cpp @@ -23,6 +23,7 @@ #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/Language.h" #include "lldb/Target/Target.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" @@ -203,8 +204,15 @@ void BreakpointResolver::SetSCMatchesByLine( SearchFilter &filter, SymbolContextList &sc_list, bool skip_prologue, llvm::StringRef log_ident, uint32_t line, std::optional<uint16_t> column) { llvm::SmallVector<SymbolContext, 16> all_scs; - for (uint32_t i = 0; i < sc_list.GetSize(); ++i) - all_scs.push_back(sc_list[i]); + + for (const auto &sc : sc_list) { + if (Language::GetGlobalLanguageProperties() + .GetEnableFilterForLineBreakpoints()) + if (Language *lang = Language::FindPlugin(sc.GetLanguage()); + lang && lang->IgnoreForLineBreakpoints(sc)) + continue; + all_scs.push_back(sc); + } while (all_scs.size()) { uint32_t closest_line = UINT32_MAX; @@ -213,7 +221,7 @@ void BreakpointResolver::SetSCMatchesByLine( auto &match = all_scs[0]; auto worklist_begin = std::partition( all_scs.begin(), all_scs.end(), [&](const SymbolContext &sc) { - if (sc.line_entry.file == match.line_entry.file || + if (sc.line_entry.GetFile() == match.line_entry.GetFile() || *sc.line_entry.original_file_sp == *match.line_entry.original_file_sp) { // When a match is found, keep track of the smallest line number. diff --git a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp index cc4e1d26724f0451942ea40982e8b9c16eb53ba2..d7d8c714867e3e24cf9ec4965cdb281166e557ea 100644 --- a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp @@ -147,8 +147,9 @@ void BreakpointResolverFileLine::FilterContexts(SymbolContextList &sc_list) { else continue; - if (file != sc.line_entry.file) { - LLDB_LOG(log, "unexpected symbol context file {0}", sc.line_entry.file); + if (file != sc.line_entry.GetFile()) { + LLDB_LOG(log, "unexpected symbol context file {0}", + sc.line_entry.GetFile()); continue; } @@ -223,7 +224,7 @@ void BreakpointResolverFileLine::DeduceSourceMapping( const bool case_sensitive = request_file.IsCaseSensitive(); for (const SymbolContext &sc : sc_list) { - FileSpec sc_file = sc.line_entry.file; + FileSpec sc_file = sc.line_entry.GetFile(); if (FileSpec::Equal(sc_file, request_file, /*full*/ true)) continue; diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp index fbece865f113148e3685ef3267242f2802b3cb70..cd4c7790f447e18d1f13021df2ff4bf05cf535c1 100644 --- a/lldb/source/Commands/CommandObjectBreakpoint.cpp +++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp @@ -780,8 +780,8 @@ private: } else { const SymbolContext &sc = cur_frame->GetSymbolContext(eSymbolContextLineEntry); - if (sc.line_entry.file) { - file = sc.line_entry.file; + if (sc.line_entry.GetFile()) { + file = sc.line_entry.GetFile(); } else { result.AppendError("Can't find the file for the selected frame to " "use as the default file."); diff --git a/lldb/source/Commands/CommandObjectDWIMPrint.cpp b/lldb/source/Commands/CommandObjectDWIMPrint.cpp index b183cb423111fb66141f15f33f9126bc27502c59..e1255f37d9bc584ff3b34729c14ee144142f9ab6 100644 --- a/lldb/source/Commands/CommandObjectDWIMPrint.cpp +++ b/lldb/source/Commands/CommandObjectDWIMPrint.cpp @@ -23,7 +23,6 @@ #include "lldb/lldb-enumerations.h" #include "lldb/lldb-forward.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/FormatVariadic.h" #include <regex> @@ -130,6 +129,19 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command, } }; + // Dump `valobj` according to whether `po` was requested or not. + auto dump_val_object = [&](ValueObject &valobj) { + if (is_po) { + StreamString temp_result_stream; + valobj.Dump(temp_result_stream, dump_options); + llvm::StringRef output = temp_result_stream.GetString(); + maybe_add_hint(output); + result.GetOutputStream() << output; + } else { + valobj.Dump(result.GetOutputStream(), dump_options); + } + }; + // First, try `expr` as the name of a frame variable. if (frame) { auto valobj_sp = frame->FindVariable(ConstString(expr)); @@ -147,21 +159,23 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command, flags, expr); } - if (is_po) { - StreamString temp_result_stream; - valobj_sp->Dump(temp_result_stream, dump_options); - llvm::StringRef output = temp_result_stream.GetString(); - maybe_add_hint(output); - result.GetOutputStream() << output; - } else { - valobj_sp->Dump(result.GetOutputStream(), dump_options); - } + dump_val_object(*valobj_sp); result.SetStatus(eReturnStatusSuccessFinishResult); return; } } - // Second, also lastly, try `expr` as a source expression to evaluate. + // Second, try `expr` as a persistent variable. + if (expr.starts_with("$")) + if (auto *state = target.GetPersistentExpressionStateForLanguage(language)) + if (auto var_sp = state->GetVariable(expr)) + if (auto valobj_sp = var_sp->GetValueObject()) { + dump_val_object(*valobj_sp); + result.SetStatus(eReturnStatusSuccessFinishResult); + return; + } + + // Third, and lastly, try `expr` as a source expression to evaluate. { auto *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); ValueObjectSP valobj_sp; @@ -187,17 +201,8 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command, expr); } - if (valobj_sp->GetError().GetError() != UserExpression::kNoResult) { - if (is_po) { - StreamString temp_result_stream; - valobj_sp->Dump(temp_result_stream, dump_options); - llvm::StringRef output = temp_result_stream.GetString(); - maybe_add_hint(output); - result.GetOutputStream() << output; - } else { - valobj_sp->Dump(result.GetOutputStream(), dump_options); - } - } + if (valobj_sp->GetError().GetError() != UserExpression::kNoResult) + dump_val_object(*valobj_sp); if (suppress_result) if (auto result_var_sp = diff --git a/lldb/source/Commands/CommandObjectSource.cpp b/lldb/source/Commands/CommandObjectSource.cpp index fde74f02aea644bd5b96e3daf25a8558bf2ff54a..0c1267456a1845917d49088fc339109dfb78beac 100644 --- a/lldb/source/Commands/CommandObjectSource.cpp +++ b/lldb/source/Commands/CommandObjectSource.cpp @@ -158,7 +158,7 @@ protected: if (module_list.GetSize() && module_list.GetIndexForModule(module) == LLDB_INVALID_INDEX32) continue; - if (!FileSpec::Match(file_spec, line_entry.file)) + if (!FileSpec::Match(file_spec, line_entry.GetFile())) continue; if (start_line > 0 && line_entry.line < start_line) continue; @@ -239,7 +239,7 @@ protected: num_matches++; if (num_lines > 0 && num_matches > num_lines) break; - assert(cu_file_spec == line_entry.file); + assert(cu_file_spec == line_entry.GetFile()); if (!cu_header_printed) { if (num_matches > 0) strm << "\n\n"; @@ -760,11 +760,11 @@ protected: bool operator<(const SourceInfo &rhs) const { if (function.GetCString() < rhs.function.GetCString()) return true; - if (line_entry.file.GetDirectory().GetCString() < - rhs.line_entry.file.GetDirectory().GetCString()) + if (line_entry.GetFile().GetDirectory().GetCString() < + rhs.line_entry.GetFile().GetDirectory().GetCString()) return true; - if (line_entry.file.GetFilename().GetCString() < - rhs.line_entry.file.GetFilename().GetCString()) + if (line_entry.GetFile().GetFilename().GetCString() < + rhs.line_entry.GetFile().GetFilename().GetCString()) return true; if (line_entry.line < rhs.line_entry.line) return true; @@ -799,7 +799,7 @@ protected: sc.function->GetEndLineSourceInfo(end_file, end_line); } else { // We have an inlined function - start_file = source_info.line_entry.file; + start_file = source_info.line_entry.GetFile(); start_line = source_info.line_entry.line; end_line = start_line + m_options.num_lines; } diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index b2346c2402a81d44147fe83ed46f06438e06146b..ae6c6d5479a19862fd258fac1d58030bc1b86ea7 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -3377,7 +3377,7 @@ protected: case 'r': { size_t ref_count = 0; char in_shared_cache = 'Y'; - + ModuleSP module_sp(module->shared_from_this()); if (!ModuleList::ModuleIsInCache(module)) in_shared_cache = 'N'; @@ -4508,11 +4508,8 @@ protected: ModuleSpec module_spec; module_spec.GetUUID() = frame_module_sp->GetUUID(); - - if (FileSystem::Instance().Exists(frame_module_sp->GetPlatformFileSpec())) { - module_spec.GetArchitecture() = frame_module_sp->GetArchitecture(); - module_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec(); - } + module_spec.GetArchitecture() = frame_module_sp->GetArchitecture(); + module_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec(); if (!DownloadObjectAndSymbolFile(module_spec, result, flush)) { result.AppendError("unable to find debug symbols for the current frame"); @@ -4557,12 +4554,8 @@ protected: ModuleSpec module_spec; module_spec.GetUUID() = frame_module_sp->GetUUID(); - - if (FileSystem::Instance().Exists( - frame_module_sp->GetPlatformFileSpec())) { - module_spec.GetArchitecture() = frame_module_sp->GetArchitecture(); - module_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec(); - } + module_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec(); + module_spec.GetArchitecture() = frame_module_sp->GetArchitecture(); bool current_frame_flush = false; if (DownloadObjectAndSymbolFile(module_spec, result, current_frame_flush)) diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index cf4f8ccaa0c4aa17b9ba9b38d32095b3537153b1..3dbbfd4f9d344d72e87de5bb596bdab069e2b0a0 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -1705,7 +1705,7 @@ protected: line = sym_ctx.line_entry.line + m_options.m_line_offset; // Try the current file, but override if asked. - FileSpec file = sym_ctx.line_entry.file; + FileSpec file = sym_ctx.line_entry.GetFile(); if (m_options.m_filenames.GetSize() == 1) file = m_options.m_filenames.GetFileSpecAtIndex(0); diff --git a/lldb/source/Core/Address.cpp b/lldb/source/Core/Address.cpp index 6f5c366ab38a306564e21b04cc9fad529b7375f2..b23398883fa5535bb2ef726fe96123745c8cbbbc 100644 --- a/lldb/source/Core/Address.cpp +++ b/lldb/source/Core/Address.cpp @@ -398,7 +398,7 @@ bool Address::GetDescription(Stream &s, Target &target, "Non-brief descriptions not implemented"); LineEntry line_entry; if (CalculateSymbolContextLineEntry(line_entry)) { - s.Printf(" (%s:%u:%u)", line_entry.file.GetFilename().GetCString(), + s.Printf(" (%s:%u:%u)", line_entry.GetFile().GetFilename().GetCString(), line_entry.line, line_entry.column); return true; } diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 90aabde2b764f1682e5dfe991abc3171da00551f..ebd112110e5f2d2c4994323296b5c553a2373d26 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -860,6 +860,9 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) m_collection_sp->AppendProperty( "symbols", "Symbol lookup and cache settings.", true, ModuleList::GetGlobalModuleListProperties().GetValueProperties()); + m_collection_sp->AppendProperty( + LanguageProperties::GetSettingName(), "Language settings.", true, + Language::GetGlobalLanguageProperties().GetValueProperties()); if (m_command_interpreter_up) { m_collection_sp->AppendProperty( "interpreter", diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp index 7b07fcb26813076d7af1600ab288b9db9accb5c9..e31746fa0b8b9d8135555cdb78549aea4bb77f87 100644 --- a/lldb/source/Core/Disassembler.cpp +++ b/lldb/source/Core/Disassembler.cpp @@ -201,7 +201,7 @@ Disassembler::GetFunctionDeclLineEntry(const SymbolContext &sc) { uint32_t func_decl_line; sc.function->GetStartLineSourceInfo(func_decl_file, func_decl_line); - if (func_decl_file != prologue_end_line.file && + if (func_decl_file != prologue_end_line.GetFile() && func_decl_file != prologue_end_line.original_file_sp->GetSpecOnly()) return {}; @@ -354,7 +354,7 @@ void Disassembler::PrintInstructions(Debugger &debugger, const ArchSpec &arch, } if (sc.line_entry.IsValid()) { SourceLine this_line; - this_line.file = sc.line_entry.file; + this_line.file = sc.line_entry.GetFile(); this_line.line = sc.line_entry.line; this_line.column = sc.line_entry.column; if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, this_line)) @@ -406,7 +406,7 @@ void Disassembler::PrintInstructions(Debugger &debugger, const ArchSpec &arch, uint32_t func_decl_line; sc.function->GetStartLineSourceInfo(func_decl_file, func_decl_line); - if (func_decl_file == prologue_end_line.file || + if (func_decl_file == prologue_end_line.GetFile() || func_decl_file == prologue_end_line.original_file_sp->GetSpecOnly()) { // Add all the lines between the function declaration and @@ -439,7 +439,7 @@ void Disassembler::PrintInstructions(Debugger &debugger, const ArchSpec &arch, if (sc != prev_sc && sc.comp_unit && sc.line_entry.IsValid()) { SourceLine this_line; - this_line.file = sc.line_entry.file; + this_line.file = sc.line_entry.GetFile(); this_line.line = sc.line_entry.line; if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, diff --git a/lldb/source/Core/FormatEntity.cpp b/lldb/source/Core/FormatEntity.cpp index cf82676beddabeb5603658de0c23237c1b8c591c..ba62e26252591fc636e3576050b5b11c60c9eace 100644 --- a/lldb/source/Core/FormatEntity.cpp +++ b/lldb/source/Core/FormatEntity.cpp @@ -1792,7 +1792,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s, if (sc && sc->line_entry.IsValid()) { Module *module = sc->module_sp.get(); if (module) { - if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number)) + if (DumpFile(s, sc->line_entry.GetFile(), (FileKind)entry.number)) return true; } } diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp index f86dce247135f8cd933d9035a3e9ba91b7d7e91b..d922d32f9105835535e4f46896c10d26ce9e6483 100644 --- a/lldb/source/Core/IOHandlerCursesGUI.cpp +++ b/lldb/source/Core/IOHandlerCursesGUI.cpp @@ -6894,7 +6894,8 @@ public: if (context_changed) m_selected_line = m_pc_line; - if (m_file_sp && m_file_sp->GetFileSpec() == m_sc.line_entry.file) { + if (m_file_sp && + m_file_sp->GetFileSpec() == m_sc.line_entry.GetFile()) { // Same file, nothing to do, we should either have the lines or // not (source file missing) if (m_selected_line >= static_cast<size_t>(m_first_visible_line)) { @@ -6909,8 +6910,8 @@ public: } else { // File changed, set selected line to the line with the PC m_selected_line = m_pc_line; - m_file_sp = - m_debugger.GetSourceManager().GetFile(m_sc.line_entry.file); + m_file_sp = m_debugger.GetSourceManager().GetFile( + m_sc.line_entry.GetFile()); if (m_file_sp) { const size_t num_lines = m_file_sp->GetNumLines(); m_line_width = 1; @@ -7000,7 +7001,7 @@ public: LineEntry bp_loc_line_entry; if (bp_loc_sp->GetAddress().CalculateSymbolContextLineEntry( bp_loc_line_entry)) { - if (m_file_sp->GetFileSpec() == bp_loc_line_entry.file) { + if (m_file_sp->GetFileSpec() == bp_loc_line_entry.GetFile()) { bp_lines.insert(bp_loc_line_entry.line); } } @@ -7477,7 +7478,7 @@ public: LineEntry bp_loc_line_entry; if (bp_loc_sp->GetAddress().CalculateSymbolContextLineEntry( bp_loc_line_entry)) { - if (m_file_sp->GetFileSpec() == bp_loc_line_entry.file && + if (m_file_sp->GetFileSpec() == bp_loc_line_entry.GetFile() && m_selected_line + 1 == bp_loc_line_entry.line) { bool removed = exe_ctx.GetTargetRef().RemoveBreakpointByID(bp_sp->GetID()); diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index 8ffa35518b3c362f567f571406acc2add623290e..9c105b3f0e57a15328f19783359551793396dd08 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -1009,6 +1009,8 @@ SymbolFile *Module::GetSymbolFile(bool can_create, Stream *feedback_strm) { m_symfile_up.reset( SymbolVendor::FindPlugin(shared_from_this(), feedback_strm)); m_did_load_symfile = true; + if (m_unwind_table) + m_unwind_table->Update(); } } } @@ -1239,9 +1241,9 @@ void Module::SectionFileAddressesChanged() { UnwindTable &Module::GetUnwindTable() { if (!m_unwind_table) { - m_unwind_table.emplace(*this); if (!m_symfile_spec) SymbolLocator::DownloadSymbolFileAsync(GetUUID()); + m_unwind_table.emplace(*this); } return *m_unwind_table; } @@ -1359,15 +1361,10 @@ void Module::SetSymbolFileFileSpec(const FileSpec &file) { // one obj_file->ClearSymtab(); - // Clear the unwind table too, as that may also be affected by the - // symbol file information. - m_unwind_table.reset(); - // The symbol file might be a directory bundle ("/tmp/a.out.dSYM") // instead of a full path to the symbol file within the bundle // ("/tmp/a.out.dSYM/Contents/Resources/DWARF/a.out"). So we need to // check this - if (FileSystem::Instance().IsDirectory(file)) { std::string new_path(file.GetPath()); std::string old_path(obj_file->GetFileSpec().GetPath()); diff --git a/lldb/source/Core/Progress.cpp b/lldb/source/Core/Progress.cpp index b4b5e98b7ba493756d41f9438374d460ff39b256..161038284e215ab357673b922fbae1166303cdd3 100644 --- a/lldb/source/Core/Progress.cpp +++ b/lldb/source/Core/Progress.cpp @@ -35,7 +35,10 @@ Progress::Progress(std::string title, std::string details, std::lock_guard<std::mutex> guard(m_mutex); ReportProgress(); - ProgressManager::Instance().Increment(m_progress_data); + + // Report to the ProgressManager if that subsystem is enabled. + if (ProgressManager::Enabled()) + ProgressManager::Instance().Increment(m_progress_data); } Progress::~Progress() { @@ -45,7 +48,10 @@ Progress::~Progress() { if (!m_completed) m_completed = m_total; ReportProgress(); - ProgressManager::Instance().Decrement(m_progress_data); + + // Report to the ProgressManager if that subsystem is enabled. + if (ProgressManager::Enabled()) + ProgressManager::Instance().Decrement(m_progress_data); } void Progress::Increment(uint64_t amount, @@ -75,45 +81,84 @@ void Progress::ReportProgress() { } } -ProgressManager::ProgressManager() : m_progress_category_map() {} +ProgressManager::ProgressManager() + : m_entries(), m_alarm(std::chrono::milliseconds(100)) {} ProgressManager::~ProgressManager() {} +void ProgressManager::Initialize() { + assert(!InstanceImpl() && "Already initialized."); + InstanceImpl().emplace(); +} + +void ProgressManager::Terminate() { + assert(InstanceImpl() && "Already terminated."); + InstanceImpl().reset(); +} + +bool ProgressManager::Enabled() { return InstanceImpl().operator bool(); } + ProgressManager &ProgressManager::Instance() { - static std::once_flag g_once_flag; - static ProgressManager *g_progress_manager = nullptr; - std::call_once(g_once_flag, []() { - // NOTE: known leak to avoid global destructor chain issues. - g_progress_manager = new ProgressManager(); - }); - return *g_progress_manager; + assert(InstanceImpl() && "ProgressManager must be initialized"); + return *InstanceImpl(); +} + +std::optional<ProgressManager> &ProgressManager::InstanceImpl() { + static std::optional<ProgressManager> g_progress_manager; + return g_progress_manager; } void ProgressManager::Increment(const Progress::ProgressData &progress_data) { - std::lock_guard<std::mutex> lock(m_progress_map_mutex); - // If the current category exists in the map then it is not an initial report, - // therefore don't broadcast to the category bit. Also, store the current - // progress data in the map so that we have a note of the ID used for the - // initial progress report. - if (!m_progress_category_map.contains(progress_data.title)) { - m_progress_category_map[progress_data.title].second = progress_data; + std::lock_guard<std::mutex> lock(m_entries_mutex); + + llvm::StringRef key = progress_data.title; + bool new_entry = !m_entries.contains(key); + Entry &entry = m_entries[progress_data.title]; + + if (new_entry) { + // This is a new progress event. Report progress and store the progress + // data. ReportProgress(progress_data, EventType::Begin); + entry.data = progress_data; + } else if (entry.refcount == 0) { + // This is an existing entry that was scheduled to be deleted but a new one + // came in before the timer expired. + assert(entry.handle != Alarm::INVALID_HANDLE); + + if (!m_alarm.Cancel(entry.handle)) { + // The timer expired before we had a chance to cancel it. We have to treat + // this as an entirely new progress event. + ReportProgress(progress_data, EventType::Begin); + } + // Clear the alarm handle. + entry.handle = Alarm::INVALID_HANDLE; } - m_progress_category_map[progress_data.title].first++; + + // Regardless of how we got here, we need to bump the reference count. + entry.refcount++; } void ProgressManager::Decrement(const Progress::ProgressData &progress_data) { - std::lock_guard<std::mutex> lock(m_progress_map_mutex); - auto pos = m_progress_category_map.find(progress_data.title); + std::lock_guard<std::mutex> lock(m_entries_mutex); + llvm::StringRef key = progress_data.title; - if (pos == m_progress_category_map.end()) + if (!m_entries.contains(key)) return; - if (pos->second.first <= 1) { - ReportProgress(pos->second.second, EventType::End); - m_progress_category_map.erase(progress_data.title); - } else { - --pos->second.first; + Entry &entry = m_entries[key]; + entry.refcount--; + + if (entry.refcount == 0) { + assert(entry.handle == Alarm::INVALID_HANDLE); + + // Copy the key to a std::string so we can pass it by value to the lambda. + // The underlying StringRef will not exist by the time the callback is + // called. + std::string key_str = std::string(key); + + // Start a timer. If it expires before we see another progress event, it + // will be reported. + entry.handle = m_alarm.Create([=]() { Expire(key_str); }); } } @@ -129,3 +174,20 @@ void ProgressManager::ReportProgress( progress_data.debugger_id, Debugger::eBroadcastBitProgressCategory); } + +void ProgressManager::Expire(llvm::StringRef key) { + std::lock_guard<std::mutex> lock(m_entries_mutex); + + // This shouldn't happen but be resilient anyway. + if (!m_entries.contains(key)) + return; + + // A new event came in and the alarm fired before we had a chance to restart + // it. + if (m_entries[key].refcount != 0) + return; + + // We're done with this entry. + ReportProgress(m_entries[key].data, EventType::End); + m_entries.erase(key); +} diff --git a/lldb/source/Core/SourceManager.cpp b/lldb/source/Core/SourceManager.cpp index 517a4b0268d2a00fe3ccc5584368ea6c23249ac6..0d70c554e5342b866564ada464ad54f9fd8fd7d9 100644 --- a/lldb/source/Core/SourceManager.cpp +++ b/lldb/source/Core/SourceManager.cpp @@ -418,7 +418,7 @@ bool SourceManager::GetDefaultFileAndLine(FileSpec &file_spec, uint32_t &line) { if (sc.function->GetAddressRange() .GetBaseAddress() .CalculateSymbolContextLineEntry(line_entry)) { - SetDefaultFileAndLine(line_entry.file, line_entry.line); + SetDefaultFileAndLine(line_entry.GetFile(), line_entry.line); file_spec = m_last_file_spec; line = m_last_line; return true; diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index e4e131d70d4319455ade80d3da5ed92fcbece416..cb9bee8733e15d157508478a6b32e066546d0afb 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -212,18 +212,17 @@ struct IRExecDiagnosticHandler : public llvm::DiagnosticHandler { Status *err; IRExecDiagnosticHandler(Status *err) : err(err) {} bool handleDiagnostics(const llvm::DiagnosticInfo &DI) override { - if (DI.getKind() == llvm::DK_SrcMgr) { + if (DI.getSeverity() == llvm::DS_Error) { const auto &DISM = llvm::cast<llvm::DiagnosticInfoSrcMgr>(DI); if (err && err->Success()) { err->SetErrorToGenericError(); err->SetErrorStringWithFormat( - "Inline assembly error: %s", + "IRExecution error: %s", DISM.getSMDiag().getMessage().str().c_str()); } - return true; } - return false; + return true; } }; } // namespace diff --git a/lldb/source/Host/CMakeLists.txt b/lldb/source/Host/CMakeLists.txt index fe6e539f758fdaaf501dfd317db4545188dc8196..c2e091ee8555b74f3bed06d06af05852f97279d7 100644 --- a/lldb/source/Host/CMakeLists.txt +++ b/lldb/source/Host/CMakeLists.txt @@ -13,6 +13,7 @@ macro(add_host_subdirectory group) endmacro() add_host_subdirectory(common + common/Alarm.cpp common/FileAction.cpp common/FileCache.cpp common/File.cpp diff --git a/lldb/source/Host/common/Alarm.cpp b/lldb/source/Host/common/Alarm.cpp new file mode 100644 index 0000000000000000000000000000000000000000..afc770d20d7b1ed0f07b0881935e787b7082ddd6 --- /dev/null +++ b/lldb/source/Host/common/Alarm.cpp @@ -0,0 +1,222 @@ +//===-- Alarm.cpp ---------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Alarm.h" +#include "lldb/Host/ThreadLauncher.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" + +using namespace lldb; +using namespace lldb_private; + +Alarm::Alarm(Duration timeout, bool run_callback_on_exit) + : m_timeout(timeout), m_run_callbacks_on_exit(run_callback_on_exit) { + StartAlarmThread(); +} + +Alarm::~Alarm() { StopAlarmThread(); } + +Alarm::Handle Alarm::Create(std::function<void()> callback) { + // Gracefully deal with the unlikely event that the alarm thread failed to + // launch. + if (!AlarmThreadRunning()) + return INVALID_HANDLE; + + // Compute the next expiration before we take the lock. This ensures that + // waiting on the lock doesn't eat into the timeout. + const TimePoint expiration = GetNextExpiration(); + + Handle handle = INVALID_HANDLE; + + { + std::lock_guard<std::mutex> alarm_guard(m_alarm_mutex); + + // Create a new unique entry and remember its handle. + m_entries.emplace_back(callback, expiration); + handle = m_entries.back().handle; + + // Tell the alarm thread we need to recompute the next alarm. + m_recompute_next_alarm = true; + } + + m_alarm_cv.notify_one(); + return handle; +} + +bool Alarm::Restart(Handle handle) { + // Gracefully deal with the unlikely event that the alarm thread failed to + // launch. + if (!AlarmThreadRunning()) + return false; + + // Compute the next expiration before we take the lock. This ensures that + // waiting on the lock doesn't eat into the timeout. + const TimePoint expiration = GetNextExpiration(); + + { + std::lock_guard<std::mutex> alarm_guard(m_alarm_mutex); + + // Find the entry corresponding to the given handle. + const auto it = + std::find_if(m_entries.begin(), m_entries.end(), + [handle](Entry &entry) { return entry.handle == handle; }); + if (it == m_entries.end()) + return false; + + // Update the expiration. + it->expiration = expiration; + + // Tell the alarm thread we need to recompute the next alarm. + m_recompute_next_alarm = true; + } + + m_alarm_cv.notify_one(); + return true; +} + +bool Alarm::Cancel(Handle handle) { + // Gracefully deal with the unlikely event that the alarm thread failed to + // launch. + if (!AlarmThreadRunning()) + return false; + + { + std::lock_guard<std::mutex> alarm_guard(m_alarm_mutex); + + const auto it = + std::find_if(m_entries.begin(), m_entries.end(), + [handle](Entry &entry) { return entry.handle == handle; }); + + if (it == m_entries.end()) + return false; + + m_entries.erase(it); + } + + // No need to notify the alarm thread. This only affects the alarm thread if + // we removed the entry that corresponds to the next alarm. If that's the + // case, the thread will wake up as scheduled, find no expired events, and + // recompute the next alarm time. + return true; +} + +Alarm::Entry::Entry(Alarm::Callback callback, Alarm::TimePoint expiration) + : handle(Alarm::GetNextUniqueHandle()), callback(std::move(callback)), + expiration(std::move(expiration)) {} + +void Alarm::StartAlarmThread() { + if (!m_alarm_thread.IsJoinable()) { + llvm::Expected<HostThread> alarm_thread = ThreadLauncher::LaunchThread( + "lldb.debugger.alarm-thread", [this] { return AlarmThread(); }, + 8 * 1024 * 1024); // Use larger 8MB stack for this thread + if (alarm_thread) { + m_alarm_thread = *alarm_thread; + } else { + LLDB_LOG_ERROR(GetLog(LLDBLog::Host), alarm_thread.takeError(), + "failed to launch host thread: {0}"); + } + } +} + +void Alarm::StopAlarmThread() { + if (m_alarm_thread.IsJoinable()) { + { + std::lock_guard<std::mutex> alarm_guard(m_alarm_mutex); + m_exit = true; + } + m_alarm_cv.notify_one(); + m_alarm_thread.Join(nullptr); + } +} + +bool Alarm::AlarmThreadRunning() { return m_alarm_thread.IsJoinable(); } + +lldb::thread_result_t Alarm::AlarmThread() { + bool exit = false; + std::optional<TimePoint> next_alarm; + + const auto predicate = [this] { return m_exit || m_recompute_next_alarm; }; + + while (!exit) { + // Synchronization between the main thread and the alarm thread using a + // mutex and condition variable. There are 2 reasons the thread can wake up: + // + // 1. The timeout for the next alarm expired. + // + // 2. The condition variable is notified that one of our shared variables + // (see predicate) was modified. Either the thread is asked to shut down + // or a new alarm came in and we need to recompute the next timeout. + // + // Below we only deal with the timeout expiring and fall through for dealing + // with the rest. + llvm::SmallVector<Callback, 1> callbacks; + { + std::unique_lock<std::mutex> alarm_lock(m_alarm_mutex); + if (next_alarm) { + if (!m_alarm_cv.wait_until(alarm_lock, *next_alarm, predicate)) { + // The timeout for the next alarm expired. + + // Clear the next timeout to signal that we need to recompute the next + // timeout. + next_alarm.reset(); + + // Iterate over all the callbacks. Call the ones that have expired + // and remove them from the list. + const TimePoint now = std::chrono::system_clock::now(); + auto it = m_entries.begin(); + while (it != m_entries.end()) { + if (it->expiration <= now) { + callbacks.emplace_back(std::move(it->callback)); + it = m_entries.erase(it); + } else { + it++; + } + } + } + } else { + m_alarm_cv.wait(alarm_lock, predicate); + } + + // Fall through after waiting on the condition variable. At this point + // either the predicate is true or we woke up because an alarm expired. + + // The alarm thread is shutting down. + if (m_exit) { + exit = true; + if (m_run_callbacks_on_exit) { + for (Entry &entry : m_entries) + callbacks.emplace_back(std::move(entry.callback)); + } + } + + // A new alarm was added or an alarm expired. Either way we need to + // recompute when this thread should wake up for the next alarm. + if (m_recompute_next_alarm || !next_alarm) { + for (Entry &entry : m_entries) { + if (!next_alarm || entry.expiration < *next_alarm) + next_alarm = entry.expiration; + } + m_recompute_next_alarm = false; + } + } + + // Outside the lock, call the callbacks. + for (Callback &callback : callbacks) + callback(); + } + return {}; +} + +Alarm::TimePoint Alarm::GetNextExpiration() const { + return std::chrono::system_clock::now() + m_timeout; +} + +Alarm::Handle Alarm::GetNextUniqueHandle() { + static std::atomic<Handle> g_next_handle = 1; + return g_next_handle++; +} diff --git a/lldb/source/Interpreter/OptionArgParser.cpp b/lldb/source/Interpreter/OptionArgParser.cpp index 75ccad87467e95a73877d105c39298b1c2d859a9..9a8275128ede9057c8b9fb6cb25f359358aa9901 100644 --- a/lldb/source/Interpreter/OptionArgParser.cpp +++ b/lldb/source/Interpreter/OptionArgParser.cpp @@ -9,7 +9,9 @@ #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/DataFormatters/FormatManager.h" #include "lldb/Target/ABI.h" +#include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/RegisterValue.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" @@ -233,24 +235,68 @@ OptionArgParser::DoToAddress(const ExecutionContext *exe_ctx, llvm::StringRef s, // Since the compiler can't handle things like "main + 12" we should try to // do this for now. The compiler doesn't like adding offsets to function // pointer types. + // Some languages also don't have a natural representation for register + // values (e.g. swift) so handle simple uses of them here as well. + // We use a regex to parse these forms, the regex handles: + // $reg_name + // $reg_name+offset + // symbol_name+offset + // + // The important matching elements in the regex below are: + // 1: The reg name if there's no +offset + // 3: The symbol/reg name if there is an offset + // 4: +/- + // 5: The offset value. static RegularExpression g_symbol_plus_offset_regex( - "^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$"); + "^(\\$[^ +-]+)|(([^ +-]+)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*)$"); llvm::SmallVector<llvm::StringRef, 4> matches; if (g_symbol_plus_offset_regex.Execute(sref, &matches)) { uint64_t offset = 0; - llvm::StringRef name = matches[1]; - llvm::StringRef sign = matches[2]; - llvm::StringRef str_offset = matches[3]; - if (!str_offset.getAsInteger(0, offset)) { + llvm::StringRef name; + if (!matches[1].empty()) + name = matches[1]; + else + name = matches[3]; + + llvm::StringRef sign = matches[4]; + llvm::StringRef str_offset = matches[5]; + + // Some languages don't have a natural type for register values, but it + // is still useful to look them up here: + std::optional<lldb::addr_t> register_value; + StackFrame *frame = exe_ctx->GetFramePtr(); + llvm::StringRef reg_name = name; + if (frame && reg_name.consume_front("$")) { + RegisterContextSP reg_ctx_sp = frame->GetRegisterContext(); + if (reg_ctx_sp) { + const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfoByName(reg_name); + if (reg_info) { + RegisterValue reg_val; + bool success = reg_ctx_sp->ReadRegister(reg_info, reg_val); + if (success && reg_val.GetType() != RegisterValue::eTypeInvalid) { + register_value = reg_val.GetAsUInt64(0, &success); + if (!success) + register_value.reset(); + } + } + } + } + if (!str_offset.empty() && !str_offset.getAsInteger(0, offset)) { Status error; - addr = ToAddress(exe_ctx, name, LLDB_INVALID_ADDRESS, &error); + if (register_value) + addr = register_value.value(); + else + addr = ToAddress(exe_ctx, name, LLDB_INVALID_ADDRESS, &error); if (addr != LLDB_INVALID_ADDRESS) { if (sign[0] == '+') return addr + offset; return addr - offset; } - } + } else if (register_value) + // In the case of register values, someone might just want to get the + // value in a language whose expression parser doesn't support registers. + return register_value.value(); } if (error_ptr) diff --git a/lldb/source/Interpreter/OptionGroupVariable.cpp b/lldb/source/Interpreter/OptionGroupVariable.cpp index 0e35a641361b8202e0537be31b4b83d2f3dff8fd..99644b3f423c81be3462f93bda8e8d160ec3ca64 100644 --- a/lldb/source/Interpreter/OptionGroupVariable.cpp +++ b/lldb/source/Interpreter/OptionGroupVariable.cpp @@ -50,6 +50,11 @@ static constexpr OptionDefinition g_variable_options[] = { "Specify a summary string to use to format the variable output."}, }; +static constexpr auto g_num_frame_options = 4; +static const auto g_variable_options_noframe = + llvm::ArrayRef<OptionDefinition>(g_variable_options) + .drop_front(g_num_frame_options); + static Status ValidateNamedSummary(const char *str, void *) { if (!str || !str[0]) return Status("must specify a valid named summary"); @@ -77,9 +82,9 @@ OptionGroupVariable::SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) { Status error; - if (!include_frame_options) - option_idx += 3; - const int short_option = g_variable_options[option_idx].short_option; + llvm::ArrayRef<OptionDefinition> variable_options = + include_frame_options ? g_variable_options : g_variable_options_noframe; + const int short_option = variable_options[option_idx].short_option; switch (short_option) { case 'r': use_regex = true; @@ -128,16 +133,9 @@ void OptionGroupVariable::OptionParsingStarting( summary_string.Clear(); } -#define NUM_FRAME_OPTS 3 - llvm::ArrayRef<OptionDefinition> OptionGroupVariable::GetDefinitions() { - auto result = llvm::ArrayRef(g_variable_options); - // Show the "--no-args", "--no-locals" and "--show-globals" options if we are - // showing frame specific options - if (include_frame_options) - return result; - - // Skip the "--no-args", "--no-locals" and "--show-globals" options if we are - // not showing frame specific options (globals only) - return result.drop_front(NUM_FRAME_OPTS); + // Show the "--no-args", "--no-recognized-args", "--no-locals" and + // "--show-globals" options if we are showing frame specific options + return include_frame_options ? g_variable_options + : g_variable_options_noframe; } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp index 3d43ed3f99ffba95a7ad08c2350a1c6516ceb9a3..3b601726388d6b89ad00c7d98d5e60cedee1f58c 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp @@ -417,7 +417,7 @@ bool ClangExpressionSourceCode::GetText( if (sc.comp_unit && sc.line_entry.IsValid()) { DebugMacros *dm = sc.comp_unit->GetDebugMacros(); if (dm) { - AddMacroState state(sc.line_entry.file, sc.line_entry.line); + AddMacroState state(sc.line_entry.GetFile(), sc.line_entry.line); AddMacros(dm, sc.comp_unit, state, debug_macros_stream); } } diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt index 97fa894ea737612b69e34cf92cfdd62df51c3fc5..0c6fdb2b957315284706fa7104a7a9dadf175724 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt +++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt @@ -13,6 +13,7 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN LibCxxMap.cpp LibCxxQueue.cpp LibCxxRangesRefView.cpp + LibCxxSliceArray.cpp LibCxxSpan.cpp LibCxxTuple.cpp LibCxxUnorderedMap.cpp diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 675ca3851861029956026a9bc18becadf5643b64..4a536096a066ffbe3db297d55a016d6e732db0f6 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -755,6 +755,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { lldb_private::formatters::LibcxxStdValarraySyntheticFrontEndCreator, "libc++ std::valarray synthetic children", "^std::__[[:alnum:]]+::valarray<.+>$", stl_deref_flags, true); + AddCXXSynthetic( + cpp_category_sp, + lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEndCreator, + "libc++ std::slice_array synthetic children", + "^std::__[[:alnum:]]+::slice_array<.+>$", stl_deref_flags, true); AddCXXSynthetic( cpp_category_sp, lldb_private::formatters::LibcxxStdForwardListSyntheticFrontEndCreator, @@ -880,6 +885,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::valarray summary provider", "^std::__[[:alnum:]]+::valarray<.+>$", stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxStdSliceArraySummaryProvider, + "libc++ std::slice_array summary provider", + "^std::__[[:alnum:]]+::slice_array<.+>$", stl_summary_flags, + true); AddCXXSummary( cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::list summary provider", diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp index 10a1fe0391898495840c689b74188ad5b46bd81d..d2d50152c07cf89e3f5e90a10fe1382fb5298986 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -106,13 +106,13 @@ bool lldb_private::formatters::LibcxxFunctionSummaryProvider( case CPPLanguageRuntime::LibCppStdFunctionCallableCase::Lambda: stream.Printf( " Lambda in File %s at Line %u", - callable_info.callable_line_entry.file.GetFilename().GetCString(), + callable_info.callable_line_entry.GetFile().GetFilename().GetCString(), callable_info.callable_line_entry.line); break; case CPPLanguageRuntime::LibCppStdFunctionCallableCase::CallableObject: stream.Printf( " Function in File %s at Line %u", - callable_info.callable_line_entry.file.GetFilename().GetCString(), + callable_info.callable_line_entry.GetFile().GetFilename().GetCString(), callable_info.callable_line_entry.line); break; case CPPLanguageRuntime::LibCppStdFunctionCallableCase::FreeOrMemberFunction: @@ -1192,7 +1192,7 @@ bool lldb_private::formatters::LibcxxChronoWeekdaySummaryProvider( return false; const unsigned weekday = ptr_sp->GetValueAsUnsigned(0); - if (weekday >= 0 && weekday < 7) + if (weekday < 7) stream << "weekday=" << weekdays[weekday]; else stream.Printf("weekday=%u", weekday); diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h index a59f21841ec89008934c56565d35b735dec06b29..d8b807d180e0683428d68e7cc9c929ea358d02c1 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h @@ -59,6 +59,10 @@ bool LibcxxWStringViewSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); // libc++ std::wstring_view +bool LibcxxStdSliceArraySummaryProvider( + ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &options); // libc++ std::slice_array + bool LibcxxSmartPointerSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions @@ -223,6 +227,10 @@ SyntheticChildrenFrontEnd * LibcxxStdValarraySyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); +SyntheticChildrenFrontEnd * +LibcxxStdSliceArraySyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP); + SyntheticChildrenFrontEnd * LibcxxStdListSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxSliceArray.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxSliceArray.cpp new file mode 100644 index 0000000000000000000000000000000000000000..32e67d2e38c5d3ee453a47a838c17fc3f3b0b8db --- /dev/null +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxSliceArray.cpp @@ -0,0 +1,166 @@ +//===-- LibCxxSliceArray.cpp-----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "LibCxx.h" + +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include <optional> + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +namespace lldb_private { +namespace formatters { + +bool LibcxxStdSliceArraySummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &options) { + ValueObjectSP obj = valobj.GetNonSyntheticValue(); + if (!obj) + return false; + + ValueObjectSP ptr_sp = obj->GetChildMemberWithName("__size_"); + if (!ptr_sp) + return false; + const size_t size = ptr_sp->GetValueAsUnsigned(0); + + ptr_sp = obj->GetChildMemberWithName("__stride_"); + if (!ptr_sp) + return false; + const size_t stride = ptr_sp->GetValueAsUnsigned(0); + + stream.Printf("stride=%zu size=%zu", stride, size); + + return true; +} + +/// Data formatter for libc++'s std::slice_array. +/// +/// A slice_array is created by using: +/// operator[](std::slice slicearr); +/// and std::slice is created by: +/// slice(std::size_t start, std::size_t size, std::size_t stride); +/// The std::slice_array has the following members: +/// - __vp_ points to std::valarray::__begin_ + @a start +/// - __size_ is @a size +/// - __stride_is @a stride +class LibcxxStdSliceArraySyntheticFrontEnd : public SyntheticChildrenFrontEnd { +public: + LibcxxStdSliceArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + + ~LibcxxStdSliceArraySyntheticFrontEnd() override; + + llvm::Expected<uint32_t> CalculateNumChildren() override; + + lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override; + + lldb::ChildCacheState Update() override; + + bool MightHaveChildren() override; + + size_t GetIndexOfChildWithName(ConstString name) override; + +private: + /// A non-owning pointer to slice_array.__vp_. + ValueObject *m_start = nullptr; + /// slice_array.__size_. + size_t m_size = 0; + /// slice_array.__stride_. + size_t m_stride = 0; + /// The type of slize_array's template argument T. + CompilerType m_element_type; + /// The sizeof slize_array's template argument T. + uint32_t m_element_size = 0; +}; + +} // namespace formatters +} // namespace lldb_private + +lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd:: + LibcxxStdSliceArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) + : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() { + if (valobj_sp) + Update(); +} + +lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd:: + ~LibcxxStdSliceArraySyntheticFrontEnd() { + // these need to stay around because they are child objects who will follow + // their parent's life cycle + // delete m_start; +} + +llvm::Expected<uint32_t> lldb_private::formatters:: + LibcxxStdSliceArraySyntheticFrontEnd::CalculateNumChildren() { + return m_size; +} + +lldb::ValueObjectSP +lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::GetChildAtIndex( + uint32_t idx) { + if (!m_start) + return lldb::ValueObjectSP(); + + uint64_t offset = idx * m_stride * m_element_size; + offset = offset + m_start->GetValueAsUnsigned(0); + StreamString name; + name.Printf("[%" PRIu64 "]", (uint64_t)idx); + return CreateValueObjectFromAddress(name.GetString(), offset, + m_backend.GetExecutionContextRef(), + m_element_type); +} + +lldb::ChildCacheState +lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd::Update() { + m_start = nullptr; + + CompilerType type = m_backend.GetCompilerType(); + if (type.GetNumTemplateArguments() == 0) + return ChildCacheState::eRefetch; + + m_element_type = type.GetTypeTemplateArgument(0); + if (std::optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) + m_element_size = *size; + + if (m_element_size == 0) + return ChildCacheState::eRefetch; + + ValueObjectSP start = m_backend.GetChildMemberWithName("__vp_"); + ValueObjectSP size = m_backend.GetChildMemberWithName("__size_"); + ValueObjectSP stride = m_backend.GetChildMemberWithName("__stride_"); + + if (!start || !size || !stride) + return ChildCacheState::eRefetch; + + m_start = start.get(); + m_size = size->GetValueAsUnsigned(0); + m_stride = stride->GetValueAsUnsigned(0); + + return ChildCacheState::eRefetch; +} + +bool lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd:: + MightHaveChildren() { + return true; +} + +size_t lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEnd:: + GetIndexOfChildWithName(ConstString name) { + if (!m_start) + return std::numeric_limits<size_t>::max(); + return ExtractIndexFromString(name.GetCString()); +} + +lldb_private::SyntheticChildrenFrontEnd * +lldb_private::formatters::LibcxxStdSliceArraySyntheticFrontEndCreator( + CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { + if (!valobj_sp) + return nullptr; + return new LibcxxStdSliceArraySyntheticFrontEnd(valobj_sp); +} diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 3e5ee6f66373032e76dc9c13492bd94224866187..d3fc487aed4333d2b2425b516d9fe69ce74c1854 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -3154,7 +3154,7 @@ AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor( << m_objc_debug_taggedpointer_ext_payload_lshift) >> m_objc_debug_taggedpointer_ext_payload_rshift); int64_t data_payload_signed = - ((int64_t)((int64_t)unobfuscated + ((int64_t)((uint64_t)unobfuscated << m_objc_debug_taggedpointer_ext_payload_lshift) >> m_objc_debug_taggedpointer_ext_payload_rshift); diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index bcf3a3274cf3a086605e8086feac867f8e698d5d..1caf93659956b4e80a510dcf4e0a7cae4a18183a 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -905,6 +905,11 @@ ConstString ObjectFileMachO::GetSegmentNameDWARF() { return g_section_name; } +ConstString ObjectFileMachO::GetSegmentNameLLVM_COV() { + static ConstString g_section_name("__LLVM_COV"); + return g_section_name; +} + ConstString ObjectFileMachO::GetSectionNameEHFrame() { static ConstString g_section_name_eh_frame("__eh_frame"); return g_section_name_eh_frame; @@ -6145,6 +6150,13 @@ bool ObjectFileMachO::SectionIsLoadable(const Section *section) { return false; if (GetModule().get() != section->GetModule().get()) return false; + // firmware style binaries with llvm gcov segment do + // not have that segment mapped into memory. + if (section->GetName() == GetSegmentNameLLVM_COV()) { + const Strata strata = GetStrata(); + if (strata == eStrataKernel || strata == eStrataRawImage) + return false; + } // Be careful with __LINKEDIT and __DWARF segments if (section->GetName() == GetSegmentNameLINKEDIT() || section->GetName() == GetSegmentNameDWARF()) { diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h index 0a47f3a7dd18616042273ec46514578b3fb64027..55bc688126eb36ee9d35af61e9d915ab0c3153d2 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h @@ -271,6 +271,7 @@ protected: static lldb_private::ConstString GetSegmentNameOBJC(); static lldb_private::ConstString GetSegmentNameLINKEDIT(); static lldb_private::ConstString GetSegmentNameDWARF(); + static lldb_private::ConstString GetSegmentNameLLVM_COV(); static lldb_private::ConstString GetSectionNameEHFrame(); llvm::MachO::dysymtab_command m_dysymtab; diff --git a/lldb/source/Plugins/Process/Utility/AuxVector.h b/lldb/source/Plugins/Process/Utility/AuxVector.h index 3b0f55d35e5d116078bdc21c6ee99f2668a90ef5..2670b34f6b0af9713ec5b7897af6fb7fb4df2ef3 100644 --- a/lldb/source/Plugins/Process/Utility/AuxVector.h +++ b/lldb/source/Plugins/Process/Utility/AuxVector.h @@ -20,25 +20,30 @@ public: AuxVector(const lldb_private::DataExtractor &data); /// Constants describing the type of entry. - /// On Linux, running "LD_SHOW_AUXV=1 ./executable" will spew AUX + /// On Linux and FreeBSD, running "LD_SHOW_AUXV=1 ./executable" will spew AUX /// information. Added AUXV prefix to avoid potential conflicts with system- - /// defined macros + /// defined macros. For FreeBSD, the numbers can be found in sys/elf_common.h. enum EntryType { - AUXV_AT_NULL = 0, ///< End of auxv. - AUXV_AT_IGNORE = 1, ///< Ignore entry. - AUXV_AT_EXECFD = 2, ///< File descriptor of program. - AUXV_AT_PHDR = 3, ///< Program headers. - AUXV_AT_PHENT = 4, ///< Size of program header. - AUXV_AT_PHNUM = 5, ///< Number of program headers. - AUXV_AT_PAGESZ = 6, ///< Page size. - AUXV_AT_BASE = 7, ///< Interpreter base address. - AUXV_AT_FLAGS = 8, ///< Flags. - AUXV_AT_ENTRY = 9, ///< Program entry point. - AUXV_AT_NOTELF = 10, ///< Set if program is not an ELF. - AUXV_AT_UID = 11, ///< UID. - AUXV_AT_EUID = 12, ///< Effective UID. - AUXV_AT_GID = 13, ///< GID. - AUXV_AT_EGID = 14, ///< Effective GID. + AUXV_AT_NULL = 0, ///< End of auxv. + AUXV_AT_IGNORE = 1, ///< Ignore entry. + AUXV_AT_EXECFD = 2, ///< File descriptor of program. + AUXV_AT_PHDR = 3, ///< Program headers. + AUXV_AT_PHENT = 4, ///< Size of program header. + AUXV_AT_PHNUM = 5, ///< Number of program headers. + AUXV_AT_PAGESZ = 6, ///< Page size. + AUXV_AT_BASE = 7, ///< Interpreter base address. + AUXV_AT_FLAGS = 8, ///< Flags. + AUXV_AT_ENTRY = 9, ///< Program entry point. + AUXV_AT_NOTELF = 10, ///< Set if program is not an ELF. + AUXV_AT_UID = 11, ///< UID. + AUXV_AT_EUID = 12, ///< Effective UID. + AUXV_AT_GID = 13, ///< GID. + AUXV_AT_EGID = 14, ///< Effective GID. + + // At this point Linux and FreeBSD diverge and many of the following values + // are Linux specific. If you use them make sure you are in Linux specific + // code or they have the same value on other platforms. + AUXV_AT_CLKTCK = 17, ///< Clock frequency (e.g. times(2)). AUXV_AT_PLATFORM = 15, ///< String identifying platform. AUXV_AT_HWCAP = @@ -60,6 +65,10 @@ public: AUXV_AT_L1D_CACHESHAPE = 35, AUXV_AT_L2_CACHESHAPE = 36, AUXV_AT_L3_CACHESHAPE = 37, + + // Platform specific values which may overlap the Linux values. + + AUXV_FREEBSD_AT_HWCAP = 25, ///< FreeBSD specific AT_HWCAP value. }; std::optional<uint64_t> GetAuxValue(enum EntryType entry_type) const; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 5b9a9d71802f86c365c6f970e27f66d12aec7d81..871683a605686febc037546b7ce4085a13493732 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -900,7 +900,7 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { } AddressableBits addressable_bits = m_gdb_comm.GetAddressableBits(); - addressable_bits.SetProcessMasks(*this); + SetAddressableBitMasks(addressable_bits); if (process_arch.IsValid()) { const ArchSpec &target_arch = GetTarget().GetArchitecture(); @@ -2337,7 +2337,7 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { } } - addressable_bits.SetProcessMasks(*this); + SetAddressableBitMasks(addressable_bits); ThreadSP thread_sp = SetThreadStopInfo( tid, expedited_register_map, signo, thread_name, reason, description, diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp index 3961dcf0fbcc0eabc9c8ffa2517ccd7239c3841e..1da7696c9a352abd90aaae3cc50445b89beec67e 100644 --- a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp +++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp @@ -574,7 +574,7 @@ Status ProcessMachCore::DoLoadCore() { CleanupMemoryRegionPermissions(); AddressableBits addressable_bits = core_objfile->GetAddressableBits(); - addressable_bits.SetProcessMasks(*this); + SetAddressableBitMasks(addressable_bits); return error; } @@ -652,7 +652,7 @@ size_t ProcessMachCore::ReadMemory(addr_t addr, void *buf, size_t size, Status &error) { // Don't allow the caching that lldb_private::Process::ReadMemory does since // in core files we have it all cached our our core file anyway. - return DoReadMemory(addr, buf, size, error); + return DoReadMemory(FixAnyAddress(addr), buf, size, error); } size_t ProcessMachCore::DoReadMemory(addr_t addr, void *buf, size_t size, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 5f67658f86ea96160d3fc0a0accebffefb196c7b..49f13d2c89e3803da429d3e7bd1f27e888251e0c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -693,6 +693,7 @@ llvm::DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() { if (debug_abbrev_data.GetByteSize() == 0) return nullptr; + ElapsedTime elapsed(m_parse_time); auto abbr = std::make_unique<llvm::DWARFDebugAbbrev>(debug_abbrev_data.GetAsLLVM()); llvm::Error error = abbr->parse(); @@ -3419,8 +3420,8 @@ static DWARFExpressionList GetExprListFromAtLocation(DWARFFormValue form_value, if (DWARFFormValue::IsBlockForm(form_value.Form())) { const DWARFDataExtractor &data = die.GetData(); - uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); - uint32_t block_length = form_value.Unsigned(); + uint64_t block_offset = form_value.BlockData() - data.GetDataStart(); + uint64_t block_length = form_value.Unsigned(); return DWARFExpressionList( module, DataExtractor(data, block_offset, block_length), die.GetCU()); } @@ -3449,9 +3450,9 @@ GetExprListFromAtConstValue(DWARFFormValue form_value, ModuleSP module, const DWARFDataExtractor &debug_info_data = die.GetData(); if (DWARFFormValue::IsBlockForm(form_value.Form())) { // Retrieve the value as a block expression. - uint32_t block_offset = + uint64_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); - uint32_t block_length = form_value.Unsigned(); + uint64_t block_length = form_value.Unsigned(); return DWARFExpressionList( module, DataExtractor(debug_info_data, block_offset, block_length), die.GetCU()); @@ -4060,8 +4061,8 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) { if (!DWARFFormValue::IsBlockForm(form_value.Form())) return {}; auto data = child.GetData(); - uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); - uint32_t block_length = form_value.Unsigned(); + uint64_t block_offset = form_value.BlockData() - data.GetDataStart(); + uint64_t block_length = form_value.Unsigned(); return DWARFExpressionList( module, DataExtractor(data, block_offset, block_length), child.GetCU()); @@ -4166,8 +4167,8 @@ SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) { } auto data = child.GetData(); - uint32_t block_offset = form_value.BlockData() - data.GetDataStart(); - uint32_t block_length = form_value.Unsigned(); + uint64_t block_offset = form_value.BlockData() - data.GetDataStart(); + uint64_t block_length = form_value.Unsigned(); call_target = DWARFExpressionList( module, DataExtractor(data, block_offset, block_length), child.GetCU()); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 6dd3eb3677b7af2f019c56a580169f9572198ee1..4bc2cfd60688a8980936bbf9128a1645cb82fa42 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1233,7 +1233,7 @@ void SymbolFileDWARFDebugMap::FindTypes(const TypeQuery &query, std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { oso_dwarf->FindTypes(query, results); - return !results.Done(query); // Keep iterating if we aren't done. + return results.Done(query); // Keep iterating if we aren't done. }); } @@ -1391,7 +1391,7 @@ void SymbolFileDWARFDebugMap::ParseDeclsForContext( lldb_private::CompilerDeclContext decl_ctx) { ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { oso_dwarf->ParseDeclsForContext(decl_ctx); - return true; // Keep iterating + return false; // Keep iterating }); } diff --git a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp index f7df4650941a800713cad3ed153495c7fe6abbb7..69595c6c14e4c003725ea452f3514f5dc3ddf4d4 100644 --- a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp +++ b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp @@ -1066,11 +1066,21 @@ bool SymbolLocatorDebugSymbols::DownloadObjectAndSymbolFile( command << lookup_arg; // Log and report progress. + std::string lookup_desc; + if (uuid_ptr && file_spec_ptr) + lookup_desc = + llvm::formatv("{0} ({1})", file_spec_ptr->GetFilename().GetString(), + uuid_ptr->GetAsString()); + else if (uuid_ptr) + lookup_desc = uuid_ptr->GetAsString(); + else if (file_spec_ptr) + lookup_desc = file_spec_ptr->GetFilename().GetString(); + Log *log = GetLog(LLDBLog::Host); - LLDB_LOG(log, "Calling {0} with {1} to find dSYM: {2}", dsymForUUID_exe_path, - lookup_arg, command.GetString()); + LLDB_LOG(log, "Calling {0} for {1} to find dSYM: {2}", dsymForUUID_exe_path, + lookup_desc, command.GetString()); - Progress progress("Downloading symbol file", lookup_arg); + Progress progress("Downloading symbol file for", lookup_desc); // Invoke dsymForUUID. int exit_status = -1; diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 68d9165b90a47b1610cb6d0f273c9ff769b884cf..4a1c8d57655215ab09fe2e2f7256d54496d21396 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -477,6 +477,7 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) { // Based on the base language, pick one. switch (IK.getLanguage()) { case clang::Language::Unknown: + case clang::Language::CIR: case clang::Language::LLVM_IR: case clang::Language::RenderScript: llvm_unreachable("Invalid input kind!"); @@ -4074,6 +4075,7 @@ TypeSystemClang::GetTypeClass(lldb::opaque_compiler_type_t type) { switch (qual_type->getTypeClass()) { case clang::Type::Atomic: case clang::Type::Auto: + case clang::Type::CountAttributed: case clang::Type::Decltype: case clang::Type::Elaborated: case clang::Type::Paren: @@ -4095,6 +4097,8 @@ TypeSystemClang::GetTypeClass(lldb::opaque_compiler_type_t type) { return lldb::eTypeClassArray; case clang::Type::DependentSizedArray: return lldb::eTypeClassArray; + case clang::Type::ArrayParameter: + return lldb::eTypeClassArray; case clang::Type::DependentSizedExtVector: return lldb::eTypeClassVector; case clang::Type::DependentVector: @@ -4755,6 +4759,7 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type, switch (qual_type->getTypeClass()) { case clang::Type::Atomic: case clang::Type::Auto: + case clang::Type::CountAttributed: case clang::Type::Decltype: case clang::Type::Elaborated: case clang::Type::Paren: @@ -4773,6 +4778,7 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type, case clang::Type::IncompleteArray: case clang::Type::VariableArray: + case clang::Type::ArrayParameter: break; case clang::Type::ConstantArray: @@ -5088,6 +5094,7 @@ lldb::Format TypeSystemClang::GetFormat(lldb::opaque_compiler_type_t type) { switch (qual_type->getTypeClass()) { case clang::Type::Atomic: case clang::Type::Auto: + case clang::Type::CountAttributed: case clang::Type::Decltype: case clang::Type::Elaborated: case clang::Type::Paren: @@ -5105,6 +5112,7 @@ lldb::Format TypeSystemClang::GetFormat(lldb::opaque_compiler_type_t type) { case clang::Type::IncompleteArray: case clang::Type::VariableArray: + case clang::Type::ArrayParameter: break; case clang::Type::ConstantArray: diff --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp index 1b3cd23d94006a292f518ae9bbeaa8304d2c1859..ddeacf18e855ee324bc05d2745b3ca32b1a3cb6b 100644 --- a/lldb/source/Symbol/CompileUnit.cpp +++ b/lldb/source/Symbol/CompileUnit.cpp @@ -320,7 +320,7 @@ void CompileUnit::ResolveSymbolContext( src_location_spec.GetColumn() ? std::optional<uint16_t>(line_entry.column) : std::nullopt; - SourceLocationSpec found_entry(line_entry.file, line_entry.line, column, + SourceLocationSpec found_entry(line_entry.GetFile(), line_entry.line, column, inlines, exact); while (line_idx != UINT32_MAX) { diff --git a/lldb/source/Symbol/Function.cpp b/lldb/source/Symbol/Function.cpp index fdc090355771c6aea66197f1f96f3ffe95e2570a..194f89bc51d80729a956fa6894021be3c3dc546f 100644 --- a/lldb/source/Symbol/Function.cpp +++ b/lldb/source/Symbol/Function.cpp @@ -289,7 +289,7 @@ void Function::GetStartLineSourceInfo(FileSpec &source_file, if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), line_entry, nullptr)) { line_no = line_entry.line; - source_file = line_entry.file; + source_file = line_entry.GetFile(); } } } @@ -311,7 +311,7 @@ void Function::GetEndLineSourceInfo(FileSpec &source_file, uint32_t &line_no) { LineEntry line_entry; if (line_table->FindLineEntryByAddress(scratch_addr, line_entry, nullptr)) { line_no = line_entry.line; - source_file = line_entry.file; + source_file = line_entry.GetFile(); } } diff --git a/lldb/source/Symbol/LineEntry.cpp b/lldb/source/Symbol/LineEntry.cpp index 389f8dcb65d8d8ef5c36b0b3ca3db8fc301d5091..461399e0326e919fc380edc3524c973842839b5c 100644 --- a/lldb/source/Symbol/LineEntry.cpp +++ b/lldb/source/Symbol/LineEntry.cpp @@ -14,12 +14,14 @@ using namespace lldb_private; LineEntry::LineEntry() - : range(), file(), is_start_of_statement(0), is_start_of_basic_block(0), - is_prologue_end(0), is_epilogue_begin(0), is_terminal_entry(0) {} + : range(), file_sp(std::make_shared<SupportFile>()), + original_file_sp(std::make_shared<SupportFile>()), + is_start_of_statement(0), is_start_of_basic_block(0), is_prologue_end(0), + is_epilogue_begin(0), is_terminal_entry(0) {} void LineEntry::Clear() { range.Clear(); - file.Clear(); + file_sp = std::make_shared<SupportFile>(); original_file_sp = std::make_shared<SupportFile>(); line = LLDB_INVALID_LINE_NUMBER; column = 0; @@ -35,6 +37,7 @@ bool LineEntry::IsValid() const { } bool LineEntry::DumpStopContext(Stream *s, bool show_fullpaths) const { + const FileSpec &file = file_sp->GetSpecOnly(); if (file) { if (show_fullpaths) file.Dump(s->AsRawOstream()); @@ -67,7 +70,7 @@ bool LineEntry::Dump(Stream *s, Target *target, bool show_file, return false; } if (show_file) - *s << ", file = " << file; + *s << ", file = " << GetFile(); if (line) s->Printf(", line = %u", line); if (column) @@ -103,7 +106,7 @@ bool LineEntry::GetDescription(Stream *s, lldb::DescriptionLevel level, Address::DumpStyleFileAddress); } - *s << ": " << file; + *s << ": " << GetFile(); if (line) { s->Printf(":%u", line); @@ -173,7 +176,7 @@ int LineEntry::Compare(const LineEntry &a, const LineEntry &b) { if (a.column > b.column) return +1; - return FileSpec::Compare(a.file, b.file, true); + return FileSpec::Compare(a.GetFile(), b.GetFile(), true); } AddressRange LineEntry::GetSameLineContiguousAddressRange( @@ -242,6 +245,6 @@ void LineEntry::ApplyFileMappings(lldb::TargetSP target_sp) { // Apply any file remappings to our file. if (auto new_file_spec = target_sp->GetSourcePathMap().FindFile( original_file_sp->GetSpecOnly())) - file = *new_file_spec; + file_sp->Update(*new_file_spec); } } diff --git a/lldb/source/Symbol/LineTable.cpp b/lldb/source/Symbol/LineTable.cpp index 444135f63bc0c9ff728f7428b3f0d5d20a6c7df6..06cf4f698316c63e34824693ac3a89090a9d4f90 100644 --- a/lldb/source/Symbol/LineTable.cpp +++ b/lldb/source/Symbol/LineTable.cpp @@ -288,8 +288,8 @@ bool LineTable::ConvertEntryAtIndexToLineEntry(uint32_t idx, else line_entry.range.SetByteSize(0); - line_entry.file = - m_comp_unit->GetSupportFiles().GetFileSpecAtIndex(entry.file_idx); + line_entry.file_sp = std::make_shared<SupportFile>( + m_comp_unit->GetSupportFiles().GetFileSpecAtIndex(entry.file_idx)); line_entry.original_file_sp = m_comp_unit->GetSupportFiles().GetSupportFileAtIndex(entry.file_idx); line_entry.line = entry.line; diff --git a/lldb/source/Symbol/SymbolContext.cpp b/lldb/source/Symbol/SymbolContext.cpp index 3c70b8d8743cfc1409abf2ea6ad2ef3e6ca61091..f368896fbad490e78c0171cde02c1b235f4639b6 100644 --- a/lldb/source/Symbol/SymbolContext.cpp +++ b/lldb/source/Symbol/SymbolContext.cpp @@ -472,8 +472,8 @@ bool SymbolContext::GetParentOfInlinedScope(const Address &curr_frame_pc, curr_inlined_block->GetInlinedFunctionInfo(); next_frame_pc = range.GetBaseAddress(); next_frame_sc.line_entry.range.GetBaseAddress() = next_frame_pc; - next_frame_sc.line_entry.file = - curr_inlined_block_inlined_info->GetCallSite().GetFile(); + next_frame_sc.line_entry.file_sp = std::make_shared<SupportFile>( + curr_inlined_block_inlined_info->GetCallSite().GetFile()); next_frame_sc.line_entry.original_file_sp = std::make_shared<SupportFile>( curr_inlined_block_inlined_info->GetCallSite().GetFile()); diff --git a/lldb/source/Symbol/UnwindTable.cpp b/lldb/source/Symbol/UnwindTable.cpp index 3c1a5187b11054bac41899a37a8db9ea9af62b82..11bedf3d6052e7f28906176d7818e18d1eb78045 100644 --- a/lldb/source/Symbol/UnwindTable.cpp +++ b/lldb/source/Symbol/UnwindTable.cpp @@ -84,6 +84,51 @@ void UnwindTable::Initialize() { } } +void UnwindTable::Update() { + if (!m_initialized) + return Initialize(); + + std::lock_guard<std::mutex> guard(m_mutex); + + ObjectFile *object_file = m_module.GetObjectFile(); + if (!object_file) + return; + + if (!m_object_file_unwind_up) + m_object_file_unwind_up = object_file->CreateCallFrameInfo(); + + SectionList *sl = m_module.GetSectionList(); + if (!sl) + return; + + SectionSP sect = sl->FindSectionByType(eSectionTypeEHFrame, true); + if (!m_eh_frame_up && sect) { + m_eh_frame_up = std::make_unique<DWARFCallFrameInfo>( + *object_file, sect, DWARFCallFrameInfo::EH); + } + + sect = sl->FindSectionByType(eSectionTypeDWARFDebugFrame, true); + if (!m_debug_frame_up && sect) { + m_debug_frame_up = std::make_unique<DWARFCallFrameInfo>( + *object_file, sect, DWARFCallFrameInfo::DWARF); + } + + sect = sl->FindSectionByType(eSectionTypeCompactUnwind, true); + if (!m_compact_unwind_up && sect) { + m_compact_unwind_up = + std::make_unique<CompactUnwindInfo>(*object_file, sect); + } + + sect = sl->FindSectionByType(eSectionTypeARMexidx, true); + if (!m_arm_unwind_up && sect) { + SectionSP sect_extab = sl->FindSectionByType(eSectionTypeARMextab, true); + if (sect_extab.get()) { + m_arm_unwind_up = + std::make_unique<ArmUnwindInfo>(*object_file, sect, sect_extab); + } + } +} + UnwindTable::~UnwindTable() = default; std::optional<AddressRange> diff --git a/lldb/source/Target/Language.cpp b/lldb/source/Target/Language.cpp index caf3e6636c1de13dea2586445146c9dafbe2201c..1542c8cb68ce657352e2d64c54939df00b2e8363 100644 --- a/lldb/source/Target/Language.cpp +++ b/lldb/source/Target/Language.cpp @@ -13,6 +13,7 @@ #include "lldb/Target/Language.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Interpreter/OptionValueProperties.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Target/Target.h" @@ -27,6 +28,35 @@ using namespace lldb_private::formatters; typedef std::unique_ptr<Language> LanguageUP; typedef std::map<lldb::LanguageType, LanguageUP> LanguagesMap; +#define LLDB_PROPERTIES_language +#include "TargetProperties.inc" + +enum { +#define LLDB_PROPERTIES_language +#include "TargetPropertiesEnum.inc" +}; + +LanguageProperties &Language::GetGlobalLanguageProperties() { + static LanguageProperties g_settings; + return g_settings; +} + +llvm::StringRef LanguageProperties::GetSettingName() { + static constexpr llvm::StringLiteral g_setting_name("language"); + return g_setting_name; +} + +LanguageProperties::LanguageProperties() { + m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); + m_collection_sp->Initialize(g_language_properties); +} + +bool LanguageProperties::GetEnableFilterForLineBreakpoints() const { + const uint32_t idx = ePropertyEnableFilterForLineBreakpoints; + return GetPropertyAtIndexAs<bool>( + idx, g_language_properties[idx].default_uint_value != 0); +} + static LanguagesMap &GetLanguagesMap() { static LanguagesMap *g_map = nullptr; static llvm::once_flag g_initialize; diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 6d58873b54a3adba2fe00e6146f955e59d6f086d..f02ec37cb0f08fbe0f0ff1b671567724fd23022a 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -63,6 +63,7 @@ #include "lldb/Target/ThreadPlanCallFunction.h" #include "lldb/Target/ThreadPlanStack.h" #include "lldb/Target/UnixSignals.h" +#include "lldb/Utility/AddressableBits.h" #include "lldb/Utility/Event.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" @@ -6453,3 +6454,25 @@ Status Process::CalculateCoreFileSaveRanges(lldb::SaveCoreStyle core_style, return Status(); // Success! } + +void Process::SetAddressableBitMasks(AddressableBits bit_masks) { + uint32_t low_memory_addr_bits = bit_masks.GetLowmemAddressableBits(); + uint32_t high_memory_addr_bits = bit_masks.GetHighmemAddressableBits(); + + if (low_memory_addr_bits == 0 && high_memory_addr_bits == 0) + return; + + if (low_memory_addr_bits != 0) { + addr_t low_addr_mask = + AddressableBits::AddressableBitToMask(low_memory_addr_bits); + SetCodeAddressMask(low_addr_mask); + SetDataAddressMask(low_addr_mask); + } + + if (high_memory_addr_bits != 0) { + addr_t high_addr_mask = + AddressableBits::AddressableBitToMask(high_memory_addr_bits); + SetHighmemCodeAddressMask(high_addr_mask); + SetHighmemDataAddressMask(high_addr_mask); + } +} diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index c29a71d92572e2e42c5ee5f0d3023e6f4eace815..03a74f29e76e99f81ebad6134965e985fef09aff 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -1800,7 +1800,6 @@ void StackFrame::DumpUsingSettingsFormat(Stream *strm, bool show_unique, return; ExecutionContext exe_ctx(shared_from_this()); - StreamString s; const FormatEntity::Entry *frame_format = nullptr; Target *target = exe_ctx.GetTargetPtr(); @@ -1922,7 +1921,7 @@ bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source, size_t num_lines = target->GetSourceManager().DisplaySourceLinesWithLineNumbers( - m_sc.line_entry.file, start_line, m_sc.line_entry.column, + m_sc.line_entry.GetFile(), start_line, m_sc.line_entry.column, source_lines_before, source_lines_after, "->", &strm); if (num_lines != 0) have_source = true; diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp index 2273e52e2e048190ad055d8d9eca9cb94a53f920..314b5e39c71699d577eb427fcc4112c45ca6c610 100644 --- a/lldb/source/Target/StackFrameList.cpp +++ b/lldb/source/Target/StackFrameList.cpp @@ -884,9 +884,9 @@ void StackFrameList::SetDefaultFileAndLineToSelectedFrame() { GetFrameAtIndex(GetSelectedFrameIndex(DoNoSelectMostRelevantFrame))); if (frame_sp) { SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextLineEntry); - if (sc.line_entry.file) + if (sc.line_entry.GetFile()) m_thread.CalculateTarget()->GetSourceManager().SetDefaultFileAndLine( - sc.line_entry.file, sc.line_entry.line); + sc.line_entry.GetFile(), sc.line_entry.line); } } } diff --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td index d2fccdb7b9b39c9d1ddfcb1503379a2c1e5eec49..7f79218e0a6a4d4a63910a67b5a05dbbfe29e4ed 100644 --- a/lldb/source/Target/TargetProperties.td +++ b/lldb/source/Target/TargetProperties.td @@ -311,3 +311,9 @@ let Definition = "thread" in { DefaultUnsignedValue<600000>, Desc<"Maximum number of frames to backtrace.">; } + +let Definition = "language" in { + def EnableFilterForLineBreakpoints: Property<"enable-filter-for-line-breakpoints", "Boolean">, + DefaultTrue, + Desc<"If true, allow Language plugins to filter locations when setting breakpoints by line number or regex.">; +} diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index 4dfad23b56e2cb6655b598cdfe0134db62c15bd1..412e44ede9c13b4eb2114ce9932291d0dad1f62b 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -302,10 +302,10 @@ bool Thread::SetSelectedFrameByIndexNoisily(uint32_t frame_idx, SymbolContext frame_sc( frame_sp->GetSymbolContext(eSymbolContextLineEntry)); const Debugger &debugger = GetProcess()->GetTarget().GetDebugger(); - if (debugger.GetUseExternalEditor() && frame_sc.line_entry.file && + if (debugger.GetUseExternalEditor() && frame_sc.line_entry.GetFile() && frame_sc.line_entry.line != 0) { if (llvm::Error e = Host::OpenFileInExternalEditor( - debugger.GetExternalEditor(), frame_sc.line_entry.file, + debugger.GetExternalEditor(), frame_sc.line_entry.GetFile(), frame_sc.line_entry.line)) { LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(e), "OpenFileInExternalEditor failed: {0}"); @@ -1753,10 +1753,10 @@ size_t Thread::GetStatus(Stream &strm, uint32_t start_frame, if (frame_sp) { SymbolContext frame_sc( frame_sp->GetSymbolContext(eSymbolContextLineEntry)); - if (frame_sc.line_entry.line != 0 && frame_sc.line_entry.file) { + if (frame_sc.line_entry.line != 0 && frame_sc.line_entry.GetFile()) { if (llvm::Error e = Host::OpenFileInExternalEditor( target->GetDebugger().GetExternalEditor(), - frame_sc.line_entry.file, frame_sc.line_entry.line)) { + frame_sc.line_entry.GetFile(), frame_sc.line_entry.line)) { LLDB_LOG_ERROR(GetLog(LLDBLog::Host), std::move(e), "OpenFileInExternalEditor failed: {0}"); } diff --git a/lldb/source/Target/TraceDumper.cpp b/lldb/source/Target/TraceDumper.cpp index e92419e70b32baa29257fbea86cf49caf2cf60ce..4ef8efc1a67689cda1e42a4e6f3c5c03f52b7889 100644 --- a/lldb/source/Target/TraceDumper.cpp +++ b/lldb/source/Target/TraceDumper.cpp @@ -57,7 +57,7 @@ static bool FileLineAndColumnMatches(const LineEntry &a, const LineEntry &b) { return false; if (a.column != b.column) return false; - return a.file == b.file; + return a.GetFile() == b.GetFile(); } /// Compare the symbol contexts of the provided \a SymbolInfo @@ -396,7 +396,7 @@ public: m_j.attribute( "source", ToOptionalString( - item.symbol_info->sc.line_entry.file.GetPath().c_str())); + item.symbol_info->sc.line_entry.GetFile().GetPath().c_str())); m_j.attribute("line", item.symbol_info->sc.line_entry.line); m_j.attribute("column", item.symbol_info->sc.line_entry.column); } diff --git a/lldb/source/Utility/AddressableBits.cpp b/lldb/source/Utility/AddressableBits.cpp index 7f9d7ec6c1349cb52712d710d0f8d3eafb653e8c..4c98addc1f073bf3d13d354c439a7468657b9a4b 100644 --- a/lldb/source/Utility/AddressableBits.cpp +++ b/lldb/source/Utility/AddressableBits.cpp @@ -7,9 +7,10 @@ //===----------------------------------------------------------------------===// #include "lldb/Utility/AddressableBits.h" -#include "lldb/Target/Process.h" #include "lldb/lldb-types.h" +#include <cassert> + using namespace lldb; using namespace lldb_private; @@ -28,11 +29,19 @@ void AddressableBits::SetLowmemAddressableBits( m_low_memory_addr_bits = lowmem_addressing_bits; } +uint32_t AddressableBits::GetLowmemAddressableBits() const { + return m_low_memory_addr_bits; +} + void AddressableBits::SetHighmemAddressableBits( uint32_t highmem_addressing_bits) { m_high_memory_addr_bits = highmem_addressing_bits; } +uint32_t AddressableBits::GetHighmemAddressableBits() const { + return m_high_memory_addr_bits; +} + addr_t AddressableBits::AddressableBitToMask(uint32_t addressable_bits) { assert(addressable_bits <= sizeof(addr_t) * 8); if (addressable_bits == 64) @@ -40,20 +49,3 @@ addr_t AddressableBits::AddressableBitToMask(uint32_t addressable_bits) { else return ~((1ULL << addressable_bits) - 1); } - -void AddressableBits::SetProcessMasks(Process &process) { - if (m_low_memory_addr_bits == 0 && m_high_memory_addr_bits == 0) - return; - - if (m_low_memory_addr_bits != 0) { - addr_t low_addr_mask = AddressableBitToMask(m_low_memory_addr_bits); - process.SetCodeAddressMask(low_addr_mask); - process.SetDataAddressMask(low_addr_mask); - } - - if (m_high_memory_addr_bits != 0) { - addr_t hi_addr_mask = AddressableBitToMask(m_high_memory_addr_bits); - process.SetHighmemCodeAddressMask(hi_addr_mask); - process.SetHighmemDataAddressMask(hi_addr_mask); - } -} diff --git a/lldb/source/Utility/Scalar.cpp b/lldb/source/Utility/Scalar.cpp index 5ad68065bce1b76711ac6a71c04589954c80535f..e94fd459623665b864aa6d491f5efb4850fb65a3 100644 --- a/lldb/source/Utility/Scalar.cpp +++ b/lldb/source/Utility/Scalar.cpp @@ -813,6 +813,48 @@ bool Scalar::ExtractBitfield(uint32_t bit_size, uint32_t bit_offset) { return false; } +llvm::APFloat Scalar::CreateAPFloatFromAPSInt(lldb::BasicType basic_type) { + switch (basic_type) { + case lldb::eBasicTypeFloat: + return llvm::APFloat( + m_integer.isSigned() + ? llvm::APIntOps::RoundSignedAPIntToFloat(m_integer) + : llvm::APIntOps::RoundAPIntToFloat(m_integer)); + case lldb::eBasicTypeDouble: + // No way to get more precision at the moment. + case lldb::eBasicTypeLongDouble: + return llvm::APFloat( + m_integer.isSigned() + ? llvm::APIntOps::RoundSignedAPIntToDouble(m_integer) + : llvm::APIntOps::RoundAPIntToDouble(m_integer)); + default: + const llvm::fltSemantics &sem = APFloat::IEEEsingle(); + return llvm::APFloat::getNaN(sem); + } +} + +llvm::APFloat Scalar::CreateAPFloatFromAPFloat(lldb::BasicType basic_type) { + switch (basic_type) { + case lldb::eBasicTypeFloat: { + bool loses_info; + m_float.convert(llvm::APFloat::IEEEsingle(), + llvm::APFloat::rmNearestTiesToEven, &loses_info); + return m_float; + } + case lldb::eBasicTypeDouble: + // No way to get more precision at the moment. + case lldb::eBasicTypeLongDouble: { + bool loses_info; + m_float.convert(llvm::APFloat::IEEEdouble(), + llvm::APFloat::rmNearestTiesToEven, &loses_info); + return m_float; + } + default: + const llvm::fltSemantics &sem = APFloat::IEEEsingle(); + return llvm::APFloat::getNaN(sem); + } +} + bool lldb_private::operator==(Scalar lhs, Scalar rhs) { // If either entry is void then we can just compare the types if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void) diff --git a/lldb/test/API/benchmarks/expression/TestExpressionCmd.py b/lldb/test/API/benchmarks/expression/TestExpressionCmd.py index 9b512305d626bd3a450084c7c7b1640a39cd909f..8261b1b25da9f2fcc76a47bcb64d7e759696237b 100644 --- a/lldb/test/API/benchmarks/expression/TestExpressionCmd.py +++ b/lldb/test/API/benchmarks/expression/TestExpressionCmd.py @@ -17,10 +17,7 @@ class ExpressionEvaluationCase(BenchBase): self.count = 25 @benchmarks_test - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows", - ) + @add_test_categories(["pexpect"]) def test_expr_cmd(self): """Test lldb's expression commands and collect statistics.""" self.build() diff --git a/lldb/test/API/benchmarks/expression/TestRepeatedExprs.py b/lldb/test/API/benchmarks/expression/TestRepeatedExprs.py index 104e69b384237c3622642ddb91184900a58b4afc..acc6b74c17b7e60ee1374e2ec9a657db26cb457c 100644 --- a/lldb/test/API/benchmarks/expression/TestRepeatedExprs.py +++ b/lldb/test/API/benchmarks/expression/TestRepeatedExprs.py @@ -19,10 +19,7 @@ class RepeatedExprsCase(BenchBase): self.count = 100 @benchmarks_test - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows", - ) + @add_test_categories(["pexpect"]) def test_compare_lldb_to_gdb(self): """Test repeated expressions with lldb vs. gdb.""" self.build() diff --git a/lldb/test/API/benchmarks/frame_variable/TestFrameVariableResponse.py b/lldb/test/API/benchmarks/frame_variable/TestFrameVariableResponse.py index f3989fc0ff4838bc42109d786410c95c1ae486dd..e364fb8ce77821bff8f6f99bf347bb0b4e565a07 100644 --- a/lldb/test/API/benchmarks/frame_variable/TestFrameVariableResponse.py +++ b/lldb/test/API/benchmarks/frame_variable/TestFrameVariableResponse.py @@ -17,10 +17,7 @@ class FrameVariableResponseBench(BenchBase): @benchmarks_test @no_debug_info_test - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows", - ) + @add_test_categories(["pexpect"]) def test_startup_delay(self): """Test response time for the 'frame variable' command.""" print() diff --git a/lldb/test/API/benchmarks/startup/TestStartupDelays.py b/lldb/test/API/benchmarks/startup/TestStartupDelays.py index f31a10507ed7efc1a1e82506e673be54f67a4047..faec21e95e5d206bb91ec9c678df2e367c67268c 100644 --- a/lldb/test/API/benchmarks/startup/TestStartupDelays.py +++ b/lldb/test/API/benchmarks/startup/TestStartupDelays.py @@ -22,10 +22,7 @@ class StartupDelaysBench(BenchBase): @benchmarks_test @no_debug_info_test - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows", - ) + @add_test_categories(["pexpect"]) def test_startup_delay(self): """Test start up delays creating a target, setting a breakpoint, and run to breakpoint stop.""" print() diff --git a/lldb/test/API/benchmarks/stepping/TestSteppingSpeed.py b/lldb/test/API/benchmarks/stepping/TestSteppingSpeed.py index a3264e3f3253bff25b1fe93ca3f8279cf058a3ea..d0f9b0d61d17ef1ec944dbbc43fe070c2fb726be 100644 --- a/lldb/test/API/benchmarks/stepping/TestSteppingSpeed.py +++ b/lldb/test/API/benchmarks/stepping/TestSteppingSpeed.py @@ -22,10 +22,7 @@ class SteppingSpeedBench(BenchBase): @benchmarks_test @no_debug_info_test - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows", - ) + @add_test_categories(["pexpect"]) def test_run_lldb_steppings(self): """Test lldb steppings on a large executable.""" print() diff --git a/lldb/test/API/benchmarks/turnaround/TestCompileRunToBreakpointTurnaround.py b/lldb/test/API/benchmarks/turnaround/TestCompileRunToBreakpointTurnaround.py index 98a2ec9ebf231d7686a8ed082698dc4b87a8402b..91527cd114534c7576b4c6d1cce0f6636cde5ff4 100644 --- a/lldb/test/API/benchmarks/turnaround/TestCompileRunToBreakpointTurnaround.py +++ b/lldb/test/API/benchmarks/turnaround/TestCompileRunToBreakpointTurnaround.py @@ -21,10 +21,7 @@ class CompileRunToBreakpointBench(BenchBase): @benchmarks_test @no_debug_info_test - @expectedFailureAll( - oslist=["windows"], - bugnumber="llvm.org/pr22274: need a pexpect replacement for windows", - ) + @add_test_categories(["pexpect"]) def test_run_lldb_then_gdb(self): """Benchmark turnaround time with lldb vs. gdb.""" print() diff --git a/lldb/test/API/commands/dwim-print/TestDWIMPrint.py b/lldb/test/API/commands/dwim-print/TestDWIMPrint.py index 040632096c70e79be3ce1dfea74684fc9ce478c0..c650b1e3533e083c7e8e0f6881b195537819070a 100644 --- a/lldb/test/API/commands/dwim-print/TestDWIMPrint.py +++ b/lldb/test/API/commands/dwim-print/TestDWIMPrint.py @@ -146,3 +146,15 @@ class TestCase(TestBase): self, "// break here", lldb.SBFileSpec("main.c") ) self.expect("dwim-print (void)15", matching=False, patterns=["(?i)error"]) + + def test_preserves_persistent_variables(self): + """Test dwim-print does not delete persistent variables.""" + self.build() + lldbutil.run_to_source_breakpoint( + self, "// break here", lldb.SBFileSpec("main.c") + ) + self.expect("dwim-print int $i = 15") + # Run the same expression twice and verify success. This ensures the + # first command does not delete the persistent variable. + for _ in range(2): + self.expect("dwim-print $i", startstr="(int) 15") diff --git a/lldb/test/API/commands/target/modules/lookup/Makefile b/lldb/test/API/commands/target/modules/lookup/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..695335e068c0c92372578f62a4750f7cabad8468 --- /dev/null +++ b/lldb/test/API/commands/target/modules/lookup/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +CFLAGS_EXTRAS := -std=c99 + +include Makefile.rules diff --git a/lldb/test/API/commands/target/modules/lookup/TestImageLookupPCExpression.py b/lldb/test/API/commands/target/modules/lookup/TestImageLookupPCExpression.py new file mode 100644 index 0000000000000000000000000000000000000000..9872e057cbbfbaa7b1a3889e66f30e80645abe1d --- /dev/null +++ b/lldb/test/API/commands/target/modules/lookup/TestImageLookupPCExpression.py @@ -0,0 +1,27 @@ +""" +Make sure that "target modules lookup -va $pc" works +""" + + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + + +class TestImageLookupPCInC(TestBase): + def test_sample_rename_this(self): + """There can be many tests in a test case - describe this test here.""" + self.build() + self.main_source_file = lldb.SBFileSpec("main.c") + self.sample_test() + + def sample_test(self): + """Make sure the address expression resolves to the right function""" + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, "Set a breakpoint here", self.main_source_file + ) + + self.expect("target modules lookup -va $pc", substrs=["doSomething"]) + self.expect("target modules lookup -va $pc+4", substrs=["doSomething"]) + diff --git a/lldb/test/API/commands/target/modules/lookup/main.c b/lldb/test/API/commands/target/modules/lookup/main.c new file mode 100644 index 0000000000000000000000000000000000000000..afe962f30916c9e576b38252dff8b7f6918d0a62 --- /dev/null +++ b/lldb/test/API/commands/target/modules/lookup/main.c @@ -0,0 +1,15 @@ +#include <stdio.h> + +void +doSomething() +{ + printf ("Set a breakpoint here.\n"); + printf ("Need a bit more code.\n"); +} + +int +main() +{ + doSomething(); + return 0; +} diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py b/lldb/test/API/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py index 8930bea619bb6e9ce4a53780950dbf26c7d1c67b..d87e6275f7b51eee5854bfe4cbb1f14263bd50b4 100644 --- a/lldb/test/API/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py +++ b/lldb/test/API/functionalities/breakpoint/breakpoint_locations/TestBreakpointLocations.py @@ -293,6 +293,12 @@ class BreakpointLocationsTestCase(TestBase): startstr="3 breakpoints enabled.", ) + # The 'breakpoint enable 1.' command should not crash. + self.expect( + "breakpoint enable 1.", + startstr="0 breakpoints enabled.", + ) + # The 'breakpoint disable 1.1' command should disable 1 location. self.expect( "breakpoint disable 1.1", diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_options/TestBreakpointOptions.py b/lldb/test/API/functionalities/breakpoint/breakpoint_options/TestBreakpointOptions.py index 5179ffe730b9a0dd5cbf8404f8111c01b95d1756..d262b627195bc85cbc8e2e7cabef83042ae25e65 100644 --- a/lldb/test/API/functionalities/breakpoint/breakpoint_options/TestBreakpointOptions.py +++ b/lldb/test/API/functionalities/breakpoint/breakpoint_options/TestBreakpointOptions.py @@ -95,8 +95,10 @@ class BreakpointOptionsTestCase(TestBase): self.expect( "breakpoint list -v", "Verbose breakpoint list contains mangled names", + # The demangled function name is system-dependent, e.g. + # 'int ns::func(void)' on Windows and 'ns::func()' on Linux. substrs=[ - "function = ns::func", + f"function = {function.GetName()}", f"mangled function = {function.GetMangledName()}", ], ) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/TestDataFormatterLibcxxValarray.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/TestDataFormatterLibcxxValarray.py index 7b54b3485d04d4b3c6ca2c655ee4b7083f701f48..b59b770ed6790d2e834093918da015e0bee46747 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/TestDataFormatterLibcxxValarray.py +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/TestDataFormatterLibcxxValarray.py @@ -18,6 +18,10 @@ class LibcxxChronoDataFormatterTestCase(TestBase): self, "break here", lldb.SBFileSpec("main.cpp", False) ) + # + # std::valarray + # + self.expect( "frame variable va_int", substrs=[ @@ -76,3 +80,30 @@ class LibcxxChronoDataFormatterTestCase(TestBase): error=True, substrs=['array index 4 is not valid for "(valarray<double>) va_double"'], ) + + # + # std::slice_array + # + + self.expect( + "frame variable sa", + substrs=[ + "sa = stride=2 size=4", + "[0] = 1", + "[1] = 3", + "[2] = 5", + "[3] = 7", + "}", + ], + ) + + # check access-by-index + self.expect("frame variable sa[0]", substrs=["1"]) + self.expect("frame variable sa[1]", substrs=["3"]) + self.expect("frame variable sa[2]", substrs=["5"]) + self.expect("frame variable sa[3]", substrs=["7"]) + self.expect( + "frame variable sa[4]", + error=True, + substrs=['array index 4 is not valid for "(slice_array<int>) sa"'], + ) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/main.cpp index f32921e16fa10e34f24a1324e9c2eccfed866bf5..1481d8b4032927618d8d31cccd487e920af2195c 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/valarray/main.cpp @@ -13,5 +13,8 @@ int main() { std::valarray<double> va_double({1.0, 0.5, 0.25, 0.125}); + std::valarray<int> va({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + std::slice_array<int> sa = va[std::slice(1, 4, 2)]; + std::cout << "break here\n"; } diff --git a/lldb/test/API/functionalities/fork/concurrent_vfork/TestConcurrentVFork.py b/lldb/test/API/functionalities/fork/concurrent_vfork/TestConcurrentVFork.py index 2dcbb728549fb4c15558f20585dd185882b7ad5b..1790bd497f4e6be088110a1ca64cb6d92add94ac 100644 --- a/lldb/test/API/functionalities/fork/concurrent_vfork/TestConcurrentVFork.py +++ b/lldb/test/API/functionalities/fork/concurrent_vfork/TestConcurrentVFork.py @@ -48,6 +48,8 @@ class TestConcurrentVFork(TestBase): self.expect("continue", patterns=[r"exited with status = 1[0-4]"]) @skipUnlessPlatform(["linux"]) + # See https://github.com/llvm/llvm-project/issues/85084. + @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_parent_vfork_no_exec(self): """ Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-parent. @@ -56,6 +58,8 @@ class TestConcurrentVFork(TestBase): self.follow_parent_helper(use_fork=False, call_exec=False) @skipUnlessPlatform(["linux"]) + # See https://github.com/llvm/llvm-project/issues/85084. + @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_parent_fork_no_exec(self): """ Make sure that debugging concurrent fork() from multiple threads won't crash lldb during follow-parent. @@ -64,6 +68,8 @@ class TestConcurrentVFork(TestBase): self.follow_parent_helper(use_fork=True, call_exec=False) @skipUnlessPlatform(["linux"]) + # See https://github.com/llvm/llvm-project/issues/85084. + @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_parent_vfork_call_exec(self): """ Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-parent. @@ -72,6 +78,8 @@ class TestConcurrentVFork(TestBase): self.follow_parent_helper(use_fork=False, call_exec=True) @skipUnlessPlatform(["linux"]) + # See https://github.com/llvm/llvm-project/issues/85084. + @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_parent_fork_call_exec(self): """ Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-parent. @@ -80,6 +88,8 @@ class TestConcurrentVFork(TestBase): self.follow_parent_helper(use_fork=True, call_exec=True) @skipUnlessPlatform(["linux"]) + # See https://github.com/llvm/llvm-project/issues/85084. + @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_child_vfork_no_exec(self): """ Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-child. @@ -88,6 +98,8 @@ class TestConcurrentVFork(TestBase): self.follow_child_helper(use_fork=False, call_exec=False) @skipUnlessPlatform(["linux"]) + # See https://github.com/llvm/llvm-project/issues/85084. + @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_child_fork_no_exec(self): """ Make sure that debugging concurrent fork() from multiple threads won't crash lldb during follow-child. @@ -96,6 +108,8 @@ class TestConcurrentVFork(TestBase): self.follow_child_helper(use_fork=True, call_exec=False) @skipUnlessPlatform(["linux"]) + # See https://github.com/llvm/llvm-project/issues/85084. + @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_child_vfork_call_exec(self): """ Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-child. @@ -104,6 +118,8 @@ class TestConcurrentVFork(TestBase): self.follow_child_helper(use_fork=False, call_exec=True) @skipUnlessPlatform(["linux"]) + # See https://github.com/llvm/llvm-project/issues/85084. + @skipIf(oslist=["linux"], archs=["aarch64", "arm"]) def test_follow_child_fork_call_exec(self): """ Make sure that debugging concurrent fork() from multiple threads won't crash lldb during follow-child. diff --git a/lldb/test/API/functionalities/target_var/TestTargetVar.py b/lldb/test/API/functionalities/target_var/TestTargetVar.py index a0f3663f0365102ac4bf32b8d56521ca575b9c64..54b7b77b6773ce4ab87d18dfa74df2bd5c804e3e 100644 --- a/lldb/test/API/functionalities/target_var/TestTargetVar.py +++ b/lldb/test/API/functionalities/target_var/TestTargetVar.py @@ -15,6 +15,16 @@ class targetCommandTestCase(TestBase): def testTargetVarExpr(self): self.build() lldbutil.run_to_name_breakpoint(self, "main") + self.expect( + "help target variable", + substrs=[ + "--no-args", + "--no-recognized-args", + "--no-locals", + "--show-globals", + ], + matching=False, + ) self.expect("target variable i", substrs=["i", "42"]) self.expect( "target variable var", patterns=["\(incomplete \*\) var = 0[xX](0)*dead"] diff --git a/lldb/test/API/functionalities/type_find_first/Makefile b/lldb/test/API/functionalities/type_find_first/Makefile index 3d0b98f13f3d7be79aa6f4f5fd40d1697bb1e1a1..e027553c7a6b09ec09a4533780fc94d9d46d2d6d 100644 --- a/lldb/test/API/functionalities/type_find_first/Makefile +++ b/lldb/test/API/functionalities/type_find_first/Makefile @@ -1,2 +1,2 @@ -CXX_SOURCES := main.cpp +CXX_SOURCES := main.cpp other.cpp include Makefile.rules diff --git a/lldb/test/API/functionalities/type_find_first/TestFindFirstType.py b/lldb/test/API/functionalities/type_find_first/TestFindFirstType.py index 6347a35e72ea3f78404ed9637bc5c8cf9152b946..b1c5659a324a4c8bf962d80e5b99398810f97f06 100644 --- a/lldb/test/API/functionalities/type_find_first/TestFindFirstType.py +++ b/lldb/test/API/functionalities/type_find_first/TestFindFirstType.py @@ -8,8 +8,6 @@ from lldbsuite.test import lldbutil class TypeFindFirstTestCase(TestBase): - NO_DEBUG_INFO_TESTCASE = True - def test_find_first_type(self): """ Test SBTarget::FindFirstType() and SBModule::FindFirstType() APIs. @@ -19,19 +17,22 @@ class TypeFindFirstTestCase(TestBase): basename, FindFirstType() could end up failing depending on which type was found first in the debug info indexes. This test will ensure this doesn't regress in the future. + + The test also looks for a type defined in a different compilation unit + to verify that SymbolFileDWARFDebugMap searches each symbol file in a + module. """ self.build() target = self.createTestTarget() - # Test the SBTarget APIs for FindFirstType - integer_type = target.FindFirstType("Integer::Point") - self.assertTrue(integer_type.IsValid()) - float_type = target.FindFirstType("Float::Point") - self.assertTrue(float_type.IsValid()) - - # Test the SBModule APIs for FindFirstType exe_module = target.GetModuleAtIndex(0) self.assertTrue(exe_module.IsValid()) - integer_type = exe_module.FindFirstType("Integer::Point") - self.assertTrue(integer_type.IsValid()) - float_type = exe_module.FindFirstType("Float::Point") - self.assertTrue(float_type.IsValid()) + # Test the SBTarget and SBModule APIs for FindFirstType + for api in [target, exe_module]: + integer_type = api.FindFirstType("Integer::Point") + self.assertTrue(integer_type.IsValid()) + float_type = api.FindFirstType("Float::Point") + self.assertTrue(float_type.IsValid()) + external_type = api.FindFirstType("OtherCompilationUnit::Type") + self.assertTrue(external_type.IsValid()) + nonexistent_type = api.FindFirstType("NonexistentType") + self.assertFalse(nonexistent_type.IsValid()) diff --git a/lldb/test/API/functionalities/type_find_first/main.cpp b/lldb/test/API/functionalities/type_find_first/main.cpp index f4e467286004d6fe46324c38ce7b8cd828266173..bbb060872a1e9a5fda2fc363f6843356d51772ff 100644 --- a/lldb/test/API/functionalities/type_find_first/main.cpp +++ b/lldb/test/API/functionalities/type_find_first/main.cpp @@ -10,8 +10,13 @@ struct Point { }; } // namespace Float +namespace OtherCompilationUnit { +void Function(); +} // namespace OtherCompilationUnit + int main(int argc, char const *argv[]) { Integer::Point ip = {2, 3}; Float::Point fp = {2.0, 3.0}; + OtherCompilationUnit::Function(); return 0; } diff --git a/lldb/test/API/functionalities/type_find_first/other.cpp b/lldb/test/API/functionalities/type_find_first/other.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b91edcd8e1d76de4d94b7e1b6a36521c860c677c --- /dev/null +++ b/lldb/test/API/functionalities/type_find_first/other.cpp @@ -0,0 +1,4 @@ +namespace OtherCompilationUnit { +struct Type {}; +void Function() { Type typeIsActuallyUsed; } +} // namespace OtherCompilationUnit \ No newline at end of file diff --git a/lldb/test/API/macosx/indirect_symbol/TestIndirectSymbols.py b/lldb/test/API/macosx/indirect_symbol/TestIndirectSymbols.py index fbe6db9f892d55517183cff4da9dd45c297bbb53..c4bbedc9289130369e0a1c54bc5920cf1e157927 100644 --- a/lldb/test/API/macosx/indirect_symbol/TestIndirectSymbols.py +++ b/lldb/test/API/macosx/indirect_symbol/TestIndirectSymbols.py @@ -16,6 +16,7 @@ class TestIndirectFunctions(TestBase): @skipUnlessDarwin @add_test_categories(["pyapi"]) + @skipIf(bugnumber="rdar://120796553") def test_with_python_api(self): """Test stepping and setting breakpoints in indirect and re-exported symbols.""" self.build() diff --git a/lldb/test/API/macosx/tbi-honored/Makefile b/lldb/test/API/macosx/tbi-honored/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..10495940055b63d2b69fd0ee465e69dad1889d2f --- /dev/null +++ b/lldb/test/API/macosx/tbi-honored/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/macosx/tbi-honored/TestTBIHonored.py b/lldb/test/API/macosx/tbi-honored/TestTBIHonored.py new file mode 100644 index 0000000000000000000000000000000000000000..a5c0abd70e5a90f3e33640c473c9528b2a8fd1e7 --- /dev/null +++ b/lldb/test/API/macosx/tbi-honored/TestTBIHonored.py @@ -0,0 +1,57 @@ +"""Test that lldb on Darwin ignores metadata in the top byte of addresses, both corefile and live.""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestTBIHonored(TestBase): + NO_DEBUG_INFO_TESTCASE = True + + def do_variable_access_tests(self, frame): + self.assertEqual( + frame.variables["pb"][0] + .GetChildMemberWithName("p") + .Dereference() + .GetValueAsUnsigned(), + 15, + ) + addr = frame.variables["pb"][0].GetChildMemberWithName("p").GetValueAsUnsigned() + # Confirm that there is metadata in the top byte of our pointer + self.assertEqual((addr >> 56) & 0xFF, 0xFE) + self.expect("expr -- *pb.p", substrs=["15"]) + self.expect("frame variable *pb.p", substrs=["15"]) + self.expect("expr -- *(int*)0x%x" % addr, substrs=["15"]) + + # This test is valid on AArch64 systems with TBI mode enabled, + # and an address mask that clears the top byte before reading + # from memory. + @skipUnlessDarwin + @skipIf(archs=no_match(["arm64", "arm64e"])) + @skipIfRemote + def test(self): + corefile = self.getBuildArtifact("process.core") + self.build() + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, "// break here", lldb.SBFileSpec("main.c") + ) + + # Test that we can dereference a pointer with TBI data + # in a live process. + self.do_variable_access_tests(thread.GetFrameAtIndex(0)) + + # Create a corefile, delete this process + self.runCmd("process save-core -s stack " + corefile) + process.Destroy() + self.dbg.DeleteTarget(target) + + # Now load the corefile + target = self.dbg.CreateTarget("") + process = target.LoadCore(corefile) + thread = process.GetSelectedThread() + self.assertTrue(process.GetSelectedThread().IsValid()) + + # Test that we can dereference a pointer with TBI data + # in a corefile process. + self.do_variable_access_tests(thread.GetFrameAtIndex(0)) diff --git a/lldb/test/API/macosx/tbi-honored/main.c b/lldb/test/API/macosx/tbi-honored/main.c new file mode 100644 index 0000000000000000000000000000000000000000..3d7ad0b04cd6642e7ad34a0e55a45f36287cc4a8 --- /dev/null +++ b/lldb/test/API/macosx/tbi-honored/main.c @@ -0,0 +1,13 @@ +#include <stdint.h> +#include <stdio.h> +union ptrbytes { + int *p; + uint8_t bytes[8]; +}; +int main() { + int c = 15; + union ptrbytes pb; + pb.p = &c; + pb.bytes[7] = 0xfe; + printf("%d\n", *pb.p); // break here +} diff --git a/lldb/test/API/python_api/run_locker/TestRunLocker.py b/lldb/test/API/python_api/run_locker/TestRunLocker.py index 10832840ac0955655f5e58db11a38cc7f82160a1..4e0dd26bff70d2430ff5285a9f74e137926d5012 100644 --- a/lldb/test/API/python_api/run_locker/TestRunLocker.py +++ b/lldb/test/API/python_api/run_locker/TestRunLocker.py @@ -15,6 +15,8 @@ class TestRunLocker(TestBase): NO_DEBUG_INFO_TESTCASE = True @expectedFailureAll(oslist=["windows"]) + # Is flaky on Linux AArch64 buildbot. + @skipIf(oslist=["linux"], archs=["aarch64"]) def test_run_locker(self): """Test that the run locker is set correctly when we launch""" self.build() diff --git a/lldb/test/API/source-manager/TestSourceManager.py b/lldb/test/API/source-manager/TestSourceManager.py index eab8924d1081468a14e382b5b9084f8de6020931..ad7c85aac70eaf4d6755fb269cd8af0226345f3a 100644 --- a/lldb/test/API/source-manager/TestSourceManager.py +++ b/lldb/test/API/source-manager/TestSourceManager.py @@ -323,13 +323,12 @@ class SourceManagerTestCase(TestBase): ) self.expect( - "run", - RUN_SUCCEEDED, + "process status", substrs=[ "stop reason = breakpoint", - "%s:%d" % (src_file, 0), - "Note: this address is compiler-generated code in " "function", - "that has no source code associated " "with it.", + f"{src_file}:0", + "Note: this address is compiler-generated code in function", + "that has no source code associated with it.", ], ) diff --git a/lldb/test/API/terminal/TestSTTYBeforeAndAfter.py b/lldb/test/API/terminal/TestSTTYBeforeAndAfter.py index e5663c50c736e6532a9f8f718ac2761ff7f92eba..21aca5fc85d5f11574a069888a7445e3ba6e7fd3 100644 --- a/lldb/test/API/terminal/TestSTTYBeforeAndAfter.py +++ b/lldb/test/API/terminal/TestSTTYBeforeAndAfter.py @@ -19,7 +19,7 @@ class TestSTTYBeforeAndAfter(TestBase): cls.RemoveTempFile("child_send2.txt") cls.RemoveTempFile("child_read2.txt") - @skipIfWindows # llvm.org/pr22274: need a pexpect replacement for windows + @add_test_categories(["pexpect"]) @no_debug_info_test def test_stty_dash_a_before_and_afetr_invoking_lldb_command(self): """Test that 'stty -a' displays the same output before and after running the lldb command.""" diff --git a/lldb/test/CMakeLists.txt b/lldb/test/CMakeLists.txt index 0ef2eb1c42ce0641d2e8da7362e44f5a012d83e7..b6ec5bc4d819e3a3e2c9519243cf74ab6b155847 100644 --- a/lldb/test/CMakeLists.txt +++ b/lldb/test/CMakeLists.txt @@ -31,23 +31,6 @@ if(LLDB_ENFORCE_STRICT_TEST_REQUIREMENTS) endforeach() endif() -# The "pexpect" package should come from the system environment, not from the -# LLDB tree. However, we delay the deletion of it from the tree in case -# users/buildbots don't have the package yet and need some time to install it. -# Windows is configured to skip all pexpect tests, and guards all -# "import pexpect" calls, so we do not need pexpect installed there. -if (NOT LLDB_TEST_USE_VENDOR_PACKAGES AND NOT WIN32) - unset(PY_pexpect_FOUND CACHE) - lldb_find_python_module(pexpect) - if (NOT PY_pexpect_FOUND) - message(FATAL_ERROR - "Python module 'pexpect' not found. Please install it via pip or via " - "your operating system's package manager. For a temporary workaround, " - "use a version from the LLDB tree with " - "`LLDB_TEST_USE_VENDOR_PACKAGES=ON`") - endif() -endif() - if(LLDB_BUILT_STANDALONE) # In order to run check-lldb-* we need the correct map_config directives in # llvm-lit. Because this is a standalone build, LLVM doesn't know about LLDB, diff --git a/lldb/unittests/Core/ProgressReportTest.cpp b/lldb/unittests/Core/ProgressReportTest.cpp index 1f993180fd839277035618201260c443f4061760..f0d253be9bf621583d39a9646e1aa3b1947022b5 100644 --- a/lldb/unittests/Core/ProgressReportTest.cpp +++ b/lldb/unittests/Core/ProgressReportTest.cpp @@ -22,7 +22,7 @@ using namespace lldb; using namespace lldb_private; -static std::chrono::milliseconds TIMEOUT(100); +static std::chrono::milliseconds TIMEOUT(500); class ProgressReportTest : public ::testing::Test { public: @@ -56,7 +56,8 @@ protected: DebuggerSP m_debugger_sp; ListenerSP m_listener_sp; - SubsystemRAII<FileSystem, HostInfo, PlatformMacOSX> subsystems; + SubsystemRAII<FileSystem, HostInfo, PlatformMacOSX, ProgressManager> + subsystems; }; TEST_F(ProgressReportTest, TestReportCreation) { @@ -210,3 +211,37 @@ TEST_F(ProgressReportTest, TestOverlappingEvents) { // initial report. EXPECT_EQ(data->GetID(), expected_progress_id); } + +TEST_F(ProgressReportTest, TestProgressManagerDisjointReports) { + ListenerSP listener_sp = + CreateListenerFor(Debugger::eBroadcastBitProgressCategory); + EventSP event_sp; + const ProgressEventData *data; + uint64_t expected_progress_id; + + { Progress progress("Coalesced report 1", "Starting report 1"); } + { Progress progress("Coalesced report 1", "Starting report 2"); } + { Progress progress("Coalesced report 1", "Starting report 3"); } + + ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT)); + data = ProgressEventData::GetEventDataFromEvent(event_sp.get()); + expected_progress_id = data->GetID(); + + EXPECT_EQ(data->GetDetails(), ""); + EXPECT_FALSE(data->IsFinite()); + EXPECT_FALSE(data->GetCompleted()); + EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal); + EXPECT_EQ(data->GetMessage(), "Coalesced report 1"); + + ASSERT_TRUE(listener_sp->GetEvent(event_sp, TIMEOUT)); + data = ProgressEventData::GetEventDataFromEvent(event_sp.get()); + + EXPECT_EQ(data->GetID(), expected_progress_id); + EXPECT_EQ(data->GetDetails(), ""); + EXPECT_FALSE(data->IsFinite()); + EXPECT_TRUE(data->GetCompleted()); + EXPECT_EQ(data->GetTotal(), Progress::kNonDeterministicTotal); + EXPECT_EQ(data->GetMessage(), "Coalesced report 1"); + + ASSERT_FALSE(listener_sp->GetEvent(event_sp, TIMEOUT)); +} diff --git a/lldb/unittests/Host/AlarmTest.cpp b/lldb/unittests/Host/AlarmTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9f6ad189dee970bbc0fd26a3e9e752b6205dfc7c --- /dev/null +++ b/lldb/unittests/Host/AlarmTest.cpp @@ -0,0 +1,159 @@ +//===-- AlarmTest.cpp -----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Alarm.h" +#include "gtest/gtest.h" + +#include <chrono> +#include <thread> + +using namespace lldb_private; +using namespace std::chrono_literals; + +// Increase the timeout tenfold when running under ASan as it can have about the +// same performance overhead. +#if __has_feature(address_sanitizer) +static constexpr auto TEST_TIMEOUT = 10000ms; +#else +static constexpr auto TEST_TIMEOUT = 1000ms; +#endif + +// The time between scheduling a callback and it getting executed. This should +// NOT be increased under ASan. +static constexpr auto ALARM_TIMEOUT = 500ms; + +// If there are any pending callbacks, make sure they run before the Alarm +// object is destroyed. +static constexpr bool RUN_CALLBACKS_ON_EXIT = true; + +TEST(AlarmTest, Create) { + std::mutex m; + + std::vector<Alarm::TimePoint> callbacks_actual; + std::vector<Alarm::TimePoint> callbacks_expected; + + Alarm alarm(ALARM_TIMEOUT, RUN_CALLBACKS_ON_EXIT); + + // Create 5 alarms some time apart. + for (size_t i = 0; i < 5; ++i) { + callbacks_actual.emplace_back(); + callbacks_expected.emplace_back(std::chrono::system_clock::now() + + ALARM_TIMEOUT); + + alarm.Create([&callbacks_actual, &m, i]() { + std::lock_guard<std::mutex> guard(m); + callbacks_actual[i] = std::chrono::system_clock::now(); + }); + + std::this_thread::sleep_for(ALARM_TIMEOUT / 5); + } + + // Leave plenty of time for all the alarms to fire. + std::this_thread::sleep_for(TEST_TIMEOUT); + + // Make sure all the alarms fired around the expected time. + for (size_t i = 0; i < 5; ++i) + EXPECT_GE(callbacks_actual[i], callbacks_expected[i]); +} + +TEST(AlarmTest, Exit) { + std::mutex m; + + std::vector<Alarm::Handle> handles; + std::vector<bool> callbacks; + + { + Alarm alarm(ALARM_TIMEOUT, RUN_CALLBACKS_ON_EXIT); + + // Create 5 alarms. + for (size_t i = 0; i < 5; ++i) { + callbacks.emplace_back(false); + + handles.push_back(alarm.Create([&callbacks, &m, i]() { + std::lock_guard<std::mutex> guard(m); + callbacks[i] = true; + })); + } + + // Let the alarm go out of scope before any alarm had a chance to fire. + } + + // Make sure none of the alarms fired. + for (bool callback : callbacks) + EXPECT_TRUE(callback); +} + +TEST(AlarmTest, Cancel) { + std::mutex m; + + std::vector<Alarm::Handle> handles; + std::vector<bool> callbacks; + + Alarm alarm(ALARM_TIMEOUT, RUN_CALLBACKS_ON_EXIT); + + // Create 5 alarms. + for (size_t i = 0; i < 5; ++i) { + callbacks.emplace_back(false); + + handles.push_back(alarm.Create([&callbacks, &m, i]() { + std::lock_guard<std::mutex> guard(m); + callbacks[i] = true; + })); + } + + // Make sure we can cancel the first 4 alarms. + for (size_t i = 0; i < 4; ++i) + EXPECT_TRUE(alarm.Cancel(handles[i])); + + // Leave plenty of time for all the alarms to fire. + std::this_thread::sleep_for(TEST_TIMEOUT); + + // Make sure none of the first 4 alarms fired. + for (size_t i = 0; i < 4; ++i) + EXPECT_FALSE(callbacks[i]); + + // Make sure the fifth alarm still fired. + EXPECT_TRUE(callbacks[4]); +} + +TEST(AlarmTest, Restart) { + std::mutex m; + + std::vector<Alarm::Handle> handles; + std::vector<Alarm::TimePoint> callbacks_actual; + std::vector<Alarm::TimePoint> callbacks_expected; + + Alarm alarm(ALARM_TIMEOUT, RUN_CALLBACKS_ON_EXIT); + + // Create 5 alarms some time apart. + for (size_t i = 0; i < 5; ++i) { + callbacks_actual.emplace_back(); + callbacks_expected.emplace_back(std::chrono::system_clock::now() + + ALARM_TIMEOUT); + + handles.push_back(alarm.Create([&callbacks_actual, &m, i]() { + std::lock_guard<std::mutex> guard(m); + callbacks_actual[i] = std::chrono::system_clock::now(); + })); + + std::this_thread::sleep_for(ALARM_TIMEOUT / 5); + } + + // Update the last 2 alarms. + for (size_t i = 3; i < 5; ++i) { + callbacks_expected[i] = std::chrono::system_clock::now() + ALARM_TIMEOUT; + EXPECT_TRUE(alarm.Restart(handles[i])); + } + + // Leave plenty of time for all the alarms to fire. + std::this_thread::sleep_for(TEST_TIMEOUT); + + // Make sure all the alarms around the expected time. + for (size_t i = 0; i < 5; ++i) + EXPECT_GE(callbacks_actual[i], callbacks_expected[i]); +} diff --git a/lldb/unittests/Host/CMakeLists.txt b/lldb/unittests/Host/CMakeLists.txt index c959478970d184a80bdd718a406e4e43c9bba7b1..7c09932b39c2ad165461b70f1e0b694bc18e2fae 100644 --- a/lldb/unittests/Host/CMakeLists.txt +++ b/lldb/unittests/Host/CMakeLists.txt @@ -1,4 +1,5 @@ set (FILES + AlarmTest.cpp ConnectionFileDescriptorTest.cpp FileActionTest.cpp FileSystemTest.cpp diff --git a/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp b/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp index f237dd63ab1cce464dd980887cd1e0c74c7949a2..4379ffac9d744e6300ef6ef4923d2fc93c36137b 100644 --- a/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp +++ b/lldb/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp @@ -102,7 +102,7 @@ protected: EXPECT_EQ(line, entry.line); EXPECT_EQ(address, entry.range.GetBaseAddress()); - EXPECT_TRUE(FileSpecMatchesAsBaseOrFull(spec, entry.file)); + EXPECT_TRUE(FileSpecMatchesAsBaseOrFull(spec, entry.GetFile())); } bool ContainsCompileUnit(const SymbolContextList &sc_list, diff --git a/lldb/unittests/Utility/ScalarTest.cpp b/lldb/unittests/Utility/ScalarTest.cpp index 29a4bcd356f113565d9d571d535f5647fea86b6d..8d957d16593ee71d45b9a2e7e081767f1341bcef 100644 --- a/lldb/unittests/Utility/ScalarTest.cpp +++ b/lldb/unittests/Utility/ScalarTest.cpp @@ -402,3 +402,61 @@ TEST(ScalarTest, TruncOrExtendTo) { S.TruncOrExtendTo(16, false); EXPECT_EQ(S.UInt128(APInt()), APInt(16, 0xffffu)); } + +TEST(ScalarTest, APFloatConstructor) { + llvm::APFloat my_single(llvm::APFloatBase::IEEEsingle(), "3.14159"); + llvm::APFloat my_double(llvm::APFloatBase::IEEEdouble(), "3.14159"); + Scalar S(my_single); + Scalar D(my_double); + + EXPECT_EQ(S.GetType(), Scalar::e_float); + EXPECT_EQ(D.GetType(), Scalar::e_float); + ASSERT_TRUE(S != D); +} + +TEST(ScalarTest, CreateAPFloats) { + llvm::APFloat ap_float(llvm::APFloatBase::IEEEsingle(), "3.14159"); + llvm::APFloat ap_nan = llvm::APFloat::getNaN(llvm::APFloat::IEEEsingle()); + llvm::APSInt int1("12"); + llvm::APSInt int2("-4"); + Scalar I1(int1); + Scalar I2(int2); + Scalar F(ap_float); + + llvm::APFloat out1_float = I1.CreateAPFloatFromAPSInt(lldb::eBasicTypeFloat); + llvm::APFloat out1_double = + I1.CreateAPFloatFromAPSInt(lldb::eBasicTypeDouble); + llvm::APFloat out1_longdouble = + I1.CreateAPFloatFromAPSInt(lldb::eBasicTypeLongDouble); + llvm::APFloat out1_nan = + I1.CreateAPFloatFromAPSInt(lldb::eBasicTypeFloatComplex); + EXPECT_TRUE(!out1_float.isNegative()); + EXPECT_TRUE(!out1_double.isNegative()); + EXPECT_TRUE(out1_double.bitwiseIsEqual(out1_longdouble)); + EXPECT_FALSE(out1_double.bitwiseIsEqual(out1_float)); + EXPECT_TRUE(out1_nan.bitwiseIsEqual(ap_nan)); + + llvm::APFloat out2_float = I2.CreateAPFloatFromAPSInt(lldb::eBasicTypeFloat); + llvm::APFloat out2_double = + I2.CreateAPFloatFromAPSInt(lldb::eBasicTypeDouble); + llvm::APFloat out2_longdouble = + I2.CreateAPFloatFromAPSInt(lldb::eBasicTypeLongDouble); + llvm::APFloat out2_nan = + I2.CreateAPFloatFromAPSInt(lldb::eBasicTypeFloatComplex); + EXPECT_TRUE(out2_float.isNegative()); + EXPECT_TRUE(out2_double.isNegative()); + EXPECT_TRUE(out2_double.bitwiseIsEqual(out2_longdouble)); + EXPECT_FALSE(out2_double.bitwiseIsEqual(out2_float)); + EXPECT_TRUE(out2_nan.bitwiseIsEqual(ap_nan)); + + llvm::APFloat out3_float = F.CreateAPFloatFromAPFloat(lldb::eBasicTypeFloat); + llvm::APFloat out3_double = + F.CreateAPFloatFromAPFloat(lldb::eBasicTypeDouble); + llvm::APFloat out3_longdouble = + F.CreateAPFloatFromAPFloat(lldb::eBasicTypeLongDouble); + llvm::APFloat out3_nan = + F.CreateAPFloatFromAPFloat(lldb::eBasicTypeFloatComplex); + EXPECT_TRUE(out3_double.bitwiseIsEqual(out3_longdouble)); + EXPECT_FALSE(out3_double.bitwiseIsEqual(out3_float)); + EXPECT_TRUE(out3_nan.bitwiseIsEqual(ap_nan)); +} diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index bd141619d03fd188e2c8bf907a3be468baf36b9f..6f5647d70d8bc11ce4f47c618338fc6f217eda1a 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -159,6 +159,18 @@ foreach(proj IN LISTS LLVM_ENABLE_RUNTIMES) endif() endforeach() +# Set a shorthand option to enable the GPU build of the 'libc' project. +option(LIBC_GPU_BUILD "Enable the 'libc' project targeting the GPU" OFF) +if(LIBC_GPU_BUILD) + if(LLVM_RUNTIME_TARGETS) + list(APPEND LLVM_RUNTIME_TARGETS "nvptx64-nvidia-cuda" "amdgcn-amd-amdhsa") + else() + set(LLVM_RUNTIME_TARGETS "default;nvptx64-nvidia-cuda;amdgcn-amd-amdhsa") + endif() + list(APPEND RUNTIMES_nvptx64-nvidia-cuda_LLVM_ENABLE_RUNTIMES "libc") + list(APPEND RUNTIMES_amdgcn-amd-amdhsa_LLVM_ENABLE_RUNTIMES "libc") +endif() + set(NEED_LIBC_HDRGEN FALSE) if("libc" IN_LIST LLVM_ENABLE_RUNTIMES) set(NEED_LIBC_HDRGEN TRUE) diff --git a/llvm/bindings/ocaml/debuginfo/debuginfo_ocaml.c b/llvm/bindings/ocaml/debuginfo/debuginfo_ocaml.c index a793e893524fe2098cd7975f0aaead825acfcc58..fbe45c0c1e0b0371ecce00da439b6ad82583fa60 100644 --- a/llvm/bindings/ocaml/debuginfo/debuginfo_ocaml.c +++ b/llvm/bindings/ocaml/debuginfo/debuginfo_ocaml.c @@ -972,7 +972,7 @@ value llvm_dibuild_create_parameter_variable_bytecode(value *argv, int arg) { value llvm_dibuild_insert_declare_before_native(value Builder, value Storage, value VarInfo, value Expr, value DebugLoc, value Instr) { - LLVMValueRef Value = LLVMDIBuilderInsertDeclareBefore( + LLVMDbgRecordRef Value = LLVMDIBuilderInsertDeclareBefore( DIBuilder_val(Builder), Value_val(Storage), Metadata_val(VarInfo), Metadata_val(Expr), Metadata_val(DebugLoc), Value_val(Instr)); return to_val(Value); @@ -992,7 +992,7 @@ value llvm_dibuild_insert_declare_before_bytecode(value *argv, int arg) { value llvm_dibuild_insert_declare_at_end_native(value Builder, value Storage, value VarInfo, value Expr, value DebugLoc, value Block) { - LLVMValueRef Value = LLVMDIBuilderInsertDeclareAtEnd( + LLVMDbgRecordRef Value = LLVMDIBuilderInsertDeclareAtEnd( DIBuilder_val(Builder), Value_val(Storage), Metadata_val(VarInfo), Metadata_val(Expr), Metadata_val(DebugLoc), BasicBlock_val(Block)); return to_val(Value); @@ -1012,3 +1012,14 @@ value llvm_dibuild_expression(value Builder, value Addr) { return to_val(LLVMDIBuilderCreateExpression( DIBuilder_val(Builder), (uint64_t *)Op_val(Addr), Wosize_val(Addr))); } + +/* llmodule -> bool */ +value llvm_is_new_dbg_info_format(value Module) { + return Val_bool(LLVMIsNewDbgInfoFormat(Module_val(Module))); +} + +/* llmodule -> bool -> unit */ +value llvm_set_is_new_dbg_info_format(value Module, value UseNewFormat) { + LLVMSetIsNewDbgInfoFormat(Module_val(Module), Bool_val(UseNewFormat)); + return Val_unit; +} diff --git a/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.ml b/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.ml index a6d74ed0eb817dcce1a6d9ea4031cdf6d72b9569..8bb5edb17a2c9748d49a3d5cd8e6e5ac2dd35c70 100644 --- a/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.ml +++ b/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.ml @@ -599,7 +599,7 @@ external dibuild_insert_declare_before : expr:Llvm.llmetadata -> location:Llvm.llmetadata -> instr:Llvm.llvalue -> - Llvm.llvalue + Llvm.lldbgrecord = "llvm_dibuild_insert_declare_before_bytecode" "llvm_dibuild_insert_declare_before_native" external dibuild_insert_declare_at_end : @@ -609,7 +609,7 @@ external dibuild_insert_declare_at_end : expr:Llvm.llmetadata -> location:Llvm.llmetadata -> block:Llvm.llbasicblock -> - Llvm.llvalue + Llvm.lldbgrecord = "llvm_dibuild_insert_declare_at_end_bytecode" "llvm_dibuild_insert_declare_at_end_native" external dibuild_expression : @@ -617,3 +617,9 @@ external dibuild_expression : Int64.t array -> Llvm.llmetadata = "llvm_dibuild_expression" + +external is_new_dbg_info_format : Llvm.llmodule -> bool + = "llvm_is_new_dbg_info_format" + +external set_is_new_dbg_info_format : Llvm.llmodule -> bool -> unit + = "llvm_set_is_new_dbg_info_format" diff --git a/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.mli b/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.mli index e92778b07589f8413d289ce88393270aa84cb23a..7c7882ccce85550364ebd204a845449c41deea36 100644 --- a/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.mli +++ b/llvm/bindings/ocaml/debuginfo/llvm_debuginfo.mli @@ -659,7 +659,7 @@ val dibuild_insert_declare_before : expr:Llvm.llmetadata -> location:Llvm.llmetadata -> instr:Llvm.llvalue -> - Llvm.llvalue + Llvm.lldbgrecord (** [dibuild_insert_declare_before] Insert a new llvm.dbg.declare intrinsic call before the given instruction [instr]. *) @@ -670,7 +670,7 @@ val dibuild_insert_declare_at_end : expr:Llvm.llmetadata -> location:Llvm.llmetadata -> block:Llvm.llbasicblock -> - Llvm.llvalue + Llvm.lldbgrecord (** [dibuild_insert_declare_at_end] Insert a new llvm.dbg.declare intrinsic call at the end of basic block [block]. If [block] has a terminator instruction, the intrinsic is inserted @@ -680,3 +680,9 @@ val dibuild_expression : lldibuilder -> Int64.t array -> Llvm.llmetadata (** [dibuild_expression] Create a new descriptor for the specified variable which has a complex address expression for its address. See LLVMDIBuilderCreateExpression. *) + +val is_new_dbg_info_format : Llvm.llmodule -> bool +(** [is_new_dbg_info_format] See LLVMIsNewDbgInfoFormat *) + +val set_is_new_dbg_info_format : Llvm.llmodule -> bool -> unit +(** [set_is_new_dbg_info_format] See LLVMSetIsNewDbgInfoFormat *) diff --git a/llvm/bindings/ocaml/llvm/llvm.ml b/llvm/bindings/ocaml/llvm/llvm.ml index 057798fc0cea2d0a64b217399bed6f0f3c9c498c..003fd750cd9f83af8806c9a62f3a2aa6b1d5ea15 100644 --- a/llvm/bindings/ocaml/llvm/llvm.ml +++ b/llvm/bindings/ocaml/llvm/llvm.ml @@ -12,6 +12,7 @@ type llmodule type llmetadata type lltype type llvalue +type lldbgrecord type lluse type llbasicblock type llbuilder @@ -528,6 +529,7 @@ external value_name : llvalue -> string = "llvm_value_name" external set_value_name : string -> llvalue -> unit = "llvm_set_value_name" external dump_value : llvalue -> unit = "llvm_dump_value" external string_of_llvalue : llvalue -> string = "llvm_string_of_llvalue" +external string_of_lldbgrecord : lldbgrecord -> string = "llvm_string_of_lldbgrecord" external replace_all_uses_with : llvalue -> llvalue -> unit = "llvm_replace_all_uses_with" diff --git a/llvm/bindings/ocaml/llvm/llvm.mli b/llvm/bindings/ocaml/llvm/llvm.mli index e0febb79a2b61d899bbe9ad222f55ae36502f20c..93540c619efba3f03caa4c0e7cf71481bbae85b5 100644 --- a/llvm/bindings/ocaml/llvm/llvm.mli +++ b/llvm/bindings/ocaml/llvm/llvm.mli @@ -36,6 +36,9 @@ type lltype This type covers a wide range of subclasses. *) type llvalue +(** Non-instruction debug info record. See the [llvm::DbgRecord] class.*) +type lldbgrecord + (** Used to store users and usees of values. See the [llvm::Use] class. *) type lluse @@ -793,6 +796,9 @@ val dump_value : llvalue -> unit (** [string_of_llvalue v] returns a string describing the value [v]. *) val string_of_llvalue : llvalue -> string +(** [string_of_lldbgrecord r] returns a string describing the DbgRecord [r]. *) +val string_of_lldbgrecord : lldbgrecord -> string + (** [replace_all_uses_with old new] replaces all uses of the value [old] with the value [new]. See the method [llvm::Value::replaceAllUsesWith]. *) val replace_all_uses_with : llvalue -> llvalue -> unit diff --git a/llvm/bindings/ocaml/llvm/llvm_ocaml.c b/llvm/bindings/ocaml/llvm/llvm_ocaml.c index 55679f218b307e455c29e70c4ffdb79bfd091d18..6d08d78b84455b72acfddbb6848314654d1edc4f 100644 --- a/llvm/bindings/ocaml/llvm/llvm_ocaml.c +++ b/llvm/bindings/ocaml/llvm/llvm_ocaml.c @@ -800,6 +800,15 @@ value llvm_string_of_llvalue(value M) { return ValueStr; } +/* lldbgrecord -> string */ +value llvm_string_of_lldbgrecord(value Record) { + char *ValueCStr = LLVMPrintDbgRecordToString(DbgRecord_val(Record)); + value ValueStr = caml_copy_string(ValueCStr); + LLVMDisposeMessage(ValueCStr); + + return ValueStr; +} + /* llvalue -> llvalue -> unit */ value llvm_replace_all_uses_with(value OldVal, value NewVal) { LLVMReplaceAllUsesWith(Value_val(OldVal), Value_val(NewVal)); diff --git a/llvm/bindings/ocaml/llvm/llvm_ocaml.h b/llvm/bindings/ocaml/llvm/llvm_ocaml.h index a3791744e647b2f5c16f6c0e73b54a99a2c182b9..ec60d6a5dad63df2cdbd3e3825fd12126268818f 100644 --- a/llvm/bindings/ocaml/llvm/llvm_ocaml.h +++ b/llvm/bindings/ocaml/llvm/llvm_ocaml.h @@ -53,6 +53,7 @@ void *from_val_array(value Elements); #define Metadata_val(v) ((LLVMMetadataRef)from_val(v)) #define Type_val(v) ((LLVMTypeRef)from_val(v)) #define Value_val(v) ((LLVMValueRef)from_val(v)) +#define DbgRecord_val(v) ((LLVMDbgRecordRef)from_val(v)) #define Use_val(v) ((LLVMUseRef)from_val(v)) #define BasicBlock_val(v) ((LLVMBasicBlockRef)from_val(v)) #define MemoryBuffer_val(v) ((LLVMMemoryBufferRef)from_val(v)) diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake index 374f5e085d91180c31bb1d2b2cf37dfc0d62cc85..745935f14051706028477d6b91972ec67df371ce 100644 --- a/llvm/cmake/modules/AddLLVM.cmake +++ b/llvm/cmake/modules/AddLLVM.cmake @@ -257,6 +257,17 @@ if (NOT DEFINED LLVM_LINKER_DETECTED AND NOT WIN32) message(STATUS "Linker detection: unknown") endif() endif() + + # Apple's linker complains about duplicate libraries, which CMake likes to do + # to support ELF platforms. To silence that warning, we can use + # -no_warn_duplicate_libraries, but only in versions of the linker that + # support that flag. + if(NOT LLVM_USE_LINKER AND ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + include(CheckLinkerFlag) + check_linker_flag(C "-Wl,-no_warn_duplicate_libraries" LLVM_LINKER_SUPPORTS_NO_WARN_DUPLICATE_LIBRARIES) + else() + set(LLVM_LINKER_SUPPORTS_NO_WARN_DUPLICATE_LIBRARIES OFF CACHE INTERNAL "") + endif() endif() function(add_link_opts target_name) @@ -310,6 +321,11 @@ function(add_link_opts target_name) endif() endif() + if(LLVM_LINKER_SUPPORTS_NO_WARN_DUPLICATE_LIBRARIES) + set_property(TARGET ${target_name} APPEND_STRING PROPERTY + LINK_FLAGS " -Wl,-no_warn_duplicate_libraries") + endif() + if(ARG_SUPPORT_PLUGINS AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") set_property(TARGET ${target_name} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-brtl") @@ -1621,8 +1637,14 @@ function(add_unittest test_suite test_name) # The runtime benefits of LTO don't outweight the compile time costs for tests. if(LLVM_ENABLE_LTO) if((UNIX OR MINGW) AND LINKER_IS_LLD) - set_property(TARGET ${test_name} APPEND_STRING PROPERTY - LINK_FLAGS " -Wl,--lto-O0") + if(LLVM_ENABLE_FATLTO AND NOT APPLE) + # When using FatLTO, just use relocatable linking. + set_property(TARGET ${test_name} APPEND_STRING PROPERTY + LINK_FLAGS " -Wl,--no-fat-lto-objects") + else() + set_property(TARGET ${test_name} APPEND_STRING PROPERTY + LINK_FLAGS " -Wl,--lto-O0") + endif() elseif(LINKER_IS_LLD_LINK) set_property(TARGET ${test_name} APPEND_STRING PROPERTY LINK_FLAGS " /opt:lldlto=0") @@ -2074,7 +2096,7 @@ function(add_lit_testsuites project directory) endfunction() function(llvm_install_library_symlink name dest type) - cmake_parse_arguments(ARG "" "COMPONENT;SOVERSION" "" ${ARGN}) + cmake_parse_arguments(ARG "FULL_DEST" "COMPONENT" "" ${ARGN}) foreach(path ${CMAKE_MODULE_PATH}) if(EXISTS ${path}/LLVMInstallSymlink.cmake) set(INSTALL_SYMLINK ${path}/LLVMInstallSymlink.cmake) @@ -2088,8 +2110,8 @@ function(llvm_install_library_symlink name dest type) endif() set(full_name ${CMAKE_${type}_LIBRARY_PREFIX}${name}${CMAKE_${type}_LIBRARY_SUFFIX}) - if (ARG_SOVERSION) - set(full_dest ${CMAKE_${type}_LIBRARY_PREFIX}${dest}${CMAKE_${type}_LIBRARY_SUFFIX}.${ARG_SOVERSION}) + if (ARG_FULL_DEST) + set(full_dest ${dest}) else() set(full_dest ${CMAKE_${type}_LIBRARY_PREFIX}${dest}${CMAKE_${type}_LIBRARY_SUFFIX}) endif() diff --git a/llvm/cmake/modules/HandleLLVMOptions.cmake b/llvm/cmake/modules/HandleLLVMOptions.cmake index 745a8354f118964769efda095c84b4c03250a3e7..185266c0861e86b121475675be8705995da59d47 100644 --- a/llvm/cmake/modules/HandleLLVMOptions.cmake +++ b/llvm/cmake/modules/HandleLLVMOptions.cmake @@ -32,6 +32,8 @@ endif() set(LLVM_ENABLE_LTO OFF CACHE STRING "Build LLVM with LTO. May be specified as Thin or Full to use a particular kind of LTO") string(TOUPPER "${LLVM_ENABLE_LTO}" uppercase_LLVM_ENABLE_LTO) +option(LLVM_ENABLE_FATLTO "Build LLVM with -ffat-lto-objects." OFF) + # Ninja Job Pool support # The following only works with the Ninja generator in CMake >= 3.0. set(LLVM_PARALLEL_COMPILE_JOBS "" CACHE STRING @@ -1280,6 +1282,13 @@ elseif(LLVM_ENABLE_LTO) endif() endif() +if(LLVM_ENABLE_FATLTO AND UNIX AND NOT APPLE) + append("-ffat-lto-objects" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + if(NOT LINKER_IS_LLD_LINK) + append("-ffat-lto-objects" CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS) + endif() +endif() + # Set an AIX default for LLVM_EXPORT_SYMBOLS_FOR_PLUGINS based on whether we are # doing dynamic linking (see below). set(LLVM_EXPORT_SYMBOLS_FOR_PLUGINS_AIX_default OFF) diff --git a/llvm/docs/AMDGPUUsage.rst b/llvm/docs/AMDGPUUsage.rst index 99d7a482710f5ec58505a2671fe5af5891c418b3..22c1d1f186ea546790faa933aeef68714b4b5ad7 100644 --- a/llvm/docs/AMDGPUUsage.rst +++ b/llvm/docs/AMDGPUUsage.rst @@ -1312,23 +1312,30 @@ The AMDGPU backend implements the following LLVM IR intrinsics. List AMDGPU intrinsics. +.. _amdgpu_metadata: + LLVM IR Metadata ------------------- +================ -The AMDGPU backend implements the following LLVM IR metadata. +The AMDGPU backend implements the following target custom LLVM IR +metadata. -.. table:: AMDGPU LLVM IR Metadata - :name: amdgpu-llvm-ir-metadata-table +.. _amdgpu_last_use: + +'``amdgpu.last.use``' Metadata +------------------------------ + +Sets TH_LOAD_LU temporal hint on load instructions that support it. +Takes priority over nontemporal hint (TH_LOAD_NT). This takes no +arguments. + +.. code-block:: llvm + + %val = load i32, ptr %in, align 4, !amdgpu.last.use !{} - ============================================== ========================================================== - LLVM IR Metadata Description - ============================================== ========================================================== - !amdgpu.last.use Sets TH_LOAD_LU temporal hint on load instructions that support it. - Takes priority over nontemporal hint (TH_LOAD_NT). - ============================================== ========================================================== LLVM IR Attributes ------------------- +================== The AMDGPU backend supports the following LLVM IR attributes. @@ -1442,15 +1449,56 @@ The AMDGPU backend supports the following LLVM IR attributes. the frame. This is an internal detail of how LDS variables are lowered, language front ends should not set this attribute. + "amdgpu-gds-size" Bytes expected to be allocated at the start of GDS memory at entry. + + "amdgpu-git-ptr-high" The hard-wired high half of the address of the global information table + for AMDPAL OS type. 0xffffffff represents no hard-wired high half, since + current hardware only allows a 16 bit value. + + "amdgpu-32bit-address-high-bits" Assumed high 32-bits for 32-bit address spaces which are really truncated + 64-bit addresses (i.e., addrspace(6)) + + "amdgpu-color-export" Indicates shader exports color information if set to 1. + Defaults to 1 for :ref:`amdgpu_ps <amdgpu-cc>`, and 0 for other calling + conventions. Determines the necessity and type of null exports when a shader + terminates early by killing lanes. + + "amdgpu-depth-export" Indicates shader exports depth information if set to 1. Determines the + necessity and type of null exports when a shader terminates early by killing + lanes. A depth-only shader will export to depth channel when no null export + target is available (GFX11+). + + "InitialPSInputAddr" Set the initial value of the `spi_ps_input_addr` register for + :ref:`amdgpu_ps <amdgpu-cc>` shaders. Any bits enabled by this value will + be enabled in the final register value. + + "amdgpu-wave-priority-threshold" VALU instruction count threshold for adjusting wave priority. If exceeded, + temporarily raise the wave priority at the start of the shader function + until its last VMEM instructions to allow younger waves to issue their VMEM + instructions as well. + + "amdgpu-memory-bound" Set internally by backend + + "amdgpu-wave-limiter" Set internally by backend + + "amdgpu-unroll-threshold" Set base cost threshold preference for loop unrolling within this function, + default is 300. Actual threshold may be varied by per-loop metadata or + reduced by heuristics. + "amdgpu-max-num-workgroups"="x,y,z" Specify the maximum number of work groups for the kernel dispatch in the X, Y, and Z dimensions. Generated by the ``amdgpu_max_num_work_groups`` CLANG attribute [CLANG-ATTR]_. Clang only emits this attribute when all the three numbers are >= 1. + "amdgpu-no-agpr" Indicates the function will not require allocating AGPRs. This is only + relevant on subtargets with AGPRs. The behavior is undefined if a + function which requires AGPRs is reached through any function marked + with this attribute. + ======================================= ========================================================== Calling Conventions -------------------- +=================== The AMDGPU backend supports the following calling conventions: @@ -1545,6 +1593,25 @@ The AMDGPU backend supports the following calling conventions: =============================== ========================================================== +AMDGPU MCExpr +------------- + +As part of the AMDGPU MC layer, AMDGPU provides the following target specific +``MCExpr``\s. + + .. table:: AMDGPU MCExpr types: + :name: amdgpu-mcexpr-table + + =================== ================= ======================================================== + MCExpr Operands Return value + =================== ================= ======================================================== + ``max(arg, ...)`` 1 or more Variadic signed operation that returns the maximum + value of all its arguments. + + ``or(arg, ...)`` 1 or more Variadic signed operation that returns the bitwise-or + result of all its arguments. + + =================== ================= ======================================================== .. _amdgpu-elf-code-object: diff --git a/llvm/docs/CommandGuide/dsymutil.rst b/llvm/docs/CommandGuide/dsymutil.rst index af9d7f16b36196e55bb8c03c98e1e71e2acc297f..e3f2f33224b015d0bb7904d834af0347a466fa16 100644 --- a/llvm/docs/CommandGuide/dsymutil.rst +++ b/llvm/docs/CommandGuide/dsymutil.rst @@ -140,10 +140,6 @@ OPTIONS (in bytes) to the linked dSYM. The table is sorted by the output size listing the object files with the largest contribution first. -.. option:: --symbol-map <bcsymbolmap> - - Update the existing dSYMs inplace using symbol map specified. - .. option:: -s, --symtab Dumps the symbol table found in *executable* or object file(s) and exits. diff --git a/llvm/docs/CommandGuide/llvm-ar.rst b/llvm/docs/CommandGuide/llvm-ar.rst index 03d5b9e41ada386ba639df06cf1de9e3ac0c2460..63b3a519550bc01fe46f4ee764ab5875378b460d 100644 --- a/llvm/docs/CommandGuide/llvm-ar.rst +++ b/llvm/docs/CommandGuide/llvm-ar.rst @@ -261,7 +261,7 @@ Other .. option:: --format=<type> - This option allows for default, gnu, darwin or bsd ``<type>`` to be selected. + This option allows for default, gnu, darwin, bsd or coff ``<type>`` to be selected. When creating an ``archive`` with the default ``<type>``, :program:``llvm-ar`` will attempt to infer it from the input files and fallback to the default toolchain target if unable to do so. diff --git a/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst b/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst index a78066a5eea37e04d2a7e1fa4ccafbe54c4c7301..5b3200a4b78235a201b90bdfd3792511ddf9c315 100644 --- a/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst +++ b/llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst @@ -16,7 +16,7 @@ DESCRIPTION binary object files and prints their contents in a logical view, which is a human readable representation that closely matches the structure of the original user source code. Supported object file formats include -ELF, Mach-O, PDB and COFF. +ELF, Mach-O, WebAssembly, PDB and COFF. The **logical view** abstracts the complexity associated with the different low-level representations of the debugging information that @@ -468,8 +468,9 @@ If the <pattern> criteria is too general, a more selective option can be specified to target a particular category of elements: lines (:option:`--select-lines`), scopes (:option:`--select-scopes`), symbols (:option:`--select-symbols`) and types (:option:`--select-types`). + These options require knowledge of the debug information format (DWARF, -CodeView, COFF), as the given **kind** describes a very specific type +CodeView), as the given **kind** describes a very specific type of element. LINES @@ -598,7 +599,7 @@ When comparing logical views created from different debug formats, its accuracy depends on how close the debug information represents the user code. For instance, a logical view created from a binary file with DWARF debug information may include more detailed data than a logical -view created from a binary file with CodeView/COFF debug information. +view created from a binary file with CodeView debug information. The following options describe the elements to compare. @@ -1952,11 +1953,324 @@ The **{Coverage}** and **{Location}** attributes describe the debug location and coverage for logical symbols. For optimized code, the coverage value decreases and it affects the program debuggability. +WEBASSEMBLY SUPPORT +~~~~~~~~~~~~~~~~~~~ +The below example is used to show the WebAssembly output generated by +:program:`llvm-debuginfo-analyzer`. We compiled the example for a +WebAssembly 32-bit target with Clang (-O0 -g --target=wasm32): + +.. code-block:: c++ + + 1 using INTPTR = const int *; + 2 int foo(INTPTR ParamPtr, unsigned ParamUnsigned, bool ParamBool) { + 3 if (ParamBool) { + 4 typedef int INTEGER; + 5 const INTEGER CONSTANT = 7; + 6 return CONSTANT; + 7 } + 8 return ParamUnsigned; + 9 } + +PRINT BASIC DETAILS +^^^^^^^^^^^^^^^^^^^ +The following command prints basic details for all the logical elements +sorted by the debug information internal offset; it includes its lexical +level and debug info format. + +.. code-block:: none + + llvm-debuginfo-analyzer --attribute=level,format + --output-sort=offset + --print=scopes,symbols,types,lines,instructions + test-clang.o + +or + +.. code-block:: none + + llvm-debuginfo-analyzer --attribute=level,format + --output-sort=offset + --print=elements + test-clang.o + +Each row represents an element that is present within the debug +information. The first column represents the scope level, followed by +the associated line number (if any), and finally the description of +the element. + +.. code-block:: none + + Logical View: + [000] {File} 'test-clang.o' -> WASM + + [001] {CompileUnit} 'test.cpp' + [002] 2 {Function} extern not_inlined 'foo' -> 'int' + [003] 2 {Parameter} 'ParamPtr' -> 'INTPTR' + [003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int' + [003] 2 {Parameter} 'ParamBool' -> 'bool' + [003] {Block} + [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER' + [004] 5 {Line} + [004] {Code} 'i32.const 7' + [004] {Code} 'local.set 10' + [004] {Code} 'local.get 5' + [004] {Code} 'local.get 10' + [004] {Code} 'i32.store 12' + [004] 6 {Line} + [004] {Code} 'i32.const 7' + [004] {Code} 'local.set 11' + [004] {Code} 'local.get 5' + [004] {Code} 'local.get 11' + [004] {Code} 'i32.store 28' + [004] {Code} 'br 1' + [004] - {Line} + [004] {Code} 'end' + [003] 4 {TypeAlias} 'INTEGER' -> 'int' + [003] 2 {Line} + [003] {Code} 'nop' + [003] {Code} 'end' + [003] {Code} 'i64.div_s' + [003] {Code} 'global.get 0' + [003] {Code} 'local.set 3' + [003] {Code} 'i32.const 32' + [003] {Code} 'local.set 4' + [003] {Code} 'local.get 3' + [003] {Code} 'local.get 4' + [003] {Code} 'i32.sub' + [003] {Code} 'local.set 5' + [003] {Code} 'local.get 5' + [003] {Code} 'local.get 0' + [003] {Code} 'i32.store 24' + [003] {Code} 'local.get 5' + [003] {Code} 'local.get 1' + [003] {Code} 'i32.store 20' + [003] {Code} 'local.get 2' + [003] {Code} 'local.set 6' + [003] {Code} 'local.get 5' + [003] {Code} 'local.get 6' + [003] {Code} 'i32.store8 19' + [003] 3 {Line} + [003] {Code} 'local.get 5' + [003] {Code} 'i32.load8_u 19' + [003] {Code} 'local.set 7' + [003] 3 {Line} + [003] {Code} 'i32.const 1' + [003] {Code} 'local.set 8' + [003] {Code} 'local.get 7' + [003] {Code} 'local.get 8' + [003] {Code} 'i32.and' + [003] {Code} 'local.set 9' + [003] {Code} 'block' + [003] {Code} 'block' + [003] {Code} 'local.get 9' + [003] {Code} 'i32.eqz' + [003] {Code} 'br_if 0' + [003] 8 {Line} + [003] {Code} 'local.get 5' + [003] {Code} 'i32.load 20' + [003] {Code} 'local.set 12' + [003] 8 {Line} + [003] {Code} 'local.get 5' + [003] {Code} 'local.get 12' + [003] {Code} 'i32.store 28' + [003] - {Line} + [003] {Code} 'end' + [003] 9 {Line} + [003] {Code} 'local.get 5' + [003] {Code} 'i32.load 28' + [003] {Code} 'local.set 13' + [003] {Code} 'local.get 13' + [003] {Code} 'return' + [003] {Code} 'end' + [003] 9 {Line} + [003] {Code} 'unreachable' + [002] 1 {TypeAlias} 'INTPTR' -> '* const int' + +SELECT LOGICAL ELEMENTS +^^^^^^^^^^^^^^^^^^^^^^^ +The following prints all *instructions*, *symbols* and *types* that +contain **'block'** or **'.store'** in their names or types, using a tab +layout and given the number of matches. + +.. code-block:: none + + llvm-debuginfo-analyzer --attribute=level + --select-nocase --select-regex + --select=BLOCK --select=.store + --report=list + --print=symbols,types,instructions,summary + test-clang.o + + Logical View: + [000] {File} 'test-clang.o' + + [001] {CompileUnit} 'test.cpp' + [003] {Code} 'block' + [003] {Code} 'block' + [004] {Code} 'i32.store 12' + [003] {Code} 'i32.store 20' + [003] {Code} 'i32.store 24' + [004] {Code} 'i32.store 28' + [003] {Code} 'i32.store 28' + [003] {Code} 'i32.store8 19' + + ----------------------------- + Element Total Printed + ----------------------------- + Scopes 3 0 + Symbols 4 0 + Types 2 0 + Lines 62 8 + ----------------------------- + Total 71 8 + +COMPARISON MODE +^^^^^^^^^^^^^^^ +Given the previous example we found the above debug information issue +(related to the previous invalid scope location for the **'typedef int +INTEGER'**) by comparing against another compiler. + +Using GCC to generate test-dwarf-gcc.o, we can apply a selection pattern +with the printing mode to obtain the following logical view output. + +.. code-block:: none + + llvm-debuginfo-analyzer --attribute=level + --select-regex --select-nocase --select=INTe + --report=list + --print=symbols,types + test-clang.o test-dwarf-gcc.o + + Logical View: + [000] {File} 'test-clang.o' + + [001] {CompileUnit} 'test.cpp' + [003] 4 {TypeAlias} 'INTEGER' -> 'int' + [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER' + + Logical View: + [000] {File} 'test-dwarf-gcc.o' + + [001] {CompileUnit} 'test.cpp' + [004] 4 {TypeAlias} 'INTEGER' -> 'int' + [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER' + +The output shows that both objects contain the same elements. But the +**'typedef INTEGER'** is located at different scope level. The GCC +generated object, shows **'4'**, which is the correct value. + +There are 2 comparison methods: logical view and logical elements. + +LOGICAL VIEW +"""""""""""" +It compares the logical view as a whole unit; for a match, each compared +logical element must have the same parents and children. + +The output shows in view form the **missing (-), added (+)** elements, +giving more context by swapping the reference and target object files. + +.. code-block:: none + + llvm-debuginfo-analyzer --attribute=level + --compare=types + --report=view + --print=symbols,types + test-clang.o test-dwarf-gcc.o + + Reference: 'test-clang.o' + Target: 'test-dwarf-gcc.o' + + Logical View: + [000] {File} 'test-clang.o' + + [001] {CompileUnit} 'test.cpp' + [002] 1 {TypeAlias} 'INTPTR' -> '* const int' + [002] 2 {Function} extern not_inlined 'foo' -> 'int' + [003] {Block} + [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER' + +[004] 4 {TypeAlias} 'INTEGER' -> 'int' + [003] 2 {Parameter} 'ParamBool' -> 'bool' + [003] 2 {Parameter} 'ParamPtr' -> 'INTPTR' + [003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int' + -[003] 4 {TypeAlias} 'INTEGER' -> 'int' + +The output shows the merging view path (reference and target) with the +missing and added elements. + +LOGICAL ELEMENTS +"""""""""""""""" +It compares individual logical elements without considering if their +parents are the same. For both comparison methods, the equal criteria +includes the name, source code location, type, lexical scope level. + +.. code-block:: none + + llvm-debuginfo-analyzer --attribute=level + --compare=types + --report=list + --print=symbols,types,summary + test-clang.o test-dwarf-gcc.o + + Reference: 'test-clang.o' + Target: 'test-dwarf-gcc.o' + + (1) Missing Types: + -[003] 4 {TypeAlias} 'INTEGER' -> 'int' + + (1) Added Types: + +[004] 4 {TypeAlias} 'INTEGER' -> 'int' + + ---------------------------------------- + Element Expected Missing Added + ---------------------------------------- + Scopes 4 0 0 + Symbols 0 0 0 + Types 2 1 1 + Lines 0 0 0 + ---------------------------------------- + Total 6 1 1 + +Changing the *Reference* and *Target* order: + +.. code-block:: none + + llvm-debuginfo-analyzer --attribute=level + --compare=types + --report=list + --print=symbols,types,summary + test-dwarf-gcc.o test-clang.o + + Reference: 'test-dwarf-gcc.o' + Target: 'test-clang.o' + + (1) Missing Types: + -[004] 4 {TypeAlias} 'INTEGER' -> 'int' + + (1) Added Types: + +[003] 4 {TypeAlias} 'INTEGER' -> 'int' + + ---------------------------------------- + Element Expected Missing Added + ---------------------------------------- + Scopes 4 0 0 + Symbols 0 0 0 + Types 2 1 1 + Lines 0 0 0 + ---------------------------------------- + Total 6 1 1 + +As the *Reference* and *Target* are switched, the *Added Types* from +the first case now are listed as *Missing Types*. + EXIT STATUS ----------- :program:`llvm-debuginfo-analyzer` returns 0 if the input files were parsed and printed successfully. Otherwise, it returns 1. +LIMITATIONS AND KNOWN ISSUES +---------------------------- +See :download:`Limitations <../../tools/llvm-debuginfo-analyzer/README.md>`. + SEE ALSO -------- :manpage:`llvm-dwarfdump` diff --git a/llvm/docs/CommandGuide/llvm-objcopy.rst b/llvm/docs/CommandGuide/llvm-objcopy.rst index 9d0cb7ad11958933daea80dd4172443d7a695f71..985d16eb11cfb68678432341ccb5908239c427fa 100644 --- a/llvm/docs/CommandGuide/llvm-objcopy.rst +++ b/llvm/docs/CommandGuide/llvm-objcopy.rst @@ -464,6 +464,19 @@ them. Read a list of symbols from <filename> and change their visibility to the specified value. Visibility values: default, internal, hidden, protected. +.. option:: --skip-symbol <symbol> + + Do not change the parameters of symbol ``<symbol>`` when executing other + options that can change the symbol's name, binding or visibility. + +.. option:: --skip-symbols <filename> + + Do not change the parameters of symbols named in the file ``<filename>`` when + executing other options that can change the symbol's name, binding or + visibility. In the file, each line represents a single symbol, with leading + and trailing whitespace ignored, as is anything following a '#'. + Can be specified multiple times to read names from multiple files. + .. option:: --split-dwo <dwo-file> Equivalent to running :program:`llvm-objcopy` with :option:`--extract-dwo` and diff --git a/llvm/docs/DirectX/DXILArchitecture.rst b/llvm/docs/DirectX/DXILArchitecture.rst index d6712bea4f77128daaf44f96a435e7772760e0eb..32b1e72deae7cdf7367a1429b831ac4b2207fc89 100644 --- a/llvm/docs/DirectX/DXILArchitecture.rst +++ b/llvm/docs/DirectX/DXILArchitecture.rst @@ -61,6 +61,19 @@ on the utilities described in "Common Code" above in order to share logic with both the DirectX backend and with Clang's codegen of HLSL support as much as possible. +The DirectX Intrinsic Expansion Pass +==================================== +There are intrinsics that don't map directly to DXIL Ops. In some cases +an intrinsic needs to be expanded to a set of LLVM IR instructions. In +other cases an intrinsic needs modifications to the arguments or return +values of a DXIL Op. The `DXILIntrinsicExpansion` pass handles all +the cases where our intrinsics don't have a one to one mapping. This +pass may also be used when the expansion is specific to DXIL to keep +implementation details out of CodeGen. Finally, there is an expectation +that we maintain vector types through this pass. Therefore, best +practice would be to avoid scalarization in this pass. + + The DirectX Backend =================== diff --git a/llvm/docs/GettingInvolved.rst b/llvm/docs/GettingInvolved.rst index 763aeb87c688051f59ce2dbbd4160f1391ffeb1b..a4247796cb65914c66c5df41f198dc3552496dfb 100644 --- a/llvm/docs/GettingInvolved.rst +++ b/llvm/docs/GettingInvolved.rst @@ -323,6 +323,11 @@ The :doc:`CodeOfConduct` applies to all office hours. - Monthly, 4th Wednesday of the month at 9:30am PT, for 30 minutes. - `Google meet <https://meet.google.com/pdd-dibg-cwv>`__ - English + * - Maksim Levental and Jeremy Kun + - MLIR newcomers and general discussion (`livestreamed <https://www.youtube.com/playlist?list=PLhxO86S3jsX2k7kOhZaV-qKWm8tNsUdAE>`__) + - Every two weeks, Fridays at 3:00pm US Pacific, for 90 minutes. + - Livestream chat or `Google meet <https://meet.google.com/wit-tvzc-dwc>`__ + - English * - Rotating hosts - Getting Started, beginner questions, new contributors. - Every Tuesday at 2 PM ET (11 AM PT), for 30 minutes. diff --git a/llvm/docs/GlobalISel/GenericOpcode.rst b/llvm/docs/GlobalISel/GenericOpcode.rst index bf1b3cb30a52e5e0a85dc5ce3c792d073313dd4d..a12627c01d205b2f699573d0cc949a93398569cc 100644 --- a/llvm/docs/GlobalISel/GenericOpcode.rst +++ b/llvm/docs/GlobalISel/GenericOpcode.rst @@ -690,6 +690,10 @@ G_SPLAT_VECTOR Create a vector where all elements are the scalar from the source operand. +The type of the operand must be equal to or larger than the vector element +type. If the operand is larger than the vector element type, the scalar is +implicitly truncated to the vector element type. + Vector Reduction Operations --------------------------- @@ -790,11 +794,17 @@ G_ATOMIC_CMPXCHG Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit operands. -G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB, G_ATOMICRMW_AND, -G_ATOMICRMW_NAND, G_ATOMICRMW_OR, G_ATOMICRMW_XOR, G_ATOMICRMW_MAX, -G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX, G_ATOMICRMW_UMIN, G_ATOMICRMW_FADD, -G_ATOMICRMW_FSUB, G_ATOMICRMW_FMAX, G_ATOMICRMW_FMIN -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +|all_g_atomicrmw| +^^^^^^^^^^^^^^^^^ + +.. |all_g_atomicrmw| replace:: G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, + G_ATOMICRMW_SUB, G_ATOMICRMW_AND, + G_ATOMICRMW_NAND, G_ATOMICRMW_OR, + G_ATOMICRMW_XOR, G_ATOMICRMW_MAX, + G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX, + G_ATOMICRMW_UMIN, G_ATOMICRMW_FADD, + G_ATOMICRMW_FSUB, G_ATOMICRMW_FMAX, + G_ATOMICRMW_FMIN Generic atomicrmw. Expects a MachineMemOperand in addition to explicit operands. @@ -933,6 +943,25 @@ The _CONVERGENT variant corresponds to an LLVM IR intrinsic marked `convergent`. Unlike SelectionDAG, there is no _VOID variant. Both of these are permitted to have zero, one, or multiple results. +G_TRAP, G_DEBUGTRAP, G_UBSANTRAP +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Represents :ref:`llvm.trap <llvm.trap>`, :ref:`llvm.debugtrap <llvm.debugtrap>` +and :ref:`llvm.ubsantrap <llvm.ubsantrap>` that generate a target dependent +trap instructions. + +.. code-block:: none + + G_TRAP + +.. code-block:: none + + G_DEBUGTRAP + +.. code-block:: none + + G_UBSANTRAP 12 + Variadic Arguments ------------------ diff --git a/llvm/docs/InstCombineContributorGuide.md b/llvm/docs/InstCombineContributorGuide.md new file mode 100644 index 0000000000000000000000000000000000000000..2416fd0920f62ca12c9ce686bb6e8f0bb55d6f26 --- /dev/null +++ b/llvm/docs/InstCombineContributorGuide.md @@ -0,0 +1,556 @@ +# InstCombine contributor guide + +This guide lays out a series of rules that contributions to InstCombine should +follow. **Following these rules will results in much faster PR approvals.** + +## Tests + +### Precommit tests + +Tests for new optimizations or miscompilation fixes should be pre-committed. +This means that you first commit the test with CHECK lines showing the behavior +*without* your change. Your actual change will then only contain CHECK line +diffs relative to that baseline. + +This means that pull requests should generally contain two commits: First, +one commit adding new tests with baseline check lines. Second, a commit with +functional changes and test diffs. + +If the second commit in your PR does not contain test diffs, you did something +wrong. Either you made a mistake when generating CHECK lines, or your tests are +not actually affected by your patch. + +Exceptions: When fixing assertion failures or infinite loops, do not pre-commit +tests. + +### Use `update_test_checks.py` + +CHECK lines should be generated using the `update_test_checks.py` script. Do +**not** manually edit check lines after using it. + +Be sure to use the correct opt binary when using the script. For example, if +your build directory is `build`, then you'll want to run: + +```sh +llvm/utils/update_test_checks.py --opt-binary build/bin/opt \ + llvm/test/Transforms/InstCombine/the_test.ll +``` + +Exceptions: Hand-written CHECK lines are allowed for debuginfo tests. + +### General testing considerations + +Place all tests relating to a transform into a single file. If you are adding +a regression test for a crash/miscompile in an existing transform, find the +file where the existing tests are located. A good way to do that is to comment +out the transform and see which tests fail. + +Make tests minimal. Only test exactly the pattern being transformed. If your +original motivating case is a larger pattern that your fold enables to +optimize in some non-trivial way, you may add it as well -- however, the bulk +of the test coverage should be minimal. + +Give tests short, but meaningful names. Don't call them `@test1`, `@test2` etc. +For example, a test checking multi-use behavior of a fold involving the +addition of two selects might be called `@add_of_selects_multi_use`. + +Add representative tests for each test category (discussed below), but don't +test all combinations of everything. If you have multi-use tests, and you have +commuted tests, you shouldn't also add commuted multi-use tests. + +Prefer to keep bit-widths for tests low to improve performance of proof checking using alive2. Using `i8` is better than `i128` where possible. + +### Add negative tests + +Make sure to add tests for which your transform does **not** apply. Start with +one of the test cases that succeeds and then create a sequence of negative +tests, such that **exactly one** different pre-condition of your transform is +not satisfied in each test. + +### Add multi-use tests + +Add multi-use tests that ensures your transform does not increase instruction +count if some instructions have additional uses. The standard pattern is to +introduce extra uses with function calls: + +```llvm +declare void @use(i8) + +define i8 @add_mul_const_multi_use(i8 %x) { + %add = add i8 %x, 1 + call void @use(i8 %add) + %mul = mul i8 %add, 3 + ret i8 %mul +} +``` + +Exceptions: For transform that only produce one instruction, multi-use tests +may be omitted. + +### Add commuted tests + +If the transform involves commutative operations, add tests with commuted +(swapped) operands. + +Make sure that the operand order stays intact in the CHECK lines of your +pre-commited tests. You should not see something like this: + +```llvm +; CHECK-NEXT: [[OR:%.*]] = or i8 [[X]], [[Y]] +; ... +%or = or i8 %y, %x +``` + +If this happens, you may need to change one of the operands to have higher +complexity (include the "thwart" comment in that case): + +```llvm +%y2 = mul i8 %y, %y ; thwart complexity-based canonicalization +%or = or i8 %y, %x +``` + +### Add vector tests + +When possible, it is recommended to add at least one test that uses vectors +instead of scalars. + +For patterns that include constants, we distinguish three kinds of tests. +The first are "splat" vectors, where all the vector elements are the same. +These tests *should* usually fold without additional effort. + +```llvm +define <2 x i8> @add_mul_const_vec_splat(<2 x i8> %x) { + %add = add <2 x i8> %x, <i8 1, i8 1> + %mul = mul <2 x i8> %add, <i8 3, i8 3> + ret <2 x i8> %mul +} +``` + +A minor variant is to replace some of the splat elements with poison. These +will often also fold without additional effort. + +```llvm +define <2 x i8> @add_mul_const_vec_splat_poison(<2 x i8> %x) { + %add = add <2 x i8> %x, <i8 1, i8 poison> + %mul = mul <2 x i8> %add, <i8 3, i8 poison> + ret <2 x i8> %mul +} +``` + +Finally, you can have non-splat vectors, where the vector elements are not +the same: + +```llvm +define <2 x i8> @add_mul_const_vec_non_splat(<2 x i8> %x) { + %add = add <2 x i8> %x, <i8 1, i8 5> + %mul = mul <2 x i8> %add, <i8 3, i8 6> + ret <2 x i8> %mul +} +``` + +Non-splat vectors will often not fold by default. You should **not** try to +make them fold, unless doing so does not add **any** additional complexity. +You should still add the test though, even if it does not fold. + +### Flag tests + +If your transform involves instructions that can have poison-generating flags, +such as `nuw` and `nsw` on `add`, you should test how these interact with the +transform. + +If your transform *requires* a certain flag for correctness, make sure to add +negative tests missing the required flag. + +If your transform doesn't require flags for correctness, you should have tests +for preservation behavior. If the input instructions have certain flags, are +they preserved in the output instructions, if it is valid to preserve them? +(This depends on the transform. Check with alive2.) + +The same also applies to fast-math-flags (FMF). In that case, please always +test specific flags like `nnan`, `nsz` or `reassoc`, rather than the umbrella +`fast` flag. + +### Other tests + +The test categories mentioned above are non-exhaustive. There may be more tests +to be added, depending on the instructions involved in the transform. Some +examples: + + * For folds involving memory accesses like load/store, check that scalable vectors and non-byte-size types (like i3) are handled correctly. Also check that volatile/atomic are handled. + * For folds that interact with the bitwidth in some non-trivial way, check an illegal type like i13. Also confirm that the transform is correct for i1. + * For folds that involve phis, you may want to check that the case of multiple incoming values from one block is handled correctly. + +## Proofs + +Your pull request description should contain one or more +[alive2 proofs](https://alive2.llvm.org/ce/) for the correctness of the +proposed transform. + +### Basics + +Proofs are written using LLVM IR, by specifying a `@src` and `@tgt` function. +It is possible to include multiple proofs in a single file by giving the src +and tgt functions matching suffixes. + +For example, here is a pair of proofs that both `(x-y)+y` and `(x+y)-y` can +be simplified to `x` ([online](https://alive2.llvm.org/ce/z/MsPPGz)): + +```llvm +define i8 @src_add_sub(i8 %x, i8 %y) { + %add = add i8 %x, %y + %sub = sub i8 %add, %y + ret i8 %sub +} + +define i8 @tgt_add_sub(i8 %x, i8 %y) { + ret i8 %x +} + + +define i8 @src_sub_add(i8 %x, i8 %y) { + %sub = sub i8 %x, %y + %add = add i8 %sub, %y + ret i8 %add +} + +define i8 @tgt_sub_add(i8 %x, i8 %y) { + ret i8 %x +} +``` + +### Use generic values in proofs + +Proofs should operate on generic values, rather than specific constants, to the degree that this is possible. + +For example, if we want to fold `X s/ C s< X` to `X s> 0`, the following would +be a *bad* proof: + +```llvm +; Don't do this! +define i1 @src(i8 %x) { + %div = sdiv i8 %x, 123 + %cmp = icmp slt i8 %div, %x + ret i1 %cmp +} + +define i1 @tgt(i8 %x) { + %cmp = icmp sgt i8 %x, 0 + ret i1 %cmp +} +``` + +This is because it only proves that the transform is correct for the specific +constant 123. Maybe there are some constants for which the transform is +incorrect? + +The correct way to write this proof is as follows +([online](https://alive2.llvm.org/ce/z/acjwb6)): + +```llvm +define i1 @src(i8 %x, i8 %C) { + %precond = icmp ne i8 %C, 1 + call void @llvm.assume(i1 %precond) + %div = sdiv i8 %x, %C + %cmp = icmp slt i8 %div, %x + ret i1 %cmp +} + +define i1 @tgt(i8 %x, i8 %C) { + %cmp = icmp sgt i8 %x, 0 + ret i1 %cmp +} +``` + +Note that the `@llvm.assume` intrinsic is used to specify pre-conditions for +the transform. In this case, the proof will fail unless we specify `C != 1` as +a pre-condition. + +It should be emphasized that there is, in general, no expectation that the +IR in the proofs will be transformed by the implemented fold. In the above +example, the transform would only apply if `%C` is actually a constant, but we +need to use non-constants in the proof. + +### Common pre-conditions + +Here are some examples of common preconditions. + +```llvm +; %x is non-negative: +%nonneg = icmp sgt i8 %x, -1 +call void @llvm.assume(i1 %nonneg) + +; %x is a power of two: +%ctpop = call i8 @llvm.ctpop.i8(i8 %x) +%pow2 = icmp eq i8 %x, 1 +call void @llvm.assume(i1 %pow2) + +; %x is a power of two or zero: +%ctpop = call i8 @llvm.ctpop.i8(i8 %x) +%pow2orzero = icmp ult i8 %x, 2 +call void @llvm.assume(i1 %pow2orzero) + +; Adding %x and %y does not overflow in a signed sense: +%wo = call { i8, i1 } @llvm.sadd.with.overflow(i8 %x, i8 %y) +%ov = extractvalue { i8, i1 } %wo, 1 +%ov.not = xor i1 %ov, true +call void @llvm.assume(i1 %ov.not) +``` + +### Timeouts + +Alive2 proofs will sometimes produce a timeout with the following message: + +``` +Alive2 timed out while processing your query. +There are a few things you can try: + +- remove extraneous instructions, if any + +- reduce variable widths, for example to i16, i8, or i4 + +- add the --disable-undef-input command line flag, which + allows Alive2 to assume that arguments to your IR are not + undef. This is, in general, unsound: it can cause Alive2 + to miss bugs. +``` + +This is good advice, follow it! + +Reducing the bitwidth usually helps. For floating point numbers, you can use +the `half` type for bitwidth reduction purposes. For pointers, you can reduce +the bitwidth by specifying a custom data layout: + +```llvm +; For 16-bit pointers +target datalayout = "p:16:16" +``` + +If reducing the bitwidth does not help, try `-disable-undef-input`. This will +often significantly improve performance, but also implies that the correctness +of the transform with `undef` values is no longer verified. This is usually +fine if the transform does not increase the number of uses of any value. + +Finally, it's possible to build alive2 locally and use `-smt-to=<m>` to verify +the proof with a larger timeout. If you don't want to do this (or it still +does not work), please submit the proof you have despite the timeout. + +## Implementation + +### Real-world usefulness + +There is a very large number of transforms that *could* be implemented, but +only a tiny fraction of them are useful for real-world code. + +Transforms that do not have real-world usefulness provide *negative* value to +the LLVM project, by taking up valuable reviewer time, increasing code +complexity and increasing compile-time overhead. + +We do not require explicit proof of real-world usefulness for every transform +-- in most cases the usefulness is fairly "obvious". However, the question may +come up for complex or unusual folds. Keep this in mind when chosing what you +work on. + +In particular, fixes for fuzzer-generated missed optimization reports will +likely be rejected if there is no evidence of real-world usefulness. + +### Pick the correct optimization pass + +There are a number of passes and utilities in the InstCombine family, and it +is important to pick the right place when implementing a fold. + + * `ConstantFolding`: For folding instructions with constant arguments to a constant. (Mainly relevant for intrinsics.) + * `ValueTracking`: For analyzing instructions, e.g. for known bits, non-zero, etc. Tests should usually use `-passes=instsimplify`. + * `InstructionSimplify`: For folds that do not create new instructions (either fold to existing value or constant). + * `InstCombine`: For folds that create or modify instructions. + * `AggressiveInstCombine`: For folds that are expensive, or violate InstCombine requirements. + * `VectorCombine`: For folds of vector operations that require target-dependent cost-modelling. + +Sometimes, folds that logically belong in InstSimplify are placed in InstCombine instead, for example because they are too expensive, or because they are structurally simpler to implement in InstCombine. + +For example, if a fold produces new instructions in some cases but returns an existing value in others, it may be preferable to keep all cases in InstCombine, rather than trying to split them among InstCombine and InstSimplify. + +### Canonicalization and target-independence + +InstCombine is a target-independent canonicalization pass. This means that it +tries to bring IR into a "canonical form" that other optimizations (both inside +and outside of InstCombine) can rely on. For this reason, the chosen canonical +form needs to be the same for all targets, and not depend on target-specific +cost modelling. + +In many cases, "canonicalization" and "optimization" coincide. For example, if +we convert `x * 2` into `x << 1`, this both makes the IR more canonical +(because there is now only one way to express the same operation, rather than +two) and faster (because shifts will usually have lower latency than +multiplies). + +However, there are also canonicalizations that don't serve any direct +optimization purpose. For example, InstCombine will canonicalize non-strict +predicates like `ule` to strict predicates like `ult`. `icmp ule i8 %x, 7` +becomes `icmp ult i8 %x, 8`. This is not an optimization in any meaningful +sense, but it does reduce the number of cases that other transforms need to +handle. + +If some canonicalization is not profitable for a specific target, then a reverse +transform needs to be added in the backend. Patches to disable specific +InstCombine transforms on certain targets, or to drive them using +target-specific cost-modelling, **will not be accepted**. The only permitted +target-dependence is on DataLayout and TargetLibraryInfo. + +The use of TargetTransformInfo is only allowed for hooks for target-specific +intrinsics, such as `TargetTransformInfo::instCombineIntrinsic()`. These are +already inherently target-dependent anyway. + +For vector-specific transforms that require cost-modelling, the VectorCombine +pass can be used instead. In very rare circumstances, if there are no other +alternatives, target-dependent transforms may be accepted into +AggressiveInstCombine. + +### PatternMatch + +Many transforms make use of the matching infrastructure defined in +[PatternMatch.h](https://github.com/llvm/llvm-project/blame/main/llvm/include/llvm/IR/PatternMatch.h). + +Here is a typical usage example: + +``` +// Fold (A - B) + B and B + (A - B) to A. +Value *A, *B; +if (match(V, m_c_Add(m_Sub(m_Value(A), m_Value(B)), m_Deferred(B)))) + return A; +``` + +And another: + +``` +// Fold A + C1 == C2 to A == C1+C2 +Value *A; +if (match(V, m_ICmp(Pred, m_Add(m_Value(A), m_APInt(C1)), m_APInt(C2))) && + ICmpInst::isEquality(Pred)) + return Builder.CreateICmp(Pred, A, + ConstantInt::get(A->getType(), *C1 + *C2)); +``` + +Some common matchers are: + + * `m_Value(A)`: Match any value and write it into `Value *A`. + * `m_Specific(A)`: Check that the operand equals A. Use this if A is + assigned **outside** the pattern. + * `m_Deferred(A)`: Check that the operand equals A. Use this if A is + assigned **inside** the pattern, for example via `m_Value(A)`. + * `m_APInt(C)`: Match a scalar integer constant or splat vector constant into + `const APInt *C`. Does not permit undef/poison values. + * `m_ImmConstant(C)`: Match any non-constant-expression constant into + `Constant *C`. + * `m_Constant(C)`: Match any constant into `Constant *C`. Don't use this unless + you know what you're doing. + * `m_Add(M1, M2)`, `m_Sub(M1, M2)`, etc: Match an add/sub/etc where the first + operand matches M1 and the second M2. + * `m_c_Add(M1, M2)`, etc: Match an add commutatively. The operands must match + either M1 and M2 or M2 and M1. Most instruction matchers have a commutative + variant. + * `m_ICmp(Pred, M1, M2)` and `m_c_ICmp(Pred, M1, M2)`: Match an icmp, writing + the predicate into `IcmpInst::Predicate Pred`. If the commutative version + is used, and the operands match in order M2, M1, then `Pred` will be the + swapped predicate. + * `m_OneUse(M)`: Check that the value only has one use, and also matches M. + For example `m_OneUse(m_Add(...))`. See the next section for more + information. + +See the header for the full list of available matchers. + +### InstCombine APIs + +InstCombine transforms are handled by `visitXYZ()` methods, where XYZ +corresponds to the root instruction of your transform. If the outermost +instruction of the pattern you are matching is an icmp, the fold will be +located somewhere inside `visitICmpInst()`. + +The return value of the visit method is an instruction. You can either return +a new instruction, in which case it will be inserted before the old one, and +uses of the old one will be replaced by it. Or you can return the original +instruction to indicate that *some* kind of change has been made. Finally, a +nullptr return value indicates that no change occurred. + +For example, if your transform produces a single new icmp instruction, you could +write the following: + +``` +if (...) + return new ICmpInst(Pred, X, Y); +``` + +In this case the main InstCombine loop takes care of inserting the instruction +and replacing uses of the old instruction. + +Alternatively, you can also write it like this: + +``` +if (...) + return replaceInstUsesWith(OrigI, Builder.CreateICmp(Pred, X, Y)); +``` + +In this case `IRBuilder` will insert the instruction and `replaceInstUsesWith()` +will replace the uses of the old instruction, and return it to indicate that +a change occurred. + +Both forms are equivalent, and you can use whichever is more convenient in +context. For example, it's common that folds are inside helper functions that +return `Value *` and then `replaceInstUsesWith()` is invoked on the result of +that helper. + +InstCombine makes use of a worklist, which needs to be correctly updated during +transforms. This usually happens automatically, but there are some things to +keep in mind: + + * Don't use the `Value::replaceAllUsesWith()` API. Use InstCombine's + `replaceInstUsesWith()` helper instead. + * Don't use the `Instruction::eraseFromParent()` API. Use InstCombine's + `eraseInstFromFunction()` helper instead. (Explicitly erasing instruction + is usually not necessary, as side-effect free instructions without users + are automatically removed.) + * Apart from the "directly return an instruction" pattern above, use IRBUilder + to create all instruction. Do not manually create and insert them. + * When replacing operands or uses of instructions, use `replaceOperand()` + and `replaceUse()` instead of `setOperand()`. + +### Multi-use handling + +Transforms should usually not increase the total number of instructions. This +is not a hard requirement: For example, it is usually worthwhile to replace a +single division instruction with multiple other instructions. + +For example, if you have a transform that replaces two instructions, with two +other instructions, this is (usually) only profitable if *both* the original +instructions can be removed. To ensure that both instructions are removed, you +need to add a one-use check for the inner instruction. + +One-use checks can be performed using the `m_OneUse()` matcher, or the +`V->hasOneUse()` method. + +### Generalization + +Transforms can both be too specific (only handling some odd subset of patterns, +leading to unexpected optimization cliffs) and too general (introducing +complexity to handle cases with no real-world relevance). The right level of +generality is quite subjective, so this section only provides some broad +guidelines. + + * Avoid transforms that are hardcoded to specific constants. Try to figure + out what the general rule for arbitrary constants is. + * Add handling for conjugate patterns. For example, if you implement a fold + for `icmp eq`, you almost certainly also want to support `icmp ne`, with the + inverse result. Similarly, if you implement a pattern for `and` of `icmp`s, + you should also handle the de-Morgan conjugate using `or`. + * Handle non-splat vector constants if doing so is free, but do not add + handling for them if it adds any additional complexity to the code. + * Do not handle non-canonical patterns, unless there is a specific motivation + to do so. For example, it may sometimes be worthwhile to handle a pattern + that would normally be converted into a different canonical form, but can + still occur in multi-use scenarios. This is fine to do if there is specific + real-world motivation, but you should not go out of your way to do this + otherwise. + * Sometimes the motivating pattern uses a constant value with certain + properties, but the fold can be generalized to non-constant values by making + use of ValueTracking queries. Whether this makes sense depends on the case, + but it's usually a good idea to only handle the constant pattern first, and + then generalize later if it seems useful. diff --git a/llvm/docs/InstrProfileFormat.rst b/llvm/docs/InstrProfileFormat.rst index 2069b87a245a130dfaef50cb7b71ec2bae634d1e..3b33c09f8c7a2f4cf3aa7c8a2400c9ec1ea35c20 100644 --- a/llvm/docs/InstrProfileFormat.rst +++ b/llvm/docs/InstrProfileFormat.rst @@ -150,6 +150,13 @@ Header Records the in-memory address of name section. Not used except for raw profile reader error checking. +``NumVTables`` + Records the number of instrumented vtable entries in the binary. Used for + `type profiling`_. + +``VNamesSize`` + Records the byte size in the virtual table names section. Used for `type profiling`_. + ``ValueKindLast`` Records the number of value kinds. Macro `VALUE_PROF_KIND`_ defines the value kinds with a description of the kind. @@ -323,6 +330,8 @@ for the design. .. _`Modified Condition/Decision Coverage`: https://en.wikipedia.org/wiki/Modified_condition/decision_coverage .. _`Bitmap RFC`: https://discourse.llvm.org/t/rfc-source-based-mc-dc-code-coverage/59244 +.. _`function names`: + Names ^^^^^^ @@ -333,6 +342,37 @@ Function names serve as keys in the PGO data hash table when raw profiles are converted into indexed profiles. They are also crucial for ``llvm-profdata`` to show the profiles in a human-readable way. +Virtual Table Profile Data +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This section is used for `type profiling`_. Each entry corresponds to one virtual +table and is defined by the following C++ struct + +.. code-block:: c++ + + struct VTableProfData { + // The start address of the vtable, collected at runtime. + uint64_t StartAddress; + // The byte size of the vtable. `StartAddress` and `ByteSize` specifies an address range to look up. + uint32_t ByteSize; + // The hash of vtable's (PGO) name + uint64_t MD5HashOfName; + }; + +At profile use time, the compiler looks up a profiled address in the sorted vtable +address ranges and maps the address to a specific vtable through hashed name. + +Virtual Table Names +^^^^^^^^^^^^^^^^^^^^ + +This section is similar to `function names`_ section above, except it contains the PGO +names of profiled virtual tables. It's a standalone section such that raw profile +readers could directly find each name set by accessing the corresponding profile +data section. + +This section is stored in raw profiles such that `llvm-profdata` could show the +profiles in a human-readable way. + Value Profile Data ^^^^^^^^^^^^^^^^^^^^ @@ -360,6 +400,10 @@ profiles generated by older tools or compilers. General Storage Layout ----------------------- +The ASCII art depicts the general storage layout of indexed profiles. +Specifically, the indexed profile header describes the byte offset of individual +payload sections. + :: +-----------------------+---+ @@ -369,55 +413,49 @@ General Storage Layout +-----------------------+ | | HashType | H +-----------------------+ E - +-------| HashOffset | A - | +-----------------------+ D - +-----------| MemProfOffset | E - | | +-----------------------+ R - | | +--| BinaryIdOffset | | - | | | +-----------------------+ | - +---------------| TemporalProf- | | - | | | | | TracesOffset | | - | | | | +-----------------------+---+ - | | | | | Profile Summary | | - | | | | +-----------------------+ P - | | +------>| Function data | A - | | | +-----------------------+ Y - | +---------->| MemProf profile data | L - | | +-----------------------+ O - | +->| Binary Ids | A + | Byte Offset | A + +------ | of section A | D + | +-----------------------+ E + | | Byte Of fset | R + +-----------| of section B | | + | | +-----------------------+ | + | | | ... | | + | | +-----------------------+ | + | | | Byte Offset | | + +---------------| of section Z | | + | | | +-----------------------+---+ + | | | | Profile Summary | | + | | | +-----------------------+ P + | | +------>| Section A | A + | | +-----------------------+ Y + | +---------->| Section B | L + | +-----------------------+ O + | | ... | A | +-----------------------+ D - +-------------->| Temporal profiles | | + +-------------->| Section Z | | +-----------------------+---+ -Header --------- +.. note:: -``Magic`` - The purpose of the magic number is to be able to tell if the profile is an - indexed profile. + Profile summary section is at the beginning of payload. It's right after the + header so its position is implicitly known after reading the header. -``Version`` - Similar to raw profile version, the lower 32 bits specify the version of the - indexed profile and the most significant 32 bits are reserved to specify the - variant types of the profile. +Header +-------- -``HashType`` - The hashing scheme for on-disk hash table keys. Only MD5 hashing is used as of - writing. +The `Header struct`_ is the source of truth and struct fields should explain +what's in the header. At a high level, `*Offset` fields record section byte +offsets, which are used by readers to locate interesting sections and skip +uninteresting ones. -``HashOffset`` - An on-disk hash table stores the per-function profile records. This field records - the offset of this hash table's metadata (i.e., the number of buckets and - entries), which follows right after the payload of the entire hash table. +.. note:: -``MemProfOffset`` - Records the byte offset of MemProf profiling data. + To maintain backward compatibility of the indexed profiles, existing fields + shouldn't be deleted from struct definition; the field order shouldn't be + modified. New fields should be appended. -``BinaryIdOffset`` - Records the byte offset of binary id sections. +.. _`Header struct`: https://github.com/llvm/llvm-project/blob/1a2960bab6381f2b288328e2371829b460ac020c/llvm/include/llvm/ProfileData/InstrProf.h#L1053-L1080 -``TemporalProfTracesOffset`` - Records the byte offset of temporal profiles. Payload Sections ------------------ @@ -428,6 +466,8 @@ This section is right after profile header. It stores the serialized profile summary. For context-sensitive IR-based instrumentation PGO, this section stores an additional profile summary corresponding to the context-sensitive profiles. +.. _`function data`: + Function data ^^^^^^^^^^^^^^^^^^ This section stores functions and their profiling data as an on-disk hash table. @@ -455,6 +495,16 @@ Temporal Profile Traces The section is used to carry on temporal profile information from raw profiles. See `temporal profiling`_ for the design. +Virtual Table Names +^^^^^^^^^^^^^^^^^^^^ +This section is used to store the names of vtables from raw profile in the indexed +profile. + +Unlike function names which are stored as keys of `function data`_ hash table, +vtable names need to be stored in a standalone section in indexed profiles. +This way, `llvm-profdata` could show the profiled vtable information in a +human-readable way. + Profile Data Usage ======================================= @@ -478,3 +528,4 @@ based profile data. For supported usages, check out `llvm-profdata documentation .. _`single-byte counters`: https://discourse.llvm.org/t/rfc-single-byte-counters-for-source-based-code-coverage/75685 .. _`binary profile correlation`: https://discourse.llvm.org/t/rfc-add-binary-profile-correlation-to-not-load-profile-metadata-sections-into-memory-at-runtime/74565 .. _`binary id`: https://lists.llvm.org/pipermail/llvm-dev/2021-June/151154.html +.. _`type profiling`: https://discourse.llvm.org/t/rfc-dynamic-type-profiling-and-optimizations-in-llvm/74600 diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 939a90be27936940ed9ba6d93f885632a0f02754..1d4ff5238226c2be69519ddd45cb24d53448eddc 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -2571,7 +2571,7 @@ are grouped into a single :ref:`attribute group <attrgrp>`. ``sanitize_memtag`` This attribute indicates that the global variable should have AArch64 memory tags (MTE) instrumentation applied to it. This attribute causes the - suppression of certain optimisations, like GlobalMerge, as well as ensuring + suppression of certain optimizations, like GlobalMerge, as well as ensuring extra directives are emitted in the assembly and extra bits of metadata are placed in the object file so that the linker can ensure the accesses are protected by MTE. This attribute is added by clang when @@ -3638,7 +3638,7 @@ floating-point transformations. ``contract`` Allow floating-point contraction (e.g. fusing a multiply followed by an - addition into a fused multiply-and-add). This does not enable reassociating + addition into a fused multiply-and-add). This does not enable reassociation to form arbitrary contractions. For example, ``(a*b) + (c*d) + e`` can not be transformed into ``(a*b) + ((c*d) + e)`` to create two fma operations. @@ -5622,34 +5622,106 @@ occurs on. Metadata ======== -LLVM IR allows metadata to be attached to instructions and global objects in the -program that can convey extra information about the code to the optimizers and -code generator. One example application of metadata is source-level -debug information. There are two metadata primitives: strings and nodes. +LLVM IR allows metadata to be attached to instructions and global objects in +the program that can convey extra information about the code to the optimizers +and code generator. -Metadata does not have a type, and is not a value. If referenced from a -``call`` instruction, it uses the ``metadata`` type. +There are two metadata primitives: strings and nodes. There are +also specialized nodes which have a distinguished name and a set of named +arguments. + +.. note:: + + One example application of metadata is source-level debug information, + which is currently the only user of specialized nodes. + +Metadata does not have a type, and is not a value. + +A value of non-\ ``metadata`` type can be used in a metadata context using the +syntax '``<type> <value>``'. + +All other metadata is identified in syntax as starting with an exclamation +point ('``!``'). + +Metadata may be used in the following value contexts by using the ``metadata`` +type: + +- Arguments to certain intrinsic functions, as described in their specification. +- Arguments to the ``catchpad``/``cleanuppad`` instructions. + +.. note:: + + Metadata can be "wrapped" in a ``MetadataAsValue`` so it can be referenced + in a value context: ``MetadataAsValue`` is-a ``Value``. + + A typed value can be "wrapped" in ``ValueAsMetadata`` so it can be + referenced in a metadata context: ``ValueAsMetadata`` is-a ``Metadata``. + + There is no explicit syntax for a ``ValueAsMetadata``, and instead + the fact that a type identifier cannot begin with an exclamation point + is used to resolve ambiguity. + + A ``metadata`` type implies a ``MetadataAsValue``, and when followed with a + '``<type> <value>``' pair it wraps the typed value in a ``ValueAsMetadata``. + + For example, the first argument + to this call is a ``MetadataAsValue(ValueAsMetadata(Value))``: + + .. code-block:: llvm + + call void @llvm.foo(metadata i32 1) + + Whereas the first argument to this call is a ``MetadataAsValue(MDNode)``: -All metadata are identified in syntax by an exclamation point ('``!``'). + .. code-block:: llvm + + call void @llvm.foo(metadata !0) + + The first element of this ``MDTuple`` is a ``MDNode``: + + .. code-block:: llvm + + !{!0} + + And the first element of this ``MDTuple`` is a ``ValueAsMetadata(Value)``: + + .. code-block:: llvm + + !{i32 1} .. _metadata-string: -Metadata Nodes and Metadata Strings ------------------------------------ +Metadata Strings (``MDString``) +------------------------------- + +.. FIXME Either fix all references to "MDString" in the docs, or make that + identifier a formal part of the document. A metadata string is a string surrounded by double quotes. It can contain any character by escaping non-printable characters with "``\xx``" where "``xx``" is the two digit hex code. For example: "``!"test\00"``". -Metadata nodes are represented with notation similar to structure -constants (a comma separated list of elements, surrounded by braces and -preceded by an exclamation point). Metadata nodes can have any values as +.. note:: + + A metadata string is metadata, but is not a metadata node. + +.. _metadata-node: + +Metadata Nodes (``MDNode``) +--------------------------- + +.. FIXME Either fix all references to "MDNode" in the docs, or make that + identifier a formal part of the document. + +Metadata tuples are represented with notation similar to structure +constants: a comma separated list of elements, surrounded by braces and +preceded by an exclamation point. Metadata nodes can have any values as their operand. For example: .. code-block:: llvm - !{ !"test\00", i32 10} + !{!"test\00", i32 10} Metadata nodes that aren't uniqued use the ``distinct`` keyword. For example: @@ -5676,6 +5748,12 @@ intrinsic is using three metadata arguments: call void @llvm.dbg.value(metadata !24, metadata !25, metadata !26) + +.. FIXME Attachments cannot be ValueAsMetadata, but we don't have a + particularly clear way to refer to ValueAsMetadata without getting into + implementation details. Ideally the restriction would be explicit somewhere, + though? + Metadata can be attached to an instruction. Here metadata ``!21`` is attached to the ``add`` instruction using the ``!dbg`` identifier: @@ -6309,7 +6387,7 @@ valid debug intrinsic. !5 = !DIExpression(DW_OP_constu, 42, DW_OP_stack_value) DIAssignID -"""""""""""" +"""""""""" ``DIAssignID`` nodes have no operands and are always distinct. They are used to link together `@llvm.dbg.assign` intrinsics (:ref:`debug @@ -6324,7 +6402,13 @@ Assignment Tracking <AssignmentTracking.html>`_ for more info. !2 = distinct !DIAssignID() DIArgList -"""""""""""" +""""""""" + +.. FIXME In the implementation this is not a "node", but as it can only appear + inline in a function context that distinction isn't observable anyway. Even + if it is not required, it would be nice to be more clear about what is a + "node", and what that actually means. The names in the implementation could + also be updated to mirror whatever we decide here. ``DIArgList`` nodes hold a list of constant or SSA value references. These are used in :ref:`debug intrinsics<dbg_intrinsics>` (currently only in @@ -6340,7 +6424,7 @@ inlined, and cannot appear in named metadata. metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus)) DIFlags -""""""""""""""" +""""""" These flags encode various properties of DINodes. @@ -6416,6 +6500,46 @@ within the file where the label is declared. !2 = !DILabel(scope: !0, name: "foo", file: !1, line: 7) +DICommonBlock +""""""""""""" + +``DICommonBlock`` nodes represent Fortran common blocks. The ``scope:`` field +is mandatory and points to a :ref:`DILexicalBlockFile`, a +:ref:`DILexicalBlock`, or a :ref:`DISubprogram`. The ``declaration:``, +``name:``, ``file:``, and ``line:`` fields are optional. + +DIModule +"""""""" + +``DIModule`` nodes represent a source language module, for example, a Clang +module, or a Fortran module. The ``scope:`` field is mandatory and points to a +:ref:`DILexicalBlockFile`, a :ref:`DILexicalBlock`, or a :ref:`DISubprogram`. +The ``name:`` field is mandatory. The ``configMacros:``, ``includePath:``, +``apinotes:``, ``file:``, ``line:``, and ``isDecl:`` fields are optional. + +DIStringType +"""""""""""" + +``DIStringType`` nodes represent a Fortran ``CHARACTER(n)`` type, with a +dynamic length and location encoded as an expression. +The ``tag:`` field is optional and defaults to ``DW_TAG_string_type``. The ``name:``, +``stringLength:``, ``stringLengthExpression``, ``stringLocationExpression:``, +``size:``, ``align:``, and ``encoding:`` fields are optional. + +If not present, the ``size:`` and ``align:`` fields default to the value zero. + +The length in bits of the string is specified by the first of the following +fields present: + +- ``stringLength:``, which points to a ``DIVariable`` whose value is the string + length in bits. +- ``stringLengthExpression:``, which points to a ``DIExpression`` which + computes the length in bits. +- ``size``, which contains the literal length in bits. + +The ``stringLocationExpression:`` points to a ``DIExpression`` which describes +the "data location" of the string object, if present. + '``tbaa``' Metadata ^^^^^^^^^^^^^^^^^^^ @@ -7365,7 +7489,7 @@ matches the ``llvm.loop.parallel_accesses`` list. If all memory-accessing instructions in a loop have ``llvm.access.group`` metadata that each refer to one of the access groups of a loop's ``llvm.loop.parallel_accesses`` metadata, then the -loop has no loop carried memory dependences and is considered to be a +loop has no loop carried memory dependencies and is considered to be a parallel loop. Note that if not all memory access instructions belong to an access @@ -11049,9 +11173,10 @@ Syntax: :: - <result> = getelementptr <ty>, ptr <ptrval>{, [inrange] <ty> <idx>}* - <result> = getelementptr inbounds <ty>, ptr <ptrval>{, [inrange] <ty> <idx>}* - <result> = getelementptr <ty>, <N x ptr> <ptrval>, [inrange] <vector index type> <idx> + <result> = getelementptr <ty>, ptr <ptrval>{, <ty> <idx>}* + <result> = getelementptr inbounds <ty>, ptr <ptrval>{, <ty> <idx>}* + <result> = getelementptr inrange(S,E) <ty>, ptr <ptrval>{, <ty> <idx>}* + <result> = getelementptr <ty>, <N x ptr> <ptrval>, <vector index type> <idx> Overview: """"""""" @@ -11196,16 +11321,15 @@ These rules are based on the assumption that no allocated object may cross the unsigned address space boundary, and no allocated object may be larger than half the pointer index type space. -If the ``inrange`` keyword is present before any index, loading from or +If the ``inrange(Start, End)`` attribute is present, loading from or storing to any pointer derived from the ``getelementptr`` has undefined -behavior if the load or store would access memory outside of the bounds of -the element selected by the index marked as ``inrange``. The result of a -pointer comparison or ``ptrtoint`` (including ``ptrtoint``-like operations +behavior if the load or store would access memory outside the half-open range +``[Start, End)`` from the ``getelementptr`` expression result. The result of +a pointer comparison or ``ptrtoint`` (including ``ptrtoint``-like operations involving memory) involving a pointer derived from a ``getelementptr`` with the ``inrange`` keyword is undefined, with the exception of comparisons -in the case where both operands are in the range of the element selected -by the ``inrange`` keyword, inclusive of the address one past the end of -that element. Note that the ``inrange`` keyword is currently only allowed +in the case where both operands are in the closed range ``[Start, End]``. +Note that the ``inrange`` keyword is currently only allowed in constant ``getelementptr`` expressions. The getelementptr instruction is often confusing. For some more insight @@ -11295,6 +11419,9 @@ Syntax: :: <result> = trunc <ty> <value> to <ty2> ; yields ty2 + <result> = trunc nsw <ty> <value> to <ty2> ; yields ty2 + <result> = trunc nuw <ty> <value> to <ty2> ; yields ty2 + <result> = trunc nuw nsw <ty> <value> to <ty2> ; yields ty2 Overview: """"""""" @@ -11318,6 +11445,11 @@ and converts the remaining bits to ``ty2``. Since the source size must be larger than the destination size, ``trunc`` cannot be a *no-op cast*. It will always truncate bits. +If the ``nuw`` keyword is present, and any of the truncated bits are zero, +the result is a :ref:`poison value <poisonvalues>`. If the ``nsw`` keyword +is present, and any of the truncated bits are not the same as the top bit +of the truncation result, the result is a :ref:`poison value <poisonvalues>`. + Example: """""""" @@ -12815,10 +12947,11 @@ Variable argument support is defined in LLVM with the functions. These functions are related to the similarly named macros defined in the ``<stdarg.h>`` header file. -All of these functions operate on arguments that use a target-specific +All of these functions take as arguments pointers to a target-specific value type "``va_list``". The LLVM assembly language reference manual does not define what this type is, so all transformations should be -prepared to handle these functions regardless of the type used. +prepared to handle these functions regardless of the type used. The intrinsics +are overloaded, and can be used for pointers to different address spaces. This example shows how the :ref:`va_arg <i_va_arg>` instruction and the variable argument handling intrinsic functions are used. @@ -12835,24 +12968,24 @@ variable argument handling intrinsic functions are used. define i32 @test(i32 %X, ...) { ; Initialize variable argument processing %ap = alloca %struct.va_list - call void @llvm.va_start(ptr %ap) + call void @llvm.va_start.p0(ptr %ap) ; Read a single integer argument %tmp = va_arg ptr %ap, i32 ; Demonstrate usage of llvm.va_copy and llvm.va_end %aq = alloca ptr - call void @llvm.va_copy(ptr %aq, ptr %ap) - call void @llvm.va_end(ptr %aq) + call void @llvm.va_copy.p0(ptr %aq, ptr %ap) + call void @llvm.va_end.p0(ptr %aq) ; Stop processing of arguments. - call void @llvm.va_end(ptr %ap) + call void @llvm.va_end.p0(ptr %ap) ret i32 %tmp } - declare void @llvm.va_start(ptr) - declare void @llvm.va_copy(ptr, ptr) - declare void @llvm.va_end(ptr) + declare void @llvm.va_start.p0(ptr) + declare void @llvm.va_copy.p0(ptr, ptr) + declare void @llvm.va_end.p0(ptr) .. _int_va_start: @@ -12864,7 +12997,8 @@ Syntax: :: - declare void @llvm.va_start(ptr <arglist>) + declare void @llvm.va_start.p0(ptr <arglist>) + declare void @llvm.va_start.p5(ptr addrspace(5) <arglist>) Overview: """"""""" @@ -12896,7 +13030,8 @@ Syntax: :: - declare void @llvm.va_end(ptr <arglist>) + declare void @llvm.va_end.p0(ptr <arglist>) + declare void @llvm.va_end.p5(ptr addrspace(5) <arglist>) Overview: """"""""" @@ -12929,7 +13064,8 @@ Syntax: :: - declare void @llvm.va_copy(ptr <destarglist>, ptr <srcarglist>) + declare void @llvm.va_copy.p0(ptr <destarglist>, ptr <srcarglist>) + declare void @llvm.va_copy.p5(ptr addrspace(5) <destarglist>, ptr addrspace(5) <srcarglist>) Overview: """"""""" @@ -12942,6 +13078,7 @@ Arguments: The first argument is a pointer to a ``va_list`` element to initialize. The second argument is a pointer to a ``va_list`` element to copy from. +The address spaces of the two arguments must match. Semantics: """""""""" @@ -13577,12 +13714,12 @@ Overview: """"""""" The '``llvm.seh.try.begin``' and '``llvm.seh.try.end``' intrinsics mark -the boundary of a _try region for Windows SEH Asynchrous Exception Handling. +the boundary of a _try region for Windows SEH Asynchronous Exception Handling. Semantics: """""""""" -When a C-function is compiled with Windows SEH Asynchrous Exception option, +When a C-function is compiled with Windows SEH Asynchronous Exception option, -feh_asynch (aka MSVC -EHa), these two intrinsics are injected to mark _try boundary and to prevent potential exceptions from being moved across boundary. Any set of operations can then be confined to the region by reading their leaf @@ -13603,7 +13740,7 @@ Overview: """"""""" The '``llvm.seh.scope.begin``' and '``llvm.seh.scope.end``' intrinsics mark -the boundary of a CPP object lifetime for Windows SEH Asynchrous Exception +the boundary of a CPP object lifetime for Windows SEH Asynchronous Exception Handling (MSVC option -EHa). Semantics: @@ -14574,6 +14711,63 @@ The arguments (``%a`` and ``%b``) may be of any integer type or a vector with integer element type. The argument types must match each other, and the return type must match the argument type. +.. _int_scmp: + +'``llvm.scmp.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``@llvm.scmp`` on any +integer bit width or any vector of integer elements. + +:: + + declare i2 @llvm.scmp.i2.i32(i32 %a, i32 %b) + declare <4 x i32> @llvm.scmp.v4i32.v4i32(<4 x i32> %a, <4 x i32> %b) + +Overview: +""""""""" + +Return ``-1`` if ``%a`` is signed less than ``%b``, ``0`` if they are equal, and +``1`` if ``%a`` is signed greater than ``%b``. Vector intrinsics operate on a per-element basis. + +Arguments: +"""""""""" + +The arguments (``%a`` and ``%b``) may be of any integer type or a vector with +integer element type. The argument types must match each other, and the return +type must be at least as wide as ``i2``, to hold the three possible return values. + +.. _int_ucmp: + +'``llvm.ucmp.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``@llvm.ucmp`` on any +integer bit width or any vector of integer elements. + +:: + + declare i2 @llvm.ucmp.i2.i32(i32 %a, i32 %b) + declare <4 x i32> @llvm.ucmp.v4i32.v4i32(<4 x i32> %a, <4 x i32> %b) + +Overview: +""""""""" + +Return ``-1`` if ``%a`` is unsigned less than ``%b``, ``0`` if they are equal, and +``1`` if ``%a`` is unsigned greater than ``%b``. Vector intrinsics operate on a per-element basis. + +Arguments: +"""""""""" + +The arguments (``%a`` and ``%b``) may be of any integer type or a vector with +integer element type. The argument types must match each other, and the return +type must be at least as wide as ``i2``, to hold the three possible return values. .. _int_memcpy: @@ -17656,7 +17850,7 @@ Examples %res = call i4 @llvm.udiv.fix.sat.i4(i4 8, i4 2, i32 2) ; %res = 15 (2 / 0.5 = 4 => 3.75) -Specialised Arithmetic Intrinsics +Specialized Arithmetic Intrinsics --------------------------------- .. _i_intr_llvm_canonicalize: @@ -17980,9 +18174,9 @@ The '``llvm.loop.decrement.reg.*``' intrinsics do an integer ``SUB`` of its two operands, which is not allowed to wrap. They return the remaining number of iterations still to be executed, and can be used together with a ``PHI``, ``ICMP`` and ``BR`` to control the number of loop iterations executed. Any -optimisations are allowed to treat it is a ``SUB``, and it is supported by +optimizations are allowed to treat it is a ``SUB``, and it is supported by SCEV, so it's the backends responsibility to handle cases where it may be -optimised. These intrinsics are marked as ``IntrNoDuplicate`` to avoid +optimized. These intrinsics are marked as ``IntrNoDuplicate`` to avoid optimizers duplicating these instructions. @@ -18684,7 +18878,7 @@ Arguments: The first argument is the vector to be counted. This argument must be a vector with integer element type. The return type must also be an integer type which is wide enough to hold the maximum number of elements of the source vector. The -behaviour of this intrinsic is undefined if the return type is not wide enough +behavior of this intrinsic is undefined if the return type is not wide enough for the number of elements in the input vector. The second argument is a constant flag that indicates whether the intrinsic @@ -21969,7 +22163,7 @@ and ``evl2`` are unsigned integers indicating the explicit vector lengths of ``vec1`` and ``vec2`` respectively. ``imm``, ``evl1`` and ``evl2`` should respect the following constraints: ``-evl1 <= imm < evl1``, ``0 <= evl1 <= VL`` and ``0 <= evl2 <= VL``, where ``VL`` is the runtime vector factor. If these -constraints are not satisfied the intrinsic has undefined behaviour. +constraints are not satisfied the intrinsic has undefined behavior. Semantics: """""""""" @@ -24385,7 +24579,7 @@ operand. The pointer alignment defaults to 1. Semantics: """""""""" -The '``llvm.masked.compressstore``' intrinsic is designed for compressing data in memory. It allows to collect elements from possibly non-adjacent lanes of a vector and store them contiguously in memory in one IR operation. It is useful for targets that support compressing store operations and allows vectorizing loops with cross-iteration dependences like in the following example: +The '``llvm.masked.compressstore``' intrinsic is designed for compressing data in memory. It allows to collect elements from possibly non-adjacent lanes of a vector and store them contiguously in memory in one IR operation. It is useful for targets that support compressing store operations and allows vectorizing loops with cross-iteration dependencies like in the following example: .. code-block:: c @@ -26527,7 +26721,7 @@ Semantics: The '``llvm.set.fpenv``' intrinsic sets the current floating-point environment to the state specified by the argument. The state may be previously obtained by a -call to '``llvm.get.fpenv``' or synthesised in a platform-dependent way. +call to '``llvm.get.fpenv``' or synthesized in a platform-dependent way. '``llvm.reset.fpenv``' Intrinsic @@ -26869,6 +27063,8 @@ Arguments: The argument should be an MDTuple containing any number of MDStrings. +.. _llvm.trap: + '``llvm.trap``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26896,6 +27092,8 @@ This intrinsic is lowered to the target dependent trap instruction. If the target does not have a trap instruction, this intrinsic will be lowered to a call of the ``abort()`` function. +.. _llvm.debugtrap: + '``llvm.debugtrap``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26923,6 +27121,8 @@ This intrinsic is lowered to code which is intended to cause an execution trap with the intention of requesting the attention of a debugger. +.. _llvm.ubsantrap: + '``llvm.ubsantrap``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26950,7 +27150,7 @@ This intrinsic is lowered to code which is intended to cause an execution trap, embedding the argument into encoding of that trap somehow to discriminate crashes if possible. -Equivalent to ``@llvm.trap`` for targets that do not support this behaviour. +Equivalent to ``@llvm.trap`` for targets that do not support this behavior. '``llvm.stackprotector``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -27639,47 +27839,113 @@ constant `true`. However it is always correct to replace it with any other `i1` value. Any pass can freely do it if it can benefit from non-default lowering. -'``llvm.experimental.hot``' Intrinsic -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +'``llvm.allow.ubsan.check``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Syntax: """"""" :: - declare i1 @llvm.experimental.hot() + declare i1 @llvm.allow.ubsan.check(i8 immarg %kind) Overview: """"""""" -This intrinsic returns ``true`` iff it's known that containing basic block is -hot in profile. +This intrinsic returns ``true`` if and only if the compiler opted to enable the +ubsan check in the current basic block. + +Rules to allow ubsan checks are not part of the intrinsic declaration, and +controlled by compiler options. -When used with profile based optimization allows to change program behaviour -depending on the code hotness. +This intrinsic is the ubsan specific version of ``@llvm.allow.runtime.check()``. Arguments: """""""""" -None. +An integer describing the kind of ubsan check guarded by the intrinsic. Semantics: """""""""" -The intrinsic ``@llvm.experimental.hot()`` returns either ``true`` or ``false``, -depending on profile used. Expresion is evaluated as ``true`` iff profile and -summary are available and profile counter for the block reach hotness threshold. +The intrinsic ``@llvm.allow.ubsan.check()`` returns either ``true`` or +``false``, depending on compiler options. + +For each evaluation of a call to this intrinsic, the program must be valid and +correct both if it returns ``true`` and if it returns ``false``. + +When used in a branch condition, it selects one of the two paths: + +* `true``: Executes the UBSan check and reports any failures. + +* `false`: Bypasses the check, assuming it always succeeds. + +Example: + +.. code-block:: text + + %allow = call i1 @llvm.allow.ubsan.check(i8 5) + %not.allow = xor i1 %allow, true + %cond = or i1 %ubcheck, %not.allow + br i1 %cond, label %cont, label %trap + + cont: + ; Proceed + + trap: + call void @llvm.ubsantrap(i8 5) + unreachable + + +'``llvm.allow.runtime.check``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare i1 @llvm.allow.runtime.check(metadata %kind) + +Overview: +""""""""" + +This intrinsic returns ``true`` if and only if the compiler opted to enable +runtime checks in the current basic block. + +Rules to allow runtime checks are not part of the intrinsic declaration, and +controlled by compiler options. + +This intrinsic is non-ubsan specific version of ``@llvm.allow.ubsan.check()``. + +Arguments: +"""""""""" + +A string identifying the kind of runtime check guarded by the intrinsic. The +string can be used to control rules to allow checks. + +Semantics: +"""""""""" + +The intrinsic ``@llvm.allow.runtime.check()`` returns either ``true`` or +``false``, depending on compiler options. + For each evaluation of a call to this intrinsic, the program must be valid and correct both if it returns ``true`` and if it returns ``false``. When used in a branch condition, it allows us to choose between -two alternative correct solutions for the same problem, like -in example below: +two alternative correct solutions for the same problem. + +If the intrinsic is evaluated as ``true``, program should execute a guarded +check. If the intrinsic is evaluated as ``false``, the program should avoid any +unnecessary checks. + +Example: .. code-block:: text - %cond = call i1 @llvm.experimental.hot() - br i1 %cond, label %fast_path, label %slow_path + %allow = call i1 @llvm.allow.runtime.check(metadata !"my_check") + br i1 %allow, label %fast_path, label %slow_path fast_path: ; Omit diagnostics. @@ -27939,7 +28205,7 @@ Arguments: The first three arguments are the same as they are in the :ref:`@llvm.memcpy <int_memcpy>` intrinsic, with the added constraint that ``len`` is required to be a positive integer multiple of the ``element_size``. If ``len`` is not a positive integer multiple of -``element_size``, then the behaviour of the intrinsic is undefined. +``element_size``, then the behavior of the intrinsic is undefined. ``element_size`` must be a compile-time constant positive power of two no greater than target-specific atomic access size limit. @@ -28015,7 +28281,7 @@ The first three arguments are the same as they are in the :ref:`@llvm.memmove <int_memmove>` intrinsic, with the added constraint that ``len`` is required to be a positive integer multiple of the ``element_size``. If ``len`` is not a positive integer multiple of ``element_size``, then the -behaviour of the intrinsic is undefined. +behavior of the intrinsic is undefined. ``element_size`` must be a compile-time constant positive power of two no greater than a target-specific atomic access size limit. @@ -28094,7 +28360,7 @@ Arguments: The first three arguments are the same as they are in the :ref:`@llvm.memset <int_memset>` intrinsic, with the added constraint that ``len`` is required to be a positive integer multiple of the ``element_size``. If ``len`` is not a positive integer multiple of -``element_size``, then the behaviour of the intrinsic is undefined. +``element_size``, then the behavior of the intrinsic is undefined. ``element_size`` must be a compile-time constant positive power of two no greater than target-specific atomic access size limit. diff --git a/llvm/docs/PointerAuth.md b/llvm/docs/PointerAuth.md index 41266b43bc29ab74a5aa559e85961c031d9ed5b5..a8d2b4d8f5f0bdc3a281e55568c250bb0ae1734d 100644 --- a/llvm/docs/PointerAuth.md +++ b/llvm/docs/PointerAuth.md @@ -10,6 +10,9 @@ Before the pointer is used, it needs to be authenticated, i.e., have its signature checked. This prevents pointer values of unknown origin from being used to replace the signed pointer value. +For more details, see the clang documentation page for +[Pointer Authentication](https://clang.llvm.org/docs/PointerAuthentication.html). + At the IR level, it is represented using: * a [set of intrinsics](#intrinsics) (to sign/authenticate pointers) diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst index a1de8596480da9ac531dfff87c6008284170073f..2f17c9d7dda04a3058ac009ffdbd7a2723244364 100644 --- a/llvm/docs/RISCVUsage.rst +++ b/llvm/docs/RISCVUsage.rst @@ -362,6 +362,15 @@ The current vendor extensions supported are: ``XCVbi`` LLVM implements `version 1.0.0 of the CORE-V immediate branching custom instructions specification <https://github.com/openhwgroup/cv32e40p/blob/cv32e40p_v1.3.2/docs/source/instruction_set_extensions.rst>`__ by OpenHW Group. All instructions are prefixed with `cv.` as described in the specification. These instructions are only available for riscv32 at this time. +``XSiFivecdiscarddlone`` + LLVM implements `the SiFive sf.cdiscard.d.l1 instruction specified in <https://sifive.cdn.prismic.io/sifive/767804da-53b2-4893-97d5-b7c030ae0a94_s76mc_core_complex_manual_21G3.pdf>`_ by SiFive. + +``XSiFivecflushdlone`` + LLVM implements `the SiFive sf.cflush.d.l1 instruction specified in <https://sifive.cdn.prismic.io/sifive/767804da-53b2-4893-97d5-b7c030ae0a94_s76mc_core_complex_manual_21G3.pdf>`_ by SiFive. + +``XSfcease`` + LLVM implements `the SiFive sf.cease instruction specified in <https://sifive.cdn.prismic.io/sifive/767804da-53b2-4893-97d5-b7c030ae0a94_s76mc_core_complex_manual_21G3.pdf>`_ by SiFive. + Experimental C Intrinsics ========================= diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index b34a5f31c5eb0adf9159b0c7bd9c683277e47f86..7588048334d7928a9a2452a6a8dd5085032109c1 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -67,6 +67,8 @@ Changes to Interprocedural Optimizations Changes to the AArch64 Backend ------------------------------ +* Added support for Cortex-A78AE, Cortex-A520AE and Cortex-A720AE CPUs. + Changes to the AMDGPU Backend ----------------------------- @@ -74,6 +76,7 @@ Changes to the AMDGPU Backend Changes to the ARM Backend -------------------------- +* FEAT_F32MM is no longer activated by default when using `+sve` on v8.6-A or greater. The feature is still available and can be used by adding `+f32mm` to the command line options. Changes to the AVR Backend -------------------------- @@ -106,6 +109,7 @@ Changes to the RISC-V Backend * The experimental Ssnpm, Smnpm, Smmpm, Sspm, and Supm 0.8.1 Pointer Masking extensions are supported. * The experimental Ssqosid extension is supported. * Zacas is no longer experimental. +* Added the CSR names from the Resumable Non-Maskable Interrupts (Smrnmi) extension. Changes to the WebAssembly Backend ---------------------------------- @@ -131,6 +135,20 @@ Changes to the C API * Added ``LLVMConstStringInContext2`` function, which better matches the C++ API by using ``size_t`` for string length. Deprecated ``LLVMConstStringInContext``. +* Added the following functions for accessing a function's prefix data: + + * ``LLVMHasPrefixData`` + * ``LLVMGetPrefixData`` + * ``LLVMSetPrefixData`` + +* Added the following functions for accessing a function's prologue data: + + * ``LLVMHasPrologueData`` + * ``LLVMGetPrologueData`` + * ``LLVMSetPrologueData`` + +* Deprecated ``LLVMConstNUWNeg`` and ``LLVMBuildNUWNeg``. + Changes to the CodeGen infrastructure ------------------------------------- @@ -153,10 +171,22 @@ Changes to the LLVM tools if it's not specified with the ``--format`` argument and cannot be inferred from input files. +* llvm-ar now allows specifying COFF archive format with ``--format`` argument + and uses it by default for COFF targets. + * llvm-objcopy now supports ``--set-symbol-visibility`` and ``--set-symbols-visibility`` options for ELF input to change the visibility of symbols. +* llvm-objcopy now supports ``--skip-symbol`` and ``--skip-symbols`` options + for ELF input to skip the specified symbols when executing other options + that can change a symbol's name, binding or visibility. + +* llvm-profgen now supports COFF+DWARF binaries. This enables Sample-based PGO + on Windows using Intel VTune's SEP. For details on usage, see the `end-user + documentation for SPGO + <https://clang.llvm.org/docs/UsersManual.html#using-sampling-profilers>`_. + Changes to LLDB --------------------------------- diff --git a/llvm/docs/RemoveDIsDebugInfo.md b/llvm/docs/RemoveDIsDebugInfo.md index a9857733c70d30728389d76ec16f80065247f267..9e50a2a604aa69a14bce2c4c798583b767322c3a 100644 --- a/llvm/docs/RemoveDIsDebugInfo.md +++ b/llvm/docs/RemoveDIsDebugInfo.md @@ -24,12 +24,40 @@ The debug records are not instructions, do not appear in the instruction list, a # Great, what do I need to do! -Approximately nothing -- we've already instrumented all of LLVM to handle these new records ("`DPValues`") and behave identically to past LLVM behaviour. We plan on turning this on by default some time soon, with IR converted to the intrinsic form of debug info at terminals (textual IR, bitcode) for a short while, before then changing the textual IR and bitcode formats. +Approximately nothing -- we've already instrumented all of LLVM to handle these new records ("`DbgRecords`") and behave identically to past LLVM behaviour. We plan on turning this on by default some time soon, with IR converted to the intrinsic form of debug info at terminals (textual IR, bitcode) for a short while, before then changing the textual IR and bitcode formats. There are two significant changes to be aware of. Firstly, we're adding a single bit of debug relevant data to the `BasicBlock::iterator` class (it's so that we can determine whether ranges intend on including debug info at the beginning of a block or not). That means when writing passes that insert LLVM IR instructions, you need to identify positions with `BasicBlock::iterator` rather than just a bare `Instruction *`. Most of the time this means that after identifying where you intend on inserting something, you must also call `getIterator` on the instruction position -- however when inserting at the start of a block you _must_ use `getFirstInsertionPt`, `getFirstNonPHIIt` or `begin` and use that iterator to insert, rather than just fetching a pointer to the first instruction. The second matter is that if you transfer sequences of instructions from one place to another manually, i.e. repeatedly using `moveBefore` where you might have used `splice`, then you should instead use the method `moveBeforePreserving`. `moveBeforePreserving` will transfer debug info records with the instruction they're attached to. This is something that happens automatically today -- if you use `moveBefore` on every element of an instruction sequence, then debug intrinsics will be moved in the normal course of your code, but we lose this behaviour with non-instruction debug info. +# C-API changes + +All the functions that have been added are temporary and will be deprecated in the future. The intention is that they'll help downstream projects adapt during the transition period. + +``` +New functions (all to be deprecated) +------------------------------------ +LLVMIsNewDbgInfoFormat # Returns true if the module is in the new non-instruction mode. +LLVMSetIsNewDbgInfoFormat # Convert to the requested debug info format. + +LLVMDIBuilderInsertDeclareIntrinsicBefore # Insert a debug intrinsic (old debug info format). +LLVMDIBuilderInsertDeclareIntrinsicAtEnd # Same as above. +LLVMDIBuilderInsertDbgValueIntrinsicBefore # Same as above. +LLVMDIBuilderInsertDbgValueIntrinsicAtEnd # Same as above. + +LLVMDIBuilderInsertDeclareRecordBefore # Insert a debug record (new debug info format). +LLVMDIBuilderInsertDeclareRecordAtEnd # Same as above. +LLVMDIBuilderInsertDbgValueRecordBefore # Same as above. +LLVMDIBuilderInsertDbgValueRecordAtEnd # Same as above. + +Existing functions (behaviour change) +------------------------------------- +LLVMDIBuilderInsertDeclareBefore # Insert a debug record (new debug info format) instead of a debug intrinsic (old debug info format). +LLVMDIBuilderInsertDeclareAtEnd # Same as above. +LLVMDIBuilderInsertDbgValueBefore # Same as above. +LLVMDIBuilderInsertDbgValueAtEnd # Same as above. +``` + # Anything else? Not really, but here's an "old vs new" comparison of how to do certain things and quickstart for how this "new" debug info is structured. @@ -40,13 +68,15 @@ This will all happen transparently without needing to think about it! ## What exactly have you replaced debug intrinsics with? -We're using a dedicated C++ class called `DPValue` to store debug info, with a one-to-one relationship between each instance of a debug intrinsic and each `DPValue` object in any LLVM IR program. This class stores exactly the same information as is stored in debugging intrinsics. It also has almost entirely the same set of methods, that behave in the same way: +We're using a dedicated C++ class called `DbgRecord` to store debug info, with a one-to-one relationship between each instance of a debug intrinsic and each `DbgRecord` object in any LLVM IR program; these `DbgRecord`s are represented in the IR as non-instruction debug records, as described in the [Source Level Debugging](project:SourceLevelDebugging.rst#Debug Records) document. This class has a set of subclasses that store exactly the same information as is stored in debugging intrinsics. Each one also has almost entirely the same set of methods, that behave in the same way: - https://llvm.org/docs/doxygen/classllvm_1_1DPValue.html + https://llvm.org/docs/doxygen/classllvm_1_1DbgRecord.html + https://llvm.org/docs/doxygen/classllvm_1_1DbgVariableRecord.html + https://llvm.org/docs/doxygen/classllvm_1_1DbgLabelRecord.html -This allows you to treat a `DPValue` as if it's a `dbg.value` intrinsic most of the time, for example in generic (auto-param) lambdas. +This allows you to treat a `DbgVariableRecord` as if it's a `dbg.value`/`dbg.declare`/`dbg.assign` intrinsic most of the time, for example in generic (auto-param) lambdas, and the same for `DbgLabelRecord` and `dbg.label`s. -## How do these DPValues fit into the instruction stream? +## How do these `DbgRecords` fit into the instruction stream? Like so: @@ -59,38 +89,38 @@ Like so: | | v - +------------+ - <-----+ DPMarker |<---- - / +------------+ \ - / \ - / \ - v ^ - +-----------+ +-----------+ +-----------+ - | DPValue +--->| DPValue +-->| DPValue | - +-----------+ +-----------+ +-----------+ + +-------------+ + <-------+ DbgMarker |<------- + / +-------------+ \ + / \ + / \ + v ^ + +-------------+ +-------------+ +-------------+ + | DbgRecord +--->| DbgRecord +-->| DbgRecord | + +-------------+ +-------------+ +-------------+ ``` -Each instruction has a pointer to a `DPMarker` (which will become optional), that contains a list of `DPValue` objects. No debugging records appear in the instruction list at all. `DPValue`s have a parent pointer to their owning `DPMarker`, and each `DPMarker` has a pointer back to it's owning instruction. +Each instruction has a pointer to a `DbgMarker` (which will become optional), that contains a list of `DbgRecord` objects. No debugging records appear in the instruction list at all. `DbgRecord`s have a parent pointer to their owning `DbgMarker`, and each `DbgMarker` has a pointer back to it's owning instruction. -Not shown are the links from DPValues to other parts of the `Value`/`Metadata` hierachy: `DPValue`s have raw pointers to `DILocalVariable`, `DIExpression` and `DILocation` objects, and references to `Value`s are stored in a `DebugValueUser` base class. This refers to a `ValueAsMetadata` object referring to `Value`s, via the `TrackingMetadata` facility. +Not shown are the links from DbgRecord to other parts of the `Value`/`Metadata` hierachy: `DbgRecord` subclasses have tracking pointers to the DIMetadata that they use, and `DbgVariableRecord` has references to `Value`s that are stored in a `DebugValueUser` base class. This refers to a `ValueAsMetadata` object referring to `Value`s, via the `TrackingMetadata` facility. -The various kinds of debug intrinsic (value, declare, assign) are all stored in the `DPValue` object, with a "Type" field disamgibuating which is which. +The various kinds of debug intrinsic (value, declare, assign, label) are all stored in `DbgRecord` subclasses, with a "RecordKind" field distinguishing `DbgLabelRecord`s from `DbgVariableRecord`s, and a `LocationType` field in the `DbgVariableRecord` class further disambiguating the various debug variable intrinsics it can represent. ## Finding debug info records -Utilities such as `findDbgUsers` and the like now have an optional argument that will return the set of `DPValue` records that refer to a `Value`. You should be able to treat them the same as intrinsics. +Utilities such as `findDbgUsers` and the like now have an optional argument that will return the set of `DbgVariableRecord` records that refer to a `Value`. You should be able to treat them the same as intrinsics. ## Examining debug info records at positions -Call `Instruction::getDbgRecordRange()` to get the range of `DPValue` objects that are attached to an instruction. +Call `Instruction::getDbgRecordRange()` to get the range of `DbgRecord` objects that are attached to an instruction. ## Moving around, deleting -You can use `DPValue::removeFromParent` to unlink a `DPValue` from it's marker, and then `BasicBlock::insertDbgRecordBefore` or `BasicBlock::insertDbgRecordAfter` to re-insert the `DPValue` somewhere else. You cannot insert a `DPValue` at an arbitary point in a list of `DPValue`s (if you're doing this with `dbg.value`s then it's unlikely to be correct). +You can use `DbgRecord::removeFromParent` to unlink a `DbgRecord` from it's marker, and then `BasicBlock::insertDbgRecordBefore` or `BasicBlock::insertDbgRecordAfter` to re-insert the `DbgRecord` somewhere else. You cannot insert a `DbgRecord` at an arbitary point in a list of `DbgRecord`s (if you're doing this with `dbg.value`s then it's unlikely to be correct). -Erase `DPValue`s by calling `eraseFromParent` or `deleteInstr` if it's already been removed. +Erase `DbgRecord`s by calling `eraseFromParent` or `deleteInstr` if it's already been removed. -## What about dangling `DPValue`s? +## What about dangling `DbgRecord`s? If you have a block like so: @@ -101,6 +131,6 @@ If you have a block like so: br label %xyzzy ``` -your optimisation pass may wish to erase the terminator and then do something to the block. This is easy to do when debug info is kept in instructions, but with `DPValue`s there is no trailing instruction to attach the variable information to in the block above, once the terminator is erased. For such degenerate blocks, `DPValue`s are stored temporarily in a map in `LLVMContext`, and are re-inserted when a terminator is reinserted to the block or other instruction inserted at `end()`. +your optimisation pass may wish to erase the terminator and then do something to the block. This is easy to do when debug info is kept in instructions, but with `DbgRecord`s there is no trailing instruction to attach the variable information to in the block above, once the terminator is erased. For such degenerate blocks, `DbgRecord`s are stored temporarily in a map in `LLVMContext`, and are re-inserted when a terminator is reinserted to the block or other instruction inserted at `end()`. This can technically lead to trouble in the vanishingly rare scenario where an optimisation pass erases a terminator and then decides to erase the whole block. (We recommend not doing that). diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst index 5ca035b68392f01259c0092c60c248356cb9ded6..a183877c48cb2252ebe274a2aecf30831a5c2310 100644 --- a/llvm/docs/SPIRVUsage.rst +++ b/llvm/docs/SPIRVUsage.rst @@ -14,10 +14,43 @@ Introduction The SPIR-V target provides code generation for the SPIR-V binary format described in `the official SPIR-V specification <https://www.khronos.org/registry/SPIR-V/>`_. +Usage +===== + +The SPIR-V backend can be invoked either from LLVM's Static Compiler (llc) or Clang, +allowing developers to compile LLVM intermediate language (IL) files or OpenCL kernel +sources directly to SPIR-V. This section outlines the usage of various commands to +leverage the SPIR-V backend for different purposes. + +Static Compiler Commands +------------------------ + +1. **Basic SPIR-V Compilation** + Command: `llc -mtriple=spirv32-unknown-unknown input.ll -o output.spvt` + Description: This command compiles an LLVM IL file (`input.ll`) to a SPIR-V binary (`output.spvt`) for a 32-bit architecture. + +2. **Compilation with Extensions and Optimization** + Command: `llc -O1 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_arbitrary_precision_integers input.ll -o output.spvt` + Description: Compiles an LLVM IL file to SPIR-V with (`-O1`) optimizations, targeting a 64-bit architecture. It enables the SPV_INTEL_arbitrary_precision_integers extension. + +3. **SPIR-V Binary Generation** + Command: `llc -O0 -mtriple=spirv64-unknown-unknown -filetype=obj input.ll -o output.spvt` + Description: Generates a SPIR-V object file (`output.spvt`) from an LLVM module, targeting a 64-bit SPIR-V architecture with no optimizations. + +Clang Commands +-------------- + +1. **SPIR-V Generation** + Command: `clang –target=spirv64 input.cl` + Description: Generates a SPIR-V file directly from an OpenCL kernel source file (`input.cl`). + +Compiler Options +================ + .. _spirv-target-triples: Target Triples -============== +-------------- For cross-compilation into SPIR-V use option @@ -32,6 +65,7 @@ to specify the target triple: ============ ============================================================== ``spirv32`` SPIR-V with 32-bit pointer width. ``spirv64`` SPIR-V with 64-bit pointer width. + ``spirv`` SPIR-V with logical memory layout. ============ ============================================================== .. table:: SPIR-V Subarchitectures @@ -39,13 +73,14 @@ to specify the target triple: =============== ============================================================== Subarchitecture Description =============== ============================================================== - *<empty>* SPIR-V version deduced by tools based on the compiled input. + *<empty>* SPIR-V version deduced by backend based on the input. ``v1.0`` SPIR-V version 1.0. ``v1.1`` SPIR-V version 1.1. ``v1.2`` SPIR-V version 1.2. ``v1.3`` SPIR-V version 1.3. ``v1.4`` SPIR-V version 1.4. ``v1.5`` SPIR-V version 1.5. + ``v1.6`` SPIR-V version 1.6. =============== ============================================================== .. table:: SPIR-V Vendors @@ -62,6 +97,9 @@ to specify the target triple: OS Description ===================== ============================================================ *<empty>*/``unknown`` Defaults to the OpenCL runtime. + ``vulkan`` Vulkan shader runtime. + ``vulkan1.2`` Vulkan 1.2 runtime, corresponding to SPIR-V 1.5. + ``vulkan1.3`` Vulkan 1.3 runtime, corresponding to SPIR-V 1.6. ===================== ============================================================ .. table:: SPIR-V Environments @@ -69,20 +107,95 @@ to specify the target triple: ===================== ============================================================== Environment Description ===================== ============================================================== - *<empty>*/``unknown`` Defaults to the OpenCL environment. + *<empty>*/``unknown`` OpenCL environment or deduced by backend based on the input. ===================== ============================================================== Example: ``-target spirv64v1.0`` can be used to compile for SPIR-V version 1.0 with 64-bit pointer width. -.. _spirv-types: +.. _spirv-extensions: + +Extensions +---------- + +The SPIR-V backend supports a variety of `extensions <https://github.com/KhronosGroup/SPIRV-Registry/tree/main/extensions>`_ +that enable or enhance features beyond the core SPIR-V specification. +These extensions can be enabled using the ``-spirv-extensions`` option +followed by the name of the extension(s) you wish to enable. Below is a +list of supported SPIR-V extensions, sorted alphabetically by their extension names: + +.. list-table:: Supported SPIR-V Extensions + :widths: 50 150 + :header-rows: 1 + + * - Extension Name + - Description + * - ``SPV_EXT_shader_atomic_float16_add`` + - Extends the SPV_EXT_shader_atomic_float_add extension to support atomically adding to 16-bit floating-point numbers in memory. + * - ``SPV_EXT_shader_atomic_float_add`` + - Adds atomic add instruction on floating-point numbers. + * - ``SPV_EXT_shader_atomic_float_min_max`` + - Adds atomic min and max instruction on floating-point numbers. + * - ``SPV_INTEL_arbitrary_precision_integers`` + - Allows generating arbitrary width integer types. + * - ``SPV_INTEL_bfloat16_conversion`` + - Adds instructions to convert between single-precision 32-bit floating-point values and 16-bit bfloat16 values. + * - ``SPV_INTEL_function_pointers`` + - Allows translation of function pointers. + * - ``SPV_INTEL_optnone`` + - Adds OptNoneINTEL value for Function Control mask that indicates a request to not optimize the function. + * - ``SPV_INTEL_subgroups`` + - Allows work items in a subgroup to share data without the use of local memory and work group barriers, and to utilize specialized hardware to load and store blocks of data from images or buffers. + * - ``SPV_INTEL_usm_storage_classes`` + - Introduces two new storage classes that are subclasses of the CrossWorkgroup storage class that provides additional information that can enable optimization. + * - ``SPV_INTEL_variable_length_array`` + - Allows to allocate local arrays whose number of elements is unknown at compile time. + * - ``SPV_KHR_bit_instructions`` + - Enables bit instructions to be used by SPIR-V modules without requiring the Shader capability. + * - ``SPV_KHR_expect_assume`` + - Provides additional information to a compiler, similar to the llvm.assume and llvm.expect intrinsics. + * - ``SPV_KHR_float_controls`` + - Provides new execution modes to control floating-point computations by overriding an implementation’s default behavior for rounding modes, denormals, signed zero, and infinities. + * - ``SPV_KHR_linkonce_odr`` + - Allows to use the LinkOnceODR linkage type that lets a function or global variable to be merged with other functions or global variables of the same name when linkage occurs. + * - ``SPV_KHR_no_integer_wrap_decoration`` + - Adds decorations to indicate that a given instruction does not cause integer wrapping. + * - ``SPV_KHR_subgroup_rotate`` + - Adds a new instruction that enables rotating values across invocations within a subgroup. + * - ``SPV_KHR_uniform_group_instructions`` + - Allows support for additional group operations within uniform control flow. -Representing special types in SPIR-V -==================================== +To enable multiple extensions, list them separated by spaces. For example, to enable support for atomic operations on floating-point numbers and arbitrary precision integers, use: + +``-spirv-ext=+SPV_EXT_shader_atomic_float_add,+SPV_INTEL_arbitrary_precision_integers`` + +To enable all extensions, use the following option: +``-spirv-ext=all`` + +To enable all extensions except specified, specify ``all`` followed by a list of disallowed extensions. For example: +``-spirv-ext=all,-SPV_INTEL_arbitrary_precision_integers`` + +SPIR-V representation in LLVM IR +================================ + +SPIR-V is intentionally designed for seamless integration with various Intermediate +Representations (IRs), including LLVM IR, facilitating straightforward mappings for +most of its entities. The development of the SPIR-V backend has been guided by a +principle of compatibility with the `Khronos Group SPIR-V LLVM Translator <https://github.com/KhronosGroup/SPIRV-LLVM-Translator>`_. +Consequently, the input representation accepted by the SPIR-V backend aligns closely +with that detailed in `the SPIR-V Representation in LLVM document <https://github.com/KhronosGroup/SPIRV-LLVM-Translator/blob/main/docs/SPIRVRepresentationInLLVM.rst>`_. +This document, along with the sections that follow, delineate the main points and focus +on any differences between the LLVM IR that this backend processes and the conventions +used by other tools. + +.. _spirv-special-types: + +Special types +------------- SPIR-V specifies several kinds of opaque types. These types are represented -using target extension types. These types are represented as follows: +using target extension types and are represented as follows: .. table:: SPIR-V Opaque Types @@ -108,3 +221,210 @@ dimensionality parameter as ``1`` meaning 2D. Sampled image types include the parameters of its underlying image type, so that a sampled image for the previous type has the representation ``target("spirv.SampledImage, void, 1, 1, 0, 0, 0, 0, 0)``. + +.. _spirv-intrinsics: + +Target Intrinsics +----------------- + +The SPIR-V backend employs several LLVM IR intrinsics that facilitate various low-level +operations essential for generating correct and efficient SPIR-V code. These intrinsics +cover a range of functionalities from type assignment and memory management to control +flow and atomic operations. Below is a detailed table of selected intrinsics used in the +SPIR-V backend, along with their descriptions and argument details. + +.. list-table:: LLVM IR Intrinsics for SPIR-V + :widths: 25 15 20 40 + :header-rows: 1 + + * - Intrinsic ID + - Return Type + - Argument Types + - Description + * - `int_spv_assign_type` + - None + - `[Type, Metadata]` + - Associates a type with metadata, crucial for maintaining type information in SPIR-V structures. Not emitted directly but supports the type system internally. + * - `int_spv_assign_ptr_type` + - None + - `[Type, Metadata, Integer]` + - Similar to `int_spv_assign_type`, but for pointer types with an additional integer specifying the storage class. Supports SPIR-V's detailed pointer type system. Not emitted directly. + * - `int_spv_assign_name` + - None + - `[Type, Vararg]` + - Assigns names to types or values, enhancing readability and debuggability of SPIR-V code. Not emitted directly but used for metadata enrichment. + * - `int_spv_track_constant` + - Type + - `[Type, Metadata]` + - Tracks constants in the SPIR-V module. Essential for optimizing and reducing redundancy. Emitted for internal use only. + * - `int_spv_init_global` + - None + - `[Type, Type]` + - Initializes global variables, a necessary step for ensuring correct global state management in SPIR-V. Emitted for internal use only. + * - `int_spv_unref_global` + - None + - `[Type]` + - Manages the lifetime of global variables by marking them as unreferenced, thus enabling optimizations related to global variable usage. Emitted for internal use only. + * - `int_spv_gep` + - Pointer + - `[Boolean, Type, Vararg]` + - Computes the address of a sub-element of an aggregate type. Critical for accessing array elements and structure fields. Supports conditionally addressing elements in a generic way. + * - `int_spv_load` + - 32-bit Integer + - `[Pointer, 16-bit Integer, 8-bit Integer]` + - Loads a value from a memory location. The additional integers specify memory access and alignment details, vital for ensuring correct and efficient memory operations. + * - `int_spv_store` + - None + - `[Type, Pointer, 16-bit Integer, 8-bit Integer]` + - Stores a value to a memory location. Like `int_spv_load`, it includes specifications for memory access and alignment, essential for memory operations. + * - `int_spv_extractv` + - Type + - `[32-bit Integer, Vararg]` + - Extracts a value from a vector, allowing for vector operations within SPIR-V. Enables manipulation of vector components. + * - `int_spv_insertv` + - 32-bit Integer + - `[32-bit Integer, Type, Vararg]` + - Inserts a value into a vector. Complementary to `int_spv_extractv`, it facilitates the construction and manipulation of vectors. + * - `int_spv_extractelt` + - Type + - `[Type, Any Integer]` + - Extracts an element from an aggregate type based on an index. Essential for operations on arrays and vectors. + * - `int_spv_insertelt` + - Type + - `[Type, Type, Any Integer]` + - Inserts an element into an aggregate type at a specified index. Allows for building and modifying arrays and vectors. + * - `int_spv_const_composite` + - 32-bit Integer + - `[Vararg]` + - Constructs a composite type from given elements. Key for creating arrays, structs, and vectors from individual components. + * - `int_spv_bitcast` + - Type + - `[Type]` + - Performs a bit-wise cast between types. Critical for type conversions that do not change the bit representation. + * - `int_spv_ptrcast` + - Type + - `[Type, Metadata, Integer]` + - Casts pointers between different types. Similar to `int_spv_bitcast` but specifically for pointers, taking into account SPIR-V's strict type system. + * - `int_spv_switch` + - None + - `[Type, Vararg]` + - Implements a multi-way branch based on a value. Enables complex control flow structures, similar to the switch statement in high-level languages. + * - `int_spv_cmpxchg` + - 32-bit Integer + - `[Type, Vararg]` + - Performs an atomic compare-and-exchange operation. Crucial for synchronization and concurrency control in compute shaders. + * - `int_spv_unreachable` + - None + - `[]` + - Marks a point in the code that should never be reached, enabling optimizations by indicating unreachable code paths. + * - `int_spv_alloca` + - Type + - `[]` + - Allocates memory on the stack. Fundamental for local variable storage in functions. + * - `int_spv_alloca_array` + - Type + - `[Any Integer]` + - Allocates an array on the stack. Extends `int_spv_alloca` to support array allocations, essential for temporary arrays. + * - `int_spv_undef` + - 32-bit Integer + - `[]` + - Generates an undefined value. Useful for optimizations and indicating uninitialized variables. + * - `int_spv_assume` + - None + - `[1-bit Integer]` + - Provides hints to the optimizer about assumptions that can be made about program state. Improves optimization potential. + * - `int_spv_expect` + - Any Integer Type + - `[Type, Type]` + - Guides branch prediction by indicating expected branch paths. Enhances performance by optimizing common code paths. + * - `int_spv_thread_id` + - 32-bit Integer + - `[32-bit Integer]` + - Retrieves the thread ID within a workgroup. Essential for identifying execution context in parallel compute operations. + * - `int_spv_create_handle` + - Pointer + - `[8-bit Integer]` + - Creates a resource handle for graphics or compute resources. Facilitates the management and use of resources in shaders. + +.. _spirv-builtin-functions: + +Builtin Functions +----------------- + +The following section highlights the representation of SPIR-V builtins in LLVM IR, +emphasizing builtins that do not have direct counterparts in LLVM. + +Instructions as Function Calls +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +SPIR-V builtins without direct LLVM counterparts are represented as LLVM function calls. +These functions, termed SPIR-V builtin functions, follow an IA64 mangling scheme with +SPIR-V-specific extensions. Parsing non-mangled calls to builtins is supported in some cases, +but not tested extensively. The general format is: + +.. code-block:: c + + __spirv_{OpCodeName}{_OptionalPostfixes} + +Where `{OpCodeName}` is the SPIR-V opcode name sans the "Op" prefix, and +`{OptionalPostfixes}` are decoration-specific postfixes, if any. The mangling and +postfixes allow for the representation of SPIR-V's rich instruction set within LLVM's +framework. + +Extended Instruction Sets +~~~~~~~~~~~~~~~~~~~~~~~~~ + +SPIR-V defines several extended instruction sets for additional functionalities, such as +OpenCL-specific operations. In LLVM IR, these are represented by function calls to +mangled builtins and selected based on the environment. For example: + +.. code-block:: c + + acos_f32 + +represents the `acos` function from the OpenCL extended instruction set for a float32 +input. + +Builtin Variables +~~~~~~~~~~~~~~~~~ + +SPIR-V builtin variables, which provide access to special hardware or execution model +properties, are mapped to either LLVM function calls or LLVM global variables. The +representation follows the naming convention: + +.. code-block:: c + + __spirv_BuiltIn{VariableName} + +For instance, the SPIR-V builtin `GlobalInvocationId` is accessible in LLVM IR as +`__spirv_BuiltInGlobalInvocationId`. + +Vector Load and Store Builtins +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +SPIR-V's capabilities for loading and storing vectors are represented in LLVM IR using +functions that mimic the SPIR-V instructions. These builtins handle cases that LLVM's +native instructions do not directly support, enabling fine-grained control over memory +operations. + +Atomic Operations +~~~~~~~~~~~~~~~~~ + +SPIR-V's atomic operations, especially those operating on floating-point data, are +represented in LLVM IR with corresponding function calls. These builtins ensure +atomicity in operations where LLVM might not have direct support, essential for parallel +execution and synchronization. + +Image Operations +~~~~~~~~~~~~~~~~ + +SPIR-V provides extensive support for image and sampler operations, which LLVM +represents through function calls to builtins. These include image reads, writes, and +queries, allowing detailed manipulation of image data and parameters. + +Group and Subgroup Operations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For workgroup and subgroup operations, LLVM uses function calls to represent SPIR-V's +group-based instructions. These builtins facilitate group synchronization, data sharing, +and collective operations essential for efficient parallel computation. diff --git a/llvm/docs/UserGuides.rst b/llvm/docs/UserGuides.rst index 2eeb076192033b8687a35affd98c6fccbfe3fdfb..f40a04d414a28c0385d4a1da66a376dd49d16d5a 100644 --- a/llvm/docs/UserGuides.rst +++ b/llvm/docs/UserGuides.rst @@ -43,6 +43,7 @@ intermediate LLVM representation. HowToCrossCompileBuiltinsOnArm HowToCrossCompileLLVM HowToUpdateDebugInfo + InstCombineContributorGuide InstrProfileFormat InstrRefDebugInfo LinkTimeOptimization @@ -181,11 +182,15 @@ Optimizations :doc:`RemoveDIsDebugInfo` This is a migration guide describing how to move from debug info using - intrinsics such as dbg.value to using the non-instruction DPValue object. + intrinsics such as dbg.value to using the non-instruction DbgRecord object. :doc:`InstrProfileFormat` This document explains two binary formats of instrumentation-based profiles. +:doc:`InstCombineContributorGuide` + This document specifies guidelines for contributions for InstCombine and + related passes. + Code Generation --------------- diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h index 7cfe4dc4f775fd1ab7e5782e39aa72101c9e3c3c..6be5957ce610336a7374a22b98becfb1362f2fe3 100644 --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -744,6 +744,24 @@ LLVMModuleRef LLVMCloneModule(LLVMModuleRef M); */ void LLVMDisposeModule(LLVMModuleRef M); +/** + * Soon to be deprecated. + * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes + * + * Returns true if the module is in the new debug info mode which uses + * non-instruction debug records instead of debug intrinsics for variable + * location tracking. + */ +LLVMBool LLVMIsNewDbgInfoFormat(LLVMModuleRef M); + +/** + * Soon to be deprecated. + * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes + * + * Convert module into desired debug info format. + */ +void LLVMSetIsNewDbgInfoFormat(LLVMModuleRef M, LLVMBool UseNewFormat); + /** * Obtain the identifier of a module. * @@ -1848,6 +1866,14 @@ void LLVMDumpValue(LLVMValueRef Val); */ char *LLVMPrintValueToString(LLVMValueRef Val); +/** + * Return a string representation of the DbgRecord. Use + * LLVMDisposeMessage to free the string. + * + * @see llvm::DbgRecord::print() + */ +char *LLVMPrintDbgRecordToString(LLVMDbgRecordRef Record); + /** * Replace all uses of a value with another one. * @@ -2298,7 +2324,9 @@ LLVMValueRef LLVMAlignOf(LLVMTypeRef Ty); LLVMValueRef LLVMSizeOf(LLVMTypeRef Ty); LLVMValueRef LLVMConstNeg(LLVMValueRef ConstantVal); LLVMValueRef LLVMConstNSWNeg(LLVMValueRef ConstantVal); -LLVMValueRef LLVMConstNUWNeg(LLVMValueRef ConstantVal); +LLVM_ATTRIBUTE_C_DEPRECATED( + LLVMValueRef LLVMConstNUWNeg(LLVMValueRef ConstantVal), + "Use LLVMConstNull instead."); LLVMValueRef LLVMConstNot(LLVMValueRef ConstantVal); LLVMValueRef LLVMConstAdd(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); LLVMValueRef LLVMConstNSWAdd(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant); @@ -2730,6 +2758,44 @@ const char *LLVMGetGC(LLVMValueRef Fn); */ void LLVMSetGC(LLVMValueRef Fn, const char *Name); +/** + * Gets the prefix data associated with a function. Only valid on functions, and + * only if LLVMHasPrefixData returns true. + * See https://llvm.org/docs/LangRef.html#prefix-data + */ +LLVMValueRef LLVMGetPrefixData(LLVMValueRef Fn); + +/** + * Check if a given function has prefix data. Only valid on functions. + * See https://llvm.org/docs/LangRef.html#prefix-data + */ +LLVMBool LLVMHasPrefixData(LLVMValueRef Fn); + +/** + * Sets the prefix data for the function. Only valid on functions. + * See https://llvm.org/docs/LangRef.html#prefix-data + */ +void LLVMSetPrefixData(LLVMValueRef Fn, LLVMValueRef prefixData); + +/** + * Gets the prologue data associated with a function. Only valid on functions, + * and only if LLVMHasPrologueData returns true. + * See https://llvm.org/docs/LangRef.html#prologue-data + */ +LLVMValueRef LLVMGetPrologueData(LLVMValueRef Fn); + +/** + * Check if a given function has prologue data. Only valid on functions. + * See https://llvm.org/docs/LangRef.html#prologue-data + */ +LLVMBool LLVMHasPrologueData(LLVMValueRef Fn); + +/** + * Sets the prologue data for the function. Only valid on functions. + * See https://llvm.org/docs/LangRef.html#prologue-data + */ +void LLVMSetPrologueData(LLVMValueRef Fn, LLVMValueRef prologueData); + /** * Add an attribute to a function. * @@ -4096,8 +4162,10 @@ LLVMValueRef LLVMBuildBinOp(LLVMBuilderRef B, LLVMOpcode Op, LLVMValueRef LLVMBuildNeg(LLVMBuilderRef, LLVMValueRef V, const char *Name); LLVMValueRef LLVMBuildNSWNeg(LLVMBuilderRef B, LLVMValueRef V, const char *Name); -LLVMValueRef LLVMBuildNUWNeg(LLVMBuilderRef B, LLVMValueRef V, - const char *Name); +LLVM_ATTRIBUTE_C_DEPRECATED(LLVMValueRef LLVMBuildNUWNeg(LLVMBuilderRef B, + LLVMValueRef V, + const char *Name), + "Use LLVMBuildNeg + LLVMSetNUW instead."); LLVMValueRef LLVMBuildFNeg(LLVMBuilderRef, LLVMValueRef V, const char *Name); LLVMValueRef LLVMBuildNot(LLVMBuilderRef, LLVMValueRef V, const char *Name); diff --git a/llvm/include/llvm-c/DebugInfo.h b/llvm/include/llvm-c/DebugInfo.h index 5924294708cc354e769b87f1a63edf88f514390f..dab1d697761b4e36ed4b484c5a162fd318ff6027 100644 --- a/llvm/include/llvm-c/DebugInfo.h +++ b/llvm/include/llvm-c/DebugInfo.h @@ -1248,7 +1248,29 @@ LLVMMetadataRef LLVMDIBuilderCreateTempGlobalVariableFwdDecl( unsigned LineNo, LLVMMetadataRef Ty, LLVMBool LocalToUnit, LLVMMetadataRef Decl, uint32_t AlignInBits); +/* + * Insert a new Declare DbgRecord before the given instruction. + * + * Only use in "new debug mode" (LLVMIsNewDbgInfoFormat() is true). + * Use LLVMSetIsNewDbgInfoFormat(LLVMBool) to convert between formats. + * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes + * + * \param Builder The DIBuilder. + * \param Storage The storage of the variable to declare. + * \param VarInfo The variable's debug info descriptor. + * \param Expr A complex location expression for the variable. + * \param DebugLoc Debug info location. + * \param Instr Instruction acting as a location for the new intrinsic. + */ +LLVMDbgRecordRef +LLVMDIBuilderInsertDeclareBefore(LLVMDIBuilderRef Builder, LLVMValueRef Storage, + LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, + LLVMMetadataRef DebugLoc, LLVMValueRef Instr); /** + * Soon to be deprecated. + * Only use in "old debug mode" (LLVMIsNewDbgInfoFormat() is false). + * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes + * * Insert a new llvm.dbg.declare intrinsic call before the given instruction. * \param Builder The DIBuilder. * \param Storage The storage of the variable to declare. @@ -1257,11 +1279,50 @@ LLVMMetadataRef LLVMDIBuilderCreateTempGlobalVariableFwdDecl( * \param DebugLoc Debug info location. * \param Instr Instruction acting as a location for the new intrinsic. */ -LLVMValueRef LLVMDIBuilderInsertDeclareBefore( - LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, - LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr); +LLVMValueRef LLVMDIBuilderInsertDeclareIntrinsicBefore( + LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr); +/** + * Soon to be deprecated. + * Only use in "new debug mode" (LLVMIsNewDbgInfoFormat() is true). + * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes + * + * Insert a Declare DbgRecord before the given instruction. + * \param Builder The DIBuilder. + * \param Storage The storage of the variable to declare. + * \param VarInfo The variable's debug info descriptor. + * \param Expr A complex location expression for the variable. + * \param DebugLoc Debug info location. + * \param Instr Instruction acting as a location for the new record. + */ +LLVMDbgRecordRef LLVMDIBuilderInsertDeclareRecordBefore( + LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr); /** + * Insert a new Declare DbgRecord at the end of the given basic block. If the + * basic block has a terminator instruction, the intrinsic is inserted before + * that terminator instruction. + * + * Only use in "new debug mode" (LLVMIsNewDbgInfoFormat() is true). + * Use LLVMSetIsNewDbgInfoFormat(LLVMBool) to convert between formats. + * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes + * + * \param Builder The DIBuilder. + * \param Storage The storage of the variable to declare. + * \param VarInfo The variable's debug info descriptor. + * \param Expr A complex location expression for the variable. + * \param DebugLoc Debug info location. + * \param Block Basic block acting as a location for the new intrinsic. + */ +LLVMDbgRecordRef LLVMDIBuilderInsertDeclareAtEnd( + LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block); +/** + * Soon to be deprecated. + * Only use in "old debug mode" (LLVMIsNewDbgInfoFormat() is false). + * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes + * * Insert a new llvm.dbg.declare intrinsic call at the end of the given basic * block. If the basic block has a terminator instruction, the intrinsic is * inserted before that terminator instruction. @@ -1272,11 +1333,51 @@ LLVMValueRef LLVMDIBuilderInsertDeclareBefore( * \param DebugLoc Debug info location. * \param Block Basic block acting as a location for the new intrinsic. */ -LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd( +LLVMValueRef LLVMDIBuilderInsertDeclareIntrinsicAtEnd( + LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block); +/** + * Soon to be deprecated. + * Only use in "new debug mode" (LLVMIsNewDbgInfoFormat() is true). + * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes + * + * Insert a Declare DbgRecord at the end of the given basic block. If the basic + * block has a terminator instruction, the record is inserted before that + * terminator instruction. + * \param Builder The DIBuilder. + * \param Storage The storage of the variable to declare. + * \param VarInfo The variable's debug info descriptor. + * \param Expr A complex location expression for the variable. + * \param DebugLoc Debug info location. + * \param Block Basic block acting as a location for the new record. + */ +LLVMDbgRecordRef LLVMDIBuilderInsertDeclareRecordAtEnd( LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block); /** + * Insert a new Value DbgRecord before the given instruction. + * + * Only use in "new debug mode" (LLVMIsNewDbgInfoFormat() is true). + * Use LLVMSetIsNewDbgInfoFormat(LLVMBool) to convert between formats. + * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes + * + * \param Builder The DIBuilder. + * \param Val The value of the variable. + * \param VarInfo The variable's debug info descriptor. + * \param Expr A complex location expression for the variable. + * \param DebugLoc Debug info location. + * \param Instr Instruction acting as a location for the new intrinsic. + */ +LLVMDbgRecordRef +LLVMDIBuilderInsertDbgValueBefore(LLVMDIBuilderRef Builder, LLVMValueRef Val, + LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, + LLVMMetadataRef DebugLoc, LLVMValueRef Instr); +/** + * Soon to be deprecated. + * Only use in "old debug mode" (LLVMIsNewDbgInfoFormat() is false). + * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes + * * Insert a new llvm.dbg.value intrinsic call before the given instruction. * \param Builder The DIBuilder. * \param Val The value of the variable. @@ -1285,14 +1386,68 @@ LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd( * \param DebugLoc Debug info location. * \param Instr Instruction acting as a location for the new intrinsic. */ -LLVMValueRef LLVMDIBuilderInsertDbgValueBefore(LLVMDIBuilderRef Builder, - LLVMValueRef Val, - LLVMMetadataRef VarInfo, - LLVMMetadataRef Expr, - LLVMMetadataRef DebugLoc, - LLVMValueRef Instr); +LLVMValueRef LLVMDIBuilderInsertDbgValueIntrinsicBefore( + LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr); +/** + * Soon to be deprecated. + * Only use in "new debug mode" (LLVMIsNewDbgInfoFormat() is true). + * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes + * + * Insert a new llvm.dbg.value intrinsic call before the given instruction. + * \param Builder The DIBuilder. + * \param Val The value of the variable. + * \param VarInfo The variable's debug info descriptor. + * \param Expr A complex location expression for the variable. + * \param DebugLoc Debug info location. + * \param Instr Instruction acting as a location for the new intrinsic. + */ +LLVMDbgRecordRef LLVMDIBuilderInsertDbgValueRecordBefore( + LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr); /** + * Insert a new Value DbgRecord at the end of the given basic block. If the + * basic block has a terminator instruction, the intrinsic is inserted before + * that terminator instruction. + * + * Only use in "new debug mode" (LLVMIsNewDbgInfoFormat() is true). + * Use LLVMSetIsNewDbgInfoFormat(LLVMBool) to convert between formats. + * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes + * + * \param Builder The DIBuilder. + * \param Val The value of the variable. + * \param VarInfo The variable's debug info descriptor. + * \param Expr A complex location expression for the variable. + * \param DebugLoc Debug info location. + * \param Block Basic block acting as a location for the new intrinsic. + */ +LLVMDbgRecordRef LLVMDIBuilderInsertDbgValueAtEnd( + LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block); +/** + * Soon to be deprecated. + * Only use in "old debug mode" (LLVMIsNewDbgInfoFormat() is false). + * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes + * + * Insert a new llvm.dbg.value intrinsic call at the end of the given basic + * block. If the basic block has a terminator instruction, the intrinsic is + * inserted before that terminator instruction. + * \param Builder The DIBuilder. + * \param Val The value of the variable. + * \param VarInfo The variable's debug info descriptor. + * \param Expr A complex location expression for the variable. + * \param DebugLoc Debug info location. + * \param Block Basic block acting as a location for the new intrinsic. + */ +LLVMValueRef LLVMDIBuilderInsertDbgValueIntrinsicAtEnd( + LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block); +/** + * Soon to be deprecated. + * Only use in "new debug mode" (LLVMIsNewDbgInfoFormat() is true). + * See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes + * * Insert a new llvm.dbg.value intrinsic call at the end of the given basic * block. If the basic block has a terminator instruction, the intrinsic is * inserted before that terminator instruction. @@ -1303,12 +1458,9 @@ LLVMValueRef LLVMDIBuilderInsertDbgValueBefore(LLVMDIBuilderRef Builder, * \param DebugLoc Debug info location. * \param Block Basic block acting as a location for the new intrinsic. */ -LLVMValueRef LLVMDIBuilderInsertDbgValueAtEnd(LLVMDIBuilderRef Builder, - LLVMValueRef Val, - LLVMMetadataRef VarInfo, - LLVMMetadataRef Expr, - LLVMMetadataRef DebugLoc, - LLVMBasicBlockRef Block); +LLVMDbgRecordRef LLVMDIBuilderInsertDbgValueRecordAtEnd( + LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block); /** * Create a new descriptor for a local auto variable. diff --git a/llvm/include/llvm-c/Types.h b/llvm/include/llvm-c/Types.h index d5474d986309fa02fc6b855628226f441af143e8..4681500ef9da3d3f322e948a3829e09e6ea178a2 100644 --- a/llvm/include/llvm-c/Types.h +++ b/llvm/include/llvm-c/Types.h @@ -169,6 +169,11 @@ typedef struct LLVMOpaqueJITEventListener *LLVMJITEventListenerRef; */ typedef struct LLVMOpaqueBinary *LLVMBinaryRef; +/** + * @see llvm::DbgRecord + */ +typedef struct LLVMOpaqueDbgRecord *LLVMDbgRecordRef; + /** * @} */ diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h index bea3e28adf308fb6342b8c9cfe9a8ae707271a92..b9b39f3b9dfbc44840f082ec6f38bf10816af05b 100644 --- a/llvm/include/llvm/ADT/APInt.h +++ b/llvm/include/llvm/ADT/APInt.h @@ -997,6 +997,12 @@ public: APInt ushl_ov(const APInt &Amt, bool &Overflow) const; APInt ushl_ov(unsigned Amt, bool &Overflow) const; + /// Signed integer floor division operation. + /// + /// Rounds towards negative infinity, i.e. 5 / -2 = -3. Iff minimum value + /// divided by -1 set Overflow to true. + APInt sfloordiv_ov(const APInt &RHS, bool &Overflow) const; + // Operations that saturate APInt sadd_sat(const APInt &RHS) const; APInt uadd_sat(const APInt &RHS) const; @@ -2198,6 +2204,26 @@ inline const APInt abdu(const APInt &A, const APInt &B) { return A.uge(B) ? (A - B) : (B - A); } +/// Compute the floor of the signed average of C1 and C2 +APInt avgFloorS(const APInt &C1, const APInt &C2); + +/// Compute the floor of the unsigned average of C1 and C2 +APInt avgFloorU(const APInt &C1, const APInt &C2); + +/// Compute the ceil of the signed average of C1 and C2 +APInt avgCeilS(const APInt &C1, const APInt &C2); + +/// Compute the ceil of the unsigned average of C1 and C2 +APInt avgCeilU(const APInt &C1, const APInt &C2); + +/// Performs (2*N)-bit multiplication on sign-extended operands. +/// Returns the high N bits of the multiplication result. +APInt mulhs(const APInt &C1, const APInt &C2); + +/// Performs (2*N)-bit multiplication on zero-extended operands. +/// Returns the high N bits of the multiplication result. +APInt mulhu(const APInt &C1, const APInt &C2); + /// Compute GCD of two unsigned APInt values. /// /// This function returns the greatest common divisor of the two APInt values diff --git a/llvm/include/llvm/ADT/SCCIterator.h b/llvm/include/llvm/ADT/SCCIterator.h index e743ae7c11edbc0ac678b3907eda06429a129bea..3bd103c13f19f9f039c9a5baee64eb64546a2661 100644 --- a/llvm/include/llvm/ADT/SCCIterator.h +++ b/llvm/include/llvm/ADT/SCCIterator.h @@ -281,14 +281,14 @@ class scc_member_iterator { if (G1 == G2) return false; - // Make the smaller rank tree a direct child or the root of high rank tree. - if (G1->Rank < G1->Rank) + // Make the smaller rank tree a direct child of high rank tree. + if (G1->Rank < G2->Rank) G1->Group = G2; else { G2->Group = G1; // If the ranks are the same, increment root of one tree by one. if (G1->Rank == G2->Rank) - G2->Rank++; + G1->Rank++; } return true; } diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h index 5ac549c44756051321863d5c5d3c1ab7515ce9f0..02a3074ae1f0d7cfc9059728ec5775b9d16b7a48 100644 --- a/llvm/include/llvm/ADT/STLExtras.h +++ b/llvm/include/llvm/ADT/STLExtras.h @@ -1945,6 +1945,19 @@ auto partition(R &&Range, UnaryPredicate P) { return std::partition(adl_begin(Range), adl_end(Range), P); } +/// Provide wrappers to std::binary_search which take ranges instead of having +/// to pass begin/end explicitly. +template <typename R, typename T> auto binary_search(R &&Range, T &&Value) { + return std::binary_search(adl_begin(Range), adl_end(Range), + std::forward<T>(Value)); +} + +template <typename R, typename T, typename Compare> +auto binary_search(R &&Range, T &&Value, Compare C) { + return std::binary_search(adl_begin(Range), adl_end(Range), + std::forward<T>(Value), C); +} + /// Provide wrappers to std::lower_bound which take ranges instead of having to /// pass begin/end explicitly. template <typename R, typename T> auto lower_bound(R &&Range, T &&Value) { diff --git a/llvm/include/llvm/Analysis/ConstantFolding.h b/llvm/include/llvm/Analysis/ConstantFolding.h index fd885a8c0ea3e5b3e2008f0c1768f646fcefa6e5..c54b1e8f01d2b650e08d3e7de78028917396af85 100644 --- a/llvm/include/llvm/Analysis/ConstantFolding.h +++ b/llvm/include/llvm/Analysis/ConstantFolding.h @@ -22,6 +22,11 @@ #include <stdint.h> namespace llvm { + +namespace Intrinsic { +using ID = unsigned; +} + class APInt; template <typename T> class ArrayRef; class CallBase; @@ -187,6 +192,10 @@ Constant *ConstantFoldCall(const CallBase *Call, Function *F, ArrayRef<Constant *> Operands, const TargetLibraryInfo *TLI = nullptr); +Constant *ConstantFoldBinaryIntrinsic(Intrinsic::ID ID, Constant *LHS, + Constant *RHS, Type *Ty, + Instruction *FMFSource); + /// ConstantFoldLoadThroughBitcast - try to cast constant to destination type /// returning null if unsuccessful. Can cast pointer to pointer or pointer to /// integer and vice versa if their sizes are equal. diff --git a/llvm/include/llvm/Analysis/EHUtils.h b/llvm/include/llvm/Analysis/EHUtils.h index f2ff6cbd2e9036b073b9040a17e2e9debf1ff1e2..3ad0878bd64f88b97c974b15179820661d8a4000 100644 --- a/llvm/include/llvm/Analysis/EHUtils.h +++ b/llvm/include/llvm/Analysis/EHUtils.h @@ -79,7 +79,6 @@ static void computeEHOnlyBlocks(FunctionT &F, DenseSet<BlockT *> &EHBlocks) { } } - EHBlocks.clear(); for (auto Entry : Statuses) { if (Entry.second == EH) EHBlocks.insert(Entry.first); diff --git a/llvm/include/llvm/Analysis/IndirectCallVisitor.h b/llvm/include/llvm/Analysis/IndirectCallVisitor.h index 0825e19ecd2d24008ed832216c5163698405e1b8..50815f4e3e839859ca0cf40c5adfa665495c227c 100644 --- a/llvm/include/llvm/Analysis/IndirectCallVisitor.h +++ b/llvm/include/llvm/Analysis/IndirectCallVisitor.h @@ -16,23 +16,75 @@ #include <vector> namespace llvm { -// Visitor class that finds all indirect call. +// Visitor class that finds indirect calls or instructions that gives vtable +// value, depending on Type. struct PGOIndirectCallVisitor : public InstVisitor<PGOIndirectCallVisitor> { + enum class InstructionType { + kIndirectCall = 0, + kVTableVal = 1, + }; std::vector<CallBase *> IndirectCalls; - PGOIndirectCallVisitor() = default; + std::vector<Instruction *> ProfiledAddresses; + PGOIndirectCallVisitor(InstructionType Type) : Type(Type) {} void visitCallBase(CallBase &Call) { - if (Call.isIndirectCall()) + if (!Call.isIndirectCall()) + return; + + if (Type == InstructionType::kIndirectCall) { IndirectCalls.push_back(&Call); + return; + } + + assert(Type == InstructionType::kVTableVal && "Control flow guaranteed"); + + LoadInst *LI = dyn_cast<LoadInst>(Call.getCalledOperand()); + // The code pattern to look for + // + // %vtable = load ptr, ptr %b + // %vfn = getelementptr inbounds ptr, ptr %vtable, i64 1 + // %2 = load ptr, ptr %vfn + // %call = tail call i32 %2(ptr %b) + // + // %vtable is the vtable address value to profile, and + // %2 is the indirect call target address to profile. + if (LI != nullptr) { + Value *Ptr = LI->getPointerOperand(); + Value *VTablePtr = Ptr->stripInBoundsConstantOffsets(); + // This is a heuristic to find address feeding instructions. + // FIXME: Add support in the frontend so LLVM type intrinsics are + // emitted without LTO. This way, added intrinsics could filter + // non-vtable instructions and reduce instrumentation overhead. + // Since a non-vtable profiled address is not within the address + // range of vtable objects, it's stored as zero in indexed profiles. + // A pass that looks up symbol with an zero hash will (almost) always + // find nullptr and skip the actual transformation (e.g., comparison + // of symbols). So the performance overhead from non-vtable profiled + // address is negligible if exists at all. Comparing loaded address + // with symbol address guarantees correctness. + if (VTablePtr != nullptr && isa<Instruction>(VTablePtr)) + ProfiledAddresses.push_back(cast<Instruction>(VTablePtr)); + } } + +private: + InstructionType Type; }; -// Helper function that finds all indirect call sites. inline std::vector<CallBase *> findIndirectCalls(Function &F) { - PGOIndirectCallVisitor ICV; + PGOIndirectCallVisitor ICV( + PGOIndirectCallVisitor::InstructionType::kIndirectCall); ICV.visit(F); return ICV.IndirectCalls; } + +inline std::vector<Instruction *> findVTableAddrs(Function &F) { + PGOIndirectCallVisitor ICV( + PGOIndirectCallVisitor::InstructionType::kVTableVal); + ICV.visit(F); + return ICV.ProfiledAddresses; +} + } // namespace llvm #endif diff --git a/llvm/include/llvm/Analysis/InlineCost.h b/llvm/include/llvm/Analysis/InlineCost.h index 3a760e0a85cecf26f7cf154db435ed5103e01b5f..c5978ce54fc18b256d4942e1b1237d1211702e25 100644 --- a/llvm/include/llvm/Analysis/InlineCost.h +++ b/llvm/include/llvm/Analysis/InlineCost.h @@ -65,7 +65,8 @@ const char MaxInlineStackSizeAttributeName[] = "inline-max-stacksize"; // The cost-benefit pair computed by cost-benefit analysis. class CostBenefitPair { public: - CostBenefitPair(APInt Cost, APInt Benefit) : Cost(Cost), Benefit(Benefit) {} + CostBenefitPair(APInt Cost, APInt Benefit) + : Cost(std::move(Cost)), Benefit(std::move(Benefit)) {} const APInt &getCost() const { return Cost; } diff --git a/llvm/include/llvm/Analysis/InstSimplifyFolder.h b/llvm/include/llvm/Analysis/InstSimplifyFolder.h index 23e2ea80e8cbe6f88db9ba9539a4b290bd720479..8a3269d6add0e092ce4e1d23316d68426ad5090e 100644 --- a/llvm/include/llvm/Analysis/InstSimplifyFolder.h +++ b/llvm/include/llvm/Analysis/InstSimplifyFolder.h @@ -117,6 +117,12 @@ public: return simplifyCastInst(Op, V, DestTy, SQ); } + Value *FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty, + Instruction *FMFSource) const override { + return simplifyBinaryIntrinsic(ID, Ty, LHS, RHS, SQ, + dyn_cast_if_present<CallBase>(FMFSource)); + } + //===--------------------------------------------------------------------===// // Cast/Conversion Operators //===--------------------------------------------------------------------===// diff --git a/llvm/include/llvm/Analysis/InstructionSimplify.h b/llvm/include/llvm/Analysis/InstructionSimplify.h index a29955a06cf4e025386930ad006101c22b873086..03d7ad12c12d8f18b0e39c4d605c944882df7ada 100644 --- a/llvm/include/llvm/Analysis/InstructionSimplify.h +++ b/llvm/include/llvm/Analysis/InstructionSimplify.h @@ -186,6 +186,11 @@ Value *simplifyExtractElementInst(Value *Vec, Value *Idx, Value *simplifyCastInst(unsigned CastOpc, Value *Op, Type *Ty, const SimplifyQuery &Q); +/// Given operands for a BinaryIntrinsic, fold the result or return null. +Value *simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType, Value *Op0, + Value *Op1, const SimplifyQuery &Q, + const CallBase *Call); + /// Given operands for a ShuffleVectorInst, fold the result or return null. /// See class ShuffleVectorInst for a description of the mask representation. Value *simplifyShuffleVectorInst(Value *Op0, Value *Op1, ArrayRef<int> Mask, diff --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h index 37ce1518f00c083c6848bd41a718bd873fa5bb08..bb282a1b73d320b5a3bc30357b3c6f3047d8e739 100644 --- a/llvm/include/llvm/Analysis/MemoryBuiltins.h +++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h @@ -196,7 +196,8 @@ public: T Offset; SizeOffsetType() = default; - SizeOffsetType(T Size, T Offset) : Size(Size), Offset(Offset) {} + SizeOffsetType(T Size, T Offset) + : Size(std::move(Size)), Offset(std::move(Offset)) {} bool knownSize() const { return C::known(Size); } bool knownOffset() const { return C::known(Offset); } @@ -215,9 +216,10 @@ public: /// \p APInts. struct SizeOffsetAPInt : public SizeOffsetType<APInt, SizeOffsetAPInt> { SizeOffsetAPInt() = default; - SizeOffsetAPInt(APInt Size, APInt Offset) : SizeOffsetType(Size, Offset) {} + SizeOffsetAPInt(APInt Size, APInt Offset) + : SizeOffsetType(std::move(Size), std::move(Offset)) {} - static bool known(APInt V) { return V.getBitWidth() > 1; } + static bool known(const APInt &V) { return V.getBitWidth() > 1; } }; /// Evaluate the size and offset of an object pointed to by a Value* diff --git a/llvm/include/llvm/Analysis/MemoryLocation.h b/llvm/include/llvm/Analysis/MemoryLocation.h index b72a27cab86b349b4feab3a97ba627378ae0097b..7d896c44f46795d28013e86ca0ad32fe8656c7b3 100644 --- a/llvm/include/llvm/Analysis/MemoryLocation.h +++ b/llvm/include/llvm/Analysis/MemoryLocation.h @@ -191,8 +191,14 @@ public: return Value == Other.Value; } + bool operator==(const TypeSize &Other) const { + return hasValue() && getValue() == Other; + } + bool operator!=(const LocationSize &Other) const { return !(*this == Other); } + bool operator!=(const TypeSize &Other) const { return !(*this == Other); } + // Ordering operators are not provided, since it's unclear if there's only one // reasonable way to compare: // - values that don't exist against values that do, and @@ -291,12 +297,6 @@ public: return MemoryLocation(Ptr, LocationSize::beforeOrAfterPointer(), AATags); } - // Return the exact size if the exact size is known at compiletime, - // otherwise return MemoryLocation::UnknownSize. - static uint64_t getSizeOrUnknown(const TypeSize &T) { - return T.isScalable() ? UnknownSize : T.getFixedValue(); - } - MemoryLocation() : Ptr(nullptr), Size(LocationSize::beforeOrAfterPointer()) {} explicit MemoryLocation(const Value *Ptr, LocationSize Size, diff --git a/llvm/include/llvm/Analysis/TargetFolder.h b/llvm/include/llvm/Analysis/TargetFolder.h index 978e1002515fc05c582dd2fb07891f1a01109653..b4105ad76c02e21d152e33dfc597b218cd1af6db 100644 --- a/llvm/include/llvm/Analysis/TargetFolder.h +++ b/llvm/include/llvm/Analysis/TargetFolder.h @@ -191,6 +191,15 @@ public: return nullptr; } + Value *FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty, + Instruction *FMFSource) const override { + auto *C1 = dyn_cast<Constant>(LHS); + auto *C2 = dyn_cast<Constant>(RHS); + if (C1 && C2) + return ConstantFoldBinaryIntrinsic(ID, C1, C2, Ty, FMFSource); + return nullptr; + } + //===--------------------------------------------------------------------===// // Cast/Conversion Operators //===--------------------------------------------------------------------===// diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h index 4eab357f1b33b6079d6cb546604ad569397a5845..bad0a77b0f2da28eec263f8d57b86e82cd7c5029 100644 --- a/llvm/include/llvm/Analysis/TargetTransformInfo.h +++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h @@ -696,6 +696,12 @@ public: /// immediate without having to materialize the immediate into a register. bool isLegalAddImmediate(int64_t Imm) const; + /// Return true if adding the specified scalable immediate is legal, that is + /// the target has add instructions which can add a register with the + /// immediate (multiplied by vscale) without having to materialize the + /// immediate into a register. + bool isLegalAddScalableImmediate(int64_t Imm) const; + /// Return true if the specified immediate is legal icmp immediate, /// that is the target has icmp instructions which can compare a register /// against the immediate without having to materialize the immediate into a @@ -707,11 +713,15 @@ public: /// The type may be VoidTy, in which case only return true if the addressing /// mode is legal for a load/store of any legal type. /// If target returns true in LSRWithInstrQueries(), I may be valid. + /// \param ScalableOffset represents a quantity of bytes multiplied by vscale, + /// an invariant value known only at runtime. Most targets should not accept + /// a scalable offset. + /// /// TODO: Handle pre/postinc as well. bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool HasBaseReg, int64_t Scale, - unsigned AddrSpace = 0, - Instruction *I = nullptr) const; + unsigned AddrSpace = 0, Instruction *I = nullptr, + int64_t ScalableOffset = 0) const; /// Return true if LSR cost of C1 is lower than C2. bool isLSRCostLess(const TargetTransformInfo::LSRCost &C1, @@ -1247,13 +1257,16 @@ public: /// cases or optimizations based on those values. /// \p CxtI is the optional original context instruction, if one exists, to /// provide even more information. + /// \p TLibInfo is used to search for platform specific vector library + /// functions for instructions that might be converted to calls (e.g. frem). InstructionCost getArithmeticInstrCost( unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput, TTI::OperandValueInfo Opd1Info = {TTI::OK_AnyValue, TTI::OP_None}, TTI::OperandValueInfo Opd2Info = {TTI::OK_AnyValue, TTI::OP_None}, ArrayRef<const Value *> Args = ArrayRef<const Value *>(), - const Instruction *CxtI = nullptr) const; + const Instruction *CxtI = nullptr, + const TargetLibraryInfo *TLibInfo = nullptr) const; /// Returns the cost estimation for alternating opcode pattern that can be /// lowered to a single instruction on the target. In X86 this is for the @@ -1835,11 +1848,13 @@ public: std::function<void(Instruction *, unsigned, APInt, APInt &)> SimplifyAndSetOp) = 0; virtual bool isLegalAddImmediate(int64_t Imm) = 0; + virtual bool isLegalAddScalableImmediate(int64_t Imm) = 0; virtual bool isLegalICmpImmediate(int64_t Imm) = 0; virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace, - Instruction *I) = 0; + Instruction *I, + int64_t ScalableOffset) = 0; virtual bool isLSRCostLess(const TargetTransformInfo::LSRCost &C1, const TargetTransformInfo::LSRCost &C2) = 0; virtual bool isNumRegsMajorCostOfLSR() = 0; @@ -2295,14 +2310,17 @@ public: bool isLegalAddImmediate(int64_t Imm) override { return Impl.isLegalAddImmediate(Imm); } + bool isLegalAddScalableImmediate(int64_t Imm) override { + return Impl.isLegalAddScalableImmediate(Imm); + } bool isLegalICmpImmediate(int64_t Imm) override { return Impl.isLegalICmpImmediate(Imm); } bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace, - Instruction *I) override { + Instruction *I, int64_t ScalableOffset) override { return Impl.isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, Scale, - AddrSpace, I); + AddrSpace, I, ScalableOffset); } bool isLSRCostLess(const TargetTransformInfo::LSRCost &C1, const TargetTransformInfo::LSRCost &C2) override { diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h index 7f661bb4a1df209bdb8d8e11a2e604e0b11db735..63c2ef8912b29cfbe094ffe43391b6e058eef018 100644 --- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -216,11 +216,14 @@ public: bool isLegalAddImmediate(int64_t Imm) const { return false; } + bool isLegalAddScalableImmediate(int64_t Imm) const { return false; } + bool isLegalICmpImmediate(int64_t Imm) const { return false; } bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace, - Instruction *I = nullptr) const { + Instruction *I = nullptr, + int64_t ScalableOffset = 0) const { // Guess that only reg and reg+reg addressing is allowed. This heuristic is // taken from the implementation of LSR. return !BaseGV && BaseOffset == 0 && (Scale == 0 || Scale == 1); @@ -711,6 +714,8 @@ public: switch (ICA.getID()) { default: break; + case Intrinsic::allow_runtime_check: + case Intrinsic::allow_ubsan_check: case Intrinsic::annotation: case Intrinsic::assume: case Intrinsic::sideeffect: diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h index e85728aa3c0da073f88873da5ea9e3d5f6d82345..8ebd0d3409c89903de2b3015eac23e88ff0ff5bd 100644 --- a/llvm/include/llvm/AsmParser/LLParser.h +++ b/llvm/include/llvm/AsmParser/LLParser.h @@ -563,8 +563,7 @@ namespace llvm { Type *ExpectedTy = nullptr); bool parseGlobalValue(Type *Ty, Constant *&C); bool parseGlobalTypeAndValue(Constant *&V); - bool parseGlobalValueVector(SmallVectorImpl<Constant *> &Elts, - std::optional<unsigned> *InRangeOp = nullptr); + bool parseGlobalValueVector(SmallVectorImpl<Constant *> &Elts); bool parseOptionalComdat(StringRef GlobalName, Comdat *&C); bool parseSanitizer(GlobalVariable *GV); bool parseMetadataAsValue(Value *&V, PerFunctionState &PFS); diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h index 5863a8d6e8ee84e7a5cf873d8d6c4629d485bc9c..65ccb1b81b3a87f2dbad96e8786ab1b2f0ca9c4c 100644 --- a/llvm/include/llvm/AsmParser/LLToken.h +++ b/llvm/include/llvm/AsmParser/LLToken.h @@ -181,6 +181,7 @@ enum Kind { kw_tailcc, kw_m68k_rtdcc, kw_graalcc, + kw_riscv_vector_cc, // Attributes: kw_attributes, diff --git a/llvm/include/llvm/BinaryFormat/COFF.h b/llvm/include/llvm/BinaryFormat/COFF.h index 72461d0d9c316a3e0add8531364d3270ae00e328..4c31cd847bdfb7e06fa26ecb725d8c1a5ec95356 100644 --- a/llvm/include/llvm/BinaryFormat/COFF.h +++ b/llvm/include/llvm/BinaryFormat/COFF.h @@ -806,6 +806,12 @@ enum Feat00Flags : uint32_t { Kernel = 0x40000000, }; +enum class Arm64ECThunkType : uint8_t { + GuestExit = 0, + Entry = 1, + Exit = 4, +}; + inline bool isReservedSectionNumber(int32_t SectionNumber) { return SectionNumber <= 0; } diff --git a/llvm/include/llvm/BinaryFormat/DXContainer.h b/llvm/include/llvm/BinaryFormat/DXContainer.h index a28e19edb4c6a624c066b8edda66d130b4726bf8..e8d03f806715f1da773322b75324a0a4d713baca 100644 --- a/llvm/include/llvm/BinaryFormat/DXContainer.h +++ b/llvm/include/llvm/BinaryFormat/DXContainer.h @@ -141,7 +141,7 @@ enum class PartType { #include "DXContainerConstants.def" }; -#define SHADER_FEATURE_FLAG(Num, Val, Str) Val = 1ull << Num, +#define SHADER_FEATURE_FLAG(Num, DxilModuleNum, Val, Str) Val = 1ull << Num, enum class FeatureFlags : uint64_t { #include "DXContainerConstants.def" }; @@ -424,6 +424,22 @@ struct ResourceBindInfo : public v0::ResourceBindInfo { }; } // namespace v2 + +namespace v3 { +struct RuntimeInfo : public v2::RuntimeInfo { + uint32_t EntryNameOffset; + + void swapBytes() { + v2::RuntimeInfo::swapBytes(); + sys::swapByteOrder(EntryNameOffset); + } + + void swapBytes(Triple::EnvironmentType Stage) { + v2::RuntimeInfo::swapBytes(Stage); + } +}; + +} // namespace v3 } // namespace PSV #define COMPONENT_PRECISION(Val, Enum) Enum = Val, diff --git a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def index 80ed86bc3a499e9c2b0749f6b02cf8b69ada91f4..62dc573555198b46a3c9cc051b82e5892bfa1d24 100644 --- a/llvm/include/llvm/BinaryFormat/DXContainerConstants.def +++ b/llvm/include/llvm/BinaryFormat/DXContainerConstants.def @@ -9,46 +9,63 @@ CONTAINER_PART(OSG1) CONTAINER_PART(PSG1) #undef CONTAINER_PART -#endif +#endif // CONTAINER_PART #ifdef SHADER_FEATURE_FLAG -SHADER_FEATURE_FLAG(0, Doubles, "Double-precision floating point") -SHADER_FEATURE_FLAG(1, ComputeShadersPlusRawAndStructuredBuffers, "Raw and Structured buffers") -SHADER_FEATURE_FLAG(2, UAVsAtEveryStage, "UAVs at every shader stage") -SHADER_FEATURE_FLAG(3, Max64UAVs, "64 UAV slots") -SHADER_FEATURE_FLAG(4, MinimumPrecision, "Minimum-precision data types") -SHADER_FEATURE_FLAG(5, DX11_1_DoubleExtensions, "Double-precision extensions for 11.1") -SHADER_FEATURE_FLAG(6, DX11_1_ShaderExtensions, "Shader extensions for 11.1") -SHADER_FEATURE_FLAG(7, LEVEL9ComparisonFiltering, "Comparison filtering for feature level 9") -SHADER_FEATURE_FLAG(8, TiledResources, "Tiled resources") -SHADER_FEATURE_FLAG(9, StencilRef, "PS Output Stencil Ref") -SHADER_FEATURE_FLAG(10, InnerCoverage, "PS Inner Coverage") -SHADER_FEATURE_FLAG(11, TypedUAVLoadAdditionalFormats, "Typed UAV Load Additional Formats") -SHADER_FEATURE_FLAG(12, ROVs, "Raster Ordered UAVs") -SHADER_FEATURE_FLAG(13, ViewportAndRTArrayIndexFromAnyShaderFeedingRasterizer, "SV_RenderTargetArrayIndex or SV_ViewportArrayIndex from any shader feeding rasterizer") -SHADER_FEATURE_FLAG(14, WaveOps, "Wave level operations") -SHADER_FEATURE_FLAG(15, Int64Ops, "64-Bit integer") -SHADER_FEATURE_FLAG(16, ViewID, "View Instancing") -SHADER_FEATURE_FLAG(17, Barycentrics, "Barycentrics") -SHADER_FEATURE_FLAG(18, NativeLowPrecision, "Use native low precision") -SHADER_FEATURE_FLAG(19, ShadingRate, "Shading Rate") -SHADER_FEATURE_FLAG(20, Raytracing_Tier_1_1, "Raytracing tier 1.1 features") -SHADER_FEATURE_FLAG(21, SamplerFeedback, "Sampler feedback") -SHADER_FEATURE_FLAG(22, AtomicInt64OnTypedResource, "64-bit Atomics on Typed Resources") -SHADER_FEATURE_FLAG(23, AtomicInt64OnGroupShared, "64-bit Atomics on Group Shared") -SHADER_FEATURE_FLAG(24, DerivativesInMeshAndAmpShaders, "Derivatives in mesh and amplification shaders") -SHADER_FEATURE_FLAG(25, ResourceDescriptorHeapIndexing, "Resource descriptor heap indexing") -SHADER_FEATURE_FLAG(26, SamplerDescriptorHeapIndexing, "Sampler descriptor heap indexing") -SHADER_FEATURE_FLAG(27, RESERVED, "<RESERVED>") -SHADER_FEATURE_FLAG(28, AtomicInt64OnHeapResource, "64-bit Atomics on Heap Resources") -SHADER_FEATURE_FLAG(29, AdvancedTextureOps, "Advanced Texture Ops") -SHADER_FEATURE_FLAG(30, WriteableMSAATextures, "Writeable MSAA Textures") - -SHADER_FEATURE_FLAG(31, NextUnusedBit, "Next reserved shader flag bit (not a flag)") +// SHADER_FEATURE_FLAG(bit offset for the shader info flag, bit offset for DXIL module flag, name, description. + +SHADER_FEATURE_FLAG(0, 2, Doubles, "Double-precision floating point") +SHADER_FEATURE_FLAG(1, 17, ComputeShadersPlusRawAndStructuredBuffers, "Raw and Structured buffers") +SHADER_FEATURE_FLAG(2, 16, UAVsAtEveryStage, "UAVs at every shader stage") +SHADER_FEATURE_FLAG(3, 15, Max64UAVs, "64 UAV slots") +SHADER_FEATURE_FLAG(4, -1, MinimumPrecision, "Minimum-precision data types") +SHADER_FEATURE_FLAG(5, 6, DX11_1_DoubleExtensions, "Double-precision extensions for 11.1") +SHADER_FEATURE_FLAG(6, 7, DX11_1_ShaderExtensions, "Shader extensions for 11.1") +SHADER_FEATURE_FLAG(7, 14, LEVEL9ComparisonFiltering, "Comparison filtering for feature level 9") +SHADER_FEATURE_FLAG(8, 12, TiledResources, "Tiled resources") +SHADER_FEATURE_FLAG(9, 11, StencilRef, "PS Output Stencil Ref") +SHADER_FEATURE_FLAG(10, 10, InnerCoverage, "PS Inner Coverage") +SHADER_FEATURE_FLAG(11, 13, TypedUAVLoadAdditionalFormats, "Typed UAV Load Additional Formats") +SHADER_FEATURE_FLAG(12, 18, ROVs, "Raster Ordered UAVs") +SHADER_FEATURE_FLAG(13, 9, ViewportAndRTArrayIndexFromAnyShaderFeedingRasterizer, "SV_RenderTargetArrayIndex or SV_ViewportArrayIndex from any shader feeding rasterizer") +SHADER_FEATURE_FLAG(14, 19, WaveOps, "Wave level operations") +SHADER_FEATURE_FLAG(15, 20, Int64Ops, "64-Bit integer") +SHADER_FEATURE_FLAG(16, 21, ViewID, "View Instancing") +SHADER_FEATURE_FLAG(17, 22, Barycentrics, "Barycentrics") +SHADER_FEATURE_FLAG(18, -1, NativeLowPrecision, "Use native low precision") +SHADER_FEATURE_FLAG(19, 24, ShadingRate, "Shading Rate") +SHADER_FEATURE_FLAG(20, 25, Raytracing_Tier_1_1, "Raytracing tier 1.1 features") +SHADER_FEATURE_FLAG(21, 26, SamplerFeedback, "Sampler feedback") +SHADER_FEATURE_FLAG(22, 27, AtomicInt64OnTypedResource, "64-bit Atomics on Typed Resources") +SHADER_FEATURE_FLAG(23, 28, AtomicInt64OnGroupShared, "64-bit Atomics on Group Shared") +SHADER_FEATURE_FLAG(24, 29, DerivativesInMeshAndAmpShaders, "Derivatives in mesh and amplification shaders") +SHADER_FEATURE_FLAG(25, 30, ResourceDescriptorHeapIndexing, "Resource descriptor heap indexing") +SHADER_FEATURE_FLAG(26, 31, SamplerDescriptorHeapIndexing, "Sampler descriptor heap indexing") +SHADER_FEATURE_FLAG(27, 63, RESERVED, "<RESERVED>") +SHADER_FEATURE_FLAG(28, 32, AtomicInt64OnHeapResource, "64-bit Atomics on Heap Resources") +SHADER_FEATURE_FLAG(29, 34, AdvancedTextureOps, "Advanced Texture Ops") +SHADER_FEATURE_FLAG(30, 35, WriteableMSAATextures, "Writeable MSAA Textures") + +SHADER_FEATURE_FLAG(31, 36, NextUnusedBit, "Next reserved shader flag bit (not a flag)") #undef SHADER_FEATURE_FLAG -#endif +#endif // SHADER_FEATURE_FLAG + +#ifdef DXIL_MODULE_FLAG + +// Only save DXIL module flags which not map to feature flags here. +DXIL_MODULE_FLAG( 0, DisableOptimizations, "D3D11_1_SB_GLOBAL_FLAG_SKIP_OPTIMIZATION") +DXIL_MODULE_FLAG( 1, DisableMathRefactoring, "D3D10_SB_GLOBAL_FLAG_REFACTORING_ALLOWED") +DXIL_MODULE_FLAG( 3, ForceEarlyDepthStencil, "D3D11_SB_GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL") +DXIL_MODULE_FLAG( 4, EnableRawAndStructuredBuffers, "D3D11_SB_GLOBAL_FLAG_ENABLE_RAW_AND_STRUCTURED_BUFFERS") +DXIL_MODULE_FLAG( 5, LowPrecisionPresent, "D3D11_1_SB_GLOBAL_FLAG_ENABLE_MINIMUM_PRECISION") +DXIL_MODULE_FLAG( 8, AllResourcesBound, "D3D12_SB_GLOBAL_FLAG_ALL_RESOURCES_BOUND") +DXIL_MODULE_FLAG(23, UseNativeLowPrecision, "Native 16bit types enabled") +DXIL_MODULE_FLAG(33, ResMayNotAlias, "Any UAV may not alias any other UAV") + +#undef DXIL_MODULE_FLAG +#endif // DXIL_MODULE_FLAG #ifdef SEMANTIC_KIND @@ -86,7 +103,7 @@ SEMANTIC_KIND(30, CullPrimitive) SEMANTIC_KIND(30, Invalid) #undef SEMANTIC_KIND -#endif +#endif // SEMANTIC_KIND #ifdef COMPONENT_TYPE @@ -102,7 +119,7 @@ COMPONENT_TYPE(8, SInt64) COMPONENT_TYPE(9, Float64) #undef COMPONENT_TYPE -#endif +#endif // COMPONENT_TYPE #ifdef COMPONENT_PRECISION @@ -116,7 +133,7 @@ COMPONENT_PRECISION(0xf0, Any16) COMPONENT_PRECISION(0xf1, Any10) #undef COMPONENT_PRECISION -#endif +#endif // COMPONENT_PRECISION #ifdef INTERPOLATION_MODE @@ -131,7 +148,7 @@ INTERPOLATION_MODE(7, LinearNoperspectiveSample) INTERPOLATION_MODE(8, Invalid) #undef INTERPOLATION_MODE -#endif +#endif // INTERPOLATION_MODE #ifdef D3D_SYSTEM_VALUE @@ -165,4 +182,4 @@ D3D_SYSTEM_VALUE(70, InnerCoverage) #undef D3D_SYSTEM_VALUE -#endif +#endif // D3D_SYSTEM_VALUE diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def index e70b58d5ea50fc6c3f747cf59e0b5b8917d16015..8cf90de637a3d5662c4128a78986f0132f2e33a4 100644 --- a/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -1040,6 +1040,8 @@ HANDLE_DW_CC(0xca, LLVM_PreserveAll) HANDLE_DW_CC(0xcb, LLVM_X86RegCall) HANDLE_DW_CC(0xcc, LLVM_M68kRTD) HANDLE_DW_CC(0xcd, LLVM_PreserveNone) +HANDLE_DW_CC(0xce, LLVM_RISCVVectorCall) +HANDLE_DW_CC(0xcf, LLVM_SwiftTail) // From GCC source code (include/dwarf2.h): This DW_CC_ value is not currently // generated by any toolchain. It is used internally to GDB to indicate OpenCL // C functions that have been compiled with the IBM XL C for OpenCL compiler and diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index bace3a92677a823a5eb5039bb6d63830ea5e4a32..877f3f7862c8ba844f31348ce23466d19b3a298a 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -1141,6 +1141,8 @@ enum : unsigned { SHT_CSKY_ATTRIBUTES = 0x70000001U, + SHT_HEXAGON_ATTRIBUTES = 0x70000003U, + SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type. SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. SHT_HIUSER = 0xffffffff // Highest type reserved for applications. diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index c0a52d64a101d05968238025d93cab8e74fba938..909eb833c601a9dab88d39e0bdebea09b7b2e9ac 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -399,18 +399,19 @@ enum ConstantsCodes { CST_CODE_DATA = 22, // DATA: [n x elements] CST_CODE_INLINEASM_OLD2 = 23, // INLINEASM: [sideeffect|alignstack| // asmdialect,asmstr,conststr] - CST_CODE_CE_GEP_WITH_INRANGE_INDEX = 24, // [opty, flags, n x operands] - CST_CODE_CE_UNOP = 25, // CE_UNOP: [opcode, opval] - CST_CODE_POISON = 26, // POISON - CST_CODE_DSO_LOCAL_EQUIVALENT = 27, // DSO_LOCAL_EQUIVALENT [gvty, gv] - CST_CODE_INLINEASM_OLD3 = 28, // INLINEASM: [sideeffect|alignstack| - // asmdialect|unwind, - // asmstr,conststr] - CST_CODE_NO_CFI_VALUE = 29, // NO_CFI [ fty, f ] - CST_CODE_INLINEASM = 30, // INLINEASM: [fnty, - // sideeffect|alignstack| - // asmdialect|unwind, - // asmstr,conststr] + CST_CODE_CE_GEP_WITH_INRANGE_INDEX_OLD = 24, // [opty, flags, n x operands] + CST_CODE_CE_UNOP = 25, // CE_UNOP: [opcode, opval] + CST_CODE_POISON = 26, // POISON + CST_CODE_DSO_LOCAL_EQUIVALENT = 27, // DSO_LOCAL_EQUIVALENT [gvty, gv] + CST_CODE_INLINEASM_OLD3 = 28, // INLINEASM: [sideeffect|alignstack| + // asmdialect|unwind, + // asmstr,conststr] + CST_CODE_NO_CFI_VALUE = 29, // NO_CFI [ fty, f ] + CST_CODE_INLINEASM = 30, // INLINEASM: [fnty, + // sideeffect|alignstack| + // asmdialect|unwind, + // asmstr,conststr] + CST_CODE_CE_GEP_WITH_INRANGE = 31, // [opty, flags, range, n x operands] }; /// CastOpcodes - These are values used in the bitcode files to encode which @@ -491,6 +492,13 @@ enum OverflowingBinaryOperatorOptionalFlags { OBO_NO_SIGNED_WRAP = 1 }; +/// TruncInstOptionalFlags - Flags for serializing +/// TruncInstOptionalFlags's SubclassOptionalData contents. +enum TruncInstOptionalFlags { + TIO_NO_UNSIGNED_WRAP = 0, + TIO_NO_SIGNED_WRAP = 1 +}; + /// FastMath Flags /// This is a fixed layout derived from the bitcode emitted by LLVM 5.0 /// intended to decouple the in-memory representation from the serialization. @@ -624,6 +632,17 @@ enum FunctionCodes { // operation, align, vol, // ordering, synchscope] FUNC_CODE_BLOCKADDR_USERS = 60, // BLOCKADDR_USERS: [value...] + + FUNC_CODE_DEBUG_RECORD_VALUE = + 61, // [DILocation, DILocalVariable, DIExpression, ValueAsMetadata] + FUNC_CODE_DEBUG_RECORD_DECLARE = + 62, // [DILocation, DILocalVariable, DIExpression, ValueAsMetadata] + FUNC_CODE_DEBUG_RECORD_ASSIGN = + 63, // [DILocation, DILocalVariable, DIExpression, ValueAsMetadata, + // DIAssignID, DIExpression (addr), ValueAsMetadata (addr)] + FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE = + 64, // [DILocation, DILocalVariable, DIExpression, Value] + FUNC_CODE_DEBUG_RECORD_LABEL = 65, // [DILocation, DILabel] }; enum UseListCodes { diff --git a/llvm/include/llvm/CodeGen/AccelTable.h b/llvm/include/llvm/CodeGen/AccelTable.h index 6ee817a7124dc379a537ff8745404fdb5094d375..cff8fcbaf2cd7b04e2cc8263235296ef36738a35 100644 --- a/llvm/include/llvm/CodeGen/AccelTable.h +++ b/llvm/include/llvm/CodeGen/AccelTable.h @@ -353,7 +353,7 @@ public: dwarf::Index Index; dwarf::Form Form; }; - DebugNamesAbbrev(uint32_t DieTag) : DieTag(DieTag) {} + DebugNamesAbbrev(uint32_t DieTag) : DieTag(DieTag), Number(0) {} /// Add attribute encoding to an abbreviation. void addAttribute(const DebugNamesAbbrev::AttributeEncoding &Attr) { AttrVect.push_back(Attr); diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h index 61f6564e8cd79b07f83485087f490c9baa999753..92fa726c31df146640e39fa5d09f24ea51b557d3 100644 --- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h +++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h @@ -328,18 +328,24 @@ public: return getTLI()->isLegalAddImmediate(imm); } + bool isLegalAddScalableImmediate(int64_t Imm) { + return getTLI()->isLegalAddScalableImmediate(Imm); + } + bool isLegalICmpImmediate(int64_t imm) { return getTLI()->isLegalICmpImmediate(imm); } bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, - bool HasBaseReg, int64_t Scale, - unsigned AddrSpace, Instruction *I = nullptr) { + bool HasBaseReg, int64_t Scale, unsigned AddrSpace, + Instruction *I = nullptr, + int64_t ScalableOffset = 0) { TargetLoweringBase::AddrMode AM; AM.BaseGV = BaseGV; AM.BaseOffs = BaseOffset; AM.HasBaseReg = HasBaseReg; AM.Scale = Scale; + AM.ScalableOffset = ScalableOffset; return getTLI()->isLegalAddressingMode(DL, AM, Ty, AddrSpace, I); } diff --git a/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h b/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h index 31af3014afe4e7b52dd9d899b8ad482323b68689..45a47d7333e35a5484763eca80ffdd351de49452 100644 --- a/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -191,7 +191,7 @@ public: /// Collection of dbg.declare instructions handled after argument /// lowering and before ISel proper. SmallPtrSet<const DbgDeclareInst *, 8> PreprocessedDbgDeclares; - SmallPtrSet<const DPValue *, 8> PreprocessedDPVDeclares; + SmallPtrSet<const DbgVariableRecord *, 8> PreprocessedDVRDeclares; /// set - Initialize this FunctionLoweringInfo with the given Function /// and its associated MachineFunction. diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h b/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h index 3c3b91661d5788933114b197702b3b5148df7e81..4c187a3068d8233f84c37bcc2fea24b188ea1629 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h @@ -117,6 +117,9 @@ public: /// vreg that the swifterror should be copied into after the call. Register SwiftErrorVReg; + /// Valid if the call is a controlled convergent operation. + Register ConvergenceCtrlToken; + /// Original IR callsite corresponding to this call, if available. const CallBase *CB = nullptr; @@ -584,6 +587,7 @@ public: bool lowerCall(MachineIRBuilder &MIRBuilder, const CallBase &Call, ArrayRef<Register> ResRegs, ArrayRef<ArrayRef<Register>> ArgRegs, Register SwiftErrorVReg, + Register ConvergenceCtrlToken, std::function<unsigned()> GetCalleeReg) const; /// For targets which want to use big-endian can enable it with diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h index 23728636498ba06dc709b31606605e17443fde28..3af32043391fec2eba6e7cf3e4cc17bf3b36ab9a 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -594,6 +594,10 @@ public: /// This variant does not erase \p MI after calling the build function. void applyBuildFnNoErase(MachineInstr &MI, BuildFnTy &MatchInfo); + /// Use a function which takes in a MachineIRBuilder to perform a combine. + /// By default, it erases the instruction \p MI from the function. + void applyBuildFnMO(const MachineOperand &MO, BuildFnTy &MatchInfo); + bool matchOrShiftToFunnelShift(MachineInstr &MI, BuildFnTy &MatchInfo); bool matchFunnelShiftToRotate(MachineInstr &MI); void applyFunnelShiftToRotate(MachineInstr &MI); @@ -673,6 +677,14 @@ public: bool matchSDivByConst(MachineInstr &MI); void applySDivByConst(MachineInstr &MI); + /// Given an G_SDIV \p MI expressing a signed divided by a pow2 constant, + /// return expressions that implements it by shifting. + bool matchDivByPow2(MachineInstr &MI, bool IsSigned); + void applySDivByPow2(MachineInstr &MI); + /// Given an G_UDIV \p MI expressing an unsigned divided by a pow2 constant, + /// return expressions that implements it by shifting. + void applyUDivByPow2(MachineInstr &MI); + // G_UMULH x, (1 << c)) -> x >> (bitwidth - c) bool matchUMulHToLShr(MachineInstr &MI); void applyUMulHToLShr(MachineInstr &MI); @@ -696,10 +708,6 @@ public: /// (G_*MULO x, 0) -> 0 + no carry out bool matchMulOBy0(MachineInstr &MI, BuildFnTy &MatchInfo); - /// Match: - /// (G_*ADDO x, 0) -> x + no carry out - bool matchAddOBy0(MachineInstr &MI, BuildFnTy &MatchInfo); - /// Match: /// (G_*ADDE x, y, 0) -> (G_*ADDO x, y) /// (G_*SUBE x, y, 0) -> (G_*SUBO x, y) @@ -810,12 +818,36 @@ public: /// Combine selects. bool matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo); - /// Combine ands, + /// Combine ands. bool matchAnd(MachineInstr &MI, BuildFnTy &MatchInfo); - /// Combine ors, + /// Combine ors. bool matchOr(MachineInstr &MI, BuildFnTy &MatchInfo); + /// Combine addos. + bool matchAddOverflow(MachineInstr &MI, BuildFnTy &MatchInfo); + + /// Combine extract vector element. + bool matchExtractVectorElement(MachineInstr &MI, BuildFnTy &MatchInfo); + + /// Combine extract vector element with freeze on the vector register. + bool matchExtractVectorElementWithFreeze(const MachineOperand &MO, + BuildFnTy &MatchInfo); + + /// Combine extract vector element with a build vector on the vector register. + bool matchExtractVectorElementWithBuildVector(const MachineOperand &MO, + BuildFnTy &MatchInfo); + + /// Combine extract vector element with a build vector trunc on the vector + /// register. + bool matchExtractVectorElementWithBuildVectorTrunc(const MachineOperand &MO, + BuildFnTy &MatchInfo); + + /// Combine extract vector element with a insert vector element on the vector + /// register and different indices. + bool matchExtractVectorElementWithDifferentIndices(const MachineOperand &MO, + BuildFnTy &MatchInfo); + private: /// Checks for legality of an indexed variant of \p LdSt. bool isIndexedLoadStoreLegal(GLoadStore &LdSt) const; @@ -919,6 +951,7 @@ private: bool isZeroOrZeroSplat(Register Src, bool AllowUndefs); bool isConstantSplatVector(Register Src, int64_t SplatValue, bool AllowUndefs); + bool isConstantOrConstantVectorI(Register Src) const; std::optional<APInt> getConstantOrConstantSplatVector(Register Src); diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h index 8e456015cd37365182c49b12eaa53fe01d2e5984..c73ac2c9f55b7b5f18f664fea952a39903b4a964 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h @@ -647,15 +647,15 @@ bool GIMatchTableExecutor::executeMatchTable( unsigned Size = MRI.getType(MO.getReg()).getSizeInBits(); if (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT && - MMO->getSizeInBits() != Size) { + MMO->getSizeInBits().getValue() != Size) { if (handleReject() == RejectAndGiveUp) return false; } else if (MatcherOpcode == GIM_CheckMemorySizeLessThanLLT && - MMO->getSizeInBits() >= Size) { + MMO->getSizeInBits().getValue() >= Size) { if (handleReject() == RejectAndGiveUp) return false; } else if (MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT && - MMO->getSizeInBits() <= Size) + MMO->getSizeInBits().getValue() <= Size) if (handleReject() == RejectAndGiveUp) return false; diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h index f5a6528d10a973db6c806a7005ee1ec5d6adf4ad..25e47114e4a39abc1c8c25b5d9b29a6d599079f5 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h @@ -54,9 +54,9 @@ public: bool isUnordered() const { return getMMO().isUnordered(); } /// Returns the size in bytes of the memory access. - uint64_t getMemSize() const { return getMMO().getSize(); } + LocationSize getMemSize() const { return getMMO().getSize(); } /// Returns the size in bits of the memory access. - uint64_t getMemSizeInBits() const { return getMMO().getSizeInBits(); } + LocationSize getMemSizeInBits() const { return getMMO().getSizeInBits(); } static bool classof(const MachineInstr *MI) { return GenericMachineInstr::classof(MI) && MI->hasOneMemOperand(); @@ -286,6 +286,14 @@ public: } }; +/// Represents a G_BUILD_VECTOR_TRUNC. +class GBuildVectorTrunc : public GMergeLikeInstr { +public: + static bool classof(const MachineInstr *MI) { + return MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR_TRUNC; + } +}; + /// Represents a G_PTR_ADD. class GPtrAdd : public GenericMachineInstr { public: @@ -359,6 +367,8 @@ public: Register getCarryOutReg() const { return getReg(1); } MachineOperand &getLHS() { return getOperand(2); } MachineOperand &getRHS() { return getOperand(3); } + Register getLHSReg() const { return getOperand(2).getReg(); } + Register getRHSReg() const { return getOperand(3).getReg(); } static bool classof(const MachineInstr *MI) { switch (MI->getOpcode()) { @@ -429,6 +439,23 @@ public: } }; +/// Represents overflowing add operations. +/// G_UADDO, G_SADDO +class GAddCarryOut : public GBinOpCarryOut { +public: + bool isSigned() const { return getOpcode() == TargetOpcode::G_SADDO; } + + static bool classof(const MachineInstr *MI) { + switch (MI->getOpcode()) { + case TargetOpcode::G_UADDO: + case TargetOpcode::G_SADDO: + return true; + default: + return false; + } + } +}; + /// Represents overflowing add/sub operations that also consume a carry-in. /// G_UADDE, G_SADDE, G_USUBE, G_SSUBE class GAddSubCarryInOut : public GAddSubCarryOut { @@ -720,6 +747,39 @@ public: }; }; +/// Represents an extract vector element. +class GExtractVectorElement : public GenericMachineInstr { +public: + Register getVectorReg() const { return getOperand(1).getReg(); } + Register getIndexReg() const { return getOperand(2).getReg(); } + + static bool classof(const MachineInstr *MI) { + return MI->getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT; + } +}; + +/// Represents an insert vector element. +class GInsertVectorElement : public GenericMachineInstr { +public: + Register getVectorReg() const { return getOperand(1).getReg(); } + Register getElementReg() const { return getOperand(2).getReg(); } + Register getIndexReg() const { return getOperand(3).getReg(); } + + static bool classof(const MachineInstr *MI) { + return MI->getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT; + } +}; + +/// Represents a freeze. +class GFreeze : public GenericMachineInstr { +public: + Register getSourceReg() const { return getOperand(1).getReg(); } + + static bool classof(const MachineInstr *MI) { + return MI->getOpcode() == TargetOpcode::G_FREEZE; + } +}; + } // namespace llvm #endif // LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h index bfac54a65c5b4ea6a61044ad14a82f39bd27f079..5f28908e998a9bdd619aaf0fe4b35e01eb006104 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -205,7 +205,7 @@ private: bool translate(const Constant &C, Register Reg); /// Examine any debug-info attached to the instruction (in the form of - /// DPValues) and translate it. + /// DbgRecords) and translate it. void translateDbgInfo(const Instruction &Inst, MachineIRBuilder &MIRBuilder); @@ -243,6 +243,18 @@ private: bool translateMemFunc(const CallInst &CI, MachineIRBuilder &MIRBuilder, unsigned Opcode); + /// Translate an LLVM trap intrinsic (trap, debugtrap, ubsantrap). + bool translateTrap(const CallInst &U, MachineIRBuilder &MIRBuilder, + unsigned Opcode); + + // Translate @llvm.experimental.vector.interleave2 and + // @llvm.experimental.vector.deinterleave2 intrinsics for fixed-width vector + // types into vector shuffles. + bool translateVectorInterleave2Intrinsic(const CallInst &CI, + MachineIRBuilder &MIRBuilder); + bool translateVectorDeinterleave2Intrinsic(const CallInst &CI, + MachineIRBuilder &MIRBuilder); + void getStackGuard(Register DstReg, MachineIRBuilder &MIRBuilder); bool translateOverflowIntrinsic(const CallInst &CI, unsigned Op, @@ -579,6 +591,10 @@ private: return false; } + bool translateConvergenceControlIntrinsic(const CallInst &CI, + Intrinsic::ID ID, + MachineIRBuilder &MIRBuilder); + /// @} // Builder for machine instruction a la IRBuilder. @@ -697,6 +713,23 @@ private: return Regs[0]; } + Register getOrCreateConvergenceTokenVReg(const Value &Token) { + assert(Token.getType()->isTokenTy()); + auto &Regs = *VMap.getVRegs(Token); + if (!Regs.empty()) { + assert(Regs.size() == 1 && + "Expected a single register for convergence tokens."); + return Regs[0]; + } + + auto Reg = MRI->createGenericVirtualRegister(LLT::token()); + Regs.push_back(Reg); + auto &Offsets = *VMap.getOffsets(Token); + if (Offsets.empty()) + Offsets.push_back(0); + return Reg; + } + /// Allocate some vregs and offsets in the VMap. Then populate just the /// offsets while leaving the vregs empty. ValueToVRegInfo::VRegListT &allocateVRegs(const Value &Val); diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h index da330b517c280143f2cc3effd91acb442828c338..ca62f38061b115445bfc002ee82c0fc0e81e1eb1 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h @@ -432,9 +432,13 @@ public: DestTy.isVector() ? CastSrcTy.getNumElements() / NumDefs : 1; LLT UnmergeTy = CastSrcTy.changeElementCount( ElementCount::getFixed(UnmergeNumElts)); + LLT SrcWideTy = + SrcTy.changeElementCount(ElementCount::getFixed(UnmergeNumElts)); if (isInstUnsupported( - {TargetOpcode::G_UNMERGE_VALUES, {UnmergeTy, CastSrcTy}})) + {TargetOpcode::G_UNMERGE_VALUES, {UnmergeTy, CastSrcTy}}) || + LI.getAction({TargetOpcode::G_TRUNC, {SrcWideTy, UnmergeTy}}) + .Action == LegalizeActions::MoreElements) return false; Builder.setInstr(MI); diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index 5bb3692f0a46b40f34eb45c33e63f754a0eee0a4..284f434fbb9b0ca492593d70c70352c665c77733 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -429,6 +429,7 @@ public: LegalizeResult lowerDIVREM(MachineInstr &MI); LegalizeResult lowerAbsToAddXor(MachineInstr &MI); LegalizeResult lowerAbsToMaxNeg(MachineInstr &MI); + LegalizeResult lowerAbsToCNeg(MachineInstr &MI); LegalizeResult lowerVectorReduction(MachineInstr &MI); LegalizeResult lowerMemcpyInline(MachineInstr &MI); LegalizeResult lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen = 0); diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h index 6afaea3f3fc5c6fb3ef2d57288e2f360a285142a..82e713f30ea31c89aba6f8ef30f66138bf47a5df 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h @@ -879,7 +879,8 @@ public: } /// Widen the scalar to the next power of two that is at least MinSize. - /// No effect if the type is not a scalar or is a power of two. + /// No effect if the type is a power of two, except if the type is smaller + /// than MinSize, or if the type is a vector type. LegalizeRuleSet &widenScalarToNextPow2(unsigned TypeIdx, unsigned MinSize = 0) { using namespace LegalityPredicates; diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index aaa81342845bffa4079b9da5d9ffbbdd7d53daa4..4c9d85fd9f51404a0bbf36a3c4fffead4e347ade 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -1165,6 +1165,17 @@ public: /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildVScale(const DstOp &Res, const ConstantInt &MinElts); + /// Build and insert \p Res = G_VSCALE \p MinElts + /// + /// G_VSCALE puts the value of the runtime vscale multiplied by \p MinElts + /// into \p Res. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res must be a generic virtual register with scalar type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildVScale(const DstOp &Res, const APInt &MinElts); + /// Build and insert a G_INTRINSIC instruction. /// /// There are four different opcodes based on combinations of whether the @@ -1322,9 +1333,9 @@ public: /// /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder - buildAtomicCmpXchgWithSuccess(Register OldValRes, Register SuccessRes, - Register Addr, Register CmpVal, Register NewVal, - MachineMemOperand &MMO); + buildAtomicCmpXchgWithSuccess(const DstOp &OldValRes, const DstOp &SuccessRes, + const SrcOp &Addr, const SrcOp &CmpVal, + const SrcOp &NewVal, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMIC_CMPXCHG Addr, CmpVal, NewVal, /// MMO`. @@ -1340,8 +1351,9 @@ public: /// registers of the same type. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAtomicCmpXchg(Register OldValRes, Register Addr, - Register CmpVal, Register NewVal, + MachineInstrBuilder buildAtomicCmpXchg(const DstOp &OldValRes, + const SrcOp &Addr, const SrcOp &CmpVal, + const SrcOp &NewVal, MachineMemOperand &MMO); /// Build and insert `OldValRes<def> = G_ATOMICRMW_<Opcode> Addr, Val, MMO`. @@ -2113,6 +2125,11 @@ public: DstMMO, SrcMMO); } + /// Build and insert G_TRAP or G_DEBUGTRAP + MachineInstrBuilder buildTrap(bool Debug = false) { + return buildInstr(Debug ? TargetOpcode::G_DEBUGTRAP : TargetOpcode::G_TRAP); + } + /// Build and insert \p Dst = G_SBFX \p Src, \p LSB, \p Width. MachineInstrBuilder buildSbfx(const DstOp &Dst, const SrcOp &Src, const SrcOp &LSB, const SrcOp &Width) { diff --git a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h index f8900f3434ccaae3a4caa7060410b26d39b858f7..807cec3c177d9fd9f997b92baa8958d4550f0334 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h @@ -308,10 +308,16 @@ std::optional<APFloat> ConstantFoldIntToFloat(unsigned Opcode, LLT DstTy, Register Src, const MachineRegisterInfo &MRI); -/// Tries to constant fold a G_CTLZ operation on \p Src. If \p Src is a vector -/// then it tries to do an element-wise constant fold. +/// Tries to constant fold a counting-zero operation (G_CTLZ or G_CTTZ) on \p +/// Src. If \p Src is a vector then it tries to do an element-wise constant +/// fold. std::optional<SmallVector<unsigned>> -ConstantFoldCTLZ(Register Src, const MachineRegisterInfo &MRI); +ConstantFoldCountZeros(Register Src, const MachineRegisterInfo &MRI, + std::function<unsigned(APInt)> CB); + +std::optional<SmallVector<APInt>> +ConstantFoldICmp(unsigned Pred, const Register Op1, const Register Op2, + const MachineRegisterInfo &MRI); /// Test if the given value is known to have exactly one bit set. This differs /// from computeKnownBits in that it doesn't necessarily determine which bit is diff --git a/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/llvm/include/llvm/CodeGen/MachineFrameInfo.h index 7d11d63d4066f4a500b899e092abaf8bd22e0247..0fe73fec7ee67fb06cff4f176fe726531a027844 100644 --- a/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -638,13 +638,17 @@ public: bool hasTailCall() const { return HasTailCall; } void setHasTailCall(bool V = true) { HasTailCall = V; } - /// Computes the maximum size of a callframe and the AdjustsStack property. + /// Computes the maximum size of a callframe. /// This only works for targets defining /// TargetInstrInfo::getCallFrameSetupOpcode(), getCallFrameDestroyOpcode(), /// and getFrameSize(). /// This is usually computed by the prologue epilogue inserter but some /// targets may call this to compute it earlier. - void computeMaxCallFrameSize(const MachineFunction &MF); + /// If FrameSDOps is passed, the frame instructions in the MF will be + /// inserted into it. + void computeMaxCallFrameSize( + MachineFunction &MF, + std::vector<MachineBasicBlock::iterator> *FrameSDOps = nullptr); /// Return the maximum size of a call frame that must be /// allocated for an outgoing function call. This is only available if diff --git a/llvm/include/llvm/CodeGen/MachineFunction.h b/llvm/include/llvm/CodeGen/MachineFunction.h index a2c90c9f42f38f63025d09eafb3d2f9bd73f1c9b..470997b31fe85fe69fe0e54d86882f271fed28bd 100644 --- a/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/llvm/include/llvm/CodeGen/MachineFunction.h @@ -481,9 +481,11 @@ public: assert(Arg < (1 << 16) && "Arg out of range"); } }; - /// Vector of call argument and its forwarding register. - using CallSiteInfo = SmallVector<ArgRegPair, 1>; - using CallSiteInfoImpl = SmallVectorImpl<ArgRegPair>; + + struct CallSiteInfo { + /// Vector of call argument and its forwarding register. + SmallVector<ArgRegPair, 1> ArgRegPairs; + }; private: Delegate *TheDelegate = nullptr; @@ -1026,18 +1028,27 @@ public: /// MachineMemOperands are owned by the MachineFunction and need not be /// explicitly deallocated. MachineMemOperand *getMachineMemOperand( - MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, uint64_t s, + MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr, SyncScope::ID SSID = SyncScope::System, AtomicOrdering Ordering = AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic); - MachineMemOperand *getMachineMemOperand( - MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, - Align base_alignment, const AAMDNodes &AAInfo = AAMDNodes(), + MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LocationSize Size, + Align BaseAlignment, const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr, SyncScope::ID SSID = SyncScope::System, AtomicOrdering Ordering = AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic); + MachineMemOperand *getMachineMemOperand( + MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, uint64_t Size, + Align BaseAlignment, const AAMDNodes &AAInfo = AAMDNodes(), + const MDNode *Ranges = nullptr, SyncScope::ID SSID = SyncScope::System, + AtomicOrdering Ordering = AtomicOrdering::NotAtomic, + AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic) { + return getMachineMemOperand(PtrInfo, F, LocationSize::precise(Size), + BaseAlignment, AAInfo, Ranges, SSID, Ordering, + FailureOrdering); + } /// getMachineMemOperand - Allocate a new MachineMemOperand by copying /// an existing one, adjusting by an offset and using the given size. @@ -1046,9 +1057,17 @@ public: MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, int64_t Offset, LLT Ty); MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, - int64_t Offset, uint64_t Size) { + int64_t Offset, LocationSize Size) { return getMachineMemOperand( - MMO, Offset, Size == ~UINT64_C(0) ? LLT() : LLT::scalar(8 * Size)); + MMO, Offset, + !Size.hasValue() ? LLT() + : Size.isScalable() + ? LLT::scalable_vector(1, 8 * Size.getValue().getKnownMinValue()) + : LLT::scalar(8 * Size.getValue().getKnownMinValue())); + } + MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, + int64_t Offset, uint64_t Size) { + return getMachineMemOperand(MMO, Offset, LocationSize::precise(Size)); } /// getMachineMemOperand - Allocate a new MachineMemOperand by copying @@ -1057,10 +1076,15 @@ public: /// explicitly deallocated. MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, const MachinePointerInfo &PtrInfo, - uint64_t Size); + LocationSize Size); MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, const MachinePointerInfo &PtrInfo, LLT Ty); + MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO, + const MachinePointerInfo &PtrInfo, + uint64_t Size) { + return getMachineMemOperand(MMO, PtrInfo, LocationSize::precise(Size)); + } /// Allocate a new MachineMemOperand by copying an existing one, /// replacing only AliasAnalysis information. MachineMemOperands are owned @@ -1323,8 +1347,7 @@ public: } /// Start tracking the arguments passed to the call \p CallI. - void addCallArgsForwardingRegs(const MachineInstr *CallI, - CallSiteInfoImpl &&CallInfo) { + void addCallSiteInfo(const MachineInstr *CallI, CallSiteInfo &&CallInfo) { assert(CallI->isCandidateForCallSiteEntry()); bool Inserted = CallSitesInfo.try_emplace(CallI, std::move(CallInfo)).second; diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h index fcdd73d8b65fdd1cbd8c4817339a0c89cd1927d1..7249f812d2cc4cf498acc6ceda615ac6500d4814 100644 --- a/llvm/include/llvm/CodeGen/MachineInstr.h +++ b/llvm/include/llvm/CodeGen/MachineInstr.h @@ -115,6 +115,8 @@ public: // this instruction. Unpredictable = 1 << 16, // Instruction with unpredictable condition. NoConvergent = 1 << 17, // Call does not require convergence guarantees. + NonNeg = 1 << 18, // The operand is non-negative. + Disjoint = 1 << 19, // Each bit is zero in at least one of the inputs. }; private: diff --git a/llvm/include/llvm/CodeGen/MachineLoopInfo.h b/llvm/include/llvm/CodeGen/MachineLoopInfo.h index 445c9b1c3bc00f6da9520e57b54e6e82c55ebe86..967c4a70ca4699b9b64e0ebb839b151dc125d68f 100644 --- a/llvm/include/llvm/CodeGen/MachineLoopInfo.h +++ b/llvm/include/llvm/CodeGen/MachineLoopInfo.h @@ -89,6 +89,9 @@ public: private: friend class LoopInfoBase<MachineBasicBlock, MachineLoop>; + /// Returns true if the given physreg has no defs inside the loop. + bool isLoopInvariantImplicitPhysReg(Register Reg) const; + explicit MachineLoop(MachineBasicBlock *MBB) : LoopBase<MachineBasicBlock, MachineLoop>(MBB) {} diff --git a/llvm/include/llvm/CodeGen/MachineMemOperand.h b/llvm/include/llvm/CodeGen/MachineMemOperand.h index 12c18aaea5b26c545760ee58b7c97645fc03e482..da4ca582cb9e4fbf2a04cc033368ffcf382b7b8b 100644 --- a/llvm/include/llvm/CodeGen/MachineMemOperand.h +++ b/llvm/include/llvm/CodeGen/MachineMemOperand.h @@ -17,6 +17,7 @@ #include "llvm/ADT/BitmaskEnum.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/Analysis/MemoryLocation.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGenTypes/LowLevelType.h" #include "llvm/IR/DerivedTypes.h" @@ -186,7 +187,7 @@ public: /// and atomic ordering requirements must also be specified. For cmpxchg /// atomic operations the atomic ordering requirements when store does not /// occur must also be specified. - MachineMemOperand(MachinePointerInfo PtrInfo, Flags flags, uint64_t s, + MachineMemOperand(MachinePointerInfo PtrInfo, Flags flags, LocationSize TS, Align a, const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr, SyncScope::ID SSID = SyncScope::System, @@ -235,13 +236,17 @@ public: LLT getMemoryType() const { return MemoryType; } /// Return the size in bytes of the memory reference. - uint64_t getSize() const { - return MemoryType.isValid() ? MemoryType.getSizeInBytes() : ~UINT64_C(0); + LocationSize getSize() const { + return MemoryType.isValid() + ? LocationSize::precise(MemoryType.getSizeInBytes()) + : LocationSize::beforeOrAfterPointer(); } /// Return the size in bits of the memory reference. - uint64_t getSizeInBits() const { - return MemoryType.isValid() ? MemoryType.getSizeInBits() : ~UINT64_C(0); + LocationSize getSizeInBits() const { + return MemoryType.isValid() + ? LocationSize::precise(MemoryType.getSizeInBits()) + : LocationSize::beforeOrAfterPointer(); } LLT getType() const { diff --git a/llvm/include/llvm/CodeGen/MachinePassManager.h b/llvm/include/llvm/CodeGen/MachinePassManager.h index 7713c55661ccc17560ce34475d857a19874880fa..8689fd19030f90b98e0c1f7ffbd7a6dd04292f2b 100644 --- a/llvm/include/llvm/CodeGen/MachinePassManager.h +++ b/llvm/include/llvm/CodeGen/MachinePassManager.h @@ -16,8 +16,6 @@ // their respective analysis managers such as ModuleAnalysisManager and // FunctionAnalysisManager. // -// TODO: Add MachineFunctionProperties support. -// //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_MACHINEPASSMANAGER_H @@ -44,23 +42,67 @@ using MachineFunctionAnalysisManager = AnalysisManager<MachineFunction>; /// automatically mixes in \c PassInfoMixin. template <typename DerivedT> struct MachinePassInfoMixin : public PassInfoMixin<DerivedT> { - // TODO: Add MachineFunctionProperties support. +protected: + class PropertyChanger { + MachineFunction &MF; + + template <typename T> + using has_get_required_properties_t = + decltype(std::declval<T &>().getRequiredProperties()); + + template <typename T> + using has_get_set_properties_t = + decltype(std::declval<T &>().getSetProperties()); + + template <typename T> + using has_get_cleared_properties_t = + decltype(std::declval<T &>().getClearedProperties()); + + public: + PropertyChanger(MachineFunction &MF) : MF(MF) { +#ifndef NDEBUG + if constexpr (is_detected<has_get_required_properties_t, + DerivedT>::value) { + auto &MFProps = MF.getProperties(); + auto RequiredProperties = DerivedT::getRequiredProperties(); + if (!MFProps.verifyRequiredProperties(RequiredProperties)) { + errs() << "MachineFunctionProperties required by " << DerivedT::name() + << " pass are not met by function " << MF.getName() << ".\n" + << "Required properties: "; + RequiredProperties.print(errs()); + errs() << "\nCurrent properties: "; + MFProps.print(errs()); + errs() << '\n'; + report_fatal_error("MachineFunctionProperties check failed"); + } + } +#endif + } + + ~PropertyChanger() { + if constexpr (is_detected<has_get_set_properties_t, DerivedT>::value) + MF.getProperties().set(DerivedT::getSetProperties()); + if constexpr (is_detected<has_get_cleared_properties_t, DerivedT>::value) + MF.getProperties().reset(DerivedT::getClearedProperties()); + } + }; + +public: + PreservedAnalyses runImpl(MachineFunction &MF, + MachineFunctionAnalysisManager &MFAM) { + PropertyChanger PC(MF); + return static_cast<DerivedT *>(this)->run(MF, MFAM); + } }; namespace detail { -struct MachinePassConcept - : PassConcept<MachineFunction, MachineFunctionAnalysisManager> { - virtual MachineFunctionProperties getRequiredProperties() const = 0; - virtual MachineFunctionProperties getSetProperties() const = 0; - virtual MachineFunctionProperties getClearedProperties() const = 0; -}; -template <typename PassT> struct MachinePassModel : MachinePassConcept { - explicit MachinePassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - MachinePassModel(const MachinePassModel &Arg) : Pass(Arg.Pass) {} - MachinePassModel(MachinePassModel &&Arg) : Pass(std::move(Arg.Pass)) {} +template <typename PassT> +struct MachinePassModel + : PassModel<MachineFunction, PassT, MachineFunctionAnalysisManager> { + explicit MachinePassModel(PassT &&Pass) + : PassModel<MachineFunction, PassT, MachineFunctionAnalysisManager>( + std::move(Pass)) {} friend void swap(MachinePassModel &LHS, MachinePassModel &RHS) { using std::swap; @@ -72,91 +114,11 @@ template <typename PassT> struct MachinePassModel : MachinePassConcept { return *this; } + MachinePassModel &operator=(const MachinePassModel &) = delete; PreservedAnalyses run(MachineFunction &IR, MachineFunctionAnalysisManager &AM) override { - return Pass.run(IR, AM); - } - - void printPipeline( - raw_ostream &OS, - function_ref<StringRef(StringRef)> MapClassName2PassName) override { - Pass.printPipeline(OS, MapClassName2PassName); - } - - StringRef name() const override { return PassT::name(); } - - template <typename T> - using has_required_t = decltype(std::declval<T &>().isRequired()); - template <typename T> - static std::enable_if_t<is_detected<has_required_t, T>::value, bool> - passIsRequiredImpl() { - return T::isRequired(); + return this->Pass.runImpl(IR, AM); } - template <typename T> - static std::enable_if_t<!is_detected<has_required_t, T>::value, bool> - passIsRequiredImpl() { - return false; - } - bool isRequired() const override { return passIsRequiredImpl<PassT>(); } - - template <typename T> - using has_get_required_properties_t = - decltype(std::declval<T &>().getRequiredProperties()); - template <typename T> - static std::enable_if_t<is_detected<has_get_required_properties_t, T>::value, - MachineFunctionProperties> - getRequiredPropertiesImpl() { - return PassT::getRequiredProperties(); - } - template <typename T> - static std::enable_if_t<!is_detected<has_get_required_properties_t, T>::value, - MachineFunctionProperties> - getRequiredPropertiesImpl() { - return MachineFunctionProperties(); - } - MachineFunctionProperties getRequiredProperties() const override { - return getRequiredPropertiesImpl<PassT>(); - } - - template <typename T> - using has_get_set_properties_t = - decltype(std::declval<T &>().getSetProperties()); - template <typename T> - static std::enable_if_t<is_detected<has_get_set_properties_t, T>::value, - MachineFunctionProperties> - getSetPropertiesImpl() { - return PassT::getSetProperties(); - } - template <typename T> - static std::enable_if_t<!is_detected<has_get_set_properties_t, T>::value, - MachineFunctionProperties> - getSetPropertiesImpl() { - return MachineFunctionProperties(); - } - MachineFunctionProperties getSetProperties() const override { - return getSetPropertiesImpl<PassT>(); - } - - template <typename T> - using has_get_cleared_properties_t = - decltype(std::declval<T &>().getClearedProperties()); - template <typename T> - static std::enable_if_t<is_detected<has_get_cleared_properties_t, T>::value, - MachineFunctionProperties> - getClearedPropertiesImpl() { - return PassT::getClearedProperties(); - } - template <typename T> - static std::enable_if_t<!is_detected<has_get_cleared_properties_t, T>::value, - MachineFunctionProperties> - getClearedPropertiesImpl() { - return MachineFunctionProperties(); - } - MachineFunctionProperties getClearedProperties() const override { - return getClearedPropertiesImpl<PassT>(); - } - - PassT Pass; }; } // namespace detail @@ -250,11 +212,12 @@ private: class ModuleToMachineFunctionPassAdaptor : public PassInfoMixin<ModuleToMachineFunctionPassAdaptor> { - using MachinePassConcept = detail::MachinePassConcept; - public: + using PassConceptT = + detail::PassConcept<MachineFunction, MachineFunctionAnalysisManager>; + explicit ModuleToMachineFunctionPassAdaptor( - std::unique_ptr<MachinePassConcept> Pass) + std::unique_ptr<PassConceptT> Pass) : Pass(std::move(Pass)) {} /// Runs the function pass across every function in the module. @@ -265,20 +228,41 @@ public: static bool isRequired() { return true; } private: - std::unique_ptr<MachinePassConcept> Pass; + std::unique_ptr<PassConceptT> Pass; }; template <typename MachineFunctionPassT> ModuleToMachineFunctionPassAdaptor createModuleToMachineFunctionPassAdaptor(MachineFunctionPassT &&Pass) { - using PassModelT = detail::MachinePassModel<MachineFunctionPassT>; + using PassModelT = detail::PassModel<MachineFunction, MachineFunctionPassT, + MachineFunctionAnalysisManager>; // Do not use make_unique, it causes too many template instantiations, // causing terrible compile times. return ModuleToMachineFunctionPassAdaptor( - std::unique_ptr<detail::MachinePassConcept>( + std::unique_ptr<ModuleToMachineFunctionPassAdaptor::PassConceptT>( new PassModelT(std::forward<MachineFunctionPassT>(Pass)))); } +template <> +template <typename PassT> +void PassManager<MachineFunction>::addPass(PassT &&Pass) { + using PassModelT = + detail::PassModel<MachineFunction, PassT, MachineFunctionAnalysisManager>; + using MachinePassModelT = detail::MachinePassModel<PassT>; + // Do not use make_unique or emplace_back, they cause too many template + // instantiations, causing terrible compile times. + if constexpr (std::is_base_of_v<MachinePassInfoMixin<PassT>, PassT>) { + Passes.push_back(std::unique_ptr<PassConceptT>( + new MachinePassModelT(std::forward<PassT>(Pass)))); + } else if constexpr (std::is_same_v<PassT, PassManager<MachineFunction>>) { + for (auto &P : Pass.Passes) + Passes.push_back(std::move(P)); + } else { + Passes.push_back(std::unique_ptr<PassConceptT>( + new PassModelT(std::forward<PassT>(Pass)))); + } +} + template <> PreservedAnalyses PassManager<MachineFunction>::run(MachineFunction &, diff --git a/llvm/include/llvm/CodeGen/MachineScheduler.h b/llvm/include/llvm/CodeGen/MachineScheduler.h index 25703dd6b61f0ddff94d8aa1e2e51faab7318d0d..9cca6b3a571c3b74094d348a0cb4844ab1e38a53 100644 --- a/llvm/include/llvm/CodeGen/MachineScheduler.h +++ b/llvm/include/llvm/CodeGen/MachineScheduler.h @@ -1296,6 +1296,11 @@ protected: SchedBoundary Bot; MachineSchedPolicy RegionPolicy; + /// Candidate last picked from Top boundary. + SchedCandidate TopCand; + /// Candidate last picked from Bot boundary. + SchedCandidate BotCand; + public: PostGenericScheduler(const MachineSchedContext *C) : GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ"), @@ -1316,6 +1321,8 @@ public: SUnit *pickNode(bool &IsTopNode) override; + SUnit *pickNodeBidirectional(bool &IsTopNode); + void scheduleTree(unsigned SubtreeID) override { llvm_unreachable("PostRA scheduler does not support subtree analysis."); } @@ -1326,12 +1333,14 @@ public: if (SU->isScheduled) return; Top.releaseNode(SU, SU->TopReadyCycle, false); + TopCand.SU = nullptr; } void releaseBottomNode(SUnit *SU) override { if (SU->isScheduled) return; Bot.releaseNode(SU, SU->BotReadyCycle, false); + BotCand.SU = nullptr; } protected: diff --git a/llvm/include/llvm/CodeGen/NonRelocatableStringpool.h b/llvm/include/llvm/CodeGen/NonRelocatableStringpool.h index 3dc0731f5a04ee029717dfb73785d1aac2049afa..4b8eed7bdb1b53886df8b498d78f5608caef15b2 100644 --- a/llvm/include/llvm/CodeGen/NonRelocatableStringpool.h +++ b/llvm/include/llvm/CodeGen/NonRelocatableStringpool.h @@ -27,10 +27,7 @@ public: /// order. using MapTy = StringMap<DwarfStringPoolEntry, BumpPtrAllocator>; - NonRelocatableStringpool( - std::function<StringRef(StringRef Input)> Translator = nullptr, - bool PutEmptyString = false) - : Translator(Translator) { + NonRelocatableStringpool(bool PutEmptyString = false) { if (PutEmptyString) getEntry(""); } @@ -59,7 +56,6 @@ private: MapTy Strings; uint64_t CurrentEndOffset = 0; unsigned NumEntries = 0; - std::function<StringRef(StringRef Input)> Translator; }; /// Helper for making strong types. diff --git a/llvm/include/llvm/CodeGen/RegisterBankInfo.h b/llvm/include/llvm/CodeGen/RegisterBankInfo.h index 62c4a57a605d68a33c7474d163e06d71a76a1974..9704e3b1fdedd6cbb8a5e35367b6fc848cbb0390 100644 --- a/llvm/include/llvm/CodeGen/RegisterBankInfo.h +++ b/llvm/include/llvm/CodeGen/RegisterBankInfo.h @@ -399,22 +399,22 @@ protected: /// Keep dynamically allocated PartialMapping in a separate map. /// This shouldn't be needed when everything gets TableGen'ed. - mutable DenseMap<unsigned, std::unique_ptr<const PartialMapping>> + mutable DenseMap<hash_code, std::unique_ptr<const PartialMapping>> MapOfPartialMappings; /// Keep dynamically allocated ValueMapping in a separate map. /// This shouldn't be needed when everything gets TableGen'ed. - mutable DenseMap<unsigned, std::unique_ptr<const ValueMapping>> + mutable DenseMap<hash_code, std::unique_ptr<const ValueMapping>> MapOfValueMappings; /// Keep dynamically allocated array of ValueMapping in a separate map. /// This shouldn't be needed when everything gets TableGen'ed. - mutable DenseMap<unsigned, std::unique_ptr<ValueMapping[]>> + mutable DenseMap<hash_code, std::unique_ptr<ValueMapping[]>> MapOfOperandsMappings; /// Keep dynamically allocated InstructionMapping in a separate map. /// This shouldn't be needed when everything gets TableGen'ed. - mutable DenseMap<unsigned, std::unique_ptr<const InstructionMapping>> + mutable DenseMap<hash_code, std::unique_ptr<const InstructionMapping>> MapOfInstructionMappings; /// Getting the minimal register class of a physreg is expensive. diff --git a/llvm/include/llvm/CodeGen/SDPatternMatch.h b/llvm/include/llvm/CodeGen/SDPatternMatch.h index 412bf42677cc5da65c741002bf5c0fcb2014c60f..4cc7bb9c3b55a9199a05a8c3af3a7d88d8d2b1fa 100644 --- a/llvm/include/llvm/CodeGen/SDPatternMatch.h +++ b/llvm/include/llvm/CodeGen/SDPatternMatch.h @@ -495,6 +495,41 @@ inline BinaryOpc_match<LHS, RHS, true> m_Mul(const LHS &L, const RHS &R) { return BinaryOpc_match<LHS, RHS, true>(ISD::MUL, L, R); } +template <typename LHS, typename RHS> +inline BinaryOpc_match<LHS, RHS, true> m_And(const LHS &L, const RHS &R) { + return BinaryOpc_match<LHS, RHS, true>(ISD::AND, L, R); +} + +template <typename LHS, typename RHS> +inline BinaryOpc_match<LHS, RHS, true> m_Or(const LHS &L, const RHS &R) { + return BinaryOpc_match<LHS, RHS, true>(ISD::OR, L, R); +} + +template <typename LHS, typename RHS> +inline BinaryOpc_match<LHS, RHS, true> m_Xor(const LHS &L, const RHS &R) { + return BinaryOpc_match<LHS, RHS, true>(ISD::XOR, L, R); +} + +template <typename LHS, typename RHS> +inline BinaryOpc_match<LHS, RHS, true> m_SMin(const LHS &L, const RHS &R) { + return BinaryOpc_match<LHS, RHS, true>(ISD::SMIN, L, R); +} + +template <typename LHS, typename RHS> +inline BinaryOpc_match<LHS, RHS, true> m_SMax(const LHS &L, const RHS &R) { + return BinaryOpc_match<LHS, RHS, true>(ISD::SMAX, L, R); +} + +template <typename LHS, typename RHS> +inline BinaryOpc_match<LHS, RHS, true> m_UMin(const LHS &L, const RHS &R) { + return BinaryOpc_match<LHS, RHS, true>(ISD::UMIN, L, R); +} + +template <typename LHS, typename RHS> +inline BinaryOpc_match<LHS, RHS, true> m_UMax(const LHS &L, const RHS &R) { + return BinaryOpc_match<LHS, RHS, true>(ISD::UMAX, L, R); +} + template <typename LHS, typename RHS> inline BinaryOpc_match<LHS, RHS, false> m_UDiv(const LHS &L, const RHS &R) { return BinaryOpc_match<LHS, RHS, false>(ISD::UDIV, L, R); @@ -597,6 +632,38 @@ template <typename Opnd> inline UnaryOpc_match<Opnd> m_Trunc(const Opnd &Op) { return UnaryOpc_match<Opnd>(ISD::TRUNCATE, Op); } +/// Match a zext or identity +/// Allows to peek through optional extensions +template <typename Opnd> +inline Or<UnaryOpc_match<Opnd>, Opnd> m_ZExtOrSelf(Opnd &&Op) { + return Or<UnaryOpc_match<Opnd>, Opnd>(m_ZExt(std::forward<Opnd>(Op)), + std::forward<Opnd>(Op)); +} + +/// Match a sext or identity +/// Allows to peek through optional extensions +template <typename Opnd> +inline Or<UnaryOpc_match<Opnd>, Opnd> m_SExtOrSelf(Opnd &&Op) { + return Or<UnaryOpc_match<Opnd>, Opnd>(m_SExt(std::forward<Opnd>(Op)), + std::forward<Opnd>(Op)); +} + +/// Match a aext or identity +/// Allows to peek through optional extensions +template <typename Opnd> +inline Or<UnaryOpc_match<Opnd>, Opnd> m_AExtOrSelf(Opnd &&Op) { + return Or<UnaryOpc_match<Opnd>, Opnd>(m_AnyExt(std::forward<Opnd>(Op)), + std::forward<Opnd>(Op)); +} + +/// Match a trunc or identity +/// Allows to peek through optional truncations +template <typename Opnd> +inline Or<UnaryOpc_match<Opnd>, Opnd> m_TruncOrSelf(Opnd &&Op) { + return Or<UnaryOpc_match<Opnd>, Opnd>(m_Trunc(std::forward<Opnd>(Op)), + std::forward<Opnd>(Op)); +} + // === Constants === struct ConstantInt_match { APInt *BindVal; @@ -648,6 +715,7 @@ inline SpecificInt_match m_SpecificInt(uint64_t V) { } inline SpecificInt_match m_Zero() { return m_SpecificInt(0U); } +inline SpecificInt_match m_One() { return m_SpecificInt(1U); } inline SpecificInt_match m_AllOnes() { return m_SpecificInt(~0U); } /// Match true boolean value based on the information provided by @@ -689,6 +757,19 @@ inline auto m_False() { }, m_Value()}; } + +/// Match a negate as a sub(0, v) +template <typename ValTy> +inline BinaryOpc_match<SpecificInt_match, ValTy> m_Neg(const ValTy &V) { + return m_Sub(m_Zero(), V); +} + +/// Match a Not as a xor(v, -1) or xor(-1, v) +template <typename ValTy> +inline BinaryOpc_match<ValTy, SpecificInt_match, true> m_Not(const ValTy &V) { + return m_Xor(V, m_AllOnes()); +} + } // namespace SDPatternMatch } // namespace llvm #endif diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h index 25e6c525b672a18137431d85c04e5c937b38f2ec..f347131be080f63fb2b9ac6a97d19b86ac090ac4 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -279,7 +279,6 @@ class SelectionDAG { SDDbgInfo *DbgInfo; using CallSiteInfo = MachineFunction::CallSiteInfo; - using CallSiteInfoImpl = MachineFunction::CallSiteInfoImpl; struct NodeExtraInfo { CallSiteInfo CSInfo; @@ -883,7 +882,7 @@ public: /// Returns a vector of type ResVT whose elements contain the linear sequence /// <0, Step, Step * 2, Step * 3, ...> - SDValue getStepVector(const SDLoc &DL, EVT ResVT, APInt StepVal); + SDValue getStepVector(const SDLoc &DL, EVT ResVT, const APInt &StepVal); /// Returns a vector of type ResVT whose elements contain the linear sequence /// <0, 1, 2, 3, ...> @@ -1299,7 +1298,7 @@ public: EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags Flags = MachineMemOperand::MOLoad | MachineMemOperand::MOStore, - uint64_t Size = 0, const AAMDNodes &AAInfo = AAMDNodes()); + LocationSize Size = 0, const AAMDNodes &AAInfo = AAMDNodes()); inline SDValue getMemIntrinsicNode( unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef<SDValue> Ops, @@ -1307,7 +1306,7 @@ public: MaybeAlign Alignment = std::nullopt, MachineMemOperand::Flags Flags = MachineMemOperand::MOLoad | MachineMemOperand::MOStore, - uint64_t Size = 0, const AAMDNodes &AAInfo = AAMDNodes()) { + LocationSize Size = 0, const AAMDNodes &AAInfo = AAMDNodes()) { // Ensure that codegen never sees alignment 0 return getMemIntrinsicNode(Opcode, dl, VTList, Ops, MemVT, PtrInfo, Alignment.value_or(getEVTAlign(MemVT)), Flags, @@ -2259,7 +2258,7 @@ public: } /// Set CallSiteInfo to be associated with Node. - void addCallSiteInfo(const SDNode *Node, CallSiteInfoImpl &&CallInfo) { + void addCallSiteInfo(const SDNode *Node, CallSiteInfo &&CallInfo) { SDEI[Node].CSInfo = std::move(CallInfo); } /// Return CallSiteInfo associated with Node, or a default if none exists. diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h index d1015630b05d129ac7356617a153d8ecd18e5f27..261f7e49e5c8ca6e60e75d4be31bce3b651abe4d 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -558,6 +558,7 @@ BEGIN_TWO_BYTE_PACK() class LoadSDNodeBitfields { friend class LoadSDNode; + friend class AtomicSDNode; friend class VPLoadSDNode; friend class VPStridedLoadSDNode; friend class MaskedLoadSDNode; @@ -1475,6 +1476,16 @@ public: MMO->isAtomic()) && "then why are we using an AtomicSDNode?"); } + void setExtensionType(ISD::LoadExtType ETy) { + assert(getOpcode() == ISD::ATOMIC_LOAD && "Only used for atomic loads."); + LoadSDNodeBits.ExtTy = ETy; + } + + ISD::LoadExtType getExtensionType() const { + assert(getOpcode() == ISD::ATOMIC_LOAD && "Only used for atomic loads."); + return static_cast<ISD::LoadExtType>(LoadSDNodeBits.ExtTy); + } + const SDValue &getBasePtr() const { return getOpcode() == ISD::ATOMIC_STORE ? getOperand(2) : getOperand(1); } diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h index be4ee5b6f9e29a821f8833afef91b2f0f8e23bfb..9fd0ebe6956fbe49746558c9a4575cdd62a37965 100644 --- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h +++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h @@ -204,6 +204,7 @@ public: /// if they exist (-1 otherwise). Some targets use pseudo instructions in /// order to abstract away the difference between operating with a frame /// pointer and operating without, through the use of these two instructions. + /// A FrameSetup MI in MF implies MFI::AdjustsStack. /// unsigned getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; } unsigned getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; } diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index 2f164a460db84321d3b7dac00ad2b856cdba7643..a4dc097446186a030e715dd90f50e6f923b56f50 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -1454,6 +1454,28 @@ public: getLoadExtAction(ExtType, ValVT, MemVT) == Custom; } + /// Same as getLoadExtAction, but for atomic loads. + LegalizeAction getAtomicLoadExtAction(unsigned ExtType, EVT ValVT, + EVT MemVT) const { + if (ValVT.isExtended() || MemVT.isExtended()) return Expand; + unsigned ValI = (unsigned)ValVT.getSimpleVT().SimpleTy; + unsigned MemI = (unsigned)MemVT.getSimpleVT().SimpleTy; + assert(ExtType < ISD::LAST_LOADEXT_TYPE && ValI < MVT::VALUETYPE_SIZE && + MemI < MVT::VALUETYPE_SIZE && "Table isn't big enough!"); + unsigned Shift = 4 * ExtType; + LegalizeAction Action = + (LegalizeAction)((AtomicLoadExtActions[ValI][MemI] >> Shift) & 0xf); + assert((Action == Legal || Action == Expand) && + "Unsupported atomic load extension action."); + return Action; + } + + /// Return true if the specified atomic load with extension is legal on + /// this target. + bool isAtomicLoadExtLegal(unsigned ExtType, EVT ValVT, EVT MemVT) const { + return getAtomicLoadExtAction(ExtType, ValVT, MemVT) == Legal; + } + /// Return how this store with truncation should be treated: either it is /// legal, needs to be promoted to a larger size, needs to be expanded to some /// other code sequence, or the target has a custom expander for it. @@ -2536,6 +2558,30 @@ protected: setLoadExtAction(ExtTypes, ValVT, MemVT, Action); } + /// Let target indicate that an extending atomic load of the specified type + /// is legal. + void setAtomicLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, + LegalizeAction Action) { + assert(ExtType < ISD::LAST_LOADEXT_TYPE && ValVT.isValid() && + MemVT.isValid() && "Table isn't big enough!"); + assert((unsigned)Action < 0x10 && "too many bits for bitfield array"); + unsigned Shift = 4 * ExtType; + AtomicLoadExtActions[ValVT.SimpleTy][MemVT.SimpleTy] &= + ~((uint16_t)0xF << Shift); + AtomicLoadExtActions[ValVT.SimpleTy][MemVT.SimpleTy] |= + ((uint16_t)Action << Shift); + } + void setAtomicLoadExtAction(ArrayRef<unsigned> ExtTypes, MVT ValVT, MVT MemVT, + LegalizeAction Action) { + for (auto ExtType : ExtTypes) + setAtomicLoadExtAction(ExtType, ValVT, MemVT, Action); + } + void setAtomicLoadExtAction(ArrayRef<unsigned> ExtTypes, MVT ValVT, + ArrayRef<MVT> MemVTs, LegalizeAction Action) { + for (auto MemVT : MemVTs) + setAtomicLoadExtAction(ExtTypes, ValVT, MemVT, Action); + } + /// Indicate that the specified truncating store does not work with the /// specified type and indicate what to do about it. void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action) { @@ -2722,17 +2768,19 @@ public: } /// This represents an addressing mode of: - /// BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + /// BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*vscale /// If BaseGV is null, there is no BaseGV. /// If BaseOffs is zero, there is no base offset. /// If HasBaseReg is false, there is no base register. /// If Scale is zero, there is no ScaleReg. Scale of 1 indicates a reg with /// no scale. + /// If ScalableOffset is zero, there is no scalable offset. struct AddrMode { GlobalValue *BaseGV = nullptr; int64_t BaseOffs = 0; bool HasBaseReg = false; int64_t Scale = 0; + int64_t ScalableOffset = 0; AddrMode() = default; }; @@ -2770,6 +2818,12 @@ public: return true; } + /// Return true if adding the specified scalable immediate is legal, that is + /// the target has add instructions which can add a register with the + /// immediate (multiplied by vscale) without having to materialize the + /// immediate into a register. + virtual bool isLegalAddScalableImmediate(int64_t) const { return false; } + /// Return true if the specified immediate is legal for the value input of a /// store instruction. virtual bool isLegalStoreImmediate(int64_t Value) const { @@ -3513,6 +3567,10 @@ private: /// for each of the 4 load ext types. uint16_t LoadExtActions[MVT::VALUETYPE_SIZE][MVT::VALUETYPE_SIZE]; + /// Similar to LoadExtActions, but for atomic loads. Only Legal or Expand + /// (default) values are supported. + uint16_t AtomicLoadExtActions[MVT::VALUETYPE_SIZE][MVT::VALUETYPE_SIZE]; + /// For each value type pair keep a LegalizeAction that indicates whether a /// truncating store of a specific value type and truncating type is legal. LegalizeAction TruncStoreActions[MVT::VALUETYPE_SIZE][MVT::VALUETYPE_SIZE]; diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h index e7c9ecd2e1851a1b07f7c452886f82b36b2d932a..33c4c745c3416ce4cff08d041f5bf27df9a437c7 100644 --- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h +++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h @@ -243,9 +243,20 @@ public: unsigned RegSize, SpillSize, SpillAlignment; unsigned VTListOffset; }; + + /// SubRegCoveredBits - Emitted by tablegen: bit range covered by a subreg + /// index, -1 in any being invalid. + struct SubRegCoveredBits { + uint16_t Offset; + uint16_t Size; + }; + private: const TargetRegisterInfoDesc *InfoDesc; // Extra desc array for codegen const char *const *SubRegIndexNames; // Names of subreg indexes. + const SubRegCoveredBits *SubRegIdxRanges; // Pointer to the subreg covered + // bit ranges array. + // Pointer to array of lane masks, one per sub-reg index. const LaneBitmask *SubRegIndexLaneMasks; @@ -256,12 +267,10 @@ private: unsigned HwMode; protected: - TargetRegisterInfo(const TargetRegisterInfoDesc *ID, - regclass_iterator RCB, - regclass_iterator RCE, - const char *const *SRINames, - const LaneBitmask *SRILaneMasks, - LaneBitmask CoveringLanes, + TargetRegisterInfo(const TargetRegisterInfoDesc *ID, regclass_iterator RCB, + regclass_iterator RCE, const char *const *SRINames, + const SubRegCoveredBits *SubIdxRanges, + const LaneBitmask *SRILaneMasks, LaneBitmask CoveringLanes, const RegClassInfo *const RCIs, const MVT::SimpleValueType *const RCVTLists, unsigned Mode = 0); @@ -382,6 +391,16 @@ public: return SubRegIndexNames[SubIdx-1]; } + /// Get the size of the bit range covered by a sub-register index. + /// If the index isn't continuous, return the sum of the sizes of its parts. + /// If the index is used to access subregisters of different sizes, return -1. + unsigned getSubRegIdxSize(unsigned Idx) const; + + /// Get the offset of the bit range covered by a sub-register index. + /// If an Offset doesn't make sense (the index isn't continuous, or is used to + /// access sub-registers at different offsets), return -1. + unsigned getSubRegIdxOffset(unsigned Idx) const; + /// Return a bitmask representing the parts of a register that are covered by /// SubIdx \see LaneBitmask. /// @@ -572,6 +591,12 @@ public: return false; } + /// Returns true if MachineLoopInfo should analyze the given physreg + /// for loop invariance. + virtual bool shouldAnalyzePhysregInMachineLoopInfo(MCRegister R) const { + return false; + } + /// Physical registers that may be modified within a function but are /// guaranteed to be restored before any uses. This is useful for targets that /// have call sequences where a GOT register may be updated by the caller diff --git a/llvm/include/llvm/CodeGenTypes/LowLevelType.h b/llvm/include/llvm/CodeGenTypes/LowLevelType.h index 5a16cffb80b32b05478dbfbe4fba9c4bda326fb7..62ee28cfac99c5ce8f02e367ab23abb58e791661 100644 --- a/llvm/include/llvm/CodeGenTypes/LowLevelType.h +++ b/llvm/include/llvm/CodeGenTypes/LowLevelType.h @@ -45,6 +45,14 @@ public: /*AddressSpace=*/0}; } + /// Get a low-level token; just a scalar with zero bits (or no size). + static constexpr LLT token() { + return LLT{/*isPointer=*/false, /*isVector=*/false, + /*isScalar=*/true, ElementCount::getFixed(0), + /*SizeInBits=*/0, + /*AddressSpace=*/0}; + } + /// Get a low-level pointer in the given address space. static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits) { assert(SizeInBits > 0 && "invalid pointer size"); @@ -134,17 +142,17 @@ public: explicit LLT(MVT VT); - constexpr bool isValid() const { return IsScalar || IsPointer || IsVector; } - + constexpr bool isValid() const { return IsScalar || RawData != 0; } constexpr bool isScalar() const { return IsScalar; } - - constexpr bool isPointer() const { return IsPointer && !IsVector; } - - constexpr bool isPointerVector() const { return IsPointer && IsVector; } - - constexpr bool isPointerOrPointerVector() const { return IsPointer; } - - constexpr bool isVector() const { return IsVector; } + constexpr bool isToken() const { return IsScalar && RawData == 0; }; + constexpr bool isVector() const { return isValid() && IsVector; } + constexpr bool isPointer() const { + return isValid() && IsPointer && !IsVector; + } + constexpr bool isPointerVector() const { return IsPointer && isVector(); } + constexpr bool isPointerOrPointerVector() const { + return IsPointer && isValid(); + } /// Returns the number of elements in a vector LLT. Must only be called on /// vector types. @@ -314,6 +322,28 @@ private: /// described in static const *Field variables. Each of these variables /// is a 2-element array, with the first element describing the bitfield size /// and the second element describing the bitfield offset. + /// + /// +--------+---------+--------+----------+----------------------+ + /// |isScalar|isPointer|isVector| RawData |Notes | + /// +--------+---------+--------+----------+----------------------+ + /// | 0 | 0 | 0 | 0 |Invalid | + /// +--------+---------+--------+----------+----------------------+ + /// | 0 | 0 | 1 | 0 |Tombstone Key | + /// +--------+---------+--------+----------+----------------------+ + /// | 0 | 1 | 0 | 0 |Empty Key | + /// +--------+---------+--------+----------+----------------------+ + /// | 1 | 0 | 0 | 0 |Token | + /// +--------+---------+--------+----------+----------------------+ + /// | 1 | 0 | 0 | non-zero |Scalar | + /// +--------+---------+--------+----------+----------------------+ + /// | 0 | 1 | 0 | non-zero |Pointer | + /// +--------+---------+--------+----------+----------------------+ + /// | 0 | 0 | 1 | non-zero |Vector of non-pointer | + /// +--------+---------+--------+----------+----------------------+ + /// | 0 | 1 | 1 | non-zero |Vector of pointer | + /// +--------+---------+--------+----------+----------------------+ + /// + /// Everything else is reserved. typedef int BitFieldInfo[2]; /// /// This is how the bitfields are packed per Kind: diff --git a/llvm/include/llvm/DWARFLinker/Classic/DWARFStreamer.h b/llvm/include/llvm/DWARFLinker/Classic/DWARFStreamer.h index bebdfd5e60257ef0312a3dafb00f2ccf78da0647..e7a1a3cd838c2295ca8611f3adcabd0cb551bd17 100644 --- a/llvm/include/llvm/DWARFLinker/Classic/DWARFStreamer.h +++ b/llvm/include/llvm/DWARFLinker/Classic/DWARFStreamer.h @@ -45,16 +45,13 @@ class DwarfStreamer : public DwarfEmitter { public: DwarfStreamer(DWARFLinkerBase::OutputFileType OutFileType, raw_pwrite_stream &OutFile, - DWARFLinkerBase::TranslatorFuncTy Translator, DWARFLinkerBase::MessageHandlerTy Warning) - : OutFile(OutFile), OutFileType(OutFileType), Translator(Translator), - WarningHandler(Warning) {} + : OutFile(OutFile), OutFileType(OutFileType), WarningHandler(Warning) {} virtual ~DwarfStreamer() = default; static Expected<std::unique_ptr<DwarfStreamer>> createStreamer( const Triple &TheTriple, DWARFLinkerBase::OutputFileType FileType, - raw_pwrite_stream &OutFile, DWARFLinkerBase::TranslatorFuncTy Translator, - DWARFLinkerBase::MessageHandlerTy Warning); + raw_pwrite_stream &OutFile, DWARFLinkerBase::MessageHandlerTy Warning); Error init(Triple TheTriple, StringRef Swift5ReflectionSegmentName); @@ -295,7 +292,6 @@ private: /// The output file we stream the linked Dwarf to. raw_pwrite_stream &OutFile; DWARFLinker::OutputFileType OutFileType = DWARFLinker::OutputFileType::Object; - std::function<StringRef(StringRef Input)> Translator; uint64_t RangesSectionSize = 0; uint64_t RngListsSectionSize = 0; diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h b/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h index 5c811b668f0a3158287a98909cbd056f2f4339c0..70b25cf02df7f81ccdd120fd8290691361832960 100644 --- a/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h +++ b/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h @@ -82,7 +82,6 @@ public: std::function<void(const DWARFFile &File, llvm::StringRef Output)>; using ObjectPrefixMapTy = std::map<std::string, std::string>; using CompileUnitHandlerTy = function_ref<void(const DWARFUnit &Unit)>; - using TranslatorFuncTy = std::function<StringRef(StringRef)>; using SwiftInterfacesMapTy = std::map<std::string, std::string>; /// Type of output file. enum class OutputFileType : uint8_t { diff --git a/llvm/include/llvm/DWARFLinker/Parallel/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/Parallel/DWARFLinker.h index 5312712a4a5b8133c5fa1d008c006d9104a6bdd3..8acc046d072493dd033c5b85ff9fe0deb029623d 100644 --- a/llvm/include/llvm/DWARFLinker/Parallel/DWARFLinker.h +++ b/llvm/include/llvm/DWARFLinker/Parallel/DWARFLinker.h @@ -123,8 +123,7 @@ public: /// Creates dwarf linker instance. static std::unique_ptr<DWARFLinker> - createLinker(MessageHandlerTy ErrorHandler, MessageHandlerTy WarningHandler, - TranslatorFuncTy StringsTranslator = nullptr); + createLinker(MessageHandlerTy ErrorHandler, MessageHandlerTy WarningHandler); /// Set output DWARF handler. Result of linking DWARF is set of sections /// containing final debug info. DWARFLinkerBase::link() pass generated diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h index d368c7e0ece8f390201c886b12a978a4c0adac37..f1d4fc72d5a72710dfbfbb848fad9b322c75b66d 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h @@ -605,6 +605,9 @@ public: NameIndex(const DWARFDebugNames &Section, uint64_t Base) : Section(Section), Base(Base) {} + /// Returns Hdr field + Header getHeader() const { return Hdr; } + /// Reads offset of compilation unit CU. CU is 0-based. uint64_t getCUOffset(uint32_t CU) const; uint32_t getCUCount() const { return Hdr.CompUnitCount; } diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h index a66cf4608823beedd6f0854fb1a61636c11b66e6..f76f2ecd3e2121089c7155998ced2486478b2776 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h @@ -122,6 +122,48 @@ protected: std::unique_ptr<MCContext> MC; std::unique_ptr<MCInstPrinter> MIP; + // https://yurydelendik.github.io/webassembly-dwarf/ + // 2. Consuming and Generating DWARF for WebAssembly Code + // Note: Some DWARF constructs don't map one-to-one onto WebAssembly + // constructs. We strive to enumerate and resolve any ambiguities here. + // + // 2.1. Code Addresses + // Note: DWARF associates various bits of debug info + // with particular locations in the program via its code address (instruction + // pointer or PC). However, WebAssembly's linear memory address space does not + // contain WebAssembly instructions. + // + // Wherever a code address (see 2.17 of [DWARF]) is used in DWARF for + // WebAssembly, it must be the offset of an instruction relative within the + // Code section of the WebAssembly file. The DWARF is considered malformed if + // a PC offset is between instruction boundaries within the Code section. + // + // Note: It is expected that a DWARF consumer does not know how to decode + // WebAssembly instructions. The instruction pointer is selected as the offset + // in the binary file of the first byte of the instruction, and it is + // consistent with the WebAssembly Web API conventions definition of the code + // location. + // + // EXAMPLE: .DEBUG_LINE INSTRUCTION POINTERS + // The .debug_line DWARF section maps instruction pointers to source + // locations. With WebAssembly, the .debug_line section maps Code + // section-relative instruction offsets to source locations. + // + // EXAMPLE: DW_AT_* ATTRIBUTES + // For entities with a single associated code address, DWARF uses + // the DW_AT_low_pc attribute to specify the associated code address value. + // For WebAssembly, the DW_AT_low_pc's value is a Code section-relative + // instruction offset. + // + // For entities with a single contiguous range of code, DWARF uses a + // pair of DW_AT_low_pc and DW_AT_high_pc attributes to specify the associated + // contiguous range of code address values. For WebAssembly, these attributes + // are Code section-relative instruction offsets. + // + // For entities with multiple ranges of code, DWARF uses the DW_AT_ranges + // attribute, which refers to the array located at the .debug_ranges section. + LVAddress WasmCodeSectionOffset = 0; + // Loads all info for the architecture of the provided object file. Error loadGenericTargetInfo(StringRef TheTriple, StringRef TheFeatures); diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h index 8a32210bac3c9cc944fbfad131c8907d19124695..4dd7c967ddc17d6b5e5d8499e76335ad8fa4a30f 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h @@ -58,7 +58,7 @@ class LVSymbolVisitorDelegate; using LVNames = SmallVector<StringRef, 16>; -// The ELF reader uses the DWARF constants to create the logical elements. +// The DWARF reader uses the DWARF constants to create the logical elements. // The DW_TAG_* and DW_AT_* are used to select the logical object and to // set specific attributes, such as name, type, etc. // As the CodeView constants are different to the DWARF constants, the diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVELFReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h similarity index 87% rename from llvm/include/llvm/DebugInfo/LogicalView/Readers/LVELFReader.h rename to llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h index 0837b886a273a62a31114f255126565472628820..fdc97249d8e5a9d994b133e562c14de9f38e7b7e 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVELFReader.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h @@ -1,4 +1,4 @@ -//===-- LVELFReader.h -------------------------------------------*- C++ -*-===// +//===-- LVDWARFReader.h -----------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// // -// This file defines the LVELFReader class, which is used to describe a +// This file defines the LVDWARFReader class, which is used to describe a // debug information (DWARF) reader. // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVELFREADER_H -#define LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVELFREADER_H +#ifndef LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVDWARFREADER_H +#define LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVDWARFREADER_H #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" @@ -30,7 +30,7 @@ class LVType; using AttributeSpec = DWARFAbbreviationDeclaration::AttributeSpec; -class LVELFReader final : public LVBinaryReader { +class LVDWARFReader final : public LVBinaryReader { object::ObjectFile &Obj; // Indicates if ranges data are available; in the case of split DWARF any @@ -49,7 +49,7 @@ class LVELFReader final : public LVBinaryReader { // In DWARF v4, the files are 1-indexed. // In DWARF v5, the files are 0-indexed. - // The ELF reader expects the indexes as 1-indexed. + // The DWARF reader expects the indexes as 1-indexed. bool IncrementFileIndex = false; // Address ranges collected for current DIE. @@ -127,14 +127,14 @@ protected: void sortScopes() override; public: - LVELFReader() = delete; - LVELFReader(StringRef Filename, StringRef FileFormatName, - object::ObjectFile &Obj, ScopedPrinter &W) + LVDWARFReader() = delete; + LVDWARFReader(StringRef Filename, StringRef FileFormatName, + object::ObjectFile &Obj, ScopedPrinter &W) : LVBinaryReader(Filename, FileFormatName, W, LVBinaryType::ELF), Obj(Obj) {} - LVELFReader(const LVELFReader &) = delete; - LVELFReader &operator=(const LVELFReader &) = delete; - ~LVELFReader() = default; + LVDWARFReader(const LVDWARFReader &) = delete; + LVDWARFReader &operator=(const LVDWARFReader &) = delete; + ~LVDWARFReader() = default; LVAddress getCUBaseAddress() const { return CUBaseAddress; } void setCUBaseAddress(LVAddress Address) { CUBaseAddress = Address; } @@ -158,4 +158,4 @@ public: } // end namespace logicalview } // end namespace llvm -#endif // LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVELFREADER_H +#endif // LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVDWARFREADER_H diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h index 30a9383dc0bc158dd571200a4a977dc808faf703..4ce0c8d9fd17ed6586ab51b5f098bb73ed4ddf4a 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h @@ -567,7 +567,7 @@ public: orc::ExecutorAddrDiff getOffset() const { return Offset; } void setOffset(orc::ExecutorAddrDiff NewOffset) { - assert(NewOffset < getBlock().getSize() && "Offset out of range"); + assert(NewOffset <= getBlock().getSize() && "Offset out of range"); Offset = NewOffset; } diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h index f7c286bec778b04aea07d92fc30e4bd4fa08b247..ed30a792e9e9ce2d43f5697c5d1b60f804e5a63e 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h @@ -352,7 +352,7 @@ private: : ES(ES), L(L) {} static Expected<unsigned> getTargetPointerSize(const Triple &TT); - static Expected<llvm::endianness> getTargetEndianness(const Triple &TT); + static Expected<llvm::endianness> getEndianness(const Triple &TT); Expected<std::unique_ptr<jitlink::LinkGraph>> createStubsGraph(const SymbolMap &Resolved); diff --git a/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h b/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h index e928faf478855920622d30e41b315551d43c158d..2ffde1f9eb10e837939fb08087e4b4fe5eba45b5 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h @@ -60,9 +60,9 @@ public: struct BuildVersionOpts { - // Derive platform from triple. - static BuildVersionOpts fromTriple(const Triple &TT, uint32_t MinOS, - uint32_t SDK); + // Derive platform from triple if possible. + static std::optional<BuildVersionOpts> + fromTriple(const Triple &TT, uint32_t MinOS, uint32_t SDK); uint32_t Platform; // Platform. uint32_t MinOS; // X.Y.Z is encoded in nibbles xxxx.yy.zz @@ -73,13 +73,12 @@ public: /// will be used. std::optional<Dylib> IDDylib; - /// Override for LC_BUILD_VERSION. If this is nullopt then - std::optional<BuildVersionOpts> BuildVersion; - /// List of LC_LOAD_DYLIBs. std::vector<Dylib> LoadDylibs; /// List of LC_RPATHs. std::vector<std::string> RPaths; + /// List of LC_BUILD_VERSIONs. + std::vector<BuildVersionOpts> BuildVersions; HeaderOptions() = default; HeaderOptions(Dylib D) : IDDylib(std::move(D)) {} diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/VTuneSharedStructs.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/VTuneSharedStructs.h index 667d3446faff74f8cf19844118b8c61861684e7f..3517d0b09171990ed3287982cab584bcfeb3a18d 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/VTuneSharedStructs.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/VTuneSharedStructs.h @@ -13,6 +13,10 @@ #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_VTUNESHAREDSTRUCTS_H #define LLVM_EXECUTIONENGINE_ORC_SHARED_VTUNESHAREDSTRUCTS_H +#include "ExecutorAddress.h" +#include <utility> +#include <vector> + namespace llvm { namespace orc { diff --git a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h new file mode 100644 index 0000000000000000000000000000000000000000..6ce972adcf0fb03f404943bdc74e6f134d1f05a0 --- /dev/null +++ b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h @@ -0,0 +1,1268 @@ +//===- ClauseT.h -- clause template definitions ---------------------------===// +// +// 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 template classes that represent OpenMP clauses, as +// described in the OpenMP API specification. +// +// The general structure of any specific clause class is that it is either +// empty, or it consists of a single data member, which can take one of these +// three forms: +// - a value member, named `v`, or +// - a tuple of values, named `t`, or +// - a variant (i.e. union) of values, named `u`. +// To assist with generic visit algorithms, classes define one of the following +// traits: +// - EmptyTrait: the class has no data members. +// - WrapperTrait: the class has a single member `v` +// - TupleTrait: the class has a tuple member `t` +// - UnionTrait the class has a varuant member `u` +// - IncompleteTrait: the class is a placeholder class that is currently empty, +// but will be completed at a later time. +// Note: This structure follows the one used in flang parser. +// +// The types used in the class definitions follow the names used in the spec +// (there are a few exceptions to this). For example, given +// Clause `foo` +// - foo-modifier : description... +// - list : list of variables +// the corresponding class would be +// template <...> +// struct FooT { +// using FooModifier = type that can represent the modifier +// using List = ListT<ObjectT<...>>; +// using TupleTrait = std::true_type; +// std::tuple<std::optional<FooModifier>, List> t; +// }; +//===----------------------------------------------------------------------===// +#ifndef LLVM_FRONTEND_OPENMP_CLAUSET_H +#define LLVM_FRONTEND_OPENMP_CLAUSET_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Frontend/OpenMP/OMP.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +#include <algorithm> +#include <iterator> +#include <optional> +#include <tuple> +#include <type_traits> +#include <utility> +#include <variant> + +#define ENUM(Name, ...) enum class Name { __VA_ARGS__ } +#define OPT(x) std::optional<x> + +// A number of OpenMP clauses contain values that come from a given set of +// possibilities. In the IR these are usually represented by enums. Both +// clang and flang use different types for the enums, and the enum elements +// representing the same thing may have different values between clang and +// flang. +// Since the representation below tries to adhere to the spec, and be source +// language agnostic, it defines its own enums, independent from any language +// frontend. As a consequence, when instantiating the templates below, +// frontend-specific enums need to be translated into the representation +// used here. The macros below are intended to assist with the conversion. + +// Helper macro for enum-class conversion. +#define CLAUSET_SCOPED_ENUM_MEMBER_CONVERT(Ov, Tv) \ + if (v == OtherEnum::Ov) { \ + return ThisEnum::Tv; \ + } + +// Helper macro for enum (non-class) conversion. +#define CLAUSET_UNSCOPED_ENUM_MEMBER_CONVERT(Ov, Tv) \ + if (v == Ov) { \ + return ThisEnum::Tv; \ + } + +#define CLAUSET_ENUM_CONVERT(func, OtherE, ThisE, Maps) \ + auto func = [](OtherE v) -> ThisE { \ + using ThisEnum = ThisE; \ + using OtherEnum = OtherE; \ + (void)sizeof(OtherEnum); /*Avoid "unused local typedef" warning*/ \ + Maps; \ + llvm_unreachable("Unexpected value in " #OtherE); \ + } + +// Usage: +// +// Given two enums, +// enum class Other { o1, o2 }; +// enum class This { t1, t2 }; +// generate conversion function "Func : Other -> This" with +// CLAUSET_ENUM_CONVERT( +// Func, Other, This, +// CLAUSET_ENUM_MEMBER_CONVERT(o1, t1) // <- No comma +// CLAUSET_ENUM_MEMBER_CONVERT(o2, t2) +// ... +// ) +// +// Note that the sequence of M(other-value, this-value) is separated +// with _spaces_, not commas. + +namespace detail { +// Type trait to determine whether T is a specialization of std::variant. +template <typename T> struct is_variant { + static constexpr bool value = false; +}; + +template <typename... Ts> struct is_variant<std::variant<Ts...>> { + static constexpr bool value = true; +}; + +template <typename T> constexpr bool is_variant_v = is_variant<T>::value; + +// Helper utility to create a type which is a union of two given variants. +template <typename...> struct UnionOfTwo; + +template <typename... Types1, typename... Types2> +struct UnionOfTwo<std::variant<Types1...>, std::variant<Types2...>> { + using type = std::variant<Types1..., Types2...>; +}; +} // namespace detail + +namespace tomp { +namespace type { + +// Helper utility to create a type which is a union of an arbitrary number +// of variants. +template <typename...> struct Union; + +template <> struct Union<> { + // Legal to define, illegal to instantiate. + using type = std::variant<>; +}; + +template <typename T, typename... Ts> struct Union<T, Ts...> { + static_assert(detail::is_variant_v<T>); + using type = + typename detail::UnionOfTwo<T, typename Union<Ts...>::type>::type; +}; + +template <typename T> using ListT = llvm::SmallVector<T, 0>; + +// The ObjectT class represents a variable (as defined in the OpenMP spec). +// +// A specialization of ObjectT<Id, Expr> must provide the following definitions: +// { +// using IdTy = Id; +// using ExprTy = Expr; +// +// auto id() const -> IdTy { +// return the identifier of the object (for use in tests for +// presence/absence of the object) +// } +// +// auto ref() const -> (e.g. const ExprTy&) { +// return the expression accessing (referencing) the object +// } +// } +// +// For example, the ObjectT instance created for "var[x+1]" would have +// the `id()` return the identifier for `var`, and the `ref()` return the +// representation of the array-access `var[x+1]`. +// +// The identity of an object must always be present, i.e. it cannot be +// nullptr, std::nullopt, etc. The reference is optional. +// +// Note: the ObjectT template is not defined. Any user of it is expected to +// provide their own specialization that conforms to the above requirements. +template <typename IdType, typename ExprType> struct ObjectT; + +template <typename I, typename E> using ObjectListT = ListT<ObjectT<I, E>>; + +using DirectiveName = llvm::omp::Directive; + +template <typename I, typename E> // +struct DefinedOperatorT { + struct DefinedOpName { + using WrapperTrait = std::true_type; + ObjectT<I, E> v; + }; + ENUM(IntrinsicOperator, Power, Multiply, Divide, Add, Subtract, Concat, LT, + LE, EQ, NE, GE, GT, NOT, AND, OR, EQV, NEQV, Min, Max); + using UnionTrait = std::true_type; + std::variant<DefinedOpName, IntrinsicOperator> u; +}; + +// V5.2: [3.2.6] `iterator` modifier +template <typename E> // +struct RangeT { + // range-specification: begin : end[: step] + using TupleTrait = std::true_type; + std::tuple<E, E, OPT(E)> t; +}; + +// V5.2: [3.2.6] `iterator` modifier +template <typename TypeType, typename IdType, typename ExprType> // +struct IteratorSpecifierT { + // iterators-specifier: [ iterator-type ] identifier = range-specification + using TupleTrait = std::true_type; + std::tuple<OPT(TypeType), ObjectT<IdType, ExprType>, RangeT<ExprType>> t; +}; + +// Note: +// For motion or map clauses the OpenMP spec allows a unique mapper modifier. +// In practice, since these clauses apply to multiple objects, there can be +// multiple effective mappers applicable to these objects (due to overloads, +// etc.). Because of that store a list of mappers every time a mapper modifier +// is allowed. If the mapper list contains a single element, it applies to +// all objects in the clause, otherwise there should be as many mappers as +// there are objects. +// V5.2: [5.8.2] Mapper identifiers and `mapper` modifiers +template <typename I, typename E> // +struct MapperT { + using MapperIdentifier = ObjectT<I, E>; + using WrapperTrait = std::true_type; + MapperIdentifier v; +}; + +// V5.2: [15.8.1] `memory-order` clauses +// When used as arguments for other clauses, e.g. `fail`. +ENUM(MemoryOrder, AcqRel, Acquire, Relaxed, Release, SeqCst); +ENUM(MotionExpectation, Present); +// V5.2: [15.9.1] `task-dependence-type` modifier +ENUM(TaskDependenceType, In, Out, Inout, Mutexinoutset, Inoutset, Depobj); + +template <typename I, typename E> // +struct LoopIterationT { + struct Distance { + using TupleTrait = std::true_type; + std::tuple<DefinedOperatorT<I, E>, E> t; + }; + using TupleTrait = std::true_type; + std::tuple<ObjectT<I, E>, OPT(Distance)> t; +}; + +template <typename I, typename E> // +struct ProcedureDesignatorT { + using WrapperTrait = std::true_type; + ObjectT<I, E> v; +}; + +// Note: +// For reduction clauses the OpenMP spec allows a unique reduction identifier. +// For reasons analogous to those listed for the MapperT type, clauses that +// according to the spec contain a reduction identifier will contain a list of +// reduction identifiers. The same constraints apply: there is either a single +// identifier that applies to all objects, or there are as many identifiers +// as there are objects. +template <typename I, typename E> // +struct ReductionIdentifierT { + using UnionTrait = std::true_type; + std::variant<DefinedOperatorT<I, E>, ProcedureDesignatorT<I, E>> u; +}; + +template <typename T, typename I, typename E> // +using IteratorT = ListT<IteratorSpecifierT<T, I, E>>; +} // namespace type + +template <typename T> using ListT = type::ListT<T>; + +template <typename I, typename E> using ObjectT = type::ObjectT<I, E>; +template <typename I, typename E> using ObjectListT = type::ObjectListT<I, E>; + +template <typename T, typename I, typename E> +using IteratorT = type::IteratorT<T, I, E>; + +template < + typename ContainerTy, typename FunctionTy, + typename ElemTy = typename llvm::remove_cvref_t<ContainerTy>::value_type, + typename ResultTy = std::invoke_result_t<FunctionTy, ElemTy>> +ListT<ResultTy> makeList(ContainerTy &&container, FunctionTy &&func) { + ListT<ResultTy> v; + llvm::transform(container, std::back_inserter(v), func); + return v; +} + +namespace clause { +// V5.2: [8.3.1] `assumption` clauses +template <typename T, typename I, typename E> // +struct AbsentT { + using List = ListT<type::DirectiveName>; + using WrapperTrait = std::true_type; + List v; +}; + +// V5.2: [15.8.1] `memory-order` clauses +template <typename T, typename I, typename E> // +struct AcqRelT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [15.8.1] `memory-order` clauses +template <typename T, typename I, typename E> // +struct AcquireT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [7.5.2] `adjust_args` clause +template <typename T, typename I, typename E> // +struct AdjustArgsT { + using IncompleteTrait = std::true_type; +}; + +// V5.2: [12.5.1] `affinity` clause +template <typename T, typename I, typename E> // +struct AffinityT { + using Iterator = type::IteratorT<T, I, E>; + using LocatorList = ObjectListT<I, E>; + + using TupleTrait = std::true_type; + std::tuple<OPT(Iterator), LocatorList> t; +}; + +// V5.2: [6.3] `align` clause +template <typename T, typename I, typename E> // +struct AlignT { + using Alignment = E; + + using WrapperTrait = std::true_type; + Alignment v; +}; + +// V5.2: [5.11] `aligned` clause +template <typename T, typename I, typename E> // +struct AlignedT { + using Alignment = E; + using List = ObjectListT<I, E>; + + using TupleTrait = std::true_type; + std::tuple<OPT(Alignment), List> t; +}; + +template <typename T, typename I, typename E> // +struct AllocatorT; + +// V5.2: [6.6] `allocate` clause +template <typename T, typename I, typename E> // +struct AllocateT { + using AllocatorSimpleModifier = E; + using AllocatorComplexModifier = AllocatorT<T, I, E>; + using AlignModifier = AlignT<T, I, E>; + using List = ObjectListT<I, E>; + + using TupleTrait = std::true_type; + std::tuple<OPT(AllocatorSimpleModifier), OPT(AllocatorComplexModifier), + OPT(AlignModifier), List> + t; +}; + +// V5.2: [6.4] `allocator` clause +template <typename T, typename I, typename E> // +struct AllocatorT { + using Allocator = E; + using WrapperTrait = std::true_type; + Allocator v; +}; + +// V5.2: [7.5.3] `append_args` clause +template <typename T, typename I, typename E> // +struct AppendArgsT { + using IncompleteTrait = std::true_type; +}; + +// V5.2: [8.1] `at` clause +template <typename T, typename I, typename E> // +struct AtT { + ENUM(ActionTime, Compilation, Execution); + using WrapperTrait = std::true_type; + ActionTime v; +}; + +// V5.2: [8.2.1] `requirement` clauses +template <typename T, typename I, typename E> // +struct AtomicDefaultMemOrderT { + using MemoryOrder = type::MemoryOrder; + using WrapperTrait = std::true_type; + MemoryOrder v; // Name not provided in spec +}; + +// V5.2: [11.7.1] `bind` clause +template <typename T, typename I, typename E> // +struct BindT { + ENUM(Binding, Teams, Parallel, Thread); + using WrapperTrait = std::true_type; + Binding v; +}; + +// V5.2: [15.8.3] `extended-atomic` clauses +template <typename T, typename I, typename E> // +struct CaptureT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [4.4.3] `collapse` clause +template <typename T, typename I, typename E> // +struct CollapseT { + using N = E; + using WrapperTrait = std::true_type; + N v; +}; + +// V5.2: [15.8.3] `extended-atomic` clauses +template <typename T, typename I, typename E> // +struct CompareT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [8.3.1] `assumption` clauses +template <typename T, typename I, typename E> // +struct ContainsT { + using List = ListT<type::DirectiveName>; + using WrapperTrait = std::true_type; + List v; +}; + +// V5.2: [5.7.1] `copyin` clause +template <typename T, typename I, typename E> // +struct CopyinT { + using List = ObjectListT<I, E>; + using WrapperTrait = std::true_type; + List v; +}; + +// V5.2: [5.7.2] `copyprivate` clause +template <typename T, typename I, typename E> // +struct CopyprivateT { + using List = ObjectListT<I, E>; + using WrapperTrait = std::true_type; + List v; +}; + +// V5.2: [5.4.1] `default` clause +template <typename T, typename I, typename E> // +struct DefaultT { + ENUM(DataSharingAttribute, Firstprivate, None, Private, Shared); + using WrapperTrait = std::true_type; + DataSharingAttribute v; +}; + +// V5.2: [5.8.7] `defaultmap` clause +template <typename T, typename I, typename E> // +struct DefaultmapT { + ENUM(ImplicitBehavior, Alloc, To, From, Tofrom, Firstprivate, None, Default, + Present); + ENUM(VariableCategory, Scalar, Aggregate, Pointer, Allocatable); + using TupleTrait = std::true_type; + std::tuple<ImplicitBehavior, OPT(VariableCategory)> t; +}; + +template <typename T, typename I, typename E> // +struct DoacrossT; + +// V5.2: [15.9.5] `depend` clause +template <typename T, typename I, typename E> // +struct DependT { + using Iterator = type::IteratorT<T, I, E>; + using LocatorList = ObjectListT<I, E>; + using TaskDependenceType = tomp::type::TaskDependenceType; + + struct WithLocators { // Modern form + using TupleTrait = std::true_type; + // Empty LocatorList means "omp_all_memory". + std::tuple<TaskDependenceType, OPT(Iterator), LocatorList> t; + }; + + using Doacross = DoacrossT<T, I, E>; + using UnionTrait = std::true_type; + std::variant<Doacross, WithLocators> u; // Doacross form is legacy +}; + +// V5.2: [3.5] `destroy` clause +template <typename T, typename I, typename E> // +struct DestroyT { + using DestroyVar = ObjectT<I, E>; + using WrapperTrait = std::true_type; + // DestroyVar can be ommitted in "depobj destroy". + OPT(DestroyVar) v; +}; + +// V5.2: [12.5.2] `detach` clause +template <typename T, typename I, typename E> // +struct DetachT { + using EventHandle = ObjectT<I, E>; + using WrapperTrait = std::true_type; + EventHandle v; +}; + +// V5.2: [13.2] `device` clause +template <typename T, typename I, typename E> // +struct DeviceT { + using DeviceDescription = E; + ENUM(DeviceModifier, Ancestor, DeviceNum); + using TupleTrait = std::true_type; + std::tuple<OPT(DeviceModifier), DeviceDescription> t; +}; + +// V5.2: [13.1] `device_type` clause +template <typename T, typename I, typename E> // +struct DeviceTypeT { + ENUM(DeviceTypeDescription, Any, Host, Nohost); + using WrapperTrait = std::true_type; + DeviceTypeDescription v; +}; + +// V5.2: [11.6.1] `dist_schedule` clause +template <typename T, typename I, typename E> // +struct DistScheduleT { + ENUM(Kind, Static); + using ChunkSize = E; + using TupleTrait = std::true_type; + std::tuple<Kind, OPT(ChunkSize)> t; +}; + +// V5.2: [15.9.6] `doacross` clause +template <typename T, typename I, typename E> // +struct DoacrossT { + using Vector = ListT<type::LoopIterationT<I, E>>; + ENUM(DependenceType, Source, Sink); + using TupleTrait = std::true_type; + // Empty Vector means "omp_cur_iteration" + std::tuple<DependenceType, Vector> t; +}; + +// V5.2: [8.2.1] `requirement` clauses +template <typename T, typename I, typename E> // +struct DynamicAllocatorsT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [5.8.4] `enter` clause +template <typename T, typename I, typename E> // +struct EnterT { + using List = ObjectListT<I, E>; + using WrapperTrait = std::true_type; + List v; +}; + +// V5.2: [5.6.2] `exclusive` clause +template <typename T, typename I, typename E> // +struct ExclusiveT { + using WrapperTrait = std::true_type; + using List = ObjectListT<I, E>; + List v; +}; + +// V5.2: [15.8.3] `extended-atomic` clauses +template <typename T, typename I, typename E> // +struct FailT { + using MemoryOrder = type::MemoryOrder; + using WrapperTrait = std::true_type; + MemoryOrder v; +}; + +// V5.2: [10.5.1] `filter` clause +template <typename T, typename I, typename E> // +struct FilterT { + using ThreadNum = E; + using WrapperTrait = std::true_type; + ThreadNum v; +}; + +// V5.2: [12.3] `final` clause +template <typename T, typename I, typename E> // +struct FinalT { + using Finalize = E; + using WrapperTrait = std::true_type; + Finalize v; +}; + +// V5.2: [5.4.4] `firstprivate` clause +template <typename T, typename I, typename E> // +struct FirstprivateT { + using List = ObjectListT<I, E>; + using WrapperTrait = std::true_type; + List v; +}; + +// V5.2: [5.9.2] `from` clause +template <typename T, typename I, typename E> // +struct FromT { + using LocatorList = ObjectListT<I, E>; + using Expectation = type::MotionExpectation; + using Iterator = type::IteratorT<T, I, E>; + // See note at the definition of the MapperT type. + using Mappers = ListT<type::MapperT<I, E>>; // Not a spec name + + using TupleTrait = std::true_type; + std::tuple<OPT(Expectation), OPT(Mappers), OPT(Iterator), LocatorList> t; +}; + +// V5.2: [9.2.1] `full` clause +template <typename T, typename I, typename E> // +struct FullT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [12.6.1] `grainsize` clause +template <typename T, typename I, typename E> // +struct GrainsizeT { + ENUM(Prescriptiveness, Strict); + using GrainSize = E; + using TupleTrait = std::true_type; + std::tuple<OPT(Prescriptiveness), GrainSize> t; +}; + +// V5.2: [5.4.9] `has_device_addr` clause +template <typename T, typename I, typename E> // +struct HasDeviceAddrT { + using List = ObjectListT<I, E>; + using WrapperTrait = std::true_type; + List v; +}; + +// V5.2: [15.1.2] `hint` clause +template <typename T, typename I, typename E> // +struct HintT { + using HintExpr = E; + using WrapperTrait = std::true_type; + HintExpr v; +}; + +// V5.2: [8.3.1] Assumption clauses +template <typename T, typename I, typename E> // +struct HoldsT { + using WrapperTrait = std::true_type; + E v; // No argument name in spec 5.2 +}; + +// V5.2: [3.4] `if` clause +template <typename T, typename I, typename E> // +struct IfT { + using DirectiveNameModifier = type::DirectiveName; + using IfExpression = E; + using TupleTrait = std::true_type; + std::tuple<OPT(DirectiveNameModifier), IfExpression> t; +}; + +// V5.2: [7.7.1] `branch` clauses +template <typename T, typename I, typename E> // +struct InbranchT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [5.6.1] `exclusive` clause +template <typename T, typename I, typename E> // +struct InclusiveT { + using List = ObjectListT<I, E>; + using WrapperTrait = std::true_type; + List v; +}; + +// V5.2: [7.8.3] `indirect` clause +template <typename T, typename I, typename E> // +struct IndirectT { + using InvokedByFptr = E; + using WrapperTrait = std::true_type; + InvokedByFptr v; +}; + +// V5.2: [14.1.2] `init` clause +template <typename T, typename I, typename E> // +struct InitT { + using ForeignRuntimeId = E; + using InteropVar = ObjectT<I, E>; + using InteropPreference = ListT<ForeignRuntimeId>; + ENUM(InteropType, Target, Targetsync); // Repeatable + using InteropTypes = ListT<InteropType>; // Not a spec name + + using TupleTrait = std::true_type; + std::tuple<OPT(InteropPreference), InteropTypes, InteropVar> t; +}; + +// V5.2: [5.5.4] `initializer` clause +template <typename T, typename I, typename E> // +struct InitializerT { + using InitializerExpr = E; + using WrapperTrait = std::true_type; + InitializerExpr v; +}; + +// V5.2: [5.5.10] `in_reduction` clause +template <typename T, typename I, typename E> // +struct InReductionT { + using List = ObjectListT<I, E>; + // See note at the definition of the ReductionIdentifierT type. + // The name ReductionIdentifiers is not a spec name. + using ReductionIdentifiers = ListT<type::ReductionIdentifierT<I, E>>; + using TupleTrait = std::true_type; + std::tuple<ReductionIdentifiers, List> t; +}; + +// V5.2: [5.4.7] `is_device_ptr` clause +template <typename T, typename I, typename E> // +struct IsDevicePtrT { + using List = ObjectListT<I, E>; + using WrapperTrait = std::true_type; + List v; +}; + +// V5.2: [5.4.5] `lastprivate` clause +template <typename T, typename I, typename E> // +struct LastprivateT { + using List = ObjectListT<I, E>; + ENUM(LastprivateModifier, Conditional); + using TupleTrait = std::true_type; + std::tuple<OPT(LastprivateModifier), List> t; +}; + +// V5.2: [5.4.6] `linear` clause +template <typename T, typename I, typename E> // +struct LinearT { + // std::get<type> won't work here due to duplicate types in the tuple. + using List = ObjectListT<I, E>; + using StepSimpleModifier = E; + using StepComplexModifier = E; + ENUM(LinearModifier, Ref, Val, Uval); + + using TupleTrait = std::true_type; + // Step == nullptr means 1. + std::tuple<OPT(StepSimpleModifier), OPT(StepComplexModifier), + OPT(LinearModifier), List> + t; +}; + +// V5.2: [5.8.5] `link` clause +template <typename T, typename I, typename E> // +struct LinkT { + using List = ObjectListT<I, E>; + using WrapperTrait = std::true_type; + List v; +}; + +// V5.2: [5.8.3] `map` clause +template <typename T, typename I, typename E> // +struct MapT { + using LocatorList = ObjectListT<I, E>; + ENUM(MapType, To, From, Tofrom, Alloc, Release, Delete); + ENUM(MapTypeModifier, Always, Close, Present, OmpxHold); + // See note at the definition of the MapperT type. + using Mappers = ListT<type::MapperT<I, E>>; // Not a spec name + using Iterator = type::IteratorT<T, I, E>; + using MapTypeModifiers = ListT<MapTypeModifier>; // Not a spec name + + using TupleTrait = std::true_type; + std::tuple<OPT(MapType), OPT(MapTypeModifiers), OPT(Mappers), OPT(Iterator), + LocatorList> + t; +}; + +// V5.2: [7.5.1] `match` clause +template <typename T, typename I, typename E> // +struct MatchT { + using IncompleteTrait = std::true_type; +}; + +// V5.2: [12.2] `mergeable` clause +template <typename T, typename I, typename E> // +struct MergeableT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [8.5.2] `message` clause +template <typename T, typename I, typename E> // +struct MessageT { + using MsgString = E; + using WrapperTrait = std::true_type; + MsgString v; +}; + +// V5.2: [7.6.2] `nocontext` clause +template <typename T, typename I, typename E> // +struct NocontextT { + using DoNotUpdateContext = E; + using WrapperTrait = std::true_type; + DoNotUpdateContext v; +}; + +// V5.2: [15.7] `nowait` clause +template <typename T, typename I, typename E> // +struct NogroupT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [10.4.1] `nontemporal` clause +template <typename T, typename I, typename E> // +struct NontemporalT { + using List = ObjectListT<I, E>; + using WrapperTrait = std::true_type; + List v; +}; + +// V5.2: [8.3.1] `assumption` clauses +template <typename T, typename I, typename E> // +struct NoOpenmpT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [8.3.1] `assumption` clauses +template <typename T, typename I, typename E> // +struct NoOpenmpRoutinesT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [8.3.1] `assumption` clauses +template <typename T, typename I, typename E> // +struct NoParallelismT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [7.7.1] `branch` clauses +template <typename T, typename I, typename E> // +struct NotinbranchT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [7.6.1] `novariants` clause +template <typename T, typename I, typename E> // +struct NovariantsT { + using DoNotUseVariant = E; + using WrapperTrait = std::true_type; + DoNotUseVariant v; +}; + +// V5.2: [15.6] `nowait` clause +template <typename T, typename I, typename E> // +struct NowaitT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [12.6.2] `num_tasks` clause +template <typename T, typename I, typename E> // +struct NumTasksT { + using NumTasks = E; + ENUM(Prescriptiveness, Strict); + using TupleTrait = std::true_type; + std::tuple<OPT(Prescriptiveness), NumTasks> t; +}; + +// V5.2: [10.2.1] `num_teams` clause +template <typename T, typename I, typename E> // +struct NumTeamsT { + using TupleTrait = std::true_type; + using LowerBound = E; + using UpperBound = E; + std::tuple<OPT(LowerBound), UpperBound> t; +}; + +// V5.2: [10.1.2] `num_threads` clause +template <typename T, typename I, typename E> // +struct NumThreadsT { + using Nthreads = E; + using WrapperTrait = std::true_type; + Nthreads v; +}; + +template <typename T, typename I, typename E> // +struct OmpxAttributeT { + using EmptyTrait = std::true_type; +}; + +template <typename T, typename I, typename E> // +struct OmpxBareT { + using EmptyTrait = std::true_type; +}; + +template <typename T, typename I, typename E> // +struct OmpxDynCgroupMemT { + using WrapperTrait = std::true_type; + E v; +}; + +// V5.2: [10.3] `order` clause +template <typename T, typename I, typename E> // +struct OrderT { + ENUM(OrderModifier, Reproducible, Unconstrained); + ENUM(Ordering, Concurrent); + using TupleTrait = std::true_type; + std::tuple<OPT(OrderModifier), Ordering> t; +}; + +// V5.2: [4.4.4] `ordered` clause +template <typename T, typename I, typename E> // +struct OrderedT { + using N = E; + using WrapperTrait = std::true_type; + OPT(N) v; +}; + +// V5.2: [7.4.2] `otherwise` clause +template <typename T, typename I, typename E> // +struct OtherwiseT { + using IncompleteTrait = std::true_type; +}; + +// V5.2: [9.2.2] `partial` clause +template <typename T, typename I, typename E> // +struct PartialT { + using UnrollFactor = E; + using WrapperTrait = std::true_type; + OPT(UnrollFactor) v; +}; + +// V5.2: [12.4] `priority` clause +template <typename T, typename I, typename E> // +struct PriorityT { + using PriorityValue = E; + using WrapperTrait = std::true_type; + PriorityValue v; +}; + +// V5.2: [5.4.3] `private` clause +template <typename T, typename I, typename E> // +struct PrivateT { + using List = ObjectListT<I, E>; + using WrapperTrait = std::true_type; + List v; +}; + +// V5.2: [10.1.4] `proc_bind` clause +template <typename T, typename I, typename E> // +struct ProcBindT { + ENUM(AffinityPolicy, Close, Master, Spread, Primary); + using WrapperTrait = std::true_type; + AffinityPolicy v; +}; + +// V5.2: [15.8.2] Atomic clauses +template <typename T, typename I, typename E> // +struct ReadT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [5.5.8] `reduction` clause +template <typename T, typename I, typename E> // +struct ReductionT { + using List = ObjectListT<I, E>; + // See note at the definition of the ReductionIdentifierT type. + // The name ReductionIdentifiers is not a spec name. + using ReductionIdentifiers = ListT<type::ReductionIdentifierT<I, E>>; + ENUM(ReductionModifier, Default, Inscan, Task); + using TupleTrait = std::true_type; + std::tuple<ReductionIdentifiers, OPT(ReductionModifier), List> t; +}; + +// V5.2: [15.8.1] `memory-order` clauses +template <typename T, typename I, typename E> // +struct RelaxedT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [15.8.1] `memory-order` clauses +template <typename T, typename I, typename E> // +struct ReleaseT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [8.2.1] `requirement` clauses +template <typename T, typename I, typename E> // +struct ReverseOffloadT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [10.4.2] `safelen` clause +template <typename T, typename I, typename E> // +struct SafelenT { + using Length = E; + using WrapperTrait = std::true_type; + Length v; +}; + +// V5.2: [11.5.3] `schedule` clause +template <typename T, typename I, typename E> // +struct ScheduleT { + ENUM(Kind, Static, Dynamic, Guided, Auto, Runtime); + using ChunkSize = E; + ENUM(OrderingModifier, Monotonic, Nonmonotonic); + ENUM(ChunkModifier, Simd); + using TupleTrait = std::true_type; + std::tuple<Kind, OPT(OrderingModifier), OPT(ChunkModifier), OPT(ChunkSize)> t; +}; + +// V5.2: [15.8.1] Memory-order clauses +template <typename T, typename I, typename E> // +struct SeqCstT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [8.5.1] `severity` clause +template <typename T, typename I, typename E> // +struct SeverityT { + ENUM(SevLevel, Fatal, Warning); + using WrapperTrait = std::true_type; + SevLevel v; +}; + +// V5.2: [5.4.2] `shared` clause +template <typename T, typename I, typename E> // +struct SharedT { + using List = ObjectListT<I, E>; + using WrapperTrait = std::true_type; + List v; +}; + +// V5.2: [15.10.3] `parallelization-level` clauses +template <typename T, typename I, typename E> // +struct SimdT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [10.4.3] `simdlen` clause +template <typename T, typename I, typename E> // +struct SimdlenT { + using Length = E; + using WrapperTrait = std::true_type; + Length v; +}; + +// V5.2: [9.1.1] `sizes` clause +template <typename T, typename I, typename E> // +struct SizesT { + using SizeList = ListT<E>; + using WrapperTrait = std::true_type; + SizeList v; +}; + +// V5.2: [5.5.9] `task_reduction` clause +template <typename T, typename I, typename E> // +struct TaskReductionT { + using List = ObjectListT<I, E>; + // See note at the definition of the ReductionIdentifierT type. + // The name ReductionIdentifiers is not a spec name. + using ReductionIdentifiers = ListT<type::ReductionIdentifierT<I, E>>; + using TupleTrait = std::true_type; + std::tuple<ReductionIdentifiers, List> t; +}; + +// V5.2: [13.3] `thread_limit` clause +template <typename T, typename I, typename E> // +struct ThreadLimitT { + using Threadlim = E; + using WrapperTrait = std::true_type; + Threadlim v; +}; + +// V5.2: [15.10.3] `parallelization-level` clauses +template <typename T, typename I, typename E> // +struct ThreadsT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [5.9.1] `to` clause +template <typename T, typename I, typename E> // +struct ToT { + using LocatorList = ObjectListT<I, E>; + using Expectation = type::MotionExpectation; + // See note at the definition of the MapperT type. + using Mappers = ListT<type::MapperT<I, E>>; // Not a spec name + using Iterator = type::IteratorT<T, I, E>; + + using TupleTrait = std::true_type; + std::tuple<OPT(Expectation), OPT(Mappers), OPT(Iterator), LocatorList> t; +}; + +// V5.2: [8.2.1] `requirement` clauses +template <typename T, typename I, typename E> // +struct UnifiedAddressT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [8.2.1] `requirement` clauses +template <typename T, typename I, typename E> // +struct UnifiedSharedMemoryT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [5.10] `uniform` clause +template <typename T, typename I, typename E> // +struct UniformT { + using ParameterList = ObjectListT<I, E>; + using WrapperTrait = std::true_type; + ParameterList v; +}; + +template <typename T, typename I, typename E> // +struct UnknownT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [12.1] `untied` clause +template <typename T, typename I, typename E> // +struct UntiedT { + using EmptyTrait = std::true_type; +}; + +// Both of the following +// V5.2: [15.8.2] `atomic` clauses +// V5.2: [15.9.3] `update` clause +template <typename T, typename I, typename E> // +struct UpdateT { + using TaskDependenceType = tomp::type::TaskDependenceType; + using WrapperTrait = std::true_type; + OPT(TaskDependenceType) v; +}; + +// V5.2: [14.1.3] `use` clause +template <typename T, typename I, typename E> // +struct UseT { + using InteropVar = ObjectT<I, E>; + using WrapperTrait = std::true_type; + InteropVar v; +}; + +// V5.2: [5.4.10] `use_device_addr` clause +template <typename T, typename I, typename E> // +struct UseDeviceAddrT { + using List = ObjectListT<I, E>; + using WrapperTrait = std::true_type; + List v; +}; + +// V5.2: [5.4.8] `use_device_ptr` clause +template <typename T, typename I, typename E> // +struct UseDevicePtrT { + using List = ObjectListT<I, E>; + using WrapperTrait = std::true_type; + List v; +}; + +// V5.2: [6.8] `uses_allocators` clause +template <typename T, typename I, typename E> // +struct UsesAllocatorsT { + using MemSpace = E; + using TraitsArray = ObjectT<I, E>; + using Allocator = E; + using AllocatorSpec = + std::tuple<OPT(MemSpace), OPT(TraitsArray), Allocator>; // Not a spec name + using Allocators = ListT<AllocatorSpec>; // Not a spec name + using WrapperTrait = std::true_type; + Allocators v; +}; + +// V5.2: [15.8.3] `extended-atomic` clauses +template <typename T, typename I, typename E> // +struct WeakT { + using EmptyTrait = std::true_type; +}; + +// V5.2: [7.4.1] `when` clause +template <typename T, typename I, typename E> // +struct WhenT { + using IncompleteTrait = std::true_type; +}; + +// V5.2: [15.8.2] Atomic clauses +template <typename T, typename I, typename E> // +struct WriteT { + using EmptyTrait = std::true_type; +}; + +// --- + +template <typename T, typename I, typename E> +using ExtensionClausesT = + std::variant<OmpxAttributeT<T, I, E>, OmpxBareT<T, I, E>, + OmpxDynCgroupMemT<T, I, E>>; + +template <typename T, typename I, typename E> +using EmptyClausesT = std::variant< + AcqRelT<T, I, E>, AcquireT<T, I, E>, CaptureT<T, I, E>, CompareT<T, I, E>, + DynamicAllocatorsT<T, I, E>, FullT<T, I, E>, InbranchT<T, I, E>, + MergeableT<T, I, E>, NogroupT<T, I, E>, NoOpenmpRoutinesT<T, I, E>, + NoOpenmpT<T, I, E>, NoParallelismT<T, I, E>, NotinbranchT<T, I, E>, + NowaitT<T, I, E>, ReadT<T, I, E>, RelaxedT<T, I, E>, ReleaseT<T, I, E>, + ReverseOffloadT<T, I, E>, SeqCstT<T, I, E>, SimdT<T, I, E>, + ThreadsT<T, I, E>, UnifiedAddressT<T, I, E>, UnifiedSharedMemoryT<T, I, E>, + UnknownT<T, I, E>, UntiedT<T, I, E>, UseT<T, I, E>, WeakT<T, I, E>, + WriteT<T, I, E>>; + +template <typename T, typename I, typename E> +using IncompleteClausesT = + std::variant<AdjustArgsT<T, I, E>, AppendArgsT<T, I, E>, MatchT<T, I, E>, + OtherwiseT<T, I, E>, WhenT<T, I, E>>; + +template <typename T, typename I, typename E> +using TupleClausesT = + std::variant<AffinityT<T, I, E>, AlignedT<T, I, E>, AllocateT<T, I, E>, + DefaultmapT<T, I, E>, DeviceT<T, I, E>, DistScheduleT<T, I, E>, + DoacrossT<T, I, E>, FromT<T, I, E>, GrainsizeT<T, I, E>, + IfT<T, I, E>, InitT<T, I, E>, InReductionT<T, I, E>, + LastprivateT<T, I, E>, LinearT<T, I, E>, MapT<T, I, E>, + NumTasksT<T, I, E>, OrderT<T, I, E>, ReductionT<T, I, E>, + ScheduleT<T, I, E>, TaskReductionT<T, I, E>, ToT<T, I, E>>; + +template <typename T, typename I, typename E> +using UnionClausesT = std::variant<DependT<T, I, E>>; + +template <typename T, typename I, typename E> +using WrapperClausesT = std::variant< + AbsentT<T, I, E>, AlignT<T, I, E>, AllocatorT<T, I, E>, + AtomicDefaultMemOrderT<T, I, E>, AtT<T, I, E>, BindT<T, I, E>, + CollapseT<T, I, E>, ContainsT<T, I, E>, CopyinT<T, I, E>, + CopyprivateT<T, I, E>, DefaultT<T, I, E>, DestroyT<T, I, E>, + DetachT<T, I, E>, DeviceTypeT<T, I, E>, EnterT<T, I, E>, + ExclusiveT<T, I, E>, FailT<T, I, E>, FilterT<T, I, E>, FinalT<T, I, E>, + FirstprivateT<T, I, E>, HasDeviceAddrT<T, I, E>, HintT<T, I, E>, + HoldsT<T, I, E>, InclusiveT<T, I, E>, IndirectT<T, I, E>, + InitializerT<T, I, E>, IsDevicePtrT<T, I, E>, LinkT<T, I, E>, + MessageT<T, I, E>, NocontextT<T, I, E>, NontemporalT<T, I, E>, + NovariantsT<T, I, E>, NumTeamsT<T, I, E>, NumThreadsT<T, I, E>, + OrderedT<T, I, E>, PartialT<T, I, E>, PriorityT<T, I, E>, PrivateT<T, I, E>, + ProcBindT<T, I, E>, SafelenT<T, I, E>, SeverityT<T, I, E>, SharedT<T, I, E>, + SimdlenT<T, I, E>, SizesT<T, I, E>, ThreadLimitT<T, I, E>, + UniformT<T, I, E>, UpdateT<T, I, E>, UseDeviceAddrT<T, I, E>, + UseDevicePtrT<T, I, E>, UsesAllocatorsT<T, I, E>>; + +template <typename T, typename I, typename E> +using UnionOfAllClausesT = typename type::Union< // + EmptyClausesT<T, I, E>, // + ExtensionClausesT<T, I, E>, // + IncompleteClausesT<T, I, E>, // + TupleClausesT<T, I, E>, // + UnionClausesT<T, I, E>, // + WrapperClausesT<T, I, E> // + >::type; + +} // namespace clause + +// The variant wrapper that encapsulates all possible specific clauses. +// The `Extras` arguments are additional types representing local extensions +// to the clause set, e.g. +// +// using Clause = ClauseT<Type, Id, Expr, +// MyClause1, MyClause2>; +// +// The member Clause::u will be a variant containing all specific clauses +// defined above, plus MyClause1 and MyClause2. +template <typename TypeType, typename IdType, typename ExprType, + typename... Extras> +struct ClauseT { + using TypeTy = TypeType; + using IdTy = IdType; + using ExprTy = ExprType; + + using VariantTy = typename type::Union< + clause::UnionOfAllClausesT<TypeType, IdType, ExprType>, + std::variant<Extras...>>::type; + + llvm::omp::Clause id; // The numeric id of the clause + using UnionTrait = std::true_type; + VariantTy u; +}; + +} // namespace tomp + +#undef OPT +#undef ENUM + +#endif // LLVM_FRONTEND_OPENMP_CLAUSET_H diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h b/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h index 1bfaf3718552e5ba48b6fb52c9cd08e7e4d2c55d..338b56226f204199cebd1f2d559310a66b542aeb 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h +++ b/llvm/include/llvm/Frontend/OpenMP/OMPConstants.h @@ -72,7 +72,10 @@ enum class IdentFlag { #include "llvm/Frontend/OpenMP/OMPKinds.def" // Version of the kernel argument format used by the omp runtime. -#define OMP_KERNEL_ARG_VERSION 2 +#define OMP_KERNEL_ARG_VERSION 3 + +// Minimum version of the compiler that generates a kernel dynamic pointer. +#define OMP_KERNEL_ARG_MIN_VERSION_WITH_DYN_PTR 3 /// \note This needs to be kept in sync with kmp.h enum sched_type. /// Todo: Update kmp.h to include this file, and remove the enums in kmp.h diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h index 5bbaa8c208b8cdc7c41f15ad7f0c090e3d6e3df4..c9ee0c25194c23de058181a24b7191539cde8a3b 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h +++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h @@ -1339,10 +1339,12 @@ public: /// in reductions. /// \param ReductionInfos A list of info on each reduction variable. /// \param IsNoWait A flag set if the reduction is marked as nowait. + /// \param IsByRef A flag set if the reduction is using reference + /// or direct value. InsertPointTy createReductions(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef<ReductionInfo> ReductionInfos, - bool IsNoWait = false); + bool IsNoWait = false, bool IsByRef = false); ///} diff --git a/llvm/include/llvm/IR/Argument.h b/llvm/include/llvm/IR/Argument.h index f0c0ce75d2b7e18063389a98379fddfeda2a71ec..3349f1306970eb271a865c2dd431de11d474af9f 100644 --- a/llvm/include/llvm/IR/Argument.h +++ b/llvm/include/llvm/IR/Argument.h @@ -16,9 +16,12 @@ #include "llvm/ADT/Twine.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Value.h" +#include <optional> namespace llvm { +class ConstantRange; + /// This class represents an incoming formal argument to a Function. A formal /// argument, since it is ``formal'', does not contain an actual value but /// instead represents the type, argument number, and attributes of an argument @@ -67,6 +70,10 @@ public: /// disallowed floating-point values. Otherwise, fcNone is returned. FPClassTest getNoFPClass() const; + /// If this argument has a range attribute, return the value range of the + /// argument. Otherwise, std::nullopt is returned. + std::optional<ConstantRange> getRange() const; + /// Return true if this argument has the byval attribute. bool hasByValAttr() const; diff --git a/llvm/include/llvm/IR/AutoUpgrade.h b/llvm/include/llvm/IR/AutoUpgrade.h index 1ef32bcb121bec0cdfcd7659e7df72c981905c14..152f781ffa9b30598310c8d07c74913c6bcb5d1a 100644 --- a/llvm/include/llvm/IR/AutoUpgrade.h +++ b/llvm/include/llvm/IR/AutoUpgrade.h @@ -88,9 +88,6 @@ namespace llvm { /// info. Return true if module is modified. bool UpgradeDebugInfo(Module &M); - /// Copies module attributes to the functions in the module. - void CopyModuleAttrToFunctions(Module &M); - /// Check whether a string looks like an old loop attachment tag. inline bool mayBeOldLoopAttachmentTag(StringRef Name) { return Name.starts_with("llvm.vectorizer."); diff --git a/llvm/include/llvm/IR/BasicBlock.h b/llvm/include/llvm/IR/BasicBlock.h index 5bac113c9b7b42ac0bc5f0875149485c70cb8ad3..0c5a07bde4ecf099dbc826ea8cfac2a7a50e846d 100644 --- a/llvm/include/llvm/IR/BasicBlock.h +++ b/llvm/include/llvm/IR/BasicBlock.h @@ -14,6 +14,7 @@ #define LLVM_IR_BASICBLOCK_H #include "llvm-c/Types.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Twine.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" @@ -21,7 +22,6 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/IR/DebugProgramInstruction.h" #include "llvm/IR/Instruction.h" -#include "llvm/IR/DebugProgramInstruction.h" #include "llvm/IR/SymbolTableListTraits.h" #include "llvm/IR/Value.h" #include <cassert> @@ -38,8 +38,8 @@ class LLVMContext; class Module; class PHINode; class ValueSymbolTable; -class DPValue; -class DPMarker; +class DbgVariableRecord; +class DbgMarker; /// LLVM Basic Block Representation /// @@ -72,19 +72,19 @@ private: Function *Parent; public: - /// Attach a DPMarker to the given instruction. Enables the storage of any + /// Attach a DbgMarker to the given instruction. Enables the storage of any /// debug-info at this position in the program. - DPMarker *createMarker(Instruction *I); - DPMarker *createMarker(InstListType::iterator It); + DbgMarker *createMarker(Instruction *I); + DbgMarker *createMarker(InstListType::iterator It); /// Convert variable location debugging information stored in dbg.value - /// intrinsics into DPMarker / DPValue records. Deletes all dbg.values in + /// intrinsics into DbgMarkers / DbgRecords. Deletes all dbg.values in /// the process and sets IsNewDbgInfoFormat = true. Only takes effect if /// the UseNewDbgInfoFormat LLVM command line option is given. void convertToNewDbgValues(); - /// Convert variable location debugging information stored in DPMarkers and - /// DPValues into the dbg.value intrinsic representation. Sets + /// Convert variable location debugging information stored in DbgMarkers and + /// DbgRecords into the dbg.value intrinsic representation. Sets /// IsNewDbgInfoFormat = false. void convertFromNewDbgValues(); @@ -93,50 +93,50 @@ public: /// if necessary. void setIsNewDbgInfoFormat(bool NewFlag); - /// Record that the collection of DPValues in \p M "trails" after the last + /// Record that the collection of DbgRecords in \p M "trails" after the last /// instruction of this block. These are equivalent to dbg.value intrinsics /// that exist at the end of a basic block with no terminator (a transient /// state that occurs regularly). - void setTrailingDbgRecords(DPMarker *M); + void setTrailingDbgRecords(DbgMarker *M); - /// Fetch the collection of DPValues that "trail" after the last instruction + /// Fetch the collection of DbgRecords that "trail" after the last instruction /// of this block, see \ref setTrailingDbgRecords. If there are none, returns /// nullptr. - DPMarker *getTrailingDbgRecords(); + DbgMarker *getTrailingDbgRecords(); - /// Delete any trailing DPValues at the end of this block, see + /// Delete any trailing DbgRecords at the end of this block, see /// \ref setTrailingDbgRecords. void deleteTrailingDbgRecords(); void dumpDbgValues() const; - /// Return the DPMarker for the position given by \p It, so that DPValues can - /// be inserted there. This will either be nullptr if not present, a DPMarker, - /// or TrailingDPValues if It is end(). - DPMarker *getMarker(InstListType::iterator It); + /// Return the DbgMarker for the position given by \p It, so that DbgRecords + /// can be inserted there. This will either be nullptr if not present, a + /// DbgMarker, or TrailingDbgRecords if It is end(). + DbgMarker *getMarker(InstListType::iterator It); - /// Return the DPMarker for the position that comes after \p I. \see - /// BasicBlock::getMarker, this can be nullptr, a DPMarker, or - /// TrailingDPValues if there is no next instruction. - DPMarker *getNextMarker(Instruction *I); + /// Return the DbgMarker for the position that comes after \p I. \see + /// BasicBlock::getMarker, this can be nullptr, a DbgMarker, or + /// TrailingDbgRecords if there is no next instruction. + DbgMarker *getNextMarker(Instruction *I); - /// Insert a DPValue into a block at the position given by \p I. - void insertDbgRecordAfter(DbgRecord *DPV, Instruction *I); + /// Insert a DbgRecord into a block at the position given by \p I. + void insertDbgRecordAfter(DbgRecord *DR, Instruction *I); - /// Insert a DPValue into a block at the position given by \p Here. - void insertDbgRecordBefore(DbgRecord *DPV, InstListType::iterator Here); + /// Insert a DbgRecord into a block at the position given by \p Here. + void insertDbgRecordBefore(DbgRecord *DR, InstListType::iterator Here); - /// Eject any debug-info trailing at the end of a block. DPValues can + /// Eject any debug-info trailing at the end of a block. DbgRecords can /// transiently be located "off the end" of a block if the blocks terminator /// is temporarily removed. Once a terminator is re-inserted this method will - /// move such DPValues back to the right place (ahead of the terminator). - void flushTerminatorDbgValues(); + /// move such DbgRecords back to the right place (ahead of the terminator). + void flushTerminatorDbgRecords(); /// In rare circumstances instructions can be speculatively removed from /// blocks, and then be re-inserted back into that position later. When this /// happens in RemoveDIs debug-info mode, some special patching-up needs to /// occur: inserting into the middle of a sequence of dbg.value intrinsics - /// does not have an equivalent with DPValues. + /// does not have an equivalent with DbgRecords. void reinsertInstInDbgRecords(Instruction *I, std::optional<DbgRecord::self_iterator> Pos); @@ -522,7 +522,7 @@ private: BasicBlock::iterator FromEndIt); /// Perform any debug-info specific maintenence for the given splice - /// activity. In the DPValue debug-info representation, debug-info is not + /// activity. In the DbgRecord debug-info representation, debug-info is not /// in instructions, and so it does not automatically move from one block /// to another. void spliceDebugInfo(BasicBlock::iterator ToIt, BasicBlock *FromBB, @@ -774,6 +774,32 @@ BasicBlock::iterator skipDebugIntrinsics(BasicBlock::iterator It); inline void BasicBlock::validateInstrOrdering() const {} #endif +// Specialize DenseMapInfo for iterators, so that ththey can be installed into +// maps and sets. The iterator is made up of its node pointer, and the +// debug-info "head" bit. +template <> struct DenseMapInfo<BasicBlock::iterator> { + static inline BasicBlock::iterator getEmptyKey() { + return BasicBlock::iterator(nullptr); + } + + static inline BasicBlock::iterator getTombstoneKey() { + BasicBlock::iterator It(nullptr); + It.setHeadBit(true); + return It; + } + + static unsigned getHashValue(const BasicBlock::iterator &It) { + return DenseMapInfo<void *>::getHashValue( + reinterpret_cast<void *>(It.getNodePtr())) ^ + (unsigned)It.getHeadBit(); + } + + static bool isEqual(const BasicBlock::iterator &LHS, + const BasicBlock::iterator &RHS) { + return LHS == RHS && LHS.getHeadBit() == RHS.getHeadBit(); + } +}; + } // end namespace llvm #endif // LLVM_IR_BASICBLOCK_H diff --git a/llvm/include/llvm/IR/CallingConv.h b/llvm/include/llvm/IR/CallingConv.h index ef8aaf52f4e6acaaa5b41ac02af0d0d215332ec2..a05d1a4d587845c13fc3d989c569d3a3beeb09fd 100644 --- a/llvm/include/llvm/IR/CallingConv.h +++ b/llvm/include/llvm/IR/CallingConv.h @@ -264,6 +264,9 @@ namespace CallingConv { /// except that the first parameter is mapped to x9. ARM64EC_Thunk_Native = 109, + /// Calling convention used for RISC-V V-extension. + RISCV_VectorCall = 110, + /// The highest possible ID. Must be some 2^k - 1. MaxID = 1023 }; diff --git a/llvm/include/llvm/IR/ConstantFold.h b/llvm/include/llvm/IR/ConstantFold.h index 77f5f0eb174a2bb2f045dfb3774d87ac32cadeb5..9b3c8a0e5a6329e0bc1eeba83dc15dc96342bd9b 100644 --- a/llvm/include/llvm/IR/ConstantFold.h +++ b/llvm/include/llvm/IR/ConstantFold.h @@ -53,7 +53,7 @@ namespace llvm { Constant *ConstantFoldCompareInstruction(CmpInst::Predicate Predicate, Constant *C1, Constant *C2); Constant *ConstantFoldGetElementPtr(Type *Ty, Constant *C, bool InBounds, - std::optional<unsigned> InRangeIndex, + std::optional<ConstantRange> InRange, ArrayRef<Value *> Idxs); } // End llvm namespace diff --git a/llvm/include/llvm/IR/ConstantFolder.h b/llvm/include/llvm/IR/ConstantFolder.h index c2b30a65e32e25141a8dbe655877dc05166459ea..3e74a563a58421b4220f756cc5c56ee511b4e636 100644 --- a/llvm/include/llvm/IR/ConstantFolder.h +++ b/llvm/include/llvm/IR/ConstantFolder.h @@ -18,8 +18,8 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/IR/Constants.h" #include "llvm/IR/ConstantFold.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/IRBuilderFolder.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Operator.h" @@ -89,7 +89,7 @@ public: } Value *FoldUnOpFMF(Instruction::UnaryOps Opc, Value *V, - FastMathFlags FMF) const override { + FastMathFlags FMF) const override { if (Constant *C = dyn_cast<Constant>(V)) return ConstantFoldUnaryInstruction(Opc, C); return nullptr; @@ -183,6 +183,12 @@ public: return nullptr; } + Value *FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty, + Instruction *FMFSource) const override { + // Use TargetFolder or InstSimplifyFolder instead. + return nullptr; + } + //===--------------------------------------------------------------------===// // Cast/Conversion Operators //===--------------------------------------------------------------------===// diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h index c0ac9a4aa6750cfbe10dbb454031db4c9d5025ae..4290ef4486c6f4cce8b25db7b85519f982d3753e 100644 --- a/llvm/include/llvm/IR/Constants.h +++ b/llvm/include/llvm/IR/Constants.h @@ -26,6 +26,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/Constant.h" +#include "llvm/IR/ConstantRange.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/OperandTraits.h" @@ -1045,8 +1046,7 @@ public: /// static Constant *getSizeOf(Type *Ty); - static Constant *getNeg(Constant *C, bool HasNUW = false, - bool HasNSW = false); + static Constant *getNeg(Constant *C, bool HasNSW = false); static Constant *getNot(Constant *C); static Constant *getAdd(Constant *C1, Constant *C2, bool HasNUW = false, bool HasNSW = false); @@ -1067,8 +1067,7 @@ public: static Constant *getAddrSpaceCast(Constant *C, Type *Ty, bool OnlyIfReduced = false); - static Constant *getNSWNeg(Constant *C) { return getNeg(C, false, true); } - static Constant *getNUWNeg(Constant *C) { return getNeg(C, true, false); } + static Constant *getNSWNeg(Constant *C) { return getNeg(C, /*HasNSW=*/true); } static Constant *getNSWAdd(Constant *C1, Constant *C2) { return getAdd(C1, C2, false, true); @@ -1195,31 +1194,31 @@ public: /// Getelementptr form. Value* is only accepted for convenience; /// all elements must be Constants. /// - /// \param InRangeIndex the inrange index if present or std::nullopt. + /// \param InRange the inrange range if present or std::nullopt. /// \param OnlyIfReducedTy see \a getWithOperands() docs. static Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList, bool InBounds = false, - std::optional<unsigned> InRangeIndex = std::nullopt, + std::optional<ConstantRange> InRange = std::nullopt, Type *OnlyIfReducedTy = nullptr) { return getGetElementPtr( Ty, C, ArrayRef((Value *const *)IdxList.data(), IdxList.size()), - InBounds, InRangeIndex, OnlyIfReducedTy); + InBounds, InRange, OnlyIfReducedTy); } static Constant * getGetElementPtr(Type *Ty, Constant *C, Constant *Idx, bool InBounds = false, - std::optional<unsigned> InRangeIndex = std::nullopt, + std::optional<ConstantRange> InRange = std::nullopt, Type *OnlyIfReducedTy = nullptr) { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return getGetElementPtr(Ty, C, cast<Value>(Idx), InBounds, InRangeIndex, + return getGetElementPtr(Ty, C, cast<Value>(Idx), InBounds, InRange, OnlyIfReducedTy); } static Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList, bool InBounds = false, - std::optional<unsigned> InRangeIndex = std::nullopt, + std::optional<ConstantRange> InRange = std::nullopt, Type *OnlyIfReducedTy = nullptr); /// Create an "inbounds" getelementptr. See the documentation for the @@ -1289,14 +1288,13 @@ public: Type *SrcTy = nullptr) const; /// Returns an Instruction which implements the same operation as this - /// ConstantExpr. If \p InsertBefore is not null, the new instruction is - /// inserted before it, otherwise it is not inserted into any basic block. + /// ConstantExpr. It is not inserted into any basic block. /// /// A better approach to this could be to have a constructor for Instruction /// which would take a ConstantExpr parameter, but that would have spread /// implementation details of ConstantExpr outside of Constants.cpp, which /// would make it harder to remove ConstantExprs altogether. - Instruction *getAsInstruction(Instruction *InsertBefore = nullptr) const; + Instruction *getAsInstruction() const; /// Whether creating a constant expression for this binary operator is /// desirable. diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h index 94af17af8160e933f94c45cc8f7aad5fd92aedaf..002f2db6da5447b2bcf2a28b25a6193e8a49038d 100644 --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -101,9 +101,10 @@ namespace llvm { DbgInstPtr insertLabel(DILabel *LabelInfo, const DILocation *DL, BasicBlock *InsertBB, Instruction *InsertBefore); - /// Internal helper. Track metadata if untracked and insert \p DPV. - void insertDPValue(DPValue *DPV, BasicBlock *InsertBB, - Instruction *InsertBefore, bool InsertAtHead = false); + /// Internal helper. Track metadata if untracked and insert \p DVR. + void insertDbgVariableRecord(DbgVariableRecord *DVR, BasicBlock *InsertBB, + Instruction *InsertBefore, + bool InsertAtHead = false); /// Internal helper with common code used by insertDbg{Value,Addr}Intrinsic. Instruction *insertDbgIntrinsic(llvm::Function *Intrinsic, llvm::Value *Val, @@ -270,6 +271,13 @@ namespace llvm { std::optional<unsigned> DWARFAddressSpace = std::nullopt, StringRef Name = "", DINodeArray Annotations = nullptr); + /// Create a __ptrauth qualifier. + DIDerivedType *createPtrAuthQualifiedType(DIType *FromTy, unsigned Key, + bool IsAddressDiscriminated, + unsigned ExtraDiscriminator, + bool IsaPointer, + bool authenticatesNullValues); + /// Create debugging information entry for a pointer to member. /// \param PointeeTy Type pointed to by this pointer. /// \param SizeInBits Size. diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h index 71f7f51d8ee431afb5b87b7b7dd2f575d7213e59..d14adfe1590be5f1605166fd40aa3ebd22b42dce 100644 --- a/llvm/include/llvm/IR/DataLayout.h +++ b/llvm/include/llvm/IR/DataLayout.h @@ -337,7 +337,7 @@ public: case MM_WinCOFF: return ".L"; case MM_GOFF: - return "@"; + return "L#"; case MM_Mips: return "$"; case MM_MachO: diff --git a/llvm/include/llvm/IR/DebugInfo.h b/llvm/include/llvm/IR/DebugInfo.h index 6673908d3ed355b25ca5aaab942db8994d3716ad..53cede5409e260dd6cf378c9d2f997083e8669fd 100644 --- a/llvm/include/llvm/IR/DebugInfo.h +++ b/llvm/include/llvm/IR/DebugInfo.h @@ -34,23 +34,25 @@ namespace llvm { class DbgDeclareInst; class DbgValueInst; class DbgVariableIntrinsic; -class DPValue; +class DbgVariableRecord; class Instruction; class Module; /// Finds dbg.declare intrinsics declaring local variables as living in the /// memory that 'V' points to. TinyPtrVector<DbgDeclareInst *> findDbgDeclares(Value *V); -/// As above, for DPVDeclares. -TinyPtrVector<DPValue *> findDPVDeclares(Value *V); +/// As above, for DVRDeclares. +TinyPtrVector<DbgVariableRecord *> findDVRDeclares(Value *V); /// Finds the llvm.dbg.value intrinsics describing a value. -void findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues, - Value *V, SmallVectorImpl<DPValue *> *DPValues = nullptr); +void findDbgValues( + SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V, + SmallVectorImpl<DbgVariableRecord *> *DbgVariableRecords = nullptr); /// Finds the debug info intrinsics describing a value. -void findDbgUsers(SmallVectorImpl<DbgVariableIntrinsic *> &DbgInsts, - Value *V, SmallVectorImpl<DPValue *> *DPValues = nullptr); +void findDbgUsers( + SmallVectorImpl<DbgVariableIntrinsic *> &DbgInsts, Value *V, + SmallVectorImpl<DbgVariableRecord *> *DbgVariableRecords = nullptr); /// Find subprogram that is enclosing this scope. DISubprogram *getDISubprogram(const MDNode *Scope); @@ -58,7 +60,7 @@ DISubprogram *getDISubprogram(const MDNode *Scope); /// Produce a DebugLoc to use for each dbg.declare that is promoted to a /// dbg.value. DebugLoc getDebugValueLoc(DbgVariableIntrinsic *DII); -DebugLoc getDebugValueLoc(DPValue *DPV); +DebugLoc getDebugValueLoc(DbgVariableRecord *DVR); /// Strip debug info in the module if it exists. /// @@ -109,7 +111,8 @@ public: void processVariable(const Module &M, const DILocalVariable *DVI); /// Process debug info location. void processLocation(const Module &M, const DILocation *Loc); - /// Process a DbgRecord (e.g, treat a DPValue like a DbgVariableIntrinsic). + /// Process a DbgRecord (e.g, treat a DbgVariableRecord like a + /// DbgVariableIntrinsic). void processDbgRecord(const Module &M, const DbgRecord &DR); /// Process subprogram. @@ -193,10 +196,10 @@ inline AssignmentInstRange getAssignmentInsts(const DbgAssignIntrinsic *DAI) { return getAssignmentInsts(DAI->getAssignID()); } -inline AssignmentInstRange getAssignmentInsts(const DPValue *DPV) { - assert(DPV->isDbgAssign() && - "Can't get assignment instructions for non-assign DPV!"); - return getAssignmentInsts(DPV->getAssignID()); +inline AssignmentInstRange getAssignmentInsts(const DbgVariableRecord *DVR) { + assert(DVR->isDbgAssign() && + "Can't get assignment instructions for non-assign DVR!"); + return getAssignmentInsts(DVR->getAssignID()); } // @@ -231,9 +234,10 @@ inline AssignmentMarkerRange getAssignmentMarkers(const Instruction *Inst) { return make_range(Value::user_iterator(), Value::user_iterator()); } -inline SmallVector<DPValue *> getDPVAssignmentMarkers(const Instruction *Inst) { +inline SmallVector<DbgVariableRecord *> +getDVRAssignmentMarkers(const Instruction *Inst) { if (auto *ID = Inst->getMetadata(LLVMContext::MD_DIAssignID)) - return cast<DIAssignID>(ID)->getAllDPValueUsers(); + return cast<DIAssignID>(ID)->getAllDbgVariableRecordUsers(); return {}; } @@ -261,7 +265,7 @@ bool calculateFragmentIntersect( std::optional<DIExpression::FragmentInfo> &Result); bool calculateFragmentIntersect( const DataLayout &DL, const Value *Dest, uint64_t SliceOffsetInBits, - uint64_t SliceSizeInBits, const DPValue *DPVAssign, + uint64_t SliceSizeInBits, const DbgVariableRecord *DVRAssign, std::optional<DIExpression::FragmentInfo> &Result); /// Helper struct for trackAssignments, below. We don't use the similar @@ -276,8 +280,8 @@ struct VarRecord { VarRecord(DbgVariableIntrinsic *DVI) : Var(DVI->getVariable()), DL(getDebugValueLoc(DVI)) {} - VarRecord(DPValue *DPV) - : Var(DPV->getVariable()), DL(getDebugValueLoc(DPV)) {} + VarRecord(DbgVariableRecord *DVR) + : Var(DVR->getVariable()), DL(getDebugValueLoc(DVR)) {} VarRecord(DILocalVariable *Var, DILocation *DL) : Var(Var), DL(DL) {} friend bool operator<(const VarRecord &LHS, const VarRecord &RHS) { return std::tie(LHS.Var, LHS.DL) < std::tie(RHS.Var, RHS.DL); diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index 156f6eb49253de78a68e91ff5fd0284e77928823..2805f6c4780578061e3bb5eee154383c1255af97 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -65,7 +65,7 @@ enum Tag : uint16_t; } class DbgVariableIntrinsic; -class DPValue; +class DbgVariableRecord; extern cl::opt<bool> EnableFSDiscriminator; @@ -323,8 +323,8 @@ public: // This node has no operands to replace. void replaceOperandWith(unsigned I, Metadata *New) = delete; - SmallVector<DPValue *> getAllDPValueUsers() { - return Context.getReplaceableUses()->getAllDPValueUsers(); + SmallVector<DbgVariableRecord *> getAllDbgVariableRecordUsers() { + return Context.getReplaceableUses()->getAllDbgVariableRecordUsers(); } static DIAssignID *getDistinct(LLVMContext &Context) { @@ -745,7 +745,7 @@ public: unsigned getLine() const { return Line; } uint64_t getSizeInBits() const { return SizeInBits; } - uint32_t getAlignInBits() const { return SubclassData32; } + uint32_t getAlignInBits() const; uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT; } uint64_t getOffsetInBits() const { return OffsetInBits; } DIFlags getFlags() const { return Flags; } @@ -972,6 +972,35 @@ public: /// /// TODO: Split out members (inheritance, fields, methods, etc.). class DIDerivedType : public DIType { +public: + /// Pointer authentication (__ptrauth) metadata. + struct PtrAuthData { + // RawData layout: + // - Bits 0..3: Key + // - Bit 4: IsAddressDiscriminated + // - Bits 5..20: ExtraDiscriminator + // - Bit 21: IsaPointer + // - Bit 22: AuthenticatesNullValues + unsigned RawData; + + PtrAuthData(unsigned FromRawData) : RawData(FromRawData) {} + PtrAuthData(unsigned Key, bool IsDiscr, unsigned Discriminator, + bool IsaPointer, bool AuthenticatesNullValues) { + assert(Key < 16); + assert(Discriminator <= 0xffff); + RawData = (Key << 0) | (IsDiscr ? (1 << 4) : 0) | (Discriminator << 5) | + (IsaPointer ? (1 << 21) : 0) | + (AuthenticatesNullValues ? (1 << 22) : 0); + } + + unsigned key() { return (RawData >> 0) & 0b1111; } + bool isAddressDiscriminated() { return (RawData >> 4) & 1; } + unsigned extraDiscriminator() { return (RawData >> 5) & 0xffff; } + bool isaPointer() { return (RawData >> 21) & 1; } + bool authenticatesNullValues() { return (RawData >> 22) & 1; } + }; + +private: friend class LLVMContextImpl; friend class MDNode; @@ -982,59 +1011,70 @@ class DIDerivedType : public DIType { DIDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag, unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, - std::optional<unsigned> DWARFAddressSpace, DIFlags Flags, + std::optional<unsigned> DWARFAddressSpace, + std::optional<PtrAuthData> PtrAuthData, DIFlags Flags, ArrayRef<Metadata *> Ops) : DIType(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags, Ops), - DWARFAddressSpace(DWARFAddressSpace) {} + DWARFAddressSpace(DWARFAddressSpace) { + if (PtrAuthData) + SubclassData32 = PtrAuthData->RawData; + } ~DIDerivedType() = default; static DIDerivedType * getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, DIFile *File, unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, - std::optional<unsigned> DWARFAddressSpace, DIFlags Flags, + std::optional<unsigned> DWARFAddressSpace, + std::optional<PtrAuthData> PtrAuthData, DIFlags Flags, Metadata *ExtraData, DINodeArray Annotations, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, - DWARFAddressSpace, Flags, ExtraData, Annotations.get(), - Storage, ShouldCreate); + DWARFAddressSpace, PtrAuthData, Flags, ExtraData, + Annotations.get(), Storage, ShouldCreate); } static DIDerivedType * getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, - std::optional<unsigned> DWARFAddressSpace, DIFlags Flags, + std::optional<unsigned> DWARFAddressSpace, + std::optional<PtrAuthData> PtrAuthData, DIFlags Flags, Metadata *ExtraData, Metadata *Annotations, StorageType Storage, bool ShouldCreate = true); TempDIDerivedType cloneImpl() const { - return getTemporary( - getContext(), getTag(), getName(), getFile(), getLine(), getScope(), - getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(), - getDWARFAddressSpace(), getFlags(), getExtraData(), getAnnotations()); + return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), + getScope(), getBaseType(), getSizeInBits(), + getAlignInBits(), getOffsetInBits(), + getDWARFAddressSpace(), getPtrAuthData(), getFlags(), + getExtraData(), getAnnotations()); } public: - DEFINE_MDNODE_GET( - DIDerivedType, - (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, - Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, - uint32_t AlignInBits, uint64_t OffsetInBits, - std::optional<unsigned> DWARFAddressSpace, DIFlags Flags, - Metadata *ExtraData = nullptr, Metadata *Annotations = nullptr), - (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, - OffsetInBits, DWARFAddressSpace, Flags, ExtraData, Annotations)) + DEFINE_MDNODE_GET(DIDerivedType, + (unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint32_t AlignInBits, + uint64_t OffsetInBits, + std::optional<unsigned> DWARFAddressSpace, + std::optional<PtrAuthData> PtrAuthData, DIFlags Flags, + Metadata *ExtraData = nullptr, + Metadata *Annotations = nullptr), + (Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, DWARFAddressSpace, PtrAuthData, + Flags, ExtraData, Annotations)) DEFINE_MDNODE_GET(DIDerivedType, (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, - std::optional<unsigned> DWARFAddressSpace, DIFlags Flags, + std::optional<unsigned> DWARFAddressSpace, + std::optional<PtrAuthData> PtrAuthData, DIFlags Flags, Metadata *ExtraData = nullptr, DINodeArray Annotations = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, - ExtraData, Annotations)) + AlignInBits, OffsetInBits, DWARFAddressSpace, PtrAuthData, + Flags, ExtraData, Annotations)) TempDIDerivedType clone() const { return cloneImpl(); } @@ -1048,6 +1088,8 @@ public: return DWARFAddressSpace; } + std::optional<PtrAuthData> getPtrAuthData() const; + /// Get extra data associated with this derived type. /// /// Class type for pointer-to-members, objective-c property node for ivars, @@ -1087,6 +1129,16 @@ public: } }; +inline bool operator==(DIDerivedType::PtrAuthData Lhs, + DIDerivedType::PtrAuthData Rhs) { + return Lhs.RawData == Rhs.RawData; +} + +inline bool operator!=(DIDerivedType::PtrAuthData Lhs, + DIDerivedType::PtrAuthData Rhs) { + return !(Lhs == Rhs); +} + /// Composite types. /// /// TODO: Detach from DerivedTypeBase (split out MDEnumType?). @@ -3788,8 +3840,8 @@ public: return MD->getMetadataID() == DIArgListKind; } - SmallVector<DPValue *> getAllDPValueUsers() { - return ReplaceableMetadataImpl::getAllDPValueUsers(); + SmallVector<DbgVariableRecord *> getAllDbgVariableRecordUsers() { + return ReplaceableMetadataImpl::getAllDbgVariableRecordUsers(); } void handleChangedOperand(void *Ref, Metadata *New); @@ -3819,7 +3871,7 @@ class DebugVariable { public: DebugVariable(const DbgVariableIntrinsic *DII); - DebugVariable(const DPValue *DPV); + DebugVariable(const DbgVariableRecord *DVR); DebugVariable(const DILocalVariable *Var, std::optional<FragmentInfo> FragmentInfo, diff --git a/llvm/include/llvm/IR/DebugProgramInstruction.h b/llvm/include/llvm/IR/DebugProgramInstruction.h index 507b652feeb016d45eb89ccce64bd3bd6c261845..c9477131c09ca8b7589624825ea0fa2d6e7ac101 100644 --- a/llvm/include/llvm/IR/DebugProgramInstruction.h +++ b/llvm/include/llvm/IR/DebugProgramInstruction.h @@ -1,4 +1,4 @@ -//===-- llvm/DebugProgramInstruction.h - Stream of debug info -------*- C++ -*-===// +//===-- llvm/DebugProgramInstruction.h - Stream of debug info ---*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -15,24 +15,25 @@ // %bar = void call @ext(%foo); // // and all information is stored in the Value / Metadata hierachy defined -// elsewhere in LLVM. In the "DPValue" design, each instruction /may/ have a -// connection with a DPMarker, which identifies a position immediately before the -// instruction, and each DPMarker /may/ then have connections to DPValues which -// record the variable assignment information. To illustrate: +// elsewhere in LLVM. In the "DbgRecord" design, each instruction /may/ have a +// connection with a DbgMarker, which identifies a position immediately before +// the instruction, and each DbgMarker /may/ then have connections to DbgRecords +// which record the variable assignment information. To illustrate: // // %foo = add i32 1, %0 -// ; foo->DbgMarker == nullptr +// ; foo->DebugMarker == nullptr // ;; There are no variable assignments / debug records "in front" of -// ;; the instruction for %foo, therefore it has no DbgMarker. +// ;; the instruction for %foo, therefore it has no DebugMarker. // %bar = void call @ext(%foo) -// ; bar->DbgMarker = { -// ; StoredDPValues = { -// ; DPValue(metadata i32 %foo, ...) +// ; bar->DebugMarker = { +// ; StoredDbgRecords = { +// ; DbgVariableRecord(metadata i32 %foo, ...) // ; } // ; } // ;; There is a debug-info record in front of the %bar instruction, -// ;; thus it points at a DPMarker object. That DPMarker contains a -// ;; DPValue in it's ilist, storing the equivalent information to the +// ;; thus it points at a DbgMarker object. That DbgMarker contains a +// ;; DbgVariableRecord in it's ilist, storing the equivalent information +// to the // ;; dbg.value above: the Value, DILocalVariable, etc. // // This structure separates the two concerns of the position of the debug-info @@ -65,8 +66,8 @@ class DbgVariableIntrinsic; class DbgInfoIntrinsic; class DbgLabelInst; class DIAssignID; -class DPMarker; -class DPValue; +class DbgMarker; +class DbgVariableRecord; class raw_ostream; /// A typed tracking MDNode reference that does not require a definition for its @@ -119,7 +120,7 @@ public: /// Base class for non-instruction debug metadata records that have positions /// within IR. Features various methods copied across from the Instruction /// class to aid ease-of-use. DbgRecords should always be linked into a -/// DPMarker's StoredDPValues list. The marker connects a DbgRecord back to +/// DbgMarker's StoredDbgRecords list. The marker connects a DbgRecord back to /// it's position in the BasicBlock. /// /// We need a discriminator for dyn/isa casts. In order to avoid paying for a @@ -133,7 +134,7 @@ public: class DbgRecord : public ilist_node<DbgRecord> { public: /// Marker that this DbgRecord is linked into. - DPMarker *Marker = nullptr; + DbgMarker *Marker = nullptr; /// Subclass discriminator. enum Kind : uint8_t { ValueKind, LabelKind }; @@ -165,10 +166,10 @@ public: Kind getRecordKind() const { return RecordKind; } - void setMarker(DPMarker *M) { Marker = M; } + void setMarker(DbgMarker *M) { Marker = M; } - DPMarker *getMarker() { return Marker; } - const DPMarker *getMarker() const { return Marker; } + DbgMarker *getMarker() { return Marker; } + const DbgMarker *getMarker() const { return Marker; } BasicBlock *getBlock(); const BasicBlock *getBlock() const; @@ -219,24 +220,25 @@ inline raw_ostream &operator<<(raw_ostream &OS, const DbgRecord &R) { /// Records a position in IR for a source label (DILabel). Corresponds to the /// llvm.dbg.label intrinsic. -/// FIXME: Rename DbgLabelRecord when DPValue is renamed to DbgVariableRecord. -class DPLabel : public DbgRecord { +class DbgLabelRecord : public DbgRecord { DbgRecordParamRef<DILabel> Label; /// This constructor intentionally left private, so that it is only called via - /// "createUnresolvedDPLabel", which clearly expresses that it is for parsing - /// only. - DPLabel(MDNode *Label, MDNode *DL); + /// "createUnresolvedDbgLabelRecord", which clearly expresses that it is for + /// parsing only. + DbgLabelRecord(MDNode *Label, MDNode *DL); public: - DPLabel(DILabel *Label, DebugLoc DL); + DbgLabelRecord(DILabel *Label, DebugLoc DL); - /// For use during parsing; creates a DPLabel from as-of-yet unresolved - /// MDNodes. Trying to access the resulting DPLabel's fields before they are - /// resolved, or if they resolve to the wrong type, will result in a crash. - static DPLabel *createUnresolvedDPLabel(MDNode *Label, MDNode *DL); + /// For use during parsing; creates a DbgLabelRecord from as-of-yet unresolved + /// MDNodes. Trying to access the resulting DbgLabelRecord's fields before + /// they are resolved, or if they resolve to the wrong type, will result in a + /// crash. + static DbgLabelRecord *createUnresolvedDbgLabelRecord(MDNode *Label, + MDNode *DL); - DPLabel *clone() const; + DbgLabelRecord *clone() const; void print(raw_ostream &O, bool IsForDebug = false) const; void print(raw_ostream &ROS, ModuleSlotTracker &MST, bool IsForDebug) const; DbgLabelInst *createDebugIntrinsic(Module *M, @@ -257,7 +259,7 @@ public: /// /// This class inherits from DebugValueUser to allow LLVM's metadata facilities /// to update our references to metadata beneath our feet. -class DPValue : public DbgRecord, protected DebugValueUser { +class DbgVariableRecord : public DbgRecord, protected DebugValueUser { friend class DebugValueUser; public: @@ -269,9 +271,10 @@ public: End, ///< Marks the end of the concrete types. Any, ///< To indicate all LocationTypes in searches. }; - /// Classification of the debug-info record that this DPValue represents. - /// Essentially, "is this a dbg.value or dbg.declare?". dbg.declares are not - /// currently supported, but it would be trivial to do so. + /// Classification of the debug-info record that this DbgVariableRecord + /// represents. Essentially, "is this a dbg.value or dbg.declare?". + /// dbg.declares are not currently supported, but it would be trivial to do + /// so. /// FIXME: We could use spare padding bits from DbgRecord for this. LocationType Type; @@ -284,63 +287,69 @@ public: DbgRecordParamRef<DIExpression> AddressExpression; public: - /// Create a new DPValue representing the intrinsic \p DVI, for example the - /// assignment represented by a dbg.value. - DPValue(const DbgVariableIntrinsic *DVI); - DPValue(const DPValue &DPV); - /// Directly construct a new DPValue representing a dbg.value intrinsic - /// assigning \p Location to the DV / Expr / DI variable. - DPValue(Metadata *Location, DILocalVariable *DV, DIExpression *Expr, - const DILocation *DI, LocationType Type = LocationType::Value); - DPValue(Metadata *Value, DILocalVariable *Variable, DIExpression *Expression, - DIAssignID *AssignID, Metadata *Address, - DIExpression *AddressExpression, const DILocation *DI); + /// Create a new DbgVariableRecord representing the intrinsic \p DVI, for + /// example the assignment represented by a dbg.value. + DbgVariableRecord(const DbgVariableIntrinsic *DVI); + DbgVariableRecord(const DbgVariableRecord &DVR); + /// Directly construct a new DbgVariableRecord representing a dbg.value + /// intrinsic assigning \p Location to the DV / Expr / DI variable. + DbgVariableRecord(Metadata *Location, DILocalVariable *DV, DIExpression *Expr, + const DILocation *DI, + LocationType Type = LocationType::Value); + DbgVariableRecord(Metadata *Value, DILocalVariable *Variable, + DIExpression *Expression, DIAssignID *AssignID, + Metadata *Address, DIExpression *AddressExpression, + const DILocation *DI); private: /// Private constructor for creating new instances during parsing only. Only - /// called through `createUnresolvedDPValue` below, which makes clear that - /// this is used for parsing only, and will later return a subclass depending - /// on which Type is passed. - DPValue(LocationType Type, Metadata *Val, MDNode *Variable, - MDNode *Expression, MDNode *AssignID, Metadata *Address, - MDNode *AddressExpression, MDNode *DI); + /// called through `createUnresolvedDbgVariableRecord` below, which makes + /// clear that this is used for parsing only, and will later return a subclass + /// depending on which Type is passed. + DbgVariableRecord(LocationType Type, Metadata *Val, MDNode *Variable, + MDNode *Expression, MDNode *AssignID, Metadata *Address, + MDNode *AddressExpression, MDNode *DI); public: - /// Used to create DPValues during parsing, where some metadata references may - /// still be unresolved. Although for some fields a generic `Metadata*` - /// argument is accepted for forward type-references, the verifier and - /// accessors will reject incorrect types later on. The function is used for - /// all types of DPValues for simplicity while parsing, but asserts if any - /// necessary fields are empty or unused fields are not empty, i.e. if the - /// #dbg_assign fields are used for a non-dbg-assign type. - static DPValue *createUnresolvedDPValue(LocationType Type, Metadata *Val, - MDNode *Variable, MDNode *Expression, - MDNode *AssignID, Metadata *Address, - MDNode *AddressExpression, - MDNode *DI); - - static DPValue *createDPVAssign(Value *Val, DILocalVariable *Variable, - DIExpression *Expression, - DIAssignID *AssignID, Value *Address, - DIExpression *AddressExpression, - const DILocation *DI); - static DPValue *createLinkedDPVAssign(Instruction *LinkedInstr, Value *Val, - DILocalVariable *Variable, - DIExpression *Expression, - Value *Address, - DIExpression *AddressExpression, - const DILocation *DI); - - static DPValue *createDPValue(Value *Location, DILocalVariable *DV, - DIExpression *Expr, const DILocation *DI); - static DPValue *createDPValue(Value *Location, DILocalVariable *DV, - DIExpression *Expr, const DILocation *DI, - DPValue &InsertBefore); - static DPValue *createDPVDeclare(Value *Address, DILocalVariable *DV, - DIExpression *Expr, const DILocation *DI); - static DPValue *createDPVDeclare(Value *Address, DILocalVariable *DV, - DIExpression *Expr, const DILocation *DI, - DPValue &InsertBefore); + /// Used to create DbgVariableRecords during parsing, where some metadata + /// references may still be unresolved. Although for some fields a generic + /// `Metadata*` argument is accepted for forward type-references, the verifier + /// and accessors will reject incorrect types later on. The function is used + /// for all types of DbgVariableRecords for simplicity while parsing, but + /// asserts if any necessary fields are empty or unused fields are not empty, + /// i.e. if the #dbg_assign fields are used for a non-dbg-assign type. + static DbgVariableRecord * + createUnresolvedDbgVariableRecord(LocationType Type, Metadata *Val, + MDNode *Variable, MDNode *Expression, + MDNode *AssignID, Metadata *Address, + MDNode *AddressExpression, MDNode *DI); + + static DbgVariableRecord * + createDVRAssign(Value *Val, DILocalVariable *Variable, + DIExpression *Expression, DIAssignID *AssignID, + Value *Address, DIExpression *AddressExpression, + const DILocation *DI); + static DbgVariableRecord * + createLinkedDVRAssign(Instruction *LinkedInstr, Value *Val, + DILocalVariable *Variable, DIExpression *Expression, + Value *Address, DIExpression *AddressExpression, + const DILocation *DI); + + static DbgVariableRecord *createDbgVariableRecord(Value *Location, + DILocalVariable *DV, + DIExpression *Expr, + const DILocation *DI); + static DbgVariableRecord * + createDbgVariableRecord(Value *Location, DILocalVariable *DV, + DIExpression *Expr, const DILocation *DI, + DbgVariableRecord &InsertBefore); + static DbgVariableRecord *createDVRDeclare(Value *Address, + DILocalVariable *DV, + DIExpression *Expr, + const DILocation *DI); + static DbgVariableRecord * + createDVRDeclare(Value *Address, DILocalVariable *DV, DIExpression *Expr, + const DILocation *DI, DbgVariableRecord &InsertBefore); /// Iterator for ValueAsMetadata that internally uses direct pointer iteration /// over either a ValueAsMetadata* or a ValueAsMetadata**, dereferencing to the @@ -412,7 +421,8 @@ public: unsigned getNumVariableLocationOps() const; bool hasArgList() const { return isa<DIArgList>(getRawLocation()); } - /// Returns true if this DPValue has no empty MDNodes in its location list. + /// Returns true if this DbgVariableRecord has no empty MDNodes in its + /// location list. bool hasValidLocation() const { return getVariableLocationOp(0) != nullptr; } /// Does this describe the address of a local variable. True for dbg.addr @@ -445,10 +455,10 @@ public: /// replaceVariableLocationOp and addVariableLocationOps should be used where /// possible to avoid creating invalid state. void setRawLocation(Metadata *NewLocation) { - assert( - (isa<ValueAsMetadata>(NewLocation) || isa<DIArgList>(NewLocation) || - isa<MDNode>(NewLocation)) && - "Location for a DPValue must be either ValueAsMetadata or DIArgList"); + assert((isa<ValueAsMetadata>(NewLocation) || isa<DIArgList>(NewLocation) || + isa<MDNode>(NewLocation)) && + "Location for a DbgVariableRecord must be either ValueAsMetadata or " + "DIArgList"); resetDebugValue(0, NewLocation); } @@ -456,12 +466,12 @@ public: /// is described. std::optional<uint64_t> getFragmentSizeInBits() const; - bool isEquivalentTo(const DPValue &Other) const { + bool isEquivalentTo(const DbgVariableRecord &Other) const { return DbgLoc == Other.DbgLoc && isIdenticalToWhenDefined(Other); } // Matches the definition of the Instruction version, equivalent to above but // without checking DbgLoc. - bool isIdenticalToWhenDefined(const DPValue &Other) const { + bool isIdenticalToWhenDefined(const DbgVariableRecord &Other) const { return std::tie(Type, DebugValues, Variable, Expression, AddressExpression) == std::tie(Other.Type, Other.DebugValues, Other.Variable, @@ -497,10 +507,10 @@ public: /// @} - DPValue *clone() const; - /// Convert this DPValue back into a dbg.value intrinsic. + DbgVariableRecord *clone() const; + /// Convert this DbgVariableRecord back into a dbg.value intrinsic. /// \p InsertBefore Optional position to insert this intrinsic. - /// \returns A new dbg.value intrinsic representiung this DPValue. + /// \returns A new dbg.value intrinsic representiung this DbgVariableRecord. DbgVariableIntrinsic *createDebugIntrinsic(Module *M, Instruction *InsertBefore) const; @@ -511,22 +521,23 @@ public: void print(raw_ostream &O, bool IsForDebug = false) const; void print(raw_ostream &ROS, ModuleSlotTracker &MST, bool IsForDebug) const; - /// Filter the DbgRecord range to DPValue types only and downcast. - static inline auto - filter(iterator_range<simple_ilist<DbgRecord>::iterator> R) { - return map_range( - make_filter_range(R, [](DbgRecord &E) { return isa<DPValue>(E); }), - [](DbgRecord &E) { return std::ref(cast<DPValue>(E)); }); - } - /// Support type inquiry through isa, cast, and dyn_cast. static bool classof(const DbgRecord *E) { return E->getRecordKind() == ValueKind; } }; +/// Filter the DbgRecord range to DbgVariableRecord types only and downcast. +static inline auto +filterDbgVars(iterator_range<simple_ilist<DbgRecord>::iterator> R) { + return map_range( + make_filter_range(R, + [](DbgRecord &E) { return isa<DbgVariableRecord>(E); }), + [](DbgRecord &E) { return std::ref(cast<DbgVariableRecord>(E)); }); +} + /// Per-instruction record of debug-info. If an Instruction is the position of -/// some debugging information, it points at a DPMarker storing that info. Each +/// some debugging information, it points at a DbgMarker storing that info. Each /// marker points back at the instruction that owns it. Various utilities are /// provided for manipulating the DbgRecords contained within this marker. /// @@ -546,9 +557,9 @@ public: /// which we can improve in the future. Additionally, many improvements in the /// way that debug-info is stored can be achieved in this class, at a future /// date. -class DPMarker { +class DbgMarker { public: - DPMarker() {} + DbgMarker() {} /// Link back to the Instruction that owns this marker. Can be null during /// operations that move a marker from one instruction to another. Instruction *MarkedInstr = nullptr; @@ -557,8 +568,8 @@ public: /// intrinsics. There is a one-to-one relationship between each debug /// intrinsic in a block and each DbgRecord once the representation has been /// converted, and the ordering is meaningful in the same way. - simple_ilist<DbgRecord> StoredDPValues; - bool empty() const { return StoredDPValues.empty(); } + simple_ilist<DbgRecord> StoredDbgRecords; + bool empty() const { return StoredDbgRecords.empty(); } const BasicBlock *getParent() const; BasicBlock *getParent(); @@ -572,77 +583,82 @@ public: void removeFromParent(); void eraseFromParent(); - /// Implement operator<< on DPMarker. + /// Implement operator<< on DbgMarker. void print(raw_ostream &O, bool IsForDebug = false) const; void print(raw_ostream &ROS, ModuleSlotTracker &MST, bool IsForDebug) const; - /// Produce a range over all the DPValues in this Marker. + /// Produce a range over all the DbgRecords in this Marker. iterator_range<simple_ilist<DbgRecord>::iterator> getDbgRecordRange(); iterator_range<simple_ilist<DbgRecord>::const_iterator> getDbgRecordRange() const; - /// Transfer any DPValues from \p Src into this DPMarker. If \p InsertAtHead - /// is true, place them before existing DPValues, otherwise afterwards. - void absorbDebugValues(DPMarker &Src, bool InsertAtHead); - /// Transfer the DPValues in \p Range from \p Src into this DPMarker. If - /// \p InsertAtHead is true, place them before existing DPValues, otherwise + /// Transfer any DbgRecords from \p Src into this DbgMarker. If \p + /// InsertAtHead is true, place them before existing DbgRecords, otherwise + /// afterwards. + void absorbDebugValues(DbgMarker &Src, bool InsertAtHead); + /// Transfer the DbgRecords in \p Range from \p Src into this DbgMarker. If + /// \p InsertAtHead is true, place them before existing DbgRecords, otherwise // afterwards. void absorbDebugValues(iterator_range<DbgRecord::self_iterator> Range, - DPMarker &Src, bool InsertAtHead); - /// Insert a DPValue into this DPMarker, at the end of the list. If + DbgMarker &Src, bool InsertAtHead); + /// Insert a DbgRecord into this DbgMarker, at the end of the list. If /// \p InsertAtHead is true, at the start. void insertDbgRecord(DbgRecord *New, bool InsertAtHead); - /// Insert a DPValue prior to a DPValue contained within this marker. + /// Insert a DbgRecord prior to a DbgRecord contained within this marker. void insertDbgRecord(DbgRecord *New, DbgRecord *InsertBefore); - /// Insert a DPValue after a DPValue contained within this marker. + /// Insert a DbgRecord after a DbgRecord contained within this marker. void insertDbgRecordAfter(DbgRecord *New, DbgRecord *InsertAfter); - /// Clone all DPMarkers from \p From into this marker. There are numerous + /// Clone all DbgMarkers from \p From into this marker. There are numerous /// options to customise the source/destination, due to gnarliness, see class /// comment. - /// \p FromHere If non-null, copy from FromHere to the end of From's DPValues - /// \p InsertAtHead Place the cloned DPValues at the start of StoredDPValues - /// \returns Range over all the newly cloned DPValues + /// \p FromHere If non-null, copy from FromHere to the end of From's + /// DbgRecords + /// \p InsertAtHead Place the cloned DbgRecords at the start of + /// StoredDbgRecords + /// \returns Range over all the newly cloned DbgRecords iterator_range<simple_ilist<DbgRecord>::iterator> - cloneDebugInfoFrom(DPMarker *From, + cloneDebugInfoFrom(DbgMarker *From, std::optional<simple_ilist<DbgRecord>::iterator> FromHere, bool InsertAtHead = false); - /// Erase all DPValues in this DPMarker. + /// Erase all DbgRecords in this DbgMarker. void dropDbgRecords(); /// Erase a single DbgRecord from this marker. In an ideal future, we would /// never erase an assignment in this way, but it's the equivalent to /// erasing a debug intrinsic from a block. void dropOneDbgRecord(DbgRecord *DR); - /// We generally act like all llvm Instructions have a range of DPValues - /// attached to them, but in reality sometimes we don't allocate the DPMarker - /// to save time and memory, but still have to return ranges of DPValues. When - /// we need to describe such an unallocated DPValue range, use this static - /// markers range instead. This will bite us if someone tries to insert a - /// DPValue in that range, but they should be using the Official (TM) API for - /// that. - static DPMarker EmptyDPMarker; + /// We generally act like all llvm Instructions have a range of DbgRecords + /// attached to them, but in reality sometimes we don't allocate the DbgMarker + /// to save time and memory, but still have to return ranges of DbgRecords. + /// When we need to describe such an unallocated DbgRecord range, use this + /// static markers range instead. This will bite us if someone tries to insert + /// a DbgRecord in that range, but they should be using the Official (TM) API + /// for that. + static DbgMarker EmptyDbgMarker; static iterator_range<simple_ilist<DbgRecord>::iterator> getEmptyDbgRecordRange() { - return make_range(EmptyDPMarker.StoredDPValues.end(), - EmptyDPMarker.StoredDPValues.end()); + return make_range(EmptyDbgMarker.StoredDbgRecords.end(), + EmptyDbgMarker.StoredDbgRecords.end()); } }; -inline raw_ostream &operator<<(raw_ostream &OS, const DPMarker &Marker) { +inline raw_ostream &operator<<(raw_ostream &OS, const DbgMarker &Marker) { Marker.print(OS); return OS; } -/// Inline helper to return a range of DPValues attached to a marker. It needs +/// Inline helper to return a range of DbgRecords attached to a marker. It needs /// to be inlined as it's frequently called, but also come after the declaration -/// of DPMarker. Thus: it's pre-declared by users like Instruction, then an +/// of DbgMarker. Thus: it's pre-declared by users like Instruction, then an /// inlineable body defined here. inline iterator_range<simple_ilist<DbgRecord>::iterator> -getDbgRecordRange(DPMarker *DbgMarker) { - if (!DbgMarker) - return DPMarker::getEmptyDbgRecordRange(); - return DbgMarker->getDbgRecordRange(); +getDbgRecordRange(DbgMarker *DebugMarker) { + if (!DebugMarker) + return DbgMarker::getEmptyDbgRecordRange(); + return DebugMarker->getDbgRecordRange(); } +DEFINE_ISA_CONVERSION_FUNCTIONS(DbgRecord, LLVMDbgRecordRef) + } // namespace llvm #endif // LLVM_IR_DEBUGPROGRAMINSTRUCTION_H diff --git a/llvm/include/llvm/IR/DiagnosticHandler.h b/llvm/include/llvm/IR/DiagnosticHandler.h index db7d7444f75f051f5a57a1a0fc4ebca42bf47179..1f0544b9fa9f8f3e59ad904594dfcde2c53d9c38 100644 --- a/llvm/include/llvm/IR/DiagnosticHandler.h +++ b/llvm/include/llvm/IR/DiagnosticHandler.h @@ -28,7 +28,7 @@ struct DiagnosticHandler { : DiagnosticContext(DiagContext) {} virtual ~DiagnosticHandler() = default; - using DiagnosticHandlerTy = void (*)(const DiagnosticInfo &DI, void *Context); + using DiagnosticHandlerTy = void (*)(const DiagnosticInfo *DI, void *Context); /// DiagHandlerCallback is settable from the C API and base implementation /// of DiagnosticHandler will call it from handleDiagnostics(). Any derived @@ -42,7 +42,7 @@ struct DiagnosticHandler { /// with a prefix based on the severity. virtual bool handleDiagnostics(const DiagnosticInfo &DI) { if (DiagHandlerCallback) { - DiagHandlerCallback(DI, DiagnosticContext); + DiagHandlerCallback(&DI, DiagnosticContext); return true; } return false; diff --git a/llvm/include/llvm/IR/GlobalValue.h b/llvm/include/llvm/IR/GlobalValue.h index aa8188cd99fee19652a2482d8f7baa1733f69fb7..c61d502aa332b080f72327476fb2dfb7aa5aeee0 100644 --- a/llvm/include/llvm/IR/GlobalValue.h +++ b/llvm/include/llvm/IR/GlobalValue.h @@ -360,6 +360,7 @@ public: // storage is shared between `G1` and `G2`. void setSanitizerMetadata(SanitizerMetadata Meta); void removeSanitizerMetadata(); + void setNoSanitizeMetadata(); bool isTagged() const { return hasSanitizerMetadata() && getSanitizerMetadata().Memtag; diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index f2922311097e9b236fb04274ee7d02c065b6bece..2e2ec9a1c8302677aabe040e794e35632f6905ef 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -221,6 +221,12 @@ public: AddOrRemoveMetadataToCopy(LLVMContext::MD_dbg, L.getAsMDNode()); } + /// Set nosanitize metadata. + void SetNoSanitizeMetadata() { + AddOrRemoveMetadataToCopy(llvm::LLVMContext::MD_nosanitize, + llvm::MDNode::get(getContext(), std::nullopt)); + } + /// Collect metadata with IDs \p MetadataKinds from \p Src which should be /// added to all created instructions. Entries present in MedataDataToCopy but /// not on \p Src will be dropped from MetadataToCopy. @@ -962,9 +968,9 @@ public: /// Create a call to intrinsic \p ID with 2 operands which is mangled on the /// first type. - CallInst *CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, - Instruction *FMFSource = nullptr, - const Twine &Name = ""); + Value *CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, + Instruction *FMFSource = nullptr, + const Twine &Name = ""); /// Create a call to intrinsic \p ID with \p Args, mangled using \p Types. If /// \p FMFSource is provided, copy fast-math-flags from that instruction to @@ -983,7 +989,7 @@ public: const Twine &Name = ""); /// Create call to the minnum intrinsic. - CallInst *CreateMinNum(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateMinNum(Value *LHS, Value *RHS, const Twine &Name = "") { if (IsFPConstrained) { return CreateConstrainedFPUnroundedBinOp( Intrinsic::experimental_constrained_minnum, LHS, RHS, nullptr, Name); @@ -993,7 +999,7 @@ public: } /// Create call to the maxnum intrinsic. - CallInst *CreateMaxNum(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateMaxNum(Value *LHS, Value *RHS, const Twine &Name = "") { if (IsFPConstrained) { return CreateConstrainedFPUnroundedBinOp( Intrinsic::experimental_constrained_maxnum, LHS, RHS, nullptr, Name); @@ -1003,19 +1009,19 @@ public: } /// Create call to the minimum intrinsic. - CallInst *CreateMinimum(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateMinimum(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateBinaryIntrinsic(Intrinsic::minimum, LHS, RHS, nullptr, Name); } /// Create call to the maximum intrinsic. - CallInst *CreateMaximum(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateMaximum(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateBinaryIntrinsic(Intrinsic::maximum, LHS, RHS, nullptr, Name); } /// Create call to the copysign intrinsic. - CallInst *CreateCopySign(Value *LHS, Value *RHS, - Instruction *FMFSource = nullptr, - const Twine &Name = "") { + Value *CreateCopySign(Value *LHS, Value *RHS, + Instruction *FMFSource = nullptr, + const Twine &Name = "") { return CreateBinaryIntrinsic(Intrinsic::copysign, LHS, RHS, FMFSource, Name); } @@ -1712,18 +1718,13 @@ public: const Twine &Name = "", MDNode *FPMathTag = nullptr, std::optional<fp::ExceptionBehavior> Except = std::nullopt); - Value *CreateNeg(Value *V, const Twine &Name = "", bool HasNUW = false, - bool HasNSW = false) { - return CreateSub(Constant::getNullValue(V->getType()), V, Name, HasNUW, - HasNSW); + Value *CreateNeg(Value *V, const Twine &Name = "", bool HasNSW = false) { + return CreateSub(Constant::getNullValue(V->getType()), V, Name, + /*HasNUW=*/0, HasNSW); } Value *CreateNSWNeg(Value *V, const Twine &Name = "") { - return CreateNeg(V, Name, false, true); - } - - Value *CreateNUWNeg(Value *V, const Twine &Name = "") { - return CreateNeg(V, Name, true, false); + return CreateNeg(V, Name, /*HasNSW=*/true); } Value *CreateFNeg(Value *V, const Twine &Name = "", @@ -2707,6 +2708,7 @@ public: IRBuilder(const IRBuilder &) = delete; InserterTy &getInserter() { return Inserter; } + const InserterTy &getInserter() const { return Inserter; } }; template <typename FolderTy, typename InserterTy> diff --git a/llvm/include/llvm/IR/IRBuilderFolder.h b/llvm/include/llvm/IR/IRBuilderFolder.h index bd2324dfc5f1ba8f5e0dd001c9b1f392f1b12350..3020f2684ee4579937905286b859cc3e8d19562c 100644 --- a/llvm/include/llvm/IR/IRBuilderFolder.h +++ b/llvm/include/llvm/IR/IRBuilderFolder.h @@ -73,6 +73,10 @@ public: virtual Value *FoldCast(Instruction::CastOps Op, Value *V, Type *DestTy) const = 0; + virtual Value * + FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty, + Instruction *FMFSource = nullptr) const = 0; + //===--------------------------------------------------------------------===// // Cast/Conversion Operators //===--------------------------------------------------------------------===// diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h index fed21b992e3d10ad8c6dd5c0ccf297cb9ea04aa7..e4e5fa15c399eb5aaf7aec2d637938d45d36202c 100644 --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -43,6 +43,7 @@ namespace llvm { class StringRef; class Type; class Value; +class ConstantRange; namespace Intrinsic { typedef unsigned ID; @@ -475,12 +476,6 @@ public: Instruction *InsertBefore = nullptr); static BinaryOperator *CreateNSWNeg(Value *Op, const Twine &Name, BasicBlock *InsertAtEnd); - static BinaryOperator *CreateNUWNeg(Value *Op, const Twine &Name, - BasicBlock::iterator InsertBefore); - static BinaryOperator *CreateNUWNeg(Value *Op, const Twine &Name = "", - Instruction *InsertBefore = nullptr); - static BinaryOperator *CreateNUWNeg(Value *Op, const Twine &Name, - BasicBlock *InsertAtEnd); static BinaryOperator *CreateNot(Value *Op, const Twine &Name, BasicBlock::iterator InsertBefore); static BinaryOperator *CreateNot(Value *Op, const Twine &Name = "", @@ -1037,7 +1032,7 @@ public: /// the two operands. Insert the instruction into a BasicBlock right before /// the specified instruction. /// Create a CmpInst - static CmpInst *Create(OtherOps Op, Predicate predicate, Value *S1, Value *S2, + static CmpInst *Create(OtherOps Op, Predicate Pred, Value *S1, Value *S2, const Twine &Name, BasicBlock::iterator InsertBefore); /// Construct a compare instruction, given the opcode, the predicate and @@ -1045,17 +1040,28 @@ public: /// instruction into a BasicBlock right before the specified instruction. /// The specified Instruction is allowed to be a dereferenced end iterator. /// Create a CmpInst - static CmpInst *Create(OtherOps Op, - Predicate predicate, Value *S1, - Value *S2, const Twine &Name = "", + static CmpInst *Create(OtherOps Op, Predicate Pred, Value *S1, Value *S2, + const Twine &Name = "", Instruction *InsertBefore = nullptr); /// Construct a compare instruction, given the opcode, the predicate and the /// two operands. Also automatically insert this instruction to the end of /// the BasicBlock specified. /// Create a CmpInst - static CmpInst *Create(OtherOps Op, Predicate predicate, Value *S1, - Value *S2, const Twine &Name, BasicBlock *InsertAtEnd); + static CmpInst *Create(OtherOps Op, Predicate Pred, Value *S1, Value *S2, + const Twine &Name, BasicBlock *InsertAtEnd); + + /// Construct a compare instruction, given the opcode, the predicate, + /// the two operands and the instruction to copy the flags from. Optionally + /// (if InstBefore is specified) insert the instruction into a BasicBlock + /// right before the specified instruction. The specified Instruction is + /// allowed to be a dereferenced end iterator. + /// Create a CmpInst + static CmpInst *CreateWithCopiedFlags(OtherOps Op, Predicate Pred, Value *S1, + Value *S2, + const Instruction *FlagsSource, + const Twine &Name = "", + Instruction *InsertBefore = nullptr); /// Get the opcode casted to the right type OtherOps getOpcode() const { @@ -1917,7 +1923,7 @@ public: // Look at the callee, if available. if (const Function *F = getCalledFunction()) - return F->getAttributes().getRetAttr(Kind); + return F->getRetAttribute(Kind); return Attribute(); } @@ -2154,6 +2160,10 @@ public: /// parameter. FPClassTest getParamNoFPClass(unsigned i) const; + /// If this return value has a range attribute, return the value range of the + /// argument. Otherwise, std::nullopt is returned. + std::optional<ConstantRange> getRange() const; + /// Return true if the return value is known to be not null. /// This may be because it has the nonnull attribute, or because at least /// one byte is dereferenceable and the pointer is in addrspace(0). diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h index 817abd6afbcae05a5fd10ce847cc866e3d4e2c3b..6e0874c5b04f29685a907fbbeb0682d61dff1436 100644 --- a/llvm/include/llvm/IR/Instruction.h +++ b/llvm/include/llvm/IR/Instruction.h @@ -29,19 +29,20 @@ namespace llvm { class BasicBlock; -class DPMarker; +class DbgMarker; class FastMathFlags; class MDNode; class Module; struct AAMDNodes; -class DPMarker; +class DbgMarker; class DbgRecord; template <> struct ilist_alloc_traits<Instruction> { static inline void deleteNode(Instruction *V); }; -iterator_range<simple_ilist<DbgRecord>::iterator> getDbgRecordRange(DPMarker *); +iterator_range<simple_ilist<DbgRecord>::iterator> +getDbgRecordRange(DbgMarker *); class Instruction : public User, public ilist_node_with_parent<Instruction, BasicBlock, @@ -60,51 +61,52 @@ public: /// Optional marker recording the position for debugging information that /// takes effect immediately before this instruction. Null unless there is /// debugging information present. - DPMarker *DbgMarker = nullptr; + DbgMarker *DebugMarker = nullptr; /// Clone any debug-info attached to \p From onto this instruction. Used to /// copy debugging information from one block to another, when copying entire - /// blocks. \see DebugProgramInstruction.h , because the ordering of DPValues - /// is still important, fine grain control of which instructions are moved and - /// where they go is necessary. + /// blocks. \see DebugProgramInstruction.h , because the ordering of + /// DbgRecords is still important, fine grain control of which instructions + /// are moved and where they go is necessary. /// \p From The instruction to clone debug-info from. - /// \p from_here Optional iterator to limit DPValues cloned to be a range from + /// \p from_here Optional iterator to limit DbgRecords cloned to be a range + /// from /// from_here to end(). - /// \p InsertAtHead Whether the cloned DPValues should be placed at the end - /// or the beginning of existing DPValues attached to this. - /// \returns A range over the newly cloned DPValues. + /// \p InsertAtHead Whether the cloned DbgRecords should be placed at the end + /// or the beginning of existing DbgRecords attached to this. + /// \returns A range over the newly cloned DbgRecords. iterator_range<simple_ilist<DbgRecord>::iterator> cloneDebugInfoFrom( const Instruction *From, std::optional<simple_ilist<DbgRecord>::iterator> FromHere = std::nullopt, bool InsertAtHead = false); - /// Return a range over the DPValues attached to this instruction. + /// Return a range over the DbgRecords attached to this instruction. iterator_range<simple_ilist<DbgRecord>::iterator> getDbgRecordRange() const { - return llvm::getDbgRecordRange(DbgMarker); + return llvm::getDbgRecordRange(DebugMarker); } - /// Return an iterator to the position of the "Next" DPValue after this + /// Return an iterator to the position of the "Next" DbgRecord after this /// instruction, or std::nullopt. This is the position to pass to /// BasicBlock::reinsertInstInDbgRecords when re-inserting an instruction. std::optional<simple_ilist<DbgRecord>::iterator> getDbgReinsertionPosition(); - /// Returns true if any DPValues are attached to this instruction. + /// Returns true if any DbgRecords are attached to this instruction. bool hasDbgRecords() const; - /// Transfer any DPValues on the position \p It onto this instruction, - /// by simply adopting the sequence of DPValues (which is efficient) if + /// Transfer any DbgRecords on the position \p It onto this instruction, + /// by simply adopting the sequence of DbgRecords (which is efficient) if /// possible, by merging two sequences otherwise. void adoptDbgRecords(BasicBlock *BB, InstListType::iterator It, bool InsertAtHead); - /// Erase any DPValues attached to this instruction. + /// Erase any DbgRecords attached to this instruction. void dropDbgRecords(); - /// Erase a single DPValue \p I that is attached to this instruction. + /// Erase a single DbgRecord \p I that is attached to this instruction. void dropOneDbgRecord(DbgRecord *I); /// Handle the debug-info implications of this instruction being removed. Any - /// attached DPValues need to "fall" down onto the next instruction. + /// attached DbgRecords need to "fall" down onto the next instruction. void handleMarkerRemoval(); protected: diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h index 4e4cf71a349d74159c5b5797e3a497e011b45aef..4ffa6349871baf0af7975c85a513c71edb0ca3be 100644 --- a/llvm/include/llvm/IR/Instructions.h +++ b/llvm/include/llvm/IR/Instructions.h @@ -5345,6 +5345,8 @@ protected: TruncInst *cloneImpl() const; public: + enum { AnyWrap = 0, NoUnsignedWrap = (1 << 0), NoSignedWrap = (1 << 1) }; + /// Constructor with insert-before-instruction semantics TruncInst( Value *S, ///< The value to be truncated @@ -5376,6 +5378,39 @@ public: static bool classof(const Value *V) { return isa<Instruction>(V) && classof(cast<Instruction>(V)); } + + void setHasNoUnsignedWrap(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~NoUnsignedWrap) | (B * NoUnsignedWrap); + } + void setHasNoSignedWrap(bool B) { + SubclassOptionalData = + (SubclassOptionalData & ~NoSignedWrap) | (B * NoSignedWrap); + } + + /// Test whether this operation is known to never + /// undergo unsigned overflow, aka the nuw property. + bool hasNoUnsignedWrap() const { + return SubclassOptionalData & NoUnsignedWrap; + } + + /// Test whether this operation is known to never + /// undergo signed overflow, aka the nsw property. + bool hasNoSignedWrap() const { + return (SubclassOptionalData & NoSignedWrap) != 0; + } + + /// Returns the no-wrap kind of the operation. + unsigned getNoWrapKind() const { + unsigned NoWrapKind = 0; + if (hasNoUnsignedWrap()) + NoWrapKind |= NoUnsignedWrap; + + if (hasNoSignedWrap()) + NoWrapKind |= NoSignedWrap; + + return NoWrapKind; + } }; //===----------------------------------------------------------------------===// diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h index c07b83a81a63e13eb7a4f79700e22ec40c31416e..4f22720f1c558d9a27cc90b402ef592de528b3a3 100644 --- a/llvm/include/llvm/IR/IntrinsicInst.h +++ b/llvm/include/llvm/IR/IntrinsicInst.h @@ -1782,6 +1782,19 @@ public: static bool classof(const Value *V) { return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); } + + // Returns the convergence intrinsic referenced by |I|'s convergencectrl + // attribute if any. + static IntrinsicInst *getParentConvergenceToken(Instruction *I) { + auto *CI = dyn_cast<llvm::CallInst>(I); + if (!CI) + return nullptr; + + auto Bundle = CI->getOperandBundle(llvm::LLVMContext::OB_convergencectrl); + assert(Bundle->Inputs.size() == 1 && + Bundle->Inputs[0]->getType()->isTokenTy()); + return dyn_cast<llvm::IntrinsicInst>(Bundle->Inputs[0].get()); + } }; } // end namespace llvm diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index 5829957ecb6d739a0e7da6562d05a8bd915a8369..c04f4c52692158ae0568a418134f00b6f2b272bf 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -700,10 +700,13 @@ class MSBuiltin<string name> { //===--------------- Variable Argument Handling Intrinsics ----------------===// // -def int_vastart : DefaultAttrsIntrinsic<[], [llvm_ptr_ty], [], "llvm.va_start">; -def int_vacopy : DefaultAttrsIntrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], [], - "llvm.va_copy">; -def int_vaend : DefaultAttrsIntrinsic<[], [llvm_ptr_ty], [], "llvm.va_end">; +def int_vastart : DefaultAttrsIntrinsic<[], + [llvm_anyptr_ty], [], "llvm.va_start">; +def int_vacopy : DefaultAttrsIntrinsic<[], + [llvm_anyptr_ty, LLVMMatchType<0>], [], + "llvm.va_copy">; +def int_vaend : DefaultAttrsIntrinsic<[], + [llvm_anyptr_ty], [], "llvm.va_end">; //===------------------- Garbage Collection Intrinsics --------------------===// // @@ -1528,6 +1531,12 @@ def int_umax : DefaultAttrsIntrinsic< def int_umin : DefaultAttrsIntrinsic< [llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; +def int_scmp : DefaultAttrsIntrinsic< + [llvm_anyint_ty], [llvm_anyint_ty, LLVMMatchType<1>], + [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; +def int_ucmp : DefaultAttrsIntrinsic< + [llvm_anyint_ty], [llvm_anyint_ty, LLVMMatchType<1>], + [IntrNoMem, IntrSpeculatable, IntrWillReturn]>; //===------------------------- Memory Use Markers -------------------------===// // @@ -1584,11 +1593,11 @@ def int_experimental_patchpoint_void : Intrinsic<[], llvm_ptr_ty, llvm_i32_ty, llvm_vararg_ty], [Throws]>; -def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty], - [llvm_i64_ty, llvm_i32_ty, - llvm_ptr_ty, llvm_i32_ty, - llvm_vararg_ty], - [Throws]>; +def int_experimental_patchpoint : Intrinsic<[llvm_any_ty], + [llvm_i64_ty, llvm_i32_ty, + llvm_ptr_ty, llvm_i32_ty, + llvm_vararg_ty], + [Throws]>; //===------------------------ Garbage Collection Intrinsics ---------------===// @@ -1722,10 +1731,15 @@ def int_debugtrap : Intrinsic<[]>, def int_ubsantrap : Intrinsic<[], [llvm_i8_ty], [IntrNoReturn, IntrCold, ImmArg<ArgIndex<0>>]>; -// Return true if profile counter for containing block is hot. -def int_experimental_hot : Intrinsic<[llvm_i1_ty], [], - [IntrInaccessibleMemOnly, IntrWriteMem, - IntrWillReturn, NoUndef<RetIndex>]>; +// Return true if ubsan check is allowed. +def int_allow_ubsan_check : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_i8_ty], + [IntrInaccessibleMemOnly, IntrWriteMem, ImmArg<ArgIndex<0>>, NoUndef<RetIndex>]>, + ClangBuiltin<"__builtin_allow_ubsan_check">; + +// Return true if runtime check is allowed. +def int_allow_runtime_check : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_metadata_ty], + [IntrInaccessibleMemOnly, IntrWriteMem, NoUndef<RetIndex>]>, + ClangBuiltin<"__builtin_allow_runtime_check">; // Support for dynamic deoptimization (or de-specialization) def int_experimental_deoptimize : Intrinsic<[llvm_any_ty], [llvm_vararg_ty], diff --git a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td index 051e603c0819d201258e71b0a6e2f7e480bb20c8..6bbc13f1de86e2ecf10dfe2aa76ff3ab6254b0a8 100644 --- a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td +++ b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td @@ -851,16 +851,19 @@ class AMDGPUImageDimIntrinsic<AMDGPUDimProfile P_, list<SDNodeProperty> sdnodeprops> : Intrinsic< P_.RetTypes, // vdata(VGPR) -- for load/atomic-with-return !listconcat( - !foreach(arg, P_.DataArgs, arg.Type), // vdata(VGPR) -- for store/atomic - !if(P_.IsAtomic, [], [llvm_i32_ty]), // dmask(imm) - P_.AddrTypes, // vaddr(VGPR) - [llvm_v8i32_ty], // rsrc(SGPR) - !if(P_.IsSample, [llvm_v4i32_ty, // samp(SGPR) - llvm_i1_ty], []), // unorm(imm) - [llvm_i32_ty, // texfailctrl(imm; bit 0 = tfe, bit 1 = lwe) - llvm_i32_ty]), // cachepolicy(imm; bit 0 = glc, bit 1 = slc, bit 2 = dlc; - // gfx12+ imm: bits [0-2] = th, bits [3-4] = scope) - + !foreach(arg, P_.DataArgs, arg.Type), // vdata(VGPR) -- for store/atomic + !if(P_.IsAtomic, [], [llvm_i32_ty]), // dmask(imm) + P_.AddrTypes, // vaddr(VGPR) + [llvm_v8i32_ty], // rsrc(SGPR) + !if(P_.IsSample, [llvm_v4i32_ty, // samp(SGPR) + llvm_i1_ty], []), // unorm(imm) + [llvm_i32_ty, // texfailctrl(imm; bit 0 = tfe, bit 1 = lwe) + llvm_i32_ty]), // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, + // bit 2 = dlc (gfx10/gfx11), + // bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope !listconcat(props, [IntrNoCallback, IntrNoFree, IntrWillReturn], !if(P_.IsAtomic, [], [ImmArg<ArgIndex<AMDGPUImageDimIntrinsicEval<P_>.DmaskArgIndex>>]), !if(P_.IsSample, [ImmArg<ArgIndex<AMDGPUImageDimIntrinsicEval<P_>.UnormArgIndex>>], []), @@ -1085,11 +1088,15 @@ def int_amdgcn_buffer_load : AMDGPUBufferLoad; // the offset argument is uniform. def int_amdgcn_s_buffer_load : DefaultAttrsIntrinsic < [llvm_any_ty], - [llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // byte offset - llvm_i32_ty], // cachepolicy(imm; bit 0 = glc, bit 1 = slc, bit 2 = dlc; - // gfx12+ imm: bits [0-2] = th, bits [3-4] = scope) - // Note: volatile bit is **not** permitted here. + [llvm_v4i32_ty, // rsrc(SGPR) + llvm_i32_ty, // byte offset + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // Note: volatile bit is **not** permitted here. [IntrNoMem, ImmArg<ArgIndex<2>>]>, AMDGPURsrcIntrinsic<0>; @@ -1123,19 +1130,16 @@ def int_amdgcn_buffer_store : AMDGPUBufferStore; // operation is volatile. class AMDGPURawBufferLoad<LLVMType data_ty = llvm_any_ty> : DefaultAttrsIntrinsic < [data_ty], - [llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11), - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - // all: - // volatile op (bit 31, stripped at lowering)) + [llvm_v4i32_ty, // rsrc(SGPR) + llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) + llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrReadMem, ImmArg<ArgIndex<3>>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<0>; def int_amdgcn_raw_buffer_load_format : AMDGPURawBufferLoad<llvm_anyfloat_ty>; @@ -1143,20 +1147,16 @@ def int_amdgcn_raw_buffer_load : AMDGPURawBufferLoad; class AMDGPURawPtrBufferLoad<LLVMType data_ty = llvm_any_ty> : DefaultAttrsIntrinsic < [data_ty], - [AMDGPUBufferRsrcTy, // rsrc(SGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11), - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - // all: - // volatile op (bit 31, stripped at lowering)) - + [AMDGPUBufferRsrcTy, // rsrc(SGPR) + llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) + llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrArgMemOnly, IntrReadMem, ReadOnly<ArgIndex<0>>, NoCapture<ArgIndex<0>>, ImmArg<ArgIndex<3>>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<0>; @@ -1165,20 +1165,17 @@ def int_amdgcn_raw_ptr_buffer_load : AMDGPURawPtrBufferLoad; class AMDGPUStructBufferLoad<LLVMType data_ty = llvm_any_ty> : DefaultAttrsIntrinsic < [data_ty], - [llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11), - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - // all: - // volatile op (bit 31, stripped at lowering)) + [llvm_v4i32_ty, // rsrc(SGPR) + llvm_i32_ty, // vindex(VGPR) + llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) + llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrReadMem, ImmArg<ArgIndex<4>>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<0>; def int_amdgcn_struct_buffer_load_format : AMDGPUStructBufferLoad; @@ -1186,20 +1183,17 @@ def int_amdgcn_struct_buffer_load : AMDGPUStructBufferLoad; class AMDGPUStructPtrBufferLoad<LLVMType data_ty = llvm_any_ty> : DefaultAttrsIntrinsic < [data_ty], - [AMDGPUBufferRsrcTy, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11), - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - // all: - // volatile op (bit 31, stripped at lowering)) + [AMDGPUBufferRsrcTy, // rsrc(SGPR) + llvm_i32_ty, // vindex(VGPR) + llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) + llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrArgMemOnly, IntrReadMem, ReadOnly<ArgIndex<0>>, NoCapture<ArgIndex<0>>, ImmArg<ArgIndex<4>>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<0>; @@ -1208,20 +1202,17 @@ def int_amdgcn_struct_ptr_buffer_load : AMDGPUStructPtrBufferLoad; class AMDGPURawBufferStore<LLVMType data_ty = llvm_any_ty> : DefaultAttrsIntrinsic < [], - [data_ty, // vdata(VGPR) - llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11), - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - // all: - // volatile op (bit 31, stripped at lowering)) + [data_ty, // vdata(VGPR) + llvm_v4i32_ty, // rsrc(SGPR) + llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) + llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrWriteMem, ImmArg<ArgIndex<4>>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<1>; def int_amdgcn_raw_buffer_store_format : AMDGPURawBufferStore<llvm_anyfloat_ty>; @@ -1229,20 +1220,17 @@ def int_amdgcn_raw_buffer_store : AMDGPURawBufferStore; class AMDGPURawPtrBufferStore<LLVMType data_ty = llvm_any_ty> : DefaultAttrsIntrinsic < [], - [data_ty, // vdata(VGPR) - AMDGPUBufferRsrcTy, // rsrc(SGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11), - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - // all: - // volatile op (bit 31, stripped at lowering)) + [data_ty, // vdata(VGPR) + AMDGPUBufferRsrcTy, // rsrc(SGPR) + llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) + llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrArgMemOnly, IntrWriteMem, WriteOnly<ArgIndex<1>>, NoCapture<ArgIndex<1>>, ImmArg<ArgIndex<4>>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<1>; @@ -1251,21 +1239,18 @@ def int_amdgcn_raw_ptr_buffer_store : AMDGPURawPtrBufferStore; class AMDGPUStructBufferStore<LLVMType data_ty = llvm_any_ty> : DefaultAttrsIntrinsic < [], - [data_ty, // vdata(VGPR) - llvm_v4i32_ty, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11), - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - // all: - // volatile op (bit 31, stripped at lowering)) + [data_ty, // vdata(VGPR) + llvm_v4i32_ty, // rsrc(SGPR) + llvm_i32_ty, // vindex(VGPR) + llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) + llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrWriteMem, ImmArg<ArgIndex<5>>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<1>; def int_amdgcn_struct_buffer_store_format : AMDGPUStructBufferStore; @@ -1273,21 +1258,18 @@ def int_amdgcn_struct_buffer_store : AMDGPUStructBufferStore; class AMDGPUStructPtrBufferStore<LLVMType data_ty = llvm_any_ty> : DefaultAttrsIntrinsic < [], - [data_ty, // vdata(VGPR) - AMDGPUBufferRsrcTy, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11), - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - // all: - // volatile op (bit 31, stripped at lowering)) + [data_ty, // vdata(VGPR) + AMDGPUBufferRsrcTy, // rsrc(SGPR) + llvm_i32_ty, // vindex(VGPR) + llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) + llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrArgMemOnly, IntrWriteMem, WriteOnly<ArgIndex<1>>, NoCapture<ArgIndex<1>>, ImmArg<ArgIndex<5>>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<1>; @@ -1540,33 +1522,29 @@ def int_amdgcn_raw_tbuffer_load : DefaultAttrsIntrinsic < llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11), - // swizzled buffer (bit 3 = swz)) - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz [IntrReadMem, ImmArg<ArgIndex<3>>, ImmArg<ArgIndex<4>>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<0>; def int_amdgcn_raw_ptr_tbuffer_load : DefaultAttrsIntrinsic < - [llvm_any_ty], // overloaded for types f32/i32, v2f32/v2i32, v4f32/v4i32 + [llvm_any_ty], // overloaded for types f32/i32, v2f32/v2i32, v4f32/v4i32 [AMDGPUBufferRsrcTy, // rsrc(SGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds` checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11), - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz) - // volatile op (bit 31, stripped at lowering)) + llvm_i32_ty, // offset(VGPR/imm, included in bounds` checking and swizzling) + llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) + llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrArgMemOnly, IntrReadMem, ReadOnly<ArgIndex<0>>, NoCapture<ArgIndex<0>>, ImmArg<ArgIndex<3>>, ImmArg<ArgIndex<4>>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<0>; @@ -1578,16 +1556,13 @@ def int_amdgcn_raw_tbuffer_store : DefaultAttrsIntrinsic < llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11), - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - // all: - // volatile op (bit 31, stripped at lowering)) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrWriteMem, ImmArg<ArgIndex<4>>, ImmArg<ArgIndex<5>>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<1>; @@ -1599,16 +1574,13 @@ def int_amdgcn_raw_ptr_tbuffer_store : DefaultAttrsIntrinsic < llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11), - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - // all: - // volatile op (bit 31, stripped at lowering)) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrArgMemOnly, IntrWriteMem, WriteOnly<ArgIndex<1>>, NoCapture<ArgIndex<1>>, ImmArg<ArgIndex<4>>, ImmArg<ArgIndex<5>>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<1>; @@ -1620,59 +1592,50 @@ def int_amdgcn_struct_tbuffer_load : DefaultAttrsIntrinsic < llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11), - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - // all: - // volatile op (bit 31, stripped at lowering)) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrReadMem, ImmArg<ArgIndex<4>>, ImmArg<ArgIndex<5>>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<0>; def int_amdgcn_struct_ptr_tbuffer_load : DefaultAttrsIntrinsic < - [llvm_any_ty], // overloaded for types f32/i32, v2f32/v2i32, v4f32/v4i32 + [llvm_any_ty], // overloaded for types f32/i32, v2f32/v2i32, v4f32/v4i32 [AMDGPUBufferRsrcTy, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11), - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - // all: - // volatile op (bit 31, stripped at lowering)) + llvm_i32_ty, // vindex(VGPR) + llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) + llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) + llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrArgMemOnly, IntrReadMem, ReadOnly<ArgIndex<0>>, NoCapture<ArgIndex<0>>, ImmArg<ArgIndex<4>>, ImmArg<ArgIndex<5>>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<0>; def int_amdgcn_struct_ptr_tbuffer_store : DefaultAttrsIntrinsic < [], - [llvm_any_ty, // vdata(VGPR), overloaded for types f32/i32, v2f32/v2i32, v4f32/v4i32 + [llvm_any_ty, // vdata(VGPR), overloaded for types f32/i32, v2f32/v2i32, v4f32/v4i32 AMDGPUBufferRsrcTy, // rsrc(SGPR) - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11), - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - // all: - // volatile op (bit 31, stripped at lowering)) + llvm_i32_ty, // vindex(VGPR) + llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) + llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) + llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrArgMemOnly, IntrWriteMem, WriteOnly<ArgIndex<1>>, NoCapture<ArgIndex<1>>, ImmArg<ArgIndex<5>>, ImmArg<ArgIndex<6>>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<1>; @@ -1685,16 +1648,13 @@ def int_amdgcn_struct_tbuffer_store : DefaultAttrsIntrinsic < llvm_i32_ty, // offset(VGPR/imm, included in bounds checking and swizzling) llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) llvm_i32_ty, // format(imm; bits 3..0 = dfmt, bits 6..4 = nfmt) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11), - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - // all: - // volatile op (bit 31, stripped at lowering)) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrWriteMem, ImmArg<ArgIndex<5>>, ImmArg<ArgIndex<6>>], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<1>; @@ -1746,44 +1706,38 @@ def int_amdgcn_buffer_atomic_fadd : AMDGPUBufferAtomicFP; class AMDGPURawBufferLoadLDS : Intrinsic < [], - [llvm_v4i32_ty, // rsrc(SGPR) - LLVMQualPointerType<3>, // LDS base offset - llvm_i32_ty, // Data byte size: 1/2/4 - llvm_i32_ty, // voffset(VGPR, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty, // imm offset(imm, included in bounds checking and swizzling) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11)) - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - // all: - // volatile op (bit 31, stripped at lowering)) + [llvm_v4i32_ty, // rsrc(SGPR) + LLVMQualPointerType<3>, // LDS base offset + llvm_i32_ty, // Data byte size: 1/2/4 + llvm_i32_ty, // voffset(VGPR, included in bounds checking and swizzling) + llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) + llvm_i32_ty, // imm offset(imm, included in bounds checking and swizzling) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrWillReturn, NoCapture<ArgIndex<1>>, ImmArg<ArgIndex<2>>, ImmArg<ArgIndex<5>>, ImmArg<ArgIndex<6>>, IntrNoCallback, IntrNoFree], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<0>; def int_amdgcn_raw_buffer_load_lds : AMDGPURawBufferLoadLDS; class AMDGPURawPtrBufferLoadLDS : Intrinsic < [], - [AMDGPUBufferRsrcTy, // rsrc(SGPR) - LLVMQualPointerType<3>, // LDS base offset - llvm_i32_ty, // Data byte size: 1/2/4 - llvm_i32_ty, // voffset(VGPR, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty, // imm offset(imm, included in bounds checking and swizzling) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11)) - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - // all: - // volatile op (bit 31, stripped at lowering)) + [AMDGPUBufferRsrcTy, // rsrc(SGPR) + LLVMQualPointerType<3>, // LDS base offset + llvm_i32_ty, // Data byte size: 1/2/4 + llvm_i32_ty, // voffset(VGPR, included in bounds checking and swizzling) + llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) + llvm_i32_ty, // imm offset(imm, included in bounds checking and swizzling) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrWillReturn, IntrArgMemOnly, ReadOnly<ArgIndex<0>>, NoCapture<ArgIndex<0>>, WriteOnly<ArgIndex<1>>, NoCapture<ArgIndex<1>>, @@ -1793,46 +1747,40 @@ def int_amdgcn_raw_ptr_buffer_load_lds : AMDGPURawPtrBufferLoadLDS; class AMDGPUStructBufferLoadLDS : Intrinsic < [], - [llvm_v4i32_ty, // rsrc(SGPR) - LLVMQualPointerType<3>, // LDS base offset - llvm_i32_ty, // Data byte size: 1/2/4 - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // voffset(VGPR, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty, // imm offset(imm, included in bounds checking and swizzling) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11)) - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - // all: - // volatile op (bit 31, stripped at lowering)) + [llvm_v4i32_ty, // rsrc(SGPR) + LLVMQualPointerType<3>, // LDS base offset + llvm_i32_ty, // Data byte size: 1/2/4 + llvm_i32_ty, // vindex(VGPR) + llvm_i32_ty, // voffset(VGPR, included in bounds checking and swizzling) + llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) + llvm_i32_ty, // imm offset(imm, included in bounds checking and swizzling) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrWillReturn, NoCapture<ArgIndex<1>>, ImmArg<ArgIndex<2>>, ImmArg<ArgIndex<6>>, ImmArg<ArgIndex<7>>, IntrNoCallback, IntrNoFree], "", [SDNPMemOperand]>, AMDGPURsrcIntrinsic<0>; def int_amdgcn_struct_buffer_load_lds : AMDGPUStructBufferLoadLDS; class AMDGPUStructPtrBufferLoadLDS : Intrinsic < [], - [AMDGPUBufferRsrcTy, // rsrc(SGPR) - LLVMQualPointerType<3> , // LDS base offset - llvm_i32_ty, // Data byte size: 1/2/4 - llvm_i32_ty, // vindex(VGPR) - llvm_i32_ty, // voffset(VGPR, included in bounds checking and swizzling) - llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) - llvm_i32_ty, // imm offset(imm, included in bounds checking and swizzling) - llvm_i32_ty], // auxiliary data (imm, cachepolicy (bit 0 = glc, - // bit 1 = slc, - // bit 2 = dlc on gfx10/gfx11)) - // swizzled buffer (bit 3 = swz), - // gfx12+: - // cachepolicy (bits [0-2] = th, - // bits [3-4] = scope) - // swizzled buffer (bit 6 = swz), - // all: - // volatile op (bit 31, stripped at lowering)) + [AMDGPUBufferRsrcTy, // rsrc(SGPR) + LLVMQualPointerType<3>, // LDS base offset + llvm_i32_ty, // Data byte size: 1/2/4 + llvm_i32_ty, // vindex(VGPR) + llvm_i32_ty, // voffset(VGPR, included in bounds checking and swizzling) + llvm_i32_ty, // soffset(SGPR/imm, excluded from bounds checking and swizzling) + llvm_i32_ty, // imm offset(imm, included in bounds checking and swizzling) + llvm_i32_ty], // auxiliary/cachepolicy(imm): + // bit 0 = glc, bit 1 = slc, bit 2 = dlc (gfx10/gfx11), + // bit 3 = swz, bit 4 = scc (gfx90a) + // gfx940: bit 0 = sc0, bit 1 = nt, bit 3 = swz, bit 4 = sc1 + // gfx12+: bits [0-2] = th, bits [3-4] = scope, + // bit 6 = swz + // all: volatile op (bit 31, stripped at lowering) [IntrWillReturn, IntrArgMemOnly, ReadOnly<ArgIndex<0>>, NoCapture<ArgIndex<0>>, WriteOnly<ArgIndex<1>>, NoCapture<ArgIndex<1>>, @@ -2066,6 +2014,24 @@ def int_amdgcn_interp_inreg_p2_f16 : [IntrNoMem, IntrSpeculatable, ImmArg<ArgIndex<3>>]>; +// llvm.amdgcn.interp.p10.rtz.f16 <p>, <i>, <p0>, <high> +// gfx11+ fp16 interpolation intrinsic, with round-toward-zero rounding mode. +// high selects whether high or low 16-bits are used for p and p0 operands +def int_amdgcn_interp_p10_rtz_f16: + DefaultAttrsIntrinsic<[llvm_float_ty], + [llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_i1_ty], + [IntrNoMem, IntrSpeculatable, + ImmArg<ArgIndex<3>>]>; + +// llvm.amdgcn.interp.p2.rtz.f16 <p>, <j>, <tmp>, <high> +// gfx11+ fp16 interpolation intrinsic, with round-toward-zero rounding mode. +// high selects whether high or low 16-bits are used for p operand +def int_amdgcn_interp_p2_rtz_f16 : + DefaultAttrsIntrinsic<[llvm_half_ty], + [llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_i1_ty], + [IntrNoMem, IntrSpeculatable, + ImmArg<ArgIndex<3>>]>; + // Deprecated: use llvm.amdgcn.live.mask instead. def int_amdgcn_ps_live : DefaultAttrsIntrinsic < [llvm_i1_ty], @@ -2653,6 +2619,8 @@ class AMDGPUWmmaIntrinsicIU<LLVMType AB, LLVMType CD> : // The OPSEL intrinsics read from and write to one half of the registers, selected by the op_sel bit. // The tied versions of the f16/bf16 wmma intrinsics tie the destination matrix registers to the input accumulator registers. // The content of the other 16-bit half is preserved from the input. + +defset list<Intrinsic> AMDGPUWMMAIntrinsicsGFX11 = { def int_amdgcn_wmma_f16_16x16x16_f16_tied : AMDGPUWmmaIntrinsicOPSEL<llvm_anyfloat_ty, llvm_anyfloat_ty>; def int_amdgcn_wmma_bf16_16x16x16_bf16_tied : AMDGPUWmmaIntrinsicOPSEL<llvm_anyint_ty, llvm_anyint_ty>; @@ -2668,6 +2636,7 @@ def int_amdgcn_wmma_i32_16x16x16_iu4 : AMDGPUWmmaIntrinsicIU<llvm_anyint_ty, l // GFX12: The op_sel bit must be 0. def int_amdgcn_wmma_f16_16x16x16_f16 : AMDGPUWmmaIntrinsicOPSEL<llvm_anyfloat_ty, llvm_anyfloat_ty>; def int_amdgcn_wmma_bf16_16x16x16_bf16 : AMDGPUWmmaIntrinsicOPSEL<llvm_anyint_ty, llvm_anyint_ty>; +} //===----------------------------------------------------------------------===// // GFX12 Intrinsics @@ -2687,20 +2656,6 @@ def int_amdgcn_permlanex16_var : ClangBuiltin<"__builtin_amdgcn_permlanex16_var" [IntrNoMem, IntrConvergent, IntrWillReturn, ImmArg<ArgIndex<3>>, ImmArg<ArgIndex<4>>, IntrNoCallback, IntrNoFree]>; - -// WMMA (Wave Matrix Multiply-Accumulate) intrinsics -// -// These operations perform a matrix multiplication and accumulation of -// the form: D = A * B + C . - -// A and B are <8 x fp8> or <8 x bf8>, but since fp8 and bf8 are not supported by llvm we use <2 x i32>. -def int_amdgcn_wmma_f32_16x16x16_fp8_fp8 : AMDGPUWmmaIntrinsic<llvm_anyint_ty, llvm_anyfloat_ty>; -def int_amdgcn_wmma_f32_16x16x16_fp8_bf8 : AMDGPUWmmaIntrinsic<llvm_anyint_ty, llvm_anyfloat_ty>; -def int_amdgcn_wmma_f32_16x16x16_bf8_fp8 : AMDGPUWmmaIntrinsic<llvm_anyint_ty, llvm_anyfloat_ty>; -def int_amdgcn_wmma_f32_16x16x16_bf8_bf8 : AMDGPUWmmaIntrinsic<llvm_anyint_ty, llvm_anyfloat_ty>; -// A and B are <16 x iu4>. -def int_amdgcn_wmma_i32_16x16x32_iu4 : AMDGPUWmmaIntrinsicIU<llvm_anyint_ty, llvm_anyint_ty>; - // SWMMAC (Wave Matrix(sparse) Multiply-Accumulate) intrinsics // // These operations perform a sparse matrix multiplication and accumulation of @@ -2734,6 +2689,20 @@ class AMDGPUSWmmacIntrinsicIUIdx<LLVMType A, LLVMType B, LLVMType CD, LLVMType I [IntrNoMem, IntrConvergent, IntrWillReturn, ImmArg<ArgIndex<0>>, ImmArg<ArgIndex<2>>, ImmArg<ArgIndex<6>>] >; +defset list<Intrinsic> AMDGPUWMMAIntrinsicsGFX12 = { +// WMMA (Wave Matrix Multiply-Accumulate) intrinsics +// +// These operations perform a matrix multiplication and accumulation of +// the form: D = A * B + C . + +// A and B are <8 x fp8> or <8 x bf8>, but since fp8 and bf8 are not supported by llvm we use <2 x i32>. +def int_amdgcn_wmma_f32_16x16x16_fp8_fp8 : AMDGPUWmmaIntrinsic<llvm_anyint_ty, llvm_anyfloat_ty>; +def int_amdgcn_wmma_f32_16x16x16_fp8_bf8 : AMDGPUWmmaIntrinsic<llvm_anyint_ty, llvm_anyfloat_ty>; +def int_amdgcn_wmma_f32_16x16x16_bf8_fp8 : AMDGPUWmmaIntrinsic<llvm_anyint_ty, llvm_anyfloat_ty>; +def int_amdgcn_wmma_f32_16x16x16_bf8_bf8 : AMDGPUWmmaIntrinsic<llvm_anyint_ty, llvm_anyfloat_ty>; +// A and B are <16 x iu4>. +def int_amdgcn_wmma_i32_16x16x32_iu4 : AMDGPUWmmaIntrinsicIU<llvm_anyint_ty, llvm_anyint_ty>; + def int_amdgcn_swmmac_f32_16x16x32_f16 : AMDGPUSWmmacIntrinsicIdx<llvm_anyfloat_ty, llvm_anyfloat_ty, llvm_anyfloat_ty, llvm_anyint_ty>; def int_amdgcn_swmmac_f32_16x16x32_bf16 : AMDGPUSWmmacIntrinsicIdx<llvm_anyint_ty, llvm_anyint_ty, llvm_anyfloat_ty, llvm_anyint_ty>; def int_amdgcn_swmmac_f16_16x16x32_f16 : AMDGPUSWmmacIntrinsicIdx<llvm_anyfloat_ty, llvm_anyfloat_ty, llvm_anyfloat_ty, llvm_anyint_ty>; @@ -2745,6 +2714,7 @@ def int_amdgcn_swmmac_f32_16x16x32_fp8_fp8 : AMDGPUSWmmacIntrinsicIdx<llvm_anyin def int_amdgcn_swmmac_f32_16x16x32_fp8_bf8 : AMDGPUSWmmacIntrinsicIdx<llvm_anyint_ty, llvm_anyint_ty, llvm_anyfloat_ty, llvm_anyint_ty>; def int_amdgcn_swmmac_f32_16x16x32_bf8_fp8 : AMDGPUSWmmacIntrinsicIdx<llvm_anyint_ty, llvm_anyint_ty, llvm_anyfloat_ty, llvm_anyint_ty>; def int_amdgcn_swmmac_f32_16x16x32_bf8_bf8 : AMDGPUSWmmacIntrinsicIdx<llvm_anyint_ty, llvm_anyint_ty, llvm_anyfloat_ty, llvm_anyint_ty>; +} def int_amdgcn_global_atomic_ordered_add_b64 : AMDGPUAtomicRtn<llvm_i64_ty, global_ptr_ty>; @@ -2765,17 +2735,14 @@ class AMDGPULoadIntrinsic<LLVMType ptr_ty>: >; // Wave32 -// <2 x i32> @llvm.amdgcn.global.load.tr.v2i32(ptr addrspace(1)) -> global_load_tr_b64 -// <8 x i16> @llvm.amdgcn.global.load.tr.v8i16(ptr addrspace(1)) -> global_load_tr_b128 -// <8 x half> @llvm.amdgcn.global.load.tr.v8f16(ptr addrspace(1)) -> global_load_tr_b128 -// <8 x bfloat> @llvm.amdgcn.global.load.tr.v8bf16(ptr addrspace(1)) -> global_load_tr_b128 +// <2 x i32> @llvm.amdgcn.global.load.tr.b64.v2i32(ptr addrspace(1)) -> global_load_tr_b64 +// <8 x i16> @llvm.amdgcn.global.load.tr.b128.v8i16(ptr addrspace(1)) -> global_load_tr_b128 // Wave64 -// i32 @llvm.amdgcn.global.load.tr.i32(ptr addrspace(1)) -> global_load_tr_b64 -// <4 x i16> @llvm.amdgcn.global.load.tr.v4i16(ptr addrspace(1)) -> global_load_tr_b128 -// <4 x half> @llvm.amdgcn.global.load.tr.v4f16(ptr addrspace(1)) -> global_load_tr_b128 -// <4 x bfloat> @llvm.amdgcn.global.load.tr.v4bf16(ptr addrspace(1)) -> global_load_tr_b128 +// i32 @llvm.amdgcn.global.load.tr.b64.i32(ptr addrspace(1)) -> global_load_tr_b64 +// <4 x i16> @llvm.amdgcn.global.load.tr.b128.v4i16(ptr addrspace(1)) -> global_load_tr_b128 -def int_amdgcn_global_load_tr : AMDGPULoadIntrinsic<global_ptr_ty>; +def int_amdgcn_global_load_tr_b64 : AMDGPULoadIntrinsic<global_ptr_ty>; +def int_amdgcn_global_load_tr_b128 : AMDGPULoadIntrinsic<global_ptr_ty>; // i32 @llvm.amdgcn.wave.id() def int_amdgcn_wave_id : @@ -3012,6 +2979,7 @@ class AMDGPUMfmaIntrinsic<LLVMType DestTy, LLVMType SrcABTy> : [IntrConvergent, IntrNoMem, ImmArg<ArgIndex<3>>, ImmArg<ArgIndex<4>>, ImmArg<ArgIndex<5>>]>; +defset list<Intrinsic> AMDGPUMFMAIntrinsics908 = { def int_amdgcn_mfma_f32_32x32x1f32 : AMDGPUMfmaIntrinsic<llvm_v32f32_ty, llvm_float_ty>; def int_amdgcn_mfma_f32_16x16x1f32 : AMDGPUMfmaIntrinsic<llvm_v16f32_ty, llvm_float_ty>; def int_amdgcn_mfma_f32_4x4x1f32 : AMDGPUMfmaIntrinsic<llvm_v4f32_ty, llvm_float_ty>; @@ -3032,6 +3000,7 @@ def int_amdgcn_mfma_f32_16x16x2bf16 : AMDGPUMfmaIntrinsic<llvm_v16f32_ty, llvm_v def int_amdgcn_mfma_f32_4x4x2bf16 : AMDGPUMfmaIntrinsic<llvm_v4f32_ty, llvm_v2i16_ty>; def int_amdgcn_mfma_f32_32x32x4bf16 : AMDGPUMfmaIntrinsic<llvm_v16f32_ty, llvm_v2i16_ty>; def int_amdgcn_mfma_f32_16x16x8bf16 : AMDGPUMfmaIntrinsic<llvm_v4f32_ty, llvm_v2i16_ty>; +} //===----------------------------------------------------------------------===// // gfx90a intrinsics @@ -3043,6 +3012,7 @@ def int_amdgcn_flat_atomic_fadd : AMDGPUAtomicRtn<llvm_anyfloat_ty>; def int_amdgcn_flat_atomic_fmin : AMDGPUAtomicRtn<llvm_anyfloat_ty>; def int_amdgcn_flat_atomic_fmax : AMDGPUAtomicRtn<llvm_anyfloat_ty>; +defset list<Intrinsic> AMDGPUMFMAIntrinsics90A = { def int_amdgcn_mfma_f32_32x32x4bf16_1k : AMDGPUMfmaIntrinsic<llvm_v32f32_ty, llvm_v4i16_ty>; def int_amdgcn_mfma_f32_16x16x4bf16_1k : AMDGPUMfmaIntrinsic<llvm_v16f32_ty, llvm_v4i16_ty>; def int_amdgcn_mfma_f32_4x4x4bf16_1k : AMDGPUMfmaIntrinsic<llvm_v4f32_ty, llvm_v4i16_ty>; @@ -3054,25 +3024,12 @@ def int_amdgcn_mfma_f32_16x16x16bf16_1k : AMDGPUMfmaIntrinsic<llvm_v4f32_ty, ll // source operand. def int_amdgcn_mfma_f64_16x16x4f64 : AMDGPUMfmaIntrinsic<llvm_v4f64_ty, llvm_double_ty>; def int_amdgcn_mfma_f64_4x4x4f64 : AMDGPUMfmaIntrinsic<llvm_double_ty, llvm_double_ty>; +} //===----------------------------------------------------------------------===// // gfx940 intrinsics // ===----------------------------------------------------------------------===// -// bf16 atomics use v2i16 argument since there is no bf16 data type in the llvm. -def int_amdgcn_global_atomic_fadd_v2bf16 : AMDGPUAtomicRtn<llvm_v2i16_ty>; -def int_amdgcn_flat_atomic_fadd_v2bf16 : AMDGPUAtomicRtn<llvm_v2i16_ty>; -def int_amdgcn_ds_fadd_v2bf16 : DefaultAttrsIntrinsic< - [llvm_v2i16_ty], - [LLVMQualPointerType<3>, llvm_v2i16_ty], - [IntrArgMemOnly, NoCapture<ArgIndex<0>>]>, - ClangBuiltin<"__builtin_amdgcn_ds_atomic_fadd_v2bf16">; - -def int_amdgcn_mfma_i32_16x16x32_i8 : AMDGPUMfmaIntrinsic<llvm_v4i32_ty, llvm_i64_ty>; -def int_amdgcn_mfma_i32_32x32x16_i8 : AMDGPUMfmaIntrinsic<llvm_v16i32_ty, llvm_i64_ty>; -def int_amdgcn_mfma_f32_16x16x8_xf32 : AMDGPUMfmaIntrinsic<llvm_v4f32_ty, llvm_v2f32_ty>; -def int_amdgcn_mfma_f32_32x32x4_xf32 : AMDGPUMfmaIntrinsic<llvm_v16f32_ty, llvm_v2f32_ty>; - class AMDGPUMFp8MfmaIntrinsic<LLVMType DestTy> : AMDGPUMfmaIntrinsic<DestTy, llvm_i64_ty>; @@ -3081,9 +3038,6 @@ multiclass AMDGPUMFp8MfmaIntrinsic<LLVMType DestTy> { def NAME#"_"#kind : AMDGPUMFp8MfmaIntrinsic<DestTy>; } -defm int_amdgcn_mfma_f32_16x16x32 : AMDGPUMFp8MfmaIntrinsic<llvm_v4f32_ty>; -defm int_amdgcn_mfma_f32_32x32x16 : AMDGPUMFp8MfmaIntrinsic<llvm_v16f32_ty>; - // llvm.amdgcn.smfmac.?32.* vdst, srcA, srcB, srcC, index, cbsz, abid class AMDGPUMSmfmacIntrinsic<LLVMType DestTy, LLVMType SrcA, LLVMType SrcB> : ClangBuiltin<!subst("int", "__builtin", NAME)>, @@ -3093,13 +3047,6 @@ class AMDGPUMSmfmacIntrinsic<LLVMType DestTy, LLVMType SrcA, LLVMType SrcB> : [IntrConvergent, IntrNoMem, ImmArg<ArgIndex<4>>, ImmArg<ArgIndex<5>>]>; -def int_amdgcn_smfmac_f32_16x16x32_f16 : AMDGPUMSmfmacIntrinsic<llvm_v4f32_ty, llvm_v4f16_ty, llvm_v8f16_ty>; -def int_amdgcn_smfmac_f32_32x32x16_f16 : AMDGPUMSmfmacIntrinsic<llvm_v16f32_ty, llvm_v4f16_ty, llvm_v8f16_ty>; -def int_amdgcn_smfmac_f32_16x16x32_bf16 : AMDGPUMSmfmacIntrinsic<llvm_v4f32_ty, llvm_v4i16_ty, llvm_v8i16_ty>; -def int_amdgcn_smfmac_f32_32x32x16_bf16 : AMDGPUMSmfmacIntrinsic<llvm_v16f32_ty, llvm_v4i16_ty, llvm_v8i16_ty>; -def int_amdgcn_smfmac_i32_16x16x64_i8 : AMDGPUMSmfmacIntrinsic<llvm_v4i32_ty, llvm_v2i32_ty, llvm_v4i32_ty>; -def int_amdgcn_smfmac_i32_32x32x32_i8 : AMDGPUMSmfmacIntrinsic<llvm_v16i32_ty, llvm_v2i32_ty, llvm_v4i32_ty>; - class AMDGPUMFp8SmfmacIntrinsic<LLVMType DestTy> : AMDGPUMSmfmacIntrinsic<DestTy, llvm_v2i32_ty, llvm_v4i32_ty>; @@ -3108,8 +3055,34 @@ multiclass AMDGPUMFp8SmfmacIntrinsic<LLVMType DestTy> { def NAME#"_"#kind : AMDGPUMFp8SmfmacIntrinsic<DestTy>; } +// bf16 atomics use v2i16 argument since there is no bf16 data type in the llvm. +def int_amdgcn_global_atomic_fadd_v2bf16 : AMDGPUAtomicRtn<llvm_v2i16_ty>; +def int_amdgcn_flat_atomic_fadd_v2bf16 : AMDGPUAtomicRtn<llvm_v2i16_ty>; +def int_amdgcn_ds_fadd_v2bf16 : DefaultAttrsIntrinsic< + [llvm_v2i16_ty], + [LLVMQualPointerType<3>, llvm_v2i16_ty], + [IntrArgMemOnly, NoCapture<ArgIndex<0>>]>, + ClangBuiltin<"__builtin_amdgcn_ds_atomic_fadd_v2bf16">; + +defset list<Intrinsic> AMDGPUMFMAIntrinsics940 = { +def int_amdgcn_mfma_i32_16x16x32_i8 : AMDGPUMfmaIntrinsic<llvm_v4i32_ty, llvm_i64_ty>; +def int_amdgcn_mfma_i32_32x32x16_i8 : AMDGPUMfmaIntrinsic<llvm_v16i32_ty, llvm_i64_ty>; +def int_amdgcn_mfma_f32_16x16x8_xf32 : AMDGPUMfmaIntrinsic<llvm_v4f32_ty, llvm_v2f32_ty>; +def int_amdgcn_mfma_f32_32x32x4_xf32 : AMDGPUMfmaIntrinsic<llvm_v16f32_ty, llvm_v2f32_ty>; + +defm int_amdgcn_mfma_f32_16x16x32 : AMDGPUMFp8MfmaIntrinsic<llvm_v4f32_ty>; +defm int_amdgcn_mfma_f32_32x32x16 : AMDGPUMFp8MfmaIntrinsic<llvm_v16f32_ty>; + +def int_amdgcn_smfmac_f32_16x16x32_f16 : AMDGPUMSmfmacIntrinsic<llvm_v4f32_ty, llvm_v4f16_ty, llvm_v8f16_ty>; +def int_amdgcn_smfmac_f32_32x32x16_f16 : AMDGPUMSmfmacIntrinsic<llvm_v16f32_ty, llvm_v4f16_ty, llvm_v8f16_ty>; +def int_amdgcn_smfmac_f32_16x16x32_bf16 : AMDGPUMSmfmacIntrinsic<llvm_v4f32_ty, llvm_v4i16_ty, llvm_v8i16_ty>; +def int_amdgcn_smfmac_f32_32x32x16_bf16 : AMDGPUMSmfmacIntrinsic<llvm_v16f32_ty, llvm_v4i16_ty, llvm_v8i16_ty>; +def int_amdgcn_smfmac_i32_16x16x64_i8 : AMDGPUMSmfmacIntrinsic<llvm_v4i32_ty, llvm_v2i32_ty, llvm_v4i32_ty>; +def int_amdgcn_smfmac_i32_32x32x32_i8 : AMDGPUMSmfmacIntrinsic<llvm_v16i32_ty, llvm_v2i32_ty, llvm_v4i32_ty>; + defm int_amdgcn_smfmac_f32_16x16x64 : AMDGPUMFp8SmfmacIntrinsic<llvm_v4f32_ty>; defm int_amdgcn_smfmac_f32_32x32x32 : AMDGPUMFp8SmfmacIntrinsic<llvm_v16f32_ty>; +} // llvm.amdgcn.cvt.f32.bf8 float vdst, int srcA, imm byte_sel [0..3] // byte_sel selects byte from srcA. diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td index 7229292e377a8337d3994a0fc40cc966ad3e76fd..a871fac46b9fd5d77b411a19fd17e721ad83813d 100644 --- a/llvm/include/llvm/IR/IntrinsicsDirectX.td +++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td @@ -21,20 +21,41 @@ def int_dx_create_handle : ClangBuiltin<"__builtin_hlsl_create_handle">, Intrinsic<[ llvm_ptr_ty ], [llvm_i8_ty], [IntrWillReturn]>; def int_dx_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty]>; +def int_dx_clamp : DefaultAttrsIntrinsic<[llvm_any_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; +def int_dx_uclamp : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; -def int_dx_dot : +def int_dx_dot2 : Intrinsic<[LLVMVectorElementType<0>], - [llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>], + [llvm_anyfloat_ty, LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>], + [IntrNoMem, IntrWillReturn, Commutative] >; +def int_dx_dot3 : + Intrinsic<[LLVMVectorElementType<0>], + [llvm_anyfloat_ty, LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>], + [IntrNoMem, IntrWillReturn, Commutative] >; +def int_dx_dot4 : + Intrinsic<[LLVMVectorElementType<0>], + [llvm_anyfloat_ty, LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>], + [IntrNoMem, IntrWillReturn, Commutative] >; +def int_dx_sdot : + Intrinsic<[LLVMVectorElementType<0>], + [llvm_anyint_ty, LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>], + [IntrNoMem, IntrWillReturn, Commutative] >; +def int_dx_udot : + Intrinsic<[LLVMVectorElementType<0>], + [llvm_anyint_ty, LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>], [IntrNoMem, IntrWillReturn, Commutative] >; def int_dx_frac : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; -def int_dx_lerp : - Intrinsic<[LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>], - [llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>,LLVMScalarOrSameVectorWidth<0, LLVMVectorElementType<0>>], +def int_dx_isinf : + DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], + [llvm_anyfloat_ty]>; + +def int_dx_lerp : Intrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>], [IntrNoMem, IntrWillReturn] >; def int_dx_imad : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; def int_dx_umad : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; def int_dx_rcp : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; +def int_dx_rsqrt : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; } diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index 766b3b542a9e06352f296d3054c3c4836e5db8f4..0eb09b1699aff4e64de6c14a5b433b561e2f5984 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -40,6 +40,18 @@ let TargetPrefix = "spv" in { def int_spv_assume : Intrinsic<[], [llvm_i1_ty]>; def int_spv_expect : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; + // Memory Use Markers + def int_spv_lifetime_start : Intrinsic<[], + [llvm_i64_ty, llvm_anyptr_ty], + [IntrArgMemOnly, IntrWillReturn, + NoCapture<ArgIndex<1>>, + ImmArg<ArgIndex<0>>]>; + def int_spv_lifetime_end : Intrinsic<[], + [llvm_i64_ty, llvm_anyptr_ty], + [IntrArgMemOnly, IntrWillReturn, + NoCapture<ArgIndex<1>>, + ImmArg<ArgIndex<0>>]>; + // The following intrinsic(s) are mirrored from IntrinsicsDirectX.td for HLSL support. def int_spv_thread_id : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem, IntrWillReturn]>; def int_spv_create_handle : ClangBuiltin<"__builtin_hlsl_create_handle">, diff --git a/llvm/include/llvm/IR/Mangler.h b/llvm/include/llvm/IR/Mangler.h index 747a4085235c9b8818973a3e8a3a83101552b9a2..f28ffc961b6db06de4d7cbfb6a0f48ec349e575e 100644 --- a/llvm/include/llvm/IR/Mangler.h +++ b/llvm/include/llvm/IR/Mangler.h @@ -14,6 +14,7 @@ #define LLVM_IR_MANGLER_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" namespace llvm { @@ -52,6 +53,9 @@ void emitLinkerFlagsForGlobalCOFF(raw_ostream &OS, const GlobalValue *GV, void emitLinkerFlagsForUsedCOFF(raw_ostream &OS, const GlobalValue *GV, const Triple &T, Mangler &M); +std::optional<std::string> getArm64ECMangledFunctionName(StringRef Name); +std::optional<std::string> getArm64ECDemangledFunctionName(StringRef Name); + } // End llvm namespace #endif diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h index da6744fdd091669b0299e6a1c2eaedfbd83483d3..22da54a1f03c594d99b75448aa4b12f91c54dc72 100644 --- a/llvm/include/llvm/IR/Metadata.h +++ b/llvm/include/llvm/IR/Metadata.h @@ -43,7 +43,7 @@ namespace llvm { class Module; class ModuleSlotTracker; class raw_ostream; -class DPValue; +class DbgVariableRecord; template <typename T> class StringMapEntry; template <typename ValueTy> class StringMapEntryStorage; class Type; @@ -205,23 +205,23 @@ private: /// Base class for tracking ValueAsMetadata/DIArgLists with user lookups and /// Owner callbacks outside of ValueAsMetadata. /// -/// Currently only inherited by DPValue; if other classes need to use it, then -/// a SubclassID will need to be added (either as a new field or by making -/// DebugValue into a PointerIntUnion) to discriminate between the subclasses in -/// lookup and callback handling. +/// Currently only inherited by DbgVariableRecord; if other classes need to use +/// it, then a SubclassID will need to be added (either as a new field or by +/// making DebugValue into a PointerIntUnion) to discriminate between the +/// subclasses in lookup and callback handling. class DebugValueUser { protected: // Capacity to store 3 debug values. // TODO: Not all DebugValueUser instances need all 3 elements, if we - // restructure the DPValue class then we can template parameterize this array - // size. + // restructure the DbgVariableRecord class then we can template parameterize + // this array size. std::array<Metadata *, 3> DebugValues; ArrayRef<Metadata *> getDebugValues() const { return DebugValues; } public: - DPValue *getUser(); - const DPValue *getUser() const; + DbgVariableRecord *getUser(); + const DbgVariableRecord *getUser() const; /// To be called by ReplaceableMetadataImpl::replaceAllUsesWith, where `Old` /// is a pointer to one of the pointers in `DebugValues` (so should be type /// Metadata**), and `NewDebugValue` is the new Metadata* that is replacing @@ -407,8 +407,8 @@ public: static void SalvageDebugInfo(const Constant &C); /// Returns the list of all DIArgList users of this. SmallVector<Metadata *> getAllArgListUsers(); - /// Returns the list of all DPValue users of this. - SmallVector<DPValue *> getAllDPValueUsers(); + /// Returns the list of all DbgVariableRecord users of this. + SmallVector<DbgVariableRecord *> getAllDbgVariableRecordUsers(); /// Resolve all uses of this. /// @@ -494,8 +494,8 @@ public: SmallVector<Metadata *> getAllArgListUsers() { return ReplaceableMetadataImpl::getAllArgListUsers(); } - SmallVector<DPValue *> getAllDPValueUsers() { - return ReplaceableMetadataImpl::getAllDPValueUsers(); + SmallVector<DbgVariableRecord *> getAllDbgVariableRecordUsers() { + return ReplaceableMetadataImpl::getAllDbgVariableRecordUsers(); } static void handleDeletion(Value *V); diff --git a/llvm/include/llvm/IR/NoFolder.h b/llvm/include/llvm/IR/NoFolder.h index a612f98465aeaa86a993cdf0cabd06d92dead68c..7bb5d5e696e9ead772d2fb62ba70d3800460207f 100644 --- a/llvm/include/llvm/IR/NoFolder.h +++ b/llvm/include/llvm/IR/NoFolder.h @@ -112,6 +112,11 @@ public: return nullptr; } + Value *FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty, + Instruction *FMFSource) const override { + return nullptr; + } + //===--------------------------------------------------------------------===// // Cast/Conversion Operators //===--------------------------------------------------------------------===// diff --git a/llvm/include/llvm/IR/Operator.h b/llvm/include/llvm/IR/Operator.h index e5264983390109d87b742f9e720eae41b4d154ee..e14a916b474935afe354746d233c08810438a50c 100644 --- a/llvm/include/llvm/IR/Operator.h +++ b/llvm/include/llvm/IR/Operator.h @@ -404,7 +404,6 @@ class GEPOperator enum { IsInBounds = (1 << 0), - // InRangeIndex: bits 1-6 }; void setIsInBounds(bool B) { @@ -423,11 +422,7 @@ public: /// Returns the offset of the index with an inrange attachment, or /// std::nullopt if none. - std::optional<unsigned> getInRangeIndex() const { - if (SubclassOptionalData >> 1 == 0) - return std::nullopt; - return (SubclassOptionalData >> 1) - 1; - } + std::optional<ConstantRange> getInRange() const; inline op_iterator idx_begin() { return op_begin()+1; } inline const_op_iterator idx_begin() const { return op_begin()+1; } diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h index c03d49c3b7b978ab1465a9c0502ccfe6cf7df899..108465478d3779359fa4a91a44667e60a1a02ef8 100644 --- a/llvm/include/llvm/IR/PassManager.h +++ b/llvm/include/llvm/IR/PassManager.h @@ -227,7 +227,7 @@ public: detail::getAnalysisResult<PassInstrumentationAnalysis>( AM, IR, std::tuple<ExtraArgTs...>(ExtraArgs...)); - // RemoveDIs: if requested, convert debug-info to DPValue representation + // RemoveDIs: if requested, convert debug-info to DbgRecord representation // for duration of these passes. bool ShouldConvertDbgInfo = shouldConvertDbgInfo(IR); if (ShouldConvertDbgInfo) @@ -267,29 +267,24 @@ public: return PA; } - template <typename PassT> - LLVM_ATTRIBUTE_MINSIZE - std::enable_if_t<!std::is_same<PassT, PassManager>::value> - addPass(PassT &&Pass) { + // FIXME: Revert to enable_if style when gcc >= 11.1 + template <typename PassT> LLVM_ATTRIBUTE_MINSIZE void addPass(PassT &&Pass) { using PassModelT = detail::PassModel<IRUnitT, PassT, AnalysisManagerT, ExtraArgTs...>; - // Do not use make_unique or emplace_back, they cause too many template - // instantiations, causing terrible compile times. - Passes.push_back(std::unique_ptr<PassConceptT>( - new PassModelT(std::forward<PassT>(Pass)))); - } - - /// When adding a pass manager pass that has the same type as this pass - /// manager, simply move the passes over. This is because we don't have use - /// cases rely on executing nested pass managers. Doing this could reduce - /// implementation complexity and avoid potential invalidation issues that may - /// happen with nested pass managers of the same type. - template <typename PassT> - LLVM_ATTRIBUTE_MINSIZE - std::enable_if_t<std::is_same<PassT, PassManager>::value> - addPass(PassT &&Pass) { - for (auto &P : Pass.Passes) - Passes.push_back(std::move(P)); + if constexpr (!std::is_same_v<PassT, PassManager>) { + // Do not use make_unique or emplace_back, they cause too many template + // instantiations, causing terrible compile times. + Passes.push_back(std::unique_ptr<PassConceptT>( + new PassModelT(std::forward<PassT>(Pass)))); + } else { + /// When adding a pass manager pass that has the same type as this pass + /// manager, simply move the passes over. This is because we don't have + /// use cases rely on executing nested pass managers. Doing this could + /// reduce implementation complexity and avoid potential invalidation + /// issues that may happen with nested pass managers of the same type. + for (auto &P : Pass.Passes) + Passes.push_back(std::move(P)); + } } /// Returns if the pass manager contains any passes. diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 487ae170210de91ce02df23812015b5606b092ea..92cb79d54afc29f764401b42d28baffbdd5d5b41 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -68,6 +68,22 @@ template <typename T> inline OneUse_match<T> m_OneUse(const T &SubPattern) { return SubPattern; } +template <typename SubPattern_t> struct AllowReassoc_match { + SubPattern_t SubPattern; + + AllowReassoc_match(const SubPattern_t &SP) : SubPattern(SP) {} + + template <typename OpTy> bool match(OpTy *V) { + auto *I = dyn_cast<FPMathOperator>(V); + return I && I->hasAllowReassoc() && SubPattern.match(I); + } +}; + +template <typename T> +inline AllowReassoc_match<T> m_AllowReassoc(const T &SubPattern) { + return SubPattern; +} + template <typename Class> struct class_match { template <typename ITy> bool match(ITy *V) { return isa<Class>(V); } }; @@ -868,9 +884,9 @@ struct bind_const_intval_ty { /// Match a specified integer value or vector of all elements of that /// value. template <bool AllowUndefs> struct specific_intval { - APInt Val; + const APInt &Val; - specific_intval(APInt V) : Val(std::move(V)) {} + specific_intval(const APInt &V) : Val(V) {} template <typename ITy> bool match(ITy *V) { const auto *CI = dyn_cast<ConstantInt>(V); @@ -882,22 +898,37 @@ template <bool AllowUndefs> struct specific_intval { } }; +template <bool AllowUndefs> struct specific_intval64 { + uint64_t Val; + + specific_intval64(uint64_t V) : Val(V) {} + + template <typename ITy> bool match(ITy *V) { + const auto *CI = dyn_cast<ConstantInt>(V); + if (!CI && V->getType()->isVectorTy()) + if (const auto *C = dyn_cast<Constant>(V)) + CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue(AllowUndefs)); + + return CI && CI->getValue() == Val; + } +}; + /// Match a specific integer value or vector with all elements equal to /// the value. -inline specific_intval<false> m_SpecificInt(APInt V) { - return specific_intval<false>(std::move(V)); +inline specific_intval<false> m_SpecificInt(const APInt &V) { + return specific_intval<false>(V); } -inline specific_intval<false> m_SpecificInt(uint64_t V) { - return m_SpecificInt(APInt(64, V)); +inline specific_intval64<false> m_SpecificInt(uint64_t V) { + return specific_intval64<false>(V); } -inline specific_intval<true> m_SpecificIntAllowUndef(APInt V) { - return specific_intval<true>(std::move(V)); +inline specific_intval<true> m_SpecificIntAllowUndef(const APInt &V) { + return specific_intval<true>(V); } -inline specific_intval<true> m_SpecificIntAllowUndef(uint64_t V) { - return m_SpecificIntAllowUndef(APInt(64, V)); +inline specific_intval64<true> m_SpecificIntAllowUndef(uint64_t V) { + return specific_intval64<true>(V); } /// Match a ConstantInt and bind to its value. This does not match @@ -1154,7 +1185,7 @@ inline BinaryOp_match<LHS, RHS, Instruction::AShr> m_AShr(const LHS &L, } template <typename LHS_t, typename RHS_t, unsigned Opcode, - unsigned WrapFlags = 0> + unsigned WrapFlags = 0, bool Commutable = false> struct OverflowingBinaryOp_match { LHS_t L; RHS_t R; @@ -1172,7 +1203,9 @@ struct OverflowingBinaryOp_match { if ((WrapFlags & OverflowingBinaryOperator::NoSignedWrap) && !Op->hasNoSignedWrap()) return false; - return L.match(Op->getOperand(0)) && R.match(Op->getOperand(1)); + return (L.match(Op->getOperand(0)) && R.match(Op->getOperand(1))) || + (Commutable && L.match(Op->getOperand(1)) && + R.match(Op->getOperand(0))); } return false; } @@ -1219,6 +1252,16 @@ m_NUWAdd(const LHS &L, const RHS &R) { OverflowingBinaryOperator::NoUnsignedWrap>( L, R); } + +template <typename LHS, typename RHS> +inline OverflowingBinaryOp_match< + LHS, RHS, Instruction::Add, OverflowingBinaryOperator::NoUnsignedWrap, true> +m_c_NUWAdd(const LHS &L, const RHS &R) { + return OverflowingBinaryOp_match<LHS, RHS, Instruction::Add, + OverflowingBinaryOperator::NoUnsignedWrap, + true>(L, R); +} + template <typename LHS, typename RHS> inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Sub, OverflowingBinaryOperator::NoUnsignedWrap> @@ -1303,10 +1346,31 @@ m_AddLike(const LHS &L, const RHS &R) { return m_CombineOr(m_Add(L, R), m_DisjointOr(L, R)); } +/// Match either "add nsw" or "or disjoint" +template <typename LHS, typename RHS> +inline match_combine_or< + OverflowingBinaryOp_match<LHS, RHS, Instruction::Add, + OverflowingBinaryOperator::NoSignedWrap>, + DisjointOr_match<LHS, RHS>> +m_NSWAddLike(const LHS &L, const RHS &R) { + return m_CombineOr(m_NSWAdd(L, R), m_DisjointOr(L, R)); +} + +/// Match either "add nuw" or "or disjoint" +template <typename LHS, typename RHS> +inline match_combine_or< + OverflowingBinaryOp_match<LHS, RHS, Instruction::Add, + OverflowingBinaryOperator::NoUnsignedWrap>, + DisjointOr_match<LHS, RHS>> +m_NUWAddLike(const LHS &L, const RHS &R) { + return m_CombineOr(m_NUWAdd(L, R), m_DisjointOr(L, R)); +} + //===----------------------------------------------------------------------===// // Class that matches a group of binary opcodes. // -template <typename LHS_t, typename RHS_t, typename Predicate> +template <typename LHS_t, typename RHS_t, typename Predicate, + bool Commutable = false> struct BinOpPred_match : Predicate { LHS_t L; RHS_t R; @@ -1315,8 +1379,10 @@ struct BinOpPred_match : Predicate { template <typename OpTy> bool match(OpTy *V) { if (auto *I = dyn_cast<Instruction>(V)) - return this->isOpType(I->getOpcode()) && L.match(I->getOperand(0)) && - R.match(I->getOperand(1)); + return this->isOpType(I->getOpcode()) && + ((L.match(I->getOperand(0)) && R.match(I->getOperand(1))) || + (Commutable && L.match(I->getOperand(1)) && + R.match(I->getOperand(0)))); return false; } }; @@ -1383,6 +1449,13 @@ m_BitwiseLogic(const LHS &L, const RHS &R) { return BinOpPred_match<LHS, RHS, is_bitwiselogic_op>(L, R); } +/// Matches bitwise logic operations in either order. +template <typename LHS, typename RHS> +inline BinOpPred_match<LHS, RHS, is_bitwiselogic_op, true> +m_c_BitwiseLogic(const LHS &L, const RHS &R) { + return BinOpPred_match<LHS, RHS, is_bitwiselogic_op, true>(L, R); +} + /// Matches integer division operations. template <typename LHS, typename RHS> inline BinOpPred_match<LHS, RHS, is_idiv_op> m_IDiv(const LHS &L, diff --git a/llvm/include/llvm/IR/ProfDataUtils.h b/llvm/include/llvm/IR/ProfDataUtils.h index 255fa2ff1c79065304659cd6498311a9d6264291..c0897408986fb3221267e24a89506ba10182de5c 100644 --- a/llvm/include/llvm/IR/ProfDataUtils.h +++ b/llvm/include/llvm/IR/ProfDataUtils.h @@ -108,5 +108,8 @@ bool extractProfTotalWeight(const Instruction &I, uint64_t &TotalWeights); /// a `prof` metadata reference to instruction `I`. void setBranchWeights(Instruction &I, ArrayRef<uint32_t> Weights); +/// Scaling the profile data attached to 'I' using the ratio of S/T. +void scaleProfData(Instruction &I, uint64_t S, uint64_t T); + } // namespace llvm #endif diff --git a/llvm/include/llvm/MC/ConstantPools.h b/llvm/include/llvm/MC/ConstantPools.h index 7eac75362effdc8c1ad6201b14dc82ecef1366b4..ff21ccda07a83645735a3ecd972ecaa7e3ce78a2 100644 --- a/llvm/include/llvm/MC/ConstantPools.h +++ b/llvm/include/llvm/MC/ConstantPools.h @@ -43,8 +43,13 @@ struct ConstantPoolEntry { class ConstantPool { using EntryVecTy = SmallVector<ConstantPoolEntry, 4>; EntryVecTy Entries; - std::map<int64_t, const MCSymbolRefExpr *> CachedConstantEntries; - DenseMap<const MCSymbol *, const MCSymbolRefExpr *> CachedSymbolEntries; + + // Caches of entries that already exist, indexed by their contents + // and also the size of the constant. + std::map<std::pair<int64_t, unsigned>, const MCSymbolRefExpr *> + CachedConstantEntries; + DenseMap<std::pair<const MCSymbol *, unsigned>, const MCSymbolRefExpr *> + CachedSymbolEntries; public: // Initialize a new empty constant pool diff --git a/llvm/include/llvm/MC/DXContainerPSVInfo.h b/llvm/include/llvm/MC/DXContainerPSVInfo.h index 7d21c18d252f1cc7b489630e6e27cc95792b3388..bad2fe78eb8fbbf38412c8f1a99723859013e50f 100644 --- a/llvm/include/llvm/MC/DXContainerPSVInfo.h +++ b/llvm/include/llvm/MC/DXContainerPSVInfo.h @@ -9,9 +9,11 @@ #ifndef LLVM_MC_DXCONTAINERPSVINFO_H #define LLVM_MC_DXCONTAINERPSVINFO_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/DXContainer.h" +#include "llvm/MC/StringTableBuilder.h" #include "llvm/TargetParser/Triple.h" #include <array> @@ -45,8 +47,9 @@ struct PSVSignatureElement { // modifiable format, and can be used to serialize the data back into valid PSV // RuntimeInfo. struct PSVRuntimeInfo { + PSVRuntimeInfo() : DXConStrTabBuilder(StringTableBuilder::DXContainer) {} bool IsFinalized = false; - dxbc::PSV::v2::RuntimeInfo BaseData; + dxbc::PSV::v3::RuntimeInfo BaseData; SmallVector<dxbc::PSV::v2::ResourceBindInfo> Resources; SmallVector<PSVSignatureElement> InputElements; SmallVector<PSVSignatureElement> OutputElements; @@ -64,6 +67,7 @@ struct PSVRuntimeInfo { std::array<SmallVector<uint32_t>, 4> InputOutputMap; SmallVector<uint32_t> InputPatchMap; SmallVector<uint32_t> PatchOutputMap; + llvm::StringRef EntryName; // Serialize PSVInfo into the provided raw_ostream. The version field // specifies the data version to encode, the default value specifies encoding @@ -71,19 +75,12 @@ struct PSVRuntimeInfo { void write(raw_ostream &OS, uint32_t Version = std::numeric_limits<uint32_t>::max()) const; - void finalize(Triple::EnvironmentType Stage) { - IsFinalized = true; - BaseData.SigInputElements = static_cast<uint32_t>(InputElements.size()); - BaseData.SigOutputElements = static_cast<uint32_t>(OutputElements.size()); - BaseData.SigPatchOrPrimElements = - static_cast<uint32_t>(PatchOrPrimElements.size()); - if (!sys::IsBigEndianHost) - return; - BaseData.swapBytes(); - BaseData.swapBytes(Stage); - for (auto &Res : Resources) - Res.swapBytes(); - } + void finalize(Triple::EnvironmentType Stage); + +private: + SmallVector<uint32_t, 64> IndexBuffer; + SmallVector<llvm::dxbc::PSV::v0::SignatureElement, 32> SignatureElements; + StringTableBuilder DXConStrTabBuilder; }; class Signature { diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h index 3f585d4d2efaf5a499974c3578933bc41569d520..ef9833cdf2b070a0e0dc270d9e1c5fcfd6fe17d9 100644 --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -26,6 +26,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/Error.h" #include "llvm/Support/MD5.h" +#include "llvm/Support/StringSaver.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> @@ -70,6 +71,10 @@ class SMLoc; class SourceMgr; enum class EmitDwarfUnwindType; +namespace wasm { +struct WasmSignature; +} + /// Context object for machine code objects. This class owns all of the /// sections that it creates. /// @@ -139,6 +144,8 @@ private: SpecificBumpPtrAllocator<MCSectionXCOFF> XCOFFAllocator; SpecificBumpPtrAllocator<MCInst> MCInstAllocator; + SpecificBumpPtrAllocator<wasm::WasmSignature> WasmSignatureAllocator; + /// Bindings of names to symbols. SymbolTable Symbols; @@ -538,6 +545,10 @@ public: /// inline assembly. void registerInlineAsmLabel(MCSymbol *Sym); + /// Allocates and returns a new `WasmSignature` instance (with empty parameter + /// and return type lists). + wasm::WasmSignature *createWasmSignature(); + /// @} /// \name Section Management @@ -850,6 +861,12 @@ public: void deallocate(void *Ptr) {} + /// Allocates a copy of the given string on the allocator managed by this + /// context and returns the result. + StringRef allocateString(StringRef s) { + return StringSaver(Allocator).save(s); + } + bool hadError() { return HadError; } void diagnose(const SMDiagnostic &SMD); void reportError(SMLoc L, const Twine &Msg); diff --git a/llvm/include/llvm/MC/MCInstBuilder.h b/llvm/include/llvm/MC/MCInstBuilder.h index 6e5e9dd69018f4fc262c3f21cba635113b3cb66e..d06ed4c6c840a9f6db49740d69c871b0605b6eb5 100644 --- a/llvm/include/llvm/MC/MCInstBuilder.h +++ b/llvm/include/llvm/MC/MCInstBuilder.h @@ -27,6 +27,12 @@ public: Inst.setOpcode(Opcode); } + /// Set the location. + MCInstBuilder &setLoc(SMLoc SM) { + Inst.setLoc(SM); + return *this; + } + /// Add a new register operand. MCInstBuilder &addReg(unsigned Reg) { Inst.addOperand(MCOperand::createReg(Reg)); diff --git a/llvm/include/llvm/MC/MCInstrAnalysis.h b/llvm/include/llvm/MC/MCInstrAnalysis.h index e3ddf0b8b8939c907bdd699035be30f763cb07b5..87db57f74f520e99598c9fdbd40b2a7ed937085b 100644 --- a/llvm/include/llvm/MC/MCInstrAnalysis.h +++ b/llvm/include/llvm/MC/MCInstrAnalysis.h @@ -123,14 +123,14 @@ public: /// broken. Each bit of the mask is associated with a specific input operand. /// Bits associated with explicit input operands are laid out first in the /// mask; implicit operands come after explicit operands. - /// + /// /// Dependencies are broken only for operands that have their corresponding bit /// set. Operands that have their bit cleared, or that don't have a /// corresponding bit in the mask don't have their dependency broken. Note /// that Mask may not be big enough to describe all operands. The assumption /// for operands that don't have a correspondent bit in the mask is that those /// are still data dependent. - /// + /// /// The only exception to the rule is for when Mask has all zeroes. /// A zero mask means: dependencies are broken for all explicit register /// operands. diff --git a/llvm/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/llvm/include/llvm/MC/MCParser/MCParsedAsmOperand.h index 0c9668904e8261bda827dc4d8e47ad9a2bd5e4a3..27ecb7b85d229177ac6c379dd488ca7f92382f05 100644 --- a/llvm/include/llvm/MC/MCParser/MCParsedAsmOperand.h +++ b/llvm/include/llvm/MC/MCParser/MCParsedAsmOperand.h @@ -15,6 +15,7 @@ namespace llvm { +class MCRegister; class raw_ostream; /// MCParsedAsmOperand - This abstract class represents a source-level assembly @@ -57,7 +58,7 @@ public: virtual bool isImm() const = 0; /// isReg - Is this a register operand? virtual bool isReg() const = 0; - virtual unsigned getReg() const = 0; + virtual MCRegister getReg() const = 0; /// isMem - Is this a memory operand? virtual bool isMem() const = 0; diff --git a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h index 7edd3f8ce4904c9afc565e533719df3c96ec31f2..49ce417e6fbb205787ba376751ad05d787e29876 100644 --- a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h +++ b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h @@ -514,9 +514,7 @@ public: /// by the tied-operands checks in the AsmMatcher. This method can be /// overridden to allow e.g. a sub- or super-register as the tied operand. virtual bool areEqualRegs(const MCParsedAsmOperand &Op1, - const MCParsedAsmOperand &Op2) const { - return Op1.isReg() && Op2.isReg() && Op1.getReg() == Op2.getReg(); - } + const MCParsedAsmOperand &Op2) const; // Return whether this parser uses assignment statements with equals tokens virtual bool equalIsAsmAssignment() { return true; }; diff --git a/llvm/include/llvm/MC/MCRegisterInfo.h b/llvm/include/llvm/MC/MCRegisterInfo.h index fb4d11ec1d4d1650618b5eb429e6a9fdba445c8a..c648ef20fa84c67e254111352bde9e527b73e441 100644 --- a/llvm/include/llvm/MC/MCRegisterInfo.h +++ b/llvm/include/llvm/MC/MCRegisterInfo.h @@ -153,13 +153,6 @@ public: bool operator<(DwarfLLVMRegPair RHS) const { return FromReg < RHS.FromReg; } }; - /// SubRegCoveredBits - Emitted by tablegen: bit range covered by a subreg - /// index, -1 in any being invalid. - struct SubRegCoveredBits { - uint16_t Offset; - uint16_t Size; - }; - private: const MCRegisterDesc *Desc; // Pointer to the descriptor array unsigned NumRegs; // Number of entries in the array @@ -176,8 +169,6 @@ private: const char *RegClassStrings; // Pointer to the class strings. const uint16_t *SubRegIndices; // Pointer to the subreg lookup // array. - const SubRegCoveredBits *SubRegIdxRanges; // Pointer to the subreg covered - // bit ranges array. unsigned NumSubRegIndices; // Number of subreg indices. const uint16_t *RegEncodingTable; // Pointer to array of register // encodings. @@ -278,7 +269,6 @@ public: const int16_t *DL, const LaneBitmask *RUMS, const char *Strings, const char *ClassStrings, const uint16_t *SubIndices, unsigned NumIndices, - const SubRegCoveredBits *SubIdxRanges, const uint16_t *RET) { Desc = D; NumRegs = NR; @@ -294,7 +284,6 @@ public: NumRegUnits = NRU; SubRegIndices = SubIndices; NumSubRegIndices = NumIndices; - SubRegIdxRanges = SubIdxRanges; RegEncodingTable = RET; // Initialize DWARF register mapping variables @@ -387,16 +376,6 @@ public: /// otherwise. unsigned getSubRegIndex(MCRegister RegNo, MCRegister SubRegNo) const; - /// Get the size of the bit range covered by a sub-register index. - /// If the index isn't continuous, return the sum of the sizes of its parts. - /// If the index is used to access subregisters of different sizes, return -1. - unsigned getSubRegIdxSize(unsigned Idx) const; - - /// Get the offset of the bit range covered by a sub-register index. - /// If an Offset doesn't make sense (the index isn't continuous, or is used to - /// access sub-registers at different offsets), return -1. - unsigned getSubRegIdxOffset(unsigned Idx) const; - /// Return the human-readable symbolic target-specific name for the /// specified physical register. const char *getName(MCRegister RegNo) const { diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 671511ab4b88e3ed74d3e2d3384b6f4fb60f1f2e..69867620e1bf8ade6e16a9f08285ae38889ccedc 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -740,7 +740,7 @@ public: /// Special case of EmitValue that avoids the client having /// to pass in a MCExpr for constant integers. virtual void emitIntValue(uint64_t Value, unsigned Size); - virtual void emitIntValue(APInt Value); + virtual void emitIntValue(const APInt &Value); /// Special case of EmitValue that avoids the client having to pass /// in a MCExpr for constant integers & prints in Hex format for certain diff --git a/llvm/include/llvm/MC/MCSymbolXCOFF.h b/llvm/include/llvm/MC/MCSymbolXCOFF.h index 11c3b8831ba517642600fe20b516aade3ee531d2..3bf4491e8fe2f8cdc42a237bb8174f8d97443c2b 100644 --- a/llvm/include/llvm/MC/MCSymbolXCOFF.h +++ b/llvm/include/llvm/MC/MCSymbolXCOFF.h @@ -26,6 +26,8 @@ public: static bool classof(const MCSymbol *S) { return S->isXCOFF(); } + enum CodeModel : uint8_t { CM_Small, CM_Large }; + static StringRef getUnqualifiedName(StringRef Name) { if (Name.back() == ']') { StringRef Lhs, Rhs; @@ -72,8 +74,22 @@ public: void setEHInfo() const { modifyFlags(SF_EHInfo, SF_EHInfo); } + bool hasPerSymbolCodeModel() const { return PerSymbolCodeModel.has_value(); } + + CodeModel getPerSymbolCodeModel() const { + assert(hasPerSymbolCodeModel() && + "Requested code model for symbol without one"); + return *PerSymbolCodeModel; + } + + void setPerSymbolCodeModel(MCSymbolXCOFF::CodeModel Model) { + PerSymbolCodeModel = Model; + } + private: std::optional<XCOFF::StorageClass> StorageClass; + std::optional<CodeModel> PerSymbolCodeModel; + MCSectionXCOFF *RepresentedCsect = nullptr; XCOFF::VisibilityType VisibilityType = XCOFF::SYM_V_UNSPECIFIED; StringRef SymbolTableName; diff --git a/llvm/include/llvm/MC/StringTableBuilder.h b/llvm/include/llvm/MC/StringTableBuilder.h index 4ee421e22c171feb1a8539c787cccc01aae48266..a738683548cfa54c7f61273fb22c2ef4daa860b1 100644 --- a/llvm/include/llvm/MC/StringTableBuilder.h +++ b/llvm/include/llvm/MC/StringTableBuilder.h @@ -74,12 +74,8 @@ public: /// Check if a string is contained in the string table. Since this class /// doesn't store the string values, this function can be used to check if /// storage needs to be done prior to adding the string. - bool contains(StringRef S) const { - return contains(CachedHashStringRef(S)); - } - bool contains(CachedHashStringRef S) const { - return StringIndexMap.count(S); - } + bool contains(StringRef S) const { return contains(CachedHashStringRef(S)); } + bool contains(CachedHashStringRef S) const { return StringIndexMap.count(S); } size_t getSize() const { return Size; } void clear(); diff --git a/llvm/include/llvm/ObjCopy/CommonConfig.h b/llvm/include/llvm/ObjCopy/CommonConfig.h index 383395941475a42209aa6e3495a5d5e7cb7f519a..9d6d5fb23b18e7fbc91be356ed63a7bd630d270b 100644 --- a/llvm/include/llvm/ObjCopy/CommonConfig.h +++ b/llvm/include/llvm/ObjCopy/CommonConfig.h @@ -16,13 +16,11 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Object/ELFTypes.h" +#include "llvm/Support/Compression.h" #include "llvm/Support/GlobPattern.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Regex.h" -// Necessary for llvm::DebugCompressionType::None -#include "llvm/Target/TargetOptions.h" #include <optional> -#include <vector> namespace llvm { namespace objcopy { @@ -126,8 +124,8 @@ public: // provided for that option. class NameMatcher { DenseSet<CachedHashStringRef> PosNames; - std::vector<NameOrPattern> PosPatterns; - std::vector<NameOrPattern> NegMatchers; + SmallVector<NameOrPattern, 0> PosPatterns; + SmallVector<NameOrPattern, 0> NegMatchers; public: Error addMatcher(Expected<NameOrPattern> Matcher) { @@ -179,8 +177,8 @@ struct NewSymbolInfo { StringRef SymbolName; StringRef SectionName; uint64_t Value = 0; - std::vector<SymbolFlag> Flags; - std::vector<StringRef> BeforeSyms; + SmallVector<SymbolFlag, 0> Flags; + SmallVector<StringRef, 0> BeforeSyms; }; // Specify section name and section body for newly added or updated section. @@ -218,9 +216,9 @@ struct CommonConfig { DiscardType DiscardMode = DiscardType::None; // Repeated options - std::vector<NewSectionInfo> AddSection; - std::vector<StringRef> DumpSection; - std::vector<NewSectionInfo> UpdateSection; + SmallVector<NewSectionInfo, 0> AddSection; + SmallVector<StringRef, 0> DumpSection; + SmallVector<NewSectionInfo, 0> UpdateSection; // Section matchers NameMatcher KeepSection; @@ -235,6 +233,7 @@ struct CommonConfig { NameMatcher UnneededSymbolsToRemove; NameMatcher SymbolsToWeaken; NameMatcher SymbolsToKeepGlobal; + NameMatcher SymbolsToSkip; // Map options StringMap<SectionRename> SectionsToRename; @@ -244,7 +243,7 @@ struct CommonConfig { StringMap<StringRef> SymbolsToRename; // Symbol info specified by --add-symbol option. - std::vector<NewSymbolInfo> SymbolsToAdd; + SmallVector<NewSymbolInfo, 0> SymbolsToAdd; // Boolean options bool DeterministicArchives = true; diff --git a/llvm/include/llvm/Object/Archive.h b/llvm/include/llvm/Object/Archive.h index f71630054dc6373e30280676a43729c16ced341a..a3165c3235e0ed23de720bd6171ab67efc298eb8 100644 --- a/llvm/include/llvm/Object/Archive.h +++ b/llvm/include/llvm/Object/Archive.h @@ -339,6 +339,7 @@ public: Kind kind() const { return (Kind)Format; } bool isThin() const { return IsThin; } static object::Archive::Kind getDefaultKind(); + static object::Archive::Kind getDefaultKindForTriple(Triple &T); child_iterator child_begin(Error &Err, bool SkipInternal = true) const; child_iterator child_end() const; diff --git a/llvm/include/llvm/Object/ArchiveWriter.h b/llvm/include/llvm/Object/ArchiveWriter.h index 7f915929cd7219fdaedd851de0b3f1fcb69fb715..a19f8fcc79d7414250a8c8b92912f01abaa51780 100644 --- a/llvm/include/llvm/Object/ArchiveWriter.h +++ b/llvm/include/llvm/Object/ArchiveWriter.h @@ -52,7 +52,7 @@ Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers, SymtabWritingMode WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin, std::unique_ptr<MemoryBuffer> OldArchiveBuf = nullptr, - bool IsEC = false); + std::optional<bool> IsEC = std::nullopt); // writeArchiveToBuffer is similar to writeArchive but returns the Archive in a // buffer instead of writing it out to a file. diff --git a/llvm/include/llvm/Object/COFF.h b/llvm/include/llvm/Object/COFF.h index 2a5c3d8913b15cbeb98032107a48634398af2367..a548b2c15c5fdc9385e3f881d7d1c7b3fa075bce 100644 --- a/llvm/include/llvm/Object/COFF.h +++ b/llvm/include/llvm/Object/COFF.h @@ -1362,47 +1362,6 @@ public: SectionStrippedError() { setErrorCode(object_error::section_stripped); } }; -inline std::optional<std::string> -getArm64ECMangledFunctionName(StringRef Name) { - bool IsCppFn = Name[0] == '?'; - if (IsCppFn && Name.find("$$h") != std::string::npos) - return std::nullopt; - if (!IsCppFn && Name[0] == '#') - return std::nullopt; - - StringRef Prefix = "$$h"; - size_t InsertIdx = 0; - if (IsCppFn) { - InsertIdx = Name.find("@@"); - size_t ThreeAtSignsIdx = Name.find("@@@"); - if (InsertIdx != std::string::npos && InsertIdx != ThreeAtSignsIdx) { - InsertIdx += 2; - } else { - InsertIdx = Name.find("@"); - if (InsertIdx != std::string::npos) - InsertIdx++; - } - } else { - Prefix = "#"; - } - - return std::optional<std::string>( - (Name.substr(0, InsertIdx) + Prefix + Name.substr(InsertIdx)).str()); -} - -inline std::optional<std::string> -getArm64ECDemangledFunctionName(StringRef Name) { - if (Name[0] == '#') - return std::string(Name.substr(1)); - if (Name[0] != '?') - return std::nullopt; - - std::pair<StringRef, StringRef> Pair = Name.split("$$h"); - if (Pair.second.empty()) - return std::nullopt; - return (Pair.first + Pair.second).str(); -} - } // end namespace object } // end namespace llvm diff --git a/llvm/include/llvm/Object/COFFImportFile.h b/llvm/include/llvm/Object/COFFImportFile.h index 7268faa87eb70baf829fd25353fd0ec88b9307af..2c06f529ecdfc50f9d0f72b7d2b6930b0d4c0d27 100644 --- a/llvm/include/llvm/Object/COFFImportFile.h +++ b/llvm/include/llvm/Object/COFFImportFile.h @@ -17,6 +17,7 @@ #define LLVM_OBJECT_COFFIMPORTFILE_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/IR/Mangler.h" #include "llvm/Object/COFF.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Object/SymbolicFile.h" @@ -44,26 +45,7 @@ public: void moveSymbolNext(DataRefImpl &Symb) const override { ++Symb.p; } - Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override { - switch (Symb.p) { - case ImpSymbol: - OS << "__imp_"; - break; - case ECAuxSymbol: - OS << "__imp_aux_"; - break; - } - const char *Name = Data.getBufferStart() + sizeof(coff_import_header); - if (Symb.p != ECThunkSymbol && COFF::isArm64EC(getMachine())) { - if (std::optional<std::string> DemangledName = - getArm64ECDemangledFunctionName(Name)) { - OS << StringRef(*DemangledName); - return Error::success(); - } - } - OS << StringRef(Name); - return Error::success(); - } + Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override { return SymbolRef::SF_Global; diff --git a/llvm/include/llvm/Object/DXContainer.h b/llvm/include/llvm/Object/DXContainer.h index b6e3d321da2461a99be961df29d643082011aeb4..19c83ba6c6e85df6657241ba581c8a6af673232c 100644 --- a/llvm/include/llvm/Object/DXContainer.h +++ b/llvm/include/llvm/Object/DXContainer.h @@ -125,7 +125,8 @@ class PSVRuntimeInfo { uint32_t Size; using InfoStruct = std::variant<std::monostate, dxbc::PSV::v0::RuntimeInfo, - dxbc::PSV::v1::RuntimeInfo, dxbc::PSV::v2::RuntimeInfo>; + dxbc::PSV::v1::RuntimeInfo, dxbc::PSV::v2::RuntimeInfo, + dxbc::PSV::v3::RuntimeInfo>; InfoStruct BasicInfo; ResourceArray Resources; StringRef StringTable; @@ -151,9 +152,11 @@ public: ResourceArray getResources() const { return Resources; } uint32_t getVersion() const { - return Size >= sizeof(dxbc::PSV::v2::RuntimeInfo) - ? 2 - : (Size >= sizeof(dxbc::PSV::v1::RuntimeInfo) ? 1 : 0); + return Size >= sizeof(dxbc::PSV::v3::RuntimeInfo) + ? 3 + : (Size >= sizeof(dxbc::PSV::v2::RuntimeInfo) ? 2 + : (Size >= sizeof(dxbc::PSV::v1::RuntimeInfo)) ? 1 + : 0); } uint32_t getResourceStride() const { return Resources.Stride; } @@ -161,6 +164,11 @@ public: const InfoStruct &getInfo() const { return BasicInfo; } template <typename T> const T *getInfoAs() const { + if (const auto *P = std::get_if<dxbc::PSV::v3::RuntimeInfo>(&BasicInfo)) + return static_cast<const T *>(P); + if (std::is_same<T, dxbc::PSV::v3::RuntimeInfo>::value) + return nullptr; + if (const auto *P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&BasicInfo)) return static_cast<const T *>(P); if (std::is_same<T, dxbc::PSV::v2::RuntimeInfo>::value) diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h index c9227da65708cc3a1da6efbab79648e0a54ac676..1d457be93741f274d38f3e6b4d0fa1ebe0a71bac 100644 --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -60,6 +60,7 @@ class ELFObjectFileBase : public ObjectFile { SubtargetFeatures getMIPSFeatures() const; SubtargetFeatures getARMFeatures() const; + SubtargetFeatures getHexagonFeatures() const; Expected<SubtargetFeatures> getRISCVFeatures() const; SubtargetFeatures getLoongArchFeatures() const; @@ -389,25 +390,38 @@ protected: } Error getBuildAttributes(ELFAttributeParser &Attributes) const override { + uint32_t Type; + switch (getEMachine()) { + case ELF::EM_ARM: + Type = ELF::SHT_ARM_ATTRIBUTES; + break; + case ELF::EM_RISCV: + Type = ELF::SHT_RISCV_ATTRIBUTES; + break; + case ELF::EM_HEXAGON: + Type = ELF::SHT_HEXAGON_ATTRIBUTES; + break; + default: + return Error::success(); + } + auto SectionsOrErr = EF.sections(); if (!SectionsOrErr) return SectionsOrErr.takeError(); - for (const Elf_Shdr &Sec : *SectionsOrErr) { - if (Sec.sh_type == ELF::SHT_ARM_ATTRIBUTES || - Sec.sh_type == ELF::SHT_RISCV_ATTRIBUTES) { - auto ErrorOrContents = EF.getSectionContents(Sec); - if (!ErrorOrContents) - return ErrorOrContents.takeError(); - - auto Contents = ErrorOrContents.get(); - if (Contents[0] != ELFAttrs::Format_Version || Contents.size() == 1) - return Error::success(); - - if (Error E = Attributes.parse(Contents, ELFT::TargetEndianness)) - return E; - break; - } + if (Sec.sh_type != Type) + continue; + auto ErrorOrContents = EF.getSectionContents(Sec); + if (!ErrorOrContents) + return ErrorOrContents.takeError(); + + auto Contents = ErrorOrContents.get(); + if (Contents[0] != ELFAttrs::Format_Version || Contents.size() == 1) + return Error::success(); + + if (Error E = Attributes.parse(Contents, ELFT::Endianness)) + return E; + break; } return Error::success(); } @@ -468,7 +482,7 @@ public: bool isDyldType() const { return isDyldELFObject; } static bool classof(const Binary *v) { return v->getType() == - getELFType(ELFT::TargetEndianness == llvm::endianness::little, + getELFType(ELFT::Endianness == llvm::endianness::little, ELFT::Is64Bits); } @@ -1141,10 +1155,9 @@ ELFObjectFile<ELFT>::ELFObjectFile(MemoryBufferRef Object, ELFFile<ELFT> EF, const Elf_Shdr *DotDynSymSec, const Elf_Shdr *DotSymtabSec, const Elf_Shdr *DotSymtabShndx) - : ELFObjectFileBase( - getELFType(ELFT::TargetEndianness == llvm::endianness::little, - ELFT::Is64Bits), - Object), + : ELFObjectFileBase(getELFType(ELFT::Endianness == llvm::endianness::little, + ELFT::Is64Bits), + Object), EF(EF), DotDynSymSec(DotDynSymSec), DotSymtabSec(DotSymtabSec), DotSymtabShndxSec(DotSymtabShndx) {} @@ -1212,8 +1225,7 @@ uint8_t ELFObjectFile<ELFT>::getBytesInAddress() const { template <class ELFT> StringRef ELFObjectFile<ELFT>::getFileFormatName() const { - constexpr bool IsLittleEndian = - ELFT::TargetEndianness == llvm::endianness::little; + constexpr bool IsLittleEndian = ELFT::Endianness == llvm::endianness::little; switch (EF.getHeader().e_ident[ELF::EI_CLASS]) { case ELF::ELFCLASS32: switch (EF.getHeader().e_machine) { @@ -1291,7 +1303,7 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { } template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const { - bool IsLittleEndian = ELFT::TargetEndianness == llvm::endianness::little; + bool IsLittleEndian = ELFT::Endianness == llvm::endianness::little; switch (EF.getHeader().e_machine) { case ELF::EM_68K: return Triple::m68k; diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h index 4986ecf8323d021984942ef366ef3447bc1595c1..4ab23e4ea81b1aa963129ce4ffbf9389565bdcae 100644 --- a/llvm/include/llvm/Object/ELFTypes.h +++ b/llvm/include/llvm/Object/ELFTypes.h @@ -51,7 +51,7 @@ private: using packed = support::detail::packed_endian_specific_integral<Ty, E, 1>; public: - static const endianness TargetEndianness = E; + static const endianness Endianness = E; static const bool Is64Bits = Is64; using uint = std::conditional_t<Is64, uint64_t, uint32_t>; @@ -145,9 +145,9 @@ using ELF64BE = ELFType<llvm::endianness::big, true>; // Section header. template <class ELFT> struct Elf_Shdr_Base; -template <endianness TargetEndianness> -struct Elf_Shdr_Base<ELFType<TargetEndianness, false>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template <endianness Endianness> +struct Elf_Shdr_Base<ELFType<Endianness, false>> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Word sh_flags; // Section flags (SHF_*) @@ -160,9 +160,9 @@ struct Elf_Shdr_Base<ELFType<TargetEndianness, false>> { Elf_Word sh_entsize; // Size of records contained within the section }; -template <endianness TargetEndianness> -struct Elf_Shdr_Base<ELFType<TargetEndianness, true>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template <endianness Endianness> +struct Elf_Shdr_Base<ELFType<Endianness, true>> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Xword sh_flags; // Section flags (SHF_*) @@ -190,9 +190,9 @@ struct Elf_Shdr_Impl : Elf_Shdr_Base<ELFT> { template <class ELFT> struct Elf_Sym_Base; -template <endianness TargetEndianness> -struct Elf_Sym_Base<ELFType<TargetEndianness, false>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template <endianness Endianness> +struct Elf_Sym_Base<ELFType<Endianness, false>> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) Elf_Word st_name; // Symbol name (index into string table) Elf_Addr st_value; // Value or address associated with the symbol Elf_Word st_size; // Size of the symbol @@ -201,9 +201,9 @@ struct Elf_Sym_Base<ELFType<TargetEndianness, false>> { Elf_Half st_shndx; // Which section (header table index) it's defined in }; -template <endianness TargetEndianness> -struct Elf_Sym_Base<ELFType<TargetEndianness, true>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template <endianness Endianness> +struct Elf_Sym_Base<ELFType<Endianness, true>> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) Elf_Word st_name; // Symbol name (index into string table) unsigned char st_info; // Symbol's type and binding attributes unsigned char st_other; // Must be zero; reserved @@ -349,9 +349,9 @@ struct Elf_Vernaux_Impl { /// table section (.dynamic) look like. template <class ELFT> struct Elf_Dyn_Base; -template <endianness TargetEndianness> -struct Elf_Dyn_Base<ELFType<TargetEndianness, false>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template <endianness Endianness> +struct Elf_Dyn_Base<ELFType<Endianness, false>> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) Elf_Sword d_tag; union { Elf_Word d_val; @@ -359,9 +359,9 @@ struct Elf_Dyn_Base<ELFType<TargetEndianness, false>> { } d_un; }; -template <endianness TargetEndianness> -struct Elf_Dyn_Base<ELFType<TargetEndianness, true>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template <endianness Endianness> +struct Elf_Dyn_Base<ELFType<Endianness, true>> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) Elf_Sxword d_tag; union { Elf_Xword d_val; @@ -381,9 +381,9 @@ struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> { uintX_t getPtr() const { return d_un.d_ptr; } }; -template <endianness TargetEndianness> -struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template <endianness Endianness> +struct Elf_Rel_Impl<ELFType<Endianness, false>, false> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) static const bool IsRela = false; Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Word r_info; // Symbol table index and type of relocation to apply @@ -416,17 +416,17 @@ struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> { } }; -template <endianness TargetEndianness> -struct Elf_Rel_Impl<ELFType<TargetEndianness, false>, true> - : public Elf_Rel_Impl<ELFType<TargetEndianness, false>, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template <endianness Endianness> +struct Elf_Rel_Impl<ELFType<Endianness, false>, true> + : public Elf_Rel_Impl<ELFType<Endianness, false>, false> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) static const bool IsRela = true; Elf_Sword r_addend; // Compute value for relocatable field by adding this }; -template <endianness TargetEndianness> -struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template <endianness Endianness> +struct Elf_Rel_Impl<ELFType<Endianness, true>, false> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) static const bool IsRela = false; Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Xword r_info; // Symbol table index and type of relocation to apply @@ -469,10 +469,10 @@ struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> { } }; -template <endianness TargetEndianness> -struct Elf_Rel_Impl<ELFType<TargetEndianness, true>, true> - : public Elf_Rel_Impl<ELFType<TargetEndianness, true>, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template <endianness Endianness> +struct Elf_Rel_Impl<ELFType<Endianness, true>, true> + : public Elf_Rel_Impl<ELFType<Endianness, true>, false> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) static const bool IsRela = true; Elf_Sxword r_addend; // Compute value for relocatable field by adding this. }; @@ -504,9 +504,9 @@ struct Elf_Ehdr_Impl { unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; } }; -template <endianness TargetEndianness> -struct Elf_Phdr_Impl<ELFType<TargetEndianness, false>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template <endianness Endianness> +struct Elf_Phdr_Impl<ELFType<Endianness, false>> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) Elf_Word p_type; // Type of segment Elf_Off p_offset; // FileOffset where segment is located, in bytes Elf_Addr p_vaddr; // Virtual Address of beginning of segment @@ -517,9 +517,9 @@ struct Elf_Phdr_Impl<ELFType<TargetEndianness, false>> { Elf_Word p_align; // Segment alignment constraint }; -template <endianness TargetEndianness> -struct Elf_Phdr_Impl<ELFType<TargetEndianness, true>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template <endianness Endianness> +struct Elf_Phdr_Impl<ELFType<Endianness, true>> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) Elf_Word p_type; // Type of segment Elf_Word p_flags; // Segment flags Elf_Off p_offset; // FileOffset where segment is located, in bytes @@ -574,17 +574,17 @@ struct Elf_GnuHash_Impl { // Compressed section headers. // http://www.sco.com/developers/gabi/latest/ch4.sheader.html#compression_header -template <endianness TargetEndianness> -struct Elf_Chdr_Impl<ELFType<TargetEndianness, false>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template <endianness Endianness> +struct Elf_Chdr_Impl<ELFType<Endianness, false>> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) Elf_Word ch_type; Elf_Word ch_size; Elf_Word ch_addralign; }; -template <endianness TargetEndianness> -struct Elf_Chdr_Impl<ELFType<TargetEndianness, true>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template <endianness Endianness> +struct Elf_Chdr_Impl<ELFType<Endianness, true>> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) Elf_Word ch_type; Elf_Word ch_reserved; Elf_Xword ch_size; @@ -742,17 +742,17 @@ template <class ELFT> struct Elf_CGProfile_Impl { template <class ELFT> struct Elf_Mips_RegInfo; -template <llvm::endianness TargetEndianness> -struct Elf_Mips_RegInfo<ELFType<TargetEndianness, false>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) +template <llvm::endianness Endianness> +struct Elf_Mips_RegInfo<ELFType<Endianness, false>> { + LLVM_ELF_IMPORT_TYPES(Endianness, false) Elf_Word ri_gprmask; // bit-mask of used general registers Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers Elf_Addr ri_gp_value; // gp register value }; -template <llvm::endianness TargetEndianness> -struct Elf_Mips_RegInfo<ELFType<TargetEndianness, true>> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) +template <llvm::endianness Endianness> +struct Elf_Mips_RegInfo<ELFType<Endianness, true>> { + LLVM_ELF_IMPORT_TYPES(Endianness, true) Elf_Word ri_gprmask; // bit-mask of used general registers Elf_Word ri_pad; // unused padding field Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers diff --git a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h index 497f82bbd0f32a5ded3a97031273d279c9d4adb1..9c4d9e19f11ba324236250282c12d82be8225bcd 100644 --- a/llvm/include/llvm/ObjectYAML/DXContainerYAML.h +++ b/llvm/include/llvm/ObjectYAML/DXContainerYAML.h @@ -56,7 +56,7 @@ struct DXILProgram { std::optional<std::vector<llvm::yaml::Hex8>> DXIL; }; -#define SHADER_FEATURE_FLAG(Num, Val, Str) bool Val = false; +#define SHADER_FEATURE_FLAG(Num, DxilModuleNum, Val, Str) bool Val = false; struct ShaderFeatureFlags { ShaderFeatureFlags() = default; ShaderFeatureFlags(uint64_t FlagData); @@ -107,7 +107,7 @@ struct PSVInfo { // the format. uint32_t Version; - dxbc::PSV::v2::RuntimeInfo Info; + dxbc::PSV::v3::RuntimeInfo Info; uint32_t ResourceStride; SmallVector<ResourceBindInfo> Resources; SmallVector<SignatureElement> SigInputElements; @@ -121,12 +121,15 @@ struct PSVInfo { MaskVector InputPatchMap; MaskVector PatchOutputMap; + StringRef EntryName; + void mapInfoForVersion(yaml::IO &IO); PSVInfo(); PSVInfo(const dxbc::PSV::v0::RuntimeInfo *P, uint16_t Stage); PSVInfo(const dxbc::PSV::v1::RuntimeInfo *P); PSVInfo(const dxbc::PSV::v2::RuntimeInfo *P); + PSVInfo(const dxbc::PSV::v3::RuntimeInfo *P, StringRef StringTable); }; struct SignatureParameter { diff --git a/llvm/include/llvm/Passes/MachinePassRegistry.def b/llvm/include/llvm/Passes/MachinePassRegistry.def index 016602730e0e97d50c542dbee86060f177061464..2f77ae655d9b227a34ba356020abba40463217cf 100644 --- a/llvm/include/llvm/Passes/MachinePassRegistry.def +++ b/llvm/include/llvm/Passes/MachinePassRegistry.def @@ -127,6 +127,8 @@ MACHINE_FUNCTION_PASS("dead-mi-elimination", DeadMachineInstructionElimPass()) // MACHINE_FUNCTION_PASS("free-machine-function", FreeMachineFunctionPass()) MACHINE_FUNCTION_PASS("no-op-machine-function", NoOpMachineFunctionPass()) MACHINE_FUNCTION_PASS("print", PrintMIRPass()) +MACHINE_FUNCTION_PASS("require-all-machine-function-properties", + RequireAllMachineFunctionPropertiesPass()) #undef MACHINE_FUNCTION_PASS // After a pass is converted to new pass manager, its entry should be moved from diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h index 6822cfdb4957b69262e8c4fad942817bfd2ecce0..d1232124d5d819b088a9178268e36d179c61e4d8 100644 --- a/llvm/include/llvm/Passes/PassBuilder.h +++ b/llvm/include/llvm/Passes/PassBuilder.h @@ -626,6 +626,59 @@ public: void invokePipelineEarlySimplificationEPCallbacks(ModulePassManager &MPM, OptimizationLevel Level); + static bool checkParametrizedPassName(StringRef Name, StringRef PassName) { + if (!Name.consume_front(PassName)) + return false; + // normal pass name w/o parameters == default parameters + if (Name.empty()) + return true; + return Name.starts_with("<") && Name.ends_with(">"); + } + + /// This performs customized parsing of pass name with parameters. + /// + /// We do not need parametrization of passes in textual pipeline very often, + /// yet on a rare occasion ability to specify parameters right there can be + /// useful. + /// + /// \p Name - parameterized specification of a pass from a textual pipeline + /// is a string in a form of : + /// PassName '<' parameter-list '>' + /// + /// Parameter list is being parsed by the parser callable argument, \p Parser, + /// It takes a string-ref of parameters and returns either StringError or a + /// parameter list in a form of a custom parameters type, all wrapped into + /// Expected<> template class. + /// + template <typename ParametersParseCallableT> + static auto parsePassParameters(ParametersParseCallableT &&Parser, + StringRef Name, StringRef PassName) + -> decltype(Parser(StringRef{})) { + using ParametersT = typename decltype(Parser(StringRef{}))::value_type; + + StringRef Params = Name; + if (!Params.consume_front(PassName)) { + llvm_unreachable( + "unable to strip pass name from parametrized pass specification"); + } + if (!Params.empty() && + (!Params.consume_front("<") || !Params.consume_back(">"))) { + llvm_unreachable("invalid format for parametrized pass name"); + } + + Expected<ParametersT> Result = Parser(Params); + assert((Result || Result.template errorIsA<StringError>()) && + "Pass parameter parser can only return StringErrors."); + return Result; + } + + /// Handle passes only accept one bool-valued parameter. + /// + /// \return false when Params is empty. + static Expected<bool> parseSinglePassOption(StringRef Params, + StringRef OptionName, + StringRef PassName); + private: // O1 pass pipeline FunctionPassManager diff --git a/llvm/include/llvm/Passes/TargetPassRegistry.inc b/llvm/include/llvm/Passes/TargetPassRegistry.inc new file mode 100644 index 0000000000000000000000000000000000000000..b618331c69988e2e62e5b79d026ae7712ff228df --- /dev/null +++ b/llvm/include/llvm/Passes/TargetPassRegistry.inc @@ -0,0 +1,194 @@ +//===- TargetPassRegistry.inc - Registry of passes --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is used as the registry of passes in registerPassBuilderCallbacks +// Just put the following lines in the body of registerPassBuilderCallbacks: +// #define GET_PASS_REGISTRY "<Target>PassRegistry.def" +// #include "llvm/Passes/TargetPassRegistry.inc" +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +#ifdef GET_PASS_REGISTRY + +#if !__has_include(GET_PASS_REGISTRY) +#error "must provide <Target>PassRegistry.def" +#endif + +if (PopulateClassToPassNames) { + auto *PIC = PB.getPassInstrumentationCallbacks(); + +#define ADD_CLASS_PASS_TO_PASS_NAME(NAME, CREATE_PASS) \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); +#define ADD_CLASS_PASS_TO_PASS_NAME_WITH_PARAMS(NAME, CLASS) \ + PIC->addClassToPassName(CLASS, NAME); + +#define MODULE_ANALYSIS(NAME, CREATE_PASS) \ + ADD_CLASS_PASS_TO_PASS_NAME(NAME, CREATE_PASS) +#define MODULE_PASS(NAME, CREATE_PASS) \ + ADD_CLASS_PASS_TO_PASS_NAME(NAME, CREATE_PASS) +#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \ + ADD_CLASS_PASS_TO_PASS_NAME_WITH_PARAMS(NAME, CLASS) +#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ + ADD_CLASS_PASS_TO_PASS_NAME(NAME, CREATE_PASS) +#define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) \ + ADD_CLASS_PASS_TO_PASS_NAME(NAME, CREATE_PASS) +#define FUNCTION_PASS(NAME, CREATE_PASS) \ + ADD_CLASS_PASS_TO_PASS_NAME(NAME, CREATE_PASS) +#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \ + ADD_CLASS_PASS_TO_PASS_NAME_WITH_PARAMS(NAME, CLASS) +#define LOOP_ANALYSIS(NAME, CREATE_PASS) \ + ADD_CLASS_PASS_TO_PASS_NAME(NAME, CREATE_PASS) +#define LOOP_PASS(NAME, CREATE_PASS) \ + ADD_CLASS_PASS_TO_PASS_NAME(NAME, CREATE_PASS) +#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ + ADD_CLASS_PASS_TO_PASS_NAME(NAME, CREATE_PASS) +#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) \ + ADD_CLASS_PASS_TO_PASS_NAME(NAME, CREATE_PASS) +#define MACHINE_FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, \ + PARAMS) \ + ADD_CLASS_PASS_TO_PASS_NAME_WITH_PARAMS(NAME, CLASS) +#include GET_PASS_REGISTRY +#undef MODULE_ANALYSIS +#undef MODULE_PASS +#undef MODULE_PASS_WITH_PARAMS +#undef FUNCTION_ANALYSIS +#undef FUNCTION_ALIAS_ANALYSIS +#undef FUNCTION_PASS +#undef FUNCTION_PASS_WITH_PARAMS +#undef LOOP_ANALYSIS +#undef LOOP_PASS +#undef MACHINE_FUNCTION_ANALYSIS +#undef MACHINE_FUNCTION_PASS +#undef MACHINE_FUNCTION_PASS_WITH_PARAMS +#undef ADD_CLASS_PASS_TO_PASS_NAME +#undef ADD_CLASS_PASS_TO_PASS_NAME_WITH_PARAMS +} + +#define ADD_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + PM.addPass(CREATE_PASS); \ + return true; \ + } + +#define ADD_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \ + if (PassBuilder::checkParametrizedPassName(Name, NAME)) { \ + auto Params = PassBuilder::parsePassParameters(PARSER, Name, NAME); \ + if (!Params) { \ + errs() << NAME ": " << toString(Params.takeError()) << '\n'; \ + return false; \ + } \ + PM.addPass(CREATE_PASS(Params.get())); \ + return true; \ + } + +PB.registerPipelineParsingCallback([=](StringRef Name, ModulePassManager &PM, + ArrayRef<PassBuilder::PipelineElement>) { +#define MODULE_PASS(NAME, CREATE_PASS) ADD_PASS(NAME, CREATE_PASS) +#include GET_PASS_REGISTRY +#undef MODULE_PASS + return false; +}); + +PB.registerPipelineParsingCallback([=](StringRef Name, ModulePassManager &PM, + ArrayRef<PassBuilder::PipelineElement>) { +#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \ + ADD_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) +#include GET_PASS_REGISTRY +#undef MODULE_PASS_WITH_PARAMS + return false; +}); + +PB.registerPipelineParsingCallback([=](StringRef Name, FunctionPassManager &PM, + ArrayRef<PassBuilder::PipelineElement>) { +#define FUNCTION_PASS(NAME, CREATE_PASS) ADD_PASS(NAME, CREATE_PASS) +#include GET_PASS_REGISTRY +#undef FUNCTION_PASS + return false; +}); + +PB.registerPipelineParsingCallback([=](StringRef Name, FunctionPassManager &PM, + ArrayRef<PassBuilder::PipelineElement>) { +#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \ + ADD_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) +#include GET_PASS_REGISTRY +#undef FUNCTION_PASS_WITH_PARAMS + return false; +}); + +PB.registerPipelineParsingCallback([=](StringRef Name, LoopPassManager &PM, + ArrayRef<PassBuilder::PipelineElement>) { +#define LOOP_PASS(NAME, CREATE_PASS) ADD_PASS(NAME, CREATE_PASS) +#include GET_PASS_REGISTRY + return false; +}); + +PB.registerPipelineParsingCallback([=](StringRef Name, + MachineFunctionPassManager &PM, + ArrayRef<PassBuilder::PipelineElement>) { +#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) ADD_PASS(NAME, CREATE_PASS) +#include GET_PASS_REGISTRY + return false; +}); + +PB.registerPipelineParsingCallback([=](StringRef Name, FunctionPassManager &PM, + ArrayRef<PassBuilder::PipelineElement>) { +#define MACHINE_FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, \ + PARAMS) \ + ADD_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) +#include GET_PASS_REGISTRY +#undef MACHINE_FUNCTION_PASS_WITH_PARAMS + return false; +}); + +#undef ADD_PASS +#undef ADD_PASS_WITH_PARAMS + +PB.registerAnalysisRegistrationCallback([](ModuleAnalysisManager &AM) { +#define MODULE_ANALYSIS(NAME, CREATE_PASS) \ + AM.registerPass([&] { return CREATE_PASS; }); +#include GET_PASS_REGISTRY +#undef MODULE_ANALYSIS +}); + +PB.registerAnalysisRegistrationCallback([](FunctionAnalysisManager &AM) { +#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ + AM.registerPass([&] { return CREATE_PASS; }); +#include GET_PASS_REGISTRY +#undef FUNCTION_ANALYSIS +}); + +PB.registerParseAACallback([](StringRef Name, AAManager &AM) { +#define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + AM.registerFunctionAnalysis< \ + std::remove_reference_t<decltype(CREATE_PASS)>>(); \ + return true; \ + } +#include GET_PASS_REGISTRY +#undef FUNCTION_ALIAS_ANALYSIS + return false; +}); + +PB.registerAnalysisRegistrationCallback([](LoopAnalysisManager &AM) { +#define LOOP_ANALYSIS(NAME, CREATE_PASS) \ + AM.registerPass([&] { return CREATE_PASS; }); +#include GET_PASS_REGISTRY +#undef LOOP_ANALYSIS +}); + +PB.registerAnalysisRegistrationCallback([](MachineFunctionAnalysisManager &AM) { +#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ + AM.registerPass([&] { return CREATE_PASS; }); +#include GET_PASS_REGISTRY +#undef MACHINE_FUNCTION_ANALYSIS +}); + +#undef GET_PASS_REGISTRY +#endif // GET_PASS_REGISTRY diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h index 346ca4ad2eb3143a5e33751352c3484b316bef6b..f05b90114d75a682cea08c07361a295fe741573d 100644 --- a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h +++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h @@ -184,7 +184,7 @@ public: private: std::vector<std::string> Filenames; std::vector<ProfileMappingRecord> MappingRecords; - InstrProfSymtab ProfileNames; + std::unique_ptr<InstrProfSymtab> ProfileNames; size_t CurrentRecord = 0; std::vector<StringRef> FunctionsFilenames; std::vector<CounterExpression> Expressions; @@ -195,8 +195,9 @@ private: // D69471, which can split up function records into multiple sections on ELF. FuncRecordsStorage FuncRecords; - BinaryCoverageReader(FuncRecordsStorage &&FuncRecords) - : FuncRecords(std::move(FuncRecords)) {} + BinaryCoverageReader(std::unique_ptr<InstrProfSymtab> Symtab, + FuncRecordsStorage &&FuncRecords) + : ProfileNames(std::move(Symtab)), FuncRecords(std::move(FuncRecords)) {} public: BinaryCoverageReader(const BinaryCoverageReader &) = delete; @@ -209,12 +210,10 @@ public: SmallVectorImpl<object::BuildIDRef> *BinaryIDs = nullptr); static Expected<std::unique_ptr<BinaryCoverageReader>> - createCoverageReaderFromBuffer(StringRef Coverage, - FuncRecordsStorage &&FuncRecords, - InstrProfSymtab &&ProfileNames, - uint8_t BytesInAddress, - llvm::endianness Endian, - StringRef CompilationDir = ""); + createCoverageReaderFromBuffer( + StringRef Coverage, FuncRecordsStorage &&FuncRecords, + std::unique_ptr<InstrProfSymtab> ProfileNamesPtr, uint8_t BytesInAddress, + llvm::endianness Endian, StringRef CompilationDir = ""); Error readNextRecord(CoverageMappingRecord &Record) override; }; diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h index 25ec06a7392027b6a78198e05bbf560a111b50c9..eb3c10bcba1ca717514877af820969a29ecc3d7e 100644 --- a/llvm/include/llvm/ProfileData/InstrProf.h +++ b/llvm/include/llvm/ProfileData/InstrProf.h @@ -17,6 +17,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitmaskEnum.h" +#include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" @@ -89,6 +90,9 @@ inline StringRef getInstrProfValueProfMemOpFuncName() { /// Return the name prefix of variables containing instrumented function names. inline StringRef getInstrProfNameVarPrefix() { return "__profn_"; } +/// Return the name prefix of variables containing virtual table profile data. +inline StringRef getInstrProfVTableVarPrefix() { return "__profvt_"; } + /// Return the name prefix of variables containing per-function control data. inline StringRef getInstrProfDataVarPrefix() { return "__profd_"; } @@ -106,9 +110,9 @@ inline StringRef getInstrProfVNodesVarName() { return "__llvm_prf_vnodes"; } /// Return the name of the variable holding the strings (possibly compressed) /// of all function's PGO names. -inline StringRef getInstrProfNamesVarName() { - return "__llvm_prf_nm"; -} +inline StringRef getInstrProfNamesVarName() { return "__llvm_prf_nm"; } + +inline StringRef getInstrProfVTableNamesVarName() { return "__llvm_prf_vnm"; } /// Return the name of a covarage mapping variable (internal linkage) /// for each instrumented source module. Such variables are allocated @@ -140,7 +144,8 @@ inline StringRef getInstrProfRegFuncName() { return "__llvm_profile_register_function"; } -/// Return the name of the runtime interface that registers the PGO name strings. +/// Return the name of the runtime interface that registers the PGO name +/// strings. inline StringRef getInstrProfNamesRegFuncName() { return "__llvm_profile_register_names_function"; } @@ -246,6 +251,9 @@ Error collectGlobalObjectNameStrings(ArrayRef<std::string> NameStrs, Error collectPGOFuncNameStrings(ArrayRef<GlobalVariable *> NameVars, std::string &Result, bool doCompression = true); +Error collectVTableStrings(ArrayRef<GlobalVariable *> VTables, + std::string &Result, bool doCompression); + /// Check if INSTR_PROF_RAW_VERSION_VAR is defined. This global is only being /// set in IR PGO compilation. bool isIRPGOFlagSet(const Module *M); @@ -275,7 +283,7 @@ void annotateValueSite(Module &M, Instruction &Inst, /// Extract the value profile data from \p Inst which is annotated with /// value profile meta data. Return false if there is no value data annotated, -/// otherwise return true. +/// otherwise return true. bool getValueProfDataFromInst(const Instruction &Inst, InstrProfValueKind ValueKind, uint32_t MaxNumValueData, @@ -283,11 +291,23 @@ bool getValueProfDataFromInst(const Instruction &Inst, uint32_t &ActualNumValueData, uint64_t &TotalC, bool GetNoICPValue = false); +/// Extract the value profile data from \p Inst and returns them if \p Inst is +/// annotated with value profile data. Returns nullptr otherwise. It's similar +/// to `getValueProfDataFromInst` above except that an array is allocated only +/// after a preliminary checking that the value profiles of kind `ValueKind` +/// exist. +std::unique_ptr<InstrProfValueData[]> +getValueProfDataFromInst(const Instruction &Inst, InstrProfValueKind ValueKind, + uint32_t MaxNumValueData, uint32_t &ActualNumValueData, + uint64_t &TotalC, bool GetNoICPValue = false); + inline StringRef getPGOFuncNameMetadataName() { return "PGOFuncName"; } /// Return the PGOFuncName meta data associated with a function. MDNode *getPGOFuncNameMetadata(const Function &F); +std::string getPGOName(const GlobalVariable &V, bool InLTO = false); + /// Create the PGOFuncName meta data if PGOFuncName is different from /// function's raw name. This should only apply to internal linkage functions /// declared by users only. @@ -295,7 +315,7 @@ void createPGOFuncNameMetadata(Function &F, StringRef PGOFuncName); /// Check if we can use Comdat for profile variables. This will eliminate /// the duplicated profile variables for Comdat functions. -bool needsComdatForCounter(const Function &F, const Module &M); +bool needsComdatForCounter(const GlobalObject &GV, const Module &M); /// An enum describing the attributes of an instrumented profile. enum class InstrProfKind { @@ -431,23 +451,34 @@ public: using AddrHashMap = std::vector<std::pair<uint64_t, uint64_t>>; private: + using AddrIntervalMap = + IntervalMap<uint64_t, uint64_t, 4, IntervalMapHalfOpenInfo<uint64_t>>; StringRef Data; uint64_t Address = 0; - // Unique name strings. + // Unique name strings. Used to ensure entries in MD5NameMap (a vector that's + // going to be sorted) has unique MD5 keys in the first place. StringSet<> NameTab; + // Records the unique virtual table names. This is used by InstrProfWriter to + // write out an on-disk chained hash table of virtual table names. + // InstrProfWriter stores per function profile data (keyed by function names) + // so it doesn't use a StringSet for function names. + StringSet<> VTableNames; // A map from MD5 keys to function name strings. std::vector<std::pair<uint64_t, StringRef>> MD5NameMap; + // A map from MD5 keys to function define. We only populate this map // when build the Symtab from a Module. std::vector<std::pair<uint64_t, Function *>> MD5FuncMap; // A map from function runtime address to function name MD5 hash. // This map is only populated and used by raw instr profile reader. AddrHashMap AddrToMD5Map; + + AddrIntervalMap::Allocator VTableAddrMapAllocator; + // This map is only populated and used by raw instr profile reader. + AddrIntervalMap VTableAddrMap; bool Sorted = false; - static StringRef getExternalSymbol() { - return "** External Symbol **"; - } + static StringRef getExternalSymbol() { return "** External Symbol **"; } // Returns the canonial name of the given PGOName. In a canonical name, all // suffixes that begins with "." except ".__uniq." are stripped. @@ -469,7 +500,14 @@ private: inline void finalizeSymtab(); public: - InstrProfSymtab() = default; + InstrProfSymtab() : VTableAddrMap(VTableAddrMapAllocator) {} + + // Not copyable or movable. + // Consider std::unique_ptr for move. + InstrProfSymtab(const InstrProfSymtab &) = delete; + InstrProfSymtab &operator=(const InstrProfSymtab &) = delete; + InstrProfSymtab(InstrProfSymtab &&) = delete; + InstrProfSymtab &operator=(InstrProfSymtab &&) = delete; /// Create InstrProfSymtab from an object file section which /// contains function PGO names. When section may contain raw @@ -481,9 +519,19 @@ public: /// \c NameStrings is a string composed of one of more sub-strings /// encoded in the format described in \c collectPGOFuncNameStrings. - /// This method is a wrapper to \c readPGOFuncNameStrings method. + /// This method is a wrapper to \c readAndDecodeStrings method. Error create(StringRef NameStrings); + /// Initialize symtab states with function names and vtable names. \c + /// FuncNameStrings is a string composed of one or more encoded function name + /// strings, and \c VTableNameStrings composes of one or more encoded vtable + /// names. This interface is solely used by raw profile reader. + Error create(StringRef FuncNameStrings, StringRef VTableNameStrings); + + /// Initialize 'this' with the set of vtable names encoded in + /// \c CompressedVTableNames. + Error initVTableNamesFromCompressedStrings(StringRef CompressedVTableNames); + /// This interface is used by reader of CoverageMapping test /// format. inline Error create(StringRef D, uint64_t BaseAddr); @@ -496,32 +544,69 @@ public: /// Create InstrProfSymtab from a set of names iteratable from /// \p IterRange. This interface is used by IndexedProfReader. - template <typename NameIterRange> Error create(const NameIterRange &IterRange); - - /// Update the symtab by adding \p FuncName to the table. This interface - /// is used by the raw and text profile readers. - Error addFuncName(StringRef FuncName) { - if (FuncName.empty()) + template <typename NameIterRange> + Error create(const NameIterRange &IterRange); + + /// Create InstrProfSymtab from a set of function names and vtable + /// names iteratable from \p IterRange. This interface is used by + /// IndexedProfReader. + template <typename FuncNameIterRange, typename VTableNameIterRange> + Error create(const FuncNameIterRange &FuncIterRange, + const VTableNameIterRange &VTableIterRange); + + Error addSymbolName(StringRef SymbolName) { + if (SymbolName.empty()) return make_error<InstrProfError>(instrprof_error::malformed, - "function name is empty"); - auto Ins = NameTab.insert(FuncName); + "symbol name is empty"); + + // Insert into NameTab so that MD5NameMap (a vector that will be sorted) + // won't have duplicated entries in the first place. + auto Ins = NameTab.insert(SymbolName); if (Ins.second) { MD5NameMap.push_back(std::make_pair( - IndexedInstrProf::ComputeHash(FuncName), Ins.first->getKey())); + IndexedInstrProf::ComputeHash(SymbolName), Ins.first->getKey())); Sorted = false; } return Error::success(); } + /// The method name is kept since there are many callers. + /// It just forwards to 'addSymbolName'. + Error addFuncName(StringRef FuncName) { return addSymbolName(FuncName); } + + /// Adds VTableName as a known symbol, and inserts it to a map that + /// tracks all vtable names. + Error addVTableName(StringRef VTableName) { + if (Error E = addSymbolName(VTableName)) + return E; + + // Record VTableName. InstrProfWriter uses this set. The comment around + // class member explains why. + VTableNames.insert(VTableName); + return Error::success(); + } + + const StringSet<> &getVTableNames() const { return VTableNames; } + /// Map a function address to its name's MD5 hash. This interface /// is only used by the raw profiler reader. void mapAddress(uint64_t Addr, uint64_t MD5Val) { AddrToMD5Map.push_back(std::make_pair(Addr, MD5Val)); } + /// Map the address range (i.e., [start_address, end_address)) of a variable + /// to its names' MD5 hash. This interface is only used by the raw profile + /// reader. + void mapVTableAddress(uint64_t StartAddr, uint64_t EndAddr, uint64_t MD5Val) { + VTableAddrMap.insert(StartAddr, EndAddr, MD5Val); + } + /// Return a function's hash, or 0, if the function isn't in this SymTab. uint64_t getFunctionHashFromAddress(uint64_t Address); + /// Return a vtable's hash, or 0 if the vtable doesn't exist in this SymTab. + uint64_t getVTableHashFromAddress(uint64_t Address); + /// Return function's PGO name from the function name's symbol /// address in the object file. If an error occurs, return /// an empty string. @@ -567,6 +652,24 @@ Error InstrProfSymtab::create(const NameIterRange &IterRange) { return Error::success(); } +template <typename FuncNameIterRange, typename VTableNameIterRange> +Error InstrProfSymtab::create(const FuncNameIterRange &FuncIterRange, + const VTableNameIterRange &VTableIterRange) { + // Iterate elements by StringRef rather than by const reference. + // StringRef is small enough, so the loop is efficient whether + // element in the range is std::string or StringRef. + for (StringRef Name : FuncIterRange) + if (Error E = addFuncName(Name)) + return E; + + for (StringRef VTableName : VTableIterRange) + if (Error E = addVTableName(VTableName)) + return E; + + finalizeSymtab(); + return Error::success(); +} + void InstrProfSymtab::finalizeSymtab() { if (Sorted) return; @@ -870,6 +973,8 @@ private: return ValueData->IndirectCallSites; case IPVK_MemOPSize: return ValueData->MemOPSizes; + case IPVK_VTableTarget: + return ValueData->VTableTargets; default: llvm_unreachable("Unknown value kind!"); } @@ -1055,9 +1160,15 @@ inline uint64_t ComputeHash(StringRef K) { return ComputeHash(HashType, K); } // as appropriate when updating the indexed profile format. struct Header { uint64_t Magic; + // The lower 32 bits specify the version of the indexed profile. + // The most significant 32 bits are reserved to specify the variant types of + // the profile. uint64_t Version; uint64_t Unused; // Becomes unused since version 4 uint64_t HashType; + // This field records the offset of this hash table's metadata (i.e., the + // number of buckets and entries), which follows right after the payload of + // the entire hash table. uint64_t HashOffset; uint64_t MemProfOffset; uint64_t BinaryIdOffset; @@ -1182,6 +1293,7 @@ namespace RawInstrProf { // Version 7: Reorder binary id and include version in signature. // Version 8: Use relative counter pointer. // Version 9: Added relative bitmap bytes pointer and count used by MC/DC. +// Version 10: Added vtable, a new type of value profile data. const uint64_t Version = INSTR_PROF_RAW_VERSION; template <class IntPtrT> inline uint64_t getMagic(); diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h index cfde5d3fc77d65b42c066cd9d8c0a837e3945750..e46570af3873f98290d2473e68bec55203e38b8a 100644 --- a/llvm/include/llvm/ProfileData/InstrProfReader.h +++ b/llvm/include/llvm/ProfileData/InstrProfReader.h @@ -626,6 +626,12 @@ public: InstrProfKind getProfileKind() const override; Error populateSymtab(InstrProfSymtab &Symtab) override { + // FIXME: the create method calls 'finalizeSymtab' and sorts a bunch of + // arrays/maps. Since there are other data sources other than 'HashTable' to + // populate a symtab, it might make sense to have something like this + // 1. Let each data source populate Symtab and init the arrays/maps without + // calling 'finalizeSymtab' + // 2. Call 'finalizeSymtab' once to get all arrays/maps sorted if needed. return Symtab.create(HashTable->keys()); } }; diff --git a/llvm/include/llvm/ProfileData/InstrProfWriter.h b/llvm/include/llvm/ProfileData/InstrProfWriter.h index f70574d1f756325b3c4b311639e09cd373330df3..4b42392bc1e061dc28d60c496ccba92fb0a4d506 100644 --- a/llvm/include/llvm/ProfileData/InstrProfWriter.h +++ b/llvm/include/llvm/ProfileData/InstrProfWriter.h @@ -63,6 +63,9 @@ private: // List of binary ids. std::vector<llvm::object::BuildID> BinaryIds; + // Read the vtable names from raw instr profile reader. + StringSet<> VTableNames; + // An enum describing the attributes of the profile. InstrProfKind ProfileKind = InstrProfKind::Unknown; // Use raw pointer here for the incomplete type object. @@ -75,11 +78,14 @@ private: // deployment of newer versions of llvm-profdata. bool WritePrevVersion = false; + // The MemProf version we should write. + memprof::IndexedVersion MemProfVersionRequested; + public: - InstrProfWriter(bool Sparse = false, - uint64_t TemporalProfTraceReservoirSize = 0, - uint64_t MaxTemporalProfTraceLength = 0, - bool WritePrevVersion = false); + InstrProfWriter( + bool Sparse = false, uint64_t TemporalProfTraceReservoirSize = 0, + uint64_t MaxTemporalProfTraceLength = 0, bool WritePrevVersion = false, + memprof::IndexedVersion MemProfVersionRequested = memprof::Version0); ~InstrProfWriter(); StringMap<ProfilingData> &getProfileData() { return FunctionData; } @@ -92,6 +98,7 @@ public: void addRecord(NamedInstrProfRecord &&I, function_ref<void(Error)> Warn) { addRecord(std::move(I), 1, Warn); } + void addVTableName(StringRef VTableName) { VTableNames.insert(VTableName); } /// Add \p SrcTraces using reservoir sampling where \p SrcStreamSize is the /// total number of temporal profiling traces the source has seen. diff --git a/llvm/include/llvm/ProfileData/MemProf.h b/llvm/include/llvm/ProfileData/MemProf.h index 37c19094bc2a630bc1de0ce152098144a5d377c1..ff00900a1466a8c3e3147da551a1284b51b4dd13 100644 --- a/llvm/include/llvm/ProfileData/MemProf.h +++ b/llvm/include/llvm/ProfileData/MemProf.h @@ -1,6 +1,7 @@ #ifndef LLVM_PROFILEDATA_MEMPROF_H_ #define LLVM_PROFILEDATA_MEMPROF_H_ +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/STLFunctionalExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/GlobalValue.h" @@ -15,6 +16,20 @@ namespace llvm { namespace memprof { +// The versions of the indexed MemProf format +enum IndexedVersion : uint64_t { + // Version 0: This version didn't have a version field. + Version0 = 0, + // Version 1: Added a version field to the header. + Version1 = 1, +}; + +constexpr uint64_t MinimumSupportedVersion = Version0; +constexpr uint64_t MaximumSupportedVersion = Version1; + +// Verify that the minimum and maximum satisfy the obvious constraint. +static_assert(MinimumSupportedVersion <= MaximumSupportedVersion); + enum class Meta : uint64_t { Start = 0, #define MIBEntryDef(NameTag, Name, Type) NameTag, @@ -252,18 +267,26 @@ struct Frame { } }; +// A type representing the index into the table of call stacks. +using CallStackId = uint64_t; + // Holds allocation information in a space efficient format where frames are // represented using unique identifiers. struct IndexedAllocationInfo { // The dynamic calling context for the allocation in bottom-up (leaf-to-root) // order. Frame contents are stored out-of-line. + // TODO: Remove once we fully transition to CSId. llvm::SmallVector<FrameId> CallStack; + // Conceptually the same as above. We are going to keep both CallStack and + // CallStackId while we are transitioning from CallStack to CallStackId. + CallStackId CSId = 0; // The statistics obtained from the runtime for the allocation. PortableMemInfoBlock Info; IndexedAllocationInfo() = default; - IndexedAllocationInfo(ArrayRef<FrameId> CS, const MemInfoBlock &MB) - : CallStack(CS.begin(), CS.end()), Info(MB) {} + IndexedAllocationInfo(ArrayRef<FrameId> CS, CallStackId CSId, + const MemInfoBlock &MB) + : CallStack(CS.begin(), CS.end()), CSId(CSId), Info(MB) {} // Returns the size in bytes when this allocation info struct is serialized. size_t serializedSize() const { @@ -622,6 +645,21 @@ public: return Frame::deserialize(D); } }; + +// Compute a CallStackId for a given call stack. +CallStackId hashCallStack(ArrayRef<FrameId> CS); + +// Verify that each CallStackId is computed with hashCallStack. This function +// is intended to help transition from CallStack to CSId in +// IndexedAllocationInfo. +void verifyIndexedMemProfRecord(const IndexedMemProfRecord &Record); + +// Verify that each CallStackId is computed with hashCallStack. This function +// is intended to help transition from CallStack to CSId in +// IndexedAllocationInfo. +void verifyFunctionProfileData( + const llvm::MapVector<GlobalValue::GUID, IndexedMemProfRecord> + &FunctionProfileData); } // namespace memprof } // namespace llvm diff --git a/llvm/include/llvm/Support/AMDHSAKernelDescriptor.h b/llvm/include/llvm/Support/AMDHSAKernelDescriptor.h index 84cac3ef700e05f66238de010df0e2b5b1b0aad7..a119b0724d677fd8b0964be2229e2b0a9b2621cb 100644 --- a/llvm/include/llvm/Support/AMDHSAKernelDescriptor.h +++ b/llvm/include/llvm/Support/AMDHSAKernelDescriptor.h @@ -46,9 +46,12 @@ // Sets bits for specified bit mask in specified destination. #ifndef AMDHSA_BITS_SET -#define AMDHSA_BITS_SET(DST, MSK, VAL) \ - DST &= ~MSK; \ - DST |= ((VAL << MSK ## _SHIFT) & MSK) +#define AMDHSA_BITS_SET(DST, MSK, VAL) \ + do { \ + auto local = VAL; \ + DST &= ~MSK; \ + DST |= ((local << MSK##_SHIFT) & MSK); \ + } while (0) #endif // AMDHSA_BITS_SET namespace llvm { diff --git a/llvm/include/llvm/Support/BalancedPartitioning.h b/llvm/include/llvm/Support/BalancedPartitioning.h index 9738e742f7f1e96d1a597196de457e9aa8458845..539d157343fbe3bc4badbd938f1988985f5781dc 100644 --- a/llvm/include/llvm/Support/BalancedPartitioning.h +++ b/llvm/include/llvm/Support/BalancedPartitioning.h @@ -142,9 +142,8 @@ private: std::optional<BPThreadPool> &TP) const; /// Run bisection iterations - void runIterations(const FunctionNodeRange Nodes, unsigned RecDepth, - unsigned LeftBucket, unsigned RightBucket, - std::mt19937 &RNG) const; + void runIterations(const FunctionNodeRange Nodes, unsigned LeftBucket, + unsigned RightBucket, std::mt19937 &RNG) const; /// Run a bisection iteration to improve the optimization goal /// \returns the total number of moved FunctionNodes diff --git a/llvm/include/llvm/Support/DXILABI.h b/llvm/include/llvm/Support/DXILABI.h index c1d81775b6711e32b1cc4d0685c4ee30771573c9..da4bea8fc46e3a14aff0182f4e8e9fbd06ab9ee0 100644 --- a/llvm/include/llvm/Support/DXILABI.h +++ b/llvm/include/llvm/Support/DXILABI.h @@ -23,20 +23,20 @@ namespace llvm { namespace dxil { enum class ParameterKind : uint8_t { - INVALID = 0, - VOID, - HALF, - FLOAT, - DOUBLE, + Invalid = 0, + Void, + Half, + Float, + Double, I1, I8, I16, I32, I64, - OVERLOAD, - CBUFFER_RET, - RESOURCE_RET, - DXIL_HANDLE, + Overload, + CBufferRet, + ResourceRet, + DXILHandle, }; /// The kind of resource for an SRV or UAV resource. Sometimes referred to as diff --git a/llvm/include/llvm/Support/FormatAdapters.h b/llvm/include/llvm/Support/FormatAdapters.h index 495205d11748b4ef8cfce575b1f282795d295663..4131e956873e9e99684ef75b31b8a792062597a2 100644 --- a/llvm/include/llvm/Support/FormatAdapters.h +++ b/llvm/include/llvm/Support/FormatAdapters.h @@ -16,13 +16,15 @@ #include "llvm/Support/raw_ostream.h" namespace llvm { -template <typename T> class FormatAdapter : public detail::format_adapter { +template <typename T> +class FormatAdapter : public support::detail::format_adapter { protected: explicit FormatAdapter(T &&Item) : Item(std::forward<T>(Item)) {} T Item; }; +namespace support { namespace detail { template <typename T> class AlignAdapter final : public FormatAdapter<T> { AlignStyle Where; @@ -80,29 +82,31 @@ public: Stream << Item; } }; -} +} // namespace detail +} // namespace support template <typename T> -detail::AlignAdapter<T> fmt_align(T &&Item, AlignStyle Where, size_t Amount, - char Fill = ' ') { - return detail::AlignAdapter<T>(std::forward<T>(Item), Where, Amount, Fill); +support::detail::AlignAdapter<T> fmt_align(T &&Item, AlignStyle Where, + size_t Amount, char Fill = ' ') { + return support::detail::AlignAdapter<T>(std::forward<T>(Item), Where, Amount, + Fill); } template <typename T> -detail::PadAdapter<T> fmt_pad(T &&Item, size_t Left, size_t Right) { - return detail::PadAdapter<T>(std::forward<T>(Item), Left, Right); +support::detail::PadAdapter<T> fmt_pad(T &&Item, size_t Left, size_t Right) { + return support::detail::PadAdapter<T>(std::forward<T>(Item), Left, Right); } template <typename T> -detail::RepeatAdapter<T> fmt_repeat(T &&Item, size_t Count) { - return detail::RepeatAdapter<T>(std::forward<T>(Item), Count); +support::detail::RepeatAdapter<T> fmt_repeat(T &&Item, size_t Count) { + return support::detail::RepeatAdapter<T>(std::forward<T>(Item), Count); } // llvm::Error values must be consumed before being destroyed. // Wrapping an error in fmt_consume explicitly indicates that the formatv_object // should take ownership and consume it. -inline detail::ErrorAdapter fmt_consume(Error &&Item) { - return detail::ErrorAdapter(std::move(Item)); +inline support::detail::ErrorAdapter fmt_consume(Error &&Item) { + return support::detail::ErrorAdapter(std::move(Item)); } } diff --git a/llvm/include/llvm/Support/FormatCommon.h b/llvm/include/llvm/Support/FormatCommon.h index 24a40c325e13148e78987c18f820affc0ca9e392..326e00936aa7c56fb52a1cbafa5f728ce1519580 100644 --- a/llvm/include/llvm/Support/FormatCommon.h +++ b/llvm/include/llvm/Support/FormatCommon.h @@ -17,13 +17,13 @@ namespace llvm { enum class AlignStyle { Left, Center, Right }; struct FmtAlign { - detail::format_adapter &Adapter; + support::detail::format_adapter &Adapter; AlignStyle Where; size_t Amount; char Fill; - FmtAlign(detail::format_adapter &Adapter, AlignStyle Where, size_t Amount, - char Fill = ' ') + FmtAlign(support::detail::format_adapter &Adapter, AlignStyle Where, + size_t Amount, char Fill = ' ') : Adapter(Adapter), Where(Where), Amount(Amount), Fill(Fill) {} void format(raw_ostream &S, StringRef Options) { diff --git a/llvm/include/llvm/Support/FormatProviders.h b/llvm/include/llvm/Support/FormatProviders.h index aa0773847161c126b9c7a28aee4a120aa1d85e08..bf489e2bfa077ef55f59a25c51e7beba42bdb25e 100644 --- a/llvm/include/llvm/Support/FormatProviders.h +++ b/llvm/include/llvm/Support/FormatProviders.h @@ -25,6 +25,7 @@ #include <type_traits> namespace llvm { +namespace support { namespace detail { template <typename T> struct use_integral_formatter @@ -98,7 +99,8 @@ protected: return Default; } }; -} +} // namespace detail +} // namespace support /// Implementation of format_provider<T> for integral arithmetic types. /// @@ -125,8 +127,8 @@ protected: template <typename T> struct format_provider< - T, std::enable_if_t<detail::use_integral_formatter<T>::value>> - : public detail::HelperFunctions { + T, std::enable_if_t<support::detail::use_integral_formatter<T>::value>> + : public support::detail::HelperFunctions { private: public: static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) { @@ -174,8 +176,8 @@ public: /// cases indicates the minimum number of nibbles to print. template <typename T> struct format_provider< - T, std::enable_if_t<detail::use_pointer_formatter<T>::value>> - : public detail::HelperFunctions { + T, std::enable_if_t<support::detail::use_pointer_formatter<T>::value>> + : public support::detail::HelperFunctions { private: public: static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) { @@ -199,7 +201,7 @@ public: template <typename T> struct format_provider< - T, std::enable_if_t<detail::use_string_formatter<T>::value>> { + T, std::enable_if_t<support::detail::use_string_formatter<T>::value>> { static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) { size_t N = StringRef::npos; if (!Style.empty() && Style.getAsInteger(10, N)) { @@ -231,8 +233,8 @@ template <> struct format_provider<Twine> { /// character. Otherwise, it is treated as an integer options string. /// template <typename T> -struct format_provider<T, - std::enable_if_t<detail::use_char_formatter<T>::value>> { +struct format_provider< + T, std::enable_if_t<support::detail::use_char_formatter<T>::value>> { static void format(const char &V, llvm::raw_ostream &Stream, StringRef Style) { if (Style.empty()) @@ -297,9 +299,9 @@ template <> struct format_provider<bool> { /// else. template <typename T> -struct format_provider<T, - std::enable_if_t<detail::use_double_formatter<T>::value>> - : public detail::HelperFunctions { +struct format_provider< + T, std::enable_if_t<support::detail::use_double_formatter<T>::value>> + : public support::detail::HelperFunctions { static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) { FloatStyle S; if (Style.consume_front("P") || Style.consume_front("p")) @@ -321,6 +323,7 @@ struct format_provider<T, } }; +namespace support { namespace detail { template <typename IterT> using IterValue = typename std::iterator_traits<IterT>::value_type; @@ -328,8 +331,10 @@ using IterValue = typename std::iterator_traits<IterT>::value_type; template <typename IterT> struct range_item_has_provider : public std::integral_constant< - bool, !uses_missing_provider<IterValue<IterT>>::value> {}; -} + bool, + !support::detail::uses_missing_provider<IterValue<IterT>>::value> {}; +} // namespace detail +} // namespace support /// Implementation of format_provider<T> for ranges. /// @@ -393,7 +398,7 @@ template <typename IterT> class format_provider<llvm::iterator_range<IterT>> { } public: - static_assert(detail::range_item_has_provider<IterT>::value, + static_assert(support::detail::range_item_has_provider<IterT>::value, "Range value_type does not have a format provider!"); static void format(const llvm::iterator_range<IterT> &V, llvm::raw_ostream &Stream, StringRef Style) { @@ -403,18 +408,18 @@ public: auto Begin = V.begin(); auto End = V.end(); if (Begin != End) { - auto Adapter = detail::build_format_adapter(*Begin); + auto Adapter = support::detail::build_format_adapter(*Begin); Adapter.format(Stream, ArgStyle); ++Begin; } while (Begin != End) { Stream << Sep; - auto Adapter = detail::build_format_adapter(*Begin); + auto Adapter = support::detail::build_format_adapter(*Begin); Adapter.format(Stream, ArgStyle); ++Begin; } } }; -} +} // namespace llvm #endif diff --git a/llvm/include/llvm/Support/FormatVariadic.h b/llvm/include/llvm/Support/FormatVariadic.h index ddd80d89f1cddd80faf32a5131827fb7b296543a..595f2cf559a428b2618c0dca53d1993eeba55e6d 100644 --- a/llvm/include/llvm/Support/FormatVariadic.h +++ b/llvm/include/llvm/Support/FormatVariadic.h @@ -66,7 +66,7 @@ struct ReplacementItem { class formatv_object_base { protected: StringRef Fmt; - ArrayRef<detail::format_adapter *> Adapters; + ArrayRef<support::detail::format_adapter *> Adapters; static bool consumeFieldLayout(StringRef &Spec, AlignStyle &Where, size_t &Align, char &Pad); @@ -75,7 +75,7 @@ protected: splitLiteralAndReplacement(StringRef Fmt); formatv_object_base(StringRef Fmt, - ArrayRef<detail::format_adapter *> Adapters) + ArrayRef<support::detail::format_adapter *> Adapters) : Fmt(Fmt), Adapters(Adapters) {} formatv_object_base(formatv_object_base const &rhs) = delete; @@ -130,7 +130,7 @@ template <typename Tuple> class formatv_object : public formatv_object_base { // of the parameters, we have to own the storage for the parameters here, and // have the base class store type-erased pointers into this tuple. Tuple Parameters; - std::array<detail::format_adapter *, std::tuple_size<Tuple>::value> + std::array<support::detail::format_adapter *, std::tuple_size<Tuple>::value> ParameterPointers; // The parameters are stored in a std::tuple, which does not provide runtime @@ -142,8 +142,8 @@ template <typename Tuple> class formatv_object : public formatv_object_base { // std::array<Base*>. struct create_adapters { template <typename... Ts> - std::array<detail::format_adapter *, std::tuple_size<Tuple>::value> - operator()(Ts &... Items) { + std::array<support::detail::format_adapter *, std::tuple_size<Tuple>::value> + operator()(Ts &...Items) { return {{&Items...}}; } }; @@ -248,13 +248,14 @@ public: // the details of what that is are undefined. // template <typename... Ts> -inline auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object<decltype( - std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...))> { - using ParamTuple = decltype( - std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...)); +inline auto formatv(const char *Fmt, Ts &&...Vals) + -> formatv_object<decltype(std::make_tuple( + support::detail::build_format_adapter(std::forward<Ts>(Vals))...))> { + using ParamTuple = decltype(std::make_tuple( + support::detail::build_format_adapter(std::forward<Ts>(Vals))...)); return formatv_object<ParamTuple>( - Fmt, - std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...)); + Fmt, std::make_tuple(support::detail::build_format_adapter( + std::forward<Ts>(Vals))...)); } } // end namespace llvm diff --git a/llvm/include/llvm/Support/FormatVariadicDetails.h b/llvm/include/llvm/Support/FormatVariadicDetails.h index 068c327df396781b066a082932711c1c473ff015..a221fcadbd3c7485d429a3f1ed484cff96550fd7 100644 --- a/llvm/include/llvm/Support/FormatVariadicDetails.h +++ b/llvm/include/llvm/Support/FormatVariadicDetails.h @@ -19,6 +19,7 @@ namespace llvm { template <typename T, typename Enable = void> struct format_provider {}; class Error; +namespace support { namespace detail { class format_adapter { virtual void anchor(); @@ -156,7 +157,8 @@ std::enable_if_t<uses_missing_provider<T>::value, missing_format_adapter<T>> build_format_adapter(T &&) { return missing_format_adapter<T>(); } -} -} +} // namespace detail +} // namespace support +} // namespace llvm #endif diff --git a/llvm/include/llvm/Support/FormattedStream.h b/llvm/include/llvm/Support/FormattedStream.h index 5f937cfa798408a817baf0cf76e83f6a81d60341..850a18dbb94121758ce9e47749d27432c2acab03 100644 --- a/llvm/include/llvm/Support/FormattedStream.h +++ b/llvm/include/llvm/Support/FormattedStream.h @@ -52,6 +52,10 @@ class formatted_raw_ostream : public raw_ostream { /// have the rest of it. SmallString<4> PartialUTF8Char; + /// DisableScan - Temporarily disable scanning of output. Used to ignore color + /// codes. + bool DisableScan; + void write_impl(const char *Ptr, size_t Size) override; /// current_pos - Return the current position within the stream, @@ -89,9 +93,33 @@ class formatted_raw_ostream : public raw_ostream { SetUnbuffered(); TheStream->SetUnbuffered(); + enable_colors(TheStream->colors_enabled()); + Scanned = nullptr; } + void PreDisableScan() { + assert(!DisableScan); + ComputePosition(getBufferStart(), GetNumBytesInBuffer()); + assert(PartialUTF8Char.empty()); + DisableScan = true; + } + + void PostDisableScan() { + assert(DisableScan); + DisableScan = false; + Scanned = getBufferStart() + GetNumBytesInBuffer(); + } + + struct DisableScanScope { + formatted_raw_ostream *S; + + DisableScanScope(formatted_raw_ostream *FRO) : S(FRO) { + S->PreDisableScan(); + } + ~DisableScanScope() { S->PostDisableScan(); } + }; + public: /// formatted_raw_ostream - Open the specified file for /// writing. If an error occurs, information about the error is @@ -104,12 +132,12 @@ public: /// underneath it. /// formatted_raw_ostream(raw_ostream &Stream) - : TheStream(nullptr), Position(0, 0) { + : TheStream(nullptr), Position(0, 0), DisableScan(false) { setStream(Stream); } - explicit formatted_raw_ostream() : TheStream(nullptr), Position(0, 0) { - Scanned = nullptr; - } + explicit formatted_raw_ostream() + : TheStream(nullptr), Position(0, 0), Scanned(nullptr), + DisableScan(false) {} ~formatted_raw_ostream() override { flush(); @@ -136,17 +164,26 @@ public: } raw_ostream &resetColor() override { - TheStream->resetColor(); + if (colors_enabled()) { + DisableScanScope S(this); + raw_ostream::resetColor(); + } return *this; } raw_ostream &reverseColor() override { - TheStream->reverseColor(); + if (colors_enabled()) { + DisableScanScope S(this); + raw_ostream::reverseColor(); + } return *this; } raw_ostream &changeColor(enum Colors Color, bool Bold, bool BG) override { - TheStream->changeColor(Color, Bold, BG); + if (colors_enabled()) { + DisableScanScope S(this); + raw_ostream::changeColor(Color, Bold, BG); + } return *this; } diff --git a/llvm/include/llvm/Support/HexagonAttributeParser.h b/llvm/include/llvm/Support/HexagonAttributeParser.h new file mode 100644 index 0000000000000000000000000000000000000000..1116dd42b1ad014625465d0296fb9313460ca269 --- /dev/null +++ b/llvm/include/llvm/Support/HexagonAttributeParser.h @@ -0,0 +1,37 @@ +//===-- HexagonAttributeParser.h - Hexagon Attribute Parser -----*- 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_SUPPORT_HEXAGONATTRIBUTEPARSER_H +#define LLVM_SUPPORT_HEXAGONATTRIBUTEPARSER_H + +#include "llvm/Support/ELFAttributeParser.h" +#include "llvm/Support/HexagonAttributes.h" + +namespace llvm { +class HexagonAttributeParser : public ELFAttributeParser { + struct DisplayHandler { + HexagonAttrs::AttrType Attribute; + Error (HexagonAttributeParser::*Routine)(unsigned); + }; + + static const DisplayHandler DisplayRoutines[]; + + Error handler(uint64_t Tag, bool &Handled) override; + +public: + HexagonAttributeParser(ScopedPrinter *SP) + : ELFAttributeParser(SP, HexagonAttrs::getHexagonAttributeTags(), + "hexagon") {} + HexagonAttributeParser() + : ELFAttributeParser(HexagonAttrs::getHexagonAttributeTags(), "hexagon") { + } +}; + +} // namespace llvm + +#endif diff --git a/llvm/include/llvm/Support/HexagonAttributes.h b/llvm/include/llvm/Support/HexagonAttributes.h new file mode 100644 index 0000000000000000000000000000000000000000..8a50d8993e633bbf9a97b1e5938c61172d570f5a --- /dev/null +++ b/llvm/include/llvm/Support/HexagonAttributes.h @@ -0,0 +1,32 @@ +//===-- HexagonAttributes.h - Qualcomm Hexagon Attributes -----------------===// +// +// 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_SUPPORT_HEXAGONATTRIBUTES_H +#define LLVM_SUPPORT_HEXAGONATTRIBUTES_H + +#include "llvm/Support/ELFAttributes.h" + +namespace llvm { +namespace HexagonAttrs { + +const TagNameMap &getHexagonAttributeTags(); + +enum AttrType : unsigned { + ARCH = 4, + HVXARCH = 5, + HVXIEEEFP = 6, + HVXQFLOAT = 7, + ZREG = 8, + AUDIO = 9, + CABAC = 10 +}; + +} // namespace HexagonAttrs +} // namespace llvm + +#endif diff --git a/llvm/include/llvm/Support/LEB128.h b/llvm/include/llvm/Support/LEB128.h index 7fc572b6ff06efc038d4dce38750ea4a6ea78bf1..c4e741549f3ff1779646231cc579389af885370a 100644 --- a/llvm/include/llvm/Support/LEB128.h +++ b/llvm/include/llvm/Support/LEB128.h @@ -200,6 +200,20 @@ inline int64_t decodeSLEB128(const uint8_t *p, unsigned *n = nullptr, return Value; } +inline uint64_t decodeULEB128AndInc(const uint8_t *&p) { + unsigned n; + auto ret = decodeULEB128(p, &n); + p += n; + return ret; +} + +inline int64_t decodeSLEB128AndInc(const uint8_t *&p) { + unsigned n; + auto ret = decodeSLEB128(p, &n); + p += n; + return ret; +} + /// Utility function to get the size of the ULEB128-encoded value. extern unsigned getULEB128Size(uint64_t Value); diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def index 899eaad5842ae0fb2848f1b9f618f1bbcf55981e..5765926d6d93d36e8495255d8f7efb3f692cda51 100644 --- a/llvm/include/llvm/Support/TargetOpcodes.def +++ b/llvm/include/llvm/Support/TargetOpcodes.def @@ -837,6 +837,11 @@ HANDLE_TARGET_OPCODE(G_MEMMOVE) HANDLE_TARGET_OPCODE(G_MEMSET) HANDLE_TARGET_OPCODE(G_BZERO) +/// llvm.trap, llvm.debugtrap and llvm.ubsantrap intrinsics +HANDLE_TARGET_OPCODE(G_TRAP) +HANDLE_TARGET_OPCODE(G_DEBUGTRAP) +HANDLE_TARGET_OPCODE(G_UBSANTRAP) + /// Vector reductions HANDLE_TARGET_OPCODE(G_VECREDUCE_SEQ_FADD) HANDLE_TARGET_OPCODE(G_VECREDUCE_SEQ_FMUL) diff --git a/llvm/include/llvm/Support/TimeProfiler.h b/llvm/include/llvm/Support/TimeProfiler.h index 454a65f70231f457d128cf96d3188d894306e70b..31f7df10916db909dc88465414e930e46ca5b2cd 100644 --- a/llvm/include/llvm/Support/TimeProfiler.h +++ b/llvm/include/llvm/Support/TimeProfiler.h @@ -86,6 +86,8 @@ class raw_pwrite_stream; struct TimeTraceProfiler; TimeTraceProfiler *getTimeTraceProfilerInstance(); +struct TimeTraceProfilerEntry; + /// Initialize the time trace profiler. /// This sets up the global \p TimeTraceProfilerInstance /// variable to be the profiler instance. @@ -120,19 +122,30 @@ Error timeTraceProfilerWrite(StringRef PreferredFileName, /// Profiler copies the string data, so the pointers can be given into /// temporaries. Time sections can be hierarchical; every Begin must have a /// matching End pair but they can nest. -void timeTraceProfilerBegin(StringRef Name, StringRef Detail); -void timeTraceProfilerBegin(StringRef Name, - llvm::function_ref<std::string()> Detail); +TimeTraceProfilerEntry *timeTraceProfilerBegin(StringRef Name, + StringRef Detail); +TimeTraceProfilerEntry * +timeTraceProfilerBegin(StringRef Name, + llvm::function_ref<std::string()> Detail); + +/// Manually begin a time section, with the given \p Name and \p Detail. +/// This starts Async Events having \p Name as a category which is shown +/// separately from other traces. See +/// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview#heading=h.jh64i9l3vwa1 +/// for more details. +TimeTraceProfilerEntry *timeTraceAsyncProfilerBegin(StringRef Name, + StringRef Detail); /// Manually end the last time section. void timeTraceProfilerEnd(); +void timeTraceProfilerEnd(TimeTraceProfilerEntry *E); /// The TimeTraceScope is a helper class to call the begin and end functions /// of the time trace profiler. When the object is constructed, it begins /// the section; and when it is destroyed, it stops it. If the time profiler /// is not initialized, the overhead is a single branch. -struct TimeTraceScope { - +class TimeTraceScope { +public: TimeTraceScope() = delete; TimeTraceScope(const TimeTraceScope &) = delete; TimeTraceScope &operator=(const TimeTraceScope &) = delete; @@ -141,20 +154,23 @@ struct TimeTraceScope { TimeTraceScope(StringRef Name) { if (getTimeTraceProfilerInstance() != nullptr) - timeTraceProfilerBegin(Name, StringRef("")); + Entry = timeTraceProfilerBegin(Name, StringRef("")); } TimeTraceScope(StringRef Name, StringRef Detail) { if (getTimeTraceProfilerInstance() != nullptr) - timeTraceProfilerBegin(Name, Detail); + Entry = timeTraceProfilerBegin(Name, Detail); } TimeTraceScope(StringRef Name, llvm::function_ref<std::string()> Detail) { if (getTimeTraceProfilerInstance() != nullptr) - timeTraceProfilerBegin(Name, Detail); + Entry = timeTraceProfilerBegin(Name, Detail); } ~TimeTraceScope() { if (getTimeTraceProfilerInstance() != nullptr) - timeTraceProfilerEnd(); + timeTraceProfilerEnd(Entry); } + +private: + TimeTraceProfilerEntry *Entry = nullptr; }; } // end namespace llvm diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h index ef1fac92c2fa4a4fd7b8aff98edeef00efaf3507..770ca8764426a4ce290f4ec0e2fdfb13e6c2df6f 100644 --- a/llvm/include/llvm/Support/VirtualFileSystem.h +++ b/llvm/include/llvm/Support/VirtualFileSystem.h @@ -929,12 +929,12 @@ private: /// Canonicalize path by removing ".", "..", "./", components. This is /// a VFS request, do not bother about symlinks in the path components /// but canonicalize in order to perform the correct entry search. - std::error_code makeCanonical(SmallVectorImpl<char> &Path) const; + std::error_code makeCanonicalForLookup(SmallVectorImpl<char> &Path) const; /// Get the File status, or error, from the underlying external file system. /// This returns the status with the originally requested name, while looking - /// up the entry using the canonical path. - ErrorOr<Status> getExternalStatus(const Twine &CanonicalPath, + /// up the entry using a potentially different path. + ErrorOr<Status> getExternalStatus(const Twine &LookupPath, const Twine &OriginalPath) const; /// Make \a Path an absolute path. @@ -1022,7 +1022,7 @@ private: llvm::SmallVectorImpl<Entry *> &Entries) const; /// Get the status for a path with the provided \c LookupResult. - ErrorOr<Status> status(const Twine &CanonicalPath, const Twine &OriginalPath, + ErrorOr<Status> status(const Twine &LookupPath, const Twine &OriginalPath, const LookupResult &Result); public: diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td index 67d405ba96fa10f506650546b0198e4a725ccf26..d0f471eb29b6fdc726b9200537ffeb577f38361b 100644 --- a/llvm/include/llvm/Target/GenericOpcodes.td +++ b/llvm/include/llvm/Target/GenericOpcodes.td @@ -1575,6 +1575,28 @@ def G_BZERO : GenericInstruction { let mayStore = true; } +//------------------------------------------------------------------------------ +// Trap intrinsics +//------------------------------------------------------------------------------ +def G_TRAP : GenericInstruction { + let OutOperandList = (outs); + let InOperandList = (ins); + let hasSideEffects = true; + let mayStore = true; +} + +def G_DEBUGTRAP : GenericInstruction { + let OutOperandList = (outs); + let InOperandList = (ins); + let hasSideEffects = true; +} + +def G_UBSANTRAP : GenericInstruction { + let OutOperandList = (outs); + let InOperandList = (ins i8imm:$kind); + let hasSideEffects = true; +} + //------------------------------------------------------------------------------ // Bitfield extraction. //------------------------------------------------------------------------------ diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td index 18db7a819540afb12b73105d3f07e01b1a0e2ec4..778ff7e437eb50b57d1eeb5e3bba7c6d3f92588d 100644 --- a/llvm/include/llvm/Target/GlobalISel/Combine.td +++ b/llvm/include/llvm/Target/GlobalISel/Combine.td @@ -179,6 +179,7 @@ def FmArcp : MIFlagEnum<"FmArcp">; def FmContract : MIFlagEnum<"FmContract">; def FmAfn : MIFlagEnum<"FmAfn">; def FmReassoc : MIFlagEnum<"FmReassoc">; +def IsExact : MIFlagEnum<"IsExact">; def MIFlags; // def not; -> Already defined as a SDNode @@ -264,7 +265,7 @@ def combine_extracted_vector_load : GICombineRule< (match (wip_match_opcode G_EXTRACT_VECTOR_ELT):$root, [{ return Helper.matchCombineExtractedVectorLoad(*${root}, ${matchinfo}); }]), (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; - + def combine_indexed_load_store : GICombineRule< (defs root:$root, indexed_load_store_matchdata:$matchinfo), (match (wip_match_opcode G_LOAD, G_SEXTLOAD, G_ZEXTLOAD, G_STORE):$root, @@ -1036,7 +1037,20 @@ def sdiv_by_const : GICombineRule< [{ return Helper.matchSDivByConst(*${root}); }]), (apply [{ Helper.applySDivByConst(*${root}); }])>; -def intdiv_combines : GICombineGroup<[udiv_by_const, sdiv_by_const]>; +def sdiv_by_pow2 : GICombineRule< + (defs root:$root), + (match (G_SDIV $dst, $x, $y, (MIFlags (not IsExact))):$root, + [{ return Helper.matchDivByPow2(*${root}, /*IsSigned=*/true); }]), + (apply [{ Helper.applySDivByPow2(*${root}); }])>; + +def udiv_by_pow2 : GICombineRule< + (defs root:$root), + (match (G_UDIV $dst, $x, $y, (MIFlags (not IsExact))):$root, + [{ return Helper.matchDivByPow2(*${root}, /*IsSigned=*/false); }]), + (apply [{ Helper.applyUDivByPow2(*${root}); }])>; + +def intdiv_combines : GICombineGroup<[udiv_by_const, sdiv_by_const, + sdiv_by_pow2, udiv_by_pow2]>; def reassoc_ptradd : GICombineRule< (defs root:$root, build_fn_matchinfo:$matchinfo), @@ -1090,12 +1104,6 @@ def mulo_by_0: GICombineRule< [{ return Helper.matchMulOBy0(*${root}, ${matchinfo}); }]), (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; -def addo_by_0: GICombineRule< - (defs root:$root, build_fn_matchinfo:$matchinfo), - (match (wip_match_opcode G_UADDO, G_SADDO):$root, - [{ return Helper.matchAddOBy0(*${root}, ${matchinfo}); }]), - (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; - // Transform (uadde x, y, 0) -> (uaddo x, y) // (sadde x, y, 0) -> (saddo x, y) // (usube x, y, 0) -> (usubo x, y) @@ -1291,6 +1299,206 @@ def match_ors : GICombineRule< [{ return Helper.matchOr(*${root}, ${matchinfo}); }]), (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; +def match_addos : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (wip_match_opcode G_SADDO, G_UADDO):$root, + [{ return Helper.matchAddOverflow(*${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; + +def match_extract_of_element_undef_vector: GICombineRule < + (defs root:$root), + (match (G_IMPLICIT_DEF $vector), + (G_EXTRACT_VECTOR_ELT $root, $vector, $idx)), + (apply (G_IMPLICIT_DEF $root)) +>; + +def match_extract_of_element_undef_index: GICombineRule < + (defs root:$root), + (match (G_IMPLICIT_DEF $idx), + (G_EXTRACT_VECTOR_ELT $root, $vector, $idx)), + (apply (G_IMPLICIT_DEF $root)) +>; + +def match_extract_of_element : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (wip_match_opcode G_EXTRACT_VECTOR_ELT):$root, + [{ return Helper.matchExtractVectorElement(*${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; + +def extract_vector_element_not_const : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_INSERT_VECTOR_ELT $src, $x, $value, $idx), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx)), + (apply (GIReplaceReg $root, $value))>; + +def extract_vector_element_different_indices : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_INSERT_VECTOR_ELT $src, $x, $value, $idx2), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx1), + [{ return Helper.matchExtractVectorElementWithDifferentIndices(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector2 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector3 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector4 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector5 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector6 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector7 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector8 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector9 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector10 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector11 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g, $h), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector12 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g, $h, $i), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector13 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g, $h, $i, $j), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector14 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector15 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector16 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR $src, $x, $y, $z, $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $k, $l, $m), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVector(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector_trunc2 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR_TRUNC $src, $x, $y), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector_trunc3 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector_trunc4 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector_trunc5 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a, $b), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector_trunc6 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a, $b, $c), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector_trunc7 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a, $b, $c, $d), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_build_vector_trunc8 : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_BUILD_VECTOR_TRUNC $src, $x, $y, $z, $a, $b, $c, $d, $e), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithBuildVectorTrunc(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + +def extract_vector_element_freeze : GICombineRule< + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_FREEZE $src, $input), + (G_EXTRACT_VECTOR_ELT $root, $src, $idx), + [{ return Helper.matchExtractVectorElementWithFreeze(${root}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>; + // Combines concat operations def concat_matchinfo : GIDefMatchData<"SmallVector<Register>">; def combine_concat_vector : GICombineRule< @@ -1299,6 +1507,37 @@ def combine_concat_vector : GICombineRule< [{ return Helper.matchCombineConcatVectors(*${root}, ${matchinfo}); }]), (apply [{ Helper.applyCombineConcatVectors(*${root}, ${matchinfo}); }])>; +// match_extract_of_element must be the first! +def vector_ops_combines: GICombineGroup<[ +match_extract_of_element_undef_vector, +match_extract_of_element_undef_index, +match_extract_of_element, +extract_vector_element_not_const, +extract_vector_element_different_indices, +extract_vector_element_build_vector2, +extract_vector_element_build_vector3, +extract_vector_element_build_vector4, +extract_vector_element_build_vector5, +extract_vector_element_build_vector7, +extract_vector_element_build_vector8, +extract_vector_element_build_vector9, +extract_vector_element_build_vector10, +extract_vector_element_build_vector11, +extract_vector_element_build_vector12, +extract_vector_element_build_vector13, +extract_vector_element_build_vector14, +extract_vector_element_build_vector15, +extract_vector_element_build_vector16, +extract_vector_element_build_vector_trunc2, +extract_vector_element_build_vector_trunc3, +extract_vector_element_build_vector_trunc4, +extract_vector_element_build_vector_trunc5, +extract_vector_element_build_vector_trunc6, +extract_vector_element_build_vector_trunc7, +extract_vector_element_build_vector_trunc8, +extract_vector_element_freeze +]>; + // FIXME: These should use the custom predicate feature once it lands. def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero, undef_to_negative_one, @@ -1326,7 +1565,7 @@ def identity_combines : GICombineGroup<[select_same_val, right_identity_zero, def const_combines : GICombineGroup<[constant_fold_fp_ops, const_ptradd_to_i2p, overlapping_and, mulo_by_2, mulo_by_0, - addo_by_0, adde_to_addo, + adde_to_addo, combine_minmax_nan]>; def known_bits_simplifications : GICombineGroup<[ @@ -1354,9 +1593,10 @@ def fma_combines : GICombineGroup<[combine_fadd_fmul_to_fmad_or_fma, def constant_fold_binops : GICombineGroup<[constant_fold_binop, constant_fold_fp_binop]>; -def all_combines : GICombineGroup<[trivial_combines, insert_vec_elt_combines, - extract_vec_elt_combines, combines_for_extload, combine_extracted_vector_load, - undef_combines, identity_combines, phi_combines, +def all_combines : GICombineGroup<[trivial_combines, vector_ops_combines, + insert_vec_elt_combines, extract_vec_elt_combines, combines_for_extload, + combine_extracted_vector_load, + undef_combines, identity_combines, phi_combines, simplify_add_to_sub, hoist_logic_op_with_same_opcode_hands, shifts_too_big, reassocs, ptr_add_immed_chain, shl_ashr_to_sext_inreg, sext_inreg_of_load, @@ -1373,8 +1613,8 @@ def all_combines : GICombineGroup<[trivial_combines, insert_vec_elt_combines, intdiv_combines, mulh_combines, redundant_neg_operands, and_or_disjoint_mask, fma_combines, fold_binop_into_select, sub_add_reg, select_to_minmax, redundant_binop_in_equality, - fsub_to_fneg, commute_constant_to_rhs, match_ands, match_ors, - combine_concat_vector, double_icmp_zero_and_or_combine]>; + fsub_to_fneg, commute_constant_to_rhs, match_ands, match_ors, + combine_concat_vector, double_icmp_zero_and_or_combine, match_addos]>; // A combine group used to for prelegalizer combiners at -O0. The combines in // this group have been selected based on experiments to balance code size and diff --git a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td index b1f3c500a1b6c54a9873721daac0f99a2d4e6279..3208c63fb42d9be69ac3709cf33ed0385ea480e2 100644 --- a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td +++ b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td @@ -90,6 +90,7 @@ def : GINodeEquiv<G_UDIVFIX, udivfix>; def : GINodeEquiv<G_SDIVFIXSAT, sdivfixsat>; def : GINodeEquiv<G_UDIVFIXSAT, udivfixsat>; def : GINodeEquiv<G_SELECT, select>; +def : GINodeEquiv<G_SELECT, vselect>; def : GINodeEquiv<G_FNEG, fneg>; def : GINodeEquiv<G_FPEXT, fpextend>; def : GINodeEquiv<G_FPTRUNC, fpround>; @@ -250,6 +251,9 @@ def : GINodeEquiv<G_ATOMICRMW_UINC_WRAP, atomic_load_uinc_wrap>; def : GINodeEquiv<G_ATOMICRMW_UDEC_WRAP, atomic_load_udec_wrap>; def : GINodeEquiv<G_FENCE, atomic_fence>; def : GINodeEquiv<G_PREFETCH, prefetch>; +def : GINodeEquiv<G_TRAP, trap>; +def : GINodeEquiv<G_DEBUGTRAP, debugtrap>; +def : GINodeEquiv<G_UBSANTRAP, ubsantrap>; // Specifies the GlobalISel equivalents for SelectionDAG's ComplexPattern. // Should be used on defs that subclass GIComplexOperandMatcher<>. diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td index 0577c58f8da2df8721c6d2a1bab55cb989e439a9..1f7dc6922f13e4a9e2274c423e0cdb3492a0a43e 100644 --- a/llvm/include/llvm/Target/Target.td +++ b/llvm/include/llvm/Target/Target.td @@ -83,10 +83,27 @@ class RegInfoByHwMode<list<HwMode> Ms = [], list<RegInfo> Ts = []> list<RegInfo> Objects = Ts; } +class SubRegRange<int size, int offset = 0> { + int Size = size; // Sub register size in bits. + int Offset = offset; // Offset of the first bit of the sub-reg index. +} + +class SubRegRangeByHwMode<list<HwMode> Ms = [], list<SubRegRange> Ts = []> + : HwModeSelect<Ms> { + // The length of this list must be the same as the length of Ms. + list<SubRegRange> Objects = Ts; +} + // SubRegIndex - Use instances of SubRegIndex to identify subregisters. class SubRegIndex<int size, int offset = 0> { string Namespace = ""; + // The size/offset information, parameterized by a HW mode. + // If the HwModes provided for SubRegRanges does not include the DefaultMode, + // the/ Size and Offset fields below will be used for the default. Otherwise, + // the Size and Offset fields are ignored. + SubRegRangeByHwMode SubRegRanges; + // Size - Size (in bits) of the sub-registers represented by this index. int Size = size; @@ -697,7 +714,20 @@ class Instruction : InstructionEncoding { // Scheduling information from TargetSchedule.td. list<SchedReadWrite> SchedRW; - string Constraints = ""; // OperandConstraint, e.g. $src = $dst. + /// Support for operand constraints. There are currently two kinds: + /// "$src = $dst" + /// Ensures that the operands are allocated to the same register. + /// + /// "@earlyclobber $rd" + /// Ensures that LLVM will not use the same register for any inputs (other + /// than an input tied to this output). + /// + /// See also: + /// - MC/MCInstrDesc.h:OperandConstraint::{TIED_TO, EARLY_CLOBBER}. + /// - CodeGen/MachineOperand.h:MachineOperand::{TiedTo, IsEarlyClobber}. + /// - The LLVM IR specification: Section `Output constraints` in the + /// discussion of inline assembly constraint strings. + string Constraints = ""; /// DisableEncoding - List of operand names (e.g. "$op1,$op2") that should not /// be encoded into the output machineinstr. @@ -947,8 +977,6 @@ class AsmOperandClass { /// instruction if it hasn't matched all the operands yet. However, this /// error will be suppressed if all of the remaining unmatched operands are /// marked as IsOptional. - /// - /// Optional arguments must be at the end of the operand list. bit IsOptional = false; /// The name of the method on the target specific asm parser that returns the @@ -1564,6 +1592,20 @@ class AsmParser { // method shall be called for all operands as opposed to only those // that have their own specified custom parsers. bit CallCustomParserForAllOperands = false; + + // PreferSmallerInstructions - Should the assembly matcher prefer the smaller + // instructions. + // + // This is useful for the ARM instructions set where smaller encodings must + // be preferentially selected. + // + // The preference order is: + // Instrution size (if this option is enabled, smallest first) + // Number of Operands (least first), + // Operand Classes (lexicographically by operand), + // (Optional) Instruction id (see AsmMatcherEmitter.cpp for details), + // Number of required features (least first) + bit PreferSmallerInstructions = false; } def DefaultAsmParser : AsmParser; @@ -1865,3 +1907,8 @@ include "llvm/Target/GlobalISel/SelectionDAGCompat.td" // Pull in the common support for Pfm Counters generation. // include "llvm/Target/TargetPfmCounters.td" + +//===----------------------------------------------------------------------===// +// Pull in the common support for macro fusion. +// +include "llvm/Target/TargetMacroFusion.td" diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h index 37df9589e30d664883e546c2efe2d5be8fb14e8a..ceb371bdc7348038d0d2acff56a3b5ce71fcaac7 100644 --- a/llvm/include/llvm/Target/TargetMachine.h +++ b/llvm/include/llvm/Target/TargetMachine.h @@ -455,7 +455,7 @@ public: virtual Error buildCodeGenPipeline(ModulePassManager &, raw_pwrite_stream &, raw_pwrite_stream *, CodeGenFileType, - CGPassBuilderOption, + const CGPassBuilderOption &, PassInstrumentationCallbacks *) { return make_error<StringError>("buildCodeGenPipeline is not overridden", inconvertibleErrorCode()); diff --git a/llvm/include/llvm/Target/TargetMacroFusion.td b/llvm/include/llvm/Target/TargetMacroFusion.td new file mode 100644 index 0000000000000000000000000000000000000000..0306794ef50d1fe2bb3aeae05692fdc6cf1ec21a --- /dev/null +++ b/llvm/include/llvm/Target/TargetMacroFusion.td @@ -0,0 +1,153 @@ +//===-- TargetMacroFusion.td - Target Macro Fusion ---------*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the TableGen-based macro fusion classes. + +// The target instruction that FusionPredicate will be evaluated on. +class FusionTarget; +def first_fusion_target : FusionTarget; +def second_fusion_target : FusionTarget; +def both_fusion_target : FusionTarget; + +// Base class of FusionPredicate, etc. The avaliable variables are: +// * const TargetInstrInfo &TII +// * const TargetSubtargetInfo &STI +// * const MachineRegisterInfo &MRI +// * const MachineInstr *FirstMI +// * const MachineInstr &SecondMI +class FusionPredicate<FusionTarget target> { + FusionTarget Target = target; +} +class FirstFusionPredicate: FusionPredicate<first_fusion_target>; +class SecondFusionPredicate: FusionPredicate<second_fusion_target>; +class BothFusionPredicate: FusionPredicate<both_fusion_target>; + +// FusionPredicate with raw code predicate. +class FusionPredicateWithCode<code pred> : FusionPredicate<both_fusion_target> { + code Predicate = pred; +} + +// FusionPredicate with MCInstPredicate. +class FusionPredicateWithMCInstPredicate<FusionTarget target, MCInstPredicate pred> + : FusionPredicate<target> { + MCInstPredicate Predicate = pred; +} +class FirstFusionPredicateWithMCInstPredicate<MCInstPredicate pred> + : FusionPredicateWithMCInstPredicate<first_fusion_target, pred>; +class SecondFusionPredicateWithMCInstPredicate<MCInstPredicate pred> + : FusionPredicateWithMCInstPredicate<second_fusion_target, pred>; +// The pred will be applied on both firstMI and secondMI. +class BothFusionPredicateWithMCInstPredicate<MCInstPredicate pred> + : FusionPredicateWithMCInstPredicate<both_fusion_target, pred>; + +// Tie firstOpIdx and secondOpIdx. The operand of `FirstMI` at position +// `firstOpIdx` should be the same as the operand of `SecondMI` at position +// `secondOpIdx`. +// If the fusion has `IsCommutable` being true and the operand at `secondOpIdx` +// has commutable operand, then the commutable operand will be checked too. +class TieReg<int firstOpIdx, int secondOpIdx> : BothFusionPredicate { + int FirstOpIdx = firstOpIdx; + int SecondOpIdx = secondOpIdx; +} + +// The operand of `SecondMI` at position `firstOpIdx` should be the same as the +// operand at position `secondOpIdx`. +// If the fusion has `IsCommutable` being true and the operand at `secondOpIdx` +// has commutable operand, then the commutable operand will be checked too. +class SameReg<int firstOpIdx, int secondOpIdx> : SecondFusionPredicate { + int FirstOpIdx = firstOpIdx; + int SecondOpIdx = secondOpIdx; +} + +// A predicate for wildcard. The generated code will be like: +// ``` +// if (!FirstMI) +// return ReturnValue; +// ``` +class WildcardPred<bit ret> : FirstFusionPredicate { + bit ReturnValue = ret; +} +def WildcardFalse : WildcardPred<0>; +def WildcardTrue : WildcardPred<1>; + +// Indicates that the destination register of `FirstMI` should have one use if +// it is a virtual register. +class OneUsePred : FirstFusionPredicate; +def OneUse : OneUsePred; + +// Handled by MacroFusionPredicatorEmitter backend. +// The generated predicator will be like: +// ``` +// bool isNAME(const TargetInstrInfo &TII, +// const TargetSubtargetInfo &STI, +// const MachineInstr *FirstMI, +// const MachineInstr &SecondMI) { +// auto &MRI = SecondMI.getMF()->getRegInfo(); +// /* Predicates */ +// return true; +// } +// ``` +// +// `IsCommutable` means whether we should handle commutable operands. +class Fusion<string name, string fieldName, string desc, list<FusionPredicate> predicates> + : SubtargetFeature<name, fieldName, "true", desc> { + list<FusionPredicate> Predicates = predicates; + bit IsCommutable = 0; +} + +// The generated predicator will be like: +// ``` +// bool isNAME(const TargetInstrInfo &TII, +// const TargetSubtargetInfo &STI, +// const MachineInstr *FirstMI, +// const MachineInstr &SecondMI) { +// auto &MRI = SecondMI.getMF()->getRegInfo(); +// /* Prolog */ +// /* Predicate for `SecondMI` */ +// /* Wildcard */ +// /* Predicate for `FirstMI` */ +// /* Check same registers */ +// /* Check One Use */ +// /* Tie registers */ +// /* Epilog */ +// return true; +// } +// ``` +class SimpleFusion<string name, string fieldName, string desc, + MCInstPredicate firstPred, MCInstPredicate secondPred, + list<FusionPredicate> prolog = [], + list<FusionPredicate> epilog = []> + : Fusion<name, fieldName, desc, + !listconcat( + prolog, + [ + SecondFusionPredicateWithMCInstPredicate<secondPred>, + WildcardTrue, + FirstFusionPredicateWithMCInstPredicate<firstPred>, + SameReg<0, 1>, + OneUse, + TieReg<0, 1>, + ], + epilog)>; + +class SingleFusion<string name, string fieldName, string desc, + Instruction firstInst, Instruction secondInst, + MCInstPredicate firstInstPred = TruePred, + MCInstPredicate secondInstPred = TruePred, + list<FusionPredicate> prolog = [], + list<FusionPredicate> epilog = []> + : SimpleFusion<name, fieldName, desc, + CheckAll<!listconcat( + [CheckOpcode<[firstInst]>], + [firstInstPred])>, + CheckAll<!listconcat( + [CheckOpcode<[secondInst]>], + [secondInstPred])>, + prolog, epilog> { + let IsCommutable = secondInst.isCommutable; +} diff --git a/llvm/include/llvm/Target/TargetSchedule.td b/llvm/include/llvm/Target/TargetSchedule.td index 069eb2900bfe6862b70d930e02a2651564114933..2562ed0901303fe882bfc8a7522e750f0e2839c0 100644 --- a/llvm/include/llvm/Target/TargetSchedule.td +++ b/llvm/include/llvm/Target/TargetSchedule.td @@ -581,119 +581,3 @@ class MemoryQueue<ProcResourceKind PR> { class LoadQueue<ProcResourceKind LDQueue> : MemoryQueue<LDQueue>; class StoreQueue<ProcResourceKind STQueue> : MemoryQueue<STQueue>; - -// The target instruction that FusionPredicate will be evaluated on. -class FusionTarget; -def first_fusion_target : FusionTarget; -def second_fusion_target : FusionTarget; -def both_fusion_target : FusionTarget; - -// Base class of FusionPredicate, etc. The avaliable variables are: -// * const TargetInstrInfo &TII -// * const TargetSubtargetInfo &STI -// * const MachineRegisterInfo &MRI -// * const MachineInstr *FirstMI -// * const MachineInstr &SecondMI -class FusionPredicate<FusionTarget target> { - FusionTarget Target = target; -} -class FirstFusionPredicate: FusionPredicate<first_fusion_target>; -class SecondFusionPredicate: FusionPredicate<second_fusion_target>; -class BothFusionPredicate: FusionPredicate<both_fusion_target>; - -// FusionPredicate with raw code predicate. -class FusionPredicateWithCode<code pred> : FusionPredicate<both_fusion_target> { - code Predicate = pred; -} - -// FusionPredicate with MCInstPredicate. -class FusionPredicateWithMCInstPredicate<FusionTarget target, MCInstPredicate pred> - : FusionPredicate<target> { - MCInstPredicate Predicate = pred; -} -class FirstFusionPredicateWithMCInstPredicate<MCInstPredicate pred> - : FusionPredicateWithMCInstPredicate<first_fusion_target, pred>; -class SecondFusionPredicateWithMCInstPredicate<MCInstPredicate pred> - : FusionPredicateWithMCInstPredicate<second_fusion_target, pred>; -// The pred will be applied on both firstMI and secondMI. -class BothFusionPredicateWithMCInstPredicate<MCInstPredicate pred> - : FusionPredicateWithMCInstPredicate<both_fusion_target, pred>; - -// Tie firstOpIdx and secondOpIdx. The operand of `FirstMI` at position -// `firstOpIdx` should be the same as the operand of `SecondMI` at position -// `secondOpIdx`. -class TieReg<int firstOpIdx, int secondOpIdx> : BothFusionPredicate { - int FirstOpIdx = firstOpIdx; - int SecondOpIdx = secondOpIdx; -} - -// A predicate for wildcard. The generated code will be like: -// ``` -// if (!FirstMI) -// return ReturnValue; -// ``` -class WildcardPred<bit ret> : FirstFusionPredicate { - bit ReturnValue = ret; -} -def WildcardFalse : WildcardPred<0>; -def WildcardTrue : WildcardPred<1>; - -// Indicates that the destination register of `FirstMI` should have one use if -// it is a virtual register. -class OneUsePred : FirstFusionPredicate; -def OneUse : OneUsePred; - -// Handled by MacroFusionPredicatorEmitter backend. -// The generated predicator will be like: -// ``` -// bool isNAME(const TargetInstrInfo &TII, -// const TargetSubtargetInfo &STI, -// const MachineInstr *FirstMI, -// const MachineInstr &SecondMI) { -// auto &MRI = SecondMI.getMF()->getRegInfo(); -// /* Predicates */ -// return true; -// } -// ``` -class Fusion<string name, string fieldName, string desc, list<FusionPredicate> predicates> - : SubtargetFeature<name, fieldName, "true", desc> { - list<FusionPredicate> Predicates = predicates; -} - -// The generated predicator will be like: -// ``` -// bool isNAME(const TargetInstrInfo &TII, -// const TargetSubtargetInfo &STI, -// const MachineInstr *FirstMI, -// const MachineInstr &SecondMI) { -// auto &MRI = SecondMI.getMF()->getRegInfo(); -// /* Prolog */ -// /* Predicate for `SecondMI` */ -// /* Wildcard */ -// /* Predicate for `FirstMI` */ -// /* Check One Use */ -// /* Tie registers */ -// /* Epilog */ -// return true; -// } -// ``` -class SimpleFusion<string name, string fieldName, string desc, - MCInstPredicate firstPred, MCInstPredicate secondPred, - list<FusionPredicate> prolog = [], - list<FusionPredicate> epilog = []> - : Fusion<name, fieldName, desc, - !listconcat( - prolog, - [ - SecondFusionPredicateWithMCInstPredicate<secondPred>, - WildcardTrue, - FirstFusionPredicateWithMCInstPredicate<firstPred>, - SecondFusionPredicateWithMCInstPredicate< - CheckAny<[ - CheckIsVRegOperand<0>, - CheckSameRegOperand<0, 1> - ]>>, - OneUse, - TieReg<0, 1>, - ], - epilog)>; diff --git a/llvm/include/llvm/Target/TargetSelectionDAG.td b/llvm/include/llvm/Target/TargetSelectionDAG.td index d7bf8c35ee10721be99168b5c7e628e8bf1bca96..ea3520835fa07d6b5690976c1024cfcff9f07f61 100644 --- a/llvm/include/llvm/Target/TargetSelectionDAG.td +++ b/llvm/include/llvm/Target/TargetSelectionDAG.td @@ -318,7 +318,7 @@ def SDTAtomicStore : SDTypeProfile<0, 2, [ SDTCisInt<0>, SDTCisPtrTy<1> ]>; def SDTAtomicLoad : SDTypeProfile<1, 1, [ - SDTCisInt<0>, SDTCisPtrTy<1> + SDTCisPtrTy<1> ]>; class SDCallSeqStart<list<SDTypeConstraint> constraints> : diff --git a/llvm/include/llvm/TargetParser/AArch64TargetParser.h b/llvm/include/llvm/TargetParser/AArch64TargetParser.h index f4bb94f98bcd77c01080a1b9e599e42a31dda092..805b963a7a13c7c0d6847038f29e9fb70c45393c 100644 --- a/llvm/include/llvm/TargetParser/AArch64TargetParser.h +++ b/llvm/include/llvm/TargetParser/AArch64TargetParser.h @@ -554,6 +554,11 @@ inline constexpr CpuInfo CpuInfos[] = { {AArch64::AEK_SB, AArch64::AEK_SSBS, AArch64::AEK_MTE, AArch64::AEK_FP16FML, AArch64::AEK_PAUTH, AArch64::AEK_SVE2BITPERM, AArch64::AEK_FLAGM, AArch64::AEK_PERFMON, AArch64::AEK_PREDRES})}, + {"cortex-a520ae", ARMV9_2A, + AArch64::ExtensionBitset( + {AArch64::AEK_SB, AArch64::AEK_SSBS, AArch64::AEK_MTE, + AArch64::AEK_FP16FML, AArch64::AEK_PAUTH, AArch64::AEK_SVE2BITPERM, + AArch64::AEK_FLAGM, AArch64::AEK_PERFMON, AArch64::AEK_PREDRES})}, {"cortex-a57", ARMV8A, AArch64::ExtensionBitset( {AArch64::AEK_AES, AArch64::AEK_SHA2, AArch64::AEK_CRC})}, @@ -621,6 +626,12 @@ inline constexpr CpuInfo CpuInfos[] = { AArch64::AEK_PAUTH, AArch64::AEK_SVE2BITPERM, AArch64::AEK_FLAGM, AArch64::AEK_PERFMON, AArch64::AEK_PREDRES, AArch64::AEK_PROFILE})}, + {"cortex-a720ae", ARMV9_2A, + AArch64::ExtensionBitset({AArch64::AEK_SB, AArch64::AEK_SSBS, + AArch64::AEK_MTE, AArch64::AEK_FP16FML, + AArch64::AEK_PAUTH, AArch64::AEK_SVE2BITPERM, + AArch64::AEK_FLAGM, AArch64::AEK_PERFMON, + AArch64::AEK_PREDRES, AArch64::AEK_PROFILE})}, {"cortex-r82", ARMV8R, AArch64::ExtensionBitset({AArch64::AEK_LSE})}, {"cortex-x1", ARMV8_2A, AArch64::ExtensionBitset({AArch64::AEK_AES, AArch64::AEK_SHA2, diff --git a/llvm/include/llvm/TextAPI/DylibReader.h b/llvm/include/llvm/TextAPI/DylibReader.h index b556fbf6832a935b8fea2593aaeb2e533260dffb..6861d3cb1591b7a0c6d649e4f9af61a7cd6d158a 100644 --- a/llvm/include/llvm/TextAPI/DylibReader.h +++ b/llvm/include/llvm/TextAPI/DylibReader.h @@ -13,6 +13,7 @@ #ifndef LLVM_TEXTAPI_DYLIBREADER_H #define LLVM_TEXTAPI_DYLIBREADER_H +#include "llvm/ADT/StringMap.h" #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/TextAPI/ArchitectureSet.h" @@ -43,6 +44,14 @@ Expected<Records> readFile(MemoryBufferRef Buffer, const ParseOption &Opt); /// \param Buffer Data that points to dylib. Expected<std::unique_ptr<InterfaceFile>> get(MemoryBufferRef Buffer); +using SymbolToSourceLocMap = llvm::StringMap<RecordLoc>; +/// Get the source location for each symbol from dylib. +/// +/// \param DSYM Path to DSYM file. +/// \param T Requested target slice for dylib. +SymbolToSourceLocMap accumulateSourceLocFromDSYM(const StringRef DSYM, + const Target &T); + } // namespace llvm::MachO::DylibReader #endif // LLVM_TEXTAPI_DYLIBREADER_H diff --git a/llvm/include/llvm/TextAPI/Record.h b/llvm/include/llvm/TextAPI/Record.h index 98639b064eaadda753b55de5736bbfd06bcbaf84..7d721988ec3dab0d40aa7396ba92842c4d7a47c4 100644 --- a/llvm/include/llvm/TextAPI/Record.h +++ b/llvm/include/llvm/TextAPI/Record.h @@ -27,6 +27,23 @@ LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); class RecordsSlice; +// Defines lightweight source location for records. +struct RecordLoc { + RecordLoc() = default; + RecordLoc(std::string File, unsigned Line) + : File(std::move(File)), Line(Line) {} + + /// Whether there is source location tied to the RecordLoc object. + bool isValid() const { return !File.empty(); } + + bool operator==(const RecordLoc &O) const { + return std::tie(File, Line) == std::tie(O.File, O.Line); + } + + const std::string File; + const unsigned Line = 0; +}; + // Defines a list of linkage types. enum class RecordLinkage : uint8_t { // Unknown linkage. @@ -51,7 +68,8 @@ class Record { public: Record() = default; Record(StringRef Name, RecordLinkage Linkage, SymbolFlags Flags) - : Name(Name), Linkage(Linkage), Flags(mergeFlags(Flags, Linkage)) {} + : Name(Name), Linkage(Linkage), Flags(mergeFlags(Flags, Linkage)), + Verified(false) {} bool isWeakDefined() const { return (Flags & SymbolFlags::WeakDefined) == SymbolFlags::WeakDefined; @@ -79,6 +97,9 @@ public: bool isExported() const { return Linkage >= RecordLinkage::Rexported; } bool isRexported() const { return Linkage == RecordLinkage::Rexported; } + bool isVerified() const { return Verified; } + void setVerify(bool V = true) { Verified = V; } + StringRef getName() const { return Name; } SymbolFlags getFlags() const { return Flags; } @@ -89,6 +110,7 @@ protected: StringRef Name; RecordLinkage Linkage; SymbolFlags Flags; + bool Verified; friend class RecordsSlice; }; diff --git a/llvm/include/llvm/TextAPI/Utils.h b/llvm/include/llvm/TextAPI/Utils.h index 31d3c45f9e2964fdf9e0781afb5554d7212546ba..319e0abce25b030b126b088c4ff05cbd5a521320 100644 --- a/llvm/include/llvm/TextAPI/Utils.h +++ b/llvm/include/llvm/TextAPI/Utils.h @@ -14,8 +14,10 @@ #define LLVM_TEXTAPI_UTILS_H #include "llvm/ADT/Twine.h" +#include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Regex.h" #if !defined(PATH_MAX) #define PATH_MAX 1024 @@ -68,5 +70,10 @@ std::error_code make_relative(StringRef From, StringRef To, /// \param IsSymLink Whether path points to a symlink. bool isPrivateLibrary(StringRef Path, bool IsSymLink = false); +/// Create a regex rule from provided glob string. +/// \param Glob String that represents glob input. +/// \return The equivalent regex rule. +llvm::Expected<llvm::Regex> createRegexFromGlob(llvm::StringRef Glob); + } // namespace llvm::MachO #endif // LLVM_TEXTAPI_UTILS_H diff --git a/llvm/include/llvm/Transforms/IPO/SampleProfileMatcher.h b/llvm/include/llvm/Transforms/IPO/SampleProfileMatcher.h new file mode 100644 index 0000000000000000000000000000000000000000..7ae6194da7c9ccee5c6aca35b637df5084abc373 --- /dev/null +++ b/llvm/include/llvm/Transforms/IPO/SampleProfileMatcher.h @@ -0,0 +1,154 @@ +//===- Transforms/IPO/SampleProfileMatcher.h ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file +/// This file provides the interface for SampleProfileMatcher. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_SAMPLEPROFILEMATCHER_H +#define LLVM_TRANSFORMS_IPO_SAMPLEPROFILEMATCHER_H + +#include "llvm/ADT/StringSet.h" +#include "llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h" + +namespace llvm { + +// Sample profile matching - fuzzy match. +class SampleProfileMatcher { + Module &M; + SampleProfileReader &Reader; + const PseudoProbeManager *ProbeManager; + const ThinOrFullLTOPhase LTOPhase; + SampleProfileMap FlattenedProfiles; + // For each function, the matcher generates a map, of which each entry is a + // mapping from the source location of current build to the source location in + // the profile. + StringMap<LocToLocMap> FuncMappings; + + // Match state for an anchor/callsite. + enum class MatchState { + Unknown = 0, + // Initial match between input profile and current IR. + InitialMatch = 1, + // Initial mismatch between input profile and current IR. + InitialMismatch = 2, + // InitialMatch stays matched after fuzzy profile matching. + UnchangedMatch = 3, + // InitialMismatch stays mismatched after fuzzy profile matching. + UnchangedMismatch = 4, + // InitialMismatch is recovered after fuzzy profile matching. + RecoveredMismatch = 5, + // InitialMatch is removed and becomes mismatched after fuzzy profile + // matching. + RemovedMatch = 6, + }; + + // For each function, store every callsite and its matching state into this + // map, of which each entry is a pair of callsite location and MatchState. + // This is used for profile staleness computation and report. + StringMap<std::unordered_map<LineLocation, MatchState, LineLocationHash>> + FuncCallsiteMatchStates; + + // Profile mismatch statstics: + uint64_t TotalProfiledFunc = 0; + // Num of checksum-mismatched function. + uint64_t NumStaleProfileFunc = 0; + uint64_t TotalProfiledCallsites = 0; + uint64_t NumMismatchedCallsites = 0; + uint64_t NumRecoveredCallsites = 0; + // Total samples for all profiled functions. + uint64_t TotalFunctionSamples = 0; + // Total samples for all checksum-mismatched functions. + uint64_t MismatchedFunctionSamples = 0; + uint64_t MismatchedCallsiteSamples = 0; + uint64_t RecoveredCallsiteSamples = 0; + + // A dummy name for unknown indirect callee, used to differentiate from a + // non-call instruction that also has an empty callee name. + static constexpr const char *UnknownIndirectCallee = + "unknown.indirect.callee"; + +public: + SampleProfileMatcher(Module &M, SampleProfileReader &Reader, + const PseudoProbeManager *ProbeManager, + ThinOrFullLTOPhase LTOPhase) + : M(M), Reader(Reader), ProbeManager(ProbeManager), LTOPhase(LTOPhase){}; + void runOnModule(); + void clearMatchingData() { + // Do not clear FuncMappings, it stores IRLoc to ProfLoc remappings which + // will be used for sample loader. + FuncCallsiteMatchStates.clear(); + } + +private: + FunctionSamples *getFlattenedSamplesFor(const Function &F) { + StringRef CanonFName = FunctionSamples::getCanonicalFnName(F); + auto It = FlattenedProfiles.find(FunctionId(CanonFName)); + if (It != FlattenedProfiles.end()) + return &It->second; + return nullptr; + } + void runOnFunction(Function &F); + void findIRAnchors(const Function &F, + std::map<LineLocation, StringRef> &IRAnchors); + void findProfileAnchors( + const FunctionSamples &FS, + std::map<LineLocation, std::unordered_set<FunctionId>> &ProfileAnchors); + // Record the callsite match states for profile staleness report, the result + // is saved in FuncCallsiteMatchStates. + void recordCallsiteMatchStates( + const Function &F, const std::map<LineLocation, StringRef> &IRAnchors, + const std::map<LineLocation, std::unordered_set<FunctionId>> + &ProfileAnchors, + const LocToLocMap *IRToProfileLocationMap); + + bool isMismatchState(const enum MatchState &State) { + return State == MatchState::InitialMismatch || + State == MatchState::UnchangedMismatch || + State == MatchState::RemovedMatch; + }; + + bool isInitialState(const enum MatchState &State) { + return State == MatchState::InitialMatch || + State == MatchState::InitialMismatch; + }; + + bool isFinalState(const enum MatchState &State) { + return State == MatchState::UnchangedMatch || + State == MatchState::UnchangedMismatch || + State == MatchState::RecoveredMismatch || + State == MatchState::RemovedMatch; + }; + + // Count the samples of checksum mismatched function for the top-level + // function and all inlinees. + void countMismatchedFuncSamples(const FunctionSamples &FS, bool IsTopLevel); + // Count the number of mismatched or recovered callsites. + void countMismatchCallsites(const FunctionSamples &FS); + // Count the samples of mismatched or recovered callsites for top-level + // function and all inlinees. + void countMismatchedCallsiteSamples(const FunctionSamples &FS); + void computeAndReportProfileStaleness(); + + LocToLocMap &getIRToProfileLocationMap(const Function &F) { + auto Ret = FuncMappings.try_emplace( + FunctionSamples::getCanonicalFnName(F.getName()), LocToLocMap()); + return Ret.first->second; + } + void distributeIRToProfileLocationMap(); + void distributeIRToProfileLocationMap(FunctionSamples &FS); + void runStaleProfileMatching( + const Function &F, const std::map<LineLocation, StringRef> &IRAnchors, + const std::map<LineLocation, std::unordered_set<FunctionId>> + &ProfileAnchors, + LocToLocMap &IRToProfileLocationMap); + void reportOrPersistProfileStats(); +}; +} // end namespace llvm +#endif // LLVM_TRANSFORMS_IPO_SAMPLEPROFILEMATCHER_H diff --git a/llvm/include/llvm/Transforms/IPO/SampleProfileProbe.h b/llvm/include/llvm/Transforms/IPO/SampleProfileProbe.h index 0f2729a9462de2eefd6e41820315385052eaf390..03aa93ce6bd387ba104f1b0ddd563ea38d557c38 100644 --- a/llvm/include/llvm/Transforms/IPO/SampleProfileProbe.h +++ b/llvm/include/llvm/Transforms/IPO/SampleProfileProbe.h @@ -81,8 +81,17 @@ private: uint64_t getFunctionHash() const { return FunctionHash; } uint32_t getBlockId(const BasicBlock *BB) const; uint32_t getCallsiteId(const Instruction *Call) const; - void computeCFGHash(); - void computeProbeIdForBlocks(); + void findUnreachableBlocks(DenseSet<BasicBlock *> &BlocksToIgnore); + void findInvokeNormalDests(DenseSet<BasicBlock *> &InvokeNormalDests); + void computeBlocksToIgnore(DenseSet<BasicBlock *> &BlocksToIgnore, + DenseSet<BasicBlock *> &BlocksAndCallsToIgnore); + void computeProbeIdForCallsites( + const DenseSet<BasicBlock *> &BlocksAndCallsToIgnore); + const Instruction * + getOriginalTerminator(const BasicBlock *Head, + const DenseSet<BasicBlock *> &BlocksToIgnore); + void computeCFGHash(const DenseSet<BasicBlock *> &BlocksToIgnore); + void computeProbeIdForBlocks(const DenseSet<BasicBlock *> &BlocksToIgnore); void computeProbeIdForCallsites(); Function *F; diff --git a/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h b/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h index a4d1653fdf4bc685932a3a882ad4617d39d039ca..48f8421c1813c8fa28a36bb30fb1aa91d9054c80 100644 --- a/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h +++ b/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h @@ -172,11 +172,12 @@ private: void collectMatInsertPts( const consthoist::RebasedConstantListType &RebasedConstants, - SmallVectorImpl<Instruction *> &MatInsertPts) const; - Instruction *findMatInsertPt(Instruction *Inst, unsigned Idx = ~0U) const; - SetVector<Instruction *> - findConstantInsertionPoint(const consthoist::ConstantInfo &ConstInfo, - const ArrayRef<Instruction *> MatInsertPts) const; + SmallVectorImpl<BasicBlock::iterator> &MatInsertPts) const; + BasicBlock::iterator findMatInsertPt(Instruction *Inst, + unsigned Idx = ~0U) const; + SetVector<BasicBlock::iterator> findConstantInsertionPoint( + const consthoist::ConstantInfo &ConstInfo, + const ArrayRef<BasicBlock::iterator> MatInsertPts) const; void collectConstantCandidates(ConstCandMapType &ConstCandMap, Instruction *Inst, unsigned Idx, ConstantInt *ConstInt); @@ -203,9 +204,9 @@ private: struct UserAdjustment { Constant *Offset; Type *Ty; - Instruction *MatInsertPt; + BasicBlock::iterator MatInsertPt; const consthoist::ConstantUser User; - UserAdjustment(Constant *O, Type *T, Instruction *I, + UserAdjustment(Constant *O, Type *T, BasicBlock::iterator I, consthoist::ConstantUser U) : Offset(O), Ty(T), MatInsertPt(I), User(U) {} }; diff --git a/llvm/include/llvm/Transforms/Scalar/Float2Int.h b/llvm/include/llvm/Transforms/Scalar/Float2Int.h index 83be329bed60bab8b0be0c5b5054428a3b3c9a1b..337e229efcf3795c062251d350a750303b11709b 100644 --- a/llvm/include/llvm/Transforms/Scalar/Float2Int.h +++ b/llvm/include/llvm/Transforms/Scalar/Float2Int.h @@ -44,7 +44,7 @@ private: std::optional<ConstantRange> calcRange(Instruction *I); void walkBackwards(); void walkForwards(); - bool validateAndTransform(); + bool validateAndTransform(const DataLayout &DL); Value *convert(Instruction *I, Type *ToTy); void cleanup(); diff --git a/llvm/include/llvm/Transforms/Utils/CodeExtractor.h b/llvm/include/llvm/Transforms/Utils/CodeExtractor.h index 27b34ef023db7298b4f8048e66e8df5534e5f16c..333ed6774d6c7eb5d3c51dc9b2b15d3aed53712e 100644 --- a/llvm/include/llvm/Transforms/Utils/CodeExtractor.h +++ b/llvm/include/llvm/Transforms/Utils/CodeExtractor.h @@ -249,7 +249,7 @@ public: Instruction *Addr, BasicBlock *ExitBlock) const; void severSplitPHINodesOfEntry(BasicBlock *&Header); - void severSplitPHINodesOfExits(const SmallPtrSetImpl<BasicBlock *> &Exits); + void severSplitPHINodesOfExits(const SetVector<BasicBlock *> &Exits); void splitReturnBlocks(); Function *constructFunction(const ValueSet &inputs, diff --git a/llvm/include/llvm/Transforms/Utils/Local.h b/llvm/include/llvm/Transforms/Utils/Local.h index cc1336287436290b7d4addfbd5bb8e65eb582506..9ae026fa95d21ad1e0786100182e30c5af390ab7 100644 --- a/llvm/include/llvm/Transforms/Utils/Local.h +++ b/llvm/include/llvm/Transforms/Utils/Local.h @@ -262,21 +262,21 @@ CallInst *changeToCall(InvokeInst *II, DomTreeUpdater *DTU = nullptr); /// that has an associated llvm.dbg.declare intrinsic. void ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, StoreInst *SI, DIBuilder &Builder); -void ConvertDebugDeclareToDebugValue(DPValue *DPV, StoreInst *SI, +void ConvertDebugDeclareToDebugValue(DbgVariableRecord *DVR, StoreInst *SI, DIBuilder &Builder); /// Inserts a llvm.dbg.value intrinsic before a load of an alloca'd value /// that has an associated llvm.dbg.declare intrinsic. void ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, LoadInst *LI, DIBuilder &Builder); -void ConvertDebugDeclareToDebugValue(DPValue *DPV, LoadInst *LI, +void ConvertDebugDeclareToDebugValue(DbgVariableRecord *DVR, LoadInst *LI, DIBuilder &Builder); /// Inserts a llvm.dbg.value intrinsic after a phi that has an associated /// llvm.dbg.declare intrinsic. void ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, PHINode *LI, DIBuilder &Builder); -void ConvertDebugDeclareToDebugValue(DPValue *DPV, PHINode *LI, +void ConvertDebugDeclareToDebugValue(DbgVariableRecord *DVR, PHINode *LI, DIBuilder &Builder); /// Lowers llvm.dbg.declare intrinsics into appropriate set of @@ -313,7 +313,7 @@ void salvageDebugInfo(Instruction &I); /// Mark undef if salvaging cannot be completed. void salvageDebugInfoForDbgValues(Instruction &I, ArrayRef<DbgVariableIntrinsic *> Insns, - ArrayRef<DPValue *> DPInsns); + ArrayRef<DbgVariableRecord *> DPInsns); /// Given an instruction \p I and DIExpression \p DIExpr operating on /// it, append the effects of \p I to the DIExpression operand list diff --git a/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h b/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h index eb00e6c4e856df642baefab30c11be52856926a2..fb3ab33a0629dae4357f2335f1f02d57c09f32c5 100644 --- a/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h +++ b/llvm/include/llvm/Transforms/Utils/MemoryTaggingSupport.h @@ -17,6 +17,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/StackSafetyAnalysis.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/Support/Alignment.h" namespace llvm { @@ -53,7 +54,7 @@ struct AllocaInfo { SmallVector<IntrinsicInst *, 2> LifetimeEnd; SmallVector<DbgVariableIntrinsic *, 2> DbgVariableIntrinsics; // Non-intrinsic records of variable locations. - SmallVector<DPValue *, 2> DbgVariableRecords; + SmallVector<DbgVariableRecord *, 2> DbgVariableRecords; }; struct StackInfo { @@ -78,6 +79,12 @@ private: uint64_t getAllocaSizeInBytes(const AllocaInst &AI); void alignAndPadAlloca(memtag::AllocaInfo &Info, llvm::Align Align); +bool isLifetimeIntrinsic(Value *V); + +Value *readRegister(IRBuilder<> &IRB, StringRef Name); +Value *getFP(IRBuilder<> &IRB); +Value *getPC(const Triple &TargetTriple, IRBuilder<> &IRB); +Value *getAndroidSlotPtr(IRBuilder<> &IRB, int Slot); } // namespace memtag } // namespace llvm diff --git a/llvm/include/llvm/Transforms/Utils/SSAUpdater.h b/llvm/include/llvm/Transforms/Utils/SSAUpdater.h index c79d436fc676bb9e68544271219aeab063a17c28..29d96a0ab6bf5b7a4d546b7f9deac2c89d38c783 100644 --- a/llvm/include/llvm/Transforms/Utils/SSAUpdater.h +++ b/llvm/include/llvm/Transforms/Utils/SSAUpdater.h @@ -23,7 +23,7 @@ class BasicBlock; class Instruction; class LoadInst; class PHINode; -class DPValue; +class DbgVariableRecord; template <typename T> class SmallVectorImpl; template <typename T> class SSAUpdaterTraits; class Type; @@ -124,7 +124,8 @@ public: void UpdateDebugValues(Instruction *I); void UpdateDebugValues(Instruction *I, SmallVectorImpl<DbgValueInst *> &DbgValues); - void UpdateDebugValues(Instruction *I, SmallVectorImpl<DPValue *> &DbgValues); + void UpdateDebugValues(Instruction *I, + SmallVectorImpl<DbgVariableRecord *> &DbgValues); /// Rewrite a use like \c RewriteUse but handling in-block definitions. /// @@ -136,7 +137,7 @@ public: private: Value *GetValueAtEndOfBlockInternal(BasicBlock *BB); void UpdateDebugValue(Instruction *I, DbgValueInst *DbgValue); - void UpdateDebugValue(Instruction *I, DPValue *DbgValue); + void UpdateDebugValue(Instruction *I, DbgVariableRecord *DbgValue); }; /// Helper class for promoting a collection of loads and stores into SSA diff --git a/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h b/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h index 66814d395273010da07162aa2a526d330a65248c..d898ee58307ead53319baa91fd15f56ab7ce1ead 100644 --- a/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h +++ b/llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h @@ -86,9 +86,12 @@ template <> struct IRTraits<BasicBlock> { // SampleProfileProber. class PseudoProbeManager { DenseMap<uint64_t, PseudoProbeDescriptor> GUIDToProbeDescMap; + const ThinOrFullLTOPhase LTOPhase; public: - PseudoProbeManager(const Module &M) { + PseudoProbeManager(const Module &M, + ThinOrFullLTOPhase LTOPhase = ThinOrFullLTOPhase::None) + : LTOPhase(LTOPhase) { if (NamedMDNode *FuncInfo = M.getNamedMetadata(PseudoProbeDescMetadataName)) { for (const auto *Operand : FuncInfo->operands()) { @@ -126,17 +129,16 @@ public: bool profileIsValid(const Function &F, const FunctionSamples &Samples) const { const auto *Desc = getDesc(F); - if (!Desc) { - LLVM_DEBUG(dbgs() << "Probe descriptor missing for Function " - << F.getName() << "\n"); - return false; - } - if (Desc->getFunctionHash() != Samples.getFunctionHash()) { - LLVM_DEBUG(dbgs() << "Hash mismatch for Function " << F.getName() - << "\n"); - return false; - } - return true; + assert((LTOPhase != ThinOrFullLTOPhase::ThinLTOPostLink || !Desc || + profileIsHashMismatched(*Desc, Samples) == + F.hasFnAttribute("profile-checksum-mismatch")) && + "In post-link, profile checksum matching state doesn't match " + "function 'profile-checksum-mismatch' attribute."); + (void)LTOPhase; + // The desc for import function is unavailable. Check the function attribute + // for mismatch. + return (!Desc && !F.hasFnAttribute("profile-checksum-mismatch")) || + (Desc && !profileIsHashMismatched(*Desc, Samples)); } }; @@ -144,6 +146,10 @@ public: extern cl::opt<bool> SampleProfileUseProfi; +static inline bool skipProfileForFunction(const Function &F) { + return F.isDeclaration() || !F.hasFnAttribute("use-sample-profile"); +} + template <typename FT> class SampleProfileLoaderBaseImpl { public: SampleProfileLoaderBaseImpl(std::string Name, std::string RemapName, diff --git a/llvm/include/llvm/Transforms/Utils/ValueMapper.h b/llvm/include/llvm/Transforms/Utils/ValueMapper.h index dd183bc04f0c249dfcbc271ef345c16b6a6655e6..54e3e62dc3af50b84fc24299392178b0eaa53aac 100644 --- a/llvm/include/llvm/Transforms/Utils/ValueMapper.h +++ b/llvm/include/llvm/Transforms/Utils/ValueMapper.h @@ -180,8 +180,9 @@ public: Constant *mapConstant(const Constant &C); void remapInstruction(Instruction &I); - void remapDPValue(Module *M, DPValue &V); - void remapDPValueRange(Module *M, iterator_range<DbgRecordIterator> Range); + void remapDbgVariableRecord(Module *M, DbgVariableRecord &V); + void remapDbgVariableRecordRange(Module *M, + iterator_range<DbgRecordIterator> Range); void remapFunction(Function &F); void remapGlobalObjectMetadata(GlobalObject &GO); @@ -267,21 +268,26 @@ inline void RemapInstruction(Instruction *I, ValueToValueMapTy &VM, ValueMapper(VM, Flags, TypeMapper, Materializer).remapInstruction(*I); } -/// Remap the Values used in the DPValue \a V using the value map \a VM. -inline void RemapDPValue(Module *M, DPValue *V, ValueToValueMapTy &VM, - RemapFlags Flags = RF_None, - ValueMapTypeRemapper *TypeMapper = nullptr, - ValueMaterializer *Materializer = nullptr) { - ValueMapper(VM, Flags, TypeMapper, Materializer).remapDPValue(M, *V); +/// Remap the Values used in the DbgVariableRecord \a V using the value map \a +/// VM. +inline void RemapDbgVariableRecord(Module *M, DbgVariableRecord *V, + ValueToValueMapTy &VM, + RemapFlags Flags = RF_None, + ValueMapTypeRemapper *TypeMapper = nullptr, + ValueMaterializer *Materializer = nullptr) { + ValueMapper(VM, Flags, TypeMapper, Materializer) + .remapDbgVariableRecord(M, *V); } -/// Remap the Values used in the DPValue \a V using the value map \a VM. -inline void RemapDPValueRange(Module *M, - iterator_range<DbgRecordIterator> Range, - ValueToValueMapTy &VM, RemapFlags Flags = RF_None, - ValueMapTypeRemapper *TypeMapper = nullptr, - ValueMaterializer *Materializer = nullptr) { - ValueMapper(VM, Flags, TypeMapper, Materializer).remapDPValueRange(M, Range); +/// Remap the Values used in the DbgVariableRecord \a V using the value map \a +/// VM. +inline void +RemapDbgVariableRecordRange(Module *M, iterator_range<DbgRecordIterator> Range, + ValueToValueMapTy &VM, RemapFlags Flags = RF_None, + ValueMapTypeRemapper *TypeMapper = nullptr, + ValueMaterializer *Materializer = nullptr) { + ValueMapper(VM, Flags, TypeMapper, Materializer) + .remapDbgVariableRecordRange(M, Range); } /// Remap the operands, metadata, arguments, and instructions of a function. diff --git a/llvm/lib/Analysis/AliasSetTracker.cpp b/llvm/lib/Analysis/AliasSetTracker.cpp index 59bb40cdba6e150f0bb04f6da827c8740732ed41..32e545daaf226923f72bc948c65eecfba529b8f7 100644 --- a/llvm/lib/Analysis/AliasSetTracker.cpp +++ b/llvm/lib/Analysis/AliasSetTracker.cpp @@ -354,6 +354,8 @@ void AliasSetTracker::addUnknown(Instruction *Inst) { default: break; // FIXME: Add lifetime/invariant intrinsics (See: PR30807). + case Intrinsic::allow_runtime_check: + case Intrinsic::allow_ubsan_check: case Intrinsic::assume: case Intrinsic::experimental_noalias_scope_decl: case Intrinsic::sideeffect: diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 8b7031e7fe4a6fa6ed32b4195383bd0a2c102bac..749374a3aa48af2a7f2cf42c2183da65e135c0ef 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -751,7 +751,7 @@ Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty, Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty, const DataLayout &DL) { APInt Offset(DL.getIndexTypeSizeInBits(C->getType()), 0); - return ConstantFoldLoadFromConstPtr(C, Ty, Offset, DL); + return ConstantFoldLoadFromConstPtr(C, Ty, std::move(Offset), DL); } Constant *llvm::ConstantFoldLoadFromUniformValue(Constant *C, Type *Ty, @@ -828,7 +828,7 @@ Constant *SymbolicallyEvaluateBinop(unsigned Opc, Constant *Op0, Constant *Op1, /// that they aren't implicitly casted by the getelementptr. Constant *CastGEPIndices(Type *SrcElemTy, ArrayRef<Constant *> Ops, Type *ResultTy, bool InBounds, - std::optional<unsigned> InRangeIndex, + std::optional<ConstantRange> InRange, const DataLayout &DL, const TargetLibraryInfo *TLI) { Type *IntIdxTy = DL.getIndexType(ResultTy); Type *IntIdxScalarTy = IntIdxTy->getScalarType(); @@ -856,8 +856,8 @@ Constant *CastGEPIndices(Type *SrcElemTy, ArrayRef<Constant *> Ops, if (!Any) return nullptr; - Constant *C = ConstantExpr::getGetElementPtr( - SrcElemTy, Ops[0], NewIdxs, InBounds, InRangeIndex); + Constant *C = ConstantExpr::getGetElementPtr(SrcElemTy, Ops[0], NewIdxs, + InBounds, InRange); return ConstantFoldConstant(C, DL, TLI); } @@ -866,7 +866,6 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP, ArrayRef<Constant *> Ops, const DataLayout &DL, const TargetLibraryInfo *TLI) { - const GEPOperator *InnermostGEP = GEP; bool InBounds = GEP->isInBounds(); Type *SrcElemTy = GEP->getSourceElementType(); @@ -875,9 +874,8 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP, if (!SrcElemTy->isSized() || isa<ScalableVectorType>(SrcElemTy)) return nullptr; - if (Constant *C = CastGEPIndices(SrcElemTy, Ops, ResTy, - GEP->isInBounds(), GEP->getInRangeIndex(), - DL, TLI)) + if (Constant *C = CastGEPIndices(SrcElemTy, Ops, ResTy, GEP->isInBounds(), + GEP->getInRange(), DL, TLI)) return C; Constant *Ptr = Ops[0]; @@ -896,9 +894,12 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP, DL.getIndexedOffsetInType( SrcElemTy, ArrayRef((Value *const *)Ops.data() + 1, Ops.size() - 1))); + std::optional<ConstantRange> InRange = GEP->getInRange(); + if (InRange) + InRange = InRange->sextOrTrunc(BitWidth); + // If this is a GEP of a GEP, fold it all into a single GEP. while (auto *GEP = dyn_cast<GEPOperator>(Ptr)) { - InnermostGEP = GEP; InBounds &= GEP->isInBounds(); SmallVector<Value *, 4> NestedOps(llvm::drop_begin(GEP->operands())); @@ -913,6 +914,14 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP, if (!AllConstantInt) break; + // TODO: Try to intersect two inrange attributes? + if (!InRange) { + InRange = GEP->getInRange(); + if (InRange) + // Adjust inrange by offset until now. + InRange = InRange->sextOrTrunc(BitWidth).subtract(Offset); + } + Ptr = cast<Constant>(GEP->getOperand(0)); SrcElemTy = GEP->getSourceElementType(); Offset += APInt(BitWidth, DL.getIndexedOffsetInType(SrcElemTy, NestedOps)); @@ -971,21 +980,8 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP, NewIdxs.push_back(ConstantInt::get( Type::getIntNTy(Ptr->getContext(), Index.getBitWidth()), Index)); - // Preserve the inrange index from the innermost GEP if possible. We must - // have calculated the same indices up to and including the inrange index. - std::optional<unsigned> InRangeIndex; - if (std::optional<unsigned> LastIRIndex = InnermostGEP->getInRangeIndex()) - if (SrcElemTy == InnermostGEP->getSourceElementType() && - NewIdxs.size() > *LastIRIndex) { - InRangeIndex = LastIRIndex; - for (unsigned I = 0; I <= *LastIRIndex; ++I) - if (NewIdxs[I] != InnermostGEP->getOperand(I + 1)) - return nullptr; - } - - // Create a GEP. return ConstantExpr::getGetElementPtr(SrcElemTy, Ptr, NewIdxs, InBounds, - InRangeIndex); + InRange); } /// Attempt to constant fold an instruction with the @@ -1033,8 +1029,7 @@ Constant *ConstantFoldInstOperandsImpl(const Value *InstOrCE, unsigned Opcode, return C; return ConstantExpr::getGetElementPtr(SrcElemTy, Ops[0], Ops.slice(1), - GEP->isInBounds(), - GEP->getInRangeIndex()); + GEP->isInBounds(), GEP->getInRange()); } if (auto *CE = dyn_cast<ConstantExpr>(InstOrCE)) { @@ -2534,12 +2529,73 @@ static Constant *evaluateCompare(const APFloat &Op1, const APFloat &Op2, return nullptr; } -static Constant *ConstantFoldScalarCall2(StringRef Name, - Intrinsic::ID IntrinsicID, - Type *Ty, - ArrayRef<Constant *> Operands, - const TargetLibraryInfo *TLI, - const CallBase *Call) { +static Constant *ConstantFoldLibCall2(StringRef Name, Type *Ty, + ArrayRef<Constant *> Operands, + const TargetLibraryInfo *TLI) { + if (!TLI) + return nullptr; + + LibFunc Func = NotLibFunc; + if (!TLI->getLibFunc(Name, Func)) + return nullptr; + + const auto *Op1 = dyn_cast<ConstantFP>(Operands[0]); + if (!Op1) + return nullptr; + + const auto *Op2 = dyn_cast<ConstantFP>(Operands[1]); + if (!Op2) + return nullptr; + + const APFloat &Op1V = Op1->getValueAPF(); + const APFloat &Op2V = Op2->getValueAPF(); + + switch (Func) { + default: + break; + case LibFunc_pow: + case LibFunc_powf: + case LibFunc_pow_finite: + case LibFunc_powf_finite: + if (TLI->has(Func)) + return ConstantFoldBinaryFP(pow, Op1V, Op2V, Ty); + break; + case LibFunc_fmod: + case LibFunc_fmodf: + if (TLI->has(Func)) { + APFloat V = Op1->getValueAPF(); + if (APFloat::opStatus::opOK == V.mod(Op2->getValueAPF())) + return ConstantFP::get(Ty->getContext(), V); + } + break; + case LibFunc_remainder: + case LibFunc_remainderf: + if (TLI->has(Func)) { + APFloat V = Op1->getValueAPF(); + if (APFloat::opStatus::opOK == V.remainder(Op2->getValueAPF())) + return ConstantFP::get(Ty->getContext(), V); + } + break; + case LibFunc_atan2: + case LibFunc_atan2f: + // atan2(+/-0.0, +/-0.0) is known to raise an exception on some libm + // (Solaris), so we do not assume a known result for that. + if (Op1V.isZero() && Op2V.isZero()) + return nullptr; + [[fallthrough]]; + case LibFunc_atan2_finite: + case LibFunc_atan2f_finite: + if (TLI->has(Func)) + return ConstantFoldBinaryFP(atan2, Op1V, Op2V, Ty); + break; + } + + return nullptr; +} + +static Constant *ConstantFoldIntrinsicCall2(Intrinsic::ID IntrinsicID, Type *Ty, + ArrayRef<Constant *> Operands, + const CallBase *Call) { assert(Operands.size() == 2 && "Wrong number of operands."); if (Ty->isFloatingPointTy()) { @@ -2569,7 +2625,8 @@ static Constant *ConstantFoldScalarCall2(StringRef Name, return nullptr; const APFloat &Op2V = Op2->getValueAPF(); - if (const auto *ConstrIntr = dyn_cast<ConstrainedFPIntrinsic>(Call)) { + if (const auto *ConstrIntr = + dyn_cast_if_present<ConstrainedFPIntrinsic>(Call)) { RoundingMode RM = getEvaluationRoundingMode(ConstrIntr); APFloat Res = Op1V; APFloat::opStatus St; @@ -2632,52 +2689,6 @@ static Constant *ConstantFoldScalarCall2(StringRef Name, return ConstantFP::get(Ty->getContext(), Op1V * Op2V); } - if (!TLI) - return nullptr; - - LibFunc Func = NotLibFunc; - if (!TLI->getLibFunc(Name, Func)) - return nullptr; - - switch (Func) { - default: - break; - case LibFunc_pow: - case LibFunc_powf: - case LibFunc_pow_finite: - case LibFunc_powf_finite: - if (TLI->has(Func)) - return ConstantFoldBinaryFP(pow, Op1V, Op2V, Ty); - break; - case LibFunc_fmod: - case LibFunc_fmodf: - if (TLI->has(Func)) { - APFloat V = Op1->getValueAPF(); - if (APFloat::opStatus::opOK == V.mod(Op2->getValueAPF())) - return ConstantFP::get(Ty->getContext(), V); - } - break; - case LibFunc_remainder: - case LibFunc_remainderf: - if (TLI->has(Func)) { - APFloat V = Op1->getValueAPF(); - if (APFloat::opStatus::opOK == V.remainder(Op2->getValueAPF())) - return ConstantFP::get(Ty->getContext(), V); - } - break; - case LibFunc_atan2: - case LibFunc_atan2f: - // atan2(+/-0.0, +/-0.0) is known to raise an exception on some libm - // (Solaris), so we do not assume a known result for that. - if (Op1V.isZero() && Op2V.isZero()) - return nullptr; - [[fallthrough]]; - case LibFunc_atan2_finite: - case LibFunc_atan2f_finite: - if (TLI->has(Func)) - return ConstantFoldBinaryFP(atan2, Op1V, Op2V, Ty); - break; - } } else if (auto *Op2C = dyn_cast<ConstantInt>(Operands[1])) { switch (IntrinsicID) { case Intrinsic::ldexp: { @@ -3168,8 +3179,13 @@ static Constant *ConstantFoldScalarCall(StringRef Name, if (Operands.size() == 1) return ConstantFoldScalarCall1(Name, IntrinsicID, Ty, Operands, TLI, Call); - if (Operands.size() == 2) - return ConstantFoldScalarCall2(Name, IntrinsicID, Ty, Operands, TLI, Call); + if (Operands.size() == 2) { + if (Constant *FoldedLibCall = + ConstantFoldLibCall2(Name, Ty, Operands, TLI)) { + return FoldedLibCall; + } + return ConstantFoldIntrinsicCall2(IntrinsicID, Ty, Operands, Call); + } if (Operands.size() == 3) return ConstantFoldScalarCall3(Name, IntrinsicID, Ty, Operands, TLI, Call); @@ -3376,6 +3392,13 @@ ConstantFoldStructCall(StringRef Name, Intrinsic::ID IntrinsicID, } // end anonymous namespace +Constant *llvm::ConstantFoldBinaryIntrinsic(Intrinsic::ID ID, Constant *LHS, + Constant *RHS, Type *Ty, + Instruction *FMFSource) { + return ConstantFoldIntrinsicCall2(ID, Ty, {LHS, RHS}, + dyn_cast_if_present<CallBase>(FMFSource)); +} + Constant *llvm::ConstantFoldCall(const CallBase *Call, Function *F, ArrayRef<Constant *> Operands, const TargetLibraryInfo *TLI) { diff --git a/llvm/lib/Analysis/IndirectCallPromotionAnalysis.cpp b/llvm/lib/Analysis/IndirectCallPromotionAnalysis.cpp index ebfa1c8fc08e1c630e0f5cb91dc6280329e64a4e..ab53717eb889a0cd6875b347c972ca85b65a8b02 100644 --- a/llvm/lib/Analysis/IndirectCallPromotionAnalysis.cpp +++ b/llvm/lib/Analysis/IndirectCallPromotionAnalysis.cpp @@ -45,6 +45,10 @@ static cl::opt<unsigned> cl::desc("Max number of promotions for a single indirect " "call callsite")); +cl::opt<unsigned> MaxNumVTableAnnotations( + "icp-max-num-vtables", cl::init(6), cl::Hidden, + cl::desc("Max number of vtables annotated for a vtable load instruction.")); + ICallPromotionAnalysis::ICallPromotionAnalysis() { ValueDataArray = std::make_unique<InstrProfValueData[]>(MaxNumPromotions); } diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp index e55eaa55f8e947635cca9d59c97e03352f77ca91..c75460f44c1d9f5906585225d1dbea30bde45943 100644 --- a/llvm/lib/Analysis/InlineCost.cpp +++ b/llvm/lib/Analysis/InlineCost.cpp @@ -800,7 +800,7 @@ class InlineCostCallAnalyzer final : public CallAnalyzer { return false; } else { // Otherwise, require instrumentation profile. - if (!(PSI->hasInstrumentationProfile() || PSI->hasSampleProfile())) + if (!PSI->hasInstrumentationProfile()) return false; } diff --git a/llvm/lib/Analysis/InlineOrder.cpp b/llvm/lib/Analysis/InlineOrder.cpp index 09fc4f9a00f49cdaaa8ee95370292d10159ea039..f156daa2f126fbab4dbd85dbb1f1da28d61c32a9 100644 --- a/llvm/lib/Analysis/InlineOrder.cpp +++ b/llvm/lib/Analysis/InlineOrder.cpp @@ -114,7 +114,10 @@ public: CostBenefitPriority(const CallBase *CB, FunctionAnalysisManager &FAM, const InlineParams &Params) { auto IC = getInlineCostWrapper(const_cast<CallBase &>(*CB), FAM, Params); - Cost = IC.getCost(); + if (IC.isVariable()) + Cost = IC.getCost(); + else + Cost = IC.isNever() ? INT_MAX : INT_MIN; StaticBonusApplied = IC.getStaticBonusApplied(); CostBenefit = IC.getCostBenefit(); } diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index ce651783caf16bc1bff1276828dd7e92c7e927ec..9ff3faff799027d3755e3507d314a512e566df9f 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -3736,15 +3736,10 @@ static std::optional<ConstantRange> getRange(Value *V, if (MDNode *MD = IIQ.getMetadata(I, LLVMContext::MD_range)) return getConstantRangeFromMetadata(*MD); - Attribute Range; - if (const Argument *A = dyn_cast<Argument>(V)) { - Range = A->getAttribute(llvm::Attribute::Range); - } else if (const CallBase *CB = dyn_cast<CallBase>(V)) { - Range = CB->getRetAttr(llvm::Attribute::Range); - } - - if (Range.isValid()) - return Range.getRange(); + if (const Argument *A = dyn_cast<Argument>(V)) + return A->getRange(); + else if (const CallBase *CB = dyn_cast<CallBase>(V)) + return CB->getRange(); return std::nullopt; } @@ -5767,11 +5762,16 @@ static Value *simplifyFMAFMul(Value *Op0, Value *Op1, FastMathFlags FMF, if (FMF.noNaNs() && FMF.noSignedZeros()) return ConstantFP::getZero(Op0->getType()); - // +normal number * (-)0.0 --> (-)0.0 KnownFPClass Known = computeKnownFPClass(Op0, FMF, fcInf | fcNan, /*Depth=*/0, Q); - if (Known.SignBit == false && Known.isKnownNever(fcInf | fcNan)) - return Op1; + if (Known.isKnownNever(fcInf | fcNan)) { + // +normal number * (-)0.0 --> (-)0.0 + if (Known.SignBit == false) + return Op1; + // -normal number * (-)0.0 --> -(-)0.0 + if (Known.SignBit == true) + return foldConstant(Instruction::FNeg, Op1, Q); + } } // sqrt(X) * sqrt(X) --> X, if we can: @@ -6115,7 +6115,8 @@ static Value *simplifyRelativeLoad(Constant *Ptr, Constant *Offset, if (OffsetInt.srem(4) != 0) return nullptr; - Constant *Loaded = ConstantFoldLoadFromConstPtr(Ptr, Int32Ty, OffsetInt, DL); + Constant *Loaded = + ConstantFoldLoadFromConstPtr(Ptr, Int32Ty, std::move(OffsetInt), DL); if (!Loaded) return nullptr; @@ -6384,11 +6385,10 @@ static Value *foldMinimumMaximumSharedOp(Intrinsic::ID IID, Value *Op0, return nullptr; } -static Value *simplifyBinaryIntrinsic(Function *F, Value *Op0, Value *Op1, - const SimplifyQuery &Q, - const CallBase *Call) { - Intrinsic::ID IID = F->getIntrinsicID(); - Type *ReturnType = F->getReturnType(); +Value *llvm::simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType, + Value *Op0, Value *Op1, + const SimplifyQuery &Q, + const CallBase *Call) { unsigned BitWidth = ReturnType->getScalarSizeInBits(); switch (IID) { case Intrinsic::abs: @@ -6646,19 +6646,21 @@ static Value *simplifyBinaryIntrinsic(Function *F, Value *Op0, Value *Op1, // float, if the ninf flag is set. const APFloat *C; if (match(Op1, m_APFloat(C)) && - (C->isInfinity() || (Call->hasNoInfs() && C->isLargest()))) { + (C->isInfinity() || (Call && Call->hasNoInfs() && C->isLargest()))) { // minnum(X, -inf) -> -inf // maxnum(X, +inf) -> +inf // minimum(X, -inf) -> -inf if nnan // maximum(X, +inf) -> +inf if nnan - if (C->isNegative() == IsMin && (!PropagateNaN || Call->hasNoNaNs())) + if (C->isNegative() == IsMin && + (!PropagateNaN || (Call && Call->hasNoNaNs()))) return ConstantFP::get(ReturnType, *C); // minnum(X, +inf) -> X if nnan // maxnum(X, -inf) -> X if nnan // minimum(X, +inf) -> X // maximum(X, -inf) -> X - if (C->isNegative() != IsMin && (PropagateNaN || Call->hasNoNaNs())) + if (C->isNegative() != IsMin && + (PropagateNaN || (Call && Call->hasNoNaNs()))) return Op0; } @@ -6672,8 +6674,6 @@ static Value *simplifyBinaryIntrinsic(Function *F, Value *Op0, Value *Op1, break; } case Intrinsic::vector_extract: { - Type *ReturnType = F->getReturnType(); - // (extract_vector (insert_vector _, X, 0), 0) -> X unsigned IdxN = cast<ConstantInt>(Op1)->getZExtValue(); Value *X = nullptr; @@ -6720,7 +6720,8 @@ static Value *simplifyIntrinsic(CallBase *Call, Value *Callee, return simplifyUnaryIntrinsic(F, Args[0], Q, Call); if (NumOperands == 2) - return simplifyBinaryIntrinsic(F, Args[0], Args[1], Q, Call); + return simplifyBinaryIntrinsic(IID, F->getReturnType(), Args[0], Args[1], Q, + Call); // Handle intrinsics with 3 or more arguments. switch (IID) { @@ -6983,7 +6984,8 @@ Value *llvm::simplifyLoadInst(LoadInst *LI, Value *PtrOp, if (PtrOp == GV) { // Index size may have changed due to address space casts. Offset = Offset.sextOrTrunc(Q.DL.getIndexTypeSizeInBits(PtrOp->getType())); - return ConstantFoldLoadFromConstPtr(GV, LI->getType(), Offset, Q.DL); + return ConstantFoldLoadFromConstPtr(GV, LI->getType(), std::move(Offset), + Q.DL); } return nullptr; diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp index 9ae31d165235ca29ef55e061e993acd3f50860f6..b8bc81197c95c0a8d389cc0f4bcc99267b7b8fdb 100644 --- a/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/llvm/lib/Analysis/LazyValueInfo.cpp @@ -1069,14 +1069,14 @@ static bool matchICmpOperand(APInt &Offset, Value *LHS, Value *Val, // Handle range checking idiom produced by InstCombine. We will subtract the // offset from the allowed range for RHS in this case. const APInt *C; - if (match(LHS, m_Add(m_Specific(Val), m_APInt(C)))) { + if (match(LHS, m_AddLike(m_Specific(Val), m_APInt(C)))) { Offset = *C; return true; } // Handle the symmetric case. This appears in saturation patterns like // (x == 16) ? 16 : (x + 1). - if (match(Val, m_Add(m_Specific(LHS), m_APInt(C)))) { + if (match(Val, m_AddLike(m_Specific(LHS), m_APInt(C)))) { Offset = -*C; return true; } diff --git a/llvm/lib/Analysis/MemorySSA.cpp b/llvm/lib/Analysis/MemorySSA.cpp index 82a6c470650cc98d5fab7f5a87324c66fc898530..49450d85d742257c0830b30e0ae5777f12a8e0e1 100644 --- a/llvm/lib/Analysis/MemorySSA.cpp +++ b/llvm/lib/Analysis/MemorySSA.cpp @@ -292,6 +292,8 @@ instructionClobbersQuery(const MemoryDef *MD, const MemoryLocation &UseLoc, // clobbers where they don't really exist at all. Please see D43269 for // context. switch (II->getIntrinsicID()) { + case Intrinsic::allow_runtime_check: + case Intrinsic::allow_ubsan_check: case Intrinsic::invariant_start: case Intrinsic::invariant_end: case Intrinsic::assume: @@ -1725,6 +1727,8 @@ MemoryUseOrDef *MemorySSA::createNewAccess(Instruction *I, switch (II->getIntrinsicID()) { default: break; + case Intrinsic::allow_runtime_check: + case Intrinsic::allow_ubsan_check: case Intrinsic::assume: case Intrinsic::experimental_noalias_scope_decl: case Intrinsic::pseudoprobe: diff --git a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp index 1f15e94783240a7c6be03a642531668f8e667922..3ad0bab827a512d6f5b0e8b07852fd12ddbca8eb 100644 --- a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp +++ b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp @@ -82,6 +82,8 @@ static cl::opt<std::string> ModuleSummaryDotFile( extern cl::opt<bool> ScalePartialSampleProfileWorkingSetSize; +extern cl::opt<unsigned> MaxNumVTableAnnotations; + // Walk through the operands of a given User via worklist iteration and populate // the set of GlobalValue references encountered. Invoked either on an // Instruction or a GlobalVariable (which walks its initializer). @@ -124,6 +126,24 @@ static bool findRefEdges(ModuleSummaryIndex &Index, const User *CurUser, Worklist.push_back(Operand); } } + + const Instruction *I = dyn_cast<Instruction>(CurUser); + if (I) { + uint32_t ActualNumValueData = 0; + uint64_t TotalCount = 0; + // MaxNumVTableAnnotations is the maximum number of vtables annotated on + // the instruction. + auto ValueDataArray = + getValueProfDataFromInst(*I, IPVK_VTableTarget, MaxNumVTableAnnotations, + ActualNumValueData, TotalCount); + + if (ValueDataArray.get()) { + for (uint32_t j = 0; j < ActualNumValueData; j++) { + RefEdges.insert(Index.getOrInsertValueInfo(/* VTableGUID = */ + ValueDataArray[j].Value)); + } + } + } return HasBlockAddress; } diff --git a/llvm/lib/Analysis/PHITransAddr.cpp b/llvm/lib/Analysis/PHITransAddr.cpp index 5700fd664a4cd3f3d70d0302c537a1ccb8df9ba0..d16dec0d42927dcae8319bcd325f90c7165ab1fe 100644 --- a/llvm/lib/Analysis/PHITransAddr.cpp +++ b/llvm/lib/Analysis/PHITransAddr.cpp @@ -369,7 +369,7 @@ Value *PHITransAddr::insertTranslatedSubExpr( // Otherwise insert a cast at the end of PredBB. CastInst *New = CastInst::Create(Cast->getOpcode(), OpVal, InVal->getType(), InVal->getName() + ".phi.trans.insert", - PredBB->getTerminator()); + PredBB->getTerminator()->getIterator()); New->setDebugLoc(Inst->getDebugLoc()); NewInsts.push_back(New); return New; @@ -387,7 +387,8 @@ Value *PHITransAddr::insertTranslatedSubExpr( GetElementPtrInst *Result = GetElementPtrInst::Create( GEP->getSourceElementType(), GEPOps[0], ArrayRef(GEPOps).slice(1), - InVal->getName() + ".phi.trans.insert", PredBB->getTerminator()); + InVal->getName() + ".phi.trans.insert", + PredBB->getTerminator()->getIterator()); Result->setDebugLoc(Inst->getDebugLoc()); Result->setIsInBounds(GEP->isInBounds()); NewInsts.push_back(Result); @@ -408,9 +409,9 @@ Value *PHITransAddr::insertTranslatedSubExpr( if (OpVal == nullptr) return nullptr; - BinaryOperator *Res = BinaryOperator::CreateAdd(OpVal, Inst->getOperand(1), - InVal->getName()+".phi.trans.insert", - PredBB->getTerminator()); + BinaryOperator *Res = BinaryOperator::CreateAdd( + OpVal, Inst->getOperand(1), InVal->getName() + ".phi.trans.insert", + PredBB->getTerminator()->getIterator()); Res->setHasNoSignedWrap(cast<BinaryOperator>(Inst)->hasNoSignedWrap()); Res->setHasNoUnsignedWrap(cast<BinaryOperator>(Inst)->hasNoUnsignedWrap()); NewInsts.push_back(Res); diff --git a/llvm/lib/Analysis/ReplayInlineAdvisor.cpp b/llvm/lib/Analysis/ReplayInlineAdvisor.cpp index 0814483db343ceeaca7493883d59696c612f7005..2ca02eb1741712b09355e07a69f513ea3718f880 100644 --- a/llvm/lib/Analysis/ReplayInlineAdvisor.cpp +++ b/llvm/lib/Analysis/ReplayInlineAdvisor.cpp @@ -43,8 +43,8 @@ ReplayInlineAdvisor::ReplayInlineAdvisor( // main:3:1.1; // We use the callsite string after `at callsite` to replay inlining. line_iterator LineIt(*BufferOrErr.get(), /*SkipBlanks=*/true); - static const std::string PositiveRemark = "' inlined into '"; - static const std::string NegativeRemark = "' will not be inlined into '"; + const std::string PositiveRemark = "' inlined into '"; + const std::string NegativeRemark = "' will not be inlined into '"; for (; !LineIt.is_at_eof(); ++LineIt) { StringRef Line = *LineIt; diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp index c8195584ade378375b4da95a080df5db248e1371..9e17dcaa55925d0106b6800a53b093a5459f15ba 100644 --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -1190,107 +1190,113 @@ void TargetLibraryInfoImpl::addVectorizableFunctions(ArrayRef<VecDesc> Fns) { llvm::sort(ScalarDescs, compareByVectorFnName); } +static const VecDesc VecFuncs_Accelerate[] = { +#define TLI_DEFINE_ACCELERATE_VECFUNCS +#include "llvm/Analysis/VecFuncs.def" +}; + +static const VecDesc VecFuncs_DarwinLibSystemM[] = { +#define TLI_DEFINE_DARWIN_LIBSYSTEM_M_VECFUNCS +#include "llvm/Analysis/VecFuncs.def" +}; + +static const VecDesc VecFuncs_LIBMVEC_X86[] = { +#define TLI_DEFINE_LIBMVEC_X86_VECFUNCS +#include "llvm/Analysis/VecFuncs.def" +}; + +static const VecDesc VecFuncs_MASSV[] = { +#define TLI_DEFINE_MASSV_VECFUNCS +#include "llvm/Analysis/VecFuncs.def" +}; + +static const VecDesc VecFuncs_SVML[] = { +#define TLI_DEFINE_SVML_VECFUNCS +#include "llvm/Analysis/VecFuncs.def" +}; + +static const VecDesc VecFuncs_SLEEFGNUABI_VF2[] = { +#define TLI_DEFINE_SLEEFGNUABI_VF2_VECFUNCS +#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) \ + {SCAL, VEC, VF, /* MASK = */ false, VABI_PREFIX}, +#include "llvm/Analysis/VecFuncs.def" +}; +static const VecDesc VecFuncs_SLEEFGNUABI_VF4[] = { +#define TLI_DEFINE_SLEEFGNUABI_VF4_VECFUNCS +#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) \ + {SCAL, VEC, VF, /* MASK = */ false, VABI_PREFIX}, +#include "llvm/Analysis/VecFuncs.def" +}; +static const VecDesc VecFuncs_SLEEFGNUABI_VFScalable[] = { +#define TLI_DEFINE_SLEEFGNUABI_SCALABLE_VECFUNCS +#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \ + {SCAL, VEC, VF, MASK, VABI_PREFIX}, +#include "llvm/Analysis/VecFuncs.def" +}; + +static const VecDesc VecFuncs_ArmPL[] = { +#define TLI_DEFINE_ARMPL_VECFUNCS +#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \ + {SCAL, VEC, VF, MASK, VABI_PREFIX}, +#include "llvm/Analysis/VecFuncs.def" +}; + +const VecDesc VecFuncs_AMDLIBM[] = { +#define TLI_DEFINE_AMDLIBM_VECFUNCS +#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \ + {SCAL, VEC, VF, MASK, VABI_PREFIX}, +#include "llvm/Analysis/VecFuncs.def" +}; + void TargetLibraryInfoImpl::addVectorizableFunctionsFromVecLib( enum VectorLibrary VecLib, const llvm::Triple &TargetTriple) { switch (VecLib) { case Accelerate: { - const VecDesc VecFuncs[] = { - #define TLI_DEFINE_ACCELERATE_VECFUNCS - #include "llvm/Analysis/VecFuncs.def" - }; - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs_Accelerate); break; } case DarwinLibSystemM: { - const VecDesc VecFuncs[] = { - #define TLI_DEFINE_DARWIN_LIBSYSTEM_M_VECFUNCS - #include "llvm/Analysis/VecFuncs.def" - }; - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs_DarwinLibSystemM); break; } case LIBMVEC_X86: { - const VecDesc VecFuncs[] = { - #define TLI_DEFINE_LIBMVEC_X86_VECFUNCS - #include "llvm/Analysis/VecFuncs.def" - }; - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs_LIBMVEC_X86); break; } case MASSV: { - const VecDesc VecFuncs[] = { - #define TLI_DEFINE_MASSV_VECFUNCS - #include "llvm/Analysis/VecFuncs.def" - }; - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs_MASSV); break; } case SVML: { - const VecDesc VecFuncs[] = { - #define TLI_DEFINE_SVML_VECFUNCS - #include "llvm/Analysis/VecFuncs.def" - }; - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs_SVML); break; } case SLEEFGNUABI: { - const VecDesc VecFuncs_VF2[] = { -#define TLI_DEFINE_SLEEFGNUABI_VF2_VECFUNCS -#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) \ - {SCAL, VEC, VF, /* MASK = */ false, VABI_PREFIX}, -#include "llvm/Analysis/VecFuncs.def" - }; - const VecDesc VecFuncs_VF4[] = { -#define TLI_DEFINE_SLEEFGNUABI_VF4_VECFUNCS -#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, VABI_PREFIX) \ - {SCAL, VEC, VF, /* MASK = */ false, VABI_PREFIX}, -#include "llvm/Analysis/VecFuncs.def" - }; - const VecDesc VecFuncs_VFScalable[] = { -#define TLI_DEFINE_SLEEFGNUABI_SCALABLE_VECFUNCS -#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \ - {SCAL, VEC, VF, MASK, VABI_PREFIX}, -#include "llvm/Analysis/VecFuncs.def" - }; - switch (TargetTriple.getArch()) { default: break; case llvm::Triple::aarch64: case llvm::Triple::aarch64_be: - addVectorizableFunctions(VecFuncs_VF2); - addVectorizableFunctions(VecFuncs_VF4); - addVectorizableFunctions(VecFuncs_VFScalable); + addVectorizableFunctions(VecFuncs_SLEEFGNUABI_VF2); + addVectorizableFunctions(VecFuncs_SLEEFGNUABI_VF4); + addVectorizableFunctions(VecFuncs_SLEEFGNUABI_VFScalable); break; } break; } case ArmPL: { - const VecDesc VecFuncs[] = { -#define TLI_DEFINE_ARMPL_VECFUNCS -#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \ - {SCAL, VEC, VF, MASK, VABI_PREFIX}, -#include "llvm/Analysis/VecFuncs.def" - }; - switch (TargetTriple.getArch()) { default: break; case llvm::Triple::aarch64: case llvm::Triple::aarch64_be: - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs_ArmPL); break; } break; } case AMDLIBM: { - const VecDesc VecFuncs[] = { -#define TLI_DEFINE_AMDLIBM_VECFUNCS -#define TLI_DEFINE_VECFUNC(SCAL, VEC, VF, MASK, VABI_PREFIX) \ - {SCAL, VEC, VF, MASK, VABI_PREFIX}, -#include "llvm/Analysis/VecFuncs.def" - }; - addVectorizableFunctions(VecFuncs); + addVectorizableFunctions(VecFuncs_AMDLIBM); break; } case NoLibrary: diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp index 15311be4dba277203598b63448792c795382bdef..5f933b4587843cb8cd8e8fdb6c65192497c8fe10 100644 --- a/llvm/lib/Analysis/TargetTransformInfo.cpp +++ b/llvm/lib/Analysis/TargetTransformInfo.cpp @@ -9,6 +9,7 @@ #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Analysis/CFG.h" #include "llvm/Analysis/LoopIterator.h" +#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfoImpl.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Dominators.h" @@ -395,6 +396,10 @@ bool TargetTransformInfo::isLegalAddImmediate(int64_t Imm) const { return TTIImpl->isLegalAddImmediate(Imm); } +bool TargetTransformInfo::isLegalAddScalableImmediate(int64_t Imm) const { + return TTIImpl->isLegalAddScalableImmediate(Imm); +} + bool TargetTransformInfo::isLegalICmpImmediate(int64_t Imm) const { return TTIImpl->isLegalICmpImmediate(Imm); } @@ -403,9 +408,10 @@ bool TargetTransformInfo::isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool HasBaseReg, int64_t Scale, unsigned AddrSpace, - Instruction *I) const { + Instruction *I, + int64_t ScalableOffset) const { return TTIImpl->isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, - Scale, AddrSpace, I); + Scale, AddrSpace, I, ScalableOffset); } bool TargetTransformInfo::isLSRCostLess(const LSRCost &C1, @@ -874,7 +880,22 @@ TargetTransformInfo::getOperandInfo(const Value *V) { InstructionCost TargetTransformInfo::getArithmeticInstrCost( unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, OperandValueInfo Op1Info, OperandValueInfo Op2Info, - ArrayRef<const Value *> Args, const Instruction *CxtI) const { + ArrayRef<const Value *> Args, const Instruction *CxtI, + const TargetLibraryInfo *TLibInfo) const { + + // Use call cost for frem intructions that have platform specific vector math + // functions, as those will be replaced with calls later by SelectionDAG or + // ReplaceWithVecLib pass. + if (TLibInfo && Opcode == Instruction::FRem) { + VectorType *VecTy = dyn_cast<VectorType>(Ty); + LibFunc Func; + if (VecTy && + TLibInfo->getLibFunc(Instruction::FRem, Ty->getScalarType(), Func) && + TLibInfo->isFunctionVectorizable(TLibInfo->getName(Func), + VecTy->getElementCount())) + return getCallInstrCost(nullptr, VecTy, {VecTy, VecTy}, CostKind); + } + InstructionCost Cost = TTIImpl->getArithmeticInstrCost(Opcode, Ty, CostKind, Op1Info, Op2Info, diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 371ad41ee96562a2f03cfe8f01847a952fb3cb6f..b5e8a1d22f264bd28b66bf5e4ffe2b1c982a60ee 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -699,7 +699,7 @@ static void computeKnownBitsFromCmp(const Value *V, CmpInst::Predicate Pred, } default: const APInt *Offset = nullptr; - if (match(LHS, m_CombineOr(m_V, m_Add(m_V, m_APInt(Offset)))) && + if (match(LHS, m_CombineOr(m_V, m_AddLike(m_V, m_APInt(Offset)))) && match(RHS, m_APInt(C))) { ConstantRange LHSRange = ConstantRange::makeAllowedICmpRegion(Pred, *C); if (Offset) @@ -1023,11 +1023,44 @@ static void computeKnownBitsFromOperator(const Operator *I, break; } case Instruction::Select: { - computeKnownBits(I->getOperand(2), Known, Depth + 1, Q); - computeKnownBits(I->getOperand(1), Known2, Depth + 1, Q); - + auto ComputeForArm = [&](Value *Arm, bool Invert) { + KnownBits Res(Known.getBitWidth()); + computeKnownBits(Arm, Res, Depth + 1, Q); + // If we have a constant arm, we are done. + if (Res.isConstant()) + return Res; + + // See what condition implies about the bits of the two select arms. + KnownBits CondRes(Res.getBitWidth()); + computeKnownBitsFromCond(Arm, I->getOperand(0), CondRes, Depth + 1, Q, + Invert); + // If we don't get any information from the condition, no reason to + // proceed. + if (CondRes.isUnknown()) + return Res; + + // We can have conflict if the condition is dead. I.e if we have + // (x | 64) < 32 ? (x | 64) : y + // we will have conflict at bit 6 from the condition/the `or`. + // In that case just return. Its not particularly important + // what we do, as this select is going to be simplified soon. + CondRes = CondRes.unionWith(Res); + if (CondRes.hasConflict()) + return Res; + + // Finally make sure the information we found is valid. This is relatively + // expensive so it's left for the very end. + if (!isGuaranteedNotToBeUndef(Arm, Q.AC, Q.CxtI, Q.DT, Depth + 1)) + return Res; + + // Finally, we know we get information from the condition and its valid, + // so return it. + return CondRes; + }; // Only known if known in both the LHS and RHS. - Known = Known.intersectWith(Known2); + Known = + ComputeForArm(I->getOperand(1), /*Invert=*/false) + .intersectWith(ComputeForArm(I->getOperand(2), /*Invert=*/true)); break; } case Instruction::FPTrunc: @@ -1467,14 +1500,20 @@ static void computeKnownBitsFromOperator(const Operator *I, break; } case Instruction::Call: - case Instruction::Invoke: + case Instruction::Invoke: { // If range metadata is attached to this call, set known bits from that, // and then intersect with known bits based on other properties of the // function. if (MDNode *MD = Q.IIQ.getMetadata(cast<Instruction>(I), LLVMContext::MD_range)) computeKnownBitsFromRangeMetadata(*MD, Known); - if (const Value *RV = cast<CallBase>(I)->getReturnedArgOperand()) { + + const auto *CB = cast<CallBase>(I); + + if (std::optional<ConstantRange> Range = CB->getRange()) + Known = Known.unionWith(Range->toKnownBits()); + + if (const Value *RV = CB->getReturnedArgOperand()) { if (RV->getType() == I->getType()) { computeKnownBits(RV, Known2, Depth + 1, Q); Known = Known.unionWith(Known2); @@ -1646,6 +1685,7 @@ static void computeKnownBitsFromOperator(const Operator *I, } } break; + } case Instruction::ShuffleVector: { auto *Shuf = dyn_cast<ShuffleVectorInst>(I); // FIXME: Do we need to handle ConstantExpr involving shufflevectors? @@ -1900,6 +1940,10 @@ void computeKnownBits(const Value *V, const APInt &DemandedElts, // assumptions. Confirm that we've handled them all. assert(!isa<ConstantData>(V) && "Unhandled constant data!"); + if (const auto *A = dyn_cast<Argument>(V)) + if (std::optional<ConstantRange> Range = A->getRange()) + Known = Range->toKnownBits(); + // All recursive calls that increase depth must come after this. if (Depth == MaxAnalysisRecursionDepth) return; @@ -2726,27 +2770,38 @@ static bool isKnownNonZeroFromOperator(const Operator *I, auto *LI = cast<LoadInst>(I); // A Load tagged with nonnull or dereferenceable with null pointer undefined // is never null. - if (auto *PtrT = dyn_cast<PointerType>(I->getType())) + if (auto *PtrT = dyn_cast<PointerType>(I->getType())) { if (Q.IIQ.getMetadata(LI, LLVMContext::MD_nonnull) || (Q.IIQ.getMetadata(LI, LLVMContext::MD_dereferenceable) && !NullPointerIsDefined(LI->getFunction(), PtrT->getAddressSpace()))) return true; + } else if (MDNode *Ranges = Q.IIQ.getMetadata(LI, LLVMContext::MD_range)) { + return rangeMetadataExcludesValue(Ranges, APInt::getZero(BitWidth)); + } // No need to fall through to computeKnownBits as range metadata is already // handled in isKnownNonZero. return false; } case Instruction::Call: - case Instruction::Invoke: + case Instruction::Invoke: { + const auto *Call = cast<CallBase>(I); if (I->getType()->isPointerTy()) { - const auto *Call = cast<CallBase>(I); if (Call->isReturnNonNull()) return true; if (const auto *RP = getArgumentAliasingToReturnedPointer(Call, true)) return isKnownNonZero(RP, Depth, Q); - } else if (const Value *RV = cast<CallBase>(I)->getReturnedArgOperand()) { - if (RV->getType() == I->getType() && isKnownNonZero(RV, Depth, Q)) - return true; + } else { + if (MDNode *Ranges = Q.IIQ.getMetadata(Call, LLVMContext::MD_range)) + return rangeMetadataExcludesValue(Ranges, APInt::getZero(BitWidth)); + if (std::optional<ConstantRange> Range = Call->getRange()) { + const APInt ZeroValue(Range->getBitWidth(), 0); + if (!Range->contains(ZeroValue)) + return true; + } + if (const Value *RV = Call->getReturnedArgOperand()) + if (RV->getType() == I->getType() && isKnownNonZero(RV, Depth, Q)) + return true; } if (auto *II = dyn_cast<IntrinsicInst>(I)) { @@ -2816,6 +2871,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I, return false; } + } KnownBits Known(BitWidth); computeKnownBits(I, DemandedElts, Known, Depth, Q); @@ -2830,9 +2886,9 @@ static bool isKnownNonZeroFromOperator(const Operator *I, /// Supports values with integer or pointer type and vectors of integers. bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth, const SimplifyQuery &Q) { + Type *Ty = V->getType(); #ifndef NDEBUG - Type *Ty = V->getType(); assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth"); if (auto *FVTy = dyn_cast<FixedVectorType>(Ty)) { @@ -2854,7 +2910,7 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth, // For constant vectors, check that all elements are undefined or known // non-zero to determine that the whole vector is known non-zero. - if (auto *VecTy = dyn_cast<FixedVectorType>(C->getType())) { + if (auto *VecTy = dyn_cast<FixedVectorType>(Ty)) { for (unsigned i = 0, e = VecTy->getNumElements(); i != e; ++i) { if (!DemandedElts[i]) continue; @@ -2881,17 +2937,12 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth, return false; } - if (auto *I = dyn_cast<Instruction>(V)) { - if (MDNode *Ranges = Q.IIQ.getMetadata(I, LLVMContext::MD_range)) { - // If the possible ranges don't contain zero, then the value is - // definitely non-zero. - if (auto *Ty = dyn_cast<IntegerType>(V->getType())) { - const APInt ZeroValue(Ty->getBitWidth(), 0); - if (rangeMetadataExcludesValue(Ranges, ZeroValue)) - return true; - } + if (const auto *A = dyn_cast<Argument>(V)) + if (std::optional<ConstantRange> Range = A->getRange()) { + const APInt ZeroValue(Range->getBitWidth(), 0); + if (!Range->contains(ZeroValue)) + return true; } - } if (!isa<Constant>(V) && isKnownNonZeroFromAssume(V, Q)) return true; @@ -2902,7 +2953,7 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth, // Check for pointer simplifications. - if (PointerType *PtrTy = dyn_cast<PointerType>(V->getType())) { + if (PointerType *PtrTy = dyn_cast<PointerType>(Ty)) { // A byval, inalloca may not be null in a non-default addres space. A // nonnull argument is assumed never 0. if (const Argument *A = dyn_cast<Argument>(V)) { @@ -3939,10 +3990,16 @@ std::tuple<Value *, FPClassTest, FPClassTest> llvm::fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS, FPClassTest RHSClass, bool LookThroughSrc) { assert(RHSClass != fcNone); + Value *Src = LHS; + + if (Pred == FCmpInst::FCMP_TRUE) + return exactClass(Src, fcAllFlags); + + if (Pred == FCmpInst::FCMP_FALSE) + return exactClass(Src, fcNone); const FPClassTest OrigClass = RHSClass; - Value *Src = LHS; const bool IsNegativeRHS = (RHSClass & fcNegative) == RHSClass; const bool IsPositiveRHS = (RHSClass & fcPositive) == RHSClass; const bool IsNaN = (RHSClass & ~fcNan) == fcNone; @@ -3961,12 +4018,6 @@ llvm::fcmpImpliesClass(CmpInst::Predicate Pred, const Function &F, Value *LHS, if (Pred == FCmpInst::FCMP_UNO) return exactClass(Src, fcNan); - if (Pred == FCmpInst::FCMP_TRUE) - return exactClass(Src, fcAllFlags); - - if (Pred == FCmpInst::FCMP_FALSE) - return exactClass(Src, fcNone); - const bool IsFabs = LookThroughSrc && match(LHS, m_FAbs(m_Value(Src))); if (IsFabs) RHSClass = llvm::inverse_fabs(RHSClass); @@ -5709,7 +5760,7 @@ llvm::FindInsertedValue(Value *V, ArrayRef<unsigned> idx_range, // looking for, then. if (*req_idx != *i) return FindInsertedValue(I->getAggregateOperand(), idx_range, - *InsertBefore); + InsertBefore); } // If we end up here, the indices of the insertvalue match with those // requested (though possibly only partially). Now we recursively look at @@ -8438,26 +8489,12 @@ isImpliedCondOperands(CmpInst::Predicate Pred, const Value *ALHS, } } -/// Return true if the operands of two compares (expanded as "L0 pred L1" and -/// "R0 pred R1") match. IsSwappedOps is true when the operands match, but are -/// swapped. -static bool areMatchingOperands(const Value *L0, const Value *L1, const Value *R0, - const Value *R1, bool &AreSwappedOps) { - bool AreMatchingOps = (L0 == R0 && L1 == R1); - AreSwappedOps = (L0 == R1 && L1 == R0); - return AreMatchingOps || AreSwappedOps; -} - /// Return true if "icmp1 LPred X, Y" implies "icmp2 RPred X, Y" is true. /// Return false if "icmp1 LPred X, Y" implies "icmp2 RPred X, Y" is false. /// Otherwise, return std::nullopt if we can't infer anything. static std::optional<bool> isImpliedCondMatchingOperands(CmpInst::Predicate LPred, - CmpInst::Predicate RPred, bool AreSwappedOps) { - // Canonicalize the predicate as if the operands were not commuted. - if (AreSwappedOps) - RPred = ICmpInst::getSwappedPredicate(RPred); - + CmpInst::Predicate RPred) { if (CmpInst::isImpliedTrueByMatchingCmp(LPred, RPred)) return true; if (CmpInst::isImpliedFalseByMatchingCmp(LPred, RPred)) @@ -8499,6 +8536,26 @@ static std::optional<bool> isImpliedCondICmps(const ICmpInst *LHS, CmpInst::Predicate LPred = LHSIsTrue ? LHS->getPredicate() : LHS->getInversePredicate(); + // We can have non-canonical operands, so try to normalize any common operand + // to L0/R0. + if (L0 == R1) { + std::swap(R0, R1); + RPred = ICmpInst::getSwappedPredicate(RPred); + } + if (R0 == L1) { + std::swap(L0, L1); + LPred = ICmpInst::getSwappedPredicate(LPred); + } + if (L1 == R1) { + // If we have L0 == R0 and L1 == R1, then make L1/R1 the constants. + if (L0 != R0 || match(L0, m_ImmConstant())) { + std::swap(L0, L1); + LPred = ICmpInst::getSwappedPredicate(LPred); + std::swap(R0, R1); + RPred = ICmpInst::getSwappedPredicate(RPred); + } + } + // Can we infer anything when the 0-operands match and the 1-operands are // constants (not necessarily matching)? const APInt *LC, *RC; @@ -8506,32 +8563,15 @@ static std::optional<bool> isImpliedCondICmps(const ICmpInst *LHS, return isImpliedCondCommonOperandWithConstants(LPred, *LC, RPred, *RC); // Can we infer anything when the two compares have matching operands? - bool AreSwappedOps; - if (areMatchingOperands(L0, L1, R0, R1, AreSwappedOps)) - return isImpliedCondMatchingOperands(LPred, RPred, AreSwappedOps); + if (L0 == R0 && L1 == R1) + return isImpliedCondMatchingOperands(LPred, RPred); // L0 = R0 = L1 + R1, L0 >=u L1 implies R0 >=u R1, L0 <u L1 implies R0 <u R1 - if (ICmpInst::isUnsigned(LPred) && ICmpInst::isUnsigned(RPred)) { - if (L0 == R1) { - std::swap(R0, R1); - RPred = ICmpInst::getSwappedPredicate(RPred); - } - if (L1 == R0) { - std::swap(L0, L1); - LPred = ICmpInst::getSwappedPredicate(LPred); - } - if (L1 == R1) { - std::swap(L0, L1); - LPred = ICmpInst::getSwappedPredicate(LPred); - std::swap(R0, R1); - RPred = ICmpInst::getSwappedPredicate(RPred); - } - if (L0 == R0 && - (LPred == ICmpInst::ICMP_ULT || LPred == ICmpInst::ICMP_UGE) && - (RPred == ICmpInst::ICMP_ULT || RPred == ICmpInst::ICMP_UGE) && - match(L0, m_c_Add(m_Specific(L1), m_Specific(R1)))) - return LPred == RPred; - } + if (L0 == R0 && + (LPred == ICmpInst::ICMP_ULT || LPred == ICmpInst::ICMP_UGE) && + (RPred == ICmpInst::ICMP_ULT || RPred == ICmpInst::ICMP_UGE) && + match(L0, m_c_Add(m_Specific(L1), m_Specific(R1)))) + return LPred == RPred; if (LPred == RPred) return isImpliedCondOperands(LPred, L0, L1, R0, R1, DL, Depth); @@ -8589,6 +8629,10 @@ llvm::isImpliedCondition(const Value *LHS, CmpInst::Predicate RHSPred, assert(LHS->getType()->isIntOrIntVectorTy(1) && "Expected integer type only!"); + // Match not + if (match(LHS, m_Not(m_Value(LHS)))) + LHSIsTrue = !LHSIsTrue; + // Both LHS and RHS are icmps. const ICmpInst *LHSCmp = dyn_cast<ICmpInst>(LHS); if (LHSCmp) @@ -8615,10 +8659,21 @@ std::optional<bool> llvm::isImpliedCondition(const Value *LHS, const Value *RHS, if (LHS == RHS) return LHSIsTrue; - if (const ICmpInst *RHSCmp = dyn_cast<ICmpInst>(RHS)) - return isImpliedCondition(LHS, RHSCmp->getPredicate(), - RHSCmp->getOperand(0), RHSCmp->getOperand(1), DL, - LHSIsTrue, Depth); + // Match not + bool InvertRHS = false; + if (match(RHS, m_Not(m_Value(RHS)))) { + if (LHS == RHS) + return !LHSIsTrue; + InvertRHS = true; + } + + if (const ICmpInst *RHSCmp = dyn_cast<ICmpInst>(RHS)) { + if (auto Implied = isImpliedCondition( + LHS, RHSCmp->getPredicate(), RHSCmp->getOperand(0), + RHSCmp->getOperand(1), DL, LHSIsTrue, Depth)) + return InvertRHS ? !*Implied : *Implied; + return std::nullopt; + } if (Depth == MaxAnalysisRecursionDepth) return std::nullopt; @@ -8630,21 +8685,21 @@ std::optional<bool> llvm::isImpliedCondition(const Value *LHS, const Value *RHS, if (std::optional<bool> Imp = isImpliedCondition(LHS, RHS1, DL, LHSIsTrue, Depth + 1)) if (*Imp == true) - return true; + return !InvertRHS; if (std::optional<bool> Imp = isImpliedCondition(LHS, RHS2, DL, LHSIsTrue, Depth + 1)) if (*Imp == true) - return true; + return !InvertRHS; } if (match(RHS, m_LogicalAnd(m_Value(RHS1), m_Value(RHS2)))) { if (std::optional<bool> Imp = isImpliedCondition(LHS, RHS1, DL, LHSIsTrue, Depth + 1)) if (*Imp == false) - return false; + return InvertRHS; if (std::optional<bool> Imp = isImpliedCondition(LHS, RHS2, DL, LHSIsTrue, Depth + 1)) if (*Imp == false) - return false; + return InvertRHS; } return std::nullopt; @@ -9114,12 +9169,19 @@ ConstantRange llvm::computeConstantRange(const Value *V, bool ForSigned, // TODO: Return ConstantRange. setLimitForFPToI(cast<Instruction>(V), Lower, Upper); CR = ConstantRange::getNonEmpty(Lower, Upper); - } + } else if (const auto *A = dyn_cast<Argument>(V)) + if (std::optional<ConstantRange> Range = A->getRange()) + CR = *Range; - if (auto *I = dyn_cast<Instruction>(V)) + if (auto *I = dyn_cast<Instruction>(V)) { if (auto *Range = IIQ.getMetadata(I, LLVMContext::MD_range)) CR = CR.intersectWith(getConstantRangeFromMetadata(*Range)); + if (const auto *CB = dyn_cast<CallBase>(V)) + if (std::optional<ConstantRange> Range = CB->getRange()) + CR = CR.intersectWith(*Range); + } + if (CtxI && AC) { // Try to restrict the range based on information from assumptions. for (auto &AssumeVH : AC->assumptionsFor(V)) { @@ -9223,7 +9285,7 @@ void llvm::findValuesAffectedByCondition( } else { // Handle (A + C1) u< C2, which is the canonical form of // A > C3 && A < C4. - if (match(A, m_Add(m_Value(X), m_ConstantInt())) && + if (match(A, m_AddLike(m_Value(X), m_ConstantInt())) && match(B, m_ConstantInt())) AddAffected(X); diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index 02f64fcfac4f0cf58a6ac0bec05e0b8d204544fe..2301a27731eaffc84fa2cd74ffe478309b0b9326 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -640,6 +640,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(tailcc); KEYWORD(m68k_rtdcc); KEYWORD(graalcc); + KEYWORD(riscv_vector_cc); KEYWORD(cc); KEYWORD(c); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 2e0f5ba82220c9c26e05756276832b76eec6d894..fe49e52ae4283c0dc36a4aa29b7560725df6e14a 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -2143,6 +2143,7 @@ void LLParser::parseOptionalDLLStorageClass(unsigned &Res) { /// ::= 'tailcc' /// ::= 'm68k_rtdcc' /// ::= 'graalcc' +/// ::= 'riscv_vector_cc' /// ::= 'cc' UINT /// bool LLParser::parseOptionalCallingConv(unsigned &CC) { @@ -2213,6 +2214,9 @@ bool LLParser::parseOptionalCallingConv(unsigned &CC) { case lltok::kw_tailcc: CC = CallingConv::Tail; break; case lltok::kw_m68k_rtdcc: CC = CallingConv::M68k_RTD; break; case lltok::kw_graalcc: CC = CallingConv::GRAAL; break; + case lltok::kw_riscv_vector_cc: + CC = CallingConv::RISCV_VectorCall; + break; case lltok::kw_cc: { Lex.Lex(); return parseUInt32(CC); @@ -4169,11 +4173,32 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) { unsigned Opc = Lex.getUIntVal(); SmallVector<Constant*, 16> Elts; bool InBounds = false; + bool HasInRange = false; + APSInt InRangeStart; + APSInt InRangeEnd; Type *Ty; Lex.Lex(); - if (Opc == Instruction::GetElementPtr) + if (Opc == Instruction::GetElementPtr) { InBounds = EatIfPresent(lltok::kw_inbounds); + if (EatIfPresent(lltok::kw_inrange)) { + if (parseToken(lltok::lparen, "expected '('")) + return true; + if (Lex.getKind() != lltok::APSInt) + return tokError("expected integer"); + InRangeStart = Lex.getAPSIntVal(); + Lex.Lex(); + if (parseToken(lltok::comma, "expected ','")) + return true; + if (Lex.getKind() != lltok::APSInt) + return tokError("expected integer"); + InRangeEnd = Lex.getAPSIntVal(); + Lex.Lex(); + if (parseToken(lltok::rparen, "expected ')'")) + return true; + HasInRange = true; + } + } if (parseToken(lltok::lparen, "expected '(' in constantexpr")) return true; @@ -4184,9 +4209,7 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) { return true; } - std::optional<unsigned> InRangeOp; - if (parseGlobalValueVector( - Elts, Opc == Instruction::GetElementPtr ? &InRangeOp : nullptr) || + if (parseGlobalValueVector(Elts) || parseToken(lltok::rparen, "expected ')' in constantexpr")) return true; @@ -4196,6 +4219,17 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) { return error(ID.Loc, "base of getelementptr must be a pointer"); Type *BaseType = Elts[0]->getType(); + std::optional<ConstantRange> InRange; + if (HasInRange) { + unsigned IndexWidth = + M->getDataLayout().getIndexTypeSizeInBits(BaseType); + InRangeStart = InRangeStart.extOrTrunc(IndexWidth); + InRangeEnd = InRangeEnd.extOrTrunc(IndexWidth); + if (InRangeStart.sge(InRangeEnd)) + return error(ID.Loc, "expected end to be larger than start"); + InRange = ConstantRange::getNonEmpty(InRangeStart, InRangeEnd); + } + unsigned GEPWidth = BaseType->isVectorTy() ? cast<FixedVectorType>(BaseType)->getNumElements() @@ -4225,15 +4259,8 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) { if (!GetElementPtrInst::getIndexedType(Ty, Indices)) return error(ID.Loc, "invalid getelementptr indices"); - if (InRangeOp) { - if (*InRangeOp == 0) - return error(ID.Loc, - "inrange keyword may not appear on pointer operand"); - --*InRangeOp; - } - ID.ConstantVal = ConstantExpr::getGetElementPtr(Ty, Elts[0], Indices, - InBounds, InRangeOp); + InBounds, InRange); } else if (Opc == Instruction::ShuffleVector) { if (Elts.size() != 3) return error(ID.Loc, "expected three operands to shufflevector"); @@ -4309,9 +4336,8 @@ bool LLParser::parseOptionalComdat(StringRef GlobalName, Comdat *&C) { /// parseGlobalValueVector /// ::= /*empty*/ -/// ::= [inrange] TypeAndValue (',' [inrange] TypeAndValue)* -bool LLParser::parseGlobalValueVector(SmallVectorImpl<Constant *> &Elts, - std::optional<unsigned> *InRangeOp) { +/// ::= TypeAndValue (',' TypeAndValue)* +bool LLParser::parseGlobalValueVector(SmallVectorImpl<Constant *> &Elts) { // Empty list. if (Lex.getKind() == lltok::rbrace || Lex.getKind() == lltok::rsquare || @@ -4320,8 +4346,9 @@ bool LLParser::parseGlobalValueVector(SmallVectorImpl<Constant *> &Elts, return false; do { - if (InRangeOp && !*InRangeOp && EatIfPresent(lltok::kw_inrange)) - *InRangeOp = Elts.size(); + // Let the caller deal with inrange. + if (Lex.getKind() == lltok::kw_inrange) + return false; Constant *C; if (parseGlobalTypeAndValue(C)) @@ -5184,7 +5211,11 @@ bool LLParser::parseDIStringType(MDNode *&Result, bool IsDistinct) { /// ::= !DIDerivedType(tag: DW_TAG_pointer_type, name: "int", file: !0, /// line: 7, scope: !1, baseType: !2, size: 32, /// align: 32, offset: 0, flags: 0, extraData: !3, -/// dwarfAddressSpace: 3) +/// dwarfAddressSpace: 3, ptrAuthKey: 1, +/// ptrAuthIsAddressDiscriminated: true, +/// ptrAuthExtraDiscriminator: 0x1234, +/// ptrAuthIsaPointer: 1, ptrAuthAuthenticatesNullValues:1 +/// ) bool LLParser::parseDIDerivedType(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ REQUIRED(tag, DwarfTagField, ); \ @@ -5199,19 +5230,30 @@ bool LLParser::parseDIDerivedType(MDNode *&Result, bool IsDistinct) { OPTIONAL(flags, DIFlagField, ); \ OPTIONAL(extraData, MDField, ); \ OPTIONAL(dwarfAddressSpace, MDUnsignedField, (UINT32_MAX, UINT32_MAX)); \ - OPTIONAL(annotations, MDField, ); + OPTIONAL(annotations, MDField, ); \ + OPTIONAL(ptrAuthKey, MDUnsignedField, (0, 7)); \ + OPTIONAL(ptrAuthIsAddressDiscriminated, MDBoolField, ); \ + OPTIONAL(ptrAuthExtraDiscriminator, MDUnsignedField, (0, 0xffff)); \ + OPTIONAL(ptrAuthIsaPointer, MDBoolField, ); \ + OPTIONAL(ptrAuthAuthenticatesNullValues, MDBoolField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS std::optional<unsigned> DWARFAddressSpace; if (dwarfAddressSpace.Val != UINT32_MAX) DWARFAddressSpace = dwarfAddressSpace.Val; + std::optional<DIDerivedType::PtrAuthData> PtrAuthData; + if (ptrAuthKey.Val) + PtrAuthData.emplace( + (unsigned)ptrAuthKey.Val, ptrAuthIsAddressDiscriminated.Val, + (unsigned)ptrAuthExtraDiscriminator.Val, ptrAuthIsaPointer.Val, + ptrAuthAuthenticatesNullValues.Val); Result = GET_OR_DISTINCT(DIDerivedType, (Context, tag.Val, name.Val, file.Val, line.Val, scope.Val, baseType.Val, size.Val, align.Val, - offset.Val, DWARFAddressSpace, flags.Val, - extraData.Val, annotations.Val)); + offset.Val, DWARFAddressSpace, PtrAuthData, + flags.Val, extraData.Val, annotations.Val)); return false; } @@ -6543,10 +6585,10 @@ bool LLParser::parseBasicBlock(PerFunctionState &PFS) { /// (MDNode ',' Metadata ',' Metadata ',')? MDNode ')' bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) { using RecordKind = DbgRecord::Kind; - using LocType = DPValue::LocationType; - LocTy DPVLoc = Lex.getLoc(); + using LocType = DbgVariableRecord::LocationType; + LocTy DVRLoc = Lex.getLoc(); if (Lex.getKind() != lltok::DbgRecordType) - return error(DPVLoc, "expected debug record type here"); + return error(DVRLoc, "expected debug record type here"); RecordKind RecordType = StringSwitch<RecordKind>(Lex.getStrVal()) .Case("declare", RecordKind::ValueKind) .Case("value", RecordKind::ValueKind) @@ -6554,7 +6596,7 @@ bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) { .Case("label", RecordKind::LabelKind); // Parsing labels is trivial; parse here and early exit, otherwise go into the - // full DPValue processing stage. + // full DbgVariableRecord processing stage. if (RecordType == RecordKind::LabelKind) { Lex.Lex(); if (parseToken(lltok::lparen, "Expected '(' here")) @@ -6569,7 +6611,7 @@ bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) { return true; if (parseToken(lltok::rparen, "Expected ')' here")) return true; - DR = DPLabel::createUnresolvedDPLabel(Label, DbgLoc); + DR = DbgLabelRecord::createUnresolvedDbgLabelRecord(Label, DbgLoc); return false; } @@ -6634,9 +6676,9 @@ bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) { if (parseToken(lltok::rparen, "Expected ')' here")) return true; - DR = DPValue::createUnresolvedDPValue(ValueType, ValLocMD, Variable, - Expression, AssignID, AddressLocation, - AddressExpression, DebugLoc); + DR = DbgVariableRecord::createUnresolvedDbgVariableRecord( + ValueType, ValLocMD, Variable, Expression, AssignID, AddressLocation, + AddressExpression, DebugLoc); return false; } //===----------------------------------------------------------------------===// @@ -6772,7 +6814,19 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB, Inst->setNonNeg(); return 0; } - case lltok::kw_trunc: + case lltok::kw_trunc: { + bool NUW = EatIfPresent(lltok::kw_nuw); + bool NSW = EatIfPresent(lltok::kw_nsw); + if (!NUW) + NUW = EatIfPresent(lltok::kw_nuw); + if (parseCast(Inst, PFS, KeywordVal)) + return true; + if (NUW) + cast<TruncInst>(Inst)->setHasNoUnsignedWrap(true); + if (NSW) + cast<TruncInst>(Inst)->setHasNoSignedWrap(true); + return false; + } case lltok::kw_sext: case lltok::kw_fptrunc: case lltok::kw_fpext: @@ -8349,7 +8403,7 @@ int LLParser::parseInsertValue(Instruction *&Inst, PerFunctionState &PFS) { /// parseMDNodeVector /// ::= { Element (',' Element)* } /// Element -/// ::= 'null' | TypeAndValue +/// ::= 'null' | Metadata bool LLParser::parseMDNodeVector(SmallVectorImpl<Metadata *> &Elts) { if (parseToken(lltok::lbrace, "expected '{' here")) return true; @@ -8359,7 +8413,6 @@ bool LLParser::parseMDNodeVector(SmallVectorImpl<Metadata *> &Elts) { return false; do { - // Null is a special case since it is typeless. if (EatIfPresent(lltok::kw_null)) { Elts.push_back(nullptr); continue; diff --git a/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp b/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp index 7005011980ebc9552315929676adc988420a7b8c..c085c715179ba69515428ec88946e30bd826b07c 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp @@ -270,6 +270,11 @@ GetCodeName(unsigned CodeID, unsigned BlockID, STRINGIFY_CODE(FUNC_CODE, INST_CMPXCHG) STRINGIFY_CODE(FUNC_CODE, INST_CALLBR) STRINGIFY_CODE(FUNC_CODE, BLOCKADDR_USERS) + STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_DECLARE) + STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_VALUE) + STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_ASSIGN) + STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_VALUE_SIMPLE) + STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_LABEL) } case bitc::VALUE_SYMTAB_BLOCK_ID: switch (CodeID) { diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 9c63116114f3c5161bbee9079baa55bdc57383e6..aa6c9c95ca24038eaae2699ac444840fa84d0221 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -100,8 +100,14 @@ static cl::opt<bool> ExpandConstantExprs( cl::desc( "Expand constant expressions to instructions for testing purposes")); -// Declare external flag for whether we're using the new debug-info format. -extern llvm::cl::opt<bool> UseNewDbgInfoFormat; +/// Load bitcode directly into RemoveDIs format (use debug records instead +/// of debug intrinsics). UNSET is treated as FALSE, so the default action +/// is to do nothing. Individual tools can override this to incrementally add +/// support for the RemoveDIs format. +cl::opt<cl::boolOrDefault> LoadBitcodeIntoNewDbgInfoFormat( + "load-bitcode-into-experimental-debuginfo-iterators", cl::Hidden, + cl::desc("Load bitcode directly into the new debug info format (regardless " + "of input format)")); namespace { @@ -514,25 +520,31 @@ public: struct ExtraInfo { uint8_t Opcode; uint8_t Flags; - unsigned Extra; - Type *SrcElemTy; + unsigned BlockAddressBB = 0; + Type *SrcElemTy = nullptr; + std::optional<ConstantRange> InRange; - ExtraInfo(uint8_t Opcode, uint8_t Flags = 0, unsigned Extra = 0, - Type *SrcElemTy = nullptr) - : Opcode(Opcode), Flags(Flags), Extra(Extra), SrcElemTy(SrcElemTy) {} + ExtraInfo(uint8_t Opcode, uint8_t Flags = 0, Type *SrcElemTy = nullptr, + std::optional<ConstantRange> InRange = std::nullopt) + : Opcode(Opcode), Flags(Flags), SrcElemTy(SrcElemTy), + InRange(std::move(InRange)) {} + + ExtraInfo(uint8_t Opcode, uint8_t Flags, unsigned BlockAddressBB) + : Opcode(Opcode), Flags(Flags), BlockAddressBB(BlockAddressBB) {} }; uint8_t Opcode; uint8_t Flags; unsigned NumOperands; - unsigned Extra; // GEP inrange index or blockaddress BB id. + unsigned BlockAddressBB; Type *SrcElemTy; // GEP source element type. + std::optional<ConstantRange> InRange; // GEP inrange attribute. private: BitcodeConstant(Type *Ty, const ExtraInfo &Info, ArrayRef<unsigned> OpIDs) : Value(Ty, SubclassID), Opcode(Info.Opcode), Flags(Info.Flags), - NumOperands(OpIDs.size()), Extra(Info.Extra), - SrcElemTy(Info.SrcElemTy) { + NumOperands(OpIDs.size()), BlockAddressBB(Info.BlockAddressBB), + SrcElemTy(Info.SrcElemTy), InRange(Info.InRange) { std::uninitialized_copy(OpIDs.begin(), OpIDs.end(), getTrailingObjects<unsigned>()); } @@ -554,11 +566,9 @@ public: return ArrayRef(getTrailingObjects<unsigned>(), NumOperands); } - std::optional<unsigned> getInRangeIndex() const { + std::optional<ConstantRange> getInRange() const { assert(Opcode == Instruction::GetElementPtr); - if (Extra == (unsigned)-1) - return std::nullopt; - return Extra; + return InRange; } const char *getOpcodeName() const { @@ -1553,7 +1563,7 @@ Expected<Value *> BitcodeReader::materializeValue(unsigned StartValID, // If the function is already parsed we can insert the block address // right away. BasicBlock *BB; - unsigned BBID = BC->Extra; + unsigned BBID = BC->BlockAddressBB; if (!BBID) // Invalid reference to entry block. return error("Invalid ID"); @@ -1596,7 +1606,7 @@ Expected<Value *> BitcodeReader::materializeValue(unsigned StartValID, case Instruction::GetElementPtr: C = ConstantExpr::getGetElementPtr(BC->SrcElemTy, ConstOps[0], ArrayRef(ConstOps).drop_front(), - BC->Flags, BC->getInRangeIndex()); + BC->Flags, BC->getInRange()); break; case Instruction::ExtractElement: C = ConstantExpr::getExtractElement(ConstOps[0], ConstOps[1]); @@ -3302,22 +3312,34 @@ Error BitcodeReader::parseConstants() { } case bitc::CST_CODE_CE_INBOUNDS_GEP: // [ty, n x operands] case bitc::CST_CODE_CE_GEP: // [ty, n x operands] - case bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX: { // [ty, flags, n x - // operands] + case bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX_OLD: // [ty, flags, n x + // operands] + case bitc::CST_CODE_CE_GEP_WITH_INRANGE: { // [ty, flags, start, end, n x + // operands] if (Record.size() < 2) return error("Constant GEP record must have at least two elements"); unsigned OpNum = 0; Type *PointeeType = nullptr; - if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX || - Record.size() % 2) + if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX_OLD || + BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE || Record.size() % 2) PointeeType = getTypeByID(Record[OpNum++]); bool InBounds = false; - std::optional<unsigned> InRangeIndex; - if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX) { + std::optional<ConstantRange> InRange; + if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX_OLD) { + uint64_t Op = Record[OpNum++]; + InBounds = Op & 1; + unsigned InRangeIndex = Op >> 1; + // "Upgrade" inrange by dropping it. The feature is too niche to + // bother. + (void)InRangeIndex; + } else if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE) { uint64_t Op = Record[OpNum++]; InBounds = Op & 1; - InRangeIndex = Op >> 1; + Expected<ConstantRange> MaybeInRange = readConstantRange(Record, OpNum); + if (!MaybeInRange) + return MaybeInRange.takeError(); + InRange = MaybeInRange.get(); } else if (BitCode == bitc::CST_CODE_CE_INBOUNDS_GEP) InBounds = true; @@ -3350,10 +3372,9 @@ Error BitcodeReader::parseConstants() { return error("Missing element type for old-style constant GEP"); } - V = BitcodeConstant::create(Alloc, CurTy, - {Instruction::GetElementPtr, InBounds, - InRangeIndex.value_or(-1), PointeeType}, - Elts); + V = BitcodeConstant::create( + Alloc, CurTy, + {Instruction::GetElementPtr, InBounds, PointeeType, InRange}, Elts); break; } case bitc::CST_CODE_CE_SELECT: { // CE_SELECT: [opval#, opval#, opval#] @@ -4279,6 +4300,12 @@ Error BitcodeReader::parseGlobalIndirectSymbolRecord( Error BitcodeReader::parseModule(uint64_t ResumeBit, bool ShouldLazyLoadMetadata, ParserCallbacks Callbacks) { + // Load directly into RemoveDIs format if LoadBitcodeIntoNewDbgInfoFormat + // has been set to true (default action: load into the old debug format). + TheModule->IsNewDbgInfoFormat = + UseNewDbgInfoFormat && + LoadBitcodeIntoNewDbgInfoFormat == cl::boolOrDefault::BOU_TRUE; + this->ValueTypeCallback = std::move(Callbacks.ValueType); if (ResumeBit) { if (Error JumpFailed = Stream.JumpToBit(ResumeBit)) @@ -4995,9 +5022,19 @@ Error BitcodeReader::parseFunctionBody(Function *F) { return error("Invalid cast"); I = CastInst::Create(CastOp, Op, ResTy); } - if (OpNum < Record.size() && isa<PossiblyNonNegInst>(I) && - (Record[OpNum] & (1 << bitc::PNNI_NON_NEG))) - I->setNonNeg(true); + + if (OpNum < Record.size()) { + if (Opc == Instruction::ZExt) { + if (Record[OpNum] & (1 << bitc::PNNI_NON_NEG)) + cast<PossiblyNonNegInst>(I)->setNonNeg(true); + } else if (Opc == Instruction::Trunc) { + if (Record[OpNum] & (1 << bitc::TIO_NO_UNSIGNED_WRAP)) + cast<TruncInst>(I)->setHasNoUnsignedWrap(true); + if (Record[OpNum] & (1 << bitc::TIO_NO_SIGNED_WRAP)) + cast<TruncInst>(I)->setHasNoSignedWrap(true); + } + } + InstructionList.push_back(I); break; } @@ -6398,6 +6435,92 @@ Error BitcodeReader::parseFunctionBody(Function *F) { InstructionList.push_back(I); break; } + case bitc::FUNC_CODE_DEBUG_RECORD_LABEL: { + // DbgLabelRecords are placed after the Instructions that they are + // attached to. + Instruction *Inst = getLastInstruction(); + if (!Inst) + return error("Invalid dbg record: missing instruction"); + DILocation *DIL = cast<DILocation>(getFnMetadataByID(Record[0])); + DILabel *Label = cast<DILabel>(getFnMetadataByID(Record[1])); + Inst->getParent()->insertDbgRecordBefore( + new DbgLabelRecord(Label, DebugLoc(DIL)), Inst->getIterator()); + continue; // This isn't an instruction. + } + case bitc::FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE: + case bitc::FUNC_CODE_DEBUG_RECORD_VALUE: + case bitc::FUNC_CODE_DEBUG_RECORD_DECLARE: + case bitc::FUNC_CODE_DEBUG_RECORD_ASSIGN: { + // DbgVariableRecords are placed after the Instructions that they are + // attached to. + Instruction *Inst = getLastInstruction(); + if (!Inst) + return error("Invalid dbg record: missing instruction"); + + // First 3 fields are common to all kinds: + // DILocation, DILocalVariable, DIExpression + // dbg_value (FUNC_CODE_DEBUG_RECORD_VALUE) + // ..., LocationMetadata + // dbg_value (FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE - abbrev'd) + // ..., Value + // dbg_declare (FUNC_CODE_DEBUG_RECORD_DECLARE) + // ..., LocationMetadata + // dbg_assign (FUNC_CODE_DEBUG_RECORD_ASSIGN) + // ..., LocationMetadata, DIAssignID, DIExpression, LocationMetadata + unsigned Slot = 0; + // Common fields (0-2). + DILocation *DIL = cast<DILocation>(getFnMetadataByID(Record[Slot++])); + DILocalVariable *Var = + cast<DILocalVariable>(getFnMetadataByID(Record[Slot++])); + DIExpression *Expr = + cast<DIExpression>(getFnMetadataByID(Record[Slot++])); + + // Union field (3: LocationMetadata | Value). + Metadata *RawLocation = nullptr; + if (BitCode == bitc::FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE) { + Value *V = nullptr; + unsigned TyID = 0; + // We never expect to see a fwd reference value here because + // use-before-defs are encoded with the standard non-abbrev record + // type (they'd require encoding the type too, and they're rare). As a + // result, getValueTypePair only ever increments Slot by one here (once + // for the value, never twice for value and type). + unsigned SlotBefore = Slot; + if (getValueTypePair(Record, Slot, NextValueNo, V, TyID, CurBB)) + return error("Invalid dbg record: invalid value"); + (void)SlotBefore; + assert((SlotBefore == Slot - 1) && "unexpected fwd ref"); + RawLocation = ValueAsMetadata::get(V); + } else { + RawLocation = getFnMetadataByID(Record[Slot++]); + } + + DbgVariableRecord *DVR = nullptr; + switch (BitCode) { + case bitc::FUNC_CODE_DEBUG_RECORD_VALUE: + case bitc::FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE: + DVR = new DbgVariableRecord(RawLocation, Var, Expr, DIL, + DbgVariableRecord::LocationType::Value); + break; + case bitc::FUNC_CODE_DEBUG_RECORD_DECLARE: + DVR = new DbgVariableRecord(RawLocation, Var, Expr, DIL, + DbgVariableRecord::LocationType::Declare); + break; + case bitc::FUNC_CODE_DEBUG_RECORD_ASSIGN: { + DIAssignID *ID = cast<DIAssignID>(getFnMetadataByID(Record[Slot++])); + DIExpression *AddrExpr = + cast<DIExpression>(getFnMetadataByID(Record[Slot++])); + Metadata *Addr = getFnMetadataByID(Record[Slot++]); + DVR = new DbgVariableRecord(RawLocation, Var, Expr, ID, Addr, AddrExpr, + DIL); + break; + } + default: + llvm_unreachable("Unknown DbgVariableRecord bitcode"); + } + Inst->getParent()->insertDbgRecordBefore(DVR, Inst->getIterator()); + continue; // This isn't an instruction. + } case bitc::FUNC_CODE_INST_CALL: { // CALL: [paramattrs, cc, fmf, fnty, fnid, arg0, arg1...] if (Record.size() < 3) @@ -6677,10 +6800,22 @@ Error BitcodeReader::materialize(GlobalValue *GV) { // Move the bit stream to the saved position of the deferred function body. if (Error JumpFailed = Stream.JumpToBit(DFII->second)) return JumpFailed; + + // Set the debug info mode to "new", possibly creating a mismatch between + // module and function debug modes. This is okay because we'll convert + // everything back to the old mode after parsing if needed. + // FIXME: Remove this once all tools support RemoveDIs. + F->IsNewDbgInfoFormat = true; + if (Error Err = parseFunctionBody(F)) return Err; F->setIsMaterializable(false); + // Convert new debug info records into intrinsics. + // FIXME: Remove this once all tools support RemoveDIs. + if (!F->getParent()->IsNewDbgInfoFormat) + F->convertFromNewDbgValues(); + if (StripDebugInfo) stripDebugInfo(*F); diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index 770eb83af17f9b012b2391593ec299c450981ee2..9102f3a60cffc2ae433348d0e7ed7b6bba7a3b22 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -609,17 +609,25 @@ class MetadataLoader::MetadataLoaderImpl { if (!NeedDeclareExpressionUpgrade) return; + auto UpdateDeclareIfNeeded = [&](auto *Declare) { + auto *DIExpr = Declare->getExpression(); + if (!DIExpr || !DIExpr->startsWithDeref() || + !isa_and_nonnull<Argument>(Declare->getAddress())) + return; + SmallVector<uint64_t, 8> Ops; + Ops.append(std::next(DIExpr->elements_begin()), DIExpr->elements_end()); + Declare->setExpression(DIExpression::get(Context, Ops)); + }; + for (auto &BB : F) - for (auto &I : BB) + for (auto &I : BB) { + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { + if (DVR.isDbgDeclare()) + UpdateDeclareIfNeeded(&DVR); + } if (auto *DDI = dyn_cast<DbgDeclareInst>(&I)) - if (auto *DIExpr = DDI->getExpression()) - if (DIExpr->startsWithDeref() && - isa_and_nonnull<Argument>(DDI->getAddress())) { - SmallVector<uint64_t, 8> Ops; - Ops.append(std::next(DIExpr->elements_begin()), - DIExpr->elements_end()); - DDI->setExpression(DIExpression::get(Context, Ops)); - } + UpdateDeclareIfNeeded(DDI); + } } /// Upgrade the expression from previous versions. @@ -1556,7 +1564,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( break; } case bitc::METADATA_DERIVED_TYPE: { - if (Record.size() < 12 || Record.size() > 14) + if (Record.size() < 12 || Record.size() > 15) return error("Invalid record"); // DWARF address space is encoded as N->getDWARFAddressSpace() + 1. 0 means @@ -1566,8 +1574,17 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( DWARFAddressSpace = Record[12] - 1; Metadata *Annotations = nullptr; - if (Record.size() > 13 && Record[13]) - Annotations = getMDOrNull(Record[13]); + std::optional<DIDerivedType::PtrAuthData> PtrAuthData; + + // Only look for annotations/ptrauth if both are allocated. + // If not, we can't tell which was intended to be embedded, as both ptrauth + // and annotations have been expected at Record[13] at various times. + if (Record.size() > 14) { + if (Record[13]) + Annotations = getMDOrNull(Record[13]); + if (Record[14]) + PtrAuthData.emplace(Record[14]); + } IsDistinct = Record[0]; DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[10]); @@ -1577,7 +1594,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( getMDOrNull(Record[3]), Record[4], getDITypeRefOrNull(Record[5]), getDITypeRefOrNull(Record[6]), Record[7], Record[8], - Record[9], DWARFAddressSpace, Flags, + Record[9], DWARFAddressSpace, PtrAuthData, Flags, getDITypeRefOrNull(Record[11]), Annotations)), NextMetadataNo); NextMetadataNo++; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 597f49332fad25e7f3999a1689022e11e17aabd8..dd554e422516f65b1fcfcd3cd55ba9f0fb5e2756 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -99,6 +99,9 @@ namespace llvm { extern FunctionSummary::ForceSummaryHotnessType ForceSummaryEdgesCold; } +extern bool WriteNewDbgInfoFormatToBitcode; +extern llvm::cl::opt<bool> UseNewDbgInfoFormat; + namespace { /// These are manifest constants used by the bitcode writer. They do not need to @@ -128,6 +131,7 @@ enum { FUNCTION_INST_RET_VAL_ABBREV, FUNCTION_INST_UNREACHABLE_ABBREV, FUNCTION_INST_GEP_ABBREV, + FUNCTION_DEBUG_RECORD_VALUE_ABBREV, }; /// Abstract class to manage the bitcode writing, subclassed for each bitcode @@ -199,7 +203,7 @@ public: for (const auto &GUIDSummaryLists : *Index) // Examine all summaries for this GUID. for (auto &Summary : GUIDSummaryLists.second.SummaryList) - if (auto FS = dyn_cast<FunctionSummary>(Summary.get())) + if (auto FS = dyn_cast<FunctionSummary>(Summary.get())) { // For each call in the function summary, see if the call // is to a GUID (which means it is for an indirect call, // otherwise we would have a Value for it). If so, synthesize @@ -207,6 +211,15 @@ public: for (auto &CallEdge : FS->calls()) if (!CallEdge.first.haveGVs() || !CallEdge.first.getValue()) assignValueId(CallEdge.first.getGUID()); + + // For each referenced variables in the function summary, see if the + // variable is represented by a GUID (as opposed to a symbol to + // declarations or definitions in the module). If so, synthesize a + // value id. + for (auto &RefEdge : FS->refs()) + if (!RefEdge.haveGVs() || !RefEdge.getValue()) + assignValueId(RefEdge.getGUID()); + } } protected: @@ -1636,6 +1649,11 @@ static uint64_t getOptimizationFlags(const Value *V) { } else if (const auto *NNI = dyn_cast<PossiblyNonNegInst>(V)) { if (NNI->hasNonNeg()) Flags |= 1 << bitc::PNNI_NON_NEG; + } else if (const auto *TI = dyn_cast<TruncInst>(V)) { + if (TI->hasNoSignedWrap()) + Flags |= 1 << bitc::TIO_NO_SIGNED_WRAP; + if (TI->hasNoUnsignedWrap()) + Flags |= 1 << bitc::TIO_NO_UNSIGNED_WRAP; } return Flags; @@ -1825,6 +1843,11 @@ void ModuleBitcodeWriter::writeDIDerivedType(const DIDerivedType *N, Record.push_back(VE.getMetadataOrNullID(N->getAnnotations().get())); + if (auto PtrAuthData = N->getPtrAuthData()) + Record.push_back(PtrAuthData->RawData); + else + Record.push_back(0); + Stream.EmitRecord(bitc::METADATA_DERIVED_TYPE, Record, Abbrev); Record.clear(); } @@ -2742,9 +2765,10 @@ void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal, Code = bitc::CST_CODE_CE_GEP; const auto *GO = cast<GEPOperator>(C); Record.push_back(VE.getTypeID(GO->getSourceElementType())); - if (std::optional<unsigned> Idx = GO->getInRangeIndex()) { - Code = bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX; - Record.push_back((*Idx << 1) | GO->isInBounds()); + if (std::optional<ConstantRange> Range = GO->getInRange()) { + Code = bitc::CST_CODE_CE_GEP_WITH_INRANGE; + Record.push_back(GO->isInBounds()); + emitConstantRange(Record, *Range); } else if (GO->isInBounds()) Code = bitc::CST_CODE_CE_INBOUNDS_GEP; for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) { @@ -3512,25 +3536,96 @@ void ModuleBitcodeWriter::writeFunction( NeedsMetadataAttachment |= I.hasMetadataOtherThanDebugLoc(); // If the instruction has a debug location, emit it. - DILocation *DL = I.getDebugLoc(); - if (!DL) - continue; - - if (DL == LastDL) { - // Just repeat the same debug loc as last time. - Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC_AGAIN, Vals); - continue; + if (DILocation *DL = I.getDebugLoc()) { + if (DL == LastDL) { + // Just repeat the same debug loc as last time. + Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC_AGAIN, Vals); + } else { + Vals.push_back(DL->getLine()); + Vals.push_back(DL->getColumn()); + Vals.push_back(VE.getMetadataOrNullID(DL->getScope())); + Vals.push_back(VE.getMetadataOrNullID(DL->getInlinedAt())); + Vals.push_back(DL->isImplicitCode()); + Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC, Vals); + Vals.clear(); + LastDL = DL; + } } - Vals.push_back(DL->getLine()); - Vals.push_back(DL->getColumn()); - Vals.push_back(VE.getMetadataOrNullID(DL->getScope())); - Vals.push_back(VE.getMetadataOrNullID(DL->getInlinedAt())); - Vals.push_back(DL->isImplicitCode()); - Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC, Vals); - Vals.clear(); - - LastDL = DL; + // If the instruction has DbgRecords attached to it, emit them. Note that + // they come after the instruction so that it's easy to attach them again + // when reading the bitcode, even though conceptually the debug locations + // start "before" the instruction. + if (I.hasDbgRecords() && WriteNewDbgInfoFormatToBitcode) { + /// Try to push the value only (unwrapped), otherwise push the + /// metadata wrapped value. Returns true if the value was pushed + /// without the ValueAsMetadata wrapper. + auto PushValueOrMetadata = [&Vals, InstID, + this](Metadata *RawLocation) { + assert(RawLocation && + "RawLocation unexpectedly null in DbgVariableRecord"); + if (ValueAsMetadata *VAM = dyn_cast<ValueAsMetadata>(RawLocation)) { + SmallVector<unsigned, 2> ValAndType; + // If the value is a fwd-ref the type is also pushed. We don't + // want the type, so fwd-refs are kept wrapped (pushValueAndType + // returns false if the value is pushed without type). + if (!pushValueAndType(VAM->getValue(), InstID, ValAndType)) { + Vals.push_back(ValAndType[0]); + return true; + } + } + // The metadata is a DIArgList, or ValueAsMetadata wrapping a + // fwd-ref. Push the metadata ID. + Vals.push_back(VE.getMetadataID(RawLocation)); + return false; + }; + + // Write out non-instruction debug information attached to this + // instruction. Write it after the instruction so that it's easy to + // re-attach to the instruction reading the records in. + for (DbgRecord &DR : I.DebugMarker->getDbgRecordRange()) { + if (DbgLabelRecord *DLR = dyn_cast<DbgLabelRecord>(&DR)) { + Vals.push_back(VE.getMetadataID(&*DLR->getDebugLoc())); + Vals.push_back(VE.getMetadataID(DLR->getLabel())); + Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_LABEL, Vals); + Vals.clear(); + continue; + } + + // First 3 fields are common to all kinds: + // DILocation, DILocalVariable, DIExpression + // dbg_value (FUNC_CODE_DEBUG_RECORD_VALUE) + // ..., LocationMetadata + // dbg_value (FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE - abbrev'd) + // ..., Value + // dbg_declare (FUNC_CODE_DEBUG_RECORD_DECLARE) + // ..., LocationMetadata + // dbg_assign (FUNC_CODE_DEBUG_RECORD_ASSIGN) + // ..., LocationMetadata, DIAssignID, DIExpression, LocationMetadata + DbgVariableRecord &DVR = cast<DbgVariableRecord>(DR); + Vals.push_back(VE.getMetadataID(&*DVR.getDebugLoc())); + Vals.push_back(VE.getMetadataID(DVR.getVariable())); + Vals.push_back(VE.getMetadataID(DVR.getExpression())); + if (DVR.isDbgValue()) { + if (PushValueOrMetadata(DVR.getRawLocation())) + Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE, Vals, + FUNCTION_DEBUG_RECORD_VALUE_ABBREV); + else + Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_VALUE, Vals); + } else if (DVR.isDbgDeclare()) { + Vals.push_back(VE.getMetadataID(DVR.getRawLocation())); + Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_DECLARE, Vals); + } else { + assert(DVR.isDbgAssign() && "Unexpected DbgRecord kind"); + Vals.push_back(VE.getMetadataID(DVR.getRawLocation())); + Vals.push_back(VE.getMetadataID(DVR.getAssignID())); + Vals.push_back(VE.getMetadataID(DVR.getAddressExpression())); + Vals.push_back(VE.getMetadataID(DVR.getRawAddress())); + Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_ASSIGN, Vals); + } + Vals.clear(); + } + } } if (BlockAddress *BA = BlockAddress::lookup(&BB)) { @@ -3771,7 +3866,17 @@ void ModuleBitcodeWriter::writeBlockInfo() { FUNCTION_INST_GEP_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } - + { + auto Abbv = std::make_shared<BitCodeAbbrev>(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // dbgloc + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // var + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 7)); // expr + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // val + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != + FUNCTION_DEBUG_RECORD_VALUE_ABBREV) + llvm_unreachable("Unexpected abbrev ordering! 1"); + } Stream.ExitBlock(); } @@ -4092,7 +4197,7 @@ void ModuleBitcodeWriterBase::writePerModuleFunctionSummaryRecord( NameVals.push_back(SpecialRefCnts.second); // worefcnt for (auto &RI : FS->refs()) - NameVals.push_back(VE.getValueID(RI.getValue())); + NameVals.push_back(getValueId(RI)); const bool UseRelBFRecord = WriteRelBFToSummary && !F.hasProfileData() && diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp index 93fb2a821dee7451d6e045c23e69ba0315ebefb3..de2396f31f6669d72f3fc82e13f7a1776c803ba8 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp @@ -18,11 +18,12 @@ #include "llvm/Pass.h" using namespace llvm; +extern bool WriteNewDbgInfoFormatToBitcode; + PreservedAnalyses BitcodeWriterPass::run(Module &M, ModuleAnalysisManager &AM) { - // RemoveDIs: there's no bitcode representation of the DPValue debug-info, - // convert to dbg.values before writing out. - bool IsNewDbgInfoFormat = M.IsNewDbgInfoFormat; - if (IsNewDbgInfoFormat) + bool ConvertToOldDbgFormatForWrite = + M.IsNewDbgInfoFormat && !WriteNewDbgInfoFormatToBitcode; + if (ConvertToOldDbgFormatForWrite) M.convertFromNewDbgValues(); const ModuleSummaryIndex *Index = @@ -30,7 +31,7 @@ PreservedAnalyses BitcodeWriterPass::run(Module &M, ModuleAnalysisManager &AM) { : nullptr; WriteBitcodeToFile(M, OS, ShouldPreserveUseListOrder, Index, EmitModuleHash); - if (IsNewDbgInfoFormat) + if (ConvertToOldDbgFormatForWrite) M.convertToNewDbgValues(); return PreservedAnalyses::all(); @@ -56,16 +57,15 @@ namespace { StringRef getPassName() const override { return "Bitcode Writer"; } bool runOnModule(Module &M) override { - // RemoveDIs: there's no bitcode representation of the DPValue debug-info, - // convert to dbg.values before writing out. - bool IsNewDbgInfoFormat = M.IsNewDbgInfoFormat; - if (IsNewDbgInfoFormat) + bool ConvertToOldDbgFormatForWrite = + M.IsNewDbgInfoFormat && !WriteNewDbgInfoFormatToBitcode; + if (ConvertToOldDbgFormatForWrite) M.convertFromNewDbgValues(); WriteBitcodeToFile(M, OS, ShouldPreserveUseListOrder, /*Index=*/nullptr, /*EmitModuleHash=*/false); - if (IsNewDbgInfoFormat) + if (ConvertToOldDbgFormatForWrite) M.convertToNewDbgValues(); return false; } diff --git a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp index fccb2a606f7ed9f92d40acff88b265425ebe85fd..e6787e245a49b2aead271890d67cd5dcf1d5d796 100644 --- a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -134,20 +134,28 @@ static OrderMap orderModule(const Module &M) { // Metadata used by instructions is decoded before the actual instructions, // so visit any constants used by it beforehand. for (const BasicBlock &BB : F) - for (const Instruction &I : BB) - for (const Value *V : I.operands()) { - if (const auto *MAV = dyn_cast<MetadataAsValue>(V)) { - if (const auto *VAM = - dyn_cast<ValueAsMetadata>(MAV->getMetadata())) { + for (const Instruction &I : BB) { + auto OrderConstantFromMetadata = [&](Metadata *MD) { + if (const auto *VAM = dyn_cast<ValueAsMetadata>(MD)) { + orderConstantValue(VAM->getValue()); + } else if (const auto *AL = dyn_cast<DIArgList>(MD)) { + for (const auto *VAM : AL->getArgs()) orderConstantValue(VAM->getValue()); - } else if (const auto *AL = - dyn_cast<DIArgList>(MAV->getMetadata())) { - for (const auto *VAM : AL->getArgs()) - orderConstantValue(VAM->getValue()); - } } + }; + + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { + OrderConstantFromMetadata(DVR.getRawLocation()); + if (DVR.isDbgAssign()) + OrderConstantFromMetadata(DVR.getRawAddress()); } + for (const Value *V : I.operands()) { + if (const auto *MAV = dyn_cast<MetadataAsValue>(V)) + OrderConstantFromMetadata(MAV->getMetadata()); + } + } + for (const Argument &A : F.args()) orderValue(&A, OM); for (const BasicBlock &BB : F) @@ -261,33 +269,39 @@ static UseListOrderStack predictUseListOrder(const Module &M) { // constants in the last Function they're used in. Module-level constants // have already been visited above. for (const Function &F : llvm::reverse(M)) { + auto PredictValueOrderFromMetadata = [&](Metadata *MD) { + if (const auto *VAM = dyn_cast<ValueAsMetadata>(MD)) { + predictValueUseListOrder(VAM->getValue(), &F, OM, Stack); + } else if (const auto *AL = dyn_cast<DIArgList>(MD)) { + for (const auto *VAM : AL->getArgs()) + predictValueUseListOrder(VAM->getValue(), &F, OM, Stack); + } + }; if (F.isDeclaration()) continue; for (const BasicBlock &BB : F) predictValueUseListOrder(&BB, &F, OM, Stack); for (const Argument &A : F.args()) predictValueUseListOrder(&A, &F, OM, Stack); - for (const BasicBlock &BB : F) + for (const BasicBlock &BB : F) { for (const Instruction &I : BB) { + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { + PredictValueOrderFromMetadata(DVR.getRawLocation()); + if (DVR.isDbgAssign()) + PredictValueOrderFromMetadata(DVR.getRawAddress()); + } for (const Value *Op : I.operands()) { if (isa<Constant>(*Op) || isa<InlineAsm>(*Op)) // Visit GlobalValues. predictValueUseListOrder(Op, &F, OM, Stack); - if (const auto *MAV = dyn_cast<MetadataAsValue>(Op)) { - if (const auto *VAM = - dyn_cast<ValueAsMetadata>(MAV->getMetadata())) { - predictValueUseListOrder(VAM->getValue(), &F, OM, Stack); - } else if (const auto *AL = - dyn_cast<DIArgList>(MAV->getMetadata())) { - for (const auto *VAM : AL->getArgs()) - predictValueUseListOrder(VAM->getValue(), &F, OM, Stack); - } - } + if (const auto *MAV = dyn_cast<MetadataAsValue>(Op)) + PredictValueOrderFromMetadata(MAV->getMetadata()); } if (auto *SVI = dyn_cast<ShuffleVectorInst>(&I)) predictValueUseListOrder(SVI->getShuffleMaskForBitcode(), &F, OM, Stack); predictValueUseListOrder(&I, &F, OM, Stack); } + } } // Visit globals last, since the module-level use-list block will be seen @@ -409,6 +423,41 @@ ValueEnumerator::ValueEnumerator(const Module &M, for (const BasicBlock &BB : F) for (const Instruction &I : BB) { + // Local metadata is enumerated during function-incorporation, but + // any ConstantAsMetadata arguments in a DIArgList should be examined + // now. + auto EnumerateNonLocalValuesFromMetadata = [&](Metadata *MD) { + assert(MD && "Metadata unexpectedly null"); + if (const auto *AL = dyn_cast<DIArgList>(MD)) { + for (const auto *VAM : AL->getArgs()) { + if (isa<ConstantAsMetadata>(VAM)) + EnumerateMetadata(&F, VAM); + } + return; + } + + if (!isa<LocalAsMetadata>(MD)) + EnumerateMetadata(&F, MD); + }; + + for (DbgRecord &DR : I.getDbgRecordRange()) { + if (DbgLabelRecord *DLR = dyn_cast<DbgLabelRecord>(&DR)) { + EnumerateMetadata(&F, DLR->getLabel()); + EnumerateMetadata(&F, &*DLR->getDebugLoc()); + continue; + } + // Enumerate non-local location metadata. + DbgVariableRecord &DVR = cast<DbgVariableRecord>(DR); + EnumerateNonLocalValuesFromMetadata(DVR.getRawLocation()); + EnumerateMetadata(&F, DVR.getExpression()); + EnumerateMetadata(&F, DVR.getVariable()); + EnumerateMetadata(&F, &*DVR.getDebugLoc()); + if (DVR.isDbgAssign()) { + EnumerateNonLocalValuesFromMetadata(DVR.getRawAddress()); + EnumerateMetadata(&F, DVR.getAssignID()); + EnumerateMetadata(&F, DVR.getAddressExpression()); + } + } for (const Use &Op : I.operands()) { auto *MD = dyn_cast<MetadataAsValue>(&Op); if (!MD) { @@ -416,19 +465,7 @@ ValueEnumerator::ValueEnumerator(const Module &M, continue; } - // Local metadata is enumerated during function-incorporation, but - // any ConstantAsMetadata arguments in a DIArgList should be examined - // now. - if (isa<LocalAsMetadata>(MD->getMetadata())) - continue; - if (auto *AL = dyn_cast<DIArgList>(MD->getMetadata())) { - for (auto *VAM : AL->getArgs()) - if (isa<ConstantAsMetadata>(VAM)) - EnumerateMetadata(&F, VAM); - continue; - } - - EnumerateMetadata(&F, MD->getMetadata()); + EnumerateNonLocalValuesFromMetadata(MD->getMetadata()); } if (auto *SVI = dyn_cast<ShuffleVectorInst>(&I)) EnumerateType(SVI->getShuffleMaskForBitcode()->getType()); @@ -1064,27 +1101,43 @@ void ValueEnumerator::incorporateFunction(const Function &F) { SmallVector<LocalAsMetadata *, 8> FnLocalMDVector; SmallVector<DIArgList *, 8> ArgListMDVector; + + auto AddFnLocalMetadata = [&](Metadata *MD) { + if (!MD) + return; + if (auto *Local = dyn_cast<LocalAsMetadata>(MD)) { + // Enumerate metadata after the instructions they might refer to. + FnLocalMDVector.push_back(Local); + } else if (auto *ArgList = dyn_cast<DIArgList>(MD)) { + ArgListMDVector.push_back(ArgList); + for (ValueAsMetadata *VMD : ArgList->getArgs()) { + if (auto *Local = dyn_cast<LocalAsMetadata>(VMD)) { + // Enumerate metadata after the instructions they might refer + // to. + FnLocalMDVector.push_back(Local); + } + } + } + }; + // Add all of the instructions. for (const BasicBlock &BB : F) { for (const Instruction &I : BB) { for (const Use &OI : I.operands()) { - if (auto *MD = dyn_cast<MetadataAsValue>(&OI)) { - if (auto *Local = dyn_cast<LocalAsMetadata>(MD->getMetadata())) { - // Enumerate metadata after the instructions they might refer to. - FnLocalMDVector.push_back(Local); - } else if (auto *ArgList = dyn_cast<DIArgList>(MD->getMetadata())) { - ArgListMDVector.push_back(ArgList); - for (ValueAsMetadata *VMD : ArgList->getArgs()) { - if (auto *Local = dyn_cast<LocalAsMetadata>(VMD)) { - // Enumerate metadata after the instructions they might refer - // to. - FnLocalMDVector.push_back(Local); - } - } - } + if (auto *MD = dyn_cast<MetadataAsValue>(&OI)) + AddFnLocalMetadata(MD->getMetadata()); + } + /// RemoveDIs: Add non-instruction function-local metadata uses. + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { + assert(DVR.getRawLocation() && + "DbgVariableRecord location unexpectedly null"); + AddFnLocalMetadata(DVR.getRawLocation()); + if (DVR.isDbgAssign()) { + assert(DVR.getRawAddress() && + "DbgVariableRecord location unexpectedly null"); + AddFnLocalMetadata(DVR.getRawAddress()); } } - if (!I.getType()->isVoidTy()) EnumerateValue(&I); } diff --git a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp index 55cdc3c9286420587455e497177b51458403cd3b..2e8e7d0a88af0320e8b8bb0cbb6356d389b66b96 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp @@ -369,7 +369,8 @@ void AppleAccelTableWriter::emit() const { DWARF5AccelTableData::DWARF5AccelTableData(const DIE &Die, const uint32_t UnitID, const bool IsTU) - : OffsetVal(&Die), DieTag(Die.getTag()), IsTU(IsTU), UnitID(UnitID) {} + : OffsetVal(&Die), DieTag(Die.getTag()), AbbrevNumber(0), IsTU(IsTU), + UnitID(UnitID) {} void Dwarf5AccelTableWriter::Header::emit(Dwarf5AccelTableWriter &Ctx) { assert(CompUnitCount > 0 && "Index must have at least one CU."); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 0efe7a0e733672e8691a135088918c9e156fc394..a15538755d73b3876d4b0d2734e180b04a2773b5 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -538,8 +538,10 @@ bool AsmPrinter::doInitialization(Module &M) { if (!M.getModuleInlineAsm().empty()) { OutStreamer->AddComment("Start of file scope inline assembly"); OutStreamer->addBlankLine(); - emitInlineAsm(M.getModuleInlineAsm() + "\n", *TM.getMCSubtargetInfo(), - TM.Options.MCOptions); + emitInlineAsm( + M.getModuleInlineAsm() + "\n", *TM.getMCSubtargetInfo(), + TM.Options.MCOptions, nullptr, + InlineAsm::AsmDialect(TM.getMCAsmInfo()->getAssemblerDialect())); OutStreamer->AddComment("End of file scope inline assembly"); OutStreamer->addBlankLine(); } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 6b5ad62e083e3b26077cb2de18b0da47888bdbc1..a85a8e04666aa999a309b30010f4d34df8d4d37b 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -798,10 +798,10 @@ static void collectCallSiteParameters(const MachineInstr *CallMI, ParamSet &Params) { const MachineFunction *MF = CallMI->getMF(); const auto &CalleesMap = MF->getCallSitesInfo(); - auto CallFwdRegsInfo = CalleesMap.find(CallMI); + auto CSInfo = CalleesMap.find(CallMI); // There is no information for the call instruction. - if (CallFwdRegsInfo == CalleesMap.end()) + if (CSInfo == CalleesMap.end()) return; const MachineBasicBlock *MBB = CallMI->getParent(); @@ -815,7 +815,7 @@ static void collectCallSiteParameters(const MachineInstr *CallMI, DIExpression::get(MF->getFunction().getContext(), {}); // Add all the forwarding registers into the ForwardedRegWorklist. - for (const auto &ArgReg : CallFwdRegsInfo->second) { + for (const auto &ArgReg : CSInfo->second.ArgRegPairs) { bool InsertedReg = ForwardedRegWorklist.insert({ArgReg.Reg, {{ArgReg.Reg, EmptyExpr}}}) .second; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index d462859e48946524299b16e6db833723bcb06004..c40beeeb925e0e8c65ed9bcac32fb394106c33c5 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -803,6 +803,18 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy) { if (DTy->getDWARFAddressSpace()) addUInt(Buffer, dwarf::DW_AT_address_class, dwarf::DW_FORM_data4, *DTy->getDWARFAddressSpace()); + if (auto PtrAuthData = DTy->getPtrAuthData()) { + addUInt(Buffer, dwarf::DW_AT_LLVM_ptrauth_key, dwarf::DW_FORM_data1, + PtrAuthData->key()); + if (PtrAuthData->isAddressDiscriminated()) + addFlag(Buffer, dwarf::DW_AT_LLVM_ptrauth_address_discriminated); + addUInt(Buffer, dwarf::DW_AT_LLVM_ptrauth_extra_discriminator, + dwarf::DW_FORM_data2, PtrAuthData->extraDiscriminator()); + if (PtrAuthData->isaPointer()) + addFlag(Buffer, dwarf::DW_AT_LLVM_ptrauth_isa_pointer); + if (PtrAuthData->authenticatesNullValues()) + addFlag(Buffer, dwarf::DW_AT_LLVM_ptrauth_authenticates_null_values); + } } void DwarfUnit::constructSubprogramArguments(DIE &Buffer, DITypeRefArray Args) { diff --git a/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp b/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp index a4b819a735c640543d5102c4efc4d1aeea282cdf..09177950fc82469c671744a010bb0c1c8884f381 100644 --- a/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp +++ b/llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp @@ -215,22 +215,24 @@ void FunctionVarLocs::init(FunctionVarLocsBuilder &Builder) { // Insert a contiguous block of VarLocInfos for each instruction, mapping it // to the start and end position in the vector with VarLocsBeforeInst. This - // block includes VarLocs for any DPValues attached to that instruction. + // block includes VarLocs for any DbgVariableRecords attached to that + // instruction. for (auto &P : Builder.VarLocsBeforeInst) { - // Process VarLocs attached to a DPValue alongside their marker Instruction. + // Process VarLocs attached to a DbgRecord alongside their marker + // Instruction. if (isa<const DbgRecord *>(P.first)) continue; const Instruction *I = cast<const Instruction *>(P.first); unsigned BlockStart = VarLocRecords.size(); - // Any VarLocInfos attached to a DPValue should now be remapped to their - // marker Instruction, in order of DPValue appearance and prior to any + // Any VarLocInfos attached to a DbgRecord should now be remapped to their + // marker Instruction, in order of DbgRecord appearance and prior to any // VarLocInfos attached directly to that instruction. - for (const DPValue &DPV : DPValue::filter(I->getDbgRecordRange())) { - // Even though DPV defines a variable location, VarLocsBeforeInst can + for (const DbgVariableRecord &DVR : filterDbgVars(I->getDbgRecordRange())) { + // Even though DVR defines a variable location, VarLocsBeforeInst can // still be empty if that VarLoc was redundant. - if (!Builder.VarLocsBeforeInst.count(&DPV)) + if (!Builder.VarLocsBeforeInst.count(&DVR)) continue; - for (const VarLocInfo &VarLoc : Builder.VarLocsBeforeInst[&DPV]) + for (const VarLocInfo &VarLoc : Builder.VarLocsBeforeInst[&DVR]) VarLocRecords.emplace_back(VarLoc); } for (const VarLocInfo &VarLoc : P.second) @@ -829,10 +831,10 @@ class MemLocFragmentFill { void process(BasicBlock &BB, VarFragMap &LiveSet) { BBInsertBeforeMap[&BB].clear(); for (auto &I : BB) { - for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) { - if (const auto *Locs = FnVarLocs->getWedge(&DPV)) { + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { + if (const auto *Locs = FnVarLocs->getWedge(&DVR)) { for (const VarLocInfo &Loc : *Locs) { - addDef(Loc, &DPV, *I.getParent(), LiveSet); + addDef(Loc, &DVR, *I.getParent(), LiveSet); } } } @@ -1026,7 +1028,7 @@ public: /// i.e. for all values x and y where x != y: /// join(x, x) = x /// join(x, y) = NoneOrPhi - using AssignRecord = PointerUnion<DbgAssignIntrinsic *, DPValue *>; + using AssignRecord = PointerUnion<DbgAssignIntrinsic *, DbgVariableRecord *>; struct Assignment { enum S { Known, NoneOrPhi } Status; /// ID of the assignment. nullptr if Status is not Known. @@ -1053,16 +1055,16 @@ public: else if (isa<DbgAssignIntrinsic *>(Source)) OS << Source.get<DbgAssignIntrinsic *>(); else - OS << Source.get<DPValue *>(); + OS << Source.get<DbgVariableRecord *>(); OS << ")"; } static Assignment make(DIAssignID *ID, DbgAssignIntrinsic *Source) { return Assignment(Known, ID, Source); } - static Assignment make(DIAssignID *ID, DPValue *Source) { + static Assignment make(DIAssignID *ID, DbgVariableRecord *Source) { assert(Source->isDbgAssign() && - "Cannot make an assignment from a non-assign DPValue"); + "Cannot make an assignment from a non-assign DbgVariableRecord"); return Assignment(Known, ID, Source); } static Assignment make(DIAssignID *ID, AssignRecord Source) { @@ -1083,7 +1085,7 @@ public: // If the Status is Known then we expect there to be an assignment ID. assert(Status == NoneOrPhi || ID); } - Assignment(S Status, DIAssignID *ID, DPValue *Source) + Assignment(S Status, DIAssignID *ID, DbgVariableRecord *Source) : Status(Status), ID(ID), Source(Source) { // If the Status is Known then we expect there to be an assignment ID. assert(Status == NoneOrPhi || ID); @@ -1118,10 +1120,10 @@ private: /// Clear the location definitions currently cached for insertion after /p /// After. void resetInsertionPoint(Instruction &After); - void resetInsertionPoint(DPValue &After); + void resetInsertionPoint(DbgVariableRecord &After); // emitDbgValue can be called with: - // Source=[AssignRecord|DbgValueInst*|DbgAssignIntrinsic*|DPValue*] + // Source=[AssignRecord|DbgValueInst*|DbgAssignIntrinsic*|DbgVariableRecord*] // Since AssignRecord can be cast to one of the latter two types, and all // other types have a shared interface, we use a template to handle the latter // three types, and an explicit overload for AssignRecord that forwards to @@ -1354,9 +1356,10 @@ private: /// attachment, \p I. void processUntaggedInstruction(Instruction &I, BlockInfo *LiveSet); void processDbgAssign(AssignRecord Assign, BlockInfo *LiveSet); - void processDPValue(DPValue &DPV, BlockInfo *LiveSet); - void processDbgValue(PointerUnion<DbgValueInst *, DPValue *> DbgValueRecord, - BlockInfo *LiveSet); + void processDbgVariableRecord(DbgVariableRecord &DVR, BlockInfo *LiveSet); + void processDbgValue( + PointerUnion<DbgValueInst *, DbgVariableRecord *> DbgValueRecord, + BlockInfo *LiveSet); /// Add an assignment to memory for the variable /p Var. void addMemDef(BlockInfo *LiveSet, VariableID Var, const Assignment &AV); /// Add an assignment to the variable /p Var. @@ -1456,10 +1459,10 @@ static DIAssignID *getIDFromMarker(const DbgAssignIntrinsic &DAI) { return cast<DIAssignID>(DAI.getAssignID()); } -static DIAssignID *getIDFromMarker(const DPValue &DPV) { - assert(DPV.isDbgAssign() && - "Cannot get a DIAssignID from a non-assign DPValue!"); - return DPV.getAssignID(); +static DIAssignID *getIDFromMarker(const DbgVariableRecord &DVR) { + assert(DVR.isDbgAssign() && + "Cannot get a DIAssignID from a non-assign DbgVariableRecord!"); + return DVR.getAssignID(); } /// Return true if \p Var has an assignment in \p M matching \p AV. @@ -1492,10 +1495,10 @@ const char *locStr(AssignmentTrackingLowering::LocKind Loc) { } #endif -VarLocInsertPt getNextNode(const DbgRecord *DPV) { - auto NextIt = ++(DPV->getIterator()); - if (NextIt == DPV->getMarker()->getDbgRecordRange().end()) - return DPV->getMarker()->MarkedInstr; +VarLocInsertPt getNextNode(const DbgRecord *DVR) { + auto NextIt = ++(DVR->getIterator()); + if (NextIt == DVR->getMarker()->getDbgRecordRange().end()) + return DVR->getMarker()->MarkedInstr; return &*NextIt; } VarLocInsertPt getNextNode(const Instruction *Inst) { @@ -1514,10 +1517,10 @@ DbgAssignIntrinsic *CastToDbgAssign(DbgVariableIntrinsic *DVI) { return cast<DbgAssignIntrinsic>(DVI); } -DPValue *CastToDbgAssign(DPValue *DPV) { - assert(DPV->isDbgAssign() && - "Attempted to cast non-assign DPValue to DPVAssign."); - return DPV; +DbgVariableRecord *CastToDbgAssign(DbgVariableRecord *DVR) { + assert(DVR->isDbgAssign() && + "Attempted to cast non-assign DbgVariableRecord to DVRAssign."); + return DVR; } void AssignmentTrackingLowering::emitDbgValue( @@ -1526,7 +1529,7 @@ void AssignmentTrackingLowering::emitDbgValue( if (isa<DbgAssignIntrinsic *>(Source)) emitDbgValue(Kind, cast<DbgAssignIntrinsic *>(Source), After); else - emitDbgValue(Kind, cast<DPValue *>(Source), After); + emitDbgValue(Kind, cast<DbgVariableRecord *>(Source), After); } template <typename T> void AssignmentTrackingLowering::emitDbgValue( @@ -1649,7 +1652,7 @@ void AssignmentTrackingLowering::processUntaggedInstruction( Ops.push_back(dwarf::DW_OP_deref); DIE = DIExpression::prependOpcodes(DIE, Ops, /*StackValue=*/false, /*EntryValue=*/false); - // Find a suitable insert point, before the next instruction or DPValue + // Find a suitable insert point, before the next instruction or DbgRecord // after I. auto InsertBefore = getNextNode(&I); assert(InsertBefore && "Shouldn't be inserting after a terminator"); @@ -1673,7 +1676,7 @@ void AssignmentTrackingLowering::processUntaggedInstruction( void AssignmentTrackingLowering::processTaggedInstruction( Instruction &I, AssignmentTrackingLowering::BlockInfo *LiveSet) { auto Linked = at::getAssignmentMarkers(&I); - auto LinkedDPAssigns = at::getDPVAssignmentMarkers(&I); + auto LinkedDPAssigns = at::getDVRAssignmentMarkers(&I); // No dbg.assign intrinsics linked. // FIXME: All vars that have a stack slot this store modifies that don't have // a dbg.assign linked to it should probably treat this like an untagged @@ -1756,8 +1759,8 @@ void AssignmentTrackingLowering::processTaggedInstruction( }; for (DbgAssignIntrinsic *DAI : Linked) ProcessLinkedAssign(DAI); - for (DPValue *DPV : LinkedDPAssigns) - ProcessLinkedAssign(DPV); + for (DbgVariableRecord *DVR : LinkedDPAssigns) + ProcessLinkedAssign(DVR); } void AssignmentTrackingLowering::processDbgAssign(AssignRecord Assign, @@ -1802,13 +1805,13 @@ void AssignmentTrackingLowering::processDbgAssign(AssignRecord Assign, emitDbgValue(LocKind::Val, DbgAssign, DbgAssign); } }; - if (isa<DPValue *>(Assign)) - return ProcessDbgAssignImpl(cast<DPValue *>(Assign)); + if (isa<DbgVariableRecord *>(Assign)) + return ProcessDbgAssignImpl(cast<DbgVariableRecord *>(Assign)); return ProcessDbgAssignImpl(cast<DbgAssignIntrinsic *>(Assign)); } void AssignmentTrackingLowering::processDbgValue( - PointerUnion<DbgValueInst *, DPValue *> DbgValueRecord, + PointerUnion<DbgValueInst *, DbgVariableRecord *> DbgValueRecord, BlockInfo *LiveSet) { auto ProcessDbgValueImpl = [&](auto *DbgValue) { // Only other tracking variables that are at some point stack homed. @@ -1833,8 +1836,8 @@ void AssignmentTrackingLowering::processDbgValue( setLocKind(LiveSet, Var, LocKind::Val); emitDbgValue(LocKind::Val, DbgValue, DbgValue); }; - if (isa<DPValue *>(DbgValueRecord)) - return ProcessDbgValueImpl(cast<DPValue *>(DbgValueRecord)); + if (isa<DbgVariableRecord *>(DbgValueRecord)) + return ProcessDbgValueImpl(cast<DbgVariableRecord *>(DbgValueRecord)); return ProcessDbgValueImpl(cast<DbgValueInst *>(DbgValueRecord)); } @@ -1859,16 +1862,16 @@ void AssignmentTrackingLowering::processDbgInstruction( else if (auto *DVI = dyn_cast<DbgValueInst>(&I)) processDbgValue(DVI, LiveSet); } -void AssignmentTrackingLowering::processDPValue( - DPValue &DPV, AssignmentTrackingLowering::BlockInfo *LiveSet) { +void AssignmentTrackingLowering::processDbgVariableRecord( + DbgVariableRecord &DVR, AssignmentTrackingLowering::BlockInfo *LiveSet) { // Ignore assignments to zero bits of the variable. - if (hasZeroSizedFragment(DPV)) + if (hasZeroSizedFragment(DVR)) return; - if (DPV.isDbgAssign()) - processDbgAssign(&DPV, LiveSet); - else if (DPV.isDbgValue()) - processDbgValue(&DPV, LiveSet); + if (DVR.isDbgAssign()) + processDbgAssign(&DVR, LiveSet); + else if (DVR.isDbgValue()) + processDbgValue(&DVR, LiveSet); } void AssignmentTrackingLowering::resetInsertionPoint(Instruction &After) { @@ -1878,7 +1881,7 @@ void AssignmentTrackingLowering::resetInsertionPoint(Instruction &After) { return; R->second.clear(); } -void AssignmentTrackingLowering::resetInsertionPoint(DPValue &After) { +void AssignmentTrackingLowering::resetInsertionPoint(DbgVariableRecord &After) { auto *R = InsertBeforeMap.find(getNextNode(&After)); if (R == InsertBeforeMap.end()) return; @@ -1886,21 +1889,21 @@ void AssignmentTrackingLowering::resetInsertionPoint(DPValue &After) { } void AssignmentTrackingLowering::process(BasicBlock &BB, BlockInfo *LiveSet) { - // If the block starts with DPValues, we need to process those DPValues as + // If the block starts with DbgRecords, we need to process those DbgRecords as // their own frame without processing any instructions first. - bool ProcessedLeadingDPValues = !BB.begin()->hasDbgRecords(); + bool ProcessedLeadingDbgRecords = !BB.begin()->hasDbgRecords(); for (auto II = BB.begin(), EI = BB.end(); II != EI;) { assert(VarsTouchedThisFrame.empty()); // Process the instructions in "frames". A "frame" includes a single // non-debug instruction followed any debug instructions before the // next non-debug instruction. - // Skip the current instruction if it has unprocessed DPValues attached (see - // comment above `ProcessedLeadingDPValues`). - if (ProcessedLeadingDPValues) { + // Skip the current instruction if it has unprocessed DbgRecords attached + // (see comment above `ProcessedLeadingDbgRecords`). + if (ProcessedLeadingDbgRecords) { // II is now either a debug intrinsic, a non-debug instruction with no - // attached DPValues, or a non-debug instruction with attached processed - // DPValues. + // attached DbgRecords, or a non-debug instruction with attached processed + // DbgRecords. // II has not been processed. if (!isa<DbgInfoIntrinsic>(&*II)) { if (II->isTerminator()) @@ -1912,19 +1915,19 @@ void AssignmentTrackingLowering::process(BasicBlock &BB, BlockInfo *LiveSet) { } } // II is now either a debug intrinsic, a non-debug instruction with no - // attached DPValues, or a non-debug instruction with attached unprocessed - // DPValues. + // attached DbgRecords, or a non-debug instruction with attached unprocessed + // DbgRecords. if (II != EI && II->hasDbgRecords()) { // Skip over non-variable debug records (i.e., labels). They're going to // be read from IR (possibly re-ordering them within the debug record // range) rather than from the analysis results. - for (DPValue &DPV : DPValue::filter(II->getDbgRecordRange())) { - resetInsertionPoint(DPV); - processDPValue(DPV, LiveSet); + for (DbgVariableRecord &DVR : filterDbgVars(II->getDbgRecordRange())) { + resetInsertionPoint(DVR); + processDbgVariableRecord(DVR, LiveSet); assert(LiveSet->isValid()); } } - ProcessedLeadingDPValues = true; + ProcessedLeadingDbgRecords = true; while (II != EI) { auto *Dbg = dyn_cast<DbgInfoIntrinsic>(&*II); if (!Dbg) @@ -1934,9 +1937,9 @@ void AssignmentTrackingLowering::process(BasicBlock &BB, BlockInfo *LiveSet) { assert(LiveSet->isValid()); ++II; } - // II is now a non-debug instruction either with no attached DPValues, or - // with attached processed DPValues. II has not been processed, and all - // debug instructions or DPValues in the frame preceding II have been + // II is now a non-debug instruction either with no attached DbgRecords, or + // with attached processed DbgRecords. II has not been processed, and all + // debug instructions or DbgRecords in the frame preceding II have been // processed. // We've processed everything in the "frame". Now determine which variables @@ -1999,9 +2002,11 @@ AssignmentTrackingLowering::joinAssignment(const Assignment &A, return A.Source; if (!A.Source || !B.Source) return AssignRecord(); - assert(isa<DPValue *>(A.Source) == isa<DPValue *>(B.Source)); - if (isa<DPValue *>(A.Source) && - cast<DPValue *>(A.Source)->isEquivalentTo(*cast<DPValue *>(B.Source))) + assert(isa<DbgVariableRecord *>(A.Source) == + isa<DbgVariableRecord *>(B.Source)); + if (isa<DbgVariableRecord *>(A.Source) && + cast<DbgVariableRecord *>(A.Source)->isEquivalentTo( + *cast<DbgVariableRecord *>(B.Source))) return A.Source; if (isa<DbgAssignIntrinsic *>(A.Source) && cast<DbgAssignIntrinsic *>(A.Source)->isIdenticalTo( @@ -2122,8 +2127,8 @@ DbgDeclareInst *DynCastToDbgDeclare(DbgVariableIntrinsic *DVI) { return dyn_cast<DbgDeclareInst>(DVI); } -DPValue *DynCastToDbgDeclare(DPValue *DPV) { - return DPV->isDbgDeclare() ? DPV : nullptr; +DbgVariableRecord *DynCastToDbgDeclare(DbgVariableRecord *DVR) { + return DVR->isDbgDeclare() ? DVR : nullptr; } /// Build a map of {Variable x: Variables y} where all variable fragments @@ -2160,7 +2165,7 @@ static AssignmentTrackingLowering::OverlapMap buildOverlapMapAndRecordDeclares( // We need to add fragments for untagged stores too so that we can correctly // clobber overlapped fragment locations later. SmallVector<DbgDeclareInst *> InstDeclares; - SmallVector<DPValue *> DPDeclares; + SmallVector<DbgVariableRecord *> DPDeclares; auto ProcessDbgRecord = [&](auto *Record, auto &DeclareList) { if (auto *Declare = DynCastToDbgDeclare(Record)) { DeclareList.push_back(Declare); @@ -2175,8 +2180,8 @@ static AssignmentTrackingLowering::OverlapMap buildOverlapMapAndRecordDeclares( }; for (auto &BB : Fn) { for (auto &I : BB) { - for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) - ProcessDbgRecord(&DPV, DPDeclares); + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) + ProcessDbgRecord(&DVR, DPDeclares); if (auto *DII = dyn_cast<DbgVariableIntrinsic>(&I)) { ProcessDbgRecord(DII, InstDeclares); } else if (auto Info = getUntaggedStoreAssignmentInfo( @@ -2217,8 +2222,8 @@ static AssignmentTrackingLowering::OverlapMap buildOverlapMapAndRecordDeclares( }; for (DbgAssignIntrinsic *DAI : at::getAssignmentMarkers(Info->Base)) HandleDbgAssignForStore(DAI); - for (DPValue *DPV : at::getDPVAssignmentMarkers(Info->Base)) - HandleDbgAssignForStore(DPV); + for (DbgVariableRecord *DVR : at::getDVRAssignmentMarkers(Info->Base)) + HandleDbgAssignForStore(DVR); } } } @@ -2268,10 +2273,10 @@ static AssignmentTrackingLowering::OverlapMap buildOverlapMapAndRecordDeclares( for (auto *DDI : InstDeclares) FnVarLocs->addSingleLocVar(DebugVariable(DDI), DDI->getExpression(), DDI->getDebugLoc(), DDI->getWrappedLocation()); - for (auto *DPV : DPDeclares) - FnVarLocs->addSingleLocVar(DebugVariable(DPV), DPV->getExpression(), - DPV->getDebugLoc(), - RawLocationWrapper(DPV->getRawLocation())); + for (auto *DVR : DPDeclares) + FnVarLocs->addSingleLocVar(DebugVariable(DVR), DVR->getExpression(), + DVR->getDebugLoc(), + RawLocationWrapper(DVR->getRawLocation())); return Map; } @@ -2465,9 +2470,9 @@ bool AssignmentTrackingLowering::emitPromotedVarLocs( for (auto &BB : Fn) { for (auto &I : BB) { // Skip instructions other than dbg.values and dbg.assigns. - for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) - if (DPV.isDbgValue() || DPV.isDbgAssign()) - TranslateDbgRecord(&DPV); + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) + if (DVR.isDbgValue() || DVR.isDbgAssign()) + TranslateDbgRecord(&DVR); auto *DVI = dyn_cast<DbgValueInst>(&I); if (DVI) TranslateDbgRecord(DVI); @@ -2567,8 +2572,8 @@ removeRedundantDbgLocsUsingBackwardScan(const BasicBlock *BB, } }; HandleLocsForWedge(&I); - for (DPValue &DPV : reverse(DPValue::filter(I.getDbgRecordRange()))) - HandleLocsForWedge(&DPV); + for (DbgVariableRecord &DVR : reverse(filterDbgVars(I.getDbgRecordRange()))) + HandleLocsForWedge(&DVR); } return Changed; @@ -2632,8 +2637,8 @@ removeRedundantDbgLocsUsingForwardScan(const BasicBlock *BB, } }; - for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) - HandleLocsForWedge(&DPV); + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) + HandleLocsForWedge(&DVR); HandleLocsForWedge(&I); } @@ -2718,8 +2723,8 @@ removeUndefDbgLocsFromEntryBlock(const BasicBlock *BB, Changed = true; } }; - for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) - HandleLocsForWedge(&DPV); + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) + HandleLocsForWedge(&DVR); HandleLocsForWedge(&I); } @@ -2752,8 +2757,8 @@ static DenseSet<DebugAggregate> findVarsWithStackSlot(Function &Fn) { for (DbgAssignIntrinsic *DAI : at::getAssignmentMarkers(&I)) { Result.insert({DAI->getVariable(), DAI->getDebugLoc().getInlinedAt()}); } - for (DPValue *DPV : at::getDPVAssignmentMarkers(&I)) { - Result.insert({DPV->getVariable(), DPV->getDebugLoc().getInlinedAt()}); + for (DbgVariableRecord *DVR : at::getDVRAssignmentMarkers(&I)) { + Result.insert({DVR->getVariable(), DVR->getDebugLoc().getInlinedAt()}); } } } diff --git a/llvm/lib/CodeGen/AtomicExpandPass.cpp b/llvm/lib/CodeGen/AtomicExpandPass.cpp index 894285a7eb25642cc9d0c160e3fbdfcb8d86a5fc..d5db79df68622a086f03697cd09bbae24d9dd3bc 100644 --- a/llvm/lib/CodeGen/AtomicExpandPass.cpp +++ b/llvm/lib/CodeGen/AtomicExpandPass.cpp @@ -135,10 +135,13 @@ public: // IRBuilder to be used for replacement atomic instructions. struct ReplacementIRBuilder : IRBuilder<InstSimplifyFolder> { // Preserves the DebugLoc from I, and preserves still valid metadata. + // Enable StrictFP builder mode when appropriate. explicit ReplacementIRBuilder(Instruction *I, const DataLayout &DL) : IRBuilder(I->getContext(), DL) { SetInsertPoint(I); this->CollectMetadataToCopy(I, {LLVMContext::MD_pcsections}); + if (BB->getParent()->getAttributes().hasFnAttr(Attribute::StrictFP)) + this->setIsFPConstrained(true); } }; diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index 59a0c64d3c9f2df93b2417c26eb4741338427851..e657872c38284828dfe76889a5be54bb994a6c5c 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -445,8 +445,8 @@ private: bool optimizeExtractElementInst(Instruction *Inst); bool dupRetToEnableTailCallOpts(BasicBlock *BB, ModifyDT &ModifiedDT); bool fixupDbgValue(Instruction *I); - bool fixupDPValue(DPValue &I); - bool fixupDPValuesOnInst(Instruction &I); + bool fixupDbgVariableRecord(DbgVariableRecord &I); + bool fixupDbgVariableRecordsOnInst(Instruction &I); bool placeDbgValues(Function &F); bool placePseudoProbes(Function &F); bool canFormExtLd(const SmallVectorImpl<Instruction *> &MovedExts, @@ -1943,6 +1943,39 @@ static bool swapICmpOperandsToExposeCSEOpportunities(CmpInst *Cmp) { return false; } +static bool foldFCmpToFPClassTest(CmpInst *Cmp, const TargetLowering &TLI, + const DataLayout &DL) { + FCmpInst *FCmp = dyn_cast<FCmpInst>(Cmp); + if (!FCmp) + return false; + + // Don't fold if the target offers free fabs and the predicate is legal. + EVT VT = TLI.getValueType(DL, Cmp->getOperand(0)->getType()); + if (TLI.isFAbsFree(VT) && + TLI.isCondCodeLegal(getFCmpCondCode(FCmp->getPredicate()), + VT.getSimpleVT())) + return false; + + // Reverse the canonicalization if it is a FP class test + auto ShouldReverseTransform = [](FPClassTest ClassTest) { + return ClassTest == fcInf || ClassTest == (fcInf | fcNan); + }; + auto [ClassVal, ClassTest] = + fcmpToClassTest(FCmp->getPredicate(), *FCmp->getParent()->getParent(), + FCmp->getOperand(0), FCmp->getOperand(1)); + if (!ClassVal) + return false; + + if (!ShouldReverseTransform(ClassTest) && !ShouldReverseTransform(~ClassTest)) + return false; + + IRBuilder<> Builder(Cmp); + Value *IsFPClass = Builder.createIsFPClass(ClassVal, ClassTest); + Cmp->replaceAllUsesWith(IsFPClass); + RecursivelyDeleteTriviallyDeadInstructions(Cmp); + return true; +} + bool CodeGenPrepare::optimizeCmp(CmpInst *Cmp, ModifyDT &ModifiedDT) { if (sinkCmpExpression(Cmp, *TLI)) return true; @@ -1959,6 +1992,9 @@ bool CodeGenPrepare::optimizeCmp(CmpInst *Cmp, ModifyDT &ModifiedDT) { if (swapICmpOperandsToExposeCSEOpportunities(Cmp)) return true; + if (foldFCmpToFPClassTest(Cmp, *TLI, *DL)) + return true; + return false; } @@ -2021,9 +2057,9 @@ static bool sinkAndCmp0Expression(Instruction *AndI, const TargetLowering &TLI, // Keep the 'and' in the same place if the use is already in the same block. Instruction *InsertPt = User->getParent() == AndI->getParent() ? AndI : User; - Instruction *InsertedAnd = - BinaryOperator::Create(Instruction::And, AndI->getOperand(0), - AndI->getOperand(1), "", InsertPt); + Instruction *InsertedAnd = BinaryOperator::Create( + Instruction::And, AndI->getOperand(0), AndI->getOperand(1), "", + InsertPt->getIterator()); // Propagate the debug info. InsertedAnd->setDebugLoc(AndI->getDebugLoc()); @@ -2426,8 +2462,10 @@ bool CodeGenPrepare::optimizeCallInst(CallInst *CI, ModifyDT &ModifiedDT) { break; case Intrinsic::assume: llvm_unreachable("llvm.assume should have been removed already"); + case Intrinsic::allow_runtime_check: + case Intrinsic::allow_ubsan_check: case Intrinsic::experimental_widenable_condition: { - // Give up on future widening oppurtunties so that we can fold away dead + // Give up on future widening opportunities so that we can fold away dead // paths and merge blocks before going into block-local instruction // selection. if (II->use_empty()) { @@ -2946,7 +2984,7 @@ class TypePromotionTransaction { Instruction *PrevInst; BasicBlock *BB; } Point; - std::optional<DPValue::self_iterator> BeforeDPValue = std::nullopt; + std::optional<DbgRecord::self_iterator> BeforeDbgRecord = std::nullopt; /// Remember whether or not the instruction had a previous instruction. bool HasPrevInstruction; @@ -2958,9 +2996,9 @@ class TypePromotionTransaction { BasicBlock *BB = Inst->getParent(); // Record where we would have to re-insert the instruction in the sequence - // of DPValues, if we ended up reinserting. + // of DbgRecords, if we ended up reinserting. if (BB->IsNewDbgInfoFormat) - BeforeDPValue = Inst->getDbgReinsertionPosition(); + BeforeDbgRecord = Inst->getDbgReinsertionPosition(); if (HasPrevInstruction) { Point.PrevInst = &*std::prev(Inst->getIterator()); @@ -2983,7 +3021,7 @@ class TypePromotionTransaction { Inst->insertBefore(*Point.BB, Position); } - Inst->getParent()->reinsertInstInDbgRecords(Inst, BeforeDPValue); + Inst->getParent()->reinsertInstInDbgRecords(Inst, BeforeDbgRecord); } }; @@ -3187,7 +3225,7 @@ class TypePromotionTransaction { /// Keep track of the debug users. SmallVector<DbgValueInst *, 1> DbgValues; /// And non-instruction debug-users too. - SmallVector<DPValue *, 1> DPValues; + SmallVector<DbgVariableRecord *, 1> DbgVariableRecords; /// Keep track of the new value so that we can undo it by replacing /// instances of the new value with the original value. @@ -3208,7 +3246,7 @@ class TypePromotionTransaction { } // Record the debug uses separately. They are not in the instruction's // use list, but they are replaced by RAUW. - findDbgValues(DbgValues, Inst, &DPValues); + findDbgValues(DbgValues, Inst, &DbgVariableRecords); // Now, we can replace the uses. Inst->replaceAllUsesWith(New); @@ -3225,10 +3263,10 @@ class TypePromotionTransaction { // correctness and utility of debug value instructions. for (auto *DVI : DbgValues) DVI->replaceVariableLocationOp(New, Inst); - // Similar story with DPValues, the non-instruction representation of - // dbg.values. - for (DPValue *DPV : DPValues) // tested by transaction-test I'm adding - DPV->replaceVariableLocationOp(New, Inst); + // Similar story with DbgVariableRecords, the non-instruction + // representation of dbg.values. + for (DbgVariableRecord *DVR : DbgVariableRecords) + DVR->replaceVariableLocationOp(New, Inst); } }; @@ -4117,9 +4155,10 @@ private: if (SelectInst *CurrentSelect = dyn_cast<SelectInst>(Current)) { // Is it OK to get metadata from OrigSelect?! // Create a Select placeholder with dummy value. - SelectInst *Select = SelectInst::Create( - CurrentSelect->getCondition(), Dummy, Dummy, - CurrentSelect->getName(), CurrentSelect, CurrentSelect); + SelectInst *Select = + SelectInst::Create(CurrentSelect->getCondition(), Dummy, Dummy, + CurrentSelect->getName(), + CurrentSelect->getIterator(), CurrentSelect); Map[Current] = Select; ST.insertNewSelect(Select); // We are interested in True and False values. @@ -6430,8 +6469,8 @@ bool CodeGenPrepare::optimizePhiType( ValMap[D] = D->getOperand(0); DeletedInstrs.insert(D); } else { - ValMap[D] = - new BitCastInst(D, ConvertTy, D->getName() + ".bc", D->getNextNode()); + BasicBlock::iterator insertPt = std::next(D->getIterator()); + ValMap[D] = new BitCastInst(D, ConvertTy, D->getName() + ".bc", insertPt); } } for (PHINode *Phi : PhiNodes) @@ -6451,8 +6490,8 @@ bool CodeGenPrepare::optimizePhiType( DeletedInstrs.insert(U); replaceAllUsesWith(U, ValMap[U->getOperand(0)], FreshBBs, IsHugeFunc); } else { - U->setOperand(0, - new BitCastInst(ValMap[U->getOperand(0)], PhiTy, "bc", U)); + U->setOperand(0, new BitCastInst(ValMap[U->getOperand(0)], PhiTy, "bc", + U->getIterator())); } } @@ -7080,9 +7119,9 @@ bool CodeGenPrepare::optimizeSelectInst(SelectInst *SI) { CurInstIterator = std::next(LastSI->getIterator()); // Examine debug-info attached to the consecutive select instructions. They // won't be individually optimised by optimizeInst, so we need to perform - // DPValue maintenence here instead. + // DbgVariableRecord maintenence here instead. for (SelectInst *SI : ArrayRef(ASI).drop_front()) - fixupDPValuesOnInst(*SI); + fixupDbgVariableRecordsOnInst(*SI); bool VectorCond = !SI->getCondition()->getType()->isIntegerTy(1); @@ -8238,7 +8277,7 @@ static bool optimizeBranch(BranchInst *Branch, const TargetLowering &TLI, bool CodeGenPrepare::optimizeInst(Instruction *I, ModifyDT &ModifiedDT) { bool AnyChange = false; - AnyChange = fixupDPValuesOnInst(*I); + AnyChange = fixupDbgVariableRecordsOnInst(*I); // Bail out if we inserted the instruction to prevent optimizations from // stepping on each other's toes. @@ -8348,7 +8387,7 @@ bool CodeGenPrepare::optimizeInst(Instruction *I, ModifyDT &ModifiedDT) { if (GEPI->hasAllZeroIndices()) { /// The GEP operand must be a pointer, so must its result -> BitCast Instruction *NC = new BitCastInst(GEPI->getOperand(0), GEPI->getType(), - GEPI->getName(), GEPI); + GEPI->getName(), GEPI->getIterator()); NC->setDebugLoc(GEPI->getDebugLoc()); replaceAllUsesWith(GEPI, NC, FreshBBs, IsHugeFunc); RecursivelyDeleteTriviallyDeadInstructions( @@ -8380,7 +8419,7 @@ bool CodeGenPrepare::optimizeInst(Instruction *I, ModifyDT &ModifiedDT) { isa<ConstantPointerNull>(Op1); if (Const0 || Const1) { if (!Const0 || !Const1) { - auto *F = new FreezeInst(Const0 ? Op1 : Op0, "", CmpI); + auto *F = new FreezeInst(Const0 ? Op1 : Op0, "", CmpI->getIterator()); F->takeName(FI); CmpI->setOperand(Const0 ? 1 : 0, F); } @@ -8504,24 +8543,24 @@ bool CodeGenPrepare::fixupDbgValue(Instruction *I) { return AnyChange; } -bool CodeGenPrepare::fixupDPValuesOnInst(Instruction &I) { +bool CodeGenPrepare::fixupDbgVariableRecordsOnInst(Instruction &I) { bool AnyChange = false; - for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) - AnyChange |= fixupDPValue(DPV); + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) + AnyChange |= fixupDbgVariableRecord(DVR); return AnyChange; } // FIXME: should updating debug-info really cause the "changed" flag to fire, // which can cause a function to be reprocessed? -bool CodeGenPrepare::fixupDPValue(DPValue &DPV) { - if (DPV.Type != DPValue::LocationType::Value && - DPV.Type != DPValue::LocationType::Assign) +bool CodeGenPrepare::fixupDbgVariableRecord(DbgVariableRecord &DVR) { + if (DVR.Type != DbgVariableRecord::LocationType::Value && + DVR.Type != DbgVariableRecord::LocationType::Assign) return false; - // Does this DPValue refer to a sunk address calculation? + // Does this DbgVariableRecord refer to a sunk address calculation? bool AnyChange = false; - SmallDenseSet<Value *> LocationOps(DPV.location_ops().begin(), - DPV.location_ops().end()); + SmallDenseSet<Value *> LocationOps(DVR.location_ops().begin(), + DVR.location_ops().end()); for (Value *Location : LocationOps) { WeakTrackingVH SunkAddrVH = SunkAddrs[Location]; Value *SunkAddr = SunkAddrVH.pointsToAliveValue() ? SunkAddrVH : nullptr; @@ -8531,7 +8570,7 @@ bool CodeGenPrepare::fixupDPValue(DPValue &DPV) { // of pointer being referred to; however this makes no difference to // debugging information, and we can't generate bitcasts that may affect // codegen. - DPV.replaceVariableLocationOp(Location, SunkAddr); + DVR.replaceVariableLocationOp(Location, SunkAddr); AnyChange = true; } } @@ -8546,13 +8585,13 @@ static void DbgInserterHelper(DbgValueInst *DVI, Instruction *VI) { DVI->insertAfter(VI); } -static void DbgInserterHelper(DPValue *DPV, Instruction *VI) { - DPV->removeFromParent(); +static void DbgInserterHelper(DbgVariableRecord *DVR, Instruction *VI) { + DVR->removeFromParent(); BasicBlock *VIBB = VI->getParent(); if (isa<PHINode>(VI)) - VIBB->insertDbgRecordBefore(DPV, VIBB->getFirstInsertionPt()); + VIBB->insertDbgRecordBefore(DVR, VIBB->getFirstInsertionPt()); else - VIBB->insertDbgRecordAfter(DPV, VI); + VIBB->insertDbgRecordAfter(DVR, VI); } // A llvm.dbg.value may be using a value before its definition, due to @@ -8617,13 +8656,13 @@ bool CodeGenPrepare::placeDbgValues(Function &F) { continue; } - // If this isn't a dbg.value, process any attached DPValue records - // attached to this instruction. - for (DPValue &DPV : llvm::make_early_inc_range( - DPValue::filter(Insn.getDbgRecordRange()))) { - if (DPV.Type != DPValue::LocationType::Value) + // If this isn't a dbg.value, process any attached DbgVariableRecord + // records attached to this instruction. + for (DbgVariableRecord &DVR : llvm::make_early_inc_range( + filterDbgVars(Insn.getDbgRecordRange()))) { + if (DVR.Type != DbgVariableRecord::LocationType::Value) continue; - DbgProcessor(&DPV, &Insn); + DbgProcessor(&DVR, &Insn); } } } diff --git a/llvm/lib/CodeGen/DFAPacketizer.cpp b/llvm/lib/CodeGen/DFAPacketizer.cpp index 48bb4a07662e10fbecfc89ea2d64ce7f18390a83..c16166a1d5e1c556b62c70dedb0bfae3705755a0 100644 --- a/llvm/lib/CodeGen/DFAPacketizer.cpp +++ b/llvm/lib/CodeGen/DFAPacketizer.cpp @@ -252,12 +252,13 @@ void VLIWPacketizerList::PacketizeMIs(MachineBasicBlock *MBB, bool VLIWPacketizerList::alias(const MachineMemOperand &Op1, const MachineMemOperand &Op2, bool UseTBAA) const { - if (!Op1.getValue() || !Op2.getValue()) + if (!Op1.getValue() || !Op2.getValue() || !Op1.getSize().hasValue() || + !Op2.getSize().hasValue()) return true; int64_t MinOffset = std::min(Op1.getOffset(), Op2.getOffset()); - int64_t Overlapa = Op1.getSize() + Op1.getOffset() - MinOffset; - int64_t Overlapb = Op2.getSize() + Op2.getOffset() - MinOffset; + int64_t Overlapa = Op1.getSize().getValue() + Op1.getOffset() - MinOffset; + int64_t Overlapb = Op2.getSize().getValue() + Op2.getOffset() - MinOffset; AliasResult AAResult = AA->alias(MemoryLocation(Op1.getValue(), Overlapa, diff --git a/llvm/lib/CodeGen/DwarfEHPrepare.cpp b/llvm/lib/CodeGen/DwarfEHPrepare.cpp index e7eb34d8e6518cd0a2e225aed6ee21556523ad45..09e7cfb12bdbadd48a3b6e5bd9248124400083b1 100644 --- a/llvm/lib/CodeGen/DwarfEHPrepare.cpp +++ b/llvm/lib/CodeGen/DwarfEHPrepare.cpp @@ -111,7 +111,8 @@ Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) { } if (!ExnObj) - ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI); + ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", + RI->getIterator()); RI->eraseFromParent(); @@ -158,7 +159,7 @@ size_t DwarfEHPrepare::pruneUnreachableResumes( Resumes[ResumesLeft++] = RI; } else { BasicBlock *BB = RI->getParent(); - new UnreachableInst(Ctx, RI); + new UnreachableInst(Ctx, RI->getIterator()); RI->eraseFromParent(); simplifyCFG(BB, *TTI, DTU); } diff --git a/llvm/lib/CodeGen/ExpandLargeDivRem.cpp b/llvm/lib/CodeGen/ExpandLargeDivRem.cpp index 973c814604b389ac6485de49c15945bdb088f70a..ab893410fabc3a83b2fc67a8aae73fb5f45d5651 100644 --- a/llvm/lib/CodeGen/ExpandLargeDivRem.cpp +++ b/llvm/lib/CodeGen/ExpandLargeDivRem.cpp @@ -54,8 +54,32 @@ static bool isSigned(unsigned int Opcode) { return Opcode == Instruction::SDiv || Opcode == Instruction::SRem; } +static void scalarize(BinaryOperator *BO, + SmallVectorImpl<BinaryOperator *> &Replace) { + VectorType *VTy = cast<FixedVectorType>(BO->getType()); + + IRBuilder<> Builder(BO); + + unsigned NumElements = VTy->getElementCount().getFixedValue(); + Value *Result = PoisonValue::get(VTy); + for (unsigned Idx = 0; Idx < NumElements; ++Idx) { + Value *LHS = Builder.CreateExtractElement(BO->getOperand(0), Idx); + Value *RHS = Builder.CreateExtractElement(BO->getOperand(1), Idx); + Value *Op = Builder.CreateBinOp(BO->getOpcode(), LHS, RHS); + Result = Builder.CreateInsertElement(Result, Op, Idx); + if (auto *NewBO = dyn_cast<BinaryOperator>(Op)) { + NewBO->copyIRFlags(Op, true); + Replace.push_back(NewBO); + } + } + BO->replaceAllUsesWith(Result); + BO->dropAllReferences(); + BO->eraseFromParent(); +} + static bool runImpl(Function &F, const TargetLowering &TLI) { SmallVector<BinaryOperator *, 4> Replace; + SmallVector<BinaryOperator *, 4> ReplaceVector; bool Modified = false; unsigned MaxLegalDivRemBitWidth = TLI.getMaxDivRemBitWidthSupported(); @@ -71,16 +95,23 @@ static bool runImpl(Function &F, const TargetLowering &TLI) { case Instruction::SDiv: case Instruction::URem: case Instruction::SRem: { - // TODO: This doesn't handle vectors. - auto *IntTy = dyn_cast<IntegerType>(I.getType()); + // TODO: This pass doesn't handle scalable vectors. + if (I.getOperand(0)->getType()->isScalableTy()) + continue; + + auto *IntTy = dyn_cast<IntegerType>(I.getType()->getScalarType()); if (!IntTy || IntTy->getIntegerBitWidth() <= MaxLegalDivRemBitWidth) continue; // The backend has peephole optimizations for powers of two. + // TODO: We don't consider vectors here. if (isConstantPowerOfTwo(I.getOperand(1), isSigned(I.getOpcode()))) continue; - Replace.push_back(&cast<BinaryOperator>(I)); + if (I.getOperand(0)->getType()->isVectorTy()) + ReplaceVector.push_back(&cast<BinaryOperator>(I)); + else + Replace.push_back(&cast<BinaryOperator>(I)); Modified = true; break; } @@ -89,6 +120,11 @@ static bool runImpl(Function &F, const TargetLowering &TLI) { } } + while (!ReplaceVector.empty()) { + BinaryOperator *BO = ReplaceVector.pop_back_val(); + scalarize(BO, Replace); + } + if (Replace.empty()) return false; diff --git a/llvm/lib/CodeGen/ExpandLargeFpConvert.cpp b/llvm/lib/CodeGen/ExpandLargeFpConvert.cpp index 78ad2a25d0e47a9e793d04b51c392c60bc166c0e..4ec966e56d6eef2c56aa3cbc11c0925cb7c9d412 100644 --- a/llvm/lib/CodeGen/ExpandLargeFpConvert.cpp +++ b/llvm/lib/CodeGen/ExpandLargeFpConvert.cpp @@ -175,9 +175,10 @@ static void expandFPToI(Instruction *FPToI) { // if.end: Builder.SetInsertPoint(IfEnd); Value *Add1 = Builder.CreateAdd( - And2, ConstantInt::getSigned(IntTy, -int64_t(ExponentBias + BitWidth))); - Value *Cmp3 = - Builder.CreateICmpULT(Add1, ConstantInt::getSigned(IntTy, -BitWidth)); + And2, ConstantInt::getSigned( + IntTy, -static_cast<int64_t>(ExponentBias + BitWidth))); + Value *Cmp3 = Builder.CreateICmpULT( + Add1, ConstantInt::getSigned(IntTy, -static_cast<int64_t>(BitWidth))); Builder.CreateCondBr(Cmp3, IfThen5, IfEnd9); // if.then5: @@ -203,8 +204,8 @@ static void expandFPToI(Instruction *FPToI) { // if.else: Builder.SetInsertPoint(IfElse); Value *Sub15 = Builder.CreateAdd( - And2, - ConstantInt::getSigned(IntTy, -(ExponentBias + FPMantissaWidth))); + And2, ConstantInt::getSigned( + IntTy, -static_cast<int64_t>(ExponentBias + FPMantissaWidth))); Value *Shl = Builder.CreateShl(Or, Sub15); Value *Mul16 = Builder.CreateMul(Shl, Sign); Builder.CreateBr(End); @@ -375,7 +376,7 @@ static void expandIToFP(Instruction *IToFP) { Value *Sub2 = Builder.CreateSub(Builder.getIntN(BitWidthNew, BitWidth - 1), FloatWidth == 128 ? Call : Cast); Value *Cmp3 = Builder.CreateICmpSGT( - Sub2, Builder.getIntN(BitWidthNew, FPMantissaWidth + 1)); + Sub1, Builder.getIntN(BitWidthNew, FPMantissaWidth + 1)); Builder.CreateCondBr(Cmp3, IfThen4, IfElse); // if.then4: diff --git a/llvm/lib/CodeGen/FinalizeISel.cpp b/llvm/lib/CodeGen/FinalizeISel.cpp index 329c9587e32122869b63ed636919cbcfbc013c16..bf967eac22f177ec96ff0c88c6d242781390278f 100644 --- a/llvm/lib/CodeGen/FinalizeISel.cpp +++ b/llvm/lib/CodeGen/FinalizeISel.cpp @@ -14,8 +14,10 @@ // //===----------------------------------------------------------------------===// +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/InitializePasses.h" @@ -45,6 +47,7 @@ INITIALIZE_PASS(FinalizeISel, DEBUG_TYPE, bool FinalizeISel::runOnMachineFunction(MachineFunction &MF) { bool Changed = false; + const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); const TargetLowering *TLI = MF.getSubtarget().getTargetLowering(); // Iterate through each instruction in the function, looking for pseudos. @@ -54,6 +57,11 @@ bool FinalizeISel::runOnMachineFunction(MachineFunction &MF) { MBBI != MBBE; ) { MachineInstr &MI = *MBBI++; + // Set AdjustsStack to true if the instruction selector emits a stack + // frame setup instruction or a stack aligning inlineasm. + if (TII->isFrameInstr(MI) || MI.isStackAligningInlineAsm()) + MF.getFrameInfo().setAdjustsStack(true); + // If MI is a pseudo, expand it. if (MI.usesCustomInsertionHook()) { Changed = true; diff --git a/llvm/lib/CodeGen/GCRootLowering.cpp b/llvm/lib/CodeGen/GCRootLowering.cpp index 894ab9a0486a7b9397da9eff0d003bff3c2ad4ba..700714d53984702da3abfcda843ce414a48af334 100644 --- a/llvm/lib/CodeGen/GCRootLowering.cpp +++ b/llvm/lib/CodeGen/GCRootLowering.cpp @@ -81,6 +81,9 @@ public: PreservedAnalyses GCLoweringPass::run(Function &F, FunctionAnalysisManager &FAM) { + if (!F.hasGC()) + return PreservedAnalyses::all(); + auto &Info = FAM.getResult<GCFunctionAnalysis>(F); bool Changed = DoLowering(F, Info.getStrategy()); @@ -178,7 +181,7 @@ static bool InsertRootInitializers(Function &F, ArrayRef<AllocaInst *> Roots) { if (!InitedRoots.count(Root)) { new StoreInst( ConstantPointerNull::get(cast<PointerType>(Root->getAllocatedType())), - Root, Root->getNextNode()); + Root, std::next(Root->getIterator())); MadeChange = true; } @@ -213,8 +216,8 @@ bool DoLowering(Function &F, GCStrategy &S) { default: break; case Intrinsic::gcwrite: { // Replace a write barrier with a simple store. - Value *St = new StoreInst(CI->getArgOperand(0), - CI->getArgOperand(2), CI); + Value *St = new StoreInst(CI->getArgOperand(0), CI->getArgOperand(2), + CI->getIterator()); CI->replaceAllUsesWith(St); CI->eraseFromParent(); MadeChange = true; @@ -222,7 +225,8 @@ bool DoLowering(Function &F, GCStrategy &S) { } case Intrinsic::gcread: { // Replace a read barrier with a simple load. - Value *Ld = new LoadInst(CI->getType(), CI->getArgOperand(1), "", CI); + Value *Ld = new LoadInst(CI->getType(), CI->getArgOperand(1), "", + CI->getIterator()); Ld->takeName(CI); CI->replaceAllUsesWith(Ld); CI->eraseFromParent(); diff --git a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt index 46e6c6df5998e5b4d33f4c7ecaeebd9af1dfea77..54ac7f72011a6ed762f1931a7835c65fb5123a95 100644 --- a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt +++ b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt @@ -6,6 +6,7 @@ add_llvm_component_library(LLVMGlobalISel GlobalISel.cpp Combiner.cpp CombinerHelper.cpp + CombinerHelperVectorOps.cpp GIMatchTableExecutor.cpp GISelChangeObserver.cpp IRTranslator.cpp diff --git a/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp index 1869e0d41a51f637da42087e9d6a533b94a364fc..551ba1e6036c17b99f40532f6991c1b63503be6b 100644 --- a/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp @@ -174,6 +174,20 @@ MachineInstrBuilder CSEMIRBuilder::buildInstr(unsigned Opc, switch (Opc) { default: break; + case TargetOpcode::G_ICMP: { + assert(SrcOps.size() == 3 && "Invalid sources"); + assert(DstOps.size() == 1 && "Invalid dsts"); + LLT SrcTy = SrcOps[1].getLLTTy(*getMRI()); + + if (std::optional<SmallVector<APInt>> Cst = + ConstantFoldICmp(SrcOps[0].getPredicate(), SrcOps[1].getReg(), + SrcOps[2].getReg(), *getMRI())) { + if (SrcTy.isVector()) + return buildBuildVectorConstant(DstOps[0], *Cst); + return buildConstant(DstOps[0], Cst->front()); + } + break; + } case TargetOpcode::G_ADD: case TargetOpcode::G_PTR_ADD: case TargetOpcode::G_AND: @@ -256,10 +270,16 @@ MachineInstrBuilder CSEMIRBuilder::buildInstr(unsigned Opc, return buildFConstant(DstOps[0], *Cst); break; } - case TargetOpcode::G_CTLZ: { + case TargetOpcode::G_CTLZ: + case TargetOpcode::G_CTTZ: { assert(SrcOps.size() == 1 && "Expected one source"); assert(DstOps.size() == 1 && "Expected one dest"); - auto MaybeCsts = ConstantFoldCTLZ(SrcOps[0].getReg(), *getMRI()); + std::function<unsigned(APInt)> CB; + if (Opc == TargetOpcode::G_CTLZ) + CB = [](APInt V) -> unsigned { return V.countl_zero(); }; + else + CB = [](APInt V) -> unsigned { return V.countTrailingZeros(); }; + auto MaybeCsts = ConstantFoldCountZeros(SrcOps[0].getReg(), *getMRI(), CB); if (!MaybeCsts) break; if (MaybeCsts->size() == 1) diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp index 3a37bf3cd7a8a3344311964299f1650cc1c22101..363fad53b76c35e394c29804f0828147bf428a76 100644 --- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp @@ -21,6 +21,7 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Target/TargetMachine.h" @@ -91,6 +92,7 @@ bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const CallBase &CB, ArrayRef<Register> ResRegs, ArrayRef<ArrayRef<Register>> ArgRegs, Register SwiftErrorVReg, + Register ConvergenceCtrlToken, std::function<unsigned()> GetCalleeReg) const { CallLoweringInfo Info; const DataLayout &DL = MIRBuilder.getDataLayout(); @@ -121,7 +123,6 @@ bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const CallBase &CB, CanBeTailCalled = false; } - // First step is to marshall all the function's parameters into the correct // physregs and memory locations. Gather the sequence of argument types that // we'll pass to the assigner function. @@ -187,6 +188,7 @@ bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const CallBase &CB, Info.KnownCallees = CB.getMetadata(LLVMContext::MD_callees); Info.CallConv = CallConv; Info.SwiftErrorVReg = SwiftErrorVReg; + Info.ConvergenceCtrlToken = ConvergenceCtrlToken; Info.IsMustTailCall = CB.isMustTailCall(); Info.IsTailCall = CanBeTailCalled; Info.IsVarArg = IsVarArg; diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp index ab055b723dbb1fd52ffe409b03e4be1ef722ee1a..5cf7a33a5f6756b8137e2fb4d579f1f67c861be2 100644 --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -770,12 +770,12 @@ bool CombinerHelper::matchCombineLoadWithAndMask(MachineInstr &MI, LLT RegTy = MRI.getType(LoadReg); Register PtrReg = LoadMI->getPointerReg(); unsigned RegSize = RegTy.getSizeInBits(); - uint64_t LoadSizeBits = LoadMI->getMemSizeInBits(); + LocationSize LoadSizeBits = LoadMI->getMemSizeInBits(); unsigned MaskSizeBits = MaskVal.countr_one(); // The mask may not be larger than the in-memory type, as it might cover sign // extended bits - if (MaskSizeBits > LoadSizeBits) + if (MaskSizeBits > LoadSizeBits.getValue()) return false; // If the mask covers the whole destination register, there's nothing to @@ -795,7 +795,8 @@ bool CombinerHelper::matchCombineLoadWithAndMask(MachineInstr &MI, // still adjust the opcode to indicate the high bit behavior. if (LoadMI->isSimple()) MemDesc.MemoryTy = LLT::scalar(MaskSizeBits); - else if (LoadSizeBits > MaskSizeBits || LoadSizeBits == RegSize) + else if (LoadSizeBits.getValue() > MaskSizeBits || + LoadSizeBits.getValue() == RegSize) return false; // TODO: Could check if it's legal with the reduced or original memory size. @@ -860,7 +861,8 @@ bool CombinerHelper::matchSextTruncSextLoad(MachineInstr &MI) { if (auto *LoadMI = getOpcodeDef<GSExtLoad>(LoadUser, MRI)) { // If truncating more than the original extended value, abort. auto LoadSizeBits = LoadMI->getMemSizeInBits(); - if (TruncSrc && MRI.getType(TruncSrc).getSizeInBits() < LoadSizeBits) + if (TruncSrc && + MRI.getType(TruncSrc).getSizeInBits() < LoadSizeBits.getValue()) return false; if (LoadSizeBits == SizeInBits) return true; @@ -870,7 +872,6 @@ bool CombinerHelper::matchSextTruncSextLoad(MachineInstr &MI) { void CombinerHelper::applySextTruncSextLoad(MachineInstr &MI) { assert(MI.getOpcode() == TargetOpcode::G_SEXT_INREG); - Builder.setInstrAndDebugLoc(MI); Builder.buildCopy(MI.getOperand(0).getReg(), MI.getOperand(1).getReg()); MI.eraseFromParent(); } @@ -891,7 +892,7 @@ bool CombinerHelper::matchSextInRegOfLoad( if (!LoadDef || !MRI.hasOneNonDBGUse(DstReg)) return false; - uint64_t MemBits = LoadDef->getMemSizeInBits(); + uint64_t MemBits = LoadDef->getMemSizeInBits().getValue(); // If the sign extend extends from a narrower width than the load's width, // then we can narrow the load width when we combine to a G_SEXTLOAD. @@ -1297,7 +1298,6 @@ bool CombinerHelper::matchCombineIndexedLoadStore( void CombinerHelper::applyCombineIndexedLoadStore( MachineInstr &MI, IndexedLoadStoreMatchInfo &MatchInfo) { MachineInstr &AddrDef = *MRI.getUniqueVRegDef(MatchInfo.Addr); - Builder.setInstrAndDebugLoc(MI); unsigned Opcode = MI.getOpcode(); bool IsStore = Opcode == TargetOpcode::G_STORE; unsigned NewOpcode = getIndexedOpc(Opcode); @@ -1414,14 +1414,8 @@ void CombinerHelper::applyCombineDivRem(MachineInstr &MI, // deps by "moving" the instruction incorrectly. Also keep track of which // instruction is first so we pick it's operands, avoiding use-before-def // bugs. - MachineInstr *FirstInst; - if (dominates(MI, *OtherMI)) { - Builder.setInstrAndDebugLoc(MI); - FirstInst = &MI; - } else { - Builder.setInstrAndDebugLoc(*OtherMI); - FirstInst = OtherMI; - } + MachineInstr *FirstInst = dominates(MI, *OtherMI) ? &MI : OtherMI; + Builder.setInstrAndDebugLoc(*FirstInst); Builder.buildInstr(IsSigned ? TargetOpcode::G_SDIVREM : TargetOpcode::G_UDIVREM, @@ -1490,7 +1484,7 @@ void CombinerHelper::applyOptBrCondByInvertingCond(MachineInstr &MI, Observer.changedInstr(*BrCond); } - + bool CombinerHelper::tryEmitMemcpyInline(MachineInstr &MI) { MachineIRBuilder HelperBuilder(MI); GISelObserverWrapper DummyObserver; @@ -1554,7 +1548,6 @@ static APFloat constantFoldFpUnary(const MachineInstr &MI, void CombinerHelper::applyCombineConstantFoldFpUnary(MachineInstr &MI, const ConstantFP *Cst) { - Builder.setInstrAndDebugLoc(MI); APFloat Folded = constantFoldFpUnary(MI, MRI, Cst->getValue()); const ConstantFP *NewCst = ConstantFP::get(Builder.getContext(), Folded); Builder.buildFConstant(MI.getOperand(0), *NewCst); @@ -1689,7 +1682,6 @@ void CombinerHelper::applyShiftImmedChain(MachineInstr &MI, Opcode == TargetOpcode::G_USHLSAT) && "Expected G_SHL, G_ASHR, G_LSHR, G_SSHLSAT or G_USHLSAT"); - Builder.setInstrAndDebugLoc(MI); LLT Ty = MRI.getType(MI.getOperand(1).getReg()); unsigned const ScalarSizeInBits = Ty.getScalarSizeInBits(); auto Imm = MatchInfo.Imm; @@ -1805,7 +1797,6 @@ void CombinerHelper::applyShiftOfShiftedLogic(MachineInstr &MI, LLT ShlType = MRI.getType(MI.getOperand(2).getReg()); LLT DestType = MRI.getType(MI.getOperand(0).getReg()); - Builder.setInstrAndDebugLoc(MI); Register Const = Builder.buildConstant(ShlType, MatchInfo.ValSum).getReg(0); @@ -1941,7 +1932,6 @@ void CombinerHelper::applyCombineShlOfExtend(MachineInstr &MI, int64_t ShiftAmtVal = MatchData.Imm; LLT ExtSrcTy = MRI.getType(ExtSrcReg); - Builder.setInstrAndDebugLoc(MI); auto ShiftAmt = Builder.buildConstant(ExtSrcTy, ShiftAmtVal); auto NarrowShift = Builder.buildShl(ExtSrcTy, ExtSrcReg, ShiftAmt, MI.getFlags()); @@ -2011,7 +2001,6 @@ void CombinerHelper::applyCombineUnmergeMergeToPlainValues( LLT SrcTy = MRI.getType(Operands[0]); LLT DstTy = MRI.getType(MI.getOperand(0).getReg()); bool CanReuseInputDirectly = DstTy == SrcTy; - Builder.setInstrAndDebugLoc(MI); for (unsigned Idx = 0; Idx < NumElems; ++Idx) { Register DstReg = MI.getOperand(Idx).getReg(); Register SrcReg = Operands[Idx]; @@ -2064,7 +2053,6 @@ void CombinerHelper::applyCombineUnmergeConstant(MachineInstr &MI, assert((MI.getNumOperands() - 1 == Csts.size()) && "Not enough operands to replace all defs"); unsigned NumElems = MI.getNumOperands() - 1; - Builder.setInstrAndDebugLoc(MI); for (unsigned Idx = 0; Idx < NumElems; ++Idx) { Register DstReg = MI.getOperand(Idx).getReg(); Builder.buildConstant(DstReg, Csts[Idx]); @@ -2102,7 +2090,6 @@ bool CombinerHelper::matchCombineUnmergeWithDeadLanesToTrunc(MachineInstr &MI) { } void CombinerHelper::applyCombineUnmergeWithDeadLanesToTrunc(MachineInstr &MI) { - Builder.setInstrAndDebugLoc(MI); Register SrcReg = MI.getOperand(MI.getNumDefs()).getReg(); Register Dst0Reg = MI.getOperand(0).getReg(); Builder.buildTrunc(Dst0Reg, SrcReg); @@ -2150,8 +2137,6 @@ void CombinerHelper::applyCombineUnmergeZExtToZExt(MachineInstr &MI) { LLT Dst0Ty = MRI.getType(Dst0Reg); LLT ZExtSrcTy = MRI.getType(ZExtSrcReg); - Builder.setInstrAndDebugLoc(MI); - if (Dst0Ty.getSizeInBits() > ZExtSrcTy.getSizeInBits()) { Builder.buildZExt(Dst0Reg, ZExtSrcReg); } else { @@ -2205,7 +2190,6 @@ void CombinerHelper::applyCombineShiftToUnmerge(MachineInstr &MI, LLT HalfTy = LLT::scalar(HalfSize); - Builder.setInstr(MI); auto Unmerge = Builder.buildUnmerge(HalfTy, SrcReg); unsigned NarrowShiftAmt = ShiftVal - HalfSize; @@ -2290,7 +2274,6 @@ bool CombinerHelper::matchCombineI2PToP2I(MachineInstr &MI, Register &Reg) { void CombinerHelper::applyCombineI2PToP2I(MachineInstr &MI, Register &Reg) { assert(MI.getOpcode() == TargetOpcode::G_INTTOPTR && "Expected a G_INTTOPTR"); Register DstReg = MI.getOperand(0).getReg(); - Builder.setInstr(MI); Builder.buildCopy(DstReg, Reg); MI.eraseFromParent(); } @@ -2298,7 +2281,6 @@ void CombinerHelper::applyCombineI2PToP2I(MachineInstr &MI, Register &Reg) { void CombinerHelper::applyCombineP2IToI2P(MachineInstr &MI, Register &Reg) { assert(MI.getOpcode() == TargetOpcode::G_PTRTOINT && "Expected a G_PTRTOINT"); Register DstReg = MI.getOperand(0).getReg(); - Builder.setInstr(MI); Builder.buildZExtOrTrunc(DstReg, Reg); MI.eraseFromParent(); } @@ -2341,7 +2323,6 @@ void CombinerHelper::applyCombineAddP2IToPtrAdd( LLT PtrTy = MRI.getType(LHS); - Builder.setInstrAndDebugLoc(MI); auto PtrAdd = Builder.buildPtrAdd(PtrTy, LHS, RHS); Builder.buildPtrToInt(Dst, PtrAdd); MI.eraseFromParent(); @@ -2373,7 +2354,6 @@ void CombinerHelper::applyCombineConstPtrAddToI2P(MachineInstr &MI, auto &PtrAdd = cast<GPtrAdd>(MI); Register Dst = PtrAdd.getReg(0); - Builder.setInstrAndDebugLoc(MI); Builder.buildConstant(Dst, NewCst); PtrAdd.eraseFromParent(); } @@ -2453,7 +2433,6 @@ void CombinerHelper::applyCombineExtOfExt( (MI.getOpcode() == TargetOpcode::G_SEXT && SrcExtOp == TargetOpcode::G_ZEXT)) { Register DstReg = MI.getOperand(0).getReg(); - Builder.setInstrAndDebugLoc(MI); Builder.buildInstr(SrcExtOp, {DstReg}, {Reg}); MI.eraseFromParent(); } @@ -2486,7 +2465,6 @@ void CombinerHelper::applyCombineTruncOfExt( replaceRegWith(MRI, DstReg, SrcReg); return; } - Builder.setInstrAndDebugLoc(MI); if (SrcTy.getSizeInBits() < DstTy.getSizeInBits()) Builder.buildInstr(SrcExtOp, {DstReg}, {SrcReg}); else @@ -2574,8 +2552,6 @@ bool CombinerHelper::matchCombineTruncOfShift( void CombinerHelper::applyCombineTruncOfShift( MachineInstr &MI, std::pair<MachineInstr *, LLT> &MatchInfo) { - Builder.setInstrAndDebugLoc(MI); - MachineInstr *ShiftMI = MatchInfo.first; LLT NewShiftTy = MatchInfo.second; @@ -2821,7 +2797,6 @@ void CombinerHelper::applyFunnelShiftConstantModulo(MachineInstr &MI) { APInt NewConst = VRegAndVal->Value.urem( APInt(ConstTy.getSizeInBits(), DstTy.getScalarSizeInBits())); - Builder.setInstrAndDebugLoc(MI); auto NewConstInstr = Builder.buildConstant(ConstTy, NewConst.getZExtValue()); Builder.buildInstr( MI.getOpcode(), {MI.getOperand(0)}, @@ -2864,35 +2839,31 @@ bool CombinerHelper::matchOperandIsKnownToBeAPowerOfTwo(MachineInstr &MI, void CombinerHelper::replaceInstWithFConstant(MachineInstr &MI, double C) { assert(MI.getNumDefs() == 1 && "Expected only one def?"); - Builder.setInstr(MI); Builder.buildFConstant(MI.getOperand(0), C); MI.eraseFromParent(); } void CombinerHelper::replaceInstWithConstant(MachineInstr &MI, int64_t C) { assert(MI.getNumDefs() == 1 && "Expected only one def?"); - Builder.setInstr(MI); Builder.buildConstant(MI.getOperand(0), C); MI.eraseFromParent(); } void CombinerHelper::replaceInstWithConstant(MachineInstr &MI, APInt C) { assert(MI.getNumDefs() == 1 && "Expected only one def?"); - Builder.setInstr(MI); Builder.buildConstant(MI.getOperand(0), C); MI.eraseFromParent(); } -void CombinerHelper::replaceInstWithFConstant(MachineInstr &MI, ConstantFP *CFP) { +void CombinerHelper::replaceInstWithFConstant(MachineInstr &MI, + ConstantFP *CFP) { assert(MI.getNumDefs() == 1 && "Expected only one def?"); - Builder.setInstr(MI); Builder.buildFConstant(MI.getOperand(0), CFP->getValueAPF()); MI.eraseFromParent(); } void CombinerHelper::replaceInstWithUndef(MachineInstr &MI) { assert(MI.getNumDefs() == 1 && "Expected only one def?"); - Builder.setInstr(MI); Builder.buildUndef(MI.getOperand(0)); MI.eraseFromParent(); } @@ -2960,7 +2931,6 @@ bool CombinerHelper::matchCombineInsertVecElts( void CombinerHelper::applyCombineInsertVecElts( MachineInstr &MI, SmallVectorImpl<Register> &MatchInfo) { - Builder.setInstr(MI); Register UndefReg; auto GetUndef = [&]() { if (UndefReg) @@ -2979,7 +2949,6 @@ void CombinerHelper::applyCombineInsertVecElts( void CombinerHelper::applySimplifyAddToSub( MachineInstr &MI, std::tuple<Register, Register> &MatchInfo) { - Builder.setInstr(MI); Register SubLHS, SubRHS; std::tie(SubLHS, SubRHS) = MatchInfo; Builder.buildSub(MI.getOperand(0).getReg(), SubLHS, SubRHS); @@ -3082,7 +3051,6 @@ void CombinerHelper::applyBuildInstructionSteps( MachineInstr &MI, InstructionStepsMatchInfo &MatchInfo) { assert(MatchInfo.InstrsToBuild.size() && "Expected at least one instr to build?"); - Builder.setInstr(MI); for (auto &InstrToBuild : MatchInfo.InstrsToBuild) { assert(InstrToBuild.Opcode && "Expected a valid opcode?"); assert(InstrToBuild.OperandFns.size() && "Expected at least one operand?"); @@ -3118,7 +3086,6 @@ void CombinerHelper::applyAshShlToSextInreg( int64_t ShiftAmt; std::tie(Src, ShiftAmt) = MatchInfo; unsigned Size = MRI.getType(Src).getScalarSizeInBits(); - Builder.setInstrAndDebugLoc(MI); Builder.buildSExtInReg(MI.getOperand(0).getReg(), Src, Size - ShiftAmt); MI.eraseFromParent(); } @@ -3397,7 +3364,6 @@ bool CombinerHelper::matchXorOfAndWithSameReg( void CombinerHelper::applyXorOfAndWithSameReg( MachineInstr &MI, std::pair<Register, Register> &MatchInfo) { // Fold (xor (and x, y), y) -> (and (not x), y) - Builder.setInstrAndDebugLoc(MI); Register X, Y; std::tie(X, Y) = MatchInfo; auto Not = Builder.buildNot(MRI.getType(X), X); @@ -3429,7 +3395,6 @@ bool CombinerHelper::matchPtrAddZero(MachineInstr &MI) { void CombinerHelper::applyPtrAddZero(MachineInstr &MI) { auto &PtrAdd = cast<GPtrAdd>(MI); - Builder.setInstrAndDebugLoc(PtrAdd); Builder.buildIntToPtr(PtrAdd.getReg(0), PtrAdd.getOffsetReg()); PtrAdd.eraseFromParent(); } @@ -3440,7 +3405,6 @@ void CombinerHelper::applySimplifyURemByPow2(MachineInstr &MI) { Register Src0 = MI.getOperand(1).getReg(); Register Pow2Src1 = MI.getOperand(2).getReg(); LLT Ty = MRI.getType(DstReg); - Builder.setInstrAndDebugLoc(MI); // Fold (urem x, pow2) -> (and x, pow2-1) auto NegOne = Builder.buildConstant(Ty, -1); @@ -3505,8 +3469,6 @@ bool CombinerHelper::matchFoldBinOpIntoSelect(MachineInstr &MI, /// to fold. void CombinerHelper::applyFoldBinOpIntoSelect(MachineInstr &MI, const unsigned &SelectOperand) { - Builder.setInstrAndDebugLoc(MI); - Register Dst = MI.getOperand(0).getReg(); Register LHS = MI.getOperand(1).getReg(); Register RHS = MI.getOperand(2).getReg(); @@ -4027,7 +3989,6 @@ void CombinerHelper::applyExtractVecEltBuildVec(MachineInstr &MI, Register DstReg = MI.getOperand(0).getReg(); LLT DstTy = MRI.getType(DstReg); - Builder.setInstrAndDebugLoc(MI); if (ScalarTy != DstTy) { assert(ScalarTy.getSizeInBits() > DstTy.getSizeInBits()); Builder.buildTrunc(DstReg, Reg); @@ -4093,14 +4054,20 @@ void CombinerHelper::applyExtractAllEltsFromBuildVector( void CombinerHelper::applyBuildFn( MachineInstr &MI, std::function<void(MachineIRBuilder &)> &MatchInfo) { - Builder.setInstrAndDebugLoc(MI); - MatchInfo(Builder); + applyBuildFnNoErase(MI, MatchInfo); MI.eraseFromParent(); } +void CombinerHelper::applyBuildFnMO(const MachineOperand &MO, + BuildFnTy &MatchInfo) { + MachineInstr *Root = getDefIgnoringCopies(MO.getReg(), MRI); + Builder.setInstrAndDebugLoc(*Root); + MatchInfo(Builder); + Root->eraseFromParent(); +} + void CombinerHelper::applyBuildFnNoErase( MachineInstr &MI, std::function<void(MachineIRBuilder &)> &MatchInfo) { - Builder.setInstrAndDebugLoc(MI); MatchInfo(Builder); } @@ -4202,7 +4169,6 @@ void CombinerHelper::applyRotateOutOfRange(MachineInstr &MI) { MI.getOpcode() == TargetOpcode::G_ROTR); unsigned Bitsize = MRI.getType(MI.getOperand(0).getReg()).getScalarSizeInBits(); - Builder.setInstrAndDebugLoc(MI); Register Amt = MI.getOperand(2).getReg(); LLT AmtTy = MRI.getType(Amt); auto Bits = Builder.buildConstant(AmtTy, Bitsize); @@ -4936,24 +4902,6 @@ bool CombinerHelper::matchMulOBy0(MachineInstr &MI, BuildFnTy &MatchInfo) { return true; } -bool CombinerHelper::matchAddOBy0(MachineInstr &MI, BuildFnTy &MatchInfo) { - // (G_*ADDO x, 0) -> x + no carry out - assert(MI.getOpcode() == TargetOpcode::G_UADDO || - MI.getOpcode() == TargetOpcode::G_SADDO); - if (!mi_match(MI.getOperand(3).getReg(), MRI, m_SpecificICstOrSplat(0))) - return false; - Register Carry = MI.getOperand(1).getReg(); - if (!isConstantLegalOrBeforeLegalizer(MRI.getType(Carry))) - return false; - Register Dst = MI.getOperand(0).getReg(); - Register LHS = MI.getOperand(2).getReg(); - MatchInfo = [=](MachineIRBuilder &B) { - B.buildCopy(Dst, LHS); - B.buildConstant(Carry, 0); - }; - return true; -} - bool CombinerHelper::matchAddEToAddO(MachineInstr &MI, BuildFnTy &MatchInfo) { // (G_*ADDE x, y, 0) -> (G_*ADDO x, y) // (G_*SUBE x, y, 0) -> (G_*SUBO x, y) @@ -5043,7 +4991,6 @@ MachineInstr *CombinerHelper::buildUDivUsingMul(MachineInstr &MI) { LLT ShiftAmtTy = getTargetLowering().getPreferredShiftAmountTy(Ty); LLT ScalarShiftAmtTy = ShiftAmtTy.getScalarType(); auto &MIB = Builder; - MIB.setInstrAndDebugLoc(MI); bool UseNPQ = false; SmallVector<Register, 16> PreShifts, PostShifts, MagicFactors, NPQFactors; @@ -5229,7 +5176,6 @@ MachineInstr *CombinerHelper::buildSDivUsingMul(MachineInstr &MI) { LLT ShiftAmtTy = getTargetLowering().getPreferredShiftAmountTy(Ty); LLT ScalarShiftAmtTy = ShiftAmtTy.getScalarType(); auto &MIB = Builder; - MIB.setInstrAndDebugLoc(MI); bool UseSRA = false; SmallVector<Register, 16> Shifts, Factors; @@ -5286,6 +5232,93 @@ MachineInstr *CombinerHelper::buildSDivUsingMul(MachineInstr &MI) { return MIB.buildMul(Ty, Res, Factor); } +bool CombinerHelper::matchDivByPow2(MachineInstr &MI, bool IsSigned) { + assert((MI.getOpcode() == TargetOpcode::G_SDIV || + MI.getOpcode() == TargetOpcode::G_UDIV) && + "Expected SDIV or UDIV"); + auto &Div = cast<GenericMachineInstr>(MI); + Register RHS = Div.getReg(2); + auto MatchPow2 = [&](const Constant *C) { + auto *CI = dyn_cast<ConstantInt>(C); + return CI && (CI->getValue().isPowerOf2() || + (IsSigned && CI->getValue().isNegatedPowerOf2())); + }; + return matchUnaryPredicate(MRI, RHS, MatchPow2, /*AllowUndefs=*/false); +} + +void CombinerHelper::applySDivByPow2(MachineInstr &MI) { + assert(MI.getOpcode() == TargetOpcode::G_SDIV && "Expected SDIV"); + auto &SDiv = cast<GenericMachineInstr>(MI); + Register Dst = SDiv.getReg(0); + Register LHS = SDiv.getReg(1); + Register RHS = SDiv.getReg(2); + LLT Ty = MRI.getType(Dst); + LLT ShiftAmtTy = getTargetLowering().getPreferredShiftAmountTy(Ty); + LLT CCVT = + Ty.isVector() ? LLT::vector(Ty.getElementCount(), 1) : LLT::scalar(1); + + // Effectively we want to lower G_SDIV %lhs, %rhs, where %rhs is a power of 2, + // to the following version: + // + // %c1 = G_CTTZ %rhs + // %inexact = G_SUB $bitwidth, %c1 + // %sign = %G_ASHR %lhs, $(bitwidth - 1) + // %lshr = G_LSHR %sign, %inexact + // %add = G_ADD %lhs, %lshr + // %ashr = G_ASHR %add, %c1 + // %ashr = G_SELECT, %isoneorallones, %lhs, %ashr + // %zero = G_CONSTANT $0 + // %neg = G_NEG %ashr + // %isneg = G_ICMP SLT %rhs, %zero + // %res = G_SELECT %isneg, %neg, %ashr + + unsigned BitWidth = Ty.getScalarSizeInBits(); + auto Zero = Builder.buildConstant(Ty, 0); + + auto Bits = Builder.buildConstant(ShiftAmtTy, BitWidth); + auto C1 = Builder.buildCTTZ(ShiftAmtTy, RHS); + auto Inexact = Builder.buildSub(ShiftAmtTy, Bits, C1); + // Splat the sign bit into the register + auto Sign = Builder.buildAShr( + Ty, LHS, Builder.buildConstant(ShiftAmtTy, BitWidth - 1)); + + // Add (LHS < 0) ? abs2 - 1 : 0; + auto LSrl = Builder.buildLShr(Ty, Sign, Inexact); + auto Add = Builder.buildAdd(Ty, LHS, LSrl); + auto AShr = Builder.buildAShr(Ty, Add, C1); + + // Special case: (sdiv X, 1) -> X + // Special Case: (sdiv X, -1) -> 0-X + auto One = Builder.buildConstant(Ty, 1); + auto MinusOne = Builder.buildConstant(Ty, -1); + auto IsOne = Builder.buildICmp(CmpInst::Predicate::ICMP_EQ, CCVT, RHS, One); + auto IsMinusOne = + Builder.buildICmp(CmpInst::Predicate::ICMP_EQ, CCVT, RHS, MinusOne); + auto IsOneOrMinusOne = Builder.buildOr(CCVT, IsOne, IsMinusOne); + AShr = Builder.buildSelect(Ty, IsOneOrMinusOne, LHS, AShr); + + // If divided by a positive value, we're done. Otherwise, the result must be + // negated. + auto Neg = Builder.buildNeg(Ty, AShr); + auto IsNeg = Builder.buildICmp(CmpInst::Predicate::ICMP_SLT, CCVT, RHS, Zero); + Builder.buildSelect(MI.getOperand(0).getReg(), IsNeg, Neg, AShr); + MI.eraseFromParent(); +} + +void CombinerHelper::applyUDivByPow2(MachineInstr &MI) { + assert(MI.getOpcode() == TargetOpcode::G_UDIV && "Expected UDIV"); + auto &UDiv = cast<GenericMachineInstr>(MI); + Register Dst = UDiv.getReg(0); + Register LHS = UDiv.getReg(1); + Register RHS = UDiv.getReg(2); + LLT Ty = MRI.getType(Dst); + LLT ShiftAmtTy = getTargetLowering().getPreferredShiftAmountTy(Ty); + + auto C1 = Builder.buildCTTZ(ShiftAmtTy, RHS); + Builder.buildLShr(MI.getOperand(0).getReg(), LHS, C1); + MI.eraseFromParent(); +} + bool CombinerHelper::matchUMulHToLShr(MachineInstr &MI) { assert(MI.getOpcode() == TargetOpcode::G_UMULH); Register RHS = MI.getOperand(2).getReg(); @@ -5310,7 +5343,6 @@ void CombinerHelper::applyUMulHToLShr(MachineInstr &MI) { LLT ShiftAmtTy = getTargetLowering().getPreferredShiftAmountTy(Ty); unsigned NumEltBits = Ty.getScalarSizeInBits(); - Builder.setInstrAndDebugLoc(MI); auto LogBase2 = buildLogBase2(RHS, Builder); auto ShiftAmt = Builder.buildSub(Ty, Builder.buildConstant(Ty, NumEltBits), LogBase2); @@ -5390,7 +5422,6 @@ bool CombinerHelper::matchFsubToFneg(MachineInstr &MI, Register &MatchInfo) { } void CombinerHelper::applyFsubToFneg(MachineInstr &MI, Register &MatchInfo) { - Builder.setInstrAndDebugLoc(MI); Register Dst = MI.getOperand(0).getReg(); Builder.buildFNeg( Dst, Builder.buildFCanonicalize(MRI.getType(Dst), MatchInfo).getReg(0)); @@ -6354,6 +6385,26 @@ CombinerHelper::getConstantOrConstantSplatVector(Register Src) { return Value; } +// FIXME G_SPLAT_VECTOR +bool CombinerHelper::isConstantOrConstantVectorI(Register Src) const { + auto IConstant = getIConstantVRegValWithLookThrough(Src, MRI); + if (IConstant) + return true; + + GBuildVector *BuildVector = getOpcodeDef<GBuildVector>(Src, MRI); + if (!BuildVector) + return false; + + unsigned NumSources = BuildVector->getNumSources(); + for (unsigned I = 0; I < NumSources; ++I) { + std::optional<ValueAndVReg> IConstant = + getIConstantVRegValWithLookThrough(BuildVector->getSourceReg(I), MRI); + if (!IConstant) + return false; + } + return true; +} + // TODO: use knownbits to determine zeros bool CombinerHelper::tryFoldSelectOfConstants(GSelect *Select, BuildFnTy &MatchInfo) { @@ -6928,3 +6979,170 @@ bool CombinerHelper::matchOr(MachineInstr &MI, BuildFnTy &MatchInfo) { return false; } + +bool CombinerHelper::matchAddOverflow(MachineInstr &MI, BuildFnTy &MatchInfo) { + GAddCarryOut *Add = cast<GAddCarryOut>(&MI); + + // Addo has no flags + Register Dst = Add->getReg(0); + Register Carry = Add->getReg(1); + Register LHS = Add->getLHSReg(); + Register RHS = Add->getRHSReg(); + bool IsSigned = Add->isSigned(); + LLT DstTy = MRI.getType(Dst); + LLT CarryTy = MRI.getType(Carry); + + // Fold addo, if the carry is dead -> add, undef. + if (MRI.use_nodbg_empty(Carry) && + isLegalOrBeforeLegalizer({TargetOpcode::G_ADD, {DstTy}})) { + MatchInfo = [=](MachineIRBuilder &B) { + B.buildAdd(Dst, LHS, RHS); + B.buildUndef(Carry); + }; + return true; + } + + // Canonicalize constant to RHS. + if (isConstantOrConstantVectorI(LHS) && !isConstantOrConstantVectorI(RHS)) { + if (IsSigned) { + MatchInfo = [=](MachineIRBuilder &B) { + B.buildSAddo(Dst, Carry, RHS, LHS); + }; + return true; + } + // !IsSigned + MatchInfo = [=](MachineIRBuilder &B) { + B.buildUAddo(Dst, Carry, RHS, LHS); + }; + return true; + } + + std::optional<APInt> MaybeLHS = getConstantOrConstantSplatVector(LHS); + std::optional<APInt> MaybeRHS = getConstantOrConstantSplatVector(RHS); + + // Fold addo(c1, c2) -> c3, carry. + if (MaybeLHS && MaybeRHS && isConstantLegalOrBeforeLegalizer(DstTy) && + isConstantLegalOrBeforeLegalizer(CarryTy)) { + bool Overflow; + APInt Result = IsSigned ? MaybeLHS->sadd_ov(*MaybeRHS, Overflow) + : MaybeLHS->uadd_ov(*MaybeRHS, Overflow); + MatchInfo = [=](MachineIRBuilder &B) { + B.buildConstant(Dst, Result); + B.buildConstant(Carry, Overflow); + }; + return true; + } + + // Fold (addo x, 0) -> x, no carry + if (MaybeRHS && *MaybeRHS == 0 && isConstantLegalOrBeforeLegalizer(CarryTy)) { + MatchInfo = [=](MachineIRBuilder &B) { + B.buildCopy(Dst, LHS); + B.buildConstant(Carry, 0); + }; + return true; + } + + // Given 2 constant operands whose sum does not overflow: + // uaddo (X +nuw C0), C1 -> uaddo X, C0 + C1 + // saddo (X +nsw C0), C1 -> saddo X, C0 + C1 + GAdd *AddLHS = getOpcodeDef<GAdd>(LHS, MRI); + if (MaybeRHS && AddLHS && MRI.hasOneNonDBGUse(Add->getReg(0)) && + ((IsSigned && AddLHS->getFlag(MachineInstr::MIFlag::NoSWrap)) || + (!IsSigned && AddLHS->getFlag(MachineInstr::MIFlag::NoUWrap)))) { + std::optional<APInt> MaybeAddRHS = + getConstantOrConstantSplatVector(AddLHS->getRHSReg()); + if (MaybeAddRHS) { + bool Overflow; + APInt NewC = IsSigned ? MaybeAddRHS->sadd_ov(*MaybeRHS, Overflow) + : MaybeAddRHS->uadd_ov(*MaybeRHS, Overflow); + if (!Overflow && isConstantLegalOrBeforeLegalizer(DstTy)) { + if (IsSigned) { + MatchInfo = [=](MachineIRBuilder &B) { + auto ConstRHS = B.buildConstant(DstTy, NewC); + B.buildSAddo(Dst, Carry, AddLHS->getLHSReg(), ConstRHS); + }; + return true; + } + // !IsSigned + MatchInfo = [=](MachineIRBuilder &B) { + auto ConstRHS = B.buildConstant(DstTy, NewC); + B.buildUAddo(Dst, Carry, AddLHS->getLHSReg(), ConstRHS); + }; + return true; + } + } + }; + + // We try to combine addo to non-overflowing add. + if (!isLegalOrBeforeLegalizer({TargetOpcode::G_ADD, {DstTy}}) || + !isConstantLegalOrBeforeLegalizer(CarryTy)) + return false; + + // We try to combine uaddo to non-overflowing add. + if (!IsSigned) { + ConstantRange CRLHS = + ConstantRange::fromKnownBits(KB->getKnownBits(LHS), /*IsSigned=*/false); + ConstantRange CRRHS = + ConstantRange::fromKnownBits(KB->getKnownBits(RHS), /*IsSigned=*/false); + + switch (CRLHS.unsignedAddMayOverflow(CRRHS)) { + case ConstantRange::OverflowResult::MayOverflow: + return false; + case ConstantRange::OverflowResult::NeverOverflows: { + MatchInfo = [=](MachineIRBuilder &B) { + B.buildAdd(Dst, LHS, RHS, MachineInstr::MIFlag::NoUWrap); + B.buildConstant(Carry, 0); + }; + return true; + } + case ConstantRange::OverflowResult::AlwaysOverflowsLow: + case ConstantRange::OverflowResult::AlwaysOverflowsHigh: { + MatchInfo = [=](MachineIRBuilder &B) { + B.buildAdd(Dst, LHS, RHS); + B.buildConstant(Carry, 1); + }; + return true; + } + } + return false; + } + + // We try to combine saddo to non-overflowing add. + + // If LHS and RHS each have at least two sign bits, then there is no signed + // overflow. + if (KB->computeNumSignBits(RHS) > 1 && KB->computeNumSignBits(LHS) > 1) { + MatchInfo = [=](MachineIRBuilder &B) { + B.buildAdd(Dst, LHS, RHS, MachineInstr::MIFlag::NoSWrap); + B.buildConstant(Carry, 0); + }; + return true; + } + + ConstantRange CRLHS = + ConstantRange::fromKnownBits(KB->getKnownBits(LHS), /*IsSigned=*/true); + ConstantRange CRRHS = + ConstantRange::fromKnownBits(KB->getKnownBits(RHS), /*IsSigned=*/true); + + switch (CRLHS.signedAddMayOverflow(CRRHS)) { + case ConstantRange::OverflowResult::MayOverflow: + return false; + case ConstantRange::OverflowResult::NeverOverflows: { + MatchInfo = [=](MachineIRBuilder &B) { + B.buildAdd(Dst, LHS, RHS, MachineInstr::MIFlag::NoSWrap); + B.buildConstant(Carry, 0); + }; + return true; + } + case ConstantRange::OverflowResult::AlwaysOverflowsLow: + case ConstantRange::OverflowResult::AlwaysOverflowsHigh: { + MatchInfo = [=](MachineIRBuilder &B) { + B.buildAdd(Dst, LHS, RHS); + B.buildConstant(Carry, 1); + }; + return true; + } + } + + return false; +} diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelperVectorOps.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelperVectorOps.cpp new file mode 100644 index 0000000000000000000000000000000000000000..123bf21f657c3643240fba5424ea008902f5d5c6 --- /dev/null +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelperVectorOps.cpp @@ -0,0 +1,326 @@ +//===- CombinerHelperVectorOps.cpp-----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements CombinerHelper for G_EXTRACT_VECTOR_ELT. +// +//===----------------------------------------------------------------------===// +#include "llvm/CodeGen/GlobalISel/CombinerHelper.h" +#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" +#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" +#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" +#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h" +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" +#include "llvm/CodeGen/GlobalISel/Utils.h" +#include "llvm/CodeGen/LowLevelTypeUtils.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/TargetLowering.h" +#include "llvm/CodeGen/TargetOpcodes.h" +#include "llvm/Support/Casting.h" +#include <optional> + +#define DEBUG_TYPE "gi-combiner" + +using namespace llvm; +using namespace MIPatternMatch; + +bool CombinerHelper::matchExtractVectorElement(MachineInstr &MI, + BuildFnTy &MatchInfo) { + GExtractVectorElement *Extract = cast<GExtractVectorElement>(&MI); + + Register Dst = Extract->getReg(0); + Register Vector = Extract->getVectorReg(); + Register Index = Extract->getIndexReg(); + LLT DstTy = MRI.getType(Dst); + LLT VectorTy = MRI.getType(Vector); + + // The vector register can be def'd by various ops that have vector as its + // type. They can all be used for constant folding, scalarizing, + // canonicalization, or combining based on symmetry. + // + // vector like ops + // * build vector + // * build vector trunc + // * shuffle vector + // * splat vector + // * concat vectors + // * insert/extract vector element + // * insert/extract subvector + // * vector loads + // * scalable vector loads + // + // compute like ops + // * binary ops + // * unary ops + // * exts and truncs + // * casts + // * fneg + // * select + // * phis + // * cmps + // * freeze + // * bitcast + // * undef + + // We try to get the value of the Index register. + std::optional<ValueAndVReg> MaybeIndex = + getIConstantVRegValWithLookThrough(Index, MRI); + std::optional<APInt> IndexC = std::nullopt; + + if (MaybeIndex) + IndexC = MaybeIndex->Value; + + // Fold extractVectorElement(Vector, TOOLARGE) -> undef + if (IndexC && VectorTy.isFixedVector() && + IndexC->getZExtValue() >= VectorTy.getNumElements() && + isLegalOrBeforeLegalizer({TargetOpcode::G_IMPLICIT_DEF, {DstTy}})) { + // For fixed-length vectors, it's invalid to extract out-of-range elements. + MatchInfo = [=](MachineIRBuilder &B) { B.buildUndef(Dst); }; + return true; + } + + return false; +} + +bool CombinerHelper::matchExtractVectorElementWithDifferentIndices( + const MachineOperand &MO, BuildFnTy &MatchInfo) { + MachineInstr *Root = getDefIgnoringCopies(MO.getReg(), MRI); + GExtractVectorElement *Extract = cast<GExtractVectorElement>(Root); + + // + // %idx1:_(s64) = G_CONSTANT i64 1 + // %idx2:_(s64) = G_CONSTANT i64 2 + // %insert:_(<2 x s32>) = G_INSERT_VECTOR_ELT_ELT %bv(<2 x s32>), + // %value(s32), %idx2(s64) %extract:_(s32) = G_EXTRACT_VECTOR_ELT %insert(<2 + // x s32>), %idx1(s64) + // + // --> + // + // %insert:_(<2 x s32>) = G_INSERT_VECTOR_ELT_ELT %bv(<2 x s32>), + // %value(s32), %idx2(s64) %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x + // s32>), %idx1(s64) + // + // + + Register Index = Extract->getIndexReg(); + + // We try to get the value of the Index register. + std::optional<ValueAndVReg> MaybeIndex = + getIConstantVRegValWithLookThrough(Index, MRI); + std::optional<APInt> IndexC = std::nullopt; + + if (!MaybeIndex) + return false; + else + IndexC = MaybeIndex->Value; + + Register Vector = Extract->getVectorReg(); + + GInsertVectorElement *Insert = + getOpcodeDef<GInsertVectorElement>(Vector, MRI); + if (!Insert) + return false; + + Register Dst = Extract->getReg(0); + + std::optional<ValueAndVReg> MaybeInsertIndex = + getIConstantVRegValWithLookThrough(Insert->getIndexReg(), MRI); + + if (MaybeInsertIndex && MaybeInsertIndex->Value != *IndexC) { + // There is no one-use check. We have to keep the insert. When both Index + // registers are constants and not equal, we can look into the Vector + // register of the insert. + MatchInfo = [=](MachineIRBuilder &B) { + B.buildExtractVectorElement(Dst, Insert->getVectorReg(), Index); + }; + return true; + } + + return false; +} + +bool CombinerHelper::matchExtractVectorElementWithFreeze( + const MachineOperand &MO, BuildFnTy &MatchInfo) { + MachineInstr *Root = getDefIgnoringCopies(MO.getReg(), MRI); + GExtractVectorElement *Extract = cast<GExtractVectorElement>(Root); + + Register Vector = Extract->getVectorReg(); + + // + // %bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32) + // %freeze:_(<2 x s32>) = G_FREEZE %bv(<2 x s32>) + // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %opaque(s64) + // + // --> + // + // %bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32) + // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %opaque(s64) + // %freeze:_(s32) = G_FREEZE %extract(s32) + // + // + + // For G_FREEZE, the input and the output types are identical. Moving the + // freeze from the Vector into the front of the extract preserves the freeze + // semantics. The result is still freeze'd. Furthermore, the Vector register + // becomes easier to analyze. A build vector could have been hidden behind the + // freeze. + + // We expect a freeze on the Vector register. + GFreeze *Freeze = getOpcodeDef<GFreeze>(Vector, MRI); + if (!Freeze) + return false; + + Register Dst = Extract->getReg(0); + LLT DstTy = MRI.getType(Dst); + + // We first have to check for one-use and legality of the freeze. + // The type of the extractVectorElement did not change. + if (!MRI.hasOneNonDBGUse(Freeze->getReg(0)) || + !isLegalOrBeforeLegalizer({TargetOpcode::G_FREEZE, {DstTy}})) + return false; + + Register Index = Extract->getIndexReg(); + + // We move the freeze from the Vector register in front of the + // extractVectorElement. + MatchInfo = [=](MachineIRBuilder &B) { + auto Extract = + B.buildExtractVectorElement(DstTy, Freeze->getSourceReg(), Index); + B.buildFreeze(Dst, Extract); + }; + + return true; +} + +bool CombinerHelper::matchExtractVectorElementWithBuildVector( + const MachineOperand &MO, BuildFnTy &MatchInfo) { + MachineInstr *Root = getDefIgnoringCopies(MO.getReg(), MRI); + GExtractVectorElement *Extract = cast<GExtractVectorElement>(Root); + + // + // %zero:_(s64) = G_CONSTANT i64 0 + // %bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32) + // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %zero(s64) + // + // --> + // + // %extract:_(32) = COPY %arg1(s32) + // + // + // + // %bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32) + // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %opaque(s64) + // + // --> + // + // %bv:_(<2 x s32>) = G_BUILD_VECTOR %arg1(s32), %arg2(s32) + // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %opaque(s64) + // + + Register Vector = Extract->getVectorReg(); + + // We expect a buildVector on the Vector register. + GBuildVector *Build = getOpcodeDef<GBuildVector>(Vector, MRI); + if (!Build) + return false; + + LLT VectorTy = MRI.getType(Vector); + + // There is a one-use check. There are more combines on build vectors. + EVT Ty(getMVTForLLT(VectorTy)); + if (!MRI.hasOneNonDBGUse(Build->getReg(0)) || + !getTargetLowering().aggressivelyPreferBuildVectorSources(Ty)) + return false; + + Register Index = Extract->getIndexReg(); + + // If the Index is constant, then we can extract the element from the given + // offset. + std::optional<ValueAndVReg> MaybeIndex = + getIConstantVRegValWithLookThrough(Index, MRI); + if (!MaybeIndex) + return false; + + // We now know that there is a buildVector def'd on the Vector register and + // the index is const. The combine will succeed. + + Register Dst = Extract->getReg(0); + + MatchInfo = [=](MachineIRBuilder &B) { + B.buildCopy(Dst, Build->getSourceReg(MaybeIndex->Value.getZExtValue())); + }; + + return true; +} + +bool CombinerHelper::matchExtractVectorElementWithBuildVectorTrunc( + const MachineOperand &MO, BuildFnTy &MatchInfo) { + MachineInstr *Root = getDefIgnoringCopies(MO.getReg(), MRI); + GExtractVectorElement *Extract = cast<GExtractVectorElement>(Root); + + // + // %zero:_(s64) = G_CONSTANT i64 0 + // %bv:_(<2 x s32>) = G_BUILD_VECTOR_TRUNC %arg1(s64), %arg2(s64) + // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %zero(s64) + // + // --> + // + // %extract:_(32) = G_TRUNC %arg1(s64) + // + // + // + // %bv:_(<2 x s32>) = G_BUILD_VECTOR_TRUNC %arg1(s64), %arg2(s64) + // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %opaque(s64) + // + // --> + // + // %bv:_(<2 x s32>) = G_BUILD_VECTOR_TRUNC %arg1(s64), %arg2(s64) + // %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %opaque(s64) + // + + Register Vector = Extract->getVectorReg(); + + // We expect a buildVectorTrunc on the Vector register. + GBuildVectorTrunc *Build = getOpcodeDef<GBuildVectorTrunc>(Vector, MRI); + if (!Build) + return false; + + LLT VectorTy = MRI.getType(Vector); + + // There is a one-use check. There are more combines on build vectors. + EVT Ty(getMVTForLLT(VectorTy)); + if (!MRI.hasOneNonDBGUse(Build->getReg(0)) || + !getTargetLowering().aggressivelyPreferBuildVectorSources(Ty)) + return false; + + Register Index = Extract->getIndexReg(); + + // If the Index is constant, then we can extract the element from the given + // offset. + std::optional<ValueAndVReg> MaybeIndex = + getIConstantVRegValWithLookThrough(Index, MRI); + if (!MaybeIndex) + return false; + + // We now know that there is a buildVectorTrunc def'd on the Vector register + // and the index is const. The combine will succeed. + + Register Dst = Extract->getReg(0); + LLT DstTy = MRI.getType(Dst); + LLT SrcTy = MRI.getType(Build->getSourceReg(0)); + + // For buildVectorTrunc, the inputs are truncated. + if (!isLegalOrBeforeLegalizer({TargetOpcode::G_TRUNC, {DstTy, SrcTy}})) + return false; + + MatchInfo = [=](MachineIRBuilder &B) { + B.buildTrunc(Dst, Build->getSourceReg(MaybeIndex->Value.getZExtValue())); + }; + + return true; +} diff --git a/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp b/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp index 099bf45b2734cbaa18b1c1bf9e2a4ad6ab257883..51ab7b6262c6229165e13e9f10c83ee41d7ce161 100644 --- a/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp +++ b/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp @@ -405,17 +405,23 @@ void GISelKnownBits::computeKnownBitsImpl(Register R, KnownBits &Known, } case TargetOpcode::G_LOAD: { const MachineMemOperand *MMO = *MI.memoperands_begin(); - if (const MDNode *Ranges = MMO->getRanges()) { - computeKnownBitsFromRangeMetadata(*Ranges, Known); - } - + KnownBits KnownRange(MMO->getMemoryType().getScalarSizeInBits()); + if (const MDNode *Ranges = MMO->getRanges()) + computeKnownBitsFromRangeMetadata(*Ranges, KnownRange); + Known = KnownRange.anyext(Known.getBitWidth()); break; } + case TargetOpcode::G_SEXTLOAD: case TargetOpcode::G_ZEXTLOAD: { if (DstTy.isVector()) break; - // Everything above the retrieved bits is zero - Known.Zero.setBitsFrom((*MI.memoperands_begin())->getSizeInBits()); + const MachineMemOperand *MMO = *MI.memoperands_begin(); + KnownBits KnownRange(MMO->getMemoryType().getScalarSizeInBits()); + if (const MDNode *Ranges = MMO->getRanges()) + computeKnownBitsFromRangeMetadata(*Ranges, KnownRange); + Known = Opcode == TargetOpcode::G_SEXTLOAD + ? KnownRange.sext(Known.getBitWidth()) + : KnownRange.zext(Known.getBitWidth()); break; } case TargetOpcode::G_ASHR: { @@ -588,6 +594,17 @@ void GISelKnownBits::computeKnownBitsImpl(Register R, KnownBits &Known, } break; } + case TargetOpcode::G_CTLZ: + case TargetOpcode::G_CTLZ_ZERO_UNDEF: { + KnownBits SrcOpKnown; + computeKnownBitsImpl(MI.getOperand(1).getReg(), SrcOpKnown, DemandedElts, + Depth + 1); + // If we have a known 1, its position is our upper bound. + unsigned PossibleLZ = SrcOpKnown.countMaxLeadingZeros(); + unsigned LowBits = llvm::bit_width(PossibleLZ); + Known.Zero.setBitsFrom(LowBits); + break; + } } assert(!Known.hasConflict() && "Bits known to be one AND zero?"); @@ -666,7 +683,7 @@ unsigned GISelKnownBits::computeNumSignBits(Register R, // e.g. i16->i32 = '17' bits known. const MachineMemOperand *MMO = *MI.memoperands_begin(); - return TyBits - MMO->getSizeInBits() + 1; + return TyBits - MMO->getSizeInBits().getValue() + 1; } case TargetOpcode::G_ZEXTLOAD: { // FIXME: We need an in-memory type representation. @@ -675,7 +692,7 @@ unsigned GISelKnownBits::computeNumSignBits(Register R, // e.g. i16->i32 = '16' bits known. const MachineMemOperand *MMO = *MI.memoperands_begin(); - return TyBits - MMO->getSizeInBits(); + return TyBits - MMO->getSizeInBits().getValue(); } case TargetOpcode::G_TRUNC: { Register Src = MI.getOperand(1).getReg(); diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index 94fdb37e283bb4bc0d0316c573ae9737cc77e1e7..47e980e05281fcb2a278888049e72546a2326bed 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -21,6 +21,7 @@ #include "llvm/Analysis/Loads.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/Analysis/VectorUtils.h" #include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/GlobalISel/CSEInfo.h" #include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h" @@ -213,8 +214,9 @@ ArrayRef<Register> IRTranslator::getOrCreateVRegs(const Value &Val) { auto *VRegs = VMap.getVRegs(Val); auto *Offsets = VMap.getOffsets(Val); - assert(Val.getType()->isSized() && - "Don't know how to create an empty vreg"); + if (!Val.getType()->isTokenTy()) + assert(Val.getType()->isSized() && + "Don't know how to create an empty vreg"); SmallVector<LLT, 4> SplitTys; computeValueLLTs(*DL, *Val.getType(), SplitTys, @@ -1361,9 +1363,8 @@ static bool isSwiftError(const Value *V) { bool IRTranslator::translateLoad(const User &U, MachineIRBuilder &MIRBuilder) { const LoadInst &LI = cast<LoadInst>(U); - - unsigned StoreSize = DL->getTypeStoreSize(LI.getType()); - if (StoreSize == 0) + TypeSize StoreSize = DL->getTypeStoreSize(LI.getType()); + if (StoreSize.isZero()) return true; ArrayRef<Register> Regs = getOrCreateVRegs(LI); @@ -1561,9 +1562,14 @@ bool IRTranslator::translateCast(unsigned Opcode, const User &U, if (U.getType()->getScalarType()->isBFloatTy() || U.getOperand(0)->getType()->getScalarType()->isBFloatTy()) return false; + + uint32_t Flags = 0; + if (const Instruction *I = dyn_cast<Instruction>(&U)) + Flags = MachineInstr::copyFlagsFromInstruction(*I); + Register Op = getOrCreateVReg(*U.getOperand(0)); Register Res = getOrCreateVReg(U); - MIRBuilder.buildInstr(Opcode, {Res}, {Op}); + MIRBuilder.buildInstr(Opcode, {Res}, {Op}, Flags); return true; } @@ -1770,6 +1776,67 @@ bool IRTranslator::translateMemFunc(const CallInst &CI, return true; } +bool IRTranslator::translateTrap(const CallInst &CI, + MachineIRBuilder &MIRBuilder, + unsigned Opcode) { + StringRef TrapFuncName = + CI.getAttributes().getFnAttr("trap-func-name").getValueAsString(); + if (TrapFuncName.empty()) { + if (Opcode == TargetOpcode::G_UBSANTRAP) { + uint64_t Code = cast<ConstantInt>(CI.getOperand(0))->getZExtValue(); + MIRBuilder.buildInstr(Opcode, {}, ArrayRef<llvm::SrcOp>{Code}); + } else { + MIRBuilder.buildInstr(Opcode); + } + return true; + } + + CallLowering::CallLoweringInfo Info; + if (Opcode == TargetOpcode::G_UBSANTRAP) + Info.OrigArgs.push_back({getOrCreateVRegs(*CI.getArgOperand(0)), + CI.getArgOperand(0)->getType(), 0}); + + Info.Callee = MachineOperand::CreateES(TrapFuncName.data()); + Info.CB = &CI; + Info.OrigRet = {Register(), Type::getVoidTy(CI.getContext()), 0}; + return CLI->lowerCall(MIRBuilder, Info); +} + +bool IRTranslator::translateVectorInterleave2Intrinsic( + const CallInst &CI, MachineIRBuilder &MIRBuilder) { + assert(CI.getIntrinsicID() == Intrinsic::experimental_vector_interleave2 && + "This function can only be called on the interleave2 intrinsic!"); + // Canonicalize interleave2 to G_SHUFFLE_VECTOR (similar to SelectionDAG). + Register Op0 = getOrCreateVReg(*CI.getOperand(0)); + Register Op1 = getOrCreateVReg(*CI.getOperand(1)); + Register Res = getOrCreateVReg(CI); + + LLT OpTy = MRI->getType(Op0); + MIRBuilder.buildShuffleVector(Res, Op0, Op1, + createInterleaveMask(OpTy.getNumElements(), 2)); + + return true; +} + +bool IRTranslator::translateVectorDeinterleave2Intrinsic( + const CallInst &CI, MachineIRBuilder &MIRBuilder) { + assert(CI.getIntrinsicID() == Intrinsic::experimental_vector_deinterleave2 && + "This function can only be called on the deinterleave2 intrinsic!"); + // Canonicalize deinterleave2 to shuffles that extract sub-vectors (similar to + // SelectionDAG). + Register Op = getOrCreateVReg(*CI.getOperand(0)); + auto Undef = MIRBuilder.buildUndef(MRI->getType(Op)); + ArrayRef<Register> Res = getOrCreateVRegs(CI); + + LLT ResTy = MRI->getType(Res[0]); + MIRBuilder.buildShuffleVector(Res[0], Op, Undef, + createStrideMask(0, 2, ResTy.getNumElements())); + MIRBuilder.buildShuffleVector(Res[1], Op, Undef, + createStrideMask(1, 2, ResTy.getNumElements())); + + return true; +} + void IRTranslator::getStackGuard(Register DstReg, MachineIRBuilder &MIRBuilder) { const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); @@ -2038,6 +2105,36 @@ bool IRTranslator::translateIfEntryValueArgument(bool isDeclare, Value *Val, return true; } +static unsigned getConvOpcode(Intrinsic::ID ID) { + switch (ID) { + default: + llvm_unreachable("Unexpected intrinsic"); + case Intrinsic::experimental_convergence_anchor: + return TargetOpcode::CONVERGENCECTRL_ANCHOR; + case Intrinsic::experimental_convergence_entry: + return TargetOpcode::CONVERGENCECTRL_ENTRY; + case Intrinsic::experimental_convergence_loop: + return TargetOpcode::CONVERGENCECTRL_LOOP; + } +} + +bool IRTranslator::translateConvergenceControlIntrinsic( + const CallInst &CI, Intrinsic::ID ID, MachineIRBuilder &MIRBuilder) { + MachineInstrBuilder MIB = MIRBuilder.buildInstr(getConvOpcode(ID)); + Register OutputReg = getOrCreateConvergenceTokenVReg(CI); + MIB.addDef(OutputReg); + + if (ID == Intrinsic::experimental_convergence_loop) { + auto Bundle = CI.getOperandBundle(LLVMContext::OB_convergencectrl); + assert(Bundle && "Expected a convergence control token."); + Register InputReg = + getOrCreateConvergenceTokenVReg(*Bundle->Inputs[0].get()); + MIB.addUse(InputReg); + } + + return true; +} + bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, MachineIRBuilder &MIRBuilder) { if (auto *MI = dyn_cast<AnyMemIntrinsic>(&CI)) { @@ -2393,22 +2490,16 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, return true; } case Intrinsic::trap: + return translateTrap(CI, MIRBuilder, TargetOpcode::G_TRAP); case Intrinsic::debugtrap: - case Intrinsic::ubsantrap: { - StringRef TrapFuncName = - CI.getAttributes().getFnAttr("trap-func-name").getValueAsString(); - if (TrapFuncName.empty()) - break; // Use the default handling. - CallLowering::CallLoweringInfo Info; - if (ID == Intrinsic::ubsantrap) { - Info.OrigArgs.push_back({getOrCreateVRegs(*CI.getArgOperand(0)), - CI.getArgOperand(0)->getType(), 0}); - } - Info.Callee = MachineOperand::CreateES(TrapFuncName.data()); - Info.CB = &CI; - Info.OrigRet = {Register(), Type::getVoidTy(CI.getContext()), 0}; - return CLI->lowerCall(MIRBuilder, Info); - } + return translateTrap(CI, MIRBuilder, TargetOpcode::G_DEBUGTRAP); + case Intrinsic::ubsantrap: + return translateTrap(CI, MIRBuilder, TargetOpcode::G_UBSANTRAP); + case Intrinsic::allow_runtime_check: + case Intrinsic::allow_ubsan_check: + MIRBuilder.buildCopy(getOrCreateVReg(CI), + getOrCreateVReg(*ConstantInt::getTrue(CI.getType()))); + return true; case Intrinsic::amdgcn_cs_chain: return translateCallBase(CI, MIRBuilder); case Intrinsic::fptrunc_round: { @@ -2474,12 +2565,30 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, return true; } + + case Intrinsic::experimental_vector_interleave2: + case Intrinsic::experimental_vector_deinterleave2: { + // Both intrinsics have at least one operand. + Value *Op0 = CI.getOperand(0); + LLT ResTy = getLLTForType(*Op0->getType(), MIRBuilder.getDataLayout()); + if (!ResTy.isFixedVector()) + return false; + + if (CI.getIntrinsicID() == Intrinsic::experimental_vector_interleave2) + return translateVectorInterleave2Intrinsic(CI, MIRBuilder); + + return translateVectorDeinterleave2Intrinsic(CI, MIRBuilder); + } + #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ case Intrinsic::INTRINSIC: #include "llvm/IR/ConstrainedOps.def" return translateConstrainedFPIntrinsic(cast<ConstrainedFPIntrinsic>(CI), MIRBuilder); - + case Intrinsic::experimental_convergence_anchor: + case Intrinsic::experimental_convergence_entry: + case Intrinsic::experimental_convergence_loop: + return translateConvergenceControlIntrinsic(CI, ID, MIRBuilder); } return false; } @@ -2530,12 +2639,18 @@ bool IRTranslator::translateCallBase(const CallBase &CB, } } + Register ConvergenceCtrlToken = 0; + if (auto Bundle = CB.getOperandBundle(LLVMContext::OB_convergencectrl)) { + const auto &Token = *Bundle->Inputs[0].get(); + ConvergenceCtrlToken = getOrCreateConvergenceTokenVReg(Token); + } + // We don't set HasCalls on MFI here yet because call lowering may decide to // optimize into tail calls. Instead, we defer that to selection where a final // scan is done to check if any instructions are calls. - bool Success = - CLI->lowerCall(MIRBuilder, CB, Res, Args, SwiftErrorVReg, - [&]() { return getOrCreateVReg(*CB.getCalledOperand()); }); + bool Success = CLI->lowerCall( + MIRBuilder, CB, Res, Args, SwiftErrorVReg, ConvergenceCtrlToken, + [&]() { return getOrCreateVReg(*CB.getCalledOperand()); }); // Check if we just inserted a tail call. if (Success) { @@ -2649,6 +2764,14 @@ bool IRTranslator::translateCall(const User &U, MachineIRBuilder &MIRBuilder) { MF->getMachineMemOperand(MPI, Info.flags, MemTy, Alignment, CI.getAAMetadata())); } + if (CI.isConvergent()) { + if (auto Bundle = CI.getOperandBundle(LLVMContext::OB_convergencectrl)) { + auto *Token = Bundle->Inputs[0].get(); + Register TokenReg = getOrCreateVReg(*Token); + MIB.addUse(TokenReg, RegState::Implicit); + } + } + return true; } @@ -2949,7 +3072,7 @@ bool IRTranslator::translateUnreachable(const User &U, MachineIRBuilder &MIRBuil } } - MIRBuilder.buildIntrinsic(Intrinsic::trap, ArrayRef<Register>()); + MIRBuilder.buildTrap(); return true; } @@ -3278,25 +3401,25 @@ void IRTranslator::translateDbgDeclareRecord(Value *Address, bool HasArgList, void IRTranslator::translateDbgInfo(const Instruction &Inst, MachineIRBuilder &MIRBuilder) { for (DbgRecord &DR : Inst.getDbgRecordRange()) { - if (DPLabel *DPL = dyn_cast<DPLabel>(&DR)) { - MIRBuilder.setDebugLoc(DPL->getDebugLoc()); - assert(DPL->getLabel() && "Missing label"); - assert(DPL->getLabel()->isValidLocationForIntrinsic( + if (DbgLabelRecord *DLR = dyn_cast<DbgLabelRecord>(&DR)) { + MIRBuilder.setDebugLoc(DLR->getDebugLoc()); + assert(DLR->getLabel() && "Missing label"); + assert(DLR->getLabel()->isValidLocationForIntrinsic( MIRBuilder.getDebugLoc()) && "Expected inlined-at fields to agree"); - MIRBuilder.buildDbgLabel(DPL->getLabel()); + MIRBuilder.buildDbgLabel(DLR->getLabel()); continue; } - DPValue &DPV = cast<DPValue>(DR); - const DILocalVariable *Variable = DPV.getVariable(); - const DIExpression *Expression = DPV.getExpression(); - Value *V = DPV.getVariableLocationOp(0); - if (DPV.isDbgDeclare()) - translateDbgDeclareRecord(V, DPV.hasArgList(), Variable, - Expression, DPV.getDebugLoc(), MIRBuilder); + DbgVariableRecord &DVR = cast<DbgVariableRecord>(DR); + const DILocalVariable *Variable = DVR.getVariable(); + const DIExpression *Expression = DVR.getExpression(); + Value *V = DVR.getVariableLocationOp(0); + if (DVR.isDbgDeclare()) + translateDbgDeclareRecord(V, DVR.hasArgList(), Variable, Expression, + DVR.getDebugLoc(), MIRBuilder); else - translateDbgValueRecord(V, DPV.hasArgList(), Variable, - Expression, DPV.getDebugLoc(), MIRBuilder); + translateDbgValueRecord(V, DVR.hasArgList(), Variable, Expression, + DVR.getDebugLoc(), MIRBuilder); } } diff --git a/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp b/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp index 4089a5e941b05129fcf2fe51571a493f7953f3eb..14e1e1fdf01dea7c34add818c40e71622556fed8 100644 --- a/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp +++ b/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp @@ -538,6 +538,14 @@ bool InlineAsmLowering::lowerInlineAsm( } } + if (auto Bundle = Call.getOperandBundle(LLVMContext::OB_convergencectrl)) { + auto *Token = Bundle->Inputs[0].get(); + ArrayRef<Register> SourceRegs = GetOrCreateVRegs(*Token); + assert(SourceRegs.size() == 1 && + "Expected the control token to fit into a single virtual register"); + Inst.addUse(SourceRegs[0], RegState::Implicit); + } + if (const MDNode *SrcLoc = Call.getMetadata("srcloc")) Inst.addMetadata(SrcLoc); diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index bd3ff7265d51f9144367948fa577bfc539368c74..797bbf7efe605b591d91c0ed81d8b5e29b3234ea 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -1317,7 +1317,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, if (DstTy.isVector()) return UnableToLegalize; - if (8 * LoadMI.getMemSize() != DstTy.getSizeInBits()) { + if (8 * LoadMI.getMemSize().getValue() != DstTy.getSizeInBits()) { Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy); MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO()); MIRBuilder.buildAnyExt(DstReg, TmpReg); @@ -1335,7 +1335,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy); auto &MMO = LoadMI.getMMO(); - unsigned MemSize = MMO.getSizeInBits(); + unsigned MemSize = MMO.getSizeInBits().getValue(); if (MemSize == NarrowSize) { MIRBuilder.buildLoad(TmpReg, PtrReg, MMO); @@ -1368,7 +1368,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, if (SrcTy.isVector() && LeftoverBits != 0) return UnableToLegalize; - if (8 * StoreMI.getMemSize() != SrcTy.getSizeInBits()) { + if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) { Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy); MIRBuilder.buildTrunc(TmpReg, SrcReg); MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO()); @@ -1699,6 +1699,20 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, case TargetOpcode::G_FLDEXP: case TargetOpcode::G_STRICT_FLDEXP: return narrowScalarFLDEXP(MI, TypeIdx, NarrowTy); + case TargetOpcode::G_VSCALE: { + Register Dst = MI.getOperand(0).getReg(); + LLT Ty = MRI.getType(Dst); + + // Assume VSCALE(1) fits into a legal integer + const APInt One(NarrowTy.getSizeInBits(), 1); + auto VScaleBase = MIRBuilder.buildVScale(NarrowTy, One); + auto ZExt = MIRBuilder.buildZExt(Ty, VScaleBase); + auto C = MIRBuilder.buildConstant(Ty, *MI.getOperand(1).getCImm()); + MIRBuilder.buildMul(Dst, ZExt, C); + + MI.eraseFromParent(); + return Legalized; + } } } @@ -2966,7 +2980,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { case TargetOpcode::G_VECREDUCE_FMIN: case TargetOpcode::G_VECREDUCE_FMAX: case TargetOpcode::G_VECREDUCE_FMINIMUM: - case TargetOpcode::G_VECREDUCE_FMAXIMUM: + case TargetOpcode::G_VECREDUCE_FMAXIMUM: { if (TypeIdx != 0) return UnableToLegalize; Observer.changingInstr(MI); @@ -2980,6 +2994,19 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { Observer.changedInstr(MI); return Legalized; } + case TargetOpcode::G_VSCALE: { + MachineOperand &SrcMO = MI.getOperand(1); + LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext(); + const APInt &SrcVal = SrcMO.getCImm()->getValue(); + // The CImm is always a signed value + const APInt Val = SrcVal.sext(WideTy.getSizeInBits()); + Observer.changingInstr(MI); + SrcMO.setCImm(ConstantInt::get(Ctx, Val)); + widenScalarDst(MI, WideTy); + Observer.changedInstr(MI); + return Legalized; + } + } } static void getUnmergePieces(SmallVectorImpl<Register> &Pieces, @@ -3741,9 +3768,11 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) { } case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: { auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] = MI.getFirst5Regs(); - MIRBuilder.buildAtomicCmpXchg(OldValRes, Addr, CmpVal, NewVal, + Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes); + MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal, **MI.memoperands_begin()); - MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, OldValRes, CmpVal); + MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, NewOldValRes, CmpVal); + MIRBuilder.buildCopy(OldValRes, NewOldValRes); MI.eraseFromParent(); return Legalized; } @@ -3762,8 +3791,12 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) { case G_UADDO: { auto [Res, CarryOut, LHS, RHS] = MI.getFirst4Regs(); - MIRBuilder.buildAdd(Res, LHS, RHS); - MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, Res, RHS); + Register NewRes = MRI.cloneVirtualRegister(Res); + + MIRBuilder.buildAdd(NewRes, LHS, RHS); + MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, NewRes, RHS); + + MIRBuilder.buildCopy(Res, NewRes); MI.eraseFromParent(); return Legalized; @@ -3773,6 +3806,8 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) { const LLT CondTy = MRI.getType(CarryOut); const LLT Ty = MRI.getType(Res); + Register NewRes = MRI.cloneVirtualRegister(Res); + // Initial add of the two operands. auto TmpRes = MIRBuilder.buildAdd(Ty, LHS, RHS); @@ -3781,15 +3816,18 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) { // Add the sum and the carry. auto ZExtCarryIn = MIRBuilder.buildZExt(Ty, CarryIn); - MIRBuilder.buildAdd(Res, TmpRes, ZExtCarryIn); + MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn); // Second check for carry. We can only carry if the initial sum is all 1s // and the carry is set, resulting in a new sum of 0. auto Zero = MIRBuilder.buildConstant(Ty, 0); - auto ResEqZero = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, CondTy, Res, Zero); + auto ResEqZero = + MIRBuilder.buildICmp(CmpInst::ICMP_EQ, CondTy, NewRes, Zero); auto Carry2 = MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn); MIRBuilder.buildOr(CarryOut, Carry, Carry2); + MIRBuilder.buildCopy(Res, NewRes); + MI.eraseFromParent(); return Legalized; } @@ -4456,7 +4494,7 @@ LegalizerHelper::reduceLoadStoreWidth(GLoadStore &LdStMI, unsigned TypeIdx, LLT ValTy = MRI.getType(ValReg); // FIXME: Do we need a distinct NarrowMemory legalize action? - if (ValTy.getSizeInBits() != 8 * LdStMI.getMemSize()) { + if (ValTy.getSizeInBits() != 8 * LdStMI.getMemSize().getValue()) { LLVM_DEBUG(dbgs() << "Can't narrow extload/truncstore\n"); return UnableToLegalize; } @@ -5411,6 +5449,9 @@ LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx, MI.eraseFromParent(); return Legalized; } + case TargetOpcode::G_SEXT: + case TargetOpcode::G_ZEXT: + case TargetOpcode::G_ANYEXT: case TargetOpcode::G_TRUNC: case TargetOpcode::G_FPTRUNC: case TargetOpcode::G_FPEXT: @@ -5418,14 +5459,22 @@ LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx, case TargetOpcode::G_FPTOUI: case TargetOpcode::G_SITOFP: case TargetOpcode::G_UITOFP: { - if (TypeIdx != 0) - return UnableToLegalize; Observer.changingInstr(MI); - LLT SrcTy = LLT::fixed_vector( - MoreTy.getNumElements(), - MRI.getType(MI.getOperand(1).getReg()).getElementType()); - moreElementsVectorSrc(MI, SrcTy, 1); - moreElementsVectorDst(MI, MoreTy, 0); + LLT SrcExtTy; + LLT DstExtTy; + if (TypeIdx == 0) { + DstExtTy = MoreTy; + SrcExtTy = LLT::fixed_vector( + MoreTy.getNumElements(), + MRI.getType(MI.getOperand(1).getReg()).getElementType()); + } else { + DstExtTy = LLT::fixed_vector( + MoreTy.getNumElements(), + MRI.getType(MI.getOperand(0).getReg()).getElementType()); + SrcExtTy = MoreTy; + } + moreElementsVectorSrc(MI, SrcExtTy, 1); + moreElementsVectorDst(MI, DstExtTy, 0); Observer.changedInstr(MI); return Legalized; } @@ -6351,12 +6400,26 @@ LegalizerHelper::lowerBitCount(MachineInstr &MI) { // 8 bits can hold CTPOP result of 128 bit int or smaller. Mul with this // bitmask will set 8 msb in ResTmp to sum of all B8Counts in 8 bit blocks. auto MulMask = B.buildConstant(Ty, APInt::getSplat(Size, APInt(8, 0x01))); - auto ResTmp = B.buildMul(Ty, B8Count, MulMask); // Shift count result from 8 high bits to low bits. auto C_SizeM8 = B.buildConstant(Ty, Size - 8); - B.buildLShr(MI.getOperand(0).getReg(), ResTmp, C_SizeM8); + auto IsMulSupported = [this](const LLT Ty) { + auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action; + return Action == Legal || Action == WidenScalar || Action == Custom; + }; + if (IsMulSupported(Ty)) { + auto ResTmp = B.buildMul(Ty, B8Count, MulMask); + B.buildLShr(MI.getOperand(0).getReg(), ResTmp, C_SizeM8); + } else { + auto ResTmp = B8Count; + for (unsigned Shift = 8; Shift < Size; Shift *= 2) { + auto ShiftC = B.buildConstant(Ty, Shift); + auto Shl = B.buildShl(Ty, ResTmp, ShiftC); + ResTmp = B.buildAdd(Ty, ResTmp, Shl); + } + B.buildLShr(MI.getOperand(0).getReg(), ResTmp, C_SizeM8); + } MI.eraseFromParent(); return Legalized; } @@ -7619,10 +7682,12 @@ LegalizerHelper::lowerSADDO_SSUBO(MachineInstr &MI) { LLT Ty = Dst0Ty; LLT BoolTy = Dst1Ty; + Register NewDst0 = MRI.cloneVirtualRegister(Dst0); + if (IsAdd) - MIRBuilder.buildAdd(Dst0, LHS, RHS); + MIRBuilder.buildAdd(NewDst0, LHS, RHS); else - MIRBuilder.buildSub(Dst0, LHS, RHS); + MIRBuilder.buildSub(NewDst0, LHS, RHS); // TODO: If SADDSAT/SSUBSAT is legal, compare results to detect overflow. @@ -7635,12 +7700,15 @@ LegalizerHelper::lowerSADDO_SSUBO(MachineInstr &MI) { // (LHS) if and only if the other operand (RHS) is (non-zero) positive, // otherwise there will be overflow. auto ResultLowerThanLHS = - MIRBuilder.buildICmp(CmpInst::ICMP_SLT, BoolTy, Dst0, LHS); + MIRBuilder.buildICmp(CmpInst::ICMP_SLT, BoolTy, NewDst0, LHS); auto ConditionRHS = MIRBuilder.buildICmp( IsAdd ? CmpInst::ICMP_SLT : CmpInst::ICMP_SGT, BoolTy, RHS, Zero); MIRBuilder.buildXor(Dst1, ConditionRHS, ResultLowerThanLHS); + + MIRBuilder.buildCopy(Dst0, NewDst0); MI.eraseFromParent(); + return Legalized; } @@ -7852,7 +7920,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerBswap(MachineInstr &MI) { //{ (Src & Mask) >> N } | { (Src << N) & Mask } static MachineInstrBuilder SwapN(unsigned N, DstOp Dst, MachineIRBuilder &B, - MachineInstrBuilder Src, APInt Mask) { + MachineInstrBuilder Src, const APInt &Mask) { const LLT Ty = Dst.getLLTTy(*B.getMRI()); MachineInstrBuilder C_N = B.buildConstant(Ty, N); MachineInstrBuilder MaskLoNTo0 = B.buildConstant(Ty, Mask); @@ -8212,9 +8280,22 @@ LegalizerHelper::lowerAbsToMaxNeg(MachineInstr &MI) { // %res = G_SMAX %a, %v2 Register SrcReg = MI.getOperand(1).getReg(); LLT Ty = MRI.getType(SrcReg); + auto Zero = MIRBuilder.buildConstant(Ty, 0); + auto Sub = MIRBuilder.buildSub(Ty, Zero, SrcReg); + MIRBuilder.buildSMax(MI.getOperand(0), SrcReg, Sub); + MI.eraseFromParent(); + return Legalized; +} + +LegalizerHelper::LegalizeResult +LegalizerHelper::lowerAbsToCNeg(MachineInstr &MI) { + Register SrcReg = MI.getOperand(1).getReg(); + Register DestReg = MI.getOperand(0).getReg(); + LLT Ty = MRI.getType(SrcReg), IType = LLT::scalar(1); auto Zero = MIRBuilder.buildConstant(Ty, 0).getReg(0); auto Sub = MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0); - MIRBuilder.buildSMax(MI.getOperand(0), SrcReg, Sub); + auto ICmp = MIRBuilder.buildICmp(CmpInst::ICMP_SGT, IType, SrcReg, Zero); + MIRBuilder.buildSelect(DestReg, ICmp, SrcReg, Sub); MI.eraseFromParent(); return Legalized; } diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp index 4ee1793d33d2ca4438fbab9e82d30181c1071a9e..c9ee35373cd4455f879fde122da936e6ab0cd3e8 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp @@ -154,7 +154,8 @@ static bool mutationIsSane(const LegalizeRule &Rule, case WidenScalar: { if (OldTy.isVector()) { // Number of elements should not change. - if (!NewTy.isVector() || OldTy.getNumElements() != NewTy.getNumElements()) + if (!NewTy.isVector() || + OldTy.getElementCount() != NewTy.getElementCount()) return false; } else { // Both types must be vectors diff --git a/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp b/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp index b5c9d3e912cc207666aef3121498eaf0afc0784c..fb9656c09ca39de127dd668749bb764cc70f1388 100644 --- a/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp @@ -117,12 +117,8 @@ bool GISelAddressing::aliasIsKnownForLoadStore(const MachineInstr &MI1, if (!BasePtr0.BaseReg.isValid() || !BasePtr1.BaseReg.isValid()) return false; - LocationSize Size1 = LdSt1->getMemSize() != MemoryLocation::UnknownSize - ? LdSt1->getMemSize() - : LocationSize::beforeOrAfterPointer(); - LocationSize Size2 = LdSt2->getMemSize() != MemoryLocation::UnknownSize - ? LdSt2->getMemSize() - : LocationSize::beforeOrAfterPointer(); + LocationSize Size1 = LdSt1->getMemSize(); + LocationSize Size2 = LdSt2->getMemSize(); int64_t PtrDiff; if (BasePtr0.BaseReg == BasePtr1.BaseReg) { @@ -132,14 +128,14 @@ bool GISelAddressing::aliasIsKnownForLoadStore(const MachineInstr &MI1, // vector objects on the stack. // BasePtr1 is PtrDiff away from BasePtr0. They alias if none of the // following situations arise: - if (PtrDiff >= 0 && Size1.hasValue()) { + if (PtrDiff >= 0 && Size1.hasValue() && !Size1.isScalable()) { // [----BasePtr0----] // [---BasePtr1--] // ========PtrDiff========> IsAlias = !((int64_t)Size1.getValue() <= PtrDiff); return true; } - if (PtrDiff < 0 && Size2.hasValue()) { + if (PtrDiff < 0 && Size2.hasValue() && !Size2.isScalable()) { // [----BasePtr0----] // [---BasePtr1--] // =====(-PtrDiff)====> @@ -214,14 +210,9 @@ bool GISelAddressing::instMayAlias(const MachineInstr &MI, Offset = 0; } - TypeSize Size = LS->getMMO().getMemoryType().getSizeInBytes(); - return {LS->isVolatile(), - LS->isAtomic(), - BaseReg, - Offset /*base offset*/, - Size.isScalable() ? LocationSize::beforeOrAfterPointer() - : LocationSize::precise(Size), - &LS->getMMO()}; + LocationSize Size = LS->getMMO().getSize(); + return {LS->isVolatile(), LS->isAtomic(), BaseReg, + Offset /*base offset*/, Size, &LS->getMMO()}; } // FIXME: support recognizing lifetime instructions. // Default. @@ -257,10 +248,20 @@ bool GISelAddressing::instMayAlias(const MachineInstr &MI, return false; } + // If NumBytes is scalable and offset is not 0, conservatively return may + // alias + if ((MUC0.NumBytes.isScalable() && MUC0.Offset != 0) || + (MUC1.NumBytes.isScalable() && MUC1.Offset != 0)) + return true; + + const bool BothNotScalable = + !MUC0.NumBytes.isScalable() && !MUC1.NumBytes.isScalable(); + // Try to prove that there is aliasing, or that there is no aliasing. Either // way, we can return now. If nothing can be proved, proceed with more tests. bool IsAlias; - if (GISelAddressing::aliasIsKnownForLoadStore(MI, Other, IsAlias, MRI)) + if (BothNotScalable && + GISelAddressing::aliasIsKnownForLoadStore(MI, Other, IsAlias, MRI)) return IsAlias; // The following all rely on MMO0 and MMO1 being valid. @@ -276,12 +277,18 @@ bool GISelAddressing::instMayAlias(const MachineInstr &MI, Size1.hasValue()) { // Use alias analysis information. int64_t MinOffset = std::min(SrcValOffset0, SrcValOffset1); - int64_t Overlap0 = Size0.getValue() + SrcValOffset0 - MinOffset; - int64_t Overlap1 = Size1.getValue() + SrcValOffset1 - MinOffset; - if (AA->isNoAlias(MemoryLocation(MUC0.MMO->getValue(), Overlap0, - MUC0.MMO->getAAInfo()), - MemoryLocation(MUC1.MMO->getValue(), Overlap1, - MUC1.MMO->getAAInfo()))) + int64_t Overlap0 = + Size0.getValue().getKnownMinValue() + SrcValOffset0 - MinOffset; + int64_t Overlap1 = + Size1.getValue().getKnownMinValue() + SrcValOffset1 - MinOffset; + LocationSize Loc0 = + Size0.isScalable() ? Size0 : LocationSize::precise(Overlap0); + LocationSize Loc1 = + Size1.isScalable() ? Size1 : LocationSize::precise(Overlap1); + + if (AA->isNoAlias( + MemoryLocation(MUC0.MMO->getValue(), Loc0, MUC0.MMO->getAAInfo()), + MemoryLocation(MUC1.MMO->getValue(), Loc1, MUC1.MMO->getAAInfo()))) return false; } diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp index f7aaa0f02efcb313e85bc63b0ec53ca7eafd538b..b8ba782254c37010c41ce41a48ec319d8aeeb402 100644 --- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -811,6 +811,13 @@ MachineInstrBuilder MachineIRBuilder::buildVScale(const DstOp &Res, return VScale; } +MachineInstrBuilder MachineIRBuilder::buildVScale(const DstOp &Res, + const APInt &MinElts) { + ConstantInt *CI = + ConstantInt::get(getMF().getFunction().getContext(), MinElts); + return buildVScale(Res, *CI); +} + static unsigned getIntrinsicOpcode(bool HasSideEffects, bool IsConvergent) { if (HasSideEffects && IsConvergent) return TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS; @@ -923,14 +930,14 @@ MachineIRBuilder::buildExtractVectorElement(const DstOp &Res, const SrcOp &Val, } MachineInstrBuilder MachineIRBuilder::buildAtomicCmpXchgWithSuccess( - Register OldValRes, Register SuccessRes, Register Addr, Register CmpVal, - Register NewVal, MachineMemOperand &MMO) { + const DstOp &OldValRes, const DstOp &SuccessRes, const SrcOp &Addr, + const SrcOp &CmpVal, const SrcOp &NewVal, MachineMemOperand &MMO) { #ifndef NDEBUG - LLT OldValResTy = getMRI()->getType(OldValRes); - LLT SuccessResTy = getMRI()->getType(SuccessRes); - LLT AddrTy = getMRI()->getType(Addr); - LLT CmpValTy = getMRI()->getType(CmpVal); - LLT NewValTy = getMRI()->getType(NewVal); + LLT OldValResTy = OldValRes.getLLTTy(*getMRI()); + LLT SuccessResTy = SuccessRes.getLLTTy(*getMRI()); + LLT AddrTy = Addr.getLLTTy(*getMRI()); + LLT CmpValTy = CmpVal.getLLTTy(*getMRI()); + LLT NewValTy = NewVal.getLLTTy(*getMRI()); assert(OldValResTy.isScalar() && "invalid operand type"); assert(SuccessResTy.isScalar() && "invalid operand type"); assert(AddrTy.isPointer() && "invalid operand type"); @@ -940,24 +947,25 @@ MachineInstrBuilder MachineIRBuilder::buildAtomicCmpXchgWithSuccess( assert(OldValResTy == NewValTy && "type mismatch"); #endif - return buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS) - .addDef(OldValRes) - .addDef(SuccessRes) - .addUse(Addr) - .addUse(CmpVal) - .addUse(NewVal) - .addMemOperand(&MMO); + auto MIB = buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS); + OldValRes.addDefToMIB(*getMRI(), MIB); + SuccessRes.addDefToMIB(*getMRI(), MIB); + Addr.addSrcToMIB(MIB); + CmpVal.addSrcToMIB(MIB); + NewVal.addSrcToMIB(MIB); + MIB.addMemOperand(&MMO); + return MIB; } MachineInstrBuilder -MachineIRBuilder::buildAtomicCmpXchg(Register OldValRes, Register Addr, - Register CmpVal, Register NewVal, +MachineIRBuilder::buildAtomicCmpXchg(const DstOp &OldValRes, const SrcOp &Addr, + const SrcOp &CmpVal, const SrcOp &NewVal, MachineMemOperand &MMO) { #ifndef NDEBUG - LLT OldValResTy = getMRI()->getType(OldValRes); - LLT AddrTy = getMRI()->getType(Addr); - LLT CmpValTy = getMRI()->getType(CmpVal); - LLT NewValTy = getMRI()->getType(NewVal); + LLT OldValResTy = OldValRes.getLLTTy(*getMRI()); + LLT AddrTy = Addr.getLLTTy(*getMRI()); + LLT CmpValTy = CmpVal.getLLTTy(*getMRI()); + LLT NewValTy = NewVal.getLLTTy(*getMRI()); assert(OldValResTy.isScalar() && "invalid operand type"); assert(AddrTy.isPointer() && "invalid operand type"); assert(CmpValTy.isValid() && "invalid operand type"); @@ -966,12 +974,13 @@ MachineIRBuilder::buildAtomicCmpXchg(Register OldValRes, Register Addr, assert(OldValResTy == NewValTy && "type mismatch"); #endif - return buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG) - .addDef(OldValRes) - .addUse(Addr) - .addUse(CmpVal) - .addUse(NewVal) - .addMemOperand(&MMO); + auto MIB = buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG); + OldValRes.addDefToMIB(*getMRI(), MIB); + Addr.addSrcToMIB(MIB); + CmpVal.addSrcToMIB(MIB); + NewVal.addSrcToMIB(MIB); + MIB.addMemOperand(&MMO); + return MIB; } MachineInstrBuilder MachineIRBuilder::buildAtomicRMW( @@ -1153,7 +1162,7 @@ void MachineIRBuilder::validateSelectOp(const LLT ResTy, const LLT TstTy, else assert((TstTy.isScalar() || (TstTy.isVector() && - TstTy.getNumElements() == Op0Ty.getNumElements())) && + TstTy.getElementCount() == Op0Ty.getElementCount())) && "type mismatch"); #endif } diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp index a9fa73b60a097f44efc66656bae35382bbe3d29b..c3bc3203b636057c6e58f69eeed6c11d64526ae5 100644 --- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp +++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp @@ -966,14 +966,15 @@ llvm::ConstantFoldIntToFloat(unsigned Opcode, LLT DstTy, Register Src, } std::optional<SmallVector<unsigned>> -llvm::ConstantFoldCTLZ(Register Src, const MachineRegisterInfo &MRI) { +llvm::ConstantFoldCountZeros(Register Src, const MachineRegisterInfo &MRI, + std::function<unsigned(APInt)> CB) { LLT Ty = MRI.getType(Src); SmallVector<unsigned> FoldedCTLZs; auto tryFoldScalar = [&](Register R) -> std::optional<unsigned> { auto MaybeCst = getIConstantVRegVal(R, MRI); if (!MaybeCst) return std::nullopt; - return MaybeCst->countl_zero(); + return CB(*MaybeCst); }; if (Ty.isVector()) { // Try to constant fold each element. @@ -996,6 +997,74 @@ llvm::ConstantFoldCTLZ(Register Src, const MachineRegisterInfo &MRI) { return std::nullopt; } +std::optional<SmallVector<APInt>> +llvm::ConstantFoldICmp(unsigned Pred, const Register Op1, const Register Op2, + const MachineRegisterInfo &MRI) { + LLT Ty = MRI.getType(Op1); + if (Ty != MRI.getType(Op2)) + return std::nullopt; + + auto TryFoldScalar = [&MRI, Pred](Register LHS, + Register RHS) -> std::optional<APInt> { + auto LHSCst = getIConstantVRegVal(LHS, MRI); + auto RHSCst = getIConstantVRegVal(RHS, MRI); + if (!LHSCst || !RHSCst) + return std::nullopt; + + switch (Pred) { + case CmpInst::Predicate::ICMP_EQ: + return APInt(/*numBits=*/1, LHSCst->eq(*RHSCst)); + case CmpInst::Predicate::ICMP_NE: + return APInt(/*numBits=*/1, LHSCst->ne(*RHSCst)); + case CmpInst::Predicate::ICMP_UGT: + return APInt(/*numBits=*/1, LHSCst->ugt(*RHSCst)); + case CmpInst::Predicate::ICMP_UGE: + return APInt(/*numBits=*/1, LHSCst->uge(*RHSCst)); + case CmpInst::Predicate::ICMP_ULT: + return APInt(/*numBits=*/1, LHSCst->ult(*RHSCst)); + case CmpInst::Predicate::ICMP_ULE: + return APInt(/*numBits=*/1, LHSCst->ule(*RHSCst)); + case CmpInst::Predicate::ICMP_SGT: + return APInt(/*numBits=*/1, LHSCst->sgt(*RHSCst)); + case CmpInst::Predicate::ICMP_SGE: + return APInt(/*numBits=*/1, LHSCst->sge(*RHSCst)); + case CmpInst::Predicate::ICMP_SLT: + return APInt(/*numBits=*/1, LHSCst->slt(*RHSCst)); + case CmpInst::Predicate::ICMP_SLE: + return APInt(/*numBits=*/1, LHSCst->sle(*RHSCst)); + default: + return std::nullopt; + } + }; + + SmallVector<APInt> FoldedICmps; + + if (Ty.isVector()) { + // Try to constant fold each element. + auto *BV1 = getOpcodeDef<GBuildVector>(Op1, MRI); + auto *BV2 = getOpcodeDef<GBuildVector>(Op2, MRI); + if (!BV1 || !BV2) + return std::nullopt; + assert(BV1->getNumSources() == BV2->getNumSources() && "Invalid vectors"); + for (unsigned I = 0; I < BV1->getNumSources(); ++I) { + if (auto MaybeFold = + TryFoldScalar(BV1->getSourceReg(I), BV2->getSourceReg(I))) { + FoldedICmps.emplace_back(*MaybeFold); + continue; + } + return std::nullopt; + } + return FoldedICmps; + } + + if (auto MaybeCst = TryFoldScalar(Op1, Op2)) { + FoldedICmps.emplace_back(*MaybeCst); + return FoldedICmps; + } + + return std::nullopt; +} + bool llvm::isKnownToBeAPowerOfTwo(Register Reg, const MachineRegisterInfo &MRI, GISelKnownBits *KB) { std::optional<DefinitionAndSourceRegister> DefSrcReg = diff --git a/llvm/lib/CodeGen/GlobalMerge.cpp b/llvm/lib/CodeGen/GlobalMerge.cpp index 4941d5b01ae0f36101158c2613b5fbf7412d9e54..545ee1741834a113913d3ccc719d475d28f9fe6a 100644 --- a/llvm/lib/CodeGen/GlobalMerge.cpp +++ b/llvm/lib/CodeGen/GlobalMerge.cpp @@ -309,10 +309,9 @@ bool GlobalMergeImpl::doMerge(SmallVectorImpl<GlobalVariable *> &Globals, for (size_t GI = 0, GE = Globals.size(); GI != GE; ++GI) { GlobalVariable *GV = Globals[GI]; - // Reset the encountered sets for this global... - std::fill(EncounteredUGS.begin(), EncounteredUGS.end(), 0); - // ...and grow it in case we created new sets for the previous global. - EncounteredUGS.resize(UsedGlobalSets.size()); + // Reset the encountered sets for this global and grow it in case we created + // new sets for the previous global. + EncounteredUGS.assign(UsedGlobalSets.size(), 0); // We might need to create a set that only consists of the current global. // Keep track of its index into UsedGlobalSets. diff --git a/llvm/lib/CodeGen/HardwareLoops.cpp b/llvm/lib/CodeGen/HardwareLoops.cpp index c536ec9f79d62527b82786ebb4d93eb3f75cf808..cc5aad14e1b56f721de75ff1b82603c868638b24 100644 --- a/llvm/lib/CodeGen/HardwareLoops.cpp +++ b/llvm/lib/CodeGen/HardwareLoops.cpp @@ -580,7 +580,7 @@ PHINode* HardwareLoop::InsertPHICounter(Value *NumElts, Value *EltsRem) { BasicBlock *Preheader = L->getLoopPreheader(); BasicBlock *Header = L->getHeader(); BasicBlock *Latch = ExitBranch->getParent(); - IRBuilder<> Builder(Header->getFirstNonPHI()); + IRBuilder<> Builder(Header, Header->getFirstNonPHIIt()); PHINode *Index = Builder.CreatePHI(NumElts->getType(), 2); Index->addIncoming(NumElts, Preheader); Index->addIncoming(EltsRem, Latch); diff --git a/llvm/lib/CodeGen/IndirectBrExpandPass.cpp b/llvm/lib/CodeGen/IndirectBrExpandPass.cpp index f7b931a3bdac2dd4e02a79b8995ba4345964a387..13f595bef8eeb898a675d2535858e788e3a05aeb 100644 --- a/llvm/lib/CodeGen/IndirectBrExpandPass.cpp +++ b/llvm/lib/CodeGen/IndirectBrExpandPass.cpp @@ -113,7 +113,7 @@ bool runImpl(Function &F, const TargetLowering *TLI, DomTreeUpdater *DTU) { // Handle the degenerate case of no successors by replacing the indirectbr // with unreachable as there is no successor available. if (IBr->getNumSuccessors() == 0) { - (void)new UnreachableInst(F.getContext(), IBr); + (void)new UnreachableInst(F.getContext(), IBr->getIterator()); IBr->eraseFromParent(); continue; } @@ -183,7 +183,7 @@ bool runImpl(Function &F, const TargetLowering *TLI, DomTreeUpdater *DTU) { for (BasicBlock *SuccBB : IBr->successors()) Updates.push_back({DominatorTree::Delete, IBr->getParent(), SuccBB}); } - (void)new UnreachableInst(F.getContext(), IBr); + (void)new UnreachableInst(F.getContext(), IBr->getIterator()); IBr->eraseFromParent(); } if (DTU) { @@ -207,9 +207,10 @@ bool runImpl(Function &F, const TargetLowering *TLI, DomTreeUpdater *DTU) { } auto GetSwitchValue = [CommonITy](IndirectBrInst *IBr) { - return CastInst::CreatePointerCast( - IBr->getAddress(), CommonITy, - Twine(IBr->getAddress()->getName()) + ".switch_cast", IBr); + return CastInst::CreatePointerCast(IBr->getAddress(), CommonITy, + Twine(IBr->getAddress()->getName()) + + ".switch_cast", + IBr->getIterator()); }; SmallVector<DominatorTree::UpdateType, 8> Updates; @@ -243,7 +244,7 @@ bool runImpl(Function &F, const TargetLowering *TLI, DomTreeUpdater *DTU) { Updates.reserve(IndirectBrs.size() + 2 * IndirectBrSuccs.size()); for (auto *IBr : IndirectBrs) { SwitchPN->addIncoming(GetSwitchValue(IBr), IBr->getParent()); - BranchInst::Create(SwitchBB, IBr); + BranchInst::Create(SwitchBB, IBr->getIterator()); if (DTU) { Updates.push_back({DominatorTree::Insert, IBr->getParent(), SwitchBB}); for (BasicBlock *SuccBB : IBr->successors()) diff --git a/llvm/lib/CodeGen/InterleavedAccessPass.cpp b/llvm/lib/CodeGen/InterleavedAccessPass.cpp index 2a0daf404c97830f36a83fe6e54b30a5384ce480..438ac1c3cc6e2c4bcedbd9b4d0c4c0389fdc1145 100644 --- a/llvm/lib/CodeGen/InterleavedAccessPass.cpp +++ b/llvm/lib/CodeGen/InterleavedAccessPass.cpp @@ -388,14 +388,15 @@ bool InterleavedAccessImpl::replaceBinOpShuffles( return Idx < (int)cast<FixedVectorType>(BIOp0Ty)->getNumElements(); })); + BasicBlock::iterator insertPos = SVI->getIterator(); auto *NewSVI1 = new ShuffleVectorInst(BI->getOperand(0), PoisonValue::get(BIOp0Ty), - Mask, SVI->getName(), SVI); + Mask, SVI->getName(), insertPos); auto *NewSVI2 = new ShuffleVectorInst( BI->getOperand(1), PoisonValue::get(BI->getOperand(1)->getType()), Mask, - SVI->getName(), SVI); + SVI->getName(), insertPos); BinaryOperator *NewBI = BinaryOperator::CreateWithCopiedFlags( - BI->getOpcode(), NewSVI1, NewSVI2, BI, BI->getName(), SVI); + BI->getOpcode(), NewSVI1, NewSVI2, BI, BI->getName(), insertPos); SVI->replaceAllUsesWith(NewBI); LLVM_DEBUG(dbgs() << " Replaced: " << *BI << "\n And : " << *SVI << "\n With : " << *NewSVI1 << "\n And : " diff --git a/llvm/lib/CodeGen/IntrinsicLowering.cpp b/llvm/lib/CodeGen/IntrinsicLowering.cpp index fe450cba4a33321da7f38e8fc6e711fe860d58a3..45fba4341ad0073c42ab583572885f7a3a6cfe28 100644 --- a/llvm/lib/CodeGen/IntrinsicLowering.cpp +++ b/llvm/lib/CodeGen/IntrinsicLowering.cpp @@ -243,6 +243,11 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) { break; } + case Intrinsic::allow_runtime_check: + case Intrinsic::allow_ubsan_check: + CI->replaceAllUsesWith(ConstantInt::getTrue(CI->getType())); + return; + case Intrinsic::ctpop: CI->replaceAllUsesWith(LowerCTPOP(Context, CI->getArgOperand(0), CI)); break; @@ -472,7 +477,7 @@ bool IntrinsicLowering::LowerToByteSwap(CallInst *CI) { Function *Int = Intrinsic::getDeclaration(M, Intrinsic::bswap, Ty); Value *Op = CI->getArgOperand(0); - Op = CallInst::Create(Int, Op, CI->getName(), CI); + Op = CallInst::Create(Int, Op, CI->getName(), CI->getIterator()); CI->replaceAllUsesWith(Op); CI->eraseFromParent(); diff --git a/llvm/lib/CodeGen/JMCInstrumenter.cpp b/llvm/lib/CodeGen/JMCInstrumenter.cpp index 62a38191887524fb878a30c675dcfa58153886b3..e2aaebedf5a4fd4950e5ca38abd3e3335178fd00 100644 --- a/llvm/lib/CodeGen/JMCInstrumenter.cpp +++ b/llvm/lib/CodeGen/JMCInstrumenter.cpp @@ -227,7 +227,7 @@ bool runImpl(Module &M) { // FIXME: it would be nice to make CI scheduling boundary, although in // practice it does not matter much. auto *CI = CallInst::Create(getCheckFunctionType(Ctx), CheckFunction, - {Flag}, "", &*F.begin()->getFirstInsertionPt()); + {Flag}, "", F.begin()->getFirstInsertionPt()); CI->addParamAttr(0, Attribute::NoUndef); if (UseX86FastCall) { CI->setCallingConv(CallingConv::X86_FastCall); diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp index cfc8c28b99e562d0ed7181386b618d7052e58fe1..481d9e341da3772bd7c92f4786e123b37b24d35c 100644 --- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp @@ -1356,10 +1356,11 @@ InstrRefBasedLDV::findLocationForMemOperand(const MachineInstr &MI) { // from the stack at some point. Happily the memory operand will tell us // the size written to the stack. auto *MemOperand = *MI.memoperands_begin(); - unsigned SizeInBits = MemOperand->getSizeInBits(); + LocationSize SizeInBits = MemOperand->getSizeInBits(); + assert(SizeInBits.hasValue() && "Expected to find a valid size!"); // Find that position in the stack indexes we're tracking. - auto IdxIt = MTracker->StackSlotIdxes.find({SizeInBits, 0}); + auto IdxIt = MTracker->StackSlotIdxes.find({SizeInBits.getValue(), 0}); if (IdxIt == MTracker->StackSlotIdxes.end()) // That index is not tracked. This is suprising, and unlikely to ever // occur, but the safe action is to indicate the variable is optimised out. diff --git a/llvm/lib/CodeGen/LowLevelTypeUtils.cpp b/llvm/lib/CodeGen/LowLevelTypeUtils.cpp index bc2ea3f05b6da6cc0c27b2112f50ea1f5969697a..1602cd99c383c69bdfd2492cb7e797eac0418f11 100644 --- a/llvm/lib/CodeGen/LowLevelTypeUtils.cpp +++ b/llvm/lib/CodeGen/LowLevelTypeUtils.cpp @@ -39,6 +39,9 @@ LLT llvm::getLLTForType(Type &Ty, const DataLayout &DL) { return LLT::scalar(SizeInBits); } + if (Ty.isTokenTy()) + return LLT::token(); + return LLT(); } @@ -48,7 +51,7 @@ MVT llvm::getMVTForLLT(LLT Ty) { return MVT::getVectorVT( MVT::getIntegerVT(Ty.getElementType().getSizeInBits()), - Ty.getNumElements()); + Ty.getElementCount()); } EVT llvm::getApproximateEVTForLLT(LLT Ty, const DataLayout &DL, diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp index 870611248466f5bcc3372842bcaa72feb819f1c4..7bb21655320474a2cea8466379179c53d2134081 100644 --- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp +++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp @@ -213,6 +213,8 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) { .Case("nuw", MIToken::kw_nuw) .Case("nsw", MIToken::kw_nsw) .Case("exact", MIToken::kw_exact) + .Case("nneg", MIToken::kw_nneg) + .Case("disjoint", MIToken::kw_disjoint) .Case("nofpexcept", MIToken::kw_nofpexcept) .Case("unpredictable", MIToken::kw_unpredictable) .Case("debug-location", MIToken::kw_debug_location) diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h index 0f344da521820515c8f32da0e4cafb168ab5c6cd..6617ec68e941508f22f199fffdc797a18e9318cc 100644 --- a/llvm/lib/CodeGen/MIRParser/MILexer.h +++ b/llvm/lib/CodeGen/MIRParser/MILexer.h @@ -74,6 +74,8 @@ struct MIToken { kw_exact, kw_nofpexcept, kw_unpredictable, + kw_nneg, + kw_disjoint, kw_debug_location, kw_debug_instr_number, kw_dbg_instr_ref, diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp index d41fc97cb806037c617b4e2f8885e16538727e54..95924f0566283b0247eb5c62e00b32a73208bf96 100644 --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -1471,7 +1471,9 @@ bool MIParser::parseInstruction(unsigned &OpCode, unsigned &Flags) { Token.is(MIToken::kw_exact) || Token.is(MIToken::kw_nofpexcept) || Token.is(MIToken::kw_noconvergent) || - Token.is(MIToken::kw_unpredictable)) { + Token.is(MIToken::kw_unpredictable) || + Token.is(MIToken::kw_nneg) || + Token.is(MIToken::kw_disjoint)) { // clang-format on // Mine frame and fast math flags if (Token.is(MIToken::kw_frame_setup)) @@ -1504,6 +1506,10 @@ bool MIParser::parseInstruction(unsigned &OpCode, unsigned &Flags) { Flags |= MachineInstr::Unpredictable; if (Token.is(MIToken::kw_noconvergent)) Flags |= MachineInstr::NoConvergent; + if (Token.is(MIToken::kw_nneg)) + Flags |= MachineInstr::NonNeg; + if (Token.is(MIToken::kw_disjoint)) + Flags |= MachineInstr::Disjoint; lex(); } @@ -1919,10 +1925,13 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) { if (Token.range().front() == 's') { auto ScalarSize = APSInt(Token.range().drop_front()).getZExtValue(); - if (!verifyScalarSize(ScalarSize)) - return error("invalid size for scalar type"); - - Ty = LLT::scalar(ScalarSize); + if (ScalarSize) { + if (!verifyScalarSize(ScalarSize)) + return error("invalid size for scalar type"); + Ty = LLT::scalar(ScalarSize); + } else { + Ty = LLT::token(); + } lex(); return false; } else if (Token.range().front() == 'p') { @@ -1980,7 +1989,7 @@ bool MIParser::parseLowLevelType(StringRef::iterator Loc, LLT &Ty) { if (Token.range().front() == 's') { auto ScalarSize = APSInt(Token.range().drop_front()).getZExtValue(); if (!verifyScalarSize(ScalarSize)) - return error("invalid size for scalar type"); + return error("invalid size for scalar element in vector"); Ty = LLT::scalar(ScalarSize); } else if (Token.range().front() == 'p') { const DataLayout &DL = MF.getDataLayout(); diff --git a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp index e09318a486955b396c3577afa3859654c41c895f..4d9a8dc5602ba60256a971a99128104f77b44c51 100644 --- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp @@ -425,11 +425,11 @@ bool MIRParserImpl::initializeCallSiteInfo( Register Reg; if (parseNamedRegisterReference(PFS, Reg, ArgRegPair.Reg.Value, Error)) return error(Error, ArgRegPair.Reg.SourceRange); - CSInfo.emplace_back(Reg, ArgRegPair.ArgNo); + CSInfo.ArgRegPairs.emplace_back(Reg, ArgRegPair.ArgNo); } if (TM.Options.EmitCallSiteInfo) - MF.addCallArgsForwardingRegs(&*CallI, std::move(CSInfo)); + MF.addCallSiteInfo(&*CallI, std::move(CSInfo)); } if (YamlMF.CallSitesInfo.size() && !TM.Options.EmitCallSiteInfo) diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp index 4ed44d1c06f48c332d7a24d38d9b18c8faf51d04..bbc6d39d17fc49a485f1ce1bcafea34ed970f35f 100644 --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -540,7 +540,7 @@ void MIRPrinter::convertCallSiteObjects(yaml::MachineFunction &YMF, std::distance(CallI->getParent()->instr_begin(), CallI); YmlCS.CallLocation = CallLocation; // Construct call arguments and theirs forwarding register info. - for (auto ArgReg : CSInfo.second) { + for (auto ArgReg : CSInfo.second.ArgRegPairs) { yaml::CallSiteInfo::ArgRegPair YmlArgReg; YmlArgReg.ArgNo = ArgReg.ArgNo; printRegMIR(ArgReg.Reg, YmlArgReg.Reg, TRI); @@ -806,6 +806,10 @@ void MIPrinter::print(const MachineInstr &MI) { OS << "unpredictable "; if (MI.getFlag(MachineInstr::NoConvergent)) OS << "noconvergent "; + if (MI.getFlag(MachineInstr::NonNeg)) + OS << "nneg "; + if (MI.getFlag(MachineInstr::Disjoint)) + OS << "disjoint "; OS << TII->getName(MI.getOpcode()); if (I < E) @@ -982,7 +986,7 @@ void MIRFormatter::printIRValue(raw_ostream &OS, const Value &V, } void llvm::printMIR(raw_ostream &OS, const Module &M) { - // RemoveDIs: as there's no textual form for DPValues yet, print debug-info + // RemoveDIs: as there's no textual form for DbgRecords yet, print debug-info // in dbg.value format. bool IsNewDbgInfoFormat = M.IsNewDbgInfoFormat; if (IsNewDbgInfoFormat) @@ -996,7 +1000,7 @@ void llvm::printMIR(raw_ostream &OS, const Module &M) { } void llvm::printMIR(raw_ostream &OS, const MachineFunction &MF) { - // RemoveDIs: as there's no textual form for DPValues yet, print debug-info + // RemoveDIs: as there's no textual form for DbgRecords yet, print debug-info // in dbg.value format. bool IsNewDbgInfoFormat = MF.getFunction().IsNewDbgInfoFormat; if (IsNewDbgInfoFormat) diff --git a/llvm/lib/CodeGen/MIRVRegNamerUtils.cpp b/llvm/lib/CodeGen/MIRVRegNamerUtils.cpp index 812d57984e6cae4e7d22f7f5281e92616c309e45..ccfc4565d3a9bc0ba27c2b2f38534d89f7b2d327 100644 --- a/llvm/lib/CodeGen/MIRVRegNamerUtils.cpp +++ b/llvm/lib/CodeGen/MIRVRegNamerUtils.cpp @@ -123,7 +123,7 @@ std::string VRegRenamer::getInstructionOpcodeHash(MachineInstr &MI) { llvm::transform(MI.uses(), std::back_inserter(MIOperands), GetHashableMO); for (const auto *Op : MI.memoperands()) { - MIOperands.push_back((unsigned)Op->getSize()); + MIOperands.push_back((unsigned)Op->getSize().getValue()); MIOperands.push_back((unsigned)Op->getFlags()); MIOperands.push_back((unsigned)Op->getOffset()); MIOperands.push_back((unsigned)Op->getSuccessOrdering()); diff --git a/llvm/lib/CodeGen/MachineCombiner.cpp b/llvm/lib/CodeGen/MachineCombiner.cpp index c65937935ed82004b6aeb6c23caa430367254ef5..a4c87a7678bd8d2e715d0d18c8ba218652e15ae1 100644 --- a/llvm/lib/CodeGen/MachineCombiner.cpp +++ b/llvm/lib/CodeGen/MachineCombiner.cpp @@ -155,9 +155,6 @@ MachineCombiner::getOperandDef(const MachineOperand &MO) { // We need a virtual register definition. if (MO.isReg() && MO.getReg().isVirtual()) DefInstr = MRI->getUniqueVRegDef(MO.getReg()); - // PHI's have no depth etc. - if (DefInstr && DefInstr->isPHI()) - DefInstr = nullptr; return DefInstr; } diff --git a/llvm/lib/CodeGen/MachineCopyPropagation.cpp b/llvm/lib/CodeGen/MachineCopyPropagation.cpp index 9a0ab300b21b7acf68640dc438a0077d6858f20d..8dc6781fcb018f1ff01ef32a5b64abd0c065345a 100644 --- a/llvm/lib/CodeGen/MachineCopyPropagation.cpp +++ b/llvm/lib/CodeGen/MachineCopyPropagation.cpp @@ -411,6 +411,7 @@ private: typedef enum { DebugUse = false, RegularUse = true } DebugType; void ReadRegister(MCRegister Reg, MachineInstr &Reader, DebugType DT); + void readSuccessorLiveIns(const MachineBasicBlock &MBB); void ForwardCopyPropagateBlock(MachineBasicBlock &MBB); void BackwardCopyPropagateBlock(MachineBasicBlock &MBB); void EliminateSpillageCopies(MachineBasicBlock &MBB); @@ -463,6 +464,22 @@ void MachineCopyPropagation::ReadRegister(MCRegister Reg, MachineInstr &Reader, } } +void MachineCopyPropagation::readSuccessorLiveIns( + const MachineBasicBlock &MBB) { + if (MaybeDeadCopies.empty()) + return; + + // If a copy result is livein to a successor, it is not dead. + for (const MachineBasicBlock *Succ : MBB.successors()) { + for (const auto &LI : Succ->liveins()) { + for (MCRegUnit Unit : TRI->regunits(LI.PhysReg)) { + if (MachineInstr *Copy = Tracker.findCopyForUnit(Unit, *TRI)) + MaybeDeadCopies.remove(Copy); + } + } + } +} + /// Return true if \p PreviousCopy did copy register \p Src to register \p Def. /// This fact may have been obscured by sub register usage or may not be true at /// all even though Src and Def are subregisters of the registers used in @@ -640,7 +657,7 @@ bool MachineCopyPropagation::hasImplicitOverlap(const MachineInstr &MI, /// The umull instruction is unpredictable unless RdHi and RdLo are different. bool MachineCopyPropagation::hasOverlappingMultipleDef( const MachineInstr &MI, const MachineOperand &MODef, Register Def) { - for (const MachineOperand &MIDef : MI.defs()) { + for (const MachineOperand &MIDef : MI.all_defs()) { if ((&MIDef != &MODef) && MIDef.isReg() && TRI->regsOverlap(Def, MIDef.getReg())) return true; @@ -914,10 +931,17 @@ void MachineCopyPropagation::ForwardCopyPropagateBlock(MachineBasicBlock &MBB) { Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr); } - // If MBB doesn't have successors, delete the copies whose defs are not used. - // If MBB does have successors, then conservative assume the defs are live-out - // since we don't want to trust live-in lists. - if (MBB.succ_empty()) { + bool TracksLiveness = MRI->tracksLiveness(); + + // If liveness is tracked, we can use the live-in lists to know which + // copies aren't dead. + if (TracksLiveness) + readSuccessorLiveIns(MBB); + + // If MBB doesn't have succesor, delete copies whose defs are not used. + // If MBB does have successors, we can only delete copies if we are able to + // use liveness information from successors to confirm they are really dead. + if (MBB.succ_empty() || TracksLiveness) { for (MachineInstr *MaybeDead : MaybeDeadCopies) { LLVM_DEBUG(dbgs() << "MCP: Removing copy due to no live-out succ: "; MaybeDead->dump()); diff --git a/llvm/lib/CodeGen/MachineFrameInfo.cpp b/llvm/lib/CodeGen/MachineFrameInfo.cpp index 280d3a6a41edc9520ac25a193460c7229838852d..853de4c88caeb7981dfa584a170c49b40b6af8a4 100644 --- a/llvm/lib/CodeGen/MachineFrameInfo.cpp +++ b/llvm/lib/CodeGen/MachineFrameInfo.cpp @@ -184,7 +184,8 @@ uint64_t MachineFrameInfo::estimateStackSize(const MachineFunction &MF) const { return alignTo(Offset, StackAlign); } -void MachineFrameInfo::computeMaxCallFrameSize(const MachineFunction &MF) { +void MachineFrameInfo::computeMaxCallFrameSize( + MachineFunction &MF, std::vector<MachineBasicBlock::iterator> *FrameSDOps) { const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); unsigned FrameSetupOpcode = TII.getCallFrameSetupOpcode(); unsigned FrameDestroyOpcode = TII.getCallFrameDestroyOpcode(); @@ -192,18 +193,14 @@ void MachineFrameInfo::computeMaxCallFrameSize(const MachineFunction &MF) { "Can only compute MaxCallFrameSize if Setup/Destroy opcode are known"); MaxCallFrameSize = 0; - for (const MachineBasicBlock &MBB : MF) { - for (const MachineInstr &MI : MBB) { + for (MachineBasicBlock &MBB : MF) { + for (MachineInstr &MI : MBB) { unsigned Opcode = MI.getOpcode(); if (Opcode == FrameSetupOpcode || Opcode == FrameDestroyOpcode) { unsigned Size = TII.getFrameSize(MI); MaxCallFrameSize = std::max(MaxCallFrameSize, Size); - AdjustsStack = true; - } else if (MI.isInlineAsm()) { - // Some inline asm's need a stack frame, as indicated by operand 1. - unsigned ExtraInfo = MI.getOperand(InlineAsm::MIOp_ExtraInfo).getImm(); - if (ExtraInfo & InlineAsm::Extra_IsAlignStack) - AdjustsStack = true; + if (FrameSDOps != nullptr) + FrameSDOps->push_back(&MI); } } } diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp index 323f1a6a1b2bd737d0d76dbb84dbad2920077958..ad532149926670949f09d213f56c42e5419c9175 100644 --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -484,13 +484,17 @@ void MachineFunction::deleteMachineBasicBlock(MachineBasicBlock *MBB) { } MachineMemOperand *MachineFunction::getMachineMemOperand( - MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, uint64_t s, - Align base_alignment, const AAMDNodes &AAInfo, const MDNode *Ranges, + MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LocationSize Size, + Align BaseAlignment, const AAMDNodes &AAInfo, const MDNode *Ranges, SyncScope::ID SSID, AtomicOrdering Ordering, AtomicOrdering FailureOrdering) { + assert((!Size.hasValue() || + Size.getValue().getKnownMinValue() != ~UINT64_C(0)) && + "Unexpected an unknown size to be represented using " + "LocationSize::beforeOrAfter()"); return new (Allocator) - MachineMemOperand(PtrInfo, f, s, base_alignment, AAInfo, Ranges, - SSID, Ordering, FailureOrdering); + MachineMemOperand(PtrInfo, F, Size, BaseAlignment, AAInfo, Ranges, SSID, + Ordering, FailureOrdering); } MachineMemOperand *MachineFunction::getMachineMemOperand( @@ -503,8 +507,14 @@ MachineMemOperand *MachineFunction::getMachineMemOperand( Ordering, FailureOrdering); } -MachineMemOperand *MachineFunction::getMachineMemOperand( - const MachineMemOperand *MMO, const MachinePointerInfo &PtrInfo, uint64_t Size) { +MachineMemOperand * +MachineFunction::getMachineMemOperand(const MachineMemOperand *MMO, + const MachinePointerInfo &PtrInfo, + LocationSize Size) { + assert((!Size.hasValue() || + Size.getValue().getKnownMinValue() != ~UINT64_C(0)) && + "Unexpected an unknown size to be represented using " + "LocationSize::beforeOrAfter()"); return new (Allocator) MachineMemOperand(PtrInfo, MMO->getFlags(), Size, MMO->getBaseAlign(), AAMDNodes(), nullptr, MMO->getSyncScopeID(), diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp index 6654e1d6ceceea5b24cbfa6363f3c5fe39430bc0..83604003a038bd78da3497b08f240da15f0f72f6 100644 --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -39,6 +39,7 @@ #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Function.h" #include "llvm/IR/InlineAsm.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" @@ -553,6 +554,22 @@ uint32_t MachineInstr::copyFlagsFromInstruction(const Instruction &I) { MIFlags |= MachineInstr::MIFlag::NoSWrap; if (OB->hasNoUnsignedWrap()) MIFlags |= MachineInstr::MIFlag::NoUWrap; + } else if (const TruncInst *TI = dyn_cast<TruncInst>(&I)) { + if (TI->hasNoSignedWrap()) + MIFlags |= MachineInstr::MIFlag::NoSWrap; + if (TI->hasNoUnsignedWrap()) + MIFlags |= MachineInstr::MIFlag::NoUWrap; + } + + // Copy the nonneg flag. + if (const PossiblyNonNegInst *PNI = dyn_cast<PossiblyNonNegInst>(&I)) { + if (PNI->hasNonNeg()) + MIFlags |= MachineInstr::MIFlag::NonNeg; + // Copy the disjoint flag. + } else if (const PossiblyDisjointInst *PD = + dyn_cast<PossiblyDisjointInst>(&I)) { + if (PD->isDisjoint()) + MIFlags |= MachineInstr::MIFlag::Disjoint; } // Copy the exact flag. @@ -1302,10 +1319,11 @@ static bool MemOperandsHaveAlias(const MachineFrameInfo &MFI, AAResults *AA, int64_t OffsetB = MMOb->getOffset(); int64_t MinOffset = std::min(OffsetA, OffsetB); - uint64_t WidthA = MMOa->getSize(); - uint64_t WidthB = MMOb->getSize(); - bool KnownWidthA = WidthA != MemoryLocation::UnknownSize; - bool KnownWidthB = WidthB != MemoryLocation::UnknownSize; + LocationSize WidthA = MMOa->getSize(); + LocationSize WidthB = MMOb->getSize(); + bool KnownWidthA = WidthA.hasValue(); + bool KnownWidthB = WidthB.hasValue(); + bool BothMMONonScalable = !WidthA.isScalable() && !WidthB.isScalable(); const Value *ValA = MMOa->getValue(); const Value *ValB = MMOb->getValue(); @@ -1321,11 +1339,13 @@ static bool MemOperandsHaveAlias(const MachineFrameInfo &MFI, AAResults *AA, SameVal = true; } - if (SameVal) { + if (SameVal && BothMMONonScalable) { if (!KnownWidthA || !KnownWidthB) return true; int64_t MaxOffset = std::max(OffsetA, OffsetB); - int64_t LowWidth = (MinOffset == OffsetA) ? WidthA : WidthB; + int64_t LowWidth = (MinOffset == OffsetA) + ? WidthA.getValue().getKnownMinValue() + : WidthB.getValue().getKnownMinValue(); return (MinOffset + LowWidth > MaxOffset); } @@ -1338,15 +1358,29 @@ static bool MemOperandsHaveAlias(const MachineFrameInfo &MFI, AAResults *AA, assert((OffsetA >= 0) && "Negative MachineMemOperand offset"); assert((OffsetB >= 0) && "Negative MachineMemOperand offset"); + // If Scalable Location Size has non-zero offset, Width + Offset does not work + // at the moment + if ((WidthA.isScalable() && OffsetA > 0) || + (WidthB.isScalable() && OffsetB > 0)) + return true; + int64_t OverlapA = - KnownWidthA ? WidthA + OffsetA - MinOffset : MemoryLocation::UnknownSize; + KnownWidthA ? WidthA.getValue().getKnownMinValue() + OffsetA - MinOffset + : MemoryLocation::UnknownSize; int64_t OverlapB = - KnownWidthB ? WidthB + OffsetB - MinOffset : MemoryLocation::UnknownSize; + KnownWidthB ? WidthB.getValue().getKnownMinValue() + OffsetB - MinOffset + : MemoryLocation::UnknownSize; + + LocationSize LocA = (WidthA.isScalable() || !KnownWidthA) + ? WidthA + : LocationSize::precise(OverlapA); + LocationSize LocB = (WidthB.isScalable() || !KnownWidthB) + ? WidthB + : LocationSize::precise(OverlapB); return !AA->isNoAlias( - MemoryLocation(ValA, OverlapA, UseTBAA ? MMOa->getAAInfo() : AAMDNodes()), - MemoryLocation(ValB, OverlapB, - UseTBAA ? MMOb->getAAInfo() : AAMDNodes())); + MemoryLocation(ValA, LocA, UseTBAA ? MMOa->getAAInfo() : AAMDNodes()), + MemoryLocation(ValB, LocB, UseTBAA ? MMOb->getAAInfo() : AAMDNodes())); } bool MachineInstr::mayAlias(AAResults *AA, const MachineInstr &Other, @@ -1689,6 +1723,10 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST, OS << "nofpexcept "; if (getFlag(MachineInstr::NoMerge)) OS << "nomerge "; + if (getFlag(MachineInstr::NonNeg)) + OS << "nneg "; + if (getFlag(MachineInstr::Disjoint)) + OS << "disjoint "; // Print the opcode name. if (TII) @@ -2357,15 +2395,16 @@ using MMOList = SmallVector<const MachineMemOperand *, 2>; static LocationSize getSpillSlotSize(const MMOList &Accesses, const MachineFrameInfo &MFI) { uint64_t Size = 0; - for (const auto *A : Accesses) + for (const auto *A : Accesses) { if (MFI.isSpillSlotObjectIndex( cast<FixedStackPseudoSourceValue>(A->getPseudoValue()) ->getFrameIndex())) { - uint64_t S = A->getSize(); - if (S == ~UINT64_C(0)) + LocationSize S = A->getSize(); + if (!S.hasValue()) return LocationSize::beforeOrAfterPointer(); - Size += S; + Size += S.getValue(); } + } return Size; } @@ -2374,10 +2413,8 @@ MachineInstr::getSpillSize(const TargetInstrInfo *TII) const { int FI; if (TII->isStoreToStackSlotPostFE(*this, FI)) { const MachineFrameInfo &MFI = getMF()->getFrameInfo(); - if (MFI.isSpillSlotObjectIndex(FI)) { - uint64_t Size = (*memoperands_begin())->getSize(); - return Size == ~UINT64_C(0) ? LocationSize::beforeOrAfterPointer() : Size; - } + if (MFI.isSpillSlotObjectIndex(FI)) + return (*memoperands_begin())->getSize(); } return std::nullopt; } @@ -2395,10 +2432,8 @@ MachineInstr::getRestoreSize(const TargetInstrInfo *TII) const { int FI; if (TII->isLoadFromStackSlotPostFE(*this, FI)) { const MachineFrameInfo &MFI = getMF()->getFrameInfo(); - if (MFI.isSpillSlotObjectIndex(FI)) { - uint64_t Size = (*memoperands_begin())->getSize(); - return Size == ~UINT64_C(0) ? LocationSize::beforeOrAfterPointer() : Size; - } + if (MFI.isSpillSlotObjectIndex(FI)) + return (*memoperands_begin())->getSize(); } return std::nullopt; } diff --git a/llvm/lib/CodeGen/MachineLoopInfo.cpp b/llvm/lib/CodeGen/MachineLoopInfo.cpp index 1492c8c366fb411959633aebd918cc0b99e0820d..1019c53e57c6fbf25beaf852f440a29714d76c25 100644 --- a/llvm/lib/CodeGen/MachineLoopInfo.cpp +++ b/llvm/lib/CodeGen/MachineLoopInfo.cpp @@ -198,6 +198,23 @@ MDNode *MachineLoop::getLoopID() const { return LoopID; } +bool MachineLoop::isLoopInvariantImplicitPhysReg(Register Reg) const { + MachineFunction *MF = getHeader()->getParent(); + MachineRegisterInfo *MRI = &MF->getRegInfo(); + + if (MRI->isConstantPhysReg(Reg)) + return true; + + if (!MF->getSubtarget() + .getRegisterInfo() + ->shouldAnalyzePhysregInMachineLoopInfo(Reg)) + return false; + + return !llvm::any_of( + MRI->def_instructions(Reg), + [this](const MachineInstr &MI) { return this->contains(&MI); }); +} + bool MachineLoop::isLoopInvariant(MachineInstr &I, const Register ExcludeReg) const { MachineFunction *MF = I.getParent()->getParent(); @@ -226,7 +243,7 @@ bool MachineLoop::isLoopInvariant(MachineInstr &I, // it could get allocated to something with a def during allocation. // However, if the physreg is known to always be caller saved/restored // then this use is safe to hoist. - if (!MRI->isConstantPhysReg(Reg) && + if (!isLoopInvariantImplicitPhysReg(Reg) && !(TRI->isCallerPreservedPhysReg(Reg.asMCReg(), *I.getMF())) && !TII->isIgnorableUse(MO)) return false; diff --git a/llvm/lib/CodeGen/MachineOperand.cpp b/llvm/lib/CodeGen/MachineOperand.cpp index c7c0a1c20d57f4fa82ec1a2aed4afe69f25b31f5..ace05902d5df79eb450ca025a6b465eef3b8db97 100644 --- a/llvm/lib/CodeGen/MachineOperand.cpp +++ b/llvm/lib/CodeGen/MachineOperand.cpp @@ -1101,24 +1101,27 @@ MachineMemOperand::MachineMemOperand(MachinePointerInfo ptrinfo, Flags f, assert(getFailureOrdering() == FailureOrdering && "Value truncated"); } -MachineMemOperand::MachineMemOperand(MachinePointerInfo ptrinfo, Flags f, - uint64_t s, Align a, +MachineMemOperand::MachineMemOperand(MachinePointerInfo ptrinfo, Flags F, + LocationSize TS, Align BaseAlignment, const AAMDNodes &AAInfo, const MDNode *Ranges, SyncScope::ID SSID, AtomicOrdering Ordering, AtomicOrdering FailureOrdering) - : MachineMemOperand(ptrinfo, f, - s == ~UINT64_C(0) ? LLT() : LLT::scalar(8 * s), a, - AAInfo, Ranges, SSID, Ordering, FailureOrdering) {} + : MachineMemOperand( + ptrinfo, F, + !TS.hasValue() ? LLT() + : TS.isScalable() + ? LLT::scalable_vector(1, 8 * TS.getValue().getKnownMinValue()) + : LLT::scalar(8 * TS.getValue().getKnownMinValue()), + BaseAlignment, AAInfo, Ranges, SSID, Ordering, FailureOrdering) {} void MachineMemOperand::refineAlignment(const MachineMemOperand *MMO) { // The Value and Offset may differ due to CSE. But the flags and size // should be the same. assert(MMO->getFlags() == getFlags() && "Flags mismatch!"); - assert((MMO->getSize() == ~UINT64_C(0) || getSize() == ~UINT64_C(0) || + assert((!MMO->getSize().hasValue() || !getSize().hasValue() || MMO->getSize() == getSize()) && "Size mismatch!"); - if (MMO->getBaseAlign() >= getBaseAlign()) { // Update the alignment value. BaseAlign = MMO->getBaseAlign(); @@ -1240,7 +1243,8 @@ void MachineMemOperand::print(raw_ostream &OS, ModuleSlotTracker &MST, << "unknown-address"; } MachineOperand::printOperandOffset(OS, getOffset()); - if (getSize() > 0 && getAlign() != getSize()) + if (!getSize().hasValue() || + getAlign() != getSize().getValue().getKnownMinValue()) OS << ", align " << getAlign().value(); if (getAlign() != getBaseAlign()) OS << ", basealign " << getBaseAlign().value(); diff --git a/llvm/lib/CodeGen/MachinePipeliner.cpp b/llvm/lib/CodeGen/MachinePipeliner.cpp index d8cb6816883394d3bf183dff2af97fb68a7024ab..eb42a78603d4079ccb48df5422c31c52f48e347a 100644 --- a/llvm/lib/CodeGen/MachinePipeliner.cpp +++ b/llvm/lib/CodeGen/MachinePipeliner.cpp @@ -2732,19 +2732,20 @@ bool SwingSchedulerDAG::isLoopCarriedDep(SUnit *Source, const SDep &Dep, if (!LoopDefS || !TII->getIncrementValue(*LoopDefS, D)) return true; - uint64_t AccessSizeS = (*SI->memoperands_begin())->getSize(); - uint64_t AccessSizeD = (*DI->memoperands_begin())->getSize(); + LocationSize AccessSizeS = (*SI->memoperands_begin())->getSize(); + LocationSize AccessSizeD = (*DI->memoperands_begin())->getSize(); // This is the main test, which checks the offset values and the loop // increment value to determine if the accesses may be loop carried. - if (AccessSizeS == MemoryLocation::UnknownSize || - AccessSizeD == MemoryLocation::UnknownSize) + if (!AccessSizeS.hasValue() || !AccessSizeD.hasValue()) return true; - if (DeltaS != DeltaD || DeltaS < AccessSizeS || DeltaD < AccessSizeD) + if (DeltaS != DeltaD || DeltaS < AccessSizeS.getValue() || + DeltaD < AccessSizeD.getValue()) return true; - return (OffsetS + (int64_t)AccessSizeS < OffsetD + (int64_t)AccessSizeD); + return (OffsetS + (int64_t)AccessSizeS.getValue() < + OffsetD + (int64_t)AccessSizeD.getValue()); } void SwingSchedulerDAG::postProcessDAG() { diff --git a/llvm/lib/CodeGen/MachineScheduler.cpp b/llvm/lib/CodeGen/MachineScheduler.cpp index 0d5bf32993878118a84a9aa94a49fdee34276cbb..203bdffc49ae18181999e5fbd5bac261a13d3749 100644 --- a/llvm/lib/CodeGen/MachineScheduler.cpp +++ b/llvm/lib/CodeGen/MachineScheduler.cpp @@ -85,6 +85,7 @@ namespace MISchedPostRASched { enum Direction { TopDown, BottomUp, + Bidirectional, }; } // end namespace MISchedPostRASched cl::opt<MISchedPostRASched::Direction> PostRADirection( @@ -93,10 +94,13 @@ cl::opt<MISchedPostRASched::Direction> PostRADirection( // Default to top-down because it was implemented first and existing targets // expect that behavior by default. cl::init(MISchedPostRASched::TopDown), - cl::values(clEnumValN(MISchedPostRASched::TopDown, "topdown", - "Force top-down post reg-alloc list scheduling"), - clEnumValN(MISchedPostRASched::BottomUp, "bottomup", - "Force bottom-up post reg-alloc list scheduling"))); + cl::values( + clEnumValN(MISchedPostRASched::TopDown, "topdown", + "Force top-down post reg-alloc list scheduling"), + clEnumValN(MISchedPostRASched::BottomUp, "bottomup", + "Force bottom-up post reg-alloc list scheduling"), + clEnumValN(MISchedPostRASched::Bidirectional, "bidirectional", + "Force bidirectional post reg-alloc list scheduling"))); cl::opt<bool> DumpCriticalPathLength("misched-dcpl", cl::Hidden, cl::desc("Print critical path length to stdout")); @@ -500,8 +504,10 @@ bool PostMachineScheduler::runOnMachineFunction(MachineFunction &mf) { ScheduleDAGMI::DumpDirection D; if (PostRADirection == MISchedPostRASched::TopDown) D = ScheduleDAGMI::DumpDirection::TopDown; - else + else if (PostRADirection == MISchedPostRASched::BottomUp) D = ScheduleDAGMI::DumpDirection::BottomUp; + else + D = ScheduleDAGMI::DumpDirection::Bidirectional; Scheduler->setDumpDirection(D); scheduleRegions(*Scheduler, true); @@ -3257,14 +3263,10 @@ void GenericScheduler::initialize(ScheduleDAGMI *dag) { // are disabled, then these HazardRecs will be disabled. const InstrItineraryData *Itin = SchedModel->getInstrItineraries(); if (!Top.HazardRec) { - Top.HazardRec = - DAG->MF.getSubtarget().getInstrInfo()->CreateTargetMIHazardRecognizer( - Itin, DAG); + Top.HazardRec = DAG->TII->CreateTargetMIHazardRecognizer(Itin, DAG); } if (!Bot.HazardRec) { - Bot.HazardRec = - DAG->MF.getSubtarget().getInstrInfo()->CreateTargetMIHazardRecognizer( - Itin, DAG); + Bot.HazardRec = DAG->TII->CreateTargetMIHazardRecognizer(Itin, DAG); } TopCand.SU = nullptr; BotCand.SU = nullptr; @@ -3715,7 +3717,7 @@ SUnit *GenericScheduler::pickNodeBidirectional(bool &IsTopNode) { TCand.reset(CandPolicy()); pickNodeFromQueue(Top, TopPolicy, DAG->getTopRPTracker(), TCand); assert(TCand.SU == TopCand.SU && - "Last pick result should correspond to re-picking right now"); + "Last pick result should correspond to re-picking right now"); } #endif } @@ -3871,14 +3873,10 @@ void PostGenericScheduler::initialize(ScheduleDAGMI *Dag) { // or are disabled, then these HazardRecs will be disabled. const InstrItineraryData *Itin = SchedModel->getInstrItineraries(); if (!Top.HazardRec) { - Top.HazardRec = - DAG->MF.getSubtarget().getInstrInfo()->CreateTargetMIHazardRecognizer( - Itin, DAG); + Top.HazardRec = DAG->TII->CreateTargetMIHazardRecognizer(Itin, DAG); } if (!Bot.HazardRec) { - Bot.HazardRec = - DAG->MF.getSubtarget().getInstrInfo()->CreateTargetMIHazardRecognizer( - Itin, DAG); + Bot.HazardRec = DAG->TII->CreateTargetMIHazardRecognizer(Itin, DAG); } } @@ -3891,6 +3889,9 @@ void PostGenericScheduler::initPolicy(MachineBasicBlock::iterator Begin, } else if (PostRADirection == MISchedPostRASched::BottomUp) { RegionPolicy.OnlyTopDown = false; RegionPolicy.OnlyBottomUp = true; + } else if (PostRADirection == MISchedPostRASched::Bidirectional) { + RegionPolicy.OnlyBottomUp = false; + RegionPolicy.OnlyTopDown = false; } } @@ -3970,6 +3971,87 @@ void PostGenericScheduler::pickNodeFromQueue(SchedBoundary &Zone, } } +/// Pick the best candidate node from either the top or bottom queue. +SUnit *PostGenericScheduler::pickNodeBidirectional(bool &IsTopNode) { + // FIXME: This is similiar to GenericScheduler::pickNodeBidirectional. Factor + // out common parts. + + // Schedule as far as possible in the direction of no choice. This is most + // efficient, but also provides the best heuristics for CriticalPSets. + if (SUnit *SU = Bot.pickOnlyChoice()) { + IsTopNode = false; + tracePick(Only1, false); + return SU; + } + if (SUnit *SU = Top.pickOnlyChoice()) { + IsTopNode = true; + tracePick(Only1, true); + return SU; + } + // Set the bottom-up policy based on the state of the current bottom zone and + // the instructions outside the zone, including the top zone. + CandPolicy BotPolicy; + setPolicy(BotPolicy, /*IsPostRA=*/true, Bot, &Top); + // Set the top-down policy based on the state of the current top zone and + // the instructions outside the zone, including the bottom zone. + CandPolicy TopPolicy; + setPolicy(TopPolicy, /*IsPostRA=*/true, Top, &Bot); + + // See if BotCand is still valid (because we previously scheduled from Top). + LLVM_DEBUG(dbgs() << "Picking from Bot:\n"); + if (!BotCand.isValid() || BotCand.SU->isScheduled || + BotCand.Policy != BotPolicy) { + BotCand.reset(CandPolicy()); + pickNodeFromQueue(Bot, BotCand); + assert(BotCand.Reason != NoCand && "failed to find the first candidate"); + } else { + LLVM_DEBUG(traceCandidate(BotCand)); +#ifndef NDEBUG + if (VerifyScheduling) { + SchedCandidate TCand; + TCand.reset(CandPolicy()); + pickNodeFromQueue(Bot, BotCand); + assert(TCand.SU == BotCand.SU && + "Last pick result should correspond to re-picking right now"); + } +#endif + } + + // Check if the top Q has a better candidate. + LLVM_DEBUG(dbgs() << "Picking from Top:\n"); + if (!TopCand.isValid() || TopCand.SU->isScheduled || + TopCand.Policy != TopPolicy) { + TopCand.reset(CandPolicy()); + pickNodeFromQueue(Top, TopCand); + assert(TopCand.Reason != NoCand && "failed to find the first candidate"); + } else { + LLVM_DEBUG(traceCandidate(TopCand)); +#ifndef NDEBUG + if (VerifyScheduling) { + SchedCandidate TCand; + TCand.reset(CandPolicy()); + pickNodeFromQueue(Top, TopCand); + assert(TCand.SU == TopCand.SU && + "Last pick result should correspond to re-picking right now"); + } +#endif + } + + // Pick best from BotCand and TopCand. + assert(BotCand.isValid()); + assert(TopCand.isValid()); + SchedCandidate Cand = BotCand; + TopCand.Reason = NoCand; + if (tryCandidate(Cand, TopCand)) { + Cand.setBest(TopCand); + LLVM_DEBUG(traceCandidate(Cand)); + } + + IsTopNode = Cand.AtTop; + tracePick(Cand); + return Cand.SU; +} + /// Pick the next node to schedule. SUnit *PostGenericScheduler::pickNode(bool &IsTopNode) { if (DAG->top() == DAG->bottom()) { @@ -3980,13 +4062,12 @@ SUnit *PostGenericScheduler::pickNode(bool &IsTopNode) { SUnit *SU; do { if (RegionPolicy.OnlyBottomUp) { - assert(!RegionPolicy.OnlyTopDown); SU = Bot.pickOnlyChoice(); if (SU) { tracePick(Only1, true); } else { CandPolicy NoPolicy; - SchedCandidate BotCand(NoPolicy); + BotCand.reset(NoPolicy); // Set the bottom-up policy based on the state of the current bottom // zone and the instructions outside the zone, including the top zone. setPolicy(BotCand.Policy, /*IsPostRA=*/true, Bot, nullptr); @@ -3996,15 +4077,13 @@ SUnit *PostGenericScheduler::pickNode(bool &IsTopNode) { SU = BotCand.SU; } IsTopNode = false; - } else { - - assert(RegionPolicy.OnlyTopDown); + } else if (RegionPolicy.OnlyTopDown) { SU = Top.pickOnlyChoice(); if (SU) { tracePick(Only1, true); } else { CandPolicy NoPolicy; - SchedCandidate TopCand(NoPolicy); + TopCand.reset(NoPolicy); // Set the top-down policy based on the state of the current top zone // and the instructions outside the zone, including the bottom zone. setPolicy(TopCand.Policy, /*IsPostRA=*/true, Top, nullptr); @@ -4014,6 +4093,8 @@ SUnit *PostGenericScheduler::pickNode(bool &IsTopNode) { SU = TopCand.SU; } IsTopNode = true; + } else { + SU = pickNodeBidirectional(IsTopNode); } } while (SU->isScheduled); diff --git a/llvm/lib/CodeGen/MachineStableHash.cpp b/llvm/lib/CodeGen/MachineStableHash.cpp index 1cd90474898e7769e799e894271640318e960b03..5abfbd5981fba801fee9eab82f02178556592cd0 100644 --- a/llvm/lib/CodeGen/MachineStableHash.cpp +++ b/llvm/lib/CodeGen/MachineStableHash.cpp @@ -200,7 +200,7 @@ stable_hash llvm::stableHashValue(const MachineInstr &MI, bool HashVRegs, for (const auto *Op : MI.memoperands()) { if (!HashMemOperands) break; - HashComponents.push_back(static_cast<unsigned>(Op->getSize())); + HashComponents.push_back(static_cast<unsigned>(Op->getSize().getValue())); HashComponents.push_back(static_cast<unsigned>(Op->getFlags())); HashComponents.push_back(static_cast<unsigned>(Op->getOffset())); HashComponents.push_back(static_cast<unsigned>(Op->getSuccessOrdering())); diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp index c2d6dd35e1cb21809412e1151fcc52e1dc243cb3..fd7ea28426470ae487e7c654c31d54e10d7cec99 100644 --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -1195,13 +1195,16 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { const MachineMemOperand &MMO = **MI->memoperands_begin(); if (MI->getOpcode() == TargetOpcode::G_ZEXTLOAD || MI->getOpcode() == TargetOpcode::G_SEXTLOAD) { - if (MMO.getSizeInBits() >= ValTy.getSizeInBits()) + if (TypeSize::isKnownGE(MMO.getSizeInBits().getValue(), + ValTy.getSizeInBits())) report("Generic extload must have a narrower memory type", MI); } else if (MI->getOpcode() == TargetOpcode::G_LOAD) { - if (MMO.getSize() > ValTy.getSizeInBytes()) + if (TypeSize::isKnownGT(MMO.getSize().getValue(), + ValTy.getSizeInBytes())) report("load memory size cannot exceed result size", MI); } else if (MI->getOpcode() == TargetOpcode::G_STORE) { - if (ValTy.getSizeInBytes() < MMO.getSize()) + if (TypeSize::isKnownLT(ValTy.getSizeInBytes(), + MMO.getSize().getValue())) report("store memory size cannot exceed value size", MI); } @@ -1503,7 +1506,8 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { LLT SrcTy = MRI->getType(MI->getOperand(2).getReg()); if ((DstTy.isVector() != SrcTy.isVector()) || - (DstTy.isVector() && DstTy.getNumElements() != SrcTy.getNumElements())) + (DstTy.isVector() && + DstTy.getElementCount() != SrcTy.getElementCount())) report("Generic vector icmp/fcmp must preserve number of lanes", MI); break; @@ -1764,16 +1768,23 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); LLT SrcTy = MRI->getType(MI->getOperand(1).getReg()); - if (!DstTy.isScalableVector()) + if (!DstTy.isScalableVector()) { report("Destination type must be a scalable vector", MI); + break; + } - if (!SrcTy.isScalar()) + if (!SrcTy.isScalar()) { report("Source type must be a scalar", MI); + break; + } - if (DstTy.getScalarType() != SrcTy) - report("Element type of the destination must be the same type as the " - "source type", + if (TypeSize::isKnownGT(DstTy.getElementType().getSizeInBits(), + SrcTy.getSizeInBits())) { + report("Element type of the destination must be the same size or smaller " + "than the source type", MI); + break; + } break; } @@ -1864,6 +1875,17 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { break; } + case TargetOpcode::G_UBSANTRAP: { + const MachineOperand &KindOp = MI->getOperand(0); + if (!MI->getOperand(0).isImm()) { + report("Crash kind must be an immediate", &KindOp, 0); + break; + } + int64_t Kind = MI->getOperand(0).getImm(); + if (!isInt<8>(Kind)) + report("Crash kind must be 8 bit wide", &KindOp, 0); + break; + } case TargetOpcode::G_VECREDUCE_SEQ_FADD: case TargetOpcode::G_VECREDUCE_SEQ_FMUL: { LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); @@ -3694,6 +3716,9 @@ void MachineVerifier::verifyStackFrame() { if (I.getOpcode() == FrameSetupOpcode) { if (BBState.ExitIsSetup) report("FrameSetup is after another FrameSetup", &I); + if (!MRI->isSSA() && !MF->getFrameInfo().adjustsStack()) + report("AdjustsStack not set in presence of a frame pseudo " + "instruction.", &I); BBState.ExitValue -= TII->getFrameTotalSize(I); BBState.ExitIsSetup = true; } @@ -3709,6 +3734,9 @@ void MachineVerifier::verifyStackFrame() { errs() << "FrameDestroy <" << Size << "> is after FrameSetup <" << AbsSPAdj << ">.\n"; } + if (!MRI->isSSA() && !MF->getFrameInfo().adjustsStack()) + report("AdjustsStack not set in presence of a frame pseudo " + "instruction.", &I); BBState.ExitValue += Size; BBState.ExitIsSetup = false; } diff --git a/llvm/lib/CodeGen/ModuloSchedule.cpp b/llvm/lib/CodeGen/ModuloSchedule.cpp index 0bef513342ff123b75863fa242c9a0b555b4b07d..bdae94c4e6f885c69782f46474d81cd180bd7fca 100644 --- a/llvm/lib/CodeGen/ModuloSchedule.cpp +++ b/llvm/lib/CodeGen/ModuloSchedule.cpp @@ -979,8 +979,8 @@ void ModuloScheduleExpander::updateMemOperands(MachineInstr &NewMI, NewMMOs.push_back( MF.getMachineMemOperand(MMO, AdjOffset, MMO->getSize())); } else { - NewMMOs.push_back( - MF.getMachineMemOperand(MMO, 0, MemoryLocation::UnknownSize)); + NewMMOs.push_back(MF.getMachineMemOperand( + MMO, 0, LocationSize::beforeOrAfterPointer())); } } NewMI.setMemRefs(MF, NewMMOs); diff --git a/llvm/lib/CodeGen/NonRelocatableStringpool.cpp b/llvm/lib/CodeGen/NonRelocatableStringpool.cpp index e8391afb8e3f8d9cdb7c420e4b018e096ba7c473..26857c6a40889d1003f8cf2acdc8b3c75102fde2 100644 --- a/llvm/lib/CodeGen/NonRelocatableStringpool.cpp +++ b/llvm/lib/CodeGen/NonRelocatableStringpool.cpp @@ -12,8 +12,6 @@ namespace llvm { DwarfStringPoolEntryRef NonRelocatableStringpool::getEntry(StringRef S) { - if (Translator) - S = Translator(S); auto I = Strings.insert({S, DwarfStringPoolEntry()}); auto &Entry = I.first->second; if (I.second || !Entry.isIndexed()) { @@ -28,9 +26,6 @@ DwarfStringPoolEntryRef NonRelocatableStringpool::getEntry(StringRef S) { StringRef NonRelocatableStringpool::internString(StringRef S) { DwarfStringPoolEntry Entry{nullptr, 0, DwarfStringPoolEntry::NotIndexed}; - if (Translator) - S = Translator(S); - auto InsertResult = Strings.insert({S, Entry}); return InsertResult.first->getKey(); } diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp index 8af17e63e25c75a17cfef42f89bab5618f2c0eb9..eaf96ec5cbde8c5417b7369c1e8dff69820397f0 100644 --- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -228,9 +228,8 @@ bool PEI::runOnMachineFunction(MachineFunction &MF) { FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(MF); ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE(); - // Calculate the MaxCallFrameSize and AdjustsStack variables for the - // function's frame information. Also eliminates call frame pseudo - // instructions. + // Calculate the MaxCallFrameSize value for the function's frame + // information. Also eliminates call frame pseudo instructions. calculateCallFrameInfo(MF); // Determine placement of CSR spill/restore code and prolog/epilog code: @@ -350,17 +349,13 @@ bool PEI::runOnMachineFunction(MachineFunction &MF) { return true; } -/// Calculate the MaxCallFrameSize and AdjustsStack -/// variables for the function's frame information and eliminate call frame -/// pseudo instructions. +/// Calculate the MaxCallFrameSize variable for the function's frame +/// information and eliminate call frame pseudo instructions. void PEI::calculateCallFrameInfo(MachineFunction &MF) { const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); MachineFrameInfo &MFI = MF.getFrameInfo(); - unsigned MaxCallFrameSize = 0; - bool AdjustsStack = MFI.adjustsStack(); - // Get the function call frame set-up and tear-down instruction opcode unsigned FrameSetupOpcode = TII.getCallFrameSetupOpcode(); unsigned FrameDestroyOpcode = TII.getCallFrameDestroyOpcode(); @@ -370,26 +365,15 @@ void PEI::calculateCallFrameInfo(MachineFunction &MF) { if (FrameSetupOpcode == ~0u && FrameDestroyOpcode == ~0u) return; + // (Re-)Compute the MaxCallFrameSize. + [[maybe_unused]] uint32_t MaxCFSIn = + MFI.isMaxCallFrameSizeComputed() ? MFI.getMaxCallFrameSize() : UINT32_MAX; std::vector<MachineBasicBlock::iterator> FrameSDOps; - for (MachineBasicBlock &BB : MF) - for (MachineBasicBlock::iterator I = BB.begin(); I != BB.end(); ++I) - if (TII.isFrameInstr(*I)) { - unsigned Size = TII.getFrameSize(*I); - if (Size > MaxCallFrameSize) MaxCallFrameSize = Size; - AdjustsStack = true; - FrameSDOps.push_back(I); - } else if (I->isInlineAsm()) { - // Some inline asm's need a stack frame, as indicated by operand 1. - unsigned ExtraInfo = I->getOperand(InlineAsm::MIOp_ExtraInfo).getImm(); - if (ExtraInfo & InlineAsm::Extra_IsAlignStack) - AdjustsStack = true; - } - - assert(!MFI.isMaxCallFrameSizeComputed() || - (MFI.getMaxCallFrameSize() >= MaxCallFrameSize && - !(AdjustsStack && !MFI.adjustsStack()))); - MFI.setAdjustsStack(AdjustsStack); - MFI.setMaxCallFrameSize(MaxCallFrameSize); + MFI.computeMaxCallFrameSize(MF, &FrameSDOps); + assert(MFI.getMaxCallFrameSize() <= MaxCFSIn && + "Recomputing MaxCFS gave a larger value."); + assert((FrameSDOps.empty() || MF.getFrameInfo().adjustsStack()) && + "AdjustsStack not set in presence of a frame pseudo instruction."); if (TFI->canSimplifyCallFramePseudos(MF)) { // If call frames are not being included as part of the stack frame, and diff --git a/llvm/lib/CodeGen/RegisterBankInfo.cpp b/llvm/lib/CodeGen/RegisterBankInfo.cpp index 5548430d1b0ae8847aed364ae39940588025d904..72b07eb1902d9bf1c6b954060705928406064aaf 100644 --- a/llvm/lib/CodeGen/RegisterBankInfo.cpp +++ b/llvm/lib/CodeGen/RegisterBankInfo.cpp @@ -484,9 +484,10 @@ void RegisterBankInfo::applyDefaultMapping(const OperandsMapper &OpdMapper) { // the storage. However, right now we don't necessarily bump all // the types to storage size. For instance, we can consider // s16 G_AND legal whereas the storage size is going to be 32. - assert(OrigTy.getSizeInBits() <= NewTy.getSizeInBits() && - "Types with difference size cannot be handled by the default " - "mapping"); + assert( + TypeSize::isKnownLE(OrigTy.getSizeInBits(), NewTy.getSizeInBits()) && + "Types with difference size cannot be handled by the default " + "mapping"); LLVM_DEBUG(dbgs() << "\nChange type of new opd from " << NewTy << " to " << OrigTy); MRI.setType(NewReg, OrigTy); diff --git a/llvm/lib/CodeGen/SelectOptimize.cpp b/llvm/lib/CodeGen/SelectOptimize.cpp index 40898d284a09ae5e6a65888afd3d910ef6637ea3..2e03ae6aec94d3a5c1e7e57c4660b2ed6bc8c320 100644 --- a/llvm/lib/CodeGen/SelectOptimize.cpp +++ b/llvm/lib/CodeGen/SelectOptimize.cpp @@ -624,8 +624,8 @@ void SelectOptimizeImpl::convertProfitableSIGroups(SelectGroups &ProfSIGroups) { // With RemoveDIs turned off, SplitPt can be a dbg.* intrinsic. With // RemoveDIs turned on, SplitPt would instead point to the next // instruction. To match existing dbg.* intrinsic behaviour with RemoveDIs, - // tell splitBasicBlock that we want to include any DPValues attached to - // SplitPt in the splice. + // tell splitBasicBlock that we want to include any DbgVariableRecords + // attached to SplitPt in the splice. SplitPt.setHeadBit(true); BasicBlock *EndBlock = StartBlock->splitBasicBlock(SplitPt, "select.end"); BFI->setBlockFreq(EndBlock, BFI->getBlockFreq(StartBlock)); @@ -645,12 +645,13 @@ void SelectOptimizeImpl::convertProfitableSIGroups(SelectGroups &ProfSIGroups) { DI->moveBeforePreserving(&*EndBlock->getFirstInsertionPt()); } - // Duplicate implementation for DPValues, the non-instruction debug-info - // record. Helper lambda for moving DPValues to the end block. - auto TransferDPValues = [&](Instruction &I) { - for (auto &DPValue : llvm::make_early_inc_range(I.getDbgRecordRange())) { - DPValue.removeFromParent(); - EndBlock->insertDbgRecordBefore(&DPValue, + // Duplicate implementation for DbgRecords, the non-instruction debug-info + // format. Helper lambda for moving DbgRecords to the end block. + auto TransferDbgRecords = [&](Instruction &I) { + for (auto &DbgRecord : + llvm::make_early_inc_range(I.getDbgRecordRange())) { + DbgRecord.removeFromParent(); + EndBlock->insertDbgRecordBefore(&DbgRecord, EndBlock->getFirstInsertionPt()); } }; @@ -660,7 +661,7 @@ void SelectOptimizeImpl::convertProfitableSIGroups(SelectGroups &ProfSIGroups) { // middle" of the select group. auto R = make_range(std::next(SI.getI()->getIterator()), std::next(LastSI.getI()->getIterator())); - llvm::for_each(R, TransferDPValues); + llvm::for_each(R, TransferDbgRecords); // These are the new basic blocks for the conditional branch. // At least one will become an actual new basic block. diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 735cec8ecc062797221d8843a4dbe51efab9b02c..2f46b23a97c62cab273778d1f06d23a3bce3c6c2 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -597,8 +597,8 @@ namespace { SDValue foldSextSetcc(SDNode *N); SDValue foldLogicOfSetCCs(bool IsAnd, SDValue N0, SDValue N1, const SDLoc &DL); - SDValue foldSubToUSubSat(EVT DstVT, SDNode *N); - SDValue foldABSToABD(SDNode *N); + SDValue foldSubToUSubSat(EVT DstVT, SDNode *N, const SDLoc &DL); + SDValue foldABSToABD(SDNode *N, const SDLoc &DL); SDValue unfoldMaskedMerge(SDNode *N); SDValue unfoldExtremeBitClearingToShifts(SDNode *N); SDValue SimplifySetCC(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond, @@ -609,6 +609,9 @@ namespace { SDValue &CC, bool MatchStrict = false) const; bool isOneUseSetCC(SDValue N) const; + SDValue foldAddToAvg(SDNode *N, const SDLoc &DL); + SDValue foldSubToAvg(SDNode *N, const SDLoc &DL); + SDValue SimplifyNodeWithTwoResults(SDNode *N, unsigned LoOp, unsigned HiOp); SDValue CombineConsecutiveLoads(SDNode *N, EVT VT); @@ -2490,7 +2493,8 @@ SDValue DAGCombiner::foldBinOpIntoSelect(SDNode *BO) { return SelectOp; } -static SDValue foldAddSubBoolOfMaskedVal(SDNode *N, SelectionDAG &DAG) { +static SDValue foldAddSubBoolOfMaskedVal(SDNode *N, const SDLoc &DL, + SelectionDAG &DAG) { assert((N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) && "Expecting add or sub"); @@ -2522,16 +2526,37 @@ static SDValue foldAddSubBoolOfMaskedVal(SDNode *N, SelectionDAG &DAG) { // add (zext i1 (seteq (X & 1), 0)), C --> sub C+1, (zext (X & 1)) // sub C, (zext i1 (seteq (X & 1), 0)) --> add C-1, (zext (X & 1)) EVT VT = C.getValueType(); - SDLoc DL(N); SDValue LowBit = DAG.getZExtOrTrunc(SetCC.getOperand(0), DL, VT); SDValue C1 = IsAdd ? DAG.getConstant(CN->getAPIntValue() + 1, DL, VT) : DAG.getConstant(CN->getAPIntValue() - 1, DL, VT); return DAG.getNode(IsAdd ? ISD::SUB : ISD::ADD, DL, VT, C1, LowBit); } +// Attempt to form avgceil(A, B) from (A | B) - ((A ^ B) >> 1) +SDValue DAGCombiner::foldSubToAvg(SDNode *N, const SDLoc &DL) { + SDValue N0 = N->getOperand(0); + EVT VT = N0.getValueType(); + SDValue A, B; + + if (hasOperation(ISD::AVGCEILU, VT) && + sd_match(N, m_Sub(m_Or(m_Value(A), m_Value(B)), + m_Srl(m_Xor(m_Deferred(A), m_Deferred(B)), + m_SpecificInt(1))))) { + return DAG.getNode(ISD::AVGCEILU, DL, VT, A, B); + } + if (hasOperation(ISD::AVGCEILS, VT) && + sd_match(N, m_Sub(m_Or(m_Value(A), m_Value(B)), + m_Sra(m_Xor(m_Deferred(A), m_Deferred(B)), + m_SpecificInt(1))))) { + return DAG.getNode(ISD::AVGCEILS, DL, VT, A, B); + } + return SDValue(); +} + /// Try to fold a 'not' shifted sign-bit with add/sub with constant operand into /// a shift and add with a different constant. -static SDValue foldAddSubOfSignBit(SDNode *N, SelectionDAG &DAG) { +static SDValue foldAddSubOfSignBit(SDNode *N, const SDLoc &DL, + SelectionDAG &DAG) { assert((N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) && "Expecting add or sub"); @@ -2559,7 +2584,6 @@ static SDValue foldAddSubOfSignBit(SDNode *N, SelectionDAG &DAG) { // Eliminate the 'not' by adjusting the shift and add/sub constant: // add (srl (not X), 31), C --> add (sra X, 31), (C + 1) // sub C, (srl (not X), 31) --> add (srl X, 31), (C - 1) - SDLoc DL(N); if (SDValue NewC = DAG.FoldConstantArithmetic( IsAdd ? ISD::ADD : ISD::SUB, DL, VT, {ConstantOp, DAG.getConstant(1, DL, VT)})) { @@ -2703,11 +2727,11 @@ SDValue DAGCombiner::visitADDLike(SDNode *N) { SDValue A, B, C; // fold ((0-A) + B) -> B-A - if (sd_match(N0, m_Sub(m_Zero(), m_Value(A)))) + if (sd_match(N0, m_Neg(m_Value(A)))) return DAG.getNode(ISD::SUB, DL, VT, N1, A); // fold (A + (0-B)) -> A-B - if (sd_match(N1, m_Sub(m_Zero(), m_Value(B)))) + if (sd_match(N1, m_Neg(m_Value(B)))) return DAG.getNode(ISD::SUB, DL, VT, N0, B); // fold (A+(B-A)) -> B @@ -2799,8 +2823,7 @@ SDValue DAGCombiner::visitADDLike(SDNode *N) { // Limit this to after legalization if the add has wrap flags (Level >= AfterLegalizeDAG || (!N->getFlags().hasNoUnsignedWrap() && !N->getFlags().hasNoSignedWrap()))) { - SDValue Not = DAG.getNode(ISD::XOR, DL, VT, N0.getOperand(0), - DAG.getAllOnesConstant(DL, VT)); + SDValue Not = DAG.getNOT(DL, N0.getOperand(0), VT); return DAG.getNode(ISD::SUB, DL, VT, N0.getOperand(1), Not); } } @@ -2821,6 +2844,28 @@ SDValue DAGCombiner::visitADDLike(SDNode *N) { return SDValue(); } +// Attempt to form avgfloor(A, B) from (A & B) + ((A ^ B) >> 1) +SDValue DAGCombiner::foldAddToAvg(SDNode *N, const SDLoc &DL) { + SDValue N0 = N->getOperand(0); + EVT VT = N0.getValueType(); + SDValue A, B; + + if (hasOperation(ISD::AVGFLOORU, VT) && + sd_match(N, m_Add(m_And(m_Value(A), m_Value(B)), + m_Srl(m_Xor(m_Deferred(A), m_Deferred(B)), + m_SpecificInt(1))))) { + return DAG.getNode(ISD::AVGFLOORU, DL, VT, A, B); + } + if (hasOperation(ISD::AVGFLOORS, VT) && + sd_match(N, m_Add(m_And(m_Value(A), m_Value(B)), + m_Sra(m_Xor(m_Deferred(A), m_Deferred(B)), + m_SpecificInt(1))))) { + return DAG.getNode(ISD::AVGFLOORS, DL, VT, A, B); + } + + return SDValue(); +} + SDValue DAGCombiner::visitADD(SDNode *N) { SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); @@ -2830,16 +2875,23 @@ SDValue DAGCombiner::visitADD(SDNode *N) { if (SDValue Combined = visitADDLike(N)) return Combined; - if (SDValue V = foldAddSubBoolOfMaskedVal(N, DAG)) + if (SDValue V = foldAddSubBoolOfMaskedVal(N, DL, DAG)) return V; - if (SDValue V = foldAddSubOfSignBit(N, DAG)) + if (SDValue V = foldAddSubOfSignBit(N, DL, DAG)) + return V; + + // Try to match AVGFLOOR fixedwidth pattern + if (SDValue V = foldAddToAvg(N, DL)) return V; // fold (a+b) -> (a|b) iff a and b share no bits. if ((!LegalOperations || TLI.isOperationLegal(ISD::OR, VT)) && - DAG.haveNoCommonBitsSet(N0, N1)) - return DAG.getNode(ISD::OR, DL, VT, N0, N1); + DAG.haveNoCommonBitsSet(N0, N1)) { + SDNodeFlags Flags; + Flags.setDisjoint(true); + return DAG.getNode(ISD::OR, DL, VT, N0, N1, Flags); + } // Fold (add (vscale * C0), (vscale * C1)) to (vscale * (C0 + C1)). if (N0.getOpcode() == ISD::VSCALE && N1.getOpcode() == ISD::VSCALE) { @@ -3025,8 +3077,7 @@ SDValue DAGCombiner::visitADDLikeCommutative(SDValue N0, SDValue N1, // Limit this to after legalization if the add has wrap flags (Level >= AfterLegalizeDAG || (!N0->getFlags().hasNoUnsignedWrap() && !N0->getFlags().hasNoSignedWrap()))) { - SDValue Not = DAG.getNode(ISD::XOR, DL, VT, N0.getOperand(0), - DAG.getAllOnesConstant(DL, VT)); + SDValue Not = DAG.getNOT(DL, N0.getOperand(0), VT); return DAG.getNode(ISD::SUB, DL, VT, N1, Not); } @@ -3437,6 +3488,11 @@ static SDValue combineCarryDiamond(SelectionDAG &DAG, const TargetLowering &TLI, return SDValue(); if (Opcode != ISD::UADDO && Opcode != ISD::USUBO) return SDValue(); + // Guarantee identical type of CarryOut + EVT CarryOutType = N->getValueType(0); + if (CarryOutType != Carry0.getValue(1).getValueType() || + CarryOutType != Carry1.getValue(1).getValueType()) + return SDValue(); // Canonicalize the add/sub of A and B (the top node in the above ASCII art) // as Carry0 and the add/sub of the carry in as Carry1 (the middle node). @@ -3484,7 +3540,7 @@ static SDValue combineCarryDiamond(SelectionDAG &DAG, const TargetLowering &TLI, // TODO: match other operations that can merge flags (ADD, etc) DAG.ReplaceAllUsesOfValueWith(Carry1.getValue(0), Merged.getValue(0)); if (N->getOpcode() == ISD::AND) - return DAG.getConstant(0, DL, MVT::i1); + return DAG.getConstant(0, DL, CarryOutType); return Merged.getValue(1); } @@ -3598,7 +3654,7 @@ static SDValue getTruncatedUSUBSAT(EVT DstVT, EVT SrcVT, SDValue LHS, // Try to find umax(a,b) - b or a - umin(a,b) patterns that may be converted to // usubsat(a,b), optionally as a truncated type. -SDValue DAGCombiner::foldSubToUSubSat(EVT DstVT, SDNode *N) { +SDValue DAGCombiner::foldSubToUSubSat(EVT DstVT, SDNode *N, const SDLoc &DL) { if (N->getOpcode() != ISD::SUB || !(!LegalOperations || hasOperation(ISD::USUBSAT, DstVT))) return SDValue(); @@ -3613,18 +3669,18 @@ SDValue DAGCombiner::foldSubToUSubSat(EVT DstVT, SDNode *N) { SDValue MaxLHS = Op0.getOperand(0); SDValue MaxRHS = Op0.getOperand(1); if (MaxLHS == Op1) - return getTruncatedUSUBSAT(DstVT, SubVT, MaxRHS, Op1, DAG, SDLoc(N)); + return getTruncatedUSUBSAT(DstVT, SubVT, MaxRHS, Op1, DAG, DL); if (MaxRHS == Op1) - return getTruncatedUSUBSAT(DstVT, SubVT, MaxLHS, Op1, DAG, SDLoc(N)); + return getTruncatedUSUBSAT(DstVT, SubVT, MaxLHS, Op1, DAG, DL); } if (Op1.getOpcode() == ISD::UMIN && Op1.hasOneUse()) { SDValue MinLHS = Op1.getOperand(0); SDValue MinRHS = Op1.getOperand(1); if (MinLHS == Op0) - return getTruncatedUSUBSAT(DstVT, SubVT, Op0, MinRHS, DAG, SDLoc(N)); + return getTruncatedUSUBSAT(DstVT, SubVT, Op0, MinRHS, DAG, DL); if (MinRHS == Op0) - return getTruncatedUSUBSAT(DstVT, SubVT, Op0, MinLHS, DAG, SDLoc(N)); + return getTruncatedUSUBSAT(DstVT, SubVT, Op0, MinLHS, DAG, DL); } // sub(a,trunc(umin(zext(a),b))) -> usubsat(a,trunc(umin(b,SatLimit))) @@ -3635,10 +3691,10 @@ SDValue DAGCombiner::foldSubToUSubSat(EVT DstVT, SDNode *N) { SDValue MinRHS = Op1.getOperand(0).getOperand(1); if (MinLHS.getOpcode() == ISD::ZERO_EXTEND && MinLHS.getOperand(0) == Op0) return getTruncatedUSUBSAT(DstVT, MinLHS.getValueType(), MinLHS, MinRHS, - DAG, SDLoc(N)); + DAG, DL); if (MinRHS.getOpcode() == ISD::ZERO_EXTEND && MinRHS.getOperand(0) == Op0) return getTruncatedUSUBSAT(DstVT, MinLHS.getValueType(), MinRHS, MinLHS, - DAG, SDLoc(N)); + DAG, DL); } return SDValue(); @@ -3659,6 +3715,7 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); EVT VT = N0.getValueType(); + unsigned BitWidth = VT.getScalarSizeInBits(); SDLoc DL(N); auto PeekThroughFreeze = [](SDValue N) { @@ -3689,16 +3746,12 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { if (SDValue NewSel = foldBinOpIntoSelect(N)) return NewSel; - ConstantSDNode *N1C = getAsNonOpaqueConstant(N1); - // fold (sub x, c) -> (add x, -c) - if (N1C) { + if (ConstantSDNode *N1C = getAsNonOpaqueConstant(N1)) return DAG.getNode(ISD::ADD, DL, VT, N0, DAG.getConstant(-N1C->getAPIntValue(), DL, VT)); - } if (isNullOrNullSplat(N0)) { - unsigned BitWidth = VT.getScalarSizeInBits(); // Right-shifting everything out but the sign bit followed by negation is // the same as flipping arithmetic/logical shift type without the negation: // -(X >>u 31) -> (X >>s 31) @@ -3789,63 +3842,34 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { return DAG.getNode(ISD::SUB, DL, VT, NewC, N0.getOperand(1)); } - // fold ((A+(B+or-C))-B) -> A+or-C - if (N0.getOpcode() == ISD::ADD && - (N0.getOperand(1).getOpcode() == ISD::SUB || - N0.getOperand(1).getOpcode() == ISD::ADD) && - N0.getOperand(1).getOperand(0) == N1) - return DAG.getNode(N0.getOperand(1).getOpcode(), DL, VT, N0.getOperand(0), - N0.getOperand(1).getOperand(1)); - - // fold ((A+(C+B))-B) -> A+C - if (N0.getOpcode() == ISD::ADD && N0.getOperand(1).getOpcode() == ISD::ADD && - N0.getOperand(1).getOperand(1) == N1) - return DAG.getNode(ISD::ADD, DL, VT, N0.getOperand(0), - N0.getOperand(1).getOperand(0)); + SDValue A, B, C; + + // fold ((A+(B+C))-B) -> A+C + if (sd_match(N0, m_Add(m_Value(A), m_Add(m_Specific(N1), m_Value(C))))) + return DAG.getNode(ISD::ADD, DL, VT, A, C); + + // fold ((A+(B-C))-B) -> A-C + if (sd_match(N0, m_Add(m_Value(A), m_Sub(m_Specific(N1), m_Value(C))))) + return DAG.getNode(ISD::SUB, DL, VT, A, C); // fold ((A-(B-C))-C) -> A-B - if (N0.getOpcode() == ISD::SUB && N0.getOperand(1).getOpcode() == ISD::SUB && - N0.getOperand(1).getOperand(1) == N1) - return DAG.getNode(ISD::SUB, DL, VT, N0.getOperand(0), - N0.getOperand(1).getOperand(0)); + if (sd_match(N0, m_Sub(m_Value(A), m_Sub(m_Value(B), m_Specific(N1))))) + return DAG.getNode(ISD::SUB, DL, VT, A, B); // fold (A-(B-C)) -> A+(C-B) - if (N1.getOpcode() == ISD::SUB && N1.hasOneUse()) + if (sd_match(N1, m_OneUse(m_Sub(m_Value(B), m_Value(C))))) return DAG.getNode(ISD::ADD, DL, VT, N0, - DAG.getNode(ISD::SUB, DL, VT, N1.getOperand(1), - N1.getOperand(0))); + DAG.getNode(ISD::SUB, DL, VT, C, B)); // A - (A & B) -> A & (~B) - if (N1.getOpcode() == ISD::AND) { - SDValue A = N1.getOperand(0); - SDValue B = N1.getOperand(1); - if (A != N0) - std::swap(A, B); - if (A == N0 && - (N1.hasOneUse() || isConstantOrConstantVector(B, /*NoOpaques=*/true))) { - SDValue InvB = - DAG.getNode(ISD::XOR, DL, VT, B, DAG.getAllOnesConstant(DL, VT)); - return DAG.getNode(ISD::AND, DL, VT, A, InvB); - } - } + if (sd_match(N1, m_And(m_Specific(N0), m_Value(B))) && + (N1.hasOneUse() || isConstantOrConstantVector(B, /*NoOpaques=*/true))) + return DAG.getNode(ISD::AND, DL, VT, N0, DAG.getNOT(DL, B, VT)); - // fold (X - (-Y * Z)) -> (X + (Y * Z)) - if (N1.getOpcode() == ISD::MUL && N1.hasOneUse()) { - if (N1.getOperand(0).getOpcode() == ISD::SUB && - isNullOrNullSplat(N1.getOperand(0).getOperand(0))) { - SDValue Mul = DAG.getNode(ISD::MUL, DL, VT, - N1.getOperand(0).getOperand(1), - N1.getOperand(1)); - return DAG.getNode(ISD::ADD, DL, VT, N0, Mul); - } - if (N1.getOperand(1).getOpcode() == ISD::SUB && - isNullOrNullSplat(N1.getOperand(1).getOperand(0))) { - SDValue Mul = DAG.getNode(ISD::MUL, DL, VT, - N1.getOperand(0), - N1.getOperand(1).getOperand(1)); - return DAG.getNode(ISD::ADD, DL, VT, N0, Mul); - } - } + // fold (A - (-B * C)) -> (A + (B * C)) + if (sd_match(N1, m_OneUse(m_Mul(m_Neg(m_Value(B)), m_Value(C))))) + return DAG.getNode(ISD::ADD, DL, VT, N0, + DAG.getNode(ISD::MUL, DL, VT, B, C)); // If either operand of a sub is undef, the result is undef if (N0.isUndef()) @@ -3853,24 +3877,25 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { if (N1.isUndef()) return N1; - if (SDValue V = foldAddSubBoolOfMaskedVal(N, DAG)) + if (SDValue V = foldAddSubBoolOfMaskedVal(N, DL, DAG)) return V; - if (SDValue V = foldAddSubOfSignBit(N, DAG)) + if (SDValue V = foldAddSubOfSignBit(N, DL, DAG)) return V; - if (SDValue V = foldAddSubMasked1(false, N0, N1, DAG, SDLoc(N))) + // Try to match AVGCEIL fixedwidth pattern + if (SDValue V = foldSubToAvg(N, DL)) return V; - if (SDValue V = foldSubToUSubSat(VT, N)) + if (SDValue V = foldAddSubMasked1(false, N0, N1, DAG, DL)) return V; - // (x - y) - 1 -> add (xor y, -1), x - if (N0.getOpcode() == ISD::SUB && N0.hasOneUse() && isOneOrOneSplat(N1)) { - SDValue Xor = DAG.getNode(ISD::XOR, DL, VT, N0.getOperand(1), - DAG.getAllOnesConstant(DL, VT)); - return DAG.getNode(ISD::ADD, DL, VT, Xor, N0.getOperand(0)); - } + if (SDValue V = foldSubToUSubSat(VT, N, DL)) + return V; + + // (A - B) - 1 -> add (xor B, -1), A + if (sd_match(N, m_Sub(m_OneUse(m_Sub(m_Value(A), m_Value(B))), m_One()))) + return DAG.getNode(ISD::ADD, DL, VT, A, DAG.getNOT(DL, B, VT)); // Look for: // sub y, (xor x, -1) @@ -3926,8 +3951,8 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { SDValue S0 = N1.getOperand(0); if ((X0 == S0 && X1 == N1) || (X0 == N1 && X1 == S0)) if (ConstantSDNode *C = isConstOrConstSplat(N1.getOperand(1))) - if (C->getAPIntValue() == (VT.getScalarSizeInBits() - 1)) - return DAG.getNode(ISD::ABS, SDLoc(N), VT, S0); + if (C->getAPIntValue() == (BitWidth - 1)) + return DAG.getNode(ISD::ABS, DL, VT, S0); } } @@ -3969,8 +3994,7 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { if (!LegalOperations && N1.getOpcode() == ISD::SRL && N1.hasOneUse()) { SDValue ShAmt = N1.getOperand(1); ConstantSDNode *ShAmtC = isConstOrConstSplat(ShAmt); - if (ShAmtC && - ShAmtC->getAPIntValue() == (N1.getScalarValueSizeInBits() - 1)) { + if (ShAmtC && ShAmtC->getAPIntValue() == (BitWidth - 1)) { SDValue SRA = DAG.getNode(ISD::SRA, DL, VT, N1.getOperand(0), ShAmt); return DAG.getNode(ISD::ADD, DL, VT, N0, SRA); } @@ -3981,7 +4005,7 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { // N0 - (X << BW-1) --> N0 + (X << BW-1) if (N1.getOpcode() == ISD::SHL) { ConstantSDNode *ShlC = isConstOrConstSplat(N1.getOperand(1)); - if (ShlC && ShlC->getAPIntValue() == VT.getScalarSizeInBits() - 1) + if (ShlC && ShlC->getAPIntValue() == (BitWidth - 1)) return DAG.getNode(ISD::ADD, DL, VT, N1, N0); } @@ -4014,23 +4038,17 @@ SDValue DAGCombiner::visitSUB(SDNode *N) { } } - // max(a,b) - min(a,b) --> abd(a,b) - auto MatchSubMaxMin = [&](unsigned Max, unsigned Min, unsigned Abd) { - if (N0.getOpcode() != Max || N1.getOpcode() != Min) - return SDValue(); - if ((N0.getOperand(0) != N1.getOperand(0) || - N0.getOperand(1) != N1.getOperand(1)) && - (N0.getOperand(0) != N1.getOperand(1) || - N0.getOperand(1) != N1.getOperand(0))) - return SDValue(); - if (!hasOperation(Abd, VT)) - return SDValue(); - return DAG.getNode(Abd, DL, VT, N0.getOperand(0), N0.getOperand(1)); - }; - if (SDValue R = MatchSubMaxMin(ISD::SMAX, ISD::SMIN, ISD::ABDS)) - return R; - if (SDValue R = MatchSubMaxMin(ISD::UMAX, ISD::UMIN, ISD::ABDU)) - return R; + // smax(a,b) - smin(a,b) --> abds(a,b) + if (hasOperation(ISD::ABDS, VT) && + sd_match(N0, m_SMax(m_Value(A), m_Value(B))) && + sd_match(N1, m_SMin(m_Specific(A), m_Specific(B)))) + return DAG.getNode(ISD::ABDS, DL, VT, A, B); + + // umax(a,b) - umin(a,b) --> abdu(a,b) + if (hasOperation(ISD::ABDU, VT) && + sd_match(N0, m_UMax(m_Value(A), m_Value(B))) && + sd_match(N1, m_UMin(m_Specific(A), m_Specific(B)))) + return DAG.getNode(ISD::ABDU, DL, VT, A, B); return SDValue(); } @@ -4123,13 +4141,11 @@ SDValue DAGCombiner::visitSUBO(SDNode *N) { return CombineTo(N, DAG.getConstant(0, DL, VT), DAG.getConstant(0, DL, CarryVT)); - ConstantSDNode *N1C = getAsNonOpaqueConstant(N1); - // fold (subox, c) -> (addo x, -c) - if (IsSigned && N1C && !N1C->isMinSignedValue()) { - return DAG.getNode(ISD::SADDO, DL, N->getVTList(), N0, - DAG.getConstant(-N1C->getAPIntValue(), DL, VT)); - } + if (ConstantSDNode *N1C = getAsNonOpaqueConstant(N1)) + if (IsSigned && !N1C->isMinSignedValue()) + return DAG.getNode(ISD::SADDO, DL, N->getVTList(), N0, + DAG.getConstant(-N1C->getAPIntValue(), DL, VT)); // fold (subo x, 0) -> x + no borrow if (isNullOrNullSplat(N1)) @@ -6689,35 +6705,25 @@ static SDValue combineShiftAnd1ToBitTest(SDNode *And, SelectionDAG &DAG) { /// For targets that support usubsat, match a bit-hack form of that operation /// that ends in 'and' and convert it. -static SDValue foldAndToUsubsat(SDNode *N, SelectionDAG &DAG) { - SDValue N0 = N->getOperand(0); - SDValue N1 = N->getOperand(1); - EVT VT = N1.getValueType(); - - // Canonicalize SRA as operand 1. - if (N0.getOpcode() == ISD::SRA) - std::swap(N0, N1); - - // xor/add with SMIN (signmask) are logically equivalent. - if (N0.getOpcode() != ISD::XOR && N0.getOpcode() != ISD::ADD) - return SDValue(); - - if (N1.getOpcode() != ISD::SRA || !N0.hasOneUse() || !N1.hasOneUse() || - N0.getOperand(0) != N1.getOperand(0)) - return SDValue(); - +static SDValue foldAndToUsubsat(SDNode *N, SelectionDAG &DAG, const SDLoc &DL) { + EVT VT = N->getValueType(0); unsigned BitWidth = VT.getScalarSizeInBits(); - ConstantSDNode *XorC = isConstOrConstSplat(N0.getOperand(1), true); - ConstantSDNode *SraC = isConstOrConstSplat(N1.getOperand(1), true); - if (!XorC || !XorC->getAPIntValue().isSignMask() || - !SraC || SraC->getAPIntValue() != BitWidth - 1) - return SDValue(); + APInt SignMask = APInt::getSignMask(BitWidth); // (i8 X ^ 128) & (i8 X s>> 7) --> usubsat X, 128 // (i8 X + 128) & (i8 X s>> 7) --> usubsat X, 128 - SDLoc DL(N); - SDValue SignMask = DAG.getConstant(XorC->getAPIntValue(), DL, VT); - return DAG.getNode(ISD::USUBSAT, DL, VT, N0.getOperand(0), SignMask); + // xor/add with SMIN (signmask) are logically equivalent. + SDValue X; + if (!sd_match(N, m_And(m_OneUse(m_Xor(m_Value(X), m_SpecificInt(SignMask))), + m_OneUse(m_Sra(m_Deferred(X), + m_SpecificInt(BitWidth - 1))))) && + !sd_match(N, m_And(m_OneUse(m_Add(m_Value(X), m_SpecificInt(SignMask))), + m_OneUse(m_Sra(m_Deferred(X), + m_SpecificInt(BitWidth - 1)))))) + return SDValue(); + + return DAG.getNode(ISD::USUBSAT, DL, VT, X, + DAG.getConstant(SignMask, DL, VT)); } /// Given a bitwise logic operation N with a matching bitwise logic operand, @@ -6807,34 +6813,34 @@ SDValue DAGCombiner::visitAND(SDNode *N) { SDValue N0 = N->getOperand(0); SDValue N1 = N->getOperand(1); EVT VT = N1.getValueType(); + SDLoc DL(N); // x & x --> x if (N0 == N1) return N0; // fold (and c1, c2) -> c1&c2 - if (SDValue C = DAG.FoldConstantArithmetic(ISD::AND, SDLoc(N), VT, {N0, N1})) + if (SDValue C = DAG.FoldConstantArithmetic(ISD::AND, DL, VT, {N0, N1})) return C; // canonicalize constant to RHS if (DAG.isConstantIntBuildVectorOrConstantInt(N0) && !DAG.isConstantIntBuildVectorOrConstantInt(N1)) - return DAG.getNode(ISD::AND, SDLoc(N), VT, N1, N0); + return DAG.getNode(ISD::AND, DL, VT, N1, N0); if (areBitwiseNotOfEachother(N0, N1)) - return DAG.getConstant(APInt::getZero(VT.getScalarSizeInBits()), SDLoc(N), - VT); + return DAG.getConstant(APInt::getZero(VT.getScalarSizeInBits()), DL, VT); // fold vector ops if (VT.isVector()) { - if (SDValue FoldedVOp = SimplifyVBinOp(N, SDLoc(N))) + if (SDValue FoldedVOp = SimplifyVBinOp(N, DL)) return FoldedVOp; // fold (and x, 0) -> 0, vector edition if (ISD::isConstantSplatVectorAllZeros(N1.getNode())) // do not return N1, because undef node may exist in N1 - return DAG.getConstant(APInt::getZero(N1.getScalarValueSizeInBits()), - SDLoc(N), N1.getValueType()); + return DAG.getConstant(APInt::getZero(N1.getScalarValueSizeInBits()), DL, + N1.getValueType()); // fold (and x, -1) -> x, vector edition if (ISD::isConstantSplatVectorAllOnes(N1.getNode())) @@ -6854,8 +6860,8 @@ SDValue DAGCombiner::visitAND(SDNode *N) { uint64_t ElementSize = LoadVT.getVectorElementType().getScalarSizeInBits(); if (Splat->getAPIntValue().isMask(ElementSize)) { - auto NewLoad = DAG.getMaskedLoad( - ExtVT, SDLoc(N), MLoad->getChain(), MLoad->getBasePtr(), + SDValue NewLoad = DAG.getMaskedLoad( + ExtVT, DL, MLoad->getChain(), MLoad->getBasePtr(), MLoad->getOffset(), MLoad->getMask(), MLoad->getPassThru(), LoadVT, MLoad->getMemOperand(), MLoad->getAddressingMode(), ISD::ZEXTLOAD, MLoad->isExpandingLoad()); @@ -6877,7 +6883,7 @@ SDValue DAGCombiner::visitAND(SDNode *N) { unsigned BitWidth = VT.getScalarSizeInBits(); ConstantSDNode *N1C = isConstOrConstSplat(N1); if (N1C && DAG.MaskedValueIsZero(SDValue(N, 0), APInt::getAllOnes(BitWidth))) - return DAG.getConstant(0, SDLoc(N), VT); + return DAG.getConstant(0, DL, VT); if (SDValue R = foldAndOrOfSETCC(N, DAG)) return R; @@ -6886,12 +6892,12 @@ SDValue DAGCombiner::visitAND(SDNode *N) { return NewSel; // reassociate and - if (SDValue RAND = reassociateOps(ISD::AND, SDLoc(N), N0, N1, N->getFlags())) + if (SDValue RAND = reassociateOps(ISD::AND, DL, N0, N1, N->getFlags())) return RAND; // Fold and(vecreduce(x), vecreduce(y)) -> vecreduce(and(x, y)) - if (SDValue SD = reassociateReduction(ISD::VECREDUCE_AND, ISD::AND, SDLoc(N), - VT, N0, N1)) + if (SDValue SD = + reassociateReduction(ISD::VECREDUCE_AND, ISD::AND, DL, VT, N0, N1)) return SD; // fold (and (or x, C), D) -> D if (C & D) == D @@ -6911,18 +6917,16 @@ SDValue DAGCombiner::visitAND(SDNode *N) { // fold (and (any_ext V), c) -> (zero_ext V) if 'and' only clears top bits. if (DAG.MaskedValueIsZero(N0Op0, Mask)) - return DAG.getNode(ISD::ZERO_EXTEND, SDLoc(N), VT, N0Op0); + return DAG.getNode(ISD::ZERO_EXTEND, DL, VT, N0Op0); // fold (and (any_ext V), c) -> (zero_ext (and (trunc V), c)) if profitable. if (N1C->getAPIntValue().countLeadingZeros() >= (BitWidth - SrcBitWidth) && TLI.isTruncateFree(VT, SrcVT) && TLI.isZExtFree(SrcVT, VT) && TLI.isTypeDesirableForOp(ISD::AND, SrcVT) && - TLI.isNarrowingProfitable(VT, SrcVT)) { - SDLoc DL(N); + TLI.isNarrowingProfitable(VT, SrcVT)) return DAG.getNode(ISD::ZERO_EXTEND, DL, VT, DAG.getNode(ISD::AND, DL, SrcVT, N0Op0, DAG.getZExtOrTrunc(N1, DL, SrcVT))); - } } // fold (and (ext (and V, c1)), c2) -> (and (ext V), (and c1, (ext c2))) @@ -6934,7 +6938,6 @@ SDValue DAGCombiner::visitAND(SDNode *N) { DAG.isConstantIntBuildVectorOrConstantInt(N1) && DAG.isConstantIntBuildVectorOrConstantInt(N0Op0.getOperand(1)) && N0->hasOneUse() && N0Op0->hasOneUse()) { - SDLoc DL(N); SDValue NewMask = DAG.getNode(ISD::AND, DL, VT, N1, DAG.getNode(ExtOpc, DL, VT, N0Op0.getOperand(1))); @@ -6955,8 +6958,8 @@ SDValue DAGCombiner::visitAND(SDNode *N) { N0.getOperand(0).getOpcode() == ISD::LOAD && N0.getOperand(0).getResNo() == 0) || (N0.getOpcode() == ISD::LOAD && N0.getResNo() == 0)) { - LoadSDNode *Load = cast<LoadSDNode>( (N0.getOpcode() == ISD::LOAD) ? - N0 : N0.getOperand(0) ); + auto *Load = + cast<LoadSDNode>((N0.getOpcode() == ISD::LOAD) ? N0 : N0.getOperand(0)); // Get the constant (if applicable) the zero'th operand is being ANDed with. // This can be a pure constant or a vector splat, in which case we treat the @@ -7066,9 +7069,9 @@ SDValue DAGCombiner::visitAND(SDNode *N) { // (and (extract_subvector (zext|anyext|sext v) _) iN_mask) // => (extract_subvector (iN_zeroext v)) SDValue ZeroExtExtendee = - DAG.getNode(ISD::ZERO_EXTEND, SDLoc(N), ExtVT, Extendee); + DAG.getNode(ISD::ZERO_EXTEND, DL, ExtVT, Extendee); - return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(N), VT, ZeroExtExtendee, + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, ZeroExtExtendee, N0.getOperand(1)); } } @@ -7085,8 +7088,8 @@ SDValue DAGCombiner::visitAND(SDNode *N) { GN0->getBasePtr(), GN0->getIndex(), GN0->getScale()}; SDValue ZExtLoad = DAG.getMaskedGather( - DAG.getVTList(VT, MVT::Other), MemVT, SDLoc(N), Ops, - GN0->getMemOperand(), GN0->getIndexType(), ISD::ZEXTLOAD); + DAG.getVTList(VT, MVT::Other), MemVT, DL, Ops, GN0->getMemOperand(), + GN0->getIndexType(), ISD::ZEXTLOAD); CombineTo(N, ZExtLoad); AddToWorklist(ZExtLoad.getNode()); @@ -7138,7 +7141,7 @@ SDValue DAGCombiner::visitAND(SDNode *N) { return SubRHS; if (SubRHS.getOpcode() == ISD::SIGN_EXTEND && SubRHS.getOperand(0).getScalarValueSizeInBits() == 1) - return DAG.getNode(ISD::ZERO_EXTEND, SDLoc(N), VT, SubRHS.getOperand(0)); + return DAG.getNode(ISD::ZERO_EXTEND, DL, VT, SubRHS.getOperand(0)); } } @@ -7152,7 +7155,7 @@ SDValue DAGCombiner::visitAND(SDNode *N) { if (ISD::isUNINDEXEDLoad(N0.getNode()) && (ISD::isEXTLoad(N0.getNode()) || (ISD::isSEXTLoad(N0.getNode()) && N0.hasOneUse()))) { - LoadSDNode *LN0 = cast<LoadSDNode>(N0); + auto *LN0 = cast<LoadSDNode>(N0); EVT MemVT = LN0->getMemoryVT(); // If we zero all the possible extended bits, then we can turn this into // a zextload if we are running before legalize or the operation is legal. @@ -7207,10 +7210,10 @@ SDValue DAGCombiner::visitAND(SDNode *N) { // Replace (and (sign_extend ...) #bitmask) with (zero_extend ...). if (IsAndZeroExtMask(N0, N1)) - return DAG.getNode(ISD::ZERO_EXTEND, SDLoc(N), VT, N0.getOperand(0)); + return DAG.getNode(ISD::ZERO_EXTEND, DL, VT, N0.getOperand(0)); if (hasOperation(ISD::USUBSAT, VT)) - if (SDValue V = foldAndToUsubsat(N, DAG)) + if (SDValue V = foldAndToUsubsat(N, DAG, DL)) return V; // Postpone until legalization completed to avoid interference with bswap @@ -9289,8 +9292,11 @@ SDValue DAGCombiner::visitXOR(SDNode *N) { // fold (a^b) -> (a|b) iff a and b share no bits. if ((!LegalOperations || TLI.isOperationLegal(ISD::OR, VT)) && - DAG.haveNoCommonBitsSet(N0, N1)) - return DAG.getNode(ISD::OR, DL, VT, N0, N1); + DAG.haveNoCommonBitsSet(N0, N1)) { + SDNodeFlags Flags; + Flags.setDisjoint(true); + return DAG.getNode(ISD::OR, DL, VT, N0, N1, Flags); + } // look for 'add-like' folds: // XOR(N0,MIN_SIGNED_VALUE) == ADD(N0,MIN_SIGNED_VALUE) @@ -10767,7 +10773,7 @@ SDValue DAGCombiner::visitSHLSAT(SDNode *N) { // (ABS (SUB (EXTEND a), (EXTEND b))). // (TRUNC (ABS (SUB (EXTEND a), (EXTEND b)))). // Generates UABD/SABD instruction. -SDValue DAGCombiner::foldABSToABD(SDNode *N) { +SDValue DAGCombiner::foldABSToABD(SDNode *N, const SDLoc &DL) { EVT SrcVT = N->getValueType(0); if (N->getOpcode() == ISD::TRUNCATE) @@ -10779,7 +10785,6 @@ SDValue DAGCombiner::foldABSToABD(SDNode *N) { EVT VT = N->getValueType(0); SDValue AbsOp1 = N->getOperand(0); SDValue Op0, Op1; - SDLoc DL(N); if (AbsOp1.getOpcode() != ISD::SUB) return SDValue(); @@ -10838,9 +10843,10 @@ SDValue DAGCombiner::foldABSToABD(SDNode *N) { SDValue DAGCombiner::visitABS(SDNode *N) { SDValue N0 = N->getOperand(0); EVT VT = N->getValueType(0); + SDLoc DL(N); // fold (abs c1) -> c2 - if (SDValue C = DAG.FoldConstantArithmetic(ISD::ABS, SDLoc(N), VT, {N0})) + if (SDValue C = DAG.FoldConstantArithmetic(ISD::ABS, DL, VT, {N0})) return C; // fold (abs (abs x)) -> (abs x) if (N0.getOpcode() == ISD::ABS) @@ -10849,7 +10855,7 @@ SDValue DAGCombiner::visitABS(SDNode *N) { if (DAG.SignBitIsZero(N0)) return N0; - if (SDValue ABD = foldABSToABD(N)) + if (SDValue ABD = foldABSToABD(N, DL)) return ABD; // fold (abs (sign_extend_inreg x)) -> (zero_extend (abs (truncate x))) @@ -10859,7 +10865,6 @@ SDValue DAGCombiner::visitABS(SDNode *N) { if (TLI.isTruncateFree(VT, ExtVT) && TLI.isZExtFree(ExtVT, VT) && TLI.isTypeDesirableForOp(ISD::ABS, ExtVT) && hasOperation(ISD::ABS, ExtVT)) { - SDLoc DL(N); return DAG.getNode( ISD::ZERO_EXTEND, DL, VT, DAG.getNode(ISD::ABS, DL, ExtVT, @@ -13144,6 +13149,37 @@ tryToFoldExtOfMaskedLoad(SelectionDAG &DAG, const TargetLowering &TLI, EVT VT, return NewLoad; } +// fold ([s|z]ext (atomic_load)) -> ([s|z]ext (truncate ([s|z]ext atomic_load))) +static SDValue tryToFoldExtOfAtomicLoad(SelectionDAG &DAG, + const TargetLowering &TLI, EVT VT, + SDValue N0, + ISD::LoadExtType ExtLoadType) { + auto *ALoad = dyn_cast<AtomicSDNode>(N0); + if (!ALoad || ALoad->getOpcode() != ISD::ATOMIC_LOAD) + return {}; + EVT MemoryVT = ALoad->getMemoryVT(); + if (!TLI.isAtomicLoadExtLegal(ExtLoadType, VT, MemoryVT)) + return {}; + // Can't fold into ALoad if it is already extending differently. + ISD::LoadExtType ALoadExtTy = ALoad->getExtensionType(); + if ((ALoadExtTy == ISD::ZEXTLOAD && ExtLoadType == ISD::SEXTLOAD) || + (ALoadExtTy == ISD::SEXTLOAD && ExtLoadType == ISD::ZEXTLOAD)) + return {}; + + EVT OrigVT = ALoad->getValueType(0); + assert(OrigVT.getSizeInBits() < VT.getSizeInBits() && "VT should be wider."); + auto *NewALoad = cast<AtomicSDNode>(DAG.getAtomic( + ISD::ATOMIC_LOAD, SDLoc(ALoad), MemoryVT, VT, ALoad->getChain(), + ALoad->getBasePtr(), ALoad->getMemOperand())); + NewALoad->setExtensionType(ExtLoadType); + DAG.ReplaceAllUsesOfValueWith( + SDValue(ALoad, 0), + DAG.getNode(ISD::TRUNCATE, SDLoc(ALoad), OrigVT, SDValue(NewALoad, 0))); + // Update the chain uses. + DAG.ReplaceAllUsesOfValueWith(SDValue(ALoad, 1), SDValue(NewALoad, 1)); + return SDValue(NewALoad, 0); +} + static SDValue foldExtendedSignBitTest(SDNode *N, SelectionDAG &DAG, bool LegalOperations) { assert((N->getOpcode() == ISD::SIGN_EXTEND || @@ -13415,6 +13451,11 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) { DAG, *this, TLI, VT, LegalOperations, N, N0, ISD::SEXTLOAD)) return foldedExt; + // Try to simplify (sext (atomic_load x)). + if (SDValue foldedExt = + tryToFoldExtOfAtomicLoad(DAG, TLI, VT, N0, ISD::SEXTLOAD)) + return foldedExt; + // fold (sext (and/or/xor (load x), cst)) -> // (and/or/xor (sextload x), (sext cst)) if (ISD::isBitwiseLogicOp(N0.getOpcode()) && @@ -13726,6 +13767,11 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { if (SDValue ExtLoad = CombineExtLoad(N)) return ExtLoad; + // Try to simplify (zext (atomic_load x)). + if (SDValue foldedExt = + tryToFoldExtOfAtomicLoad(DAG, TLI, VT, N0, ISD::ZEXTLOAD)) + return foldedExt; + // fold (zext (and/or/xor (load x), cst)) -> // (and/or/xor (zextload x), (zext cst)) // Unless (and (load x) cst) will match as a zextload already and has @@ -13850,11 +13896,20 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { if (N0.getOpcode() == ISD::SHL) { // If the original shl may be shifting out bits, do not perform this // transformation. - // TODO: Add MaskedValueIsZero check. unsigned KnownZeroBits = ShVal.getValueSizeInBits() - ShVal.getOperand(0).getValueSizeInBits(); - if (ShAmtC->getAPIntValue().ugt(KnownZeroBits)) - return SDValue(); + if (ShAmtC->getAPIntValue().ugt(KnownZeroBits)) { + // If the shift is too large, then see if we can deduce that the + // shift is safe anyway. + // Create a mask that has ones for the bits being shifted out. + APInt ShiftOutMask = + APInt::getHighBitsSet(ShVal.getValueSizeInBits(), + ShAmtC->getAPIntValue().getZExtValue()); + + // Check if the bits being shifted out are known to be zero. + if (!DAG.MaskedValueIsZero(ShVal, ShiftOutMask)) + return SDValue(); + } } // Ensure that the shift amount is wide enough for the shifted value. @@ -14655,6 +14710,7 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { EVT VT = N->getValueType(0); EVT SrcVT = N0.getValueType(); bool isLE = DAG.getDataLayout().isLittleEndian(); + SDLoc DL(N); // trunc(undef) = undef if (N0.isUndef()) @@ -14662,10 +14718,10 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { // fold (truncate (truncate x)) -> (truncate x) if (N0.getOpcode() == ISD::TRUNCATE) - return DAG.getNode(ISD::TRUNCATE, SDLoc(N), VT, N0.getOperand(0)); + return DAG.getNode(ISD::TRUNCATE, DL, VT, N0.getOperand(0)); // fold (truncate c1) -> c1 - if (SDValue C = DAG.FoldConstantArithmetic(ISD::TRUNCATE, SDLoc(N), VT, {N0})) + if (SDValue C = DAG.FoldConstantArithmetic(ISD::TRUNCATE, DL, VT, {N0})) return C; // fold (truncate (ext x)) -> (ext x) or (truncate x) or x @@ -14674,10 +14730,10 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { N0.getOpcode() == ISD::ANY_EXTEND) { // if the source is smaller than the dest, we still need an extend. if (N0.getOperand(0).getValueType().bitsLT(VT)) - return DAG.getNode(N0.getOpcode(), SDLoc(N), VT, N0.getOperand(0)); + return DAG.getNode(N0.getOpcode(), DL, VT, N0.getOperand(0)); // if the source is larger than the dest, than we just need the truncate. if (N0.getOperand(0).getValueType().bitsGT(VT)) - return DAG.getNode(ISD::TRUNCATE, SDLoc(N), VT, N0.getOperand(0)); + return DAG.getNode(ISD::TRUNCATE, DL, VT, N0.getOperand(0)); // if the source and dest are the same type, we can drop both the extend // and the truncate. return N0.getOperand(0); @@ -14691,8 +14747,8 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { SDValue ExtVal = N0.getOperand(1); EVT ExtVT = cast<VTSDNode>(ExtVal)->getVT(); if (ExtVT.bitsLT(VT) && TLI.preferSextInRegOfTruncate(VT, SrcVT, ExtVT)) { - SDValue TrX = DAG.getNode(ISD::TRUNCATE, SDLoc(N), VT, X); - return DAG.getNode(ISD::SIGN_EXTEND_INREG, SDLoc(N), VT, TrX, ExtVal); + SDValue TrX = DAG.getNode(ISD::TRUNCATE, DL, VT, X); + return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, TrX, ExtVal); } } @@ -14727,8 +14783,6 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { if (isa<ConstantSDNode>(EltNo) && isTypeLegal(NVT)) { int Elt = EltNo->getAsZExtVal(); int Index = isLE ? (Elt*SizeRatio) : (Elt*SizeRatio + (SizeRatio-1)); - - SDLoc DL(N); return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, TrTy, DAG.getBitcast(NVT, N0.getOperand(0)), DAG.getVectorIdxConstant(Index, DL)); @@ -14743,7 +14797,7 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { SDValue Cond = N0.getOperand(0); SDValue TruncOp0 = DAG.getNode(ISD::TRUNCATE, SL, VT, N0.getOperand(1)); SDValue TruncOp1 = DAG.getNode(ISD::TRUNCATE, SL, VT, N0.getOperand(2)); - return DAG.getNode(ISD::SELECT, SDLoc(N), VT, Cond, TruncOp0, TruncOp1); + return DAG.getNode(ISD::SELECT, DL, VT, Cond, TruncOp0, TruncOp1); } } @@ -14755,22 +14809,20 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { KnownBits Known = DAG.computeKnownBits(Amt); unsigned Size = VT.getScalarSizeInBits(); if (Known.countMaxActiveBits() <= Log2_32(Size)) { - SDLoc SL(N); EVT AmtVT = TLI.getShiftAmountTy(VT, DAG.getDataLayout()); - - SDValue Trunc = DAG.getNode(ISD::TRUNCATE, SL, VT, N0.getOperand(0)); + SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, VT, N0.getOperand(0)); if (AmtVT != Amt.getValueType()) { - Amt = DAG.getZExtOrTrunc(Amt, SL, AmtVT); + Amt = DAG.getZExtOrTrunc(Amt, DL, AmtVT); AddToWorklist(Amt.getNode()); } - return DAG.getNode(ISD::SHL, SL, VT, Trunc, Amt); + return DAG.getNode(ISD::SHL, DL, VT, Trunc, Amt); } } - if (SDValue V = foldSubToUSubSat(VT, N0.getNode())) + if (SDValue V = foldSubToUSubSat(VT, N0.getNode(), DL)) return V; - if (SDValue ABD = foldABSToABD(N)) + if (SDValue ABD = foldABSToABD(N, DL)) return ABD; // Attempt to pre-truncate BUILD_VECTOR sources. @@ -14779,7 +14831,6 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { TLI.isTruncateFree(SrcVT.getScalarType(), VT.getScalarType()) && // Avoid creating illegal types if running after type legalizer. (!LegalTypes || TLI.isTypeLegal(VT.getScalarType()))) { - SDLoc DL(N); EVT SVT = VT.getScalarType(); SmallVector<SDValue, 8> TruncOps; for (const SDValue &Op : N0->op_values()) { @@ -14793,7 +14844,6 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { if (N0.getOpcode() == ISD::SPLAT_VECTOR && (!LegalTypes || TLI.isTypeLegal(VT.getScalarType())) && (!LegalOperations || TLI.isOperationLegal(ISD::SPLAT_VECTOR, VT))) { - SDLoc DL(N); EVT SVT = VT.getScalarType(); return DAG.getSplatVector( VT, DL, DAG.getNode(ISD::TRUNCATE, DL, SVT, N0->getOperand(0))); @@ -14825,7 +14875,7 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { for (unsigned i = 0, e = BuildVecNumElts; i != e; i += TruncEltOffset) Opnds.push_back(BuildVect.getOperand(i)); - return DAG.getBuildVector(VT, SDLoc(N), Opnds); + return DAG.getBuildVector(VT, DL, Opnds); } } @@ -14888,7 +14938,7 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { AddToWorklist(NV.getNode()); Opnds.push_back(NV); } - return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), VT, Opnds); + return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Opnds); } } @@ -14902,11 +14952,9 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { if (VecSrcVT.isVector() && VecSrcVT.getScalarType() == VT && (!LegalOperations || TLI.isOperationLegal(ISD::EXTRACT_VECTOR_ELT, VecSrcVT))) { - SDLoc SL(N); - unsigned Idx = isLE ? 0 : VecSrcVT.getVectorNumElements() - 1; - return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, VT, VecSrc, - DAG.getVectorIdxConstant(Idx, SL)); + return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, VecSrc, + DAG.getVectorIdxConstant(Idx, DL)); } } @@ -14951,7 +14999,6 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { // we are extra cautious to not create an unsupported operation. // Target-specific changes are likely needed to avoid regressions here. if (VT.isScalarInteger() || TLI.isOperationLegal(N0.getOpcode(), VT)) { - SDLoc DL(N); SDValue NarrowL = DAG.getNode(ISD::TRUNCATE, DL, VT, N0.getOperand(0)); SDValue NarrowR = DAG.getNode(ISD::TRUNCATE, DL, VT, N0.getOperand(1)); return DAG.getNode(N0.getOpcode(), DL, VT, NarrowL, NarrowR); @@ -14968,7 +15015,6 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { if (((!LegalOperations && N0.getOpcode() == ISD::UADDO_CARRY) || TLI.isOperationLegal(N0.getOpcode(), VT)) && N0.hasOneUse() && !N0->hasAnyUseOfValue(1)) { - SDLoc DL(N); SDValue X = DAG.getNode(ISD::TRUNCATE, DL, VT, N0.getOperand(0)); SDValue Y = DAG.getNode(ISD::TRUNCATE, DL, VT, N0.getOperand(1)); SDVTList VTs = DAG.getVTList(VT, N0->getValueType(1)); @@ -14985,7 +15031,7 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) { VT.getScalarSizeInBits() && hasOperation(N0.getOpcode(), VT)) { return getTruncatedUSUBSAT(VT, SrcVT, N0.getOperand(0), N0.getOperand(1), - DAG, SDLoc(N)); + DAG, DL); } break; } @@ -22479,17 +22525,16 @@ SDValue DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *N) { // -> extract_vector_elt b, 0 // extract_vector_elt (concat_vectors v2i16:a, v2i16:b), 3 // -> extract_vector_elt b, 1 - SDLoc SL(N); EVT ConcatVT = VecOp.getOperand(0).getValueType(); unsigned ConcatNumElts = ConcatVT.getVectorNumElements(); - SDValue NewIdx = DAG.getConstant(Elt % ConcatNumElts, SL, + SDValue NewIdx = DAG.getConstant(Elt % ConcatNumElts, DL, Index.getValueType()); SDValue ConcatOp = VecOp.getOperand(Elt / ConcatNumElts); - SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, + SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, ConcatVT.getVectorElementType(), ConcatOp, NewIdx); - return DAG.getNode(ISD::BITCAST, SL, ScalarVT, Elt); + return DAG.getNode(ISD::BITCAST, DL, ScalarVT, Elt); } // Make sure we found a non-volatile load and the extractelement is @@ -23466,9 +23511,7 @@ static SDValue combineConcatVectorOfScalars(SDNode *N, SelectionDAG &DAG) { SDLoc DL(N); EVT VT = N->getValueType(0); SmallVector<SDValue, 8> Ops; - EVT SVT = EVT::getIntegerVT(*DAG.getContext(), OpVT.getSizeInBits()); - SDValue ScalarUndef = DAG.getNode(ISD::UNDEF, DL, SVT); // Keep track of what we encounter. bool AnyInteger = false; @@ -23478,7 +23521,7 @@ static SDValue combineConcatVectorOfScalars(SDNode *N, SelectionDAG &DAG) { !Op.getOperand(0).getValueType().isVector()) Ops.push_back(Op.getOperand(0)); else if (ISD::UNDEF == Op.getOpcode()) - Ops.push_back(ScalarUndef); + Ops.push_back(DAG.getNode(ISD::UNDEF, DL, SVT)); else return SDValue(); @@ -23498,13 +23541,12 @@ static SDValue combineConcatVectorOfScalars(SDNode *N, SelectionDAG &DAG) { // Replace UNDEFs by another scalar UNDEF node, of the final desired type. if (AnyFP) { SVT = EVT::getFloatingPointVT(OpVT.getSizeInBits()); - ScalarUndef = DAG.getNode(ISD::UNDEF, DL, SVT); if (AnyInteger) { for (SDValue &Op : Ops) { if (Op.getValueType() == SVT) continue; if (Op.isUndef()) - Op = ScalarUndef; + Op = DAG.getNode(ISD::UNDEF, DL, SVT); else Op = DAG.getBitcast(SVT, Op); } @@ -24217,7 +24259,7 @@ static SDValue narrowExtractedVectorLoad(SDNode *Extract, SelectionDAG &DAG) { // TODO: Use "BaseIndexOffset" to make this more effective. SDValue NewAddr = DAG.getMemBasePlusOffset(Ld->getBasePtr(), Offset, DL); - uint64_t StoreSize = MemoryLocation::getSizeOrUnknown(VT.getStoreSize()); + LocationSize StoreSize = LocationSize::precise(VT.getStoreSize()); MachineFunction &MF = DAG.getMachineFunction(); MachineMemOperand *MMO; if (Offset.isScalable()) { @@ -26137,6 +26179,13 @@ SDValue DAGCombiner::visitINSERT_SUBVECTOR(SDNode *N) { } } + // Handle case where we've ended up inserting back into the source vector + // we extracted the subvector from. + // insert_subvector(N0, extract_subvector(N0, N2), N2) --> N0 + if (N1.getOpcode() == ISD::EXTRACT_SUBVECTOR && N1.getOperand(0) == N0 && + N1.getOperand(1) == N2) + return N0; + // Simplify scalar inserts into an undef vector: // insert_subvector undef, (splat X), N2 -> splat X if (N0.isUndef() && N1.getOpcode() == ISD::SPLAT_VECTOR) @@ -27862,15 +27911,10 @@ bool DAGCombiner::mayAlias(SDNode *Op0, SDNode *Op1) const { : (LSN->getAddressingMode() == ISD::PRE_DEC) ? -1 * C->getSExtValue() : 0; - uint64_t Size = - MemoryLocation::getSizeOrUnknown(LSN->getMemoryVT().getStoreSize()); - return {LSN->isVolatile(), - LSN->isAtomic(), - LSN->getBasePtr(), - Offset /*base offset*/, - Size != ~UINT64_C(0) ? LocationSize::precise(Size) - : LocationSize::beforeOrAfterPointer(), - LSN->getMemOperand()}; + TypeSize Size = LSN->getMemoryVT().getStoreSize(); + return {LSN->isVolatile(), LSN->isAtomic(), + LSN->getBasePtr(), Offset /*base offset*/, + LocationSize::precise(Size), LSN->getMemOperand()}; } if (const auto *LN = cast<LifetimeSDNode>(N)) return {false /*isVolatile*/, @@ -27912,6 +27956,13 @@ bool DAGCombiner::mayAlias(SDNode *Op0, SDNode *Op1) const { return false; } + // If NumBytes is scalable and offset is not 0, conservatively return may + // alias + if ((MUC0.NumBytes.hasValue() && MUC0.NumBytes.isScalable() && + MUC0.Offset != 0) || + (MUC1.NumBytes.hasValue() && MUC1.NumBytes.isScalable() && + MUC1.Offset != 0)) + return true; // Try to prove that there is aliasing, or that there is no aliasing. Either // way, we can return now. If nothing can be proved, proceed with more tests. bool IsAlias; @@ -27942,18 +27993,22 @@ bool DAGCombiner::mayAlias(SDNode *Op0, SDNode *Op1) const { Align OrigAlignment1 = MUC1.MMO->getBaseAlign(); LocationSize Size0 = MUC0.NumBytes; LocationSize Size1 = MUC1.NumBytes; + if (OrigAlignment0 == OrigAlignment1 && SrcValOffset0 != SrcValOffset1 && - Size0.hasValue() && Size1.hasValue() && Size0 == Size1 && - OrigAlignment0 > Size0.getValue() && - SrcValOffset0 % Size0.getValue() == 0 && - SrcValOffset1 % Size1.getValue() == 0) { + Size0.hasValue() && Size1.hasValue() && !Size0.isScalable() && + !Size1.isScalable() && Size0 == Size1 && + OrigAlignment0 > Size0.getValue().getKnownMinValue() && + SrcValOffset0 % Size0.getValue().getKnownMinValue() == 0 && + SrcValOffset1 % Size1.getValue().getKnownMinValue() == 0) { int64_t OffAlign0 = SrcValOffset0 % OrigAlignment0.value(); int64_t OffAlign1 = SrcValOffset1 % OrigAlignment1.value(); // There is no overlap between these relatively aligned accesses of // similar size. Return no alias. - if ((OffAlign0 + (int64_t)Size0.getValue()) <= OffAlign1 || - (OffAlign1 + (int64_t)Size1.getValue()) <= OffAlign0) + if ((OffAlign0 + static_cast<int64_t>( + Size0.getValue().getKnownMinValue())) <= OffAlign1 || + (OffAlign1 + static_cast<int64_t>( + Size1.getValue().getKnownMinValue())) <= OffAlign0) return false; } @@ -27970,12 +28025,18 @@ bool DAGCombiner::mayAlias(SDNode *Op0, SDNode *Op1) const { Size0.hasValue() && Size1.hasValue()) { // Use alias analysis information. int64_t MinOffset = std::min(SrcValOffset0, SrcValOffset1); - int64_t Overlap0 = Size0.getValue() + SrcValOffset0 - MinOffset; - int64_t Overlap1 = Size1.getValue() + SrcValOffset1 - MinOffset; + int64_t Overlap0 = + Size0.getValue().getKnownMinValue() + SrcValOffset0 - MinOffset; + int64_t Overlap1 = + Size1.getValue().getKnownMinValue() + SrcValOffset1 - MinOffset; + LocationSize Loc0 = + Size0.isScalable() ? Size0 : LocationSize::precise(Overlap0); + LocationSize Loc1 = + Size1.isScalable() ? Size1 : LocationSize::precise(Overlap1); if (AA->isNoAlias( - MemoryLocation(MUC0.MMO->getValue(), Overlap0, + MemoryLocation(MUC0.MMO->getValue(), Loc0, UseTBAA ? MUC0.MMO->getAAInfo() : AAMDNodes()), - MemoryLocation(MUC1.MMO->getValue(), Overlap1, + MemoryLocation(MUC1.MMO->getValue(), Loc1, UseTBAA ? MUC1.MMO->getAAInfo() : AAMDNodes()))) return false; } diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp index cce91dbd9531c9f993861051baebb9fa811e80c0..aefedd060f897dfb527931ef15fb715090828cfa 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -752,17 +752,25 @@ FastISel::CallLoweringInfo &FastISel::CallLoweringInfo::setCallee( } bool FastISel::selectPatchpoint(const CallInst *I) { - // void|i64 @llvm.experimental.patchpoint.void|i64(i64 <id>, - // i32 <numBytes>, - // i8* <target>, - // i32 <numArgs>, - // [Args...], - // [live variables...]) + // <ty> @llvm.experimental.patchpoint.<ty>(i64 <id>, + // i32 <numBytes>, + // i8* <target>, + // i32 <numArgs>, + // [Args...], + // [live variables...]) CallingConv::ID CC = I->getCallingConv(); bool IsAnyRegCC = CC == CallingConv::AnyReg; bool HasDef = !I->getType()->isVoidTy(); Value *Callee = I->getOperand(PatchPointOpers::TargetPos)->stripPointerCasts(); + // Check if we can lower the return type when using anyregcc. + MVT ValueType; + if (IsAnyRegCC && HasDef) { + ValueType = TLI.getSimpleValueType(DL, I->getType(), /*AllowUnknown=*/true); + if (ValueType == MVT::Other) + return false; + } + // Get the real number of arguments participating in the call <numArgs> assert(isa<ConstantInt>(I->getOperand(PatchPointOpers::NArgPos)) && "Expected a constant integer."); @@ -790,7 +798,8 @@ bool FastISel::selectPatchpoint(const CallInst *I) { // Add an explicit result reg if we use the anyreg calling convention. if (IsAnyRegCC && HasDef) { assert(CLI.NumResultRegs == 0 && "Unexpected result register."); - CLI.ResultReg = createResultReg(TLI.getRegClassFor(MVT::i64)); + assert(ValueType.isValid()); + CLI.ResultReg = createResultReg(TLI.getRegClassFor(ValueType)); CLI.NumResultRegs = 1; Ops.push_back(MachineOperand::CreateReg(CLI.ResultReg, /*isDef=*/true)); } @@ -1192,40 +1201,40 @@ void FastISel::handleDbgInfo(const Instruction *II) { flushLocalValueMap(); recomputeInsertPt(); - if (DPLabel *DPL = dyn_cast<DPLabel>(&DR)) { - assert(DPL->getLabel() && "Missing label"); + if (DbgLabelRecord *DLR = dyn_cast<DbgLabelRecord>(&DR)) { + assert(DLR->getLabel() && "Missing label"); if (!FuncInfo.MF->getMMI().hasDebugInfo()) { - LLVM_DEBUG(dbgs() << "Dropping debug info for " << *DPL << "\n"); + LLVM_DEBUG(dbgs() << "Dropping debug info for " << *DLR << "\n"); continue; } - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DPL->getDebugLoc(), + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DLR->getDebugLoc(), TII.get(TargetOpcode::DBG_LABEL)) - .addMetadata(DPL->getLabel()); + .addMetadata(DLR->getLabel()); continue; } - DPValue &DPV = cast<DPValue>(DR); + DbgVariableRecord &DVR = cast<DbgVariableRecord>(DR); Value *V = nullptr; - if (!DPV.hasArgList()) - V = DPV.getVariableLocationOp(0); + if (!DVR.hasArgList()) + V = DVR.getVariableLocationOp(0); bool Res = false; - if (DPV.getType() == DPValue::LocationType::Value || - DPV.getType() == DPValue::LocationType::Assign) { - Res = lowerDbgValue(V, DPV.getExpression(), DPV.getVariable(), - DPV.getDebugLoc()); + if (DVR.getType() == DbgVariableRecord::LocationType::Value || + DVR.getType() == DbgVariableRecord::LocationType::Assign) { + Res = lowerDbgValue(V, DVR.getExpression(), DVR.getVariable(), + DVR.getDebugLoc()); } else { - assert(DPV.getType() == DPValue::LocationType::Declare); - if (FuncInfo.PreprocessedDPVDeclares.contains(&DPV)) + assert(DVR.getType() == DbgVariableRecord::LocationType::Declare); + if (FuncInfo.PreprocessedDVRDeclares.contains(&DVR)) continue; - Res = lowerDbgDeclare(V, DPV.getExpression(), DPV.getVariable(), - DPV.getDebugLoc()); + Res = lowerDbgDeclare(V, DVR.getExpression(), DVR.getVariable(), + DVR.getDebugLoc()); } if (!Res) - LLVM_DEBUG(dbgs() << "Dropping debug-info for " << DPV << "\n";); + LLVM_DEBUG(dbgs() << "Dropping debug-info for " << DVR << "\n";); } } @@ -1452,6 +1461,15 @@ bool FastISel::selectIntrinsicCall(const IntrinsicInst *II) { case Intrinsic::is_constant: llvm_unreachable("llvm.is.constant.* should have been lowered already"); + case Intrinsic::allow_runtime_check: + case Intrinsic::allow_ubsan_check: { + Register ResultReg = getRegForValue(ConstantInt::getTrue(II->getType())); + if (!ResultReg) + return false; + updateValueMap(II, ResultReg); + return true; + } + case Intrinsic::launder_invariant_group: case Intrinsic::strip_invariant_group: case Intrinsic::expect: { @@ -1464,7 +1482,7 @@ bool FastISel::selectIntrinsicCall(const IntrinsicInst *II) { case Intrinsic::experimental_stackmap: return selectStackmap(II); case Intrinsic::experimental_patchpoint_void: - case Intrinsic::experimental_patchpoint_i64: + case Intrinsic::experimental_patchpoint: return selectPatchpoint(II); case Intrinsic::xray_customevent: diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index e01cd8cbf925a20ee9b04b380442b379870a1d1a..8fb6b11b8805c577a89cefcd6488b7715a27976f 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -358,7 +358,7 @@ void FunctionLoweringInfo::clear() { StatepointRelocationMaps.clear(); PreferredExtendType.clear(); PreprocessedDbgDeclares.clear(); - PreprocessedDPVDeclares.clear(); + PreprocessedDVRDeclares.clear(); } /// CreateReg - Allocate a single virtual register for the given type. diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 2dccc45c803a050cd427e757b50fc9d9abbaa4bc..24f69ea1b742a67e6dd8f1204896ebdb74d8ee02 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -118,14 +118,7 @@ private: void LegalizeLoadOps(SDNode *Node); void LegalizeStoreOps(SDNode *Node); - /// Some targets cannot handle a variable - /// insertion index for the INSERT_VECTOR_ELT instruction. In this case, it - /// is necessary to spill the vector being inserted into to memory, perform - /// the insert there, and then read the result back. - SDValue PerformInsertVectorEltInMemory(SDValue Vec, SDValue Val, SDValue Idx, - const SDLoc &dl); - SDValue ExpandINSERT_VECTOR_ELT(SDValue Vec, SDValue Val, SDValue Idx, - const SDLoc &dl); + SDValue ExpandINSERT_VECTOR_ELT(SDValue Op); /// Return a vector shuffle operation which /// performs the same shuffe in terms of order or result bytes, but on a type @@ -267,7 +260,9 @@ static MachineMemOperand *getStackAlignedMMO(SDValue StackPtr, auto &MFI = MF.getFrameInfo(); int FI = cast<FrameIndexSDNode>(StackPtr)->getIndex(); MachinePointerInfo PtrInfo = MachinePointerInfo::getFixedStack(MF, FI); - uint64_t ObjectSize = isObjectScalable ? ~UINT64_C(0) : MFI.getObjectSize(FI); + LocationSize ObjectSize = isObjectScalable + ? LocationSize::beforeOrAfterPointer() + : LocationSize::precise(MFI.getObjectSize(FI)); return MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOStore, ObjectSize, MFI.getObjectAlign(FI)); } @@ -376,49 +371,12 @@ SDValue SelectionDAGLegalize::ExpandConstant(ConstantSDNode *CP) { return Result; } -/// Some target cannot handle a variable insertion index for the -/// INSERT_VECTOR_ELT instruction. In this case, it -/// is necessary to spill the vector being inserted into to memory, perform -/// the insert there, and then read the result back. -SDValue SelectionDAGLegalize::PerformInsertVectorEltInMemory(SDValue Vec, - SDValue Val, - SDValue Idx, - const SDLoc &dl) { - SDValue Tmp1 = Vec; - SDValue Tmp2 = Val; - SDValue Tmp3 = Idx; - - // If the target doesn't support this, we have to spill the input vector - // to a temporary stack slot, update the element, then reload it. This is - // badness. We could also load the value into a vector register (either - // with a "move to register" or "extload into register" instruction, then - // permute it into place, if the idx is a constant and if the idx is - // supported by the target. - EVT VT = Tmp1.getValueType(); - EVT EltVT = VT.getVectorElementType(); - SDValue StackPtr = DAG.CreateStackTemporary(VT); - - int SPFI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex(); - - // Store the vector. - SDValue Ch = DAG.getStore( - DAG.getEntryNode(), dl, Tmp1, StackPtr, - MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), SPFI)); - - SDValue StackPtr2 = TLI.getVectorElementPointer(DAG, StackPtr, VT, Tmp3); - - // Store the scalar value. - Ch = DAG.getTruncStore( - Ch, dl, Tmp2, StackPtr2, - MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()), EltVT); - // Load the updated vector. - return DAG.getLoad(VT, dl, Ch, StackPtr, MachinePointerInfo::getFixedStack( - DAG.getMachineFunction(), SPFI)); -} +SDValue SelectionDAGLegalize::ExpandINSERT_VECTOR_ELT(SDValue Op) { + SDValue Vec = Op.getOperand(0); + SDValue Val = Op.getOperand(1); + SDValue Idx = Op.getOperand(2); + SDLoc dl(Op); -SDValue SelectionDAGLegalize::ExpandINSERT_VECTOR_ELT(SDValue Vec, SDValue Val, - SDValue Idx, - const SDLoc &dl) { if (ConstantSDNode *InsertPos = dyn_cast<ConstantSDNode>(Idx)) { // SCALAR_TO_VECTOR requires that the type of the value being inserted // match the element type of the vector being created, except for @@ -440,7 +398,7 @@ SDValue SelectionDAGLegalize::ExpandINSERT_VECTOR_ELT(SDValue Vec, SDValue Val, return DAG.getVectorShuffle(Vec.getValueType(), dl, Vec, ScVec, ShufOps); } } - return PerformInsertVectorEltInMemory(Vec, Val, Idx, dl); + return ExpandInsertToVectorThroughStack(Op); } SDValue SelectionDAGLegalize::OptimizeFloatStore(StoreSDNode* ST) { @@ -1488,7 +1446,7 @@ SDValue SelectionDAGLegalize::ExpandInsertToVectorThroughStack(SDValue Op) { // Store the value to a temporary stack slot, then LOAD the returned part. EVT VecVT = Vec.getValueType(); - EVT SubVecVT = Part.getValueType(); + EVT PartVT = Part.getValueType(); SDValue StackPtr = DAG.CreateStackTemporary(VecVT); int FI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex(); MachinePointerInfo PtrInfo = @@ -1497,14 +1455,28 @@ SDValue SelectionDAGLegalize::ExpandInsertToVectorThroughStack(SDValue Op) { // First store the whole vector. SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo); + // Freeze the index so we don't poison the clamping code we're about to emit. + Idx = DAG.getFreeze(Idx); + // Then store the inserted part. - SDValue SubStackPtr = - TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVecVT, Idx); + if (PartVT.isVector()) { + SDValue SubStackPtr = + TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, PartVT, Idx); + + // Store the subvector. + Ch = DAG.getStore( + Ch, dl, Part, SubStackPtr, + MachinePointerInfo::getUnknownStack(DAG.getMachineFunction())); + } else { + SDValue SubStackPtr = + TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx); - // Store the subvector. - Ch = DAG.getStore( - Ch, dl, Part, SubStackPtr, - MachinePointerInfo::getUnknownStack(DAG.getMachineFunction())); + // Store the scalar value. + Ch = DAG.getTruncStore( + Ch, dl, Part, SubStackPtr, + MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()), + VecVT.getVectorElementType()); + } // Finally, load the updated vector. return DAG.getLoad(Op.getValueType(), dl, Ch, StackPtr, PtrInfo); @@ -3418,9 +3390,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) { Results.push_back(ExpandSCALAR_TO_VECTOR(Node)); break; case ISD::INSERT_VECTOR_ELT: - Results.push_back(ExpandINSERT_VECTOR_ELT(Node->getOperand(0), - Node->getOperand(1), - Node->getOperand(2), dl)); + Results.push_back(ExpandINSERT_VECTOR_ELT(SDValue(Node, 0))); break; case ISD::VECTOR_SHUFFLE: { SmallVector<int, 32> NewMask; diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 909c669abd120bab562e9d99d342212bfcab884e..93ce9c22af5525fd65473dea85760f14f5fee1f7 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -349,6 +349,26 @@ SDValue DAGTypeLegalizer::PromoteIntRes_Atomic0(AtomicSDNode *N) { N->getMemoryVT(), ResVT, N->getChain(), N->getBasePtr(), N->getMemOperand()); + if (N->getOpcode() == ISD::ATOMIC_LOAD) { + ISD::LoadExtType ETy = cast<AtomicSDNode>(N)->getExtensionType(); + if (ETy == ISD::NON_EXTLOAD) { + switch (TLI.getExtendForAtomicOps()) { + case ISD::SIGN_EXTEND: + ETy = ISD::SEXTLOAD; + break; + case ISD::ZERO_EXTEND: + ETy = ISD::ZEXTLOAD; + break; + case ISD::ANY_EXTEND: + ETy = ISD::EXTLOAD; + break; + default: + llvm_unreachable("Invalid atomic op extension"); + } + } + cast<AtomicSDNode>(Res)->setExtensionType(ETy); + } + // Legalize the chain result - switch anything that used the old chain to // use the new one. ReplaceValueWith(SDValue(N, 1), Res.getValue(1)); @@ -4527,6 +4547,7 @@ void DAGTypeLegalizer::ExpandIntRes_ShiftThroughStack(SDNode *N, SDValue &Lo, void DAGTypeLegalizer::ExpandIntRes_Shift(SDNode *N, SDValue &Lo, SDValue &Hi) { EVT VT = N->getValueType(0); + unsigned Opc = N->getOpcode(); SDLoc dl(N); // If we can emit an efficient shift operation, do so now. Check to see if @@ -4541,12 +4562,12 @@ void DAGTypeLegalizer::ExpandIntRes_Shift(SDNode *N, // If this target supports shift_PARTS, use it. First, map to the _PARTS opc. unsigned PartsOpc; - if (N->getOpcode() == ISD::SHL) { + if (Opc == ISD::SHL) { PartsOpc = ISD::SHL_PARTS; - } else if (N->getOpcode() == ISD::SRL) { + } else if (Opc == ISD::SRL) { PartsOpc = ISD::SRL_PARTS; } else { - assert(N->getOpcode() == ISD::SRA && "Unknown shift!"); + assert(Opc == ISD::SRA && "Unknown shift!"); PartsOpc = ISD::SRA_PARTS; } @@ -4599,7 +4620,7 @@ void DAGTypeLegalizer::ExpandIntRes_Shift(SDNode *N, // Otherwise, emit a libcall. RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; bool isSigned; - if (N->getOpcode() == ISD::SHL) { + if (Opc == ISD::SHL) { isSigned = false; /*sign irrelevant*/ if (VT == MVT::i16) LC = RTLIB::SHL_I16; @@ -4609,7 +4630,7 @@ void DAGTypeLegalizer::ExpandIntRes_Shift(SDNode *N, LC = RTLIB::SHL_I64; else if (VT == MVT::i128) LC = RTLIB::SHL_I128; - } else if (N->getOpcode() == ISD::SRL) { + } else if (Opc == ISD::SRL) { isSigned = false; if (VT == MVT::i16) LC = RTLIB::SRL_I16; @@ -4620,7 +4641,7 @@ void DAGTypeLegalizer::ExpandIntRes_Shift(SDNode *N, else if (VT == MVT::i128) LC = RTLIB::SRL_I128; } else { - assert(N->getOpcode() == ISD::SRA && "Unknown shift!"); + assert(Opc == ISD::SRA && "Unknown shift!"); isSigned = true; if (VT == MVT::i16) LC = RTLIB::SRA_I16; diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp index 5fb9d8d07d1514edaf6a607964be317a7a6f3332..1f6e0097f31ab440e9471fdd5441f4ce0a3b4f96 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -1967,7 +1967,8 @@ void DAGTypeLegalizer::SplitVecRes_VP_LOAD(VPLoadSDNode *LD, SDValue &Lo, MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( LD->getPointerInfo(), MachineMemOperand::MOLoad, - MemoryLocation::UnknownSize, Alignment, LD->getAAInfo(), LD->getRanges()); + LocationSize::beforeOrAfterPointer(), Alignment, LD->getAAInfo(), + LD->getRanges()); Lo = DAG.getLoadVP(LD->getAddressingMode(), ExtType, LoVT, dl, Ch, Ptr, Offset, @@ -1990,8 +1991,8 @@ void DAGTypeLegalizer::SplitVecRes_VP_LOAD(VPLoadSDNode *LD, SDValue &Lo, LoMemVT.getStoreSize().getFixedValue()); MMO = DAG.getMachineFunction().getMachineMemOperand( - MPI, MachineMemOperand::MOLoad, MemoryLocation::UnknownSize, Alignment, - LD->getAAInfo(), LD->getRanges()); + MPI, MachineMemOperand::MOLoad, LocationSize::beforeOrAfterPointer(), + Alignment, LD->getAAInfo(), LD->getRanges()); Hi = DAG.getLoadVP(LD->getAddressingMode(), ExtType, HiVT, dl, Ch, Ptr, Offset, MaskHi, EVLHi, HiMemVT, MMO, @@ -2070,8 +2071,8 @@ void DAGTypeLegalizer::SplitVecRes_VP_STRIDED_LOAD(VPStridedLoadSDNode *SLD, MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( MachinePointerInfo(SLD->getPointerInfo().getAddrSpace()), - MachineMemOperand::MOLoad, MemoryLocation::UnknownSize, Alignment, - SLD->getAAInfo(), SLD->getRanges()); + MachineMemOperand::MOLoad, LocationSize::beforeOrAfterPointer(), + Alignment, SLD->getAAInfo(), SLD->getRanges()); Hi = DAG.getStridedLoadVP(SLD->getAddressingMode(), SLD->getExtensionType(), HiVT, DL, SLD->getChain(), Ptr, SLD->getOffset(), @@ -2130,7 +2131,7 @@ void DAGTypeLegalizer::SplitVecRes_MLOAD(MaskedLoadSDNode *MLD, MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( MLD->getPointerInfo(), MachineMemOperand::MOLoad, - MemoryLocation::UnknownSize, Alignment, MLD->getAAInfo(), + LocationSize::beforeOrAfterPointer(), Alignment, MLD->getAAInfo(), MLD->getRanges()); Lo = DAG.getMaskedLoad(LoVT, dl, Ch, Ptr, Offset, MaskLo, PassThruLo, LoMemVT, @@ -2154,8 +2155,8 @@ void DAGTypeLegalizer::SplitVecRes_MLOAD(MaskedLoadSDNode *MLD, LoMemVT.getStoreSize().getFixedValue()); MMO = DAG.getMachineFunction().getMachineMemOperand( - MPI, MachineMemOperand::MOLoad, MemoryLocation::UnknownSize, Alignment, - MLD->getAAInfo(), MLD->getRanges()); + MPI, MachineMemOperand::MOLoad, LocationSize::beforeOrAfterPointer(), + Alignment, MLD->getAAInfo(), MLD->getRanges()); Hi = DAG.getMaskedLoad(HiVT, dl, Ch, Ptr, Offset, MaskHi, PassThruHi, HiMemVT, MMO, MLD->getAddressingMode(), ExtType, @@ -2217,7 +2218,8 @@ void DAGTypeLegalizer::SplitVecRes_Gather(MemSDNode *N, SDValue &Lo, MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( N->getPointerInfo(), MachineMemOperand::MOLoad, - MemoryLocation::UnknownSize, Alignment, N->getAAInfo(), N->getRanges()); + LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(), + N->getRanges()); if (auto *MGT = dyn_cast<MaskedGatherSDNode>(N)) { SDValue PassThru = MGT->getPassThru(); @@ -2884,10 +2886,10 @@ void DAGTypeLegalizer::SplitVecRes_VP_REVERSE(SDNode *N, SDValue &Lo, auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex); MachineMemOperand *StoreMMO = DAG.getMachineFunction().getMachineMemOperand( - PtrInfo, MachineMemOperand::MOStore, MemoryLocation::UnknownSize, + PtrInfo, MachineMemOperand::MOStore, LocationSize::beforeOrAfterPointer(), Alignment); MachineMemOperand *LoadMMO = DAG.getMachineFunction().getMachineMemOperand( - PtrInfo, MachineMemOperand::MOLoad, MemoryLocation::UnknownSize, + PtrInfo, MachineMemOperand::MOLoad, LocationSize::beforeOrAfterPointer(), Alignment); unsigned EltWidth = VT.getScalarSizeInBits() / 8; @@ -3478,7 +3480,8 @@ SDValue DAGTypeLegalizer::SplitVecOp_VP_STORE(VPStoreSDNode *N, unsigned OpNo) { SDValue Lo, Hi; MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( N->getPointerInfo(), MachineMemOperand::MOStore, - MemoryLocation::UnknownSize, Alignment, N->getAAInfo(), N->getRanges()); + LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(), + N->getRanges()); Lo = DAG.getStoreVP(Ch, DL, DataLo, Ptr, Offset, MaskLo, EVLLo, LoMemVT, MMO, N->getAddressingMode(), N->isTruncatingStore(), @@ -3501,8 +3504,8 @@ SDValue DAGTypeLegalizer::SplitVecOp_VP_STORE(VPStoreSDNode *N, unsigned OpNo) { LoMemVT.getStoreSize().getFixedValue()); MMO = DAG.getMachineFunction().getMachineMemOperand( - MPI, MachineMemOperand::MOStore, MemoryLocation::UnknownSize, Alignment, - N->getAAInfo(), N->getRanges()); + MPI, MachineMemOperand::MOStore, LocationSize::beforeOrAfterPointer(), + Alignment, N->getAAInfo(), N->getRanges()); Hi = DAG.getStoreVP(Ch, DL, DataHi, Ptr, Offset, MaskHi, EVLHi, HiMemVT, MMO, N->getAddressingMode(), N->isTruncatingStore(), @@ -3574,8 +3577,8 @@ SDValue DAGTypeLegalizer::SplitVecOp_VP_STRIDED_STORE(VPStridedStoreSDNode *N, MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( MachinePointerInfo(N->getPointerInfo().getAddrSpace()), - MachineMemOperand::MOStore, MemoryLocation::UnknownSize, Alignment, - N->getAAInfo(), N->getRanges()); + MachineMemOperand::MOStore, LocationSize::beforeOrAfterPointer(), + Alignment, N->getAAInfo(), N->getRanges()); SDValue Hi = DAG.getStridedStoreVP( N->getChain(), DL, HiData, Ptr, N->getOffset(), N->getStride(), HiMask, @@ -3626,7 +3629,8 @@ SDValue DAGTypeLegalizer::SplitVecOp_MSTORE(MaskedStoreSDNode *N, SDValue Lo, Hi, Res; MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( N->getPointerInfo(), MachineMemOperand::MOStore, - MemoryLocation::UnknownSize, Alignment, N->getAAInfo(), N->getRanges()); + LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(), + N->getRanges()); Lo = DAG.getMaskedStore(Ch, DL, DataLo, Ptr, Offset, MaskLo, LoMemVT, MMO, N->getAddressingMode(), N->isTruncatingStore(), @@ -3651,8 +3655,8 @@ SDValue DAGTypeLegalizer::SplitVecOp_MSTORE(MaskedStoreSDNode *N, LoMemVT.getStoreSize().getFixedValue()); MMO = DAG.getMachineFunction().getMachineMemOperand( - MPI, MachineMemOperand::MOStore, MemoryLocation::UnknownSize, Alignment, - N->getAAInfo(), N->getRanges()); + MPI, MachineMemOperand::MOStore, LocationSize::beforeOrAfterPointer(), + Alignment, N->getAAInfo(), N->getRanges()); Hi = DAG.getMaskedStore(Ch, DL, DataHi, Ptr, Offset, MaskHi, HiMemVT, MMO, N->getAddressingMode(), N->isTruncatingStore(), @@ -3716,7 +3720,8 @@ SDValue DAGTypeLegalizer::SplitVecOp_Scatter(MemSDNode *N, unsigned OpNo) { SDValue Lo; MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( N->getPointerInfo(), MachineMemOperand::MOStore, - MemoryLocation::UnknownSize, Alignment, N->getAAInfo(), N->getRanges()); + LocationSize::beforeOrAfterPointer(), Alignment, N->getAAInfo(), + N->getRanges()); if (auto *MSC = dyn_cast<MaskedScatterSDNode>(N)) { SDValue OpsLo[] = {Ch, DataLo, MaskLo, Ptr, IndexLo, Ops.Scale}; diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp index c9e2745f00c9584c8e5d0e75173ce1ec7ba650c7..862fce6959f1aaeeddcd70c65dc0bef81d312d38 100644 --- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp @@ -888,8 +888,9 @@ EmitSchedule(MachineBasicBlock::iterator &InsertPos) { } if (MI->isCandidateForCallSiteEntry() && - DAG->getTarget().Options.EmitCallSiteInfo) - MF.addCallArgsForwardingRegs(MI, DAG->getCallSiteInfo(Node)); + DAG->getTarget().Options.EmitCallSiteInfo) { + MF.addCallSiteInfo(MI, DAG->getCallSiteInfo(Node)); + } if (DAG->getNoMergeSiteInfo(Node)) { MI->setFlag(MachineInstr::MIFlag::NoMerge); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index c24303592769a008834ff8e2b7f92421b56cd51f..8c543ae8038a0c66ebfc633ebe9da655b7b57157 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -37,6 +37,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/RuntimeLibcalls.h" +#include "llvm/CodeGen/SDPatternMatch.h" #include "llvm/CodeGen/SelectionDAGAddressAnalysis.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/SelectionDAGTargetInfo.h" @@ -81,6 +82,7 @@ #include <vector> using namespace llvm; +using namespace llvm::SDPatternMatch; /// makeVTList - Return an instance of the SDVTList struct initialized with the /// specified members. @@ -2029,7 +2031,8 @@ SDValue SelectionDAG::getStepVector(const SDLoc &DL, EVT ResVT) { return getStepVector(DL, ResVT, One); } -SDValue SelectionDAG::getStepVector(const SDLoc &DL, EVT ResVT, APInt StepVal) { +SDValue SelectionDAG::getStepVector(const SDLoc &DL, EVT ResVT, + const APInt &StepVal) { assert(ResVT.getScalarSizeInBits() == StepVal.getBitWidth()); if (ResVT.isScalableVector()) return getNode( @@ -3416,13 +3419,18 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts, Known = KnownBits::mulhs(Known, Known2); break; } - case ISD::AVGCEILU: { + case ISD::AVGFLOORU: + case ISD::AVGCEILU: + case ISD::AVGFLOORS: + case ISD::AVGCEILS: { + bool IsCeil = Opcode == ISD::AVGCEILU || Opcode == ISD::AVGCEILS; + bool IsSigned = Opcode == ISD::AVGFLOORS || Opcode == ISD::AVGCEILS; Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); - Known = Known.zext(BitWidth + 1); - Known2 = Known2.zext(BitWidth + 1); - KnownBits One = KnownBits::makeConstant(APInt(1, 1)); - Known = KnownBits::computeForAddCarry(Known, Known2, One); + Known = IsSigned ? Known.sext(BitWidth + 1) : Known.zext(BitWidth + 1); + Known2 = IsSigned ? Known2.sext(BitWidth + 1) : Known2.zext(BitWidth + 1); + KnownBits Carry = KnownBits::makeConstant(APInt(1, IsCeil ? 1 : 0)); + Known = KnownBits::computeForAddCarry(Known, Known2, Carry); Known = Known.extractBits(BitWidth, 1); break; } @@ -4068,6 +4076,9 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts, if (Op.getResNo() == 0) { if (TLI->getExtendForAtomicOps() == ISD::ZERO_EXTEND) Known.Zero.setBitsFrom(MemBits); + else if (Op->getOpcode() == ISD::ATOMIC_LOAD && + cast<AtomicSDNode>(Op)->getExtensionType() == ISD::ZEXTLOAD) + Known.Zero.setBitsFrom(MemBits); } break; } @@ -4290,21 +4301,15 @@ bool SelectionDAG::isKnownToBeAPowerOfTwo(SDValue Val, unsigned Depth) const { return isKnownToBeAPowerOfTwo(Val.getOperand(2), Depth + 1) && isKnownToBeAPowerOfTwo(Val.getOperand(1), Depth + 1); - if (Val.getOpcode() == ISD::AND) { - // Looking for `x & -x` pattern: - // If x == 0: - // x & -x -> 0 - // If x != 0: - // x & -x -> non-zero pow2 - // so if we find the pattern return whether we know `x` is non-zero. - for (unsigned OpIdx = 0; OpIdx < 2; ++OpIdx) { - SDValue NegOp = Val.getOperand(OpIdx); - if (NegOp.getOpcode() == ISD::SUB && - NegOp.getOperand(1) == Val.getOperand(1 - OpIdx) && - isNullOrNullSplat(NegOp.getOperand(0))) - return isKnownNeverZero(Val.getOperand(1 - OpIdx), Depth); - } - } + // Looking for `x & -x` pattern: + // If x == 0: + // x & -x -> 0 + // If x != 0: + // x & -x -> non-zero pow2 + // so if we find the pattern return whether we know `x` is non-zero. + SDValue X; + if (sd_match(Val, m_And(m_Value(X), m_Sub(m_Zero(), m_Deferred(X))))) + return isKnownNeverZero(X, Depth); if (Val.getOpcode() == ISD::ZERO_EXTEND) return isKnownToBeAPowerOfTwo(Val.getOperand(0), Depth + 1); @@ -4879,6 +4884,13 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, const APInt &DemandedElts, return VTBits - Tmp + 1; if (TLI->getExtendForAtomicOps() == ISD::ZERO_EXTEND) return VTBits - Tmp; + if (Op->getOpcode() == ISD::ATOMIC_LOAD) { + ISD::LoadExtType ETy = cast<AtomicSDNode>(Op)->getExtensionType(); + if (ETy == ISD::SEXTLOAD) + return VTBits - Tmp + 1; + if (ETy == ISD::ZEXTLOAD) + return VTBits - Tmp; + } } break; } @@ -5036,8 +5048,9 @@ bool SelectionDAG::isGuaranteedNotToBeUndefOrPoison(SDValue Op, // If Op can't create undef/poison and none of its operands are undef/poison // then Op is never undef/poison. - // NOTE: TargetNodes should handle this in themselves in - // isGuaranteedNotToBeUndefOrPoisonForTargetNode. + // NOTE: TargetNodes can handle this in themselves in + // isGuaranteedNotToBeUndefOrPoisonForTargetNode or let + // TargetLowering::isGuaranteedNotToBeUndefOrPoisonForTargetNode handle it. return !canCreateUndefOrPoison(Op, PoisonOnly, /*ConsiderFlags*/ true, Depth) && all_of(Op->ops(), [&](SDValue V) { @@ -5354,10 +5367,44 @@ bool SelectionDAG::isKnownNeverZero(SDValue Op, unsigned Depth) const { return isKnownNeverZero(Op.getOperand(1), Depth + 1) || isKnownNeverZero(Op.getOperand(0), Depth + 1); - // TODO for smin/smax: If either operand is known negative/positive + // For smin/smax: If either operand is known negative/positive // respectively we don't need the other to be known at all. - case ISD::SMAX: - case ISD::SMIN: + case ISD::SMAX: { + KnownBits Op1 = computeKnownBits(Op.getOperand(1), Depth + 1); + if (Op1.isStrictlyPositive()) + return true; + + KnownBits Op0 = computeKnownBits(Op.getOperand(0), Depth + 1); + if (Op0.isStrictlyPositive()) + return true; + + if (Op1.isNonZero() && Op0.isNonZero()) + return true; + + if (KnownBits::smax(Op0, Op1).isNonZero()) + return true; + + return isKnownNeverZero(Op.getOperand(1), Depth + 1) && + isKnownNeverZero(Op.getOperand(0), Depth + 1); + } + case ISD::SMIN: { + KnownBits Op1 = computeKnownBits(Op.getOperand(1), Depth + 1); + if (Op1.isNegative()) + return true; + + KnownBits Op0 = computeKnownBits(Op.getOperand(0), Depth + 1); + if (Op0.isNegative()) + return true; + + if (Op1.isNonZero() && Op0.isNonZero()) + return true; + + if (KnownBits::smin(Op0, Op1).isNonZero()) + return true; + + return isKnownNeverZero(Op.getOperand(1), Depth + 1) && + isKnownNeverZero(Op.getOperand(0), Depth + 1); + } case ISD::UMIN: return isKnownNeverZero(Op.getOperand(1), Depth + 1) && isKnownNeverZero(Op.getOperand(0), Depth + 1); @@ -6031,50 +6078,25 @@ static std::optional<APInt> FoldValue(unsigned Opcode, const APInt &C1, if (!C2.getBoolValue()) break; return C1.srem(C2); - case ISD::MULHS: { - unsigned FullWidth = C1.getBitWidth() * 2; - APInt C1Ext = C1.sext(FullWidth); - APInt C2Ext = C2.sext(FullWidth); - return (C1Ext * C2Ext).extractBits(C1.getBitWidth(), C1.getBitWidth()); - } - case ISD::MULHU: { - unsigned FullWidth = C1.getBitWidth() * 2; - APInt C1Ext = C1.zext(FullWidth); - APInt C2Ext = C2.zext(FullWidth); - return (C1Ext * C2Ext).extractBits(C1.getBitWidth(), C1.getBitWidth()); - } - case ISD::AVGFLOORS: { - unsigned FullWidth = C1.getBitWidth() + 1; - APInt C1Ext = C1.sext(FullWidth); - APInt C2Ext = C2.sext(FullWidth); - return (C1Ext + C2Ext).extractBits(C1.getBitWidth(), 1); - } - case ISD::AVGFLOORU: { - unsigned FullWidth = C1.getBitWidth() + 1; - APInt C1Ext = C1.zext(FullWidth); - APInt C2Ext = C2.zext(FullWidth); - return (C1Ext + C2Ext).extractBits(C1.getBitWidth(), 1); - } - case ISD::AVGCEILS: { - unsigned FullWidth = C1.getBitWidth() + 1; - APInt C1Ext = C1.sext(FullWidth); - APInt C2Ext = C2.sext(FullWidth); - return (C1Ext + C2Ext + 1).extractBits(C1.getBitWidth(), 1); - } - case ISD::AVGCEILU: { - unsigned FullWidth = C1.getBitWidth() + 1; - APInt C1Ext = C1.zext(FullWidth); - APInt C2Ext = C2.zext(FullWidth); - return (C1Ext + C2Ext + 1).extractBits(C1.getBitWidth(), 1); - } + case ISD::AVGFLOORS: + return APIntOps::avgFloorS(C1, C2); + case ISD::AVGFLOORU: + return APIntOps::avgFloorU(C1, C2); + case ISD::AVGCEILS: + return APIntOps::avgCeilS(C1, C2); + case ISD::AVGCEILU: + return APIntOps::avgCeilU(C1, C2); case ISD::ABDS: return APIntOps::abds(C1, C2); case ISD::ABDU: return APIntOps::abdu(C1, C2); + case ISD::MULHS: + return APIntOps::mulhs(C1, C2); + case ISD::MULHU: + return APIntOps::mulhu(C1, C2); } return std::nullopt; } - // Handle constant folding with UNDEF. // TODO: Handle more cases. static std::optional<APInt> FoldValueWithUndef(unsigned Opcode, const APInt &C1, @@ -8412,11 +8434,10 @@ SDValue SelectionDAG::getMergeValues(ArrayRef<SDValue> Ops, const SDLoc &dl) { SDValue SelectionDAG::getMemIntrinsicNode( unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef<SDValue> Ops, EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment, - MachineMemOperand::Flags Flags, uint64_t Size, const AAMDNodes &AAInfo) { - if (!Size && MemVT.isScalableVector()) - Size = MemoryLocation::UnknownSize; - else if (!Size) - Size = MemVT.getStoreSize(); + MachineMemOperand::Flags Flags, LocationSize Size, + const AAMDNodes &AAInfo) { + if (Size.hasValue() && !Size.getValue()) + Size = LocationSize::precise(MemVT.getStoreSize()); MachineFunction &MF = getMachineFunction(); MachineMemOperand *MMO = @@ -8578,7 +8599,7 @@ SDValue SelectionDAG::getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, if (PtrInfo.V.isNull()) PtrInfo = InferPointerInfo(PtrInfo, *this, Ptr, Offset); - uint64_t Size = MemoryLocation::getSizeOrUnknown(MemVT.getStoreSize()); + LocationSize Size = LocationSize::precise(MemVT.getStoreSize()); MachineFunction &MF = getMachineFunction(); MachineMemOperand *MMO = MF.getMachineMemOperand(PtrInfo, MMOFlags, Size, Alignment, AAInfo, Ranges); @@ -8699,8 +8720,7 @@ SDValue SelectionDAG::getStore(SDValue Chain, const SDLoc &dl, SDValue Val, PtrInfo = InferPointerInfo(PtrInfo, *this, Ptr); MachineFunction &MF = getMachineFunction(); - uint64_t Size = - MemoryLocation::getSizeOrUnknown(Val.getValueType().getStoreSize()); + LocationSize Size = LocationSize::precise(Val.getValueType().getStoreSize()); MachineMemOperand *MMO = MF.getMachineMemOperand(PtrInfo, MMOFlags, Size, Alignment, AAInfo); return getStore(Chain, dl, Val, Ptr, MMO); @@ -8753,8 +8773,8 @@ SDValue SelectionDAG::getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, MachineFunction &MF = getMachineFunction(); MachineMemOperand *MMO = MF.getMachineMemOperand( - PtrInfo, MMOFlags, MemoryLocation::getSizeOrUnknown(SVT.getStoreSize()), - Alignment, AAInfo); + PtrInfo, MMOFlags, LocationSize::precise(SVT.getStoreSize()), Alignment, + AAInfo); return getTruncStore(Chain, dl, Val, Ptr, SVT, MMO); } @@ -8848,7 +8868,7 @@ SDValue SelectionDAG::getLoadVP( if (PtrInfo.V.isNull()) PtrInfo = InferPointerInfo(PtrInfo, *this, Ptr, Offset); - uint64_t Size = MemoryLocation::getSizeOrUnknown(MemVT.getStoreSize()); + LocationSize Size = LocationSize::precise(MemVT.getStoreSize()); MachineFunction &MF = getMachineFunction(); MachineMemOperand *MMO = MF.getMachineMemOperand(PtrInfo, MMOFlags, Size, Alignment, AAInfo, Ranges); @@ -9001,8 +9021,8 @@ SDValue SelectionDAG::getTruncStoreVP(SDValue Chain, const SDLoc &dl, MachineFunction &MF = getMachineFunction(); MachineMemOperand *MMO = MF.getMachineMemOperand( - PtrInfo, MMOFlags, MemoryLocation::getSizeOrUnknown(SVT.getStoreSize()), - Alignment, AAInfo); + PtrInfo, MMOFlags, LocationSize::precise(SVT.getStoreSize()), Alignment, + AAInfo); return getTruncStoreVP(Chain, dl, Val, Ptr, Mask, EVL, SVT, MMO, IsCompressing); } @@ -9604,6 +9624,10 @@ SDValue SelectionDAG::simplifyShift(SDValue X, SDValue Y) { if (ISD::matchUnaryPredicate(Y, isShiftTooBig, true)) return getUNDEF(X.getValueType()); + // shift i1/vXi1 X, Y --> X (any non-zero shift amount is undefined). + if (X.getValueType().getScalarType() == MVT::i1) + return X; + return SDValue(); } @@ -11737,9 +11761,10 @@ MemSDNode::MemSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, // We check here that the size of the memory operand fits within the size of // the MMO. This is because the MMO might indicate only a possible address // range instead of specifying the affected memory addresses precisely. - // TODO: Make MachineMemOperands aware of scalable vectors. - assert(memvt.getStoreSize().getKnownMinValue() <= MMO->getSize() && - "Size mismatch!"); + assert( + (!MMO->getType().isValid() || + TypeSize::isKnownLE(memvt.getStoreSize(), MMO->getSize().getValue())) && + "Size mismatch!"); } /// Profile - Gather unique data for the node. diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp index 9670c3ac8430eb9e735319a7a2bcb5b14b9294e1..f2ab88851b780ef5f6b6e7aa93f097f309069716 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp @@ -106,8 +106,6 @@ bool BaseIndexOffset::computeAliasing(const SDNode *Op0, int64_t PtrDiff; if (BasePtr0.equalBaseIndex(BasePtr1, DAG, PtrDiff)) { // If the size of memory access is unknown, do not use it to analysis. - // One example of unknown size memory access is to load/store scalable - // vector objects on the stack. // BasePtr1 is PtrDiff away from BasePtr0. They alias if none of the // following situations arise: if (PtrDiff >= 0 && NumBytes0.hasValue() && !NumBytes0.isScalable()) { diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index d1936481e02384fe26dfd0b1849786d183c6a4fb..618bdee7f4053193c092775ba592e86d8b00d566 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1245,63 +1245,65 @@ void SelectionDAGBuilder::visitDbgInfo(const Instruction &I) { } } - // We must skip DPValues if they've already been processed above as we - // have just emitted the debug values resulting from assignment tracking - // analysis, making any existing DPValues redundant (and probably less - // correct). We still need to process DPLabels. This does sink DPLabels - // to the bottom of the group of debug records. That sholdn't be important - // as it does so deterministcally and ordering between DPLabels and DPValues - // is immaterial (other than for MIR/IR printing). - bool SkipDPValues = DAG.getFunctionVarLocs(); + // We must skip DbgVariableRecords if they've already been processed above as + // we have just emitted the debug values resulting from assignment tracking + // analysis, making any existing DbgVariableRecords redundant (and probably + // less correct). We still need to process DbgLabelRecords. This does sink + // DbgLabelRecords to the bottom of the group of debug records. That sholdn't + // be important as it does so deterministcally and ordering between + // DbgLabelRecords and DbgVariableRecords is immaterial (other than for MIR/IR + // printing). + bool SkipDbgVariableRecords = DAG.getFunctionVarLocs(); // Is there is any debug-info attached to this instruction, in the form of // DbgRecord non-instruction debug-info records. for (DbgRecord &DR : I.getDbgRecordRange()) { - if (DPLabel *DPL = dyn_cast<DPLabel>(&DR)) { - assert(DPL->getLabel() && "Missing label"); + if (DbgLabelRecord *DLR = dyn_cast<DbgLabelRecord>(&DR)) { + assert(DLR->getLabel() && "Missing label"); SDDbgLabel *SDV = - DAG.getDbgLabel(DPL->getLabel(), DPL->getDebugLoc(), SDNodeOrder); + DAG.getDbgLabel(DLR->getLabel(), DLR->getDebugLoc(), SDNodeOrder); DAG.AddDbgLabel(SDV); continue; } - if (SkipDPValues) + if (SkipDbgVariableRecords) continue; - DPValue &DPV = cast<DPValue>(DR); - DILocalVariable *Variable = DPV.getVariable(); - DIExpression *Expression = DPV.getExpression(); + DbgVariableRecord &DVR = cast<DbgVariableRecord>(DR); + DILocalVariable *Variable = DVR.getVariable(); + DIExpression *Expression = DVR.getExpression(); dropDanglingDebugInfo(Variable, Expression); - if (DPV.getType() == DPValue::LocationType::Declare) { - if (FuncInfo.PreprocessedDPVDeclares.contains(&DPV)) + if (DVR.getType() == DbgVariableRecord::LocationType::Declare) { + if (FuncInfo.PreprocessedDVRDeclares.contains(&DVR)) continue; - LLVM_DEBUG(dbgs() << "SelectionDAG visiting dbg_declare: " << DPV + LLVM_DEBUG(dbgs() << "SelectionDAG visiting dbg_declare: " << DVR << "\n"); - handleDebugDeclare(DPV.getVariableLocationOp(0), Variable, Expression, - DPV.getDebugLoc()); + handleDebugDeclare(DVR.getVariableLocationOp(0), Variable, Expression, + DVR.getDebugLoc()); continue; } - // A DPValue with no locations is a kill location. - SmallVector<Value *, 4> Values(DPV.location_ops()); + // A DbgVariableRecord with no locations is a kill location. + SmallVector<Value *, 4> Values(DVR.location_ops()); if (Values.empty()) { - handleKillDebugValue(Variable, Expression, DPV.getDebugLoc(), + handleKillDebugValue(Variable, Expression, DVR.getDebugLoc(), SDNodeOrder); continue; } - // A DPValue with an undef or absent location is also a kill location. + // A DbgVariableRecord with an undef or absent location is also a kill + // location. if (llvm::any_of(Values, [](Value *V) { return !V || isa<UndefValue>(V); })) { - handleKillDebugValue(Variable, Expression, DPV.getDebugLoc(), + handleKillDebugValue(Variable, Expression, DVR.getDebugLoc(), SDNodeOrder); continue; } - bool IsVariadic = DPV.hasArgList(); - if (!handleDebugValue(Values, Variable, Expression, DPV.getDebugLoc(), + bool IsVariadic = DVR.hasArgList(); + if (!handleDebugValue(Values, Variable, Expression, DVR.getDebugLoc(), SDNodeOrder, IsVariadic)) { addDanglingDebugInfo(Values, Variable, Expression, IsVariadic, - DPV.getDebugLoc(), SDNodeOrder); + DVR.getDebugLoc(), SDNodeOrder); } } } @@ -3037,7 +3039,8 @@ static SDValue getLoadStackGuard(SelectionDAG &DAG, const SDLoc &DL, auto Flags = MachineMemOperand::MOLoad | MachineMemOperand::MOInvariant | MachineMemOperand::MODereferenceable; MachineMemOperand *MemRef = MF.getMachineMemOperand( - MPInfo, Flags, PtrTy.getSizeInBits() / 8, DAG.getEVTAlign(PtrTy)); + MPInfo, Flags, LocationSize::precise(PtrTy.getSizeInBits() / 8), + DAG.getEVTAlign(PtrTy)); DAG.setNodeMemRefs(Node, {MemRef}); } if (PtrTy != PtrMemTy) @@ -3328,7 +3331,7 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) { EHPadMBB->setMachineBlockAddressTaken(); break; case Intrinsic::experimental_patchpoint_void: - case Intrinsic::experimental_patchpoint_i64: + case Intrinsic::experimental_patchpoint: visitPatchpoint(I, EHPadBB); break; case Intrinsic::experimental_gc_statepoint: @@ -4753,7 +4756,7 @@ void SelectionDAGBuilder::visitMaskedStore(const CallInst &I, MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( MachinePointerInfo(PtrOperand), MachineMemOperand::MOStore, - MemoryLocation::UnknownSize, Alignment, I.getAAMetadata()); + LocationSize::beforeOrAfterPointer(), Alignment, I.getAAMetadata()); SDValue StoreNode = DAG.getMaskedStore(getMemoryRoot(), sdl, Src0, Ptr, Offset, Mask, VT, MMO, ISD::UNINDEXED, false /* Truncating */, IsCompressing); @@ -4857,9 +4860,7 @@ void SelectionDAGBuilder::visitMaskedScatter(const CallInst &I) { unsigned AS = Ptr->getType()->getScalarType()->getPointerAddressSpace(); MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( MachinePointerInfo(AS), MachineMemOperand::MOStore, - // TODO: Make MachineMemOperands aware of scalable - // vectors. - MemoryLocation::UnknownSize, Alignment, I.getAAMetadata()); + LocationSize::beforeOrAfterPointer(), Alignment, I.getAAMetadata()); if (!UniformBase) { Base = DAG.getConstant(0, sdl, TLI.getPointerTy(DAG.getDataLayout())); Index = getValue(Ptr); @@ -4925,7 +4926,7 @@ void SelectionDAGBuilder::visitMaskedLoad(const CallInst &I, bool IsExpanding) { MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( MachinePointerInfo(PtrOperand), MachineMemOperand::MOLoad, - MemoryLocation::UnknownSize, Alignment, AAInfo, Ranges); + LocationSize::beforeOrAfterPointer(), Alignment, AAInfo, Ranges); SDValue Load = DAG.getMaskedLoad(VT, sdl, InChain, Ptr, Offset, Mask, Src0, VT, MMO, @@ -4961,9 +4962,8 @@ void SelectionDAGBuilder::visitMaskedGather(const CallInst &I) { unsigned AS = Ptr->getType()->getScalarType()->getPointerAddressSpace(); MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( MachinePointerInfo(AS), MachineMemOperand::MOLoad, - // TODO: Make MachineMemOperands aware of scalable - // vectors. - MemoryLocation::UnknownSize, Alignment, I.getAAMetadata(), Ranges); + LocationSize::beforeOrAfterPointer(), Alignment, I.getAAMetadata(), + Ranges); if (!UniformBase) { Base = DAG.getConstant(0, sdl, TLI.getPointerTy(DAG.getDataLayout())); @@ -5003,9 +5003,9 @@ void SelectionDAGBuilder::visitAtomicCmpXchg(const AtomicCmpXchgInst &I) { MachineFunction &MF = DAG.getMachineFunction(); MachineMemOperand *MMO = MF.getMachineMemOperand( - MachinePointerInfo(I.getPointerOperand()), Flags, MemVT.getStoreSize(), - DAG.getEVTAlign(MemVT), AAMDNodes(), nullptr, SSID, SuccessOrdering, - FailureOrdering); + MachinePointerInfo(I.getPointerOperand()), Flags, + LocationSize::precise(MemVT.getStoreSize()), DAG.getEVTAlign(MemVT), + AAMDNodes(), nullptr, SSID, SuccessOrdering, FailureOrdering); SDValue L = DAG.getAtomicCmpSwap(ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS, dl, MemVT, VTs, InChain, @@ -5057,8 +5057,9 @@ void SelectionDAGBuilder::visitAtomicRMW(const AtomicRMWInst &I) { MachineFunction &MF = DAG.getMachineFunction(); MachineMemOperand *MMO = MF.getMachineMemOperand( - MachinePointerInfo(I.getPointerOperand()), Flags, MemVT.getStoreSize(), - DAG.getEVTAlign(MemVT), AAMDNodes(), nullptr, SSID, Ordering); + MachinePointerInfo(I.getPointerOperand()), Flags, + LocationSize::precise(MemVT.getStoreSize()), DAG.getEVTAlign(MemVT), + AAMDNodes(), nullptr, SSID, Ordering); SDValue L = DAG.getAtomic(NT, dl, MemVT, InChain, @@ -5103,8 +5104,9 @@ void SelectionDAGBuilder::visitAtomicLoad(const LoadInst &I) { auto Flags = TLI.getLoadMemOperandFlags(I, DAG.getDataLayout(), AC, LibInfo); MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( - MachinePointerInfo(I.getPointerOperand()), Flags, MemVT.getStoreSize(), - I.getAlign(), AAMDNodes(), nullptr, SSID, Order); + MachinePointerInfo(I.getPointerOperand()), Flags, + LocationSize::precise(MemVT.getStoreSize()), I.getAlign(), AAMDNodes(), + nullptr, SSID, Order); InChain = TLI.prepareVolatileOrAtomicLoad(InChain, dl, DAG); @@ -5140,8 +5142,9 @@ void SelectionDAGBuilder::visitAtomicStore(const StoreInst &I) { MachineFunction &MF = DAG.getMachineFunction(); MachineMemOperand *MMO = MF.getMachineMemOperand( - MachinePointerInfo(I.getPointerOperand()), Flags, MemVT.getStoreSize(), - I.getAlign(), AAMDNodes(), nullptr, SSID, Ordering); + MachinePointerInfo(I.getPointerOperand()), Flags, + LocationSize::precise(MemVT.getStoreSize()), I.getAlign(), AAMDNodes(), + nullptr, SSID, Ordering); SDValue Val = getValue(I.getValueOperand()); if (Val.getValueType() != MemVT) @@ -6004,12 +6007,15 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue( // incorrect hoisting of the DBG_VALUE to the function entry). // Notice that we allow one dbg.value per IR level argument, to accommodate // for the situation with fragments above. + // If there is no node for the value being handled, we return true to skip + // the normal generation of debug info, as it would kill existing debug + // info for the parameter in case of duplicates. if (VariableIsFunctionInputArg) { unsigned ArgNo = Arg->getArgNo(); if (ArgNo >= FuncInfo.DescribedArgs.size()) FuncInfo.DescribedArgs.resize(ArgNo + 1, false); else if (!IsInPrologue && FuncInfo.DescribedArgs.test(ArgNo)) - return false; + return !NodeMap[V].getNode(); FuncInfo.DescribedArgs.set(ArgNo); } } @@ -6904,7 +6910,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, auto MPI = MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), SPFI); MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( - MPI, MachineMemOperand::MOStore, MemoryLocation::UnknownSize, + MPI, MachineMemOperand::MOStore, LocationSize::beforeOrAfterPointer(), TempAlign); Chain = DAG.getGetFPEnv(Chain, sdl, Temp, EnvVT, MMO); Res = DAG.getLoad(EnvVT, sdl, Chain, Temp, MPI); @@ -6933,7 +6939,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, Chain = DAG.getStore(Chain, sdl, Env, Temp, MPI, TempAlign, MachineMemOperand::MOStore); MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( - MPI, MachineMemOperand::MOLoad, MemoryLocation::UnknownSize, + MPI, MachineMemOperand::MOLoad, LocationSize::beforeOrAfterPointer(), TempAlign); Chain = DAG.getSetFPEnv(Chain, sdl, Temp, EnvVT, MMO); } @@ -7276,12 +7282,6 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, setValue(&I, getValue(I.getArgOperand(0))); return; - case Intrinsic::experimental_hot: - // Default lowering to false. It's intended to be lowered as soon as profile - // is avalible to unblock other optimizations. - setValue(&I, DAG.getConstant(0, sdl, MVT::i1)); - return; - case Intrinsic::ubsantrap: case Intrinsic::debugtrap: case Intrinsic::trap: { @@ -7326,6 +7326,11 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, return; } + case Intrinsic::allow_runtime_check: + case Intrinsic::allow_ubsan_check: + setValue(&I, getValue(ConstantInt::getTrue(I.getType()))); + return; + case Intrinsic::uadd_with_overflow: case Intrinsic::sadd_with_overflow: case Intrinsic::usub_with_overflow: @@ -7448,7 +7453,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, visitStackmap(I); return; case Intrinsic::experimental_patchpoint_void: - case Intrinsic::experimental_patchpoint_i64: + case Intrinsic::experimental_patchpoint: visitPatchpoint(I); return; case Intrinsic::experimental_gc_statepoint: @@ -8093,7 +8098,7 @@ void SelectionDAGBuilder::visitVPLoad( SDValue InChain = AddToChain ? DAG.getRoot() : DAG.getEntryNode(); MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( MachinePointerInfo(PtrOperand), MachineMemOperand::MOLoad, - MemoryLocation::UnknownSize, *Alignment, AAInfo, Ranges); + LocationSize::beforeOrAfterPointer(), *Alignment, AAInfo, Ranges); LD = DAG.getLoadVP(VT, DL, InChain, OpValues[0], OpValues[1], OpValues[2], MMO, false /*IsExpanding */); if (AddToChain) @@ -8116,8 +8121,8 @@ void SelectionDAGBuilder::visitVPGather( unsigned AS = PtrOperand->getType()->getScalarType()->getPointerAddressSpace(); MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( - MachinePointerInfo(AS), MachineMemOperand::MOLoad, - MemoryLocation::UnknownSize, *Alignment, AAInfo, Ranges); + MachinePointerInfo(AS), MachineMemOperand::MOLoad, + LocationSize::beforeOrAfterPointer(), *Alignment, AAInfo, Ranges); SDValue Base, Index, Scale; ISD::MemIndexType IndexType; bool UniformBase = getUniformBase(PtrOperand, Base, Index, IndexType, Scale, @@ -8157,7 +8162,7 @@ void SelectionDAGBuilder::visitVPStore( SDValue Offset = DAG.getUNDEF(Ptr.getValueType()); MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( MachinePointerInfo(PtrOperand), MachineMemOperand::MOStore, - MemoryLocation::UnknownSize, *Alignment, AAInfo); + LocationSize::beforeOrAfterPointer(), *Alignment, AAInfo); ST = DAG.getStoreVP(getMemoryRoot(), DL, OpValues[0], Ptr, Offset, OpValues[2], OpValues[3], VT, MMO, ISD::UNINDEXED, /* IsTruncating */ false, /*IsCompressing*/ false); @@ -8180,7 +8185,7 @@ void SelectionDAGBuilder::visitVPScatter( PtrOperand->getType()->getScalarType()->getPointerAddressSpace(); MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( MachinePointerInfo(AS), MachineMemOperand::MOStore, - MemoryLocation::UnknownSize, *Alignment, AAInfo); + LocationSize::beforeOrAfterPointer(), *Alignment, AAInfo); SDValue Base, Index, Scale; ISD::MemIndexType IndexType; bool UniformBase = getUniformBase(PtrOperand, Base, Index, IndexType, Scale, @@ -8223,7 +8228,7 @@ void SelectionDAGBuilder::visitVPStridedLoad( unsigned AS = PtrOperand->getType()->getPointerAddressSpace(); MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( MachinePointerInfo(AS), MachineMemOperand::MOLoad, - MemoryLocation::UnknownSize, *Alignment, AAInfo, Ranges); + LocationSize::beforeOrAfterPointer(), *Alignment, AAInfo, Ranges); SDValue LD = DAG.getStridedLoadVP(VT, DL, InChain, OpValues[0], OpValues[1], OpValues[2], OpValues[3], MMO, @@ -8246,7 +8251,7 @@ void SelectionDAGBuilder::visitVPStridedStore( unsigned AS = PtrOperand->getType()->getPointerAddressSpace(); MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand( MachinePointerInfo(AS), MachineMemOperand::MOStore, - MemoryLocation::UnknownSize, *Alignment, AAInfo); + LocationSize::beforeOrAfterPointer(), *Alignment, AAInfo); SDValue ST = DAG.getStridedStoreVP( getMemoryRoot(), DL, OpValues[0], OpValues[1], @@ -8607,8 +8612,6 @@ void SelectionDAGBuilder::LowerCallTo(const CallBase &CB, SDValue Callee, if (auto Bundle = CB.getOperandBundle(LLVMContext::OB_convergencectrl)) { auto *Token = Bundle->Inputs[0].get(); ConvControlToken = getValue(Token); - } else { - ConvControlToken = DAG.getUNDEF(MVT::Untyped); } TargetLowering::CallLoweringInfo CLI(DAG); @@ -10260,12 +10263,12 @@ void SelectionDAGBuilder::visitStackmap(const CallInst &CI) { /// Lower llvm.experimental.patchpoint directly to its target opcode. void SelectionDAGBuilder::visitPatchpoint(const CallBase &CB, const BasicBlock *EHPadBB) { - // void|i64 @llvm.experimental.patchpoint.void|i64(i64 <id>, - // i32 <numBytes>, - // i8* <target>, - // i32 <numArgs>, - // [Args...], - // [live variables...]) + // <ty> @llvm.experimental.patchpoint.<ty>(i64 <id>, + // i32 <numBytes>, + // i8* <target>, + // i32 <numArgs>, + // [Args...], + // [live variables...]) CallingConv::ID CC = CB.getCallingConv(); bool IsAnyRegCC = CC == CallingConv::AnyReg; @@ -10504,14 +10507,14 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const { CLI.Ins.clear(); Type *OrigRetTy = CLI.RetTy; SmallVector<EVT, 4> RetTys; - SmallVector<uint64_t, 4> Offsets; + SmallVector<TypeSize, 4> Offsets; auto &DL = CLI.DAG.getDataLayout(); - ComputeValueVTs(*this, DL, CLI.RetTy, RetTys, &Offsets, 0); + ComputeValueVTs(*this, DL, CLI.RetTy, RetTys, &Offsets); if (CLI.IsPostTypeLegalization) { // If we are lowering a libcall after legalization, split the return type. SmallVector<EVT, 4> OldRetTys; - SmallVector<uint64_t, 4> OldOffsets; + SmallVector<TypeSize, 4> OldOffsets; RetTys.swap(OldRetTys); Offsets.swap(OldOffsets); @@ -10523,7 +10526,7 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const { unsigned RegisterVTByteSZ = RegisterVT.getSizeInBits() / 8; RetTys.append(NumRegs, RegisterVT); for (unsigned j = 0; j != NumRegs; ++j) - Offsets.push_back(Offset + j * RegisterVTByteSZ); + Offsets.push_back(TypeSize::getFixed(Offset + j * RegisterVTByteSZ)); } } diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index dcf46e0563ff9de7165c10842d052e0f36415955..211e1653de560a99407a70fd2fd0c6caf6fdc244 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -449,7 +449,7 @@ public: ArrayRef<const Use> GCTransitionArgs; /// The ID that the resulting STATEPOINT instruction has to report. - unsigned ID = -1; + uint64_t ID = -1; /// Information regarding the underlying call instruction. TargetLowering::CallLoweringInfo CLI; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp index fa71adc8da3f381fdf883b143ba50753c1702575..20375a0f92b2385e765cd0496ce68920ff0bddc9 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp @@ -841,6 +841,18 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const { } else if (const MemSDNode *M = dyn_cast<MemSDNode>(this)) { OS << "<"; printMemOperand(OS, *M->getMemOperand(), G); + if (auto *A = dyn_cast<AtomicSDNode>(M)) + if (A->getOpcode() == ISD::ATOMIC_LOAD) { + bool doExt = true; + switch (A->getExtensionType()) { + default: doExt = false; break; + case ISD::EXTLOAD: OS << ", anyext"; break; + case ISD::SEXTLOAD: OS << ", sext"; break; + case ISD::ZEXTLOAD: OS << ", zext"; break; + } + if (doExt) + OS << " from " << A->getMemoryVT(); + } OS << ">"; } else if (const BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(this)) { diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index c78c3ed294e46b7de532591c25d219dc9f5514be..d629c36bc792e32835718304e495ed1b1ad07920 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -1461,12 +1461,12 @@ static void processDbgDeclares(FunctionLoweringInfo &FuncInfo) { if (DI && processDbgDeclare(FuncInfo, DI->getAddress(), DI->getExpression(), DI->getVariable(), DI->getDebugLoc())) FuncInfo.PreprocessedDbgDeclares.insert(DI); - for (const DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) { - if (DPV.Type == DPValue::LocationType::Declare && - processDbgDeclare(FuncInfo, DPV.getVariableLocationOp(0), - DPV.getExpression(), DPV.getVariable(), - DPV.getDebugLoc())) - FuncInfo.PreprocessedDPVDeclares.insert(&DPV); + for (const DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { + if (DVR.Type == DbgVariableRecord::LocationType::Declare && + processDbgDeclare(FuncInfo, DVR.getVariableLocationOp(0), + DVR.getExpression(), DVR.getVariable(), + DVR.getDebugLoc())) + FuncInfo.PreprocessedDVRDeclares.insert(&DVR); } } } diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index b3dc9de7137311f1b5e73d5228ecb702e815d3bb..962f0d98e3be90f7b91090b3c021322a047565fe 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -3786,7 +3786,15 @@ bool TargetLowering::isGuaranteedNotToBeUndefOrPoisonForTargetNode( Op.getOpcode() == ISD::INTRINSIC_VOID) && "Should use isGuaranteedNotToBeUndefOrPoison if you don't know whether Op" " is a target node!"); - return false; + + // If Op can't create undef/poison and none of its operands are undef/poison + // then Op is never undef/poison. + return !canCreateUndefOrPoisonForTargetNode(Op, DemandedElts, DAG, PoisonOnly, + /*ConsiderFlags*/ true, Depth) && + all_of(Op->ops(), [&](SDValue V) { + return DAG.isGuaranteedNotToBeUndefOrPoison(V, PoisonOnly, + Depth + 1); + }); } bool TargetLowering::canCreateUndefOrPoisonForTargetNode( @@ -6908,6 +6916,11 @@ TargetLowering::prepareSREMEqFold(EVT SETCCVT, SDValue REMNode, // Q = floor((2 * A) / (2^K)) APInt Q = (2 * A).udiv(APInt::getOneBitSet(W, K)); + assert(APInt::getAllOnes(SVT.getSizeInBits()).ugt(A) && + "We are expecting that A is always less than all-ones for SVT"); + assert(APInt::getAllOnes(ShSVT.getSizeInBits()).ugt(K) && + "We are expecting that K is always less than all-ones for ShSVT"); + // If D was a power of two, apply the alternate constant derivation. if (D0.isOne()) { // A = 2^(W-1) @@ -6916,11 +6929,6 @@ TargetLowering::prepareSREMEqFold(EVT SETCCVT, SDValue REMNode, Q = APInt::getAllOnes(W - K).zext(W); } - assert(APInt::getAllOnes(SVT.getSizeInBits()).ugt(A) && - "We are expecting that A is always less than all-ones for SVT"); - assert(APInt::getAllOnes(ShSVT.getSizeInBits()).ugt(K) && - "We are expecting that K is always less than all-ones for ShSVT"); - // If the divisor is 1 the result can be constant-folded. Likewise, we // don't care about INT_MIN lanes, those can be set to undef if appropriate. if (D.isOne()) { @@ -8702,11 +8710,21 @@ SDValue TargetLowering::expandCTPOP(SDNode *Node, SelectionDAG &DAG) const { } // v = (v * 0x01010101...) >> (Len - 8) - SDValue Mask01 = - DAG.getConstant(APInt::getSplat(Len, APInt(8, 0x01)), dl, VT); - return DAG.getNode(ISD::SRL, dl, VT, - DAG.getNode(ISD::MUL, dl, VT, Op, Mask01), - DAG.getConstant(Len - 8, dl, ShVT)); + SDValue V; + if (isOperationLegalOrCustomOrPromote( + ISD::MUL, getTypeToTransformTo(*DAG.getContext(), VT))) { + SDValue Mask01 = + DAG.getConstant(APInt::getSplat(Len, APInt(8, 0x01)), dl, VT); + V = DAG.getNode(ISD::MUL, dl, VT, Op, Mask01); + } else { + V = Op; + for (unsigned Shift = 8; Shift < Len; Shift *= 2) { + SDValue ShiftC = DAG.getShiftAmountConstant(Shift, VT, dl); + V = DAG.getNode(ISD::ADD, dl, VT, V, + DAG.getNode(ISD::SHL, dl, VT, V, ShiftC)); + } + } + return DAG.getNode(ISD::SRL, dl, VT, V, DAG.getConstant(Len - 8, dl, ShVT)); } SDValue TargetLowering::expandVPCTPOP(SDNode *Node, SelectionDAG &DAG) const { @@ -8759,10 +8777,22 @@ SDValue TargetLowering::expandVPCTPOP(SDNode *Node, SelectionDAG &DAG) const { return Op; // v = (v * 0x01010101...) >> (Len - 8) - SDValue Mask01 = - DAG.getConstant(APInt::getSplat(Len, APInt(8, 0x01)), dl, VT); - return DAG.getNode(ISD::VP_LSHR, dl, VT, - DAG.getNode(ISD::VP_MUL, dl, VT, Op, Mask01, Mask, VL), + SDValue V; + if (isOperationLegalOrCustomOrPromote( + ISD::VP_MUL, getTypeToTransformTo(*DAG.getContext(), VT))) { + SDValue Mask01 = + DAG.getConstant(APInt::getSplat(Len, APInt(8, 0x01)), dl, VT); + V = DAG.getNode(ISD::VP_MUL, dl, VT, Op, Mask01, Mask, VL); + } else { + V = Op; + for (unsigned Shift = 8; Shift < Len; Shift *= 2) { + SDValue ShiftC = DAG.getShiftAmountConstant(Shift, VT, dl); + V = DAG.getNode(ISD::VP_ADD, dl, VT, V, + DAG.getNode(ISD::VP_SHL, dl, VT, V, ShiftC, Mask, VL), + Mask, VL); + } + } + return DAG.getNode(ISD::VP_LSHR, dl, VT, V, DAG.getConstant(Len - 8, dl, ShVT), Mask, VL); } @@ -10694,7 +10724,7 @@ SDValue TargetLowering::expandVecReduce(SDNode *Node, SelectionDAG &DAG) const { SDValue Lo, Hi; std::tie(Lo, Hi) = DAG.SplitVector(Op, dl); - Op = DAG.getNode(BaseOpcode, dl, HalfVT, Lo, Hi); + Op = DAG.getNode(BaseOpcode, dl, HalfVT, Lo, Hi, Node->getFlags()); VT = HalfVT; } } diff --git a/llvm/lib/CodeGen/SjLjEHPrepare.cpp b/llvm/lib/CodeGen/SjLjEHPrepare.cpp index 515b5764a09479c7aad1e8fe25bf508ba47d986c..20c827ce08d84566f9cd9cc573c43ebb4841e7ac 100644 --- a/llvm/lib/CodeGen/SjLjEHPrepare.cpp +++ b/llvm/lib/CodeGen/SjLjEHPrepare.cpp @@ -150,9 +150,7 @@ static void MarkBlocksLiveIn(BasicBlock *BB, if (!LiveBBs.insert(BB).second) return; // already been here. - df_iterator_default_set<BasicBlock*> Visited; - - for (BasicBlock *B : inverse_depth_first_ext(BB, Visited)) + for (BasicBlock *B : inverse_depth_first(BB)) LiveBBs.insert(B); } @@ -204,7 +202,7 @@ SjLjEHPrepareImpl::setupFunctionContext(Function &F, auto &DL = F.getParent()->getDataLayout(); const Align Alignment = DL.getPrefTypeAlign(FunctionContextTy); FuncCtx = new AllocaInst(FunctionContextTy, DL.getAllocaAddrSpace(), nullptr, - Alignment, "fn_context", &EntryBB->front()); + Alignment, "fn_context", EntryBB->begin()); // Fill in the function context structure. for (LandingPadInst *LPI : LPads) { @@ -273,7 +271,7 @@ void SjLjEHPrepareImpl::lowerIncomingArguments(Function &F) { Value *TrueValue = ConstantInt::getTrue(F.getContext()); Value *UndefValue = UndefValue::get(Ty); Instruction *SI = SelectInst::Create( - TrueValue, &AI, UndefValue, AI.getName() + ".tmp", &*AfterAllocaInsPt); + TrueValue, &AI, UndefValue, AI.getName() + ".tmp", AfterAllocaInsPt); AI.replaceAllUsesWith(SI); // Reset the operand, because it was clobbered by the RAUW above. @@ -388,7 +386,7 @@ bool SjLjEHPrepareImpl::setupEntryBlockAndCallSites(Function &F) { if (Function *Callee = II->getCalledFunction()) if (Callee->getIntrinsicID() == Intrinsic::donothing) { // Remove the NOP invoke. - BranchInst::Create(II->getNormalDest(), II); + BranchInst::Create(II->getNormalDest(), II->getIterator()); II->eraseFromParent(); continue; } @@ -447,7 +445,7 @@ bool SjLjEHPrepareImpl::setupEntryBlockAndCallSites(Function &F) { // Record the call site value for the back end so it stays associated with // the invoke. - CallInst::Create(CallSiteFn, CallSiteNum, "", Invokes[I]); + CallInst::Create(CallSiteFn, CallSiteNum, "", Invokes[I]->getIterator()); } // Mark call instructions that aren't nounwind as no-action (call_site == @@ -464,8 +462,8 @@ bool SjLjEHPrepareImpl::setupEntryBlockAndCallSites(Function &F) { } // Register the function context and make sure it's known to not throw - CallInst *Register = - CallInst::Create(RegisterFn, FuncCtx, "", EntryBB->getTerminator()); + CallInst *Register = CallInst::Create( + RegisterFn, FuncCtx, "", EntryBB->getTerminator()->getIterator()); Register->setDoesNotThrow(); // Following any allocas not in the entry block, update the saved SP in the @@ -482,7 +480,8 @@ bool SjLjEHPrepareImpl::setupEntryBlockAndCallSites(Function &F) { } Instruction *StackAddr = CallInst::Create(StackAddrFn, "sp"); StackAddr->insertAfter(&I); - new StoreInst(StackAddr, StackPtr, true, StackAddr->getNextNode()); + new StoreInst(StackAddr, StackPtr, true, + std::next(StackAddr->getIterator())); } } @@ -492,7 +491,7 @@ bool SjLjEHPrepareImpl::setupEntryBlockAndCallSites(Function &F) { Instruction *InsertPoint = Return; if (CallInst *CI = Return->getParent()->getTerminatingMustTailCall()) InsertPoint = CI; - CallInst::Create(UnregisterFn, FuncCtx, "", InsertPoint); + CallInst::Create(UnregisterFn, FuncCtx, "", InsertPoint->getIterator()); } return true; diff --git a/llvm/lib/CodeGen/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp index 5b02c1bc39c0a7936a05caa4a6432f7ad403fc2a..9fbd516acea8e146b00e0bec8b4c34063f963ea3 100644 --- a/llvm/lib/CodeGen/TargetInstrInfo.cpp +++ b/llvm/lib/CodeGen/TargetInstrInfo.cpp @@ -1554,7 +1554,8 @@ TargetInstrInfo::describeLoadedValue(const MachineInstr &MI, SmallVector<uint64_t, 8> Ops; DIExpression::appendOffset(Ops, Offset); Ops.push_back(dwarf::DW_OP_deref_size); - Ops.push_back(MMO->getSize()); + Ops.push_back(MMO->getSize().hasValue() ? MMO->getSize().getValue() + : ~UINT64_C(0)); Expr = DIExpression::prependOpcodes(Expr, Ops); return ParamLoadedValue(*BaseOp, Expr); } diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp index 8ac55ee6a5d0c1370dffdb8af83ad9a3f91b7961..f64ded4f2cf965b77f3db7ec5c853a678aefd9bb 100644 --- a/llvm/lib/CodeGen/TargetLoweringBase.cpp +++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -823,6 +823,12 @@ void TargetLoweringBase::initActions() { std::fill(std::begin(TargetDAGCombineArray), std::end(TargetDAGCombineArray), 0); + // Let extending atomic loads be unsupported by default. + for (MVT ValVT : MVT::all_valuetypes()) + for (MVT MemVT : MVT::all_valuetypes()) + setAtomicLoadExtAction({ISD::SEXTLOAD, ISD::ZEXTLOAD}, ValVT, MemVT, + Expand); + // We're somewhat special casing MVT::i2 and MVT::i4. Ideally we want to // remove this and targets should individually set these types if not legal. for (ISD::NodeType NT : enum_seq(ISD::DELETED_NODE, ISD::BUILTIN_OP_END, @@ -2011,6 +2017,10 @@ bool TargetLoweringBase::isLegalAddressingMode(const DataLayout &DL, // The default implementation of this implements a conservative RISCy, r+r and // r+i addr mode. + // Scalable offsets not supported + if (AM.ScalableOffset) + return false; + // Allows a sign-extended 16-bit immediate field. if (AM.BaseOffs <= -(1LL << 16) || AM.BaseOffs >= (1LL << 16)-1) return false; @@ -2069,7 +2079,8 @@ void TargetLoweringBase::insertSSPDeclarations(Module &M) const { // FreeBSD has "__stack_chk_guard" defined externally on libc.so if (M.getDirectAccessExternalData() && !TM.getTargetTriple().isWindowsGNUEnvironment() && - !TM.getTargetTriple().isOSFreeBSD() && + !(TM.getTargetTriple().isPPC64() && + TM.getTargetTriple().isOSFreeBSD()) && (!TM.getTargetTriple().isOSDarwin() || TM.getRelocationModel() == Reloc::Static)) GV->setDSOLocal(true); diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 6943ce261d9d9c814049e61e49136f9c87c1c813..15b59421a0f44aae6cf8f174e2090575ba4583a2 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -2680,21 +2680,34 @@ MCSection *TargetLoweringObjectFileXCOFF::getSectionForFunctionDescriptor( MCSection *TargetLoweringObjectFileXCOFF::getSectionForTOCEntry( const MCSymbol *Sym, const TargetMachine &TM) const { - // Use TE storage-mapping class when large code model is enabled so that - // the chance of needing -bbigtoc is decreased. Also, the toc-entry for - // EH info is never referenced directly using instructions so it can be - // allocated with TE storage-mapping class. - // The "_$TLSML" symbol for TLS local-dynamic mode requires XMC_TC, otherwise - // the AIX assembler will complain. + const XCOFF::StorageMappingClass SMC = [](const MCSymbol *Sym, + const TargetMachine &TM) { + const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(Sym); + + // The "_$TLSML" symbol for TLS local-dynamic mode requires XMC_TC, + // otherwise the AIX assembler will complain. + if (XSym->getSymbolTableName() == "_$TLSML") + return XCOFF::XMC_TC; + + // Use large code model toc entries for ehinfo symbols as they are + // never referenced directly. The runtime loads their TOC entry + // addresses from the trace-back table. + if (XSym->isEHInfo()) + return XCOFF::XMC_TE; + + // If the symbol does not have a code model specified use the module value. + if (!XSym->hasPerSymbolCodeModel()) + return TM.getCodeModel() == CodeModel::Large ? XCOFF::XMC_TE + : XCOFF::XMC_TC; + + return XSym->getPerSymbolCodeModel() == MCSymbolXCOFF::CM_Large + ? XCOFF::XMC_TE + : XCOFF::XMC_TC; + }(Sym, TM); + return getContext().getXCOFFSection( cast<MCSymbolXCOFF>(Sym)->getSymbolTableName(), SectionKind::getData(), - XCOFF::CsectProperties( - ((TM.getCodeModel() == CodeModel::Large && - cast<MCSymbolXCOFF>(Sym)->getSymbolTableName() != "_$TLSML") || - cast<MCSymbolXCOFF>(Sym)->isEHInfo()) - ? XCOFF::XMC_TE - : XCOFF::XMC_TC, - XCOFF::XTY_SD)); + XCOFF::CsectProperties(SMC, XCOFF::XTY_SD)); } MCSection *TargetLoweringObjectFileXCOFF::getSectionForLSDA( diff --git a/llvm/lib/CodeGen/TargetRegisterInfo.cpp b/llvm/lib/CodeGen/TargetRegisterInfo.cpp index c9503fcb77bb215319b62b92dc651266fc7a98c7..4e06393f4cc1d39700fdd8190443cecb286196a1 100644 --- a/llvm/lib/CodeGen/TargetRegisterInfo.cpp +++ b/llvm/lib/CodeGen/TargetRegisterInfo.cpp @@ -50,20 +50,16 @@ static cl::opt<unsigned> "high compile time cost in global splitting."), cl::init(5000)); -TargetRegisterInfo::TargetRegisterInfo(const TargetRegisterInfoDesc *ID, - regclass_iterator RCB, regclass_iterator RCE, - const char *const *SRINames, - const LaneBitmask *SRILaneMasks, - LaneBitmask SRICoveringLanes, - const RegClassInfo *const RCIs, - const MVT::SimpleValueType *const RCVTLists, - unsigned Mode) - : InfoDesc(ID), SubRegIndexNames(SRINames), - SubRegIndexLaneMasks(SRILaneMasks), - RegClassBegin(RCB), RegClassEnd(RCE), - CoveringLanes(SRICoveringLanes), - RCInfos(RCIs), RCVTLists(RCVTLists), HwMode(Mode) { -} +TargetRegisterInfo::TargetRegisterInfo( + const TargetRegisterInfoDesc *ID, regclass_iterator RCB, + regclass_iterator RCE, const char *const *SRINames, + const SubRegCoveredBits *SubIdxRanges, const LaneBitmask *SRILaneMasks, + LaneBitmask SRICoveringLanes, const RegClassInfo *const RCIs, + const MVT::SimpleValueType *const RCVTLists, unsigned Mode) + : InfoDesc(ID), SubRegIndexNames(SRINames), SubRegIdxRanges(SubIdxRanges), + SubRegIndexLaneMasks(SRILaneMasks), RegClassBegin(RCB), RegClassEnd(RCE), + CoveringLanes(SRICoveringLanes), RCInfos(RCIs), RCVTLists(RCVTLists), + HwMode(Mode) {} TargetRegisterInfo::~TargetRegisterInfo() = default; @@ -596,6 +592,18 @@ bool TargetRegisterInfo::getCoveringSubRegIndexes( return BestIdx; } +unsigned TargetRegisterInfo::getSubRegIdxSize(unsigned Idx) const { + assert(Idx && Idx < getNumSubRegIndices() && + "This is not a subregister index"); + return SubRegIdxRanges[HwMode * getNumSubRegIndices() + Idx].Size; +} + +unsigned TargetRegisterInfo::getSubRegIdxOffset(unsigned Idx) const { + assert(Idx && Idx < getNumSubRegIndices() && + "This is not a subregister index"); + return SubRegIdxRanges[HwMode * getNumSubRegIndices() + Idx].Offset; +} + Register TargetRegisterInfo::lookThruCopyLike(Register SrcReg, const MachineRegisterInfo *MRI) const { diff --git a/llvm/lib/CodeGen/TypePromotion.cpp b/llvm/lib/CodeGen/TypePromotion.cpp index b0830308908d6e7c6a33c250f1f9520ef12b675a..89aea3a2916118ea433183465735722d84a173d6 100644 --- a/llvm/lib/CodeGen/TypePromotion.cpp +++ b/llvm/lib/CodeGen/TypePromotion.cpp @@ -643,7 +643,7 @@ void IRPromoter::ConvertTruncs() { ConstantInt *Mask = ConstantInt::get(SrcTy, APInt::getMaxValue(NumBits).getZExtValue()); Value *Masked = Builder.CreateAnd(Trunc->getOperand(0), Mask); - if (SrcTy != ExtTy) + if (SrcTy->getBitWidth() > ExtTy->getBitWidth()) Masked = Builder.CreateTrunc(Masked, ExtTy); if (auto *I = dyn_cast<Instruction>(Masked)) diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp index 95976c218c2f1485d6ecd5d6fa04fe8bc611434e..93a18f5bc9e8d4c597728fa3a4b594e0c72f89c4 100644 --- a/llvm/lib/CodeGen/WinEHPrepare.cpp +++ b/llvm/lib/CodeGen/WinEHPrepare.cpp @@ -1234,10 +1234,10 @@ AllocaInst *WinEHPrepareImpl::insertPHILoads(PHINode *PN, Function &F) { // that will dominate all uses. SpillSlot = new AllocaInst(PN->getType(), DL->getAllocaAddrSpace(), nullptr, Twine(PN->getName(), ".wineh.spillslot"), - &F.getEntryBlock().front()); + F.getEntryBlock().begin()); Value *V = new LoadInst(PN->getType(), SpillSlot, Twine(PN->getName(), ".wineh.reload"), - &*PHIBlock->getFirstInsertionPt()); + PHIBlock->getFirstInsertionPt()); PN->replaceAllUsesWith(V); return SpillSlot; } @@ -1309,7 +1309,7 @@ void WinEHPrepareImpl::insertPHIStore( } // Otherwise, insert the store at the end of the basic block. - new StoreInst(PredVal, SpillSlot, PredBlock->getTerminator()); + new StoreInst(PredVal, SpillSlot, PredBlock->getTerminator()->getIterator()); } void WinEHPrepareImpl::replaceUseWithLoad( @@ -1319,7 +1319,7 @@ void WinEHPrepareImpl::replaceUseWithLoad( if (!SpillSlot) SpillSlot = new AllocaInst(V->getType(), DL->getAllocaAddrSpace(), nullptr, Twine(V->getName(), ".wineh.spillslot"), - &F.getEntryBlock().front()); + F.getEntryBlock().begin()); auto *UsingInst = cast<Instruction>(U.getUser()); if (auto *UsingPHI = dyn_cast<PHINode>(UsingInst)) { @@ -1376,16 +1376,16 @@ void WinEHPrepareImpl::replaceUseWithLoad( Value *&Load = Loads[IncomingBlock]; // Insert the load into the predecessor block if (!Load) - Load = new LoadInst(V->getType(), SpillSlot, - Twine(V->getName(), ".wineh.reload"), - /*isVolatile=*/false, IncomingBlock->getTerminator()); + Load = new LoadInst( + V->getType(), SpillSlot, Twine(V->getName(), ".wineh.reload"), + /*isVolatile=*/false, IncomingBlock->getTerminator()->getIterator()); U.set(Load); } else { // Reload right before the old use. auto *Load = new LoadInst(V->getType(), SpillSlot, Twine(V->getName(), ".wineh.reload"), - /*isVolatile=*/false, UsingInst); + /*isVolatile=*/false, UsingInst->getIterator()); U.set(Load); } } diff --git a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp index 9b581a6c9ab7744495cc1a7bde098283d26ac221..60f664ece7eef97717ed95730091824136f6cb9c 100644 --- a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp @@ -2701,8 +2701,8 @@ Error DWARFLinker::link() { // This Dwarf string pool which is used for emission. It must be used // serially as the order of calling getStringOffset matters for // reproducibility. - OffsetsStringPool DebugStrPool(StringsTranslator, true); - OffsetsStringPool DebugLineStrPool(StringsTranslator, false); + OffsetsStringPool DebugStrPool(true); + OffsetsStringPool DebugLineStrPool(false); DebugDieValuePool StringOffsetPool; // ODR Contexts for the optimize. diff --git a/llvm/lib/DWARFLinker/Classic/DWARFStreamer.cpp b/llvm/lib/DWARFLinker/Classic/DWARFStreamer.cpp index 6d522370e440d1d4d7bf8e25a1e26feb34a69388..8b31b5ead29ad054dae9a80c0910f2a5808ba704 100644 --- a/llvm/lib/DWARFLinker/Classic/DWARFStreamer.cpp +++ b/llvm/lib/DWARFLinker/Classic/DWARFStreamer.cpp @@ -32,10 +32,9 @@ using namespace dwarf_linker::classic; Expected<std::unique_ptr<DwarfStreamer>> DwarfStreamer::createStreamer( const Triple &TheTriple, DWARFLinkerBase::OutputFileType FileType, - raw_pwrite_stream &OutFile, DWARFLinkerBase::TranslatorFuncTy Translator, - DWARFLinkerBase::MessageHandlerTy Warning) { + raw_pwrite_stream &OutFile, DWARFLinkerBase::MessageHandlerTy Warning) { std::unique_ptr<DwarfStreamer> Streamer = - std::make_unique<DwarfStreamer>(FileType, OutFile, Translator, Warning); + std::make_unique<DwarfStreamer>(FileType, OutFile, Warning); if (Error Err = Streamer->init(TheTriple, "__DWARF")) return std::move(Err); @@ -977,11 +976,10 @@ void DwarfStreamer::emitLineTableString(const DWARFDebugLine::Prologue &P, switch (String.getForm()) { case dwarf::DW_FORM_string: { - StringRef TranslatedString = - (Translator) ? Translator(*StringVal) : *StringVal; - Asm->OutStreamer->emitBytes(TranslatedString.data()); + StringRef Str = *StringVal; + Asm->OutStreamer->emitBytes(Str.data()); Asm->emitInt8(0); - LineSectionSize += TranslatedString.size() + 1; + LineSectionSize += Str.size() + 1; } break; case dwarf::DW_FORM_strp: case dwarf::DW_FORM_line_strp: { diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinker.cpp b/llvm/lib/DWARFLinker/Parallel/DWARFLinker.cpp index ad8d28a643174afa15579dc088ee7344a5e5b1b5..31c7e867767a0f84c4c0530ee57f2df0dfe6f9ae 100644 --- a/llvm/lib/DWARFLinker/Parallel/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinker.cpp @@ -15,8 +15,6 @@ using namespace dwarf_linker::parallel; std::unique_ptr<DWARFLinker> DWARFLinker::createLinker(MessageHandlerTy ErrorHandler, - MessageHandlerTy WarningHandler, - TranslatorFuncTy StringsTranslator) { - return std::make_unique<DWARFLinkerImpl>(ErrorHandler, WarningHandler, - StringsTranslator); + MessageHandlerTy WarningHandler) { + return std::make_unique<DWARFLinkerImpl>(ErrorHandler, WarningHandler); } diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerGlobalData.h b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerGlobalData.h index 38c261a8106fcd9b771c977daa8c63bf8df97271..7ca81eb34f005ef54a96a87e1066f76b215dbe7e 100644 --- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerGlobalData.h +++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerGlobalData.h @@ -21,7 +21,6 @@ class DWARFDie; namespace dwarf_linker { namespace parallel { -using TranslatorFuncTy = std::function<StringRef(StringRef)>; using MessageHandlerTy = std::function<void( const Twine &Warning, StringRef Context, const DWARFDie *DIE)>; @@ -95,19 +94,6 @@ public: /// Returns global string pool. StringPool &getStringPool() { return Strings; } - /// Set translation function. - void setTranslator(TranslatorFuncTy Translator) { - this->Translator = Translator; - } - - /// Translate specified string. - StringRef translateString(StringRef String) { - if (Translator) - return Translator(String); - - return String; - } - /// Returns linking options. const DWARFLinkerOptions &getOptions() const { return Options; } @@ -161,7 +147,6 @@ public: protected: llvm::parallel::PerThreadBumpPtrAllocator Allocator; StringPool Strings; - TranslatorFuncTy Translator; DWARFLinkerOptions Options; MessageHandlerTy WarningHandler; MessageHandlerTy ErrorHandler; diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.cpp b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.cpp index 49b08997eb9c1c1dadaed10136f9013b7d039add..e68bf0c227a0a0e0689bb56e0c998a01365bdc60 100644 --- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.cpp +++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.cpp @@ -20,11 +20,9 @@ using namespace dwarf_linker; using namespace dwarf_linker::parallel; DWARFLinkerImpl::DWARFLinkerImpl(MessageHandlerTy ErrorHandler, - MessageHandlerTy WarningHandler, - TranslatorFuncTy StringsTranslator) + MessageHandlerTy WarningHandler) : UniqueUnitID(0), DebugStrStrings(GlobalData), DebugLineStrStrings(GlobalData), CommonSections(GlobalData) { - GlobalData.setTranslator(StringsTranslator); GlobalData.setErrorHandler(ErrorHandler); GlobalData.setWarningHandler(WarningHandler); } diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.h b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.h index 7c17c5b79c7c187181b09e9a168e4f6de5c41f00..597bb1b4da59a8b885f46d34b2682f506fbc2aec 100644 --- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.h +++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.h @@ -26,8 +26,7 @@ namespace parallel { class DWARFLinkerImpl : public DWARFLinker { public: DWARFLinkerImpl(MessageHandlerTy ErrorHandler, - MessageHandlerTy WarningHandler, - TranslatorFuncTy StringsTranslator); + MessageHandlerTy WarningHandler); /// Add object file to be linked. Pre-load compile unit die. Call /// \p OnCUDieLoaded for each compile unit die. If specified \p File diff --git a/llvm/lib/DWARFLinker/Parallel/OutputSections.h b/llvm/lib/DWARFLinker/Parallel/OutputSections.h index a21e4b2b75a503f768753e4521b1dfdc4f6206d3..0e1f2dae54bcc205b620a611c0f95d7380a3e7c9 100644 --- a/llvm/lib/DWARFLinker/Parallel/OutputSections.h +++ b/llvm/lib/DWARFLinker/Parallel/OutputSections.h @@ -253,7 +253,7 @@ struct SectionDescriptor : SectionDescriptorBase { /// Emit specified inplace string value into the current section contents. void emitInplaceString(StringRef String) { - OS << GlobalData.translateString(String); + OS << String; emitIntVal(0, 1); } diff --git a/llvm/lib/DWARFLinker/Parallel/StringEntryToDwarfStringPoolEntryMap.h b/llvm/lib/DWARFLinker/Parallel/StringEntryToDwarfStringPoolEntryMap.h index 858f224777dba76f7e38d50aeafeb6ea752bad26..f67536ef7a1a84c813658524cfc064f82829055a 100644 --- a/llvm/lib/DWARFLinker/Parallel/StringEntryToDwarfStringPoolEntryMap.h +++ b/llvm/lib/DWARFLinker/Parallel/StringEntryToDwarfStringPoolEntryMap.h @@ -33,7 +33,7 @@ public: DwarfStringPoolEntryWithExtString *DataPtr = GlobalData.getAllocator() .Allocate<DwarfStringPoolEntryWithExtString>(); - DataPtr->String = GlobalData.translateString(String->getKey()); + DataPtr->String = String->getKey(); DataPtr->Index = DwarfStringPoolEntry::NotIndexed; DataPtr->Offset = 0; DataPtr->Symbol = nullptr; diff --git a/llvm/lib/DebugInfo/LogicalView/CMakeLists.txt b/llvm/lib/DebugInfo/LogicalView/CMakeLists.txt index 38a174661b4f3fd3bd78857760a18dc2e03936bf..f5adab723927a904ec9e6e3cc856758760c0b541 100644 --- a/llvm/lib/DebugInfo/LogicalView/CMakeLists.txt +++ b/llvm/lib/DebugInfo/LogicalView/CMakeLists.txt @@ -24,7 +24,7 @@ add_lv_impl_folder(Readers Readers/LVBinaryReader.cpp Readers/LVCodeViewReader.cpp Readers/LVCodeViewVisitor.cpp - Readers/LVELFReader.cpp + Readers/LVDWARFReader.cpp ) list(APPEND LIBLV_ADDITIONAL_HEADER_DIRS diff --git a/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp b/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp index 5f82f816dc19d5f3f2c7f9f34c01765f2e8ba5cf..c841015405953589e4be5a6d39217da18ad8184a 100644 --- a/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp +++ b/llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp @@ -14,7 +14,7 @@ #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/LogicalView/Core/LVCompare.h" #include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h" -#include "llvm/DebugInfo/LogicalView/Readers/LVELFReader.h" +#include "llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/DebugInfo/PDB/PDB.h" #include "llvm/Object/COFF.h" @@ -48,8 +48,9 @@ Error LVReaderHandler::createReader(StringRef Filename, LVReaders &Readers, return std::make_unique<LVCodeViewReader>(Filename, FileFormatName, *COFF, W, ExePath); } - if (Obj.isELF() || Obj.isMachO()) - return std::make_unique<LVELFReader>(Filename, FileFormatName, Obj, W); + if (Obj.isELF() || Obj.isMachO() || Obj.isWasm()) + return std::make_unique<LVDWARFReader>(Filename, FileFormatName, Obj, + W); } if (isa<PDBFile *>(Input)) { PDBFile &Pdb = *cast<PDBFile *>(Input); diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp index a0cd8b7839cf7ac968ca06956db429cc6884b798..2d46414a6986acff13c33f47ed4f5cbeeba2be55 100644 --- a/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp @@ -146,6 +146,30 @@ bool LVBinaryReader::getSymbolTableIsComdat(StringRef Name) { void LVBinaryReader::mapVirtualAddress(const object::ObjectFile &Obj) { for (const object::SectionRef &Section : Obj.sections()) { + LLVM_DEBUG({ + Expected<StringRef> SectionNameOrErr = Section.getName(); + StringRef Name; + if (!SectionNameOrErr) + consumeError(SectionNameOrErr.takeError()); + else + Name = *SectionNameOrErr; + dbgs() << "Index: " << format_decimal(Section.getIndex(), 3) << ", " + << "Address: " << hexValue(Section.getAddress()) << ", " + << "Size: " << hexValue(Section.getSize()) << ", " + << "Name: " << Name << "\n"; + dbgs() << "isCompressed: " << Section.isCompressed() << ", " + << "isText: " << Section.isText() << ", " + << "isData: " << Section.isData() << ", " + << "isBSS: " << Section.isBSS() << ", " + << "isVirtual: " << Section.isVirtual() << "\n"; + dbgs() << "isBitcode: " << Section.isBitcode() << ", " + << "isStripped: " << Section.isStripped() << ", " + << "isBerkeleyText: " << Section.isBerkeleyText() << ", " + << "isBerkeleyData: " << Section.isBerkeleyData() << ", " + << "isDebugSection: " << Section.isDebugSection() << "\n"; + dbgs() << "\n"; + }); + if (!Section.isText() || Section.isVirtual() || !Section.getSize()) continue; @@ -161,8 +185,14 @@ void LVBinaryReader::mapVirtualAddress(const object::ObjectFile &Obj) { continue; } if ((*SectionNameOrErr).equals(".text") || - (*SectionNameOrErr).equals(".code")) + (*SectionNameOrErr).equals("CODE") || + (*SectionNameOrErr).equals(".code")) { DotTextSectionIndex = Section.getIndex(); + // If the object is WebAssembly, update the address offset that + // will be added to DWARF DW_AT_* attributes. + if (Obj.isWasm()) + WasmCodeSectionOffset = Section.getAddress(); + } } // Process the symbol table. diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVELFReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp similarity index 93% rename from llvm/lib/DebugInfo/LogicalView/Readers/LVELFReader.cpp rename to llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp index 4469092099dacab74b751b7fbbb70f9484be8300..6a97bed9e3a838308bfd37cafe5b2d798c00046d 100644 --- a/llvm/lib/DebugInfo/LogicalView/Readers/LVELFReader.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp @@ -1,4 +1,4 @@ -//===-- LVELFReader.cpp ---------------------------------------------------===// +//===-- LVDWARFReader.cpp -------------------------------------------------===// // // 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,12 @@ // //===----------------------------------------------------------------------===// // -// This implements the LVELFReader class. -// It supports ELF and Mach-O formats. +// This implements the LVDWARFReader class. +// It supports ELF, Mach-O and Wasm binary formats. // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/LogicalView/Readers/LVELFReader.h" +#include "llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include "llvm/DebugInfo/DWARF/DWARFExpression.h" @@ -27,9 +27,9 @@ using namespace llvm; using namespace llvm::object; using namespace llvm::logicalview; -#define DEBUG_TYPE "ElfReader" +#define DEBUG_TYPE "DWARFReader" -LVElement *LVELFReader::createElement(dwarf::Tag Tag) { +LVElement *LVDWARFReader::createElement(dwarf::Tag Tag) { CurrentScope = nullptr; CurrentSymbol = nullptr; CurrentType = nullptr; @@ -243,8 +243,9 @@ LVElement *LVELFReader::createElement(dwarf::Tag Tag) { return nullptr; } -void LVELFReader::processOneAttribute(const DWARFDie &Die, LVOffset *OffsetPtr, - const AttributeSpec &AttrSpec) { +void LVDWARFReader::processOneAttribute(const DWARFDie &Die, + LVOffset *OffsetPtr, + const AttributeSpec &AttrSpec) { uint64_t OffsetOnEntry = *OffsetPtr; DWARFUnit *U = Die.getDwarfUnit(); const DWARFFormValue &FormValue = @@ -415,6 +416,8 @@ void LVELFReader::processOneAttribute(const DWARFDie &Die, LVOffset *OffsetPtr, if (FoundLowPC) { if (CurrentLowPC == MaxAddress) CurrentElement->setIsDiscarded(); + // Consider the case of WebAssembly. + CurrentLowPC += WasmCodeSectionOffset; if (CurrentElement->isCompileUnit()) setCUBaseAddress(CurrentLowPC); } @@ -429,10 +432,17 @@ void LVELFReader::processOneAttribute(const DWARFDie &Die, LVOffset *OffsetPtr, CurrentHighPC = *Address; if (std::optional<uint64_t> Offset = FormValue.getAsUnsignedConstant()) // High PC is an offset from LowPC. - CurrentHighPC = CurrentLowPC + *Offset; + // Don't add the WebAssembly offset if we have seen a DW_AT_low_pc, as + // the CurrentLowPC has already that offset added. Basically, use the + // original DW_AT_loc_pc value. + CurrentHighPC = + (FoundLowPC ? CurrentLowPC - WasmCodeSectionOffset : CurrentLowPC) + + *Offset; // Store the real upper limit for the address range. if (UpdateHighAddress && CurrentHighPC > 0) --CurrentHighPC; + // Consider the case of WebAssembly. + CurrentHighPC += WasmCodeSectionOffset; if (CurrentElement->isCompileUnit()) setCUHighAddress(CurrentHighPC); } @@ -466,6 +476,9 @@ void LVELFReader::processOneAttribute(const DWARFDie &Die, LVOffset *OffsetPtr, // Store the real upper limit for the address range. if (UpdateHighAddress && Range.HighPC > 0) --Range.HighPC; + // Consider the case of WebAssembly. + Range.LowPC += WasmCodeSectionOffset; + Range.HighPC += WasmCodeSectionOffset; // Add the pair of addresses. CurrentScope->addObject(Range.LowPC, Range.HighPC); // If the scope is the CU, do not update the ranges set. @@ -503,8 +516,8 @@ void LVELFReader::processOneAttribute(const DWARFDie &Die, LVOffset *OffsetPtr, } } -LVScope *LVELFReader::processOneDie(const DWARFDie &InputDIE, LVScope *Parent, - DWARFDie &SkeletonDie) { +LVScope *LVDWARFReader::processOneDie(const DWARFDie &InputDIE, LVScope *Parent, + DWARFDie &SkeletonDie) { // If the input DIE corresponds to the compile unit, it can be: // a) Simple DWARF: a standard DIE. Ignore the skeleton DIE (is empty). // b) Split DWARF: the DIE for the split DWARF. The skeleton is the DIE @@ -676,8 +689,8 @@ LVScope *LVELFReader::processOneDie(const DWARFDie &InputDIE, LVScope *Parent, return CurrentScope; } -void LVELFReader::traverseDieAndChildren(DWARFDie &DIE, LVScope *Parent, - DWARFDie &SkeletonDie) { +void LVDWARFReader::traverseDieAndChildren(DWARFDie &DIE, LVScope *Parent, + DWARFDie &SkeletonDie) { // Process the current DIE. LVScope *Scope = processOneDie(DIE, Parent, SkeletonDie); if (Scope) { @@ -697,13 +710,13 @@ void LVELFReader::traverseDieAndChildren(DWARFDie &DIE, LVScope *Parent, } } -void LVELFReader::processLocationGaps() { +void LVDWARFReader::processLocationGaps() { if (options().getAttributeAnyLocation()) for (LVSymbol *Symbol : SymbolsWithLocations) Symbol->fillLocationGaps(); } -void LVELFReader::createLineAndFileRecords( +void LVDWARFReader::createLineAndFileRecords( const DWARFDebugLine::LineTable *Lines) { if (!Lines) return; @@ -735,7 +748,8 @@ void LVELFReader::createLineAndFileRecords( // and they will be released when its scope parent is deleted. LVLineDebug *Line = createLineDebug(); CULines.push_back(Line); - Line->setAddress(Row.Address.Address); + // Consider the case of WebAssembly. + Line->setAddress(Row.Address.Address + WasmCodeSectionOffset); Line->setFilename( CompileUnit->getFilename(IncrementIndex ? Row.File + 1 : Row.File)); Line->setLineNumber(Row.Line); @@ -759,8 +773,8 @@ void LVELFReader::createLineAndFileRecords( } } -std::string LVELFReader::getRegisterName(LVSmall Opcode, - ArrayRef<uint64_t> Operands) { +std::string LVDWARFReader::getRegisterName(LVSmall Opcode, + ArrayRef<uint64_t> Operands) { // The 'prettyPrintRegisterOp' function uses the DWARFUnit to support // DW_OP_regval_type. At this point we are operating on a logical view // item, with no access to the underlying DWARF data used by LLVM. @@ -787,7 +801,7 @@ std::string LVELFReader::getRegisterName(LVSmall Opcode, return Stream.str(); } -Error LVELFReader::createScopes() { +Error LVDWARFReader::createScopes() { LLVM_DEBUG({ W.startLine() << "\n"; W.printString("File", Obj.getFileName().str()); @@ -864,7 +878,7 @@ Error LVELFReader::createScopes() { // Additional discussions here: // https://www.mail-archive.com/dwarf-discuss@lists.dwarfstd.org/msg00883.html - // The ELF Reader is expecting the files are 1-indexed, so using + // The DWARF reader is expecting the files are 1-indexed, so using // the .debug_line header information decide if the indexed require // an internal adjustment. @@ -904,7 +918,7 @@ Error LVELFReader::createScopes() { // DWARF-5 -> Increment index. return true; }; - // The ELF reader expects the indexes as 1-indexed. + // The DWARF reader expects the indexes as 1-indexed. IncrementFileIndex = DeduceIncrementFileIndex(); DWARFDie UnitDie = CU->getUnitDIE(); @@ -967,11 +981,11 @@ Error LVELFReader::createScopes() { } // Get the location information for the associated attribute. -void LVELFReader::processLocationList(dwarf::Attribute Attr, - const DWARFFormValue &FormValue, - const DWARFDie &Die, - uint64_t OffsetOnEntry, - bool CallSiteLocation) { +void LVDWARFReader::processLocationList(dwarf::Attribute Attr, + const DWARFFormValue &FormValue, + const DWARFDie &Die, + uint64_t OffsetOnEntry, + bool CallSiteLocation) { auto ProcessLocationExpression = [&](const DWARFExpression &Expression) { for (const DWARFExpression::Operation &Op : Expression) @@ -1048,10 +1062,10 @@ void LVELFReader::processLocationList(dwarf::Attribute Attr, } } -void LVELFReader::processLocationMember(dwarf::Attribute Attr, - const DWARFFormValue &FormValue, - const DWARFDie &Die, - uint64_t OffsetOnEntry) { +void LVDWARFReader::processLocationMember(dwarf::Attribute Attr, + const DWARFFormValue &FormValue, + const DWARFDie &Die, + uint64_t OffsetOnEntry) { // Check if the value is an integer constant. if (FormValue.isFormClass(DWARFFormValue::FC_Constant)) // Add a record to hold a constant as location. @@ -1063,8 +1077,8 @@ void LVELFReader::processLocationMember(dwarf::Attribute Attr, } // Update the current element with the reference. -void LVELFReader::updateReference(dwarf::Attribute Attr, - const DWARFFormValue &FormValue) { +void LVDWARFReader::updateReference(dwarf::Attribute Attr, + const DWARFFormValue &FormValue) { // FIXME: We are assuming that at most one Reference (DW_AT_specification, // DW_AT_abstract_origin, ...) and at most one Type (DW_AT_import, DW_AT_type) // appear in any single DIE, but this may not be true. @@ -1116,8 +1130,8 @@ void LVELFReader::updateReference(dwarf::Attribute Attr, } // Get an element given the DIE offset. -LVElement *LVELFReader::getElementForOffset(LVOffset Offset, LVElement *Element, - bool IsType) { +LVElement *LVDWARFReader::getElementForOffset(LVOffset Offset, + LVElement *Element, bool IsType) { auto Iter = ElementTable.try_emplace(Offset).first; // Update the element and all the references pointing to this element. LVElementEntry &Entry = Iter->second; @@ -1130,7 +1144,7 @@ LVElement *LVELFReader::getElementForOffset(LVOffset Offset, LVElement *Element, return Entry.Element; } -Error LVELFReader::loadTargetInfo(const ObjectFile &Obj) { +Error LVDWARFReader::loadTargetInfo(const ObjectFile &Obj) { // Detect the architecture from the object file. We usually don't need OS // info to lookup a target and create register info. Triple TT; @@ -1149,7 +1163,7 @@ Error LVELFReader::loadTargetInfo(const ObjectFile &Obj) { return loadGenericTargetInfo(TT.str(), FeaturesValue.getString()); } -void LVELFReader::mapRangeAddress(const ObjectFile &Obj) { +void LVDWARFReader::mapRangeAddress(const ObjectFile &Obj) { for (auto Iter = Obj.symbol_begin(); Iter != Obj.symbol_end(); ++Iter) { const SymbolRef &Symbol = *Iter; @@ -1225,9 +1239,9 @@ void LVELFReader::mapRangeAddress(const ObjectFile &Obj) { } } -void LVELFReader::sortScopes() { Root->sort(); } +void LVDWARFReader::sortScopes() { Root->sort(); } -void LVELFReader::print(raw_ostream &OS) const { +void LVDWARFReader::print(raw_ostream &OS) const { OS << "LVType\n"; LLVM_DEBUG(dbgs() << "CreateReaders\n"); } diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp index 5f29226c14b705ab22eacbe15fd105dea9ec1483..32c5e3251df62f0f274f726e35bb10aa8a205890 100644 --- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp +++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -628,13 +628,20 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { ObjectPair Objects = ObjectsOrErr.get(); std::unique_ptr<DIContext> Context; - // If this is a COFF object containing PDB info, use a PDBContext to - // symbolize. Otherwise, use DWARF. + // If this is a COFF object containing PDB info and not containing DWARF + // section, use a PDBContext to symbolize. Otherwise, use DWARF. if (auto CoffObject = dyn_cast<COFFObjectFile>(Objects.first)) { const codeview::DebugInfo *DebugInfo; StringRef PDBFileName; auto EC = CoffObject->getDebugPDBInfo(DebugInfo, PDBFileName); - if (!EC && DebugInfo != nullptr && !PDBFileName.empty()) { + // Use DWARF if there're DWARF sections. + bool HasDwarf = + llvm::any_of(Objects.first->sections(), [](SectionRef Section) -> bool { + if (Expected<StringRef> SectionName = Section.getName()) + return SectionName.get() == ".debug_info"; + return false; + }); + if (!EC && !HasDwarf && DebugInfo != nullptr && !PDBFileName.empty()) { using namespace pdb; std::unique_ptr<IPDBSession> Session; diff --git a/llvm/lib/ExecutionEngine/JITLink/DefineExternalSectionStartAndEndSymbols.h b/llvm/lib/ExecutionEngine/JITLink/DefineExternalSectionStartAndEndSymbols.h index 159880e4b152941c154210f18e827e17d10410d9..4a492ee2f7d07bb7d24ac2845fa493e144bbbf18 100644 --- a/llvm/lib/ExecutionEngine/JITLink/DefineExternalSectionStartAndEndSymbols.h +++ b/llvm/lib/ExecutionEngine/JITLink/DefineExternalSectionStartAndEndSymbols.h @@ -108,6 +108,48 @@ createDefineExternalSectionStartAndEndSymbolsPass( std::forward<SymbolIdentifierFunction>(F)); } +/// ELF section start/end symbol detection. +inline SectionRangeSymbolDesc +identifyELFSectionStartAndEndSymbols(LinkGraph &G, Symbol &Sym) { + constexpr StringRef StartSymbolPrefix = "__start_"; + constexpr StringRef EndSymbolPrefix = "__stop_"; + + auto SymName = Sym.getName(); + if (SymName.starts_with(StartSymbolPrefix)) { + if (auto *Sec = + G.findSectionByName(SymName.drop_front(StartSymbolPrefix.size()))) + return {*Sec, true}; + } else if (SymName.starts_with(EndSymbolPrefix)) { + if (auto *Sec = + G.findSectionByName(SymName.drop_front(EndSymbolPrefix.size()))) + return {*Sec, false}; + } + return {}; +} + +/// MachO section start/end symbol detection. +inline SectionRangeSymbolDesc +identifyMachOSectionStartAndEndSymbols(LinkGraph &G, Symbol &Sym) { + constexpr StringRef StartSymbolPrefix = "section$start$"; + constexpr StringRef EndSymbolPrefix = "section$end$"; + + auto SymName = Sym.getName(); + if (SymName.starts_with(StartSymbolPrefix)) { + auto [SegName, SecName] = + SymName.drop_front(StartSymbolPrefix.size()).split('$'); + std::string SectionName = (SegName + "," + SecName).str(); + if (auto *Sec = G.findSectionByName(SectionName)) + return {*Sec, true}; + } else if (SymName.starts_with(EndSymbolPrefix)) { + auto [SegName, SecName] = + SymName.drop_front(EndSymbolPrefix.size()).split('$'); + std::string SectionName = (SegName + "," + SecName).str(); + if (auto *Sec = G.findSectionByName(SectionName)) + return {*Sec, false}; + } + return {}; +} + } // end namespace jitlink } // end namespace llvm diff --git a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h index e1b11dfcfc211a11ad21d8fea7d5314453538a45..5dae6006293957e56e892163b9d47b83c69c0951 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h +++ b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h @@ -193,7 +193,7 @@ ELFLinkGraphBuilder<ELFT>::ELFLinkGraphBuilder( StringRef FileName, LinkGraph::GetEdgeKindNameFunction GetEdgeKindName) : ELFLinkGraphBuilderBase(std::make_unique<LinkGraph>( FileName.str(), Triple(std::move(TT)), std::move(Features), - ELFT::Is64Bits ? 8 : 4, llvm::endianness(ELFT::TargetEndianness), + ELFT::Is64Bits ? 8 : 4, llvm::endianness(ELFT::Endianness), std::move(GetEdgeKindName))), Obj(Obj) { LLVM_DEBUG( diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp index f17b2c626ac250dde5e3050d4b412e0e03939bd7..6b03bb3c90b20e52d5ffb368d66ba09c2739ebc0 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp @@ -11,15 +11,17 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/JITLink/ELF_aarch64.h" -#include "EHFrameSupportImpl.h" -#include "ELFLinkGraphBuilder.h" -#include "JITLinkGeneric.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" #include "llvm/ExecutionEngine/JITLink/aarch64.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Endian.h" +#include "DefineExternalSectionStartAndEndSymbols.h" +#include "EHFrameSupportImpl.h" +#include "ELFLinkGraphBuilder.h" +#include "JITLinkGeneric.h" + #define DEBUG_TYPE "jitlink" using namespace llvm; @@ -611,6 +613,11 @@ void link_ELF_aarch64(std::unique_ptr<LinkGraph> G, else Config.PrePrunePasses.push_back(markAllSymbolsLive); + // Resolve any external section start / end symbols. + Config.PostAllocationPasses.push_back( + createDefineExternalSectionStartAndEndSymbolsPass( + identifyELFSectionStartAndEndSymbols)); + // Add an in-place GOT/TLS/Stubs build pass. Config.PostPrunePasses.push_back(buildTables_ELF_aarch64); } diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp index a1fe9c5fcd733a8cddb45bb0cc667f24615bf4aa..52dd83d9040fe85487962893678038935974f3ed 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp @@ -343,24 +343,6 @@ createLinkGraphFromELFObject_x86_64(MemoryBufferRef ObjectBuffer) { .buildGraph(); } -static SectionRangeSymbolDesc -identifyELFSectionStartAndEndSymbols(LinkGraph &G, Symbol &Sym) { - constexpr StringRef StartSymbolPrefix = "__start"; - constexpr StringRef EndSymbolPrefix = "__end"; - - auto SymName = Sym.getName(); - if (SymName.starts_with(StartSymbolPrefix)) { - if (auto *Sec = - G.findSectionByName(SymName.drop_front(StartSymbolPrefix.size()))) - return {*Sec, true}; - } else if (SymName.starts_with(EndSymbolPrefix)) { - if (auto *Sec = - G.findSectionByName(SymName.drop_front(EndSymbolPrefix.size()))) - return {*Sec, false}; - } - return {}; -} - void link_ELF_x86_64(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx) { PassConfiguration Config; diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp index 7f743dba60a93450d5fc350404b111ca74c6b787..b103a9ca98e1899f28f6d51c1edff17cfedf0c71 100644 --- a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp @@ -338,7 +338,8 @@ void LinkGraph::dump(raw_ostream &OS) { OS << "\nExternal symbols:\n"; if (!external_symbols().empty()) { for (auto *Sym : external_symbols()) - OS << " " << Sym->getAddress() << ": " << *Sym << "\n"; + OS << " " << Sym->getAddress() << ": " << *Sym + << (Sym->isWeaklyReferenced() ? " (weakly referenced)" : "") << "\n"; } else OS << " none\n"; } diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp index 556031baaaed500198f9627a1ec5f1ad996973ee..8733306bab6b5f38a8420878849c19425e79e046 100644 --- a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp @@ -14,6 +14,7 @@ #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" #include "llvm/ExecutionEngine/JITLink/aarch64.h" +#include "DefineExternalSectionStartAndEndSymbols.h" #include "MachOLinkGraphBuilder.h" #define DEBUG_TYPE "jitlink" @@ -593,6 +594,11 @@ void link_MachO_arm64(std::unique_ptr<LinkGraph> G, Config.PrePrunePasses.push_back(createEHFrameSplitterPass_MachO_arm64()); Config.PrePrunePasses.push_back(createEHFrameEdgeFixerPass_MachO_arm64()); + // Resolve any external section start / end symbols. + Config.PostAllocationPasses.push_back( + createDefineExternalSectionStartAndEndSymbolsPass( + identifyMachOSectionStartAndEndSymbols)); + // Add an in-place GOT/Stubs pass. Config.PostPrunePasses.push_back(buildTables_MachO_arm64); } diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp index eeca27771ad646dbfcf66ad4a73acaf0bfd76afb..2c69d61316a8ad7f86195d766e3433f29b83543a 100644 --- a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp @@ -14,6 +14,7 @@ #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" #include "llvm/ExecutionEngine/JITLink/x86_64.h" +#include "DefineExternalSectionStartAndEndSymbols.h" #include "MachOLinkGraphBuilder.h" #define DEBUG_TYPE "jitlink" @@ -516,6 +517,11 @@ void link_MachO_x86_64(std::unique_ptr<LinkGraph> G, else Config.PrePrunePasses.push_back(markAllSymbolsLive); + // Resolve any external section start / end symbols. + Config.PostAllocationPasses.push_back( + createDefineExternalSectionStartAndEndSymbolsPass( + identifyMachOSectionStartAndEndSymbols)); + // Add an in-place GOT/Stubs pass. Config.PostPrunePasses.push_back(buildGOTAndStubs_MachO_x86_64); diff --git a/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp b/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp index 88cc3b04fb6425aef54c99b32af6e1ddccf2bdee..ec2187bad0f2c7c8e1a3f197cf1f8a711461be04 100644 --- a/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp +++ b/llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp @@ -7,8 +7,11 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h" +#include "llvm/ExecutionEngine/Orc/DebugUtils.h" #include "llvm/Support/Error.h" +#define DEBUG_TYPE "orc" + namespace llvm { namespace orc { @@ -31,6 +34,11 @@ Error EPCDynamicLibrarySearchGenerator::tryToGenerate( if (Symbols.empty()) return Error::success(); + LLVM_DEBUG({ + dbgs() << "EPCDynamicLibrarySearchGenerator trying to generate " + << Symbols << "\n"; + }); + SymbolLookupSet LookupSymbols; for (auto &KV : Symbols) { @@ -44,8 +52,12 @@ Error EPCDynamicLibrarySearchGenerator::tryToGenerate( // Copy-capture LookupSymbols, since LookupRequest keeps a reference. EPC.lookupSymbolsAsync(Request, [this, &JD, LS = std::move(LS), LookupSymbols](auto Result) mutable { - if (!Result) + if (!Result) { + LLVM_DEBUG({ + dbgs() << "EPCDynamicLibrarySearchGenerator lookup failed due to error"; + }); return LS.continueLookup(Result.takeError()); + } assert(Result->size() == 1 && "Results for more than one library returned"); assert(Result->front().size() == LookupSymbols.size() && @@ -59,6 +71,11 @@ Error EPCDynamicLibrarySearchGenerator::tryToGenerate( ++ResultI; } + LLVM_DEBUG({ + dbgs() << "EPCDynamicLibrarySearchGenerator lookup returned " + << NewSymbols << "\n"; + }); + // If there were no resolved symbols bail out. if (NewSymbols.empty()) return LS.continueLookup(Error::success()); diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp index 3952445bb1aa4bcd40a4cd5f0c280f39451c6f99..670c8cf996fd615d8f69d4297d5651dbfd7874b5 100644 --- a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp @@ -545,7 +545,7 @@ DLLImportDefinitionGenerator::getTargetPointerSize(const Triple &TT) { } Expected<llvm::endianness> -DLLImportDefinitionGenerator::getTargetEndianness(const Triple &TT) { +DLLImportDefinitionGenerator::getEndianness(const Triple &TT) { switch (TT.getArch()) { case Triple::x86_64: return llvm::endianness::little; @@ -562,7 +562,7 @@ DLLImportDefinitionGenerator::createStubsGraph(const SymbolMap &Resolved) { auto PointerSize = getTargetPointerSize(TT); if (!PointerSize) return PointerSize.takeError(); - auto Endianness = getTargetEndianness(TT); + auto Endianness = getEndianness(TT); if (!Endianness) return Endianness.takeError(); diff --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp index 994acf5843642aabaac0eda8ed89a17e514c7e5d..1fa8a1274911ca3729d3a77c78177040b07c4ecc 100644 --- a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp +++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp @@ -255,7 +255,7 @@ struct ObjCImageInfoFlags { namespace llvm { namespace orc { -MachOPlatform::HeaderOptions::BuildVersionOpts +std::optional<MachOPlatform::HeaderOptions::BuildVersionOpts> MachOPlatform::HeaderOptions::BuildVersionOpts::fromTriple(const Triple &TT, uint32_t MinOS, uint32_t SDK) { @@ -263,26 +263,25 @@ MachOPlatform::HeaderOptions::BuildVersionOpts::fromTriple(const Triple &TT, uint32_t Platform; switch (TT.getOS()) { case Triple::IOS: - Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_IOS - : MachO::PLATFORM_IOSSIMULATOR; + Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_IOSSIMULATOR + : MachO::PLATFORM_IOS; break; case Triple::MacOSX: Platform = MachO::PLATFORM_MACOS; break; case Triple::TvOS: - Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_TVOS - : MachO::PLATFORM_TVOSSIMULATOR; + Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_TVOSSIMULATOR + : MachO::PLATFORM_TVOS; break; case Triple::WatchOS: - Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_WATCHOS - : MachO::PLATFORM_WATCHOSSIMULATOR; + Platform = TT.isSimulatorEnvironment() ? MachO::PLATFORM_WATCHOSSIMULATOR + : MachO::PLATFORM_WATCHOS; break; default: - Platform = MachO::PLATFORM_UNKNOWN; - break; + return std::nullopt; } - return {Platform, MinOS, SDK}; + return MachOPlatform::HeaderOptions::BuildVersionOpts{Platform, MinOS, SDK}; } Expected<std::unique_ptr<MachOPlatform>> MachOPlatform::Create( @@ -1725,11 +1724,9 @@ jitlink::Block &createHeaderBlock(MachOPlatform &MOP, else B.template addLoadCommand<MachO::LC_ID_DYLIB>(JD.getName(), 0, 0, 0); - if (Opts.BuildVersion) + for (auto &BV : Opts.BuildVersions) B.template addLoadCommand<MachO::LC_BUILD_VERSION>( - Opts.BuildVersion->Platform, Opts.BuildVersion->MinOS, - Opts.BuildVersion->SDK, static_cast<uint32_t>(0)); - + BV.Platform, BV.MinOS, BV.SDK, static_cast<uint32_t>(0)); for (auto &D : Opts.LoadDylibs) B.template addLoadCommand<MachO::LC_LOAD_DYLIB>( D.Name, D.Timestamp, D.CurrentVersion, D.CompatibilityVersion); diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp index 8a4145a6b02a266a7acf9e9f05c8d4e6c9e4e0fe..7529d9cef67ed52492d092a588bfed58d961ed2b 100644 --- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp +++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp @@ -26,11 +26,13 @@ extern "C" { // We put information about the JITed function in this global, which the // debugger reads. Make sure to specify the version statically, because the // debugger checks the version before we can set it during runtime. +LLVM_ATTRIBUTE_VISIBILITY_DEFAULT struct jit_descriptor __jit_debug_descriptor = {JitDescriptorVersion, 0, nullptr, nullptr}; // Debuggers that implement the GDB JIT interface put a special breakpoint in // this function. +LLVM_ATTRIBUTE_VISIBILITY_DEFAULT LLVM_ATTRIBUTE_NOINLINE void __jit_debug_register_code() { // The noinline and the asm prevent calls to this function from being // optimized out. diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.cpp index d346214d3ae29111ec0c78ae3dfb9e1a4c8083a4..57ac991ee37f3d97dcdee2dd438d8c70553d0dc6 100644 --- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.cpp +++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.cpp @@ -87,7 +87,7 @@ static void registerJITLoaderVTuneUnregisterImpl( for (auto &Method : UM) { JITEventWrapper::Wrapper->iJIT_NotifyEvent( iJVM_EVENT_TYPE_METHOD_UNLOAD_START, - const_cast<unsigned long *>(&Method.first)); + const_cast<uint64_t *>(&Method.first)); } } diff --git a/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp b/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp index fec1bdbe9d8c7436dbb967b52a8c8d9180524832..7241d15ed1c6707200f7a494e4f382eff0a1c45a 100644 --- a/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp +++ b/llvm/lib/Frontend/Offloading/OffloadWrapper.cpp @@ -186,57 +186,62 @@ GlobalVariable *createBinDesc(Module &M, ArrayRef<ArrayRef<char>> Bufs, ".omp_offloading.descriptor" + Suffix); } -void createRegisterFunction(Module &M, GlobalVariable *BinDesc, - StringRef Suffix) { +Function *createUnregisterFunction(Module &M, GlobalVariable *BinDesc, + StringRef Suffix) { LLVMContext &C = M.getContext(); auto *FuncTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false); - auto *Func = Function::Create(FuncTy, GlobalValue::InternalLinkage, - ".omp_offloading.descriptor_reg" + Suffix, &M); + auto *Func = + Function::Create(FuncTy, GlobalValue::InternalLinkage, + ".omp_offloading.descriptor_unreg" + Suffix, &M); Func->setSection(".text.startup"); - // Get __tgt_register_lib function declaration. - auto *RegFuncTy = FunctionType::get(Type::getVoidTy(C), getBinDescPtrTy(M), - /*isVarArg*/ false); - FunctionCallee RegFuncC = - M.getOrInsertFunction("__tgt_register_lib", RegFuncTy); + // Get __tgt_unregister_lib function declaration. + auto *UnRegFuncTy = FunctionType::get(Type::getVoidTy(C), getBinDescPtrTy(M), + /*isVarArg*/ false); + FunctionCallee UnRegFuncC = + M.getOrInsertFunction("__tgt_unregister_lib", UnRegFuncTy); // Construct function body IRBuilder<> Builder(BasicBlock::Create(C, "entry", Func)); - Builder.CreateCall(RegFuncC, BinDesc); + Builder.CreateCall(UnRegFuncC, BinDesc); Builder.CreateRetVoid(); - // Add this function to constructors. - // Set priority to 1 so that __tgt_register_lib is executed AFTER - // __tgt_register_requires (we want to know what requirements have been - // asked for before we load a libomptarget plugin so that by the time the - // plugin is loaded it can report how many devices there are which can - // satisfy these requirements). - appendToGlobalCtors(M, Func, /*Priority*/ 1); + return Func; } -void createUnregisterFunction(Module &M, GlobalVariable *BinDesc, - StringRef Suffix) { +void createRegisterFunction(Module &M, GlobalVariable *BinDesc, + StringRef Suffix) { LLVMContext &C = M.getContext(); auto *FuncTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg*/ false); - auto *Func = - Function::Create(FuncTy, GlobalValue::InternalLinkage, - ".omp_offloading.descriptor_unreg" + Suffix, &M); + auto *Func = Function::Create(FuncTy, GlobalValue::InternalLinkage, + ".omp_offloading.descriptor_reg" + Suffix, &M); Func->setSection(".text.startup"); - // Get __tgt_unregister_lib function declaration. - auto *UnRegFuncTy = FunctionType::get(Type::getVoidTy(C), getBinDescPtrTy(M), - /*isVarArg*/ false); - FunctionCallee UnRegFuncC = - M.getOrInsertFunction("__tgt_unregister_lib", UnRegFuncTy); + // Get __tgt_register_lib function declaration. + auto *RegFuncTy = FunctionType::get(Type::getVoidTy(C), getBinDescPtrTy(M), + /*isVarArg*/ false); + FunctionCallee RegFuncC = + M.getOrInsertFunction("__tgt_register_lib", RegFuncTy); + + auto *AtExitTy = FunctionType::get( + Type::getInt32Ty(C), PointerType::getUnqual(C), /*isVarArg=*/false); + FunctionCallee AtExit = M.getOrInsertFunction("atexit", AtExitTy); + + Function *UnregFunc = createUnregisterFunction(M, BinDesc, Suffix); // Construct function body IRBuilder<> Builder(BasicBlock::Create(C, "entry", Func)); - Builder.CreateCall(UnRegFuncC, BinDesc); + + // Register the destructors with 'atexit'. This is expected by the CUDA + // runtime and ensures that we clean up before dynamic objects are destroyed. + // This needs to be done before the runtime is called and registers its own. + Builder.CreateCall(AtExit, UnregFunc); + + Builder.CreateCall(RegFuncC, BinDesc); Builder.CreateRetVoid(); - // Add this function to global destructors. - // Match priority of __tgt_register_lib - appendToGlobalDtors(M, Func, /*Priority*/ 1); + // Add this function to constructors. + appendToGlobalCtors(M, Func, /*Priority=*/101); } // struct fatbin_wrapper { @@ -578,7 +583,7 @@ void createRegisterFatbinFunction(Module &M, GlobalVariable *FatbinDesc, DtorBuilder.CreateRetVoid(); // Add this function to constructors. - appendToGlobalCtors(M, CtorFunc, /*Priority*/ 1); + appendToGlobalCtors(M, CtorFunc, /*Priority=*/101); } } // namespace @@ -591,7 +596,6 @@ Error offloading::wrapOpenMPBinaries(Module &M, ArrayRef<ArrayRef<char>> Images, return createStringError(inconvertibleErrorCode(), "No binary descriptors created."); createRegisterFunction(M, Desc, Suffix); - createUnregisterFunction(M, Desc, Suffix); return Error::success(); } diff --git a/llvm/lib/Frontend/OpenMP/OMPContext.cpp b/llvm/lib/Frontend/OpenMP/OMPContext.cpp index e870c5aa2ba6b84b4bb53b817cb6ee3c068f876c..37936d6000c8912d7941378cf1a3f8b80d16175b 100644 --- a/llvm/lib/Frontend/OpenMP/OMPContext.cpp +++ b/llvm/lib/Frontend/OpenMP/OMPContext.cpp @@ -44,6 +44,7 @@ OMPContext::OMPContext(bool IsDeviceCompilation, Triple TargetTriple) { case Triple::ppcle: case Triple::ppc64: case Triple::ppc64le: + case Triple::systemz: case Triple::x86: case Triple::x86_64: ActiveTraits.set(unsigned(TraitProperty::device_kind_cpu)); diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp index d65ed8c11d86cc0e4537f7331525581209e6b54f..16507a69ea8502e8a1f7ced7ae4bd682f7e38b58 100644 --- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp +++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp @@ -2110,7 +2110,7 @@ Function *getFreshReductionFunc(Module &M) { OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createReductions( const LocationDescription &Loc, InsertPointTy AllocaIP, - ArrayRef<ReductionInfo> ReductionInfos, bool IsNoWait) { + ArrayRef<ReductionInfo> ReductionInfos, bool IsNoWait, bool IsByRef) { for (const ReductionInfo &RI : ReductionInfos) { (void)RI; assert(RI.Variable && "expected non-null variable"); @@ -2197,17 +2197,29 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createReductions( for (auto En : enumerate(ReductionInfos)) { const ReductionInfo &RI = En.value(); Type *ValueType = RI.ElementType; - Value *RedValue = Builder.CreateLoad(ValueType, RI.Variable, - "red.value." + Twine(En.index())); + // We have one less load for by-ref case because that load is now inside of + // the reduction region + Value *RedValue = nullptr; + if (!IsByRef) { + RedValue = Builder.CreateLoad(ValueType, RI.Variable, + "red.value." + Twine(En.index())); + } Value *PrivateRedValue = Builder.CreateLoad(ValueType, RI.PrivateVariable, "red.private.value." + Twine(En.index())); Value *Reduced; - Builder.restoreIP( - RI.ReductionGen(Builder.saveIP(), RedValue, PrivateRedValue, Reduced)); + if (IsByRef) { + Builder.restoreIP(RI.ReductionGen(Builder.saveIP(), RI.Variable, + PrivateRedValue, Reduced)); + } else { + Builder.restoreIP(RI.ReductionGen(Builder.saveIP(), RedValue, + PrivateRedValue, Reduced)); + } if (!Builder.GetInsertBlock()) return InsertPointTy(); - Builder.CreateStore(Reduced, RI.Variable); + // for by-ref case, the load is inside of the reduction region + if (!IsByRef) + Builder.CreateStore(Reduced, RI.Variable); } Function *EndReduceFunc = getOrCreateRuntimeFunctionPtr( IsNoWait ? RuntimeFunction::OMPRTL___kmpc_end_reduce_nowait @@ -2219,7 +2231,7 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createReductions( // function. There are no loads/stores here because they will be happening // inside the atomic elementwise reduction. Builder.SetInsertPoint(AtomicRedBlock); - if (CanGenerateAtomic) { + if (CanGenerateAtomic && !IsByRef) { for (const ReductionInfo &RI : ReductionInfos) { Builder.restoreIP(RI.AtomicReductionGen(Builder.saveIP(), RI.ElementType, RI.Variable, RI.PrivateVariable)); @@ -2257,7 +2269,9 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createReductions( Builder.restoreIP(RI.ReductionGen(Builder.saveIP(), LHS, RHS, Reduced)); if (!Builder.GetInsertBlock()) return InsertPointTy(); - Builder.CreateStore(Reduced, LHSPtr); + // store is inside of the reduction region when using by-ref + if (!IsByRef) + Builder.CreateStore(Reduced, LHSPtr); } Builder.CreateRetVoid(); @@ -4869,8 +4883,11 @@ OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::createTargetData( return InsertPointTy(); // Disable TargetData CodeGen on Device pass. - if (Config.IsTargetDevice.value_or(false)) + if (Config.IsTargetDevice.value_or(false)) { + if (BodyGenCB) + Builder.restoreIP(BodyGenCB(Builder.saveIP(), BodyGenTy::NoPriv)); return Builder.saveIP(); + } Builder.restoreIP(CodeGenIP); bool IsStandAlone = !BodyGenCB; @@ -5056,10 +5073,15 @@ FunctionCallee OpenMPIRBuilder::createDispatchFiniFunction(unsigned IVSize, static void replaceConstatExprUsesInFuncWithInstr(ConstantExpr *ConstExpr, Function *Func) { - for (User *User : make_early_inc_range(ConstExpr->users())) - if (auto *Instr = dyn_cast<Instruction>(User)) - if (Instr->getFunction() == Func) - Instr->replaceUsesOfWith(ConstExpr, ConstExpr->getAsInstruction(Instr)); + for (User *User : make_early_inc_range(ConstExpr->users())) { + if (auto *Instr = dyn_cast<Instruction>(User)) { + if (Instr->getFunction() == Func) { + Instruction *ConstInst = ConstExpr->getAsInstruction(); + ConstInst->insertBefore(*Instr->getParent(), Instr->getIterator()); + Instr->replaceUsesOfWith(ConstExpr, ConstInst); + } + } + } } static void replaceConstantValueUsesInFuncWithInstr(llvm::Value *Input, diff --git a/llvm/lib/FuzzMutate/OpDescriptor.cpp b/llvm/lib/FuzzMutate/OpDescriptor.cpp index 4baf45284de105e79e0cb7c7e08125bfcf17f8e2..6ec70d917918f378930b8b89cebddace761f068f 100644 --- a/llvm/lib/FuzzMutate/OpDescriptor.cpp +++ b/llvm/lib/FuzzMutate/OpDescriptor.cpp @@ -8,10 +8,15 @@ #include "llvm/FuzzMutate/OpDescriptor.h" #include "llvm/IR/Constants.h" +#include "llvm/Support/CommandLine.h" using namespace llvm; using namespace fuzzerop; +static cl::opt<bool> UseUndef("use-undef", + cl::desc("Use undef when generating programs."), + cl::init(false)); + void fuzzerop::makeConstantsWithType(Type *T, std::vector<Constant *> &Cs) { if (auto *IntTy = dyn_cast<IntegerType>(T)) { uint64_t W = IntTy->getBitWidth(); @@ -42,7 +47,8 @@ void fuzzerop::makeConstantsWithType(Type *T, std::vector<Constant *> &Cs) { Cs.push_back(ConstantVector::getSplat(EC, Elt)); } } else { - Cs.push_back(UndefValue::get(T)); + if (UseUndef) + Cs.push_back(UndefValue::get(T)); Cs.push_back(PoisonValue::get(T)); } } diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 1beb4c069a6997b64536ec9a6105a0f1c6bcef64..b778a14158ef2be0ba8d3fe946c86bec5e8b4be8 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -286,7 +286,7 @@ static const Module *getModuleFromVal(const Value *V) { return nullptr; } -static const Module *getModuleFromDPI(const DPMarker *Marker) { +static const Module *getModuleFromDPI(const DbgMarker *Marker) { const Function *M = Marker->getParent() ? Marker->getParent()->getParent() : nullptr; return M ? M->getParent() : nullptr; @@ -363,6 +363,9 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) { case CallingConv::AMDGPU_KERNEL: Out << "amdgpu_kernel"; break; case CallingConv::AMDGPU_Gfx: Out << "amdgpu_gfx"; break; case CallingConv::M68k_RTD: Out << "m68k_rtdcc"; break; + case CallingConv::RISCV_VectorCall: + Out << "riscv_vector_cc"; + break; } } @@ -862,7 +865,7 @@ private: void processInstructionMetadata(const Instruction &I); /// Add all of the metadata from a DbgRecord. - void processDbgRecordMetadata(const DbgRecord &DPV); + void processDbgRecordMetadata(const DbgRecord &DVR); }; } // end namespace llvm @@ -1139,15 +1142,21 @@ void SlotTracker::processFunctionMetadata(const Function &F) { } void SlotTracker::processDbgRecordMetadata(const DbgRecord &DR) { - if (const DPValue *DPV = dyn_cast<const DPValue>(&DR)) { + if (const DbgVariableRecord *DVR = dyn_cast<const DbgVariableRecord>(&DR)) { // Process metadata used by DbgRecords; we only specifically care about the // DILocalVariable, DILocation, and DIAssignID fields, as the Value and // Expression fields should only be printed inline and so do not use a slot. - CreateMetadataSlot(DPV->getRawVariable()); - if (DPV->isDbgAssign()) - CreateMetadataSlot(cast<MDNode>(DPV->getRawAssignID())); - } else if (const DPLabel *DPL = dyn_cast<const DPLabel>(&DR)) { - CreateMetadataSlot(DPL->getRawLabel()); + // Note: The above doesn't apply for empty-metadata operands. + if (auto *Empty = dyn_cast<MDNode>(DVR->getRawLocation())) + CreateMetadataSlot(Empty); + CreateMetadataSlot(DVR->getRawVariable()); + if (DVR->isDbgAssign()) { + CreateMetadataSlot(cast<MDNode>(DVR->getRawAssignID())); + if (auto *Empty = dyn_cast<MDNode>(DVR->getRawAddress())) + CreateMetadataSlot(Empty); + } + } else if (const DbgLabelRecord *DLR = dyn_cast<const DbgLabelRecord>(&DR)) { + CreateMetadataSlot(DLR->getRawLabel()); } else { llvm_unreachable("unsupported DbgRecord kind"); } @@ -1408,9 +1417,18 @@ static void WriteOptimizationInfo(raw_ostream &Out, const User *U) { } else if (const GEPOperator *GEP = dyn_cast<GEPOperator>(U)) { if (GEP->isInBounds()) Out << " inbounds"; + if (auto InRange = GEP->getInRange()) { + Out << " inrange(" << InRange->getLower() << ", " << InRange->getUpper() + << ")"; + } } else if (const auto *NNI = dyn_cast<PossiblyNonNegInst>(U)) { if (NNI->hasNonNeg()) Out << " nneg"; + } else if (const auto *TI = dyn_cast<TruncInst>(U)) { + if (TI->hasNoUnsignedWrap()) + Out << " nuw"; + if (TI->hasNoSignedWrap()) + Out << " nsw"; } } @@ -1685,18 +1703,13 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, Out << ' ' << static_cast<CmpInst::Predicate>(CE->getPredicate()); Out << " ("; - std::optional<unsigned> InRangeOp; if (const GEPOperator *GEP = dyn_cast<GEPOperator>(CE)) { WriterCtx.TypePrinter->print(GEP->getSourceElementType(), Out); Out << ", "; - InRangeOp = GEP->getInRangeIndex(); - if (InRangeOp) - ++*InRangeOp; } - for (User::const_op_iterator OI=CE->op_begin(); OI != CE->op_end(); ++OI) { - if (InRangeOp && unsigned(OI - CE->op_begin()) == *InRangeOp) - Out << "inrange "; + for (User::const_op_iterator OI = CE->op_begin(); OI != CE->op_end(); + ++OI) { WriterCtx.TypePrinter->print((*OI)->getType(), Out); Out << ' '; WriteAsOperandInternal(Out, *OI, WriterCtx); @@ -2135,6 +2148,16 @@ static void writeDIDerivedType(raw_ostream &Out, const DIDerivedType *N, Printer.printInt("dwarfAddressSpace", *DWARFAddressSpace, /* ShouldSkipZero */ false); Printer.printMetadata("annotations", N->getRawAnnotations()); + if (auto PtrAuthData = N->getPtrAuthData()) { + Printer.printInt("ptrAuthKey", PtrAuthData->key()); + Printer.printBool("ptrAuthIsAddressDiscriminated", + PtrAuthData->isAddressDiscriminated()); + Printer.printInt("ptrAuthExtraDiscriminator", + PtrAuthData->extraDiscriminator()); + Printer.printBool("ptrAuthIsaPointer", PtrAuthData->isaPointer()); + Printer.printBool("ptrAuthAuthenticatesNullValues", + PtrAuthData->authenticatesNullValues()); + } Out << ")"; } @@ -2702,11 +2725,11 @@ public: void printBasicBlock(const BasicBlock *BB); void printInstructionLine(const Instruction &I); void printInstruction(const Instruction &I); - void printDPMarker(const DPMarker &DPI); - void printDPValue(const DPValue &DPI); - void printDPLabel(const DPLabel &DPL); - void printDbgRecord(const DbgRecord &DPI); - void printDbgRecordLine(const DbgRecord &DPI); + void printDbgMarker(const DbgMarker &DPI); + void printDbgVariableRecord(const DbgVariableRecord &DVR); + void printDbgLabelRecord(const DbgLabelRecord &DLR); + void printDbgRecord(const DbgRecord &DR); + void printDbgRecordLine(const DbgRecord &DR); void printUseListOrder(const Value *V, const std::vector<unsigned> &Shuffle); void printUseLists(const Function *F); @@ -4589,61 +4612,62 @@ void AssemblyWriter::printInstruction(const Instruction &I) { printInfoComment(I); } -void AssemblyWriter::printDPMarker(const DPMarker &Marker) { - // There's no formal representation of a DPMarker -- print purely as a +void AssemblyWriter::printDbgMarker(const DbgMarker &Marker) { + // There's no formal representation of a DbgMarker -- print purely as a // debugging aid. - for (const DbgRecord &DPR : Marker.StoredDPValues) { + for (const DbgRecord &DPR : Marker.StoredDbgRecords) { printDbgRecord(DPR); Out << "\n"; } - Out << " DPMarker -> { "; + Out << " DbgMarker -> { "; printInstruction(*Marker.MarkedInstr); Out << " }"; return; } void AssemblyWriter::printDbgRecord(const DbgRecord &DR) { - if (auto *DPV = dyn_cast<DPValue>(&DR)) - printDPValue(*DPV); - else if (auto *DPL = dyn_cast<DPLabel>(&DR)) - printDPLabel(*DPL); + if (auto *DVR = dyn_cast<DbgVariableRecord>(&DR)) + printDbgVariableRecord(*DVR); + else if (auto *DLR = dyn_cast<DbgLabelRecord>(&DR)) + printDbgLabelRecord(*DLR); else llvm_unreachable("Unexpected DbgRecord kind"); } -void AssemblyWriter::printDPValue(const DPValue &DPV) { +void AssemblyWriter::printDbgVariableRecord(const DbgVariableRecord &DVR) { auto WriterCtx = getContext(); Out << "#dbg_"; - switch (DPV.getType()) { - case DPValue::LocationType::Value: + switch (DVR.getType()) { + case DbgVariableRecord::LocationType::Value: Out << "value"; break; - case DPValue::LocationType::Declare: + case DbgVariableRecord::LocationType::Declare: Out << "declare"; break; - case DPValue::LocationType::Assign: + case DbgVariableRecord::LocationType::Assign: Out << "assign"; break; default: - llvm_unreachable("Tried to print a DPValue with an invalid LocationType!"); + llvm_unreachable( + "Tried to print a DbgVariableRecord with an invalid LocationType!"); } Out << "("; - WriteAsOperandInternal(Out, DPV.getRawLocation(), WriterCtx, true); + WriteAsOperandInternal(Out, DVR.getRawLocation(), WriterCtx, true); Out << ", "; - WriteAsOperandInternal(Out, DPV.getRawVariable(), WriterCtx, true); + WriteAsOperandInternal(Out, DVR.getRawVariable(), WriterCtx, true); Out << ", "; - WriteAsOperandInternal(Out, DPV.getRawExpression(), WriterCtx, true); + WriteAsOperandInternal(Out, DVR.getRawExpression(), WriterCtx, true); Out << ", "; - if (DPV.isDbgAssign()) { - WriteAsOperandInternal(Out, DPV.getRawAssignID(), WriterCtx, true); + if (DVR.isDbgAssign()) { + WriteAsOperandInternal(Out, DVR.getRawAssignID(), WriterCtx, true); Out << ", "; - WriteAsOperandInternal(Out, DPV.getRawAddress(), WriterCtx, true); + WriteAsOperandInternal(Out, DVR.getRawAddress(), WriterCtx, true); Out << ", "; - WriteAsOperandInternal(Out, DPV.getRawAddressExpression(), WriterCtx, true); + WriteAsOperandInternal(Out, DVR.getRawAddressExpression(), WriterCtx, true); Out << ", "; } - WriteAsOperandInternal(Out, DPV.getDebugLoc().getAsMDNode(), WriterCtx, true); + WriteAsOperandInternal(Out, DVR.getDebugLoc().getAsMDNode(), WriterCtx, true); Out << ")"; } @@ -4656,7 +4680,7 @@ void AssemblyWriter::printDbgRecordLine(const DbgRecord &DR) { Out << '\n'; } -void AssemblyWriter::printDPLabel(const DPLabel &Label) { +void AssemblyWriter::printDbgLabelRecord(const DbgLabelRecord &Label) { auto WriterCtx = getContext(); Out << "#dbg_label("; WriteAsOperandInternal(Out, Label.getRawLabel(), WriterCtx, true); @@ -4891,20 +4915,20 @@ static bool isReferencingMDNode(const Instruction &I) { return false; } -void DPMarker::print(raw_ostream &ROS, bool IsForDebug) const { +void DbgMarker::print(raw_ostream &ROS, bool IsForDebug) const { ModuleSlotTracker MST(getModuleFromDPI(this), true); print(ROS, MST, IsForDebug); } -void DPValue::print(raw_ostream &ROS, bool IsForDebug) const { +void DbgVariableRecord::print(raw_ostream &ROS, bool IsForDebug) const { ModuleSlotTracker MST(getModuleFromDPI(this), true); print(ROS, MST, IsForDebug); } -void DPMarker::print(raw_ostream &ROS, ModuleSlotTracker &MST, - bool IsForDebug) const { +void DbgMarker::print(raw_ostream &ROS, ModuleSlotTracker &MST, + bool IsForDebug) const { formatted_raw_ostream OS(ROS); SlotTracker EmptySlotTable(static_cast<const Module *>(nullptr)); SlotTracker &SlotTable = @@ -4915,17 +4939,17 @@ void DPMarker::print(raw_ostream &ROS, ModuleSlotTracker &MST, }; incorporateFunction(getParent() ? getParent()->getParent() : nullptr); AssemblyWriter W(OS, SlotTable, getModuleFromDPI(this), nullptr, IsForDebug); - W.printDPMarker(*this); + W.printDbgMarker(*this); } -void DPLabel::print(raw_ostream &ROS, bool IsForDebug) const { +void DbgLabelRecord::print(raw_ostream &ROS, bool IsForDebug) const { ModuleSlotTracker MST(getModuleFromDPI(this), true); print(ROS, MST, IsForDebug); } -void DPValue::print(raw_ostream &ROS, ModuleSlotTracker &MST, - bool IsForDebug) const { +void DbgVariableRecord::print(raw_ostream &ROS, ModuleSlotTracker &MST, + bool IsForDebug) const { formatted_raw_ostream OS(ROS); SlotTracker EmptySlotTable(static_cast<const Module *>(nullptr)); SlotTracker &SlotTable = @@ -4938,11 +4962,11 @@ void DPValue::print(raw_ostream &ROS, ModuleSlotTracker &MST, ? Marker->getParent()->getParent() : nullptr); AssemblyWriter W(OS, SlotTable, getModuleFromDPI(this), nullptr, IsForDebug); - W.printDPValue(*this); + W.printDbgVariableRecord(*this); } -void DPLabel::print(raw_ostream &ROS, ModuleSlotTracker &MST, - bool IsForDebug) const { +void DbgLabelRecord::print(raw_ostream &ROS, ModuleSlotTracker &MST, + bool IsForDebug) const { formatted_raw_ostream OS(ROS); SlotTracker EmptySlotTable(static_cast<const Module *>(nullptr)); SlotTracker &SlotTable = @@ -4954,7 +4978,7 @@ void DPLabel::print(raw_ostream &ROS, ModuleSlotTracker &MST, incorporateFunction(Marker->getParent() ? Marker->getParent()->getParent() : nullptr); AssemblyWriter W(OS, SlotTable, getModuleFromDPI(this), nullptr, IsForDebug); - W.printDPLabel(*this); + W.printDbgLabelRecord(*this); } void Value::print(raw_ostream &ROS, bool IsForDebug) const { @@ -5204,7 +5228,10 @@ void Value::dump() const { print(dbgs(), /*IsForDebug=*/true); dbgs() << '\n'; } // Value::dump - allow easy printing of Values from the debugger. LLVM_DUMP_METHOD -void DPMarker::dump() const { print(dbgs(), /*IsForDebug=*/true); dbgs() << '\n'; } +void DbgMarker::dump() const { + print(dbgs(), /*IsForDebug=*/true); + dbgs() << '\n'; +} // Value::dump - allow easy printing of Values from the debugger. LLVM_DUMP_METHOD diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp index 25992395e471b355f9e93253510c02e6da387bfe..a44f6af4162f03ffdbc52523e99d5967fe8721a1 100644 --- a/llvm/lib/IR/AutoUpgrade.cpp +++ b/llvm/lib/IR/AutoUpgrade.cpp @@ -647,11 +647,12 @@ static bool upgradeArmOrAarch64IntrinsicFunction(bool IsArm, Function *F, // v16i8 respectively. if (Name.consume_front("bfdot.")) { // (arm|aarch64).neon.bfdot.*'. - Intrinsic::ID ID = StringSwitch<Intrinsic::ID>(Name) - .Cases("v2f32.v8i8", "v4f32.v16i8", - IsArm ? Intrinsic::arm_neon_bfdot - : Intrinsic::aarch64_neon_bfdot) - .Default(Intrinsic::not_intrinsic); + Intrinsic::ID ID = + StringSwitch<Intrinsic::ID>(Name) + .Cases("v2f32.v8i8", "v4f32.v16i8", + IsArm ? (Intrinsic::ID)Intrinsic::arm_neon_bfdot + : (Intrinsic::ID)Intrinsic::aarch64_neon_bfdot) + .Default(Intrinsic::not_intrinsic); if (ID != Intrinsic::not_intrinsic) { size_t OperandWidth = F->getReturnType()->getPrimitiveSizeInBits(); assert((OperandWidth == 64 || OperandWidth == 128) && @@ -674,12 +675,15 @@ static bool upgradeArmOrAarch64IntrinsicFunction(bool IsArm, Function *F, // (arm|aarch64).neon.bfm*.v4f32.v16i8'. Intrinsic::ID ID = StringSwitch<Intrinsic::ID>(Name) - .Case("mla", IsArm ? Intrinsic::arm_neon_bfmmla - : Intrinsic::aarch64_neon_bfmmla) - .Case("lalb", IsArm ? Intrinsic::arm_neon_bfmlalb - : Intrinsic::aarch64_neon_bfmlalb) - .Case("lalt", IsArm ? Intrinsic::arm_neon_bfmlalt - : Intrinsic::aarch64_neon_bfmlalt) + .Case("mla", + IsArm ? (Intrinsic::ID)Intrinsic::arm_neon_bfmmla + : (Intrinsic::ID)Intrinsic::aarch64_neon_bfmmla) + .Case("lalb", + IsArm ? (Intrinsic::ID)Intrinsic::arm_neon_bfmlalb + : (Intrinsic::ID)Intrinsic::aarch64_neon_bfmlalb) + .Case("lalt", + IsArm ? (Intrinsic::ID)Intrinsic::arm_neon_bfmlalt + : (Intrinsic::ID)Intrinsic::aarch64_neon_bfmlalt) .Default(Intrinsic::not_intrinsic); if (ID != Intrinsic::not_intrinsic) { NewFn = Intrinsic::getDeclaration(F->getParent(), ID); @@ -1052,6 +1056,18 @@ static bool upgradeIntrinsicFunction1(Function *F, Function *&NewFn) { } case 'd': if (Name.consume_front("dbg.")) { + // Mark debug intrinsics for upgrade to new debug format. + if (F->getParent()->IsNewDbgInfoFormat) { + if (Name == "addr" || Name == "value" || Name == "assign" || + Name == "declare" || Name == "label") { + // There's no function to replace these with. + NewFn = nullptr; + // But we do want these to get upgraded. + return true; + } + } + // Update llvm.dbg.addr intrinsics even in "new debug mode"; they'll get + // converted to DbgVariableRecords later. if (Name == "addr" || (Name == "value" && F->arg_size() == 4)) { rename(F); NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::dbg_value); @@ -2328,6 +2344,59 @@ static Value *upgradeAMDGCNIntrinsicCall(StringRef Name, CallBase *CI, llvm_unreachable("Unknown function for AMDGPU intrinsic upgrade."); } +/// Helper to unwrap intrinsic call MetadataAsValue operands. +template <typename MDType> +static MDType *unwrapMAVOp(CallBase *CI, unsigned Op) { + if (MetadataAsValue *MAV = dyn_cast<MetadataAsValue>(CI->getArgOperand(Op))) + return dyn_cast<MDType>(MAV->getMetadata()); + return nullptr; +} + +/// Convert debug intrinsic calls to non-instruction debug records. +/// \p Name - Final part of the intrinsic name, e.g. 'value' in llvm.dbg.value. +/// \p CI - The debug intrinsic call. +static void upgradeDbgIntrinsicToDbgRecord(StringRef Name, CallBase *CI) { + DbgRecord *DR = nullptr; + if (Name == "label") { + DR = new DbgLabelRecord(unwrapMAVOp<DILabel>(CI, 0), CI->getDebugLoc()); + } else if (Name == "assign") { + DR = new DbgVariableRecord( + unwrapMAVOp<Metadata>(CI, 0), unwrapMAVOp<DILocalVariable>(CI, 1), + unwrapMAVOp<DIExpression>(CI, 2), unwrapMAVOp<DIAssignID>(CI, 3), + unwrapMAVOp<Metadata>(CI, 4), unwrapMAVOp<DIExpression>(CI, 5), + CI->getDebugLoc()); + } else if (Name == "declare") { + DR = new DbgVariableRecord( + unwrapMAVOp<Metadata>(CI, 0), unwrapMAVOp<DILocalVariable>(CI, 1), + unwrapMAVOp<DIExpression>(CI, 2), CI->getDebugLoc(), + DbgVariableRecord::LocationType::Declare); + } else if (Name == "addr") { + // Upgrade dbg.addr to dbg.value with DW_OP_deref. + DIExpression *Expr = unwrapMAVOp<DIExpression>(CI, 2); + Expr = DIExpression::append(Expr, dwarf::DW_OP_deref); + DR = new DbgVariableRecord(unwrapMAVOp<Metadata>(CI, 0), + unwrapMAVOp<DILocalVariable>(CI, 1), Expr, + CI->getDebugLoc()); + } else if (Name == "value") { + // An old version of dbg.value had an extra offset argument. + unsigned VarOp = 1; + unsigned ExprOp = 2; + if (CI->arg_size() == 4) { + auto *Offset = dyn_cast_or_null<Constant>(CI->getArgOperand(1)); + // Nonzero offset dbg.values get dropped without a replacement. + if (!Offset || !Offset->isZeroValue()) + return; + VarOp = 2; + ExprOp = 3; + } + DR = new DbgVariableRecord( + unwrapMAVOp<Metadata>(CI, 0), unwrapMAVOp<DILocalVariable>(CI, VarOp), + unwrapMAVOp<DIExpression>(CI, ExprOp), CI->getDebugLoc()); + } + assert(DR && "Unhandled intrinsic kind in upgrade to DbgRecord"); + CI->getParent()->insertDbgRecordBefore(DR, CI->getIterator()); +} + /// Upgrade a call to an old intrinsic. All argument and return casting must be /// provided to seamlessly integrate with existing context. void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) { @@ -2353,6 +2422,7 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) { bool IsNVVM = Name.consume_front("nvvm."); bool IsARM = Name.consume_front("arm."); bool IsAMDGCN = Name.consume_front("amdgcn."); + bool IsDbg = Name.consume_front("dbg."); if (IsX86 && Name.starts_with("sse4a.movnt.")) { SmallVector<Metadata *, 1> Elts; @@ -2457,7 +2527,7 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) { return; } - Value *Rep; + Value *Rep = nullptr; // Upgrade packed integer vector compare intrinsics to compare instructions. if (IsX86 && (Name.starts_with("sse2.pcmp") || Name.starts_with("avx2.pcmp"))) { @@ -4192,6 +4262,8 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) { Rep = upgradeARMIntrinsicCall(Name, CI, F, Builder); } else if (IsAMDGCN) { Rep = upgradeAMDGCNIntrinsicCall(Name, CI, F, Builder); + } else if (IsDbg && CI->getModule()->IsNewDbgInfoFormat) { + upgradeDbgIntrinsicToDbgRecord(Name, CI); } else { llvm_unreachable("Unknown function for CallBase upgrade."); } @@ -5178,72 +5250,6 @@ void llvm::UpgradeFunctionAttributes(Function &F) { Arg.removeAttrs(AttributeFuncs::typeIncompatible(Arg.getType())); } -// Check if the module attribute is present and not zero. -static bool isModuleAttributeSet(Module &M, const StringRef &ModAttr) { - const auto *Attr = - mdconst::extract_or_null<ConstantInt>(M.getModuleFlag(ModAttr)); - return Attr && Attr->getZExtValue(); -} - -// Copy an attribute from module to the function if exists. -// First value of the pair is used when the module attribute is not zero -// the second otherwise. -static void -CopyModuleAttributeToFunction(Function &F, StringRef FnAttrName, - StringRef ModAttrName, - std::pair<StringRef, StringRef> Values) { - if (F.hasFnAttribute(FnAttrName)) - return; - F.addFnAttr(FnAttrName, isModuleAttributeSet(*F.getParent(), ModAttrName) - ? Values.first - : Values.second); -} - -// Copy a boolean attribute from module to the function if exists. -// Module attribute treated false if zero otherwise true. -static void CopyModuleAttributeToFunction(Function &F, StringRef AttrName) { - CopyModuleAttributeToFunction( - F, AttrName, AttrName, - std::make_pair<StringRef, StringRef>("true", "false")); -} - -// Copy an attribute from module to the function if exists. -// First value of the pair is used when the module attribute is not zero -// the second otherwise. -static void -CopyModuleAttributeToFunction(Function &F, StringRef AttrName, - std::pair<StringRef, StringRef> Values) { - CopyModuleAttributeToFunction(F, AttrName, AttrName, Values); -} - -void llvm::CopyModuleAttrToFunctions(Module &M) { - Triple T(M.getTargetTriple()); - if (!T.isThumb() && !T.isARM() && !T.isAArch64()) - return; - - for (Function &F : M.getFunctionList()) { - if (F.isDeclaration()) - continue; - - if (!F.hasFnAttribute("sign-return-address")) { - StringRef SignType = "none"; - if (isModuleAttributeSet(M, "sign-return-address")) - SignType = "non-leaf"; - - if (isModuleAttributeSet(M, "sign-return-address-all")) - SignType = "all"; - - F.addFnAttr("sign-return-address", SignType); - } - CopyModuleAttributeToFunction(F, "branch-target-enforcement"); - CopyModuleAttributeToFunction(F, "branch-protection-pauth-lr"); - CopyModuleAttributeToFunction(F, "guarded-control-stack"); - CopyModuleAttributeToFunction( - F, "sign-return-address-key", - std::make_pair<StringRef, StringRef>("b_key", "a_key")); - } -} - static bool isOldLoopArgument(Metadata *MD) { auto *T = dyn_cast_or_null<MDTuple>(MD); if (!T) diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp index 7ead7ce3bf08ab28a65fa23c6f16dc4c52fab505..ae99267f5ba8796068f9b6e5d8849a74cb55fd9f 100644 --- a/llvm/lib/IR/BasicBlock.cpp +++ b/llvm/lib/IR/BasicBlock.cpp @@ -36,64 +36,71 @@ cl::opt<bool> "through iterators, eliminating intrinsics"), cl::init(true)); -DPMarker *BasicBlock::createMarker(Instruction *I) { +bool WriteNewDbgInfoFormatToBitcode /*set default value in cl::init() below*/; +cl::opt<bool, true> WriteNewDbgInfoFormatToBitcode2( + "write-experimental-debuginfo-iterators-to-bitcode", cl::Hidden, + cl::location(WriteNewDbgInfoFormatToBitcode), cl::init(true)); + +DbgMarker *BasicBlock::createMarker(Instruction *I) { assert(IsNewDbgInfoFormat && "Tried to create a marker in a non new debug-info block!"); - if (I->DbgMarker) - return I->DbgMarker; - DPMarker *Marker = new DPMarker(); + if (I->DebugMarker) + return I->DebugMarker; + DbgMarker *Marker = new DbgMarker(); Marker->MarkedInstr = I; - I->DbgMarker = Marker; + I->DebugMarker = Marker; return Marker; } -DPMarker *BasicBlock::createMarker(InstListType::iterator It) { +DbgMarker *BasicBlock::createMarker(InstListType::iterator It) { assert(IsNewDbgInfoFormat && "Tried to create a marker in a non new debug-info block!"); if (It != end()) return createMarker(&*It); - DPMarker *DPM = getTrailingDbgRecords(); - if (DPM) - return DPM; - DPM = new DPMarker(); - setTrailingDbgRecords(DPM); - return DPM; + DbgMarker *DM = getTrailingDbgRecords(); + if (DM) + return DM; + DM = new DbgMarker(); + setTrailingDbgRecords(DM); + return DM; } void BasicBlock::convertToNewDbgValues() { IsNewDbgInfoFormat = true; - // Iterate over all instructions in the instruction list, collecting dbg.value - // instructions and converting them to DPValues. Once we find a "real" - // instruction, attach all those DPValues to a DPMarker in that instruction. - SmallVector<DbgRecord *, 4> DPVals; + // Iterate over all instructions in the instruction list, collecting debug + // info intrinsics and converting them to DbgRecords. Once we find a "real" + // instruction, attach all those DbgRecords to a DbgMarker in that + // instruction. + SmallVector<DbgRecord *, 4> DbgVarRecs; for (Instruction &I : make_early_inc_range(InstList)) { - assert(!I.DbgMarker && "DbgMarker already set on old-format instrs?"); + assert(!I.DebugMarker && "DebugMarker already set on old-format instrs?"); if (DbgVariableIntrinsic *DVI = dyn_cast<DbgVariableIntrinsic>(&I)) { - // Convert this dbg.value to a DPValue. - DPValue *Value = new DPValue(DVI); - DPVals.push_back(Value); + // Convert this dbg.value to a DbgVariableRecord. + DbgVariableRecord *Value = new DbgVariableRecord(DVI); + DbgVarRecs.push_back(Value); DVI->eraseFromParent(); continue; } if (DbgLabelInst *DLI = dyn_cast<DbgLabelInst>(&I)) { - DPVals.push_back(new DPLabel(DLI->getLabel(), DLI->getDebugLoc())); + DbgVarRecs.push_back( + new DbgLabelRecord(DLI->getLabel(), DLI->getDebugLoc())); DLI->eraseFromParent(); continue; } - if (DPVals.empty()) + if (DbgVarRecs.empty()) continue; - // Create a marker to store DPValues in. + // Create a marker to store DbgRecords in. createMarker(&I); - DPMarker *Marker = I.DbgMarker; + DbgMarker *Marker = I.DebugMarker; - for (DbgRecord *DPV : DPVals) - Marker->insertDbgRecord(DPV, false); + for (DbgRecord *DVR : DbgVarRecs) + Marker->insertDbgRecord(DVR, false); - DPVals.clear(); + DbgVarRecs.clear(); } } @@ -101,14 +108,14 @@ void BasicBlock::convertFromNewDbgValues() { invalidateOrders(); IsNewDbgInfoFormat = false; - // Iterate over the block, finding instructions annotated with DPMarkers. - // Convert any attached DPValues to dbg.values and insert ahead of the + // Iterate over the block, finding instructions annotated with DbgMarkers. + // Convert any attached DbgRecords to debug intrinsics and insert ahead of the // instruction. for (auto &Inst : *this) { - if (!Inst.DbgMarker) + if (!Inst.DebugMarker) continue; - DPMarker &Marker = *Inst.DbgMarker; + DbgMarker &Marker = *Inst.DebugMarker; for (DbgRecord &DR : Marker.getDbgRecordRange()) InstList.insert(Inst.getIterator(), DR.createDebugIntrinsic(getModule(), nullptr)); @@ -116,7 +123,7 @@ void BasicBlock::convertFromNewDbgValues() { Marker.eraseFromParent(); } - // Assume no trailing DPValues: we could technically create them at the end + // Assume no trailing DbgRecords: we could technically create them at the end // of the block, after a terminator, but this would be non-cannonical and // indicates that something else is broken somewhere. assert(!getTrailingDbgRecords()); @@ -125,11 +132,11 @@ void BasicBlock::convertFromNewDbgValues() { #ifndef NDEBUG void BasicBlock::dumpDbgValues() const { for (auto &Inst : *this) { - if (!Inst.DbgMarker) + if (!Inst.DebugMarker) continue; - dbgs() << "@ " << Inst.DbgMarker << " "; - Inst.DbgMarker->dump(); + dbgs() << "@ " << Inst.DebugMarker << " "; + Inst.DebugMarker->dump(); }; } #endif @@ -212,9 +219,9 @@ BasicBlock::~BasicBlock() { assert(getParent() == nullptr && "BasicBlock still linked into the program!"); dropAllReferences(); for (auto &Inst : *this) { - if (!Inst.DbgMarker) + if (!Inst.DebugMarker) continue; - Inst.DbgMarker->eraseFromParent(); + Inst.DebugMarker->eraseFromParent(); } InstList.clear(); } @@ -691,15 +698,15 @@ void BasicBlock::renumberInstructions() { NumInstrRenumberings++; } -void BasicBlock::flushTerminatorDbgValues() { - // If we erase the terminator in a block, any DPValues will sink and "fall +void BasicBlock::flushTerminatorDbgRecords() { + // If we erase the terminator in a block, any DbgRecords will sink and "fall // off the end", existing after any terminator that gets inserted. With // dbg.value intrinsics we would just insert the terminator at end() and - // the dbg.values would come before the terminator. With DPValues, we must + // the dbg.values would come before the terminator. With DbgRecords, we must // do this manually. // To get out of this unfortunate form, whenever we insert a terminator, - // check whether there's anything trailing at the end and move those DPValues - // in front of the terminator. + // check whether there's anything trailing at the end and move those + // DbgRecords in front of the terminator. // Do nothing if we're not in new debug-info format. if (!IsNewDbgInfoFormat) @@ -710,15 +717,15 @@ void BasicBlock::flushTerminatorDbgValues() { if (!Term) return; - // Are there any dangling DPValues? - DPMarker *TrailingDPValues = getTrailingDbgRecords(); - if (!TrailingDPValues) + // Are there any dangling DbgRecords? + DbgMarker *TrailingDbgRecords = getTrailingDbgRecords(); + if (!TrailingDbgRecords) return; - // Transfer DPValues from the trailing position onto the terminator. + // Transfer DbgRecords from the trailing position onto the terminator. createMarker(Term); - Term->DbgMarker->absorbDebugValues(*TrailingDPValues, false); - TrailingDPValues->eraseFromParent(); + Term->DebugMarker->absorbDebugValues(*TrailingDbgRecords, false); + TrailingDbgRecords->eraseFromParent(); deleteTrailingDbgRecords(); } @@ -735,7 +742,7 @@ void BasicBlock::spliceDebugInfoEmptyBlock(BasicBlock::iterator Dest, // If an optimisation pass attempts to splice the contents of the block from // BB1->begin() to BB1->getTerminator(), then the dbg.value will be // transferred to the destination. - // However, in the "new" DPValue format for debug-info, that range is empty: + // However, in the "new" DbgRecord format for debug-info, that range is empty: // begin() returns an iterator to the terminator, as there will only be a // single instruction in the block. We must piece together from the bits set // in the iterators whether there was the intention to transfer any debug @@ -750,16 +757,16 @@ void BasicBlock::spliceDebugInfoEmptyBlock(BasicBlock::iterator Dest, bool ReadFromHead = First.getHeadBit(); // If the source block is completely empty, including no terminator, then - // transfer any trailing DPValues that are still hanging around. This can + // transfer any trailing DbgRecords that are still hanging around. This can // occur when a block is optimised away and the terminator has been moved // somewhere else. if (Src->empty()) { - DPMarker *SrcTrailingDPValues = Src->getTrailingDbgRecords(); - if (!SrcTrailingDPValues) + DbgMarker *SrcTrailingDbgRecords = Src->getTrailingDbgRecords(); + if (!SrcTrailingDbgRecords) return; Dest->adoptDbgRecords(Src, Src->end(), InsertAtHead); - // adoptDbgRecords should have released the trailing DPValues. + // adoptDbgRecords should have released the trailing DbgRecords. assert(!Src->getTrailingDbgRecords()); return; } @@ -774,7 +781,7 @@ void BasicBlock::spliceDebugInfoEmptyBlock(BasicBlock::iterator Dest, if (!First->hasDbgRecords()) return; - createMarker(Dest)->absorbDebugValues(*First->DbgMarker, InsertAtHead); + createMarker(Dest)->absorbDebugValues(*First->DebugMarker, InsertAtHead); return; } @@ -785,8 +792,8 @@ void BasicBlock::spliceDebugInfo(BasicBlock::iterator Dest, BasicBlock *Src, /* Do a quick normalisation before calling the real splice implementation. We might be operating on a degenerate basic block that has no instructions in it, a legitimate transient state. In that case, Dest will be end() and - any DPValues temporarily stored in the TrailingDPValues map in LLVMContext. - We might illustrate it thus: + any DbgRecords temporarily stored in the TrailingDbgRecords map in + LLVMContext. We might illustrate it thus: Dest | @@ -795,35 +802,35 @@ void BasicBlock::spliceDebugInfo(BasicBlock::iterator Dest, BasicBlock *Src, | | First Last - However: does the caller expect the "~" DPValues to end up before or after - the spliced segment? This is communciated in the "Head" bit of Dest, which - signals whether the caller called begin() or end() on this block. + However: does the caller expect the "~" DbgRecords to end up before or + after the spliced segment? This is communciated in the "Head" bit of Dest, + which signals whether the caller called begin() or end() on this block. - If the head bit is set, then all is well, we leave DPValues trailing just + If the head bit is set, then all is well, we leave DbgRecords trailing just like how dbg.value instructions would trail after instructions spliced to the beginning of this block. - If the head bit isn't set, then try to jam the "~" DPValues onto the front - of the First instruction, then splice like normal, which joins the "~" - DPValues with the "+" DPValues. However if the "+" DPValues are supposed to - be left behind in Src, then: - * detach the "+" DPValues, - * move the "~" DPValues onto First, + If the head bit isn't set, then try to jam the "~" DbgRecords onto the + front of the First instruction, then splice like normal, which joins the + "~" DbgRecords with the "+" DbgRecords. However if the "+" DbgRecords are + supposed to be left behind in Src, then: + * detach the "+" DbgRecords, + * move the "~" DbgRecords onto First, * splice like normal, - * replace the "+" DPValues onto the Last position. + * replace the "+" DbgRecords onto the Last position. Complicated, but gets the job done. */ - // If we're inserting at end(), and not in front of dangling DPValues, then - // move the DPValues onto "First". They'll then be moved naturally in the + // If we're inserting at end(), and not in front of dangling DbgRecords, then + // move the DbgRecords onto "First". They'll then be moved naturally in the // splice process. - DPMarker *MoreDanglingDPValues = nullptr; - DPMarker *OurTrailingDPValues = getTrailingDbgRecords(); - if (Dest == end() && !Dest.getHeadBit() && OurTrailingDPValues) { - // Are the "+" DPValues not supposed to move? If so, detach them + DbgMarker *MoreDanglingDbgRecords = nullptr; + DbgMarker *OurTrailingDbgRecords = getTrailingDbgRecords(); + if (Dest == end() && !Dest.getHeadBit() && OurTrailingDbgRecords) { + // Are the "+" DbgRecords not supposed to move? If so, detach them // temporarily. if (!First.getHeadBit() && First->hasDbgRecords()) { - MoreDanglingDPValues = Src->getMarker(First); - MoreDanglingDPValues->removeFromParent(); + MoreDanglingDbgRecords = Src->getMarker(First); + MoreDanglingDbgRecords->removeFromParent(); } if (First->hasDbgRecords()) { @@ -838,9 +845,9 @@ void BasicBlock::spliceDebugInfo(BasicBlock::iterator Dest, BasicBlock *Src, } else { // No current marker, create one and absorb in. (FIXME: we can avoid an // allocation in the future). - DPMarker *CurMarker = Src->createMarker(&*First); - CurMarker->absorbDebugValues(*OurTrailingDPValues, false); - OurTrailingDPValues->eraseFromParent(); + DbgMarker *CurMarker = Src->createMarker(&*First); + CurMarker->absorbDebugValues(*OurTrailingDbgRecords, false); + OurTrailingDbgRecords->eraseFromParent(); } deleteTrailingDbgRecords(); First.setHeadBit(true); @@ -849,16 +856,16 @@ void BasicBlock::spliceDebugInfo(BasicBlock::iterator Dest, BasicBlock *Src, // Call the main debug-info-splicing implementation. spliceDebugInfoImpl(Dest, Src, First, Last); - // Do we have some "+" DPValues hanging around that weren't supposed to move, - // and we detached to make things easier? - if (!MoreDanglingDPValues) + // Do we have some "+" DbgRecords hanging around that weren't supposed to + // move, and we detached to make things easier? + if (!MoreDanglingDbgRecords) return; // FIXME: we could avoid an allocation here sometimes. (adoptDbgRecords // requires an iterator). - DPMarker *LastMarker = Src->createMarker(Last); - LastMarker->absorbDebugValues(*MoreDanglingDPValues, true); - MoreDanglingDPValues->eraseFromParent(); + DbgMarker *LastMarker = Src->createMarker(Last); + LastMarker->absorbDebugValues(*MoreDanglingDbgRecords, true); + MoreDanglingDbgRecords->eraseFromParent(); } void BasicBlock::spliceDebugInfoImpl(BasicBlock::iterator Dest, BasicBlock *Src, @@ -870,15 +877,16 @@ void BasicBlock::spliceDebugInfoImpl(BasicBlock::iterator Dest, BasicBlock *Src, bool InsertAtHead = Dest.getHeadBit(); bool ReadFromHead = First.getHeadBit(); // Use this flag to signal the abnormal case, where we don't want to copy the - // DPValues ahead of the "Last" position. + // DbgRecords ahead of the "Last" position. bool ReadFromTail = !Last.getTailBit(); bool LastIsEnd = (Last == Src->end()); /* Here's an illustration of what we're about to do. We have two blocks, this and Src, and two segments of list. Each instruction is marked by a capital - while potential DPValue debug-info is marked out by "-" characters and a few - other special characters (+:=) where I want to highlight what's going on. + while potential DbgRecord debug-info is marked out by "-" characters and a + few other special characters (+:=) where I want to highlight what's going + on. Dest | @@ -889,18 +897,18 @@ void BasicBlock::spliceDebugInfoImpl(BasicBlock::iterator Dest, BasicBlock *Src, The splice method is going to take all the instructions from First up to (but not including) Last and insert them in _front_ of Dest, forming one - long list. All the DPValues attached to instructions _between_ First and + long list. All the DbgRecords attached to instructions _between_ First and Last need no maintenence. However, we have to do special things with the - DPValues marked with the +:= characters. We only have three positions: - should the "+" DPValues be transferred, and if so to where? Do we move the - ":" DPValues? Would they go in front of the "=" DPValues, or should the "=" - DPValues go before "+" DPValues? + DbgRecords marked with the +:= characters. We only have three positions: + should the "+" DbgRecords be transferred, and if so to where? Do we move the + ":" DbgRecords? Would they go in front of the "=" DbgRecords, or should the + "=" DbgRecords go before "+" DbgRecords? We're told which way it should be by the bits carried in the iterators. The "Head" bit indicates whether the specified position is supposed to be at the - front of the attached DPValues (true) or not (false). The Tail bit is true - on the other end of a range: is the range intended to include DPValues up to - the end (false) or not (true). + front of the attached DbgRecords (true) or not (false). The Tail bit is true + on the other end of a range: is the range intended to include DbgRecords up + to the end (false) or not (true). FIXME: the tail bit doesn't need to be distinct from the head bit, we could combine them. @@ -934,53 +942,54 @@ void BasicBlock::spliceDebugInfoImpl(BasicBlock::iterator Dest, BasicBlock *Src, */ - // Detach the marker at Dest -- this lets us move the "====" DPValues around. - DPMarker *DestMarker = nullptr; + // Detach the marker at Dest -- this lets us move the "====" DbgRecords + // around. + DbgMarker *DestMarker = nullptr; if (Dest != end()) { if ((DestMarker = getMarker(Dest))) DestMarker->removeFromParent(); } - // If we're moving the tail range of DPValues (":::"), absorb them into the - // front of the DPValues at Dest. + // If we're moving the tail range of DbgRecords (":::"), absorb them into the + // front of the DbgRecords at Dest. if (ReadFromTail && Src->getMarker(Last)) { - DPMarker *FromLast = Src->getMarker(Last); + DbgMarker *FromLast = Src->getMarker(Last); if (LastIsEnd) { Dest->adoptDbgRecords(Src, Last, true); // adoptDbgRecords will release any trailers. assert(!Src->getTrailingDbgRecords()); } else { // FIXME: can we use adoptDbgRecords here to reduce allocations? - DPMarker *OntoDest = createMarker(Dest); + DbgMarker *OntoDest = createMarker(Dest); OntoDest->absorbDebugValues(*FromLast, true); } } - // If we're _not_ reading from the head of First, i.e. the "++++" DPValues, + // If we're _not_ reading from the head of First, i.e. the "++++" DbgRecords, // move their markers onto Last. They remain in the Src block. No action // needed. if (!ReadFromHead && First->hasDbgRecords()) { if (Last != Src->end()) { Last->adoptDbgRecords(Src, First, true); } else { - DPMarker *OntoLast = Src->createMarker(Last); - DPMarker *FromFirst = Src->createMarker(First); + DbgMarker *OntoLast = Src->createMarker(Last); + DbgMarker *FromFirst = Src->createMarker(First); // Always insert at front of Last. OntoLast->absorbDebugValues(*FromFirst, true); } } - // Finally, do something with the "====" DPValues we detached. + // Finally, do something with the "====" DbgRecords we detached. if (DestMarker) { if (InsertAtHead) { - // Insert them at the end of the DPValues at Dest. The "::::" DPValues + // Insert them at the end of the DbgRecords at Dest. The "::::" DbgRecords // might be in front of them. - DPMarker *NewDestMarker = createMarker(Dest); + DbgMarker *NewDestMarker = createMarker(Dest); NewDestMarker->absorbDebugValues(*DestMarker, false); } else { // Insert them right at the start of the range we moved, ahead of First - // and the "++++" DPValues. - DPMarker *FirstMarker = createMarker(First); + // and the "++++" DbgRecords. + DbgMarker *FirstMarker = createMarker(First); FirstMarker->absorbDebugValues(*DestMarker, true); } DestMarker->eraseFromParent(); @@ -989,11 +998,11 @@ void BasicBlock::spliceDebugInfoImpl(BasicBlock::iterator Dest, BasicBlock *Src, // generate the iterator with begin() / getFirstInsertionPt(), it means // any trailing debug-info at the end of the block would "normally" have // been pushed in front of "First". Move it there now. - DPMarker *FirstMarker = getMarker(First); - DPMarker *TrailingDPValues = getTrailingDbgRecords(); - if (TrailingDPValues) { - FirstMarker->absorbDebugValues(*TrailingDPValues, true); - TrailingDPValues->eraseFromParent(); + DbgMarker *FirstMarker = getMarker(First); + DbgMarker *TrailingDbgRecords = getTrailingDbgRecords(); + if (TrailingDbgRecords) { + FirstMarker->absorbDebugValues(*TrailingDbgRecords, true); + TrailingDbgRecords->eraseFromParent(); deleteTrailingDbgRecords(); } } @@ -1024,88 +1033,90 @@ void BasicBlock::splice(iterator Dest, BasicBlock *Src, iterator First, // And move the instructions. getInstList().splice(Dest, Src->getInstList(), First, Last); - flushTerminatorDbgValues(); + flushTerminatorDbgRecords(); } -void BasicBlock::insertDbgRecordAfter(DbgRecord *DPV, Instruction *I) { +void BasicBlock::insertDbgRecordAfter(DbgRecord *DR, Instruction *I) { assert(IsNewDbgInfoFormat); assert(I->getParent() == this); iterator NextIt = std::next(I->getIterator()); - DPMarker *NextMarker = createMarker(NextIt); - NextMarker->insertDbgRecord(DPV, true); + DbgMarker *NextMarker = createMarker(NextIt); + NextMarker->insertDbgRecord(DR, true); } -void BasicBlock::insertDbgRecordBefore(DbgRecord *DPV, +void BasicBlock::insertDbgRecordBefore(DbgRecord *DR, InstListType::iterator Where) { assert(Where == end() || Where->getParent() == this); bool InsertAtHead = Where.getHeadBit(); - DPMarker *M = createMarker(Where); - M->insertDbgRecord(DPV, InsertAtHead); + DbgMarker *M = createMarker(Where); + M->insertDbgRecord(DR, InsertAtHead); } -DPMarker *BasicBlock::getNextMarker(Instruction *I) { +DbgMarker *BasicBlock::getNextMarker(Instruction *I) { return getMarker(std::next(I->getIterator())); } -DPMarker *BasicBlock::getMarker(InstListType::iterator It) { +DbgMarker *BasicBlock::getMarker(InstListType::iterator It) { if (It == end()) { - DPMarker *DPM = getTrailingDbgRecords(); - return DPM; + DbgMarker *DM = getTrailingDbgRecords(); + return DM; } - return It->DbgMarker; + return It->DebugMarker; } void BasicBlock::reinsertInstInDbgRecords( - Instruction *I, std::optional<DPValue::self_iterator> Pos) { + Instruction *I, std::optional<DbgRecord::self_iterator> Pos) { // "I" was originally removed from a position where it was - // immediately in front of Pos. Any DPValues on that position then "fell down" - // onto Pos. "I" has been re-inserted at the front of that wedge of DPValues, - // shuffle them around to represent the original positioning. To illustrate: + // immediately in front of Pos. Any DbgRecords on that position then "fell + // down" onto Pos. "I" has been re-inserted at the front of that wedge of + // DbgRecords, shuffle them around to represent the original positioning. To + // illustrate: // // Instructions: I1---I---I0 - // DPValues: DDD DDD + // DbgRecords: DDD DDD // // Instruction "I" removed, // // Instructions: I1------I0 - // DPValues: DDDDDD + // DbgRecords: DDDDDD // ^Pos // // Instruction "I" re-inserted (now): // // Instructions: I1---I------I0 - // DPValues: DDDDDD + // DbgRecords: DDDDDD // ^Pos // // After this method completes: // // Instructions: I1---I---I0 - // DPValues: DDD DDD + // DbgRecords: DDD DDD - // This happens if there were no DPValues on I0. Are there now DPValues there? + // This happens if there were no DbgRecords on I0. Are there now DbgRecords + // there? if (!Pos) { - DPMarker *NextMarker = getNextMarker(I); + DbgMarker *NextMarker = getNextMarker(I); if (!NextMarker) return; - if (NextMarker->StoredDPValues.empty()) + if (NextMarker->StoredDbgRecords.empty()) return; - // There are DPMarkers there now -- they fell down from "I". - DPMarker *ThisMarker = createMarker(I); + // There are DbgMarkers there now -- they fell down from "I". + DbgMarker *ThisMarker = createMarker(I); ThisMarker->absorbDebugValues(*NextMarker, false); return; } - // Is there even a range of DPValues to move? - DPMarker *DPM = (*Pos)->getMarker(); - auto Range = make_range(DPM->StoredDPValues.begin(), (*Pos)); + // Is there even a range of DbgRecords to move? + DbgMarker *DM = (*Pos)->getMarker(); + auto Range = make_range(DM->StoredDbgRecords.begin(), (*Pos)); if (Range.begin() == Range.end()) return; // Otherwise: splice. - DPMarker *ThisMarker = createMarker(I); - assert(ThisMarker->StoredDPValues.empty()); - ThisMarker->absorbDebugValues(Range, *DPM, true); + DbgMarker *ThisMarker = createMarker(I); + assert(ThisMarker->StoredDbgRecords.empty()); + ThisMarker->absorbDebugValues(Range, *DM, true); } #ifndef NDEBUG @@ -1123,11 +1134,11 @@ void BasicBlock::validateInstrOrdering() const { } #endif -void BasicBlock::setTrailingDbgRecords(DPMarker *foo) { +void BasicBlock::setTrailingDbgRecords(DbgMarker *foo) { getContext().pImpl->setTrailingDbgRecords(this, foo); } -DPMarker *BasicBlock::getTrailingDbgRecords() { +DbgMarker *BasicBlock::getTrailingDbgRecords() { return getContext().pImpl->getTrailingDbgRecords(this); } diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp index 034e397bc69fcea83a6bdbef8c183906b27bb294..a766b1fe6018233e0b058b4ea0248393a4494b17 100644 --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -1154,10 +1154,9 @@ static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2) { GV->getType()->getAddressSpace())) return ICmpInst::ICMP_UGT; } - } else { + } else if (auto *CE1 = dyn_cast<ConstantExpr>(V1)) { // Ok, the LHS is known to be a constantexpr. The RHS can be any of a // constantexpr, a global, block address, or a simple constant. - ConstantExpr *CE1 = cast<ConstantExpr>(V1); Constant *CE1Op0 = CE1->getOperand(0); switch (CE1->getOpcode()) { @@ -1469,6 +1468,10 @@ static Constant *foldGEPOfGEP(GEPOperator *GEP, Type *PointeeTy, bool InBounds, if (PointeeTy != GEP->getResultElementType()) return nullptr; + // Leave inrange handling to DL-aware constant folding. + if (GEP->getInRange()) + return nullptr; + Constant *Idx0 = cast<Constant>(Idxs[0]); if (Idx0->isNullValue()) { // Handle the simple case of a zero index. @@ -1478,7 +1481,7 @@ static Constant *foldGEPOfGEP(GEPOperator *GEP, Type *PointeeTy, bool InBounds, NewIndices.append(Idxs.begin() + 1, Idxs.end()); return ConstantExpr::getGetElementPtr( GEP->getSourceElementType(), cast<Constant>(GEP->getPointerOperand()), - NewIndices, InBounds && GEP->isInBounds(), GEP->getInRangeIndex()); + NewIndices, InBounds && GEP->isInBounds()); } gep_type_iterator LastI = gep_type_end(GEP); @@ -1527,21 +1530,14 @@ static Constant *foldGEPOfGEP(GEPOperator *GEP, Type *PointeeTy, bool InBounds, NewIndices.push_back(ConstantExpr::get(Instruction::Add, Idx0, LastIdx)); NewIndices.append(Idxs.begin() + 1, Idxs.end()); - // The combined GEP normally inherits its index inrange attribute from - // the inner GEP, but if the inner GEP's last index was adjusted by the - // outer GEP, any inbounds attribute on that index is invalidated. - std::optional<unsigned> IRIndex = GEP->getInRangeIndex(); - if (IRIndex && *IRIndex == GEP->getNumIndices() - 1) - IRIndex = std::nullopt; - return ConstantExpr::getGetElementPtr( GEP->getSourceElementType(), cast<Constant>(GEP->getPointerOperand()), - NewIndices, InBounds && GEP->isInBounds(), IRIndex); + NewIndices, InBounds && GEP->isInBounds()); } Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C, bool InBounds, - std::optional<unsigned> InRangeIndex, + std::optional<ConstantRange> InRange, ArrayRef<Value *> Idxs) { if (Idxs.empty()) return C; @@ -1557,7 +1553,7 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C, auto IsNoOp = [&]() { // Avoid losing inrange information. - if (InRangeIndex) + if (InRange) return false; return all_of(Idxs, [](Value *Idx) { @@ -1595,12 +1591,6 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C, if (!isa<ConstantInt>(Idxs[i - 1]) && !isa<ConstantDataVector>(Idxs[i - 1])) // Skip if the type of the previous index is not supported. continue; - if (InRangeIndex && i == *InRangeIndex + 1) { - // If an index is marked inrange, we cannot apply this canonicalization to - // the following index, as that will cause the inrange index to point to - // the wrong element. - continue; - } if (isa<StructType>(Ty)) { // The verify makes sure that GEPs into a struct are in range. continue; @@ -1622,16 +1612,16 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C, } } else { auto *CV = cast<ConstantDataVector>(Idxs[i]); - bool InRange = true; + bool IsInRange = true; for (unsigned I = 0, E = CV->getNumElements(); I != E; ++I) { auto *CI = cast<ConstantInt>(CV->getElementAsConstant(I)); - InRange &= isIndexInRangeOfArrayType(STy->getNumElements(), CI); + IsInRange &= isIndexInRangeOfArrayType(STy->getNumElements(), CI); if (CI->isNegative()) { Unknown = true; break; } } - if (InRange || Unknown) + if (IsInRange || Unknown) // It's in range, skip to the next index. // It's out of range and negative, don't try to factor it. continue; @@ -1721,7 +1711,7 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C, for (unsigned i = 0, e = Idxs.size(); i != e; ++i) if (!NewIdxs[i]) NewIdxs[i] = cast<Constant>(Idxs[i]); return ConstantExpr::getGetElementPtr(PointeeTy, C, NewIdxs, InBounds, - InRangeIndex); + InRange); } // If all indices are known integers and normalized, we can do a simple @@ -1731,7 +1721,7 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C, if (!GV->hasExternalWeakLinkage() && GV->getValueType() == PointeeTy && isInBoundsIndices(Idxs)) return ConstantExpr::getGetElementPtr(PointeeTy, C, Idxs, - /*InBounds=*/true, InRangeIndex); + /*InBounds=*/true, InRange); return nullptr; } diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp index 3394a1ec8dc476cdabee70fcfbbcffc3aff72fb5..59e7a9f5eb11143fdb60c9721a15dea7735ffa31 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -746,7 +746,7 @@ ConstantRange ConstantRange::castOp(Instruction::CastOps CastOp, Min = Min.zext(ResultBitWidth); Max = Max.zext(ResultBitWidth); } - return ConstantRange(std::move(Min), std::move(Max)); + return getNonEmpty(std::move(Min), std::move(Max) + 1); } case Instruction::SIToFP: { // TODO: use input range if available @@ -757,7 +757,7 @@ ConstantRange ConstantRange::castOp(Instruction::CastOps CastOp, SMin = SMin.sext(ResultBitWidth); SMax = SMax.sext(ResultBitWidth); } - return ConstantRange(std::move(SMin), std::move(SMax)); + return getNonEmpty(std::move(SMin), std::move(SMax) + 1); } case Instruction::FPTrunc: case Instruction::FPExt: diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index e6b92aad392f66d6abf0d4e59860dacc7a1ecef0..a5fb497f54ed15705e5829f72f08f81e61768f91 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -1568,7 +1568,7 @@ Constant *ConstantExpr::getWithOperands(ArrayRef<Constant *> Ops, Type *Ty, assert(SrcTy || (Ops[0]->getType() == getOperand(0)->getType())); return ConstantExpr::getGetElementPtr( SrcTy ? SrcTy : GEPO->getSourceElementType(), Ops[0], Ops.slice(1), - GEPO->isInBounds(), GEPO->getInRangeIndex(), OnlyIfReducedTy); + GEPO->isInBounds(), GEPO->getInRange(), OnlyIfReducedTy); } case Instruction::ICmp: case Instruction::FCmp: @@ -2349,17 +2349,16 @@ Constant *ConstantExpr::getCompare(unsigned short Predicate, Constant *C1, Constant *ConstantExpr::getGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> Idxs, bool InBounds, - std::optional<unsigned> InRangeIndex, + std::optional<ConstantRange> InRange, Type *OnlyIfReducedTy) { assert(Ty && "Must specify element type"); assert(isSupportedGetElementPtr(Ty) && "Element type is unsupported!"); - if (Constant *FC = - ConstantFoldGetElementPtr(Ty, C, InBounds, InRangeIndex, Idxs)) - return FC; // Fold a few common cases. + if (Constant *FC = ConstantFoldGetElementPtr(Ty, C, InBounds, InRange, Idxs)) + return FC; // Fold a few common cases. - assert(GetElementPtrInst::getIndexedType(Ty, Idxs) && - "GEP indices invalid!");; + assert(GetElementPtrInst::getIndexedType(Ty, Idxs) && "GEP indices invalid!"); + ; // Get the result type of the getelementptr! Type *ReqTy = GetElementPtrInst::getGEPReturnType(C, Idxs); @@ -2392,10 +2391,9 @@ Constant *ConstantExpr::getGetElementPtr(Type *Ty, Constant *C, } unsigned SubClassOptionalData = InBounds ? GEPOperator::IsInBounds : 0; - if (InRangeIndex && *InRangeIndex < 63) - SubClassOptionalData |= (*InRangeIndex + 1) << 1; const ConstantExprKeyType Key(Instruction::GetElementPtr, ArgVec, 0, - SubClassOptionalData, std::nullopt, Ty); + SubClassOptionalData, std::nullopt, Ty, + InRange); LLVMContextImpl *pImpl = C->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(ReqTy, Key); @@ -2522,10 +2520,10 @@ Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2, return pImpl->ExprConstants.getOrCreate(ShufTy, Key); } -Constant *ConstantExpr::getNeg(Constant *C, bool HasNUW, bool HasNSW) { +Constant *ConstantExpr::getNeg(Constant *C, bool HasNSW) { assert(C->getType()->isIntOrIntVectorTy() && "Cannot NEG a nonintegral value!"); - return getSub(ConstantInt::get(C->getType(), 0), C, HasNUW, HasNSW); + return getSub(ConstantInt::get(C->getType(), 0), C, /*HasNUW=*/false, HasNSW); } Constant *ConstantExpr::getNot(Constant *C) { @@ -2691,13 +2689,15 @@ const char *ConstantExpr::getOpcodeName() const { } GetElementPtrConstantExpr::GetElementPtrConstantExpr( - Type *SrcElementTy, Constant *C, ArrayRef<Constant *> IdxList, Type *DestTy) + Type *SrcElementTy, Constant *C, ArrayRef<Constant *> IdxList, Type *DestTy, + std::optional<ConstantRange> InRange) : ConstantExpr(DestTy, Instruction::GetElementPtr, OperandTraits<GetElementPtrConstantExpr>::op_end(this) - (IdxList.size() + 1), IdxList.size() + 1), SrcElementTy(SrcElementTy), - ResElementTy(GetElementPtrInst::getIndexedType(SrcElementTy, IdxList)) { + ResElementTy(GetElementPtrInst::getIndexedType(SrcElementTy, IdxList)), + InRange(std::move(InRange)) { Op<0>() = C; Use *OperandList = getOperandList(); for (unsigned i = 0, E = IdxList.size(); i != E; ++i) @@ -2712,6 +2712,10 @@ Type *GetElementPtrConstantExpr::getResultElementType() const { return ResElementTy; } +std::optional<ConstantRange> GetElementPtrConstantExpr::getInRange() const { + return InRange; +} + //===----------------------------------------------------------------------===// // ConstantData* implementations @@ -3303,7 +3307,7 @@ Value *ConstantExpr::handleOperandChangeImpl(Value *From, Value *ToV) { NewOps, this, From, To, NumUpdated, OperandNo); } -Instruction *ConstantExpr::getAsInstruction(Instruction *InsertBefore) const { +Instruction *ConstantExpr::getAsInstruction() const { SmallVector<Value *, 4> ValueOperands(operands()); ArrayRef<Value*> Ops(ValueOperands); @@ -3322,32 +3326,31 @@ Instruction *ConstantExpr::getAsInstruction(Instruction *InsertBefore) const { case Instruction::BitCast: case Instruction::AddrSpaceCast: return CastInst::Create((Instruction::CastOps)getOpcode(), Ops[0], - getType(), "", InsertBefore); + getType(), ""); case Instruction::InsertElement: - return InsertElementInst::Create(Ops[0], Ops[1], Ops[2], "", InsertBefore); + return InsertElementInst::Create(Ops[0], Ops[1], Ops[2], ""); case Instruction::ExtractElement: - return ExtractElementInst::Create(Ops[0], Ops[1], "", InsertBefore); + return ExtractElementInst::Create(Ops[0], Ops[1], ""); case Instruction::ShuffleVector: - return new ShuffleVectorInst(Ops[0], Ops[1], getShuffleMask(), "", - InsertBefore); + return new ShuffleVectorInst(Ops[0], Ops[1], getShuffleMask(), ""); case Instruction::GetElementPtr: { const auto *GO = cast<GEPOperator>(this); if (GO->isInBounds()) - return GetElementPtrInst::CreateInBounds( - GO->getSourceElementType(), Ops[0], Ops.slice(1), "", InsertBefore); + return GetElementPtrInst::CreateInBounds(GO->getSourceElementType(), + Ops[0], Ops.slice(1), ""); return GetElementPtrInst::Create(GO->getSourceElementType(), Ops[0], - Ops.slice(1), "", InsertBefore); + Ops.slice(1), ""); } case Instruction::ICmp: case Instruction::FCmp: return CmpInst::Create((Instruction::OtherOps)getOpcode(), (CmpInst::Predicate)getPredicate(), Ops[0], Ops[1], - "", InsertBefore); + ""); default: assert(getNumOperands() == 2 && "Must be binary operator?"); BinaryOperator *BO = BinaryOperator::Create( - (Instruction::BinaryOps)getOpcode(), Ops[0], Ops[1], "", InsertBefore); + (Instruction::BinaryOps)getOpcode(), Ops[0], Ops[1], ""); if (isa<OverflowingBinaryOperator>(BO)) { BO->setHasNoUnsignedWrap(SubclassOptionalData & OverflowingBinaryOperator::NoUnsignedWrap); diff --git a/llvm/lib/IR/ConstantsContext.h b/llvm/lib/IR/ConstantsContext.h index 44a926b5dc58e0518e6a29f6275da73d90fbda6b..7067d0d121117baab485624dab806d4e058b7fbb 100644 --- a/llvm/lib/IR/ConstantsContext.h +++ b/llvm/lib/IR/ConstantsContext.h @@ -183,25 +183,29 @@ public: /// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is /// used behind the scenes to implement getelementptr constant exprs. -class GetElementPtrConstantExpr final : public ConstantExpr { +class GetElementPtrConstantExpr : public ConstantExpr { Type *SrcElementTy; Type *ResElementTy; + std::optional<ConstantRange> InRange; GetElementPtrConstantExpr(Type *SrcElementTy, Constant *C, - ArrayRef<Constant *> IdxList, Type *DestTy); + ArrayRef<Constant *> IdxList, Type *DestTy, + std::optional<ConstantRange> InRange); public: - static GetElementPtrConstantExpr *Create(Type *SrcElementTy, Constant *C, - ArrayRef<Constant *> IdxList, - Type *DestTy, unsigned Flags) { + static GetElementPtrConstantExpr * + Create(Type *SrcElementTy, Constant *C, ArrayRef<Constant *> IdxList, + Type *DestTy, unsigned Flags, std::optional<ConstantRange> InRange) { GetElementPtrConstantExpr *Result = new (IdxList.size() + 1) - GetElementPtrConstantExpr(SrcElementTy, C, IdxList, DestTy); + GetElementPtrConstantExpr(SrcElementTy, C, IdxList, DestTy, + std::move(InRange)); Result->SubclassOptionalData = Flags; return Result; } Type *getSourceElementType() const; Type *getResultElementType() const; + std::optional<ConstantRange> getInRange() const; /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -405,6 +409,7 @@ private: ArrayRef<Constant *> Ops; ArrayRef<int> ShuffleMask; Type *ExplicitTy; + std::optional<ConstantRange> InRange; static ArrayRef<int> getShuffleMaskIfValid(const ConstantExpr *CE) { if (CE->getOpcode() == Instruction::ShuffleVector) @@ -418,22 +423,31 @@ private: return nullptr; } + static std::optional<ConstantRange> + getInRangeIfValid(const ConstantExpr *CE) { + if (auto *GEPCE = dyn_cast<GetElementPtrConstantExpr>(CE)) + return GEPCE->getInRange(); + return std::nullopt; + } + public: ConstantExprKeyType(unsigned Opcode, ArrayRef<Constant *> Ops, unsigned short SubclassData = 0, unsigned short SubclassOptionalData = 0, ArrayRef<int> ShuffleMask = std::nullopt, - Type *ExplicitTy = nullptr) + Type *ExplicitTy = nullptr, + std::optional<ConstantRange> InRange = std::nullopt) : Opcode(Opcode), SubclassOptionalData(SubclassOptionalData), SubclassData(SubclassData), Ops(Ops), ShuffleMask(ShuffleMask), - ExplicitTy(ExplicitTy) {} + ExplicitTy(ExplicitTy), InRange(std::move(InRange)) {} ConstantExprKeyType(ArrayRef<Constant *> Operands, const ConstantExpr *CE) : Opcode(CE->getOpcode()), SubclassOptionalData(CE->getRawSubclassOptionalData()), SubclassData(CE->isCompare() ? CE->getPredicate() : 0), Ops(Operands), ShuffleMask(getShuffleMaskIfValid(CE)), - ExplicitTy(getSourceElementTypeIfValid(CE)) {} + ExplicitTy(getSourceElementTypeIfValid(CE)), + InRange(getInRangeIfValid(CE)) {} ConstantExprKeyType(const ConstantExpr *CE, SmallVectorImpl<Constant *> &Storage) @@ -441,17 +455,26 @@ public: SubclassOptionalData(CE->getRawSubclassOptionalData()), SubclassData(CE->isCompare() ? CE->getPredicate() : 0), ShuffleMask(getShuffleMaskIfValid(CE)), - ExplicitTy(getSourceElementTypeIfValid(CE)) { + ExplicitTy(getSourceElementTypeIfValid(CE)), + InRange(getInRangeIfValid(CE)) { assert(Storage.empty() && "Expected empty storage"); for (unsigned I = 0, E = CE->getNumOperands(); I != E; ++I) Storage.push_back(CE->getOperand(I)); Ops = Storage; } + static bool rangesEqual(const std::optional<ConstantRange> &A, + const std::optional<ConstantRange> &B) { + if (!A.has_value() || !B.has_value()) + return A.has_value() == B.has_value(); + return A->getBitWidth() == B->getBitWidth() && A == B; + } + bool operator==(const ConstantExprKeyType &X) const { return Opcode == X.Opcode && SubclassData == X.SubclassData && SubclassOptionalData == X.SubclassOptionalData && Ops == X.Ops && - ShuffleMask == X.ShuffleMask && ExplicitTy == X.ExplicitTy; + ShuffleMask == X.ShuffleMask && ExplicitTy == X.ExplicitTy && + rangesEqual(InRange, X.InRange); } bool operator==(const ConstantExpr *CE) const { @@ -470,6 +493,8 @@ public: return false; if (ExplicitTy != getSourceElementTypeIfValid(CE)) return false; + if (!rangesEqual(InRange, getInRangeIfValid(CE))) + return false; return true; } @@ -499,8 +524,8 @@ public: case Instruction::ShuffleVector: return new ShuffleVectorConstantExpr(Ops[0], Ops[1], ShuffleMask); case Instruction::GetElementPtr: - return GetElementPtrConstantExpr::Create(ExplicitTy, Ops[0], Ops.slice(1), - Ty, SubclassOptionalData); + return GetElementPtrConstantExpr::Create( + ExplicitTy, Ops[0], Ops.slice(1), Ty, SubclassOptionalData, InRange); case Instruction::ICmp: return new CompareConstantExpr(Ty, Instruction::ICmp, SubclassData, Ops[0], Ops[1]); diff --git a/llvm/lib/IR/ConvergenceVerifier.cpp b/llvm/lib/IR/ConvergenceVerifier.cpp index e73aeaade5f71494ae24a953d98d838d6c3ba6b8..6708f85819df7f66d46cfa5f8930f4b79a359df2 100644 --- a/llvm/lib/IR/ConvergenceVerifier.cpp +++ b/llvm/lib/IR/ConvergenceVerifier.cpp @@ -75,14 +75,14 @@ GenericConvergenceVerifier<SSAContext>::findAndCheckConvergenceTokenUsed( template <> bool GenericConvergenceVerifier<SSAContext>::isInsideConvergentFunction( - const InstructionT &I) { + const Instruction &I) { auto *F = I.getFunction(); return F->isConvergent(); } template <> bool GenericConvergenceVerifier<SSAContext>::isConvergent( - const InstructionT &I) { + const Instruction &I) { if (auto *CB = dyn_cast<CallBase>(&I)) { return CB->isConvergent(); } diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp index 4b804a41a1676f7f2cc0d28f182cfe8f469b3ff8..8ce9c5ca63bede39867d1af4d587c135340afae5 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -404,6 +404,14 @@ void LLVMAddModuleFlag(LLVMModuleRef M, LLVMModuleFlagBehavior Behavior, {Key, KeyLen}, unwrap(Val)); } +LLVMBool LLVMIsNewDbgInfoFormat(LLVMModuleRef M) { + return unwrap(M)->IsNewDbgInfoFormat; +} + +void LLVMSetIsNewDbgInfoFormat(LLVMModuleRef M, LLVMBool UseNewFormat) { + unwrap(M)->setIsNewDbgInfoFormat(UseNewFormat); +} + /*--.. Printing modules ....................................................--*/ void LLVMDumpModule(LLVMModuleRef M) { @@ -982,6 +990,20 @@ char* LLVMPrintValueToString(LLVMValueRef Val) { return strdup(buf.c_str()); } +char *LLVMPrintDbgRecordToString(LLVMDbgRecordRef Record) { + std::string buf; + raw_string_ostream os(buf); + + if (unwrap(Record)) + unwrap(Record)->print(os); + else + os << "Printing <null> DbgRecord"; + + os.flush(); + + return strdup(buf.c_str()); +} + void LLVMReplaceAllUsesWith(LLVMValueRef OldVal, LLVMValueRef NewVal) { unwrap(OldVal)->replaceAllUsesWith(unwrap(NewVal)); } @@ -1640,7 +1662,7 @@ LLVMValueRef LLVMConstNSWNeg(LLVMValueRef ConstantVal) { } LLVMValueRef LLVMConstNUWNeg(LLVMValueRef ConstantVal) { - return wrap(ConstantExpr::getNUWNeg(unwrap<Constant>(ConstantVal))); + return wrap(ConstantExpr::getNeg(unwrap<Constant>(ConstantVal))); } @@ -2414,6 +2436,38 @@ void LLVMSetGC(LLVMValueRef Fn, const char *GC) { F->clearGC(); } +LLVMValueRef LLVMGetPrefixData(LLVMValueRef Fn) { + Function *F = unwrap<Function>(Fn); + return wrap(F->getPrefixData()); +} + +LLVMBool LLVMHasPrefixData(LLVMValueRef Fn) { + Function *F = unwrap<Function>(Fn); + return F->hasPrefixData(); +} + +void LLVMSetPrefixData(LLVMValueRef Fn, LLVMValueRef prefixData) { + Function *F = unwrap<Function>(Fn); + Constant *prefix = unwrap<Constant>(prefixData); + F->setPrefixData(prefix); +} + +LLVMValueRef LLVMGetPrologueData(LLVMValueRef Fn) { + Function *F = unwrap<Function>(Fn); + return wrap(F->getPrologueData()); +} + +LLVMBool LLVMHasPrologueData(LLVMValueRef Fn) { + Function *F = unwrap<Function>(Fn); + return F->hasPrologueData(); +} + +void LLVMSetPrologueData(LLVMValueRef Fn, LLVMValueRef prologueData) { + Function *F = unwrap<Function>(Fn); + Constant *prologue = unwrap<Constant>(prologueData); + F->setPrologueData(prologue); +} + void LLVMAddAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, LLVMAttributeRef A) { unwrap<Function>(F)->addAttributeAtIndex(Idx, unwrap(A)); @@ -3517,7 +3571,10 @@ LLVMValueRef LLVMBuildNSWNeg(LLVMBuilderRef B, LLVMValueRef V, LLVMValueRef LLVMBuildNUWNeg(LLVMBuilderRef B, LLVMValueRef V, const char *Name) { - return wrap(unwrap(B)->CreateNUWNeg(unwrap(V), Name)); + Value *Neg = unwrap(B)->CreateNeg(unwrap(V), Name); + if (auto *I = dyn_cast<BinaryOperator>(Neg)) + I->setHasNoUnsignedWrap(); + return wrap(Neg); } LLVMValueRef LLVMBuildFNeg(LLVMBuilderRef B, LLVMValueRef V, const char *Name) { diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index c673abd8bc30d06b2f2132f414ad79f40baa2f80..f86e557b8def219700774f4b563b7b666baf73a4 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -296,7 +296,20 @@ DIStringType *DIBuilder::createStringType(StringRef Name, DIDerivedType *DIBuilder::createQualifiedType(unsigned Tag, DIType *FromTy) { return DIDerivedType::get(VMContext, Tag, "", nullptr, 0, nullptr, FromTy, 0, - 0, 0, std::nullopt, DINode::FlagZero); + 0, 0, std::nullopt, std::nullopt, DINode::FlagZero); +} + +DIDerivedType *DIBuilder::createPtrAuthQualifiedType( + DIType *FromTy, unsigned Key, bool IsAddressDiscriminated, + unsigned ExtraDiscriminator, bool IsaPointer, + bool AuthenticatesNullValues) { + return DIDerivedType::get(VMContext, dwarf::DW_TAG_LLVM_ptrauth_type, "", + nullptr, 0, nullptr, FromTy, 0, 0, 0, std::nullopt, + std::optional<DIDerivedType::PtrAuthData>( + std::in_place, Key, IsAddressDiscriminated, + ExtraDiscriminator, IsaPointer, + AuthenticatesNullValues), + DINode::FlagZero); } DIDerivedType * @@ -307,8 +320,8 @@ DIBuilder::createPointerType(DIType *PointeeTy, uint64_t SizeInBits, // FIXME: Why is there a name here? return DIDerivedType::get(VMContext, dwarf::DW_TAG_pointer_type, Name, nullptr, 0, nullptr, PointeeTy, SizeInBits, - AlignInBits, 0, DWARFAddressSpace, DINode::FlagZero, - nullptr, Annotations); + AlignInBits, 0, DWARFAddressSpace, std::nullopt, + DINode::FlagZero, nullptr, Annotations); } DIDerivedType *DIBuilder::createMemberPointerType(DIType *PointeeTy, @@ -318,7 +331,8 @@ DIDerivedType *DIBuilder::createMemberPointerType(DIType *PointeeTy, DINode::DIFlags Flags) { return DIDerivedType::get(VMContext, dwarf::DW_TAG_ptr_to_member_type, "", nullptr, 0, nullptr, PointeeTy, SizeInBits, - AlignInBits, 0, std::nullopt, Flags, Base); + AlignInBits, 0, std::nullopt, std::nullopt, Flags, + Base); } DIDerivedType * @@ -327,7 +341,7 @@ DIBuilder::createReferenceType(unsigned Tag, DIType *RTy, uint64_t SizeInBits, std::optional<unsigned> DWARFAddressSpace) { assert(RTy && "Unable to create reference type"); return DIDerivedType::get(VMContext, Tag, "", nullptr, 0, nullptr, RTy, - SizeInBits, AlignInBits, 0, DWARFAddressSpace, + SizeInBits, AlignInBits, 0, DWARFAddressSpace, {}, DINode::FlagZero); } @@ -338,15 +352,16 @@ DIDerivedType *DIBuilder::createTypedef(DIType *Ty, StringRef Name, DINodeArray Annotations) { return DIDerivedType::get(VMContext, dwarf::DW_TAG_typedef, Name, File, LineNo, getNonCompileUnitScope(Context), Ty, 0, - AlignInBits, 0, std::nullopt, Flags, nullptr, - Annotations); + AlignInBits, 0, std::nullopt, std::nullopt, Flags, + nullptr, Annotations); } DIDerivedType *DIBuilder::createFriend(DIType *Ty, DIType *FriendTy) { assert(Ty && "Invalid type!"); assert(FriendTy && "Invalid friend type!"); return DIDerivedType::get(VMContext, dwarf::DW_TAG_friend, "", nullptr, 0, Ty, - FriendTy, 0, 0, 0, std::nullopt, DINode::FlagZero); + FriendTy, 0, 0, 0, std::nullopt, std::nullopt, + DINode::FlagZero); } DIDerivedType *DIBuilder::createInheritance(DIType *Ty, DIType *BaseTy, @@ -358,7 +373,7 @@ DIDerivedType *DIBuilder::createInheritance(DIType *Ty, DIType *BaseTy, ConstantInt::get(IntegerType::get(VMContext, 32), VBPtrOffset)); return DIDerivedType::get(VMContext, dwarf::DW_TAG_inheritance, "", nullptr, 0, Ty, BaseTy, 0, 0, BaseOffset, std::nullopt, - Flags, ExtraData); + std::nullopt, Flags, ExtraData); } DIDerivedType *DIBuilder::createMemberType( @@ -368,7 +383,7 @@ DIDerivedType *DIBuilder::createMemberType( return DIDerivedType::get(VMContext, dwarf::DW_TAG_member, Name, File, LineNumber, getNonCompileUnitScope(Scope), Ty, SizeInBits, AlignInBits, OffsetInBits, std::nullopt, - Flags, nullptr, Annotations); + std::nullopt, Flags, nullptr, Annotations); } static ConstantAsMetadata *getConstantOrNull(Constant *C) { @@ -381,10 +396,10 @@ DIDerivedType *DIBuilder::createVariantMemberType( DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, Constant *Discriminant, DINode::DIFlags Flags, DIType *Ty) { - return DIDerivedType::get(VMContext, dwarf::DW_TAG_member, Name, File, - LineNumber, getNonCompileUnitScope(Scope), Ty, - SizeInBits, AlignInBits, OffsetInBits, std::nullopt, - Flags, getConstantOrNull(Discriminant)); + return DIDerivedType::get( + VMContext, dwarf::DW_TAG_member, Name, File, LineNumber, + getNonCompileUnitScope(Scope), Ty, SizeInBits, AlignInBits, OffsetInBits, + std::nullopt, std::nullopt, Flags, getConstantOrNull(Discriminant)); } DIDerivedType *DIBuilder::createBitFieldMemberType( @@ -395,7 +410,7 @@ DIDerivedType *DIBuilder::createBitFieldMemberType( return DIDerivedType::get( VMContext, dwarf::DW_TAG_member, Name, File, LineNumber, getNonCompileUnitScope(Scope), Ty, SizeInBits, /*AlignInBits=*/0, - OffsetInBits, std::nullopt, Flags, + OffsetInBits, std::nullopt, std::nullopt, Flags, ConstantAsMetadata::get(ConstantInt::get(IntegerType::get(VMContext, 64), StorageOffsetInBits)), Annotations); @@ -409,7 +424,8 @@ DIBuilder::createStaticMemberType(DIScope *Scope, StringRef Name, DIFile *File, Flags |= DINode::FlagStaticMember; return DIDerivedType::get(VMContext, Tag, Name, File, LineNumber, getNonCompileUnitScope(Scope), Ty, 0, AlignInBits, - 0, std::nullopt, Flags, getConstantOrNull(Val)); + 0, std::nullopt, std::nullopt, Flags, + getConstantOrNull(Val)); } DIDerivedType * @@ -420,7 +436,7 @@ DIBuilder::createObjCIVar(StringRef Name, DIFile *File, unsigned LineNumber, return DIDerivedType::get(VMContext, dwarf::DW_TAG_member, Name, File, LineNumber, getNonCompileUnitScope(File), Ty, SizeInBits, AlignInBits, OffsetInBits, std::nullopt, - Flags, PropertyNode); + std::nullopt, Flags, PropertyNode); } DIObjCProperty * @@ -555,10 +571,10 @@ DIDerivedType *DIBuilder::createSetType(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo, uint64_t SizeInBits, uint32_t AlignInBits, DIType *Ty) { - auto *R = - DIDerivedType::get(VMContext, dwarf::DW_TAG_set_type, Name, File, LineNo, - getNonCompileUnitScope(Scope), Ty, SizeInBits, - AlignInBits, 0, std::nullopt, DINode::FlagZero); + auto *R = DIDerivedType::get(VMContext, dwarf::DW_TAG_set_type, Name, File, + LineNo, getNonCompileUnitScope(Scope), Ty, + SizeInBits, AlignInBits, 0, std::nullopt, + std::nullopt, DINode::FlagZero); trackIfUnresolved(R); return R; } @@ -951,14 +967,14 @@ DbgInstPtr DIBuilder::insertDbgAssign(Instruction *LinkedInstr, Value *Val, assert(Link && "Linked instruction must have DIAssign metadata attached"); if (M.IsNewDbgInfoFormat) { - DPValue *DPV = DPValue::createDPVAssign(Val, SrcVar, ValExpr, Link, Addr, - AddrExpr, DL); + DbgVariableRecord *DVR = DbgVariableRecord::createDVRAssign( + Val, SrcVar, ValExpr, Link, Addr, AddrExpr, DL); BasicBlock *InsertBB = LinkedInstr->getParent(); // Insert after LinkedInstr. BasicBlock::iterator NextIt = std::next(LinkedInstr->getIterator()); Instruction *InsertBefore = NextIt == InsertBB->end() ? nullptr : &*NextIt; - insertDPValue(DPV, InsertBB, InsertBefore, true); - return DPV; + insertDbgVariableRecord(DVR, InsertBB, InsertBefore, true); + return DVR; } LLVMContext &Ctx = LinkedInstr->getContext(); @@ -1040,9 +1056,10 @@ DbgInstPtr DIBuilder::insertDbgValueIntrinsic( llvm::Value *Val, DILocalVariable *VarInfo, DIExpression *Expr, const DILocation *DL, BasicBlock *InsertBB, Instruction *InsertBefore) { if (M.IsNewDbgInfoFormat) { - DPValue *DPV = DPValue::createDPValue(Val, VarInfo, Expr, DL); - insertDPValue(DPV, InsertBB, InsertBefore); - return DPV; + DbgVariableRecord *DVR = + DbgVariableRecord::createDbgVariableRecord(Val, VarInfo, Expr, DL); + insertDbgVariableRecord(DVR, InsertBB, InsertBefore); + return DVR; } if (!ValueFn) @@ -1062,9 +1079,10 @@ DbgInstPtr DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, "Expected matching subprograms"); if (M.IsNewDbgInfoFormat) { - DPValue *DPV = DPValue::createDPVDeclare(Storage, VarInfo, Expr, DL); - insertDPValue(DPV, InsertBB, InsertBefore); - return DPV; + DbgVariableRecord *DVR = + DbgVariableRecord::createDVRDeclare(Storage, VarInfo, Expr, DL); + insertDbgVariableRecord(DVR, InsertBB, InsertBefore); + return DVR; } if (!DeclareFn) @@ -1081,13 +1099,15 @@ DbgInstPtr DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, return B.CreateCall(DeclareFn, Args); } -void DIBuilder::insertDPValue(DPValue *DPV, BasicBlock *InsertBB, - Instruction *InsertBefore, bool InsertAtHead) { +void DIBuilder::insertDbgVariableRecord(DbgVariableRecord *DVR, + BasicBlock *InsertBB, + Instruction *InsertBefore, + bool InsertAtHead) { assert(InsertBefore || InsertBB); - trackIfUnresolved(DPV->getVariable()); - trackIfUnresolved(DPV->getExpression()); - if (DPV->isDbgAssign()) - trackIfUnresolved(DPV->getAddressExpression()); + trackIfUnresolved(DVR->getVariable()); + trackIfUnresolved(DVR->getExpression()); + if (DVR->isDbgAssign()) + trackIfUnresolved(DVR->getAddressExpression()); BasicBlock::iterator InsertPt; if (InsertBB && InsertBefore) @@ -1095,7 +1115,7 @@ void DIBuilder::insertDPValue(DPValue *DPV, BasicBlock *InsertBB, else if (InsertBB) InsertPt = InsertBB->end(); InsertPt.setHeadBit(InsertAtHead); - InsertBB->insertDbgRecordBefore(DPV, InsertPt); + InsertBB->insertDbgRecordBefore(DVR, InsertPt); } Instruction *DIBuilder::insertDbgIntrinsic(llvm::Function *IntrinsicFn, @@ -1135,12 +1155,12 @@ DbgInstPtr DIBuilder::insertLabel(DILabel *LabelInfo, const DILocation *DL, trackIfUnresolved(LabelInfo); if (M.IsNewDbgInfoFormat) { - DPLabel *DPL = new DPLabel(LabelInfo, DL); + DbgLabelRecord *DLR = new DbgLabelRecord(LabelInfo, DL); if (InsertBB && InsertBefore) - InsertBB->insertDbgRecordBefore(DPL, InsertBefore->getIterator()); + InsertBB->insertDbgRecordBefore(DLR, InsertBefore->getIterator()); else if (InsertBB) - InsertBB->insertDbgRecordBefore(DPL, InsertBB->end()); - return DPL; + InsertBB->insertDbgRecordBefore(DLR, InsertBB->end()); + return DLR; } if (!LabelFn) diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index e63b1e67dad7c21a66b9becc673ca4a9708aa0a7..4206162d1768234f9a047957f06e255f28af15a9 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -63,7 +63,7 @@ TinyPtrVector<DbgDeclareInst *> llvm::findDbgDeclares(Value *V) { return Declares; } -TinyPtrVector<DPValue *> llvm::findDPVDeclares(Value *V) { +TinyPtrVector<DbgVariableRecord *> llvm::findDVRDeclares(Value *V) { // This function is hot. Check whether the value has any metadata to avoid a // DenseMap lookup. if (!V->isUsedByMetadata()) @@ -72,18 +72,19 @@ TinyPtrVector<DPValue *> llvm::findDPVDeclares(Value *V) { if (!L) return {}; - TinyPtrVector<DPValue *> Declares; - for (DPValue *DPV : L->getAllDPValueUsers()) - if (DPV->getType() == DPValue::LocationType::Declare) - Declares.push_back(DPV); + TinyPtrVector<DbgVariableRecord *> Declares; + for (DbgVariableRecord *DVR : L->getAllDbgVariableRecordUsers()) + if (DVR->getType() == DbgVariableRecord::LocationType::Declare) + Declares.push_back(DVR); return Declares; } -template <typename IntrinsicT, - DPValue::LocationType Type = DPValue::LocationType::Any> -static void findDbgIntrinsics(SmallVectorImpl<IntrinsicT *> &Result, Value *V, - SmallVectorImpl<DPValue *> *DPValues) { +template <typename IntrinsicT, DbgVariableRecord::LocationType Type = + DbgVariableRecord::LocationType::Any> +static void +findDbgIntrinsics(SmallVectorImpl<IntrinsicT *> &Result, Value *V, + SmallVectorImpl<DbgVariableRecord *> *DbgVariableRecords) { // This function is hot. Check whether the value has any metadata to avoid a // DenseMap lookup. if (!V->isUsedByMetadata()) @@ -96,25 +97,27 @@ static void findDbgIntrinsics(SmallVectorImpl<IntrinsicT *> &Result, Value *V, // V will also appear twice in a dbg.assign if its used in the both the value // and address components. SmallPtrSet<IntrinsicT *, 4> EncounteredIntrinsics; - SmallPtrSet<DPValue *, 4> EncounteredDPValues; + SmallPtrSet<DbgVariableRecord *, 4> EncounteredDbgVariableRecords; /// Append IntrinsicT users of MetadataAsValue(MD). - auto AppendUsers = [&Ctx, &EncounteredIntrinsics, &EncounteredDPValues, - &Result, DPValues](Metadata *MD) { + auto AppendUsers = [&Ctx, &EncounteredIntrinsics, + &EncounteredDbgVariableRecords, &Result, + DbgVariableRecords](Metadata *MD) { if (auto *MDV = MetadataAsValue::getIfExists(Ctx, MD)) { for (User *U : MDV->users()) if (IntrinsicT *DVI = dyn_cast<IntrinsicT>(U)) if (EncounteredIntrinsics.insert(DVI).second) Result.push_back(DVI); } - if (!DPValues) + if (!DbgVariableRecords) return; - // Get DPValues that use this as a single value. + // Get DbgVariableRecords that use this as a single value. if (LocalAsMetadata *L = dyn_cast<LocalAsMetadata>(MD)) { - for (DPValue *DPV : L->getAllDPValueUsers()) { - if (Type == DPValue::LocationType::Any || DPV->getType() == Type) - if (EncounteredDPValues.insert(DPV).second) - DPValues->push_back(DPV); + for (DbgVariableRecord *DVR : L->getAllDbgVariableRecordUsers()) { + if (Type == DbgVariableRecord::LocationType::Any || + DVR->getType() == Type) + if (EncounteredDbgVariableRecords.insert(DVR).second) + DbgVariableRecords->push_back(DVR); } } }; @@ -123,27 +126,30 @@ static void findDbgIntrinsics(SmallVectorImpl<IntrinsicT *> &Result, Value *V, AppendUsers(L); for (Metadata *AL : L->getAllArgListUsers()) { AppendUsers(AL); - if (!DPValues) + if (!DbgVariableRecords) continue; DIArgList *DI = cast<DIArgList>(AL); - for (DPValue *DPV : DI->getAllDPValueUsers()) - if (Type == DPValue::LocationType::Any || DPV->getType() == Type) - if (EncounteredDPValues.insert(DPV).second) - DPValues->push_back(DPV); + for (DbgVariableRecord *DVR : DI->getAllDbgVariableRecordUsers()) + if (Type == DbgVariableRecord::LocationType::Any || + DVR->getType() == Type) + if (EncounteredDbgVariableRecords.insert(DVR).second) + DbgVariableRecords->push_back(DVR); } } } -void llvm::findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues, - Value *V, SmallVectorImpl<DPValue *> *DPValues) { - findDbgIntrinsics<DbgValueInst, DPValue::LocationType::Value>(DbgValues, V, - DPValues); +void llvm::findDbgValues( + SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V, + SmallVectorImpl<DbgVariableRecord *> *DbgVariableRecords) { + findDbgIntrinsics<DbgValueInst, DbgVariableRecord::LocationType::Value>( + DbgValues, V, DbgVariableRecords); } -void llvm::findDbgUsers(SmallVectorImpl<DbgVariableIntrinsic *> &DbgUsers, - Value *V, SmallVectorImpl<DPValue *> *DPValues) { - findDbgIntrinsics<DbgVariableIntrinsic, DPValue::LocationType::Any>( - DbgUsers, V, DPValues); +void llvm::findDbgUsers( + SmallVectorImpl<DbgVariableIntrinsic *> &DbgUsers, Value *V, + SmallVectorImpl<DbgVariableRecord *> *DbgVariableRecords) { + findDbgIntrinsics<DbgVariableIntrinsic, DbgVariableRecord::LocationType::Any>( + DbgUsers, V, DbgVariableRecords); } DISubprogram *llvm::getDISubprogram(const MDNode *Scope) { @@ -164,16 +170,16 @@ DebugLoc llvm::getDebugValueLoc(DbgVariableIntrinsic *DII) { return DILocation::get(DII->getContext(), 0, 0, Scope, InlinedAt); } -DebugLoc llvm::getDebugValueLoc(DPValue *DPV) { +DebugLoc llvm::getDebugValueLoc(DbgVariableRecord *DVR) { // Original dbg.declare must have a location. - const DebugLoc &DeclareLoc = DPV->getDebugLoc(); + const DebugLoc &DeclareLoc = DVR->getDebugLoc(); MDNode *Scope = DeclareLoc.getScope(); DILocation *InlinedAt = DeclareLoc.getInlinedAt(); // Because no machine insts can come from debug intrinsics, only the scope // and inlinedAt is significant. Zero line numbers are used in case this // DebugLoc leaks into any adjacent instructions. Produce an unknown location // with the correct scope / inlinedAt fields. - return DILocation::get(DPV->getContext(), 0, 0, Scope, InlinedAt); + return DILocation::get(DVR->getContext(), 0, 0, Scope, InlinedAt); } //===----------------------------------------------------------------------===// @@ -253,8 +259,8 @@ void DebugInfoFinder::processLocation(const Module &M, const DILocation *Loc) { } void DebugInfoFinder::processDbgRecord(const Module &M, const DbgRecord &DR) { - if (const DPValue *DPV = dyn_cast<const DPValue>(&DR)) - processVariable(M, DPV->getVariable()); + if (const DbgVariableRecord *DVR = dyn_cast<const DbgVariableRecord>(&DR)) + processVariable(M, DVR->getVariable()); processLocation(M, DR.getDebugLoc().get()); } @@ -895,7 +901,7 @@ bool llvm::stripNonLineTableDebugInfo(Module &M) { if (I.hasMetadataOtherThanDebugLoc()) I.setMetadata("heapallocsite", nullptr); - // Strip any DPValues attached. + // Strip any DbgRecords attached. I.dropDbgRecords(); } } @@ -1336,9 +1342,9 @@ LLVMMetadataRef LLVMDIBuilderCreatePointerType( LLVMDIBuilderRef Builder, LLVMMetadataRef PointeeTy, uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace, const char *Name, size_t NameLen) { - return wrap(unwrap(Builder)->createPointerType(unwrapDI<DIType>(PointeeTy), - SizeInBits, AlignInBits, - AddressSpace, {Name, NameLen})); + return wrap(unwrap(Builder)->createPointerType( + unwrapDI<DIType>(PointeeTy), SizeInBits, AlignInBits, AddressSpace, + {Name, NameLen})); } LLVMMetadataRef LLVMDIBuilderCreateStructType( @@ -1659,52 +1665,157 @@ LLVMMetadataRef LLVMDIBuilderCreateTempGlobalVariableFwdDecl( unwrapDI<MDNode>(Decl), nullptr, AlignInBits)); } -LLVMValueRef +LLVMDbgRecordRef LLVMDIBuilderInsertDeclareBefore(LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMValueRef Instr) { + return LLVMDIBuilderInsertDeclareRecordBefore(Builder, Storage, VarInfo, Expr, + DL, Instr); +} +LLVMValueRef LLVMDIBuilderInsertDeclareIntrinsicBefore( + LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMValueRef Instr) { DbgInstPtr DbgInst = unwrap(Builder)->insertDeclare( unwrap(Storage), unwrap<DILocalVariable>(VarInfo), unwrap<DIExpression>(Expr), unwrap<DILocation>(DL), unwrap<Instruction>(Instr)); + // This assert will fail if the module is in the new debug info format. + // This function should only be called if the module is in the old + // debug info format. + // See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes, + // LLVMIsNewDbgInfoFormat, and LLVMSetIsNewDbgInfoFormat for more info. assert(isa<Instruction *>(DbgInst) && - "Inserted a DbgRecord into function using old debug info mode"); + "Function unexpectedly in new debug info format"); return wrap(cast<Instruction *>(DbgInst)); } +LLVMDbgRecordRef LLVMDIBuilderInsertDeclareRecordBefore( + LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMValueRef Instr) { + DbgInstPtr DbgInst = unwrap(Builder)->insertDeclare( + unwrap(Storage), unwrap<DILocalVariable>(VarInfo), + unwrap<DIExpression>(Expr), unwrap<DILocation>(DL), + unwrap<Instruction>(Instr)); + // This assert will fail if the module is in the old debug info format. + // This function should only be called if the module is in the new + // debug info format. + // See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes, + // LLVMIsNewDbgInfoFormat, and LLVMSetIsNewDbgInfoFormat for more info. + assert(isa<DbgRecord *>(DbgInst) && + "Function unexpectedly in old debug info format"); + return wrap(cast<DbgRecord *>(DbgInst)); +} -LLVMValueRef +LLVMDbgRecordRef LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMBasicBlockRef Block) { + return LLVMDIBuilderInsertDeclareRecordAtEnd(Builder, Storage, VarInfo, Expr, + DL, Block); +} +LLVMValueRef LLVMDIBuilderInsertDeclareIntrinsicAtEnd( + LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMBasicBlockRef Block) { DbgInstPtr DbgInst = unwrap(Builder)->insertDeclare( unwrap(Storage), unwrap<DILocalVariable>(VarInfo), unwrap<DIExpression>(Expr), unwrap<DILocation>(DL), unwrap(Block)); + // This assert will fail if the module is in the new debug info format. + // This function should only be called if the module is in the old + // debug info format. + // See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes, + // LLVMIsNewDbgInfoFormat, and LLVMSetIsNewDbgInfoFormat for more info. assert(isa<Instruction *>(DbgInst) && - "Inserted a DbgRecord into function using old debug info mode"); + "Function unexpectedly in new debug info format"); return wrap(cast<Instruction *>(DbgInst)); } +LLVMDbgRecordRef LLVMDIBuilderInsertDeclareRecordAtEnd( + LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMBasicBlockRef Block) { + DbgInstPtr DbgInst = unwrap(Builder)->insertDeclare( + unwrap(Storage), unwrap<DILocalVariable>(VarInfo), + unwrap<DIExpression>(Expr), unwrap<DILocation>(DL), unwrap(Block)); + // This assert will fail if the module is in the old debug info format. + // This function should only be called if the module is in the new + // debug info format. + // See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes, + // LLVMIsNewDbgInfoFormat, and LLVMSetIsNewDbgInfoFormat for more info. + assert(isa<DbgRecord *>(DbgInst) && + "Function unexpectedly in old debug info format"); + return wrap(cast<DbgRecord *>(DbgInst)); +} -LLVMValueRef LLVMDIBuilderInsertDbgValueBefore( +LLVMDbgRecordRef LLVMDIBuilderInsertDbgValueBefore( + LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr) { + return LLVMDIBuilderInsertDbgValueRecordBefore(Builder, Val, VarInfo, Expr, + DebugLoc, Instr); +} +LLVMValueRef LLVMDIBuilderInsertDbgValueIntrinsicBefore( LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr) { DbgInstPtr DbgInst = unwrap(Builder)->insertDbgValueIntrinsic( unwrap(Val), unwrap<DILocalVariable>(VarInfo), unwrap<DIExpression>(Expr), unwrap<DILocation>(DebugLoc), unwrap<Instruction>(Instr)); + // This assert will fail if the module is in the new debug info format. + // This function should only be called if the module is in the old + // debug info format. + // See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes, + // LLVMIsNewDbgInfoFormat, and LLVMSetIsNewDbgInfoFormat for more info. assert(isa<Instruction *>(DbgInst) && - "Inserted a DbgRecord into function using old debug info mode"); + "Function unexpectedly in new debug info format"); return wrap(cast<Instruction *>(DbgInst)); } +LLVMDbgRecordRef LLVMDIBuilderInsertDbgValueRecordBefore( + LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr) { + DbgInstPtr DbgInst = unwrap(Builder)->insertDbgValueIntrinsic( + unwrap(Val), unwrap<DILocalVariable>(VarInfo), unwrap<DIExpression>(Expr), + unwrap<DILocation>(DebugLoc), unwrap<Instruction>(Instr)); + // This assert will fail if the module is in the old debug info format. + // This function should only be called if the module is in the new + // debug info format. + // See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes, + // LLVMIsNewDbgInfoFormat, and LLVMSetIsNewDbgInfoFormat for more info. + assert(isa<DbgRecord *>(DbgInst) && + "Function unexpectedly in old debug info format"); + return wrap(cast<DbgRecord *>(DbgInst)); +} -LLVMValueRef LLVMDIBuilderInsertDbgValueAtEnd( +LLVMDbgRecordRef LLVMDIBuilderInsertDbgValueAtEnd( + LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block) { + return LLVMDIBuilderInsertDbgValueRecordAtEnd(Builder, Val, VarInfo, Expr, + DebugLoc, Block); +} +LLVMValueRef LLVMDIBuilderInsertDbgValueIntrinsicAtEnd( LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block) { DbgInstPtr DbgInst = unwrap(Builder)->insertDbgValueIntrinsic( unwrap(Val), unwrap<DILocalVariable>(VarInfo), unwrap<DIExpression>(Expr), unwrap<DILocation>(DebugLoc), unwrap(Block)); + // This assert will fail if the module is in the new debug info format. + // This function should only be called if the module is in the old + // debug info format. + // See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes, + // LLVMIsNewDbgInfoFormat, and LLVMSetIsNewDbgInfoFormat for more info. assert(isa<Instruction *>(DbgInst) && - "Inserted a DbgRecord into function using old debug info mode"); + "Function unexpectedly in new debug info format"); return wrap(cast<Instruction *>(DbgInst)); } +LLVMDbgRecordRef LLVMDIBuilderInsertDbgValueRecordAtEnd( + LLVMDIBuilderRef Builder, LLVMValueRef Val, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block) { + DbgInstPtr DbgInst = unwrap(Builder)->insertDbgValueIntrinsic( + unwrap(Val), unwrap<DILocalVariable>(VarInfo), unwrap<DIExpression>(Expr), + unwrap<DILocation>(DebugLoc), unwrap(Block)); + // This assert will fail if the module is in the old debug info format. + // This function should only be called if the module is in the new + // debug info format. + // See https://llvm.org/docs/RemoveDIsDebugInfo.html#c-api-changes, + // LLVMIsNewDbgInfoFormat, and LLVMSetIsNewDbgInfoFormat for more info. + assert(isa<DbgRecord *>(DbgInst) && + "Function unexpectedly in old debug info format"); + return wrap(cast<DbgRecord *>(DbgInst)); +} LLVMMetadataRef LLVMDIBuilderCreateAutoVariable( LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, @@ -1800,14 +1911,14 @@ AssignmentMarkerRange at::getAssignmentMarkers(DIAssignID *ID) { void at::deleteAssignmentMarkers(const Instruction *Inst) { auto Range = getAssignmentMarkers(Inst); - SmallVector<DPValue *> DPVAssigns = getDPVAssignmentMarkers(Inst); - if (Range.empty() && DPVAssigns.empty()) + SmallVector<DbgVariableRecord *> DVRAssigns = getDVRAssignmentMarkers(Inst); + if (Range.empty() && DVRAssigns.empty()) return; SmallVector<DbgAssignIntrinsic *> ToDelete(Range.begin(), Range.end()); for (auto *DAI : ToDelete) DAI->eraseFromParent(); - for (auto *DPV : DPVAssigns) - DPV->eraseFromParent(); + for (auto *DVR : DVRAssigns) + DVR->eraseFromParent(); } void at::RAUW(DIAssignID *Old, DIAssignID *New) { @@ -1825,12 +1936,12 @@ void at::RAUW(DIAssignID *Old, DIAssignID *New) { void at::deleteAll(Function *F) { SmallVector<DbgAssignIntrinsic *, 12> ToDelete; - SmallVector<DPValue *, 12> DPToDelete; + SmallVector<DbgVariableRecord *, 12> DPToDelete; for (BasicBlock &BB : *F) { for (Instruction &I : BB) { - for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) - if (DPV.isDbgAssign()) - DPToDelete.push_back(&DPV); + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) + if (DVR.isDbgAssign()) + DPToDelete.push_back(&DVR); if (auto *DAI = dyn_cast<DbgAssignIntrinsic>(&I)) ToDelete.push_back(DAI); else @@ -1839,20 +1950,20 @@ void at::deleteAll(Function *F) { } for (auto *DAI : ToDelete) DAI->eraseFromParent(); - for (auto *DPV : DPToDelete) - DPV->eraseFromParent(); + for (auto *DVR : DPToDelete) + DVR->eraseFromParent(); } /// Get the FragmentInfo for the variable if it exists, otherwise return a /// FragmentInfo that covers the entire variable if the variable size is /// known, otherwise return a zero-sized fragment. static DIExpression::FragmentInfo -getFragmentOrEntireVariable(const DPValue *DPV) { +getFragmentOrEntireVariable(const DbgVariableRecord *DVR) { DIExpression::FragmentInfo VariableSlice(0, 0); // Get the fragment or variable size, or zero. - if (auto Sz = DPV->getFragmentSizeInBits()) + if (auto Sz = DVR->getFragmentSizeInBits()) VariableSlice.SizeInBits = *Sz; - if (auto Frag = DPV->getExpression()->getFragmentInfo()) + if (auto Frag = DVR->getExpression()->getFragmentInfo()) VariableSlice.OffsetInBits = Frag->OffsetInBits; return VariableSlice; } @@ -2016,10 +2127,10 @@ bool at::calculateFragmentIntersect( } bool at::calculateFragmentIntersect( const DataLayout &DL, const Value *Dest, uint64_t SliceOffsetInBits, - uint64_t SliceSizeInBits, const DPValue *DPVAssign, + uint64_t SliceSizeInBits, const DbgVariableRecord *DVRAssign, std::optional<DIExpression::FragmentInfo> &Result) { return calculateFragmentIntersectImpl(DL, Dest, SliceOffsetInBits, - SliceSizeInBits, DPVAssign, Result); + SliceSizeInBits, DVRAssign, Result); } /// Collect constant properies (base, size, offset) of \p StoreDest. @@ -2113,7 +2224,7 @@ static void emitDbgAssign(AssignmentInfo Info, Value *Val, Value *Dest, DIExpression *AddrExpr = DIExpression::get(StoreLikeInst.getContext(), std::nullopt); if (StoreLikeInst.getParent()->IsNewDbgInfoFormat) { - auto *Assign = DPValue::createLinkedDPVAssign( + auto *Assign = DbgVariableRecord::createLinkedDVRAssign( &StoreLikeInst, Val, VarRec.Var, Expr, Dest, AddrExpr, VarRec.DL); (void)Assign; LLVM_DEBUG(if (Assign) errs() << " > INSERT: " << *Assign << "\n"); @@ -2231,7 +2342,7 @@ bool AssignmentTrackingPass::runOnFunction(Function &F) { // storage" is limited to Allocas). We'll use this to find dbg.declares to // delete after running `trackAssignments`. DenseMap<const AllocaInst *, SmallPtrSet<DbgDeclareInst *, 2>> DbgDeclares; - DenseMap<const AllocaInst *, SmallPtrSet<DPValue *, 2>> DPVDeclares; + DenseMap<const AllocaInst *, SmallPtrSet<DbgVariableRecord *, 2>> DVRDeclares; // Create another similar map of {storage : variables} that we'll pass to // trackAssignments. StorageToVarsMap Vars; @@ -2257,9 +2368,9 @@ bool AssignmentTrackingPass::runOnFunction(Function &F) { }; for (auto &BB : F) { for (auto &I : BB) { - for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) { - if (DPV.isDbgDeclare()) - ProcessDeclare(&DPV, DPVDeclares); + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { + if (DVR.isDbgDeclare()) + ProcessDeclare(&DVR, DVRDeclares); } if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(&I)) ProcessDeclare(DDI, DbgDeclares); @@ -2300,8 +2411,8 @@ bool AssignmentTrackingPass::runOnFunction(Function &F) { }; for (auto &P : DbgDeclares) DeleteSubsumedDeclare(at::getAssignmentMarkers(P.first), P.second); - for (auto &P : DPVDeclares) - DeleteSubsumedDeclare(at::getDPVAssignmentMarkers(P.first), P.second); + for (auto &P : DVRDeclares) + DeleteSubsumedDeclare(at::getDVRAssignmentMarkers(P.first), P.second); return Changed; } diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index 28f96653d815b5d23587fc0c9dc88b72ef18b854..570515505607fb7c9bb4e17d63d442120df4f888 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -34,6 +34,10 @@ cl::opt<bool> EnableFSDiscriminator( cl::desc("Enable adding flow sensitive discriminators")); } // namespace llvm +uint32_t DIType::getAlignInBits() const { + return (getTag() == dwarf::DW_TAG_LLVM_ptrauth_type ? 0 : SubclassData32); +} + const DIExpression::FragmentInfo DebugVariable::DefaultFragment = { std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::min()}; @@ -42,10 +46,10 @@ DebugVariable::DebugVariable(const DbgVariableIntrinsic *DII) Fragment(DII->getExpression()->getFragmentInfo()), InlinedAt(DII->getDebugLoc().getInlinedAt()) {} -DebugVariable::DebugVariable(const DPValue *DPV) - : Variable(DPV->getVariable()), - Fragment(DPV->getExpression()->getFragmentInfo()), - InlinedAt(DPV->getDebugLoc().getInlinedAt()) {} +DebugVariable::DebugVariable(const DbgVariableRecord *DVR) + : Variable(DVR->getVariable()), + Fragment(DVR->getExpression()->getFragmentInfo()), + InlinedAt(DVR->getDebugLoc().getInlinedAt()) {} DebugVariableAggregate::DebugVariableAggregate(const DbgVariableIntrinsic *DVI) : DebugVariable(DVI->getVariable(), std::nullopt, @@ -731,26 +735,32 @@ Constant *DIDerivedType::getDiscriminantValue() const { return nullptr; } -DIDerivedType * -DIDerivedType::getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, - Metadata *File, unsigned Line, Metadata *Scope, - Metadata *BaseType, uint64_t SizeInBits, - uint32_t AlignInBits, uint64_t OffsetInBits, - std::optional<unsigned> DWARFAddressSpace, DIFlags Flags, - Metadata *ExtraData, Metadata *Annotations, - StorageType Storage, bool ShouldCreate) { +DIDerivedType *DIDerivedType::getImpl( + LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, + uint32_t AlignInBits, uint64_t OffsetInBits, + std::optional<unsigned> DWARFAddressSpace, + std::optional<PtrAuthData> PtrAuthData, DIFlags Flags, Metadata *ExtraData, + Metadata *Annotations, StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP(DIDerivedType, (Tag, Name, File, Line, Scope, BaseType, SizeInBits, - AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, - ExtraData, Annotations)); + AlignInBits, OffsetInBits, DWARFAddressSpace, + PtrAuthData, Flags, ExtraData, Annotations)); Metadata *Ops[] = {File, Scope, Name, BaseType, ExtraData, Annotations}; DEFINE_GETIMPL_STORE(DIDerivedType, (Tag, Line, SizeInBits, AlignInBits, OffsetInBits, - DWARFAddressSpace, Flags), + DWARFAddressSpace, PtrAuthData, Flags), Ops); } +std::optional<DIDerivedType::PtrAuthData> +DIDerivedType::getPtrAuthData() const { + return getTag() == dwarf::DW_TAG_LLVM_ptrauth_type + ? std::optional<PtrAuthData>(PtrAuthData(SubclassData32)) + : std::nullopt; +} + DICompositeType *DICompositeType::getImpl( LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, @@ -1880,11 +1890,12 @@ DIExpression *DIExpression::append(const DIExpression *Expr, DIExpression *DIExpression::appendToStack(const DIExpression *Expr, ArrayRef<uint64_t> Ops) { assert(Expr && !Ops.empty() && "Can't append ops to this expression"); - assert(none_of(Ops, - [](uint64_t Op) { - return Op == dwarf::DW_OP_stack_value || - Op == dwarf::DW_OP_LLVM_fragment; - }) && + assert(std::none_of(expr_op_iterator(Ops.begin()), + expr_op_iterator(Ops.end()), + [](auto Op) { + return Op.getOp() == dwarf::DW_OP_stack_value || + Op.getOp() == dwarf::DW_OP_LLVM_fragment; + }) && "Can't append this op"); // Append a DW_OP_deref after Expr's current op list if it's non-empty and diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp index 019b00c2e2087da35afcfe06f592a08443d89b73..fbca7cdfcf3f5589297a0d00664e0d8d5b4333ec 100644 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ b/llvm/lib/IR/DebugProgramInstruction.cpp @@ -1,4 +1,4 @@ -//======-- DebugProgramInstruction.cpp - Implement DPValues/DPMarkers --======// +//=====-- DebugProgramInstruction.cpp - Implement DbgRecords/DbgMarkers --====// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -28,7 +28,7 @@ template class DbgRecordParamRef<DIExpression>; template class DbgRecordParamRef<DILabel>; template class DbgRecordParamRef<DILocalVariable>; -DPValue::DPValue(const DbgVariableIntrinsic *DVI) +DbgVariableRecord::DbgVariableRecord(const DbgVariableIntrinsic *DVI) : DbgRecord(ValueKind, DVI->getDebugLoc()), DebugValueUser({DVI->getRawLocation(), nullptr, nullptr}), Variable(DVI->getVariable()), Expression(DVI->getExpression()), @@ -51,25 +51,27 @@ DPValue::DPValue(const DbgVariableIntrinsic *DVI) } default: llvm_unreachable( - "Trying to create a DPValue with an invalid intrinsic type!"); + "Trying to create a DbgVariableRecord with an invalid intrinsic type!"); } } -DPValue::DPValue(const DPValue &DPV) - : DbgRecord(ValueKind, DPV.getDebugLoc()), DebugValueUser(DPV.DebugValues), - Type(DPV.getType()), Variable(DPV.getVariable()), - Expression(DPV.getExpression()), - AddressExpression(DPV.AddressExpression) {} +DbgVariableRecord::DbgVariableRecord(const DbgVariableRecord &DVR) + : DbgRecord(ValueKind, DVR.getDebugLoc()), DebugValueUser(DVR.DebugValues), + Type(DVR.getType()), Variable(DVR.getVariable()), + Expression(DVR.getExpression()), + AddressExpression(DVR.AddressExpression) {} -DPValue::DPValue(Metadata *Location, DILocalVariable *DV, DIExpression *Expr, - const DILocation *DI, LocationType Type) +DbgVariableRecord::DbgVariableRecord(Metadata *Location, DILocalVariable *DV, + DIExpression *Expr, const DILocation *DI, + LocationType Type) : DbgRecord(ValueKind, DI), DebugValueUser({Location, nullptr, nullptr}), Type(Type), Variable(DV), Expression(Expr) {} -DPValue::DPValue(Metadata *Value, DILocalVariable *Variable, - DIExpression *Expression, DIAssignID *AssignID, - Metadata *Address, DIExpression *AddressExpression, - const DILocation *DI) +DbgVariableRecord::DbgVariableRecord(Metadata *Value, DILocalVariable *Variable, + DIExpression *Expression, + DIAssignID *AssignID, Metadata *Address, + DIExpression *AddressExpression, + const DILocation *DI) : DbgRecord(ValueKind, DI), DebugValueUser({Value, Address, AssignID}), Type(LocationType::Assign), Variable(Variable), Expression(Expression), AddressExpression(AddressExpression) {} @@ -77,10 +79,10 @@ DPValue::DPValue(Metadata *Value, DILocalVariable *Variable, void DbgRecord::deleteRecord() { switch (RecordKind) { case ValueKind: - delete cast<DPValue>(this); + delete cast<DbgVariableRecord>(this); return; case LabelKind: - delete cast<DPLabel>(this); + delete cast<DbgLabelRecord>(this); return; } llvm_unreachable("unsupported DbgRecord kind"); @@ -89,10 +91,10 @@ void DbgRecord::deleteRecord() { void DbgRecord::print(raw_ostream &O, bool IsForDebug) const { switch (RecordKind) { case ValueKind: - cast<DPValue>(this)->print(O, IsForDebug); + cast<DbgVariableRecord>(this)->print(O, IsForDebug); return; case LabelKind: - cast<DPLabel>(this)->print(O, IsForDebug); + cast<DbgLabelRecord>(this)->print(O, IsForDebug); return; }; llvm_unreachable("unsupported DbgRecord kind"); @@ -102,10 +104,10 @@ void DbgRecord::print(raw_ostream &O, ModuleSlotTracker &MST, bool IsForDebug) const { switch (RecordKind) { case ValueKind: - cast<DPValue>(this)->print(O, MST, IsForDebug); + cast<DbgVariableRecord>(this)->print(O, MST, IsForDebug); return; case LabelKind: - cast<DPLabel>(this)->print(O, MST, IsForDebug); + cast<DbgLabelRecord>(this)->print(O, MST, IsForDebug); return; }; llvm_unreachable("unsupported DbgRecord kind"); @@ -116,9 +118,11 @@ bool DbgRecord::isIdenticalToWhenDefined(const DbgRecord &R) const { return false; switch (RecordKind) { case ValueKind: - return cast<DPValue>(this)->isIdenticalToWhenDefined(*cast<DPValue>(&R)); + return cast<DbgVariableRecord>(this)->isIdenticalToWhenDefined( + *cast<DbgVariableRecord>(&R)); case LabelKind: - return cast<DPLabel>(this)->getLabel() == cast<DPLabel>(R).getLabel(); + return cast<DbgLabelRecord>(this)->getLabel() == + cast<DbgLabelRecord>(R).getLabel(); }; llvm_unreachable("unsupported DbgRecord kind"); } @@ -131,101 +135,106 @@ DbgInfoIntrinsic * DbgRecord::createDebugIntrinsic(Module *M, Instruction *InsertBefore) const { switch (RecordKind) { case ValueKind: - return cast<DPValue>(this)->createDebugIntrinsic(M, InsertBefore); + return cast<DbgVariableRecord>(this)->createDebugIntrinsic(M, InsertBefore); case LabelKind: - return cast<DPLabel>(this)->createDebugIntrinsic(M, InsertBefore); + return cast<DbgLabelRecord>(this)->createDebugIntrinsic(M, InsertBefore); }; llvm_unreachable("unsupported DbgRecord kind"); } -DPLabel::DPLabel(MDNode *Label, MDNode *DL) +DbgLabelRecord::DbgLabelRecord(MDNode *Label, MDNode *DL) : DbgRecord(LabelKind, DebugLoc(DL)), Label(Label) { assert(Label && "Unexpected nullptr"); assert((isa<DILabel>(Label) || Label->isTemporary()) && "Label type must be or resolve to a DILabel"); } -DPLabel::DPLabel(DILabel *Label, DebugLoc DL) +DbgLabelRecord::DbgLabelRecord(DILabel *Label, DebugLoc DL) : DbgRecord(LabelKind, DL), Label(Label) { assert(Label && "Unexpected nullptr"); } -DPLabel *DPLabel::createUnresolvedDPLabel(MDNode *Label, MDNode *DL) { - return new DPLabel(Label, DL); +DbgLabelRecord *DbgLabelRecord::createUnresolvedDbgLabelRecord(MDNode *Label, + MDNode *DL) { + return new DbgLabelRecord(Label, DL); } -DPValue::DPValue(DPValue::LocationType Type, Metadata *Val, MDNode *Variable, - MDNode *Expression, MDNode *AssignID, Metadata *Address, - MDNode *AddressExpression, MDNode *DI) +DbgVariableRecord::DbgVariableRecord(DbgVariableRecord::LocationType Type, + Metadata *Val, MDNode *Variable, + MDNode *Expression, MDNode *AssignID, + Metadata *Address, + MDNode *AddressExpression, MDNode *DI) : DbgRecord(ValueKind, DebugLoc(DI)), DebugValueUser({Val, Address, AssignID}), Type(Type), Variable(Variable), Expression(Expression), AddressExpression(AddressExpression) {} -DPValue *DPValue::createUnresolvedDPValue(DPValue::LocationType Type, - Metadata *Val, MDNode *Variable, - MDNode *Expression, MDNode *AssignID, - Metadata *Address, - MDNode *AddressExpression, - MDNode *DI) { - return new DPValue(Type, Val, Variable, Expression, AssignID, Address, - AddressExpression, DI); +DbgVariableRecord *DbgVariableRecord::createUnresolvedDbgVariableRecord( + DbgVariableRecord::LocationType Type, Metadata *Val, MDNode *Variable, + MDNode *Expression, MDNode *AssignID, Metadata *Address, + MDNode *AddressExpression, MDNode *DI) { + return new DbgVariableRecord(Type, Val, Variable, Expression, AssignID, + Address, AddressExpression, DI); } -DPValue *DPValue::createDPValue(Value *Location, DILocalVariable *DV, - DIExpression *Expr, const DILocation *DI) { - return new DPValue(ValueAsMetadata::get(Location), DV, Expr, DI, - LocationType::Value); +DbgVariableRecord * +DbgVariableRecord::createDbgVariableRecord(Value *Location, DILocalVariable *DV, + DIExpression *Expr, + const DILocation *DI) { + return new DbgVariableRecord(ValueAsMetadata::get(Location), DV, Expr, DI, + LocationType::Value); } -DPValue *DPValue::createDPValue(Value *Location, DILocalVariable *DV, - DIExpression *Expr, const DILocation *DI, - DPValue &InsertBefore) { - auto *NewDPValue = createDPValue(Location, DV, Expr, DI); - NewDPValue->insertBefore(&InsertBefore); - return NewDPValue; +DbgVariableRecord *DbgVariableRecord::createDbgVariableRecord( + Value *Location, DILocalVariable *DV, DIExpression *Expr, + const DILocation *DI, DbgVariableRecord &InsertBefore) { + auto *NewDbgVariableRecord = createDbgVariableRecord(Location, DV, Expr, DI); + NewDbgVariableRecord->insertBefore(&InsertBefore); + return NewDbgVariableRecord; } -DPValue *DPValue::createDPVDeclare(Value *Address, DILocalVariable *DV, - DIExpression *Expr, const DILocation *DI) { - return new DPValue(ValueAsMetadata::get(Address), DV, Expr, DI, - LocationType::Declare); +DbgVariableRecord *DbgVariableRecord::createDVRDeclare(Value *Address, + DILocalVariable *DV, + DIExpression *Expr, + const DILocation *DI) { + return new DbgVariableRecord(ValueAsMetadata::get(Address), DV, Expr, DI, + LocationType::Declare); } -DPValue *DPValue::createDPVDeclare(Value *Address, DILocalVariable *DV, - DIExpression *Expr, const DILocation *DI, - DPValue &InsertBefore) { - auto *NewDPVDeclare = createDPVDeclare(Address, DV, Expr, DI); - NewDPVDeclare->insertBefore(&InsertBefore); - return NewDPVDeclare; +DbgVariableRecord * +DbgVariableRecord::createDVRDeclare(Value *Address, DILocalVariable *DV, + DIExpression *Expr, const DILocation *DI, + DbgVariableRecord &InsertBefore) { + auto *NewDVRDeclare = createDVRDeclare(Address, DV, Expr, DI); + NewDVRDeclare->insertBefore(&InsertBefore); + return NewDVRDeclare; } -DPValue *DPValue::createDPVAssign(Value *Val, DILocalVariable *Variable, - DIExpression *Expression, - DIAssignID *AssignID, Value *Address, - DIExpression *AddressExpression, - const DILocation *DI) { - return new DPValue(ValueAsMetadata::get(Val), Variable, Expression, AssignID, - ValueAsMetadata::get(Address), AddressExpression, DI); +DbgVariableRecord *DbgVariableRecord::createDVRAssign( + Value *Val, DILocalVariable *Variable, DIExpression *Expression, + DIAssignID *AssignID, Value *Address, DIExpression *AddressExpression, + const DILocation *DI) { + return new DbgVariableRecord(ValueAsMetadata::get(Val), Variable, Expression, + AssignID, ValueAsMetadata::get(Address), + AddressExpression, DI); } -DPValue *DPValue::createLinkedDPVAssign(Instruction *LinkedInstr, Value *Val, - DILocalVariable *Variable, - DIExpression *Expression, - Value *Address, - DIExpression *AddressExpression, - const DILocation *DI) { +DbgVariableRecord *DbgVariableRecord::createLinkedDVRAssign( + Instruction *LinkedInstr, Value *Val, DILocalVariable *Variable, + DIExpression *Expression, Value *Address, DIExpression *AddressExpression, + const DILocation *DI) { auto *Link = LinkedInstr->getMetadata(LLVMContext::MD_DIAssignID); assert(Link && "Linked instruction must have DIAssign metadata attached"); - auto *NewDPVAssign = DPValue::createDPVAssign(Val, Variable, Expression, - cast<DIAssignID>(Link), Address, - AddressExpression, DI); - LinkedInstr->getParent()->insertDbgRecordAfter(NewDPVAssign, LinkedInstr); - return NewDPVAssign; + auto *NewDVRAssign = DbgVariableRecord::createDVRAssign( + Val, Variable, Expression, cast<DIAssignID>(Link), Address, + AddressExpression, DI); + LinkedInstr->getParent()->insertDbgRecordAfter(NewDVRAssign, LinkedInstr); + return NewDVRAssign; } -iterator_range<DPValue::location_op_iterator> DPValue::location_ops() const { +iterator_range<DbgVariableRecord::location_op_iterator> +DbgVariableRecord::location_ops() const { auto *MD = getRawLocation(); - // If a Value has been deleted, the "location" for this DPValue will be - // replaced by nullptr. Return an empty range. + // If a Value has been deleted, the "location" for this DbgVariableRecord will + // be replaced by nullptr. Return an empty range. if (!MD) return {location_op_iterator(static_cast<ValueAsMetadata *>(nullptr)), location_op_iterator(static_cast<ValueAsMetadata *>(nullptr))}; @@ -245,13 +254,13 @@ iterator_range<DPValue::location_op_iterator> DPValue::location_ops() const { location_op_iterator(static_cast<ValueAsMetadata *>(nullptr))}; } -unsigned DPValue::getNumVariableLocationOps() const { +unsigned DbgVariableRecord::getNumVariableLocationOps() const { if (hasArgList()) return cast<DIArgList>(getRawLocation())->getArgs().size(); return 1; } -Value *DPValue::getVariableLocationOp(unsigned OpIdx) const { +Value *DbgVariableRecord::getVariableLocationOp(unsigned OpIdx) const { auto *MD = getRawLocation(); if (!MD) return nullptr; @@ -261,7 +270,7 @@ Value *DPValue::getVariableLocationOp(unsigned OpIdx) const { if (isa<MDNode>(MD)) return nullptr; assert(isa<ValueAsMetadata>(MD) && - "Attempted to get location operand from DPValue with none."); + "Attempted to get location operand from DbgVariableRecord with none."); auto *V = cast<ValueAsMetadata>(MD); assert(OpIdx == 0 && "Operand Index must be 0 for a debug intrinsic with a " "single location operand."); @@ -274,8 +283,9 @@ static ValueAsMetadata *getAsMetadata(Value *V) { : ValueAsMetadata::get(V); } -void DPValue::replaceVariableLocationOp(Value *OldValue, Value *NewValue, - bool AllowEmpty) { +void DbgVariableRecord::replaceVariableLocationOp(Value *OldValue, + Value *NewValue, + bool AllowEmpty) { assert(NewValue && "Values must be non-null"); bool DbgAssignAddrReplaced = isDbgAssign() && OldValue == getAddress(); @@ -307,7 +317,8 @@ void DPValue::replaceVariableLocationOp(Value *OldValue, Value *NewValue, setRawLocation(DIArgList::get(getVariableLocationOp(0)->getContext(), MDs)); } -void DPValue::replaceVariableLocationOp(unsigned OpIdx, Value *NewValue) { +void DbgVariableRecord::replaceVariableLocationOp(unsigned OpIdx, + Value *NewValue) { assert(OpIdx < getNumVariableLocationOps() && "Invalid Operand Index"); if (!hasArgList()) { @@ -326,8 +337,8 @@ void DPValue::replaceVariableLocationOp(unsigned OpIdx, Value *NewValue) { setRawLocation(DIArgList::get(getVariableLocationOp(0)->getContext(), MDs)); } -void DPValue::addVariableLocationOps(ArrayRef<Value *> NewValues, - DIExpression *NewExpr) { +void DbgVariableRecord::addVariableLocationOps(ArrayRef<Value *> NewValues, + DIExpression *NewExpr) { assert(NewExpr->hasAllLocationOps(getNumVariableLocationOps() + NewValues.size()) && "NewExpr for debug variable intrinsic does not reference every " @@ -342,7 +353,7 @@ void DPValue::addVariableLocationOps(ArrayRef<Value *> NewValues, setRawLocation(DIArgList::get(getVariableLocationOp(0)->getContext(), MDs)); } -void DPValue::setKillLocation() { +void DbgVariableRecord::setKillLocation() { // TODO: When/if we remove duplicate values from DIArgLists, we don't need // this set anymore. SmallPtrSet<Value *, 4> RemovedValues; @@ -354,13 +365,13 @@ void DPValue::setKillLocation() { } } -bool DPValue::isKillLocation() const { +bool DbgVariableRecord::isKillLocation() const { return (getNumVariableLocationOps() == 0 && !getExpression()->isComplex()) || any_of(location_ops(), [](Value *V) { return isa<UndefValue>(V); }); } -std::optional<uint64_t> DPValue::getFragmentSizeInBits() const { +std::optional<uint64_t> DbgVariableRecord::getFragmentSizeInBits() const { if (auto Fragment = getExpression()->getFragmentInfo()) return Fragment->SizeInBits; return getVariable()->getSizeInBits(); @@ -369,21 +380,24 @@ std::optional<uint64_t> DPValue::getFragmentSizeInBits() const { DbgRecord *DbgRecord::clone() const { switch (RecordKind) { case ValueKind: - return cast<DPValue>(this)->clone(); + return cast<DbgVariableRecord>(this)->clone(); case LabelKind: - return cast<DPLabel>(this)->clone(); + return cast<DbgLabelRecord>(this)->clone(); }; llvm_unreachable("unsupported DbgRecord kind"); } -DPValue *DPValue::clone() const { return new DPValue(*this); } +DbgVariableRecord *DbgVariableRecord::clone() const { + return new DbgVariableRecord(*this); +} -DPLabel *DPLabel::clone() const { - return new DPLabel(getLabel(), getDebugLoc()); +DbgLabelRecord *DbgLabelRecord::clone() const { + return new DbgLabelRecord(getLabel(), getDebugLoc()); } DbgVariableIntrinsic * -DPValue::createDebugIntrinsic(Module *M, Instruction *InsertBefore) const { +DbgVariableRecord::createDebugIntrinsic(Module *M, + Instruction *InsertBefore) const { [[maybe_unused]] DICompileUnit *Unit = getDebugLoc().get()->getScope()->getSubprogram()->getUnit(); assert(M && Unit && @@ -394,24 +408,25 @@ DPValue::createDebugIntrinsic(Module *M, Instruction *InsertBefore) const { // Work out what sort of intrinsic we're going to produce. switch (getType()) { - case DPValue::LocationType::Declare: + case DbgVariableRecord::LocationType::Declare: IntrinsicFn = Intrinsic::getDeclaration(M, Intrinsic::dbg_declare); break; - case DPValue::LocationType::Value: + case DbgVariableRecord::LocationType::Value: IntrinsicFn = Intrinsic::getDeclaration(M, Intrinsic::dbg_value); break; - case DPValue::LocationType::Assign: + case DbgVariableRecord::LocationType::Assign: IntrinsicFn = Intrinsic::getDeclaration(M, Intrinsic::dbg_assign); break; - case DPValue::LocationType::End: - case DPValue::LocationType::Any: + case DbgVariableRecord::LocationType::End: + case DbgVariableRecord::LocationType::Any: llvm_unreachable("Invalid LocationType"); } - // Create the intrinsic from this DPValue's information, optionally insert - // into the target location. + // Create the intrinsic from this DbgVariableRecord's information, optionally + // insert into the target location. DbgVariableIntrinsic *DVI; - assert(getRawLocation() && "DPValue's RawLocation should be non-null."); + assert(getRawLocation() && + "DbgVariableRecord's RawLocation should be non-null."); if (isDbgAssign()) { Value *AssignArgs[] = { MetadataAsValue::get(Context, getRawLocation()), @@ -437,8 +452,9 @@ DPValue::createDebugIntrinsic(Module *M, Instruction *InsertBefore) const { return DVI; } -DbgLabelInst *DPLabel::createDebugIntrinsic(Module *M, - Instruction *InsertBefore) const { +DbgLabelInst * +DbgLabelRecord::createDebugIntrinsic(Module *M, + Instruction *InsertBefore) const { auto *LabelFn = Intrinsic::getDeclaration(M, Intrinsic::dbg_label); Value *Args[] = { MetadataAsValue::get(getDebugLoc()->getContext(), getLabel())}; @@ -451,7 +467,7 @@ DbgLabelInst *DPLabel::createDebugIntrinsic(Module *M, return DbgLabel; } -Value *DPValue::getAddress() const { +Value *DbgVariableRecord::getAddress() const { auto *MD = getRawAddress(); if (auto *V = dyn_cast<ValueAsMetadata>(MD)) return V->getValue(); @@ -461,18 +477,20 @@ Value *DPValue::getAddress() const { return nullptr; } -DIAssignID *DPValue::getAssignID() const { +DIAssignID *DbgVariableRecord::getAssignID() const { return cast<DIAssignID>(DebugValues[2]); } -void DPValue::setAssignId(DIAssignID *New) { resetDebugValue(2, New); } +void DbgVariableRecord::setAssignId(DIAssignID *New) { + resetDebugValue(2, New); +} -void DPValue::setKillAddress() { +void DbgVariableRecord::setKillAddress() { resetDebugValue( 1, ValueAsMetadata::get(UndefValue::get(getAddress()->getType()))); } -bool DPValue::isKillAddress() const { +bool DbgVariableRecord::isKillAddress() const { Value *Addr = getAddress(); return !Addr || isa<UndefValue>(Addr); } @@ -511,73 +529,73 @@ const LLVMContext &DbgRecord::getContext() const { void DbgRecord::insertBefore(DbgRecord *InsertBefore) { assert(!getMarker() && - "Cannot insert a DbgRecord that is already has a DPMarker!"); + "Cannot insert a DbgRecord that is already has a DbgMarker!"); assert(InsertBefore->getMarker() && "Cannot insert a DbgRecord before a DbgRecord that does not have a " - "DPMarker!"); + "DbgMarker!"); InsertBefore->getMarker()->insertDbgRecord(this, InsertBefore); } void DbgRecord::insertAfter(DbgRecord *InsertAfter) { assert(!getMarker() && - "Cannot insert a DbgRecord that is already has a DPMarker!"); + "Cannot insert a DbgRecord that is already has a DbgMarker!"); assert(InsertAfter->getMarker() && "Cannot insert a DbgRecord after a DbgRecord that does not have a " - "DPMarker!"); + "DbgMarker!"); InsertAfter->getMarker()->insertDbgRecordAfter(this, InsertAfter); } void DbgRecord::moveBefore(DbgRecord *MoveBefore) { assert(getMarker() && - "Canot move a DbgRecord that does not currently have a DPMarker!"); + "Canot move a DbgRecord that does not currently have a DbgMarker!"); removeFromParent(); insertBefore(MoveBefore); } void DbgRecord::moveAfter(DbgRecord *MoveAfter) { assert(getMarker() && - "Canot move a DbgRecord that does not currently have a DPMarker!"); + "Canot move a DbgRecord that does not currently have a DbgMarker!"); removeFromParent(); insertAfter(MoveAfter); } /////////////////////////////////////////////////////////////////////////////// -// An empty, global, DPMarker for the purpose of describing empty ranges of -// DPValues. -DPMarker DPMarker::EmptyDPMarker; +// An empty, global, DbgMarker for the purpose of describing empty ranges of +// DbgRecords. +DbgMarker DbgMarker::EmptyDbgMarker; -void DPMarker::dropDbgRecords() { - while (!StoredDPValues.empty()) { - auto It = StoredDPValues.begin(); +void DbgMarker::dropDbgRecords() { + while (!StoredDbgRecords.empty()) { + auto It = StoredDbgRecords.begin(); DbgRecord *DR = &*It; - StoredDPValues.erase(It); + StoredDbgRecords.erase(It); DR->deleteRecord(); } } -void DPMarker::dropOneDbgRecord(DbgRecord *DR) { +void DbgMarker::dropOneDbgRecord(DbgRecord *DR) { assert(DR->getMarker() == this); - StoredDPValues.erase(DR->getIterator()); + StoredDbgRecords.erase(DR->getIterator()); DR->deleteRecord(); } -const BasicBlock *DPMarker::getParent() const { +const BasicBlock *DbgMarker::getParent() const { return MarkedInstr->getParent(); } -BasicBlock *DPMarker::getParent() { return MarkedInstr->getParent(); } +BasicBlock *DbgMarker::getParent() { return MarkedInstr->getParent(); } -void DPMarker::removeMarker() { - // Are there any DPValues in this DPMarker? If not, nothing to preserve. +void DbgMarker::removeMarker() { + // Are there any DbgRecords in this DbgMarker? If not, nothing to preserve. Instruction *Owner = MarkedInstr; - if (StoredDPValues.empty()) { + if (StoredDbgRecords.empty()) { eraseFromParent(); - Owner->DbgMarker = nullptr; + Owner->DebugMarker = nullptr; return; } - // The attached DPValues need to be preserved; attach them to the next + // The attached DbgRecords need to be preserved; attach them to the next // instruction. If there isn't a next instruction, put them on the // "trailing" list. - DPMarker *NextMarker = Owner->getParent()->getNextMarker(Owner); + DbgMarker *NextMarker = Owner->getParent()->getNextMarker(Owner); if (NextMarker) { NextMarker->absorbDebugValues(*this, true); eraseFromParent(); @@ -590,35 +608,35 @@ void DPMarker::removeMarker() { getParent()->setTrailingDbgRecords(this); MarkedInstr = nullptr; } else { - NextIt->DbgMarker = this; + NextIt->DebugMarker = this; MarkedInstr = &*NextIt; } } - Owner->DbgMarker = nullptr; + Owner->DebugMarker = nullptr; } -void DPMarker::removeFromParent() { - MarkedInstr->DbgMarker = nullptr; +void DbgMarker::removeFromParent() { + MarkedInstr->DebugMarker = nullptr; MarkedInstr = nullptr; } -void DPMarker::eraseFromParent() { +void DbgMarker::eraseFromParent() { if (MarkedInstr) removeFromParent(); dropDbgRecords(); delete this; } -iterator_range<DbgRecord::self_iterator> DPMarker::getDbgRecordRange() { - return make_range(StoredDPValues.begin(), StoredDPValues.end()); +iterator_range<DbgRecord::self_iterator> DbgMarker::getDbgRecordRange() { + return make_range(StoredDbgRecords.begin(), StoredDbgRecords.end()); } iterator_range<DbgRecord::const_self_iterator> -DPMarker::getDbgRecordRange() const { - return make_range(StoredDPValues.begin(), StoredDPValues.end()); +DbgMarker::getDbgRecordRange() const { + return make_range(StoredDbgRecords.begin(), StoredDbgRecords.end()); } void DbgRecord::removeFromParent() { - getMarker()->StoredDPValues.erase(getIterator()); + getMarker()->StoredDbgRecords.erase(getIterator()); Marker = nullptr; } @@ -627,77 +645,78 @@ void DbgRecord::eraseFromParent() { deleteRecord(); } -void DPMarker::insertDbgRecord(DbgRecord *New, bool InsertAtHead) { - auto It = InsertAtHead ? StoredDPValues.begin() : StoredDPValues.end(); - StoredDPValues.insert(It, *New); +void DbgMarker::insertDbgRecord(DbgRecord *New, bool InsertAtHead) { + auto It = InsertAtHead ? StoredDbgRecords.begin() : StoredDbgRecords.end(); + StoredDbgRecords.insert(It, *New); New->setMarker(this); } -void DPMarker::insertDbgRecord(DbgRecord *New, DbgRecord *InsertBefore) { +void DbgMarker::insertDbgRecord(DbgRecord *New, DbgRecord *InsertBefore) { assert(InsertBefore->getMarker() == this && - "DPValue 'InsertBefore' must be contained in this DPMarker!"); - StoredDPValues.insert(InsertBefore->getIterator(), *New); + "DbgRecord 'InsertBefore' must be contained in this DbgMarker!"); + StoredDbgRecords.insert(InsertBefore->getIterator(), *New); New->setMarker(this); } -void DPMarker::insertDbgRecordAfter(DbgRecord *New, DbgRecord *InsertAfter) { +void DbgMarker::insertDbgRecordAfter(DbgRecord *New, DbgRecord *InsertAfter) { assert(InsertAfter->getMarker() == this && - "DPValue 'InsertAfter' must be contained in this DPMarker!"); - StoredDPValues.insert(++(InsertAfter->getIterator()), *New); + "DbgRecord 'InsertAfter' must be contained in this DbgMarker!"); + StoredDbgRecords.insert(++(InsertAfter->getIterator()), *New); New->setMarker(this); } -void DPMarker::absorbDebugValues(DPMarker &Src, bool InsertAtHead) { - auto It = InsertAtHead ? StoredDPValues.begin() : StoredDPValues.end(); - for (DbgRecord &DPV : Src.StoredDPValues) - DPV.setMarker(this); +void DbgMarker::absorbDebugValues(DbgMarker &Src, bool InsertAtHead) { + auto It = InsertAtHead ? StoredDbgRecords.begin() : StoredDbgRecords.end(); + for (DbgRecord &DVR : Src.StoredDbgRecords) + DVR.setMarker(this); - StoredDPValues.splice(It, Src.StoredDPValues); + StoredDbgRecords.splice(It, Src.StoredDbgRecords); } -void DPMarker::absorbDebugValues(iterator_range<DbgRecord::self_iterator> Range, - DPMarker &Src, bool InsertAtHead) { +void DbgMarker::absorbDebugValues( + iterator_range<DbgRecord::self_iterator> Range, DbgMarker &Src, + bool InsertAtHead) { for (DbgRecord &DR : Range) DR.setMarker(this); auto InsertPos = - (InsertAtHead) ? StoredDPValues.begin() : StoredDPValues.end(); + (InsertAtHead) ? StoredDbgRecords.begin() : StoredDbgRecords.end(); - StoredDPValues.splice(InsertPos, Src.StoredDPValues, Range.begin(), - Range.end()); + StoredDbgRecords.splice(InsertPos, Src.StoredDbgRecords, Range.begin(), + Range.end()); } -iterator_range<simple_ilist<DbgRecord>::iterator> DPMarker::cloneDebugInfoFrom( - DPMarker *From, std::optional<simple_ilist<DbgRecord>::iterator> from_here, +iterator_range<simple_ilist<DbgRecord>::iterator> DbgMarker::cloneDebugInfoFrom( + DbgMarker *From, std::optional<simple_ilist<DbgRecord>::iterator> from_here, bool InsertAtHead) { DbgRecord *First = nullptr; - // Work out what range of DPValues to clone: normally all the contents of the - // "From" marker, optionally we can start from the from_here position down to - // end(). + // Work out what range of DbgRecords to clone: normally all the contents of + // the "From" marker, optionally we can start from the from_here position down + // to end(). auto Range = - make_range(From->StoredDPValues.begin(), From->StoredDPValues.end()); + make_range(From->StoredDbgRecords.begin(), From->StoredDbgRecords.end()); if (from_here.has_value()) - Range = make_range(*from_here, From->StoredDPValues.end()); + Range = make_range(*from_here, From->StoredDbgRecords.end()); - // Clone each DPValue and insert into StoreDPValues; optionally place them at - // the start or the end of the list. - auto Pos = (InsertAtHead) ? StoredDPValues.begin() : StoredDPValues.end(); + // Clone each DbgVariableRecord and insert into StoreDbgVariableRecords; + // optionally place them at the start or the end of the list. + auto Pos = (InsertAtHead) ? StoredDbgRecords.begin() : StoredDbgRecords.end(); for (DbgRecord &DR : Range) { DbgRecord *New = DR.clone(); New->setMarker(this); - StoredDPValues.insert(Pos, *New); + StoredDbgRecords.insert(Pos, *New); if (!First) First = New; } if (!First) - return {StoredDPValues.end(), StoredDPValues.end()}; + return {StoredDbgRecords.end(), StoredDbgRecords.end()}; if (InsertAtHead) // If InsertAtHead is set, we cloned a range onto the front of of the - // StoredDPValues collection, return that range. - return {StoredDPValues.begin(), Pos}; + // StoredDbgRecords collection, return that range. + return {StoredDbgRecords.begin(), Pos}; else // We inserted a block at the end, return that range. - return {First->getIterator(), StoredDPValues.end()}; + return {First->getIterator(), StoredDbgRecords.end()}; } } // end namespace llvm diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index d22e1c123111896a8773c0854d16f0ecfda589fe..eb126f182eadcb7a57a56a9fed84139fa0a7ddc2 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -24,6 +24,7 @@ #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constant.h" +#include "llvm/IR/ConstantRange.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GlobalValue.h" @@ -256,6 +257,13 @@ FPClassTest Argument::getNoFPClass() const { return getParent()->getParamNoFPClass(getArgNo()); } +std::optional<ConstantRange> Argument::getRange() const { + const Attribute RangeAttr = getAttribute(llvm::Attribute::Range); + if (RangeAttr.isValid()) + return RangeAttr.getRange(); + return std::nullopt; +} + bool Argument::hasNestAttr() const { if (!getType()->isPointerTy()) return false; return hasAttribute(Attribute::Nest); diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp index 481a1d802e66b6aa8e749240c49a6359842de21c..40f854a2c90635784b261634a529b4979b1ad546 100644 --- a/llvm/lib/IR/Globals.cpp +++ b/llvm/lib/IR/Globals.cpp @@ -243,6 +243,13 @@ void GlobalValue::removeSanitizerMetadata() { HasSanitizerMetadata = false; } +void GlobalValue::setNoSanitizeMetadata() { + SanitizerMetadata Meta; + Meta.NoAddress = true; + Meta.NoHWAddress = true; + setSanitizerMetadata(Meta); +} + StringRef GlobalObject::getSectionImpl() const { assert(hasSection()); return getContext().pImpl->GlobalObjectSections[this]; diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index b09b80f95871a1c8c2aa3463d0e1d6cb4de08884..d6746d1d438242b6540387436edade17a6906356 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -918,12 +918,14 @@ CallInst *IRBuilderBase::CreateUnaryIntrinsic(Intrinsic::ID ID, Value *V, return createCallHelper(Fn, {V}, Name, FMFSource); } -CallInst *IRBuilderBase::CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, - Value *RHS, - Instruction *FMFSource, - const Twine &Name) { +Value *IRBuilderBase::CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, + Value *RHS, Instruction *FMFSource, + const Twine &Name) { Module *M = BB->getModule(); Function *Fn = Intrinsic::getDeclaration(M, ID, { LHS->getType() }); + if (Value *V = Folder.FoldBinaryIntrinsic(ID, LHS, RHS, Fn->getReturnType(), + FMFSource)) + return V; return createCallHelper(Fn, {LHS, RHS}, Name, FMFSource); } diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp index e0892398f4344530e684499a0ed7d90182b7046f..0602a55b9fe7f3ae92fb2b13cced53ced89b76a8 100644 --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -93,10 +93,10 @@ void Instruction::removeFromParent() { } void Instruction::handleMarkerRemoval() { - if (!Parent->IsNewDbgInfoFormat || !DbgMarker) + if (!Parent->IsNewDbgInfoFormat || !DebugMarker) return; - DbgMarker->removeMarker(); + DebugMarker->removeMarker(); } BasicBlock::iterator Instruction::eraseFromParent() { @@ -135,7 +135,7 @@ extern cl::opt<bool> UseNewDbgInfoFormat; void Instruction::insertBefore(BasicBlock &BB, InstListType::iterator InsertPos) { - assert(!DbgMarker); + assert(!DebugMarker); BB.getInstList().insert(InsertPos, this); @@ -143,11 +143,11 @@ void Instruction::insertBefore(BasicBlock &BB, return; // We've inserted "this": if InsertAtHead is set then it comes before any - // DPValues attached to InsertPos. But if it's not set, then any DPValues - // should now come before "this". + // DbgVariableRecords attached to InsertPos. But if it's not set, then any + // DbgRecords should now come before "this". bool InsertAtHead = InsertPos.getHeadBit(); if (!InsertAtHead) { - DPMarker *SrcMarker = BB.getMarker(InsertPos); + DbgMarker *SrcMarker = BB.getMarker(InsertPos); if (SrcMarker && !SrcMarker->empty()) { // If this assertion fires, the calling code is about to insert a PHI // after debug-records, which would form a sequence like: @@ -166,10 +166,10 @@ void Instruction::insertBefore(BasicBlock &BB, } // If we're inserting a terminator, check if we need to flush out - // TrailingDPValues. Inserting instructions at the end of an incomplete + // TrailingDbgRecords. Inserting instructions at the end of an incomplete // block is handled by the code block above. if (isTerminator()) - getParent()->flushTerminatorDbgValues(); + getParent()->flushTerminatorDbgRecords(); } /// Unlink this instruction from its current basic block and insert it into the @@ -212,12 +212,12 @@ void Instruction::moveBeforeImpl(BasicBlock &BB, InstListType::iterator I, assert(I == BB.end() || I->getParent() == &BB); bool InsertAtHead = I.getHeadBit(); - // If we've been given the "Preserve" flag, then just move the DPValues with + // If we've been given the "Preserve" flag, then just move the DbgRecords with // the instruction, no more special handling needed. - if (BB.IsNewDbgInfoFormat && DbgMarker && !Preserve) { + if (BB.IsNewDbgInfoFormat && DebugMarker && !Preserve) { if (I != this->getIterator() || InsertAtHead) { // "this" is definitely moving in the list, or it's moving ahead of its - // attached DPValues. Detach any existing DPValues. + // attached DbgVariableRecords. Detach any existing DbgRecords. handleMarkerRemoval(); } } @@ -227,73 +227,74 @@ void Instruction::moveBeforeImpl(BasicBlock &BB, InstListType::iterator I, BB.getInstList().splice(I, getParent()->getInstList(), getIterator()); if (BB.IsNewDbgInfoFormat && !Preserve) { - DPMarker *NextMarker = getParent()->getNextMarker(this); + DbgMarker *NextMarker = getParent()->getNextMarker(this); - // If we're inserting at point I, and not in front of the DPValues attached - // there, then we should absorb the DPValues attached to I. + // If we're inserting at point I, and not in front of the DbgRecords + // attached there, then we should absorb the DbgRecords attached to I. if (!InsertAtHead && NextMarker && !NextMarker->empty()) { adoptDbgRecords(&BB, I, false); } } if (isTerminator()) - getParent()->flushTerminatorDbgValues(); + getParent()->flushTerminatorDbgRecords(); } iterator_range<DbgRecord::self_iterator> Instruction::cloneDebugInfoFrom( const Instruction *From, std::optional<DbgRecord::self_iterator> FromHere, bool InsertAtHead) { - if (!From->DbgMarker) - return DPMarker::getEmptyDbgRecordRange(); + if (!From->DebugMarker) + return DbgMarker::getEmptyDbgRecordRange(); assert(getParent()->IsNewDbgInfoFormat); assert(getParent()->IsNewDbgInfoFormat == From->getParent()->IsNewDbgInfoFormat); - if (!DbgMarker) + if (!DebugMarker) getParent()->createMarker(this); - return DbgMarker->cloneDebugInfoFrom(From->DbgMarker, FromHere, InsertAtHead); + return DebugMarker->cloneDebugInfoFrom(From->DebugMarker, FromHere, + InsertAtHead); } std::optional<DbgRecord::self_iterator> Instruction::getDbgReinsertionPosition() { // Is there a marker on the next instruction? - DPMarker *NextMarker = getParent()->getNextMarker(this); + DbgMarker *NextMarker = getParent()->getNextMarker(this); if (!NextMarker) return std::nullopt; - // Are there any DPValues in the next marker? - if (NextMarker->StoredDPValues.empty()) + // Are there any DbgRecords in the next marker? + if (NextMarker->StoredDbgRecords.empty()) return std::nullopt; - return NextMarker->StoredDPValues.begin(); + return NextMarker->StoredDbgRecords.begin(); } bool Instruction::hasDbgRecords() const { return !getDbgRecordRange().empty(); } void Instruction::adoptDbgRecords(BasicBlock *BB, BasicBlock::iterator It, bool InsertAtHead) { - DPMarker *SrcMarker = BB->getMarker(It); - auto ReleaseTrailingDPValues = [BB, It, SrcMarker]() { + DbgMarker *SrcMarker = BB->getMarker(It); + auto ReleaseTrailingDbgRecords = [BB, It, SrcMarker]() { if (BB->end() == It) { SrcMarker->eraseFromParent(); BB->deleteTrailingDbgRecords(); } }; - if (!SrcMarker || SrcMarker->StoredDPValues.empty()) { - ReleaseTrailingDPValues(); + if (!SrcMarker || SrcMarker->StoredDbgRecords.empty()) { + ReleaseTrailingDbgRecords(); return; } - // If we have DPMarkers attached to this instruction, we have to honour the - // ordering of DPValues between this and the other marker. Fall back to just + // If we have DbgMarkers attached to this instruction, we have to honour the + // ordering of DbgRecords between this and the other marker. Fall back to just // absorbing from the source. - if (DbgMarker || It == BB->end()) { + if (DebugMarker || It == BB->end()) { // Ensure we _do_ have a marker. getParent()->createMarker(this); - DbgMarker->absorbDebugValues(*SrcMarker, InsertAtHead); + DebugMarker->absorbDebugValues(*SrcMarker, InsertAtHead); // Having transferred everything out of SrcMarker, we _could_ clean it up // and free the marker now. However, that's a lot of heap-accounting for a @@ -304,23 +305,24 @@ void Instruction::adoptDbgRecords(BasicBlock *BB, BasicBlock::iterator It, // block, it's important to not leave the empty marker trailing. It will // give a misleading impression that some debug records have been left // trailing. - ReleaseTrailingDPValues(); + ReleaseTrailingDbgRecords(); } else { - // Optimisation: we're transferring all the DPValues from the source marker - // onto this empty location: just adopt the other instructions marker. - DbgMarker = SrcMarker; - DbgMarker->MarkedInstr = this; - It->DbgMarker = nullptr; + // Optimisation: we're transferring all the DbgRecords from the source + // marker onto this empty location: just adopt the other instructions + // marker. + DebugMarker = SrcMarker; + DebugMarker->MarkedInstr = this; + It->DebugMarker = nullptr; } } void Instruction::dropDbgRecords() { - if (DbgMarker) - DbgMarker->dropDbgRecords(); + if (DebugMarker) + DebugMarker->dropDbgRecords(); } -void Instruction::dropOneDbgRecord(DbgRecord *DPV) { - DbgMarker->dropOneDbgRecord(DPV); +void Instruction::dropOneDbgRecord(DbgRecord *DVR) { + DebugMarker->dropOneDbgRecord(DVR); } bool Instruction::comesBefore(const Instruction *Other) const { @@ -368,11 +370,17 @@ bool Instruction::isOnlyUserOfAnyOperand() { } void Instruction::setHasNoUnsignedWrap(bool b) { - cast<OverflowingBinaryOperator>(this)->setHasNoUnsignedWrap(b); + if (auto *Inst = dyn_cast<OverflowingBinaryOperator>(this)) + Inst->setHasNoUnsignedWrap(b); + else + cast<TruncInst>(this)->setHasNoUnsignedWrap(b); } void Instruction::setHasNoSignedWrap(bool b) { - cast<OverflowingBinaryOperator>(this)->setHasNoSignedWrap(b); + if (auto *Inst = dyn_cast<OverflowingBinaryOperator>(this)) + Inst->setHasNoSignedWrap(b); + else + cast<TruncInst>(this)->setHasNoSignedWrap(b); } void Instruction::setIsExact(bool b) { @@ -386,11 +394,17 @@ void Instruction::setNonNeg(bool b) { } bool Instruction::hasNoUnsignedWrap() const { - return cast<OverflowingBinaryOperator>(this)->hasNoUnsignedWrap(); + if (auto *Inst = dyn_cast<OverflowingBinaryOperator>(this)) + return Inst->hasNoUnsignedWrap(); + + return cast<TruncInst>(this)->hasNoUnsignedWrap(); } bool Instruction::hasNoSignedWrap() const { - return cast<OverflowingBinaryOperator>(this)->hasNoSignedWrap(); + if (auto *Inst = dyn_cast<OverflowingBinaryOperator>(this)) + return Inst->hasNoSignedWrap(); + + return cast<TruncInst>(this)->hasNoSignedWrap(); } bool Instruction::hasNonNeg() const { @@ -430,6 +444,11 @@ void Instruction::dropPoisonGeneratingFlags() { case Instruction::ZExt: setNonNeg(false); break; + + case Instruction::Trunc: + cast<TruncInst>(this)->setHasNoUnsignedWrap(false); + cast<TruncInst>(this)->setHasNoSignedWrap(false); + break; } if (isa<FPMathOperator>(this)) { @@ -624,6 +643,13 @@ void Instruction::andIRFlags(const Value *V) { } } + if (auto *TI = dyn_cast<TruncInst>(V)) { + if (isa<TruncInst>(this)) { + setHasNoSignedWrap(hasNoSignedWrap() && TI->hasNoSignedWrap()); + setHasNoUnsignedWrap(hasNoUnsignedWrap() && TI->hasNoUnsignedWrap()); + } + } + if (auto *PE = dyn_cast<PossiblyExactOperator>(V)) if (isa<PossiblyExactOperator>(this)) setIsExact(isExact() && PE->isExact()); diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index c55d6cff84ed55099013269282790d1a8dd2964a..cec02e2ce6338bbdc4ecc73b9e9a6c406050f8cb 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -19,6 +19,7 @@ #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constant.h" +#include "llvm/IR/ConstantRange.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" @@ -395,6 +396,13 @@ FPClassTest CallBase::getParamNoFPClass(unsigned i) const { return Mask; } +std::optional<ConstantRange> CallBase::getRange() const { + const Attribute RangeAttr = getRetAttr(llvm::Attribute::Range); + if (RangeAttr.isValid()) + return RangeAttr.getRange(); + return std::nullopt; +} + bool CallBase::isReturnNonNull() const { if (hasRetAttr(Attribute::NonNull)) return true; @@ -825,15 +833,6 @@ CallInst *CallInst::Create(CallInst *CI, ArrayRef<OperandBundleDef> OpB, // of S/T. The meaning of "branch_weights" meta data for call instruction is // transfered to represent call count. void CallInst::updateProfWeight(uint64_t S, uint64_t T) { - auto *ProfileData = getMetadata(LLVMContext::MD_prof); - if (ProfileData == nullptr) - return; - - auto *ProfDataName = dyn_cast<MDString>(ProfileData->getOperand(0)); - if (!ProfDataName || (!ProfDataName->getString().equals("branch_weights") && - !ProfDataName->getString().equals("VP"))) - return; - if (T == 0) { LLVM_DEBUG(dbgs() << "Attempting to update profile weights will result in " "div by 0. Ignoring. Likely the function " @@ -842,42 +841,7 @@ void CallInst::updateProfWeight(uint64_t S, uint64_t T) { "with non-zero prof info."); return; } - - MDBuilder MDB(getContext()); - SmallVector<Metadata *, 3> Vals; - Vals.push_back(ProfileData->getOperand(0)); - APInt APS(128, S), APT(128, T); - if (ProfDataName->getString().equals("branch_weights") && - ProfileData->getNumOperands() > 0) { - // Using APInt::div may be expensive, but most cases should fit 64 bits. - APInt Val(128, mdconst::dyn_extract<ConstantInt>(ProfileData->getOperand(1)) - ->getValue() - .getZExtValue()); - Val *= APS; - Vals.push_back(MDB.createConstant( - ConstantInt::get(Type::getInt32Ty(getContext()), - Val.udiv(APT).getLimitedValue(UINT32_MAX)))); - } else if (ProfDataName->getString().equals("VP")) - for (unsigned i = 1; i < ProfileData->getNumOperands(); i += 2) { - // The first value is the key of the value profile, which will not change. - Vals.push_back(ProfileData->getOperand(i)); - uint64_t Count = - mdconst::dyn_extract<ConstantInt>(ProfileData->getOperand(i + 1)) - ->getValue() - .getZExtValue(); - // Don't scale the magic number. - if (Count == NOMORE_ICP_MAGICNUM) { - Vals.push_back(ProfileData->getOperand(i + 1)); - continue; - } - // Using APInt::div may be expensive, but most cases should fit 64 bits. - APInt Val(128, Count); - Val *= APS; - Vals.push_back(MDB.createConstant( - ConstantInt::get(Type::getInt64Ty(getContext()), - Val.udiv(APT).getLimitedValue()))); - } - setMetadata(LLVMContext::MD_prof, MDNode::get(getContext(), Vals)); + scaleProfData(*this, S, T); } //===----------------------------------------------------------------------===// @@ -3364,18 +3328,6 @@ BinaryOperator *BinaryOperator::CreateNSWNeg(Value *Op, const Twine &Name, return BinaryOperator::CreateNSWSub(Zero, Op, Name, InsertAtEnd); } -BinaryOperator *BinaryOperator::CreateNUWNeg(Value *Op, const Twine &Name, - Instruction *InsertBefore) { - Value *Zero = ConstantInt::get(Op->getType(), 0); - return BinaryOperator::CreateNUWSub(Zero, Op, Name, InsertBefore); -} - -BinaryOperator *BinaryOperator::CreateNUWNeg(Value *Op, const Twine &Name, - BasicBlock *InsertAtEnd) { - Value *Zero = ConstantInt::get(Op->getType(), 0); - return BinaryOperator::CreateNUWSub(Zero, Op, Name, InsertAtEnd); -} - BinaryOperator *BinaryOperator::CreateNot(Value *Op, const Twine &Name, BasicBlock::iterator InsertBefore) { Constant *C = Constant::getAllOnesValue(Op->getType()); @@ -4615,6 +4567,16 @@ CmpInst::Create(OtherOps Op, Predicate predicate, Value *S1, Value *S2, S1, S2, Name); } +CmpInst *CmpInst::CreateWithCopiedFlags(OtherOps Op, Predicate Pred, Value *S1, + Value *S2, + const Instruction *FlagsSource, + const Twine &Name, + Instruction *InsertBefore) { + CmpInst *Inst = Create(Op, Pred, S1, S2, Name, InsertBefore); + Inst->copyIRFlags(FlagsSource); + return Inst; +} + void CmpInst::swapOperands() { if (ICmpInst *IC = dyn_cast<ICmpInst>(this)) IC->swapOperands(); diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp index a0bf9cae7926bbedf0521695a1bd6c8e764e2a16..72fedd8d673980a0d616ce5586965db86598de02 100644 --- a/llvm/lib/IR/LLVMContextImpl.cpp +++ b/llvm/lib/IR/LLVMContextImpl.cpp @@ -48,9 +48,9 @@ LLVMContextImpl::~LLVMContextImpl() { #ifndef NDEBUG // Check that any variable location records that fell off the end of a block // when it's terminator was removed were eventually replaced. This assertion - // firing indicates that DPValues went missing during the lifetime of the - // LLVMContext. - assert(TrailingDPValues.empty() && "DPValue records in blocks not cleaned"); + // firing indicates that DbgVariableRecords went missing during the lifetime + // of the LLVMContext. + assert(TrailingDbgRecords.empty() && "DbgRecords in blocks not cleaned"); #endif // NOTE: We need to delete the contents of OwnedModules, but Module's dtor diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index c841b28ca4380b56d6dbf4c78b0432192749276f..7c67e191348eaf799280828bd93b22550e3abd2c 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -58,7 +58,7 @@ class AttributeSetNode; class BasicBlock; class ConstantRangeAttributeImpl; struct DiagnosticHandler; -class DPMarker; +class DbgMarker; class ElementCount; class Function; class GlobalObject; @@ -441,7 +441,7 @@ template <> struct MDNodeKeyImpl<DIEnumerator> { bool IsUnsigned; MDNodeKeyImpl(APInt Value, bool IsUnsigned, MDString *Name) - : Value(Value), Name(Name), IsUnsigned(IsUnsigned) {} + : Value(std::move(Value)), Name(Name), IsUnsigned(IsUnsigned) {} MDNodeKeyImpl(int64_t Value, bool IsUnsigned, MDString *Name) : Value(APInt(64, Value, !IsUnsigned)), Name(Name), IsUnsigned(IsUnsigned) {} @@ -540,6 +540,7 @@ template <> struct MDNodeKeyImpl<DIDerivedType> { uint64_t OffsetInBits; uint32_t AlignInBits; std::optional<unsigned> DWARFAddressSpace; + std::optional<DIDerivedType::PtrAuthData> PtrAuthData; unsigned Flags; Metadata *ExtraData; Metadata *Annotations; @@ -547,18 +548,21 @@ template <> struct MDNodeKeyImpl<DIDerivedType> { MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, - std::optional<unsigned> DWARFAddressSpace, unsigned Flags, - Metadata *ExtraData, Metadata *Annotations) + std::optional<unsigned> DWARFAddressSpace, + std::optional<DIDerivedType::PtrAuthData> PtrAuthData, + unsigned Flags, Metadata *ExtraData, Metadata *Annotations) : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope), BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits), AlignInBits(AlignInBits), DWARFAddressSpace(DWARFAddressSpace), - Flags(Flags), ExtraData(ExtraData), Annotations(Annotations) {} + PtrAuthData(PtrAuthData), Flags(Flags), ExtraData(ExtraData), + Annotations(Annotations) {} MDNodeKeyImpl(const DIDerivedType *N) : Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()), Scope(N->getRawScope()), BaseType(N->getRawBaseType()), SizeInBits(N->getSizeInBits()), OffsetInBits(N->getOffsetInBits()), AlignInBits(N->getAlignInBits()), - DWARFAddressSpace(N->getDWARFAddressSpace()), Flags(N->getFlags()), + DWARFAddressSpace(N->getDWARFAddressSpace()), + PtrAuthData(N->getPtrAuthData()), Flags(N->getFlags()), ExtraData(N->getRawExtraData()), Annotations(N->getRawAnnotations()) {} bool isKeyOf(const DIDerivedType *RHS) const { @@ -569,7 +573,8 @@ template <> struct MDNodeKeyImpl<DIDerivedType> { AlignInBits == RHS->getAlignInBits() && OffsetInBits == RHS->getOffsetInBits() && DWARFAddressSpace == RHS->getDWARFAddressSpace() && - Flags == RHS->getFlags() && ExtraData == RHS->getRawExtraData() && + PtrAuthData == RHS->getPtrAuthData() && Flags == RHS->getFlags() && + ExtraData == RHS->getRawExtraData() && Annotations == RHS->getRawAnnotations(); } @@ -1670,33 +1675,33 @@ public: /// LLVMContext is used by compilation. void setOptPassGate(OptPassGate &); - /// Mapping of blocks to collections of "trailing" DPValues. As part of the - /// "RemoveDIs" project, debug-info variable location records are going to - /// cease being instructions... which raises the problem of where should they - /// be recorded when we remove the terminator of a blocks, such as: + /// Mapping of blocks to collections of "trailing" DbgVariableRecords. As part + /// of the "RemoveDIs" project, debug-info variable location records are going + /// to cease being instructions... which raises the problem of where should + /// they be recorded when we remove the terminator of a blocks, such as: /// /// %foo = add i32 0, 0 /// br label %bar /// /// If the branch is removed, a legitimate transient state while editing a /// block, any debug-records between those two instructions will not have a - /// location. Each block thus records any DPValue records that "trail" in - /// such a way. These are stored in LLVMContext because typically LLVM only - /// edits a small number of blocks at a time, so there's no need to bloat - /// BasicBlock with such a data structure. - SmallDenseMap<BasicBlock *, DPMarker *> TrailingDPValues; + /// location. Each block thus records any DbgVariableRecord records that + /// "trail" in such a way. These are stored in LLVMContext because typically + /// LLVM only edits a small number of blocks at a time, so there's no need to + /// bloat BasicBlock with such a data structure. + SmallDenseMap<BasicBlock *, DbgMarker *> TrailingDbgRecords; - // Set, get and delete operations for TrailingDPValues. - void setTrailingDbgRecords(BasicBlock *B, DPMarker *M) { - assert(!TrailingDPValues.count(B)); - TrailingDPValues[B] = M; + // Set, get and delete operations for TrailingDbgRecords. + void setTrailingDbgRecords(BasicBlock *B, DbgMarker *M) { + assert(!TrailingDbgRecords.count(B)); + TrailingDbgRecords[B] = M; } - DPMarker *getTrailingDbgRecords(BasicBlock *B) { - return TrailingDPValues.lookup(B); + DbgMarker *getTrailingDbgRecords(BasicBlock *B) { + return TrailingDbgRecords.lookup(B); } - void deleteTrailingDbgRecords(BasicBlock *B) { TrailingDPValues.erase(B); } + void deleteTrailingDbgRecords(BasicBlock *B) { TrailingDbgRecords.erase(B); } }; } // end namespace llvm diff --git a/llvm/lib/IR/LegacyPassManager.cpp b/llvm/lib/IR/LegacyPassManager.cpp index 8945c6dbc8d84882b340515c4aa1b8dc5dd3a77a..953f21ce7405900def38e7e5a8710f2dd6f94c73 100644 --- a/llvm/lib/IR/LegacyPassManager.cpp +++ b/llvm/lib/IR/LegacyPassManager.cpp @@ -528,8 +528,9 @@ bool PassManagerImpl::run(Module &M) { dumpArguments(); dumpPasses(); - // RemoveDIs: if a command line flag is given, convert to the DPValue - // representation of debug-info for the duration of these passes. + // RemoveDIs: if a command line flag is given, convert to the + // DbgVariableRecord representation of debug-info for the duration of these + // passes. bool shouldConvertDbgInfo = UseNewDbgInfoFormat && !M.IsNewDbgInfoFormat; if (shouldConvertDbgInfo) M.convertToNewDbgValues(); diff --git a/llvm/lib/IR/Mangler.cpp b/llvm/lib/IR/Mangler.cpp index 3acac2c3e3db162a37271198fb890d5d0c5dccbf..72e2bc1f24ac9713dfceb0692dda20d3b6370a7d 100644 --- a/llvm/lib/IR/Mangler.cpp +++ b/llvm/lib/IR/Mangler.cpp @@ -20,6 +20,7 @@ #include "llvm/IR/Module.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Triple.h" + using namespace llvm; namespace { @@ -192,7 +193,7 @@ void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName, // Check if the name needs quotes to be safe for the linker to interpret. static bool canBeUnquotedInDirective(char C) { - return isAlnum(C) || C == '_' || C == '@'; + return isAlnum(C) || C == '_' || C == '@' || C == '#'; } static bool canBeUnquotedInDirective(StringRef Name) { @@ -233,6 +234,16 @@ void llvm::emitLinkerFlagsForGlobalCOFF(raw_ostream &OS, const GlobalValue *GV, } else { Mangler.getNameWithPrefix(OS, GV, false); } + if (TT.isWindowsArm64EC()) { + // Use EXPORTAS for mangled ARM64EC symbols. + // FIXME: During LTO, we're invoked prior to the EC lowering pass, + // so symbols are not yet mangled. Emitting the unmangled name + // typically functions correctly; the linker can resolve the export + // with the demangled alias. + if (std::optional<std::string> demangledName = + getArm64ECDemangledFunctionName(GV->getName())) + OS << ",EXPORTAS," << *demangledName; + } if (NeedQuotes) OS << "\""; @@ -279,3 +290,42 @@ void llvm::emitLinkerFlagsForUsedCOFF(raw_ostream &OS, const GlobalValue *GV, OS << "\""; } +std::optional<std::string> llvm::getArm64ECMangledFunctionName(StringRef Name) { + bool IsCppFn = Name[0] == '?'; + if (IsCppFn && Name.find("$$h") != std::string::npos) + return std::nullopt; + if (!IsCppFn && Name[0] == '#') + return std::nullopt; + + StringRef Prefix = "$$h"; + size_t InsertIdx = 0; + if (IsCppFn) { + InsertIdx = Name.find("@@"); + size_t ThreeAtSignsIdx = Name.find("@@@"); + if (InsertIdx != std::string::npos && InsertIdx != ThreeAtSignsIdx) { + InsertIdx += 2; + } else { + InsertIdx = Name.find("@"); + if (InsertIdx != std::string::npos) + InsertIdx++; + } + } else { + Prefix = "#"; + } + + return std::optional<std::string>( + (Name.substr(0, InsertIdx) + Prefix + Name.substr(InsertIdx)).str()); +} + +std::optional<std::string> +llvm::getArm64ECDemangledFunctionName(StringRef Name) { + if (Name[0] == '#') + return std::optional<std::string>(Name.substr(1)); + if (Name[0] != '?') + return std::nullopt; + + std::pair<StringRef, StringRef> Pair = Name.split("$$h"); + if (Pair.second.empty()) + return std::nullopt; + return std::optional<std::string>((Pair.first + Pair.second).str()); +} diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp index 06db91fe4f8e74b00ac9631dd8113c4eaea6f6b5..4472bf128c323fb5c9cc3d3218c0ecd28aef024a 100644 --- a/llvm/lib/IR/Metadata.cpp +++ b/llvm/lib/IR/Metadata.cpp @@ -148,9 +148,11 @@ void MetadataAsValue::untrack() { MetadataTracking::untrack(MD); } -DPValue *DebugValueUser::getUser() { return static_cast<DPValue *>(this); } -const DPValue *DebugValueUser::getUser() const { - return static_cast<const DPValue *>(this); +DbgVariableRecord *DebugValueUser::getUser() { + return static_cast<DbgVariableRecord *>(this); +} +const DbgVariableRecord *DebugValueUser::getUser() const { + return static_cast<const DbgVariableRecord *>(this); } void DebugValueUser::handleChangedValue(void *Old, Metadata *New) { @@ -266,28 +268,29 @@ SmallVector<Metadata *> ReplaceableMetadataImpl::getAllArgListUsers() { return MDUsers; } -SmallVector<DPValue *> ReplaceableMetadataImpl::getAllDPValueUsers() { - SmallVector<std::pair<OwnerTy, uint64_t> *> DPVUsersWithID; +SmallVector<DbgVariableRecord *> +ReplaceableMetadataImpl::getAllDbgVariableRecordUsers() { + SmallVector<std::pair<OwnerTy, uint64_t> *> DVRUsersWithID; for (auto Pair : UseMap) { OwnerTy Owner = Pair.second.first; if (Owner.isNull()) continue; if (!Owner.is<DebugValueUser *>()) continue; - DPVUsersWithID.push_back(&UseMap[Pair.first]); + DVRUsersWithID.push_back(&UseMap[Pair.first]); } - // Order DPValue users in reverse-creation order. Normal dbg.value users - // of MetadataAsValues are ordered by their UseList, i.e. reverse order of - // when they were added: we need to replicate that here. The structure of + // Order DbgVariableRecord users in reverse-creation order. Normal dbg.value + // users of MetadataAsValues are ordered by their UseList, i.e. reverse order + // of when they were added: we need to replicate that here. The structure of // debug-info output depends on the ordering of intrinsics, thus we need // to keep them consistent for comparisons sake. - llvm::sort(DPVUsersWithID, [](auto UserA, auto UserB) { + llvm::sort(DVRUsersWithID, [](auto UserA, auto UserB) { return UserA->second > UserB->second; }); - SmallVector<DPValue *> DPVUsers; - for (auto UserWithID : DPVUsersWithID) - DPVUsers.push_back(UserWithID->first.get<DebugValueUser *>()->getUser()); - return DPVUsers; + SmallVector<DbgVariableRecord *> DVRUsers; + for (auto UserWithID : DVRUsersWithID) + DVRUsers.push_back(UserWithID->first.get<DebugValueUser *>()->getUser()); + return DVRUsers; } void ReplaceableMetadataImpl::addRef(void *Ref, OwnerTy Owner) { diff --git a/llvm/lib/IR/Operator.cpp b/llvm/lib/IR/Operator.cpp index caf8fe654a36dcf47557f9999e5d9b80652bc187..7b4449cd825f9b9a521a088a47350e454b88b9f5 100644 --- a/llvm/lib/IR/Operator.cpp +++ b/llvm/lib/IR/Operator.cpp @@ -27,6 +27,11 @@ bool Operator::hasPoisonGeneratingFlags() const { auto *OBO = cast<OverflowingBinaryOperator>(this); return OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap(); } + case Instruction::Trunc: { + if (auto *TI = dyn_cast<TruncInst>(this)) + return TI->hasNoUnsignedWrap() || TI->hasNoSignedWrap(); + return false; + } case Instruction::UDiv: case Instruction::SDiv: case Instruction::AShr: @@ -37,7 +42,7 @@ bool Operator::hasPoisonGeneratingFlags() const { case Instruction::GetElementPtr: { auto *GEP = cast<GEPOperator>(this); // Note: inrange exists on constexpr only - return GEP->isInBounds() || GEP->getInRangeIndex() != std::nullopt; + return GEP->isInBounds() || GEP->getInRange() != std::nullopt; } case Instruction::ZExt: if (auto *NNI = dyn_cast<PossiblyNonNegInst>(this)) @@ -69,6 +74,12 @@ Type *GEPOperator::getResultElementType() const { return cast<GetElementPtrConstantExpr>(this)->getResultElementType(); } +std::optional<ConstantRange> GEPOperator::getInRange() const { + if (auto *CE = dyn_cast<GetElementPtrConstantExpr>(this)) + return CE->getInRange(); + return std::nullopt; +} + Align GEPOperator::getMaxPreservedAlignment(const DataLayout &DL) const { /// compute the worse possible offset for every level of the GEP et accumulate /// the minimum alignment into Result. diff --git a/llvm/lib/IR/ProfDataUtils.cpp b/llvm/lib/IR/ProfDataUtils.cpp index b1a10d0ce5a522637c12f65395a1c737152fd0b2..dc86f4204b1a1d9f2296bd240386c6742bc4d396 100644 --- a/llvm/lib/IR/ProfDataUtils.cpp +++ b/llvm/lib/IR/ProfDataUtils.cpp @@ -190,4 +190,52 @@ void setBranchWeights(Instruction &I, ArrayRef<uint32_t> Weights) { I.setMetadata(LLVMContext::MD_prof, BranchWeights); } +void scaleProfData(Instruction &I, uint64_t S, uint64_t T) { + assert(T != 0 && "Caller should guarantee"); + auto *ProfileData = I.getMetadata(LLVMContext::MD_prof); + if (ProfileData == nullptr) + return; + + auto *ProfDataName = dyn_cast<MDString>(ProfileData->getOperand(0)); + if (!ProfDataName || (!ProfDataName->getString().equals("branch_weights") && + !ProfDataName->getString().equals("VP"))) + return; + + LLVMContext &C = I.getContext(); + + MDBuilder MDB(C); + SmallVector<Metadata *, 3> Vals; + Vals.push_back(ProfileData->getOperand(0)); + APInt APS(128, S), APT(128, T); + if (ProfDataName->getString().equals("branch_weights") && + ProfileData->getNumOperands() > 0) { + // Using APInt::div may be expensive, but most cases should fit 64 bits. + APInt Val(128, mdconst::dyn_extract<ConstantInt>(ProfileData->getOperand(1)) + ->getValue() + .getZExtValue()); + Val *= APS; + Vals.push_back(MDB.createConstant(ConstantInt::get( + Type::getInt32Ty(C), Val.udiv(APT).getLimitedValue(UINT32_MAX)))); + } else if (ProfDataName->getString().equals("VP")) + for (unsigned i = 1; i < ProfileData->getNumOperands(); i += 2) { + // The first value is the key of the value profile, which will not change. + Vals.push_back(ProfileData->getOperand(i)); + uint64_t Count = + mdconst::dyn_extract<ConstantInt>(ProfileData->getOperand(i + 1)) + ->getValue() + .getZExtValue(); + // Don't scale the magic number. + if (Count == NOMORE_ICP_MAGICNUM) { + Vals.push_back(ProfileData->getOperand(i + 1)); + continue; + } + // Using APInt::div may be expensive, but most cases should fit 64 bits. + APInt Val(128, Count); + Val *= APS; + Vals.push_back(MDB.createConstant(ConstantInt::get( + Type::getInt64Ty(C), Val.udiv(APT).getLimitedValue()))); + } + I.setMetadata(LLVMContext::MD_prof, MDNode::get(C, Vals)); +} + } // namespace llvm diff --git a/llvm/lib/IR/ReplaceConstant.cpp b/llvm/lib/IR/ReplaceConstant.cpp index 42dec7c72328ea822006fb3b49e77d4291c0bbaf..9b07bd8040492afe86cf53ec449c987d29a89e6e 100644 --- a/llvm/lib/IR/ReplaceConstant.cpp +++ b/llvm/lib/IR/ReplaceConstant.cpp @@ -22,11 +22,13 @@ static bool isExpandableUser(User *U) { return isa<ConstantExpr>(U) || isa<ConstantAggregate>(U); } -static SmallVector<Instruction *, 4> expandUser(Instruction *InsertPt, +static SmallVector<Instruction *, 4> expandUser(BasicBlock::iterator InsertPt, Constant *C) { SmallVector<Instruction *, 4> NewInsts; if (auto *CE = dyn_cast<ConstantExpr>(C)) { - NewInsts.push_back(CE->getAsInstruction(InsertPt)); + Instruction *ConstInst = CE->getAsInstruction(); + ConstInst->insertBefore(*InsertPt->getParent(), InsertPt); + NewInsts.push_back(ConstInst); } else if (isa<ConstantStruct>(C) || isa<ConstantArray>(C)) { Value *V = PoisonValue::get(C->getType()); for (auto [Idx, Op] : enumerate(C->operands())) { @@ -80,12 +82,11 @@ bool convertUsersOfConstantsToInstructions(ArrayRef<Constant *> Consts) { Instruction *I = InstructionWorklist.pop_back_val(); DebugLoc Loc = I->getDebugLoc(); for (Use &U : I->operands()) { - auto *BI = I; + BasicBlock::iterator BI = I->getIterator(); if (auto *Phi = dyn_cast<PHINode>(I)) { BasicBlock *BB = Phi->getIncomingBlock(U); - BasicBlock::iterator It = BB->getFirstInsertionPt(); - assert(It != BB->end() && "Unexpected empty basic block"); - BI = &*It; + BI = BB->getFirstInsertionPt(); + assert(BI != BB->end() && "Unexpected empty basic block"); } if (auto *C = dyn_cast<Constant>(U.get())) { diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp index c4e47975b1822114f97a2bc3b8c0af64d4edf034..8522747ccf1288846ecb2608e33054318e190853 100644 --- a/llvm/lib/IR/Value.cpp +++ b/llvm/lib/IR/Value.cpp @@ -574,16 +574,16 @@ void Value::replaceUsesWithIf(Value *New, /// with New. static void replaceDbgUsesOutsideBlock(Value *V, Value *New, BasicBlock *BB) { SmallVector<DbgVariableIntrinsic *> DbgUsers; - SmallVector<DPValue *> DPUsers; + SmallVector<DbgVariableRecord *> DPUsers; findDbgUsers(DbgUsers, V, &DPUsers); for (auto *DVI : DbgUsers) { if (DVI->getParent() != BB) DVI->replaceVariableLocationOp(V, New); } - for (auto *DPV : DPUsers) { - DPMarker *Marker = DPV->getMarker(); + for (auto *DVR : DPUsers) { + DbgMarker *Marker = DVR->getMarker(); if (Marker->getParent() != BB) - DPV->replaceVariableLocationOp(V, New); + DVR->replaceVariableLocationOp(V, New); } } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 2b9dc745d7bfc5ad21fe154aae18241bc4cd3aa5..33f358440a312d68b6eb2072ee409a6f9e740a2a 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -180,21 +180,21 @@ private: } } - void Write(DPValue::LocationType Type) { + void Write(DbgVariableRecord::LocationType Type) { switch (Type) { - case DPValue::LocationType::Value: + case DbgVariableRecord::LocationType::Value: *OS << "value"; break; - case DPValue::LocationType::Declare: + case DbgVariableRecord::LocationType::Declare: *OS << "declare"; break; - case DPValue::LocationType::Assign: + case DbgVariableRecord::LocationType::Assign: *OS << "assign"; break; - case DPValue::LocationType::End: + case DbgVariableRecord::LocationType::End: *OS << "end"; break; - case DPValue::LocationType::Any: + case DbgVariableRecord::LocationType::Any: *OS << "any"; break; }; @@ -544,8 +544,8 @@ private: void visitTemplateParams(const MDNode &N, const Metadata &RawParams); - void visit(DPLabel &DPL); - void visit(DPValue &DPV); + void visit(DbgLabelRecord &DLR); + void visit(DbgVariableRecord &DVR); // InstVisitor overrides... using InstVisitor<Verifier>::visit; void visitDbgRecords(Instruction &I); @@ -632,15 +632,15 @@ private: void verifySiblingFuncletUnwinds(); void verifyFragmentExpression(const DbgVariableIntrinsic &I); - void verifyFragmentExpression(const DPValue &I); + void verifyFragmentExpression(const DbgVariableRecord &I); template <typename ValueOrMetadata> void verifyFragmentExpression(const DIVariable &V, DIExpression::FragmentInfo Fragment, ValueOrMetadata *Desc); void verifyFnArgs(const DbgVariableIntrinsic &I); - void verifyFnArgs(const DPValue &DPV); + void verifyFnArgs(const DbgVariableRecord &DVR); void verifyNotEntryValue(const DbgVariableIntrinsic &I); - void verifyNotEntryValue(const DPValue &I); + void verifyNotEntryValue(const DbgVariableRecord &I); /// Module-level debug info verification... void verifyCompileUnits(); @@ -678,26 +678,26 @@ private: } while (false) void Verifier::visitDbgRecords(Instruction &I) { - if (!I.DbgMarker) + if (!I.DebugMarker) return; - CheckDI(I.DbgMarker->MarkedInstr == &I, "Instruction has invalid DbgMarker", - &I); + CheckDI(I.DebugMarker->MarkedInstr == &I, + "Instruction has invalid DebugMarker", &I); CheckDI(!isa<PHINode>(&I) || !I.hasDbgRecords(), "PHI Node must not have any attached DbgRecords", &I); for (DbgRecord &DR : I.getDbgRecordRange()) { - CheckDI(DR.getMarker() == I.DbgMarker, "DbgRecord had invalid DbgMarker", - &I, &DR); + CheckDI(DR.getMarker() == I.DebugMarker, + "DbgRecord had invalid DebugMarker", &I, &DR); if (auto *Loc = dyn_cast_or_null<DILocation>(DR.getDebugLoc().getAsMDNode())) visitMDNode(*Loc, AreDebugLocsAllowed::Yes); - if (auto *DPV = dyn_cast<DPValue>(&DR)) { - visit(*DPV); + if (auto *DVR = dyn_cast<DbgVariableRecord>(&DR)) { + visit(*DVR); // These have to appear after `visit` for consistency with existing // intrinsic behaviour. - verifyFragmentExpression(*DPV); - verifyNotEntryValue(*DPV); - } else if (auto *DPL = dyn_cast<DPLabel>(&DR)) { - visit(*DPL); + verifyFragmentExpression(*DVR); + verifyNotEntryValue(*DVR); + } else if (auto *DLR = dyn_cast<DbgLabelRecord>(&DR)) { + visit(*DLR); } } } @@ -1235,6 +1235,7 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) { N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || + N.getTag() == dwarf::DW_TAG_LLVM_ptrauth_type || N.getTag() == dwarf::DW_TAG_member || (N.getTag() == dwarf::DW_TAG_variable && N.isStaticMember()) || N.getTag() == dwarf::DW_TAG_inheritance || @@ -4807,11 +4808,12 @@ void Verifier::visitDIAssignIDMetadata(Instruction &I, MDNode *MD) { "dbg.assign not in same function as inst", DAI, &I); } } - for (DPValue *DPV : cast<DIAssignID>(MD)->getAllDPValueUsers()) { - CheckDI(DPV->isDbgAssign(), - "!DIAssignID should only be used by Assign DPVs.", MD, DPV); - CheckDI(DPV->getFunction() == I.getFunction(), - "DPVAssign not in same function as inst", DPV, &I); + for (DbgVariableRecord *DVR : + cast<DIAssignID>(MD)->getAllDbgVariableRecordUsers()) { + CheckDI(DVR->isDbgAssign(), + "!DIAssignID should only be used by Assign DVRs.", MD, DVR); + CheckDI(DVR->getFunction() == I.getFunction(), + "DVRAssign not in same function as inst", DVR, &I); } } @@ -5014,7 +5016,7 @@ void Verifier::visitInstruction(Instruction &I) { F->getIntrinsicID() == Intrinsic::coro_await_suspend_handle || F->getIntrinsicID() == Intrinsic::experimental_patchpoint_void || - F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64 || + F->getIntrinsicID() == Intrinsic::experimental_patchpoint || F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic::wasm_rethrow || IsAttachedCallOperand(F, CBI, i), @@ -5265,6 +5267,29 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { } break; } + case Intrinsic::ucmp: + case Intrinsic::scmp: { + Type *SrcTy = Call.getOperand(0)->getType(); + Type *DestTy = Call.getType(); + + Check(DestTy->getScalarSizeInBits() >= 2, + "result type must be at least 2 bits wide", Call); + + bool IsDestTypeVector = DestTy->isVectorTy(); + Check(SrcTy->isVectorTy() == IsDestTypeVector, + "ucmp/scmp argument and result types must both be either vector or " + "scalar types", + Call); + if (IsDestTypeVector) { + auto SrcVecLen = cast<VectorType>(SrcTy)->getElementCount(); + auto DestVecLen = cast<VectorType>(DestTy)->getElementCount(); + Check(SrcVecLen == DestVecLen, + "return type and arguments must have the same number of " + "elements", + Call); + } + break; + } case Intrinsic::coro_id: { auto *InfoArg = Call.getArgOperand(3)->stripPointerCasts(); if (isa<ConstantPointerNull>(InfoArg)) @@ -5636,6 +5661,13 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { } break; } + case Intrinsic::experimental_patchpoint: { + if (Call.getCallingConv() == CallingConv::AnyReg) { + Check(Call.getType()->isSingleValueType(), + "patchpoint: invalid return type used with anyregcc", Call); + } + break; + } case Intrinsic::eh_exceptioncode: case Intrinsic::eh_exceptionpointer: { Check(isa<CatchPadInst>(Call.getArgOperand(0)), @@ -6219,22 +6251,22 @@ static DISubprogram *getSubprogram(Metadata *LocalScope) { return nullptr; } -void Verifier::visit(DPLabel &DPL) { - CheckDI(isa<DILabel>(DPL.getRawLabel()), - "invalid #dbg_label intrinsic variable", &DPL, DPL.getRawLabel()); +void Verifier::visit(DbgLabelRecord &DLR) { + CheckDI(isa<DILabel>(DLR.getRawLabel()), + "invalid #dbg_label intrinsic variable", &DLR, DLR.getRawLabel()); // Ignore broken !dbg attachments; they're checked elsewhere. - if (MDNode *N = DPL.getDebugLoc().getAsMDNode()) + if (MDNode *N = DLR.getDebugLoc().getAsMDNode()) if (!isa<DILocation>(N)) return; - BasicBlock *BB = DPL.getParent(); + BasicBlock *BB = DLR.getParent(); Function *F = BB ? BB->getParent() : nullptr; // The scopes for variables and !dbg attachments must agree. - DILabel *Label = DPL.getLabel(); - DILocation *Loc = DPL.getDebugLoc(); - CheckDI(Loc, "#dbg_label record requires a !dbg attachment", &DPL, BB, F); + DILabel *Label = DLR.getLabel(); + DILocation *Loc = DLR.getDebugLoc(); + CheckDI(Loc, "#dbg_label record requires a !dbg attachment", &DLR, BB, F); DISubprogram *LabelSP = getSubprogram(Label->getRawScope()); DISubprogram *LocSP = getSubprogram(Loc->getRawScope()); @@ -6243,75 +6275,76 @@ void Verifier::visit(DPLabel &DPL) { CheckDI(LabelSP == LocSP, "mismatched subprogram between #dbg_label label and !dbg attachment", - &DPL, BB, F, Label, Label->getScope()->getSubprogram(), Loc, + &DLR, BB, F, Label, Label->getScope()->getSubprogram(), Loc, Loc->getScope()->getSubprogram()); } -void Verifier::visit(DPValue &DPV) { - BasicBlock *BB = DPV.getParent(); +void Verifier::visit(DbgVariableRecord &DVR) { + BasicBlock *BB = DVR.getParent(); Function *F = BB->getParent(); - CheckDI(DPV.getType() == DPValue::LocationType::Value || - DPV.getType() == DPValue::LocationType::Declare || - DPV.getType() == DPValue::LocationType::Assign, - "invalid #dbg record type", &DPV, DPV.getType()); + CheckDI(DVR.getType() == DbgVariableRecord::LocationType::Value || + DVR.getType() == DbgVariableRecord::LocationType::Declare || + DVR.getType() == DbgVariableRecord::LocationType::Assign, + "invalid #dbg record type", &DVR, DVR.getType()); - // The location for a DPValue must be either a ValueAsMetadata, DIArgList, or - // an empty MDNode (which is a legacy representation for an "undef" location). - auto *MD = DPV.getRawLocation(); + // The location for a DbgVariableRecord must be either a ValueAsMetadata, + // DIArgList, or an empty MDNode (which is a legacy representation for an + // "undef" location). + auto *MD = DVR.getRawLocation(); CheckDI(MD && (isa<ValueAsMetadata>(MD) || isa<DIArgList>(MD) || (isa<MDNode>(MD) && !cast<MDNode>(MD)->getNumOperands())), - "invalid #dbg record address/value", &DPV, MD); + "invalid #dbg record address/value", &DVR, MD); if (auto *VAM = dyn_cast<ValueAsMetadata>(MD)) visitValueAsMetadata(*VAM, F); else if (auto *AL = dyn_cast<DIArgList>(MD)) visitDIArgList(*AL, F); - CheckDI(isa_and_nonnull<DILocalVariable>(DPV.getRawVariable()), - "invalid #dbg record variable", &DPV, DPV.getRawVariable()); - visitMDNode(*DPV.getRawVariable(), AreDebugLocsAllowed::No); + CheckDI(isa_and_nonnull<DILocalVariable>(DVR.getRawVariable()), + "invalid #dbg record variable", &DVR, DVR.getRawVariable()); + visitMDNode(*DVR.getRawVariable(), AreDebugLocsAllowed::No); - CheckDI(isa_and_nonnull<DIExpression>(DPV.getRawExpression()), - "invalid #dbg record expression", &DPV, DPV.getRawExpression()); - visitMDNode(*DPV.getExpression(), AreDebugLocsAllowed::No); + CheckDI(isa_and_nonnull<DIExpression>(DVR.getRawExpression()), + "invalid #dbg record expression", &DVR, DVR.getRawExpression()); + visitMDNode(*DVR.getExpression(), AreDebugLocsAllowed::No); - if (DPV.isDbgAssign()) { - CheckDI(isa_and_nonnull<DIAssignID>(DPV.getRawAssignID()), - "invalid #dbg_assign DIAssignID", &DPV, DPV.getRawAssignID()); - visitMDNode(*cast<DIAssignID>(DPV.getRawAssignID()), + if (DVR.isDbgAssign()) { + CheckDI(isa_and_nonnull<DIAssignID>(DVR.getRawAssignID()), + "invalid #dbg_assign DIAssignID", &DVR, DVR.getRawAssignID()); + visitMDNode(*cast<DIAssignID>(DVR.getRawAssignID()), AreDebugLocsAllowed::No); - const auto *RawAddr = DPV.getRawAddress(); - // Similarly to the location above, the address for an assign DPValue must - // be a ValueAsMetadata or an empty MDNode, which represents an undef - // address. + const auto *RawAddr = DVR.getRawAddress(); + // Similarly to the location above, the address for an assign + // DbgVariableRecord must be a ValueAsMetadata or an empty MDNode, which + // represents an undef address. CheckDI( isa<ValueAsMetadata>(RawAddr) || (isa<MDNode>(RawAddr) && !cast<MDNode>(RawAddr)->getNumOperands()), - "invalid #dbg_assign address", &DPV, DPV.getRawAddress()); + "invalid #dbg_assign address", &DVR, DVR.getRawAddress()); if (auto *VAM = dyn_cast<ValueAsMetadata>(RawAddr)) visitValueAsMetadata(*VAM, F); - CheckDI(isa_and_nonnull<DIExpression>(DPV.getRawAddressExpression()), - "invalid #dbg_assign address expression", &DPV, - DPV.getRawAddressExpression()); - visitMDNode(*DPV.getAddressExpression(), AreDebugLocsAllowed::No); + CheckDI(isa_and_nonnull<DIExpression>(DVR.getRawAddressExpression()), + "invalid #dbg_assign address expression", &DVR, + DVR.getRawAddressExpression()); + visitMDNode(*DVR.getAddressExpression(), AreDebugLocsAllowed::No); - // All of the linked instructions should be in the same function as DPV. - for (Instruction *I : at::getAssignmentInsts(&DPV)) - CheckDI(DPV.getFunction() == I->getFunction(), - "inst not in same function as #dbg_assign", I, &DPV); + // All of the linked instructions should be in the same function as DVR. + for (Instruction *I : at::getAssignmentInsts(&DVR)) + CheckDI(DVR.getFunction() == I->getFunction(), + "inst not in same function as #dbg_assign", I, &DVR); } // This check is redundant with one in visitLocalVariable(). - DILocalVariable *Var = DPV.getVariable(); + DILocalVariable *Var = DVR.getVariable(); CheckDI(isType(Var->getRawType()), "invalid type ref", Var, Var->getRawType()); - auto *DLNode = DPV.getDebugLoc().getAsMDNode(); + auto *DLNode = DVR.getDebugLoc().getAsMDNode(); CheckDI(isa_and_nonnull<DILocation>(DLNode), "invalid #dbg record DILocation", - &DPV, DLNode); - DILocation *Loc = DPV.getDebugLoc(); + &DVR, DLNode); + DILocation *Loc = DVR.getDebugLoc(); // The scopes for variables and !dbg attachments must agree. DISubprogram *VarSP = getSubprogram(Var->getRawScope()); @@ -6321,10 +6354,10 @@ void Verifier::visit(DPValue &DPV) { CheckDI(VarSP == LocSP, "mismatched subprogram between #dbg record variable and DILocation", - &DPV, BB, F, Var, Var->getScope()->getSubprogram(), Loc, + &DVR, BB, F, Var, Var->getScope()->getSubprogram(), Loc, Loc->getScope()->getSubprogram()); - verifyFnArgs(DPV); + verifyFnArgs(DVR); } void Verifier::visitVPIntrinsic(VPIntrinsic &VPI) { @@ -6685,9 +6718,9 @@ void Verifier::verifyFragmentExpression(const DbgVariableIntrinsic &I) { verifyFragmentExpression(*V, *Fragment, &I); } -void Verifier::verifyFragmentExpression(const DPValue &DPV) { - DILocalVariable *V = dyn_cast_or_null<DILocalVariable>(DPV.getRawVariable()); - DIExpression *E = dyn_cast_or_null<DIExpression>(DPV.getRawExpression()); +void Verifier::verifyFragmentExpression(const DbgVariableRecord &DVR) { + DILocalVariable *V = dyn_cast_or_null<DILocalVariable>(DVR.getRawVariable()); + DIExpression *E = dyn_cast_or_null<DIExpression>(DVR.getRawExpression()); // We don't know whether this intrinsic verified correctly. if (!V || !E || !E->isValid()) @@ -6707,7 +6740,7 @@ void Verifier::verifyFragmentExpression(const DPValue &DPV) { if (V->isArtificial()) return; - verifyFragmentExpression(*V, *Fragment, &DPV); + verifyFragmentExpression(*V, *Fragment, &DVR); } template <typename ValueOrMetadata> @@ -6755,7 +6788,7 @@ void Verifier::verifyFnArgs(const DbgVariableIntrinsic &I) { CheckDI(!Prev || (Prev == Var), "conflicting debug info for argument", &I, Prev, Var); } -void Verifier::verifyFnArgs(const DPValue &DPV) { +void Verifier::verifyFnArgs(const DbgVariableRecord &DVR) { // This function does not take the scope of noninlined function arguments into // account. Don't run it if current function is nodebug, because it may // contain inlined debug intrinsics. @@ -6763,10 +6796,10 @@ void Verifier::verifyFnArgs(const DPValue &DPV) { return; // For performance reasons only check non-inlined ones. - if (DPV.getDebugLoc()->getInlinedAt()) + if (DVR.getDebugLoc()->getInlinedAt()) return; - DILocalVariable *Var = DPV.getVariable(); + DILocalVariable *Var = DVR.getVariable(); CheckDI(Var, "#dbg record without variable"); unsigned ArgNo = Var->getArg(); @@ -6780,7 +6813,7 @@ void Verifier::verifyFnArgs(const DPValue &DPV) { auto *Prev = DebugFnArgs[ArgNo - 1]; DebugFnArgs[ArgNo - 1] = Var; - CheckDI(!Prev || (Prev == Var), "conflicting debug info for argument", &DPV, + CheckDI(!Prev || (Prev == Var), "conflicting debug info for argument", &DVR, Prev, Var); } @@ -6807,15 +6840,15 @@ void Verifier::verifyNotEntryValue(const DbgVariableIntrinsic &I) { "swiftasync Argument", &I); } -void Verifier::verifyNotEntryValue(const DPValue &DPV) { - DIExpression *E = dyn_cast_or_null<DIExpression>(DPV.getRawExpression()); +void Verifier::verifyNotEntryValue(const DbgVariableRecord &DVR) { + DIExpression *E = dyn_cast_or_null<DIExpression>(DVR.getRawExpression()); // We don't know whether this intrinsic verified correctly. if (!E || !E->isValid()) return; - if (isa<ValueAsMetadata>(DPV.getRawLocation())) { - Value *VarValue = DPV.getVariableLocationOp(0); + if (isa<ValueAsMetadata>(DVR.getRawLocation())) { + Value *VarValue = DVR.getVariableLocationOp(0); if (isa<UndefValue>(VarValue) || isa<PoisonValue>(VarValue)) return; // We allow EntryValues for swift async arguments, as they have an @@ -6828,7 +6861,7 @@ void Verifier::verifyNotEntryValue(const DPValue &DPV) { CheckDI(!E->isEntryValue(), "Entry values are only allowed in MIR unless they target a " "swiftasync Argument", - &DPV); + &DVR); } void Verifier::verifyCompileUnits() { diff --git a/llvm/lib/InterfaceStub/ELFObjHandler.cpp b/llvm/lib/InterfaceStub/ELFObjHandler.cpp index c1256563d0d62729231f7d7ef4a1e7d50155367c..9c81a8832c0f2afc9b27063463b22e9d39d9f1a7 100644 --- a/llvm/lib/InterfaceStub/ELFObjHandler.cpp +++ b/llvm/lib/InterfaceStub/ELFObjHandler.cpp @@ -57,7 +57,7 @@ static void initELFHeader(typename ELFT::Ehdr &ElfHeader, uint16_t Machine) { ElfHeader.e_ident[EI_MAG2] = ElfMagic[EI_MAG2]; ElfHeader.e_ident[EI_MAG3] = ElfMagic[EI_MAG3]; ElfHeader.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32; - bool IsLittleEndian = ELFT::TargetEndianness == llvm::endianness::little; + bool IsLittleEndian = ELFT::Endianness == llvm::endianness::little; ElfHeader.e_ident[EI_DATA] = IsLittleEndian ? ELFDATA2LSB : ELFDATA2MSB; ElfHeader.e_ident[EI_VERSION] = EV_CURRENT; ElfHeader.e_ident[EI_OSABI] = ELFOSABI_NONE; diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index b58418c64a116b948791f136329af3889f744172..53060df7f503e0ba5005d427ccbcda36385a39c9 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -579,7 +579,9 @@ LTO::RegularLTOState::RegularLTOState(unsigned ParallelCodeGenParallelismLevel, const Config &Conf) : ParallelCodeGenParallelismLevel(ParallelCodeGenParallelismLevel), Ctx(Conf), CombinedModule(std::make_unique<Module>("ld-temp.o", Ctx)), - Mover(std::make_unique<IRMover>(*CombinedModule)) {} + Mover(std::make_unique<IRMover>(*CombinedModule)) { + CombinedModule->IsNewDbgInfoFormat = UseNewDbgInfoFormat; +} LTO::ThinLTOState::ThinLTOState(ThinBackend Backend) : Backend(Backend), CombinedIndex(/*HaveGVs*/ false) { diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp index a9afb6f7348a8f1cf6e3cf2f313d0684311e80eb..a7e6db82e5c23c717c9f43b767ab7d97c2d30cb8 100644 --- a/llvm/lib/Linker/IRMover.cpp +++ b/llvm/lib/Linker/IRMover.cpp @@ -8,6 +8,7 @@ #include "llvm/Linker/IRMover.h" #include "LinkDiagnosticInfo.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" @@ -1546,7 +1547,23 @@ Error IRLinker::run() { if (Error Err = SrcM->getMaterializer()->materializeMetadata()) return Err; - DstM.IsNewDbgInfoFormat = SrcM->IsNewDbgInfoFormat; + // Convert source module to match dest for the duration of the link. + bool SrcModuleNewDbgFormat = SrcM->IsNewDbgInfoFormat; + if (DstM.IsNewDbgInfoFormat != SrcM->IsNewDbgInfoFormat) { + if (DstM.IsNewDbgInfoFormat) + SrcM->convertToNewDbgValues(); + else + SrcM->convertFromNewDbgValues(); + } + // Undo debug mode conversion afterwards. + auto Cleanup = make_scope_exit([&]() { + if (SrcModuleNewDbgFormat != SrcM->IsNewDbgInfoFormat) { + if (SrcModuleNewDbgFormat) + SrcM->convertToNewDbgValues(); + else + SrcM->convertFromNewDbgValues(); + } + }); // Inherit the target data from the source module if the destination module // doesn't have one already. @@ -1606,11 +1623,6 @@ Error IRLinker::run() { // Loop over all of the linked values to compute type mappings. computeTypeMapping(); - // Convert module level attributes to function level attributes because - // after merging modules the attributes might change and would have different - // effect on the functions as the original module would have. - CopyModuleAttrToFunctions(*SrcM); - std::reverse(Worklist.begin(), Worklist.end()); while (!Worklist.empty()) { GlobalValue *GV = Worklist.back(); @@ -1780,8 +1792,6 @@ IRMover::IRMover(Module &M) : Composite(M) { Error IRMover::move(std::unique_ptr<Module> Src, ArrayRef<GlobalValue *> ValuesToLink, LazyCallback AddLazyFor, bool IsPerformingImport) { - if (getModule().IsNewDbgInfoFormat) - Src->convertToNewDbgValues(); IRLinker TheIRLinker(Composite, SharedMDs, IdentifiedStructTypes, std::move(Src), ValuesToLink, std::move(AddLazyFor), IsPerformingImport); diff --git a/llvm/lib/MC/ConstantPools.cpp b/llvm/lib/MC/ConstantPools.cpp index f895cc6413d74f77d29084d3c41987bf2719b2cf..824d2463f30fc5e36912ea7ee0ef6c5cb1636aac 100644 --- a/llvm/lib/MC/ConstantPools.cpp +++ b/llvm/lib/MC/ConstantPools.cpp @@ -43,14 +43,15 @@ const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context, // Check if there is existing entry for the same constant. If so, reuse it. if (C) { - auto CItr = CachedConstantEntries.find(C->getValue()); + auto CItr = CachedConstantEntries.find(std::make_pair(C->getValue(), Size)); if (CItr != CachedConstantEntries.end()) return CItr->second; } // Check if there is existing entry for the same symbol. If so, reuse it. if (S) { - auto SItr = CachedSymbolEntries.find(&(S->getSymbol())); + auto SItr = + CachedSymbolEntries.find(std::make_pair(&(S->getSymbol()), Size)); if (SItr != CachedSymbolEntries.end()) return SItr->second; } @@ -60,9 +61,9 @@ const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context, Entries.push_back(ConstantPoolEntry(CPEntryLabel, Value, Size, Loc)); const auto SymRef = MCSymbolRefExpr::create(CPEntryLabel, Context); if (C) - CachedConstantEntries[C->getValue()] = SymRef; + CachedConstantEntries[std::make_pair(C->getValue(), Size)] = SymRef; if (S) - CachedSymbolEntries[&(S->getSymbol())] = SymRef; + CachedSymbolEntries[std::make_pair(&(S->getSymbol()), Size)] = SymRef; return SymRef; } diff --git a/llvm/lib/MC/DXContainerPSVInfo.cpp b/llvm/lib/MC/DXContainerPSVInfo.cpp index 48182fcd31df0677ed5be253a859cd2b914ecb41..aeff69380139770d47834aacc806d18a50724aee 100644 --- a/llvm/lib/MC/DXContainerPSVInfo.cpp +++ b/llvm/lib/MC/DXContainerPSVInfo.cpp @@ -81,13 +81,18 @@ void PSVRuntimeInfo::write(raw_ostream &OS, uint32_t Version) const { BindingSize = sizeof(dxbc::PSV::v0::ResourceBindInfo); break; case 2: - default: InfoSize = sizeof(dxbc::PSV::v2::RuntimeInfo); BindingSize = sizeof(dxbc::PSV::v2::ResourceBindInfo); + break; + case 3: + default: + InfoSize = sizeof(dxbc::PSV::v3::RuntimeInfo); + BindingSize = sizeof(dxbc::PSV::v2::ResourceBindInfo); } - // Write the size of the info. + // Write the size of the info. support::endian::write(OS, InfoSize, llvm::endianness::little); + // Write the info itself. OS.write(reinterpret_cast<const char *>(&BaseData), InfoSize); @@ -104,32 +109,12 @@ void PSVRuntimeInfo::write(raw_ostream &OS, uint32_t Version) const { if (Version == 0) return; - StringTableBuilder StrTabBuilder((StringTableBuilder::DXContainer)); - SmallVector<uint32_t, 64> IndexBuffer; - SmallVector<v0::SignatureElement, 32> SignatureElements; - SmallVector<StringRef, 32> SemanticNames; - - ProcessElementList(StrTabBuilder, IndexBuffer, SignatureElements, - SemanticNames, InputElements); - ProcessElementList(StrTabBuilder, IndexBuffer, SignatureElements, - SemanticNames, OutputElements); - ProcessElementList(StrTabBuilder, IndexBuffer, SignatureElements, - SemanticNames, PatchOrPrimElements); - - StrTabBuilder.finalize(); - for (auto ElAndName : zip(SignatureElements, SemanticNames)) { - v0::SignatureElement &El = std::get<0>(ElAndName); - StringRef Name = std::get<1>(ElAndName); - El.NameOffset = static_cast<uint32_t>(StrTabBuilder.getOffset(Name)); - if (sys::IsBigEndianHost) - El.swapBytes(); - } - - support::endian::write(OS, static_cast<uint32_t>(StrTabBuilder.getSize()), + support::endian::write(OS, + static_cast<uint32_t>(DXConStrTabBuilder.getSize()), llvm::endianness::little); // Write the string table. - StrTabBuilder.write(OS); + DXConStrTabBuilder.write(OS); // Write the index table size, then table. support::endian::write(OS, static_cast<uint32_t>(IndexBuffer.size()), @@ -162,6 +147,46 @@ void PSVRuntimeInfo::write(raw_ostream &OS, uint32_t Version) const { llvm::endianness::little); } +void PSVRuntimeInfo::finalize(Triple::EnvironmentType Stage) { + IsFinalized = true; + BaseData.SigInputElements = static_cast<uint32_t>(InputElements.size()); + BaseData.SigOutputElements = static_cast<uint32_t>(OutputElements.size()); + BaseData.SigPatchOrPrimElements = + static_cast<uint32_t>(PatchOrPrimElements.size()); + + SmallVector<StringRef, 32> SemanticNames; + + // Build a string table and set associated offsets to be written when + // write() is called + ProcessElementList(DXConStrTabBuilder, IndexBuffer, SignatureElements, + SemanticNames, InputElements); + ProcessElementList(DXConStrTabBuilder, IndexBuffer, SignatureElements, + SemanticNames, OutputElements); + ProcessElementList(DXConStrTabBuilder, IndexBuffer, SignatureElements, + SemanticNames, PatchOrPrimElements); + + DXConStrTabBuilder.add(EntryName); + + DXConStrTabBuilder.finalize(); + for (auto ElAndName : zip(SignatureElements, SemanticNames)) { + llvm::dxbc::PSV::v0::SignatureElement &El = std::get<0>(ElAndName); + StringRef Name = std::get<1>(ElAndName); + El.NameOffset = static_cast<uint32_t>(DXConStrTabBuilder.getOffset(Name)); + if (sys::IsBigEndianHost) + El.swapBytes(); + } + + BaseData.EntryNameOffset = + static_cast<uint32_t>(DXConStrTabBuilder.getOffset(EntryName)); + + if (!sys::IsBigEndianHost) + return; + BaseData.swapBytes(); + BaseData.swapBytes(Stage); + for (auto &Res : Resources) + Res.swapBytes(); +} + void Signature::write(raw_ostream &OS) { SmallVector<dxbc::ProgramSignatureElement> SigParams; SigParams.reserve(Params.size()); diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index 3c4d3ab9a508b330628cd8a530c0c5f69a7023a9..005521bad6e014e0b68c732985be5fa4538bb547 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -141,7 +141,6 @@ struct ELFWriter { // TargetObjectWriter wrappers. bool is64Bit() const; - bool usesRela(const MCSectionELF &Sec) const; uint64_t align(Align Alignment); @@ -260,6 +259,7 @@ public: void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) override; + bool usesRela(const MCSectionELF &Sec) const; void executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) override; @@ -394,11 +394,6 @@ bool ELFWriter::is64Bit() const { return OWriter.TargetObjectWriter->is64Bit(); } -bool ELFWriter::usesRela(const MCSectionELF &Sec) const { - return OWriter.hasRelocationAddend() && - Sec.getType() != ELF::SHT_LLVM_CALL_GRAPH_PROFILE; -} - // Emit the ELF header. void ELFWriter::writeHeader(const MCAssembler &Asm) { // ELF Header @@ -825,24 +820,22 @@ MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx, if (OWriter.Relocations[&Sec].empty()) return nullptr; - const StringRef SectionName = Sec.getName(); - bool Rela = usesRela(Sec); - std::string RelaSectionName = Rela ? ".rela" : ".rel"; - RelaSectionName += SectionName; + unsigned Flags = ELF::SHF_INFO_LINK; + if (Sec.getFlags() & ELF::SHF_GROUP) + Flags = ELF::SHF_GROUP; + const StringRef SectionName = Sec.getName(); + const bool Rela = OWriter.usesRela(Sec); unsigned EntrySize; if (Rela) EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rela) : sizeof(ELF::Elf32_Rela); else EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel); - unsigned Flags = ELF::SHF_INFO_LINK; - if (Sec.getFlags() & ELF::SHF_GROUP) - Flags = ELF::SHF_GROUP; - - MCSectionELF *RelaSection = Ctx.createELFRelSection( - RelaSectionName, Rela ? ELF::SHT_RELA : ELF::SHT_REL, Flags, EntrySize, - Sec.getGroup(), &Sec); + MCSectionELF *RelaSection = + Ctx.createELFRelSection(((Rela ? ".rela" : ".rel") + SectionName), + Rela ? ELF::SHT_RELA : ELF::SHT_REL, Flags, + EntrySize, Sec.getGroup(), &Sec); RelaSection->setAlignment(is64Bit() ? Align(8) : Align(4)); return RelaSection; } @@ -938,52 +931,33 @@ void ELFWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, void ELFWriter::writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec) { std::vector<ELFRelocationEntry> &Relocs = OWriter.Relocations[&Sec]; - - // We record relocations by pushing to the end of a vector. Reverse the vector - // to get the relocations in the order they were created. - // In most cases that is not important, but it can be for special sections - // (.eh_frame) or specific relocations (TLS optimizations on SystemZ). - std::reverse(Relocs.begin(), Relocs.end()); + const bool Rela = OWriter.usesRela(Sec); // Sort the relocation entries. MIPS needs this. OWriter.TargetObjectWriter->sortRelocs(Asm, Relocs); - const bool Rela = usesRela(Sec); - for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { - const ELFRelocationEntry &Entry = Relocs[e - i - 1]; - unsigned Index = Entry.Symbol ? Entry.Symbol->getIndex() : 0; - - if (is64Bit()) { - write(Entry.Offset); - if (OWriter.TargetObjectWriter->getEMachine() == ELF::EM_MIPS) { - write(uint32_t(Index)); - + if (OWriter.TargetObjectWriter->getEMachine() == ELF::EM_MIPS) { + for (const ELFRelocationEntry &Entry : Relocs) { + uint32_t Symidx = Entry.Symbol ? Entry.Symbol->getIndex() : 0; + if (is64Bit()) { + write(Entry.Offset); + write(uint32_t(Symidx)); write(OWriter.TargetObjectWriter->getRSsym(Entry.Type)); write(OWriter.TargetObjectWriter->getRType3(Entry.Type)); write(OWriter.TargetObjectWriter->getRType2(Entry.Type)); write(OWriter.TargetObjectWriter->getRType(Entry.Type)); + if (Rela) + write(Entry.Addend); } else { - struct ELF::Elf64_Rela ERE64; - ERE64.setSymbolAndType(Index, Entry.Type); - write(ERE64.r_info); - } - if (Rela) - write(Entry.Addend); - } else { - write(uint32_t(Entry.Offset)); - - struct ELF::Elf32_Rela ERE32; - ERE32.setSymbolAndType(Index, Entry.Type); - write(ERE32.r_info); - - if (Rela) - write(uint32_t(Entry.Addend)); - - if (OWriter.TargetObjectWriter->getEMachine() == ELF::EM_MIPS) { + write(uint32_t(Entry.Offset)); + ELF::Elf32_Rela ERE32; + ERE32.setSymbolAndType(Symidx, Entry.Type); + write(ERE32.r_info); + if (Rela) + write(uint32_t(Entry.Addend)); if (uint32_t RType = OWriter.TargetObjectWriter->getRType2(Entry.Type)) { write(uint32_t(Entry.Offset)); - ERE32.setSymbolAndType(0, RType); write(ERE32.r_info); write(uint32_t(0)); @@ -991,13 +965,31 @@ void ELFWriter::writeRelocations(const MCAssembler &Asm, if (uint32_t RType = OWriter.TargetObjectWriter->getRType3(Entry.Type)) { write(uint32_t(Entry.Offset)); - ERE32.setSymbolAndType(0, RType); write(ERE32.r_info); write(uint32_t(0)); } } } + return; + } + for (const ELFRelocationEntry &Entry : Relocs) { + uint32_t Symidx = Entry.Symbol ? Entry.Symbol->getIndex() : 0; + if (is64Bit()) { + write(Entry.Offset); + ELF::Elf64_Rela ERE; + ERE.setSymbolAndType(Symidx, Entry.Type); + write(ERE.r_info); + if (Rela) + write(Entry.Addend); + } else { + write(uint32_t(Entry.Offset)); + ELF::Elf32_Rela ERE; + ERE.setSymbolAndType(Symidx, Entry.Type); + write(ERE.r_info); + if (Rela) + write(uint32_t(Entry.Addend)); + } } } @@ -1500,7 +1492,7 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm, FixedValue = !RelocateWithSymbol && SymA && !SymA->isUndefined() ? C + Layout.getSymbolOffset(*SymA) : C; - if (hasRelocationAddend()) { + if (usesRela(FixupSection)) { Addend = FixedValue; FixedValue = 0; } @@ -1529,6 +1521,11 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm, Relocations[&FixupSection].push_back(Rec); } +bool ELFObjectWriter::usesRela(const MCSectionELF &Sec) const { + return hasRelocationAddend() && + Sec.getType() != ELF::SHT_LLVM_CALL_GRAPH_PROFILE; +} + bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl( const MCAssembler &Asm, const MCSymbol &SA, const MCFragment &FB, bool InSet, bool IsPCRel) const { diff --git a/llvm/lib/MC/MCAsmInfoGOFF.cpp b/llvm/lib/MC/MCAsmInfoGOFF.cpp index 81704ffe4b24608c378d1b0f8ed7ac8922c99998..3c81a466e82e7983e9cf34b6a8db1ff0037d54e6 100644 --- a/llvm/lib/MC/MCAsmInfoGOFF.cpp +++ b/llvm/lib/MC/MCAsmInfoGOFF.cpp @@ -21,7 +21,7 @@ void MCAsmInfoGOFF::anchor() {} MCAsmInfoGOFF::MCAsmInfoGOFF() { Data64bitsDirective = "\t.quad\t"; HasDotTypeDotSizeDirective = false; - PrivateGlobalPrefix = "@@"; - PrivateLabelPrefix = "@"; + PrivateGlobalPrefix = "L#"; + PrivateLabelPrefix = "L#"; ZeroDirective = "\t.space\t"; } diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp index ba5cefaf18c1fd8ca13cb91b21b9b6606d3a32dc..3aee96fdf57fc262ce8d950e783fb578fb268802 100644 --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -147,6 +147,7 @@ void MCContext::reset() { XCOFFAllocator.DestroyAll(); MCInstAllocator.DestroyAll(); SPIRVAllocator.DestroyAll(); + WasmSignatureAllocator.DestroyAll(); MCSubtargetAllocator.DestroyAll(); InlineAsmUsedLabelNames.clear(); @@ -375,6 +376,10 @@ void MCContext::registerInlineAsmLabel(MCSymbol *Sym) { InlineAsmUsedLabelNames[Sym->getName()] = Sym; } +wasm::WasmSignature *MCContext::createWasmSignature() { + return new (WasmSignatureAllocator.Allocate()) wasm::WasmSignature; +} + MCSymbolXCOFF * MCContext::createXCOFFSymbolImpl(const StringMapEntry<bool> *Name, bool IsTemporary) { diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp index d0face9140de6686503d18808a39612c5acaf537..2ee0c3eb27b92e2481fbab1dae07a698b4ee80e7 100644 --- a/llvm/lib/MC/MCDwarf.cpp +++ b/llvm/lib/MC/MCDwarf.cpp @@ -360,7 +360,12 @@ void MCDwarfLineStr::emitRef(MCStreamer *MCOS, StringRef Path) { size_t Offset = addString(Path); if (UseRelocs) { MCContext &Ctx = MCOS->getContext(); - MCOS->emitValue(makeStartPlusIntExpr(Ctx, *LineStrLabel, Offset), RefSize); + if (Ctx.getAsmInfo()->needsDwarfSectionOffsetDirective()) { + MCOS->emitCOFFSecRel32(LineStrLabel, Offset); + } else { + MCOS->emitValue(makeStartPlusIntExpr(Ctx, *LineStrLabel, Offset), + RefSize); + } } else MCOS->emitIntValue(Offset, RefSize); } diff --git a/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp b/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp index 0db5fb36f7950850ebb0e10ace1142a2fe8ca229..665d92eb9a21c5352ad5f0215d793d6ce7a022ee 100644 --- a/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp +++ b/llvm/lib/MC/MCParser/MCTargetAsmParser.cpp @@ -8,6 +8,7 @@ #include "llvm/MC/MCParser/MCTargetAsmParser.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCRegister.h" using namespace llvm; @@ -48,3 +49,8 @@ ParseStatus MCTargetAsmParser::parseDirective(AsmToken DirectiveID) { return ParseStatus::Failure; return ParseStatus::NoMatch; } + +bool MCTargetAsmParser::areEqualRegs(const MCParsedAsmOperand &Op1, + const MCParsedAsmOperand &Op2) const { + return Op1.isReg() && Op2.isReg() && Op1.getReg() == Op2.getReg(); +} diff --git a/llvm/lib/MC/MCRegisterInfo.cpp b/llvm/lib/MC/MCRegisterInfo.cpp index a2c1737e2964f1d0e634964702e02c6f7dd3c906..334655616d8dbb9bb163d20c74d3486edc58b53d 100644 --- a/llvm/lib/MC/MCRegisterInfo.cpp +++ b/llvm/lib/MC/MCRegisterInfo.cpp @@ -57,18 +57,6 @@ unsigned MCRegisterInfo::getSubRegIndex(MCRegister Reg, return 0; } -unsigned MCRegisterInfo::getSubRegIdxSize(unsigned Idx) const { - assert(Idx && Idx < getNumSubRegIndices() && - "This is not a subregister index"); - return SubRegIdxRanges[Idx].Size; -} - -unsigned MCRegisterInfo::getSubRegIdxOffset(unsigned Idx) const { - assert(Idx && Idx < getNumSubRegIndices() && - "This is not a subregister index"); - return SubRegIdxRanges[Idx].Offset; -} - int MCRegisterInfo::getDwarfRegNum(MCRegister RegNum, bool isEH) const { const DwarfLLVMRegPair *M = isEH ? EHL2DwarfRegs : L2DwarfRegs; unsigned Size = isEH ? EHL2DwarfRegsSize : L2DwarfRegsSize; diff --git a/llvm/lib/MC/MCSectionXCOFF.cpp b/llvm/lib/MC/MCSectionXCOFF.cpp index 95d32e3580e3f554eb8363e1d0981a8bf00dc0cb..609ef096293042cd34476d0ed505606a3a70a70b 100644 --- a/llvm/lib/MC/MCSectionXCOFF.cpp +++ b/llvm/lib/MC/MCSectionXCOFF.cpp @@ -87,8 +87,7 @@ void MCSectionXCOFF::printSwitchToSection(const MCAsmInfo &MAI, const Triple &T, if (getKind().isCommon() && !getKind().isBSSLocal()) return; - assert((getKind().isBSSExtern() || getKind().isBSSLocal()) && - "Unexepected section kind for toc-data"); + assert(getKind().isBSS() && "Unexpected section kind for toc-data"); printCsectDirective(OS); return; } diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index d0395770ae8b051fc22e3e533aaa581fcb3b0f2c..176d55aa890bedcf2e5386bccd1604f0d1d7d43e 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -141,7 +141,7 @@ void MCStreamer::emitIntValue(uint64_t Value, unsigned Size) { unsigned Index = IsLittleEndian ? 0 : 8 - Size; emitBytes(StringRef(reinterpret_cast<char *>(&Swapped) + Index, Size)); } -void MCStreamer::emitIntValue(APInt Value) { +void MCStreamer::emitIntValue(const APInt &Value) { if (Value.getNumWords() == 1) { emitIntValue(Value.getLimitedValue(), Value.getBitWidth() / 8); return; diff --git a/llvm/lib/MC/SPIRVObjectWriter.cpp b/llvm/lib/MC/SPIRVObjectWriter.cpp index 39856e96e9be51ca15c2e2d60c28f4f301e39bdb..d72d6e07f2e6fdc7ea95dcd328dd22c931a32140 100644 --- a/llvm/lib/MC/SPIRVObjectWriter.cpp +++ b/llvm/lib/MC/SPIRVObjectWriter.cpp @@ -43,18 +43,14 @@ private: void SPIRVObjectWriter::writeHeader(const MCAssembler &Asm) { constexpr uint32_t MagicNumber = 0x07230203; - - // TODO: set the version on a min-necessary basis (just like the translator - // does) requires some refactoring of MCAssembler::VersionInfoType. - constexpr uint32_t Major = 1; - constexpr uint32_t Minor = 0; - constexpr uint32_t VersionNumber = 0 | (Major << 16) | (Minor << 8); - // TODO: check if we could use anything other than 0 (spec allows). constexpr uint32_t GeneratorMagicNumber = 0; - // TODO: do not hardcode this as well. - constexpr uint32_t Bound = 900; constexpr uint32_t Schema = 0; + // Construct SPIR-V version and Bound + const MCAssembler::VersionInfoType &VIT = Asm.getVersionInfo(); + uint32_t VersionNumber = 0 | (VIT.Major << 16) | (VIT.Minor << 8); + uint32_t Bound = VIT.Update; + W.write<uint32_t>(MagicNumber); W.write<uint32_t>(VersionNumber); W.write<uint32_t>(GeneratorMagicNumber); diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp index f265fafa59e744e47d95802b4015134bb45930fa..3c9ff71b6b06224bd2727ed243ce11035d567279 100644 --- a/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -266,7 +266,7 @@ WinCOFFWriter::WinCOFFWriter(WinCOFFObjectWriter &OWriter, // limited range for the immediate offset (+/- 1 MB); create extra offset // label symbols with regular intervals to allow referencing a // non-temporary symbol that is close enough. - UseOffsetLabels = Header.Machine == COFF::IMAGE_FILE_MACHINE_ARM64; + UseOffsetLabels = COFF::isAnyArm64(Header.Machine); } COFFSymbol *WinCOFFWriter::createSymbol(StringRef Name) { @@ -954,7 +954,7 @@ void WinCOFFWriter::recordRelocation(MCAssembler &Asm, Reloc.Data.Type == COFF::IMAGE_REL_I386_REL32) || (Header.Machine == COFF::IMAGE_FILE_MACHINE_ARMNT && Reloc.Data.Type == COFF::IMAGE_REL_ARM_REL32) || - (Header.Machine == COFF::IMAGE_FILE_MACHINE_ARM64 && + (COFF::isAnyArm64(Header.Machine) && Reloc.Data.Type == COFF::IMAGE_REL_ARM64_REL32)) FixedValue += 4; diff --git a/llvm/lib/MC/XCOFFObjectWriter.cpp b/llvm/lib/MC/XCOFFObjectWriter.cpp index d46bbaf7576571522f8458d893ffdffe5b9be42d..a7c3818d598b71482343aba8cb6683cf5780f53e 100644 --- a/llvm/lib/MC/XCOFFObjectWriter.cpp +++ b/llvm/lib/MC/XCOFFObjectWriter.cpp @@ -736,11 +736,26 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm, } else { // The FixedValue should be the TOC entry offset from the TOC-base plus // any constant offset value. - const int64_t TOCEntryOffset = SectionMap[SymASec]->Address - - TOCCsects.front().Address + - Target.getConstant(); + int64_t TOCEntryOffset = SectionMap[SymASec]->Address - + TOCCsects.front().Address + Target.getConstant(); + // For small code model, if the TOCEntryOffset overflows the 16-bit value, + // we truncate it back down to 16 bits. The linker will be able to insert + // fix-up code when needed. + // For non toc-data symbols, we already did the truncation in + // PPCAsmPrinter.cpp through setting Target.getConstant() in the + // expression above by calling getTOCEntryLoadingExprForXCOFF for the + // various TOC PseudoOps. + // For toc-data symbols, we were not able to calculate the offset from + // the TOC in PPCAsmPrinter.cpp since the TOC has not been finalized at + // that point, so we are adjusting it here though + // llvm::SignExtend64<16>(TOCEntryOffset); + // TODO: Since the time that the handling for offsets over 16-bits was + // added in PPCAsmPrinter.cpp using getTOCEntryLoadingExprForXCOFF, the + // system assembler and linker have been updated to be able to handle the + // overflowing offsets, so we no longer need to keep + // getTOCEntryLoadingExprForXCOFF. if (Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset)) - report_fatal_error("TOCEntryOffset overflows in small code model mode"); + TOCEntryOffset = llvm::SignExtend64<16>(TOCEntryOffset); FixedValue = TOCEntryOffset; } diff --git a/llvm/lib/ObjCopy/ConfigManager.cpp b/llvm/lib/ObjCopy/ConfigManager.cpp index e46b595a56dc44c94f03e7686292c8d38a677ff2..6442f1b958fb4dd76124494a48aa1524c519e47c 100644 --- a/llvm/lib/ObjCopy/ConfigManager.cpp +++ b/llvm/lib/ObjCopy/ConfigManager.cpp @@ -15,7 +15,7 @@ namespace objcopy { Expected<const COFFConfig &> ConfigManager::getCOFFConfig() const { if (!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() || - !Common.SymbolsPrefixRemove.empty() || + !Common.SymbolsPrefixRemove.empty() || !Common.SymbolsToSkip.empty() || !Common.AllocSectionsPrefix.empty() || !Common.KeepSection.empty() || !Common.SymbolsToGlobalize.empty() || !Common.SymbolsToKeep.empty() || !Common.SymbolsToLocalize.empty() || !Common.SymbolsToWeaken.empty() || @@ -34,7 +34,7 @@ Expected<const COFFConfig &> ConfigManager::getCOFFConfig() const { Expected<const MachOConfig &> ConfigManager::getMachOConfig() const { if (!Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() || - !Common.SymbolsPrefixRemove.empty() || + !Common.SymbolsPrefixRemove.empty() || !Common.SymbolsToSkip.empty() || !Common.AllocSectionsPrefix.empty() || !Common.KeepSection.empty() || !Common.SymbolsToGlobalize.empty() || !Common.SymbolsToKeep.empty() || !Common.SymbolsToLocalize.empty() || @@ -56,7 +56,7 @@ Expected<const MachOConfig &> ConfigManager::getMachOConfig() const { Expected<const WasmConfig &> ConfigManager::getWasmConfig() const { if (!Common.AddGnuDebugLink.empty() || Common.ExtractPartition || !Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() || - !Common.SymbolsPrefixRemove.empty() || + !Common.SymbolsPrefixRemove.empty() || !Common.SymbolsToSkip.empty() || !Common.AllocSectionsPrefix.empty() || Common.DiscardMode != DiscardType::None || !Common.SymbolsToAdd.empty() || !Common.SymbolsToGlobalize.empty() || !Common.SymbolsToLocalize.empty() || @@ -77,7 +77,7 @@ Expected<const WasmConfig &> ConfigManager::getWasmConfig() const { Expected<const XCOFFConfig &> ConfigManager::getXCOFFConfig() const { if (!Common.AddGnuDebugLink.empty() || Common.ExtractPartition || !Common.SplitDWO.empty() || !Common.SymbolsPrefix.empty() || - !Common.SymbolsPrefixRemove.empty() || + !Common.SymbolsPrefixRemove.empty() || !Common.SymbolsToSkip.empty() || !Common.AllocSectionsPrefix.empty() || Common.DiscardMode != DiscardType::None || !Common.AddSection.empty() || !Common.DumpSection.empty() || !Common.SymbolsToAdd.empty() || diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp index f52bcb74938d156adc41b75bec6d55191b651d23..205bc1ef5b1a19686aedc3f4c1a00ea65b3745ed 100644 --- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp +++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp @@ -214,33 +214,32 @@ static Error dumpSectionToFile(StringRef SecName, StringRef Filename, SecName.str().c_str()); } -static bool isCompressable(const SectionBase &Sec) { - return !(Sec.Flags & ELF::SHF_COMPRESSED) && - StringRef(Sec.Name).starts_with(".debug"); -} - -static Error replaceDebugSections( - Object &Obj, function_ref<bool(const SectionBase &)> ShouldReplace, - function_ref<Expected<SectionBase *>(const SectionBase *)> AddSection) { +Error Object::compressOrDecompressSections(const CommonConfig &Config) { // Build a list of the debug sections we are going to replace. // We can't call `AddSection` while iterating over sections, // because it would mutate the sections array. - SmallVector<SectionBase *, 13> ToReplace; - for (auto &Sec : Obj.sections()) - if (ShouldReplace(Sec)) - ToReplace.push_back(&Sec); - - // Build a mapping from original section to a new one. - DenseMap<SectionBase *, SectionBase *> FromTo; - for (SectionBase *S : ToReplace) { - Expected<SectionBase *> NewSection = AddSection(S); - if (!NewSection) - return NewSection.takeError(); - - FromTo[S] = *NewSection; + SmallVector<std::pair<SectionBase *, std::function<SectionBase *()>>, 0> + ToReplace; + for (SectionBase &Sec : sections()) { + if ((Sec.Flags & SHF_ALLOC) || !StringRef(Sec.Name).starts_with(".debug")) + continue; + if (auto *CS = dyn_cast<CompressedSection>(&Sec)) { + if (Config.DecompressDebugSections) { + ToReplace.emplace_back( + &Sec, [=] { return &addSection<DecompressedSection>(*CS); }); + } + } else if (Config.CompressionType != DebugCompressionType::None) { + ToReplace.emplace_back(&Sec, [&, S = &Sec] { + return &addSection<CompressedSection>( + CompressedSection(*S, Config.CompressionType, Is64Bits)); + }); + } } - return Obj.replaceSections(FromTo); + DenseMap<SectionBase *, SectionBase *> FromTo; + for (auto [S, Func] : ToReplace) + FromTo[S] = Func(); + return replaceSections(FromTo); } static bool isAArch64MappingSymbol(const Symbol &Sym) { @@ -292,6 +291,9 @@ static Error updateAndRemoveSymbols(const CommonConfig &Config, return Error::success(); Obj.SymbolTable->updateSymbols([&](Symbol &Sym) { + if (Config.SymbolsToSkip.matches(Sym.Name)) + return; + // Common and undefined symbols don't make sense as local symbols, and can // even cause crashes if we localize those, so skip them. if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF && @@ -534,24 +536,8 @@ static Error replaceAndRemoveSections(const CommonConfig &Config, if (Error E = Obj.removeSections(ELFConfig.AllowBrokenLinks, RemovePred)) return E; - if (Config.CompressionType != DebugCompressionType::None) { - if (Error Err = replaceDebugSections( - Obj, isCompressable, - [&Config, &Obj](const SectionBase *S) -> Expected<SectionBase *> { - return &Obj.addSection<CompressedSection>( - CompressedSection(*S, Config.CompressionType, Obj.Is64Bits)); - })) - return Err; - } else if (Config.DecompressDebugSections) { - if (Error Err = replaceDebugSections( - Obj, - [](const SectionBase &S) { return isa<CompressedSection>(&S); }, - [&Obj](const SectionBase *S) { - const CompressedSection *CS = cast<CompressedSection>(S); - return &Obj.addSection<DecompressedSection>(*CS); - })) - return Err; - } + if (Error E = Obj.compressOrDecompressSections(Config)) + return E; return Error::success(); } diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp index 9547cc10d2a0baaaddd3fe640ba88d20099ea5e0..8b6a0035dae35620ddbba769defe0ef3bec05860 100644 --- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp +++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp @@ -33,6 +33,7 @@ using namespace llvm; using namespace llvm::ELF; using namespace llvm::objcopy::elf; using namespace llvm::object; +using namespace llvm::support; template <class ELFT> void ELFWriter<ELFT>::writePhdr(const Segment &Seg) { uint8_t *B = reinterpret_cast<uint8_t *>(Buf->getBufferStart()) + @@ -1175,9 +1176,9 @@ template <class ELFT> Error ELFSectionWriter<ELFT>::visit(const GroupSection &Sec) { ELF::Elf32_Word *Buf = reinterpret_cast<ELF::Elf32_Word *>(Out.getBufferStart() + Sec.Offset); - support::endian::write32<ELFT::TargetEndianness>(Buf++, Sec.FlagWord); + endian::write32<ELFT::Endianness>(Buf++, Sec.FlagWord); for (SectionBase *S : Sec.GroupMembers) - support::endian::write32<ELFT::TargetEndianness>(Buf++, S->Index); + endian::write32<ELFT::Endianness>(Buf++, S->Index); return Error::success(); } @@ -1522,10 +1523,9 @@ Error ELFBuilder<ELFT>::initGroupSection(GroupSection *GroupSec) { reinterpret_cast<const ELF::Elf32_Word *>(GroupSec->Contents.data()); const ELF::Elf32_Word *End = Word + GroupSec->Contents.size() / sizeof(ELF::Elf32_Word); - GroupSec->setFlagWord( - support::endian::read32<ELFT::TargetEndianness>(Word++)); + GroupSec->setFlagWord(endian::read32<ELFT::Endianness>(Word++)); for (; Word != End; ++Word) { - uint32_t Index = support::endian::read32<ELFT::TargetEndianness>(Word); + uint32_t Index = support::endian::read32<ELFT::Endianness>(Word); Expected<SectionBase *> Sec = SecTable.getSection( Index, "group member index " + Twine(Index) + " in section '" + GroupSec->Name + "' is invalid"); @@ -1993,9 +1993,8 @@ template <class ELFT> void ELFWriter<ELFT>::writeEhdr() { Ehdr.e_ident[EI_MAG2] = 'L'; Ehdr.e_ident[EI_MAG3] = 'F'; Ehdr.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32; - Ehdr.e_ident[EI_DATA] = ELFT::TargetEndianness == llvm::endianness::big - ? ELFDATA2MSB - : ELFDATA2LSB; + Ehdr.e_ident[EI_DATA] = + ELFT::Endianness == llvm::endianness::big ? ELFDATA2MSB : ELFDATA2LSB; Ehdr.e_ident[EI_VERSION] = EV_CURRENT; Ehdr.e_ident[EI_OSABI] = Obj.OSABI; Ehdr.e_ident[EI_ABIVERSION] = Obj.ABIVersion; diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.h b/llvm/lib/ObjCopy/ELF/ELFObject.h index 7a2e20d82d11502ee2ea5fcd2e26de7bb67677ac..f72c109b6009e8b79f4968a14ca53e2427c7ec23 100644 --- a/llvm/lib/ObjCopy/ELF/ELFObject.h +++ b/llvm/lib/ObjCopy/ELF/ELFObject.h @@ -1210,6 +1210,7 @@ public: Error removeSections(bool AllowBrokenLinks, std::function<bool(const SectionBase &)> ToRemove); + Error compressOrDecompressSections(const CommonConfig &Config); Error replaceSections(const DenseMap<SectionBase *, SectionBase *> &FromTo); Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove); template <class T, class... Ts> T &addSection(Ts &&...Args) { diff --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp index 9000e9aa81ff4191156ba3c03590d817822e2692..6139d9996bdad3dc8949ab86728fd43328459aec 100644 --- a/llvm/lib/Object/Archive.cpp +++ b/llvm/lib/Object/Archive.cpp @@ -969,12 +969,19 @@ Archive::Archive(MemoryBufferRef Source, Error &Err) Err = Error::success(); } +object::Archive::Kind Archive::getDefaultKindForTriple(Triple &T) { + if (T.isOSDarwin()) + return object::Archive::K_DARWIN; + if (T.isOSAIX()) + return object::Archive::K_AIXBIG; + if (T.isOSWindows()) + return object::Archive::K_COFF; + return object::Archive::K_GNU; +} + object::Archive::Kind Archive::getDefaultKind() { Triple HostTriple(sys::getDefaultTargetTriple()); - return HostTriple.isOSDarwin() - ? object::Archive::K_DARWIN - : (HostTriple.isOSAIX() ? object::Archive::K_AIXBIG - : object::Archive::K_GNU); + return getDefaultKindForTriple(HostTriple); } Archive::child_iterator Archive::child_begin(Error &Err, diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp index e0629747b40cd7ab4fb83f46d180f7010e368679..913b74c110b364b4694ce6cba4685521f0df1ae8 100644 --- a/llvm/lib/Object/ArchiveWriter.cpp +++ b/llvm/lib/Object/ArchiveWriter.cpp @@ -48,7 +48,7 @@ using namespace llvm; using namespace llvm::object; struct SymMap { - bool UseECMap; + bool UseECMap = false; std::map<std::string, uint16_t> Map; std::map<std::string, uint16_t> ECMap; }; @@ -62,12 +62,16 @@ object::Archive::Kind NewArchiveMember::detectKindFromObject() const { Expected<std::unique_ptr<object::ObjectFile>> OptionalObject = object::ObjectFile::createObjectFile(MemBufferRef); - if (OptionalObject) - return isa<object::MachOObjectFile>(**OptionalObject) - ? object::Archive::K_DARWIN - : (isa<object::XCOFFObjectFile>(**OptionalObject) - ? object::Archive::K_AIXBIG - : object::Archive::K_GNU); + if (OptionalObject) { + if (isa<object::MachOObjectFile>(**OptionalObject)) + return object::Archive::K_DARWIN; + if (isa<object::XCOFFObjectFile>(**OptionalObject)) + return object::Archive::K_AIXBIG; + if (isa<object::COFFObjectFile>(**OptionalObject) || + isa<object::COFFImportFile>(**OptionalObject)) + return object::Archive::K_COFF; + return object::Archive::K_GNU; + } // Squelch the error in case we had a non-object file. consumeError(OptionalObject.takeError()); @@ -80,10 +84,7 @@ object::Archive::Kind NewArchiveMember::detectKindFromObject() const { MemBufferRef, file_magic::bitcode, &Context)) { auto &IRObject = cast<object::IRObjectFile>(**ObjOrErr); auto TargetTriple = Triple(IRObject.getTargetTriple()); - return TargetTriple.isOSDarwin() - ? object::Archive::K_DARWIN - : (TargetTriple.isOSAIX() ? object::Archive::K_AIXBIG - : object::Archive::K_GNU); + return object::Archive::getDefaultKindForTriple(TargetTriple); } else { // Squelch the error in case this was not a SymbolicFile. consumeError(ObjOrErr.takeError()); @@ -677,6 +678,25 @@ static bool isECObject(object::SymbolicFile &Obj) { return false; } +static bool isAnyArm64COFF(object::SymbolicFile &Obj) { + if (Obj.isCOFF()) + return COFF::isAnyArm64(cast<COFFObjectFile>(&Obj)->getMachine()); + + if (Obj.isCOFFImportFile()) + return COFF::isAnyArm64(cast<COFFImportFile>(&Obj)->getMachine()); + + if (Obj.isIR()) { + Expected<std::string> TripleStr = + getBitcodeTargetTriple(Obj.getMemoryBufferRef()); + if (!TripleStr) + return false; + Triple T(*TripleStr); + return T.isOSWindows() && T.getArch() == Triple::aarch64; + } + + return false; +} + bool isImportDescriptor(StringRef Name) { return Name.starts_with(ImportDescriptorPrefix) || Name == StringRef{NullImportDescriptorSymbolName} || @@ -730,7 +750,8 @@ static Expected<std::vector<MemberData>> computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames, object::Archive::Kind Kind, bool Thin, bool Deterministic, SymtabWritingMode NeedSymbols, SymMap *SymMap, - LLVMContext &Context, ArrayRef<NewArchiveMember> NewMembers) { + LLVMContext &Context, ArrayRef<NewArchiveMember> NewMembers, + std::optional<bool> IsEC) { static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'}; uint64_t MemHeadPadSize = 0; uint64_t Pos = @@ -794,23 +815,55 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames, Entry.second = Entry.second > 1 ? 1 : 0; } + std::vector<std::unique_ptr<SymbolicFile>> SymFiles; + + if (NeedSymbols != SymtabWritingMode::NoSymtab || isAIXBigArchive(Kind)) { + for (const NewArchiveMember &M : NewMembers) { + Expected<std::unique_ptr<SymbolicFile>> SymFileOrErr = + getSymbolicFile(M.Buf->getMemBufferRef(), Context); + if (!SymFileOrErr) + return createFileError(M.MemberName, SymFileOrErr.takeError()); + SymFiles.push_back(std::move(*SymFileOrErr)); + } + } + + if (SymMap) { + if (IsEC) { + SymMap->UseECMap = *IsEC; + } else { + // When IsEC is not specified by the caller, use it when we have both + // any ARM64 object (ARM64 or ARM64EC) and any EC object (ARM64EC or + // AMD64). This may be a single ARM64EC object, but may also be separate + // ARM64 and AMD64 objects. + bool HaveArm64 = false, HaveEC = false; + for (std::unique_ptr<SymbolicFile> &SymFile : SymFiles) { + if (!SymFile) + continue; + if (!HaveArm64) + HaveArm64 = isAnyArm64COFF(*SymFile); + if (!HaveEC) + HaveEC = isECObject(*SymFile); + if (HaveArm64 && HaveEC) { + SymMap->UseECMap = true; + break; + } + } + } + } + // The big archive format needs to know the offset of the previous member // header. uint64_t PrevOffset = 0; uint64_t NextMemHeadPadSize = 0; - std::unique_ptr<SymbolicFile> CurSymFile; - std::unique_ptr<SymbolicFile> NextSymFile; - uint16_t Index = 0; - for (auto M = NewMembers.begin(); M < NewMembers.end(); ++M) { + for (uint32_t Index = 0; Index < NewMembers.size(); ++Index) { + const NewArchiveMember *M = &NewMembers[Index]; std::string Header; raw_string_ostream Out(Header); MemoryBufferRef Buf = M->Buf->getMemBufferRef(); StringRef Data = Thin ? "" : Buf.getBuffer(); - Index++; - // ld64 expects the members to be 8-byte aligned for 64-bit content and at // least 4-byte aligned for 32-bit content. Opt for the larger encoding // uniformly. This matches the behaviour with cctools and ensures that ld64 @@ -836,29 +889,9 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames, std::move(StringMsg), object::object_error::parse_failed); } - if (NeedSymbols != SymtabWritingMode::NoSymtab || isAIXBigArchive(Kind)) { - auto SetNextSymFile = [&NextSymFile, - &Context](MemoryBufferRef Buf, - StringRef MemberName) -> Error { - Expected<std::unique_ptr<SymbolicFile>> SymFileOrErr = - getSymbolicFile(Buf, Context); - if (!SymFileOrErr) - return createFileError(MemberName, SymFileOrErr.takeError()); - NextSymFile = std::move(*SymFileOrErr); - return Error::success(); - }; - - if (M == NewMembers.begin()) - if (Error Err = SetNextSymFile(Buf, M->MemberName)) - return std::move(Err); - - CurSymFile = std::move(NextSymFile); - - if ((M + 1) != NewMembers.end()) - if (Error Err = SetNextSymFile((M + 1)->Buf->getMemBufferRef(), - (M + 1)->MemberName)) - return std::move(Err); - } + std::unique_ptr<SymbolicFile> CurSymFile; + if (!SymFiles.empty()) + CurSymFile = std::move(SymFiles[Index]); // In the big archive file format, we need to calculate and include the next // member offset and previous member offset in the file member header. @@ -879,13 +912,13 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames, // If there is another member file after this, we need to calculate the // padding before the header. - if ((M + 1) != NewMembers.end()) { - uint64_t OffsetToNextMemData = NextOffset + - sizeof(object::BigArMemHdrType) + - alignTo((M + 1)->MemberName.size(), 2); + if (Index + 1 != SymFiles.size()) { + uint64_t OffsetToNextMemData = + NextOffset + sizeof(object::BigArMemHdrType) + + alignTo(NewMembers[Index + 1].MemberName.size(), 2); NextMemHeadPadSize = alignToPowerOf2(OffsetToNextMemData, - getMemberAlignment(NextSymFile.get())) - + getMemberAlignment(SymFiles[Index + 1].get())) - OffsetToNextMemData; NextOffset += NextMemHeadPadSize; } @@ -901,7 +934,7 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames, std::vector<unsigned> Symbols; if (NeedSymbols != SymtabWritingMode::NoSymtab) { Expected<std::vector<unsigned>> SymbolsOrErr = - getSymbols(CurSymFile.get(), Index, SymNames, SymMap); + getSymbols(CurSymFile.get(), Index + 1, SymNames, SymMap); if (!SymbolsOrErr) return createFileError(M->MemberName, SymbolsOrErr.takeError()); Symbols = std::move(*SymbolsOrErr); @@ -964,11 +997,10 @@ Expected<std::string> computeArchiveRelativePath(StringRef From, StringRef To) { return std::string(Relative); } -static Error writeArchiveToStream(raw_ostream &Out, - ArrayRef<NewArchiveMember> NewMembers, - SymtabWritingMode WriteSymtab, - object::Archive::Kind Kind, - bool Deterministic, bool Thin, bool IsEC) { +static Error +writeArchiveToStream(raw_ostream &Out, ArrayRef<NewArchiveMember> NewMembers, + SymtabWritingMode WriteSymtab, object::Archive::Kind Kind, + bool Deterministic, bool Thin, std::optional<bool> IsEC) { assert((!Thin || !isBSDLike(Kind)) && "Only the gnu format has a thin mode"); SmallString<0> SymNamesBuf; @@ -976,20 +1008,21 @@ static Error writeArchiveToStream(raw_ostream &Out, SmallString<0> StringTableBuf; raw_svector_ostream StringTable(StringTableBuf); SymMap SymMap; + bool ShouldWriteSymtab = WriteSymtab != SymtabWritingMode::NoSymtab; // COFF symbol map uses 16-bit indexes, so we can't use it if there are too - // many members. - if (isCOFFArchive(Kind) && NewMembers.size() > 0xfffe) + // many members. COFF format also requires symbol table presence, so use + // GNU format when NoSymtab is requested. + if (isCOFFArchive(Kind) && (NewMembers.size() > 0xfffe || !ShouldWriteSymtab)) Kind = object::Archive::K_GNU; // In the scenario when LLVMContext is populated SymbolicFile will contain a // reference to it, thus SymbolicFile should be destroyed first. LLVMContext Context; - SymMap.UseECMap = IsEC; Expected<std::vector<MemberData>> DataOrErr = computeMemberData( StringTable, SymNames, Kind, Thin, Deterministic, WriteSymtab, - isCOFFArchive(Kind) ? &SymMap : nullptr, Context, NewMembers); + isCOFFArchive(Kind) ? &SymMap : nullptr, Context, NewMembers, IsEC); if (Error E = DataOrErr.takeError()) return E; std::vector<MemberData> &Data = *DataOrErr; @@ -1008,7 +1041,6 @@ static Error writeArchiveToStream(raw_ostream &Out, uint64_t LastMemberHeaderOffset = 0; uint64_t NumSyms = 0; uint64_t NumSyms32 = 0; // Store symbol number of 32-bit member files. - bool ShouldWriteSymtab = WriteSymtab != SymtabWritingMode::NoSymtab; for (const auto &M : Data) { // Record the start of the member's offset @@ -1236,7 +1268,8 @@ static Error writeArchiveToStream(raw_ostream &Out, Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers, SymtabWritingMode WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin, - std::unique_ptr<MemoryBuffer> OldArchiveBuf, bool IsEC) { + std::unique_ptr<MemoryBuffer> OldArchiveBuf, + std::optional<bool> IsEC) { Expected<sys::fs::TempFile> Temp = sys::fs::TempFile::create(ArcName + ".temp-archive-%%%%%%%.a"); if (!Temp) @@ -1273,7 +1306,7 @@ writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers, raw_svector_ostream ArchiveStream(ArchiveBufferVector); if (Error E = writeArchiveToStream(ArchiveStream, NewMembers, WriteSymtab, - Kind, Deterministic, Thin, false)) + Kind, Deterministic, Thin, std::nullopt)) return std::move(E); return std::make_unique<SmallVectorMemoryBuffer>( diff --git a/llvm/lib/Object/COFFImportFile.cpp b/llvm/lib/Object/COFFImportFile.cpp index 46c8e702581eacaef850520b244134248d690531..48c3ea0ed8f4e495b504f36316b3e865fe48bf92 100644 --- a/llvm/lib/Object/COFFImportFile.cpp +++ b/llvm/lib/Object/COFFImportFile.cpp @@ -84,6 +84,27 @@ StringRef COFFImportFile::getExportName() const { return name; } +Error COFFImportFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const { + switch (Symb.p) { + case ImpSymbol: + OS << "__imp_"; + break; + case ECAuxSymbol: + OS << "__imp_aux_"; + break; + } + const char *Name = Data.getBufferStart() + sizeof(coff_import_header); + if (Symb.p != ECThunkSymbol && COFF::isArm64EC(getMachine())) { + if (std::optional<std::string> DemangledName = + getArm64ECDemangledFunctionName(Name)) { + OS << StringRef(*DemangledName); + return Error::success(); + } + } + OS << StringRef(Name); + return Error::success(); +} + static uint16_t getImgRelRelocation(MachineTypes Machine) { switch (Machine) { default: @@ -626,8 +647,11 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path, MachineTypes Machine, bool MinGW, ArrayRef<COFFShortExport> NativeExports) { - MachineTypes NativeMachine = - isArm64EC(Machine) ? IMAGE_FILE_MACHINE_ARM64 : Machine; + MachineTypes NativeMachine = Machine; + if (isArm64EC(Machine)) { + NativeMachine = IMAGE_FILE_MACHINE_ARM64; + Machine = IMAGE_FILE_MACHINE_ARM64EC; + } std::vector<NewArchiveMember> Members; ObjectFactory OF(llvm::sys::path::filename(ImportName), NativeMachine); @@ -687,12 +711,12 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path, if (ImportType == IMPORT_CODE && isArm64EC(M)) { if (std::optional<std::string> MangledName = getArm64ECMangledFunctionName(Name)) { - if (ExportName.empty()) { + if (!E.Noname && ExportName.empty()) { NameType = IMPORT_NAME_EXPORTAS; ExportName.swap(Name); } Name = std::move(*MangledName); - } else if (ExportName.empty()) { + } else if (!E.Noname && ExportName.empty()) { NameType = IMPORT_NAME_EXPORTAS; ExportName = std::move(*getArm64ECDemangledFunctionName(Name)); } diff --git a/llvm/lib/Object/DXContainer.cpp b/llvm/lib/Object/DXContainer.cpp index 935749afe33852ccfdc1a3b49224d10575c42927..3b1a6203a1f8fcb5cba71c3652e9062b147d6c18 100644 --- a/llvm/lib/Object/DXContainer.cpp +++ b/llvm/lib/Object/DXContainer.cpp @@ -247,7 +247,14 @@ Error DirectX::PSVRuntimeInfo::parse(uint16_t ShaderKind) { const uint32_t PSVVersion = getVersion(); // Detect the PSVVersion by looking at the size field. - if (PSVVersion == 2) { + if (PSVVersion == 3) { + v3::RuntimeInfo Info; + if (Error Err = readStruct(PSVInfoData, Current, Info)) + return Err; + if (sys::IsBigEndianHost) + Info.swapBytes(ShaderStage); + BasicInfo = Info; + } else if (PSVVersion == 2) { v2::RuntimeInfo Info; if (Error Err = readStruct(PSVInfoData, Current, Info)) return Err; @@ -425,6 +432,8 @@ Error DirectX::PSVRuntimeInfo::parse(uint16_t ShaderKind) { } uint8_t DirectX::PSVRuntimeInfo::getSigInputCount() const { + if (const auto *P = std::get_if<dxbc::PSV::v3::RuntimeInfo>(&BasicInfo)) + return P->SigInputElements; if (const auto *P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&BasicInfo)) return P->SigInputElements; if (const auto *P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(&BasicInfo)) @@ -433,6 +442,8 @@ uint8_t DirectX::PSVRuntimeInfo::getSigInputCount() const { } uint8_t DirectX::PSVRuntimeInfo::getSigOutputCount() const { + if (const auto *P = std::get_if<dxbc::PSV::v3::RuntimeInfo>(&BasicInfo)) + return P->SigOutputElements; if (const auto *P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&BasicInfo)) return P->SigOutputElements; if (const auto *P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(&BasicInfo)) @@ -441,6 +452,8 @@ uint8_t DirectX::PSVRuntimeInfo::getSigOutputCount() const { } uint8_t DirectX::PSVRuntimeInfo::getSigPatchOrPrimCount() const { + if (const auto *P = std::get_if<dxbc::PSV::v3::RuntimeInfo>(&BasicInfo)) + return P->SigPatchOrPrimElements; if (const auto *P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&BasicInfo)) return P->SigPatchOrPrimElements; if (const auto *P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(&BasicInfo)) diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp index 137f606dd2d46bd9144ee754e9f2d7bdc1d82450..0ac4e7a57759acf6b7e5bb731c6771093fe375b5 100644 --- a/llvm/lib/Object/ELF.cpp +++ b/llvm/lib/Object/ELF.cpp @@ -251,7 +251,10 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) { } break; case ELF::EM_HEXAGON: - switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_HEX_ORDERED); } + switch (Type) { + STRINGIFY_ENUM_CASE(ELF, SHT_HEX_ORDERED); + STRINGIFY_ENUM_CASE(ELF, SHT_HEXAGON_ATTRIBUTES); + } break; case ELF::EM_X86_64: switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_X86_64_UNWIND); } @@ -557,7 +560,11 @@ Expected<typename ELFT::DynRange> ELFFile<ELFT>::dynamicEntries() const { for (const Elf_Phdr &Phdr : *ProgramHeadersOrError) { if (Phdr.p_type == ELF::PT_DYNAMIC) { - Dyn = ArrayRef(reinterpret_cast<const Elf_Dyn *>(base() + Phdr.p_offset), + const uint8_t *DynOffset = base() + Phdr.p_offset; + if (DynOffset > end()) + return createError( + "dynamic section offset past file size: corrupted ELF"); + Dyn = ArrayRef(reinterpret_cast<const Elf_Dyn *>(DynOffset), Phdr.p_filesz / sizeof(Elf_Dyn)); break; } diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp index 33be48196ae7d27d6b3151c08afdd354707c4a06..efec612957de33352ce64ee0d62559c2826254ad 100644 --- a/llvm/lib/Object/ELFObjectFile.cpp +++ b/llvm/lib/Object/ELFObjectFile.cpp @@ -20,6 +20,7 @@ #include "llvm/Support/ARMAttributeParser.h" #include "llvm/Support/ARMBuildAttributes.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/HexagonAttributeParser.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/RISCVAttributeParser.h" #include "llvm/Support/RISCVAttributes.h" @@ -287,6 +288,81 @@ SubtargetFeatures ELFObjectFileBase::getARMFeatures() const { return Features; } +static std::optional<std::string> hexagonAttrToFeatureString(unsigned Attr) { + switch (Attr) { + case 5: + return "v5"; + case 55: + return "v55"; + case 60: + return "v60"; + case 62: + return "v62"; + case 65: + return "v65"; + case 67: + return "v67"; + case 68: + return "v68"; + case 69: + return "v69"; + case 71: + return "v71"; + case 73: + return "v73"; + default: + return {}; + } +} + +SubtargetFeatures ELFObjectFileBase::getHexagonFeatures() const { + SubtargetFeatures Features; + HexagonAttributeParser Parser; + if (Error E = getBuildAttributes(Parser)) { + // Return no attributes if none can be read. + // This behavior is important for backwards compatibility. + consumeError(std::move(E)); + return Features; + } + std::optional<unsigned> Attr; + + if ((Attr = Parser.getAttributeValue(HexagonAttrs::ARCH))) { + if (std::optional<std::string> FeatureString = + hexagonAttrToFeatureString(*Attr)) + Features.AddFeature(*FeatureString); + } + + if ((Attr = Parser.getAttributeValue(HexagonAttrs::HVXARCH))) { + std::optional<std::string> FeatureString = + hexagonAttrToFeatureString(*Attr); + // There is no corresponding hvx arch for v5 and v55. + if (FeatureString && *Attr >= 60) + Features.AddFeature("hvx" + *FeatureString); + } + + if ((Attr = Parser.getAttributeValue(HexagonAttrs::HVXIEEEFP))) + if (*Attr) + Features.AddFeature("hvx-ieee-fp"); + + if ((Attr = Parser.getAttributeValue(HexagonAttrs::HVXQFLOAT))) + if (*Attr) + Features.AddFeature("hvx-qfloat"); + + if ((Attr = Parser.getAttributeValue(HexagonAttrs::ZREG))) + if (*Attr) + Features.AddFeature("zreg"); + + if ((Attr = Parser.getAttributeValue(HexagonAttrs::AUDIO))) + if (*Attr) + Features.AddFeature("audio"); + + if ((Attr = Parser.getAttributeValue(HexagonAttrs::CABAC))) + if (*Attr) + Features.AddFeature("cabac"); + + return Features; +} + Expected<SubtargetFeatures> ELFObjectFileBase::getRISCVFeatures() const { SubtargetFeatures Features; unsigned PlatformFlags = getPlatformFlags(); @@ -349,6 +425,8 @@ Expected<SubtargetFeatures> ELFObjectFileBase::getFeatures() const { return getRISCVFeatures(); case ELF::EM_LOONGARCH: return getLoongArchFeatures(); + case ELF::EM_HEXAGON: + return getHexagonFeatures(); default: return SubtargetFeatures(); } diff --git a/llvm/lib/Object/GOFFObjectFile.cpp b/llvm/lib/Object/GOFFObjectFile.cpp index 76a13559ebfe352cd0ad7160e3e23fe913eaedcb..d3dfd5d1540cfee3f27ccc2ac578bf6c994c3d47 100644 --- a/llvm/lib/Object/GOFFObjectFile.cpp +++ b/llvm/lib/Object/GOFFObjectFile.cpp @@ -104,16 +104,13 @@ GOFFObjectFile::GOFFObjectFile(MemoryBufferRef Object, Error &Err) PrevContinuationBits = I[1] & 0x03; continue; } - -#ifndef NDEBUG - for (size_t J = 0; J < GOFF::RecordLength; ++J) { + LLVM_DEBUG(for (size_t J = 0; J < GOFF::RecordLength; ++J) { const uint8_t *P = I + J; if (J % 8 == 0) dbgs() << " "; - dbgs() << format("%02hhX", *P); - } -#endif + }); + switch (RecordType) { case GOFF::RT_ESD: { // Save ESD record. diff --git a/llvm/lib/Object/OffloadBinary.cpp b/llvm/lib/Object/OffloadBinary.cpp index 4ab6536dc90b52efb82d819ce7c83d8704d67696..6e9f8bed513c19c2bccd914b1d1cac5ca475e7da 100644 --- a/llvm/lib/Object/OffloadBinary.cpp +++ b/llvm/lib/Object/OffloadBinary.cpp @@ -189,7 +189,10 @@ OffloadBinary::create(MemoryBufferRef Buf) { return errorCodeToError(object_error::parse_failed); if (TheHeader->Size > Buf.getBufferSize() || - TheHeader->EntryOffset > TheHeader->Size - sizeof(Entry) || + TheHeader->Size < sizeof(Entry) || TheHeader->Size < sizeof(Header)) + return errorCodeToError(object_error::unexpected_eof); + + if (TheHeader->EntryOffset > TheHeader->Size - sizeof(Entry) || TheHeader->EntrySize > TheHeader->Size - sizeof(Header)) return errorCodeToError(object_error::unexpected_eof); diff --git a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp index 09a5e41c71234f38e120e28ea3a7e6590a5c6848..f3a518df317504020628f1f6d71fd6585b375f11 100644 --- a/llvm/lib/ObjectYAML/DXContainerEmitter.cpp +++ b/llvm/lib/ObjectYAML/DXContainerEmitter.cpp @@ -198,8 +198,9 @@ void DXContainerWriter::writeParts(raw_ostream &OS) { if (!P.Info.has_value()) continue; mcdxbc::PSVRuntimeInfo PSV; - memcpy(&PSV.BaseData, &P.Info->Info, sizeof(dxbc::PSV::v2::RuntimeInfo)); + memcpy(&PSV.BaseData, &P.Info->Info, sizeof(dxbc::PSV::v3::RuntimeInfo)); PSV.Resources = P.Info->Resources; + PSV.EntryName = P.Info->EntryName; for (auto El : P.Info->SigInputElements) PSV.InputElements.push_back(mcdxbc::PSVSignatureElement{ diff --git a/llvm/lib/ObjectYAML/DXContainerYAML.cpp b/llvm/lib/ObjectYAML/DXContainerYAML.cpp index 7dc9822bdd221d6902144e9c89648419376a20a7..38063670aee6e87e855168ec47d0959ed2080515 100644 --- a/llvm/lib/ObjectYAML/DXContainerYAML.cpp +++ b/llvm/lib/ObjectYAML/DXContainerYAML.cpp @@ -24,14 +24,14 @@ static_assert((uint64_t)dxbc::FeatureFlags::NextUnusedBit <= 1ull << 63, "Shader flag bits exceed enum size."); DXContainerYAML::ShaderFeatureFlags::ShaderFeatureFlags(uint64_t FlagData) { -#define SHADER_FEATURE_FLAG(Num, Val, Str) \ +#define SHADER_FEATURE_FLAG(Num, DxilModuleNum, Val, Str) \ Val = (FlagData & (uint64_t)dxbc::FeatureFlags::Val) > 0; #include "llvm/BinaryFormat/DXContainerConstants.def" } uint64_t DXContainerYAML::ShaderFeatureFlags::getEncodedFlags() { uint64_t Flag = 0; -#define SHADER_FEATURE_FLAG(Num, Val, Str) \ +#define SHADER_FEATURE_FLAG(Num, DxilModuleNum, Val, Str) \ if (Val) \ Flag |= (uint64_t)dxbc::FeatureFlags::Val; #include "llvm/BinaryFormat/DXContainerConstants.def" @@ -74,6 +74,16 @@ DXContainerYAML::PSVInfo::PSVInfo(const dxbc::PSV::v2::RuntimeInfo *P) memcpy(&Info, P, sizeof(dxbc::PSV::v2::RuntimeInfo)); } +DXContainerYAML::PSVInfo::PSVInfo(const dxbc::PSV::v3::RuntimeInfo *P, + StringRef StringTable) + : Version(3), + EntryName(StringTable.substr(P->EntryNameOffset, + StringTable.find('\0', P->EntryNameOffset) - + P->EntryNameOffset)) { + memset(&Info, 0, sizeof(Info)); + memcpy(&Info, P, sizeof(dxbc::PSV::v3::RuntimeInfo)); +} + namespace yaml { void MappingTraits<DXContainerYAML::VersionTuple>::mapping( @@ -105,7 +115,8 @@ void MappingTraits<DXContainerYAML::DXILProgram>::mapping( void MappingTraits<DXContainerYAML::ShaderFeatureFlags>::mapping( IO &IO, DXContainerYAML::ShaderFeatureFlags &Flags) { -#define SHADER_FEATURE_FLAG(Num, Val, Str) IO.mapRequired(#Val, Flags.Val); +#define SHADER_FEATURE_FLAG(Num, DxilModuleNum, Val, Str) \ + IO.mapRequired(#Val, Flags.Val); #include "llvm/BinaryFormat/DXContainerConstants.def" } @@ -347,6 +358,11 @@ void DXContainerYAML::PSVInfo::mapInfoForVersion(yaml::IO &IO) { IO.mapRequired("NumThreadsX", Info.NumThreadsX); IO.mapRequired("NumThreadsY", Info.NumThreadsY); IO.mapRequired("NumThreadsZ", Info.NumThreadsZ); + + if (Version == 2) + return; + + IO.mapRequired("EntryName", EntryName); } } // namespace llvm diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp index 58a725f8d8778851ac8d1eb743a450d54e34f573..b7118a543faed356ffdd819de5ab086d1dfeb229 100644 --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -1314,7 +1314,7 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, if (!ELFT::Is64Bits && E > UINT32_MAX) reportError(Section.Name + ": the value is too large for 32-bits: 0x" + Twine::utohexstr(E)); - CBA.write<uintX_t>(E, ELFT::TargetEndianness); + CBA.write<uintX_t>(E, ELFT::Endianness); } SHeader.sh_size = sizeof(uintX_t) * Section.Entries->size(); @@ -1333,7 +1333,7 @@ void ELFState<ELFT>::writeSectionContent( return; for (uint32_t E : *Shndx.Entries) - CBA.write<uint32_t>(E, ELFT::TargetEndianness); + CBA.write<uint32_t>(E, ELFT::Endianness); SHeader.sh_size = Shndx.Entries->size() * SHeader.sh_entsize; } @@ -1357,7 +1357,7 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, SectionIndex = llvm::ELF::GRP_COMDAT; else SectionIndex = toSectionIndex(Member.sectionNameOrType, Section.Name); - CBA.write<uint32_t>(SectionIndex, ELFT::TargetEndianness); + CBA.write<uint32_t>(SectionIndex, ELFT::Endianness); } SHeader.sh_size = SHeader.sh_entsize * Section.Members->size(); } @@ -1370,7 +1370,7 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, return; for (uint16_t Version : *Section.Entries) - CBA.write<uint16_t>(Version, ELFT::TargetEndianness); + CBA.write<uint16_t>(Version, ELFT::Endianness); SHeader.sh_size = Section.Entries->size() * SHeader.sh_entsize; } @@ -1382,7 +1382,7 @@ void ELFState<ELFT>::writeSectionContent( return; for (const ELFYAML::StackSizeEntry &E : *Section.Entries) { - CBA.write<uintX_t>(E.Address, ELFT::TargetEndianness); + CBA.write<uintX_t>(E.Address, ELFT::Endianness); SHeader.sh_size += sizeof(uintX_t) + CBA.writeULEB128(E.Size); } } @@ -1444,7 +1444,7 @@ void ELFState<ELFT>::writeSectionContent( uint64_t TotalNumBlocks = 0; for (const ELFYAML::BBAddrMapEntry::BBRangeEntry &BBR : *E.BBRanges) { // Write the base address of the range. - CBA.write<uintX_t>(BBR.BaseAddress, ELFT::TargetEndianness); + CBA.write<uintX_t>(BBR.BaseAddress, ELFT::Endianness); // Write number of BBEntries (number of basic blocks in this basic block // range). This is overridden by the 'NumBlocks' YAML field when // specified. @@ -1558,7 +1558,7 @@ void ELFState<ELFT>::writeSectionContent( return; for (const ELFYAML::CallGraphEntryWeight &E : *Section.Entries) { - CBA.write<uint64_t>(E.Weight, ELFT::TargetEndianness); + CBA.write<uint64_t>(E.Weight, ELFT::Endianness); SHeader.sh_size += sizeof(object::Elf_CGProfile_Impl<ELFT>); } } @@ -1572,15 +1572,15 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, CBA.write<uint32_t>( Section.NBucket.value_or(llvm::yaml::Hex64(Section.Bucket->size())), - ELFT::TargetEndianness); + ELFT::Endianness); CBA.write<uint32_t>( Section.NChain.value_or(llvm::yaml::Hex64(Section.Chain->size())), - ELFT::TargetEndianness); + ELFT::Endianness); for (uint32_t Val : *Section.Bucket) - CBA.write<uint32_t>(Val, ELFT::TargetEndianness); + CBA.write<uint32_t>(Val, ELFT::Endianness); for (uint32_t Val : *Section.Chain) - CBA.write<uint32_t>(Val, ELFT::TargetEndianness); + CBA.write<uint32_t>(Val, ELFT::Endianness); SHeader.sh_size = (2 + Section.Bucket->size() + Section.Chain->size()) * 4; } @@ -1687,8 +1687,8 @@ void ELFState<ELFT>::writeSectionContent( return; for (const ELFYAML::ARMIndexTableEntry &E : *Section.Entries) { - CBA.write<uint32_t>(E.Offset, ELFT::TargetEndianness); - CBA.write<uint32_t>(E.Value, ELFT::TargetEndianness); + CBA.write<uint32_t>(E.Offset, ELFT::Endianness); + CBA.write<uint32_t>(E.Value, ELFT::Endianness); } SHeader.sh_size = Section.Entries->size() * 8; } @@ -1729,8 +1729,8 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, return; for (const ELFYAML::DynamicEntry &DE : *Section.Entries) { - CBA.write<uintX_t>(DE.Tag, ELFT::TargetEndianness); - CBA.write<uintX_t>(DE.Val, ELFT::TargetEndianness); + CBA.write<uintX_t>(DE.Tag, ELFT::Endianness); + CBA.write<uintX_t>(DE.Val, ELFT::Endianness); } SHeader.sh_size = 2 * sizeof(uintX_t) * Section.Entries->size(); } @@ -1758,18 +1758,18 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, for (const ELFYAML::NoteEntry &NE : *Section.Notes) { // Write name size. if (NE.Name.empty()) - CBA.write<uint32_t>(0, ELFT::TargetEndianness); + CBA.write<uint32_t>(0, ELFT::Endianness); else - CBA.write<uint32_t>(NE.Name.size() + 1, ELFT::TargetEndianness); + CBA.write<uint32_t>(NE.Name.size() + 1, ELFT::Endianness); // Write description size. if (NE.Desc.binary_size() == 0) - CBA.write<uint32_t>(0, ELFT::TargetEndianness); + CBA.write<uint32_t>(0, ELFT::Endianness); else - CBA.write<uint32_t>(NE.Desc.binary_size(), ELFT::TargetEndianness); + CBA.write<uint32_t>(NE.Desc.binary_size(), ELFT::Endianness); // Write type. - CBA.write<uint32_t>(NE.Type, ELFT::TargetEndianness); + CBA.write<uint32_t>(NE.Type, ELFT::Endianness); // Write name, null terminator and padding. if (!NE.Name.empty()) { @@ -1803,35 +1803,35 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, // be used to override this field, which is useful for producing broken // objects. if (Section.Header->NBuckets) - CBA.write<uint32_t>(*Section.Header->NBuckets, ELFT::TargetEndianness); + CBA.write<uint32_t>(*Section.Header->NBuckets, ELFT::Endianness); else - CBA.write<uint32_t>(Section.HashBuckets->size(), ELFT::TargetEndianness); + CBA.write<uint32_t>(Section.HashBuckets->size(), ELFT::Endianness); // Write the index of the first symbol in the dynamic symbol table accessible // via the hash table. - CBA.write<uint32_t>(Section.Header->SymNdx, ELFT::TargetEndianness); + CBA.write<uint32_t>(Section.Header->SymNdx, ELFT::Endianness); // Write the number of words in the Bloom filter. As above, the "MaskWords" // property can be used to set this field to any value. if (Section.Header->MaskWords) - CBA.write<uint32_t>(*Section.Header->MaskWords, ELFT::TargetEndianness); + CBA.write<uint32_t>(*Section.Header->MaskWords, ELFT::Endianness); else - CBA.write<uint32_t>(Section.BloomFilter->size(), ELFT::TargetEndianness); + CBA.write<uint32_t>(Section.BloomFilter->size(), ELFT::Endianness); // Write the shift constant used by the Bloom filter. - CBA.write<uint32_t>(Section.Header->Shift2, ELFT::TargetEndianness); + CBA.write<uint32_t>(Section.Header->Shift2, ELFT::Endianness); // We've finished writing the header. Now write the Bloom filter. for (llvm::yaml::Hex64 Val : *Section.BloomFilter) - CBA.write<uintX_t>(Val, ELFT::TargetEndianness); + CBA.write<uintX_t>(Val, ELFT::Endianness); // Write an array of hash buckets. for (llvm::yaml::Hex32 Val : *Section.HashBuckets) - CBA.write<uint32_t>(Val, ELFT::TargetEndianness); + CBA.write<uint32_t>(Val, ELFT::Endianness); // Write an array of hash values. for (llvm::yaml::Hex32 Val : *Section.HashValues) - CBA.write<uint32_t>(Val, ELFT::TargetEndianness); + CBA.write<uint32_t>(Val, ELFT::Endianness); SHeader.sh_size = 16 /*Header size*/ + Section.BloomFilter->size() * sizeof(typename ELFT::uint) + diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp index 9c1a28db592a1cd9fb5ed5d114313b11203112a1..045211c44b907956a6dbbc14aa1cdfbf1f84dbe0 100644 --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -716,6 +716,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration( break; case ELF::EM_HEXAGON: ECase(SHT_HEX_ORDERED); + ECase(SHT_HEXAGON_ATTRIBUTES); break; case ELF::EM_X86_64: ECase(SHT_X86_64_UNWIND); diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 4d1eb10d2d41c611d429474fde5890075a65b68b..57975e34d4265bd66cb1ccb1f6369dc66578e18e 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -358,13 +358,40 @@ public: // Intentionally break the Function by inserting a terminator // instruction in the middle of a basic block. BasicBlock &BB = F.getEntryBlock(); - new UnreachableInst(F.getContext(), BB.getTerminator()); + new UnreachableInst(F.getContext(), BB.getTerminator()->getIterator()); return PreservedAnalyses::none(); } static StringRef name() { return "TriggerVerifierErrorPass"; } }; +// A pass requires all MachineFunctionProperties. +// DO NOT USE THIS EXCEPT FOR TESTING! +class RequireAllMachineFunctionPropertiesPass + : public MachinePassInfoMixin<RequireAllMachineFunctionPropertiesPass> { +public: + PreservedAnalyses run(MachineFunction &, MachineFunctionAnalysisManager &) { + return PreservedAnalyses::none(); + } + + static MachineFunctionProperties getRequiredProperties() { + MachineFunctionProperties MFProps; + MFProps.set(MachineFunctionProperties::Property::FailedISel); + MFProps.set(MachineFunctionProperties::Property::FailsVerification); + MFProps.set(MachineFunctionProperties::Property::IsSSA); + MFProps.set(MachineFunctionProperties::Property::Legalized); + MFProps.set(MachineFunctionProperties::Property::NoPHIs); + MFProps.set(MachineFunctionProperties::Property::NoVRegs); + MFProps.set(MachineFunctionProperties::Property::RegBankSelected); + MFProps.set(MachineFunctionProperties::Property::Selected); + MFProps.set(MachineFunctionProperties::Property::TiedOpsRewritten); + MFProps.set(MachineFunctionProperties::Property::TracksDebugUserValues); + MFProps.set(MachineFunctionProperties::Property::TracksLiveness); + return MFProps; + } + static StringRef name() { return "RequireAllMachineFunctionPropertiesPass"; } +}; + } // namespace PassBuilder::PassBuilder(TargetMachine *TM, PipelineTuningOptions PTO, @@ -503,15 +530,6 @@ static std::optional<int> parseDevirtPassName(StringRef Name) { return Count; } -static bool checkParametrizedPassName(StringRef Name, StringRef PassName) { - if (!Name.consume_front(PassName)) - return false; - // normal pass name w/o parameters == default parameters - if (Name.empty()) - return true; - return Name.starts_with("<") && Name.ends_with(">"); -} - static std::optional<OptimizationLevel> parseOptLevel(StringRef S) { return StringSwitch<std::optional<OptimizationLevel>>(S) .Case("O0", OptimizationLevel::O0) @@ -523,44 +541,28 @@ static std::optional<OptimizationLevel> parseOptLevel(StringRef S) { .Default(std::nullopt); } -namespace { - -/// This performs customized parsing of pass name with parameters. -/// -/// We do not need parametrization of passes in textual pipeline very often, -/// yet on a rare occasion ability to specify parameters right there can be -/// useful. -/// -/// \p Name - parameterized specification of a pass from a textual pipeline -/// is a string in a form of : -/// PassName '<' parameter-list '>' -/// -/// Parameter list is being parsed by the parser callable argument, \p Parser, -/// It takes a string-ref of parameters and returns either StringError or a -/// parameter list in a form of a custom parameters type, all wrapped into -/// Expected<> template class. -/// -template <typename ParametersParseCallableT> -auto parsePassParameters(ParametersParseCallableT &&Parser, StringRef Name, - StringRef PassName) -> decltype(Parser(StringRef{})) { - using ParametersT = typename decltype(Parser(StringRef{}))::value_type; +Expected<bool> PassBuilder::parseSinglePassOption(StringRef Params, + StringRef OptionName, + StringRef PassName) { + bool Result = false; + while (!Params.empty()) { + StringRef ParamName; + std::tie(ParamName, Params) = Params.split(';'); - StringRef Params = Name; - if (!Params.consume_front(PassName)) { - assert(false && - "unable to strip pass name from parametrized pass specification"); - } - if (!Params.empty() && - (!Params.consume_front("<") || !Params.consume_back(">"))) { - assert(false && "invalid format for parametrized pass name"); + if (ParamName == OptionName) { + Result = true; + } else { + return make_error<StringError>( + formatv("invalid {1} pass parameter '{0}' ", ParamName, PassName) + .str(), + inconvertibleErrorCode()); + } } - - Expected<ParametersT> Result = Parser(Params); - assert((Result || Result.template errorIsA<StringError>()) && - "Pass parameter parser can only return StringErrors."); return Result; } +namespace { + /// Parser of parameters for HardwareLoops pass. Expected<HardwareLoopOptions> parseHardwareLoopOptions(StringRef Params) { HardwareLoopOptions HardwareLoopOpts; @@ -645,44 +647,29 @@ Expected<LoopUnrollOptions> parseLoopUnrollOptions(StringRef Params) { return UnrollOpts; } -Expected<bool> parseSinglePassOption(StringRef Params, StringRef OptionName, - StringRef PassName) { - bool Result = false; - while (!Params.empty()) { - StringRef ParamName; - std::tie(ParamName, Params) = Params.split(';'); - - if (ParamName == OptionName) { - Result = true; - } else { - return make_error<StringError>( - formatv("invalid {1} pass parameter '{0}' ", ParamName, PassName) - .str(), - inconvertibleErrorCode()); - } - } - return Result; -} - Expected<bool> parseGlobalDCEPassOptions(StringRef Params) { - return parseSinglePassOption(Params, "vfe-linkage-unit-visibility", "GlobalDCE"); + return PassBuilder::parseSinglePassOption( + Params, "vfe-linkage-unit-visibility", "GlobalDCE"); } Expected<bool> parseCGProfilePassOptions(StringRef Params) { - return parseSinglePassOption(Params, "in-lto-post-link", "CGProfile"); + return PassBuilder::parseSinglePassOption(Params, "in-lto-post-link", + "CGProfile"); } Expected<bool> parseInlinerPassOptions(StringRef Params) { - return parseSinglePassOption(Params, "only-mandatory", "InlinerPass"); + return PassBuilder::parseSinglePassOption(Params, "only-mandatory", + "InlinerPass"); } Expected<bool> parseCoroSplitPassOptions(StringRef Params) { - return parseSinglePassOption(Params, "reuse-storage", "CoroSplitPass"); + return PassBuilder::parseSinglePassOption(Params, "reuse-storage", + "CoroSplitPass"); } Expected<bool> parsePostOrderFunctionAttrsPassOptions(StringRef Params) { - return parseSinglePassOption(Params, "skip-non-recursive-function-attrs", - "PostOrderFunctionAttrs"); + return PassBuilder::parseSinglePassOption( + Params, "skip-non-recursive-function-attrs", "PostOrderFunctionAttrs"); } Expected<CFGuardPass::Mechanism> parseCFGuardPassOptions(StringRef Params) { @@ -706,19 +693,21 @@ Expected<CFGuardPass::Mechanism> parseCFGuardPassOptions(StringRef Params) { } Expected<bool> parseEarlyCSEPassOptions(StringRef Params) { - return parseSinglePassOption(Params, "memssa", "EarlyCSE"); + return PassBuilder::parseSinglePassOption(Params, "memssa", "EarlyCSE"); } Expected<bool> parseEntryExitInstrumenterPassOptions(StringRef Params) { - return parseSinglePassOption(Params, "post-inline", "EntryExitInstrumenter"); + return PassBuilder::parseSinglePassOption(Params, "post-inline", + "EntryExitInstrumenter"); } Expected<bool> parseLoopExtractorPassOptions(StringRef Params) { - return parseSinglePassOption(Params, "single", "LoopExtractor"); + return PassBuilder::parseSinglePassOption(Params, "single", "LoopExtractor"); } Expected<bool> parseLowerMatrixIntrinsicsPassOptions(StringRef Params) { - return parseSinglePassOption(Params, "minimal", "LowerMatrixIntrinsics"); + return PassBuilder::parseSinglePassOption(Params, "minimal", + "LowerMatrixIntrinsics"); } Expected<AddressSanitizerOptions> parseASanPassOptions(StringRef Params) { @@ -1058,13 +1047,13 @@ parseStackLifetimeOptions(StringRef Params) { } Expected<bool> parseDependenceAnalysisPrinterOptions(StringRef Params) { - return parseSinglePassOption(Params, "normalized-results", - "DependenceAnalysisPrinter"); + return PassBuilder::parseSinglePassOption(Params, "normalized-results", + "DependenceAnalysisPrinter"); } Expected<bool> parseSeparateConstOffsetFromGEPPassOptions(StringRef Params) { - return parseSinglePassOption(Params, "lower-gep", - "SeparateConstOffsetFromGEP"); + return PassBuilder::parseSinglePassOption(Params, "lower-gep", + "SeparateConstOffsetFromGEP"); } Expected<OptimizationLevel> @@ -1080,13 +1069,13 @@ parseFunctionSimplificationPipelineOptions(StringRef Params) { } Expected<bool> parseMemorySSAPrinterPassOptions(StringRef Params) { - return parseSinglePassOption(Params, "no-ensure-optimized-uses", - "MemorySSAPrinterPass"); + return PassBuilder::parseSinglePassOption(Params, "no-ensure-optimized-uses", + "MemorySSAPrinterPass"); } Expected<bool> parseSpeculativeExecutionPassOptions(StringRef Params) { - return parseSinglePassOption(Params, "only-if-divergent-target", - "SpeculativeExecutionPass"); + return PassBuilder::parseSinglePassOption(Params, "only-if-divergent-target", + "SpeculativeExecutionPass"); } Expected<std::string> parseMemProfUsePassOptions(StringRef Params) { @@ -1107,13 +1096,13 @@ Expected<std::string> parseMemProfUsePassOptions(StringRef Params) { } Expected<bool> parseStructuralHashPrinterPassOptions(StringRef Params) { - return parseSinglePassOption(Params, "detailed", - "StructuralHashPrinterPass"); + return PassBuilder::parseSinglePassOption(Params, "detailed", + "StructuralHashPrinterPass"); } Expected<bool> parseWinEHPrepareOptions(StringRef Params) { - return parseSinglePassOption(Params, "demote-catchswitch-only", - "WinEHPreparePass"); + return PassBuilder::parseSinglePassOption(Params, "demote-catchswitch-only", + "WinEHPreparePass"); } Expected<GlobalMergeOptions> parseGlobalMergeOptions(StringRef Params) { @@ -1196,7 +1185,7 @@ static bool isModulePassName(StringRef Name, CallbacksT &Callbacks) { if (Name == NAME) \ return true; #define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \ - if (checkParametrizedPassName(Name, NAME)) \ + if (PassBuilder::checkParametrizedPassName(Name, NAME)) \ return true; #define MODULE_ANALYSIS(NAME, CREATE_PASS) \ if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ @@ -1225,7 +1214,7 @@ static bool isCGSCCPassName(StringRef Name, CallbacksT &Callbacks) { if (Name == NAME) \ return true; #define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \ - if (checkParametrizedPassName(Name, NAME)) \ + if (PassBuilder::checkParametrizedPassName(Name, NAME)) \ return true; #define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ @@ -1252,7 +1241,7 @@ static bool isFunctionPassName(StringRef Name, CallbacksT &Callbacks) { if (Name == NAME) \ return true; #define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \ - if (checkParametrizedPassName(Name, NAME)) \ + if (PassBuilder::checkParametrizedPassName(Name, NAME)) \ return true; #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ @@ -1293,7 +1282,7 @@ static bool isLoopNestPassName(StringRef Name, CallbacksT &Callbacks, if (parseRepeatPassName(Name)) return true; - if (checkParametrizedPassName(Name, "lnicm")) { + if (PassBuilder::checkParametrizedPassName(Name, "lnicm")) { UseMemorySSA = true; return true; } @@ -1315,7 +1304,7 @@ static bool isLoopPassName(StringRef Name, CallbacksT &Callbacks, if (parseRepeatPassName(Name)) return true; - if (checkParametrizedPassName(Name, "licm")) { + if (PassBuilder::checkParametrizedPassName(Name, "licm")) { UseMemorySSA = true; return true; } @@ -1324,7 +1313,7 @@ static bool isLoopPassName(StringRef Name, CallbacksT &Callbacks, if (Name == NAME) \ return true; #define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \ - if (checkParametrizedPassName(Name, NAME)) \ + if (PassBuilder::checkParametrizedPassName(Name, NAME)) \ return true; #define LOOP_ANALYSIS(NAME, CREATE_PASS) \ if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp index d328460510830ae82542088eaa451677fb81a4a0..445b48067a9755b05f99aeb042d733a88042769a 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp @@ -894,31 +894,34 @@ static Error readCoverageMappingData( Expected<std::unique_ptr<BinaryCoverageReader>> BinaryCoverageReader::createCoverageReaderFromBuffer( StringRef Coverage, FuncRecordsStorage &&FuncRecords, - InstrProfSymtab &&ProfileNames, uint8_t BytesInAddress, + std::unique_ptr<InstrProfSymtab> ProfileNamesPtr, uint8_t BytesInAddress, llvm::endianness Endian, StringRef CompilationDir) { - std::unique_ptr<BinaryCoverageReader> Reader( - new BinaryCoverageReader(std::move(FuncRecords))); - Reader->ProfileNames = std::move(ProfileNames); + if (ProfileNamesPtr == nullptr) + return make_error<CoverageMapError>(coveragemap_error::malformed, + "Caller must provide ProfileNames"); + std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader( + std::move(ProfileNamesPtr), std::move(FuncRecords))); + InstrProfSymtab &ProfileNames = *Reader->ProfileNames; StringRef FuncRecordsRef = Reader->FuncRecords->getBuffer(); if (BytesInAddress == 4 && Endian == llvm::endianness::little) { if (Error E = readCoverageMappingData<uint32_t, llvm::endianness::little>( - Reader->ProfileNames, Coverage, FuncRecordsRef, - Reader->MappingRecords, CompilationDir, Reader->Filenames)) + ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords, + CompilationDir, Reader->Filenames)) return std::move(E); } else if (BytesInAddress == 4 && Endian == llvm::endianness::big) { if (Error E = readCoverageMappingData<uint32_t, llvm::endianness::big>( - Reader->ProfileNames, Coverage, FuncRecordsRef, - Reader->MappingRecords, CompilationDir, Reader->Filenames)) + ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords, + CompilationDir, Reader->Filenames)) return std::move(E); } else if (BytesInAddress == 8 && Endian == llvm::endianness::little) { if (Error E = readCoverageMappingData<uint64_t, llvm::endianness::little>( - Reader->ProfileNames, Coverage, FuncRecordsRef, - Reader->MappingRecords, CompilationDir, Reader->Filenames)) + ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords, + CompilationDir, Reader->Filenames)) return std::move(E); } else if (BytesInAddress == 8 && Endian == llvm::endianness::big) { if (Error E = readCoverageMappingData<uint64_t, llvm::endianness::big>( - Reader->ProfileNames, Coverage, FuncRecordsRef, - Reader->MappingRecords, CompilationDir, Reader->Filenames)) + ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords, + CompilationDir, Reader->Filenames)) return std::move(E); } else return make_error<CoverageMapError>( @@ -963,8 +966,8 @@ loadTestingFormat(StringRef Data, StringRef CompilationDir) { if (Data.size() < ProfileNamesSize) return make_error<CoverageMapError>(coveragemap_error::malformed, "the size of ProfileNames is too big"); - InstrProfSymtab ProfileNames; - if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address)) + auto ProfileNames = std::make_unique<InstrProfSymtab>(); + if (Error E = ProfileNames->create(Data.substr(0, ProfileNamesSize), Address)) return std::move(E); Data = Data.substr(ProfileNamesSize); @@ -1099,7 +1102,7 @@ loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch, OF->isLittleEndian() ? llvm::endianness::little : llvm::endianness::big; // Look for the sections that we are interested in. - InstrProfSymtab ProfileNames; + auto ProfileNames = std::make_unique<InstrProfSymtab>(); std::vector<SectionRef> NamesSectionRefs; // If IPSK_name is not found, fallback to search for IPK_covname, which is // used when binary correlation is enabled. @@ -1116,7 +1119,7 @@ loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch, return make_error<CoverageMapError>( coveragemap_error::malformed, "the size of coverage mapping section is not one"); - if (Error E = ProfileNames.create(NamesSectionRefs.back())) + if (Error E = ProfileNames->create(NamesSectionRefs.back())) return std::move(E); auto CoverageSection = lookupSections(*OF, IPSK_covmap); diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp index 8cf97fcb1dab574af98c11ac2fccfced336da718..95f900d0fff1ca96b981abf7264df44b81829f8d 100644 --- a/llvm/lib/ProfileData/InstrProf.cpp +++ b/llvm/lib/ProfileData/InstrProf.cpp @@ -34,6 +34,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Compression.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" @@ -57,6 +58,8 @@ using namespace llvm; +#define DEBUG_TYPE "instrprof" + static cl::opt<bool> StaticFuncFullModulePrefix( "static-func-full-module-prefix", cl::init(true), cl::Hidden, cl::desc("Use full module build paths in the profile counter names for " @@ -219,6 +222,12 @@ cl::opt<bool> DoInstrProfNameCompression( "enable-name-compression", cl::desc("Enable name/filename string compression"), cl::init(true)); +cl::opt<bool> EnableVTableValueProfiling( + "enable-vtable-value-profiling", cl::init(false), + cl::desc("If true, the virtual table address will be instrumented to know " + "the types of a C++ pointer. The information is used in indirect " + "call promotion to do selective vtable-based comparison.")); + std::string getInstrProfSectionName(InstrProfSectKind IPSK, Triple::ObjectFormatType OF, bool AddSegmentInfo) { @@ -378,6 +387,13 @@ std::string getPGOFuncName(const Function &F, bool InLTO, uint64_t Version) { return getPGOFuncName(F.getName(), GlobalValue::ExternalLinkage, ""); } +std::string getPGOName(const GlobalVariable &V, bool InLTO) { + // PGONameMetadata should be set by compiler at profile use time + // and read by symtab creation to look up symbols corresponding to + // a MD5 hash. + return getIRPGOObjectName(V, InLTO, /*PGONameMetadata=*/nullptr); +} + // See getIRPGOObjectName() for a discription of the format. std::pair<StringRef, StringRef> getParsedIRPGOName(StringRef IRPGOName) { auto [FileName, MangledName] = IRPGOName.split(kGlobalIdentifierDelimiter); @@ -459,6 +475,7 @@ Error InstrProfSymtab::create(Module &M, bool InLTO) { if (Error E = addFuncWithName(F, getPGOFuncName(F, InLTO))) return E; } + Sorted = false; finalizeSymtab(); return Error::success(); @@ -517,6 +534,25 @@ Error InstrProfSymtab::create(StringRef NameStrings) { std::bind(&InstrProfSymtab::addFuncName, this, std::placeholders::_1)); } +Error InstrProfSymtab::create(StringRef FuncNameStrings, + StringRef VTableNameStrings) { + if (Error E = readAndDecodeStrings(FuncNameStrings, + std::bind(&InstrProfSymtab::addFuncName, + this, std::placeholders::_1))) + return E; + + return readAndDecodeStrings( + VTableNameStrings, + std::bind(&InstrProfSymtab::addVTableName, this, std::placeholders::_1)); +} + +Error InstrProfSymtab::initVTableNamesFromCompressedStrings( + StringRef CompressedVTableStrings) { + return readAndDecodeStrings( + CompressedVTableStrings, + std::bind(&InstrProfSymtab::addVTableName, this, std::placeholders::_1)); +} + StringRef InstrProfSymtab::getCanonicalName(StringRef PGOName) { // In ThinLTO, local function may have been promoted to global and have // suffix ".llvm." added to the function name. We need to add the @@ -560,6 +596,12 @@ Error InstrProfSymtab::addFuncWithName(Function &F, StringRef PGOFuncName) { return Error::success(); } +uint64_t InstrProfSymtab::getVTableHashFromAddress(uint64_t Address) { + // Given a runtime address, look up the hash value in the interval map, and + // fallback to value 0 if a hash value is not found. + return VTableAddrMap.lookup(Address, 0); +} + uint64_t InstrProfSymtab::getFunctionHashFromAddress(uint64_t Address) { finalizeSymtab(); auto It = partition_point(AddrToMD5Map, [=](std::pair<uint64_t, uint64_t> A) { @@ -636,6 +678,16 @@ Error collectPGOFuncNameStrings(ArrayRef<GlobalVariable *> NameVars, NameStrs, compression::zlib::isAvailable() && doCompression, Result); } +Error collectVTableStrings(ArrayRef<GlobalVariable *> VTables, + std::string &Result, bool doCompression) { + std::vector<std::string> VTableNameStrs; + for (auto *VTable : VTables) + VTableNameStrs.push_back(getPGOName(*VTable)); + return collectGlobalObjectNameStrings( + VTableNameStrs, compression::zlib::isAvailable() && doCompression, + Result); +} + void InstrProfRecord::accumulateCounts(CountSumOrPercent &Sum) const { uint64_t FuncSum = 0; Sum.NumEntries += Counts.size(); @@ -898,6 +950,9 @@ uint64_t InstrProfRecord::remapValue(uint64_t Value, uint32_t ValueKind, if (ValueKind == IPVK_IndirectCallTarget) return SymTab->getFunctionHashFromAddress(Value); + if (ValueKind == IPVK_VTableTarget) + return SymTab->getVTableHashFromAddress(Value); + return Value; } @@ -1216,46 +1271,44 @@ void annotateValueSite(Module &M, Instruction &Inst, Inst.setMetadata(LLVMContext::MD_prof, MDNode::get(Ctx, Vals)); } -bool getValueProfDataFromInst(const Instruction &Inst, - InstrProfValueKind ValueKind, - uint32_t MaxNumValueData, - InstrProfValueData ValueData[], - uint32_t &ActualNumValueData, uint64_t &TotalC, - bool GetNoICPValue) { +MDNode *mayHaveValueProfileOfKind(const Instruction &Inst, + InstrProfValueKind ValueKind) { MDNode *MD = Inst.getMetadata(LLVMContext::MD_prof); if (!MD) - return false; - - unsigned NOps = MD->getNumOperands(); + return nullptr; - if (NOps < 5) - return false; + if (MD->getNumOperands() < 5) + return nullptr; - // Operand 0 is a string tag "VP": MDString *Tag = cast<MDString>(MD->getOperand(0)); - if (!Tag) - return false; - - if (!Tag->getString().equals("VP")) - return false; + if (!Tag || !Tag->getString().equals("VP")) + return nullptr; // Now check kind: ConstantInt *KindInt = mdconst::dyn_extract<ConstantInt>(MD->getOperand(1)); if (!KindInt) - return false; + return nullptr; if (KindInt->getZExtValue() != ValueKind) - return false; + return nullptr; + + return MD; +} +static bool getValueProfDataFromInstImpl(const MDNode *const MD, + const uint32_t MaxNumDataWant, + InstrProfValueData ValueData[], + uint32_t &ActualNumValueData, + uint64_t &TotalC, bool GetNoICPValue) { + const unsigned NOps = MD->getNumOperands(); // Get total count ConstantInt *TotalCInt = mdconst::dyn_extract<ConstantInt>(MD->getOperand(2)); if (!TotalCInt) return false; TotalC = TotalCInt->getZExtValue(); - ActualNumValueData = 0; for (unsigned I = 3; I < NOps; I += 2) { - if (ActualNumValueData >= MaxNumValueData) + if (ActualNumValueData >= MaxNumDataWant) break; ConstantInt *Value = mdconst::dyn_extract<ConstantInt>(MD->getOperand(I)); ConstantInt *Count = @@ -1272,6 +1325,36 @@ bool getValueProfDataFromInst(const Instruction &Inst, return true; } +std::unique_ptr<InstrProfValueData[]> +getValueProfDataFromInst(const Instruction &Inst, InstrProfValueKind ValueKind, + uint32_t MaxNumValueData, uint32_t &ActualNumValueData, + uint64_t &TotalC, bool GetNoICPValue) { + MDNode *MD = mayHaveValueProfileOfKind(Inst, ValueKind); + if (!MD) + return nullptr; + auto ValueDataArray = std::make_unique<InstrProfValueData[]>(MaxNumValueData); + if (!getValueProfDataFromInstImpl(MD, MaxNumValueData, ValueDataArray.get(), + ActualNumValueData, TotalC, GetNoICPValue)) + return nullptr; + return ValueDataArray; +} + +// FIXME: Migrate existing callers to the function above that returns an +// array. +bool getValueProfDataFromInst(const Instruction &Inst, + InstrProfValueKind ValueKind, + uint32_t MaxNumValueData, + InstrProfValueData ValueData[], + uint32_t &ActualNumValueData, uint64_t &TotalC, + bool GetNoICPValue) { + MDNode *MD = mayHaveValueProfileOfKind(Inst, ValueKind); + if (!MD) + return false; + return getValueProfDataFromInstImpl(MD, MaxNumValueData, ValueData, + ActualNumValueData, TotalC, + GetNoICPValue); +} + MDNode *getPGOFuncNameMetadata(const Function &F) { return F.getMetadata(getPGOFuncNameMetadataName()); } @@ -1288,8 +1371,8 @@ void createPGOFuncNameMetadata(Function &F, StringRef PGOFuncName) { F.setMetadata(getPGOFuncNameMetadataName(), N); } -bool needsComdatForCounter(const Function &F, const Module &M) { - if (F.hasComdat()) +bool needsComdatForCounter(const GlobalObject &GO, const Module &M) { + if (GO.hasComdat()) return true; if (!Triple(M.getTargetTriple()).supportsCOMDAT()) @@ -1305,7 +1388,7 @@ bool needsComdatForCounter(const Function &F, const Module &M) { // available_externally functions will end up being duplicated in raw profile // data. This can result in distorted profile as the counts of those dups // will be accumulated by the profile merger. - GlobalValue::LinkageTypes Linkage = F.getLinkage(); + GlobalValue::LinkageTypes Linkage = GO.getLinkage(); if (Linkage != GlobalValue::ExternalWeakLinkage && Linkage != GlobalValue::AvailableExternallyLinkage) return false; @@ -1461,7 +1544,7 @@ void OverlapStats::dump(raw_fd_ostream &OS) const { for (unsigned I = 0; I < IPVK_Last - IPVK_First + 1; I++) { if (Base.ValueCounts[I] < 1.0f && Test.ValueCounts[I] < 1.0f) continue; - char ProfileKindName[20]; + char ProfileKindName[20] = {0}; switch (I) { case IPVK_IndirectCallTarget: strncpy(ProfileKindName, "IndirectCall", 19); @@ -1469,6 +1552,9 @@ void OverlapStats::dump(raw_fd_ostream &OS) const { case IPVK_MemOPSize: strncpy(ProfileKindName, "MemOP", 19); break; + case IPVK_VTableTarget: + strncpy(ProfileKindName, "VTable", 19); + break; default: snprintf(ProfileKindName, 19, "VP[%d]", I); break; diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp index 31b742bca14d6fb5961bee6e83887d6eec988e7a..7ac5c561dc080960f97656e385e31bf0a31cfa7c 100644 --- a/llvm/lib/ProfileData/InstrProfReader.cpp +++ b/llvm/lib/ProfileData/InstrProfReader.cpp @@ -24,6 +24,7 @@ #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorOr.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SwapByteOrder.h" #include "llvm/Support/VirtualFileSystem.h" @@ -369,8 +370,11 @@ TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) { } else if (ValueKind == IPVK_VTableTarget) { if (InstrProfSymtab::isExternalSymbol(VD.first)) Value = 0; - else + else { + if (Error E = Symtab->addVTableName(VD.first)) + return E; Value = IndexedInstrProf::ComputeHash(VD.first); + } } else { READ_NUM(VD.first, Value); } @@ -538,7 +542,8 @@ Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) { template <class IntPtrT> Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) { - if (Error E = Symtab.create(StringRef(NamesStart, NamesEnd - NamesStart))) + if (Error E = Symtab.create(StringRef(NamesStart, NamesEnd - NamesStart), + StringRef(VNamesStart, VNamesEnd - VNamesStart))) return error(std::move(E)); for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) { const IntPtrT FPtr = swap(I->FunctionPointer); @@ -546,6 +551,21 @@ Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) { continue; Symtab.mapAddress(FPtr, swap(I->NameRef)); } + + if (VTableBegin != nullptr && VTableEnd != nullptr) { + for (const RawInstrProf::VTableProfileData<IntPtrT> *I = VTableBegin; + I != VTableEnd; ++I) { + const IntPtrT VPtr = swap(I->VTablePointer); + if (!VPtr) + continue; + // Map both begin and end address to the name hash, since the instrumented + // address could be somewhere in the middle. + // VPtr is of type uint32_t or uint64_t so 'VPtr + I->VTableSize' marks + // the end of vtable address. + Symtab.mapVTableAddress(VPtr, VPtr + swap(I->VTableSize), + swap(I->VTableNameHash)); + } + } return success(); } @@ -1230,10 +1250,39 @@ Error IndexedInstrProfReader::readHeader() { Header->MemProfOffset); const unsigned char *Ptr = Start + MemProfOffset; - // The value returned from RecordTableGenerator.Emit. - const uint64_t RecordTableOffset = + + // Read the first 64-bit word, which may be RecordTableOffset in + // memprof::MemProfVersion0 or the MemProf version number in + // memprof::MemProfVersion1. + const uint64_t FirstWord = support::endian::readNext<uint64_t, llvm::endianness::little, unaligned>(Ptr); + + memprof::IndexedVersion Version = memprof::Version0; + if (FirstWord == memprof::Version1) { + // Everything is good. We can proceed to deserialize the rest. + Version = memprof::Version1; + } else if (FirstWord >= 24) { + // This is a heuristic/hack to detect memprof::MemProfVersion0, + // which does not have a version field in the header. + // In memprof::MemProfVersion0, FirstWord will be RecordTableOffset, + // which should be at least 24 because of the MemProf header size. + Version = memprof::Version0; + } else { + return make_error<InstrProfError>( + instrprof_error::unsupported_version, + formatv("MemProf version {} not supported; " + "requires version between {} and {}, inclusive", + FirstWord, memprof::MinimumSupportedVersion, + memprof::MaximumSupportedVersion)); + } + + // The value returned from RecordTableGenerator.Emit. + const uint64_t RecordTableOffset = + Version == memprof::Version0 + ? FirstWord + : support::endian::readNext<uint64_t, llvm::endianness::little, + unaligned>(Ptr); // The offset in the stream right before invoking // FrameTableGenerator.Emit. const uint64_t FramePayloadOffset = @@ -1261,6 +1310,14 @@ Error IndexedInstrProfReader::readHeader() { /*Buckets=*/Start + FrameTableOffset, /*Payload=*/Start + FramePayloadOffset, /*Base=*/Start, memprof::FrameLookupTrait())); + +#ifdef EXPENSIVE_CHECKS + // Go through all the records and verify that CSId has been correctly + // populated. Do this only under EXPENSIVE_CHECKS. Otherwise, we + // would defeat the purpose of OnDiskIterableChainedHashTable. + for (const auto &Record : MemProfRecordTable->data()) + verifyIndexedMemProfRecord(Record); +#endif } // BinaryIdOffset field in the header is only valid when the format version @@ -1359,7 +1416,15 @@ InstrProfSymtab &IndexedInstrProfReader::getSymtab() { if (Symtab) return *Symtab; - std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>(); + auto NewSymtab = std::make_unique<InstrProfSymtab>(); + + if (Error E = NewSymtab->initVTableNamesFromCompressedStrings( + StringRef(VTableNamePtr, CompressedVTableNamesLen))) { + auto [ErrCode, Msg] = InstrProfError::take(std::move(E)); + consumeError(error(ErrCode, Msg)); + } + + // finalizeSymtab is called inside populateSymtab. if (Error E = Index->populateSymtab(*NewSymtab)) { auto [ErrCode, Msg] = InstrProfError::take(std::move(E)); consumeError(error(ErrCode, Msg)); diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp index e757c735719b1f3cdbbfd676a91270bb7d4e6bc9..c2c94ba30c6583ea758071c86c64c7915b7b9d55 100644 --- a/llvm/lib/ProfileData/InstrProfWriter.cpp +++ b/llvm/lib/ProfileData/InstrProfWriter.cpp @@ -19,9 +19,11 @@ #include "llvm/ProfileData/InstrProf.h" #include "llvm/ProfileData/MemProf.h" #include "llvm/ProfileData/ProfileCommon.h" +#include "llvm/Support/Compression.h" #include "llvm/Support/Endian.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/Error.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/OnDiskHashTable.h" #include "llvm/Support/raw_ostream.h" @@ -60,16 +62,16 @@ public: // \c patch can only be called when all data is written and flushed. // For raw_string_ostream, the patch is done on the target string // directly and it won't be reflected in the stream's internal buffer. - void patch(PatchItem *P, int NItems) { + void patch(ArrayRef<PatchItem> P) { using namespace support; if (IsFDOStream) { raw_fd_ostream &FDOStream = static_cast<raw_fd_ostream &>(OS); const uint64_t LastPos = FDOStream.tell(); - for (int K = 0; K < NItems; K++) { - FDOStream.seek(P[K].Pos); - for (int I = 0; I < P[K].N; I++) - write(P[K].D[I]); + for (const auto &K : P) { + FDOStream.seek(K.Pos); + for (int I = 0; I < K.N; I++) + write(K.D[I]); } // Reset the stream to the last position after patching so that users // don't accidentally overwrite data. This makes it consistent with @@ -78,11 +80,11 @@ public: } else { raw_string_ostream &SOStream = static_cast<raw_string_ostream &>(OS); std::string &Data = SOStream.str(); // with flush - for (int K = 0; K < NItems; K++) { - for (int I = 0; I < P[K].N; I++) { + for (const auto &K : P) { + for (int I = 0; I < K.N; I++) { uint64_t Bytes = - endian::byte_swap<uint64_t, llvm::endianness::little>(P[K].D[I]); - Data.replace(P[K].Pos + I * sizeof(uint64_t), sizeof(uint64_t), + endian::byte_swap<uint64_t, llvm::endianness::little>(K.D[I]); + Data.replace(K.Pos + I * sizeof(uint64_t), sizeof(uint64_t), (const char *)&Bytes, sizeof(uint64_t)); } } @@ -179,14 +181,15 @@ public: } // end namespace llvm -InstrProfWriter::InstrProfWriter(bool Sparse, - uint64_t TemporalProfTraceReservoirSize, - uint64_t MaxTemporalProfTraceLength, - bool WritePrevVersion) +InstrProfWriter::InstrProfWriter( + bool Sparse, uint64_t TemporalProfTraceReservoirSize, + uint64_t MaxTemporalProfTraceLength, bool WritePrevVersion, + memprof::IndexedVersion MemProfVersionRequested) : Sparse(Sparse), MaxTemporalProfTraceLength(MaxTemporalProfTraceLength), TemporalProfTraceReservoirSize(TemporalProfTraceReservoirSize), InfoObj(new InstrProfRecordWriterTrait()), - WritePrevVersion(WritePrevVersion) {} + WritePrevVersion(WritePrevVersion), + MemProfVersionRequested(MemProfVersionRequested) {} InstrProfWriter::~InstrProfWriter() { delete InfoObj; } @@ -516,6 +519,7 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) { // Write the MemProf profile data if we have it. This includes a simple schema // with the format described below followed by the hashtable: + // uint64_t Version // uint64_t RecordTableOffset = RecordTableGenerator.Emit // uint64_t FramePayloadOffset = Stream offset before emitting the frame table // uint64_t FrameTableOffset = FrameTableGenerator.Emit @@ -528,7 +532,21 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) { // OnDiskChainedHashTable MemProfFrameData uint64_t MemProfSectionStart = 0; if (static_cast<bool>(ProfileKind & InstrProfKind::MemProf)) { + if (MemProfVersionRequested < memprof::MinimumSupportedVersion || + MemProfVersionRequested > memprof::MaximumSupportedVersion) { + return make_error<InstrProfError>( + instrprof_error::unsupported_version, + formatv("MemProf version {} not supported; " + "requires version between {} and {}, inclusive", + MemProfVersionRequested, memprof::MinimumSupportedVersion, + memprof::MaximumSupportedVersion)); + } + MemProfSectionStart = OS.tell(); + + if (MemProfVersionRequested >= memprof::Version1) + OS.write(MemProfVersionRequested); + OS.write(0ULL); // Reserve space for the memprof record table offset. OS.write(0ULL); // Reserve space for the memprof frame payload offset. OS.write(0ULL); // Reserve space for the memprof frame table offset. @@ -570,12 +588,13 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) { uint64_t FrameTableOffset = FrameTableGenerator.Emit(OS.OS, *FrameWriter); - PatchItem PatchItems[] = { - {MemProfSectionStart, &RecordTableOffset, 1}, - {MemProfSectionStart + sizeof(uint64_t), &FramePayloadOffset, 1}, - {MemProfSectionStart + 2 * sizeof(uint64_t), &FrameTableOffset, 1}, - }; - OS.patch(PatchItems, 3); + uint64_t Header[] = {RecordTableOffset, FramePayloadOffset, + FrameTableOffset}; + uint64_t HeaderUpdatePos = MemProfSectionStart; + if (MemProfVersionRequested >= memprof::Version1) + // The updates go just after the version field. + HeaderUpdatePos += sizeof(uint64_t); + OS.patch({{HeaderUpdatePos, Header, std::size(Header)}}); } // BinaryIdSection has two parts: @@ -618,13 +637,18 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) { uint64_t VTableNamesSectionStart = OS.tell(); if (!WritePrevVersion) { - // Use a dummy (and uncompressed) string as compressed vtable names and get - // the necessary profile format change in place for version 12. - // TODO: Store the list of vtable names in InstrProfWriter and use the - // real compressed name. - std::string CompressedVTableNames = "VTableNames"; + std::vector<std::string> VTableNameStrs; + for (StringRef VTableName : VTableNames.keys()) + VTableNameStrs.push_back(VTableName.str()); + + std::string CompressedVTableNames; + if (!VTableNameStrs.empty()) + if (Error E = collectGlobalObjectNameStrings( + VTableNameStrs, compression::zlib::isAvailable(), + CompressedVTableNames)) + return E; - uint64_t CompressedStringLen = CompressedVTableNames.length(); + const uint64_t CompressedStringLen = CompressedVTableNames.length(); // Record the length of compressed string. OS.write(CompressedStringLen); @@ -634,12 +658,11 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) { OS.writeByte(static_cast<uint8_t>(c)); // Pad up to a multiple of 8. - // InstrProfReader would read bytes according to 'CompressedStringLen'. - uint64_t PaddedLength = alignTo(CompressedStringLen, 8); + // InstrProfReader could read bytes according to 'CompressedStringLen'. + const uint64_t PaddedLength = alignTo(CompressedStringLen, 8); - for (uint64_t K = CompressedStringLen; K < PaddedLength; K++) { + for (uint64_t K = CompressedStringLen; K < PaddedLength; K++) OS.writeByte(0); - } } uint64_t TemporalProfTracesSectionStart = 0; @@ -693,7 +716,7 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) { {CSSummaryOffset, reinterpret_cast<uint64_t *>(TheCSSummary.get()), (int)CSSummarySize}}; - OS.patch(PatchItems, std::size(PatchItems)); + OS.patch(PatchItems); } else { // Now do the final patch: PatchItem PatchItems[] = { @@ -713,7 +736,7 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) { {CSSummaryOffset, reinterpret_cast<uint64_t *>(TheCSSummary.get()), (int)CSSummarySize}}; - OS.patch(PatchItems, std::size(PatchItems)); + OS.patch(PatchItems); } for (const auto &I : FunctionData) @@ -848,6 +871,10 @@ Error InstrProfWriter::writeText(raw_fd_ostream &OS) { } } + for (const auto &VTableName : VTableNames) + if (Error E = Symtab.addVTableName(VTableName.getKey())) + return E; + if (static_cast<bool>(ProfileKind & InstrProfKind::TemporalProfile)) writeTextTemporalProfTraceData(OS, Symtab); diff --git a/llvm/lib/ProfileData/MemProf.cpp b/llvm/lib/ProfileData/MemProf.cpp index 0461f0e9f840789d7b65d87e31d4839b53d96bf3..6c419811d59e2f1dcc3332c09eff78a448f2a9ad 100644 --- a/llvm/lib/ProfileData/MemProf.cpp +++ b/llvm/lib/ProfileData/MemProf.cpp @@ -3,8 +3,10 @@ #include "llvm/IR/Function.h" #include "llvm/ProfileData/InstrProf.h" #include "llvm/ProfileData/SampleProf.h" +#include "llvm/Support/BLAKE3.h" #include "llvm/Support/Endian.h" #include "llvm/Support/EndianStream.h" +#include "llvm/Support/HashBuilder.h" namespace llvm { namespace memprof { @@ -51,6 +53,7 @@ IndexedMemProfRecord::deserialize(const MemProfSchema &Schema, endian::readNext<FrameId, llvm::endianness::little, unaligned>(Ptr); Node.CallStack.push_back(Id); } + Node.CSId = hashCallStack(Node.CallStack); Node.Info.deserialize(Schema, Ptr); Ptr += PortableMemInfoBlock::serializedSize(); Record.AllocSites.push_back(Node); @@ -117,5 +120,32 @@ Expected<MemProfSchema> readMemProfSchema(const unsigned char *&Buffer) { return Result; } +CallStackId hashCallStack(ArrayRef<FrameId> CS) { + llvm::HashBuilder<llvm::TruncatedBLAKE3<8>, llvm::endianness::little> + HashBuilder; + for (FrameId F : CS) + HashBuilder.add(F); + llvm::BLAKE3Result<8> Hash = HashBuilder.final(); + CallStackId CSId; + std::memcpy(&CSId, Hash.data(), sizeof(Hash)); + return CSId; +} + +void verifyIndexedMemProfRecord(const IndexedMemProfRecord &Record) { + for (const auto &AS : Record.AllocSites) { + assert(AS.CSId == hashCallStack(AS.CallStack)); + (void)AS; + } +} + +void verifyFunctionProfileData( + const llvm::MapVector<GlobalValue::GUID, IndexedMemProfRecord> + &FunctionProfileData) { + for (const auto &[GUID, Record] : FunctionProfileData) { + (void)GUID; + verifyIndexedMemProfRecord(Record); + } +} + } // namespace memprof } // namespace llvm diff --git a/llvm/lib/ProfileData/RawMemProfReader.cpp b/llvm/lib/ProfileData/RawMemProfReader.cpp index 0e2b8668bab72c9b7d4dcb096e728a2c64eae0ba..5dc1ff8978154c53bd00500a920e733c7d26e935 100644 --- a/llvm/lib/ProfileData/RawMemProfReader.cpp +++ b/llvm/lib/ProfileData/RawMemProfReader.cpp @@ -127,6 +127,7 @@ CallStackMap readStackInfo(const char *Ptr) { endian::readNext<uint64_t, llvm::endianness::little, unaligned>(Ptr); SmallVector<uint64_t> CallStack; + CallStack.reserve(NumPCs); for (uint64_t J = 0; J < NumPCs; J++) { CallStack.push_back( endian::readNext<uint64_t, llvm::endianness::little, unaligned>(Ptr)); @@ -445,6 +446,8 @@ Error RawMemProfReader::mapRawProfileToRecords() { Callstack.append(Frames.begin(), Frames.end()); } + CallStackId CSId = hashCallStack(Callstack); + // We attach the memprof record to each function bottom-up including the // first non-inline frame. for (size_t I = 0; /*Break out using the condition below*/; I++) { @@ -452,7 +455,7 @@ Error RawMemProfReader::mapRawProfileToRecords() { auto Result = FunctionProfileData.insert({F.Function, IndexedMemProfRecord()}); IndexedMemProfRecord &Record = Result.first->second; - Record.AllocSites.emplace_back(Callstack, Entry.second); + Record.AllocSites.emplace_back(Callstack, CSId, Entry.second); if (!F.IsInlineFrame) break; @@ -470,6 +473,8 @@ Error RawMemProfReader::mapRawProfileToRecords() { } } + verifyFunctionProfileData(FunctionProfileData); + return Error::success(); } diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp index e686b9765233020bda1a0ec7e3266ba67a4eb496..c20609748dc97c1aedb68cc3ec2d5ce2c4364af2 100644 --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -2022,6 +2022,13 @@ APInt APInt::ushl_ov(unsigned ShAmt, bool &Overflow) const { return *this << ShAmt; } +APInt APInt::sfloordiv_ov(const APInt &RHS, bool &Overflow) const { + APInt quotient = sdiv_ov(RHS, Overflow); + if ((quotient * RHS != *this) && (isNegative() != RHS.isNegative())) + return quotient - 1; + return quotient; +} + APInt APInt::sadd_sat(const APInt &RHS) const { bool Overflow; APInt Res = sadd_ov(RHS, Overflow); @@ -3094,3 +3101,39 @@ void llvm::LoadIntFromMemory(APInt &IntVal, const uint8_t *Src, memcpy(Dst + sizeof(uint64_t) - LoadBytes, Src, LoadBytes); } } + +APInt APIntOps::avgFloorS(const APInt &C1, const APInt &C2) { + // Return floor((C1 + C2) / 2) + return (C1 & C2) + (C1 ^ C2).ashr(1); +} + +APInt APIntOps::avgFloorU(const APInt &C1, const APInt &C2) { + // Return floor((C1 + C2) / 2) + return (C1 & C2) + (C1 ^ C2).lshr(1); +} + +APInt APIntOps::avgCeilS(const APInt &C1, const APInt &C2) { + // Return ceil((C1 + C2) / 2) + return (C1 | C2) - (C1 ^ C2).ashr(1); +} + +APInt APIntOps::avgCeilU(const APInt &C1, const APInt &C2) { + // Return ceil((C1 + C2) / 2) + return (C1 | C2) - (C1 ^ C2).lshr(1); +} + +APInt APIntOps::mulhs(const APInt &C1, const APInt &C2) { + assert(C1.getBitWidth() == C2.getBitWidth() && "Unequal bitwidths"); + unsigned FullWidth = C1.getBitWidth() * 2; + APInt C1Ext = C1.sext(FullWidth); + APInt C2Ext = C2.sext(FullWidth); + return (C1Ext * C2Ext).extractBits(C1.getBitWidth(), C1.getBitWidth()); +} + +APInt APIntOps::mulhu(const APInt &C1, const APInt &C2) { + assert(C1.getBitWidth() == C2.getBitWidth() && "Unequal bitwidths"); + unsigned FullWidth = C1.getBitWidth() * 2; + APInt C1Ext = C1.zext(FullWidth); + APInt C2Ext = C2.zext(FullWidth); + return (C1Ext * C2Ext).extractBits(C1.getBitWidth(), C1.getBitWidth()); +} diff --git a/llvm/lib/Support/BalancedPartitioning.cpp b/llvm/lib/Support/BalancedPartitioning.cpp index f4254b50d26c91487259d7ae214f4ec8cd19df9b..141f0034a23f0471ea205609a24212aeec543912 100644 --- a/llvm/lib/Support/BalancedPartitioning.cpp +++ b/llvm/lib/Support/BalancedPartitioning.cpp @@ -136,7 +136,7 @@ void BalancedPartitioning::bisect(const FunctionNodeRange Nodes, // Split into two and assign to the left and right buckets split(Nodes, LeftBucket); - runIterations(Nodes, RecDepth, LeftBucket, RightBucket, RNG); + runIterations(Nodes, LeftBucket, RightBucket, RNG); // Split nodes wrt the resulting buckets auto NodesMid = @@ -163,7 +163,7 @@ void BalancedPartitioning::bisect(const FunctionNodeRange Nodes, } void BalancedPartitioning::runIterations(const FunctionNodeRange Nodes, - unsigned RecDepth, unsigned LeftBucket, + unsigned LeftBucket, unsigned RightBucket, std::mt19937 &RNG) const { unsigned NumNodes = std::distance(Nodes.begin(), Nodes.end()); diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt index 1f2d82427552f7e3511013bb9e9cd65095670ce0..e18beddf7bc5b7f77aad45511fbf4fbde86535ff 100644 --- a/llvm/lib/Support/CMakeLists.txt +++ b/llvm/lib/Support/CMakeLists.txt @@ -188,6 +188,8 @@ add_llvm_component_library(LLVMSupport GlobPattern.cpp GraphWriter.cpp Hashing.cpp + HexagonAttributeParser.cpp + HexagonAttributes.cpp InitLLVM.cpp InstructionCost.cpp IntEqClasses.cpp diff --git a/llvm/lib/Support/FormatVariadic.cpp b/llvm/lib/Support/FormatVariadic.cpp index 91b4c38ade4fac9efa88325c8459dcf28fd4f118..3c07a80a00ae6d71c7d5241ec111fe7c3914b109 100644 --- a/llvm/lib/Support/FormatVariadic.cpp +++ b/llvm/lib/Support/FormatVariadic.cpp @@ -152,4 +152,4 @@ formatv_object_base::parseFormatString(StringRef Fmt) { return Replacements; } -void detail::format_adapter::anchor() { } +void support::detail::format_adapter::anchor() {} diff --git a/llvm/lib/Support/FormattedStream.cpp b/llvm/lib/Support/FormattedStream.cpp index c0d28435099570a90278e112fabc8960ff29f52d..c50530e76efc0a37112d31613ce19655ec12f1bf 100644 --- a/llvm/lib/Support/FormattedStream.cpp +++ b/llvm/lib/Support/FormattedStream.cpp @@ -94,6 +94,9 @@ void formatted_raw_ostream::UpdatePosition(const char *Ptr, size_t Size) { /// ComputePosition - Examine the current output and update line and column /// counts. void formatted_raw_ostream::ComputePosition(const char *Ptr, size_t Size) { + if (DisableScan) + return; + // If our previous scan pointer is inside the buffer, assume we already // scanned those bytes. This depends on raw_ostream to not change our buffer // in unexpected ways. diff --git a/llvm/lib/Support/HexagonAttributeParser.cpp b/llvm/lib/Support/HexagonAttributeParser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2143162d11c79c2b9f4da20a89a94105c4e88662 --- /dev/null +++ b/llvm/lib/Support/HexagonAttributeParser.cpp @@ -0,0 +1,55 @@ +//===-- HexagonAttributeParser.cpp - Hexagon Attribute Parser -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/HexagonAttributeParser.h" + +using namespace llvm; + +const HexagonAttributeParser::DisplayHandler + HexagonAttributeParser::DisplayRoutines[] = { + { + HexagonAttrs::ARCH, + &ELFAttributeParser::integerAttribute, + }, + { + HexagonAttrs::HVXARCH, + &ELFAttributeParser::integerAttribute, + }, + { + HexagonAttrs::HVXIEEEFP, + &ELFAttributeParser::integerAttribute, + }, + { + HexagonAttrs::HVXQFLOAT, + &ELFAttributeParser::integerAttribute, + }, + { + HexagonAttrs::ZREG, + &ELFAttributeParser::integerAttribute, + }, + { + HexagonAttrs::AUDIO, + &ELFAttributeParser::integerAttribute, + }, + { + HexagonAttrs::CABAC, + &ELFAttributeParser::integerAttribute, + }}; + +Error HexagonAttributeParser::handler(uint64_t Tag, bool &Handled) { + Handled = false; + for (const auto &R : DisplayRoutines) { + if (uint64_t(R.Attribute) == Tag) { + if (Error E = (this->*R.Routine)(Tag)) + return E; + Handled = true; + break; + } + } + return Error::success(); +} diff --git a/llvm/lib/Support/HexagonAttributes.cpp b/llvm/lib/Support/HexagonAttributes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..165215c8fb676a306e23885bf71487eb5f177b12 --- /dev/null +++ b/llvm/lib/Support/HexagonAttributes.cpp @@ -0,0 +1,27 @@ +//===-- HexagonAttributes.cpp - Qualcomm Hexagon Attributes ---------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/HexagonAttributes.h" + +using namespace llvm; +using namespace llvm::HexagonAttrs; + +static constexpr TagNameItem TagData[] = { + {ARCH, "Tag_arch"}, + {HVXARCH, "Tag_hvx_arch"}, + {HVXIEEEFP, "Tag_hvx_ieeefp"}, + {HVXQFLOAT, "Tag_hvx_qfloat"}, + {ZREG, "Tag_zreg"}, + {AUDIO, "Tag_audio"}, + {CABAC, "Tag_cabac"}, +}; + +constexpr TagNameMap HexagonAttributeTags{TagData}; +const TagNameMap &llvm::HexagonAttrs::getHexagonAttributeTags() { + return HexagonAttributeTags; +} diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp index 6eec03fd6f70829a7ba8f4e8f87c978716d7f7ff..67e6e5b962b1a9323e6c92a501ace90e0a12555a 100644 --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -36,6 +36,11 @@ struct RISCVSupportedExtension { } }; +struct RISCVProfile { + StringLiteral Name; + StringLiteral MArch; +}; + } // end anonymous namespace static constexpr StringLiteral AllStdExts = "mafdqlcbkjtpvnh"; @@ -90,11 +95,14 @@ static const RISCVSupportedExtension SupportedExtensions[] = { {"xcvmac", {1, 0}}, {"xcvmem", {1, 0}}, {"xcvsimd", {1, 0}}, + {"xsfcease", {1, 0}}, {"xsfvcp", {1, 0}}, {"xsfvfnrclipxfqf", {1, 0}}, {"xsfvfwmaccqqq", {1, 0}}, {"xsfvqmaccdod", {1, 0}}, {"xsfvqmaccqoq", {1, 0}}, + {"xsifivecdiscarddlone", {1, 0}}, + {"xsifivecflushdlone", {1, 0}}, {"xtheadba", {1, 0}}, {"xtheadbb", {1, 0}}, {"xtheadbs", {1, 0}}, @@ -241,6 +249,42 @@ static const RISCVSupportedExtension SupportedExperimentalExtensions[] = { }; // clang-format on +static constexpr RISCVProfile SupportedProfiles[] = { + {"rvi20u32", "rv32i"}, + {"rvi20u64", "rv64i"}, + {"rva20u64", "rv64imafdc_ziccamoa_ziccif_zicclsm_ziccrse_zicntr_za128rs"}, + {"rva20s64", "rv64imafdc_ziccamoa_ziccif_zicclsm_ziccrse_zicntr_zifencei_" + "za128rs_ssccptr_sstvala_sstvecd_svade_svbare"}, + {"rva22u64", + "rv64imafdc_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_" + "zicntr_zihintpause_zihpm_za64rs_zfhmin_zba_zbb_zbs_zkt"}, + {"rva22s64", + "rv64imafdc_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_" + "zicntr_zifencei_zihintpause_zihpm_za64rs_zfhmin_zba_zbb_zbs_zkt_ssccptr_" + "sscounterenw_sstvala_sstvecd_svade_svbare_svinval_svpbmt"}, + {"rva23u64", + "rv64imafdcv_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_" + "zicntr_zicond_zihintntl_zihintpause_zihpm_zimop0p1_za64rs_zawrs_zfa_" + "zfhmin_zcb_zcmop0p2_zba_zbb_zbs_zkt_zvbb_zvfhmin_zvkt"}, + {"rva23s64", + "rv64imafdcvh_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_" + "zicntr_zicond_zifencei_zihintntl_zihintpause_zihpm_zimop0p1_za64rs_zawrs_" + "zfa_zfhmin_zcb_zcmop0p2_zba_zbb_zbs_zkt_zvbb_zvfhmin_zvkt_shcounterenw_" + "shgatpa_shtvala_shvsatpa_shvstvala_shvstvecd_ssccptr_sscofpmf_" + "sscounterenw_ssnpm0p8_ssstateen_sstc_sstvala_sstvecd_ssu64xl_svade_" + "svbare_svinval_svnapot_svpbmt"}, + {"rvb23u64", "rv64imafdc_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_" + "zicclsm_ziccrse_zicntr_zicond_zihintntl_zihintpause_zihpm_" + "zimop0p1_za64rs_zawrs_zfa_zcb_zcmop0p2_zba_zbb_zbs_zkt"}, + {"rvb23s64", + "rv64imafdc_zic64b_zicbom_zicbop_zicboz_ziccamoa_ziccif_zicclsm_ziccrse_" + "zicntr_zicond_zifencei_zihintntl_zihintpause_zihpm_zimop0p1_za64rs_zawrs_" + "zfa_zcb_zcmop0p2_zba_zbb_zbs_zkt_ssccptr_sscofpmf_sscounterenw_sstc_" + "sstvala_sstvecd_ssu64xl_svade_svbare_svinval_svnapot_svpbmt"}, + {"rvm23u32", "rv32im_zicbop_zicond_zicsr_zihintntl_zihintpause_zimop0p1_" + "zca_zcb_zce_zcmop0p2_zcmp_zcmt_zba_zbb_zbs"}, +}; + static void verifyTables() { #ifndef NDEBUG static std::atomic<bool> TableChecked(false); @@ -258,7 +302,7 @@ static void PrintExtension(StringRef Name, StringRef Version, StringRef Description) { outs().indent(4); unsigned VersionWidth = Description.empty() ? 0 : 10; - outs() << left_justify(Name, 20) << left_justify(Version, VersionWidth) + outs() << left_justify(Name, 21) << left_justify(Version, VersionWidth) << Description << "\n"; } @@ -854,6 +898,29 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension, "string must be lowercase"); } + if (Arch.starts_with("rvi") || Arch.starts_with("rva") || + Arch.starts_with("rvb") || Arch.starts_with("rvm")) { + const auto *FoundProfile = + llvm::find_if(SupportedProfiles, [Arch](const RISCVProfile &Profile) { + return Arch.starts_with(Profile.Name); + }); + + if (FoundProfile == std::end(SupportedProfiles)) + return createStringError(errc::invalid_argument, "unsupported profile"); + + std::string NewArch = FoundProfile->MArch.str(); + StringRef ArchWithoutProfile = Arch.substr(FoundProfile->Name.size()); + if (!ArchWithoutProfile.empty()) { + if (!ArchWithoutProfile.starts_with("_")) + return createStringError( + errc::invalid_argument, + "additional extensions must be after separator '_'"); + NewArch += ArchWithoutProfile.str(); + } + return parseArchString(NewArch, EnableExperimentalExtension, + ExperimentalExtensionVersionCheck, IgnoreUnknown); + } + bool HasRV64 = Arch.starts_with("rv64"); // ISA string must begin with rv32 or rv64. if (!(Arch.starts_with("rv32") || HasRV64) || (Arch.size() < 5)) { diff --git a/llvm/lib/Support/TimeProfiler.cpp b/llvm/lib/Support/TimeProfiler.cpp index 4d625b3eb5b17092017c4501c72f81d9f6223789..092028dd2a5b343b2f95b790e2bc3aa3dff6c1fe 100644 --- a/llvm/lib/Support/TimeProfiler.cpp +++ b/llvm/lib/Support/TimeProfiler.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/TimeProfiler.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLFunctionalExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/JSON.h" @@ -20,6 +21,7 @@ #include <algorithm> #include <cassert> #include <chrono> +#include <memory> #include <mutex> #include <string> #include <vector> @@ -64,17 +66,19 @@ using CountAndDurationType = std::pair<size_t, DurationType>; using NameAndCountAndDurationType = std::pair<std::string, CountAndDurationType>; +} // anonymous namespace + /// Represents an open or completed time section entry to be captured. -struct TimeTraceProfilerEntry { +struct llvm::TimeTraceProfilerEntry { const TimePointType Start; TimePointType End; const std::string Name; const std::string Detail; - + const bool AsyncEvent = false; TimeTraceProfilerEntry(TimePointType &&S, TimePointType &&E, std::string &&N, - std::string &&Dt) + std::string &&Dt, bool Ae) : Start(std::move(S)), End(std::move(E)), Name(std::move(N)), - Detail(std::move(Dt)) {} + Detail(std::move(Dt)), AsyncEvent(Ae) {} // Calculate timings for FlameGraph. Cast time points to microsecond precision // rather than casting duration. This avoids truncation issues causing inner @@ -92,8 +96,6 @@ struct TimeTraceProfilerEntry { } }; -} // anonymous namespace - struct llvm::TimeTraceProfiler { TimeTraceProfiler(unsigned TimeTraceGranularity = 0, StringRef ProcName = "") : BeginningOfTime(system_clock::now()), StartTime(ClockType::now()), @@ -102,22 +104,23 @@ struct llvm::TimeTraceProfiler { llvm::get_thread_name(ThreadName); } - void begin(std::string Name, llvm::function_ref<std::string()> Detail) { - Stack.emplace_back(ClockType::now(), TimePointType(), std::move(Name), - Detail()); + TimeTraceProfilerEntry *begin(std::string Name, + llvm::function_ref<std::string()> Detail, + bool AsyncEvent = false) { + Stack.emplace_back(std::make_unique<TimeTraceProfilerEntry>( + ClockType::now(), TimePointType(), std::move(Name), Detail(), + AsyncEvent)); + return Stack.back().get(); } void end() { assert(!Stack.empty() && "Must call begin() first"); - TimeTraceProfilerEntry &E = Stack.back(); - E.End = ClockType::now(); + end(*Stack.back().get()); + } - // Check that end times monotonically increase. - assert((Entries.empty() || - (E.getFlameGraphStartUs(StartTime) + E.getFlameGraphDurUs() >= - Entries.back().getFlameGraphStartUs(StartTime) + - Entries.back().getFlameGraphDurUs())) && - "TimeProfiler scope ended earlier than previous scope"); + void end(TimeTraceProfilerEntry &E) { + assert(!Stack.empty() && "Must call begin() first"); + E.End = ClockType::now(); // Calculate duration at full precision for overall counts. DurationType Duration = E.End - E.Start; @@ -132,15 +135,18 @@ struct llvm::TimeTraceProfiler { // happens to be the ones that don't have any currently open entries above // itself. if (llvm::none_of(llvm::drop_begin(llvm::reverse(Stack)), - [&](const TimeTraceProfilerEntry &Val) { - return Val.Name == E.Name; + [&](const std::unique_ptr<TimeTraceProfilerEntry> &Val) { + return Val->Name == E.Name; })) { auto &CountAndTotal = CountAndTotalPerName[E.Name]; CountAndTotal.first++; CountAndTotal.second += Duration; - } + }; - Stack.pop_back(); + llvm::erase_if(Stack, + [&](const std::unique_ptr<TimeTraceProfilerEntry> &Val) { + return Val.get() == &E; + }); } // Write events from this TimeTraceProfilerInstance and @@ -168,14 +174,32 @@ struct llvm::TimeTraceProfiler { J.object([&] { J.attribute("pid", Pid); J.attribute("tid", int64_t(Tid)); - J.attribute("ph", "X"); J.attribute("ts", StartUs); - J.attribute("dur", DurUs); + if (E.AsyncEvent) { + J.attribute("cat", E.Name); + J.attribute("ph", "b"); + J.attribute("id", 0); + } else { + J.attribute("ph", "X"); + J.attribute("dur", DurUs); + } J.attribute("name", E.Name); if (!E.Detail.empty()) { J.attributeObject("args", [&] { J.attribute("detail", E.Detail); }); } }); + + if (E.AsyncEvent) { + J.object([&] { + J.attribute("pid", Pid); + J.attribute("tid", int64_t(Tid)); + J.attribute("ts", StartUs + DurUs); + J.attribute("cat", E.Name); + J.attribute("ph", "e"); + J.attribute("id", 0); + J.attribute("name", E.Name); + }); + } }; for (const TimeTraceProfilerEntry &E : Entries) writeEvent(E, this->Tid); @@ -269,7 +293,7 @@ struct llvm::TimeTraceProfiler { J.objectEnd(); } - SmallVector<TimeTraceProfilerEntry, 16> Stack; + SmallVector<std::unique_ptr<TimeTraceProfilerEntry>, 16> Stack; SmallVector<TimeTraceProfilerEntry, 128> Entries; StringMap<CountAndDurationType> CountAndTotalPerName; // System clock time when the session was begun. @@ -341,19 +365,36 @@ Error llvm::timeTraceProfilerWrite(StringRef PreferredFileName, return Error::success(); } -void llvm::timeTraceProfilerBegin(StringRef Name, StringRef Detail) { +TimeTraceProfilerEntry *llvm::timeTraceProfilerBegin(StringRef Name, + StringRef Detail) { if (TimeTraceProfilerInstance != nullptr) - TimeTraceProfilerInstance->begin(std::string(Name), - [&]() { return std::string(Detail); }); + return TimeTraceProfilerInstance->begin( + std::string(Name), [&]() { return std::string(Detail); }, false); + return nullptr; } -void llvm::timeTraceProfilerBegin(StringRef Name, - llvm::function_ref<std::string()> Detail) { +TimeTraceProfilerEntry * +llvm::timeTraceProfilerBegin(StringRef Name, + llvm::function_ref<std::string()> Detail) { if (TimeTraceProfilerInstance != nullptr) - TimeTraceProfilerInstance->begin(std::string(Name), Detail); + return TimeTraceProfilerInstance->begin(std::string(Name), Detail, false); + return nullptr; +} + +TimeTraceProfilerEntry *llvm::timeTraceAsyncProfilerBegin(StringRef Name, + StringRef Detail) { + if (TimeTraceProfilerInstance != nullptr) + return TimeTraceProfilerInstance->begin( + std::string(Name), [&]() { return std::string(Detail); }, true); + return nullptr; } void llvm::timeTraceProfilerEnd() { if (TimeTraceProfilerInstance != nullptr) TimeTraceProfilerInstance->end(); } + +void llvm::timeTraceProfilerEnd(TimeTraceProfilerEntry *E) { + if (TimeTraceProfilerInstance != nullptr) + TimeTraceProfilerInstance->end(*E); +} diff --git a/llvm/lib/Support/Unix/Threading.inc b/llvm/lib/Support/Unix/Threading.inc index 55e7dcfa4678cf14418df30bccb5a7d178cba481..839c00c5ebbf9690ed89cf979e46176139744400 100644 --- a/llvm/lib/Support/Unix/Threading.inc +++ b/llvm/lib/Support/Unix/Threading.inc @@ -115,8 +115,11 @@ uint64_t llvm::get_threadid() { // Calling "mach_thread_self()" bumps the reference count on the thread // port, so we need to deallocate it. mach_task_self() doesn't bump the ref // count. - thread_port_t Self = mach_thread_self(); - mach_port_deallocate(mach_task_self(), Self); + static thread_local thread_port_t Self = [] { + thread_port_t InitSelf = mach_thread_self(); + mach_port_deallocate(mach_task_self(), Self); + return InitSelf; + }(); return Self; #elif defined(__FreeBSD__) return uint64_t(pthread_getthreadid_np()); diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index 051dd2a67d120fda43894f97e86c351e7207510c..057f8eae0552c61909b4ab031a77e2dc33b2c391 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -1344,7 +1344,7 @@ std::error_code RedirectingFileSystem::isLocal(const Twine &Path_, SmallString<256> Path; Path_.toVector(Path); - if (makeCanonical(Path)) + if (makeAbsolute(Path)) return {}; return ExternalFS->isLocal(Path, Result); @@ -1411,7 +1411,7 @@ directory_iterator RedirectingFileSystem::dir_begin(const Twine &Dir, SmallString<256> Path; Dir.toVector(Path); - EC = makeCanonical(Path); + EC = makeAbsolute(Path); if (EC) return {}; @@ -2261,8 +2261,8 @@ void RedirectingFileSystem::LookupResult::getPath( llvm::sys::path::append(Result, E->getName()); } -std::error_code -RedirectingFileSystem::makeCanonical(SmallVectorImpl<char> &Path) const { +std::error_code RedirectingFileSystem::makeCanonicalForLookup( + SmallVectorImpl<char> &Path) const { if (std::error_code EC = makeAbsolute(Path)) return EC; @@ -2277,12 +2277,16 @@ RedirectingFileSystem::makeCanonical(SmallVectorImpl<char> &Path) const { ErrorOr<RedirectingFileSystem::LookupResult> RedirectingFileSystem::lookupPath(StringRef Path) const { + llvm::SmallString<128> CanonicalPath(Path); + if (std::error_code EC = makeCanonicalForLookup(CanonicalPath)) + return EC; + // RedirectOnly means the VFS is always used. if (UsageTrackingActive && Redirection == RedirectKind::RedirectOnly) HasBeenUsed = true; - sys::path::const_iterator Start = sys::path::begin(Path); - sys::path::const_iterator End = sys::path::end(Path); + sys::path::const_iterator Start = sys::path::begin(CanonicalPath); + sys::path::const_iterator End = sys::path::end(CanonicalPath); llvm::SmallVector<Entry *, 32> Entries; for (const auto &Root : Roots) { ErrorOr<RedirectingFileSystem::LookupResult> Result = @@ -2358,14 +2362,14 @@ static Status getRedirectedFileStatus(const Twine &OriginalPath, } ErrorOr<Status> RedirectingFileSystem::status( - const Twine &CanonicalPath, const Twine &OriginalPath, + const Twine &LookupPath, const Twine &OriginalPath, const RedirectingFileSystem::LookupResult &Result) { if (std::optional<StringRef> ExtRedirect = Result.getExternalRedirect()) { - SmallString<256> CanonicalRemappedPath((*ExtRedirect).str()); - if (std::error_code EC = makeCanonical(CanonicalRemappedPath)) + SmallString<256> RemappedPath((*ExtRedirect).str()); + if (std::error_code EC = makeAbsolute(RemappedPath)) return EC; - ErrorOr<Status> S = ExternalFS->status(CanonicalRemappedPath); + ErrorOr<Status> S = ExternalFS->status(RemappedPath); if (!S) return S; S = Status::copyWithNewName(*S, *ExtRedirect); @@ -2375,13 +2379,13 @@ ErrorOr<Status> RedirectingFileSystem::status( } auto *DE = cast<RedirectingFileSystem::DirectoryEntry>(Result.E); - return Status::copyWithNewName(DE->getStatus(), CanonicalPath); + return Status::copyWithNewName(DE->getStatus(), LookupPath); } ErrorOr<Status> -RedirectingFileSystem::getExternalStatus(const Twine &CanonicalPath, +RedirectingFileSystem::getExternalStatus(const Twine &LookupPath, const Twine &OriginalPath) const { - auto Result = ExternalFS->status(CanonicalPath); + auto Result = ExternalFS->status(LookupPath); // The path has been mapped by some nested VFS, don't override it with the // original path. @@ -2391,38 +2395,37 @@ RedirectingFileSystem::getExternalStatus(const Twine &CanonicalPath, } ErrorOr<Status> RedirectingFileSystem::status(const Twine &OriginalPath) { - SmallString<256> CanonicalPath; - OriginalPath.toVector(CanonicalPath); + SmallString<256> Path; + OriginalPath.toVector(Path); - if (std::error_code EC = makeCanonical(CanonicalPath)) + if (std::error_code EC = makeAbsolute(Path)) return EC; if (Redirection == RedirectKind::Fallback) { // Attempt to find the original file first, only falling back to the // mapped file if that fails. - ErrorOr<Status> S = getExternalStatus(CanonicalPath, OriginalPath); + ErrorOr<Status> S = getExternalStatus(Path, OriginalPath); if (S) return S; } - ErrorOr<RedirectingFileSystem::LookupResult> Result = - lookupPath(CanonicalPath); + ErrorOr<RedirectingFileSystem::LookupResult> Result = lookupPath(Path); if (!Result) { // Was not able to map file, fallthrough to using the original path if // that was the specified redirection type. if (Redirection == RedirectKind::Fallthrough && isFileNotFound(Result.getError())) - return getExternalStatus(CanonicalPath, OriginalPath); + return getExternalStatus(Path, OriginalPath); return Result.getError(); } - ErrorOr<Status> S = status(CanonicalPath, OriginalPath, *Result); + ErrorOr<Status> S = status(Path, OriginalPath, *Result); if (!S && Redirection == RedirectKind::Fallthrough && isFileNotFound(S.getError(), Result->E)) { // Mapped the file but it wasn't found in the underlying filesystem, // fallthrough to using the original path if that was the specified // redirection type. - return getExternalStatus(CanonicalPath, OriginalPath); + return getExternalStatus(Path, OriginalPath); } return S; @@ -2471,30 +2474,27 @@ File::getWithPath(ErrorOr<std::unique_ptr<File>> Result, const Twine &P) { ErrorOr<std::unique_ptr<File>> RedirectingFileSystem::openFileForRead(const Twine &OriginalPath) { - SmallString<256> CanonicalPath; - OriginalPath.toVector(CanonicalPath); + SmallString<256> Path; + OriginalPath.toVector(Path); - if (std::error_code EC = makeCanonical(CanonicalPath)) + if (std::error_code EC = makeAbsolute(Path)) return EC; if (Redirection == RedirectKind::Fallback) { // Attempt to find the original file first, only falling back to the // mapped file if that fails. - auto F = File::getWithPath(ExternalFS->openFileForRead(CanonicalPath), - OriginalPath); + auto F = File::getWithPath(ExternalFS->openFileForRead(Path), OriginalPath); if (F) return F; } - ErrorOr<RedirectingFileSystem::LookupResult> Result = - lookupPath(CanonicalPath); + ErrorOr<RedirectingFileSystem::LookupResult> Result = lookupPath(Path); if (!Result) { // Was not able to map file, fallthrough to using the original path if // that was the specified redirection type. if (Redirection == RedirectKind::Fallthrough && isFileNotFound(Result.getError())) - return File::getWithPath(ExternalFS->openFileForRead(CanonicalPath), - OriginalPath); + return File::getWithPath(ExternalFS->openFileForRead(Path), OriginalPath); return Result.getError(); } @@ -2502,22 +2502,21 @@ RedirectingFileSystem::openFileForRead(const Twine &OriginalPath) { return make_error_code(llvm::errc::invalid_argument); StringRef ExtRedirect = *Result->getExternalRedirect(); - SmallString<256> CanonicalRemappedPath(ExtRedirect.str()); - if (std::error_code EC = makeCanonical(CanonicalRemappedPath)) + SmallString<256> RemappedPath(ExtRedirect.str()); + if (std::error_code EC = makeAbsolute(RemappedPath)) return EC; auto *RE = cast<RedirectingFileSystem::RemapEntry>(Result->E); - auto ExternalFile = File::getWithPath( - ExternalFS->openFileForRead(CanonicalRemappedPath), ExtRedirect); + auto ExternalFile = + File::getWithPath(ExternalFS->openFileForRead(RemappedPath), ExtRedirect); if (!ExternalFile) { if (Redirection == RedirectKind::Fallthrough && isFileNotFound(ExternalFile.getError(), Result->E)) { // Mapped the file but it wasn't found in the underlying filesystem, // fallthrough to using the original path if that was the specified // redirection type. - return File::getWithPath(ExternalFS->openFileForRead(CanonicalPath), - OriginalPath); + return File::getWithPath(ExternalFS->openFileForRead(Path), OriginalPath); } return ExternalFile; } @@ -2537,28 +2536,27 @@ RedirectingFileSystem::openFileForRead(const Twine &OriginalPath) { std::error_code RedirectingFileSystem::getRealPath(const Twine &OriginalPath, SmallVectorImpl<char> &Output) const { - SmallString<256> CanonicalPath; - OriginalPath.toVector(CanonicalPath); + SmallString<256> Path; + OriginalPath.toVector(Path); - if (std::error_code EC = makeCanonical(CanonicalPath)) + if (std::error_code EC = makeAbsolute(Path)) return EC; if (Redirection == RedirectKind::Fallback) { // Attempt to find the original file first, only falling back to the // mapped file if that fails. - std::error_code EC = ExternalFS->getRealPath(CanonicalPath, Output); + std::error_code EC = ExternalFS->getRealPath(Path, Output); if (!EC) return EC; } - ErrorOr<RedirectingFileSystem::LookupResult> Result = - lookupPath(CanonicalPath); + ErrorOr<RedirectingFileSystem::LookupResult> Result = lookupPath(Path); if (!Result) { // Was not able to map file, fallthrough to using the original path if // that was the specified redirection type. if (Redirection == RedirectKind::Fallthrough && isFileNotFound(Result.getError())) - return ExternalFS->getRealPath(CanonicalPath, Output); + return ExternalFS->getRealPath(Path, Output); return Result.getError(); } @@ -2571,7 +2569,7 @@ RedirectingFileSystem::getRealPath(const Twine &OriginalPath, // Mapped the file but it wasn't found in the underlying filesystem, // fallthrough to using the original path if that was the specified // redirection type. - return ExternalFS->getRealPath(CanonicalPath, Output); + return ExternalFS->getRealPath(Path, Output); } return P; } diff --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc index 3e4c1f74161c6f1d2e5dde8510cf0fcae0e8a392..854d531ab371fc7027b87a8e870e2c3276df10d1 100644 --- a/llvm/lib/Support/Windows/Path.inc +++ b/llvm/lib/Support/Windows/Path.inc @@ -623,6 +623,10 @@ std::error_code access(const Twine &Path, AccessMode Mode) { DWORD Attributes = ::GetFileAttributesW(PathUtf16.begin()); if (Attributes == INVALID_FILE_ATTRIBUTES) { + // Avoid returning unexpected error codes when querying for existence. + if (Mode == AccessMode::Exist) + return errc::no_such_file_or_directory; + // See if the file didn't actually exist. DWORD LastError = ::GetLastError(); if (LastError != ERROR_FILE_NOT_FOUND && LastError != ERROR_PATH_NOT_FOUND) diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td index 402c7292d7f81cf8edf68a9e6fcea89b766ee609..6425aa9b091f7f457ace63cfbd0e25e338708730 100644 --- a/llvm/lib/Target/AArch64/AArch64.td +++ b/llvm/lib/Target/AArch64/AArch64.td @@ -873,6 +873,12 @@ def TuneA520 : SubtargetFeature<"a520", "ARMProcFamily", "CortexA520", FeatureFuseAdrpAdd, FeaturePostRAScheduler]>; +def TuneA520AE : SubtargetFeature<"a520ae", "ARMProcFamily", "CortexA520", + "Cortex-A520AE ARM processors", [ + FeatureFuseAES, + FeatureFuseAdrpAdd, + FeaturePostRAScheduler]>; + def TuneA57 : SubtargetFeature<"a57", "ARMProcFamily", "CortexA57", "Cortex-A57 ARM processors", [ FeatureFuseAES, @@ -1001,6 +1007,17 @@ def TuneA720 : SubtargetFeature<"a720", "ARMProcFamily", "CortexA720", FeatureEnableSelectOptimize, FeaturePredictableSelectIsExpensive]>; +def TuneA720AE : SubtargetFeature<"a720ae", "ARMProcFamily", "CortexA720", + "Cortex-A720AE ARM processors", [ + FeatureFuseAES, + FeaturePostRAScheduler, + FeatureCmpBccFusion, + FeatureAddrLSLFast, + FeatureALULSLFast, + FeatureFuseAdrpAdd, + FeatureEnableSelectOptimize, + FeaturePredictableSelectIsExpensive]>; + def TuneR82 : SubtargetFeature<"cortex-r82", "ARMProcFamily", "CortexR82", "Cortex-R82 ARM processors", [ @@ -1423,6 +1440,9 @@ def ProcessorFeatures { list<SubtargetFeature> A520 = [HasV9_2aOps, FeaturePerfMon, FeatureAM, FeatureMTE, FeatureETE, FeatureSVE2BitPerm, FeatureFP16FML]; + list<SubtargetFeature> A520AE = [HasV9_2aOps, FeaturePerfMon, FeatureAM, + FeatureMTE, FeatureETE, FeatureSVE2BitPerm, + FeatureFP16FML]; list<SubtargetFeature> A65 = [HasV8_2aOps, FeatureCrypto, FeatureFPARMv8, FeatureNEON, FeatureFullFP16, FeatureDotProd, FeatureRCPC, FeatureSSBS, FeatureRAS, @@ -1456,6 +1476,9 @@ def ProcessorFeatures { list<SubtargetFeature> A720 = [HasV9_2aOps, FeatureMTE, FeatureFP16FML, FeatureTRBE, FeatureSVE2BitPerm, FeatureETE, FeaturePerfMon, FeatureSPE, FeatureSPE_EEF]; + list<SubtargetFeature> A720AE = [HasV9_2aOps, FeatureMTE, FeatureFP16FML, + FeatureTRBE, FeatureSVE2BitPerm, FeatureETE, + FeaturePerfMon, FeatureSPE, FeatureSPE_EEF]; list<SubtargetFeature> R82 = [HasV8_0rOps, FeaturePerfMon, FeatureFullFP16, FeatureFP16FML, FeatureSSBS, FeaturePredRes, FeatureSB, FeatureRDM, FeatureDotProd, @@ -1598,6 +1621,8 @@ def : ProcessorModel<"cortex-a510", CortexA510Model, ProcessorFeatures.A510, [TuneA510]>; def : ProcessorModel<"cortex-a520", CortexA510Model, ProcessorFeatures.A520, [TuneA520]>; +def : ProcessorModel<"cortex-a520ae", CortexA510Model, ProcessorFeatures.A520AE, + [TuneA520AE]>; def : ProcessorModel<"cortex-a57", CortexA57Model, ProcessorFeatures.A53, [TuneA57]>; def : ProcessorModel<"cortex-a65", CortexA53Model, ProcessorFeatures.A65, @@ -1628,6 +1653,8 @@ def : ProcessorModel<"cortex-a715", NeoverseN2Model, ProcessorFeatures.A715, [TuneA715]>; def : ProcessorModel<"cortex-a720", NeoverseN2Model, ProcessorFeatures.A720, [TuneA720]>; +def : ProcessorModel<"cortex-a720ae", NeoverseN2Model, ProcessorFeatures.A720AE, + [TuneA720AE]>; def : ProcessorModel<"cortex-r82", CortexA55Model, ProcessorFeatures.R82, [TuneR82]>; def : ProcessorModel<"cortex-x1", CortexA57Model, ProcessorFeatures.X1, diff --git a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp index f147ded2ab701abf0638aa2d32e0de6cb7a1b18a..3bf6283b79e9b8335d7f04dc10fdda587082a3c6 100644 --- a/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64Arm64ECCallLowering.cpp @@ -23,6 +23,7 @@ #include "llvm/IR/CallingConv.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instruction.h" +#include "llvm/IR/Mangler.h" #include "llvm/InitializePasses.h" #include "llvm/Object/COFF.h" #include "llvm/Pass.h" @@ -30,7 +31,7 @@ #include "llvm/TargetParser/Triple.h" using namespace llvm; -using namespace llvm::object; +using namespace llvm::COFF; using OperandBundleDef = OperandBundleDefT<Value *>; @@ -45,8 +46,6 @@ static cl::opt<bool> GenerateThunks("arm64ec-generate-thunks", cl::Hidden, namespace { -enum class ThunkType { GuestExit, Entry, Exit }; - class AArch64Arm64ECCallLowering : public ModulePass { public: static char ID; @@ -73,15 +72,15 @@ private: Type *I64Ty; Type *VoidTy; - void getThunkType(FunctionType *FT, AttributeList AttrList, ThunkType TT, - raw_ostream &Out, FunctionType *&Arm64Ty, - FunctionType *&X64Ty); + void getThunkType(FunctionType *FT, AttributeList AttrList, + Arm64ECThunkType TT, raw_ostream &Out, + FunctionType *&Arm64Ty, FunctionType *&X64Ty); void getThunkRetType(FunctionType *FT, AttributeList AttrList, raw_ostream &Out, Type *&Arm64RetTy, Type *&X64RetTy, SmallVectorImpl<Type *> &Arm64ArgTypes, SmallVectorImpl<Type *> &X64ArgTypes, bool &HasSretPtr); - void getThunkArgTypes(FunctionType *FT, AttributeList AttrList, ThunkType TT, - raw_ostream &Out, + void getThunkArgTypes(FunctionType *FT, AttributeList AttrList, + Arm64ECThunkType TT, raw_ostream &Out, SmallVectorImpl<Type *> &Arm64ArgTypes, SmallVectorImpl<Type *> &X64ArgTypes, bool HasSretPtr); void canonicalizeThunkType(Type *T, Align Alignment, bool Ret, @@ -91,13 +90,11 @@ private: } // end anonymous namespace -void AArch64Arm64ECCallLowering::getThunkType(FunctionType *FT, - AttributeList AttrList, - ThunkType TT, raw_ostream &Out, - FunctionType *&Arm64Ty, - FunctionType *&X64Ty) { - Out << (TT == ThunkType::Entry ? "$ientry_thunk$cdecl$" - : "$iexit_thunk$cdecl$"); +void AArch64Arm64ECCallLowering::getThunkType( + FunctionType *FT, AttributeList AttrList, Arm64ECThunkType TT, + raw_ostream &Out, FunctionType *&Arm64Ty, FunctionType *&X64Ty) { + Out << (TT == Arm64ECThunkType::Entry ? "$ientry_thunk$cdecl$" + : "$iexit_thunk$cdecl$"); Type *Arm64RetTy; Type *X64RetTy; @@ -108,7 +105,7 @@ void AArch64Arm64ECCallLowering::getThunkType(FunctionType *FT, // The first argument to a thunk is the called function, stored in x9. // For exit thunks, we pass the called function down to the emulator; // for entry/guest exit thunks, we just call the Arm64 function directly. - if (TT == ThunkType::Exit) + if (TT == Arm64ECThunkType::Exit) Arm64ArgTypes.push_back(PtrTy); X64ArgTypes.push_back(PtrTy); @@ -125,8 +122,8 @@ void AArch64Arm64ECCallLowering::getThunkType(FunctionType *FT, } void AArch64Arm64ECCallLowering::getThunkArgTypes( - FunctionType *FT, AttributeList AttrList, ThunkType TT, raw_ostream &Out, - SmallVectorImpl<Type *> &Arm64ArgTypes, + FunctionType *FT, AttributeList AttrList, Arm64ECThunkType TT, + raw_ostream &Out, SmallVectorImpl<Type *> &Arm64ArgTypes, SmallVectorImpl<Type *> &X64ArgTypes, bool HasSretPtr) { Out << "$"; @@ -163,7 +160,7 @@ void AArch64Arm64ECCallLowering::getThunkArgTypes( X64ArgTypes.push_back(PtrTy); // x5 Arm64ArgTypes.push_back(I64Ty); - if (TT != ThunkType::Entry) { + if (TT != Arm64ECThunkType::Entry) { // FIXME: x5 isn't actually used by the x64 side; revisit once we // have proper isel for varargs X64ArgTypes.push_back(I64Ty); @@ -348,7 +345,8 @@ Function *AArch64Arm64ECCallLowering::buildExitThunk(FunctionType *FT, SmallString<256> ExitThunkName; llvm::raw_svector_ostream ExitThunkStream(ExitThunkName); FunctionType *Arm64Ty, *X64Ty; - getThunkType(FT, Attrs, ThunkType::Exit, ExitThunkStream, Arm64Ty, X64Ty); + getThunkType(FT, Attrs, Arm64ECThunkType::Exit, ExitThunkStream, Arm64Ty, + X64Ty); if (Function *F = M->getFunction(ExitThunkName)) return F; @@ -451,8 +449,8 @@ Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *F) { SmallString<256> EntryThunkName; llvm::raw_svector_ostream EntryThunkStream(EntryThunkName); FunctionType *Arm64Ty, *X64Ty; - getThunkType(F->getFunctionType(), F->getAttributes(), ThunkType::Entry, - EntryThunkStream, Arm64Ty, X64Ty); + getThunkType(F->getFunctionType(), F->getAttributes(), + Arm64ECThunkType::Entry, EntryThunkStream, Arm64Ty, X64Ty); if (Function *F = M->getFunction(EntryThunkName)) return F; @@ -543,8 +541,8 @@ Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *F) { Function *AArch64Arm64ECCallLowering::buildGuestExitThunk(Function *F) { llvm::raw_null_ostream NullThunkName; FunctionType *Arm64Ty, *X64Ty; - getThunkType(F->getFunctionType(), F->getAttributes(), ThunkType::GuestExit, - NullThunkName, Arm64Ty, X64Ty); + getThunkType(F->getFunctionType(), F->getAttributes(), + Arm64ECThunkType::GuestExit, NullThunkName, Arm64Ty, X64Ty); auto MangledName = getArm64ECMangledFunctionName(F->getName().str()); assert(MangledName && "Can't guest exit to function that's already native"); std::string ThunkName = *MangledName; @@ -679,7 +677,7 @@ bool AArch64Arm64ECCallLowering::runOnModule(Module &Mod) { struct ThunkInfo { Constant *Src; Constant *Dst; - unsigned Kind; + Arm64ECThunkType Kind; }; SmallVector<ThunkInfo> ThunkMapping; for (Function &F : Mod) { @@ -688,14 +686,17 @@ bool AArch64Arm64ECCallLowering::runOnModule(Module &Mod) { F.getCallingConv() != CallingConv::ARM64EC_Thunk_X64) { if (!F.hasComdat()) F.setComdat(Mod.getOrInsertComdat(F.getName())); - ThunkMapping.push_back({&F, buildEntryThunk(&F), 1}); + ThunkMapping.push_back( + {&F, buildEntryThunk(&F), Arm64ECThunkType::Entry}); } } for (Function *F : DirectCalledFns) { ThunkMapping.push_back( - {F, buildExitThunk(F->getFunctionType(), F->getAttributes()), 4}); + {F, buildExitThunk(F->getFunctionType(), F->getAttributes()), + Arm64ECThunkType::Exit}); if (!F->hasDLLImportStorageClass()) - ThunkMapping.push_back({buildGuestExitThunk(F), F, 0}); + ThunkMapping.push_back( + {buildGuestExitThunk(F), F, Arm64ECThunkType::GuestExit}); } if (!ThunkMapping.empty()) { @@ -704,7 +705,7 @@ bool AArch64Arm64ECCallLowering::runOnModule(Module &Mod) { ThunkMappingArrayElems.push_back(ConstantStruct::getAnon( {ConstantExpr::getBitCast(Thunk.Src, PtrTy), ConstantExpr::getBitCast(Thunk.Dst, PtrTy), - ConstantInt::get(M->getContext(), APInt(32, Thunk.Kind))})); + ConstantInt::get(M->getContext(), APInt(32, uint8_t(Thunk.Kind)))})); } Constant *ThunkMappingArray = ConstantArray::get( llvm::ArrayType::get(ThunkMappingArrayElems[0]->getType(), diff --git a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp index b2c52b443753dc1e02a4f565640a4a706b4aa81b..03f0778bae59d5e20198095e7fadaa498bdc8a21 100644 --- a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp +++ b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp @@ -987,7 +987,7 @@ AArch64ExpandPseudo::expandCondSMToggle(MachineBasicBlock &MBB, // Expand the pseudo into smstart or smstop instruction. The pseudo has the // following operands: // - // MSRpstatePseudo <za|sm|both>, <0|1>, pstate.sm, expectedval, <regmask> + // MSRpstatePseudo <za|sm|both>, <0|1>, condition[, pstate.sm], <regmask> // // The pseudo is expanded into a conditional smstart/smstop, with a // check if pstate.sm (register) equals the expected value, and if not, @@ -997,9 +997,9 @@ AArch64ExpandPseudo::expandCondSMToggle(MachineBasicBlock &MBB, // streaming-compatible function: // // OrigBB: - // MSRpstatePseudo 3, 0, %0, 0, <regmask> <- Conditional SMSTOP + // MSRpstatePseudo 3, 0, IfCallerIsStreaming, %0, <regmask> <- Cond SMSTOP // bl @normal_callee - // MSRpstatePseudo 3, 1, %0, 0, <regmask> <- Conditional SMSTART + // MSRpstatePseudo 3, 1, IfCallerIsStreaming, %0, <regmask> <- Cond SMSTART // // ...which will be transformed into: // @@ -1022,11 +1022,20 @@ AArch64ExpandPseudo::expandCondSMToggle(MachineBasicBlock &MBB, // We test the live value of pstate.sm and toggle pstate.sm if this is not the // expected value for the callee (0 for a normal callee and 1 for a streaming // callee). - auto PStateSM = MI.getOperand(2).getReg(); + unsigned Opc; + switch (MI.getOperand(2).getImm()) { + case AArch64SME::Always: + llvm_unreachable("Should have matched to instruction directly"); + case AArch64SME::IfCallerIsStreaming: + Opc = AArch64::TBNZW; + break; + case AArch64SME::IfCallerIsNonStreaming: + Opc = AArch64::TBZW; + break; + } + auto PStateSM = MI.getOperand(3).getReg(); auto TRI = MBB.getParent()->getSubtarget().getRegisterInfo(); unsigned SMReg32 = TRI->getSubReg(PStateSM, AArch64::sub_32); - bool IsStreamingCallee = MI.getOperand(3).getImm(); - unsigned Opc = IsStreamingCallee ? AArch64::TBZW : AArch64::TBNZW; MachineInstrBuilder Tbx = BuildMI(MBB, MBBI, DL, TII->get(Opc)).addReg(SMReg32).addImm(0); diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 054311d39e7b837c110ae3c4a630bd419eea5808..8218960406ec139b4887c0f21051afb0b5e11eda 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -1131,6 +1131,9 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM, ISD::FMUL, ISD::FDIV, ISD::FMA, ISD::FNEG, ISD::FABS, ISD::FCEIL, ISD::FSQRT, ISD::FFLOOR, ISD::FNEARBYINT, + ISD::FSIN, ISD::FCOS, ISD::FPOW, + ISD::FLOG, ISD::FLOG2, ISD::FLOG10, + ISD::FEXP, ISD::FEXP2, ISD::FEXP10, ISD::FRINT, ISD::FROUND, ISD::FROUNDEVEN, ISD::FTRUNC, ISD::FMINNUM, ISD::FMAXNUM, ISD::FMINIMUM, ISD::FMAXIMUM, ISD::STRICT_FADD, @@ -5270,13 +5273,13 @@ SDValue AArch64TargetLowering::LowerINTRINSIC_VOID(SDValue Op, AArch64ISD::SMSTART, DL, MVT::Other, Op->getOperand(0), // Chain DAG.getTargetConstant((int32_t)(AArch64SVCR::SVCRZA), DL, MVT::i32), - DAG.getConstant(0, DL, MVT::i64), DAG.getConstant(1, DL, MVT::i64)); + DAG.getConstant(AArch64SME::Always, DL, MVT::i64)); case Intrinsic::aarch64_sme_za_disable: return DAG.getNode( AArch64ISD::SMSTOP, DL, MVT::Other, Op->getOperand(0), // Chain DAG.getTargetConstant((int32_t)(AArch64SVCR::SVCRZA), DL, MVT::i32), - DAG.getConstant(0, DL, MVT::i64), DAG.getConstant(1, DL, MVT::i64)); + DAG.getConstant(AArch64SME::Always, DL, MVT::i64)); } } @@ -6892,6 +6895,11 @@ AArch64TargetLowering::allocateLazySaveBuffer(SDValue &Chain, const SDLoc &DL, return TPIDR2Obj; } +static bool isPassedInFPR(EVT VT) { + return VT.isFixedLengthVector() || + (VT.isFloatingPoint() && !VT.isScalableVector()); +} + SDValue AArch64TargetLowering::LowerFormalArguments( SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, @@ -7028,6 +7036,13 @@ SDValue AArch64TargetLowering::LowerFormalArguments( // This will be the new Chain/Root node. ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT, Glue); Glue = ArgValue.getValue(2); + if (isPassedInFPR(ArgValue.getValueType())) { + ArgValue = + DAG.getNode(AArch64ISD::COALESCER_BARRIER, DL, + DAG.getVTList(ArgValue.getValueType(), MVT::Glue), + {ArgValue, Glue}); + Glue = ArgValue.getValue(1); + } } else ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT); @@ -7197,11 +7212,11 @@ SDValue AArch64TargetLowering::LowerFormalArguments( getRegClassFor(PStateSM.getValueType().getSimpleVT())); FuncInfo->setPStateSMReg(Reg); Chain = DAG.getCopyToReg(Chain, DL, Reg, PStateSM); - } else { - PStateSM = DAG.getConstant(0, DL, MVT::i64); - } - Chain = changeStreamingMode(DAG, DL, /*Enable*/ true, Chain, Glue, PStateSM, - /*Entry*/ true); + Chain = changeStreamingMode(DAG, DL, /*Enable*/ true, Chain, Glue, + AArch64SME::IfCallerIsNonStreaming, PStateSM); + } else + Chain = changeStreamingMode(DAG, DL, /*Enable*/ true, Chain, Glue, + AArch64SME::Always); // Ensure that the SMSTART happens after the CopyWithChain such that its // chain result is used. @@ -7399,11 +7414,6 @@ void AArch64TargetLowering::saveVarArgRegisters(CCState &CCInfo, } } -static bool isPassedInFPR(EVT VT) { - return VT.isFixedLengthVector() || - (VT.isFloatingPoint() && !VT.isScalableVector()); -} - /// LowerCallResult - Lower the result values of a call into the /// appropriate copies out of appropriate physical registers. SDValue AArch64TargetLowering::LowerCallResult( @@ -7751,7 +7761,7 @@ void AArch64TargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI, // register allocator to pass call args in callee saved regs, without extra // copies to avoid these fake clobbers of actually-preserved GPRs. if (MI.getOpcode() == AArch64::MSRpstatesvcrImm1 || - MI.getOpcode() == AArch64::MSRpstatePseudo) + MI.getOpcode() == AArch64::MSRpstatePseudo) { for (unsigned I = MI.getNumOperands() - 1; I > 0; --I) if (MachineOperand &MO = MI.getOperand(I); MO.isReg() && MO.isImplicit() && MO.isDef() && @@ -7759,6 +7769,16 @@ void AArch64TargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI, AArch64::GPR64RegClass.contains(MO.getReg()))) MI.removeOperand(I); + // The SVE vector length can change when entering/leaving streaming mode. + if (MI.getOperand(0).getImm() == AArch64SVCR::SVCRSM || + MI.getOperand(0).getImm() == AArch64SVCR::SVCRSMZA) { + MI.addOperand(MachineOperand::CreateReg(AArch64::VG, /*IsDef=*/false, + /*IsImplicit=*/true)); + MI.addOperand(MachineOperand::CreateReg(AArch64::VG, /*IsDef=*/true, + /*IsImplicit=*/true)); + } + } + // Add an implicit use of 'VG' for ADDXri/SUBXri, which are instructions that // have nothing to do with VG, were it not that they are used to materialise a // frame-address. If they contain a frame-index to a scalable vector, this @@ -7776,9 +7796,11 @@ void AArch64TargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI, } } -SDValue AArch64TargetLowering::changeStreamingMode( - SelectionDAG &DAG, SDLoc DL, bool Enable, - SDValue Chain, SDValue InGlue, SDValue PStateSM, bool Entry) const { +SDValue AArch64TargetLowering::changeStreamingMode(SelectionDAG &DAG, SDLoc DL, + bool Enable, SDValue Chain, + SDValue InGlue, + unsigned Condition, + SDValue PStateSM) const { MachineFunction &MF = DAG.getMachineFunction(); AArch64FunctionInfo *FuncInfo = MF.getInfo<AArch64FunctionInfo>(); FuncInfo->setHasStreamingModeChanges(true); @@ -7787,10 +7809,13 @@ SDValue AArch64TargetLowering::changeStreamingMode( SDValue RegMask = DAG.getRegisterMask(TRI->getSMStartStopCallPreservedMask()); SDValue MSROp = DAG.getTargetConstant((int32_t)AArch64SVCR::SVCRSM, DL, MVT::i32); - - SDValue ExpectedSMVal = - DAG.getTargetConstant(Entry ? Enable : !Enable, DL, MVT::i64); - SmallVector<SDValue> Ops = {Chain, MSROp, PStateSM, ExpectedSMVal, RegMask}; + SDValue ConditionOp = DAG.getTargetConstant(Condition, DL, MVT::i64); + SmallVector<SDValue> Ops = {Chain, MSROp, ConditionOp}; + if (Condition != AArch64SME::Always) { + assert(PStateSM && "PStateSM should be defined"); + Ops.push_back(PStateSM); + } + Ops.push_back(RegMask); if (InGlue) Ops.push_back(InGlue); @@ -7799,6 +7824,19 @@ SDValue AArch64TargetLowering::changeStreamingMode( return DAG.getNode(Opcode, DL, DAG.getVTList(MVT::Other, MVT::Glue), Ops); } +static unsigned getSMCondition(const SMEAttrs &CallerAttrs, + const SMEAttrs &CalleeAttrs) { + if (!CallerAttrs.hasStreamingCompatibleInterface() || + CallerAttrs.hasStreamingBody()) + return AArch64SME::Always; + if (CalleeAttrs.hasNonStreamingInterface()) + return AArch64SME::IfCallerIsStreaming; + if (CalleeAttrs.hasStreamingInterface()) + return AArch64SME::IfCallerIsNonStreaming; + + llvm_unreachable("Unsupported attributes"); +} + /// LowerCall - Lower a call to a callseq_start + CALL + callseq_end chain, /// and add input and output parameter nodes. SDValue @@ -8018,7 +8056,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI, Chain = DAG.getNode( AArch64ISD::SMSTOP, DL, MVT::Other, Chain, DAG.getTargetConstant((int32_t)(AArch64SVCR::SVCRZA), DL, MVT::i32), - DAG.getConstant(0, DL, MVT::i64), DAG.getConstant(1, DL, MVT::i64)); + DAG.getConstant(AArch64SME::Always, DL, MVT::i64)); // Adjust the stack pointer for the new arguments... // These operations are automatically eliminated by the prolog/epilog pass @@ -8181,9 +8219,10 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI, // Call site info is used for function's parameter entry value // tracking. For now we track only simple cases when parameter // is transferred through whole register. - llvm::erase_if(CSInfo, [&VA](MachineFunction::ArgRegPair ArgReg) { - return ArgReg.Reg == VA.getLocReg(); - }); + llvm::erase_if(CSInfo.ArgRegPairs, + [&VA](MachineFunction::ArgRegPair ArgReg) { + return ArgReg.Reg == VA.getLocReg(); + }); } else { // Add an extra level of indirection for streaming mode changes by // using a pseudo copy node that cannot be rematerialised between a @@ -8195,7 +8234,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI, RegsUsed.insert(VA.getLocReg()); const TargetOptions &Options = DAG.getTarget().Options; if (Options.EmitCallSiteInfo) - CSInfo.emplace_back(VA.getLocReg(), i); + CSInfo.ArgRegPairs.emplace_back(VA.getLocReg(), i); } } else { assert(VA.isMemLoc()); @@ -8289,9 +8328,9 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI, SDValue InGlue; if (RequiresSMChange) { - SDValue NewChain = - changeStreamingMode(DAG, DL, CalleeAttrs.hasStreamingInterface(), Chain, - InGlue, PStateSM, true); + SDValue NewChain = changeStreamingMode( + DAG, DL, CalleeAttrs.hasStreamingInterface(), Chain, InGlue, + getSMCondition(CallerAttrs, CalleeAttrs), PStateSM); Chain = NewChain.getValue(0); InGlue = NewChain.getValue(1); } @@ -8445,8 +8484,9 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI, if (RequiresSMChange) { assert(PStateSM && "Expected a PStateSM to be set"); - Result = changeStreamingMode(DAG, DL, !CalleeAttrs.hasStreamingInterface(), - Result, InGlue, PStateSM, false); + Result = changeStreamingMode( + DAG, DL, !CalleeAttrs.hasStreamingInterface(), Result, InGlue, + getSMCondition(CallerAttrs, CalleeAttrs), PStateSM); } if (CallerAttrs.requiresEnablingZAAfterCall(CalleeAttrs)) @@ -8454,7 +8494,7 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI, Result = DAG.getNode( AArch64ISD::SMSTART, DL, MVT::Other, Result, DAG.getTargetConstant((int32_t)(AArch64SVCR::SVCRZA), DL, MVT::i32), - DAG.getConstant(0, DL, MVT::i64), DAG.getConstant(1, DL, MVT::i64)); + DAG.getConstant(AArch64SME::Always, DL, MVT::i64)); if (ShouldPreserveZT0) Result = @@ -8589,18 +8629,21 @@ AArch64TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, Register Reg = FuncInfo->getPStateSMReg(); assert(Reg.isValid() && "PStateSM Register is invalid"); SDValue PStateSM = DAG.getCopyFromReg(Chain, DL, Reg, MVT::i64); - Chain = - changeStreamingMode(DAG, DL, /*Enable*/ false, Chain, - /*Glue*/ SDValue(), PStateSM, /*Entry*/ false); + Chain = changeStreamingMode(DAG, DL, /*Enable*/ false, Chain, + /*Glue*/ SDValue(), + AArch64SME::IfCallerIsNonStreaming, PStateSM); } else - Chain = changeStreamingMode( - DAG, DL, /*Enable*/ false, Chain, - /*Glue*/ SDValue(), DAG.getConstant(1, DL, MVT::i64), /*Entry*/ true); + Chain = changeStreamingMode(DAG, DL, /*Enable*/ false, Chain, + /*Glue*/ SDValue(), AArch64SME::Always); Glue = Chain.getValue(1); } SmallVector<SDValue, 4> RetOps(1, Chain); for (auto &RetVal : RetVals) { + if (FuncAttrs.hasStreamingBody() && !FuncAttrs.hasStreamingInterface() && + isPassedInFPR(RetVal.second.getValueType())) + RetVal.second = DAG.getNode(AArch64ISD::COALESCER_BARRIER, DL, + RetVal.second.getValueType(), RetVal.second); Chain = DAG.getCopyToReg(Chain, DL, RetVal.first, RetVal.second, Glue); Glue = Chain.getValue(1); RetOps.push_back( @@ -16585,6 +16628,38 @@ bool AArch64TargetLowering::isLegalAddImmediate(int64_t Immed) const { return IsLegal; } +bool AArch64TargetLowering::isLegalAddScalableImmediate(int64_t Imm) const { + // We will only emit addvl/inc* instructions for SVE2 + if (!Subtarget->hasSVE2()) + return false; + + // addvl's immediates are in terms of the number of bytes in a register. + // Since there are 16 in the base supported size (128bits), we need to + // divide the immediate by that much to give us a useful immediate to + // multiply by vscale. We can't have a remainder as a result of this. + if (Imm % 16 == 0) + return isInt<6>(Imm / 16); + + // Inc[b|h|w|d] instructions take a pattern and a positive immediate + // multiplier. For now, assume a pattern of 'all'. Incb would be a subset + // of addvl as a result, so only take h|w|d into account. + // Dec[h|w|d] will cover subtractions. + // Immediates are in the range [1,16], so we can't do a 2's complement check. + // FIXME: Can we make use of other patterns to cover other immediates? + + // inch|dech + if (Imm % 8 == 0) + return std::labs(Imm / 8) <= 16; + // incw|decw + if (Imm % 4 == 0) + return std::labs(Imm / 4) <= 16; + // incd|decd + if (Imm % 2 == 0) + return std::labs(Imm / 2) <= 16; + + return false; +} + // Return false to prevent folding // (mul (add x, c1), c2) -> (add (mul x, c2), c2*c1) in DAGCombine, // if the folding leads to worse code. @@ -16661,15 +16736,29 @@ bool AArch64TargetLowering::isLegalAddressingMode(const DataLayout &DL, if (Ty->isScalableTy()) { if (isa<ScalableVectorType>(Ty)) { + // See if we have a foldable vscale-based offset, for vector types which + // are either legal or smaller than the minimum; more work will be + // required if we need to consider addressing for types which need + // legalization by splitting. + uint64_t VecNumBytes = DL.getTypeSizeInBits(Ty).getKnownMinValue() / 8; + if (AM.HasBaseReg && !AM.BaseOffs && AM.ScalableOffset && !AM.Scale && + (AM.ScalableOffset % VecNumBytes == 0) && VecNumBytes <= 16 && + isPowerOf2_64(VecNumBytes)) + return isInt<4>(AM.ScalableOffset / (int64_t)VecNumBytes); + uint64_t VecElemNumBytes = DL.getTypeSizeInBits(cast<VectorType>(Ty)->getElementType()) / 8; - return AM.HasBaseReg && !AM.BaseOffs && + return AM.HasBaseReg && !AM.BaseOffs && !AM.ScalableOffset && (AM.Scale == 0 || (uint64_t)AM.Scale == VecElemNumBytes); } - return AM.HasBaseReg && !AM.BaseOffs && !AM.Scale; + return AM.HasBaseReg && !AM.BaseOffs && !AM.ScalableOffset && !AM.Scale; } + // No scalable offsets allowed for non-scalable types. + if (AM.ScalableOffset) + return false; + // check reg + imm case: // i.e., reg + 0, reg + imm9, reg + SIZE_IN_BYTES * uimm12 uint64_t NumBytes = 0; @@ -18552,12 +18641,16 @@ static SDValue performConcatVectorsCombine(SDNode *N, } } - if (N->getOperand(0).getValueType() == MVT::v4i8) { + if (N->getOperand(0).getValueType() == MVT::v4i8 || + N->getOperand(0).getValueType() == MVT::v2i16 || + N->getOperand(0).getValueType() == MVT::v2i8) { + EVT SrcVT = N->getOperand(0).getValueType(); // If we have a concat of v4i8 loads, convert them to a buildvector of f32 // loads to prevent having to go through the v4i8 load legalization that // needs to extend each element into a larger type. - if (N->getNumOperands() % 2 == 0 && all_of(N->op_values(), [](SDValue V) { - if (V.getValueType() != MVT::v4i8) + if (N->getNumOperands() % 2 == 0 && + all_of(N->op_values(), [SrcVT](SDValue V) { + if (V.getValueType() != SrcVT) return false; if (V.isUndef()) return true; @@ -18565,19 +18658,18 @@ static SDValue performConcatVectorsCombine(SDNode *N, return LD && V.hasOneUse() && LD->isSimple() && !LD->isIndexed() && LD->getExtensionType() == ISD::NON_EXTLOAD; })) { - EVT NVT = - EVT::getVectorVT(*DAG.getContext(), MVT::f32, N->getNumOperands()); + EVT FVT = SrcVT == MVT::v2i8 ? MVT::f16 : MVT::f32; + EVT NVT = EVT::getVectorVT(*DAG.getContext(), FVT, N->getNumOperands()); SmallVector<SDValue> Ops; for (unsigned i = 0; i < N->getNumOperands(); i++) { SDValue V = N->getOperand(i); if (V.isUndef()) - Ops.push_back(DAG.getUNDEF(MVT::f32)); + Ops.push_back(DAG.getUNDEF(FVT)); else { LoadSDNode *LD = cast<LoadSDNode>(V); - SDValue NewLoad = - DAG.getLoad(MVT::f32, dl, LD->getChain(), LD->getBasePtr(), - LD->getMemOperand()); + SDValue NewLoad = DAG.getLoad(FVT, dl, LD->getChain(), + LD->getBasePtr(), LD->getMemOperand()); DAG.ReplaceAllUsesOfValueWith(SDValue(LD, 1), NewLoad.getValue(1)); Ops.push_back(NewLoad); } @@ -21413,12 +21505,8 @@ static SDValue performUzpCombine(SDNode *N, SelectionDAG &DAG, } } - // uzp1(xtn x, xtn y) -> xtn(uzp1 (x, y)) - // Only implemented on little-endian subtargets. - bool IsLittleEndian = DAG.getDataLayout().isLittleEndian(); - - // This optimization only works on little endian. - if (!IsLittleEndian) + // These optimizations only work on little endian. + if (!DAG.getDataLayout().isLittleEndian()) return SDValue(); // uzp1(bitcast(x), bitcast(y)) -> uzp1(x, y) @@ -21437,21 +21525,28 @@ static SDValue performUzpCombine(SDNode *N, SelectionDAG &DAG, if (ResVT != MVT::v2i32 && ResVT != MVT::v4i16 && ResVT != MVT::v8i8) return SDValue(); - auto getSourceOp = [](SDValue Operand) -> SDValue { - const unsigned Opcode = Operand.getOpcode(); - if (Opcode == ISD::TRUNCATE) - return Operand->getOperand(0); - if (Opcode == ISD::BITCAST && - Operand->getOperand(0).getOpcode() == ISD::TRUNCATE) - return Operand->getOperand(0)->getOperand(0); - return SDValue(); - }; + SDValue SourceOp0 = peekThroughBitcasts(Op0); + SDValue SourceOp1 = peekThroughBitcasts(Op1); - SDValue SourceOp0 = getSourceOp(Op0); - SDValue SourceOp1 = getSourceOp(Op1); + // truncating uzp1(x, y) -> xtn(concat (x, y)) + if (SourceOp0.getValueType() == SourceOp1.getValueType()) { + EVT Op0Ty = SourceOp0.getValueType(); + if ((ResVT == MVT::v4i16 && Op0Ty == MVT::v2i32) || + (ResVT == MVT::v8i8 && Op0Ty == MVT::v4i16)) { + SDValue Concat = + DAG.getNode(ISD::CONCAT_VECTORS, DL, + Op0Ty.getDoubleNumVectorElementsVT(*DAG.getContext()), + SourceOp0, SourceOp1); + return DAG.getNode(ISD::TRUNCATE, DL, ResVT, Concat); + } + } - if (!SourceOp0 || !SourceOp1) + // uzp1(xtn x, xtn y) -> xtn(uzp1 (x, y)) + if (SourceOp0.getOpcode() != ISD::TRUNCATE || + SourceOp1.getOpcode() != ISD::TRUNCATE) return SDValue(); + SourceOp0 = SourceOp0.getOperand(0); + SourceOp1 = SourceOp1.getOperand(0); if (SourceOp0.getValueType() != SourceOp1.getValueType() || !SourceOp0.getValueType().isSimple()) diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h index 68341c199e0a2a17714151e4840ed0ab9c03b5ba..3465f3be8875430f335bebb43de05d91fc28efe2 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -689,6 +689,7 @@ public: StoreInst *SI) const override; bool isLegalAddImmediate(int64_t) const override; + bool isLegalAddScalableImmediate(int64_t) const override; bool isLegalICmpImmediate(int64_t) const override; bool isMulAddWithConstProfitable(SDValue AddNode, @@ -968,12 +969,12 @@ public: bool shouldExpandCttzElements(EVT VT) const override; /// If a change in streaming mode is required on entry to/return from a - /// function call it emits and returns the corresponding SMSTART or SMSTOP node. - /// \p Entry tells whether this is before/after the Call, which is necessary - /// because PSTATE.SM is only queried once. + /// function call it emits and returns the corresponding SMSTART or SMSTOP + /// node. \p Condition should be one of the enum values from + /// AArch64SME::ToggleCondition. SDValue changeStreamingMode(SelectionDAG &DAG, SDLoc DL, bool Enable, - SDValue Chain, SDValue InGlue, - SDValue PStateSM, bool Entry) const; + SDValue Chain, SDValue InGlue, unsigned Condition, + SDValue PStateSM = SDValue()) const; bool isVScaleKnownToBeAPowerOfTwo() const override { return true; } diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index 02943b8a4ab158dd5fe2034aab1df2b682ca88bb..d0c5e6b99e9eec22ba94c765ebe56ab4dd55d5e3 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -2687,10 +2687,7 @@ bool AArch64InstrInfo::getMemOperandsWithOffsetWidth( return false; // The maximum vscale is 16 under AArch64, return the maximal extent for the // vector. - Width = WidthN.isScalable() - ? WidthN.getKnownMinValue() * AArch64::SVEMaxBitsPerVector / - AArch64::SVEBitsPerBlock - : WidthN.getKnownMinValue(); + Width = LocationSize::precise(WidthN); BaseOps.push_back(BaseOp); return true; } diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index 6254e68326f79df2d584348c0c6f2e2f618cc044..b1f514f75207f00ef97abae76d094080d4208a8c 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -6153,26 +6153,39 @@ defm UZP2 : SIMDZipVector<0b101, "uzp2", AArch64uzp2>; defm ZIP1 : SIMDZipVector<0b011, "zip1", AArch64zip1>; defm ZIP2 : SIMDZipVector<0b111, "zip2", AArch64zip2>; -def : Pat<(v16i8 (concat_vectors (v8i8 (trunc (v8i16 V128:$Vn))), - (v8i8 (trunc (v8i16 V128:$Vm))))), - (UZP1v16i8 V128:$Vn, V128:$Vm)>; -def : Pat<(v8i16 (concat_vectors (v4i16 (trunc (v4i32 V128:$Vn))), - (v4i16 (trunc (v4i32 V128:$Vm))))), - (UZP1v8i16 V128:$Vn, V128:$Vm)>; -def : Pat<(v4i32 (concat_vectors (v2i32 (trunc (v2i64 V128:$Vn))), - (v2i32 (trunc (v2i64 V128:$Vm))))), - (UZP1v4i32 V128:$Vn, V128:$Vm)>; -// These are the same as above, with an optional assertzext node that can be -// generated from fptoi lowering. -def : Pat<(v16i8 (concat_vectors (v8i8 (assertzext (trunc (v8i16 V128:$Vn)))), - (v8i8 (assertzext (trunc (v8i16 V128:$Vm)))))), - (UZP1v16i8 V128:$Vn, V128:$Vm)>; -def : Pat<(v8i16 (concat_vectors (v4i16 (assertzext (trunc (v4i32 V128:$Vn)))), - (v4i16 (assertzext (trunc (v4i32 V128:$Vm)))))), - (UZP1v8i16 V128:$Vn, V128:$Vm)>; -def : Pat<(v4i32 (concat_vectors (v2i32 (assertzext (trunc (v2i64 V128:$Vn)))), - (v2i32 (assertzext (trunc (v2i64 V128:$Vm)))))), - (UZP1v4i32 V128:$Vn, V128:$Vm)>; +def trunc_optional_assert_ext : PatFrags<(ops node:$op0), + [(trunc node:$op0), + (assertzext (trunc node:$op0)), + (assertsext (trunc node:$op0))]>; + +// concat_vectors(trunc(x), trunc(y)) -> uzp1(x, y) +// concat_vectors(assertzext(trunc(x)), assertzext(trunc(y))) -> uzp1(x, y) +// concat_vectors(assertsext(trunc(x)), assertsext(trunc(y))) -> uzp1(x, y) +class concat_trunc_to_uzp1_pat<ValueType SrcTy, ValueType TruncTy, ValueType ConcatTy> + : Pat<(ConcatTy (concat_vectors (TruncTy (trunc_optional_assert_ext (SrcTy V128:$Vn))), + (TruncTy (trunc_optional_assert_ext (SrcTy V128:$Vm))))), + (!cast<Instruction>("UZP1"#ConcatTy) V128:$Vn, V128:$Vm)>; +def : concat_trunc_to_uzp1_pat<v8i16, v8i8, v16i8>; +def : concat_trunc_to_uzp1_pat<v4i32, v4i16, v8i16>; +def : concat_trunc_to_uzp1_pat<v2i64, v2i32, v4i32>; + +// trunc(concat_vectors(trunc(x), trunc(y))) -> xtn(uzp1(x, y)) +// trunc(concat_vectors(assertzext(trunc(x)), assertzext(trunc(y)))) -> xtn(uzp1(x, y)) +// trunc(concat_vectors(assertsext(trunc(x)), assertsext(trunc(y)))) -> xtn(uzp1(x, y)) +class trunc_concat_trunc_to_xtn_uzp1_pat<ValueType SrcTy, ValueType TruncTy, ValueType ConcatTy, + ValueType Ty> + : Pat<(Ty (trunc_optional_assert_ext + (ConcatTy (concat_vectors + (TruncTy (trunc_optional_assert_ext (SrcTy V128:$Vn))), + (TruncTy (trunc_optional_assert_ext (SrcTy V128:$Vm))))))), + (!cast<Instruction>("XTN"#Ty) (!cast<Instruction>("UZP1"#ConcatTy) V128:$Vn, V128:$Vm))>; +def : trunc_concat_trunc_to_xtn_uzp1_pat<v4i32, v4i16, v8i16, v8i8>; +def : trunc_concat_trunc_to_xtn_uzp1_pat<v2i64, v2i32, v4i32, v4i16>; + +def : Pat<(v8i8 (trunc (concat_vectors (v4i16 V64:$Vn), (v4i16 V64:$Vm)))), + (UZP1v8i8 V64:$Vn, V64:$Vm)>; +def : Pat<(v4i16 (trunc (concat_vectors (v2i32 V64:$Vn), (v2i32 V64:$Vm)))), + (UZP1v4i16 V64:$Vn, V64:$Vm)>; def : Pat<(v16i8 (concat_vectors (v8i8 (trunc (AArch64vlshr (v8i16 V128:$Vn), (i32 8)))), @@ -8423,6 +8436,9 @@ def ubsan_trap_xform : SDNodeXForm<timm, [{ return CurDAG->getTargetConstant(N->getZExtValue() | ('U' << 8), SDLoc(N), MVT::i32); }]>; +def gi_ubsan_trap_xform : GICustomOperandRenderer<"renderUbsanTrap">, + GISDNodeXFormEquiv<ubsan_trap_xform>; + def ubsan_trap_imm : TImmLeaf<i32, [{ return isUInt<8>(Imm); }], ubsan_trap_xform>; diff --git a/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp b/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp index 0ab2c401b1749ddfaf6f3334cf694f4838b4513d..d0adb78b231a761106cb555508569250a1091350 100644 --- a/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp +++ b/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp @@ -2362,7 +2362,7 @@ bool AArch64LoadStoreOpt::tryToPairLdStInst(MachineBasicBlock::iterator &MBBI) { // Get the needed alignments to check them if // ldp-aligned-only/stp-aligned-only features are opted. uint64_t MemAlignment = MemOp->getAlign().value(); - uint64_t TypeAlignment = Align(MemOp->getSize()).value(); + uint64_t TypeAlignment = Align(MemOp->getSize().getValue()).value(); if (MemAlignment < 2 * TypeAlignment) { NumFailedAlignmentCheck++; diff --git a/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp b/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp index 6865850cf04febd184cb4ff18014f08fa9e86c54..22da7ddef98a2a83d7cb6df21afe1340e9691513 100644 --- a/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp +++ b/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp @@ -680,9 +680,11 @@ bool AArch64MIPeepholeOpt::visitFMOVDr(MachineInstr &MI) { // Let's remove MIs for high 64-bits. Register OldDef = MI.getOperand(0).getReg(); Register NewDef = MI.getOperand(1).getReg(); + LLVM_DEBUG(dbgs() << "Removing: " << MI << "\n"); + MRI->clearKillFlags(OldDef); + MRI->clearKillFlags(NewDef); MRI->constrainRegClass(NewDef, MRI->getRegClass(OldDef)); MRI->replaceRegWith(OldDef, NewDef); - LLVM_DEBUG(dbgs() << "Removed: " << MI << "\n"); MI.eraseFromParent(); return true; diff --git a/bolt/lib/Profile/ProfileReaderBase.cpp b/llvm/lib/Target/AArch64/AArch64PassRegistry.def similarity index 52% rename from bolt/lib/Profile/ProfileReaderBase.cpp rename to llvm/lib/Target/AArch64/AArch64PassRegistry.def index ee6166b1da369ec9b063481a1ca0e42f49af350a..ca944579f93a935f981d0b490a517cb561fad11c 100644 --- a/bolt/lib/Profile/ProfileReaderBase.cpp +++ b/llvm/lib/Target/AArch64/AArch64PassRegistry.def @@ -1,4 +1,4 @@ -//===- bolt/Profile/ProfileReaderBase.cpp ---------------------------------===// +//===- AArch64PassRegistry.def - Registry of AArch64 passes -----*- 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,18 +6,15 @@ // //===----------------------------------------------------------------------===// // -// Interface to be implemented by all profile readers. +// This file is used as the registry of passes that are part of the +// AArch64 backend. // //===----------------------------------------------------------------------===// -#include "bolt/Profile/ProfileReaderBase.h" +// NOTE: NO INCLUDE GUARD DESIRED! -namespace llvm { -namespace bolt { - -bool ProfileReaderBase::mayHaveProfileData(const BinaryFunction &BF) { - return true; -} - -} // namespace bolt -} // namespace llvm +#ifndef LOOP_PASS +#define LOOP_PASS(NAME, CREATE_PASS) +#endif +LOOP_PASS("aarch64-lit", AArch64LoopIdiomTransformPass()) +#undef LOOP_PASS diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp index ec59778cbb0efa42de14b0a5a7723dcf04fcaa1e..ad29003f1e817387c58ca2d946676c5d120e5f74 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -1072,3 +1072,8 @@ bool AArch64RegisterInfo::shouldCoalesce( return true; } + +bool AArch64RegisterInfo::shouldAnalyzePhysregInMachineLoopInfo( + MCRegister R) const { + return R == AArch64::VG; +} diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h index e93352c13b3c720153b80edae1d815e97c512296..5c8a5e029584fc68905e78d0098a0bb6038ba85b 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.h +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.h @@ -145,6 +145,8 @@ public: void getOffsetOpcodes(const StackOffset &Offset, SmallVectorImpl<uint64_t> &Ops) const override; + + bool shouldAnalyzePhysregInMachineLoopInfo(MCRegister R) const override; }; } // end namespace llvm diff --git a/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td index 2907ba74ff8108e8f9afeaca469fa5944a1bc2f6..2db0fa253434501f487e16621a4609a5eff74471 100644 --- a/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td @@ -10,12 +10,12 @@ // //===----------------------------------------------------------------------===// -def AArch64_smstart : SDNode<"AArch64ISD::SMSTART", SDTypeProfile<0, 3, - [SDTCisInt<0>, SDTCisInt<0>, SDTCisInt<0>]>, +def AArch64_smstart : SDNode<"AArch64ISD::SMSTART", SDTypeProfile<0, 2, + [SDTCisInt<0>, SDTCisInt<0>]>, [SDNPHasChain, SDNPSideEffect, SDNPVariadic, SDNPOptInGlue, SDNPOutGlue]>; -def AArch64_smstop : SDNode<"AArch64ISD::SMSTOP", SDTypeProfile<0, 3, - [SDTCisInt<0>, SDTCisInt<0>, SDTCisInt<0>]>, +def AArch64_smstop : SDNode<"AArch64ISD::SMSTOP", SDTypeProfile<0, 2, + [SDTCisInt<0>, SDTCisInt<0>]>, [SDNPHasChain, SDNPSideEffect, SDNPVariadic, SDNPOptInGlue, SDNPOutGlue]>; def AArch64_restore_za : SDNode<"AArch64ISD::RESTORE_ZA", SDTypeProfile<0, 3, @@ -29,7 +29,7 @@ def AArch64_save_zt : SDNode<"AArch64ISD::SAVE_ZT", SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisPtrTy<1>]>, [SDNPHasChain, SDNPSideEffect, SDNPMayStore]>; def AArch64CoalescerBarrier - : SDNode<"AArch64ISD::COALESCER_BARRIER", SDTypeProfile<1, 1, []>, []>; + : SDNode<"AArch64ISD::COALESCER_BARRIER", SDTypeProfile<1, 1, []>, [SDNPOptInGlue, SDNPOutGlue]>; //===----------------------------------------------------------------------===// // Instruction naming conventions. @@ -158,40 +158,14 @@ def : Pat<(AArch64_restore_za (i64 GPR64:$tpidr2_el0), (i64 GPR64sp:$tpidr2obj), (i64 texternalsym:$restore_routine)), (RestoreZAPseudo GPR64:$tpidr2_el0, GPR64sp:$tpidr2obj, texternalsym:$restore_routine)>; -// Scenario A: -// -// %pstate.before.call = 1 -// if (%pstate.before.call != 0) -// smstop (pstate_za|pstate_sm) -// call fn() -// if (%pstate.before.call != 0) -// smstart (pstate_za|pstate_sm) -// -def : Pat<(AArch64_smstop (i32 svcr_op:$pstate), (i64 1), (i64 0)), // before call - (MSRpstatesvcrImm1 svcr_op:$pstate, 0b0)>; -def : Pat<(AArch64_smstart (i32 svcr_op:$pstate), (i64 1), (i64 0)), // after call - (MSRpstatesvcrImm1 svcr_op:$pstate, 0b1)>; - -// Scenario B: -// -// %pstate.before.call = 0 -// if (%pstate.before.call != 1) -// smstart (pstate_za|pstate_sm) -// call fn() -// if (%pstate.before.call != 1) -// smstop (pstate_za|pstate_sm) -// -def : Pat<(AArch64_smstart (i32 svcr_op:$pstate), (i64 0), (i64 1)), // before call - (MSRpstatesvcrImm1 svcr_op:$pstate, 0b1)>; -def : Pat<(AArch64_smstop (i32 svcr_op:$pstate), (i64 0), (i64 1)), // after call - (MSRpstatesvcrImm1 svcr_op:$pstate, 0b0)>; - // Read and write TPIDR2_EL0 def : Pat<(int_aarch64_sme_set_tpidr2 i64:$val), (MSR 0xde85, GPR64:$val)>; def : Pat<(i64 (int_aarch64_sme_get_tpidr2)), (MRS 0xde85)>; +} // End let Predicates = [HasSME] + multiclass CoalescerBarrierPseudo<RegisterClass rc, list<ValueType> vts> { def NAME : Pseudo<(outs rc:$dst), (ins rc:$src), []>, Sched<[]> { let Constraints = "$dst = $src"; @@ -211,8 +185,6 @@ multiclass CoalescerBarriers { defm COALESCER_BARRIER : CoalescerBarriers; -} // End let Predicates = [HasSME] - // Pseudo to match to smstart/smstop. This expands: // // pseudonode (pstate_za|pstate_sm), before_call, expected_value @@ -230,17 +202,24 @@ defm COALESCER_BARRIER : CoalescerBarriers; // SME instructions. def MSRpstatePseudo : Pseudo<(outs), - (ins svcr_op:$pstatefield, timm0_1:$imm, GPR64:$rtpstate, timm0_1:$expected_pstate, variable_ops), []>, + (ins svcr_op:$pstatefield, timm0_1:$imm, timm0_31:$condition, variable_ops), []>, Sched<[WriteSys]> { let hasPostISelHook = 1; let Uses = [VG]; let Defs = [VG]; } -def : Pat<(AArch64_smstart (i32 svcr_op:$pstate), (i64 GPR64:$rtpstate), (i64 timm0_1:$expected_pstate)), - (MSRpstatePseudo svcr_op:$pstate, 0b1, GPR64:$rtpstate, timm0_1:$expected_pstate)>; -def : Pat<(AArch64_smstop (i32 svcr_op:$pstate), (i64 GPR64:$rtpstate), (i64 timm0_1:$expected_pstate)), - (MSRpstatePseudo svcr_op:$pstate, 0b0, GPR64:$rtpstate, timm0_1:$expected_pstate)>; +def : Pat<(AArch64_smstart (i32 svcr_op:$pstate), (i64 timm0_31:$condition)), + (MSRpstatePseudo svcr_op:$pstate, 0b1, timm0_31:$condition)>; +def : Pat<(AArch64_smstop (i32 svcr_op:$pstate), (i64 timm0_31:$condition)), + (MSRpstatePseudo svcr_op:$pstate, 0b0, timm0_31:$condition)>; + +// Unconditional start/stop +def : Pat<(AArch64_smstart (i32 svcr_op:$pstate), (i64 /*AArch64SME::Always*/0)), + (MSRpstatesvcrImm1 svcr_op:$pstate, 0b1)>; +def : Pat<(AArch64_smstop (i32 svcr_op:$pstate), (i64 /*AArch64SME::Always*/0)), + (MSRpstatesvcrImm1 svcr_op:$pstate, 0b0)>; + //===----------------------------------------------------------------------===// // SME2 Instructions diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td index e0a010af415534f790379ad813da6520bd7af663..dd5e11c0f5e35de12d8a6f61f02804436fbd3714 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -2042,9 +2042,8 @@ let Predicates = [HasSVEorSME] in { defm CNTP_XPP : sve_int_pcount_pred<0b0000, "cntp", int_aarch64_sve_cntp>; def : Pat<(i64 (AArch64CttzElts nxv16i1:$Op1)), - (i64 (!cast<Instruction>(CNTP_XPP_B) - (nxv16i1 (!cast<Instruction>(BRKB_PPzP) (PTRUE_B 31), nxv16i1:$Op1)), - (nxv16i1 (!cast<Instruction>(BRKB_PPzP) (PTRUE_B 31), nxv16i1:$Op1))))>; + (CNTP_XPP_B (BRKB_PPzP (PTRUE_B 31), PPR:$Op1), + (BRKB_PPzP (PTRUE_B 31), PPR:$Op1))>; } defm INCB_XPiI : sve_int_pred_pattern_a<0b000, "incb", add, int_aarch64_sve_cntb>; @@ -2131,15 +2130,12 @@ let Predicates = [HasSVEorSME] in { defm DECP_ZP : sve_int_count_v<0b10100, "decp">; def : Pat<(i64 (add GPR64:$Op1, (i64 (AArch64CttzElts nxv16i1:$Op2)))), - (i64 (!cast<Instruction>(INCP_XP_B) - (nxv16i1 (!cast<Instruction>(BRKB_PPzP) (PTRUE_B 31), nxv16i1:$Op2)), - GPR64:$Op1))>; + (INCP_XP_B (BRKB_PPzP (PTRUE_B 31), PPR:$Op2), GPR64:$Op1)>; def : Pat<(i32 (add GPR32:$Op1, (trunc (i64 (AArch64CttzElts nxv16i1:$Op2))))), - (i32 (EXTRACT_SUBREG (i64 (!cast<Instruction>(INCP_XP_B) - (nxv16i1 (!cast<Instruction>(BRKB_PPzP) (PTRUE_B 31), nxv16i1:$Op2)), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$Op1, sub_32))), - sub_32))>; + (EXTRACT_SUBREG (INCP_XP_B (BRKB_PPzP (PTRUE_B 31), PPR:$Op2), + (INSERT_SUBREG (IMPLICIT_DEF), GPR32:$Op1, sub_32)), + sub_32)>; defm INDEX_RR : sve_int_index_rr<"index", AArch64mul_p_oneuse>; defm INDEX_IR : sve_int_index_ir<"index", AArch64mul_p, AArch64mul_p_oneuse>; @@ -2521,9 +2517,9 @@ let Predicates = [HasSVEorSME] in { (ADDVL_XXI GPR64:$op, $imm)>; def : Pat<(add GPR32:$op, (i32 (trunc (vscale (sve_rdvl_imm i32:$imm))))), - (i32 (EXTRACT_SUBREG (ADDVL_XXI (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - GPR32:$op, sub_32), $imm), - sub_32))>; + (EXTRACT_SUBREG (ADDVL_XXI (INSERT_SUBREG (IMPLICIT_DEF), + GPR32:$op, sub_32), $imm), + sub_32)>; def : Pat<(add GPR64:$op, (vscale (sve_cnth_imm i32:$imm))), (INCH_XPiI GPR64:$op, 31, $imm)>; @@ -2540,30 +2536,30 @@ let Predicates = [HasSVEorSME] in { (DECD_XPiI GPR64:$op, 31, $imm)>; def : Pat<(add GPR32:$op, (i32 (trunc (vscale (sve_cnth_imm i32:$imm))))), - (i32 (EXTRACT_SUBREG (INCH_XPiI (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - GPR32:$op, sub_32), 31, $imm), - sub_32))>; + (EXTRACT_SUBREG (INCH_XPiI (INSERT_SUBREG (IMPLICIT_DEF), + GPR32:$op, sub_32), 31, $imm), + sub_32)>; def : Pat<(add GPR32:$op, (i32 (trunc (vscale (sve_cntw_imm i32:$imm))))), - (i32 (EXTRACT_SUBREG (INCW_XPiI (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - GPR32:$op, sub_32), 31, $imm), - sub_32))>; + (EXTRACT_SUBREG (INCW_XPiI (INSERT_SUBREG (IMPLICIT_DEF), + GPR32:$op, sub_32), 31, $imm), + sub_32)>; def : Pat<(add GPR32:$op, (i32 (trunc (vscale (sve_cntd_imm i32:$imm))))), - (i32 (EXTRACT_SUBREG (INCD_XPiI (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - GPR32:$op, sub_32), 31, $imm), - sub_32))>; + (EXTRACT_SUBREG (INCD_XPiI (INSERT_SUBREG (IMPLICIT_DEF), + GPR32:$op, sub_32), 31, $imm), + sub_32)>; def : Pat<(add GPR32:$op, (i32 (trunc (vscale (sve_cnth_imm_neg i32:$imm))))), - (i32 (EXTRACT_SUBREG (DECH_XPiI (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - GPR32:$op, sub_32), 31, $imm), - sub_32))>; + (EXTRACT_SUBREG (DECH_XPiI (INSERT_SUBREG (IMPLICIT_DEF), + GPR32:$op, sub_32), 31, $imm), + sub_32)>; def : Pat<(add GPR32:$op, (i32 (trunc (vscale (sve_cntw_imm_neg i32:$imm))))), - (i32 (EXTRACT_SUBREG (DECW_XPiI (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - GPR32:$op, sub_32), 31, $imm), - sub_32))>; + (EXTRACT_SUBREG (DECW_XPiI (INSERT_SUBREG (IMPLICIT_DEF), + GPR32:$op, sub_32), 31, $imm), + sub_32)>; def : Pat<(add GPR32:$op, (i32 (trunc (vscale (sve_cntd_imm_neg i32:$imm))))), - (i32 (EXTRACT_SUBREG (DECD_XPiI (INSERT_SUBREG (i64 (IMPLICIT_DEF)), - GPR32:$op, sub_32), 31, $imm), - sub_32))>; + (EXTRACT_SUBREG (DECD_XPiI (INSERT_SUBREG (IMPLICIT_DEF), + GPR32:$op, sub_32), 31, $imm), + sub_32)>; } // FIXME: BigEndian requires an additional REV instruction to satisfy the @@ -3266,58 +3262,58 @@ let Predicates = [HasSVEorSME] in { // Extract element from vector with immediate index that's within the bottom 128-bits. let Predicates = [IsNeonAvailable], AddedComplexity = 1 in { def : Pat<(i32 (vector_extract (nxv16i8 ZPR:$vec), VectorIndexB:$index)), - (i32 (UMOVvi8 (v16i8 (EXTRACT_SUBREG ZPR:$vec, zsub)), VectorIndexB:$index))>; + (UMOVvi8 (v16i8 (EXTRACT_SUBREG ZPR:$vec, zsub)), VectorIndexB:$index)>; def : Pat<(i32 (vector_extract (nxv8i16 ZPR:$vec), VectorIndexH:$index)), - (i32 (UMOVvi16 (v8i16 (EXTRACT_SUBREG ZPR:$vec, zsub)), VectorIndexH:$index))>; + (UMOVvi16 (v8i16 (EXTRACT_SUBREG ZPR:$vec, zsub)), VectorIndexH:$index)>; def : Pat<(i32 (vector_extract (nxv4i32 ZPR:$vec), VectorIndexS:$index)), - (i32 (UMOVvi32 (v4i32 (EXTRACT_SUBREG ZPR:$vec, zsub)), VectorIndexS:$index))>; + (UMOVvi32 (v4i32 (EXTRACT_SUBREG ZPR:$vec, zsub)), VectorIndexS:$index)>; def : Pat<(i64 (vector_extract (nxv2i64 ZPR:$vec), VectorIndexD:$index)), - (i64 (UMOVvi64 (v2i64 (EXTRACT_SUBREG ZPR:$vec, zsub)), VectorIndexD:$index))>; + (UMOVvi64 (v2i64 (EXTRACT_SUBREG ZPR:$vec, zsub)), VectorIndexD:$index)>; } // End IsNeonAvailable let Predicates = [IsNeonAvailable] in { def : Pat<(sext_inreg (vector_extract (nxv16i8 ZPR:$vec), VectorIndexB:$index), i8), - (i32 (SMOVvi8to32 (v16i8 (EXTRACT_SUBREG ZPR:$vec, zsub)), VectorIndexB:$index))>; + (SMOVvi8to32 (v16i8 (EXTRACT_SUBREG ZPR:$vec, zsub)), VectorIndexB:$index)>; def : Pat<(sext_inreg (anyext (i32 (vector_extract (nxv16i8 ZPR:$vec), VectorIndexB:$index))), i8), - (i64 (SMOVvi8to64 (v16i8 (EXTRACT_SUBREG ZPR:$vec, zsub)), VectorIndexB:$index))>; + (SMOVvi8to64 (v16i8 (EXTRACT_SUBREG ZPR:$vec, zsub)), VectorIndexB:$index)>; def : Pat<(sext_inreg (vector_extract (nxv8i16 ZPR:$vec), VectorIndexH:$index), i16), - (i32 (SMOVvi16to32 (v8i16 (EXTRACT_SUBREG ZPR:$vec, zsub)), VectorIndexH:$index))>; + (SMOVvi16to32 (v8i16 (EXTRACT_SUBREG ZPR:$vec, zsub)), VectorIndexH:$index)>; def : Pat<(sext_inreg (anyext (i32 (vector_extract (nxv8i16 ZPR:$vec), VectorIndexH:$index))), i16), - (i64 (SMOVvi16to64 (v8i16 (EXTRACT_SUBREG ZPR:$vec, zsub)), VectorIndexH:$index))>; + (SMOVvi16to64 (v8i16 (EXTRACT_SUBREG ZPR:$vec, zsub)), VectorIndexH:$index)>; def : Pat<(sext (i32 (vector_extract (nxv4i32 ZPR:$vec), VectorIndexS:$index))), - (i64 (SMOVvi32to64 (v4i32 (EXTRACT_SUBREG ZPR:$vec, zsub)), VectorIndexS:$index))>; + (SMOVvi32to64 (v4i32 (EXTRACT_SUBREG ZPR:$vec, zsub)), VectorIndexS:$index)>; } // End IsNeonAvailable // Extract first element from vector. let AddedComplexity = 2 in { - def : Pat<(vector_extract (nxv16i8 ZPR:$Zs), (i64 0)), - (i32 (EXTRACT_SUBREG ZPR:$Zs, ssub))>; - def : Pat<(vector_extract (nxv8i16 ZPR:$Zs), (i64 0)), - (i32 (EXTRACT_SUBREG ZPR:$Zs, ssub))>; - def : Pat<(vector_extract (nxv4i32 ZPR:$Zs), (i64 0)), - (i32 (EXTRACT_SUBREG ZPR:$Zs, ssub))>; - def : Pat<(vector_extract (nxv2i64 ZPR:$Zs), (i64 0)), - (i64 (EXTRACT_SUBREG ZPR:$Zs, dsub))>; - def : Pat<(vector_extract (nxv8f16 ZPR:$Zs), (i64 0)), - (f16 (EXTRACT_SUBREG ZPR:$Zs, hsub))>; - def : Pat<(vector_extract (nxv4f16 ZPR:$Zs), (i64 0)), - (f16 (EXTRACT_SUBREG ZPR:$Zs, hsub))>; - def : Pat<(vector_extract (nxv2f16 ZPR:$Zs), (i64 0)), - (f16 (EXTRACT_SUBREG ZPR:$Zs, hsub))>; - def : Pat<(vector_extract (nxv8bf16 ZPR:$Zs), (i64 0)), - (bf16 (EXTRACT_SUBREG ZPR:$Zs, hsub))>; - def : Pat<(vector_extract (nxv4bf16 ZPR:$Zs), (i64 0)), - (bf16 (EXTRACT_SUBREG ZPR:$Zs, hsub))>; - def : Pat<(vector_extract (nxv2bf16 ZPR:$Zs), (i64 0)), - (bf16 (EXTRACT_SUBREG ZPR:$Zs, hsub))>; - def : Pat<(vector_extract (nxv4f32 ZPR:$Zs), (i64 0)), - (f32 (EXTRACT_SUBREG ZPR:$Zs, ssub))>; - def : Pat<(vector_extract (nxv2f32 ZPR:$Zs), (i64 0)), - (f32 (EXTRACT_SUBREG ZPR:$Zs, ssub))>; - def : Pat<(vector_extract (nxv2f64 ZPR:$Zs), (i64 0)), - (f64 (EXTRACT_SUBREG ZPR:$Zs, dsub))>; + def : Pat<(i32 (vector_extract (nxv16i8 ZPR:$Zs), (i64 0))), + (EXTRACT_SUBREG ZPR:$Zs, ssub)>; + def : Pat<(i32 (vector_extract (nxv8i16 ZPR:$Zs), (i64 0))), + (EXTRACT_SUBREG ZPR:$Zs, ssub)>; + def : Pat<(i32 (vector_extract (nxv4i32 ZPR:$Zs), (i64 0))), + (EXTRACT_SUBREG ZPR:$Zs, ssub)>; + def : Pat<(i64 (vector_extract (nxv2i64 ZPR:$Zs), (i64 0))), + (EXTRACT_SUBREG ZPR:$Zs, dsub)>; + def : Pat<(f16 (vector_extract (nxv8f16 ZPR:$Zs), (i64 0))), + (EXTRACT_SUBREG ZPR:$Zs, hsub)>; + def : Pat<(f16 (vector_extract (nxv4f16 ZPR:$Zs), (i64 0))), + (EXTRACT_SUBREG ZPR:$Zs, hsub)>; + def : Pat<(f16 (vector_extract (nxv2f16 ZPR:$Zs), (i64 0))), + (EXTRACT_SUBREG ZPR:$Zs, hsub)>; + def : Pat<(bf16 (vector_extract (nxv8bf16 ZPR:$Zs), (i64 0))), + (EXTRACT_SUBREG ZPR:$Zs, hsub)>; + def : Pat<(bf16 (vector_extract (nxv4bf16 ZPR:$Zs), (i64 0))), + (EXTRACT_SUBREG ZPR:$Zs, hsub)>; + def : Pat<(bf16 (vector_extract (nxv2bf16 ZPR:$Zs), (i64 0))), + (EXTRACT_SUBREG ZPR:$Zs, hsub)>; + def : Pat<(f32 (vector_extract (nxv4f32 ZPR:$Zs), (i64 0))), + (EXTRACT_SUBREG ZPR:$Zs, ssub)>; + def : Pat<(f32 (vector_extract (nxv2f32 ZPR:$Zs), (i64 0))), + (EXTRACT_SUBREG ZPR:$Zs, ssub)>; + def : Pat<(f64 (vector_extract (nxv2f64 ZPR:$Zs), (i64 0))), + (EXTRACT_SUBREG ZPR:$Zs, dsub)>; } multiclass sve_predicated_add<SDNode extend, int value> { diff --git a/llvm/lib/Target/AArch64/AArch64SchedAmpere1.td b/llvm/lib/Target/AArch64/AArch64SchedAmpere1.td index cf9f50c2784bbe8fc6420f7cd42268d5777c60b7..269f4ec5e5fb16266eed65fc4cbf8a337ce74244 100644 --- a/llvm/lib/Target/AArch64/AArch64SchedAmpere1.td +++ b/llvm/lib/Target/AArch64/AArch64SchedAmpere1.td @@ -18,7 +18,7 @@ def Ampere1Model : SchedMachineModel { let IssueWidth = 4; // 4-way decode and dispatch - let MicroOpBufferSize = 174; // micro-op re-order buffer size + let MicroOpBufferSize = 192; // re-order buffer size let LoadLatency = 4; // Optimistic load latency let MispredictPenalty = 10; // Branch mispredict penalty let LoopMicroOpBufferSize = 32; // Instruction queue size diff --git a/llvm/lib/Target/AArch64/AArch64SchedAmpere1B.td b/llvm/lib/Target/AArch64/AArch64SchedAmpere1B.td index 9c4f000cf351b265776fd8639919f3b26cb02150..67f8593f1577a3037ef3186150d62781933d70b3 100644 --- a/llvm/lib/Target/AArch64/AArch64SchedAmpere1B.td +++ b/llvm/lib/Target/AArch64/AArch64SchedAmpere1B.td @@ -18,7 +18,7 @@ def Ampere1BModel : SchedMachineModel { let IssueWidth = 12; // Maximum micro-ops dispatch rate. - let MicroOpBufferSize = 192; // micro-op re-order buffer size + let MicroOpBufferSize = 208; // micro-op re-order buffer size let LoadLatency = 3; // Optimistic load latency let MispredictPenalty = 10; // Branch mispredict penalty let LoopMicroOpBufferSize = 32; // Instruction queue size diff --git a/llvm/lib/Target/AArch64/AArch64SchedNeoverseV1.td b/llvm/lib/Target/AArch64/AArch64SchedNeoverseV1.td index c7dfd64b2fb24e77ba373b57eb3129453f28f838..f7e6545f0dd386870707617fbb779ae30968e1a9 100644 --- a/llvm/lib/Target/AArch64/AArch64SchedNeoverseV1.td +++ b/llvm/lib/Target/AArch64/AArch64SchedNeoverseV1.td @@ -1446,7 +1446,7 @@ def : InstRW<[V1Write_3c_1V01], (instregex "^[SU]DOT_ZZZI?_S$")>; def : InstRW<[V1Write_3c_1V], (instrs SUDOT_ZZZI, USDOT_ZZZ, USDOT_ZZZI)>; // Dot product, 16 bit -def : InstRW<[V1Write_4c_1V01], (instregex "^[SU]DOT_ZZZI?_D$")>; +def : InstRW<[V1Write_4c_1V0], (instregex "^[SU]DOT_ZZZI?_D$")>; // Duplicate, immediate and indexed form def : InstRW<[V1Write_2c_1V01], (instregex "^DUP_ZI_[BHSD]$", diff --git a/llvm/lib/Target/AArch64/AArch64SchedNeoverseV2.td b/llvm/lib/Target/AArch64/AArch64SchedNeoverseV2.td index f10b94523d2e035e8c114c0899814d7904099598..4d7f44e7b9b9ab15c50d304d373bdfc9dc9ec032 100644 --- a/llvm/lib/Target/AArch64/AArch64SchedNeoverseV2.td +++ b/llvm/lib/Target/AArch64/AArch64SchedNeoverseV2.td @@ -1076,14 +1076,12 @@ def V2Write_7cyc_1V02_7rc : SchedWriteRes<[V2UnitV02]> { let Latency = 7; let def V2Write_10cyc_1V02_5rc : SchedWriteRes<[V2UnitV02]> { let Latency = 10; let ReleaseAtCycles = [ 5]; } def V2Write_10cyc_1V02_9rc : SchedWriteRes<[V2UnitV02]> { let Latency = 10; let ReleaseAtCycles = [ 9]; } def V2Write_10cyc_1V02_10rc : SchedWriteRes<[V2UnitV02]> { let Latency = 10; let ReleaseAtCycles = [10]; } -def V2Write_10cyc_1V0_9rc : SchedWriteRes<[V2UnitV0]> { let Latency = 10; let ReleaseAtCycles = [ 9]; } def V2Write_10cyc_1V1_9rc : SchedWriteRes<[V2UnitV1]> { let Latency = 10; let ReleaseAtCycles = [ 9]; } -def V2Write_13cyc_1V0_12rc : SchedWriteRes<[V2UnitV0]> { let Latency = 13; let ReleaseAtCycles = [12]; } def V2Write_13cyc_1V02_12rc : SchedWriteRes<[V2UnitV02]> { let Latency = 13; let ReleaseAtCycles = [12]; } def V2Write_13cyc_1V02_13rc : SchedWriteRes<[V2UnitV02]> { let Latency = 13; let ReleaseAtCycles = [13]; } def V2Write_15cyc_1V02_14rc : SchedWriteRes<[V2UnitV02]> { let Latency = 15; let ReleaseAtCycles = [14]; } +def V2Write_16cyc_1V02_14rc : SchedWriteRes<[V2UnitV02]> { let Latency = 16; let ReleaseAtCycles = [14]; } def V2Write_16cyc_1V02_15rc : SchedWriteRes<[V2UnitV02]> { let Latency = 16; let ReleaseAtCycles = [15]; } -def V2Write_16cyc_1V0_14rc : SchedWriteRes<[V2UnitV0]> { let Latency = 16; let ReleaseAtCycles = [14]; } // Miscellaneous // ----------------------------------------------------------------------------- @@ -2567,13 +2565,13 @@ def : InstRW<[V2Write_4cyc_2V02], (instregex "^FRINT[AIMNPXZ]_ZPmZ_S")>; def : InstRW<[V2Write_3cyc_1V02], (instregex "^FRINT[AIMNPXZ]_ZPmZ_D")>; // Floating point square root, F16 -def : InstRW<[V2Write_13cyc_1V0_12rc], (instregex "^FSQRT_ZPmZ_H")>; +def : InstRW<[V2Write_13cyc_1V02_12rc], (instregex "^FSQRT_ZPmZ_H")>; // Floating point square root, F32 -def : InstRW<[V2Write_10cyc_1V0_9rc], (instregex "^FSQRT_ZPmZ_S")>; +def : InstRW<[V2Write_10cyc_1V02_9rc], (instregex "^FSQRT_ZPmZ_S")>; // Floating point square root, F64 -def : InstRW<[V2Write_16cyc_1V0_14rc], (instregex "^FSQRT_ZPmZ_D")>; +def : InstRW<[V2Write_16cyc_1V02_14rc], (instregex "^FSQRT_ZPmZ_D")>; // Floating point trigonometric exponentiation def : InstRW<[V2Write_3cyc_1V1], (instregex "^FEXPA_ZZ_[HSD]")>; diff --git a/llvm/lib/Target/AArch64/AArch64StackTagging.cpp b/llvm/lib/Target/AArch64/AArch64StackTagging.cpp index ef7c517732ef3fad2ea8fd34b412081f9f2caa1f..aabc5d5d22e2d31cf2bc63b495556e45dfbac7bf 100644 --- a/llvm/lib/Target/AArch64/AArch64StackTagging.cpp +++ b/llvm/lib/Target/AArch64/AArch64StackTagging.cpp @@ -532,8 +532,10 @@ bool AArch64StackTagging::runOnFunction(Function &Fn) { ConstantInt::get(IRB.getInt64Ty(), Tag)}); if (Info.AI->hasName()) TagPCall->setName(Info.AI->getName() + ".tag"); - // Does not replace metadata, so we don't have to handle DPValues. - Info.AI->replaceNonMetadataUsesWith(TagPCall); + // Does not replace metadata, so we don't have to handle DbgVariableRecords. + Info.AI->replaceUsesWithIf(TagPCall, [&](const Use &U) { + return !memtag::isLifetimeIntrinsic(U.getUser()); + }); TagPCall->setOperand(0, Info.AI); // Calls to functions that may return twice (e.g. setjmp) confuse the @@ -550,7 +552,7 @@ bool AArch64StackTagging::runOnFunction(Function &Fn) { uint64_t Size = cast<ConstantInt>(Start->getArgOperand(0))->getZExtValue(); Size = alignTo(Size, kTagGranuleSize); - tagAlloca(AI, Start->getNextNode(), Start->getArgOperand(1), Size); + tagAlloca(AI, Start->getNextNode(), TagPCall, Size); auto TagEnd = [&](Instruction *Node) { untagAlloca(AI, Node, Size); }; if (!DT || !PDT || diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp index e5e60459e8148abf7b153891083c26e3ab138877..7d4a57d792a191e89bba5f7760897a97100d22b5 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp @@ -547,6 +547,10 @@ public: void AArch64TargetMachine::registerPassBuilderCallbacks( PassBuilder &PB, bool PopulateClassToPassNames) { + +#define GET_PASS_REGISTRY "AArch64PassRegistry.def" +#include "llvm/Passes/TargetPassRegistry.inc" + PB.registerLateLoopOptimizationsEPCallback( [=](LoopPassManager &LPM, OptimizationLevel Level) { LPM.addPass(AArch64LoopIdiomTransformPass()); @@ -599,7 +603,7 @@ void AArch64PassConfig::addIRPasses() { addPass(createFalkorMarkStridedAccessesPass()); } - if (TM->getOptLevel() == CodeGenOptLevel::Aggressive && EnableGEPOpt) { + if (EnableGEPOpt) { // Call SeparateConstOffsetFromGEP pass to extract constants within indices // and lower a GEP with multiple indices to either arithmetic operations or // multiple GEPs with single index. diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp index 755b034764ed2d372fc85ab759c2028a699164b1..ee7137b92445bb14ecbf8dc98a175ff1ea82cdaf 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp @@ -479,7 +479,7 @@ AArch64TTIImpl::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, return TTI::TCC_Free; break; case Intrinsic::experimental_patchpoint_void: - case Intrinsic::experimental_patchpoint_i64: + case Intrinsic::experimental_patchpoint: if ((Idx < 4) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue()))) return TTI::TCC_Free; break; @@ -1129,7 +1129,7 @@ static std::optional<Instruction *> instCombineSVELast(InstCombiner &IC, auto *NewRHS = IC.Builder.CreateIntrinsic(IntrinsicID, {Vec->getType()}, {Pg, RHS}); auto *NewBinOp = BinaryOperator::CreateWithCopiedFlags( - OpC, NewLHS, NewRHS, OldBinOp, OldBinOp->getName(), &II); + OpC, NewLHS, NewRHS, OldBinOp, OldBinOp->getName(), II.getIterator()); return IC.replaceInstUsesWith(II, NewBinOp); } } diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index b807aaf76fdb006a61080513aa55b13961f3f984..21643ebb413847288cb3677be30485c72e236c21 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -654,7 +654,7 @@ public: return Barrier.HasnXSModifier; } - unsigned getReg() const override { + MCRegister getReg() const override { assert(Kind == k_Register && "Invalid access!"); return Reg.RegNum; } diff --git a/llvm/lib/Target/AArch64/GISel/AArch64GlobalISelUtils.cpp b/llvm/lib/Target/AArch64/GISel/AArch64GlobalISelUtils.cpp index 92db89cc0915b861f46c1c823e7bc90299e8da72..80fe4bcb8b58f7aa6ed3641eda946e5e5718a2a1 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64GlobalISelUtils.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64GlobalISelUtils.cpp @@ -147,6 +147,12 @@ void AArch64GISelUtils::changeFCMPPredToAArch64CC( case CmpInst::FCMP_UNE: CondCode = AArch64CC::NE; break; + case CmpInst::FCMP_TRUE: + CondCode = AArch64CC::AL; + break; + case CmpInst::FCMP_FALSE: + CondCode = AArch64CC::NV; + break; } } diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp index 7a49422c064b7c5a15bbe1053fdf77b2e19fec5e..a8f2c45279e61fc7ccc6ea8648fadafe7b6a6be0 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -479,6 +479,8 @@ private: int OpIdx = -1) const; void renderLogicalImm64(MachineInstrBuilder &MIB, const MachineInstr &I, int OpIdx = -1) const; + void renderUbsanTrap(MachineInstrBuilder &MIB, const MachineInstr &MI, + int OpIdx) const; void renderFPImm16(MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx = -1) const; void renderFPImm32(MachineInstrBuilder &MIB, const MachineInstr &MI, @@ -2852,8 +2854,8 @@ bool AArch64InstructionSelector::select(MachineInstr &I) { return false; } - uint64_t MemSizeInBytes = LdSt.getMemSize(); - unsigned MemSizeInBits = LdSt.getMemSizeInBits(); + uint64_t MemSizeInBytes = LdSt.getMemSize().getValue(); + unsigned MemSizeInBits = LdSt.getMemSizeInBits().getValue(); AtomicOrdering Order = LdSt.getMMO().getSuccessOrdering(); // Need special instructions for atomics that affect ordering. @@ -3276,7 +3278,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) { RBI.getRegBank(SrcReg, MRI, TRI)->getID() == AArch64::GPRRegBankID; if (LoadMI && IsGPR) { const MachineMemOperand *MemOp = *LoadMI->memoperands_begin(); - unsigned BytesLoaded = MemOp->getSize(); + unsigned BytesLoaded = MemOp->getSize().getValue(); if (BytesLoaded < 4 && SrcTy.getSizeInBytes() == BytesLoaded) return selectCopy(I, TII, MRI, TRI, RBI); } @@ -6159,16 +6161,6 @@ bool AArch64InstructionSelector::selectIntrinsicWithSideEffects( constrainSelectedInstRegOperands(*NewI, TII, TRI, RBI); break; } - case Intrinsic::trap: - MIB.buildInstr(AArch64::BRK, {}, {}).addImm(1); - break; - case Intrinsic::debugtrap: - MIB.buildInstr(AArch64::BRK, {}, {}).addImm(0xF000); - break; - case Intrinsic::ubsantrap: - MIB.buildInstr(AArch64::BRK, {}, {}) - .addImm(I.getOperand(1).getImm() | ('U' << 8)); - break; case Intrinsic::aarch64_neon_ld1x2: { LLT Ty = MRI.getType(I.getOperand(0).getReg()); unsigned Opc = 0; @@ -7663,6 +7655,14 @@ void AArch64InstructionSelector::renderLogicalImm64( MIB.addImm(Enc); } +void AArch64InstructionSelector::renderUbsanTrap(MachineInstrBuilder &MIB, + const MachineInstr &MI, + int OpIdx) const { + assert(MI.getOpcode() == TargetOpcode::G_UBSANTRAP && OpIdx == 0 && + "Expected G_UBSANTRAP"); + MIB.addImm(MI.getOperand(0).getImm() | ('U' << 8)); +} + void AArch64InstructionSelector::renderFPImm16(MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const { diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp index 36adada27965314a229f0c6dc0602ee9aeb7afdc..33dba6a5c61eaf078a0904a76ca62f9acf334a87 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp @@ -373,6 +373,11 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) .legalForTypesWithMemDesc( {{s32, p0, s8, 8}, {s32, p0, s16, 8}, {s64, p0, s32, 8}}) .widenScalarToNextPow2(0, /* MinSize = */ 8) + .clampMaxNumElements(0, s8, 16) + .clampMaxNumElements(0, s16, 8) + .clampMaxNumElements(0, s32, 4) + .clampMaxNumElements(0, s64, 2) + .clampMaxNumElements(0, p0, 2) .lowerIfMemSizeNotByteSizePow2() .clampScalar(0, s8, s64) .narrowScalarIf( @@ -383,11 +388,6 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) Query.Types[0].getSizeInBits() > 32; }, changeTo(0, s32)) - .clampMaxNumElements(0, s8, 16) - .clampMaxNumElements(0, s16, 8) - .clampMaxNumElements(0, s32, 4) - .clampMaxNumElements(0, s64, 2) - .clampMaxNumElements(0, p0, 2) // TODO: Use BITCAST for v2i8, v2i16 after G_TRUNC gets sorted out .bitcastIf(typeInSet(0, {v4s8}), [=](const LegalityQuery &Query) { @@ -600,7 +600,7 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) .legalIf(ExtLegalFunc) .legalFor({{v2s64, v2s32}, {v4s32, v4s16}, {v8s16, v8s8}}) .clampScalar(0, s64, s64) // Just for s128, others are handled above. - .moreElementsToNextPow2(1) + .moreElementsToNextPow2(0) .clampMaxNumElements(1, s8, 8) .clampMaxNumElements(1, s16, 4) .clampMaxNumElements(1, s32, 2) @@ -611,7 +611,9 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) Query.Types[0].isVector() && (Query.Types[1].getScalarSizeInBits() == 8 || Query.Types[1].getScalarSizeInBits() == 16); - }); + }) + .clampMinNumElements(1, s8, 8) + .clampMinNumElements(1, s16, 4); getActionDefinitionsBuilder(G_TRUNC) .legalFor({{v2s32, v2s64}, {v4s16, v4s32}, {v8s8, v8s16}}) @@ -628,7 +630,8 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) return DstTy.isVector() && SrcTy.getSizeInBits() > 128 && DstTy.getScalarSizeInBits() * 2 <= SrcTy.getScalarSizeInBits(); }) - + .clampMinNumElements(0, s8, 8) + .clampMinNumElements(0, s16, 4) .alwaysLegal(); getActionDefinitionsBuilder(G_SEXT_INREG) @@ -1010,6 +1013,11 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST) ABSActions .legalFor({s32, s64}); ABSActions.legalFor(PackedVectorAllTypeList) + .customIf([=](const LegalityQuery &Q) { + // TODO: Fix suboptimal codegen for 128+ bit types. + LLT SrcTy = Q.Types[0]; + return SrcTy.isScalar() && SrcTy.getSizeInBits() < 128; + }) .widenScalarIf( [=](const LegalityQuery &Query) { return Query.Types[0] == v4s8; }, [=](const LegalityQuery &Query) { return std::make_pair(0, v4s16); }) @@ -1262,6 +1270,8 @@ bool AArch64LegalizerInfo::legalizeCustom( return legalizeDynStackAlloc(MI, Helper); case TargetOpcode::G_PREFETCH: return legalizePrefetch(MI, Helper); + case TargetOpcode::G_ABS: + return Helper.lowerAbsToCNeg(MI); } llvm_unreachable("expected switch to return"); diff --git a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp index 51c52aad3594975d7deb1fb11a7aef1c34f47329..d8ca5494ba50a489ae6afebe55d0c53e439d3a35 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp @@ -311,7 +311,7 @@ bool matchSplitStoreZero128(MachineInstr &MI, MachineRegisterInfo &MRI) { LLT ValTy = MRI.getType(Store.getValueReg()); if (!ValTy.isVector() || ValTy.getSizeInBits() != 128) return false; - if (ValTy.getSizeInBits() != Store.getMemSizeInBits()) + if (Store.getMemSizeInBits() != ValTy.getSizeInBits()) return false; // Don't split truncating stores. if (!MRI.hasOneNonDBGUse(Store.getValueReg())) return false; @@ -658,7 +658,7 @@ bool AArch64PostLegalizerCombiner::optimizeConsecutiveMemOpAddressing( APInt Offset; LLT StoredValTy = MRI.getType(St->getValueReg()); unsigned ValSize = StoredValTy.getSizeInBits(); - if (ValSize < 32 || ValSize != St->getMMO().getSizeInBits()) + if (ValSize < 32 || St->getMMO().getSizeInBits() != ValSize) continue; Register PtrReg = St->getPointerReg(); diff --git a/llvm/lib/Target/AArch64/SMEInstrFormats.td b/llvm/lib/Target/AArch64/SMEInstrFormats.td index 33cb5f9734b81992182d7be15985a1e1f6750739..44d9a8ac7cb677e05fe72e7f5f6780329b9e1e92 100644 --- a/llvm/lib/Target/AArch64/SMEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SMEInstrFormats.td @@ -223,8 +223,6 @@ def MSRpstatesvcrImm1 let Inst{8} = imm; let Inst{7-5} = 0b011; // op2 let hasPostISelHook = 1; - let Uses = [VG]; - let Defs = [VG]; } def : InstAlias<"smstart", (MSRpstatesvcrImm1 0b011, 0b1)>; diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td index c19e02bb03d1f927c5bd488c48db10da6e8da8c0..1e76d58669da11bc8cfae95350127fad20f74b97 100644 --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -958,39 +958,39 @@ multiclass sve_int_count_r_x64<bits<5> opc, string asm, // combine_op(x, trunc(cntp(all_active, p))) ==> inst p, x def : Pat<(i32 (combine_op GPR32:$Rn, (trunc (int_aarch64_sve_cntp_oneuse (nxv16i1 (SVEAllActive)), (nxv16i1 PPRAny:$pred))))), - (i32 (EXTRACT_SUBREG (!cast<Instruction>(NAME # _B) PPRAny:$pred, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$Rn, sub_32)), - sub_32))>; + (EXTRACT_SUBREG (!cast<Instruction>(NAME # _B) PPRAny:$pred, + (INSERT_SUBREG (IMPLICIT_DEF), GPR32:$Rn, sub_32)), + sub_32)>; def : Pat<(i32 (combine_op GPR32:$Rn, (trunc (int_aarch64_sve_cntp_oneuse (nxv8i1 (SVEAllActive)), (nxv8i1 PPRAny:$pred))))), - (i32 (EXTRACT_SUBREG (!cast<Instruction>(NAME # _H) PPRAny:$pred, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$Rn, sub_32)), - sub_32))>; + (EXTRACT_SUBREG (!cast<Instruction>(NAME # _H) PPRAny:$pred, + (INSERT_SUBREG (IMPLICIT_DEF), GPR32:$Rn, sub_32)), + sub_32)>; def : Pat<(i32 (combine_op GPR32:$Rn, (trunc (int_aarch64_sve_cntp_oneuse (nxv4i1 (SVEAllActive)), (nxv4i1 PPRAny:$pred))))), - (i32 (EXTRACT_SUBREG (!cast<Instruction>(NAME # _S) PPRAny:$pred, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$Rn, sub_32)), - sub_32))>; + (EXTRACT_SUBREG (!cast<Instruction>(NAME # _S) PPRAny:$pred, + (INSERT_SUBREG (IMPLICIT_DEF), GPR32:$Rn, sub_32)), + sub_32)>; def : Pat<(i32 (combine_op GPR32:$Rn, (trunc (int_aarch64_sve_cntp_oneuse (nxv2i1 (SVEAllActive)), (nxv2i1 PPRAny:$pred))))), - (i32 (EXTRACT_SUBREG (!cast<Instruction>(NAME # _D) PPRAny:$pred, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$Rn, sub_32)), - sub_32))>; + (EXTRACT_SUBREG (!cast<Instruction>(NAME # _D) PPRAny:$pred, + (INSERT_SUBREG (IMPLICIT_DEF), GPR32:$Rn, sub_32)), + sub_32)>; // combine_op(x, trunc(cntp(p, p))) ==> inst p, x def : Pat<(i32 (combine_op GPR32:$Rn, (trunc (int_aarch64_sve_cntp_oneuse (nxv16i1 PPRAny:$pred), (nxv16i1 PPRAny:$pred))))), - (i32 (EXTRACT_SUBREG (!cast<Instruction>(NAME # _B) PPRAny:$pred, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$Rn, sub_32)), - sub_32))>; + (EXTRACT_SUBREG (!cast<Instruction>(NAME # _B) PPRAny:$pred, + (INSERT_SUBREG (IMPLICIT_DEF), GPR32:$Rn, sub_32)), + sub_32)>; def : Pat<(i32 (combine_op GPR32:$Rn, (trunc (int_aarch64_sve_cntp_oneuse (nxv8i1 PPRAny:$pred), (nxv8i1 PPRAny:$pred))))), - (i32 (EXTRACT_SUBREG (!cast<Instruction>(NAME # _H) PPRAny:$pred, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$Rn, sub_32)), - sub_32))>; + (EXTRACT_SUBREG (!cast<Instruction>(NAME # _H) PPRAny:$pred, + (INSERT_SUBREG (IMPLICIT_DEF), GPR32:$Rn, sub_32)), + sub_32)>; def : Pat<(i32 (combine_op GPR32:$Rn, (trunc (int_aarch64_sve_cntp_oneuse (nxv4i1 PPRAny:$pred), (nxv4i1 PPRAny:$pred))))), - (i32 (EXTRACT_SUBREG (!cast<Instruction>(NAME # _S) PPRAny:$pred, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$Rn, sub_32)), - sub_32))>; + (EXTRACT_SUBREG (!cast<Instruction>(NAME # _S) PPRAny:$pred, + (INSERT_SUBREG (IMPLICIT_DEF), GPR32:$Rn, sub_32)), + sub_32)>; def : Pat<(i32 (combine_op GPR32:$Rn, (trunc (int_aarch64_sve_cntp_oneuse (nxv2i1 PPRAny:$pred), (nxv2i1 PPRAny:$pred))))), - (i32 (EXTRACT_SUBREG (!cast<Instruction>(NAME # _D) PPRAny:$pred, - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$Rn, sub_32)), - sub_32))>; + (EXTRACT_SUBREG (!cast<Instruction>(NAME # _D) PPRAny:$pred, + (INSERT_SUBREG (IMPLICIT_DEF), GPR32:$Rn, sub_32)), + sub_32)>; } class sve_int_count_v<bits<2> sz8_64, bits<5> opc, string asm, @@ -1195,19 +1195,19 @@ multiclass sve_int_pred_pattern_a<bits<3> opc, string asm, (!cast<Instruction>(NAME) GPR64:$Rdn, sve_pred_enum:$pattern, $imm)>; def : Pat<(i32 (op GPR32:$Rdn, (i32 (trunc (opcnt (sve_pred_enum:$pattern)))))), - (i32 (EXTRACT_SUBREG (!cast<Instruction>(NAME) (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (EXTRACT_SUBREG (!cast<Instruction>(NAME) (INSERT_SUBREG (IMPLICIT_DEF), GPR32:$Rdn, sub_32), sve_pred_enum:$pattern, 1), - sub_32))>; + sub_32)>; def : Pat<(i32 (op GPR32:$Rdn, (mul (i32 (trunc (opcnt (sve_pred_enum:$pattern)))), (sve_cnt_mul_imm_i32 i32:$imm)))), - (i32 (EXTRACT_SUBREG (!cast<Instruction>(NAME) (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (EXTRACT_SUBREG (!cast<Instruction>(NAME) (INSERT_SUBREG (IMPLICIT_DEF), GPR32:$Rdn, sub_32), sve_pred_enum:$pattern, $imm), - sub_32))>; + sub_32)>; def : Pat<(i32 (op GPR32:$Rdn, (shl (i32 (trunc (opcnt (sve_pred_enum:$pattern)))), (sve_cnt_shl_imm i32:$imm)))), - (i32 (EXTRACT_SUBREG (!cast<Instruction>(NAME) (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (EXTRACT_SUBREG (!cast<Instruction>(NAME) (INSERT_SUBREG (IMPLICIT_DEF), GPR32:$Rdn, sub_32), sve_pred_enum:$pattern, $imm), - sub_32))>; + sub_32)>; } } @@ -5160,9 +5160,9 @@ multiclass SVE_SETCC_Pat<CondCode cc, CondCode invcc, ValueType predvt, (cmp $Op1, $Op2, $Op3)>; def : Pat<(predvt (AArch64setcc_z predvt:$Op1, intvt:$Op2, intvt:$Op3, invcc)), (cmp $Op1, $Op3, $Op2)>; - def : Pat<(predvt (and predvt:$Pg, (AArch64setcc_z_oneuse (predvt (AArch64ptrue 31)), intvt:$Op2, intvt:$Op3, cc))), + def : Pat<(predvt (and predvt:$Pg, (AArch64setcc_z_oneuse (predvt (SVEAllActive)), intvt:$Op2, intvt:$Op3, cc))), (cmp $Pg, $Op2, $Op3)>; - def : Pat<(predvt (and predvt:$Pg, (AArch64setcc_z_oneuse (predvt (AArch64ptrue 31)), intvt:$Op2, intvt:$Op3, invcc))), + def : Pat<(predvt (and predvt:$Pg, (AArch64setcc_z_oneuse (predvt (SVEAllActive)), intvt:$Op2, intvt:$Op3, invcc))), (cmp $Pg, $Op3, $Op2)>; } @@ -5172,9 +5172,9 @@ multiclass SVE_SETCC_Pat_With_Zero<CondCode cc, CondCode invcc, ValueType predvt (cmp $Op1, $Op2)>; def : Pat<(predvt (AArch64setcc_z predvt:$Op1, (SVEDup0), intvt:$Op2, invcc)), (cmp $Op1, $Op2)>; - def : Pat<(predvt (and predvt:$Pg, (AArch64setcc_z_oneuse (predvt (AArch64ptrue 31)), intvt:$Op1, (SVEDup0), cc))), + def : Pat<(predvt (and predvt:$Pg, (AArch64setcc_z_oneuse (predvt (SVEAllActive)), intvt:$Op1, (SVEDup0), cc))), (cmp $Pg, $Op1)>; - def : Pat<(predvt (and predvt:$Pg, (AArch64setcc_z_oneuse (predvt (AArch64ptrue 31)), (SVEDup0), intvt:$Op1, invcc))), + def : Pat<(predvt (and predvt:$Pg, (AArch64setcc_z_oneuse (predvt (SVEAllActive)), (SVEDup0), intvt:$Op1, invcc))), (cmp $Pg, $Op1)>; } @@ -5258,13 +5258,13 @@ multiclass SVE_SETCC_Imm_Pat<CondCode cc, CondCode commuted_cc, commuted_cc)), (cmp $Pg, $Zs1, immtype:$imm)>; def : Pat<(predvt (and predvt:$Pg, - (AArch64setcc_z_oneuse (predvt (AArch64ptrue 31)), + (AArch64setcc_z_oneuse (predvt (SVEAllActive)), (intvt ZPR:$Zs1), (intvt (splat_vector (immtype:$imm))), cc))), (cmp $Pg, $Zs1, immtype:$imm)>; def : Pat<(predvt (and predvt:$Pg, - (AArch64setcc_z_oneuse (predvt (AArch64ptrue 31)), + (AArch64setcc_z_oneuse (predvt (SVEAllActive)), (intvt (splat_vector (immtype:$imm))), (intvt ZPR:$Zs1), commuted_cc))), @@ -5743,23 +5743,23 @@ multiclass sve_int_index_ir<string asm, SDPatternOperator mulop, SDPatternOperat (!cast<Instruction>(NAME # "_D") simm5_64b:$imm5, (SUBREG_TO_REG (i64 0), (!cast<Instruction>("MOVi32imm") (!cast<SDNodeXForm>("trunc_imm") $imm)), sub_32))>; // mul(step_vector(1), dup(Y)) -> index(0, Y). - def : Pat<(mulop (nxv16i1 (AArch64ptrue 31)), (nxv16i8 (step_vector_oneuse (i8 1))), (nxv16i8 (splat_vector(i32 GPR32:$Rm)))), + def : Pat<(mulop (nxv16i1 (SVEAllActive)), (nxv16i8 (step_vector_oneuse (i8 1))), (nxv16i8 (splat_vector(i32 GPR32:$Rm)))), (!cast<Instruction>(NAME # "_B") (i32 0), GPR32:$Rm)>; - def : Pat<(mulop (nxv8i1 (AArch64ptrue 31)), (nxv8i16 (step_vector_oneuse (i16 1))), (nxv8i16 (splat_vector(i32 GPR32:$Rm)))), + def : Pat<(mulop (nxv8i1 (SVEAllActive)), (nxv8i16 (step_vector_oneuse (i16 1))), (nxv8i16 (splat_vector(i32 GPR32:$Rm)))), (!cast<Instruction>(NAME # "_H") (i32 0), GPR32:$Rm)>; - def : Pat<(mulop (nxv4i1 (AArch64ptrue 31)), (nxv4i32 (step_vector_oneuse (i32 1))), (nxv4i32 (splat_vector(i32 GPR32:$Rm)))), + def : Pat<(mulop (nxv4i1 (SVEAllActive)), (nxv4i32 (step_vector_oneuse (i32 1))), (nxv4i32 (splat_vector(i32 GPR32:$Rm)))), (!cast<Instruction>(NAME # "_S") (i32 0), GPR32:$Rm)>; - def : Pat<(mulop (nxv2i1 (AArch64ptrue 31)), (nxv2i64 (step_vector_oneuse (i64 1))), (nxv2i64 (splat_vector(i64 GPR64:$Rm)))), + def : Pat<(mulop (nxv2i1 (SVEAllActive)), (nxv2i64 (step_vector_oneuse (i64 1))), (nxv2i64 (splat_vector(i64 GPR64:$Rm)))), (!cast<Instruction>(NAME # "_D") (i64 0), GPR64:$Rm)>; // add(mul(step_vector(1), dup(Y)), dup(X)) -> index(X, Y). - def : Pat<(add (muloneuseop (nxv16i1 (AArch64ptrue 31)), (nxv16i8 (step_vector_oneuse (i8 1))), (nxv16i8 (splat_vector(i32 GPR32:$Rm)))), (nxv16i8 (splat_vector(simm5_8b:$imm5)))), + def : Pat<(add (muloneuseop (nxv16i1 (SVEAllActive)), (nxv16i8 (step_vector_oneuse (i8 1))), (nxv16i8 (splat_vector(i32 GPR32:$Rm)))), (nxv16i8 (splat_vector(simm5_8b:$imm5)))), (!cast<Instruction>(NAME # "_B") simm5_8b:$imm5, GPR32:$Rm)>; - def : Pat<(add (muloneuseop (nxv8i1 (AArch64ptrue 31)), (nxv8i16 (step_vector_oneuse (i16 1))), (nxv8i16 (splat_vector(i32 GPR32:$Rm)))), (nxv8i16 (splat_vector(simm5_16b:$imm5)))), + def : Pat<(add (muloneuseop (nxv8i1 (SVEAllActive)), (nxv8i16 (step_vector_oneuse (i16 1))), (nxv8i16 (splat_vector(i32 GPR32:$Rm)))), (nxv8i16 (splat_vector(simm5_16b:$imm5)))), (!cast<Instruction>(NAME # "_H") simm5_16b:$imm5, GPR32:$Rm)>; - def : Pat<(add (muloneuseop (nxv4i1 (AArch64ptrue 31)), (nxv4i32 (step_vector_oneuse (i32 1))), (nxv4i32 (splat_vector(i32 GPR32:$Rm)))), (nxv4i32 (splat_vector(simm5_32b:$imm5)))), + def : Pat<(add (muloneuseop (nxv4i1 (SVEAllActive)), (nxv4i32 (step_vector_oneuse (i32 1))), (nxv4i32 (splat_vector(i32 GPR32:$Rm)))), (nxv4i32 (splat_vector(simm5_32b:$imm5)))), (!cast<Instruction>(NAME # "_S") simm5_32b:$imm5, GPR32:$Rm)>; - def : Pat<(add (muloneuseop (nxv2i1 (AArch64ptrue 31)), (nxv2i64 (step_vector_oneuse (i64 1))), (nxv2i64 (splat_vector(i64 GPR64:$Rm)))), (nxv2i64 (splat_vector(simm5_64b:$imm5)))), + def : Pat<(add (muloneuseop (nxv2i1 (SVEAllActive)), (nxv2i64 (step_vector_oneuse (i64 1))), (nxv2i64 (splat_vector(i64 GPR64:$Rm)))), (nxv2i64 (splat_vector(simm5_64b:$imm5)))), (!cast<Instruction>(NAME # "_D") simm5_64b:$imm5, GPR64:$Rm)>; } @@ -5837,13 +5837,13 @@ multiclass sve_int_index_rr<string asm, SDPatternOperator mulop> { (!cast<Instruction>(NAME # "_D") GPR64:$Rn, (SUBREG_TO_REG (i64 0), (!cast<Instruction>("MOVi32imm") (!cast<SDNodeXForm>("trunc_imm") $imm)), sub_32))>; // add(mul(step_vector(1), dup(Y)), dup(X)) -> index(X, Y). - def : Pat<(add (mulop (nxv16i1 (AArch64ptrue 31)), (nxv16i8 (step_vector_oneuse (i8 1))), (nxv16i8 (splat_vector(i32 GPR32:$Rm)))), (nxv16i8 (splat_vector(i32 GPR32:$Rn)))), + def : Pat<(add (mulop (nxv16i1 (SVEAllActive)), (nxv16i8 (step_vector_oneuse (i8 1))), (nxv16i8 (splat_vector(i32 GPR32:$Rm)))), (nxv16i8 (splat_vector(i32 GPR32:$Rn)))), (!cast<Instruction>(NAME # "_B") GPR32:$Rn, GPR32:$Rm)>; - def : Pat<(add (mulop (nxv8i1 (AArch64ptrue 31)), (nxv8i16 (step_vector_oneuse (i16 1))), (nxv8i16 (splat_vector(i32 GPR32:$Rm)))),(nxv8i16 (splat_vector(i32 GPR32:$Rn)))), + def : Pat<(add (mulop (nxv8i1 (SVEAllActive)), (nxv8i16 (step_vector_oneuse (i16 1))), (nxv8i16 (splat_vector(i32 GPR32:$Rm)))),(nxv8i16 (splat_vector(i32 GPR32:$Rn)))), (!cast<Instruction>(NAME # "_H") GPR32:$Rn, GPR32:$Rm)>; - def : Pat<(add (mulop (nxv4i1 (AArch64ptrue 31)), (nxv4i32 (step_vector_oneuse (i32 1))), (nxv4i32 (splat_vector(i32 GPR32:$Rm)))),(nxv4i32 (splat_vector(i32 GPR32:$Rn)))), + def : Pat<(add (mulop (nxv4i1 (SVEAllActive)), (nxv4i32 (step_vector_oneuse (i32 1))), (nxv4i32 (splat_vector(i32 GPR32:$Rm)))),(nxv4i32 (splat_vector(i32 GPR32:$Rn)))), (!cast<Instruction>(NAME # "_S") GPR32:$Rn, GPR32:$Rm)>; - def : Pat<(add (mulop (nxv2i1 (AArch64ptrue 31)), (nxv2i64 (step_vector_oneuse (i64 1))), (nxv2i64 (splat_vector(i64 GPR64:$Rm)))),(nxv2i64 (splat_vector(i64 GPR64:$Rn)))), + def : Pat<(add (mulop (nxv2i1 (SVEAllActive)), (nxv2i64 (step_vector_oneuse (i64 1))), (nxv2i64 (splat_vector(i64 GPR64:$Rm)))),(nxv2i64 (splat_vector(i64 GPR64:$Rn)))), (!cast<Instruction>(NAME # "_D") GPR64:$Rn, GPR64:$Rm)>; } diff --git a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h index ed8336a2e8ad349ac96734891d98746909c5ca46..f821bb527aedb87e5813e66b8baecade520f0d43 100644 --- a/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h +++ b/llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h @@ -591,6 +591,14 @@ namespace AArch64BTIHint { #include "AArch64GenSystemOperands.inc" } +namespace AArch64SME { +enum ToggleCondition : unsigned { + Always, + IfCallerIsStreaming, + IfCallerIsNonStreaming +}; +} + namespace AArch64SE { enum ShiftExtSpecifiers { Invalid = -1, diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.td b/llvm/lib/Target/AMDGPU/AMDGPU.td index c877658cd38e2bba9d84882d165b65762315c6b2..37dcfef3b2a3daf1761b89c403008336fbb77bb0 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPU.td +++ b/llvm/lib/Target/AMDGPU/AMDGPU.td @@ -831,10 +831,12 @@ def FeatureNoDataDepHazard : SubtargetFeature<"no-data-dep-hazard", "Does not need SW waitstates" >; -def FeatureGFX11FullVGPRs : SubtargetFeature<"gfx11-full-vgprs", - "HasGFX11FullVGPRs", +// Allocate 1536 VGPRs for wave32 and 768 VGPRs for wave64 +// with allocation granularity 24 for wave32 and 12 for wave64 +def Feature1_5xVGPRs : SubtargetFeature<"allocate1_5xvgprs", + "Has1_5xVGPRs", "true", - "GFX11 with 50% more physical VGPRs and 50% larger allocation granule than GFX10" + "Has 50% more physical VGPRs and 50% larger allocation granule" >; @@ -1491,12 +1493,12 @@ def FeatureISAVersion11_0_Common : FeatureSet< def FeatureISAVersion11_0_0 : FeatureSet< !listconcat(FeatureISAVersion11_0_Common.Features, - [FeatureGFX11FullVGPRs, + [Feature1_5xVGPRs, FeatureUserSGPRInit16Bug])>; def FeatureISAVersion11_0_1 : FeatureSet< !listconcat(FeatureISAVersion11_0_Common.Features, - [FeatureGFX11FullVGPRs])>; + [Feature1_5xVGPRs])>; def FeatureISAVersion11_0_2 : FeatureSet< !listconcat(FeatureISAVersion11_0_Common.Features, @@ -1517,7 +1519,7 @@ def FeatureISAVersion11_5_1 : FeatureSet< [FeatureSALUFloatInsts, FeatureDPPSrc1SGPR, FeatureVGPRSingleUseHintInsts, - FeatureGFX11FullVGPRs])>; + Feature1_5xVGPRs])>; def FeatureISAVersion12 : FeatureSet< [FeatureGFX12, diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp index d9970a200804aee02a96d243fb88f57cd4cedc8e..052b231d62a3eba796c8bd8916f6a73ccc685799 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp @@ -22,6 +22,7 @@ #include "AMDKernelCodeT.h" #include "GCNSubtarget.h" #include "MCTargetDesc/AMDGPUInstPrinter.h" +#include "MCTargetDesc/AMDGPUMCKernelDescriptor.h" #include "MCTargetDesc/AMDGPUTargetStreamer.h" #include "R600AsmPrinter.h" #include "SIMachineFunctionInfo.h" @@ -428,38 +429,43 @@ uint16_t AMDGPUAsmPrinter::getAmdhsaKernelCodeProperties( return KernelCodeProperties; } -amdhsa::kernel_descriptor_t AMDGPUAsmPrinter::getAmdhsaKernelDescriptor( - const MachineFunction &MF, - const SIProgramInfo &PI) const { +MCKernelDescriptor +AMDGPUAsmPrinter::getAmdhsaKernelDescriptor(const MachineFunction &MF, + const SIProgramInfo &PI) const { const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>(); const Function &F = MF.getFunction(); const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>(); + MCContext &Ctx = MF.getContext(); - amdhsa::kernel_descriptor_t KernelDescriptor; - memset(&KernelDescriptor, 0x0, sizeof(KernelDescriptor)); + MCKernelDescriptor KernelDescriptor; assert(isUInt<32>(PI.ScratchSize)); assert(isUInt<32>(PI.getComputePGMRSrc1(STM))); assert(isUInt<32>(PI.getComputePGMRSrc2())); - KernelDescriptor.group_segment_fixed_size = PI.LDSSize; - KernelDescriptor.private_segment_fixed_size = PI.ScratchSize; + KernelDescriptor.group_segment_fixed_size = + MCConstantExpr::create(PI.LDSSize, Ctx); + KernelDescriptor.private_segment_fixed_size = + MCConstantExpr::create(PI.ScratchSize, Ctx); Align MaxKernArgAlign; - KernelDescriptor.kernarg_size = STM.getKernArgSegmentSize(F, MaxKernArgAlign); + KernelDescriptor.kernarg_size = MCConstantExpr::create( + STM.getKernArgSegmentSize(F, MaxKernArgAlign), Ctx); - KernelDescriptor.compute_pgm_rsrc1 = PI.getComputePGMRSrc1(STM); - KernelDescriptor.compute_pgm_rsrc2 = PI.getComputePGMRSrc2(); - KernelDescriptor.kernel_code_properties = getAmdhsaKernelCodeProperties(MF); + KernelDescriptor.compute_pgm_rsrc1 = + MCConstantExpr::create(PI.getComputePGMRSrc1(STM), Ctx); + KernelDescriptor.compute_pgm_rsrc2 = + MCConstantExpr::create(PI.getComputePGMRSrc2(), Ctx); + KernelDescriptor.kernel_code_properties = + MCConstantExpr::create(getAmdhsaKernelCodeProperties(MF), Ctx); assert(STM.hasGFX90AInsts() || CurrentProgramInfo.ComputePGMRSrc3GFX90A == 0); - if (STM.hasGFX90AInsts()) - KernelDescriptor.compute_pgm_rsrc3 = - CurrentProgramInfo.ComputePGMRSrc3GFX90A; + KernelDescriptor.compute_pgm_rsrc3 = MCConstantExpr::create( + STM.hasGFX90AInsts() ? CurrentProgramInfo.ComputePGMRSrc3GFX90A : 0, Ctx); - if (AMDGPU::hasKernargPreload(STM)) - KernelDescriptor.kernarg_preload = - static_cast<uint16_t>(Info->getNumKernargPreloadedSGPRs()); + KernelDescriptor.kernarg_preload = MCConstantExpr::create( + AMDGPU::hasKernargPreload(STM) ? Info->getNumKernargPreloadedSGPRs() : 0, + Ctx); return KernelDescriptor; } @@ -1033,6 +1039,27 @@ void AMDGPUAsmPrinter::EmitProgramInfoSI(const MachineFunction &MF, OutStreamer->emitInt32(MFI->getNumSpilledVGPRs()); } +// Helper function to add common PAL Metadata 3.0+ +static void EmitPALMetadataCommon(AMDGPUPALMetadata *MD, + const SIProgramInfo &CurrentProgramInfo, + CallingConv::ID CC, const GCNSubtarget &ST) { + if (ST.hasIEEEMode()) + MD->setHwStage(CC, ".ieee_mode", (bool)CurrentProgramInfo.IEEEMode); + + MD->setHwStage(CC, ".wgp_mode", (bool)CurrentProgramInfo.WgpMode); + MD->setHwStage(CC, ".mem_ordered", (bool)CurrentProgramInfo.MemOrdered); + + if (AMDGPU::isCompute(CC)) { + MD->setHwStage(CC, ".trap_present", + (bool)CurrentProgramInfo.TrapHandlerEnable); + MD->setHwStage(CC, ".excp_en", CurrentProgramInfo.EXCPEnable); + + MD->setHwStage(CC, ".lds_size", + (unsigned)(CurrentProgramInfo.LdsSize * + getLdsDwGranularity(ST) * sizeof(uint32_t))); + } +} + // This is the equivalent of EmitProgramInfoSI above, but for when the OS type // is AMDPAL. It stores each compute/SPI register setting and other PAL // metadata items into the PALMD::Metadata, combining with any provided by the @@ -1064,24 +1091,8 @@ void AMDGPUAsmPrinter::EmitPALMetadata(const MachineFunction &MF, } } else { MD->setHwStage(CC, ".debug_mode", (bool)CurrentProgramInfo.DebugMode); - MD->setHwStage(CC, ".ieee_mode", (bool)CurrentProgramInfo.IEEEMode); - MD->setHwStage(CC, ".wgp_mode", (bool)CurrentProgramInfo.WgpMode); - MD->setHwStage(CC, ".mem_ordered", (bool)CurrentProgramInfo.MemOrdered); - - if (AMDGPU::isCompute(CC)) { - MD->setHwStage(CC, ".scratch_en", (bool)CurrentProgramInfo.ScratchEnable); - MD->setHwStage(CC, ".trap_present", - (bool)CurrentProgramInfo.TrapHandlerEnable); - - // EXCPEnMSB? - const unsigned LdsDwGranularity = 128; - MD->setHwStage(CC, ".lds_size", - (unsigned)(CurrentProgramInfo.LdsSize * LdsDwGranularity * - sizeof(uint32_t))); - MD->setHwStage(CC, ".excp_en", CurrentProgramInfo.EXCPEnable); - } else { - MD->setHwStage(CC, ".scratch_en", (bool)CurrentProgramInfo.ScratchEnable); - } + MD->setHwStage(CC, ".scratch_en", (bool)CurrentProgramInfo.ScratchEnable); + EmitPALMetadataCommon(MD, CurrentProgramInfo, CC, STM); } // ScratchSize is in bytes, 16 aligned. @@ -1135,10 +1146,15 @@ void AMDGPUAsmPrinter::emitPALFunctionMetadata(const MachineFunction &MF) { MD->setFunctionScratchSize(FnName, MFI.getStackSize()); const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>(); - // Set compute registers - MD->setRsrc1(CallingConv::AMDGPU_CS, - CurrentProgramInfo.getPGMRSrc1(CallingConv::AMDGPU_CS, ST)); - MD->setRsrc2(CallingConv::AMDGPU_CS, CurrentProgramInfo.getComputePGMRSrc2()); + if (MD->getPALMajorVersion() < 3) { + // Set compute registers + MD->setRsrc1(CallingConv::AMDGPU_CS, + CurrentProgramInfo.getPGMRSrc1(CallingConv::AMDGPU_CS, ST)); + MD->setRsrc2(CallingConv::AMDGPU_CS, + CurrentProgramInfo.getComputePGMRSrc2()); + } else { + EmitPALMetadataCommon(MD, CurrentProgramInfo, CallingConv::AMDGPU_CS, ST); + } // Set optional info MD->setFunctionLdsSize(FnName, CurrentProgramInfo.LDSSize); diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h index 79326cd3d3289f0f92e4030f14a64390cdc49f28..b8b2718d293e69d7bd70dfb1f80604bedb887e17 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.h @@ -28,15 +28,12 @@ class MCCodeEmitter; class MCOperand; namespace AMDGPU { +struct MCKernelDescriptor; namespace HSAMD { class MetadataStreamer; } } // namespace AMDGPU -namespace amdhsa { -struct kernel_descriptor_t; -} - class AMDGPUAsmPrinter final : public AsmPrinter { private: unsigned CodeObjectVersion; @@ -75,9 +72,9 @@ private: uint16_t getAmdhsaKernelCodeProperties( const MachineFunction &MF) const; - amdhsa::kernel_descriptor_t getAmdhsaKernelDescriptor( - const MachineFunction &MF, - const SIProgramInfo &PI) const; + AMDGPU::MCKernelDescriptor + getAmdhsaKernelDescriptor(const MachineFunction &MF, + const SIProgramInfo &PI) const; void initTargetStreamer(Module &M); diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAtomicOptimizer.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAtomicOptimizer.cpp index 9ba74a23e8afcb25aaa0593a3f9a84ff0b6805cb..dbb3de76b4ddae064af3e8b6769fa6633d477ae1 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUAtomicOptimizer.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUAtomicOptimizer.cpp @@ -209,8 +209,9 @@ void AMDGPUAtomicOptimizerImpl::visitAtomicRMWInst(AtomicRMWInst &I) { break; } - // Only 32-bit floating point atomic ops are supported. - if (AtomicRMWInst::isFPOperation(Op) && !I.getType()->isFloatTy()) { + // Only 32 and 64 bit floating point atomic ops are supported. + if (AtomicRMWInst::isFPOperation(Op) && + !(I.getType()->isFloatTy() || I.getType()->isDoubleTy())) { return; } @@ -920,8 +921,10 @@ void AMDGPUAtomicOptimizerImpl::optimizeAtomic(Instruction &I, Value *BroadcastI = nullptr; if (TyBitWidth == 64) { - Value *const ExtractLo = B.CreateTrunc(PHI, Int32Ty); - Value *const ExtractHi = B.CreateTrunc(B.CreateLShr(PHI, 32), Int32Ty); + Value *CastedPhi = B.CreateBitCast(PHI, IntNTy); + Value *const ExtractLo = B.CreateTrunc(CastedPhi, Int32Ty); + Value *const ExtractHi = + B.CreateTrunc(B.CreateLShr(CastedPhi, 32), Int32Ty); CallInst *const ReadFirstLaneLo = B.CreateIntrinsic(Intrinsic::amdgcn_readfirstlane, {}, ExtractLo); CallInst *const ReadFirstLaneHi = diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAttributor.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAttributor.cpp index d7f5110427ecec8fa8d2c5ed013603d81ddddf5f..9bd30458bc0a7e43f17995863ed546eb245057ec 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUAttributor.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUAttributor.cpp @@ -918,6 +918,96 @@ AAAMDWavesPerEU &AAAMDWavesPerEU::createForPosition(const IRPosition &IRP, llvm_unreachable("AAAMDWavesPerEU is only valid for function position"); } +static bool inlineAsmUsesAGPRs(const InlineAsm *IA) { + for (const auto &CI : IA->ParseConstraints()) { + for (StringRef Code : CI.Codes) { + Code.consume_front("{"); + if (Code.starts_with("a")) + return true; + } + } + + return false; +} + +struct AAAMDGPUNoAGPR + : public IRAttribute<Attribute::NoUnwind, + StateWrapper<BooleanState, AbstractAttribute>, + AAAMDGPUNoAGPR> { + AAAMDGPUNoAGPR(const IRPosition &IRP, Attributor &A) : IRAttribute(IRP) {} + + static AAAMDGPUNoAGPR &createForPosition(const IRPosition &IRP, + Attributor &A) { + if (IRP.getPositionKind() == IRPosition::IRP_FUNCTION) + return *new (A.Allocator) AAAMDGPUNoAGPR(IRP, A); + llvm_unreachable("AAAMDGPUNoAGPR is only valid for function position"); + } + + void initialize(Attributor &A) override { + Function *F = getAssociatedFunction(); + if (F->hasFnAttribute("amdgpu-no-agpr")) + indicateOptimisticFixpoint(); + } + + const std::string getAsStr(Attributor *A) const override { + return getAssumed() ? "amdgpu-no-agpr" : "amdgpu-maybe-agpr"; + } + + void trackStatistics() const override {} + + ChangeStatus updateImpl(Attributor &A) override { + // TODO: Use AACallEdges, but then we need a way to inspect asm edges. + + auto CheckForNoAGPRs = [&](Instruction &I) { + const auto &CB = cast<CallBase>(I); + const Value *CalleeOp = CB.getCalledOperand(); + const Function *Callee = dyn_cast<Function>(CalleeOp); + if (!Callee) { + if (const InlineAsm *IA = dyn_cast<InlineAsm>(CalleeOp)) + return !inlineAsmUsesAGPRs(IA); + return false; + } + + // Some intrinsics may use AGPRs, but if we have a choice, we are not + // required to use AGPRs. + if (Callee->isIntrinsic()) + return true; + + // TODO: Handle callsite attributes + const auto *CalleeInfo = A.getAAFor<AAAMDGPUNoAGPR>( + *this, IRPosition::function(*Callee), DepClassTy::REQUIRED); + return CalleeInfo && CalleeInfo->getAssumed(); + }; + + bool UsedAssumedInformation = false; + if (!A.checkForAllCallLikeInstructions(CheckForNoAGPRs, *this, + UsedAssumedInformation)) + return indicatePessimisticFixpoint(); + return ChangeStatus::UNCHANGED; + } + + ChangeStatus manifest(Attributor &A) override { + if (!getAssumed()) + return ChangeStatus::UNCHANGED; + LLVMContext &Ctx = getAssociatedFunction()->getContext(); + return A.manifestAttrs(getIRPosition(), + {Attribute::get(Ctx, "amdgpu-no-agpr")}); + } + + const std::string getName() const override { return "AAAMDGPUNoAGPR"; } + const char *getIdAddr() const override { return &ID; } + + /// This function should return true if the type of the \p AA is + /// AAAMDGPUNoAGPRs + static bool classof(const AbstractAttribute *AA) { + return (AA->getIdAddr() == &ID); + } + + static const char ID; +}; + +const char AAAMDGPUNoAGPR::ID = 0; + static void addPreloadKernArgHint(Function &F, TargetMachine &TM) { const GCNSubtarget &ST = TM.getSubtarget<GCNSubtarget>(F); for (unsigned I = 0; @@ -946,8 +1036,9 @@ static bool runImpl(Module &M, AnalysisGetter &AG, TargetMachine &TM) { DenseSet<const char *> Allowed( {&AAAMDAttributes::ID, &AAUniformWorkGroupSize::ID, &AAPotentialValues::ID, &AAAMDFlatWorkGroupSize::ID, - &AAAMDWavesPerEU::ID, &AACallEdges::ID, &AAPointerInfo::ID, - &AAPotentialConstantValues::ID, &AAUnderlyingObjects::ID}); + &AAAMDWavesPerEU::ID, &AAAMDGPUNoAGPR::ID, &AACallEdges::ID, + &AAPointerInfo::ID, &AAPotentialConstantValues::ID, + &AAUnderlyingObjects::ID}); AttributorConfig AC(CGUpdater); AC.Allowed = &Allowed; @@ -963,6 +1054,7 @@ static bool runImpl(Module &M, AnalysisGetter &AG, TargetMachine &TM) { if (!F.isIntrinsic()) { A.getOrCreateAAFor<AAAMDAttributes>(IRPosition::function(F)); A.getOrCreateAAFor<AAUniformWorkGroupSize>(IRPosition::function(F)); + A.getOrCreateAAFor<AAAMDGPUNoAGPR>(IRPosition::function(F)); CallingConv::ID CC = F.getCallingConv(); if (!AMDGPU::isEntryFunctionCC(CC)) { A.getOrCreateAAFor<AAAMDFlatWorkGroupSize>(IRPosition::function(F)); diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp index 6d05c3678bf09e5fe8c15a9627b819caee21f2eb..7e1f041fa1093306ae7c9a83bfab591639c29197 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp @@ -1301,6 +1301,9 @@ bool AMDGPUCallLowering::lowerTailCall( if (!handleAssignments(Handler, OutArgs, CCInfo, ArgLocs, MIRBuilder)) return false; + if (Info.ConvergenceCtrlToken) { + MIB.addUse(Info.ConvergenceCtrlToken, RegState::Implicit); + } handleImplicitCallArguments(MIRBuilder, MIB, ST, *FuncInfo, CalleeCC, ImplicitArgRegs); @@ -1483,6 +1486,9 @@ bool AMDGPUCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>(); + if (Info.ConvergenceCtrlToken) { + MIB.addUse(Info.ConvergenceCtrlToken, RegState::Implicit); + } handleImplicitCallArguments(MIRBuilder, MIB, ST, *MFI, Info.CallConv, ImplicitArgRegs); diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp index 0edbbf7cb0af544484841b70427591059f4e8608..6e7d34f5adaa3f97d9f01c97c51079563cc64c81 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUCodeGenPrepare.cpp @@ -1594,6 +1594,9 @@ bool AMDGPUCodeGenPrepareImpl::visitBinaryOperator(BinaryOperator &I) { } } + if (auto *NewEltI = dyn_cast<Instruction>(NewElt)) + NewEltI->copyIRFlags(&I); + NewDiv = Builder.CreateInsertElement(NewDiv, NewElt, N); } } else { @@ -1749,7 +1752,7 @@ static bool isInterestingPHIIncomingValue(const Value *V) { // Non constant index/out of bounds index -> folding is unlikely. // The latter is more of a sanity check because canonical IR should just // have replaced those with poison. - if (!Idx || Idx->getSExtValue() >= FVT->getNumElements()) + if (!Idx || Idx->getZExtValue() >= FVT->getNumElements()) return false; const auto *VecSrc = IE->getOperand(0); @@ -1761,7 +1764,7 @@ static bool isInterestingPHIIncomingValue(const Value *V) { return false; CurVal = VecSrc; - EltsCovered.set(Idx->getSExtValue()); + EltsCovered.set(Idx->getZExtValue()); // All elements covered. if (EltsCovered.all()) @@ -1987,7 +1990,7 @@ bool AMDGPUCodeGenPrepareImpl::visitPHINode(PHINode &I) { for (VectorSlice &S : Slices) { // We need to reset the build on each iteration, because getSlicedVal may // have inserted something into I's BB. - B.SetInsertPoint(I.getParent()->getFirstNonPHI()); + B.SetInsertPoint(I.getParent()->getFirstNonPHIIt()); S.NewPHI = B.CreatePHI(S.Ty, I.getNumIncomingValues()); for (const auto &[Idx, BB] : enumerate(I.blocks())) { diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp index c99e490014668b6ec5d7b06e945efa3bb533e6de..bba7682cd7a0d153b262ace96ec6da121d5b6710 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp @@ -3556,7 +3556,10 @@ bool AMDGPUDAGToDAGISel::isUniformLoad(const SDNode *N) const { if (N->isDivergent() && !AMDGPUInstrInfo::isUniformMMO(MMO)) return false; - return Ld->getAlign() >= Align(std::min(MMO->getSize(), uint64_t(4))) && + return MMO->getSize().hasValue() && + Ld->getAlign() >= + Align(std::min(MMO->getSize().getValue().getKnownMinValue(), + uint64_t(4))) && ((Ld->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS || Ld->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS_32BIT) || (Subtarget->getScalarizeGlobalBehavior() && diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp index 8a71550e5532cd7ed77994462a765efc99745899..f283af6fa07d3ecfe3b50e39b49f4f811eb767f0 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp @@ -582,6 +582,7 @@ AMDGPUTargetLowering::AMDGPUTargetLowering(const TargetMachine &TM, setMaxAtomicSizeInBitsSupported(64); setMaxDivRemBitWidthSupported(64); + setMaxLargeFPConvertBitWidthSupported(64); } bool AMDGPUTargetLowering::mayIgnoreSignedZero(SDValue Op) const { @@ -850,12 +851,7 @@ bool AMDGPUTargetLowering::isSDNodeAlwaysUniform(const SDNode *N) const { return true; case ISD::INTRINSIC_WO_CHAIN: { unsigned IntrID = N->getConstantOperandVal(0); - switch (IntrID) { - case Intrinsic::amdgcn_readfirstlane: - case Intrinsic::amdgcn_readlane: - return true; - } - return false; + return AMDGPU::isIntrinsicAlwaysUniform(IntrID); } case ISD::LOAD: if (cast<LoadSDNode>(N)->getMemOperand()->getAddrSpace() == diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp index fb829fab0a2c19c8fbe7dc77d368a7e98ea2b40c..5b7fa13f2e835ff40d1b264ce85452e23450ccf3 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp @@ -767,19 +767,21 @@ GCNTTIImpl::instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const { // Checking for NaN before canonicalization provides better fidelity when // mapping other operations onto fmed3 since the order of operands is // unchanged. - CallInst *NewCall = nullptr; + Value *V = nullptr; if (match(Src0, PatternMatch::m_NaN()) || isa<UndefValue>(Src0)) { - NewCall = IC.Builder.CreateMinNum(Src1, Src2); + V = IC.Builder.CreateMinNum(Src1, Src2); } else if (match(Src1, PatternMatch::m_NaN()) || isa<UndefValue>(Src1)) { - NewCall = IC.Builder.CreateMinNum(Src0, Src2); + V = IC.Builder.CreateMinNum(Src0, Src2); } else if (match(Src2, PatternMatch::m_NaN()) || isa<UndefValue>(Src2)) { - NewCall = IC.Builder.CreateMaxNum(Src0, Src1); + V = IC.Builder.CreateMaxNum(Src0, Src1); } - if (NewCall) { - NewCall->copyFastMathFlags(&II); - NewCall->takeName(&II); - return IC.replaceInstUsesWith(II, NewCall); + if (V) { + if (auto *CI = dyn_cast<CallInst>(V)) { + CI->copyFastMathFlags(&II); + CI->takeName(&II); + } + return IC.replaceInstUsesWith(II, V); } bool Swap = false; diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp index 94cc1d90e0ca58a51f9ef6ffc0f2688a20c1ca5a..e13c13913d4e82c3dc01dab3bb40023b4fe0eaf8 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp @@ -2045,38 +2045,6 @@ bool AMDGPUInstructionSelector::selectImageIntrinsic( if (BaseOpcode->HasD16) MIB.addImm(IsD16 ? -1 : 0); - if (IsTexFail) { - // An image load instruction with TFE/LWE only conditionally writes to its - // result registers. Initialize them to zero so that we always get well - // defined result values. - assert(VDataOut && !VDataIn); - Register Tied = MRI->cloneVirtualRegister(VDataOut); - Register Zero = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass); - BuildMI(*MBB, *MIB, DL, TII.get(AMDGPU::V_MOV_B32_e32), Zero) - .addImm(0); - auto Parts = TRI.getRegSplitParts(MRI->getRegClass(Tied), 4); - if (STI.usePRTStrictNull()) { - // With enable-prt-strict-null enabled, initialize all result registers to - // zero. - auto RegSeq = - BuildMI(*MBB, *MIB, DL, TII.get(AMDGPU::REG_SEQUENCE), Tied); - for (auto Sub : Parts) - RegSeq.addReg(Zero).addImm(Sub); - } else { - // With enable-prt-strict-null disabled, only initialize the extra TFE/LWE - // result register. - Register Undef = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass); - BuildMI(*MBB, *MIB, DL, TII.get(AMDGPU::IMPLICIT_DEF), Undef); - auto RegSeq = - BuildMI(*MBB, *MIB, DL, TII.get(AMDGPU::REG_SEQUENCE), Tied); - for (auto Sub : Parts.drop_back(1)) - RegSeq.addReg(Undef).addImm(Sub); - RegSeq.addReg(Zero).addImm(Parts.back()); - } - MIB.addReg(Tied, RegState::Implicit); - MIB->tieOperands(0, MIB->getNumOperands() - 1); - } - MI.eraseFromParent(); constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); TII.enforceOperandRCAlignment(*MIB, AMDGPU::OpName::vaddr); diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td b/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td index 5ed82c0c4b1b8e11a017f9477e11f269a3304b98..86f77f7b64e88d3f52d15ad8cd6fa7bb10fe3509 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td +++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructions.td @@ -194,7 +194,25 @@ class HasOneUseTernaryOp<SDPatternOperator op> : PatFrag< }]; } -class is_canonicalized<SDPatternOperator op> : PatFrag< +class is_canonicalized_1<SDPatternOperator op> : PatFrag< + (ops node:$src0), + (op $src0), + [{ + const SITargetLowering &Lowering = + *static_cast<const SITargetLowering *>(getTargetLowering()); + + return Lowering.isCanonicalized(*CurDAG, N->getOperand(0)); + }]> { + + let GISelPredicateCode = [{ + const SITargetLowering *TLI = static_cast<const SITargetLowering *>( + MF.getSubtarget().getTargetLowering()); + + return TLI->isCanonicalized(MI.getOperand(1).getReg(), MF); + }]; +} + +class is_canonicalized_2<SDPatternOperator op> : PatFrag< (ops node:$src0, node:$src1), (op $src0, $src1), [{ @@ -210,8 +228,8 @@ class is_canonicalized<SDPatternOperator op> : PatFrag< const SITargetLowering *TLI = static_cast<const SITargetLowering *>( MF.getSubtarget().getTargetLowering()); - return TLI->isCanonicalized(MI.getOperand(1).getReg(), const_cast<MachineFunction&>(MF)) && - TLI->isCanonicalized(MI.getOperand(2).getReg(), const_cast<MachineFunction&>(MF)); + return TLI->isCanonicalized(MI.getOperand(1).getReg(), MF) && + TLI->isCanonicalized(MI.getOperand(2).getReg(), MF); }]; } diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp index 0029c51231f2863d836da8c61974c0a37101edd9..e55d1de01b4fd12b8b5d1649eb5a4e54118038f1 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -2030,6 +2030,8 @@ AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST_, getActionDefinitionsBuilder({G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET}) .lower(); + getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP}).custom(); + getActionDefinitionsBuilder({G_VASTART, G_VAARG, G_BRJT, G_JUMP_TABLE, G_INDEXED_LOAD, G_INDEXED_SEXTLOAD, G_INDEXED_ZEXTLOAD, G_INDEXED_STORE}) @@ -2134,6 +2136,10 @@ bool AMDGPULegalizerInfo::legalizeCustom( return legalizeGetFPEnv(MI, MRI, B); case TargetOpcode::G_SET_FPENV: return legalizeSetFPEnv(MI, MRI, B); + case TargetOpcode::G_TRAP: + return legalizeTrap(MI, MRI, B); + case TargetOpcode::G_DEBUGTRAP: + return legalizeDebugTrap(MI, MRI, B); default: return false; } @@ -2925,7 +2931,7 @@ bool AMDGPULegalizerInfo::legalizeGlobalValue( // functions that use local objects. However, if these dead functions are // not eliminated, we don't want a compile time error. Just emit a warning // and a trap, since there should be no callable path here. - B.buildIntrinsic(Intrinsic::trap, ArrayRef<Register>()); + B.buildTrap(); B.buildUndef(DstReg); MI.eraseFromParent(); return true; @@ -5661,7 +5667,7 @@ bool AMDGPULegalizerInfo::legalizeBufferStore(MachineInstr &MI, Register RSrc = MI.getOperand(2).getReg(); MachineMemOperand *MMO = *MI.memoperands_begin(); - const int MemSize = MMO->getSize(); + const int MemSize = MMO->getSize().getValue(); unsigned ImmOffset; @@ -6618,9 +6624,9 @@ bool AMDGPULegalizerInfo::legalizeSBufferLoad(LegalizerHelper &Helper, } // TODO: Move to selection -bool AMDGPULegalizerInfo::legalizeTrapIntrinsic(MachineInstr &MI, - MachineRegisterInfo &MRI, - MachineIRBuilder &B) const { +bool AMDGPULegalizerInfo::legalizeTrap(MachineInstr &MI, + MachineRegisterInfo &MRI, + MachineIRBuilder &B) const { if (!ST.isTrapHandlerEnabled() || ST.getTrapHandlerAbi() != GCNSubtarget::TrapHandlerAbi::AMDHSA) return legalizeTrapEndpgm(MI, MRI, B); @@ -6726,8 +6732,9 @@ bool AMDGPULegalizerInfo::legalizeTrapHsa( return true; } -bool AMDGPULegalizerInfo::legalizeDebugTrapIntrinsic( - MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const { +bool AMDGPULegalizerInfo::legalizeDebugTrap(MachineInstr &MI, + MachineRegisterInfo &MRI, + MachineIRBuilder &B) const { // Is non-HSA path or trap-handler disabled? Then, report a warning // accordingly if (!ST.isTrapHandlerEnabled() || @@ -7270,10 +7277,6 @@ bool AMDGPULegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper, case Intrinsic::amdgcn_struct_buffer_atomic_fadd_v2bf16: case Intrinsic::amdgcn_struct_ptr_buffer_atomic_fadd_v2bf16: return legalizeBufferAtomic(MI, B, IntrID); - case Intrinsic::trap: - return legalizeTrapIntrinsic(MI, MRI, B); - case Intrinsic::debugtrap: - return legalizeDebugTrapIntrinsic(MI, MRI, B); case Intrinsic::amdgcn_rsq_clamp: return legalizeRsqClampIntrinsic(MI, MRI, B); case Intrinsic::amdgcn_ds_fadd: diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h index 9661646fffc9d85315c6736aa3f0d5453168b729..e5ba84a74a0f8a3866c523c22438da2ee4ee48db 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h +++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h @@ -226,16 +226,16 @@ public: bool legalizeSBufferLoad(LegalizerHelper &Helper, MachineInstr &MI) const; - bool legalizeTrapIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, - MachineIRBuilder &B) const; + bool legalizeTrap(MachineInstr &MI, MachineRegisterInfo &MRI, + MachineIRBuilder &B) const; bool legalizeTrapEndpgm(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const; bool legalizeTrapHsaQueuePtr(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const; bool legalizeTrapHsa(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const; - bool legalizeDebugTrapIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, - MachineIRBuilder &B) const; + bool legalizeDebugTrap(MachineInstr &MI, MachineRegisterInfo &MRI, + MachineIRBuilder &B) const; bool legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const override; diff --git a/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp b/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp index 2da896edc79a7f258cf5602cbe962c14cb6cc945..5aa35becd842c38cc4f59a3332da41f7bf025844 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULibCalls.cpp @@ -470,9 +470,11 @@ bool AMDGPULibCalls::sincosUseNative(CallInst *aCI, const FuncInfo &FInfo) { nf.setId(AMDGPULibFunc::EI_COS); FunctionCallee cosExpr = getFunction(M, nf); if (sinExpr && cosExpr) { - Value *sinval = CallInst::Create(sinExpr, opr0, "splitsin", aCI); - Value *cosval = CallInst::Create(cosExpr, opr0, "splitcos", aCI); - new StoreInst(cosval, aCI->getArgOperand(1), aCI); + Value *sinval = + CallInst::Create(sinExpr, opr0, "splitsin", aCI->getIterator()); + Value *cosval = + CallInst::Create(cosExpr, opr0, "splitcos", aCI->getIterator()); + new StoreInst(cosval, aCI->getArgOperand(1), aCI->getIterator()); DEBUG_WITH_TYPE("usenative", dbgs() << "<useNative> replace " << *aCI << " with native version of sin/cos"); @@ -655,6 +657,8 @@ bool AMDGPULibCalls::fold(CallInst *CI) { return true; IRBuilder<> B(CI); + if (CI->isStrictFP()) + B.setIsFPConstrained(true); if (FPMathOperator *FPOp = dyn_cast<FPMathOperator>(CI)) { // Under unsafe-math, evaluate calls if possible. @@ -1655,7 +1659,7 @@ bool AMDGPULibCalls::evaluateCall(CallInst *aCI, const FuncInfo &FInfo) { // sincos assert(FInfo.getId() == AMDGPULibFunc::EI_SINCOS && "math function with ptr arg not supported yet"); - new StoreInst(nval1, aCI->getArgOperand(1), aCI); + new StoreInst(nval1, aCI->getArgOperand(1), aCI->getIterator()); } replaceCall(aCI, nval0); diff --git a/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp b/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp index 2cfd1de93a04f95b0aa463b05db9b4bf123b2597..9083150b3384883a97352b9c475e926139c3ad8e 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp @@ -801,7 +801,7 @@ Value *FatPtrConstMaterializer::materialize(Value *V) { Ops.push_back(cast<Constant>(U.get())); auto *NewGEP = ConstantExpr::getGetElementPtr( NewSrcTy, Ops[0], ArrayRef<Constant *>(Ops).slice(1), - GEPO->isInBounds(), GEPO->getInRangeIndex()); + GEPO->isInBounds(), GEPO->getInRange()); LLVM_DEBUG(dbgs() << "p7-getting GEP: " << *GEPO << " becomes " << *NewGEP << "\n"); Value *FurtherMap = materialize(NewGEP); diff --git a/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp b/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp index b85cb26fdc95651037a16bb4a376d826c9366c5d..595f09664c55e4f6d4f92f3e970770d022d865a9 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp @@ -340,26 +340,11 @@ public: // Get uses from the current function, excluding uses by called functions // Two output variables to avoid walking the globals list twice - std::optional<bool> HasAbsoluteGVs; for (auto &GV : M.globals()) { if (!AMDGPU::isLDSVariableToLower(GV)) { continue; } - // Check if the module is consistent: either all GVs are absolute (happens - // when we run the pass more than once), or none are. - const bool IsAbsolute = GV.isAbsoluteSymbolRef(); - if (HasAbsoluteGVs.has_value()) { - if (*HasAbsoluteGVs != IsAbsolute) { - report_fatal_error( - "Module cannot mix absolute and non-absolute LDS GVs"); - } - } else - HasAbsoluteGVs = IsAbsolute; - - if (IsAbsolute) - continue; - for (User *V : GV.users()) { if (auto *I = dyn_cast<Instruction>(V)) { Function *F = I->getFunction(); @@ -469,6 +454,31 @@ public: } } + // Verify that we fall into one of 2 cases: + // - All variables are absolute: this is a re-run of the pass + // so we don't have anything to do. + // - No variables are absolute. + std::optional<bool> HasAbsoluteGVs; + for (auto &Map : {direct_map_kernel, indirect_map_kernel}) { + for (auto &[Fn, GVs] : Map) { + for (auto *GV : GVs) { + bool IsAbsolute = GV->isAbsoluteSymbolRef(); + if (HasAbsoluteGVs.has_value()) { + if (*HasAbsoluteGVs != IsAbsolute) { + report_fatal_error( + "Module cannot mix absolute and non-absolute LDS GVs"); + } + } else + HasAbsoluteGVs = IsAbsolute; + } + } + } + + // If we only had absolute GVs, we have nothing to do, return an empty + // result. + if (HasAbsoluteGVs && *HasAbsoluteGVs) + return {FunctionVariableMap(), FunctionVariableMap()}; + return {std::move(direct_map_kernel), std::move(indirect_map_kernel)}; } diff --git a/llvm/lib/Target/AMDGPU/AMDGPUPassRegistry.def b/llvm/lib/Target/AMDGPU/AMDGPUPassRegistry.def new file mode 100644 index 0000000000000000000000000000000000000000..90f36fadf35903cde150880f6c37b99fb02a131c --- /dev/null +++ b/llvm/lib/Target/AMDGPU/AMDGPUPassRegistry.def @@ -0,0 +1,73 @@ +//===- AMDGPUPassRegistry.def - Registry of AMDGPU passes -------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is used as the registry of passes that are part of the +// AMDGPU backend. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +#ifndef MODULE_PASS +#define MODULE_PASS(NAME, CREATE_PASS) +#endif +MODULE_PASS("amdgpu-always-inline", AMDGPUAlwaysInlinePass()) +MODULE_PASS("amdgpu-attributor", AMDGPUAttributorPass(*this)) +MODULE_PASS("amdgpu-lower-buffer-fat-pointers", + AMDGPULowerBufferFatPointersPass(*this)) +MODULE_PASS("amdgpu-lower-ctor-dtor", AMDGPUCtorDtorLoweringPass()) +MODULE_PASS("amdgpu-lower-module-lds", AMDGPULowerModuleLDSPass(*this)) +MODULE_PASS("amdgpu-printf-runtime-binding", AMDGPUPrintfRuntimeBindingPass()) +MODULE_PASS("amdgpu-unify-metadata", AMDGPUUnifyMetadataPass()) +#undef MODULE_PASS + +#ifndef FUNCTION_PASS +#define FUNCTION_PASS(NAME, CREATE_PASS) +#endif +FUNCTION_PASS("amdgpu-codegenprepare", AMDGPUCodeGenPreparePass(*this)) +FUNCTION_PASS("amdgpu-image-intrinsic-opt", + AMDGPUImageIntrinsicOptimizerPass(*this)) +FUNCTION_PASS("amdgpu-lower-kernel-arguments", + AMDGPULowerKernelArgumentsPass(*this)) +FUNCTION_PASS("amdgpu-lower-kernel-attributes", + AMDGPULowerKernelAttributesPass()) +FUNCTION_PASS("amdgpu-simplifylib", AMDGPUSimplifyLibCallsPass()) +FUNCTION_PASS("amdgpu-promote-alloca", AMDGPUPromoteAllocaPass(*this)) +FUNCTION_PASS("amdgpu-promote-alloca-to-vector", + AMDGPUPromoteAllocaToVectorPass(*this)) +FUNCTION_PASS("amdgpu-promote-kernel-arguments", + AMDGPUPromoteKernelArgumentsPass()) +FUNCTION_PASS("amdgpu-rewrite-undef-for-phi", AMDGPURewriteUndefForPHIPass()) +FUNCTION_PASS("amdgpu-unify-divergent-exit-nodes", + AMDGPUUnifyDivergentExitNodesPass()) +FUNCTION_PASS("amdgpu-usenative", AMDGPUUseNativeCallsPass()) +#undef FUNCTION_PASS + +#ifndef FUNCTION_ANALYSIS +#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) +#endif + +#ifndef FUNCTION_ALIAS_ANALYSIS +#define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) \ + FUNCTION_ANALYSIS(NAME, CREATE_PASS) +#endif +FUNCTION_ALIAS_ANALYSIS("amdgpu-aa", AMDGPUAA()) +#undef FUNCTION_ALIAS_ANALYSIS +#undef FUNCTION_ANALYSIS + +#ifndef FUNCTION_PASS_WITH_PARAMS +#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) +#endif +FUNCTION_PASS_WITH_PARAMS( + "amdgpu-atomic-optimizer", + "AMDGPUAtomicOptimizerPass", + [=](ScanOptions Strategy) { + return AMDGPUAtomicOptimizerPass(*this, Strategy); + }, + parseAMDGPUAtomicOptimizerStrategy, "strategy=dpp|iterative|none") +#undef FUNCTION_PASS_WITH_PARAMS diff --git a/llvm/lib/Target/AMDGPU/AMDGPUPrintfRuntimeBinding.cpp b/llvm/lib/Target/AMDGPU/AMDGPUPrintfRuntimeBinding.cpp index 7b5dc3795b0227ffbfe9344aa841a57c5844a74c..aef0ade6d9be635dd42259da4123fb72a2ab94c8 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUPrintfRuntimeBinding.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUPrintfRuntimeBinding.cpp @@ -290,8 +290,8 @@ bool AMDGPUPrintfRuntimeBindingImpl::lowerPrintfForGpu(Module &M) { Value *sumC = ConstantInt::get(SizetTy, Sum, false); SmallVector<Value *, 1> alloc_args; alloc_args.push_back(sumC); - CallInst *pcall = - CallInst::Create(PrintfAllocFn, alloc_args, "printf_alloc_fn", CI); + CallInst *pcall = CallInst::Create(PrintfAllocFn, alloc_args, + "printf_alloc_fn", CI->getIterator()); // // Insert code to split basicblock with a @@ -309,25 +309,27 @@ bool AMDGPUPrintfRuntimeBindingImpl::lowerPrintfForGpu(Module &M) { SplitBlock(CI->getParent(), cmp); Instruction *Brnch = SplitBlockAndInsertIfThen(cmp, cmp->getNextNode(), false); + BasicBlock::iterator BrnchPoint = Brnch->getIterator(); Builder.SetInsertPoint(Brnch); // store unique printf id in the buffer // GetElementPtrInst *BufferIdx = GetElementPtrInst::Create( - I8Ty, pcall, ConstantInt::get(Ctx, APInt(32, 0)), "PrintBuffID", Brnch); + I8Ty, pcall, ConstantInt::get(Ctx, APInt(32, 0)), "PrintBuffID", + BrnchPoint); Type *idPointer = PointerType::get(I32Ty, AMDGPUAS::GLOBAL_ADDRESS); Value *id_gep_cast = - new BitCastInst(BufferIdx, idPointer, "PrintBuffIdCast", Brnch); + new BitCastInst(BufferIdx, idPointer, "PrintBuffIdCast", BrnchPoint); - new StoreInst(ConstantInt::get(I32Ty, UniqID), id_gep_cast, Brnch); + new StoreInst(ConstantInt::get(I32Ty, UniqID), id_gep_cast, BrnchPoint); // 1st 4 bytes hold the printf_id // the following GEP is the buffer pointer BufferIdx = GetElementPtrInst::Create(I8Ty, pcall, ConstantInt::get(Ctx, APInt(32, 4)), - "PrintBuffGep", Brnch); + "PrintBuffGep", BrnchPoint); Type *Int32Ty = Type::getInt32Ty(Ctx); for (unsigned ArgCount = 1; @@ -405,7 +407,7 @@ bool AMDGPUPrintfRuntimeBindingImpl::lowerPrintfForGpu(Module &M) { for (unsigned I = 0, E = WhatToStore.size(); I != E; ++I) { Value *TheBtCast = WhatToStore[I]; unsigned ArgSize = TD->getTypeAllocSize(TheBtCast->getType()); - StoreInst *StBuff = new StoreInst(TheBtCast, BufferIdx, Brnch); + StoreInst *StBuff = new StoreInst(TheBtCast, BufferIdx, BrnchPoint); LLVM_DEBUG(dbgs() << "inserting store to printf buffer:\n" << *StBuff << '\n'); (void)StBuff; @@ -413,7 +415,7 @@ bool AMDGPUPrintfRuntimeBindingImpl::lowerPrintfForGpu(Module &M) { break; BufferIdx = GetElementPtrInst::Create( I8Ty, BufferIdx, {ConstantInt::get(I32Ty, ArgSize)}, - "PrintBuffNextPtr", Brnch); + "PrintBuffNextPtr", BrnchPoint); LLVM_DEBUG(dbgs() << "inserting gep to the printf buffer:\n" << *BufferIdx << '\n'); } diff --git a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp index b1b15e9915aea312b2ab013336fbf37340336dba..6f3cdf54dceec7fd3a4c9f2db4472f11596f2f25 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp @@ -32,6 +32,7 @@ #include "llvm/Analysis/CaptureTracking.h" #include "llvm/Analysis/InstSimplifyFolder.h" #include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/IR/IRBuilder.h" @@ -39,6 +40,7 @@ #include "llvm/IR/IntrinsicsAMDGPU.h" #include "llvm/IR/IntrinsicsR600.h" #include "llvm/IR/PatternMatch.h" +#include "llvm/InitializePasses.h" #include "llvm/Pass.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/Utils/SSAUpdater.h" @@ -64,10 +66,17 @@ static cl::opt<unsigned> PromoteAllocaToVectorLimit( cl::desc("Maximum byte size to consider promote alloca to vector"), cl::init(0)); +static cl::opt<unsigned> + LoopUserWeight("promote-alloca-vector-loop-user-weight", + cl::desc("The bonus weight of users of allocas within loop " + "when sorting profitable allocas"), + cl::init(4)); + // Shared implementation which can do both promotion to vector and to LDS. class AMDGPUPromoteAllocaImpl { private: const TargetMachine &TM; + LoopInfo &LI; Module *Mod = nullptr; const DataLayout *DL = nullptr; @@ -101,8 +110,11 @@ private: bool tryPromoteAllocaToVector(AllocaInst &I); bool tryPromoteAllocaToLDS(AllocaInst &I, bool SufficientLDS); + void sortAllocasToPromote(SmallVectorImpl<AllocaInst *> &Allocas); + public: - AMDGPUPromoteAllocaImpl(TargetMachine &TM) : TM(TM) { + AMDGPUPromoteAllocaImpl(TargetMachine &TM, LoopInfo &LI) : TM(TM), LI(LI) { + const Triple &TT = TM.getTargetTriple(); IsAMDGCN = TT.getArch() == Triple::amdgcn; IsAMDHSA = TT.getOS() == Triple::AMDHSA; @@ -122,7 +134,9 @@ public: if (skipFunction(F)) return false; if (auto *TPC = getAnalysisIfAvailable<TargetPassConfig>()) - return AMDGPUPromoteAllocaImpl(TPC->getTM<TargetMachine>()) + return AMDGPUPromoteAllocaImpl( + TPC->getTM<TargetMachine>(), + getAnalysis<LoopInfoWrapperPass>().getLoopInfo()) .run(F, /*PromoteToLDS*/ true); return false; } @@ -131,6 +145,7 @@ public: void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesCFG(); + AU.addRequired<LoopInfoWrapperPass>(); FunctionPass::getAnalysisUsage(AU); } }; @@ -145,7 +160,9 @@ public: if (skipFunction(F)) return false; if (auto *TPC = getAnalysisIfAvailable<TargetPassConfig>()) - return AMDGPUPromoteAllocaImpl(TPC->getTM<TargetMachine>()) + return AMDGPUPromoteAllocaImpl( + TPC->getTM<TargetMachine>(), + getAnalysis<LoopInfoWrapperPass>().getLoopInfo()) .run(F, /*PromoteToLDS*/ false); return false; } @@ -156,6 +173,7 @@ public: void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesCFG(); + AU.addRequired<LoopInfoWrapperPass>(); FunctionPass::getAnalysisUsage(AU); } }; @@ -186,18 +204,23 @@ INITIALIZE_PASS_BEGIN(AMDGPUPromoteAlloca, DEBUG_TYPE, // Move LDS uses from functions to kernels before promote alloca for accurate // estimation of LDS available INITIALIZE_PASS_DEPENDENCY(AMDGPULowerModuleLDSLegacy) +INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) INITIALIZE_PASS_END(AMDGPUPromoteAlloca, DEBUG_TYPE, "AMDGPU promote alloca to vector or LDS", false, false) -INITIALIZE_PASS(AMDGPUPromoteAllocaToVector, DEBUG_TYPE "-to-vector", - "AMDGPU promote alloca to vector", false, false) +INITIALIZE_PASS_BEGIN(AMDGPUPromoteAllocaToVector, DEBUG_TYPE "-to-vector", + "AMDGPU promote alloca to vector", false, false) +INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) +INITIALIZE_PASS_END(AMDGPUPromoteAllocaToVector, DEBUG_TYPE "-to-vector", + "AMDGPU promote alloca to vector", false, false) char &llvm::AMDGPUPromoteAllocaID = AMDGPUPromoteAlloca::ID; char &llvm::AMDGPUPromoteAllocaToVectorID = AMDGPUPromoteAllocaToVector::ID; PreservedAnalyses AMDGPUPromoteAllocaPass::run(Function &F, FunctionAnalysisManager &AM) { - bool Changed = AMDGPUPromoteAllocaImpl(TM).run(F, /*PromoteToLDS*/ true); + auto &LI = AM.getResult<LoopAnalysis>(F); + bool Changed = AMDGPUPromoteAllocaImpl(TM, LI).run(F, /*PromoteToLDS=*/true); if (Changed) { PreservedAnalyses PA; PA.preserveSet<CFGAnalyses>(); @@ -208,7 +231,8 @@ PreservedAnalyses AMDGPUPromoteAllocaPass::run(Function &F, PreservedAnalyses AMDGPUPromoteAllocaToVectorPass::run(Function &F, FunctionAnalysisManager &AM) { - bool Changed = AMDGPUPromoteAllocaImpl(TM).run(F, /*PromoteToLDS*/ false); + auto &LI = AM.getResult<LoopAnalysis>(F); + bool Changed = AMDGPUPromoteAllocaImpl(TM, LI).run(F, /*PromoteToLDS=*/false); if (Changed) { PreservedAnalyses PA; PA.preserveSet<CFGAnalyses>(); @@ -225,6 +249,55 @@ FunctionPass *llvm::createAMDGPUPromoteAllocaToVector() { return new AMDGPUPromoteAllocaToVector(); } +static void collectAllocaUses(AllocaInst &Alloca, + SmallVectorImpl<Use *> &Uses) { + SmallVector<Instruction *, 4> WorkList({&Alloca}); + while (!WorkList.empty()) { + auto *Cur = WorkList.pop_back_val(); + for (auto &U : Cur->uses()) { + Uses.push_back(&U); + + if (isa<GetElementPtrInst>(U.getUser())) + WorkList.push_back(cast<Instruction>(U.getUser())); + } + } +} + +void AMDGPUPromoteAllocaImpl::sortAllocasToPromote( + SmallVectorImpl<AllocaInst *> &Allocas) { + DenseMap<AllocaInst *, unsigned> Scores; + + for (auto *Alloca : Allocas) { + LLVM_DEBUG(dbgs() << "Scoring: " << *Alloca << "\n"); + unsigned &Score = Scores[Alloca]; + // Increment score by one for each user + a bonus for users within loops. + SmallVector<Use *, 8> Uses; + collectAllocaUses(*Alloca, Uses); + for (auto *U : Uses) { + Instruction *Inst = cast<Instruction>(U->getUser()); + if (isa<GetElementPtrInst>(Inst)) + continue; + unsigned UserScore = + 1 + (LoopUserWeight * LI.getLoopDepth(Inst->getParent())); + LLVM_DEBUG(dbgs() << " [+" << UserScore << "]:\t" << *Inst << "\n"); + Score += UserScore; + } + LLVM_DEBUG(dbgs() << " => Final Score:" << Score << "\n"); + } + + stable_sort(Allocas, [&](AllocaInst *A, AllocaInst *B) { + return Scores.at(A) > Scores.at(B); + }); + + // clang-format off + LLVM_DEBUG( + dbgs() << "Sorted Worklist:\n"; + for (auto *A: Allocas) + dbgs() << " " << *A << "\n"; + ); + // clang-format on +} + bool AMDGPUPromoteAllocaImpl::run(Function &F, bool PromoteToLDS) { Mod = F.getParent(); DL = &Mod->getDataLayout(); @@ -237,6 +310,13 @@ bool AMDGPUPromoteAllocaImpl::run(Function &F, bool PromoteToLDS) { bool SufficientLDS = PromoteToLDS ? hasSufficientLocalMem(F) : false; + // Use up to 1/4 of available register budget for vectorization. + // FIXME: Increase the limit for whole function budgets? Perhaps x2? + unsigned VectorizationBudget = + (PromoteAllocaToVectorLimit ? PromoteAllocaToVectorLimit * 8 + : (MaxVGPRs * 32)) / + 4; + SmallVector<AllocaInst *, 16> Allocas; for (Instruction &I : F.getEntryBlock()) { if (AllocaInst *AI = dyn_cast<AllocaInst>(&I)) { @@ -248,11 +328,27 @@ bool AMDGPUPromoteAllocaImpl::run(Function &F, bool PromoteToLDS) { } } + sortAllocasToPromote(Allocas); + bool Changed = false; for (AllocaInst *AI : Allocas) { - if (tryPromoteAllocaToVector(*AI)) + const unsigned AllocaCost = DL->getTypeSizeInBits(AI->getAllocatedType()); + if (AllocaCost > VectorizationBudget) { + LLVM_DEBUG(dbgs() << " Alloca too big for vectorization: " << *AI + << "\n"); + return false; + } + + if (tryPromoteAllocaToVector(*AI)) { Changed = true; - else if (PromoteToLDS && tryPromoteAllocaToLDS(*AI, SufficientLDS)) + assert((VectorizationBudget - AllocaCost) < VectorizationBudget && + "Underflow!"); + VectorizationBudget -= AllocaCost; + LLVM_DEBUG(dbgs() << " Remaining vectorization budget:" + << VectorizationBudget << "\n"); + if (VectorizationBudget == 0) + break; + } else if (PromoteToLDS && tryPromoteAllocaToLDS(*AI, SufficientLDS)) Changed = true; } @@ -641,16 +737,6 @@ bool AMDGPUPromoteAllocaImpl::tryPromoteAllocaToVector(AllocaInst &Alloca) { ArrayTy->getNumElements()); } - // Use up to 1/4 of available register budget for vectorization. - unsigned Limit = PromoteAllocaToVectorLimit ? PromoteAllocaToVectorLimit * 8 - : (MaxVGPRs * 32); - - if (DL->getTypeSizeInBits(AllocaTy) * 4 > Limit) { - LLVM_DEBUG(dbgs() << " Alloca too big for vectorization with " << MaxVGPRs - << " registers available\n"); - return false; - } - // FIXME: There is no reason why we can't support larger arrays, we // are just being conservative for now. // FIXME: We also reject alloca's of the form [ 2 x [ 2 x i32 ]] or @@ -671,7 +757,6 @@ bool AMDGPUPromoteAllocaImpl::tryPromoteAllocaToVector(AllocaInst &Alloca) { SmallVector<Instruction *> WorkList; SmallVector<Instruction *> UsersToRemove; SmallVector<Instruction *> DeferredInsts; - SmallVector<Use *, 8> Uses; DenseMap<MemTransferInst *, MemTransferInfo> TransferInfo; const auto RejectUser = [&](Instruction *Inst, Twine Msg) { @@ -680,15 +765,14 @@ bool AMDGPUPromoteAllocaImpl::tryPromoteAllocaToVector(AllocaInst &Alloca) { return false; }; - for (Use &U : Alloca.uses()) - Uses.push_back(&U); + SmallVector<Use *, 8> Uses; + collectAllocaUses(Alloca, Uses); LLVM_DEBUG(dbgs() << " Attempting promotion to: " << *VectorTy << "\n"); Type *VecEltTy = VectorTy->getElementType(); unsigned ElementSize = DL->getTypeSizeInBits(VecEltTy) / 8; - while (!Uses.empty()) { - Use *U = Uses.pop_back_val(); + for (auto *U : Uses) { Instruction *Inst = cast<Instruction>(U->getUser()); if (Value *Ptr = getLoadStorePointerOperand(Inst)) { @@ -724,14 +808,6 @@ bool AMDGPUPromoteAllocaImpl::tryPromoteAllocaToVector(AllocaInst &Alloca) { continue; } - if (isa<BitCastInst>(Inst)) { - // Look through bitcasts. - for (Use &U : Inst->uses()) - Uses.push_back(&U); - UsersToRemove.push_back(Inst); - continue; - } - if (auto *GEP = dyn_cast<GetElementPtrInst>(Inst)) { // If we can't compute a vector index from this GEP, then we can't // promote this alloca to vector. @@ -740,8 +816,6 @@ bool AMDGPUPromoteAllocaImpl::tryPromoteAllocaToVector(AllocaInst &Alloca) { return RejectUser(Inst, "cannot compute vector index for GEP"); GEPVectorIdx[GEP] = Index; - for (Use &U : Inst->uses()) - Uses.push_back(&U); UsersToRemove.push_back(Inst); continue; } diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp index b174d57bd57656de4bf6019a67ec21220dfc5908..aa4ec785bf02a3ef8f857a88a5b3b9052f291d0a 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp @@ -449,7 +449,7 @@ bool AMDGPURegisterBankInfo::isScalarLoadLegal(const MachineInstr &MI) const { const unsigned AS = MMO->getAddrSpace(); const bool IsConst = AS == AMDGPUAS::CONSTANT_ADDRESS || AS == AMDGPUAS::CONSTANT_ADDRESS_32BIT; - const unsigned MemSize = 8 * MMO->getSize(); + const unsigned MemSize = 8 * MMO->getSize().getValue(); // Require 4-byte alignment. return (MMO->getAlign() >= Align(4) || @@ -1070,7 +1070,7 @@ bool AMDGPURegisterBankInfo::applyMappingLoad( return false; MachineMemOperand *MMO = *MI.memoperands_begin(); - const unsigned MemSize = 8 * MMO->getSize(); + const unsigned MemSize = 8 * MMO->getSize().getValue(); // Scalar loads of size 8 or 16 bit with proper alignment may be widened to // 32 bit. Check to see if we need to widen the memory access, 8 or 16 bit // scalar loads should have a load size of 32 but memory access size of less @@ -3135,6 +3135,8 @@ void AMDGPURegisterBankInfo::applyMappingImpl( case Intrinsic::amdgcn_interp_inreg_p2: case Intrinsic::amdgcn_interp_inreg_p10_f16: case Intrinsic::amdgcn_interp_inreg_p2_f16: + case Intrinsic::amdgcn_interp_p10_rtz_f16: + case Intrinsic::amdgcn_interp_p2_rtz_f16: applyDefaultMapping(OpdMapper); return; case Intrinsic::amdgcn_permlane16: @@ -4778,7 +4780,9 @@ AMDGPURegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { case Intrinsic::amdgcn_interp_inreg_p10: case Intrinsic::amdgcn_interp_inreg_p2: case Intrinsic::amdgcn_interp_inreg_p10_f16: - case Intrinsic::amdgcn_interp_inreg_p2_f16: { + case Intrinsic::amdgcn_interp_inreg_p2_f16: + case Intrinsic::amdgcn_interp_p10_rtz_f16: + case Intrinsic::amdgcn_interp_p2_rtz_f16: { unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, DstSize); OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VGPRRegBankID, 32); @@ -4889,7 +4893,8 @@ AMDGPURegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { case Intrinsic::amdgcn_flat_atomic_fadd_v2bf16: case Intrinsic::amdgcn_atomic_cond_sub_u32: case Intrinsic::amdgcn_global_atomic_ordered_add_b64: - case Intrinsic::amdgcn_global_load_tr: + case Intrinsic::amdgcn_global_load_tr_b64: + case Intrinsic::amdgcn_global_load_tr_b128: return getDefaultMappingAllVGPR(MI); case Intrinsic::amdgcn_ds_ordered_add: case Intrinsic::amdgcn_ds_ordered_swap: diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSearchableTables.td b/llvm/lib/Target/AMDGPU/AMDGPUSearchableTables.td index bb1c6b73372999b1da3366d8b7cccd2aa9a7bc12..410dc83d45c57fb90675b5b2cb354e070645259a 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUSearchableTables.td +++ b/llvm/lib/Target/AMDGPU/AMDGPUSearchableTables.td @@ -354,83 +354,19 @@ def : SourceOfDivergence<int_amdgcn_mov_dpp8>; def : SourceOfDivergence<int_amdgcn_update_dpp>; def : SourceOfDivergence<int_amdgcn_writelane>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_4x4x1f32>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_4x4x1f32>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_4x4x4f16>; -def : SourceOfDivergence<int_amdgcn_mfma_i32_4x4x4i8>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_4x4x2bf16>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_16x16x1f32>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_16x16x4f32>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_16x16x4f16>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_16x16x16f16>; -def : SourceOfDivergence<int_amdgcn_mfma_i32_16x16x4i8>; -def : SourceOfDivergence<int_amdgcn_mfma_i32_16x16x16i8>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_16x16x2bf16>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_16x16x8bf16>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_32x32x1f32>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_32x32x2f32>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_32x32x4f16>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_32x32x8f16>; -def : SourceOfDivergence<int_amdgcn_mfma_i32_32x32x4i8>; -def : SourceOfDivergence<int_amdgcn_mfma_i32_32x32x8i8>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_32x32x2bf16>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_32x32x4bf16>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_32x32x4bf16_1k>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_16x16x4bf16_1k>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_4x4x4bf16_1k>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_32x32x8bf16_1k>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_16x16x16bf16_1k>; -def : SourceOfDivergence<int_amdgcn_mfma_f64_16x16x4f64>; -def : SourceOfDivergence<int_amdgcn_mfma_f64_4x4x4f64>; -def : SourceOfDivergence<int_amdgcn_mfma_i32_16x16x32_i8>; -def : SourceOfDivergence<int_amdgcn_mfma_i32_32x32x16_i8>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_16x16x8_xf32>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_32x32x4_xf32>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_16x16x32_bf8_bf8>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_16x16x32_bf8_fp8>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_16x16x32_fp8_bf8>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_16x16x32_fp8_fp8>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_32x32x16_bf8_bf8>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_32x32x16_bf8_fp8>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_32x32x16_fp8_bf8>; -def : SourceOfDivergence<int_amdgcn_mfma_f32_32x32x16_fp8_fp8>; -def : SourceOfDivergence<int_amdgcn_smfmac_f32_16x16x32_f16>; -def : SourceOfDivergence<int_amdgcn_smfmac_f32_32x32x16_f16>; -def : SourceOfDivergence<int_amdgcn_smfmac_f32_16x16x32_bf16>; -def : SourceOfDivergence<int_amdgcn_smfmac_f32_32x32x16_bf16>; -def : SourceOfDivergence<int_amdgcn_smfmac_i32_16x16x64_i8>; -def : SourceOfDivergence<int_amdgcn_smfmac_i32_32x32x32_i8>; -def : SourceOfDivergence<int_amdgcn_smfmac_f32_16x16x64_bf8_bf8>; -def : SourceOfDivergence<int_amdgcn_smfmac_f32_16x16x64_bf8_fp8>; -def : SourceOfDivergence<int_amdgcn_smfmac_f32_16x16x64_fp8_bf8>; -def : SourceOfDivergence<int_amdgcn_smfmac_f32_16x16x64_fp8_fp8>; -def : SourceOfDivergence<int_amdgcn_smfmac_f32_32x32x32_bf8_bf8>; -def : SourceOfDivergence<int_amdgcn_smfmac_f32_32x32x32_bf8_fp8>; -def : SourceOfDivergence<int_amdgcn_smfmac_f32_32x32x32_fp8_bf8>; -def : SourceOfDivergence<int_amdgcn_smfmac_f32_32x32x32_fp8_fp8>; -def : SourceOfDivergence<int_amdgcn_wmma_f32_16x16x16_f16>; -def : SourceOfDivergence<int_amdgcn_wmma_f32_16x16x16_bf16>; -def : SourceOfDivergence<int_amdgcn_wmma_f16_16x16x16_f16>; -def : SourceOfDivergence<int_amdgcn_wmma_bf16_16x16x16_bf16>; -def : SourceOfDivergence<int_amdgcn_wmma_i32_16x16x16_iu8>; -def : SourceOfDivergence<int_amdgcn_wmma_i32_16x16x16_iu4>; -def : SourceOfDivergence<int_amdgcn_wmma_f32_16x16x16_fp8_fp8>; -def : SourceOfDivergence<int_amdgcn_wmma_f32_16x16x16_fp8_bf8>; -def : SourceOfDivergence<int_amdgcn_wmma_f32_16x16x16_bf8_fp8>; -def : SourceOfDivergence<int_amdgcn_wmma_f32_16x16x16_bf8_bf8>; -def : SourceOfDivergence<int_amdgcn_wmma_i32_16x16x32_iu4>; -def : SourceOfDivergence<int_amdgcn_swmmac_f32_16x16x32_f16>; -def : SourceOfDivergence<int_amdgcn_swmmac_f32_16x16x32_bf16>; -def : SourceOfDivergence<int_amdgcn_swmmac_f16_16x16x32_f16>; -def : SourceOfDivergence<int_amdgcn_swmmac_bf16_16x16x32_bf16>; -def : SourceOfDivergence<int_amdgcn_swmmac_i32_16x16x32_iu8>; -def : SourceOfDivergence<int_amdgcn_swmmac_i32_16x16x32_iu4>; -def : SourceOfDivergence<int_amdgcn_swmmac_i32_16x16x64_iu4>; -def : SourceOfDivergence<int_amdgcn_swmmac_f32_16x16x32_fp8_fp8>; -def : SourceOfDivergence<int_amdgcn_swmmac_f32_16x16x32_fp8_bf8>; -def : SourceOfDivergence<int_amdgcn_swmmac_f32_16x16x32_bf8_fp8>; -def : SourceOfDivergence<int_amdgcn_swmmac_f32_16x16x32_bf8_bf8>; -def : SourceOfDivergence<int_amdgcn_global_load_tr>; +foreach intr = AMDGPUMFMAIntrinsics908 in +def : SourceOfDivergence<intr>; +foreach intr = AMDGPUMFMAIntrinsics90A in +def : SourceOfDivergence<intr>; +foreach intr = AMDGPUMFMAIntrinsics940 in +def : SourceOfDivergence<intr>; +foreach intr = AMDGPUWMMAIntrinsicsGFX11 in +def : SourceOfDivergence<intr>; +foreach intr = AMDGPUWMMAIntrinsicsGFX12 in +def : SourceOfDivergence<intr>; + +def : SourceOfDivergence<int_amdgcn_global_load_tr_b64>; +def : SourceOfDivergence<int_amdgcn_global_load_tr_b128>; // The dummy boolean output is divergent from the IR's perspective, // but the mask results are uniform. These produce a divergent and diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp index 2b457fe519d96c8e7ee4cf271a2543ab5f9f257b..f7e552177d6f502c408ca318add8cb6b55562556 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp @@ -631,107 +631,26 @@ void AMDGPUTargetMachine::registerDefaultAliasAnalyses(AAManager &AAM) { AAM.registerFunctionAnalysis<AMDGPUAA>(); } +static Expected<ScanOptions> +parseAMDGPUAtomicOptimizerStrategy(StringRef Params) { + if (Params.empty()) + return ScanOptions::Iterative; + Params.consume_front("strategy="); + auto Result = StringSwitch<std::optional<ScanOptions>>(Params) + .Case("dpp", ScanOptions::DPP) + .Cases("iterative", "", ScanOptions::Iterative) + .Case("none", ScanOptions::None) + .Default(std::nullopt); + if (Result) + return *Result; + return make_error<StringError>("invalid parameter", inconvertibleErrorCode()); +} + void AMDGPUTargetMachine::registerPassBuilderCallbacks( PassBuilder &PB, bool PopulateClassToPassNames) { - PB.registerPipelineParsingCallback( - [this](StringRef PassName, ModulePassManager &PM, - ArrayRef<PassBuilder::PipelineElement>) { - if (PassName == "amdgpu-attributor") { - PM.addPass(AMDGPUAttributorPass(*this)); - return true; - } - if (PassName == "amdgpu-unify-metadata") { - PM.addPass(AMDGPUUnifyMetadataPass()); - return true; - } - if (PassName == "amdgpu-printf-runtime-binding") { - PM.addPass(AMDGPUPrintfRuntimeBindingPass()); - return true; - } - if (PassName == "amdgpu-always-inline") { - PM.addPass(AMDGPUAlwaysInlinePass()); - return true; - } - if (PassName == "amdgpu-lower-module-lds") { - PM.addPass(AMDGPULowerModuleLDSPass(*this)); - return true; - } - if (PassName == "amdgpu-lower-buffer-fat-pointers") { - PM.addPass(AMDGPULowerBufferFatPointersPass(*this)); - return true; - } - if (PassName == "amdgpu-lower-ctor-dtor") { - PM.addPass(AMDGPUCtorDtorLoweringPass()); - return true; - } - return false; - }); - PB.registerPipelineParsingCallback( - [this](StringRef PassName, FunctionPassManager &PM, - ArrayRef<PassBuilder::PipelineElement>) { - if (PassName == "amdgpu-simplifylib") { - PM.addPass(AMDGPUSimplifyLibCallsPass()); - return true; - } - if (PassName == "amdgpu-image-intrinsic-opt") { - PM.addPass(AMDGPUImageIntrinsicOptimizerPass(*this)); - return true; - } - if (PassName == "amdgpu-usenative") { - PM.addPass(AMDGPUUseNativeCallsPass()); - return true; - } - if (PassName == "amdgpu-promote-alloca") { - PM.addPass(AMDGPUPromoteAllocaPass(*this)); - return true; - } - if (PassName == "amdgpu-promote-alloca-to-vector") { - PM.addPass(AMDGPUPromoteAllocaToVectorPass(*this)); - return true; - } - if (PassName == "amdgpu-lower-kernel-attributes") { - PM.addPass(AMDGPULowerKernelAttributesPass()); - return true; - } - if (PassName == "amdgpu-promote-kernel-arguments") { - PM.addPass(AMDGPUPromoteKernelArgumentsPass()); - return true; - } - if (PassName == "amdgpu-unify-divergent-exit-nodes") { - PM.addPass(AMDGPUUnifyDivergentExitNodesPass()); - return true; - } - if (PassName == "amdgpu-atomic-optimizer") { - PM.addPass( - AMDGPUAtomicOptimizerPass(*this, AMDGPUAtomicOptimizerStrategy)); - return true; - } - if (PassName == "amdgpu-codegenprepare") { - PM.addPass(AMDGPUCodeGenPreparePass(*this)); - return true; - } - if (PassName == "amdgpu-lower-kernel-arguments") { - PM.addPass(AMDGPULowerKernelArgumentsPass(*this)); - return true; - } - if (PassName == "amdgpu-rewrite-undef-for-phi") { - PM.addPass(AMDGPURewriteUndefForPHIPass()); - return true; - } - return false; - }); - - PB.registerAnalysisRegistrationCallback([](FunctionAnalysisManager &FAM) { - FAM.registerPass([&] { return AMDGPUAA(); }); - }); - PB.registerParseAACallback([](StringRef AAName, AAManager &AAM) { - if (AAName == "amdgpu-aa") { - AAM.registerFunctionAnalysis<AMDGPUAA>(); - return true; - } - return false; - }); +#define GET_PASS_REGISTRY "AMDGPUPassRegistry.def" +#include "llvm/Passes/TargetPassRegistry.inc" PB.registerPipelineStartEPCallback( [](ModulePassManager &PM, OptimizationLevel Level) { @@ -793,6 +712,15 @@ void AMDGPUTargetMachine::registerPassBuilderCallbacks( PM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM))); }); + + PB.registerFullLinkTimeOptimizationLastEPCallback( + [this](ModulePassManager &PM, OptimizationLevel Level) { + // We want to support the -lto-partitions=N option as "best effort". + // For that, we need to lower LDS earlier in the pipeline before the + // module is partitioned for codegen. + if (EnableLowerModuleLDS) + PM.addPass(AMDGPULowerModuleLDSPass(*this)); + }); } int64_t AMDGPUTargetMachine::getNullPointerValue(unsigned AddrSpace) { diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp index 027dd0f2c22448b6dab1d49c6a9fa8dbe504b228..294fc683fe9216d3b2c0876322cb04f74e754240 100644 --- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -7,6 +7,8 @@ //===----------------------------------------------------------------------===// #include "AMDKernelCodeT.h" +#include "MCTargetDesc/AMDGPUMCExpr.h" +#include "MCTargetDesc/AMDGPUMCKernelDescriptor.h" #include "MCTargetDesc/AMDGPUMCTargetDesc.h" #include "MCTargetDesc/AMDGPUTargetStreamer.h" #include "SIDefines.h" @@ -980,7 +982,7 @@ public: return Imm.Type; } - unsigned getReg() const override { + MCRegister getReg() const override { assert(isRegKind()); return Reg.RegNo; } @@ -1816,6 +1818,7 @@ private: public: void onBeginOfFile() override; + bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override; ParseStatus parseCustomOperand(OperandVector &Operands, unsigned MCK); @@ -5415,7 +5418,9 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { if (getParser().parseIdentifier(KernelName)) return true; - kernel_descriptor_t KD = getDefaultAmdhsaKernelDescriptor(&getSTI()); + AMDGPU::MCKernelDescriptor KD = + AMDGPU::MCKernelDescriptor::getDefaultAmdhsaKernelDescriptor( + &getSTI(), getContext()); StringSet<> Seen; @@ -5455,89 +5460,111 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { return TokError(".amdhsa_ directives cannot be repeated"); SMLoc ValStart = getLoc(); - int64_t IVal; - if (getParser().parseAbsoluteExpression(IVal)) + const MCExpr *ExprVal; + if (getParser().parseExpression(ExprVal)) return true; SMLoc ValEnd = getLoc(); SMRange ValRange = SMRange(ValStart, ValEnd); - if (IVal < 0) - return OutOfRangeError(ValRange); - + int64_t IVal = 0; uint64_t Val = IVal; + bool EvaluatableExpr; + if ((EvaluatableExpr = ExprVal->evaluateAsAbsolute(IVal))) { + if (IVal < 0) + return OutOfRangeError(ValRange); + Val = IVal; + } #define PARSE_BITS_ENTRY(FIELD, ENTRY, VALUE, RANGE) \ - if (!isUInt<ENTRY##_WIDTH>(VALUE)) \ + if (!isUInt<ENTRY##_WIDTH>(Val)) \ return OutOfRangeError(RANGE); \ - AMDHSA_BITS_SET(FIELD, ENTRY, VALUE); + AMDGPU::MCKernelDescriptor::bits_set(FIELD, VALUE, ENTRY##_SHIFT, ENTRY, \ + getContext()); + +// Some fields use the parsed value immediately which requires the expression to +// be solvable. +#define EXPR_RESOLVE_OR_ERROR(RESOLVED) \ + if (!(RESOLVED)) \ + return Error(IDRange.Start, "directive should have resolvable expression", \ + IDRange); if (ID == ".amdhsa_group_segment_fixed_size") { - if (!isUInt<sizeof(KD.group_segment_fixed_size) * CHAR_BIT>(Val)) + if (!isUInt<sizeof(kernel_descriptor_t::group_segment_fixed_size) * + CHAR_BIT>(Val)) return OutOfRangeError(ValRange); - KD.group_segment_fixed_size = Val; + KD.group_segment_fixed_size = ExprVal; } else if (ID == ".amdhsa_private_segment_fixed_size") { - if (!isUInt<sizeof(KD.private_segment_fixed_size) * CHAR_BIT>(Val)) + if (!isUInt<sizeof(kernel_descriptor_t::private_segment_fixed_size) * + CHAR_BIT>(Val)) return OutOfRangeError(ValRange); - KD.private_segment_fixed_size = Val; + KD.private_segment_fixed_size = ExprVal; } else if (ID == ".amdhsa_kernarg_size") { - if (!isUInt<sizeof(KD.kernarg_size) * CHAR_BIT>(Val)) + if (!isUInt<sizeof(kernel_descriptor_t::kernarg_size) * CHAR_BIT>(Val)) return OutOfRangeError(ValRange); - KD.kernarg_size = Val; + KD.kernarg_size = ExprVal; } else if (ID == ".amdhsa_user_sgpr_count") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); ExplicitUserSGPRCount = Val; } else if (ID == ".amdhsa_user_sgpr_private_segment_buffer") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); if (hasArchitectedFlatScratch()) return Error(IDRange.Start, "directive is not supported with architected flat scratch", IDRange); PARSE_BITS_ENTRY(KD.kernel_code_properties, KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER, - Val, ValRange); + ExprVal, ValRange); if (Val) ImpliedUserSGPRCount += 4; } else if (ID == ".amdhsa_user_sgpr_kernarg_preload_length") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); if (!hasKernargPreload()) return Error(IDRange.Start, "directive requires gfx90a+", IDRange); if (Val > getMaxNumUserSGPRs()) return OutOfRangeError(ValRange); - PARSE_BITS_ENTRY(KD.kernarg_preload, KERNARG_PRELOAD_SPEC_LENGTH, Val, + PARSE_BITS_ENTRY(KD.kernarg_preload, KERNARG_PRELOAD_SPEC_LENGTH, ExprVal, ValRange); if (Val) { ImpliedUserSGPRCount += Val; PreloadLength = Val; } } else if (ID == ".amdhsa_user_sgpr_kernarg_preload_offset") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); if (!hasKernargPreload()) return Error(IDRange.Start, "directive requires gfx90a+", IDRange); if (Val >= 1024) return OutOfRangeError(ValRange); - PARSE_BITS_ENTRY(KD.kernarg_preload, KERNARG_PRELOAD_SPEC_OFFSET, Val, + PARSE_BITS_ENTRY(KD.kernarg_preload, KERNARG_PRELOAD_SPEC_OFFSET, ExprVal, ValRange); if (Val) PreloadOffset = Val; } else if (ID == ".amdhsa_user_sgpr_dispatch_ptr") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); PARSE_BITS_ENTRY(KD.kernel_code_properties, - KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR, Val, + KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR, ExprVal, ValRange); if (Val) ImpliedUserSGPRCount += 2; } else if (ID == ".amdhsa_user_sgpr_queue_ptr") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); PARSE_BITS_ENTRY(KD.kernel_code_properties, - KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR, Val, + KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR, ExprVal, ValRange); if (Val) ImpliedUserSGPRCount += 2; } else if (ID == ".amdhsa_user_sgpr_kernarg_segment_ptr") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); PARSE_BITS_ENTRY(KD.kernel_code_properties, KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR, - Val, ValRange); + ExprVal, ValRange); if (Val) ImpliedUserSGPRCount += 2; } else if (ID == ".amdhsa_user_sgpr_dispatch_id") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); PARSE_BITS_ENTRY(KD.kernel_code_properties, - KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID, Val, + KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID, ExprVal, ValRange); if (Val) ImpliedUserSGPRCount += 2; @@ -5546,34 +5573,39 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { return Error(IDRange.Start, "directive is not supported with architected flat scratch", IDRange); + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); PARSE_BITS_ENTRY(KD.kernel_code_properties, - KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT, Val, - ValRange); + KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT, + ExprVal, ValRange); if (Val) ImpliedUserSGPRCount += 2; } else if (ID == ".amdhsa_user_sgpr_private_segment_size") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); PARSE_BITS_ENTRY(KD.kernel_code_properties, KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE, - Val, ValRange); + ExprVal, ValRange); if (Val) ImpliedUserSGPRCount += 1; } else if (ID == ".amdhsa_wavefront_size32") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); if (IVersion.Major < 10) return Error(IDRange.Start, "directive requires gfx10+", IDRange); EnableWavefrontSize32 = Val; PARSE_BITS_ENTRY(KD.kernel_code_properties, - KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32, - Val, ValRange); + KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32, ExprVal, + ValRange); } else if (ID == ".amdhsa_uses_dynamic_stack") { PARSE_BITS_ENTRY(KD.kernel_code_properties, - KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK, Val, ValRange); + KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK, ExprVal, + ValRange); } else if (ID == ".amdhsa_system_sgpr_private_segment_wavefront_offset") { if (hasArchitectedFlatScratch()) return Error(IDRange.Start, "directive is not supported with architected flat scratch", IDRange); PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, - COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, Val, ValRange); + COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, ExprVal, + ValRange); } else if (ID == ".amdhsa_enable_private_segment") { if (!hasArchitectedFlatScratch()) return Error( @@ -5581,42 +5613,48 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { "directive is not supported without architected flat scratch", IDRange); PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, - COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, Val, ValRange); + COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, ExprVal, + ValRange); } else if (ID == ".amdhsa_system_sgpr_workgroup_id_x") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, - COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, Val, + COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, ExprVal, ValRange); } else if (ID == ".amdhsa_system_sgpr_workgroup_id_y") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, - COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y, Val, + COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y, ExprVal, ValRange); } else if (ID == ".amdhsa_system_sgpr_workgroup_id_z") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, - COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z, Val, + COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z, ExprVal, ValRange); } else if (ID == ".amdhsa_system_sgpr_workgroup_info") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, - COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO, Val, + COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO, ExprVal, ValRange); } else if (ID == ".amdhsa_system_vgpr_workitem_id") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, - COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID, Val, + COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID, ExprVal, ValRange); } else if (ID == ".amdhsa_next_free_vgpr") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); VGPRRange = ValRange; NextFreeVGPR = Val; } else if (ID == ".amdhsa_next_free_sgpr") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); SGPRRange = ValRange; NextFreeSGPR = Val; } else if (ID == ".amdhsa_accum_offset") { if (!isGFX90A()) return Error(IDRange.Start, "directive requires gfx90a+", IDRange); + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); AccumOffset = Val; } else if (ID == ".amdhsa_reserve_vcc") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); if (!isUInt<1>(Val)) return OutOfRangeError(ValRange); ReserveVCC = Val; } else if (ID == ".amdhsa_reserve_flat_scratch") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); if (IVersion.Major < 7) return Error(IDRange.Start, "directive requires gfx7+", IDRange); if (hasArchitectedFlatScratch()) @@ -5636,97 +5674,105 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { IDRange); } else if (ID == ".amdhsa_float_round_mode_32") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, - COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32, Val, ValRange); + COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32, ExprVal, + ValRange); } else if (ID == ".amdhsa_float_round_mode_16_64") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, - COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64, Val, ValRange); + COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64, ExprVal, + ValRange); } else if (ID == ".amdhsa_float_denorm_mode_32") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, - COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32, Val, ValRange); + COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32, ExprVal, + ValRange); } else if (ID == ".amdhsa_float_denorm_mode_16_64") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, - COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, Val, + COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, ExprVal, ValRange); } else if (ID == ".amdhsa_dx10_clamp") { if (IVersion.Major >= 12) return Error(IDRange.Start, "directive unsupported on gfx12+", IDRange); PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, - COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP, Val, + COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP, ExprVal, ValRange); } else if (ID == ".amdhsa_ieee_mode") { if (IVersion.Major >= 12) return Error(IDRange.Start, "directive unsupported on gfx12+", IDRange); PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, - COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE, Val, + COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE, ExprVal, ValRange); } else if (ID == ".amdhsa_fp16_overflow") { if (IVersion.Major < 9) return Error(IDRange.Start, "directive requires gfx9+", IDRange); - PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL, Val, + PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, + COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL, ExprVal, ValRange); } else if (ID == ".amdhsa_tg_split") { if (!isGFX90A()) return Error(IDRange.Start, "directive requires gfx90a+", IDRange); - PARSE_BITS_ENTRY(KD.compute_pgm_rsrc3, COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT, Val, - ValRange); + PARSE_BITS_ENTRY(KD.compute_pgm_rsrc3, COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT, + ExprVal, ValRange); } else if (ID == ".amdhsa_workgroup_processor_mode") { if (IVersion.Major < 10) return Error(IDRange.Start, "directive requires gfx10+", IDRange); - PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE, Val, + PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, + COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE, ExprVal, ValRange); } else if (ID == ".amdhsa_memory_ordered") { if (IVersion.Major < 10) return Error(IDRange.Start, "directive requires gfx10+", IDRange); - PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED, Val, + PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, + COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED, ExprVal, ValRange); } else if (ID == ".amdhsa_forward_progress") { if (IVersion.Major < 10) return Error(IDRange.Start, "directive requires gfx10+", IDRange); - PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS, Val, + PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, + COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS, ExprVal, ValRange); } else if (ID == ".amdhsa_shared_vgpr_count") { + EXPR_RESOLVE_OR_ERROR(EvaluatableExpr); if (IVersion.Major < 10 || IVersion.Major >= 12) return Error(IDRange.Start, "directive requires gfx10 or gfx11", IDRange); SharedVGPRCount = Val; PARSE_BITS_ENTRY(KD.compute_pgm_rsrc3, - COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT, Val, + COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT, ExprVal, ValRange); } else if (ID == ".amdhsa_exception_fp_ieee_invalid_op") { PARSE_BITS_ENTRY( KD.compute_pgm_rsrc2, - COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION, Val, - ValRange); + COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION, + ExprVal, ValRange); } else if (ID == ".amdhsa_exception_fp_denorm_src") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE, - Val, ValRange); + ExprVal, ValRange); } else if (ID == ".amdhsa_exception_fp_ieee_div_zero") { PARSE_BITS_ENTRY( KD.compute_pgm_rsrc2, - COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO, Val, - ValRange); + COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO, + ExprVal, ValRange); } else if (ID == ".amdhsa_exception_fp_ieee_overflow") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW, - Val, ValRange); + ExprVal, ValRange); } else if (ID == ".amdhsa_exception_fp_ieee_underflow") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW, - Val, ValRange); + ExprVal, ValRange); } else if (ID == ".amdhsa_exception_fp_ieee_inexact") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT, - Val, ValRange); + ExprVal, ValRange); } else if (ID == ".amdhsa_exception_int_div_zero") { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO, - Val, ValRange); + ExprVal, ValRange); } else if (ID == ".amdhsa_round_robin_scheduling") { if (IVersion.Major < 12) return Error(IDRange.Start, "directive requires gfx12+", IDRange); PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, - COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN, Val, + COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN, ExprVal, ValRange); } else { return Error(IDRange.Start, "unknown .amdhsa_kernel directive", IDRange); @@ -5753,15 +5799,18 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { if (!isUInt<COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT_WIDTH>( VGPRBlocks)) return OutOfRangeError(VGPRRange); - AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, - COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT, VGPRBlocks); + AMDGPU::MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc1, MCConstantExpr::create(VGPRBlocks, getContext()), + COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT_SHIFT, + COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT, getContext()); if (!isUInt<COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT_WIDTH>( SGPRBlocks)) return OutOfRangeError(SGPRRange); - AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, - COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT, - SGPRBlocks); + AMDGPU::MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc1, MCConstantExpr::create(SGPRBlocks, getContext()), + COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT_SHIFT, + COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT, getContext()); if (ExplicitUserSGPRCount && ImpliedUserSGPRCount > *ExplicitUserSGPRCount) return TokError("amdgpu_user_sgpr_count smaller than than implied by " @@ -5772,11 +5821,17 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { if (!isUInt<COMPUTE_PGM_RSRC2_USER_SGPR_COUNT_WIDTH>(UserSGPRCount)) return TokError("too many user SGPRs enabled"); - AMDHSA_BITS_SET(KD.compute_pgm_rsrc2, COMPUTE_PGM_RSRC2_USER_SGPR_COUNT, - UserSGPRCount); - - if (PreloadLength && KD.kernarg_size && - (PreloadLength * 4 + PreloadOffset * 4 > KD.kernarg_size)) + AMDGPU::MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc2, MCConstantExpr::create(UserSGPRCount, getContext()), + COMPUTE_PGM_RSRC2_USER_SGPR_COUNT_SHIFT, + COMPUTE_PGM_RSRC2_USER_SGPR_COUNT, getContext()); + + int64_t IVal = 0; + if (!KD.kernarg_size->evaluateAsAbsolute(IVal)) + return TokError("Kernarg size should be resolvable"); + uint64_t kernarg_size = IVal; + if (PreloadLength && kernarg_size && + (PreloadLength * 4 + PreloadOffset * 4 > kernarg_size)) return TokError("Kernarg preload length + offset is larger than the " "kernarg segment size"); @@ -5788,8 +5843,11 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { "increments of 4"); if (AccumOffset > alignTo(std::max((uint64_t)1, NextFreeVGPR), 4)) return TokError("accum_offset exceeds total VGPR allocation"); - AMDHSA_BITS_SET(KD.compute_pgm_rsrc3, COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET, - (AccumOffset / 4 - 1)); + MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc3, + MCConstantExpr::create(AccumOffset / 4 - 1, getContext()), + COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET_SHIFT, + COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET, getContext()); } if (IVersion.Major >= 10 && IVersion.Major < 12) { @@ -8330,6 +8388,59 @@ void AMDGPUAsmParser::onBeginOfFile() { getTargetStreamer().EmitDirectiveAMDGCNTarget(); } +/// Parse AMDGPU specific expressions. +/// +/// expr ::= or(expr, ...) | +/// max(expr, ...) +/// +bool AMDGPUAsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { + using AGVK = AMDGPUVariadicMCExpr::VariadicKind; + + if (isToken(AsmToken::Identifier)) { + StringRef TokenId = getTokenStr(); + AGVK VK = StringSwitch<AGVK>(TokenId) + .Case("max", AGVK::AGVK_Max) + .Case("or", AGVK::AGVK_Or) + .Default(AGVK::AGVK_None); + + if (VK != AGVK::AGVK_None && peekToken().is(AsmToken::LParen)) { + SmallVector<const MCExpr *, 4> Exprs; + uint64_t CommaCount = 0; + lex(); // Eat 'max'/'or' + lex(); // Eat '(' + while (true) { + if (trySkipToken(AsmToken::RParen)) { + if (Exprs.empty()) { + Error(getToken().getLoc(), + "empty " + Twine(TokenId) + " expression"); + return true; + } + if (CommaCount + 1 != Exprs.size()) { + Error(getToken().getLoc(), + "mismatch of commas in " + Twine(TokenId) + " expression"); + return true; + } + Res = AMDGPUVariadicMCExpr::create(VK, Exprs, getContext()); + return false; + } + const MCExpr *Expr; + if (getParser().parseExpression(Expr, EndLoc)) + return true; + Exprs.push_back(Expr); + bool LastTokenWasComma = trySkipToken(AsmToken::Comma); + if (LastTokenWasComma) + CommaCount++; + if (!LastTokenWasComma && !isToken(AsmToken::RParen)) { + Error(getToken().getLoc(), + "unexpected token in " + Twine(TokenId) + " expression"); + return true; + } + } + } + } + return getParser().parsePrimaryExpr(Res, EndLoc, nullptr); +} + ParseStatus AMDGPUAsmParser::parseOModSI(OperandVector &Operands) { StringRef Name = getTokenStr(); if (Name == "mul") { diff --git a/llvm/lib/Target/AMDGPU/BUFInstructions.td b/llvm/lib/Target/AMDGPU/BUFInstructions.td index c7091028b3b5e576c48298aee7b5cb138f770e42..273f92abf3546567c08e4b316baa385025f03de0 100644 --- a/llvm/lib/Target/AMDGPU/BUFInstructions.td +++ b/llvm/lib/Target/AMDGPU/BUFInstructions.td @@ -86,7 +86,7 @@ class BUF_Pseudo <string opName, dag outs, dag ins, bits<1> has_soffset = 1; bits<1> has_offset = 1; bits<1> has_slc = 1; - bits<1> tfe = ?; + bits<1> tfe = 0; bits<4> elements = 0; bits<1> has_sccb = 1; bits<1> sccb_value = 0; @@ -323,6 +323,7 @@ class MUBUF_Pseudo <string opName, dag outs, dag ins, Instruction BaseOpcode = !cast<Instruction>(MUBUFGetBaseOpcode<NAME>.ret); let MUBUF = 1; let AsmMatchConverter = "cvtMubuf"; + let usesCustomInserter = 1; } class MUBUF_Real <MUBUF_Pseudo ps, string real_name = ps.Mnemonic> : @@ -2616,7 +2617,6 @@ defm BUFFER_ATOMIC_CMPSWAP_X2 : MUBUF_Real_Atomic_gfx11_gfx12<0x042, "buffer defm BUFFER_ATOMIC_FCMPSWAP : MUBUF_Real_Atomic_gfx11<0x050, "buffer_atomic_cmpswap_f32">; defm BUFFER_ATOMIC_COND_SUB_U32 : MUBUF_Real_Atomic_gfx12<0x050>; defm BUFFER_ATOMIC_CSUB : MUBUF_Real_Atomic_gfx11_gfx12<0x037, "buffer_atomic_sub_clamp_u32", "buffer_atomic_csub_u32">; -def : Mnem_gfx11_gfx12<"buffer_atomic_csub", "buffer_atomic_csub_u32">; defm BUFFER_ATOMIC_DEC : MUBUF_Real_Atomic_gfx11_gfx12<0x040, "buffer_atomic_dec_u32">; defm BUFFER_ATOMIC_DEC_X2 : MUBUF_Real_Atomic_gfx11_gfx12<0x04D, "buffer_atomic_dec_u64">; defm BUFFER_ATOMIC_INC : MUBUF_Real_Atomic_gfx11_gfx12<0x03F, "buffer_atomic_inc_u32">; @@ -3370,7 +3370,7 @@ def MUBUFInfoTable : GenericTable { let CppTypeName = "MUBUFInfo"; let Fields = [ "Opcode", "BaseOpcode", "elements", "has_vaddr", "has_srsrc", "has_soffset", - "IsBufferInv" + "IsBufferInv", "tfe" ]; let PrimaryKey = ["Opcode"]; diff --git a/llvm/lib/Target/AMDGPU/DSInstructions.td b/llvm/lib/Target/AMDGPU/DSInstructions.td index 87ace01a6d0e56d368afd5b0d30c44452f2fd986..e944dde159904274e6ef76992cff9babc15f0df0 100644 --- a/llvm/lib/Target/AMDGPU/DSInstructions.td +++ b/llvm/lib/Target/AMDGPU/DSInstructions.td @@ -1735,14 +1735,12 @@ def DS_WRITE_B128_vi : DS_Real_vi<0xdf, DS_WRITE_B128>; def DS_READ_B96_vi : DS_Real_vi<0xfe, DS_READ_B96>; def DS_READ_B128_vi : DS_Real_vi<0xff, DS_READ_B128>; -let SubtargetPredicate = isGFX90APlus in { - def DS_ADD_F64_vi : DS_Real_vi<0x5c, DS_ADD_F64>; - def DS_ADD_RTN_F64_vi : DS_Real_vi<0x7c, DS_ADD_RTN_F64>; -} // End SubtargetPredicate = isGFX90APlus - -let SubtargetPredicate = isGFX940Plus in { - def DS_PK_ADD_F16_vi : DS_Real_vi<0x17, DS_PK_ADD_F16>; - def DS_PK_ADD_RTN_F16_vi : DS_Real_vi<0xb7, DS_PK_ADD_RTN_F16>; - def DS_PK_ADD_BF16_vi : DS_Real_vi<0x18, DS_PK_ADD_BF16>; - def DS_PK_ADD_RTN_BF16_vi : DS_Real_vi<0xb8, DS_PK_ADD_RTN_BF16>; -} // End SubtargetPredicate = isGFX940Plus +// GFX90A+. +def DS_ADD_F64_vi : DS_Real_vi<0x5c, DS_ADD_F64>; +def DS_ADD_RTN_F64_vi : DS_Real_vi<0x7c, DS_ADD_RTN_F64>; + +// GFX940+. +def DS_PK_ADD_F16_vi : DS_Real_vi<0x17, DS_PK_ADD_F16>; +def DS_PK_ADD_RTN_F16_vi : DS_Real_vi<0xb7, DS_PK_ADD_RTN_F16>; +def DS_PK_ADD_BF16_vi : DS_Real_vi<0x18, DS_PK_ADD_BF16>; +def DS_PK_ADD_RTN_BF16_vi : DS_Real_vi<0xb8, DS_PK_ADD_RTN_BF16>; diff --git a/llvm/lib/Target/AMDGPU/FLATInstructions.td b/llvm/lib/Target/AMDGPU/FLATInstructions.td index f42d4ae416bd76f9e6d829e40fa62579ada3c7a4..d017ec4a7415108015e9a7e83f41e1741f50ef54 100644 --- a/llvm/lib/Target/AMDGPU/FLATInstructions.td +++ b/llvm/lib/Target/AMDGPU/FLATInstructions.td @@ -115,8 +115,7 @@ class FLAT_Real <bits<7> op, FLAT_Pseudo ps, string opName = ps.Mnemonic> : bits<1> lds = ps.lds; // LDS DMA for global and scratch // Segment, 00=flat, 01=scratch, 10=global, 11=reserved - bits<2> seg = !if(ps.is_flat_global, 0b10, - !if(ps.is_flat_scratch, 0b01, 0)); + bits<2> seg = {ps.is_flat_global, ps.is_flat_scratch}; // Signed offset. Highest bit ignored for flat and treated as 12-bit // unsigned for flat accesses. @@ -174,7 +173,7 @@ class VFLAT_Real <bits<8> op, FLAT_Pseudo ps, string opName = ps.Mnemonic> : bits<8> vaddr; bits<24> offset; - let Inst{6-0} = !if(ps.has_saddr, !if(ps.enabled_saddr, saddr, 0x7f), 0); + let Inst{6-0} = !if(ps.enabled_saddr, saddr, SGPR_NULL_gfx11plus.Index); let Inst{21-14} = op; let Inst{31-26} = 0x3b; let Inst{39-32} = !if(ps.has_vdst, vdst, ?); @@ -240,7 +239,7 @@ class FLAT_Store_Pseudo <string opName, RegisterClass vdataClass, } multiclass FLAT_Global_Load_Pseudo<string opName, RegisterClass regClass, bit HasTiedInput = 0> { - let is_flat_global = 1, SubtargetPredicate = HasFlatGlobalInsts in { + let is_flat_global = 1 in { def "" : FLAT_Load_Pseudo<opName, regClass, HasTiedInput, 1>, GlobalSaddrTable<0, opName>; def _SADDR : FLAT_Load_Pseudo<opName, regClass, HasTiedInput, 1, 1>, @@ -277,7 +276,7 @@ multiclass FLAT_Global_Load_AddTid_Pseudo<string opName, RegisterClass regClass, } multiclass FLAT_Global_Store_Pseudo<string opName, RegisterClass regClass> { - let is_flat_global = 1, SubtargetPredicate = HasFlatGlobalInsts in { + let is_flat_global = 1 in { def "" : FLAT_Store_Pseudo<opName, regClass, 1>, GlobalSaddrTable<0, opName>; def _SADDR : FLAT_Store_Pseudo<opName, regClass, 1, 1>, @@ -390,6 +389,7 @@ class FLAT_Scratch_Load_Pseudo <string opName, RegisterClass regClass, !if(HasTiedOutput, (ins CPol:$cpol, getLdStRegisterOperand<regClass>.ret:$vdst_in), (ins CPol_0:$cpol))), " $vdst, "#!if(EnableVaddr, "$vaddr, ", "off, ")#!if(EnableSaddr, "$saddr", "off")#"$offset$cpol"> { + let is_flat_scratch = 1; let has_data = 0; let mayLoad = 1; let has_saddr = 1; @@ -417,6 +417,7 @@ class FLAT_Scratch_Store_Pseudo <string opName, RegisterClass vdataClass, bit En (ins vdata_op:$vdata, VGPR_32:$vaddr, flat_offset:$offset, CPol_0:$cpol), (ins vdata_op:$vdata, flat_offset:$offset, CPol_0:$cpol)))), " "#!if(EnableVaddr, "$vaddr", "off")#", $vdata, "#!if(EnableSaddr, "$saddr", "off")#"$offset$cpol"> { + let is_flat_scratch = 1; let mayLoad = 0; let mayStore = 1; let has_vdst = 0; @@ -429,37 +430,33 @@ class FLAT_Scratch_Store_Pseudo <string opName, RegisterClass vdataClass, bit En } multiclass FLAT_Scratch_Load_Pseudo<string opName, RegisterClass regClass, bit HasTiedOutput = 0> { - let is_flat_scratch = 1 in { - def "" : FLAT_Scratch_Load_Pseudo<opName, regClass, HasTiedOutput>, - FlatScratchInst<opName, "SV">; - def _SADDR : FLAT_Scratch_Load_Pseudo<opName, regClass, HasTiedOutput, 1>, - FlatScratchInst<opName, "SS">; - - let SubtargetPredicate = HasFlatScratchSVSMode in - def _SVS : FLAT_Scratch_Load_Pseudo<opName, regClass, HasTiedOutput, 1, 1>, - FlatScratchInst<opName, "SVS">; + def "" : FLAT_Scratch_Load_Pseudo<opName, regClass, HasTiedOutput>, + FlatScratchInst<opName, "SV">; + def _SADDR : FLAT_Scratch_Load_Pseudo<opName, regClass, HasTiedOutput, 1>, + FlatScratchInst<opName, "SS">; - let SubtargetPredicate = HasFlatScratchSTMode in - def _ST : FLAT_Scratch_Load_Pseudo<opName, regClass, HasTiedOutput, 0, 0, 0>, - FlatScratchInst<opName, "ST">; - } + let SubtargetPredicate = HasFlatScratchSVSMode in + def _SVS : FLAT_Scratch_Load_Pseudo<opName, regClass, HasTiedOutput, 1, 1>, + FlatScratchInst<opName, "SVS">; + + let SubtargetPredicate = HasFlatScratchSTMode in + def _ST : FLAT_Scratch_Load_Pseudo<opName, regClass, HasTiedOutput, 0, 0, 0>, + FlatScratchInst<opName, "ST">; } multiclass FLAT_Scratch_Store_Pseudo<string opName, RegisterClass regClass> { - let is_flat_scratch = 1 in { - def "" : FLAT_Scratch_Store_Pseudo<opName, regClass>, - FlatScratchInst<opName, "SV">; - def _SADDR : FLAT_Scratch_Store_Pseudo<opName, regClass, 1>, - FlatScratchInst<opName, "SS">; - - let SubtargetPredicate = HasFlatScratchSVSMode in - def _SVS : FLAT_Scratch_Store_Pseudo<opName, regClass, 1, 1>, - FlatScratchInst<opName, "SVS">; + def "" : FLAT_Scratch_Store_Pseudo<opName, regClass>, + FlatScratchInst<opName, "SV">; + def _SADDR : FLAT_Scratch_Store_Pseudo<opName, regClass, 1>, + FlatScratchInst<opName, "SS">; - let SubtargetPredicate = HasFlatScratchSTMode in - def _ST : FLAT_Scratch_Store_Pseudo<opName, regClass, 0, 0, 0>, - FlatScratchInst<opName, "ST">; - } + let SubtargetPredicate = HasFlatScratchSVSMode in + def _SVS : FLAT_Scratch_Store_Pseudo<opName, regClass, 1, 1>, + FlatScratchInst<opName, "SVS">; + + let SubtargetPredicate = HasFlatScratchSTMode in + def _ST : FLAT_Scratch_Store_Pseudo<opName, regClass, 0, 0, 0>, + FlatScratchInst<opName, "ST">; } class FLAT_Scratch_Load_LDS_Pseudo <string opName, bit EnableSaddr = 0, @@ -584,25 +581,27 @@ multiclass FLAT_Global_Atomic_Pseudo_NO_RTN< RegisterClass data_rc = vdst_rc, RegisterOperand data_op = getLdStRegisterOperand<data_rc>.ret> { - def "" : FLAT_AtomicNoRet_Pseudo <opName, - (outs), - (ins VReg_64:$vaddr, data_op:$vdata, flat_offset:$offset, CPol_0:$cpol), - " $vaddr, $vdata, off$offset$cpol">, - GlobalSaddrTable<0, opName> { - let has_saddr = 1; - let PseudoInstr = NAME; - let FPAtomic = data_vt.isFP; - } + let is_flat_global = 1 in { + def "" : FLAT_AtomicNoRet_Pseudo <opName, + (outs), + (ins VReg_64:$vaddr, data_op:$vdata, flat_offset:$offset, CPol_0:$cpol), + " $vaddr, $vdata, off$offset$cpol">, + GlobalSaddrTable<0, opName> { + let has_saddr = 1; + let PseudoInstr = NAME; + let FPAtomic = data_vt.isFP; + } - def _SADDR : FLAT_AtomicNoRet_Pseudo <opName, - (outs), - (ins VGPR_32:$vaddr, data_op:$vdata, SReg_64:$saddr, flat_offset:$offset, CPol_0:$cpol), - " $vaddr, $vdata, $saddr$offset$cpol">, - GlobalSaddrTable<1, opName> { - let has_saddr = 1; - let enabled_saddr = 1; - let PseudoInstr = NAME#"_SADDR"; - let FPAtomic = data_vt.isFP; + def _SADDR : FLAT_AtomicNoRet_Pseudo <opName, + (outs), + (ins VGPR_32:$vaddr, data_op:$vdata, SReg_64:$saddr, flat_offset:$offset, CPol_0:$cpol), + " $vaddr, $vdata, $saddr$offset$cpol">, + GlobalSaddrTable<1, opName> { + let has_saddr = 1; + let enabled_saddr = 1; + let PseudoInstr = NAME#"_SADDR"; + let FPAtomic = data_vt.isFP; + } } } @@ -615,24 +614,26 @@ multiclass FLAT_Global_Atomic_Pseudo_RTN< RegisterOperand data_op = getLdStRegisterOperand<data_rc>.ret, RegisterOperand vdst_op = getLdStRegisterOperand<vdst_rc>.ret> { - def _RTN : FLAT_AtomicRet_Pseudo <opName, - (outs vdst_op:$vdst), - (ins VReg_64:$vaddr, data_op:$vdata, flat_offset:$offset, CPol_GLC1:$cpol), - " $vdst, $vaddr, $vdata, off$offset$cpol">, - GlobalSaddrTable<0, opName#"_rtn"> { - let has_saddr = 1; - let FPAtomic = data_vt.isFP; - } + let is_flat_global = 1 in { + def _RTN : FLAT_AtomicRet_Pseudo <opName, + (outs vdst_op:$vdst), + (ins VReg_64:$vaddr, data_op:$vdata, flat_offset:$offset, CPol_GLC1:$cpol), + " $vdst, $vaddr, $vdata, off$offset$cpol">, + GlobalSaddrTable<0, opName#"_rtn"> { + let has_saddr = 1; + let FPAtomic = data_vt.isFP; + } - def _SADDR_RTN : FLAT_AtomicRet_Pseudo <opName, - (outs vdst_op:$vdst), - (ins VGPR_32:$vaddr, data_op:$vdata, SReg_64:$saddr, flat_offset:$offset, CPol_GLC1:$cpol), - " $vdst, $vaddr, $vdata, $saddr$offset$cpol">, - GlobalSaddrTable<1, opName#"_rtn"> { - let has_saddr = 1; - let enabled_saddr = 1; - let PseudoInstr = NAME#"_SADDR_RTN"; - let FPAtomic = data_vt.isFP; + def _SADDR_RTN : FLAT_AtomicRet_Pseudo <opName, + (outs vdst_op:$vdst), + (ins VGPR_32:$vaddr, data_op:$vdata, SReg_64:$saddr, flat_offset:$offset, CPol_GLC1:$cpol), + " $vdst, $vaddr, $vdata, $saddr$offset$cpol">, + GlobalSaddrTable<1, opName#"_rtn"> { + let has_saddr = 1; + let enabled_saddr = 1; + let PseudoInstr = NAME#"_SADDR_RTN"; + let FPAtomic = data_vt.isFP; + } } } @@ -642,10 +643,8 @@ multiclass FLAT_Global_Atomic_Pseudo< ValueType vt, ValueType data_vt = vt, RegisterClass data_rc = vdst_rc> { - let is_flat_global = 1, SubtargetPredicate = HasFlatGlobalInsts in { - defm "" : FLAT_Global_Atomic_Pseudo_NO_RTN<opName, vdst_rc, vt, data_vt, data_rc>; - defm "" : FLAT_Global_Atomic_Pseudo_RTN<opName, vdst_rc, vt, data_vt, data_rc>; - } + defm "" : FLAT_Global_Atomic_Pseudo_NO_RTN<opName, vdst_rc, vt, data_vt, data_rc>; + defm "" : FLAT_Global_Atomic_Pseudo_RTN<opName, vdst_rc, vt, data_vt, data_rc>; } //===----------------------------------------------------------------------===// @@ -849,7 +848,6 @@ defm GLOBAL_STORE_DWORD_ADDTID : FLAT_Global_Store_AddTid_Pseudo <"global_store_ defm GLOBAL_STORE_BYTE_D16_HI : FLAT_Global_Store_Pseudo <"global_store_byte_d16_hi", VGPR_32>; defm GLOBAL_STORE_SHORT_D16_HI : FLAT_Global_Store_Pseudo <"global_store_short_d16_hi", VGPR_32>; -let is_flat_global = 1 in { defm GLOBAL_ATOMIC_CMPSWAP : FLAT_Global_Atomic_Pseudo <"global_atomic_cmpswap", VGPR_32, i32, v2i32, VReg_64>; @@ -948,9 +946,6 @@ let SubtargetPredicate = isGFX12Plus in { def GLOBAL_WBINV : FLAT_Global_Invalidate_Writeback<"global_wbinv">; } // End SubtargetPredicate = isGFX12Plus -} // End is_flat_global = 1 - -let SubtargetPredicate = HasFlatScratchInsts in { defm SCRATCH_LOAD_UBYTE : FLAT_Scratch_Load_Pseudo <"scratch_load_ubyte", VGPR_32>; defm SCRATCH_LOAD_SBYTE : FLAT_Scratch_Load_Pseudo <"scratch_load_sbyte", VGPR_32>; defm SCRATCH_LOAD_USHORT : FLAT_Scratch_Load_Pseudo <"scratch_load_ushort", VGPR_32>; @@ -985,20 +980,22 @@ defm SCRATCH_LOAD_LDS_USHORT : FLAT_Scratch_Load_LDS_Pseudo <"scratch_load_lds_u defm SCRATCH_LOAD_LDS_SSHORT : FLAT_Scratch_Load_LDS_Pseudo <"scratch_load_lds_sshort">; defm SCRATCH_LOAD_LDS_DWORD : FLAT_Scratch_Load_LDS_Pseudo <"scratch_load_lds_dword">; -} // End SubtargetPredicate = HasFlatScratchInsts - let SubtargetPredicate = isGFX12Plus in { let WaveSizePredicate = isWave32 in { + let Mnemonic = "global_load_tr_b128" in defm GLOBAL_LOAD_TR_B128_w32 : FLAT_Global_Load_Pseudo <"global_load_tr_b128_w32", VReg_128>; + let Mnemonic = "global_load_tr_b64" in defm GLOBAL_LOAD_TR_B64_w32 : FLAT_Global_Load_Pseudo <"global_load_tr_b64_w32", VReg_64>; } let WaveSizePredicate = isWave64 in { + let Mnemonic = "global_load_tr_b128" in defm GLOBAL_LOAD_TR_B128_w64 : FLAT_Global_Load_Pseudo <"global_load_tr_b128_w64", VReg_64>; + let Mnemonic = "global_load_tr_b64" in defm GLOBAL_LOAD_TR_B64_w64 : FLAT_Global_Load_Pseudo <"global_load_tr_b64_w64", VGPR_32>; } } // End SubtargetPredicate = isGFX12Plus -let SubtargetPredicate = isGFX10Plus, is_flat_global = 1 in { +let SubtargetPredicate = isGFX10Plus in { defm GLOBAL_ATOMIC_FCMPSWAP : FLAT_Global_Atomic_Pseudo<"global_atomic_fcmpswap", VGPR_32, f32, v2f32, VReg_64>; defm GLOBAL_ATOMIC_FMIN : @@ -1011,9 +1008,8 @@ let SubtargetPredicate = isGFX10Plus, is_flat_global = 1 in { FLAT_Global_Atomic_Pseudo<"global_atomic_fmin_x2", VReg_64, f64>; defm GLOBAL_ATOMIC_FMAX_X2 : FLAT_Global_Atomic_Pseudo<"global_atomic_fmax_x2", VReg_64, f64>; -} // End SubtargetPredicate = isGFX10Plus, is_flat_global = 1 +} // End SubtargetPredicate = isGFX10Plus -let is_flat_global = 1 in { let OtherPredicates = [HasAtomicFaddNoRtnInsts] in defm GLOBAL_ATOMIC_ADD_F32 : FLAT_Global_Atomic_Pseudo_NO_RTN < "global_atomic_add_f32", VGPR_32, f32 @@ -1030,7 +1026,6 @@ let OtherPredicates = [HasAtomicBufferGlobalPkAddF16Insts] in defm GLOBAL_ATOMIC_PK_ADD_F16 : FLAT_Global_Atomic_Pseudo_RTN < "global_atomic_pk_add_f16", VGPR_32, v2f16 >; -} // End is_flat_global = 1 //===----------------------------------------------------------------------===// // Flat Patterns @@ -1598,16 +1593,12 @@ let OtherPredicates = [isGFX12Plus] in { defm : GlobalFLATAtomicPatsRtn <"GLOBAL_ATOMIC_ORDERED_ADD_B64", "int_amdgcn_global_atomic_ordered_add_b64", i64, i64, /* isIntr */ 1>; let WaveSizePredicate = isWave32 in { - defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B64_w32, int_amdgcn_global_load_tr, v2i32>; - defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B128_w32, int_amdgcn_global_load_tr, v8i16>; - defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B128_w32, int_amdgcn_global_load_tr, v8f16>; - defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B128_w32, int_amdgcn_global_load_tr, v8bf16>; + defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B64_w32, int_amdgcn_global_load_tr_b64, v2i32>; + defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B128_w32, int_amdgcn_global_load_tr_b128, v8i16>; } let WaveSizePredicate = isWave64 in { - defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B64_w64, int_amdgcn_global_load_tr, i32>; - defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B128_w64, int_amdgcn_global_load_tr, v4i16>; - defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B128_w64, int_amdgcn_global_load_tr, v4f16>; - defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B128_w64, int_amdgcn_global_load_tr, v4bf16>; + defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B64_w64, int_amdgcn_global_load_tr_b64, i32>; + defm : GlobalFLATLoadPats <GLOBAL_LOAD_TR_B128_w64, int_amdgcn_global_load_tr_b128, v4i16>; } } @@ -1787,45 +1778,46 @@ def FLAT_STORE_DWORDX2_ci : FLAT_Real_ci <0x1d, FLAT_STORE_DWORDX2>; def FLAT_STORE_DWORDX4_ci : FLAT_Real_ci <0x1e, FLAT_STORE_DWORDX4>; def FLAT_STORE_DWORDX3_ci : FLAT_Real_ci <0x1f, FLAT_STORE_DWORDX3>; -multiclass FLAT_Real_Atomics_ci <bits<7> op, FLAT_Pseudo ps> { +multiclass FLAT_Real_Atomics_ci <bits<7> op> { + defvar ps = !cast<FLAT_Pseudo>(NAME); def _ci : FLAT_Real_ci<op, !cast<FLAT_Pseudo>(ps.PseudoInstr)>; def _RTN_ci : FLAT_Real_ci<op, !cast<FLAT_Pseudo>(ps.PseudoInstr # "_RTN")>; } -defm FLAT_ATOMIC_SWAP : FLAT_Real_Atomics_ci <0x30, FLAT_ATOMIC_SWAP>; -defm FLAT_ATOMIC_CMPSWAP : FLAT_Real_Atomics_ci <0x31, FLAT_ATOMIC_CMPSWAP>; -defm FLAT_ATOMIC_ADD : FLAT_Real_Atomics_ci <0x32, FLAT_ATOMIC_ADD>; -defm FLAT_ATOMIC_SUB : FLAT_Real_Atomics_ci <0x33, FLAT_ATOMIC_SUB>; -defm FLAT_ATOMIC_SMIN : FLAT_Real_Atomics_ci <0x35, FLAT_ATOMIC_SMIN>; -defm FLAT_ATOMIC_UMIN : FLAT_Real_Atomics_ci <0x36, FLAT_ATOMIC_UMIN>; -defm FLAT_ATOMIC_SMAX : FLAT_Real_Atomics_ci <0x37, FLAT_ATOMIC_SMAX>; -defm FLAT_ATOMIC_UMAX : FLAT_Real_Atomics_ci <0x38, FLAT_ATOMIC_UMAX>; -defm FLAT_ATOMIC_AND : FLAT_Real_Atomics_ci <0x39, FLAT_ATOMIC_AND>; -defm FLAT_ATOMIC_OR : FLAT_Real_Atomics_ci <0x3a, FLAT_ATOMIC_OR>; -defm FLAT_ATOMIC_XOR : FLAT_Real_Atomics_ci <0x3b, FLAT_ATOMIC_XOR>; -defm FLAT_ATOMIC_INC : FLAT_Real_Atomics_ci <0x3c, FLAT_ATOMIC_INC>; -defm FLAT_ATOMIC_DEC : FLAT_Real_Atomics_ci <0x3d, FLAT_ATOMIC_DEC>; -defm FLAT_ATOMIC_SWAP_X2 : FLAT_Real_Atomics_ci <0x50, FLAT_ATOMIC_SWAP_X2>; -defm FLAT_ATOMIC_CMPSWAP_X2 : FLAT_Real_Atomics_ci <0x51, FLAT_ATOMIC_CMPSWAP_X2>; -defm FLAT_ATOMIC_ADD_X2 : FLAT_Real_Atomics_ci <0x52, FLAT_ATOMIC_ADD_X2>; -defm FLAT_ATOMIC_SUB_X2 : FLAT_Real_Atomics_ci <0x53, FLAT_ATOMIC_SUB_X2>; -defm FLAT_ATOMIC_SMIN_X2 : FLAT_Real_Atomics_ci <0x55, FLAT_ATOMIC_SMIN_X2>; -defm FLAT_ATOMIC_UMIN_X2 : FLAT_Real_Atomics_ci <0x56, FLAT_ATOMIC_UMIN_X2>; -defm FLAT_ATOMIC_SMAX_X2 : FLAT_Real_Atomics_ci <0x57, FLAT_ATOMIC_SMAX_X2>; -defm FLAT_ATOMIC_UMAX_X2 : FLAT_Real_Atomics_ci <0x58, FLAT_ATOMIC_UMAX_X2>; -defm FLAT_ATOMIC_AND_X2 : FLAT_Real_Atomics_ci <0x59, FLAT_ATOMIC_AND_X2>; -defm FLAT_ATOMIC_OR_X2 : FLAT_Real_Atomics_ci <0x5a, FLAT_ATOMIC_OR_X2>; -defm FLAT_ATOMIC_XOR_X2 : FLAT_Real_Atomics_ci <0x5b, FLAT_ATOMIC_XOR_X2>; -defm FLAT_ATOMIC_INC_X2 : FLAT_Real_Atomics_ci <0x5c, FLAT_ATOMIC_INC_X2>; -defm FLAT_ATOMIC_DEC_X2 : FLAT_Real_Atomics_ci <0x5d, FLAT_ATOMIC_DEC_X2>; +defm FLAT_ATOMIC_SWAP : FLAT_Real_Atomics_ci <0x30>; +defm FLAT_ATOMIC_CMPSWAP : FLAT_Real_Atomics_ci <0x31>; +defm FLAT_ATOMIC_ADD : FLAT_Real_Atomics_ci <0x32>; +defm FLAT_ATOMIC_SUB : FLAT_Real_Atomics_ci <0x33>; +defm FLAT_ATOMIC_SMIN : FLAT_Real_Atomics_ci <0x35>; +defm FLAT_ATOMIC_UMIN : FLAT_Real_Atomics_ci <0x36>; +defm FLAT_ATOMIC_SMAX : FLAT_Real_Atomics_ci <0x37>; +defm FLAT_ATOMIC_UMAX : FLAT_Real_Atomics_ci <0x38>; +defm FLAT_ATOMIC_AND : FLAT_Real_Atomics_ci <0x39>; +defm FLAT_ATOMIC_OR : FLAT_Real_Atomics_ci <0x3a>; +defm FLAT_ATOMIC_XOR : FLAT_Real_Atomics_ci <0x3b>; +defm FLAT_ATOMIC_INC : FLAT_Real_Atomics_ci <0x3c>; +defm FLAT_ATOMIC_DEC : FLAT_Real_Atomics_ci <0x3d>; +defm FLAT_ATOMIC_SWAP_X2 : FLAT_Real_Atomics_ci <0x50>; +defm FLAT_ATOMIC_CMPSWAP_X2 : FLAT_Real_Atomics_ci <0x51>; +defm FLAT_ATOMIC_ADD_X2 : FLAT_Real_Atomics_ci <0x52>; +defm FLAT_ATOMIC_SUB_X2 : FLAT_Real_Atomics_ci <0x53>; +defm FLAT_ATOMIC_SMIN_X2 : FLAT_Real_Atomics_ci <0x55>; +defm FLAT_ATOMIC_UMIN_X2 : FLAT_Real_Atomics_ci <0x56>; +defm FLAT_ATOMIC_SMAX_X2 : FLAT_Real_Atomics_ci <0x57>; +defm FLAT_ATOMIC_UMAX_X2 : FLAT_Real_Atomics_ci <0x58>; +defm FLAT_ATOMIC_AND_X2 : FLAT_Real_Atomics_ci <0x59>; +defm FLAT_ATOMIC_OR_X2 : FLAT_Real_Atomics_ci <0x5a>; +defm FLAT_ATOMIC_XOR_X2 : FLAT_Real_Atomics_ci <0x5b>; +defm FLAT_ATOMIC_INC_X2 : FLAT_Real_Atomics_ci <0x5c>; +defm FLAT_ATOMIC_DEC_X2 : FLAT_Real_Atomics_ci <0x5d>; // CI Only flat instructions -defm FLAT_ATOMIC_FCMPSWAP : FLAT_Real_Atomics_ci <0x3e, FLAT_ATOMIC_FCMPSWAP>; -defm FLAT_ATOMIC_FMIN : FLAT_Real_Atomics_ci <0x3f, FLAT_ATOMIC_FMIN>; -defm FLAT_ATOMIC_FMAX : FLAT_Real_Atomics_ci <0x40, FLAT_ATOMIC_FMAX>; -defm FLAT_ATOMIC_FCMPSWAP_X2 : FLAT_Real_Atomics_ci <0x5e, FLAT_ATOMIC_FCMPSWAP_X2>; -defm FLAT_ATOMIC_FMIN_X2 : FLAT_Real_Atomics_ci <0x5f, FLAT_ATOMIC_FMIN_X2>; -defm FLAT_ATOMIC_FMAX_X2 : FLAT_Real_Atomics_ci <0x60, FLAT_ATOMIC_FMAX_X2>; +defm FLAT_ATOMIC_FCMPSWAP : FLAT_Real_Atomics_ci <0x3e>; +defm FLAT_ATOMIC_FMIN : FLAT_Real_Atomics_ci <0x3f>; +defm FLAT_ATOMIC_FMAX : FLAT_Real_Atomics_ci <0x40>; +defm FLAT_ATOMIC_FCMPSWAP_X2 : FLAT_Real_Atomics_ci <0x5e>; +defm FLAT_ATOMIC_FMIN_X2 : FLAT_Real_Atomics_ci <0x5f>; +defm FLAT_ATOMIC_FMAX_X2 : FLAT_Real_Atomics_ci <0x60>; //===----------------------------------------------------------------------===// @@ -1925,8 +1917,9 @@ def FLAT_LOAD_SBYTE_D16_HI_vi : FLAT_Real_vi <0x23, FLAT_LOAD_SBYTE_D16_HI>; def FLAT_LOAD_SHORT_D16_vi : FLAT_Real_vi <0x24, FLAT_LOAD_SHORT_D16>; def FLAT_LOAD_SHORT_D16_HI_vi : FLAT_Real_vi <0x25, FLAT_LOAD_SHORT_D16_HI>; -multiclass FLAT_Real_Atomics_vi <bits<7> op, FLAT_Pseudo ps, +multiclass FLAT_Real_Atomics_vi <bits<7> op, bit has_sccb = !cast<FLAT_Pseudo>(NAME).has_sccb> { + defvar ps = !cast<FLAT_Pseudo>(NAME); def _vi : FLAT_Real_vi<op, !cast<FLAT_Pseudo>(ps.PseudoInstr), has_sccb>; def _RTN_vi : FLAT_Real_vi<op, !cast<FLAT_Pseudo>(ps.PseudoInstr # "_RTN"), has_sccb>; } @@ -1939,32 +1932,32 @@ multiclass FLAT_Global_Real_Atomics_vi<bits<7> op, } -defm FLAT_ATOMIC_SWAP : FLAT_Real_Atomics_vi <0x40, FLAT_ATOMIC_SWAP>; -defm FLAT_ATOMIC_CMPSWAP : FLAT_Real_Atomics_vi <0x41, FLAT_ATOMIC_CMPSWAP>; -defm FLAT_ATOMIC_ADD : FLAT_Real_Atomics_vi <0x42, FLAT_ATOMIC_ADD>; -defm FLAT_ATOMIC_SUB : FLAT_Real_Atomics_vi <0x43, FLAT_ATOMIC_SUB>; -defm FLAT_ATOMIC_SMIN : FLAT_Real_Atomics_vi <0x44, FLAT_ATOMIC_SMIN>; -defm FLAT_ATOMIC_UMIN : FLAT_Real_Atomics_vi <0x45, FLAT_ATOMIC_UMIN>; -defm FLAT_ATOMIC_SMAX : FLAT_Real_Atomics_vi <0x46, FLAT_ATOMIC_SMAX>; -defm FLAT_ATOMIC_UMAX : FLAT_Real_Atomics_vi <0x47, FLAT_ATOMIC_UMAX>; -defm FLAT_ATOMIC_AND : FLAT_Real_Atomics_vi <0x48, FLAT_ATOMIC_AND>; -defm FLAT_ATOMIC_OR : FLAT_Real_Atomics_vi <0x49, FLAT_ATOMIC_OR>; -defm FLAT_ATOMIC_XOR : FLAT_Real_Atomics_vi <0x4a, FLAT_ATOMIC_XOR>; -defm FLAT_ATOMIC_INC : FLAT_Real_Atomics_vi <0x4b, FLAT_ATOMIC_INC>; -defm FLAT_ATOMIC_DEC : FLAT_Real_Atomics_vi <0x4c, FLAT_ATOMIC_DEC>; -defm FLAT_ATOMIC_SWAP_X2 : FLAT_Real_Atomics_vi <0x60, FLAT_ATOMIC_SWAP_X2>; -defm FLAT_ATOMIC_CMPSWAP_X2 : FLAT_Real_Atomics_vi <0x61, FLAT_ATOMIC_CMPSWAP_X2>; -defm FLAT_ATOMIC_ADD_X2 : FLAT_Real_Atomics_vi <0x62, FLAT_ATOMIC_ADD_X2>; -defm FLAT_ATOMIC_SUB_X2 : FLAT_Real_Atomics_vi <0x63, FLAT_ATOMIC_SUB_X2>; -defm FLAT_ATOMIC_SMIN_X2 : FLAT_Real_Atomics_vi <0x64, FLAT_ATOMIC_SMIN_X2>; -defm FLAT_ATOMIC_UMIN_X2 : FLAT_Real_Atomics_vi <0x65, FLAT_ATOMIC_UMIN_X2>; -defm FLAT_ATOMIC_SMAX_X2 : FLAT_Real_Atomics_vi <0x66, FLAT_ATOMIC_SMAX_X2>; -defm FLAT_ATOMIC_UMAX_X2 : FLAT_Real_Atomics_vi <0x67, FLAT_ATOMIC_UMAX_X2>; -defm FLAT_ATOMIC_AND_X2 : FLAT_Real_Atomics_vi <0x68, FLAT_ATOMIC_AND_X2>; -defm FLAT_ATOMIC_OR_X2 : FLAT_Real_Atomics_vi <0x69, FLAT_ATOMIC_OR_X2>; -defm FLAT_ATOMIC_XOR_X2 : FLAT_Real_Atomics_vi <0x6a, FLAT_ATOMIC_XOR_X2>; -defm FLAT_ATOMIC_INC_X2 : FLAT_Real_Atomics_vi <0x6b, FLAT_ATOMIC_INC_X2>; -defm FLAT_ATOMIC_DEC_X2 : FLAT_Real_Atomics_vi <0x6c, FLAT_ATOMIC_DEC_X2>; +defm FLAT_ATOMIC_SWAP : FLAT_Real_Atomics_vi <0x40>; +defm FLAT_ATOMIC_CMPSWAP : FLAT_Real_Atomics_vi <0x41>; +defm FLAT_ATOMIC_ADD : FLAT_Real_Atomics_vi <0x42>; +defm FLAT_ATOMIC_SUB : FLAT_Real_Atomics_vi <0x43>; +defm FLAT_ATOMIC_SMIN : FLAT_Real_Atomics_vi <0x44>; +defm FLAT_ATOMIC_UMIN : FLAT_Real_Atomics_vi <0x45>; +defm FLAT_ATOMIC_SMAX : FLAT_Real_Atomics_vi <0x46>; +defm FLAT_ATOMIC_UMAX : FLAT_Real_Atomics_vi <0x47>; +defm FLAT_ATOMIC_AND : FLAT_Real_Atomics_vi <0x48>; +defm FLAT_ATOMIC_OR : FLAT_Real_Atomics_vi <0x49>; +defm FLAT_ATOMIC_XOR : FLAT_Real_Atomics_vi <0x4a>; +defm FLAT_ATOMIC_INC : FLAT_Real_Atomics_vi <0x4b>; +defm FLAT_ATOMIC_DEC : FLAT_Real_Atomics_vi <0x4c>; +defm FLAT_ATOMIC_SWAP_X2 : FLAT_Real_Atomics_vi <0x60>; +defm FLAT_ATOMIC_CMPSWAP_X2 : FLAT_Real_Atomics_vi <0x61>; +defm FLAT_ATOMIC_ADD_X2 : FLAT_Real_Atomics_vi <0x62>; +defm FLAT_ATOMIC_SUB_X2 : FLAT_Real_Atomics_vi <0x63>; +defm FLAT_ATOMIC_SMIN_X2 : FLAT_Real_Atomics_vi <0x64>; +defm FLAT_ATOMIC_UMIN_X2 : FLAT_Real_Atomics_vi <0x65>; +defm FLAT_ATOMIC_SMAX_X2 : FLAT_Real_Atomics_vi <0x66>; +defm FLAT_ATOMIC_UMAX_X2 : FLAT_Real_Atomics_vi <0x67>; +defm FLAT_ATOMIC_AND_X2 : FLAT_Real_Atomics_vi <0x68>; +defm FLAT_ATOMIC_OR_X2 : FLAT_Real_Atomics_vi <0x69>; +defm FLAT_ATOMIC_XOR_X2 : FLAT_Real_Atomics_vi <0x6a>; +defm FLAT_ATOMIC_INC_X2 : FLAT_Real_Atomics_vi <0x6b>; +defm FLAT_ATOMIC_DEC_X2 : FLAT_Real_Atomics_vi <0x6c>; defm GLOBAL_LOAD_UBYTE : FLAT_Real_AllAddr_vi <0x10>; defm GLOBAL_LOAD_SBYTE : FLAT_Real_AllAddr_vi <0x11>; @@ -2060,9 +2053,9 @@ let SubtargetPredicate = isGFX8GFX9NotGFX940 in { } let SubtargetPredicate = isGFX90AOnly in { - defm FLAT_ATOMIC_ADD_F64 : FLAT_Real_Atomics_vi<0x4f, FLAT_ATOMIC_ADD_F64, 0>; - defm FLAT_ATOMIC_MIN_F64 : FLAT_Real_Atomics_vi<0x50, FLAT_ATOMIC_MIN_F64, 0>; - defm FLAT_ATOMIC_MAX_F64 : FLAT_Real_Atomics_vi<0x51, FLAT_ATOMIC_MAX_F64, 0>; + defm FLAT_ATOMIC_ADD_F64 : FLAT_Real_Atomics_vi<0x4f, 0>; + defm FLAT_ATOMIC_MIN_F64 : FLAT_Real_Atomics_vi<0x50, 0>; + defm FLAT_ATOMIC_MAX_F64 : FLAT_Real_Atomics_vi<0x51, 0>; defm GLOBAL_ATOMIC_ADD_F64 : FLAT_Global_Real_Atomics_vi<0x4f, 0>; defm GLOBAL_ATOMIC_MIN_F64 : FLAT_Global_Real_Atomics_vi<0x50, 0>; defm GLOBAL_ATOMIC_MAX_F64 : FLAT_Global_Real_Atomics_vi<0x51, 0>; @@ -2073,7 +2066,8 @@ multiclass FLAT_Real_AllAddr_gfx940<bits<7> op> { def _SADDR_gfx940 : FLAT_Real_gfx940<op, !cast<FLAT_Pseudo>(NAME#"_SADDR")>; } -multiclass FLAT_Real_Atomics_gfx940 <bits<7> op, FLAT_Pseudo ps> { +multiclass FLAT_Real_Atomics_gfx940 <bits<7> op> { + defvar ps = !cast<FLAT_Pseudo>(NAME); def _gfx940 : FLAT_Real_gfx940<op, !cast<FLAT_Pseudo>(ps.PseudoInstr)>; def _RTN_gfx940 : FLAT_Real_gfx940<op, !cast<FLAT_Pseudo>(ps.PseudoInstr # "_RTN")>; } @@ -2089,15 +2083,15 @@ let SubtargetPredicate = isGFX940Plus in { defm GLOBAL_ATOMIC_ADD_F32 : FLAT_Global_Real_Atomics_gfx940 <0x04d>; defm GLOBAL_ATOMIC_PK_ADD_F16 : FLAT_Global_Real_Atomics_gfx940 <0x04e>; - defm FLAT_ATOMIC_ADD_F64 : FLAT_Real_Atomics_gfx940<0x4f, FLAT_ATOMIC_ADD_F64>; - defm FLAT_ATOMIC_MIN_F64 : FLAT_Real_Atomics_gfx940<0x50, FLAT_ATOMIC_MIN_F64>; - defm FLAT_ATOMIC_MAX_F64 : FLAT_Real_Atomics_gfx940<0x51, FLAT_ATOMIC_MAX_F64>; + defm FLAT_ATOMIC_ADD_F64 : FLAT_Real_Atomics_gfx940<0x4f>; + defm FLAT_ATOMIC_MIN_F64 : FLAT_Real_Atomics_gfx940<0x50>; + defm FLAT_ATOMIC_MAX_F64 : FLAT_Real_Atomics_gfx940<0x51>; defm GLOBAL_ATOMIC_ADD_F64 : FLAT_Global_Real_Atomics_gfx940<0x4f>; defm GLOBAL_ATOMIC_MIN_F64 : FLAT_Global_Real_Atomics_gfx940<0x50>; defm GLOBAL_ATOMIC_MAX_F64 : FLAT_Global_Real_Atomics_gfx940<0x51>; - defm FLAT_ATOMIC_ADD_F32 : FLAT_Real_Atomics_vi<0x4d, FLAT_ATOMIC_ADD_F32>; - defm FLAT_ATOMIC_PK_ADD_F16 : FLAT_Real_Atomics_vi<0x4e, FLAT_ATOMIC_PK_ADD_F16>; - defm FLAT_ATOMIC_PK_ADD_BF16 : FLAT_Real_Atomics_vi<0x52, FLAT_ATOMIC_PK_ADD_BF16>; + defm FLAT_ATOMIC_ADD_F32 : FLAT_Real_Atomics_vi<0x4d>; + defm FLAT_ATOMIC_PK_ADD_F16 : FLAT_Real_Atomics_vi<0x4e>; + defm FLAT_ATOMIC_PK_ADD_BF16 : FLAT_Real_Atomics_vi<0x52>; defm GLOBAL_ATOMIC_PK_ADD_BF16 : FLAT_Global_Real_Atomics_vi<0x52>; } // End SubtargetPredicate = isGFX940Plus @@ -2112,7 +2106,9 @@ class FLAT_Real_gfx10<bits<7> op, FLAT_Pseudo ps> : let Inst{11-0} = offset{11-0}; let Inst{12} = !if(ps.has_dlc, cpol{CPolBit.DLC}, ps.dlcValue); - let Inst{54-48} = !if(ps.has_saddr, !if(ps.enabled_saddr, saddr, 0x7d), 0x7d); + let Inst{54-48} = !cond(ps.enabled_saddr : saddr, + !and(ps.is_flat_scratch, !not(ps.has_vaddr)) : EXEC_HI.Index{6-0}, // ST mode + true : SGPR_NULL_gfxpre11.Index{6-0}); let Inst{55} = 0; } @@ -2139,10 +2135,7 @@ multiclass FLAT_Real_SADDR_RTN_gfx10<bits<7> op> { multiclass FLAT_Real_ST_gfx10<bits<7> op> { def _ST_gfx10 : - FLAT_Real_gfx10<op, !cast<FLAT_Pseudo>(NAME#"_ST")> { - let Inst{54-48} = EXEC_HI.Index; - let OtherPredicates = [HasFlatScratchSTMode]; - } + FLAT_Real_gfx10<op, !cast<FLAT_Pseudo>(NAME#"_ST")>; } multiclass FLAT_Real_AllAddr_gfx10<bits<7> op> : @@ -2340,421 +2333,388 @@ defm SCRATCH_LOAD_LDS_DWORD : FLAT_Real_ScratchAllAddr_LDS_gfx10 <0x00c>; // GFX11 //===----------------------------------------------------------------------===// -class FLAT_Real_gfx11 <bits<7> op, FLAT_Pseudo ps, string opName = ps.Mnemonic> : - FLAT_Real <op, ps, opName>, - SIMCInstr <ps.PseudoInstr, SIEncodingFamily.GFX11> { - let AssemblerPredicate = isGFX11Only; - let DecoderNamespace = "GFX11"; - - let Inst{13} = !if(ps.has_dlc, cpol{CPolBit.DLC}, ps.dlcValue); - let Inst{14} = !if(ps.has_glc, cpol{CPolBit.GLC}, ps.glcValue); - let Inst{15} = cpol{CPolBit.SLC}; - let Inst{17-16} = seg; - let Inst{55} = ps.sve; +class get_FLAT_ps<string name> { + string Mnemonic = !cast<FLAT_Pseudo>(name).Mnemonic; } -multiclass FLAT_Aliases_gfx11<string ps, string opName, int renamed> { - if renamed then - def _renamed_gfx11 : MnemonicAlias<!cast<FLAT_Pseudo>(ps).Mnemonic, opName>, Requires<[isGFX11Only]>; -} +multiclass FLAT_Real_gfx11 <bits<7> op, + string name = get_FLAT_ps<NAME>.Mnemonic> { + defvar ps = !cast<FLAT_Pseudo>(NAME); + def _gfx11 : FLAT_Real <op, ps, name>, + SIMCInstr <ps.PseudoInstr, SIEncodingFamily.GFX11> { + let AssemblerPredicate = isGFX11Only; + let DecoderNamespace = "GFX11"; -multiclass FLAT_Real_Base_gfx11<bits<7> op, string ps, string opName, int renamed = false> : - FLAT_Aliases_gfx11<ps, opName, renamed> { - def _gfx11 : FLAT_Real_gfx11<op, !cast<FLAT_Pseudo>(ps), opName> { - let Inst{54-48} = SGPR_NULL_gfx11plus.Index; + let Inst{13} = !if(ps.has_dlc, cpol{CPolBit.DLC}, ps.dlcValue); + let Inst{14} = !if(ps.has_glc, cpol{CPolBit.GLC}, ps.glcValue); + let Inst{15} = cpol{CPolBit.SLC}; + let Inst{17-16} = seg; + let Inst{54-48} = !if(ps.enabled_saddr, saddr, SGPR_NULL_gfx11plus.Index); + let Inst{55} = ps.sve; } } -multiclass FLAT_Real_RTN_gfx11<bits<7> op, string ps, string opName> { - def _RTN_gfx11 : FLAT_Real_gfx11<op, !cast<FLAT_Pseudo>(ps#"_RTN"), opName> { - let Inst{54-48} = SGPR_NULL_gfx11plus.Index; - } +multiclass FLAT_Aliases_gfx11<string name> { + defvar ps = get_FLAT_ps<NAME>; + if !ne(ps.Mnemonic, name) then + def : MnemonicAlias<ps.Mnemonic, name>, Requires<[isGFX11Only]>; } -multiclass FLAT_Real_SADDR_gfx11<bits<7> op, string ps, string opName> { - def _SADDR_gfx11 : FLAT_Real_gfx11<op, !cast<FLAT_Pseudo>(ps#"_SADDR"), opName>; -} +multiclass FLAT_Real_Base_gfx11<bits<7> op, + string name = get_FLAT_ps<NAME>.Mnemonic> : + FLAT_Aliases_gfx11<name>, + FLAT_Real_gfx11<op, name>; -multiclass FLAT_Real_SADDR_RTN_gfx11<bits<7> op, string ps, string opName> { - def _SADDR_RTN_gfx11 : FLAT_Real_gfx11<op, !cast<FLAT_Pseudo>(ps#"_SADDR_RTN"), opName>; +multiclass FLAT_Real_Atomics_gfx11<bits<7> op, + string name = get_FLAT_ps<NAME>.Mnemonic> : + FLAT_Real_Base_gfx11<op, name> { + defm _RTN : FLAT_Real_gfx11<op, name>; } -multiclass FLAT_Real_ST_gfx11<bits<7> op, string ps, string opName> { - def _ST_gfx11 : FLAT_Real_gfx11<op, !cast<FLAT_Pseudo>(ps#"_ST"), opName> { - let Inst{54-48} = SGPR_NULL_gfx11plus.Index; - let OtherPredicates = [HasFlatScratchSTMode]; - } +multiclass GLOBAL_Real_AllAddr_gfx11<bits<7> op, + string name = get_FLAT_ps<NAME>.Mnemonic> : + FLAT_Real_Base_gfx11<op, name> { + defm _SADDR : FLAT_Real_gfx11<op, name>; } -multiclass FLAT_Real_SVS_gfx11<bits<7> op, string ps, string opName> { - def _SVS_gfx11 : FLAT_Real_gfx11<op, !cast<FLAT_Pseudo>(ps#"_SVS"), opName> { - let OtherPredicates = [HasFlatScratchSVSMode]; - } +multiclass GLOBAL_Real_Atomics_gfx11<bits<7> op, + string name = get_FLAT_ps<NAME>.Mnemonic> : + GLOBAL_Real_AllAddr_gfx11<op, name> { + defm _RTN : FLAT_Real_gfx11<op, name>; + defm _SADDR_RTN : FLAT_Real_gfx11<op, name>; } -multiclass FLAT_Real_AllAddr_gfx11<bits<7> op, string ps, string opName, int renamed = false> : - FLAT_Real_Base_gfx11<op, ps, opName, renamed>, - FLAT_Real_SADDR_gfx11<op, ps, opName>; - -multiclass FLAT_Real_Atomics_gfx11<bits<7> op, string ps, string opName, int renamed = false> : - FLAT_Real_Base_gfx11<op, ps, opName, renamed>, - FLAT_Real_RTN_gfx11<op, ps, opName>; - -multiclass FLAT_Real_GlblAtomics_gfx11<bits<7> op, string ps, string opName, int renamed = false> : - FLAT_Real_AllAddr_gfx11<op, ps, opName, renamed>, - FLAT_Real_RTN_gfx11<op, ps, opName>, - FLAT_Real_SADDR_RTN_gfx11<op, ps, opName>; - -multiclass FLAT_Real_GlblAtomics_RTN_gfx11<bits<7> op, string ps, string opName, int renamed = false> : - FLAT_Aliases_gfx11<ps#"_RTN", opName, renamed>, - FLAT_Real_RTN_gfx11<op, ps, opName>, - FLAT_Real_SADDR_RTN_gfx11<op, ps, opName>; - -multiclass FLAT_Real_ScratchAllAddr_gfx11<bits<7> op, string ps, string opName, int renamed = false> : - FLAT_Real_Base_gfx11<op, ps, opName, renamed>, - FLAT_Real_SADDR_gfx11<op, ps, opName>, - FLAT_Real_ST_gfx11<op, ps, opName>, - FLAT_Real_SVS_gfx11<op, ps, opName>; +multiclass SCRATCH_Real_AllAddr_gfx11<bits<7> op, + string name = get_FLAT_ps<NAME>.Mnemonic> : + FLAT_Real_Base_gfx11<op, name> { + defm _SADDR : FLAT_Real_gfx11<op, name>; + defm _ST : FLAT_Real_gfx11<op, name>; + defm _SVS : FLAT_Real_gfx11<op, name>; +} // ENC_FLAT. -defm FLAT_LOAD_U8 : FLAT_Real_Base_gfx11<0x010, "FLAT_LOAD_UBYTE", "flat_load_u8", true>; -defm FLAT_LOAD_I8 : FLAT_Real_Base_gfx11<0x011, "FLAT_LOAD_SBYTE", "flat_load_i8", true>; -defm FLAT_LOAD_U16 : FLAT_Real_Base_gfx11<0x012, "FLAT_LOAD_USHORT", "flat_load_u16", true>; -defm FLAT_LOAD_I16 : FLAT_Real_Base_gfx11<0x013, "FLAT_LOAD_SSHORT", "flat_load_i16", true>; -defm FLAT_LOAD_B32 : FLAT_Real_Base_gfx11<0x014, "FLAT_LOAD_DWORD", "flat_load_b32", true>; -defm FLAT_LOAD_B64 : FLAT_Real_Base_gfx11<0x015, "FLAT_LOAD_DWORDX2", "flat_load_b64", true>; -defm FLAT_LOAD_B96 : FLAT_Real_Base_gfx11<0x016, "FLAT_LOAD_DWORDX3", "flat_load_b96", true>; -defm FLAT_LOAD_B128 : FLAT_Real_Base_gfx11<0x017, "FLAT_LOAD_DWORDX4", "flat_load_b128", true>; -defm FLAT_STORE_B8 : FLAT_Real_Base_gfx11<0x018, "FLAT_STORE_BYTE", "flat_store_b8", true>; -defm FLAT_STORE_B16 : FLAT_Real_Base_gfx11<0x019, "FLAT_STORE_SHORT", "flat_store_b16", true>; -defm FLAT_STORE_B32 : FLAT_Real_Base_gfx11<0x01a, "FLAT_STORE_DWORD", "flat_store_b32", true>; -defm FLAT_STORE_B64 : FLAT_Real_Base_gfx11<0x01b, "FLAT_STORE_DWORDX2", "flat_store_b64", true>; -defm FLAT_STORE_B96 : FLAT_Real_Base_gfx11<0x01c, "FLAT_STORE_DWORDX3", "flat_store_b96", true>; -defm FLAT_STORE_B128 : FLAT_Real_Base_gfx11<0x01d, "FLAT_STORE_DWORDX4", "flat_store_b128", true>; -defm FLAT_LOAD_D16_U8 : FLAT_Real_Base_gfx11<0x01e, "FLAT_LOAD_UBYTE_D16", "flat_load_d16_u8">; -defm FLAT_LOAD_D16_I8 : FLAT_Real_Base_gfx11<0x01f, "FLAT_LOAD_SBYTE_D16", "flat_load_d16_i8">; -defm FLAT_LOAD_D16_B16 : FLAT_Real_Base_gfx11<0x020, "FLAT_LOAD_SHORT_D16", "flat_load_d16_b16">; -defm FLAT_LOAD_D16_HI_U8 : FLAT_Real_Base_gfx11<0x021, "FLAT_LOAD_UBYTE_D16_HI", "flat_load_d16_hi_u8">; -defm FLAT_LOAD_D16_HI_I8 : FLAT_Real_Base_gfx11<0x022, "FLAT_LOAD_SBYTE_D16_HI", "flat_load_d16_hi_i8">; -defm FLAT_LOAD_D16_HI_B16 : FLAT_Real_Base_gfx11<0x023, "FLAT_LOAD_SHORT_D16_HI", "flat_load_d16_hi_b16">; -defm FLAT_STORE_D16_HI_B8 : FLAT_Real_Base_gfx11<0x024, "FLAT_STORE_BYTE_D16_HI", "flat_store_d16_hi_b8">; -defm FLAT_STORE_D16_HI_B16 : FLAT_Real_Base_gfx11<0x025, "FLAT_STORE_SHORT_D16_HI", "flat_store_d16_hi_b16">; -defm FLAT_ATOMIC_SWAP_B32 : FLAT_Real_Atomics_gfx11<0x033, "FLAT_ATOMIC_SWAP", "flat_atomic_swap_b32", true>; -defm FLAT_ATOMIC_CMPSWAP_B32 : FLAT_Real_Atomics_gfx11<0x034, "FLAT_ATOMIC_CMPSWAP", "flat_atomic_cmpswap_b32", true>; -defm FLAT_ATOMIC_ADD_U32 : FLAT_Real_Atomics_gfx11<0x035, "FLAT_ATOMIC_ADD", "flat_atomic_add_u32", true>; -defm FLAT_ATOMIC_SUB_U32 : FLAT_Real_Atomics_gfx11<0x036, "FLAT_ATOMIC_SUB", "flat_atomic_sub_u32", true>; -defm FLAT_ATOMIC_MIN_I32 : FLAT_Real_Atomics_gfx11<0x038, "FLAT_ATOMIC_SMIN", "flat_atomic_min_i32", true>; -defm FLAT_ATOMIC_MIN_U32 : FLAT_Real_Atomics_gfx11<0x039, "FLAT_ATOMIC_UMIN", "flat_atomic_min_u32", true>; -defm FLAT_ATOMIC_MAX_I32 : FLAT_Real_Atomics_gfx11<0x03a, "FLAT_ATOMIC_SMAX", "flat_atomic_max_i32", true>; -defm FLAT_ATOMIC_MAX_U32 : FLAT_Real_Atomics_gfx11<0x03b, "FLAT_ATOMIC_UMAX", "flat_atomic_max_u32", true>; -defm FLAT_ATOMIC_AND_B32 : FLAT_Real_Atomics_gfx11<0x03c, "FLAT_ATOMIC_AND", "flat_atomic_and_b32", true>; -defm FLAT_ATOMIC_OR_B32 : FLAT_Real_Atomics_gfx11<0x03d, "FLAT_ATOMIC_OR", "flat_atomic_or_b32", true>; -defm FLAT_ATOMIC_XOR_B32 : FLAT_Real_Atomics_gfx11<0x03e, "FLAT_ATOMIC_XOR", "flat_atomic_xor_b32", true>; -defm FLAT_ATOMIC_INC_U32 : FLAT_Real_Atomics_gfx11<0x03f, "FLAT_ATOMIC_INC", "flat_atomic_inc_u32", true>; -defm FLAT_ATOMIC_DEC_U32 : FLAT_Real_Atomics_gfx11<0x040, "FLAT_ATOMIC_DEC", "flat_atomic_dec_u32", true>; -defm FLAT_ATOMIC_SWAP_B64 : FLAT_Real_Atomics_gfx11<0x041, "FLAT_ATOMIC_SWAP_X2", "flat_atomic_swap_b64", true>; -defm FLAT_ATOMIC_CMPSWAP_B64 : FLAT_Real_Atomics_gfx11<0x042, "FLAT_ATOMIC_CMPSWAP_X2", "flat_atomic_cmpswap_b64", true>; -defm FLAT_ATOMIC_ADD_U64 : FLAT_Real_Atomics_gfx11<0x043, "FLAT_ATOMIC_ADD_X2", "flat_atomic_add_u64", true>; -defm FLAT_ATOMIC_SUB_U64 : FLAT_Real_Atomics_gfx11<0x044, "FLAT_ATOMIC_SUB_X2", "flat_atomic_sub_u64", true>; -defm FLAT_ATOMIC_MIN_I64 : FLAT_Real_Atomics_gfx11<0x045, "FLAT_ATOMIC_SMIN_X2", "flat_atomic_min_i64", true>; -defm FLAT_ATOMIC_MIN_U64 : FLAT_Real_Atomics_gfx11<0x046, "FLAT_ATOMIC_UMIN_X2", "flat_atomic_min_u64", true>; -defm FLAT_ATOMIC_MAX_I64 : FLAT_Real_Atomics_gfx11<0x047, "FLAT_ATOMIC_SMAX_X2", "flat_atomic_max_i64", true>; -defm FLAT_ATOMIC_MAX_U64 : FLAT_Real_Atomics_gfx11<0x048, "FLAT_ATOMIC_UMAX_X2", "flat_atomic_max_u64", true>; -defm FLAT_ATOMIC_AND_B64 : FLAT_Real_Atomics_gfx11<0x049, "FLAT_ATOMIC_AND_X2", "flat_atomic_and_b64", true>; -defm FLAT_ATOMIC_OR_B64 : FLAT_Real_Atomics_gfx11<0x04a, "FLAT_ATOMIC_OR_X2", "flat_atomic_or_b64", true>; -defm FLAT_ATOMIC_XOR_B64 : FLAT_Real_Atomics_gfx11<0x04b, "FLAT_ATOMIC_XOR_X2", "flat_atomic_xor_b64", true>; -defm FLAT_ATOMIC_INC_U64 : FLAT_Real_Atomics_gfx11<0x04c, "FLAT_ATOMIC_INC_X2", "flat_atomic_inc_u64", true>; -defm FLAT_ATOMIC_DEC_U64 : FLAT_Real_Atomics_gfx11<0x04d, "FLAT_ATOMIC_DEC_X2", "flat_atomic_dec_u64", true>; -defm FLAT_ATOMIC_CMPSWAP_F32 : FLAT_Real_Atomics_gfx11<0x050, "FLAT_ATOMIC_FCMPSWAP", "flat_atomic_cmpswap_f32">; -defm FLAT_ATOMIC_MIN_F32 : FLAT_Real_Atomics_gfx11<0x051, "FLAT_ATOMIC_FMIN", "flat_atomic_min_f32">; -defm FLAT_ATOMIC_MAX_F32 : FLAT_Real_Atomics_gfx11<0x052, "FLAT_ATOMIC_FMAX", "flat_atomic_max_f32">; -defm FLAT_ATOMIC_ADD_F32 : FLAT_Real_Atomics_gfx11<0x056, "FLAT_ATOMIC_ADD_F32", "flat_atomic_add_f32">; +defm FLAT_LOAD_UBYTE : FLAT_Real_Base_gfx11<0x010, "flat_load_u8">; +defm FLAT_LOAD_SBYTE : FLAT_Real_Base_gfx11<0x011, "flat_load_i8">; +defm FLAT_LOAD_USHORT : FLAT_Real_Base_gfx11<0x012, "flat_load_u16">; +defm FLAT_LOAD_SSHORT : FLAT_Real_Base_gfx11<0x013, "flat_load_i16">; +defm FLAT_LOAD_DWORD : FLAT_Real_Base_gfx11<0x014, "flat_load_b32">; +defm FLAT_LOAD_DWORDX2 : FLAT_Real_Base_gfx11<0x015, "flat_load_b64">; +defm FLAT_LOAD_DWORDX3 : FLAT_Real_Base_gfx11<0x016, "flat_load_b96">; +defm FLAT_LOAD_DWORDX4 : FLAT_Real_Base_gfx11<0x017, "flat_load_b128">; +defm FLAT_STORE_BYTE : FLAT_Real_Base_gfx11<0x018, "flat_store_b8">; +defm FLAT_STORE_SHORT : FLAT_Real_Base_gfx11<0x019, "flat_store_b16">; +defm FLAT_STORE_DWORD : FLAT_Real_Base_gfx11<0x01a, "flat_store_b32">; +defm FLAT_STORE_DWORDX2 : FLAT_Real_Base_gfx11<0x01b, "flat_store_b64">; +defm FLAT_STORE_DWORDX3 : FLAT_Real_Base_gfx11<0x01c, "flat_store_b96">; +defm FLAT_STORE_DWORDX4 : FLAT_Real_Base_gfx11<0x01d, "flat_store_b128">; +defm FLAT_LOAD_UBYTE_D16 : FLAT_Real_Base_gfx11<0x01e, "flat_load_d16_u8">; +defm FLAT_LOAD_SBYTE_D16 : FLAT_Real_Base_gfx11<0x01f, "flat_load_d16_i8">; +defm FLAT_LOAD_SHORT_D16 : FLAT_Real_Base_gfx11<0x020, "flat_load_d16_b16">; +defm FLAT_LOAD_UBYTE_D16_HI : FLAT_Real_Base_gfx11<0x021, "flat_load_d16_hi_u8">; +defm FLAT_LOAD_SBYTE_D16_HI : FLAT_Real_Base_gfx11<0x022, "flat_load_d16_hi_i8">; +defm FLAT_LOAD_SHORT_D16_HI : FLAT_Real_Base_gfx11<0x023, "flat_load_d16_hi_b16">; +defm FLAT_STORE_BYTE_D16_HI : FLAT_Real_Base_gfx11<0x024, "flat_store_d16_hi_b8">; +defm FLAT_STORE_SHORT_D16_HI : FLAT_Real_Base_gfx11<0x025, "flat_store_d16_hi_b16">; +defm FLAT_ATOMIC_SWAP : FLAT_Real_Atomics_gfx11<0x033, "flat_atomic_swap_b32">; +defm FLAT_ATOMIC_CMPSWAP : FLAT_Real_Atomics_gfx11<0x034, "flat_atomic_cmpswap_b32">; +defm FLAT_ATOMIC_ADD : FLAT_Real_Atomics_gfx11<0x035, "flat_atomic_add_u32">; +defm FLAT_ATOMIC_SUB : FLAT_Real_Atomics_gfx11<0x036, "flat_atomic_sub_u32">; +defm FLAT_ATOMIC_SMIN : FLAT_Real_Atomics_gfx11<0x038, "flat_atomic_min_i32">; +defm FLAT_ATOMIC_UMIN : FLAT_Real_Atomics_gfx11<0x039, "flat_atomic_min_u32">; +defm FLAT_ATOMIC_SMAX : FLAT_Real_Atomics_gfx11<0x03a, "flat_atomic_max_i32">; +defm FLAT_ATOMIC_UMAX : FLAT_Real_Atomics_gfx11<0x03b, "flat_atomic_max_u32">; +defm FLAT_ATOMIC_AND : FLAT_Real_Atomics_gfx11<0x03c, "flat_atomic_and_b32">; +defm FLAT_ATOMIC_OR : FLAT_Real_Atomics_gfx11<0x03d, "flat_atomic_or_b32">; +defm FLAT_ATOMIC_XOR : FLAT_Real_Atomics_gfx11<0x03e, "flat_atomic_xor_b32">; +defm FLAT_ATOMIC_INC : FLAT_Real_Atomics_gfx11<0x03f, "flat_atomic_inc_u32">; +defm FLAT_ATOMIC_DEC : FLAT_Real_Atomics_gfx11<0x040, "flat_atomic_dec_u32">; +defm FLAT_ATOMIC_SWAP_X2 : FLAT_Real_Atomics_gfx11<0x041, "flat_atomic_swap_b64">; +defm FLAT_ATOMIC_CMPSWAP_X2 : FLAT_Real_Atomics_gfx11<0x042, "flat_atomic_cmpswap_b64">; +defm FLAT_ATOMIC_ADD_X2 : FLAT_Real_Atomics_gfx11<0x043, "flat_atomic_add_u64">; +defm FLAT_ATOMIC_SUB_X2 : FLAT_Real_Atomics_gfx11<0x044, "flat_atomic_sub_u64">; +defm FLAT_ATOMIC_SMIN_X2 : FLAT_Real_Atomics_gfx11<0x045, "flat_atomic_min_i64">; +defm FLAT_ATOMIC_UMIN_X2 : FLAT_Real_Atomics_gfx11<0x046, "flat_atomic_min_u64">; +defm FLAT_ATOMIC_SMAX_X2 : FLAT_Real_Atomics_gfx11<0x047, "flat_atomic_max_i64">; +defm FLAT_ATOMIC_UMAX_X2 : FLAT_Real_Atomics_gfx11<0x048, "flat_atomic_max_u64">; +defm FLAT_ATOMIC_AND_X2 : FLAT_Real_Atomics_gfx11<0x049, "flat_atomic_and_b64">; +defm FLAT_ATOMIC_OR_X2 : FLAT_Real_Atomics_gfx11<0x04a, "flat_atomic_or_b64">; +defm FLAT_ATOMIC_XOR_X2 : FLAT_Real_Atomics_gfx11<0x04b, "flat_atomic_xor_b64">; +defm FLAT_ATOMIC_INC_X2 : FLAT_Real_Atomics_gfx11<0x04c, "flat_atomic_inc_u64">; +defm FLAT_ATOMIC_DEC_X2 : FLAT_Real_Atomics_gfx11<0x04d, "flat_atomic_dec_u64">; +defm FLAT_ATOMIC_FCMPSWAP : FLAT_Real_Atomics_gfx11<0x050, "flat_atomic_cmpswap_f32">; +defm FLAT_ATOMIC_FMIN : FLAT_Real_Atomics_gfx11<0x051, "flat_atomic_min_f32">; +defm FLAT_ATOMIC_FMAX : FLAT_Real_Atomics_gfx11<0x052, "flat_atomic_max_f32">; +defm FLAT_ATOMIC_ADD_F32 : FLAT_Real_Atomics_gfx11<0x056>; // ENC_FLAT_GLBL. -defm GLOBAL_LOAD_U8 : FLAT_Real_AllAddr_gfx11<0x010, "GLOBAL_LOAD_UBYTE", "global_load_u8", true>; -defm GLOBAL_LOAD_I8 : FLAT_Real_AllAddr_gfx11<0x011, "GLOBAL_LOAD_SBYTE", "global_load_i8", true>; -defm GLOBAL_LOAD_U16 : FLAT_Real_AllAddr_gfx11<0x012, "GLOBAL_LOAD_USHORT", "global_load_u16", true>; -defm GLOBAL_LOAD_I16 : FLAT_Real_AllAddr_gfx11<0x013, "GLOBAL_LOAD_SSHORT", "global_load_i16", true>; -defm GLOBAL_LOAD_B32 : FLAT_Real_AllAddr_gfx11<0x014, "GLOBAL_LOAD_DWORD", "global_load_b32", true>; -defm GLOBAL_LOAD_B64 : FLAT_Real_AllAddr_gfx11<0x015, "GLOBAL_LOAD_DWORDX2", "global_load_b64", true>; -defm GLOBAL_LOAD_B96 : FLAT_Real_AllAddr_gfx11<0x016, "GLOBAL_LOAD_DWORDX3", "global_load_b96", true>; -defm GLOBAL_LOAD_B128 : FLAT_Real_AllAddr_gfx11<0x017, "GLOBAL_LOAD_DWORDX4", "global_load_b128", true>; -defm GLOBAL_STORE_B8 : FLAT_Real_AllAddr_gfx11<0x018, "GLOBAL_STORE_BYTE", "global_store_b8", true>; -defm GLOBAL_STORE_B16 : FLAT_Real_AllAddr_gfx11<0x019, "GLOBAL_STORE_SHORT", "global_store_b16", true>; -defm GLOBAL_STORE_B32 : FLAT_Real_AllAddr_gfx11<0x01a, "GLOBAL_STORE_DWORD", "global_store_b32", true>; -defm GLOBAL_STORE_B64 : FLAT_Real_AllAddr_gfx11<0x01b, "GLOBAL_STORE_DWORDX2", "global_store_b64", true>; -defm GLOBAL_STORE_B96 : FLAT_Real_AllAddr_gfx11<0x01c, "GLOBAL_STORE_DWORDX3", "global_store_b96", true>; -defm GLOBAL_STORE_B128 : FLAT_Real_AllAddr_gfx11<0x01d, "GLOBAL_STORE_DWORDX4", "global_store_b128", true>; -defm GLOBAL_LOAD_D16_U8 : FLAT_Real_AllAddr_gfx11<0x01e, "GLOBAL_LOAD_UBYTE_D16", "global_load_d16_u8">; -defm GLOBAL_LOAD_D16_I8 : FLAT_Real_AllAddr_gfx11<0x01f, "GLOBAL_LOAD_SBYTE_D16", "global_load_d16_i8">; -defm GLOBAL_LOAD_D16_B16 : FLAT_Real_AllAddr_gfx11<0x020, "GLOBAL_LOAD_SHORT_D16", "global_load_d16_b16">; -defm GLOBAL_LOAD_D16_HI_U8 : FLAT_Real_AllAddr_gfx11<0x021, "GLOBAL_LOAD_UBYTE_D16_HI", "global_load_d16_hi_u8">; -defm GLOBAL_LOAD_D16_HI_I8 : FLAT_Real_AllAddr_gfx11<0x022, "GLOBAL_LOAD_SBYTE_D16_HI", "global_load_d16_hi_i8">; -defm GLOBAL_LOAD_D16_HI_B16 : FLAT_Real_AllAddr_gfx11<0x023, "GLOBAL_LOAD_SHORT_D16_HI", "global_load_d16_hi_b16">; -defm GLOBAL_STORE_D16_HI_B8 : FLAT_Real_AllAddr_gfx11<0x024, "GLOBAL_STORE_BYTE_D16_HI", "global_store_d16_hi_b8">; -defm GLOBAL_STORE_D16_HI_B16 : FLAT_Real_AllAddr_gfx11<0x025, "GLOBAL_STORE_SHORT_D16_HI", "global_store_d16_hi_b16">; -defm GLOBAL_LOAD_ADDTID_B32 : FLAT_Real_AllAddr_gfx11<0x028, "GLOBAL_LOAD_DWORD_ADDTID", "global_load_addtid_b32">; -defm GLOBAL_STORE_ADDTID_B32 : FLAT_Real_AllAddr_gfx11<0x029, "GLOBAL_STORE_DWORD_ADDTID", "global_store_addtid_b32">; -defm GLOBAL_ATOMIC_SWAP_B32 : FLAT_Real_GlblAtomics_gfx11<0x033, "GLOBAL_ATOMIC_SWAP", "global_atomic_swap_b32", true>; -defm GLOBAL_ATOMIC_CMPSWAP_B32 : FLAT_Real_GlblAtomics_gfx11<0x034, "GLOBAL_ATOMIC_CMPSWAP", "global_atomic_cmpswap_b32", true>; -defm GLOBAL_ATOMIC_ADD_U32 : FLAT_Real_GlblAtomics_gfx11<0x035, "GLOBAL_ATOMIC_ADD", "global_atomic_add_u32", true>; -defm GLOBAL_ATOMIC_SUB_U32 : FLAT_Real_GlblAtomics_gfx11<0x036, "GLOBAL_ATOMIC_SUB", "global_atomic_sub_u32", true>; -defm GLOBAL_ATOMIC_CSUB_U32 : FLAT_Real_GlblAtomics_gfx11<0x037, "GLOBAL_ATOMIC_CSUB", "global_atomic_csub_u32", true>; -defm GLOBAL_ATOMIC_MIN_I32 : FLAT_Real_GlblAtomics_gfx11<0x038, "GLOBAL_ATOMIC_SMIN", "global_atomic_min_i32", true>; -defm GLOBAL_ATOMIC_MIN_U32 : FLAT_Real_GlblAtomics_gfx11<0x039, "GLOBAL_ATOMIC_UMIN", "global_atomic_min_u32", true>; -defm GLOBAL_ATOMIC_MAX_I32 : FLAT_Real_GlblAtomics_gfx11<0x03a, "GLOBAL_ATOMIC_SMAX", "global_atomic_max_i32", true>; -defm GLOBAL_ATOMIC_MAX_U32 : FLAT_Real_GlblAtomics_gfx11<0x03b, "GLOBAL_ATOMIC_UMAX", "global_atomic_max_u32", true>; -defm GLOBAL_ATOMIC_AND_B32 : FLAT_Real_GlblAtomics_gfx11<0x03c, "GLOBAL_ATOMIC_AND", "global_atomic_and_b32", true>; -defm GLOBAL_ATOMIC_OR_B32 : FLAT_Real_GlblAtomics_gfx11<0x03d, "GLOBAL_ATOMIC_OR", "global_atomic_or_b32", true>; -defm GLOBAL_ATOMIC_XOR_B32 : FLAT_Real_GlblAtomics_gfx11<0x03e, "GLOBAL_ATOMIC_XOR", "global_atomic_xor_b32", true>; -defm GLOBAL_ATOMIC_INC_U32 : FLAT_Real_GlblAtomics_gfx11<0x03f, "GLOBAL_ATOMIC_INC", "global_atomic_inc_u32", true>; -defm GLOBAL_ATOMIC_DEC_U32 : FLAT_Real_GlblAtomics_gfx11<0x040, "GLOBAL_ATOMIC_DEC", "global_atomic_dec_u32", true>; -defm GLOBAL_ATOMIC_SWAP_B64 : FLAT_Real_GlblAtomics_gfx11<0x041, "GLOBAL_ATOMIC_SWAP_X2", "global_atomic_swap_b64", true>; -defm GLOBAL_ATOMIC_CMPSWAP_B64 : FLAT_Real_GlblAtomics_gfx11<0x042, "GLOBAL_ATOMIC_CMPSWAP_X2", "global_atomic_cmpswap_b64", true>; -defm GLOBAL_ATOMIC_ADD_U64 : FLAT_Real_GlblAtomics_gfx11<0x043, "GLOBAL_ATOMIC_ADD_X2", "global_atomic_add_u64", true>; -defm GLOBAL_ATOMIC_SUB_U64 : FLAT_Real_GlblAtomics_gfx11<0x044, "GLOBAL_ATOMIC_SUB_X2", "global_atomic_sub_u64", true>; -defm GLOBAL_ATOMIC_MIN_I64 : FLAT_Real_GlblAtomics_gfx11<0x045, "GLOBAL_ATOMIC_SMIN_X2", "global_atomic_min_i64", true>; -defm GLOBAL_ATOMIC_MIN_U64 : FLAT_Real_GlblAtomics_gfx11<0x046, "GLOBAL_ATOMIC_UMIN_X2", "global_atomic_min_u64", true>; -defm GLOBAL_ATOMIC_MAX_I64 : FLAT_Real_GlblAtomics_gfx11<0x047, "GLOBAL_ATOMIC_SMAX_X2", "global_atomic_max_i64", true>; -defm GLOBAL_ATOMIC_MAX_U64 : FLAT_Real_GlblAtomics_gfx11<0x048, "GLOBAL_ATOMIC_UMAX_X2", "global_atomic_max_u64", true>; -defm GLOBAL_ATOMIC_AND_B64 : FLAT_Real_GlblAtomics_gfx11<0x049, "GLOBAL_ATOMIC_AND_X2", "global_atomic_and_b64", true>; -defm GLOBAL_ATOMIC_OR_B64 : FLAT_Real_GlblAtomics_gfx11<0x04a, "GLOBAL_ATOMIC_OR_X2", "global_atomic_or_b64", true>; -defm GLOBAL_ATOMIC_XOR_B64 : FLAT_Real_GlblAtomics_gfx11<0x04b, "GLOBAL_ATOMIC_XOR_X2", "global_atomic_xor_b64", true>; -defm GLOBAL_ATOMIC_INC_U64 : FLAT_Real_GlblAtomics_gfx11<0x04c, "GLOBAL_ATOMIC_INC_X2", "global_atomic_inc_u64", true>; -defm GLOBAL_ATOMIC_DEC_U64 : FLAT_Real_GlblAtomics_gfx11<0x04d, "GLOBAL_ATOMIC_DEC_X2", "global_atomic_dec_u64", true>; -defm GLOBAL_ATOMIC_CMPSWAP_F32 : FLAT_Real_GlblAtomics_gfx11<0x050, "GLOBAL_ATOMIC_FCMPSWAP", "global_atomic_cmpswap_f32">; -defm GLOBAL_ATOMIC_MIN_F32 : FLAT_Real_GlblAtomics_gfx11<0x051, "GLOBAL_ATOMIC_FMIN", "global_atomic_min_f32">; -defm GLOBAL_ATOMIC_MAX_F32 : FLAT_Real_GlblAtomics_gfx11<0x052, "GLOBAL_ATOMIC_FMAX", "global_atomic_max_f32">; -defm GLOBAL_ATOMIC_ADD_F32 : FLAT_Real_GlblAtomics_gfx11<0x056, "GLOBAL_ATOMIC_ADD_F32", "global_atomic_add_f32">; +defm GLOBAL_LOAD_UBYTE : GLOBAL_Real_AllAddr_gfx11<0x010, "global_load_u8">; +defm GLOBAL_LOAD_SBYTE : GLOBAL_Real_AllAddr_gfx11<0x011, "global_load_i8">; +defm GLOBAL_LOAD_USHORT : GLOBAL_Real_AllAddr_gfx11<0x012, "global_load_u16">; +defm GLOBAL_LOAD_SSHORT : GLOBAL_Real_AllAddr_gfx11<0x013, "global_load_i16">; +defm GLOBAL_LOAD_DWORD : GLOBAL_Real_AllAddr_gfx11<0x014, "global_load_b32">; +defm GLOBAL_LOAD_DWORDX2 : GLOBAL_Real_AllAddr_gfx11<0x015, "global_load_b64">; +defm GLOBAL_LOAD_DWORDX3 : GLOBAL_Real_AllAddr_gfx11<0x016, "global_load_b96">; +defm GLOBAL_LOAD_DWORDX4 : GLOBAL_Real_AllAddr_gfx11<0x017, "global_load_b128">; +defm GLOBAL_STORE_BYTE : GLOBAL_Real_AllAddr_gfx11<0x018, "global_store_b8">; +defm GLOBAL_STORE_SHORT : GLOBAL_Real_AllAddr_gfx11<0x019, "global_store_b16">; +defm GLOBAL_STORE_DWORD : GLOBAL_Real_AllAddr_gfx11<0x01a, "global_store_b32">; +defm GLOBAL_STORE_DWORDX2 : GLOBAL_Real_AllAddr_gfx11<0x01b, "global_store_b64">; +defm GLOBAL_STORE_DWORDX3 : GLOBAL_Real_AllAddr_gfx11<0x01c, "global_store_b96">; +defm GLOBAL_STORE_DWORDX4 : GLOBAL_Real_AllAddr_gfx11<0x01d, "global_store_b128">; +defm GLOBAL_LOAD_UBYTE_D16 : GLOBAL_Real_AllAddr_gfx11<0x01e, "global_load_d16_u8">; +defm GLOBAL_LOAD_SBYTE_D16 : GLOBAL_Real_AllAddr_gfx11<0x01f, "global_load_d16_i8">; +defm GLOBAL_LOAD_SHORT_D16 : GLOBAL_Real_AllAddr_gfx11<0x020, "global_load_d16_b16">; +defm GLOBAL_LOAD_UBYTE_D16_HI : GLOBAL_Real_AllAddr_gfx11<0x021, "global_load_d16_hi_u8">; +defm GLOBAL_LOAD_SBYTE_D16_HI : GLOBAL_Real_AllAddr_gfx11<0x022, "global_load_d16_hi_i8">; +defm GLOBAL_LOAD_SHORT_D16_HI : GLOBAL_Real_AllAddr_gfx11<0x023, "global_load_d16_hi_b16">; +defm GLOBAL_STORE_BYTE_D16_HI : GLOBAL_Real_AllAddr_gfx11<0x024, "global_store_d16_hi_b8">; +defm GLOBAL_STORE_SHORT_D16_HI : GLOBAL_Real_AllAddr_gfx11<0x025, "global_store_d16_hi_b16">; +defm GLOBAL_LOAD_DWORD_ADDTID : GLOBAL_Real_AllAddr_gfx11<0x028, "global_load_addtid_b32">; +defm GLOBAL_STORE_DWORD_ADDTID : GLOBAL_Real_AllAddr_gfx11<0x029, "global_store_addtid_b32">; +defm GLOBAL_ATOMIC_SWAP : GLOBAL_Real_Atomics_gfx11<0x033, "global_atomic_swap_b32">; +defm GLOBAL_ATOMIC_CMPSWAP : GLOBAL_Real_Atomics_gfx11<0x034, "global_atomic_cmpswap_b32">; +defm GLOBAL_ATOMIC_ADD : GLOBAL_Real_Atomics_gfx11<0x035, "global_atomic_add_u32">; +defm GLOBAL_ATOMIC_SUB : GLOBAL_Real_Atomics_gfx11<0x036, "global_atomic_sub_u32">; +defm GLOBAL_ATOMIC_CSUB : GLOBAL_Real_Atomics_gfx11<0x037, "global_atomic_csub_u32">; +defm GLOBAL_ATOMIC_SMIN : GLOBAL_Real_Atomics_gfx11<0x038, "global_atomic_min_i32">; +defm GLOBAL_ATOMIC_UMIN : GLOBAL_Real_Atomics_gfx11<0x039, "global_atomic_min_u32">; +defm GLOBAL_ATOMIC_SMAX : GLOBAL_Real_Atomics_gfx11<0x03a, "global_atomic_max_i32">; +defm GLOBAL_ATOMIC_UMAX : GLOBAL_Real_Atomics_gfx11<0x03b, "global_atomic_max_u32">; +defm GLOBAL_ATOMIC_AND : GLOBAL_Real_Atomics_gfx11<0x03c, "global_atomic_and_b32">; +defm GLOBAL_ATOMIC_OR : GLOBAL_Real_Atomics_gfx11<0x03d, "global_atomic_or_b32">; +defm GLOBAL_ATOMIC_XOR : GLOBAL_Real_Atomics_gfx11<0x03e, "global_atomic_xor_b32">; +defm GLOBAL_ATOMIC_INC : GLOBAL_Real_Atomics_gfx11<0x03f, "global_atomic_inc_u32">; +defm GLOBAL_ATOMIC_DEC : GLOBAL_Real_Atomics_gfx11<0x040, "global_atomic_dec_u32">; +defm GLOBAL_ATOMIC_SWAP_X2 : GLOBAL_Real_Atomics_gfx11<0x041, "global_atomic_swap_b64">; +defm GLOBAL_ATOMIC_CMPSWAP_X2 : GLOBAL_Real_Atomics_gfx11<0x042, "global_atomic_cmpswap_b64">; +defm GLOBAL_ATOMIC_ADD_X2 : GLOBAL_Real_Atomics_gfx11<0x043, "global_atomic_add_u64">; +defm GLOBAL_ATOMIC_SUB_X2 : GLOBAL_Real_Atomics_gfx11<0x044, "global_atomic_sub_u64">; +defm GLOBAL_ATOMIC_SMIN_X2 : GLOBAL_Real_Atomics_gfx11<0x045, "global_atomic_min_i64">; +defm GLOBAL_ATOMIC_UMIN_X2 : GLOBAL_Real_Atomics_gfx11<0x046, "global_atomic_min_u64">; +defm GLOBAL_ATOMIC_SMAX_X2 : GLOBAL_Real_Atomics_gfx11<0x047, "global_atomic_max_i64">; +defm GLOBAL_ATOMIC_UMAX_X2 : GLOBAL_Real_Atomics_gfx11<0x048, "global_atomic_max_u64">; +defm GLOBAL_ATOMIC_AND_X2 : GLOBAL_Real_Atomics_gfx11<0x049, "global_atomic_and_b64">; +defm GLOBAL_ATOMIC_OR_X2 : GLOBAL_Real_Atomics_gfx11<0x04a, "global_atomic_or_b64">; +defm GLOBAL_ATOMIC_XOR_X2 : GLOBAL_Real_Atomics_gfx11<0x04b, "global_atomic_xor_b64">; +defm GLOBAL_ATOMIC_INC_X2 : GLOBAL_Real_Atomics_gfx11<0x04c, "global_atomic_inc_u64">; +defm GLOBAL_ATOMIC_DEC_X2 : GLOBAL_Real_Atomics_gfx11<0x04d, "global_atomic_dec_u64">; +defm GLOBAL_ATOMIC_FCMPSWAP : GLOBAL_Real_Atomics_gfx11<0x050, "global_atomic_cmpswap_f32">; +defm GLOBAL_ATOMIC_FMIN : GLOBAL_Real_Atomics_gfx11<0x051, "global_atomic_min_f32">; +defm GLOBAL_ATOMIC_FMAX : GLOBAL_Real_Atomics_gfx11<0x052, "global_atomic_max_f32">; +defm GLOBAL_ATOMIC_ADD_F32 : GLOBAL_Real_Atomics_gfx11<0x056>; // ENC_FLAT_SCRATCH. -defm SCRATCH_LOAD_U8 : FLAT_Real_ScratchAllAddr_gfx11<0x10, "SCRATCH_LOAD_UBYTE", "scratch_load_u8", true>; -defm SCRATCH_LOAD_I8 : FLAT_Real_ScratchAllAddr_gfx11<0x11, "SCRATCH_LOAD_SBYTE", "scratch_load_i8", true>; -defm SCRATCH_LOAD_U16 : FLAT_Real_ScratchAllAddr_gfx11<0x12, "SCRATCH_LOAD_USHORT", "scratch_load_u16", true>; -defm SCRATCH_LOAD_I16 : FLAT_Real_ScratchAllAddr_gfx11<0x13, "SCRATCH_LOAD_SSHORT", "scratch_load_i16", true>; -defm SCRATCH_LOAD_B32 : FLAT_Real_ScratchAllAddr_gfx11<0x14, "SCRATCH_LOAD_DWORD", "scratch_load_b32", true>; -defm SCRATCH_LOAD_B64 : FLAT_Real_ScratchAllAddr_gfx11<0x15, "SCRATCH_LOAD_DWORDX2", "scratch_load_b64", true>; -defm SCRATCH_LOAD_B96 : FLAT_Real_ScratchAllAddr_gfx11<0x16, "SCRATCH_LOAD_DWORDX3", "scratch_load_b96", true>; -defm SCRATCH_LOAD_B128 : FLAT_Real_ScratchAllAddr_gfx11<0x17, "SCRATCH_LOAD_DWORDX4", "scratch_load_b128", true>; -defm SCRATCH_STORE_B8 : FLAT_Real_ScratchAllAddr_gfx11<0x18, "SCRATCH_STORE_BYTE", "scratch_store_b8", true>; -defm SCRATCH_STORE_B16 : FLAT_Real_ScratchAllAddr_gfx11<0x19, "SCRATCH_STORE_SHORT", "scratch_store_b16", true>; -defm SCRATCH_STORE_B32 : FLAT_Real_ScratchAllAddr_gfx11<0x1a, "SCRATCH_STORE_DWORD", "scratch_store_b32", true>; -defm SCRATCH_STORE_B64 : FLAT_Real_ScratchAllAddr_gfx11<0x1b, "SCRATCH_STORE_DWORDX2", "scratch_store_b64", true>; -defm SCRATCH_STORE_B96 : FLAT_Real_ScratchAllAddr_gfx11<0x1c, "SCRATCH_STORE_DWORDX3", "scratch_store_b96", true>; -defm SCRATCH_STORE_B128 : FLAT_Real_ScratchAllAddr_gfx11<0x1d, "SCRATCH_STORE_DWORDX4", "scratch_store_b128", true>; -defm SCRATCH_LOAD_D16_U8 : FLAT_Real_ScratchAllAddr_gfx11<0x1e, "SCRATCH_LOAD_UBYTE_D16", "scratch_load_d16_u8">; -defm SCRATCH_LOAD_D16_I8 : FLAT_Real_ScratchAllAddr_gfx11<0x1f, "SCRATCH_LOAD_SBYTE_D16", "scratch_load_d16_i8">; -defm SCRATCH_LOAD_D16_B16 : FLAT_Real_ScratchAllAddr_gfx11<0x20, "SCRATCH_LOAD_SHORT_D16", "scratch_load_d16_b16">; -defm SCRATCH_LOAD_D16_HI_U8 : FLAT_Real_ScratchAllAddr_gfx11<0x21, "SCRATCH_LOAD_UBYTE_D16_HI", "scratch_load_d16_hi_u8">; -defm SCRATCH_LOAD_D16_HI_I8 : FLAT_Real_ScratchAllAddr_gfx11<0x22, "SCRATCH_LOAD_SBYTE_D16_HI", "scratch_load_d16_hi_i8">; -defm SCRATCH_LOAD_D16_HI_B16 : FLAT_Real_ScratchAllAddr_gfx11<0x23, "SCRATCH_LOAD_SHORT_D16_HI", "scratch_load_d16_hi_b16">; -defm SCRATCH_STORE_D16_HI_B8 : FLAT_Real_ScratchAllAddr_gfx11<0x24, "SCRATCH_STORE_BYTE_D16_HI", "scratch_store_d16_hi_b8">; -defm SCRATCH_STORE_D16_HI_B16 : FLAT_Real_ScratchAllAddr_gfx11<0x25, "SCRATCH_STORE_SHORT_D16_HI", "scratch_store_d16_hi_b16">; +defm SCRATCH_LOAD_UBYTE : SCRATCH_Real_AllAddr_gfx11<0x10, "scratch_load_u8">; +defm SCRATCH_LOAD_SBYTE : SCRATCH_Real_AllAddr_gfx11<0x11, "scratch_load_i8">; +defm SCRATCH_LOAD_USHORT : SCRATCH_Real_AllAddr_gfx11<0x12, "scratch_load_u16">; +defm SCRATCH_LOAD_SSHORT : SCRATCH_Real_AllAddr_gfx11<0x13, "scratch_load_i16">; +defm SCRATCH_LOAD_DWORD : SCRATCH_Real_AllAddr_gfx11<0x14, "scratch_load_b32">; +defm SCRATCH_LOAD_DWORDX2 : SCRATCH_Real_AllAddr_gfx11<0x15, "scratch_load_b64">; +defm SCRATCH_LOAD_DWORDX3 : SCRATCH_Real_AllAddr_gfx11<0x16, "scratch_load_b96">; +defm SCRATCH_LOAD_DWORDX4 : SCRATCH_Real_AllAddr_gfx11<0x17, "scratch_load_b128">; +defm SCRATCH_STORE_BYTE : SCRATCH_Real_AllAddr_gfx11<0x18, "scratch_store_b8">; +defm SCRATCH_STORE_SHORT : SCRATCH_Real_AllAddr_gfx11<0x19, "scratch_store_b16">; +defm SCRATCH_STORE_DWORD : SCRATCH_Real_AllAddr_gfx11<0x1a, "scratch_store_b32">; +defm SCRATCH_STORE_DWORDX2 : SCRATCH_Real_AllAddr_gfx11<0x1b, "scratch_store_b64">; +defm SCRATCH_STORE_DWORDX3 : SCRATCH_Real_AllAddr_gfx11<0x1c, "scratch_store_b96">; +defm SCRATCH_STORE_DWORDX4 : SCRATCH_Real_AllAddr_gfx11<0x1d, "scratch_store_b128">; +defm SCRATCH_LOAD_UBYTE_D16 : SCRATCH_Real_AllAddr_gfx11<0x1e, "scratch_load_d16_u8">; +defm SCRATCH_LOAD_SBYTE_D16 : SCRATCH_Real_AllAddr_gfx11<0x1f, "scratch_load_d16_i8">; +defm SCRATCH_LOAD_SHORT_D16 : SCRATCH_Real_AllAddr_gfx11<0x20, "scratch_load_d16_b16">; +defm SCRATCH_LOAD_UBYTE_D16_HI : SCRATCH_Real_AllAddr_gfx11<0x21, "scratch_load_d16_hi_u8">; +defm SCRATCH_LOAD_SBYTE_D16_HI : SCRATCH_Real_AllAddr_gfx11<0x22, "scratch_load_d16_hi_i8">; +defm SCRATCH_LOAD_SHORT_D16_HI : SCRATCH_Real_AllAddr_gfx11<0x23, "scratch_load_d16_hi_b16">; +defm SCRATCH_STORE_BYTE_D16_HI : SCRATCH_Real_AllAddr_gfx11<0x24, "scratch_store_d16_hi_b8">; +defm SCRATCH_STORE_SHORT_D16_HI : SCRATCH_Real_AllAddr_gfx11<0x25, "scratch_store_d16_hi_b16">; //===----------------------------------------------------------------------===// // GFX12 //===----------------------------------------------------------------------===// -class VFLAT_Real_gfx12 <bits<8> op, FLAT_Pseudo ps, - string opName = ps.Mnemonic> : - VFLAT_Real <op, ps, opName>, - SIMCInstr <ps.PseudoInstr, SIEncodingFamily.GFX12> { - let AssemblerPredicate = isGFX12Plus; - let DecoderNamespace = "GFX12"; - - let Inst{25-24} = !if(ps.is_flat_scratch, 0b01, - !if(ps.is_flat_global, 0b10, 0b00)); -} +multiclass VFLAT_Real_gfx12 <bits<8> op, string name = get_FLAT_ps<NAME>.Mnemonic> { + defvar ps = !cast<FLAT_Pseudo>(NAME); + def _gfx12 : VFLAT_Real <op, ps, name>, + SIMCInstr <ps.PseudoInstr, SIEncodingFamily.GFX12> { + let AssemblerPredicate = isGFX12Only; + let DecoderNamespace = "GFX12"; -multiclass VFLAT_Aliases_gfx12<string ps, string opName, int renamed, string alias> { - if renamed then - def _renamed_gfx12 : MnemonicAlias<!cast<FLAT_Pseudo>(ps).Mnemonic, opName>, Requires<[isGFX12Plus]>; - if !not(!empty(alias)) then - def _alias_gfx12 : MnemonicAlias<alias, opName>, Requires<[isGFX12Plus]>; -} - -multiclass VFLAT_Real_Base_gfx12<bits<8> op, string ps = NAME, string opName = !tolower(NAME), - int renamed = false, string alias = ""> : - VFLAT_Aliases_gfx12<ps, opName, renamed, alias> { - def _gfx12 : VFLAT_Real_gfx12<op, !cast<FLAT_Pseudo>(ps), opName> { - let Inst{6-0} = !cast<int>(SGPR_NULL_gfx11plus.HWEncoding); + let Inst{25-24} = {ps.is_flat_global, ps.is_flat_scratch}; } } -multiclass VFLAT_Real_RTN_gfx12<bits<8> op, string ps, string opName> { - def _RTN_gfx12 : VFLAT_Real_gfx12<op, !cast<FLAT_Pseudo>(ps#"_RTN"), opName> { - let Inst{6-0} = !cast<int>(SGPR_NULL_gfx11plus.HWEncoding); - } +multiclass VFLAT_Aliases_gfx12<string name, string alias = name> { + defvar ps = get_FLAT_ps<NAME>; + if !ne(ps.Mnemonic, name) then + def : MnemonicAlias<ps.Mnemonic, name>, Requires<[isGFX12Only]>; + if !ne(alias, name) then + def : MnemonicAlias<alias, name>, Requires<[isGFX12Only]>; } -multiclass VFLAT_Real_SADDR_gfx12<bits<8> op, string ps, string opName> { - def _SADDR_gfx12 : VFLAT_Real_gfx12<op, !cast<FLAT_Pseudo>(ps#"_SADDR"), opName>; -} +multiclass VFLAT_Real_Base_gfx12<bits<8> op, + string name = get_FLAT_ps<NAME>.Mnemonic, + string alias = name> : + VFLAT_Aliases_gfx12<name, alias>, + VFLAT_Real_gfx12<op, name>; -multiclass VFLAT_Real_SADDR_RTN_gfx12<bits<8> op, string ps, string opName> { - def _SADDR_RTN_gfx12 : VFLAT_Real_gfx12<op, !cast<FLAT_Pseudo>(ps#"_SADDR_RTN"), opName>; +multiclass VFLAT_Real_Atomics_gfx12<bits<8> op, + string name = get_FLAT_ps<NAME>.Mnemonic, + string alias = ""> : + VFLAT_Real_Base_gfx12<op, name, alias> { + defm _RTN : VFLAT_Real_gfx12<op, name>; } -multiclass VFLAT_Real_ST_gfx12<bits<8> op, string ps, string opName> { - def _ST_gfx12 : VFLAT_Real_gfx12<op, !cast<FLAT_Pseudo>(ps#"_ST"), opName> { - let Inst{6-0} = !cast<int>(SGPR_NULL_gfx11plus.HWEncoding); - let OtherPredicates = [HasFlatScratchSTMode]; - } +multiclass VGLOBAL_Real_AllAddr_gfx12<bits<8> op, + string name = get_FLAT_ps<NAME>.Mnemonic, + string alias = name> : + VFLAT_Real_Base_gfx12<op, name, alias> { + defm _SADDR : VFLAT_Real_gfx12<op, name>; } -multiclass VFLAT_Real_SVS_gfx12<bits<8> op, string ps, string opName> { - def _SVS_gfx12 : VFLAT_Real_gfx12<op, !cast<FLAT_Pseudo>(ps#"_SVS"), opName> { - let OtherPredicates = [HasFlatScratchSVSMode]; +multiclass VGLOBAL_Real_AllAddr_gfx12_w64<bits<8> op, + string name = get_FLAT_ps<NAME>.Mnemonic> : + VFLAT_Aliases_gfx12<name> { + let DecoderNamespace = "GFX12W64" in { + defm "" : VFLAT_Real_gfx12<op, name>; + defm _SADDR : VFLAT_Real_gfx12<op, name>; } } -multiclass VFLAT_Real_Atomics_gfx12<bits<8> op, string ps = NAME, string opName = !tolower(NAME), - int renamed = false, string alias = ""> : - VFLAT_Real_Base_gfx12<op, ps, opName, renamed, alias>, - VFLAT_Real_RTN_gfx12<op, ps, opName>; - -multiclass VGLOBAL_Real_AllAddr_gfx12<bits<8> op, string ps = NAME, string opName = !tolower(NAME), - int renamed = false, string alias = ""> : - VFLAT_Real_Base_gfx12<op, ps, opName, renamed, alias>, - VFLAT_Real_SADDR_gfx12<op, ps, opName>; - -multiclass VGLOBAL_Real_Atomics_gfx12<bits<8> op, string ps = NAME, string opName = !tolower(NAME), - int renamed = false, string alias = ""> : - VGLOBAL_Real_AllAddr_gfx12<op, ps, opName, renamed, alias>, - VFLAT_Real_RTN_gfx12<op, ps, opName>, - VFLAT_Real_SADDR_RTN_gfx12<op, ps, opName>; +multiclass VGLOBAL_Real_Atomics_gfx12<bits<8> op, + string name = get_FLAT_ps<NAME>.Mnemonic, + string alias = ""> : + VGLOBAL_Real_AllAddr_gfx12<op, name, alias> { + defm _RTN : VFLAT_Real_gfx12<op, name>; + defm _SADDR_RTN : VFLAT_Real_gfx12<op, name>; +} -multiclass VSCRATCH_Real_AllAddr_gfx12<bits<8> op, string ps = NAME, string opName = !tolower(NAME), - int renamed = false> : - VFLAT_Real_Base_gfx12<op, ps, opName, renamed>, - VFLAT_Real_SADDR_gfx12<op, ps, opName>, - VFLAT_Real_ST_gfx12<op, ps, opName>, - VFLAT_Real_SVS_gfx12<op, ps, opName>; +multiclass VSCRATCH_Real_AllAddr_gfx12<bits<8> op, + string name = get_FLAT_ps<NAME>.Mnemonic> : + VFLAT_Real_Base_gfx12<op, name> { + defm _SADDR : VFLAT_Real_gfx12<op, name>; + defm _ST : VFLAT_Real_gfx12<op, name>; + defm _SVS : VFLAT_Real_gfx12<op, name>; +} // ENC_VFLAT. -defm FLAT_LOAD_U8 : VFLAT_Real_Base_gfx12<0x010, "FLAT_LOAD_UBYTE", "flat_load_u8", true>; -defm FLAT_LOAD_I8 : VFLAT_Real_Base_gfx12<0x011, "FLAT_LOAD_SBYTE", "flat_load_i8", true>; -defm FLAT_LOAD_U16 : VFLAT_Real_Base_gfx12<0x012, "FLAT_LOAD_USHORT", "flat_load_u16", true>; -defm FLAT_LOAD_I16 : VFLAT_Real_Base_gfx12<0x013, "FLAT_LOAD_SSHORT", "flat_load_i16", true>; -defm FLAT_LOAD_B32 : VFLAT_Real_Base_gfx12<0x014, "FLAT_LOAD_DWORD", "flat_load_b32", true>; -defm FLAT_LOAD_B64 : VFLAT_Real_Base_gfx12<0x015, "FLAT_LOAD_DWORDX2", "flat_load_b64", true>; -defm FLAT_LOAD_B96 : VFLAT_Real_Base_gfx12<0x016, "FLAT_LOAD_DWORDX3", "flat_load_b96", true>; -defm FLAT_LOAD_B128 : VFLAT_Real_Base_gfx12<0x017, "FLAT_LOAD_DWORDX4", "flat_load_b128", true>; -defm FLAT_STORE_B8 : VFLAT_Real_Base_gfx12<0x018, "FLAT_STORE_BYTE", "flat_store_b8", true>; -defm FLAT_STORE_B16 : VFLAT_Real_Base_gfx12<0x019, "FLAT_STORE_SHORT", "flat_store_b16", true>; -defm FLAT_STORE_B32 : VFLAT_Real_Base_gfx12<0x01a, "FLAT_STORE_DWORD", "flat_store_b32", true>; -defm FLAT_STORE_B64 : VFLAT_Real_Base_gfx12<0x01b, "FLAT_STORE_DWORDX2", "flat_store_b64", true>; -defm FLAT_STORE_B96 : VFLAT_Real_Base_gfx12<0x01c, "FLAT_STORE_DWORDX3", "flat_store_b96", true>; -defm FLAT_STORE_B128 : VFLAT_Real_Base_gfx12<0x01d, "FLAT_STORE_DWORDX4", "flat_store_b128", true>; -defm FLAT_LOAD_D16_U8 : VFLAT_Real_Base_gfx12<0x01e, "FLAT_LOAD_UBYTE_D16">; -defm FLAT_LOAD_D16_I8 : VFLAT_Real_Base_gfx12<0x01f, "FLAT_LOAD_SBYTE_D16">; -defm FLAT_LOAD_D16_B16 : VFLAT_Real_Base_gfx12<0x020, "FLAT_LOAD_SHORT_D16">; -defm FLAT_LOAD_D16_HI_U8 : VFLAT_Real_Base_gfx12<0x021, "FLAT_LOAD_UBYTE_D16_HI">; -defm FLAT_LOAD_D16_HI_I8 : VFLAT_Real_Base_gfx12<0x022, "FLAT_LOAD_SBYTE_D16_HI">; -defm FLAT_LOAD_D16_HI_B16 : VFLAT_Real_Base_gfx12<0x023, "FLAT_LOAD_SHORT_D16_HI">; -defm FLAT_STORE_D16_HI_B8 : VFLAT_Real_Base_gfx12<0x024, "FLAT_STORE_BYTE_D16_HI">; -defm FLAT_STORE_D16_HI_B16 : VFLAT_Real_Base_gfx12<0x025, "FLAT_STORE_SHORT_D16_HI">; -defm FLAT_ATOMIC_SWAP_B32 : VFLAT_Real_Atomics_gfx12<0x033, "FLAT_ATOMIC_SWAP", "flat_atomic_swap_b32", true>; -defm FLAT_ATOMIC_CMPSWAP_B32 : VFLAT_Real_Atomics_gfx12<0x034, "FLAT_ATOMIC_CMPSWAP", "flat_atomic_cmpswap_b32", true>; -defm FLAT_ATOMIC_ADD_U32 : VFLAT_Real_Atomics_gfx12<0x035, "FLAT_ATOMIC_ADD", "flat_atomic_add_u32", true>; -defm FLAT_ATOMIC_SUB_U32 : VFLAT_Real_Atomics_gfx12<0x036, "FLAT_ATOMIC_SUB", "flat_atomic_sub_u32", true>; -defm FLAT_ATOMIC_SUB_CLAMP_U32 : VFLAT_Real_Atomics_gfx12<0x037, "FLAT_ATOMIC_CSUB_U32", "flat_atomic_sub_clamp_u32", true>; -defm FLAT_ATOMIC_MIN_I32 : VFLAT_Real_Atomics_gfx12<0x038, "FLAT_ATOMIC_SMIN", "flat_atomic_min_i32", true>; -defm FLAT_ATOMIC_MIN_U32 : VFLAT_Real_Atomics_gfx12<0x039, "FLAT_ATOMIC_UMIN", "flat_atomic_min_u32", true>; -defm FLAT_ATOMIC_MAX_I32 : VFLAT_Real_Atomics_gfx12<0x03a, "FLAT_ATOMIC_SMAX", "flat_atomic_max_i32", true>; -defm FLAT_ATOMIC_MAX_U32 : VFLAT_Real_Atomics_gfx12<0x03b, "FLAT_ATOMIC_UMAX", "flat_atomic_max_u32", true>; -defm FLAT_ATOMIC_AND_B32 : VFLAT_Real_Atomics_gfx12<0x03c, "FLAT_ATOMIC_AND", "flat_atomic_and_b32", true>; -defm FLAT_ATOMIC_OR_B32 : VFLAT_Real_Atomics_gfx12<0x03d, "FLAT_ATOMIC_OR", "flat_atomic_or_b32", true>; -defm FLAT_ATOMIC_XOR_B32 : VFLAT_Real_Atomics_gfx12<0x03e, "FLAT_ATOMIC_XOR", "flat_atomic_xor_b32", true>; -defm FLAT_ATOMIC_INC_U32 : VFLAT_Real_Atomics_gfx12<0x03f, "FLAT_ATOMIC_INC", "flat_atomic_inc_u32", true>; -defm FLAT_ATOMIC_DEC_U32 : VFLAT_Real_Atomics_gfx12<0x040, "FLAT_ATOMIC_DEC", "flat_atomic_dec_u32", true>; -defm FLAT_ATOMIC_SWAP_B64 : VFLAT_Real_Atomics_gfx12<0x041, "FLAT_ATOMIC_SWAP_X2", "flat_atomic_swap_b64", true>; -defm FLAT_ATOMIC_CMPSWAP_B64 : VFLAT_Real_Atomics_gfx12<0x042, "FLAT_ATOMIC_CMPSWAP_X2", "flat_atomic_cmpswap_b64", true>; -defm FLAT_ATOMIC_ADD_U64 : VFLAT_Real_Atomics_gfx12<0x043, "FLAT_ATOMIC_ADD_X2", "flat_atomic_add_u64", true>; -defm FLAT_ATOMIC_SUB_U64 : VFLAT_Real_Atomics_gfx12<0x044, "FLAT_ATOMIC_SUB_X2", "flat_atomic_sub_u64", true>; -defm FLAT_ATOMIC_MIN_I64 : VFLAT_Real_Atomics_gfx12<0x045, "FLAT_ATOMIC_SMIN_X2", "flat_atomic_min_i64", true>; -defm FLAT_ATOMIC_MIN_U64 : VFLAT_Real_Atomics_gfx12<0x046, "FLAT_ATOMIC_UMIN_X2", "flat_atomic_min_u64", true>; -defm FLAT_ATOMIC_MAX_I64 : VFLAT_Real_Atomics_gfx12<0x047, "FLAT_ATOMIC_SMAX_X2", "flat_atomic_max_i64", true>; -defm FLAT_ATOMIC_MAX_U64 : VFLAT_Real_Atomics_gfx12<0x048, "FLAT_ATOMIC_UMAX_X2", "flat_atomic_max_u64", true>; -defm FLAT_ATOMIC_AND_B64 : VFLAT_Real_Atomics_gfx12<0x049, "FLAT_ATOMIC_AND_X2", "flat_atomic_and_b64", true>; -defm FLAT_ATOMIC_OR_B64 : VFLAT_Real_Atomics_gfx12<0x04a, "FLAT_ATOMIC_OR_X2", "flat_atomic_or_b64", true>; -defm FLAT_ATOMIC_XOR_B64 : VFLAT_Real_Atomics_gfx12<0x04b, "FLAT_ATOMIC_XOR_X2", "flat_atomic_xor_b64", true>; -defm FLAT_ATOMIC_INC_U64 : VFLAT_Real_Atomics_gfx12<0x04c, "FLAT_ATOMIC_INC_X2", "flat_atomic_inc_u64", true>; -defm FLAT_ATOMIC_DEC_U64 : VFLAT_Real_Atomics_gfx12<0x04d, "FLAT_ATOMIC_DEC_X2", "flat_atomic_dec_u64", true>; -defm FLAT_ATOMIC_COND_SUB_U32 : VFLAT_Real_Atomics_gfx12<0x050, "FLAT_ATOMIC_COND_SUB_U32", "flat_atomic_cond_sub_u32">; -defm FLAT_ATOMIC_MIN_NUM_F32 : VFLAT_Real_Atomics_gfx12<0x051, "FLAT_ATOMIC_FMIN", "flat_atomic_min_num_f32", true, "flat_atomic_min_f32">; -defm FLAT_ATOMIC_MAX_NUM_F32 : VFLAT_Real_Atomics_gfx12<0x052, "FLAT_ATOMIC_FMAX", "flat_atomic_max_num_f32", true, "flat_atomic_max_f32">; +defm FLAT_LOAD_UBYTE : VFLAT_Real_Base_gfx12<0x010, "flat_load_u8">; +defm FLAT_LOAD_SBYTE : VFLAT_Real_Base_gfx12<0x011, "flat_load_i8">; +defm FLAT_LOAD_USHORT : VFLAT_Real_Base_gfx12<0x012, "flat_load_u16">; +defm FLAT_LOAD_SSHORT : VFLAT_Real_Base_gfx12<0x013, "flat_load_i16">; +defm FLAT_LOAD_DWORD : VFLAT_Real_Base_gfx12<0x014, "flat_load_b32">; +defm FLAT_LOAD_DWORDX2 : VFLAT_Real_Base_gfx12<0x015, "flat_load_b64">; +defm FLAT_LOAD_DWORDX3 : VFLAT_Real_Base_gfx12<0x016, "flat_load_b96">; +defm FLAT_LOAD_DWORDX4 : VFLAT_Real_Base_gfx12<0x017, "flat_load_b128">; +defm FLAT_STORE_BYTE : VFLAT_Real_Base_gfx12<0x018, "flat_store_b8">; +defm FLAT_STORE_SHORT : VFLAT_Real_Base_gfx12<0x019, "flat_store_b16">; +defm FLAT_STORE_DWORD : VFLAT_Real_Base_gfx12<0x01a, "flat_store_b32">; +defm FLAT_STORE_DWORDX2 : VFLAT_Real_Base_gfx12<0x01b, "flat_store_b64">; +defm FLAT_STORE_DWORDX3 : VFLAT_Real_Base_gfx12<0x01c, "flat_store_b96">; +defm FLAT_STORE_DWORDX4 : VFLAT_Real_Base_gfx12<0x01d, "flat_store_b128">; +defm FLAT_LOAD_UBYTE_D16 : VFLAT_Real_Base_gfx12<0x01e, "flat_load_d16_u8">; +defm FLAT_LOAD_SBYTE_D16 : VFLAT_Real_Base_gfx12<0x01f, "flat_load_d16_i8">; +defm FLAT_LOAD_SHORT_D16 : VFLAT_Real_Base_gfx12<0x020, "flat_load_d16_b16">; +defm FLAT_LOAD_UBYTE_D16_HI : VFLAT_Real_Base_gfx12<0x021, "flat_load_d16_hi_u8">; +defm FLAT_LOAD_SBYTE_D16_HI : VFLAT_Real_Base_gfx12<0x022, "flat_load_d16_hi_i8">; +defm FLAT_LOAD_SHORT_D16_HI : VFLAT_Real_Base_gfx12<0x023, "flat_load_d16_hi_b16">; +defm FLAT_STORE_BYTE_D16_HI : VFLAT_Real_Base_gfx12<0x024, "flat_store_d16_hi_b8">; +defm FLAT_STORE_SHORT_D16_HI : VFLAT_Real_Base_gfx12<0x025, "flat_store_d16_hi_b16">; +defm FLAT_ATOMIC_SWAP : VFLAT_Real_Atomics_gfx12<0x033, "flat_atomic_swap_b32">; +defm FLAT_ATOMIC_CMPSWAP : VFLAT_Real_Atomics_gfx12<0x034, "flat_atomic_cmpswap_b32">; +defm FLAT_ATOMIC_ADD : VFLAT_Real_Atomics_gfx12<0x035, "flat_atomic_add_u32">; +defm FLAT_ATOMIC_SUB : VFLAT_Real_Atomics_gfx12<0x036, "flat_atomic_sub_u32">; +defm FLAT_ATOMIC_CSUB_U32 : VFLAT_Real_Atomics_gfx12<0x037, "flat_atomic_sub_clamp_u32">; +defm FLAT_ATOMIC_SMIN : VFLAT_Real_Atomics_gfx12<0x038, "flat_atomic_min_i32">; +defm FLAT_ATOMIC_UMIN : VFLAT_Real_Atomics_gfx12<0x039, "flat_atomic_min_u32">; +defm FLAT_ATOMIC_SMAX : VFLAT_Real_Atomics_gfx12<0x03a, "flat_atomic_max_i32">; +defm FLAT_ATOMIC_UMAX : VFLAT_Real_Atomics_gfx12<0x03b, "flat_atomic_max_u32">; +defm FLAT_ATOMIC_AND : VFLAT_Real_Atomics_gfx12<0x03c, "flat_atomic_and_b32">; +defm FLAT_ATOMIC_OR : VFLAT_Real_Atomics_gfx12<0x03d, "flat_atomic_or_b32">; +defm FLAT_ATOMIC_XOR : VFLAT_Real_Atomics_gfx12<0x03e, "flat_atomic_xor_b32">; +defm FLAT_ATOMIC_INC : VFLAT_Real_Atomics_gfx12<0x03f, "flat_atomic_inc_u32">; +defm FLAT_ATOMIC_DEC : VFLAT_Real_Atomics_gfx12<0x040, "flat_atomic_dec_u32">; +defm FLAT_ATOMIC_SWAP_X2 : VFLAT_Real_Atomics_gfx12<0x041, "flat_atomic_swap_b64">; +defm FLAT_ATOMIC_CMPSWAP_X2 : VFLAT_Real_Atomics_gfx12<0x042, "flat_atomic_cmpswap_b64">; +defm FLAT_ATOMIC_ADD_X2 : VFLAT_Real_Atomics_gfx12<0x043, "flat_atomic_add_u64">; +defm FLAT_ATOMIC_SUB_X2 : VFLAT_Real_Atomics_gfx12<0x044, "flat_atomic_sub_u64">; +defm FLAT_ATOMIC_SMIN_X2 : VFLAT_Real_Atomics_gfx12<0x045, "flat_atomic_min_i64">; +defm FLAT_ATOMIC_UMIN_X2 : VFLAT_Real_Atomics_gfx12<0x046, "flat_atomic_min_u64">; +defm FLAT_ATOMIC_SMAX_X2 : VFLAT_Real_Atomics_gfx12<0x047, "flat_atomic_max_i64">; +defm FLAT_ATOMIC_UMAX_X2 : VFLAT_Real_Atomics_gfx12<0x048, "flat_atomic_max_u64">; +defm FLAT_ATOMIC_AND_X2 : VFLAT_Real_Atomics_gfx12<0x049, "flat_atomic_and_b64">; +defm FLAT_ATOMIC_OR_X2 : VFLAT_Real_Atomics_gfx12<0x04a, "flat_atomic_or_b64">; +defm FLAT_ATOMIC_XOR_X2 : VFLAT_Real_Atomics_gfx12<0x04b, "flat_atomic_xor_b64">; +defm FLAT_ATOMIC_INC_X2 : VFLAT_Real_Atomics_gfx12<0x04c, "flat_atomic_inc_u64">; +defm FLAT_ATOMIC_DEC_X2 : VFLAT_Real_Atomics_gfx12<0x04d, "flat_atomic_dec_u64">; +defm FLAT_ATOMIC_COND_SUB_U32 : VFLAT_Real_Atomics_gfx12<0x050>; +defm FLAT_ATOMIC_FMIN : VFLAT_Real_Atomics_gfx12<0x051, "flat_atomic_min_num_f32", "flat_atomic_min_f32">; +defm FLAT_ATOMIC_FMAX : VFLAT_Real_Atomics_gfx12<0x052, "flat_atomic_max_num_f32", "flat_atomic_max_f32">; defm FLAT_ATOMIC_ADD_F32 : VFLAT_Real_Atomics_gfx12<0x056>; defm FLAT_ATOMIC_PK_ADD_F16 : VFLAT_Real_Atomics_gfx12<0x059>; defm FLAT_ATOMIC_PK_ADD_BF16 : VFLAT_Real_Atomics_gfx12<0x05a>; // ENC_VGLOBAL. -defm GLOBAL_LOAD_U8 : VGLOBAL_Real_AllAddr_gfx12<0x010, "GLOBAL_LOAD_UBYTE", "global_load_u8", true>; -defm GLOBAL_LOAD_I8 : VGLOBAL_Real_AllAddr_gfx12<0x011, "GLOBAL_LOAD_SBYTE", "global_load_i8", true>; -defm GLOBAL_LOAD_U16 : VGLOBAL_Real_AllAddr_gfx12<0x012, "GLOBAL_LOAD_USHORT", "global_load_u16", true>; -defm GLOBAL_LOAD_I16 : VGLOBAL_Real_AllAddr_gfx12<0x013, "GLOBAL_LOAD_SSHORT", "global_load_i16", true>; -defm GLOBAL_LOAD_B32 : VGLOBAL_Real_AllAddr_gfx12<0x014, "GLOBAL_LOAD_DWORD", "global_load_b32", true>; -defm GLOBAL_LOAD_B64 : VGLOBAL_Real_AllAddr_gfx12<0x015, "GLOBAL_LOAD_DWORDX2", "global_load_b64", true>; -defm GLOBAL_LOAD_B96 : VGLOBAL_Real_AllAddr_gfx12<0x016, "GLOBAL_LOAD_DWORDX3", "global_load_b96", true>; -defm GLOBAL_LOAD_B128 : VGLOBAL_Real_AllAddr_gfx12<0x017, "GLOBAL_LOAD_DWORDX4", "global_load_b128", true>; -defm GLOBAL_STORE_B8 : VGLOBAL_Real_AllAddr_gfx12<0x018, "GLOBAL_STORE_BYTE", "global_store_b8", true>; -defm GLOBAL_STORE_B16 : VGLOBAL_Real_AllAddr_gfx12<0x019, "GLOBAL_STORE_SHORT", "global_store_b16", true>; -defm GLOBAL_STORE_B32 : VGLOBAL_Real_AllAddr_gfx12<0x01a, "GLOBAL_STORE_DWORD", "global_store_b32", true>; -defm GLOBAL_STORE_B64 : VGLOBAL_Real_AllAddr_gfx12<0x01b, "GLOBAL_STORE_DWORDX2", "global_store_b64", true>; -defm GLOBAL_STORE_B96 : VGLOBAL_Real_AllAddr_gfx12<0x01c, "GLOBAL_STORE_DWORDX3", "global_store_b96", true>; -defm GLOBAL_STORE_B128 : VGLOBAL_Real_AllAddr_gfx12<0x01d, "GLOBAL_STORE_DWORDX4", "global_store_b128", true>; -defm GLOBAL_LOAD_D16_U8 : VGLOBAL_Real_AllAddr_gfx12<0x01e, "GLOBAL_LOAD_UBYTE_D16">; -defm GLOBAL_LOAD_D16_I8 : VGLOBAL_Real_AllAddr_gfx12<0x01f, "GLOBAL_LOAD_SBYTE_D16">; -defm GLOBAL_LOAD_D16_B16 : VGLOBAL_Real_AllAddr_gfx12<0x020, "GLOBAL_LOAD_SHORT_D16">; -defm GLOBAL_LOAD_D16_HI_U8 : VGLOBAL_Real_AllAddr_gfx12<0x021, "GLOBAL_LOAD_UBYTE_D16_HI">; -defm GLOBAL_LOAD_D16_HI_I8 : VGLOBAL_Real_AllAddr_gfx12<0x022, "GLOBAL_LOAD_SBYTE_D16_HI">; -defm GLOBAL_LOAD_D16_HI_B16 : VGLOBAL_Real_AllAddr_gfx12<0x023, "GLOBAL_LOAD_SHORT_D16_HI">; -defm GLOBAL_STORE_D16_HI_B8 : VGLOBAL_Real_AllAddr_gfx12<0x024, "GLOBAL_STORE_BYTE_D16_HI">; -defm GLOBAL_STORE_D16_HI_B16 : VGLOBAL_Real_AllAddr_gfx12<0x025, "GLOBAL_STORE_SHORT_D16_HI">; -defm GLOBAL_LOAD_ADDTID_B32 : VGLOBAL_Real_AllAddr_gfx12<0x028, "GLOBAL_LOAD_DWORD_ADDTID">; -defm GLOBAL_STORE_ADDTID_B32 : VGLOBAL_Real_AllAddr_gfx12<0x029, "GLOBAL_STORE_DWORD_ADDTID">; - -defm GLOBAL_ATOMIC_SWAP_B32 : VGLOBAL_Real_Atomics_gfx12<0x033, "GLOBAL_ATOMIC_SWAP", "global_atomic_swap_b32", true>; -defm GLOBAL_ATOMIC_CMPSWAP_B32 : VGLOBAL_Real_Atomics_gfx12<0x034, "GLOBAL_ATOMIC_CMPSWAP", "global_atomic_cmpswap_b32", true>; -defm GLOBAL_ATOMIC_ADD_U32 : VGLOBAL_Real_Atomics_gfx12<0x035, "GLOBAL_ATOMIC_ADD", "global_atomic_add_u32", true>; -defm GLOBAL_ATOMIC_SUB_U32 : VGLOBAL_Real_Atomics_gfx12<0x036, "GLOBAL_ATOMIC_SUB", "global_atomic_sub_u32", true>; -defm GLOBAL_ATOMIC_SUB_CLAMP_U32 : VGLOBAL_Real_Atomics_gfx12<0x037, "GLOBAL_ATOMIC_CSUB", "global_atomic_sub_clamp_u32", true, "global_atomic_csub_u32">; -defm GLOBAL_ATOMIC_MIN_I32 : VGLOBAL_Real_Atomics_gfx12<0x038, "GLOBAL_ATOMIC_SMIN", "global_atomic_min_i32", true>; -defm GLOBAL_ATOMIC_MIN_U32 : VGLOBAL_Real_Atomics_gfx12<0x039, "GLOBAL_ATOMIC_UMIN", "global_atomic_min_u32", true>; -defm GLOBAL_ATOMIC_MAX_I32 : VGLOBAL_Real_Atomics_gfx12<0x03a, "GLOBAL_ATOMIC_SMAX", "global_atomic_max_i32", true>; -defm GLOBAL_ATOMIC_MAX_U32 : VGLOBAL_Real_Atomics_gfx12<0x03b, "GLOBAL_ATOMIC_UMAX", "global_atomic_max_u32", true>; -defm GLOBAL_ATOMIC_AND_B32 : VGLOBAL_Real_Atomics_gfx12<0x03c, "GLOBAL_ATOMIC_AND", "global_atomic_and_b32", true>; -defm GLOBAL_ATOMIC_OR_B32 : VGLOBAL_Real_Atomics_gfx12<0x03d, "GLOBAL_ATOMIC_OR", "global_atomic_or_b32", true>; -defm GLOBAL_ATOMIC_XOR_B32 : VGLOBAL_Real_Atomics_gfx12<0x03e, "GLOBAL_ATOMIC_XOR", "global_atomic_xor_b32", true>; -defm GLOBAL_ATOMIC_INC_U32 : VGLOBAL_Real_Atomics_gfx12<0x03f, "GLOBAL_ATOMIC_INC", "global_atomic_inc_u32", true>; -defm GLOBAL_ATOMIC_DEC_U32 : VGLOBAL_Real_Atomics_gfx12<0x040, "GLOBAL_ATOMIC_DEC", "global_atomic_dec_u32", true>; -defm GLOBAL_ATOMIC_SWAP_B64 : VGLOBAL_Real_Atomics_gfx12<0x041, "GLOBAL_ATOMIC_SWAP_X2", "global_atomic_swap_b64", true>; -defm GLOBAL_ATOMIC_CMPSWAP_B64 : VGLOBAL_Real_Atomics_gfx12<0x042, "GLOBAL_ATOMIC_CMPSWAP_X2", "global_atomic_cmpswap_b64", true>; -defm GLOBAL_ATOMIC_ADD_U64 : VGLOBAL_Real_Atomics_gfx12<0x043, "GLOBAL_ATOMIC_ADD_X2", "global_atomic_add_u64", true>; -defm GLOBAL_ATOMIC_SUB_U64 : VGLOBAL_Real_Atomics_gfx12<0x044, "GLOBAL_ATOMIC_SUB_X2", "global_atomic_sub_u64", true>; -defm GLOBAL_ATOMIC_MIN_I64 : VGLOBAL_Real_Atomics_gfx12<0x045, "GLOBAL_ATOMIC_SMIN_X2", "global_atomic_min_i64", true>; -defm GLOBAL_ATOMIC_MIN_U64 : VGLOBAL_Real_Atomics_gfx12<0x046, "GLOBAL_ATOMIC_UMIN_X2", "global_atomic_min_u64", true>; -defm GLOBAL_ATOMIC_MAX_I64 : VGLOBAL_Real_Atomics_gfx12<0x047, "GLOBAL_ATOMIC_SMAX_X2", "global_atomic_max_i64", true>; -defm GLOBAL_ATOMIC_MAX_U64 : VGLOBAL_Real_Atomics_gfx12<0x048, "GLOBAL_ATOMIC_UMAX_X2", "global_atomic_max_u64", true>; -defm GLOBAL_ATOMIC_AND_B64 : VGLOBAL_Real_Atomics_gfx12<0x049, "GLOBAL_ATOMIC_AND_X2", "global_atomic_and_b64", true>; -defm GLOBAL_ATOMIC_OR_B64 : VGLOBAL_Real_Atomics_gfx12<0x04a, "GLOBAL_ATOMIC_OR_X2", "global_atomic_or_b64", true>; -defm GLOBAL_ATOMIC_XOR_B64 : VGLOBAL_Real_Atomics_gfx12<0x04b, "GLOBAL_ATOMIC_XOR_X2", "global_atomic_xor_b64", true>; -defm GLOBAL_ATOMIC_INC_U64 : VGLOBAL_Real_Atomics_gfx12<0x04c, "GLOBAL_ATOMIC_INC_X2", "global_atomic_inc_u64", true>; -defm GLOBAL_ATOMIC_DEC_U64 : VGLOBAL_Real_Atomics_gfx12<0x04d, "GLOBAL_ATOMIC_DEC_X2", "global_atomic_dec_u64", true>; -defm GLOBAL_ATOMIC_COND_SUB_U32 : VGLOBAL_Real_Atomics_gfx12<0x050, "GLOBAL_ATOMIC_COND_SUB_U32", "global_atomic_cond_sub_u32">; -defm GLOBAL_ATOMIC_MIN_NUM_F32 : VGLOBAL_Real_Atomics_gfx12<0x051, "GLOBAL_ATOMIC_FMIN", "global_atomic_min_num_f32", true, "global_atomic_min_f32">; -defm GLOBAL_ATOMIC_MAX_NUM_F32 : VGLOBAL_Real_Atomics_gfx12<0x052, "GLOBAL_ATOMIC_FMAX", "global_atomic_max_num_f32", true, "global_atomic_max_f32">; +defm GLOBAL_LOAD_UBYTE : VGLOBAL_Real_AllAddr_gfx12<0x010, "global_load_u8">; +defm GLOBAL_LOAD_SBYTE : VGLOBAL_Real_AllAddr_gfx12<0x011, "global_load_i8">; +defm GLOBAL_LOAD_USHORT : VGLOBAL_Real_AllAddr_gfx12<0x012, "global_load_u16">; +defm GLOBAL_LOAD_SSHORT : VGLOBAL_Real_AllAddr_gfx12<0x013, "global_load_i16">; +defm GLOBAL_LOAD_DWORD : VGLOBAL_Real_AllAddr_gfx12<0x014, "global_load_b32">; +defm GLOBAL_LOAD_DWORDX2 : VGLOBAL_Real_AllAddr_gfx12<0x015, "global_load_b64">; +defm GLOBAL_LOAD_DWORDX3 : VGLOBAL_Real_AllAddr_gfx12<0x016, "global_load_b96">; +defm GLOBAL_LOAD_DWORDX4 : VGLOBAL_Real_AllAddr_gfx12<0x017, "global_load_b128">; +defm GLOBAL_STORE_BYTE : VGLOBAL_Real_AllAddr_gfx12<0x018, "global_store_b8">; +defm GLOBAL_STORE_SHORT : VGLOBAL_Real_AllAddr_gfx12<0x019, "global_store_b16">; +defm GLOBAL_STORE_DWORD : VGLOBAL_Real_AllAddr_gfx12<0x01a, "global_store_b32">; +defm GLOBAL_STORE_DWORDX2 : VGLOBAL_Real_AllAddr_gfx12<0x01b, "global_store_b64">; +defm GLOBAL_STORE_DWORDX3 : VGLOBAL_Real_AllAddr_gfx12<0x01c, "global_store_b96">; +defm GLOBAL_STORE_DWORDX4 : VGLOBAL_Real_AllAddr_gfx12<0x01d, "global_store_b128">; +defm GLOBAL_LOAD_UBYTE_D16 : VGLOBAL_Real_AllAddr_gfx12<0x01e, "global_load_d16_u8">; +defm GLOBAL_LOAD_SBYTE_D16 : VGLOBAL_Real_AllAddr_gfx12<0x01f, "global_load_d16_i8">; +defm GLOBAL_LOAD_SHORT_D16 : VGLOBAL_Real_AllAddr_gfx12<0x020, "global_load_d16_b16">; +defm GLOBAL_LOAD_UBYTE_D16_HI : VGLOBAL_Real_AllAddr_gfx12<0x021, "global_load_d16_hi_u8">; +defm GLOBAL_LOAD_SBYTE_D16_HI : VGLOBAL_Real_AllAddr_gfx12<0x022, "global_load_d16_hi_i8">; +defm GLOBAL_LOAD_SHORT_D16_HI : VGLOBAL_Real_AllAddr_gfx12<0x023, "global_load_d16_hi_b16">; +defm GLOBAL_STORE_BYTE_D16_HI : VGLOBAL_Real_AllAddr_gfx12<0x024, "global_store_d16_hi_b8">; +defm GLOBAL_STORE_SHORT_D16_HI : VGLOBAL_Real_AllAddr_gfx12<0x025, "global_store_d16_hi_b16">; +defm GLOBAL_LOAD_DWORD_ADDTID : VGLOBAL_Real_AllAddr_gfx12<0x028, "global_load_addtid_b32">; +defm GLOBAL_STORE_DWORD_ADDTID : VGLOBAL_Real_AllAddr_gfx12<0x029, "global_store_addtid_b32">; + +defm GLOBAL_ATOMIC_SWAP : VGLOBAL_Real_Atomics_gfx12<0x033, "global_atomic_swap_b32">; +defm GLOBAL_ATOMIC_CMPSWAP : VGLOBAL_Real_Atomics_gfx12<0x034, "global_atomic_cmpswap_b32">; +defm GLOBAL_ATOMIC_ADD : VGLOBAL_Real_Atomics_gfx12<0x035, "global_atomic_add_u32">; +defm GLOBAL_ATOMIC_SUB : VGLOBAL_Real_Atomics_gfx12<0x036, "global_atomic_sub_u32">; +defm GLOBAL_ATOMIC_CSUB : VGLOBAL_Real_Atomics_gfx12<0x037, "global_atomic_sub_clamp_u32", "global_atomic_csub_u32">; +defm GLOBAL_ATOMIC_SMIN : VGLOBAL_Real_Atomics_gfx12<0x038, "global_atomic_min_i32">; +defm GLOBAL_ATOMIC_UMIN : VGLOBAL_Real_Atomics_gfx12<0x039, "global_atomic_min_u32">; +defm GLOBAL_ATOMIC_SMAX : VGLOBAL_Real_Atomics_gfx12<0x03a, "global_atomic_max_i32">; +defm GLOBAL_ATOMIC_UMAX : VGLOBAL_Real_Atomics_gfx12<0x03b, "global_atomic_max_u32">; +defm GLOBAL_ATOMIC_AND : VGLOBAL_Real_Atomics_gfx12<0x03c, "global_atomic_and_b32">; +defm GLOBAL_ATOMIC_OR : VGLOBAL_Real_Atomics_gfx12<0x03d, "global_atomic_or_b32">; +defm GLOBAL_ATOMIC_XOR : VGLOBAL_Real_Atomics_gfx12<0x03e, "global_atomic_xor_b32">; +defm GLOBAL_ATOMIC_INC : VGLOBAL_Real_Atomics_gfx12<0x03f, "global_atomic_inc_u32">; +defm GLOBAL_ATOMIC_DEC : VGLOBAL_Real_Atomics_gfx12<0x040, "global_atomic_dec_u32">; +defm GLOBAL_ATOMIC_SWAP_X2 : VGLOBAL_Real_Atomics_gfx12<0x041, "global_atomic_swap_b64">; +defm GLOBAL_ATOMIC_CMPSWAP_X2 : VGLOBAL_Real_Atomics_gfx12<0x042, "global_atomic_cmpswap_b64">; +defm GLOBAL_ATOMIC_ADD_X2 : VGLOBAL_Real_Atomics_gfx12<0x043, "global_atomic_add_u64">; +defm GLOBAL_ATOMIC_SUB_X2 : VGLOBAL_Real_Atomics_gfx12<0x044, "global_atomic_sub_u64">; +defm GLOBAL_ATOMIC_SMIN_X2 : VGLOBAL_Real_Atomics_gfx12<0x045, "global_atomic_min_i64">; +defm GLOBAL_ATOMIC_UMIN_X2 : VGLOBAL_Real_Atomics_gfx12<0x046, "global_atomic_min_u64">; +defm GLOBAL_ATOMIC_SMAX_X2 : VGLOBAL_Real_Atomics_gfx12<0x047, "global_atomic_max_i64">; +defm GLOBAL_ATOMIC_UMAX_X2 : VGLOBAL_Real_Atomics_gfx12<0x048, "global_atomic_max_u64">; +defm GLOBAL_ATOMIC_AND_X2 : VGLOBAL_Real_Atomics_gfx12<0x049, "global_atomic_and_b64">; +defm GLOBAL_ATOMIC_OR_X2 : VGLOBAL_Real_Atomics_gfx12<0x04a, "global_atomic_or_b64">; +defm GLOBAL_ATOMIC_XOR_X2 : VGLOBAL_Real_Atomics_gfx12<0x04b, "global_atomic_xor_b64">; +defm GLOBAL_ATOMIC_INC_X2 : VGLOBAL_Real_Atomics_gfx12<0x04c, "global_atomic_inc_u64">; +defm GLOBAL_ATOMIC_DEC_X2 : VGLOBAL_Real_Atomics_gfx12<0x04d, "global_atomic_dec_u64">; +defm GLOBAL_ATOMIC_COND_SUB_U32 : VGLOBAL_Real_Atomics_gfx12<0x050>; +defm GLOBAL_ATOMIC_FMIN : VGLOBAL_Real_Atomics_gfx12<0x051, "global_atomic_min_num_f32", "global_atomic_min_f32">; +defm GLOBAL_ATOMIC_FMAX : VGLOBAL_Real_Atomics_gfx12<0x052, "global_atomic_max_num_f32", "global_atomic_max_f32">; defm GLOBAL_ATOMIC_ADD_F32 : VGLOBAL_Real_Atomics_gfx12<0x056>; -let DecoderNamespace = "GFX12" in { - defm GLOBAL_LOAD_TR_B128_w32 : VGLOBAL_Real_AllAddr_gfx12<0x057, "GLOBAL_LOAD_TR_B128_w32", "global_load_tr_b128">; - defm GLOBAL_LOAD_TR_B64_w32 : VGLOBAL_Real_AllAddr_gfx12<0x058, "GLOBAL_LOAD_TR_B64_w32", "global_load_tr_b64">; -} +defm GLOBAL_LOAD_TR_B128_w32 : VGLOBAL_Real_AllAddr_gfx12<0x057>; +defm GLOBAL_LOAD_TR_B64_w32 : VGLOBAL_Real_AllAddr_gfx12<0x058>; -let DecoderNamespace = "GFX12W64" in { - defm GLOBAL_LOAD_TR_B128_w64 : VGLOBAL_Real_AllAddr_gfx12<0x057, "GLOBAL_LOAD_TR_B128_w64", "global_load_tr_b128">; - defm GLOBAL_LOAD_TR_B64_w64 : VGLOBAL_Real_AllAddr_gfx12<0x058, "GLOBAL_LOAD_TR_B64_w64", "global_load_tr_b64">; -} +defm GLOBAL_LOAD_TR_B128_w64 : VGLOBAL_Real_AllAddr_gfx12_w64<0x057>; +defm GLOBAL_LOAD_TR_B64_w64 : VGLOBAL_Real_AllAddr_gfx12_w64<0x058>; defm GLOBAL_ATOMIC_ORDERED_ADD_B64 : VGLOBAL_Real_Atomics_gfx12<0x073>; defm GLOBAL_ATOMIC_PK_ADD_F16 : VGLOBAL_Real_Atomics_gfx12<0x059>; @@ -2765,25 +2725,25 @@ defm GLOBAL_WB : VFLAT_Real_Base_gfx12<0x02c>; defm GLOBAL_WBINV : VFLAT_Real_Base_gfx12<0x04f>; // ENC_VSCRATCH. -defm SCRATCH_LOAD_U8 : VSCRATCH_Real_AllAddr_gfx12<0x10, "SCRATCH_LOAD_UBYTE", "scratch_load_u8", true>; -defm SCRATCH_LOAD_I8 : VSCRATCH_Real_AllAddr_gfx12<0x11, "SCRATCH_LOAD_SBYTE", "scratch_load_i8", true>; -defm SCRATCH_LOAD_U16 : VSCRATCH_Real_AllAddr_gfx12<0x12, "SCRATCH_LOAD_USHORT", "scratch_load_u16", true>; -defm SCRATCH_LOAD_I16 : VSCRATCH_Real_AllAddr_gfx12<0x13, "SCRATCH_LOAD_SSHORT", "scratch_load_i16", true>; -defm SCRATCH_LOAD_B32 : VSCRATCH_Real_AllAddr_gfx12<0x14, "SCRATCH_LOAD_DWORD", "scratch_load_b32", true>; -defm SCRATCH_LOAD_B64 : VSCRATCH_Real_AllAddr_gfx12<0x15, "SCRATCH_LOAD_DWORDX2", "scratch_load_b64", true>; -defm SCRATCH_LOAD_B96 : VSCRATCH_Real_AllAddr_gfx12<0x16, "SCRATCH_LOAD_DWORDX3", "scratch_load_b96", true>; -defm SCRATCH_LOAD_B128 : VSCRATCH_Real_AllAddr_gfx12<0x17, "SCRATCH_LOAD_DWORDX4", "scratch_load_b128", true>; -defm SCRATCH_STORE_B8 : VSCRATCH_Real_AllAddr_gfx12<0x18, "SCRATCH_STORE_BYTE", "scratch_store_b8", true>; -defm SCRATCH_STORE_B16 : VSCRATCH_Real_AllAddr_gfx12<0x19, "SCRATCH_STORE_SHORT", "scratch_store_b16", true>; -defm SCRATCH_STORE_B32 : VSCRATCH_Real_AllAddr_gfx12<0x1a, "SCRATCH_STORE_DWORD", "scratch_store_b32", true>; -defm SCRATCH_STORE_B64 : VSCRATCH_Real_AllAddr_gfx12<0x1b, "SCRATCH_STORE_DWORDX2", "scratch_store_b64", true>; -defm SCRATCH_STORE_B96 : VSCRATCH_Real_AllAddr_gfx12<0x1c, "SCRATCH_STORE_DWORDX3", "scratch_store_b96", true>; -defm SCRATCH_STORE_B128 : VSCRATCH_Real_AllAddr_gfx12<0x1d, "SCRATCH_STORE_DWORDX4", "scratch_store_b128", true>; -defm SCRATCH_LOAD_D16_U8 : VSCRATCH_Real_AllAddr_gfx12<0x1e, "SCRATCH_LOAD_UBYTE_D16">; -defm SCRATCH_LOAD_D16_I8 : VSCRATCH_Real_AllAddr_gfx12<0x1f, "SCRATCH_LOAD_SBYTE_D16">; -defm SCRATCH_LOAD_D16_B16 : VSCRATCH_Real_AllAddr_gfx12<0x20, "SCRATCH_LOAD_SHORT_D16">; -defm SCRATCH_LOAD_D16_HI_U8 : VSCRATCH_Real_AllAddr_gfx12<0x21, "SCRATCH_LOAD_UBYTE_D16_HI">; -defm SCRATCH_LOAD_D16_HI_I8 : VSCRATCH_Real_AllAddr_gfx12<0x22, "SCRATCH_LOAD_SBYTE_D16_HI">; -defm SCRATCH_LOAD_D16_HI_B16 : VSCRATCH_Real_AllAddr_gfx12<0x23, "SCRATCH_LOAD_SHORT_D16_HI">; -defm SCRATCH_STORE_D16_HI_B8 : VSCRATCH_Real_AllAddr_gfx12<0x24, "SCRATCH_STORE_BYTE_D16_HI">; -defm SCRATCH_STORE_D16_HI_B16 : VSCRATCH_Real_AllAddr_gfx12<0x25, "SCRATCH_STORE_SHORT_D16_HI">; +defm SCRATCH_LOAD_UBYTE : VSCRATCH_Real_AllAddr_gfx12<0x10, "scratch_load_u8">; +defm SCRATCH_LOAD_SBYTE : VSCRATCH_Real_AllAddr_gfx12<0x11, "scratch_load_i8">; +defm SCRATCH_LOAD_USHORT : VSCRATCH_Real_AllAddr_gfx12<0x12, "scratch_load_u16">; +defm SCRATCH_LOAD_SSHORT : VSCRATCH_Real_AllAddr_gfx12<0x13, "scratch_load_i16">; +defm SCRATCH_LOAD_DWORD : VSCRATCH_Real_AllAddr_gfx12<0x14, "scratch_load_b32">; +defm SCRATCH_LOAD_DWORDX2 : VSCRATCH_Real_AllAddr_gfx12<0x15, "scratch_load_b64">; +defm SCRATCH_LOAD_DWORDX3 : VSCRATCH_Real_AllAddr_gfx12<0x16, "scratch_load_b96">; +defm SCRATCH_LOAD_DWORDX4 : VSCRATCH_Real_AllAddr_gfx12<0x17, "scratch_load_b128">; +defm SCRATCH_STORE_BYTE : VSCRATCH_Real_AllAddr_gfx12<0x18, "scratch_store_b8">; +defm SCRATCH_STORE_SHORT : VSCRATCH_Real_AllAddr_gfx12<0x19, "scratch_store_b16">; +defm SCRATCH_STORE_DWORD : VSCRATCH_Real_AllAddr_gfx12<0x1a, "scratch_store_b32">; +defm SCRATCH_STORE_DWORDX2 : VSCRATCH_Real_AllAddr_gfx12<0x1b, "scratch_store_b64">; +defm SCRATCH_STORE_DWORDX3 : VSCRATCH_Real_AllAddr_gfx12<0x1c, "scratch_store_b96">; +defm SCRATCH_STORE_DWORDX4 : VSCRATCH_Real_AllAddr_gfx12<0x1d, "scratch_store_b128">; +defm SCRATCH_LOAD_UBYTE_D16 : VSCRATCH_Real_AllAddr_gfx12<0x1e, "scratch_load_d16_u8">; +defm SCRATCH_LOAD_SBYTE_D16 : VSCRATCH_Real_AllAddr_gfx12<0x1f, "scratch_load_d16_i8">; +defm SCRATCH_LOAD_SHORT_D16 : VSCRATCH_Real_AllAddr_gfx12<0x20, "scratch_load_d16_b16">; +defm SCRATCH_LOAD_UBYTE_D16_HI : VSCRATCH_Real_AllAddr_gfx12<0x21, "scratch_load_d16_hi_u8">; +defm SCRATCH_LOAD_SBYTE_D16_HI : VSCRATCH_Real_AllAddr_gfx12<0x22, "scratch_load_d16_hi_i8">; +defm SCRATCH_LOAD_SHORT_D16_HI : VSCRATCH_Real_AllAddr_gfx12<0x23, "scratch_load_d16_hi_b16">; +defm SCRATCH_STORE_BYTE_D16_HI : VSCRATCH_Real_AllAddr_gfx12<0x24, "scratch_store_d16_hi_b8">; +defm SCRATCH_STORE_SHORT_D16_HI : VSCRATCH_Real_AllAddr_gfx12<0x25, "scratch_store_d16_hi_b16">; diff --git a/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp b/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp index e515b729e7d7e891553208f6dc49c5a2fd318036..75766b11ca82299827dbd5ef36c93b9898c86af4 100644 --- a/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp +++ b/llvm/lib/Target/AMDGPU/GCNHazardRecognizer.cpp @@ -2357,6 +2357,9 @@ int GCNHazardRecognizer::checkMAIHazards90A(MachineInstr *MI) { break; } + // Pad neighboring MFMA with noops for better inter-wave performance. + WaitStatesNeeded = std::max(WaitStatesNeeded, checkMFMAPadding(MI)); + return WaitStatesNeeded; } diff --git a/llvm/lib/Target/AMDGPU/GCNSchedStrategy.cpp b/llvm/lib/Target/AMDGPU/GCNSchedStrategy.cpp index 9f419a7fbf6834ff417268f1a29f00db153ae034..94d93390d0916f79fb494d70f4ef98b83722a1c7 100644 --- a/llvm/lib/Target/AMDGPU/GCNSchedStrategy.cpp +++ b/llvm/lib/Target/AMDGPU/GCNSchedStrategy.cpp @@ -973,12 +973,17 @@ void GCNSchedStage::checkScheduling() { LLVM_DEBUG(dbgs() << "Occupancy lowered for the function to " << DAG.MinOccupancy << ".\n"); } - + // The maximum number of arch VGPR on non-unified register file, or the + // maximum VGPR + AGPR in the unified register file case. unsigned MaxVGPRs = ST.getMaxNumVGPRs(MF); + // The maximum number of arch VGPR for both unified and non-unified register + // file. + unsigned MaxArchVGPRs = std::min(MaxVGPRs, ST.getAddressableNumArchVGPRs()); unsigned MaxSGPRs = ST.getMaxNumSGPRs(MF); - if (PressureAfter.getVGPRNum(false) > MaxVGPRs || - PressureAfter.getAGPRNum() > MaxVGPRs || + if (PressureAfter.getVGPRNum(ST.hasGFX90AInsts()) > MaxVGPRs || + PressureAfter.getVGPRNum(false) > MaxArchVGPRs || + PressureAfter.getAGPRNum() > MaxArchVGPRs || PressureAfter.getSGPRNum() > MaxSGPRs) { DAG.RescheduleRegions[RegionIdx] = true; DAG.RegionsWithHighRP[RegionIdx] = true; diff --git a/llvm/lib/Target/AMDGPU/GCNSubtarget.h b/llvm/lib/Target/AMDGPU/GCNSubtarget.h index ca51da659c33116ae0b96233d2ede077a9f7fe98..4da10beabe3162f830c6022b9bd36a8a0ce03061 100644 --- a/llvm/lib/Target/AMDGPU/GCNSubtarget.h +++ b/llvm/lib/Target/AMDGPU/GCNSubtarget.h @@ -223,7 +223,7 @@ protected: bool HasImageStoreD16Bug = false; bool HasImageGather4D16Bug = false; bool HasMSAALoadDstSelBug = false; - bool HasGFX11FullVGPRs = false; + bool Has1_5xVGPRs = false; bool HasMADIntraFwdBug = false; bool HasVOPDInsts = false; bool HasVALUTransUseHazard = false; @@ -1202,7 +1202,7 @@ public: /// target. bool hasNullExportTarget() const { return !GFX11Insts; } - bool hasGFX11FullVGPRs() const { return HasGFX11FullVGPRs; } + bool has1_5xVGPRs() const { return Has1_5xVGPRs; } bool hasVOPDInsts() const { return HasVOPDInsts; } diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCExpr.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCExpr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4578c33d92dce1aab9ae7e35d724c07e81b59270 --- /dev/null +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCExpr.cpp @@ -0,0 +1,115 @@ +//===- AMDGPUMCExpr.cpp - AMDGPU specific MC expression classes -----------===// +// +// 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 "AMDGPUMCExpr.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/raw_ostream.h" +#include <optional> + +using namespace llvm; + +AMDGPUVariadicMCExpr::AMDGPUVariadicMCExpr(VariadicKind Kind, + ArrayRef<const MCExpr *> Args, + MCContext &Ctx) + : Kind(Kind), Ctx(Ctx) { + assert(Args.size() >= 1 && "Needs a minimum of one expression."); + assert(Kind != AGVK_None && + "Cannot construct AMDGPUVariadicMCExpr of kind none."); + + // Allocating the variadic arguments through the same allocation mechanism + // that the object itself is allocated with so they end up in the same memory. + // + // Will result in an asan failure if allocated on the heap through standard + // allocation (e.g., through SmallVector's grow). + RawArgs = static_cast<const MCExpr **>( + Ctx.allocate(sizeof(const MCExpr *) * Args.size())); + std::uninitialized_copy(Args.begin(), Args.end(), RawArgs); + this->Args = ArrayRef<const MCExpr *>(RawArgs, Args.size()); +} + +AMDGPUVariadicMCExpr::~AMDGPUVariadicMCExpr() { Ctx.deallocate(RawArgs); } + +const AMDGPUVariadicMCExpr * +AMDGPUVariadicMCExpr::create(VariadicKind Kind, ArrayRef<const MCExpr *> Args, + MCContext &Ctx) { + return new (Ctx) AMDGPUVariadicMCExpr(Kind, Args, Ctx); +} + +const MCExpr *AMDGPUVariadicMCExpr::getSubExpr(size_t Index) const { + assert(Index < Args.size() && + "Indexing out of bounds AMDGPUVariadicMCExpr sub-expr"); + return Args[Index]; +} + +void AMDGPUVariadicMCExpr::printImpl(raw_ostream &OS, + const MCAsmInfo *MAI) const { + switch (Kind) { + default: + llvm_unreachable("Unknown AMDGPUVariadicMCExpr kind."); + case AGVK_Or: + OS << "or("; + break; + case AGVK_Max: + OS << "max("; + break; + } + for (auto It = Args.begin(); It != Args.end(); ++It) { + (*It)->print(OS, MAI, /*InParens=*/false); + if ((It + 1) != Args.end()) + OS << ", "; + } + OS << ')'; +} + +static int64_t op(AMDGPUVariadicMCExpr::VariadicKind Kind, int64_t Arg1, + int64_t Arg2) { + switch (Kind) { + default: + llvm_unreachable("Unknown AMDGPUVariadicMCExpr kind."); + case AMDGPUVariadicMCExpr::AGVK_Max: + return std::max(Arg1, Arg2); + case AMDGPUVariadicMCExpr::AGVK_Or: + return Arg1 | Arg2; + } +} + +bool AMDGPUVariadicMCExpr::evaluateAsRelocatableImpl( + MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const { + std::optional<int64_t> Total; + + for (const MCExpr *Arg : Args) { + MCValue ArgRes; + if (!Arg->evaluateAsRelocatable(ArgRes, Layout, Fixup) || + !ArgRes.isAbsolute()) + return false; + + if (!Total.has_value()) + Total = ArgRes.getConstant(); + Total = op(Kind, *Total, ArgRes.getConstant()); + } + + Res = MCValue::get(*Total); + return true; +} + +void AMDGPUVariadicMCExpr::visitUsedExpr(MCStreamer &Streamer) const { + for (const MCExpr *Arg : Args) + Streamer.visitUsedExpr(*Arg); +} + +MCFragment *AMDGPUVariadicMCExpr::findAssociatedFragment() const { + for (const MCExpr *Arg : Args) { + if (Arg->findAssociatedFragment()) + return Arg->findAssociatedFragment(); + } + return nullptr; +} diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCExpr.h b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCExpr.h new file mode 100644 index 0000000000000000000000000000000000000000..238e0dea791b24d7344581e24d77e3eb909f4b58 --- /dev/null +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCExpr.h @@ -0,0 +1,72 @@ +//===- AMDGPUMCExpr.h - AMDGPU specific MC expression classes ---*- 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_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCEXPR_H +#define LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCEXPR_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/MC/MCExpr.h" + +namespace llvm { + +/// AMDGPU target specific variadic MCExpr operations. +/// +/// Takes in a minimum of 1 argument to be used with an operation. The supported +/// operations are: +/// - (bitwise) or +/// - max +/// +/// \note If the 'or'/'max' operations are provided only a single argument, the +/// operation will act as a no-op and simply resolve as the provided argument. +/// +class AMDGPUVariadicMCExpr : public MCTargetExpr { +public: + enum VariadicKind { AGVK_None, AGVK_Or, AGVK_Max }; + +private: + VariadicKind Kind; + MCContext &Ctx; + const MCExpr **RawArgs; + ArrayRef<const MCExpr *> Args; + + AMDGPUVariadicMCExpr(VariadicKind Kind, ArrayRef<const MCExpr *> Args, + MCContext &Ctx); + ~AMDGPUVariadicMCExpr(); + +public: + static const AMDGPUVariadicMCExpr * + create(VariadicKind Kind, ArrayRef<const MCExpr *> Args, MCContext &Ctx); + + static const AMDGPUVariadicMCExpr *createOr(ArrayRef<const MCExpr *> Args, + MCContext &Ctx) { + return create(VariadicKind::AGVK_Or, Args, Ctx); + } + + static const AMDGPUVariadicMCExpr *createMax(ArrayRef<const MCExpr *> Args, + MCContext &Ctx) { + return create(VariadicKind::AGVK_Max, Args, Ctx); + } + + VariadicKind getKind() const { return Kind; } + const MCExpr *getSubExpr(size_t Index) const; + + void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override; + bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, + const MCFixup *Fixup) const override; + void visitUsedExpr(MCStreamer &Streamer) const override; + MCFragment *findAssociatedFragment() const override; + void fixELFSymbolsInTLSFixups(MCAssembler &) const override{}; + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Target; + } +}; + +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCEXPR_H diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCKernelDescriptor.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCKernelDescriptor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..77e7e30ff5281bddde23461fe3c7ff8fdf60b9d4 --- /dev/null +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCKernelDescriptor.cpp @@ -0,0 +1,98 @@ +//===--- AMDHSAKernelDescriptor.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 +// +//===----------------------------------------------------------------------===// + +#include "AMDGPUMCKernelDescriptor.h" +#include "AMDGPUMCTargetDesc.h" +#include "Utils/AMDGPUBaseInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/TargetParser/TargetParser.h" + +using namespace llvm; +using namespace llvm::AMDGPU; + +MCKernelDescriptor +MCKernelDescriptor::getDefaultAmdhsaKernelDescriptor(const MCSubtargetInfo *STI, + MCContext &Ctx) { + IsaVersion Version = getIsaVersion(STI->getCPU()); + + MCKernelDescriptor KD; + const MCExpr *ZeroMCExpr = MCConstantExpr::create(0, Ctx); + const MCExpr *OneMCExpr = MCConstantExpr::create(1, Ctx); + + KD.group_segment_fixed_size = ZeroMCExpr; + KD.private_segment_fixed_size = ZeroMCExpr; + KD.compute_pgm_rsrc1 = ZeroMCExpr; + KD.compute_pgm_rsrc2 = ZeroMCExpr; + KD.compute_pgm_rsrc3 = ZeroMCExpr; + KD.kernarg_size = ZeroMCExpr; + KD.kernel_code_properties = ZeroMCExpr; + KD.kernarg_preload = ZeroMCExpr; + + MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc1, + MCConstantExpr::create(amdhsa::FLOAT_DENORM_MODE_FLUSH_NONE, Ctx), + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, Ctx); + if (Version.Major < 12) { + MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc1, OneMCExpr, + amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP, Ctx); + MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc1, OneMCExpr, + amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE, Ctx); + } + MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc2, OneMCExpr, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, Ctx); + if (Version.Major >= 10) { + if (STI->getFeatureBits().test(FeatureWavefrontSize32)) + MCKernelDescriptor::bits_set( + KD.kernel_code_properties, OneMCExpr, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32, Ctx); + if (!STI->getFeatureBits().test(FeatureCuMode)) + MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc1, OneMCExpr, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE, Ctx); + + MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc1, OneMCExpr, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED, Ctx); + } + if (AMDGPU::isGFX90A(*STI) && STI->getFeatureBits().test(FeatureTgSplit)) + MCKernelDescriptor::bits_set( + KD.compute_pgm_rsrc3, OneMCExpr, + amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT_SHIFT, + amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT, Ctx); + return KD; +} + +void MCKernelDescriptor::bits_set(const MCExpr *&Dst, const MCExpr *Value, + uint32_t Shift, uint32_t Mask, + MCContext &Ctx) { + auto Sft = MCConstantExpr::create(Shift, Ctx); + auto Msk = MCConstantExpr::create(Mask, Ctx); + Dst = MCBinaryExpr::createAnd(Dst, MCUnaryExpr::createNot(Msk, Ctx), Ctx); + Dst = MCBinaryExpr::createOr(Dst, MCBinaryExpr::createShl(Value, Sft, Ctx), + Ctx); +} + +const MCExpr *MCKernelDescriptor::bits_get(const MCExpr *Src, uint32_t Shift, + uint32_t Mask, MCContext &Ctx) { + auto Sft = MCConstantExpr::create(Shift, Ctx); + auto Msk = MCConstantExpr::create(Mask, Ctx); + return MCBinaryExpr::createLShr(MCBinaryExpr::createAnd(Src, Msk, Ctx), Sft, + Ctx); +} diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCKernelDescriptor.h b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCKernelDescriptor.h new file mode 100644 index 0000000000000000000000000000000000000000..26958ac8b9ee17f24dbd880b36dce89cbe00a59b --- /dev/null +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCKernelDescriptor.h @@ -0,0 +1,54 @@ +//===--- AMDGPUMCKernelDescriptor.h ---------------------------*- C++ -*---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file +/// AMDHSA kernel descriptor MCExpr struct for use in MC layer. Uses +/// AMDHSAKernelDescriptor.h for sizes and constants. +/// +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCKERNELDESCRIPTOR_H +#define LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCKERNELDESCRIPTOR_H + +#include "llvm/Support/AMDHSAKernelDescriptor.h" + +namespace llvm { +class MCExpr; +class MCContext; +class MCSubtargetInfo; +namespace AMDGPU { + +struct MCKernelDescriptor { + const MCExpr *group_segment_fixed_size = nullptr; + const MCExpr *private_segment_fixed_size = nullptr; + const MCExpr *kernarg_size = nullptr; + const MCExpr *compute_pgm_rsrc3 = nullptr; + const MCExpr *compute_pgm_rsrc1 = nullptr; + const MCExpr *compute_pgm_rsrc2 = nullptr; + const MCExpr *kernel_code_properties = nullptr; + const MCExpr *kernarg_preload = nullptr; + + static MCKernelDescriptor + getDefaultAmdhsaKernelDescriptor(const MCSubtargetInfo *STI, MCContext &Ctx); + // MCExpr for: + // Dst = Dst & ~Mask + // Dst = Dst | (Value << Shift) + static void bits_set(const MCExpr *&Dst, const MCExpr *Value, uint32_t Shift, + uint32_t Mask, MCContext &Ctx); + + // MCExpr for: + // return (Src & Mask) >> Shift + static const MCExpr *bits_get(const MCExpr *Src, uint32_t Shift, + uint32_t Mask, MCContext &Ctx); +}; + +} // end namespace AMDGPU +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_AMDGPU_MCTARGETDESC_AMDGPUMCKERNELDESCRIPTOR_H diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp index 4742b0b3e52ecf6d59920941bf7d101753b827fd..02fe7be06280e115512fce979f55938838e02015 100644 --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "AMDGPUTargetStreamer.h" +#include "AMDGPUMCKernelDescriptor.h" #include "AMDGPUPTNote.h" #include "AMDKernelCodeT.h" #include "Utils/AMDGPUBaseInfo.h" @@ -283,6 +284,15 @@ bool AMDGPUTargetAsmStreamer::EmitHSAMetadata( return true; } +bool AMDGPUTargetAsmStreamer::EmitKernargPreloadHeader( + const MCSubtargetInfo &STI, bool TrapEnabled) { + OS << (TrapEnabled ? "\ts_trap 2" : "\ts_endpgm") + << " ; Kernarg preload header. Trap with incompatible firmware that " + "doesn't support preloading kernel arguments.\n"; + OS << "\t.fill 63, 4, 0xbf800000 ; s_nop 0\n"; + return true; +} + bool AMDGPUTargetAsmStreamer::EmitCodeEnd(const MCSubtargetInfo &STI) { const uint32_t Encoded_s_code_end = 0xbf9f0000; const uint32_t Encoded_s_nop = 0xbf800000; @@ -307,94 +317,142 @@ bool AMDGPUTargetAsmStreamer::EmitCodeEnd(const MCSubtargetInfo &STI) { void AMDGPUTargetAsmStreamer::EmitAmdhsaKernelDescriptor( const MCSubtargetInfo &STI, StringRef KernelName, - const amdhsa::kernel_descriptor_t &KD, uint64_t NextVGPR, uint64_t NextSGPR, + const MCKernelDescriptor &KD, uint64_t NextVGPR, uint64_t NextSGPR, bool ReserveVCC, bool ReserveFlatScr) { IsaVersion IVersion = getIsaVersion(STI.getCPU()); + const MCAsmInfo *MAI = getContext().getAsmInfo(); OS << "\t.amdhsa_kernel " << KernelName << '\n'; -#define PRINT_FIELD(STREAM, DIRECTIVE, KERNEL_DESC, MEMBER_NAME, FIELD_NAME) \ - STREAM << "\t\t" << DIRECTIVE << " " \ - << AMDHSA_BITS_GET(KERNEL_DESC.MEMBER_NAME, FIELD_NAME) << '\n'; - - OS << "\t\t.amdhsa_group_segment_fixed_size " << KD.group_segment_fixed_size - << '\n'; - OS << "\t\t.amdhsa_private_segment_fixed_size " - << KD.private_segment_fixed_size << '\n'; - OS << "\t\t.amdhsa_kernarg_size " << KD.kernarg_size << '\n'; - - PRINT_FIELD(OS, ".amdhsa_user_sgpr_count", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_USER_SGPR_COUNT); + auto PrintField = [&](const MCExpr *Expr, uint32_t Shift, uint32_t Mask, + StringRef Directive) { + int64_t IVal; + OS << "\t\t" << Directive << ' '; + const MCExpr *pgm_rsrc1_bits = + MCKernelDescriptor::bits_get(Expr, Shift, Mask, getContext()); + if (pgm_rsrc1_bits->evaluateAsAbsolute(IVal)) + OS << static_cast<uint64_t>(IVal); + else + pgm_rsrc1_bits->print(OS, MAI); + OS << '\n'; + }; + + OS << "\t\t.amdhsa_group_segment_fixed_size "; + KD.group_segment_fixed_size->print(OS, MAI); + OS << '\n'; + + OS << "\t\t.amdhsa_private_segment_fixed_size "; + KD.private_segment_fixed_size->print(OS, MAI); + OS << '\n'; + + OS << "\t\t.amdhsa_kernarg_size "; + KD.kernarg_size->print(OS, MAI); + OS << '\n'; + + PrintField( + KD.compute_pgm_rsrc2, amdhsa::COMPUTE_PGM_RSRC2_USER_SGPR_COUNT_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_USER_SGPR_COUNT, ".amdhsa_user_sgpr_count"); if (!hasArchitectedFlatScratch(STI)) - PRINT_FIELD( - OS, ".amdhsa_user_sgpr_private_segment_buffer", KD, - kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER); - PRINT_FIELD(OS, ".amdhsa_user_sgpr_dispatch_ptr", KD, - kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR); - PRINT_FIELD(OS, ".amdhsa_user_sgpr_queue_ptr", KD, - kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR); - PRINT_FIELD(OS, ".amdhsa_user_sgpr_kernarg_segment_ptr", KD, - kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR); - PRINT_FIELD(OS, ".amdhsa_user_sgpr_dispatch_id", KD, - kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID); + PrintField( + KD.kernel_code_properties, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER, + ".amdhsa_user_sgpr_private_segment_buffer"); + PrintField(KD.kernel_code_properties, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR, + ".amdhsa_user_sgpr_dispatch_ptr"); + PrintField(KD.kernel_code_properties, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR, + ".amdhsa_user_sgpr_queue_ptr"); + PrintField(KD.kernel_code_properties, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR, + ".amdhsa_user_sgpr_kernarg_segment_ptr"); + PrintField(KD.kernel_code_properties, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID, + ".amdhsa_user_sgpr_dispatch_id"); if (!hasArchitectedFlatScratch(STI)) - PRINT_FIELD(OS, ".amdhsa_user_sgpr_flat_scratch_init", KD, - kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT); + PrintField(KD.kernel_code_properties, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT, + ".amdhsa_user_sgpr_flat_scratch_init"); if (hasKernargPreload(STI)) { - PRINT_FIELD(OS, ".amdhsa_user_sgpr_kernarg_preload_length ", KD, - kernarg_preload, amdhsa::KERNARG_PRELOAD_SPEC_LENGTH); - PRINT_FIELD(OS, ".amdhsa_user_sgpr_kernarg_preload_offset ", KD, - kernarg_preload, amdhsa::KERNARG_PRELOAD_SPEC_OFFSET); + PrintField(KD.kernarg_preload, amdhsa::KERNARG_PRELOAD_SPEC_LENGTH_SHIFT, + amdhsa::KERNARG_PRELOAD_SPEC_LENGTH, + ".amdhsa_user_sgpr_kernarg_preload_length"); + PrintField(KD.kernarg_preload, amdhsa::KERNARG_PRELOAD_SPEC_OFFSET_SHIFT, + amdhsa::KERNARG_PRELOAD_SPEC_OFFSET, + ".amdhsa_user_sgpr_kernarg_preload_offset"); } - PRINT_FIELD(OS, ".amdhsa_user_sgpr_private_segment_size", KD, - kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE); + PrintField( + KD.kernel_code_properties, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE, + ".amdhsa_user_sgpr_private_segment_size"); if (IVersion.Major >= 10) - PRINT_FIELD(OS, ".amdhsa_wavefront_size32", KD, - kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32); + PrintField(KD.kernel_code_properties, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32, + ".amdhsa_wavefront_size32"); if (CodeObjectVersion >= AMDGPU::AMDHSA_COV5) - PRINT_FIELD(OS, ".amdhsa_uses_dynamic_stack", KD, kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK); - PRINT_FIELD(OS, - (hasArchitectedFlatScratch(STI) - ? ".amdhsa_enable_private_segment" - : ".amdhsa_system_sgpr_private_segment_wavefront_offset"), - KD, compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT); - PRINT_FIELD(OS, ".amdhsa_system_sgpr_workgroup_id_x", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X); - PRINT_FIELD(OS, ".amdhsa_system_sgpr_workgroup_id_y", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y); - PRINT_FIELD(OS, ".amdhsa_system_sgpr_workgroup_id_z", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z); - PRINT_FIELD(OS, ".amdhsa_system_sgpr_workgroup_info", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO); - PRINT_FIELD(OS, ".amdhsa_system_vgpr_workitem_id", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID); + PrintField(KD.kernel_code_properties, + amdhsa::KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK_SHIFT, + amdhsa::KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK, + ".amdhsa_uses_dynamic_stack"); + PrintField(KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, + (hasArchitectedFlatScratch(STI) + ? ".amdhsa_enable_private_segment" + : ".amdhsa_system_sgpr_private_segment_wavefront_offset")); + PrintField(KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, + ".amdhsa_system_sgpr_workgroup_id_x"); + PrintField(KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y, + ".amdhsa_system_sgpr_workgroup_id_y"); + PrintField(KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z, + ".amdhsa_system_sgpr_workgroup_id_z"); + PrintField(KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO, + ".amdhsa_system_sgpr_workgroup_info"); + PrintField(KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID, + ".amdhsa_system_vgpr_workitem_id"); // These directives are required. OS << "\t\t.amdhsa_next_free_vgpr " << NextVGPR << '\n'; OS << "\t\t.amdhsa_next_free_sgpr " << NextSGPR << '\n'; - if (AMDGPU::isGFX90A(STI)) - OS << "\t\t.amdhsa_accum_offset " << - (AMDHSA_BITS_GET(KD.compute_pgm_rsrc3, - amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET) + 1) * 4 - << '\n'; + if (AMDGPU::isGFX90A(STI)) { + // MCExpr equivalent of taking the (accum_offset + 1) * 4. + const MCExpr *accum_bits = MCKernelDescriptor::bits_get( + KD.compute_pgm_rsrc3, + amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET_SHIFT, + amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET, getContext()); + accum_bits = MCBinaryExpr::createAdd( + accum_bits, MCConstantExpr::create(1, getContext()), getContext()); + accum_bits = MCBinaryExpr::createMul( + accum_bits, MCConstantExpr::create(4, getContext()), getContext()); + OS << "\t\t.amdhsa_accum_offset "; + int64_t IVal; + if (accum_bits->evaluateAsAbsolute(IVal)) { + OS << static_cast<uint64_t>(IVal); + } else { + accum_bits->print(OS, MAI); + } + OS << '\n'; + } if (!ReserveVCC) OS << "\t\t.amdhsa_reserve_vcc " << ReserveVCC << '\n'; @@ -411,74 +469,105 @@ void AMDGPUTargetAsmStreamer::EmitAmdhsaKernelDescriptor( break; } - PRINT_FIELD(OS, ".amdhsa_float_round_mode_32", KD, - compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32); - PRINT_FIELD(OS, ".amdhsa_float_round_mode_16_64", KD, - compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64); - PRINT_FIELD(OS, ".amdhsa_float_denorm_mode_32", KD, - compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32); - PRINT_FIELD(OS, ".amdhsa_float_denorm_mode_16_64", KD, - compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64); + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32, + ".amdhsa_float_round_mode_32"); + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64, + ".amdhsa_float_round_mode_16_64"); + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32, + ".amdhsa_float_denorm_mode_32"); + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, + ".amdhsa_float_denorm_mode_16_64"); if (IVersion.Major < 12) { - PRINT_FIELD(OS, ".amdhsa_dx10_clamp", KD, compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP); - PRINT_FIELD(OS, ".amdhsa_ieee_mode", KD, compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE); + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP, + ".amdhsa_dx10_clamp"); + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE, + ".amdhsa_ieee_mode"); + } + if (IVersion.Major >= 9) { + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL, + ".amdhsa_fp16_overflow"); } - if (IVersion.Major >= 9) - PRINT_FIELD(OS, ".amdhsa_fp16_overflow", KD, - compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL); if (AMDGPU::isGFX90A(STI)) - PRINT_FIELD(OS, ".amdhsa_tg_split", KD, - compute_pgm_rsrc3, - amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT); + PrintField(KD.compute_pgm_rsrc3, + amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT_SHIFT, + amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT, ".amdhsa_tg_split"); if (IVersion.Major >= 10) { - PRINT_FIELD(OS, ".amdhsa_workgroup_processor_mode", KD, - compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE); - PRINT_FIELD(OS, ".amdhsa_memory_ordered", KD, - compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED); - PRINT_FIELD(OS, ".amdhsa_forward_progress", KD, - compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS); + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE, + ".amdhsa_workgroup_processor_mode"); + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED, + ".amdhsa_memory_ordered"); + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS, + ".amdhsa_forward_progress"); } if (IVersion.Major >= 10 && IVersion.Major < 12) { - PRINT_FIELD(OS, ".amdhsa_shared_vgpr_count", KD, compute_pgm_rsrc3, - amdhsa::COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT); + PrintField(KD.compute_pgm_rsrc3, + amdhsa::COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT_SHIFT, + amdhsa::COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT, + ".amdhsa_shared_vgpr_count"); + } + if (IVersion.Major >= 12) { + PrintField(KD.compute_pgm_rsrc1, + amdhsa::COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN_SHIFT, + amdhsa::COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN, + ".amdhsa_round_robin_scheduling"); } - if (IVersion.Major >= 12) - PRINT_FIELD(OS, ".amdhsa_round_robin_scheduling", KD, compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN); - PRINT_FIELD( - OS, ".amdhsa_exception_fp_ieee_invalid_op", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION); - PRINT_FIELD(OS, ".amdhsa_exception_fp_denorm_src", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE); - PRINT_FIELD( - OS, ".amdhsa_exception_fp_ieee_div_zero", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO); - PRINT_FIELD(OS, ".amdhsa_exception_fp_ieee_overflow", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW); - PRINT_FIELD(OS, ".amdhsa_exception_fp_ieee_underflow", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW); - PRINT_FIELD(OS, ".amdhsa_exception_fp_ieee_inexact", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT); - PRINT_FIELD(OS, ".amdhsa_exception_int_div_zero", KD, - compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO); -#undef PRINT_FIELD + PrintField( + KD.compute_pgm_rsrc2, + amdhsa:: + COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION, + ".amdhsa_exception_fp_ieee_invalid_op"); + PrintField( + KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE, + ".amdhsa_exception_fp_denorm_src"); + PrintField( + KD.compute_pgm_rsrc2, + amdhsa:: + COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO, + ".amdhsa_exception_fp_ieee_div_zero"); + PrintField( + KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW, + ".amdhsa_exception_fp_ieee_overflow"); + PrintField( + KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW, + ".amdhsa_exception_fp_ieee_underflow"); + PrintField( + KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT, + ".amdhsa_exception_fp_ieee_inexact"); + PrintField( + KD.compute_pgm_rsrc2, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO_SHIFT, + amdhsa::COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO, + ".amdhsa_exception_int_div_zero"); OS << "\t.end_amdhsa_kernel\n"; } @@ -781,18 +870,6 @@ bool AMDGPUTargetELFStreamer::EmitHSAMetadata(msgpack::Document &HSAMetadataDoc, return true; } -bool AMDGPUTargetAsmStreamer::EmitKernargPreloadHeader( - const MCSubtargetInfo &STI, bool TrapEnabled) { - const char *TrapInstr = TrapEnabled ? "\ts_trap 2" : "\ts_endpgm"; - OS << TrapInstr - << " ; Trap with incompatible firmware that doesn't " - "support preloading kernel arguments.\n"; - for (int i = 0; i < 63; ++i) { - OS << "\ts_nop 0\n"; - } - return true; -} - bool AMDGPUTargetELFStreamer::EmitKernargPreloadHeader( const MCSubtargetInfo &STI, bool TrapEnabled) { const uint32_t Encoded_s_nop = 0xbf800000; @@ -835,7 +912,7 @@ bool AMDGPUTargetELFStreamer::EmitCodeEnd(const MCSubtargetInfo &STI) { void AMDGPUTargetELFStreamer::EmitAmdhsaKernelDescriptor( const MCSubtargetInfo &STI, StringRef KernelName, - const amdhsa::kernel_descriptor_t &KernelDescriptor, uint64_t NextVGPR, + const MCKernelDescriptor &KernelDescriptor, uint64_t NextVGPR, uint64_t NextSGPR, bool ReserveVCC, bool ReserveFlatScr) { auto &Streamer = getStreamer(); auto &Context = Streamer.getContext(); @@ -853,7 +930,7 @@ void AMDGPUTargetELFStreamer::EmitAmdhsaKernelDescriptor( // Kernel descriptor symbol's type and size are fixed. KernelDescriptorSymbol->setType(ELF::STT_OBJECT); KernelDescriptorSymbol->setSize( - MCConstantExpr::create(sizeof(KernelDescriptor), Context)); + MCConstantExpr::create(sizeof(amdhsa::kernel_descriptor_t), Context)); // The visibility of the kernel code symbol must be protected or less to allow // static relocations from the kernel descriptor to be used. @@ -861,31 +938,43 @@ void AMDGPUTargetELFStreamer::EmitAmdhsaKernelDescriptor( KernelCodeSymbol->setVisibility(ELF::STV_PROTECTED); Streamer.emitLabel(KernelDescriptorSymbol); - Streamer.emitInt32(KernelDescriptor.group_segment_fixed_size); - Streamer.emitInt32(KernelDescriptor.private_segment_fixed_size); - Streamer.emitInt32(KernelDescriptor.kernarg_size); - - for (uint8_t Res : KernelDescriptor.reserved0) - Streamer.emitInt8(Res); + Streamer.emitValue( + KernelDescriptor.group_segment_fixed_size, + sizeof(amdhsa::kernel_descriptor_t::group_segment_fixed_size)); + Streamer.emitValue( + KernelDescriptor.private_segment_fixed_size, + sizeof(amdhsa::kernel_descriptor_t::private_segment_fixed_size)); + Streamer.emitValue(KernelDescriptor.kernarg_size, + sizeof(amdhsa::kernel_descriptor_t::kernarg_size)); + + for (uint32_t i = 0; i < sizeof(amdhsa::kernel_descriptor_t::reserved0); ++i) + Streamer.emitInt8(0u); // FIXME: Remove the use of VK_AMDGPU_REL64 in the expression below. The // expression being created is: // (start of kernel code) - (start of kernel descriptor) // It implies R_AMDGPU_REL64, but ends up being R_AMDGPU_ABS64. - Streamer.emitValue(MCBinaryExpr::createSub( - MCSymbolRefExpr::create( - KernelCodeSymbol, MCSymbolRefExpr::VK_AMDGPU_REL64, Context), - MCSymbolRefExpr::create( - KernelDescriptorSymbol, MCSymbolRefExpr::VK_None, Context), - Context), - sizeof(KernelDescriptor.kernel_code_entry_byte_offset)); - for (uint8_t Res : KernelDescriptor.reserved1) - Streamer.emitInt8(Res); - Streamer.emitInt32(KernelDescriptor.compute_pgm_rsrc3); - Streamer.emitInt32(KernelDescriptor.compute_pgm_rsrc1); - Streamer.emitInt32(KernelDescriptor.compute_pgm_rsrc2); - Streamer.emitInt16(KernelDescriptor.kernel_code_properties); - Streamer.emitInt16(KernelDescriptor.kernarg_preload); - for (uint8_t Res : KernelDescriptor.reserved3) - Streamer.emitInt8(Res); + Streamer.emitValue( + MCBinaryExpr::createSub( + MCSymbolRefExpr::create(KernelCodeSymbol, + MCSymbolRefExpr::VK_AMDGPU_REL64, Context), + MCSymbolRefExpr::create(KernelDescriptorSymbol, + MCSymbolRefExpr::VK_None, Context), + Context), + sizeof(amdhsa::kernel_descriptor_t::kernel_code_entry_byte_offset)); + for (uint32_t i = 0; i < sizeof(amdhsa::kernel_descriptor_t::reserved1); ++i) + Streamer.emitInt8(0u); + Streamer.emitValue(KernelDescriptor.compute_pgm_rsrc3, + sizeof(amdhsa::kernel_descriptor_t::compute_pgm_rsrc3)); + Streamer.emitValue(KernelDescriptor.compute_pgm_rsrc1, + sizeof(amdhsa::kernel_descriptor_t::compute_pgm_rsrc1)); + Streamer.emitValue(KernelDescriptor.compute_pgm_rsrc2, + sizeof(amdhsa::kernel_descriptor_t::compute_pgm_rsrc2)); + Streamer.emitValue( + KernelDescriptor.kernel_code_properties, + sizeof(amdhsa::kernel_descriptor_t::kernel_code_properties)); + Streamer.emitValue(KernelDescriptor.kernarg_preload, + sizeof(amdhsa::kernel_descriptor_t::kernarg_preload)); + for (uint32_t i = 0; i < sizeof(amdhsa::kernel_descriptor_t::reserved3); ++i) + Streamer.emitInt8(0u); } diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h index 5aa80ff578c6b6f70f42fe1bd4c1ed50d668b7b7..706897a5dc1f4d5598be728580fff76601300135 100644 --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h @@ -22,15 +22,13 @@ class MCSymbol; class formatted_raw_ostream; namespace AMDGPU { + +struct MCKernelDescriptor; namespace HSAMD { struct Metadata; } } // namespace AMDGPU -namespace amdhsa { -struct kernel_descriptor_t; -} - class AMDGPUTargetStreamer : public MCTargetStreamer { AMDGPUPALMetadata PALMetadata; @@ -94,10 +92,11 @@ public: return true; } - virtual void EmitAmdhsaKernelDescriptor( - const MCSubtargetInfo &STI, StringRef KernelName, - const amdhsa::kernel_descriptor_t &KernelDescriptor, uint64_t NextVGPR, - uint64_t NextSGPR, bool ReserveVCC, bool ReserveFlatScr) {} + virtual void + EmitAmdhsaKernelDescriptor(const MCSubtargetInfo &STI, StringRef KernelName, + const AMDGPU::MCKernelDescriptor &KernelDescriptor, + uint64_t NextVGPR, uint64_t NextSGPR, + bool ReserveVCC, bool ReserveFlatScr) {} static StringRef getArchNameFromElfMach(unsigned ElfMach); static unsigned getElfMach(StringRef GPU); @@ -150,10 +149,11 @@ public: bool EmitKernargPreloadHeader(const MCSubtargetInfo &STI, bool TrapEnabled) override; - void EmitAmdhsaKernelDescriptor( - const MCSubtargetInfo &STI, StringRef KernelName, - const amdhsa::kernel_descriptor_t &KernelDescriptor, uint64_t NextVGPR, - uint64_t NextSGPR, bool ReserveVCC, bool ReserveFlatScr) override; + void + EmitAmdhsaKernelDescriptor(const MCSubtargetInfo &STI, StringRef KernelName, + const AMDGPU::MCKernelDescriptor &KernelDescriptor, + uint64_t NextVGPR, uint64_t NextSGPR, + bool ReserveVCC, bool ReserveFlatScr) override; }; class AMDGPUTargetELFStreamer final : public AMDGPUTargetStreamer { @@ -205,10 +205,11 @@ public: bool EmitKernargPreloadHeader(const MCSubtargetInfo &STI, bool TrapEnabled) override; - void EmitAmdhsaKernelDescriptor( - const MCSubtargetInfo &STI, StringRef KernelName, - const amdhsa::kernel_descriptor_t &KernelDescriptor, uint64_t NextVGPR, - uint64_t NextSGPR, bool ReserveVCC, bool ReserveFlatScr) override; + void + EmitAmdhsaKernelDescriptor(const MCSubtargetInfo &STI, StringRef KernelName, + const AMDGPU::MCKernelDescriptor &KernelDescriptor, + uint64_t NextVGPR, uint64_t NextSGPR, + bool ReserveVCC, bool ReserveFlatScr) override; }; } #endif diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/AMDGPU/MCTargetDesc/CMakeLists.txt index 5dc76071b0594e9ff3573b8513f22361c1dd4935..14a02b6d8e36873fc19d8297c38abd1480206421 100644 --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/CMakeLists.txt +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/CMakeLists.txt @@ -5,8 +5,10 @@ add_llvm_component_library(LLVMAMDGPUDesc AMDGPUInstPrinter.cpp AMDGPUMCAsmInfo.cpp AMDGPUMCCodeEmitter.cpp + AMDGPUMCExpr.cpp AMDGPUMCTargetDesc.cpp AMDGPUTargetStreamer.cpp + AMDGPUMCKernelDescriptor.cpp R600InstPrinter.cpp R600MCCodeEmitter.cpp R600MCTargetDesc.cpp diff --git a/llvm/lib/Target/AMDGPU/MIMGInstructions.td b/llvm/lib/Target/AMDGPU/MIMGInstructions.td index 595ef39ce03eb67e8920040b37f87d83e42d362b..23e8be0d5e45ea6793f92dca164e95f87fa76977 100644 --- a/llvm/lib/Target/AMDGPU/MIMGInstructions.td +++ b/llvm/lib/Target/AMDGPU/MIMGInstructions.td @@ -210,6 +210,7 @@ class MIMG <dag outs, string dns = ""> : MIMG_Base <outs, dns> { let hasPostISelHook = 1; + let usesCustomInserter = 1; Instruction Opcode = !cast<Instruction>(NAME); MIMGBaseOpcode BaseOpcode; diff --git a/llvm/lib/Target/AMDGPU/SIDefines.h b/llvm/lib/Target/AMDGPU/SIDefines.h index 0b516bfffb9b66a4a845f23b139c9735aec4ab26..1f0207ddb0ebd2deab98b42a31c184c9a876d66b 100644 --- a/llvm/lib/Target/AMDGPU/SIDefines.h +++ b/llvm/lib/Target/AMDGPU/SIDefines.h @@ -460,7 +460,8 @@ enum Id { // Message ID, width(4) [3:0]. ID_RTN_GET_REALTIME = 131, ID_RTN_SAVE_WAVE = 132, ID_RTN_GET_TBA = 133, - ID_RTN_GET_SE_AID_ID = 134, + ID_RTN_GET_TBA_TO_PC = 134, + ID_RTN_GET_SE_AID_ID = 135, ID_MASK_PreGFX11_ = 0xF, ID_MASK_GFX11Plus_ = 0xFF diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index 9bc1b8eb598f3a0ce737f6aa684812f5413ace77..14948ef9ea8d177dfd85cf7046a9b8267a15cacc 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -1355,7 +1355,8 @@ bool SITargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info, MachineMemOperand::MOVolatile; return true; } - case Intrinsic::amdgcn_global_load_tr: { + case Intrinsic::amdgcn_global_load_tr_b64: + case Intrinsic::amdgcn_global_load_tr_b128: { Info.opc = ISD::INTRINSIC_W_CHAIN; Info.memVT = MVT::getVT(CI.getType()); Info.ptrVal = CI.getOperand(0); @@ -1462,7 +1463,8 @@ bool SITargetLowering::getAddrModeArguments(IntrinsicInst *II, case Intrinsic::amdgcn_global_atomic_fmin: case Intrinsic::amdgcn_global_atomic_fmin_num: case Intrinsic::amdgcn_global_atomic_ordered_add_b64: - case Intrinsic::amdgcn_global_load_tr: + case Intrinsic::amdgcn_global_load_tr_b64: + case Intrinsic::amdgcn_global_load_tr_b128: Ptr = II->getArgOperand(0); break; case Intrinsic::amdgcn_global_load_lds: @@ -3831,9 +3833,6 @@ SDValue SITargetLowering::LowerCall(CallLoweringInfo &CLI, Ops.push_back(DAG.getTargetConstant(0, DL, MVT::i64)); } - if (!IsTailCall) - Ops.push_back(CLI.ConvergenceControlToken); - if (IsTailCall) { // Each tail call may have to adjust the stack by a different amount, so // this information must travel along with the operation for eventual @@ -3860,6 +3859,17 @@ SDValue SITargetLowering::LowerCall(CallLoweringInfo &CLI, if (InGlue.getNode()) Ops.push_back(InGlue); + // NOTE: This potentially results in *two* glue operands, and the wrong one + // might possibly show up where the other was intended. In particular, + // Emitter::EmitMachineNode() expects only the glued convergence token if it + // exists. Similarly, the selection of the call expects to match only the + // InGlue operand if it exists. + if (SDValue Token = CLI.ConvergenceControlToken) { + Ops.push_back(SDValue(DAG.getMachineNode(TargetOpcode::CONVERGENCECTRL_GLUE, + DL, MVT::Glue, Token), + 0)); + } + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); // If we're doing a tall call, use a TC_RETURN here rather than an @@ -4858,8 +4868,8 @@ MachineBasicBlock *SITargetLowering::EmitInstrWithCustomInserter( if (Subtarget->hasScalarAddSub64()) { unsigned Opc = IsAdd ? AMDGPU::S_ADD_U64 : AMDGPU::S_SUB_U64; BuildMI(*BB, MI, DL, TII->get(Opc), Dest.getReg()) - .addReg(Src0.getReg()) - .addReg(Src1.getReg()); + .add(Src0) + .add(Src1); } else { const SIRegisterInfo *TRI = ST.getRegisterInfo(); const TargetRegisterClass *BoolRC = TRI->getBoolRC(); @@ -5224,24 +5234,8 @@ MachineBasicBlock *SITargetLowering::EmitInstrWithCustomInserter( MachineInstrBuilder MIB; MIB = BuildMI(*BB, MI, DL, TII->get(AMDGPU::SI_CALL), ReturnAddrReg); - for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) { - MachineOperand &MO = MI.getOperand(I); - if (I != 2) { - MIB.add(MO); - continue; - } - } - - MachineOperand &MO = MI.getOperand(2); - MachineRegisterInfo &MRI = BB->getParent()->getRegInfo(); - // The token operand is always a register, whose definition is IMPLICIT_DEF - // iff there was no token on the call. - if (MachineInstr *Def = MRI.getVRegDef(MO.getReg())) { - if (Def->getOpcode() != TargetOpcode::IMPLICIT_DEF) { - MO.setImplicit(); - MIB.add(MO); - } - } + for (const MachineOperand &MO : MI.operands()) + MIB.add(MO); MIB.cloneMemRefs(MI); MI.eraseFromParent(); @@ -5409,6 +5403,11 @@ MachineBasicBlock *SITargetLowering::EmitInstrWithCustomInserter( return SplitBB; } default: + if (TII->isImage(MI) || TII->isMUBUF(MI)) { + if (!MI.mayStore()) + AddMemOpInit(MI); + return BB; + } return AMDGPUTargetLowering::EmitInstrWithCustomInserter(MI, BB); } } @@ -12572,6 +12571,10 @@ bool SITargetLowering::isCanonicalized(SelectionDAG &DAG, SDValue Op, case ISD::FREM: case ISD::FP_ROUND: case ISD::FP_EXTEND: + case ISD::FP16_TO_FP: + case ISD::FP_TO_FP16: + case ISD::BF16_TO_FP: + case ISD::FP_TO_BF16: case ISD::FLDEXP: case AMDGPUISD::FMUL_LEGACY: case AMDGPUISD::FMAD_FTZ: @@ -12591,6 +12594,9 @@ bool SITargetLowering::isCanonicalized(SelectionDAG &DAG, SDValue Op, case AMDGPUISD::CVT_F32_UBYTE1: case AMDGPUISD::CVT_F32_UBYTE2: case AMDGPUISD::CVT_F32_UBYTE3: + case AMDGPUISD::FP_TO_FP16: + case AMDGPUISD::SIN_HW: + case AMDGPUISD::COS_HW: return true; // It can/will be lowered or combined as a bit operation. @@ -12600,6 +12606,20 @@ bool SITargetLowering::isCanonicalized(SelectionDAG &DAG, SDValue Op, case ISD::FCOPYSIGN: return isCanonicalized(DAG, Op.getOperand(0), MaxDepth - 1); + case ISD::AND: + if (Op.getValueType() == MVT::i32) { + // Be careful as we only know it is a bitcast floating point type. It + // could be f32, v2f16, we have no way of knowing. Luckily the constant + // value that we optimize for, which comes up in fp32 to bf16 conversions, + // is valid to optimize for all types. + if (auto *RHS = dyn_cast<ConstantSDNode>(Op.getOperand(1))) { + if (RHS->getZExtValue() == 0xffff0000) { + return isCanonicalized(DAG, Op.getOperand(0), MaxDepth - 1); + } + } + } + break; + case ISD::FSIN: case ISD::FCOS: case ISD::FSINCOS: @@ -12665,6 +12685,9 @@ bool SITargetLowering::isCanonicalized(SelectionDAG &DAG, SDValue Op, return false; case ISD::BITCAST: + // TODO: This is incorrect as it loses track of the operand's type. We may + // end up effectively bitcasting from f32 to v2f16 or vice versa, and the + // same bits that are canonicalized in one type need not be in the other. return isCanonicalized(DAG, Op.getOperand(0), MaxDepth - 1); case ISD::TRUNCATE: { // Hack round the mess we make when legalizing extract_vector_elt @@ -12694,25 +12717,26 @@ bool SITargetLowering::isCanonicalized(SelectionDAG &DAG, SDValue Op, case Intrinsic::amdgcn_trig_preop: case Intrinsic::amdgcn_log: case Intrinsic::amdgcn_exp2: + case Intrinsic::amdgcn_sqrt: return true; default: break; } - [[fallthrough]]; + break; } default: - // FIXME: denormalsEnabledForType is broken for dynamic - return denormalsEnabledForType(DAG, Op.getValueType()) && - DAG.isKnownNeverSNaN(Op); + break; } - llvm_unreachable("invalid operation"); + // FIXME: denormalsEnabledForType is broken for dynamic + return denormalsEnabledForType(DAG, Op.getValueType()) && + DAG.isKnownNeverSNaN(Op); } -bool SITargetLowering::isCanonicalized(Register Reg, MachineFunction &MF, +bool SITargetLowering::isCanonicalized(Register Reg, const MachineFunction &MF, unsigned MaxDepth) const { - MachineRegisterInfo &MRI = MF.getRegInfo(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); MachineInstr *MI = MRI.getVRegDef(Reg); unsigned Opcode = MI->getOpcode(); @@ -12931,27 +12955,7 @@ SDValue SITargetLowering::performFCanonicalizeCombine( } } - unsigned SrcOpc = N0.getOpcode(); - - // If it's free to do so, push canonicalizes further up the source, which may - // find a canonical source. - // - // TODO: More opcodes. Note this is unsafe for the _ieee minnum/maxnum for - // sNaNs. - if (SrcOpc == ISD::FMINNUM || SrcOpc == ISD::FMAXNUM) { - auto *CRHS = dyn_cast<ConstantFPSDNode>(N0.getOperand(1)); - if (CRHS && N0.hasOneUse()) { - SDLoc SL(N); - SDValue Canon0 = DAG.getNode(ISD::FCANONICALIZE, SL, VT, - N0.getOperand(0)); - SDValue Canon1 = getCanonicalConstantFP(DAG, SL, VT, CRHS->getValueAPF()); - DCI.AddToWorklist(Canon0.getNode()); - - return DAG.getNode(N0.getOpcode(), SL, VT, Canon0, Canon1); - } - } - - return isCanonicalized(DAG, N0) ? N0 : SDValue(); + return SDValue(); } static unsigned minMaxOpcToMin3Max3Opc(unsigned Opc) { @@ -15028,60 +15032,67 @@ SDNode *SITargetLowering::PostISelFolding(MachineSDNode *Node, // result register that will be written in the case of a memory access failure. // The required code is also added to tie this init code to the result of the // img instruction. -void SITargetLowering::AddIMGInit(MachineInstr &MI) const { +void SITargetLowering::AddMemOpInit(MachineInstr &MI) const { const SIInstrInfo *TII = getSubtarget()->getInstrInfo(); const SIRegisterInfo &TRI = TII->getRegisterInfo(); MachineRegisterInfo &MRI = MI.getMF()->getRegInfo(); MachineBasicBlock &MBB = *MI.getParent(); - MachineOperand *TFE = TII->getNamedOperand(MI, AMDGPU::OpName::tfe); - MachineOperand *LWE = TII->getNamedOperand(MI, AMDGPU::OpName::lwe); - MachineOperand *D16 = TII->getNamedOperand(MI, AMDGPU::OpName::d16); - - if (!TFE && !LWE) // intersect_ray - return; + int DstIdx = + AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata); + unsigned InitIdx = 0; - unsigned TFEVal = TFE ? TFE->getImm() : 0; - unsigned LWEVal = LWE ? LWE->getImm() : 0; - unsigned D16Val = D16 ? D16->getImm() : 0; + if (TII->isImage(MI)) { + MachineOperand *TFE = TII->getNamedOperand(MI, AMDGPU::OpName::tfe); + MachineOperand *LWE = TII->getNamedOperand(MI, AMDGPU::OpName::lwe); + MachineOperand *D16 = TII->getNamedOperand(MI, AMDGPU::OpName::d16); - if (!TFEVal && !LWEVal) - return; + if (!TFE && !LWE) // intersect_ray + return; - // At least one of TFE or LWE are non-zero - // We have to insert a suitable initialization of the result value and - // tie this to the dest of the image instruction. + unsigned TFEVal = TFE ? TFE->getImm() : 0; + unsigned LWEVal = LWE ? LWE->getImm() : 0; + unsigned D16Val = D16 ? D16->getImm() : 0; - const DebugLoc &DL = MI.getDebugLoc(); + if (!TFEVal && !LWEVal) + return; - int DstIdx = - AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata); + // At least one of TFE or LWE are non-zero + // We have to insert a suitable initialization of the result value and + // tie this to the dest of the image instruction. - // Calculate which dword we have to initialize to 0. - MachineOperand *MO_Dmask = TII->getNamedOperand(MI, AMDGPU::OpName::dmask); + // Calculate which dword we have to initialize to 0. + MachineOperand *MO_Dmask = TII->getNamedOperand(MI, AMDGPU::OpName::dmask); - // check that dmask operand is found. - assert(MO_Dmask && "Expected dmask operand in instruction"); + // check that dmask operand is found. + assert(MO_Dmask && "Expected dmask operand in instruction"); - unsigned dmask = MO_Dmask->getImm(); - // Determine the number of active lanes taking into account the - // Gather4 special case - unsigned ActiveLanes = TII->isGather4(MI) ? 4 : llvm::popcount(dmask); + unsigned dmask = MO_Dmask->getImm(); + // Determine the number of active lanes taking into account the + // Gather4 special case + unsigned ActiveLanes = TII->isGather4(MI) ? 4 : llvm::popcount(dmask); - bool Packed = !Subtarget->hasUnpackedD16VMem(); + bool Packed = !Subtarget->hasUnpackedD16VMem(); - unsigned InitIdx = - D16Val && Packed ? ((ActiveLanes + 1) >> 1) + 1 : ActiveLanes + 1; + InitIdx = D16Val && Packed ? ((ActiveLanes + 1) >> 1) + 1 : ActiveLanes + 1; - // Abandon attempt if the dst size isn't large enough - // - this is in fact an error but this is picked up elsewhere and - // reported correctly. - uint32_t DstSize = TRI.getRegSizeInBits(*TII->getOpRegClass(MI, DstIdx)) / 32; - if (DstSize < InitIdx) + // Abandon attempt if the dst size isn't large enough + // - this is in fact an error but this is picked up elsewhere and + // reported correctly. + uint32_t DstSize = + TRI.getRegSizeInBits(*TII->getOpRegClass(MI, DstIdx)) / 32; + if (DstSize < InitIdx) + return; + } else if (TII->isMUBUF(MI) && AMDGPU::getMUBUFTfe(MI.getOpcode())) { + InitIdx = TRI.getRegSizeInBits(*TII->getOpRegClass(MI, DstIdx)) / 32; + } else { return; + } + + const DebugLoc &DL = MI.getDebugLoc(); // Create a register for the initialization value. - Register PrevDst = MRI.createVirtualRegister(TII->getOpRegClass(MI, DstIdx)); + Register PrevDst = MRI.cloneVirtualRegister(MI.getOperand(DstIdx).getReg()); unsigned NewDst = 0; // Final initialized value will be in here // If PRTStrictNull feature is enabled (the default) then initialize @@ -15179,11 +15190,8 @@ void SITargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI, return; } - if (TII->isImage(MI)) { - if (!MI.mayStore()) - AddIMGInit(MI); + if (TII->isImage(MI)) TII->enforceOperandRCAlignment(MI, AMDGPU::OpName::vaddr); - } } static SDValue buildSMovImm32(SelectionDAG &DAG, const SDLoc &DL, @@ -15939,8 +15947,8 @@ bool SITargetLowering::denormalsEnabledForType(const SelectionDAG &DAG, } } -bool SITargetLowering::denormalsEnabledForType(LLT Ty, - MachineFunction &MF) const { +bool SITargetLowering::denormalsEnabledForType( + LLT Ty, const MachineFunction &MF) const { switch (Ty.getScalarSizeInBits()) { case 32: return !denormalModeIsFlushAllF32(MF); diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.h b/llvm/lib/Target/AMDGPU/SIISelLowering.h index a20442e3737ee111c715646dc058855acadd950f..9856a2923d38f736fef941e43654dec35cb52d23 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.h +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.h @@ -466,7 +466,7 @@ public: SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; SDNode *PostISelFolding(MachineSDNode *N, SelectionDAG &DAG) const override; - void AddIMGInit(MachineInstr &MI) const; + void AddMemOpInit(MachineInstr &MI) const; void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override; @@ -523,10 +523,10 @@ public: bool isCanonicalized(SelectionDAG &DAG, SDValue Op, unsigned MaxDepth = 5) const; - bool isCanonicalized(Register Reg, MachineFunction &MF, + bool isCanonicalized(Register Reg, const MachineFunction &MF, unsigned MaxDepth = 5) const; bool denormalsEnabledForType(const SelectionDAG &DAG, EVT VT) const; - bool denormalsEnabledForType(LLT Ty, MachineFunction &MF) const; + bool denormalsEnabledForType(LLT Ty, const MachineFunction &MF) const; bool checkForPhysRegDependency(SDNode *Def, SDNode *User, unsigned Op, const TargetRegisterInfo *TRI, diff --git a/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp b/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp index a6184c5e1e048767e9140f2c3c0683aff174de94..27621906e4c5fdad89809c57f3f946350c2596b6 100644 --- a/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp +++ b/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp @@ -485,6 +485,16 @@ public: virtual AMDGPU::Waitcnt getAllZeroWaitcnt(bool IncludeVSCnt) const = 0; virtual ~WaitcntGenerator() = default; + + // Create a mask value from the initializer list of wait event types. + static constexpr unsigned + eventMask(std::initializer_list<WaitEventType> Events) { + unsigned Mask = 0; + for (auto &E : Events) + Mask |= 1 << E; + + return Mask; + } }; class WaitcntGeneratorPreGFX12 : public WaitcntGenerator { @@ -506,14 +516,12 @@ public: assert(ST); static const unsigned WaitEventMaskForInstPreGFX12[NUM_INST_CNTS] = { - (1 << VMEM_ACCESS) | (1 << VMEM_READ_ACCESS) | - (1 << VMEM_SAMPLER_READ_ACCESS) | (1 << VMEM_BVH_READ_ACCESS), - (1 << SMEM_ACCESS) | (1 << LDS_ACCESS) | (1 << GDS_ACCESS) | - (1 << SQ_MESSAGE), - (1 << EXP_GPR_LOCK) | (1 << GDS_GPR_LOCK) | (1 << VMW_GPR_LOCK) | - (1 << EXP_PARAM_ACCESS) | (1 << EXP_POS_ACCESS) | - (1 << EXP_LDS_ACCESS), - (1 << VMEM_WRITE_ACCESS) | (1 << SCRATCH_WRITE_ACCESS), + eventMask({VMEM_ACCESS, VMEM_READ_ACCESS, VMEM_SAMPLER_READ_ACCESS, + VMEM_BVH_READ_ACCESS}), + eventMask({SMEM_ACCESS, LDS_ACCESS, GDS_ACCESS, SQ_MESSAGE}), + eventMask({EXP_GPR_LOCK, GDS_GPR_LOCK, VMW_GPR_LOCK, EXP_PARAM_ACCESS, + EXP_POS_ACCESS, EXP_LDS_ACCESS}), + eventMask({VMEM_WRITE_ACCESS, SCRATCH_WRITE_ACCESS}), 0, 0, 0}; @@ -543,15 +551,14 @@ public: assert(ST); static const unsigned WaitEventMaskForInstGFX12Plus[NUM_INST_CNTS] = { - (1 << VMEM_ACCESS) | (1 << VMEM_READ_ACCESS), - (1 << LDS_ACCESS) | (1 << GDS_ACCESS), - (1 << EXP_GPR_LOCK) | (1 << GDS_GPR_LOCK) | (1 << VMW_GPR_LOCK) | - (1 << EXP_PARAM_ACCESS) | (1 << EXP_POS_ACCESS) | - (1 << EXP_LDS_ACCESS), - (1 << VMEM_WRITE_ACCESS) | (1 << SCRATCH_WRITE_ACCESS), - (1 << VMEM_SAMPLER_READ_ACCESS), - (1 << VMEM_BVH_READ_ACCESS), - (1 << SMEM_ACCESS) | (1 << SQ_MESSAGE)}; + eventMask({VMEM_ACCESS, VMEM_READ_ACCESS}), + eventMask({LDS_ACCESS, GDS_ACCESS}), + eventMask({EXP_GPR_LOCK, GDS_GPR_LOCK, VMW_GPR_LOCK, EXP_PARAM_ACCESS, + EXP_POS_ACCESS, EXP_LDS_ACCESS}), + eventMask({VMEM_WRITE_ACCESS, SCRATCH_WRITE_ACCESS}), + eventMask({VMEM_SAMPLER_READ_ACCESS}), + eventMask({VMEM_BVH_READ_ACCESS}), + eventMask({SMEM_ACCESS, SQ_MESSAGE})}; return WaitEventMaskForInstGFX12Plus; } diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp index c19c3c6017a7c8fa04ed03cea55e93f3097e5898..f4b21b7dfac391b6716e9f5e059393d0b3b8b680 100644 --- a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp +++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp @@ -3635,12 +3635,13 @@ memOpsHaveSameBaseOperands(ArrayRef<const MachineOperand *> BaseOps1, return true; } -static bool offsetsDoNotOverlap(int WidthA, int OffsetA, - int WidthB, int OffsetB) { +static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA, + LocationSize WidthB, int OffsetB) { int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB; int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA; - int LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB; - return LowOffset + LowWidth <= HighOffset; + LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB; + return LowWidth.hasValue() && + LowOffset + (int)LowWidth.getValue() <= HighOffset; } bool SIInstrInfo::checkInstOffsetsDoNotOverlap(const MachineInstr &MIa, @@ -3662,8 +3663,8 @@ bool SIInstrInfo::checkInstOffsetsDoNotOverlap(const MachineInstr &MIa, // FIXME: Handle ds_read2 / ds_write2. return false; } - unsigned Width0 = MIa.memoperands().front()->getSize(); - unsigned Width1 = MIb.memoperands().front()->getSize(); + LocationSize Width0 = MIa.memoperands().front()->getSize(); + LocationSize Width1 = MIb.memoperands().front()->getSize(); return offsetsDoNotOverlap(Width0, Offset0, Width1, Offset1); } diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.h b/llvm/lib/Target/AMDGPU/SIInstrInfo.h index a62bf779fe2e2dbd302bf1d5415689f62b0a21b5..4c5978cdc6665c68c912589878bf2b4fbed320a5 100644 --- a/llvm/lib/Target/AMDGPU/SIInstrInfo.h +++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.h @@ -815,7 +815,7 @@ public: } static bool isMFMAorWMMA(const MachineInstr &MI) { - return isMFMA(MI) || isWMMA(MI); + return isMFMA(MI) || isWMMA(MI) || isSWMMAC(MI); } static bool isSWMMAC(const MachineInstr &MI) { diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.td b/llvm/lib/Target/AMDGPU/SIInstrInfo.td index 835a5a247231541c43af299d62a8353397df91bf..1694436bad15ceb0faa93befef58035c60d463e3 100644 --- a/llvm/lib/Target/AMDGPU/SIInstrInfo.td +++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.td @@ -835,6 +835,19 @@ def fp16_zeros_high_16bits : PatLeaf<(f16 VGPR_32:$src), [{ return fp16SrcZerosHighBits(N->getOpcode()); }]>; +def is_canonicalized : PatLeaf<(fAny srcvalue:$src), [{ + const SITargetLowering &Lowering = + *static_cast<const SITargetLowering *>(getTargetLowering()); + return Lowering.isCanonicalized(*CurDAG, SDValue(N, 0)); +}]> { + let GISelPredicateCode = [{ + const SITargetLowering *TLI = static_cast<const SITargetLowering *>( + MF.getSubtarget().getTargetLowering()); + const MachineOperand &Dst = MI.getOperand(0); + assert(Dst.isDef()); + return TLI->isCanonicalized(Dst.getReg(), MF); + }]; +} //===----------------------------------------------------------------------===// // MUBUF/SMEM Patterns diff --git a/llvm/lib/Target/AMDGPU/SIInstructions.td b/llvm/lib/Target/AMDGPU/SIInstructions.td index 33c93cdf20c43b8f58a1e0c0e295d87fc1d96644..04f3a2f57605326c03655ecf5dd8d5d264b70a3f 100644 --- a/llvm/lib/Target/AMDGPU/SIInstructions.td +++ b/llvm/lib/Target/AMDGPU/SIInstructions.td @@ -618,8 +618,8 @@ def SI_RETURN : SPseudoInstSI < // This version is only needed so we can fill in the output register // in the custom inserter. def SI_CALL_ISEL : SPseudoInstSI < - (outs), (ins SSrc_b64:$src0, unknown:$callee, unknown:$token), - [(AMDGPUcall i64:$src0, tglobaladdr:$callee, untyped:$token)]> { + (outs), (ins SSrc_b64:$src0, unknown:$callee), + [(AMDGPUcall i64:$src0, tglobaladdr:$callee)]> { let Size = 4; let isCall = 1; let SchedRW = [WriteBranch]; @@ -629,8 +629,8 @@ def SI_CALL_ISEL : SPseudoInstSI < } def : GCNPat< - (AMDGPUcall i64:$src0, (i64 0), untyped:$token), - (SI_CALL_ISEL $src0, (i64 0), untyped:$token) + (AMDGPUcall i64:$src0, (i64 0)), + (SI_CALL_ISEL $src0, (i64 0)) >; // Wrapper around s_swappc_b64 with extra $callee parameter to track @@ -2944,6 +2944,16 @@ def : GCNPat< (V_BFREV_B32_e64 (i32 (EXTRACT_SUBREG VReg_64:$a, sub1))), sub0, (V_BFREV_B32_e64 (i32 (EXTRACT_SUBREG VReg_64:$a, sub0))), sub1)>; +// If fcanonicalize's operand is implicitly canonicalized, we only need a copy. +let AddedComplexity = 1000 in { +foreach vt = [f16, v2f16, f32, v2f32, f64] in { + def : GCNPat< + (fcanonicalize (vt is_canonicalized:$src)), + (COPY vt:$src) + >; +} +} + // Prefer selecting to max when legal, but using mul is always valid. let AddedComplexity = -5 in { @@ -3277,8 +3287,8 @@ def : GCNPat < let AddedComplexity = 5 in { def : GCNPat < - (v2f16 (is_canonicalized<build_vector> (f16 (VOP3Mods (f16 VGPR_32:$src0), i32:$src0_mods)), - (f16 (VOP3Mods (f16 VGPR_32:$src1), i32:$src1_mods)))), + (v2f16 (is_canonicalized_2<build_vector> (f16 (VOP3Mods (f16 VGPR_32:$src0), i32:$src0_mods)), + (f16 (VOP3Mods (f16 VGPR_32:$src1), i32:$src1_mods)))), (V_PACK_B32_F16_e64 $src0_mods, VGPR_32:$src0, $src1_mods, VGPR_32:$src1) >; } @@ -3590,6 +3600,17 @@ FPMinMaxPat<Instruction minmaxInst, ValueType vt, SDPatternOperator min_or_max, DSTCLAMP.NONE, DSTOMOD.NONE) >; +class +FPMinCanonMaxPat<Instruction minmaxInst, ValueType vt, SDPatternOperator min_or_max, + SDPatternOperator max_or_min_oneuse> : GCNPat < + (min_or_max (is_canonicalized_1<fcanonicalize> + (max_or_min_oneuse (VOP3Mods vt:$src0, i32:$src0_mods), + (VOP3Mods vt:$src1, i32:$src1_mods))), + (vt (VOP3Mods vt:$src2, i32:$src2_mods))), + (minmaxInst $src0_mods, $src0, $src1_mods, $src1, $src2_mods, $src2, + DSTCLAMP.NONE, DSTOMOD.NONE) +>; + let OtherPredicates = [isGFX11Plus] in { def : IntMinMaxPat<V_MAXMIN_I32_e64, smin, smax_oneuse>; def : IntMinMaxPat<V_MINMAX_I32_e64, smax, smin_oneuse>; @@ -3599,6 +3620,10 @@ def : FPMinMaxPat<V_MINMAX_F32_e64, f32, fmaxnum_like, fminnum_like_oneuse>; def : FPMinMaxPat<V_MAXMIN_F32_e64, f32, fminnum_like, fmaxnum_like_oneuse>; def : FPMinMaxPat<V_MINMAX_F16_e64, f16, fmaxnum_like, fminnum_like_oneuse>; def : FPMinMaxPat<V_MAXMIN_F16_e64, f16, fminnum_like, fmaxnum_like_oneuse>; +def : FPMinCanonMaxPat<V_MINMAX_F32_e64, f32, fmaxnum_like, fminnum_like_oneuse>; +def : FPMinCanonMaxPat<V_MAXMIN_F32_e64, f32, fminnum_like, fmaxnum_like_oneuse>; +def : FPMinCanonMaxPat<V_MINMAX_F16_e64, f16, fmaxnum_like, fminnum_like_oneuse>; +def : FPMinCanonMaxPat<V_MAXMIN_F16_e64, f16, fminnum_like, fmaxnum_like_oneuse>; } let OtherPredicates = [isGFX9Plus] in { @@ -3612,6 +3637,10 @@ def : FPMinMaxPat<V_MINIMUMMAXIMUM_F32_e64, f32, DivergentBinFrag<fmaximum>, fmi def : FPMinMaxPat<V_MAXIMUMMINIMUM_F32_e64, f32, DivergentBinFrag<fminimum>, fmaximum_oneuse>; def : FPMinMaxPat<V_MINIMUMMAXIMUM_F16_e64, f16, DivergentBinFrag<fmaximum>, fminimum_oneuse>; def : FPMinMaxPat<V_MAXIMUMMINIMUM_F16_e64, f16, DivergentBinFrag<fminimum>, fmaximum_oneuse>; +def : FPMinCanonMaxPat<V_MINIMUMMAXIMUM_F32_e64, f32, DivergentBinFrag<fmaximum>, fminimum_oneuse>; +def : FPMinCanonMaxPat<V_MAXIMUMMINIMUM_F32_e64, f32, DivergentBinFrag<fminimum>, fmaximum_oneuse>; +def : FPMinCanonMaxPat<V_MINIMUMMAXIMUM_F16_e64, f16, DivergentBinFrag<fmaximum>, fminimum_oneuse>; +def : FPMinCanonMaxPat<V_MAXIMUMMINIMUM_F16_e64, f16, DivergentBinFrag<fminimum>, fmaximum_oneuse>; } // Convert a floating-point power of 2 to the integer exponent. diff --git a/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp b/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp index 9c85ff3c43e22fda992c5eab4cd30bffc85b0283..e2e70ba9733b5b4bfeba91a2f441c6bd105d4eb1 100644 --- a/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp +++ b/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp @@ -399,19 +399,35 @@ static InstClassEnum getInstClass(unsigned Opc, const SIInstrInfo &TII) { switch (AMDGPU::getMUBUFBaseOpcode(Opc)) { default: return UNKNOWN; + case AMDGPU::BUFFER_LOAD_DWORD_BOTHEN: + case AMDGPU::BUFFER_LOAD_DWORD_BOTHEN_exact: + case AMDGPU::BUFFER_LOAD_DWORD_IDXEN: + case AMDGPU::BUFFER_LOAD_DWORD_IDXEN_exact: case AMDGPU::BUFFER_LOAD_DWORD_OFFEN: case AMDGPU::BUFFER_LOAD_DWORD_OFFEN_exact: case AMDGPU::BUFFER_LOAD_DWORD_OFFSET: case AMDGPU::BUFFER_LOAD_DWORD_OFFSET_exact: + case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_BOTHEN: + case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact: + case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_IDXEN: + case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact: case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFEN: case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFEN_exact: case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFSET: case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFSET_exact: return BUFFER_LOAD; + case AMDGPU::BUFFER_STORE_DWORD_BOTHEN: + case AMDGPU::BUFFER_STORE_DWORD_BOTHEN_exact: + case AMDGPU::BUFFER_STORE_DWORD_IDXEN: + case AMDGPU::BUFFER_STORE_DWORD_IDXEN_exact: case AMDGPU::BUFFER_STORE_DWORD_OFFEN: case AMDGPU::BUFFER_STORE_DWORD_OFFEN_exact: case AMDGPU::BUFFER_STORE_DWORD_OFFSET: case AMDGPU::BUFFER_STORE_DWORD_OFFSET_exact: + case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_BOTHEN: + case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_BOTHEN_exact: + case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_IDXEN: + case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_IDXEN_exact: case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFEN: case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFEN_exact: case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFSET: @@ -862,7 +878,7 @@ SILoadStoreOptimizer::combineKnownAdjacentMMOs(const CombineInfo &CI, const MachineMemOperand *MMOa = *CI.I->memoperands_begin(); const MachineMemOperand *MMOb = *Paired.I->memoperands_begin(); - unsigned Size = MMOa->getSize() + MMOb->getSize(); + unsigned Size = MMOa->getSize().getValue() + MMOb->getSize().getValue(); // A base pointer for the combined operation is the same as the leading // operation's pointer. diff --git a/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.cpp b/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.cpp index 2569f40fec0e48bd65b0c3a90fb2eb1a6bdd1b9a..12433dc83c4892e89c29eb9f90b25fbe03302ac2 100644 --- a/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.cpp +++ b/llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.cpp @@ -748,35 +748,7 @@ bool SIMachineFunctionInfo::initializeBaseYamlFields( } bool SIMachineFunctionInfo::mayUseAGPRs(const Function &F) const { - for (const BasicBlock &BB : F) { - for (const Instruction &I : BB) { - const auto *CB = dyn_cast<CallBase>(&I); - if (!CB) - continue; - - if (CB->isInlineAsm()) { - const InlineAsm *IA = dyn_cast<InlineAsm>(CB->getCalledOperand()); - for (const auto &CI : IA->ParseConstraints()) { - for (StringRef Code : CI.Codes) { - Code.consume_front("{"); - if (Code.starts_with("a")) - return true; - } - } - continue; - } - - const Function *Callee = - dyn_cast<Function>(CB->getCalledOperand()->stripPointerCasts()); - if (!Callee) - return true; - - if (Callee->getIntrinsicID() == Intrinsic::not_intrinsic) - return true; - } - } - - return false; + return !F.hasFnAttribute("amdgpu-no-agpr"); } bool SIMachineFunctionInfo::usesAGPRs(const MachineFunction &MF) const { diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp index 5c64c6bcd1968c6c33c0d0efcf3ea81114f45439..245731ad5fc7c9a2dd124de18d3f272cccee3b55 100644 --- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp +++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp @@ -363,8 +363,8 @@ SIRegisterInfo::SIRegisterInfo(const GCNSubtarget &ST) for (auto &Row : SubRegFromChannelTable) Row.fill(AMDGPU::NoSubRegister); for (unsigned Idx = 1; Idx < getNumSubRegIndices(); ++Idx) { - unsigned Width = AMDGPUSubRegIdxRanges[Idx].Size / 32; - unsigned Offset = AMDGPUSubRegIdxRanges[Idx].Offset / 32; + unsigned Width = getSubRegIdxSize(Idx) / 32; + unsigned Offset = getSubRegIdxOffset(Idx) / 32; assert(Width < SubRegFromChannelTableWidthMap.size()); Width = SubRegFromChannelTableWidthMap[Width]; if (Width == 0) @@ -1753,12 +1753,12 @@ void SIRegisterInfo::buildVGPRSpillLoadStore(SGPRSpillBuilder &SB, int Index, unsigned Opc = ST.enableFlatScratch() ? AMDGPU::SCRATCH_LOAD_DWORD_SADDR : AMDGPU::BUFFER_LOAD_DWORD_OFFSET; buildSpillLoadStore(*SB.MBB, SB.MI, SB.DL, Opc, Index, SB.TmpVGPR, false, - FrameReg, Offset * SB.EltSize, MMO, SB.RS); + FrameReg, (int64_t)Offset * SB.EltSize, MMO, SB.RS); } else { unsigned Opc = ST.enableFlatScratch() ? AMDGPU::SCRATCH_STORE_DWORD_SADDR : AMDGPU::BUFFER_STORE_DWORD_OFFSET; buildSpillLoadStore(*SB.MBB, SB.MI, SB.DL, Opc, Index, SB.TmpVGPR, IsKill, - FrameReg, Offset * SB.EltSize, MMO, SB.RS); + FrameReg, (int64_t)Offset * SB.EltSize, MMO, SB.RS); // This only ever adds one VGPR spill SB.MFI.addToSpilledVGPRs(1); } @@ -2265,10 +2265,10 @@ bool SIRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI, *MBB, MI, DL, Opc, Index, VData->getReg(), VData->isKill(), FrameReg, TII->getNamedOperand(*MI, AMDGPU::OpName::offset)->getImm(), *MI->memoperands_begin(), RS); - - if (IsWWMRegSpill) + + if (IsWWMRegSpill) TII->restoreExec(*MF, *MBB, MI, DL, MFI->getSGPRForEXECCopy()); - + MI->eraseFromParent(); return true; } diff --git a/llvm/lib/Target/AMDGPU/SMInstructions.td b/llvm/lib/Target/AMDGPU/SMInstructions.td index a91fb87998fe59a9b064036543410075f06a30d6..afc9da07bc96fa9fc4156c88e942a7152878728d 100644 --- a/llvm/lib/Target/AMDGPU/SMInstructions.td +++ b/llvm/lib/Target/AMDGPU/SMInstructions.td @@ -67,6 +67,7 @@ class SM_Real <SM_Pseudo ps, string opName = ps.Mnemonic> let UseNamedOperandTable = ps.UseNamedOperandTable; let SchedRW = ps.SchedRW; let SubtargetPredicate = ps.SubtargetPredicate; + let OtherPredicates = ps.OtherPredicates; let AsmMatchConverter = ps.AsmMatchConverter; let IsAtomicRet = ps.IsAtomicRet; let IsAtomicNoRet = ps.IsAtomicNoRet; @@ -1172,11 +1173,9 @@ defm S_LOAD_DWORDX4 : SM_Real_Loads_gfx10<0x002>; defm S_LOAD_DWORDX8 : SM_Real_Loads_gfx10<0x003>; defm S_LOAD_DWORDX16 : SM_Real_Loads_gfx10<0x004>; -let SubtargetPredicate = HasScalarFlatScratchInsts in { defm S_SCRATCH_LOAD_DWORD : SM_Real_Loads_gfx10<0x005>; defm S_SCRATCH_LOAD_DWORDX2 : SM_Real_Loads_gfx10<0x006>; defm S_SCRATCH_LOAD_DWORDX4 : SM_Real_Loads_gfx10<0x007>; -} // End SubtargetPredicate = HasScalarFlatScratchInsts defm S_BUFFER_LOAD_DWORD : SM_Real_Loads_gfx10<0x008>; defm S_BUFFER_LOAD_DWORDX2 : SM_Real_Loads_gfx10<0x009>; @@ -1184,19 +1183,15 @@ defm S_BUFFER_LOAD_DWORDX4 : SM_Real_Loads_gfx10<0x00a>; defm S_BUFFER_LOAD_DWORDX8 : SM_Real_Loads_gfx10<0x00b>; defm S_BUFFER_LOAD_DWORDX16 : SM_Real_Loads_gfx10<0x00c>; -let SubtargetPredicate = HasScalarStores in { defm S_STORE_DWORD : SM_Real_Stores_gfx10<0x010>; defm S_STORE_DWORDX2 : SM_Real_Stores_gfx10<0x011>; defm S_STORE_DWORDX4 : SM_Real_Stores_gfx10<0x012>; -let OtherPredicates = [HasScalarFlatScratchInsts] in { defm S_SCRATCH_STORE_DWORD : SM_Real_Stores_gfx10<0x015>; defm S_SCRATCH_STORE_DWORDX2 : SM_Real_Stores_gfx10<0x016>; defm S_SCRATCH_STORE_DWORDX4 : SM_Real_Stores_gfx10<0x017>; -} // End OtherPredicates = [HasScalarFlatScratchInsts] defm S_BUFFER_STORE_DWORD : SM_Real_Stores_gfx10<0x018>; defm S_BUFFER_STORE_DWORDX2 : SM_Real_Stores_gfx10<0x019>; defm S_BUFFER_STORE_DWORDX4 : SM_Real_Stores_gfx10<0x01a>; -} // End SubtargetPredicate = HasScalarStores def S_MEMREALTIME_gfx10 : SMEM_Real_gfx10<0x025, S_MEMREALTIME>; def S_MEMTIME_gfx10 : SMEM_Real_gfx10<0x024, S_MEMTIME>; @@ -1204,9 +1199,7 @@ def S_GL1_INV_gfx10 : SMEM_Real_gfx10<0x01f, S_GL1_INV>; def S_GET_WAVEID_IN_WORKGROUP_gfx10 : SMEM_Real_gfx10<0x02a, S_GET_WAVEID_IN_WORKGROUP>; def S_DCACHE_INV_gfx10 : SMEM_Real_gfx10<0x020, S_DCACHE_INV>; -let SubtargetPredicate = HasScalarStores in { def S_DCACHE_WB_gfx10 : SMEM_Real_gfx10<0x021, S_DCACHE_WB>; -} // End SubtargetPredicate = HasScalarStores multiclass SM_Real_Probe_gfx10<bits<8> op> { defvar ps = NAME; @@ -1243,8 +1236,6 @@ multiclass SM_Real_Atomics_gfx10<bits<8> op> { def _SGPR_IMM_RTN_gfx10 : SMEM_Atomic_Real_gfx10 <op, !cast<SM_Atomic_Pseudo>(ps#_SGPR_IMM_RTN)>; } -let SubtargetPredicate = HasScalarAtomics in { - defm S_BUFFER_ATOMIC_SWAP : SM_Real_Atomics_gfx10 <0x40>; defm S_BUFFER_ATOMIC_CMPSWAP : SM_Real_Atomics_gfx10 <0x41>; defm S_BUFFER_ATOMIC_ADD : SM_Real_Atomics_gfx10 <0x42>; @@ -1311,8 +1302,6 @@ multiclass SM_Real_Discard_gfx10<bits<8> op> { defm S_DCACHE_DISCARD : SM_Real_Discard_gfx10 <0x28>; defm S_DCACHE_DISCARD_X2 : SM_Real_Discard_gfx10 <0x29>; -} // End SubtargetPredicate = HasScalarAtomics - def SMInfoTable : GenericTable { let FilterClass = "SM_Real"; let CppTypeName = "SMInfo"; diff --git a/llvm/lib/Target/AMDGPU/SOPInstructions.td b/llvm/lib/Target/AMDGPU/SOPInstructions.td index bccdf4b5ca63740092719aa19ea3408decbd72e7..d34ee34e5bbffc631ecf239e93ee9b32fb6a5cf1 100644 --- a/llvm/lib/Target/AMDGPU/SOPInstructions.td +++ b/llvm/lib/Target/AMDGPU/SOPInstructions.td @@ -60,6 +60,11 @@ class SOP1_Real<bits<8> op, SOP1_Pseudo ps, string real_name = ps.Mnemonic> : let SchedRW = ps.SchedRW; let mayLoad = ps.mayLoad; let mayStore = ps.mayStore; + let isTerminator = ps.isTerminator; + let isReturn = ps.isReturn; + let isCall = ps.isCall; + let isBranch = ps.isBranch; + let isBarrier = ps.isBarrier; // encoding bits<7> sdst; @@ -744,19 +749,19 @@ def S_NOR_B64 : SOP2_64 <"s_nor_b64", // There are also separate patterns for types other than i32 def S_ANDN2_B32 : SOP2_32 <"s_andn2_b32", - [(set i32:$sdst, (UniformBinFrag<and> i32:$src0, (UniformUnaryFrag<not> i32:$src1)))] + [(set i32:$sdst, (UniformBinFrag<and> i32:$src0, (not i32:$src1)))] >; def S_ANDN2_B64 : SOP2_64 <"s_andn2_b64", - [(set i64:$sdst, (UniformBinFrag<and> i64:$src0, (UniformUnaryFrag<not> i64:$src1)))] + [(set i64:$sdst, (UniformBinFrag<and> i64:$src0, (not i64:$src1)))] >; def S_ORN2_B32 : SOP2_32 <"s_orn2_b32", - [(set i32:$sdst, (UniformBinFrag<or> i32:$src0, (UniformUnaryFrag<not> i32:$src1)))] + [(set i32:$sdst, (UniformBinFrag<or> i32:$src0, (not i32:$src1)))] >; def S_ORN2_B64 : SOP2_64 <"s_orn2_b64", - [(set i64:$sdst, (UniformBinFrag<or> i64:$src0, (UniformUnaryFrag<not> i64:$src1)))] + [(set i64:$sdst, (UniformBinFrag<or> i64:$src0, (not i64:$src1)))] >; } // End Defs = [SCC] @@ -977,6 +982,9 @@ class SOPK_Real<SOPK_Pseudo ps, string name = ps.Mnemonic> : let mayStore = ps.mayStore; let isBranch = ps.isBranch; let isCall = ps.isCall; + let isTerminator = ps.isTerminator; + let isReturn = ps.isReturn; + let isBarrier = ps.isBarrier; // encoding bits<7> sdst; @@ -1426,6 +1434,11 @@ class SOPP_Real<SOPP_Pseudo ps, string name = ps.Mnemonic> : let SchedRW = ps.SchedRW; let mayLoad = ps.mayLoad; let mayStore = ps.mayStore; + let isTerminator = ps.isTerminator; + let isReturn = ps.isReturn; + let isCall = ps.isCall; + let isBranch = ps.isBranch; + let isBarrier = ps.isBarrier; bits <16> simm16; } @@ -1905,21 +1918,20 @@ def : GCNPat< (S_AND_B32 (S_MOV_B32 (i32 0xffff)), $src) >; -// FIXME: ValueType should have isVector field class ScalarNot2Pat<Instruction inst, SDPatternOperator op, ValueType vt, - bit isVector = 1> : GCNPat< - (UniformBinFrag<op> vt:$src0, (UniformUnaryFrag<!if(isVector, vnot, not)> vt:$src1)), + SDPatternOperator notnode = !if(vt.isVector, vnot, not)> : GCNPat< + (UniformBinFrag<op> vt:$src0, (notnode vt:$src1)), (inst getSOPSrcForVT<vt>.ret:$src0, getSOPSrcForVT<vt>.ret:$src1) >; // Match these for some more types // TODO: i1 -def : ScalarNot2Pat<S_ANDN2_B32, and, i16, 0>; +def : ScalarNot2Pat<S_ANDN2_B32, and, i16>; def : ScalarNot2Pat<S_ANDN2_B32, and, v2i16>; def : ScalarNot2Pat<S_ANDN2_B64, and, v4i16>; def : ScalarNot2Pat<S_ANDN2_B64, and, v2i32>; -def : ScalarNot2Pat<S_ORN2_B32, or, i16, 0>; +def : ScalarNot2Pat<S_ORN2_B32, or, i16>; def : ScalarNot2Pat<S_ORN2_B32, or, v2i16>; def : ScalarNot2Pat<S_ORN2_B64, or, v4i16>; def : ScalarNot2Pat<S_ORN2_B64, or, v2i32>; diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp index 23434d2de0fc661c034ab9308c32fb29a636ed6e..d468b14d54d3fc980cbc7ac4c70b5f5b9a9c4267 100644 --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUAsmUtils.cpp @@ -60,6 +60,7 @@ const CustomOperand<const MCSubtargetInfo &> Msg[] = { {{"MSG_RTN_GET_REALTIME"}, ID_RTN_GET_REALTIME, isGFX11Plus}, {{"MSG_RTN_SAVE_WAVE"}, ID_RTN_SAVE_WAVE, isGFX11Plus}, {{"MSG_RTN_GET_TBA"}, ID_RTN_GET_TBA, isGFX11Plus}, + {{"MSG_RTN_GET_TBA_TO_PC"}, ID_RTN_GET_TBA_TO_PC, isGFX11Plus}, {{"MSG_RTN_GET_SE_AID_ID"}, ID_RTN_GET_SE_AID_ID, isGFX12Plus}, }; // clang-format on diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp index aa47dccf2dd2811fb4b19f1b9ef2d5fb76677be9..5d44396b07b605019dbe1412fae561fbd0aec69d 100644 --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp @@ -318,6 +318,7 @@ struct MUBUFInfo { bool has_srsrc; bool has_soffset; bool IsBufferInv; + bool tfe; }; struct MTBUFInfo { @@ -466,6 +467,11 @@ bool getMUBUFIsBufferInv(unsigned Opc) { return Info ? Info->IsBufferInv : false; } +bool getMUBUFTfe(unsigned Opc) { + const MUBUFInfo *Info = getMUBUFOpcodeHelper(Opc); + return Info ? Info->tfe : false; +} + bool getSMEMIsBuffer(unsigned Opc) { const SMInfo *Info = getSMEMOpcodeHelper(Opc); return Info ? Info->IsBuffer : false; @@ -1081,7 +1087,7 @@ unsigned getVGPRAllocGranule(const MCSubtargetInfo *STI, *EnableWavefrontSize32 : STI->getFeatureBits().test(FeatureWavefrontSize32); - if (STI->getFeatureBits().test(FeatureGFX11FullVGPRs)) + if (STI->getFeatureBits().test(Feature1_5xVGPRs)) return IsWave32 ? 24 : 12; if (hasGFX10_3Insts(*STI)) @@ -1108,7 +1114,7 @@ unsigned getTotalNumVGPRs(const MCSubtargetInfo *STI) { if (!isGFX10Plus(*STI)) return 256; bool IsWave32 = STI->getFeatureBits().test(FeatureWavefrontSize32); - if (STI->getFeatureBits().test(FeatureGFX11FullVGPRs)) + if (STI->getFeatureBits().test(Feature1_5xVGPRs)) return IsWave32 ? 1536 : 768; return IsWave32 ? 1024 : 512; } @@ -1215,47 +1221,6 @@ void initDefaultAMDKernelCodeT(amd_kernel_code_t &Header, } } -amdhsa::kernel_descriptor_t getDefaultAmdhsaKernelDescriptor( - const MCSubtargetInfo *STI) { - IsaVersion Version = getIsaVersion(STI->getCPU()); - - amdhsa::kernel_descriptor_t KD; - memset(&KD, 0, sizeof(KD)); - - AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, - amdhsa::FLOAT_DENORM_MODE_FLUSH_NONE); - if (Version.Major >= 12) { - AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN, 0); - AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX12_PLUS_DISABLE_PERF, 0); - } else { - AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP, 1); - AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE, 1); - } - AMDHSA_BITS_SET(KD.compute_pgm_rsrc2, - amdhsa::COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, 1); - if (Version.Major >= 10) { - AMDHSA_BITS_SET(KD.kernel_code_properties, - amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32, - STI->getFeatureBits().test(FeatureWavefrontSize32) ? 1 : 0); - AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE, - STI->getFeatureBits().test(FeatureCuMode) ? 0 : 1); - AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, - amdhsa::COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED, 1); - } - if (AMDGPU::isGFX90A(*STI)) { - AMDHSA_BITS_SET(KD.compute_pgm_rsrc3, - amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT, - STI->getFeatureBits().test(FeatureTgSplit) ? 1 : 0); - } - return KD; -} - bool isGroupSegment(const GlobalValue *GV) { return GV->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS; } @@ -3055,6 +3020,11 @@ bool isDPALU_DPP(const MCInstrDesc &OpDesc) { return hasAny64BitVGPROperands(OpDesc); } +unsigned getLdsDwGranularity(const MCSubtargetInfo &ST) { + // Currently this is 128 for all subtargets + return 128; +} + } // namespace AMDGPU raw_ostream &operator<<(raw_ostream &OS, diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h index f8521cba077c695167b10a7cb80b208126f74b16..943588fe701cc8a5a0d01e2925983ba4b441d8a4 100644 --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h @@ -34,10 +34,6 @@ class StringRef; class Triple; class raw_ostream; -namespace amdhsa { -struct kernel_descriptor_t; -} - namespace AMDGPU { struct IsaVersion; @@ -525,6 +521,9 @@ bool getMUBUFHasSoffset(unsigned Opc); LLVM_READONLY bool getMUBUFIsBufferInv(unsigned Opc); +LLVM_READONLY +bool getMUBUFTfe(unsigned Opc); + LLVM_READONLY bool getSMEMIsBuffer(unsigned Opc); @@ -852,9 +851,6 @@ unsigned mapWMMA3AddrTo2AddrOpcode(unsigned Opc); void initDefaultAMDKernelCodeT(amd_kernel_code_t &Header, const MCSubtargetInfo *STI); -amdhsa::kernel_descriptor_t getDefaultAmdhsaKernelDescriptor( - const MCSubtargetInfo *STI); - bool isGroupSegment(const GlobalValue *GV); bool isGlobalSegment(const GlobalValue *GV); bool isReadOnlySegment(const GlobalValue *GV); @@ -1513,6 +1509,11 @@ bool isIntrinsicSourceOfDivergence(unsigned IntrID); /// \returns true if the intrinsic is uniform bool isIntrinsicAlwaysUniform(unsigned IntrID); +/// \returns lds block size in terms of dwords. \p +/// This is used to calculate the lds size encoded for PAL metadata 3.0+ which +/// must be defined in terms of bytes. +unsigned getLdsDwGranularity(const MCSubtargetInfo &ST); + } // end namespace AMDGPU raw_ostream &operator<<(raw_ostream &OS, diff --git a/llvm/lib/Target/AMDGPU/VINTERPInstructions.td b/llvm/lib/Target/AMDGPU/VINTERPInstructions.td index 77063e2b70f66c32e4a1a30ded8e372db0e691f3..1f7bffb26a60f437aa75b2e134f03602f27de9fb 100644 --- a/llvm/lib/Target/AMDGPU/VINTERPInstructions.td +++ b/llvm/lib/Target/AMDGPU/VINTERPInstructions.td @@ -173,6 +173,12 @@ defm : VInterpF16Pat<int_amdgcn_interp_inreg_p10_f16, defm : VInterpF16Pat<int_amdgcn_interp_inreg_p2_f16, V_INTERP_P2_F16_F32_inreg, f16, [VINTERPModsHi, VINTERPMods, VINTERPMods]>; +defm : VInterpF16Pat<int_amdgcn_interp_p10_rtz_f16, + V_INTERP_P10_RTZ_F16_F32_inreg, f32, + [VINTERPModsHi, VINTERPMods, VINTERPModsHi]>; +defm : VInterpF16Pat<int_amdgcn_interp_p2_rtz_f16, + V_INTERP_P2_RTZ_F16_F32_inreg, f16, + [VINTERPModsHi, VINTERPMods, VINTERPMods]>; //===----------------------------------------------------------------------===// // VINTERP Real Instructions diff --git a/llvm/lib/Target/ARM/ARM.td b/llvm/lib/Target/ARM/ARM.td index 4510c7cf4f42e20517664614f5bdb422ebb7aab8..66596dbda83c951a01cdbc04ffab533de2caf706 100644 --- a/llvm/lib/Target/ARM/ARM.td +++ b/llvm/lib/Target/ARM/ARM.td @@ -1742,6 +1742,7 @@ def ARMAsmWriter : AsmWriter { def ARMAsmParser : AsmParser { bit ReportMultipleNearMisses = 1; + let PreferSmallerInstructions = true; } def ARMAsmParserVariant : AsmParserVariant { diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp index dd63ca17e5b9f1e08cdb38a864a981ea70cf22b7..5d0468948dfb6172afed64fd3626d9f6eb3795f5 100644 --- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -3710,7 +3710,7 @@ unsigned ARMBaseInstrInfo::getNumLDMAddresses(const MachineInstr &MI) const { for (MachineInstr::mmo_iterator I = MI.memoperands_begin(), E = MI.memoperands_end(); I != E; ++I) { - Size += (*I)->getSize(); + Size += (*I)->getSize().getValue(); } // FIXME: The scheduler currently can't handle values larger than 16. But // the values can actually go up to 32 for floating-point load/store diff --git a/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp b/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp index 9b26aac6c0b71e0024357c08958ade392e8a4c75..34b6f0575f7276748c708f5981eecd0808a36fb8 100644 --- a/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp +++ b/llvm/lib/Target/ARM/ARMHazardRecognizer.cpp @@ -191,7 +191,7 @@ ARMBankConflictHazardRecognizer::getHazardType(SUnit *SU, int Stalls) { auto BasePseudoVal0 = MO0->getPseudoValue(); int64_t Offset0 = 0; - if (MO0->getSize() > 4) + if (!MO0->getSize().hasValue() || MO0->getSize().getValue() > 4) return NoHazard; bool SPvalid = false; @@ -259,8 +259,8 @@ void ARMBankConflictHazardRecognizer::EmitInstruction(SUnit *SU) { return; auto MO = *MI.memoperands().begin(); - uint64_t Size1 = MO->getSize(); - if (Size1 > 4) + LocationSize Size1 = MO->getSize(); + if (Size1.hasValue() && Size1.getValue() > 4) return; Accesses.push_back(&MI); } diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 7ac49782ea8466ff592141fffe74bcfe560fbe7f..3907131be6d13128b30c926f09a767c4a247efb4 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -2571,7 +2571,7 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, } const TargetOptions &Options = DAG.getTarget().Options; if (Options.EmitCallSiteInfo) - CSInfo.emplace_back(VA.getLocReg(), i); + CSInfo.ArgRegPairs.emplace_back(VA.getLocReg(), i); RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); } else if (isByVal) { assert(VA.isMemLoc()); diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td index 404085820a666055f4b944a3f16d5b21a4d304d7..d0678f378da1ea3900e68693b85cab525bcb6db5 100644 --- a/llvm/lib/Target/ARM/ARMInstrFormats.td +++ b/llvm/lib/Target/ARM/ARMInstrFormats.td @@ -155,7 +155,11 @@ def iflags_op : Operand<i32> { // ARM Predicate operand. Default to 14 = always (AL). Second part is CC // register whose default is 0 (no register). -def CondCodeOperand : AsmOperandClass { let Name = "CondCode"; } +def CondCodeOperand : AsmOperandClass { + let Name = "CondCode"; + let DefaultMethod = "defaultCondCodeOp"; + let IsOptional = true; +} def pred : PredicateOperand<OtherVT, (ops i32imm, i32imm), (ops (i32 14), (i32 zero_reg))> { let PrintMethod = "printPredicateOperand"; @@ -174,7 +178,11 @@ def cmovpred : Operand<i32>, PredicateOp, } // Conditional code result for instructions whose 's' bit is set, e.g. subs. -def CCOutOperand : AsmOperandClass { let Name = "CCOut"; } +def CCOutOperand : AsmOperandClass { + let Name = "CCOut"; + let DefaultMethod = "defaultCCOutOp"; + let IsOptional = true; +} def cc_out : OptionalDefOperand<OtherVT, (ops CCR), (ops (i32 zero_reg))> { let EncoderMethod = "getCCOutOpValue"; let PrintMethod = "printSBitModifierOperand"; @@ -202,10 +210,14 @@ def inv_cond_XFORM : SDNodeXForm<imm, [{ def VPTPredNOperand : AsmOperandClass { let Name = "VPTPredN"; let PredicateMethod = "isVPTPred"; + let DefaultMethod = "defaultVPTPredOp"; + let IsOptional = true; } def VPTPredROperand : AsmOperandClass { let Name = "VPTPredR"; let PredicateMethod = "isVPTPred"; + let DefaultMethod = "defaultVPTPredOp"; + let IsOptional = true; } // Operand classes for the cluster of MC operands describing a @@ -468,7 +480,7 @@ class InstThumb<AddrMode am, int sz, IndexMode im, // These are aliases that require C++ handling to convert to the target // instruction, while InstAliases can be handled directly by tblgen. class AsmPseudoInst<string asm, dag iops, dag oops = (outs)> - : InstTemplate<AddrModeNone, 0, IndexModeNone, Pseudo, GenericDomain, + : InstTemplate<AddrModeNone, 4, IndexModeNone, Pseudo, GenericDomain, "", NoItinerary> { let OutOperandList = oops; let InOperandList = iops; diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td index be0ca964d3f912a508a3d21b95063f517dc57b51..e7f4059935138ad5996cedbfd66884756a3129b7 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb.td @@ -1210,7 +1210,7 @@ def tMOVi8 : T1sI<(outs tGPR:$Rd), (ins imm0_255_expr:$imm8), IIC_iMOVi, // Because we have an explicit tMOVSr below, we need an alias to handle // the immediate "movs" form here. Blech. def : tInstAlias <"movs $Rdn, $imm8", - (tMOVi8 tGPR:$Rdn, CPSR, imm0_255_expr:$imm8, 14, 0)>; + (tMOVi8 tGPR:$Rdn, CPSR, imm0_255_expr:$imm8, 14, zero_reg)>; // A7-73: MOV(2) - mov setting flag. @@ -1768,7 +1768,7 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { // In Thumb1, "nop" is encoded as a "mov r8, r8". Technically, the bf00 // encoding is available on ARMv6K, but we don't differentiate that finely. -def : InstAlias<"nop", (tMOVr R8, R8, 14, 0), 0>, Requires<[IsThumb, IsThumb1Only]>; +def : InstAlias<"nop", (tMOVr R8, R8, 14, zero_reg), 0>, Requires<[IsThumb, IsThumb1Only]>; // "neg" is and alias for "rsb rd, rn, #0" diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td index acd46e8093aa78d87c6bb901a8fadf9db2499f33..f227d68deeb8bc2c51f0a044473a2de51108ee02 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb2.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td @@ -5092,14 +5092,14 @@ def : InstAlias<"dmb${p}.w", (t2DMB 0xf, pred:$p), 0>, Requires<[HasDB]>; def : InstAlias<"dsb${p}.w\t$opt", (t2DSB memb_opt:$opt, pred:$p), 0>, Requires<[HasDB]>; def : InstAlias<"dsb${p}", (t2DSB 0xf, pred:$p), 0>, Requires<[HasDB]>; def : InstAlias<"dsb${p}.w", (t2DSB 0xf, pred:$p), 0>, Requires<[HasDB]>; -def : InstAlias<"isb${p}.w\t$opt", (t2ISB memb_opt:$opt, pred:$p), 0>, Requires<[HasDB]>; +def : InstAlias<"isb${p}.w\t$opt", (t2ISB instsyncb_opt:$opt, pred:$p), 0>, Requires<[HasDB]>; def : InstAlias<"isb${p}", (t2ISB 0xf, pred:$p), 0>, Requires<[HasDB]>; def : InstAlias<"isb${p}.w", (t2ISB 0xf, pred:$p), 0>, Requires<[HasDB]>; -// Non-predicable aliases of a predicable DSB: the predicate is (14, 0) where -// 14 = AL (always execute) and 0 = "instruction doesn't read the CPSR". -def : InstAlias<"ssbb", (t2DSB 0x0, 14, 0), 1>, Requires<[HasDB, IsThumb2]>; -def : InstAlias<"pssbb", (t2DSB 0x4, 14, 0), 1>, Requires<[HasDB, IsThumb2]>; +// Non-predicable aliases of a predicable DSB: the predicate is (14, zero_reg) where +// 14 = AL (always execute) and zero_reg = "instruction doesn't read the CPSR". +def : InstAlias<"ssbb", (t2DSB 0x0, 14, zero_reg), 1>, Requires<[HasDB, IsThumb2]>; +def : InstAlias<"pssbb", (t2DSB 0x4, 14, zero_reg), 1>, Requires<[HasDB, IsThumb2]>; // Armv8-R 'Data Full Barrier' def : InstAlias<"dfb${p}", (t2DSB 0xc, pred:$p), 1>, Requires<[HasDFB]>; diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index c320bf723c88bb7387f145a61d33e51ebe01506f..028db9d17e300adc393f9dbe695792f6ea4ecc94 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" @@ -47,6 +48,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/SMLoc.h" @@ -61,6 +63,7 @@ #include <iterator> #include <limits> #include <memory> +#include <optional> #include <string> #include <utility> #include <vector> @@ -69,16 +72,8 @@ using namespace llvm; -namespace llvm { -struct ARMInstrTable { - MCInstrDesc Insts[4445]; - MCOperandInfo OperandInfo[3026]; - MCPhysReg ImplicitOps[130]; -}; -extern const ARMInstrTable ARMDescs; -} // end namespace llvm - namespace { +class ARMOperand; enum class ImplicitItModeTy { Always, Never, ARMOnly, ThumbOnly }; @@ -356,11 +351,6 @@ class ARMAsmParser : public MCTargetAsmParser { ITState.CurPosition = ~0U; } - // Return the low-subreg of a given Q register. - unsigned getDRegFromQReg(unsigned QReg) const { - return MRI->getSubReg(QReg, ARM::dsub_0); - } - // Get the condition code corresponding to the current IT block slot. ARMCC::CondCodes currentITCond() { unsigned MaskBit = extractITMaskBit(ITState.Mask, ITState.CurPosition); @@ -446,13 +436,15 @@ class ARMAsmParser : public MCTargetAsmParser { } bool validatetLDMRegList(const MCInst &Inst, const OperandVector &Operands, - unsigned ListNo, bool IsARPop = false); + unsigned MnemonicOpsEndInd, unsigned ListIndex, + bool IsARPop = false); bool validatetSTMRegList(const MCInst &Inst, const OperandVector &Operands, - unsigned ListNo); + unsigned MnemonicOpsEndInd, unsigned ListIndex); int tryParseRegister(bool AllowOutofBoundReg = false); bool tryParseRegisterWithWriteBack(OperandVector &); int tryParseShiftRegister(OperandVector &); + std::optional<ARM_AM::ShiftOpc> tryParseShiftToken(); bool parseRegisterList(OperandVector &, bool EnforceOrder = true, bool AllowRAAC = false, bool AllowOutOfBoundReg = false); @@ -505,6 +497,10 @@ class ARMAsmParser : public MCTargetAsmParser { bool parseDirectiveSEHEpilogEnd(SMLoc L); bool parseDirectiveSEHCustom(SMLoc L); + std::unique_ptr<ARMOperand> defaultCondCodeOp(); + std::unique_ptr<ARMOperand> defaultCCOutOp(); + std::unique_ptr<ARMOperand> defaultVPTPredOp(); + bool isMnemonicVPTPredicable(StringRef Mnemonic, StringRef ExtraToken); StringRef splitMnemonic(StringRef Mnemonic, StringRef ExtraToken, ARMCC::CondCodes &PredicationCode, @@ -517,9 +513,13 @@ class ARMAsmParser : public MCTargetAsmParser { bool &CanAcceptVPTPredicationCode); bool enableArchExtFeature(StringRef Name, SMLoc &ExtLoc); - void tryConvertingToTwoOperandForm(StringRef Mnemonic, bool CarrySetting, - OperandVector &Operands); - bool CDEConvertDualRegOperand(StringRef Mnemonic, OperandVector &Operands); + void tryConvertingToTwoOperandForm(StringRef Mnemonic, + ARMCC::CondCodes PredicationCode, + bool CarrySetting, OperandVector &Operands, + unsigned MnemonicOpsEndInd); + + bool CDEConvertDualRegOperand(StringRef Mnemonic, OperandVector &Operands, + unsigned MnemonicOpsEndInd); bool isThumb() const { // FIXME: Can tablegen auto-generate this? @@ -572,9 +572,6 @@ class ARMAsmParser : public MCTargetAsmParser { bool hasV8_1MMainline() const { return getSTI().hasFeature(ARM::HasV8_1MMainlineOps); } - bool hasMVE() const { - return getSTI().hasFeature(ARM::HasMVEIntegerOps); - } bool hasMVEFloat() const { return getSTI().hasFeature(ARM::HasMVEFloatOps); } @@ -635,12 +632,13 @@ class ARMAsmParser : public MCTargetAsmParser { ParseStatus parseProcIFlagsOperand(OperandVector &); ParseStatus parseMSRMaskOperand(OperandVector &); ParseStatus parseBankedRegOperand(OperandVector &); - ParseStatus parsePKHImm(OperandVector &O, StringRef Op, int Low, int High); + ParseStatus parsePKHImm(OperandVector &O, ARM_AM::ShiftOpc, int Low, + int High); ParseStatus parsePKHLSLImm(OperandVector &O) { - return parsePKHImm(O, "lsl", 0, 31); + return parsePKHImm(O, ARM_AM::lsl, 0, 31); } ParseStatus parsePKHASRImm(OperandVector &O) { - return parsePKHImm(O, "asr", 1, 32); + return parsePKHImm(O, ARM_AM::asr, 1, 32); } ParseStatus parseSetEndImm(OperandVector &); ParseStatus parseShifterImm(OperandVector &); @@ -659,15 +657,20 @@ class ARMAsmParser : public MCTargetAsmParser { void cvtThumbBranches(MCInst &Inst, const OperandVector &); void cvtMVEVMOVQtoDReg(MCInst &Inst, const OperandVector &); - bool validateInstruction(MCInst &Inst, const OperandVector &Ops); - bool processInstruction(MCInst &Inst, const OperandVector &Ops, MCStreamer &Out); - bool shouldOmitCCOutOperand(StringRef Mnemonic, OperandVector &Operands); - bool shouldOmitPredicateOperand(StringRef Mnemonic, OperandVector &Operands); - bool shouldOmitVectorPredicateOperand(StringRef Mnemonic, OperandVector &Operands); + bool validateInstruction(MCInst &Inst, const OperandVector &Ops, + unsigned MnemonicOpsEndInd); + bool processInstruction(MCInst &Inst, const OperandVector &Ops, + unsigned MnemonicOpsEndInd, MCStreamer &Out); + bool shouldOmitVectorPredicateOperand(StringRef Mnemonic, + OperandVector &Operands, + unsigned MnemonicOpsEndInd); bool isITBlockTerminator(MCInst &Inst) const; - void fixupGNULDRDAlias(StringRef Mnemonic, OperandVector &Operands); - bool validateLDRDSTRD(MCInst &Inst, const OperandVector &Operands, - bool Load, bool ARMMode, bool Writeback); + + void fixupGNULDRDAlias(StringRef Mnemonic, OperandVector &Operands, + unsigned MnemonicOpsEndInd); + bool validateLDRDSTRD(MCInst &Inst, const OperandVector &Operands, bool Load, + bool ARMMode, bool Writeback, + unsigned MnemonicOpsEndInd); public: enum ARMMatchResultTy { @@ -716,6 +719,9 @@ public: unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, unsigned Kind) override; unsigned checkTargetMatchPredicate(MCInst &Inst) override; + unsigned + checkEarlyTargetMatchPredicate(MCInst &Inst, + const OperandVector &Operands) override; bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, @@ -745,6 +751,19 @@ public: void doBeforeLabelEmit(MCSymbol *Symbol, SMLoc IDLoc) override; void onLabelParsed(MCSymbol *Symbol) override; + + const MCInstrDesc &getInstrDesc(unsigned int Opcode) const { + return MII.get(Opcode); + } + + bool hasMVE() const { return getSTI().hasFeature(ARM::HasMVEIntegerOps); } + + // Return the low-subreg of a given Q register. + unsigned getDRegFromQReg(unsigned QReg) const { + return MRI->getSubReg(QReg, ARM::dsub_0); + } + + const MCRegisterInfo *getMRI() const { return MRI; } }; /// ARMOperand - Instances of this class represent a parsed ARM machine @@ -791,6 +810,8 @@ class ARMOperand : public MCParsedAsmOperand { SMLoc StartLoc, EndLoc, AlignmentLoc; SmallVector<unsigned, 8> Registers; + ARMAsmParser *Parser; + struct CCOp { ARMCC::CondCodes Val; }; @@ -941,7 +962,7 @@ class ARMOperand : public MCParsedAsmOperand { }; public: - ARMOperand(KindTy K) : Kind(K) {} + ARMOperand(KindTy K, ARMAsmParser &Parser) : Kind(K), Parser(&Parser) {} /// getStartLoc - Get the location of the first token of this operand. SMLoc getStartLoc() const override { return StartLoc; } @@ -979,7 +1000,7 @@ public: return StringRef(Tok.Data, Tok.Length); } - unsigned getReg() const override { + MCRegister getReg() const override { assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!"); return Reg.RegNum; } @@ -1347,6 +1368,14 @@ public: bool isRegListWithAPSR() const { return Kind == k_RegisterListWithAPSR || Kind == k_RegisterList; } + bool isDReg() const { + return isReg() && + ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg.RegNum); + } + bool isQReg() const { + return isReg() && + ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg.RegNum); + } bool isDPRRegList() const { return Kind == k_DPRRegisterList; } bool isSPRRegList() const { return Kind == k_SPRRegisterList; } bool isFPSRegListWithVPR() const { return Kind == k_FPSRegisterListWithVPR; } @@ -2012,6 +2041,13 @@ public: bool isProcIFlags() const { return Kind == k_ProcIFlags; } // NEON operands. + bool isAnyVectorList() const { + return Kind == k_VectorList || Kind == k_VectorListAllLanes || + Kind == k_VectorListIndexed; + } + + bool isVectorList() const { return Kind == k_VectorList; } + bool isSingleSpacedVectorList() const { return Kind == k_VectorList && !VectorList.isDoubleSpaced; } @@ -2021,6 +2057,9 @@ public: } bool isVecListOneD() const { + // We convert a single D reg to a list containing a D reg + if (isDReg() && !Parser->hasMVE()) + return true; if (!isSingleSpacedVectorList()) return false; return VectorList.Count == 1; } @@ -2032,6 +2071,10 @@ public: } bool isVecListDPair() const { + // We convert a single Q reg to a list with the two corresponding D + // registers + if (isQReg() && !Parser->hasMVE()) + return true; if (!isSingleSpacedVectorList()) return false; return (ARMMCRegisterClasses[ARM::DPairRegClassID] .contains(VectorList.RegNum)); @@ -2452,6 +2495,20 @@ public: CC == ARMCC::GT || CC == ARMCC::LE || CC == ARMCC::GE; } + void setVecListDPair(unsigned int DPair) { + Kind = k_VectorList; + VectorList.RegNum = DPair; + VectorList.Count = 2; + VectorList.isDoubleSpaced = false; + } + + void setVecListOneD(unsigned int DReg) { + Kind = k_VectorList; + VectorList.RegNum = DReg; + VectorList.Count = 1; + VectorList.isDoubleSpaced = false; + } + void addExpr(MCInst &Inst, const MCExpr *Expr) const { // Add as immediates when possible. Null MCExpr = 0. if (!Expr) @@ -2495,8 +2552,7 @@ public: RegNum = 0; } else { unsigned NextOpIndex = Inst.getNumOperands(); - const MCInstrDesc &MCID = - ARMDescs.Insts[ARM::INSTRUCTION_LIST_END - 1 - Inst.getOpcode()]; + auto &MCID = Parser->getInstrDesc(Inst.getOpcode()); int TiedOp = MCID.getOperandConstraint(NextOpIndex, MCOI::TIED_TO); assert(TiedOp >= 0 && "Inactive register in vpred_r is not tied to an output!"); @@ -3331,7 +3387,21 @@ public: void addVecListOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(VectorList.RegNum)); + + if (isAnyVectorList()) + Inst.addOperand(MCOperand::createReg(VectorList.RegNum)); + else if (isDReg() && !Parser->hasMVE()) { + Inst.addOperand(MCOperand::createReg(Reg.RegNum)); + } else if (isQReg() && !Parser->hasMVE()) { + auto DPair = Parser->getDRegFromQReg(Reg.RegNum); + DPair = Parser->getMRI()->getMatchingSuperReg( + DPair, ARM::dsub_0, &ARMMCRegisterClasses[ARM::DPairRegClassID]); + Inst.addOperand(MCOperand::createReg(DPair)); + } else { + LLVM_DEBUG(dbgs() << "TYPE: " << Kind << "\n"); + llvm_unreachable( + "attempted to add a vector list register with wrong type!"); + } } void addMVEVecListOperands(MCInst &Inst, unsigned N) const { @@ -3560,67 +3630,72 @@ public: void print(raw_ostream &OS) const override; - static std::unique_ptr<ARMOperand> CreateITMask(unsigned Mask, SMLoc S) { - auto Op = std::make_unique<ARMOperand>(k_ITCondMask); + static std::unique_ptr<ARMOperand> CreateITMask(unsigned Mask, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_ITCondMask, Parser); Op->ITMask.Mask = Mask; Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr<ARMOperand> CreateCondCode(ARMCC::CondCodes CC, - SMLoc S) { - auto Op = std::make_unique<ARMOperand>(k_CondCode); + static std::unique_ptr<ARMOperand> + CreateCondCode(ARMCC::CondCodes CC, SMLoc S, ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_CondCode, Parser); Op->CC.Val = CC; Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr<ARMOperand> CreateVPTPred(ARMVCC::VPTCodes CC, - SMLoc S) { - auto Op = std::make_unique<ARMOperand>(k_VPTPred); + static std::unique_ptr<ARMOperand> CreateVPTPred(ARMVCC::VPTCodes CC, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_VPTPred, Parser); Op->VCC.Val = CC; Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr<ARMOperand> CreateCoprocNum(unsigned CopVal, SMLoc S) { - auto Op = std::make_unique<ARMOperand>(k_CoprocNum); + static std::unique_ptr<ARMOperand> CreateCoprocNum(unsigned CopVal, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_CoprocNum, Parser); Op->Cop.Val = CopVal; Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr<ARMOperand> CreateCoprocReg(unsigned CopVal, SMLoc S) { - auto Op = std::make_unique<ARMOperand>(k_CoprocReg); + static std::unique_ptr<ARMOperand> CreateCoprocReg(unsigned CopVal, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_CoprocReg, Parser); Op->Cop.Val = CopVal; Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr<ARMOperand> CreateCoprocOption(unsigned Val, SMLoc S, - SMLoc E) { - auto Op = std::make_unique<ARMOperand>(k_CoprocOption); + static std::unique_ptr<ARMOperand> + CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E, ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_CoprocOption, Parser); Op->Cop.Val = Val; Op->StartLoc = S; Op->EndLoc = E; return Op; } - static std::unique_ptr<ARMOperand> CreateCCOut(unsigned RegNum, SMLoc S) { - auto Op = std::make_unique<ARMOperand>(k_CCOut); + static std::unique_ptr<ARMOperand> CreateCCOut(unsigned RegNum, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_CCOut, Parser); Op->Reg.RegNum = RegNum; Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr<ARMOperand> CreateToken(StringRef Str, SMLoc S) { - auto Op = std::make_unique<ARMOperand>(k_Token); + static std::unique_ptr<ARMOperand> CreateToken(StringRef Str, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_Token, Parser); Op->Tok.Data = Str.data(); Op->Tok.Length = Str.size(); Op->StartLoc = S; @@ -3629,8 +3704,8 @@ public: } static std::unique_ptr<ARMOperand> CreateReg(unsigned RegNum, SMLoc S, - SMLoc E) { - auto Op = std::make_unique<ARMOperand>(k_Register); + SMLoc E, ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_Register, Parser); Op->Reg.RegNum = RegNum; Op->StartLoc = S; Op->EndLoc = E; @@ -3639,9 +3714,9 @@ public: static std::unique_ptr<ARMOperand> CreateShiftedRegister(ARM_AM::ShiftOpc ShTy, unsigned SrcReg, - unsigned ShiftReg, unsigned ShiftImm, SMLoc S, - SMLoc E) { - auto Op = std::make_unique<ARMOperand>(k_ShiftedRegister); + unsigned ShiftReg, unsigned ShiftImm, SMLoc S, SMLoc E, + ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_ShiftedRegister, Parser); Op->RegShiftedReg.ShiftTy = ShTy; Op->RegShiftedReg.SrcReg = SrcReg; Op->RegShiftedReg.ShiftReg = ShiftReg; @@ -3653,8 +3728,9 @@ public: static std::unique_ptr<ARMOperand> CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy, unsigned SrcReg, - unsigned ShiftImm, SMLoc S, SMLoc E) { - auto Op = std::make_unique<ARMOperand>(k_ShiftedImmediate); + unsigned ShiftImm, SMLoc S, SMLoc E, + ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_ShiftedImmediate, Parser); Op->RegShiftedImm.ShiftTy = ShTy; Op->RegShiftedImm.SrcReg = SrcReg; Op->RegShiftedImm.ShiftImm = ShiftImm; @@ -3664,8 +3740,9 @@ public: } static std::unique_ptr<ARMOperand> CreateShifterImm(bool isASR, unsigned Imm, - SMLoc S, SMLoc E) { - auto Op = std::make_unique<ARMOperand>(k_ShifterImmediate); + SMLoc S, SMLoc E, + ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_ShifterImmediate, Parser); Op->ShifterImm.isASR = isASR; Op->ShifterImm.Imm = Imm; Op->StartLoc = S; @@ -3673,9 +3750,9 @@ public: return Op; } - static std::unique_ptr<ARMOperand> CreateRotImm(unsigned Imm, SMLoc S, - SMLoc E) { - auto Op = std::make_unique<ARMOperand>(k_RotateImmediate); + static std::unique_ptr<ARMOperand> + CreateRotImm(unsigned Imm, SMLoc S, SMLoc E, ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_RotateImmediate, Parser); Op->RotImm.Imm = Imm; Op->StartLoc = S; Op->EndLoc = E; @@ -3683,8 +3760,9 @@ public: } static std::unique_ptr<ARMOperand> CreateModImm(unsigned Bits, unsigned Rot, - SMLoc S, SMLoc E) { - auto Op = std::make_unique<ARMOperand>(k_ModifiedImmediate); + SMLoc S, SMLoc E, + ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_ModifiedImmediate, Parser); Op->ModImm.Bits = Bits; Op->ModImm.Rot = Rot; Op->StartLoc = S; @@ -3693,17 +3771,20 @@ public: } static std::unique_ptr<ARMOperand> - CreateConstantPoolImm(const MCExpr *Val, SMLoc S, SMLoc E) { - auto Op = std::make_unique<ARMOperand>(k_ConstantPoolImmediate); + CreateConstantPoolImm(const MCExpr *Val, SMLoc S, SMLoc E, + ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_ConstantPoolImmediate, Parser); Op->Imm.Val = Val; Op->StartLoc = S; Op->EndLoc = E; return Op; } - static std::unique_ptr<ARMOperand> - CreateBitfield(unsigned LSB, unsigned Width, SMLoc S, SMLoc E) { - auto Op = std::make_unique<ARMOperand>(k_BitfieldDescriptor); + static std::unique_ptr<ARMOperand> CreateBitfield(unsigned LSB, + unsigned Width, SMLoc S, + SMLoc E, + ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_BitfieldDescriptor, Parser); Op->Bitfield.LSB = LSB; Op->Bitfield.Width = Width; Op->StartLoc = S; @@ -3713,7 +3794,7 @@ public: static std::unique_ptr<ARMOperand> CreateRegList(SmallVectorImpl<std::pair<unsigned, unsigned>> &Regs, - SMLoc StartLoc, SMLoc EndLoc) { + SMLoc StartLoc, SMLoc EndLoc, ARMAsmParser &Parser) { assert(Regs.size() > 0 && "RegList contains no registers?"); KindTy Kind = k_RegisterList; @@ -3736,7 +3817,7 @@ public: assert(llvm::is_sorted(Regs) && "Register list must be sorted by encoding"); - auto Op = std::make_unique<ARMOperand>(Kind); + auto Op = std::make_unique<ARMOperand>(Kind, Parser); for (const auto &P : Regs) Op->Registers.push_back(P.second); @@ -3745,11 +3826,10 @@ public: return Op; } - static std::unique_ptr<ARMOperand> CreateVectorList(unsigned RegNum, - unsigned Count, - bool isDoubleSpaced, - SMLoc S, SMLoc E) { - auto Op = std::make_unique<ARMOperand>(k_VectorList); + static std::unique_ptr<ARMOperand> + CreateVectorList(unsigned RegNum, unsigned Count, bool isDoubleSpaced, + SMLoc S, SMLoc E, ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_VectorList, Parser); Op->VectorList.RegNum = RegNum; Op->VectorList.Count = Count; Op->VectorList.isDoubleSpaced = isDoubleSpaced; @@ -3760,8 +3840,8 @@ public: static std::unique_ptr<ARMOperand> CreateVectorListAllLanes(unsigned RegNum, unsigned Count, bool isDoubleSpaced, - SMLoc S, SMLoc E) { - auto Op = std::make_unique<ARMOperand>(k_VectorListAllLanes); + SMLoc S, SMLoc E, ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_VectorListAllLanes, Parser); Op->VectorList.RegNum = RegNum; Op->VectorList.Count = Count; Op->VectorList.isDoubleSpaced = isDoubleSpaced; @@ -3772,8 +3852,9 @@ public: static std::unique_ptr<ARMOperand> CreateVectorListIndexed(unsigned RegNum, unsigned Count, unsigned Index, - bool isDoubleSpaced, SMLoc S, SMLoc E) { - auto Op = std::make_unique<ARMOperand>(k_VectorListIndexed); + bool isDoubleSpaced, SMLoc S, SMLoc E, + ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_VectorListIndexed, Parser); Op->VectorList.RegNum = RegNum; Op->VectorList.Count = Count; Op->VectorList.LaneIndex = Index; @@ -3783,9 +3864,10 @@ public: return Op; } - static std::unique_ptr<ARMOperand> - CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) { - auto Op = std::make_unique<ARMOperand>(k_VectorIndex); + static std::unique_ptr<ARMOperand> CreateVectorIndex(unsigned Idx, SMLoc S, + SMLoc E, MCContext &Ctx, + ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_VectorIndex, Parser); Op->VectorIndex.Val = Idx; Op->StartLoc = S; Op->EndLoc = E; @@ -3793,8 +3875,8 @@ public: } static std::unique_ptr<ARMOperand> CreateImm(const MCExpr *Val, SMLoc S, - SMLoc E) { - auto Op = std::make_unique<ARMOperand>(k_Immediate); + SMLoc E, ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_Immediate, Parser); Op->Imm.Val = Val; Op->StartLoc = S; Op->EndLoc = E; @@ -3804,8 +3886,9 @@ public: static std::unique_ptr<ARMOperand> CreateMem(unsigned BaseRegNum, const MCExpr *OffsetImm, unsigned OffsetRegNum, ARM_AM::ShiftOpc ShiftType, unsigned ShiftImm, unsigned Alignment, - bool isNegative, SMLoc S, SMLoc E, SMLoc AlignmentLoc = SMLoc()) { - auto Op = std::make_unique<ARMOperand>(k_Memory); + bool isNegative, SMLoc S, SMLoc E, ARMAsmParser &Parser, + SMLoc AlignmentLoc = SMLoc()) { + auto Op = std::make_unique<ARMOperand>(k_Memory, Parser); Op->Memory.BaseRegNum = BaseRegNum; Op->Memory.OffsetImm = OffsetImm; Op->Memory.OffsetRegNum = OffsetRegNum; @@ -3821,8 +3904,8 @@ public: static std::unique_ptr<ARMOperand> CreatePostIdxReg(unsigned RegNum, bool isAdd, ARM_AM::ShiftOpc ShiftTy, - unsigned ShiftImm, SMLoc S, SMLoc E) { - auto Op = std::make_unique<ARMOperand>(k_PostIndexRegister); + unsigned ShiftImm, SMLoc S, SMLoc E, ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_PostIndexRegister, Parser); Op->PostIdxReg.RegNum = RegNum; Op->PostIdxReg.isAdd = isAdd; Op->PostIdxReg.ShiftTy = ShiftTy; @@ -3832,9 +3915,9 @@ public: return Op; } - static std::unique_ptr<ARMOperand> CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, - SMLoc S) { - auto Op = std::make_unique<ARMOperand>(k_MemBarrierOpt); + static std::unique_ptr<ARMOperand> + CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S, ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_MemBarrierOpt, Parser); Op->MBOpt.Val = Opt; Op->StartLoc = S; Op->EndLoc = S; @@ -3842,8 +3925,9 @@ public: } static std::unique_ptr<ARMOperand> - CreateInstSyncBarrierOpt(ARM_ISB::InstSyncBOpt Opt, SMLoc S) { - auto Op = std::make_unique<ARMOperand>(k_InstSyncBarrierOpt); + CreateInstSyncBarrierOpt(ARM_ISB::InstSyncBOpt Opt, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_InstSyncBarrierOpt, Parser); Op->ISBOpt.Val = Opt; Op->StartLoc = S; Op->EndLoc = S; @@ -3851,33 +3935,36 @@ public: } static std::unique_ptr<ARMOperand> - CreateTraceSyncBarrierOpt(ARM_TSB::TraceSyncBOpt Opt, SMLoc S) { - auto Op = std::make_unique<ARMOperand>(k_TraceSyncBarrierOpt); + CreateTraceSyncBarrierOpt(ARM_TSB::TraceSyncBOpt Opt, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_TraceSyncBarrierOpt, Parser); Op->TSBOpt.Val = Opt; Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr<ARMOperand> CreateProcIFlags(ARM_PROC::IFlags IFlags, - SMLoc S) { - auto Op = std::make_unique<ARMOperand>(k_ProcIFlags); + static std::unique_ptr<ARMOperand> + CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S, ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_ProcIFlags, Parser); Op->IFlags.Val = IFlags; Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr<ARMOperand> CreateMSRMask(unsigned MMask, SMLoc S) { - auto Op = std::make_unique<ARMOperand>(k_MSRMask); + static std::unique_ptr<ARMOperand> CreateMSRMask(unsigned MMask, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_MSRMask, Parser); Op->MMask.Val = MMask; Op->StartLoc = S; Op->EndLoc = S; return Op; } - static std::unique_ptr<ARMOperand> CreateBankedReg(unsigned Reg, SMLoc S) { - auto Op = std::make_unique<ARMOperand>(k_BankedReg); + static std::unique_ptr<ARMOperand> CreateBankedReg(unsigned Reg, SMLoc S, + ARMAsmParser &Parser) { + auto Op = std::make_unique<ARMOperand>(k_BankedReg, Parser); Op->BankedReg.Val = Reg; Op->StartLoc = S; Op->EndLoc = S; @@ -4054,6 +4141,63 @@ static MCRegister MatchRegisterName(StringRef Name); /// } +static bool isDataTypeToken(StringRef Tok) { + static const DenseSet<StringRef> DataTypes{ + ".8", ".16", ".32", ".64", ".i8", ".i16", ".i32", ".i64", + ".u8", ".u16", ".u32", ".u64", ".s8", ".s16", ".s32", ".s64", + ".p8", ".p16", ".f32", ".f64", ".f", ".d"}; + return DataTypes.contains(Tok); +} + +static unsigned getMnemonicOpsEndInd(const OperandVector &Operands) { + unsigned MnemonicOpsEndInd = 1; + // Special case for CPS which has a Mnemonic side token for possibly storing + // ie/id variant + if (Operands[0]->isToken() && + static_cast<ARMOperand &>(*Operands[0]).getToken() == "cps") { + if (Operands.size() > 1 && Operands[1]->isImm() && + static_cast<ARMOperand &>(*Operands[1]).getImm()->getKind() == + llvm::MCExpr::Constant && + (dyn_cast<MCConstantExpr>( + static_cast<ARMOperand &>(*Operands[1]).getImm()) + ->getValue() == ARM_PROC::IE || + dyn_cast<MCConstantExpr>( + static_cast<ARMOperand &>(*Operands[1]).getImm()) + ->getValue() == ARM_PROC::ID)) + ++MnemonicOpsEndInd; + } + + // In some circumstances the condition code moves to the right + bool RHSCondCode = false; + while (MnemonicOpsEndInd < Operands.size()) { + auto Op = static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd]); + // Special case for it instructions which have a condition code on the RHS + if (Op.isITMask()) { + RHSCondCode = true; + MnemonicOpsEndInd++; + } else if (Op.isToken() && + ( + // There are several special cases not covered by + // isDataTypeToken + Op.getToken() == ".w" || Op.getToken() == ".bf16" || + Op.getToken() == ".p64" || Op.getToken() == ".f16" || + isDataTypeToken(Op.getToken()))) { + // In the mnemonic operators the cond code must always precede the data + // type. So we can now safely assume any subsequent cond code is on the + // RHS. As is the case for VCMP and VPT. + RHSCondCode = true; + MnemonicOpsEndInd++; + } + // Skip all mnemonic operator types + else if (Op.isCCOut() || (Op.isCondCode() && !RHSCondCode) || + Op.isVPTPred() || (Op.isToken() && Op.getToken() == ".w")) + MnemonicOpsEndInd++; + else + break; + } + return MnemonicOpsEndInd; +} + bool ARMAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) { const AsmToken &Tok = getParser().getTok(); @@ -4127,30 +4271,36 @@ int ARMAsmParser::tryParseRegister(bool AllowOutOfBoundReg) { return RegNum; } -// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0. -// If a recoverable error occurs, return 1. If an irrecoverable error -// occurs, return -1. An irrecoverable error is one where tokens have been -// consumed in the process of trying to parse the shifter (i.e., when it is -// indeed a shifter operand, but malformed). -int ARMAsmParser::tryParseShiftRegister(OperandVector &Operands) { +std::optional<ARM_AM::ShiftOpc> ARMAsmParser::tryParseShiftToken() { MCAsmParser &Parser = getParser(); - SMLoc S = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); if (Tok.isNot(AsmToken::Identifier)) - return -1; + return std::nullopt; std::string lowerCase = Tok.getString().lower(); - ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase) + return StringSwitch<std::optional<ARM_AM::ShiftOpc>>(lowerCase) .Case("asl", ARM_AM::lsl) .Case("lsl", ARM_AM::lsl) .Case("lsr", ARM_AM::lsr) .Case("asr", ARM_AM::asr) .Case("ror", ARM_AM::ror) .Case("rrx", ARM_AM::rrx) - .Default(ARM_AM::no_shift); + .Default(std::nullopt); +} - if (ShiftTy == ARM_AM::no_shift) +// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0. +// If a recoverable error occurs, return 1. If an irrecoverable error +// occurs, return -1. An irrecoverable error is one where tokens have been +// consumed in the process of trying to parse the shifter (i.e., when it is +// indeed a shifter operand, but malformed). +int ARMAsmParser::tryParseShiftRegister(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + SMLoc S = Parser.getTok().getLoc(); + + auto ShiftTyOpt = tryParseShiftToken(); + if (ShiftTyOpt == std::nullopt) return 1; + auto ShiftTy = ShiftTyOpt.value(); Parser.Lex(); // Eat the operator. @@ -4218,12 +4368,11 @@ int ARMAsmParser::tryParseShiftRegister(OperandVector &Operands) { } if (ShiftReg && ShiftTy != ARM_AM::rrx) - Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg, - ShiftReg, Imm, - S, EndLoc)); + Operands.push_back(ARMOperand::CreateShiftedRegister( + ShiftTy, SrcReg, ShiftReg, Imm, S, EndLoc, *this)); else Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm, - S, EndLoc)); + S, EndLoc, *this)); return 0; } @@ -4242,12 +4391,13 @@ bool ARMAsmParser::tryParseRegisterWithWriteBack(OperandVector &Operands) { if (RegNo == -1) return true; - Operands.push_back(ARMOperand::CreateReg(RegNo, RegStartLoc, RegEndLoc)); + Operands.push_back( + ARMOperand::CreateReg(RegNo, RegStartLoc, RegEndLoc, *this)); const AsmToken &ExclaimTok = Parser.getTok(); if (ExclaimTok.is(AsmToken::Exclaim)) { Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(), - ExclaimTok.getLoc())); + ExclaimTok.getLoc(), *this)); Parser.Lex(); // Eat exclaim token return false; } @@ -4272,9 +4422,8 @@ bool ARMAsmParser::tryParseRegisterWithWriteBack(OperandVector &Operands) { SMLoc E = Parser.getTok().getEndLoc(); Parser.Lex(); // Eat right bracket token. - Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(), - SIdx, E, - getContext())); + Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(), SIdx, E, + getContext(), *this)); } return false; @@ -4341,7 +4490,8 @@ ParseStatus ARMAsmParser::parseITCondCode(OperandVector &Operands) { return ParseStatus::NoMatch; Parser.Lex(); // Eat the token. - Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S)); + Operands.push_back( + ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S, *this)); return ParseStatus::Success; } @@ -4363,7 +4513,7 @@ ParseStatus ARMAsmParser::parseCoprocNumOperand(OperandVector &Operands) { return ParseStatus::NoMatch; Parser.Lex(); // Eat identifier token. - Operands.push_back(ARMOperand::CreateCoprocNum(Num, S)); + Operands.push_back(ARMOperand::CreateCoprocNum(Num, S, *this)); return ParseStatus::Success; } @@ -4382,7 +4532,7 @@ ParseStatus ARMAsmParser::parseCoprocRegOperand(OperandVector &Operands) { return ParseStatus::NoMatch; Parser.Lex(); // Eat identifier token. - Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S)); + Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S, *this)); return ParseStatus::Success; } @@ -4413,7 +4563,7 @@ ParseStatus ARMAsmParser::parseCoprocOptionOperand(OperandVector &Operands) { SMLoc E = Parser.getTok().getEndLoc(); Parser.Lex(); // Eat the '}' - Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E)); + Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E, *this)); return ParseStatus::Success; } @@ -4616,11 +4766,12 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands, bool EnforceOrder, Parser.Lex(); // Eat '}' token. // Push the register list operand. - Operands.push_back(ARMOperand::CreateRegList(Registers, S, E)); + Operands.push_back(ARMOperand::CreateRegList(Registers, S, E, *this)); // The ARM system instruction variants for LDM/STM have a '^' token here. if (Parser.getTok().is(AsmToken::Caret)) { - Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc())); + Operands.push_back( + ARMOperand::CreateToken("^", Parser.getTok().getLoc(), *this)); Parser.Lex(); // Eat '^' token. } @@ -4680,6 +4831,8 @@ ParseStatus ARMAsmParser::parseVectorList(OperandVector &Operands) { // As an extension (to match gas), support a plain D register or Q register // (without encosing curly braces) as a single or double entry list, // respectively. + // If there is no lane supplied, just parse as a register and + // use the custom matcher to convert to list if necessary if (!hasMVE() && Parser.getTok().is(AsmToken::Identifier)) { SMLoc E = Parser.getTok().getEndLoc(); int Reg = tryParseRegister(); @@ -4691,16 +4844,15 @@ ParseStatus ARMAsmParser::parseVectorList(OperandVector &Operands) { return Res; switch (LaneKind) { case NoLanes: - Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E)); + Operands.push_back(ARMOperand::CreateReg(Reg, S, E, *this)); break; case AllLanes: - Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false, - S, E)); + Operands.push_back( + ARMOperand::CreateVectorListAllLanes(Reg, 1, false, S, E, *this)); break; case IndexedLane: - Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1, - LaneIndex, - false, S, E)); + Operands.push_back(ARMOperand::CreateVectorListIndexed( + Reg, 1, LaneIndex, false, S, E, *this)); break; } return ParseStatus::Success; @@ -4712,25 +4864,23 @@ ParseStatus ARMAsmParser::parseVectorList(OperandVector &Operands) { return Res; switch (LaneKind) { case NoLanes: - Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0, - &ARMMCRegisterClasses[ARM::DPairRegClassID]); - Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E)); + Operands.push_back(ARMOperand::CreateReg(Reg, S, E, *this)); break; case AllLanes: Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0, &ARMMCRegisterClasses[ARM::DPairRegClassID]); - Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false, - S, E)); + Operands.push_back( + ARMOperand::CreateVectorListAllLanes(Reg, 2, false, S, E, *this)); break; case IndexedLane: - Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2, - LaneIndex, - false, S, E)); + Operands.push_back(ARMOperand::CreateVectorListIndexed( + Reg, 2, LaneIndex, false, S, E, *this)); break; } return ParseStatus::Success; } - return Error(S, "vector register expected"); + Operands.push_back(ARMOperand::CreateReg(Reg, S, E, *this)); + return ParseStatus::Success; } if (Parser.getTok().isNot(AsmToken::LCurly)) @@ -4883,14 +5033,12 @@ ParseStatus ARMAsmParser::parseVectorList(OperandVector &Operands) { } auto Create = (LaneKind == NoLanes ? ARMOperand::CreateVectorList : ARMOperand::CreateVectorListAllLanes); - Operands.push_back(Create(FirstReg, Count, (Spacing == 2), S, E)); + Operands.push_back(Create(FirstReg, Count, (Spacing == 2), S, E, *this)); break; } case IndexedLane: - Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count, - LaneIndex, - (Spacing == 2), - S, E)); + Operands.push_back(ARMOperand::CreateVectorListIndexed( + FirstReg, Count, LaneIndex, (Spacing == 2), S, E, *this)); break; } return ParseStatus::Success; @@ -4957,7 +5105,8 @@ ParseStatus ARMAsmParser::parseMemBarrierOptOperand(OperandVector &Operands) { } else return ParseStatus::Failure; - Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S)); + Operands.push_back( + ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S, *this)); return ParseStatus::Success; } @@ -4975,7 +5124,8 @@ ARMAsmParser::parseTraceSyncBarrierOptOperand(OperandVector &Operands) { Parser.Lex(); // Eat identifier token. - Operands.push_back(ARMOperand::CreateTraceSyncBarrierOpt(ARM_TSB::CSYNC, S)); + Operands.push_back( + ARMOperand::CreateTraceSyncBarrierOpt(ARM_TSB::CSYNC, S, *this)); return ParseStatus::Success; } @@ -5020,7 +5170,7 @@ ARMAsmParser::parseInstSyncBarrierOptOperand(OperandVector &Operands) { return ParseStatus::Failure; Operands.push_back(ARMOperand::CreateInstSyncBarrierOpt( - (ARM_ISB::InstSyncBOpt)Opt, S)); + (ARM_ISB::InstSyncBOpt)Opt, S, *this)); return ParseStatus::Success; } @@ -5054,12 +5204,17 @@ ParseStatus ARMAsmParser::parseProcIFlagsOperand(OperandVector &Operands) { } Parser.Lex(); // Eat identifier token. - Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S)); + Operands.push_back( + ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S, *this)); return ParseStatus::Success; } /// parseMSRMaskOperand - Try to parse mask flags from MSR instruction. ParseStatus ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) { + // Don't parse two MSR registers in a row + if (static_cast<ARMOperand &>(*Operands.back()).isMSRMask() || + static_cast<ARMOperand &>(*Operands.back()).isBankedReg()) + return ParseStatus::NoMatch; MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); @@ -5071,7 +5226,7 @@ ParseStatus ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) { } unsigned SYSmvalue = Val & 0xFF; Parser.Lex(); - Operands.push_back(ARMOperand::CreateMSRMask(SYSmvalue, S)); + Operands.push_back(ARMOperand::CreateMSRMask(SYSmvalue, S, *this)); return ParseStatus::Success; } @@ -5087,7 +5242,7 @@ ParseStatus ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) { unsigned SYSmvalue = TheReg->Encoding & 0xFFF; Parser.Lex(); // Eat identifier token. - Operands.push_back(ARMOperand::CreateMSRMask(SYSmvalue, S)); + Operands.push_back(ARMOperand::CreateMSRMask(SYSmvalue, S, *this)); return ParseStatus::Success; } @@ -5150,13 +5305,17 @@ ParseStatus ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) { FlagsVal |= 16; Parser.Lex(); // Eat identifier token. - Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S)); + Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S, *this)); return ParseStatus::Success; } /// parseBankedRegOperand - Try to parse a banked register (e.g. "lr_irq") for /// use in the MRS/MSR instructions added to support virtualization. ParseStatus ARMAsmParser::parseBankedRegOperand(OperandVector &Operands) { + // Don't parse two Banked registers in a row + if (static_cast<ARMOperand &>(*Operands.back()).isBankedReg() || + static_cast<ARMOperand &>(*Operands.back()).isMSRMask()) + return ParseStatus::NoMatch; MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); @@ -5170,27 +5329,34 @@ ParseStatus ARMAsmParser::parseBankedRegOperand(OperandVector &Operands) { unsigned Encoding = TheReg->Encoding; Parser.Lex(); // Eat identifier token. - Operands.push_back(ARMOperand::CreateBankedReg(Encoding, S)); + Operands.push_back(ARMOperand::CreateBankedReg(Encoding, S, *this)); return ParseStatus::Success; } -ParseStatus ARMAsmParser::parsePKHImm(OperandVector &Operands, StringRef Op, - int Low, int High) { +// FIXME: Unify the different methods for handling shift operators +// and use TableGen matching mechanisms to do the validation rather than +// separate parsing paths. +ParseStatus ARMAsmParser::parsePKHImm(OperandVector &Operands, + ARM_AM::ShiftOpc Op, int Low, int High) { MCAsmParser &Parser = getParser(); - const AsmToken &Tok = Parser.getTok(); - if (Tok.isNot(AsmToken::Identifier)) - return Error(Parser.getTok().getLoc(), Op + " operand expected."); - StringRef ShiftName = Tok.getString(); - std::string LowerOp = Op.lower(); - std::string UpperOp = Op.upper(); - if (ShiftName != LowerOp && ShiftName != UpperOp) - return Error(Parser.getTok().getLoc(), Op + " operand expected."); + auto ShiftCodeOpt = tryParseShiftToken(); + + if (!ShiftCodeOpt.has_value()) + return ParseStatus::NoMatch; + auto ShiftCode = ShiftCodeOpt.value(); + + // The wrong shift code has been provided. Can error here as has matched the + // correct operand in this case. + if (ShiftCode != Op) + return Error(Parser.getTok().getLoc(), + ARM_AM::getShiftOpcStr(Op) + " operand expected."); + Parser.Lex(); // Eat shift type token. // There must be a '#' and a shift amount. if (Parser.getTok().isNot(AsmToken::Hash) && Parser.getTok().isNot(AsmToken::Dollar)) - return Error(Parser.getTok().getLoc(), "'#' expected"); + return ParseStatus::NoMatch; Parser.Lex(); // Eat hash token. const MCExpr *ShiftAmount; @@ -5205,7 +5371,7 @@ ParseStatus ARMAsmParser::parsePKHImm(OperandVector &Operands, StringRef Op, if (Val < Low || Val > High) return Error(Loc, "immediate value out of range"); - Operands.push_back(ARMOperand::CreateImm(CE, Loc, EndLoc)); + Operands.push_back(ARMOperand::CreateImm(CE, Loc, EndLoc, *this)); return ParseStatus::Success; } @@ -5224,9 +5390,8 @@ ParseStatus ARMAsmParser::parseSetEndImm(OperandVector &Operands) { if (Val == -1) return Error(S, "'be' or 'le' operand expected"); - Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::create(Val, - getContext()), - S, Tok.getEndLoc())); + Operands.push_back(ARMOperand::CreateImm( + MCConstantExpr::create(Val, getContext()), S, Tok.getEndLoc(), *this)); return ParseStatus::Success; } @@ -5240,7 +5405,7 @@ ParseStatus ARMAsmParser::parseShifterImm(OperandVector &Operands) { const AsmToken &Tok = Parser.getTok(); SMLoc S = Tok.getLoc(); if (Tok.isNot(AsmToken::Identifier)) - return Error(S, "shift operator 'asr' or 'lsl' expected"); + return ParseStatus::NoMatch; StringRef ShiftName = Tok.getString(); bool isASR; if (ShiftName == "lsl" || ShiftName == "LSL") @@ -5248,7 +5413,7 @@ ParseStatus ARMAsmParser::parseShifterImm(OperandVector &Operands) { else if (ShiftName == "asr" || ShiftName == "ASR") isASR = true; else - return Error(S, "shift operator 'asr' or 'lsl' expected"); + return ParseStatus::NoMatch; Parser.Lex(); // Eat the operator. // A '#' and a shift amount. @@ -5281,7 +5446,8 @@ ParseStatus ARMAsmParser::parseShifterImm(OperandVector &Operands) { return Error(ExLoc, "'lsr' shift amount must be in range [0,31]"); } - Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, EndLoc)); + Operands.push_back( + ARMOperand::CreateShifterImm(isASR, Val, S, EndLoc, *this)); return ParseStatus::Success; } @@ -5322,7 +5488,7 @@ ParseStatus ARMAsmParser::parseRotImm(OperandVector &Operands) { if (Val != 8 && Val != 16 && Val != 24 && Val != 0) return Error(ExLoc, "'ror' rotate amount must be 8, 16, or 24"); - Operands.push_back(ARMOperand::CreateRotImm(Val, S, EndLoc)); + Operands.push_back(ARMOperand::CreateRotImm(Val, S, EndLoc, *this)); return ParseStatus::Success; } @@ -5372,9 +5538,8 @@ ParseStatus ARMAsmParser::parseModImm(OperandVector &Operands) { int Enc = ARM_AM::getSOImmVal(Imm1); if (Enc != -1 && Parser.getTok().is(AsmToken::EndOfStatement)) { // We have a match! - Operands.push_back(ARMOperand::CreateModImm((Enc & 0xFF), - (Enc & 0xF00) >> 7, - Sx1, Ex1)); + Operands.push_back(ARMOperand::CreateModImm( + (Enc & 0xFF), (Enc & 0xF00) >> 7, Sx1, Ex1, *this)); return ParseStatus::Success; } @@ -5385,13 +5550,13 @@ ParseStatus ARMAsmParser::parseModImm(OperandVector &Operands) { // instruction with a mod_imm operand. The alias is defined such that the // parser method is shared, that's why we have to do this here. if (Parser.getTok().is(AsmToken::EndOfStatement)) { - Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1)); + Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1, *this)); return ParseStatus::Success; } } else { // Operands like #(l1 - l2) can only be evaluated at a later stage (via an // MCFixup). Fallback to a plain immediate. - Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1)); + Operands.push_back(ARMOperand::CreateImm(Imm1Exp, Sx1, Ex1, *this)); return ParseStatus::Success; } @@ -5425,7 +5590,7 @@ ParseStatus ARMAsmParser::parseModImm(OperandVector &Operands) { Imm2 = CE->getValue(); if (!(Imm2 & ~0x1E)) { // We have a match! - Operands.push_back(ARMOperand::CreateModImm(Imm1, Imm2, S, Ex2)); + Operands.push_back(ARMOperand::CreateModImm(Imm1, Imm2, S, Ex2, *this)); return ParseStatus::Success; } return Error(Sx2, @@ -5441,7 +5606,7 @@ ParseStatus ARMAsmParser::parseBitfield(OperandVector &Operands) { // The bitfield descriptor is really two operands, the LSB and the width. if (Parser.getTok().isNot(AsmToken::Hash) && Parser.getTok().isNot(AsmToken::Dollar)) - return Error(Parser.getTok().getLoc(), "'#' expected"); + return ParseStatus::NoMatch; Parser.Lex(); // Eat hash token. const MCExpr *LSBExpr; @@ -5480,7 +5645,7 @@ ParseStatus ARMAsmParser::parseBitfield(OperandVector &Operands) { if (Width < 1 || Width > 32 - LSB) return Error(E, "'width' operand must be in the range [1,32-lsb]"); - Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, EndLoc)); + Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, EndLoc, *this)); return ParseStatus::Success; } @@ -5527,8 +5692,8 @@ ParseStatus ARMAsmParser::parsePostIdxReg(OperandVector &Operands) { E = Parser.getTok().getLoc(); } - Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy, - ShiftImm, S, E)); + Operands.push_back( + ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy, ShiftImm, S, E, *this)); return ParseStatus::Success; } @@ -5569,8 +5734,8 @@ ParseStatus ARMAsmParser::parseAM3Offset(OperandVector &Operands) { if (isNegative && Val == 0) Val = std::numeric_limits<int32_t>::min(); - Operands.push_back( - ARMOperand::CreateImm(MCConstantExpr::create(Val, getContext()), S, E)); + Operands.push_back(ARMOperand::CreateImm( + MCConstantExpr::create(Val, getContext()), S, E, *this)); return ParseStatus::Success; } @@ -5594,43 +5759,93 @@ ParseStatus ARMAsmParser::parseAM3Offset(OperandVector &Operands) { return Error(Tok.getLoc(), "register expected"); } - Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift, - 0, S, Tok.getEndLoc())); + Operands.push_back(ARMOperand::CreatePostIdxReg( + Reg, isAdd, ARM_AM::no_shift, 0, S, Tok.getEndLoc(), *this)); return ParseStatus::Success; } +// Finds the index of the first CondCode operator, if there is none returns 0 +unsigned findCondCodeInd(const OperandVector &Operands, + unsigned MnemonicOpsEndInd) { + for (unsigned I = 1; I < MnemonicOpsEndInd; ++I) { + auto Op = static_cast<ARMOperand &>(*Operands[I]); + if (Op.isCondCode()) + return I; + } + return 0; +} + +unsigned findCCOutInd(const OperandVector &Operands, + unsigned MnemonicOpsEndInd) { + for (unsigned I = 1; I < MnemonicOpsEndInd; ++I) { + auto Op = static_cast<ARMOperand &>(*Operands[I]); + if (Op.isCCOut()) + return I; + } + return 0; +} + /// Convert parsed operands to MCInst. Needed here because this instruction /// only has two register operands, but multiplication is commutative so /// assemblers should accept both "mul rD, rN, rD" and "mul rD, rD, rN". void ARMAsmParser::cvtThumbMultiply(MCInst &Inst, const OperandVector &Operands) { - ((ARMOperand &)*Operands[3]).addRegOperands(Inst, 1); - ((ARMOperand &)*Operands[1]).addCCOutOperands(Inst, 1); - // If we have a three-operand form, make sure to set Rn to be the operand - // that isn't the same as Rd. - unsigned RegOp = 4; - if (Operands.size() == 6 && - ((ARMOperand &)*Operands[4]).getReg() == - ((ARMOperand &)*Operands[3]).getReg()) - RegOp = 5; - ((ARMOperand &)*Operands[RegOp]).addRegOperands(Inst, 1); - Inst.addOperand(Inst.getOperand(0)); - ((ARMOperand &)*Operands[2]).addCondCodeOperands(Inst, 2); + unsigned MnemonicOpsEndInd = getMnemonicOpsEndInd(Operands); + unsigned CondI = findCondCodeInd(Operands, MnemonicOpsEndInd); + unsigned CondOutI = findCCOutInd(Operands, MnemonicOpsEndInd); + + // 2 operand form + unsigned RegRd = MnemonicOpsEndInd; + unsigned RegRn = MnemonicOpsEndInd + 1; + unsigned RegRm = MnemonicOpsEndInd; + + if (Operands.size() == MnemonicOpsEndInd + 3) { + // If we have a three-operand form, make sure to set Rn to be the operand + // that isn't the same as Rd. + if (((ARMOperand &)*Operands[RegRd]).getReg() == + ((ARMOperand &)*Operands[MnemonicOpsEndInd + 1]).getReg()) { + RegRn = MnemonicOpsEndInd + 2; + RegRm = MnemonicOpsEndInd + 1; + } else { + RegRn = MnemonicOpsEndInd + 1; + RegRm = MnemonicOpsEndInd + 2; + } + } + + // Rd + ((ARMOperand &)*Operands[RegRd]).addRegOperands(Inst, 1); + // CCOut + if (CondOutI != 0) { + ((ARMOperand &)*Operands[CondOutI]).addCCOutOperands(Inst, 1); + } else { + ARMOperand Op = + *ARMOperand::CreateCCOut(0, Operands[0]->getEndLoc(), *this); + Op.addCCOutOperands(Inst, 1); + } + // Rn + ((ARMOperand &)*Operands[RegRn]).addRegOperands(Inst, 1); + // Rm + ((ARMOperand &)*Operands[RegRm]).addRegOperands(Inst, 1); + + // Cond code + if (CondI != 0) { + ((ARMOperand &)*Operands[CondI]).addCondCodeOperands(Inst, 2); + } else { + ARMOperand Op = *ARMOperand::CreateCondCode( + llvm::ARMCC::AL, Operands[0]->getEndLoc(), *this); + Op.addCondCodeOperands(Inst, 2); + } } void ARMAsmParser::cvtThumbBranches(MCInst &Inst, const OperandVector &Operands) { - int CondOp = -1, ImmOp = -1; - switch(Inst.getOpcode()) { - case ARM::tB: - case ARM::tBcc: CondOp = 1; ImmOp = 2; break; + unsigned MnemonicOpsEndInd = getMnemonicOpsEndInd(Operands); + unsigned CondI = findCondCodeInd(Operands, MnemonicOpsEndInd); + unsigned Cond = + (CondI == 0 ? ARMCC::AL + : static_cast<ARMOperand &>(*Operands[CondI]).getCondCode()); - case ARM::t2B: - case ARM::t2Bcc: CondOp = 1; ImmOp = 3; break; - - default: llvm_unreachable("Unexpected instruction in cvtThumbBranches"); - } // first decide whether or not the branch should be conditional // by looking at it's location relative to an IT block if(inITBlock()) { @@ -5641,9 +5856,6 @@ void ARMAsmParser::cvtThumbBranches(MCInst &Inst, case ARM::t2Bcc: Inst.setOpcode(ARM::t2B); break; } } else { - // outside IT blocks we can only have unconditional branches with AL - // condition code or conditional branches with non-AL condition code - unsigned Cond = static_cast<ARMOperand &>(*Operands[CondOp]).getCondCode(); switch(Inst.getOpcode()) { case ARM::tB: case ARM::tBcc: @@ -5660,36 +5872,56 @@ void ARMAsmParser::cvtThumbBranches(MCInst &Inst, switch(Inst.getOpcode()) { // classify tB as either t2B or t1B based on range of immediate operand case ARM::tB: { - ARMOperand &op = static_cast<ARMOperand &>(*Operands[ImmOp]); + ARMOperand &op = static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd]); if (!op.isSignedOffset<11, 1>() && isThumb() && hasV8MBaseline()) Inst.setOpcode(ARM::t2B); break; } // classify tBcc as either t2Bcc or t1Bcc based on range of immediate operand case ARM::tBcc: { - ARMOperand &op = static_cast<ARMOperand &>(*Operands[ImmOp]); + ARMOperand &op = static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd]); if (!op.isSignedOffset<8, 1>() && isThumb() && hasV8MBaseline()) Inst.setOpcode(ARM::t2Bcc); break; } } - ((ARMOperand &)*Operands[ImmOp]).addImmOperands(Inst, 1); - ((ARMOperand &)*Operands[CondOp]).addCondCodeOperands(Inst, 2); + ((ARMOperand &)*Operands[MnemonicOpsEndInd]).addImmOperands(Inst, 1); + if (CondI != 0) { + ((ARMOperand &)*Operands[CondI]).addCondCodeOperands(Inst, 2); + } else { + ARMOperand Op = *ARMOperand::CreateCondCode( + llvm::ARMCC::AL, Operands[0]->getEndLoc(), *this); + Op.addCondCodeOperands(Inst, 2); + } } void ARMAsmParser::cvtMVEVMOVQtoDReg( MCInst &Inst, const OperandVector &Operands) { - // mnemonic, condition code, Rt, Rt2, Qd, idx, Qd again, idx2 - assert(Operands.size() == 8); + unsigned MnemonicOpsEndInd = getMnemonicOpsEndInd(Operands); + unsigned CondI = findCondCodeInd(Operands, MnemonicOpsEndInd); - ((ARMOperand &)*Operands[2]).addRegOperands(Inst, 1); // Rt - ((ARMOperand &)*Operands[3]).addRegOperands(Inst, 1); // Rt2 - ((ARMOperand &)*Operands[4]).addRegOperands(Inst, 1); // Qd - ((ARMOperand &)*Operands[5]).addMVEPairVectorIndexOperands(Inst, 1); // idx + // mnemonic, condition code, Rt, Rt2, Qd, idx, Qd again, idx2 + assert(Operands.size() == MnemonicOpsEndInd + 6); + + ((ARMOperand &)*Operands[MnemonicOpsEndInd]).addRegOperands(Inst, 1); // Rt + ((ARMOperand &)*Operands[MnemonicOpsEndInd + 1]) + .addRegOperands(Inst, 1); // Rt2 + ((ARMOperand &)*Operands[MnemonicOpsEndInd + 2]) + .addRegOperands(Inst, 1); // Qd + ((ARMOperand &)*Operands[MnemonicOpsEndInd + 3]) + .addMVEPairVectorIndexOperands(Inst, 1); // idx // skip second copy of Qd in Operands[6] - ((ARMOperand &)*Operands[7]).addMVEPairVectorIndexOperands(Inst, 1); // idx2 - ((ARMOperand &)*Operands[1]).addCondCodeOperands(Inst, 2); // condition code + ((ARMOperand &)*Operands[MnemonicOpsEndInd + 5]) + .addMVEPairVectorIndexOperands(Inst, 1); // idx2 + if (CondI != 0) { + ((ARMOperand &)*Operands[CondI]) + .addCondCodeOperands(Inst, 2); // condition code + } else { + ARMOperand Op = + *ARMOperand::CreateCondCode(ARMCC::AL, Operands[0]->getEndLoc(), *this); + Op.addCondCodeOperands(Inst, 2); + } } /// Parse an ARM memory expression, return false if successful else return true @@ -5717,14 +5949,14 @@ bool ARMAsmParser::parseMemory(OperandVector &Operands) { E = Tok.getEndLoc(); Parser.Lex(); // Eat right bracket token. - Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, 0, - ARM_AM::no_shift, 0, 0, false, - S, E)); + Operands.push_back(ARMOperand::CreateMem( + BaseRegNum, nullptr, 0, ARM_AM::no_shift, 0, 0, false, S, E, *this)); // If there's a pre-indexing writeback marker, '!', just add it as a token // operand. It's rather odd, but syntactically valid. if (Parser.getTok().is(AsmToken::Exclaim)) { - Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); + Operands.push_back( + ARMOperand::CreateToken("!", Parser.getTok().getLoc(), *this)); Parser.Lex(); // Eat the '!'. } @@ -5775,13 +6007,14 @@ bool ARMAsmParser::parseMemory(OperandVector &Operands) { // Don't worry about range checking the value here. That's handled by // the is*() predicates. Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, 0, - ARM_AM::no_shift, 0, Align, - false, S, E, AlignmentLoc)); + ARM_AM::no_shift, 0, Align, false, + S, E, *this, AlignmentLoc)); // If there's a pre-indexing writeback marker, '!', just add it as a token // operand. if (Parser.getTok().is(AsmToken::Exclaim)) { - Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); + Operands.push_back( + ARMOperand::CreateToken("!", Parser.getTok().getLoc(), *this)); Parser.Lex(); // Eat the '!'. } @@ -5817,8 +6050,9 @@ bool ARMAsmParser::parseMemory(OperandVector &Operands) { AdjustedOffset = CE; } else AdjustedOffset = Offset; - Operands.push_back(ARMOperand::CreateMem( - BaseRegNum, AdjustedOffset, 0, ARM_AM::no_shift, 0, 0, false, S, E)); + Operands.push_back(ARMOperand::CreateMem(BaseRegNum, AdjustedOffset, 0, + ARM_AM::no_shift, 0, 0, false, S, + E, *this)); // Now we should have the closing ']' if (Parser.getTok().isNot(AsmToken::RBrac)) @@ -5829,7 +6063,8 @@ bool ARMAsmParser::parseMemory(OperandVector &Operands) { // If there's a pre-indexing writeback marker, '!', just add it as a token // operand. if (Parser.getTok().is(AsmToken::Exclaim)) { - Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); + Operands.push_back( + ARMOperand::CreateToken("!", Parser.getTok().getLoc(), *this)); Parser.Lex(); // Eat the '!'. } @@ -5868,12 +6103,13 @@ bool ARMAsmParser::parseMemory(OperandVector &Operands) { Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, OffsetRegNum, ShiftType, ShiftImm, 0, isNegative, - S, E)); + S, E, *this)); // If there's a pre-indexing writeback marker, '!', just add it as a token // operand. if (Parser.getTok().is(AsmToken::Exclaim)) { - Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc())); + Operands.push_back( + ARMOperand::CreateToken("!", Parser.getTok().getLoc(), *this)); Parser.Lex(); // Eat the '!'. } @@ -5948,6 +6184,8 @@ bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St, /// parseFPImm - A floating point immediate expression operand. ParseStatus ARMAsmParser::parseFPImm(OperandVector &Operands) { + LLVM_DEBUG(dbgs() << "PARSE FPImm, Ops: " << Operands.size()); + MCAsmParser &Parser = getParser(); // Anything that can accept a floating point constant as an operand // needs to go through here, as the regular parseExpression is @@ -5974,10 +6212,19 @@ ParseStatus ARMAsmParser::parseFPImm(OperandVector &Operands) { // integer constant. Make sure we don't try to parse an FPImm // for these: // vmov.i{8|16|32|64} <dreg|qreg>, #imm - ARMOperand &TyOp = static_cast<ARMOperand &>(*Operands[2]); - bool isVmovf = TyOp.isToken() && - (TyOp.getToken() == ".f32" || TyOp.getToken() == ".f64" || - TyOp.getToken() == ".f16"); + + bool isVmovf = false; + unsigned MnemonicOpsEndInd = getMnemonicOpsEndInd(Operands); + for (unsigned I = 1; I < MnemonicOpsEndInd; ++I) { + ARMOperand &TyOp = static_cast<ARMOperand &>(*Operands[I]); + if (TyOp.isToken() && + (TyOp.getToken() == ".f32" || TyOp.getToken() == ".f64" || + TyOp.getToken() == ".f16")) { + isVmovf = true; + break; + } + } + ARMOperand &Mnemonic = static_cast<ARMOperand &>(*Operands[0]); bool isFconst = Mnemonic.isToken() && (Mnemonic.getToken() == "fconstd" || Mnemonic.getToken() == "fconsts"); @@ -6000,9 +6247,9 @@ ParseStatus ARMAsmParser::parseFPImm(OperandVector &Operands) { // If we had a '-' in front, toggle the sign bit. IntVal ^= (uint64_t)isNegative << 31; Parser.Lex(); // Eat the token. - Operands.push_back(ARMOperand::CreateImm( - MCConstantExpr::create(IntVal, getContext()), - S, Parser.getTok().getLoc())); + Operands.push_back( + ARMOperand::CreateImm(MCConstantExpr::create(IntVal, getContext()), S, + Parser.getTok().getLoc(), *this)); return ParseStatus::Success; } // Also handle plain integers. Instructions which allow floating point @@ -6015,9 +6262,9 @@ ParseStatus ARMAsmParser::parseFPImm(OperandVector &Operands) { float RealVal = ARM_AM::getFPImmFloat(Val); Val = APFloat(RealVal).bitcastToAPInt().getZExtValue(); - Operands.push_back(ARMOperand::CreateImm( - MCConstantExpr::create(Val, getContext()), S, - Parser.getTok().getLoc())); + Operands.push_back( + ARMOperand::CreateImm(MCConstantExpr::create(Val, getContext()), S, + Parser.getTok().getLoc(), *this)); return ParseStatus::Success; } @@ -6063,7 +6310,7 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { Parser.getTok().getString().equals_insensitive("apsr_nzcv")) { S = Parser.getTok().getLoc(); Parser.Lex(); - Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S)); + Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S, *this)); return false; } } @@ -6083,7 +6330,7 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { if (getParser().parseExpression(IdVal)) return true; E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(ARMOperand::CreateImm(IdVal, S, E)); + Operands.push_back(ARMOperand::CreateImm(IdVal, S, E, *this)); return false; } case AsmToken::LBrac: @@ -6127,14 +6374,14 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { getContext()); } E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E)); + Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E, *this)); // There can be a trailing '!' on operands that we want as a separate // '!' Token operand. Handle that here. For example, the compatibility // alias for 'srsdb sp!, #imm' is 'srsdb #imm!'. if (Parser.getTok().is(AsmToken::Exclaim)) { - Operands.push_back(ARMOperand::CreateToken(Parser.getTok().getString(), - Parser.getTok().getLoc())); + Operands.push_back(ARMOperand::CreateToken( + Parser.getTok().getString(), Parser.getTok().getLoc(), *this)); Parser.Lex(); // Eat exclaim token } return false; @@ -6159,7 +6406,7 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { const MCExpr *ExprVal = ARMMCExpr::create(RefKind, SubExprVal, getContext()); E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E)); + Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E, *this)); return false; } case AsmToken::Equal: { @@ -6174,7 +6421,8 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { // execute-only: we assume that assembly programmers know what they are // doing and allow literal pool creation here - Operands.push_back(ARMOperand::CreateConstantPoolImm(SubExprVal, S, E)); + Operands.push_back( + ARMOperand::CreateConstantPoolImm(SubExprVal, S, E, *this)); return false; } } @@ -6493,18 +6741,30 @@ void ARMAsmParser::getMnemonicAcceptInfo(StringRef Mnemonic, CanAcceptPredicationCode = true; } +bool operandsContainWide(OperandVector &Operands, unsigned MnemonicOpsEndInd) { + for (unsigned I = 0; I < MnemonicOpsEndInd; ++I) { + auto &Op = static_cast<ARMOperand &>(*Operands[I]); + if (Op.isToken() && Op.getToken() == ".w") + return true; + } + return false; +} + // Some Thumb instructions have two operand forms that are not // available as three operand, convert to two operand form if possible. // // FIXME: We would really like to be able to tablegen'erate this. -void ARMAsmParser::tryConvertingToTwoOperandForm(StringRef Mnemonic, - bool CarrySetting, - OperandVector &Operands) { - if (Operands.size() != 6) +void ARMAsmParser::tryConvertingToTwoOperandForm( + StringRef Mnemonic, ARMCC::CondCodes PredicationCode, bool CarrySetting, + OperandVector &Operands, unsigned MnemonicOpsEndInd) { + + if (operandsContainWide(Operands, MnemonicOpsEndInd)) + return; + if (Operands.size() != MnemonicOpsEndInd + 3) return; - const auto &Op3 = static_cast<ARMOperand &>(*Operands[3]); - auto &Op4 = static_cast<ARMOperand &>(*Operands[4]); + const auto &Op3 = static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd]); + auto &Op4 = static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 1]); if (!Op3.isReg() || !Op4.isReg()) return; @@ -6515,7 +6775,7 @@ void ARMAsmParser::tryConvertingToTwoOperandForm(StringRef Mnemonic, // it in processInstruction(), but the 3 operand form of ADD (t2ADDrr) // won't accept SP or PC so we do the transformation here taking care // with immediate range in the 'add sp, sp #imm' case. - auto &Op5 = static_cast<ARMOperand &>(*Operands[5]); + auto &Op5 = static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 2]); if (isThumbTwo()) { if (Mnemonic != "add") return; @@ -6575,7 +6835,7 @@ void ARMAsmParser::tryConvertingToTwoOperandForm(StringRef Mnemonic, if (Transform) { if (Swap) std::swap(Op4, Op5); - Operands.erase(Operands.begin() + 3); + Operands.erase(Operands.begin() + MnemonicOpsEndInd); } } @@ -6600,183 +6860,9 @@ static bool isThumbI8Relocation(MCParsedAsmOperand &MCOp) { return false; } -bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic, - OperandVector &Operands) { - // FIXME: This is all horribly hacky. We really need a better way to deal - // with optional operands like this in the matcher table. - - // The 'mov' mnemonic is special. One variant has a cc_out operand, while - // another does not. Specifically, the MOVW instruction does not. So we - // special case it here and remove the defaulted (non-setting) cc_out - // operand if that's the instruction we're trying to match. - // - // We do this as post-processing of the explicit operands rather than just - // conditionally adding the cc_out in the first place because we need - // to check the type of the parsed immediate operand. - if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() && - !static_cast<ARMOperand &>(*Operands[4]).isModImm() && - static_cast<ARMOperand &>(*Operands[4]).isImm0_65535Expr() && - static_cast<ARMOperand &>(*Operands[1]).getReg() == 0) - return true; - - if (Mnemonic == "movs" && Operands.size() > 3 && isThumb() && - isThumbI8Relocation(*Operands[3])) - return true; - - // Register-register 'add' for thumb does not have a cc_out operand - // when there are only two register operands. - if (isThumb() && Mnemonic == "add" && Operands.size() == 5 && - static_cast<ARMOperand &>(*Operands[3]).isReg() && - static_cast<ARMOperand &>(*Operands[4]).isReg() && - static_cast<ARMOperand &>(*Operands[1]).getReg() == 0) - return true; - // Register-register 'add' for thumb does not have a cc_out operand - // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do - // have to check the immediate range here since Thumb2 has a variant - // that can handle a different range and has a cc_out operand. - if (((isThumb() && Mnemonic == "add") || - (isThumbTwo() && Mnemonic == "sub")) && - Operands.size() == 6 && static_cast<ARMOperand &>(*Operands[3]).isReg() && - static_cast<ARMOperand &>(*Operands[4]).isReg() && - static_cast<ARMOperand &>(*Operands[4]).getReg() == ARM::SP && - static_cast<ARMOperand &>(*Operands[1]).getReg() == 0 && - ((Mnemonic == "add" && static_cast<ARMOperand &>(*Operands[5]).isReg()) || - static_cast<ARMOperand &>(*Operands[5]).isImm0_1020s4())) - return true; - // For Thumb2, add/sub immediate does not have a cc_out operand for the - // imm0_4095 variant. That's the least-preferred variant when - // selecting via the generic "add" mnemonic, so to know that we - // should remove the cc_out operand, we have to explicitly check that - // it's not one of the other variants. Ugh. - if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") && - Operands.size() == 6 && static_cast<ARMOperand &>(*Operands[3]).isReg() && - static_cast<ARMOperand &>(*Operands[4]).isReg() && - static_cast<ARMOperand &>(*Operands[5]).isImm()) { - // Nest conditions rather than one big 'if' statement for readability. - // - // If both registers are low, we're in an IT block, and the immediate is - // in range, we should use encoding T1 instead, which has a cc_out. - if (inITBlock() && - isARMLowRegister(static_cast<ARMOperand &>(*Operands[3]).getReg()) && - isARMLowRegister(static_cast<ARMOperand &>(*Operands[4]).getReg()) && - static_cast<ARMOperand &>(*Operands[5]).isImm0_7()) - return false; - // Check against T3. If the second register is the PC, this is an - // alternate form of ADR, which uses encoding T4, so check for that too. - if (static_cast<ARMOperand &>(*Operands[4]).getReg() != ARM::PC && - (static_cast<ARMOperand &>(*Operands[5]).isT2SOImm() || - static_cast<ARMOperand &>(*Operands[5]).isT2SOImmNeg())) - return false; - - // Otherwise, we use encoding T4, which does not have a cc_out - // operand. - return true; - } - - // The thumb2 multiply instruction doesn't have a CCOut register, so - // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to - // use the 16-bit encoding or not. - if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 && - static_cast<ARMOperand &>(*Operands[1]).getReg() == 0 && - static_cast<ARMOperand &>(*Operands[3]).isReg() && - static_cast<ARMOperand &>(*Operands[4]).isReg() && - static_cast<ARMOperand &>(*Operands[5]).isReg() && - // If the registers aren't low regs, the destination reg isn't the - // same as one of the source regs, or the cc_out operand is zero - // outside of an IT block, we have to use the 32-bit encoding, so - // remove the cc_out operand. - (!isARMLowRegister(static_cast<ARMOperand &>(*Operands[3]).getReg()) || - !isARMLowRegister(static_cast<ARMOperand &>(*Operands[4]).getReg()) || - !isARMLowRegister(static_cast<ARMOperand &>(*Operands[5]).getReg()) || - !inITBlock() || (static_cast<ARMOperand &>(*Operands[3]).getReg() != - static_cast<ARMOperand &>(*Operands[5]).getReg() && - static_cast<ARMOperand &>(*Operands[3]).getReg() != - static_cast<ARMOperand &>(*Operands[4]).getReg()))) - return true; - - // Also check the 'mul' syntax variant that doesn't specify an explicit - // destination register. - if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 && - static_cast<ARMOperand &>(*Operands[1]).getReg() == 0 && - static_cast<ARMOperand &>(*Operands[3]).isReg() && - static_cast<ARMOperand &>(*Operands[4]).isReg() && - // If the registers aren't low regs or the cc_out operand is zero - // outside of an IT block, we have to use the 32-bit encoding, so - // remove the cc_out operand. - (!isARMLowRegister(static_cast<ARMOperand &>(*Operands[3]).getReg()) || - !isARMLowRegister(static_cast<ARMOperand &>(*Operands[4]).getReg()) || - !inITBlock())) - return true; - - // Register-register 'add/sub' for thumb does not have a cc_out operand - // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also - // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't - // right, this will result in better diagnostics (which operand is off) - // anyway. - if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") && - (Operands.size() == 5 || Operands.size() == 6) && - static_cast<ARMOperand &>(*Operands[3]).isReg() && - static_cast<ARMOperand &>(*Operands[3]).getReg() == ARM::SP && - static_cast<ARMOperand &>(*Operands[1]).getReg() == 0 && - (static_cast<ARMOperand &>(*Operands[4]).isImm() || - (Operands.size() == 6 && - static_cast<ARMOperand &>(*Operands[5]).isImm()))) { - // Thumb2 (add|sub){s}{p}.w GPRnopc, sp, #{T2SOImm} has cc_out - return (!(isThumbTwo() && - (static_cast<ARMOperand &>(*Operands[4]).isT2SOImm() || - static_cast<ARMOperand &>(*Operands[4]).isT2SOImmNeg()))); - } - // Fixme: Should join all the thumb+thumb2 (add|sub) in a single if case - // Thumb2 ADD r0, #4095 -> ADDW r0, r0, #4095 (T4) - // Thumb2 SUB r0, #4095 -> SUBW r0, r0, #4095 - if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") && - (Operands.size() == 5) && - static_cast<ARMOperand &>(*Operands[3]).isReg() && - static_cast<ARMOperand &>(*Operands[3]).getReg() != ARM::SP && - static_cast<ARMOperand &>(*Operands[3]).getReg() != ARM::PC && - static_cast<ARMOperand &>(*Operands[1]).getReg() == 0 && - static_cast<ARMOperand &>(*Operands[4]).isImm()) { - const ARMOperand &IMM = static_cast<ARMOperand &>(*Operands[4]); - if (IMM.isT2SOImm() || IMM.isT2SOImmNeg()) - return false; // add.w / sub.w - if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(IMM.getImm())) { - const int64_t Value = CE->getValue(); - // Thumb1 imm8 sub / add - if ((Value < ((1 << 7) - 1) << 2) && inITBlock() && (!(Value & 3)) && - isARMLowRegister(static_cast<ARMOperand &>(*Operands[3]).getReg())) - return false; - return true; // Thumb2 T4 addw / subw - } - } - return false; -} - -bool ARMAsmParser::shouldOmitPredicateOperand(StringRef Mnemonic, - OperandVector &Operands) { - // VRINT{Z, X} have a predicate operand in VFP, but not in NEON - unsigned RegIdx = 3; - if ((((Mnemonic == "vrintz" || Mnemonic == "vrintx") && !hasMVE()) || - Mnemonic == "vrintr") && - (static_cast<ARMOperand &>(*Operands[2]).getToken() == ".f32" || - static_cast<ARMOperand &>(*Operands[2]).getToken() == ".f16")) { - if (static_cast<ARMOperand &>(*Operands[3]).isToken() && - (static_cast<ARMOperand &>(*Operands[3]).getToken() == ".f32" || - static_cast<ARMOperand &>(*Operands[3]).getToken() == ".f16")) - RegIdx = 4; - - if (static_cast<ARMOperand &>(*Operands[RegIdx]).isReg() && - (ARMMCRegisterClasses[ARM::DPRRegClassID].contains( - static_cast<ARMOperand &>(*Operands[RegIdx]).getReg()) || - ARMMCRegisterClasses[ARM::QPRRegClassID].contains( - static_cast<ARMOperand &>(*Operands[RegIdx]).getReg()))) - return true; - } - return false; -} - -bool ARMAsmParser::shouldOmitVectorPredicateOperand(StringRef Mnemonic, - OperandVector &Operands) { - if (!hasMVE() || Operands.size() < 3) +bool ARMAsmParser::shouldOmitVectorPredicateOperand( + StringRef Mnemonic, OperandVector &Operands, unsigned MnemonicOpsEndInd) { + if (!hasMVE() || Operands.size() <= MnemonicOpsEndInd) return true; if (Mnemonic.starts_with("vld2") || Mnemonic.starts_with("vld4") || @@ -6806,24 +6892,13 @@ bool ARMAsmParser::shouldOmitVectorPredicateOperand(StringRef Mnemonic, // MQPR, to more accurately report errors when using Q registers // outside of the allowed range. if (static_cast<ARMOperand &>(*Operand).isVectorIndex() || - (Operand->isReg() && - (ARMMCRegisterClasses[ARM::QPRRegClassID].contains( - Operand->getReg())))) + static_cast<ARMOperand &>(*Operand).isQReg()) return false; } return true; } } -static bool isDataTypeToken(StringRef Tok) { - return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" || - Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" || - Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" || - Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" || - Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" || - Tok == ".f" || Tok == ".d"; -} - // FIXME: This bit should probably be handled via an explicit match class // in the .td files that matches the suffix instead of having it be // a literal string token the way it is now. @@ -6835,8 +6910,9 @@ static void applyMnemonicAliases(StringRef &Mnemonic, const FeatureBitset &Features, unsigned VariantID); -// The GNU assembler has aliases of ldrd and strd with the second register -// omitted. We don't have a way to do that in tablegen, so fix it up here. +// The GNU assembler has aliases of ldrd, strd, ldrexd, strexd, ldaexd, and +// stlexd with the second register omitted. We don't have a way to do that in +// tablegen, so fix it up here. // // We have to be careful to not emit an invalid Rt2 here, because the rest of // the assembly parser could then generate confusing diagnostics refering to @@ -6844,14 +6920,21 @@ static void applyMnemonicAliases(StringRef &Mnemonic, // bail out, and let the assembly parser report an error on the instruction as // it is written. void ARMAsmParser::fixupGNULDRDAlias(StringRef Mnemonic, - OperandVector &Operands) { - if (Mnemonic != "ldrd" && Mnemonic != "strd") + OperandVector &Operands, + unsigned MnemonicOpsEndInd) { + if (Mnemonic != "ldrd" && Mnemonic != "strd" && Mnemonic != "ldrexd" && + Mnemonic != "strexd" && Mnemonic != "ldaexd" && Mnemonic != "stlexd") return; - if (Operands.size() < 4) + + unsigned IdX = Mnemonic == "strexd" || Mnemonic == "stlexd" + ? MnemonicOpsEndInd + 1 + : MnemonicOpsEndInd; + + if (Operands.size() < IdX + 2) return; - ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[2]); - ARMOperand &Op3 = static_cast<ARMOperand &>(*Operands[3]); + ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[IdX]); + ARMOperand &Op3 = static_cast<ARMOperand &>(*Operands[IdX + 1]); if (!Op2.isReg()) return; @@ -6875,9 +6958,9 @@ void ARMAsmParser::fixupGNULDRDAlias(StringRef Mnemonic, (PairedReg == ARM::SP && !hasV8Ops())) return; - Operands.insert( - Operands.begin() + 3, - ARMOperand::CreateReg(PairedReg, Op2.getStartLoc(), Op2.getEndLoc())); + Operands.insert(Operands.begin() + IdX + 1, + ARMOperand::CreateReg(PairedReg, Op2.getStartLoc(), + Op2.getEndLoc(), *this)); } // Dual-register instruction have the following syntax: @@ -6886,19 +6969,17 @@ void ARMAsmParser::fixupGNULDRDAlias(StringRef Mnemonic, // operand. If the conversion fails an error is diagnosed, and the function // returns true. bool ARMAsmParser::CDEConvertDualRegOperand(StringRef Mnemonic, - OperandVector &Operands) { + OperandVector &Operands, + unsigned MnemonicOpsEndInd) { assert(MS.isCDEDualRegInstr(Mnemonic)); - bool isPredicable = - Mnemonic == "cx1da" || Mnemonic == "cx2da" || Mnemonic == "cx3da"; - size_t NumPredOps = isPredicable ? 1 : 0; - if (Operands.size() <= 3 + NumPredOps) + if (Operands.size() < 3 + MnemonicOpsEndInd) return false; StringRef Op2Diag( "operand must be an even-numbered register in the range [r0, r10]"); - const MCParsedAsmOperand &Op2 = *Operands[2 + NumPredOps]; + const MCParsedAsmOperand &Op2 = *Operands[MnemonicOpsEndInd + 1]; if (!Op2.isReg()) return Error(Op2.getStartLoc(), Op2Diag); @@ -6933,16 +7014,43 @@ bool ARMAsmParser::CDEConvertDualRegOperand(StringRef Mnemonic, break; } - const MCParsedAsmOperand &Op3 = *Operands[3 + NumPredOps]; + const MCParsedAsmOperand &Op3 = *Operands[MnemonicOpsEndInd + 2]; if (!Op3.isReg() || Op3.getReg() != RNext) return Error(Op3.getStartLoc(), "operand must be a consecutive register"); - Operands.erase(Operands.begin() + 3 + NumPredOps); - Operands[2 + NumPredOps] = - ARMOperand::CreateReg(RPair, Op2.getStartLoc(), Op2.getEndLoc()); + Operands.erase(Operands.begin() + MnemonicOpsEndInd + 2); + Operands[MnemonicOpsEndInd + 1] = + ARMOperand::CreateReg(RPair, Op2.getStartLoc(), Op2.getEndLoc(), *this); return false; } +void removeCondCode(OperandVector &Operands, unsigned &MnemonicOpsEndInd) { + for (unsigned I = 0; I < MnemonicOpsEndInd; ++I) + if (static_cast<ARMOperand &>(*Operands[I]).isCondCode()) { + Operands.erase(Operands.begin() + I); + --MnemonicOpsEndInd; + break; + } +} + +void removeCCOut(OperandVector &Operands, unsigned &MnemonicOpsEndInd) { + for (unsigned I = 0; I < MnemonicOpsEndInd; ++I) + if (static_cast<ARMOperand &>(*Operands[I]).isCCOut()) { + Operands.erase(Operands.begin() + I); + --MnemonicOpsEndInd; + break; + } +} + +void removeVPTCondCode(OperandVector &Operands, unsigned &MnemonicOpsEndInd) { + for (unsigned I = 0; I < MnemonicOpsEndInd; ++I) + if (static_cast<ARMOperand &>(*Operands[I]).isVPTPred()) { + Operands.erase(Operands.begin() + I); + --MnemonicOpsEndInd; + break; + } +} + /// Parse an arm instruction mnemonic followed by its operands. bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) { @@ -6985,7 +7093,7 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, return Error(NameLoc, "conditional execution not supported in Thumb1"); } - Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc)); + Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc, *this)); // Handle the mask for IT and VPT instructions. In ARMOperand and // MCOperand, this is stored in a format independent of the @@ -7017,7 +7125,7 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, if (Pos == 'e') Mask |= 8; } - Operands.push_back(ARMOperand::CreateITMask(Mask, Loc)); + Operands.push_back(ARMOperand::CreateITMask(Mask, Loc, *this)); } // FIXME: This is all a pretty gross hack. We should automatically handle @@ -7055,42 +7163,37 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, } // Add the carry setting operand, if necessary. - if (CanAcceptCarrySet) { + if (CanAcceptCarrySet && CarrySetting) { SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size()); - Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0, - Loc)); + Operands.push_back( + ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0, Loc, *this)); } // Add the predication code operand, if necessary. - if (CanAcceptPredicationCode) { + if (CanAcceptPredicationCode && PredicationCode != llvm::ARMCC::AL) { SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() + CarrySetting); Operands.push_back(ARMOperand::CreateCondCode( - ARMCC::CondCodes(PredicationCode), Loc)); + ARMCC::CondCodes(PredicationCode), Loc, *this)); } // Add the VPT predication code operand, if necessary. - // FIXME: We don't add them for the instructions filtered below as these can - // have custom operands which need special parsing. This parsing requires - // the operand to be in the same place in the OperandVector as their - // definition in tblgen. Since these instructions may also have the - // scalar predication operand we do not add the vector one and leave until - // now to fix it up. - if (CanAcceptVPTPredicationCode && Mnemonic != "vmov" && - !Mnemonic.starts_with("vcmp") && + // Dont add in certain cases of VCVT as this needs to be disambiguated + // after operand parsing. + if (CanAcceptVPTPredicationCode && VPTPredicationCode != llvm::ARMVCC::None && !(Mnemonic.starts_with("vcvt") && Mnemonic != "vcvta" && Mnemonic != "vcvtn" && Mnemonic != "vcvtp" && Mnemonic != "vcvtm")) { SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() + CarrySetting); Operands.push_back(ARMOperand::CreateVPTPred( - ARMVCC::VPTCodes(VPTPredicationCode), Loc)); + ARMVCC::VPTCodes(VPTPredicationCode), Loc, *this)); } // Add the processor imod operand, if necessary. if (ProcessorIMod) { Operands.push_back(ARMOperand::CreateImm( - MCConstantExpr::create(ProcessorIMod, getContext()), - NameLoc, NameLoc)); + MCConstantExpr::create(ProcessorIMod, getContext()), NameLoc, NameLoc, + *this)); } else if (Mnemonic == "cps" && isMClass()) { return Error(NameLoc, "instruction 'cps' requires effect for M-class"); } @@ -7119,10 +7222,15 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // so discard it to avoid errors that can be caused by the matcher. if (ExtraToken != ".n" && (isThumb() || ExtraToken != ".w")) { SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start); - Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc)); + Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc, *this)); } } + // This marks the end of the LHS Mnemonic operators. + // This is used for indexing into the non-menmonic operators as some of the + // mnemonic operators are optional and therfore indexes can differ. + unsigned MnemonicOpsEndInd = Operands.size(); + // Read the remaining operands. if (getLexer().isNot(AsmToken::EndOfStatement)) { // Read the first operand. @@ -7141,7 +7249,8 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list")) return true; - tryConvertingToTwoOperandForm(Mnemonic, CarrySetting, Operands); + tryConvertingToTwoOperandForm(Mnemonic, PredicationCode, CarrySetting, + Operands, MnemonicOpsEndInd); if (hasCDE() && MS.isCDEInstr(Mnemonic)) { // Dual-register instructions use even-odd register pairs as their @@ -7152,33 +7261,16 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // returns false, the function either succeeded or an error (e.g. missing // operand) will be diagnosed elsewhere. if (MS.isCDEDualRegInstr(Mnemonic)) { - bool GotError = CDEConvertDualRegOperand(Mnemonic, Operands); + bool GotError = + CDEConvertDualRegOperand(Mnemonic, Operands, MnemonicOpsEndInd); if (GotError) return GotError; } } - // Some instructions, mostly Thumb, have forms for the same mnemonic that - // do and don't have a cc_out optional-def operand. With some spot-checks - // of the operand list, we can figure out which variant we're trying to - // parse and adjust accordingly before actually matching. We shouldn't ever - // try to remove a cc_out operand that was explicitly set on the - // mnemonic, of course (CarrySetting == true). Reason number #317 the - // table driven matcher doesn't fit well with the ARM instruction set. - if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) - Operands.erase(Operands.begin() + 1); - - // Some instructions have the same mnemonic, but don't always - // have a predicate. Distinguish them here and delete the - // appropriate predicate if needed. This could be either the scalar - // predication code or the vector predication code. - if (PredicationCode == ARMCC::AL && - shouldOmitPredicateOperand(Mnemonic, Operands)) - Operands.erase(Operands.begin() + 1); - - if (hasMVE()) { - if (!shouldOmitVectorPredicateOperand(Mnemonic, Operands) && + if (!shouldOmitVectorPredicateOperand(Mnemonic, Operands, + MnemonicOpsEndInd) && Mnemonic == "vmov" && PredicationCode == ARMCC::LT) { // Very nasty hack to deal with the vector predicated variant of vmovlt // the scalar predicated vmov with condition 'lt'. We can not tell them @@ -7189,11 +7281,12 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc PLoc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() - 1 + CarrySetting); Operands.insert(Operands.begin(), - ARMOperand::CreateVPTPred(ARMVCC::None, PLoc)); - Operands.insert(Operands.begin(), - ARMOperand::CreateToken(StringRef("vmovlt"), MLoc)); + ARMOperand::CreateVPTPred(ARMVCC::None, PLoc, *this)); + Operands.insert(Operands.begin(), ARMOperand::CreateToken( + StringRef("vmovlt"), MLoc, *this)); } else if (Mnemonic == "vcvt" && PredicationCode == ARMCC::NE && - !shouldOmitVectorPredicateOperand(Mnemonic, Operands)) { + !shouldOmitVectorPredicateOperand(Mnemonic, Operands, + MnemonicOpsEndInd)) { // Another nasty hack to deal with the ambiguity between vcvt with scalar // predication 'ne' and vcvtn with vector predication 'e'. As above we // can only distinguish between the two after we have parsed their @@ -7204,40 +7297,37 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc PLoc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() - 1 + CarrySetting); Operands.insert(Operands.begin(), - ARMOperand::CreateVPTPred(ARMVCC::Else, PLoc)); + ARMOperand::CreateVPTPred(ARMVCC::Else, PLoc, *this)); Operands.insert(Operands.begin(), - ARMOperand::CreateToken(StringRef("vcvtn"), MLoc)); + ARMOperand::CreateToken(StringRef("vcvtn"), MLoc, *this)); } else if (Mnemonic == "vmul" && PredicationCode == ARMCC::LT && - !shouldOmitVectorPredicateOperand(Mnemonic, Operands)) { + !shouldOmitVectorPredicateOperand(Mnemonic, Operands, + MnemonicOpsEndInd)) { // Another hack, this time to distinguish between scalar predicated vmul // with 'lt' predication code and the vector instruction vmullt with // vector predication code "none" - Operands.erase(Operands.begin() + 1); + removeCondCode(Operands, MnemonicOpsEndInd); Operands.erase(Operands.begin()); SMLoc MLoc = SMLoc::getFromPointer(NameLoc.getPointer()); - Operands.insert(Operands.begin(), - ARMOperand::CreateToken(StringRef("vmullt"), MLoc)); - } - // For vmov and vcmp, as mentioned earlier, we did not add the vector - // predication code, since these may contain operands that require - // special parsing. So now we have to see if they require vector - // predication and replace the scalar one with the vector predication - // operand if that is the case. - else if (Mnemonic == "vmov" || Mnemonic.starts_with("vcmp") || - (Mnemonic.starts_with("vcvt") && !Mnemonic.starts_with("vcvta") && - !Mnemonic.starts_with("vcvtn") && - !Mnemonic.starts_with("vcvtp") && - !Mnemonic.starts_with("vcvtm"))) { - if (!shouldOmitVectorPredicateOperand(Mnemonic, Operands)) { + Operands.insert(Operands.begin(), ARMOperand::CreateToken( + StringRef("vmullt"), MLoc, *this)); + } else if (Mnemonic.starts_with("vcvt") && !Mnemonic.starts_with("vcvta") && + !Mnemonic.starts_with("vcvtn") && + !Mnemonic.starts_with("vcvtp") && + !Mnemonic.starts_with("vcvtm")) { + if (!shouldOmitVectorPredicateOperand(Mnemonic, Operands, + MnemonicOpsEndInd)) { // We could not split the vector predicate off vcvt because it might // have been the scalar vcvtt instruction. Now we know its a vector // instruction, we still need to check whether its the vector // predicated vcvt with 'Then' predication or the vector vcvtt. We can // distinguish the two based on the suffixes, if it is any of // ".f16.f32", ".f32.f16", ".f16.f64" or ".f64.f16" then it is the vcvtt. - if (Mnemonic.starts_with("vcvtt") && Operands.size() >= 4) { - auto Sz1 = static_cast<ARMOperand &>(*Operands[2]); - auto Sz2 = static_cast<ARMOperand &>(*Operands[3]); + if (Mnemonic.starts_with("vcvtt") && MnemonicOpsEndInd > 2) { + auto Sz1 = + static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd - 2]); + auto Sz2 = + static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd - 1]); if (!(Sz1.isToken() && Sz1.getToken().starts_with(".f") && Sz2.isToken() && Sz2.getToken().starts_with(".f"))) { Operands.erase(Operands.begin()); @@ -7246,27 +7336,24 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, Mnemonic = Mnemonic.substr(0, 4); Operands.insert(Operands.begin(), - ARMOperand::CreateToken(Mnemonic, MLoc)); + ARMOperand::CreateToken(Mnemonic, MLoc, *this)); } } - Operands.erase(Operands.begin() + 1); SMLoc PLoc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() + CarrySetting); + // Add VPTPred Operands.insert(Operands.begin() + 1, ARMOperand::CreateVPTPred( - ARMVCC::VPTCodes(VPTPredicationCode), PLoc)); + ARMVCC::VPTCodes(VPTPredicationCode), PLoc, *this)); + ++MnemonicOpsEndInd; } } else if (CanAcceptVPTPredicationCode) { // For all other instructions, make sure only one of the two // predication operands is left behind, depending on whether we should // use the vector predication. - if (shouldOmitVectorPredicateOperand(Mnemonic, Operands)) { - if (CanAcceptPredicationCode) - Operands.erase(Operands.begin() + 2); - else - Operands.erase(Operands.begin() + 1); - } else if (CanAcceptPredicationCode && PredicationCode == ARMCC::AL) { - Operands.erase(Operands.begin() + 1); + if (shouldOmitVectorPredicateOperand(Mnemonic, Operands, + MnemonicOpsEndInd)) { + removeVPTCondCode(Operands, MnemonicOpsEndInd); } } } @@ -7287,73 +7374,82 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, Mnemonic = Name.slice(0, Mnemonic.size() + 1); Operands.erase(Operands.begin()); Operands.insert(Operands.begin(), - ARMOperand::CreateToken(Mnemonic, NameLoc)); + ARMOperand::CreateToken(Mnemonic, NameLoc, *this)); } } - // ARM mode 'blx' need special handling, as the register operand version - // is predicable, but the label operand version is not. So, we can't rely - // on the Mnemonic based checking to correctly figure out when to put - // a k_CondCode operand in the list. If we're trying to match the label - // version, remove the k_CondCode operand here. - if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 && - static_cast<ARMOperand &>(*Operands[2]).isImm()) - Operands.erase(Operands.begin() + 1); - - // Adjust operands of ldrexd/strexd to MCK_GPRPair. - // ldrexd/strexd require even/odd GPR pair. To enforce this constraint, - // a single GPRPair reg operand is used in the .td file to replace the two - // GPRs. However, when parsing from asm, the two GRPs cannot be - // automatically - // expressed as a GPRPair, so we have to manually merge them. - // FIXME: We would really like to be able to tablegen'erate this. - if (!isThumb() && Operands.size() > 4 && - (Mnemonic == "ldrexd" || Mnemonic == "strexd" || Mnemonic == "ldaexd" || - Mnemonic == "stlexd")) { - bool isLoad = (Mnemonic == "ldrexd" || Mnemonic == "ldaexd"); - unsigned Idx = isLoad ? 2 : 3; - ARMOperand &Op1 = static_cast<ARMOperand &>(*Operands[Idx]); - ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[Idx + 1]); - - const MCRegisterClass &MRC = MRI->getRegClass(ARM::GPRRegClassID); - // Adjust only if Op1 and Op2 are GPRs. - if (Op1.isReg() && Op2.isReg() && MRC.contains(Op1.getReg()) && - MRC.contains(Op2.getReg())) { - unsigned Reg1 = Op1.getReg(); - unsigned Reg2 = Op2.getReg(); - unsigned Rt = MRI->getEncodingValue(Reg1); - unsigned Rt2 = MRI->getEncodingValue(Reg2); - - // Rt2 must be Rt + 1 and Rt must be even. - if (Rt + 1 != Rt2 || (Rt & 1)) { - return Error(Op2.getStartLoc(), - isLoad ? "destination operands must be sequential" - : "source operands must be sequential"); - } - unsigned NewReg = MRI->getMatchingSuperReg( - Reg1, ARM::gsub_0, &(MRI->getRegClass(ARM::GPRPairRegClassID))); - Operands[Idx] = - ARMOperand::CreateReg(NewReg, Op1.getStartLoc(), Op2.getEndLoc()); - Operands.erase(Operands.begin() + Idx + 1); - } - } + // ARM mode 'blx' need special handling, as the register operand version + // is predicable, but the label operand version is not. So, we can't rely + // on the Mnemonic based checking to correctly figure out when to put + // a k_CondCode operand in the list. If we're trying to match the label + // version, remove the k_CondCode operand here. + if (!isThumb() && Mnemonic == "blx" && + Operands.size() == MnemonicOpsEndInd + 1 && + static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd]).isImm()) + removeCondCode(Operands, MnemonicOpsEndInd); // GNU Assembler extension (compatibility). - fixupGNULDRDAlias(Mnemonic, Operands); + fixupGNULDRDAlias(Mnemonic, Operands, MnemonicOpsEndInd); + + // Adjust operands of ldrexd/strexd to MCK_GPRPair. + // ldrexd/strexd require even/odd GPR pair. To enforce this constraint, + // a single GPRPair reg operand is used in the .td file to replace the two + // GPRs. However, when parsing from asm, the two GRPs cannot be + // automatically + // expressed as a GPRPair, so we have to manually merge them. + // FIXME: We would really like to be able to tablegen'erate this. + bool IsLoad = (Mnemonic == "ldrexd" || Mnemonic == "ldaexd"); + if (!isThumb() && Operands.size() > MnemonicOpsEndInd + 1 + (!IsLoad) && + (Mnemonic == "ldrexd" || Mnemonic == "strexd" || Mnemonic == "ldaexd" || + Mnemonic == "stlexd")) { + unsigned Idx = IsLoad ? MnemonicOpsEndInd : MnemonicOpsEndInd + 1; + ARMOperand &Op1 = static_cast<ARMOperand &>(*Operands[Idx]); + ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[Idx + 1]); + + const MCRegisterClass &MRC = MRI->getRegClass(ARM::GPRRegClassID); + // Adjust only if Op1 is a GPR. + if (Op1.isReg() && MRC.contains(Op1.getReg())) { + unsigned Reg1 = Op1.getReg(); + unsigned Rt = MRI->getEncodingValue(Reg1); + unsigned Reg2 = Op2.getReg(); + unsigned Rt2 = MRI->getEncodingValue(Reg2); + // Rt2 must be Rt + 1. + if (Rt + 1 != Rt2) + return Error(Op2.getStartLoc(), + IsLoad ? "destination operands must be sequential" + : "source operands must be sequential"); + + // Rt must be even + if (Rt & 1) + return Error( + Op1.getStartLoc(), + IsLoad ? "destination operands must start start at an even register" + : "source operands must start start at an even register"); + + unsigned NewReg = MRI->getMatchingSuperReg( + Reg1, ARM::gsub_0, &(MRI->getRegClass(ARM::GPRPairRegClassID))); + Operands[Idx] = ARMOperand::CreateReg(NewReg, Op1.getStartLoc(), + Op2.getEndLoc(), *this); + Operands.erase(Operands.begin() + Idx + 1); + } + } // FIXME: As said above, this is all a pretty gross hack. This instruction // does not fit with other "subs" and tblgen. // Adjust operands of B9.3.19 SUBS PC, LR, #imm (Thumb2) system instruction // so the Mnemonic is the original name "subs" and delete the predicate // operand so it will match the table entry. - if (isThumbTwo() && Mnemonic == "sub" && Operands.size() == 6 && - static_cast<ARMOperand &>(*Operands[3]).isReg() && - static_cast<ARMOperand &>(*Operands[3]).getReg() == ARM::PC && - static_cast<ARMOperand &>(*Operands[4]).isReg() && - static_cast<ARMOperand &>(*Operands[4]).getReg() == ARM::LR && - static_cast<ARMOperand &>(*Operands[5]).isImm()) { - Operands.front() = ARMOperand::CreateToken(Name, NameLoc); - Operands.erase(Operands.begin() + 1); + if (isThumbTwo() && Mnemonic == "sub" && + Operands.size() == MnemonicOpsEndInd + 3 && + static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd]).isReg() && + static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd]).getReg() == + ARM::PC && + static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 1]).isReg() && + static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 1]).getReg() == + ARM::LR && + static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 2]).isImm()) { + Operands.front() = ARMOperand::CreateToken(Name, NameLoc, *this); + removeCCOut(Operands, MnemonicOpsEndInd); } return false; } @@ -7398,49 +7494,61 @@ static bool instIsBreakpoint(const MCInst &Inst) { Inst.getOpcode() == ARM::HLT; } +unsigned getRegListInd(const OperandVector &Operands, + unsigned MnemonicOpsEndInd) { + for (unsigned I = MnemonicOpsEndInd; I < Operands.size(); ++I) { + const ARMOperand &Op = static_cast<const ARMOperand &>(*Operands[I]); + if (Op.isRegList()) { + return I; + } + } + return 0; +} + bool ARMAsmParser::validatetLDMRegList(const MCInst &Inst, const OperandVector &Operands, - unsigned ListNo, bool IsARPop) { - const ARMOperand &Op = static_cast<const ARMOperand &>(*Operands[ListNo]); - bool HasWritebackToken = Op.isToken() && Op.getToken() == "!"; - - bool ListContainsSP = listContainsReg(Inst, ListNo, ARM::SP); - bool ListContainsLR = listContainsReg(Inst, ListNo, ARM::LR); - bool ListContainsPC = listContainsReg(Inst, ListNo, ARM::PC); + unsigned MnemonicOpsEndInd, + unsigned ListIndex, bool IsARPop) { + bool ListContainsSP = listContainsReg(Inst, ListIndex, ARM::SP); + bool ListContainsLR = listContainsReg(Inst, ListIndex, ARM::LR); + bool ListContainsPC = listContainsReg(Inst, ListIndex, ARM::PC); if (!IsARPop && ListContainsSP) - return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), - "SP may not be in the register list"); - else if (ListContainsPC && ListContainsLR) - return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), - "PC and LR may not be in the register list simultaneously"); + return Error( + Operands[getRegListInd(Operands, MnemonicOpsEndInd)]->getStartLoc(), + "SP may not be in the register list"); + if (ListContainsPC && ListContainsLR) + return Error( + Operands[getRegListInd(Operands, MnemonicOpsEndInd)]->getStartLoc(), + "PC and LR may not be in the register list simultaneously"); return false; } bool ARMAsmParser::validatetSTMRegList(const MCInst &Inst, const OperandVector &Operands, - unsigned ListNo) { - const ARMOperand &Op = static_cast<const ARMOperand &>(*Operands[ListNo]); - bool HasWritebackToken = Op.isToken() && Op.getToken() == "!"; - - bool ListContainsSP = listContainsReg(Inst, ListNo, ARM::SP); - bool ListContainsPC = listContainsReg(Inst, ListNo, ARM::PC); + unsigned MnemonicOpsEndInd, + unsigned ListIndex) { + bool ListContainsSP = listContainsReg(Inst, ListIndex, ARM::SP); + bool ListContainsPC = listContainsReg(Inst, ListIndex, ARM::PC); if (ListContainsSP && ListContainsPC) - return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), - "SP and PC may not be in the register list"); - else if (ListContainsSP) - return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), - "SP may not be in the register list"); - else if (ListContainsPC) - return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), - "PC may not be in the register list"); + return Error( + Operands[getRegListInd(Operands, MnemonicOpsEndInd)]->getStartLoc(), + "SP and PC may not be in the register list"); + if (ListContainsSP) + return Error( + Operands[getRegListInd(Operands, MnemonicOpsEndInd)]->getStartLoc(), + "SP may not be in the register list"); + if (ListContainsPC) + return Error( + Operands[getRegListInd(Operands, MnemonicOpsEndInd)]->getStartLoc(), + "PC may not be in the register list"); return false; } -bool ARMAsmParser::validateLDRDSTRD(MCInst &Inst, - const OperandVector &Operands, - bool Load, bool ARMMode, bool Writeback) { +bool ARMAsmParser::validateLDRDSTRD(MCInst &Inst, const OperandVector &Operands, + bool Load, bool ARMMode, bool Writeback, + unsigned MnemonicOpsEndInd) { unsigned RtIndex = Load || !Writeback ? 0 : 1; unsigned Rt = MRI->getEncodingValue(Inst.getOperand(RtIndex).getReg()); unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(RtIndex + 1).getReg()); @@ -7448,21 +7556,21 @@ bool ARMAsmParser::validateLDRDSTRD(MCInst &Inst, if (ARMMode) { // Rt can't be R14. if (Rt == 14) - return Error(Operands[3]->getStartLoc(), - "Rt can't be R14"); + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), + "Rt can't be R14"); // Rt must be even-numbered. if ((Rt & 1) == 1) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "Rt must be even-numbered"); // Rt2 must be Rt + 1. if (Rt2 != Rt + 1) { if (Load) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "destination operands must be sequential"); else - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "source operands must be sequential"); } @@ -7472,7 +7580,7 @@ bool ARMAsmParser::validateLDRDSTRD(MCInst &Inst, if (!ARMMode && Load) { if (Rt2 == Rt) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "destination operands can't be identical"); } @@ -7481,11 +7589,11 @@ bool ARMAsmParser::validateLDRDSTRD(MCInst &Inst, if (Rn == Rt || Rn == Rt2) { if (Load) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "base register needs to be different from destination " "registers"); else - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "source register and base register can't be identical"); } @@ -7523,7 +7631,8 @@ static bool isARMMCExpr(MCParsedAsmOperand &MCOp) { // FIXME: We would really like to be able to tablegen'erate this. bool ARMAsmParser::validateInstruction(MCInst &Inst, - const OperandVector &Operands) { + const OperandVector &Operands, + unsigned MnemonicOpsEndInd) { const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); SMLoc Loc = Operands[0]->getStartLoc(); @@ -7538,7 +7647,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm()); if (Cond != currentITCond()) { // Find the condition code Operand to get its SMLoc information. - SMLoc CondLoc; + SMLoc CondLoc = Operands[0]->getEndLoc(); for (unsigned I = 1; I < Operands.size(); ++I) if (static_cast<ARMOperand &>(*Operands[I]).isCondCode()) CondLoc = Operands[I]->getStartLoc(); @@ -7608,9 +7717,10 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, case ARM::VLSTM_T2: { // Since in some cases both T1 and T2 are valid, tablegen can not always // pick the correct instruction. - if (Operands.size() == 4) { // a register list has been provided + if (Operands.size() == + MnemonicOpsEndInd + 2) { // a register list has been provided ARMOperand &Op = static_cast<ARMOperand &>( - *Operands[3]); // the register list, a dpr_reglist + *Operands[MnemonicOpsEndInd + 1]); // the register list, a dpr_reglist assert(Op.isDPRRegList()); auto &RegList = Op.getRegList(); // T2 requires v8.1-M.Main (cannot be handled by tablegen) @@ -7644,50 +7754,50 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, break; } case ARM::LDRD: - if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/true, - /*Writeback*/false)) + if (validateLDRDSTRD(Inst, Operands, /*Load*/ true, /*ARMMode*/ true, + /*Writeback*/ false, MnemonicOpsEndInd)) return true; break; case ARM::LDRD_PRE: case ARM::LDRD_POST: - if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/true, - /*Writeback*/true)) + if (validateLDRDSTRD(Inst, Operands, /*Load*/ true, /*ARMMode*/ true, + /*Writeback*/ true, MnemonicOpsEndInd)) return true; break; case ARM::t2LDRDi8: - if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/false, - /*Writeback*/false)) + if (validateLDRDSTRD(Inst, Operands, /*Load*/ true, /*ARMMode*/ false, + /*Writeback*/ false, MnemonicOpsEndInd)) return true; break; case ARM::t2LDRD_PRE: case ARM::t2LDRD_POST: - if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/false, - /*Writeback*/true)) + if (validateLDRDSTRD(Inst, Operands, /*Load*/ true, /*ARMMode*/ false, + /*Writeback*/ true, MnemonicOpsEndInd)) return true; break; case ARM::t2BXJ: { const unsigned RmReg = Inst.getOperand(0).getReg(); // Rm = SP is no longer unpredictable in v8-A if (RmReg == ARM::SP && !hasV8Ops()) - return Error(Operands[2]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "r13 (SP) is an unpredictable operand to BXJ"); return false; } case ARM::STRD: - if (validateLDRDSTRD(Inst, Operands, /*Load*/false, /*ARMMode*/true, - /*Writeback*/false)) + if (validateLDRDSTRD(Inst, Operands, /*Load*/ false, /*ARMMode*/ true, + /*Writeback*/ false, MnemonicOpsEndInd)) return true; break; case ARM::STRD_PRE: case ARM::STRD_POST: - if (validateLDRDSTRD(Inst, Operands, /*Load*/false, /*ARMMode*/true, - /*Writeback*/true)) + if (validateLDRDSTRD(Inst, Operands, /*Load*/ false, /*ARMMode*/ true, + /*Writeback*/ true, MnemonicOpsEndInd)) return true; break; case ARM::t2STRD_PRE: case ARM::t2STRD_POST: - if (validateLDRDSTRD(Inst, Operands, /*Load*/false, /*ARMMode*/false, - /*Writeback*/true)) + if (validateLDRDSTRD(Inst, Operands, /*Load*/ false, /*ARMMode*/ false, + /*Writeback*/ true, MnemonicOpsEndInd)) return true; break; case ARM::STR_PRE_IMM: @@ -7711,7 +7821,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(2).getReg()); if (Rt == Rn) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 1]->getStartLoc(), "source register and base register can't be identical"); return false; } @@ -7724,19 +7834,19 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(1).getReg()); if (Rt == Rn) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "destination register and base register can't be identical"); if (Inst.getOpcode() == ARM::t2LDR_POST_imm || Inst.getOpcode() == ARM::t2STR_POST_imm) { int Imm = Inst.getOperand(2).getImm(); if (Imm > 255 || Imm < -255) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "operand must be in range [-255, 255]"); } if (Inst.getOpcode() == ARM::t2STR_PRE_imm || Inst.getOpcode() == ARM::t2STR_POST_imm) { if (Inst.getOperand(0).getReg() == ARM::PC) { - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "operand must be a register in range [r0, r14]"); } } @@ -7755,17 +7865,17 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, Inst.getOpcode() == ARM::t2STRB_PRE_imm) { int Imm = Inst.getOperand(2).getImm(); if (Imm > 255 || Imm < -255) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "operand must be in range [-255, 255]"); } else if (Inst.getOpcode() == ARM::t2LDRB_OFFSET_imm || Inst.getOpcode() == ARM::t2STRB_OFFSET_imm) { int Imm = Inst.getOperand(2).getImm(); if (Imm > 0 || Imm < -255) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "operand must be in range [0, 255] with a negative sign"); } if (Inst.getOperand(0).getReg() == ARM::PC) { - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "if operand is PC, should call the LDRB (literal)"); } return false; @@ -7783,17 +7893,17 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, Inst.getOpcode() == ARM::t2STRH_PRE_imm) { int Imm = Inst.getOperand(2).getImm(); if (Imm > 255 || Imm < -255) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "operand must be in range [-255, 255]"); } else if (Inst.getOpcode() == ARM::t2LDRH_OFFSET_imm || Inst.getOpcode() == ARM::t2STRH_OFFSET_imm) { int Imm = Inst.getOperand(2).getImm(); if (Imm > 0 || Imm < -255) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "operand must be in range [0, 255] with a negative sign"); } if (Inst.getOperand(0).getReg() == ARM::PC) { - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "if operand is PC, should call the LDRH (literal)"); } return false; @@ -7806,16 +7916,16 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, Inst.getOpcode() == ARM::t2LDRSB_PRE_imm) { int Imm = Inst.getOperand(2).getImm(); if (Imm > 255 || Imm < -255) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "operand must be in range [-255, 255]"); } else if (Inst.getOpcode() == ARM::t2LDRSB_OFFSET_imm) { int Imm = Inst.getOperand(2).getImm(); if (Imm > 0 || Imm < -255) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "operand must be in range [0, 255] with a negative sign"); } if (Inst.getOperand(0).getReg() == ARM::PC) { - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "if operand is PC, should call the LDRH (literal)"); } return false; @@ -7828,16 +7938,16 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, Inst.getOpcode() == ARM::t2LDRSH_PRE_imm) { int Imm = Inst.getOperand(2).getImm(); if (Imm > 255 || Imm < -255) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "operand must be in range [-255, 255]"); } else if (Inst.getOpcode() == ARM::t2LDRSH_OFFSET_imm) { int Imm = Inst.getOperand(2).getImm(); if (Imm > 0 || Imm < -255) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "operand must be in range [0, 255] with a negative sign"); } if (Inst.getOperand(0).getReg() == ARM::PC) { - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "if operand is PC, should call the LDRH (literal)"); } return false; @@ -7872,7 +7982,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(2).getReg()); if (Rt == Rn) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "destination register and base register can't be identical"); return false; } @@ -7916,10 +8026,10 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, const unsigned Qm = MRI->getEncodingValue(Inst.getOperand(QmIdx).getReg()); if (Qd == Qm) { - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), Twine("destination vector register and vector ") + - (QmIsPointer ? "pointer" : "offset") + - " register can't be identical"); + (QmIsPointer ? "pointer" : "offset") + + " register can't be identical"); } return false; } @@ -7932,7 +8042,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, unsigned LSB = Inst.getOperand(2).getImm(); unsigned Widthm1 = Inst.getOperand(3).getImm(); if (Widthm1 >= 32 - LSB) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "bitfield width must be in range [1,32-lsb]"); return false; } @@ -7946,24 +8056,29 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, // in the register list. unsigned Rn = Inst.getOperand(0).getReg(); bool HasWritebackToken = - (static_cast<ARMOperand &>(*Operands[3]).isToken() && - static_cast<ARMOperand &>(*Operands[3]).getToken() == "!"); + (static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 1]) + .isToken() && + static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 1]) + .getToken() == "!"); + bool ListContainsBase; if (checkLowRegisterList(Inst, 3, Rn, 0, ListContainsBase) && !isThumbTwo()) - return Error(Operands[3 + HasWritebackToken]->getStartLoc(), - "registers must be in range r0-r7"); + return Error( + Operands[getRegListInd(Operands, MnemonicOpsEndInd)]->getStartLoc(), + "registers must be in range r0-r7"); // If we should have writeback, then there should be a '!' token. if (!ListContainsBase && !HasWritebackToken && !isThumbTwo()) - return Error(Operands[2]->getStartLoc(), - "writeback operator '!' expected"); + return Error( + Operands[getRegListInd(Operands, MnemonicOpsEndInd)]->getStartLoc(), + "writeback operator '!' expected"); // If we should not have writeback, there must not be a '!'. This is // true even for the 32-bit wide encodings. if (ListContainsBase && HasWritebackToken) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 1]->getStartLoc(), "writeback operator '!' not allowed when base register " "in register list"); - if (validatetLDMRegList(Inst, Operands, 3)) + if (validatetLDMRegList(Inst, Operands, MnemonicOpsEndInd, 3)) return true; break; } @@ -7981,12 +8096,12 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, break; case ARM::t2LDMIA: case ARM::t2LDMDB: - if (validatetLDMRegList(Inst, Operands, 3)) + if (validatetLDMRegList(Inst, Operands, MnemonicOpsEndInd, 3)) return true; break; case ARM::t2STMIA: case ARM::t2STMDB: - if (validatetSTMRegList(Inst, Operands, 3)) + if (validatetSTMRegList(Inst, Operands, MnemonicOpsEndInd, 3)) return true; break; case ARM::t2LDMIA_UPD: @@ -7998,10 +8113,10 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, "writeback register not allowed in register list"); if (Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) { - if (validatetLDMRegList(Inst, Operands, 3)) + if (validatetLDMRegList(Inst, Operands, MnemonicOpsEndInd, 3)) return true; } else { - if (validatetSTMRegList(Inst, Operands, 3)) + if (validatetSTMRegList(Inst, Operands, MnemonicOpsEndInd, 3)) return true; } break; @@ -8011,7 +8126,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, case ARM::sysLDMDB_UPD: case ARM::sysLDMIB_UPD: if (!listContainsReg(Inst, 3, ARM::PC)) - return Error(Operands[4]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 1]->getStartLoc(), "writeback register only allowed on system LDM " "if PC in register-list"); break; @@ -8019,26 +8134,8 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, case ARM::sysSTMDA_UPD: case ARM::sysSTMDB_UPD: case ARM::sysSTMIB_UPD: - return Error(Operands[2]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "system STM cannot have writeback register"); - case ARM::tMUL: - // The second source operand must be the same register as the destination - // operand. - // - // In this case, we must directly check the parsed operands because the - // cvtThumbMultiply() function is written in such a way that it guarantees - // this first statement is always true for the new Inst. Essentially, the - // destination is unconditionally copied into the second source operand - // without checking to see if it matches what we actually parsed. - if (Operands.size() == 6 && (((ARMOperand &)*Operands[3]).getReg() != - ((ARMOperand &)*Operands[5]).getReg()) && - (((ARMOperand &)*Operands[3]).getReg() != - ((ARMOperand &)*Operands[4]).getReg())) { - return Error(Operands[3]->getStartLoc(), - "destination register must match source register"); - } - break; - // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2, // so only issue a diagnostic for thumb1. The instructions will be // switched to the t2 encodings in processInstruction() if necessary. @@ -8046,9 +8143,9 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, bool ListContainsBase; if (checkLowRegisterList(Inst, 2, 0, ARM::PC, ListContainsBase) && !isThumbTwo()) - return Error(Operands[2]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "registers must be in range r0-r7 or pc"); - if (validatetLDMRegList(Inst, Operands, 2, !isMClass())) + if (validatetLDMRegList(Inst, Operands, MnemonicOpsEndInd, 2, !isMClass())) return true; break; } @@ -8056,9 +8153,9 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, bool ListContainsBase; if (checkLowRegisterList(Inst, 2, 0, ARM::LR, ListContainsBase) && !isThumbTwo()) - return Error(Operands[2]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "registers must be in range r0-r7 or lr"); - if (validatetSTMRegList(Inst, Operands, 2)) + if (validatetSTMRegList(Inst, Operands, MnemonicOpsEndInd, 2)) return true; break; } @@ -8067,17 +8164,17 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, InvalidLowList = checkLowRegisterList(Inst, 4, Inst.getOperand(0).getReg(), 0, ListContainsBase); if (InvalidLowList && !isThumbTwo()) - return Error(Operands[4]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "registers must be in range r0-r7"); // This would be converted to a 32-bit stm, but that's not valid if the // writeback register is in the list. if (InvalidLowList && ListContainsBase) - return Error(Operands[4]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "writeback operator '!' not allowed when base register " "in register list"); - if (validatetSTMRegList(Inst, Operands, 4)) + if (validatetSTMRegList(Inst, Operands, MnemonicOpsEndInd, 4)) return true; break; } @@ -8086,7 +8183,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, // same, we need thumb2 (for the wide encoding), or we have an error. if (!isThumbTwo() && Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) { - return Error(Operands[4]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "source register must be the same as destination"); } break; @@ -8097,17 +8194,20 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, case ARM::t2SUBrs: if (Inst.getOperand(0).getReg() == ARM::SP && Inst.getOperand(1).getReg() != ARM::SP) - return Error(Operands[4]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 1]->getStartLoc(), "source register must be sp if destination is sp"); break; // Final range checking for Thumb unconditional branch instructions. case ARM::tB: - if (!(static_cast<ARMOperand &>(*Operands[2])).isSignedOffset<11, 1>()) - return Error(Operands[2]->getStartLoc(), "branch target out of range"); + if (!(static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd])) + .isSignedOffset<11, 1>()) + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), + "branch target out of range"); break; case ARM::t2B: { - int op = (Operands[2]->isImm()) ? 2 : 3; + int op = (Operands[MnemonicOpsEndInd]->isImm()) ? MnemonicOpsEndInd + : MnemonicOpsEndInd + 1; ARMOperand &Operand = static_cast<ARMOperand &>(*Operands[op]); // Delay the checks of symbolic expressions until they are resolved. if (!isa<MCBinaryExpr>(Operand.getImm()) && @@ -8117,19 +8217,24 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, } // Final range checking for Thumb conditional branch instructions. case ARM::tBcc: - if (!static_cast<ARMOperand &>(*Operands[2]).isSignedOffset<8, 1>()) - return Error(Operands[2]->getStartLoc(), "branch target out of range"); + if (!static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd]) + .isSignedOffset<8, 1>()) + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), + "branch target out of range"); break; case ARM::t2Bcc: { - int Op = (Operands[2]->isImm()) ? 2 : 3; + int Op = (Operands[MnemonicOpsEndInd]->isImm()) ? MnemonicOpsEndInd + : MnemonicOpsEndInd + 1; if (!static_cast<ARMOperand &>(*Operands[Op]).isSignedOffset<20, 1>()) return Error(Operands[Op]->getStartLoc(), "branch target out of range"); break; } case ARM::tCBZ: case ARM::tCBNZ: { - if (!static_cast<ARMOperand &>(*Operands[2]).isUnsignedOffset<6, 1>()) - return Error(Operands[2]->getStartLoc(), "branch target out of range"); + if (!static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 1]) + .isUnsignedOffset<6, 1>()) + return Error(Operands[MnemonicOpsEndInd + 1]->getStartLoc(), + "branch target out of range"); break; } case ARM::MOVi16: @@ -8143,7 +8248,8 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, // want the behavior of silently truncating, which can be unexpected and // lead to bugs that are difficult to find since this is an easy mistake // to make. - int i = (Operands[3]->isImm()) ? 3 : 4; + int i = (Operands[MnemonicOpsEndInd]->isImm()) ? MnemonicOpsEndInd + : MnemonicOpsEndInd + 1; ARMOperand &Op = static_cast<ARMOperand &>(*Operands[i]); const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm()); if (CE) break; @@ -8158,7 +8264,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, break; } case ARM::tADDi8: { - MCParsedAsmOperand &Op = *Operands[4]; + MCParsedAsmOperand &Op = *Operands[MnemonicOpsEndInd + 1]; if (isARMMCExpr(Op) && !isThumbI8Relocation(Op)) return Error(Op.getStartLoc(), "Immediate expression for Thumb adds requires :lower0_7:," @@ -8166,7 +8272,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, break; } case ARM::tMOVi8: { - MCParsedAsmOperand &Op = *Operands[2]; + MCParsedAsmOperand &Op = *Operands[MnemonicOpsEndInd]; if (isARMMCExpr(Op) && !isThumbI8Relocation(Op)) return Error(Op.getStartLoc(), "Immediate expression for Thumb movs requires :lower0_7:," @@ -8193,30 +8299,36 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, case ARM::t2BFr: case ARM::t2BFLi: case ARM::t2BFLr: { - if (!static_cast<ARMOperand &>(*Operands[2]).isUnsignedOffset<4, 1>() || - (Inst.getOperand(0).isImm() && Inst.getOperand(0).getImm() == 0)) - return Error(Operands[2]->getStartLoc(), + if (!static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd]) + .isUnsignedOffset<4, 1>() || + (Inst.getOperand(0).isImm() && Inst.getOperand(0).getImm() == 0)) { + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "branch location out of range or not a multiple of 2"); + } if (Opcode == ARM::t2BFi) { - if (!static_cast<ARMOperand &>(*Operands[3]).isSignedOffset<16, 1>()) - return Error(Operands[3]->getStartLoc(), + if (!static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 1]) + .isSignedOffset<16, 1>()) + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "branch target out of range or not a multiple of 2"); } else if (Opcode == ARM::t2BFLi) { - if (!static_cast<ARMOperand &>(*Operands[3]).isSignedOffset<18, 1>()) - return Error(Operands[3]->getStartLoc(), + if (!static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 1]) + .isSignedOffset<18, 1>()) + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "branch target out of range or not a multiple of 2"); } break; } case ARM::t2BFic: { - if (!static_cast<ARMOperand &>(*Operands[1]).isUnsignedOffset<4, 1>() || + if (!static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd]) + .isUnsignedOffset<4, 1>() || (Inst.getOperand(0).isImm() && Inst.getOperand(0).getImm() == 0)) return Error(Operands[1]->getStartLoc(), "branch location out of range or not a multiple of 2"); - if (!static_cast<ARMOperand &>(*Operands[2]).isSignedOffset<16, 1>()) - return Error(Operands[2]->getStartLoc(), + if (!static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 1]) + .isSignedOffset<16, 1>()) + return Error(Operands[MnemonicOpsEndInd + 1]->getStartLoc(), "branch target out of range or not a multiple of 2"); assert(Inst.getOperand(0).isImm() == Inst.getOperand(2).isImm() && @@ -8237,7 +8349,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, if (Inst.getOperand(i).isReg() && !ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains( Inst.getOperand(i).getReg())) { - return Error(Operands[2]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "invalid register in register list. Valid registers are " "r0-r12, lr/r14 and APSR."); } @@ -8269,7 +8381,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, const unsigned Sm = MRI->getEncodingValue(Inst.getOperand(2).getReg()); const unsigned Sm1 = MRI->getEncodingValue(Inst.getOperand(3).getReg()); if (Sm1 != Sm + 1) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "source operands must be sequential"); break; } @@ -8278,16 +8390,17 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, const unsigned Sm = MRI->getEncodingValue(Inst.getOperand(0).getReg()); const unsigned Sm1 = MRI->getEncodingValue(Inst.getOperand(1).getReg()); if (Sm1 != Sm + 1) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "destination operands must be sequential"); break; } case ARM::VLDMDIA: case ARM::VSTMDIA: { - ARMOperand &Op = static_cast<ARMOperand&>(*Operands[3]); + ARMOperand &Op = + static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 1]); auto &RegList = Op.getRegList(); if (RegList.size() < 1 || RegList.size() > 16) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 1]->getStartLoc(), "list of registers must be at least 1 and at most 16"); break; } @@ -8298,13 +8411,15 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, case ARM::MVE_VMULLTs32: case ARM::MVE_VMULLBu32: case ARM::MVE_VMULLTu32: { - if (Operands[3]->getReg() == Operands[4]->getReg()) { - return Error (Operands[3]->getStartLoc(), - "Qd register and Qn register can't be identical"); + if (Operands[MnemonicOpsEndInd]->getReg() == + Operands[MnemonicOpsEndInd + 1]->getReg()) { + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), + "Qd register and Qn register can't be identical"); } - if (Operands[3]->getReg() == Operands[5]->getReg()) { - return Error (Operands[3]->getStartLoc(), - "Qd register and Qm register can't be identical"); + if (Operands[MnemonicOpsEndInd]->getReg() == + Operands[MnemonicOpsEndInd + 2]->getReg()) { + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), + "Qd register and Qm register can't be identical"); } break; } @@ -8313,41 +8428,56 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, case ARM::MVE_VREV64_32: case ARM::MVE_VQDMULL_qr_s32bh: case ARM::MVE_VQDMULL_qr_s32th: { - if (Operands[3]->getReg() == Operands[4]->getReg()) { - return Error (Operands[3]->getStartLoc(), - "Qd register and Qn register can't be identical"); + if (Operands[MnemonicOpsEndInd]->getReg() == + Operands[MnemonicOpsEndInd + 1]->getReg()) { + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), + "Qd register and Qn register can't be identical"); } break; } case ARM::MVE_VCADDi32: case ARM::MVE_VCADDf32: case ARM::MVE_VHCADDs32: { - if (Operands[3]->getReg() == Operands[5]->getReg()) { - return Error (Operands[3]->getStartLoc(), - "Qd register and Qm register can't be identical"); + if (Operands[MnemonicOpsEndInd]->getReg() == + Operands[MnemonicOpsEndInd + 2]->getReg()) { + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), + "Qd register and Qm register can't be identical"); } break; } case ARM::MVE_VMOV_rr_q: { - if (Operands[4]->getReg() != Operands[6]->getReg()) - return Error (Operands[4]->getStartLoc(), "Q-registers must be the same"); - if (static_cast<ARMOperand &>(*Operands[5]).getVectorIndex() != - static_cast<ARMOperand &>(*Operands[7]).getVectorIndex() + 2) - return Error (Operands[5]->getStartLoc(), "Q-register indexes must be 2 and 0 or 3 and 1"); + if (Operands[MnemonicOpsEndInd + 2]->getReg() != + Operands[MnemonicOpsEndInd + 4]->getReg()) + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), + "Q-registers must be the same"); + if (static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 3]) + .getVectorIndex() != + static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 5]) + .getVectorIndex() + + 2) + return Error(Operands[MnemonicOpsEndInd + 3]->getStartLoc(), + "Q-register indexes must be 2 and 0 or 3 and 1"); break; } case ARM::MVE_VMOV_q_rr: { - if (Operands[2]->getReg() != Operands[4]->getReg()) - return Error (Operands[2]->getStartLoc(), "Q-registers must be the same"); - if (static_cast<ARMOperand &>(*Operands[3]).getVectorIndex() != - static_cast<ARMOperand &>(*Operands[5]).getVectorIndex() + 2) - return Error (Operands[3]->getStartLoc(), "Q-register indexes must be 2 and 0 or 3 and 1"); + if (Operands[MnemonicOpsEndInd]->getReg() != + Operands[MnemonicOpsEndInd + 2]->getReg()) + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), + "Q-registers must be the same"); + if (static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 1]) + .getVectorIndex() != + static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 3]) + .getVectorIndex() + + 2) + return Error(Operands[MnemonicOpsEndInd + 1]->getStartLoc(), + "Q-register indexes must be 2 and 0 or 3 and 1"); break; } case ARM::MVE_SQRSHR: case ARM::MVE_UQRSHL: { - if (Operands[2]->getReg() == Operands[3]->getReg()) { - return Error(Operands[2]->getStartLoc(), + if (Operands[MnemonicOpsEndInd]->getReg() == + Operands[MnemonicOpsEndInd + 1]->getReg()) { + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "Rda register and Rm register can't be identical"); } break; @@ -8751,6 +8881,7 @@ static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) { bool ARMAsmParser::processInstruction(MCInst &Inst, const OperandVector &Operands, + unsigned MnemonicOpsEndInd, MCStreamer &Out) { // Check if we have the wide qualifier, because if it's present we // must avoid selecting a 16-bit thumb instruction. @@ -8768,9 +8899,10 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, case ARM::VLSTM: { // In some cases both T1 and T2 are valid, causing tablegen pick T1 instead // of T2 - if (Operands.size() == 4) { // a register list has been provided + if (Operands.size() == + MnemonicOpsEndInd + 2) { // a register list has been provided ARMOperand &Op = static_cast<ARMOperand &>( - *Operands[3]); // the register list, a dpr_reglist + *Operands[MnemonicOpsEndInd + 1]); // the register list, a dpr_reglist assert(Op.isDPRRegList()); auto &RegList = Op.getRegList(); // When the register list is {d0-d31} the instruction has to be the T2 @@ -9097,9 +9229,7 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, else if (Inst.getOpcode() == ARM::t2LDRConstPool) TmpInst.setOpcode(ARM::t2LDRpci); const ARMOperand &PoolOperand = - (HasWideQualifier ? - static_cast<ARMOperand &>(*Operands[4]) : - static_cast<ARMOperand &>(*Operands[3])); + static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 1]); const MCExpr *SubExprVal = PoolOperand.getConstantPoolImm(); // If SubExprVal is a constant we may be able to use a MOV if (isa<MCConstantExpr>(SubExprVal) && @@ -10526,7 +10656,8 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, // to encoding T2 if <Rd> is specified and encoding T2 is preferred // to encoding T1 if <Rd> is omitted." if (Inst.getOperand(3).isImm() && - (unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) { + (unsigned)Inst.getOperand(3).getImm() < 8 && + Operands.size() == MnemonicOpsEndInd + 3) { Inst.setOpcode(ARM::tADDi3); return true; } @@ -10536,7 +10667,8 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, // explicitly specified. From the ARM ARM: "Encoding T1 is preferred // to encoding T2 if <Rd> is specified and encoding T2 is preferred // to encoding T1 if <Rd> is omitted." - if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) { + if ((unsigned)Inst.getOperand(3).getImm() < 8 && + Operands.size() == MnemonicOpsEndInd + 3) { Inst.setOpcode(ARM::tSUBi3); return true; } @@ -10656,8 +10788,10 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, // an error in validateInstruction(). unsigned Rn = Inst.getOperand(0).getReg(); bool hasWritebackToken = - (static_cast<ARMOperand &>(*Operands[3]).isToken() && - static_cast<ARMOperand &>(*Operands[3]).getToken() == "!"); + (static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 1]) + .isToken() && + static_cast<ARMOperand &>(*Operands[MnemonicOpsEndInd + 1]) + .getToken() == "!"); bool listContainsBase; if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) || (!listContainsBase && !hasWritebackToken) || @@ -10956,6 +11090,26 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, return false; } +unsigned +ARMAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst, + const OperandVector &Operands) { + unsigned Opc = Inst.getOpcode(); + switch (Opc) { + // Prevent the mov r8 r8 encoding for nop being selected when the v6/thumb 2 + // encoding is available. + case ARM::tMOVr: { + if (Operands[0]->isToken() && + static_cast<ARMOperand &>(*Operands[0]).getToken() == "nop" && + ((isThumb() && !isThumbOne()) || hasV6MOps())) { + return Match_MnemonicFail; + } + } + LLVM_FALLTHROUGH; + default: + return Match_Success; + } +} + unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) { // 16-bit thumb arithmetic instructions either require or preclude the 'S' // suffix depending on whether they're in an IT block or not. @@ -10966,22 +11120,23 @@ unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) { "optionally flag setting instruction missing optional def operand"); assert(MCID.NumOperands == Inst.getNumOperands() && "operand count mismatch!"); - // Find the optional-def operand (cc_out). - unsigned OpNo; - for (OpNo = 0; - OpNo < MCID.NumOperands && !MCID.operands()[OpNo].isOptionalDef(); - ++OpNo) - ; + bool IsCPSR = false; + // Check if the instruction has CPSR set. + for (unsigned OpNo = 0; OpNo < MCID.NumOperands; ++OpNo) { + if (MCID.operands()[OpNo].isOptionalDef() && + Inst.getOperand(OpNo).isReg() && + Inst.getOperand(OpNo).getReg() == ARM::CPSR) + IsCPSR = true; + } + // If we're parsing Thumb1, reject it completely. - if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR) + if (isThumbOne() && !IsCPSR) return Match_RequiresFlagSetting; // If we're parsing Thumb2, which form is legal depends on whether we're // in an IT block. - if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR && - !inITBlock()) + if (isThumbTwo() && !IsCPSR && !inITBlock()) return Match_RequiresITBlock; - if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR && - inITBlock()) + if (isThumbTwo() && IsCPSR && inITBlock()) return Match_RequiresNotITBlock; // LSL with zero immediate is not allowed in an IT block if (Opc == ARM::tLSLri && Inst.getOperand(3).getImm() == 0 && inITBlock()) @@ -11042,6 +11197,14 @@ unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) { if (!hasV8Ops() && (Inst.getOperand(0).getReg() == ARM::SP)) return Match_RequiresV8; break; + case ARM::tMUL: + // The second source operand must be the same register as the destination + // operand. + // FIXME: Ideally this would be handled by ARMGenAsmMatcher and + // emitAsmTiedOperandConstraints. + if (Inst.getOperand(0).getReg() != Inst.getOperand(3).getReg()) + return Match_InvalidTiedOperand; + break; default: break; } @@ -11200,6 +11363,9 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, MatchResult = MatchInstruction(Operands, Inst, NearMisses, MatchingInlineAsm, PendConditionalInstruction, Out); + // Find the number of operators that are part of the Mnumonic (LHS). + unsigned MnemonicOpsEndInd = getMnemonicOpsEndInd(Operands); + switch (MatchResult) { case Match_Success: LLVM_DEBUG(dbgs() << "Parsed as: "; @@ -11208,7 +11374,7 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, // Context sensitive operand constraints aren't handled by the matcher, // so check them here. - if (validateInstruction(Inst, Operands)) { + if (validateInstruction(Inst, Operands, MnemonicOpsEndInd)) { // Still progress the IT block, otherwise one wrong condition causes // nasty cascading errors. forwardITPosition(); @@ -11221,7 +11387,7 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, // encoding is selected. Loop on it while changes happen so the // individual transformations can chain off each other. E.g., // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8) - while (processInstruction(Inst, Operands, Out)) + while (processInstruction(Inst, Operands, MnemonicOpsEndInd, Out)) LLVM_DEBUG(dbgs() << "Changed to: "; Inst.dump_pretty(dbgs(), MII.getName(Inst.getOpcode())); dbgs() << "\n"); @@ -12562,6 +12728,8 @@ ARMAsmParser::FilterNearMisses(SmallVectorImpl<NearMissInfo> &NearMissesIn, SmallSet<FeatureBitset, 4> FeatureMissesSeen; bool ReportedTooFewOperands = false; + unsigned MnemonicOpsEndInd = getMnemonicOpsEndInd(Operands); + // Process the near-misses in reverse order, so that we see more general ones // first, and so can avoid emitting more specific ones. for (NearMissInfo &I : reverse(NearMissesIn)) { @@ -12670,6 +12838,16 @@ ARMAsmParser::FilterNearMisses(SmallVectorImpl<NearMissInfo> &NearMissesIn, case Match_RequiresFlagSetting: Message.Message = "no flag-preserving variant of this instruction available"; break; + case Match_InvalidTiedOperand: { + ARMOperand &Op = static_cast<ARMOperand &>(*Operands[0]); + if (Op.isToken() && Op.getToken() == "mul") { + Message.Message = "destination register must match a source register"; + Message.Loc = Operands[MnemonicOpsEndInd]->getStartLoc(); + } else { + llvm_unreachable("Match_InvalidTiedOperand only used for tMUL."); + } + break; + } case Match_InvalidOperand: Message.Message = "invalid operand for instruction"; break; @@ -12869,11 +13047,6 @@ unsigned ARMAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, if (hasV8Ops() && Op.isReg() && Op.getReg() == ARM::SP) return Match_Success; return Match_rGPR; - case MCK_GPRPair: - if (Op.isReg() && - MRI->getRegClass(ARM::GPRRegClassID).contains(Op.getReg())) - return Match_Success; - break; } return Match_InvalidOperand; } @@ -12921,3 +13094,15 @@ bool ARMAsmParser::isMnemonicVPTPredicable(StringRef Mnemonic, std::begin(predicable_prefixes), std::end(predicable_prefixes), [&Mnemonic](const char *prefix) { return Mnemonic.starts_with(prefix); }); } + +std::unique_ptr<ARMOperand> ARMAsmParser::defaultCondCodeOp() { + return ARMOperand::CreateCondCode(ARMCC::AL, SMLoc(), *this); +} + +std::unique_ptr<ARMOperand> ARMAsmParser::defaultCCOutOp() { + return ARMOperand::CreateCCOut(0, SMLoc(), *this); +} + +std::unique_ptr<ARMOperand> ARMAsmParser::defaultVPTPredOp() { + return ARMOperand::CreateVPTPred(ARMVCC::None, SMLoc(), *this); +} diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h b/llvm/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h index 163360c08ffba05094704a1ce8ea7c02e504d1b3..28e5840fdde5b4842f38a7fd49a65e1df2c5d20a 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h @@ -41,7 +41,7 @@ namespace ARM_AM { inline const char *getAddrOpcStr(AddrOpc Op) { return Op == sub ? "-" : ""; } - inline const char *getShiftOpcStr(ShiftOpc Op) { + inline const StringRef getShiftOpcStr(ShiftOpc Op) { switch (Op) { default: llvm_unreachable("Unknown shift opc!"); case ARM_AM::asr: return "asr"; diff --git a/llvm/lib/Target/ARM/MVEGatherScatterLowering.cpp b/llvm/lib/Target/ARM/MVEGatherScatterLowering.cpp index 404c280ab979918fbc4e0d7214d44c4e9700404e..924a4580aa5fdf5b26f5d3ee7f8500865e697617 100644 --- a/llvm/lib/Target/ARM/MVEGatherScatterLowering.cpp +++ b/llvm/lib/Target/ARM/MVEGatherScatterLowering.cpp @@ -780,8 +780,9 @@ Instruction *MVEGatherScatterLowering::tryCreateIncrementingGatScat( // Make sure the offsets are scaled correctly Instruction *ScaledOffsets = BinaryOperator::Create( Instruction::Shl, OffsetsIncoming, - Builder.CreateVectorSplat(Ty->getNumElements(), Builder.getInt32(TypeScale)), - "ScaledIndex", I); + Builder.CreateVectorSplat(Ty->getNumElements(), + Builder.getInt32(TypeScale)), + "ScaledIndex", I->getIterator()); // Add the base to the offsets OffsetsIncoming = BinaryOperator::Create( Instruction::Add, ScaledOffsets, @@ -790,7 +791,7 @@ Instruction *MVEGatherScatterLowering::tryCreateIncrementingGatScat( Builder.CreatePtrToInt( BasePtr, cast<VectorType>(ScaledOffsets->getType())->getElementType())), - "StartIndex", I); + "StartIndex", I->getIterator()); if (I->getIntrinsicID() == Intrinsic::masked_gather) return tryCreateMaskedGatherBase(I, OffsetsIncoming, Builder, Immediate); @@ -838,7 +839,8 @@ Instruction *MVEGatherScatterLowering::tryCreateIncrementingWBGatScat( Instruction *ScaledOffsets = BinaryOperator::Create( Instruction::Shl, Phi->getIncomingValue(1 - IncrementIndex), Builder.CreateVectorSplat(NumElems, Builder.getInt32(TypeScale)), - "ScaledIndex", &Phi->getIncomingBlock(1 - IncrementIndex)->back()); + "ScaledIndex", + Phi->getIncomingBlock(1 - IncrementIndex)->back().getIterator()); // Add the base to the offsets OffsetsIncoming = BinaryOperator::Create( Instruction::Add, ScaledOffsets, @@ -847,13 +849,14 @@ Instruction *MVEGatherScatterLowering::tryCreateIncrementingWBGatScat( Builder.CreatePtrToInt( BasePtr, cast<VectorType>(ScaledOffsets->getType())->getElementType())), - "StartIndex", &Phi->getIncomingBlock(1 - IncrementIndex)->back()); + "StartIndex", + Phi->getIncomingBlock(1 - IncrementIndex)->back().getIterator()); // The gather is pre-incrementing OffsetsIncoming = BinaryOperator::Create( Instruction::Sub, OffsetsIncoming, Builder.CreateVectorSplat(NumElems, Builder.getInt32(Immediate)), "PreIncrementStartIndex", - &Phi->getIncomingBlock(1 - IncrementIndex)->back()); + Phi->getIncomingBlock(1 - IncrementIndex)->back().getIterator()); Phi->setIncomingValue(1 - IncrementIndex, OffsetsIncoming); Builder.SetInsertPoint(I); @@ -886,8 +889,8 @@ void MVEGatherScatterLowering::pushOutAdd(PHINode *&Phi, Value *OffsSecondOperand, unsigned StartIndex) { LLVM_DEBUG(dbgs() << "masked gathers/scatters: optimising add instruction\n"); - Instruction *InsertionPoint = - &cast<Instruction>(Phi->getIncomingBlock(StartIndex)->back()); + BasicBlock::iterator InsertionPoint = + Phi->getIncomingBlock(StartIndex)->back().getIterator(); // Initialize the phi with a vector that contains a sum of the constants Instruction *NewIndex = BinaryOperator::Create( Instruction::Add, Phi->getIncomingValue(StartIndex), OffsSecondOperand, @@ -911,8 +914,8 @@ void MVEGatherScatterLowering::pushOutMulShl(unsigned Opcode, PHINode *&Phi, // Create a new scalar add outside of the loop and transform it to a splat // by which loop variable can be incremented - Instruction *InsertionPoint = &cast<Instruction>( - Phi->getIncomingBlock(LoopIncrement == 1 ? 0 : 1)->back()); + BasicBlock::iterator InsertionPoint = + Phi->getIncomingBlock(LoopIncrement == 1 ? 0 : 1)->back().getIterator(); // Create a new index Value *StartIndex = @@ -923,11 +926,14 @@ void MVEGatherScatterLowering::pushOutMulShl(unsigned Opcode, PHINode *&Phi, Instruction *Product = BinaryOperator::Create((Instruction::BinaryOps)Opcode, IncrementPerRound, OffsSecondOperand, "Product", InsertionPoint); + + BasicBlock::iterator NewIncrInsertPt = + Phi->getIncomingBlock(LoopIncrement)->back().getIterator(); + NewIncrInsertPt = std::prev(NewIncrInsertPt); + // Increment NewIndex by Product instead of the multiplication Instruction *NewIncrement = BinaryOperator::Create( - Instruction::Add, Phi, Product, "IncrementPushedOutMul", - cast<Instruction>(Phi->getIncomingBlock(LoopIncrement)->back()) - .getPrevNode()); + Instruction::Add, Phi, Product, "IncrementPushedOutMul", NewIncrInsertPt); Phi->addIncoming(StartIndex, Phi->getIncomingBlock(LoopIncrement == 1 ? 0 : 1)); @@ -1054,7 +1060,7 @@ bool MVEGatherScatterLowering::optimiseOffsets(Value *Offsets, BasicBlock *BB, // our phi, we need to copy it IncInstruction = BinaryOperator::Create( Instruction::BinaryOps(IncInstruction->getOpcode()), Phi, - IncrementPerRound, "LoopIncrement", IncInstruction); + IncrementPerRound, "LoopIncrement", IncInstruction->getIterator()); Phi->setIncomingValue(IncrementingBlock, IncInstruction); } NewPhi = Phi; @@ -1066,7 +1072,7 @@ bool MVEGatherScatterLowering::optimiseOffsets(Value *Offsets, BasicBlock *BB, Phi->getIncomingBlock(IncrementingBlock == 1 ? 0 : 1)); IncInstruction = BinaryOperator::Create( Instruction::BinaryOps(IncInstruction->getOpcode()), NewPhi, - IncrementPerRound, "LoopIncrement", IncInstruction); + IncrementPerRound, "LoopIncrement", IncInstruction->getIterator()); NewPhi->addIncoming(IncInstruction, Phi->getIncomingBlock(IncrementingBlock)); IncrementingBlock = 1; @@ -1229,7 +1235,7 @@ bool MVEGatherScatterLowering::optimiseAddress(Value *Address, BasicBlock *BB, BaseTy = FixedVectorType::get(BaseTy, VecTy); GetElementPtrInst *NewAddress = GetElementPtrInst::Create( Builder.getInt8Ty(), Builder.CreateBitCast(Base, BaseTy), Offsets, - "gep.merged", GEP); + "gep.merged", GEP->getIterator()); LLVM_DEBUG(dbgs() << "Folded GEP: " << *GEP << "\n new : " << *NewAddress << "\n"); GEP->replaceAllUsesWith( diff --git a/llvm/lib/Target/ARM/MVETPAndVPTOptimisationsPass.cpp b/llvm/lib/Target/ARM/MVETPAndVPTOptimisationsPass.cpp index 5c113ccfdc1579cbc57ea475361cfc51dd0989ec..e8d2cba7ee556fc1087e683bbfa00b8187a3e5f7 100644 --- a/llvm/lib/Target/ARM/MVETPAndVPTOptimisationsPass.cpp +++ b/llvm/lib/Target/ARM/MVETPAndVPTOptimisationsPass.cpp @@ -958,6 +958,7 @@ bool MVETPAndVPTOptimisations::ReplaceConstByVPNOTs(MachineBasicBlock &MBB, unsigned NotImm = ~Imm & 0xffff; if (LastVPTReg != 0 && LastVPTReg != VPR && LastVPTImm == Imm) { + MRI->clearKillFlags(LastVPTReg); Instr.getOperand(PIdx + 1).setReg(LastVPTReg); if (MRI->use_empty(VPR)) { DeadInstructions.insert(Copy); diff --git a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp index 0f4ece64bff53234d12a2de05e87fbaf7df7b307..047c6731333c9b36e1270c2067d530bb3ee8f4dc 100644 --- a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp +++ b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp @@ -612,11 +612,11 @@ bool Thumb1FrameLowering::needPopSpecialFixUp(const MachineFunction &MF) const { static void findTemporariesForLR(const BitVector &GPRsNoLRSP, const BitVector &PopFriendly, - const LivePhysRegs &UsedRegs, unsigned &PopReg, + const LiveRegUnits &UsedRegs, unsigned &PopReg, unsigned &TmpReg, MachineRegisterInfo &MRI) { PopReg = TmpReg = 0; for (auto Reg : GPRsNoLRSP.set_bits()) { - if (UsedRegs.available(MRI, Reg)) { + if (UsedRegs.available(Reg)) { // Remember the first pop-friendly register and exit. if (PopFriendly.test(Reg)) { PopReg = Reg; @@ -684,7 +684,7 @@ bool Thumb1FrameLowering::emitPopSpecialFixUp(MachineBasicBlock &MBB, // Look for a temporary register to use. // First, compute the liveness information. const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); - LivePhysRegs UsedRegs(TRI); + LiveRegUnits UsedRegs(TRI); UsedRegs.addLiveOuts(MBB); // The semantic of pristines changed recently and now, // the callee-saved registers that are touched in the function @@ -710,11 +710,6 @@ bool Thumb1FrameLowering::emitPopSpecialFixUp(MachineBasicBlock &MBB, unsigned TemporaryReg = 0; BitVector PopFriendly = TRI.getAllocatableSet(MF, TRI.getRegClass(ARM::tGPRRegClassID)); - // R7 may be used as a frame pointer, hence marked as not generally - // allocatable, however there's no reason to not use it as a temporary for - // restoring LR. - if (STI.getFramePointerReg() == ARM::R7) - PopFriendly.set(ARM::R7); assert(PopFriendly.any() && "No allocatable pop-friendly register?!"); // Rebuild the GPRs from the high registers because they are removed diff --git a/llvm/lib/Target/AVR/AVRInstrInfo.td b/llvm/lib/Target/AVR/AVRInstrInfo.td index 68e14f7dc920314f8538a99c7a791319237c9572..38ebfab64c618ded7a46ef6e7dd98797e8e941e7 100644 --- a/llvm/lib/Target/AVR/AVRInstrInfo.td +++ b/llvm/lib/Target/AVR/AVRInstrInfo.td @@ -343,13 +343,9 @@ def AVR_COND_PL : PatLeaf<(i8 7)>; // Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become // sub / add which can clobber SREG. let Defs = [SP, SREG], Uses = [SP] in { - def ADJCALLSTACKDOWN : Pseudo<(outs), - (ins i16imm - : $amt, i16imm - : $amt2), - "#ADJCALLSTACKDOWN", [(AVRcallseq_start timm - : $amt, timm - : $amt2)]>; + def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i16imm:$amt, i16imm:$amt2), + "#ADJCALLSTACKDOWN", + [(AVRcallseq_start timm:$amt, timm:$amt2)]>; // R31R30 is used to update SP. It is normally free because it is a // call-clobbered register but it is necessary to set it as a def as the @@ -357,13 +353,8 @@ let Defs = [SP, SREG], Uses = [SP] in { // seems). hasSideEffects needs to be set to true so this instruction isn't // considered dead. let Defs = [R31R30], hasSideEffects = 1 in def ADJCALLSTACKUP - : Pseudo<(outs), - (ins i16imm - : $amt1, i16imm - : $amt2), - "#ADJCALLSTACKUP", [(AVRcallseq_end timm - : $amt1, timm - : $amt2)]>; + : Pseudo<(outs), (ins i16imm:$amt1, i16imm:$amt2), + "#ADJCALLSTACKUP", [(AVRcallseq_end timm:$amt1, timm:$amt2)]>; } //===----------------------------------------------------------------------===// @@ -372,19 +363,9 @@ let Defs = [SP, SREG], Uses = [SP] in { let isCommutable = 1, Constraints = "$src = $rd", Defs = [SREG] in { // ADD Rd, Rr // Adds two 8-bit registers. - def ADDRdRr - : FRdRr<0b0000, 0b11, - (outs GPR8 - : $rd), - (ins GPR8 - : $src, GPR8 - : $rr), - "add\t$rd, $rr", - [(set i8 - : $rd, (add i8 - : $src, i8 - : $rr)), - (implicit SREG)]>; + def ADDRdRr : FRdRr<0b0000, 0b11, (outs GPR8:$rd),(ins GPR8:$src, GPR8:$rr), + "add\t$rd, $rr", + [(set i8:$rd, (add i8:$src, i8:$rr)), (implicit SREG)]>; // ADDW Rd+1:Rd, Rr+1:Rr // Pseudo instruction to add four 8-bit registers as two 16-bit values. @@ -392,34 +373,17 @@ let isCommutable = 1, Constraints = "$src = $rd", Defs = [SREG] in { // Expands to: // add Rd, Rr // adc Rd+1, Rr+1 - def ADDWRdRr - : Pseudo<(outs DREGS - : $rd), - (ins DREGS - : $src, DREGS - : $rr), - "addw\t$rd, $rr", - [(set i16 - : $rd, (add i16 - : $src, i16 - : $rr)), - (implicit SREG)]>; + def ADDWRdRr : Pseudo<(outs DREGS:$rd), (ins DREGS:$src, DREGS:$rr), + "addw\t$rd, $rr", + [(set i16:$rd, (add i16:$src, i16:$rr)), + (implicit SREG)]>; // ADC Rd, Rr // Adds two 8-bit registers with carry. - let Uses = [SREG] in def ADCRdRr - : FRdRr<0b0001, 0b11, - (outs GPR8 - : $rd), - (ins GPR8 - : $src, GPR8 - : $rr), - "adc\t$rd, $rr", - [(set i8 - : $rd, (adde i8 - : $src, i8 - : $rr)), - (implicit SREG)]>; + let Uses = [SREG] in + def ADCRdRr : FRdRr<0b0001, 0b11, (outs GPR8:$rd), (ins GPR8:$src, GPR8:$rr), + "adc\t$rd, $rr", + [(set i8:$rd, (adde i8:$src, i8:$rr)), (implicit SREG)]>; // ADCW Rd+1:Rd, Rr+1:Rr // Pseudo instruction to add four 8-bit registers as two 16-bit values with @@ -428,56 +392,30 @@ let isCommutable = 1, Constraints = "$src = $rd", Defs = [SREG] in { // Expands to: // adc Rd, Rr // adc Rd+1, Rr+1 - let Uses = [SREG] in def ADCWRdRr : Pseudo<(outs DREGS - : $rd), - (ins DREGS - : $src, DREGS - : $rr), - "adcw\t$rd, $rr", [ - (set i16 - : $rd, (adde i16 - : $src, i16 - : $rr)), - (implicit SREG) - ]>; + let Uses = [SREG] in + def ADCWRdRr : Pseudo<(outs DREGS:$rd), (ins DREGS:$src, DREGS:$rr), + "adcw\t$rd, $rr", + [(set i16:$rd, (adde i16:$src, i16:$rr)), + (implicit SREG)]>; // AIDW Rd, k // Adds an immediate 6-bit value K to Rd, placing the result in Rd. - def ADIWRdK - : FWRdK<0b0, - (outs IWREGS - : $rd), - (ins IWREGS - : $src, imm_arith6 - : $k), - "adiw\t$rd, $k", - [(set i16 - : $rd, (add i16 - : $src, uimm6 - : $k)), - (implicit SREG)]>, - Requires<[HasADDSUBIW]>; + def ADIWRdK : FWRdK<0b0, (outs IWREGS:$rd), (ins IWREGS :$src, imm_arith6:$k), + "adiw\t$rd, $k", + [(set i16:$rd, (add i16:$src, uimm6:$k)), + (implicit SREG)]>, + Requires<[HasADDSUBIW]>; } //===----------------------------------------------------------------------===// // Subtraction //===----------------------------------------------------------------------===// -let Constraints = "$src = $rd", Defs = [SREG] in { +let Constraints = "$rs = $rd", Defs = [SREG] in { // SUB Rd, Rr // Subtracts the 8-bit value of Rr from Rd and places the value in Rd. - def SUBRdRr - : FRdRr<0b0001, 0b10, - (outs GPR8 - : $rd), - (ins GPR8 - : $src, GPR8 - : $rr), - "sub\t$rd, $rr", - [(set i8 - : $rd, (sub i8 - : $src, i8 - : $rr)), - (implicit SREG)]>; + def SUBRdRr : FRdRr<0b0001, 0b10, (outs GPR8:$rd), (ins GPR8:$rs, GPR8:$rr), + "sub\t$rd, $rr", + [(set i8:$rd, (sub i8:$rs, i8:$rr)), (implicit SREG)]>; // SUBW Rd+1:Rd, Rr+1:Rr // Subtracts two 16-bit values and places the result into Rd. @@ -485,129 +423,58 @@ let Constraints = "$src = $rd", Defs = [SREG] in { // Expands to: // sub Rd, Rr // sbc Rd+1, Rr+1 - def SUBWRdRr - : Pseudo<(outs DREGS - : $rd), - (ins DREGS - : $src, DREGS - : $rr), - "subw\t$rd, $rr", - [(set i16 - : $rd, (sub i16 - : $src, i16 - : $rr)), - (implicit SREG)]>; + def SUBWRdRr : Pseudo<(outs DREGS:$rd), (ins DREGS:$rs, DREGS:$rr), + "subw\t$rd, $rr", + [(set i16:$rd, (sub i16:$rs, i16:$rr)), + (implicit SREG)]>; - def SUBIRdK - : FRdK<0b0101, - (outs LD8 - : $rd), - (ins LD8 - : $src, imm_ldi8 - : $k), - "subi\t$rd, $k", - [(set i8 - : $rd, (sub i8 - : $src, imm - : $k)), - (implicit SREG)]>; + def SUBIRdK : FRdK<0b0101, (outs LD8:$rd), (ins LD8:$rs, imm_ldi8:$k), + "subi\t$rd, $k", + [(set i8:$rd, (sub i8:$rs, imm:$k)), (implicit SREG)]>; // SUBIW Rd+1:Rd, K+1:K // // Expands to: // subi Rd, K // sbci Rd+1, K+1 - def SUBIWRdK - : Pseudo<(outs DLDREGS - : $rd), - (ins DLDREGS - : $src, i16imm - : $rr), - "subiw\t$rd, $rr", - [(set i16 - : $rd, (sub i16 - : $src, imm - : $rr)), - (implicit SREG)]>; + def SUBIWRdK : Pseudo<(outs DLDREGS:$rd), (ins DLDREGS:$rs, i16imm:$rr), + "subiw\t$rd, $rr", + [(set i16:$rd, (sub i16:$rs, imm:$rr)), + (implicit SREG)]>; - def SBIWRdK - : FWRdK<0b1, - (outs IWREGS - : $rd), - (ins IWREGS - : $src, imm_arith6 - : $k), - "sbiw\t$rd, $k", - [(set i16 - : $rd, (sub i16 - : $src, uimm6 - : $k)), - (implicit SREG)]>, - Requires<[HasADDSUBIW]>; + def SBIWRdK : FWRdK<0b1, (outs IWREGS:$rd), (ins IWREGS:$rs, imm_arith6:$k), + "sbiw\t$rd, $k", + [(set i16:$rd, (sub i16:$rs, uimm6:$k)), + (implicit SREG)]>, + Requires<[HasADDSUBIW]>; // Subtract with carry operations which must read the carry flag in SREG. let Uses = [SREG] in { - def SBCRdRr - : FRdRr<0b0000, 0b10, - (outs GPR8 - : $rd), - (ins GPR8 - : $src, GPR8 - : $rr), - "sbc\t$rd, $rr", - [(set i8 - : $rd, (sube i8 - : $src, i8 - : $rr)), - (implicit SREG)]>; + def SBCRdRr : FRdRr<0b0000, 0b10, (outs GPR8:$rd), (ins GPR8:$rs, GPR8:$rr), + "sbc\t$rd, $rr", + [(set i8:$rd, (sube i8:$rs, i8:$rr)), (implicit SREG)]>; // SBCW Rd+1:Rd, Rr+1:Rr // // Expands to: // sbc Rd, Rr // sbc Rd+1, Rr+1 - def SBCWRdRr : Pseudo<(outs DREGS - : $rd), - (ins DREGS - : $src, DREGS - : $rr), - "sbcw\t$rd, $rr", [ - (set i16 - : $rd, (sube i16 - : $src, i16 - : $rr)), - (implicit SREG) - ]>; + def SBCWRdRr : Pseudo<(outs DREGS:$rd), (ins DREGS:$rs, DREGS:$rr), + "sbcw\t$rd, $rr", + [(set i16:$rd, (sube i16:$rs, i16:$rr)), + (implicit SREG)]>; - def SBCIRdK - : FRdK<0b0100, - (outs LD8 - : $rd), - (ins LD8 - : $src, imm_ldi8 - : $k), - "sbci\t$rd, $k", - [(set i8 - : $rd, (sube i8 - : $src, imm - : $k)), - (implicit SREG)]>; + def SBCIRdK : FRdK<0b0100, (outs LD8:$rd), (ins LD8:$rs, imm_ldi8:$k), + "sbci\t$rd, $k", + [(set i8:$rd, (sube i8:$rs, imm:$k)), (implicit SREG)]>; // SBCIW Rd+1:Rd, K+1:K // sbci Rd, K // sbci Rd+1, K+1 - def SBCIWRdK : Pseudo<(outs DLDREGS - : $rd), - (ins DLDREGS - : $src, i16imm - : $rr), - "sbciw\t$rd, $rr", [ - (set i16 - : $rd, (sube i16 - : $src, imm - : $rr)), - (implicit SREG) - ]>; + def SBCIWRdK : Pseudo<(outs DLDREGS:$rd), (ins DLDREGS:$rs, i16imm:$rr), + "sbciw\t$rd, $rr", + [(set i16:$rd, (sube i16:$rs, imm:$rr)), + (implicit SREG)]>; } } @@ -615,27 +482,13 @@ let Constraints = "$src = $rd", Defs = [SREG] in { // Increment and Decrement //===----------------------------------------------------------------------===// let Constraints = "$src = $rd", Defs = [SREG] in { - def INCRd - : FRd<0b1001, 0b0100011, - (outs GPR8 - : $rd), - (ins GPR8 - : $src), - "inc\t$rd", [(set i8 - : $rd, (add i8 - : $src, 1)), - (implicit SREG)]>; + def INCRd : FRd<0b1001, 0b0100011, (outs GPR8:$rd), (ins GPR8:$src), + "inc\t$rd", + [(set i8:$rd, (add i8:$src, 1)), (implicit SREG)]>; - def DECRd - : FRd<0b1001, 0b0101010, - (outs GPR8 - : $rd), - (ins GPR8 - : $src), - "dec\t$rd", [(set i8 - : $rd, (add i8 - : $src, -1)), - (implicit SREG)]>; + def DECRd : FRd<0b1001, 0b0101010, (outs GPR8:$rd), (ins GPR8:$src), + "dec\t$rd", + [(set i8:$rd, (add i8:$src, -1)), (implicit SREG)]>; } //===----------------------------------------------------------------------===// @@ -646,58 +499,35 @@ let isCommutable = 1, Defs = [R1, R0, SREG] in { // MUL Rd, Rr // Multiplies Rd by Rr and places the result into R1:R0. let usesCustomInserter = 1 in { - def MULRdRr : FRdRr<0b1001, 0b11, (outs), - (ins GPR8 - : $rd, GPR8 - : $rr), - "mul\t$rd, $rr", - [/*(set R1, R0, (smullohi i8:$rd, i8:$rr))*/]>, + def MULRdRr : FRdRr<0b1001, 0b11, (outs), (ins GPR8:$rd, GPR8:$rr), + "mul\t$rd, $rr", []>, Requires<[SupportsMultiplication]>; - def MULSRdRr : FMUL2RdRr<0, (outs), - (ins LD8 - : $rd, LD8 - : $rr), + def MULSRdRr : FMUL2RdRr<0, (outs), (ins LD8:$rd, LD8:$rr), "muls\t$rd, $rr", []>, Requires<[SupportsMultiplication]>; } - def MULSURdRr : FMUL2RdRr<1, (outs), - (ins LD8lo - : $rd, LD8lo - : $rr), + def MULSURdRr : FMUL2RdRr<1, (outs), (ins LD8lo:$rd, LD8lo:$rr), "mulsu\t$rd, $rr", []>, Requires<[SupportsMultiplication]>; - def FMUL : FFMULRdRr<0b01, (outs), - (ins LD8lo - : $rd, LD8lo - : $rr), + def FMUL : FFMULRdRr<0b01, (outs), (ins LD8lo:$rd, LD8lo:$rr), "fmul\t$rd, $rr", []>, Requires<[SupportsMultiplication]>; - def FMULS : FFMULRdRr<0b10, (outs), - (ins LD8lo - : $rd, LD8lo - : $rr), + def FMULS : FFMULRdRr<0b10, (outs), (ins LD8lo:$rd, LD8lo:$rr), "fmuls\t$rd, $rr", []>, Requires<[SupportsMultiplication]>; - def FMULSU : FFMULRdRr<0b11, (outs), - (ins LD8lo - : $rd, LD8lo - : $rr), + def FMULSU : FFMULRdRr<0b11, (outs), (ins LD8lo:$rd, LD8lo:$rr), "fmulsu\t$rd, $rr", []>, Requires<[SupportsMultiplication]>; } let Defs = - [R15, R14, R13, R12, R11, R10, R9, R8, R7, R6, R5, R4, R3, R2, R1, - R0] in def DESK : FDES<(outs), - (ins i8imm - : $k), - "des\t$k", []>, - Requires<[HasDES]>; + [R15, R14, R13, R12, R11, R10, R9, R8, R7, R6, R5, R4, R3, R2, R1, R0] in +def DESK : FDES<(outs), (ins i8imm:$k), "des\t$k", []>, Requires<[HasDES]>; //===----------------------------------------------------------------------===// // Logic @@ -1387,7 +1217,7 @@ let mayLoad = 1, hasSideEffects = 0, // Load indirect with displacement operations. let canFoldAsLoad = 1, isReMaterializable = 1 in { - let Constraints = "@earlyclobber $reg" in def LDDRdPtrQ + def LDDRdPtrQ : FSTDLDD<0, (outs GPR8 : $reg), diff --git a/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp b/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp index db4aa03437c648bbd5b8715719348c8f3a4f50bb..383dfcc31117c1be2d0631c19715dfa7bf4a279c 100644 --- a/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp +++ b/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp @@ -195,7 +195,7 @@ public: return Tok; } - unsigned getReg() const override { + MCRegister getReg() const override { assert((Kind == k_Register || Kind == k_Memri) && "Invalid access!"); return RegImm.Reg; diff --git a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp index 3145bc3d19f5dc4f12bf14550ee1250f8bf44e18..9672ed009e9be12fa33335aeeba50d4717fd1823 100644 --- a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp +++ b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp @@ -148,7 +148,7 @@ public: /// getEndLoc - Gets location of the last token of this operand SMLoc getEndLoc() const override { return EndLoc; } - unsigned getReg() const override { + MCRegister getReg() const override { assert(Kind == Register && "Invalid type access!"); return Reg.RegNum; } @@ -232,6 +232,7 @@ public: .Case("callx", true) .Case("goto", true) .Case("gotol", true) + .Case("may_goto", true) .Case("*", true) .Case("exit", true) .Case("lock", true) diff --git a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp index f2d1206d02316ab6345de2e09d902f5e4653d1f2..4be6220b358ba3b879f0ce2136aa593762500c29 100644 --- a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp +++ b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp @@ -426,8 +426,9 @@ static void replaceWithGEP(CallInst *Call, uint32_t DimensionIndex, IdxList.push_back(Zero); IdxList.push_back(Call->getArgOperand(GEPIndex)); - auto *GEP = GetElementPtrInst::CreateInBounds( - getBaseElementType(Call), Call->getArgOperand(0), IdxList, "", Call); + auto *GEP = GetElementPtrInst::CreateInBounds(getBaseElementType(Call), + Call->getArgOperand(0), IdxList, + "", Call->getIterator()); Call->replaceAllUsesWith(GEP); Call->eraseFromParent(); } @@ -1091,9 +1092,11 @@ bool BPFAbstractMemberAccess::transformGEPChain(CallInst *Call, // Load the global variable which represents the returned field info. LoadInst *LDInst; if (IsInt32Ret) - LDInst = new LoadInst(Type::getInt32Ty(BB->getContext()), GV, "", Call); + LDInst = new LoadInst(Type::getInt32Ty(BB->getContext()), GV, "", + Call->getIterator()); else - LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "", Call); + LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "", + Call->getIterator()); Instruction *PassThroughInst = BPFCoreSharedInfo::insertPassThrough(M, BB, LDInst, Call); @@ -1113,7 +1116,8 @@ bool BPFAbstractMemberAccess::transformGEPChain(CallInst *Call, // The original Call inst is removed. // Load the global variable. - auto *LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "", Call); + auto *LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "", + Call->getIterator()); // Generate a BitCast auto *BCInst = diff --git a/llvm/lib/Target/BPF/BPFCheckAndAdjustIR.cpp b/llvm/lib/Target/BPF/BPFCheckAndAdjustIR.cpp index edd59aaa6d01d243ba5335ced7c54b194cf396c0..2b78ed7134c92f2cf6b9f6c389c26c2bc97d2b96 100644 --- a/llvm/lib/Target/BPF/BPFCheckAndAdjustIR.cpp +++ b/llvm/lib/Target/BPF/BPFCheckAndAdjustIR.cpp @@ -15,7 +15,7 @@ // - remove llvm.bpf.getelementptr.and.load builtins. // - remove llvm.bpf.getelementptr.and.store builtins. // - for loads and stores with base addresses from non-zero address space -// cast base address to zero address space (support for BPF arenas). +// cast base address to zero address space (support for BPF address spaces). // //===----------------------------------------------------------------------===// @@ -482,7 +482,7 @@ static void aspaceWrapOperand(DenseMap<Value *, Value *> &Cache, Instruction *I, } } -// Support for BPF arenas: +// Support for BPF address spaces: // - for each function in the module M, update pointer operand of // each memory access instruction (load/store/cmpxchg/atomicrmw) // by casting it from non-zero address space to zero address space, e.g: @@ -490,7 +490,7 @@ static void aspaceWrapOperand(DenseMap<Value *, Value *> &Cache, Instruction *I, // (load (ptr addrspace (N) %p) ...) // -> (load (addrspacecast ptr addrspace (N) %p to ptr)) // -// - assign section with name .arena.N for globals defined in +// - assign section with name .addr_space.N for globals defined in // non-zero address space N bool BPFCheckAndAdjustIR::insertASpaceCasts(Module &M) { bool Changed = false; @@ -517,13 +517,13 @@ bool BPFCheckAndAdjustIR::insertASpaceCasts(Module &M) { Changed |= !CastsCache.empty(); } // Merge all globals within same address space into single - // .arena.<addr space no> section + // .addr_space.<addr space no> section for (GlobalVariable &G : M.globals()) { if (G.getAddressSpace() == 0 || G.hasSection()) continue; SmallString<16> SecName; raw_svector_ostream OS(SecName); - OS << ".arena." << G.getAddressSpace(); + OS << ".addr_space." << G.getAddressSpace(); G.setSection(SecName); // Prevent having separate section for constants G.setConstant(false); diff --git a/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp b/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp index d8139958e9fcf2a3a621877fc18e474b827ebd46..7b8bcb2c5866da817e5f0813328cdab8fc240471 100644 --- a/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp +++ b/llvm/lib/Target/BPF/BPFISelDAGToDAG.cpp @@ -242,7 +242,9 @@ void BPFDAGToDAGISel::PreprocessLoad(SDNode *Node, bool to_replace = false; SDLoc DL(Node); const LoadSDNode *LD = cast<LoadSDNode>(Node); - uint64_t size = LD->getMemOperand()->getSize(); + if (!LD->getMemOperand()->getSize().hasValue()) + return; + uint64_t size = LD->getMemOperand()->getSize().getValue(); if (!size || size > 8 || (size & (size - 1)) || !LD->isSimple()) return; diff --git a/llvm/lib/Target/BPF/BPFISelLowering.cpp b/llvm/lib/Target/BPF/BPFISelLowering.cpp index b8ca8ec98c06e5de61056a81533e65125b490e16..071fe004806e3e5d012189306352b878a28407af 100644 --- a/llvm/lib/Target/BPF/BPFISelLowering.cpp +++ b/llvm/lib/Target/BPF/BPFISelLowering.cpp @@ -113,6 +113,10 @@ BPFTargetLowering::BPFTargetLowering(const TargetMachine &TM, setOperationAction(ISD::SRL_PARTS, VT, Expand); setOperationAction(ISD::SRA_PARTS, VT, Expand); setOperationAction(ISD::CTPOP, VT, Expand); + setOperationAction(ISD::CTTZ, VT, Expand); + setOperationAction(ISD::CTLZ, VT, Expand); + setOperationAction(ISD::CTTZ_ZERO_UNDEF, VT, Expand); + setOperationAction(ISD::CTLZ_ZERO_UNDEF, VT, Expand); setOperationAction(ISD::SETCC, VT, Expand); setOperationAction(ISD::SELECT, VT, Expand); @@ -125,11 +129,6 @@ BPFTargetLowering::BPFTargetLowering(const TargetMachine &TM, STI.getHasJmp32() ? Custom : Promote); } - setOperationAction(ISD::CTTZ, MVT::i64, Custom); - setOperationAction(ISD::CTLZ, MVT::i64, Custom); - setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Custom); - setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Custom); - setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); if (!STI.hasMovsx()) { setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand); diff --git a/llvm/lib/Target/BPF/BPFInstrFormats.td b/llvm/lib/Target/BPF/BPFInstrFormats.td index 6ed83d877ac0f23d168ee1b9cbd23c51b363477d..feffdbc69465eac17a4e7d4da3de4dfa8c06f568 100644 --- a/llvm/lib/Target/BPF/BPFInstrFormats.td +++ b/llvm/lib/Target/BPF/BPFInstrFormats.td @@ -73,6 +73,7 @@ def BPF_JLT : BPFJumpOp<0xa>; def BPF_JLE : BPFJumpOp<0xb>; def BPF_JSLT : BPFJumpOp<0xc>; def BPF_JSLE : BPFJumpOp<0xd>; +def BPF_JCOND : BPFJumpOp<0xe>; class BPFWidthModifer<bits<2> val> { bits<2> Value = val; diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td b/llvm/lib/Target/BPF/BPFInstrInfo.td index 7198e9499bc32a0e8ee3a8eb8fff08b31c3687ea..66c57952a7f10e9307b2a4c47ebf0e9899cf2270 100644 --- a/llvm/lib/Target/BPF/BPFInstrInfo.td +++ b/llvm/lib/Target/BPF/BPFInstrInfo.td @@ -215,6 +215,18 @@ class JMP_RI<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond> let BPFClass = BPF_JMP; } +class JMP_JCOND<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern> + : TYPE_ALU_JMP<Opc.Value, BPF_K.Value, + (outs), + (ins brtarget:$BrDst), + !strconcat(OpcodeStr, " $BrDst"), + Pattern> { + bits<16> BrDst; + + let Inst{47-32} = BrDst; + let BPFClass = BPF_JMP; +} + class JMP_RR_32<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond> : TYPE_ALU_JMP<Opc.Value, BPF_X.Value, (outs), @@ -267,6 +279,7 @@ defm JULE : J<BPF_JLE, "<=", BPF_CC_LEU, BPF_CC_LEU_32>; defm JSLT : J<BPF_JSLT, "s<", BPF_CC_LT, BPF_CC_LT_32>; defm JSLE : J<BPF_JSLE, "s<=", BPF_CC_LE, BPF_CC_LE_32>; defm JSET : J<BPF_JSET, "&", NoCond, NoCond>; +def JCOND : JMP_JCOND<BPF_JCOND, "may_goto", []>; } // ALU instructions diff --git a/llvm/lib/Target/BPF/BPFPassRegistry.def b/llvm/lib/Target/BPF/BPFPassRegistry.def new file mode 100644 index 0000000000000000000000000000000000000000..73a8ef2f95bf3cac5e40b3b678895f3a0adf571e --- /dev/null +++ b/llvm/lib/Target/BPF/BPFPassRegistry.def @@ -0,0 +1,32 @@ +//===- BPFPassRegistry.def - Registry of BPF passes -------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is used as the registry of passes that are part of the +// BPF backend. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +#ifndef FUNCTION_PASS +#define FUNCTION_PASS(NAME, CREATE_PASS) +#endif +FUNCTION_PASS("bpf-aspace-simplify", BPFASpaceCastSimplifyPass()) +FUNCTION_PASS("bpf-ir-peephole", BPFIRPeepholePass()) +#undef FUNCTION_PASS + +#ifndef FUNCTION_PASS_WITH_PARAMS +#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) +#endif +FUNCTION_PASS_WITH_PARAMS( + "bpf-preserve-static-offset", "BPFPreserveStaticOffsetPass", + [=](bool AllowPartial) { + return BPFPreserveStaticOffsetPass(AllowPartial); + }, + parseBPFPreserveStaticOffsetOptions, "allow-partial") +#undef FUNCTION_PASS_WITH_PARAMS diff --git a/llvm/lib/Target/BPF/BPFPreserveDIType.cpp b/llvm/lib/Target/BPF/BPFPreserveDIType.cpp index dae1aeea3521892721e77b997779f2231016fe8a..afc154988050c89ecf6c8d34b4670aca3041999c 100644 --- a/llvm/lib/Target/BPF/BPFPreserveDIType.cpp +++ b/llvm/lib/Target/BPF/BPFPreserveDIType.cpp @@ -116,8 +116,8 @@ static bool BPFPreserveDITypeImpl(Function &F) { GV->setMetadata(LLVMContext::MD_preserve_access_index, MD); // Load the global variable which represents the type info. - auto *LDInst = - new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "", Call); + auto *LDInst = new LoadInst(Type::getInt64Ty(BB->getContext()), GV, "", + Call->getIterator()); Instruction *PassThroughInst = BPFCoreSharedInfo::insertPassThrough(M, BB, LDInst, Call); Call->replaceAllUsesWith(PassThroughInst); diff --git a/llvm/lib/Target/BPF/BPFTargetMachine.cpp b/llvm/lib/Target/BPF/BPFTargetMachine.cpp index 5f26bec2e390c8f43c762695e12426b1ff0b7286..a7bed69b0f2ab61a25e95c7aa6e3ed3a50560704 100644 --- a/llvm/lib/Target/BPF/BPFTargetMachine.cpp +++ b/llvm/lib/Target/BPF/BPFTargetMachine.cpp @@ -108,25 +108,16 @@ TargetPassConfig *BPFTargetMachine::createPassConfig(PassManagerBase &PM) { return new BPFPassConfig(*this, PM); } +static Expected<bool> parseBPFPreserveStaticOffsetOptions(StringRef Params) { + return PassBuilder::parseSinglePassOption(Params, "allow-partial", + "BPFPreserveStaticOffsetPass"); +} + void BPFTargetMachine::registerPassBuilderCallbacks( PassBuilder &PB, bool PopulateClassToPassNames) { - PB.registerPipelineParsingCallback( - [](StringRef PassName, FunctionPassManager &FPM, - ArrayRef<PassBuilder::PipelineElement>) { - if (PassName == "bpf-ir-peephole") { - FPM.addPass(BPFIRPeepholePass()); - return true; - } - if (PassName == "bpf-preserve-static-offset") { - FPM.addPass(BPFPreserveStaticOffsetPass(false)); - return true; - } - if (PassName == "bpf-aspace-simplify") { - FPM.addPass(BPFASpaceCastSimplifyPass()); - return true; - } - return false; - }); +#define GET_PASS_REGISTRY "BPFPassRegistry.def" +#include "llvm/Passes/TargetPassRegistry.inc" + PB.registerPipelineStartEPCallback( [=](ModulePassManager &MPM, OptimizationLevel) { FunctionPassManager FPM; diff --git a/llvm/lib/Target/BPF/CMakeLists.txt b/llvm/lib/Target/BPF/CMakeLists.txt index cb21ed03a86c1e2ee826821e3010728a959925ea..eade4cacb7100e6070aa5907efafe09fc9193c0d 100644 --- a/llvm/lib/Target/BPF/CMakeLists.txt +++ b/llvm/lib/Target/BPF/CMakeLists.txt @@ -54,6 +54,7 @@ add_llvm_target(BPFCodeGen GlobalISel IPO MC + Passes Scalar SelectionDAG Support diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp b/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp index 7dad40803d47708b86b459c4060722240f6c175b..44932383fb43e974e89e9beebe1a9825cb031fc9 100644 --- a/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp +++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp @@ -81,7 +81,10 @@ public: // The target is the 3rd operand of cond inst and the 1st of uncond inst. int32_t Imm; if (isConditionalBranch(Inst)) { - Imm = (short)Inst.getOperand(2).getImm(); + if (Inst.getOpcode() == BPF::JCOND) + Imm = (short)Inst.getOperand(0).getImm(); + else + Imm = (short)Inst.getOperand(2).getImm(); } else if (isUnconditionalBranch(Inst)) { if (Inst.getOpcode() == BPF::JMP) Imm = (short)Inst.getOperand(0).getImm(); diff --git a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp index 4711e58bbed6113fb71d031f7182508d5493a692..30bd3dcefa605a66dc228770f50340ad80a8c0a9 100644 --- a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp +++ b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp @@ -400,7 +400,7 @@ public: /// Gets location of the last token of this operand. SMLoc getEndLoc() const override { return EndLoc; } - unsigned getReg() const override { + MCRegister getReg() const override { assert(Kind == Register && "Invalid type access!"); return Reg.RegNum; } diff --git a/llvm/lib/Target/DirectX/CMakeLists.txt b/llvm/lib/Target/DirectX/CMakeLists.txt index bf93280779bf8bef1e99be9871c82df55529c7ff..4c70b3f9230edba81eb2be7ce1ba1fcdc308865f 100644 --- a/llvm/lib/Target/DirectX/CMakeLists.txt +++ b/llvm/lib/Target/DirectX/CMakeLists.txt @@ -19,6 +19,7 @@ add_llvm_target(DirectXCodeGen DirectXSubtarget.cpp DirectXTargetMachine.cpp DXContainerGlobals.cpp + DXILIntrinsicExpansion.cpp DXILMetadata.cpp DXILOpBuilder.cpp DXILOpLowering.cpp diff --git a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp index 56063b487f68472d5fc762c615d8d64942cff06c..65cf1dfdb4031bcf9fff3f7d84d7047fab72e79f 100644 --- a/llvm/lib/Target/DirectX/DXContainerGlobals.cpp +++ b/llvm/lib/Target/DirectX/DXContainerGlobals.cpp @@ -28,7 +28,7 @@ using namespace llvm::dxil; namespace { class DXContainerGlobals : public llvm::ModulePass { - GlobalVariable *getShaderFlags(Module &M); + GlobalVariable *getFeatureFlags(Module &M); GlobalVariable *computeShaderHash(Module &M); public: @@ -53,21 +53,24 @@ public: bool DXContainerGlobals::runOnModule(Module &M) { llvm::SmallVector<GlobalValue *> Globals; - Globals.push_back(getShaderFlags(M)); + Globals.push_back(getFeatureFlags(M)); Globals.push_back(computeShaderHash(M)); appendToCompilerUsed(M, Globals); return true; } -GlobalVariable *DXContainerGlobals::getShaderFlags(Module &M) { - const uint64_t Flags = - (uint64_t)(getAnalysis<ShaderFlagsAnalysisWrapper>().getShaderFlags()); +GlobalVariable *DXContainerGlobals::getFeatureFlags(Module &M) { + const uint64_t FeatureFlags = + static_cast<uint64_t>(getAnalysis<ShaderFlagsAnalysisWrapper>() + .getShaderFlags() + .getFeatureFlags()); - Constant *FlagsConstant = ConstantInt::get(M.getContext(), APInt(64, Flags)); - auto *GV = new llvm::GlobalVariable(M, FlagsConstant->getType(), true, + Constant *FeatureFlagsConstant = + ConstantInt::get(M.getContext(), APInt(64, FeatureFlags)); + auto *GV = new llvm::GlobalVariable(M, FeatureFlagsConstant->getType(), true, GlobalValue::PrivateLinkage, - FlagsConstant, "dx.sfi0"); + FeatureFlagsConstant, "dx.sfi0"); GV->setSection("SFI0"); GV->setAlignment(Align(4)); return GV; diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td index 66b0ef24332c25ab56ca88baa319f1cd2a41ea75..cd388ed3e3191b193cd8771646345961092deb9b 100644 --- a/llvm/lib/Target/DirectX/DXIL.td +++ b/llvm/lib/Target/DirectX/DXIL.td @@ -255,6 +255,14 @@ class DXILOpMapping<int opCode, DXILOpClass opClass, } // Concrete definition of DXIL Operation mapping to corresponding LLVM intrinsic +def Abs : DXILOpMapping<6, unary, int_fabs, + "Returns the absolute value of the input.">; +def IsInf : DXILOpMapping<9, isSpecialFloat, int_dx_isinf, + "Determines if the specified value is infinite.", + [llvm_i1_ty, llvm_halforfloat_ty]>; +def Cos : DXILOpMapping<12, unary, int_cos, + "Returns cosine(theta) for theta in radians.", + [llvm_halforfloat_ty, LLVMMatchType<0>]>; def Sin : DXILOpMapping<13, unary, int_sin, "Returns sine(theta) for theta in radians.", [llvm_halforfloat_ty, LLVMMatchType<0>]>; @@ -266,18 +274,60 @@ def Frac : DXILOpMapping<22, unary, int_dx_frac, "Returns a fraction from 0 to 1 that represents the " "decimal part of the input.", [llvm_halforfloat_ty, LLVMMatchType<0>]>; -def Round : DXILOpMapping<26, unary, int_round, +def Log2 : DXILOpMapping<23, unary, int_log2, + "Returns the base-2 logarithm of the specified value.", + [llvm_halforfloat_ty, LLVMMatchType<0>]>; +def Sqrt : DXILOpMapping<24, unary, int_sqrt, + "Returns the square root of the specified floating-point" + "value, per component.", + [llvm_halforfloat_ty, LLVMMatchType<0>]>; +def RSqrt : DXILOpMapping<25, unary, int_dx_rsqrt, + "Returns the reciprocal of the square root of the specified value." + "rsqrt(x) = 1 / sqrt(x).", + [llvm_halforfloat_ty, LLVMMatchType<0>]>; +def Round : DXILOpMapping<26, unary, int_roundeven, "Returns the input rounded to the nearest integer" "within a floating-point type.", [llvm_halforfloat_ty, LLVMMatchType<0>]>; +def Floor : DXILOpMapping<27, unary, int_floor, + "Returns the largest integer that is less than or equal to the input.", + [llvm_halforfloat_ty, LLVMMatchType<0>]>; +def Ceil : DXILOpMapping<28, unary, int_ceil, + "Returns the smallest integer that is greater than or equal to the input.", + [llvm_halforfloat_ty, LLVMMatchType<0>]>; +def Trunc : DXILOpMapping<29, unary, int_trunc, + "Returns the specified value truncated to the integer component.", + [llvm_halforfloat_ty, LLVMMatchType<0>]>; +def Rbits : DXILOpMapping<30, unary, int_bitreverse, + "Returns the specified value with its bits reversed.", + [llvm_anyint_ty, LLVMMatchType<0>]>; +def FMax : DXILOpMapping<35, binary, int_maxnum, + "Float maximum. FMax(a,b) = a > b ? a : b">; +def FMin : DXILOpMapping<36, binary, int_minnum, + "Float minimum. FMin(a,b) = a < b ? a : b">; +def SMax : DXILOpMapping<37, binary, int_smax, + "Signed integer maximum. SMax(a,b) = a > b ? a : b">; +def SMin : DXILOpMapping<38, binary, int_smin, + "Signed integer minimum. SMin(a,b) = a < b ? a : b">; def UMax : DXILOpMapping<39, binary, int_umax, "Unsigned integer maximum. UMax(a,b) = a > b ? a : b">; +def UMin : DXILOpMapping<40, binary, int_umin, + "Unsigned integer minimum. UMin(a,b) = a < b ? a : b">; def FMad : DXILOpMapping<46, tertiary, int_fmuladd, "Floating point arithmetic multiply/add operation. fmad(m,a,b) = m * a + b.">; def IMad : DXILOpMapping<48, tertiary, int_dx_imad, "Signed integer arithmetic multiply/add operation. imad(m,a,b) = m * a + b.">; def UMad : DXILOpMapping<49, tertiary, int_dx_umad, "Unsigned integer arithmetic multiply/add operation. umad(m,a,b) = m * a + b.">; +let OpTypes = !listconcat([llvm_halforfloat_ty], !listsplat(llvm_halforfloat_ty, 4)) in + def Dot2 : DXILOpMapping<54, dot2, int_dx_dot2, + "dot product of two float vectors Dot(a,b) = a[0]*b[0] + ... + a[n]*b[n] where n is between 0 and 1">; +let OpTypes = !listconcat([llvm_halforfloat_ty], !listsplat(llvm_halforfloat_ty, 6)) in + def Dot3 : DXILOpMapping<55, dot3, int_dx_dot3, + "dot product of two float vectors Dot(a,b) = a[0]*b[0] + ... + a[n]*b[n] where n is between 0 and 2">; +let OpTypes = !listconcat([llvm_halforfloat_ty], !listsplat(llvm_halforfloat_ty, 8)) in + def Dot4 : DXILOpMapping<56, dot4, int_dx_dot4, + "dot product of two float vectors Dot(a,b) = a[0]*b[0] + ... + a[n]*b[n] where n is between 0 and 3">; def ThreadId : DXILOpMapping<93, threadId, int_dx_thread_id, "Reads the thread ID">; def GroupId : DXILOpMapping<94, groupId, int_dx_group_id, diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3e2d10f5ee7a238cf5a8922f956e24d06b0e402b --- /dev/null +++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp @@ -0,0 +1,349 @@ +//===- DXILIntrinsicExpansion.cpp - Prepare LLVM Module for DXIL encoding--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file This file contains DXIL intrinsic expansions for those that don't have +// opcodes in DirectX Intermediate Language (DXIL). +//===----------------------------------------------------------------------===// + +#include "DXILIntrinsicExpansion.h" +#include "DirectX.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/IntrinsicsDirectX.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/Type.h" +#include "llvm/Pass.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" + +#define DEBUG_TYPE "dxil-intrinsic-expansion" + +using namespace llvm; + +static bool isIntrinsicExpansion(Function &F) { + switch (F.getIntrinsicID()) { + case Intrinsic::abs: + case Intrinsic::exp: + case Intrinsic::log: + case Intrinsic::log10: + case Intrinsic::pow: + case Intrinsic::dx_any: + case Intrinsic::dx_clamp: + case Intrinsic::dx_uclamp: + case Intrinsic::dx_lerp: + case Intrinsic::dx_rcp: + case Intrinsic::dx_sdot: + case Intrinsic::dx_udot: + return true; + } + return false; +} + +static bool expandAbs(CallInst *Orig) { + Value *X = Orig->getOperand(0); + IRBuilder<> Builder(Orig->getParent()); + Builder.SetInsertPoint(Orig); + Type *Ty = X->getType(); + Type *EltTy = Ty->getScalarType(); + Constant *Zero = Ty->isVectorTy() + ? ConstantVector::getSplat( + ElementCount::getFixed( + cast<FixedVectorType>(Ty)->getNumElements()), + ConstantInt::get(EltTy, 0)) + : ConstantInt::get(EltTy, 0); + auto *V = Builder.CreateSub(Zero, X); + auto *MaxCall = + Builder.CreateIntrinsic(Ty, Intrinsic::smax, {X, V}, nullptr, "dx.max"); + Orig->replaceAllUsesWith(MaxCall); + Orig->eraseFromParent(); + return true; +} + +static bool expandIntegerDot(CallInst *Orig, Intrinsic::ID DotIntrinsic) { + assert(DotIntrinsic == Intrinsic::dx_sdot || + DotIntrinsic == Intrinsic::dx_udot); + Intrinsic::ID MadIntrinsic = DotIntrinsic == Intrinsic::dx_sdot + ? Intrinsic::dx_imad + : Intrinsic::dx_umad; + Value *A = Orig->getOperand(0); + Value *B = Orig->getOperand(1); + Type *ATy = A->getType(); + Type *BTy = B->getType(); + assert(ATy->isVectorTy() && BTy->isVectorTy()); + + IRBuilder<> Builder(Orig->getParent()); + Builder.SetInsertPoint(Orig); + + auto *AVec = dyn_cast<FixedVectorType>(A->getType()); + Value *Elt0 = Builder.CreateExtractElement(A, (uint64_t)0); + Value *Elt1 = Builder.CreateExtractElement(B, (uint64_t)0); + Value *Result = Builder.CreateMul(Elt0, Elt1); + for (unsigned I = 1; I < AVec->getNumElements(); I++) { + Elt0 = Builder.CreateExtractElement(A, I); + Elt1 = Builder.CreateExtractElement(B, I); + Result = Builder.CreateIntrinsic(Result->getType(), MadIntrinsic, + ArrayRef<Value *>{Elt0, Elt1, Result}, + nullptr, "dx.mad"); + } + Orig->replaceAllUsesWith(Result); + Orig->eraseFromParent(); + return true; +} + +static bool expandExpIntrinsic(CallInst *Orig) { + Value *X = Orig->getOperand(0); + IRBuilder<> Builder(Orig->getParent()); + Builder.SetInsertPoint(Orig); + Type *Ty = X->getType(); + Type *EltTy = Ty->getScalarType(); + Constant *Log2eConst = + Ty->isVectorTy() ? ConstantVector::getSplat( + ElementCount::getFixed( + cast<FixedVectorType>(Ty)->getNumElements()), + ConstantFP::get(EltTy, numbers::log2ef)) + : ConstantFP::get(EltTy, numbers::log2ef); + Value *NewX = Builder.CreateFMul(Log2eConst, X); + auto *Exp2Call = + Builder.CreateIntrinsic(Ty, Intrinsic::exp2, {NewX}, nullptr, "dx.exp2"); + Exp2Call->setTailCall(Orig->isTailCall()); + Exp2Call->setAttributes(Orig->getAttributes()); + Orig->replaceAllUsesWith(Exp2Call); + Orig->eraseFromParent(); + return true; +} + +static bool expandAnyIntrinsic(CallInst *Orig) { + Value *X = Orig->getOperand(0); + IRBuilder<> Builder(Orig->getParent()); + Builder.SetInsertPoint(Orig); + Type *Ty = X->getType(); + Type *EltTy = Ty->getScalarType(); + + if (!Ty->isVectorTy()) { + Value *Cond = EltTy->isFloatingPointTy() + ? Builder.CreateFCmpUNE(X, ConstantFP::get(EltTy, 0)) + : Builder.CreateICmpNE(X, ConstantInt::get(EltTy, 0)); + Orig->replaceAllUsesWith(Cond); + } else { + auto *XVec = dyn_cast<FixedVectorType>(Ty); + Value *Cond = + EltTy->isFloatingPointTy() + ? Builder.CreateFCmpUNE( + X, ConstantVector::getSplat( + ElementCount::getFixed(XVec->getNumElements()), + ConstantFP::get(EltTy, 0))) + : Builder.CreateICmpNE( + X, ConstantVector::getSplat( + ElementCount::getFixed(XVec->getNumElements()), + ConstantInt::get(EltTy, 0))); + Value *Result = Builder.CreateExtractElement(Cond, (uint64_t)0); + for (unsigned I = 1; I < XVec->getNumElements(); I++) { + Value *Elt = Builder.CreateExtractElement(Cond, I); + Result = Builder.CreateOr(Result, Elt); + } + Orig->replaceAllUsesWith(Result); + } + Orig->eraseFromParent(); + return true; +} + +static bool expandLerpIntrinsic(CallInst *Orig) { + Value *X = Orig->getOperand(0); + Value *Y = Orig->getOperand(1); + Value *S = Orig->getOperand(2); + IRBuilder<> Builder(Orig->getParent()); + Builder.SetInsertPoint(Orig); + auto *V = Builder.CreateFSub(Y, X); + V = Builder.CreateFMul(S, V); + auto *Result = Builder.CreateFAdd(X, V, "dx.lerp"); + Orig->replaceAllUsesWith(Result); + Orig->eraseFromParent(); + return true; +} + +static bool expandLogIntrinsic(CallInst *Orig, + float LogConstVal = numbers::ln2f) { + Value *X = Orig->getOperand(0); + IRBuilder<> Builder(Orig->getParent()); + Builder.SetInsertPoint(Orig); + Type *Ty = X->getType(); + Type *EltTy = Ty->getScalarType(); + Constant *Ln2Const = + Ty->isVectorTy() ? ConstantVector::getSplat( + ElementCount::getFixed( + cast<FixedVectorType>(Ty)->getNumElements()), + ConstantFP::get(EltTy, LogConstVal)) + : ConstantFP::get(EltTy, LogConstVal); + auto *Log2Call = + Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2"); + Log2Call->setTailCall(Orig->isTailCall()); + Log2Call->setAttributes(Orig->getAttributes()); + auto *Result = Builder.CreateFMul(Ln2Const, Log2Call); + Orig->replaceAllUsesWith(Result); + Orig->eraseFromParent(); + return true; +} +static bool expandLog10Intrinsic(CallInst *Orig) { + return expandLogIntrinsic(Orig, numbers::ln2f / numbers::ln10f); +} + +static bool expandPowIntrinsic(CallInst *Orig) { + + Value *X = Orig->getOperand(0); + Value *Y = Orig->getOperand(1); + Type *Ty = X->getType(); + IRBuilder<> Builder(Orig->getParent()); + Builder.SetInsertPoint(Orig); + + auto *Log2Call = + Builder.CreateIntrinsic(Ty, Intrinsic::log2, {X}, nullptr, "elt.log2"); + auto *Mul = Builder.CreateFMul(Log2Call, Y); + auto *Exp2Call = + Builder.CreateIntrinsic(Ty, Intrinsic::exp2, {Mul}, nullptr, "elt.exp2"); + Exp2Call->setTailCall(Orig->isTailCall()); + Exp2Call->setAttributes(Orig->getAttributes()); + Orig->replaceAllUsesWith(Exp2Call); + Orig->eraseFromParent(); + return true; +} + +static bool expandRcpIntrinsic(CallInst *Orig) { + Value *X = Orig->getOperand(0); + IRBuilder<> Builder(Orig->getParent()); + Builder.SetInsertPoint(Orig); + Type *Ty = X->getType(); + Type *EltTy = Ty->getScalarType(); + Constant *One = + Ty->isVectorTy() + ? ConstantVector::getSplat( + ElementCount::getFixed( + dyn_cast<FixedVectorType>(Ty)->getNumElements()), + ConstantFP::get(EltTy, 1.0)) + : ConstantFP::get(EltTy, 1.0); + auto *Result = Builder.CreateFDiv(One, X, "dx.rcp"); + Orig->replaceAllUsesWith(Result); + Orig->eraseFromParent(); + return true; +} + +static Intrinsic::ID getMaxForClamp(Type *ElemTy, + Intrinsic::ID ClampIntrinsic) { + if (ClampIntrinsic == Intrinsic::dx_uclamp) + return Intrinsic::umax; + assert(ClampIntrinsic == Intrinsic::dx_clamp); + if (ElemTy->isVectorTy()) + ElemTy = ElemTy->getScalarType(); + if (ElemTy->isIntegerTy()) + return Intrinsic::smax; + assert(ElemTy->isFloatingPointTy()); + return Intrinsic::maxnum; +} + +static Intrinsic::ID getMinForClamp(Type *ElemTy, + Intrinsic::ID ClampIntrinsic) { + if (ClampIntrinsic == Intrinsic::dx_uclamp) + return Intrinsic::umin; + assert(ClampIntrinsic == Intrinsic::dx_clamp); + if (ElemTy->isVectorTy()) + ElemTy = ElemTy->getScalarType(); + if (ElemTy->isIntegerTy()) + return Intrinsic::smin; + assert(ElemTy->isFloatingPointTy()); + return Intrinsic::minnum; +} + +static bool expandClampIntrinsic(CallInst *Orig, Intrinsic::ID ClampIntrinsic) { + Value *X = Orig->getOperand(0); + Value *Min = Orig->getOperand(1); + Value *Max = Orig->getOperand(2); + Type *Ty = X->getType(); + IRBuilder<> Builder(Orig->getParent()); + Builder.SetInsertPoint(Orig); + auto *MaxCall = Builder.CreateIntrinsic( + Ty, getMaxForClamp(Ty, ClampIntrinsic), {X, Min}, nullptr, "dx.max"); + auto *MinCall = + Builder.CreateIntrinsic(Ty, getMinForClamp(Ty, ClampIntrinsic), + {MaxCall, Max}, nullptr, "dx.min"); + + Orig->replaceAllUsesWith(MinCall); + Orig->eraseFromParent(); + return true; +} + +static bool expandIntrinsic(Function &F, CallInst *Orig) { + switch (F.getIntrinsicID()) { + case Intrinsic::abs: + return expandAbs(Orig); + case Intrinsic::exp: + return expandExpIntrinsic(Orig); + case Intrinsic::log: + return expandLogIntrinsic(Orig); + case Intrinsic::log10: + return expandLog10Intrinsic(Orig); + case Intrinsic::pow: + return expandPowIntrinsic(Orig); + case Intrinsic::dx_any: + return expandAnyIntrinsic(Orig); + case Intrinsic::dx_uclamp: + case Intrinsic::dx_clamp: + return expandClampIntrinsic(Orig, F.getIntrinsicID()); + case Intrinsic::dx_lerp: + return expandLerpIntrinsic(Orig); + case Intrinsic::dx_rcp: + return expandRcpIntrinsic(Orig); + case Intrinsic::dx_sdot: + case Intrinsic::dx_udot: + return expandIntegerDot(Orig, F.getIntrinsicID()); + } + return false; +} + +static bool expansionIntrinsics(Module &M) { + for (auto &F : make_early_inc_range(M.functions())) { + if (!isIntrinsicExpansion(F)) + continue; + bool IntrinsicExpanded = false; + for (User *U : make_early_inc_range(F.users())) { + auto *IntrinsicCall = dyn_cast<CallInst>(U); + if (!IntrinsicCall) + continue; + IntrinsicExpanded = expandIntrinsic(F, IntrinsicCall); + } + if (F.user_empty() && IntrinsicExpanded) + F.eraseFromParent(); + } + return true; +} + +PreservedAnalyses DXILIntrinsicExpansion::run(Module &M, + ModuleAnalysisManager &) { + if (expansionIntrinsics(M)) + return PreservedAnalyses::none(); + return PreservedAnalyses::all(); +} + +bool DXILIntrinsicExpansionLegacy::runOnModule(Module &M) { + return expansionIntrinsics(M); +} + +char DXILIntrinsicExpansionLegacy::ID = 0; + +INITIALIZE_PASS_BEGIN(DXILIntrinsicExpansionLegacy, DEBUG_TYPE, + "DXIL Intrinsic Expansion", false, false) +INITIALIZE_PASS_END(DXILIntrinsicExpansionLegacy, DEBUG_TYPE, + "DXIL Intrinsic Expansion", false, false) + +ModulePass *llvm::createDXILIntrinsicExpansionLegacyPass() { + return new DXILIntrinsicExpansionLegacy(); +} diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.h b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.h new file mode 100644 index 0000000000000000000000000000000000000000..c86681af7a3712dc7110f0fa611a115e8f8d0c41 --- /dev/null +++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.h @@ -0,0 +1,33 @@ +//===- DXILIntrinsicExpansion.h - Prepare LLVM Module for DXIL encoding----===// +// +// 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_TARGET_DIRECTX_DXILINTRINSICEXPANSION_H +#define LLVM_TARGET_DIRECTX_DXILINTRINSICEXPANSION_H + +#include "DXILResource.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" + +namespace llvm { + +/// A pass that transforms DXIL Intrinsics that don't have DXIL opCodes +class DXILIntrinsicExpansion : public PassInfoMixin<DXILIntrinsicExpansion> { +public: + PreservedAnalyses run(Module &M, ModuleAnalysisManager &); +}; + +class DXILIntrinsicExpansionLegacy : public ModulePass { + +public: + bool runOnModule(Module &M) override; + DXILIntrinsicExpansionLegacy() : ModulePass(ID) {} + + static char ID; // Pass identification. +}; +} // namespace llvm + +#endif // LLVM_TARGET_DIRECTX_DXILINTRINSICEXPANSION_H diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp index 11b24d044923687ef29a1486a511eb7444a0607a..0b3982ea0f438a80bc56786a78dd09dccbbe2959 100644 --- a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp +++ b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp @@ -190,13 +190,13 @@ static StructType *getHandleType(LLVMContext &Ctx) { static Type *getTypeFromParameterKind(ParameterKind Kind, Type *OverloadTy) { auto &Ctx = OverloadTy->getContext(); switch (Kind) { - case ParameterKind::VOID: + case ParameterKind::Void: return Type::getVoidTy(Ctx); - case ParameterKind::HALF: + case ParameterKind::Half: return Type::getHalfTy(Ctx); - case ParameterKind::FLOAT: + case ParameterKind::Float: return Type::getFloatTy(Ctx); - case ParameterKind::DOUBLE: + case ParameterKind::Double: return Type::getDoubleTy(Ctx); case ParameterKind::I1: return Type::getInt1Ty(Ctx); @@ -208,11 +208,11 @@ static Type *getTypeFromParameterKind(ParameterKind Kind, Type *OverloadTy) { return Type::getInt32Ty(Ctx); case ParameterKind::I64: return Type::getInt64Ty(Ctx); - case ParameterKind::OVERLOAD: + case ParameterKind::Overload: return OverloadTy; - case ParameterKind::RESOURCE_RET: + case ParameterKind::ResourceRet: return getResRetType(OverloadTy, Ctx); - case ParameterKind::DXIL_HANDLE: + case ParameterKind::DXILHandle: return getHandleType(Ctx); default: break; @@ -229,13 +229,13 @@ static Type *getTypeFromParameterKind(ParameterKind Kind, Type *OverloadTy) { /// its specification in DXIL.td. /// \param OverloadTy Return type to be used to construct DXIL function type. static FunctionType *getDXILOpFunctionType(const OpCodeProperty *Prop, - Type *OverloadTy) { + Type *ReturnTy, Type *OverloadTy) { SmallVector<Type *> ArgTys; auto ParamKinds = getOpCodeParameterKind(*Prop); - // Add OverloadTy as return type of the function - ArgTys.emplace_back(OverloadTy); + // Add ReturnTy as return type of the function + ArgTys.emplace_back(ReturnTy); // Add DXIL Opcode value type viz., Int32 as first argument ArgTys.emplace_back(Type::getInt32Ty(OverloadTy->getContext())); @@ -249,34 +249,31 @@ static FunctionType *getDXILOpFunctionType(const OpCodeProperty *Prop, ArgTys[0], ArrayRef<Type *>(&ArgTys[1], ArgTys.size() - 1), false); } -static FunctionCallee getOrCreateDXILOpFunction(dxil::OpCode DXILOp, - Type *OverloadTy, Module &M) { - const OpCodeProperty *Prop = getOpCodeProperty(DXILOp); +namespace llvm { +namespace dxil { + +CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy, + Type *OverloadTy, + SmallVector<Value *> Args) { + const OpCodeProperty *Prop = getOpCodeProperty(OpCode); OverloadKind Kind = getOverloadKind(OverloadTy); if ((Prop->OverloadTys & (uint16_t)Kind) == 0) { report_fatal_error("Invalid Overload Type", /* gen_crash_diag=*/false); } - std::string FnName = constructOverloadName(Kind, OverloadTy, *Prop); - // Dependent on name to dedup. - if (auto *Fn = M.getFunction(FnName)) - return FunctionCallee(Fn); - - FunctionType *DXILOpFT = getDXILOpFunctionType(Prop, OverloadTy); - return M.getOrInsertFunction(FnName, DXILOpFT); -} - -namespace llvm { -namespace dxil { + std::string DXILFnName = constructOverloadName(Kind, OverloadTy, *Prop); + FunctionCallee DXILFn; + // Get the function with name DXILFnName, if one exists + if (auto *Func = M.getFunction(DXILFnName)) { + DXILFn = FunctionCallee(Func); + } else { + // Construct and add a function with name DXILFnName + FunctionType *DXILOpFT = getDXILOpFunctionType(Prop, ReturnTy, OverloadTy); + DXILFn = M.getOrInsertFunction(DXILFnName, DXILOpFT); + } -CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode, Type *OverloadTy, - llvm::iterator_range<Use *> Args) { - auto Fn = getOrCreateDXILOpFunction(OpCode, OverloadTy, M); - SmallVector<Value *> FullArgs; - FullArgs.emplace_back(B.getInt32((int32_t)OpCode)); - FullArgs.append(Args.begin(), Args.end()); - return B.CreateCall(Fn, FullArgs); + return B.CreateCall(DXILFn, Args); } Type *DXILOpBuilder::getOverloadTy(dxil::OpCode OpCode, FunctionType *FT) { @@ -321,8 +318,8 @@ Type *DXILOpBuilder::getOverloadTy(dxil::OpCode OpCode, FunctionType *FT) { auto ParamKinds = getOpCodeParameterKind(*Prop); auto Kind = ParamKinds[Prop->OverloadParamIndex]; // For ResRet and CBufferRet, OverloadTy is in field of StructType. - if (Kind == ParameterKind::CBUFFER_RET || - Kind == ParameterKind::RESOURCE_RET) { + if (Kind == ParameterKind::CBufferRet || + Kind == ParameterKind::ResourceRet) { auto *ST = cast<StructType>(OverloadType); OverloadType = ST->getElementType(0); } diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.h b/llvm/lib/Target/DirectX/DXILOpBuilder.h index 1c15f109184adf6f91dff2b9c030da29556a1a33..5babeae470178b50b640f0ef93994fabccbd5a9d 100644 --- a/llvm/lib/Target/DirectX/DXILOpBuilder.h +++ b/llvm/lib/Target/DirectX/DXILOpBuilder.h @@ -13,7 +13,7 @@ #define LLVM_LIB_TARGET_DIRECTX_DXILOPBUILDER_H #include "DXILConstants.h" -#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/SmallVector.h" namespace llvm { class Module; @@ -29,8 +29,13 @@ namespace dxil { class DXILOpBuilder { public: DXILOpBuilder(Module &M, IRBuilderBase &B) : M(M), B(B) {} - CallInst *createDXILOpCall(dxil::OpCode OpCode, Type *OverloadTy, - llvm::iterator_range<Use *> Args); + /// Create an instruction that calls DXIL Op with return type, specified + /// opcode, and call arguments. \param OpCode Opcode of the DXIL Op call + /// constructed \param ReturnTy Return type of the DXIL Op call constructed + /// \param OverloadTy Overload type of the DXIL Op call constructed + /// \return DXIL Op call constructed + CallInst *createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy, + Type *OverloadTy, SmallVector<Value *> Args); Type *getOverloadTy(dxil::OpCode OpCode, FunctionType *FT); static const char *getOpCodeName(dxil::OpCode DXILOp); diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index 6b649b76beecdfec4d050a9825fad084a5b6e84d..f09e322f88e1fd96b107c988902122c22db087f5 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "DXILConstants.h" +#include "DXILIntrinsicExpansion.h" #include "DXILOpBuilder.h" #include "DirectX.h" #include "llvm/ADT/SmallVector.h" @@ -29,9 +30,50 @@ using namespace llvm; using namespace llvm::dxil; +static bool isVectorArgExpansion(Function &F) { + switch (F.getIntrinsicID()) { + case Intrinsic::dx_dot2: + case Intrinsic::dx_dot3: + case Intrinsic::dx_dot4: + return true; + } + return false; +} + +static SmallVector<Value *> populateOperands(Value *Arg, IRBuilder<> &Builder) { + SmallVector<Value *, 4> ExtractedElements; + auto *VecArg = dyn_cast<FixedVectorType>(Arg->getType()); + for (unsigned I = 0; I < VecArg->getNumElements(); ++I) { + Value *Index = ConstantInt::get(Type::getInt32Ty(Arg->getContext()), I); + Value *ExtractedElement = Builder.CreateExtractElement(Arg, Index); + ExtractedElements.push_back(ExtractedElement); + } + return ExtractedElements; +} + +static SmallVector<Value *> argVectorFlatten(CallInst *Orig, + IRBuilder<> &Builder) { + // Note: arg[NumOperands-1] is a pointer and is not needed by our flattening. + unsigned NumOperands = Orig->getNumOperands() - 1; + assert(NumOperands > 0); + Value *Arg0 = Orig->getOperand(0); + [[maybe_unused]] auto *VecArg0 = dyn_cast<FixedVectorType>(Arg0->getType()); + assert(VecArg0); + SmallVector<Value *> NewOperands = populateOperands(Arg0, Builder); + for (unsigned I = 1; I < NumOperands; ++I) { + Value *Arg = Orig->getOperand(I); + [[maybe_unused]] auto *VecArg = dyn_cast<FixedVectorType>(Arg->getType()); + assert(VecArg); + assert(VecArg0->getElementType() == VecArg->getElementType()); + assert(VecArg0->getNumElements() == VecArg->getNumElements()); + auto NextOperandList = populateOperands(Arg, Builder); + NewOperands.append(NextOperandList.begin(), NextOperandList.end()); + } + return NewOperands; +} + static void lowerIntrinsic(dxil::OpCode DXILOp, Function &F, Module &M) { IRBuilder<> B(M.getContext()); - Value *DXILOpArg = B.getInt32(static_cast<unsigned>(DXILOp)); DXILOpBuilder DXILB(M, B); Type *OverloadTy = DXILB.getOverloadTy(DXILOp, F.getFunctionType()); for (User *U : make_early_inc_range(F.users())) { @@ -40,10 +82,17 @@ static void lowerIntrinsic(dxil::OpCode DXILOp, Function &F, Module &M) { continue; SmallVector<Value *> Args; + Value *DXILOpArg = B.getInt32(static_cast<unsigned>(DXILOp)); Args.emplace_back(DXILOpArg); - Args.append(CI->arg_begin(), CI->arg_end()); B.SetInsertPoint(CI); - CallInst *DXILCI = DXILB.createDXILOpCall(DXILOp, OverloadTy, CI->args()); + if (isVectorArgExpansion(F)) { + SmallVector<Value *> NewArgs = argVectorFlatten(CI, B); + Args.append(NewArgs.begin(), NewArgs.end()); + } else + Args.append(CI->arg_begin(), CI->arg_end()); + + CallInst *DXILCI = + DXILB.createDXILOpCall(DXILOp, F.getReturnType(), OverloadTy, Args); CI->replaceAllUsesWith(DXILCI); CI->eraseFromParent(); @@ -94,9 +143,12 @@ public: DXILOpLoweringLegacy() : ModulePass(ID) {} static char ID; // Pass identification. + void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { + // Specify the passes that your pass depends on + AU.addRequired<DXILIntrinsicExpansionLegacy>(); + } }; char DXILOpLoweringLegacy::ID = 0; - } // end anonymous namespace INITIALIZE_PASS_BEGIN(DXILOpLoweringLegacy, DEBUG_TYPE, "DXIL Op Lowering", diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp index 66a9dc46bcbfbf6c5d2092c7a2069f56e10fd34b..9fa137b4c025e18a3dcd3fa46ca82d702cbc0a78 100644 --- a/llvm/lib/Target/DirectX/DXILShaderFlags.cpp +++ b/llvm/lib/Target/DirectX/DXILShaderFlags.cpp @@ -51,9 +51,14 @@ void ComputedShaderFlags::print(raw_ostream &OS) const { if (FlagVal == 0) return; OS << "; Note: shader requires additional functionality:\n"; -#define SHADER_FEATURE_FLAG(bit, FlagName, Str) \ +#define SHADER_FEATURE_FLAG(FeatureBit, DxilModuleNum, FlagName, Str) \ if (FlagName) \ - OS << "; " Str "\n"; + (OS << ";").indent(7) << Str << "\n"; +#include "llvm/BinaryFormat/DXContainerConstants.def" + OS << "; Note: extra DXIL module flags:\n"; +#define DXIL_MODULE_FLAG(DxilModuleBit, FlagName, Str) \ + if (FlagName) \ + (OS << ";").indent(7) << Str << "\n"; #include "llvm/BinaryFormat/DXContainerConstants.def" OS << ";\n"; } diff --git a/llvm/lib/Target/DirectX/DXILShaderFlags.h b/llvm/lib/Target/DirectX/DXILShaderFlags.h index 574a7b090f528148d6eda32db740109e4ddae2ba..1df7d27de13d3c4eb7ccf7b22862e75c679bbea0 100644 --- a/llvm/lib/Target/DirectX/DXILShaderFlags.h +++ b/llvm/lib/Target/DirectX/DXILShaderFlags.h @@ -14,7 +14,6 @@ #ifndef LLVM_TARGET_DIRECTX_DXILSHADERFLAGS_H #define LLVM_TARGET_DIRECTX_DXILSHADERFLAGS_H -#include "llvm/BinaryFormat/DXContainer.h" #include "llvm/IR/PassManager.h" #include "llvm/Pass.h" #include "llvm/Support/Compiler.h" @@ -29,22 +28,37 @@ class GlobalVariable; namespace dxil { struct ComputedShaderFlags { -#define SHADER_FEATURE_FLAG(bit, FlagName, Str) bool FlagName : 1; +#define SHADER_FEATURE_FLAG(FeatureBit, DxilModuleBit, FlagName, Str) \ + bool FlagName : 1; +#define DXIL_MODULE_FLAG(DxilModuleBit, FlagName, Str) bool FlagName : 1; #include "llvm/BinaryFormat/DXContainerConstants.def" -#define SHADER_FEATURE_FLAG(bit, FlagName, Str) FlagName = false; +#define SHADER_FEATURE_FLAG(FeatureBit, DxilModuleBit, FlagName, Str) \ + FlagName = false; +#define DXIL_MODULE_FLAG(DxilModuleBit, FlagName, Str) FlagName = false; ComputedShaderFlags() { #include "llvm/BinaryFormat/DXContainerConstants.def" } + constexpr uint64_t getMask(int Bit) const { + return Bit != -1 ? 1ull << Bit : 0; + } operator uint64_t() const { uint64_t FlagValue = 0; -#define SHADER_FEATURE_FLAG(bit, FlagName, Str) \ - FlagValue |= \ - FlagName ? static_cast<uint64_t>(dxbc::FeatureFlags::FlagName) : 0ull; +#define SHADER_FEATURE_FLAG(FeatureBit, DxilModuleBit, FlagName, Str) \ + FlagValue |= FlagName ? getMask(DxilModuleBit) : 0ull; +#define DXIL_MODULE_FLAG(DxilModuleBit, FlagName, Str) \ + FlagValue |= FlagName ? getMask(DxilModuleBit) : 0ull; #include "llvm/BinaryFormat/DXContainerConstants.def" return FlagValue; } + uint64_t getFeatureFlags() const { + uint64_t FeatureFlags = 0; +#define SHADER_FEATURE_FLAG(FeatureBit, DxilModuleBit, FlagName, Str) \ + FeatureFlags |= FlagName ? getMask(FeatureBit) : 0ull; +#include "llvm/BinaryFormat/DXContainerConstants.def" + return FeatureFlags; + } static ComputedShaderFlags computeFlags(Module &M); void print(raw_ostream &OS = dbgs()) const; diff --git a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp index 9c959c66be8bdda03cd3c5d7e326aa7d64516587..80d94bf0c9d488966d7c0e5a52cfbff67c851d41 100644 --- a/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp +++ b/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp @@ -53,8 +53,8 @@ bool DXILTranslateMetadata::runOnModule(Module &M) { getAnalysis<DXILResourceWrapper>().getDXILResource(); Res.write(M); - const uint64_t Flags = - (uint64_t)(getAnalysis<ShaderFlagsAnalysisWrapper>().getShaderFlags()); + const uint64_t Flags = static_cast<uint64_t>( + getAnalysis<ShaderFlagsAnalysisWrapper>().getShaderFlags()); dxil::createEntryMD(M, Flags); return false; diff --git a/llvm/lib/Target/DirectX/DirectX.h b/llvm/lib/Target/DirectX/DirectX.h index eaecc3ac280c4cc9577d35632b5466d8858fedfb..11b5412c21d783b96722a56c17788dca51a04a29 100644 --- a/llvm/lib/Target/DirectX/DirectX.h +++ b/llvm/lib/Target/DirectX/DirectX.h @@ -28,6 +28,12 @@ void initializeDXILPrepareModulePass(PassRegistry &); /// Pass to convert modules into DXIL-compatable modules ModulePass *createDXILPrepareModulePass(); +/// Initializer for DXIL Intrinsic Expansion +void initializeDXILIntrinsicExpansionLegacyPass(PassRegistry &); + +/// Pass to expand intrinsic operations that lack DXIL opCodes +ModulePass *createDXILIntrinsicExpansionLegacyPass(); + /// Initializer for DXILOpLowering void initializeDXILOpLoweringLegacyPass(PassRegistry &); diff --git a/llvm/lib/Target/DirectX/DirectXPassRegistry.def b/llvm/lib/Target/DirectX/DirectXPassRegistry.def new file mode 100644 index 0000000000000000000000000000000000000000..1b326d020d51146027afaf3a996afc882d6eabef --- /dev/null +++ b/llvm/lib/Target/DirectX/DirectXPassRegistry.def @@ -0,0 +1,29 @@ +//===- DirectXPassRegistry.def - Registry of DirectX passes -----*- C++--*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is used as the registry of passes that are part of the +// DirectX backend. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +#ifndef MODULE_ANALYSIS +#define MODULE_ANALYSIS(NAME, CREATE_PASS) +#endif +MODULE_ANALYSIS("dx-shader-flags", dxil::ShaderFlagsAnalysis()) +MODULE_ANALYSIS("dxil-resource", DXILResourceAnalysis()) +#undef MODULE_ANALYSIS + +#ifndef MODULE_PASS +#define MODULE_PASS(NAME, CREATE_PASS) +#endif +// TODO: rename to print<foo> after NPM switch +MODULE_PASS("print-dx-shader-flags", dxil::ShaderFlagsAnalysisPrinter(dbgs())) +MODULE_PASS("print-dxil-resource", DXILResourcePrinterPass(dbgs())) +#undef MODULE_PASS diff --git a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp index 06938f8c74f155e2414659fabe01ae1e65a6e51b..bebca0675522f3db52b0bdd02e19a850ab189d23 100644 --- a/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp +++ b/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp @@ -39,6 +39,7 @@ using namespace llvm; extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeDirectXTarget() { RegisterTargetMachine<DirectXTargetMachine> X(getTheDirectXTarget()); auto *PR = PassRegistry::getPassRegistry(); + initializeDXILIntrinsicExpansionLegacyPass(*PR); initializeDXILPrepareModulePass(*PR); initializeEmbedDXILPassPass(*PR); initializeWriteDXILPassPass(*PR); @@ -76,6 +77,7 @@ public: FunctionPass *createTargetRegisterAllocator(bool) override { return nullptr; } void addCodeGenPrepare() override { + addPass(createDXILIntrinsicExpansionLegacyPass()); addPass(createDXILOpLoweringLegacyPass()); addPass(createDXILPrepareModulePass()); addPass(createDXILTranslateMetadataPass()); @@ -102,24 +104,8 @@ DirectXTargetMachine::~DirectXTargetMachine() {} void DirectXTargetMachine::registerPassBuilderCallbacks( PassBuilder &PB, bool PopulateClassToPassNames) { - PB.registerPipelineParsingCallback( - [](StringRef PassName, ModulePassManager &PM, - ArrayRef<PassBuilder::PipelineElement>) { - if (PassName == "print-dxil-resource") { - PM.addPass(DXILResourcePrinterPass(dbgs())); - return true; - } - if (PassName == "print-dx-shader-flags") { - PM.addPass(dxil::ShaderFlagsAnalysisPrinter(dbgs())); - return true; - } - return false; - }); - - PB.registerAnalysisRegistrationCallback([](ModuleAnalysisManager &MAM) { - MAM.registerPass([&] { return DXILResourceAnalysis(); }); - MAM.registerPass([&] { return dxil::ShaderFlagsAnalysis(); }); - }); +#define GET_PASS_REGISTRY "DirectXPassRegistry.def" +#include "llvm/Passes/TargetPassRegistry.inc" } bool DirectXTargetMachine::addPassesToEmitFile( diff --git a/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp b/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp index fd7d25fa16d1dae675f81eaae5dd69ba601335a5..092cccbcca9c47c08b8fe3145bbb0693a7b95dce 100644 --- a/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp +++ b/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp @@ -43,6 +43,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" +#include "llvm/Support/HexagonAttributes.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/SMLoc.h" #include "llvm/Support/SourceMgr.h" @@ -79,7 +80,7 @@ static cl::opt<bool> ErrorNoncontigiousRegister( "merror-noncontigious-register", cl::desc("Error for register names that aren't contigious"), cl::init(false)); - +static cl::opt<bool> AddBuildAttributes("hexagon-add-build-attributes"); namespace { struct HexagonOperand; @@ -120,6 +121,9 @@ class HexagonAsmParser : public MCTargetAsmParser { SMLoc &EndLoc) override; bool ParseDirectiveSubsection(SMLoc L); bool ParseDirectiveComm(bool IsLocal, SMLoc L); + + bool parseDirectiveAttribute(SMLoc L); + bool RegisterMatchesArch(unsigned MatchNum) const; bool matchBundleOptions(); @@ -164,6 +168,9 @@ public: Parser.addAliasForDirective(".word", ".4byte"); MCAsmParserExtension::Initialize(_Parser); + + if (AddBuildAttributes) + getTargetStreamer().emitTargetAttributes(*STI); } bool splitIdentifier(OperandVector &Operands); @@ -238,7 +245,7 @@ public: /// getEndLoc - Get the location of the last token of this operand. SMLoc getEndLoc() const override { return EndLoc; } - unsigned getReg() const override { + MCRegister getReg() const override { assert(Kind == Register && "Invalid access!"); return Reg.RegNum; } @@ -652,6 +659,56 @@ bool HexagonAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return finishBundle(IDLoc, Out); return false; } +/// parseDirectiveAttribute +/// ::= .attribute int, int +/// ::= .attribute Tag_name, int +bool HexagonAsmParser::parseDirectiveAttribute(SMLoc L) { + MCAsmParser &Parser = getParser(); + int64_t Tag; + SMLoc TagLoc = Parser.getTok().getLoc(); + if (Parser.getTok().is(AsmToken::Identifier)) { + StringRef Name = Parser.getTok().getIdentifier(); + std::optional<unsigned> Ret = ELFAttrs::attrTypeFromString( + Name, HexagonAttrs::getHexagonAttributeTags()); + if (!Ret) + return Error(TagLoc, "attribute name not recognized: " + Name); + Tag = *Ret; + Parser.Lex(); + } else { + const MCExpr *AttrExpr; + + TagLoc = Parser.getTok().getLoc(); + if (Parser.parseExpression(AttrExpr)) + return true; + + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr); + if (check(!CE, TagLoc, "expected numeric constant")) + return true; + + Tag = CE->getValue(); + } + + if (Parser.parseComma()) + return true; + + // We currently only have integer values. + int64_t IntegerValue = 0; + SMLoc ValueExprLoc = Parser.getTok().getLoc(); + const MCExpr *ValueExpr; + if (Parser.parseExpression(ValueExpr)) + return true; + + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr); + if (!CE) + return Error(ValueExprLoc, "expected numeric constant"); + IntegerValue = CE->getValue(); + + if (Parser.parseEOL()) + return true; + + getTargetStreamer().emitAttribute(Tag, IntegerValue); + return false; +} /// ParseDirective parses the Hexagon specific directives bool HexagonAsmParser::ParseDirective(AsmToken DirectiveID) { @@ -664,6 +721,8 @@ bool HexagonAsmParser::ParseDirective(AsmToken DirectiveID) { return ParseDirectiveComm(false, DirectiveID.getLoc()); if (IDVal.lower() == ".subsection") return ParseDirectiveSubsection(DirectiveID.getLoc()); + if (IDVal == ".attribute") + return parseDirectiveAttribute(DirectiveID.getLoc()); return true; } diff --git a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp index 4ee67cb05d4953028d29746ee40cda8a9c688039..d2f64ac9e90b0b30b84bbf18df8ca861eb6a0671 100644 --- a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp +++ b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.cpp @@ -17,6 +17,7 @@ #include "HexagonInstrInfo.h" #include "HexagonRegisterInfo.h" #include "HexagonSubtarget.h" +#include "HexagonTargetStreamer.h" #include "MCTargetDesc/HexagonInstPrinter.h" #include "MCTargetDesc/HexagonMCExpr.h" #include "MCTargetDesc/HexagonMCInstrInfo.h" @@ -46,6 +47,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" #include <algorithm> #include <cassert> #include <cstdint> @@ -775,6 +777,24 @@ void HexagonAsmPrinter::emitInstruction(const MachineInstr *MI) { OutStreamer->emitInstruction(MCB, getSubtargetInfo()); } +void HexagonAsmPrinter::emitStartOfAsmFile(Module &M) { + if (TM.getTargetTriple().isOSBinFormatELF()) + emitAttributes(); +} + +void HexagonAsmPrinter::emitEndOfAsmFile(Module &M) { + HexagonTargetStreamer &HTS = + static_cast<HexagonTargetStreamer &>(*OutStreamer->getTargetStreamer()); + if (TM.getTargetTriple().isOSBinFormatELF()) + HTS.finishAttributeSection(); +} + +void HexagonAsmPrinter::emitAttributes() { + HexagonTargetStreamer &HTS = + static_cast<HexagonTargetStreamer &>(*OutStreamer->getTargetStreamer()); + HTS.emitTargetAttributes(*TM.getMCSubtargetInfo()); +} + void HexagonAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind) { static const int8_t NoopsInSledCount = 4; // We want to emit the following pattern: diff --git a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h index 5cb1edf54d1a76d0f64623866c3c344a3dd6d753..b555c8859650361a123a3f77bdf92bb52e3da00c 100644 --- a/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h +++ b/llvm/lib/Target/Hexagon/HexagonAsmPrinter.h @@ -29,6 +29,8 @@ class TargetMachine; class HexagonAsmPrinter : public AsmPrinter { const HexagonSubtarget *Subtarget = nullptr; + void emitAttributes(); + public: explicit HexagonAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer) @@ -68,6 +70,8 @@ class TargetMachine; const char *ExtraCode, raw_ostream &OS) override; bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS) override; + void emitStartOfAsmFile(Module &M) override; + void emitEndOfAsmFile(Module &M) override; }; } // end namespace llvm diff --git a/llvm/lib/Target/Hexagon/HexagonCommonGEP.cpp b/llvm/lib/Target/Hexagon/HexagonCommonGEP.cpp index 4ead8c68cb9014ffad99417df9a83141c3186427..b0de0405ce9619b94505126e7057bdb5529482b5 100644 --- a/llvm/lib/Target/Hexagon/HexagonCommonGEP.cpp +++ b/llvm/lib/Target/Hexagon/HexagonCommonGEP.cpp @@ -1109,7 +1109,7 @@ Value *HexagonCommonGEP::fabricateGEP(NodeVect &NA, BasicBlock::iterator At, break; } } - NewInst = GetElementPtrInst::Create(InpTy, Input, IdxList, "cgep", &*At); + NewInst = GetElementPtrInst::Create(InpTy, Input, IdxList, "cgep", At); NewInst->setIsInBounds(RN->Flags & GepNode::InBounds); LLVM_DEBUG(dbgs() << "new GEP: " << *NewInst << '\n'); if (Idx < Num) { diff --git a/llvm/lib/Target/Hexagon/HexagonPassRegistry.def b/llvm/lib/Target/Hexagon/HexagonPassRegistry.def new file mode 100644 index 0000000000000000000000000000000000000000..4f58ae6193e05b7866cb9a99c407bffcc7277f43 --- /dev/null +++ b/llvm/lib/Target/Hexagon/HexagonPassRegistry.def @@ -0,0 +1,21 @@ +//===- HexagonPassRegistry.def - Registry of Hexagon passes -----*- C++--*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is used as the registry of passes that are part of the +// Hexagon backend. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +#ifndef LOOP_PASS +#define LOOP_PASS(NAME, CREATE_PASS) +#endif +LOOP_PASS("hexagon-loop-idiom", HexagonLoopIdiomRecognitionPass()) +LOOP_PASS("hexagon-vlcr", HexagonVectorLoopCarriedReusePass()) +#undef LOOP_PASS diff --git a/llvm/lib/Target/Hexagon/HexagonStoreWidening.cpp b/llvm/lib/Target/Hexagon/HexagonStoreWidening.cpp index a647e699a8f07a46d4415d7f7e18fd4a1218d2e6..9d8e5c53b8227a81af0d237a25d81e272e0db7d6 100644 --- a/llvm/lib/Target/Hexagon/HexagonStoreWidening.cpp +++ b/llvm/lib/Target/Hexagon/HexagonStoreWidening.cpp @@ -292,8 +292,8 @@ bool HexagonStoreWidening::storesAreAdjacent(const MachineInstr *S1, int Off1 = S1->getOperand(1).getImm(); int Off2 = S2->getOperand(1).getImm(); - return (Off1 >= 0) ? Off1+S1MO.getSize() == unsigned(Off2) - : int(Off1+S1MO.getSize()) == Off2; + return (Off1 >= 0) ? Off1 + S1MO.getSize().getValue() == unsigned(Off2) + : int(Off1 + S1MO.getSize().getValue()) == Off2; } /// Given a sequence of adjacent stores, and a maximum size of a single wide @@ -315,7 +315,7 @@ bool HexagonStoreWidening::selectStores(InstrGroup::iterator Begin, assert(!FirstMI->memoperands_empty() && "Expecting some memory operands"); const MachineMemOperand &FirstMMO = getStoreTarget(FirstMI); unsigned Alignment = FirstMMO.getAlign().value(); - unsigned SizeAccum = FirstMMO.getSize(); + unsigned SizeAccum = FirstMMO.getSize().getValue(); unsigned FirstOffset = getStoreOffset(FirstMI); // The initial value of SizeAccum should always be a power of 2. @@ -357,7 +357,7 @@ bool HexagonStoreWidening::selectStores(InstrGroup::iterator Begin, if (!storesAreAdjacent(S1, S2)) break; - unsigned S2Size = getStoreTarget(S2).getSize(); + unsigned S2Size = getStoreTarget(S2).getSize().getValue(); if (SizeAccum + S2Size > std::min(MaxSize, Alignment)) break; @@ -405,7 +405,7 @@ bool HexagonStoreWidening::createWideStores(InstrGroup &OG, InstrGroup &NG, MachineOperand &SO = MI->getOperand(2); // Source. assert(SO.isImm() && "Expecting an immediate operand"); - unsigned NBits = MMO.getSize()*8; + unsigned NBits = MMO.getSize().getValue() * 8; unsigned Mask = (0xFFFFFFFFU >> (32-NBits)); unsigned Val = (SO.getImm() & Mask) << Shift; Acc |= Val; diff --git a/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp b/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp index 3c346c334d6d30a3a92cbd7f8700df09ac5fed1a..e64d7e52a9aa9b172eae670f78376f3f208bb69b 100644 --- a/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp +++ b/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp @@ -299,6 +299,9 @@ HexagonTargetMachine::getSubtargetImpl(const Function &F) const { void HexagonTargetMachine::registerPassBuilderCallbacks( PassBuilder &PB, bool PopulateClassToPassNames) { +#define GET_PASS_REGISTRY "HexagonPassRegistry.def" +#include "llvm/Passes/TargetPassRegistry.inc" + PB.registerLateLoopOptimizationsEPCallback( [=](LoopPassManager &LPM, OptimizationLevel Level) { LPM.addPass(HexagonLoopIdiomRecognitionPass()); diff --git a/llvm/lib/Target/Hexagon/HexagonTargetStreamer.h b/llvm/lib/Target/Hexagon/HexagonTargetStreamer.h index ff84363106629f5bedd767e436737029488f4d84..a2f93d476bfe1bee89d2bb657547aeface198a8f 100644 --- a/llvm/lib/Target/Hexagon/HexagonTargetStreamer.h +++ b/llvm/lib/Target/Hexagon/HexagonTargetStreamer.h @@ -24,6 +24,15 @@ public: virtual void emitLocalCommonSymbolSorted(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlign, unsigned AccessGranularity){}; + void finish() override {} + + virtual void finishAttributeSection() {} + + virtual void emitAttribute(unsigned Attribute, unsigned Value) {} + + void emitTargetAttributes(const MCSubtargetInfo &STI); + + virtual void reset() {} }; } diff --git a/llvm/lib/Target/Hexagon/HexagonTargetTransformInfo.cpp b/llvm/lib/Target/Hexagon/HexagonTargetTransformInfo.cpp index cf4b66f8bf8619baa40f249f03ee8e66b4ff3990..458b8717256f24051bf83e0d2e4a09d3d17d752a 100644 --- a/llvm/lib/Target/Hexagon/HexagonTargetTransformInfo.cpp +++ b/llvm/lib/Target/Hexagon/HexagonTargetTransformInfo.cpp @@ -138,20 +138,6 @@ ElementCount HexagonTTIImpl::getMinimumVF(unsigned ElemWidth, return ElementCount::getFixed((8 * ST.getVectorLength()) / ElemWidth); } -InstructionCost HexagonTTIImpl::getScalarizationOverhead( - VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract, - TTI::TargetCostKind CostKind) { - return BaseT::getScalarizationOverhead(Ty, DemandedElts, Insert, Extract, - CostKind); -} - -InstructionCost -HexagonTTIImpl::getOperandsScalarizationOverhead(ArrayRef<const Value *> Args, - ArrayRef<Type *> Tys, - TTI::TargetCostKind CostKind) { - return BaseT::getOperandsScalarizationOverhead(Args, Tys, CostKind); -} - InstructionCost HexagonTTIImpl::getCallInstrCost(Function *F, Type *RetTy, ArrayRef<Type *> Tys, TTI::TargetCostKind CostKind) { diff --git a/llvm/lib/Target/Hexagon/HexagonTargetTransformInfo.h b/llvm/lib/Target/Hexagon/HexagonTargetTransformInfo.h index ec0fd454c80847643611be775d04df6b2101514a..fdb34f308e641e1c3e1fa31a46a151cb780410b1 100644 --- a/llvm/lib/Target/Hexagon/HexagonTargetTransformInfo.h +++ b/llvm/lib/Target/Hexagon/HexagonTargetTransformInfo.h @@ -103,14 +103,6 @@ public: return true; } - InstructionCost getScalarizationOverhead(VectorType *Ty, - const APInt &DemandedElts, - bool Insert, bool Extract, - TTI::TargetCostKind CostKind); - InstructionCost - getOperandsScalarizationOverhead(ArrayRef<const Value *> Args, - ArrayRef<Type *> Tys, - TTI::TargetCostKind CostKind); InstructionCost getCallInstrCost(Function *F, Type *RetTy, ArrayRef<Type *> Tys, TTI::TargetCostKind CostKind); diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp index d1678fa0241ca891df01c523cba64d4f9226ae23..22c82bf5ac1b40eac3aa9dc298dedb5c619b082b 100644 --- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp +++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCELFStreamer.cpp @@ -12,6 +12,8 @@ //===----------------------------------------------------------------------===// #include "MCTargetDesc/HexagonMCELFStreamer.h" +#include "HexagonTargetStreamer.h" +#include "MCTargetDesc/HexagonMCChecker.h" #include "MCTargetDesc/HexagonMCInstrInfo.h" #include "MCTargetDesc/HexagonMCShuffler.h" #include "llvm/ADT/StringRef.h" @@ -27,11 +29,13 @@ #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbolELF.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/HexagonAttributes.h" #include "llvm/Support/MathExtras.h" #include <cassert> #include <cstdint> @@ -147,6 +151,63 @@ void HexagonMCELFStreamer::HexagonMCEmitLocalCommonSymbol(MCSymbol *Symbol, HexagonMCEmitCommonSymbol(Symbol, Size, ByteAlignment, AccessSize); } +static unsigned featureToArchVersion(unsigned Feature) { + switch (Feature) { + case Hexagon::ArchV5: + return 5; + case Hexagon::ArchV55: + return 55; + case Hexagon::ArchV60: + case Hexagon::ExtensionHVXV60: + return 60; + case Hexagon::ArchV62: + case Hexagon::ExtensionHVXV62: + return 62; + case Hexagon::ArchV65: + case Hexagon::ExtensionHVXV65: + return 65; + case Hexagon::ArchV66: + case Hexagon::ExtensionHVXV66: + return 66; + case Hexagon::ArchV67: + case Hexagon::ExtensionHVXV67: + return 67; + case Hexagon::ArchV68: + case Hexagon::ExtensionHVXV68: + return 68; + case Hexagon::ArchV69: + case Hexagon::ExtensionHVXV69: + return 69; + case Hexagon::ArchV71: + case Hexagon::ExtensionHVXV71: + return 71; + case Hexagon::ArchV73: + case Hexagon::ExtensionHVXV73: + return 73; + } + llvm_unreachable("Expected valid arch feature"); + return 0; +} + +void HexagonTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI) { + auto Features = STI.getFeatureBits(); + unsigned Arch = featureToArchVersion(Hexagon_MC::getArchVersion(Features)); + std::optional<unsigned> HVXArch = Hexagon_MC::getHVXVersion(Features); + emitAttribute(HexagonAttrs::ARCH, Arch); + if (HVXArch) + emitAttribute(HexagonAttrs::HVXARCH, featureToArchVersion(*HVXArch)); + if (Features.test(Hexagon::ExtensionHVXIEEEFP)) + emitAttribute(HexagonAttrs::HVXIEEEFP, 1); + if (Features.test(Hexagon::ExtensionHVXQFloat)) + emitAttribute(HexagonAttrs::HVXQFLOAT, 1); + if (Features.test(Hexagon::ExtensionZReg)) + emitAttribute(HexagonAttrs::ZREG, 1); + if (Features.test(Hexagon::ExtensionAudio)) + emitAttribute(HexagonAttrs::AUDIO, 1); + if (Features.test(Hexagon::FeatureCabac)) + emitAttribute(HexagonAttrs::CABAC, 1); +} + namespace llvm { MCStreamer *createHexagonELFStreamer(Triple const &TT, MCContext &Context, std::unique_ptr<MCAsmBackend> MAB, diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp index 0740ac58a33813425006ef8ca2f50dca8ef63054..dc8328a6705da8ea5a9701e00c0c3f128aa61b4e 100644 --- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp +++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp @@ -35,6 +35,7 @@ #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/HexagonAttributes.h" #include "llvm/Support/raw_ostream.h" #include <cassert> #include <cstdint> @@ -224,12 +225,13 @@ bool isSlot0Only(unsigned units) { namespace { class HexagonTargetAsmStreamer : public HexagonTargetStreamer { + formatted_raw_ostream &OS; + bool IsVerboseAsm; + public: - HexagonTargetAsmStreamer(MCStreamer &S, - formatted_raw_ostream &OS, - bool isVerboseAsm, - MCInstPrinter &IP) - : HexagonTargetStreamer(S) {} + HexagonTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS, + bool IsVerboseAsm, MCInstPrinter &IP) + : HexagonTargetStreamer(S), OS(OS), IsVerboseAsm(IsVerboseAsm) {} void prettyPrintAsm(MCInstPrinter &InstPrinter, uint64_t Address, const MCInst &Inst, const MCSubtargetInfo &STI, @@ -266,6 +268,21 @@ public: else OS << "\t}" << PacketBundle.second; } + + void finish() override { finishAttributeSection(); } + + void finishAttributeSection() override {} + + void emitAttribute(unsigned Attribute, unsigned Value) override { + OS << "\t.attribute\t" << Attribute << ", " << Twine(Value); + if (IsVerboseAsm) { + StringRef Name = ELFAttrs::attrTypeAsString( + Attribute, HexagonAttrs::getHexagonAttributeTags()); + if (!Name.empty()) + OS << "\t// " << Name; + } + OS << "\n"; + } }; class HexagonTargetELFStreamer : public HexagonTargetStreamer { @@ -279,7 +296,6 @@ public: MCA.setELFHeaderEFlags(Hexagon_MC::GetELFFlags(STI)); } - void emitCommonSymbolSorted(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment, unsigned AccessSize) override { @@ -297,6 +313,27 @@ public: HexagonELFStreamer.HexagonMCEmitLocalCommonSymbol( Symbol, Size, Align(ByteAlignment), AccessSize); } + + void finish() override { finishAttributeSection(); } + + void reset() override { AttributeSection = nullptr; } + +private: + MCSection *AttributeSection = nullptr; + + void finishAttributeSection() override { + MCELFStreamer &S = getStreamer(); + if (S.Contents.empty()) + return; + + S.emitAttributesSection("hexagon", ".hexagon.attributes", + ELF::SHT_HEXAGON_ATTRIBUTES, AttributeSection); + } + + void emitAttribute(uint32_t Attribute, uint32_t Value) override { + getStreamer().setAttributeItem(Attribute, Value, + /*OverwriteExisting=*/true); + } }; } // end anonymous namespace @@ -591,6 +628,29 @@ void Hexagon_MC::addArchSubtarget(MCSubtargetInfo const *STI, StringRef FS) { } } +std::optional<unsigned> +Hexagon_MC::getHVXVersion(const FeatureBitset &Features) { + for (auto Arch : {Hexagon::ExtensionHVXV73, Hexagon::ExtensionHVXV71, + Hexagon::ExtensionHVXV69, Hexagon::ExtensionHVXV68, + Hexagon::ExtensionHVXV67, Hexagon::ExtensionHVXV66, + Hexagon::ExtensionHVXV65, Hexagon::ExtensionHVXV62, + Hexagon::ExtensionHVXV60}) + if (Features.test(Arch)) + return Arch; + return {}; +} + +unsigned Hexagon_MC::getArchVersion(const FeatureBitset &Features) { + for (auto Arch : + {Hexagon::ArchV73, Hexagon::ArchV71, Hexagon::ArchV69, Hexagon::ArchV68, + Hexagon::ArchV67, Hexagon::ArchV66, Hexagon::ArchV65, Hexagon::ArchV62, + Hexagon::ArchV60, Hexagon::ArchV55, Hexagon::ArchV5}) + if (Features.test(Arch)) + return Arch; + llvm_unreachable("Expected arch v5-v73"); + return 0; +} + unsigned Hexagon_MC::GetELFFlags(const MCSubtargetInfo &STI) { return StringSwitch<unsigned>(STI.getCPU()) .Case("generic", llvm::ELF::EF_HEXAGON_MACH_V5) diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h index ffb81bca208df1c557ea8c1413f93e32426b12fa..6110c7a93982ca655041235cd5d78db9ac3c6311 100644 --- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h +++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.h @@ -81,7 +81,11 @@ namespace Hexagon_MC { unsigned GetELFFlags(const MCSubtargetInfo &STI); llvm::ArrayRef<MCPhysReg> GetVectRegRev(); -} + + std::optional<unsigned> getHVXVersion(const FeatureBitset &Features); + + unsigned getArchVersion(const FeatureBitset &Features); + } // namespace Hexagon_MC MCCodeEmitter *createHexagonMCCodeEmitter(const MCInstrInfo &MCII, MCContext &MCT); diff --git a/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp b/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp index ff3649b77e351eedf9abcd37f84b1a4dddc6088f..6ab1375b974ec6257b0bbd3eaa7bab2d407e5cc3 100644 --- a/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp +++ b/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp @@ -151,7 +151,7 @@ public: // getEndLoc - Gets location of the last token of this operand SMLoc getEndLoc() const override { return EndLoc; } - unsigned getReg() const override { + MCRegister getReg() const override { assert(isReg() && "Invalid type access!"); return Reg.RegNum; } diff --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp index 46f63a4103f9f9afc5d8e4ba96767bdf472784b1..20284b18428bd8d1caf59329a87136d4a925b333 100644 --- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp +++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp @@ -453,15 +453,23 @@ public: } bool isImm32() const { return isSImm<32>() || isUImm<32>(); } + bool isImm64() const { + if (!isImm()) + return false; + int64_t Imm; + LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None; + bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); + return IsConstantImm && VK == LoongArchMCExpr::VK_LoongArch_None; + } /// Gets location of the first token of this operand. SMLoc getStartLoc() const override { return StartLoc; } /// Gets location of the last token of this operand. SMLoc getEndLoc() const override { return EndLoc; } - unsigned getReg() const override { + MCRegister getReg() const override { assert(Kind == KindTy::Register && "Invalid type access!"); - return Reg.RegNum.id(); + return Reg.RegNum; } const MCExpr *getImm() const { @@ -1514,6 +1522,10 @@ bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); return Error(ErrorLoc, "operand must be a 32 bit immediate"); } + case Match_InvalidImm64: { + SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); + return Error(ErrorLoc, "operand must be a 64 bit immediate"); + } case Match_InvalidBareSymbol: { SMLoc ErrorLoc = ((LoongArchOperand &)*Operands[ErrorInfo]).getStartLoc(); return Error(ErrorLoc, "operand must be a bare symbol name"); diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index c87f5341d7fea93ef6bbe1636039ec72d959c462..c13b10a320f83636f242cfa13b83e70767cb51cc 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -968,28 +968,6 @@ static SDValue checkIntrinsicImmArg(SDValue Op, unsigned ImmOp, return SDValue(); } -static SDValue checkAndModifyXVPERMI_QIntrinsicImmArg(SDValue Op, - SelectionDAG &DAG) { - SDValue Op3 = Op->getOperand(3); - uint64_t Imm = Op3->getAsZExtVal(); - // Check the range of ImmArg. - if (!isUInt<8>(Imm)) { - DAG.getContext()->emitError(Op->getOperationName(0) + - ": argument out of range."); - return DAG.getNode(ISD::UNDEF, SDLoc(Op), Op.getValueType()); - } - - // For instruction xvpermi.q, only [1:0] and [5:4] bits of operands[3] - // are used. The unused bits in operands[3] need to be set to 0 to avoid - // causing undefined behavior on LA464. - if ((Imm & 0x33) != Imm) { - Op3 = DAG.getTargetConstant(Imm & 0x33, SDLoc(Op), Op3.getValueType()); - DAG.UpdateNodeOperands(Op.getNode(), Op->getOperand(0), Op->getOperand(1), - Op->getOperand(2), Op3); - } - return SDValue(); -} - SDValue LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const { @@ -1247,14 +1225,13 @@ LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, case Intrinsic::loongarch_lsx_vextrins_d: case Intrinsic::loongarch_lasx_xvshuf4i_d: case Intrinsic::loongarch_lasx_xvpermi_w: + case Intrinsic::loongarch_lasx_xvpermi_q: case Intrinsic::loongarch_lasx_xvbitseli_b: case Intrinsic::loongarch_lasx_xvextrins_b: case Intrinsic::loongarch_lasx_xvextrins_h: case Intrinsic::loongarch_lasx_xvextrins_w: case Intrinsic::loongarch_lasx_xvextrins_d: return checkIntrinsicImmArg<8>(Op, 3, DAG); - case Intrinsic::loongarch_lasx_xvpermi_q: - return checkAndModifyXVPERMI_QIntrinsicImmArg(Op, DAG); case Intrinsic::loongarch_lsx_vrepli_b: case Intrinsic::loongarch_lsx_vrepli_h: case Intrinsic::loongarch_lsx_vrepli_w: diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td index fcfff08d1a9f54c49c9ff0885b0a8186974a5dbf..80429bc45be14c168bf610af3bb445adb0531a20 100644 --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td @@ -219,6 +219,9 @@ def grlenimm : Operand<GRLenVT>; def imm32 : Operand<GRLenVT> { let ParserMatchClass = ImmAsmOperand<"", 32, "">; } +def imm64 : Operand<i64> { + let ParserMatchClass = ImmAsmOperand<"", 64, "">; +} def uimm1 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<1>(Imm);}]>{ let ParserMatchClass = UImmAsmOperand<1>; @@ -2179,7 +2182,7 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0, isAsmParserOnly = 1 in { def PseudoLI_W : Pseudo<(outs GPR:$rd), (ins imm32:$imm), [], "li.w", "$rd, $imm">; -def PseudoLI_D : Pseudo<(outs GPR:$rd), (ins grlenimm:$imm), [], +def PseudoLI_D : Pseudo<(outs GPR:$rd), (ins imm64:$imm), [], "li.d", "$rd, $imm">, Requires<[IsLA64]>; } diff --git a/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp b/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp index b2c0fda1ccc24a791aa48d620d4cdb78e8364f64..126176133dc02741e7bd90d1c755a6bc3cc8d7ca 100644 --- a/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp +++ b/llvm/lib/Target/M68k/AsmParser/M68kAsmParser.cpp @@ -157,7 +157,7 @@ public: bool isDReg() const; bool isFPDReg() const; bool isFPCReg() const; - unsigned getReg() const override; + MCRegister getReg() const override; void addRegOperands(MCInst &Inst, unsigned N) const; static std::unique_ptr<M68kOperand> createMemOp(M68kMemOp MemOp, SMLoc Start, @@ -312,7 +312,7 @@ bool M68kOperand::isReg() const { return Kind == KindTy::MemOp && MemOp.Op == M68kMemOp::Kind::Reg; } -unsigned M68kOperand::getReg() const { +MCRegister M68kOperand::getReg() const { assert(isReg()); return MemOp.OuterReg; } diff --git a/llvm/lib/Target/M68k/M68kISelLowering.cpp b/llvm/lib/Target/M68k/M68kISelLowering.cpp index 158393f02a24709fd0e191cd4f0d6ea5a5acce39..786aa7bcb64ea0d4440ba425e277a3f54a8bfb1a 100644 --- a/llvm/lib/Target/M68k/M68kISelLowering.cpp +++ b/llvm/lib/Target/M68k/M68kISelLowering.cpp @@ -939,6 +939,7 @@ SDValue M68kTargetLowering::LowerFormalArguments( for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; assert(VA.getValNo() != LastVal && "Same value in different locations"); + (void)LastVal; LastVal = VA.getValNo(); diff --git a/llvm/lib/Target/M68k/M68kInstrInfo.td b/llvm/lib/Target/M68k/M68kInstrInfo.td index 84eb8e56da760bb1a7be1388325fe1bf12714111..3a9e4fe77f1ccf4cc457927d7d115361605b6161 100644 --- a/llvm/lib/Target/M68k/M68kInstrInfo.td +++ b/llvm/lib/Target/M68k/M68kInstrInfo.td @@ -200,32 +200,35 @@ class MxRegOp<ValueType vt, // REGISTER DIRECT. The operand is in the data register specified by // the effective address register field. -def MxXRD16 : MxRegOp<i16, XR16, MxSize16, "r">; -def MxXRD32 : MxRegOp<i32, XR32, MxSize32, "r">; - -def MxXRD16_TC : MxRegOp<i16, XR16_TC, MxSize16, "r">; -def MxXRD32_TC : MxRegOp<i32, XR32_TC, MxSize32, "r">; +foreach size = [16, 32] in { + def MxXRD # size : MxRegOp<!cast<ValueType>("i"#size), !cast<MxRegClass>("XR"#size), + !cast<MxSize>("MxSize"#size), "r">; + def MxXRD # size # _TC : MxRegOp<!cast<ValueType>("i"#size), !cast<MxRegClass>("XR"#size#"_TC"), + !cast<MxSize>("MxSize"#size), "r">; +} // foreach size // DATA REGISTER DIRECT. The operand is in the data register specified by // the effective address register field. let ParserMatchClass = MxDRegClass in { - def MxDRD8 : MxRegOp<i8, DR8, MxSize8, "d">; - def MxDRD16 : MxRegOp<i16, DR16, MxSize16, "d">; - def MxDRD32 : MxRegOp<i32, DR32, MxSize32, "d">; - - def MxDRD16_TC : MxRegOp<i16, DR16_TC, MxSize16, "d">; - def MxDRD32_TC : MxRegOp<i32, DR32_TC, MxSize32, "d">; -} +foreach size = [8, 16, 32] in { + def MxDRD # size : MxRegOp<!cast<ValueType>("i"#size), !cast<MxRegClass>("DR"#size), + !cast<MxSize>("MxSize"#size), "d">; + if !gt(size, 8) then + def MxDRD # size # _TC : MxRegOp<!cast<ValueType>("i"#size), !cast<MxRegClass>("DR"#size#"_TC"), + !cast<MxSize>("MxSize"#size), "d">; +} // foreach size +} // let ParserMatchClass // ADDRESS REGISTER DIRECT. The operand is in the address register specified by // the effective address register field. let ParserMatchClass = MxARegClass in { - def MxARD16 : MxRegOp<i16, AR16, MxSize16, "a">; - def MxARD32 : MxRegOp<i32, AR32, MxSize32, "a">; - - def MxARD16_TC : MxRegOp<i16, AR16_TC, MxSize16, "a">; - def MxARD32_TC : MxRegOp<i32, AR32_TC, MxSize32, "a">; -} +foreach size = [16, 32] in { + def MxARD # size : MxRegOp<!cast<ValueType>("i"#size), !cast<MxRegClass>("AR"#size), + !cast<MxSize>("MxSize"#size), "a">; + def MxARD # size # _TC : MxRegOp<!cast<ValueType>("i"#size), !cast<MxRegClass>("AR"#size#"_TC"), + !cast<MxSize>("MxSize"#size), "a">; +} // foreach size +} // let ParserMatchClass // FLOATING POINT DATA REGISTER. let ParserMatchClass = MxFPDRegClass in { @@ -255,13 +258,11 @@ class MxMemOp<dag ops, MxSize size, string letter, // a data reference with the exception of the jump and jump-to-subroutine // instructions. def MxARI : MxOpClass<"ARI">; -def MxARI8 : MxMemOp<(ops AR32), MxSize8, "j", "printARI8Mem", MxARI>; -def MxARI16 : MxMemOp<(ops AR32), MxSize16, "j", "printARI16Mem", MxARI>; -def MxARI32 : MxMemOp<(ops AR32), MxSize32, "j", "printARI32Mem", MxARI>; - -def MxARI8_TC : MxMemOp<(ops AR32_TC), MxSize8, "j", "printARI8Mem", MxARI>; -def MxARI16_TC : MxMemOp<(ops AR32_TC), MxSize16, "j", "printARI16Mem", MxARI>; -def MxARI32_TC : MxMemOp<(ops AR32_TC), MxSize32, "j", "printARI32Mem", MxARI>; +foreach size = ["8", "16", "32"] in { + defvar ResSize = !cast<MxSize>("MxSize"#size); + def MxARI # size : MxMemOp<(ops AR32), ResSize, "j", "printARI"#size#"Mem", MxARI>; + def MxARI # size # _TC : MxMemOp<(ops AR32_TC), ResSize, "j", "printARI"#size#"Mem", MxARI>; +} // foreach size // ADDRESS REGISTER INDIRECT WITH POSTINCREMENT. The address of the operand is // in the address register specified by the register field. After the operand @@ -271,13 +272,11 @@ def MxARI32_TC : MxMemOp<(ops AR32_TC), MxSize32, "j", "printARI32Mem", MxARI // by two rather than one to keep the stack pointer on a word boundary. // The reference is classified as a data reference. def MxARIPI : MxOpClass<"ARIPI">; -def MxARIPI8 : MxMemOp<(ops AR32), MxSize8, "o", "printARIPI8Mem", MxARIPI>; -def MxARIPI16 : MxMemOp<(ops AR32), MxSize16, "o", "printARIPI16Mem", MxARIPI>; -def MxARIPI32 : MxMemOp<(ops AR32), MxSize32, "o", "printARIPI32Mem", MxARIPI>; - -def MxARIPI8_TC : MxMemOp<(ops AR32_TC), MxSize8, "o", "printARIPI8Mem", MxARIPI>; -def MxARIPI16_TC : MxMemOp<(ops AR32_TC), MxSize16, "o", "printARIPI16Mem", MxARIPI>; -def MxARIPI32_TC : MxMemOp<(ops AR32_TC), MxSize32, "o", "printARIPI32Mem", MxARIPI>; +foreach size = ["8", "16", "32"] in { + defvar ResSize = !cast<MxSize>("MxSize"#size); + def MxARIPI # size : MxMemOp<(ops AR32), ResSize, "o", "printARIPI"#size#"Mem", MxARIPI>; + def MxARIPI # size # _TC : MxMemOp<(ops AR32_TC), ResSize, "o", "printARIPI"#size#"Mem", MxARIPI>; +} // foreach size // ADDRESS REGISTER INDIRECT WITH PREDECREMENT. The address of the operand is in // the address register specified by the register field. Before the operand @@ -287,13 +286,11 @@ def MxARIPI32_TC : MxMemOp<(ops AR32_TC), MxSize32, "o", "printARIPI32Mem", MxA // two rather than one to keep the stack pointer on a word boundary. // The reference is classified as a data reference. def MxARIPD : MxOpClass<"ARIPD">; -def MxARIPD8 : MxMemOp<(ops AR32), MxSize8, "e", "printARIPD8Mem", MxARIPD>; -def MxARIPD16 : MxMemOp<(ops AR32), MxSize16, "e", "printARIPD16Mem", MxARIPD>; -def MxARIPD32 : MxMemOp<(ops AR32), MxSize32, "e", "printARIPD32Mem", MxARIPD>; - -def MxARIPD8_TC : MxMemOp<(ops AR32_TC), MxSize8, "e", "printARIPD8Mem", MxARIPD>; -def MxARIPD16_TC : MxMemOp<(ops AR32_TC), MxSize16, "e", "printARIPD16Mem", MxARIPD>; -def MxARIPD32_TC : MxMemOp<(ops AR32_TC), MxSize32, "e", "printARIPD32Mem", MxARIPD>; +foreach size = ["8", "16", "32"] in { + defvar ResSize = !cast<MxSize>("MxSize"#size); + def MxARIPD # size : MxMemOp<(ops AR32), ResSize, "e", "printARIPD"#size#"Mem", MxARIPD>; + def MxARIPD # size # _TC : MxMemOp<(ops AR32_TC), ResSize, "e", "printARIPD"#size#"Mem", MxARIPD>; +} // foreach size // ADDRESS REGISTER INDIRECT WITH DISPLACEMENT. This addressing mode requires one // word of extension. The address of the operand is the sum of the address in @@ -301,13 +298,11 @@ def MxARIPD32_TC : MxMemOp<(ops AR32_TC), MxSize32, "e", "printARIPD32Mem", MxA // extension word. The reference is classified as a data reference with the // exception of the jump and jump-to-subroutine instructions. def MxARID : MxOpClass<"ARID">; -def MxARID8 : MxMemOp<(ops i16imm:$disp, AR32:$reg), MxSize8, "p", "printARID8Mem", MxARID>; -def MxARID16 : MxMemOp<(ops i16imm:$disp, AR32:$reg), MxSize16, "p", "printARID16Mem", MxARID>; -def MxARID32 : MxMemOp<(ops i16imm:$disp, AR32:$reg), MxSize32, "p", "printARID32Mem", MxARID>; - -def MxARID8_TC : MxMemOp<(ops i16imm:$disp, AR32_TC:$reg), MxSize8, "p", "printARID8Mem", MxARID>; -def MxARID16_TC : MxMemOp<(ops i16imm:$disp, AR32_TC:$reg), MxSize16, "p", "printARID16Mem", MxARID>; -def MxARID32_TC : MxMemOp<(ops i16imm:$disp, AR32_TC:$reg), MxSize32, "p", "printARID32Mem", MxARID>; +foreach size = ["8", "16", "32"] in { + defvar ResSize = !cast<MxSize>("MxSize"#size); + def MxARID # size : MxMemOp<(ops i16imm:$disp, AR32:$reg), ResSize, "p", "printARID"#size#"Mem", MxARID>; + def MxARID # size # _TC : MxMemOp<(ops i16imm:$disp, AR32_TC:$reg), ResSize, "p", "printARID"#size#"Mem", MxARID>; +} // foreach size // ADDRESS REGISTER INDIRECT WITH INDEX. This addressing mode requires one word // of extension. The address of the operand is the sum of the address in the @@ -316,19 +311,11 @@ def MxARID32_TC : MxMemOp<(ops i16imm:$disp, AR32_TC:$reg), MxSize32, "p", "pr // The reference is classified as a data reference with the exception of the // jump and jump-to-subroutine instructions def MxARII : MxOpClass<"ARII">; -def MxARII8 : MxMemOp<(ops i8imm:$disp, AR32:$reg, XR32:$index), - MxSize8, "f", "printARII8Mem", MxARII>; -def MxARII16 : MxMemOp<(ops i8imm:$disp, AR32:$reg, XR32:$index), - MxSize16, "f", "printARII16Mem", MxARII>; -def MxARII32 : MxMemOp<(ops i8imm:$disp, AR32:$reg, XR32:$index), - MxSize32, "f", "printARII32Mem", MxARII>; - -def MxARII8_TC : MxMemOp<(ops i8imm:$disp, AR32_TC:$reg, XR32_TC:$index), - MxSize8, "f", "printARII8Mem", MxARII>; -def MxARII16_TC : MxMemOp<(ops i8imm:$disp, AR32_TC:$reg, XR32_TC:$index), - MxSize16, "f", "printARII16Mem", MxARII>; -def MxARII32_TC : MxMemOp<(ops i8imm:$disp, AR32_TC:$reg, XR32_TC:$index), - MxSize32, "f", "printARII32Mem", MxARII>; +foreach size = ["8", "16", "32"] in { + defvar ResSize = !cast<MxSize>("MxSize"#size); + def MxARII # size : MxMemOp<(ops i8imm:$disp, AR32:$reg, XR32:$index), ResSize, "f", "printARII"#size#"Mem", MxARII>; + def MxARII # size # _TC : MxMemOp<(ops i8imm:$disp, AR32_TC:$reg, XR32:$index), ResSize, "f", "printARII"#size#"Mem", MxARII>; +} // foreach size // ABSOLUTE SHORT ADDRESS. This addressing mode requires one word of extension. // The address of the operand is the extension word. The 16-bit address is sign @@ -361,14 +348,14 @@ def MxPCD : MxOpClass<"PCD">; def MxPCI : MxOpClass<"PCI">; let OperandType = "OPERAND_PCREL" in { +foreach size = ["8", "16", "32"] in { +defvar ResSize = !cast<MxSize>("MxSize"#size); // PROGRAM COUNTER WITH DISPLACEMENT. This addressing mode requires one word of // extension. The address of the operand is the sum of the address in the program // counter and the Sign-extended 16-bit displacement integer in the extension // word. The value in the program counter is the address of the extension word. // The reference is classified as a program reference. -def MxPCD8 : MxMemOp<(ops i16imm), MxSize8, "q", "printPCD8Mem", MxPCD>; -def MxPCD16 : MxMemOp<(ops i16imm), MxSize16, "q", "printPCD16Mem", MxPCD>; -def MxPCD32 : MxMemOp<(ops i16imm), MxSize32, "q", "printPCD32Mem", MxPCD>; +def MxPCD # size : MxMemOp<(ops i16imm), ResSize, "q", "printPCD"#size#"Mem", MxPCD>; // PROGRAM COUNTER WITH INDEX. This addressing mode requires one word of // extension. The address is the sum of the address in the program counter, the @@ -376,9 +363,8 @@ def MxPCD32 : MxMemOp<(ops i16imm), MxSize32, "q", "printPCD32Mem", MxPCD>; // word, and the contents of the index register. The value in the program // counter is the address of the extension word. This reference is classified as // a program reference. -def MxPCI8 : MxMemOp<(ops i8imm:$disp, XR32:$index), MxSize8, "k", "printPCI8Mem", MxPCI>; -def MxPCI16 : MxMemOp<(ops i8imm:$disp, XR32:$index), MxSize16, "k", "printPCI16Mem", MxPCI>; -def MxPCI32 : MxMemOp<(ops i8imm:$disp, XR32:$index), MxSize32, "k", "printPCI32Mem", MxPCI>; +def MxPCI # size : MxMemOp<(ops i8imm:$disp, XR32:$index), ResSize, "k", "printPCI"#size#"Mem", MxPCI>; +} // foreach size } // OPERAND_PCREL def MxImm : AsmOperandClass { diff --git a/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp b/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp index 818a468612a57edd24a9b9bf5ebba2656d177ff5..2bc1a89ef59cf0c41b5bbd9b098493e5253e9ae9 100644 --- a/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp +++ b/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp @@ -183,7 +183,7 @@ public: return Tok; } - unsigned getReg() const override { + MCRegister getReg() const override { assert(Kind == k_Reg && "Invalid access!"); return Reg; } diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 9d6e8dc573a8d1ed270aa56e556c6e33d6fe92b0..076e0a20cb97e95ec39920afb34f696773010f3c 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1458,7 +1458,7 @@ public: return StringRef(Tok.Data, Tok.Length); } - unsigned getReg() const override { + MCRegister getReg() const override { // As a special case until we sort out the definition of div/divu, accept // $0/$zero here so that MCK_ZERO works correctly. if (Kind == k_RegisterIndex && RegIdx.Index == 0 && diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index 181b82f14bfe8664e2421643a8bc25b6a29aef4f..4d6a00c14a3575ca3cd2a1ffbd37a853ed6d691b 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -498,10 +498,9 @@ void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm, assert(Relocs.size() == Sorted.size() && "Some relocs were not consumed"); - // Overwrite the original vector with the sorted elements. The caller expects - // them in reverse order. + // Overwrite the original vector with the sorted elements. unsigned CopyTo = 0; - for (const auto &R : reverse(Sorted)) + for (const auto &R : Sorted) Relocs[CopyTo++] = R.R; } diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index adfcea7361583153b167cb94a9718fe91c11238a..bdf299ae8ac11244fcbcea3b0b2cda7e13e4285b 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -1255,28 +1255,6 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, emitRRI(Mips::SD, GPReg, Mips::SP, RegOrOffset, SMLoc(), &STI); } -#if 0 - // We haven't support -mabicalls -mno-shared yet. - if (-mno-shared) { - MCSymbol *GPSym = MCA.getContext().getOrCreateSymbol("__gnu_local_gp"); - const MipsMCExpr *HiExpr = MipsMCExpr::create( - MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(GPSym, MCA.getContext()), - MCA.getContext()); - const MipsMCExpr *LoExpr = MipsMCExpr::create( - MipsMCExpr::MEK_LO, MCSymbolRefExpr::create(GPSym, MCA.getContext()), - MCA.getContext()); - - // lui $gp, %hi(__gnu_local_gp) - emitRX(Mips::LUi, GPReg, MCOperand::createExpr(HiExpr), SMLoc(), &STI); - - // addiu $gp, $gp, %lo(__gnu_local_gp) - emitRRX(Mips::ADDiu, GPReg, GPReg, MCOperand::createExpr(LoExpr), SMLoc(), - &STI); - - return; - } -#endif - const MipsMCExpr *HiExpr = MipsMCExpr::createGpOff( MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(&Sym, MCA.getContext()), MCA.getContext()); diff --git a/llvm/lib/Target/Mips/Mips.td b/llvm/lib/Target/Mips/Mips.td index dbff25dfa0f36c581a0d268bb9c2708ea26629ae..923e0c9cdde758b9a603dc4b39af2ebc1b4e6884 100644 --- a/llvm/lib/Target/Mips/Mips.td +++ b/llvm/lib/Target/Mips/Mips.td @@ -208,6 +208,10 @@ def FeatureUseIndirectJumpsHazard : SubtargetFeature<"use-indirect-jump-hazard", "true", "Use indirect jump" " guards to prevent certain speculation based attacks">; +def FeatureStrictAlign + : SubtargetFeature<"strict-align", "StrictAlign", "true", + "Disable unaligned load store for r6">; + //===----------------------------------------------------------------------===// // Register File, Calling Conv, Instruction Descriptions //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/Mips/Mips16HardFloat.cpp b/llvm/lib/Target/Mips/Mips16HardFloat.cpp index 5c96044b1f0b850642083019e3c831c5de0b4e75..f7b623785b70c24287287ad693cf03c0222927bf 100644 --- a/llvm/lib/Target/Mips/Mips16HardFloat.cpp +++ b/llvm/lib/Target/Mips/Mips16HardFloat.cpp @@ -414,7 +414,7 @@ static bool fixupFPReturnAndCall(Function &F, Module *M, C, Attribute::getWithMemoryEffects(C, MemoryEffects::none())); A = A.addFnAttribute(C, Attribute::NoInline); FunctionCallee F = (M->getOrInsertFunction(Name, A, MyVoid, T)); - CallInst::Create(F, Params, "", &I); + CallInst::Create(F, Params, "", I.getIterator()); } else if (const CallInst *CI = dyn_cast<CallInst>(&I)) { FunctionType *FT = CI->getFunctionType(); Function *F_ = CI->getCalledFunction(); diff --git a/llvm/lib/Target/Mips/MipsExpandPseudo.cpp b/llvm/lib/Target/Mips/MipsExpandPseudo.cpp index bded59439a736a6ef6fc523866bb48038b829388..c30129743a9626c385f055ce1c6cb12f98be31cc 100644 --- a/llvm/lib/Target/Mips/MipsExpandPseudo.cpp +++ b/llvm/lib/Target/Mips/MipsExpandPseudo.cpp @@ -500,6 +500,15 @@ bool MipsExpandPseudo::expandAtomicBinOpSubword( .addReg(Incr, RegState::Kill) .addImm(ShiftImm); } + } else { + // and OldVal, OldVal, Mask + // and Incr, Incr, Mask + BuildMI(loopMBB, DL, TII->get(Mips::AND), OldVal) + .addReg(OldVal) + .addReg(Mask); + BuildMI(loopMBB, DL, TII->get(Mips::AND), Incr) + .addReg(Incr) + .addReg(Mask); } } // unsigned: sltu Scratch4, oldVal, Incr diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index 7e5f148e7bf4e7992f207fed12a8864bd82ff290..7bc66b2d9f4b1bf6393d95c136154cc197afc36e 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -365,8 +365,13 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::JumpTable, MVT::i64, Custom); setOperationAction(ISD::ConstantPool, MVT::i64, Custom); setOperationAction(ISD::SELECT, MVT::i64, Custom); - setOperationAction(ISD::LOAD, MVT::i64, Custom); - setOperationAction(ISD::STORE, MVT::i64, Custom); + if (Subtarget.hasMips64r6()) { + setOperationAction(ISD::LOAD, MVT::i64, Legal); + setOperationAction(ISD::STORE, MVT::i64, Legal); + } else { + setOperationAction(ISD::LOAD, MVT::i64, Custom); + setOperationAction(ISD::STORE, MVT::i64, Custom); + } setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); setOperationAction(ISD::SHL_PARTS, MVT::i64, Custom); setOperationAction(ISD::SRA_PARTS, MVT::i64, Custom); @@ -481,7 +486,12 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, if (!Subtarget.hasMips64r2()) setOperationAction(ISD::BSWAP, MVT::i64, Expand); - if (Subtarget.isGP64bit()) { + if (Subtarget.isGP64bit() && Subtarget.hasMips64r6()) { + setLoadExtAction(ISD::SEXTLOAD, MVT::i64, MVT::i32, Legal); + setLoadExtAction(ISD::ZEXTLOAD, MVT::i64, MVT::i32, Legal); + setLoadExtAction(ISD::EXTLOAD, MVT::i64, MVT::i32, Legal); + setTruncStoreAction(MVT::i64, MVT::i32, Legal); + } else if (Subtarget.isGP64bit()) { setLoadExtAction(ISD::SEXTLOAD, MVT::i64, MVT::i32, Custom); setLoadExtAction(ISD::ZEXTLOAD, MVT::i64, MVT::i32, Custom); setLoadExtAction(ISD::EXTLOAD, MVT::i64, MVT::i32, Custom); @@ -3371,8 +3381,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // Collect CSInfo about which register passes which parameter. const TargetOptions &Options = DAG.getTarget().Options; - if (Options.SupportsDebugEntryValues) - CSInfo.emplace_back(VA.getLocReg(), i); + if (Options.EmitCallSiteInfo) + CSInfo.ArgRegPairs.emplace_back(VA.getLocReg(), i); continue; } diff --git a/llvm/lib/Target/Mips/MipsInstructionSelector.cpp b/llvm/lib/Target/Mips/MipsInstructionSelector.cpp index 654f29d08af0b5cd38a4f2985996ef461578b3e9..4e1e27088cce42de2af7eb5d56ec981a2dece1be 100644 --- a/llvm/lib/Target/Mips/MipsInstructionSelector.cpp +++ b/llvm/lib/Target/Mips/MipsInstructionSelector.cpp @@ -184,7 +184,8 @@ MipsInstructionSelector::selectLoadStoreOpCode(MachineInstr &I, const Register ValueReg = I.getOperand(0).getReg(); const LLT Ty = MRI.getType(ValueReg); const unsigned TySize = Ty.getSizeInBits(); - const unsigned MemSizeInBytes = (*I.memoperands_begin())->getSize(); + const unsigned MemSizeInBytes = + (*I.memoperands_begin())->getSize().getValue(); unsigned Opc = I.getOpcode(); const bool isStore = Opc == TargetOpcode::G_STORE; @@ -455,7 +456,8 @@ bool MipsInstructionSelector::select(MachineInstr &I) { } // Unaligned memory access - if (MMO->getAlign() < MMO->getSize() && + if ((!MMO->getSize().hasValue() || + MMO->getAlign() < MMO->getSize().getValue()) && !STI.systemSupportsUnalignedAccess()) { if (MMO->getSize() != 4 || !isRegInGprb(I.getOperand(0).getReg(), MRI)) return false; diff --git a/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp b/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp index f5e94235859a06ad88ac5a192df2d24f07ffd577..8468dd6a22119f9033d99958226fb59e433b7c47 100644 --- a/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp +++ b/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp @@ -344,7 +344,7 @@ bool MipsLegalizerInfo::legalizeCustom( switch (MI.getOpcode()) { case G_LOAD: case G_STORE: { - unsigned MemSize = (**MI.memoperands_begin()).getSize(); + unsigned MemSize = (**MI.memoperands_begin()).getSize().getValue(); Register Val = MI.getOperand(0).getReg(); unsigned Size = MRI.getType(Val).getSizeInBits(); @@ -508,16 +508,8 @@ bool MipsLegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const { MachineIRBuilder &MIRBuilder = Helper.MIRBuilder; const MipsSubtarget &ST = MI.getMF()->getSubtarget<MipsSubtarget>(); - const MipsInstrInfo &TII = *ST.getInstrInfo(); - const MipsRegisterInfo &TRI = *ST.getRegisterInfo(); - const RegisterBankInfo &RBI = *ST.getRegBankInfo(); switch (cast<GIntrinsic>(MI).getIntrinsicID()) { - case Intrinsic::trap: { - MachineInstr *Trap = MIRBuilder.buildInstr(Mips::TRAP); - MI.eraseFromParent(); - return constrainSelectedInstRegOperands(*Trap, TII, TRI, RBI); - } case Intrinsic::vacopy: { MachinePointerInfo MPO; LLT PtrTy = LLT::pointer(0, 32); diff --git a/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp b/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp index acf0d6312ef51b93a21ecd35e741238108d2bf29..639e623954ffc64d7e42c1cc7e312597718cca3c 100644 --- a/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp +++ b/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp @@ -70,9 +70,10 @@ public: // subtarget doesn't support them. auto MMO = *MI.memoperands_begin(); const MipsSubtarget &STI = MI.getMF()->getSubtarget<MipsSubtarget>(); - if (!isPowerOf2_64(MMO->getSize())) + if (!MMO->getSize().hasValue() || + !isPowerOf2_64(MMO->getSize().getValue())) return false; - bool isUnaligned = MMO->getAlign() < MMO->getSize(); + bool isUnaligned = MMO->getAlign() < MMO->getSize().getValue(); if (!STI.systemSupportsUnalignedAccess() && isUnaligned) return false; diff --git a/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp b/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp index db7afc3c86c57e9d92c1f9c0593f773ee109440b..6af1fd8c88e5702218ce434840b4d6db57f9ba68 100644 --- a/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp +++ b/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp @@ -155,7 +155,8 @@ static bool isGprbTwoInstrUnalignedLoadOrStore(const MachineInstr *MI) { auto MMO = *MI->memoperands_begin(); const MipsSubtarget &STI = MI->getMF()->getSubtarget<MipsSubtarget>(); if (MMO->getSize() == 4 && (!STI.systemSupportsUnalignedAccess() && - MMO->getAlign() < MMO->getSize())) + (!MMO->getSize().hasValue() || + MMO->getAlign() < MMO->getSize().getValue()))) return true; } return false; diff --git a/llvm/lib/Target/Mips/MipsSEISelLowering.cpp b/llvm/lib/Target/Mips/MipsSEISelLowering.cpp index b87d13cea787dd2d6cfaf1f280cff3eb4525b086..5c8d64e3b6e3cc92d3d662ee83bc573e0c02cd66 100644 --- a/llvm/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsSEISelLowering.cpp @@ -197,8 +197,13 @@ MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::SDIVREM, MVT::i32, Custom); setOperationAction(ISD::UDIVREM, MVT::i32, Custom); setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); - setOperationAction(ISD::LOAD, MVT::i32, Custom); - setOperationAction(ISD::STORE, MVT::i32, Custom); + if (Subtarget.hasMips32r6()) { + setOperationAction(ISD::LOAD, MVT::i32, Legal); + setOperationAction(ISD::STORE, MVT::i32, Legal); + } else { + setOperationAction(ISD::LOAD, MVT::i32, Custom); + setOperationAction(ISD::STORE, MVT::i32, Custom); + } setTargetDAGCombine(ISD::MUL); @@ -425,6 +430,8 @@ bool MipsSETargetLowering::allowsMisalignedMemoryAccesses( if (Fast) *Fast = 1; return true; + } else if (Subtarget.hasMips32r6()) { + return false; } switch (SVT) { diff --git a/llvm/lib/Target/Mips/MipsSubtarget.cpp b/llvm/lib/Target/Mips/MipsSubtarget.cpp index 0134fcb341f187f3b8f3555aa60adc16060cc889..1bd35ca4a41914c3f03c4c53a965658043f4d383 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.cpp +++ b/llvm/lib/Target/Mips/MipsSubtarget.cpp @@ -82,7 +82,7 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS, HasDSPR2(false), HasDSPR3(false), AllowMixed16_32(Mixed16_32 || Mips_Os16), Os16(Mips_Os16), HasMSA(false), UseTCCInDIV(false), HasSym32(false), HasEVA(false), DisableMadd4(false), HasMT(false), HasCRC(false), - HasVirt(false), HasGINV(false), UseIndirectJumpsHazard(false), + HasVirt(false), HasGINV(false), UseIndirectJumpsHazard(false), StrictAlign(false), StackAlignOverride(StackAlignOverride), TM(TM), TargetTriple(TT), TSInfo(), InstrInfo(MipsInstrInfo::create( initializeSubtargetDependencies(CPU, FS, TM))), diff --git a/llvm/lib/Target/Mips/MipsSubtarget.h b/llvm/lib/Target/Mips/MipsSubtarget.h index 225ee139d036f3d92e412042b1ac36a4f5efcdec..fea7f11fd07054f0cbea49678ee4be7fd4e7802e 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.h +++ b/llvm/lib/Target/Mips/MipsSubtarget.h @@ -200,6 +200,9 @@ class MipsSubtarget : public MipsGenSubtargetInfo { // Assume 32-bit GOT. bool UseXGOT = false; + // Disable unaligned load store for r6. + bool StrictAlign; + /// The minimum alignment known to hold of the stack frame on /// entry to the function and which must be maintained by every function. Align stackAlignment; @@ -372,7 +375,9 @@ public: /// MIPS32r6/MIPS64r6 require full unaligned access support but does not /// specify which component of the system provides it. Hardware, software, and /// hybrid implementations are all valid. - bool systemSupportsUnalignedAccess() const { return hasMips32r6(); } + bool systemSupportsUnalignedAccess() const { + return hasMips32r6() && !StrictAlign; + } // Set helper classes void setHelperClassesMips16(); diff --git a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp index 2219d9f6619aaf006c75cc8ecb71107af77f067c..9f31b72bbceb1f9159613cfa34fa8951ce4e03e2 100644 --- a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp @@ -489,8 +489,11 @@ void NVPTXAsmPrinter::emitFunctionEntryLabel() { OutStreamer->emitRawText(StringRef("{\n")); setAndEmitFunctionVirtualRegisters(*MF); // Emit initial .loc debug directive for correct relocation symbol data. - if (MMI && MMI->hasDebugInfo()) - emitInitialRawDwarfLocDirective(*MF); + if (const DISubprogram *SP = MF->getFunction().getSubprogram()) { + assert(SP->getUnit()); + if (!SP->getUnit()->isDebugDirectivesOnly() && MMI && MMI->hasDebugInfo()) + emitInitialRawDwarfLocDirective(*MF); + } } bool NVPTXAsmPrinter::runOnMachineFunction(MachineFunction &F) { @@ -1019,7 +1022,6 @@ void NVPTXAsmPrinter::printModuleLevelGV(const GlobalVariable *GVar, const DataLayout &DL = getDataLayout(); // GlobalVariables are always constant pointers themselves. - PointerType *PTy = GVar->getType(); Type *ETy = GVar->getValueType(); if (GVar->hasExternalLinkage()) { @@ -1027,6 +1029,9 @@ void NVPTXAsmPrinter::printModuleLevelGV(const GlobalVariable *GVar, O << ".visible "; else O << ".extern "; + } else if (STI.getPTXVersion() >= 50 && GVar->hasCommonLinkage() && + GVar->getAddressSpace() == ADDRESS_SPACE_GLOBAL) { + O << ".common "; } else if (GVar->hasLinkOnceLinkage() || GVar->hasWeakLinkage() || GVar->hasAvailableExternallyLinkage() || GVar->hasCommonLinkage()) { @@ -1138,7 +1143,7 @@ void NVPTXAsmPrinter::printModuleLevelGV(const GlobalVariable *GVar, } O << "."; - emitPTXAddressSpace(PTy->getAddressSpace(), O); + emitPTXAddressSpace(GVar->getAddressSpace(), O); if (isManaged(*GVar)) { if (STI.getPTXVersion() < 40 || STI.getSmVersion() < 30) { @@ -1167,8 +1172,8 @@ void NVPTXAsmPrinter::printModuleLevelGV(const GlobalVariable *GVar, // Ptx allows variable initilization only for constant and global state // spaces. if (GVar->hasInitializer()) { - if ((PTy->getAddressSpace() == ADDRESS_SPACE_GLOBAL) || - (PTy->getAddressSpace() == ADDRESS_SPACE_CONST)) { + if ((GVar->getAddressSpace() == ADDRESS_SPACE_GLOBAL) || + (GVar->getAddressSpace() == ADDRESS_SPACE_CONST)) { const Constant *Initializer = GVar->getInitializer(); // 'undef' is treated as there is no value specified. if (!Initializer->isNullValue() && !isa<UndefValue>(Initializer)) { @@ -1183,7 +1188,7 @@ void NVPTXAsmPrinter::printModuleLevelGV(const GlobalVariable *GVar, !isa<UndefValue>(GVar->getInitializer())) { report_fatal_error("initial value of '" + GVar->getName() + "' is not allowed in addrspace(" + - Twine(PTy->getAddressSpace()) + ")"); + Twine(GVar->getAddressSpace()) + ")"); } } } @@ -1202,8 +1207,8 @@ void NVPTXAsmPrinter::printModuleLevelGV(const GlobalVariable *GVar, ElementSize = DL.getTypeStoreSize(ETy); // Ptx allows variable initilization only for constant and // global state spaces. - if (((PTy->getAddressSpace() == ADDRESS_SPACE_GLOBAL) || - (PTy->getAddressSpace() == ADDRESS_SPACE_CONST)) && + if (((GVar->getAddressSpace() == ADDRESS_SPACE_GLOBAL) || + (GVar->getAddressSpace() == ADDRESS_SPACE_CONST)) && GVar->hasInitializer()) { const Constant *Initializer = GVar->getInitializer(); if (!isa<UndefValue>(Initializer) && !Initializer->isNullValue()) { @@ -1716,7 +1721,7 @@ void NVPTXAsmPrinter::setAndEmitFunctionVirtualRegisters( // Emit the Fake Stack Object const MachineFrameInfo &MFI = MF.getFrameInfo(); - int NumBytes = (int) MFI.getStackSize(); + int64_t NumBytes = MFI.getStackSize(); if (NumBytes) { O << "\t.local .align " << MFI.getMaxAlign().value() << " .b8 \t" << DEPOTNAME << getFunctionNumber() << "[" << NumBytes << "];\n"; diff --git a/llvm/lib/Target/NVPTX/NVPTXFrameLowering.cpp b/llvm/lib/Target/NVPTX/NVPTXFrameLowering.cpp index 86fb367780dc1a0824594edf99b9071e6409b400..c34472c21ccbe945c21312979ad0b6e569c48249 100644 --- a/llvm/lib/Target/NVPTX/NVPTXFrameLowering.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXFrameLowering.cpp @@ -60,10 +60,12 @@ void NVPTXFrameLowering::emitPrologue(MachineFunction &MF, NRI->getFrameRegister(MF)) .addReg(NRI->getFrameLocalRegister(MF)); } - BuildMI(MBB, MBBI, dl, - MF.getSubtarget().getInstrInfo()->get(MovDepotOpcode), - NRI->getFrameLocalRegister(MF)) - .addImm(MF.getFunctionNumber()); + if (!MR.use_empty(NRI->getFrameLocalRegister(MF))) { + BuildMI(MBB, MBBI, dl, + MF.getSubtarget().getInstrInfo()->get(MovDepotOpcode), + NRI->getFrameLocalRegister(MF)) + .addImm(MF.getFunctionNumber()); + } } } diff --git a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp index c979c03dc1b8359d56968a0ff5612744360b6c55..e1cdbd6a4b4dc6defbddf625175edd4c643fdd56 100644 --- a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp @@ -580,9 +580,6 @@ NVPTXTargetLowering::NVPTXTargetLowering(const NVPTXTargetMachine &TM, setOperationAction(ISD::ROTL, MVT::i8, Expand); setOperationAction(ISD::ROTR, MVT::i8, Expand); setOperationAction(ISD::BSWAP, MVT::i16, Expand); - setOperationAction(ISD::BSWAP, MVT::v2i16, Expand); - setOperationAction(ISD::BSWAP, MVT::i32, Expand); - setOperationAction(ISD::BSWAP, MVT::i64, Expand); // Indirect branch is not supported. // This also disables Jump Table creation. @@ -645,8 +642,6 @@ NVPTXTargetLowering::NVPTXTargetLowering(const NVPTXTargetMachine &TM, setOperationAction(ISD::ConstantFP, MVT::f16, Legal); setOperationAction(ISD::ConstantFP, MVT::bf16, Legal); - // Lowering of DYNAMIC_STACKALLOC is unsupported. - // Custom lower to produce an error. setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom); setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Custom); @@ -937,6 +932,7 @@ const char *NVPTXTargetLowering::getTargetNodeName(unsigned Opcode) const { MAKE_CASE(NVPTXISD::BFE) MAKE_CASE(NVPTXISD::BFI) MAKE_CASE(NVPTXISD::PRMT) + MAKE_CASE(NVPTXISD::DYNAMIC_STACKALLOC) MAKE_CASE(NVPTXISD::SETP_F16X2) MAKE_CASE(NVPTXISD::SETP_BF16X2) MAKE_CASE(NVPTXISD::Dummy) @@ -2211,14 +2207,39 @@ SDValue NVPTXTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, SDValue NVPTXTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const { - const Function &Fn = DAG.getMachineFunction().getFunction(); - - DiagnosticInfoUnsupported NoDynamicAlloca( - Fn, "dynamic alloca unsupported by NVPTX backend", - SDLoc(Op).getDebugLoc()); - DAG.getContext()->diagnose(NoDynamicAlloca); - auto Ops = {DAG.getConstant(0, SDLoc(), Op.getValueType()), Op.getOperand(0)}; - return DAG.getMergeValues(Ops, SDLoc()); + + if (STI.getPTXVersion() < 73 || STI.getSmVersion() < 52) { + const Function &Fn = DAG.getMachineFunction().getFunction(); + + DiagnosticInfoUnsupported NoDynamicAlloca( + Fn, + "Support for dynamic alloca introduced in PTX ISA version 7.3 and " + "requires target sm_52.", + SDLoc(Op).getDebugLoc()); + DAG.getContext()->diagnose(NoDynamicAlloca); + auto Ops = {DAG.getConstant(0, SDLoc(), Op.getValueType()), + Op.getOperand(0)}; + return DAG.getMergeValues(Ops, SDLoc()); + } + + SDValue Chain = Op.getOperand(0); + SDValue Size = Op.getOperand(1); + uint64_t Align = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue(); + SDLoc DL(Op.getNode()); + + // The size for ptx alloca instruction is 64-bit for m64 and 32-bit for m32. + if (nvTM->is64Bit()) + Size = DAG.getZExtOrTrunc(Size, DL, MVT::i64); + else + Size = DAG.getZExtOrTrunc(Size, DL, MVT::i32); + + SDValue AllocOps[] = {Chain, Size, + DAG.getTargetConstant(Align, DL, MVT::i32)}; + SDValue Alloca = DAG.getNode(NVPTXISD::DYNAMIC_STACKALLOC, DL, + nvTM->is64Bit() ? MVT::i64 : MVT::i32, AllocOps); + + SDValue MergeOps[] = {Alloca, Chain}; + return DAG.getMergeValues(MergeOps, DL); } // By default CONCAT_VECTORS is lowered by ExpandVectorBuildThroughStack() @@ -6100,6 +6121,9 @@ NVPTXTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const { if (AI->isFloatingPointOperation()) { if (AI->getOperation() == AtomicRMWInst::BinOp::FAdd) { + if (Ty->isHalfTy() && STI.getSmVersion() >= 70 && + STI.getPTXVersion() >= 63) + return AtomicExpansionKind::None; if (Ty->isFloatTy()) return AtomicExpansionKind::None; if (Ty->isDoubleTy() && STI.hasAtomAddF64()) diff --git a/llvm/lib/Target/NVPTX/NVPTXISelLowering.h b/llvm/lib/Target/NVPTX/NVPTXISelLowering.h index cf1d4580766918eb9c617bcc9dd9192ed697ac1b..c9db10e555cefe653f3dca12c4e15bcb7b7571b3 100644 --- a/llvm/lib/Target/NVPTX/NVPTXISelLowering.h +++ b/llvm/lib/Target/NVPTX/NVPTXISelLowering.h @@ -61,6 +61,7 @@ enum NodeType : unsigned { BFE, BFI, PRMT, + DYNAMIC_STACKALLOC, Dummy, LoadV2 = ISD::FIRST_TARGET_MEMORY_OPCODE, diff --git a/llvm/lib/Target/NVPTX/NVPTXImageOptimizer.cpp b/llvm/lib/Target/NVPTX/NVPTXImageOptimizer.cpp index 202134ed7035aaf0b5aebb690ceb3bbbc6d396a9..c3fce14df06884755c71e583e70a133116e0174b 100644 --- a/llvm/lib/Target/NVPTX/NVPTXImageOptimizer.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXImageOptimizer.cpp @@ -157,7 +157,7 @@ void NVPTXImageOptimizer::replaceWith(Instruction *From, ConstantInt *To) { else // Get true block Dest = BI->getSuccessor(0); - BranchInst::Create(Dest, BI); + BranchInst::Create(Dest, BI->getIterator()); InstrToDelete.push_back(BI); } } diff --git a/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td b/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td index 3dc5b450cbf5cfe1bd157fb07adff6f5c1aeeb0d..4daf47cfd4df8a9ce14bcfaf3e7d67f15dabb94a 100644 --- a/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td +++ b/llvm/lib/Target/NVPTX/NVPTXInstrInfo.td @@ -3549,6 +3549,11 @@ let hasSideEffects = false in { (ins Int64Regs:$s), "{{ .reg .b32 tmp; mov.b64 {tmp, $high}, $s; }}", []>; + def I64toI32L : NVPTXInst<(outs Int32Regs:$low), + (ins Int64Regs:$s), + "{{ .reg .b32 tmp; mov.b64 {$low, tmp}, $s; }}", + []>; + } // Using partial vectorized move produces better SASS code for extraction of @@ -3805,6 +3810,28 @@ def CALL_PROTOTYPE : NVPTXInst<(outs), (ins ProtoIdent:$ident), "$ident", [(CallPrototype (i32 texternalsym:$ident))]>; +def SDTDynAllocaOp : + SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>, SDTCisInt<1>, SDTCisInt<2>]>; + +def dyn_alloca : + SDNode<"NVPTXISD::DYNAMIC_STACKALLOC", SDTDynAllocaOp, + [SDNPHasChain, SDNPSideEffect]>; + +def DYNAMIC_STACKALLOC32 : + NVPTXInst<(outs Int32Regs:$ptr), + (ins Int32Regs:$size, i32imm:$align), + "alloca.u32 \t$ptr, $size, $align;\n\t" + "cvta.local.u32 \t$ptr, $ptr;", + [(set (i32 Int32Regs:$ptr), (dyn_alloca Int32Regs:$size, (i32 timm:$align)))]>, + Requires<[hasPTX<73>, hasSM<52>]>; + +def DYNAMIC_STACKALLOC64 : + NVPTXInst<(outs Int64Regs:$ptr), + (ins Int64Regs:$size, i32imm:$align), + "alloca.u64 \t$ptr, $size, $align;\n\t" + "cvta.local.u64 \t$ptr, $ptr;", + [(set Int64Regs:$ptr, (dyn_alloca Int64Regs:$size, (i32 timm:$align)))]>, + Requires<[hasPTX<73>, hasSM<52>]>; include "NVPTXIntrinsics.td" @@ -3816,3 +3843,17 @@ include "NVPTXIntrinsics.td" // - for sm_20, use pmpt (use vector scalar mov to get the pack and // unpack). sm_20 supports native 32-bit register, but not native 16-bit // register. + +def : Pat < + (i32 (bswap i32:$a)), + (INT_NVVM_PRMT Int32Regs:$a, (i32 0), (i32 0x0123))>; + +def : Pat < + (v2i16 (bswap v2i16:$a)), + (INT_NVVM_PRMT Int32Regs:$a, (i32 0), (i32 0x2301))>; + +def : Pat < + (i64 (bswap i64:$a)), + (V2I32toI64 + (INT_NVVM_PRMT (I64toI32H Int64Regs:$a), (i32 0), (i32 0x0123)), + (INT_NVVM_PRMT (I64toI32L Int64Regs:$a), (i32 0), (i32 0x0123)))>; diff --git a/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td b/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td index 477789a164ead2304b415d6c0aee33a4279fc402..c0c53380a13e9b469fa2f327119d5289d0c5d269 100644 --- a/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td +++ b/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td @@ -1520,7 +1520,7 @@ multiclass F_ATOMIC_2_imp<ValueType ptrT, NVPTXRegClass ptrclass, def imm : NVPTXInst<(outs regclass:$dst), (ins ptrclass:$addr, IMMType:$b), !strconcat("atom", SpaceStr, OpcStr, TypeStr, " \t$dst, [$addr], $b;", ""), [(set (regT regclass:$dst), (IntOp (ptrT ptrclass:$addr), IMM:$b))]>, - Requires<Pred>; + Requires<!if(!eq(TypeStr, ".f16"), [Predicate<"false">], Pred)>; } multiclass F_ATOMIC_2<ValueType regT, NVPTXRegClass regclass, string SpaceStr, string TypeStr, string OpcStr, PatFrag IntOp, Operand IMMType, SDNode IMM, @@ -1630,6 +1630,13 @@ defm INT_PTX_ATOM_ADD_GEN_64 : F_ATOMIC_2<i64, Int64Regs, "", ".u64", ".add", defm INT_PTX_ATOM_ADD_GEN_64_USE_G : F_ATOMIC_2<i64, Int64Regs, ".global", ".u64", ".add", atomic_load_add_64_gen, i64imm, imm>; +defm INT_PTX_ATOM_ADD_G_F16 : F_ATOMIC_2<f16, Int16Regs, ".global", ".f16", ".add.noftz", + atomic_load_add_g, f16imm, fpimm, [hasSM<70>, hasPTX<63>]>; +defm INT_PTX_ATOM_ADD_S_F16 : F_ATOMIC_2<f16, Int16Regs, ".shared", ".f16", ".add.noftz", + atomic_load_add_s, f16imm, fpimm, [hasSM<70>, hasPTX<63>]>; +defm INT_PTX_ATOM_ADD_GEN_F16 : F_ATOMIC_2<f16, Int16Regs, "", ".f16", ".add.noftz", + atomic_load_add_gen, f16imm, fpimm, [hasSM<70>, hasPTX<63>]>; + defm INT_PTX_ATOM_ADD_G_F32 : F_ATOMIC_2<f32, Float32Regs, ".global", ".f32", ".add", atomic_load_add_g, f32imm, fpimm>; defm INT_PTX_ATOM_ADD_S_F32 : F_ATOMIC_2<f32, Float32Regs, ".shared", ".f32", ".add", @@ -2007,6 +2014,9 @@ multiclass ATOM2P_impl<string AsmStr, Intrinsic Intr, SDNode Imm, ValueType ImmTy, list<Predicate> Preds> { let AddedComplexity = 1 in { + def : ATOM23_impl<AsmStr, regT, regclass, Preds, + (ins Int16Regs:$src, regclass:$b), + (Intr (i16 Int16Regs:$src), (regT regclass:$b))>; def : ATOM23_impl<AsmStr, regT, regclass, Preds, (ins Int32Regs:$src, regclass:$b), (Intr (i32 Int32Regs:$src), (regT regclass:$b))>; @@ -2017,6 +2027,9 @@ multiclass ATOM2P_impl<string AsmStr, Intrinsic Intr, // tablegen can't infer argument types from Intrinsic (though it can // from Instruction) so we have to enforce specific type on // immediates via explicit cast to ImmTy. + def : ATOM23_impl<AsmStr, regT, regclass, Preds, + (ins Int16Regs:$src, ImmType:$b), + (Intr (i16 Int16Regs:$src), (ImmTy Imm:$b))>; def : ATOM23_impl<AsmStr, regT, regclass, Preds, (ins Int32Regs:$src, ImmType:$b), (Intr (i32 Int32Regs:$src), (ImmTy Imm:$b))>; @@ -2136,6 +2149,8 @@ multiclass ATOM2_add_impl<string OpStr> { defm _s32 : ATOM2S_impl<OpStr, "i", "s32", i32, Int32Regs, i32imm, imm, i32, []>; defm _u32 : ATOM2S_impl<OpStr, "i", "u32", i32, Int32Regs, i32imm, imm, i32, []>; defm _u64 : ATOM2S_impl<OpStr, "i", "u64", i64, Int64Regs, i64imm, imm, i64, []>; + defm _f16 : ATOM2S_impl<OpStr, "f", "f16", f16, Int16Regs, f16imm, fpimm, f16, + [hasSM<70>, hasPTX<63>]>; defm _f32 : ATOM2S_impl<OpStr, "f", "f32", f32, Float32Regs, f32imm, fpimm, f32, []>; defm _f64 : ATOM2S_impl<OpStr, "f", "f64", f64, Float64Regs, f64imm, fpimm, f64, diff --git a/llvm/lib/Target/NVPTX/NVPTXLowerArgs.cpp b/llvm/lib/Target/NVPTX/NVPTXLowerArgs.cpp index 9e06f4689304ba3bd604ae477619f2a865eb31c5..cde02c25c4834263a040795d5b4c385c2e8ebe36 100644 --- a/llvm/lib/Target/NVPTX/NVPTXLowerArgs.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXLowerArgs.cpp @@ -183,16 +183,16 @@ static void convertToParamAS(Value *OldUser, Value *Param) { } if (auto *GEP = dyn_cast<GetElementPtrInst>(I.OldInstruction)) { SmallVector<Value *, 4> Indices(GEP->indices()); - auto *NewGEP = GetElementPtrInst::Create(GEP->getSourceElementType(), - I.NewParam, Indices, - GEP->getName(), GEP); + auto *NewGEP = GetElementPtrInst::Create( + GEP->getSourceElementType(), I.NewParam, Indices, GEP->getName(), + GEP->getIterator()); NewGEP->setIsInBounds(GEP->isInBounds()); return NewGEP; } if (auto *BC = dyn_cast<BitCastInst>(I.OldInstruction)) { auto *NewBCType = PointerType::get(BC->getContext(), ADDRESS_SPACE_PARAM); return BitCastInst::Create(BC->getOpcode(), I.NewParam, NewBCType, - BC->getName(), BC); + BC->getName(), BC->getIterator()); } if (auto *ASC = dyn_cast<AddrSpaceCastInst>(I.OldInstruction)) { assert(ASC->getDestAddressSpace() == ADDRESS_SPACE_PARAM); @@ -316,7 +316,7 @@ static void adjustByValArgAlignment(Argument *Arg, Value *ArgInParamAS, void NVPTXLowerArgs::handleByValParam(const NVPTXTargetMachine &TM, Argument *Arg) { Function *Func = Arg->getParent(); - Instruction *FirstInst = &(Func->getEntryBlock().front()); + BasicBlock::iterator FirstInst = Func->getEntryBlock().begin(); Type *StructType = Arg->getParamByValType(); assert(StructType && "Missing byval type"); @@ -407,9 +407,9 @@ void NVPTXLowerArgs::markPointerAsGlobal(Value *Ptr) { Instruction *PtrInGlobal = new AddrSpaceCastInst( Ptr, PointerType::get(Ptr->getContext(), ADDRESS_SPACE_GLOBAL), - Ptr->getName(), &*InsertPt); + Ptr->getName(), InsertPt); Value *PtrInGeneric = new AddrSpaceCastInst(PtrInGlobal, Ptr->getType(), - Ptr->getName(), &*InsertPt); + Ptr->getName(), InsertPt); // Replace with PtrInGeneric all uses of Ptr except PtrInGlobal. Ptr->replaceAllUsesWith(PtrInGeneric); PtrInGlobal->setOperand(0, Ptr); diff --git a/llvm/lib/Target/NVPTX/NVPTXLowerUnreachable.cpp b/llvm/lib/Target/NVPTX/NVPTXLowerUnreachable.cpp index 34f06b548db260d517d95b107e68866ff5b5a8df..92b90e2559154e7780a4cb40df37ec382a963579 100644 --- a/llvm/lib/Target/NVPTX/NVPTXLowerUnreachable.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXLowerUnreachable.cpp @@ -143,7 +143,7 @@ bool NVPTXLowerUnreachable::runOnFunction(Function &F) { if (auto unreachableInst = dyn_cast<UnreachableInst>(&I)) { if (isLoweredToTrap(*unreachableInst)) continue; // trap is emitted as `trap; exit;`. - CallInst::Create(ExitFTy, Exit, "", unreachableInst); + CallInst::Create(ExitFTy, Exit, "", unreachableInst->getIterator()); Changed = true; } } diff --git a/llvm/lib/Target/NVPTX/NVPTXPassRegistry.def b/llvm/lib/Target/NVPTX/NVPTXPassRegistry.def new file mode 100644 index 0000000000000000000000000000000000000000..6ff15ab6f13c44f0b701a54cf849a37da097a4d3 --- /dev/null +++ b/llvm/lib/Target/NVPTX/NVPTXPassRegistry.def @@ -0,0 +1,40 @@ +//===- NVPTXPassRegistry.def - Registry of NVPTX passes ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is used as the registry of passes that are part of the +// NVPTX backend. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +#ifndef MODULE_PASS +#define MODULE_PASS(NAME, CREATE_PASS) +#endif +MODULE_PASS("generic-to-nvvm", GenericToNVVMPass()) +MODULE_PASS("nvptx-lower-ctor-dtor", NVPTXCtorDtorLoweringPass()) +#undef MODULE_PASS + +#ifndef FUNCTION_ANALYSIS +#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) +#endif + +#ifndef FUNCTION_ALIAS_ANALYSIS +#define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) \ + FUNCTION_ANALYSIS(NAME, CREATE_PASS) +#endif +FUNCTION_ALIAS_ANALYSIS("nvptx-aa", NVPTXAA()) +#undef FUNCTION_ALIAS_ANALYSIS +#undef FUNCTION_ANALYSIS + +#ifndef FUNCTION_PASS +#define FUNCTION_PASS(NAME, CREATE_PASS) +#endif +FUNCTION_PASS("nvvm-intr-range", NVVMIntrRangePass()) +FUNCTION_PASS("nvvm-reflect", NVVMReflectPass()) +#undef FUNCTION_PASS diff --git a/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp b/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp index 69d4596f7843e4a0a5dc1d312c8dbe3d96c4f8ab..78f48652c9920fa754dcfe88f1c60d1a26fcf513 100644 --- a/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXTargetMachine.cpp @@ -227,45 +227,8 @@ void NVPTXTargetMachine::registerDefaultAliasAnalyses(AAManager &AAM) { void NVPTXTargetMachine::registerPassBuilderCallbacks( PassBuilder &PB, bool PopulateClassToPassNames) { - PB.registerPipelineParsingCallback( - [](StringRef PassName, FunctionPassManager &PM, - ArrayRef<PassBuilder::PipelineElement>) { - if (PassName == "nvvm-reflect") { - PM.addPass(NVVMReflectPass()); - return true; - } - if (PassName == "nvvm-intr-range") { - PM.addPass(NVVMIntrRangePass()); - return true; - } - return false; - }); - - PB.registerAnalysisRegistrationCallback([](FunctionAnalysisManager &FAM) { - FAM.registerPass([&] { return NVPTXAA(); }); - }); - - PB.registerParseAACallback([](StringRef AAName, AAManager &AAM) { - if (AAName == "nvptx-aa") { - AAM.registerFunctionAnalysis<NVPTXAA>(); - return true; - } - return false; - }); - - PB.registerPipelineParsingCallback( - [](StringRef PassName, ModulePassManager &PM, - ArrayRef<PassBuilder::PipelineElement>) { - if (PassName == "nvptx-lower-ctor-dtor") { - PM.addPass(NVPTXCtorDtorLoweringPass()); - return true; - } - if (PassName == "generic-to-nvvm") { - PM.addPass(GenericToNVVMPass()); - return true; - } - return false; - }); +#define GET_PASS_REGISTRY "NVPTXPassRegistry.def" +#include "llvm/Passes/TargetPassRegistry.inc" PB.registerPipelineStartEPCallback( [this](ModulePassManager &PM, OptimizationLevel Level) { diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index 8108cfa521c8075801594b69c0026069e6be1b83..55978af38000dee579335eb8b2fc0cc04d43cf1e 100644 --- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -276,9 +276,11 @@ public: return TLSReg.Sym; } - unsigned getReg() const override { + MCRegister getReg() const override { llvm_unreachable("Not implemented"); } + + unsigned getRegNum() const { assert(isRegNumber() && "Invalid access!"); - return (unsigned) Imm.Val; + return (unsigned)Imm.Val; } unsigned getFpReg() const { @@ -459,22 +461,22 @@ public: void addRegGPRCOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(RRegs[getReg()])); + Inst.addOperand(MCOperand::createReg(RRegs[getRegNum()])); } void addRegGPRCNoR0Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(RRegsNoR0[getReg()])); + Inst.addOperand(MCOperand::createReg(RRegsNoR0[getRegNum()])); } void addRegG8RCOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(XRegs[getReg()])); + Inst.addOperand(MCOperand::createReg(XRegs[getRegNum()])); } void addRegG8RCNoX0Operands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(XRegsNoX0[getReg()])); + Inst.addOperand(MCOperand::createReg(XRegsNoX0[getRegNum()])); } void addRegG8pRCOperands(MCInst &Inst, unsigned N) const { @@ -498,12 +500,12 @@ public: void addRegF4RCOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(FRegs[getReg()])); + Inst.addOperand(MCOperand::createReg(FRegs[getRegNum()])); } void addRegF8RCOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(FRegs[getReg()])); + Inst.addOperand(MCOperand::createReg(FRegs[getRegNum()])); } void addRegFpRCOperands(MCInst &Inst, unsigned N) const { @@ -513,12 +515,12 @@ public: void addRegVFRCOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(VFRegs[getReg()])); + Inst.addOperand(MCOperand::createReg(VFRegs[getRegNum()])); } void addRegVRRCOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(VRegs[getReg()])); + Inst.addOperand(MCOperand::createReg(VRegs[getRegNum()])); } void addRegVSRCOperands(MCInst &Inst, unsigned N) const { @@ -538,12 +540,12 @@ public: void addRegSPE4RCOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(RRegs[getReg()])); + Inst.addOperand(MCOperand::createReg(RRegs[getRegNum()])); } void addRegSPERCOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(SPERegs[getReg()])); + Inst.addOperand(MCOperand::createReg(SPERegs[getRegNum()])); } void addRegACCRCOperands(MCInst &Inst, unsigned N) const { diff --git a/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp b/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp index 3fd7a1ad9efa5989c2c7cc03d0c1ec3455037321..3283a5bb69404c825b3d0b777dffb5b724dbbf9d 100644 --- a/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp +++ b/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp @@ -695,8 +695,8 @@ bool PPCInstructionSelector::selectConstantPool( .addReg(HaAddrReg) .addMemOperand(MMO); else - // For medium code model, generate ADDItocL(CPI, ADDIStocHA8(X2, CPI)) - MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::ADDItocL), DstReg) + // For medium code model, generate ADDItocL8(CPI, ADDIStocHA8(X2, CPI)) + MI = BuildMI(MBB, I, DbgLoc, TII.get(PPC::ADDItocL8), DstReg) .addReg(HaAddrReg) .addConstantPoolIndex(CPI); } @@ -739,7 +739,7 @@ bool PPCInstructionSelector::select(MachineInstr &I) { auto SelectLoadStoreAddressingMode = [&]() -> MachineInstr * { const unsigned NewOpc = selectLoadStoreOp( I.getOpcode(), RBI.getRegBank(LdSt.getReg(0), MRI, TRI)->getID(), - LdSt.getMemSizeInBits()); + LdSt.getMemSizeInBits().getValue()); if (NewOpc == I.getOpcode()) return nullptr; diff --git a/llvm/lib/Target/PowerPC/P10InstrResources.td b/llvm/lib/Target/PowerPC/P10InstrResources.td index 3bbc5a63ca7abe8bde1cdd2068ac3fa38d9b18aa..5015ba887d0b6519edce17f541f6403ba357d68f 100644 --- a/llvm/lib/Target/PowerPC/P10InstrResources.td +++ b/llvm/lib/Target/PowerPC/P10InstrResources.td @@ -881,7 +881,7 @@ def : InstRW<[P10W_FX_3C, P10W_DISP_ANY], // 3 Cycles ALU operations, 1 input operands def : InstRW<[P10W_FX_3C, P10W_DISP_ANY, P10FX_Read], (instrs - ADDI, ADDI8, ADDIdtprelL32, ADDItlsldLADDR32, ADDItocL, LI, LI8, + ADDI, ADDI8, ADDIdtprelL32, ADDItlsldLADDR32, ADDItocL8, LI, LI8, ADDIC, ADDIC8, ADDIS, ADDIS8, ADDISdtprelHA32, ADDIStocHA, ADDIStocHA8, LIS, LIS8, ADDME, ADDME8, diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index 9396ca22dacf862b64c35874fb930385b9d0d3c4..16942c6893a16d94fa71a488157b391717720ce9 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -474,6 +474,35 @@ static void collectTOCStats(PPCAsmPrinter::TOCEntryType Type) { } } +static CodeModel::Model getCodeModel(const PPCSubtarget &S, + const TargetMachine &TM, + const MachineOperand &MO) { + CodeModel::Model ModuleModel = TM.getCodeModel(); + + // If the operand is not a global address then there is no + // global variable to carry an attribute. + if (!(MO.getType() == MachineOperand::MO_GlobalAddress)) + return ModuleModel; + + const GlobalValue *GV = MO.getGlobal(); + assert(GV && "expected global for MO_GlobalAddress"); + + return S.getCodeModel(TM, GV); +} + +static void setOptionalCodeModel(MCSymbolXCOFF *XSym, CodeModel::Model CM) { + switch (CM) { + case CodeModel::Large: + XSym->setPerSymbolCodeModel(MCSymbolXCOFF::CM_Large); + return; + case CodeModel::Small: + XSym->setPerSymbolCodeModel(MCSymbolXCOFF::CM_Small); + return; + default: + report_fatal_error("Invalid code model for AIX"); + } +} + /// lookUpOrCreateTOCEntry -- Given a symbol, look up whether a TOC entry /// exists for it. If not, create one. Then return a symbol that references /// the TOC entry. @@ -1014,7 +1043,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { // relative to the toc-base. if (IsAIX) { assert( - TM.getCodeModel() == CodeModel::Small && + getCodeModel(*Subtarget, TM, MO) == CodeModel::Small && "This pseudo should only be selected for 32-bit small code model."); Exp = getTOCEntryLoadingExprForXCOFF(MOSymbol, Exp, VK); TmpInst.getOperand(1) = MCOperand::createExpr(Exp); @@ -1098,7 +1127,12 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { return; } case PPC::ADDIStocHA: { - assert((IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel::Large) && + const MachineOperand &MO = MI->getOperand(2); + + assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && + "Invalid operand for ADDIStocHA."); + assert((IsAIX && !IsPPC64 && + getCodeModel(*Subtarget, TM, MO) == CodeModel::Large) && "This pseudo should only be selected for 32-bit large code model on" " AIX."); @@ -1108,10 +1142,6 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { // Change the opcode to ADDIS. TmpInst.setOpcode(PPC::ADDIS); - const MachineOperand &MO = MI->getOperand(2); - assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && - "Invalid operand for ADDIStocHA."); - // Map the machine operand to its corresponding MCSymbol. MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this); @@ -1131,7 +1161,12 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { return; } case PPC::LWZtocL: { - assert(IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel::Large && + const MachineOperand &MO = MI->getOperand(1); + + assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && + "Invalid operand for LWZtocL."); + assert(IsAIX && !IsPPC64 && + getCodeModel(*Subtarget, TM, MO) == CodeModel::Large && "This pseudo should only be selected for 32-bit large code model on" " AIX."); @@ -1141,10 +1176,6 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { // Change the opcode to lwz. TmpInst.setOpcode(PPC::LWZ); - const MachineOperand &MO = MI->getOperand(1); - assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && - "Invalid operand for LWZtocL."); - // Map the machine operand to its corresponding MCSymbol. MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this); @@ -1183,8 +1214,12 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { const bool GlobalToc = MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal()); + + const CodeModel::Model CM = + IsAIX ? getCodeModel(*Subtarget, TM, MO) : TM.getCodeModel(); + if (GlobalToc || MO.isJTI() || MO.isBlockAddress() || - (MO.isCPI() && TM.getCodeModel() == CodeModel::Large)) + (MO.isCPI() && CM == CodeModel::Large)) MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK); VK = IsAIX ? MCSymbolRefExpr::VK_PPC_U : MCSymbolRefExpr::VK_PPC_TOC_HA; @@ -1225,8 +1260,9 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this); MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO); - - if (!MO.isCPI() || TM.getCodeModel() == CodeModel::Large) + CodeModel::Model CM = + IsAIX ? getCodeModel(*Subtarget, TM, MO) : TM.getCodeModel(); + if (!MO.isCPI() || CM == CodeModel::Large) MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK); VK = IsAIX ? MCSymbolRefExpr::VK_PPC_L : MCSymbolRefExpr::VK_PPC_TOC_LO; @@ -1236,8 +1272,8 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { EmitToStreamer(*OutStreamer, TmpInst); return; } - case PPC::ADDItocL: { - // Transform %xd = ADDItocL %xs, @sym + case PPC::ADDItocL8: { + // Transform %xd = ADDItocL8 %xs, @sym LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); // Change the opcode to ADDI8. If the global address is external, then @@ -1246,7 +1282,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { TmpInst.setOpcode(PPC::ADDI8); const MachineOperand &MO = MI->getOperand(2); - assert((MO.isGlobal() || MO.isCPI()) && "Invalid operand for ADDItocL."); + assert((MO.isGlobal() || MO.isCPI()) && "Invalid operand for ADDItocL8."); LLVM_DEBUG(assert( !(MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal())) && @@ -2651,6 +2687,27 @@ uint64_t PPCAIXAsmPrinter::getAliasOffset(const Constant *C) { return 0; } +static void tocDataChecks(unsigned PointerSize, const GlobalVariable *GV) { + // TODO: These asserts should be updated as more support for the toc data + // transformation is added (struct support, etc.). + assert( + PointerSize >= GV->getAlign().valueOrOne().value() && + "GlobalVariables with an alignment requirement stricter than TOC entry " + "size not supported by the toc data transformation."); + + Type *GVType = GV->getValueType(); + assert(GVType->isSized() && "A GlobalVariable's size must be known to be " + "supported by the toc data transformation."); + if (GV->getParent()->getDataLayout().getTypeSizeInBits(GVType) > + PointerSize * 8) + report_fatal_error( + "A GlobalVariable with size larger than a TOC entry is not currently " + "supported by the toc data transformation."); + if (GV->hasPrivateLinkage()) + report_fatal_error("A GlobalVariable with private linkage is not " + "currently supported by the toc data transformation."); +} + void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { // Special LLVM global arrays have been handled at the initialization. if (isSpecialLLVMGlobalArrayToSkip(GV) || isSpecialLLVMGlobalArrayForStaticInit(GV)) @@ -2659,6 +2716,8 @@ void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { // If the Global Variable has the toc-data attribute, it needs to be emitted // when we emit the .toc section. if (GV->hasAttribute("toc-data")) { + unsigned PointerSize = GV->getParent()->getDataLayout().getPointerSize(); + tocDataChecks(PointerSize, GV); TOCDataGlobalVars.push_back(GV); return; } @@ -2786,9 +2845,9 @@ void PPCAIXAsmPrinter::emitFunctionDescriptor() { } void PPCAIXAsmPrinter::emitFunctionEntryLabel() { - // It's not necessary to emit the label when we have individual - // function in its own csect. - if (!TM.getFunctionSections()) + // For functions without user defined section, it's not necessary to emit the + // label when we have individual function in its own csect. + if (!TM.getFunctionSections() || MF->getFunction().hasSection()) PPCAsmPrinter::emitFunctionEntryLabel(); // Emit aliasing label for function entry point label. @@ -2961,6 +3020,10 @@ bool PPCAIXAsmPrinter::doInitialization(Module &M) { } setCsectAlignment(&G); + std::optional<CodeModel::Model> OptionalCodeModel = G.getCodeModel(); + if (OptionalCodeModel) + setOptionalCodeModel(cast<MCSymbolXCOFF>(getSymbol(&G)), + *OptionalCodeModel); } for (const auto &F : M) @@ -2982,6 +3045,15 @@ bool PPCAIXAsmPrinter::doInitialization(Module &M) { false); } + const GlobalVariable *GVar = + dyn_cast_or_null<GlobalVariable>(Alias.getAliaseeObject()); + if (GVar) { + std::optional<CodeModel::Model> OptionalCodeModel = GVar->getCodeModel(); + if (OptionalCodeModel) + setOptionalCodeModel(cast<MCSymbolXCOFF>(getSymbol(&Alias)), + *OptionalCodeModel); + } + GOAliasMap[Aliasee].push_back(&Alias); } diff --git a/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def b/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def index 8bbe315a2bb9a745cc46ae8c87bb4291ac73699c..6bb66bcc6c211266c87cfc4d6887a302063d5e1a 100644 --- a/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def +++ b/llvm/lib/Target/PowerPC/PPCBack2BackFusion.def @@ -29,7 +29,7 @@ FUSION_FEATURE(GeneralBack2Back, hasBack2BackFusion, -1, ADDIStocHA8, ADDIdtprelL32, ADDItlsldLADDR32, - ADDItocL, + ADDItocL8, ADDME, ADDME8, ADDME8O, @@ -518,7 +518,7 @@ FUSION_FEATURE(GeneralBack2Back, hasBack2BackFusion, -1, ADDIStocHA8, ADDIdtprelL32, ADDItlsldLADDR32, - ADDItocL, + ADDItocL8, ADDME, ADDME8, ADDME8O, diff --git a/llvm/lib/Target/PowerPC/PPCBoolRetToInt.cpp b/llvm/lib/Target/PowerPC/PPCBoolRetToInt.cpp index f1abb78d4dd343eac29a4c86cc5af9c12fb84ab1..4a3b64f30d8d496d5221a694adf49113c0362b24 100644 --- a/llvm/lib/Target/PowerPC/PPCBoolRetToInt.cpp +++ b/llvm/lib/Target/PowerPC/PPCBoolRetToInt.cpp @@ -263,7 +263,8 @@ class PPCBoolRetToInt : public FunctionPass { Value *IntRetVal = BoolToIntMap[U]; Type *Int1Ty = Type::getInt1Ty(U->getContext()); auto *I = cast<Instruction>(U.getUser()); - Value *BackToBool = new TruncInst(IntRetVal, Int1Ty, "backToBool", I); + Value *BackToBool = + new TruncInst(IntRetVal, Int1Ty, "backToBool", I->getIterator()); U.set(BackToBool); return true; diff --git a/llvm/lib/Target/PowerPC/PPCFastISel.cpp b/llvm/lib/Target/PowerPC/PPCFastISel.cpp index 56af80f9cedee8089f3bb17f8785d38ae02d7121..6e31cdae84767a1939985048ec5c1ec87c035321 100644 --- a/llvm/lib/Target/PowerPC/PPCFastISel.cpp +++ b/llvm/lib/Target/PowerPC/PPCFastISel.cpp @@ -2094,7 +2094,7 @@ unsigned PPCFastISel::PPCMaterializeGV(const GlobalValue *GV, MVT VT) { // for large code model, we generate: // LDtocL(GV, ADDIStocHA8(%x2, GV)) // Otherwise we generate: - // ADDItocL(ADDIStocHA8(%x2, GV), GV) + // ADDItocL8(ADDIStocHA8(%x2, GV), GV) // Either way, start with the ADDIStocHA8: Register HighPartReg = createResultReg(RC); BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(PPC::ADDIStocHA8), @@ -2104,9 +2104,11 @@ unsigned PPCFastISel::PPCMaterializeGV(const GlobalValue *GV, MVT VT) { BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(PPC::LDtocL), DestReg).addGlobalAddress(GV).addReg(HighPartReg); } else { - // Otherwise generate the ADDItocL. - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(PPC::ADDItocL), - DestReg).addReg(HighPartReg).addGlobalAddress(GV); + // Otherwise generate the ADDItocL8. + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(PPC::ADDItocL8), + DestReg) + .addReg(HighPartReg) + .addGlobalAddress(GV); } } diff --git a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp index 424501c35c043c49927164bcfbb70ac5e20da746..6dcb59a3a57f85d3dba8261caf373b3eefb6057d 100644 --- a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp @@ -2676,7 +2676,7 @@ bool PPCFrameLowering::restoreCalleeSavedRegisters( Restored.set(Dst); } else { - // Default behavior for non-CR saves. + // Default behavior for non-CR saves. const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); // Functions without NoUnwind need to preserve the order of elements in diff --git a/llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp b/llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp index ffaa3e05c847909b90aa14c6f903f74456084e9f..a942d2f9c7e8e5d7212fe9809f4a0d7cdc64b491 100644 --- a/llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp +++ b/llvm/lib/Target/PowerPC/PPCHazardRecognizers.cpp @@ -374,8 +374,9 @@ getHazardType(SUnit *SU, int Stalls) { // overlapping address. if (isLoad && NumStores && !MI->memoperands_empty()) { MachineMemOperand *MO = *MI->memoperands_begin(); - if (isLoadOfStoredAddress(MO->getSize(), - MO->getOffset(), MO->getValue())) + if (MO->getSize().hasValue() && + isLoadOfStoredAddress(MO->getSize().getValue(), MO->getOffset(), + MO->getValue())) return NoopHazard; } @@ -399,9 +400,10 @@ void PPCHazardRecognizer970::EmitInstruction(SUnit *SU) { if (Opcode == PPC::MTCTR || Opcode == PPC::MTCTR8) HasCTRSet = true; // Track the address stored to. - if (isStore && NumStores < 4 && !MI->memoperands_empty()) { + if (isStore && NumStores < 4 && !MI->memoperands_empty() && + (*MI->memoperands_begin())->getSize().hasValue()) { MachineMemOperand *MO = *MI->memoperands_begin(); - StoreSize[NumStores] = MO->getSize(); + StoreSize[NumStores] = MO->getSize().getValue(); StoreOffset[NumStores] = MO->getOffset(); StoreValue[NumStores] = MO->getValue(); ++NumStores; diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 9e5f0b36616d1b9af34eeaf8ba8d66dcb4f495cf..af82b6cdb1809ed34822e89cc796f3f1f4b10271 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -521,41 +521,25 @@ static bool hasTocDataAttr(SDValue Val, unsigned PointerSize) { if (!GV->hasAttribute("toc-data")) return false; + return true; +} - // TODO: These asserts should be updated as more support for the toc data - // transformation is added (struct support, etc.). - - assert( - PointerSize >= GV->getAlign().valueOrOne().value() && - "GlobalVariables with an alignment requirement stricter than TOC entry " - "size not supported by the toc data transformation."); - - Type *GVType = GV->getValueType(); - - assert(GVType->isSized() && "A GlobalVariable's size must be known to be " - "supported by the toc data transformation."); - - if (GVType->isVectorTy()) - report_fatal_error("A GlobalVariable of Vector type is not currently " - "supported by the toc data transformation."); - - if (GVType->isArrayTy()) - report_fatal_error("A GlobalVariable of Array type is not currently " - "supported by the toc data transformation."); - - if (GVType->isStructTy()) - report_fatal_error("A GlobalVariable of Struct type is not currently " - "supported by the toc data transformation."); +static CodeModel::Model getCodeModel(const PPCSubtarget &Subtarget, + const TargetMachine &TM, + const SDNode *Node) { + // If there isn't an attribute to override the module code model + // this will be the effective code model. + CodeModel::Model ModuleModel = TM.getCodeModel(); - assert(GVType->getPrimitiveSizeInBits() <= PointerSize * 8 && - "A GlobalVariable with size larger than a TOC entry is not currently " - "supported by the toc data transformation."); + GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Node->getOperand(0)); + if (!GA) + return ModuleModel; - if (GV->hasPrivateLinkage()) - report_fatal_error("A GlobalVariable with private linkage is not " - "currently supported by the toc data transformation."); + const GlobalValue *GV = GA->getGlobal(); + if (!GV) + return ModuleModel; - return true; + return Subtarget.getCodeModel(TM, GV); } /// isInt32Immediate - This method tests to see if the node is a 32-bit constant @@ -6093,7 +6077,8 @@ void PPCDAGToDAGISel::Select(SDNode *N) { const bool isAIXABI = Subtarget->isAIXABI(); // PowerPC only support small, medium and large code model. - const CodeModel::Model CModel = TM.getCodeModel(); + const CodeModel::Model CModel = getCodeModel(*Subtarget, TM, N); + assert(!(CModel == CodeModel::Tiny || CModel == CodeModel::Kernel) && "PowerPC doesn't support tiny or kernel code models."); @@ -6168,7 +6153,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) { // [64-bit ELF/AIX] // LDtocL(@sym, ADDIStocHA8(%x2, @sym)) // Otherwise we generate: - // ADDItocL(ADDIStocHA8(%x2, @sym), @sym) + // ADDItocL8(ADDIStocHA8(%x2, @sym), @sym) SDValue GA = N->getOperand(0); SDValue TOCbase = N->getOperand(1); @@ -6188,7 +6173,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) { } // Build the address relative to the TOC-pointer. - ReplaceNode(N, CurDAG->getMachineNode(PPC::ADDItocL, dl, MVT::i64, + ReplaceNode(N, CurDAG->getMachineNode(PPC::ADDItocL8, dl, MVT::i64, SDValue(Tmp, 0), GA)); return; } @@ -7573,6 +7558,16 @@ static void reduceVSXSwap(SDNode *N, SelectionDAG *DAG) { DAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), N->getOperand(0)); } +// Check if an SDValue has the 'aix-small-tls' global variable attribute. +static bool hasAIXSmallTLSAttr(SDValue Val) { + if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Val)) + if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(GA->getGlobal())) + if (GV->hasAttribute("aix-small-tls")) + return true; + + return false; +} + // Is an ADDI eligible for folding for non-TOC-based local-exec accesses? static bool isEligibleToFoldADDIForLocalExecAccesses(SelectionDAG *DAG, SDValue ADDIToFold) { @@ -7582,20 +7577,25 @@ static bool isEligibleToFoldADDIForLocalExecAccesses(SelectionDAG *DAG, (ADDIToFold.getMachineOpcode() != PPC::ADDI8)) return false; + // Folding is only allowed for the AIX small-local-exec TLS target attribute + // or when the 'aix-small-tls' global variable attribute is present. + const PPCSubtarget &Subtarget = + DAG->getMachineFunction().getSubtarget<PPCSubtarget>(); + SDValue TLSVarNode = ADDIToFold.getOperand(1); + if (!(Subtarget.hasAIXSmallLocalExecTLS() || hasAIXSmallTLSAttr(TLSVarNode))) + return false; + // The first operand of the ADDIToFold should be the thread pointer. // This transformation is only performed if the first operand of the // addi is the thread pointer. SDValue TPRegNode = ADDIToFold.getOperand(0); RegisterSDNode *TPReg = dyn_cast<RegisterSDNode>(TPRegNode.getNode()); - const PPCSubtarget &Subtarget = - DAG->getMachineFunction().getSubtarget<PPCSubtarget>(); if (!TPReg || (TPReg->getReg() != Subtarget.getThreadPointerRegister())) return false; // The second operand of the ADDIToFold should be the global TLS address // (the local-exec TLS variable). We only perform the folding if the TLS // variable is the second operand. - SDValue TLSVarNode = ADDIToFold.getOperand(1); GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(TLSVarNode); if (!GA) return false; @@ -7664,7 +7664,6 @@ static void foldADDIForLocalExecAccesses(SDNode *N, SelectionDAG *DAG) { void PPCDAGToDAGISel::PeepholePPC64() { SelectionDAG::allnodes_iterator Position = CurDAG->allnodes_end(); - bool HasAIXSmallLocalExecTLS = Subtarget->hasAIXSmallLocalExecTLS(); while (Position != CurDAG->allnodes_begin()) { SDNode *N = &*--Position; @@ -7676,8 +7675,7 @@ void PPCDAGToDAGISel::PeepholePPC64() { reduceVSXSwap(N, CurDAG); // This optimization is performed for non-TOC-based local-exec accesses. - if (HasAIXSmallLocalExecTLS) - foldADDIForLocalExecAccesses(N, CurDAG); + foldADDIForLocalExecAccesses(N, CurDAG); unsigned FirstOp; unsigned StorageOpcode = N->getMachineOpcode(); @@ -7741,7 +7739,7 @@ void PPCDAGToDAGISel::PeepholePPC64() { // target flags on the immediate operand when we fold it into the // load instruction. // - // For something like ADDItocL, the relocation information is + // For something like ADDItocL8, the relocation information is // inferred from the opcode; when we process it in the AsmPrinter, // we add the necessary relocation there. A load, though, can receive // relocation from various flavors of ADDIxxx, so we need to carry @@ -7762,7 +7760,7 @@ void PPCDAGToDAGISel::PeepholePPC64() { case PPC::ADDItlsldL: Flags = PPCII::MO_TLSLD_LO; break; - case PPC::ADDItocL: + case PPC::ADDItocL8: Flags = PPCII::MO_TOC_LO; break; } @@ -7789,7 +7787,7 @@ void PPCDAGToDAGISel::PeepholePPC64() { // If we have a addi(toc@l)/addis(toc@ha) pair, and the addis has only // one use, then we can do this for any offset, we just need to also // update the offset (i.e. the symbol addend) on the addis also. - if (Base.getMachineOpcode() != PPC::ADDItocL) + if (Base.getMachineOpcode() != PPC::ADDItocL8) continue; if (!HBase.isMachineOpcode() || @@ -7836,8 +7834,7 @@ void PPCDAGToDAGISel::PeepholePPC64() { ImmOpnd.getValueType()); } else if (Offset != 0) { // This optimization is performed for non-TOC-based local-exec accesses. - if (HasAIXSmallLocalExecTLS && - isEligibleToFoldADDIForLocalExecAccesses(CurDAG, Base)) { + if (isEligibleToFoldADDIForLocalExecAccesses(CurDAG, Base)) { // Add the non-zero offset information into the load or store // instruction to be used for non-TOC-based local-exec accesses. GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(ImmOpnd); diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index aef2d483c6df1e377cec3c3f8f70577d57cd2f0c..43e4a34a9b34832a2e3c8eee9d1c49031253809c 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -137,6 +137,10 @@ static cl::opt<unsigned> PPCMinimumJumpTableEntries( "ppc-min-jump-table-entries", cl::init(64), cl::Hidden, cl::desc("Set minimum number of entries to use a jump table on PPC")); +static cl::opt<unsigned> PPCGatherAllAliasesMaxDepth( + "ppc-gather-alias-max-depth", cl::init(18), cl::Hidden, + cl::desc("max depth when checking alias info in GatherAllAliases()")); + STATISTIC(NumTailCalls, "Number of tail calls"); STATISTIC(NumSiblingCalls, "Number of sibling calls"); STATISTIC(ShufflesHandledWithVPERM, @@ -1512,6 +1516,8 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM, // than the corresponding branch. This information is used in CGP to decide // when to convert selects into branches. PredictableSelectIsExpensive = Subtarget.isPredictableSelectIsExpensive(); + + GatherAllAliasesMaxDepth = PPCGatherAllAliasesMaxDepth; } // *********************************** NOTE ************************************ @@ -3367,15 +3373,21 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op, const GlobalValue *GV = GA->getGlobal(); EVT PtrVT = getPointerTy(DAG.getDataLayout()); bool Is64Bit = Subtarget.isPPC64(); - bool HasAIXSmallLocalExecTLS = Subtarget.hasAIXSmallLocalExecTLS(); TLSModel::Model Model = getTargetMachine().getTLSModel(GV); bool IsTLSLocalExecModel = Model == TLSModel::LocalExec; if (IsTLSLocalExecModel || Model == TLSModel::InitialExec) { + bool HasAIXSmallLocalExecTLS = Subtarget.hasAIXSmallLocalExecTLS(); + bool HasAIXSmallTLSGlobalAttr = false; SDValue VariableOffsetTGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, PPCII::MO_TPREL_FLAG); SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA); SDValue TLSReg; + + if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) + if (GVar->hasAttribute("aix-small-tls")) + HasAIXSmallTLSGlobalAttr = true; + if (Is64Bit) { // For local-exec and initial-exec on AIX (64-bit), the sequence generated // involves a load of the variable offset (from the TOC), followed by an @@ -3385,14 +3397,16 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op, // add reg2, reg1, r13 // r13 contains the thread pointer TLSReg = DAG.getRegister(PPC::X13, MVT::i64); - // With the -maix-small-local-exec-tls option, produce a faster access - // sequence for local-exec TLS variables where the offset from the TLS - // base is encoded as an immediate operand. + // With the -maix-small-local-exec-tls option, or with the "aix-small-tls" + // global variable attribute, produce a faster access sequence for + // local-exec TLS variables where the offset from the TLS base is encoded + // as an immediate operand. // // We only utilize the faster local-exec access sequence when the TLS // variable has a size within the policy limit. We treat types that are // not sized or are empty as being over the policy size limit. - if (HasAIXSmallLocalExecTLS && IsTLSLocalExecModel) { + if ((HasAIXSmallLocalExecTLS || HasAIXSmallTLSGlobalAttr) && + IsTLSLocalExecModel) { Type *GVType = GV->getValueType(); if (GVType->isSized() && !GVType->isEmptyTy() && GV->getParent()->getDataLayout().getTypeAllocSize(GVType) <= @@ -3410,8 +3424,9 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op, TLSReg = DAG.getNode(PPCISD::GET_TPOINTER, dl, PtrVT); // We do not implement the 32-bit version of the faster access sequence - // for local-exec that is controlled by -maix-small-local-exec-tls. - if (HasAIXSmallLocalExecTLS) + // for local-exec that is controlled by the -maix-small-local-exec-tls + // option, or the "aix-small-tls" global variable attribute. + if (HasAIXSmallLocalExecTLS || HasAIXSmallTLSGlobalAttr) report_fatal_error("The small-local-exec TLS access sequence is " "currently only supported on AIX (64-bit mode)."); } @@ -8519,7 +8534,8 @@ bool PPCTargetLowering::directMoveIsProfitable(const SDValue &Op) const { // If there is no LXSIBZX/LXSIHZX, like Power8, // prefer direct move if the memory size is 1 or 2 bytes. MachineMemOperand *MMO = cast<LoadSDNode>(Origin)->getMemOperand(); - if (!Subtarget.hasP9Vector() && MMO->getSize() <= 2) + if (!Subtarget.hasP9Vector() && + (!MMO->getSize().hasValue() || MMO->getSize().getValue() <= 2)) return true; for (SDNode::use_iterator UI = Origin->use_begin(), @@ -10763,30 +10779,54 @@ SDValue PPCTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, return DAG.getRegister(PPC::R2, MVT::i32); case Intrinsic::ppc_rldimi: { + assert(Subtarget.isPPC64() && "rldimi is only available in 64-bit!"); + SDValue Src = Op.getOperand(1); + APInt Mask = Op.getConstantOperandAPInt(4); + if (Mask.isZero()) + return Op.getOperand(2); + if (Mask.isAllOnes()) + return DAG.getNode(ISD::ROTL, dl, MVT::i64, Src, Op.getOperand(3)); uint64_t SH = Op.getConstantOperandVal(3); unsigned MB = 0, ME = 0; - if (!isRunOfOnes64(Op.getConstantOperandVal(4), MB, ME) || ME != 63 - SH) + if (!isRunOfOnes64(Mask.getZExtValue(), MB, ME)) report_fatal_error("invalid rldimi mask!"); - return SDValue(DAG.getMachineNode( - PPC::RLDIMI, dl, MVT::i64, - {Op.getOperand(1), Op.getOperand(2), Op.getOperand(3), - DAG.getTargetConstant(MB, dl, MVT::i32)}), - 0); + // rldimi requires ME=63-SH, otherwise rotation is needed before rldimi. + if (ME < 63 - SH) { + Src = DAG.getNode(ISD::ROTL, dl, MVT::i64, Src, + DAG.getConstant(ME + SH + 1, dl, MVT::i32)); + } else if (ME > 63 - SH) { + Src = DAG.getNode(ISD::ROTL, dl, MVT::i64, Src, + DAG.getConstant(ME + SH - 63, dl, MVT::i32)); + } + return SDValue( + DAG.getMachineNode(PPC::RLDIMI, dl, MVT::i64, + {Op.getOperand(2), Src, + DAG.getTargetConstant(63 - ME, dl, MVT::i32), + DAG.getTargetConstant(MB, dl, MVT::i32)}), + 0); } case Intrinsic::ppc_rlwimi: { + APInt Mask = Op.getConstantOperandAPInt(4); + if (Mask.isZero()) + return Op.getOperand(2); + if (Mask.isAllOnes()) + return DAG.getNode(ISD::ROTL, dl, MVT::i32, Op.getOperand(1), + Op.getOperand(3)); unsigned MB = 0, ME = 0; - if (!isRunOfOnes(Op.getConstantOperandVal(4), MB, ME)) + if (!isRunOfOnes(Mask.getZExtValue(), MB, ME)) report_fatal_error("invalid rlwimi mask!"); return SDValue(DAG.getMachineNode( PPC::RLWIMI, dl, MVT::i32, - {Op.getOperand(1), Op.getOperand(2), Op.getOperand(3), + {Op.getOperand(2), Op.getOperand(1), Op.getOperand(3), DAG.getTargetConstant(MB, dl, MVT::i32), DAG.getTargetConstant(ME, dl, MVT::i32)}), 0); } case Intrinsic::ppc_rlwnm: { + if (Op.getConstantOperandVal(3) == 0) + return DAG.getConstant(0, dl, MVT::i32); unsigned MB = 0, ME = 0; if (!isRunOfOnes(Op.getConstantOperandVal(3), MB, ME)) report_fatal_error("invalid rlwnm mask!"); @@ -15023,6 +15063,7 @@ SDValue PPCTargetLowering::combineFPToIntToFP(SDNode *N, SDValue Ld = DAG.getMemIntrinsicNode(PPCISD::LXSIZX, dl, DAG.getVTList(MVT::f64, MVT::Other), Ops, MVT::i8, LDN->getMemOperand()); + DAG.makeEquivalentMemoryOrdering(LDN, Ld); // For signed conversion, we need to sign-extend the value in the VSR if (Signed) { @@ -15114,7 +15155,7 @@ SDValue PPCTargetLowering::expandVSXLoadForLE(SDNode *N, // If the MMO suggests this isn't a load of a full vector, leave // things alone. For a built-in, we have to make the change for // correctness, so if there is a size problem that will be a bug. - if (MMO->getSize() < 16) + if (!MMO->getSize().hasValue() || MMO->getSize().getValue() < 16) return SDValue(); break; } @@ -15182,7 +15223,7 @@ SDValue PPCTargetLowering::expandVSXStoreForLE(SDNode *N, // If the MMO suggests this isn't a store of a full vector, leave // things alone. For a built-in, we have to make the change for // correctness, so if there is a size problem that will be a bug. - if (MMO->getSize() < 16) + if (!MMO->getSize().hasValue() || MMO->getSize().getValue() < 16) return SDValue(); break; } diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td index 2949d58ab664796b105a790ebd11209725d77a34..a9359794a641c95ec99ad98038eb69f2e6825360 100644 --- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -1480,8 +1480,8 @@ let hasSideEffects = 0 in { let isReMaterializable = 1 in { def ADDIStocHA8: PPCEmitTimePseudo<(outs g8rc:$rD), (ins g8rc_nox0:$reg, tocentry:$disp), "#ADDIStocHA8", []>, isPPC64; -def ADDItocL: PPCEmitTimePseudo<(outs g8rc:$rD), (ins g8rc_nox0:$reg, tocentry:$disp), - "#ADDItocL", []>, isPPC64; +def ADDItocL8: PPCEmitTimePseudo<(outs g8rc:$rD), (ins g8rc_nox0:$reg, tocentry:$disp), + "#ADDItocL8", []>, isPPC64; } // Local Data Transform diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp index 5d37e929f8755eef854c6bb347b8b0044f53a3d8..5f5eb31a5a85fa80212fd3438350180060f59be0 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -1077,7 +1077,7 @@ bool PPCInstrInfo::isReallyTriviallyReMaterializable( case PPC::LIS8: case PPC::ADDIStocHA: case PPC::ADDIStocHA8: - case PPC::ADDItocL: + case PPC::ADDItocL8: case PPC::LOAD_STACK_GUARD: case PPC::PPCLdFixedAddr: case PPC::XXLXORz: @@ -3453,7 +3453,7 @@ MachineInstr *PPCInstrInfo::getForwardingDefMI( break; case PPC::LI: case PPC::LI8: - case PPC::ADDItocL: + case PPC::ADDItocL8: case PPC::ADDI: case PPC::ADDI8: OpNoForForwarding = i; @@ -4420,7 +4420,7 @@ bool PPCInstrInfo::isDefMIElgibleForForwarding(MachineInstr &DefMI, MachineOperand *&ImmMO, MachineOperand *&RegMO) const { unsigned Opc = DefMI.getOpcode(); - if (Opc != PPC::ADDItocL && Opc != PPC::ADDI && Opc != PPC::ADDI8) + if (Opc != PPC::ADDItocL8 && Opc != PPC::ADDI && Opc != PPC::ADDI8) return false; assert(DefMI.getNumOperands() >= 3 && @@ -4485,8 +4485,8 @@ bool PPCInstrInfo::isImmElgibleForForwarding(const MachineOperand &ImmMO, int64_t &Imm, int64_t BaseImm) const { assert(isAnImmediateOperand(ImmMO) && "ImmMO is NOT an immediate"); - if (DefMI.getOpcode() == PPC::ADDItocL) { - // The operand for ADDItocL is CPI, which isn't imm at compiling time, + if (DefMI.getOpcode() == PPC::ADDItocL8) { + // The operand for ADDItocL8 is CPI, which isn't imm at compiling time, // However, we know that, it is 16-bit width, and has the alignment of 4. // Check if the instruction met the requirement. if (III.ImmMustBeMultipleOf > 4 || @@ -4899,7 +4899,7 @@ bool PPCInstrInfo::transformToImmFormFedByAdd( // register with ImmMO. // Before that, we need to fixup the target flags for imm. // For some reason, we miss to set the flag for the ImmMO if it is CPI. - if (DefMI.getOpcode() == PPC::ADDItocL) + if (DefMI.getOpcode() == PPC::ADDItocL8) ImmMO->setTargetFlags(PPCII::MO_TOC_LO); // MI didn't have the interface such as MI.setOperand(i) though diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index 82da1a3c30598385e888313ae2f096021775bf08..6423e692d88c3706823bce2ac96d3657595a3814 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -5045,12 +5045,12 @@ defm : TrapExtendedMnemonic<"lng", 6>; defm : TrapExtendedMnemonic<"u", 31>; // Atomic loads -def : Pat<(atomic_load_8 DForm:$src), (LBZ memri:$src)>; -def : Pat<(atomic_load_16 DForm:$src), (LHZ memri:$src)>; -def : Pat<(atomic_load_32 DForm:$src), (LWZ memri:$src)>; -def : Pat<(atomic_load_8 XForm:$src), (LBZX memrr:$src)>; -def : Pat<(atomic_load_16 XForm:$src), (LHZX memrr:$src)>; -def : Pat<(atomic_load_32 XForm:$src), (LWZX memrr:$src)>; +def : Pat<(i32 (atomic_load_8 DForm:$src)), (LBZ memri:$src)>; +def : Pat<(i32 (atomic_load_16 DForm:$src)), (LHZ memri:$src)>; +def : Pat<(i32 (atomic_load_32 DForm:$src)), (LWZ memri:$src)>; +def : Pat<(i32 (atomic_load_8 XForm:$src)), (LBZX memrr:$src)>; +def : Pat<(i32 (atomic_load_16 XForm:$src)), (LHZX memrr:$src)>; +def : Pat<(i32 (atomic_load_32 XForm:$src)), (LWZX memrr:$src)>; // Atomic stores def : Pat<(atomic_store_8 i32:$val, DForm:$ptr), (STB gprc:$val, memri:$ptr)>; diff --git a/llvm/lib/Target/PowerPC/PPCInstrP10.td b/llvm/lib/Target/PowerPC/PPCInstrP10.td index d5a372e4dc101086352c58695485ba4b332090f2..5f2937d47a5195ffcccccad3ced96ed5b42567dc 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrP10.td +++ b/llvm/lib/Target/PowerPC/PPCInstrP10.td @@ -1289,13 +1289,13 @@ let Predicates = [PCRelativeMemops] in { (PSTXVpc $XS, $ga, 0)>; // Atomic Load - def : Pat<(atomic_load_8 (PPCmatpcreladdr PCRelForm:$ga)), + def : Pat<(i32 (atomic_load_8 (PPCmatpcreladdr PCRelForm:$ga))), (PLBZpc $ga, 0)>; - def : Pat<(atomic_load_16 (PPCmatpcreladdr PCRelForm:$ga)), + def : Pat<(i32 (atomic_load_16 (PPCmatpcreladdr PCRelForm:$ga))), (PLHZpc $ga, 0)>; - def : Pat<(atomic_load_32 (PPCmatpcreladdr PCRelForm:$ga)), + def : Pat<(i32 (atomic_load_32 (PPCmatpcreladdr PCRelForm:$ga))), (PLWZpc $ga, 0)>; - def : Pat<(atomic_load_64 (PPCmatpcreladdr PCRelForm:$ga)), + def : Pat<(i64 (atomic_load_64 (PPCmatpcreladdr PCRelForm:$ga))), (PLDpc $ga, 0)>; // Atomic Store @@ -2347,10 +2347,10 @@ let Predicates = [PrefixInstrs] in { def : Pat<(store f64:$FRS, PDForm:$dst), (PSTFD $FRS, memri34:$dst)>; // Atomic Load - def : Pat<(atomic_load_8 PDForm:$src), (PLBZ memri34:$src)>; - def : Pat<(atomic_load_16 PDForm:$src), (PLHZ memri34:$src)>; - def : Pat<(atomic_load_32 PDForm:$src), (PLWZ memri34:$src)>; - def : Pat<(atomic_load_64 PDForm:$src), (PLD memri34:$src)>; + def : Pat<(i32 (atomic_load_8 PDForm:$src)), (PLBZ memri34:$src)>; + def : Pat<(i32 (atomic_load_16 PDForm:$src)), (PLHZ memri34:$src)>; + def : Pat<(i32 (atomic_load_32 PDForm:$src)), (PLWZ memri34:$src)>; + def : Pat<(i64 (atomic_load_64 PDForm:$src)), (PLD memri34:$src)>; // Atomic Store def : Pat<(atomic_store_8 i32:$RS, PDForm:$dst), (PSTB $RS, memri34:$dst)>; diff --git a/llvm/lib/Target/PowerPC/PPCInstrVSX.td b/llvm/lib/Target/PowerPC/PPCInstrVSX.td index 0e5f6b773bb54415b21cc5d643f6a8c80f8d5123..dd07892794d59998c5bae59e3b0f18b8b5430679 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrVSX.td +++ b/llvm/lib/Target/PowerPC/PPCInstrVSX.td @@ -1596,7 +1596,7 @@ let Predicates = [HasVSX, HasP9Vector] in { // FIXME: Setting the hasSideEffects flag here to match current behaviour. let hasSideEffects = 1 in { def XSTSTDCSP : XX2_BF3_DCMX7_RS6<60, 298, - (outs crrc:$BF), (ins u7imm:$DCMX, vsfrc:$XB), + (outs crrc:$BF), (ins u7imm:$DCMX, vssrc:$XB), "xststdcsp $BF, $XB, $DCMX", IIC_VecFP, []>; def XSTSTDCDP : XX2_BF3_DCMX7_RS6<60, 362, (outs crrc:$BF), (ins u7imm:$DCMX, vsfrc:$XB), diff --git a/llvm/lib/Target/PowerPC/PPCLoopInstrFormPrep.cpp b/llvm/lib/Target/PowerPC/PPCLoopInstrFormPrep.cpp index dc739a2c7a4d0a4b54e85bd37408c53a36452847..f19eb2af5e0709799c5d01134afefd83879240d2 100644 --- a/llvm/lib/Target/PowerPC/PPCLoopInstrFormPrep.cpp +++ b/llvm/lib/Target/PowerPC/PPCLoopInstrFormPrep.cpp @@ -725,7 +725,7 @@ PPCLoopInstrFormPrep::rewriteForBase(Loop *L, const SCEVAddRecExpr *BasePtrSCEV, Instruction *PtrInc = nullptr; Instruction *NewBasePtr = nullptr; if (CanPreInc) { - Instruction *InsPoint = &*Header->getFirstInsertionPt(); + BasicBlock::iterator InsPoint = Header->getFirstInsertionPt(); PtrInc = GetElementPtrInst::Create( I8Ty, NewPHI, IncNode, getInstrName(BaseMemI, GEPNodeIncNameSuffix), InsPoint); @@ -752,7 +752,7 @@ PPCLoopInstrFormPrep::rewriteForBase(Loop *L, const SCEVAddRecExpr *BasePtrSCEV, // For the latch predecessor, we need to insert a GEP just before the // terminator to increase the address. BasicBlock *BB = PI; - Instruction *InsPoint = BB->getTerminator(); + BasicBlock::iterator InsPoint = BB->getTerminator()->getIterator(); PtrInc = GetElementPtrInst::Create( I8Ty, NewPHI, IncNode, getInstrName(BaseMemI, GEPNodeIncNameSuffix), InsPoint); @@ -764,7 +764,7 @@ PPCLoopInstrFormPrep::rewriteForBase(Loop *L, const SCEVAddRecExpr *BasePtrSCEV, if (NewPHI->getType() != BasePtr->getType()) NewBasePtr = new BitCastInst(NewPHI, BasePtr->getType(), getInstrName(NewPHI, CastNodeNameSuffix), - &*Header->getFirstInsertionPt()); + Header->getFirstInsertionPt()); else NewBasePtr = NewPHI; } @@ -794,20 +794,25 @@ Instruction *PPCLoopInstrFormPrep::rewriteForBucketElement( cast<SCEVConstant>(Element.Offset)->getValue()->isZero())) { RealNewPtr = NewBasePtr; } else { - Instruction *PtrIP = dyn_cast<Instruction>(Ptr); + std::optional<BasicBlock::iterator> PtrIP = std::nullopt; + if (Instruction *I = dyn_cast<Instruction>(Ptr)) + PtrIP = I->getIterator(); + if (PtrIP && isa<Instruction>(NewBasePtr) && - cast<Instruction>(NewBasePtr)->getParent() == PtrIP->getParent()) - PtrIP = nullptr; - else if (PtrIP && isa<PHINode>(PtrIP)) - PtrIP = &*PtrIP->getParent()->getFirstInsertionPt(); + cast<Instruction>(NewBasePtr)->getParent() == (*PtrIP)->getParent()) + PtrIP = std::nullopt; + else if (PtrIP && isa<PHINode>(*PtrIP)) + PtrIP = (*PtrIP)->getParent()->getFirstInsertionPt(); else if (!PtrIP) - PtrIP = Element.Instr; + PtrIP = Element.Instr->getIterator(); assert(OffToBase && "There should be an offset for non base element!\n"); GetElementPtrInst *NewPtr = GetElementPtrInst::Create( I8Ty, PtrInc, OffToBase, - getInstrName(Element.Instr, GEPNodeOffNameSuffix), PtrIP); - if (!PtrIP) + getInstrName(Element.Instr, GEPNodeOffNameSuffix)); + if (PtrIP) + NewPtr->insertBefore(*(*PtrIP)->getParent(), *PtrIP); + else NewPtr->insertAfter(cast<Instruction>(PtrInc)); NewPtr->setIsInBounds(IsPtrInBounds(Ptr)); RealNewPtr = NewPtr; diff --git a/llvm/lib/Target/PowerPC/PPCMacroFusion.def b/llvm/lib/Target/PowerPC/PPCMacroFusion.def index 6b8ad22639c80fde9a9576d062c7c920c84ba168..fb6e656edb8b9b1b7811b44ee080d9f2fa795009 100644 --- a/llvm/lib/Target/PowerPC/PPCMacroFusion.def +++ b/llvm/lib/Target/PowerPC/PPCMacroFusion.def @@ -32,7 +32,7 @@ // {addi} followed by one of these {lxvd2x, lxvw4x, lxvdsx, lvebx, lvehx, // lvewx, lvx, lxsdx} FUSION_FEATURE(AddiLoad, hasAddiLoadFusion, 2, \ - FUSION_OP_SET(ADDI, ADDI8, ADDItocL), \ + FUSION_OP_SET(ADDI, ADDI8, ADDItocL8), \ FUSION_OP_SET(LXVD2X, LXVW4X, LXVDSX, LVEBX, LVEHX, LVEWX, \ LVX, LXSDX)) @@ -135,11 +135,11 @@ FUSION_FEATURE(XorisXori, hasWideImmFusion, 1, FUSION_OP_SET(XORIS, XORIS8), // addis rx,ra,si - addi rt,rx,SI, SI >= 0 FUSION_FEATURE(AddisAddi, hasWideImmFusion, 1, FUSION_OP_SET(ADDIS, ADDIS8, ADDIStocHA8), - FUSION_OP_SET(ADDI, ADDI8, ADDItocL)) + FUSION_OP_SET(ADDI, ADDI8, ADDItocL8)) // addi rx,ra,si - addis rt,rx,SI, ra > 0, SI >= 2 FUSION_FEATURE(AddiAddis, hasWideImmFusion, 1, - FUSION_OP_SET(ADDI, ADDI8, ADDItocL), + FUSION_OP_SET(ADDI, ADDI8, ADDItocL8), FUSION_OP_SET(ADDIS, ADDIS8, ADDIStocHA8)) // mtctr - { bcctr,bcctrl } diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp index 5380ec1c4c0d9c0215822c8fa4a3cceeb03916f6..653d9bda99192a4394145535aca0d32abde41b36 100644 --- a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp @@ -186,14 +186,63 @@ bool PPCSubtarget::enableSubRegLiveness() const { } bool PPCSubtarget::isGVIndirectSymbol(const GlobalValue *GV) const { + if (isAIXABI()) { + if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) + // On AIX the only symbols that aren't indirect are toc-data. + return !GVar->hasAttribute("toc-data"); + + return true; + } + // Large code model always uses the TOC even for local symbols. if (TM.getCodeModel() == CodeModel::Large) return true; + if (TM.shouldAssumeDSOLocal(GV)) return false; return true; } +CodeModel::Model PPCSubtarget::getCodeModel(const TargetMachine &TM, + const GlobalValue *GV) const { + // If there isn't an attribute to override the module code model + // this will be the effective code model. + CodeModel::Model ModuleModel = TM.getCodeModel(); + + // Initially support per global code model for AIX only. + if (!isAIXABI()) + return ModuleModel; + + // Only GlobalVariables carry an attribute which can override the module code + // model. + assert(GV && "Unexpected NULL GlobalValue"); + const GlobalVariable *GlobalVar = + [](const GlobalValue *GV) -> const GlobalVariable * { + const GlobalVariable *Var = dyn_cast<GlobalVariable>(GV); + if (Var) + return Var; + + const GlobalAlias *Alias = dyn_cast<GlobalAlias>(GV); + if (Alias) + return dyn_cast<GlobalVariable>(Alias->getAliaseeObject()); + + return nullptr; + }(GV); + + if (!GlobalVar) + return ModuleModel; + + std::optional<CodeModel::Model> MaybeCodeModel = GlobalVar->getCodeModel(); + if (MaybeCodeModel) { + CodeModel::Model CM = *MaybeCodeModel; + assert((CM == CodeModel::Small || CM == CodeModel::Large) && + "invalid code model for AIX"); + return CM; + } + + return ModuleModel; +} + bool PPCSubtarget::isELFv2ABI() const { return TM.isELFv2ABI(); } bool PPCSubtarget::isPPC64() const { return TM.isPPC64(); } diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.h b/llvm/lib/Target/PowerPC/PPCSubtarget.h index 306a52dca8362bb4f0d25ea199a6c757cac1c324..bf35f8ec151b1038c4c27672a9bff5f783023abf 100644 --- a/llvm/lib/Target/PowerPC/PPCSubtarget.h +++ b/llvm/lib/Target/PowerPC/PPCSubtarget.h @@ -245,6 +245,10 @@ public: /// True if the GV will be accessed via an indirect symbol. bool isGVIndirectSymbol(const GlobalValue *GV) const; + /// Calculates the effective code model for argument GV. + CodeModel::Model getCodeModel(const TargetMachine &TM, + const GlobalValue *GV) const; + /// True if the ABI is descriptor based. bool usesFunctionDescriptors() const { // Both 32-bit and 64-bit AIX are descriptor based. For ELF only the 64-bit diff --git a/llvm/lib/Target/PowerPC/PPCTLSDynamicCall.cpp b/llvm/lib/Target/PowerPC/PPCTLSDynamicCall.cpp index 147438dfedd87d08020c7c3f29b3366b3a9988c3..9f680ef5046dadb3c45710b3db617c5d212e6749 100644 --- a/llvm/lib/Target/PowerPC/PPCTLSDynamicCall.cpp +++ b/llvm/lib/Target/PowerPC/PPCTLSDynamicCall.cpp @@ -25,6 +25,7 @@ #include "PPCInstrInfo.h" #include "PPCTargetMachine.h" #include "llvm/CodeGen/LiveIntervals.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/InitializePasses.h" @@ -159,9 +160,11 @@ protected: // We don't really need to save data to the stack - the clobbered // registers are already saved when the SDNode (e.g. PPCaddiTlsgdLAddr) // gets translated to the pseudo instruction (e.g. ADDItlsgdLADDR). - if (NeedFence) + if (NeedFence) { + MBB.getParent()->getFrameInfo().setAdjustsStack(true); BuildMI(MBB, I, DL, TII->get(PPC::ADJCALLSTACKDOWN)).addImm(0) .addImm(0); + } if (IsAIX) { if (IsTLSLDAIXMI) { diff --git a/llvm/lib/Target/PowerPC/PPCTOCRegDeps.cpp b/llvm/lib/Target/PowerPC/PPCTOCRegDeps.cpp index 81f078ab246e6ab0bf2d2c0cb12f9ee18faf8afd..0527991b58ba81d01f6103dc728efdca4de97617 100644 --- a/llvm/lib/Target/PowerPC/PPCTOCRegDeps.cpp +++ b/llvm/lib/Target/PowerPC/PPCTOCRegDeps.cpp @@ -94,8 +94,7 @@ namespace { protected: bool hasTOCLoReloc(const MachineInstr &MI) { - if (MI.getOpcode() == PPC::LDtocL || - MI.getOpcode() == PPC::ADDItocL || + if (MI.getOpcode() == PPC::LDtocL || MI.getOpcode() == PPC::ADDItocL8 || MI.getOpcode() == PPC::LWZtocL) return true; diff --git a/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp b/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp index 7adf1adcc647680c90a8a7259925dace83810020..57e1019adb7410f2c19e1da91b77e9a480fb674c 100644 --- a/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp @@ -219,7 +219,7 @@ InstructionCost PPCTTIImpl::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, return TTI::TCC_Free; break; case Intrinsic::experimental_patchpoint_void: - case Intrinsic::experimental_patchpoint_i64: + case Intrinsic::experimental_patchpoint: if ((Idx < 4) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue()))) return TTI::TCC_Free; break; diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index d83979a873f2a313c45982096efc005bbd26cc7f..123b37442329f8607e25019bdc596290d92f0442 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -107,6 +107,7 @@ class RISCVAsmParser : public MCTargetAsmParser { uint64_t &ErrorInfo, bool MatchingInlineAsm) override; + MCRegister matchRegisterNameHelper(StringRef Name) const; bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override; ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override; @@ -212,7 +213,11 @@ class RISCVAsmParser : public MCTargetAsmParser { ParseStatus parseReglist(OperandVector &Operands); ParseStatus parseRegReg(OperandVector &Operands); ParseStatus parseRetval(OperandVector &Operands); - ParseStatus parseZcmpSpimm(OperandVector &Operands); + ParseStatus parseZcmpStackAdj(OperandVector &Operands, + bool ExpectNegative = false); + ParseStatus parseZcmpNegStackAdj(OperandVector &Operands) { + return parseZcmpStackAdj(Operands, /*ExpectNegative*/ true); + } bool parseOperand(OperandVector &Operands, StringRef Mnemonic); @@ -976,9 +981,9 @@ public: return Imm.IsRV64; } - unsigned getReg() const override { + MCRegister getReg() const override { assert(Kind == KindTy::Register && "Invalid type access!"); - return Reg.RegNum.id(); + return Reg.RegNum; } StringRef getSysReg() const { @@ -1061,7 +1066,7 @@ public: break; case KindTy::Spimm: OS << "<Spimm: "; - RISCVZC::printSpimm(Spimm.Val, OS); + OS << Spimm.Val; OS << '>'; break; case KindTy::RegReg: @@ -1607,7 +1612,7 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, ErrorLoc, "operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}"); } - case Match_InvalidSpimm: { + case Match_InvalidStackAdj: { SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); return Error( ErrorLoc, @@ -1630,7 +1635,7 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, // alternative ABI names), setting RegNo to the matching register. Upon // failure, returns a non-valid MCRegister. If IsRVE, then registers x16-x31 // will be rejected. -static MCRegister matchRegisterNameHelper(bool IsRVE, StringRef Name) { +MCRegister RISCVAsmParser::matchRegisterNameHelper(StringRef Name) const { MCRegister Reg = MatchRegisterName(Name); // The 16-/32- and 64-bit FPRs have the same asm name. Check that the initial // match always matches the 64-bit variant, and not the 16/32-bit one. @@ -1641,7 +1646,7 @@ static MCRegister matchRegisterNameHelper(bool IsRVE, StringRef Name) { static_assert(RISCV::F0_D < RISCV::F0_F, "FPR matching must be updated"); if (!Reg) Reg = MatchRegisterAltName(Name); - if (IsRVE && Reg >= RISCV::X16 && Reg <= RISCV::X31) + if (isRVE() && Reg >= RISCV::X16 && Reg <= RISCV::X31) Reg = RISCV::NoRegister; return Reg; } @@ -1660,7 +1665,7 @@ ParseStatus RISCVAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc, EndLoc = Tok.getEndLoc(); StringRef Name = getLexer().getTok().getIdentifier(); - Reg = matchRegisterNameHelper(isRVE(), Name); + Reg = matchRegisterNameHelper(Name); if (!Reg) return ParseStatus::NoMatch; @@ -1693,7 +1698,7 @@ ParseStatus RISCVAsmParser::parseRegister(OperandVector &Operands, return ParseStatus::NoMatch; case AsmToken::Identifier: StringRef Name = getLexer().getTok().getIdentifier(); - MCRegister RegNo = matchRegisterNameHelper(isRVE(), Name); + MCRegister RegNo = matchRegisterNameHelper(Name); if (!RegNo) { if (HadParens) @@ -2232,7 +2237,7 @@ ParseStatus RISCVAsmParser::parseMaskReg(OperandVector &Operands) { StringRef Name = getLexer().getTok().getIdentifier(); if (!Name.consume_back(".t")) return Error(getLoc(), "expected '.t' suffix"); - MCRegister RegNo = matchRegisterNameHelper(isRVE(), Name); + MCRegister RegNo = matchRegisterNameHelper(Name); if (!RegNo) return ParseStatus::NoMatch; @@ -2250,7 +2255,7 @@ ParseStatus RISCVAsmParser::parseGPRAsFPR(OperandVector &Operands) { return ParseStatus::NoMatch; StringRef Name = getLexer().getTok().getIdentifier(); - MCRegister RegNo = matchRegisterNameHelper(isRVE(), Name); + MCRegister RegNo = matchRegisterNameHelper(Name); if (!RegNo) return ParseStatus::NoMatch; @@ -2281,7 +2286,7 @@ ParseStatus RISCVAsmParser::parseGPRPair(OperandVector &Operands, return ParseStatus::NoMatch; StringRef Name = getLexer().getTok().getIdentifier(); - MCRegister RegNo = matchRegisterNameHelper(isRVE(), Name); + MCRegister RegNo = matchRegisterNameHelper(Name); if (!RegNo) return ParseStatus::NoMatch; @@ -2461,7 +2466,7 @@ ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) { return ParseStatus::NoMatch; StringRef RegName = getLexer().getTok().getIdentifier(); - MCRegister Reg = matchRegisterNameHelper(isRVE(), RegName); + MCRegister Reg = matchRegisterNameHelper(RegName); if (!Reg) return Error(getLoc(), "invalid register"); getLexer().Lex(); @@ -2473,7 +2478,7 @@ ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) { return Error(getLoc(), "expected register"); StringRef Reg2Name = getLexer().getTok().getIdentifier(); - MCRegister Reg2 = matchRegisterNameHelper(isRVE(), Reg2Name); + MCRegister Reg2 = matchRegisterNameHelper(Reg2Name); if (!Reg2) return Error(getLoc(), "invalid register"); getLexer().Lex(); @@ -2500,7 +2505,7 @@ ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) { return Error(getLoc(), "register list must start from 'ra' or 'x1'"); StringRef RegName = getLexer().getTok().getIdentifier(); - MCRegister RegStart = matchRegisterNameHelper(IsEABI, RegName); + MCRegister RegStart = matchRegisterNameHelper(RegName); MCRegister RegEnd; if (RegStart != RISCV::X1) return Error(getLoc(), "register list must start from 'ra' or 'x1'"); @@ -2511,7 +2516,7 @@ ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) { if (getLexer().isNot(AsmToken::Identifier)) return Error(getLoc(), "invalid register"); StringRef RegName = getLexer().getTok().getIdentifier(); - RegStart = matchRegisterNameHelper(IsEABI, RegName); + RegStart = matchRegisterNameHelper(RegName); if (!RegStart) return Error(getLoc(), "invalid register"); if (RegStart != RISCV::X8) @@ -2524,7 +2529,7 @@ ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) { if (parseOptionalToken(AsmToken::Minus)) { StringRef EndName = getLexer().getTok().getIdentifier(); // FIXME: the register mapping and checks of EABI is wrong - RegEnd = matchRegisterNameHelper(IsEABI, EndName); + RegEnd = matchRegisterNameHelper(EndName); if (!RegEnd) return Error(getLoc(), "invalid register"); if (IsEABI && RegEnd != RISCV::X9) @@ -2575,15 +2580,16 @@ ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) { RegEnd = RegStart; auto Encode = RISCVZC::encodeRlist(RegEnd, IsEABI); - if (Encode == 16) + if (Encode == RISCVZC::INVALID_RLIST) return Error(S, "invalid register list"); Operands.push_back(RISCVOperand::createRlist(Encode, S)); return ParseStatus::Success; } -ParseStatus RISCVAsmParser::parseZcmpSpimm(OperandVector &Operands) { - (void)parseOptionalToken(AsmToken::Minus); +ParseStatus RISCVAsmParser::parseZcmpStackAdj(OperandVector &Operands, + bool ExpectNegative) { + bool Negative = parseOptionalToken(AsmToken::Minus); SMLoc S = getLoc(); int64_t StackAdjustment = getLexer().getTok().getIntVal(); @@ -2591,7 +2597,8 @@ ParseStatus RISCVAsmParser::parseZcmpSpimm(OperandVector &Operands) { unsigned RlistVal = static_cast<RISCVOperand *>(Operands[1].get())->Rlist.Val; bool IsEABI = isRVE(); - if (!RISCVZC::getSpimm(RlistVal, Spimm, StackAdjustment, isRV64(), IsEABI)) + if (Negative != ExpectNegative || + !RISCVZC::getSpimm(RlistVal, Spimm, StackAdjustment, isRV64(), IsEABI)) return ParseStatus::NoMatch; Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S)); getLexer().Lex(); @@ -2716,7 +2723,7 @@ ParseStatus RISCVAsmParser::parseDirective(AsmToken DirectiveID) { bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result, bool FromOptionDirective) { - for (auto Feature : RISCVFeatureKV) + for (auto &Feature : RISCVFeatureKV) if (llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature.Key)) clearFeatureBits(Feature.Value, Feature.Key); @@ -2735,7 +2742,7 @@ bool RISCVAsmParser::resetToArch(StringRef Arch, SMLoc Loc, std::string &Result, } auto &ISAInfo = *ParseResult; - for (auto Feature : RISCVFeatureKV) + for (auto &Feature : RISCVFeatureKV) if (ISAInfo->hasExtension(Feature.Key)) setFeatureBits(Feature.Value, Feature.Key); @@ -2823,9 +2830,8 @@ bool RISCVAsmParser::parseDirectiveOption() { break; } - ArrayRef<SubtargetFeatureKV> KVArray(RISCVFeatureKV); - auto Ext = llvm::lower_bound(KVArray, Arch); - if (Ext == KVArray.end() || StringRef(Ext->Key) != Arch || + auto Ext = llvm::lower_bound(RISCVFeatureKV, Arch); + if (Ext == std::end(RISCVFeatureKV) || StringRef(Ext->Key) != Arch || !RISCVISAInfo::isSupportedExtension(Arch)) { if (isDigit(Arch.back())) return Error( @@ -2858,7 +2864,7 @@ bool RISCVAsmParser::parseDirectiveOption() { // It is invalid to disable an extension that there are other enabled // extensions depend on it. // TODO: Make use of RISCVISAInfo to handle this - for (auto Feature : KVArray) { + for (auto &Feature : RISCVFeatureKV) { if (getSTI().hasFeature(Feature.Value) && Feature.Implies.test(Ext->Value)) return Error(Loc, @@ -3081,34 +3087,11 @@ void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) { void RISCVAsmParser::emitLoadImm(MCRegister DestReg, int64_t Value, MCStreamer &Out) { - RISCVMatInt::InstSeq Seq = RISCVMatInt::generateInstSeq(Value, getSTI()); - - MCRegister SrcReg = RISCV::X0; - for (const RISCVMatInt::Inst &Inst : Seq) { - switch (Inst.getOpndKind()) { - case RISCVMatInt::Imm: - emitToStreamer(Out, - MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addImm(Inst.getImm())); - break; - case RISCVMatInt::RegX0: - emitToStreamer( - Out, MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addReg(SrcReg).addReg( - RISCV::X0)); - break; - case RISCVMatInt::RegReg: - emitToStreamer( - Out, MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addReg(SrcReg).addReg( - SrcReg)); - break; - case RISCVMatInt::RegImm: - emitToStreamer( - Out, MCInstBuilder(Inst.getOpcode()).addReg(DestReg).addReg(SrcReg).addImm( - Inst.getImm())); - break; - } + SmallVector<MCInst, 8> Seq; + RISCVMatInt::generateMCInstSeq(Value, getSTI(), DestReg, Seq); - // Only the first instruction has X0 as its source. - SrcReg = DestReg; + for (MCInst &Inst : Seq) { + emitToStreamer(Out, Inst); } } @@ -3271,11 +3254,13 @@ void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(1)) .addOperand(Inst.getOperand(2)) - .addReg(RISCV::NoRegister)); + .addReg(RISCV::NoRegister) + .setLoc(IDLoc)); emitToStreamer(Out, MCInstBuilder(RISCV::VMNAND_MM) .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(0)) - .addOperand(Inst.getOperand(0))); + .addOperand(Inst.getOperand(0)) + .setLoc(IDLoc)); } else if (Inst.getNumOperands() == 4) { // masked va >= x, vd != v0 // @@ -3287,11 +3272,13 @@ void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(1)) .addOperand(Inst.getOperand(2)) - .addOperand(Inst.getOperand(3))); + .addOperand(Inst.getOperand(3)) + .setLoc(IDLoc)); emitToStreamer(Out, MCInstBuilder(RISCV::VMXOR_MM) .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(0)) - .addReg(RISCV::V0)); + .addReg(RISCV::V0) + .setLoc(IDLoc)); } else if (Inst.getNumOperands() == 5 && Inst.getOperand(0).getReg() == RISCV::V0) { // masked va >= x, vd == v0 @@ -3306,11 +3293,13 @@ void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, .addOperand(Inst.getOperand(1)) .addOperand(Inst.getOperand(2)) .addOperand(Inst.getOperand(3)) - .addReg(RISCV::NoRegister)); + .addReg(RISCV::NoRegister) + .setLoc(IDLoc)); emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM) .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(0)) - .addOperand(Inst.getOperand(1))); + .addOperand(Inst.getOperand(1)) + .setLoc(IDLoc)); } else if (Inst.getNumOperands() == 5) { // masked va >= x, any vd // @@ -3323,19 +3312,23 @@ void RISCVAsmParser::emitVMSGE(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, .addOperand(Inst.getOperand(1)) .addOperand(Inst.getOperand(2)) .addOperand(Inst.getOperand(3)) - .addReg(RISCV::NoRegister)); + .addReg(RISCV::NoRegister) + .setLoc(IDLoc)); emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM) .addOperand(Inst.getOperand(1)) .addReg(RISCV::V0) - .addOperand(Inst.getOperand(1))); + .addOperand(Inst.getOperand(1)) + .setLoc(IDLoc)); emitToStreamer(Out, MCInstBuilder(RISCV::VMANDN_MM) .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(0)) - .addReg(RISCV::V0)); + .addReg(RISCV::V0) + .setLoc(IDLoc)); emitToStreamer(Out, MCInstBuilder(RISCV::VMOR_MM) .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(1)) - .addOperand(Inst.getOperand(0))); + .addOperand(Inst.getOperand(0)) + .setLoc(IDLoc)); } } @@ -3637,7 +3630,8 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(1)) .addImm(Imm - 1) - .addOperand(Inst.getOperand(3))); + .addOperand(Inst.getOperand(3)) + .setLoc(IDLoc)); return false; } case RISCV::PseudoVMSGEU_VI: @@ -3655,7 +3649,8 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(1)) .addOperand(Inst.getOperand(1)) - .addOperand(Inst.getOperand(3))); + .addOperand(Inst.getOperand(3)) + .setLoc(IDLoc)); } else { // Other immediate values can subtract one like signed. unsigned Opc = Inst.getOpcode() == RISCV::PseudoVMSGEU_VI @@ -3665,7 +3660,8 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, .addOperand(Inst.getOperand(0)) .addOperand(Inst.getOperand(1)) .addImm(Imm - 1) - .addOperand(Inst.getOperand(3))); + .addOperand(Inst.getOperand(3)) + .setLoc(IDLoc)); } return false; diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp index f1ca1212ec378e83a72886b02ab7224b13d7b61c..6aadabdf1bc61a32316c721095620677b213f3ce 100644 --- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp +++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp @@ -595,6 +595,14 @@ DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size, TRY_TO_DECODE_FEATURE( RISCV::FeatureVendorXSfvfnrclipxfqf, DecoderTableXSfvfnrclipxfqf32, "SiFive FP32-to-int8 Ranged Clip Instructions opcode table"); + TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXSiFivecdiscarddlone, + DecoderTableXSiFivecdiscarddlone32, + "SiFive sf.cdiscard.d.l1 custom opcode table"); + TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXSiFivecflushdlone, + DecoderTableXSiFivecflushdlone32, + "SiFive sf.cflush.d.l1 custom opcode table"); + TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXSfcease, DecoderTableXSfcease32, + "SiFive sf.cease custom opcode table"); TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXCVbitmanip, DecoderTableXCVbitmanip32, "CORE-V Bit Manipulation custom opcode table"); diff --git a/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp b/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp index 45e19cdea300b191d6f9379a28e4380807bf8997..8af4bc658409d49cbfbcb0741275b336fc894fa1 100644 --- a/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp +++ b/llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp @@ -34,14 +34,15 @@ private: // Whether this is assigning args for a return. bool IsRet; - // true if assignArg has been called for a mask argument, false otherwise. - bool AssignedFirstMaskArg = false; + RVVArgDispatcher &RVVDispatcher; public: RISCVOutgoingValueAssigner( - RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet) + RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet, + RVVArgDispatcher &RVVDispatcher) : CallLowering::OutgoingValueAssigner(nullptr), - RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet) {} + RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet), + RVVDispatcher(RVVDispatcher) {} bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, @@ -51,16 +52,9 @@ public: const DataLayout &DL = MF.getDataLayout(); const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>(); - std::optional<unsigned> FirstMaskArgument; - if (Subtarget.hasVInstructions() && !AssignedFirstMaskArg && - ValVT.isVector() && ValVT.getVectorElementType() == MVT::i1) { - FirstMaskArgument = ValNo; - AssignedFirstMaskArg = true; - } - if (RISCVAssignFn(DL, Subtarget.getTargetABI(), ValNo, ValVT, LocVT, LocInfo, Flags, State, Info.IsFixed, IsRet, Info.Ty, - *Subtarget.getTargetLowering(), FirstMaskArgument)) + *Subtarget.getTargetLowering(), RVVDispatcher)) return true; StackSize = State.getStackSize(); @@ -181,14 +175,15 @@ private: // Whether this is assigning args from a return. bool IsRet; - // true if assignArg has been called for a mask argument, false otherwise. - bool AssignedFirstMaskArg = false; + RVVArgDispatcher &RVVDispatcher; public: RISCVIncomingValueAssigner( - RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet) + RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet, + RVVArgDispatcher &RVVDispatcher) : CallLowering::IncomingValueAssigner(nullptr), - RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet) {} + RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet), + RVVDispatcher(RVVDispatcher) {} bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, @@ -201,16 +196,9 @@ public: if (LocVT.isScalableVector()) MF.getInfo<RISCVMachineFunctionInfo>()->setIsVectorCall(); - std::optional<unsigned> FirstMaskArgument; - if (Subtarget.hasVInstructions() && !AssignedFirstMaskArg && - ValVT.isVector() && ValVT.getVectorElementType() == MVT::i1) { - FirstMaskArgument = ValNo; - AssignedFirstMaskArg = true; - } - if (RISCVAssignFn(DL, Subtarget.getTargetABI(), ValNo, ValVT, LocVT, LocInfo, Flags, State, /*IsFixed=*/true, IsRet, Info.Ty, - *Subtarget.getTargetLowering(), FirstMaskArgument)) + *Subtarget.getTargetLowering(), RVVDispatcher)) return true; StackSize = State.getStackSize(); @@ -420,9 +408,11 @@ bool RISCVCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder, SmallVector<ArgInfo, 4> SplitRetInfos; splitToValueTypes(OrigRetInfo, SplitRetInfos, DL, CC); + RVVArgDispatcher Dispatcher{&MF, getTLI<RISCVTargetLowering>(), + F.getReturnType()}; RISCVOutgoingValueAssigner Assigner( CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV, - /*IsRet=*/true); + /*IsRet=*/true, Dispatcher); RISCVOutgoingValueHandler Handler(MIRBuilder, MF.getRegInfo(), Ret); return determineAndHandleAssignments(Handler, Assigner, SplitRetInfos, MIRBuilder, CC, F.isVarArg()); @@ -531,6 +521,7 @@ bool RISCVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, CallingConv::ID CC = F.getCallingConv(); SmallVector<ArgInfo, 32> SplitArgInfos; + SmallVector<Type *, 4> TypeList; unsigned Index = 0; for (auto &Arg : F.args()) { // Construct the ArgInfo object from destination register and argument type. @@ -542,12 +533,15 @@ bool RISCVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, // correspondingly and appended to SplitArgInfos. splitToValueTypes(AInfo, SplitArgInfos, DL, CC); + TypeList.push_back(Arg.getType()); + ++Index; } + RVVArgDispatcher Dispatcher{&MF, getTLI<RISCVTargetLowering>(), TypeList}; RISCVIncomingValueAssigner Assigner( CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV, - /*IsRet=*/false); + /*IsRet=*/false, Dispatcher); RISCVFormalArgHandler Handler(MIRBuilder, MF.getRegInfo()); SmallVector<CCValAssign, 16> ArgLocs; @@ -585,11 +579,13 @@ bool RISCVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, SmallVector<ArgInfo, 32> SplitArgInfos; SmallVector<ISD::OutputArg, 8> Outs; + SmallVector<Type *, 4> TypeList; for (auto &AInfo : Info.OrigArgs) { // Handle any required unmerging of split value types from a given VReg into // physical registers. ArgInfo objects are constructed correspondingly and // appended to SplitArgInfos. splitToValueTypes(AInfo, SplitArgInfos, DL, CC); + TypeList.push_back(AInfo.Ty); } // TODO: Support tail calls. @@ -607,9 +603,10 @@ bool RISCVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); Call.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv)); + RVVArgDispatcher ArgDispatcher{&MF, getTLI<RISCVTargetLowering>(), TypeList}; RISCVOutgoingValueAssigner ArgAssigner( CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV, - /*IsRet=*/false); + /*IsRet=*/false, ArgDispatcher); RISCVOutgoingValueHandler ArgHandler(MIRBuilder, MF.getRegInfo(), Call); if (!determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgInfos, MIRBuilder, CC, Info.IsVarArg)) @@ -637,9 +634,11 @@ bool RISCVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, SmallVector<ArgInfo, 4> SplitRetInfos; splitToValueTypes(Info.OrigRet, SplitRetInfos, DL, CC); + RVVArgDispatcher RetDispatcher{&MF, getTLI<RISCVTargetLowering>(), + F.getReturnType()}; RISCVIncomingValueAssigner RetAssigner( CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV, - /*IsRet=*/true); + /*IsRet=*/true, RetDispatcher); RISCVCallReturnHandler RetHandler(MIRBuilder, MF.getRegInfo(), Call); if (!determineAndHandleAssignments(RetHandler, RetAssigner, SplitRetInfos, MIRBuilder, CC, Info.IsVarArg)) diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp index 5738f86e7e9ff5b218836fcfe13b74a31782c0ef..3103992a86c0993f2edc59a5d05e36af1774a1db 100644 --- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp +++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp @@ -77,8 +77,6 @@ private: MachineRegisterInfo &MRI) const; bool selectFPCompare(MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI) const; - bool selectIntrinsicWithSideEffects(MachineInstr &MI, MachineIRBuilder &MIB, - MachineRegisterInfo &MRI) const; void emitFence(AtomicOrdering FenceOrdering, SyncScope::ID FenceSSID, MachineIRBuilder &MIB) const; bool selectMergeValues(MachineInstr &MI, MachineIRBuilder &MIB, @@ -686,8 +684,6 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) { return selectSelect(MI, MIB, MRI); case TargetOpcode::G_FCMP: return selectFPCompare(MI, MIB, MRI); - case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: - return selectIntrinsicWithSideEffects(MI, MIB, MRI); case TargetOpcode::G_FENCE: { AtomicOrdering FenceOrdering = static_cast<AtomicOrdering>(MI.getOperand(0).getImm()); @@ -1255,29 +1251,6 @@ bool RISCVInstructionSelector::selectFPCompare(MachineInstr &MI, return true; } -bool RISCVInstructionSelector::selectIntrinsicWithSideEffects( - MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI) const { - assert(MI.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS && - "Unexpected opcode"); - // Find the intrinsic ID. - unsigned IntrinID = cast<GIntrinsic>(MI).getIntrinsicID(); - - // Select the instruction. - switch (IntrinID) { - default: - return false; - case Intrinsic::trap: - MIB.buildInstr(RISCV::UNIMP, {}, {}); - break; - case Intrinsic::debugtrap: - MIB.buildInstr(RISCV::EBREAK, {}, {}); - break; - } - - MI.eraseFromParent(); - return true; -} - void RISCVInstructionSelector::emitFence(AtomicOrdering FenceOrdering, SyncScope::ID FenceSSID, MachineIRBuilder &MIB) const { diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp index 64ae4e94a8c9296169c9c2b40afd7e9eedaf5101..7f3510727dbceaf0d213254cf74e71fca03e3246 100644 --- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp +++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp @@ -40,6 +40,32 @@ static LegalityPredicate typeIsScalarFPArith(unsigned TypeIdx, }; } +static LegalityPredicate +typeIsLegalIntOrFPVec(unsigned TypeIdx, + std::initializer_list<LLT> IntOrFPVecTys, + const RISCVSubtarget &ST) { + LegalityPredicate P = [=, &ST](const LegalityQuery &Query) { + return ST.hasVInstructions() && + (Query.Types[TypeIdx].getScalarSizeInBits() != 64 || + ST.hasVInstructionsI64()) && + (Query.Types[TypeIdx].getElementCount().getKnownMinValue() != 1 || + ST.getELen() == 64); + }; + + return all(typeInSet(TypeIdx, IntOrFPVecTys), P); +} + +static LegalityPredicate +typeIsLegalBoolVec(unsigned TypeIdx, std::initializer_list<LLT> BoolVecTys, + const RISCVSubtarget &ST) { + LegalityPredicate P = [=, &ST](const LegalityQuery &Query) { + return ST.hasVInstructions() && + (Query.Types[TypeIdx].getElementCount().getKnownMinValue() != 1 || + ST.getELen() == 64); + }; + return all(typeInSet(TypeIdx, BoolVecTys), P); +} + RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) : STI(ST), XLen(STI.getXLen()), sXLen(LLT::scalar(XLen)) { const LLT sDoubleXLen = LLT::scalar(2 * XLen); @@ -50,6 +76,14 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) const LLT s32 = LLT::scalar(32); const LLT s64 = LLT::scalar(64); + const LLT nxv1s1 = LLT::scalable_vector(1, s1); + const LLT nxv2s1 = LLT::scalable_vector(2, s1); + const LLT nxv4s1 = LLT::scalable_vector(4, s1); + const LLT nxv8s1 = LLT::scalable_vector(8, s1); + const LLT nxv16s1 = LLT::scalable_vector(16, s1); + const LLT nxv32s1 = LLT::scalable_vector(32, s1); + const LLT nxv64s1 = LLT::scalable_vector(64, s1); + const LLT nxv1s8 = LLT::scalable_vector(1, s8); const LLT nxv2s8 = LLT::scalable_vector(2, s8); const LLT nxv4s8 = LLT::scalable_vector(4, s8); @@ -78,22 +112,16 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) using namespace TargetOpcode; - auto AllVecTys = {nxv1s8, nxv2s8, nxv4s8, nxv8s8, nxv16s8, nxv32s8, - nxv64s8, nxv1s16, nxv2s16, nxv4s16, nxv8s16, nxv16s16, - nxv32s16, nxv1s32, nxv2s32, nxv4s32, nxv8s32, nxv16s32, - nxv1s64, nxv2s64, nxv4s64, nxv8s64}; + auto BoolVecTys = {nxv1s1, nxv2s1, nxv4s1, nxv8s1, nxv16s1, nxv32s1, nxv64s1}; + + auto IntOrFPVecTys = {nxv1s8, nxv2s8, nxv4s8, nxv8s8, nxv16s8, nxv32s8, + nxv64s8, nxv1s16, nxv2s16, nxv4s16, nxv8s16, nxv16s16, + nxv32s16, nxv1s32, nxv2s32, nxv4s32, nxv8s32, nxv16s32, + nxv1s64, nxv2s64, nxv4s64, nxv8s64}; getActionDefinitionsBuilder({G_ADD, G_SUB, G_AND, G_OR, G_XOR}) .legalFor({s32, sXLen}) - .legalIf(all( - typeInSet(0, AllVecTys), - LegalityPredicate([=, &ST](const LegalityQuery &Query) { - return ST.hasVInstructions() && - (Query.Types[0].getScalarSizeInBits() != 64 || - ST.hasVInstructionsI64()) && - (Query.Types[0].getElementCount().getKnownMinValue() != 1 || - ST.getELen() == 64); - }))) + .legalIf(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST)) .widenScalarToNextPow2(0) .clampScalar(0, s32, sXLen); @@ -155,6 +183,12 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) getActionDefinitionsBuilder(G_BITREVERSE).maxScalar(0, sXLen).lower(); + getActionDefinitionsBuilder(G_BITCAST).legalIf( + all(LegalityPredicates::any(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST), + typeIsLegalBoolVec(0, BoolVecTys, ST)), + LegalityPredicates::any(typeIsLegalIntOrFPVec(1, IntOrFPVecTys, ST), + typeIsLegalBoolVec(1, BoolVecTys, ST)))); + auto &BSWAPActions = getActionDefinitionsBuilder(G_BSWAP); if (ST.hasStdExtZbb() || ST.hasStdExtZbkb()) BSWAPActions.legalFor({sXLen}).clampScalar(0, sXLen, sXLen); @@ -191,8 +225,11 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) ConstantActions.customFor({s64}); ConstantActions.widenScalarToNextPow2(0).clampScalar(0, s32, sXLen); + // TODO: transform illegal vector types into legal vector type getActionDefinitionsBuilder(G_IMPLICIT_DEF) .legalFor({s32, sXLen, p0}) + .legalIf(typeIsLegalBoolVec(0, BoolVecTys, ST)) + .legalIf(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST)) .widenScalarToNextPow2(0) .clampScalar(0, s32, sXLen); @@ -202,8 +239,11 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) .clampScalar(1, sXLen, sXLen) .clampScalar(0, sXLen, sXLen); - auto &SelectActions = getActionDefinitionsBuilder(G_SELECT).legalFor( - {{s32, sXLen}, {p0, sXLen}}); + auto &SelectActions = + getActionDefinitionsBuilder(G_SELECT) + .legalFor({{s32, sXLen}, {p0, sXLen}}) + .legalIf(all(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST), + typeIsLegalBoolVec(1, BoolVecTys, ST))); if (XLen == 64 || ST.hasStdExtD()) SelectActions.legalFor({{s64, sXLen}}); SelectActions.widenScalarToNextPow2(0) @@ -374,6 +414,10 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) .clampScalar(0, s32, sXLen) .lowerForCartesianProduct({s32, sXLen, p0}, {p0}); + getActionDefinitionsBuilder(G_VSCALE) + .clampScalar(0, sXLen, sXLen) + .customFor({sXLen}); + getLegacyLegalizerInfo().computeTables(); } @@ -412,7 +456,7 @@ bool RISCVLegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper, // Store the result in the destination va_list MachineMemOperand *StoreMMO = MF.getMachineMemOperand( MachinePointerInfo(), MachineMemOperand::MOStore, PtrTy, Alignment); - MIRBuilder.buildStore(DstLst, Tmp, *StoreMMO); + MIRBuilder.buildStore(Tmp, DstLst, *StoreMMO); MI.eraseFromParent(); return true; @@ -495,6 +539,48 @@ bool RISCVLegalizerInfo::shouldBeInConstantPool(APInt APImm, return !(!SeqLo.empty() && (SeqLo.size() + 2) <= STI.getMaxBuildIntsCost()); } +bool RISCVLegalizerInfo::legalizeVScale(MachineInstr &MI, + MachineIRBuilder &MIB) const { + const LLT XLenTy(STI.getXLenVT()); + Register Dst = MI.getOperand(0).getReg(); + + // We define our scalable vector types for lmul=1 to use a 64 bit known + // minimum size. e.g. <vscale x 2 x i32>. VLENB is in bytes so we calculate + // vscale as VLENB / 8. + static_assert(RISCV::RVVBitsPerBlock == 64, "Unexpected bits per block!"); + if (STI.getRealMinVLen() < RISCV::RVVBitsPerBlock) + // Support for VLEN==32 is incomplete. + return false; + + // We assume VLENB is a multiple of 8. We manually choose the best shift + // here because SimplifyDemandedBits isn't always able to simplify it. + uint64_t Val = MI.getOperand(1).getCImm()->getZExtValue(); + if (isPowerOf2_64(Val)) { + uint64_t Log2 = Log2_64(Val); + if (Log2 < 3) { + auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {}); + MIB.buildLShr(Dst, VLENB, MIB.buildConstant(XLenTy, 3 - Log2)); + } else if (Log2 > 3) { + auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {}); + MIB.buildShl(Dst, VLENB, MIB.buildConstant(XLenTy, Log2 - 3)); + } else { + MIB.buildInstr(RISCV::G_READ_VLENB, {Dst}, {}); + } + } else if ((Val % 8) == 0) { + // If the multiplier is a multiple of 8, scale it down to avoid needing + // to shift the VLENB value. + auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {}); + MIB.buildMul(Dst, VLENB, MIB.buildConstant(XLenTy, Val / 8)); + } else { + auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {}); + auto VScale = MIB.buildLShr(XLenTy, VLENB, MIB.buildConstant(XLenTy, 3)); + MIB.buildMul(Dst, VScale, MIB.buildConstant(XLenTy, Val)); + } + + MI.eraseFromParent(); + return true; +} + bool RISCVLegalizerInfo::legalizeCustom( LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const { @@ -552,6 +638,8 @@ bool RISCVLegalizerInfo::legalizeCustom( } case TargetOpcode::G_VASTART: return legalizeVAStart(MI, MIRBuilder); + case TargetOpcode::G_VSCALE: + return legalizeVScale(MI, MIRBuilder); } llvm_unreachable("expected switch to return"); diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h index 323426034827e46b923d3792574d56c29e854141..e2a98c8d2c736c5b340fed845e9a9a1162821e09 100644 --- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h +++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.h @@ -42,6 +42,7 @@ private: GISelChangeObserver &Observer) const; bool legalizeVAStart(MachineInstr &MI, MachineIRBuilder &MIRBuilder) const; + bool legalizeVScale(MachineInstr &MI, MachineIRBuilder &MIB) const; }; } // end namespace llvm #endif diff --git a/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp index 58c971aee2f4c8fc726691aaa8e826c0d4a86f0f..888bcc46ea1ef92024e7f2d02e7ea26ce4576f90 100644 --- a/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp +++ b/llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp @@ -13,6 +13,7 @@ #include "RISCVRegisterBankInfo.h" #include "MCTargetDesc/RISCVMCTargetDesc.h" #include "RISCVSubtarget.h" +#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterBank.h" #include "llvm/CodeGen/RegisterBankInfo.h" @@ -343,6 +344,8 @@ RISCVRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { } case TargetOpcode::G_IMPLICIT_DEF: { Register Dst = MI.getOperand(0).getReg(); + LLT DstTy = MRI.getType(Dst); + uint64_t DstMinSize = DstTy.getSizeInBits().getKnownMinValue(); auto Mapping = GPRValueMapping; // FIXME: May need to do a better job determining when to use FPRB. // For example, the look through COPY case: @@ -350,7 +353,11 @@ RISCVRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { // %1:_(s32) = COPY %0 // $f10_d = COPY %1(s32) if (anyUseOnlyUseFP(Dst, MRI, TRI)) - Mapping = getFPValueMapping(MRI.getType(Dst).getSizeInBits()); + Mapping = getFPValueMapping(DstMinSize); + + if (DstTy.isVector()) + Mapping = getVRBValueMapping(DstMinSize); + return getInstructionMapping(DefaultMappingID, /*Cost=*/1, Mapping, NumOperands); } @@ -401,6 +408,17 @@ RISCVRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { case TargetOpcode::G_SELECT: { LLT Ty = MRI.getType(MI.getOperand(0).getReg()); + if (Ty.isVector()) { + auto &Sel = cast<GSelect>(MI); + LLT TestTy = MRI.getType(Sel.getCondReg()); + assert(TestTy.isVector() && "Unexpected condition argument type"); + OpdsMapping[0] = OpdsMapping[2] = OpdsMapping[3] = + getVRBValueMapping(Ty.getSizeInBits().getKnownMinValue()); + OpdsMapping[1] = + getVRBValueMapping(TestTy.getSizeInBits().getKnownMinValue()); + break; + } + // Try to minimize the number of copies. If we have more floating point // constrained values than not, then we'll put everything on FPR. Otherwise, // everything has to be on GPR. diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp index 61f8e71710377eeffa764f8d9fecb20ea40060f6..5d9a58babe606c3cc732fe085b36607924096853 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp @@ -236,6 +236,4 @@ void RISCVZC::printRlist(unsigned SlistEncode, raw_ostream &OS) { OS << "}"; } -void RISCVZC::printSpimm(int64_t Spimm, raw_ostream &OS) { OS << Spimm; } - } // namespace llvm diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h index 6d0381c30d3e8612ca7f46903cf9f2b6cb671edf..92f405b5f6acbf82bf4aa7fa6e9cad3c1ab319e2 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h @@ -297,7 +297,8 @@ enum OperandType : unsigned { OPERAND_RVKRNUM_0_7, OPERAND_RVKRNUM_1_10, OPERAND_RVKRNUM_2_14, - OPERAND_LAST_RISCV_IMM = OPERAND_RVKRNUM_2_14, + OPERAND_SPIMM, + OPERAND_LAST_RISCV_IMM = OPERAND_SPIMM, // Operand is either a register or uimm5, this is used by V extension pseudo // instructions to represent a value that be passed as AVL to either vsetvli // or vsetivli. @@ -580,15 +581,17 @@ inline static bool getSpimm(unsigned RlistVal, unsigned &SpimmVal, int64_t StackAdjustment, bool IsRV64, bool IsEABI) { if (RlistVal == RLISTENCODE::INVALID_RLIST) return false; - unsigned stackAdj = getStackAdjBase(RlistVal, IsRV64, IsEABI); - SpimmVal = (StackAdjustment - stackAdj) / 16; + unsigned StackAdjBase = getStackAdjBase(RlistVal, IsRV64, IsEABI); + StackAdjustment -= StackAdjBase; + if (StackAdjustment % 16 != 0) + return false; + SpimmVal = StackAdjustment / 16; if (SpimmVal > 3) return false; return true; } void printRlist(unsigned SlistEncode, raw_ostream &OS); -void printSpimm(int64_t Spimm, raw_ostream &OS); } // namespace RISCVZC } // namespace llvm diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp index bd899495812f444f0a9d3fb9eb7ec5543f3d6aff..04e02e9fa0ab736ab8b0c64456d425941f7255ab 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp @@ -292,24 +292,25 @@ void RISCVInstPrinter::printRegReg(const MCInst *MI, unsigned OpNo, O << ")"; } -void RISCVInstPrinter::printSpimm(const MCInst *MI, unsigned OpNo, - const MCSubtargetInfo &STI, raw_ostream &O) { +void RISCVInstPrinter::printStackAdj(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, raw_ostream &O, + bool Negate) { int64_t Imm = MI->getOperand(OpNo).getImm(); - unsigned Opcode = MI->getOpcode(); bool IsRV64 = STI.hasFeature(RISCV::Feature64Bit); bool IsEABI = STI.hasFeature(RISCV::FeatureRVE); - int64_t Spimm = 0; + int64_t StackAdj = 0; auto RlistVal = MI->getOperand(0).getImm(); assert(RlistVal != 16 && "Incorrect rlist."); auto Base = RISCVZC::getStackAdjBase(RlistVal, IsRV64, IsEABI); - Spimm = Imm + Base; - assert((Spimm >= Base && Spimm <= Base + 48) && "Incorrect spimm"); - if (Opcode == RISCV::CM_PUSH) - Spimm = -Spimm; + StackAdj = Imm + Base; + assert((StackAdj >= Base && StackAdj <= Base + 48) && + "Incorrect stack adjust"); + if (Negate) + StackAdj = -StackAdj; // RAII guard for ANSI color escape sequences WithMarkup ScopedMarkup = markup(O, Markup::Immediate); - RISCVZC::printSpimm(Spimm, O); + O << StackAdj; } void RISCVInstPrinter::printVMaskReg(const MCInst *MI, unsigned OpNo, diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h index 4512bd5f4c4b7a238188d759cecf07c9360880cd..77cc7a67e88920d16a70732166a3c0841f34378a 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h @@ -52,8 +52,13 @@ public: const MCSubtargetInfo &STI, raw_ostream &O); void printRlist(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O); - void printSpimm(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, - raw_ostream &O); + void printStackAdj(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, raw_ostream &O, + bool Negate = false); + void printNegStackAdj(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, raw_ostream &O) { + return printStackAdj(MI, OpNo, STI, O, /*Negate*/ true); + } void printRegReg(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O); // Autogenerated by tblgen. diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp index 254a9a4bc0ef0b174a70dd35570d92821874b8ba..b8e0f3a867f402a3c9fcaf28d26f977bdf57558e 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp @@ -207,8 +207,6 @@ void RISCVMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { case VK_RISCV_TLS_GOT_HI: case VK_RISCV_TLS_GD_HI: case VK_RISCV_TLSDESC_HI: - case VK_RISCV_TLSDESC_ADD_LO: - case VK_RISCV_TLSDESC_LOAD_LO: break; } diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp index 4358a5b878e6316a252fcfc244832d0525d35439..c3bae152993ea49e52dd14716986366932efde5c 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp @@ -9,6 +9,7 @@ #include "RISCVMatInt.h" #include "MCTargetDesc/RISCVMCTargetDesc.h" #include "llvm/ADT/APInt.h" +#include "llvm/MC/MCInstBuilder.h" #include "llvm/Support/MathExtras.h" using namespace llvm; @@ -436,6 +437,43 @@ InstSeq generateInstSeq(int64_t Val, const MCSubtargetInfo &STI) { return Res; } +void generateMCInstSeq(int64_t Val, const MCSubtargetInfo &STI, + MCRegister DestReg, SmallVectorImpl<MCInst> &Insts) { + RISCVMatInt::InstSeq Seq = RISCVMatInt::generateInstSeq(Val, STI); + + MCRegister SrcReg = RISCV::X0; + for (RISCVMatInt::Inst &Inst : Seq) { + switch (Inst.getOpndKind()) { + case RISCVMatInt::Imm: + Insts.push_back(MCInstBuilder(Inst.getOpcode()) + .addReg(DestReg) + .addImm(Inst.getImm())); + break; + case RISCVMatInt::RegX0: + Insts.push_back(MCInstBuilder(Inst.getOpcode()) + .addReg(DestReg) + .addReg(SrcReg) + .addReg(RISCV::X0)); + break; + case RISCVMatInt::RegReg: + Insts.push_back(MCInstBuilder(Inst.getOpcode()) + .addReg(DestReg) + .addReg(SrcReg) + .addReg(SrcReg)); + break; + case RISCVMatInt::RegImm: + Insts.push_back(MCInstBuilder(Inst.getOpcode()) + .addReg(DestReg) + .addReg(SrcReg) + .addImm(Inst.getImm())); + break; + } + + // Only the first instruction has X0 as its source. + SrcReg = DestReg; + } +} + InstSeq generateTwoRegInstSeq(int64_t Val, const MCSubtargetInfo &STI, unsigned &ShiftAmt, unsigned &AddOpc) { int64_t LoVal = SignExtend64<32>(Val); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.h index 780f685463f300448bcdb8177e755313b163445f..e87e0f325647098223b31ae59adb89be567b958f 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.h +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.h @@ -10,6 +10,7 @@ #define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_MATINT_H #include "llvm/ADT/SmallVector.h" +#include "llvm/MC/MCRegister.h" #include "llvm/MC/MCSubtargetInfo.h" #include <cstdint> @@ -48,6 +49,10 @@ using InstSeq = SmallVector<Inst, 8>; // instruction selection. InstSeq generateInstSeq(int64_t Val, const MCSubtargetInfo &STI); +// Helper to generate the generateInstSeq instruction sequence using MCInsts +void generateMCInstSeq(int64_t Val, const MCSubtargetInfo &STI, + MCRegister DestReg, SmallVectorImpl<MCInst> &Insts); + // Helper to generate an instruction sequence that can materialize the given // immediate value into a register using an additional temporary register. This // handles cases where the constant can be generated by (ADD (SLLI X, C), X) or diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td index 575bd4c9d3561df345688fcc3cbe5e6e484f6d09..9fb84efd5b6f26d519478da49a830c409398f04e 100644 --- a/llvm/lib/Target/RISCV/RISCV.td +++ b/llvm/lib/Target/RISCV/RISCV.td @@ -24,8 +24,8 @@ include "RISCVSystemOperands.td" // Registers, calling conventions, instruction descriptions. //===----------------------------------------------------------------------===// -include "RISCVSchedule.td" include "RISCVRegisterInfo.td" +include "RISCVSchedule.td" include "RISCVCallingConv.td" include "RISCVInstrInfo.td" include "GISel/RISCVRegisterBanks.td" @@ -43,6 +43,7 @@ include "RISCVMacroFusion.td" include "RISCVSchedRocket.td" include "RISCVSchedSiFive7.td" include "RISCVSchedSiFiveP400.td" +include "RISCVSchedSiFiveP600.td" include "RISCVSchedSyntacoreSCR1.td" include "RISCVSchedXiangShanNanHu.td" diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp index cb82e74b1efacd94ee37380ce73d314d610dafc3..5bf594c0b5eae3ab2fd0b7173bc71bed013fdbfd 100644 --- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp +++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp @@ -100,7 +100,7 @@ public: bool emitDirectiveOptionArch(); private: - void emitAttributes(); + void emitAttributes(const MCSubtargetInfo &SubtargetInfo); void emitNTLHint(const MachineInstr *MI); @@ -385,8 +385,32 @@ void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) { if (const MDString *ModuleTargetABI = dyn_cast_or_null<MDString>(M.getModuleFlag("target-abi"))) RTS.setTargetABI(RISCVABI::getTargetABI(ModuleTargetABI->getString())); + + MCSubtargetInfo SubtargetInfo = *TM.getMCSubtargetInfo(); + + // Use module flag to update feature bits. + if (auto *MD = dyn_cast_or_null<MDNode>(M.getModuleFlag("riscv-isa"))) { + for (auto &ISA : MD->operands()) { + if (auto *ISAString = dyn_cast_or_null<MDString>(ISA)) { + auto ParseResult = llvm::RISCVISAInfo::parseArchString( + ISAString->getString(), /*EnableExperimentalExtension=*/true, + /*ExperimentalExtensionVersionCheck=*/true); + if (!errorToBool(ParseResult.takeError())) { + auto &ISAInfo = *ParseResult; + for (const auto &Feature : RISCVFeatureKV) { + if (ISAInfo->hasExtension(Feature.Key) && + !SubtargetInfo.hasFeature(Feature.Value)) + SubtargetInfo.ToggleFeature(Feature.Key); + } + } + } + } + + RTS.setFlagsFromFeatures(SubtargetInfo); + } + if (TM.getTargetTriple().isOSBinFormatELF()) - emitAttributes(); + emitAttributes(SubtargetInfo); } void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) { @@ -398,13 +422,13 @@ void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) { EmitHwasanMemaccessSymbols(M); } -void RISCVAsmPrinter::emitAttributes() { +void RISCVAsmPrinter::emitAttributes(const MCSubtargetInfo &SubtargetInfo) { RISCVTargetStreamer &RTS = static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer()); // Use MCSubtargetInfo from TargetMachine. Individual functions may have // attributes that differ from other functions in the module and we have no // way to know which function is correct. - RTS.emitTargetAttributes(*TM.getMCSubtargetInfo(), /*EmitStackAlign*/ true); + RTS.emitTargetAttributes(SubtargetInfo, /*EmitStackAlign*/ true); } void RISCVAsmPrinter::emitFunctionEntryLabel() { diff --git a/llvm/lib/Target/RISCV/RISCVCallingConv.td b/llvm/lib/Target/RISCV/RISCVCallingConv.td index 11b716f20f37166cdbb455d2c3917106cdfd7b88..ad06f47743770251328cc397716f8297076c69d8 100644 --- a/llvm/lib/Target/RISCV/RISCVCallingConv.td +++ b/llvm/lib/Target/RISCV/RISCVCallingConv.td @@ -26,6 +26,19 @@ def CSR_ILP32D_LP64D : CalleeSavedRegs<(add CSR_ILP32_LP64, F8_D, F9_D, (sequence "F%u_D", 18, 27))>; +defvar CSR_V = (add (sequence "V%u", 1, 7), (sequence "V%u", 24, 31), + V2M2, V4M2, V6M2, V24M2, V26M2, V28M2, V30M2, + V4M4, V24M4, V28M4, V24M8); + +def CSR_ILP32_LP64_V + : CalleeSavedRegs<(add CSR_ILP32_LP64, CSR_V)>; + +def CSR_ILP32F_LP64F_V + : CalleeSavedRegs<(add CSR_ILP32F_LP64F, CSR_V)>; + +def CSR_ILP32D_LP64D_V + : CalleeSavedRegs<(add CSR_ILP32D_LP64D, CSR_V)>; + // Needed for implementation of RISCVRegisterInfo::getNoPreservedMask() def CSR_NoRegs : CalleeSavedRegs<(add)>; diff --git a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp index 0a314fdd41cbe2bb9b5ec95a9d11e138a82f9453..173995f05b51cc585243f51359bd0c8f0205725e 100644 --- a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp +++ b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp @@ -312,10 +312,19 @@ bool RISCVExpandPseudo::expandRV32ZdinxStore(MachineBasicBlock &MBB, TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_even); Register Hi = TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_odd); + + assert(MBBI->hasOneMemOperand() && "Expected mem operand"); + MachineMemOperand *OldMMO = MBBI->memoperands().front(); + MachineFunction *MF = MBB.getParent(); + MachineMemOperand *MMOLo = MF->getMachineMemOperand(OldMMO, 0, 4); + MachineMemOperand *MMOHi = MF->getMachineMemOperand(OldMMO, 4, 4); + BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW)) .addReg(Lo, getKillRegState(MBBI->getOperand(0).isKill())) .addReg(MBBI->getOperand(1).getReg()) - .add(MBBI->getOperand(2)); + .add(MBBI->getOperand(2)) + .setMemRefs(MMOLo); + if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) { // FIXME: Zdinx RV32 can not work on unaligned memory. assert(!STI->hasFastUnalignedAccess()); @@ -325,13 +334,15 @@ bool RISCVExpandPseudo::expandRV32ZdinxStore(MachineBasicBlock &MBB, BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW)) .addReg(Hi, getKillRegState(MBBI->getOperand(0).isKill())) .add(MBBI->getOperand(1)) - .add(MBBI->getOperand(2)); + .add(MBBI->getOperand(2)) + .setMemRefs(MMOHi); } else { assert(isInt<12>(MBBI->getOperand(2).getImm() + 4)); BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW)) .addReg(Hi, getKillRegState(MBBI->getOperand(0).isKill())) .add(MBBI->getOperand(1)) - .addImm(MBBI->getOperand(2).getImm() + 4); + .addImm(MBBI->getOperand(2).getImm() + 4) + .setMemRefs(MMOHi); } MBBI->eraseFromParent(); return true; @@ -349,6 +360,12 @@ bool RISCVExpandPseudo::expandRV32ZdinxLoad(MachineBasicBlock &MBB, Register Hi = TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_odd); + assert(MBBI->hasOneMemOperand() && "Expected mem operand"); + MachineMemOperand *OldMMO = MBBI->memoperands().front(); + MachineFunction *MF = MBB.getParent(); + MachineMemOperand *MMOLo = MF->getMachineMemOperand(OldMMO, 0, 4); + MachineMemOperand *MMOHi = MF->getMachineMemOperand(OldMMO, 4, 4); + // If the register of operand 1 is equal to the Lo register, then swap the // order of loading the Lo and Hi statements. bool IsOp1EqualToLo = Lo == MBBI->getOperand(1).getReg(); @@ -356,7 +373,8 @@ bool RISCVExpandPseudo::expandRV32ZdinxLoad(MachineBasicBlock &MBB, if (!IsOp1EqualToLo) { BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Lo) .addReg(MBBI->getOperand(1).getReg()) - .add(MBBI->getOperand(2)); + .add(MBBI->getOperand(2)) + .setMemRefs(MMOLo); } if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) { @@ -365,20 +383,23 @@ bool RISCVExpandPseudo::expandRV32ZdinxLoad(MachineBasicBlock &MBB, MBBI->getOperand(2).setOffset(Offset + 4); BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi) .addReg(MBBI->getOperand(1).getReg()) - .add(MBBI->getOperand(2)); + .add(MBBI->getOperand(2)) + .setMemRefs(MMOHi); MBBI->getOperand(2).setOffset(Offset); } else { assert(isInt<12>(MBBI->getOperand(2).getImm() + 4)); BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi) .addReg(MBBI->getOperand(1).getReg()) - .addImm(MBBI->getOperand(2).getImm() + 4); + .addImm(MBBI->getOperand(2).getImm() + 4) + .setMemRefs(MMOHi); } // Order: Hi, Lo if (IsOp1EqualToLo) { BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Lo) .addReg(MBBI->getOperand(1).getReg()) - .add(MBBI->getOperand(2)); + .add(MBBI->getOperand(2)) + .setMemRefs(MMOLo); } MBBI->eraseFromParent(); diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td index 83619ccb24baa3d4ae0259adb61b034cd8bdeabe..6ef2289bb4beebf0c4981cdea4cb63a4cb981461 100644 --- a/llvm/lib/Target/RISCV/RISCVFeatures.td +++ b/llvm/lib/Target/RISCV/RISCVFeatures.td @@ -1058,6 +1058,30 @@ def HasVendorXSfvfnrclipxfqf AssemblerPredicate<(all_of FeatureVendorXSfvfnrclipxfqf), "'XSfvfnrclipxfqf' (SiFive FP32-to-int8 Ranged Clip Instructions)">; +def FeatureVendorXSiFivecdiscarddlone + : SubtargetFeature<"xsifivecdiscarddlone", "HasVendorXSiFivecdiscarddlone", "true", + "'XSiFivecdiscarddlone' (SiFive sf.cdiscard.d.l1 Instruction)", []>; +def HasVendorXSiFivecdiscarddlone + : Predicate<"Subtarget->hasVendorXSiFivecdiscarddlone()">, + AssemblerPredicate<(all_of FeatureVendorXSiFivecdiscarddlone), + "'XSiFivecdiscarddlone' (SiFive sf.cdiscard.d.l1 Instruction)">; + +def FeatureVendorXSiFivecflushdlone + : SubtargetFeature<"xsifivecflushdlone", "HasVendorXSiFivecflushdlone", "true", + "'XSiFivecflushdlone' (SiFive sf.cflush.d.l1 Instruction)", []>; +def HasVendorXSiFivecflushdlone + : Predicate<"Subtarget->hasVendorXSiFivecflushdlone()">, + AssemblerPredicate<(all_of FeatureVendorXSiFivecflushdlone), + "'XSiFivecflushdlone' (SiFive sf.cflush.d.l1 Instruction)">; + +def FeatureVendorXSfcease + : SubtargetFeature<"xsfcease", "HasVendorXSfcease", "true", + "'XSfcease' (SiFive sf.cease Instruction)", []>; +def HasVendorXSfcease + : Predicate<"Subtarget->hasVendorXSfcease()">, + AssemblerPredicate<(all_of FeatureVendorXSfcease), + "'XSfcease' (SiFive sf.cease Instruction)">; + // Core-V Extensions def FeatureVendorXCVelw @@ -1202,6 +1226,10 @@ def TuneNoSinkSplatOperands "false", "Disable sink splat operands to enable .vx, .vf," ".wx, and .wf instructions">; +def TuneNoStripWSuffix + : SubtargetFeature<"no-strip-w-suffix", "EnableStripWSuffix", "false", + "Disable strip W suffix">; + def TuneConditionalCompressedMoveFusion : SubtargetFeature<"conditional-cmv-fusion", "HasConditionalCompressedMoveFusion", "true", "Enable branch+c.mv fusion">; diff --git a/llvm/lib/Target/RISCV/RISCVFoldMasks.cpp b/llvm/lib/Target/RISCV/RISCVFoldMasks.cpp index fddbaa97d0638ca650a4dbd282ba6b01cb213896..2089f5dda6fe529e0e85b76a9555d0cc6eb864e5 100644 --- a/llvm/lib/Target/RISCV/RISCVFoldMasks.cpp +++ b/llvm/lib/Target/RISCV/RISCVFoldMasks.cpp @@ -47,10 +47,13 @@ public: StringRef getPassName() const override { return "RISC-V Fold Masks"; } private: - bool convertToUnmasked(MachineInstr &MI, MachineInstr *MaskDef) const; - bool convertVMergeToVMv(MachineInstr &MI, MachineInstr *MaskDef) const; + bool convertToUnmasked(MachineInstr &MI) const; + bool convertVMergeToVMv(MachineInstr &MI) const; - bool isAllOnesMask(MachineInstr *MaskDef) const; + bool isAllOnesMask(const MachineInstr *MaskDef) const; + + /// Maps uses of V0 to the corresponding def of V0. + DenseMap<const MachineInstr *, const MachineInstr *> V0Defs; }; } // namespace @@ -59,10 +62,9 @@ char RISCVFoldMasks::ID = 0; INITIALIZE_PASS(RISCVFoldMasks, DEBUG_TYPE, "RISC-V Fold Masks", false, false) -bool RISCVFoldMasks::isAllOnesMask(MachineInstr *MaskDef) const { - if (!MaskDef) - return false; - assert(MaskDef->isCopy() && MaskDef->getOperand(0).getReg() == RISCV::V0); +bool RISCVFoldMasks::isAllOnesMask(const MachineInstr *MaskDef) const { + assert(MaskDef && MaskDef->isCopy() && + MaskDef->getOperand(0).getReg() == RISCV::V0); Register SrcReg = TRI->lookThruCopyLike(MaskDef->getOperand(1).getReg(), MRI); if (!SrcReg.isVirtual()) return false; @@ -89,8 +91,7 @@ bool RISCVFoldMasks::isAllOnesMask(MachineInstr *MaskDef) const { // Transform (VMERGE_VVM_<LMUL> false, false, true, allones, vl, sew) to // (VMV_V_V_<LMUL> false, true, vl, sew). It may decrease uses of VMSET. -bool RISCVFoldMasks::convertVMergeToVMv(MachineInstr &MI, - MachineInstr *V0Def) const { +bool RISCVFoldMasks::convertVMergeToVMv(MachineInstr &MI) const { #define CASE_VMERGE_TO_VMV(lmul) \ case RISCV::PseudoVMERGE_VVM_##lmul: \ NewOpc = RISCV::PseudoVMV_V_V_##lmul; \ @@ -116,7 +117,7 @@ bool RISCVFoldMasks::convertVMergeToVMv(MachineInstr &MI, return false; assert(MI.getOperand(4).isReg() && MI.getOperand(4).getReg() == RISCV::V0); - if (!isAllOnesMask(V0Def)) + if (!isAllOnesMask(V0Defs.lookup(&MI))) return false; MI.setDesc(TII->get(NewOpc)); @@ -133,14 +134,13 @@ bool RISCVFoldMasks::convertVMergeToVMv(MachineInstr &MI, return true; } -bool RISCVFoldMasks::convertToUnmasked(MachineInstr &MI, - MachineInstr *MaskDef) const { +bool RISCVFoldMasks::convertToUnmasked(MachineInstr &MI) const { const RISCV::RISCVMaskedPseudoInfo *I = RISCV::getMaskedPseudoInfo(MI.getOpcode()); if (!I) return false; - if (!isAllOnesMask(MaskDef)) + if (!isAllOnesMask(V0Defs.lookup(&MI))) return false; // There are two classes of pseudos in the table - compares and @@ -198,20 +198,26 @@ bool RISCVFoldMasks::runOnMachineFunction(MachineFunction &MF) { // $v0:vr = COPY %mask:vr // %x:vr = Pseudo_MASK %a:vr, %b:br, $v0:vr // - // Because $v0 isn't in SSA, keep track of it so we can check the mask operand - // on each pseudo. - MachineInstr *CurrentV0Def; - for (MachineBasicBlock &MBB : MF) { - CurrentV0Def = nullptr; - for (MachineInstr &MI : MBB) { - Changed |= convertToUnmasked(MI, CurrentV0Def); - Changed |= convertVMergeToVMv(MI, CurrentV0Def); + // Because $v0 isn't in SSA, keep track of its definition at each use so we + // can check mask operands. + for (const MachineBasicBlock &MBB : MF) { + const MachineInstr *CurrentV0Def = nullptr; + for (const MachineInstr &MI : MBB) { + if (MI.readsRegister(RISCV::V0, TRI)) + V0Defs[&MI] = CurrentV0Def; if (MI.definesRegister(RISCV::V0, TRI)) CurrentV0Def = &MI; } } + for (MachineBasicBlock &MBB : MF) { + for (MachineInstr &MI : MBB) { + Changed |= convertToUnmasked(MI); + Changed |= convertVMergeToVMv(MI); + } + } + return Changed; } diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp index 8bac41372b5a83b205a6416e3cc515b9e4e0caf1..39075c81b2921f85173a62199f6cf47bc50b89a1 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -388,6 +388,21 @@ getUnmanagedCSI(const MachineFunction &MF, return NonLibcallCSI; } +static SmallVector<CalleeSavedInfo, 8> +getRVVCalleeSavedInfo(const MachineFunction &MF, + const std::vector<CalleeSavedInfo> &CSI) { + const MachineFrameInfo &MFI = MF.getFrameInfo(); + SmallVector<CalleeSavedInfo, 8> RVVCSI; + + for (auto &CS : CSI) { + int FI = CS.getFrameIdx(); + if (FI >= 0 && MFI.getStackID(FI) == TargetStackID::ScalableVector) + RVVCSI.push_back(CS); + } + + return RVVCSI; +} + void RISCVFrameLowering::adjustStackForRVV(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, @@ -554,8 +569,10 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, if (RVFI->isPushable(MF) && FirstFrameSetup != MBB.end() && FirstFrameSetup->getOpcode() == RISCV::CM_PUSH) { // Use available stack adjustment in push instruction to allocate additional - // stack space. - uint64_t Spimm = std::min(StackSize, (uint64_t)48); + // stack space. Align the stack size down to a multiple of 16. This is + // needed for RVE. + // FIXME: Can we increase the stack size to a multiple of 16 instead? + uint64_t Spimm = std::min(alignDown(StackSize, 16), (uint64_t)48); FirstFrameSetup->getOperand(1).setImm(Spimm); StackSize -= Spimm; } @@ -588,6 +605,10 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, // directives. for (const auto &Entry : CSI) { int FrameIdx = Entry.getFrameIdx(); + if (FrameIdx >= 0 && + MFI.getStackID(FrameIdx) == TargetStackID::ScalableVector) + continue; + int64_t Offset = MFI.getObjectOffset(FrameIdx); Register Reg = Entry.getReg(); unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( @@ -724,7 +745,7 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF, const auto &CSI = getUnmanagedCSI(MF, MFI.getCalleeSavedInfo()); - // Skip to before the restores of callee-saved registers + // Skip to before the restores of scalar callee-saved registers // FIXME: assumes exactly one instruction is used to restore each // callee-saved register. auto LastFrameDestroy = MBBI; @@ -776,8 +797,10 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF, if (RVFI->isPushable(MF) && MBBI != MBB.end() && MBBI->getOpcode() == RISCV::CM_POP) { // Use available stack adjustment in pop instruction to deallocate stack - // space. - uint64_t Spimm = std::min(StackSize, (uint64_t)48); + // space. Align the stack size down to a multiple of 16. This is needed for + // RVE. + // FIXME: Can we increase the stack size to a multiple of 16 instead? + uint64_t Spimm = std::min(alignDown(StackSize, 16), (uint64_t)48); MBBI->getOperand(1).setImm(Spimm); StackSize -= Spimm; } @@ -1025,15 +1048,24 @@ RISCVFrameLowering::assignRVVStackObjectOffsets(MachineFunction &MF) const { MachineFrameInfo &MFI = MF.getFrameInfo(); // Create a buffer of RVV objects to allocate. SmallVector<int, 8> ObjectsToAllocate; - for (int I = 0, E = MFI.getObjectIndexEnd(); I != E; ++I) { - unsigned StackID = MFI.getStackID(I); - if (StackID != TargetStackID::ScalableVector) - continue; - if (MFI.isDeadObjectIndex(I)) - continue; + auto pushRVVObjects = [&](int FIBegin, int FIEnd) { + for (int I = FIBegin, E = FIEnd; I != E; ++I) { + unsigned StackID = MFI.getStackID(I); + if (StackID != TargetStackID::ScalableVector) + continue; + if (MFI.isDeadObjectIndex(I)) + continue; - ObjectsToAllocate.push_back(I); - } + ObjectsToAllocate.push_back(I); + } + }; + // First push RVV Callee Saved object, then push RVV stack object + std::vector<CalleeSavedInfo> &CSI = MF.getFrameInfo().getCalleeSavedInfo(); + const auto &RVVCSI = getRVVCalleeSavedInfo(MF, CSI); + if (!RVVCSI.empty()) + pushRVVObjects(RVVCSI[0].getFrameIdx(), + RVVCSI[RVVCSI.size() - 1].getFrameIdx() + 1); + pushRVVObjects(0, MFI.getObjectIndexEnd() - RVVCSI.size()); // The minimum alignment is 16 bytes. Align RVVStackAlign(16); @@ -1483,13 +1515,19 @@ bool RISCVFrameLowering::spillCalleeSavedRegisters( // Manually spill values not spilled by libcall & Push/Pop. const auto &UnmanagedCSI = getUnmanagedCSI(*MF, CSI); - for (auto &CS : UnmanagedCSI) { - // Insert the spill to the stack frame. - Register Reg = CS.getReg(); - const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - TII.storeRegToStackSlot(MBB, MI, Reg, !MBB.isLiveIn(Reg), CS.getFrameIdx(), - RC, TRI, Register()); - } + const auto &RVVCSI = getRVVCalleeSavedInfo(*MF, CSI); + + auto storeRegToStackSlot = [&](decltype(UnmanagedCSI) CSInfo) { + for (auto &CS : CSInfo) { + // Insert the spill to the stack frame. + Register Reg = CS.getReg(); + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.storeRegToStackSlot(MBB, MI, Reg, !MBB.isLiveIn(Reg), + CS.getFrameIdx(), RC, TRI, Register()); + } + }; + storeRegToStackSlot(UnmanagedCSI); + storeRegToStackSlot(RVVCSI); return true; } @@ -1507,19 +1545,26 @@ bool RISCVFrameLowering::restoreCalleeSavedRegisters( DL = MI->getDebugLoc(); // Manually restore values not restored by libcall & Push/Pop. - // Keep the same order as in the prologue. There is no need to reverse the - // order in the epilogue. In addition, the return address will be restored - // first in the epilogue. It increases the opportunity to avoid the - // load-to-use data hazard between loading RA and return by RA. - // loadRegFromStackSlot can insert multiple instructions. + // Reverse the restore order in epilog. In addition, the return + // address will be restored first in the epilogue. It increases + // the opportunity to avoid the load-to-use data hazard between + // loading RA and return by RA. loadRegFromStackSlot can insert + // multiple instructions. const auto &UnmanagedCSI = getUnmanagedCSI(*MF, CSI); - for (auto &CS : UnmanagedCSI) { - Register Reg = CS.getReg(); - const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - TII.loadRegFromStackSlot(MBB, MI, Reg, CS.getFrameIdx(), RC, TRI, - Register()); - assert(MI != MBB.begin() && "loadRegFromStackSlot didn't insert any code!"); - } + const auto &RVVCSI = getRVVCalleeSavedInfo(*MF, CSI); + + auto loadRegFromStackSlot = [&](decltype(UnmanagedCSI) CSInfo) { + for (auto &CS : CSInfo) { + Register Reg = CS.getReg(); + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.loadRegFromStackSlot(MBB, MI, Reg, CS.getFrameIdx(), RC, TRI, + Register()); + assert(MI != MBB.begin() && + "loadRegFromStackSlot didn't insert any code!"); + } + }; + loadRegFromStackSlot(RVVCSI); + loadRegFromStackSlot(UnmanagedCSI); RISCVMachineFunctionInfo *RVFI = MF->getInfo<RISCVMachineFunctionInfo>(); if (RVFI->isPushable(*MF)) { diff --git a/llvm/lib/Target/RISCV/RISCVGatherScatterLowering.cpp b/llvm/lib/Target/RISCV/RISCVGatherScatterLowering.cpp index 0530e3d08be821c24b8937ed70100301c87e63e9..f0bd25f167d80d953727f0cbb03aff6bf08191a7 100644 --- a/llvm/lib/Target/RISCV/RISCVGatherScatterLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVGatherScatterLowering.cpp @@ -231,7 +231,7 @@ bool RISCVGatherScatterLowering::matchStridedRecurrence(Value *Index, Loop *L, BasePtr = PHINode::Create(Start->getType(), 2, Phi->getName() + ".scalar", Phi->getIterator()); Inc = BinaryOperator::CreateAdd(BasePtr, Step, Inc->getName() + ".scalar", - Inc); + Inc->getIterator()); BasePtr->addIncoming(Start, Phi->getIncomingBlock(1 - IncrementingBlock)); BasePtr->addIncoming(Inc, Phi->getIncomingBlock(IncrementingBlock)); diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp index 1b8c1434c9f2d915d4079b2996a8689522758d5f..55ba4949b3ea06f0aed698ef3ff5de41f5dcc27c 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -1007,7 +1007,44 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) { ReplaceNode(Node, Res); return; } + case RISCVISD::BuildPairF64: { + if (!Subtarget->hasStdExtZdinx()) + break; + + assert(!Subtarget->is64Bit() && "Unexpected subtarget"); + + SDValue Ops[] = { + CurDAG->getTargetConstant(RISCV::GPRPairRegClassID, DL, MVT::i32), + Node->getOperand(0), + CurDAG->getTargetConstant(RISCV::sub_gpr_even, DL, MVT::i32), + Node->getOperand(1), + CurDAG->getTargetConstant(RISCV::sub_gpr_odd, DL, MVT::i32)}; + + SDNode *N = + CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL, MVT::f64, Ops); + ReplaceNode(Node, N); + return; + } case RISCVISD::SplitF64: { + if (Subtarget->hasStdExtZdinx()) { + assert(!Subtarget->is64Bit() && "Unexpected subtarget"); + + if (!SDValue(Node, 0).use_empty()) { + SDValue Lo = CurDAG->getTargetExtractSubreg(RISCV::sub_gpr_even, DL, VT, + Node->getOperand(0)); + ReplaceUses(SDValue(Node, 0), Lo); + } + + if (!SDValue(Node, 1).use_empty()) { + SDValue Hi = CurDAG->getTargetExtractSubreg(RISCV::sub_gpr_odd, DL, VT, + Node->getOperand(0)); + ReplaceUses(SDValue(Node, 1), Hi); + } + + CurDAG->RemoveDeadNode(Node); + return; + } + if (!Subtarget->hasStdExtZfa()) break; assert(Subtarget->hasStdExtD() && !Subtarget->is64Bit() && diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 08678a859ae2b672e29df2067cc21a90f3ba317f..ee83f9da4934b878a1fc29020830d02ab078ecc7 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -22,6 +22,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/MemoryLocation.h" #include "llvm/Analysis/VectorUtils.h" +#include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -559,11 +560,12 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM, if (Subtarget.hasStdExtDOrZdinx()) { setOperationAction(FPLegalNodeTypes, MVT::f64, Legal); + if (!Subtarget.is64Bit()) + setOperationAction(ISD::BITCAST, MVT::i64, Custom); + if (Subtarget.hasStdExtZfa()) { setOperationAction(FPRndMode, MVT::f64, Legal); setOperationAction(ISD::FNEARBYINT, MVT::f64, Legal); - setOperationAction(ISD::BITCAST, MVT::i64, Custom); - setOperationAction(ISD::BITCAST, MVT::f64, Custom); } else { if (Subtarget.is64Bit()) setOperationAction(FPRndMode, MVT::f64, Custom); @@ -717,7 +719,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM, static const unsigned FloatingPointVecReduceOps[] = { ISD::VECREDUCE_FADD, ISD::VECREDUCE_SEQ_FADD, ISD::VECREDUCE_FMIN, - ISD::VECREDUCE_FMAX}; + ISD::VECREDUCE_FMAX, ISD::VECREDUCE_FMINIMUM, ISD::VECREDUCE_FMAXIMUM}; if (!Subtarget.is64Bit()) { // We must custom-lower certain vXi64 operations on RV32 due to the vector @@ -818,6 +820,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM, setOperationAction({ISD::SMIN, ISD::SMAX, ISD::UMIN, ISD::UMAX}, VT, Legal); + setOperationAction({ISD::ABDS, ISD::ABDU}, VT, Custom); + // Custom-lower extensions and truncations from/to mask types. setOperationAction({ISD::ANY_EXTEND, ISD::SIGN_EXTEND, ISD::ZERO_EXTEND}, VT, Custom); @@ -1202,6 +1206,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM, setOperationAction( {ISD::SMIN, ISD::SMAX, ISD::UMIN, ISD::UMAX, ISD::ABS}, VT, Custom); + setOperationAction({ISD::ABDS, ISD::ABDU}, VT, Custom); + // vXi64 MULHS/MULHU requires the V extension instead of Zve64*. if (VT.getVectorElementType() != MVT::i64 || Subtarget.hasStdExtV()) setOperationAction({ISD::MULHS, ISD::MULHU}, VT, Custom); @@ -1422,6 +1428,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM, ISD::SHL, ISD::STORE, ISD::SPLAT_VECTOR, ISD::BUILD_VECTOR, ISD::CONCAT_VECTORS, ISD::EXPERIMENTAL_VP_REVERSE, ISD::MUL, + ISD::SDIV, ISD::UDIV, ISD::SREM, ISD::UREM, ISD::INSERT_VECTOR_ELT, ISD::ABS}); if (Subtarget.hasVendorXTHeadMemPair()) setTargetDAGCombine({ISD::LOAD, ISD::STORE}); @@ -4617,7 +4624,13 @@ static SDValue getWideningInterleave(SDValue EvenV, SDValue OddV, SDValue Passthru = DAG.getUNDEF(WideContainerVT); SDValue Interleaved; - if (Subtarget.hasStdExtZvbb()) { + if (OddV.isUndef()) { + // If OddV is undef, this is a zero extend. + // FIXME: Not only does this optimize the code, it fixes some correctness + // issues because MIR does not have freeze. + Interleaved = + DAG.getNode(RISCVISD::VZEXT_VL, DL, WideContainerVT, EvenV, Mask, VL); + } else if (Subtarget.hasStdExtZvbb()) { // Interleaved = (OddV << VecVT.getScalarSizeInBits()) + EvenV. SDValue OffsetVec = DAG.getSplatVector(VecContainerVT, DL, @@ -4628,6 +4641,9 @@ static SDValue getWideningInterleave(SDValue EvenV, SDValue OddV, Interleaved = DAG.getNode(RISCVISD::VWADDU_W_VL, DL, WideContainerVT, Interleaved, EvenV, Passthru, Mask, VL); } else { + // FIXME: We should freeze the odd vector here. We already handled the case + // of provably undef/poison above. + // Widen EvenV and OddV with 0s and add one copy of OddV to EvenV with // vwaddu.vv Interleaved = DAG.getNode(RISCVISD::VWADDU_VL, DL, WideContainerVT, EvenV, @@ -6071,8 +6087,7 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op, DAG.getNode(RISCVISD::FMV_W_X_RV64, DL, MVT::f32, NewOp0); return FPConv; } - if (VT == MVT::f64 && Op0VT == MVT::i64 && XLenVT == MVT::i32 && - Subtarget.hasStdExtZfa()) { + if (VT == MVT::f64 && Op0VT == MVT::i64 && XLenVT == MVT::i32) { SDValue Lo, Hi; std::tie(Lo, Hi) = DAG.SplitScalar(Op0, DL, MVT::i32, MVT::i32); SDValue RetReg = @@ -6541,6 +6556,8 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op, case ISD::VECREDUCE_SEQ_FADD: case ISD::VECREDUCE_FMIN: case ISD::VECREDUCE_FMAX: + case ISD::VECREDUCE_FMAXIMUM: + case ISD::VECREDUCE_FMINIMUM: return lowerFPVECREDUCE(Op, DAG); case ISD::VP_REDUCE_ADD: case ISD::VP_REDUCE_UMAX: @@ -6609,6 +6626,30 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op, // better than going through the stack, as the default expansion does. SDLoc DL(Op); MVT VT = Op.getSimpleValueType(); + MVT ContainerVT = VT; + if (VT.isFixedLengthVector()) + ContainerVT = ::getContainerForFixedLengthVector(DAG, VT, Subtarget); + + // Recursively split concat_vectors with more than 2 operands: + // + // concat_vector op1, op2, op3, op4 + // -> + // concat_vector (concat_vector op1, op2), (concat_vector op3, op4) + // + // This reduces the length of the chain of vslideups and allows us to + // perform the vslideups at a smaller LMUL, limited to MF2. + if (Op.getNumOperands() > 2 && + ContainerVT.bitsGE(getLMUL1VT(ContainerVT))) { + MVT HalfVT = VT.getHalfNumVectorElementsVT(); + assert(isPowerOf2_32(Op.getNumOperands())); + size_t HalfNumOps = Op.getNumOperands() / 2; + SDValue Lo = DAG.getNode(ISD::CONCAT_VECTORS, DL, HalfVT, + Op->ops().take_front(HalfNumOps)); + SDValue Hi = DAG.getNode(ISD::CONCAT_VECTORS, DL, HalfVT, + Op->ops().drop_front(HalfNumOps)); + return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Lo, Hi); + } + unsigned NumOpElts = Op.getOperand(0).getSimpleValueType().getVectorMinNumElements(); SDValue Vec = DAG.getUNDEF(VT); @@ -6759,6 +6800,22 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op, if (!Op.getValueType().isVector()) return lowerSADDSAT_SSUBSAT(Op, DAG); return lowerToScalableOp(Op, DAG); + case ISD::ABDS: + case ISD::ABDU: { + SDLoc dl(Op); + EVT VT = Op->getValueType(0); + SDValue LHS = DAG.getFreeze(Op->getOperand(0)); + SDValue RHS = DAG.getFreeze(Op->getOperand(1)); + bool IsSigned = Op->getOpcode() == ISD::ABDS; + + // abds(lhs, rhs) -> sub(smax(lhs,rhs), smin(lhs,rhs)) + // abdu(lhs, rhs) -> sub(umax(lhs,rhs), umin(lhs,rhs)) + unsigned MaxOpc = IsSigned ? ISD::SMAX : ISD::UMAX; + unsigned MinOpc = IsSigned ? ISD::SMIN : ISD::UMIN; + SDValue Max = DAG.getNode(MaxOpc, dl, VT, LHS, RHS); + SDValue Min = DAG.getNode(MinOpc, dl, VT, LHS, RHS); + return DAG.getNode(ISD::SUB, dl, VT, Max, Min); + } case ISD::ABS: case ISD::VP_ABS: return lowerABS(Op, DAG); @@ -9541,14 +9598,17 @@ getRVVFPReductionOpAndOperands(SDValue Op, SelectionDAG &DAG, EVT EltVT, case ISD::VECREDUCE_SEQ_FADD: return std::make_tuple(RISCVISD::VECREDUCE_SEQ_FADD_VL, Op.getOperand(1), Op.getOperand(0)); + case ISD::VECREDUCE_FMINIMUM: + case ISD::VECREDUCE_FMAXIMUM: case ISD::VECREDUCE_FMIN: case ISD::VECREDUCE_FMAX: { SDValue Front = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, Op.getOperand(0), DAG.getVectorIdxConstant(0, DL)); - unsigned RVVOpc = (Opcode == ISD::VECREDUCE_FMIN) - ? RISCVISD::VECREDUCE_FMIN_VL - : RISCVISD::VECREDUCE_FMAX_VL; + unsigned RVVOpc = + (Opcode == ISD::VECREDUCE_FMIN || Opcode == ISD::VECREDUCE_FMINIMUM) + ? RISCVISD::VECREDUCE_FMIN_VL + : RISCVISD::VECREDUCE_FMAX_VL; return std::make_tuple(RVVOpc, Op.getOperand(0), Front); } } @@ -9571,9 +9631,30 @@ SDValue RISCVTargetLowering::lowerFPVECREDUCE(SDValue Op, VectorVal = convertToScalableVector(ContainerVT, VectorVal, DAG, Subtarget); } + MVT ResVT = Op.getSimpleValueType(); auto [Mask, VL] = getDefaultVLOps(VecVT, ContainerVT, DL, DAG, Subtarget); - return lowerReductionSeq(RVVOpcode, Op.getSimpleValueType(), ScalarVal, - VectorVal, Mask, VL, DL, DAG, Subtarget); + SDValue Res = lowerReductionSeq(RVVOpcode, ResVT, ScalarVal, VectorVal, Mask, + VL, DL, DAG, Subtarget); + if (Op.getOpcode() != ISD::VECREDUCE_FMINIMUM && + Op.getOpcode() != ISD::VECREDUCE_FMAXIMUM) + return Res; + + if (Op->getFlags().hasNoNaNs()) + return Res; + + // Force output to NaN if any element is Nan. + SDValue IsNan = + DAG.getNode(RISCVISD::SETCC_VL, DL, Mask.getValueType(), + {VectorVal, VectorVal, DAG.getCondCode(ISD::SETNE), + DAG.getUNDEF(Mask.getValueType()), Mask, VL}); + MVT XLenVT = Subtarget.getXLenVT(); + SDValue CPop = DAG.getNode(RISCVISD::VCPOP_VL, DL, XLenVT, IsNan, Mask, VL); + SDValue NoNaNs = DAG.getSetCC(DL, XLenVT, CPop, + DAG.getConstant(0, DL, XLenVT), ISD::SETEQ); + return DAG.getSelect( + DL, ResVT, NoNaNs, Res, + DAG.getConstantFP(APFloat::getNaN(DAG.EVTToAPFloatSemantics(ResVT)), DL, + ResVT)); } SDValue RISCVTargetLowering::lowerVPREDUCE(SDValue Op, @@ -10314,9 +10395,15 @@ RISCVTargetLowering::lowerFixedLengthVectorLoadToRVV(SDValue Op, RISCVTargetLowering::computeVLMAXBounds(ContainerVT, Subtarget); if (MinVLMAX == MaxVLMAX && MinVLMAX == VT.getVectorNumElements() && getLMUL1VT(ContainerVT).bitsLE(ContainerVT)) { + MachineMemOperand *MMO = Load->getMemOperand(); + MachineFunction &MF = DAG.getMachineFunction(); + MMO = MF.getMachineMemOperand( + MMO, MMO->getPointerInfo(), + MMO->getMemoryType().isValid() + ? LLT::scalable_vector(1, MMO->getMemoryType().getSizeInBits()) + : MMO->getMemoryType()); SDValue NewLoad = - DAG.getLoad(ContainerVT, DL, Load->getChain(), Load->getBasePtr(), - Load->getMemOperand()); + DAG.getLoad(ContainerVT, DL, Load->getChain(), Load->getBasePtr(), MMO); SDValue Result = convertFromScalableVector(VT, NewLoad, DAG, Subtarget); return DAG.getMergeValues({Result, NewLoad.getValue(1)}, DL); } @@ -10374,9 +10461,17 @@ RISCVTargetLowering::lowerFixedLengthVectorStoreToRVV(SDValue Op, const auto [MinVLMAX, MaxVLMAX] = RISCVTargetLowering::computeVLMAXBounds(ContainerVT, Subtarget); if (MinVLMAX == MaxVLMAX && MinVLMAX == VT.getVectorNumElements() && - getLMUL1VT(ContainerVT).bitsLE(ContainerVT)) + getLMUL1VT(ContainerVT).bitsLE(ContainerVT)) { + MachineMemOperand *MMO = Store->getMemOperand(); + MachineFunction &MF = DAG.getMachineFunction(); + MMO = MF.getMachineMemOperand( + MMO, MMO->getPointerInfo(), + MMO->getMemoryType().isValid() + ? LLT::scalable_vector(1, MMO->getMemoryType().getSizeInBits()) + : MMO->getMemoryType()); return DAG.getStore(Store->getChain(), DL, NewValue, Store->getBasePtr(), - Store->getMemOperand()); + MMO); + } SDValue VL = getVLOp(VT.getVectorNumElements(), ContainerVT, DL, DAG, Subtarget); @@ -10466,6 +10561,7 @@ SDValue RISCVTargetLowering::lowerMaskedStore(SDValue Op, SDValue BasePtr = MemSD->getBasePtr(); SDValue Val, Mask, VL; + bool IsCompressingStore = false; if (const auto *VPStore = dyn_cast<VPStoreSDNode>(Op)) { Val = VPStore->getValue(); Mask = VPStore->getMask(); @@ -10474,9 +10570,11 @@ SDValue RISCVTargetLowering::lowerMaskedStore(SDValue Op, const auto *MStore = cast<MaskedStoreSDNode>(Op); Val = MStore->getValue(); Mask = MStore->getMask(); + IsCompressingStore = MStore->isCompressingStore(); } - bool IsUnmasked = ISD::isConstantSplatVectorAllOnes(Mask.getNode()); + bool IsUnmasked = + ISD::isConstantSplatVectorAllOnes(Mask.getNode()) || IsCompressingStore; MVT VT = Val.getSimpleValueType(); MVT XLenVT = Subtarget.getXLenVT(); @@ -10486,7 +10584,7 @@ SDValue RISCVTargetLowering::lowerMaskedStore(SDValue Op, ContainerVT = getContainerForFixedLengthVector(VT); Val = convertToScalableVector(ContainerVT, Val, DAG, Subtarget); - if (!IsUnmasked) { + if (!IsUnmasked || IsCompressingStore) { MVT MaskVT = getMaskTypeFor(ContainerVT); Mask = convertToScalableVector(MaskVT, Mask, DAG, Subtarget); } @@ -10495,6 +10593,15 @@ SDValue RISCVTargetLowering::lowerMaskedStore(SDValue Op, if (!VL) VL = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget).second; + if (IsCompressingStore) { + Val = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, ContainerVT, + DAG.getConstant(Intrinsic::riscv_vcompress, DL, XLenVT), + DAG.getUNDEF(ContainerVT), Val, Mask, VL); + VL = + DAG.getNode(RISCVISD::VCPOP_VL, DL, XLenVT, Mask, + getAllOnesMask(Mask.getSimpleValueType(), VL, DL, DAG), VL); + } + unsigned IntID = IsUnmasked ? Intrinsic::riscv_vse : Intrinsic::riscv_vse_mask; SmallVector<SDValue, 8> Ops{Chain, DAG.getTargetConstant(IntID, DL, XLenVT)}; @@ -12119,8 +12226,7 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N, SDValue FPConv = DAG.getNode(RISCVISD::FMV_X_ANYEXTW_RV64, DL, MVT::i64, Op0); Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, FPConv)); - } else if (VT == MVT::i64 && Op0VT == MVT::f64 && XLenVT == MVT::i32 && - Subtarget.hasStdExtZfa()) { + } else if (VT == MVT::i64 && Op0VT == MVT::f64 && XLenVT == MVT::i32) { SDValue NewReg = DAG.getNode(RISCVISD::SplitF64, DL, DAG.getVTList(MVT::i32, MVT::i32), Op0); SDValue RetReg = DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, @@ -12838,6 +12944,58 @@ static SDValue transformAddImmMulImm(SDNode *N, SelectionDAG &DAG, return DAG.getNode(ISD::ADD, DL, VT, New1, DAG.getConstant(CB, DL, VT)); } +// add (zext, zext) -> zext (add (zext, zext)) +// sub (zext, zext) -> sext (sub (zext, zext)) +// mul (zext, zext) -> zext (mul (zext, zext)) +// sdiv (zext, zext) -> zext (sdiv (zext, zext)) +// udiv (zext, zext) -> zext (udiv (zext, zext)) +// srem (zext, zext) -> zext (srem (zext, zext)) +// urem (zext, zext) -> zext (urem (zext, zext)) +// +// where the sum of the extend widths match, and the the range of the bin op +// fits inside the width of the narrower bin op. (For profitability on rvv, we +// use a power of two for both inner and outer extend.) +static SDValue combineBinOpOfZExt(SDNode *N, SelectionDAG &DAG) { + + EVT VT = N->getValueType(0); + if (!VT.isVector() || !DAG.getTargetLoweringInfo().isTypeLegal(VT)) + return SDValue(); + + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + if (N0.getOpcode() != ISD::ZERO_EXTEND || N1.getOpcode() != ISD::ZERO_EXTEND) + return SDValue(); + if (!N0.hasOneUse() || !N1.hasOneUse()) + return SDValue(); + + SDValue Src0 = N0.getOperand(0); + SDValue Src1 = N1.getOperand(0); + EVT SrcVT = Src0.getValueType(); + if (!DAG.getTargetLoweringInfo().isTypeLegal(SrcVT) || + SrcVT != Src1.getValueType() || SrcVT.getScalarSizeInBits() < 8 || + SrcVT.getScalarSizeInBits() >= VT.getScalarSizeInBits() / 2) + return SDValue(); + + LLVMContext &C = *DAG.getContext(); + EVT ElemVT = VT.getVectorElementType().getHalfSizedIntegerVT(C); + EVT NarrowVT = EVT::getVectorVT(C, ElemVT, VT.getVectorElementCount()); + + Src0 = DAG.getNode(ISD::ZERO_EXTEND, SDLoc(Src0), NarrowVT, Src0); + Src1 = DAG.getNode(ISD::ZERO_EXTEND, SDLoc(Src1), NarrowVT, Src1); + + // Src0 and Src1 are zero extended, so they're always positive if signed. + // + // sub can produce a negative from two positive operands, so it needs sign + // extended. Other nodes produce a positive from two positive operands, so + // zero extend instead. + unsigned OuterExtend = + N->getOpcode() == ISD::SUB ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; + + return DAG.getNode( + OuterExtend, SDLoc(N), VT, + DAG.getNode(N->getOpcode(), SDLoc(N), NarrowVT, Src0, Src1)); +} + // Try to turn (add (xor bool, 1) -1) into (neg bool). static SDValue combineAddOfBooleanXor(SDNode *N, SelectionDAG &DAG) { SDValue N0 = N->getOperand(0); @@ -12875,6 +13033,8 @@ static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, return V; if (SDValue V = combineBinOpOfExtractToReduceTree(N, DAG, Subtarget)) return V; + if (SDValue V = combineBinOpOfZExt(N, DAG)) + return V; // fold (add (select lhs, rhs, cc, 0, y), x) -> // (select lhs, rhs, cc, x, (add x, y)) @@ -12942,28 +13102,8 @@ static SDValue performSUBCombine(SDNode *N, SelectionDAG &DAG, } } - // sub (zext, zext) -> sext (sub (zext, zext)) - // where the sum of the extend widths match, and the inner zexts - // add at least one bit. (For profitability on rvv, we use a - // power of two for both inner and outer extend.) - if (VT.isVector() && Subtarget.getTargetLowering()->isTypeLegal(VT) && - N0.getOpcode() == N1.getOpcode() && N0.getOpcode() == ISD::ZERO_EXTEND && - N0.hasOneUse() && N1.hasOneUse()) { - SDValue Src0 = N0.getOperand(0); - SDValue Src1 = N1.getOperand(0); - EVT SrcVT = Src0.getValueType(); - if (Subtarget.getTargetLowering()->isTypeLegal(SrcVT) && - SrcVT == Src1.getValueType() && SrcVT.getScalarSizeInBits() >= 8 && - SrcVT.getScalarSizeInBits() < VT.getScalarSizeInBits() / 2) { - LLVMContext &C = *DAG.getContext(); - EVT ElemVT = VT.getVectorElementType().getHalfSizedIntegerVT(C); - EVT NarrowVT = EVT::getVectorVT(C, ElemVT, VT.getVectorElementCount()); - Src0 = DAG.getNode(ISD::ZERO_EXTEND, SDLoc(Src0), NarrowVT, Src0); - Src1 = DAG.getNode(ISD::ZERO_EXTEND, SDLoc(Src1), NarrowVT, Src1); - return DAG.getNode(ISD::SIGN_EXTEND, SDLoc(N), VT, - DAG.getNode(ISD::SUB, SDLoc(N), NarrowVT, Src0, Src1)); - } - } + if (SDValue V = combineBinOpOfZExt(N, DAG)) + return V; // fold (sub x, (select lhs, rhs, cc, 0, y)) -> // (select lhs, rhs, cc, x, (sub x, y)) @@ -13254,6 +13394,9 @@ static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG) { return DAG.getNode(AddSubOpc, DL, VT, N0, MulVal); } + if (SDValue V = combineBinOpOfZExt(N, DAG)) + return V; + return SDValue(); } @@ -13397,7 +13540,7 @@ struct CombineResult; enum ExtKind : uint8_t { ZExt = 1 << 0, SExt = 1 << 1, FPExt = 1 << 2 }; /// Helper class for folding sign/zero extensions. /// In particular, this class is used for the following combines: -/// add | add_vl -> vwadd(u) | vwadd(u)_w +/// add | add_vl | or disjoint -> vwadd(u) | vwadd(u)_w /// sub | sub_vl -> vwsub(u) | vwsub(u)_w /// mul | mul_vl -> vwmul(u) | vwmul_su /// fadd -> vfwadd | vfwadd_w @@ -13545,6 +13688,7 @@ struct NodeExtensionHelper { case RISCVISD::ADD_VL: case RISCVISD::VWADD_W_VL: case RISCVISD::VWADDU_W_VL: + case ISD::OR: return RISCVISD::VWADD_VL; case ISD::SUB: case RISCVISD::SUB_VL: @@ -13567,6 +13711,7 @@ struct NodeExtensionHelper { case RISCVISD::ADD_VL: case RISCVISD::VWADD_W_VL: case RISCVISD::VWADDU_W_VL: + case ISD::OR: return RISCVISD::VWADDU_VL; case ISD::SUB: case RISCVISD::SUB_VL: @@ -13612,6 +13757,7 @@ struct NodeExtensionHelper { switch (Opcode) { case ISD::ADD: case RISCVISD::ADD_VL: + case ISD::OR: return SupportsExt == ExtKind::SExt ? RISCVISD::VWADD_W_VL : RISCVISD::VWADDU_W_VL; case ISD::SUB: @@ -13654,12 +13800,8 @@ struct NodeExtensionHelper { SDValue NarrowElt = OrigOperand.getOperand(0); MVT NarrowVT = NarrowElt.getSimpleValueType(); - - unsigned ScalarBits = VT.getScalarSizeInBits(); - unsigned NarrowScalarBits = NarrowVT.getScalarSizeInBits(); - - // Ensure the extension's semantic is equivalent to rvv vzext or vsext. - if (ScalarBits != NarrowScalarBits * 2) + // i1 types are legal but we can't select V{S,Z}EXT_VLs with them. + if (NarrowVT.getVectorElementType() == MVT::i1) break; SupportsZExt = Opc == ISD::ZERO_EXTEND; @@ -13736,6 +13878,10 @@ struct NodeExtensionHelper { case ISD::MUL: { return Root->getValueType(0).isScalableVector(); } + case ISD::OR: { + return Root->getValueType(0).isScalableVector() && + Root->getFlags().hasDisjoint(); + } // Vector Widening Integer Add/Sub/Mul Instructions case RISCVISD::ADD_VL: case RISCVISD::MUL_VL: @@ -13816,7 +13962,8 @@ struct NodeExtensionHelper { switch (Root->getOpcode()) { case ISD::ADD: case ISD::SUB: - case ISD::MUL: { + case ISD::MUL: + case ISD::OR: { SDLoc DL(Root); MVT VT = Root->getSimpleValueType(0); return getDefaultScalableVLOps(VT, DL, DAG, Subtarget); @@ -13839,6 +13986,7 @@ struct NodeExtensionHelper { switch (N->getOpcode()) { case ISD::ADD: case ISD::MUL: + case ISD::OR: case RISCVISD::ADD_VL: case RISCVISD::MUL_VL: case RISCVISD::VWADD_W_VL: @@ -13905,6 +14053,7 @@ struct CombineResult { case ISD::ADD: case ISD::SUB: case ISD::MUL: + case ISD::OR: Merge = DAG.getUNDEF(Root->getValueType(0)); break; } @@ -14055,6 +14204,7 @@ NodeExtensionHelper::getSupportedFoldings(const SDNode *Root) { switch (Root->getOpcode()) { case ISD::ADD: case ISD::SUB: + case ISD::OR: case RISCVISD::ADD_VL: case RISCVISD::SUB_VL: case RISCVISD::FADD_VL: @@ -14098,9 +14248,9 @@ NodeExtensionHelper::getSupportedFoldings(const SDNode *Root) { /// Combine a binary operation to its equivalent VW or VW_W form. /// The supported combines are: -/// add_vl -> vwadd(u) | vwadd(u)_w -/// sub_vl -> vwsub(u) | vwsub(u)_w -/// mul_vl -> vwmul(u) | vwmul_su +/// add | add_vl | or disjoint -> vwadd(u) | vwadd(u)_w +/// sub | sub_vl -> vwsub(u) | vwsub(u)_w +/// mul | mul_vl -> vwmul(u) | vwmul_su /// fadd_vl -> vfwadd | vfwadd_w /// fsub_vl -> vfwsub | vfwsub_w /// fmul_vl -> vfwmul @@ -15285,62 +15435,13 @@ static SDValue performINSERT_VECTOR_ELTCombine(SDNode *N, SelectionDAG &DAG, return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, ConcatOps); } -// Recursively split up concat_vectors with more than 2 operands: -// -// concat_vector op1, op2, op3, op4 -// -> -// concat_vector (concat_vector op1, op2), (concat_vector op3, op4) -// -// This reduces the length of the chain of vslideups and allows us to perform -// the vslideups at a smaller LMUL, limited to MF2. -// -// We do this as a DAG combine rather than during lowering so that any undef -// operands can get combined away. -static SDValue -performCONCAT_VECTORSSplitCombine(SDNode *N, SelectionDAG &DAG, - const RISCVTargetLowering &TLI) { - SDLoc DL(N); - - if (N->getNumOperands() <= 2) - return SDValue(); - - if (!TLI.isTypeLegal(N->getValueType(0))) - return SDValue(); - MVT VT = N->getSimpleValueType(0); - - // Don't split any further than MF2. - MVT ContainerVT = VT; - if (VT.isFixedLengthVector()) - ContainerVT = getContainerForFixedLengthVector(DAG, VT, TLI.getSubtarget()); - if (ContainerVT.bitsLT(getLMUL1VT(ContainerVT))) - return SDValue(); - - MVT HalfVT = VT.getHalfNumVectorElementsVT(); - assert(isPowerOf2_32(N->getNumOperands())); - size_t HalfNumOps = N->getNumOperands() / 2; - SDValue Lo = DAG.getNode(ISD::CONCAT_VECTORS, DL, HalfVT, - N->ops().take_front(HalfNumOps)); - SDValue Hi = DAG.getNode(ISD::CONCAT_VECTORS, DL, HalfVT, - N->ops().drop_front(HalfNumOps)); - - // Lower to an insert_subvector directly so the concat_vectors don't get - // recombined. - SDValue Vec = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, DAG.getUNDEF(VT), Lo, - DAG.getVectorIdxConstant(0, DL)); - Vec = DAG.getNode( - ISD::INSERT_SUBVECTOR, DL, VT, Vec, Hi, - DAG.getVectorIdxConstant(HalfVT.getVectorMinNumElements(), DL)); - return Vec; -} - // If we're concatenating a series of vector loads like // concat_vectors (load v4i8, p+0), (load v4i8, p+n), (load v4i8, p+n*2) ... // Then we can turn this into a strided load by widening the vector elements // vlse32 p, stride=n -static SDValue -performCONCAT_VECTORSStridedLoadCombine(SDNode *N, SelectionDAG &DAG, - const RISCVSubtarget &Subtarget, - const RISCVTargetLowering &TLI) { +static SDValue performCONCAT_VECTORSCombine(SDNode *N, SelectionDAG &DAG, + const RISCVSubtarget &Subtarget, + const RISCVTargetLowering &TLI) { SDLoc DL(N); EVT VT = N->getValueType(0); @@ -15809,14 +15910,24 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N, } case ISD::AND: return performANDCombine(N, DCI, Subtarget); - case ISD::OR: + case ISD::OR: { + if (SDValue V = combineBinOp_VLToVWBinOp_VL(N, DCI, Subtarget)) + return V; return performORCombine(N, DCI, Subtarget); + } case ISD::XOR: return performXORCombine(N, DAG, Subtarget); case ISD::MUL: if (SDValue V = combineBinOp_VLToVWBinOp_VL(N, DCI, Subtarget)) return V; return performMULCombine(N, DAG); + case ISD::SDIV: + case ISD::UDIV: + case ISD::SREM: + case ISD::UREM: + if (SDValue V = combineBinOpOfZExt(N, DAG)) + return V; + break; case ISD::FADD: case ISD::UMAX: case ISD::UMIN: @@ -16445,10 +16556,7 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N, return V; break; case ISD::CONCAT_VECTORS: - if (SDValue V = - performCONCAT_VECTORSStridedLoadCombine(N, DAG, Subtarget, *this)) - return V; - if (SDValue V = performCONCAT_VECTORSSplitCombine(N, DAG, *this)) + if (SDValue V = performCONCAT_VECTORSCombine(N, DAG, Subtarget, *this)) return V; break; case ISD::INSERT_VECTOR_ELT: @@ -17043,6 +17151,23 @@ unsigned RISCVTargetLowering::ComputeNumSignBitsForTargetNode( return 1; } +bool RISCVTargetLowering::canCreateUndefOrPoisonForTargetNode( + SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, + bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const { + + // TODO: Add more target nodes. + switch (Op.getOpcode()) { + case RISCVISD::SELECT_CC: + // Integer select_cc cannot create poison. + // TODO: What are the FP poison semantics? + // TODO: This instruction blocks poison from the unselected operand, can + // we do anything with that? + return !Op.getValueType().isInteger(); + } + return TargetLowering::canCreateUndefOrPoisonForTargetNode( + Op, DemandedElts, DAG, PoisonOnly, ConsiderFlags, Depth); +} + const Constant * RISCVTargetLowering::getTargetConstantFromLoad(LoadSDNode *Ld) const { assert(Ld && "Unexpected null LoadSDNode"); @@ -17156,9 +17281,7 @@ static MachineBasicBlock *emitReadCounterWidePseudo(MachineInstr &MI, static MachineBasicBlock *emitSplitF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const RISCVSubtarget &Subtarget) { - assert((MI.getOpcode() == RISCV::SplitF64Pseudo || - MI.getOpcode() == RISCV::SplitF64Pseudo_INX) && - "Unexpected instruction"); + assert(MI.getOpcode() == RISCV::SplitF64Pseudo && "Unexpected instruction"); MachineFunction &MF = *BB->getParent(); DebugLoc DL = MI.getDebugLoc(); @@ -17168,9 +17291,7 @@ static MachineBasicBlock *emitSplitF64Pseudo(MachineInstr &MI, Register HiReg = MI.getOperand(1).getReg(); Register SrcReg = MI.getOperand(2).getReg(); - const TargetRegisterClass *SrcRC = MI.getOpcode() == RISCV::SplitF64Pseudo_INX - ? &RISCV::GPRPairRegClass - : &RISCV::FPR64RegClass; + const TargetRegisterClass *SrcRC = &RISCV::FPR64RegClass; int FI = MF.getInfo<RISCVMachineFunctionInfo>()->getMoveF64FrameIndex(MF); TII.storeRegToStackSlot(*BB, MI, SrcReg, MI.getOperand(2).isKill(), FI, SrcRC, @@ -17195,8 +17316,7 @@ static MachineBasicBlock *emitSplitF64Pseudo(MachineInstr &MI, static MachineBasicBlock *emitBuildPairF64Pseudo(MachineInstr &MI, MachineBasicBlock *BB, const RISCVSubtarget &Subtarget) { - assert((MI.getOpcode() == RISCV::BuildPairF64Pseudo || - MI.getOpcode() == RISCV::BuildPairF64Pseudo_INX) && + assert(MI.getOpcode() == RISCV::BuildPairF64Pseudo && "Unexpected instruction"); MachineFunction &MF = *BB->getParent(); @@ -17207,9 +17327,7 @@ static MachineBasicBlock *emitBuildPairF64Pseudo(MachineInstr &MI, Register LoReg = MI.getOperand(1).getReg(); Register HiReg = MI.getOperand(2).getReg(); - const TargetRegisterClass *DstRC = - MI.getOpcode() == RISCV::BuildPairF64Pseudo_INX ? &RISCV::GPRPairRegClass - : &RISCV::FPR64RegClass; + const TargetRegisterClass *DstRC = &RISCV::FPR64RegClass; int FI = MF.getInfo<RISCVMachineFunctionInfo>()->getMoveF64FrameIndex(MF); MachinePointerInfo MPI = MachinePointerInfo::getFixedStack(MF, FI); @@ -17730,10 +17848,8 @@ RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, case RISCV::Select_FPR64IN32X_Using_CC_GPR: return emitSelectPseudo(MI, BB, Subtarget); case RISCV::BuildPairF64Pseudo: - case RISCV::BuildPairF64Pseudo_INX: return emitBuildPairF64Pseudo(MI, BB, Subtarget); case RISCV::SplitF64Pseudo: - case RISCV::SplitF64Pseudo_INX: return emitSplitF64Pseudo(MI, BB, Subtarget); case RISCV::PseudoQuietFLE_H: return emitQuietFCMP(MI, BB, RISCV::FLE_H, RISCV::FEQ_H, Subtarget); @@ -17951,33 +18067,12 @@ static bool CC_RISCVAssign2XLen(unsigned XLen, CCState &State, CCValAssign VA1, return false; } -static unsigned allocateRVVReg(MVT ValVT, unsigned ValNo, - std::optional<unsigned> FirstMaskArgument, - CCState &State, const RISCVTargetLowering &TLI) { - const TargetRegisterClass *RC = TLI.getRegClassFor(ValVT); - if (RC == &RISCV::VRRegClass) { - // Assign the first mask argument to V0. - // This is an interim calling convention and it may be changed in the - // future. - if (FirstMaskArgument && ValNo == *FirstMaskArgument) - return State.AllocateReg(RISCV::V0); - return State.AllocateReg(ArgVRs); - } - if (RC == &RISCV::VRM2RegClass) - return State.AllocateReg(ArgVRM2s); - if (RC == &RISCV::VRM4RegClass) - return State.AllocateReg(ArgVRM4s); - if (RC == &RISCV::VRM8RegClass) - return State.AllocateReg(ArgVRM8s); - llvm_unreachable("Unhandled register class for ValueType"); -} - // Implements the RISC-V calling convention. Returns true upon failure. bool RISCV::CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI, - std::optional<unsigned> FirstMaskArgument) { + RVVArgDispatcher &RVVDispatcher) { unsigned XLen = DL.getLargestLegalIntTypeSizeInBits(); assert(XLen == 32 || XLen == 64); MVT XLenVT = XLen == 32 ? MVT::i32 : MVT::i64; @@ -18146,7 +18241,7 @@ bool RISCV::CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo, else if (ValVT == MVT::f64 && !UseGPRForF64) Reg = State.AllocateReg(ArgFPR64s); else if (ValVT.isVector()) { - Reg = allocateRVVReg(ValVT, ValNo, FirstMaskArgument, State, TLI); + Reg = RVVDispatcher.getNextPhysReg(); if (!Reg) { // For return values, the vector must be passed fully via registers or // via the stack. @@ -18232,9 +18327,13 @@ void RISCVTargetLowering::analyzeInputArgs( unsigned NumArgs = Ins.size(); FunctionType *FType = MF.getFunction().getFunctionType(); - std::optional<unsigned> FirstMaskArgument; - if (Subtarget.hasVInstructions()) - FirstMaskArgument = preAssignMask(Ins); + SmallVector<Type *, 4> TypeList; + if (IsRet) + TypeList.push_back(MF.getFunction().getReturnType()); + else + for (const Argument &Arg : MF.getFunction().args()) + TypeList.push_back(Arg.getType()); + RVVArgDispatcher Dispatcher{&MF, this, TypeList}; for (unsigned i = 0; i != NumArgs; ++i) { MVT ArgVT = Ins[i].VT; @@ -18249,7 +18348,7 @@ void RISCVTargetLowering::analyzeInputArgs( RISCVABI::ABI ABI = MF.getSubtarget<RISCVSubtarget>().getTargetABI(); if (Fn(MF.getDataLayout(), ABI, i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, CCInfo, /*IsFixed=*/true, IsRet, ArgTy, *this, - FirstMaskArgument)) { + Dispatcher)) { LLVM_DEBUG(dbgs() << "InputArg #" << i << " has unhandled type " << ArgVT << '\n'); llvm_unreachable(nullptr); @@ -18263,9 +18362,13 @@ void RISCVTargetLowering::analyzeOutputArgs( CallLoweringInfo *CLI, RISCVCCAssignFn Fn) const { unsigned NumArgs = Outs.size(); - std::optional<unsigned> FirstMaskArgument; - if (Subtarget.hasVInstructions()) - FirstMaskArgument = preAssignMask(Outs); + SmallVector<Type *, 4> TypeList; + if (IsRet) + TypeList.push_back(MF.getFunction().getReturnType()); + else if (CLI) + for (const TargetLowering::ArgListEntry &Arg : CLI->getArgs()) + TypeList.push_back(Arg.Ty); + RVVArgDispatcher Dispatcher{&MF, this, TypeList}; for (unsigned i = 0; i != NumArgs; i++) { MVT ArgVT = Outs[i].VT; @@ -18275,7 +18378,7 @@ void RISCVTargetLowering::analyzeOutputArgs( RISCVABI::ABI ABI = MF.getSubtarget<RISCVSubtarget>().getTargetABI(); if (Fn(MF.getDataLayout(), ABI, i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, CCInfo, Outs[i].IsFixed, IsRet, OrigTy, *this, - FirstMaskArgument)) { + Dispatcher)) { LLVM_DEBUG(dbgs() << "OutputArg #" << i << " has unhandled type " << ArgVT << "\n"); llvm_unreachable(nullptr); @@ -18456,7 +18559,7 @@ bool RISCV::CC_RISCV_FastCC(const DataLayout &DL, RISCVABI::ABI ABI, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI, - std::optional<unsigned> FirstMaskArgument) { + RVVArgDispatcher &RVVDispatcher) { if (LocVT == MVT::i32 || LocVT == MVT::i64) { if (unsigned Reg = State.AllocateReg(getFastCCArgGPRs(ABI))) { State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); @@ -18534,13 +18637,14 @@ bool RISCV::CC_RISCV_FastCC(const DataLayout &DL, RISCVABI::ABI ABI, } if (LocVT.isVector()) { - if (unsigned Reg = - allocateRVVReg(ValVT, ValNo, FirstMaskArgument, State, TLI)) { + MCPhysReg AllocatedVReg = RVVDispatcher.getNextPhysReg(); + if (AllocatedVReg) { // Fixed-length vectors are located in the corresponding scalable-vector // container types. if (ValVT.isFixedLengthVector()) LocVT = TLI.getContainerForFixedLengthVector(LocVT); - State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + State.addLoc( + CCValAssign::getReg(ValNo, ValVT, AllocatedVReg, LocVT, LocInfo)); } else { // Try and pass the address via a "fast" GPR. if (unsigned GPRReg = State.AllocateReg(getFastCCArgGPRs(ABI))) { @@ -18642,6 +18746,7 @@ SDValue RISCVTargetLowering::LowerFormalArguments( case CallingConv::Fast: case CallingConv::SPIR_KERNEL: case CallingConv::GRAAL: + case CallingConv::RISCV_VectorCall: break; case CallingConv::GHC: if (Subtarget.isRVE()) @@ -19167,17 +19272,15 @@ bool RISCVTargetLowering::CanLowerReturn( SmallVector<CCValAssign, 16> RVLocs; CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context); - std::optional<unsigned> FirstMaskArgument; - if (Subtarget.hasVInstructions()) - FirstMaskArgument = preAssignMask(Outs); + RVVArgDispatcher Dispatcher{&MF, this, MF.getFunction().getReturnType()}; for (unsigned i = 0, e = Outs.size(); i != e; ++i) { MVT VT = Outs[i].VT; ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; RISCVABI::ABI ABI = MF.getSubtarget<RISCVSubtarget>().getTargetABI(); if (RISCV::CC_RISCV(MF.getDataLayout(), ABI, i, VT, VT, CCValAssign::Full, - ArgFlags, CCInfo, /*IsFixed=*/true, /*IsRet=*/true, nullptr, - *this, FirstMaskArgument)) + ArgFlags, CCInfo, /*IsFixed=*/true, /*IsRet=*/true, + nullptr, *this, Dispatcher)) return false; } return true; @@ -20923,7 +21026,7 @@ bool RISCVTargetLowering::fallBackToDAGISel(const Instruction &Inst) const { if (Op == Instruction::Add || Op == Instruction::Sub || Op == Instruction::And || Op == Instruction::Or || Op == Instruction::Xor || Op == Instruction::InsertElement || - Op == Instruction::Xor || Op == Instruction::ShuffleVector) + Op == Instruction::ShuffleVector || Op == Instruction::Load) return false; if (Inst.getType()->isScalableTy()) @@ -20974,6 +21077,121 @@ unsigned RISCVTargetLowering::getMinimumJumpTableEntries() const { return Subtarget.getMinimumJumpTableEntries(); } +void RVVArgDispatcher::constructArgInfos(ArrayRef<Type *> TypeList) { + const DataLayout &DL = MF->getDataLayout(); + const Function &F = MF->getFunction(); + LLVMContext &Context = F.getContext(); + + bool FirstVMaskAssigned = false; + for (Type *Ty : TypeList) { + StructType *STy = dyn_cast<StructType>(Ty); + if (STy && STy->containsHomogeneousScalableVectorTypes()) { + Type *ElemTy = STy->getTypeAtIndex(0U); + EVT VT = TLI->getValueType(DL, ElemTy); + MVT RegisterVT = + TLI->getRegisterTypeForCallingConv(Context, F.getCallingConv(), VT); + + RVVArgInfos.push_back({STy->getNumElements(), RegisterVT, false}); + } else { + SmallVector<EVT, 4> ValueVTs; + ComputeValueVTs(*TLI, DL, Ty, ValueVTs); + + for (unsigned Value = 0, NumValues = ValueVTs.size(); Value != NumValues; + ++Value) { + EVT VT = ValueVTs[Value]; + MVT RegisterVT = + TLI->getRegisterTypeForCallingConv(Context, F.getCallingConv(), VT); + unsigned NumRegs = + TLI->getNumRegistersForCallingConv(Context, F.getCallingConv(), VT); + + // Skip non-RVV register type + if (!RegisterVT.isVector()) + continue; + + if (RegisterVT.isFixedLengthVector()) + RegisterVT = TLI->getContainerForFixedLengthVector(RegisterVT); + + if (!FirstVMaskAssigned && + RegisterVT.getVectorElementType() == MVT::i1) { + RVVArgInfos.push_back({1, RegisterVT, true}); + FirstVMaskAssigned = true; + } else { + RVVArgInfos.push_back({1, RegisterVT, false}); + } + + RVVArgInfos.insert(RVVArgInfos.end(), --NumRegs, + {1, RegisterVT, false}); + } + } + } +} + +void RVVArgDispatcher::allocatePhysReg(unsigned NF, unsigned LMul, + unsigned StartReg) { + assert((StartReg % LMul) == 0 && + "Start register number should be multiple of lmul"); + const MCPhysReg *VRArrays; + switch (LMul) { + default: + report_fatal_error("Invalid lmul"); + case 1: + VRArrays = ArgVRs; + break; + case 2: + VRArrays = ArgVRM2s; + break; + case 4: + VRArrays = ArgVRM4s; + break; + case 8: + VRArrays = ArgVRM8s; + break; + } + + for (unsigned i = 0; i < NF; ++i) + if (StartReg) + AllocatedPhysRegs.push_back(VRArrays[(StartReg - 8) / LMul + i]); + else + AllocatedPhysRegs.push_back(MCPhysReg()); +} + +/// This function determines if each RVV argument is passed by register, if the +/// argument can be assigned to a VR, then give it a specific register. +/// Otherwise, assign the argument to 0 which is a invalid MCPhysReg. +void RVVArgDispatcher::compute() { + uint32_t AssignedMap = 0; + auto allocate = [&](const RVVArgInfo &ArgInfo) { + // Allocate first vector mask argument to V0. + if (ArgInfo.FirstVMask) { + AllocatedPhysRegs.push_back(RISCV::V0); + return; + } + + unsigned RegsNeeded = divideCeil( + ArgInfo.VT.getSizeInBits().getKnownMinValue(), RISCV::RVVBitsPerBlock); + unsigned TotalRegsNeeded = ArgInfo.NF * RegsNeeded; + for (unsigned StartReg = 0; StartReg + TotalRegsNeeded <= NumArgVRs; + StartReg += RegsNeeded) { + uint32_t Map = ((1 << TotalRegsNeeded) - 1) << StartReg; + if ((AssignedMap & Map) == 0) { + allocatePhysReg(ArgInfo.NF, RegsNeeded, StartReg + 8); + AssignedMap |= Map; + return; + } + } + + allocatePhysReg(ArgInfo.NF, RegsNeeded, 0); + }; + + for (unsigned i = 0; i < RVVArgInfos.size(); ++i) + allocate(RVVArgInfos[i]); +} + +MCPhysReg RVVArgDispatcher::getNextPhysReg() { + assert(CurIdx < AllocatedPhysRegs.size() && "Index out of range"); + return AllocatedPhysRegs[CurIdx++]; +} + namespace llvm::RISCVVIntrinsicsTable { #define GET_RISCVVIntrinsicsTable_IMPL diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h index f90cb4df6047612af291bc22840ccdbff0ad281e..c28552354bf4222289cb4b41c564a1fcc2f27c6f 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -24,6 +24,7 @@ namespace llvm { class InstructionCost; class RISCVSubtarget; struct RISCVRegisterInfo; +class RVVArgDispatcher; namespace RISCVISD { // clang-format off @@ -585,6 +586,12 @@ public: const SelectionDAG &DAG, unsigned Depth) const override; + bool canCreateUndefOrPoisonForTargetNode(SDValue Op, + const APInt &DemandedElts, + const SelectionDAG &DAG, + bool PoisonOnly, bool ConsiderFlags, + unsigned Depth) const override; + const Constant *getTargetConstantFromLoad(LoadSDNode *LD) const override; // This method returns the name of a target specific DAG node. @@ -869,7 +876,7 @@ public: ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI, - std::optional<unsigned> FirstMaskArgument); + RVVArgDispatcher &RVVDispatcher); private: void analyzeInputArgs(MachineFunction &MF, CCState &CCInfo, @@ -994,7 +1001,7 @@ private: /// RISC-V doesn't have flags so it's better to perform the and/or in a GPR. bool shouldNormalizeToSelectSequence(LLVMContext &, EVT) const override { return false; - }; + } /// For available scheduling models FDIV + two independent FMULs are much /// faster than two FDIVs. @@ -1009,19 +1016,68 @@ private: unsigned getMinimumJumpTableEntries() const override; }; +/// As per the spec, the rules for passing vector arguments are as follows: +/// +/// 1. For the first vector mask argument, use v0 to pass it. +/// 2. For vector data arguments or rest vector mask arguments, starting from +/// the v8 register, if a vector register group between v8-v23 that has not been +/// allocated can be found and the first register number is a multiple of LMUL, +/// then allocate this vector register group to the argument and mark these +/// registers as allocated. Otherwise, pass it by reference and are replaced in +/// the argument list with the address. +/// 3. For tuple vector data arguments, starting from the v8 register, if +/// NFIELDS consecutive vector register groups between v8-v23 that have not been +/// allocated can be found and the first register number is a multiple of LMUL, +/// then allocate these vector register groups to the argument and mark these +/// registers as allocated. Otherwise, pass it by reference and are replaced in +/// the argument list with the address. +class RVVArgDispatcher { +public: + static constexpr unsigned NumArgVRs = 16; + + struct RVVArgInfo { + unsigned NF; + MVT VT; + bool FirstVMask = false; + }; + + RVVArgDispatcher(const MachineFunction *MF, const RISCVTargetLowering *TLI, + ArrayRef<Type *> TypeList) + : MF(MF), TLI(TLI) { + constructArgInfos(TypeList); + compute(); + } + + MCPhysReg getNextPhysReg(); + +private: + SmallVector<RVVArgInfo, 4> RVVArgInfos; + SmallVector<MCPhysReg, 4> AllocatedPhysRegs; + + const MachineFunction *MF = nullptr; + const RISCVTargetLowering *TLI = nullptr; + + unsigned CurIdx = 0; + + void constructArgInfos(ArrayRef<Type *> TypeList); + void compute(); + void allocatePhysReg(unsigned NF = 1, unsigned LMul = 1, + unsigned StartReg = 0); +}; + namespace RISCV { bool CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI, - std::optional<unsigned> FirstMaskArgument); + RVVArgDispatcher &RVVDispatcher); bool CC_RISCV_FastCC(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed, bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI, - std::optional<unsigned> FirstMaskArgument); + RVVArgDispatcher &RVVDispatcher); bool CC_RISCV_GHC(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, diff --git a/llvm/lib/Target/RISCV/RISCVInstrFormats.td b/llvm/lib/Target/RISCV/RISCVInstrFormats.td index f56f49ae24571e0c4007be9d7b87ce3b7aa0a704..52c794446af08d0d37183d27c5d0c6523a0dd276 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrFormats.td +++ b/llvm/lib/Target/RISCV/RISCVInstrFormats.td @@ -109,6 +109,8 @@ def Vrgather : RISCVVConstraint<!or(VS2Constraint.Value, VMConstraint.Value)>; def Vcompress : RISCVVConstraint<!or(VS2Constraint.Value, VS1Constraint.Value)>; +def Sha2Constraint : RISCVVConstraint<!or(VS2Constraint.Value, + VS1Constraint.Value)>; // The following opcode names match those given in Table 19.1 in the // RISC-V User-level ISA specification ("RISC-V base opcode map"). diff --git a/llvm/lib/Target/RISCV/RISCVInstrGISel.td b/llvm/lib/Target/RISCV/RISCVInstrGISel.td index ede8c9809833ccc799fb52704522d4e358431310..54e22d6257814a835fe9f275abedd7d6feaa6862 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrGISel.td +++ b/llvm/lib/Target/RISCV/RISCVInstrGISel.td @@ -24,3 +24,11 @@ def G_FCLASS : RISCVGenericInstruction { let hasSideEffects = false; } def : GINodeEquiv<G_FCLASS, riscv_fclass>; + +// Pseudo equivalent to a RISCVISD::READ_VLENB. +def G_READ_VLENB : RISCVGenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins); + let hasSideEffects = false; +} +def : GINodeEquiv<G_READ_VLENB, riscv_read_vlenb>; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp index 37a8079dcbf10d2b25cc41d18a26bb4674c365ee..5582de51b17d1959293260be33f944eb8fe45f1b 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -299,36 +299,36 @@ void RISCVInstrInfo::copyPhysRegVector(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg, bool KillSrc, - unsigned Opc, unsigned NF) const { + RISCVII::VLMUL LMul, unsigned NF) const { const TargetRegisterInfo *TRI = STI.getRegisterInfo(); - RISCVII::VLMUL LMul; + unsigned Opc; unsigned SubRegIdx; unsigned VVOpc, VIOpc; - switch (Opc) { + switch (LMul) { default: llvm_unreachable("Impossible LMUL for vector register copy."); - case RISCV::VMV1R_V: - LMul = RISCVII::LMUL_1; + case RISCVII::LMUL_1: + Opc = RISCV::VMV1R_V; SubRegIdx = RISCV::sub_vrm1_0; VVOpc = RISCV::PseudoVMV_V_V_M1; VIOpc = RISCV::PseudoVMV_V_I_M1; break; - case RISCV::VMV2R_V: - LMul = RISCVII::LMUL_2; + case RISCVII::LMUL_2: + Opc = RISCV::VMV2R_V; SubRegIdx = RISCV::sub_vrm2_0; VVOpc = RISCV::PseudoVMV_V_V_M2; VIOpc = RISCV::PseudoVMV_V_I_M2; break; - case RISCV::VMV4R_V: - LMul = RISCVII::LMUL_4; + case RISCVII::LMUL_4: + Opc = RISCV::VMV4R_V; SubRegIdx = RISCV::sub_vrm4_0; VVOpc = RISCV::PseudoVMV_V_V_M4; VIOpc = RISCV::PseudoVMV_V_I_M4; break; - case RISCV::VMV8R_V: + case RISCVII::LMUL_8: assert(NF == 1); - LMul = RISCVII::LMUL_8; + Opc = RISCV::VMV8R_V; SubRegIdx = RISCV::sub_vrm1_0; // There is no sub_vrm8_0. VVOpc = RISCV::PseudoVMV_V_V_M8; VIOpc = RISCV::PseudoVMV_V_I_M8; @@ -505,87 +505,87 @@ void RISCVInstrInfo::copyPhysReg(MachineBasicBlock &MBB, // VR->VR copies. if (RISCV::VRRegClass.contains(DstReg, SrcReg)) { - copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV1R_V); + copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCVII::LMUL_1); return; } if (RISCV::VRM2RegClass.contains(DstReg, SrcReg)) { - copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV2R_V); + copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCVII::LMUL_2); return; } if (RISCV::VRM4RegClass.contains(DstReg, SrcReg)) { - copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV4R_V); + copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCVII::LMUL_4); return; } if (RISCV::VRM8RegClass.contains(DstReg, SrcReg)) { - copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV8R_V); + copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCVII::LMUL_8); return; } if (RISCV::VRN2M1RegClass.contains(DstReg, SrcReg)) { - copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV1R_V, + copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCVII::LMUL_1, /*NF=*/2); return; } if (RISCV::VRN2M2RegClass.contains(DstReg, SrcReg)) { - copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV2R_V, + copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCVII::LMUL_2, /*NF=*/2); return; } if (RISCV::VRN2M4RegClass.contains(DstReg, SrcReg)) { - copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV4R_V, + copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCVII::LMUL_4, /*NF=*/2); return; } if (RISCV::VRN3M1RegClass.contains(DstReg, SrcReg)) { - copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV1R_V, + copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCVII::LMUL_1, /*NF=*/3); return; } if (RISCV::VRN3M2RegClass.contains(DstReg, SrcReg)) { - copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV2R_V, + copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCVII::LMUL_2, /*NF=*/3); return; } if (RISCV::VRN4M1RegClass.contains(DstReg, SrcReg)) { - copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV1R_V, + copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCVII::LMUL_1, /*NF=*/4); return; } if (RISCV::VRN4M2RegClass.contains(DstReg, SrcReg)) { - copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV2R_V, + copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCVII::LMUL_2, /*NF=*/4); return; } if (RISCV::VRN5M1RegClass.contains(DstReg, SrcReg)) { - copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV1R_V, + copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCVII::LMUL_1, /*NF=*/5); return; } if (RISCV::VRN6M1RegClass.contains(DstReg, SrcReg)) { - copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV1R_V, + copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCVII::LMUL_1, /*NF=*/6); return; } if (RISCV::VRN7M1RegClass.contains(DstReg, SrcReg)) { - copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV1R_V, + copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCVII::LMUL_1, /*NF=*/7); return; } if (RISCV::VRN8M1RegClass.contains(DstReg, SrcReg)) { - copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCV::VMV1R_V, + copyPhysRegVector(MBB, MBBI, DL, DstReg, SrcReg, KillSrc, RISCVII::LMUL_1, /*NF=*/8); return; } @@ -656,7 +656,7 @@ void RISCVInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, if (IsScalableVector) { MachineMemOperand *MMO = MF->getMachineMemOperand( MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore, - MemoryLocation::UnknownSize, MFI.getObjectAlign(FI)); + LocationSize::beforeOrAfterPointer(), MFI.getObjectAlign(FI)); MFI.setStackID(FI, TargetStackID::ScalableVector); BuildMI(MBB, I, DebugLoc(), get(Opcode)) @@ -739,7 +739,7 @@ void RISCVInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, if (IsScalableVector) { MachineMemOperand *MMO = MF->getMachineMemOperand( MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad, - MemoryLocation::UnknownSize, MFI.getObjectAlign(FI)); + LocationSize::beforeOrAfterPointer(), MFI.getObjectAlign(FI)); MFI.setStackID(FI, TargetStackID::ScalableVector); BuildMI(MBB, I, DebugLoc(), get(Opcode), DstReg) @@ -2050,6 +2050,9 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI, case RISCVOp::OPERAND_RVKRNUM_2_14: Ok = Imm >= 2 && Imm <= 14; break; + case RISCVOp::OPERAND_SPIMM: + Ok = (Imm & 0xf) == 0; + break; } if (!Ok) { ErrInfo = "Invalid immediate"; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h index 8a312ee5e77958ed9947314afb57b192d00132e1..dd049fca0597199d85d8181fa4b86666e43b7d30 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h @@ -69,7 +69,7 @@ public: void copyPhysRegVector(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg, bool KillSrc, - unsigned Opc, unsigned NF = 1) const; + RISCVII::VLMUL LMul, unsigned NF = 1) const; void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg, bool KillSrc) const override; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index e753c1f1add0c6cb71dc8a0f6102b328c788907e..fd8777fdc121c7fc9b7d4cf0bb077571bd959f83 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1259,6 +1259,10 @@ def or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{ }]>; def : PatGprSimm12<or_is_add, ADDI>; +def add_like : PatFrags<(ops node:$lhs, node:$rhs), + [(or_is_add node:$lhs, node:$rhs), + (add node:$lhs, node:$rhs)]>; + // negate of low bit can be done via two (compressible) shifts. The negate // is never compressible since rs1 and rd can't be the same register. def : Pat<(XLenVT (sub 0, (and_oneuse GPR:$rs, 1))), @@ -1405,7 +1409,8 @@ multiclass BccPat<CondCode Cond, RVInstB Inst> { class BrccCompressOpt<CondCode Cond, RVInstB Inst> : Pat<(riscv_brcc GPR:$lhs, simm12_no6:$Constant, Cond, bb:$place), - (Inst (ADDI GPR:$lhs, (NegImm simm12:$Constant)), (XLenVT X0), bb:$place)>; + (Inst (XLenVT (ADDI GPR:$lhs, (NegImm simm12:$Constant))), + (XLenVT X0), bb:$place)>; defm : BccPat<SETEQ, BEQ>; defm : BccPat<SETNE, BNE>; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td index 9b4f93d55e337b53bee718f78ac6b4af3bf7eea8..8efefee383a6a557c60f1b6b9425a70b551eeeff 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td @@ -524,20 +524,6 @@ let isCall = 0, mayLoad = 0, mayStore = 1, Size = 8, isCodeGenOnly = 1 in def PseudoRV32ZdinxSD : Pseudo<(outs), (ins GPRPair:$rs2, GPRNoX0:$rs1, simm12:$imm12), []>; def : Pat<(store (f64 GPRPair:$rs2), (AddrRegImmINX (XLenVT GPR:$rs1), simm12:$imm12)), (PseudoRV32ZdinxSD GPRPair:$rs2, GPR:$rs1, simm12:$imm12)>; - -/// Pseudo-instructions needed for the soft-float ABI with RV32D - -// Moves two GPRs to an FPR. -let usesCustomInserter = 1 in -def BuildPairF64Pseudo_INX - : Pseudo<(outs FPR64IN32X:$dst), (ins GPR:$src1, GPR:$src2), - [(set FPR64IN32X:$dst, (RISCVBuildPairF64 GPR:$src1, GPR:$src2))]>; - -// Moves an FPR to two GPRs. -let usesCustomInserter = 1 in -def SplitF64Pseudo_INX - : Pseudo<(outs GPR:$dst1, GPR:$dst2), (ins FPR64IN32X:$src), - [(set GPR:$dst1, GPR:$dst2, (RISCVSplitF64 FPR64IN32X:$src))]>; } // Predicates = [HasStdExtZdinx, IsRV32] let Predicates = [HasStdExtD] in { diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoV.td b/llvm/lib/Target/RISCV/RISCVInstrInfoV.td index d7807c1203780786c0d07f906e2a661680e88e6d..e68fb42ece9f027e335abc413755a9b47fdffdfa 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoV.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoV.td @@ -157,10 +157,8 @@ class SchedBinaryMC<string write, string read0, string read1, // For instructions with three operands. class SchedTernary<string write, string read0, string read1, string read2, - string mx, int sew = 0, bit forceMasked = 0, - bit forceMergeOpRead = 0> - : SchedNary<write, [read0, read1, read2], mx, sew, forceMasked, - forceMergeOpRead>; + string mx, int sew = 0, bit forceMasked = 0> + : SchedNary<write, [read0, read1, read2], mx, sew, forceMasked>; class SchedTernaryMC<string write, string read0, string read1, string read2, int sew = 0, bit forceMasked = 1>: SchedNary<write, [read0, read1, read2], "WorstCase", sew, forceMasked>; @@ -533,14 +531,6 @@ class VALUVs2<bits<6> funct6, bits<5> vs1, RISCVVFormat opv, string opcodestr> : RVInstV<funct6, vs1, opv, (outs VR:$vd), (ins VR:$vs2, VMaskOp:$vm), opcodestr, "$vd, $vs2$vm">; - -// op vd, vs2 (use vs1 as instruction encoding) -class VALUVs2NoVm<bits<6> funct6, bits<5> vs1, RISCVVFormat opv, string opcodestr> - : RVInstV<funct6, vs1, opv, (outs VR:$vd), - (ins VR:$vs2), opcodestr, - "$vd, $vs2"> { - let vm = 1; -} } // hasSideEffects = 0, mayLoad = 0, mayStore = 0 //===----------------------------------------------------------------------===// @@ -577,7 +567,7 @@ multiclass VALU_IV_X<string opcodestr, bits<6> funct6> { } multiclass VALU_IV_I<string opcodestr, bits<6> funct6> { - def I : VALUVI<funct6, opcodestr # ".vi", simm5>, + def I : VALUVI<funct6, opcodestr # ".vi">, SchedUnaryMC<"WriteVIALUI", "ReadVIALUV">; } @@ -663,7 +653,7 @@ multiclass VALUNoVm_IV_V_X<string opcodestr, bits<6> funct6> { multiclass VALUNoVm_IV_V_X_I<string opcodestr, bits<6> funct6> : VALUNoVm_IV_V_X<opcodestr, funct6> { - def I : VALUVINoVm<funct6, opcodestr # ".vi", simm5>, + def I : VALUVINoVm<funct6, opcodestr # ".vi">, SchedUnaryMC<"WriteVICALUI", "ReadVICALUV", forceMasked=0>; } @@ -902,7 +892,7 @@ multiclass VCMP_IV_X<string opcodestr, bits<6> funct6> { } multiclass VCMP_IV_I<string opcodestr, bits<6> funct6> { - def I : VALUVI<funct6, opcodestr # ".vi", simm5>, + def I : VALUVI<funct6, opcodestr # ".vi">, SchedUnaryMC<"WriteVICmpI", "ReadVICmpV">; } @@ -949,7 +939,7 @@ multiclass VSALU_IV_V_X<string opcodestr, bits<6> funct6> { multiclass VSALU_IV_V_X_I<string opcodestr, bits<6> funct6> : VSALU_IV_V_X<opcodestr, funct6> { - def I : VALUVI<funct6, opcodestr # ".vi", simm5>, + def I : VALUVI<funct6, opcodestr # ".vi">, SchedUnaryMC<"WriteVSALUI", "ReadVSALUV">; } diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td index ae93bf694875658b47992547c4f571b288869c07..af20b11514ca1f66a6d0280715294cb630d55816 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td @@ -2133,19 +2133,6 @@ multiclass VPseudoBinary<VReg RetClass, } } -multiclass VPseudoBinaryNoMask<VReg RetClass, - VReg Op1Class, - DAGOperand Op2Class, - LMULInfo MInfo, - string Constraint = "", - int sew = 0> { - let VLMul = MInfo.value, SEW=sew in { - defvar suffix = !if(sew, "_" # MInfo.MX # "_E" # sew, "_" # MInfo.MX); - def suffix : VPseudoBinaryNoMaskTU<RetClass, Op1Class, Op2Class, - Constraint>; - } -} - multiclass VPseudoBinaryRoundingMode<VReg RetClass, VReg Op1Class, DAGOperand Op2Class, @@ -2212,7 +2199,8 @@ multiclass VPseudoTiedBinary<VReg RetClass, def "_" # MInfo.MX # "_TIED": VPseudoTiedBinaryNoMask<RetClass, Op2Class, Constraint, TargetConstraintType>; def "_" # MInfo.MX # "_MASK_TIED" : VPseudoTiedBinaryMask<RetClass, Op2Class, - Constraint, TargetConstraintType>; + Constraint, TargetConstraintType>, + RISCVMaskedPseudo<MaskIdx=2>; } } @@ -2225,7 +2213,8 @@ multiclass VPseudoTiedBinaryRoundingMode<VReg RetClass, def "_" # MInfo.MX # "_TIED": VPseudoTiedBinaryNoMaskRoundingMode<RetClass, Op2Class, Constraint, TargetConstraintType>; def "_" # MInfo.MX # "_MASK_TIED" : - VPseudoTiedBinaryMaskRoundingMode<RetClass, Op2Class, Constraint, TargetConstraintType>; + VPseudoTiedBinaryMaskRoundingMode<RetClass, Op2Class, Constraint, TargetConstraintType>, + RISCVMaskedPseudo<MaskIdx=2>; } } @@ -2921,22 +2910,6 @@ multiclass VPseudoVMAX_VV_VF { } } -multiclass VPseudoVALU_VV_VF { - foreach m = MxListF in { - defm "" : VPseudoBinaryFV_VV<m>, - SchedBinary<"WriteVFALUV", "ReadVFALUV", "ReadVFALUV", m.MX, - forceMergeOpRead=true>; - } - - foreach f = FPList in { - foreach m = f.MxList in { - defm "" : VPseudoBinaryV_VF<m, f>, - SchedBinary<"WriteVFALUF", "ReadVFALUV", "ReadVFALUF", m.MX, - forceMergeOpRead=true>; - } - } -} - multiclass VPseudoVALU_VV_VF_RM { foreach m = MxListF in { defm "" : VPseudoBinaryFV_VV_RM<m>, @@ -2953,16 +2926,6 @@ multiclass VPseudoVALU_VV_VF_RM { } } -multiclass VPseudoVALU_VF { - foreach f = FPList in { - foreach m = f.MxList in { - defm "" : VPseudoBinaryV_VF<m, f>, - SchedBinary<"WriteVFALUF", "ReadVFALUV", "ReadVFALUF", m.MX, - forceMergeOpRead=true>; - } - } -} - multiclass VPseudoVALU_VF_RM { foreach f = FPList in { foreach m = f.MxList in { @@ -2996,12 +2959,6 @@ multiclass VPseudoVWALU_VV_VX { } } -multiclass VPseudoVWALU_VV_VX_VI<Operand ImmType> : VPseudoVWALU_VV_VX { - foreach m = MxListW in { - defm "" : VPseudoBinaryW_VI<ImmType, m>; - } -} - multiclass VPseudoVWMUL_VV_VX { foreach m = MxListW in { defvar mx = m.MX; @@ -3372,22 +3329,6 @@ multiclass VPseudoVMAC_VV_VX_AAXA<string Constraint = ""> { } } -multiclass VPseudoVMAC_VV_VF_AAXA<string Constraint = ""> { - foreach m = MxListF in { - defm "" : VPseudoTernaryV_VV_AAXA<m, Constraint>, - SchedTernary<"WriteVFMulAddV", "ReadVFMulAddV", "ReadVFMulAddV", - "ReadVFMulAddV", m.MX>; - } - - foreach f = FPList in { - foreach m = f.MxList in { - defm "" : VPseudoTernaryV_VF_AAXA<m, f, Constraint>, - SchedTernary<"WriteVFMulAddF", "ReadVFMulAddV", "ReadVFMulAddF", - "ReadVFMulAddV", m.MX>; - } - } -} - multiclass VPseudoVMAC_VV_VF_AAXA_RM<string Constraint = ""> { foreach m = MxListF in { defm "" : VPseudoTernaryV_VV_AAXA_RM<m, Constraint>, @@ -6698,6 +6639,7 @@ defm PseudoVFWREDOSUM : VPseudoVFWREDO_VS_RM; // 15. Vector Mask Instructions //===----------------------------------------------------------------------===// +let Predicates = [HasVInstructions] in { //===----------------------------------------------------------------------===// // 15.1 Vector Mask-Register Logical Instructions //===----------------------------------------------------------------------===// @@ -6718,7 +6660,6 @@ defm PseudoVMSET : VPseudoNullaryPseudoM<"VMXNOR">; //===----------------------------------------------------------------------===// // 15.2. Vector mask population count vcpop //===----------------------------------------------------------------------===// - let IsSignExtendingOpW = 1 in defm PseudoVCPOP: VPseudoVPOP_M; @@ -6753,6 +6694,7 @@ defm PseudoVIOTA_M: VPseudoVIOTA_M; // 15.9. Vector Element Index Instruction //===----------------------------------------------------------------------===// defm PseudoVID : VPseudoVID_V; +} // Predicates = [HasVInstructions] //===----------------------------------------------------------------------===// // 16. Vector Permutation Instructions @@ -6828,6 +6770,7 @@ let Predicates = [HasVInstructionsAnyF] in { //===----------------------------------------------------------------------===// // 16.4. Vector Register Gather Instructions //===----------------------------------------------------------------------===// +let Predicates = [HasVInstructions] in { defm PseudoVRGATHER : VPseudoVGTR_VV_VX_VI<uimm5, "@earlyclobber $rd">; defm PseudoVRGATHEREI16 : VPseudoVGTR_VV_EEW<eew=16, Constraint="@earlyclobber $rd">; @@ -6836,6 +6779,7 @@ defm PseudoVRGATHEREI16 : VPseudoVGTR_VV_EEW<eew=16, // 16.5. Vector Compress Instruction //===----------------------------------------------------------------------===// defm PseudoVCOMPRESS : VPseudoVCPR_V; +} // Predicates = [HasVInstructions] //===----------------------------------------------------------------------===// // Patterns. diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXSf.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXSf.td index b4130e3805a1100b50fe6e8dc97e4faf2ec033c3..9a6818c99af20670a564de5091bc21c8fd163881 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoXSf.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXSf.td @@ -808,3 +808,35 @@ let Predicates = [HasVendorXSfvfnrclipxfqf] in { defm : VPatVFNRCLIP<"vfnrclip_xu_f_qf", "VFNRCLIP_XU_F_QF">; defm : VPatVFNRCLIP<"vfnrclip_x_f_qf", "VFNRCLIP_X_F_QF">; } + +let Predicates = [HasVendorXSiFivecdiscarddlone] in { + let hasNoSchedulingInfo = 1, hasSideEffects = 1, mayLoad = 0, mayStore = 0, + DecoderNamespace = "XSiFivecdiscarddlone" in + def SF_CDISCARD_D_L1 + : RVInstIUnary<0b111111000010, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1), + "sf.cdiscard.d.l1", "$rs1">, Sched<[]> { + let rd = 0; + } + def : InstAlias<"sf.cdiscard.d.l1", (SF_CDISCARD_D_L1 X0)>; +} // Predicates = [HasVendorXSifivecdiscarddlone] + +let Predicates = [HasVendorXSiFivecflushdlone] in { + let hasNoSchedulingInfo = 1, hasSideEffects = 1, mayLoad = 0, mayStore = 0, + DecoderNamespace = "XSiFivecflushdlone" in + def SF_CFLUSH_D_L1 + : RVInstIUnary<0b111111000000, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1), + "sf.cflush.d.l1", "$rs1">, Sched<[]> { + let rd = 0; + } + def : InstAlias<"sf.cflush.d.l1", (SF_CFLUSH_D_L1 X0)>; +} // Predicates = [HasVendorXSifivecflushdlone] + +let Predicates = [HasVendorXSfcease] in { + let hasNoSchedulingInfo = 1, hasSideEffects = 1, mayLoad = 0, mayStore = 0, + DecoderNamespace = "XSfcease" in + def SF_CEASE : RVInstIUnary<0b001100000101, 0b000, OPC_SYSTEM, (outs), (ins), + "sf.cease", "">, Sched<[]> { + let rs1 = 0b00000; + let rd = 0b00000; +} +} diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td index f0f8494dd9a3137e7ec58bcf0939f1401c049624..434b071e628a0e4e164ee279817bea79e8384a8d 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td @@ -255,7 +255,7 @@ class binop_with_non_imm12<SDPatternOperator binop> }]; } def add_non_imm12 : binop_with_non_imm12<add>; -def or_is_add_non_imm12 : binop_with_non_imm12<or_is_add>; +def add_like_non_imm12 : binop_with_non_imm12<add_like>; def Shifted32OnesMask : IntImmLeaf<XLenVT, [{ if (!Imm.isShiftedMask()) @@ -424,13 +424,13 @@ def CLMULH : ALU_rr<0b0000101, 0b011, "clmulh", Commutable=1>, let Predicates = [HasStdExtZbb] in { def MIN : ALU_rr<0b0000101, 0b100, "min", Commutable=1>, - Sched<[WriteIALU, ReadIALU, ReadIALU]>; + Sched<[WriteIMinMax, ReadIMinMax, ReadIMinMax]>; def MINU : ALU_rr<0b0000101, 0b101, "minu", Commutable=1>, - Sched<[WriteIALU, ReadIALU, ReadIALU]>; + Sched<[WriteIMinMax, ReadIMinMax, ReadIMinMax]>; def MAX : ALU_rr<0b0000101, 0b110, "max", Commutable=1>, - Sched<[WriteIALU, ReadIALU, ReadIALU]>; + Sched<[WriteIMinMax, ReadIMinMax, ReadIMinMax]>; def MAXU : ALU_rr<0b0000101, 0b111, "maxu", Commutable=1>, - Sched<[WriteIALU, ReadIALU, ReadIALU]>; + Sched<[WriteIMinMax, ReadIMinMax, ReadIMinMax]>; } // Predicates = [HasStdExtZbb] let Predicates = [HasStdExtZbkb] in { @@ -676,38 +676,38 @@ let Predicates = [HasStdExtZba] in { foreach i = {1,2,3} in { defvar shxadd = !cast<Instruction>("SH"#i#"ADD"); - def : Pat<(XLenVT (add_non_imm12 (shl GPR:$rs1, (XLenVT i)), GPR:$rs2)), + def : Pat<(XLenVT (add_like_non_imm12 (shl GPR:$rs1, (XLenVT i)), GPR:$rs2)), (shxadd GPR:$rs1, GPR:$rs2)>; defvar pat = !cast<ComplexPattern>("sh"#i#"add_op"); // More complex cases use a ComplexPattern. - def : Pat<(XLenVT (add_non_imm12 pat:$rs1, GPR:$rs2)), + def : Pat<(XLenVT (add_like_non_imm12 pat:$rs1, GPR:$rs2)), (shxadd pat:$rs1, GPR:$rs2)>; } -def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 6)), GPR:$rs2), +def : Pat<(add_like (mul_oneuse GPR:$rs1, (XLenVT 6)), GPR:$rs2), (SH1ADD (XLenVT (SH1ADD GPR:$rs1, GPR:$rs1)), GPR:$rs2)>; -def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 10)), GPR:$rs2), +def : Pat<(add_like (mul_oneuse GPR:$rs1, (XLenVT 10)), GPR:$rs2), (SH1ADD (XLenVT (SH2ADD GPR:$rs1, GPR:$rs1)), GPR:$rs2)>; -def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 18)), GPR:$rs2), +def : Pat<(add_like (mul_oneuse GPR:$rs1, (XLenVT 18)), GPR:$rs2), (SH1ADD (XLenVT (SH3ADD GPR:$rs1, GPR:$rs1)), GPR:$rs2)>; -def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 12)), GPR:$rs2), +def : Pat<(add_like (mul_oneuse GPR:$rs1, (XLenVT 12)), GPR:$rs2), (SH2ADD (XLenVT (SH1ADD GPR:$rs1, GPR:$rs1)), GPR:$rs2)>; -def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 20)), GPR:$rs2), +def : Pat<(add_like (mul_oneuse GPR:$rs1, (XLenVT 20)), GPR:$rs2), (SH2ADD (XLenVT (SH2ADD GPR:$rs1, GPR:$rs1)), GPR:$rs2)>; -def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 36)), GPR:$rs2), +def : Pat<(add_like (mul_oneuse GPR:$rs1, (XLenVT 36)), GPR:$rs2), (SH2ADD (XLenVT (SH3ADD GPR:$rs1, GPR:$rs1)), GPR:$rs2)>; -def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 24)), GPR:$rs2), +def : Pat<(add_like (mul_oneuse GPR:$rs1, (XLenVT 24)), GPR:$rs2), (SH3ADD (XLenVT (SH1ADD GPR:$rs1, GPR:$rs1)), GPR:$rs2)>; -def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 40)), GPR:$rs2), +def : Pat<(add_like (mul_oneuse GPR:$rs1, (XLenVT 40)), GPR:$rs2), (SH3ADD (XLenVT (SH2ADD GPR:$rs1, GPR:$rs1)), GPR:$rs2)>; -def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 72)), GPR:$rs2), +def : Pat<(add_like (mul_oneuse GPR:$rs1, (XLenVT 72)), GPR:$rs2), (SH3ADD (XLenVT (SH3ADD GPR:$rs1, GPR:$rs1)), GPR:$rs2)>; -def : Pat<(add (XLenVT GPR:$r), CSImm12MulBy4:$i), +def : Pat<(add_like (XLenVT GPR:$r), CSImm12MulBy4:$i), (SH2ADD (XLenVT (ADDI (XLenVT X0), (SimmShiftRightBy2XForm CSImm12MulBy4:$i))), GPR:$r)>; -def : Pat<(add (XLenVT GPR:$r), CSImm12MulBy8:$i), +def : Pat<(add_like (XLenVT GPR:$r), CSImm12MulBy8:$i), (SH3ADD (XLenVT (ADDI (XLenVT X0), (SimmShiftRightBy3XForm CSImm12MulBy8:$i))), GPR:$r)>; @@ -756,46 +756,43 @@ def : Pat<(i64 (shl (and GPR:$rs1, 0xFFFFFFFF), uimm5:$shamt)), def : Pat<(i64 (and GPR:$rs1, Shifted32OnesMask:$mask)), (SLLI_UW (XLenVT (SRLI GPR:$rs1, Shifted32OnesMask:$mask)), Shifted32OnesMask:$mask)>; -def : Pat<(i64 (add_non_imm12 (and GPR:$rs1, 0xFFFFFFFF), GPR:$rs2)), +def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0xFFFFFFFF), GPR:$rs2)), (ADD_UW GPR:$rs1, GPR:$rs2)>; def : Pat<(i64 (and GPR:$rs, 0xFFFFFFFF)), (ADD_UW GPR:$rs, (XLenVT X0))>; -def : Pat<(i64 (or_is_add_non_imm12 (and GPR:$rs1, 0xFFFFFFFF), GPR:$rs2)), - (ADD_UW GPR:$rs1, GPR:$rs2)>; - foreach i = {1,2,3} in { defvar shxadd_uw = !cast<Instruction>("SH"#i#"ADD_UW"); - def : Pat<(i64 (add_non_imm12 (shl (and GPR:$rs1, 0xFFFFFFFF), (i64 i)), (XLenVT GPR:$rs2))), + def : Pat<(i64 (add_like_non_imm12 (shl (and GPR:$rs1, 0xFFFFFFFF), (i64 i)), (XLenVT GPR:$rs2))), (shxadd_uw GPR:$rs1, GPR:$rs2)>; } -def : Pat<(i64 (add_non_imm12 (and (shl GPR:$rs1, (i64 1)), 0x1FFFFFFFF), (XLenVT GPR:$rs2))), +def : Pat<(i64 (add_like_non_imm12 (and (shl GPR:$rs1, (i64 1)), 0x1FFFFFFFF), (XLenVT GPR:$rs2))), (SH1ADD_UW GPR:$rs1, GPR:$rs2)>; -def : Pat<(i64 (add_non_imm12 (and (shl GPR:$rs1, (i64 2)), 0x3FFFFFFFF), (XLenVT GPR:$rs2))), +def : Pat<(i64 (add_like_non_imm12 (and (shl GPR:$rs1, (i64 2)), 0x3FFFFFFFF), (XLenVT GPR:$rs2))), (SH2ADD_UW GPR:$rs1, GPR:$rs2)>; -def : Pat<(i64 (add_non_imm12 (and (shl GPR:$rs1, (i64 3)), 0x7FFFFFFFF), (XLenVT GPR:$rs2))), +def : Pat<(i64 (add_like_non_imm12 (and (shl GPR:$rs1, (i64 3)), 0x7FFFFFFFF), (XLenVT GPR:$rs2))), (SH3ADD_UW GPR:$rs1, GPR:$rs2)>; // More complex cases use a ComplexPattern. foreach i = {1,2,3} in { defvar pat = !cast<ComplexPattern>("sh"#i#"add_uw_op"); - def : Pat<(i64 (add_non_imm12 pat:$rs1, (XLenVT GPR:$rs2))), + def : Pat<(i64 (add_like_non_imm12 pat:$rs1, (XLenVT GPR:$rs2))), (!cast<Instruction>("SH"#i#"ADD_UW") pat:$rs1, GPR:$rs2)>; } -def : Pat<(i64 (add_non_imm12 (and GPR:$rs1, 0xFFFFFFFE), (XLenVT GPR:$rs2))), +def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0xFFFFFFFE), (XLenVT GPR:$rs2))), (SH1ADD (XLenVT (SRLIW GPR:$rs1, 1)), GPR:$rs2)>; -def : Pat<(i64 (add_non_imm12 (and GPR:$rs1, 0xFFFFFFFC), (XLenVT GPR:$rs2))), +def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0xFFFFFFFC), (XLenVT GPR:$rs2))), (SH2ADD (XLenVT (SRLIW GPR:$rs1, 2)), GPR:$rs2)>; -def : Pat<(i64 (add_non_imm12 (and GPR:$rs1, 0xFFFFFFF8), (XLenVT GPR:$rs2))), +def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0xFFFFFFF8), (XLenVT GPR:$rs2))), (SH3ADD (XLenVT (SRLIW GPR:$rs1, 3)), GPR:$rs2)>; // Use SRLI to clear the LSBs and SHXADD_UW to mask and shift. -def : Pat<(i64 (add_non_imm12 (and GPR:$rs1, 0x1FFFFFFFE), (XLenVT GPR:$rs2))), +def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0x1FFFFFFFE), (XLenVT GPR:$rs2))), (SH1ADD_UW (XLenVT (SRLI GPR:$rs1, 1)), GPR:$rs2)>; -def : Pat<(i64 (add_non_imm12 (and GPR:$rs1, 0x3FFFFFFFC), (XLenVT GPR:$rs2))), +def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0x3FFFFFFFC), (XLenVT GPR:$rs2))), (SH2ADD_UW (XLenVT (SRLI GPR:$rs1, 2)), GPR:$rs2)>; -def : Pat<(i64 (add_non_imm12 (and GPR:$rs1, 0x7FFFFFFF8), (XLenVT GPR:$rs2))), +def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0x7FFFFFFF8), (XLenVT GPR:$rs2))), (SH3ADD_UW (XLenVT (SRLI GPR:$rs1, 3)), GPR:$rs2)>; def : Pat<(i64 (mul (and_oneuse GPR:$r, 0xFFFFFFFF), C3LeftShiftUW:$i)), @@ -876,16 +873,13 @@ let Predicates = [HasStdExtZba, IsRV64] in { def : Pat<(shl (i64 (zext i32:$rs1)), uimm5:$shamt), (SLLI_UW GPR:$rs1, uimm5:$shamt)>; -def : Pat<(i64 (add_non_imm12 (zext GPR:$rs1), GPR:$rs2)), +def : Pat<(i64 (add_like_non_imm12 (zext GPR:$rs1), GPR:$rs2)), (ADD_UW GPR:$rs1, GPR:$rs2)>; def : Pat<(zext GPR:$src), (ADD_UW GPR:$src, (XLenVT X0))>; -def : Pat<(i64 (or_is_add_non_imm12 (zext GPR:$rs1), GPR:$rs2)), - (ADD_UW GPR:$rs1, GPR:$rs2)>; - foreach i = {1,2,3} in { defvar shxadd = !cast<Instruction>("SH"#i#"ADD"); - def : Pat<(i32 (add_non_imm12 (shl GPR:$rs1, (i64 i)), GPR:$rs2)), + def : Pat<(i32 (add_like_non_imm12 (shl GPR:$rs1, (i64 i)), GPR:$rs2)), (shxadd GPR:$rs1, GPR:$rs2)>; } } diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td index 2c8451c5c4ceb2c10ea22ceddcd936b282aca4fb..2a4448d7881fb5f05b3328408f3f331cdb69bbb1 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZc.td @@ -41,10 +41,20 @@ def RlistAsmOperand : AsmOperandClass { let DiagnosticType = "InvalidRlist"; } -def SpimmAsmOperand : AsmOperandClass { - let Name = "Spimm"; - let ParserMethod = "parseZcmpSpimm"; - let DiagnosticType = "InvalidSpimm"; +def StackAdjAsmOperand : AsmOperandClass { + let Name = "StackAdj"; + let ParserMethod = "parseZcmpStackAdj"; + let DiagnosticType = "InvalidStackAdj"; + let PredicateMethod = "isSpimm"; + let RenderMethod = "addSpimmOperands"; +} + +def NegStackAdjAsmOperand : AsmOperandClass { + let Name = "NegStackAdj"; + let ParserMethod = "parseZcmpNegStackAdj"; + let DiagnosticType = "InvalidStackAdj"; + let PredicateMethod = "isSpimm"; + let RenderMethod = "addSpimmOperands"; } def rlist : Operand<OtherVT> { @@ -59,12 +69,26 @@ def rlist : Operand<OtherVT> { // 0~3 Reserved for EABI return isUInt<4>(Imm) && Imm >= 4; }]; - } +} + +def stackadj : RISCVOp<OtherVT> { + let ParserMatchClass = StackAdjAsmOperand; + let PrintMethod = "printStackAdj"; + let DecoderMethod = "decodeZcmpSpimm"; + let OperandType = "OPERAND_SPIMM"; + let MCOperandPredicate = [{ + int64_t Imm; + if (!MCOp.evaluateAsConstantImm(Imm)) + return false; + return isShiftedUInt<2, 4>(Imm); + }]; +} -def spimm : Operand<OtherVT> { - let ParserMatchClass = SpimmAsmOperand; - let PrintMethod = "printSpimm"; +def negstackadj : RISCVOp<OtherVT> { + let ParserMatchClass = NegStackAdjAsmOperand; + let PrintMethod = "printNegStackAdj"; let DecoderMethod = "decodeZcmpSpimm"; + let OperandType = "OPERAND_SPIMM"; let MCOperandPredicate = [{ int64_t Imm; if (!MCOp.evaluateAsConstantImm(Imm)) @@ -124,14 +148,15 @@ class RVZcArith_r<bits<5> funct5, string OpcodeStr> : let Constraints = "$rd = $rd_wb"; } -class RVInstZcCPPP<bits<5> funct5, string opcodestr> - : RVInst16<(outs), (ins rlist:$rlist, spimm:$spimm), - opcodestr, "$rlist, $spimm", [], InstFormatOther> { +class RVInstZcCPPP<bits<5> funct5, string opcodestr, + DAGOperand immtype = stackadj> + : RVInst16<(outs), (ins rlist:$rlist, immtype:$stackadj), + opcodestr, "$rlist, $stackadj", [], InstFormatOther> { bits<4> rlist; - bits<16> spimm; + bits<16> stackadj; let Inst{1-0} = 0b10; - let Inst{3-2} = spimm{5-4}; + let Inst{3-2} = stackadj{5-4}; let Inst{7-4} = rlist; let Inst{12-8} = funct5; let Inst{15-13} = 0b101; @@ -195,7 +220,7 @@ def CM_MVSA01 : RVInst16CA<0b101011, 0b01, 0b10, (outs SR07:$rs1, SR07:$rs2), let DecoderNamespace = "RVZcmp", Predicates = [HasStdExtZcmp] in { let hasSideEffects = 0, mayLoad = 0, mayStore = 1, Uses = [X2], Defs = [X2] in -def CM_PUSH : RVInstZcCPPP<0b11000, "cm.push">, +def CM_PUSH : RVInstZcCPPP<0b11000, "cm.push", negstackadj>, Sched<[WriteIALU, ReadIALU, ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData, diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td index b4bd074b710179aeb5521ce003ff63a466a272f1..51a7a0a15d97d59f3b2bfb31b69c62223220c983 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvk.td @@ -67,31 +67,51 @@ class PALUVVNoVm<bits<6> funct6, RISCVVFormat opv, string opcodestr> let Inst{6-0} = OPC_OP_P.Value; } -// op vd, vs2, imm, vm -class PALUVINoVm<bits<6> funct6, string opcodestr, Operand optype = simm5> +// op vd, vs2, vs1 +class PALUVVNoVmTernary<bits<6> funct6, RISCVVFormat opv, string opcodestr> + : RVInstVV<funct6, opv, (outs VR:$vd_wb), + (ins VR:$vd, VR:$vs2, VR:$vs1), + opcodestr, "$vd, $vs2, $vs1"> { + let Constraints = "$vd = $vd_wb"; + let vm = 1; + let Inst{6-0} = OPC_OP_P.Value; +} + +// op vd, vs2, imm +class PALUVINoVm<bits<6> funct6, string opcodestr, Operand optype> : VALUVINoVm<funct6, opcodestr, optype> { let Inst{6-0} = OPC_OP_P.Value; let Inst{14-12} = OPMVV.Value; } -// op vd, vs2 (use vs1 as instruction encoding) -class PALUVs2NoVm<bits<6> funct6, bits<5> vs1, RISCVVFormat opv, string opcodestr> - : VALUVs2NoVm<funct6, vs1, opv, opcodestr> { +// op vd, vs2, imm where vd is also a source regardless of tail policy +class PALUVINoVmBinary<bits<6> funct6, string opcodestr, Operand optype> + : RVInstIVI<funct6, (outs VR:$vd_wb), + (ins VR:$vd, VR:$vs2, optype:$imm), + opcodestr, "$vd, $vs2, $imm"> { + let Constraints = "$vd = $vd_wb"; + let vm = 1; let Inst{6-0} = OPC_OP_P.Value; + let Inst{14-12} = OPMVV.Value; } -multiclass VAES_MV_V_S<bits<6> funct6_vv, bits<6> funct6_vs, bits<5> vs1, - RISCVVFormat opv, string opcodestr> { - def NAME # _VV : PALUVs2NoVm<funct6_vv, vs1, opv, opcodestr # ".vv">; - def NAME # _VS : PALUVs2NoVm<funct6_vs, vs1, opv, opcodestr # ".vs">; +// op vd, vs2 (use vs1 as instruction encoding) where vd is also a source +// regardless of tail policy +class PALUVs2NoVmBinary<bits<6> funct6, bits<5> vs1, RISCVVFormat opv, + string opcodestr> + : RVInstV<funct6, vs1, opv, (outs VR:$vd_wb), (ins VR:$vd, VR:$vs2), + opcodestr, "$vd, $vs2"> { + let Constraints = "$vd = $vd_wb"; + let vm = 1; + let Inst{6-0} = OPC_OP_P.Value; } -// vaeskf1.vi and vaeskf2.vi uses different opcode and format, we need -// to customize one for them. -class VAESKF_MV_I<bits<6> funct6, string opcodestr, Operand optype> - : VALUVINoVm<funct6, opcodestr, optype> { - let Inst{6-0} = OPC_OP_P.Value; - let Inst{14-12} = OPMVV.Value; +multiclass VAES_MV_V_S<bits<6> funct6_vv, bits<6> funct6_vs, bits<5> vs1, + RISCVVFormat opv, string opcodestr> { + let RVVConstraint = NoConstraint in + def NAME # _VV : PALUVs2NoVmBinary<funct6_vv, vs1, opv, opcodestr # ".vv">; + let RVVConstraint = VS2Constraint in + def NAME # _VS : PALUVs2NoVmBinary<funct6_vs, vs1, opv, opcodestr # ".vs">; } } // hasSideEffects = 0, mayLoad = 0, mayStore = 0 @@ -122,33 +142,35 @@ let Predicates = [HasStdExtZvkb] in { } // Predicates = [HasStdExtZvkb] let Predicates = [HasStdExtZvkg], RVVConstraint = NoConstraint in { - def VGHSH_VV : PALUVVNoVm<0b101100, OPMVV, "vghsh.vv">; - def VGMUL_VV : PALUVs2NoVm<0b101000, 0b10001, OPMVV, "vgmul.vv">; + def VGHSH_VV : PALUVVNoVmTernary<0b101100, OPMVV, "vghsh.vv">; + def VGMUL_VV : PALUVs2NoVmBinary<0b101000, 0b10001, OPMVV, "vgmul.vv">; } // Predicates = [HasStdExtZvkg] -let Predicates = [HasStdExtZvknhaOrZvknhb], RVVConstraint = NoConstraint in { - def VSHA2CH_VV : PALUVVNoVm<0b101110, OPMVV, "vsha2ch.vv">; - def VSHA2CL_VV : PALUVVNoVm<0b101111, OPMVV, "vsha2cl.vv">; - def VSHA2MS_VV : PALUVVNoVm<0b101101, OPMVV, "vsha2ms.vv">; +let Predicates = [HasStdExtZvknhaOrZvknhb], RVVConstraint = Sha2Constraint in { + def VSHA2CH_VV : PALUVVNoVmTernary<0b101110, OPMVV, "vsha2ch.vv">; + def VSHA2CL_VV : PALUVVNoVmTernary<0b101111, OPMVV, "vsha2cl.vv">; + def VSHA2MS_VV : PALUVVNoVmTernary<0b101101, OPMVV, "vsha2ms.vv">; } // Predicates = [HasStdExtZvknhaOrZvknhb] -let Predicates = [HasStdExtZvkned], RVVConstraint = NoConstraint in { +let Predicates = [HasStdExtZvkned]in { defm VAESDF : VAES_MV_V_S<0b101000, 0b101001, 0b00001, OPMVV, "vaesdf">; defm VAESDM : VAES_MV_V_S<0b101000, 0b101001, 0b00000, OPMVV, "vaesdm">; defm VAESEF : VAES_MV_V_S<0b101000, 0b101001, 0b00011, OPMVV, "vaesef">; defm VAESEM : VAES_MV_V_S<0b101000, 0b101001, 0b00010, OPMVV, "vaesem">; - def VAESKF1_VI : VAESKF_MV_I<0b100010, "vaeskf1.vi", uimm5>; - def VAESKF2_VI : VAESKF_MV_I<0b101010, "vaeskf2.vi", uimm5>; - def VAESZ_VS : PALUVs2NoVm<0b101001, 0b00111, OPMVV, "vaesz.vs">; + def VAESKF1_VI : PALUVINoVm<0b100010, "vaeskf1.vi", uimm5>; + def VAESKF2_VI : PALUVINoVmBinary<0b101010, "vaeskf2.vi", uimm5>; + let RVVConstraint = VS2Constraint in + def VAESZ_VS : PALUVs2NoVmBinary<0b101001, 0b00111, OPMVV, "vaesz.vs">; } // Predicates = [HasStdExtZvkned] -let Predicates = [HasStdExtZvksed], RVVConstraint = NoConstraint in { +let Predicates = [HasStdExtZvksed] in { + let RVVConstraint = NoConstraint in def VSM4K_VI : PALUVINoVm<0b100001, "vsm4k.vi", uimm5>; defm VSM4R : VAES_MV_V_S<0b101000, 0b101001, 0b10000, OPMVV, "vsm4r">; } // Predicates = [HasStdExtZvksed] -let Predicates = [HasStdExtZvksh], RVVConstraint = NoConstraint in { - def VSM3C_VI : PALUVINoVm<0b101011, "vsm3c.vi", uimm5>; +let Predicates = [HasStdExtZvksh], RVVConstraint = VS2Constraint in { + def VSM3C_VI : PALUVINoVmBinary<0b101011, "vsm3c.vi", uimm5>; def VSM3ME_VV : PALUVVNoVm<0b100000, OPMVV, "vsm3me.vv">; } // Predicates = [HasStdExtZvksh] @@ -180,147 +202,132 @@ class ZvkMxSet<string vd_lmul> { !eq(vd_lmul, "MF8") : [V_MF8]); } -class VPseudoUnaryNoMask_Zvk<DAGOperand RetClass, VReg OpClass, string Constraint = ""> : - Pseudo<(outs RetClass:$rd), - (ins RetClass:$merge, OpClass:$rs2, AVL:$vl, ixlenimm:$sew, ixlenimm:$policy), []>, +class VPseudoBinaryNoMask_Zvk<DAGOperand RetClass, VReg OpClass> : + Pseudo<(outs RetClass:$rd_wb), + (ins RetClass:$rd, OpClass:$rs2, AVL:$vl, ixlenimm:$sew, ixlenimm:$policy), []>, RISCVVPseudo { let mayLoad = 0; let mayStore = 0; let hasSideEffects = 0; - let Constraints = !interleave([Constraint, "$rd = $merge"], ","); + let Constraints = "$rd_wb = $rd"; let HasVLOp = 1; let HasSEWOp = 1; let HasVecPolicyOp = 1; let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); } -class VPseudoBinaryNoMask_Zvk<VReg RetClass, - VReg Op1Class, - DAGOperand Op2Class, - string Constraint> : - Pseudo<(outs RetClass:$rd), - (ins RetClass:$merge, Op1Class:$rs2, Op2Class:$rs1, +class VPseudoTernaryNoMask_Zvk<VReg RetClass, + VReg Op1Class, + DAGOperand Op2Class> : + Pseudo<(outs RetClass:$rd_wb), + (ins RetClass:$rd, Op1Class:$rs2, Op2Class:$rs1, AVL:$vl, ixlenimm:$sew, ixlenimm:$policy), []>, RISCVVPseudo { let mayLoad = 0; let mayStore = 0; let hasSideEffects = 0; - let Constraints = !interleave([Constraint, "$rd = $merge"], ","); + let Constraints = "$rd_wb = $rd"; let HasVLOp = 1; let HasSEWOp = 1; let HasVecPolicyOp = 1; let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); } -multiclass VPseudoBinaryNoMask_Zvk<VReg RetClass, +multiclass VPseudoBinaryNoMaskTU_Zvk<VReg RetClass, + VReg Op1Class, + DAGOperand Op2Class, + LMULInfo MInfo, + string Constraint = "", + int sew = 0> { + let VLMul = MInfo.value, SEW=sew in { + defvar suffix = !if(sew, "_" # MInfo.MX # "_E" # sew, "_" # MInfo.MX); + def suffix : VPseudoBinaryNoMaskTU<RetClass, Op1Class, Op2Class, + Constraint>; + } +} + +multiclass VPseudoTernaryNoMask_Zvk<VReg RetClass, VReg Op1Class, DAGOperand Op2Class, - LMULInfo MInfo, - string Constraint = ""> { + LMULInfo MInfo> { let VLMul = MInfo.value in - def "_" # MInfo.MX : VPseudoBinaryNoMask_Zvk<RetClass, Op1Class, Op2Class, - Constraint>; + def "_" # MInfo.MX : VPseudoTernaryNoMask_Zvk<RetClass, Op1Class, Op2Class>; } -multiclass VPseudoUnaryV_V_NoMask_Zvk<LMULInfo m, string Constraint = ""> { +multiclass VPseudoBinaryV_V_NoMask_Zvk<LMULInfo m> { let VLMul = m.value in { - def "_VV_" # m.MX : VPseudoUnaryNoMask_Zvk<m.vrclass, m.vrclass, Constraint>; + def "_VV_" # m.MX : VPseudoBinaryNoMask_Zvk<m.vrclass, m.vrclass>; } } -multiclass VPseudoUnaryV_S_NoMask_Zvk<LMULInfo m, string Constraint = ""> { +multiclass VPseudoBinaryV_S_NoMask_Zvk<LMULInfo m> { let VLMul = m.value in foreach vs2_lmul = ZvkMxSet<m.MX>.vs2_lmuls in - def "_VS_" # m.MX # "_" # vs2_lmul.MX : VPseudoUnaryNoMask_Zvk<m.vrclass, vs2_lmul.vrclass, Constraint>; + def "_VS_" # m.MX # "_" # vs2_lmul.MX : VPseudoBinaryNoMask_Zvk<m.vrclass, vs2_lmul.vrclass>; } -multiclass VPseudoVALU_V_NoMask_Zvk<string Constraint = ""> { +multiclass VPseudoVALU_V_NoMask_Zvk { foreach m = MxListVF4 in { defvar mx = m.MX; - defvar WriteVIALUV_MX = !cast<SchedWrite>("WriteVIALUV_" # mx); - defvar ReadVIALUV_MX = !cast<SchedRead>("ReadVIALUV_" # mx); - - defm "" : VPseudoUnaryV_V_NoMask_Zvk<m, Constraint>, - Sched<[WriteVIALUV_MX, ReadVIALUV_MX, ReadVIALUV_MX, ReadVMask]>; + defm "" : VPseudoBinaryV_V_NoMask_Zvk<m>, + SchedBinary<"WriteVIALUV", "ReadVIALUV", "ReadVIALUV", mx>; } } -multiclass VPseudoVALU_S_NoMask_Zvk<string Constraint = ""> { +multiclass VPseudoVALU_S_NoMask_Zvk { foreach m = MxListVF4 in { defvar mx = m.MX; - defvar WriteVIALUV_MX = !cast<SchedWrite>("WriteVIALUV_" # mx); - defvar ReadVIALUV_MX = !cast<SchedRead>("ReadVIALUV_" # mx); - - defm "" : VPseudoUnaryV_S_NoMask_Zvk<m, Constraint>, - Sched<[WriteVIALUV_MX, ReadVIALUV_MX, ReadVIALUV_MX, ReadVMask]>; + defm "" : VPseudoBinaryV_S_NoMask_Zvk<m>, + SchedBinary<"WriteVIALUV", "ReadVIALUV", "ReadVIALUV", mx>; } } -multiclass VPseudoVALU_V_S_NoMask_Zvk<string Constraint = ""> { - defm "" : VPseudoVALU_V_NoMask_Zvk<Constraint>; - defm "" : VPseudoVALU_S_NoMask_Zvk<Constraint>; -} +multiclass VPseudoVALU_V_S_NoMask_Zvk + : VPseudoVALU_V_NoMask_Zvk, VPseudoVALU_S_NoMask_Zvk; -multiclass VPseudoVALU_VV_NoMask_Zvk<string Constraint = ""> { +multiclass VPseudoVALU_VV_NoMask_Zvk { foreach m = MxListVF4 in { defvar mx = m.MX; - defvar WriteVIALUV_MX = !cast<SchedWrite>("WriteVIALUV_" # mx); - defvar ReadVIALUV_MX = !cast<SchedRead>("ReadVIALUV_" # mx); - - defm _VV : VPseudoBinaryNoMask_Zvk<m.vrclass, m.vrclass, m.vrclass, m, - Constraint>, - Sched<[WriteVIALUV_MX, ReadVIALUV_MX, ReadVIALUV_MX, ReadVMask]>; + defm _VV : VPseudoTernaryNoMask_Zvk<m.vrclass, m.vrclass, m.vrclass, m>, + SchedTernary<"WriteVIALUV", "ReadVIALUV", "ReadVIALUV", "ReadVIALUV", mx>; } } -multiclass VPseudoVALU_VI_NoMask_Zvk<Operand ImmType = simm5, string Constraint = ""> { +multiclass VPseudoVALU_VI_NoMask_Zvk { foreach m = MxListVF4 in { defvar mx = m.MX; - defvar WriteVIALUV_MX = !cast<SchedWrite>("WriteVIALUV_" # mx); - defvar ReadVIALUV_MX = !cast<SchedRead>("ReadVIALUV_" # mx); - - defm _VI : VPseudoBinaryNoMask_Zvk<m.vrclass, m.vrclass, ImmType, m, - Constraint>, - Sched<[WriteVIALUV_MX, ReadVIALUV_MX, ReadVIALUV_MX, ReadVMask]>; + defm _VI : VPseudoTernaryNoMask_Zvk<m.vrclass, m.vrclass, uimm5, m>, + SchedTernary<"WriteVIALUV", "ReadVIALUV", "ReadVIALUV", "ReadVIALUV", mx>; } } -multiclass VPseudoVALU_VI_NoMaskTU_Zvk<Operand ImmType = uimm5, string Constraint = ""> { +multiclass VPseudoVALU_VI_NoMaskTU_Zvk { foreach m = MxListVF4 in { defvar mx = m.MX; - defvar WriteVIALUV_MX = !cast<SchedWrite>("WriteVIALUV_" # mx); - defvar ReadVIALUV_MX = !cast<SchedRead>("ReadVIALUV_" # mx); - - defm _VI : VPseudoBinaryNoMask<m.vrclass, m.vrclass, ImmType, m, - Constraint>, - Sched<[WriteVIALUV_MX, ReadVIALUV_MX, ReadVIALUV_MX, ReadVMask]>; + defm _VI : VPseudoBinaryNoMaskTU_Zvk<m.vrclass, m.vrclass, uimm5, m>, + SchedBinary<"WriteVIALUV", "ReadVIALUV", "ReadVIALUV", mx, + forceMergeOpRead=true>; } } -multiclass VPseudoVALU_VV_NoMaskTU_Zvk<string Constraint = ""> { +multiclass VPseudoVALU_VV_NoMaskTU_Zvk { foreach m = MxListVF4 in { defvar mx = m.MX; - defvar WriteVIALUV_MX = !cast<SchedWrite>("WriteVIALUV_" # mx); - defvar ReadVIALUV_MX = !cast<SchedRead>("ReadVIALUV_" # mx); - - defm _VV : VPseudoBinaryNoMask<m.vrclass, m.vrclass, m.vrclass, m, - Constraint>, - Sched<[WriteVIALUV_MX, ReadVIALUV_MX, ReadVIALUV_MX, ReadVMask]>; + defm _VV : VPseudoBinaryNoMaskTU_Zvk<m.vrclass, m.vrclass, m.vrclass, m>, + SchedBinary<"WriteVIALUV", "ReadVIALUV", "ReadVIALUV", mx, + forceMergeOpRead=true>; } } multiclass VPseudoVCLMUL_VV_VX { foreach m = MxList in { defvar mx = m.MX; - defvar WriteVIALUV_MX = !cast<SchedWrite>("WriteVIALUV_" # mx); - defvar WriteVIALUX_MX = !cast<SchedWrite>("WriteVIALUV_" # mx); - defvar ReadVIALUV_MX = !cast<SchedRead>("ReadVIALUV_" # mx); - defvar ReadVIALUX_MX = !cast<SchedRead>("ReadVIALUX_" # mx); - defm "" : VPseudoBinaryV_VV<m>, - Sched<[WriteVIALUV_MX, ReadVIALUV_MX, ReadVIALUV_MX, ReadVMask]>; + SchedBinary<"WriteVIALUV", "ReadVIALUV", "ReadVIALUV", mx, + forceMergeOpRead=true>; defm "" : VPseudoBinaryV_VX<m>, - Sched<[WriteVIALUX_MX, ReadVIALUV_MX, ReadVIALUX_MX, ReadVMask]>; + SchedBinary<"WriteVIALUX", "ReadVIALUV", "ReadVIALUX", mx, + forceMergeOpRead=true>; } } @@ -336,11 +343,17 @@ multiclass VPseudoUnaryV_V<LMULInfo m> { multiclass VPseudoVALU_V { foreach m = MxList in { defvar mx = m.MX; - defvar WriteVIALUV_MX = !cast<SchedWrite>("WriteVIALUV_" # mx); - defvar ReadVIALUV_MX = !cast<SchedRead>("ReadVIALUV_" # mx); - defm "" : VPseudoUnaryV_V<m>, - Sched<[WriteVIALUV_MX, ReadVIALUV_MX, ReadVIALUV_MX, ReadVMask]>; + SchedUnary<"WriteVIALUV", "ReadVIALUV", mx, + forceMergeOpRead=true>; + } +} + +multiclass VPseudoVWALU_VV_VX_VI<Operand ImmType> : VPseudoVWALU_VV_VX { + foreach m = MxListW in { + defm "" : VPseudoBinaryW_VI<ImmType, m>, + SchedUnary<"WriteVIWALUV", "ReadVIWALUV", m.MX, + forceMergeOpRead=true>; } } @@ -376,7 +389,7 @@ let Predicates = [HasStdExtZvkned] in { defm PseudoVAESEF : VPseudoVALU_V_S_NoMask_Zvk; defm PseudoVAESEM : VPseudoVALU_V_S_NoMask_Zvk; defm PseudoVAESKF1 : VPseudoVALU_VI_NoMaskTU_Zvk; - defm PseudoVAESKF2 : VPseudoVALU_VI_NoMask_Zvk<uimm5>; + defm PseudoVAESKF2 : VPseudoVALU_VI_NoMask_Zvk; defm PseudoVAESZ : VPseudoVALU_S_NoMask_Zvk; } // Predicates = [HasStdExtZvkned] @@ -392,7 +405,7 @@ let Predicates = [HasStdExtZvksed] in { } // Predicates = [HasStdExtZvksed] let Predicates = [HasStdExtZvksh] in { - defm PseudoVSM3C : VPseudoVALU_VI_NoMask_Zvk<uimm5>; + defm PseudoVSM3C : VPseudoVALU_VI_NoMask_Zvk; defm PseudoVSM3ME : VPseudoVALU_VV_NoMaskTU_Zvk; } // Predicates = [HasStdExtZvksh] @@ -668,44 +681,44 @@ foreach vtiToWti = AllWidenableIntVectors in { //===----------------------------------------------------------------------===// class VPatUnaryNoMask_Zvk<string intrinsic_name, - string inst, - string kind, - ValueType result_type, - ValueType op2_type, - int sew, - LMULInfo vlmul, - VReg result_reg_class, - VReg op2_reg_class> : + string inst, + string kind, + ValueType result_type, + ValueType op2_type, + int sew, + LMULInfo vlmul, + VReg result_reg_class, + VReg op2_reg_class> : Pat<(result_type (!cast<Intrinsic>(intrinsic_name) - (result_type result_reg_class:$merge), + (result_type result_reg_class:$rd), (op2_type op2_reg_class:$rs2), VLOpFrag, (XLenVT timm:$policy))), (!cast<Instruction>(inst#"_"#kind#"_"#vlmul.MX) - (result_type result_reg_class:$merge), + (result_type result_reg_class:$rd), (op2_type op2_reg_class:$rs2), GPR:$vl, sew, (XLenVT timm:$policy))>; class VPatUnaryNoMask_VS_Zvk<string intrinsic_name, - string inst, - string kind, - ValueType result_type, - ValueType op2_type, - int sew, - LMULInfo vlmul, - LMULInfo vs2_lmul, - VReg result_reg_class, - VReg op2_reg_class> : + string inst, + string kind, + ValueType result_type, + ValueType op2_type, + int sew, + LMULInfo vlmul, + LMULInfo vs2_lmul, + VReg result_reg_class, + VReg op2_reg_class> : Pat<(result_type (!cast<Intrinsic>(intrinsic_name) - (result_type result_reg_class:$merge), + (result_type result_reg_class:$rd), (op2_type op2_reg_class:$rs2), VLOpFrag, (XLenVT timm:$policy))), (!cast<Instruction>(inst#"_"#kind#"_"#vlmul.MX#"_"#vs2_lmul.MX) - (result_type result_reg_class:$merge), + (result_type result_reg_class:$rd), (op2_type op2_reg_class:$rs2), GPR:$vl, sew, (XLenVT timm:$policy))>; multiclass VPatUnaryV_V_NoMask_Zvk<string intrinsic, string instruction, - list<VTypeInfo> vtilist> { + list<VTypeInfo> vtilist> { foreach vti = vtilist in def : VPatUnaryNoMask_Zvk<intrinsic # "_vv", instruction, "VV", vti.Vector, vti.Vector, vti.Log2SEW, @@ -713,7 +726,7 @@ multiclass VPatUnaryV_V_NoMask_Zvk<string intrinsic, string instruction, } multiclass VPatUnaryV_S_NoMaskVectorCrypto<string intrinsic, string instruction, - list<VTypeInfo> vtilist> { + list<VTypeInfo> vtilist> { foreach vti = vtilist in foreach vti_vs2 = ZvkI32IntegerVectors<vti.LMul.MX>.vs2_types in def : VPatUnaryNoMask_VS_Zvk<intrinsic # "_vs", instruction, "VS", @@ -722,13 +735,13 @@ multiclass VPatUnaryV_S_NoMaskVectorCrypto<string intrinsic, string instruction, } multiclass VPatUnaryV_V_S_NoMask_Zvk<string intrinsic, string instruction, - list<VTypeInfo> vtilist> { + list<VTypeInfo> vtilist> { defm : VPatUnaryV_V_NoMask_Zvk<intrinsic, instruction, vtilist>; defm : VPatUnaryV_S_NoMaskVectorCrypto<intrinsic, instruction, vtilist>; } multiclass VPatBinaryV_VV_NoMask<string intrinsic, string instruction, - list<VTypeInfo> vtilist> { + list<VTypeInfo> vtilist> { foreach vti = vtilist in def : VPatTernaryNoMaskWithPolicy<intrinsic, instruction, "VV", vti.Vector, vti.Vector, vti.Vector, @@ -737,7 +750,8 @@ multiclass VPatBinaryV_VV_NoMask<string intrinsic, string instruction, } multiclass VPatBinaryV_VI_NoMask<string intrinsic, string instruction, - list<VTypeInfo> vtilist, Operand imm_type = tuimm5> { + list<VTypeInfo> vtilist, + Operand imm_type = tuimm5> { foreach vti = vtilist in def : VPatTernaryNoMaskWithPolicy<intrinsic, instruction, "VI", vti.Vector, vti.Vector, XLenVT, @@ -746,7 +760,8 @@ multiclass VPatBinaryV_VI_NoMask<string intrinsic, string instruction, } multiclass VPatBinaryV_VI_NoMaskTU<string intrinsic, string instruction, - list<VTypeInfo> vtilist, Operand imm_type = tuimm5> { + list<VTypeInfo> vtilist, + Operand imm_type = tuimm5> { foreach vti = vtilist in def : VPatBinaryNoMaskTU<intrinsic, instruction # "_VI_" # vti.LMul.MX, vti.Vector, vti.Vector, XLenVT, vti.Log2SEW, @@ -754,7 +769,7 @@ multiclass VPatBinaryV_VI_NoMaskTU<string intrinsic, string instruction, } multiclass VPatBinaryV_VV_NoMaskTU<string intrinsic, string instruction, - list<VTypeInfo> vtilist> { + list<VTypeInfo> vtilist> { foreach vti = vtilist in def : VPatBinaryNoMaskTU<intrinsic, instruction # "_VV_" # vti.LMul.MX, vti.Vector, vti.Vector, vti.Vector, vti.Log2SEW, @@ -812,13 +827,14 @@ multiclass VPatBinaryV_VI_VROL<string intrinsic, string instruction, } multiclass VPatBinaryV_VV_VX_VROL<string intrinsic, string instruction, - string instruction2, list<VTypeInfo> vtilist> + string instruction2, list<VTypeInfo> vtilist> : VPatBinaryV_VV<intrinsic, instruction, vtilist>, VPatBinaryV_VX_VROTATE<intrinsic, instruction, vtilist>, VPatBinaryV_VI_VROL<intrinsic, instruction2, vtilist>; multiclass VPatBinaryV_VV_VX_VI_VROR<string intrinsic, string instruction, - list<VTypeInfo> vtilist, Operand ImmType = uimm6> + list<VTypeInfo> vtilist, + Operand ImmType = uimm6> : VPatBinaryV_VV<intrinsic, instruction, vtilist>, VPatBinaryV_VX_VROTATE<intrinsic, instruction, vtilist>, VPatBinaryV_VI<intrinsic, instruction, vtilist, ImmType>; diff --git a/llvm/lib/Target/RISCV/RISCVMakeCompressible.cpp b/llvm/lib/Target/RISCV/RISCVMakeCompressible.cpp index af864ba0fbc46f2ba5abc95c99d427bef76e083b..3f423450618df22e7abd024e57448be86a2f4fe2 100644 --- a/llvm/lib/Target/RISCV/RISCVMakeCompressible.cpp +++ b/llvm/lib/Target/RISCV/RISCVMakeCompressible.cpp @@ -99,6 +99,13 @@ static unsigned log2LdstWidth(unsigned Opcode) { switch (Opcode) { default: llvm_unreachable("Unexpected opcode"); + case RISCV::LBU: + case RISCV::SB: + return 0; + case RISCV::LH: + case RISCV::LHU: + case RISCV::SH: + return 1; case RISCV::LW: case RISCV::SW: case RISCV::FLW: @@ -112,17 +119,47 @@ static unsigned log2LdstWidth(unsigned Opcode) { } } +// Return bit field size of immediate operand of Opcode. +static unsigned offsetMask(unsigned Opcode) { + switch (Opcode) { + default: + llvm_unreachable("Unexpected opcode"); + case RISCV::LBU: + case RISCV::SB: + return maskTrailingOnes<unsigned>(2U); + case RISCV::LH: + case RISCV::LHU: + case RISCV::SH: + return maskTrailingOnes<unsigned>(1U); + case RISCV::LW: + case RISCV::SW: + case RISCV::FLW: + case RISCV::FSW: + case RISCV::LD: + case RISCV::SD: + case RISCV::FLD: + case RISCV::FSD: + return maskTrailingOnes<unsigned>(5U); + } +} + // Return a mask for the offset bits of a non-stack-pointer based compressed // load/store. static uint8_t compressedLDSTOffsetMask(unsigned Opcode) { - return 0x1f << log2LdstWidth(Opcode); + return offsetMask(Opcode) << log2LdstWidth(Opcode); } // Return true if Offset fits within a compressed stack-pointer based // load/store. static bool compressibleSPOffset(int64_t Offset, unsigned Opcode) { - return log2LdstWidth(Opcode) == 2 ? isShiftedUInt<6, 2>(Offset) - : isShiftedUInt<6, 3>(Offset); + // Compressed sp-based loads and stores only work for 32/64 bits. + switch (log2LdstWidth(Opcode)) { + case 2: + return isShiftedUInt<6, 2>(Offset); + case 3: + return isShiftedUInt<6, 3>(Offset); + } + return false; } // Given an offset for a load/store, return the adjustment required to the base @@ -147,6 +184,10 @@ static bool isCompressibleLoad(const MachineInstr &MI) { switch (MI.getOpcode()) { default: return false; + case RISCV::LBU: + case RISCV::LH: + case RISCV::LHU: + return STI.hasStdExtZcb(); case RISCV::LW: case RISCV::LD: return STI.hasStdExtCOrZca(); @@ -164,6 +205,9 @@ static bool isCompressibleStore(const MachineInstr &MI) { switch (MI.getOpcode()) { default: return false; + case RISCV::SB: + case RISCV::SH: + return STI.hasStdExtZcb(); case RISCV::SW: case RISCV::SD: return STI.hasStdExtCOrZca(); diff --git a/llvm/lib/Target/RISCV/RISCVOptWInstrs.cpp b/llvm/lib/Target/RISCV/RISCVOptWInstrs.cpp index dcf70e8cad64080672cfdcb7a029c08affc5c434..39d420c2fbf0806b997bb5c86936d9d80412dfb5 100644 --- a/llvm/lib/Target/RISCV/RISCVOptWInstrs.cpp +++ b/llvm/lib/Target/RISCV/RISCVOptWInstrs.cpp @@ -672,7 +672,7 @@ bool RISCVOptWInstrs::stripWSuffixes(MachineFunction &MF, const RISCVInstrInfo &TII, const RISCVSubtarget &ST, MachineRegisterInfo &MRI) { - if (DisableStripWSuffix) + if (DisableStripWSuffix || !ST.enableStripWSuffix()) return false; bool MadeChange = false; diff --git a/llvm/lib/Target/RISCV/RISCVProcessors.td b/llvm/lib/Target/RISCV/RISCVProcessors.td index 8c75df41f5e3952f54e429713afb9881d94149fc..fd6d6078ec238b8d2890d43064e1d92d396f6ef5 100644 --- a/llvm/lib/Target/RISCV/RISCVProcessors.td +++ b/llvm/lib/Target/RISCV/RISCVProcessors.td @@ -245,7 +245,7 @@ def SIFIVE_P450 : RISCVProcessorModel<"sifive-p450", SiFiveP400Model, TuneLUIADDIFusion, TuneAUIPCADDIFusion]>; -def SIFIVE_P670 : RISCVProcessorModel<"sifive-p670", NoSchedModel, +def SIFIVE_P670 : RISCVProcessorModel<"sifive-p670", SiFiveP600Model, [Feature64Bit, FeatureStdExtZifencei, FeatureStdExtM, diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp index a68674b221d38eaae6d98f39b3b094586da756ad..11c3f2d57eb00fa5256265e58d352f9219811f29 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -71,6 +71,9 @@ RISCVRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { : CSR_Interrupt_SaveList; } + bool HasVectorCSR = + MF->getFunction().getCallingConv() == CallingConv::RISCV_VectorCall; + switch (Subtarget.getTargetABI()) { default: llvm_unreachable("Unrecognized ABI"); @@ -79,12 +82,18 @@ RISCVRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { return CSR_ILP32E_LP64E_SaveList; case RISCVABI::ABI_ILP32: case RISCVABI::ABI_LP64: + if (HasVectorCSR) + return CSR_ILP32_LP64_V_SaveList; return CSR_ILP32_LP64_SaveList; case RISCVABI::ABI_ILP32F: case RISCVABI::ABI_LP64F: + if (HasVectorCSR) + return CSR_ILP32F_LP64F_V_SaveList; return CSR_ILP32F_LP64F_SaveList; case RISCVABI::ABI_ILP32D: case RISCVABI::ABI_LP64D: + if (HasVectorCSR) + return CSR_ILP32D_LP64D_V_SaveList; return CSR_ILP32D_LP64D_SaveList; } } @@ -431,29 +440,35 @@ bool RISCVRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, } if (!IsRVVSpill) { - if (MI.getOpcode() == RISCV::ADDI && !isInt<12>(Offset.getFixed())) { + int64_t Val = Offset.getFixed(); + int64_t Lo12 = SignExtend64<12>(Val); + unsigned Opc = MI.getOpcode(); + if (Opc == RISCV::ADDI && !isInt<12>(Val)) { // We chose to emit the canonical immediate sequence rather than folding // the offset into the using add under the theory that doing so doesn't // save dynamic instruction count and some target may fuse the canonical // 32 bit immediate sequence. We still need to clear the portion of the // offset encoded in the immediate. MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0); + } else if ((Opc == RISCV::PREFETCH_I || Opc == RISCV::PREFETCH_R || + Opc == RISCV::PREFETCH_W) && + (Lo12 & 0b11111) != 0) { + // Prefetch instructions require the offset to be 32 byte aligned. + MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0); + } else if ((Opc == RISCV::PseudoRV32ZdinxLD || + Opc == RISCV::PseudoRV32ZdinxSD) && + Lo12 >= 2044) { + // This instruction will be split into 2 instructions. The second + // instruction will add 4 to the immediate. If that would overflow 12 + // bits, we can't fold the offset. + MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0); } else { // We can encode an add with 12 bit signed immediate in the immediate // operand of our user instruction. As a result, the remaining // offset can by construction, at worst, a LUI and a ADD. - int64_t Val = Offset.getFixed(); - int64_t Lo12 = SignExtend64<12>(Val); - if ((MI.getOpcode() == RISCV::PREFETCH_I || - MI.getOpcode() == RISCV::PREFETCH_R || - MI.getOpcode() == RISCV::PREFETCH_W) && - (Lo12 & 0b11111) != 0) - MI.getOperand(FIOperandNum + 1).ChangeToImmediate(0); - else { - MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Lo12); - Offset = StackOffset::get((uint64_t)Val - (uint64_t)Lo12, - Offset.getScalable()); - } + MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Lo12); + Offset = StackOffset::get((uint64_t)Val - (uint64_t)Lo12, + Offset.getScalable()); } } @@ -659,12 +674,18 @@ RISCVRegisterInfo::getCallPreservedMask(const MachineFunction & MF, return CSR_ILP32E_LP64E_RegMask; case RISCVABI::ABI_ILP32: case RISCVABI::ABI_LP64: + if (CC == CallingConv::RISCV_VectorCall) + return CSR_ILP32_LP64_V_RegMask; return CSR_ILP32_LP64_RegMask; case RISCVABI::ABI_ILP32F: case RISCVABI::ABI_LP64F: + if (CC == CallingConv::RISCV_VectorCall) + return CSR_ILP32F_LP64F_V_RegMask; return CSR_ILP32F_LP64F_RegMask; case RISCVABI::ABI_ILP32D: case RISCVABI::ABI_LP64D: + if (CC == CallingConv::RISCV_VectorCall) + return CSR_ILP32D_LP64D_V_RegMask; return CSR_ILP32D_LP64D_RegMask; } } @@ -742,8 +763,11 @@ bool RISCVRegisterInfo::getRegAllocationHints( bool NeedGPRC) -> void { Register Reg = MO.getReg(); Register PhysReg = Reg.isPhysical() ? Reg : Register(VRM->getPhys(Reg)); - if (PhysReg && (!NeedGPRC || RISCV::GPRCRegClass.contains(PhysReg))) { - assert(!MO.getSubReg() && !VRRegMO.getSubReg() && "Unexpected subreg!"); + // TODO: Support GPRPair subregisters? Need to be careful with even/odd + // registers. If the virtual register is an odd register of a pair and the + // physical register is even (or vice versa), we should not add the hint. + if (PhysReg && (!NeedGPRC || RISCV::GPRCRegClass.contains(PhysReg)) && + !MO.getSubReg() && !VRRegMO.getSubReg()) { if (!MRI->isReserved(PhysReg) && !is_contained(Hints, PhysReg)) TwoAddrHints.insert(PhysReg); } diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td index 225b57554c1dc01234bcc62cb16d19c8dcb2e3fa..90c4a7193ee3379059d7f94cacf0d2c8c1647fca 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td @@ -64,9 +64,14 @@ def sub_vrm1_6 : ComposedSubRegIndex<sub_vrm2_3, sub_vrm1_0>; def sub_vrm1_7 : ComposedSubRegIndex<sub_vrm2_3, sub_vrm1_1>; // GPR sizes change with HwMode. -// FIXME: Support HwMode in SubRegIndex? -def sub_gpr_even : SubRegIndex<-1>; -def sub_gpr_odd : SubRegIndex<-1, -1>; +def sub_gpr_even : SubRegIndex<32> { + let SubRegRanges = SubRegRangeByHwMode<[RV32, RV64], + [SubRegRange<32>, SubRegRange<64>]>; +} +def sub_gpr_odd : SubRegIndex<32, 32> { + let SubRegRanges = SubRegRangeByHwMode<[RV32, RV64], + [SubRegRange<32, 32>, SubRegRange<64, 64>]>; +} } // Namespace = "RISCV" // Integer registers @@ -573,7 +578,7 @@ let RegAltNameIndices = [ABIRegAltName] in { } let RegInfos = RegInfoByHwMode<[RV32, RV64], - [RegInfo<64, 64, 64>, RegInfo<128, 128, 128>]>, + [RegInfo<64, 64, 32>, RegInfo<128, 128, 64>]>, DecoderMethod = "DecodeGPRPairRegisterClass" in def GPRPair : RegisterClass<"RISCV", [XLenPairFVT], 64, (add X10_X11, X12_X13, X14_X15, X16_X17, diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td index 240d170bfcf6f9f67302d4aa7bc0a5b0b8d7f832..54a13889ee698ad83906536463b326b68d7eb321 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td @@ -186,7 +186,7 @@ class SiFive7AnyToGPRBypass<SchedRead read, int cycles = 2> WriteBEXT, WriteBEXTI, WriteCLZ, WriteCLZ32, WriteCTZ, WriteCTZ32, WriteCPOP, WriteCPOP32, - WriteREV8, WriteORCB, WriteSFB, + WriteREV8, WriteORCB, WriteIMinMax, WriteSFB, WriteIMul, WriteIMul32, WriteIDiv, WriteIDiv32, WriteIRem, WriteIRem32, @@ -305,6 +305,9 @@ def : WriteRes<WriteCPOP32, [SiFive7PipeB]>; // orc.b is in the late-B ALU. def : WriteRes<WriteORCB, [SiFive7PipeB]>; +// min/max are in the late-B ALU +def : WriteRes<WriteIMinMax, [SiFive7PipeB]>; + // rev8 is in the late-A and late-B ALUs. def : WriteRes<WriteREV8, [SiFive7PipeAB]>; @@ -947,7 +950,7 @@ def : InstRW<[WriteIALU], (instrs COPY)>; def : SiFive7AnyToGPRBypass<ReadJmp>; def : SiFive7AnyToGPRBypass<ReadJalr>; def : ReadAdvance<ReadCSR, 0>; -def : ReadAdvance<ReadStoreData, 0>; +def : SiFive7AnyToGPRBypass<ReadStoreData>; def : ReadAdvance<ReadMemBase, 0>; def : SiFive7AnyToGPRBypass<ReadIALU>; def : SiFive7AnyToGPRBypass<ReadIALU32>; @@ -1041,6 +1044,7 @@ def : SiFive7AnyToGPRBypass<ReadCTZ32>; def : ReadAdvance<ReadCPOP, 0>; def : ReadAdvance<ReadCPOP32, 0>; def : SiFive7AnyToGPRBypass<ReadORCB>; +def : SiFive7AnyToGPRBypass<ReadIMinMax>; def : SiFive7AnyToGPRBypass<ReadREV8>; def : SiFive7AnyToGPRBypass<ReadSHXADD>; def : SiFive7AnyToGPRBypass<ReadSHXADD32>; diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP400.td b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP400.td index d02d34a0fb9c58e261d186d10ac1e8773902158c..8ec2e4ff885ebbbffba429893a90cb33bb71c0b4 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP400.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP400.td @@ -109,6 +109,7 @@ def : WriteRes<WriteCTZ, [SiFiveP400IntArith]>; def : WriteRes<WriteCTZ32, [SiFiveP400IntArith]>; def : WriteRes<WriteORCB, [SiFiveP400IntArith]>; +def : WriteRes<WriteIMinMax, [SiFiveP400IntArith]>; def : WriteRes<WriteREV8, [SiFiveP400IntArith]>; @@ -349,6 +350,7 @@ def : ReadAdvance<ReadCTZ32, 0>; def : ReadAdvance<ReadCPOP, 0>; def : ReadAdvance<ReadCPOP32, 0>; def : ReadAdvance<ReadORCB, 0>; +def : ReadAdvance<ReadIMinMax, 0>; def : ReadAdvance<ReadREV8, 0>; def : ReadAdvance<ReadSHXADD, 0>; def : ReadAdvance<ReadSHXADD32, 0>; diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td new file mode 100644 index 0000000000000000000000000000000000000000..54016959d348e3393d6fc7cc067523c6aab31f89 --- /dev/null +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFiveP600.td @@ -0,0 +1,1024 @@ +//==- RISCVSchedSiFiveP600.td - SiFiveP600 Scheduling Defs ---*- tablegen -*-=// +// +// 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 +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// + +/// c is true if mx has the worst case behavior compared to LMULs in MxList. +/// On the SiFiveP600, the worst case LMUL is the Largest LMUL +/// and the worst case sew is the smallest SEW for that LMUL. +class SiFiveP600IsWorstCaseMX<string mx, list<string> MxList> { + string LLMUL = LargestLMUL<MxList>.r; + bit c = !eq(mx, LLMUL); +} + +class SiFiveP600IsWorstCaseMXSEW<string mx, int sew, list<string> MxList, bit isF = 0> { + string LLMUL = LargestLMUL<MxList>.r; + int SSEW = SmallestSEW<mx, isF>.r; + bit c = !and(!eq(mx, LLMUL), !eq(sew, SSEW)); +} + +// 1 Micro-Op per cycle. +class SiFiveP600GetLMulCycles<string mx> { + int c = !cond( + !eq(mx, "M1") : 1, + !eq(mx, "M2") : 2, + !eq(mx, "M4") : 4, + !eq(mx, "M8") : 8, + !eq(mx, "MF2") : 1, + !eq(mx, "MF4") : 1, + !eq(mx, "MF8") : 1 + ); +} + +// Latency for segmented loads and stores are calculated as vl * nf. +class SiFiveP600GetCyclesSegmented<string mx, int sew, int nf> { + defvar VLEN = 128; + defvar VLUpperBound = !cond( + !eq(mx, "M1") : !div(VLEN, sew), + !eq(mx, "M2") : !div(!mul(VLEN, 2), sew), + !eq(mx, "M4") : !div(!mul(VLEN, 4), sew), + !eq(mx, "M8") : !div(!mul(VLEN, 8), sew), + !eq(mx, "MF2") : !div(!div(VLEN, 2), sew), + !eq(mx, "MF4") : !div(!div(VLEN, 4), sew), + !eq(mx, "MF8") : !div(!div(VLEN, 8), sew), + ); + int c = !mul(VLUpperBound, nf); +} + +// SiFiveP600 machine model for scheduling and other instruction cost heuristics. +def SiFiveP600Model : SchedMachineModel { + let IssueWidth = 4; // 4 micro-ops are dispatched per cycle. + let MicroOpBufferSize = 160; // Max micro-ops that can be buffered. + let LoadLatency = 4; // Cycles for loads to access the cache. + let MispredictPenalty = 9; // Extra cycles for a mispredicted branch. + let PostRAScheduler = true; + let UnsupportedFeatures = [HasStdExtZbkb, HasStdExtZbkc, HasStdExtZbkx, + HasStdExtZknd, HasStdExtZkne, HasStdExtZknh, + HasStdExtZksed, HasStdExtZksh, HasStdExtZkr, + HasVendorXSfvqmaccqoq]; + let CompleteModel = false; +} + +let SchedModel = SiFiveP600Model in { + +def SiFiveP600IEXQ0 : ProcResource<1>; +def SiFiveP600IEXQ1 : ProcResource<1>; +def SiFiveP600IEXQ2 : ProcResource<1>; +def SiFiveP600IEXQ3 : ProcResource<1>; +def SiFiveP600FEXQ0 : ProcResource<1>; +def SiFiveP600FEXQ1 : ProcResource<1>; + +// Two Load/Store ports that can issue either two loads, two stores, or one load +// and one store (P550 has one load and one separate store pipe). +def SiFiveP600LDST : ProcResource<2>; + +// 4-wide pipeline with 4 ALU pipes. +def SiFiveP600IntArith : ProcResGroup<[SiFiveP600IEXQ0, SiFiveP600IEXQ1, SiFiveP600IEXQ2, SiFiveP600IEXQ3]>; +defvar SiFiveP600SYS = SiFiveP600IEXQ0; +defvar SiFiveP600CMOV = SiFiveP600IEXQ0; +defvar SiFiveP600MulI2F = SiFiveP600IEXQ1; +def SiFiveP600Branch : ProcResGroup<[SiFiveP600IEXQ2, SiFiveP600IEXQ3]>; +def SiFiveP600Div : ProcResource<1>; + +def SiFiveP600FloatArith : ProcResGroup<[SiFiveP600FEXQ0, SiFiveP600FEXQ1]>; +defvar SiFiveP600F2I = SiFiveP600FEXQ0; +def SiFiveP600FloatDiv : ProcResource<1>; + +// Vector pipeline +// VEXQ0 handle Mask, Simple Slide instructions, +// VEXQ1 handle Complex Slide, Permutation, Reductions, Divide instructions. +// Other vector instructions can be done in VEXQ0 and VEXQ1. +def SiFiveP600VEXQ0 : ProcResource<1>; +def SiFiveP600VEXQ1 : ProcResource<1>; +def SiFiveP600VectorArith : ProcResGroup<[SiFiveP600VEXQ0, SiFiveP600VEXQ1]>; +def SiFiveP600VLD : ProcResource<1>; +def SiFiveP600VST : ProcResource<1>; +def SiFiveP600VDiv : ProcResource<1>; +def SiFiveP600VFloatDiv : ProcResource<1>; + +// Integer arithmetic and logic +def : WriteRes<WriteIALU, [SiFiveP600IntArith]>; +def : WriteRes<WriteIALU32, [SiFiveP600IntArith]>; +def : WriteRes<WriteShiftImm, [SiFiveP600IntArith]>; +def : WriteRes<WriteShiftImm32, [SiFiveP600IntArith]>; +def : WriteRes<WriteShiftReg, [SiFiveP600IntArith]>; +def : WriteRes<WriteShiftReg32, [SiFiveP600IntArith]>; +// Branching +def : WriteRes<WriteJmp, [SiFiveP600Branch]>; +def : WriteRes<WriteJal, [SiFiveP600Branch]>; +def : WriteRes<WriteJalr, [SiFiveP600Branch]>; + +// CMOV +def P600WriteCMOV : SchedWriteRes<[SiFiveP600Branch, SiFiveP600CMOV]> { + let Latency = 2; + let NumMicroOps = 2; +} +def : InstRW<[P600WriteCMOV], (instrs PseudoCCMOVGPRNoX0)>; + +let Latency = 3 in { +// Integer multiplication +def : WriteRes<WriteIMul, [SiFiveP600MulI2F]>; +def : WriteRes<WriteIMul32, [SiFiveP600MulI2F]>; +// cpop[w] look exactly like multiply. +def : WriteRes<WriteCPOP, [SiFiveP600MulI2F]>; +def : WriteRes<WriteCPOP32, [SiFiveP600MulI2F]>; +} + +// Integer division +def : WriteRes<WriteIDiv, [SiFiveP600MulI2F, SiFiveP600Div]> { + let Latency = 35; + let ReleaseAtCycles = [1, 34]; +} +def : WriteRes<WriteIDiv32, [SiFiveP600MulI2F, SiFiveP600Div]> { + let Latency = 20; + let ReleaseAtCycles = [1, 19]; +} + +// Integer remainder +def : WriteRes<WriteIRem, [SiFiveP600MulI2F, SiFiveP600Div]> { + let Latency = 35; + let ReleaseAtCycles = [1, 34]; +} +def : WriteRes<WriteIRem32, [SiFiveP600MulI2F, SiFiveP600Div]> { + let Latency = 20; + let ReleaseAtCycles = [1, 19]; +} + +// Bitmanip +def : WriteRes<WriteRotateImm, [SiFiveP600IntArith]>; +def : WriteRes<WriteRotateImm32, [SiFiveP600IntArith]>; +def : WriteRes<WriteRotateReg, [SiFiveP600IntArith]>; +def : WriteRes<WriteRotateReg32, [SiFiveP600IntArith]>; + +def : WriteRes<WriteCLZ, [SiFiveP600IntArith]>; +def : WriteRes<WriteCLZ32, [SiFiveP600IntArith]>; +def : WriteRes<WriteCTZ, [SiFiveP600IntArith]>; +def : WriteRes<WriteCTZ32, [SiFiveP600IntArith]>; + +def : WriteRes<WriteORCB, [SiFiveP600IntArith]>; +def : WriteRes<WriteIMinMax, [SiFiveP600IntArith]>; + +def : WriteRes<WriteREV8, [SiFiveP600IntArith]>; + +def : WriteRes<WriteSHXADD, [SiFiveP600IntArith]>; +def : WriteRes<WriteSHXADD32, [SiFiveP600IntArith]>; + +def : WriteRes<WriteSingleBit, [SiFiveP600IntArith]>; +def : WriteRes<WriteSingleBitImm, [SiFiveP600IntArith]>; +def : WriteRes<WriteBEXT, [SiFiveP600IntArith]>; +def : WriteRes<WriteBEXTI, [SiFiveP600IntArith]>; + +// Memory +def : WriteRes<WriteSTB, [SiFiveP600LDST]>; +def : WriteRes<WriteSTH, [SiFiveP600LDST]>; +def : WriteRes<WriteSTW, [SiFiveP600LDST]>; +def : WriteRes<WriteSTD, [SiFiveP600LDST]>; +def : WriteRes<WriteFST16, [SiFiveP600LDST]>; +def : WriteRes<WriteFST32, [SiFiveP600LDST]>; +def : WriteRes<WriteFST64, [SiFiveP600LDST]>; + +let Latency = 4 in { +def : WriteRes<WriteLDB, [SiFiveP600LDST]>; +def : WriteRes<WriteLDH, [SiFiveP600LDST]>; +} +let Latency = 4 in { +def : WriteRes<WriteLDW, [SiFiveP600LDST]>; +def : WriteRes<WriteLDD, [SiFiveP600LDST]>; +} + +let Latency = 6 in { +def : WriteRes<WriteFLD16, [SiFiveP600LDST]>; +def : WriteRes<WriteFLD32, [SiFiveP600LDST]>; +def : WriteRes<WriteFLD64, [SiFiveP600LDST]>; +} + +// Atomic memory +let Latency = 3 in { +def : WriteRes<WriteAtomicSTW, [SiFiveP600LDST]>; +def : WriteRes<WriteAtomicSTD, [SiFiveP600LDST]>; +def : WriteRes<WriteAtomicW, [SiFiveP600LDST]>; +def : WriteRes<WriteAtomicD, [SiFiveP600LDST]>; +def : WriteRes<WriteAtomicLDW, [SiFiveP600LDST]>; +def : WriteRes<WriteAtomicLDD, [SiFiveP600LDST]>; +} + +// Floating point +let Latency = 2 in { +def : WriteRes<WriteFAdd16, [SiFiveP600FloatArith]>; +def : WriteRes<WriteFAdd32, [SiFiveP600FloatArith]>; +def : WriteRes<WriteFAdd64, [SiFiveP600FloatArith]>; +} +let Latency = 3 in { +def : WriteRes<WriteFMul16, [SiFiveP600FloatArith]>; +def : WriteRes<WriteFMul32, [SiFiveP600FloatArith]>; +def : WriteRes<WriteFMul64, [SiFiveP600FloatArith]>; +} +let Latency = 4 in { +def : WriteRes<WriteFMA16, [SiFiveP600FloatArith]>; +def : WriteRes<WriteFMA32, [SiFiveP600FloatArith]>; +def : WriteRes<WriteFMA64, [SiFiveP600FloatArith]>; +} + +let Latency = 2 in { +def : WriteRes<WriteFSGNJ16, [SiFiveP600FloatArith]>; +def : WriteRes<WriteFSGNJ32, [SiFiveP600FloatArith]>; +def : WriteRes<WriteFSGNJ64, [SiFiveP600FloatArith]>; + +def : WriteRes<WriteFMinMax16, [SiFiveP600FloatArith]>; +def : WriteRes<WriteFMinMax32, [SiFiveP600FloatArith]>; +def : WriteRes<WriteFMinMax64, [SiFiveP600FloatArith]>; +} + +// Half precision. +def : WriteRes<WriteFDiv16, [SiFiveP600FEXQ1, SiFiveP600FloatDiv]> { + let Latency = 4; + let ReleaseAtCycles = [1, 4]; +} +def : WriteRes<WriteFSqrt16, [SiFiveP600FEXQ1, SiFiveP600FloatDiv]> { + let Latency = 18; + let ReleaseAtCycles = [1, 17]; +} + +// Single precision. +def : WriteRes<WriteFDiv32, [SiFiveP600FEXQ1, SiFiveP600FloatDiv]> { + let Latency = 6; + let ReleaseAtCycles = [1, 6]; +} +def : WriteRes<WriteFSqrt32, [SiFiveP600FEXQ1, SiFiveP600FloatDiv]> { + let Latency = 18; + let ReleaseAtCycles = [1, 17]; +} + +// Double precision +def : WriteRes<WriteFDiv64, [SiFiveP600FEXQ1, SiFiveP600FloatDiv]> { + let Latency = 11; + let ReleaseAtCycles = [1, 11]; +} +def : WriteRes<WriteFSqrt64, [SiFiveP600FEXQ1, SiFiveP600FloatDiv]> { + let Latency = 33; + let ReleaseAtCycles = [1, 32]; +} + +// Conversions +let Latency = 2 in { +def : WriteRes<WriteFCvtI32ToF16, [SiFiveP600MulI2F]>; +def : WriteRes<WriteFCvtI32ToF32, [SiFiveP600MulI2F]>; +def : WriteRes<WriteFCvtI32ToF64, [SiFiveP600MulI2F]>; +def : WriteRes<WriteFCvtI64ToF16, [SiFiveP600MulI2F]>; +def : WriteRes<WriteFCvtI64ToF32, [SiFiveP600MulI2F]>; +def : WriteRes<WriteFCvtI64ToF64, [SiFiveP600MulI2F]>; +def : WriteRes<WriteFCvtF16ToI32, [SiFiveP600F2I]>; +def : WriteRes<WriteFCvtF16ToI64, [SiFiveP600F2I]>; +def : WriteRes<WriteFCvtF16ToF32, [SiFiveP600FloatArith]>; +def : WriteRes<WriteFCvtF16ToF64, [SiFiveP600FloatArith]>; +def : WriteRes<WriteFCvtF32ToI32, [SiFiveP600F2I]>; +def : WriteRes<WriteFCvtF32ToI64, [SiFiveP600F2I]>; +def : WriteRes<WriteFCvtF32ToF16, [SiFiveP600FloatArith]>; +def : WriteRes<WriteFCvtF32ToF64, [SiFiveP600FloatArith]>; +def : WriteRes<WriteFCvtF64ToI32, [SiFiveP600F2I]>; +def : WriteRes<WriteFCvtF64ToI64, [SiFiveP600F2I]>; +def : WriteRes<WriteFCvtF64ToF16, [SiFiveP600FloatArith]>; +def : WriteRes<WriteFCvtF64ToF32, [SiFiveP600FloatArith]>; + +def : WriteRes<WriteFClass16, [SiFiveP600F2I]>; +def : WriteRes<WriteFClass32, [SiFiveP600F2I]>; +def : WriteRes<WriteFClass64, [SiFiveP600F2I]>; +def : WriteRes<WriteFCmp16, [SiFiveP600F2I]>; +def : WriteRes<WriteFCmp32, [SiFiveP600F2I]>; +def : WriteRes<WriteFCmp64, [SiFiveP600F2I]>; +def : WriteRes<WriteFMovI16ToF16, [SiFiveP600MulI2F]>; +def : WriteRes<WriteFMovF16ToI16, [SiFiveP600F2I]>; +def : WriteRes<WriteFMovI32ToF32, [SiFiveP600MulI2F]>; +def : WriteRes<WriteFMovF32ToI32, [SiFiveP600F2I]>; +def : WriteRes<WriteFMovI64ToF64, [SiFiveP600MulI2F]>; +def : WriteRes<WriteFMovF64ToI64, [SiFiveP600F2I]>; +} + +// 6. Configuration-Setting Instructions +def : WriteRes<WriteVSETVLI, [SiFiveP600SYS]>; +def : WriteRes<WriteVSETIVLI, [SiFiveP600SYS]>; +def : WriteRes<WriteVSETVL, [SiFiveP600SYS]>; + +// 7. Vector Loads and Stores +// FIXME: This unit is still being improved, currently +// it is based on stage numbers. Estimates are optimistic, +// latency may be longer. +foreach mx = SchedMxList in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxList>.c; + let Latency = 8, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVLDE", [SiFiveP600VLD], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVLDM", [SiFiveP600VLD], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVLDFF", [SiFiveP600VLD], mx, IsWorstCase>; + } + let Latency = 12, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVLDS8", [SiFiveP600VLD], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVLDS16", [SiFiveP600VLD], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVLDS32", [SiFiveP600VLD], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVLDS64", [SiFiveP600VLD], mx, IsWorstCase>; + } + let Latency = 12, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVLDUX8", [SiFiveP600VLD], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVLDUX16", [SiFiveP600VLD], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVLDUX32", [SiFiveP600VLD], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVLDUX64", [SiFiveP600VLD], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVLDOX8", [SiFiveP600VLD], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVLDOX16", [SiFiveP600VLD], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVLDOX32", [SiFiveP600VLD], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVLDOX64", [SiFiveP600VLD], mx, IsWorstCase>; + } +} + +foreach mx = SchedMxList in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxList>.c; + let Latency = 8, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVSTE", [SiFiveP600VST], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSTM", [SiFiveP600VST], mx, IsWorstCase>; + } + let Latency = 12, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVSTS8", [SiFiveP600VST], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSTS16", [SiFiveP600VST], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSTS32", [SiFiveP600VST], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSTS64", [SiFiveP600VST], mx, IsWorstCase>; + } + let Latency = 12, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVSTUX8", [SiFiveP600VST], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSTUX16", [SiFiveP600VST], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSTUX32", [SiFiveP600VST], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSTUX64", [SiFiveP600VST], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSTOX8", [SiFiveP600VST], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSTOX16", [SiFiveP600VST], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSTOX32", [SiFiveP600VST], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSTOX64", [SiFiveP600VST], mx, IsWorstCase>; + } +} + +foreach mx = SchedMxList in { + foreach nf=2-8 in { + foreach eew = [8, 16, 32, 64] in { + defvar LMulLat = SiFiveP600GetCyclesSegmented<mx, eew, nf>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxList>.c; + let Latency = !add(12, LMulLat), ReleaseAtCycles = [!add(12, LMulLat)] in { + defm "" : LMULWriteResMX<"WriteVLSEG" # nf # "e" # eew, [SiFiveP600VLD], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVLSEGFF" # nf # "e" # eew, [SiFiveP600VLD], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVLSSEG" # nf # "e" # eew, [SiFiveP600VLD], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVLUXSEG" # nf # "e" # eew, [SiFiveP600VLD], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVLOXSEG" # nf # "e" # eew, [SiFiveP600VLD], mx, IsWorstCase>; + } + let Latency = !add(1, LMulLat), ReleaseAtCycles = [!add(12, LMulLat)] in { + defm "" : LMULWriteResMX<"WriteVSSEG" # nf # "e" # eew, [SiFiveP600VST], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSSSEG" # nf # "e" # eew, [SiFiveP600VST], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSUXSEG" # nf # "e" # eew, [SiFiveP600VST], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSOXSEG" # nf # "e" # eew, [SiFiveP600VST], mx, IsWorstCase>; + } + } + } +} + +// Whole register move/load/store +foreach LMul = [1, 2, 4, 8] in { + let Latency = 8, ReleaseAtCycles = [LMul] in { + def : WriteRes<!cast<SchedWrite>("WriteVLD" # LMul # "R"), [SiFiveP600VLD]>; + def : WriteRes<!cast<SchedWrite>("WriteVST" # LMul # "R"), [SiFiveP600VST]>; + } + let Latency = LMul, ReleaseAtCycles = [LMul] in { + def : WriteRes<!cast<SchedWrite>("WriteVMov" # LMul # "V"), [SiFiveP600VectorArith]>; + } +} + +// 11. Vector Integer Arithmetic Instructions +foreach mx = SchedMxList in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxList>.c; + let Latency = 1, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVIALUV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIALUX", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIALUI", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVExtV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVICALUV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVICALUX", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVICALUI", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVICmpV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVICmpX", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVICmpI", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIMergeV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIMergeX", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIMergeI", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIMovV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIMovX", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIMovI", [SiFiveP600VectorArith], mx, IsWorstCase>; + } + let Latency = 6, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVShiftV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVShiftX", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVShiftI", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIMinMaxV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIMinMaxX", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIMulV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIMulX", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIMulAddV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIMulAddX", [SiFiveP600VectorArith], mx, IsWorstCase>; + } +} +// Widening +foreach mx = SchedMxListW in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxListW>.c; + let Latency = 6, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVIWALUV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIWALUX", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIWALUI", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIWMulV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIWMulX", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIWMulAddV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIWMulAddX", [SiFiveP600VectorArith], mx, IsWorstCase>; + } +} + +// Worst case needs 64 cycles if SEW is equal to 64. +foreach mx = SchedMxList in { + foreach sew = SchedSEWSet<mx>.val in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMXSEW<mx, sew, SchedMxList>.c; + let Latency = 64, ReleaseAtCycles = [LMulLat, !mul(63, LMulLat)] in { + defm "" : LMULSEWWriteResMXSEW<"WriteVIDivV", [SiFiveP600VEXQ1, SiFiveP600VDiv], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVIDivX", [SiFiveP600VEXQ1, SiFiveP600VDiv], mx, sew, IsWorstCase>; + } + } +} + +// Narrowing Shift and Clips +foreach mx = SchedMxListW in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxListW>.c; + let Latency = 2, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVNShiftV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVNShiftX", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVNShiftI", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVNClipV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVNClipX", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVNClipI", [SiFiveP600VectorArith], mx, IsWorstCase>; + } +} + +// 12. Vector Fixed-Point Arithmetic Instructions +foreach mx = SchedMxList in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxList>.c; + let Latency = 6, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVSALUV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSALUX", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSALUI", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVAALUV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVAALUX", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSMulV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSMulX", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSShiftV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSShiftX", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVSShiftI", [SiFiveP600VectorArith], mx, IsWorstCase>; + } +} + +// 13. Vector Floating-Point Instructions +foreach mx = SchedMxList in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxList>.c; + let Latency = 6, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVFALUV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFALUF", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFMulV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFMulF", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFMulAddV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFMulAddF", [SiFiveP600VectorArith], mx, IsWorstCase>; + } + let Latency = 3, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVFCvtIToFV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFCvtFToIV", [SiFiveP600VectorArith], mx, IsWorstCase>; + } + let Latency = 2, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVFCmpV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFCmpF", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFRecpV", [SiFiveP600VectorArith], mx, IsWorstCase>; + } + let Latency = 1, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVFSgnjV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFSgnjF", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFMinMaxV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFMinMaxF", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFClassV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFMergeV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFMovV", [SiFiveP600VectorArith], mx, IsWorstCase>; + } +} + +// Widening +foreach mx = SchedMxListW in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxListW>.c; + let Latency = 3, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVFWCvtIToFV", [SiFiveP600VectorArith], mx, IsWorstCase>; + } +} +foreach mx = SchedMxListFW in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxListFW>.c; + let Latency = 6, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVFWCvtFToIV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFWCvtFToFV", [SiFiveP600VectorArith], mx, IsWorstCase>; + } +} +foreach mx = SchedMxListFW in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxListFW>.c; + let Latency = 6, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVFWALUV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFWMulV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFWMulAddV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFWMulAddF", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFWMulF", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFWALUF", [SiFiveP600VectorArith], mx, IsWorstCase>; + } +} +// Narrowing +foreach mx = SchedMxListW in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxListW>.c; + let Latency = 3, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVFNCvtFToIV", [SiFiveP600VectorArith], mx, IsWorstCase>; + } +} +foreach mx = SchedMxListFW in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxListFW>.c; + let Latency = 3, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVFNCvtIToFV", [SiFiveP600VectorArith], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFNCvtFToFV", [SiFiveP600VectorArith], mx, IsWorstCase>; + } +} + +// Worst case needs 76 cycles if SEW is equal to 64. +foreach mx = SchedMxListF in { + foreach sew = SchedSEWSet<mx, 1>.val in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMXSEW<mx, sew, SchedMxListF, 1>.c; + let Latency = 76, ReleaseAtCycles = [LMulLat, !mul(76, LMulLat)] in { + defm "" : LMULSEWWriteResMXSEW<"WriteVFDivV", [SiFiveP600VEXQ1, SiFiveP600VFloatDiv], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFDivF", [SiFiveP600VEXQ1, SiFiveP600VFloatDiv], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFSqrtV", [SiFiveP600VEXQ1, SiFiveP600VFloatDiv], mx, sew, IsWorstCase>; + } + } +} + +// 14. Vector Reduction Operations +foreach mx = SchedMxList in { + foreach sew = SchedSEWSet<mx>.val in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMXSEW<mx, sew, SchedMxList>.c; + let Latency = !add(2, !mul(2, LMulLat)), ReleaseAtCycles = [LMulLat] in { + defm "" : LMULSEWWriteResMXSEW<"WriteVIRedV_From", [SiFiveP600VEXQ1], + mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVIRedMinMaxV_From", [SiFiveP600VEXQ1], + mx, sew, IsWorstCase>; + } + } +} + +foreach mx = SchedMxListWRed in { + foreach sew = SchedSEWSet<mx, 0, 1>.val in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMXSEW<mx, sew, SchedMxListWRed>.c; + let Latency = !add(2, !mul(2, LMulLat)), ReleaseAtCycles = [LMulLat] in { + defm "" : LMULSEWWriteResMXSEW<"WriteVIWRedV_From", [SiFiveP600VEXQ1], + mx, sew, IsWorstCase>; + } + } +} + +foreach mx = SchedMxListF in { + foreach sew = SchedSEWSet<mx, 1>.val in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMXSEW<mx, sew, SchedMxListF, 1>.c; + let Latency = !add(6, !mul(6, LMulLat)), ReleaseAtCycles = [LMulLat] in { + defm "" : LMULSEWWriteResMXSEW<"WriteVFRedV_From", [SiFiveP600VEXQ1], + mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFRedMinMaxV_From", + [SiFiveP600VEXQ1], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFRedOV_From", [SiFiveP600VEXQ1], + mx, sew, IsWorstCase>; + } + } +} + +foreach mx = SchedMxListFWRed in { + foreach sew = SchedSEWSet<mx, 1, 1>.val in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMXSEW<mx, sew, SchedMxListFWRed, 1>.c; + let Latency = !add(6, !mul(6, LMulLat)), ReleaseAtCycles = [LMulLat] in { + defm "" : LMULSEWWriteResMXSEW<"WriteVFWRedV_From", [SiFiveP600VEXQ1], + mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVFWRedOV_From", [SiFiveP600VEXQ1], + mx, sew, IsWorstCase>; + } + } +} + +// 15. Vector Mask Instructions +foreach mx = SchedMxList in { + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxList>.c; + let Latency = 1, ReleaseAtCycles = [1] in { + defm "" : LMULWriteResMX<"WriteVMALUV", [SiFiveP600VEXQ0], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVMPopV", [SiFiveP600VEXQ0], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVMFFSV", [SiFiveP600VEXQ0], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVMSFSV", [SiFiveP600VEXQ0], mx, IsWorstCase>; + } + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + let Latency = 1, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVIotaV", [SiFiveP600VEXQ0], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVIdxV", [SiFiveP600VEXQ0], mx, IsWorstCase>; + } +} + +// 16. Vector Permutation Instructions +// Simple Slide +foreach mx = SchedMxList in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxList>.c; + let Latency = 2, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVISlideI", [SiFiveP600VEXQ0], mx, IsWorstCase>; + } + let Latency = 1, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVISlide1X", [SiFiveP600VEXQ0], mx, IsWorstCase>; + defm "" : LMULWriteResMX<"WriteVFSlide1F", [SiFiveP600VEXQ0], mx, IsWorstCase>; + } +} +foreach mx = ["MF8", "MF4", "MF2", "M1"] in { + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxList>.c; + let Latency = 2, ReleaseAtCycles = [1] in { + defm "" : LMULWriteResMX<"WriteVISlideX", [SiFiveP600VEXQ0], mx, IsWorstCase>; + } +} + +// Complex Slide +foreach mx = ["M8", "M4", "M2"] in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxList>.c; + let Latency = !add(4, LMulLat), ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVISlideX", [SiFiveP600VEXQ1], mx, IsWorstCase>; + } +} + +let Latency = 2, ReleaseAtCycles = [1] in { + def : WriteRes<WriteVMovSX, [SiFiveP600VectorArith]>; + def : WriteRes<WriteVMovXS, [SiFiveP600VectorArith]>; +} +let Latency = 6, ReleaseAtCycles = [1] in { + def : WriteRes<WriteVMovSF, [SiFiveP600VectorArith]>; + def : WriteRes<WriteVMovFS, [SiFiveP600VectorArith]>; +} + +// Simple Gather and Compress +foreach mx = ["MF8", "MF4", "MF2", "M1"] in { + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxList>.c; + let Latency = 3, ReleaseAtCycles = [1] in { + defm "" : LMULWriteResMX<"WriteVRGatherVX", [SiFiveP600VEXQ1], mx, IsWorstCase>; + } +} + +foreach mx = ["MF8", "MF4", "MF2", "M1"] in { + foreach sew = SchedSEWSet<mx>.val in { + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxList>.c; + let Latency = 3, ReleaseAtCycles = [1] in { + defm "" : LMULSEWWriteResMXSEW<"WriteVRGatherVV", [SiFiveP600VEXQ1], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVCompressV", [SiFiveP600VEXQ1], mx, sew, IsWorstCase>; + } + } +} + +// Complex Gather and Compress +foreach mx = ["M2", "M4", "M8"] in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxList>.c; + let Latency = 6, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVRGatherVX", [SiFiveP600VEXQ1], mx, IsWorstCase>; + } +} + +foreach mx = ["M2", "M4", "M8"] in { + foreach sew = SchedSEWSet<mx>.val in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMXSEW<mx, sew, SchedMxList>.c; + let Latency = 6, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULSEWWriteResMXSEW<"WriteVRGatherVV", [SiFiveP600VEXQ1], mx, sew, IsWorstCase>; + defm "" : LMULSEWWriteResMXSEW<"WriteVCompressV", [SiFiveP600VEXQ1], mx, sew, IsWorstCase>; + } + } +} + +// Simple Vrgather.vi +foreach mx = SchedMxList in { + defvar LMulLat = SiFiveP600GetLMulCycles<mx>.c; + defvar IsWorstCase = SiFiveP600IsWorstCaseMX<mx, SchedMxList>.c; + let Latency = 3, ReleaseAtCycles = [LMulLat] in { + defm "" : LMULWriteResMX<"WriteVRGatherVI", [SiFiveP600VEXQ1], mx, IsWorstCase>; + } +} + +// Others +def : WriteRes<WriteCSR, [SiFiveP600SYS]>; +def : WriteRes<WriteNop, []>; +def : WriteRes<WriteRdVLENB, [SiFiveP600SYS]>; + +// FIXME: This could be better modeled by looking at the regclasses of the operands. +def : InstRW<[WriteIALU, ReadIALU], (instrs COPY)>; + +//===----------------------------------------------------------------------===// +// Bypass and advance +def : ReadAdvance<ReadJmp, 0>; +def : ReadAdvance<ReadJalr, 0>; +def : ReadAdvance<ReadCSR, 0>; +def : ReadAdvance<ReadStoreData, 0>; +def : ReadAdvance<ReadMemBase, 0>; +def : ReadAdvance<ReadIALU, 0>; +def : ReadAdvance<ReadIALU32, 0>; +def : ReadAdvance<ReadShiftImm, 0>; +def : ReadAdvance<ReadShiftImm32, 0>; +def : ReadAdvance<ReadShiftReg, 0>; +def : ReadAdvance<ReadShiftReg32, 0>; +def : ReadAdvance<ReadIDiv, 0>; +def : ReadAdvance<ReadIDiv32, 0>; +def : ReadAdvance<ReadIRem, 0>; +def : ReadAdvance<ReadIRem32, 0>; +def : ReadAdvance<ReadIMul, 0>; +def : ReadAdvance<ReadIMul32, 0>; +def : ReadAdvance<ReadAtomicWA, 0>; +def : ReadAdvance<ReadAtomicWD, 0>; +def : ReadAdvance<ReadAtomicDA, 0>; +def : ReadAdvance<ReadAtomicDD, 0>; +def : ReadAdvance<ReadAtomicLDW, 0>; +def : ReadAdvance<ReadAtomicLDD, 0>; +def : ReadAdvance<ReadAtomicSTW, 0>; +def : ReadAdvance<ReadAtomicSTD, 0>; +def : ReadAdvance<ReadFStoreData, 0>; +def : ReadAdvance<ReadFMemBase, 0>; +def : ReadAdvance<ReadFAdd16, 0>; +def : ReadAdvance<ReadFAdd32, 0>; +def : ReadAdvance<ReadFAdd64, 0>; +def : ReadAdvance<ReadFMul16, 0>; +def : ReadAdvance<ReadFMA16, 0>; +def : ReadAdvance<ReadFMA16Addend, 0>; +def : ReadAdvance<ReadFMul32, 0>; +def : ReadAdvance<ReadFMA32, 0>; +def : ReadAdvance<ReadFMA32Addend, 0>; +def : ReadAdvance<ReadFMul64, 0>; +def : ReadAdvance<ReadFMA64, 0>; +def : ReadAdvance<ReadFMA64Addend, 0>; +def : ReadAdvance<ReadFDiv16, 0>; +def : ReadAdvance<ReadFDiv32, 0>; +def : ReadAdvance<ReadFDiv64, 0>; +def : ReadAdvance<ReadFSqrt16, 0>; +def : ReadAdvance<ReadFSqrt32, 0>; +def : ReadAdvance<ReadFSqrt64, 0>; +def : ReadAdvance<ReadFCmp16, 0>; +def : ReadAdvance<ReadFCmp32, 0>; +def : ReadAdvance<ReadFCmp64, 0>; +def : ReadAdvance<ReadFSGNJ16, 0>; +def : ReadAdvance<ReadFSGNJ32, 0>; +def : ReadAdvance<ReadFSGNJ64, 0>; +def : ReadAdvance<ReadFMinMax16, 0>; +def : ReadAdvance<ReadFMinMax32, 0>; +def : ReadAdvance<ReadFMinMax64, 0>; +def : ReadAdvance<ReadFCvtF16ToI32, 0>; +def : ReadAdvance<ReadFCvtF16ToI64, 0>; +def : ReadAdvance<ReadFCvtF32ToI32, 0>; +def : ReadAdvance<ReadFCvtF32ToI64, 0>; +def : ReadAdvance<ReadFCvtF64ToI32, 0>; +def : ReadAdvance<ReadFCvtF64ToI64, 0>; +def : ReadAdvance<ReadFCvtI32ToF16, 0>; +def : ReadAdvance<ReadFCvtI32ToF32, 0>; +def : ReadAdvance<ReadFCvtI32ToF64, 0>; +def : ReadAdvance<ReadFCvtI64ToF16, 0>; +def : ReadAdvance<ReadFCvtI64ToF32, 0>; +def : ReadAdvance<ReadFCvtI64ToF64, 0>; +def : ReadAdvance<ReadFCvtF32ToF64, 0>; +def : ReadAdvance<ReadFCvtF64ToF32, 0>; +def : ReadAdvance<ReadFCvtF16ToF32, 0>; +def : ReadAdvance<ReadFCvtF32ToF16, 0>; +def : ReadAdvance<ReadFCvtF16ToF64, 0>; +def : ReadAdvance<ReadFCvtF64ToF16, 0>; +def : ReadAdvance<ReadFMovF16ToI16, 0>; +def : ReadAdvance<ReadFMovI16ToF16, 0>; +def : ReadAdvance<ReadFMovF32ToI32, 0>; +def : ReadAdvance<ReadFMovI32ToF32, 0>; +def : ReadAdvance<ReadFMovF64ToI64, 0>; +def : ReadAdvance<ReadFMovI64ToF64, 0>; +def : ReadAdvance<ReadFClass16, 0>; +def : ReadAdvance<ReadFClass32, 0>; +def : ReadAdvance<ReadFClass64, 0>; + +// Bitmanip +def : ReadAdvance<ReadRotateImm, 0>; +def : ReadAdvance<ReadRotateImm32, 0>; +def : ReadAdvance<ReadRotateReg, 0>; +def : ReadAdvance<ReadRotateReg32, 0>; +def : ReadAdvance<ReadCLZ, 0>; +def : ReadAdvance<ReadCLZ32, 0>; +def : ReadAdvance<ReadCTZ, 0>; +def : ReadAdvance<ReadCTZ32, 0>; +def : ReadAdvance<ReadCPOP, 0>; +def : ReadAdvance<ReadCPOP32, 0>; +def : ReadAdvance<ReadORCB, 0>; +def : ReadAdvance<ReadIMinMax, 0>; +def : ReadAdvance<ReadREV8, 0>; +def : ReadAdvance<ReadSHXADD, 0>; +def : ReadAdvance<ReadSHXADD32, 0>; +def : ReadAdvance<ReadSingleBit, 0>; +def : ReadAdvance<ReadSingleBitImm, 0>; + +// 6. Configuration-Setting Instructions +def : ReadAdvance<ReadVSETVLI, 0>; +def : ReadAdvance<ReadVSETVL, 0>; + +// 7. Vector Loads and Stores +def : ReadAdvance<ReadVLDX, 0>; +def : ReadAdvance<ReadVSTX, 0>; +defm "" : LMULReadAdvance<"ReadVSTEV", 0>; +defm "" : LMULReadAdvance<"ReadVSTM", 0>; +def : ReadAdvance<ReadVLDSX, 0>; +def : ReadAdvance<ReadVSTSX, 0>; +defm "" : LMULReadAdvance<"ReadVSTS8V", 0>; +defm "" : LMULReadAdvance<"ReadVSTS16V", 0>; +defm "" : LMULReadAdvance<"ReadVSTS32V", 0>; +defm "" : LMULReadAdvance<"ReadVSTS64V", 0>; +defm "" : LMULReadAdvance<"ReadVLDUXV", 0>; +defm "" : LMULReadAdvance<"ReadVLDOXV", 0>; +defm "" : LMULReadAdvance<"ReadVSTUX8", 0>; +defm "" : LMULReadAdvance<"ReadVSTUX16", 0>; +defm "" : LMULReadAdvance<"ReadVSTUX32", 0>; +defm "" : LMULReadAdvance<"ReadVSTUX64", 0>; +defm "" : LMULReadAdvance<"ReadVSTUXV", 0>; +defm "" : LMULReadAdvance<"ReadVSTUX8V", 0>; +defm "" : LMULReadAdvance<"ReadVSTUX16V", 0>; +defm "" : LMULReadAdvance<"ReadVSTUX32V", 0>; +defm "" : LMULReadAdvance<"ReadVSTUX64V", 0>; +defm "" : LMULReadAdvance<"ReadVSTOX8", 0>; +defm "" : LMULReadAdvance<"ReadVSTOX16", 0>; +defm "" : LMULReadAdvance<"ReadVSTOX32", 0>; +defm "" : LMULReadAdvance<"ReadVSTOX64", 0>; +defm "" : LMULReadAdvance<"ReadVSTOXV", 0>; +defm "" : LMULReadAdvance<"ReadVSTOX8V", 0>; +defm "" : LMULReadAdvance<"ReadVSTOX16V", 0>; +defm "" : LMULReadAdvance<"ReadVSTOX32V", 0>; +defm "" : LMULReadAdvance<"ReadVSTOX64V", 0>; +// LMUL Aware +def : ReadAdvance<ReadVST1R, 0>; +def : ReadAdvance<ReadVST2R, 0>; +def : ReadAdvance<ReadVST4R, 0>; +def : ReadAdvance<ReadVST8R, 0>; + +// 12. Vector Integer Arithmetic Instructions +defm : LMULReadAdvance<"ReadVIALUV", 0>; +defm : LMULReadAdvance<"ReadVIALUX", 0>; +defm : LMULReadAdvanceW<"ReadVIWALUV", 0>; +defm : LMULReadAdvanceW<"ReadVIWALUX", 0>; +defm : LMULReadAdvance<"ReadVExtV", 0>; +defm : LMULReadAdvance<"ReadVICALUV", 0>; +defm : LMULReadAdvance<"ReadVICALUX", 0>; +defm : LMULReadAdvance<"ReadVShiftV", 0>; +defm : LMULReadAdvance<"ReadVShiftX", 0>; +defm : LMULReadAdvanceW<"ReadVNShiftV", 0>; +defm : LMULReadAdvanceW<"ReadVNShiftX", 0>; +defm : LMULReadAdvance<"ReadVICmpV", 0>; +defm : LMULReadAdvance<"ReadVICmpX", 0>; +defm : LMULReadAdvance<"ReadVIMinMaxV", 0>; +defm : LMULReadAdvance<"ReadVIMinMaxX", 0>; +defm : LMULReadAdvance<"ReadVIMulV", 0>; +defm : LMULReadAdvance<"ReadVIMulX", 0>; +defm : LMULSEWReadAdvance<"ReadVIDivV", 0>; +defm : LMULSEWReadAdvance<"ReadVIDivX", 0>; +defm : LMULReadAdvanceW<"ReadVIWMulV", 0>; +defm : LMULReadAdvanceW<"ReadVIWMulX", 0>; +defm : LMULReadAdvance<"ReadVIMulAddV", 0>; +defm : LMULReadAdvance<"ReadVIMulAddX", 0>; +defm : LMULReadAdvanceW<"ReadVIWMulAddV", 0>; +defm : LMULReadAdvanceW<"ReadVIWMulAddX", 0>; +defm : LMULReadAdvance<"ReadVIMergeV", 0>; +defm : LMULReadAdvance<"ReadVIMergeX", 0>; +defm : LMULReadAdvance<"ReadVIMovV", 0>; +defm : LMULReadAdvance<"ReadVIMovX", 0>; + +// 13. Vector Fixed-Point Arithmetic Instructions +defm "" : LMULReadAdvance<"ReadVSALUV", 0>; +defm "" : LMULReadAdvance<"ReadVSALUX", 0>; +defm "" : LMULReadAdvance<"ReadVAALUV", 0>; +defm "" : LMULReadAdvance<"ReadVAALUX", 0>; +defm "" : LMULReadAdvance<"ReadVSMulV", 0>; +defm "" : LMULReadAdvance<"ReadVSMulX", 0>; +defm "" : LMULReadAdvance<"ReadVSShiftV", 0>; +defm "" : LMULReadAdvance<"ReadVSShiftX", 0>; +defm "" : LMULReadAdvanceW<"ReadVNClipV", 0>; +defm "" : LMULReadAdvanceW<"ReadVNClipX", 0>; + +// 14. Vector Floating-Point Instructions +defm "" : LMULReadAdvance<"ReadVFALUV", 0>; +defm "" : LMULReadAdvance<"ReadVFALUF", 0>; +defm "" : LMULReadAdvanceFW<"ReadVFWALUV", 0>; +defm "" : LMULReadAdvanceFW<"ReadVFWALUF", 0>; +defm "" : LMULReadAdvance<"ReadVFMulV", 0>; +defm "" : LMULReadAdvance<"ReadVFMulF", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFDivV", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFDivF", 0>; +defm "" : LMULReadAdvanceFW<"ReadVFWMulV", 0>; +defm "" : LMULReadAdvanceFW<"ReadVFWMulF", 0>; +defm "" : LMULReadAdvance<"ReadVFMulAddV", 0>; +defm "" : LMULReadAdvance<"ReadVFMulAddF", 0>; +defm "" : LMULReadAdvanceFW<"ReadVFWMulAddV", 0>; +defm "" : LMULReadAdvanceFW<"ReadVFWMulAddF", 0>; +defm "" : LMULSEWReadAdvanceF<"ReadVFSqrtV", 0>; +defm "" : LMULReadAdvance<"ReadVFRecpV", 0>; +defm "" : LMULReadAdvance<"ReadVFCmpV", 0>; +defm "" : LMULReadAdvance<"ReadVFCmpF", 0>; +defm "" : LMULReadAdvance<"ReadVFMinMaxV", 0>; +defm "" : LMULReadAdvance<"ReadVFMinMaxF", 0>; +defm "" : LMULReadAdvance<"ReadVFSgnjV", 0>; +defm "" : LMULReadAdvance<"ReadVFSgnjF", 0>; +defm "" : LMULReadAdvance<"ReadVFClassV", 0>; +defm "" : LMULReadAdvance<"ReadVFMergeV", 0>; +defm "" : LMULReadAdvance<"ReadVFMergeF", 0>; +defm "" : LMULReadAdvance<"ReadVFMovF", 0>; +defm "" : LMULReadAdvance<"ReadVFCvtIToFV", 0>; +defm "" : LMULReadAdvance<"ReadVFCvtFToIV", 0>; +defm "" : LMULReadAdvanceW<"ReadVFWCvtIToFV", 0>; +defm "" : LMULReadAdvanceFW<"ReadVFWCvtFToIV", 0>; +defm "" : LMULReadAdvanceFW<"ReadVFWCvtFToFV", 0>; +defm "" : LMULReadAdvanceFW<"ReadVFNCvtIToFV", 0>; +defm "" : LMULReadAdvanceW<"ReadVFNCvtFToIV", 0>; +defm "" : LMULReadAdvanceFW<"ReadVFNCvtFToFV", 0>; + +// 15. Vector Reduction Operations +def : ReadAdvance<ReadVIRedV, 0>; +def : ReadAdvance<ReadVIRedV0, 0>; +def : ReadAdvance<ReadVIWRedV, 0>; +def : ReadAdvance<ReadVIWRedV0, 0>; +def : ReadAdvance<ReadVFRedV, 0>; +def : ReadAdvance<ReadVFRedV0, 0>; +def : ReadAdvance<ReadVFRedOV, 0>; +def : ReadAdvance<ReadVFRedOV0, 0>; +def : ReadAdvance<ReadVFWRedV, 0>; +def : ReadAdvance<ReadVFWRedV0, 0>; +def : ReadAdvance<ReadVFWRedOV, 0>; +def : ReadAdvance<ReadVFWRedOV0, 0>; + +// 16. Vector Mask Instructions +defm "" : LMULReadAdvance<"ReadVMALUV", 0>; +defm "" : LMULReadAdvance<"ReadVMPopV", 0>; +defm "" : LMULReadAdvance<"ReadVMFFSV", 0>; +defm "" : LMULReadAdvance<"ReadVMSFSV", 0>; +defm "" : LMULReadAdvance<"ReadVIotaV", 0>; + +// 17. Vector Permutation Instructions +def : ReadAdvance<ReadVMovXS, 0>; +def : ReadAdvance<ReadVMovSX_V, 0>; +def : ReadAdvance<ReadVMovSX_X, 0>; +def : ReadAdvance<ReadVMovFS, 0>; +def : ReadAdvance<ReadVMovSF_V, 0>; +def : ReadAdvance<ReadVMovSF_F, 0>; +defm "" : LMULReadAdvance<"ReadVISlideV", 0>; +defm "" : LMULReadAdvance<"ReadVISlideX", 0>; +defm "" : LMULReadAdvance<"ReadVFSlideV", 0>; +defm "" : LMULReadAdvance<"ReadVFSlideF", 0>; +defm "" : LMULSEWReadAdvance<"ReadVRGatherVV_data", 0>; +defm "" : LMULSEWReadAdvance<"ReadVRGatherVV_index", 0>; +defm "" : LMULReadAdvance<"ReadVRGatherVX_data", 0>; +defm "" : LMULReadAdvance<"ReadVRGatherVX_index", 0>; +defm "" : LMULReadAdvance<"ReadVRGatherVI_data", 0>; +defm "" : LMULSEWReadAdvance<"ReadVCompressV", 0>; +// LMUL Aware +def : ReadAdvance<ReadVMov1V, 0>; +def : ReadAdvance<ReadVMov2V, 0>; +def : ReadAdvance<ReadVMov4V, 0>; +def : ReadAdvance<ReadVMov8V, 0>; + +// Others +def : ReadAdvance<ReadVMask, 0>; +def : ReadAdvance<ReadVMergeOp_WorstCase, 0>; +foreach mx = SchedMxList in { + def : ReadAdvance<!cast<SchedRead>("ReadVMergeOp_" # mx), 0>; + foreach sew = SchedSEWSet<mx>.val in + def : ReadAdvance<!cast<SchedRead>("ReadVMergeOp_" # mx # "_E" # sew), 0>; +} + +//===----------------------------------------------------------------------===// +// Unsupported extensions +defm : UnsupportedSchedZabha; +defm : UnsupportedSchedZbc; +defm : UnsupportedSchedZbkb; +defm : UnsupportedSchedZbkx; +defm : UnsupportedSchedSFB; +defm : UnsupportedSchedZfa; +} diff --git a/llvm/lib/Target/RISCV/RISCVSchedXiangShanNanHu.td b/llvm/lib/Target/RISCV/RISCVSchedXiangShanNanHu.td index ef491edf3671f833babad2e94b098c18293a1d49..4fc7b0335af5381504f555596197bbfa11cfccdf 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedXiangShanNanHu.td +++ b/llvm/lib/Target/RISCV/RISCVSchedXiangShanNanHu.td @@ -85,6 +85,7 @@ def : WriteRes<WriteRotateImm32, [XS2ALU]>; def : WriteRes<WriteRotateReg, [XS2ALU]>; def : WriteRes<WriteRotateReg32, [XS2ALU]>; def : WriteRes<WriteORCB, [XS2ALU]>; +def : WriteRes<WriteIMinMax, [XS2ALU]>; def : WriteRes<WriteREV8, [XS2ALU]>; // Zbkb @@ -288,6 +289,7 @@ def : ReadAdvance<ReadCTZ32, 0>; def : ReadAdvance<ReadCPOP, 0>; def : ReadAdvance<ReadCPOP32, 0>; def : XS2LoadToALUBypass<ReadORCB>; +def : XS2LoadToALUBypass<ReadIMinMax>; def : XS2LoadToALUBypass<ReadREV8>; // Zbkc def : ReadAdvance<ReadCLMUL, 0>; diff --git a/llvm/lib/Target/RISCV/RISCVScheduleZb.td b/llvm/lib/Target/RISCV/RISCVScheduleZb.td index 0a16390e505356c11381b2b8238257b56fdf43ad..93381f439e0dfc80abd53adb1ede0bbc7b24a7dd 100644 --- a/llvm/lib/Target/RISCV/RISCVScheduleZb.td +++ b/llvm/lib/Target/RISCV/RISCVScheduleZb.td @@ -25,6 +25,7 @@ def WriteCPOP : SchedWrite; def WriteCPOP32 : SchedWrite; def WriteREV8 : SchedWrite; def WriteORCB : SchedWrite; +def WriteIMinMax : SchedWrite; // Zbc extension def WriteCLMUL : SchedWrite; // CLMUL/CLMULR/CLMULH @@ -63,6 +64,7 @@ def ReadCPOP : SchedRead; def ReadCPOP32 : SchedRead; def ReadREV8 : SchedRead; def ReadORCB : SchedRead; +def ReadIMinMax : SchedRead; // Zbc extension def ReadCLMUL : SchedRead; // CLMUL/CLMULR/CLMULH @@ -106,6 +108,7 @@ def : WriteRes<WriteCPOP, []>; def : WriteRes<WriteCPOP32, []>; def : WriteRes<WriteREV8, []>; def : WriteRes<WriteORCB, []>; +def : WriteRes<WriteIMinMax, []>; def : ReadAdvance<ReadRotateImm, 0>; def : ReadAdvance<ReadRotateImm32, 0>; @@ -119,6 +122,7 @@ def : ReadAdvance<ReadCPOP, 0>; def : ReadAdvance<ReadCPOP32, 0>; def : ReadAdvance<ReadREV8, 0>; def : ReadAdvance<ReadORCB, 0>; +def : ReadAdvance<ReadIMinMax, 0>; } } diff --git a/llvm/lib/Target/RISCV/RISCVSystemOperands.td b/llvm/lib/Target/RISCV/RISCVSystemOperands.td index 79f977e5b32266519fd4401c2561a60394b55b9f..01c2767119502c2de59e68e2258a6638b849b41e 100644 --- a/llvm/lib/Target/RISCV/RISCVSystemOperands.td +++ b/llvm/lib/Target/RISCV/RISCVSystemOperands.td @@ -418,7 +418,16 @@ def : SysReg<"vsieh", 0x214>; def : SysReg<"vsiph", 0x254>; } // isRV32Only +//===----------------------------------------------- // Jump Vector Table CSR //===----------------------------------------------- def : SysReg<"jvt", 0x017>; + +//===----------------------------------------------- +// Resumable Non-Maskable Interrupts(Smrnmi) CSRs +//===----------------------------------------------- +def : SysReg<"mnscratch", 0x740>; +def : SysReg<"mnepc", 0x741>; +def : SysReg<"mncause", 0x742>; +def : SysReg<"mnstatus", 0x744>; diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp index ecd373649e2c79207d00df51d54c8dfc6a158a2e..38304ff90252f02ae767ebaedd824e40e46db86a 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -810,9 +810,27 @@ RISCVTTIImpl::getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, case Intrinsic::smin: case Intrinsic::smax: { auto LT = getTypeLegalizationCost(RetTy); - if ((ST->hasVInstructions() && LT.second.isVector()) || - (LT.second.isScalarInteger() && ST->hasStdExtZbb())) + if (LT.second.isScalarInteger() && ST->hasStdExtZbb()) return LT.first; + + if (ST->hasVInstructions() && LT.second.isVector()) { + unsigned Op; + switch (ICA.getID()) { + case Intrinsic::umin: + Op = RISCV::VMINU_VV; + break; + case Intrinsic::umax: + Op = RISCV::VMAXU_VV; + break; + case Intrinsic::smin: + Op = RISCV::VMIN_VV; + break; + case Intrinsic::smax: + Op = RISCV::VMAX_VV; + break; + } + return LT.first * getRISCVInstructionCost(Op, LT.second, CostKind); + } break; } case Intrinsic::sadd_sat: @@ -897,74 +915,104 @@ InstructionCost RISCVTTIImpl::getCastInstrCost(unsigned Opcode, Type *Dst, TTI::CastContextHint CCH, TTI::TargetCostKind CostKind, const Instruction *I) { - if (isa<VectorType>(Dst) && isa<VectorType>(Src)) { - // FIXME: Need to compute legalizing cost for illegal types. - if (!isTypeLegal(Src) || !isTypeLegal(Dst)) - return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I); + bool IsVectorType = isa<VectorType>(Dst) && isa<VectorType>(Src); + if (!IsVectorType) + return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I); - // Skip if element size of Dst or Src is bigger than ELEN. - if (Src->getScalarSizeInBits() > ST->getELen() || - Dst->getScalarSizeInBits() > ST->getELen()) - return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I); + bool IsTypeLegal = isTypeLegal(Src) && isTypeLegal(Dst) && + (Src->getScalarSizeInBits() <= ST->getELen()) && + (Dst->getScalarSizeInBits() <= ST->getELen()); - int ISD = TLI->InstructionOpcodeToISD(Opcode); - assert(ISD && "Invalid opcode"); - - // FIXME: Need to consider vsetvli and lmul. - int PowDiff = (int)Log2_32(Dst->getScalarSizeInBits()) - - (int)Log2_32(Src->getScalarSizeInBits()); - switch (ISD) { - case ISD::SIGN_EXTEND: - case ISD::ZERO_EXTEND: - if (Src->getScalarSizeInBits() == 1) { - // We do not use vsext/vzext to extend from mask vector. - // Instead we use the following instructions to extend from mask vector: - // vmv.v.i v8, 0 - // vmerge.vim v8, v8, -1, v0 - return 2; - } - return 1; - case ISD::TRUNCATE: - if (Dst->getScalarSizeInBits() == 1) { - // We do not use several vncvt to truncate to mask vector. So we could - // not use PowDiff to calculate it. - // Instead we use the following instructions to truncate to mask vector: - // vand.vi v8, v8, 1 - // vmsne.vi v0, v8, 0 - return 2; - } - [[fallthrough]]; - case ISD::FP_EXTEND: - case ISD::FP_ROUND: - // Counts of narrow/widen instructions. - return std::abs(PowDiff); - case ISD::FP_TO_SINT: - case ISD::FP_TO_UINT: - case ISD::SINT_TO_FP: - case ISD::UINT_TO_FP: - if (Src->getScalarSizeInBits() == 1 || Dst->getScalarSizeInBits() == 1) { - // The cost of convert from or to mask vector is different from other - // cases. We could not use PowDiff to calculate it. - // For mask vector to fp, we should use the following instructions: - // vmv.v.i v8, 0 - // vmerge.vim v8, v8, -1, v0 - // vfcvt.f.x.v v8, v8 - - // And for fp vector to mask, we use: - // vfncvt.rtz.x.f.w v9, v8 - // vand.vi v8, v9, 1 - // vmsne.vi v0, v8, 0 - return 3; - } - if (std::abs(PowDiff) <= 1) - return 1; - // Backend could lower (v[sz]ext i8 to double) to vfcvt(v[sz]ext.f8 i8), - // so it only need two conversion. - if (Src->isIntOrIntVectorTy()) - return 2; - // Counts of narrow/widen instructions. - return std::abs(PowDiff); + // FIXME: Need to compute legalizing cost for illegal types. + if (!IsTypeLegal) + return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I); + + std::pair<InstructionCost, MVT> SrcLT = getTypeLegalizationCost(Src); + std::pair<InstructionCost, MVT> DstLT = getTypeLegalizationCost(Dst); + + int ISD = TLI->InstructionOpcodeToISD(Opcode); + assert(ISD && "Invalid opcode"); + + int PowDiff = (int)Log2_32(Dst->getScalarSizeInBits()) - + (int)Log2_32(Src->getScalarSizeInBits()); + switch (ISD) { + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: { + const unsigned SrcEltSize = Src->getScalarSizeInBits(); + if (SrcEltSize == 1) { + // We do not use vsext/vzext to extend from mask vector. + // Instead we use the following instructions to extend from mask vector: + // vmv.v.i v8, 0 + // vmerge.vim v8, v8, -1, v0 + return getRISCVInstructionCost({RISCV::VMV_V_I, RISCV::VMERGE_VIM}, + DstLT.second, CostKind); + } + if ((PowDiff < 1) || (PowDiff > 3)) + return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I); + unsigned SExtOp[] = {RISCV::VSEXT_VF2, RISCV::VSEXT_VF4, RISCV::VSEXT_VF8}; + unsigned ZExtOp[] = {RISCV::VZEXT_VF2, RISCV::VZEXT_VF4, RISCV::VZEXT_VF8}; + unsigned Op = + (ISD == ISD::SIGN_EXTEND) ? SExtOp[PowDiff - 1] : ZExtOp[PowDiff - 1]; + return getRISCVInstructionCost(Op, DstLT.second, CostKind); + } + case ISD::TRUNCATE: + if (Dst->getScalarSizeInBits() == 1) { + // We do not use several vncvt to truncate to mask vector. So we could + // not use PowDiff to calculate it. + // Instead we use the following instructions to truncate to mask vector: + // vand.vi v8, v8, 1 + // vmsne.vi v0, v8, 0 + return getRISCVInstructionCost({RISCV::VAND_VI, RISCV::VMSNE_VI}, + SrcLT.second, CostKind); } + [[fallthrough]]; + case ISD::FP_EXTEND: + case ISD::FP_ROUND: { + // Counts of narrow/widen instructions. + unsigned SrcEltSize = Src->getScalarSizeInBits(); + unsigned DstEltSize = Dst->getScalarSizeInBits(); + + unsigned Op = (ISD == ISD::TRUNCATE) ? RISCV::VNSRL_WI + : (ISD == ISD::FP_EXTEND) ? RISCV::VFWCVT_F_F_V + : RISCV::VFNCVT_F_F_W; + InstructionCost Cost = 0; + for (; SrcEltSize != DstEltSize;) { + MVT ElementMVT = (ISD == ISD::TRUNCATE) + ? MVT::getIntegerVT(DstEltSize) + : MVT::getFloatingPointVT(DstEltSize); + MVT DstMVT = DstLT.second.changeVectorElementType(ElementMVT); + DstEltSize = + (DstEltSize > SrcEltSize) ? DstEltSize >> 1 : DstEltSize << 1; + Cost += getRISCVInstructionCost(Op, DstMVT, CostKind); + } + return Cost; + } + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: + if (Src->getScalarSizeInBits() == 1 || Dst->getScalarSizeInBits() == 1) { + // The cost of convert from or to mask vector is different from other + // cases. We could not use PowDiff to calculate it. + // For mask vector to fp, we should use the following instructions: + // vmv.v.i v8, 0 + // vmerge.vim v8, v8, -1, v0 + // vfcvt.f.x.v v8, v8 + + // And for fp vector to mask, we use: + // vfncvt.rtz.x.f.w v9, v8 + // vand.vi v8, v9, 1 + // vmsne.vi v0, v8, 0 + return 3; + } + if (std::abs(PowDiff) <= 1) + return 1; + // Backend could lower (v[sz]ext i8 to double) to vfcvt(v[sz]ext.f8 i8), + // so it only need two conversion. + if (Src->isIntOrIntVectorTy()) + return 2; + // Counts of narrow/widen instructions. + return std::abs(PowDiff); } return BaseT::getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I); } @@ -1001,14 +1049,88 @@ RISCVTTIImpl::getMinMaxReductionCost(Intrinsic::ID IID, VectorType *Ty, return getArithmeticReductionCost(Instruction::And, Ty, FMF, CostKind); } - // IR Reduction is composed by two vmv and one rvv reduction instruction. - InstructionCost BaseCost = 2; + if (IID == Intrinsic::maximum || IID == Intrinsic::minimum) { + SmallVector<unsigned, 3> Opcodes; + InstructionCost ExtraCost = 0; + switch (IID) { + case Intrinsic::maximum: + if (FMF.noNaNs()) { + Opcodes = {RISCV::VFREDMAX_VS, RISCV::VFMV_F_S}; + } else { + Opcodes = {RISCV::VMFNE_VV, RISCV::VCPOP_M, RISCV::VFREDMAX_VS, + RISCV::VFMV_F_S}; + // Cost of Canonical Nan + branch + // lui a0, 523264 + // fmv.w.x fa0, a0 + Type *DstTy = Ty->getScalarType(); + const unsigned EltTyBits = DstTy->getScalarSizeInBits(); + Type *SrcTy = IntegerType::getIntNTy(DstTy->getContext(), EltTyBits); + ExtraCost = 1 + + getCastInstrCost(Instruction::UIToFP, DstTy, SrcTy, + TTI::CastContextHint::None, CostKind) + + getCFInstrCost(Instruction::Br, CostKind); + } + break; - if (CostKind == TTI::TCK_CodeSize) - return (LT.first - 1) + BaseCost; + case Intrinsic::minimum: + if (FMF.noNaNs()) { + Opcodes = {RISCV::VFREDMIN_VS, RISCV::VFMV_F_S}; + } else { + Opcodes = {RISCV::VMFNE_VV, RISCV::VCPOP_M, RISCV::VFREDMIN_VS, + RISCV::VFMV_F_S}; + // Cost of Canonical Nan + branch + // lui a0, 523264 + // fmv.w.x fa0, a0 + Type *DstTy = Ty->getScalarType(); + const unsigned EltTyBits = DL.getTypeSizeInBits(DstTy); + Type *SrcTy = IntegerType::getIntNTy(DstTy->getContext(), EltTyBits); + ExtraCost = 1 + + getCastInstrCost(Instruction::UIToFP, DstTy, SrcTy, + TTI::CastContextHint::None, CostKind) + + getCFInstrCost(Instruction::Br, CostKind); + } + break; + } + return ExtraCost + getRISCVInstructionCost(Opcodes, LT.second, CostKind); + } - unsigned VL = getEstimatedVLFor(Ty); - return (LT.first - 1) + BaseCost + Log2_32_Ceil(VL); + // IR Reduction is composed by two vmv and one rvv reduction instruction. + unsigned SplitOp; + SmallVector<unsigned, 3> Opcodes; + switch (IID) { + default: + llvm_unreachable("Unsupported intrinsic"); + case Intrinsic::smax: + SplitOp = RISCV::VMAX_VV; + Opcodes = {RISCV::VMV_S_X, RISCV::VREDMAX_VS, RISCV::VMV_X_S}; + break; + case Intrinsic::smin: + SplitOp = RISCV::VMIN_VV; + Opcodes = {RISCV::VMV_S_X, RISCV::VREDMIN_VS, RISCV::VMV_X_S}; + break; + case Intrinsic::umax: + SplitOp = RISCV::VMAXU_VV; + Opcodes = {RISCV::VMV_S_X, RISCV::VREDMAXU_VS, RISCV::VMV_X_S}; + break; + case Intrinsic::umin: + SplitOp = RISCV::VMINU_VV; + Opcodes = {RISCV::VMV_S_X, RISCV::VREDMINU_VS, RISCV::VMV_X_S}; + break; + case Intrinsic::maxnum: + SplitOp = RISCV::VFMAX_VV; + Opcodes = {RISCV::VFMV_S_F, RISCV::VFREDMAX_VS, RISCV::VFMV_F_S}; + break; + case Intrinsic::minnum: + SplitOp = RISCV::VFMIN_VV; + Opcodes = {RISCV::VFMV_S_F, RISCV::VFREDMIN_VS, RISCV::VFMV_F_S}; + break; + } + // Add a cost for data larger than LMUL8 + InstructionCost SplitCost = + (LT.first > 1) ? (LT.first - 1) * + getRISCVInstructionCost(SplitOp, LT.second, CostKind) + : 0; + return SplitCost + getRISCVInstructionCost(Opcodes, LT.second, CostKind); } InstructionCost @@ -1620,3 +1742,27 @@ bool RISCVTTIImpl::isLSRCostLess(const TargetTransformInfo::LSRCost &C1, C2.NumIVMuls, C2.NumBaseAdds, C2.ScaleCost, C2.ImmCost, C2.SetupCost); } + +bool RISCVTTIImpl::isLegalMaskedCompressStore(Type *DataTy, Align Alignment) { + auto *VTy = dyn_cast<VectorType>(DataTy); + if (!VTy || VTy->isScalableTy()) + return false; + + if (!isLegalMaskedLoadStore(DataTy, Alignment)) + return false; + return true; +} + +bool RISCVTTIImpl::areInlineCompatible(const Function *Caller, + const Function *Callee) const { + const TargetMachine &TM = getTLI()->getTargetMachine(); + + const FeatureBitset &CallerBits = + TM.getSubtargetImpl(*Caller)->getFeatureBits(); + const FeatureBitset &CalleeBits = + TM.getSubtargetImpl(*Callee)->getFeatureBits(); + + // Inline a callee if its target-features are a subset of the callers + // target-features. + return (CallerBits & CalleeBits) == CalleeBits; +} diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h index af36e9d5d5e886f0e913e0f923af353303bb6ceb..ac32aea4ce2b8fdb411ae150ce53c2f65f22d50b 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.h @@ -60,6 +60,9 @@ public: : BaseT(TM, F.getParent()->getDataLayout()), ST(TM->getSubtargetImpl(F)), TLI(ST->getTargetLowering()) {} + bool areInlineCompatible(const Function *Caller, + const Function *Callee) const; + /// Return the cost of materializing an immediate for a value operand of /// a store instruction. InstructionCost getStoreImmCost(Type *VecTy, TTI::OperandValueInfo OpInfo, @@ -261,6 +264,8 @@ public: return TLI->isLegalStridedLoadStore(DataTypeVT, Alignment); } + bool isLegalMaskedCompressStore(Type *DataTy, Align Alignment); + bool isVScaleKnownToBeAPowerOfTwo() const { return TLI->isVScaleKnownToBeAPowerOfTwo(); } diff --git a/llvm/lib/Target/SPIRV/CMakeLists.txt b/llvm/lib/Target/SPIRV/CMakeLists.txt index afc26dda4c68bda473e245d6c847975723f59b04..7001ac382f41cacbf1891a77cf723c3763be8bcf 100644 --- a/llvm/lib/Target/SPIRV/CMakeLists.txt +++ b/llvm/lib/Target/SPIRV/CMakeLists.txt @@ -17,6 +17,7 @@ add_llvm_target(SPIRVCodeGen SPIRVAsmPrinter.cpp SPIRVBuiltins.cpp SPIRVCallLowering.cpp + SPIRVCommandLine.cpp SPIRVDuplicatesTracker.cpp SPIRVEmitIntrinsics.cpp SPIRVGlobalRegistry.cpp diff --git a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp index 1fbf3c3e11aedc1f508b5075b470be6293ba8c78..4eee8062f28248437006a0a853c5b34895457fd7 100644 --- a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp @@ -29,7 +29,9 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/TargetRegistry.h" @@ -102,6 +104,21 @@ void SPIRVAsmPrinter::emitEndOfAsmFile(Module &M) { outputModuleSections(); ModuleSectionsEmitted = true; } + + ST = static_cast<const SPIRVTargetMachine &>(TM).getSubtargetImpl(); + uint32_t DecSPIRVVersion = ST->getSPIRVVersion(); + uint32_t Major = DecSPIRVVersion / 10; + uint32_t Minor = DecSPIRVVersion - Major * 10; + // TODO: calculate Bound more carefully from maximum used register number, + // accounting for generated OpLabels and other related instructions if + // needed. + unsigned Bound = 2 * (ST->getBound() + 1); + bool FlagToRestore = OutStreamer->getUseAssemblerInfoForParsing(); + OutStreamer->setUseAssemblerInfoForParsing(true); + if (MCAssembler *Asm = OutStreamer->getAssemblerPtr()) + Asm->setBuildVersion(static_cast<MachO::PlatformType>(0), Major, Minor, + Bound, VersionTuple(Major, Minor, 0, Bound)); + OutStreamer->setUseAssemblerInfoForParsing(FlagToRestore); } void SPIRVAsmPrinter::emitFunctionHeader() { @@ -507,6 +524,13 @@ void SPIRVAsmPrinter::outputAnnotations(const Module &M) { report_fatal_error("Unsupported value in llvm.global.annotations"); Function *Func = cast<Function>(AnnotatedVar); Register Reg = MAI->getFuncReg(Func); + if (!Reg.isValid()) { + std::string DiagMsg; + raw_string_ostream OS(DiagMsg); + AnnotatedVar->print(OS); + DiagMsg = "Unknown function in llvm.global.annotations: " + DiagMsg; + report_fatal_error(DiagMsg.c_str()); + } // The second field contains a pointer to a global annotation string. GlobalVariable *GV = diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp index 07be0b34b182716c9b2f5665fb90c920305bd410..950f9df28dd39796642c6e755004f6a2691e484d 100644 --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp @@ -53,6 +53,8 @@ struct IncomingCall { : BuiltinName(BuiltinName), Builtin(Builtin), ReturnRegister(ReturnRegister), ReturnType(ReturnType), Arguments(Arguments) {} + + bool isSpirvOp() const { return BuiltinName.rfind("__spirv_", 0) == 0; } }; struct NativeBuiltin { @@ -368,12 +370,10 @@ static Register buildLoadInst(SPIRVType *BaseType, Register PtrRegister, /// Helper function for building a load instruction for loading a builtin global /// variable of \p BuiltinValue value. -static Register buildBuiltinVariableLoad(MachineIRBuilder &MIRBuilder, - SPIRVType *VariableType, - SPIRVGlobalRegistry *GR, - SPIRV::BuiltIn::BuiltIn BuiltinValue, - LLT LLType, - Register Reg = Register(0)) { +static Register buildBuiltinVariableLoad( + MachineIRBuilder &MIRBuilder, SPIRVType *VariableType, + SPIRVGlobalRegistry *GR, SPIRV::BuiltIn::BuiltIn BuiltinValue, LLT LLType, + Register Reg = Register(0), bool isConst = true, bool hasLinkageTy = true) { Register NewRegister = MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::IDRegClass); MIRBuilder.getMRI()->setType(NewRegister, @@ -385,8 +385,9 @@ static Register buildBuiltinVariableLoad(MachineIRBuilder &MIRBuilder, // Set up the global OpVariable with the necessary builtin decorations. Register Variable = GR->buildGlobalVariable( NewRegister, PtrType, getLinkStringForBuiltIn(BuiltinValue), nullptr, - SPIRV::StorageClass::Input, nullptr, true, true, - SPIRV::LinkageType::Import, MIRBuilder, false); + SPIRV::StorageClass::Input, nullptr, /* isConst= */ isConst, + /* HasLinkageTy */ hasLinkageTy, SPIRV::LinkageType::Import, MIRBuilder, + false); // Load the value from the global variable. Register LoadedRegister = @@ -485,9 +486,27 @@ static Register buildMemSemanticsReg(Register SemanticsRegister, return buildConstantIntReg(Semantics, MIRBuilder, GR); } +static bool buildOpFromWrapper(MachineIRBuilder &MIRBuilder, unsigned Opcode, + const SPIRV::IncomingCall *Call, + Register TypeReg = Register(0)) { + MachineRegisterInfo *MRI = MIRBuilder.getMRI(); + auto MIB = MIRBuilder.buildInstr(Opcode); + if (TypeReg.isValid()) + MIB.addDef(Call->ReturnRegister).addUse(TypeReg); + for (Register ArgReg : Call->Arguments) { + if (!MRI->getRegClassOrNull(ArgReg)) + MRI->setRegClass(ArgReg, &SPIRV::IDRegClass); + MIB.addUse(ArgReg); + } + return true; +} + /// Helper function for translating atomic init to OpStore. static bool buildAtomicInitInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder) { + if (Call->isSpirvOp()) + return buildOpFromWrapper(MIRBuilder, SPIRV::OpStore, Call); + assert(Call->Arguments.size() == 2 && "Need 2 arguments for atomic init translation"); MIRBuilder.getMRI()->setRegClass(Call->Arguments[0], &SPIRV::IDRegClass); @@ -502,6 +521,10 @@ static bool buildAtomicInitInst(const SPIRV::IncomingCall *Call, static bool buildAtomicLoadInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR) { + Register TypeReg = GR->getSPIRVTypeID(Call->ReturnType); + if (Call->isSpirvOp()) + return buildOpFromWrapper(MIRBuilder, SPIRV::OpAtomicLoad, Call, TypeReg); + Register PtrRegister = Call->Arguments[0]; MIRBuilder.getMRI()->setRegClass(PtrRegister, &SPIRV::IDRegClass); // TODO: if true insert call to __translate_ocl_memory_sccope before @@ -528,7 +551,7 @@ static bool buildAtomicLoadInst(const SPIRV::IncomingCall *Call, MIRBuilder.buildInstr(SPIRV::OpAtomicLoad) .addDef(Call->ReturnRegister) - .addUse(GR->getSPIRVTypeID(Call->ReturnType)) + .addUse(TypeReg) .addUse(PtrRegister) .addUse(ScopeRegister) .addUse(MemSemanticsReg); @@ -539,6 +562,9 @@ static bool buildAtomicLoadInst(const SPIRV::IncomingCall *Call, static bool buildAtomicStoreInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR) { + if (Call->isSpirvOp()) + return buildOpFromWrapper(MIRBuilder, SPIRV::OpAtomicStore, Call); + Register ScopeRegister = buildConstantIntReg(SPIRV::Scope::Device, MIRBuilder, GR); Register PtrRegister = Call->Arguments[0]; @@ -557,12 +583,13 @@ static bool buildAtomicStoreInst(const SPIRV::IncomingCall *Call, } /// Helper function for building an atomic compare-exchange instruction. -static bool buildAtomicCompareExchangeInst(const SPIRV::IncomingCall *Call, - MachineIRBuilder &MIRBuilder, - SPIRVGlobalRegistry *GR) { - const SPIRV::DemangledBuiltin *Builtin = Call->Builtin; - unsigned Opcode = - SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode; +static bool buildAtomicCompareExchangeInst( + const SPIRV::IncomingCall *Call, const SPIRV::DemangledBuiltin *Builtin, + unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR) { + if (Call->isSpirvOp()) + return buildOpFromWrapper(MIRBuilder, Opcode, Call, + GR->getSPIRVTypeID(Call->ReturnType)); + bool IsCmpxchg = Call->Builtin->Name.contains("cmpxchg"); MachineRegisterInfo *MRI = MIRBuilder.getMRI(); @@ -667,6 +694,10 @@ static bool buildAtomicCompareExchangeInst(const SPIRV::IncomingCall *Call, static bool buildAtomicRMWInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR) { + if (Call->isSpirvOp()) + return buildOpFromWrapper(MIRBuilder, Opcode, Call, + GR->getSPIRVTypeID(Call->ReturnType)); + MachineRegisterInfo *MRI = MIRBuilder.getMRI(); Register ScopeRegister = Call->Arguments.size() >= 4 ? Call->Arguments[3] : Register(); @@ -731,6 +762,12 @@ static bool buildAtomicFloatingRMWInst(const SPIRV::IncomingCall *Call, static bool buildAtomicFlagInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR) { + bool IsSet = Opcode == SPIRV::OpAtomicFlagTestAndSet; + Register TypeReg = GR->getSPIRVTypeID(Call->ReturnType); + if (Call->isSpirvOp()) + return buildOpFromWrapper(MIRBuilder, Opcode, Call, + IsSet ? TypeReg : Register(0)); + MachineRegisterInfo *MRI = MIRBuilder.getMRI(); Register PtrRegister = Call->Arguments[0]; unsigned Semantics = SPIRV::MemorySemantics::SequentiallyConsistent; @@ -750,9 +787,8 @@ static bool buildAtomicFlagInst(const SPIRV::IncomingCall *Call, buildScopeReg(ScopeRegister, SPIRV::Scope::Device, MIRBuilder, GR, MRI); auto MIB = MIRBuilder.buildInstr(Opcode); - if (Opcode == SPIRV::OpAtomicFlagTestAndSet) - MIB.addDef(Call->ReturnRegister) - .addUse(GR->getSPIRVTypeID(Call->ReturnType)); + if (IsSet) + MIB.addDef(Call->ReturnRegister).addUse(TypeReg); MIB.addUse(PtrRegister).addUse(ScopeRegister).addUse(MemSemanticsReg); return true; @@ -763,6 +799,9 @@ static bool buildAtomicFlagInst(const SPIRV::IncomingCall *Call, static bool buildBarrierInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR) { + if (Call->isSpirvOp()) + return buildOpFromWrapper(MIRBuilder, Opcode, Call); + MachineRegisterInfo *MRI = MIRBuilder.getMRI(); unsigned MemFlags = getIConstVal(Call->Arguments[0], MRI); unsigned MemSemantics = SPIRV::MemorySemantics::None; @@ -1240,7 +1279,8 @@ static bool generateAtomicInst(const SPIRV::IncomingCall *Call, return buildAtomicStoreInst(Call, MIRBuilder, GR); case SPIRV::OpAtomicCompareExchange: case SPIRV::OpAtomicCompareExchangeWeak: - return buildAtomicCompareExchangeInst(Call, MIRBuilder, GR); + return buildAtomicCompareExchangeInst(Call, Builtin, Opcode, MIRBuilder, + GR); case SPIRV::OpAtomicIAdd: case SPIRV::OpAtomicISub: case SPIRV::OpAtomicOr: @@ -1300,6 +1340,22 @@ static bool generateDotOrFMulInst(const SPIRV::IncomingCall *Call, return true; } +static bool generateWaveInst(const SPIRV::IncomingCall *Call, + MachineIRBuilder &MIRBuilder, + SPIRVGlobalRegistry *GR) { + const SPIRV::DemangledBuiltin *Builtin = Call->Builtin; + SPIRV::BuiltIn::BuiltIn Value = + SPIRV::lookupGetBuiltin(Builtin->Name, Builtin->Set)->Value; + + // For now, we only support a single Wave intrinsic with a single return type. + assert(Call->ReturnType->getOpcode() == SPIRV::OpTypeInt); + LLT LLType = LLT::scalar(GR->getScalarOrVectorBitWidth(Call->ReturnType)); + + return buildBuiltinVariableLoad( + MIRBuilder, Call->ReturnType, GR, Value, LLType, Call->ReturnRegister, + /* isConst= */ false, /* hasLinkageTy= */ false); +} + static bool generateGetQueryInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR) { @@ -1815,14 +1871,15 @@ static bool buildEnqueueKernel(const SPIRV::IncomingCall *Call, SPIRVGlobalRegistry *GR) { MachineRegisterInfo *MRI = MIRBuilder.getMRI(); const DataLayout &DL = MIRBuilder.getDataLayout(); - bool HasEvents = Call->Builtin->Name.contains("events"); + bool IsSpirvOp = Call->isSpirvOp(); + bool HasEvents = Call->Builtin->Name.contains("events") || IsSpirvOp; const SPIRVType *Int32Ty = GR->getOrCreateSPIRVIntegerType(32, MIRBuilder); // Make vararg instructions before OpEnqueueKernel. // Local sizes arguments: Sizes of block invoke arguments. Clang generates // local size operands as an array, so we need to unpack them. SmallVector<Register, 16> LocalSizes; - if (Call->Builtin->Name.find("_varargs") != StringRef::npos) { + if (Call->Builtin->Name.find("_varargs") != StringRef::npos || IsSpirvOp) { const unsigned LocalSizeArrayIdx = HasEvents ? 9 : 6; Register GepReg = Call->Arguments[LocalSizeArrayIdx]; MachineInstr *GepMI = MRI->getUniqueVRegDef(GepReg); @@ -2187,6 +2244,8 @@ std::optional<bool> lowerBuiltin(const StringRef DemangledCall, return generateBarrierInst(Call.get(), MIRBuilder, GR); case SPIRV::Dot: return generateDotOrFMulInst(Call.get(), MIRBuilder, GR); + case SPIRV::Wave: + return generateWaveInst(Call.get(), MIRBuilder, GR); case SPIRV::GetQuery: return generateGetQueryInst(Call.get(), MIRBuilder, GR); case SPIRV::ImageSizeQuery: diff --git a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td index eb26f70b1861f2c22bd3bbfdda6925e031703e10..660000fb548d79205ef0f2fb8c07580c8b8ebc32 100644 --- a/llvm/lib/Target/SPIRV/SPIRVBuiltins.td +++ b/llvm/lib/Target/SPIRV/SPIRVBuiltins.td @@ -41,6 +41,7 @@ def Variable : BuiltinGroup; def Atomic : BuiltinGroup; def Barrier : BuiltinGroup; def Dot : BuiltinGroup; +def Wave : BuiltinGroup; def GetQuery : BuiltinGroup; def ImageSizeQuery : BuiltinGroup; def ImageMiscQuery : BuiltinGroup; @@ -500,27 +501,38 @@ defm : DemangledNativeBuiltin<"__spirv_All", OpenCL_std, Relational, 1, 1, OpAll defm : DemangledNativeBuiltin<"atomic_init", OpenCL_std, Atomic, 2, 2, OpStore>; defm : DemangledNativeBuiltin<"atomic_load", OpenCL_std, Atomic, 1, 1, OpAtomicLoad>; defm : DemangledNativeBuiltin<"atomic_load_explicit", OpenCL_std, Atomic, 2, 3, OpAtomicLoad>; +defm : DemangledNativeBuiltin<"__spirv_AtomicLoad", OpenCL_std, Atomic, 3, 3, OpAtomicLoad>; defm : DemangledNativeBuiltin<"atomic_store", OpenCL_std, Atomic, 2, 2, OpAtomicStore>; defm : DemangledNativeBuiltin<"atomic_store_explicit", OpenCL_std, Atomic, 2, 4, OpAtomicStore>; +defm : DemangledNativeBuiltin<"__spirv_AtomicStore", OpenCL_std, Atomic, 4, 4, OpAtomicStore>; defm : DemangledNativeBuiltin<"atomic_compare_exchange_strong", OpenCL_std, Atomic, 3, 6, OpAtomicCompareExchange>; +defm : DemangledNativeBuiltin<"__spirv_AtomicCompareExchange", OpenCL_std, Atomic, 6, 6, OpAtomicCompareExchange>; defm : DemangledNativeBuiltin<"atomic_compare_exchange_strong_explicit", OpenCL_std, Atomic, 5, 6, OpAtomicCompareExchange>; defm : DemangledNativeBuiltin<"atomic_compare_exchange_weak", OpenCL_std, Atomic, 3, 6, OpAtomicCompareExchangeWeak>; defm : DemangledNativeBuiltin<"atomic_compare_exchange_weak_explicit", OpenCL_std, Atomic, 5, 6, OpAtomicCompareExchangeWeak>; +defm : DemangledNativeBuiltin<"__spirv_AtomicCompareExchangeWeak", OpenCL_std, Atomic, 6, 6, OpAtomicCompareExchangeWeak>; defm : DemangledNativeBuiltin<"atom_cmpxchg", OpenCL_std, Atomic, 3, 6, OpAtomicCompareExchange>; defm : DemangledNativeBuiltin<"atomic_cmpxchg", OpenCL_std, Atomic, 3, 6, OpAtomicCompareExchange>; defm : DemangledNativeBuiltin<"atom_add", OpenCL_std, Atomic, 2, 4, OpAtomicIAdd>; defm : DemangledNativeBuiltin<"atomic_add", OpenCL_std, Atomic, 2, 4, OpAtomicIAdd>; +defm : DemangledNativeBuiltin<"__spirv_AtomicIAdd", OpenCL_std, Atomic, 4, 4, OpAtomicIAdd>; defm : DemangledNativeBuiltin<"atom_sub", OpenCL_std, Atomic, 2, 4, OpAtomicISub>; defm : DemangledNativeBuiltin<"atomic_sub", OpenCL_std, Atomic, 2, 4, OpAtomicISub>; +defm : DemangledNativeBuiltin<"__spirv_AtomicISub", OpenCL_std, Atomic, 4, 4, OpAtomicISub>; defm : DemangledNativeBuiltin<"atom_or", OpenCL_std, Atomic, 2, 4, OpAtomicOr>; defm : DemangledNativeBuiltin<"atomic_or", OpenCL_std, Atomic, 2, 4, OpAtomicOr>; +defm : DemangledNativeBuiltin<"__spirv_AtomicOr", OpenCL_std, Atomic, 4, 4, OpAtomicOr>; defm : DemangledNativeBuiltin<"atom_xor", OpenCL_std, Atomic, 2, 4, OpAtomicXor>; defm : DemangledNativeBuiltin<"atomic_xor", OpenCL_std, Atomic, 2, 4, OpAtomicXor>; +defm : DemangledNativeBuiltin<"__spirv_AtomicXor", OpenCL_std, Atomic, 4, 4, OpAtomicXor>; defm : DemangledNativeBuiltin<"atom_and", OpenCL_std, Atomic, 2, 4, OpAtomicAnd>; defm : DemangledNativeBuiltin<"atomic_and", OpenCL_std, Atomic, 2, 4, OpAtomicAnd>; +defm : DemangledNativeBuiltin<"__spirv_AtomicAnd", OpenCL_std, Atomic, 4, 4, OpAtomicAnd>; defm : DemangledNativeBuiltin<"atomic_exchange", OpenCL_std, Atomic, 2, 4, OpAtomicExchange>; defm : DemangledNativeBuiltin<"atomic_exchange_explicit", OpenCL_std, Atomic, 2, 4, OpAtomicExchange>; +defm : DemangledNativeBuiltin<"AtomicEx__spirv_change", OpenCL_std, Atomic, 2, 4, OpAtomicExchange>; defm : DemangledNativeBuiltin<"atomic_work_item_fence", OpenCL_std, Atomic, 1, 3, OpMemoryBarrier>; +defm : DemangledNativeBuiltin<"__spirv_MemoryBarrier", OpenCL_std, Atomic, 2, 2, OpMemoryBarrier>; defm : DemangledNativeBuiltin<"atomic_fetch_add", OpenCL_std, Atomic, 2, 4, OpAtomicIAdd>; defm : DemangledNativeBuiltin<"atomic_fetch_sub", OpenCL_std, Atomic, 2, 4, OpAtomicISub>; defm : DemangledNativeBuiltin<"atomic_fetch_or", OpenCL_std, Atomic, 2, 4, OpAtomicOr>; @@ -532,26 +544,37 @@ defm : DemangledNativeBuiltin<"atomic_fetch_or_explicit", OpenCL_std, Atomic, 4, defm : DemangledNativeBuiltin<"atomic_fetch_xor_explicit", OpenCL_std, Atomic, 4, 6, OpAtomicXor>; defm : DemangledNativeBuiltin<"atomic_fetch_and_explicit", OpenCL_std, Atomic, 4, 6, OpAtomicAnd>; defm : DemangledNativeBuiltin<"atomic_flag_test_and_set", OpenCL_std, Atomic, 1, 1, OpAtomicFlagTestAndSet>; +defm : DemangledNativeBuiltin<"__spirv_AtomicFlagTestAndSet", OpenCL_std, Atomic, 3, 3, OpAtomicFlagTestAndSet>; defm : DemangledNativeBuiltin<"atomic_flag_test_and_set_explicit", OpenCL_std, Atomic, 2, 3, OpAtomicFlagTestAndSet>; defm : DemangledNativeBuiltin<"atomic_flag_clear", OpenCL_std, Atomic, 1, 1, OpAtomicFlagClear>; +defm : DemangledNativeBuiltin<"__spirv_AtomicFlagClear", OpenCL_std, Atomic, 3, 3, OpAtomicFlagClear>; defm : DemangledNativeBuiltin<"atomic_flag_clear_explicit", OpenCL_std, Atomic, 2, 3, OpAtomicFlagClear>; // Barrier builtin records: defm : DemangledNativeBuiltin<"barrier", OpenCL_std, Barrier, 1, 3, OpControlBarrier>; defm : DemangledNativeBuiltin<"work_group_barrier", OpenCL_std, Barrier, 1, 3, OpControlBarrier>; +defm : DemangledNativeBuiltin<"__spirv_ControlBarrier", OpenCL_std, Barrier, 3, 3, OpControlBarrier>; // Kernel enqueue builtin records: defm : DemangledNativeBuiltin<"__enqueue_kernel_basic", OpenCL_std, Enqueue, 5, 5, OpEnqueueKernel>; defm : DemangledNativeBuiltin<"__enqueue_kernel_basic_events", OpenCL_std, Enqueue, 8, 8, OpEnqueueKernel>; defm : DemangledNativeBuiltin<"__enqueue_kernel_varargs", OpenCL_std, Enqueue, 7, 7, OpEnqueueKernel>; defm : DemangledNativeBuiltin<"__enqueue_kernel_events_varargs", OpenCL_std, Enqueue, 10, 10, OpEnqueueKernel>; +defm : DemangledNativeBuiltin<"__spirv_EnqueueKernel", OpenCL_std, Enqueue, 10, 0, OpEnqueueKernel>; defm : DemangledNativeBuiltin<"retain_event", OpenCL_std, Enqueue, 1, 1, OpRetainEvent>; +defm : DemangledNativeBuiltin<"__spirv_RetainEvent", OpenCL_std, Enqueue, 1, 1, OpRetainEvent>; defm : DemangledNativeBuiltin<"release_event", OpenCL_std, Enqueue, 1, 1, OpReleaseEvent>; +defm : DemangledNativeBuiltin<"__spirv_ReleaseEvent", OpenCL_std, Enqueue, 1, 1, OpReleaseEvent>; defm : DemangledNativeBuiltin<"create_user_event", OpenCL_std, Enqueue, 0, 0, OpCreateUserEvent>; +defm : DemangledNativeBuiltin<"__spirv_CreateUserEvent", OpenCL_std, Enqueue, 0, 0, OpCreateUserEvent>; defm : DemangledNativeBuiltin<"is_valid_event", OpenCL_std, Enqueue, 1, 1, OpIsValidEvent>; +defm : DemangledNativeBuiltin<"__spirv_IsValidEvent", OpenCL_std, Enqueue, 1, 1, OpIsValidEvent>; defm : DemangledNativeBuiltin<"set_user_event_status", OpenCL_std, Enqueue, 2, 2, OpSetUserEventStatus>; +defm : DemangledNativeBuiltin<"__spirv_SetUserEventStatus", OpenCL_std, Enqueue, 2, 2, OpSetUserEventStatus>; defm : DemangledNativeBuiltin<"capture_event_profiling_info", OpenCL_std, Enqueue, 3, 3, OpCaptureEventProfilingInfo>; +defm : DemangledNativeBuiltin<"__spirv_CaptureEventProfilingInfo", OpenCL_std, Enqueue, 3, 3, OpCaptureEventProfilingInfo>; defm : DemangledNativeBuiltin<"get_default_queue", OpenCL_std, Enqueue, 0, 0, OpGetDefaultQueue>; +defm : DemangledNativeBuiltin<"__spirv_GetDefaultQueue", OpenCL_std, Enqueue, 0, 0, OpGetDefaultQueue>; defm : DemangledNativeBuiltin<"ndrange_1D", OpenCL_std, Enqueue, 1, 3, OpBuildNDRange>; defm : DemangledNativeBuiltin<"ndrange_2D", OpenCL_std, Enqueue, 1, 3, OpBuildNDRange>; defm : DemangledNativeBuiltin<"ndrange_3D", OpenCL_std, Enqueue, 1, 3, OpBuildNDRange>; @@ -562,7 +585,9 @@ defm : DemangledNativeBuiltin<"__spirv_SpecConstantComposite", OpenCL_std, SpecC // Async Copy and Prefetch builtin records: defm : DemangledNativeBuiltin<"async_work_group_copy", OpenCL_std, AsyncCopy, 4, 4, OpGroupAsyncCopy>; +defm : DemangledNativeBuiltin<"__spirv_GroupAsyncCopy", OpenCL_std, AsyncCopy, 4, 4, OpGroupAsyncCopy>; defm : DemangledNativeBuiltin<"wait_group_events", OpenCL_std, AsyncCopy, 2, 2, OpGroupWaitEvents>; +defm : DemangledNativeBuiltin<"__spirv_GroupWaitEvents", OpenCL_std, AsyncCopy, 2, 2, OpGroupWaitEvents>; // Load and store builtin records: defm : DemangledNativeBuiltin<"__spirv_Load", OpenCL_std, LoadStore, 1, 3, OpLoad>; @@ -1119,6 +1144,7 @@ defm : DemangledGetBuiltin<"get_global_size", OpenCL_std, GetQuery, GlobalSize>; defm : DemangledGetBuiltin<"get_group_id", OpenCL_std, GetQuery, WorkgroupId>; defm : DemangledGetBuiltin<"get_enqueued_local_size", OpenCL_std, GetQuery, EnqueuedWorkgroupSize>; defm : DemangledGetBuiltin<"get_num_groups", OpenCL_std, GetQuery, NumWorkgroups>; +defm : DemangledGetBuiltin<"__hlsl_wave_get_lane_index", GLSL_std_450, Wave, SubgroupLocalInvocationId>; //===----------------------------------------------------------------------===// // Class defining an image query builtin record used for lowering the OpenCL diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp index 2d7a00bab38e915fd8118a7f21f706cdb17e149a..1674cef7cb82700ab16d85032fbc55d42e5d19b9 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp @@ -85,6 +85,42 @@ static ConstantInt *getConstInt(MDNode *MD, unsigned NumOp) { return nullptr; } +// If the function has pointer arguments, we are forced to re-create this +// function type from the very beginning, changing PointerType by +// TypedPointerType for each pointer argument. Otherwise, the same `Type*` +// potentially corresponds to different SPIR-V function type, effectively +// invalidating logic behind global registry and duplicates tracker. +static FunctionType * +fixFunctionTypeIfPtrArgs(SPIRVGlobalRegistry *GR, const Function &F, + FunctionType *FTy, const SPIRVType *SRetTy, + const SmallVector<SPIRVType *, 4> &SArgTys) { + if (F.getParent()->getNamedMetadata("spv.cloned_funcs")) + return FTy; + + bool hasArgPtrs = false; + for (auto &Arg : F.args()) { + // check if it's an instance of a non-typed PointerType + if (Arg.getType()->isPointerTy()) { + hasArgPtrs = true; + break; + } + } + if (!hasArgPtrs) { + Type *RetTy = FTy->getReturnType(); + // check if it's an instance of a non-typed PointerType + if (!RetTy->isPointerTy()) + return FTy; + } + + // re-create function type, using TypedPointerType instead of PointerType to + // properly trace argument types + const Type *RetTy = GR->getTypeForSPIRVType(SRetTy); + SmallVector<Type *, 4> ArgTys; + for (auto SArgTy : SArgTys) + ArgTys.push_back(const_cast<Type *>(GR->getTypeForSPIRVType(SArgTy))); + return FunctionType::get(const_cast<Type *>(RetTy), ArgTys, false); +} + // This code restores function args/retvalue types for composite cases // because the final types should still be aggregate whereas they're i32 // during the translation to cope with aggregate flattening etc. @@ -162,25 +198,33 @@ static SPIRVType *getArgSPIRVType(const Function &F, unsigned ArgIdx, // If OriginalArgType is non-pointer, use the OriginalArgType (the type cannot // be legally reassigned later). - if (!OriginalArgType->isPointerTy()) + if (!isPointerTy(OriginalArgType)) return GR->getOrCreateSPIRVType(OriginalArgType, MIRBuilder, ArgAccessQual); - // In case OriginalArgType is of pointer type, there are three possibilities: + Argument *Arg = F.getArg(ArgIdx); + Type *ArgType = Arg->getType(); + if (isTypedPointerTy(ArgType)) { + SPIRVType *ElementType = GR->getOrCreateSPIRVType( + cast<TypedPointerType>(ArgType)->getElementType(), MIRBuilder); + return GR->getOrCreateSPIRVPointerType( + ElementType, MIRBuilder, + addressSpaceToStorageClass(getPointerAddressSpace(ArgType), ST)); + } + + // In case OriginalArgType is of untyped pointer type, there are three + // possibilities: // 1) This is a pointer of an LLVM IR element type, passed byval/byref. // 2) This is an OpenCL/SPIR-V builtin type if there is spv_assign_type - // intrinsic assigning a TargetExtType. + // intrinsic assigning a TargetExtType. // 3) This is a pointer, try to retrieve pointer element type from a // spv_assign_ptr_type intrinsic or otherwise use default pointer element // type. - Argument *Arg = F.getArg(ArgIdx); - if (Arg->hasByValAttr() || Arg->hasByRefAttr()) { - Type *ByValRefType = Arg->hasByValAttr() ? Arg->getParamByValType() - : Arg->getParamByRefType(); - SPIRVType *ElementType = GR->getOrCreateSPIRVType(ByValRefType, MIRBuilder); + if (hasPointeeTypeAttr(Arg)) { + SPIRVType *ElementType = + GR->getOrCreateSPIRVType(getPointeeTypeByAttr(Arg), MIRBuilder); return GR->getOrCreateSPIRVPointerType( ElementType, MIRBuilder, - addressSpaceToStorageClass(Arg->getType()->getPointerAddressSpace(), - ST)); + addressSpaceToStorageClass(getPointerAddressSpace(ArgType), ST)); } for (auto User : Arg->users()) { @@ -207,6 +251,13 @@ static SPIRVType *getArgSPIRVType(const Function &F, unsigned ArgIdx, cast<ConstantInt>(II->getOperand(2))->getZExtValue(), ST)); } + // Replace PointerType with TypedPointerType to be able to map SPIR-V types to + // LLVM types in a consistent manner + if (isUntypedPointerTy(OriginalArgType)) { + OriginalArgType = + TypedPointerType::get(Type::getInt8Ty(F.getContext()), + getPointerAddressSpace(OriginalArgType)); + } return GR->getOrCreateSPIRVType(OriginalArgType, MIRBuilder, ArgAccessQual); } @@ -240,7 +291,6 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget()); // Assign types and names to all args, and store their types for later. - FunctionType *FTy = getOriginalFunctionType(F); SmallVector<SPIRVType *, 4> ArgTypeVRegs; if (VRegs.size() > 0) { unsigned i = 0; @@ -255,7 +305,7 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, if (Arg.hasName()) buildOpName(VRegs[i][0], Arg.getName(), MIRBuilder); - if (Arg.getType()->isPointerTy()) { + if (isPointerTy(Arg.getType())) { auto DerefBytes = static_cast<unsigned>(Arg.getDereferenceableBytes()); if (DerefBytes != 0) buildOpDecorate(VRegs[i][0], MIRBuilder, @@ -285,6 +335,12 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, buildOpDecorate(VRegs[i][0], MIRBuilder, SPIRV::Decoration::FuncParamAttr, {Attr}); } + if (Arg.hasAttribute(Attribute::ByVal)) { + auto Attr = + static_cast<unsigned>(SPIRV::FunctionParameterAttribute::ByVal); + buildOpDecorate(VRegs[i][0], MIRBuilder, + SPIRV::Decoration::FuncParamAttr, {Attr}); + } if (F.getCallingConv() == CallingConv::SPIR_KERNEL) { std::vector<SPIRV::Decoration::Decoration> ArgTypeQualDecs = @@ -322,7 +378,9 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, MRI->setRegClass(FuncVReg, &SPIRV::IDRegClass); if (F.isDeclaration()) GR->add(&F, &MIRBuilder.getMF(), FuncVReg); + FunctionType *FTy = getOriginalFunctionType(F); SPIRVType *RetTy = GR->getOrCreateSPIRVType(FTy->getReturnType(), MIRBuilder); + FTy = fixFunctionTypeIfPtrArgs(GR, F, FTy, RetTy, ArgTypeVRegs); SPIRVType *FuncTy = GR->getOrCreateOpTypeFunctionWithArgs( FTy, RetTy, ArgTypeVRegs, MIRBuilder); uint32_t FuncControl = getFunctionControl(F); @@ -429,7 +487,6 @@ bool SPIRVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, return false; MachineFunction &MF = MIRBuilder.getMF(); GR->setCurrentFunc(MF); - FunctionType *FTy = nullptr; const Function *CF = nullptr; std::string DemangledName; const Type *OrigRetTy = Info.OrigRet.Ty; @@ -444,7 +501,7 @@ bool SPIRVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, // TODO: support constexpr casts and indirect calls. if (CF == nullptr) return false; - if ((FTy = getOriginalFunctionType(*CF)) != nullptr) + if (FunctionType *FTy = getOriginalFunctionType(*CF)) OrigRetTy = FTy->getReturnType(); } @@ -452,9 +509,15 @@ bool SPIRVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, Register ResVReg = Info.OrigRet.Regs.empty() ? Register(0) : Info.OrigRet.Regs[0]; const auto *ST = static_cast<const SPIRVSubtarget *>(&MF.getSubtarget()); - // TODO: check that it's OCL builtin, then apply OpenCL_std. - if (!DemangledName.empty() && CF && CF->isDeclaration() && - ST->canUseExtInstSet(SPIRV::InstructionSet::OpenCL_std)) { + + bool isFunctionDecl = CF && CF->isDeclaration(); + bool canUseOpenCL = ST->canUseExtInstSet(SPIRV::InstructionSet::OpenCL_std); + bool canUseGLSL = ST->canUseExtInstSet(SPIRV::InstructionSet::GLSL_std_450); + assert(canUseGLSL != canUseOpenCL && + "Scenario where both sets are enabled is not supported."); + + if (isFunctionDecl && !DemangledName.empty() && + (canUseGLSL || canUseOpenCL)) { SmallVector<Register, 8> ArgVRegs; for (auto Arg : Info.OrigArgs) { assert(Arg.Regs.size() == 1 && "Call arg has multiple VRegs"); @@ -463,12 +526,15 @@ bool SPIRVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, if (!GR->getSPIRVTypeForVReg(Arg.Regs[0])) GR->assignSPIRVTypeToVReg(SPIRVTy, Arg.Regs[0], MF); } - if (auto Res = SPIRV::lowerBuiltin( - DemangledName, SPIRV::InstructionSet::OpenCL_std, MIRBuilder, - ResVReg, OrigRetTy, ArgVRegs, GR)) + auto instructionSet = canUseOpenCL ? SPIRV::InstructionSet::OpenCL_std + : SPIRV::InstructionSet::GLSL_std_450; + if (auto Res = + SPIRV::lowerBuiltin(DemangledName, instructionSet, MIRBuilder, + ResVReg, OrigRetTy, ArgVRegs, GR)) return *Res; } - if (CF && CF->isDeclaration() && !GR->find(CF, &MF).isValid()) { + + if (isFunctionDecl && !GR->find(CF, &MF).isValid()) { // Emit the type info and forward function declaration to the first MBB // to ensure VReg definition dependencies are valid across all MBBs. MachineIRBuilder FirstBlockBuilder; diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..691e6ee0e5829f44005edd49331a5ca8bc96518c --- /dev/null +++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp @@ -0,0 +1,101 @@ +//===--- SPIRVCommandLine.cpp ---- Command Line Options ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains definitions of classes and functions needed for +// processing, parsing, and using CLI options for the SPIR-V backend. +// +//===----------------------------------------------------------------------===// + +#include "SPIRVCommandLine.h" +#include "llvm/ADT/StringRef.h" +#include <algorithm> +#include <map> + +#define DEBUG_TYPE "spirv-commandline" + +using namespace llvm; + +static const std::map<std::string, SPIRV::Extension::Extension> + SPIRVExtensionMap = { + {"SPV_EXT_shader_atomic_float_add", + SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float_add}, + {"SPV_EXT_shader_atomic_float16_add", + SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float16_add}, + {"SPV_EXT_shader_atomic_float_min_max", + SPIRV::Extension::Extension::SPV_EXT_shader_atomic_float_min_max}, + {"SPV_INTEL_arbitrary_precision_integers", + SPIRV::Extension::Extension::SPV_INTEL_arbitrary_precision_integers}, + {"SPV_INTEL_optnone", SPIRV::Extension::Extension::SPV_INTEL_optnone}, + {"SPV_INTEL_usm_storage_classes", + SPIRV::Extension::Extension::SPV_INTEL_usm_storage_classes}, + {"SPV_INTEL_subgroups", + SPIRV::Extension::Extension::SPV_INTEL_subgroups}, + {"SPV_KHR_uniform_group_instructions", + SPIRV::Extension::Extension::SPV_KHR_uniform_group_instructions}, + {"SPV_KHR_no_integer_wrap_decoration", + SPIRV::Extension::Extension::SPV_KHR_no_integer_wrap_decoration}, + {"SPV_KHR_float_controls", + SPIRV::Extension::Extension::SPV_KHR_float_controls}, + {"SPV_KHR_expect_assume", + SPIRV::Extension::Extension::SPV_KHR_expect_assume}, + {"SPV_KHR_bit_instructions", + SPIRV::Extension::Extension::SPV_KHR_bit_instructions}, + {"SPV_KHR_linkonce_odr", + SPIRV::Extension::Extension::SPV_KHR_linkonce_odr}, + {"SPV_INTEL_bfloat16_conversion", + SPIRV::Extension::Extension::SPV_INTEL_bfloat16_conversion}, + {"SPV_KHR_subgroup_rotate", + SPIRV::Extension::Extension::SPV_KHR_subgroup_rotate}, + {"SPV_INTEL_variable_length_array", + SPIRV::Extension::Extension::SPV_INTEL_variable_length_array}, + {"SPV_INTEL_function_pointers", + SPIRV::Extension::Extension::SPV_INTEL_function_pointers}, +}; + +bool SPIRVExtensionsParser::parse(cl::Option &O, llvm::StringRef ArgName, + llvm::StringRef ArgValue, + std::set<SPIRV::Extension::Extension> &Vals) { + llvm::SmallVector<llvm::StringRef, 10> Tokens; + ArgValue.split(Tokens, ",", -1, false); + std::sort(Tokens.begin(), Tokens.end()); + + std::set<SPIRV::Extension::Extension> EnabledExtensions; + + for (const auto &Token : Tokens) { + if (Token == "all") { + for (const auto &[ExtensionName, ExtensionEnum] : SPIRVExtensionMap) + EnabledExtensions.insert(ExtensionEnum); + + continue; + } + + if (Token.empty() || (!Token.starts_with("+") && !Token.starts_with("-"))) + return O.error("Invalid extension list format: " + Token.str()); + + llvm::StringRef ExtensionName = Token.substr(1); + auto NameValuePair = SPIRVExtensionMap.find(ExtensionName.str()); + + if (NameValuePair == SPIRVExtensionMap.end()) + return O.error("Unknown SPIR-V extension: " + Token.str()); + + if (Token.starts_with("+")) { + EnabledExtensions.insert(NameValuePair->second); + } else if (EnabledExtensions.count(NameValuePair->second)) { + if (std::find(Tokens.begin(), Tokens.end(), "+" + ExtensionName.str()) != + Tokens.end()) + return O.error( + "Extension cannot be allowed and disallowed at the same time: " + + ExtensionName.str()); + + EnabledExtensions.erase(NameValuePair->second); + } + } + + Vals = std::move(EnabledExtensions); + return false; +} diff --git a/llvm/lib/Target/SPIRV/SPIRVCommandLine.h b/llvm/lib/Target/SPIRV/SPIRVCommandLine.h new file mode 100644 index 0000000000000000000000000000000000000000..741d829b2ab8f97b3d9ac22c408aa39b77f491c1 --- /dev/null +++ b/llvm/lib/Target/SPIRV/SPIRVCommandLine.h @@ -0,0 +1,38 @@ +//===--- SPIRVCommandLine.h ---- Command Line Options -----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains classes and functions needed for processing, parsing, and +// using CLI options for the SPIR-V backend. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_SPIRV_COMMANDLINE_H +#define LLVM_LIB_TARGET_SPIRV_COMMANDLINE_H + +#include "MCTargetDesc/SPIRVBaseInfo.h" +#include "llvm/Support/CommandLine.h" +#include <set> + +namespace llvm { + +/// Command line parser for toggling SPIR-V extensions. +struct SPIRVExtensionsParser + : public cl::parser<std::set<SPIRV::Extension::Extension>> { +public: + SPIRVExtensionsParser(cl::Option &O) + : cl::parser<std::set<SPIRV::Extension::Extension>>(O) {} + + /// Parses SPIR-V extension name from CLI arguments. + /// + /// \return Returns true on error. + bool parse(cl::Option &O, StringRef ArgName, StringRef ArgValue, + std::set<SPIRV::Extension::Extension> &Vals); +}; + +} // namespace llvm +#endif // LLVM_LIB_TARGET_SPIRV_COMMANDLINE_H diff --git a/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.cpp b/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.cpp index d82fb2df4539a353b706d736592af19e14a46506..7c32bb1968ef5803717f40ac66967533361494a7 100644 --- a/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.cpp @@ -39,6 +39,7 @@ void SPIRVGeneralDuplicatesTracker::buildDepsGraph( prebuildReg2Entry(GT, Reg2Entry); prebuildReg2Entry(FT, Reg2Entry); prebuildReg2Entry(AT, Reg2Entry); + prebuildReg2Entry(MT, Reg2Entry); prebuildReg2Entry(ST, Reg2Entry); for (auto &Op2E : Reg2Entry) { diff --git a/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h b/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h index 96cc621791e972dddea8db1ba38d82ac3b785591..2ec3fb35ca0451f13bccfeaad3070944a235bbee 100644 --- a/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h +++ b/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h @@ -262,6 +262,7 @@ class SPIRVGeneralDuplicatesTracker { SPIRVDuplicatesTracker<GlobalVariable> GT; SPIRVDuplicatesTracker<Function> FT; SPIRVDuplicatesTracker<Argument> AT; + SPIRVDuplicatesTracker<MachineInstr> MT; SPIRVDuplicatesTracker<SPIRV::SpecialTypeDescriptor> ST; // NOTE: using MOs instead of regs to get rid of MF dependency to be able @@ -306,6 +307,10 @@ public: AT.add(Arg, MF, R); } + void add(const MachineInstr *MI, const MachineFunction *MF, Register R) { + MT.add(MI, MF, R); + } + void add(const SPIRV::SpecialTypeDescriptor &TD, const MachineFunction *MF, Register R) { ST.add(TD, MF, R); @@ -337,6 +342,10 @@ public: return AT.find(const_cast<Argument *>(Arg), MF); } + Register find(const MachineInstr *MI, const MachineFunction *MF) { + return MT.find(const_cast<MachineInstr *>(MI), MF); + } + Register find(const SPIRV::SpecialTypeDescriptor &TD, const MachineFunction *MF) { return ST.find(TD, MF); diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp index 575e903d05bb97d49a2b867cbfeef67ba153d768..b341fcb41d0312a8bc1509a95d7484d1cdcb4a9f 100644 --- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp @@ -14,6 +14,7 @@ #include "SPIRV.h" #include "SPIRVBuiltins.h" #include "SPIRVMetadata.h" +#include "SPIRVSubtarget.h" #include "SPIRVTargetMachine.h" #include "SPIRVUtils.h" #include "llvm/IR/IRBuilder.h" @@ -53,12 +54,30 @@ class SPIRVEmitIntrinsics : public FunctionPass, public InstVisitor<SPIRVEmitIntrinsics, Instruction *> { SPIRVTargetMachine *TM = nullptr; + SPIRVGlobalRegistry *GR = nullptr; Function *F = nullptr; bool TrackConstants = true; DenseMap<Instruction *, Constant *> AggrConsts; + DenseMap<Instruction *, Type *> AggrConstTypes; DenseSet<Instruction *> AggrStores; + + // deduce element type of untyped pointers + Type *deduceElementType(Value *I); + Type *deduceElementTypeHelper(Value *I); + Type *deduceElementTypeHelper(Value *I, std::unordered_set<Value *> &Visited); + Type *deduceElementTypeByValueDeep(Type *ValueTy, Value *Operand, + std::unordered_set<Value *> &Visited); + Type *deduceElementTypeByUsersDeep(Value *Op, + std::unordered_set<Value *> &Visited); + + // deduce nested types of composites + Type *deduceNestedTypeHelper(User *U); + Type *deduceNestedTypeHelper(User *U, Type *Ty, + std::unordered_set<Value *> &Visited); + void preprocessCompositeConstants(IRBuilder<> &B); void preprocessUndefs(IRBuilder<> &B); + CallInst *buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef<Type *> Types, Value *Arg, Value *Arg2, ArrayRef<Constant *> Imms, IRBuilder<> &B) { @@ -72,6 +91,7 @@ class SPIRVEmitIntrinsics Args.push_back(Imm); return B.CreateIntrinsic(IntrID, {Types}, Args); } + void replaceMemInstrUses(Instruction *Old, Instruction *New, IRBuilder<> &B); void processInstrAfterVisit(Instruction *I, IRBuilder<> &B); void insertAssignPtrTypeIntrs(Instruction *I, IRBuilder<> &B); @@ -84,6 +104,10 @@ class SPIRVEmitIntrinsics IRBuilder<> &B); void insertPtrCastOrAssignTypeInstr(Instruction *I, IRBuilder<> &B); void processGlobalValue(GlobalVariable &GV, IRBuilder<> &B); + void processParamTypes(Function *F, IRBuilder<> &B); + Type *deduceFunParamElementType(Function *F, unsigned OpIdx); + Type *deduceFunParamElementType(Function *F, unsigned OpIdx, + std::unordered_set<Function *> &FVisited); public: static char ID; @@ -156,6 +180,194 @@ static inline void reportFatalOnTokenType(const Instruction *I) { false); } +// Set element pointer type to the given value of ValueTy and tries to +// specify this type further (recursively) by Operand value, if needed. +Type *SPIRVEmitIntrinsics::deduceElementTypeByValueDeep( + Type *ValueTy, Value *Operand, std::unordered_set<Value *> &Visited) { + Type *Ty = ValueTy; + if (Operand) { + if (auto *PtrTy = dyn_cast<PointerType>(Ty)) { + if (Type *NestedTy = deduceElementTypeHelper(Operand, Visited)) + Ty = TypedPointerType::get(NestedTy, PtrTy->getAddressSpace()); + } else { + Ty = deduceNestedTypeHelper(dyn_cast<User>(Operand), Ty, Visited); + } + } + return Ty; +} + +// Traverse User instructions to deduce an element pointer type of the operand. +Type *SPIRVEmitIntrinsics::deduceElementTypeByUsersDeep( + Value *Op, std::unordered_set<Value *> &Visited) { + if (!Op || !isPointerTy(Op->getType())) + return nullptr; + + if (auto PType = dyn_cast<TypedPointerType>(Op->getType())) + return PType->getElementType(); + + // maybe we already know operand's element type + if (Type *KnownTy = GR->findDeducedElementType(Op)) + return KnownTy; + + for (User *OpU : Op->users()) { + if (Instruction *Inst = dyn_cast<Instruction>(OpU)) { + if (Type *Ty = deduceElementTypeHelper(Inst, Visited)) + return Ty; + } + } + return nullptr; +} + +// Deduce and return a successfully deduced Type of the Instruction, +// or nullptr otherwise. +Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(Value *I) { + std::unordered_set<Value *> Visited; + return deduceElementTypeHelper(I, Visited); +} + +Type *SPIRVEmitIntrinsics::deduceElementTypeHelper( + Value *I, std::unordered_set<Value *> &Visited) { + // allow to pass nullptr as an argument + if (!I) + return nullptr; + + // maybe already known + if (Type *KnownTy = GR->findDeducedElementType(I)) + return KnownTy; + + // maybe a cycle + if (Visited.find(I) != Visited.end()) + return nullptr; + Visited.insert(I); + + // fallback value in case when we fail to deduce a type + Type *Ty = nullptr; + // look for known basic patterns of type inference + if (auto *Ref = dyn_cast<AllocaInst>(I)) { + Ty = Ref->getAllocatedType(); + } else if (auto *Ref = dyn_cast<GetElementPtrInst>(I)) { + Ty = Ref->getResultElementType(); + } else if (auto *Ref = dyn_cast<GlobalValue>(I)) { + Ty = deduceElementTypeByValueDeep( + Ref->getValueType(), + Ref->getNumOperands() > 0 ? Ref->getOperand(0) : nullptr, Visited); + } else if (auto *Ref = dyn_cast<AddrSpaceCastInst>(I)) { + Ty = deduceElementTypeHelper(Ref->getPointerOperand(), Visited); + } else if (auto *Ref = dyn_cast<BitCastInst>(I)) { + if (Type *Src = Ref->getSrcTy(), *Dest = Ref->getDestTy(); + isPointerTy(Src) && isPointerTy(Dest)) + Ty = deduceElementTypeHelper(Ref->getOperand(0), Visited); + } else if (auto *Ref = dyn_cast<AtomicCmpXchgInst>(I)) { + Value *Op = Ref->getNewValOperand(); + Ty = deduceElementTypeByValueDeep(Op->getType(), Op, Visited); + } else if (auto *Ref = dyn_cast<AtomicRMWInst>(I)) { + Value *Op = Ref->getValOperand(); + Ty = deduceElementTypeByValueDeep(Op->getType(), Op, Visited); + } else if (auto *Ref = dyn_cast<PHINode>(I)) { + for (unsigned i = 0; i < Ref->getNumIncomingValues(); i++) { + Ty = deduceElementTypeByUsersDeep(Ref->getIncomingValue(i), Visited); + if (Ty) + break; + } + } + + // remember the found relationship + if (Ty) { + // specify nested types if needed, otherwise return unchanged + GR->addDeducedElementType(I, Ty); + } + + return Ty; +} + +// Re-create a type of the value if it has untyped pointer fields, also nested. +// Return the original value type if no corrections of untyped pointer +// information is found or needed. +Type *SPIRVEmitIntrinsics::deduceNestedTypeHelper(User *U) { + std::unordered_set<Value *> Visited; + return deduceNestedTypeHelper(U, U->getType(), Visited); +} + +Type *SPIRVEmitIntrinsics::deduceNestedTypeHelper( + User *U, Type *OrigTy, std::unordered_set<Value *> &Visited) { + if (!U) + return OrigTy; + + // maybe already known + if (Type *KnownTy = GR->findDeducedCompositeType(U)) + return KnownTy; + + // maybe a cycle + if (Visited.find(U) != Visited.end()) + return OrigTy; + Visited.insert(U); + + if (dyn_cast<StructType>(OrigTy)) { + SmallVector<Type *> Tys; + bool Change = false; + for (unsigned i = 0; i < U->getNumOperands(); ++i) { + Value *Op = U->getOperand(i); + Type *OpTy = Op->getType(); + Type *Ty = OpTy; + if (Op) { + if (auto *PtrTy = dyn_cast<PointerType>(OpTy)) { + if (Type *NestedTy = deduceElementTypeHelper(Op, Visited)) + Ty = TypedPointerType::get(NestedTy, PtrTy->getAddressSpace()); + } else { + Ty = deduceNestedTypeHelper(dyn_cast<User>(Op), OpTy, Visited); + } + } + Tys.push_back(Ty); + Change |= Ty != OpTy; + } + if (Change) { + Type *NewTy = StructType::create(Tys); + GR->addDeducedCompositeType(U, NewTy); + return NewTy; + } + } else if (auto *ArrTy = dyn_cast<ArrayType>(OrigTy)) { + if (Value *Op = U->getNumOperands() > 0 ? U->getOperand(0) : nullptr) { + Type *OpTy = ArrTy->getElementType(); + Type *Ty = OpTy; + if (auto *PtrTy = dyn_cast<PointerType>(OpTy)) { + if (Type *NestedTy = deduceElementTypeHelper(Op, Visited)) + Ty = TypedPointerType::get(NestedTy, PtrTy->getAddressSpace()); + } else { + Ty = deduceNestedTypeHelper(dyn_cast<User>(Op), OpTy, Visited); + } + if (Ty != OpTy) { + Type *NewTy = ArrayType::get(Ty, ArrTy->getNumElements()); + GR->addDeducedCompositeType(U, NewTy); + return NewTy; + } + } + } else if (auto *VecTy = dyn_cast<VectorType>(OrigTy)) { + if (Value *Op = U->getNumOperands() > 0 ? U->getOperand(0) : nullptr) { + Type *OpTy = VecTy->getElementType(); + Type *Ty = OpTy; + if (auto *PtrTy = dyn_cast<PointerType>(OpTy)) { + if (Type *NestedTy = deduceElementTypeHelper(Op, Visited)) + Ty = TypedPointerType::get(NestedTy, PtrTy->getAddressSpace()); + } else { + Ty = deduceNestedTypeHelper(dyn_cast<User>(Op), OpTy, Visited); + } + if (Ty != OpTy) { + Type *NewTy = VectorType::get(Ty, VecTy->getElementCount()); + GR->addDeducedCompositeType(U, NewTy); + return NewTy; + } + } + } + + return OrigTy; +} + +Type *SPIRVEmitIntrinsics::deduceElementType(Value *I) { + if (Type *Ty = deduceElementTypeHelper(I)) + return Ty; + return IntegerType::getInt8Ty(I->getContext()); +} + void SPIRVEmitIntrinsics::replaceMemInstrUses(Instruction *Old, Instruction *New, IRBuilder<> &B) { @@ -195,6 +407,7 @@ void SPIRVEmitIntrinsics::preprocessUndefs(IRBuilder<> &B) { Worklist.push(IntrUndef); I->replaceUsesOfWith(Op, IntrUndef); AggrConsts[IntrUndef] = AggrUndef; + AggrConstTypes[IntrUndef] = AggrUndef->getType(); } } } @@ -220,6 +433,7 @@ void SPIRVEmitIntrinsics::preprocessCompositeConstants(IRBuilder<> &B) { I->replaceUsesOfWith(Op, CCI); KeepInst = true; SEI.AggrConsts[CCI] = AggrC; + SEI.AggrConstTypes[CCI] = SEI.deduceNestedTypeHelper(AggrC); }; if (auto *AggrC = dyn_cast<ConstantAggregate>(Op)) { @@ -280,7 +494,7 @@ Instruction *SPIRVEmitIntrinsics::visitBitCastInst(BitCastInst &I) { // varying element types. In case of IR coming from older versions of LLVM // such bitcasts do not provide sufficient information, should be just skipped // here, and handled in insertPtrCastOrAssignTypeInstr. - if (I.getType()->isPointerTy()) { + if (isPointerTy(I.getType())) { I.replaceAllUsesWith(Source); I.eraseFromParent(); return nullptr; @@ -333,20 +547,9 @@ void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast( while (BitCastInst *BC = dyn_cast<BitCastInst>(Pointer)) Pointer = BC->getOperand(0); - // Do not emit spv_ptrcast if Pointer is a GlobalValue of expected type. - GlobalValue *GV = dyn_cast<GlobalValue>(Pointer); - if (GV && GV->getValueType() == ExpectedElementType) - return; - - // Do not emit spv_ptrcast if Pointer is a result of alloca with expected - // type. - AllocaInst *A = dyn_cast<AllocaInst>(Pointer); - if (A && A->getAllocatedType() == ExpectedElementType) - return; - - // Do not emit spv_ptrcast if Pointer is a result of GEP of expected type. - GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(Pointer); - if (GEPI && GEPI->getResultElementType() == ExpectedElementType) + // Do not emit spv_ptrcast if Pointer's element type is ExpectedElementType + Type *PointerElemTy = deduceElementTypeHelper(Pointer); + if (PointerElemTy == ExpectedElementType) return; setInsertPointSkippingPhis(B, I); @@ -356,7 +559,7 @@ void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast( ValueAsMetadata::getConstant(ExpectedElementTypeConst); MDTuple *TyMD = MDNode::get(F->getContext(), CM); MetadataAsValue *VMD = MetadataAsValue::get(F->getContext(), TyMD); - unsigned AddressSpace = Pointer->getType()->getPointerAddressSpace(); + unsigned AddressSpace = getPointerAddressSpace(Pointer->getType()); bool FirstPtrCastOrAssignPtrType = true; // Do not emit new spv_ptrcast if equivalent one already exists or when @@ -401,9 +604,11 @@ void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast( // spv_assign_ptr_type instead. if (FirstPtrCastOrAssignPtrType && (isa<Instruction>(Pointer) || isa<Argument>(Pointer))) { - buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {Pointer->getType()}, - ExpectedElementTypeConst, Pointer, - {B.getInt32(AddressSpace)}, B); + CallInst *CI = buildIntrWithMD( + Intrinsic::spv_assign_ptr_type, {Pointer->getType()}, + ExpectedElementTypeConst, Pointer, {B.getInt32(AddressSpace)}, B); + GR->addDeducedElementType(CI, ExpectedElementType); + GR->addDeducedElementType(Pointer, ExpectedElementType); return; } @@ -419,7 +624,7 @@ void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I, // Handle basic instructions: StoreInst *SI = dyn_cast<StoreInst>(I); if (SI && F->getCallingConv() == CallingConv::SPIR_KERNEL && - SI->getValueOperand()->getType()->isPointerTy() && + isPointerTy(SI->getValueOperand()->getType()) && isa<Argument>(SI->getValueOperand())) { return replacePointerOperandWithPtrCast( I, SI->getValueOperand(), IntegerType::getInt8Ty(F->getContext()), 0, @@ -437,12 +642,42 @@ void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I, // Handle calls to builtins (non-intrinsics): CallInst *CI = dyn_cast<CallInst>(I); - if (!CI || CI->isIndirectCall() || CI->getCalledFunction()->isIntrinsic()) + if (!CI || CI->isIndirectCall() || CI->isInlineAsm() || + !CI->getCalledFunction() || CI->getCalledFunction()->isIntrinsic()) return; + // collect information about formal parameter types + Function *CalledF = CI->getCalledFunction(); + SmallVector<Type *, 4> CalledArgTys; + bool HaveTypes = false; + for (unsigned OpIdx = 0; OpIdx < CalledF->arg_size(); ++OpIdx) { + Argument *CalledArg = CalledF->getArg(OpIdx); + Type *ArgType = CalledArg->getType(); + if (!isPointerTy(ArgType)) { + CalledArgTys.push_back(nullptr); + } else if (isTypedPointerTy(ArgType)) { + CalledArgTys.push_back(cast<TypedPointerType>(ArgType)->getElementType()); + HaveTypes = true; + } else { + Type *ElemTy = GR->findDeducedElementType(CalledArg); + if (!ElemTy && hasPointeeTypeAttr(CalledArg)) + ElemTy = getPointeeTypeByAttr(CalledArg); + if (!ElemTy) { + for (User *U : CalledArg->users()) { + if (Instruction *Inst = dyn_cast<Instruction>(U)) { + if ((ElemTy = deduceElementTypeHelper(Inst)) != nullptr) + break; + } + } + } + HaveTypes |= ElemTy != nullptr; + CalledArgTys.push_back(ElemTy); + } + } + std::string DemangledName = getOclOrSpirvBuiltinDemangledName(CI->getCalledFunction()->getName()); - if (DemangledName.empty()) + if (DemangledName.empty() && !HaveTypes) return; for (unsigned OpIdx = 0; OpIdx < CI->arg_size(); OpIdx++) { @@ -455,8 +690,11 @@ void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I, if (!isa<Instruction>(ArgOperand) && !isa<Argument>(ArgOperand)) continue; - Type *ExpectedType = SPIRV::parseBuiltinCallArgumentBaseType( - DemangledName, OpIdx, I->getContext()); + Type *ExpectedType = + OpIdx < CalledArgTys.size() ? CalledArgTys[OpIdx] : nullptr; + if (!ExpectedType && !DemangledName.empty()) + ExpectedType = SPIRV::parseBuiltinCallArgumentBaseType( + DemangledName, OpIdx, I->getContext()); if (!ExpectedType) continue; @@ -624,6 +862,10 @@ void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV, if (GV.getName() == "llvm.global.annotations") return; if (GV.hasInitializer() && !isa<UndefValue>(GV.getInitializer())) { + // Deduce element type and store results in Global Registry. + // Result is ignored, because TypedPointerType is not supported + // by llvm IR general logic. + deduceElementTypeHelper(&GV); Constant *Init = GV.getInitializer(); Type *Ty = isAggrToReplace(Init) ? B.getInt32Ty() : Init->getType(); Constant *Const = isAggrToReplace(Init) ? B.getInt32(1) : Init; @@ -639,38 +881,34 @@ void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV, void SPIRVEmitIntrinsics::insertAssignPtrTypeIntrs(Instruction *I, IRBuilder<> &B) { reportFatalOnTokenType(I); - if (!I->getType()->isPointerTy() || !requireAssignType(I) || + if (!isPointerTy(I->getType()) || !requireAssignType(I) || isa<BitCastInst>(I)) return; setInsertPointSkippingPhis(B, I->getNextNode()); - Constant *EltTyConst; - unsigned AddressSpace = I->getType()->getPointerAddressSpace(); - if (auto *AI = dyn_cast<AllocaInst>(I)) - EltTyConst = UndefValue::get(AI->getAllocatedType()); - else if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) - EltTyConst = UndefValue::get(GEP->getResultElementType()); - else - EltTyConst = UndefValue::get(IntegerType::getInt8Ty(I->getContext())); - - buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {I->getType()}, EltTyConst, I, - {B.getInt32(AddressSpace)}, B); + Type *ElemTy = deduceElementType(I); + Constant *EltTyConst = UndefValue::get(ElemTy); + unsigned AddressSpace = getPointerAddressSpace(I->getType()); + CallInst *CI = buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {I->getType()}, + EltTyConst, I, {B.getInt32(AddressSpace)}, B); + GR->addDeducedElementType(CI, ElemTy); } void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I, IRBuilder<> &B) { reportFatalOnTokenType(I); Type *Ty = I->getType(); - if (!Ty->isVoidTy() && !Ty->isPointerTy() && requireAssignType(I)) { + if (!Ty->isVoidTy() && !isPointerTy(Ty) && requireAssignType(I)) { setInsertPointSkippingPhis(B, I->getNextNode()); Type *TypeToAssign = Ty; if (auto *II = dyn_cast<IntrinsicInst>(I)) { if (II->getIntrinsicID() == Intrinsic::spv_const_composite || II->getIntrinsicID() == Intrinsic::spv_undef) { - auto t = AggrConsts.find(II); - assert(t != AggrConsts.end()); - TypeToAssign = t->second->getType(); + auto It = AggrConstTypes.find(II); + if (It == AggrConstTypes.end()) + report_fatal_error("Unknown composite intrinsic type"); + TypeToAssign = It->second; } } Constant *Const = UndefValue::get(TypeToAssign); @@ -730,12 +968,103 @@ void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I, } } +Type *SPIRVEmitIntrinsics::deduceFunParamElementType(Function *F, + unsigned OpIdx) { + std::unordered_set<Function *> FVisited; + return deduceFunParamElementType(F, OpIdx, FVisited); +} + +Type *SPIRVEmitIntrinsics::deduceFunParamElementType( + Function *F, unsigned OpIdx, std::unordered_set<Function *> &FVisited) { + // maybe a cycle + if (FVisited.find(F) != FVisited.end()) + return nullptr; + FVisited.insert(F); + + std::unordered_set<Value *> Visited; + SmallVector<std::pair<Function *, unsigned>> Lookup; + // search in function's call sites + for (User *U : F->users()) { + CallInst *CI = dyn_cast<CallInst>(U); + if (!CI || OpIdx >= CI->arg_size()) + continue; + Value *OpArg = CI->getArgOperand(OpIdx); + if (!isPointerTy(OpArg->getType())) + continue; + // maybe we already know operand's element type + if (Type *KnownTy = GR->findDeducedElementType(OpArg)) + return KnownTy; + // try to deduce from the operand itself + Visited.clear(); + if (Type *Ty = deduceElementTypeHelper(OpArg, Visited)) + return Ty; + // search in actual parameter's users + for (User *OpU : OpArg->users()) { + Instruction *Inst = dyn_cast<Instruction>(OpU); + if (!Inst || Inst == CI) + continue; + Visited.clear(); + if (Type *Ty = deduceElementTypeHelper(Inst, Visited)) + return Ty; + } + // check if it's a formal parameter of the outer function + if (!CI->getParent() || !CI->getParent()->getParent()) + continue; + Function *OuterF = CI->getParent()->getParent(); + if (FVisited.find(OuterF) != FVisited.end()) + continue; + for (unsigned i = 0; i < OuterF->arg_size(); ++i) { + if (OuterF->getArg(i) == OpArg) { + Lookup.push_back(std::make_pair(OuterF, i)); + break; + } + } + } + + // search in function parameters + for (auto &Pair : Lookup) { + if (Type *Ty = deduceFunParamElementType(Pair.first, Pair.second, FVisited)) + return Ty; + } + + return nullptr; +} + +void SPIRVEmitIntrinsics::processParamTypes(Function *F, IRBuilder<> &B) { + B.SetInsertPointPastAllocas(F); + for (unsigned OpIdx = 0; OpIdx < F->arg_size(); ++OpIdx) { + Argument *Arg = F->getArg(OpIdx); + if (!isUntypedPointerTy(Arg->getType())) + continue; + + Type *ElemTy = GR->findDeducedElementType(Arg); + if (!ElemTy) { + if (hasPointeeTypeAttr(Arg) && + (ElemTy = getPointeeTypeByAttr(Arg)) != nullptr) { + GR->addDeducedElementType(Arg, ElemTy); + } else if ((ElemTy = deduceFunParamElementType(F, OpIdx)) != nullptr) { + CallInst *AssignPtrTyCI = buildIntrWithMD( + Intrinsic::spv_assign_ptr_type, {Arg->getType()}, + Constant::getNullValue(ElemTy), Arg, + {B.getInt32(getPointerAddressSpace(Arg->getType()))}, B); + GR->addDeducedElementType(AssignPtrTyCI, ElemTy); + GR->addDeducedElementType(Arg, ElemTy); + } + } + } +} + bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) { if (Func.isDeclaration()) return false; + + const SPIRVSubtarget &ST = TM->getSubtarget<SPIRVSubtarget>(Func); + GR = ST.getSPIRVGlobalRegistry(); + F = &Func; IRBuilder<> B(Func.getContext()); AggrConsts.clear(); + AggrConstTypes.clear(); AggrStores.clear(); // StoreInst's operand type can be changed during the next transformations, @@ -775,6 +1104,11 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) { continue; processInstrAfterVisit(I, B); } + + // check if function parameter types are set + if (!F->isIntrinsic()) + processParamTypes(F, B); + return true; } diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp index 8556581996fede39fd8886dcfa26925c1821d9aa..9592f3e81b402616d91dc6e7d5bc300faf937277 100644 --- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp @@ -24,7 +24,7 @@ using namespace llvm; SPIRVGlobalRegistry::SPIRVGlobalRegistry(unsigned PointerSize) - : PointerSize(PointerSize) {} + : PointerSize(PointerSize), Bound(0) {} SPIRVType *SPIRVGlobalRegistry::assignIntTypeToVReg(unsigned BitWidth, Register VReg, @@ -123,6 +123,7 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeVector(uint32_t NumElems, SPIRVType *ElemType, MachineIRBuilder &MIRBuilder) { auto EleOpc = ElemType->getOpcode(); + (void)EleOpc; assert((EleOpc == SPIRV::OpTypeInt || EleOpc == SPIRV::OpTypeFloat || EleOpc == SPIRV::OpTypeBool) && "Invalid vector element type"); @@ -479,6 +480,7 @@ Register SPIRVGlobalRegistry::buildGlobalVariable( GVar = M->getGlobalVariable(Name); if (GVar == nullptr) { const Type *Ty = getTypeForSPIRVType(BaseType); // TODO: check type. + // Module takes ownership of the global var. GVar = new GlobalVariable(*M, const_cast<Type *>(Ty), false, GlobalValue::ExternalLinkage, nullptr, Twine(Name)); @@ -721,11 +723,14 @@ SPIRVType *SPIRVGlobalRegistry::createSPIRVType( AddrSpace = PType->getAddressSpace(); else report_fatal_error("Unable to convert LLVM type to SPIRVType", true); - SPIRVType *SpvElementType; - // At the moment, all opaque pointers correspond to i8 element type. - // TODO: change the implementation once opaque pointers are supported - // in the SPIR-V specification. - SpvElementType = getOrCreateSPIRVIntegerType(8, MIRBuilder); + + SPIRVType *SpvElementType = nullptr; + if (auto PType = dyn_cast<TypedPointerType>(Ty)) + SpvElementType = getOrCreateSPIRVType(PType->getElementType(), MIRBuilder, + AccQual, EmitIR); + else + SpvElementType = getOrCreateSPIRVIntegerType(8, MIRBuilder); + // Get access to information about available extensions const SPIRVSubtarget *ST = static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget()); @@ -750,7 +755,7 @@ SPIRVType *SPIRVGlobalRegistry::createSPIRVType( SPIRVType *SPIRVGlobalRegistry::restOfCreateSPIRVType( const Type *Ty, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) { - if (TypesInProcessing.count(Ty) && !Ty->isPointerTy()) + if (TypesInProcessing.count(Ty) && !isPointerTy(Ty)) return nullptr; TypesInProcessing.insert(Ty); SPIRVType *SpirvType = createSPIRVType(Ty, MIRBuilder, AccessQual, EmitIR); @@ -762,11 +767,15 @@ SPIRVType *SPIRVGlobalRegistry::restOfCreateSPIRVType( // will be added later. For special types it is already added to DT. if (SpirvType->getOpcode() != SPIRV::OpTypeForwardPointer && !Reg.isValid() && !isSpecialOpaqueType(Ty)) { - if (!Ty->isPointerTy()) + if (!isPointerTy(Ty)) DT.add(Ty, &MIRBuilder.getMF(), getSPIRVTypeID(SpirvType)); + else if (isTypedPointerTy(Ty)) + DT.add(cast<TypedPointerType>(Ty)->getElementType(), + getPointerAddressSpace(Ty), &MIRBuilder.getMF(), + getSPIRVTypeID(SpirvType)); else DT.add(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()), - Ty->getPointerAddressSpace(), &MIRBuilder.getMF(), + getPointerAddressSpace(Ty), &MIRBuilder.getMF(), getSPIRVTypeID(SpirvType)); } @@ -787,12 +796,15 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVType( const Type *Ty, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) { Register Reg; - if (!Ty->isPointerTy()) + if (!isPointerTy(Ty)) Reg = DT.find(Ty, &MIRBuilder.getMF()); + else if (isTypedPointerTy(Ty)) + Reg = DT.find(cast<TypedPointerType>(Ty)->getElementType(), + getPointerAddressSpace(Ty), &MIRBuilder.getMF()); else Reg = DT.find(Type::getInt8Ty(MIRBuilder.getMF().getFunction().getContext()), - Ty->getPointerAddressSpace(), &MIRBuilder.getMF()); + getPointerAddressSpace(Ty), &MIRBuilder.getMF()); if (Reg.isValid() && !isSpecialOpaqueType(Ty)) return getSPIRVTypeForVReg(Reg); @@ -836,11 +848,16 @@ bool SPIRVGlobalRegistry::isScalarOrVectorOfType(Register VReg, unsigned SPIRVGlobalRegistry::getScalarOrVectorComponentCount(Register VReg) const { - if (SPIRVType *Type = getSPIRVTypeForVReg(VReg)) - return Type->getOpcode() == SPIRV::OpTypeVector - ? static_cast<unsigned>(Type->getOperand(2).getImm()) - : 1; - return 0; + return getScalarOrVectorComponentCount(getSPIRVTypeForVReg(VReg)); +} + +unsigned +SPIRVGlobalRegistry::getScalarOrVectorComponentCount(SPIRVType *Type) const { + if (!Type) + return 0; + return Type->getOpcode() == SPIRV::OpTypeVector + ? static_cast<unsigned>(Type->getOperand(2).getImm()) + : 1; } unsigned @@ -884,6 +901,15 @@ bool SPIRVGlobalRegistry::isScalarOrVectorSigned(const SPIRVType *Type) const { return IntType && IntType->getOperand(2).getImm() != 0; } +unsigned SPIRVGlobalRegistry::getPointeeTypeOp(Register PtrReg) { + SPIRVType *PtrType = getSPIRVTypeForVReg(PtrReg); + SPIRVType *ElemType = + PtrType && PtrType->getOpcode() == SPIRV::OpTypePointer + ? getSPIRVTypeForVReg(PtrType->getOperand(2).getReg()) + : nullptr; + return ElemType ? ElemType->getOpcode() : 0; +} + bool SPIRVGlobalRegistry::isBitcastCompatible(const SPIRVType *Type1, const SPIRVType *Type2) const { if (!Type1 || !Type2) diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h index 9c0061d13fd0cf8cc23ac7ff6a2c07f9826226eb..e0099e5294472526962d8730db3c3288974ed43a 100644 --- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h +++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h @@ -41,9 +41,13 @@ class SPIRVGlobalRegistry { // map a Function to its definition (as a machine instruction operand) DenseMap<const Function *, const MachineOperand *> FunctionToInstr; + DenseMap<const MachineInstr *, const Function *> FunctionToInstrRev; // map function pointer (as a machine instruction operand) to the used // Function DenseMap<const MachineOperand *, const Function *> InstrToFunction; + // Maps Functions to their calls (in a form of the machine instruction, + // OpFunctionCall) that happened before the definition is available + DenseMap<const Function *, SmallVector<MachineInstr *>> ForwardCalls; // Look for an equivalent of the newType in the map. Return the equivalent // if it's found, otherwise insert newType to the map and return the type. @@ -56,6 +60,16 @@ class SPIRVGlobalRegistry { // Number of bits pointers and size_t integers require. const unsigned PointerSize; + // Holds the maximum ID we have in the module. + unsigned Bound; + + // Maps values associated with untyped pointers into deduced element types of + // untyped pointers. + DenseMap<Value *, Type *> DeducedElTys; + // Maps composite values to deduced types where untyped pointers are replaced + // with typed ones + DenseMap<Value *, Type *> DeducedNestedTys; + // Add a new OpTypeXXX instruction without checking for duplicates. SPIRVType *createSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AQ = @@ -91,6 +105,14 @@ public: DT.add(Arg, MF, R); } + void add(const MachineInstr *MI, MachineFunction *MF, Register R) { + DT.add(MI, MF, R); + } + + Register find(const MachineInstr *MI, MachineFunction *MF) { + return DT.find(MI, MF); + } + Register find(const Constant *C, MachineFunction *MF) { return DT.find(C, MF); } @@ -108,6 +130,40 @@ public: DT.buildDepsGraph(Graph, MMI); } + void setBound(unsigned V) { Bound = V; } + unsigned getBound() { return Bound; } + + // Deduced element types of untyped pointers and composites: + // - Add a record to the map of deduced element types. + void addDeducedElementType(Value *Val, Type *Ty) { DeducedElTys[Val] = Ty; } + // - Find a record in the map of deduced element types. + Type *findDeducedElementType(const Value *Val) { + auto It = DeducedElTys.find(Val); + return It == DeducedElTys.end() ? nullptr : It->second; + } + // - Add a record to the map of deduced composite types. + void addDeducedCompositeType(Value *Val, Type *Ty) { + DeducedNestedTys[Val] = Ty; + } + // - Find a record in the map of deduced composite types. + Type *findDeducedCompositeType(const Value *Val) { + auto It = DeducedNestedTys.find(Val); + return It == DeducedNestedTys.end() ? nullptr : It->second; + } + // - Find a type of the given Global value + Type *getDeducedGlobalValueType(const GlobalValue *Global) { + // we may know element type if it was deduced earlier + Type *ElementTy = findDeducedElementType(Global); + if (!ElementTy) { + // or we may know element type if it's associated with a composite + // value + if (Value *GlobalElem = + Global->getNumOperands() > 0 ? Global->getOperand(0) : nullptr) + ElementTy = findDeducedCompositeType(GlobalElem); + } + return ElementTy ? ElementTy : Global->getValueType(); + } + // Map a machine operand that represents a use of a function via function // pointer to a machine operand that represents the function definition. // Return either the register or invalid value, because we have no context for @@ -119,18 +175,56 @@ public: auto ResReg = FunctionToInstr.find(ResF->second); return ResReg == FunctionToInstr.end() ? nullptr : ResReg->second; } + + // Map a Function to a machine instruction that represents the function + // definition. + const MachineInstr *getFunctionDefinition(const Function *F) { + if (!F) + return nullptr; + auto MOIt = FunctionToInstr.find(F); + return MOIt == FunctionToInstr.end() ? nullptr : MOIt->second->getParent(); + } + + // Map a Function to a machine instruction that represents the function + // definition. + const Function *getFunctionByDefinition(const MachineInstr *MI) { + if (!MI) + return nullptr; + auto FIt = FunctionToInstrRev.find(MI); + return FIt == FunctionToInstrRev.end() ? nullptr : FIt->second; + } + // map function pointer (as a machine instruction operand) to the used // Function void recordFunctionPointer(const MachineOperand *MO, const Function *F) { InstrToFunction[MO] = F; } + // map a Function to its definition (as a machine instruction) void recordFunctionDefinition(const Function *F, const MachineOperand *MO) { FunctionToInstr[F] = MO; + FunctionToInstrRev[MO->getParent()] = F; } + // Return true if any OpConstantFunctionPointerINTEL were generated bool hasConstFunPtr() { return !InstrToFunction.empty(); } + // Add a record about forward function call. + void addForwardCall(const Function *F, MachineInstr *MI) { + auto It = ForwardCalls.find(F); + if (It == ForwardCalls.end()) + ForwardCalls[F] = {MI}; + else + It->second.push_back(MI); + } + + // Map a Function to the vector of machine instructions that represents + // forward function calls or to nullptr if not found. + SmallVector<MachineInstr *> *getForwardCalls(const Function *F) { + auto It = ForwardCalls.find(F); + return It == ForwardCalls.end() ? nullptr : &It->second; + } + // Get or create a SPIR-V type corresponding the given LLVM IR type, // and map it to the given VReg by creating an ASSIGN_TYPE instruction. SPIRVType *assignTypeToVReg(const Type *Type, Register VReg, @@ -166,6 +260,9 @@ public: return Res->second; } + // Return a pointee's type op code, or 0 otherwise. + unsigned getPointeeTypeOp(Register PtrReg); + // Either generate a new OpTypeXXX instruction or return an existing one // corresponding to the given string containing the name of the builtin type. // Return nullptr if unable to recognize SPIRV type name from `TypeStr`. @@ -198,9 +295,10 @@ public: // opcode (e.g. OpTypeBool, or OpTypeVector %x 4, where %x is OpTypeBool). bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const; - // Return number of elements in a vector if the given VReg is associated with + // Return number of elements in a vector if the argument is associated with // a vector type. Return 1 for a scalar type, and 0 for a missing type. unsigned getScalarOrVectorComponentCount(Register VReg) const; + unsigned getScalarOrVectorComponentCount(SPIRVType *Type) const; // For vectors or scalars of booleans, integers and floats, return the scalar // type's bitwidth. Otherwise calls llvm_unreachable(). diff --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp index 61748070fc0fb26a7f3acd467d3b626a438012d4..90a31551f45a23b7fc99711d8ab6ceddf3206351 100644 --- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp @@ -86,8 +86,8 @@ bool SPIRVTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info, // when there is a type mismatch between results and operand types. static void validatePtrTypes(const SPIRVSubtarget &STI, MachineRegisterInfo *MRI, SPIRVGlobalRegistry &GR, - MachineInstr &I, SPIRVType *ResType, - unsigned OpIdx) { + MachineInstr &I, unsigned OpIdx, + SPIRVType *ResType, const Type *ResTy = nullptr) { Register OpReg = I.getOperand(OpIdx).getReg(); SPIRVType *TypeInst = MRI->getVRegDef(OpReg); SPIRVType *OpType = GR.getSPIRVTypeForVReg( @@ -97,19 +97,25 @@ static void validatePtrTypes(const SPIRVSubtarget &STI, if (!ResType || !OpType || OpType->getOpcode() != SPIRV::OpTypePointer) return; SPIRVType *ElemType = GR.getSPIRVTypeForVReg(OpType->getOperand(2).getReg()); - if (!ElemType || ElemType == ResType) + if (!ElemType) + return; + bool IsSameMF = + ElemType->getParent()->getParent() == ResType->getParent()->getParent(); + bool IsEqualTypes = IsSameMF ? ElemType == ResType + : GR.getTypeForSPIRVType(ElemType) == ResTy; + if (IsEqualTypes) return; // There is a type mismatch between results and operand types // and we insert a bitcast before the instruction to keep SPIR-V code valid SPIRV::StorageClass::StorageClass SC = static_cast<SPIRV::StorageClass::StorageClass>( OpType->getOperand(1).getImm()); - MachineInstr *PrevI = I.getPrevNode(); - MachineBasicBlock &MBB = *I.getParent(); - MachineBasicBlock::iterator InsPt = - PrevI ? PrevI->getIterator() : MBB.begin(); - MachineIRBuilder MIB(MBB, InsPt); - SPIRVType *NewPtrType = GR.getOrCreateSPIRVPointerType(ResType, MIB, SC); + MachineIRBuilder MIB(I); + SPIRVType *NewBaseType = + IsSameMF ? ResType + : GR.getOrCreateSPIRVType( + ResTy, MIB, SPIRV::AccessQualifier::ReadWrite, false); + SPIRVType *NewPtrType = GR.getOrCreateSPIRVPointerType(NewBaseType, MIB, SC); if (!GR.isBitcastCompatible(NewPtrType, OpType)) report_fatal_error( "insert validation bitcast: incompatible result and operand types"); @@ -127,6 +133,85 @@ static void validatePtrTypes(const SPIRVSubtarget &STI, I.getOperand(OpIdx).setReg(NewReg); } +// Insert a bitcast before the function call instruction to keep SPIR-V code +// valid when there is a type mismatch between actual and expected types of an +// argument: +// %formal = OpFunctionParameter %formal_type +// ... +// %res = OpFunctionCall %ty %fun %actual ... +// implies that %actual is of %formal_type, and in case of opaque pointers. +// We may need to insert a bitcast to ensure this. +void validateFunCallMachineDef(const SPIRVSubtarget &STI, + MachineRegisterInfo *DefMRI, + MachineRegisterInfo *CallMRI, + SPIRVGlobalRegistry &GR, MachineInstr &FunCall, + MachineInstr *FunDef) { + if (FunDef->getOpcode() != SPIRV::OpFunction) + return; + unsigned OpIdx = 3; + for (FunDef = FunDef->getNextNode(); + FunDef && FunDef->getOpcode() == SPIRV::OpFunctionParameter && + OpIdx < FunCall.getNumOperands(); + FunDef = FunDef->getNextNode(), OpIdx++) { + SPIRVType *DefPtrType = DefMRI->getVRegDef(FunDef->getOperand(1).getReg()); + SPIRVType *DefElemType = + DefPtrType && DefPtrType->getOpcode() == SPIRV::OpTypePointer + ? GR.getSPIRVTypeForVReg(DefPtrType->getOperand(2).getReg()) + : nullptr; + if (DefElemType) { + const Type *DefElemTy = GR.getTypeForSPIRVType(DefElemType); + // Switch GR context to the call site instead of the (default) definition + // side + GR.setCurrentFunc(*FunCall.getParent()->getParent()); + validatePtrTypes(STI, CallMRI, GR, FunCall, OpIdx, DefElemType, + DefElemTy); + GR.setCurrentFunc(*FunDef->getParent()->getParent()); + } + } +} + +// Ensure there is no mismatch between actual and expected arg types: calls +// with a processed definition. Return Function pointer if it's a forward +// call (ahead of definition), and nullptr otherwise. +const Function *validateFunCall(const SPIRVSubtarget &STI, + MachineRegisterInfo *MRI, + SPIRVGlobalRegistry &GR, + MachineInstr &FunCall) { + const GlobalValue *GV = FunCall.getOperand(2).getGlobal(); + const Function *F = dyn_cast<Function>(GV); + MachineInstr *FunDef = + const_cast<MachineInstr *>(GR.getFunctionDefinition(F)); + if (!FunDef) + return F; + validateFunCallMachineDef(STI, MRI, MRI, GR, FunCall, FunDef); + return nullptr; +} + +// Ensure there is no mismatch between actual and expected arg types: calls +// ahead of a processed definition. +void validateForwardCalls(const SPIRVSubtarget &STI, + MachineRegisterInfo *DefMRI, SPIRVGlobalRegistry &GR, + MachineInstr &FunDef) { + const Function *F = GR.getFunctionByDefinition(&FunDef); + if (SmallVector<MachineInstr *> *FwdCalls = GR.getForwardCalls(F)) + for (MachineInstr *FunCall : *FwdCalls) { + MachineRegisterInfo *CallMRI = + &FunCall->getParent()->getParent()->getRegInfo(); + validateFunCallMachineDef(STI, DefMRI, CallMRI, GR, *FunCall, &FunDef); + } +} + +// Validation of an access chain. +void validateAccessChain(const SPIRVSubtarget &STI, MachineRegisterInfo *MRI, + SPIRVGlobalRegistry &GR, MachineInstr &I) { + SPIRVType *BaseTypeInst = GR.getSPIRVTypeForVReg(I.getOperand(0).getReg()); + if (BaseTypeInst && BaseTypeInst->getOpcode() == SPIRV::OpTypePointer) { + SPIRVType *BaseElemType = + GR.getSPIRVTypeForVReg(BaseTypeInst->getOperand(2).getReg()); + validatePtrTypes(STI, MRI, GR, I, 2, BaseElemType); + } +} + // TODO: the logic of inserting additional bitcast's is to be moved // to pre-IRTranslation passes eventually void SPIRVTargetLowering::finalizeLowering(MachineFunction &MF) const { @@ -139,15 +224,80 @@ void SPIRVTargetLowering::finalizeLowering(MachineFunction &MF) const { MBBI != MBBE;) { MachineInstr &MI = *MBBI++; switch (MI.getOpcode()) { + case SPIRV::OpAtomicLoad: + case SPIRV::OpAtomicExchange: + case SPIRV::OpAtomicCompareExchange: + case SPIRV::OpAtomicCompareExchangeWeak: + case SPIRV::OpAtomicIIncrement: + case SPIRV::OpAtomicIDecrement: + case SPIRV::OpAtomicIAdd: + case SPIRV::OpAtomicISub: + case SPIRV::OpAtomicSMin: + case SPIRV::OpAtomicUMin: + case SPIRV::OpAtomicSMax: + case SPIRV::OpAtomicUMax: + case SPIRV::OpAtomicAnd: + case SPIRV::OpAtomicOr: + case SPIRV::OpAtomicXor: + // for the above listed instructions + // OpAtomicXXX <ResType>, ptr %Op, ... + // implies that %Op is a pointer to <ResType> case SPIRV::OpLoad: // OpLoad <ResType>, ptr %Op implies that %Op is a pointer to <ResType> - validatePtrTypes(STI, MRI, GR, MI, - GR.getSPIRVTypeForVReg(MI.getOperand(0).getReg()), 2); + validatePtrTypes(STI, MRI, GR, MI, 2, + GR.getSPIRVTypeForVReg(MI.getOperand(0).getReg())); + break; + case SPIRV::OpAtomicStore: + // OpAtomicStore ptr %Op, <Scope>, <Mem>, <Obj> + // implies that %Op points to the <Obj>'s type + validatePtrTypes(STI, MRI, GR, MI, 0, + GR.getSPIRVTypeForVReg(MI.getOperand(3).getReg())); break; case SPIRV::OpStore: // OpStore ptr %Op, <Obj> implies that %Op points to the <Obj>'s type - validatePtrTypes(STI, MRI, GR, MI, - GR.getSPIRVTypeForVReg(MI.getOperand(1).getReg()), 0); + validatePtrTypes(STI, MRI, GR, MI, 0, + GR.getSPIRVTypeForVReg(MI.getOperand(1).getReg())); + break; + case SPIRV::OpPtrCastToGeneric: + validateAccessChain(STI, MRI, GR, MI); + break; + case SPIRV::OpInBoundsPtrAccessChain: + if (MI.getNumOperands() == 4) + validateAccessChain(STI, MRI, GR, MI); + break; + + case SPIRV::OpFunctionCall: + // ensure there is no mismatch between actual and expected arg types: + // calls with a processed definition + if (MI.getNumOperands() > 3) + if (const Function *F = validateFunCall(STI, MRI, GR, MI)) + GR.addForwardCall(F, &MI); + break; + case SPIRV::OpFunction: + // ensure there is no mismatch between actual and expected arg types: + // calls ahead of a processed definition + validateForwardCalls(STI, MRI, GR, MI); + break; + + // ensure that LLVM IR bitwise instructions result in logical SPIR-V + // instructions when applied to bool type + case SPIRV::OpBitwiseOrS: + case SPIRV::OpBitwiseOrV: + if (GR.isScalarOrVectorOfType(MI.getOperand(1).getReg(), + SPIRV::OpTypeBool)) + MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalOr)); + break; + case SPIRV::OpBitwiseAndS: + case SPIRV::OpBitwiseAndV: + if (GR.isScalarOrVectorOfType(MI.getOperand(1).getReg(), + SPIRV::OpTypeBool)) + MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalAnd)); + break; + case SPIRV::OpBitwiseXorS: + case SPIRV::OpBitwiseXorV: + if (GR.isScalarOrVectorOfType(MI.getOperand(1).getReg(), + SPIRV::OpTypeBool)) + MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalNotEqual)); break; } } diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index 74df8de6eb90aa67728a3016097e41a7d3fab3ef..f4525e713c987fb761fdeb7a433c125bf19c5058 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -26,10 +26,33 @@ #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/IR/IntrinsicsSPIRV.h" #include "llvm/Support/Debug.h" +namespace llvm { + +class SPIRVMachineModuleInfo : public MachineModuleInfoImpl { +public: + SyncScope::ID Work_ItemSSID; + SyncScope::ID WorkGroupSSID; + SyncScope::ID DeviceSSID; + SyncScope::ID AllSVMDevicesSSID; + SyncScope::ID SubGroupSSID; + + SPIRVMachineModuleInfo(const MachineModuleInfo &MMI) { + LLVMContext &CTX = MMI.getModule()->getContext(); + Work_ItemSSID = CTX.getOrInsertSyncScopeID("work_item"); + WorkGroupSSID = CTX.getOrInsertSyncScopeID("workgroup"); + DeviceSSID = CTX.getOrInsertSyncScopeID("device"); + AllSVMDevicesSSID = CTX.getOrInsertSyncScopeID("all_svm_devices"); + SubGroupSSID = CTX.getOrInsertSyncScopeID("sub_group"); + } +}; + +} // end namespace llvm + #define DEBUG_TYPE "spirv-isel" using namespace llvm; @@ -52,6 +75,7 @@ class SPIRVInstructionSelector : public InstructionSelector { const RegisterBankInfo &RBI; SPIRVGlobalRegistry &GR; MachineRegisterInfo *MRI; + SPIRVMachineModuleInfo *MMI = nullptr; /// We need to keep track of the number we give to anonymous global values to /// generate the same name every time when this is needed. @@ -125,6 +149,8 @@ private: bool selectConstVector(Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const; + bool selectSplatVector(Register ResVReg, const SPIRVType *ResType, + MachineInstr &I) const; bool selectCmp(Register ResVReg, const SPIRVType *ResType, unsigned comparisonOpcode, MachineInstr &I) const; @@ -205,6 +231,9 @@ private: Register buildZerosVal(const SPIRVType *ResType, MachineInstr &I) const; Register buildOnesVal(bool AllOnes, const SPIRVType *ResType, MachineInstr &I) const; + + bool wrapIntoSpecConstantOp(MachineInstr &I, + SmallVector<Register> &CompositeArgs) const; }; } // end anonymous namespace @@ -231,6 +260,7 @@ void SPIRVInstructionSelector::setupMF(MachineFunction &MF, GISelKnownBits *KB, CodeGenCoverage *CoverageInfo, ProfileSummaryInfo *PSI, BlockFrequencyInfo *BFI) { + MMI = &MF.getMMI().getObjFileInfo<SPIRVMachineModuleInfo>(); MRI = &MF.getRegInfo(); GR.setCurrentFunc(MF); InstructionSelector::setupMF(MF, KB, CoverageInfo, PSI, BFI); @@ -313,6 +343,8 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg, case TargetOpcode::G_BUILD_VECTOR: return selectConstVector(ResVReg, ResType, I); + case TargetOpcode::G_SPLAT_VECTOR: + return selectSplatVector(ResVReg, ResType, I); case TargetOpcode::G_SHUFFLE_VECTOR: { MachineBasicBlock &BB = *I.getParent(); @@ -470,6 +502,7 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg, assert(I.getOperand(1).isReg() && I.getOperand(2).isReg()); Register GV = I.getOperand(1).getReg(); MachineRegisterInfo::def_instr_iterator II = MRI->def_instr_begin(GV); + (void)II; assert(((*II).getOpcode() == TargetOpcode::G_GLOBAL_VALUE || (*II).getOpcode() == TargetOpcode::COPY || (*II).getOpcode() == SPIRV::OpVariable) && @@ -609,15 +642,27 @@ bool SPIRVInstructionSelector::selectBitcast(Register ResVReg, return selectUnOp(ResVReg, ResType, I, SPIRV::OpBitcast); } -static SPIRV::Scope::Scope getScope(SyncScope::ID Ord) { - switch (Ord) { - case SyncScope::SingleThread: +static SPIRV::Scope::Scope getScope(SyncScope::ID Ord, + SPIRVMachineModuleInfo *MMI) { + if (Ord == SyncScope::SingleThread || Ord == MMI->Work_ItemSSID) return SPIRV::Scope::Invocation; - case SyncScope::System: + else if (Ord == SyncScope::System || Ord == MMI->DeviceSSID) + return SPIRV::Scope::Device; + else if (Ord == MMI->WorkGroupSSID) + return SPIRV::Scope::Workgroup; + else if (Ord == MMI->AllSVMDevicesSSID) + return SPIRV::Scope::CrossDevice; + else if (Ord == MMI->SubGroupSSID) + return SPIRV::Scope::Subgroup; + else + // OpenCL approach is: "The functions that do not have memory_scope argument + // have the same semantics as the corresponding functions with the + // memory_scope argument set to memory_scope_device." See ref.: // + // https://registry.khronos.org/OpenCL/specs/3.0-unified/html/OpenCL_C.html#atomic-functions + // In our case if the scope is unknown, assuming that SPIR-V code is to be + // consumed in an OpenCL environment, we use the same approach and set the + // scope to memory_scope_device. return SPIRV::Scope::Device; - default: - llvm_unreachable("Unsupported synchronization Scope ID."); - } } static void addMemoryOperands(MachineMemOperand *MemOp, @@ -730,10 +775,13 @@ bool SPIRVInstructionSelector::selectMemOperation(Register ResVReg, SPIRVType *VarTy = GR.getOrCreateSPIRVPointerType( ArrTy, I, TII, SPIRV::StorageClass::UniformConstant); // TODO: check if we have such GV, add init, use buildGlobalVariable. - Type *LLVMArrTy = ArrayType::get( - IntegerType::get(GR.CurMF->getFunction().getContext(), 8), Num); - GlobalVariable *GV = - new GlobalVariable(LLVMArrTy, true, GlobalValue::InternalLinkage); + Function &CurFunction = GR.CurMF->getFunction(); + Type *LLVMArrTy = + ArrayType::get(IntegerType::get(CurFunction.getContext(), 8), Num); + // Module takes ownership of the global var. + GlobalVariable *GV = new GlobalVariable(*CurFunction.getParent(), LLVMArrTy, + true, GlobalValue::InternalLinkage, + Constant::getNullValue(LLVMArrTy)); Register VarReg = MRI->createGenericVirtualRegister(LLT::scalar(32)); GR.add(GV, GR.CurMF, VarReg); @@ -769,7 +817,8 @@ bool SPIRVInstructionSelector::selectAtomicRMW(Register ResVReg, unsigned NegateOpcode) const { assert(I.hasOneMemOperand()); const MachineMemOperand *MemOp = *I.memoperands_begin(); - uint32_t Scope = static_cast<uint32_t>(getScope(MemOp->getSyncScopeID())); + uint32_t Scope = + static_cast<uint32_t>(getScope(MemOp->getSyncScopeID(), MMI)); Register ScopeReg = buildI32Constant(Scope, I); Register Ptr = I.getOperand(1).getReg(); @@ -840,7 +889,7 @@ bool SPIRVInstructionSelector::selectFence(MachineInstr &I) const { uint32_t MemSem = static_cast<uint32_t>(getMemSemantics(AO)); Register MemSemReg = buildI32Constant(MemSem, I); SyncScope::ID Ord = SyncScope::ID(I.getOperand(1).getImm()); - uint32_t Scope = static_cast<uint32_t>(getScope(Ord)); + uint32_t Scope = static_cast<uint32_t>(getScope(Ord, MMI)); Register ScopeReg = buildI32Constant(Scope, I); MachineBasicBlock &BB = *I.getParent(); return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpMemoryBarrier)) @@ -859,7 +908,8 @@ bool SPIRVInstructionSelector::selectAtomicCmpXchg(Register ResVReg, if (!isa<GIntrinsic>(I)) { assert(I.hasOneMemOperand()); const MachineMemOperand *MemOp = *I.memoperands_begin(); - unsigned Scope = static_cast<uint32_t>(getScope(MemOp->getSyncScopeID())); + unsigned Scope = + static_cast<uint32_t>(getScope(MemOp->getSyncScopeID(), MMI)); ScopeReg = buildI32Constant(Scope, I); unsigned ScSem = static_cast<uint32_t>( @@ -1185,6 +1235,74 @@ bool SPIRVInstructionSelector::selectConstVector(Register ResVReg, return MIB.constrainAllUses(TII, TRI, RBI); } +static unsigned getArrayComponentCount(MachineRegisterInfo *MRI, + const SPIRVType *ResType) { + Register OpReg = ResType->getOperand(2).getReg(); + SPIRVType *OpDef = MRI->getVRegDef(OpReg); + if (!OpDef) + return 0; + if (OpDef->getOpcode() == SPIRV::ASSIGN_TYPE && + OpDef->getOperand(1).isReg()) { + if (SPIRVType *RefDef = MRI->getVRegDef(OpDef->getOperand(1).getReg())) + OpDef = RefDef; + } + unsigned N = OpDef->getOpcode() == TargetOpcode::G_CONSTANT + ? OpDef->getOperand(1).getCImm()->getValue().getZExtValue() + : 0; + return N; +} + +// Return true if the type represents a constant register +static bool isConstReg(MachineRegisterInfo *MRI, SPIRVType *OpDef) { + if (OpDef->getOpcode() == SPIRV::ASSIGN_TYPE && + OpDef->getOperand(1).isReg()) { + if (SPIRVType *RefDef = MRI->getVRegDef(OpDef->getOperand(1).getReg())) + OpDef = RefDef; + } + return OpDef->getOpcode() == TargetOpcode::G_CONSTANT || + OpDef->getOpcode() == TargetOpcode::G_FCONSTANT; +} + +// Return true if the virtual register represents a constant +static bool isConstReg(MachineRegisterInfo *MRI, Register OpReg) { + if (SPIRVType *OpDef = MRI->getVRegDef(OpReg)) + return isConstReg(MRI, OpDef); + return false; +} + +bool SPIRVInstructionSelector::selectSplatVector(Register ResVReg, + const SPIRVType *ResType, + MachineInstr &I) const { + unsigned N = 0; + if (ResType->getOpcode() == SPIRV::OpTypeVector) + N = GR.getScalarOrVectorComponentCount(ResType); + else if (ResType->getOpcode() == SPIRV::OpTypeArray) + N = getArrayComponentCount(MRI, ResType); + else + report_fatal_error("Cannot select G_SPLAT_VECTOR with a non-vector result"); + + unsigned OpIdx = I.getNumExplicitDefs(); + if (!I.getOperand(OpIdx).isReg()) + report_fatal_error("Unexpected argument in G_SPLAT_VECTOR"); + + // check if we may construct a constant vector + Register OpReg = I.getOperand(OpIdx).getReg(); + bool IsConst = isConstReg(MRI, OpReg); + + if (!IsConst && N < 2) + report_fatal_error( + "There must be at least two constituent operands in a vector"); + + auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), + TII.get(IsConst ? SPIRV::OpConstantComposite + : SPIRV::OpCompositeConstruct)) + .addDef(ResVReg) + .addUse(GR.getSPIRVTypeID(ResType)); + for (unsigned i = 0; i < N; ++i) + MIB.addUse(OpReg); + return MIB.constrainAllUses(TII, TRI, RBI); +} + bool SPIRVInstructionSelector::selectCmp(Register ResVReg, const SPIRVType *ResType, unsigned CmpOpc, @@ -1522,11 +1640,54 @@ bool SPIRVInstructionSelector::selectGEP(Register ResVReg, return Res.constrainAllUses(TII, TRI, RBI); } +// Maybe wrap a value into OpSpecConstantOp +bool SPIRVInstructionSelector::wrapIntoSpecConstantOp( + MachineInstr &I, SmallVector<Register> &CompositeArgs) const { + bool Result = true; + unsigned Lim = I.getNumExplicitOperands(); + for (unsigned i = I.getNumExplicitDefs() + 1; i < Lim; ++i) { + Register OpReg = I.getOperand(i).getReg(); + SPIRVType *OpDefine = MRI->getVRegDef(OpReg); + SPIRVType *OpType = GR.getSPIRVTypeForVReg(OpReg); + if (!OpDefine || !OpType || isConstReg(MRI, OpDefine) || + OpDefine->getOpcode() == TargetOpcode::G_ADDRSPACE_CAST) { + // The case of G_ADDRSPACE_CAST inside spv_const_composite() is processed + // by selectAddrSpaceCast() + CompositeArgs.push_back(OpReg); + continue; + } + MachineFunction *MF = I.getMF(); + Register WrapReg = GR.find(OpDefine, MF); + if (WrapReg.isValid()) { + CompositeArgs.push_back(WrapReg); + continue; + } + // Create a new register for the wrapper + WrapReg = MRI->createVirtualRegister(&SPIRV::IDRegClass); + GR.add(OpDefine, MF, WrapReg); + CompositeArgs.push_back(WrapReg); + // Decorate the wrapper register and generate a new instruction + MRI->setType(WrapReg, LLT::pointer(0, 32)); + GR.assignSPIRVTypeToVReg(OpType, WrapReg, *MF); + MachineBasicBlock &BB = *I.getParent(); + Result = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpSpecConstantOp)) + .addDef(WrapReg) + .addUse(GR.getSPIRVTypeID(OpType)) + .addImm(static_cast<uint32_t>(SPIRV::Opcode::Bitcast)) + .addUse(OpReg) + .constrainAllUses(TII, TRI, RBI); + if (!Result) + break; + } + return Result; +} + bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const { MachineBasicBlock &BB = *I.getParent(); - switch (cast<GIntrinsic>(I).getIntrinsicID()) { + Intrinsic::ID IID = cast<GIntrinsic>(I).getIntrinsicID(); + switch (IID) { case Intrinsic::spv_load: return selectLoad(ResVReg, ResType, I); case Intrinsic::spv_store: @@ -1559,17 +1720,21 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, case Intrinsic::spv_const_composite: { // If no values are attached, the composite is null constant. bool IsNull = I.getNumExplicitDefs() + 1 == I.getNumExplicitOperands(); - unsigned Opcode = - IsNull ? SPIRV::OpConstantNull : SPIRV::OpConstantComposite; + // Select a proper instruction. + unsigned Opcode = SPIRV::OpConstantNull; + SmallVector<Register> CompositeArgs; + if (!IsNull) { + Opcode = SPIRV::OpConstantComposite; + if (!wrapIntoSpecConstantOp(I, CompositeArgs)) + return false; + } auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode)) .addDef(ResVReg) .addUse(GR.getSPIRVTypeID(ResType)); // skip type MD node we already used when generated assign.type for this if (!IsNull) { - for (unsigned i = I.getNumExplicitDefs() + 1; - i < I.getNumExplicitOperands(); ++i) { - MIB.addUse(I.getOperand(i).getReg()); - } + for (Register OpReg : CompositeArgs) + MIB.addUse(OpReg); } return MIB.constrainAllUses(TII, TRI, RBI); } @@ -1620,8 +1785,25 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, break; case Intrinsic::spv_thread_id: return selectSpvThreadId(ResVReg, ResType, I); - default: - llvm_unreachable("Intrinsic selection not implemented"); + case Intrinsic::spv_lifetime_start: + case Intrinsic::spv_lifetime_end: { + unsigned Op = IID == Intrinsic::spv_lifetime_start ? SPIRV::OpLifetimeStart + : SPIRV::OpLifetimeStop; + int64_t Size = I.getOperand(I.getNumExplicitDefs() + 1).getImm(); + Register PtrReg = I.getOperand(I.getNumExplicitDefs() + 2).getReg(); + unsigned PonteeOpType = GR.getPointeeTypeOp(PtrReg); + bool IsNonvoidPtr = PonteeOpType != 0 && PonteeOpType != SPIRV::OpTypeVoid; + if (Size == -1 || IsNonvoidPtr) + Size = 0; + BuildMI(BB, I, I.getDebugLoc(), TII.get(Op)).addUse(PtrReg).addImm(Size); + } break; + default: { + std::string DiagMsg; + raw_string_ostream OS(DiagMsg); + I.print(OS); + DiagMsg = "Intrinsic selection not implemented: " + DiagMsg; + report_fatal_error(DiagMsg.c_str(), false); + } } return true; } @@ -1715,7 +1897,7 @@ bool SPIRVInstructionSelector::selectGlobalValue( // FIXME: don't use MachineIRBuilder here, replace it with BuildMI. MachineIRBuilder MIRBuilder(I); const GlobalValue *GV = I.getOperand(1).getGlobal(); - Type *GVType = GV->getValueType(); + Type *GVType = GR.getDeducedGlobalValueType(GV); SPIRVType *PointerBaseType; if (GVType->isArrayTy()) { SPIRVType *ArrayElementType = diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp index f81548742a11e212b69b3593d2fa5dc83f4b4385..4b871bdd5d07580a36750e6fd624d1bf370e3fd7 100644 --- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp @@ -149,7 +149,9 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) { getActionDefinitionsBuilder(G_GLOBAL_VALUE).alwaysLegal(); // TODO: add proper rules for vectors legalization. - getActionDefinitionsBuilder({G_BUILD_VECTOR, G_SHUFFLE_VECTOR}).alwaysLegal(); + getActionDefinitionsBuilder( + {G_BUILD_VECTOR, G_SHUFFLE_VECTOR, G_SPLAT_VECTOR}) + .alwaysLegal(); // Vector Reduction Operations getActionDefinitionsBuilder( diff --git a/llvm/lib/Target/SPIRV/SPIRVMCInstLower.cpp b/llvm/lib/Target/SPIRV/SPIRVMCInstLower.cpp index 8c6649bf628265faa84ec9e3f924db240a7175a2..afa550d6dd424e7783a4b3c423f82465b2763a83 100644 --- a/llvm/lib/Target/SPIRV/SPIRVMCInstLower.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVMCInstLower.cpp @@ -34,7 +34,13 @@ void SPIRVMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI, llvm_unreachable("unknown operand type"); case MachineOperand::MO_GlobalAddress: { Register FuncReg = MAI->getFuncReg(dyn_cast<Function>(MO.getGlobal())); - assert(FuncReg.isValid() && "Cannot find function Id"); + if (!FuncReg.isValid()) { + std::string DiagMsg; + raw_string_ostream OS(DiagMsg); + MI->print(OS); + DiagMsg = "Unknown function in:" + DiagMsg; + report_fatal_error(DiagMsg.c_str()); + } MCOp = MCOperand::createReg(FuncReg); break; } diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index 2b4cb5ccc7b1eb0d8c5aff6b1888f3f1f544fb53..40c3e5f9c6bdab75f39e50e82ed8a7538fca3fae 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -658,7 +658,7 @@ void RequirementHandler::initAvailableCapabilitiesForVulkan( // Provided by all supported Vulkan versions. addAvailableCaps({Capability::Int16, Capability::Int64, Capability::Float16, - Capability::Float64}); + Capability::Float64, Capability::GroupNonUniform}); } } // namespace SPIRV @@ -1309,5 +1309,8 @@ bool SPIRVModuleAnalysis::runOnModule(Module &M) { if (MAI.MS[SPIRV::MB_EntryPoints].empty()) MAI.Reqs.addCapability(SPIRV::Capability::Linkage); + // Set maximum ID used. + GR->setBound(MAI.MaxID); + return false; } diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h index 708384fc55f525d0e4c08fd0c86d2b6e2f849de1..6e86eed30c5dc16a977d0e1bf0ea72d1fe500e90 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h @@ -163,8 +163,8 @@ struct ModuleAnalysisInfo { Register getFuncReg(const Function *F) { assert(F && "Function is null"); auto FuncPtrRegPair = FuncMap.find(F); - assert(FuncPtrRegPair != FuncMap.end() && "Cannot find function ID"); - return FuncPtrRegPair->second; + return FuncPtrRegPair == FuncMap.end() ? Register(0) + : FuncPtrRegPair->second; } Register getExtInstSetReg(unsigned SetNum) { return ExtInstSetMap[SetNum]; } InstrList &getMSInstrs(unsigned MSType) { return MS[MSType]; } diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp index d547f91ba4a565f982859203c5ca784e6807ff1e..b133f0ae85de202e7da49532bb57fc19f39c2278 100644 --- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp @@ -186,7 +186,10 @@ static SPIRVType *propagateSPIRVType(MachineInstr *MI, SPIRVGlobalRegistry *GR, } case TargetOpcode::G_GLOBAL_VALUE: { MIB.setInsertPt(*MI->getParent(), MI); - Type *Ty = MI->getOperand(1).getGlobal()->getType(); + const GlobalValue *Global = MI->getOperand(1).getGlobal(); + Type *ElementTy = GR->getDeducedGlobalValueType(Global); + auto *Ty = TypedPointerType::get(ElementTy, + Global->getType()->getAddressSpace()); SpirvTy = GR->getOrCreateSPIRVType(Ty, MIB); break; } @@ -543,6 +546,7 @@ static void processSwitches(MachineFunction &MF, SPIRVGlobalRegistry *GR, Register Dst = ICMP->getOperand(0).getReg(); MachineOperand &PredOp = ICMP->getOperand(1); const auto CC = static_cast<CmpInst::Predicate>(PredOp.getPredicate()); + (void)CC; assert((CC == CmpInst::ICMP_EQ || CC == CmpInst::ICMP_ULE) && MRI.hasOneUse(Dst) && MRI.hasOneDef(CompareReg)); uint64_t Value = getIConstVal(ICMP->getOperand(3).getReg(), &MRI); diff --git a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp index c376497469ce3393eb2c0e53525ef96d39c72aa3..a8a0577f60564c9132725c3b7ec5e54828124079 100644 --- a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp @@ -263,6 +263,21 @@ static void lowerExpectAssume(IntrinsicInst *II) { return; } +static bool toSpvOverloadedIntrinsic(IntrinsicInst *II, Intrinsic::ID NewID, + ArrayRef<unsigned> OpNos) { + Function *F = nullptr; + if (OpNos.empty()) { + F = Intrinsic::getDeclaration(II->getModule(), NewID); + } else { + SmallVector<Type *, 4> Tys; + for (unsigned OpNo : OpNos) + Tys.push_back(II->getOperand(OpNo)->getType()); + F = Intrinsic::getDeclaration(II->getModule(), NewID, Tys); + } + II->setCalledFunction(F); + return true; +} + static void lowerUMulWithOverflow(IntrinsicInst *UMulIntrinsic) { // Get a separate function - otherwise, we'd have to rework the CFG of the // current one. Then simply replace the intrinsic uses with a call to the new @@ -290,22 +305,35 @@ bool SPIRVPrepareFunctions::substituteIntrinsicCalls(Function *F) { if (!CF || !CF->isIntrinsic()) continue; auto *II = cast<IntrinsicInst>(Call); - if (II->getIntrinsicID() == Intrinsic::memset || - II->getIntrinsicID() == Intrinsic::bswap) + switch (II->getIntrinsicID()) { + case Intrinsic::memset: + case Intrinsic::bswap: Changed |= lowerIntrinsicToFunction(II); - else if (II->getIntrinsicID() == Intrinsic::fshl || - II->getIntrinsicID() == Intrinsic::fshr) { + break; + case Intrinsic::fshl: + case Intrinsic::fshr: lowerFunnelShifts(II); Changed = true; - } else if (II->getIntrinsicID() == Intrinsic::umul_with_overflow) { + break; + case Intrinsic::umul_with_overflow: lowerUMulWithOverflow(II); Changed = true; - } else if (II->getIntrinsicID() == Intrinsic::assume || - II->getIntrinsicID() == Intrinsic::expect) { + break; + case Intrinsic::assume: + case Intrinsic::expect: { const SPIRVSubtarget &STI = TM.getSubtarget<SPIRVSubtarget>(*F); if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume)) lowerExpectAssume(II); Changed = true; + } break; + case Intrinsic::lifetime_start: + Changed |= toSpvOverloadedIntrinsic( + II, Intrinsic::SPVIntrinsics::spv_lifetime_start, {1}); + break; + case Intrinsic::lifetime_end: + Changed |= toSpvOverloadedIntrinsic( + II, Intrinsic::SPVIntrinsics::spv_lifetime_end, {1}); + break; } } } diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp index 38caa7c8ea0a7f76ea0c7fbeadc01b64e1d322c8..f3864b56e1e97d3f7ebb2d622a154dda527298ef 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp @@ -12,6 +12,7 @@ #include "SPIRVSubtarget.h" #include "SPIRV.h" +#include "SPIRVCommandLine.h" #include "SPIRVGlobalRegistry.h" #include "SPIRVLegalizerInfo.h" #include "SPIRVRegisterBankInfo.h" @@ -27,80 +28,15 @@ using namespace llvm; #define GET_SUBTARGETINFO_CTOR #include "SPIRVGenSubtargetInfo.inc" -cl::list<SPIRV::Extension::Extension> Extensions( - "spirv-extensions", cl::desc("SPIR-V extensions"), cl::ZeroOrMore, - cl::Hidden, - cl::values( - clEnumValN(SPIRV::Extension::SPV_EXT_shader_atomic_float_add, - "SPV_EXT_shader_atomic_float_add", - "Adds atomic add instruction on floating-point numbers."), - clEnumValN( - SPIRV::Extension::SPV_EXT_shader_atomic_float16_add, - "SPV_EXT_shader_atomic_float16_add", - "Extends the SPV_EXT_shader_atomic_float_add extension to support " - "atomically adding to 16-bit floating-point numbers in memory."), - clEnumValN( - SPIRV::Extension::SPV_EXT_shader_atomic_float_min_max, - "SPV_EXT_shader_atomic_float_min_max", - "Adds atomic min and max instruction on floating-point numbers."), - clEnumValN(SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers, - "SPV_INTEL_arbitrary_precision_integers", - "Allows generating arbitrary width integer types."), - clEnumValN(SPIRV::Extension::SPV_INTEL_optnone, "SPV_INTEL_optnone", - "Adds OptNoneINTEL value for Function Control mask that " - "indicates a request to not optimize the function."), - clEnumValN(SPIRV::Extension::SPV_INTEL_usm_storage_classes, - "SPV_INTEL_usm_storage_classes", - "Introduces two new storage classes that are sub classes of " - "the CrossWorkgroup storage class " - "that provides additional information that can enable " - "optimization."), - clEnumValN(SPIRV::Extension::SPV_INTEL_subgroups, "SPV_INTEL_subgroups", - "Allows work items in a subgroup to share data without the " - "use of local memory and work group barriers, and to " - "utilize specialized hardware to load and store blocks of " - "data from images or buffers."), - clEnumValN(SPIRV::Extension::SPV_KHR_uniform_group_instructions, - "SPV_KHR_uniform_group_instructions", - "Allows support for additional group operations within " - "uniform control flow."), - clEnumValN(SPIRV::Extension::SPV_KHR_no_integer_wrap_decoration, - "SPV_KHR_no_integer_wrap_decoration", - "Adds decorations to indicate that a given instruction does " - "not cause integer wrapping."), - clEnumValN( - SPIRV::Extension::SPV_KHR_float_controls, "SPV_KHR_float_controls", - "Provides new execution modes to control floating-point " - "computations by overriding an implementation’s default behavior " - "for rounding modes, denormals, signed zero, and infinities."), - clEnumValN(SPIRV::Extension::SPV_KHR_expect_assume, - "SPV_KHR_expect_assume", - "Provides additional information to a compiler, similar to " - "the llvm.assume and llvm.expect intrinsics."), - clEnumValN(SPIRV::Extension::SPV_KHR_bit_instructions, - "SPV_KHR_bit_instructions", - "This enables bit instructions to be used by SPIR-V modules " - "without requiring the Shader capability."), - clEnumValN( - SPIRV::Extension::SPV_KHR_linkonce_odr, "SPV_KHR_linkonce_odr", - "Allows to use the LinkOnceODR linkage type that is to let " - "a function or global variable to be merged with other functions " - "or global variables of the same name when linkage occurs."), - clEnumValN(SPIRV::Extension::SPV_INTEL_bfloat16_conversion, - "SPV_INTEL_bfloat16_conversion", - "Adds instructions to convert between single-precision " - "32-bit floating-point values and 16-bit bfloat16 values."), - clEnumValN(SPIRV::Extension::SPV_KHR_subgroup_rotate, - "SPV_KHR_subgroup_rotate", - "Adds a new instruction that enables rotating values across " - "invocations within a subgroup."), - clEnumValN(SPIRV::Extension::SPV_INTEL_variable_length_array, - "SPV_INTEL_variable_length_array", - "Allows to allocate local arrays whose number of elements " - "is unknown at compile time."), - clEnumValN(SPIRV::Extension::SPV_INTEL_function_pointers, - "SPV_INTEL_function_pointers", - "Allows translation of function pointers."))); +static cl::opt<bool> + SPVTranslatorCompat("translator-compatibility-mode", + cl::desc("SPIR-V Translator compatibility mode"), + cl::Optional, cl::init(false)); + +static cl::opt<std::set<SPIRV::Extension::Extension>, false, + SPIRVExtensionsParser> + Extensions("spirv-ext", + cl::desc("Specify list of enabled SPIR-V extensions")); // Compare version numbers, but allow 0 to mean unspecified. static bool isAtLeastVer(uint32_t Target, uint32_t VerToCompareTo) { @@ -157,8 +93,9 @@ bool SPIRVSubtarget::isAtLeastOpenCLVer(uint32_t VerToCompareTo) const { } // If the SPIR-V version is >= 1.4 we can call OpPtrEqual and OpPtrNotEqual. +// In SPIR-V Translator compatibility mode this feature is not available. bool SPIRVSubtarget::canDirectlyComparePointers() const { - return isAtLeastVer(SPIRVVersion, 14); + return !SPVTranslatorCompat && isAtLeastVer(SPIRVVersion, 14); } void SPIRVSubtarget::initAvailableExtensions() { @@ -166,8 +103,7 @@ void SPIRVSubtarget::initAvailableExtensions() { if (!isOpenCLEnv()) return; - for (auto Extension : Extensions) - AvailableExtensions.insert(Extension); + AvailableExtensions.insert(Extensions.begin(), Extensions.end()); } // TODO: use command line args for this rather than just defaults. diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.h b/llvm/lib/Target/SPIRV/SPIRVSubtarget.h index 62524ebfc9bf8c1dd8fab5bfbccc2591647bafd0..3b486226a93931a5ab2191ba5845de275e5f83d2 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSubtarget.h +++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.h @@ -71,6 +71,7 @@ public: // The definition of this function is auto generated by tblgen. void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); unsigned getPointerSize() const { return PointerSize; } + unsigned getBound() const { return GR->getBound(); } bool canDirectlyComparePointers() const; // TODO: this environment is not implemented in Triple, we need to decide // how to standardize its support. For now, let's assume SPIR-V with physical diff --git a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td index 8dbbd9049844c825cd0f15abd52629adfbe1c72f..ff102e318469f4e5cb1b52e1e90330e6980dce4f 100644 --- a/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td +++ b/llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td @@ -1611,3 +1611,4 @@ multiclass OpcodeOperand<bits<32> value> { // TODO: implement other mnemonics. defm InBoundsPtrAccessChain : OpcodeOperand<70>; defm PtrCastToGeneric : OpcodeOperand<121>; +defm Bitcast : OpcodeOperand<124>; diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp index fc7502479fdcdd56bdc761bd18551aa16f7d3522..c87c1293c622fc7ce31578749be8c9e3c6462e6e 100644 --- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp @@ -306,10 +306,12 @@ static bool isNonMangledOCLBuiltin(StringRef Name) { std::string getOclOrSpirvBuiltinDemangledName(StringRef Name) { bool IsNonMangledOCL = isNonMangledOCLBuiltin(Name); bool IsNonMangledSPIRV = Name.starts_with("__spirv_"); + bool IsNonMangledHLSL = Name.starts_with("__hlsl_"); bool IsMangled = Name.starts_with("_Z"); - if (!IsNonMangledOCL && !IsNonMangledSPIRV && !IsMangled) - return std::string(); + // Otherwise use simple demangling to return the function name. + if (IsNonMangledOCL || IsNonMangledSPIRV || IsNonMangledHLSL || !IsMangled) + return Name.str(); // Try to use the itanium demangler. if (char *DemangledName = itaniumDemangle(Name.data())) { @@ -317,9 +319,6 @@ std::string getOclOrSpirvBuiltinDemangledName(StringRef Name) { free(DemangledName); return Result; } - // Otherwise use simple demangling to return the function name. - if (IsNonMangledOCL || IsNonMangledSPIRV) - return Name.str(); // Autocheck C++, maybe need to do explicit check of the source language. // OpenCL C++ built-ins are declared in cl namespace. diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h index e5f35aaca9a8baeb060d6445e099a1cb615d0c71..c2c3475e1a936f620b847bad769327f0f426798d 100644 --- a/llvm/lib/Target/SPIRV/SPIRVUtils.h +++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h @@ -15,6 +15,7 @@ #include "MCTargetDesc/SPIRVBaseInfo.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/TypedPointerType.h" #include <string> namespace llvm { @@ -100,5 +101,53 @@ bool isEntryPoint(const Function &F); // Parse basic scalar type name, substring TypeName, and return LLVM type. Type *parseBasicTypeName(StringRef TypeName, LLVMContext &Ctx); + +// True if this is an instance of TypedPointerType. +inline bool isTypedPointerTy(const Type *T) { + return T->getTypeID() == Type::TypedPointerTyID; +} + +// True if this is an instance of PointerType. +inline bool isUntypedPointerTy(const Type *T) { + return T->getTypeID() == Type::PointerTyID; +} + +// True if this is an instance of PointerType or TypedPointerType. +inline bool isPointerTy(const Type *T) { + return isUntypedPointerTy(T) || isTypedPointerTy(T); +} + +// Get the address space of this pointer or pointer vector type for instances of +// PointerType or TypedPointerType. +inline unsigned getPointerAddressSpace(const Type *T) { + Type *SubT = T->getScalarType(); + return SubT->getTypeID() == Type::PointerTyID + ? cast<PointerType>(SubT)->getAddressSpace() + : cast<TypedPointerType>(SubT)->getAddressSpace(); +} + +// Return true if the Argument is decorated with a pointee type +inline bool hasPointeeTypeAttr(Argument *Arg) { + return Arg->hasByValAttr() || Arg->hasByRefAttr() || Arg->hasStructRetAttr(); +} + +// Return the pointee type of the argument or nullptr otherwise +inline Type *getPointeeTypeByAttr(Argument *Arg) { + if (Arg->hasByValAttr()) + return Arg->getParamByValType(); + if (Arg->hasStructRetAttr()) + return Arg->getParamStructRetType(); + if (Arg->hasByRefAttr()) + return Arg->getParamByRefType(); + return nullptr; +} + +inline Type *reconstructFunctionType(Function *F) { + SmallVector<Type *> ArgTys; + for (unsigned i = 0; i < F->arg_size(); ++i) + ArgTys.push_back(F->getArg(i)->getType()); + return FunctionType::get(F->getReturnType(), ArgTys, F->isVarArg()); +} + } // namespace llvm #endif // LLVM_LIB_TARGET_SPIRV_SPIRVUTILS_H diff --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp index be4ec1e9dce2a6f5200bd2b6aba36110c92e7c88..67e2b9d7c997821851e18cc49e534edfd65dce11 100644 --- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -307,7 +307,7 @@ public: return StringRef(Tok.Data, Tok.Length); } - unsigned getReg() const override { + MCRegister getReg() const override { assert((Kind == k_Register) && "Invalid access!"); return Reg.RegNum; } diff --git a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp index a58e8e0dfedfaf93965dadbdf03285b49c04cfd7..f2c04215d12dda5c94a7767b0fb9684a3a688a98 100644 --- a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp +++ b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp @@ -227,7 +227,7 @@ public: bool isReg(RegisterKind RegKind) const { return Kind == KindReg && Reg.Kind == RegKind; } - unsigned getReg() const override { + MCRegister getReg() const override { assert(Kind == KindReg && "Not a register"); return Reg.Num; } diff --git a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp index 80c994a32ea96aa02f2f2d9a508c4ae05103627d..4897b37d8eb1ef57fdc7bd2dddaaaeab2801d30b 100644 --- a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp @@ -66,22 +66,6 @@ SystemZFrameLowering::create(const SystemZSubtarget &STI) { return std::make_unique<SystemZELFFrameLowering>(); } -MachineBasicBlock::iterator SystemZFrameLowering::eliminateCallFramePseudoInstr( - MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI) const { - switch (MI->getOpcode()) { - case SystemZ::ADJCALLSTACKDOWN: - case SystemZ::ADJCALLSTACKUP: - assert(hasReservedCallFrame(MF) && - "ADJSTACKDOWN and ADJSTACKUP should be no-ops"); - return MBB.erase(MI); - break; - - default: - llvm_unreachable("Unexpected call frame instruction"); - } -} - namespace { struct SZFrameSortingObj { bool IsValid = false; // True if we care about this Object. diff --git a/llvm/lib/Target/SystemZ/SystemZFrameLowering.h b/llvm/lib/Target/SystemZ/SystemZFrameLowering.h index 95f30e3c0d99c87a1d7b288b844799d9246bf25a..03ce8882c4de5d10fa9909be853c8631bb35fd92 100644 --- a/llvm/lib/Target/SystemZ/SystemZFrameLowering.h +++ b/llvm/lib/Target/SystemZ/SystemZFrameLowering.h @@ -41,9 +41,6 @@ public: } bool hasReservedCallFrame(const MachineFunction &MF) const override; - MachineBasicBlock::iterator - eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI) const override; }; class SystemZELFFrameLowering : public SystemZFrameLowering { diff --git a/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp b/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp index 815eca1240d827e0496fc9d0f946cafd973f335b..deaf3dcaeb92a42421b6c435db8a768b3ea8684b 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp @@ -344,6 +344,9 @@ class SystemZDAGToDAGISel : public SelectionDAGISel { // requirements for a PC-relative access. bool storeLoadIsAligned(SDNode *N) const; + // Return the load extension type of a load or atomic load. + ISD::LoadExtType getLoadExtType(SDNode *N) const; + // Try to expand a boolean SELECT_CCMASK using an IPM sequence. SDValue expandSelectBoolean(SDNode *Node); @@ -1507,15 +1510,17 @@ bool SystemZDAGToDAGISel::storeLoadCanUseBlockBinary(SDNode *N, bool SystemZDAGToDAGISel::storeLoadIsAligned(SDNode *N) const { - auto *MemAccess = cast<LSBaseSDNode>(N); + auto *MemAccess = cast<MemSDNode>(N); + auto *LdSt = dyn_cast<LSBaseSDNode>(MemAccess); TypeSize StoreSize = MemAccess->getMemoryVT().getStoreSize(); SDValue BasePtr = MemAccess->getBasePtr(); MachineMemOperand *MMO = MemAccess->getMemOperand(); assert(MMO && "Expected a memory operand."); // The memory access must have a proper alignment and no index register. + // Only load and store nodes have the offset operand (atomic loads do not). if (MemAccess->getAlign().value() < StoreSize || - !MemAccess->getOffset().isUndef()) + (LdSt && !LdSt->getOffset().isUndef())) return false; // The MMO must not have an unaligned offset. @@ -1545,6 +1550,17 @@ bool SystemZDAGToDAGISel::storeLoadIsAligned(SDNode *N) const { return true; } +ISD::LoadExtType SystemZDAGToDAGISel::getLoadExtType(SDNode *N) const { + ISD::LoadExtType ETy; + if (auto *L = dyn_cast<LoadSDNode>(N)) + ETy = L->getExtensionType(); + else if (auto *AL = dyn_cast<AtomicSDNode>(N)) + ETy = AL->getExtensionType(); + else + llvm_unreachable("Unkown load node type."); + return ETy; +} + void SystemZDAGToDAGISel::Select(SDNode *Node) { // If we have a custom node, we already have selected! if (Node->isMachineOpcode()) { @@ -1742,6 +1758,26 @@ void SystemZDAGToDAGISel::Select(SDNode *Node) { } break; } + + case ISD::ATOMIC_STORE: { + auto *AtomOp = cast<AtomicSDNode>(Node); + // Replace the atomic_store with a regular store and select it. This is + // ok since we know all store instructions <= 8 bytes are atomic, and the + // 16 byte case is already handled during lowering. + StoreSDNode *St = cast<StoreSDNode>(CurDAG->getTruncStore( + AtomOp->getChain(), SDLoc(AtomOp), AtomOp->getVal(), + AtomOp->getBasePtr(), AtomOp->getMemoryVT(), AtomOp->getMemOperand())); + assert(St->getMemOperand()->isAtomic() && "Broken MMO."); + SDNode *Chain = St; + // We have to enforce sequential consistency by performing a + // serialization operation after the store. + if (AtomOp->getSuccessOrdering() == AtomicOrdering::SequentiallyConsistent) + Chain = CurDAG->getMachineNode(SystemZ::Serialize, SDLoc(AtomOp), + MVT::Other, SDValue(Chain, 0)); + ReplaceNode(Node, Chain); + SelectCode(St); + return; + } } SelectCode(Node); diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index 3b85a6ac0371eda5646030a0dc845ce4a671ee5b..efffd669d268b5fc76f5390774f86b4c53fb4e04 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -194,11 +194,6 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM, setOperationAction(ISD::UADDO_CARRY, VT, Custom); setOperationAction(ISD::USUBO_CARRY, VT, Custom); - // Lower ATOMIC_LOAD and ATOMIC_STORE into normal volatile loads and - // stores, putting a serialization instruction after the stores. - setOperationAction(ISD::ATOMIC_LOAD, VT, Custom); - setOperationAction(ISD::ATOMIC_STORE, VT, Custom); - // Lower ATOMIC_LOAD_SUB into ATOMIC_LOAD_ADD if LAA and LAAG are // available, or if the operand is constant. setOperationAction(ISD::ATOMIC_LOAD_SUB, VT, Custom); @@ -298,6 +293,15 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM, setOperationAction(ISD::ATOMIC_LOAD, MVT::i128, Custom); setOperationAction(ISD::ATOMIC_STORE, MVT::i128, Custom); + // Mark sign/zero extending atomic loads as legal, which will make + // DAGCombiner fold extensions into atomic loads if possible. + setAtomicLoadExtAction({ISD::SEXTLOAD, ISD::ZEXTLOAD}, MVT::i64, + {MVT::i8, MVT::i16, MVT::i32}, Legal); + setAtomicLoadExtAction({ISD::SEXTLOAD, ISD::ZEXTLOAD}, MVT::i32, + {MVT::i8, MVT::i16}, Legal); + setAtomicLoadExtAction({ISD::SEXTLOAD, ISD::ZEXTLOAD}, MVT::i16, + MVT::i8, Legal); + // We can use the CC result of compare-and-swap to implement // the "success" result of ATOMIC_CMP_SWAP_WITH_SUCCESS. setOperationAction(ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS, MVT::i32, Custom); @@ -377,6 +381,9 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM, // Handle prefetches with PFD or PFDRL. setOperationAction(ISD::PREFETCH, MVT::Other, Custom); + // Handle readcyclecounter with STCKF. + setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom); + for (MVT VT : MVT::fixedlen_vector_valuetypes()) { // Assume by default that all vector operations need to be expanded. for (unsigned Opcode = 0; Opcode < ISD::BUILTIN_OP_END; ++Opcode) @@ -920,6 +927,22 @@ bool SystemZTargetLowering::hasInlineStackProbe(const MachineFunction &MF) const return false; } +TargetLowering::AtomicExpansionKind +SystemZTargetLowering::shouldCastAtomicLoadInIR(LoadInst *LI) const { + // Lower fp128 the same way as i128. + if (LI->getType()->isFP128Ty()) + return AtomicExpansionKind::CastToInteger; + return AtomicExpansionKind::None; +} + +TargetLowering::AtomicExpansionKind +SystemZTargetLowering::shouldCastAtomicStoreInIR(StoreInst *SI) const { + // Lower fp128 the same way as i128. + if (SI->getValueOperand()->getType()->isFP128Ty()) + return AtomicExpansionKind::CastToInteger; + return AtomicExpansionKind::None; +} + TargetLowering::AtomicExpansionKind SystemZTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const { // Don't expand subword operations as they require special treatment. @@ -4252,6 +4275,7 @@ SDValue SystemZTargetLowering::lowerXALUO(SDValue Op, if (N->getValueType(0) == MVT::i128) { unsigned BaseOp = 0; unsigned FlagOp = 0; + bool IsBorrow = false; switch (Op.getOpcode()) { default: llvm_unreachable("Unknown instruction!"); case ISD::UADDO: @@ -4261,6 +4285,7 @@ SDValue SystemZTargetLowering::lowerXALUO(SDValue Op, case ISD::USUBO: BaseOp = ISD::SUB; FlagOp = SystemZISD::VSCBI; + IsBorrow = true; break; } SDValue Result = DAG.getNode(BaseOp, DL, MVT::i128, LHS, RHS); @@ -4268,6 +4293,9 @@ SDValue SystemZTargetLowering::lowerXALUO(SDValue Op, Flag = DAG.getNode(ISD::AssertZext, DL, MVT::i128, Flag, DAG.getValueType(MVT::i1)); Flag = DAG.getZExtOrTrunc(Flag, DL, N->getValueType(1)); + if (IsBorrow) + Flag = DAG.getNode(ISD::XOR, DL, Flag.getValueType(), + Flag, DAG.getConstant(1, DL, Flag.getValueType())); return DAG.getNode(ISD::MERGE_VALUES, DL, N->getVTList(), Result, Flag); } @@ -4340,6 +4368,7 @@ SDValue SystemZTargetLowering::lowerUADDSUBO_CARRY(SDValue Op, if (VT == MVT::i128) { unsigned BaseOp = 0; unsigned FlagOp = 0; + bool IsBorrow = false; switch (Op.getOpcode()) { default: llvm_unreachable("Unknown instruction!"); case ISD::UADDO_CARRY: @@ -4349,14 +4378,21 @@ SDValue SystemZTargetLowering::lowerUADDSUBO_CARRY(SDValue Op, case ISD::USUBO_CARRY: BaseOp = SystemZISD::VSBI; FlagOp = SystemZISD::VSBCBI; + IsBorrow = true; break; } + if (IsBorrow) + Carry = DAG.getNode(ISD::XOR, DL, Carry.getValueType(), + Carry, DAG.getConstant(1, DL, Carry.getValueType())); Carry = DAG.getZExtOrTrunc(Carry, DL, MVT::i128); SDValue Result = DAG.getNode(BaseOp, DL, MVT::i128, LHS, RHS, Carry); SDValue Flag = DAG.getNode(FlagOp, DL, MVT::i128, LHS, RHS, Carry); Flag = DAG.getNode(ISD::AssertZext, DL, MVT::i128, Flag, DAG.getValueType(MVT::i1)); Flag = DAG.getZExtOrTrunc(Flag, DL, N->getValueType(1)); + if (IsBorrow) + Flag = DAG.getNode(ISD::XOR, DL, Flag.getValueType(), + Flag, DAG.getConstant(1, DL, Flag.getValueType())); return DAG.getNode(ISD::MERGE_VALUES, DL, N->getVTList(), Result, Flag); } @@ -4503,40 +4539,14 @@ SDValue SystemZTargetLowering::lowerATOMIC_FENCE(SDValue Op, return DAG.getNode(ISD::MEMBARRIER, DL, MVT::Other, Op.getOperand(0)); } -// Op is an atomic load. Lower it into a normal volatile load. -SDValue SystemZTargetLowering::lowerATOMIC_LOAD(SDValue Op, - SelectionDAG &DAG) const { - auto *Node = cast<AtomicSDNode>(Op.getNode()); - if (Node->getMemoryVT() == MVT::i128) { - // Use same code to handle both legal and non-legal i128 types. - SmallVector<SDValue, 2> Results; - LowerOperationWrapper(Node, Results, DAG); - return DAG.getMergeValues(Results, SDLoc(Op)); - } - return DAG.getExtLoad(ISD::EXTLOAD, SDLoc(Op), Op.getValueType(), - Node->getChain(), Node->getBasePtr(), - Node->getMemoryVT(), Node->getMemOperand()); -} - -// Op is an atomic store. Lower it into a normal volatile store. -SDValue SystemZTargetLowering::lowerATOMIC_STORE(SDValue Op, - SelectionDAG &DAG) const { +SDValue SystemZTargetLowering::lowerATOMIC_LDST_I128(SDValue Op, + SelectionDAG &DAG) const { auto *Node = cast<AtomicSDNode>(Op.getNode()); - if (Node->getMemoryVT() == MVT::i128) { - // Use same code to handle both legal and non-legal i128 types. - SmallVector<SDValue, 1> Results; - LowerOperationWrapper(Node, Results, DAG); - return DAG.getMergeValues(Results, SDLoc(Op)); - } - SDValue Chain = DAG.getTruncStore(Node->getChain(), SDLoc(Op), Node->getVal(), - Node->getBasePtr(), Node->getMemoryVT(), - Node->getMemOperand()); - // We have to enforce sequential consistency by performing a - // serialization operation after the store. - if (Node->getSuccessOrdering() == AtomicOrdering::SequentiallyConsistent) - Chain = SDValue(DAG.getMachineNode(SystemZ::Serialize, SDLoc(Op), - MVT::Other, Chain), 0); - return Chain; + assert(Node->getMemoryVT() == MVT::i128 && "Only custom lowering i128."); + // Use same code to handle both legal and non-legal i128 types. + SmallVector<SDValue, 2> Results; + LowerOperationWrapper(Node, Results, DAG); + return DAG.getMergeValues(Results, SDLoc(Op)); } // Prepare for a Compare And Swap for a subword operation. This needs to be @@ -5662,6 +5672,9 @@ static SDValue tryBuildVectorShuffle(SelectionDAG &DAG, bool SystemZTargetLowering::isVectorElementLoad(SDValue Op) const { if (Op.getOpcode() == ISD::LOAD && cast<LoadSDNode>(Op)->isUnindexed()) return true; + if (auto *AL = dyn_cast<AtomicSDNode>(Op)) + if (AL->getOpcode() == ISD::ATOMIC_LOAD) + return true; if (Subtarget.hasVectorEnhancements2() && Op.getOpcode() == SystemZISD::LRV) return true; return false; @@ -6076,6 +6089,27 @@ SDValue SystemZTargetLowering::lowerIS_FPCLASS(SDValue Op, return getCCResult(DAG, Intr); } +SDValue SystemZTargetLowering::lowerREADCYCLECOUNTER(SDValue Op, + SelectionDAG &DAG) const { + SDLoc DL(Op); + SDValue Chain = Op.getOperand(0); + + // STCKF only supports a memory operand, so we have to use a temporary. + SDValue StackPtr = DAG.CreateStackTemporary(MVT::i64); + int SPFI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex(); + MachinePointerInfo MPI = + MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), SPFI); + + // Use STCFK to store the TOD clock into the temporary. + SDValue StoreOps[] = {Chain, StackPtr}; + Chain = DAG.getMemIntrinsicNode( + SystemZISD::STCKF, DL, DAG.getVTList(MVT::Other), StoreOps, MVT::i64, + MPI, MaybeAlign(), MachineMemOperand::MOStore); + + // And read it back from there. + return DAG.getLoad(MVT::i64, DL, Chain, StackPtr, MPI); +} + SDValue SystemZTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { @@ -6138,9 +6172,8 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op, case ISD::ATOMIC_SWAP: return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_SWAPW); case ISD::ATOMIC_STORE: - return lowerATOMIC_STORE(Op, DAG); case ISD::ATOMIC_LOAD: - return lowerATOMIC_LOAD(Op, DAG); + return lowerATOMIC_LDST_I128(Op, DAG); case ISD::ATOMIC_LOAD_ADD: return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_LOADW_ADD); case ISD::ATOMIC_LOAD_SUB: @@ -6199,6 +6232,8 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op, return lowerIS_FPCLASS(Op, DAG); case ISD::GET_ROUNDING: return lowerGET_ROUNDING(Op, DAG); + case ISD::READCYCLECOUNTER: + return lowerREADCYCLECOUNTER(Op, DAG); default: llvm_unreachable("Unexpected node to lower"); } @@ -6425,6 +6460,7 @@ const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const { OPCODE(STRV); OPCODE(VLER); OPCODE(VSTER); + OPCODE(STCKF); OPCODE(PREFETCH); OPCODE(ADA_ENTRY); } @@ -6611,6 +6647,28 @@ SDValue SystemZTargetLowering::combineZERO_EXTEND( return NewSelect; } } + // Convert (zext (xor (trunc X), C)) into (xor (trunc X), C') if the size + // of the result is smaller than the size of X and all the truncated bits + // of X are already zero. + if (N0.getOpcode() == ISD::XOR && + N0.hasOneUse() && N0.getOperand(0).hasOneUse() && + N0.getOperand(0).getOpcode() == ISD::TRUNCATE && + N0.getOperand(1).getOpcode() == ISD::Constant) { + SDValue X = N0.getOperand(0).getOperand(0); + if (VT.isScalarInteger() && VT.getSizeInBits() < X.getValueSizeInBits()) { + KnownBits Known = DAG.computeKnownBits(X); + APInt TruncatedBits = APInt::getBitsSet(X.getValueSizeInBits(), + N0.getValueSizeInBits(), + VT.getSizeInBits()); + if (TruncatedBits.isSubsetOf(Known.Zero)) { + X = DAG.getNode(ISD::TRUNCATE, SDLoc(X), VT, X); + APInt Mask = N0.getConstantOperandAPInt(1).zext(VT.getSizeInBits()); + return DAG.getNode(ISD::XOR, SDLoc(N0), VT, + X, DAG.getConstant(Mask, SDLoc(N0), VT)); + } + } + } + return SDValue(); } @@ -6662,6 +6720,7 @@ SDValue SystemZTargetLowering::combineSIGN_EXTEND( } } } + return SDValue(); } @@ -6929,6 +6988,17 @@ SDValue SystemZTargetLowering::combineSTORE( } } + // Combine STORE (READCYCLECOUNTER) into STCKF. + if (!SN->isTruncatingStore() && + Op1.getOpcode() == ISD::READCYCLECOUNTER && + Op1.hasOneUse() && + N->getOperand(0).reachesChainWithoutSideEffects(SDValue(Op1.getNode(), 1))) { + SDValue Ops[] = { Op1.getOperand(0), N->getOperand(2) }; + return DAG.getMemIntrinsicNode(SystemZISD::STCKF, SDLoc(N), + DAG.getVTList(MVT::Other), + Ops, MemVT, SN->getMemOperand()); + } + // Transform a store of an i128 moved from GPRs into two separate stores. if (MemVT == MVT::i128 && SN->isSimple() && ISD::isNormalStore(SN)) { SDValue LoPart, HiPart; @@ -8103,6 +8173,27 @@ static void createPHIsForSelects(SmallVector<MachineInstr*, 8> &Selects, MF->getProperties().reset(MachineFunctionProperties::Property::NoPHIs); } +MachineBasicBlock * +SystemZTargetLowering::emitAdjCallStack(MachineInstr &MI, + MachineBasicBlock *BB) const { + MachineFunction &MF = *BB->getParent(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + auto *TFL = Subtarget.getFrameLowering<SystemZFrameLowering>(); + assert(TFL->hasReservedCallFrame(MF) && + "ADJSTACKDOWN and ADJSTACKUP should be no-ops"); + (void)TFL; + // Get the MaxCallFrameSize value and erase MI since it serves no further + // purpose as the call frame is statically reserved in the prolog. Set + // AdjustsStack as MI is *not* mapped as a frame instruction. + uint32_t NumBytes = MI.getOperand(0).getImm(); + if (NumBytes > MFI.getMaxCallFrameSize()) + MFI.setMaxCallFrameSize(NumBytes); + MFI.setAdjustsStack(true); + + MI.eraseFromParent(); + return BB; +} + // Implement EmitInstrWithCustomInserter for pseudo Select* instruction MI. MachineBasicBlock * SystemZTargetLowering::emitSelect(MachineInstr &MI, @@ -9306,6 +9397,10 @@ getBackchainAddress(SDValue SP, SelectionDAG &DAG) const { MachineBasicBlock *SystemZTargetLowering::EmitInstrWithCustomInserter( MachineInstr &MI, MachineBasicBlock *MBB) const { switch (MI.getOpcode()) { + case SystemZ::ADJCALLSTACKDOWN: + case SystemZ::ADJCALLSTACKUP: + return emitAdjCallStack(MI, MBB); + case SystemZ::Select32: case SystemZ::Select64: case SystemZ::Select128: diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h index baf4ba4165487948ea36f422c34ba8c54872a551..7140287a886ccfd8e6156ebf668ab42fd62e2d83 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h @@ -378,6 +378,9 @@ enum NodeType : unsigned { // Element swapping load/store. Same operands as regular load/store. VLER, VSTER, + // Use STORE CLOCK FAST to store current TOD clock value. + STCKF, + // Prefetch from the second operand using the 4-bit control code in // the first operand. The code is 1 for a load prefetch and 2 for // a store prefetch. @@ -474,6 +477,8 @@ public: return VT != MVT::f64; } bool hasInlineStackProbe(const MachineFunction &MF) const override; + AtomicExpansionKind shouldCastAtomicLoadInIR(LoadInst *LI) const override; + AtomicExpansionKind shouldCastAtomicStoreInIR(StoreInst *SI) const override; AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const override; bool isLegalICmpImmediate(int64_t Imm) const override; @@ -692,8 +697,7 @@ private: SDValue lowerOR(SDValue Op, SelectionDAG &DAG) const; SDValue lowerCTPOP(SDValue Op, SelectionDAG &DAG) const; SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerATOMIC_LOAD(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerATOMIC_LDST_I128(SDValue Op, SelectionDAG &DAG) const; SDValue lowerATOMIC_LOAD_OP(SDValue Op, SelectionDAG &DAG, unsigned Opcode) const; SDValue lowerATOMIC_LOAD_SUB(SDValue Op, SelectionDAG &DAG) const; @@ -716,6 +720,7 @@ private: SDValue lowerShift(SDValue Op, SelectionDAG &DAG, unsigned ByScalar) const; SDValue lowerIS_FPCLASS(SDValue Op, SelectionDAG &DAG) const; SDValue lowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG) const; bool canTreatAsByteVector(EVT VT) const; SDValue combineExtract(const SDLoc &DL, EVT ElemVT, EVT VecVT, SDValue OrigOp, @@ -755,6 +760,8 @@ private: MachineBasicBlock *Target) const; // Implement EmitInstrWithCustomInserter for individual operation types. + MachineBasicBlock *emitAdjCallStack(MachineInstr &MI, + MachineBasicBlock *BB) const; MachineBasicBlock *emitSelect(MachineInstr &MI, MachineBasicBlock *BB) const; MachineBasicBlock *emitCondStore(MachineInstr &MI, MachineBasicBlock *BB, unsigned StoreOpcode, unsigned STOCOpcode, diff --git a/llvm/lib/Target/SystemZ/SystemZInstrFP.td b/llvm/lib/Target/SystemZ/SystemZInstrFP.td index 6e67425c1e788b42140840b84d910526eb3f21b8..f4b5aeaebef9230491e12fa02899da20a57de45b 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrFP.td +++ b/llvm/lib/Target/SystemZ/SystemZInstrFP.td @@ -129,8 +129,8 @@ defm LoadStoreF128 : MVCLoadStore<load, f128, MVCImm, 15>; //===----------------------------------------------------------------------===// let canFoldAsLoad = 1, SimpleBDXLoad = 1, mayLoad = 1 in { - defm LE : UnaryRXPair<"le", 0x78, 0xED64, load, FP32, 4>; - defm LD : UnaryRXPair<"ld", 0x68, 0xED65, load, FP64, 8>; + defm LE : UnaryRXPair<"le", 0x78, 0xED64, z_load, FP32, 4>; + defm LD : UnaryRXPair<"ld", 0x68, 0xED65, z_load, FP64, 8>; // For z13 we prefer LDE over LE to avoid partial register dependencies. let isCodeGenOnly = 1 in @@ -200,14 +200,14 @@ let Predicates = [FeatureNoVectorEnhancements1] in { // Extend memory floating-point values to wider representations. let Uses = [FPC], mayRaiseFPException = 1 in { - def LDEB : UnaryRXE<"ldeb", 0xED04, any_extloadf32, FP64, 4>; + def LDEB : UnaryRXE<"ldeb", 0xED04, z_any_extloadf32, FP64, 4>; def LXEB : UnaryRXE<"lxeb", 0xED06, null_frag, FP128, 4>; def LXDB : UnaryRXE<"lxdb", 0xED05, null_frag, FP128, 8>; } let Predicates = [FeatureNoVectorEnhancements1] in { - def : Pat<(f128 (any_extloadf32 bdxaddr12only:$src)), + def : Pat<(f128 (z_any_extloadf32 bdxaddr12only:$src)), (LXEB bdxaddr12only:$src)>; - def : Pat<(f128 (any_extloadf64 bdxaddr12only:$src)), + def : Pat<(f128 (z_any_extloadf64 bdxaddr12only:$src)), (LXDB bdxaddr12only:$src)>; } @@ -430,8 +430,8 @@ let Uses = [FPC], mayRaiseFPException = 1, def ADBR : BinaryRRE<"adbr", 0xB31A, any_fadd, FP64, FP64>; def AXBR : BinaryRRE<"axbr", 0xB34A, any_fadd, FP128, FP128>; } - defm AEB : BinaryRXEAndPseudo<"aeb", 0xED0A, any_fadd, FP32, load, 4>; - defm ADB : BinaryRXEAndPseudo<"adb", 0xED1A, any_fadd, FP64, load, 8>; + defm AEB : BinaryRXEAndPseudo<"aeb", 0xED0A, any_fadd, FP32, z_load, 4>; + defm ADB : BinaryRXEAndPseudo<"adb", 0xED1A, any_fadd, FP64, z_load, 8>; } // Subtraction. @@ -441,8 +441,8 @@ let Uses = [FPC], mayRaiseFPException = 1, def SDBR : BinaryRRE<"sdbr", 0xB31B, any_fsub, FP64, FP64>; def SXBR : BinaryRRE<"sxbr", 0xB34B, any_fsub, FP128, FP128>; - defm SEB : BinaryRXEAndPseudo<"seb", 0xED0B, any_fsub, FP32, load, 4>; - defm SDB : BinaryRXEAndPseudo<"sdb", 0xED1B, any_fsub, FP64, load, 8>; + defm SEB : BinaryRXEAndPseudo<"seb", 0xED0B, any_fsub, FP32, z_load, 4>; + defm SDB : BinaryRXEAndPseudo<"sdb", 0xED1B, any_fsub, FP64, z_load, 8>; } // Multiplication. @@ -452,8 +452,8 @@ let Uses = [FPC], mayRaiseFPException = 1 in { def MDBR : BinaryRRE<"mdbr", 0xB31C, any_fmul, FP64, FP64>; def MXBR : BinaryRRE<"mxbr", 0xB34C, any_fmul, FP128, FP128>; } - defm MEEB : BinaryRXEAndPseudo<"meeb", 0xED17, any_fmul, FP32, load, 4>; - defm MDB : BinaryRXEAndPseudo<"mdb", 0xED1C, any_fmul, FP64, load, 8>; + defm MEEB : BinaryRXEAndPseudo<"meeb", 0xED17, any_fmul, FP32, z_load, 4>; + defm MDB : BinaryRXEAndPseudo<"mdb", 0xED1C, any_fmul, FP64, z_load, 8>; } // f64 multiplication of two FP32 registers. @@ -466,7 +466,7 @@ def : Pat<(any_fmul (f64 (any_fpextend FP32:$src1)), // f64 multiplication of an FP32 register and an f32 memory. let Uses = [FPC], mayRaiseFPException = 1 in - def MDEB : BinaryRXE<"mdeb", 0xED0C, null_frag, FP64, load, 4>; + def MDEB : BinaryRXE<"mdeb", 0xED0C, null_frag, FP64, z_load, 4>; def : Pat<(any_fmul (f64 (any_fpextend FP32:$src1)), (f64 (any_extloadf32 bdxaddr12only:$addr))), (MDEB (INSERT_SUBREG (f64 (IMPLICIT_DEF)), FP32:$src1, subreg_h32), @@ -483,7 +483,7 @@ let Predicates = [FeatureNoVectorEnhancements1] in // f128 multiplication of an FP64 register and an f64 memory. let Uses = [FPC], mayRaiseFPException = 1 in - def MXDB : BinaryRXE<"mxdb", 0xED07, null_frag, FP128, load, 8>; + def MXDB : BinaryRXE<"mxdb", 0xED07, null_frag, FP128, z_load, 8>; let Predicates = [FeatureNoVectorEnhancements1] in def : Pat<(any_fmul (f128 (any_fpextend FP64:$src1)), (f128 (any_extloadf64 bdxaddr12only:$addr))), @@ -495,8 +495,8 @@ let Uses = [FPC], mayRaiseFPException = 1 in { def MAEBR : TernaryRRD<"maebr", 0xB30E, z_any_fma, FP32, FP32>; def MADBR : TernaryRRD<"madbr", 0xB31E, z_any_fma, FP64, FP64>; - defm MAEB : TernaryRXFAndPseudo<"maeb", 0xED0E, z_any_fma, FP32, FP32, load, 4>; - defm MADB : TernaryRXFAndPseudo<"madb", 0xED1E, z_any_fma, FP64, FP64, load, 8>; + defm MAEB : TernaryRXFAndPseudo<"maeb", 0xED0E, z_any_fma, FP32, FP32, z_load, 4>; + defm MADB : TernaryRXFAndPseudo<"madb", 0xED1E, z_any_fma, FP64, FP64, z_load, 8>; } // Fused multiply-subtract. @@ -504,8 +504,8 @@ let Uses = [FPC], mayRaiseFPException = 1 in { def MSEBR : TernaryRRD<"msebr", 0xB30F, z_any_fms, FP32, FP32>; def MSDBR : TernaryRRD<"msdbr", 0xB31F, z_any_fms, FP64, FP64>; - defm MSEB : TernaryRXFAndPseudo<"mseb", 0xED0F, z_any_fms, FP32, FP32, load, 4>; - defm MSDB : TernaryRXFAndPseudo<"msdb", 0xED1F, z_any_fms, FP64, FP64, load, 8>; + defm MSEB : TernaryRXFAndPseudo<"mseb", 0xED0F, z_any_fms, FP32, FP32, z_load, 4>; + defm MSDB : TernaryRXFAndPseudo<"msdb", 0xED1F, z_any_fms, FP64, FP64, z_load, 8>; } // Division. @@ -514,8 +514,8 @@ let Uses = [FPC], mayRaiseFPException = 1 in { def DDBR : BinaryRRE<"ddbr", 0xB31D, any_fdiv, FP64, FP64>; def DXBR : BinaryRRE<"dxbr", 0xB34D, any_fdiv, FP128, FP128>; - defm DEB : BinaryRXEAndPseudo<"deb", 0xED0D, any_fdiv, FP32, load, 4>; - defm DDB : BinaryRXEAndPseudo<"ddb", 0xED1D, any_fdiv, FP64, load, 8>; + defm DEB : BinaryRXEAndPseudo<"deb", 0xED0D, any_fdiv, FP32, z_load, 4>; + defm DDB : BinaryRXEAndPseudo<"ddb", 0xED1D, any_fdiv, FP64, z_load, 8>; } // Divide to integer. @@ -533,15 +533,15 @@ let Uses = [FPC], mayRaiseFPException = 1, Defs = [CC], CCValues = 0xF in { def CDBR : CompareRRE<"cdbr", 0xB319, z_any_fcmp, FP64, FP64>; def CXBR : CompareRRE<"cxbr", 0xB349, z_any_fcmp, FP128, FP128>; - def CEB : CompareRXE<"ceb", 0xED09, z_any_fcmp, FP32, load, 4>; - def CDB : CompareRXE<"cdb", 0xED19, z_any_fcmp, FP64, load, 8>; + def CEB : CompareRXE<"ceb", 0xED09, z_any_fcmp, FP32, z_load, 4>; + def CDB : CompareRXE<"cdb", 0xED19, z_any_fcmp, FP64, z_load, 8>; def KEBR : CompareRRE<"kebr", 0xB308, z_strict_fcmps, FP32, FP32>; def KDBR : CompareRRE<"kdbr", 0xB318, z_strict_fcmps, FP64, FP64>; def KXBR : CompareRRE<"kxbr", 0xB348, z_strict_fcmps, FP128, FP128>; - def KEB : CompareRXE<"keb", 0xED08, z_strict_fcmps, FP32, load, 4>; - def KDB : CompareRXE<"kdb", 0xED18, z_strict_fcmps, FP64, load, 8>; + def KEB : CompareRXE<"keb", 0xED08, z_strict_fcmps, FP32, z_load, 4>; + def KDB : CompareRXE<"kdb", 0xED18, z_strict_fcmps, FP64, z_load, 8>; } // Test Data Class. diff --git a/llvm/lib/Target/SystemZ/SystemZInstrFormats.td b/llvm/lib/Target/SystemZ/SystemZInstrFormats.td index bb9fa0fc33ffa0e1cabb44e4b4533be986afe7bd..3dba33b66bf4f462d7a65d6744fee87383228470 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrFormats.td +++ b/llvm/lib/Target/SystemZ/SystemZInstrFormats.td @@ -3777,7 +3777,7 @@ class BinarySI<string mnemonic, bits<8> opcode, SDPatternOperator operator, Operand imm, AddressingMode mode = bdaddr12only> : InstSI<opcode, (outs), (ins (mode $B1, $D1):$BD1, imm:$I2), mnemonic#"\t$BD1, $I2", - [(store (operator (load mode:$BD1), imm:$I2), mode:$BD1)]> { + [(store (operator (z_load mode:$BD1), imm:$I2), mode:$BD1)]> { let mayLoad = 1; let mayStore = 1; } @@ -3786,7 +3786,7 @@ class BinarySIY<string mnemonic, bits<16> opcode, SDPatternOperator operator, Operand imm, AddressingMode mode = bdaddr20only> : InstSIY<opcode, (outs), (ins (mode $B1, $D1):$BD1, imm:$I2), mnemonic#"\t$BD1, $I2", - [(store (operator (load mode:$BD1), imm:$I2), mode:$BD1)]> { + [(store (operator (z_load mode:$BD1), imm:$I2), mode:$BD1)]> { let mayLoad = 1; let mayStore = 1; } diff --git a/llvm/lib/Target/SystemZ/SystemZInstrHFP.td b/llvm/lib/Target/SystemZ/SystemZInstrHFP.td index 2e3c9932d621426d53e32fb2a38aebd8affaf785..d2e05b63c6c630fb4e10a05db2893e78021118c9 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrHFP.td +++ b/llvm/lib/Target/SystemZ/SystemZInstrHFP.td @@ -134,8 +134,8 @@ let Defs = [CC] in { def ADR : BinaryRR<"adr", 0x2A, null_frag, FP64, FP64>; def AXR : BinaryRR<"axr", 0x36, null_frag, FP128, FP128>; } - def AE : BinaryRX<"ae", 0x7A, null_frag, FP32, load, 4>; - def AD : BinaryRX<"ad", 0x6A, null_frag, FP64, load, 8>; + def AE : BinaryRX<"ae", 0x7A, null_frag, FP32, z_load, 4>; + def AD : BinaryRX<"ad", 0x6A, null_frag, FP64, z_load, 8>; } // Addition (unnormalized). @@ -144,8 +144,8 @@ let Defs = [CC] in { def AUR : BinaryRR<"aur", 0x3E, null_frag, FP32, FP32>; def AWR : BinaryRR<"awr", 0x2E, null_frag, FP64, FP64>; } - def AU : BinaryRX<"au", 0x7E, null_frag, FP32, load, 4>; - def AW : BinaryRX<"aw", 0x6E, null_frag, FP64, load, 8>; + def AU : BinaryRX<"au", 0x7E, null_frag, FP32, z_load, 4>; + def AW : BinaryRX<"aw", 0x6E, null_frag, FP64, z_load, 8>; } // Subtraction. @@ -154,8 +154,8 @@ let Defs = [CC] in { def SDR : BinaryRR<"sdr", 0x2B, null_frag, FP64, FP64>; def SXR : BinaryRR<"sxr", 0x37, null_frag, FP128, FP128>; - def SE : BinaryRX<"se", 0x7B, null_frag, FP32, load, 4>; - def SD : BinaryRX<"sd", 0x6B, null_frag, FP64, load, 8>; + def SE : BinaryRX<"se", 0x7B, null_frag, FP32, z_load, 4>; + def SD : BinaryRX<"sd", 0x6B, null_frag, FP64, z_load, 8>; } // Subtraction (unnormalized). @@ -163,8 +163,8 @@ let Defs = [CC] in { def SUR : BinaryRR<"sur", 0x3F, null_frag, FP32, FP32>; def SWR : BinaryRR<"swr", 0x2F, null_frag, FP64, FP64>; - def SU : BinaryRX<"su", 0x7F, null_frag, FP32, load, 4>; - def SW : BinaryRX<"sw", 0x6F, null_frag, FP64, load, 8>; + def SU : BinaryRX<"su", 0x7F, null_frag, FP32, z_load, 4>; + def SW : BinaryRX<"sw", 0x6F, null_frag, FP64, z_load, 8>; } // Multiplication. @@ -173,55 +173,55 @@ let isCommutable = 1 in { def MDR : BinaryRR <"mdr", 0x2C, null_frag, FP64, FP64>; def MXR : BinaryRR <"mxr", 0x26, null_frag, FP128, FP128>; } -def MEE : BinaryRXE<"mee", 0xED37, null_frag, FP32, load, 4>; -def MD : BinaryRX <"md", 0x6C, null_frag, FP64, load, 8>; +def MEE : BinaryRXE<"mee", 0xED37, null_frag, FP32, z_load, 4>; +def MD : BinaryRX <"md", 0x6C, null_frag, FP64, z_load, 8>; // Extending multiplication (f32 x f32 -> f64). def MDER : BinaryRR<"mder", 0x3C, null_frag, FP64, FP32>; -def MDE : BinaryRX<"mde", 0x7C, null_frag, FP64, load, 4>; +def MDE : BinaryRX<"mde", 0x7C, null_frag, FP64, z_load, 4>; let isAsmParserOnly = 1 in { def MER : BinaryRR<"mer", 0x3C, null_frag, FP64, FP32>; - def ME : BinaryRX<"me", 0x7C, null_frag, FP64, load, 4>; + def ME : BinaryRX<"me", 0x7C, null_frag, FP64, z_load, 4>; } // Extending multiplication (f64 x f64 -> f128). def MXDR : BinaryRR<"mxdr", 0x27, null_frag, FP128, FP64>; -def MXD : BinaryRX<"mxd", 0x67, null_frag, FP128, load, 8>; +def MXD : BinaryRX<"mxd", 0x67, null_frag, FP128, z_load, 8>; // Fused multiply-add. def MAER : TernaryRRD<"maer", 0xB32E, null_frag, FP32, FP32>; def MADR : TernaryRRD<"madr", 0xB33E, null_frag, FP64, FP64>; -def MAE : TernaryRXF<"mae", 0xED2E, null_frag, FP32, FP32, load, 4>; -def MAD : TernaryRXF<"mad", 0xED3E, null_frag, FP64, FP64, load, 8>; +def MAE : TernaryRXF<"mae", 0xED2E, null_frag, FP32, FP32, z_load, 4>; +def MAD : TernaryRXF<"mad", 0xED3E, null_frag, FP64, FP64, z_load, 8>; // Fused multiply-subtract. def MSER : TernaryRRD<"mser", 0xB32F, null_frag, FP32, FP32>; def MSDR : TernaryRRD<"msdr", 0xB33F, null_frag, FP64, FP64>; -def MSE : TernaryRXF<"mse", 0xED2F, null_frag, FP32, FP32, load, 4>; -def MSD : TernaryRXF<"msd", 0xED3F, null_frag, FP64, FP64, load, 8>; +def MSE : TernaryRXF<"mse", 0xED2F, null_frag, FP32, FP32, z_load, 4>; +def MSD : TernaryRXF<"msd", 0xED3F, null_frag, FP64, FP64, z_load, 8>; // Multiplication (unnormalized). def MYR : BinaryRRD<"myr", 0xB33B, null_frag, FP128, FP64>; def MYHR : BinaryRRD<"myhr", 0xB33D, null_frag, FP64, FP64>; def MYLR : BinaryRRD<"mylr", 0xB339, null_frag, FP64, FP64>; -def MY : BinaryRXF<"my", 0xED3B, null_frag, FP128, FP64, load, 8>; -def MYH : BinaryRXF<"myh", 0xED3D, null_frag, FP64, FP64, load, 8>; -def MYL : BinaryRXF<"myl", 0xED39, null_frag, FP64, FP64, load, 8>; +def MY : BinaryRXF<"my", 0xED3B, null_frag, FP128, FP64, z_load, 8>; +def MYH : BinaryRXF<"myh", 0xED3D, null_frag, FP64, FP64, z_load, 8>; +def MYL : BinaryRXF<"myl", 0xED39, null_frag, FP64, FP64, z_load, 8>; // Fused multiply-add (unnormalized). def MAYR : TernaryRRD<"mayr", 0xB33A, null_frag, FP128, FP64>; def MAYHR : TernaryRRD<"mayhr", 0xB33C, null_frag, FP64, FP64>; def MAYLR : TernaryRRD<"maylr", 0xB338, null_frag, FP64, FP64>; -def MAY : TernaryRXF<"may", 0xED3A, null_frag, FP128, FP64, load, 8>; -def MAYH : TernaryRXF<"mayh", 0xED3C, null_frag, FP64, FP64, load, 8>; -def MAYL : TernaryRXF<"mayl", 0xED38, null_frag, FP64, FP64, load, 8>; +def MAY : TernaryRXF<"may", 0xED3A, null_frag, FP128, FP64, z_load, 8>; +def MAYH : TernaryRXF<"mayh", 0xED3C, null_frag, FP64, FP64, z_load, 8>; +def MAYL : TernaryRXF<"mayl", 0xED38, null_frag, FP64, FP64, z_load, 8>; // Division. def DER : BinaryRR <"der", 0x3D, null_frag, FP32, FP32>; def DDR : BinaryRR <"ddr", 0x2D, null_frag, FP64, FP64>; def DXR : BinaryRRE<"dxr", 0xB22D, null_frag, FP128, FP128>; -def DE : BinaryRX <"de", 0x7D, null_frag, FP32, load, 4>; -def DD : BinaryRX <"dd", 0x6D, null_frag, FP64, load, 8>; +def DE : BinaryRX <"de", 0x7D, null_frag, FP32, z_load, 4>; +def DD : BinaryRX <"dd", 0x6D, null_frag, FP64, z_load, 8>; //===----------------------------------------------------------------------===// @@ -233,7 +233,7 @@ let Defs = [CC] in { def CDR : CompareRR <"cdr", 0x29, null_frag, FP64, FP64>; def CXR : CompareRRE<"cxr", 0xB369, null_frag, FP128, FP128>; - def CE : CompareRX<"ce", 0x79, null_frag, FP32, load, 4>; - def CD : CompareRX<"cd", 0x69, null_frag, FP64, load, 8>; + def CE : CompareRX<"ce", 0x79, null_frag, FP32, z_load, 4>; + def CD : CompareRX<"cd", 0x69, null_frag, FP64, z_load, 8>; } diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp index 53e9bf9a9d1bb01112a6a25136e3c182da08d7b3..950548abcfa92c62200adbcb7dce2134453a8f97 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -59,7 +59,7 @@ static uint64_t allOnes(unsigned int Count) { void SystemZInstrInfo::anchor() {} SystemZInstrInfo::SystemZInstrInfo(SystemZSubtarget &sti) - : SystemZGenInstrInfo(SystemZ::ADJCALLSTACKDOWN, SystemZ::ADJCALLSTACKUP), + : SystemZGenInstrInfo(-1, -1), RI(sti.getSpecialRegisters()->getReturnFunctionAddressRegister()), STI(sti) {} @@ -2020,11 +2020,12 @@ areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, } if (SameVal) { int OffsetA = MMOa->getOffset(), OffsetB = MMOb->getOffset(); - int WidthA = MMOa->getSize(), WidthB = MMOb->getSize(); + LocationSize WidthA = MMOa->getSize(), WidthB = MMOb->getSize(); int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB; int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA; - int LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB; - if (LowOffset + LowWidth <= HighOffset) + LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB; + if (LowWidth.hasValue() && + LowOffset + (int)LowWidth.getValue() <= HighOffset) return true; } diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td index 937e36057a6ede7cea3edfd0164a36244241d1a9..7f3a143aad970959f85ab1c594cb3851f49d5bbb 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td @@ -13,9 +13,9 @@ def IsTargetELF : Predicate<"Subtarget->isTargetELF()">; // Stack allocation //===----------------------------------------------------------------------===// -// The callseq_start node requires the hasSideEffects flag, even though these -// instructions are noops on SystemZ. -let hasNoSchedulingInfo = 1, hasSideEffects = 1 in { +// These pseudos carry values needed to compute the MaxcallFrameSize of the +// function. The callseq_start node requires the hasSideEffects flag. +let usesCustomInserter = 1, hasNoSchedulingInfo = 1, hasSideEffects = 1 in { def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2), [(callseq_start timm:$amt1, timm:$amt2)]>; def ADJCALLSTACKUP : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2), @@ -306,7 +306,7 @@ let Predicates = [IsTargetXPLINK64] in { let mayLoad = 1, AddedComplexity = 20, hasNoSchedulingInfo = 1, Defs = [CC] in { def ADA_ENTRY_VALUE : Alias<12, (outs GR64:$Reg), (ins adasym:$addr, ADDR64:$ADA, imm64:$Offset), - [(set i64:$Reg, (load (z_ada_entry + [(set i64:$Reg, (z_load (z_ada_entry iPTR:$addr, iPTR:$ADA, i64:$Offset)))]>; } } @@ -468,12 +468,12 @@ let isAsCheapAsAMove = 1, isMoveImm = 1, isReMaterializable = 1 in { // Register loads. let canFoldAsLoad = 1, SimpleBDXLoad = 1, mayLoad = 1 in { // Expands to L, LY or LFH, depending on the choice of register. - def LMux : UnaryRXYPseudo<"l", load, GRX32, 4>, + def LMux : UnaryRXYPseudo<"l", z_load, GRX32, 4>, Requires<[FeatureHighWord]>; - defm L : UnaryRXPair<"l", 0x58, 0xE358, load, GR32, 4>; - def LFH : UnaryRXY<"lfh", 0xE3CA, load, GRH32, 4>, + defm L : UnaryRXPair<"l", 0x58, 0xE358, z_load, GR32, 4>; + def LFH : UnaryRXY<"lfh", 0xE3CA, z_load, GRH32, 4>, Requires<[FeatureHighWord]>; - def LG : UnaryRXY<"lg", 0xE304, load, GR64, 8>; + def LG : UnaryRXY<"lg", 0xE304, z_load, GR64, 8>; // These instructions are split after register allocation, so we don't // want a custom inserter. @@ -483,22 +483,22 @@ let canFoldAsLoad = 1, SimpleBDXLoad = 1, mayLoad = 1 in { } } let Defs = [CC], CCValues = 0xE, CompareZeroCCMask = 0xE in { - def LT : UnaryRXY<"lt", 0xE312, load, GR32, 4>; - def LTG : UnaryRXY<"ltg", 0xE302, load, GR64, 8>; + def LT : UnaryRXY<"lt", 0xE312, z_load, GR32, 4>; + def LTG : UnaryRXY<"ltg", 0xE302, z_load, GR64, 8>; } let canFoldAsLoad = 1 in { - def LRL : UnaryRILPC<"lrl", 0xC4D, aligned_load, GR32>; - def LGRL : UnaryRILPC<"lgrl", 0xC48, aligned_load, GR64>; + def LRL : UnaryRILPC<"lrl", 0xC4D, aligned_z_load, GR32>; + def LGRL : UnaryRILPC<"lgrl", 0xC48, aligned_z_load, GR64>; } // Load and zero rightmost byte. let Predicates = [FeatureLoadAndZeroRightmostByte] in { def LZRF : UnaryRXY<"lzrf", 0xE33B, null_frag, GR32, 4>; def LZRG : UnaryRXY<"lzrg", 0xE32A, null_frag, GR64, 8>; - def : Pat<(and (i32 (load bdxaddr20only:$src)), 0xffffff00), + def : Pat<(and (i32 (z_load bdxaddr20only:$src)), 0xffffff00), (LZRF bdxaddr20only:$src)>; - def : Pat<(and (i64 (load bdxaddr20only:$src)), 0xffffffffffffff00), + def : Pat<(and (i64 (z_load bdxaddr20only:$src)), 0xffffffffffffff00), (LZRG bdxaddr20only:$src)>; } @@ -689,29 +689,29 @@ def : Pat<(sext_inreg GR64:$src, i32), // 32-bit extensions from 8-bit memory. LBMux expands to LB or LBH, // depending on the choice of register. -def LBMux : UnaryRXYPseudo<"lb", asextloadi8, GRX32, 1>, +def LBMux : UnaryRXYPseudo<"lb", z_asextloadi8, GRX32, 1>, Requires<[FeatureHighWord]>; -def LB : UnaryRXY<"lb", 0xE376, asextloadi8, GR32, 1>; -def LBH : UnaryRXY<"lbh", 0xE3C0, asextloadi8, GRH32, 1>, +def LB : UnaryRXY<"lb", 0xE376, z_asextloadi8, GR32, 1>; +def LBH : UnaryRXY<"lbh", 0xE3C0, z_asextloadi8, GRH32, 1>, Requires<[FeatureHighWord]>; // 32-bit extensions from 16-bit memory. LHMux expands to LH or LHH, // depending on the choice of register. -def LHMux : UnaryRXYPseudo<"lh", asextloadi16, GRX32, 2>, +def LHMux : UnaryRXYPseudo<"lh", z_asextloadi16, GRX32, 2>, Requires<[FeatureHighWord]>; -defm LH : UnaryRXPair<"lh", 0x48, 0xE378, asextloadi16, GR32, 2>; -def LHH : UnaryRXY<"lhh", 0xE3C4, asextloadi16, GRH32, 2>, +defm LH : UnaryRXPair<"lh", 0x48, 0xE378, z_asextloadi16, GR32, 2>; +def LHH : UnaryRXY<"lhh", 0xE3C4, z_asextloadi16, GRH32, 2>, Requires<[FeatureHighWord]>; -def LHRL : UnaryRILPC<"lhrl", 0xC45, aligned_asextloadi16, GR32>; +def LHRL : UnaryRILPC<"lhrl", 0xC45, aligned_z_asextloadi16, GR32>; // 64-bit extensions from memory. -def LGB : UnaryRXY<"lgb", 0xE377, asextloadi8, GR64, 1>; -def LGH : UnaryRXY<"lgh", 0xE315, asextloadi16, GR64, 2>; -def LGF : UnaryRXY<"lgf", 0xE314, asextloadi32, GR64, 4>; -def LGHRL : UnaryRILPC<"lghrl", 0xC44, aligned_asextloadi16, GR64>; -def LGFRL : UnaryRILPC<"lgfrl", 0xC4C, aligned_asextloadi32, GR64>; +def LGB : UnaryRXY<"lgb", 0xE377, z_asextloadi8, GR64, 1>; +def LGH : UnaryRXY<"lgh", 0xE315, z_asextloadi16, GR64, 2>; +def LGF : UnaryRXY<"lgf", 0xE314, z_asextloadi32, GR64, 4>; +def LGHRL : UnaryRILPC<"lghrl", 0xC44, aligned_z_asextloadi16, GR64>; +def LGFRL : UnaryRILPC<"lgfrl", 0xC4C, aligned_z_asextloadi32, GR64>; let Defs = [CC], CCValues = 0xE, CompareZeroCCMask = 0xE in - def LTGF : UnaryRXY<"ltgf", 0xE332, asextloadi32, GR64, 4>; + def LTGF : UnaryRXY<"ltgf", 0xE332, z_asextloadi32, GR64, 4>; //===----------------------------------------------------------------------===// // Zero extensions @@ -740,40 +740,40 @@ def : Pat<(and GR64:$src, 0xffffffff), // 32-bit extensions from 8-bit memory. LLCMux expands to LLC or LLCH, // depending on the choice of register. -def LLCMux : UnaryRXYPseudo<"llc", azextloadi8, GRX32, 1>, +def LLCMux : UnaryRXYPseudo<"llc", z_azextloadi8, GRX32, 1>, Requires<[FeatureHighWord]>; -def LLC : UnaryRXY<"llc", 0xE394, azextloadi8, GR32, 1>; -def LLCH : UnaryRXY<"llch", 0xE3C2, azextloadi8, GRH32, 1>, +def LLC : UnaryRXY<"llc", 0xE394, z_azextloadi8, GR32, 1>; +def LLCH : UnaryRXY<"llch", 0xE3C2, z_azextloadi8, GRH32, 1>, Requires<[FeatureHighWord]>; // 32-bit extensions from 16-bit memory. LLHMux expands to LLH or LLHH, // depending on the choice of register. -def LLHMux : UnaryRXYPseudo<"llh", azextloadi16, GRX32, 2>, +def LLHMux : UnaryRXYPseudo<"llh", z_azextloadi16, GRX32, 2>, Requires<[FeatureHighWord]>; -def LLH : UnaryRXY<"llh", 0xE395, azextloadi16, GR32, 2>; -def LLHH : UnaryRXY<"llhh", 0xE3C6, azextloadi16, GRH32, 2>, +def LLH : UnaryRXY<"llh", 0xE395, z_azextloadi16, GR32, 2>; +def LLHH : UnaryRXY<"llhh", 0xE3C6, z_azextloadi16, GRH32, 2>, Requires<[FeatureHighWord]>; -def LLHRL : UnaryRILPC<"llhrl", 0xC42, aligned_azextloadi16, GR32>; +def LLHRL : UnaryRILPC<"llhrl", 0xC42, aligned_z_azextloadi16, GR32>; // 64-bit extensions from memory. -def LLGC : UnaryRXY<"llgc", 0xE390, azextloadi8, GR64, 1>; -def LLGH : UnaryRXY<"llgh", 0xE391, azextloadi16, GR64, 2>; -def LLGF : UnaryRXY<"llgf", 0xE316, azextloadi32, GR64, 4>; -def LLGHRL : UnaryRILPC<"llghrl", 0xC46, aligned_azextloadi16, GR64>; -def LLGFRL : UnaryRILPC<"llgfrl", 0xC4E, aligned_azextloadi32, GR64>; +def LLGC : UnaryRXY<"llgc", 0xE390, z_azextloadi8, GR64, 1>; +def LLGH : UnaryRXY<"llgh", 0xE391, z_azextloadi16, GR64, 2>; +def LLGF : UnaryRXY<"llgf", 0xE316, z_azextloadi32, GR64, 4>; +def LLGHRL : UnaryRILPC<"llghrl", 0xC46, aligned_z_azextloadi16, GR64>; +def LLGFRL : UnaryRILPC<"llgfrl", 0xC4E, aligned_z_azextloadi32, GR64>; // 31-to-64-bit zero extensions. def LLGTR : UnaryRRE<"llgtr", 0xB917, null_frag, GR64, GR64>; def LLGT : UnaryRXY<"llgt", 0xE317, null_frag, GR64, 4>; def : Pat<(and GR64:$src, 0x7fffffff), (LLGTR GR64:$src)>; -def : Pat<(and (i64 (azextloadi32 bdxaddr20only:$src)), 0x7fffffff), +def : Pat<(and (i64 (z_azextloadi32 bdxaddr20only:$src)), 0x7fffffff), (LLGT bdxaddr20only:$src)>; // Load and zero rightmost byte. let Predicates = [FeatureLoadAndZeroRightmostByte] in { def LLZRGF : UnaryRXY<"llzrgf", 0xE33A, null_frag, GR64, 4>; - def : Pat<(and (i64 (azextloadi32 bdxaddr20only:$src)), 0xffffff00), + def : Pat<(and (i64 (z_azextloadi32 bdxaddr20only:$src)), 0xffffff00), (LLZRGF bdxaddr20only:$src)>; } @@ -930,14 +930,14 @@ defm : SXU<ineg, LCGFR>; //===----------------------------------------------------------------------===// let isCodeGenOnly = 1 in - defm IC32 : BinaryRXPair<"ic", 0x43, 0xE373, inserti8, GR32, azextloadi8, 1>; -defm IC : BinaryRXPair<"ic", 0x43, 0xE373, inserti8, GR64, azextloadi8, 1>; + defm IC32 : BinaryRXPair<"ic", 0x43, 0xE373, inserti8, GR32, z_azextloadi8, 1>; +defm IC : BinaryRXPair<"ic", 0x43, 0xE373, inserti8, GR64, z_azextloadi8, 1>; -defm : InsertMem<"inserti8", IC32, GR32, azextloadi8, bdxaddr12pair>; -defm : InsertMem<"inserti8", IC32Y, GR32, azextloadi8, bdxaddr20pair>; +defm : InsertMem<"inserti8", IC32, GR32, z_azextloadi8, bdxaddr12pair>; +defm : InsertMem<"inserti8", IC32Y, GR32, z_azextloadi8, bdxaddr20pair>; -defm : InsertMem<"inserti8", IC, GR64, azextloadi8, bdxaddr12pair>; -defm : InsertMem<"inserti8", ICY, GR64, azextloadi8, bdxaddr20pair>; +defm : InsertMem<"inserti8", IC, GR64, z_azextloadi8, bdxaddr12pair>; +defm : InsertMem<"inserti8", ICY, GR64, z_azextloadi8, bdxaddr20pair>; // Insert characters under mask -- not (yet) used for codegen. let Defs = [CC] in { @@ -1015,12 +1015,12 @@ let Defs = [CC], CCValues = 0xF, CCIfNoSignedWrap = 1 in { def AGFI : BinaryRIL<"agfi", 0xC28, z_sadd, GR64, imm64sx32>; // Addition of memory. - defm AH : BinaryRXPair<"ah", 0x4A, 0xE37A, z_sadd, GR32, asextloadi16, 2>; - defm A : BinaryRXPairAndPseudo<"a", 0x5A, 0xE35A, z_sadd, GR32, load, 4>; - def AGH : BinaryRXY<"agh", 0xE338, z_sadd, GR64, asextloadi16, 2>, + defm AH : BinaryRXPair<"ah", 0x4A, 0xE37A, z_sadd, GR32, z_asextloadi16, 2>; + defm A : BinaryRXPairAndPseudo<"a", 0x5A, 0xE35A, z_sadd, GR32, z_load, 4>; + def AGH : BinaryRXY<"agh", 0xE338, z_sadd, GR64, z_asextloadi16, 2>, Requires<[FeatureMiscellaneousExtensions2]>; - def AGF : BinaryRXY<"agf", 0xE318, z_sadd, GR64, asextloadi32, 4>; - defm AG : BinaryRXYAndPseudo<"ag", 0xE308, z_sadd, GR64, load, 8>; + def AGF : BinaryRXY<"agf", 0xE318, z_sadd, GR64, z_asextloadi32, 4>; + defm AG : BinaryRXYAndPseudo<"ag", 0xE308, z_sadd, GR64, z_load, 8>; // Addition to memory. def ASI : BinarySIY<"asi", 0xEB6A, add, imm32sx8>; @@ -1058,9 +1058,9 @@ let Defs = [CC], CCValues = 0xF, IsLogical = 1 in { Requires<[FeatureHighWord]>; // Addition of memory. - defm AL : BinaryRXPairAndPseudo<"al", 0x5E, 0xE35E, z_uadd, GR32, load, 4>; - def ALGF : BinaryRXY<"algf", 0xE31A, z_uadd, GR64, azextloadi32, 4>; - defm ALG : BinaryRXYAndPseudo<"alg", 0xE30A, z_uadd, GR64, load, 8>; + defm AL : BinaryRXPairAndPseudo<"al", 0x5E, 0xE35E, z_uadd, GR32, z_load, 4>; + def ALGF : BinaryRXY<"algf", 0xE31A, z_uadd, GR64, z_azextloadi32, 4>; + defm ALG : BinaryRXYAndPseudo<"alg", 0xE30A, z_uadd, GR64, z_load, 8>; // Addition to memory. def ALSI : BinarySIY<"alsi", 0xEB6E, null_frag, imm32sx8>; @@ -1075,8 +1075,8 @@ let Defs = [CC], Uses = [CC], CCValues = 0xF, IsLogical = 1 in { def ALCGR : BinaryRRE<"alcgr", 0xB988, z_addcarry, GR64, GR64>; // Addition of memory. - def ALC : BinaryRXY<"alc", 0xE398, z_addcarry, GR32, load, 4>; - def ALCG : BinaryRXY<"alcg", 0xE388, z_addcarry, GR64, load, 8>; + def ALC : BinaryRXY<"alc", 0xE398, z_addcarry, GR32, z_load, 4>; + def ALCG : BinaryRXY<"alcg", 0xE388, z_addcarry, GR64, z_load, 8>; } // Addition that does not modify the condition code. @@ -1103,12 +1103,12 @@ let Defs = [CC], CCValues = 0xF, CompareZeroCCMask = 0x8, Requires<[FeatureHighWord]>; // Subtraction of memory. - defm SH : BinaryRXPair<"sh", 0x4B, 0xE37B, z_ssub, GR32, asextloadi16, 2>; - defm S : BinaryRXPairAndPseudo<"s", 0x5B, 0xE35B, z_ssub, GR32, load, 4>; - def SGH : BinaryRXY<"sgh", 0xE339, z_ssub, GR64, asextloadi16, 2>, + defm SH : BinaryRXPair<"sh", 0x4B, 0xE37B, z_ssub, GR32, z_asextloadi16, 2>; + defm S : BinaryRXPairAndPseudo<"s", 0x5B, 0xE35B, z_ssub, GR32, z_load, 4>; + def SGH : BinaryRXY<"sgh", 0xE339, z_ssub, GR64, z_asextloadi16, 2>, Requires<[FeatureMiscellaneousExtensions2]>; - def SGF : BinaryRXY<"sgf", 0xE319, z_ssub, GR64, asextloadi32, 4>; - defm SG : BinaryRXYAndPseudo<"sg", 0xE309, z_ssub, GR64, load, 8>; + def SGF : BinaryRXY<"sgf", 0xE319, z_ssub, GR64, z_asextloadi32, 4>; + defm SG : BinaryRXYAndPseudo<"sg", 0xE309, z_ssub, GR64, z_load, 8>; } defm : SXB<z_ssub, GR64, SGFR>; @@ -1156,9 +1156,9 @@ let Defs = [CC], CCValues = 0x7, IsLogical = 1 in { def SLGFI : BinaryRIL<"slgfi", 0xC24, z_usub, GR64, imm64zx32>; // Subtraction of memory. - defm SL : BinaryRXPairAndPseudo<"sl", 0x5F, 0xE35F, z_usub, GR32, load, 4>; - def SLGF : BinaryRXY<"slgf", 0xE31B, z_usub, GR64, azextloadi32, 4>; - defm SLG : BinaryRXYAndPseudo<"slg", 0xE30B, z_usub, GR64, load, 8>; + defm SL : BinaryRXPairAndPseudo<"sl", 0x5F, 0xE35F, z_usub, GR32, z_load, 4>; + def SLGF : BinaryRXY<"slgf", 0xE31B, z_usub, GR64, z_azextloadi32, 4>; + defm SLG : BinaryRXYAndPseudo<"slg", 0xE30B, z_usub, GR64, z_load, 8>; } defm : ZXB<z_usub, GR64, SLGFR>; @@ -1183,8 +1183,8 @@ let Defs = [CC], Uses = [CC], CCValues = 0xF, IsLogical = 1 in { def SLBGR : BinaryRRE<"slbgr", 0xB989, z_subcarry, GR64, GR64>; // Subtraction of memory. - def SLB : BinaryRXY<"slb", 0xE399, z_subcarry, GR32, load, 4>; - def SLBG : BinaryRXY<"slbg", 0xE389, z_subcarry, GR64, load, 8>; + def SLB : BinaryRXY<"slb", 0xE399, z_subcarry, GR32, z_load, 4>; + def SLBG : BinaryRXY<"slbg", 0xE389, z_subcarry, GR64, z_load, 8>; } @@ -1233,8 +1233,8 @@ let Defs = [CC] in { // ANDs of memory. let CCValues = 0xC, CompareZeroCCMask = 0x8 in { - defm N : BinaryRXPairAndPseudo<"n", 0x54, 0xE354, and, GR32, load, 4>; - defm NG : BinaryRXYAndPseudo<"ng", 0xE380, and, GR64, load, 8>; + defm N : BinaryRXPairAndPseudo<"n", 0x54, 0xE354, and, GR32, z_load, 4>; + defm NG : BinaryRXYAndPseudo<"ng", 0xE380, and, GR64, z_load, 8>; } // AND to memory @@ -1290,8 +1290,8 @@ let Defs = [CC] in { // ORs of memory. let CCValues = 0xC, CompareZeroCCMask = 0x8 in { - defm O : BinaryRXPairAndPseudo<"o", 0x56, 0xE356, or, GR32, load, 4>; - defm OG : BinaryRXYAndPseudo<"og", 0xE381, or, GR64, load, 8>; + defm O : BinaryRXPairAndPseudo<"o", 0x56, 0xE356, or, GR32, z_load, 4>; + defm OG : BinaryRXYAndPseudo<"og", 0xE381, or, GR64, z_load, 8>; } // OR to memory @@ -1330,8 +1330,8 @@ let Defs = [CC] in { // XORs of memory. let CCValues = 0xC, CompareZeroCCMask = 0x8 in { - defm X : BinaryRXPairAndPseudo<"x",0x57, 0xE357, xor, GR32, load, 4>; - defm XG : BinaryRXYAndPseudo<"xg", 0xE382, xor, GR64, load, 8>; + defm X : BinaryRXPairAndPseudo<"x",0x57, 0xE357, xor, GR32, z_load, 4>; + defm XG : BinaryRXYAndPseudo<"xg", 0xE382, xor, GR64, z_load, 8>; } // XOR to memory @@ -1411,17 +1411,17 @@ def MSFI : BinaryRIL<"msfi", 0xC21, mul, GR32, simm32>; def MSGFI : BinaryRIL<"msgfi", 0xC20, mul, GR64, imm64sx32>; // Multiplication of memory. -defm MH : BinaryRXPair<"mh", 0x4C, 0xE37C, mul, GR32, asextloadi16, 2>; -defm MS : BinaryRXPair<"ms", 0x71, 0xE351, mul, GR32, load, 4>; -def MGH : BinaryRXY<"mgh", 0xE33C, mul, GR64, asextloadi16, 2>, +defm MH : BinaryRXPair<"mh", 0x4C, 0xE37C, mul, GR32, z_asextloadi16, 2>; +defm MS : BinaryRXPair<"ms", 0x71, 0xE351, mul, GR32, z_load, 4>; +def MGH : BinaryRXY<"mgh", 0xE33C, mul, GR64, z_asextloadi16, 2>, Requires<[FeatureMiscellaneousExtensions2]>; -def MSGF : BinaryRXY<"msgf", 0xE31C, mul, GR64, asextloadi32, 4>; -def MSG : BinaryRXY<"msg", 0xE30C, mul, GR64, load, 8>; +def MSGF : BinaryRXY<"msgf", 0xE31C, mul, GR64, z_asextloadi32, 4>; +def MSG : BinaryRXY<"msg", 0xE30C, mul, GR64, z_load, 8>; // Multiplication of memory, setting the condition code. let Predicates = [FeatureMiscellaneousExtensions2], Defs = [CC] in { - defm MSC : BinaryRXYAndPseudo<"msc", 0xE353, null_frag, GR32, load, 4>; - defm MSGC : BinaryRXYAndPseudo<"msgc", 0xE383, null_frag, GR64, load, 8>; + defm MSC : BinaryRXYAndPseudo<"msc", 0xE353, null_frag, GR32, z_load, 4>; + defm MSGC : BinaryRXYAndPseudo<"msgc", 0xE383, null_frag, GR64, z_load, 8>; } // Multiplication of a register, producing two results. @@ -1437,16 +1437,16 @@ def : Pat<(z_umul_lohi GR64:$src1, GR64:$src2), (MLGR (AEXT128 GR64:$src1), GR64:$src2)>; // Multiplication of memory, producing two results. -def M : BinaryRX <"m", 0x5C, null_frag, GR128, load, 4>; -def MFY : BinaryRXY<"mfy", 0xE35C, null_frag, GR128, load, 4>; -def MG : BinaryRXY<"mg", 0xE384, null_frag, GR128, load, 8>, +def M : BinaryRX <"m", 0x5C, null_frag, GR128, z_load, 4>; +def MFY : BinaryRXY<"mfy", 0xE35C, null_frag, GR128, z_load, 4>; +def MG : BinaryRXY<"mg", 0xE384, null_frag, GR128, z_load, 8>, Requires<[FeatureMiscellaneousExtensions2]>; -def ML : BinaryRXY<"ml", 0xE396, null_frag, GR128, load, 4>; -def MLG : BinaryRXY<"mlg", 0xE386, null_frag, GR128, load, 8>; +def ML : BinaryRXY<"ml", 0xE396, null_frag, GR128, z_load, 4>; +def MLG : BinaryRXY<"mlg", 0xE386, null_frag, GR128, z_load, 8>; -def : Pat<(z_smul_lohi GR64:$src1, (i64 (load bdxaddr20only:$src2))), +def : Pat<(z_smul_lohi GR64:$src1, (i64 (z_load bdxaddr20only:$src2))), (MG (AEXT128 GR64:$src1), bdxaddr20only:$src2)>; -def : Pat<(z_umul_lohi GR64:$src1, (i64 (load bdxaddr20only:$src2))), +def : Pat<(z_umul_lohi GR64:$src1, (i64 (z_load bdxaddr20only:$src2))), (MLG (AEXT128 GR64:$src1), bdxaddr20only:$src2)>; //===----------------------------------------------------------------------===// @@ -1462,30 +1462,30 @@ let hasSideEffects = 1 in { // Do not speculatively execute. def DLGR : BinaryRRE<"dlgr", 0xB987, null_frag, GR128, GR64>; // Division and remainder, from memory. - def D : BinaryRX <"d", 0x5D, null_frag, GR128, load, 4>; - def DSGF : BinaryRXY<"dsgf", 0xE31D, null_frag, GR128, load, 4>; - def DSG : BinaryRXY<"dsg", 0xE30D, null_frag, GR128, load, 8>; - def DL : BinaryRXY<"dl", 0xE397, null_frag, GR128, load, 4>; - def DLG : BinaryRXY<"dlg", 0xE387, null_frag, GR128, load, 8>; + def D : BinaryRX <"d", 0x5D, null_frag, GR128, z_load, 4>; + def DSGF : BinaryRXY<"dsgf", 0xE31D, null_frag, GR128, z_load, 4>; + def DSG : BinaryRXY<"dsg", 0xE30D, null_frag, GR128, z_load, 8>; + def DL : BinaryRXY<"dl", 0xE397, null_frag, GR128, z_load, 4>; + def DLG : BinaryRXY<"dlg", 0xE387, null_frag, GR128, z_load, 8>; } def : Pat<(z_sdivrem GR64:$src1, GR32:$src2), (DSGFR (AEXT128 GR64:$src1), GR32:$src2)>; -def : Pat<(z_sdivrem GR64:$src1, (i32 (load bdxaddr20only:$src2))), +def : Pat<(z_sdivrem GR64:$src1, (i32 (z_load bdxaddr20only:$src2))), (DSGF (AEXT128 GR64:$src1), bdxaddr20only:$src2)>; def : Pat<(z_sdivrem GR64:$src1, GR64:$src2), (DSGR (AEXT128 GR64:$src1), GR64:$src2)>; -def : Pat<(z_sdivrem GR64:$src1, (i64 (load bdxaddr20only:$src2))), +def : Pat<(z_sdivrem GR64:$src1, (i64 (z_load bdxaddr20only:$src2))), (DSG (AEXT128 GR64:$src1), bdxaddr20only:$src2)>; def : Pat<(z_udivrem GR32:$src1, GR32:$src2), (DLR (ZEXT128 (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$src1, subreg_l32)), GR32:$src2)>; -def : Pat<(z_udivrem GR32:$src1, (i32 (load bdxaddr20only:$src2))), +def : Pat<(z_udivrem GR32:$src1, (i32 (z_load bdxaddr20only:$src2))), (DL (ZEXT128 (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$src1, subreg_l32)), bdxaddr20only:$src2)>; def : Pat<(z_udivrem GR64:$src1, GR64:$src2), (DLGR (ZEXT128 GR64:$src1), GR64:$src2)>; -def : Pat<(z_udivrem GR64:$src1, (i64 (load bdxaddr20only:$src2))), +def : Pat<(z_udivrem GR64:$src1, (i64 (z_load bdxaddr20only:$src2))), (DLG (ZEXT128 GR64:$src1), bdxaddr20only:$src2)>; //===----------------------------------------------------------------------===// @@ -1591,25 +1591,25 @@ let Defs = [CC], CCValues = 0xE in { def CGFI : CompareRIL<"cgfi", 0xC2C, z_scmp, GR64, imm64sx32>; // Comparison with memory. - defm CH : CompareRXPair<"ch", 0x49, 0xE379, z_scmp, GR32, asextloadi16, 2>; - def CMux : CompareRXYPseudo<z_scmp, GRX32, load, 4>, + defm CH : CompareRXPair<"ch", 0x49, 0xE379, z_scmp, GR32, z_asextloadi16, 2>; + def CMux : CompareRXYPseudo<z_scmp, GRX32, z_load, 4>, Requires<[FeatureHighWord]>; - defm C : CompareRXPair<"c", 0x59, 0xE359, z_scmp, GR32, load, 4>; - def CHF : CompareRXY<"chf", 0xE3CD, z_scmp, GRH32, load, 4>, + defm C : CompareRXPair<"c", 0x59, 0xE359, z_scmp, GR32, z_load, 4>; + def CHF : CompareRXY<"chf", 0xE3CD, z_scmp, GRH32, z_load, 4>, Requires<[FeatureHighWord]>; - def CGH : CompareRXY<"cgh", 0xE334, z_scmp, GR64, asextloadi16, 2>; - def CGF : CompareRXY<"cgf", 0xE330, z_scmp, GR64, asextloadi32, 4>; - def CG : CompareRXY<"cg", 0xE320, z_scmp, GR64, load, 8>; - def CHRL : CompareRILPC<"chrl", 0xC65, z_scmp, GR32, aligned_asextloadi16>; - def CRL : CompareRILPC<"crl", 0xC6D, z_scmp, GR32, aligned_load>; - def CGHRL : CompareRILPC<"cghrl", 0xC64, z_scmp, GR64, aligned_asextloadi16>; - def CGFRL : CompareRILPC<"cgfrl", 0xC6C, z_scmp, GR64, aligned_asextloadi32>; - def CGRL : CompareRILPC<"cgrl", 0xC68, z_scmp, GR64, aligned_load>; + def CGH : CompareRXY<"cgh", 0xE334, z_scmp, GR64, z_asextloadi16, 2>; + def CGF : CompareRXY<"cgf", 0xE330, z_scmp, GR64, z_asextloadi32, 4>; + def CG : CompareRXY<"cg", 0xE320, z_scmp, GR64, z_load, 8>; + def CHRL : CompareRILPC<"chrl", 0xC65, z_scmp, GR32, aligned_z_asextloadi16>; + def CRL : CompareRILPC<"crl", 0xC6D, z_scmp, GR32, aligned_z_load>; + def CGHRL : CompareRILPC<"cghrl", 0xC64, z_scmp, GR64, aligned_z_asextloadi16>; + def CGFRL : CompareRILPC<"cgfrl", 0xC6C, z_scmp, GR64, aligned_z_asextloadi32>; + def CGRL : CompareRILPC<"cgrl", 0xC68, z_scmp, GR64, aligned_z_load>; // Comparison between memory and a signed 16-bit immediate. - def CHHSI : CompareSIL<"chhsi", 0xE554, z_scmp, asextloadi16, imm32sx16>; - def CHSI : CompareSIL<"chsi", 0xE55C, z_scmp, load, imm32sx16>; - def CGHSI : CompareSIL<"cghsi", 0xE558, z_scmp, load, imm64sx16>; + def CHHSI : CompareSIL<"chhsi", 0xE554, z_scmp, z_asextloadi16, imm32sx16>; + def CHSI : CompareSIL<"chsi", 0xE55C, z_scmp, z_load, imm32sx16>; + def CGHSI : CompareSIL<"cghsi", 0xE558, z_scmp, z_load, imm64sx16>; } defm : SXB<z_scmp, GR64, CGFR>; @@ -1636,31 +1636,31 @@ let Defs = [CC], CCValues = 0xE, IsLogical = 1 in { def CLGFI : CompareRIL<"clgfi", 0xC2E, z_ucmp, GR64, imm64zx32>; // Comparison with memory. - def CLMux : CompareRXYPseudo<z_ucmp, GRX32, load, 4>, + def CLMux : CompareRXYPseudo<z_ucmp, GRX32, z_load, 4>, Requires<[FeatureHighWord]>; - defm CL : CompareRXPair<"cl", 0x55, 0xE355, z_ucmp, GR32, load, 4>; - def CLHF : CompareRXY<"clhf", 0xE3CF, z_ucmp, GRH32, load, 4>, + defm CL : CompareRXPair<"cl", 0x55, 0xE355, z_ucmp, GR32, z_load, 4>; + def CLHF : CompareRXY<"clhf", 0xE3CF, z_ucmp, GRH32, z_load, 4>, Requires<[FeatureHighWord]>; - def CLGF : CompareRXY<"clgf", 0xE331, z_ucmp, GR64, azextloadi32, 4>; - def CLG : CompareRXY<"clg", 0xE321, z_ucmp, GR64, load, 8>; + def CLGF : CompareRXY<"clgf", 0xE331, z_ucmp, GR64, z_azextloadi32, 4>; + def CLG : CompareRXY<"clg", 0xE321, z_ucmp, GR64, z_load, 8>; def CLHRL : CompareRILPC<"clhrl", 0xC67, z_ucmp, GR32, - aligned_azextloadi16>; + aligned_z_azextloadi16>; def CLRL : CompareRILPC<"clrl", 0xC6F, z_ucmp, GR32, - aligned_load>; + aligned_z_load>; def CLGHRL : CompareRILPC<"clghrl", 0xC66, z_ucmp, GR64, - aligned_azextloadi16>; + aligned_z_azextloadi16>; def CLGFRL : CompareRILPC<"clgfrl", 0xC6E, z_ucmp, GR64, - aligned_azextloadi32>; + aligned_z_azextloadi32>; def CLGRL : CompareRILPC<"clgrl", 0xC6A, z_ucmp, GR64, - aligned_load>; + aligned_z_load>; // Comparison between memory and an unsigned 8-bit immediate. - defm CLI : CompareSIPair<"cli", 0x95, 0xEB55, z_ucmp, azextloadi8, imm32zx8>; + defm CLI : CompareSIPair<"cli", 0x95, 0xEB55, z_ucmp, z_azextloadi8, imm32zx8>; // Comparison between memory and an unsigned 16-bit immediate. - def CLHHSI : CompareSIL<"clhhsi", 0xE555, z_ucmp, azextloadi16, imm32zx16>; - def CLFHSI : CompareSIL<"clfhsi", 0xE55D, z_ucmp, load, imm32zx16>; - def CLGHSI : CompareSIL<"clghsi", 0xE559, z_ucmp, load, imm64zx16>; + def CLHHSI : CompareSIL<"clhhsi", 0xE555, z_ucmp, z_azextloadi16, imm32zx16>; + def CLFHSI : CompareSIL<"clfhsi", 0xE55D, z_ucmp, z_load, imm32zx16>; + def CLGHSI : CompareSIL<"clghsi", 0xE559, z_ucmp, z_load, imm64zx16>; } defm : ZXB<z_ucmp, GR64, CLGFR>; @@ -1693,7 +1693,7 @@ let Defs = [CC] in { def TMHL64 : CompareAliasRI<z_tm_reg, GR64, imm64hl16>; def TMHH64 : CompareAliasRI<z_tm_reg, GR64, imm64hh16>; - defm TM : CompareSIPair<"tm", 0x91, 0xEB51, z_tm_mem, anyextloadi8, imm32zx8>; + defm TM : CompareSIPair<"tm", 0x91, 0xEB51, z_tm_mem, z_anyextloadi8, imm32zx8>; } def TML : InstAlias<"tml\t$R, $I", (TMLL GR32:$R, imm32ll16:$I), 0>; @@ -1914,8 +1914,8 @@ let Predicates = [FeatureGuardedStorage], hasSideEffects = 1 in { // Decimal arithmetic //===----------------------------------------------------------------------===// -defm CVB : BinaryRXPair<"cvb",0x4F, 0xE306, null_frag, GR32, load, 4>; -def CVBG : BinaryRXY<"cvbg", 0xE30E, null_frag, GR64, load, 8>; +defm CVB : BinaryRXPair<"cvb",0x4F, 0xE306, null_frag, GR32, z_load, 4>; +def CVBG : BinaryRXY<"cvbg", 0xE30E, null_frag, GR64, z_load, 8>; defm CVD : StoreRXPair<"cvd", 0x4E, 0xE326, null_frag, GR32, 4>; def CVDG : StoreRXY<"cvdg", 0xE32E, null_frag, GR64, 8>; diff --git a/llvm/lib/Target/SystemZ/SystemZInstrSystem.td b/llvm/lib/Target/SystemZ/SystemZInstrSystem.td index e26417ddb72d99d1dae11e40a7f5bfb1f194cce0..497844bec85d17f04350f884df7589772bdf08c8 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrSystem.td +++ b/llvm/lib/Target/SystemZ/SystemZInstrSystem.td @@ -339,7 +339,7 @@ let hasSideEffects = 1 in // Store clock (fast / extended). let hasSideEffects = 1, Defs = [CC] in { def STCK : StoreInherentS<"stck", 0xB205, null_frag, 8>; - def STCKF : StoreInherentS<"stckf", 0xB27C, null_frag, 8>; + def STCKF : StoreInherentS<"stckf", 0xB27C, z_stckf, 8>; def STCKE : StoreInherentS<"stcke", 0xB278, null_frag, 16>; } diff --git a/llvm/lib/Target/SystemZ/SystemZInstrVector.td b/llvm/lib/Target/SystemZ/SystemZInstrVector.td index 799b27d74414d542fea9fd566e1059d7b36ae1ab..245e3c3399a98679ba5c6299b027ff8c93b8ea8e 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrVector.td +++ b/llvm/lib/Target/SystemZ/SystemZInstrVector.td @@ -140,8 +140,8 @@ let Predicates = [FeatureVector] in { // to use those instructions rather than force a 20-bit displacement // into a GPR temporary. let mayLoad = 1 in { - def VL32 : UnaryAliasVRX<load, v32sb, bdxaddr12pair>; - def VL64 : UnaryAliasVRX<load, v64db, bdxaddr12pair>; + def VL32 : UnaryAliasVRX<z_load, v32sb, bdxaddr12pair>; + def VL64 : UnaryAliasVRX<z_load, v64db, bdxaddr12pair>; } // Load logical element and zero. @@ -198,12 +198,12 @@ multiclass ReplicatePeephole<Instruction vlrep, ValueType vectype, (scalartype (load bdxaddr12only:$addr)))), (vlrep bdxaddr12only:$addr)>; } -defm : ReplicatePeephole<VLREPB, v16i8, anyextloadi8, i32>; -defm : ReplicatePeephole<VLREPH, v8i16, anyextloadi16, i32>; -defm : ReplicatePeephole<VLREPF, v4i32, load, i32>; -defm : ReplicatePeephole<VLREPG, v2i64, load, i64>; -defm : ReplicatePeephole<VLREPF, v4f32, load, f32>; -defm : ReplicatePeephole<VLREPG, v2f64, load, f64>; +defm : ReplicatePeephole<VLREPB, v16i8, z_anyextloadi8, i32>; +defm : ReplicatePeephole<VLREPH, v8i16, z_anyextloadi16, i32>; +defm : ReplicatePeephole<VLREPF, v4i32, z_load, i32>; +defm : ReplicatePeephole<VLREPG, v2i64, z_load, i64>; +defm : ReplicatePeephole<VLREPF, v4f32, z_load, f32>; +defm : ReplicatePeephole<VLREPG, v2f64, z_load, f64>; //===----------------------------------------------------------------------===// // Stores @@ -1561,13 +1561,13 @@ let Predicates = [FeatureVector] in { // Any-extending loads into i128. let Predicates = [FeatureVector] in { - def : Pat<(i128 (extloadi8 bdxaddr12only:$addr)), + def : Pat<(i128 (z_extloadi8 bdxaddr12only:$addr)), (VLREPB bdxaddr12only:$addr)>; - def : Pat<(i128 (extloadi16 bdxaddr12only:$addr)), + def : Pat<(i128 (z_extloadi16 bdxaddr12only:$addr)), (VLREPH bdxaddr12only:$addr)>; - def : Pat<(i128 (extloadi32 bdxaddr12only:$addr)), + def : Pat<(i128 (z_extloadi32 bdxaddr12only:$addr)), (VLREPF bdxaddr12only:$addr)>; - def : Pat<(i128 (extloadi64 bdxaddr12only:$addr)), + def : Pat<(i128 (z_extloadi64 bdxaddr12only:$addr)), (VLREPG bdxaddr12only:$addr)>; } @@ -1621,13 +1621,13 @@ let Predicates = [FeatureVector] in { // Zero-extending loads into i128. let Predicates = [FeatureVector] in { - def : Pat<(i128 (zextloadi8 bdxaddr12only:$addr)), + def : Pat<(i128 (z_zextloadi8 bdxaddr12only:$addr)), (VLEB (VGBM 0), bdxaddr12only:$addr, 15)>; - def : Pat<(i128 (zextloadi16 bdxaddr12only:$addr)), + def : Pat<(i128 (z_zextloadi16 bdxaddr12only:$addr)), (VLEH (VGBM 0), bdxaddr12only:$addr, 7)>; - def : Pat<(i128 (zextloadi32 bdxaddr12only:$addr)), + def : Pat<(i128 (z_zextloadi32 bdxaddr12only:$addr)), (VLEF (VGBM 0), bdxaddr12only:$addr, 3)>; - def : Pat<(i128 (zextloadi64 bdxaddr12only:$addr)), + def : Pat<(i128 (z_zextloadi64 bdxaddr12only:$addr)), (VLEG (VGBM 0), bdxaddr12only:$addr, 1)>; } @@ -1663,13 +1663,13 @@ let Predicates = [FeatureVector] in { // Sign-extending loads into i128. let Predicates = [FeatureVector] in { - def : Pat<(i128 (sextloadi8 bdxaddr12only:$addr)), + def : Pat<(i128 (z_sextloadi8 bdxaddr12only:$addr)), (VSRAB (VLREPB bdxaddr12only:$addr), (VREPIB 120))>; - def : Pat<(i128 (sextloadi16 bdxaddr12only:$addr)), + def : Pat<(i128 (z_sextloadi16 bdxaddr12only:$addr)), (VSRAB (VLREPH bdxaddr12only:$addr), (VREPIB 112))>; - def : Pat<(i128 (sextloadi32 bdxaddr12only:$addr)), + def : Pat<(i128 (z_sextloadi32 bdxaddr12only:$addr)), (VSRAB (VLREPF bdxaddr12only:$addr), (VREPIB 96))>; - def : Pat<(i128 (sextloadi64 bdxaddr12only:$addr)), + def : Pat<(i128 (z_sextloadi64 bdxaddr12only:$addr)), (VSRAB (VLREPG bdxaddr12only:$addr), (VREPIB 64))>; } diff --git a/llvm/lib/Target/SystemZ/SystemZOperators.td b/llvm/lib/Target/SystemZ/SystemZOperators.td index d98bb886c18506d38dd1f9c7fea1f2ccdb180a27..1611436b01b7fa4a186ad7e775b9e3acb51d4194 100644 --- a/llvm/lib/Target/SystemZ/SystemZOperators.td +++ b/llvm/lib/Target/SystemZ/SystemZOperators.td @@ -132,6 +132,8 @@ def SDT_ZIPM : SDTypeProfile<1, 1, def SDT_ZPrefetch : SDTypeProfile<0, 2, [SDTCisVT<0, i32>, SDTCisPtrTy<1>]>; +def SDT_ZStoreInherent : SDTypeProfile<0, 1, + [SDTCisPtrTy<0>]>; def SDT_ZTBegin : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisPtrTy<1>, @@ -307,6 +309,8 @@ def z_loadeswap : SDNode<"SystemZISD::VLER", SDTLoad, [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; def z_storeeswap : SDNode<"SystemZISD::VSTER", SDTStore, [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; +def z_stckf : SDNode<"SystemZISD::STCKF", SDT_ZStoreInherent, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; def z_tdc : SDNode<"SystemZISD::TDC", SDT_ZTest>; @@ -534,37 +538,108 @@ def zext8 : PatFrag<(ops node:$src), (and node:$src, 0xff)>; def zext16 : PatFrag<(ops node:$src), (and node:$src, 0xffff)>; def zext32 : PatFrag<(ops node:$src), (zext (i32 node:$src))>; -// Extending loads in which the extension type can be signed. -def asextload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr), [{ - unsigned Type = cast<LoadSDNode>(N)->getExtensionType(); - return Type == ISD::EXTLOAD || Type == ISD::SEXTLOAD; +// Match a load or a non-extending atomic load. +def z_load : PatFrags<(ops node:$ptr), + [(load node:$ptr), + (atomic_load node:$ptr)], [{ + if (auto *AL = dyn_cast<AtomicSDNode>(N)) + if (AL->getExtensionType() != ISD::NON_EXTLOAD) + return false; + return true; }]>; -def asextloadi8 : PatFrag<(ops node:$ptr), (asextload node:$ptr), [{ - return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i8; + +// Sign extending (atomic) loads. +def z_sextload : PatFrags<(ops node:$ptr), + [(unindexedload node:$ptr), + (atomic_load node:$ptr)], [{ + return getLoadExtType(N) == ISD::SEXTLOAD; }]>; -def asextloadi16 : PatFrag<(ops node:$ptr), (asextload node:$ptr), [{ - return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i16; +def z_sextloadi8 : PatFrag<(ops node:$ptr), (z_sextload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i8; }]>; -def asextloadi32 : PatFrag<(ops node:$ptr), (asextload node:$ptr), [{ - return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i32; +def z_sextloadi16 : PatFrag<(ops node:$ptr), (z_sextload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i16; +}]>; +def z_sextloadi32 : PatFrag<(ops node:$ptr), (z_sextload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i32; +}]>; +def z_sextloadi64 : PatFrag<(ops node:$ptr), (z_sextload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i64; }]>; -// Extending loads in which the extension type can be unsigned. -def azextload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr), [{ - unsigned Type = cast<LoadSDNode>(N)->getExtensionType(); - return Type == ISD::EXTLOAD || Type == ISD::ZEXTLOAD; +// Zero extending (atomic) loads. +def z_zextload : PatFrags<(ops node:$ptr), + [(unindexedload node:$ptr), + (atomic_load node:$ptr)], [{ + return getLoadExtType(N) == ISD::ZEXTLOAD; }]>; -def azextloadi8 : PatFrag<(ops node:$ptr), (azextload node:$ptr), [{ - return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i8; +def z_zextloadi8 : PatFrag<(ops node:$ptr), (z_zextload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i8; }]>; -def azextloadi16 : PatFrag<(ops node:$ptr), (azextload node:$ptr), [{ - return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i16; +def z_zextloadi16 : PatFrag<(ops node:$ptr), (z_zextload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i16; }]>; -def azextloadi32 : PatFrag<(ops node:$ptr), (azextload node:$ptr), [{ - return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i32; +def z_zextloadi32 : PatFrag<(ops node:$ptr), (z_zextload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i32; +}]>; +def z_zextloadi64 : PatFrag<(ops node:$ptr), (z_zextload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i64; +}]>; + +// Extending (atomic) loads in which the extension type can be signed. +def z_asextload : PatFrags<(ops node:$ptr), + [(unindexedload node:$ptr), + (atomic_load node:$ptr)], [{ + ISD::LoadExtType ETy = getLoadExtType(N); + return ETy == ISD::EXTLOAD || ETy == ISD::SEXTLOAD; +}]>; +def z_asextloadi8 : PatFrag<(ops node:$ptr), (z_asextload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i8; +}]>; +def z_asextloadi16 : PatFrag<(ops node:$ptr), (z_asextload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i16; +}]>; +def z_asextloadi32 : PatFrag<(ops node:$ptr), (z_asextload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i32; }]>; -// Extending loads in which the extension type doesn't matter. +// Extending (atomic) loads in which the extension type can be unsigned. +def z_azextload : PatFrags<(ops node:$ptr), + [(unindexedload node:$ptr), + (atomic_load node:$ptr)], [{ + ISD::LoadExtType ETy = getLoadExtType(N); + return ETy == ISD::EXTLOAD || ETy == ISD::ZEXTLOAD; +}]>; +def z_azextloadi8 : PatFrag<(ops node:$ptr), (z_azextload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i8; +}]>; +def z_azextloadi16 : PatFrag<(ops node:$ptr), (z_azextload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i16; +}]>; +def z_azextloadi32 : PatFrag<(ops node:$ptr), (z_azextload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i32; +}]>; + +// Extending (atomic) loads in which the extension type doesn't matter. +def z_anyextload : PatFrags<(ops node:$ptr), + [(unindexedload node:$ptr), + (atomic_load node:$ptr)], [{ + return getLoadExtType(N) != ISD::NON_EXTLOAD; +}]>; +def z_anyextloadi8 : PatFrag<(ops node:$ptr), (z_anyextload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i8; +}]>; +def z_anyextloadi16 : PatFrag<(ops node:$ptr), (z_anyextload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i16; +}]>; +def z_anyextloadi32 : PatFrag<(ops node:$ptr), (z_anyextload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i32; +}]>; +def z_anyextloadi64 : PatFrag<(ops node:$ptr), (z_anyextload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i64; +}]>; + +// Extending non-atomic loads in which the extension type doesn't matter. def anyextload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr), [{ return cast<LoadSDNode>(N)->getExtensionType() != ISD::NON_EXTLOAD; }]>; @@ -578,15 +653,42 @@ def anyextloadi32 : PatFrag<(ops node:$ptr), (anyextload node:$ptr), [{ return cast<LoadSDNode>(N)->getMemoryVT() == MVT::i32; }]>; +// Extending (atomic) loads that are not sign/zero extending. +def z_extload : PatFrags<(ops node:$ptr), + [(extload node:$ptr), + (atomic_load node:$ptr)], [{ + return getLoadExtType(N) == ISD::EXTLOAD; +}]>; +def z_extloadi8 : PatFrag<(ops node:$ptr), (z_extload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i8; +}]>; +def z_extloadi16 : PatFrag<(ops node:$ptr), (z_extload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i16; +}]>; +def z_extloadi32 : PatFrag<(ops node:$ptr), (z_extload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i32; +}]>; +def z_extloadi64 : PatFrag<(ops node:$ptr), (z_extload node:$ptr), [{ + return cast<MemSDNode>(N)->getMemoryVT() == MVT::i64; +}]>; + +// Extending atomic FP loads. +def z_any_extloadf32 : PatFrags<(ops node:$ptr), + [(any_extloadf32 node:$ptr), + (any_fpextend (f32 (atomic_load node:$ptr)))]>; +def z_any_extloadf64 : PatFrags<(ops node:$ptr), + [(any_extloadf64 node:$ptr), + (any_fpextend (f64 (atomic_load node:$ptr)))]>; + // Aligned loads. class AlignedLoad<SDPatternOperator load> : PatFrag<(ops node:$addr), (load node:$addr), [{ return storeLoadIsAligned(N); }]>; -def aligned_load : AlignedLoad<load>; -def aligned_asextloadi16 : AlignedLoad<asextloadi16>; -def aligned_asextloadi32 : AlignedLoad<asextloadi32>; -def aligned_azextloadi16 : AlignedLoad<azextloadi16>; -def aligned_azextloadi32 : AlignedLoad<azextloadi32>; +def aligned_z_load : AlignedLoad<z_load>; +def aligned_z_asextloadi16 : AlignedLoad<z_asextloadi16>; +def aligned_z_asextloadi32 : AlignedLoad<z_asextloadi32>; +def aligned_z_azextloadi16 : AlignedLoad<z_azextloadi16>; +def aligned_z_azextloadi32 : AlignedLoad<z_azextloadi32>; // Aligned stores. class AlignedStore<SDPatternOperator store> @@ -749,7 +851,7 @@ def z_any_vround : PatFrags<(ops node:$src), // Create a unary operator that loads from memory and then performs // the given operation on it. -class loadu<SDPatternOperator operator, SDPatternOperator load = load> +class loadu<SDPatternOperator operator, SDPatternOperator load = z_load> : PatFrag<(ops node:$addr), (operator (load node:$addr))>; // Create a store operator that performs the given unary operation @@ -799,12 +901,12 @@ def imm32nobytes : PatLeaf<(i32 imm), [{ class z_replicate_load<ValueType scalartype, SDPatternOperator load> : PatFrag<(ops node:$addr), (z_replicate (scalartype (load node:$addr)))>; -def z_replicate_loadi8 : z_replicate_load<i32, anyextloadi8>; -def z_replicate_loadi16 : z_replicate_load<i32, anyextloadi16>; -def z_replicate_loadi32 : z_replicate_load<i32, load>; -def z_replicate_loadi64 : z_replicate_load<i64, load>; -def z_replicate_loadf32 : z_replicate_load<f32, load>; -def z_replicate_loadf64 : z_replicate_load<f64, load>; +def z_replicate_loadi8 : z_replicate_load<i32, z_anyextloadi8>; +def z_replicate_loadi16 : z_replicate_load<i32, z_anyextloadi16>; +def z_replicate_loadi32 : z_replicate_load<i32, z_load>; +def z_replicate_loadi64 : z_replicate_load<i64, z_load>; +def z_replicate_loadf32 : z_replicate_load<f32, z_load>; +def z_replicate_loadf64 : z_replicate_load<f64, z_load>; // Byte-swapped replicated vector element loads. def z_replicate_loadbswapi16 : z_replicate_load<i32, z_loadbswap16>; def z_replicate_loadbswapi32 : z_replicate_load<i32, z_loadbswap32>; @@ -815,12 +917,12 @@ class z_vle<ValueType scalartype, SDPatternOperator load> : PatFrag<(ops node:$vec, node:$addr, node:$index), (z_vector_insert node:$vec, (scalartype (load node:$addr)), node:$index)>; -def z_vlei8 : z_vle<i32, anyextloadi8>; -def z_vlei16 : z_vle<i32, anyextloadi16>; -def z_vlei32 : z_vle<i32, load>; -def z_vlei64 : z_vle<i64, load>; -def z_vlef32 : z_vle<f32, load>; -def z_vlef64 : z_vle<f64, load>; +def z_vlei8 : z_vle<i32, z_anyextloadi8>; +def z_vlei16 : z_vle<i32, z_anyextloadi16>; +def z_vlei32 : z_vle<i32, z_load>; +def z_vlei64 : z_vle<i64, z_load>; +def z_vlef32 : z_vle<f32, z_load>; +def z_vlef64 : z_vle<f64, z_load>; // Byte-swapped vector element loads. def z_vlebri16 : z_vle<i32, z_loadbswap16>; def z_vlebri32 : z_vle<i32, z_loadbswap32>; @@ -832,13 +934,13 @@ class z_vllez<ValueType scalartype, SDPatternOperator load, int index> : PatFrag<(ops node:$addr), (z_vector_insert immAllZerosV, (scalartype (load node:$addr)), (i32 index))>; -def z_vllezi8 : z_vllez<i32, anyextloadi8, 7>; -def z_vllezi16 : z_vllez<i32, anyextloadi16, 3>; -def z_vllezi32 : z_vllez<i32, load, 1>; +def z_vllezi8 : z_vllez<i32, z_anyextloadi8, 7>; +def z_vllezi16 : z_vllez<i32, z_anyextloadi16, 3>; +def z_vllezi32 : z_vllez<i32, z_load, 1>; def z_vllezi64 : PatFrags<(ops node:$addr), [(z_vector_insert immAllZerosV, - (i64 (load node:$addr)), (i32 0)), - (z_join_dwords (i64 (load node:$addr)), (i64 0))]>; + (i64 (z_load node:$addr)), (i32 0)), + (z_join_dwords (i64 (z_load node:$addr)), (i64 0))]>; // We use high merges to form a v4f32 from four f32s. Propagating zero // into all elements but index 1 gives this expression. def z_vllezf32 : PatFrag<(ops node:$addr), @@ -848,23 +950,23 @@ def z_vllezf32 : PatFrag<(ops node:$addr), (v4i32 (bitconvert (v4f32 (scalar_to_vector - (f32 (load node:$addr)))))))), + (f32 (z_load node:$addr)))))))), (v2i64 (bitconvert (v4f32 immAllZerosV))))>; def z_vllezf64 : PatFrag<(ops node:$addr), (z_merge_high - (v2f64 (scalar_to_vector (f64 (load node:$addr)))), + (v2f64 (scalar_to_vector (f64 (z_load node:$addr)))), immAllZerosV)>; // Similarly for the high element of a zeroed vector. -def z_vllezli32 : z_vllez<i32, load, 0>; +def z_vllezli32 : z_vllez<i32, z_load, 0>; def z_vllezlf32 : PatFrag<(ops node:$addr), (z_merge_high (v2i64 (bitconvert (z_merge_high (v4f32 (scalar_to_vector - (f32 (load node:$addr)))), + (f32 (z_load node:$addr)))), (v4f32 immAllZerosV)))), (v2i64 (bitconvert (v4f32 immAllZerosV))))>; diff --git a/llvm/lib/Target/SystemZ/SystemZPatterns.td b/llvm/lib/Target/SystemZ/SystemZPatterns.td index 5e5dca77e9553b4954bcf96633da738d71b6936b..4d6bc68e9a7eddfe7994f008ffb5a42709985367 100644 --- a/llvm/lib/Target/SystemZ/SystemZPatterns.td +++ b/llvm/lib/Target/SystemZ/SystemZPatterns.td @@ -49,8 +49,8 @@ class RMWI<SDPatternOperator load, SDPatternOperator operator, // memory location. IMM is the type of the second operand. multiclass RMWIByte<SDPatternOperator operator, AddressingMode mode, Instruction insn> { - def : RMWI<anyextloadi8, operator, truncstorei8, mode, imm32, insn>; - def : RMWI<anyextloadi8, operator, truncstorei8, mode, imm64, insn>; + def : RMWI<z_anyextloadi8, operator, truncstorei8, mode, imm32, insn>; + def : RMWI<z_anyextloadi8, operator, truncstorei8, mode, imm64, insn>; } // Record that INSN performs insertion TYPE into a register of class CLS. diff --git a/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp b/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp index e4adb7be5649522ed0a549f518a3d0e1ed2259fe..5bdbaf47064d6c0596f2491428619dc4115c5500 100644 --- a/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp @@ -265,7 +265,7 @@ SystemZTTIImpl::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, return TTI::TCC_Free; break; case Intrinsic::experimental_patchpoint_void: - case Intrinsic::experimental_patchpoint_i64: + case Intrinsic::experimental_patchpoint: if ((Idx < 4) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue()))) return TTI::TCC_Free; break; diff --git a/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp b/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp index f9e30a3a9378a9b3f01657060e3c3731c0247a8b..691fe8fe3aa446238ab114c9d557f6dc7615370d 100644 --- a/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp +++ b/llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp @@ -344,7 +344,7 @@ public: return StringRef(Tok.Data, Tok.Length); } - unsigned getReg() const override { + MCRegister getReg() const override { assert((Kind == k_Register) && "Invalid access!"); return Reg.RegNum; } diff --git a/llvm/lib/Target/VE/VEInstrInfo.td b/llvm/lib/Target/VE/VEInstrInfo.td index 1e548d7c101a7a8f508ae46c589ccf609e959a8d..cbad5a0eafb27f2964d2cac8203970895ad60bf1 100644 --- a/llvm/lib/Target/VE/VEInstrInfo.td +++ b/llvm/lib/Target/VE/VEInstrInfo.td @@ -1785,14 +1785,14 @@ defm : TRUNC64m<truncstorei8, ST1Brri, ST1Brii, ST1Bzri, ST1Bzii>; defm : TRUNC64m<truncstorei16, ST2Brri, ST2Brii, ST2Bzri, ST2Bzii>; defm : TRUNC64m<truncstorei32, STLrri, STLrii, STLzri, ST1Bzii>; -// Atomic loads +// Atomic loads (FIXME: replace iAny with the correct integer VT:) multiclass ATMLDm<SDPatternOperator from, RM torri, RM torii, RM tozri, RM tozii> { - def : Pat<(from ADDRrri:$addr), (torri MEMrri:$addr)>; - def : Pat<(from ADDRrii:$addr), (torii MEMrii:$addr)>; - def : Pat<(from ADDRzri:$addr), (tozri MEMzri:$addr)>; - def : Pat<(from ADDRzii:$addr), (tozii MEMzii:$addr)>; + def : Pat<(iAny (from ADDRrri:$addr)), (torri MEMrri:$addr)>; + def : Pat<(iAny (from ADDRrii:$addr)), (torii MEMrii:$addr)>; + def : Pat<(iAny (from ADDRzri:$addr)), (tozri MEMzri:$addr)>; + def : Pat<(iAny (from ADDRzii:$addr)), (tozii MEMzii:$addr)>; } defm : ATMLDm<atomic_load_8, LD1BZXrri, LD1BZXrii, LD1BZXzri, LD1BZXzii>; defm : ATMLDm<atomic_load_16, LD2BZXrri, LD2BZXrii, LD2BZXzri, LD2BZXzii>; diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp index 3cc4d50271eb1142f4b7bd2cb6160e8af9d2a8a9..8e2063121e00b17921f352a67f1f4c99858df434 100644 --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -100,7 +100,7 @@ struct WebAssemblyOperand : public MCParsedAsmOperand { bool isReg() const override { return false; } bool isBrList() const { return Kind == BrList; } - unsigned getReg() const override { + MCRegister getReg() const override { llvm_unreachable("Assembly inspects a register operand"); return 0; } @@ -196,10 +196,6 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser { MCAsmParser &Parser; MCAsmLexer &Lexer; - // Much like WebAssemblyAsmPrinter in the backend, we have to own these. - std::vector<std::unique_ptr<wasm::WasmSignature>> Signatures; - std::vector<std::unique_ptr<std::string>> Names; - // Order of labels, directives and instructions in a .s file have no // syntactical enforcement. This class is a callback from the actual parser, // and yet we have to be feeding data to the streamer in a very particular @@ -287,16 +283,6 @@ public: return Parser.Error(Loc.isValid() ? Loc : Lexer.getTok().getLoc(), Msg); } - void addSignature(std::unique_ptr<wasm::WasmSignature> &&Sig) { - Signatures.push_back(std::move(Sig)); - } - - StringRef storeName(StringRef Name) { - std::unique_ptr<std::string> N = std::make_unique<std::string>(Name); - Names.push_back(std::move(N)); - return *Names.back(); - } - std::pair<StringRef, StringRef> nestingString(NestingType NT) { switch (NT) { case Function: @@ -640,21 +626,20 @@ public: // represent as a signature, such that we can re-build this signature, // attach it to an anonymous symbol, which is what WasmObjectWriter // expects to be able to recreate the actual unique-ified type indices. + auto &Ctx = getContext(); auto Loc = Parser.getTok(); - auto Signature = std::make_unique<wasm::WasmSignature>(); - if (parseSignature(Signature.get())) + auto Signature = Ctx.createWasmSignature(); + if (parseSignature(Signature)) return true; // Got signature as block type, don't need more - TC.setLastSig(*Signature.get()); + TC.setLastSig(*Signature); if (ExpectBlockType) - NestingStack.back().Sig = *Signature.get(); + NestingStack.back().Sig = *Signature; ExpectBlockType = false; - auto &Ctx = getContext(); // The "true" here will cause this to be a nameless symbol. MCSymbol *Sym = Ctx.createTempSymbol("typeindex", true); auto *WasmSym = cast<MCSymbolWasm>(Sym); - WasmSym->setSignature(Signature.get()); - addSignature(std::move(Signature)); + WasmSym->setSignature(Signature); WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); const MCExpr *Expr = MCSymbolRefExpr::create( WasmSym, MCSymbolRefExpr::VK_WASM_TYPEINDEX, Ctx); @@ -887,12 +872,11 @@ public: CurrentState = FunctionStart; LastFunctionLabel = WasmSym; } - auto Signature = std::make_unique<wasm::WasmSignature>(); - if (parseSignature(Signature.get())) + auto Signature = Ctx.createWasmSignature(); + if (parseSignature(Signature)) return ParseStatus::Failure; TC.funcDecl(*Signature); - WasmSym->setSignature(Signature.get()); - addSignature(std::move(Signature)); + WasmSym->setSignature(Signature); WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); TOut.emitFunctionType(WasmSym); // TODO: backend also calls TOut.emitIndIdx, but that is not implemented. @@ -909,7 +893,7 @@ public: if (ExportName.empty()) return ParseStatus::Failure; auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName)); - WasmSym->setExportName(storeName(ExportName)); + WasmSym->setExportName(Ctx.allocateString(ExportName)); TOut.emitExportName(WasmSym, ExportName); return expect(AsmToken::EndOfStatement, "EOL"); } @@ -924,7 +908,7 @@ public: if (ImportModule.empty()) return ParseStatus::Failure; auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName)); - WasmSym->setImportModule(storeName(ImportModule)); + WasmSym->setImportModule(Ctx.allocateString(ImportModule)); TOut.emitImportModule(WasmSym, ImportModule); return expect(AsmToken::EndOfStatement, "EOL"); } @@ -939,7 +923,7 @@ public: if (ImportName.empty()) return ParseStatus::Failure; auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName)); - WasmSym->setImportName(storeName(ImportName)); + WasmSym->setImportName(Ctx.allocateString(ImportName)); TOut.emitImportName(WasmSym, ImportName); return expect(AsmToken::EndOfStatement, "EOL"); } @@ -949,11 +933,10 @@ public: if (SymName.empty()) return ParseStatus::Failure; auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName)); - auto Signature = std::make_unique<wasm::WasmSignature>(); + auto Signature = Ctx.createWasmSignature(); if (parseRegTypeList(Signature->Params)) return ParseStatus::Failure; - WasmSym->setSignature(Signature.get()); - addSignature(std::move(Signature)); + WasmSym->setSignature(Signature); WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TAG); TOut.emitTagType(WasmSym); // TODO: backend also calls TOut.emitIndIdx, but that is not implemented. diff --git a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp index 86fb99cc98a9055bfda4423b324222ed313a6126..fac2e0d935f5abb0892e60b095c0dff7f02cfff2 100644 --- a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp +++ b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp @@ -63,7 +63,7 @@ wasm::ValType WebAssembly::toValType(MVT Type) { } void WebAssembly::wasmSymbolSetType(MCSymbolWasm *Sym, const Type *GlobalVT, - const ArrayRef<MVT> &VTs) { + ArrayRef<MVT> VTs) { assert(!Sym->getType()); // Tables are represented as Arrays in LLVM IR therefore diff --git a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h index a184ecb9a465a55f0741181cbb6e16d7fe14af06..87660947e7de1104d415a03feb700961bcc807a6 100644 --- a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h +++ b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h @@ -60,7 +60,7 @@ wasm::ValType toValType(MVT Type); /// Sets a Wasm Symbol Type. void wasmSymbolSetType(MCSymbolWasm *Sym, const Type *GlobalVT, - const ArrayRef<MVT> &VTs); + ArrayRef<MVT> VTs); } // end namespace WebAssembly } // end namespace llvm diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp index fb949d4b19a3e12a0e924e177d616232ea3c059d..3524abba8990aa37ad2c20318259c4f11feb4d1b 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -264,12 +264,12 @@ MCSymbol *WebAssemblyAsmPrinter::getOrCreateWasmSymbol(StringRef Name) { Params.push_back(AddrType); } else { // Function symbols WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); - getLibcallSignature(Subtarget, Name, Returns, Params); + WebAssembly::getLibcallSignature(Subtarget, Name, Returns, Params); } - auto Signature = std::make_unique<wasm::WasmSignature>(std::move(Returns), - std::move(Params)); - WasmSym->setSignature(Signature.get()); - addSignature(std::move(Signature)); + auto Signature = OutContext.createWasmSignature(); + Signature->Returns = std::move(Returns); + Signature->Params = std::move(Params); + WasmSym->setSignature(Signature); return WasmSym; } @@ -338,11 +338,11 @@ void WebAssemblyAsmPrinter::emitDecls(const Module &M) { // and thus also contain a signature, but we need to get the signature // anyway here in case it is an invoke that has not yet been created. We // will discard it later if it turns out not to be necessary. - auto Signature = signatureFromMVTs(Results, Params); + auto Signature = signatureFromMVTs(OutContext, Results, Params); bool InvokeDetected = false; auto *Sym = getMCSymbolForFunction( &F, WebAssembly::WasmEnableEmEH || WebAssembly::WasmEnableEmSjLj, - Signature.get(), InvokeDetected); + Signature, InvokeDetected); // Multiple functions can be mapped to the same invoke symbol. For // example, two IR functions '__invoke_void_i8*' and '__invoke_void_i32' @@ -353,11 +353,7 @@ void WebAssemblyAsmPrinter::emitDecls(const Module &M) { Sym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); if (!Sym->getSignature()) { - Sym->setSignature(Signature.get()); - addSignature(std::move(Signature)); - } else { - // This symbol has already been created and had a signature. Discard it. - Signature.reset(); + Sym->setSignature(Signature); } getTargetStreamer()->emitFunctionType(Sym); @@ -365,7 +361,7 @@ void WebAssemblyAsmPrinter::emitDecls(const Module &M) { if (F.hasFnAttribute("wasm-import-module")) { StringRef Name = F.getFnAttribute("wasm-import-module").getValueAsString(); - Sym->setImportModule(storeName(Name)); + Sym->setImportModule(OutContext.allocateString(Name)); getTargetStreamer()->emitImportModule(Sym, Name); } if (F.hasFnAttribute("wasm-import-name")) { @@ -375,14 +371,14 @@ void WebAssemblyAsmPrinter::emitDecls(const Module &M) { InvokeDetected ? Sym->getName() : F.getFnAttribute("wasm-import-name").getValueAsString(); - Sym->setImportName(storeName(Name)); + Sym->setImportName(OutContext.allocateString(Name)); getTargetStreamer()->emitImportName(Sym, Name); } if (F.hasFnAttribute("wasm-export-name")) { auto *Sym = cast<MCSymbolWasm>(getSymbol(&F)); StringRef Name = F.getFnAttribute("wasm-export-name").getValueAsString(); - Sym->setExportName(storeName(Name)); + Sym->setExportName(OutContext.allocateString(Name)); getTargetStreamer()->emitExportName(Sym, Name); } } @@ -618,10 +614,9 @@ void WebAssemblyAsmPrinter::emitFunctionBodyStart() { SmallVector<MVT, 4> ParamVTs; computeSignatureVTs(F.getFunctionType(), &F, F, TM, ParamVTs, ResultVTs); - auto Signature = signatureFromMVTs(ResultVTs, ParamVTs); + auto Signature = signatureFromMVTs(OutContext, ResultVTs, ParamVTs); auto *WasmSym = cast<MCSymbolWasm>(CurrentFnSym); - WasmSym->setSignature(Signature.get()); - addSignature(std::move(Signature)); + WasmSym->setSignature(Signature); WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); getTargetStreamer()->emitFunctionType(WasmSym); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h index c30e0155c81e720a1a572ec04e053047dd0ad319..6a544abe6ce8306c8b98810e205215baa2c921e5 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h @@ -22,17 +22,8 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyAsmPrinter final : public AsmPrinter { const WebAssemblySubtarget *Subtarget; const MachineRegisterInfo *MRI; WebAssemblyFunctionInfo *MFI; - // TODO: Do the uniquing of Signatures here instead of ObjectFileWriter? - std::vector<std::unique_ptr<wasm::WasmSignature>> Signatures; - std::vector<std::unique_ptr<std::string>> Names; bool signaturesEmitted = false; - StringRef storeName(StringRef Name) { - std::unique_ptr<std::string> N = std::make_unique<std::string>(Name); - Names.push_back(std::move(N)); - return *Names.back(); - } - public: explicit WebAssemblyAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer) @@ -44,9 +35,6 @@ public: } const WebAssemblySubtarget &getSubtarget() const { return *Subtarget; } - void addSignature(std::unique_ptr<wasm::WasmSignature> &&Sig) { - Signatures.push_back(std::move(Sig)); - } //===------------------------------------------------------------------===// // MachineFunctionPass Implementation. diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td index 8cd41d7017a023cf0e800d76957281f7ecb8900c..af95dfa25a189338ea72f95c412b4d062f8e7ebd 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td @@ -46,10 +46,12 @@ defm "" : ARGUMENT<V128, v2i64>; defm "" : ARGUMENT<V128, v4f32>; defm "" : ARGUMENT<V128, v2f64>; -// Constrained immediate argument types +// Constrained immediate argument types. Allow any value from the minimum signed +// value to the maximum unsigned value for the lane size. foreach SIZE = [8, 16] in def ImmI#SIZE : ImmLeaf<i32, - "return -(1 << ("#SIZE#" - 1)) <= Imm && Imm < (1 << ("#SIZE#" - 1));" + // -2^(n-1) <= Imm < 2^n + "return -(1 << ("#SIZE#" - 1)) <= Imm && Imm < (1 << "#SIZE#");" >; foreach SIZE = [2, 4, 8, 16, 32] in def LaneIdx#SIZE : ImmLeaf<i32, "return 0 <= Imm && Imm < "#SIZE#";">; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp index 77e6640d5a8224a00552efffa460dc9012ab0a16..027ee1086bf4e08bae41cac40125ead4347814d6 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp @@ -129,27 +129,23 @@ /// /// If there are calls to setjmp() /// -/// 2) In the function entry that calls setjmp, initialize setjmpTable and -/// sejmpTableSize as follows: -/// setjmpTableSize = 4; -/// setjmpTable = (int *) malloc(40); -/// setjmpTable[0] = 0; -/// setjmpTable and setjmpTableSize are used to call saveSetjmp() function in -/// Emscripten compiler-rt. +/// 2) In the function entry that calls setjmp, initialize +/// functionInvocationId as follows: +/// +/// functionInvocationId = alloca(4) +/// +/// Note: the alloca size is not important as this pointer is +/// merely used for pointer comparisions. /// /// 3) Lower /// setjmp(env) /// into -/// setjmpTable = saveSetjmp(env, label, setjmpTable, setjmpTableSize); -/// setjmpTableSize = getTempRet0(); -/// For each dynamic setjmp call, setjmpTable stores its ID (a number which -/// is incrementally assigned from 0) and its label (a unique number that -/// represents each callsite of setjmp). When we need more entries in -/// setjmpTable, it is reallocated in saveSetjmp() in Emscripten's -/// compiler-rt and it will return the new table address, and assign the new -/// table size in setTempRet0(). saveSetjmp also stores the setjmp's ID into -/// the buffer 'env'. A BB with setjmp is split into two after setjmp call in -/// order to make the post-setjmp BB the possible destination of longjmp BB. +/// __wasm_setjmp(env, label, functionInvocationId) +/// +/// __wasm_setjmp records the necessary info (the label and +/// functionInvocationId) to the "env". +/// A BB with setjmp is split into two after setjmp call in order to +/// make the post-setjmp BB the possible destination of longjmp BB. /// /// 4) Lower every call that might longjmp into /// __THREW__ = 0; @@ -158,8 +154,7 @@ /// __THREW__ = 0; /// %__threwValue.val = __threwValue; /// if (%__THREW__.val != 0 & %__threwValue.val != 0) { -/// %label = testSetjmp(mem[%__THREW__.val], setjmpTable, -/// setjmpTableSize); +/// %label = __wasm_setjmp_test(%__THREW__.val, functionInvocationId); /// if (%label == 0) /// emscripten_longjmp(%__THREW__.val, %__threwValue.val); /// setTempRet0(%__threwValue.val); @@ -173,16 +168,16 @@ /// ... /// default: goto splitted next BB /// } -/// testSetjmp examines setjmpTable to see if there is a matching setjmp -/// call. After calling an invoke wrapper, if a longjmp occurred, __THREW__ -/// will be the address of matching jmp_buf buffer and __threwValue be the -/// second argument to longjmp. mem[%__THREW__.val] is a setjmp ID that is -/// stored in saveSetjmp. testSetjmp returns a setjmp label, a unique ID to -/// each setjmp callsite. Label 0 means this longjmp buffer does not -/// correspond to one of the setjmp callsites in this function, so in this -/// case we just chain the longjmp to the caller. Label -1 means no longjmp -/// occurred. Otherwise we jump to the right post-setjmp BB based on the -/// label. +/// +/// __wasm_setjmp_test examines the jmp buf to see if it was for a matching +/// setjmp call. After calling an invoke wrapper, if a longjmp occurred, +/// __THREW__ will be the address of matching jmp_buf buffer and +/// __threwValue be the second argument to longjmp. +/// __wasm_setjmp_test returns a setjmp label, a unique ID to each setjmp +/// callsite. Label 0 means this longjmp buffer does not correspond to one +/// of the setjmp callsites in this function, so in this case we just chain +/// the longjmp to the caller. Label -1 means no longjmp occurred. +/// Otherwise we jump to the right post-setjmp BB based on the label. /// /// * Wasm setjmp / longjmp handling /// This mode still uses some Emscripten library functions but not JavaScript's @@ -199,45 +194,44 @@ /// If there are calls to setjmp() /// /// 2) and 3): The same as 2) and 3) in Emscripten SjLj. -/// (setjmpTable/setjmpTableSize initialization + setjmp callsite -/// transformation) +/// (functionInvocationId initialization + setjmp callsite transformation) /// /// 4) Create a catchpad with a wasm.catch() intrinsic, which returns the value -/// thrown by __wasm_longjmp function. In Emscripten library, we have this -/// struct: +/// thrown by __wasm_longjmp function. In the runtime library, we have an +/// equivalent of the following struct: /// /// struct __WasmLongjmpArgs { /// void *env; /// int val; /// }; -/// struct __WasmLongjmpArgs __wasm_longjmp_args; /// -/// The thrown value here is a pointer to __wasm_longjmp_args struct object. We -/// use this struct to transfer two values by throwing a single value. Wasm -/// throw and catch instructions are capable of throwing and catching multiple -/// values, but it also requires multivalue support that is currently not very -/// reliable. +/// The thrown value here is a pointer to the struct. We use this struct to +/// transfer two values by throwing a single value. Wasm throw and catch +/// instructions are capable of throwing and catching multiple values, but +/// it also requires multivalue support that is currently not very reliable. /// TODO Switch to throwing and catching two values without using the struct /// /// All longjmpable function calls will be converted to an invoke that will /// unwind to this catchpad in case a longjmp occurs. Within the catchpad, we -/// test the thrown values using testSetjmp function as we do for Emscripten -/// SjLj. The main difference is, in Emscripten SjLj, we need to transform every -/// longjmpable callsite into a sequence of code including testSetjmp() call; in -/// Wasm SjLj we do the testing in only one place, in this catchpad. +/// test the thrown values using __wasm_setjmp_test function as we do for +/// Emscripten SjLj. The main difference is, in Emscripten SjLj, we need to +/// transform every longjmpable callsite into a sequence of code including +/// __wasm_setjmp_test() call; in Wasm SjLj we do the testing in only one +/// place, in this catchpad. /// -/// After testing calling testSetjmp(), if the longjmp does not correspond to -/// one of the setjmps within the current function, it rethrows the longjmp -/// by calling __wasm_longjmp(). If it corresponds to one of setjmps in the -/// function, we jump to the beginning of the function, which contains a switch -/// to each post-setjmp BB. Again, in Emscripten SjLj, this switch is added for -/// every longjmpable callsite; in Wasm SjLj we do this only once at the top of -/// the function. (after setjmpTable/setjmpTableSize initialization) +/// After testing calling __wasm_setjmp_test(), if the longjmp does not +/// correspond to one of the setjmps within the current function, it rethrows +/// the longjmp by calling __wasm_longjmp(). If it corresponds to one of +/// setjmps in the function, we jump to the beginning of the function, which +/// contains a switch to each post-setjmp BB. Again, in Emscripten SjLj, this +/// switch is added for every longjmpable callsite; in Wasm SjLj we do this +/// only once at the top of the function. (after functionInvocationId +/// initialization) /// /// The below is the pseudocode for what we have described /// /// entry: -/// Initialize setjmpTable and setjmpTableSize +/// Initialize functionInvocationId /// /// setjmp.dispatch: /// switch %label { @@ -260,7 +254,7 @@ /// %longjmp.args = wasm.catch() ;; struct __WasmLongjmpArgs /// %env = load 'env' field from __WasmLongjmpArgs /// %val = load 'val' field from __WasmLongjmpArgs -/// %label = testSetjmp(mem[%env], setjmpTable, setjmpTableSize); +/// %label = __wasm_setjmp_test(%env, functionInvocationId); /// if (%label == 0) /// __wasm_longjmp(%env, %val) /// catchret to %setjmp.dispatch @@ -309,8 +303,8 @@ class WebAssemblyLowerEmscriptenEHSjLj final : public ModulePass { Function *ResumeF = nullptr; // __resumeException() (Emscripten) Function *EHTypeIDF = nullptr; // llvm.eh.typeid.for() (intrinsic) Function *EmLongjmpF = nullptr; // emscripten_longjmp() (Emscripten) - Function *SaveSetjmpF = nullptr; // saveSetjmp() (Emscripten) - Function *TestSetjmpF = nullptr; // testSetjmp() (Emscripten) + Function *WasmSetjmpF = nullptr; // __wasm_setjmp() (Emscripten) + Function *WasmSetjmpTestF = nullptr; // __wasm_setjmp_test() (Emscripten) Function *WasmLongjmpF = nullptr; // __wasm_longjmp() (Emscripten) Function *CatchF = nullptr; // wasm.catch() (intrinsic) @@ -335,18 +329,17 @@ class WebAssemblyLowerEmscriptenEHSjLj final : public ModulePass { bool runEHOnFunction(Function &F); bool runSjLjOnFunction(Function &F); void handleLongjmpableCallsForEmscriptenSjLj( - Function &F, InstVector &SetjmpTableInsts, - InstVector &SetjmpTableSizeInsts, + Function &F, Instruction *FunctionInvocationId, SmallVectorImpl<PHINode *> &SetjmpRetPHIs); void - handleLongjmpableCallsForWasmSjLj(Function &F, InstVector &SetjmpTableInsts, - InstVector &SetjmpTableSizeInsts, + handleLongjmpableCallsForWasmSjLj(Function &F, + Instruction *FunctionInvocationId, SmallVectorImpl<PHINode *> &SetjmpRetPHIs); Function *getFindMatchingCatch(Module &M, unsigned NumClauses); Value *wrapInvoke(CallBase *CI); void wrapTestSetjmp(BasicBlock *BB, DebugLoc DL, Value *Threw, - Value *SetjmpTable, Value *SetjmpTableSize, Value *&Label, + Value *FunctionInvocationId, Value *&Label, Value *&LongjmpResult, BasicBlock *&CallEmLongjmpBB, PHINode *&CallEmLongjmpBBThrewPHI, PHINode *&CallEmLongjmpBBThrewValuePHI, @@ -618,7 +611,7 @@ static bool canLongjmp(const Value *Callee) { // There are functions in Emscripten's JS glue code or compiler-rt if (CalleeName == "__resumeException" || CalleeName == "llvm_eh_typeid_for" || - CalleeName == "saveSetjmp" || CalleeName == "testSetjmp" || + CalleeName == "__wasm_setjmp" || CalleeName == "__wasm_setjmp_test" || CalleeName == "getTempRet0" || CalleeName == "setTempRet0") return false; @@ -687,11 +680,12 @@ static bool isEmAsmCall(const Value *Callee) { CalleeName == "emscripten_asm_const_async_on_main_thread"; } -// Generate testSetjmp function call seqence with preamble and postamble. -// The code this generates is equivalent to the following JavaScript code: +// Generate __wasm_setjmp_test function call seqence with preamble and +// postamble. The code this generates is equivalent to the following +// JavaScript code: // %__threwValue.val = __threwValue; // if (%__THREW__.val != 0 & %__threwValue.val != 0) { -// %label = testSetjmp(mem[%__THREW__.val], setjmpTable, setjmpTableSize); +// %label = __wasm_setjmp_test(%__THREW__.val, functionInvocationId); // if (%label == 0) // emscripten_longjmp(%__THREW__.val, %__threwValue.val); // setTempRet0(%__threwValue.val); @@ -703,10 +697,10 @@ static bool isEmAsmCall(const Value *Callee) { // As output parameters. returns %label, %longjmp_result, and the BB the last // instruction (%longjmp_result = ...) is in. void WebAssemblyLowerEmscriptenEHSjLj::wrapTestSetjmp( - BasicBlock *BB, DebugLoc DL, Value *Threw, Value *SetjmpTable, - Value *SetjmpTableSize, Value *&Label, Value *&LongjmpResult, - BasicBlock *&CallEmLongjmpBB, PHINode *&CallEmLongjmpBBThrewPHI, - PHINode *&CallEmLongjmpBBThrewValuePHI, BasicBlock *&EndBB) { + BasicBlock *BB, DebugLoc DL, Value *Threw, Value *FunctionInvocationId, + Value *&Label, Value *&LongjmpResult, BasicBlock *&CallEmLongjmpBB, + PHINode *&CallEmLongjmpBBThrewPHI, PHINode *&CallEmLongjmpBBThrewValuePHI, + BasicBlock *&EndBB) { Function *F = BB->getParent(); Module *M = F->getParent(); LLVMContext &C = M->getContext(); @@ -743,16 +737,14 @@ void WebAssemblyLowerEmscriptenEHSjLj::wrapTestSetjmp( CallEmLongjmpBBThrewValuePHI->addIncoming(ThrewValue, ThenBB1); } - // %label = testSetjmp(mem[%__THREW__.val], setjmpTable, setjmpTableSize); + // %label = __wasm_setjmp_test(%__THREW__.val, functionInvocationId); // if (%label == 0) IRB.SetInsertPoint(ThenBB1); BasicBlock *EndBB2 = BasicBlock::Create(C, "if.end2", F); Value *ThrewPtr = IRB.CreateIntToPtr(Threw, getAddrPtrType(M), Threw->getName() + ".p"); - Value *LoadedThrew = IRB.CreateLoad(getAddrIntType(M), ThrewPtr, - ThrewPtr->getName() + ".loaded"); - Value *ThenLabel = IRB.CreateCall( - TestSetjmpF, {LoadedThrew, SetjmpTable, SetjmpTableSize}, "label"); + Value *ThenLabel = IRB.CreateCall(WasmSetjmpTestF, + {ThrewPtr, FunctionInvocationId}, "label"); Value *Cmp2 = IRB.CreateICmpEQ(ThenLabel, IRB.getInt32(0)); IRB.CreateCondBr(Cmp2, CallEmLongjmpBB, EndBB2); @@ -1007,17 +999,17 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(Module &M) { Type *Int8PtrTy = IRB.getPtrTy(); Type *Int32PtrTy = IRB.getPtrTy(); Type *Int32Ty = IRB.getInt32Ty(); - // Register saveSetjmp function + + // Register __wasm_setjmp function FunctionType *SetjmpFTy = SetjmpF->getFunctionType(); FunctionType *FTy = FunctionType::get( - Int32PtrTy, - {SetjmpFTy->getParamType(0), Int32Ty, Int32PtrTy, Int32Ty}, false); - SaveSetjmpF = getEmscriptenFunction(FTy, "saveSetjmp", &M); + IRB.getVoidTy(), {SetjmpFTy->getParamType(0), Int32Ty, Int32PtrTy}, + false); + WasmSetjmpF = getEmscriptenFunction(FTy, "__wasm_setjmp", &M); - // Register testSetjmp function - FTy = FunctionType::get(Int32Ty, - {getAddrIntType(&M), Int32PtrTy, Int32Ty}, false); - TestSetjmpF = getEmscriptenFunction(FTy, "testSetjmp", &M); + // Register __wasm_setjmp_test function + FTy = FunctionType::get(Int32Ty, {Int32PtrTy, Int32PtrTy}, false); + WasmSetjmpTestF = getEmscriptenFunction(FTy, "__wasm_setjmp_test", &M); // wasm.catch() will be lowered down to wasm 'catch' instruction in // instruction selection. @@ -1063,7 +1055,7 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runOnModule(Module &M) { if (V && V->use_empty()) V->eraseFromParent(); for (auto *V : {GetTempRet0F, SetTempRet0F, ResumeF, EHTypeIDF, EmLongjmpF, - SaveSetjmpF, TestSetjmpF, WasmLongjmpF, CatchF}) + WasmSetjmpF, WasmSetjmpTestF, WasmLongjmpF, CatchF}) if (V && V->use_empty()) V->eraseFromParent(); @@ -1268,42 +1260,20 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(Function &F) { LLVMContext &C = F.getContext(); IRBuilder<> IRB(C); SmallVector<Instruction *, 64> ToErase; - // Vector of %setjmpTable values - SmallVector<Instruction *, 4> SetjmpTableInsts; - // Vector of %setjmpTableSize values - SmallVector<Instruction *, 4> SetjmpTableSizeInsts; // Setjmp preparation - // This instruction effectively means %setjmpTableSize = 4. - // We create this as an instruction intentionally, and we don't want to fold - // this instruction to a constant 4, because this value will be used in - // SSAUpdater.AddAvailableValue(...) later. BasicBlock *Entry = &F.getEntryBlock(); DebugLoc FirstDL = getOrCreateDebugLoc(&*Entry->begin(), F.getSubprogram()); SplitBlock(Entry, &*Entry->getFirstInsertionPt()); - BinaryOperator *SetjmpTableSize = - BinaryOperator::Create(Instruction::Add, IRB.getInt32(4), IRB.getInt32(0), - "setjmpTableSize", Entry->getTerminator()); - SetjmpTableSize->setDebugLoc(FirstDL); - // setjmpTable = (int *) malloc(40); - Type *IntPtrTy = getAddrIntType(&M); - Constant *size = ConstantInt::get(IntPtrTy, 40); - IRB.SetInsertPoint(SetjmpTableSize); - auto *SetjmpTable = IRB.CreateMalloc(IntPtrTy, IRB.getInt32Ty(), size, - nullptr, nullptr, "setjmpTable"); - SetjmpTable->setDebugLoc(FirstDL); - // CallInst::CreateMalloc may return a bitcast instruction if the result types - // mismatch. We need to set the debug loc for the original call too. - auto *MallocCall = SetjmpTable->stripPointerCasts(); - if (auto *MallocCallI = dyn_cast<Instruction>(MallocCall)) { - MallocCallI->setDebugLoc(FirstDL); - } - // setjmpTable[0] = 0; - IRB.CreateStore(IRB.getInt32(0), SetjmpTable); - SetjmpTableInsts.push_back(SetjmpTable); - SetjmpTableSizeInsts.push_back(SetjmpTableSize); + IRB.SetInsertPoint(Entry->getTerminator()->getIterator()); + // This alloca'ed pointer is used by the runtime to identify function + // invocations. It's just for pointer comparisons. It will never be + // dereferenced. + Instruction *FunctionInvocationId = + IRB.CreateAlloca(IRB.getInt32Ty(), nullptr, "functionInvocationId"); + FunctionInvocationId->setDebugLoc(FirstDL); // Setjmp transformation SmallVector<PHINode *, 4> SetjmpRetPHIs; @@ -1350,92 +1320,22 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(Function &F) { // 0, because index 0 means the longjmp is not ours to handle. IRB.SetInsertPoint(CI); Value *Args[] = {CI->getArgOperand(0), IRB.getInt32(SetjmpRetPHIs.size()), - SetjmpTable, SetjmpTableSize}; - Instruction *NewSetjmpTable = - IRB.CreateCall(SaveSetjmpF, Args, "setjmpTable"); - Instruction *NewSetjmpTableSize = - IRB.CreateCall(GetTempRet0F, std::nullopt, "setjmpTableSize"); - SetjmpTableInsts.push_back(NewSetjmpTable); - SetjmpTableSizeInsts.push_back(NewSetjmpTableSize); + FunctionInvocationId}; + IRB.CreateCall(WasmSetjmpF, Args); ToErase.push_back(CI); } // Handle longjmpable calls. if (EnableEmSjLj) - handleLongjmpableCallsForEmscriptenSjLj( - F, SetjmpTableInsts, SetjmpTableSizeInsts, SetjmpRetPHIs); + handleLongjmpableCallsForEmscriptenSjLj(F, FunctionInvocationId, + SetjmpRetPHIs); else // EnableWasmSjLj - handleLongjmpableCallsForWasmSjLj(F, SetjmpTableInsts, SetjmpTableSizeInsts, - SetjmpRetPHIs); + handleLongjmpableCallsForWasmSjLj(F, FunctionInvocationId, SetjmpRetPHIs); // Erase everything we no longer need in this function for (Instruction *I : ToErase) I->eraseFromParent(); - // Free setjmpTable buffer before each return instruction + function-exiting - // call - SmallVector<Instruction *, 16> ExitingInsts; - for (BasicBlock &BB : F) { - Instruction *TI = BB.getTerminator(); - if (isa<ReturnInst>(TI)) - ExitingInsts.push_back(TI); - // Any 'call' instruction with 'noreturn' attribute exits the function at - // this point. If this throws but unwinds to another EH pad within this - // function instead of exiting, this would have been an 'invoke', which - // happens if we use Wasm EH or Wasm SjLJ. - for (auto &I : BB) { - if (auto *CI = dyn_cast<CallInst>(&I)) { - bool IsNoReturn = CI->hasFnAttr(Attribute::NoReturn); - if (Function *CalleeF = CI->getCalledFunction()) - IsNoReturn |= CalleeF->hasFnAttribute(Attribute::NoReturn); - if (IsNoReturn) - ExitingInsts.push_back(&I); - } - } - } - for (auto *I : ExitingInsts) { - DebugLoc DL = getOrCreateDebugLoc(I, F.getSubprogram()); - // If this existing instruction is a call within a catchpad, we should add - // it as "funclet" to the operand bundle of 'free' call - SmallVector<OperandBundleDef, 1> Bundles; - if (auto *CB = dyn_cast<CallBase>(I)) - if (auto Bundle = CB->getOperandBundle(LLVMContext::OB_funclet)) - Bundles.push_back(OperandBundleDef(*Bundle)); - IRB.SetInsertPoint(I); - auto *Free = IRB.CreateFree(SetjmpTable, Bundles); - Free->setDebugLoc(DL); - } - - // Every call to saveSetjmp can change setjmpTable and setjmpTableSize - // (when buffer reallocation occurs) - // entry: - // setjmpTableSize = 4; - // setjmpTable = (int *) malloc(40); - // setjmpTable[0] = 0; - // ... - // somebb: - // setjmpTable = saveSetjmp(env, label, setjmpTable, setjmpTableSize); - // setjmpTableSize = getTempRet0(); - // So we need to make sure the SSA for these variables is valid so that every - // saveSetjmp and testSetjmp calls have the correct arguments. - SSAUpdater SetjmpTableSSA; - SSAUpdater SetjmpTableSizeSSA; - SetjmpTableSSA.Initialize(PointerType::get(C, 0), "setjmpTable"); - SetjmpTableSizeSSA.Initialize(Type::getInt32Ty(C), "setjmpTableSize"); - for (Instruction *I : SetjmpTableInsts) - SetjmpTableSSA.AddAvailableValue(I->getParent(), I); - for (Instruction *I : SetjmpTableSizeInsts) - SetjmpTableSizeSSA.AddAvailableValue(I->getParent(), I); - - for (auto &U : make_early_inc_range(SetjmpTable->uses())) - if (auto *I = dyn_cast<Instruction>(U.getUser())) - if (I->getParent() != Entry) - SetjmpTableSSA.RewriteUse(U); - for (auto &U : make_early_inc_range(SetjmpTableSize->uses())) - if (auto *I = dyn_cast<Instruction>(U.getUser())) - if (I->getParent() != Entry) - SetjmpTableSizeSSA.RewriteUse(U); - // Finally, our modifications to the cfg can break dominance of SSA variables. // For example, in this code, // if (x()) { .. setjmp() .. } @@ -1454,21 +1354,13 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(Function &F) { // setjmp. Refer to 4) of "Emscripten setjmp/longjmp handling" section in the // comments at top of the file for details. void WebAssemblyLowerEmscriptenEHSjLj::handleLongjmpableCallsForEmscriptenSjLj( - Function &F, InstVector &SetjmpTableInsts, InstVector &SetjmpTableSizeInsts, + Function &F, Instruction *FunctionInvocationId, SmallVectorImpl<PHINode *> &SetjmpRetPHIs) { Module &M = *F.getParent(); LLVMContext &C = F.getContext(); IRBuilder<> IRB(C); SmallVector<Instruction *, 64> ToErase; - // We need to pass setjmpTable and setjmpTableSize to testSetjmp function. - // These values are defined in the beginning of the function and also in each - // setjmp callsite, but we don't know which values we should use at this - // point. So here we arbitraily use the ones defined in the beginning of the - // function, and SSAUpdater will later update them to the correct values. - Instruction *SetjmpTable = *SetjmpTableInsts.begin(); - Instruction *SetjmpTableSize = *SetjmpTableSizeInsts.begin(); - // call.em.longjmp BB that will be shared within the function. BasicBlock *CallEmLongjmpBB = nullptr; // PHI node for the loaded value of __THREW__ global variable in @@ -1601,7 +1493,7 @@ void WebAssemblyLowerEmscriptenEHSjLj::handleLongjmpableCallsForEmscriptenSjLj( IRB.SetInsertPoint(NormalBB); IRB.CreateBr(Tail); - BB = NormalBB; // New insertion point to insert testSetjmp() + BB = NormalBB; // New insertion point to insert __wasm_setjmp_test() } } @@ -1610,16 +1502,15 @@ void WebAssemblyLowerEmscriptenEHSjLj::handleLongjmpableCallsForEmscriptenSjLj( // right setjmp-tail if so ToErase.push_back(BB->getTerminator()); - // Generate a function call to testSetjmp function and preamble/postamble - // code to figure out (1) whether longjmp occurred (2) if longjmp - // occurred, which setjmp it corresponds to + // Generate a function call to __wasm_setjmp_test function and + // preamble/postamble code to figure out (1) whether longjmp + // occurred (2) if longjmp occurred, which setjmp it corresponds to Value *Label = nullptr; Value *LongjmpResult = nullptr; BasicBlock *EndBB = nullptr; - wrapTestSetjmp(BB, CI->getDebugLoc(), Threw, SetjmpTable, SetjmpTableSize, - Label, LongjmpResult, CallEmLongjmpBB, - CallEmLongjmpBBThrewPHI, CallEmLongjmpBBThrewValuePHI, - EndBB); + wrapTestSetjmp(BB, CI->getDebugLoc(), Threw, FunctionInvocationId, Label, + LongjmpResult, CallEmLongjmpBB, CallEmLongjmpBBThrewPHI, + CallEmLongjmpBBThrewValuePHI, EndBB); assert(Label && LongjmpResult && EndBB); // Create switch instruction @@ -1658,7 +1549,7 @@ static BasicBlock *getCleanupRetUnwindDest(const CleanupPadInst *CPI) { // BBs. Refer to 4) of "Wasm setjmp/longjmp handling" section in the comments at // top of the file for details. void WebAssemblyLowerEmscriptenEHSjLj::handleLongjmpableCallsForWasmSjLj( - Function &F, InstVector &SetjmpTableInsts, InstVector &SetjmpTableSizeInsts, + Function &F, Instruction *FunctionInvocationId, SmallVectorImpl<PHINode *> &SetjmpRetPHIs) { Module &M = *F.getParent(); LLVMContext &C = F.getContext(); @@ -1682,18 +1573,13 @@ void WebAssemblyLowerEmscriptenEHSjLj::handleLongjmpableCallsForWasmSjLj( DebugLoc FirstDL = getOrCreateDebugLoc(&*Entry->begin(), F.getSubprogram()); IRB.SetCurrentDebugLocation(FirstDL); - // Arbitrarily use the ones defined in the beginning of the function. - // SSAUpdater will later update them to the correct values. - Instruction *SetjmpTable = *SetjmpTableInsts.begin(); - Instruction *SetjmpTableSize = *SetjmpTableSizeInsts.begin(); - // Add setjmp.dispatch BB right after the entry block. Because we have - // initialized setjmpTable/setjmpTableSize in the entry block and split the + // initialized functionInvocationId in the entry block and split the // rest into another BB, here 'OrigEntry' is the function's original entry // block before the transformation. // // entry: - // setjmpTable / setjmpTableSize initialization + // functionInvocationId initialization // setjmp.dispatch: // switch will be inserted here later // entry.split: (OrigEntry) @@ -1731,17 +1617,15 @@ void WebAssemblyLowerEmscriptenEHSjLj::handleLongjmpableCallsForWasmSjLj( // int val = __wasm_longjmp_args.val; Instruction *Val = IRB.CreateLoad(IRB.getInt32Ty(), ValField, "val"); - // %label = testSetjmp(mem[%env], setjmpTable, setjmpTableSize); + // %label = __wasm_setjmp_test(%env, functionInvocatinoId); // if (%label == 0) // __wasm_longjmp(%env, %val) // catchret to %setjmp.dispatch BasicBlock *ThenBB = BasicBlock::Create(C, "if.then", &F); BasicBlock *EndBB = BasicBlock::Create(C, "if.end", &F); Value *EnvP = IRB.CreateBitCast(Env, getAddrPtrType(&M), "env.p"); - Value *SetjmpID = IRB.CreateLoad(getAddrIntType(&M), EnvP, "setjmp.id"); - Value *Label = - IRB.CreateCall(TestSetjmpF, {SetjmpID, SetjmpTable, SetjmpTableSize}, - OperandBundleDef("funclet", CatchPad), "label"); + Value *Label = IRB.CreateCall(WasmSetjmpTestF, {EnvP, FunctionInvocationId}, + OperandBundleDef("funclet", CatchPad), "label"); Value *Cmp = IRB.CreateICmpEQ(Label, IRB.getInt32(0)); IRB.CreateCondBr(Cmp, ThenBB, EndBB); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerRefTypesIntPtrConv.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerRefTypesIntPtrConv.cpp index e0a21921122858184ca03f02c6bfec4025435a66..2594430d1d8f3a9d6d01dbfc421887b038a72c95 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerRefTypesIntPtrConv.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerRefTypesIntPtrConv.cpp @@ -73,7 +73,7 @@ bool WebAssemblyLowerRefTypesIntPtrConv::runOnFunction(Function &F) { Function *TrapIntrin = Intrinsic::getDeclaration(F.getParent(), Intrinsic::debugtrap); - CallInst::Create(TrapIntrin, {}, "", &*I); + CallInst::Create(TrapIntrin, {}, "", I->getIterator()); worklist.insert(&*I); } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp index f6e24f7aaece014730df5e1ee9399bb52d8d7615..431dc7f33ac89f0825455eae11317a9b4a15a1b8 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp @@ -73,14 +73,13 @@ WebAssemblyMCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const { SmallVector<MVT, 4> ParamMVTs; const auto *const F = dyn_cast<Function>(Global); computeSignatureVTs(FuncTy, F, CurrentFunc, TM, ParamMVTs, ResultMVTs); - auto Signature = signatureFromMVTs(ResultMVTs, ParamMVTs); + auto Signature = signatureFromMVTs(Ctx, ResultMVTs, ParamMVTs); bool InvokeDetected = false; auto *WasmSym = Printer.getMCSymbolForFunction( F, WebAssembly::WasmEnableEmEH || WebAssembly::WasmEnableEmSjLj, - Signature.get(), InvokeDetected); - WasmSym->setSignature(Signature.get()); - Printer.addSignature(std::move(Signature)); + Signature, InvokeDetected); + WasmSym->setSignature(Signature); WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); return WasmSym; } @@ -142,12 +141,12 @@ MCOperand WebAssemblyMCInstLower::lowerSymbolOperand(const MachineOperand &MO, MCOperand WebAssemblyMCInstLower::lowerTypeIndexOperand( SmallVectorImpl<wasm::ValType> &&Returns, SmallVectorImpl<wasm::ValType> &&Params) const { - auto Signature = std::make_unique<wasm::WasmSignature>(std::move(Returns), - std::move(Params)); + auto Signature = Ctx.createWasmSignature(); + Signature->Returns = std::move(Returns); + Signature->Params = std::move(Params); MCSymbol *Sym = Printer.createTempSymbol("typeindex"); auto *WasmSym = cast<MCSymbolWasm>(Sym); - WasmSym->setSignature(Signature.get()); - Printer.addSignature(std::move(Signature)); + WasmSym->setSignature(Signature); WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); const MCExpr *Expr = MCSymbolRefExpr::create(WasmSym, MCSymbolRefExpr::VK_WASM_TYPEINDEX, Ctx); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp index 1e959111a4dbcb5215c7a2be61433ada005d80af..6f4e7d876c693e4b2ed0814c1ae09b689929a92f 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.cpp @@ -105,16 +105,16 @@ void llvm::computeSignatureVTs(const FunctionType *Ty, } } -void llvm::valTypesFromMVTs(const ArrayRef<MVT> &In, +void llvm::valTypesFromMVTs(ArrayRef<MVT> In, SmallVectorImpl<wasm::ValType> &Out) { for (MVT Ty : In) Out.push_back(WebAssembly::toValType(Ty)); } -std::unique_ptr<wasm::WasmSignature> -llvm::signatureFromMVTs(const SmallVectorImpl<MVT> &Results, +wasm::WasmSignature * +llvm::signatureFromMVTs(MCContext &Ctx, const SmallVectorImpl<MVT> &Results, const SmallVectorImpl<MVT> &Params) { - auto Sig = std::make_unique<wasm::WasmSignature>(); + auto Sig = Ctx.createWasmSignature(); valTypesFromMVTs(Results, Sig->Returns); valTypesFromMVTs(Params, Sig->Params); return Sig; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h index fe18347ad8c1da3835ef625ccc1d200a962d07ef..6c9824bbd5d917f0f2903a7cb91391e470faf781 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyMachineFunctionInfo.h @@ -169,12 +169,11 @@ void computeSignatureVTs(const FunctionType *Ty, const Function *TargetFunc, SmallVectorImpl<MVT> &Params, SmallVectorImpl<MVT> &Results); -void valTypesFromMVTs(const ArrayRef<MVT> &In, - SmallVectorImpl<wasm::ValType> &Out); +void valTypesFromMVTs(ArrayRef<MVT> In, SmallVectorImpl<wasm::ValType> &Out); -std::unique_ptr<wasm::WasmSignature> -signatureFromMVTs(const SmallVectorImpl<MVT> &Results, - const SmallVectorImpl<MVT> &Params); +wasm::WasmSignature *signatureFromMVTs(MCContext &Ctx, + const SmallVectorImpl<MVT> &Results, + const SmallVectorImpl<MVT> &Params); namespace yaml { diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegColoring.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegColoring.cpp index c9ef17f928144d4f463dddcc936f50a0a81813de..acd984f2f8f882a9ce4bf96fecd74c1f7c6c863d 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyRegColoring.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegColoring.cpp @@ -129,7 +129,7 @@ buildVRegToDbgValueMap(MachineFunction &MF, const LiveIntervals *Liveness) { // changes. static void undefInvalidDbgValues( const LiveIntervals *Liveness, - const ArrayRef<SmallVector<LiveInterval *, 4>> &Assignments, + ArrayRef<SmallVector<LiveInterval *, 4>> Assignments, DenseMap<Register, std::vector<std::pair<SlotIndex, MachineInstr *>>> &DbgVRegToValues) { #ifndef NDEBUG diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp index 3e2e029695ab6fa716e04d26c79ab1876b867744..1896ac631d96e53417fc318aaec2459c84038fac 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp @@ -524,10 +524,10 @@ struct StaticLibcallNameMap { } // end anonymous namespace -void llvm::getLibcallSignature(const WebAssemblySubtarget &Subtarget, - RTLIB::Libcall LC, - SmallVectorImpl<wasm::ValType> &Rets, - SmallVectorImpl<wasm::ValType> &Params) { +void WebAssembly::getLibcallSignature(const WebAssemblySubtarget &Subtarget, + RTLIB::Libcall LC, + SmallVectorImpl<wasm::ValType> &Rets, + SmallVectorImpl<wasm::ValType> &Params) { assert(Rets.empty()); assert(Params.empty()); @@ -889,10 +889,10 @@ void llvm::getLibcallSignature(const WebAssemblySubtarget &Subtarget, // TODO: If the RTLIB::Libcall-taking flavor of GetSignature remains unused // other than here, just roll its logic into this version. -void llvm::getLibcallSignature(const WebAssemblySubtarget &Subtarget, - StringRef Name, - SmallVectorImpl<wasm::ValType> &Rets, - SmallVectorImpl<wasm::ValType> &Params) { +void WebAssembly::getLibcallSignature(const WebAssemblySubtarget &Subtarget, + StringRef Name, + SmallVectorImpl<wasm::ValType> &Rets, + SmallVectorImpl<wasm::ValType> &Params) { static StaticLibcallNameMap LibcallNameMap; auto &Map = LibcallNameMap.Map; auto Val = Map.find(Name); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.h b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.h index f7a94aa20bd463f864e2c136168744ce60b0e397..ff6515d5bf4e67608585938c66e62fd26e43163e 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.h @@ -22,16 +22,18 @@ namespace llvm { class WebAssemblySubtarget; -extern void getLibcallSignature(const WebAssemblySubtarget &Subtarget, - RTLIB::Libcall LC, - SmallVectorImpl<wasm::ValType> &Rets, - SmallVectorImpl<wasm::ValType> &Params); +namespace WebAssembly { -extern void getLibcallSignature(const WebAssemblySubtarget &Subtarget, - StringRef Name, - SmallVectorImpl<wasm::ValType> &Rets, - SmallVectorImpl<wasm::ValType> &Params); +void getLibcallSignature(const WebAssemblySubtarget &Subtarget, + RTLIB::Libcall LC, + SmallVectorImpl<wasm::ValType> &Rets, + SmallVectorImpl<wasm::ValType> &Params); +void getLibcallSignature(const WebAssemblySubtarget &Subtarget, StringRef Name, + SmallVectorImpl<wasm::ValType> &Rets, + SmallVectorImpl<wasm::ValType> &Params); + +} // end namespace WebAssembly } // end namespace llvm #endif diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index e3701d69934c087f1319714a8d871ab1cfffa90c..6401df9f49f033be320895786b95e855eb613928 100644 --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -4068,7 +4068,7 @@ unsigned X86AsmParser::checkTargetMatchPredicate(MCInst &Inst) { if (UseApxExtendedReg && !X86II::canUseApxExtendedReg(MCID)) return Match_Unsupported; - if (ForcedNoFlag != !!(MCID.TSFlags & X86II::EVEX_NF)) + if (ForcedNoFlag == !(MCID.TSFlags & X86II::EVEX_NF) && !X86::isCFCMOVCC(Opc)) return Match_Unsupported; if (ForcedVEXEncoding == VEXEncoding_EVEX && diff --git a/llvm/lib/Target/X86/AsmParser/X86Operand.h b/llvm/lib/Target/X86/AsmParser/X86Operand.h index 641158cb351fc4f1dfcff2e51cf33f37a4dafcc7..78669784dd035b5df4ac8cab0df21724c2d799e6 100644 --- a/llvm/lib/Target/X86/AsmParser/X86Operand.h +++ b/llvm/lib/Target/X86/AsmParser/X86Operand.h @@ -167,7 +167,7 @@ struct X86Operand final : public MCParsedAsmOperand { Tok.Length = Value.size(); } - unsigned getReg() const override { + MCRegister getReg() const override { assert(Kind == Register && "Invalid access!"); return Reg.RegNo; } diff --git a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp index 8e0f61a855661b3dba7c6650fd49f6ed36882b54..9be3812300af12e4ee28ad1b58e0aee4c3404193 100644 --- a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp +++ b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp @@ -119,8 +119,6 @@ private: MachineFunction &MF) const; bool selectSelect(MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) const; - bool selectIntrinsicWSideEffects(MachineInstr &I, MachineRegisterInfo &MRI, - MachineFunction &MF) const; // emit insert subreg instruction and insert it before MachineInstr &I bool emitInsertSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I, @@ -434,8 +432,6 @@ bool X86InstructionSelector::select(MachineInstr &I) { return selectMulDivRem(I, MRI, MF); case TargetOpcode::G_SELECT: return selectSelect(I, MRI, MF); - case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: - return selectIntrinsicWSideEffects(I, MRI, MF); } return false; @@ -1834,21 +1830,6 @@ bool X86InstructionSelector::selectSelect(MachineInstr &I, return true; } -bool X86InstructionSelector::selectIntrinsicWSideEffects( - MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) const { - - assert(I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS && - "unexpected instruction"); - - if (I.getOperand(0).getIntrinsicID() != Intrinsic::trap) - return false; - - BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::TRAP)); - - I.eraseFromParent(); - return true; -} - InstructionSelector * llvm::createX86InstructionSelector(const X86TargetMachine &TM, X86Subtarget &Subtarget, diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp index 06389842ebb1ed848fedd0a5de5a2eef7c9ee335..07041cc5b0491c46f1330942f098d452cb21486d 100644 --- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp +++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp @@ -259,8 +259,7 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI, getActionDefinitionsBuilder(G_ICMP) .legalForCartesianProduct({s8}, Is64Bit ? IntTypes64 : IntTypes32) .clampScalar(0, s8, s8) - .clampScalar(1, s8, sMaxScalar) - .scalarSameSizeAs(2, 1); + .clampScalar(1, s8, sMaxScalar); // bswap getActionDefinitionsBuilder(G_BSWAP) diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h index 65b8ebc0b9b994ec61c7a47467caf6cf5366a69e..c0a75e215a40b515c372266e4fb312df52661128 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h +++ b/llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h @@ -545,6 +545,14 @@ enum : uint64_t { /// PrefixByte - This form is used for instructions that represent a prefix /// byte like data16 or rep. PrefixByte = 10, + /// MRMDestRegCC - This form is used for the cfcmov instructions, which use + /// the Mod/RM byte to specify the operands reg(r/m) and reg(reg) and also + /// encodes a condition code. + MRMDestRegCC = 18, + /// MRMDestMemCC - This form is used for the cfcmov instructions, which use + /// the Mod/RM byte to specify the operands mem(r/m) and reg(reg) and also + /// encodes a condition code. + MRMDestMemCC = 19, /// MRMDestMem4VOp3CC - This form is used for instructions that use the Mod/RM /// byte to specify a destination which in this case is memory and operand 3 /// with VEX.VVVV, and also encodes a condition code. @@ -1032,6 +1040,7 @@ inline int getMemoryOperandNo(uint64_t TSFlags) { return -1; case X86II::MRMDestMem: case X86II::MRMDestMemFSIB: + case X86II::MRMDestMemCC: return hasNewDataDest(TSFlags); case X86II::MRMSrcMem: case X86II::MRMSrcMemFSIB: @@ -1045,11 +1054,13 @@ inline int getMemoryOperandNo(uint64_t TSFlags) { // Skip registers encoded in reg, VEX_VVVV, and I8IMM. return 3; case X86II::MRMSrcMemCC: + return 1 + hasNewDataDest(TSFlags); case X86II::MRMDestMem4VOp3CC: // Start from 1, skip any registers encoded in VEX_VVVV or I8IMM, or a // mask register. return 1; case X86II::MRMDestReg: + case X86II::MRMDestRegCC: case X86II::MRMSrcReg: case X86II::MRMSrcReg4VOp3: case X86II::MRMSrcRegOp4: diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86InstPrinterCommon.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86InstPrinterCommon.cpp index 29a1866bf01ab03516485754da8f76b357890092..21c1556d1d8ed21de8ea9ffd7d5dbc45b52c1d81 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86InstPrinterCommon.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86InstPrinterCommon.cpp @@ -394,7 +394,7 @@ void X86InstPrinterCommon::printInstFlags(const MCInst *MI, raw_ostream &O, else if (Flags & X86::IP_HAS_REPEAT) O << "\trep\t"; - if (TSFlags & X86II::EVEX_NF) + if (TSFlags & X86II::EVEX_NF && !X86::isCFCMOVCC(MI->getOpcode())) O << "\t{nf}"; // These all require a pseudo prefix diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index dcd0551b7b765365153482355c21fecdf2c19c81..92a14226a0dc051e6bd0a510838f1d730160d5de 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -1071,6 +1071,7 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI, case X86II::MRM_C0: case X86II::RawFrm: break; + case X86II::MRMDestMemCC: case X86II::MRMDestMemFSIB: case X86II::MRMDestMem: { // MRMDestMem instructions forms: @@ -1102,6 +1103,7 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI, } break; } + case X86II::MRMSrcMemCC: case X86II::MRMSrcMemFSIB: case X86II::MRMSrcMem: { // MRMSrcMem instructions forms: @@ -1180,6 +1182,7 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI, } break; } + case X86II::MRMSrcRegCC: case X86II::MRMSrcReg: { // MRMSrcReg instructions forms: // dst(ModR/M), src1(VEX_4V), src2(ModR/M), src3(Imm[7:4]) @@ -1242,6 +1245,7 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI, ++CurOp; break; } + case X86II::MRMDestRegCC: case X86II::MRMDestReg: { // MRMDestReg instructions forms: // dst(ModR/M), src(ModR/M) @@ -1638,6 +1642,15 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, CurOp = SrcRegNum + 1; break; } + case X86II::MRMDestRegCC: { + unsigned FirstOp = CurOp++; + unsigned SecondOp = CurOp++; + unsigned CC = MI.getOperand(CurOp++).getImm(); + emitByte(BaseOpcode + CC, CB); + emitRegModRMByte(MI.getOperand(FirstOp), + getX86RegNum(MI.getOperand(SecondOp)), CB); + break; + } case X86II::MRMDestMem4VOp3CC: { unsigned CC = MI.getOperand(8).getImm(); emitByte(BaseOpcode + CC, CB); @@ -1667,6 +1680,16 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, CurOp = SrcRegNum + 1; break; } + case X86II::MRMDestMemCC: { + unsigned MemOp = CurOp; + CurOp = MemOp + X86::AddrNumOperands; + unsigned RegOp = CurOp++; + unsigned CC = MI.getOperand(CurOp++).getImm(); + emitByte(BaseOpcode + CC, CB); + emitMemModRMByte(MI, MemOp, getX86RegNum(MI.getOperand(RegOp)), TSFlags, + Kind, StartByte, CB, Fixups, STI); + break; + } case X86II::MRMSrcReg: { emitByte(BaseOpcode, CB); unsigned SrcRegNum = CurOp + 1; @@ -1717,6 +1740,8 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, break; } case X86II::MRMSrcRegCC: { + if (IsND) // Skip new data destination + ++CurOp; unsigned FirstOp = CurOp++; unsigned SecondOp = CurOp++; @@ -1778,6 +1803,8 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI, break; } case X86II::MRMSrcMemCC: { + if (IsND) // Skip new data destination + ++CurOp; unsigned RegOp = CurOp++; unsigned FirstMemOp = CurOp; CurOp = FirstMemOp + X86::AddrNumOperands; diff --git a/llvm/lib/Target/X86/X86.td b/llvm/lib/Target/X86/X86.td index 8367f938c0ddfae2b33f7bf902e3812a7b113c62..78bc043911f2fc7573d3f26f734e3d3ccec821ff 100644 --- a/llvm/lib/Target/X86/X86.td +++ b/llvm/lib/Target/X86/X86.td @@ -683,6 +683,12 @@ def TuningFastGather : SubtargetFeature<"fast-gather", "HasFastGather", "true", "Indicates if gather is reasonably fast (this is true for Skylake client and all AVX-512 CPUs)">; +// Generate vpdpwssd instead of vpmaddwd+vpaddd sequence. +def TuningFastDPWSSD + : SubtargetFeature< + "fast-dpwssd", "HasFastDPWSSD", "true", + "Prefer vpdpwssd instruction over vpmaddwd+vpaddd instruction sequence">; + def TuningPreferNoGather : SubtargetFeature<"prefer-no-gather", "PreferGather", "false", "Prefer no gather instructions">; @@ -1502,7 +1508,11 @@ def ProcessorFeatures { !listconcat(ZN2Tuning, ZN3AdditionalTuning); list<SubtargetFeature> ZN3Features = !listconcat(ZN2Features, ZN3AdditionalFeatures); - list<SubtargetFeature> ZN4Tuning = ZN3Tuning; + + + list<SubtargetFeature> ZN4AdditionalTuning = [TuningFastDPWSSD]; + list<SubtargetFeature> ZN4Tuning = + !listconcat(ZN3Tuning, ZN4AdditionalTuning); list<SubtargetFeature> ZN4AdditionalFeatures = [FeatureAVX512, FeatureEVEX512, FeatureCDI, diff --git a/llvm/lib/Target/X86/X86AvoidStoreForwardingBlocks.cpp b/llvm/lib/Target/X86/X86AvoidStoreForwardingBlocks.cpp index 04931afdec51c3e4dee3ee43da7a1a6a0efb116d..a72eeb53915d65eea9a42dc142422b125df63104 100644 --- a/llvm/lib/Target/X86/X86AvoidStoreForwardingBlocks.cpp +++ b/llvm/lib/Target/X86/X86AvoidStoreForwardingBlocks.cpp @@ -521,8 +521,8 @@ bool X86AvoidSFBPass::alias(const MachineMemOperand &Op1, return true; int64_t MinOffset = std::min(Op1.getOffset(), Op2.getOffset()); - int64_t Overlapa = Op1.getSize() + Op1.getOffset() - MinOffset; - int64_t Overlapb = Op2.getSize() + Op2.getOffset() - MinOffset; + int64_t Overlapa = Op1.getSize().getValue() + Op1.getOffset() - MinOffset; + int64_t Overlapb = Op2.getSize().getValue() + Op2.getOffset() - MinOffset; return !AA->isNoAlias( MemoryLocation(Op1.getValue(), Overlapa, Op1.getAAInfo()), @@ -688,7 +688,7 @@ bool X86AvoidSFBPass::runOnMachineFunction(MachineFunction &MF) { !isRelevantAddressingMode(PBInst) || !PBInst->hasOneMemOperand()) continue; int64_t PBstDispImm = getDispOperand(PBInst).getImm(); - unsigned PBstSize = (*PBInst->memoperands_begin())->getSize(); + unsigned PBstSize = (*PBInst->memoperands_begin())->getSize().getValue(); // This check doesn't cover all cases, but it will suffice for now. // TODO: take branch probability into consideration, if the blocking // store is in an unreached block, breaking the memcopy could lose diff --git a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp index 6ef28b373cc9312b497272adc7bbe3fccd37935b..453754381034e3cce73a3cba076880457982120f 100644 --- a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp +++ b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp @@ -48,7 +48,7 @@ Error X86CodeGenPassBuilder::addInstSelector(AddMachinePass &) const { Error X86TargetMachine::buildCodeGenPipeline( ModulePassManager &MPM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, - CodeGenFileType FileType, CGPassBuilderOption Opt, + CodeGenFileType FileType, const CGPassBuilderOption &Opt, PassInstrumentationCallbacks *PIC) { auto CGPB = X86CodeGenPassBuilder(*this, Opt, PIC); return CGPB.buildPipeline(MPM, Out, DwoOut, FileType); diff --git a/llvm/lib/Target/X86/X86DomainReassignment.cpp b/llvm/lib/Target/X86/X86DomainReassignment.cpp index 53c0486c8697fdaf99229439d12c3f8d775f48db..6289b3a1df1f26e22bccf028d2d0bdeae46a9231 100644 --- a/llvm/lib/Target/X86/X86DomainReassignment.cpp +++ b/llvm/lib/Target/X86/X86DomainReassignment.cpp @@ -650,6 +650,16 @@ void X86DomainReassignment::initConverters() { createReplacer(X86::AND16rr, X86::KANDWrr); createReplacer(X86::XOR16rr, X86::KXORWrr); + bool HasNDD = STI->hasNDD(); + if (HasNDD) { + createReplacer(X86::SHR16ri_ND, X86::KSHIFTRWri); + createReplacer(X86::SHL16ri_ND, X86::KSHIFTLWri); + createReplacer(X86::NOT16r_ND, X86::KNOTWrr); + createReplacer(X86::OR16rr_ND, X86::KORWrr); + createReplacer(X86::AND16rr_ND, X86::KANDWrr); + createReplacer(X86::XOR16rr_ND, X86::KXORWrr); + } + if (STI->hasBWI()) { createReplacer(X86::MOV32rm, GET_EGPR_IF_ENABLED(X86::KMOVDkm)); createReplacer(X86::MOV64rm, GET_EGPR_IF_ENABLED(X86::KMOVQkm)); @@ -684,6 +694,23 @@ void X86DomainReassignment::initConverters() { createReplacer(X86::XOR32rr, X86::KXORDrr); createReplacer(X86::XOR64rr, X86::KXORQrr); + if (HasNDD) { + createReplacer(X86::SHR32ri_ND, X86::KSHIFTRDri); + createReplacer(X86::SHL32ri_ND, X86::KSHIFTLDri); + createReplacer(X86::ADD32rr_ND, X86::KADDDrr); + createReplacer(X86::NOT32r_ND, X86::KNOTDrr); + createReplacer(X86::OR32rr_ND, X86::KORDrr); + createReplacer(X86::AND32rr_ND, X86::KANDDrr); + createReplacer(X86::XOR32rr_ND, X86::KXORDrr); + createReplacer(X86::SHR64ri_ND, X86::KSHIFTRQri); + createReplacer(X86::SHL64ri_ND, X86::KSHIFTLQri); + createReplacer(X86::ADD64rr_ND, X86::KADDQrr); + createReplacer(X86::NOT64r_ND, X86::KNOTQrr); + createReplacer(X86::OR64rr_ND, X86::KORQrr); + createReplacer(X86::AND64rr_ND, X86::KANDQrr); + createReplacer(X86::XOR64rr_ND, X86::KXORQrr); + } + // TODO: KTEST is not a replacement for TEST due to flag differences. Need // to prove only Z flag is used. // createReplacer(X86::TEST32rr, X86::KTESTDrr); @@ -713,6 +740,17 @@ void X86DomainReassignment::initConverters() { // createReplacer(X86::TEST16rr, X86::KTESTWrr); createReplacer(X86::XOR8rr, X86::KXORBrr); + + if (HasNDD) { + createReplacer(X86::ADD8rr_ND, X86::KADDBrr); + createReplacer(X86::ADD16rr_ND, X86::KADDWrr); + createReplacer(X86::AND8rr_ND, X86::KANDBrr); + createReplacer(X86::NOT8r_ND, X86::KNOTBrr); + createReplacer(X86::OR8rr_ND, X86::KORBrr); + createReplacer(X86::SHR8ri_ND, X86::KSHIFTRBri); + createReplacer(X86::SHL8ri_ND, X86::KSHIFTLBri); + createReplacer(X86::XOR8rr_ND, X86::KXORBrr); + } } #undef GET_EGPR_IF_ENABLED } diff --git a/llvm/lib/Target/X86/X86FastISel.cpp b/llvm/lib/Target/X86/X86FastISel.cpp index 48d3b68b1823a58377d0bb589699d773502e5250..2eae155956368f2f366a40f4c671d01d9f9def4e 100644 --- a/llvm/lib/Target/X86/X86FastISel.cpp +++ b/llvm/lib/Target/X86/X86FastISel.cpp @@ -2133,7 +2133,8 @@ bool X86FastISel::X86FastEmitCMoveSelect(MVT RetVT, const Instruction *I) { return false; const TargetRegisterInfo &TRI = *Subtarget->getRegisterInfo(); - unsigned Opc = X86::getCMovOpcode(TRI.getRegSizeInBits(*RC)/8); + unsigned Opc = X86::getCMovOpcode(TRI.getRegSizeInBits(*RC) / 8, false, + Subtarget->hasNDD()); Register ResultReg = fastEmitInst_rri(Opc, RC, RHSReg, LHSReg, CC); updateValueMap(I, ResultReg); return true; diff --git a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp index af25b34fbab995482ae38484530d4629f6fcc137..d96613d7bb7efcfb599859ea65f199588cb7d5e5 100644 --- a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp +++ b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp @@ -604,7 +604,8 @@ bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) { } // Otherwise we can just rewrite in-place. - if (X86::getCondFromCMov(MI) != X86::COND_INVALID) { + if (X86::getCondFromCMov(MI) != X86::COND_INVALID || + X86::getCondFromCFCMov(MI) != X86::COND_INVALID) { rewriteCMov(*TestMBB, TestPos, TestLoc, MI, *FlagUse, CondRegs); } else if (getCondFromFCMOV(MI.getOpcode()) != X86::COND_INVALID) { rewriteFCMov(*TestMBB, TestPos, TestLoc, MI, *FlagUse, CondRegs); @@ -829,7 +830,9 @@ void X86FlagsCopyLoweringPass::rewriteCMov(MachineBasicBlock &TestMBB, MachineOperand &FlagUse, CondRegArray &CondRegs) { // First get the register containing this specific condition. - X86::CondCode Cond = X86::getCondFromCMov(CMovI); + X86::CondCode Cond = X86::getCondFromCMov(CMovI) == X86::COND_INVALID + ? X86::getCondFromCFCMov(CMovI) + : X86::getCondFromCMov(CMovI); unsigned CondReg; bool Inverted; std::tie(CondReg, Inverted) = diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index 76c6c1645239abbc4e638bdce1c8f68d3682456d..4e4241efd63d6b30abb324fdf8918d9da3645491 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -3090,13 +3090,19 @@ bool X86DAGToDAGISel::selectLEAAddr(SDValue N, bool X86DAGToDAGISel::selectTLSADDRAddr(SDValue N, SDValue &Base, SDValue &Scale, SDValue &Index, SDValue &Disp, SDValue &Segment) { - assert(N.getOpcode() == ISD::TargetGlobalTLSAddress); - auto *GA = cast<GlobalAddressSDNode>(N); + assert(N.getOpcode() == ISD::TargetGlobalTLSAddress || + N.getOpcode() == ISD::TargetExternalSymbol); X86ISelAddressMode AM; - AM.GV = GA->getGlobal(); - AM.Disp += GA->getOffset(); - AM.SymbolFlags = GA->getTargetFlags(); + if (auto *GA = dyn_cast<GlobalAddressSDNode>(N)) { + AM.GV = GA->getGlobal(); + AM.Disp += GA->getOffset(); + AM.SymbolFlags = GA->getTargetFlags(); + } else { + auto *SA = cast<ExternalSymbolSDNode>(N); + AM.ES = SA->getSymbol(); + AM.SymbolFlags = SA->getTargetFlags(); + } if (Subtarget->is32Bit()) { AM.Scale = 1; diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 2b5e3c0379a138663507fc2a164c788af3530bf9..a9751e170fe63d0aea804a9b04b04b593140502c 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -2631,6 +2631,11 @@ bool X86::mayFoldIntoZeroExtend(SDValue Op) { return false; } +static bool isLogicOp(unsigned Opcode) { + // TODO: Add support for X86ISD::FAND/FOR/FXOR/FANDN with test coverage. + return ISD::isBitwiseLogicOp(Opcode) || X86ISD::ANDNP == Opcode; +} + static bool isTargetShuffle(unsigned Opcode) { switch(Opcode) { default: return false; @@ -4070,10 +4075,9 @@ static std::pair<SDValue, SDValue> splitVector(SDValue Op, SelectionDAG &DAG, } /// Break an operation into 2 half sized ops and then concatenate the results. -static SDValue splitVectorOp(SDValue Op, SelectionDAG &DAG) { +static SDValue splitVectorOp(SDValue Op, SelectionDAG &DAG, const SDLoc &dl) { unsigned NumOps = Op.getNumOperands(); EVT VT = Op.getValueType(); - SDLoc dl(Op); // Extract the LHS Lo/Hi vectors SmallVector<SDValue> LoOps(NumOps, SDValue()); @@ -4096,7 +4100,8 @@ static SDValue splitVectorOp(SDValue Op, SelectionDAG &DAG) { /// Break an unary integer operation into 2 half sized ops and then /// concatenate the result back. -static SDValue splitVectorIntUnary(SDValue Op, SelectionDAG &DAG) { +static SDValue splitVectorIntUnary(SDValue Op, SelectionDAG &DAG, + const SDLoc &dl) { // Make sure we only try to split 256/512-bit types to avoid creating // narrow vectors. EVT VT = Op.getValueType(); @@ -4107,19 +4112,20 @@ static SDValue splitVectorIntUnary(SDValue Op, SelectionDAG &DAG) { assert(Op.getOperand(0).getValueType().getVectorNumElements() == VT.getVectorNumElements() && "Unexpected VTs!"); - return splitVectorOp(Op, DAG); + return splitVectorOp(Op, DAG, dl); } /// Break a binary integer operation into 2 half sized ops and then /// concatenate the result back. -static SDValue splitVectorIntBinary(SDValue Op, SelectionDAG &DAG) { +static SDValue splitVectorIntBinary(SDValue Op, SelectionDAG &DAG, + const SDLoc &dl) { // Assert that all the types match. EVT VT = Op.getValueType(); (void)VT; assert(Op.getOperand(0).getValueType() == VT && Op.getOperand(1).getValueType() == VT && "Unexpected VTs!"); assert((VT.is256BitVector() || VT.is512BitVector()) && "Unsupported VT!"); - return splitVectorOp(Op, DAG); + return splitVectorOp(Op, DAG, dl); } // Helper for splitting operands of an operation to legal target size and @@ -18592,13 +18598,22 @@ GetTLSADDR(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA, MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); SDLoc dl(GA); - SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, - GA->getValueType(0), - GA->getOffset(), - OperandFlags); + SDValue TGA; + bool UseTLSDESC = DAG.getTarget().useTLSDESC(); + if (LocalDynamic && UseTLSDESC) { + TGA = DAG.getTargetExternalSymbol("_TLS_MODULE_BASE_", PtrVT, OperandFlags); + auto UI = TGA->use_begin(); + // Reuse existing GetTLSADDR node if we can find it. + if (UI != TGA->use_end()) + return SDValue(*UI->use_begin()->use_begin(), 0); + } else { + TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, GA->getValueType(0), + GA->getOffset(), OperandFlags); + } - X86ISD::NodeType CallType = LocalDynamic ? X86ISD::TLSBASEADDR - : X86ISD::TLSADDR; + X86ISD::NodeType CallType = UseTLSDESC ? X86ISD::TLSDESC + : LocalDynamic ? X86ISD::TLSBASEADDR + : X86ISD::TLSADDR; if (InGlue) { SDValue Ops[] = { Chain, TGA, *InGlue }; @@ -18613,7 +18628,19 @@ GetTLSADDR(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA, MFI.setHasCalls(true); SDValue Glue = Chain.getValue(1); - return DAG.getCopyFromReg(Chain, dl, ReturnReg, PtrVT, Glue); + SDValue Ret = DAG.getCopyFromReg(Chain, dl, ReturnReg, PtrVT, Glue); + + if (!UseTLSDESC) + return Ret; + + const X86Subtarget &Subtarget = DAG.getSubtarget<X86Subtarget>(); + unsigned Seg = Subtarget.is64Bit() ? X86AS::FS : X86AS::GS; + + Value *Ptr = Constant::getNullValue(PointerType::get(*DAG.getContext(), Seg)); + SDValue Offset = + DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), DAG.getIntPtrConstant(0, dl), + MachinePointerInfo(Ptr)); + return DAG.getNode(ISD::ADD, dl, PtrVT, Ret, Offset); } // Lower ISD::GlobalTLSAddress using the "general dynamic" model, 32 bit @@ -20054,7 +20081,7 @@ static SDValue LowerAVXExtend(SDValue Op, SelectionDAG &DAG, if (VT == MVT::v32i16 && !Subtarget.hasBWI()) { assert(InVT == MVT::v32i8 && "Unexpected VT!"); - return splitVectorIntUnary(Op, DAG); + return splitVectorIntUnary(Op, DAG, dl); } if (Subtarget.hasInt256()) @@ -20635,7 +20662,7 @@ SDValue X86TargetLowering::LowerTRUNCATE(SDValue Op, SelectionDAG &DAG) const { if (Subtarget.hasAVX512()) { if (InVT == MVT::v32i16 && !Subtarget.hasBWI()) { assert(VT == MVT::v32i8 && "Unexpected VT!"); - return splitVectorIntUnary(Op, DAG); + return splitVectorIntUnary(Op, DAG, DL); } // word to byte only under BWI. Otherwise we have to promoted to v16i32 @@ -21490,7 +21517,9 @@ SDValue X86TargetLowering::LowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const { } if (VT.getScalarType() == MVT::bf16) { - if (SVT.getScalarType() == MVT::f32 && isTypeLegal(VT)) + if (SVT.getScalarType() == MVT::f32 && + ((Subtarget.hasBF16() && Subtarget.hasVLX()) || + Subtarget.hasAVXNECONVERT())) return Op; return SDValue(); } @@ -21597,7 +21626,8 @@ SDValue X86TargetLowering::LowerFP_TO_BF16(SDValue Op, SDLoc DL(Op); MVT SVT = Op.getOperand(0).getSimpleValueType(); - if (SVT == MVT::f32 && (Subtarget.hasBF16() || Subtarget.hasAVXNECONVERT())) { + if (SVT == MVT::f32 && ((Subtarget.hasBF16() && Subtarget.hasVLX()) || + Subtarget.hasAVXNECONVERT())) { SDValue Res; Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4f32, Op.getOperand(0)); Res = DAG.getNode(X86ISD::CVTNEPS2BF16, DL, MVT::v8bf16, Res); @@ -21615,7 +21645,8 @@ SDValue X86TargetLowering::LowerFP_TO_BF16(SDValue Op, /// Depending on uarch and/or optimizing for size, we might prefer to use a /// vector operation in place of the typical scalar operation. -static SDValue lowerAddSubToHorizontalOp(SDValue Op, SelectionDAG &DAG, +static SDValue lowerAddSubToHorizontalOp(SDValue Op, const SDLoc &DL, + SelectionDAG &DAG, const X86Subtarget &Subtarget) { // If both operands have other uses, this is probably not profitable. SDValue LHS = Op.getOperand(0); @@ -21671,7 +21702,6 @@ static SDValue lowerAddSubToHorizontalOp(SDValue Op, SelectionDAG &DAG, // Creating a 256-bit horizontal op would be wasteful, and there is no 512-bit // equivalent, so extract the 256/512-bit source op to 128-bit if we can. - SDLoc DL(Op); if (BitWidth == 256 || BitWidth == 512) { unsigned LaneIdx = LExtIndex / NumEltsPerLane; X = extract128BitVector(X, LaneIdx * NumEltsPerLane, DAG, DL); @@ -21692,7 +21722,7 @@ static SDValue lowerAddSubToHorizontalOp(SDValue Op, SelectionDAG &DAG, SDValue X86TargetLowering::lowerFaddFsub(SDValue Op, SelectionDAG &DAG) const { assert((Op.getValueType() == MVT::f32 || Op.getValueType() == MVT::f64) && "Only expecting float/double"); - return lowerAddSubToHorizontalOp(Op, DAG, Subtarget); + return lowerAddSubToHorizontalOp(Op, SDLoc(Op), DAG, Subtarget); } /// ISD::FROUND is defined to round to nearest with ties rounding away from 0. @@ -24449,7 +24479,7 @@ static SDValue LowerSIGN_EXTEND(SDValue Op, const X86Subtarget &Subtarget, if (VT == MVT::v32i16 && !Subtarget.hasBWI()) { assert(InVT == MVT::v32i8 && "Unexpected VT!"); - return splitVectorIntUnary(Op, DAG); + return splitVectorIntUnary(Op, DAG, dl); } if (Subtarget.hasInt256()) @@ -27812,7 +27842,7 @@ static SDValue LowerVectorCTLZ_AVX512CDI(SDValue Op, SelectionDAG &DAG, // Split vector, it's Lo and Hi parts will be handled in next iteration. if (NumElems > 16 || (NumElems == 16 && !Subtarget.canExtendTo512DQ())) - return splitVectorIntUnary(Op, DAG); + return splitVectorIntUnary(Op, DAG, dl); MVT NewVT = MVT::getVectorVT(MVT::i32, NumElems); assert((NewVT.is256BitVector() || NewVT.is512BitVector()) && @@ -27922,11 +27952,11 @@ static SDValue LowerVectorCTLZ(SDValue Op, const SDLoc &DL, // Decompose 256-bit ops into smaller 128-bit ops. if (VT.is256BitVector() && !Subtarget.hasInt256()) - return splitVectorIntUnary(Op, DAG); + return splitVectorIntUnary(Op, DAG, DL); // Decompose 512-bit ops into smaller 256-bit ops. if (VT.is512BitVector() && !Subtarget.hasBWI()) - return splitVectorIntUnary(Op, DAG); + return splitVectorIntUnary(Op, DAG, DL); assert(Subtarget.hasSSSE3() && "Expected SSSE3 support for PSHUFB"); return LowerVectorCTLZInRegLUT(Op, DL, Subtarget, DAG); @@ -27999,16 +28029,18 @@ static SDValue LowerCTTZ(SDValue Op, const X86Subtarget &Subtarget, static SDValue lowerAddSub(SDValue Op, SelectionDAG &DAG, const X86Subtarget &Subtarget) { MVT VT = Op.getSimpleValueType(); + SDLoc DL(Op); + if (VT == MVT::i16 || VT == MVT::i32) - return lowerAddSubToHorizontalOp(Op, DAG, Subtarget); + return lowerAddSubToHorizontalOp(Op, DL, DAG, Subtarget); if (VT == MVT::v32i16 || VT == MVT::v64i8) - return splitVectorIntBinary(Op, DAG); + return splitVectorIntBinary(Op, DAG, DL); assert(Op.getSimpleValueType().is256BitVector() && Op.getSimpleValueType().isInteger() && "Only handle AVX 256-bit vector integer operation"); - return splitVectorIntBinary(Op, DAG); + return splitVectorIntBinary(Op, DAG, DL); } static SDValue LowerADDSAT_SUBSAT(SDValue Op, SelectionDAG &DAG, @@ -28022,7 +28054,7 @@ static SDValue LowerADDSAT_SUBSAT(SDValue Op, SelectionDAG &DAG, (VT.is256BitVector() && !Subtarget.hasInt256())) { assert(Op.getSimpleValueType().isInteger() && "Only handle AVX vector integer operation"); - return splitVectorIntBinary(Op, DAG); + return splitVectorIntBinary(Op, DAG, DL); } // Avoid the generic expansion with min/max if we don't have pminu*/pmaxu*. @@ -28084,10 +28116,11 @@ static SDValue LowerADDSAT_SUBSAT(SDValue Op, SelectionDAG &DAG, static SDValue LowerABS(SDValue Op, const X86Subtarget &Subtarget, SelectionDAG &DAG) { MVT VT = Op.getSimpleValueType(); + SDLoc DL(Op); + if (VT == MVT::i16 || VT == MVT::i32 || VT == MVT::i64) { // Since X86 does not have CMOV for 8-bit integer, we don't convert // 8-bit integer abs to NEG and CMOV. - SDLoc DL(Op); SDValue N0 = Op.getOperand(0); SDValue Neg = DAG.getNode(X86ISD::SUB, DL, DAG.getVTList(VT, MVT::i32), DAG.getConstant(0, DL, VT), N0); @@ -28098,7 +28131,6 @@ static SDValue LowerABS(SDValue Op, const X86Subtarget &Subtarget, // ABS(vXi64 X) --> VPBLENDVPD(X, 0-X, X). if ((VT == MVT::v2i64 || VT == MVT::v4i64) && Subtarget.hasSSE41()) { - SDLoc DL(Op); SDValue Src = Op.getOperand(0); SDValue Sub = DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), Src); @@ -28108,11 +28140,11 @@ static SDValue LowerABS(SDValue Op, const X86Subtarget &Subtarget, if (VT.is256BitVector() && !Subtarget.hasInt256()) { assert(VT.isInteger() && "Only handle AVX 256-bit vector integer operation"); - return splitVectorIntUnary(Op, DAG); + return splitVectorIntUnary(Op, DAG, DL); } if ((VT == MVT::v32i16 || VT == MVT::v64i8) && !Subtarget.hasBWI()) - return splitVectorIntUnary(Op, DAG); + return splitVectorIntUnary(Op, DAG, DL); // Default to expand. return SDValue(); @@ -28121,13 +28153,14 @@ static SDValue LowerABS(SDValue Op, const X86Subtarget &Subtarget, static SDValue LowerAVG(SDValue Op, const X86Subtarget &Subtarget, SelectionDAG &DAG) { MVT VT = Op.getSimpleValueType(); + SDLoc DL(Op); // For AVX1 cases, split to use legal ops. if (VT.is256BitVector() && !Subtarget.hasInt256()) - return splitVectorIntBinary(Op, DAG); + return splitVectorIntBinary(Op, DAG, DL); if (VT == MVT::v32i16 || VT == MVT::v64i8) - return splitVectorIntBinary(Op, DAG); + return splitVectorIntBinary(Op, DAG, DL); // Default to expand. return SDValue(); @@ -28136,13 +28169,14 @@ static SDValue LowerAVG(SDValue Op, const X86Subtarget &Subtarget, static SDValue LowerMINMAX(SDValue Op, const X86Subtarget &Subtarget, SelectionDAG &DAG) { MVT VT = Op.getSimpleValueType(); + SDLoc DL(Op); // For AVX1 cases, split to use legal ops. if (VT.is256BitVector() && !Subtarget.hasInt256()) - return splitVectorIntBinary(Op, DAG); + return splitVectorIntBinary(Op, DAG, DL); if (VT == MVT::v32i16 || VT == MVT::v64i8) - return splitVectorIntBinary(Op, DAG); + return splitVectorIntBinary(Op, DAG, DL); // Default to expand. return SDValue(); @@ -28299,15 +28333,15 @@ static SDValue LowerFMINIMUM_FMAXIMUM(SDValue Op, const X86Subtarget &Subtarget, static SDValue LowerABD(SDValue Op, const X86Subtarget &Subtarget, SelectionDAG &DAG) { MVT VT = Op.getSimpleValueType(); + SDLoc dl(Op); // For AVX1 cases, split to use legal ops. if (VT.is256BitVector() && !Subtarget.hasInt256()) - return splitVectorIntBinary(Op, DAG); + return splitVectorIntBinary(Op, DAG, dl); if ((VT == MVT::v32i16 || VT == MVT::v64i8) && !Subtarget.useBWIRegs()) - return splitVectorIntBinary(Op, DAG); + return splitVectorIntBinary(Op, DAG, dl); - SDLoc dl(Op); bool IsSigned = Op.getOpcode() == ISD::ABDS; const TargetLowering &TLI = DAG.getTargetLoweringInfo(); @@ -28350,10 +28384,10 @@ static SDValue LowerMUL(SDValue Op, const X86Subtarget &Subtarget, // Decompose 256-bit ops into 128-bit ops. if (VT.is256BitVector() && !Subtarget.hasInt256()) - return splitVectorIntBinary(Op, DAG); + return splitVectorIntBinary(Op, DAG, dl); if ((VT == MVT::v32i16 || VT == MVT::v64i8) && !Subtarget.hasBWI()) - return splitVectorIntBinary(Op, DAG); + return splitVectorIntBinary(Op, DAG, dl); SDValue A = Op.getOperand(0); SDValue B = Op.getOperand(1); @@ -28576,10 +28610,10 @@ static SDValue LowerMULH(SDValue Op, const X86Subtarget &Subtarget, // Decompose 256-bit ops into 128-bit ops. if (VT.is256BitVector() && !Subtarget.hasInt256()) - return splitVectorIntBinary(Op, DAG); + return splitVectorIntBinary(Op, DAG, dl); if ((VT == MVT::v32i16 || VT == MVT::v64i8) && !Subtarget.hasBWI()) - return splitVectorIntBinary(Op, DAG); + return splitVectorIntBinary(Op, DAG, dl); if (VT == MVT::v4i32 || VT == MVT::v8i32 || VT == MVT::v16i32) { assert((VT == MVT::v4i32 && Subtarget.hasSSE2()) || @@ -29757,10 +29791,10 @@ static SDValue LowerShift(SDValue Op, const X86Subtarget &Subtarget, // Decompose 256-bit shifts into 128-bit shifts. if (VT.is256BitVector()) - return splitVectorIntBinary(Op, DAG); + return splitVectorIntBinary(Op, DAG, dl); if (VT == MVT::v32i16 || VT == MVT::v64i8) - return splitVectorIntBinary(Op, DAG); + return splitVectorIntBinary(Op, DAG, dl); return SDValue(); } @@ -29837,7 +29871,7 @@ static SDValue LowerFunnelShift(SDValue Op, const X86Subtarget &Subtarget, EltSizeInBits < 32)) { // Pre-mask the amount modulo using the wider vector. Op = DAG.getNode(Op.getOpcode(), DL, VT, Op0, Op1, AmtMod); - return splitVectorOp(Op, DAG); + return splitVectorOp(Op, DAG, DL); } // Attempt to fold scalar shift as unpack(y,x) << zext(splat(z)) @@ -29999,7 +30033,7 @@ static SDValue LowerRotate(SDValue Op, const X86Subtarget &Subtarget, // Split 256-bit integers on XOP/pre-AVX2 targets. if (VT.is256BitVector() && (Subtarget.hasXOP() || !Subtarget.hasAVX2())) - return splitVectorIntBinary(Op, DAG); + return splitVectorIntBinary(Op, DAG, DL); // XOP has 128-bit vector variable + immediate rotates. // +ve/-ve Amt = rotate left/right - just need to handle ISD::ROTL. @@ -30035,7 +30069,7 @@ static SDValue LowerRotate(SDValue Op, const X86Subtarget &Subtarget, // Split 512-bit integers on non 512-bit BWI targets. if (VT.is512BitVector() && !Subtarget.useBWIRegs()) - return splitVectorIntBinary(Op, DAG); + return splitVectorIntBinary(Op, DAG, DL); assert( (VT == MVT::v4i32 || VT == MVT::v8i16 || VT == MVT::v16i8 || @@ -31115,11 +31149,11 @@ static SDValue LowerVectorCTPOP(SDValue Op, const SDLoc &DL, // Decompose 256-bit ops into smaller 128-bit ops. if (VT.is256BitVector() && !Subtarget.hasInt256()) - return splitVectorIntUnary(Op, DAG); + return splitVectorIntUnary(Op, DAG, DL); // Decompose 512-bit ops into smaller 256-bit ops. if (VT.is512BitVector() && !Subtarget.hasBWI()) - return splitVectorIntUnary(Op, DAG); + return splitVectorIntUnary(Op, DAG, DL); // For element types greater than i8, do vXi8 pop counts and a bytesum. if (VT.getScalarType() != MVT::i8) { @@ -31243,7 +31277,7 @@ static SDValue LowerBITREVERSE_XOP(SDValue Op, SelectionDAG &DAG) { // Decompose 256-bit ops into smaller 128-bit ops. if (VT.is256BitVector()) - return splitVectorIntUnary(Op, DAG); + return splitVectorIntUnary(Op, DAG, DL); assert(VT.is128BitVector() && "Only 128-bit vector bitreverse lowering supported."); @@ -31282,11 +31316,11 @@ static SDValue LowerBITREVERSE(SDValue Op, const X86Subtarget &Subtarget, // Split 512-bit ops without BWI so that we can still use the PSHUFB lowering. if (VT.is512BitVector() && !Subtarget.hasBWI()) - return splitVectorIntUnary(Op, DAG); + return splitVectorIntUnary(Op, DAG, DL); // Decompose 256-bit ops into smaller 128-bit ops on pre-AVX2. if (VT.is256BitVector() && !Subtarget.hasInt256()) - return splitVectorIntUnary(Op, DAG); + return splitVectorIntUnary(Op, DAG, DL); // Lower vXi16/vXi32/vXi64 as BSWAP + vXi8 BITREVERSE. if (VT.getScalarType() != MVT::i8) { @@ -33426,6 +33460,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { NODE_NAME_CASE(TLSADDR) NODE_NAME_CASE(TLSBASEADDR) NODE_NAME_CASE(TLSCALL) + NODE_NAME_CASE(TLSDESC) NODE_NAME_CASE(EH_SJLJ_SETJMP) NODE_NAME_CASE(EH_SJLJ_LONGJMP) NODE_NAME_CASE(EH_SJLJ_SETUP_DISPATCH) @@ -35206,6 +35241,7 @@ X86TargetLowering::EmitLoweredTLSAddr(MachineInstr &MI, MachineFunction &MF = *BB->getParent(); // Emit CALLSEQ_START right before the instruction. + BB->getParent()->getFrameInfo().setAdjustsStack(true); unsigned AdjStackDown = TII.getCallFrameSetupOpcode(); MachineInstrBuilder CallseqStart = BuildMI(MF, MIMD, TII.get(AdjStackDown)).addImm(0).addImm(0).addImm(0); @@ -36206,6 +36242,8 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, case X86::TLS_base_addr32: case X86::TLS_base_addr64: case X86::TLS_base_addrX32: + case X86::TLS_desc32: + case X86::TLS_desc64: return EmitLoweredTLSAddr(MI, BB); case X86::INDIRECT_THUNK_CALL32: case X86::INDIRECT_THUNK_CALL64: @@ -39923,8 +39961,10 @@ static SDValue canonicalizeShuffleWithOp(SDValue N, SelectionDAG &DAG, const SDLoc &DL) { const TargetLowering &TLI = DAG.getTargetLoweringInfo(); EVT ShuffleVT = N.getValueType(); + unsigned Opc = N.getOpcode(); - auto IsMergeableWithShuffle = [&DAG](SDValue Op, bool FoldLoad = false) { + auto IsMergeableWithShuffle = [Opc, &DAG](SDValue Op, bool FoldShuf = true, + bool FoldLoad = false) { // AllZeros/AllOnes constants are freely shuffled and will peek through // bitcasts. Other constant build vectors do not peek through bitcasts. Only // merge with target shuffles if it has one use so shuffle combining is @@ -39934,20 +39974,19 @@ static SDValue canonicalizeShuffleWithOp(SDValue N, SelectionDAG &DAG, ISD::isBuildVectorOfConstantSDNodes(Op.getNode()) || ISD::isBuildVectorOfConstantFPSDNodes(Op.getNode()) || getTargetConstantFromNode(dyn_cast<LoadSDNode>(Op)) || + (Op.getOpcode() == Opc && Op->hasOneUse()) || (Op.getOpcode() == ISD::INSERT_SUBVECTOR && Op->hasOneUse()) || - (isTargetShuffle(Op.getOpcode()) && Op->hasOneUse()) || + (FoldShuf && isTargetShuffle(Op.getOpcode()) && Op->hasOneUse()) || (FoldLoad && isShuffleFoldableLoad(Op)) || DAG.isSplatValue(Op, /*AllowUndefs*/ false); }; auto IsSafeToMoveShuffle = [ShuffleVT](SDValue Op, unsigned BinOp) { // Ensure we only shuffle whole vector src elements, unless its a logical // binops where we can more aggressively move shuffles from dst to src. - return BinOp == ISD::AND || BinOp == ISD::OR || BinOp == ISD::XOR || - BinOp == X86ISD::ANDNP || + return isLogicOp(BinOp) || (Op.getScalarValueSizeInBits() <= ShuffleVT.getScalarSizeInBits()); }; - unsigned Opc = N.getOpcode(); switch (Opc) { // Unary and Unary+Permute Shuffles. case X86ISD::PSHUFB: { @@ -39973,8 +40012,10 @@ static SDValue canonicalizeShuffleWithOp(SDValue N, SelectionDAG &DAG, if (TLI.isBinOp(SrcOpcode) && IsSafeToMoveShuffle(N0, SrcOpcode)) { SDValue Op00 = peekThroughOneUseBitcasts(N0.getOperand(0)); SDValue Op01 = peekThroughOneUseBitcasts(N0.getOperand(1)); - if (IsMergeableWithShuffle(Op00, Opc != X86ISD::PSHUFB) || - IsMergeableWithShuffle(Op01, Opc != X86ISD::PSHUFB)) { + if (IsMergeableWithShuffle(Op00, Opc != X86ISD::VPERMI, + Opc != X86ISD::PSHUFB) || + IsMergeableWithShuffle(Op01, Opc != X86ISD::VPERMI, + Opc != X86ISD::PSHUFB)) { SDValue LHS, RHS; Op00 = DAG.getBitcast(ShuffleVT, Op00); Op01 = DAG.getBitcast(ShuffleVT, Op01); @@ -42641,7 +42682,6 @@ SDValue X86TargetLowering::SimplifyMultipleUseDemandedBitsForTargetNode( bool X86TargetLowering::isGuaranteedNotToBeUndefOrPoisonForTargetNode( SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool PoisonOnly, unsigned Depth) const { - unsigned EltsBits = Op.getScalarValueSizeInBits(); unsigned NumElts = DemandedElts.getBitWidth(); // TODO: Add more target shuffles. @@ -42649,15 +42689,28 @@ bool X86TargetLowering::isGuaranteedNotToBeUndefOrPoisonForTargetNode( case X86ISD::PSHUFD: case X86ISD::VPERMILPI: { SmallVector<int, 8> Mask; - DecodePSHUFMask(NumElts, EltsBits, Op.getConstantOperandVal(1), Mask); - - APInt DemandedSrcElts = APInt::getZero(NumElts); - for (unsigned I = 0; I != NumElts; ++I) - if (DemandedElts[I]) - DemandedSrcElts.setBit(Mask[I]); - - return DAG.isGuaranteedNotToBeUndefOrPoison( - Op.getOperand(0), DemandedSrcElts, PoisonOnly, Depth + 1); + SmallVector<SDValue, 2> Ops; + if (getTargetShuffleMask(Op.getNode(), Op.getSimpleValueType(), true, Ops, + Mask)) { + SmallVector<APInt, 2> DemandedSrcElts(Ops.size(), + APInt::getZero(NumElts)); + for (auto M : enumerate(Mask)) { + if (!DemandedElts[M.index()] || M.value() == SM_SentinelZero) + continue; + if (M.value() == SM_SentinelUndef) + return false; + assert(0 <= M.value() && M.value() < (int)(Ops.size() * NumElts) && + "Shuffle mask index out of range"); + DemandedSrcElts[M.value() / NumElts].setBit(M.value() % NumElts); + } + for (auto Op : enumerate(Ops)) + if (!DemandedSrcElts[Op.index()].isZero() && + !DAG.isGuaranteedNotToBeUndefOrPoison( + Op.value(), DemandedSrcElts[Op.index()], PoisonOnly, Depth + 1)) + return false; + return true; + } + break; } } return TargetLowering::isGuaranteedNotToBeUndefOrPoisonForTargetNode( @@ -43950,6 +44003,50 @@ static SDValue combineBasicSADPattern(SDNode *Extract, SelectionDAG &DAG, Extract->getOperand(1)); } +// If this extract is from a loaded vector value and will be used as an +// integer, that requires a potentially expensive XMM -> GPR transfer. +// Additionally, if we can convert to a scalar integer load, that will likely +// be folded into a subsequent integer op. +// Note: SrcVec might not have a VecVT type, but it must be the same size. +// Note: Unlike the related fold for this in DAGCombiner, this is not limited +// to a single-use of the loaded vector. For the reasons above, we +// expect this to be profitable even if it creates an extra load. +static SDValue +combineExtractFromVectorLoad(SDNode *N, EVT VecVT, SDValue SrcVec, uint64_t Idx, + const SDLoc &dl, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI) { + assert(N->getOpcode() == ISD::EXTRACT_VECTOR_ELT && + "Only EXTRACT_VECTOR_ELT supported so far"); + + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + EVT VT = N->getValueType(0); + + bool LikelyUsedAsVector = any_of(N->uses(), [](SDNode *Use) { + return Use->getOpcode() == ISD::STORE || + Use->getOpcode() == ISD::INSERT_VECTOR_ELT || + Use->getOpcode() == ISD::SCALAR_TO_VECTOR; + }); + + auto *LoadVec = dyn_cast<LoadSDNode>(SrcVec); + if (LoadVec && ISD::isNormalLoad(LoadVec) && VT.isInteger() && + VecVT.getVectorElementType() == VT && + VecVT.getSizeInBits() == SrcVec.getValueSizeInBits() && + DCI.isAfterLegalizeDAG() && !LikelyUsedAsVector && LoadVec->isSimple()) { + SDValue NewPtr = TLI.getVectorElementPointer( + DAG, LoadVec->getBasePtr(), VecVT, DAG.getVectorIdxConstant(Idx, dl)); + unsigned PtrOff = VT.getSizeInBits() * Idx / 8; + MachinePointerInfo MPI = LoadVec->getPointerInfo().getWithOffset(PtrOff); + Align Alignment = commonAlignment(LoadVec->getAlign(), PtrOff); + SDValue Load = + DAG.getLoad(VT, dl, LoadVec->getChain(), NewPtr, MPI, Alignment, + LoadVec->getMemOperand()->getFlags(), LoadVec->getAAInfo()); + DAG.makeEquivalentMemoryOrdering(LoadVec, Load); + return Load; + } + + return SDValue(); +} + // Attempt to peek through a target shuffle and extract the scalar from the // source. static SDValue combineExtractWithShuffle(SDNode *N, SelectionDAG &DAG, @@ -44146,6 +44243,11 @@ static SDValue combineExtractWithShuffle(SDNode *N, SelectionDAG &DAG, if (SDValue V = GetLegalExtract(SrcOp, ExtractVT, ExtractIdx)) return DAG.getZExtOrTrunc(V, dl, VT); + if (N->getOpcode() == ISD::EXTRACT_VECTOR_ELT && ExtractVT == SrcVT) + if (SDValue V = combineExtractFromVectorLoad( + N, SrcVT, peekThroughBitcasts(SrcOp), ExtractIdx, dl, DAG, DCI)) + return V; + return SDValue(); } @@ -44555,6 +44657,12 @@ static SDValue combineExtractVectorElt(SDNode *N, SelectionDAG &DAG, if (SDValue V = scalarizeExtEltFP(N, DAG, Subtarget)) return V; + if (CIdx) + if (SDValue V = combineExtractFromVectorLoad( + N, InputVector.getValueType(), InputVector, CIdx->getZExtValue(), + dl, DAG, DCI)) + return V; + // Attempt to extract a i1 element by using MOVMSK to extract the signbits // and then testing the relevant element. // @@ -44600,34 +44708,6 @@ static SDValue combineExtractVectorElt(SDNode *N, SelectionDAG &DAG, } } - // If this extract is from a loaded vector value and will be used as an - // integer, that requires a potentially expensive XMM -> GPR transfer. - // Additionally, if we can convert to a scalar integer load, that will likely - // be folded into a subsequent integer op. - // Note: Unlike the related fold for this in DAGCombiner, this is not limited - // to a single-use of the loaded vector. For the reasons above, we - // expect this to be profitable even if it creates an extra load. - bool LikelyUsedAsVector = any_of(N->uses(), [](SDNode *Use) { - return Use->getOpcode() == ISD::STORE || - Use->getOpcode() == ISD::INSERT_VECTOR_ELT || - Use->getOpcode() == ISD::SCALAR_TO_VECTOR; - }); - auto *LoadVec = dyn_cast<LoadSDNode>(InputVector); - if (LoadVec && CIdx && ISD::isNormalLoad(LoadVec) && VT.isInteger() && - SrcVT.getVectorElementType() == VT && DCI.isAfterLegalizeDAG() && - !LikelyUsedAsVector && LoadVec->isSimple()) { - SDValue NewPtr = - TLI.getVectorElementPointer(DAG, LoadVec->getBasePtr(), SrcVT, EltIdx); - unsigned PtrOff = VT.getSizeInBits() * CIdx->getZExtValue() / 8; - MachinePointerInfo MPI = LoadVec->getPointerInfo().getWithOffset(PtrOff); - Align Alignment = commonAlignment(LoadVec->getAlign(), PtrOff); - SDValue Load = - DAG.getLoad(VT, dl, LoadVec->getChain(), NewPtr, MPI, Alignment, - LoadVec->getMemOperand()->getFlags(), LoadVec->getAAInfo()); - DAG.makeEquivalentMemoryOrdering(LoadVec, Load); - return Load; - } - return SDValue(); } @@ -47351,10 +47431,23 @@ static SDValue combineShiftRightArithmetic(SDNode *N, SelectionDAG &DAG, if (SDValue V = combineShiftToPMULH(N, DAG, Subtarget)) return V; - // fold (ashr (shl, a, [56,48,32,24,16]), SarConst) - // into (shl, (sext (a), [56,48,32,24,16] - SarConst)) or - // into (lshr, (sext (a), SarConst - [56,48,32,24,16])) - // depending on sign of (SarConst - [56,48,32,24,16]) + APInt ShiftAmt; + if (supportedVectorVarShift(VT, Subtarget, ISD::SRA) && + N1.getOpcode() == ISD::UMIN && + ISD::isConstantSplatVector(N1.getOperand(1).getNode(), ShiftAmt) && + ShiftAmt == VT.getScalarSizeInBits() - 1) { + SDValue ShrAmtVal = N1.getOperand(0); + SDLoc DL(N); + return DAG.getNode(X86ISD::VSRAV, DL, N->getVTList(), N0, ShrAmtVal); + } + + // fold (SRA (SHL X, ShlConst), SraConst) + // into (SHL (sext_in_reg X), ShlConst - SraConst) + // or (sext_in_reg X) + // or (SRA (sext_in_reg X), SraConst - ShlConst) + // depending on relation between SraConst and ShlConst. + // We only do this if (Size - ShlConst) is equal to 8, 16 or 32. That allows + // us to do the sext_in_reg from corresponding bit. // sexts in X86 are MOVs. The MOVs have the same code size // as above SHIFTs (only SHIFT on 1 has lower code size). @@ -47370,29 +47463,29 @@ static SDValue combineShiftRightArithmetic(SDNode *N, SelectionDAG &DAG, SDValue N00 = N0.getOperand(0); SDValue N01 = N0.getOperand(1); APInt ShlConst = N01->getAsAPIntVal(); - APInt SarConst = N1->getAsAPIntVal(); + APInt SraConst = N1->getAsAPIntVal(); EVT CVT = N1.getValueType(); - if (SarConst.isNegative()) + if (CVT != N01.getValueType()) + return SDValue(); + if (SraConst.isNegative()) return SDValue(); for (MVT SVT : { MVT::i8, MVT::i16, MVT::i32 }) { unsigned ShiftSize = SVT.getSizeInBits(); - // skipping types without corresponding sext/zext and - // ShlConst that is not one of [56,48,32,24,16] + // Only deal with (Size - ShlConst) being equal to 8, 16 or 32. if (ShiftSize >= Size || ShlConst != Size - ShiftSize) continue; SDLoc DL(N); SDValue NN = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, N00, DAG.getValueType(SVT)); - SarConst = SarConst - (Size - ShiftSize); - if (SarConst == 0) + if (SraConst.eq(ShlConst)) return NN; - if (SarConst.isNegative()) + if (SraConst.ult(ShlConst)) return DAG.getNode(ISD::SHL, DL, VT, NN, - DAG.getConstant(-SarConst, DL, CVT)); + DAG.getConstant(ShlConst - SraConst, DL, CVT)); return DAG.getNode(ISD::SRA, DL, VT, NN, - DAG.getConstant(SarConst, DL, CVT)); + DAG.getConstant(SraConst - ShlConst, DL, CVT)); } return SDValue(); } @@ -48215,7 +48308,7 @@ static SDValue combineAndShuffleNot(SDNode *N, SelectionDAG &DAG, // We do not split for SSE at all, but we need to split vectors for AVX1 and // AVX2. - if (!Subtarget.useAVX512Regs() && VT.is512BitVector() && + if (!Subtarget.useAVX512Regs() && VT.is512BitVector() && TLI.isTypeLegal(VT.getHalfNumVectorElementsVT(*DAG.getContext()))) { SDValue LoX, HiX; std::tie(LoX, HiX) = splitVector(X, DAG, DL); @@ -55474,7 +55567,19 @@ static SDValue combineConcatVectorOps(const SDLoc &DL, MVT VT, } break; // Due to VADD, VSUB, VMUL can executed on more ports than VINSERT and - // their latency are short, so here we don't replace them. + // their latency are short, so here we don't replace them unless we won't + // introduce extra VINSERT. + case ISD::FADD: + case ISD::FSUB: + case ISD::FMUL: + if (!IsSplat && (IsConcatFree(VT, Ops, 0) || IsConcatFree(VT, Ops, 1)) && + (VT.is256BitVector() || + (VT.is512BitVector() && Subtarget.useAVX512Regs()))) { + return DAG.getNode(Op0.getOpcode(), DL, VT, + ConcatSubOperand(VT, Ops, 0), + ConcatSubOperand(VT, Ops, 1)); + } + break; case ISD::FDIV: if (!IsSplat && (VT.is256BitVector() || (VT.is512BitVector() && Subtarget.useAVX512Regs()))) { @@ -55933,7 +56038,7 @@ static SDValue combineEXTRACT_SUBVECTOR(SDNode *N, SelectionDAG &DAG, if (isConcatenatedNot(InVecBC.getOperand(0)) || isConcatenatedNot(InVecBC.getOperand(1))) { // extract (and v4i64 X, (not (concat Y1, Y2))), n -> andnp v2i64 X(n), Y1 - SDValue Concat = splitVectorIntBinary(InVecBC, DAG); + SDValue Concat = splitVectorIntBinary(InVecBC, DAG, SDLoc(InVecBC)); return DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, DAG.getBitcast(InVecVT, Concat), N->getOperand(1)); } diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h index fe1943b57608449ce6de9e9d067c45343bbe7deb..0a1e8ca4427314f53e6484db4261154ee4792e3d 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.h +++ b/llvm/lib/Target/X86/X86ISelLowering.h @@ -295,6 +295,10 @@ namespace llvm { // thunk at the address from an earlier relocation. TLSCALL, + // Thread Local Storage. A descriptor containing pointer to + // code and to argument to get the TLS offset for the symbol. + TLSDESC, + // Exception Handling helpers. EH_RETURN, diff --git a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp index c7ef11aede886a72cb42abe61176f2b684b02d94..1f76f74510335c5902df5ddbac58fbfd01b9a68d 100644 --- a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp +++ b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp @@ -2224,7 +2224,7 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); const TargetOptions &Options = DAG.getTarget().Options; if (Options.EmitCallSiteInfo) - CSInfo.emplace_back(VA.getLocReg(), I); + CSInfo.ArgRegPairs.emplace_back(VA.getLocReg(), I); if (isVarArg && IsWin64) { // Win64 ABI requires argument XMM reg to be copied to the corresponding // shadow reg if callee is a varargs function. diff --git a/llvm/lib/Target/X86/X86InstrArithmetic.td b/llvm/lib/Target/X86/X86InstrArithmetic.td index fef0a5a90cd6f0fbc6f5e6f61bb41ed5970c1a8f..c45ec8981ab1fea7956e430415838f78c7fab6d2 100644 --- a/llvm/lib/Target/X86/X86InstrArithmetic.td +++ b/llvm/lib/Target/X86/X86InstrArithmetic.td @@ -334,6 +334,44 @@ let Predicates = [In64BitMode] in { def IMUL32rmi_EVEX : IMulOpMI_RF<Xi32, WriteIMul32Imm>, PL; def IMUL64rmi32_EVEX : IMulOpMI_RF<Xi64, WriteIMul64Imm>, PL; } + +// IMULZU instructions +class IMulZUOpRI8_R<X86TypeInfo t, X86FoldableSchedWrite sched> + : BinOpRI8<0x6B, "imulzu", binop_ndd_args, t, MRMSrcReg, + (outs t.RegClass:$dst)> { + let SchedRW = [sched]; +} +class IMulZUOpRI_R<X86TypeInfo t, X86FoldableSchedWrite sched> + : BinOpRI<0x69, "imulzu", binop_ndd_args, t, MRMSrcReg, + (outs t.RegClass:$dst), []> { + let SchedRW = [sched]; +} +class IMulZUOpMI8_R<X86TypeInfo t, X86FoldableSchedWrite sched> + : BinOpMI8<"imulzu", binop_ndd_args, t, MRMSrcMem, (outs t.RegClass:$dst)> { + let Opcode = 0x6B; + let SchedRW = [sched.Folded]; +} +class IMulZUOpMI_R<X86TypeInfo t, X86FoldableSchedWrite sched> + : BinOpMI<0x69, "imulzu", binop_ndd_args, t, MRMSrcMem, + (outs t.RegClass:$dst), []> { + let SchedRW = [sched.Folded]; +} + +let Defs = [EFLAGS], Predicates = [HasEGPR, In64BitMode] in { + def IMULZU16rri8 : IMulZUOpRI8_R<Xi16, WriteIMul16Imm>, ZU, PD; + def IMULZU16rmi8 : IMulZUOpMI8_R<Xi16, WriteIMul16Imm>, ZU, PD; + def IMULZU16rri : IMulZUOpRI_R<Xi16, WriteIMul16Imm>, ZU, PD; + def IMULZU16rmi : IMulZUOpMI_R<Xi16, WriteIMul16Imm>, ZU, PD; + def IMULZU32rri8 : IMulZUOpRI8_R<Xi32, WriteIMul32Imm>, ZU; + def IMULZU32rmi8 : IMulZUOpMI8_R<Xi32, WriteIMul32Imm>, ZU; + def IMULZU32rri : IMulZUOpRI_R<Xi32, WriteIMul32Imm>, ZU; + def IMULZU32rmi : IMulZUOpMI_R<Xi32, WriteIMul32Imm>, ZU; + def IMULZU64rri8 : IMulZUOpRI8_R<Xi64, WriteIMul64Imm>, ZU; + def IMULZU64rmi8 : IMulZUOpMI8_R<Xi64, WriteIMul64Imm>, ZU; + def IMULZU64rri32 : IMulZUOpRI_R<Xi64, WriteIMul64Imm>, ZU; + def IMULZU64rmi32 : IMulZUOpMI_R<Xi64, WriteIMul64Imm>, ZU; +} + //===----------------------------------------------------------------------===// // INC and DEC Instructions // diff --git a/llvm/lib/Target/X86/X86InstrAsmAlias.td b/llvm/lib/Target/X86/X86InstrAsmAlias.td index fab058dc390bb3c50946c98fbbff9cf792c6a939..6b15213a2e68332cb6605fd43cba20074b4c7677 100644 --- a/llvm/lib/Target/X86/X86InstrAsmAlias.td +++ b/llvm/lib/Target/X86/X86InstrAsmAlias.td @@ -402,6 +402,12 @@ defm : IntegerCondCodeMnemonicAlias<"cmov", "q", "att">; // No size suffix for intel-style asm. defm : IntegerCondCodeMnemonicAlias<"cmov", "", "intel">; +// Aliases for cfcmov<CC>{w,l,q} +defm : IntegerCondCodeMnemonicAlias<"cfcmov", "w", "att">; +defm : IntegerCondCodeMnemonicAlias<"cfcmov", "l", "att">; +defm : IntegerCondCodeMnemonicAlias<"cfcmov", "q", "att">; +// No size suffix for intel-style asm. +defm : IntegerCondCodeMnemonicAlias<"cfcmov", "", "intel">; //===----------------------------------------------------------------------===// // Assembler Instruction Aliases //===----------------------------------------------------------------------===// @@ -768,6 +774,20 @@ multiclass CMOV_SETCC_Aliases<string Cond, int CC> { (CMOV64rr GR64:$dst, GR64:$src, CC), 0>; def : InstAlias<"cmov"#Cond#"{q}\t{$src, $dst|$dst, $src}", (CMOV64rm GR64:$dst, i64mem:$src, CC), 0>; +let Predicates = [In64BitMode] in { + def : InstAlias<"cmov"#Cond#"{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + (CMOV16rr_ND GR16:$dst, GR16:$src1, GR16:$src2, CC), 0>; + def : InstAlias<"cmov"#Cond#"{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + (CMOV16rm_ND GR16:$dst, GR16:$src1, i16mem:$src2, CC), 0>; + def : InstAlias<"cmov"#Cond#"{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + (CMOV32rr_ND GR32:$dst, GR32:$src1, GR32:$src2, CC), 0>; + def : InstAlias<"cmov"#Cond#"{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + (CMOV32rm_ND GR32:$dst, GR32:$src1, i32mem:$src2, CC), 0>; + def : InstAlias<"cmov"#Cond#"{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + (CMOV64rr_ND GR64:$dst, GR64:$src1, GR64:$src2, CC), 0>; + def : InstAlias<"cmov"#Cond#"{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + (CMOV64rm_ND GR64:$dst, GR64:$src1, i64mem:$src2, CC), 0>; +} def : InstAlias<"set"#Cond#"\t$dst", (SETCCr GR8:$dst, CC), 0>; def : InstAlias<"set"#Cond#"\t$dst", (SETCCm i8mem:$dst, CC), 0>; @@ -790,6 +810,57 @@ defm : CMOV_SETCC_Aliases<"ge", 13>; defm : CMOV_SETCC_Aliases<"le", 14>; defm : CMOV_SETCC_Aliases<"g" , 15>; +multiclass CFCMOV_Aliases<string Cond, int CC> { +let Predicates = [In64BitMode] in { + def : InstAlias<"cfcmov"#Cond#"{w}\t{$src, $dst|$dst, $src}", + (CFCMOV16rr GR16:$dst, GR16:$src, CC), 0>; + def : InstAlias<"cfcmov"#Cond#"{l}\t{$src, $dst|$dst, $src}", + (CFCMOV32rr GR32:$dst, GR32:$src, CC), 0>; + def : InstAlias<"cfcmov"#Cond#"{q}\t{$src, $dst|$dst, $src}", + (CFCMOV64rr GR64:$dst, GR64:$src, CC), 0>; + def : InstAlias<"cfcmov"#Cond#"{w}\t{$src, $dst|$dst, $src}", + (CFCMOV16rm GR16:$dst, i16mem:$src, CC), 0>; + def : InstAlias<"cfcmov"#Cond#"{l}\t{$src, $dst|$dst, $src}", + (CFCMOV32rm GR32:$dst, i32mem:$src, CC), 0>; + def : InstAlias<"cfcmov"#Cond#"{q}\t{$src, $dst|$dst, $src}", + (CFCMOV64rm GR64:$dst, i64mem:$src, CC), 0>; + def : InstAlias<"cfcmov"#Cond#"{w}\t{$src, $dst|$dst, $src}", + (CFCMOV16mr i16mem:$dst, GR16:$src, CC), 0>; + def : InstAlias<"cfcmov"#Cond#"{l}\t{$src, $dst|$dst, $src}", + (CFCMOV32mr i32mem:$dst, GR32:$src, CC), 0>; + def : InstAlias<"cfcmov"#Cond#"{q}\t{$src, $dst|$dst, $src}", + (CFCMOV64mr i64mem:$dst, GR64:$src, CC), 0>; + def : InstAlias<"cfcmov"#Cond#"{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + (CFCMOV16rr_ND GR16:$dst, GR16:$src1, GR16:$src2, CC), 0>; + def : InstAlias<"cfcmov"#Cond#"{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + (CFCMOV32rr_ND GR32:$dst, GR32:$src1, GR32:$src2, CC), 0>; + def : InstAlias<"cfcmov"#Cond#"{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + (CFCMOV64rr_ND GR64:$dst, GR64:$src1, GR64:$src2, CC), 0>; + def : InstAlias<"cfcmov"#Cond#"{w}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + (CFCMOV16rm_ND GR16:$dst, GR16:$src1, i16mem:$src2, CC), 0>; + def : InstAlias<"cfcmov"#Cond#"{l}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + (CFCMOV32rm_ND GR32:$dst, GR32:$src1, i32mem:$src2, CC), 0>; + def : InstAlias<"cfcmov"#Cond#"{q}\t{$src2, $src1, $dst|$dst, $src1, $src2}", + (CFCMOV64rm_ND GR64:$dst, GR64:$src1, i64mem:$src2, CC), 0>; +} +} +defm : CFCMOV_Aliases<"o" , 0>; +defm : CFCMOV_Aliases<"no", 1>; +defm : CFCMOV_Aliases<"b" , 2>; +defm : CFCMOV_Aliases<"ae", 3>; +defm : CFCMOV_Aliases<"e" , 4>; +defm : CFCMOV_Aliases<"ne", 5>; +defm : CFCMOV_Aliases<"be", 6>; +defm : CFCMOV_Aliases<"a" , 7>; +defm : CFCMOV_Aliases<"s" , 8>; +defm : CFCMOV_Aliases<"ns", 9>; +defm : CFCMOV_Aliases<"p" , 10>; +defm : CFCMOV_Aliases<"np", 11>; +defm : CFCMOV_Aliases<"l" , 12>; +defm : CFCMOV_Aliases<"ge", 13>; +defm : CFCMOV_Aliases<"le", 14>; +defm : CFCMOV_Aliases<"g" , 15>; + // Condition dump instructions Alias def : InstAlias<"jo\t$dst", (JCC_1 brtarget8:$dst, 0), 0>; def : InstAlias<"jno\t$dst", (JCC_1 brtarget8:$dst, 1), 0>; diff --git a/llvm/lib/Target/X86/X86InstrCMovSetCC.td b/llvm/lib/Target/X86/X86InstrCMovSetCC.td index 2e31c05cd687d33be75803d66adeb7c4b1b8a7f8..d41591f68a6050d690f2b97897b8abc01d183666 100644 --- a/llvm/lib/Target/X86/X86InstrCMovSetCC.td +++ b/llvm/lib/Target/X86/X86InstrCMovSetCC.td @@ -13,46 +13,72 @@ // CMOV instructions. -let isCodeGenOnly = 1, ForceDisassemble = 1 in { -let Uses = [EFLAGS], Predicates = [HasCMOV], Constraints = "$src1 = $dst", - isCommutable = 1, SchedRW = [WriteCMOV] in { - def CMOV16rr - : I<0x40, MRMSrcRegCC, (outs GR16:$dst), (ins GR16:$src1, GR16:$src2, ccode:$cond), - "cmov${cond}{w}\t{$src2, $dst|$dst, $src2}", - [(set GR16:$dst, - (X86cmov GR16:$src1, GR16:$src2, timm:$cond, EFLAGS))]>, - TB, OpSize16; - def CMOV32rr - : I<0x40, MRMSrcRegCC, (outs GR32:$dst), (ins GR32:$src1, GR32:$src2, ccode:$cond), - "cmov${cond}{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, - (X86cmov GR32:$src1, GR32:$src2, timm:$cond, EFLAGS))]>, - TB, OpSize32; - def CMOV64rr - :RI<0x40, MRMSrcRegCC, (outs GR64:$dst), (ins GR64:$src1, GR64:$src2, ccode:$cond), - "cmov${cond}{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, - (X86cmov GR64:$src1, GR64:$src2, timm:$cond, EFLAGS))]>, TB; +multiclass Cmov<X86TypeInfo t, string args, bit ndd = 0, string suffix = ""> { +let isCommutable = 1, SchedRW = [WriteCMOV] in + def rr#suffix : ITy<0x40, MRMSrcRegCC, t, (outs t.RegClass:$dst), + (ins t.RegClass:$src1, t.RegClass:$src2, ccode:$cond), + "cmov${cond}", args, + [(set t.RegClass:$dst, (X86cmov t.RegClass:$src1, + t.RegClass:$src2, timm:$cond, EFLAGS))]>, UseEFLAGS, NDD<ndd>; +let SchedRW = [WriteCMOV.Folded, WriteCMOV.ReadAfterFold] in + def rm#suffix : ITy<0x40, MRMSrcMemCC, t, (outs t.RegClass:$dst), + (ins t.RegClass:$src1, t.MemOperand:$src2, ccode:$cond), + "cmov${cond}", args, + [(set t.RegClass:$dst, (X86cmov t.RegClass:$src1, + (t.LoadNode addr:$src2), timm:$cond, EFLAGS))]>, UseEFLAGS, NDD<ndd>; +} + +multiclass Cfcmov<X86TypeInfo t> { +let isCommutable = 1, SchedRW = [WriteCMOV] in { +let Predicates = [HasCMOV, HasCF, In64BitMode] in { + def rr : ITy<0x40, MRMDestRegCC, t, (outs t.RegClass:$dst), + (ins t.RegClass:$src1, ccode:$cond), + "cfcmov${cond}", unaryop_ndd_args, + [(set t.RegClass:$dst, + (X86cmov 0, t.RegClass:$src1, timm:$cond, EFLAGS))]>, UseEFLAGS, NF; + def rr_REV : ITy<0x40, MRMSrcRegCC, t, (outs t.RegClass:$dst), + (ins t.RegClass:$src1, ccode:$cond), + "cfcmov${cond}", unaryop_ndd_args, + []>, UseEFLAGS, EVEX, T_MAP4; +} +let Predicates = [HasCMOV, HasCF, HasNDD, In64BitMode] in + def rr_ND : ITy<0x40, MRMSrcRegCC, t, (outs t.RegClass:$dst), + (ins t.RegClass:$src1, t.RegClass:$src2, ccode:$cond), + "cfcmov${cond}", binop_ndd_args, []>, UseEFLAGS, NDD<1>, NF; } +let SchedRW = [WriteCMOV.Folded, WriteCMOV.ReadAfterFold] in { + let Predicates = [HasCMOV, HasCF, In64BitMode], mayLoad = 1 in + def rm : ITy<0x40, MRMSrcMemCC, t, (outs t.RegClass:$dst), + (ins t.MemOperand:$src1, ccode:$cond), + "cfcmov${cond}", unaryop_ndd_args, []>, UseEFLAGS, EVEX, T_MAP4; + let Predicates = [HasCMOV, HasCF, HasNDD, In64BitMode], mayLoad = 1 in + def rm_ND : ITy<0x40, MRMSrcMemCC, t, (outs t.RegClass:$dst), + (ins t.RegClass:$src1, t.MemOperand:$src2, ccode:$cond), + "cfcmov${cond}", binop_ndd_args, []>, UseEFLAGS, NDD<1>, NF; +} +let SchedRW = [WriteCMOV, ReadDefault, ReadDefault, ReadDefault, ReadDefault, ReadDefault], + Predicates = [HasCMOV, HasCF, In64BitMode], mayStore = 1 in + def mr : ITy<0x40, MRMDestMemCC, t, (outs t.MemOperand:$dst), + (ins t.RegClass:$src1, ccode:$cond), + "cfcmov${cond}", unaryop_ndd_args, []>, UseEFLAGS, NF; +} + +let isCodeGenOnly = 1, ForceDisassemble = 1 in { + let Predicates = [HasCMOV, NoNDD], Constraints = "$dst = $src1" in { + defm CMOV16 : Cmov<Xi16, binop_args>, OpSize16, TB; + defm CMOV32 : Cmov<Xi32, binop_args>, OpSize32, TB; + defm CMOV64 : Cmov<Xi64, binop_args>, TB; + } -let Uses = [EFLAGS], Predicates = [HasCMOV], Constraints = "$src1 = $dst", - SchedRW = [WriteCMOV.Folded, WriteCMOV.ReadAfterFold] in { - def CMOV16rm - : I<0x40, MRMSrcMemCC, (outs GR16:$dst), (ins GR16:$src1, i16mem:$src2, ccode:$cond), - "cmov${cond}{w}\t{$src2, $dst|$dst, $src2}", - [(set GR16:$dst, (X86cmov GR16:$src1, (loadi16 addr:$src2), - timm:$cond, EFLAGS))]>, TB, OpSize16; - def CMOV32rm - : I<0x40, MRMSrcMemCC, (outs GR32:$dst), (ins GR32:$src1, i32mem:$src2, ccode:$cond), - "cmov${cond}{l}\t{$src2, $dst|$dst, $src2}", - [(set GR32:$dst, (X86cmov GR32:$src1, (loadi32 addr:$src2), - timm:$cond, EFLAGS))]>, TB, OpSize32; - def CMOV64rm - :RI<0x40, MRMSrcMemCC, (outs GR64:$dst), (ins GR64:$src1, i64mem:$src2, ccode:$cond), - "cmov${cond}{q}\t{$src2, $dst|$dst, $src2}", - [(set GR64:$dst, (X86cmov GR64:$src1, (loadi64 addr:$src2), - timm:$cond, EFLAGS))]>, TB; -} // Uses = [EFLAGS], Predicates = [HasCMOV], Constraints = "$src1 = $dst" + let Predicates = [HasCMOV, HasNDD, In64BitMode] in { + defm CMOV16 : Cmov<Xi16, binop_ndd_args, 1, "_ND">, PD; + defm CMOV32 : Cmov<Xi32, binop_ndd_args, 1, "_ND">; + defm CMOV64 : Cmov<Xi64, binop_ndd_args, 1, "_ND">; + } + + defm CFCMOV16 : Cfcmov<Xi16>, PD; + defm CFCMOV32 : Cfcmov<Xi32>; + defm CFCMOV64 : Cfcmov<Xi64>; } // isCodeGenOnly = 1, ForceDisassemble = 1 def inv_cond_XFORM : SDNodeXForm<imm, [{ @@ -63,7 +89,7 @@ def inv_cond_XFORM : SDNodeXForm<imm, [{ // Conditional moves with folded loads with operands swapped and conditions // inverted. -let Predicates = [HasCMOV] in { +let Predicates = [HasCMOV, NoNDD] in { def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, timm:$cond, EFLAGS), (CMOV16rm GR16:$src2, addr:$src1, (inv_cond_XFORM timm:$cond))>; def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, timm:$cond, EFLAGS), @@ -72,6 +98,23 @@ let Predicates = [HasCMOV] in { (CMOV64rm GR64:$src2, addr:$src1, (inv_cond_XFORM timm:$cond))>; } +let Predicates = [HasCMOV, HasNDD] in { + def : Pat<(X86cmov (loadi16 addr:$src1), GR16:$src2, timm:$cond, EFLAGS), + (CMOV16rm_ND GR16:$src2, addr:$src1, (inv_cond_XFORM timm:$cond))>; + def : Pat<(X86cmov (loadi32 addr:$src1), GR32:$src2, timm:$cond, EFLAGS), + (CMOV32rm_ND GR32:$src2, addr:$src1, (inv_cond_XFORM timm:$cond))>; + def : Pat<(X86cmov (loadi64 addr:$src1), GR64:$src2, timm:$cond, EFLAGS), + (CMOV64rm_ND GR64:$src2, addr:$src1, (inv_cond_XFORM timm:$cond))>; +} +let Predicates = [HasCMOV, HasCF] in { + def : Pat<(X86cmov GR16:$src1, 0, timm:$cond, EFLAGS), + (CFCMOV16rr GR16:$src1, (inv_cond_XFORM timm:$cond))>; + def : Pat<(X86cmov GR32:$src1, 0, timm:$cond, EFLAGS), + (CFCMOV32rr GR32:$src1, (inv_cond_XFORM timm:$cond))>; + def : Pat<(X86cmov GR64:$src1, 0, timm:$cond, EFLAGS), + (CFCMOV64rr GR64:$src1, (inv_cond_XFORM timm:$cond))>; +} + // SetCC instructions. let Uses = [EFLAGS], isCodeGenOnly = 1, ForceDisassemble = 1 in { def SETCCr : I<0x90, MRMXrCC, (outs GR8:$dst), (ins ccode:$cond), diff --git a/llvm/lib/Target/X86/X86InstrCompiler.td b/llvm/lib/Target/X86/X86InstrCompiler.td index f393f86e64aaddd4e7cef159f1902d2945b3ef45..ce3b6af4cab47bc6e2e7c418470cbda237f74775 100644 --- a/llvm/lib/Target/X86/X86InstrCompiler.td +++ b/llvm/lib/Target/X86/X86InstrCompiler.td @@ -507,6 +507,16 @@ def TLS_base_addrX32 : I<0, Pseudo, (outs), (ins i32mem:$sym), Requires<[In64BitMode, NotLP64]>; } +// TLSDESC only clobbers EAX and EFLAGS. ESP is marked as a use to prevent +// stack-pointer assignments that appear immediately before calls from +// potentially appearing dead. +let Defs = [EAX, EFLAGS], usesCustomInserter = 1, Uses = [RSP, SSP] in { + def TLS_desc32 : I<0, Pseudo, (outs), (ins i32mem:$sym), + "# TLS_desc32", [(X86tlsdesc tls32addr:$sym)]>; + def TLS_desc64 : I<0, Pseudo, (outs), (ins i64mem:$sym), + "# TLS_desc64", [(X86tlsdesc tls64addr:$sym)]>; +} + // Darwin TLS Support // For i386, the address of the thunk is passed on the stack, on return the // address of the variable is in %eax. %ecx is trashed during the function diff --git a/llvm/lib/Target/X86/X86InstrFormats.td b/llvm/lib/Target/X86/X86InstrFormats.td index 13014293267b324e419c4768b77f0c7dec2e392e..31ee288c6f8bb228f23c1259cc2195dc174b7a88 100644 --- a/llvm/lib/Target/X86/X86InstrFormats.td +++ b/llvm/lib/Target/X86/X86InstrFormats.td @@ -28,6 +28,8 @@ def RawFrmImm8 : Format<7>; def RawFrmImm16 : Format<8>; def AddCCFrm : Format<9>; def PrefixByte : Format<10>; +def MRMDestRegCC : Format<18>; +def MRMDestMemCC : Format<19>; def MRMDestMem4VOp3CC : Format<20>; def MRMr0 : Format<21>; def MRMSrcMemFSIB : Format<22>; diff --git a/llvm/lib/Target/X86/X86InstrFragments.td b/llvm/lib/Target/X86/X86InstrFragments.td index adf527d72f5b43f1f1836d718384a04ea9e4818e..f14c7200af968a902776810f6e278e359ff268f2 100644 --- a/llvm/lib/Target/X86/X86InstrFragments.td +++ b/llvm/lib/Target/X86/X86InstrFragments.td @@ -223,6 +223,9 @@ def X86tlsaddr : SDNode<"X86ISD::TLSADDR", SDT_X86TLSADDR, def X86tlsbaseaddr : SDNode<"X86ISD::TLSBASEADDR", SDT_X86TLSBASEADDR, [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; +def X86tlsdesc : SDNode<"X86ISD::TLSDESC", SDT_X86TLSADDR, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; + def X86ehret : SDNode<"X86ISD::EH_RETURN", SDT_X86EHRET, [SDNPHasChain]>; diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp index b65f49527ae5dd35e689e5a296eb652ee46ef52e..f24334312c116acc081fa8dc1dc2ad59312cd4e8 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -2637,9 +2637,9 @@ MachineInstr *X86InstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI, WorkingMI = CloneIfNew(MI); WorkingMI->setDesc(get(Opc)); break; - case X86::CMOV16rr: - case X86::CMOV32rr: - case X86::CMOV64rr: { + CASE_ND(CMOV16rr) + CASE_ND(CMOV32rr) + CASE_ND(CMOV64rr) { WorkingMI = CloneIfNew(MI); unsigned OpNo = MI.getDesc().getNumOperands() - 1; X86::CondCode CC = static_cast<X86::CondCode>(MI.getOperand(OpNo).getImm()); @@ -3120,7 +3120,8 @@ bool X86InstrInfo::hasCommutePreference(MachineInstr &MI, bool &Commute) const { int X86::getCondSrcNoFromDesc(const MCInstrDesc &MCID) { unsigned Opcode = MCID.getOpcode(); - if (!(X86::isJCC(Opcode) || X86::isSETCC(Opcode) || X86::isCMOVCC(Opcode))) + if (!(X86::isJCC(Opcode) || X86::isSETCC(Opcode) || X86::isCMOVCC(Opcode) || + X86::isCFCMOVCC(Opcode))) return -1; // Assume that condition code is always the last use operand. unsigned NumUses = MCID.getNumOperands() - MCID.getNumDefs(); @@ -3151,6 +3152,11 @@ X86::CondCode X86::getCondFromCMov(const MachineInstr &MI) { : X86::COND_INVALID; } +X86::CondCode X86::getCondFromCFCMov(const MachineInstr &MI) { + return X86::isCFCMOVCC(MI.getOpcode()) ? X86::getCondFromMI(MI) + : X86::COND_INVALID; +} + /// Return the inverse of the specified condition, /// e.g. turning COND_E to COND_NE. X86::CondCode X86::GetOppositeBranchCondition(X86::CondCode CC) { @@ -3312,16 +3318,21 @@ X86::getX86ConditionCode(CmpInst::Predicate Predicate) { } /// Return a cmov opcode for the given register size in bytes, and operand type. -unsigned X86::getCMovOpcode(unsigned RegBytes, bool HasMemoryOperand) { +unsigned X86::getCMovOpcode(unsigned RegBytes, bool HasMemoryOperand, + bool HasNDD) { switch (RegBytes) { default: llvm_unreachable("Illegal register size!"); +#define GET_ND_IF_ENABLED(OPC) (HasNDD ? OPC##_ND : OPC) case 2: - return HasMemoryOperand ? X86::CMOV16rm : X86::CMOV16rr; + return HasMemoryOperand ? GET_ND_IF_ENABLED(X86::CMOV16rm) + : GET_ND_IF_ENABLED(X86::CMOV16rr); case 4: - return HasMemoryOperand ? X86::CMOV32rm : X86::CMOV32rr; + return HasMemoryOperand ? GET_ND_IF_ENABLED(X86::CMOV32rm) + : GET_ND_IF_ENABLED(X86::CMOV32rr); case 8: - return HasMemoryOperand ? X86::CMOV64rm : X86::CMOV64rr; + return HasMemoryOperand ? GET_ND_IF_ENABLED(X86::CMOV64rm) + : GET_ND_IF_ENABLED(X86::CMOV64rr); } } @@ -4047,8 +4058,9 @@ void X86InstrInfo::insertSelect(MachineBasicBlock &MBB, const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo(); const TargetRegisterClass &RC = *MRI.getRegClass(DstReg); assert(Cond.size() == 1 && "Invalid Cond array"); - unsigned Opc = X86::getCMovOpcode(TRI.getRegSizeInBits(RC) / 8, - false /*HasMemoryOperand*/); + unsigned Opc = + X86::getCMovOpcode(TRI.getRegSizeInBits(RC) / 8, + false /*HasMemoryOperand*/, Subtarget.hasNDD()); BuildMI(MBB, I, DL, get(Opc), DstReg) .addReg(FalseReg) .addReg(TrueReg) @@ -5583,9 +5595,13 @@ static unsigned convertALUrr2ALUri(unsigned Opc) { case X86::FROM: \ return X86::TO; FROM_TO(TEST64rr, TEST64ri32) + FROM_TO(CTEST64rr, CTEST64ri32) FROM_TO(CMP64rr, CMP64ri32) + FROM_TO(CCMP64rr, CCMP64ri32) FROM_TO(TEST32rr, TEST32ri) + FROM_TO(CTEST32rr, CTEST32ri) FROM_TO(CMP32rr, CMP32ri) + FROM_TO(CCMP32rr, CCMP32ri) #undef FROM_TO } } @@ -5685,7 +5701,8 @@ bool X86InstrInfo::foldImmediateImpl(MachineInstr &UseMI, MachineInstr *DefMI, UseMI.findRegisterUseOperandIdx(Reg) != 2) return false; // For CMP instructions the immediate can only be at index 1. - if ((NewOpc == X86::CMP64ri32 || NewOpc == X86::CMP32ri) && + if (((NewOpc == X86::CMP64ri32 || NewOpc == X86::CMP32ri) || + (NewOpc == X86::CCMP64ri32 || NewOpc == X86::CCMP32ri)) && UseMI.findRegisterUseOperandIdx(Reg) != 1) return false; @@ -5730,7 +5747,7 @@ bool X86InstrInfo::foldImmediateImpl(MachineInstr &UseMI, MachineInstr *DefMI, unsigned Op1 = 1, Op2 = CommuteAnyOperandIndex; unsigned ImmOpNum = 2; if (!UseMI.getOperand(0).isDef()) { - Op1 = 0; // TEST, CMP + Op1 = 0; // TEST, CMP, CTEST, CCMP ImmOpNum = 1; } if (Opc == TargetOpcode::COPY) @@ -10565,15 +10582,15 @@ bool X86InstrInfo::getMachineCombinerPatterns( bool DoRegPressureReduce) const { unsigned Opc = Root.getOpcode(); switch (Opc) { - default: - return TargetInstrInfo::getMachineCombinerPatterns(Root, Patterns, - DoRegPressureReduce); case X86::VPDPWSSDrr: case X86::VPDPWSSDrm: case X86::VPDPWSSDYrr: case X86::VPDPWSSDYrm: { - Patterns.push_back(MachineCombinerPattern::DPWSSD); - return true; + if (!Subtarget.hasFastDPWSSD()) { + Patterns.push_back(MachineCombinerPattern::DPWSSD); + return true; + } + break; } case X86::VPDPWSSDZ128r: case X86::VPDPWSSDZ128m: @@ -10581,11 +10598,15 @@ bool X86InstrInfo::getMachineCombinerPatterns( case X86::VPDPWSSDZ256m: case X86::VPDPWSSDZr: case X86::VPDPWSSDZm: { - if (Subtarget.hasBWI()) + if (Subtarget.hasBWI() && !Subtarget.hasFastDPWSSD()) { Patterns.push_back(MachineCombinerPattern::DPWSSD); - return true; + return true; + } + break; } } + return TargetInstrInfo::getMachineCombinerPatterns(Root, + Patterns, DoRegPressureReduce); } static void diff --git a/llvm/lib/Target/X86/X86InstrInfo.h b/llvm/lib/Target/X86/X86InstrInfo.h index 0e5fcbeda08f799bce5b6437cdc972def9efd83d..e719be0caf3ee15bd2df5228c609ead0c169f7a9 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.h +++ b/llvm/lib/Target/X86/X86InstrInfo.h @@ -42,7 +42,8 @@ enum AsmComments { std::pair<CondCode, bool> getX86ConditionCode(CmpInst::Predicate Predicate); /// Return a cmov opcode for the given register size in bytes, and operand type. -unsigned getCMovOpcode(unsigned RegBytes, bool HasMemoryOperand = false); +unsigned getCMovOpcode(unsigned RegBytes, bool HasMemoryOperand = false, + bool HasNDD = false); /// Return the source operand # for condition code by \p MCID. If the /// instruction doesn't have a condition code, return -1. @@ -61,6 +62,9 @@ CondCode getCondFromSETCC(const MachineInstr &MI); // Turn CMOV instruction into condition code. CondCode getCondFromCMov(const MachineInstr &MI); +// Turn CFCMOV instruction into condition code. +CondCode getCondFromCFCMov(const MachineInstr &MI); + /// GetOppositeBranchCondition - Return the inverse of the specified cond, /// e.g. turning COND_E to COND_NE. CondCode GetOppositeBranchCondition(CondCode CC); diff --git a/llvm/lib/Target/X86/X86InstrPredicates.td b/llvm/lib/Target/X86/X86InstrPredicates.td index 7dd51ba6c027aec4d47fc306883470c4ce627412..9f2709d6b1a206b4922e075bd064d3ba46d5de66 100644 --- a/llvm/lib/Target/X86/X86InstrPredicates.td +++ b/llvm/lib/Target/X86/X86InstrPredicates.td @@ -45,6 +45,7 @@ def NoEGPR : Predicate<"!Subtarget->hasEGPR()">; // entries, so that the NDD variant can be selected first to benefit RA. def HasNDD : Predicate<"Subtarget->hasNDD()">; def NoNDD : Predicate<"!Subtarget->hasNDD()">; +def HasCF : Predicate<"Subtarget->hasCF()">; def HasCMOV : Predicate<"Subtarget->canUseCMOV()">; def NoCMOV : Predicate<"!Subtarget->canUseCMOV()">; def HasNOPL : Predicate<"Subtarget->hasNOPL()">; @@ -238,5 +239,6 @@ def HasFastSHLDRotate : Predicate<"Subtarget->hasFastSHLDRotate()">; def HasERMSB : Predicate<"Subtarget->hasERMSB()">; def HasFSRM : Predicate<"Subtarget->hasFSRM()">; def HasMFence : Predicate<"Subtarget->hasMFence()">; +def HasFastDPWSSD: Predicate<"Subtarget->hasFastDPWSSD()">; def UseIndirectThunkCalls : Predicate<"Subtarget->useIndirectThunkCalls()">; def NotUseIndirectThunkCalls : Predicate<"!Subtarget->useIndirectThunkCalls()">; diff --git a/llvm/lib/Target/X86/X86InstrUtils.td b/llvm/lib/Target/X86/X86InstrUtils.td index 04d9d104ebc4b09c5a1643ba37a2a1a4a9f5cee7..8387b76a40cdda6a718c216244ff8af3971f6518 100644 --- a/llvm/lib/Target/X86/X86InstrUtils.td +++ b/llvm/lib/Target/X86/X86InstrUtils.td @@ -119,6 +119,8 @@ class NDD<bit ndd> { class NF: T_MAP4, EVEX, EVEX_NF; // PL - Helper for promoted legacy instructions class PL: T_MAP4, EVEX, ExplicitEVEXPrefix; +// ZU - Helper for Zero Upper instructions +class ZU: T_MAP4, EVEX, EVEX_B; //===----------------------------------------------------------------------===// // X86 Type infomation definitions diff --git a/llvm/lib/Target/X86/X86LowerAMXType.cpp b/llvm/lib/Target/X86/X86LowerAMXType.cpp index a57c0fe15788409e2bae0513b7d2c29fd9aa3ac4..b69058787a4e25a7114b59f7cfae90f2a873ca32 100644 --- a/llvm/lib/Target/X86/X86LowerAMXType.cpp +++ b/llvm/lib/Target/X86/X86LowerAMXType.cpp @@ -102,7 +102,7 @@ static AllocaInst *createAllocaInstAtEntry(IRBuilder<> &Builder, BasicBlock *BB, auto AllocaAlignment = DL.getPrefTypeAlign(Type::getX86_AMXTy(Ctx)); unsigned AllocaAS = DL.getAllocaAddrSpace(); AllocaInst *AllocaRes = - new AllocaInst(Ty, AllocaAS, "", &F.getEntryBlock().front()); + new AllocaInst(Ty, AllocaAS, "", F.getEntryBlock().begin()); AllocaRes->setAlignment(AllocaAlignment); return AllocaRes; } @@ -453,7 +453,7 @@ static Value *getAllocaPos(BasicBlock *BB) { unsigned AllocaAS = DL.getAllocaAddrSpace(); Type *V256I32Ty = VectorType::get(Builder.getInt32Ty(), 256, false); AllocaInst *AllocaRes = - new AllocaInst(V256I32Ty, AllocaAS, "", &F->getEntryBlock().front()); + new AllocaInst(V256I32Ty, AllocaAS, "", F->getEntryBlock().begin()); BasicBlock::iterator Iter = AllocaRes->getIterator(); ++Iter; Builder.SetInsertPoint(&*Iter); diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp index 64d4d411e7b43b706ba9ae20fc532520782e1b53..e2330ff34c1753b0ee9ee806be1da0cd24940b81 100644 --- a/llvm/lib/Target/X86/X86MCInstLower.cpp +++ b/llvm/lib/Target/X86/X86MCInstLower.cpp @@ -519,10 +519,8 @@ void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { void X86AsmPrinter::LowerTlsAddr(X86MCInstLower &MCInstLowering, const MachineInstr &MI) { NoAutoPaddingScope NoPadScope(*OutStreamer); - bool Is64Bits = MI.getOpcode() != X86::TLS_addr32 && - MI.getOpcode() != X86::TLS_base_addr32; - bool Is64BitsLP64 = MI.getOpcode() == X86::TLS_addr64 || - MI.getOpcode() == X86::TLS_base_addr64; + bool Is64Bits = getSubtarget().is64Bit(); + bool Is64BitsLP64 = getSubtarget().isTarget64BitLP64(); MCContext &Ctx = OutStreamer->getContext(); MCSymbolRefExpr::VariantKind SRVK; @@ -539,6 +537,10 @@ void X86AsmPrinter::LowerTlsAddr(X86MCInstLower &MCInstLowering, case X86::TLS_base_addrX32: SRVK = MCSymbolRefExpr::VK_TLSLD; break; + case X86::TLS_desc32: + case X86::TLS_desc64: + SRVK = MCSymbolRefExpr::VK_TLSDESC; + break; default: llvm_unreachable("unexpected opcode"); } @@ -554,7 +556,26 @@ void X86AsmPrinter::LowerTlsAddr(X86MCInstLower &MCInstLowering, bool UseGot = MMI->getModule()->getRtLibUseGOT() && Ctx.getTargetOptions()->X86RelaxRelocations; - if (Is64Bits) { + if (SRVK == MCSymbolRefExpr::VK_TLSDESC) { + const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create( + MCInstLowering.GetSymbolFromOperand(MI.getOperand(3)), + MCSymbolRefExpr::VK_TLSCALL, Ctx); + EmitAndCountInstruction( + MCInstBuilder(Is64BitsLP64 ? X86::LEA64r : X86::LEA32r) + .addReg(Is64BitsLP64 ? X86::RAX : X86::EAX) + .addReg(Is64Bits ? X86::RIP : X86::EBX) + .addImm(1) + .addReg(0) + .addExpr(Sym) + .addReg(0)); + EmitAndCountInstruction( + MCInstBuilder(Is64Bits ? X86::CALL64m : X86::CALL32m) + .addReg(Is64BitsLP64 ? X86::RAX : X86::EAX) + .addImm(1) + .addReg(0) + .addExpr(Expr) + .addReg(0)); + } else if (Is64Bits) { bool NeedsPadding = SRVK == MCSymbolRefExpr::VK_TLSGD; if (NeedsPadding && Is64BitsLP64) EmitAndCountInstruction(MCInstBuilder(X86::DATA16_PREFIX)); @@ -2164,6 +2185,8 @@ void X86AsmPrinter::emitInstruction(const MachineInstr *MI) { case X86::TLS_base_addr32: case X86::TLS_base_addr64: case X86::TLS_base_addrX32: + case X86::TLS_desc32: + case X86::TLS_desc64: return LowerTlsAddr(MCInstLowering, *MI); case X86::MOVPC32r: { diff --git a/llvm/lib/Target/X86/X86SchedBroadwell.td b/llvm/lib/Target/X86/X86SchedBroadwell.td index 61a8832000e2fadedb8084fed1f10cd3af76e3b7..0027de851df75d4f3c0b836b75f067f912edaff7 100644 --- a/llvm/lib/Target/X86/X86SchedBroadwell.td +++ b/llvm/lib/Target/X86/X86SchedBroadwell.td @@ -471,9 +471,11 @@ defm : X86WriteResPairUnsupported<WritePSADBWZ>; defm : BWWriteResPair<WritePHMINPOS, [BWPort0], 5>; // Vector PHMINPOS. // Vector integer shifts. -defm : BWWriteResPair<WriteVecShift, [BWPort0], 1, [1], 1, 5>; -defm : BWWriteResPair<WriteVecShiftX, [BWPort0,BWPort5], 2, [1,1], 2, 5>; +defm : X86WriteRes<WriteVecShift, [BWPort0], 1, [1], 1>; +defm : X86WriteRes<WriteVecShiftX, [BWPort0,BWPort5], 2, [1,1], 2>; defm : X86WriteRes<WriteVecShiftY, [BWPort0,BWPort5], 4, [1,1], 2>; +defm : X86WriteRes<WriteVecShiftLd, [BWPort0,BWPort23], 6, [1,1], 2>; +defm : X86WriteRes<WriteVecShiftXLd, [BWPort0,BWPort23], 7, [1,1], 2>; defm : X86WriteRes<WriteVecShiftYLd, [BWPort0,BWPort23], 7, [1,1], 2>; defm : X86WriteResPairUnsupported<WriteVecShiftZ>; diff --git a/llvm/lib/Target/X86/X86SchedHaswell.td b/llvm/lib/Target/X86/X86SchedHaswell.td index 8795ca95c5593766bbd962ee9255e162b825d57f..a11b470b1f5182ed64f9eb33bebb390d356be197 100644 --- a/llvm/lib/Target/X86/X86SchedHaswell.td +++ b/llvm/lib/Target/X86/X86SchedHaswell.td @@ -469,10 +469,12 @@ defm : HWWriteResPair<WritePSADBWZ, [HWPort0], 5, [1], 1, 7>; // Unsupported = 1 defm : HWWriteResPair<WritePHMINPOS, [HWPort0], 5, [1], 1, 6>; // Vector integer shifts. -defm : HWWriteResPair<WriteVecShift, [HWPort0], 1, [1], 1, 5>; -defm : HWWriteResPair<WriteVecShiftX, [HWPort0,HWPort5], 2, [1,1], 2, 6>; +defm : X86WriteRes<WriteVecShift, [HWPort0], 1, [1], 1>; +defm : X86WriteRes<WriteVecShiftX, [HWPort0,HWPort5], 2, [1,1], 2>; defm : X86WriteRes<WriteVecShiftY, [HWPort0,HWPort5], 4, [1,1], 2>; defm : X86WriteRes<WriteVecShiftZ, [HWPort0,HWPort5], 4, [1,1], 2>; // Unsupported = 1 +defm : X86WriteRes<WriteVecShiftLd, [HWPort0,HWPort23], 6, [1,1], 2>; +defm : X86WriteRes<WriteVecShiftXLd, [HWPort0,HWPort23], 8, [1,1], 2>; defm : X86WriteRes<WriteVecShiftYLd, [HWPort0,HWPort23], 8, [1,1], 2>; defm : X86WriteRes<WriteVecShiftZLd, [HWPort0,HWPort23], 8, [1,1], 2>; // Unsupported = 1 diff --git a/llvm/lib/Target/X86/X86SchedIceLake.td b/llvm/lib/Target/X86/X86SchedIceLake.td index 3981279abc3637f0b9f36c37f8aad6cac2c446e3..2d296771b1c07d7b4b6d3119d3e8910c9ece3856 100644 --- a/llvm/lib/Target/X86/X86SchedIceLake.td +++ b/llvm/lib/Target/X86/X86SchedIceLake.td @@ -413,9 +413,9 @@ defm : ICXWriteResPair<WritePHMINPOS, [ICXPort0], 4, [1], 1, 6>; // Vector PHMIN // Vector integer shifts. defm : ICXWriteResPair<WriteVecShift, [ICXPort0], 1, [1], 1, 5>; -defm : X86WriteRes<WriteVecShiftX, [ICXPort5,ICXPort01], 2, [1,1], 2>; -defm : X86WriteRes<WriteVecShiftY, [ICXPort5,ICXPort01], 4, [1,1], 2>; -defm : X86WriteRes<WriteVecShiftZ, [ICXPort5,ICXPort0], 4, [1,1], 2>; +defm : X86WriteRes<WriteVecShiftX, [ICXPort01,ICXPort15], 2, [1,1], 2>; +defm : X86WriteRes<WriteVecShiftY, [ICXPort01,ICXPort5], 4, [1,1], 2>; +defm : X86WriteRes<WriteVecShiftZ, [ICXPort0,ICXPort5], 4, [1,1], 2>; defm : X86WriteRes<WriteVecShiftXLd, [ICXPort01,ICXPort23], 7, [1,1], 2>; defm : X86WriteRes<WriteVecShiftYLd, [ICXPort01,ICXPort23], 8, [1,1], 2>; defm : X86WriteRes<WriteVecShiftZLd, [ICXPort0,ICXPort23], 8, [1,1], 2>; diff --git a/llvm/lib/Target/X86/X86TargetMachine.h b/llvm/lib/Target/X86/X86TargetMachine.h index 0fd3e47aaefe7ee1f20c10ec60023adff83abdea..4e7ded16729d07c4b55413135707b8e77fd97b77 100644 --- a/llvm/lib/Target/X86/X86TargetMachine.h +++ b/llvm/lib/Target/X86/X86TargetMachine.h @@ -60,7 +60,7 @@ public: Error buildCodeGenPipeline(ModulePassManager &, raw_pwrite_stream &, raw_pwrite_stream *, CodeGenFileType, - CGPassBuilderOption, + const CGPassBuilderOption &, PassInstrumentationCallbacks *) override; bool isJIT() const { return IsJIT; } diff --git a/llvm/lib/Target/X86/X86TargetTransformInfo.cpp b/llvm/lib/Target/X86/X86TargetTransformInfo.cpp index d336ab9d309c4ee629c148fb7cb086b3b9a13c5b..2ec29463d2fa400f6206bbda5fa35dd29538449d 100644 --- a/llvm/lib/Target/X86/X86TargetTransformInfo.cpp +++ b/llvm/lib/Target/X86/X86TargetTransformInfo.cpp @@ -1480,6 +1480,14 @@ InstructionCost X86TTIImpl::getShuffleCost(TTI::ShuffleKind Kind, Kind = improveShuffleKindFromMask(Kind, Mask, BaseTp, Index, SubTp); + // Recognize a basic concat_vector shuffle. + if (Kind == TTI::SK_PermuteTwoSrc && + Mask.size() == (2 * BaseTp->getElementCount().getKnownMinValue()) && + ShuffleVectorInst::isIdentityMask(Mask, Mask.size())) + return getShuffleCost(TTI::SK_InsertSubvector, + VectorType::getDoubleElementsVectorType(BaseTp), Mask, + CostKind, Mask.size() / 2, BaseTp); + // Treat Transpose as 2-op shuffles - there's no difference in lowering. if (Kind == TTI::SK_Transpose) Kind = TTI::SK_PermuteTwoSrc; @@ -5651,7 +5659,7 @@ InstructionCost X86TTIImpl::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, return TTI::TCC_Free; break; case Intrinsic::experimental_patchpoint_void: - case Intrinsic::experimental_patchpoint_i64: + case Intrinsic::experimental_patchpoint: if ((Idx < 4) || (Imm.getBitWidth() <= 64 && Imm.isSignedIntN(64))) return TTI::TCC_Free; break; diff --git a/llvm/lib/Target/X86/X86TargetTransformInfo.h b/llvm/lib/Target/X86/X86TargetTransformInfo.h index 1a5e6bc886aa67f724c82921b6b641e5ed989f57..23035f655098a7d1958256219d4423f5e530111e 100644 --- a/llvm/lib/Target/X86/X86TargetTransformInfo.h +++ b/llvm/lib/Target/X86/X86TargetTransformInfo.h @@ -94,6 +94,7 @@ class X86TTIImpl : public BasicTTIImplBase<X86TTIImpl> { X86::TuningNoDomainDelayBlend, X86::TuningPreferShiftShuffle, X86::TuningFastImmVectorShift, + X86::TuningFastDPWSSD, // Perf-tuning flags. X86::TuningFastGather, diff --git a/llvm/lib/Target/XCore/XCoreLowerThreadLocal.cpp b/llvm/lib/Target/XCore/XCoreLowerThreadLocal.cpp index b5a683de33ab135d65b3c25ddaf5ba1aa9ed7799..5e91cce1068b4650c8f0c71f748dd84f55b5659d 100644 --- a/llvm/lib/Target/XCore/XCoreLowerThreadLocal.cpp +++ b/llvm/lib/Target/XCore/XCoreLowerThreadLocal.cpp @@ -88,12 +88,15 @@ static bool replaceConstantExprOp(ConstantExpr *CE, Pass *P) { BasicBlock *PredBB = PN->getIncomingBlock(I); if (PredBB->getTerminator()->getNumSuccessors() > 1) PredBB = SplitEdge(PredBB, PN->getParent()); - Instruction *InsertPos = PredBB->getTerminator(); - Instruction *NewInst = CE->getAsInstruction(InsertPos); + BasicBlock::iterator InsertPos = + PredBB->getTerminator()->getIterator(); + Instruction *NewInst = CE->getAsInstruction(); + NewInst->insertBefore(*PredBB, InsertPos); PN->setOperand(I, NewInst); } } else if (Instruction *Instr = dyn_cast<Instruction>(WU)) { - Instruction *NewInst = CE->getAsInstruction(Instr); + Instruction *NewInst = CE->getAsInstruction(); + NewInst->insertBefore(*Instr->getParent(), Instr->getIterator()); Instr->replaceUsesOfWith(CE, NewInst); } else { ConstantExpr *CExpr = dyn_cast<ConstantExpr>(WU); diff --git a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp index 3f808298527f8fc960905b26984d9b4960b9d332..1fa00af2111e0c26901d1cacf924fafff67344e5 100644 --- a/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp +++ b/llvm/lib/Target/Xtensa/AsmParser/XtensaAsmParser.cpp @@ -244,7 +244,7 @@ public: /// getEndLoc - Gets location of the last token of this operand SMLoc getEndLoc() const override { return EndLoc; } - unsigned getReg() const override { + MCRegister getReg() const override { assert(Kind == Register && "Invalid type access!"); return Reg.RegNum; } diff --git a/llvm/lib/TargetParser/AArch64TargetParser.cpp b/llvm/lib/TargetParser/AArch64TargetParser.cpp index e36832f563eed8bc4e8aea9ce13f826add86336c..71099462d5ecff7ca28d8eac53c7982130ea20f3 100644 --- a/llvm/lib/TargetParser/AArch64TargetParser.cpp +++ b/llvm/lib/TargetParser/AArch64TargetParser.cpp @@ -186,11 +186,6 @@ void AArch64::ExtensionSet::enable(ArchExtKind E) { // Special cases for dependencies which vary depending on the base // architecture version. if (BaseArch) { - // +sve implies +f32mm if the base architecture is v8.6A+ or v9.1A+ - // It isn't the case in general that sve implies both f64mm and f32mm - if (E == AEK_SVE && BaseArch->is_superset(ARMV8_6A)) - enable(AEK_F32MM); - // +fp16 implies +fp16fml for v8.4A+, but not v9.0-A+ if (E == AEK_FP16 && BaseArch->is_superset(ARMV8_4A) && !BaseArch->is_superset(ARMV9A)) diff --git a/llvm/lib/TargetParser/Host.cpp b/llvm/lib/TargetParser/Host.cpp index ee4fd0425ca5e87e78e71658ad292eebf1e12902..d2c9bae97364e9f7eb1f2b35ec38d9872ead8abe 100644 --- a/llvm/lib/TargetParser/Host.cpp +++ b/llvm/lib/TargetParser/Host.cpp @@ -196,36 +196,53 @@ StringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) { .Case("0xb36", "arm1136j-s") .Case("0xb56", "arm1156t2-s") .Case("0xb76", "arm1176jz-s") + .Case("0xc05", "cortex-a5") + .Case("0xc07", "cortex-a7") .Case("0xc08", "cortex-a8") .Case("0xc09", "cortex-a9") .Case("0xc0f", "cortex-a15") + .Case("0xc0e", "cortex-a17") .Case("0xc20", "cortex-m0") .Case("0xc23", "cortex-m3") .Case("0xc24", "cortex-m4") + .Case("0xc27", "cortex-m7") + .Case("0xd20", "cortex-m23") + .Case("0xd21", "cortex-m33") .Case("0xd24", "cortex-m52") .Case("0xd22", "cortex-m55") + .Case("0xd23", "cortex-m85") + .Case("0xc18", "cortex-r8") + .Case("0xd13", "cortex-r52") + .Case("0xd15", "cortex-r82") .Case("0xd02", "cortex-a34") .Case("0xd04", "cortex-a35") .Case("0xd03", "cortex-a53") .Case("0xd05", "cortex-a55") .Case("0xd46", "cortex-a510") .Case("0xd80", "cortex-a520") + .Case("0xd88", "cortex-a520ae") .Case("0xd07", "cortex-a57") + .Case("0xd06", "cortex-a65") + .Case("0xd43", "cortex-a65ae") .Case("0xd08", "cortex-a72") .Case("0xd09", "cortex-a73") .Case("0xd0a", "cortex-a75") .Case("0xd0b", "cortex-a76") + .Case("0xd0e", "cortex-a76ae") .Case("0xd0d", "cortex-a77") .Case("0xd41", "cortex-a78") .Case("0xd42", "cortex-a78ae") + .Case("0xd4b", "cortex-a78c") .Case("0xd47", "cortex-a710") .Case("0xd4d", "cortex-a715") .Case("0xd81", "cortex-a720") + .Case("0xd89", "cortex-a720ae") .Case("0xd44", "cortex-x1") .Case("0xd4c", "cortex-x1c") .Case("0xd48", "cortex-x2") .Case("0xd4e", "cortex-x3") .Case("0xd82", "cortex-x4") + .Case("0xd4a", "neoverse-e1") .Case("0xd0c", "neoverse-n1") .Case("0xd49", "neoverse-n2") .Case("0xd40", "neoverse-v1") diff --git a/llvm/lib/TextAPI/BinaryReader/CMakeLists.txt b/llvm/lib/TextAPI/BinaryReader/CMakeLists.txt index cbdf7b2c969698bfc04e4842a21240935b425f0e..c4535310d91c17207308686e6a190f469a10f478 100644 --- a/llvm/lib/TextAPI/BinaryReader/CMakeLists.txt +++ b/llvm/lib/TextAPI/BinaryReader/CMakeLists.txt @@ -2,6 +2,7 @@ add_llvm_component_library(LLVMTextAPIBinaryReader DylibReader.cpp LINK_COMPONENTS + DebugInfoDWARF Support Object TextAPI diff --git a/llvm/lib/TextAPI/BinaryReader/DylibReader.cpp b/llvm/lib/TextAPI/BinaryReader/DylibReader.cpp index 0694d8f28df6bd816d6d352b9e75fb97b830509f..f92a2d19a63fc293b783872cfdeebb8f23709cea 100644 --- a/llvm/lib/TextAPI/BinaryReader/DylibReader.cpp +++ b/llvm/lib/TextAPI/BinaryReader/DylibReader.cpp @@ -12,7 +12,8 @@ #include "llvm/TextAPI/DylibReader.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringMap.h" +#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/Object/Binary.h" #include "llvm/Object/MachOUniversal.h" #include "llvm/Support/Endian.h" @@ -293,8 +294,11 @@ static Error readSymbols(MachOObjectFile *Obj, RecordsSlice &Slice, RecordLinkage Linkage = RecordLinkage::Unknown; SymbolFlags RecordFlags = SymbolFlags::None; - if (Opt.Undefineds && (Flags & SymbolRef::SF_Undefined)) { - Linkage = RecordLinkage::Undefined; + if (Flags & SymbolRef::SF_Undefined) { + if (Opt.Undefineds) + Linkage = RecordLinkage::Undefined; + else + continue; if (Flags & SymbolRef::SF_Weak) RecordFlags |= SymbolFlags::WeakReferenced; } else if (Flags & SymbolRef::SF_Exported) { @@ -429,3 +433,111 @@ DylibReader::get(MemoryBufferRef Buffer) { return convertToInterfaceFile(*SlicesOrErr); } + +static void DWARFErrorHandler(Error Err) { /**/ } + +static SymbolToSourceLocMap +accumulateLocs(MachOObjectFile &Obj, + const std::unique_ptr<DWARFContext> &DiCtx) { + SymbolToSourceLocMap LocMap; + for (const auto &Symbol : Obj.symbols()) { + Expected<uint32_t> FlagsOrErr = Symbol.getFlags(); + if (!FlagsOrErr) { + consumeError(FlagsOrErr.takeError()); + continue; + } + + if (!(*FlagsOrErr & SymbolRef::SF_Exported)) + continue; + + Expected<uint64_t> AddressOrErr = Symbol.getAddress(); + if (!AddressOrErr) { + consumeError(AddressOrErr.takeError()); + continue; + } + const uint64_t Address = *AddressOrErr; + + auto TypeOrErr = Symbol.getType(); + if (!TypeOrErr) { + consumeError(TypeOrErr.takeError()); + continue; + } + const bool IsCode = (*TypeOrErr & SymbolRef::ST_Function); + + auto *DWARFCU = IsCode ? DiCtx->getCompileUnitForCodeAddress(Address) + : DiCtx->getCompileUnitForDataAddress(Address); + if (!DWARFCU) + continue; + + const DWARFDie &DIE = IsCode ? DWARFCU->getSubroutineForAddress(Address) + : DWARFCU->getVariableForAddress(Address); + const std::string File = DIE.getDeclFile( + llvm::DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath); + const uint64_t Line = DIE.getDeclLine(); + + auto NameOrErr = Symbol.getName(); + if (!NameOrErr) { + consumeError(NameOrErr.takeError()); + continue; + } + auto Name = *NameOrErr; + auto Sym = parseSymbol(Name); + + if (!File.empty() && Line != 0) + LocMap.insert({Sym.Name.str(), RecordLoc(File, Line)}); + } + + return LocMap; +} + +SymbolToSourceLocMap +DylibReader::accumulateSourceLocFromDSYM(const StringRef DSYM, + const Target &T) { + // Find sidecar file. + auto DSYMsOrErr = MachOObjectFile::findDsymObjectMembers(DSYM); + if (!DSYMsOrErr) { + consumeError(DSYMsOrErr.takeError()); + return SymbolToSourceLocMap(); + } + if (DSYMsOrErr->empty()) + return SymbolToSourceLocMap(); + + const StringRef Path = DSYMsOrErr->front(); + auto BufOrErr = MemoryBuffer::getFile(Path); + if (auto Err = BufOrErr.getError()) + return SymbolToSourceLocMap(); + + auto BinOrErr = createBinary(*BufOrErr.get()); + if (!BinOrErr) { + consumeError(BinOrErr.takeError()); + return SymbolToSourceLocMap(); + } + // Handle single arch. + if (auto *Single = dyn_cast<MachOObjectFile>(BinOrErr->get())) { + auto DiCtx = DWARFContext::create( + *Single, DWARFContext::ProcessDebugRelocations::Process, nullptr, "", + DWARFErrorHandler, DWARFErrorHandler); + + return accumulateLocs(*Single, DiCtx); + } + // Handle universal companion file. + if (auto *Fat = dyn_cast<MachOUniversalBinary>(BinOrErr->get())) { + auto ObjForArch = Fat->getObjectForArch(getArchitectureName(T.Arch)); + if (!ObjForArch) { + consumeError(ObjForArch.takeError()); + return SymbolToSourceLocMap(); + } + auto MachOOrErr = ObjForArch->getAsObjectFile(); + if (!MachOOrErr) { + consumeError(MachOOrErr.takeError()); + return SymbolToSourceLocMap(); + } + auto &Obj = **MachOOrErr; + auto DiCtx = DWARFContext::create( + Obj, DWARFContext::ProcessDebugRelocations::Process, nullptr, "", + DWARFErrorHandler, DWARFErrorHandler); + + return accumulateLocs(Obj, DiCtx); + } + return SymbolToSourceLocMap(); +} diff --git a/llvm/lib/TextAPI/TextStub.cpp b/llvm/lib/TextAPI/TextStub.cpp index 24a52607a981ca6d724cd86e5ffec14124530a48..0f742523f8207cd98f52ea7171187af6bf77c890 100644 --- a/llvm/lib/TextAPI/TextStub.cpp +++ b/llvm/lib/TextAPI/TextStub.cpp @@ -1079,16 +1079,16 @@ Expected<FileType> TextAPIReader::canRead(MemoryBufferRef InputBuffer) { if (!TAPIFile.ends_with("...")) return createStringError(std::errc::not_supported, "unsupported file type"); - if (TAPIFile.starts_with("--- !tapi-tbd\n")) + if (TAPIFile.starts_with("--- !tapi-tbd")) return FileType::TBD_V4; - if (TAPIFile.starts_with("--- !tapi-tbd-v3\n")) + if (TAPIFile.starts_with("--- !tapi-tbd-v3")) return FileType::TBD_V3; - if (TAPIFile.starts_with("--- !tapi-tbd-v2\n")) + if (TAPIFile.starts_with("--- !tapi-tbd-v2")) return FileType::TBD_V2; - if (TAPIFile.starts_with("--- !tapi-tbd-v1\n") || + if (TAPIFile.starts_with("--- !tapi-tbd-v1") || TAPIFile.starts_with("---\narchs:")) return FileType::TBD_V1; diff --git a/llvm/lib/TextAPI/Utils.cpp b/llvm/lib/TextAPI/Utils.cpp index b5c3999a86ea9d0aba3ead12e5f40fda590e7d84..c541645044955cc121af09c1a355faada3855134 100644 --- a/llvm/lib/TextAPI/Utils.cpp +++ b/llvm/lib/TextAPI/Utils.cpp @@ -152,3 +152,49 @@ bool llvm::MachO::isPrivateLibrary(StringRef Path, bool IsSymLink) { } return false; } + +static StringLiteral RegexMetachars = "()^$|+.[]\\{}"; + +llvm::Expected<Regex> llvm::MachO::createRegexFromGlob(StringRef Glob) { + SmallString<128> RegexString("^"); + unsigned NumWildcards = 0; + for (unsigned i = 0; i < Glob.size(); ++i) { + char C = Glob[i]; + switch (C) { + case '?': + RegexString += '.'; + break; + case '*': { + const char *PrevChar = i > 0 ? Glob.data() + i - 1 : nullptr; + NumWildcards = 1; + ++i; + while (i < Glob.size() && Glob[i] == '*') { + ++NumWildcards; + ++i; + } + const char *NextChar = i < Glob.size() ? Glob.data() + i : nullptr; + + if ((NumWildcards > 1) && (PrevChar == nullptr || *PrevChar == '/') && + (NextChar == nullptr || *NextChar == '/')) { + RegexString += "(([^/]*(/|$))*)"; + } else + RegexString += "([^/]*)"; + break; + } + default: + if (RegexMetachars.find(C) != StringRef::npos) + RegexString.push_back('\\'); + RegexString.push_back(C); + } + } + RegexString.push_back('$'); + if (NumWildcards == 0) + return make_error<StringError>("not a glob", inconvertibleErrorCode()); + + llvm::Regex Rule = Regex(RegexString); + std::string Error; + if (!Rule.isValid(Error)) + return make_error<StringError>(Error, inconvertibleErrorCode()); + + return std::move(Rule); +} diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp index 7c29d443df51b62046e872a6688c80eea5a65c9f..08a4522e3fac6d490511680500556ca061c52b5c 100644 --- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -971,7 +971,7 @@ static void cacheDIVar(FrameDataInfo &FrameData, DIVarCache.insert({V, (*I)->getVariable()}); }; CacheIt(findDbgDeclares(V)); - CacheIt(findDPVDeclares(V)); + CacheIt(findDVRDeclares(V)); } } @@ -1123,7 +1123,7 @@ static void buildFrameDebugInfo(Function &F, coro::Shape &Shape, "Coroutine with switch ABI should own Promise alloca"); TinyPtrVector<DbgDeclareInst *> DIs = findDbgDeclares(PromiseAlloca); - TinyPtrVector<DPValue *> DPVs = findDPVDeclares(PromiseAlloca); + TinyPtrVector<DbgVariableRecord *> DVRs = findDVRDeclares(PromiseAlloca); DILocalVariable *PromiseDIVariable = nullptr; DILocation *DILoc = nullptr; @@ -1131,10 +1131,10 @@ static void buildFrameDebugInfo(Function &F, coro::Shape &Shape, DbgDeclareInst *PromiseDDI = DIs.front(); PromiseDIVariable = PromiseDDI->getVariable(); DILoc = PromiseDDI->getDebugLoc().get(); - } else if (!DPVs.empty()) { - DPValue *PromiseDPV = DPVs.front(); - PromiseDIVariable = PromiseDPV->getVariable(); - DILoc = PromiseDPV->getDebugLoc().get(); + } else if (!DVRs.empty()) { + DbgVariableRecord *PromiseDVR = DVRs.front(); + PromiseDIVariable = PromiseDVR->getVariable(); + DILoc = PromiseDVR->getDebugLoc().get(); } else { return; } @@ -1273,11 +1273,12 @@ static void buildFrameDebugInfo(Function &F, coro::Shape &Shape, } if (UseNewDbgInfoFormat) { - DPValue *NewDPV = new DPValue(ValueAsMetadata::get(Shape.FramePtr), - FrameDIVar, DBuilder.createExpression(), - DILoc, DPValue::LocationType::Declare); + DbgVariableRecord *NewDVR = + new DbgVariableRecord(ValueAsMetadata::get(Shape.FramePtr), FrameDIVar, + DBuilder.createExpression(), DILoc, + DbgVariableRecord::LocationType::Declare); BasicBlock::iterator It = Shape.getInsertPtAfterFramePtr(); - It->getParent()->insertDbgRecordBefore(NewDPV, It); + It->getParent()->insertDbgRecordBefore(NewDVR, It); } else { DBuilder.insertDeclare(Shape.FramePtr, FrameDIVar, DBuilder.createExpression(), DILoc, @@ -1862,13 +1863,13 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { SpillAlignment, E.first->getName() + Twine(".reload")); TinyPtrVector<DbgDeclareInst *> DIs = findDbgDeclares(Def); - TinyPtrVector<DPValue *> DPVs = findDPVDeclares(Def); + TinyPtrVector<DbgVariableRecord *> DVRs = findDVRDeclares(Def); // Try best to find dbg.declare. If the spill is a temp, there may not // be a direct dbg.declare. Walk up the load chain to find one from an // alias. if (F->getSubprogram()) { auto *CurDef = Def; - while (DIs.empty() && DPVs.empty() && isa<LoadInst>(CurDef)) { + while (DIs.empty() && DVRs.empty() && isa<LoadInst>(CurDef)) { auto *LdInst = cast<LoadInst>(CurDef); // Only consider ptr to ptr same type load. if (LdInst->getPointerOperandType() != LdInst->getType()) @@ -1877,7 +1878,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { if (!isa<AllocaInst, LoadInst>(CurDef)) break; DIs = findDbgDeclares(CurDef); - DPVs = findDPVDeclares(CurDef); + DVRs = findDVRDeclares(CurDef); } } @@ -1887,12 +1888,12 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { // fragments. It will be unreachable in the main function, and // processed by coro::salvageDebugInfo() by CoroCloner. if (UseNewDbgInfoFormat) { - DPValue *NewDPV = - new DPValue(ValueAsMetadata::get(CurrentReload), - DDI->getVariable(), DDI->getExpression(), - DDI->getDebugLoc(), DPValue::LocationType::Declare); + DbgVariableRecord *NewDVR = new DbgVariableRecord( + ValueAsMetadata::get(CurrentReload), DDI->getVariable(), + DDI->getExpression(), DDI->getDebugLoc(), + DbgVariableRecord::LocationType::Declare); Builder.GetInsertPoint()->getParent()->insertDbgRecordBefore( - NewDPV, Builder.GetInsertPoint()); + NewDVR, Builder.GetInsertPoint()); } else { DIBuilder(*CurrentBlock->getParent()->getParent(), AllowUnresolved) .insertDeclare(CurrentReload, DDI->getVariable(), @@ -1905,7 +1906,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { false /*UseEntryValue*/); }; for_each(DIs, SalvageOne); - for_each(DPVs, SalvageOne); + for_each(DVRs, SalvageOne); } // If we have a single edge PHINode, remove it and replace it with a @@ -1925,8 +1926,8 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { U->replaceUsesOfWith(Def, CurrentReload); // Instructions are added to Def's user list if the attached // debug records use Def. Update those now. - for (DPValue &DPV : DPValue::filter(U->getDbgRecordRange())) - DPV.replaceVariableLocationOp(Def, CurrentReload, true); + for (DbgVariableRecord &DVR : filterDbgVars(U->getDbgRecordRange())) + DVR.replaceVariableLocationOp(Def, CurrentReload, true); } } @@ -1977,12 +1978,12 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { G->setName(Alloca->getName() + Twine(".reload.addr")); SmallVector<DbgVariableIntrinsic *, 4> DIs; - SmallVector<DPValue *> DPValues; - findDbgUsers(DIs, Alloca, &DPValues); + SmallVector<DbgVariableRecord *> DbgVariableRecords; + findDbgUsers(DIs, Alloca, &DbgVariableRecords); for (auto *DVI : DIs) DVI->replaceUsesOfWith(Alloca, G); - for (auto *DPV : DPValues) - DPV->replaceVariableLocationOp(Alloca, G); + for (auto *DVR : DbgVariableRecords) + DVR->replaceVariableLocationOp(Alloca, G); for (Instruction *I : UsersToUpdate) { // It is meaningless to retain the lifetime intrinsics refer for the @@ -2960,30 +2961,30 @@ void coro::salvageDebugInfo( } void coro::salvageDebugInfo( - SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap, DPValue &DPV, - bool OptimizeFrame, bool UseEntryValue) { + SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap, + DbgVariableRecord &DVR, bool OptimizeFrame, bool UseEntryValue) { - Function *F = DPV.getFunction(); + Function *F = DVR.getFunction(); // Follow the pointer arithmetic all the way to the incoming // function argument and convert into a DIExpression. - bool SkipOutermostLoad = DPV.isDbgDeclare(); - Value *OriginalStorage = DPV.getVariableLocationOp(0); + bool SkipOutermostLoad = DVR.isDbgDeclare(); + Value *OriginalStorage = DVR.getVariableLocationOp(0); auto SalvagedInfo = ::salvageDebugInfoImpl( ArgToAllocaMap, OptimizeFrame, UseEntryValue, F, OriginalStorage, - DPV.getExpression(), SkipOutermostLoad); + DVR.getExpression(), SkipOutermostLoad); if (!SalvagedInfo) return; Value *Storage = &SalvagedInfo->first; DIExpression *Expr = &SalvagedInfo->second; - DPV.replaceVariableLocationOp(OriginalStorage, Storage); - DPV.setExpression(Expr); + DVR.replaceVariableLocationOp(OriginalStorage, Storage); + DVR.setExpression(Expr); // We only hoist dbg.declare today since it doesn't make sense to hoist // dbg.value since it does not have the same function wide guarantees that // dbg.declare does. - if (DPV.getType() == DPValue::LocationType::Declare) { + if (DVR.getType() == DbgVariableRecord::LocationType::Declare) { std::optional<BasicBlock::iterator> InsertPt; if (auto *I = dyn_cast<Instruction>(Storage)) { InsertPt = I->getInsertionPointAfterDef(); @@ -2991,12 +2992,12 @@ void coro::salvageDebugInfo( // optimizations. See https://github.com/llvm/llvm-project/pull/75104 for // an example. if (!OptimizeFrame && I->getDebugLoc()) - DPV.setDebugLoc(I->getDebugLoc()); + DVR.setDebugLoc(I->getDebugLoc()); } else if (isa<Argument>(Storage)) InsertPt = F->getEntryBlock().begin(); if (InsertPt) { - DPV.removeFromParent(); - (*InsertPt)->getParent()->insertDbgRecordBefore(&DPV, *InsertPt); + DVR.removeFromParent(); + (*InsertPt)->getParent()->insertDbgRecordBefore(&DVR, *InsertPt); } } } @@ -3188,15 +3189,15 @@ void coro::buildCoroutineFrame( for (auto &Iter : FrameData.Spills) { auto *V = Iter.first; SmallVector<DbgValueInst *, 16> DVIs; - SmallVector<DPValue *, 16> DPVs; - findDbgValues(DVIs, V, &DPVs); + SmallVector<DbgVariableRecord *, 16> DVRs; + findDbgValues(DVIs, V, &DVRs); for (DbgValueInst *DVI : DVIs) if (Checker.isDefinitionAcrossSuspend(*V, DVI)) FrameData.Spills[V].push_back(DVI); // Add the instructions which carry debug info that is in the frame. - for (DPValue *DPV : DPVs) - if (Checker.isDefinitionAcrossSuspend(*V, DPV->Marker->MarkedInstr)) - FrameData.Spills[V].push_back(DPV->Marker->MarkedInstr); + for (DbgVariableRecord *DVR : DVRs) + if (Checker.isDefinitionAcrossSuspend(*V, DVR->Marker->MarkedInstr)) + FrameData.Spills[V].push_back(DVR->Marker->MarkedInstr); } LLVM_DEBUG(dumpSpills("Spills", FrameData.Spills)); diff --git a/llvm/lib/Transforms/Coroutines/CoroInternal.h b/llvm/lib/Transforms/Coroutines/CoroInternal.h index 09d1430b4c559e7359569e6d71d8336a2e0304fc..84fd88806154e307384b3306a685dc1771f9628a 100644 --- a/llvm/lib/Transforms/Coroutines/CoroInternal.h +++ b/llvm/lib/Transforms/Coroutines/CoroInternal.h @@ -35,8 +35,8 @@ void salvageDebugInfo( SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap, DbgVariableIntrinsic &DVI, bool OptimizeFrame, bool IsEntryPoint); void salvageDebugInfo( - SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap, DPValue &DPV, - bool OptimizeFrame, bool UseEntryValue); + SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap, + DbgVariableRecord &DVR, bool OptimizeFrame, bool UseEntryValue); // Keeps data and helper functions for lowering coroutine intrinsics. struct LowererBase { diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp index 086971a1f21373c49992042c7821638184c2df66..3a43b1edcaba37ea8ff1af4a44749bb8ef7478a5 100644 --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -679,17 +679,18 @@ static void replaceSwiftErrorOps(Function &F, coro::Shape &Shape, } /// Returns all DbgVariableIntrinsic in F. -static std::pair<SmallVector<DbgVariableIntrinsic *, 8>, SmallVector<DPValue *>> +static std::pair<SmallVector<DbgVariableIntrinsic *, 8>, + SmallVector<DbgVariableRecord *>> collectDbgVariableIntrinsics(Function &F) { SmallVector<DbgVariableIntrinsic *, 8> Intrinsics; - SmallVector<DPValue *> DPValues; + SmallVector<DbgVariableRecord *> DbgVariableRecords; for (auto &I : instructions(F)) { - for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) - DPValues.push_back(&DPV); + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) + DbgVariableRecords.push_back(&DVR); if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I)) Intrinsics.push_back(DVI); } - return {Intrinsics, DPValues}; + return {Intrinsics, DbgVariableRecords}; } void CoroCloner::replaceSwiftErrorOps() { @@ -697,7 +698,7 @@ void CoroCloner::replaceSwiftErrorOps() { } void CoroCloner::salvageDebugInfo() { - auto [Worklist, DPValues] = collectDbgVariableIntrinsics(*NewF); + auto [Worklist, DbgVariableRecords] = collectDbgVariableIntrinsics(*NewF); SmallDenseMap<Argument *, AllocaInst *, 4> ArgToAllocaMap; // Only 64-bit ABIs have a register we can refer to with the entry value. @@ -706,8 +707,8 @@ void CoroCloner::salvageDebugInfo() { for (DbgVariableIntrinsic *DVI : Worklist) coro::salvageDebugInfo(ArgToAllocaMap, *DVI, Shape.OptimizeFrame, UseEntryValue); - for (DPValue *DPV : DPValues) - coro::salvageDebugInfo(ArgToAllocaMap, *DPV, Shape.OptimizeFrame, + for (DbgVariableRecord *DVR : DbgVariableRecords) + coro::salvageDebugInfo(ArgToAllocaMap, *DVR, Shape.OptimizeFrame, UseEntryValue); // Remove all salvaged dbg.declare intrinsics that became @@ -732,7 +733,7 @@ void CoroCloner::salvageDebugInfo() { } }; for_each(Worklist, RemoveOne); - for_each(DPValues, RemoveOne); + for_each(DbgVariableRecords, RemoveOne); } void CoroCloner::replaceEntryBlock() { @@ -1197,22 +1198,6 @@ static bool simplifyTerminatorLeadingToRet(Instruction *InitialInst) { assert(InitialInst->getModule()); const DataLayout &DL = InitialInst->getModule()->getDataLayout(); - auto GetFirstValidInstruction = [](Instruction *I) { - while (I) { - // BitCastInst wouldn't generate actual code so that we could skip it. - if (isa<BitCastInst>(I) || I->isDebugOrPseudoInst() || - I->isLifetimeStartOrEnd()) - I = I->getNextNode(); - else if (isInstructionTriviallyDead(I)) - // Duing we are in the middle of the transformation, we need to erase - // the dead instruction manually. - I = &*I->eraseFromParent(); - else - break; - } - return I; - }; - auto TryResolveConstant = [&ResolvedValues](Value *V) { auto It = ResolvedValues.find(V); if (It != ResolvedValues.end()) @@ -1221,8 +1206,9 @@ static bool simplifyTerminatorLeadingToRet(Instruction *InitialInst) { }; Instruction *I = InitialInst; - while (I->isTerminator() || isa<CmpInst>(I)) { + while (true) { if (isa<ReturnInst>(I)) { + assert(!cast<ReturnInst>(I)->getReturnValue()); ReplaceInstWithInst(InitialInst, I->clone()); return true; } @@ -1246,40 +1232,26 @@ static bool simplifyTerminatorLeadingToRet(Instruction *InitialInst) { BasicBlock *Succ = BR->getSuccessor(SuccIndex); scanPHIsAndUpdateValueMap(I, Succ, ResolvedValues); - I = GetFirstValidInstruction(Succ->getFirstNonPHIOrDbgOrLifetime()); - + I = Succ->getFirstNonPHIOrDbgOrLifetime(); continue; } - if (auto *CondCmp = dyn_cast<CmpInst>(I)) { + if (auto *Cmp = dyn_cast<CmpInst>(I)) { // If the case number of suspended switch instruction is reduced to // 1, then it is simplified to CmpInst in llvm::ConstantFoldTerminator. - auto *BR = dyn_cast<BranchInst>( - GetFirstValidInstruction(CondCmp->getNextNode())); - if (!BR || !BR->isConditional() || CondCmp != BR->getCondition()) - return false; - - // And the comparsion looks like : %cond = icmp eq i8 %V, constant. - // So we try to resolve constant for the first operand only since the - // second operand should be literal constant by design. - ConstantInt *Cond0 = TryResolveConstant(CondCmp->getOperand(0)); - auto *Cond1 = dyn_cast<ConstantInt>(CondCmp->getOperand(1)); - if (!Cond0 || !Cond1) - return false; - - // Both operands of the CmpInst are Constant. So that we could evaluate - // it immediately to get the destination. - auto *ConstResult = - dyn_cast_or_null<ConstantInt>(ConstantFoldCompareInstOperands( - CondCmp->getPredicate(), Cond0, Cond1, DL)); - if (!ConstResult) - return false; - - ResolvedValues[BR->getCondition()] = ConstResult; - - // Handle this branch in next iteration. - I = BR; - continue; + // Try to constant fold it. + ConstantInt *Cond0 = TryResolveConstant(Cmp->getOperand(0)); + ConstantInt *Cond1 = TryResolveConstant(Cmp->getOperand(1)); + if (Cond0 && Cond1) { + ConstantInt *Result = + dyn_cast_or_null<ConstantInt>(ConstantFoldCompareInstOperands( + Cmp->getPredicate(), Cond0, Cond1, DL)); + if (Result) { + ResolvedValues[Cmp] = Result; + I = I->getNextNode(); + continue; + } + } } if (auto *SI = dyn_cast<SwitchInst>(I)) { @@ -1287,13 +1259,21 @@ static bool simplifyTerminatorLeadingToRet(Instruction *InitialInst) { if (!Cond) return false; - BasicBlock *BB = SI->findCaseValue(Cond)->getCaseSuccessor(); - scanPHIsAndUpdateValueMap(I, BB, ResolvedValues); - I = GetFirstValidInstruction(BB->getFirstNonPHIOrDbgOrLifetime()); + BasicBlock *Succ = SI->findCaseValue(Cond)->getCaseSuccessor(); + scanPHIsAndUpdateValueMap(I, Succ, ResolvedValues); + I = Succ->getFirstNonPHIOrDbgOrLifetime(); + continue; + } + + if (I->isDebugOrPseudoInst() || I->isLifetimeStartOrEnd() || + wouldInstructionBeTriviallyDead(I)) { + // We can skip instructions without side effects. If their values are + // needed, we'll notice later, e.g. when hitting a conditional branch. + I = I->getNextNode(); continue; } - return false; + break; } return false; @@ -2107,12 +2087,12 @@ splitCoroutine(Function &F, SmallVectorImpl<Function *> &Clones, // original function. The Cloner has already salvaged debug info in the new // coroutine funclets. SmallDenseMap<Argument *, AllocaInst *, 4> ArgToAllocaMap; - auto [DbgInsts, DPValues] = collectDbgVariableIntrinsics(F); + auto [DbgInsts, DbgVariableRecords] = collectDbgVariableIntrinsics(F); for (auto *DDI : DbgInsts) coro::salvageDebugInfo(ArgToAllocaMap, *DDI, Shape.OptimizeFrame, false /*UseEntryValue*/); - for (DPValue *DPV : DPValues) - coro::salvageDebugInfo(ArgToAllocaMap, *DPV, Shape.OptimizeFrame, + for (DbgVariableRecord *DVR : DbgVariableRecords) + coro::salvageDebugInfo(ArgToAllocaMap, *DVR, Shape.OptimizeFrame, false /*UseEntryValue*/); return Shape; } diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp index 488a6f0bb153a41ece9b35538950383411dbfa08..ff680e998e71dbb77ded471ae687b3e73e24cbe5 100644 --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -5190,6 +5190,12 @@ static unsigned getKnownAlignForUse(Attributor &A, AAAlign &QueryingAA, } else if (auto *LI = dyn_cast<LoadInst>(I)) { if (LI->getPointerOperand() == UseV) MA = LI->getAlign(); + } else if (auto *AI = dyn_cast<AtomicRMWInst>(I)) { + if (AI->getPointerOperand() == UseV) + MA = AI->getAlign(); + } else if (auto *AI = dyn_cast<AtomicCmpXchgInst>(I)) { + if (AI->getPointerOperand() == UseV) + MA = AI->getAlign(); } if (!MA || *MA <= QueryingAA.getKnownAlign()) @@ -12371,7 +12377,7 @@ struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo { SplitBlockAndInsertIfThen(LastCmp, IP, /* Unreachable */ false); BasicBlock *CBBB = CB->getParent(); A.registerManifestAddedBasicBlock(*ThenTI->getParent()); - A.registerManifestAddedBasicBlock(*CBBB); + A.registerManifestAddedBasicBlock(*IP->getParent()); auto *SplitTI = cast<BranchInst>(LastCmp->getNextNode()); BasicBlock *ElseBB; if (&*IP == CB) { diff --git a/llvm/lib/Transforms/IPO/CMakeLists.txt b/llvm/lib/Transforms/IPO/CMakeLists.txt index 034f1587ae8df44bdb5b9f311197dcfdbdc1d938..5fbdbc3a014f9aae53d0be809a2fc0a4cbaf297a 100644 --- a/llvm/lib/Transforms/IPO/CMakeLists.txt +++ b/llvm/lib/Transforms/IPO/CMakeLists.txt @@ -35,6 +35,7 @@ add_llvm_component_library(LLVMipo PartialInlining.cpp SampleContextTracker.cpp SampleProfile.cpp + SampleProfileMatcher.cpp SampleProfileProbe.cpp SCCP.cpp StripDeadPrototypes.cpp diff --git a/llvm/lib/Transforms/IPO/GlobalSplit.cpp b/llvm/lib/Transforms/IPO/GlobalSplit.cpp index 84e9c219f935cdea0713de8409020ff20820c95a..dced3a5fdc7875666fd3f2aa2d8bf62069393ea9 100644 --- a/llvm/lib/Transforms/IPO/GlobalSplit.cpp +++ b/llvm/lib/Transforms/IPO/GlobalSplit.cpp @@ -47,28 +47,66 @@ static bool splitGlobal(GlobalVariable &GV) { if (!Init) return false; - // Verify that each user of the global is an inrange getelementptr constant. - // From this it follows that any loads from or stores to that global must use - // a pointer derived from an inrange getelementptr constant, which is - // sufficient to allow us to apply the splitting transform. + const DataLayout &DL = GV.getParent()->getDataLayout(); + const StructLayout *SL = DL.getStructLayout(Init->getType()); + ArrayRef<TypeSize> MemberOffsets = SL->getMemberOffsets(); + unsigned IndexWidth = DL.getIndexTypeSizeInBits(GV.getType()); + + // Verify that each user of the global is an inrange getelementptr constant, + // and collect information on how it relates to the global. + struct GEPInfo { + GEPOperator *GEP; + unsigned MemberIndex; + APInt MemberRelativeOffset; + + GEPInfo(GEPOperator *GEP, unsigned MemberIndex, APInt MemberRelativeOffset) + : GEP(GEP), MemberIndex(MemberIndex), + MemberRelativeOffset(std::move(MemberRelativeOffset)) {} + }; + SmallVector<GEPInfo> Infos; for (User *U : GV.users()) { - if (!isa<Constant>(U)) + auto *GEP = dyn_cast<GEPOperator>(U); + if (!GEP) return false; - auto *GEP = dyn_cast<GEPOperator>(U); - if (!GEP || !GEP->getInRangeIndex() || *GEP->getInRangeIndex() != 1 || - !isa<ConstantInt>(GEP->getOperand(1)) || - !cast<ConstantInt>(GEP->getOperand(1))->isZero() || - !isa<ConstantInt>(GEP->getOperand(2))) + std::optional<ConstantRange> InRange = GEP->getInRange(); + if (!InRange) + return false; + + APInt Offset(IndexWidth, 0); + if (!GEP->accumulateConstantOffset(DL, Offset)) + return false; + + // Determine source-relative inrange. + ConstantRange SrcInRange = InRange->sextOrTrunc(IndexWidth).add(Offset); + + // Check that the GEP offset is in the range (treating upper bound as + // inclusive here). + if (!SrcInRange.contains(Offset) && SrcInRange.getUpper() != Offset) + return false; + + // Find which struct member the range corresponds to. + if (SrcInRange.getLower().uge(SL->getSizeInBytes())) return false; + + unsigned MemberIndex = + SL->getElementContainingOffset(SrcInRange.getLower().getZExtValue()); + TypeSize MemberStart = MemberOffsets[MemberIndex]; + TypeSize MemberEnd = MemberIndex == MemberOffsets.size() - 1 + ? SL->getSizeInBytes() + : MemberOffsets[MemberIndex + 1]; + + // Verify that the range matches that struct member. + if (SrcInRange.getLower() != MemberStart || + SrcInRange.getUpper() != MemberEnd) + return false; + + Infos.emplace_back(GEP, MemberIndex, Offset - MemberStart); } SmallVector<MDNode *, 2> Types; GV.getMetadata(LLVMContext::MD_type, Types); - const DataLayout &DL = GV.getParent()->getDataLayout(); - const StructLayout *SL = DL.getStructLayout(Init->getType()); - IntegerType *Int32Ty = Type::getInt32Ty(GV.getContext()); std::vector<GlobalVariable *> SplitGlobals(Init->getNumOperands()); @@ -114,21 +152,13 @@ static bool splitGlobal(GlobalVariable &GV) { SplitGV->setVCallVisibilityMetadata(GV.getVCallVisibility()); } - for (User *U : GV.users()) { - auto *GEP = cast<GEPOperator>(U); - unsigned I = cast<ConstantInt>(GEP->getOperand(2))->getZExtValue(); - if (I >= SplitGlobals.size()) - continue; - - SmallVector<Value *, 4> Ops; - Ops.push_back(ConstantInt::get(Int32Ty, 0)); - for (unsigned I = 3; I != GEP->getNumOperands(); ++I) - Ops.push_back(GEP->getOperand(I)); - + for (const GEPInfo &Info : Infos) { + assert(Info.MemberIndex < SplitGlobals.size() && "Invalid member"); auto *NewGEP = ConstantExpr::getGetElementPtr( - SplitGlobals[I]->getInitializer()->getType(), SplitGlobals[I], Ops, - GEP->isInBounds()); - GEP->replaceAllUsesWith(NewGEP); + Type::getInt8Ty(GV.getContext()), SplitGlobals[Info.MemberIndex], + ConstantInt::get(GV.getContext(), Info.MemberRelativeOffset), + Info.GEP->isInBounds()); + Info.GEP->replaceAllUsesWith(NewGEP); } // Finally, remove the original global. Any remaining uses refer to invalid diff --git a/llvm/lib/Transforms/IPO/IROutliner.cpp b/llvm/lib/Transforms/IPO/IROutliner.cpp index 37f4a8749fd8e8731e5ee077d6161e977993d3fd..29f9264f2fc249c10f51403b5ba35831d4bffb42 100644 --- a/llvm/lib/Transforms/IPO/IROutliner.cpp +++ b/llvm/lib/Transforms/IPO/IROutliner.cpp @@ -723,8 +723,8 @@ static void moveFunctionData(Function &Old, Function &New, for (Instruction &Val : CurrBB) { // Since debug-info originates from many different locations in the // program, it will cause incorrect reporting from a debugger if we keep - // the same debug instructions. Drop non-intrinsic DPValues here, - // collect intrinsics for removal later. + // the same debug instructions. Drop non-intrinsic DbgVariableRecords + // here, collect intrinsics for removal later. Val.dropDbgRecords(); // We must handle the scoping of called functions differently than diff --git a/llvm/lib/Transforms/IPO/MemProfContextDisambiguation.cpp b/llvm/lib/Transforms/IPO/MemProfContextDisambiguation.cpp index ba5e3b637db7568f726ffd86fd4046d9541c43df..4e4a499977669208864d52b022c4b1fd688462b4 100644 --- a/llvm/lib/Transforms/IPO/MemProfContextDisambiguation.cpp +++ b/llvm/lib/Transforms/IPO/MemProfContextDisambiguation.cpp @@ -310,8 +310,12 @@ public: // True if this node was effectively removed from the graph, in which case // its context id set, caller edges, and callee edges should all be empty. bool isRemoved() const { - assert(ContextIds.empty() == - (CalleeEdges.empty() && CallerEdges.empty())); + // Note that we can have non-empty context ids with empty caller and + // callee edges if the graph ends up with a single node. + if (ContextIds.empty()) + assert(CalleeEdges.empty() && CallerEdges.empty() && + "Context ids empty but at least one of callee and caller edges " + "were not!"); return ContextIds.empty(); } @@ -353,9 +357,12 @@ public: } }; - /// Helper to remove callee edges that have allocation type None (due to not + /// Helpers to remove callee edges that have allocation type None (due to not /// carrying any context ids) after transformations. void removeNoneTypeCalleeEdges(ContextNode *Node); + void + recursivelyRemoveNoneTypeCalleeEdges(ContextNode *Node, + DenseSet<const ContextNode *> &Visited); protected: /// Get a list of nodes corresponding to the stack ids in the given callsite @@ -2431,11 +2438,43 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>:: } } +template <typename DerivedCCG, typename FuncTy, typename CallTy> +void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>:: + recursivelyRemoveNoneTypeCalleeEdges( + ContextNode *Node, DenseSet<const ContextNode *> &Visited) { + auto Inserted = Visited.insert(Node); + if (!Inserted.second) + return; + + removeNoneTypeCalleeEdges(Node); + + for (auto *Clone : Node->Clones) + recursivelyRemoveNoneTypeCalleeEdges(Clone, Visited); + + // The recursive call may remove some of this Node's caller edges. + // Iterate over a copy and skip any that were removed. + auto CallerEdges = Node->CallerEdges; + for (auto &Edge : CallerEdges) { + // Skip any that have been removed by an earlier recursive call. + if (Edge->Callee == nullptr && Edge->Caller == nullptr) { + assert(!std::count(Node->CallerEdges.begin(), Node->CallerEdges.end(), + Edge)); + continue; + } + recursivelyRemoveNoneTypeCalleeEdges(Edge->Caller, Visited); + } +} + template <typename DerivedCCG, typename FuncTy, typename CallTy> void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::identifyClones() { DenseSet<const ContextNode *> Visited; for (auto &Entry : AllocationCallToContextNodeMap) identifyClones(Entry.second, Visited); + Visited.clear(); + for (auto &Entry : AllocationCallToContextNodeMap) + recursivelyRemoveNoneTypeCalleeEdges(Entry.second, Visited); + if (VerifyCCG) + check(); } // helper function to check an AllocType is cold or notcold or both. @@ -2450,7 +2489,7 @@ template <typename DerivedCCG, typename FuncTy, typename CallTy> void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::identifyClones( ContextNode *Node, DenseSet<const ContextNode *> &Visited) { if (VerifyNodes) - checkNode<DerivedCCG, FuncTy, CallTy>(Node); + checkNode<DerivedCCG, FuncTy, CallTy>(Node, /*CheckEdges=*/false); assert(!Node->CloneOf); // If Node as a null call, then either it wasn't found in the module (regular @@ -2511,8 +2550,16 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::identifyClones( std::stable_sort(Node->CallerEdges.begin(), Node->CallerEdges.end(), [&](const std::shared_ptr<ContextEdge> &A, const std::shared_ptr<ContextEdge> &B) { - assert(checkColdOrNotCold(A->AllocTypes) && - checkColdOrNotCold(B->AllocTypes)); + // Nodes with non-empty context ids should be sorted before + // those with empty context ids. + if (A->ContextIds.empty()) + // Either B ContextIds are non-empty (in which case we + // should return false because B < A), or B ContextIds + // are empty, in which case they are equal, and we should + // maintain the original relative ordering. + return false; + if (B->ContextIds.empty()) + return true; if (A->AllocTypes == B->AllocTypes) // Use the first context id for each edge as a @@ -2591,39 +2638,16 @@ void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::identifyClones( Node->AllocTypes != (uint8_t)AllocationType::None); // Sanity check that no alloc types on clone or its edges are None. assert(Clone->AllocTypes != (uint8_t)AllocationType::None); - assert(llvm::none_of( - Clone->CallerEdges, [&](const std::shared_ptr<ContextEdge> &E) { - return E->AllocTypes == (uint8_t)AllocationType::None; - })); } - // Cloning may have resulted in some cloned callee edges with type None, - // because they aren't carrying any contexts. Remove those edges. - for (auto *Clone : Node->Clones) { - removeNoneTypeCalleeEdges(Clone); - if (VerifyNodes) - checkNode<DerivedCCG, FuncTy, CallTy>(Clone); - } // We should still have some context ids on the original Node. assert(!Node->ContextIds.empty()); - // Remove any callee edges that ended up with alloc type None after creating - // clones and updating callee edges. - removeNoneTypeCalleeEdges(Node); - // Sanity check that no alloc types on node or edges are None. assert(Node->AllocTypes != (uint8_t)AllocationType::None); - assert(llvm::none_of(Node->CalleeEdges, - [&](const std::shared_ptr<ContextEdge> &E) { - return E->AllocTypes == (uint8_t)AllocationType::None; - })); - assert(llvm::none_of(Node->CallerEdges, - [&](const std::shared_ptr<ContextEdge> &E) { - return E->AllocTypes == (uint8_t)AllocationType::None; - })); if (VerifyNodes) - checkNode<DerivedCCG, FuncTy, CallTy>(Node); + checkNode<DerivedCCG, FuncTy, CallTy>(Node, /*CheckEdges=*/false); } void ModuleCallsiteContextGraph::updateAllocationCall( diff --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/llvm/lib/Transforms/IPO/MergeFunctions.cpp index ed5352e7d04a979def567757bb6a30532ec3fd9c..05a3b169aaaf4c64e56a344622bbadcd909a1701 100644 --- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp +++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp @@ -256,20 +256,22 @@ private: /// Fill PDIUnrelatedWL with instructions from the entry block that are /// unrelated to parameter related debug info. - /// \param PDPVUnrelatedWL The equivalent non-intrinsic debug records. - void filterInstsUnrelatedToPDI(BasicBlock *GEntryBlock, - std::vector<Instruction *> &PDIUnrelatedWL, - std::vector<DPValue *> &PDPVUnrelatedWL); + /// \param PDVRUnrelatedWL The equivalent non-intrinsic debug records. + void + filterInstsUnrelatedToPDI(BasicBlock *GEntryBlock, + std::vector<Instruction *> &PDIUnrelatedWL, + std::vector<DbgVariableRecord *> &PDVRUnrelatedWL); /// Erase the rest of the CFG (i.e. barring the entry block). void eraseTail(Function *G); /// Erase the instructions in PDIUnrelatedWL as they are unrelated to the /// parameter debug info, from the entry block. - /// \param PDPVUnrelatedWL contains the equivalent set of non-instruction + /// \param PDVRUnrelatedWL contains the equivalent set of non-instruction /// debug-info records. - void eraseInstsUnrelatedToPDI(std::vector<Instruction *> &PDIUnrelatedWL, - std::vector<DPValue *> &PDPVUnrelatedWL); + void + eraseInstsUnrelatedToPDI(std::vector<Instruction *> &PDIUnrelatedWL, + std::vector<DbgVariableRecord *> &PDVRUnrelatedWL); /// Replace G with a simple tail call to bitcast(F). Also (unless /// MergeFunctionsPDI holds) replace direct uses of G with bitcast(F), @@ -512,7 +514,7 @@ static Value *createCast(IRBuilder<> &Builder, Value *V, Type *DestTy) { // parameter debug info, from the entry block. void MergeFunctions::eraseInstsUnrelatedToPDI( std::vector<Instruction *> &PDIUnrelatedWL, - std::vector<DPValue *> &PDPVUnrelatedWL) { + std::vector<DbgVariableRecord *> &PDVRUnrelatedWL) { LLVM_DEBUG( dbgs() << " Erasing instructions (in reverse order of appearance in " "entry block) unrelated to parameter debug info from entry " @@ -526,13 +528,13 @@ void MergeFunctions::eraseInstsUnrelatedToPDI( PDIUnrelatedWL.pop_back(); } - while (!PDPVUnrelatedWL.empty()) { - DPValue *DPV = PDPVUnrelatedWL.back(); - LLVM_DEBUG(dbgs() << " Deleting DPValue "); - LLVM_DEBUG(DPV->print(dbgs())); + while (!PDVRUnrelatedWL.empty()) { + DbgVariableRecord *DVR = PDVRUnrelatedWL.back(); + LLVM_DEBUG(dbgs() << " Deleting DbgVariableRecord "); + LLVM_DEBUG(DVR->print(dbgs())); LLVM_DEBUG(dbgs() << "\n"); - DPV->eraseFromParent(); - PDPVUnrelatedWL.pop_back(); + DVR->eraseFromParent(); + PDVRUnrelatedWL.pop_back(); } LLVM_DEBUG(dbgs() << " } // Done erasing instructions unrelated to parameter " @@ -564,12 +566,12 @@ void MergeFunctions::eraseTail(Function *G) { // PDIUnrelatedWL with such instructions. void MergeFunctions::filterInstsUnrelatedToPDI( BasicBlock *GEntryBlock, std::vector<Instruction *> &PDIUnrelatedWL, - std::vector<DPValue *> &PDPVUnrelatedWL) { + std::vector<DbgVariableRecord *> &PDVRUnrelatedWL) { std::set<Instruction *> PDIRelated; - std::set<DPValue *> PDPVRelated; + std::set<DbgVariableRecord *> PDVRRelated; - // Work out whether a dbg.value intrinsic or an equivalent DPValue is a - // parameter to be preserved. + // Work out whether a dbg.value intrinsic or an equivalent DbgVariableRecord + // is a parameter to be preserved. auto ExamineDbgValue = [](auto *DbgVal, auto &Container) { LLVM_DEBUG(dbgs() << " Deciding: "); LLVM_DEBUG(DbgVal->print(dbgs())); @@ -641,14 +643,14 @@ void MergeFunctions::filterInstsUnrelatedToPDI( for (BasicBlock::iterator BI = GEntryBlock->begin(), BIE = GEntryBlock->end(); BI != BIE; ++BI) { - // Examine DPValues as they happen "before" the instruction. Are they - // connected to parameters? - for (DPValue &DPV : DPValue::filter(BI->getDbgRecordRange())) { - if (DPV.isDbgValue() || DPV.isDbgAssign()) { - ExamineDbgValue(&DPV, PDPVRelated); + // Examine DbgVariableRecords as they happen "before" the instruction. Are + // they connected to parameters? + for (DbgVariableRecord &DVR : filterDbgVars(BI->getDbgRecordRange())) { + if (DVR.isDbgValue() || DVR.isDbgAssign()) { + ExamineDbgValue(&DVR, PDVRRelated); } else { - assert(DPV.isDbgDeclare()); - ExamineDbgDeclare(&DPV, PDPVRelated); + assert(DVR.isDbgDeclare()); + ExamineDbgDeclare(&DVR, PDVRRelated); } } @@ -686,8 +688,8 @@ void MergeFunctions::filterInstsUnrelatedToPDI( // Collect the set of unrelated instructions and debug records. for (Instruction &I : *GEntryBlock) { - for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) - IsPDIRelated(&DPV, PDPVRelated, PDPVUnrelatedWL); + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) + IsPDIRelated(&DVR, PDVRRelated, PDVRUnrelatedWL); IsPDIRelated(&I, PDIRelated, PDIUnrelatedWL); } LLVM_DEBUG(dbgs() << " }\n"); @@ -728,7 +730,7 @@ static void copyMetadataIfPresent(Function *From, Function *To, StringRef Key) { void MergeFunctions::writeThunk(Function *F, Function *G) { BasicBlock *GEntryBlock = nullptr; std::vector<Instruction *> PDIUnrelatedWL; - std::vector<DPValue *> PDPVUnrelatedWL; + std::vector<DbgVariableRecord *> PDVRUnrelatedWL; BasicBlock *BB = nullptr; Function *NewG = nullptr; if (MergeFunctionsPDI) { @@ -740,7 +742,7 @@ void MergeFunctions::writeThunk(Function *F, Function *G) { dbgs() << "writeThunk: (MergeFunctionsPDI) filter parameter related " "debug info for " << G->getName() << "() {\n"); - filterInstsUnrelatedToPDI(GEntryBlock, PDIUnrelatedWL, PDPVUnrelatedWL); + filterInstsUnrelatedToPDI(GEntryBlock, PDIUnrelatedWL, PDVRUnrelatedWL); GEntryBlock->getTerminator()->eraseFromParent(); BB = GEntryBlock; } else { @@ -790,7 +792,7 @@ void MergeFunctions::writeThunk(Function *F, Function *G) { << G->getName() << "()\n"); } eraseTail(G); - eraseInstsUnrelatedToPDI(PDIUnrelatedWL, PDPVUnrelatedWL); + eraseInstsUnrelatedToPDI(PDIUnrelatedWL, PDVRUnrelatedWL); LLVM_DEBUG( dbgs() << "} // End of parameter related debug info filtering for: " << G->getName() << "()\n"); diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp index ffc26f1a0a972d0bb200e94143394e6277bdea84..b5f45a252c7b46918d086ffc885a06d6c90a50b5 100644 --- a/llvm/lib/Transforms/IPO/SampleProfile.cpp +++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp @@ -71,6 +71,7 @@ #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/ProfiledCallGraph.h" #include "llvm/Transforms/IPO/SampleContextTracker.h" +#include "llvm/Transforms/IPO/SampleProfileMatcher.h" #include "llvm/Transforms/IPO/SampleProfileProbe.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Utils/CallPromotionUtils.h" @@ -129,16 +130,16 @@ static cl::opt<std::string> SampleProfileRemappingFile( "sample-profile-remapping-file", cl::init(""), cl::value_desc("filename"), cl::desc("Profile remapping file loaded by -sample-profile"), cl::Hidden); -static cl::opt<bool> SalvageStaleProfile( +cl::opt<bool> SalvageStaleProfile( "salvage-stale-profile", cl::Hidden, cl::init(false), cl::desc("Salvage stale profile by fuzzy matching and use the remapped " "location for sample profile query.")); -static cl::opt<bool> ReportProfileStaleness( +cl::opt<bool> ReportProfileStaleness( "report-profile-staleness", cl::Hidden, cl::init(false), cl::desc("Compute and report stale profile statistical metrics.")); -static cl::opt<bool> PersistProfileStaleness( +cl::opt<bool> PersistProfileStaleness( "persist-profile-staleness", cl::Hidden, cl::init(false), cl::desc("Compute stale profile statistical metrics and write it into the " "native object file(.llvm_stats section).")); @@ -234,6 +235,21 @@ static cl::opt<unsigned> ProfileICPRelativeHotnessSkip( cl::desc( "Skip relative hotness check for ICP up to given number of targets.")); +static cl::opt<unsigned> HotFuncCutoffForStalenessError( + "hot-func-cutoff-for-staleness-error", cl::Hidden, cl::init(800000), + cl::desc("A function is considered hot for staleness error check if its " + "total sample count is above the specified percentile")); + +static cl::opt<unsigned> MinfuncsForStalenessError( + "min-functions-for-staleness-error", cl::Hidden, cl::init(50), + cl::desc("Skip the check if the number of hot functions is smaller than " + "the specified number.")); + +static cl::opt<unsigned> PrecentMismatchForStalenessError( + "precent-mismatch-for-staleness-error", cl::Hidden, cl::init(80), + cl::desc("Reject the profile if the mismatch percent is higher than the " + "given number.")); + static cl::opt<bool> CallsitePrioritizedInline( "sample-profile-prioritized-inline", cl::Hidden, @@ -433,136 +449,6 @@ using CandidateQueue = PriorityQueue<InlineCandidate, std::vector<InlineCandidate>, CandidateComparer>; -// Sample profile matching - fuzzy match. -class SampleProfileMatcher { - Module &M; - SampleProfileReader &Reader; - const PseudoProbeManager *ProbeManager; - SampleProfileMap FlattenedProfiles; - // For each function, the matcher generates a map, of which each entry is a - // mapping from the source location of current build to the source location in - // the profile. - StringMap<LocToLocMap> FuncMappings; - - // Match state for an anchor/callsite. - enum class MatchState { - Unknown = 0, - // Initial match between input profile and current IR. - InitialMatch = 1, - // Initial mismatch between input profile and current IR. - InitialMismatch = 2, - // InitialMatch stays matched after fuzzy profile matching. - UnchangedMatch = 3, - // InitialMismatch stays mismatched after fuzzy profile matching. - UnchangedMismatch = 4, - // InitialMismatch is recovered after fuzzy profile matching. - RecoveredMismatch = 5, - // InitialMatch is removed and becomes mismatched after fuzzy profile - // matching. - RemovedMatch = 6, - }; - - // For each function, store every callsite and its matching state into this - // map, of which each entry is a pair of callsite location and MatchState. - // This is used for profile staleness computation and report. - StringMap<std::unordered_map<LineLocation, MatchState, LineLocationHash>> - FuncCallsiteMatchStates; - - // Profile mismatch statstics: - uint64_t TotalProfiledFunc = 0; - // Num of checksum-mismatched function. - uint64_t NumStaleProfileFunc = 0; - uint64_t TotalProfiledCallsites = 0; - uint64_t NumMismatchedCallsites = 0; - uint64_t NumRecoveredCallsites = 0; - // Total samples for all profiled functions. - uint64_t TotalFunctionSamples = 0; - // Total samples for all checksum-mismatched functions. - uint64_t MismatchedFunctionSamples = 0; - uint64_t MismatchedCallsiteSamples = 0; - uint64_t RecoveredCallsiteSamples = 0; - - // A dummy name for unknown indirect callee, used to differentiate from a - // non-call instruction that also has an empty callee name. - static constexpr const char *UnknownIndirectCallee = - "unknown.indirect.callee"; - -public: - SampleProfileMatcher(Module &M, SampleProfileReader &Reader, - const PseudoProbeManager *ProbeManager) - : M(M), Reader(Reader), ProbeManager(ProbeManager){}; - void runOnModule(); - void clearMatchingData() { - // Do not clear FuncMappings, it stores IRLoc to ProfLoc remappings which - // will be used for sample loader. - FuncCallsiteMatchStates.clear(); - } - -private: - FunctionSamples *getFlattenedSamplesFor(const Function &F) { - StringRef CanonFName = FunctionSamples::getCanonicalFnName(F); - auto It = FlattenedProfiles.find(FunctionId(CanonFName)); - if (It != FlattenedProfiles.end()) - return &It->second; - return nullptr; - } - void runOnFunction(const Function &F); - void findIRAnchors(const Function &F, - std::map<LineLocation, StringRef> &IRAnchors); - void findProfileAnchors( - const FunctionSamples &FS, - std::map<LineLocation, std::unordered_set<FunctionId>> &ProfileAnchors); - // Record the callsite match states for profile staleness report, the result - // is saved in FuncCallsiteMatchStates. - void recordCallsiteMatchStates( - const Function &F, const std::map<LineLocation, StringRef> &IRAnchors, - const std::map<LineLocation, std::unordered_set<FunctionId>> - &ProfileAnchors, - const LocToLocMap *IRToProfileLocationMap); - - bool isMismatchState(const enum MatchState &State) { - return State == MatchState::InitialMismatch || - State == MatchState::UnchangedMismatch || - State == MatchState::RemovedMatch; - }; - - bool isInitialState(const enum MatchState &State) { - return State == MatchState::InitialMatch || - State == MatchState::InitialMismatch; - }; - - bool isFinalState(const enum MatchState &State) { - return State == MatchState::UnchangedMatch || - State == MatchState::UnchangedMismatch || - State == MatchState::RecoveredMismatch || - State == MatchState::RemovedMatch; - }; - - // Count the samples of checksum mismatched function for the top-level - // function and all inlinees. - void countMismatchedFuncSamples(const FunctionSamples &FS, bool IsTopLevel); - // Count the number of mismatched or recovered callsites. - void countMismatchCallsites(const FunctionSamples &FS); - // Count the samples of mismatched or recovered callsites for top-level - // function and all inlinees. - void countMismatchedCallsiteSamples(const FunctionSamples &FS); - void computeAndReportProfileStaleness(); - - LocToLocMap &getIRToProfileLocationMap(const Function &F) { - auto Ret = FuncMappings.try_emplace( - FunctionSamples::getCanonicalFnName(F.getName()), LocToLocMap()); - return Ret.first->second; - } - void distributeIRToProfileLocationMap(); - void distributeIRToProfileLocationMap(FunctionSamples &FS); - void runStaleProfileMatching( - const Function &F, const std::map<LineLocation, StringRef> &IRAnchors, - const std::map<LineLocation, std::unordered_set<FunctionId>> - &ProfileAnchors, - LocToLocMap &IRToProfileLocationMap); - void reportOrPersistProfileStats(); -}; - /// Sample profile pass. /// /// This pass reads profile data from the file specified by @@ -630,6 +516,8 @@ protected: std::vector<Function *> buildFunctionOrder(Module &M, LazyCallGraph &CG); std::unique_ptr<ProfiledCallGraph> buildProfiledCallGraph(Module &M); void generateMDProfMetadata(Function &F); + bool rejectHighStalenessProfile(Module &M, ProfileSummaryInfo *PSI, + const SampleProfileMap &Profiles); /// Map from function name to Function *. Used to find the function from /// the function name. If the function name contains suffix, additional @@ -747,10 +635,6 @@ void SampleProfileLoaderBaseImpl<Function>::computeDominanceAndLoopInfo( } } // namespace llvm -static bool skipProfileForFunction(const Function &F) { - return F.isDeclaration() || !F.hasFnAttribute("use-sample-profile"); -} - ErrorOr<uint64_t> SampleProfileLoader::getInstWeight(const Instruction &Inst) { if (FunctionSamples::ProfileIsProbeBased) return getProbeWeight(Inst); @@ -1167,6 +1051,9 @@ void SampleProfileLoader::findExternalInlineCandidate( // For AutoFDO profile, retrieve candidate profiles by walking over // the nested inlinee profiles. if (!FunctionSamples::ProfileIsCS) { + // Set threshold to zero to honor pre-inliner decision. + if (UsePreInlinerDecision) + Threshold = 0; Samples->findInlinedFunctions(InlinedGUIDs, SymbolMap, Threshold); return; } @@ -1891,15 +1778,22 @@ bool SampleProfileLoader::emitAnnotations(Function &F) { bool Changed = false; if (FunctionSamples::ProfileIsProbeBased) { - if (!ProbeManager->profileIsValid(F, *Samples)) { + LLVM_DEBUG({ + if (!ProbeManager->getDesc(F)) + dbgs() << "Probe descriptor missing for Function " << F.getName() + << "\n"; + }); + + if (ProbeManager->profileIsValid(F, *Samples)) { + ++NumMatchedProfile; + } else { + ++NumMismatchedProfile; LLVM_DEBUG( dbgs() << "Profile is invalid due to CFG mismatch for Function " << F.getName() << "\n"); - ++NumMismatchedProfile; if (!SalvageStaleProfile) return false; } - ++NumMatchedProfile; } else { if (getFunctionLoc(F) == 0) return false; @@ -2165,7 +2059,7 @@ bool SampleProfileLoader::doInitialization(Module &M, // Load pseudo probe descriptors for probe-based function samples. if (Reader->profileIsProbeBased()) { - ProbeManager = std::make_unique<PseudoProbeManager>(M); + ProbeManager = std::make_unique<PseudoProbeManager>(M, LTOPhase); if (!ProbeManager->moduleIsProbed(M)) { const char *Msg = "Pseudo-probe-based profile requires SampleProfileProbePass"; @@ -2177,531 +2071,60 @@ bool SampleProfileLoader::doInitialization(Module &M, if (ReportProfileStaleness || PersistProfileStaleness || SalvageStaleProfile) { - MatchingManager = - std::make_unique<SampleProfileMatcher>(M, *Reader, ProbeManager.get()); + MatchingManager = std::make_unique<SampleProfileMatcher>( + M, *Reader, ProbeManager.get(), LTOPhase); } return true; } -void SampleProfileMatcher::findIRAnchors( - const Function &F, std::map<LineLocation, StringRef> &IRAnchors) { - // For inlined code, recover the original callsite and callee by finding the - // top-level inline frame. e.g. For frame stack "main:1 @ foo:2 @ bar:3", the - // top-level frame is "main:1", the callsite is "1" and the callee is "foo". - auto FindTopLevelInlinedCallsite = [](const DILocation *DIL) { - assert((DIL && DIL->getInlinedAt()) && "No inlined callsite"); - const DILocation *PrevDIL = nullptr; - do { - PrevDIL = DIL; - DIL = DIL->getInlinedAt(); - } while (DIL->getInlinedAt()); - - LineLocation Callsite = FunctionSamples::getCallSiteIdentifier(DIL); - StringRef CalleeName = PrevDIL->getSubprogramLinkageName(); - return std::make_pair(Callsite, CalleeName); - }; - - auto GetCanonicalCalleeName = [](const CallBase *CB) { - StringRef CalleeName = UnknownIndirectCallee; - if (Function *Callee = CB->getCalledFunction()) - CalleeName = FunctionSamples::getCanonicalFnName(Callee->getName()); - return CalleeName; - }; - - // Extract profile matching anchors in the IR. - for (auto &BB : F) { - for (auto &I : BB) { - DILocation *DIL = I.getDebugLoc(); - if (!DIL) - continue; - - if (FunctionSamples::ProfileIsProbeBased) { - if (auto Probe = extractProbe(I)) { - // Flatten inlined IR for the matching. - if (DIL->getInlinedAt()) { - IRAnchors.emplace(FindTopLevelInlinedCallsite(DIL)); - } else { - // Use empty StringRef for basic block probe. - StringRef CalleeName; - if (const auto *CB = dyn_cast<CallBase>(&I)) { - // Skip the probe inst whose callee name is "llvm.pseudoprobe". - if (!isa<IntrinsicInst>(&I)) - CalleeName = GetCanonicalCalleeName(CB); - } - IRAnchors.emplace(LineLocation(Probe->Id, 0), CalleeName); - } - } - } else { - // TODO: For line-number based profile(AutoFDO), currently only support - // find callsite anchors. In future, we need to parse all the non-call - // instructions to extract the line locations for profile matching. - if (!isa<CallBase>(&I) || isa<IntrinsicInst>(&I)) - continue; - - if (DIL->getInlinedAt()) { - IRAnchors.emplace(FindTopLevelInlinedCallsite(DIL)); - } else { - LineLocation Callsite = FunctionSamples::getCallSiteIdentifier(DIL); - StringRef CalleeName = GetCanonicalCalleeName(dyn_cast<CallBase>(&I)); - IRAnchors.emplace(Callsite, CalleeName); - } - } - } - } -} - -void SampleProfileMatcher::findProfileAnchors( - const FunctionSamples &FS, - std::map<LineLocation, std::unordered_set<FunctionId>> &ProfileAnchors) { - auto isInvalidLineOffset = [](uint32_t LineOffset) { - return LineOffset & 0x8000; - }; - - for (const auto &I : FS.getBodySamples()) { - const LineLocation &Loc = I.first; - if (isInvalidLineOffset(Loc.LineOffset)) +// Note that this is a module-level check. Even if one module is errored out, +// the entire build will be errored out. However, the user could make big +// changes to functions in single module but those changes might not be +// performance significant to the whole binary. Therefore, to avoid those false +// positives, we select a reasonable big set of hot functions that are supposed +// to be globally performance significant, only compute and check the mismatch +// within those functions. The function selection is based on two criteria: +// 1) The function is hot enough, which is tuned by a hotness-based +// flag(HotFuncCutoffForStalenessError). 2) The num of function is large enough +// which is tuned by the MinfuncsForStalenessError flag. +bool SampleProfileLoader::rejectHighStalenessProfile( + Module &M, ProfileSummaryInfo *PSI, const SampleProfileMap &Profiles) { + assert(FunctionSamples::ProfileIsProbeBased && + "Only support for probe-based profile"); + uint64_t TotalHotFunc = 0; + uint64_t NumMismatchedFunc = 0; + for (const auto &I : Profiles) { + const auto &FS = I.second; + const auto *FuncDesc = ProbeManager->getDesc(FS.getGUID()); + if (!FuncDesc) continue; - for (const auto &I : I.second.getCallTargets()) { - auto Ret = ProfileAnchors.try_emplace(Loc, - std::unordered_set<FunctionId>()); - Ret.first->second.insert(I.first); - } - } - for (const auto &I : FS.getCallsiteSamples()) { - const LineLocation &Loc = I.first; - if (isInvalidLineOffset(Loc.LineOffset)) + // Use a hotness-based threshold to control the function selection. + if (!PSI->isHotCountNthPercentile(HotFuncCutoffForStalenessError, + FS.getTotalSamples())) continue; - const auto &CalleeMap = I.second; - for (const auto &I : CalleeMap) { - auto Ret = ProfileAnchors.try_emplace(Loc, - std::unordered_set<FunctionId>()); - Ret.first->second.insert(I.first); - } - } -} -// Call target name anchor based profile fuzzy matching. -// Input: -// For IR locations, the anchor is the callee name of direct callsite; For -// profile locations, it's the call target name for BodySamples or inlinee's -// profile name for CallsiteSamples. -// Matching heuristic: -// First match all the anchors in lexical order, then split the non-anchor -// locations between the two anchors evenly, first half are matched based on the -// start anchor, second half are matched based on the end anchor. -// For example, given: -// IR locations: [1, 2(foo), 3, 5, 6(bar), 7] -// Profile locations: [1, 2, 3(foo), 4, 7, 8(bar), 9] -// The matching gives: -// [1, 2(foo), 3, 5, 6(bar), 7] -// | | | | | | -// [1, 2, 3(foo), 4, 7, 8(bar), 9] -// The output mapping: [2->3, 3->4, 5->7, 6->8, 7->9]. -void SampleProfileMatcher::runStaleProfileMatching( - const Function &F, const std::map<LineLocation, StringRef> &IRAnchors, - const std::map<LineLocation, std::unordered_set<FunctionId>> - &ProfileAnchors, - LocToLocMap &IRToProfileLocationMap) { - LLVM_DEBUG(dbgs() << "Run stale profile matching for " << F.getName() - << "\n"); - assert(IRToProfileLocationMap.empty() && - "Run stale profile matching only once per function"); - - std::unordered_map<FunctionId, std::set<LineLocation>> - CalleeToCallsitesMap; - for (const auto &I : ProfileAnchors) { - const auto &Loc = I.first; - const auto &Callees = I.second; - // Filter out possible indirect calls, use direct callee name as anchor. - if (Callees.size() == 1) { - FunctionId CalleeName = *Callees.begin(); - const auto &Candidates = CalleeToCallsitesMap.try_emplace( - CalleeName, std::set<LineLocation>()); - Candidates.first->second.insert(Loc); - } - } - - auto InsertMatching = [&](const LineLocation &From, const LineLocation &To) { - // Skip the unchanged location mapping to save memory. - if (From != To) - IRToProfileLocationMap.insert({From, To}); - }; - - // Use function's beginning location as the initial anchor. - int32_t LocationDelta = 0; - SmallVector<LineLocation> LastMatchedNonAnchors; - - for (const auto &IR : IRAnchors) { - const auto &Loc = IR.first; - auto CalleeName = IR.second; - bool IsMatchedAnchor = false; - // Match the anchor location in lexical order. - if (!CalleeName.empty()) { - auto CandidateAnchors = CalleeToCallsitesMap.find( - getRepInFormat(CalleeName)); - if (CandidateAnchors != CalleeToCallsitesMap.end() && - !CandidateAnchors->second.empty()) { - auto CI = CandidateAnchors->second.begin(); - const auto Candidate = *CI; - CandidateAnchors->second.erase(CI); - InsertMatching(Loc, Candidate); - LLVM_DEBUG(dbgs() << "Callsite with callee:" << CalleeName - << " is matched from " << Loc << " to " << Candidate - << "\n"); - LocationDelta = Candidate.LineOffset - Loc.LineOffset; - - // Match backwards for non-anchor locations. - // The locations in LastMatchedNonAnchors have been matched forwards - // based on the previous anchor, spilt it evenly and overwrite the - // second half based on the current anchor. - for (size_t I = (LastMatchedNonAnchors.size() + 1) / 2; - I < LastMatchedNonAnchors.size(); I++) { - const auto &L = LastMatchedNonAnchors[I]; - uint32_t CandidateLineOffset = L.LineOffset + LocationDelta; - LineLocation Candidate(CandidateLineOffset, L.Discriminator); - InsertMatching(L, Candidate); - LLVM_DEBUG(dbgs() << "Location is rematched backwards from " << L - << " to " << Candidate << "\n"); - } - - IsMatchedAnchor = true; - LastMatchedNonAnchors.clear(); - } - } - - // Match forwards for non-anchor locations. - if (!IsMatchedAnchor) { - uint32_t CandidateLineOffset = Loc.LineOffset + LocationDelta; - LineLocation Candidate(CandidateLineOffset, Loc.Discriminator); - InsertMatching(Loc, Candidate); - LLVM_DEBUG(dbgs() << "Location is matched from " << Loc << " to " - << Candidate << "\n"); - LastMatchedNonAnchors.emplace_back(Loc); - } + TotalHotFunc++; + if (ProbeManager->profileIsHashMismatched(*FuncDesc, FS)) + NumMismatchedFunc++; } -} - -void SampleProfileMatcher::runOnFunction(const Function &F) { - // We need to use flattened function samples for matching. - // Unlike IR, which includes all callsites from the source code, the callsites - // in profile only show up when they are hit by samples, i,e. the profile - // callsites in one context may differ from those in another context. To get - // the maximum number of callsites, we merge the function profiles from all - // contexts, aka, the flattened profile to find profile anchors. - const auto *FSFlattened = getFlattenedSamplesFor(F); - if (!FSFlattened) - return; - - // Anchors for IR. It's a map from IR location to callee name, callee name is - // empty for non-call instruction and use a dummy name(UnknownIndirectCallee) - // for unknown indrect callee name. - std::map<LineLocation, StringRef> IRAnchors; - findIRAnchors(F, IRAnchors); - // Anchors for profile. It's a map from callsite location to a set of callee - // name. - std::map<LineLocation, std::unordered_set<FunctionId>> ProfileAnchors; - findProfileAnchors(*FSFlattened, ProfileAnchors); - - // Compute the callsite match states for profile staleness report. - if (ReportProfileStaleness || PersistProfileStaleness) - recordCallsiteMatchStates(F, IRAnchors, ProfileAnchors, nullptr); - - // Run profile matching for checksum mismatched profile, currently only - // support for pseudo-probe. - if (SalvageStaleProfile && FunctionSamples::ProfileIsProbeBased && - !ProbeManager->profileIsValid(F, *FSFlattened)) { - // The matching result will be saved to IRToProfileLocationMap, create a new - // map for each function. - auto &IRToProfileLocationMap = getIRToProfileLocationMap(F); - runStaleProfileMatching(F, IRAnchors, ProfileAnchors, - IRToProfileLocationMap); - // Find and update callsite match states after matching. - if (ReportProfileStaleness || PersistProfileStaleness) - recordCallsiteMatchStates(F, IRAnchors, ProfileAnchors, - &IRToProfileLocationMap); - } -} - -void SampleProfileMatcher::recordCallsiteMatchStates( - const Function &F, const std::map<LineLocation, StringRef> &IRAnchors, - const std::map<LineLocation, std::unordered_set<FunctionId>> - &ProfileAnchors, - const LocToLocMap *IRToProfileLocationMap) { - bool IsPostMatch = IRToProfileLocationMap != nullptr; - auto &CallsiteMatchStates = - FuncCallsiteMatchStates[FunctionSamples::getCanonicalFnName(F.getName())]; - - auto MapIRLocToProfileLoc = [&](const LineLocation &IRLoc) { - // IRToProfileLocationMap is null in pre-match phrase. - if (!IRToProfileLocationMap) - return IRLoc; - const auto &ProfileLoc = IRToProfileLocationMap->find(IRLoc); - if (ProfileLoc != IRToProfileLocationMap->end()) - return ProfileLoc->second; - else - return IRLoc; - }; - - for (const auto &I : IRAnchors) { - // After fuzzy profile matching, use the matching result to remap the - // current IR callsite. - const auto &ProfileLoc = MapIRLocToProfileLoc(I.first); - const auto &IRCalleeName = I.second; - const auto &It = ProfileAnchors.find(ProfileLoc); - if (It == ProfileAnchors.end()) - continue; - const auto &Callees = It->second; - - bool IsCallsiteMatched = false; - // Since indirect call does not have CalleeName, check conservatively if - // callsite in the profile is a callsite location. This is to reduce num of - // false positive since otherwise all the indirect call samples will be - // reported as mismatching. - if (IRCalleeName == SampleProfileMatcher::UnknownIndirectCallee) - IsCallsiteMatched = true; - else if (Callees.size() == 1 && Callees.count(getRepInFormat(IRCalleeName))) - IsCallsiteMatched = true; - - if (IsCallsiteMatched) { - auto It = CallsiteMatchStates.find(ProfileLoc); - if (It == CallsiteMatchStates.end()) - CallsiteMatchStates.emplace(ProfileLoc, MatchState::InitialMatch); - else if (IsPostMatch) { - if (It->second == MatchState::InitialMatch) - It->second = MatchState::UnchangedMatch; - else if (It->second == MatchState::InitialMismatch) - It->second = MatchState::RecoveredMismatch; - } - } - } - - // Check if there are any callsites in the profile that does not match to any - // IR callsites. - for (const auto &I : ProfileAnchors) { - const auto &Loc = I.first; - [[maybe_unused]] const auto &Callees = I.second; - assert(!Callees.empty() && "Callees should not be empty"); - auto It = CallsiteMatchStates.find(Loc); - if (It == CallsiteMatchStates.end()) - CallsiteMatchStates.emplace(Loc, MatchState::InitialMismatch); - else if (IsPostMatch) { - // Update the state if it's not matched(UnchangedMatch or - // RecoveredMismatch). - if (It->second == MatchState::InitialMismatch) - It->second = MatchState::UnchangedMismatch; - else if (It->second == MatchState::InitialMatch) - It->second = MatchState::RemovedMatch; - } - } -} - -void SampleProfileMatcher::countMismatchedFuncSamples(const FunctionSamples &FS, - bool IsTopLevel) { - const auto *FuncDesc = ProbeManager->getDesc(FS.getGUID()); - // Skip the function that is external or renamed. - if (!FuncDesc) - return; - - if (ProbeManager->profileIsHashMismatched(*FuncDesc, FS)) { - if (IsTopLevel) - NumStaleProfileFunc++; - // Given currently all probe ids are after block probe ids, once the - // checksum is mismatched, it's likely all the callites are mismatched and - // dropped. We conservatively count all the samples as mismatched and stop - // counting the inlinees' profiles. - MismatchedFunctionSamples += FS.getTotalSamples(); - return; - } - - // Even the current-level function checksum is matched, it's possible that the - // nested inlinees' checksums are mismatched that affect the inlinee's sample - // loading, we need to go deeper to check the inlinees' function samples. - // Similarly, count all the samples as mismatched if the inlinee's checksum is - // mismatched using this recursive function. - for (const auto &I : FS.getCallsiteSamples()) - for (const auto &CS : I.second) - countMismatchedFuncSamples(CS.second, false); -} - -void SampleProfileMatcher::countMismatchedCallsiteSamples( - const FunctionSamples &FS) { - auto It = FuncCallsiteMatchStates.find(FS.getFuncName()); - // Skip it if no mismatched callsite or this is an external function. - if (It == FuncCallsiteMatchStates.end() || It->second.empty()) - return; - const auto &CallsiteMatchStates = It->second; - - auto findMatchState = [&](const LineLocation &Loc) { - auto It = CallsiteMatchStates.find(Loc); - if (It == CallsiteMatchStates.end()) - return MatchState::Unknown; - return It->second; - }; - - auto AttributeMismatchedSamples = [&](const enum MatchState &State, - uint64_t Samples) { - if (isMismatchState(State)) - MismatchedCallsiteSamples += Samples; - else if (State == MatchState::RecoveredMismatch) - RecoveredCallsiteSamples += Samples; - }; - - // The non-inlined callsites are saved in the body samples of function - // profile, go through it to count the non-inlined callsite samples. - for (const auto &I : FS.getBodySamples()) - AttributeMismatchedSamples(findMatchState(I.first), I.second.getSamples()); - - // Count the inlined callsite samples. - for (const auto &I : FS.getCallsiteSamples()) { - auto State = findMatchState(I.first); - uint64_t CallsiteSamples = 0; - for (const auto &CS : I.second) - CallsiteSamples += CS.second.getTotalSamples(); - AttributeMismatchedSamples(State, CallsiteSamples); - - if (isMismatchState(State)) - continue; - - // When the current level of inlined call site matches the profiled call - // site, we need to go deeper along the inline tree to count mismatches from - // lower level inlinees. - for (const auto &CS : I.second) - countMismatchedCallsiteSamples(CS.second); - } -} - -void SampleProfileMatcher::countMismatchCallsites(const FunctionSamples &FS) { - auto It = FuncCallsiteMatchStates.find(FS.getFuncName()); - // Skip it if no mismatched callsite or this is an external function. - if (It == FuncCallsiteMatchStates.end() || It->second.empty()) - return; - const auto &MatchStates = It->second; - [[maybe_unused]] bool OnInitialState = - isInitialState(MatchStates.begin()->second); - for (const auto &I : MatchStates) { - TotalProfiledCallsites++; - assert( - (OnInitialState ? isInitialState(I.second) : isFinalState(I.second)) && - "Profile matching state is inconsistent"); - - if (isMismatchState(I.second)) - NumMismatchedCallsites++; - else if (I.second == MatchState::RecoveredMismatch) - NumRecoveredCallsites++; - } -} - -void SampleProfileMatcher::computeAndReportProfileStaleness() { - if (!ReportProfileStaleness && !PersistProfileStaleness) - return; - - // Count profile mismatches for profile staleness report. - for (const auto &F : M) { - if (skipProfileForFunction(F)) - continue; - // As the stats will be merged by linker, skip reporting the metrics for - // imported functions to avoid repeated counting. - if (GlobalValue::isAvailableExternallyLinkage(F.getLinkage())) - continue; - const auto *FS = Reader.getSamplesFor(F); - if (!FS) - continue; - TotalProfiledFunc++; - TotalFunctionSamples += FS->getTotalSamples(); - - // Checksum mismatch is only used in pseudo-probe mode. - if (FunctionSamples::ProfileIsProbeBased) - countMismatchedFuncSamples(*FS, true); - - // Count mismatches and samples for calliste. - countMismatchCallsites(*FS); - countMismatchedCallsiteSamples(*FS); - } - - if (ReportProfileStaleness) { - if (FunctionSamples::ProfileIsProbeBased) { - errs() << "(" << NumStaleProfileFunc << "/" << TotalProfiledFunc << ")" - << " of functions' profile are invalid and " - << " (" << MismatchedFunctionSamples << "/" << TotalFunctionSamples - << ") of samples are discarded due to function hash mismatch.\n"; - } - errs() << "(" << (NumMismatchedCallsites + NumRecoveredCallsites) << "/" - << TotalProfiledCallsites << ")" - << " of callsites' profile are invalid and " - << "(" << (MismatchedCallsiteSamples + RecoveredCallsiteSamples) - << "/" << TotalFunctionSamples << ")" - << " of samples are discarded due to callsite location mismatch.\n"; - errs() << "(" << NumRecoveredCallsites << "/" - << (NumRecoveredCallsites + NumMismatchedCallsites) << ")" - << " of callsites and " - << "(" << RecoveredCallsiteSamples << "/" - << (RecoveredCallsiteSamples + MismatchedCallsiteSamples) << ")" - << " of samples are recovered by stale profile matching.\n"; - } - - if (PersistProfileStaleness) { - LLVMContext &Ctx = M.getContext(); - MDBuilder MDB(Ctx); - - SmallVector<std::pair<StringRef, uint64_t>> ProfStatsVec; - if (FunctionSamples::ProfileIsProbeBased) { - ProfStatsVec.emplace_back("NumStaleProfileFunc", NumStaleProfileFunc); - ProfStatsVec.emplace_back("TotalProfiledFunc", TotalProfiledFunc); - ProfStatsVec.emplace_back("MismatchedFunctionSamples", - MismatchedFunctionSamples); - ProfStatsVec.emplace_back("TotalFunctionSamples", TotalFunctionSamples); - } - - ProfStatsVec.emplace_back("NumMismatchedCallsites", NumMismatchedCallsites); - ProfStatsVec.emplace_back("NumRecoveredCallsites", NumRecoveredCallsites); - ProfStatsVec.emplace_back("TotalProfiledCallsites", TotalProfiledCallsites); - ProfStatsVec.emplace_back("MismatchedCallsiteSamples", - MismatchedCallsiteSamples); - ProfStatsVec.emplace_back("RecoveredCallsiteSamples", - RecoveredCallsiteSamples); - - auto *MD = MDB.createLLVMStats(ProfStatsVec); - auto *NMD = M.getOrInsertNamedMetadata("llvm.stats"); - NMD->addOperand(MD); - } -} - -void SampleProfileMatcher::runOnModule() { - ProfileConverter::flattenProfile(Reader.getProfiles(), FlattenedProfiles, - FunctionSamples::ProfileIsCS); - for (auto &F : M) { - if (skipProfileForFunction(F)) - continue; - runOnFunction(F); - } - if (SalvageStaleProfile) - distributeIRToProfileLocationMap(); - - computeAndReportProfileStaleness(); -} - -void SampleProfileMatcher::distributeIRToProfileLocationMap( - FunctionSamples &FS) { - const auto ProfileMappings = FuncMappings.find(FS.getFuncName()); - if (ProfileMappings != FuncMappings.end()) { - FS.setIRToProfileLocationMap(&(ProfileMappings->second)); - } - - for (auto &Inlinees : FS.getCallsiteSamples()) { - for (auto FS : Inlinees.second) { - distributeIRToProfileLocationMap(FS.second); - } - } -} + // Make sure that the num of selected function is not too small to distinguish + // from the user's benign changes. + if (TotalHotFunc < MinfuncsForStalenessError) + return false; -// Use a central place to distribute the matching results. Outlined and inlined -// profile with the function name will be set to the same pointer. -void SampleProfileMatcher::distributeIRToProfileLocationMap() { - for (auto &I : Reader.getProfiles()) { - distributeIRToProfileLocationMap(I.second); + // Finally check the mismatch percentage against the threshold. + if (NumMismatchedFunc * 100 >= + TotalHotFunc * PrecentMismatchForStalenessError) { + auto &Ctx = M.getContext(); + const char *Msg = + "The input profile significantly mismatches current source code. " + "Please recollect profile to avoid performance regression."; + Ctx.diagnose(DiagnosticInfoSampleProfile(M.getModuleIdentifier(), Msg)); + return true; } + return false; } bool SampleProfileLoader::runOnModule(Module &M, ModuleAnalysisManager *AM, @@ -2715,6 +2138,11 @@ bool SampleProfileLoader::runOnModule(Module &M, ModuleAnalysisManager *AM, ProfileSummary::PSK_Sample); PSI->refresh(); } + + if (FunctionSamples::ProfileIsProbeBased && + rejectHighStalenessProfile(M, PSI, Reader->getProfiles())) + return false; + // Compute the total number of samples collected in this profile. for (const auto &I : Reader->getProfiles()) TotalCollectedSamples += I.second.getTotalSamples(); diff --git a/llvm/lib/Transforms/IPO/SampleProfileMatcher.cpp b/llvm/lib/Transforms/IPO/SampleProfileMatcher.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb46539989ab5b7978d36cda7879c5ce1a2db77b --- /dev/null +++ b/llvm/lib/Transforms/IPO/SampleProfileMatcher.cpp @@ -0,0 +1,552 @@ +//===- SampleProfileMatcher.cpp - Sampling-based Stale Profile Matcher ----===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the SampleProfileMatcher used for stale +// profile matching. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/IPO/SampleProfileMatcher.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/MDBuilder.h" + +using namespace llvm; +using namespace sampleprof; + +#define DEBUG_TYPE "sample-profile-matcher" + +extern cl::opt<bool> SalvageStaleProfile; +extern cl::opt<bool> PersistProfileStaleness; +extern cl::opt<bool> ReportProfileStaleness; + +void SampleProfileMatcher::findIRAnchors( + const Function &F, std::map<LineLocation, StringRef> &IRAnchors) { + // For inlined code, recover the original callsite and callee by finding the + // top-level inline frame. e.g. For frame stack "main:1 @ foo:2 @ bar:3", the + // top-level frame is "main:1", the callsite is "1" and the callee is "foo". + auto FindTopLevelInlinedCallsite = [](const DILocation *DIL) { + assert((DIL && DIL->getInlinedAt()) && "No inlined callsite"); + const DILocation *PrevDIL = nullptr; + do { + PrevDIL = DIL; + DIL = DIL->getInlinedAt(); + } while (DIL->getInlinedAt()); + + LineLocation Callsite = FunctionSamples::getCallSiteIdentifier(DIL); + StringRef CalleeName = PrevDIL->getSubprogramLinkageName(); + return std::make_pair(Callsite, CalleeName); + }; + + auto GetCanonicalCalleeName = [](const CallBase *CB) { + StringRef CalleeName = UnknownIndirectCallee; + if (Function *Callee = CB->getCalledFunction()) + CalleeName = FunctionSamples::getCanonicalFnName(Callee->getName()); + return CalleeName; + }; + + // Extract profile matching anchors in the IR. + for (auto &BB : F) { + for (auto &I : BB) { + DILocation *DIL = I.getDebugLoc(); + if (!DIL) + continue; + + if (FunctionSamples::ProfileIsProbeBased) { + if (auto Probe = extractProbe(I)) { + // Flatten inlined IR for the matching. + if (DIL->getInlinedAt()) { + IRAnchors.emplace(FindTopLevelInlinedCallsite(DIL)); + } else { + // Use empty StringRef for basic block probe. + StringRef CalleeName; + if (const auto *CB = dyn_cast<CallBase>(&I)) { + // Skip the probe inst whose callee name is "llvm.pseudoprobe". + if (!isa<IntrinsicInst>(&I)) + CalleeName = GetCanonicalCalleeName(CB); + } + IRAnchors.emplace(LineLocation(Probe->Id, 0), CalleeName); + } + } + } else { + // TODO: For line-number based profile(AutoFDO), currently only support + // find callsite anchors. In future, we need to parse all the non-call + // instructions to extract the line locations for profile matching. + if (!isa<CallBase>(&I) || isa<IntrinsicInst>(&I)) + continue; + + if (DIL->getInlinedAt()) { + IRAnchors.emplace(FindTopLevelInlinedCallsite(DIL)); + } else { + LineLocation Callsite = FunctionSamples::getCallSiteIdentifier(DIL); + StringRef CalleeName = GetCanonicalCalleeName(dyn_cast<CallBase>(&I)); + IRAnchors.emplace(Callsite, CalleeName); + } + } + } + } +} + +void SampleProfileMatcher::findProfileAnchors( + const FunctionSamples &FS, + std::map<LineLocation, std::unordered_set<FunctionId>> &ProfileAnchors) { + auto isInvalidLineOffset = [](uint32_t LineOffset) { + return LineOffset & 0x8000; + }; + + for (const auto &I : FS.getBodySamples()) { + const LineLocation &Loc = I.first; + if (isInvalidLineOffset(Loc.LineOffset)) + continue; + for (const auto &I : I.second.getCallTargets()) { + auto Ret = + ProfileAnchors.try_emplace(Loc, std::unordered_set<FunctionId>()); + Ret.first->second.insert(I.first); + } + } + + for (const auto &I : FS.getCallsiteSamples()) { + const LineLocation &Loc = I.first; + if (isInvalidLineOffset(Loc.LineOffset)) + continue; + const auto &CalleeMap = I.second; + for (const auto &I : CalleeMap) { + auto Ret = + ProfileAnchors.try_emplace(Loc, std::unordered_set<FunctionId>()); + Ret.first->second.insert(I.first); + } + } +} + +// Call target name anchor based profile fuzzy matching. +// Input: +// For IR locations, the anchor is the callee name of direct callsite; For +// profile locations, it's the call target name for BodySamples or inlinee's +// profile name for CallsiteSamples. +// Matching heuristic: +// First match all the anchors in lexical order, then split the non-anchor +// locations between the two anchors evenly, first half are matched based on the +// start anchor, second half are matched based on the end anchor. +// For example, given: +// IR locations: [1, 2(foo), 3, 5, 6(bar), 7] +// Profile locations: [1, 2, 3(foo), 4, 7, 8(bar), 9] +// The matching gives: +// [1, 2(foo), 3, 5, 6(bar), 7] +// | | | | | | +// [1, 2, 3(foo), 4, 7, 8(bar), 9] +// The output mapping: [2->3, 3->4, 5->7, 6->8, 7->9]. +void SampleProfileMatcher::runStaleProfileMatching( + const Function &F, const std::map<LineLocation, StringRef> &IRAnchors, + const std::map<LineLocation, std::unordered_set<FunctionId>> + &ProfileAnchors, + LocToLocMap &IRToProfileLocationMap) { + LLVM_DEBUG(dbgs() << "Run stale profile matching for " << F.getName() + << "\n"); + assert(IRToProfileLocationMap.empty() && + "Run stale profile matching only once per function"); + + std::unordered_map<FunctionId, std::set<LineLocation>> CalleeToCallsitesMap; + for (const auto &I : ProfileAnchors) { + const auto &Loc = I.first; + const auto &Callees = I.second; + // Filter out possible indirect calls, use direct callee name as anchor. + if (Callees.size() == 1) { + FunctionId CalleeName = *Callees.begin(); + const auto &Candidates = CalleeToCallsitesMap.try_emplace( + CalleeName, std::set<LineLocation>()); + Candidates.first->second.insert(Loc); + } + } + + auto InsertMatching = [&](const LineLocation &From, const LineLocation &To) { + // Skip the unchanged location mapping to save memory. + if (From != To) + IRToProfileLocationMap.insert({From, To}); + }; + + // Use function's beginning location as the initial anchor. + int32_t LocationDelta = 0; + SmallVector<LineLocation> LastMatchedNonAnchors; + + for (const auto &IR : IRAnchors) { + const auto &Loc = IR.first; + auto CalleeName = IR.second; + bool IsMatchedAnchor = false; + // Match the anchor location in lexical order. + if (!CalleeName.empty()) { + auto CandidateAnchors = + CalleeToCallsitesMap.find(getRepInFormat(CalleeName)); + if (CandidateAnchors != CalleeToCallsitesMap.end() && + !CandidateAnchors->second.empty()) { + auto CI = CandidateAnchors->second.begin(); + const auto Candidate = *CI; + CandidateAnchors->second.erase(CI); + InsertMatching(Loc, Candidate); + LLVM_DEBUG(dbgs() << "Callsite with callee:" << CalleeName + << " is matched from " << Loc << " to " << Candidate + << "\n"); + LocationDelta = Candidate.LineOffset - Loc.LineOffset; + + // Match backwards for non-anchor locations. + // The locations in LastMatchedNonAnchors have been matched forwards + // based on the previous anchor, spilt it evenly and overwrite the + // second half based on the current anchor. + for (size_t I = (LastMatchedNonAnchors.size() + 1) / 2; + I < LastMatchedNonAnchors.size(); I++) { + const auto &L = LastMatchedNonAnchors[I]; + uint32_t CandidateLineOffset = L.LineOffset + LocationDelta; + LineLocation Candidate(CandidateLineOffset, L.Discriminator); + InsertMatching(L, Candidate); + LLVM_DEBUG(dbgs() << "Location is rematched backwards from " << L + << " to " << Candidate << "\n"); + } + + IsMatchedAnchor = true; + LastMatchedNonAnchors.clear(); + } + } + + // Match forwards for non-anchor locations. + if (!IsMatchedAnchor) { + uint32_t CandidateLineOffset = Loc.LineOffset + LocationDelta; + LineLocation Candidate(CandidateLineOffset, Loc.Discriminator); + InsertMatching(Loc, Candidate); + LLVM_DEBUG(dbgs() << "Location is matched from " << Loc << " to " + << Candidate << "\n"); + LastMatchedNonAnchors.emplace_back(Loc); + } + } +} + +void SampleProfileMatcher::runOnFunction(Function &F) { + // We need to use flattened function samples for matching. + // Unlike IR, which includes all callsites from the source code, the callsites + // in profile only show up when they are hit by samples, i,e. the profile + // callsites in one context may differ from those in another context. To get + // the maximum number of callsites, we merge the function profiles from all + // contexts, aka, the flattened profile to find profile anchors. + const auto *FSFlattened = getFlattenedSamplesFor(F); + if (!FSFlattened) + return; + + // Anchors for IR. It's a map from IR location to callee name, callee name is + // empty for non-call instruction and use a dummy name(UnknownIndirectCallee) + // for unknown indrect callee name. + std::map<LineLocation, StringRef> IRAnchors; + findIRAnchors(F, IRAnchors); + // Anchors for profile. It's a map from callsite location to a set of callee + // name. + std::map<LineLocation, std::unordered_set<FunctionId>> ProfileAnchors; + findProfileAnchors(*FSFlattened, ProfileAnchors); + + // Compute the callsite match states for profile staleness report. + if (ReportProfileStaleness || PersistProfileStaleness) + recordCallsiteMatchStates(F, IRAnchors, ProfileAnchors, nullptr); + + // Run profile matching for checksum mismatched profile, currently only + // support for pseudo-probe. + if (SalvageStaleProfile && FunctionSamples::ProfileIsProbeBased && + !ProbeManager->profileIsValid(F, *FSFlattened)) { + // For imported functions, the checksum metadata(pseudo_probe_desc) are + // dropped, so we leverage function attribute(profile-checksum-mismatch) to + // transfer the info: add the attribute during pre-link phase and check it + // during post-link phase(see "profileIsValid"). + if (FunctionSamples::ProfileIsProbeBased && + LTOPhase == ThinOrFullLTOPhase::ThinLTOPreLink) + F.addFnAttr("profile-checksum-mismatch"); + + // The matching result will be saved to IRToProfileLocationMap, create a + // new map for each function. + auto &IRToProfileLocationMap = getIRToProfileLocationMap(F); + runStaleProfileMatching(F, IRAnchors, ProfileAnchors, + IRToProfileLocationMap); + // Find and update callsite match states after matching. + if (ReportProfileStaleness || PersistProfileStaleness) + recordCallsiteMatchStates(F, IRAnchors, ProfileAnchors, + &IRToProfileLocationMap); + } +} + +void SampleProfileMatcher::recordCallsiteMatchStates( + const Function &F, const std::map<LineLocation, StringRef> &IRAnchors, + const std::map<LineLocation, std::unordered_set<FunctionId>> + &ProfileAnchors, + const LocToLocMap *IRToProfileLocationMap) { + bool IsPostMatch = IRToProfileLocationMap != nullptr; + auto &CallsiteMatchStates = + FuncCallsiteMatchStates[FunctionSamples::getCanonicalFnName(F.getName())]; + + auto MapIRLocToProfileLoc = [&](const LineLocation &IRLoc) { + // IRToProfileLocationMap is null in pre-match phrase. + if (!IRToProfileLocationMap) + return IRLoc; + const auto &ProfileLoc = IRToProfileLocationMap->find(IRLoc); + if (ProfileLoc != IRToProfileLocationMap->end()) + return ProfileLoc->second; + else + return IRLoc; + }; + + for (const auto &I : IRAnchors) { + // After fuzzy profile matching, use the matching result to remap the + // current IR callsite. + const auto &ProfileLoc = MapIRLocToProfileLoc(I.first); + const auto &IRCalleeName = I.second; + const auto &It = ProfileAnchors.find(ProfileLoc); + if (It == ProfileAnchors.end()) + continue; + const auto &Callees = It->second; + + bool IsCallsiteMatched = false; + // Since indirect call does not have CalleeName, check conservatively if + // callsite in the profile is a callsite location. This is to reduce num of + // false positive since otherwise all the indirect call samples will be + // reported as mismatching. + if (IRCalleeName == SampleProfileMatcher::UnknownIndirectCallee) + IsCallsiteMatched = true; + else if (Callees.size() == 1 && Callees.count(getRepInFormat(IRCalleeName))) + IsCallsiteMatched = true; + + if (IsCallsiteMatched) { + auto It = CallsiteMatchStates.find(ProfileLoc); + if (It == CallsiteMatchStates.end()) + CallsiteMatchStates.emplace(ProfileLoc, MatchState::InitialMatch); + else if (IsPostMatch) { + if (It->second == MatchState::InitialMatch) + It->second = MatchState::UnchangedMatch; + else if (It->second == MatchState::InitialMismatch) + It->second = MatchState::RecoveredMismatch; + } + } + } + + // Check if there are any callsites in the profile that does not match to any + // IR callsites. + for (const auto &I : ProfileAnchors) { + const auto &Loc = I.first; + [[maybe_unused]] const auto &Callees = I.second; + assert(!Callees.empty() && "Callees should not be empty"); + auto It = CallsiteMatchStates.find(Loc); + if (It == CallsiteMatchStates.end()) + CallsiteMatchStates.emplace(Loc, MatchState::InitialMismatch); + else if (IsPostMatch) { + // Update the state if it's not matched(UnchangedMatch or + // RecoveredMismatch). + if (It->second == MatchState::InitialMismatch) + It->second = MatchState::UnchangedMismatch; + else if (It->second == MatchState::InitialMatch) + It->second = MatchState::RemovedMatch; + } + } +} + +void SampleProfileMatcher::countMismatchedFuncSamples(const FunctionSamples &FS, + bool IsTopLevel) { + const auto *FuncDesc = ProbeManager->getDesc(FS.getGUID()); + // Skip the function that is external or renamed. + if (!FuncDesc) + return; + + if (ProbeManager->profileIsHashMismatched(*FuncDesc, FS)) { + if (IsTopLevel) + NumStaleProfileFunc++; + // Given currently all probe ids are after block probe ids, once the + // checksum is mismatched, it's likely all the callites are mismatched and + // dropped. We conservatively count all the samples as mismatched and stop + // counting the inlinees' profiles. + MismatchedFunctionSamples += FS.getTotalSamples(); + return; + } + + // Even the current-level function checksum is matched, it's possible that the + // nested inlinees' checksums are mismatched that affect the inlinee's sample + // loading, we need to go deeper to check the inlinees' function samples. + // Similarly, count all the samples as mismatched if the inlinee's checksum is + // mismatched using this recursive function. + for (const auto &I : FS.getCallsiteSamples()) + for (const auto &CS : I.second) + countMismatchedFuncSamples(CS.second, false); +} + +void SampleProfileMatcher::countMismatchedCallsiteSamples( + const FunctionSamples &FS) { + auto It = FuncCallsiteMatchStates.find(FS.getFuncName()); + // Skip it if no mismatched callsite or this is an external function. + if (It == FuncCallsiteMatchStates.end() || It->second.empty()) + return; + const auto &CallsiteMatchStates = It->second; + + auto findMatchState = [&](const LineLocation &Loc) { + auto It = CallsiteMatchStates.find(Loc); + if (It == CallsiteMatchStates.end()) + return MatchState::Unknown; + return It->second; + }; + + auto AttributeMismatchedSamples = [&](const enum MatchState &State, + uint64_t Samples) { + if (isMismatchState(State)) + MismatchedCallsiteSamples += Samples; + else if (State == MatchState::RecoveredMismatch) + RecoveredCallsiteSamples += Samples; + }; + + // The non-inlined callsites are saved in the body samples of function + // profile, go through it to count the non-inlined callsite samples. + for (const auto &I : FS.getBodySamples()) + AttributeMismatchedSamples(findMatchState(I.first), I.second.getSamples()); + + // Count the inlined callsite samples. + for (const auto &I : FS.getCallsiteSamples()) { + auto State = findMatchState(I.first); + uint64_t CallsiteSamples = 0; + for (const auto &CS : I.second) + CallsiteSamples += CS.second.getTotalSamples(); + AttributeMismatchedSamples(State, CallsiteSamples); + + if (isMismatchState(State)) + continue; + + // When the current level of inlined call site matches the profiled call + // site, we need to go deeper along the inline tree to count mismatches from + // lower level inlinees. + for (const auto &CS : I.second) + countMismatchedCallsiteSamples(CS.second); + } +} + +void SampleProfileMatcher::countMismatchCallsites(const FunctionSamples &FS) { + auto It = FuncCallsiteMatchStates.find(FS.getFuncName()); + // Skip it if no mismatched callsite or this is an external function. + if (It == FuncCallsiteMatchStates.end() || It->second.empty()) + return; + const auto &MatchStates = It->second; + [[maybe_unused]] bool OnInitialState = + isInitialState(MatchStates.begin()->second); + for (const auto &I : MatchStates) { + TotalProfiledCallsites++; + assert( + (OnInitialState ? isInitialState(I.second) : isFinalState(I.second)) && + "Profile matching state is inconsistent"); + + if (isMismatchState(I.second)) + NumMismatchedCallsites++; + else if (I.second == MatchState::RecoveredMismatch) + NumRecoveredCallsites++; + } +} + +void SampleProfileMatcher::computeAndReportProfileStaleness() { + if (!ReportProfileStaleness && !PersistProfileStaleness) + return; + + // Count profile mismatches for profile staleness report. + for (const auto &F : M) { + if (skipProfileForFunction(F)) + continue; + // As the stats will be merged by linker, skip reporting the metrics for + // imported functions to avoid repeated counting. + if (GlobalValue::isAvailableExternallyLinkage(F.getLinkage())) + continue; + const auto *FS = Reader.getSamplesFor(F); + if (!FS) + continue; + TotalProfiledFunc++; + TotalFunctionSamples += FS->getTotalSamples(); + + // Checksum mismatch is only used in pseudo-probe mode. + if (FunctionSamples::ProfileIsProbeBased) + countMismatchedFuncSamples(*FS, true); + + // Count mismatches and samples for calliste. + countMismatchCallsites(*FS); + countMismatchedCallsiteSamples(*FS); + } + + if (ReportProfileStaleness) { + if (FunctionSamples::ProfileIsProbeBased) { + errs() << "(" << NumStaleProfileFunc << "/" << TotalProfiledFunc + << ") of functions' profile are invalid and (" + << MismatchedFunctionSamples << "/" << TotalFunctionSamples + << ") of samples are discarded due to function hash mismatch.\n"; + } + errs() << "(" << (NumMismatchedCallsites + NumRecoveredCallsites) << "/" + << TotalProfiledCallsites + << ") of callsites' profile are invalid and (" + << (MismatchedCallsiteSamples + RecoveredCallsiteSamples) << "/" + << TotalFunctionSamples + << ") of samples are discarded due to callsite location mismatch.\n"; + errs() << "(" << NumRecoveredCallsites << "/" + << (NumRecoveredCallsites + NumMismatchedCallsites) + << ") of callsites and (" << RecoveredCallsiteSamples << "/" + << (RecoveredCallsiteSamples + MismatchedCallsiteSamples) + << ") of samples are recovered by stale profile matching.\n"; + } + + if (PersistProfileStaleness) { + LLVMContext &Ctx = M.getContext(); + MDBuilder MDB(Ctx); + + SmallVector<std::pair<StringRef, uint64_t>> ProfStatsVec; + if (FunctionSamples::ProfileIsProbeBased) { + ProfStatsVec.emplace_back("NumStaleProfileFunc", NumStaleProfileFunc); + ProfStatsVec.emplace_back("TotalProfiledFunc", TotalProfiledFunc); + ProfStatsVec.emplace_back("MismatchedFunctionSamples", + MismatchedFunctionSamples); + ProfStatsVec.emplace_back("TotalFunctionSamples", TotalFunctionSamples); + } + + ProfStatsVec.emplace_back("NumMismatchedCallsites", NumMismatchedCallsites); + ProfStatsVec.emplace_back("NumRecoveredCallsites", NumRecoveredCallsites); + ProfStatsVec.emplace_back("TotalProfiledCallsites", TotalProfiledCallsites); + ProfStatsVec.emplace_back("MismatchedCallsiteSamples", + MismatchedCallsiteSamples); + ProfStatsVec.emplace_back("RecoveredCallsiteSamples", + RecoveredCallsiteSamples); + + auto *MD = MDB.createLLVMStats(ProfStatsVec); + auto *NMD = M.getOrInsertNamedMetadata("llvm.stats"); + NMD->addOperand(MD); + } +} + +void SampleProfileMatcher::runOnModule() { + ProfileConverter::flattenProfile(Reader.getProfiles(), FlattenedProfiles, + FunctionSamples::ProfileIsCS); + for (auto &F : M) { + if (skipProfileForFunction(F)) + continue; + runOnFunction(F); + } + if (SalvageStaleProfile) + distributeIRToProfileLocationMap(); + + computeAndReportProfileStaleness(); +} + +void SampleProfileMatcher::distributeIRToProfileLocationMap( + FunctionSamples &FS) { + const auto ProfileMappings = FuncMappings.find(FS.getFuncName()); + if (ProfileMappings != FuncMappings.end()) { + FS.setIRToProfileLocationMap(&(ProfileMappings->second)); + } + + for (auto &Callees : + const_cast<CallsiteSampleMap &>(FS.getCallsiteSamples())) { + for (auto &FS : Callees.second) { + distributeIRToProfileLocationMap(FS.second); + } + } +} + +// Use a central place to distribute the matching results. Outlined and inlined +// profile with the function name will be set to the same pointer. +void SampleProfileMatcher::distributeIRToProfileLocationMap() { + for (auto &I : Reader.getProfiles()) { + distributeIRToProfileLocationMap(I.second); + } +} diff --git a/llvm/lib/Transforms/IPO/SampleProfileProbe.cpp b/llvm/lib/Transforms/IPO/SampleProfileProbe.cpp index 090e5560483edb9661aa62a92a422ebe0e882057..4d0fa24bd57ca4419648ff07132bb5da752a3e54 100644 --- a/llvm/lib/Transforms/IPO/SampleProfileProbe.cpp +++ b/llvm/lib/Transforms/IPO/SampleProfileProbe.cpp @@ -173,21 +173,114 @@ SampleProfileProber::SampleProfileProber(Function &Func, BlockProbeIds.clear(); CallProbeIds.clear(); LastProbeId = (uint32_t)PseudoProbeReservedId::Last; - computeProbeIdForBlocks(); - computeProbeIdForCallsites(); - computeCFGHash(); + + DenseSet<BasicBlock *> BlocksToIgnore; + DenseSet<BasicBlock *> BlocksAndCallsToIgnore; + computeBlocksToIgnore(BlocksToIgnore, BlocksAndCallsToIgnore); + + computeProbeIdForBlocks(BlocksToIgnore); + computeProbeIdForCallsites(BlocksAndCallsToIgnore); + computeCFGHash(BlocksToIgnore); +} + +// Two purposes to compute the blocks to ignore: +// 1. Reduce the IR size. +// 2. Make the instrumentation(checksum) stable. e.g. the frondend may +// generate unstable IR while optimizing nounwind attribute, some versions are +// optimized with the call-to-invoke conversion, while other versions do not. +// This discrepancy in probe ID could cause profile mismatching issues. +// Note that those ignored blocks are either cold blocks or new split blocks +// whose original blocks are instrumented, so it shouldn't degrade the profile +// quality. +void SampleProfileProber::computeBlocksToIgnore( + DenseSet<BasicBlock *> &BlocksToIgnore, + DenseSet<BasicBlock *> &BlocksAndCallsToIgnore) { + // Ignore the cold EH and unreachable blocks and calls. + computeEHOnlyBlocks(*F, BlocksAndCallsToIgnore); + findUnreachableBlocks(BlocksAndCallsToIgnore); + + BlocksToIgnore.insert(BlocksAndCallsToIgnore.begin(), + BlocksAndCallsToIgnore.end()); + + // Handle the call-to-invoke conversion case: make sure that the probe id and + // callsite id are consistent before and after the block split. For block + // probe, we only keep the head block probe id and ignore the block ids of the + // normal dests. For callsite probe, it's different to block probe, there is + // no additional callsite in the normal dests, so we don't ignore the + // callsites. + findInvokeNormalDests(BlocksToIgnore); +} + +// Unreachable blocks and calls are always cold, ignore them. +void SampleProfileProber::findUnreachableBlocks( + DenseSet<BasicBlock *> &BlocksToIgnore) { + for (auto &BB : *F) { + if (&BB != &F->getEntryBlock() && pred_size(&BB) == 0) + BlocksToIgnore.insert(&BB); + } +} + +// In call-to-invoke conversion, basic block can be split into multiple blocks, +// only instrument probe in the head block, ignore the normal dests. +void SampleProfileProber::findInvokeNormalDests( + DenseSet<BasicBlock *> &InvokeNormalDests) { + for (auto &BB : *F) { + auto *TI = BB.getTerminator(); + if (auto *II = dyn_cast<InvokeInst>(TI)) { + auto *ND = II->getNormalDest(); + InvokeNormalDests.insert(ND); + + // The normal dest and the try/catch block are connected by an + // unconditional branch. + while (pred_size(ND) == 1) { + auto *Pred = *pred_begin(ND); + if (succ_size(Pred) == 1) { + InvokeNormalDests.insert(Pred); + ND = Pred; + } else + break; + } + } + } +} + +// The call-to-invoke conversion splits the original block into a list of block, +// we need to compute the hash using the original block's successors to keep the +// CFG Hash consistent. For a given head block, we keep searching the +// succesor(normal dest or unconditional branch dest) to find the tail block, +// the tail block's successors are the original block's successors. +const Instruction *SampleProfileProber::getOriginalTerminator( + const BasicBlock *Head, const DenseSet<BasicBlock *> &BlocksToIgnore) { + auto *TI = Head->getTerminator(); + if (auto *II = dyn_cast<InvokeInst>(TI)) { + return getOriginalTerminator(II->getNormalDest(), BlocksToIgnore); + } else if (succ_size(Head) == 1 && + BlocksToIgnore.contains(*succ_begin(Head))) { + // Go to the unconditional branch dest. + return getOriginalTerminator(*succ_begin(Head), BlocksToIgnore); + } + return TI; } // Compute Hash value for the CFG: the lower 32 bits are CRC32 of the index // value of each BB in the CFG. The higher 32 bits record the number of edges // preceded by the number of indirect calls. // This is derived from FuncPGOInstrumentation<Edge, BBInfo>::computeCFGHash(). -void SampleProfileProber::computeCFGHash() { +void SampleProfileProber::computeCFGHash( + const DenseSet<BasicBlock *> &BlocksToIgnore) { std::vector<uint8_t> Indexes; JamCRC JC; for (auto &BB : *F) { - for (BasicBlock *Succ : successors(&BB)) { + if (BlocksToIgnore.contains(&BB)) + continue; + + auto *TI = getOriginalTerminator(&BB, BlocksToIgnore); + for (unsigned I = 0, E = TI->getNumSuccessors(); I != E; ++I) { + auto *Succ = TI->getSuccessor(I); auto Index = getBlockId(Succ); + // Ingore ignored-block(zero ID) to avoid unstable checksum. + if (Index == 0) + continue; for (int J = 0; J < 4; J++) Indexes.push_back((uint8_t)(Index >> (J * 8))); } @@ -207,23 +300,23 @@ void SampleProfileProber::computeCFGHash() { << ", Hash = " << FunctionHash << "\n"); } -void SampleProfileProber::computeProbeIdForBlocks() { - DenseSet<BasicBlock *> KnownColdBlocks; - computeEHOnlyBlocks(*F, KnownColdBlocks); - // Insert pseudo probe to non-cold blocks only. This will reduce IR size as - // well as the binary size while retaining the profile quality. +void SampleProfileProber::computeProbeIdForBlocks( + const DenseSet<BasicBlock *> &BlocksToIgnore) { for (auto &BB : *F) { - ++LastProbeId; - if (!KnownColdBlocks.contains(&BB)) - BlockProbeIds[&BB] = LastProbeId; + if (BlocksToIgnore.contains(&BB)) + continue; + BlockProbeIds[&BB] = ++LastProbeId; } } -void SampleProfileProber::computeProbeIdForCallsites() { +void SampleProfileProber::computeProbeIdForCallsites( + const DenseSet<BasicBlock *> &BlocksAndCallsToIgnore) { LLVMContext &Ctx = F->getContext(); Module *M = F->getParent(); for (auto &BB : *F) { + if (BlocksAndCallsToIgnore.contains(&BB)) + continue; for (auto &I : BB) { if (!isa<CallBase>(I)) continue; diff --git a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp index dd6062d303d42e24146599c4130656e3427d03ee..3986359b6a5a355bb9e2f43866b7ff5d9eb7a4e1 100644 --- a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp +++ b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp @@ -575,16 +575,17 @@ bool writeThinLTOBitcode(raw_ostream &OS, raw_ostream *ThinLinkOS, } } // anonymous namespace - +extern bool WriteNewDbgInfoFormatToBitcode; PreservedAnalyses llvm::ThinLTOBitcodeWriterPass::run(Module &M, ModuleAnalysisManager &AM) { FunctionAnalysisManager &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); - // RemoveDIs: there's no bitcode representation of the DPValue debug-info, - // convert to dbg.values before writing out. - bool IsNewDbgInfoFormat = M.IsNewDbgInfoFormat; - if (IsNewDbgInfoFormat) + // RemoveDIs: there's no bitcode representation of the DbgVariableRecord + // debug-info, convert to dbg.values before writing out. + bool ConvertToOldDbgFormatForWrite = + M.IsNewDbgInfoFormat && !WriteNewDbgInfoFormatToBitcode; + if (ConvertToOldDbgFormatForWrite) M.convertFromNewDbgValues(); bool Changed = writeThinLTOBitcode( @@ -594,7 +595,7 @@ llvm::ThinLTOBitcodeWriterPass::run(Module &M, ModuleAnalysisManager &AM) { }, M, &AM.getResult<ModuleSummaryIndexAnalysis>(M)); - if (IsNewDbgInfoFormat) + if (ConvertToOldDbgFormatForWrite) M.convertToNewDbgValues(); return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index aaf7184a5562cdfc53c836e6becc215b39c5de62..fa1e2280991fdd2f94551ac81aaeece29ec18eef 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -819,7 +819,7 @@ static Instruction *foldNoWrapAdd(BinaryOperator &Add, Value *X; const APInt *C1, *C2; if (match(Op1, m_APInt(C1)) && - match(Op0, m_OneUse(m_ZExt(m_NUWAdd(m_Value(X), m_APInt(C2))))) && + match(Op0, m_OneUse(m_ZExt(m_NUWAddLike(m_Value(X), m_APInt(C2))))) && C1->isNegative() && C1->sge(-C2->sext(C1->getBitWidth()))) { Constant *NewC = ConstantInt::get(X->getType(), *C2 + C1->trunc(C2->getBitWidth())); @@ -829,14 +829,16 @@ static Instruction *foldNoWrapAdd(BinaryOperator &Add, // More general combining of constants in the wide type. // (sext (X +nsw NarrowC)) + C --> (sext X) + (sext(NarrowC) + C) Constant *NarrowC; - if (match(Op0, m_OneUse(m_SExt(m_NSWAdd(m_Value(X), m_Constant(NarrowC)))))) { + if (match(Op0, + m_OneUse(m_SExt(m_NSWAddLike(m_Value(X), m_Constant(NarrowC)))))) { Value *WideC = Builder.CreateSExt(NarrowC, Ty); Value *NewC = Builder.CreateAdd(WideC, Op1C); Value *WideX = Builder.CreateSExt(X, Ty); return BinaryOperator::CreateAdd(WideX, NewC); } // (zext (X +nuw NarrowC)) + C --> (zext X) + (zext(NarrowC) + C) - if (match(Op0, m_OneUse(m_ZExt(m_NUWAdd(m_Value(X), m_Constant(NarrowC)))))) { + if (match(Op0, + m_OneUse(m_ZExt(m_NUWAddLike(m_Value(X), m_Constant(NarrowC)))))) { Value *WideC = Builder.CreateZExt(NarrowC, Ty); Value *NewC = Builder.CreateAdd(WideC, Op1C); Value *WideX = Builder.CreateZExt(X, Ty); @@ -2522,9 +2524,10 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) { // sub (xor A, B), B ; flip bits if negative and subtract -1 (add 1) // --> (A < 0) ? -A : A Value *IsNeg = Builder.CreateIsNeg(A); - // Copy the nuw/nsw flags from the sub to the negate. - Value *NegA = Builder.CreateNeg(A, "", I.hasNoUnsignedWrap(), - I.hasNoSignedWrap()); + // Copy the nsw flags from the sub to the negate. + Value *NegA = I.hasNoUnsignedWrap() + ? Constant::getNullValue(A->getType()) + : Builder.CreateNeg(A, "", I.hasNoSignedWrap()); return SelectInst::Create(IsNeg, NegA, A); } diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index bf8794bba8859f299c662984f61bafb9a0ea11db..c0cf1a7db726003679af2ccc5a9385a5febc0a1f 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -4250,10 +4250,11 @@ static Instruction *canonicalizeAbs(BinaryOperator &Xor, // xor (add A, Op1), Op1 ; add -1 and flip bits if negative // --> (A < 0) ? -A : A Value *IsNeg = Builder.CreateIsNeg(A); - // Copy the nuw/nsw flags from the add to the negate. + // Copy the nsw flags from the add to the negate. auto *Add = cast<BinaryOperator>(Op0); - Value *NegA = Builder.CreateNeg(A, "", Add->hasNoUnsignedWrap(), - Add->hasNoSignedWrap()); + Value *NegA = Add->hasNoUnsignedWrap() + ? Constant::getNullValue(A->getType()) + : Builder.CreateNeg(A, "", Add->hasNoSignedWrap()); return SelectInst::Create(IsNeg, NegA, A); } return nullptr; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index a7f2b0216bfa00a0de4864844581b2d46846602c..b1017f4d6bc179e0370b38edee95ccea83dc601b 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -274,7 +274,7 @@ Instruction *InstCombinerImpl::SimplifyAnyMemSet(AnyMemSetInst *MI) { DbgAssign->replaceVariableLocationOp(FillC, FillVal); }; for_each(at::getAssignmentMarkers(S), replaceOpForAssignmentMarkers); - for_each(at::getDPVAssignmentMarkers(S), replaceOpForAssignmentMarkers); + for_each(at::getDVRAssignmentMarkers(S), replaceOpForAssignmentMarkers); S->setAlignment(Alignment); if (isa<AtomicMemSetInst>(MI)) @@ -504,6 +504,11 @@ static Instruction *foldCttzCtlz(IntrinsicInst &II, InstCombinerImpl &IC) { return IC.replaceInstUsesWith(II, ConstantInt::getNullValue(II.getType())); } + // If ctlz/cttz is only used as a shift amount, set is_zero_poison to true. + if (II.hasOneUse() && match(Op1, m_Zero()) && + match(II.user_back(), m_Shift(m_Value(), m_Specific(&II)))) + return IC.replaceOperand(II, 1, IC.Builder.getTrue()); + Constant *C; if (IsTZ) { @@ -1790,7 +1795,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) { // We don't have a "nabs" intrinsic, so negate if needed based on the // max/min operation. if (IID == Intrinsic::smin || IID == Intrinsic::umax) - Abs = Builder.CreateNeg(Abs, "nabs", /* NUW */ false, IntMinIsPoison); + Abs = Builder.CreateNeg(Abs, "nabs", IntMinIsPoison); return replaceInstUsesWith(CI, Abs); } @@ -2088,8 +2093,9 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) { Value *Arg0 = II->getArgOperand(0); Value *Arg1 = II->getArgOperand(1); bool IsSigned = IID == Intrinsic::sadd_with_overflow; - bool HasNWAdd = IsSigned ? match(Arg0, m_NSWAdd(m_Value(X), m_APInt(C0))) - : match(Arg0, m_NUWAdd(m_Value(X), m_APInt(C0))); + bool HasNWAdd = IsSigned + ? match(Arg0, m_NSWAddLike(m_Value(X), m_APInt(C0))) + : match(Arg0, m_NUWAddLike(m_Value(X), m_APInt(C0))); if (HasNWAdd && match(Arg1, m_APInt(C1))) { bool Overflow; APInt NewC = @@ -2284,13 +2290,14 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) { default: llvm_unreachable("unexpected intrinsic ID"); } - Instruction *NewCall = Builder.CreateBinaryIntrinsic( + Value *V = Builder.CreateBinaryIntrinsic( IID, X, ConstantFP::get(Arg0->getType(), Res), II); // TODO: Conservatively intersecting FMF. If Res == C2, the transform // was a simplification (so Arg0 and its original flags could // propagate?) - NewCall->andIRFlags(M); - return replaceInstUsesWith(*II, NewCall); + if (auto *CI = dyn_cast<CallInst>(V)) + CI->andIRFlags(M); + return replaceInstUsesWith(*II, V); } } @@ -2467,6 +2474,16 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) { if (match(Sign, m_Intrinsic<Intrinsic::copysign>(m_Value(), m_Value(X)))) return replaceOperand(*II, 1, X); + // Clear sign-bit of constant magnitude: + // copysign -MagC, X --> copysign MagC, X + // TODO: Support constant folding for fabs + const APFloat *MagC; + if (match(Mag, m_APFloat(MagC)) && MagC->isNegative()) { + APFloat PosMagC = *MagC; + PosMagC.clearSign(); + return replaceOperand(*II, 0, ConstantFP::get(Mag->getType(), PosMagC)); + } + // Peek through changes of magnitude's sign-bit. This call rewrites those: // copysign (fabs X), Sign --> copysign X, Sign // copysign (fneg X), Sign --> copysign X, Sign @@ -2827,14 +2844,6 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) { })) return nullptr; break; - case Intrinsic::experimental_hot: { - // The intrinsic declaration includes sideeffects to avoid it moved. This - // prevents removing even if the intrinsic is unused. We should remove - // unused ones to enabled other optimizations. - if (CI.use_empty()) - return eraseInstFromFunction(CI); - break; - } case Intrinsic::assume: { Value *IIOperand = II->getArgOperand(0); SmallVector<OperandBundleDef, 4> OpBundles; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp index 45afa6363ae01f3e09fa03333b7bdf9838b4599e..0652a8ba80b3fe027766d05cee5750ee816576e9 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -734,19 +734,18 @@ Instruction *InstCombinerImpl::visitTrunc(TruncInst &Trunc) { if (DestWidth == 1) { Value *Zero = Constant::getNullValue(SrcTy); - if (DestTy->isIntegerTy()) { - // Canonicalize trunc x to i1 -> icmp ne (and x, 1), 0 (scalar only). - // TODO: We canonicalize to more instructions here because we are probably - // lacking equivalent analysis for trunc relative to icmp. There may also - // be codegen concerns. If those trunc limitations were removed, we could - // remove this transform. - Value *And = Builder.CreateAnd(Src, ConstantInt::get(SrcTy, 1)); - return new ICmpInst(ICmpInst::ICMP_NE, And, Zero); - } - // For vectors, we do not canonicalize all truncs to icmp, so optimize - // patterns that would be covered within visitICmpInst. Value *X; + const APInt *C1; + Constant *C2; + if (match(Src, m_OneUse(m_Shr(m_Shl(m_Power2(C1), m_Value(X)), + m_ImmConstant(C2))))) { + // trunc ((C1 << X) >> C2) to i1 --> X == (C2-cttz(C1)), where C1 is pow2 + Constant *Log2C1 = ConstantInt::get(SrcTy, C1->exactLogBase2()); + Constant *CmpC = ConstantExpr::getSub(C2, Log2C1); + return new ICmpInst(ICmpInst::ICMP_EQ, X, CmpC); + } + Constant *C; if (match(Src, m_OneUse(m_LShr(m_Value(X), m_Constant(C))))) { // trunc (lshr X, C) to i1 --> icmp ne (and X, C'), 0 @@ -763,6 +762,14 @@ Instruction *InstCombinerImpl::visitTrunc(TruncInst &Trunc) { Value *And = Builder.CreateAnd(X, Builder.CreateOr(MaskC, One)); return new ICmpInst(ICmpInst::ICMP_NE, And, Zero); } + + { + const APInt *C; + if (match(Src, m_Shl(m_APInt(C), m_Value(X))) && (*C)[0] == 1) { + // trunc (C << X) to i1 --> X == 0, where C is odd + return new ICmpInst(ICmpInst::Predicate::ICMP_EQ, X, Zero); + } + } } Value *A, *B; @@ -1121,6 +1128,10 @@ Instruction *InstCombinerImpl::visitZExt(ZExtInst &Zext) { Value *Src = Zext.getOperand(0); Type *SrcTy = Src->getType(), *DestTy = Zext.getType(); + // zext nneg bool x -> 0 + if (SrcTy->isIntOrIntVectorTy(1) && Zext.hasNonNeg()) + return replaceInstUsesWith(Zext, Constant::getNullValue(Zext.getType())); + // Try to extend the entire expression tree to the wide destination type. unsigned BitsToClear; if (shouldChangeType(SrcTy, DestTy) && @@ -1919,10 +1930,26 @@ Instruction *InstCombinerImpl::foldItoFPtoI(CastInst &FI) { return replaceInstUsesWith(FI, X); } +static Instruction *foldFPtoI(Instruction &FI, InstCombiner &IC) { + // fpto{u/s}i non-norm --> 0 + FPClassTest Mask = + FI.getOpcode() == Instruction::FPToUI ? fcPosNormal : fcNormal; + KnownFPClass FPClass = + computeKnownFPClass(FI.getOperand(0), Mask, /*Depth=*/0, + IC.getSimplifyQuery().getWithInstruction(&FI)); + if (FPClass.isKnownNever(Mask)) + return IC.replaceInstUsesWith(FI, ConstantInt::getNullValue(FI.getType())); + + return nullptr; +} + Instruction *InstCombinerImpl::visitFPToUI(FPToUIInst &FI) { if (Instruction *I = foldItoFPtoI(FI)) return I; + if (Instruction *I = foldFPtoI(FI, *this)) + return I; + return commonCastTransforms(FI); } @@ -1930,6 +1957,9 @@ Instruction *InstCombinerImpl::visitFPToSI(FPToSIInst &FI) { if (Instruction *I = foldItoFPtoI(FI)) return I; + if (Instruction *I = foldFPtoI(FI, *this)) + return I; + return commonCastTransforms(FI); } diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 0dce0077bf15883cf553c9add5f75d36c40c75ae..db302d7e5268447e73ea7a62eaf000fe88536919 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -4177,7 +4177,9 @@ static bool isMaskOrZero(const Value *V, bool Not, const SimplifyQuery &Q, /// a check for a lossy truncation. /// Folds: /// icmp SrcPred (x & Mask), x to icmp DstPred x, Mask +/// icmp SrcPred (x & ~Mask), ~Mask to icmp DstPred x, ~Mask /// icmp eq/ne (x & ~Mask), 0 to icmp DstPred x, Mask +/// icmp eq/ne (~x | Mask), -1 to icmp DstPred x, Mask /// Where Mask is some pattern that produces all-ones in low bits: /// (-1 >> y) /// ((-1 << y) >> y) <- non-canonical, has extra uses @@ -4189,82 +4191,126 @@ static bool isMaskOrZero(const Value *V, bool Not, const SimplifyQuery &Q, static Value *foldICmpWithLowBitMaskedVal(ICmpInst::Predicate Pred, Value *Op0, Value *Op1, const SimplifyQuery &Q, InstCombiner &IC) { - Value *X, *M; - bool NeedsNot = false; - - auto CheckMask = [&](Value *V, bool Not) { - if (ICmpInst::isSigned(Pred) && !match(V, m_ImmConstant())) - return false; - return isMaskOrZero(V, Not, Q); - }; - - if (match(Op0, m_c_And(m_Specific(Op1), m_Value(M))) && - CheckMask(M, /*Not*/ false)) { - X = Op1; - } else if (match(Op1, m_Zero()) && ICmpInst::isEquality(Pred) && - match(Op0, m_OneUse(m_And(m_Value(X), m_Value(M))))) { - NeedsNot = true; - if (IC.isFreeToInvert(X, X->hasOneUse()) && CheckMask(X, /*Not*/ true)) - std::swap(X, M); - else if (!IC.isFreeToInvert(M, M->hasOneUse()) || - !CheckMask(M, /*Not*/ true)) - return nullptr; - } else { - return nullptr; - } ICmpInst::Predicate DstPred; switch (Pred) { case ICmpInst::Predicate::ICMP_EQ: - // x & (-1 >> y) == x -> x u<= (-1 >> y) + // x & Mask == x + // x & ~Mask == 0 + // ~x | Mask == -1 + // -> x u<= Mask + // x & ~Mask == ~Mask + // -> ~Mask u<= x DstPred = ICmpInst::Predicate::ICMP_ULE; break; case ICmpInst::Predicate::ICMP_NE: - // x & (-1 >> y) != x -> x u> (-1 >> y) + // x & Mask != x + // x & ~Mask != 0 + // ~x | Mask != -1 + // -> x u> Mask + // x & ~Mask != ~Mask + // -> ~Mask u> x DstPred = ICmpInst::Predicate::ICMP_UGT; break; case ICmpInst::Predicate::ICMP_ULT: - // x & (-1 >> y) u< x -> x u> (-1 >> y) - // x u> x & (-1 >> y) -> x u> (-1 >> y) + // x & Mask u< x + // -> x u> Mask + // x & ~Mask u< ~Mask + // -> ~Mask u> x DstPred = ICmpInst::Predicate::ICMP_UGT; break; case ICmpInst::Predicate::ICMP_UGE: - // x & (-1 >> y) u>= x -> x u<= (-1 >> y) - // x u<= x & (-1 >> y) -> x u<= (-1 >> y) + // x & Mask u>= x + // -> x u<= Mask + // x & ~Mask u>= ~Mask + // -> ~Mask u<= x DstPred = ICmpInst::Predicate::ICMP_ULE; break; case ICmpInst::Predicate::ICMP_SLT: - // x & (-1 >> y) s< x -> x s> (-1 >> y) - // x s> x & (-1 >> y) -> x s> (-1 >> y) - if (!match(M, m_Constant())) // Can not do this fold with non-constant. - return nullptr; - if (!match(M, m_NonNegative())) // Must not have any -1 vector elements. - return nullptr; + // x & Mask s< x [iff Mask s>= 0] + // -> x s> Mask + // x & ~Mask s< ~Mask [iff ~Mask != 0] + // -> ~Mask s> x DstPred = ICmpInst::Predicate::ICMP_SGT; break; case ICmpInst::Predicate::ICMP_SGE: - // x & (-1 >> y) s>= x -> x s<= (-1 >> y) - // x s<= x & (-1 >> y) -> x s<= (-1 >> y) - if (!match(M, m_Constant())) // Can not do this fold with non-constant. - return nullptr; - if (!match(M, m_NonNegative())) // Must not have any -1 vector elements. - return nullptr; + // x & Mask s>= x [iff Mask s>= 0] + // -> x s<= Mask + // x & ~Mask s>= ~Mask [iff ~Mask != 0] + // -> ~Mask s<= x DstPred = ICmpInst::Predicate::ICMP_SLE; break; - case ICmpInst::Predicate::ICMP_SGT: - case ICmpInst::Predicate::ICMP_SLE: - return nullptr; - case ICmpInst::Predicate::ICMP_UGT: - case ICmpInst::Predicate::ICMP_ULE: - llvm_unreachable("Instsimplify took care of commut. variant"); - break; default: - llvm_unreachable("All possible folds are handled."); + // We don't support sgt,sle + // ult/ugt are simplified to true/false respectively. + return nullptr; } - // The mask value may be a vector constant that has undefined elements. But it - // may not be safe to propagate those undefs into the new compare, so replace - // those elements by copying an existing, defined, and safe scalar constant. + Value *X, *M; + // Put search code in lambda for early positive returns. + auto IsLowBitMask = [&]() { + if (match(Op0, m_c_And(m_Specific(Op1), m_Value(M)))) { + X = Op1; + // Look for: x & Mask pred x + if (isMaskOrZero(M, /*Not=*/false, Q)) { + return !ICmpInst::isSigned(Pred) || + (match(M, m_NonNegative()) || isKnownNonNegative(M, Q)); + } + + // Look for: x & ~Mask pred ~Mask + if (isMaskOrZero(X, /*Not=*/true, Q)) { + return !ICmpInst::isSigned(Pred) || + isKnownNonZero(X, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT); + } + return false; + } + if (ICmpInst::isEquality(Pred) && match(Op1, m_AllOnes()) && + match(Op0, m_OneUse(m_Or(m_Value(X), m_Value(M))))) { + + auto Check = [&]() { + // Look for: ~x | Mask == -1 + if (isMaskOrZero(M, /*Not=*/false, Q)) { + if (Value *NotX = + IC.getFreelyInverted(X, X->hasOneUse(), &IC.Builder)) { + X = NotX; + return true; + } + } + return false; + }; + if (Check()) + return true; + std::swap(X, M); + return Check(); + } + if (ICmpInst::isEquality(Pred) && match(Op1, m_Zero()) && + match(Op0, m_OneUse(m_And(m_Value(X), m_Value(M))))) { + auto Check = [&]() { + // Look for: x & ~Mask == 0 + if (isMaskOrZero(M, /*Not=*/true, Q)) { + if (Value *NotM = + IC.getFreelyInverted(M, M->hasOneUse(), &IC.Builder)) { + M = NotM; + return true; + } + } + return false; + }; + if (Check()) + return true; + std::swap(X, M); + return Check(); + } + return false; + }; + + if (!IsLowBitMask()) + return nullptr; + + // The mask value may be a vector constant that has undefined elements. But + // it may not be safe to propagate those undefs into the new compare, so + // replace those elements by copying an existing, defined, and safe scalar + // constant. Type *OpTy = M->getType(); auto *VecC = dyn_cast<Constant>(M); auto *OpVTy = dyn_cast<FixedVectorType>(OpTy); @@ -4280,8 +4326,6 @@ static Value *foldICmpWithLowBitMaskedVal(ICmpInst::Predicate Pred, Value *Op0, M = Constant::replaceUndefsWith(VecC, SafeReplacementConstant); } - if (NeedsNot) - M = IC.Builder.CreateNot(M); return IC.Builder.CreateICmp(DstPred, X, M); } diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h index 6a1ef6edeb4077ab1b82e6105716ebb90bcd3de4..b9ad3a740079296de16b42b1c71b1de9c18843a6 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -98,6 +98,7 @@ public: Instruction *visitSub(BinaryOperator &I); Instruction *visitFSub(BinaryOperator &I); Instruction *visitMul(BinaryOperator &I); + Instruction *foldPowiReassoc(BinaryOperator &I); Instruction *foldFMulReassoc(BinaryOperator &I); Instruction *visitFMul(BinaryOperator &I); Instruction *visitURem(BinaryOperator &I); @@ -757,10 +758,9 @@ public: void tryToSinkInstructionDbgValues( Instruction *I, BasicBlock::iterator InsertPos, BasicBlock *SrcBlock, BasicBlock *DestBlock, SmallVectorImpl<DbgVariableIntrinsic *> &DbgUsers); - void tryToSinkInstructionDPValues(Instruction *I, - BasicBlock::iterator InsertPos, - BasicBlock *SrcBlock, BasicBlock *DestBlock, - SmallVectorImpl<DPValue *> &DPUsers); + void tryToSinkInstructionDbgVariableRecords( + Instruction *I, BasicBlock::iterator InsertPos, BasicBlock *SrcBlock, + BasicBlock *DestBlock, SmallVectorImpl<DbgVariableRecord *> &DPUsers); bool removeInstructionsBeforeUnreachable(Instruction &I); void addDeadEdge(BasicBlock *From, BasicBlock *To, diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 278be6233f4b8a5afc6b6c1202ff97d94ef11d8c..8c698e52b5a0e67156f09f81b330ac4e4c328820 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -105,7 +105,7 @@ static Value *foldMulSelectToNegate(BinaryOperator &I, if (match(&I, m_c_Mul(m_OneUse(m_Select(m_Value(Cond), m_One(), m_AllOnes())), m_Value(OtherOp)))) { bool HasAnyNoWrap = I.hasNoSignedWrap() || I.hasNoUnsignedWrap(); - Value *Neg = Builder.CreateNeg(OtherOp, "", false, HasAnyNoWrap); + Value *Neg = Builder.CreateNeg(OtherOp, "", HasAnyNoWrap); return Builder.CreateSelect(Cond, OtherOp, Neg); } // mul (select Cond, -1, 1), OtherOp --> select Cond, -OtherOp, OtherOp @@ -113,7 +113,7 @@ static Value *foldMulSelectToNegate(BinaryOperator &I, if (match(&I, m_c_Mul(m_OneUse(m_Select(m_Value(Cond), m_AllOnes(), m_One())), m_Value(OtherOp)))) { bool HasAnyNoWrap = I.hasNoSignedWrap() || I.hasNoUnsignedWrap(); - Value *Neg = Builder.CreateNeg(OtherOp, "", false, HasAnyNoWrap); + Value *Neg = Builder.CreateNeg(OtherOp, "", HasAnyNoWrap); return Builder.CreateSelect(Cond, Neg, OtherOp); } @@ -448,6 +448,13 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) { if (match(Op1, m_ZExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1)) return SelectInst::Create(X, Op0, ConstantInt::getNullValue(Ty)); + // mul (sext X), Y -> select X, -Y, 0 + // mul Y, (sext X) -> select X, -Y, 0 + if (match(&I, m_c_Mul(m_OneUse(m_SExt(m_Value(X))), m_Value(Y))) && + X->getType()->isIntOrIntVectorTy(1)) + return SelectInst::Create(X, Builder.CreateNeg(Y, "", I.hasNoSignedWrap()), + ConstantInt::getNullValue(Op0->getType())); + Constant *ImmC; if (match(Op1, m_ImmConstant(ImmC))) { // (sext bool X) * C --> X ? -C : 0 @@ -571,6 +578,54 @@ Instruction *InstCombinerImpl::foldFPSignBitOps(BinaryOperator &I) { return nullptr; } +Instruction *InstCombinerImpl::foldPowiReassoc(BinaryOperator &I) { + auto createPowiExpr = [](BinaryOperator &I, InstCombinerImpl &IC, Value *X, + Value *Y, Value *Z) { + InstCombiner::BuilderTy &Builder = IC.Builder; + Value *YZ = Builder.CreateAdd(Y, Z); + auto *NewPow = Builder.CreateIntrinsic( + Intrinsic::powi, {X->getType(), YZ->getType()}, {X, YZ}, &I); + return IC.replaceInstUsesWith(I, NewPow); + }; + + Value *X, *Y, *Z; + + // powi(X, Y) * X --> powi(X, Y+1) + // X * powi(X, Y) --> powi(X, Y+1) + if (match(&I, m_c_FMul(m_OneUse(m_AllowReassoc(m_Intrinsic<Intrinsic::powi>( + m_Value(X), m_Value(Y)))), + m_Deferred(X)))) { + Constant *One = ConstantInt::get(Y->getType(), 1); + if (willNotOverflowSignedAdd(Y, One, I)) + return createPowiExpr(I, *this, X, Y, One); + } + + // powi(x, y) * powi(x, z) -> powi(x, y + z) + Value *Op0 = I.getOperand(0); + Value *Op1 = I.getOperand(1); + if (I.isOnlyUserOfAnyOperand() && + match(Op0, m_AllowReassoc( + m_Intrinsic<Intrinsic::powi>(m_Value(X), m_Value(Y)))) && + match(Op1, m_AllowReassoc(m_Intrinsic<Intrinsic::powi>(m_Specific(X), + m_Value(Z)))) && + Y->getType() == Z->getType()) + return createPowiExpr(I, *this, X, Y, Z); + + // powi(X, Y) / X --> powi(X, Y-1) + // This is legal when (Y - 1) can't wraparound, in which case reassoc and nnan + // are required. + // TODO: Multi-use may be also better off creating Powi(x,y-1) + if (I.hasAllowReassoc() && I.hasNoNaNs() && + match(Op0, m_OneUse(m_AllowReassoc(m_Intrinsic<Intrinsic::powi>( + m_Specific(Op1), m_Value(Y))))) && + willNotOverflowSignedSub(Y, ConstantInt::get(Y->getType(), 1), I)) { + Constant *NegOne = ConstantInt::getAllOnesValue(Y->getType()); + return createPowiExpr(I, *this, Op1, Y, NegOne); + } + + return nullptr; +} + Instruction *InstCombinerImpl::foldFMulReassoc(BinaryOperator &I) { Value *Op0 = I.getOperand(0); Value *Op1 = I.getOperand(1); @@ -683,6 +738,9 @@ Instruction *InstCombinerImpl::foldFMulReassoc(BinaryOperator &I) { return replaceInstUsesWith(I, Pow); } + if (Instruction *FoldedPowi = foldPowiReassoc(I)) + return FoldedPowi; + if (I.isOnlyUserOfAnyOperand()) { // pow(X, Y) * pow(X, Z) -> pow(X, Y + Z) if (match(Op0, m_Intrinsic<Intrinsic::pow>(m_Value(X), m_Value(Y))) && @@ -699,16 +757,6 @@ Instruction *InstCombinerImpl::foldFMulReassoc(BinaryOperator &I) { return replaceInstUsesWith(I, NewPow); } - // powi(x, y) * powi(x, z) -> powi(x, y + z) - if (match(Op0, m_Intrinsic<Intrinsic::powi>(m_Value(X), m_Value(Y))) && - match(Op1, m_Intrinsic<Intrinsic::powi>(m_Specific(X), m_Value(Z))) && - Y->getType() == Z->getType()) { - auto *YZ = Builder.CreateAdd(Y, Z); - auto *NewPow = Builder.CreateIntrinsic( - Intrinsic::powi, {X->getType(), YZ->getType()}, {X, YZ}, &I); - return replaceInstUsesWith(I, NewPow); - } - // exp(X) * exp(Y) -> exp(X + Y) if (match(Op0, m_Intrinsic<Intrinsic::exp>(m_Value(X))) && match(Op1, m_Intrinsic<Intrinsic::exp>(m_Value(Y)))) { @@ -777,8 +825,19 @@ Instruction *InstCombinerImpl::visitFMul(BinaryOperator &I) { if (match(Op1, m_SpecificFP(-1.0))) return UnaryOperator::CreateFNegFMF(Op0, &I); - // With no-nans: X * 0.0 --> copysign(0.0, X) - if (I.hasNoNaNs() && match(Op1, m_PosZeroFP())) { + // With no-nans/no-infs: + // X * 0.0 --> copysign(0.0, X) + // X * -0.0 --> copysign(0.0, -X) + const APFloat *FPC; + if (match(Op1, m_APFloatAllowUndef(FPC)) && FPC->isZero() && + ((I.hasNoInfs() && + isKnownNeverNaN(Op0, /*Depth=*/0, SQ.getWithInstruction(&I))) || + isKnownNeverNaN(&I, /*Depth=*/0, SQ.getWithInstruction(&I)))) { + if (FPC->isNegative()) + Op0 = Builder.CreateFNegFMF(Op0, &I); + Op1 = Constant::replaceUndefsWith( + cast<Constant>(Op1), + ConstantFP::get(Op1->getType()->getScalarType(), *FPC)); CallInst *CopySign = Builder.CreateIntrinsic(Intrinsic::copysign, {I.getType()}, {Op1, Op0}, &I); return replaceInstUsesWith(I, CopySign); @@ -1123,14 +1182,14 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) { // We need a multiple of the divisor for a signed add constant, but // unsigned is fine with any constant pair. if (IsSigned && - match(Op0, m_NSWAdd(m_NSWMul(m_Value(X), m_SpecificInt(*C2)), - m_APInt(C1))) && + match(Op0, m_NSWAddLike(m_NSWMul(m_Value(X), m_SpecificInt(*C2)), + m_APInt(C1))) && isMultiple(*C1, *C2, Quotient, IsSigned)) { return BinaryOperator::CreateNSWAdd(X, ConstantInt::get(Ty, Quotient)); } if (!IsSigned && - match(Op0, m_NUWAdd(m_NUWMul(m_Value(X), m_SpecificInt(*C2)), - m_APInt(C1)))) { + match(Op0, m_NUWAddLike(m_NUWMul(m_Value(X), m_SpecificInt(*C2)), + m_APInt(C1)))) { return BinaryOperator::CreateNUWAdd(X, ConstantInt::get(Ty, C1->udiv(*C2))); } @@ -1857,20 +1916,8 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) { return replaceInstUsesWith(I, Pow); } - // powi(X, Y) / X --> powi(X, Y-1) - // This is legal when (Y - 1) can't wraparound, in which case reassoc and nnan - // are required. - // TODO: Multi-use may be also better off creating Powi(x,y-1) - if (I.hasAllowReassoc() && I.hasNoNaNs() && - match(Op0, m_OneUse(m_Intrinsic<Intrinsic::powi>(m_Specific(Op1), - m_Value(Y)))) && - willNotOverflowSignedSub(Y, ConstantInt::get(Y->getType(), 1), I)) { - Constant *NegOne = ConstantInt::getAllOnesValue(Y->getType()); - Value *Y1 = Builder.CreateAdd(Y, NegOne); - Type *Types[] = {Op1->getType(), Y1->getType()}; - Value *Pow = Builder.CreateIntrinsic(Intrinsic::powi, Types, {Op1, Y1}, &I); - return replaceInstUsesWith(I, Pow); - } + if (Instruction *FoldedPowi = foldPowiReassoc(I)) + return FoldedPowi; return nullptr; } diff --git a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp index f73679f9461badb3cd76f1abebca2f0476bc9c45..cd8e47e1b39113d79f17a893c7e5b343f87b6897 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp @@ -140,7 +140,7 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) { // Integral constants can be freely negated. if (match(V, m_AnyIntegralConstant())) - return ConstantExpr::getNeg(cast<Constant>(V), /*HasNUW=*/false, + return ConstantExpr::getNeg(cast<Constant>(V), /*HasNSW=*/false); // If we have a non-instruction, then give up. diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index aee18d770f729d1e697f4f3f93e7a3e0a2b0a47f..9ab2bd8f70aa150a00291ecf106f6730e8f4920f 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -536,19 +536,29 @@ Instruction *InstCombinerImpl::foldSelectIntoOp(SelectInst &SI, Value *TrueVal, // between 0, 1 and -1. const APInt *OOpC; bool OOpIsAPInt = match(OOp, m_APInt(OOpC)); - if (!isa<Constant>(OOp) || - (OOpIsAPInt && isSelect01(C->getUniqueInteger(), *OOpC))) { - Value *NewSel = Builder.CreateSelect(SI.getCondition(), Swapped ? C : OOp, - Swapped ? OOp : C, "", &SI); - if (isa<FPMathOperator>(&SI)) - cast<Instruction>(NewSel)->setFastMathFlags(FMF); - NewSel->takeName(TVI); - BinaryOperator *BO = - BinaryOperator::Create(TVI->getOpcode(), FalseVal, NewSel); - BO->copyIRFlags(TVI); - return BO; - } - return nullptr; + if (isa<Constant>(OOp) && + (!OOpIsAPInt || !isSelect01(C->getUniqueInteger(), *OOpC))) + return nullptr; + + // If the false value is a NaN then we have that the floating point math + // operation in the transformed code may not preserve the exact NaN + // bit-pattern -- e.g. `fadd sNaN, 0.0 -> qNaN`. + // This makes the transformation incorrect since the original program would + // have preserved the exact NaN bit-pattern. + // Avoid the folding if the false value might be a NaN. + if (isa<FPMathOperator>(&SI) && + !computeKnownFPClass(FalseVal, FMF, fcNan, &SI).isKnownNeverNaN()) + return nullptr; + + Value *NewSel = Builder.CreateSelect(SI.getCondition(), Swapped ? C : OOp, + Swapped ? OOp : C, "", &SI); + if (isa<FPMathOperator>(&SI)) + cast<Instruction>(NewSel)->setFastMathFlags(FMF); + NewSel->takeName(TVI); + BinaryOperator *BO = + BinaryOperator::Create(TVI->getOpcode(), FalseVal, NewSel); + BO->copyIRFlags(TVI); + return BO; }; if (Instruction *R = TryFoldSelectIntoOp(SI, TrueVal, FalseVal, false)) @@ -1191,7 +1201,7 @@ static Value *canonicalizeSPF(ICmpInst &Cmp, Value *TrueVal, Value *FalseVal, match(RHS, m_NSWNeg(m_Specific(LHS))); Constant *IntMinIsPoisonC = ConstantInt::get(Type::getInt1Ty(Cmp.getContext()), IntMinIsPoison); - Instruction *Abs = + Value *Abs = IC.Builder.CreateBinaryIntrinsic(Intrinsic::abs, LHS, IntMinIsPoisonC); if (SPF == SelectPatternFlavor::SPF_NABS) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp index eafd2889ec50bdfd944810f36dd6babaec8a3245..95aa2119e2d88b0db0cce39b763d50e1e0914144 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp @@ -437,7 +437,7 @@ Instruction *InstCombinerImpl::commonShiftTransforms(BinaryOperator &I) { Value *A; Constant *C, *C1; if (match(Op0, m_Constant(C)) && - match(Op1, m_NUWAdd(m_Value(A), m_Constant(C1)))) { + match(Op1, m_NUWAddLike(m_Value(A), m_Constant(C1)))) { Value *NewC = Builder.CreateBinOp(I.getOpcode(), C, C1); BinaryOperator *NewShiftOp = BinaryOperator::Create(I.getOpcode(), NewC, A); if (I.getOpcode() == Instruction::Shl) { diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp index 3c4c0f35eb6d4898343cb7c697a58a0edbb6d967..99f1f8eb34bb5a658a76f2c6eeabbfafe8108dea 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -487,7 +487,9 @@ Instruction *InstCombinerImpl::visitExtractElementInst(ExtractElementInst &EI) { // extelt (cmp X, Y), Index --> cmp (extelt X, Index), (extelt Y, Index) Value *E0 = Builder.CreateExtractElement(X, Index); Value *E1 = Builder.CreateExtractElement(Y, Index); - return CmpInst::Create(cast<CmpInst>(SrcVec)->getOpcode(), Pred, E0, E1); + CmpInst *SrcCmpInst = cast<CmpInst>(SrcVec); + return CmpInst::CreateWithCopiedFlags(SrcCmpInst->getOpcode(), Pred, E0, E1, + SrcCmpInst); } if (auto *I = dyn_cast<Instruction>(SrcVec)) { @@ -2135,7 +2137,8 @@ static Instruction *foldSelectShuffleOfSelectShuffle(ShuffleVectorInst &Shuf) { return new ShuffleVectorInst(X, Y, NewMask); } -static Instruction *foldSelectShuffleWith1Binop(ShuffleVectorInst &Shuf) { +static Instruction *foldSelectShuffleWith1Binop(ShuffleVectorInst &Shuf, + const SimplifyQuery &SQ) { assert(Shuf.isSelect() && "Must have select-equivalent shuffle"); // Are we shuffling together some value and that same value after it has been @@ -2159,6 +2162,19 @@ static Instruction *foldSelectShuffleWith1Binop(ShuffleVectorInst &Shuf) { if (!IdC) return nullptr; + Value *X = Op0IsBinop ? Op1 : Op0; + + // Prevent folding in the case the non-binop operand might have NaN values. + // If X can have NaN elements then we have that the floating point math + // operation in the transformed code may not preserve the exact NaN + // bit-pattern -- e.g. `fadd sNaN, 0.0 -> qNaN`. + // This makes the transformation incorrect since the original program would + // have preserved the exact NaN bit-pattern. + // Avoid the folding if X can have NaN elements. + if (Shuf.getType()->getElementType()->isFloatingPointTy() && + !isKnownNeverNaN(X, 0, SQ)) + return nullptr; + // Shuffle identity constants into the lanes that return the original value. // Example: shuf (mul X, {-1,-2,-3,-4}), X, {0,5,6,3} --> mul X, {-1,1,1,-4} // Example: shuf X, (add X, {-1,-2,-3,-4}), {0,1,6,7} --> add X, {0,0,-3,-4} @@ -2175,7 +2191,6 @@ static Instruction *foldSelectShuffleWith1Binop(ShuffleVectorInst &Shuf) { // shuf (bop X, C), X, M --> bop X, C' // shuf X, (bop X, C), M --> bop X, C' - Value *X = Op0IsBinop ? Op1 : Op0; Instruction *NewBO = BinaryOperator::Create(BOpcode, X, NewC); NewBO->copyIRFlags(BO); @@ -2241,7 +2256,8 @@ Instruction *InstCombinerImpl::foldSelectShuffle(ShuffleVectorInst &Shuf) { if (Instruction *I = foldSelectShuffleOfSelectShuffle(Shuf)) return I; - if (Instruction *I = foldSelectShuffleWith1Binop(Shuf)) + if (Instruction *I = foldSelectShuffleWith1Binop( + Shuf, getSimplifyQuery().getWithInstruction(&Shuf))) return I; BinaryOperator *B0, *B1; diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 1688005de2104d8b94b951d0ad9ce9b549918609..7c40fb4fc86082dd903939521e87b0242a01f509 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1481,6 +1481,11 @@ Instruction *InstCombinerImpl::foldFBinOpOfIntCastsFromSign( // If we have a constant rhs, see if we can losslessly convert it to an int. if (Op1FpC != nullptr) { + // Signed + Mul req non-zero + if (OpsFromSigned && BO.getOpcode() == Instruction::FMul && + !match(Op1FpC, m_NonZeroFP())) + return nullptr; + Constant *Op1IntC = ConstantFoldCastOperand( OpsFromSigned ? Instruction::FPToSI : Instruction::FPToUI, Op1FpC, IntTy, DL); @@ -1645,6 +1650,7 @@ static Value *foldOperationIntoSelectOperand(Instruction &I, SelectInst *SI, Value *NewOp, InstCombiner &IC) { Instruction *Clone = I.clone(); Clone->replaceUsesOfWith(SI, NewOp); + Clone->dropUBImplyingAttrsAndMetadata(); IC.InsertNewInstBefore(Clone, SI->getIterator()); return Clone; } @@ -2596,6 +2602,45 @@ Value *InstCombiner::getFreelyInvertedImpl(Value *V, bool WillInvertAllUses, return nullptr; } + // De Morgan's Laws: + // (~(A | B)) -> (~A & ~B) + // (~(A & B)) -> (~A | ~B) + auto TryInvertAndOrUsingDeMorgan = [&](Instruction::BinaryOps Opcode, + bool IsLogical, Value *A, + Value *B) -> Value * { + bool LocalDoesConsume = DoesConsume; + if (!getFreelyInvertedImpl(B, B->hasOneUse(), /*Builder=*/nullptr, + LocalDoesConsume, Depth)) + return nullptr; + if (auto *NotA = getFreelyInvertedImpl(A, A->hasOneUse(), Builder, + LocalDoesConsume, Depth)) { + auto *NotB = getFreelyInvertedImpl(B, B->hasOneUse(), Builder, + LocalDoesConsume, Depth); + DoesConsume = LocalDoesConsume; + if (IsLogical) + return Builder ? Builder->CreateLogicalOp(Opcode, NotA, NotB) : NonNull; + return Builder ? Builder->CreateBinOp(Opcode, NotA, NotB) : NonNull; + } + + return nullptr; + }; + + if (match(V, m_Or(m_Value(A), m_Value(B)))) + return TryInvertAndOrUsingDeMorgan(Instruction::And, /*IsLogical=*/false, A, + B); + + if (match(V, m_And(m_Value(A), m_Value(B)))) + return TryInvertAndOrUsingDeMorgan(Instruction::Or, /*IsLogical=*/false, A, + B); + + if (match(V, m_LogicalOr(m_Value(A), m_Value(B)))) + return TryInvertAndOrUsingDeMorgan(Instruction::And, /*IsLogical=*/true, A, + B); + + if (match(V, m_LogicalAnd(m_Value(A), m_Value(B)))) + return TryInvertAndOrUsingDeMorgan(Instruction::Or, /*IsLogical=*/true, A, + B); + return nullptr; } @@ -3075,10 +3120,10 @@ Instruction *InstCombinerImpl::visitAllocSite(Instruction &MI) { // If we are removing an alloca with a dbg.declare, insert dbg.value calls // before each store. SmallVector<DbgVariableIntrinsic *, 8> DVIs; - SmallVector<DPValue *, 8> DPVs; + SmallVector<DbgVariableRecord *, 8> DVRs; std::unique_ptr<DIBuilder> DIB; if (isa<AllocaInst>(MI)) { - findDbgUsers(DVIs, &MI, &DPVs); + findDbgUsers(DVIs, &MI, &DVRs); DIB.reset(new DIBuilder(*MI.getModule(), /*AllowUnresolved=*/false)); } @@ -3118,9 +3163,9 @@ Instruction *InstCombinerImpl::visitAllocSite(Instruction &MI) { for (auto *DVI : DVIs) if (DVI->isAddressOfVariable()) ConvertDebugDeclareToDebugValue(DVI, SI, *DIB); - for (auto *DPV : DPVs) - if (DPV->isAddressOfVariable()) - ConvertDebugDeclareToDebugValue(DPV, SI, *DIB); + for (auto *DVR : DVRs) + if (DVR->isAddressOfVariable()) + ConvertDebugDeclareToDebugValue(DVR, SI, *DIB); } else { // Casts, GEP, or anything else: we're about to delete this instruction, // so it can not have any valid uses. @@ -3165,9 +3210,9 @@ Instruction *InstCombinerImpl::visitAllocSite(Instruction &MI) { for (auto *DVI : DVIs) if (DVI->isAddressOfVariable() || DVI->getExpression()->startsWithDeref()) DVI->eraseFromParent(); - for (auto *DPV : DPVs) - if (DPV->isAddressOfVariable() || DPV->getExpression()->startsWithDeref()) - DPV->eraseFromParent(); + for (auto *DVR : DVRs) + if (DVR->isAddressOfVariable() || DVR->getExpression()->startsWithDeref()) + DVR->eraseFromParent(); return eraseInstFromFunction(MI); } @@ -3834,6 +3879,12 @@ Instruction *InstCombinerImpl::visitExtractValueInst(ExtractValueInst &EV) { if (Instruction *Res = foldOpIntoPhi(EV, PN)) return Res; + // Canonicalize extract (select Cond, TV, FV) + // -> select cond, (extract TV), (extract FV) + if (auto *SI = dyn_cast<SelectInst>(Agg)) + if (Instruction *R = FoldOpIntoSelect(EV, SI, /*FoldWithMultiUse=*/true)) + return R; + // We could simplify extracts from other values. Note that nested extracts may // already be simplified implicitly by the above: extract (extract (insert) ) // will be translated into extract ( insert ( extract ) ) first and then just @@ -4562,12 +4613,13 @@ bool InstCombinerImpl::tryToSinkInstruction(Instruction *I, // mark the location undef: we know it was supposed to receive a new location // here, but that computation has been sunk. SmallVector<DbgVariableIntrinsic *, 2> DbgUsers; - SmallVector<DPValue *, 2> DPValues; - findDbgUsers(DbgUsers, I, &DPValues); + SmallVector<DbgVariableRecord *, 2> DbgVariableRecords; + findDbgUsers(DbgUsers, I, &DbgVariableRecords); if (!DbgUsers.empty()) tryToSinkInstructionDbgValues(I, InsertPos, SrcBlock, DestBlock, DbgUsers); - if (!DPValues.empty()) - tryToSinkInstructionDPValues(I, InsertPos, SrcBlock, DestBlock, DPValues); + if (!DbgVariableRecords.empty()) + tryToSinkInstructionDbgVariableRecords(I, InsertPos, SrcBlock, DestBlock, + DbgVariableRecords); // PS: there are numerous flaws with this behaviour, not least that right now // assignments can be re-ordered past other assignments to the same variable @@ -4640,47 +4692,48 @@ void InstCombinerImpl::tryToSinkInstructionDbgValues( } } -void InstCombinerImpl::tryToSinkInstructionDPValues( +void InstCombinerImpl::tryToSinkInstructionDbgVariableRecords( Instruction *I, BasicBlock::iterator InsertPos, BasicBlock *SrcBlock, - BasicBlock *DestBlock, SmallVectorImpl<DPValue *> &DPValues) { - // Implementation of tryToSinkInstructionDbgValues, but for the DPValue of - // variable assignments rather than dbg.values. - - // Fetch all DPValues not already in the destination. - SmallVector<DPValue *, 2> DPValuesToSalvage; - for (auto &DPV : DPValues) - if (DPV->getParent() != DestBlock) - DPValuesToSalvage.push_back(DPV); - - // Fetch a second collection, of DPValues in the source block that we're going - // to sink. - SmallVector<DPValue *> DPValuesToSink; - for (DPValue *DPV : DPValuesToSalvage) - if (DPV->getParent() == SrcBlock) - DPValuesToSink.push_back(DPV); - - // Sort DPValues according to their position in the block. This is a partial - // order: DPValues attached to different instructions will be ordered by the - // instruction order, but DPValues attached to the same instruction won't - // have an order. - auto Order = [](DPValue *A, DPValue *B) -> bool { + BasicBlock *DestBlock, + SmallVectorImpl<DbgVariableRecord *> &DbgVariableRecords) { + // Implementation of tryToSinkInstructionDbgValues, but for the + // DbgVariableRecord of variable assignments rather than dbg.values. + + // Fetch all DbgVariableRecords not already in the destination. + SmallVector<DbgVariableRecord *, 2> DbgVariableRecordsToSalvage; + for (auto &DVR : DbgVariableRecords) + if (DVR->getParent() != DestBlock) + DbgVariableRecordsToSalvage.push_back(DVR); + + // Fetch a second collection, of DbgVariableRecords in the source block that + // we're going to sink. + SmallVector<DbgVariableRecord *> DbgVariableRecordsToSink; + for (DbgVariableRecord *DVR : DbgVariableRecordsToSalvage) + if (DVR->getParent() == SrcBlock) + DbgVariableRecordsToSink.push_back(DVR); + + // Sort DbgVariableRecords according to their position in the block. This is a + // partial order: DbgVariableRecords attached to different instructions will + // be ordered by the instruction order, but DbgVariableRecords attached to the + // same instruction won't have an order. + auto Order = [](DbgVariableRecord *A, DbgVariableRecord *B) -> bool { return B->getInstruction()->comesBefore(A->getInstruction()); }; - llvm::stable_sort(DPValuesToSink, Order); + llvm::stable_sort(DbgVariableRecordsToSink, Order); // If there are two assignments to the same variable attached to the same // instruction, the ordering between the two assignments is important. Scan // for this (rare) case and establish which is the last assignment. using InstVarPair = std::pair<const Instruction *, DebugVariable>; - SmallDenseMap<InstVarPair, DPValue *> FilterOutMap; - if (DPValuesToSink.size() > 1) { + SmallDenseMap<InstVarPair, DbgVariableRecord *> FilterOutMap; + if (DbgVariableRecordsToSink.size() > 1) { SmallDenseMap<InstVarPair, unsigned> CountMap; // Count how many assignments to each variable there is per instruction. - for (DPValue *DPV : DPValuesToSink) { + for (DbgVariableRecord *DVR : DbgVariableRecordsToSink) { DebugVariable DbgUserVariable = - DebugVariable(DPV->getVariable(), DPV->getExpression(), - DPV->getDebugLoc()->getInlinedAt()); - CountMap[std::make_pair(DPV->getInstruction(), DbgUserVariable)] += 1; + DebugVariable(DVR->getVariable(), DVR->getExpression(), + DVR->getDebugLoc()->getInlinedAt()); + CountMap[std::make_pair(DVR->getInstruction(), DbgUserVariable)] += 1; } // If there are any instructions with two assignments, add them to the @@ -4696,74 +4749,74 @@ void InstCombinerImpl::tryToSinkInstructionDPValues( // For all instruction/variable pairs needing extra filtering, find the // latest assignment. for (const Instruction *Inst : DupSet) { - for (DPValue &DPV : - llvm::reverse(DPValue::filter(Inst->getDbgRecordRange()))) { + for (DbgVariableRecord &DVR : + llvm::reverse(filterDbgVars(Inst->getDbgRecordRange()))) { DebugVariable DbgUserVariable = - DebugVariable(DPV.getVariable(), DPV.getExpression(), - DPV.getDebugLoc()->getInlinedAt()); + DebugVariable(DVR.getVariable(), DVR.getExpression(), + DVR.getDebugLoc()->getInlinedAt()); auto FilterIt = FilterOutMap.find(std::make_pair(Inst, DbgUserVariable)); if (FilterIt == FilterOutMap.end()) continue; if (FilterIt->second != nullptr) continue; - FilterIt->second = &DPV; + FilterIt->second = &DVR; } } } - // Perform cloning of the DPValues that we plan on sinking, filter out any - // duplicate assignments identified above. - SmallVector<DPValue *, 2> DPVClones; + // Perform cloning of the DbgVariableRecords that we plan on sinking, filter + // out any duplicate assignments identified above. + SmallVector<DbgVariableRecord *, 2> DVRClones; SmallSet<DebugVariable, 4> SunkVariables; - for (DPValue *DPV : DPValuesToSink) { - if (DPV->Type == DPValue::LocationType::Declare) + for (DbgVariableRecord *DVR : DbgVariableRecordsToSink) { + if (DVR->Type == DbgVariableRecord::LocationType::Declare) continue; DebugVariable DbgUserVariable = - DebugVariable(DPV->getVariable(), DPV->getExpression(), - DPV->getDebugLoc()->getInlinedAt()); + DebugVariable(DVR->getVariable(), DVR->getExpression(), + DVR->getDebugLoc()->getInlinedAt()); // For any variable where there were multiple assignments in the same place, // ignore all but the last assignment. if (!FilterOutMap.empty()) { - InstVarPair IVP = std::make_pair(DPV->getInstruction(), DbgUserVariable); + InstVarPair IVP = std::make_pair(DVR->getInstruction(), DbgUserVariable); auto It = FilterOutMap.find(IVP); // Filter out. - if (It != FilterOutMap.end() && It->second != DPV) + if (It != FilterOutMap.end() && It->second != DVR) continue; } if (!SunkVariables.insert(DbgUserVariable).second) continue; - if (DPV->isDbgAssign()) + if (DVR->isDbgAssign()) continue; - DPVClones.emplace_back(DPV->clone()); - LLVM_DEBUG(dbgs() << "CLONE: " << *DPVClones.back() << '\n'); + DVRClones.emplace_back(DVR->clone()); + LLVM_DEBUG(dbgs() << "CLONE: " << *DVRClones.back() << '\n'); } // Perform salvaging without the clones, then sink the clones. - if (DPVClones.empty()) + if (DVRClones.empty()) return; - salvageDebugInfoForDbgValues(*I, {}, DPValuesToSalvage); + salvageDebugInfoForDbgValues(*I, {}, DbgVariableRecordsToSalvage); // The clones are in reverse order of original appearance. Assert that the // head bit is set on the iterator as we _should_ have received it via // getFirstInsertionPt. Inserting like this will reverse the clone order as // we'll repeatedly insert at the head, such as: - // DPV-3 (third insertion goes here) - // DPV-2 (second insertion goes here) - // DPV-1 (first insertion goes here) - // Any-Prior-DPVs + // DVR-3 (third insertion goes here) + // DVR-2 (second insertion goes here) + // DVR-1 (first insertion goes here) + // Any-Prior-DVRs // InsertPtInst assert(InsertPos.getHeadBit()); - for (DPValue *DPVClone : DPVClones) { - InsertPos->getParent()->insertDbgRecordBefore(DPVClone, InsertPos); - LLVM_DEBUG(dbgs() << "SINK: " << *DPVClone << '\n'); + for (DbgVariableRecord *DVRClone : DVRClones) { + InsertPos->getParent()->insertDbgRecordBefore(DVRClone, InsertPos); + LLVM_DEBUG(dbgs() << "SINK: " << *DVRClone << '\n'); } } @@ -5202,7 +5255,8 @@ static bool combineInstructionsOverFunction( if (Iteration > Opts.MaxIterations) { report_fatal_error( "Instruction Combining did not reach a fixpoint after " + - Twine(Opts.MaxIterations) + " iterations"); + Twine(Opts.MaxIterations) + " iterations", + /*GenCrashDiag=*/false); } } diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp index 11a5c29c35f7012ef8eae546708f0b6dd9a9ae14..d0d349c891a37b353a42feeb344a5233fbc01dab 100644 --- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp @@ -260,6 +260,10 @@ static cl::opt<bool> ClUsePageAliases("hwasan-experimental-use-page-aliases", namespace { +template <typename T> T optOr(cl::opt<T> &Opt, T Other) { + return Opt.getNumOccurrences() ? Opt : Other; +} + bool shouldUsePageAliases(const Triple &TargetTriple) { return ClUsePageAliases && TargetTriple.getArch() == Triple::x86_64; } @@ -269,14 +273,11 @@ bool shouldInstrumentStack(const Triple &TargetTriple) { } bool shouldInstrumentWithCalls(const Triple &TargetTriple) { - return ClInstrumentWithCalls.getNumOccurrences() - ? ClInstrumentWithCalls - : TargetTriple.getArch() == Triple::x86_64; + return optOr(ClInstrumentWithCalls, TargetTriple.getArch() == Triple::x86_64); } bool mightUseStackSafetyAnalysis(bool DisableOptimization) { - return ClUseStackSafety.getNumOccurrences() ? ClUseStackSafety - : !DisableOptimization; + return optOr(ClUseStackSafety, !DisableOptimization); } bool shouldUseStackSafetyAnalysis(const Triple &TargetTriple, @@ -296,10 +297,8 @@ public: HWAddressSanitizer(Module &M, bool CompileKernel, bool Recover, const StackSafetyGlobalInfo *SSI) : M(M), SSI(SSI) { - this->Recover = ClRecover.getNumOccurrences() > 0 ? ClRecover : Recover; - this->CompileKernel = ClEnableKhwasan.getNumOccurrences() > 0 - ? ClEnableKhwasan - : CompileKernel; + this->Recover = optOr(ClRecover, Recover); + this->CompileKernel = optOr(ClEnableKhwasan, CompileKernel); this->Rng = ClRandomSkipRate.getNumOccurrences() ? M.createRNG("hwasan") : nullptr; @@ -358,14 +357,13 @@ private: bool instrumentStack(memtag::StackInfo &Info, Value *StackTag, Value *UARTag, const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI); - Value *readRegister(IRBuilder<> &IRB, StringRef Name); bool instrumentLandingPads(SmallVectorImpl<Instruction *> &RetVec); Value *getNextTagWithCall(IRBuilder<> &IRB); Value *getStackBaseTag(IRBuilder<> &IRB); Value *getAllocaTag(IRBuilder<> &IRB, Value *StackTag, unsigned AllocaNo); Value *getUARTag(IRBuilder<> &IRB); - Value *getHwasanThreadSlotPtr(IRBuilder<> &IRB, Type *Ty); + Value *getHwasanThreadSlotPtr(IRBuilder<> &IRB); Value *applyTagMask(IRBuilder<> &IRB, Value *OldTag); unsigned retagMask(unsigned AllocaNo); @@ -374,8 +372,7 @@ private: void instrumentGlobal(GlobalVariable *GV, uint8_t Tag); void instrumentGlobals(); - Value *getPC(IRBuilder<> &IRB); - Value *getFP(IRBuilder<> &IRB); + Value *getCachedFP(IRBuilder<> &IRB); Value *getFrameRecordInfo(IRBuilder<> &IRB); void instrumentPersonalityFunctions(); @@ -411,8 +408,8 @@ private: ShadowMapping Mapping; Type *VoidTy = Type::getVoidTy(M.getContext()); - Type *IntptrTy; - PointerType *PtrTy; + Type *IntptrTy = M.getDataLayout().getIntPtrType(M.getContext()); + PointerType *PtrTy = PointerType::getUnqual(M.getContext()); Type *Int8Ty = Type::getInt8Ty(M.getContext()); Type *Int32Ty = Type::getInt32Ty(M.getContext()); Type *Int64Ty = Type::getInt64Ty(M.getContext()); @@ -425,6 +422,7 @@ private: bool InstrumentLandingPads; bool InstrumentWithCalls; bool InstrumentStack; + bool InstrumentGlobals; bool DetectUseAfterScope; bool UsePageAliases; bool UseMatchAllCallback; @@ -450,7 +448,7 @@ private: Value *ShadowBase = nullptr; Value *StackBaseTag = nullptr; - Value *CachedSP = nullptr; + Value *CachedFP = nullptr; GlobalValue *ThreadPtrGlobal = nullptr; }; @@ -595,8 +593,6 @@ void HWAddressSanitizer::createHwasanCtorComdat() { /// inserts a call to __hwasan_init to the module's constructor list. void HWAddressSanitizer::initializeModule() { LLVM_DEBUG(dbgs() << "Init " << M.getName() << "\n"); - auto &DL = M.getDataLayout(); - TargetTriple = Triple(M.getTargetTriple()); // x86_64 currently has two modes: @@ -614,8 +610,6 @@ void HWAddressSanitizer::initializeModule() { C = &(M.getContext()); IRBuilder<> IRB(*C); - IntptrTy = IRB.getIntPtrTy(DL); - PtrTy = IRB.getPtrTy(); HwasanCtorFunction = nullptr; @@ -625,19 +619,14 @@ void HWAddressSanitizer::initializeModule() { bool NewRuntime = !TargetTriple.isAndroid() || !TargetTriple.isAndroidVersionLT(30); - UseShortGranules = - ClUseShortGranules.getNumOccurrences() ? ClUseShortGranules : NewRuntime; - OutlinedChecks = - (TargetTriple.isAArch64() || TargetTriple.isRISCV64()) && - TargetTriple.isOSBinFormatELF() && - (ClInlineAllChecks.getNumOccurrences() ? !ClInlineAllChecks : !Recover); + UseShortGranules = optOr(ClUseShortGranules, NewRuntime); + OutlinedChecks = (TargetTriple.isAArch64() || TargetTriple.isRISCV64()) && + TargetTriple.isOSBinFormatELF() && + !optOr(ClInlineAllChecks, Recover); - InlineFastPath = - (ClInlineFastPathChecks.getNumOccurrences() - ? ClInlineFastPathChecks - : !(TargetTriple.isAndroid() || - TargetTriple.isOSFuchsia())); // These platforms may prefer less - // inlining to reduce binary size. + // These platforms may prefer less inlining to reduce binary size. + InlineFastPath = optOr(ClInlineFastPathChecks, !(TargetTriple.isAndroid() || + TargetTriple.isOSFuchsia())); if (ClMatchAllTag.getNumOccurrences()) { if (ClMatchAllTag != -1) { @@ -649,22 +638,19 @@ void HWAddressSanitizer::initializeModule() { UseMatchAllCallback = !CompileKernel && MatchAllTag.has_value(); // If we don't have personality function support, fall back to landing pads. - InstrumentLandingPads = ClInstrumentLandingPads.getNumOccurrences() - ? ClInstrumentLandingPads - : !NewRuntime; + InstrumentLandingPads = optOr(ClInstrumentLandingPads, !NewRuntime); + + InstrumentGlobals = + !CompileKernel && !UsePageAliases && optOr(ClGlobals, NewRuntime); if (!CompileKernel) { createHwasanCtorComdat(); - bool InstrumentGlobals = - ClGlobals.getNumOccurrences() ? ClGlobals : NewRuntime; - if (InstrumentGlobals && !UsePageAliases) + if (InstrumentGlobals) instrumentGlobals(); bool InstrumentPersonalityFunctions = - ClInstrumentPersonalityFunctions.getNumOccurrences() - ? ClInstrumentPersonalityFunctions - : NewRuntime; + optOr(ClInstrumentPersonalityFunctions, NewRuntime); if (InstrumentPersonalityFunctions) instrumentPersonalityFunctions(); } @@ -804,6 +790,13 @@ bool HWAddressSanitizer::ignoreAccess(Instruction *Inst, Value *Ptr) { if (SSI && SSI->stackAccessIsSafe(*Inst)) return true; } + + if (isa<GlobalVariable>(getUnderlyingObject(Ptr))) { + if (!InstrumentGlobals) + return true; + // TODO: Optimize inbound global accesses, like Asan `instrumentMop`. + } + return false; } @@ -1174,10 +1167,10 @@ Value *HWAddressSanitizer::getStackBaseTag(IRBuilder<> &IRB) { // Extract some entropy from the stack pointer for the tags. // Take bits 20..28 (ASLR entropy) and xor with bits 0..8 (these differ // between functions). - Value *StackPointerLong = getFP(IRB); + Value *FramePointerLong = getCachedFP(IRB); Value *StackTag = - applyTagMask(IRB, IRB.CreateXor(StackPointerLong, - IRB.CreateLShr(StackPointerLong, 20))); + applyTagMask(IRB, IRB.CreateXor(FramePointerLong, + IRB.CreateLShr(FramePointerLong, 20))); StackTag->setName("hwasan.stack.base.tag"); return StackTag; } @@ -1191,9 +1184,9 @@ Value *HWAddressSanitizer::getAllocaTag(IRBuilder<> &IRB, Value *StackTag, } Value *HWAddressSanitizer::getUARTag(IRBuilder<> &IRB) { - Value *StackPointerLong = getFP(IRB); + Value *FramePointerLong = getCachedFP(IRB); Value *UARTag = - applyTagMask(IRB, IRB.CreateLShr(StackPointerLong, PointerTagShift)); + applyTagMask(IRB, IRB.CreateLShr(FramePointerLong, PointerTagShift)); UARTag->setName("hwasan.uar.tag"); return UARTag; @@ -1236,57 +1229,34 @@ Value *HWAddressSanitizer::untagPointer(IRBuilder<> &IRB, Value *PtrLong) { return UntaggedPtrLong; } -Value *HWAddressSanitizer::getHwasanThreadSlotPtr(IRBuilder<> &IRB, Type *Ty) { - Module *M = IRB.GetInsertBlock()->getParent()->getParent(); - if (TargetTriple.isAArch64() && TargetTriple.isAndroid()) { - // Android provides a fixed TLS slot for sanitizers. See TLS_SLOT_SANITIZER - // in Bionic's libc/private/bionic_tls.h. - Function *ThreadPointerFunc = - Intrinsic::getDeclaration(M, Intrinsic::thread_pointer); - return IRB.CreateConstGEP1_32(Int8Ty, IRB.CreateCall(ThreadPointerFunc), - 0x30); - } - if (ThreadPtrGlobal) - return ThreadPtrGlobal; - - return nullptr; -} - -Value *HWAddressSanitizer::getPC(IRBuilder<> &IRB) { - if (TargetTriple.getArch() == Triple::aarch64) - return readRegister(IRB, "pc"); - return IRB.CreatePtrToInt(IRB.GetInsertBlock()->getParent(), IntptrTy); +Value *HWAddressSanitizer::getHwasanThreadSlotPtr(IRBuilder<> &IRB) { + // Android provides a fixed TLS slot for sanitizers. See TLS_SLOT_SANITIZER + // in Bionic's libc/platform/bionic/tls_defines.h. + constexpr int SanitizerSlot = 6; + if (TargetTriple.isAArch64() && TargetTriple.isAndroid()) + return memtag::getAndroidSlotPtr(IRB, SanitizerSlot); + return ThreadPtrGlobal; } -Value *HWAddressSanitizer::getFP(IRBuilder<> &IRB) { - if (!CachedSP) { - // FIXME: use addressofreturnaddress (but implement it in aarch64 backend - // first). - Function *F = IRB.GetInsertBlock()->getParent(); - Module *M = F->getParent(); - auto *GetStackPointerFn = Intrinsic::getDeclaration( - M, Intrinsic::frameaddress, - IRB.getPtrTy(M->getDataLayout().getAllocaAddrSpace())); - CachedSP = IRB.CreatePtrToInt( - IRB.CreateCall(GetStackPointerFn, {Constant::getNullValue(Int32Ty)}), - IntptrTy); - } - return CachedSP; +Value *HWAddressSanitizer::getCachedFP(IRBuilder<> &IRB) { + if (!CachedFP) + CachedFP = memtag::getFP(IRB); + return CachedFP; } Value *HWAddressSanitizer::getFrameRecordInfo(IRBuilder<> &IRB) { // Prepare ring buffer data. - Value *PC = getPC(IRB); - Value *SP = getFP(IRB); + Value *PC = memtag::getPC(TargetTriple, IRB); + Value *FP = getCachedFP(IRB); - // Mix SP and PC. + // Mix FP and PC. // Assumptions: // PC is 0x0000PPPPPPPPPPPP (48 bits are meaningful, others are zero) - // SP is 0xsssssssssssSSSS0 (4 lower bits are zero) - // We only really need ~20 lower non-zero bits (SSSS), so we mix like this: - // 0xSSSSPPPPPPPPPPPP - SP = IRB.CreateShl(SP, 44); - return IRB.CreateOr(PC, SP); + // FP is 0xfffffffffffFFFF0 (4 lower bits are zero) + // We only really need ~20 lower non-zero bits (FFFF), so we mix like this: + // 0xFFFFPPPPPPPPPPPP + FP = IRB.CreateShl(FP, 44); + return IRB.CreateOr(PC, FP); } void HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord) { @@ -1304,7 +1274,7 @@ void HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord) { auto getThreadLongMaybeUntagged = [&]() { if (!SlotPtr) - SlotPtr = getHwasanThreadSlotPtr(IRB, IntptrTy); + SlotPtr = getHwasanThreadSlotPtr(IRB); if (!ThreadLong) ThreadLong = IRB.CreateLoad(IntptrTy, SlotPtr); // Extract the address field from ThreadLong. Unnecessary on AArch64 with @@ -1340,6 +1310,22 @@ void HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord) { // The use of AShr instead of LShr is due to // https://bugs.llvm.org/show_bug.cgi?id=39030 // Runtime library makes sure not to use the highest bit. + // + // Mechanical proof of this address calculation can be found at: + // https://github.com/google/sanitizers/blob/master/hwaddress-sanitizer/prove_hwasanwrap.smt2 + // + // Example of the wrap case for N = 1 + // Pointer: 0x01AAAAAAAAAAAFF8 + // + + // 0x0000000000000008 + // = + // 0x01AAAAAAAAAAB000 + // & + // WrapMask: 0xFFFFFFFFFFFFF000 + // = + // 0x01AAAAAAAAAAA000 + // + // Then the WrapMask will be a no-op until the next wrap case. Value *WrapMask = IRB.CreateXor( IRB.CreateShl(IRB.CreateAShr(ThreadLong, 56), 12, "", true, true), ConstantInt::get(IntptrTy, (uint64_t)-1)); @@ -1371,38 +1357,24 @@ void HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord) { } } -Value *HWAddressSanitizer::readRegister(IRBuilder<> &IRB, StringRef Name) { - Module *M = IRB.GetInsertBlock()->getParent()->getParent(); - Function *ReadRegister = - Intrinsic::getDeclaration(M, Intrinsic::read_register, IntptrTy); - MDNode *MD = MDNode::get(*C, {MDString::get(*C, Name)}); - Value *Args[] = {MetadataAsValue::get(*C, MD)}; - return IRB.CreateCall(ReadRegister, Args); -} - bool HWAddressSanitizer::instrumentLandingPads( SmallVectorImpl<Instruction *> &LandingPadVec) { for (auto *LP : LandingPadVec) { IRBuilder<> IRB(LP->getNextNonDebugInstruction()); IRB.CreateCall( HwasanHandleVfork, - {readRegister(IRB, (TargetTriple.getArch() == Triple::x86_64) ? "rsp" - : "sp")}); + {memtag::readRegister( + IRB, (TargetTriple.getArch() == Triple::x86_64) ? "rsp" : "sp")}); } return true; } -static bool isLifetimeIntrinsic(Value *V) { - auto *II = dyn_cast<IntrinsicInst>(V); - return II && II->isLifetimeStartOrEnd(); -} - static DbgAssignIntrinsic *DynCastToDbgAssign(DbgVariableIntrinsic *DVI) { return dyn_cast<DbgAssignIntrinsic>(DVI); } -static DPValue *DynCastToDbgAssign(DPValue *DPV) { - return DPV->isDbgAssign() ? DPV : nullptr; +static DbgVariableRecord *DynCastToDbgAssign(DbgVariableRecord *DVR) { + return DVR->isDbgAssign() ? DVR : nullptr; } bool HWAddressSanitizer::instrumentStack(memtag::StackInfo &SInfo, @@ -1456,11 +1428,13 @@ bool HWAddressSanitizer::instrumentStack(memtag::StackInfo &SInfo, AI->replaceUsesWithIf(Replacement, [AICast, AILong](const Use &U) { auto *User = U.getUser(); - return User != AILong && User != AICast && !isLifetimeIntrinsic(User); + return User != AILong && User != AICast && + !memtag::isLifetimeIntrinsic(User); }); // Helper utility for adding DW_OP_LLVM_tag_offset to debug-info records, - // abstracted over whether they're intrinsic-stored or DPValue stored. + // abstracted over whether they're intrinsic-stored or DbgVariableRecord + // stored. auto AnnotateDbgRecord = [&](auto *DPtr) { // Prepend "tag_offset, N" to the dwarf expression. // Tag offset logically applies to the alloca pointer, and it makes sense @@ -1655,7 +1629,7 @@ void HWAddressSanitizer::sanitizeFunction(Function &F, ShadowBase = nullptr; StackBaseTag = nullptr; - CachedSP = nullptr; + CachedFP = nullptr; } void HWAddressSanitizer::instrumentGlobal(GlobalVariable *GV, uint8_t Tag) { diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp index c42c53edd511901ba46bf9ab93cbff69106c78d8..f9b58d9f278214c6bc1d52d50ea6410077a64f8d 100644 --- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -64,6 +64,9 @@ using namespace llvm; #define DEBUG_TYPE "instrprof" namespace llvm { +// Command line option to enable vtable value profiling. Defined in +// ProfileData/InstrProf.cpp: -enable-vtable-value-profiling= +extern cl::opt<bool> EnableVTableValueProfiling; // TODO: Remove -debug-info-correlate in next LLVM release, in favor of // -profile-correlate=debug-info. cl::opt<bool> DebugInfoCorrelate( @@ -219,12 +222,18 @@ private: PerFunctionProfileData() = default; }; DenseMap<GlobalVariable *, PerFunctionProfileData> ProfileDataMap; + // Key is virtual table variable, value is 'VTableProfData' in the form of + // GlobalVariable. + DenseMap<GlobalVariable *, GlobalVariable *> VTableDataMap; /// If runtime relocation is enabled, this maps functions to the load /// instruction that produces the profile relocation bias. DenseMap<const Function *, LoadInst *> FunctionToProfileBiasMap; std::vector<GlobalValue *> CompilerUsedVars; std::vector<GlobalValue *> UsedVars; std::vector<GlobalVariable *> ReferencedNames; + // The list of virtual table variables of which the VTableProfData is + // collected. + std::vector<GlobalVariable *> ReferencedVTables; GlobalVariable *NamesVar = nullptr; size_t NamesSize = 0; @@ -308,7 +317,7 @@ private: GlobalValue::LinkageTypes Linkage); /// Set Comdat property of GV, if required. - void maybeSetComdat(GlobalVariable *GV, Function *Fn, StringRef VarName); + void maybeSetComdat(GlobalVariable *GV, GlobalObject *GO, StringRef VarName); /// Setup the sections into which counters and bitmaps are allocated. GlobalVariable *setupProfileSection(InstrProfInstBase *Inc, @@ -317,9 +326,15 @@ private: /// Create INSTR_PROF_DATA variable for counters and bitmaps. void createDataVariable(InstrProfCntrInstBase *Inc); + /// Get the counters for virtual table values, creating them if necessary. + void getOrCreateVTableProfData(GlobalVariable *GV); + /// Emit the section with compressed function names. void emitNameData(); + /// Emit the section with compressed vtable names. + void emitVTableNames(); + /// Emit value nodes section for value profiling. void emitVNodes(); @@ -763,6 +778,12 @@ bool InstrLowerer::lower() { } } + if (EnableVTableValueProfiling) + for (GlobalVariable &GV : M.globals()) + // Global variables with type metadata are virtual table variables. + if (GV.hasMetadata(LLVMContext::MD_type)) + getOrCreateVTableProfData(&GV); + for (Function &F : M) MadeChange |= lowerIntrinsics(&F); @@ -776,6 +797,7 @@ bool InstrLowerer::lower() { emitVNodes(); emitNameData(); + emitVTableNames(); // Emit runtime hook for the cases where the target does not unconditionally // require pulling in profile runtime, and coverage is enabled on code that is @@ -1193,13 +1215,13 @@ static bool needsRuntimeRegistrationOfSectionRange(const Triple &TT) { return true; } -void InstrLowerer::maybeSetComdat(GlobalVariable *GV, Function *Fn, +void InstrLowerer::maybeSetComdat(GlobalVariable *GV, GlobalObject *GO, StringRef CounterGroupName) { // Place lowered global variables in a comdat group if the associated function - // is a COMDAT. This will make sure that only one copy of global variable - // (e.g. function counters) of the COMDAT function will be emitted after - // linking. - bool NeedComdat = needsComdatForCounter(*Fn, M); + // or global variable is a COMDAT. This will make sure that only one copy of + // global variable (e.g. function counters) of the COMDAT function will be + // emitted after linking. + bool NeedComdat = needsComdatForCounter(*GO, M); bool UseComdat = (NeedComdat || TT.isOSBinFormatELF()); if (!UseComdat) @@ -1237,6 +1259,104 @@ void InstrLowerer::maybeSetComdat(GlobalVariable *GV, Function *Fn, GV->setLinkage(GlobalValue::InternalLinkage); } +static inline bool shouldRecordVTableAddr(GlobalVariable *GV) { + if (!profDataReferencedByCode(*GV->getParent())) + return false; + + if (!GV->hasLinkOnceLinkage() && !GV->hasLocalLinkage() && + !GV->hasAvailableExternallyLinkage()) + return true; + + // This avoids the profile data from referencing internal symbols in + // COMDAT. + if (GV->hasLocalLinkage() && GV->hasComdat()) + return false; + + return true; +} + +// FIXME: Introduce an internal alias like what's done for functions to reduce +// the number of relocation entries. +static inline Constant *getVTableAddrForProfData(GlobalVariable *GV) { + auto *Int8PtrTy = PointerType::getUnqual(GV->getContext()); + + // Store a nullptr in __profvt_ if a real address shouldn't be used. + if (!shouldRecordVTableAddr(GV)) + return ConstantPointerNull::get(Int8PtrTy); + + return ConstantExpr::getBitCast(GV, Int8PtrTy); +} + +void InstrLowerer::getOrCreateVTableProfData(GlobalVariable *GV) { + assert(!DebugInfoCorrelate && + "Value profiling is not supported with lightweight instrumentation"); + if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) + return; + + // Skip llvm internal global variable or __prof variables. + if (GV->getName().starts_with("llvm.") || + GV->getName().starts_with("__llvm") || + GV->getName().starts_with("__prof")) + return; + + // VTableProfData already created + auto It = VTableDataMap.find(GV); + if (It != VTableDataMap.end() && It->second) + return; + + GlobalValue::LinkageTypes Linkage = GV->getLinkage(); + GlobalValue::VisibilityTypes Visibility = GV->getVisibility(); + + // This is to keep consistent with per-function profile data + // for correctness. + if (TT.isOSBinFormatXCOFF()) { + Linkage = GlobalValue::InternalLinkage; + Visibility = GlobalValue::DefaultVisibility; + } + + LLVMContext &Ctx = M.getContext(); + Type *DataTypes[] = { +#define INSTR_PROF_VTABLE_DATA(Type, LLVMType, Name, Init) LLVMType, +#include "llvm/ProfileData/InstrProfData.inc" +#undef INSTR_PROF_VTABLE_DATA + }; + + auto *DataTy = StructType::get(Ctx, ArrayRef(DataTypes)); + + // Used by INSTR_PROF_VTABLE_DATA MACRO + Constant *VTableAddr = getVTableAddrForProfData(GV); + const std::string PGOVTableName = getPGOName(*GV); + // Record the length of the vtable. This is needed since vtable pointers + // loaded from C++ objects might be from the middle of a vtable definition. + uint32_t VTableSizeVal = + M.getDataLayout().getTypeAllocSize(GV->getValueType()); + + Constant *DataVals[] = { +#define INSTR_PROF_VTABLE_DATA(Type, LLVMType, Name, Init) Init, +#include "llvm/ProfileData/InstrProfData.inc" +#undef INSTR_PROF_VTABLE_DATA + }; + + auto *Data = + new GlobalVariable(M, DataTy, /*constant=*/false, Linkage, + ConstantStruct::get(DataTy, DataVals), + getInstrProfVTableVarPrefix() + PGOVTableName); + + Data->setVisibility(Visibility); + Data->setSection(getInstrProfSectionName(IPSK_vtab, TT.getObjectFormat())); + Data->setAlignment(Align(8)); + + maybeSetComdat(Data, GV, Data->getName()); + + VTableDataMap[GV] = Data; + + ReferencedVTables.push_back(GV); + + // VTable <Hash, Addr> is used by runtime but not referenced by other + // sections. Conservatively mark it linker retained. + UsedVars.push_back(Data); +} + GlobalVariable *InstrLowerer::setupProfileSection(InstrProfInstBase *Inc, InstrProfSectKind IPSK) { GlobalVariable *NamePtr = Inc->getName(); @@ -1633,6 +1753,31 @@ void InstrLowerer::emitNameData() { NamePtr->eraseFromParent(); } +void InstrLowerer::emitVTableNames() { + if (!EnableVTableValueProfiling || ReferencedVTables.empty()) + return; + + // Collect the PGO names of referenced vtables and compress them. + std::string CompressedVTableNames; + if (Error E = collectVTableStrings(ReferencedVTables, CompressedVTableNames, + DoInstrProfNameCompression)) { + report_fatal_error(Twine(toString(std::move(E))), false); + } + + auto &Ctx = M.getContext(); + auto *VTableNamesVal = ConstantDataArray::getString( + Ctx, StringRef(CompressedVTableNames), false /* AddNull */); + GlobalVariable *VTableNamesVar = + new GlobalVariable(M, VTableNamesVal->getType(), true /* constant */, + GlobalValue::PrivateLinkage, VTableNamesVal, + getInstrProfVTableNamesVarName()); + VTableNamesVar->setSection( + getInstrProfSectionName(IPSK_vname, TT.getObjectFormat())); + VTableNamesVar->setAlignment(Align(1)); + // Make VTableNames linker retained. + UsedVars.push_back(VTableNamesVar); +} + void InstrLowerer::emitRegistration() { if (!needsRuntimeRegistrationOfSectionRange(TT)) return; diff --git a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp index 55728709cde556768f3a66a3d48eb70b17b1e2c9..98c6f8cbf5afefadcd6cc5648bffb06e0c9776c1 100644 --- a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp +++ b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp @@ -327,6 +327,9 @@ extern cl::opt<PGOViewCountsType> PGOViewCounts; // Defined in Analysis/BlockFrequencyInfo.cpp: -view-bfi-func-name= extern cl::opt<std::string> ViewBlockFreqFuncName; +// Command line option to enable vtable value profiling. Defined in +// ProfileData/InstrProf.cpp: -enable-vtable-value-profiling= +extern cl::opt<bool> EnableVTableValueProfiling; extern cl::opt<InstrProfCorrelator::ProfCorrelatorKind> ProfileCorrelate; } // namespace llvm @@ -581,6 +584,8 @@ public: NumOfPGOMemIntrinsics += ValueSites[IPVK_MemOPSize].size(); NumOfPGOBB += MST.bbInfoSize(); ValueSites[IPVK_IndirectCallTarget] = VPC.get(IPVK_IndirectCallTarget); + if (EnableVTableValueProfiling) + ValueSites[IPVK_VTableTarget] = VPC.get(IPVK_VTableTarget); } else { NumOfCSPGOSelectInsts += SIVisitor.getNumOfSelectInsts(); NumOfCSPGOMemIntrinsics += ValueSites[IPVK_MemOPSize].size(); @@ -920,7 +925,7 @@ static void instrumentOneFunc( // on the instrumentation call based on the funclet coloring. DenseMap<BasicBlock *, ColorVector> BlockColors; if (F.hasPersonalityFn() && - isFuncletEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) + isScopedEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) BlockColors = colorEHFunclets(F); // For each VP Kind, walk the VP candidates and instrument each one. @@ -1775,6 +1780,15 @@ static bool InstrumentAllFunctions( // (before LTO/ThinLTO linking) to create these variables. if (!IsCS) createIRLevelProfileFlagVar(M, /*IsCS=*/false); + + Triple TT(M.getTargetTriple()); + LLVMContext &Ctx = M.getContext(); + if (!TT.isOSBinFormatELF() && EnableVTableValueProfiling) + Ctx.diagnose(DiagnosticInfoPGOProfile( + M.getName().data(), + Twine("VTable value profiling is presently not " + "supported for non-ELF object formats"), + DS_Warning)); std::unordered_multimap<Comdat *, GlobalValue *> ComdatMembers; collectComdatMembers(M, ComdatMembers); diff --git a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp index 8ee0bca7e354f0654a1ae7171d17b6bfeb815415..956ebe8fc8b9a30ff88ff7aeeebf8e2d4bcbc4bc 100644 --- a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp @@ -43,7 +43,6 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Instrumentation.h" -#include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/EscapeEnumerator.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/ModuleUtils.h" @@ -738,8 +737,8 @@ bool ThreadSanitizer::instrumentAtomic(Instruction *I, const DataLayout &DL) { Value *Args[] = {Addr, IRB.CreateBitOrPointerCast(SI->getValueOperand(), Ty), createOrdering(&IRB, SI->getOrdering())}; - CallInst *C = CallInst::Create(TsanAtomicStore[Idx], Args); - ReplaceInstWithInst(I, C); + IRB.CreateCall(TsanAtomicStore[Idx], Args); + SI->eraseFromParent(); } else if (AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(I)) { Value *Addr = RMWI->getPointerOperand(); int Idx = @@ -752,11 +751,12 @@ bool ThreadSanitizer::instrumentAtomic(Instruction *I, const DataLayout &DL) { const unsigned ByteSize = 1U << Idx; const unsigned BitSize = ByteSize * 8; Type *Ty = Type::getIntNTy(IRB.getContext(), BitSize); - Value *Args[] = {Addr, - IRB.CreateIntCast(RMWI->getValOperand(), Ty, false), + Value *Val = RMWI->getValOperand(); + Value *Args[] = {Addr, IRB.CreateBitOrPointerCast(Val, Ty), createOrdering(&IRB, RMWI->getOrdering())}; - CallInst *C = CallInst::Create(F, Args); - ReplaceInstWithInst(I, C); + Value *C = IRB.CreateCall(F, Args); + I->replaceAllUsesWith(IRB.CreateBitOrPointerCast(C, Val->getType())); + I->eraseFromParent(); } else if (AtomicCmpXchgInst *CASI = dyn_cast<AtomicCmpXchgInst>(I)) { Value *Addr = CASI->getPointerOperand(); Type *OrigOldValTy = CASI->getNewValOperand()->getType(); @@ -794,8 +794,8 @@ bool ThreadSanitizer::instrumentAtomic(Instruction *I, const DataLayout &DL) { FunctionCallee F = FI->getSyncScopeID() == SyncScope::SingleThread ? TsanAtomicSignalFence : TsanAtomicThreadFence; - CallInst *C = CallInst::Create(F, Args); - ReplaceInstWithInst(I, C); + IRB.CreateCall(F, Args); + FI->eraseFromParent(); } return true; } diff --git a/llvm/lib/Transforms/Instrumentation/ValueProfilePlugins.inc b/llvm/lib/Transforms/Instrumentation/ValueProfilePlugins.inc index 3a129de1acd02d6ba0540d63780e86581fbbcd6b..b47ef8523ea1123a1674229904733e165e2d55be 100644 --- a/llvm/lib/Transforms/Instrumentation/ValueProfilePlugins.inc +++ b/llvm/lib/Transforms/Instrumentation/ValueProfilePlugins.inc @@ -90,9 +90,38 @@ public: } }; +///--------------------- VirtualTableValueProfilingPlugin -------------------- +class VTableProfilingPlugin { + Function &F; + +public: + static constexpr InstrProfValueKind Kind = IPVK_VTableTarget; + + VTableProfilingPlugin(Function &Fn, TargetLibraryInfo &TLI) : F(Fn) {} + + void run(std::vector<CandidateInfo> &Candidates) { + std::vector<Instruction *> Result = findVTableAddrs(F); + for (Instruction *I : Result) { + Instruction *InsertPt = I->getNextNonDebugInstruction(); + // When finding an insertion point, keep PHI and EH pad instructions + // before vp intrinsics. This is similar to + // `BasicBlock::getFirstInsertionPt`. + while (InsertPt && (dyn_cast<PHINode>(InsertPt) || InsertPt->isEHPad())) + InsertPt = InsertPt->getNextNonDebugInstruction(); + // Skip instrumentating the value if InsertPt is the last instruction. + // FIXME: Set InsertPt to the end of basic block to instrument the value + // if InsertPt is the last instruction. + if (InsertPt == nullptr) + continue; + + Instruction *AnnotatedInst = I; + Candidates.emplace_back(CandidateInfo{I, InsertPt, AnnotatedInst}); + } + } +}; + ///----------------------- Registration of the plugins ------------------------- /// For now, registering a plugin with the ValueProfileCollector is done by /// adding the plugin type to the VP_PLUGIN_LIST macro. -#define VP_PLUGIN_LIST \ - MemIntrinsicPlugin, \ - IndirectCallPromotionPlugin +#define VP_PLUGIN_LIST \ + MemIntrinsicPlugin, IndirectCallPromotionPlugin, VTableProfilingPlugin diff --git a/llvm/lib/Transforms/Scalar/ADCE.cpp b/llvm/lib/Transforms/Scalar/ADCE.cpp index 4d901310efe52028e997b5801e3b77a773a36f34..96ecd7f368a000584b58529f4ca32f697a1ef2d0 100644 --- a/llvm/lib/Transforms/Scalar/ADCE.cpp +++ b/llvm/lib/Transforms/Scalar/ADCE.cpp @@ -544,15 +544,16 @@ ADCEChanged AggressiveDeadCodeElimination::removeDeadInstructions() { // value of the function, and may therefore be deleted safely. // NOTE: We reuse the Worklist vector here for memory efficiency. for (Instruction &I : llvm::reverse(instructions(F))) { - // With "RemoveDIs" debug-info stored in DPValue objects, debug-info - // attached to this instruction, and drop any for scopes that aren't alive, - // like the rest of this loop does. Extending support to assignment tracking - // is future work. + // With "RemoveDIs" debug-info stored in DbgVariableRecord objects, + // debug-info attached to this instruction, and drop any for scopes that + // aren't alive, like the rest of this loop does. Extending support to + // assignment tracking is future work. for (DbgRecord &DR : make_early_inc_range(I.getDbgRecordRange())) { - // Avoid removing a DPV that is linked to instructions because it holds + // Avoid removing a DVR that is linked to instructions because it holds // information about an existing store. - if (DPValue *DPV = dyn_cast<DPValue>(&DR); DPV && DPV->isDbgAssign()) - if (!at::getAssignmentInsts(DPV).empty()) + if (DbgVariableRecord *DVR = dyn_cast<DbgVariableRecord>(&DR); + DVR && DVR->isDbgAssign()) + if (!at::getAssignmentInsts(DVR).empty()) continue; if (AliveScopes.count(DR.getDebugLoc()->getScope())) continue; diff --git a/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp b/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp index 49f8761a13923267727f92637a2321557a6585c9..68774cf31ce9b31c62a6fd5d4149e7cca9ed947d 100644 --- a/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp +++ b/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp @@ -162,27 +162,27 @@ bool ConstantHoistingLegacyPass::runOnFunction(Function &Fn) { void ConstantHoistingPass::collectMatInsertPts( const RebasedConstantListType &RebasedConstants, - SmallVectorImpl<Instruction *> &MatInsertPts) const { + SmallVectorImpl<BasicBlock::iterator> &MatInsertPts) const { for (const RebasedConstantInfo &RCI : RebasedConstants) for (const ConstantUser &U : RCI.Uses) MatInsertPts.emplace_back(findMatInsertPt(U.Inst, U.OpndIdx)); } /// Find the constant materialization insertion point. -Instruction *ConstantHoistingPass::findMatInsertPt(Instruction *Inst, - unsigned Idx) const { +BasicBlock::iterator ConstantHoistingPass::findMatInsertPt(Instruction *Inst, + unsigned Idx) const { // If the operand is a cast instruction, then we have to materialize the // constant before the cast instruction. if (Idx != ~0U) { Value *Opnd = Inst->getOperand(Idx); if (auto CastInst = dyn_cast<Instruction>(Opnd)) if (CastInst->isCast()) - return CastInst; + return CastInst->getIterator(); } // The simple and common case. This also includes constant expressions. if (!isa<PHINode>(Inst) && !Inst->isEHPad()) - return Inst; + return Inst->getIterator(); // We can't insert directly before a phi node or an eh pad. Insert before // the terminator of the incoming or dominating block. @@ -191,7 +191,7 @@ Instruction *ConstantHoistingPass::findMatInsertPt(Instruction *Inst, if (Idx != ~0U && isa<PHINode>(Inst)) { InsertionBlock = cast<PHINode>(Inst)->getIncomingBlock(Idx); if (!InsertionBlock->isEHPad()) { - return InsertionBlock->getTerminator(); + return InsertionBlock->getTerminator()->getIterator(); } } else { InsertionBlock = Inst->getParent(); @@ -206,7 +206,7 @@ Instruction *ConstantHoistingPass::findMatInsertPt(Instruction *Inst, IDom = IDom->getIDom(); } - return IDom->getBlock()->getTerminator(); + return IDom->getBlock()->getTerminator()->getIterator(); } /// Given \p BBs as input, find another set of BBs which collectively @@ -314,26 +314,27 @@ static void findBestInsertionSet(DominatorTree &DT, BlockFrequencyInfo &BFI, } /// Find an insertion point that dominates all uses. -SetVector<Instruction *> ConstantHoistingPass::findConstantInsertionPoint( +SetVector<BasicBlock::iterator> +ConstantHoistingPass::findConstantInsertionPoint( const ConstantInfo &ConstInfo, - const ArrayRef<Instruction *> MatInsertPts) const { + const ArrayRef<BasicBlock::iterator> MatInsertPts) const { assert(!ConstInfo.RebasedConstants.empty() && "Invalid constant info entry."); // Collect all basic blocks. SetVector<BasicBlock *> BBs; - SetVector<Instruction *> InsertPts; + SetVector<BasicBlock::iterator> InsertPts; - for (Instruction *MatInsertPt : MatInsertPts) + for (BasicBlock::iterator MatInsertPt : MatInsertPts) BBs.insert(MatInsertPt->getParent()); if (BBs.count(Entry)) { - InsertPts.insert(&Entry->front()); + InsertPts.insert(Entry->begin()); return InsertPts; } if (BFI) { findBestInsertionSet(*DT, *BFI, Entry, BBs); for (BasicBlock *BB : BBs) - InsertPts.insert(&*BB->getFirstInsertionPt()); + InsertPts.insert(BB->getFirstInsertionPt()); return InsertPts; } @@ -343,7 +344,7 @@ SetVector<Instruction *> ConstantHoistingPass::findConstantInsertionPoint( BB2 = BBs.pop_back_val(); BB = DT->findNearestCommonDominator(BB1, BB2); if (BB == Entry) { - InsertPts.insert(&Entry->front()); + InsertPts.insert(Entry->begin()); return InsertPts; } BBs.insert(BB); @@ -363,6 +364,9 @@ SetVector<Instruction *> ConstantHoistingPass::findConstantInsertionPoint( void ConstantHoistingPass::collectConstantCandidates( ConstCandMapType &ConstCandMap, Instruction *Inst, unsigned Idx, ConstantInt *ConstInt) { + if (ConstInt->getType()->isVectorTy()) + return; + InstructionCost Cost; // Ask the target about the cost of materializing the constant for the given // instruction and operand index. @@ -761,11 +765,13 @@ void ConstantHoistingPass::emitBaseConstants(Instruction *Base, Mat = GetElementPtrInst::Create(Type::getInt8Ty(*Ctx), Base, Adj->Offset, "mat_gep", Adj->MatInsertPt); // Hide it behind a bitcast. - Mat = new BitCastInst(Mat, Adj->Ty, "mat_bitcast", Adj->MatInsertPt); + Mat = new BitCastInst(Mat, Adj->Ty, "mat_bitcast", + Adj->MatInsertPt->getIterator()); } else // Constant being rebased is a ConstantInt. - Mat = BinaryOperator::Create(Instruction::Add, Base, Adj->Offset, - "const_mat", Adj->MatInsertPt); + Mat = + BinaryOperator::Create(Instruction::Add, Base, Adj->Offset, + "const_mat", Adj->MatInsertPt->getIterator()); LLVM_DEBUG(dbgs() << "Materialize constant (" << *Base->getOperand(0) << " + " << *Adj->Offset << ") in BB " @@ -816,7 +822,8 @@ void ConstantHoistingPass::emitBaseConstants(Instruction *Base, // Aside from constant GEPs, only constant cast expressions are collected. assert(ConstExpr->isCast() && "ConstExpr should be a cast"); - Instruction *ConstExprInst = ConstExpr->getAsInstruction(Adj->MatInsertPt); + Instruction *ConstExprInst = ConstExpr->getAsInstruction(); + ConstExprInst->insertBefore(Adj->MatInsertPt); ConstExprInst->setOperand(0, Mat); // Use the same debug location as the instruction we are about to update. @@ -842,9 +849,9 @@ bool ConstantHoistingPass::emitBaseConstants(GlobalVariable *BaseGV) { SmallVectorImpl<consthoist::ConstantInfo> &ConstInfoVec = BaseGV ? ConstGEPInfoMap[BaseGV] : ConstIntInfoVec; for (const consthoist::ConstantInfo &ConstInfo : ConstInfoVec) { - SmallVector<Instruction *, 4> MatInsertPts; + SmallVector<BasicBlock::iterator, 4> MatInsertPts; collectMatInsertPts(ConstInfo.RebasedConstants, MatInsertPts); - SetVector<Instruction *> IPSet = + SetVector<BasicBlock::iterator> IPSet = findConstantInsertionPoint(ConstInfo, MatInsertPts); // We can have an empty set if the function contains unreachable blocks. if (IPSet.empty()) @@ -853,7 +860,7 @@ bool ConstantHoistingPass::emitBaseConstants(GlobalVariable *BaseGV) { unsigned UsesNum = 0; unsigned ReBasesNum = 0; unsigned NotRebasedNum = 0; - for (Instruction *IP : IPSet) { + for (const BasicBlock::iterator &IP : IPSet) { // First, collect constants depending on this IP of the base. UsesNum = 0; SmallVector<UserAdjustment, 4> ToBeRebased; @@ -861,7 +868,7 @@ bool ConstantHoistingPass::emitBaseConstants(GlobalVariable *BaseGV) { for (auto const &RCI : ConstInfo.RebasedConstants) { UsesNum += RCI.Uses.size(); for (auto const &U : RCI.Uses) { - Instruction *MatInsertPt = MatInsertPts[MatCtr++]; + const BasicBlock::iterator &MatInsertPt = MatInsertPts[MatCtr++]; BasicBlock *OrigMatInsertBB = MatInsertPt->getParent(); // If Base constant is to be inserted in multiple places, // generate rebase for U using the Base dominating U. diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp index de3bfb57b538d3c3c7f707236dc38f99cd5c001a..fb334e8292eb186b32a0d992c36346da674fe222 100644 --- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -497,7 +497,7 @@ static bool processAbsIntrinsic(IntrinsicInst *II, LazyValueInfo *LVI) { // Is X in [IntMin, 0]? NOTE: INT_MIN is fine! if (Range.getSignedMax().isNonPositive()) { IRBuilder<> B(II); - Value *NegX = B.CreateNeg(X, II->getName(), /*HasNUW=*/false, + Value *NegX = B.CreateNeg(X, II->getName(), /*HasNSW=*/IsIntMinPoison); ++NumAbs; II->replaceAllUsesWith(NegX); diff --git a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp index 85d4065286e41fef3ac174195d1ba80a516bf7de..1caed93b1b668dabbe073fec6ebc36f03a0f991a 100644 --- a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp +++ b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp @@ -65,6 +65,7 @@ #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/CodeMetrics.h" #include "llvm/Analysis/DomTreeUpdater.h" +#include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/CFG.h" @@ -95,6 +96,11 @@ static cl::opt<bool> cl::desc("View the CFG before DFA Jump Threading"), cl::Hidden, cl::init(false)); +static cl::opt<bool> EarlyExitHeuristic( + "dfa-early-exit-heuristic", + cl::desc("Exit early if an unpredictable value come from the same loop"), + cl::Hidden, cl::init(true)); + static cl::opt<unsigned> MaxPathLength( "dfa-max-path-length", cl::desc("Max number of blocks searched to find a threading path"), @@ -131,9 +137,9 @@ void unfold(DomTreeUpdater *DTU, SelectInstToUnfold SIToUnfold, class DFAJumpThreading { public: - DFAJumpThreading(AssumptionCache *AC, DominatorTree *DT, + DFAJumpThreading(AssumptionCache *AC, DominatorTree *DT, LoopInfo *LI, TargetTransformInfo *TTI, OptimizationRemarkEmitter *ORE) - : AC(AC), DT(DT), TTI(TTI), ORE(ORE) {} + : AC(AC), DT(DT), LI(LI), TTI(TTI), ORE(ORE) {} bool run(Function &F); @@ -161,6 +167,7 @@ private: AssumptionCache *AC; DominatorTree *DT; + LoopInfo *LI; TargetTransformInfo *TTI; OptimizationRemarkEmitter *ORE; }; @@ -378,7 +385,8 @@ inline raw_ostream &operator<<(raw_ostream &OS, const ThreadingPath &TPath) { #endif struct MainSwitch { - MainSwitch(SwitchInst *SI, OptimizationRemarkEmitter *ORE) { + MainSwitch(SwitchInst *SI, LoopInfo *LI, OptimizationRemarkEmitter *ORE) + : LI(LI) { if (isCandidate(SI)) { Instr = SI; } else { @@ -402,7 +410,7 @@ private: /// /// Also, collect select instructions to unfold. bool isCandidate(const SwitchInst *SI) { - std::deque<Value *> Q; + std::deque<std::pair<Value *, BasicBlock *>> Q; SmallSet<Value *, 16> SeenValues; SelectInsts.clear(); @@ -411,22 +419,29 @@ private: if (!isa<PHINode>(SICond)) return false; - addToQueue(SICond, Q, SeenValues); + // The switch must be in a loop. + const Loop *L = LI->getLoopFor(SI->getParent()); + if (!L) + return false; + + addToQueue(SICond, nullptr, Q, SeenValues); while (!Q.empty()) { - Value *Current = Q.front(); + Value *Current = Q.front().first; + BasicBlock *CurrentIncomingBB = Q.front().second; Q.pop_front(); if (auto *Phi = dyn_cast<PHINode>(Current)) { - for (Value *Incoming : Phi->incoming_values()) { - addToQueue(Incoming, Q, SeenValues); + for (BasicBlock *IncomingBB : Phi->blocks()) { + Value *Incoming = Phi->getIncomingValueForBlock(IncomingBB); + addToQueue(Incoming, IncomingBB, Q, SeenValues); } LLVM_DEBUG(dbgs() << "\tphi: " << *Phi << "\n"); } else if (SelectInst *SelI = dyn_cast<SelectInst>(Current)) { if (!isValidSelectInst(SelI)) return false; - addToQueue(SelI->getTrueValue(), Q, SeenValues); - addToQueue(SelI->getFalseValue(), Q, SeenValues); + addToQueue(SelI->getTrueValue(), CurrentIncomingBB, Q, SeenValues); + addToQueue(SelI->getFalseValue(), CurrentIncomingBB, Q, SeenValues); LLVM_DEBUG(dbgs() << "\tselect: " << *SelI << "\n"); if (auto *SelIUse = dyn_cast<PHINode>(SelI->user_back())) SelectInsts.push_back(SelectInstToUnfold(SelI, SelIUse)); @@ -439,6 +454,18 @@ private: // initial switch values that can be ignored (they will hit the // unthreaded switch) but this assumption will get checked later after // paths have been enumerated (in function getStateDefMap). + + // If the unpredictable value comes from the same inner loop it is + // likely that it will also be on the enumerated paths, causing us to + // exit after we have enumerated all the paths. This heuristic save + // compile time because a search for all the paths can become expensive. + if (EarlyExitHeuristic && + L->contains(LI->getLoopFor(CurrentIncomingBB))) { + LLVM_DEBUG(dbgs() + << "\tExiting early due to unpredictability heuristic.\n"); + return false; + } + continue; } } @@ -446,11 +473,12 @@ private: return true; } - void addToQueue(Value *Val, std::deque<Value *> &Q, + void addToQueue(Value *Val, BasicBlock *BB, + std::deque<std::pair<Value *, BasicBlock *>> &Q, SmallSet<Value *, 16> &SeenValues) { if (SeenValues.contains(Val)) return; - Q.push_back(Val); + Q.push_back({Val, BB}); SeenValues.insert(Val); } @@ -488,6 +516,7 @@ private: return true; } + LoopInfo *LI; SwitchInst *Instr = nullptr; SmallVector<SelectInstToUnfold, 4> SelectInsts; }; @@ -1262,7 +1291,7 @@ bool DFAJumpThreading::run(Function &F) { LLVM_DEBUG(dbgs() << "\nCheck if SwitchInst in BB " << BB.getName() << " is a candidate\n"); - MainSwitch Switch(SI, ORE); + MainSwitch Switch(SI, LI, ORE); if (!Switch.getInstr()) continue; @@ -1315,10 +1344,11 @@ PreservedAnalyses DFAJumpThreadingPass::run(Function &F, FunctionAnalysisManager &AM) { AssumptionCache &AC = AM.getResult<AssumptionAnalysis>(F); DominatorTree &DT = AM.getResult<DominatorTreeAnalysis>(F); + LoopInfo &LI = AM.getResult<LoopAnalysis>(F); TargetTransformInfo &TTI = AM.getResult<TargetIRAnalysis>(F); OptimizationRemarkEmitter ORE(&F); - if (!DFAJumpThreading(&AC, &DT, &TTI, &ORE).run(F)) + if (!DFAJumpThreading(&AC, &DT, &LI, &TTI, &ORE).run(F)) return PreservedAnalyses::all(); PreservedAnalyses PA; diff --git a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp index 392e6ad5a66bb91dcfa9c242138109c7c24f4b8b..bfc8bd5970bf27fec21f296732bce4fddb614008 100644 --- a/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -526,7 +526,8 @@ static void shortenAssignment(Instruction *Inst, Value *OriginalDest, // returned by getAssignmentMarkers so save a copy of the markers to iterate // over. auto LinkedRange = at::getAssignmentMarkers(Inst); - SmallVector<DPValue *> LinkedDPVAssigns = at::getDPVAssignmentMarkers(Inst); + SmallVector<DbgVariableRecord *> LinkedDVRAssigns = + at::getDVRAssignmentMarkers(Inst); SmallVector<DbgAssignIntrinsic *> Linked(LinkedRange.begin(), LinkedRange.end()); auto InsertAssignForOverlap = [&](auto *Assign) { @@ -554,7 +555,7 @@ static void shortenAssignment(Instruction *Inst, Value *OriginalDest, NewAssign->setKillAddress(); }; for_each(Linked, InsertAssignForOverlap); - for_each(LinkedDPVAssigns, InsertAssignForOverlap); + for_each(LinkedDVRAssigns, InsertAssignForOverlap); } static bool tryToShorten(Instruction *DeadI, int64_t &DeadStart, diff --git a/llvm/lib/Transforms/Scalar/Float2Int.cpp b/llvm/lib/Transforms/Scalar/Float2Int.cpp index ccca8bcc1a56ac7b30360df6b0ed81d60f55f5d1..da4d39b4e3ed4476cdfd4c1af06bc09c74eb76fa 100644 --- a/llvm/lib/Transforms/Scalar/Float2Int.cpp +++ b/llvm/lib/Transforms/Scalar/Float2Int.cpp @@ -311,7 +311,7 @@ void Float2IntPass::walkForwards() { } // If there is a valid transform to be done, do it. -bool Float2IntPass::validateAndTransform() { +bool Float2IntPass::validateAndTransform(const DataLayout &DL) { bool MadeChange = false; // Iterate over every disjoint partition of the def-use graph. @@ -359,9 +359,7 @@ bool Float2IntPass::validateAndTransform() { // The number of bits required is the maximum of the upper and // lower limits, plus one so it can be signed. - unsigned MinBW = std::max(R.getLower().getSignificantBits(), - R.getUpper().getSignificantBits()) + - 1; + unsigned MinBW = R.getMinSignedBits() + 1; LLVM_DEBUG(dbgs() << "F2I: MinBitwidth=" << MinBW << ", R: " << R << "\n"); // If we've run off the realms of the exactly representable integers, @@ -376,15 +374,23 @@ bool Float2IntPass::validateAndTransform() { LLVM_DEBUG(dbgs() << "F2I: Value not guaranteed to be representable!\n"); continue; } - if (MinBW > 64) { - LLVM_DEBUG( - dbgs() << "F2I: Value requires more than 64 bits to represent!\n"); - continue; - } - // OK, R is known to be representable. Now pick a type for it. - // FIXME: Pick the smallest legal type that will fit. - Type *Ty = (MinBW > 32) ? Type::getInt64Ty(*Ctx) : Type::getInt32Ty(*Ctx); + // OK, R is known to be representable. + // Pick the smallest legal type that will fit. + Type *Ty = DL.getSmallestLegalIntType(*Ctx, MinBW); + if (!Ty) { + // Every supported target supports 64-bit and 32-bit integers, + // so fallback to a 32 or 64-bit integer if the value fits. + if (MinBW <= 32) { + Ty = Type::getInt32Ty(*Ctx); + } else if (MinBW <= 64) { + Ty = Type::getInt64Ty(*Ctx); + } else { + LLVM_DEBUG(dbgs() << "F2I: Value requires more bits to represent than " + "the target supports!\n"); + continue; + } + } for (auto MI = ECs.member_begin(It), ME = ECs.member_end(); MI != ME; ++MI) @@ -491,7 +497,8 @@ bool Float2IntPass::runImpl(Function &F, const DominatorTree &DT) { walkBackwards(); walkForwards(); - bool Modified = validateAndTransform(); + const DataLayout &DL = F.getParent()->getDataLayout(); + bool Modified = validateAndTransform(DL); if (Modified) cleanup(); return Modified; diff --git a/llvm/lib/Transforms/Scalar/GVNHoist.cpp b/llvm/lib/Transforms/Scalar/GVNHoist.cpp index b564f00eb9d1661e9c979c29b49c0823c6c3a790..261c1259c9c961ebf93de2687f883f7221813670 100644 --- a/llvm/lib/Transforms/Scalar/GVNHoist.cpp +++ b/llvm/lib/Transforms/Scalar/GVNHoist.cpp @@ -951,6 +951,14 @@ void GVNHoist::makeGepsAvailable(Instruction *Repl, BasicBlock *HoistPt, OtherGep = cast<GetElementPtrInst>( cast<StoreInst>(OtherInst)->getPointerOperand()); ClonedGep->andIRFlags(OtherGep); + + // Merge debug locations of GEPs, because the hoisted GEP replaces those + // in branches. When cloning, ClonedGep preserves the debug location of + // Gepd, so Gep is skipped to avoid merging it twice. + if (OtherGep != Gep) { + ClonedGep->applyMergedLocation(ClonedGep->getDebugLoc(), + OtherGep->getDebugLoc()); + } } // Replace uses of Gep with ClonedGep in Repl. diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp index 1058a015017e41d0c084ecf9459eeab407d8ef0b..ffcb511e6a83128fed8828cc33bef71de91c1ecd 100644 --- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp +++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp @@ -401,8 +401,8 @@ static bool replaceFoldableUses(Instruction *Cond, Value *ToVal, Changed |= replaceNonLocalUsesWith(Cond, ToVal); for (Instruction &I : reverse(*KnownAtEndOfBB)) { // Replace any debug-info record users of Cond with ToVal. - for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) - DPV.replaceVariableLocationOp(Cond, ToVal, true); + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) + DVR.replaceVariableLocationOp(Cond, ToVal, true); // Reached the Cond whose uses we are trying to replace, so there are no // more uses. @@ -1955,7 +1955,7 @@ void JumpThreadingPass::updateSSA( SSAUpdater SSAUpdate; SmallVector<Use *, 16> UsesToRename; SmallVector<DbgValueInst *, 4> DbgValues; - SmallVector<DPValue *, 4> DPValues; + SmallVector<DbgVariableRecord *, 4> DbgVariableRecords; for (Instruction &I : *BB) { // Scan all uses of this instruction to see if it is used outside of its @@ -1972,16 +1972,16 @@ void JumpThreadingPass::updateSSA( } // Find debug values outside of the block - findDbgValues(DbgValues, &I, &DPValues); + findDbgValues(DbgValues, &I, &DbgVariableRecords); llvm::erase_if(DbgValues, [&](const DbgValueInst *DbgVal) { return DbgVal->getParent() == BB; }); - llvm::erase_if(DPValues, [&](const DPValue *DPVal) { - return DPVal->getParent() == BB; + llvm::erase_if(DbgVariableRecords, [&](const DbgVariableRecord *DbgVarRec) { + return DbgVarRec->getParent() == BB; }); // If there are no uses outside the block, we're done with this instruction. - if (UsesToRename.empty() && DbgValues.empty() && DPValues.empty()) + if (UsesToRename.empty() && DbgValues.empty() && DbgVariableRecords.empty()) continue; LLVM_DEBUG(dbgs() << "JT: Renaming non-local uses of: " << I << "\n"); @@ -1994,11 +1994,11 @@ void JumpThreadingPass::updateSSA( while (!UsesToRename.empty()) SSAUpdate.RewriteUse(*UsesToRename.pop_back_val()); - if (!DbgValues.empty() || !DPValues.empty()) { + if (!DbgValues.empty() || !DbgVariableRecords.empty()) { SSAUpdate.UpdateDebugValues(&I, DbgValues); - SSAUpdate.UpdateDebugValues(&I, DPValues); + SSAUpdate.UpdateDebugValues(&I, DbgVariableRecords); DbgValues.clear(); - DPValues.clear(); + DbgVariableRecords.clear(); } LLVM_DEBUG(dbgs() << "\n"); @@ -2041,11 +2041,11 @@ JumpThreadingPass::cloneInstructions(BasicBlock::iterator BI, return true; }; - // Duplicate implementation of the above dbg.value code, using DPValues - // instead. - auto RetargetDPValueIfPossible = [&](DPValue *DPV) { + // Duplicate implementation of the above dbg.value code, using + // DbgVariableRecords instead. + auto RetargetDbgVariableRecordIfPossible = [&](DbgVariableRecord *DVR) { SmallSet<std::pair<Value *, Value *>, 16> OperandsToRemap; - for (auto *Op : DPV->location_ops()) { + for (auto *Op : DVR->location_ops()) { Instruction *OpInst = dyn_cast<Instruction>(Op); if (!OpInst) continue; @@ -2056,7 +2056,7 @@ JumpThreadingPass::cloneInstructions(BasicBlock::iterator BI, } for (auto &[OldOp, MappedOp] : OperandsToRemap) - DPV->replaceVariableLocationOp(OldOp, MappedOp); + DVR->replaceVariableLocationOp(OldOp, MappedOp); }; BasicBlock *RangeBB = BI->getParent(); @@ -2080,9 +2080,9 @@ JumpThreadingPass::cloneInstructions(BasicBlock::iterator BI, cloneNoAliasScopes(NoAliasScopes, ClonedScopes, "thread", Context); auto CloneAndRemapDbgInfo = [&](Instruction *NewInst, Instruction *From) { - auto DPVRange = NewInst->cloneDebugInfoFrom(From); - for (DPValue &DPV : DPValue::filter(DPVRange)) - RetargetDPValueIfPossible(&DPV); + auto DVRRange = NewInst->cloneDebugInfoFrom(From); + for (DbgVariableRecord &DVR : filterDbgVars(DVRRange)) + RetargetDbgVariableRecordIfPossible(&DVR); }; // Clone the non-phi instructions of the source basic block into NewBB, @@ -2109,15 +2109,15 @@ JumpThreadingPass::cloneInstructions(BasicBlock::iterator BI, } } - // There may be DPValues on the terminator, clone directly from marker - // to marker as there isn't an instruction there. + // There may be DbgVariableRecords on the terminator, clone directly from + // marker to marker as there isn't an instruction there. if (BE != RangeBB->end() && BE->hasDbgRecords()) { // Dump them at the end. - DPMarker *Marker = RangeBB->getMarker(BE); - DPMarker *EndMarker = NewBB->createMarker(NewBB->end()); - auto DPVRange = EndMarker->cloneDebugInfoFrom(Marker, std::nullopt); - for (DPValue &DPV : DPValue::filter(DPVRange)) - RetargetDPValueIfPossible(&DPV); + DbgMarker *Marker = RangeBB->getMarker(BE); + DbgMarker *EndMarker = NewBB->createMarker(NewBB->end()); + auto DVRRange = EndMarker->cloneDebugInfoFrom(Marker, std::nullopt); + for (DbgVariableRecord &DVR : filterDbgVars(DVRRange)) + RetargetDbgVariableRecordIfPossible(&DVR); } return ValueMapping; diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp index 40bc16f9b57516935d9c8787561787be18d2fc33..e50413de46b1b4b1ed45234870dc49b6d022deee 100644 --- a/llvm/lib/Transforms/Scalar/LICM.cpp +++ b/llvm/lib/Transforms/Scalar/LICM.cpp @@ -2701,6 +2701,7 @@ static bool hoistMulAddAssociation(Instruction &I, Loop &L, // First, we need to make sure we should do the transformation. SmallVector<Use *> Changes; + SmallVector<BinaryOperator *> Adds; SmallVector<BinaryOperator *> Worklist; if (BinaryOperator *VariantBinOp = dyn_cast<BinaryOperator>(VariantOp)) Worklist.push_back(VariantBinOp); @@ -2713,6 +2714,7 @@ static bool hoistMulAddAssociation(Instruction &I, Loop &L, isa<BinaryOperator>(BO->getOperand(1))) { Worklist.push_back(cast<BinaryOperator>(BO->getOperand(0))); Worklist.push_back(cast<BinaryOperator>(BO->getOperand(1))); + Adds.push_back(BO); continue; } if (!isReassociableOp(BO, Instruction::Mul, Instruction::FMul) || @@ -2735,6 +2737,12 @@ static bool hoistMulAddAssociation(Instruction &I, Loop &L, if (Changes.empty()) return false; + // Drop the poison flags for any adds we looked through. + if (I.getType()->isIntOrIntVectorTy()) { + for (auto *Add : Adds) + Add->dropPoisonGeneratingFlags(); + } + // We know we should do it so let's do the transformation. auto *Preheader = L.getLoopPreheader(); assert(Preheader && "Loop is not in simplify form?"); @@ -2743,9 +2751,11 @@ static bool hoistMulAddAssociation(Instruction &I, Loop &L, assert(L.isLoopInvariant(U->get())); Instruction *Ins = cast<Instruction>(U->getUser()); Value *Mul; - if (I.getType()->isIntOrIntVectorTy()) + if (I.getType()->isIntOrIntVectorTy()) { Mul = Builder.CreateMul(U->get(), Factor, "factor.op.mul"); - else + // Drop the poison flags on the original multiply. + Ins->dropPoisonGeneratingFlags(); + } else Mul = Builder.CreateFMulFMF(U->get(), Factor, Ins, "factor.op.fmul"); U->set(Mul); } diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp index c4e1a0db8b32302d157462971f2c08705de55518..ec42e2d6e193a688162af8e8678392f42ef725ab 100644 --- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -6367,10 +6367,10 @@ struct DVIRecoveryRec { DVIRecoveryRec(DbgValueInst *DbgValue) : DbgRef(DbgValue), Expr(DbgValue->getExpression()), HadLocationArgList(false) {} - DVIRecoveryRec(DPValue *DPV) - : DbgRef(DPV), Expr(DPV->getExpression()), HadLocationArgList(false) {} + DVIRecoveryRec(DbgVariableRecord *DVR) + : DbgRef(DVR), Expr(DVR->getExpression()), HadLocationArgList(false) {} - PointerUnion<DbgValueInst *, DPValue *> DbgRef; + PointerUnion<DbgValueInst *, DbgVariableRecord *> DbgRef; DIExpression *Expr; bool HadLocationArgList; SmallVector<WeakVH, 2> LocationOps; @@ -6466,7 +6466,7 @@ static void UpdateDbgValueInst(DVIRecoveryRec &DVIRec, if (isa<DbgValueInst *>(DVIRec.DbgRef)) UpdateDbgValueInstImpl(cast<DbgValueInst *>(DVIRec.DbgRef)); else - UpdateDbgValueInstImpl(cast<DPValue *>(DVIRec.DbgRef)); + UpdateDbgValueInstImpl(cast<DbgVariableRecord *>(DVIRec.DbgRef)); } /// Cached location ops may be erased during LSR, in which case a poison is @@ -6512,7 +6512,7 @@ static void restorePreTransformState(DVIRecoveryRec &DVIRec) { if (isa<DbgValueInst *>(DVIRec.DbgRef)) RestorePreTransformStateImpl(cast<DbgValueInst *>(DVIRec.DbgRef)); else - RestorePreTransformStateImpl(cast<DPValue *>(DVIRec.DbgRef)); + RestorePreTransformStateImpl(cast<DbgVariableRecord *>(DVIRec.DbgRef)); } static bool SalvageDVI(llvm::Loop *L, ScalarEvolution &SE, @@ -6522,7 +6522,7 @@ static bool SalvageDVI(llvm::Loop *L, ScalarEvolution &SE, if (isa<DbgValueInst *>(DVIRec.DbgRef) ? !cast<DbgValueInst *>(DVIRec.DbgRef)->isKillLocation() - : !cast<DPValue *>(DVIRec.DbgRef)->isKillLocation()) + : !cast<DbgVariableRecord *>(DVIRec.DbgRef)->isKillLocation()) return false; // LSR may have caused several changes to the dbg.value in the failed salvage @@ -6620,7 +6620,7 @@ static bool SalvageDVI(llvm::Loop *L, ScalarEvolution &SE, << *cast<DbgValueInst *>(DVIRec.DbgRef) << "\n"); else LLVM_DEBUG(dbgs() << "scev-salvage: Updated DVI: " - << *cast<DPValue *>(DVIRec.DbgRef) << "\n"); + << *cast<DbgVariableRecord *>(DVIRec.DbgRef) << "\n"); return true; } @@ -6711,9 +6711,9 @@ static void DbgGatherSalvagableDVI( SalvageableDVISCEVs.push_back(std::move(NewRec)); return true; }; - for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) { - if (DPV.isDbgValue() || DPV.isDbgAssign()) - ProcessDbgValue(&DPV); + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { + if (DVR.isDbgValue() || DVR.isDbgAssign()) + ProcessDbgValue(&DVR); } auto DVI = dyn_cast<DbgValueInst>(&I); if (!DVI) diff --git a/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp b/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp index 67c011b747acfd625d5c73ad1346cdcc513bdd1d..e991296bd2fb07fc83a0a8c0392c1ea0059b4c6b 100644 --- a/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp +++ b/llvm/lib/Transforms/Scalar/LowerMatrixIntrinsics.cpp @@ -19,6 +19,7 @@ #include "llvm/Transforms/Scalar/LowerMatrixIntrinsics.h" #include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/AliasAnalysis.h" @@ -990,12 +991,15 @@ public: bool Changed = false; SmallVector<CallInst *, 16> MaybeFusableInsts; SmallVector<Instruction *, 16> MatrixInsts; + SmallVector<IntrinsicInst *, 16> LifetimeEnds; // First, collect all instructions with shape information and candidates for // fusion (currently only matrix multiplies). ReversePostOrderTraversal<Function *> RPOT(&Func); for (auto *BB : RPOT) for (Instruction &I : *BB) { + if (match(&I, m_Intrinsic<Intrinsic::lifetime_end>())) + LifetimeEnds.push_back(cast<IntrinsicInst>(&I)); if (ShapeMap.find(&I) == ShapeMap.end()) continue; if (match(&I, m_Intrinsic<Intrinsic::matrix_multiply>())) @@ -1010,7 +1014,7 @@ public: // Third, try to fuse candidates. for (CallInst *CI : MaybeFusableInsts) - LowerMatrixMultiplyFused(CI, FusedInsts); + LowerMatrixMultiplyFused(CI, FusedInsts, LifetimeEnds); Changed = !FusedInsts.empty(); @@ -1856,8 +1860,10 @@ public: /// /// Call finalizeLowering on lowered instructions. Instructions that are /// completely eliminated by fusion are added to \p FusedInsts. - void LowerMatrixMultiplyFused(CallInst *MatMul, - SmallPtrSetImpl<Instruction *> &FusedInsts) { + void + LowerMatrixMultiplyFused(CallInst *MatMul, + SmallPtrSetImpl<Instruction *> &FusedInsts, + SmallVector<IntrinsicInst *, 16> &LifetimeEnds) { if (!FuseMatrix || !DT) return; @@ -1946,6 +1952,55 @@ public: for (Instruction *I : ToHoist) I->moveBefore(MatMul); + // Deal with lifetime.end calls that might be between Load0/Load1 and the + // store. To avoid introducing loads to dead objects (i.e. after the + // lifetime has been termined by @llvm.lifetime.end), either sink them + // after the store if in the same block, or remove the lifetime.end marker + // otherwise. This might pessimize further optimizations, by extending the + // lifetime of the object until the function returns, but should be + // conservatively correct. + MemoryLocation Load0Loc = MemoryLocation::get(LoadOp0); + MemoryLocation Load1Loc = MemoryLocation::get(LoadOp1); + BasicBlock *StoreParent = Store->getParent(); + bool FusableOpsInSameBlock = LoadOp0->getParent() == StoreParent && + LoadOp1->getParent() == StoreParent; + for (unsigned Idx = 0; Idx != LifetimeEnds.size();) { + IntrinsicInst *End = LifetimeEnds[Idx]; + auto Inc = make_scope_exit([&Idx]() { Idx++; }); + // If the lifetime.end is guaranteed to be before the loads or after the + // store, it won't interfere with fusion. + if (DT->dominates(End, LoadOp0) && DT->dominates(End, LoadOp1)) + continue; + if (DT->dominates(Store, End)) + continue; + // If all fusable ops are in the same block and the lifetime.end is in a + // different block, it won't interfere with fusion. + if (FusableOpsInSameBlock && End->getParent() != StoreParent) + continue; + + // If the loads don't alias the lifetime.end, it won't interfere with + // fusion. + MemoryLocation EndLoc = MemoryLocation::getForArgument(End, 1, nullptr); + if (!EndLoc.Ptr) + continue; + if (AA->isNoAlias(Load0Loc, EndLoc) && AA->isNoAlias(Load1Loc, EndLoc)) + continue; + + // If both lifetime.end and the store are in the same block, extend the + // lifetime until after the store, so the new lifetime covers the loads + // we introduce later. + if (End->getParent() == StoreParent) { + End->moveAfter(Store); + continue; + } + + // Otherwise remove the conflicting lifetime.end marker. + ToRemove.push_back(End); + std::swap(LifetimeEnds[Idx], LifetimeEnds.back()); + LifetimeEnds.pop_back(); + Inc.release(); + } + emitSIMDTiling(MatMul, LoadOp0, LoadOp1, Store, FusedInsts); return; } diff --git a/llvm/lib/Transforms/Scalar/MergeICmps.cpp b/llvm/lib/Transforms/Scalar/MergeICmps.cpp index 1e09067175499ca36f752be9ef764593cc91e0d6..2bd13556c69663376489b95345e5fb2004305400 100644 --- a/llvm/lib/Transforms/Scalar/MergeICmps.cpp +++ b/llvm/lib/Transforms/Scalar/MergeICmps.cpp @@ -74,7 +74,7 @@ namespace { struct BCEAtom { BCEAtom() = default; BCEAtom(GetElementPtrInst *GEP, LoadInst *LoadI, int BaseId, APInt Offset) - : GEP(GEP), LoadI(LoadI), BaseId(BaseId), Offset(Offset) {} + : GEP(GEP), LoadI(LoadI), BaseId(BaseId), Offset(std::move(Offset)) {} BCEAtom(const BCEAtom &) = delete; BCEAtom &operator=(const BCEAtom &) = delete; diff --git a/llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp b/llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp index 436a85f62df681fc29cbc1d59f86ae090180eb05..f5c9aaa4f20bc7f2f562332be7ba6309d539fbee 100644 --- a/llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp +++ b/llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp @@ -517,7 +517,7 @@ static bool doesNotRequireEntrySafepointBefore(CallBase *Call) { switch (II->getIntrinsicID()) { case Intrinsic::experimental_gc_statepoint: case Intrinsic::experimental_patchpoint_void: - case Intrinsic::experimental_patchpoint_i64: + case Intrinsic::experimental_patchpoint: // The can wrap an actual call which may grow the stack by an unbounded // amount or run forever. return false; diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp index e238f311a15bc207e03602fa30d9a7fde8e91295..096c6d1b1fad2701314162f90f6de2f845eae3d4 100644 --- a/llvm/lib/Transforms/Scalar/SROA.cpp +++ b/llvm/lib/Transforms/Scalar/SROA.cpp @@ -319,17 +319,17 @@ static DebugVariable getAggregateVariable(DbgVariableIntrinsic *DVI) { return DebugVariable(DVI->getVariable(), std::nullopt, DVI->getDebugLoc().getInlinedAt()); } -static DebugVariable getAggregateVariable(DPValue *DPV) { - return DebugVariable(DPV->getVariable(), std::nullopt, - DPV->getDebugLoc().getInlinedAt()); +static DebugVariable getAggregateVariable(DbgVariableRecord *DVR) { + return DebugVariable(DVR->getVariable(), std::nullopt, + DVR->getDebugLoc().getInlinedAt()); } /// Helpers for handling new and old debug info modes in migrateDebugInfo. /// These overloads unwrap a DbgInstPtr {Instruction* | DbgRecord*} union based /// on the \p Unused parameter type. -DPValue *UnwrapDbgInstPtr(DbgInstPtr P, DPValue *Unused) { +DbgVariableRecord *UnwrapDbgInstPtr(DbgInstPtr P, DbgVariableRecord *Unused) { (void)Unused; - return static_cast<DPValue *>(cast<DbgRecord *>(P)); + return static_cast<DbgVariableRecord *>(cast<DbgRecord *>(P)); } DbgAssignIntrinsic *UnwrapDbgInstPtr(DbgInstPtr P, DbgAssignIntrinsic *Unused) { (void)Unused; @@ -356,9 +356,9 @@ static void migrateDebugInfo(AllocaInst *OldAlloca, bool IsSplit, Instruction *Inst, Value *Dest, Value *Value, const DataLayout &DL) { auto MarkerRange = at::getAssignmentMarkers(OldInst); - auto DPVAssignMarkerRange = at::getDPVAssignmentMarkers(OldInst); + auto DVRAssignMarkerRange = at::getDVRAssignmentMarkers(OldInst); // Nothing to do if OldInst has no linked dbg.assign intrinsics. - if (MarkerRange.empty() && DPVAssignMarkerRange.empty()) + if (MarkerRange.empty() && DVRAssignMarkerRange.empty()) return; LLVM_DEBUG(dbgs() << " migrateDebugInfo\n"); @@ -379,9 +379,9 @@ static void migrateDebugInfo(AllocaInst *OldAlloca, bool IsSplit, for (auto *DAI : at::getAssignmentMarkers(OldAlloca)) BaseFragments[getAggregateVariable(DAI)] = DAI->getExpression()->getFragmentInfo(); - for (auto *DPV : at::getDPVAssignmentMarkers(OldAlloca)) - BaseFragments[getAggregateVariable(DPV)] = - DPV->getExpression()->getFragmentInfo(); + for (auto *DVR : at::getDVRAssignmentMarkers(OldAlloca)) + BaseFragments[getAggregateVariable(DVR)] = + DVR->getExpression()->getFragmentInfo(); // The new inst needs a DIAssignID unique metadata tag (if OldInst has // one). It shouldn't already have one: assert this assumption. @@ -488,7 +488,7 @@ static void migrateDebugInfo(AllocaInst *OldAlloca, bool IsSplit, }; for_each(MarkerRange, MigrateDbgAssign); - for_each(DPVAssignMarkerRange, MigrateDbgAssign); + for_each(DVRAssignMarkerRange, MigrateDbgAssign); } namespace { @@ -3195,7 +3195,7 @@ private: // emit dbg.assign intrinsics for mem intrinsics storing through non- // constant geps, or storing a variable number of bytes. assert(at::getAssignmentMarkers(&II).empty() && - at::getDPVAssignmentMarkers(&II).empty() && + at::getDVRAssignmentMarkers(&II).empty() && "AT: Unexpected link to non-const GEP"); deleteIfTriviallyDead(OldPtr); return false; @@ -3350,7 +3350,7 @@ private: DbgAssign->replaceVariableLocationOp(II.getDest(), AdjustedPtr); }; for_each(at::getAssignmentMarkers(&II), UpdateAssignAddress); - for_each(at::getDPVAssignmentMarkers(&II), UpdateAssignAddress); + for_each(at::getDVRAssignmentMarkers(&II), UpdateAssignAddress); II.setDest(AdjustedPtr); II.setDestAlignment(SliceAlign); } else { @@ -3939,7 +3939,7 @@ private: DL); } else { assert(at::getAssignmentMarkers(Store).empty() && - at::getDPVAssignmentMarkers(Store).empty() && + at::getDVRAssignmentMarkers(Store).empty() && "AT: unexpected debug.assign linked to store through " "unbounded GEP"); } @@ -5034,14 +5034,14 @@ static void insertNewDbgInst(DIBuilder &DIB, DbgAssignIntrinsic *Orig, LLVM_DEBUG(dbgs() << "Created new assign intrinsic: " << *NewAssign << "\n"); (void)NewAssign; } -static void insertNewDbgInst(DIBuilder &DIB, DPValue *Orig, AllocaInst *NewAddr, - DIExpression *NewFragmentExpr, +static void insertNewDbgInst(DIBuilder &DIB, DbgVariableRecord *Orig, + AllocaInst *NewAddr, DIExpression *NewFragmentExpr, Instruction *BeforeInst) { (void)DIB; if (Orig->isDbgDeclare()) { - DPValue *DPV = DPValue::createDPVDeclare( + DbgVariableRecord *DVR = DbgVariableRecord::createDVRDeclare( NewAddr, Orig->getVariable(), NewFragmentExpr, Orig->getDebugLoc()); - BeforeInst->getParent()->insertDbgRecordBefore(DPV, + BeforeInst->getParent()->insertDbgRecordBefore(DVR, BeforeInst->getIterator()); return; } @@ -5049,10 +5049,10 @@ static void insertNewDbgInst(DIBuilder &DIB, DPValue *Orig, AllocaInst *NewAddr, NewAddr->setMetadata(LLVMContext::MD_DIAssignID, DIAssignID::getDistinct(NewAddr->getContext())); } - DPValue *NewAssign = DPValue::createLinkedDPVAssign( + DbgVariableRecord *NewAssign = DbgVariableRecord::createLinkedDVRAssign( NewAddr, Orig->getValue(), Orig->getVariable(), NewFragmentExpr, NewAddr, Orig->getAddressExpression(), Orig->getDebugLoc()); - LLVM_DEBUG(dbgs() << "Created new DPVAssign: " << *NewAssign << "\n"); + LLVM_DEBUG(dbgs() << "Created new DVRAssign: " << *NewAssign << "\n"); (void)NewAssign; } @@ -5220,7 +5220,7 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) { OldDII->eraseFromParent(); }; for_each(findDbgDeclares(Fragment.Alloca), RemoveOne); - for_each(findDPVDeclares(Fragment.Alloca), RemoveOne); + for_each(findDVRDeclares(Fragment.Alloca), RemoveOne); insertNewDbgInst(DIB, DbgVariable, Fragment.Alloca, FragmentExpr, &AI); } @@ -5229,9 +5229,9 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) { // Migrate debug information from the old alloca to the new alloca(s) // and the individual partitions. for_each(findDbgDeclares(&AI), MigrateOne); - for_each(findDPVDeclares(&AI), MigrateOne); + for_each(findDVRDeclares(&AI), MigrateOne); for_each(at::getAssignmentMarkers(&AI), MigrateOne); - for_each(at::getDPVAssignmentMarkers(&AI), MigrateOne); + for_each(at::getDVRAssignmentMarkers(&AI), MigrateOne); return Changed; } @@ -5355,7 +5355,7 @@ bool SROA::deleteDeadInstructions( DeletedAllocas.insert(AI); for (DbgDeclareInst *OldDII : findDbgDeclares(AI)) OldDII->eraseFromParent(); - for (DPValue *OldDII : findDPVDeclares(AI)) + for (DbgVariableRecord *OldDII : findDVRDeclares(AI)) OldDII->eraseFromParent(); } diff --git a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp index 9fcaf2a89e563917652d101be6280b2fca09bc88..64b850a6a5c2ffe8b09f8f35a02f428fe834769d 100644 --- a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp +++ b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp @@ -1260,8 +1260,9 @@ static BasicBlock *buildClonedLoopBlocks( Module *M = ClonedPH->getParent()->getParent(); for (auto *ClonedBB : NewBlocks) for (Instruction &I : *ClonedBB) { - RemapDPValueRange(M, I.getDbgRecordRange(), VMap, - RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); + RemapDbgVariableRecordRange(M, I.getDbgRecordRange(), VMap, + RF_NoModuleLevelChanges | + RF_IgnoreMissingLocals); RemapInstruction(&I, VMap, RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); if (auto *II = dyn_cast<AssumeInst>(&I)) diff --git a/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp b/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp index 8686570dfd2f4419de2ea0d6fd4ef8efba33e295..f921ee72a0a1cea626231b54266aeee87fdfce1a 100644 --- a/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp +++ b/llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp @@ -260,10 +260,31 @@ static InstructionCost ComputeSpeculationCost(const Instruction *I, } } +// Do not hoist any debug info intrinsics. +// ... +// if (cond) { +// x = y * z; +// foo(); +// } +// ... +// -------- Which then becomes: +// ... +// if.then: +// %x = mul i32 %y, %z +// call void @llvm.dbg.value(%x, !"x", !DIExpression()) +// call void foo() +// +// SpeculativeExecution might decide to hoist the 'y * z' calculation +// out of the 'if' block, because it is more efficient that way, so the +// '%x = mul i32 %y, %z' moves to the block above. But it might also +// decide to hoist the 'llvm.dbg.value' call. +// This is incorrect, because even if we've moved the calculation of +// 'y * z', we should not see the value of 'x' change unless we +// actually go inside the 'if' block. + bool SpeculativeExecutionPass::considerHoistingFromTo( BasicBlock &FromBlock, BasicBlock &ToBlock) { SmallPtrSet<const Instruction *, 8> NotHoisted; - SmallDenseMap<const Instruction *, SmallVector<DPValue *>> DPValuesToHoist; auto HasNoUnhoistedInstr = [&NotHoisted](auto Values) { for (const Value *V : Values) { if (const auto *I = dyn_cast_or_null<Instruction>(V)) @@ -274,15 +295,8 @@ bool SpeculativeExecutionPass::considerHoistingFromTo( }; auto AllPrecedingUsesFromBlockHoisted = [&HasNoUnhoistedInstr](const User *U) { - // Debug variable has special operand to check it's not hoisted. - if (const auto *DVI = dyn_cast<DbgVariableIntrinsic>(U)) - return HasNoUnhoistedInstr(DVI->location_ops()); - - // Usially debug label intrinsic corresponds to label in LLVM IR. In - // these cases we should not move it here. - // TODO: Possible special processing needed to detect it is related to a - // hoisted instruction. - if (isa<DbgLabelInst>(U)) + // Do not hoist any debug info intrinsics. + if (isa<DbgInfoIntrinsic>(U)) return false; return HasNoUnhoistedInstr(U->operand_values()); @@ -291,12 +305,6 @@ bool SpeculativeExecutionPass::considerHoistingFromTo( InstructionCost TotalSpeculationCost = 0; unsigned NotHoistedInstCount = 0; for (const auto &I : FromBlock) { - // Make note of any DPValues that need hoisting. DPLabels - // get left behind just like llvm.dbg.labels. - for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) { - if (HasNoUnhoistedInstr(DPV.location_ops())) - DPValuesToHoist[DPV.getInstruction()].push_back(&DPV); - } const InstructionCost Cost = ComputeSpeculationCost(&I, *TTI); if (Cost.isValid() && isSafeToSpeculativelyExecute(&I) && AllPrecedingUsesFromBlockHoisted(&I)) { @@ -314,16 +322,6 @@ bool SpeculativeExecutionPass::considerHoistingFromTo( } for (auto I = FromBlock.begin(); I != FromBlock.end();) { - // If any DPValues attached to this instruction should be hoisted, hoist - // them now - they will end up attached to either the next hoisted - // instruction or the ToBlock terminator. - if (DPValuesToHoist.contains(&*I)) { - for (auto *DPV : DPValuesToHoist[&*I]) { - DPV->removeFromParent(); - ToBlock.insertDbgRecordBefore(DPV, - ToBlock.getTerminator()->getIterator()); - } - } // We have to increment I before moving Current as moving Current // changes the list that I is iterating through. auto Current = I; diff --git a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp index 519ff3221a3bc36b914e89beb7fa6d4f2c265cde..bc4b6de2f07f1f094095fb32f572554d46692b0a 100644 --- a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp +++ b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp @@ -509,8 +509,10 @@ void TailRecursionEliminator::createTailRecurseLoopHeader(CallInst *CI) { BasicBlock *NewEntry = BasicBlock::Create(F.getContext(), "", &F, HeaderBB); NewEntry->takeName(HeaderBB); HeaderBB->setName("tailrecurse"); - BranchInst *BI = BranchInst::Create(HeaderBB, NewEntry); - BI->setDebugLoc(CI->getDebugLoc()); + BranchInst::Create(HeaderBB, NewEntry); + // If the new branch preserves the debug location of CI, it could result in + // misleading stepping, if CI is located in a conditional branch. + // So, here we don't give any debug location to the new branch. // Move all fixed sized allocas from HeaderBB to NewEntry. for (BasicBlock::iterator OEBI = HeaderBB->begin(), E = HeaderBB->end(), diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp index 2006b40e26d05910953339624c29ac6095f96c18..915cd81661f0272a272b89838a3ffa5d78175ee6 100644 --- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -382,22 +382,23 @@ bool llvm::MergeBlockSuccessorsIntoGivenBlocks( /// - Check fully overlapping fragments and not only identical fragments. /// - Support dbg.declare. dbg.label, and possibly other meta instructions being /// part of the sequence of consecutive instructions. -static bool DPValuesRemoveRedundantDbgInstrsUsingBackwardScan(BasicBlock *BB) { - SmallVector<DPValue *, 8> ToBeRemoved; +static bool +DbgVariableRecordsRemoveRedundantDbgInstrsUsingBackwardScan(BasicBlock *BB) { + SmallVector<DbgVariableRecord *, 8> ToBeRemoved; SmallDenseSet<DebugVariable> VariableSet; for (auto &I : reverse(*BB)) { for (DbgRecord &DR : reverse(I.getDbgRecordRange())) { - if (isa<DPLabel>(DR)) { + if (isa<DbgLabelRecord>(DR)) { // Emulate existing behaviour (see comment below for dbg.declares). // FIXME: Don't do this. VariableSet.clear(); continue; } - DPValue &DPV = cast<DPValue>(DR); + DbgVariableRecord &DVR = cast<DbgVariableRecord>(DR); // Skip declare-type records, as the debug intrinsic method only works // on dbg.value intrinsics. - if (DPV.getType() == DPValue::LocationType::Declare) { + if (DVR.getType() == DbgVariableRecord::LocationType::Declare) { // The debug intrinsic method treats dbg.declares are "non-debug" // instructions (i.e., a break in a consecutive range of debug // intrinsics). Emulate that to create identical outputs. See @@ -407,8 +408,8 @@ static bool DPValuesRemoveRedundantDbgInstrsUsingBackwardScan(BasicBlock *BB) { continue; } - DebugVariable Key(DPV.getVariable(), DPV.getExpression(), - DPV.getDebugLoc()->getInlinedAt()); + DebugVariable Key(DVR.getVariable(), DVR.getExpression(), + DVR.getDebugLoc()->getInlinedAt()); auto R = VariableSet.insert(Key); // If the same variable fragment is described more than once it is enough // to keep the last one (i.e. the first found since we for reverse @@ -416,14 +417,14 @@ static bool DPValuesRemoveRedundantDbgInstrsUsingBackwardScan(BasicBlock *BB) { if (R.second) continue; - if (DPV.isDbgAssign()) { + if (DVR.isDbgAssign()) { // Don't delete dbg.assign intrinsics that are linked to instructions. - if (!at::getAssignmentInsts(&DPV).empty()) + if (!at::getAssignmentInsts(&DVR).empty()) continue; // Unlinked dbg.assign intrinsics can be treated like dbg.values. } - ToBeRemoved.push_back(&DPV); + ToBeRemoved.push_back(&DVR); continue; } // Sequence with consecutive dbg.value instrs ended. Clear the map to @@ -432,15 +433,15 @@ static bool DPValuesRemoveRedundantDbgInstrsUsingBackwardScan(BasicBlock *BB) { VariableSet.clear(); } - for (auto &DPV : ToBeRemoved) - DPV->eraseFromParent(); + for (auto &DVR : ToBeRemoved) + DVR->eraseFromParent(); return !ToBeRemoved.empty(); } static bool removeRedundantDbgInstrsUsingBackwardScan(BasicBlock *BB) { if (BB->IsNewDbgInfoFormat) - return DPValuesRemoveRedundantDbgInstrsUsingBackwardScan(BB); + return DbgVariableRecordsRemoveRedundantDbgInstrsUsingBackwardScan(BB); SmallVector<DbgValueInst *, 8> ToBeRemoved; SmallDenseSet<DebugVariable> VariableSet; @@ -499,29 +500,30 @@ static bool removeRedundantDbgInstrsUsingBackwardScan(BasicBlock *BB) { /// /// Possible improvements: /// - Keep track of non-overlapping fragments. -static bool DPValuesRemoveRedundantDbgInstrsUsingForwardScan(BasicBlock *BB) { - SmallVector<DPValue *, 8> ToBeRemoved; +static bool +DbgVariableRecordsRemoveRedundantDbgInstrsUsingForwardScan(BasicBlock *BB) { + SmallVector<DbgVariableRecord *, 8> ToBeRemoved; DenseMap<DebugVariable, std::pair<SmallVector<Value *, 4>, DIExpression *>> VariableMap; for (auto &I : *BB) { - for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) { - if (DPV.getType() == DPValue::LocationType::Declare) + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { + if (DVR.getType() == DbgVariableRecord::LocationType::Declare) continue; - DebugVariable Key(DPV.getVariable(), std::nullopt, - DPV.getDebugLoc()->getInlinedAt()); + DebugVariable Key(DVR.getVariable(), std::nullopt, + DVR.getDebugLoc()->getInlinedAt()); auto VMI = VariableMap.find(Key); // A dbg.assign with no linked instructions can be treated like a // dbg.value (i.e. can be deleted). bool IsDbgValueKind = - (!DPV.isDbgAssign() || at::getAssignmentInsts(&DPV).empty()); + (!DVR.isDbgAssign() || at::getAssignmentInsts(&DVR).empty()); // Update the map if we found a new value/expression describing the // variable, or if the variable wasn't mapped already. - SmallVector<Value *, 4> Values(DPV.location_ops()); + SmallVector<Value *, 4> Values(DVR.location_ops()); if (VMI == VariableMap.end() || VMI->second.first != Values || - VMI->second.second != DPV.getExpression()) { + VMI->second.second != DVR.getExpression()) { if (IsDbgValueKind) - VariableMap[Key] = {Values, DPV.getExpression()}; + VariableMap[Key] = {Values, DVR.getExpression()}; else VariableMap[Key] = {Values, nullptr}; continue; @@ -530,55 +532,56 @@ static bool DPValuesRemoveRedundantDbgInstrsUsingForwardScan(BasicBlock *BB) { if (!IsDbgValueKind) continue; // Found an identical mapping. Remember the instruction for later removal. - ToBeRemoved.push_back(&DPV); + ToBeRemoved.push_back(&DVR); } } - for (auto *DPV : ToBeRemoved) - DPV->eraseFromParent(); + for (auto *DVR : ToBeRemoved) + DVR->eraseFromParent(); return !ToBeRemoved.empty(); } -static bool DPValuesRemoveUndefDbgAssignsFromEntryBlock(BasicBlock *BB) { +static bool +DbgVariableRecordsRemoveUndefDbgAssignsFromEntryBlock(BasicBlock *BB) { assert(BB->isEntryBlock() && "expected entry block"); - SmallVector<DPValue *, 8> ToBeRemoved; + SmallVector<DbgVariableRecord *, 8> ToBeRemoved; DenseSet<DebugVariable> SeenDefForAggregate; // Returns the DebugVariable for DVI with no fragment info. - auto GetAggregateVariable = [](const DPValue &DPV) { - return DebugVariable(DPV.getVariable(), std::nullopt, - DPV.getDebugLoc().getInlinedAt()); + auto GetAggregateVariable = [](const DbgVariableRecord &DVR) { + return DebugVariable(DVR.getVariable(), std::nullopt, + DVR.getDebugLoc().getInlinedAt()); }; // Remove undef dbg.assign intrinsics that are encountered before // any non-undef intrinsics from the entry block. for (auto &I : *BB) { - for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) { - if (!DPV.isDbgValue() && !DPV.isDbgAssign()) + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { + if (!DVR.isDbgValue() && !DVR.isDbgAssign()) continue; bool IsDbgValueKind = - (DPV.isDbgValue() || at::getAssignmentInsts(&DPV).empty()); - DebugVariable Aggregate = GetAggregateVariable(DPV); + (DVR.isDbgValue() || at::getAssignmentInsts(&DVR).empty()); + DebugVariable Aggregate = GetAggregateVariable(DVR); if (!SeenDefForAggregate.contains(Aggregate)) { - bool IsKill = DPV.isKillLocation() && IsDbgValueKind; + bool IsKill = DVR.isKillLocation() && IsDbgValueKind; if (!IsKill) { SeenDefForAggregate.insert(Aggregate); - } else if (DPV.isDbgAssign()) { - ToBeRemoved.push_back(&DPV); + } else if (DVR.isDbgAssign()) { + ToBeRemoved.push_back(&DVR); } } } } - for (DPValue *DPV : ToBeRemoved) - DPV->eraseFromParent(); + for (DbgVariableRecord *DVR : ToBeRemoved) + DVR->eraseFromParent(); return !ToBeRemoved.empty(); } static bool removeRedundantDbgInstrsUsingForwardScan(BasicBlock *BB) { if (BB->IsNewDbgInfoFormat) - return DPValuesRemoveRedundantDbgInstrsUsingForwardScan(BB); + return DbgVariableRecordsRemoveRedundantDbgInstrsUsingForwardScan(BB); SmallVector<DbgValueInst *, 8> ToBeRemoved; DenseMap<DebugVariable, std::pair<SmallVector<Value *, 4>, DIExpression *>> @@ -642,7 +645,7 @@ static bool removeRedundantDbgInstrsUsingForwardScan(BasicBlock *BB) { /// - Keep track of non-overlapping fragments. static bool removeUndefDbgAssignsFromEntryBlock(BasicBlock *BB) { if (BB->IsNewDbgInfoFormat) - return DPValuesRemoveUndefDbgAssignsFromEntryBlock(BB); + return DbgVariableRecordsRemoveUndefDbgAssignsFromEntryBlock(BB); assert(BB->isEntryBlock() && "expected entry block"); SmallVector<DbgAssignIntrinsic *, 8> ToBeRemoved; diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp index 6931d1997aa6b2d16d301e5fa9e205dd88b2b5e6..3eac726994ae1392d70ee03a3ee1de6a2c5a2373 100644 --- a/llvm/lib/Transforms/Utils/CloneFunction.cpp +++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp @@ -276,8 +276,8 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, // attached debug-info records. for (Instruction &II : *BB) { RemapInstruction(&II, VMap, RemapFlag, TypeMapper, Materializer); - RemapDPValueRange(II.getModule(), II.getDbgRecordRange(), VMap, RemapFlag, - TypeMapper, Materializer); + RemapDbgVariableRecordRange(II.getModule(), II.getDbgRecordRange(), VMap, + RemapFlag, TypeMapper, Materializer); } // Only update !llvm.dbg.cu for DifferentModule (not CloneModule). In the @@ -641,8 +641,8 @@ void PruningFunctionCloner::CloneBlock( // Recursively clone any reachable successor blocks. append_range(ToClone, successors(BB->getTerminator())); } else { - // If we didn't create a new terminator, clone DPValues from the old - // terminator onto the new terminator. + // If we didn't create a new terminator, clone DbgVariableRecords from the + // old terminator onto the new terminator. Instruction *NewInst = NewBB->getTerminator(); assert(NewInst); @@ -884,14 +884,15 @@ void llvm::CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc, TypeMapper, Materializer); } - // Do the same for DPValues, touching all the instructions in the cloned - // range of blocks. + // Do the same for DbgVariableRecords, touching all the instructions in the + // cloned range of blocks. Function::iterator Begin = cast<BasicBlock>(VMap[StartingBB])->getIterator(); for (BasicBlock &BB : make_range(Begin, NewFunc->end())) { for (Instruction &I : BB) { - RemapDPValueRange(I.getModule(), I.getDbgRecordRange(), VMap, - ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges, - TypeMapper, Materializer); + RemapDbgVariableRecordRange(I.getModule(), I.getDbgRecordRange(), VMap, + ModuleLevelChanges ? RF_None + : RF_NoModuleLevelChanges, + TypeMapper, Materializer); } } @@ -990,8 +991,9 @@ void llvm::remapInstructionsInBlocks(ArrayRef<BasicBlock *> Blocks, // Rewrite the code to refer to itself. for (auto *BB : Blocks) { for (auto &Inst : *BB) { - RemapDPValueRange(Inst.getModule(), Inst.getDbgRecordRange(), VMap, - RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); + RemapDbgVariableRecordRange( + Inst.getModule(), Inst.getDbgRecordRange(), VMap, + RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); RemapInstruction(&Inst, VMap, RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); } diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp index 0fac5fc02e3f022b6f49fdf28df07e5f8c9f7265..6988292ac7156174cb05d6013f024eabff403d05 100644 --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -745,7 +745,7 @@ void CodeExtractor::severSplitPHINodesOfEntry(BasicBlock *&Header) { /// and other with remaining incoming blocks; then first PHIs are placed in /// outlined region. void CodeExtractor::severSplitPHINodesOfExits( - const SmallPtrSetImpl<BasicBlock *> &Exits) { + const SetVector<BasicBlock *> &Exits) { for (BasicBlock *ExitBB : Exits) { BasicBlock *NewBB = nullptr; @@ -1010,6 +1010,18 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs, newFunction->addFnAttr(Attr); } + + if (NumExitBlocks == 0) { + // Mark the new function `noreturn` if applicable. Terminators which resume + // exception propagation are treated as returning instructions. This is to + // avoid inserting traps after calls to outlined functions which unwind. + if (none_of(Blocks, [](const BasicBlock *BB) { + const Instruction *Term = BB->getTerminator(); + return isa<ReturnInst>(Term) || isa<ResumeInst>(Term); + })) + newFunction->setDoesNotReturn(); + } + newFunction->insert(newFunction->end(), newRootNode); // Create scalar and aggregate iterators to name all of the arguments we @@ -1392,19 +1404,23 @@ CallInst *CodeExtractor::emitCallAndSwitchStatement(Function *newFunction, case 0: // There are no successors (the block containing the switch itself), which // means that previously this was the last part of the function, and hence - // this should be rewritten as a `ret' - - // Check if the function should return a value - if (OldFnRetTy->isVoidTy()) { - ReturnInst::Create(Context, nullptr, TheSwitch->getIterator()); // Return void + // this should be rewritten as a `ret` or `unreachable`. + if (newFunction->doesNotReturn()) { + // If fn is no return, end with an unreachable terminator. + (void)new UnreachableInst(Context, TheSwitch->getIterator()); + } else if (OldFnRetTy->isVoidTy()) { + // We have no return value. + ReturnInst::Create(Context, nullptr, + TheSwitch->getIterator()); // Return void } else if (OldFnRetTy == TheSwitch->getCondition()->getType()) { // return what we have - ReturnInst::Create(Context, TheSwitch->getCondition(), TheSwitch->getIterator()); + ReturnInst::Create(Context, TheSwitch->getCondition(), + TheSwitch->getIterator()); } else { // Otherwise we must have code extracted an unwind or something, just // return whatever we want. - ReturnInst::Create(Context, - Constant::getNullValue(OldFnRetTy), TheSwitch->getIterator()); + ReturnInst::Create(Context, Constant::getNullValue(OldFnRetTy), + TheSwitch->getIterator()); } TheSwitch->eraseFromParent(); @@ -1508,14 +1524,14 @@ void CodeExtractor::calculateNewCallTerminatorWeights( static void eraseDebugIntrinsicsWithNonLocalRefs(Function &F) { for (Instruction &I : instructions(F)) { SmallVector<DbgVariableIntrinsic *, 4> DbgUsers; - SmallVector<DPValue *, 4> DPValues; - findDbgUsers(DbgUsers, &I, &DPValues); + SmallVector<DbgVariableRecord *, 4> DbgVariableRecords; + findDbgUsers(DbgUsers, &I, &DbgVariableRecords); for (DbgVariableIntrinsic *DVI : DbgUsers) if (DVI->getFunction() != &F) DVI->eraseFromParent(); - for (DPValue *DPV : DPValues) - if (DPV->getFunction() != &F) - DPV->eraseFromParent(); + for (DbgVariableRecord *DVR : DbgVariableRecords) + if (DVR->getFunction() != &F) + DVR->eraseFromParent(); } } @@ -1569,7 +1585,7 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc, // point to a variable in the wrong scope. SmallDenseMap<DINode *, DINode *> RemappedMetadata; SmallVector<Instruction *, 4> DebugIntrinsicsToDelete; - SmallVector<DPValue *, 4> DPVsToDelete; + SmallVector<DbgVariableRecord *, 4> DVRsToDelete; DenseMap<const MDNode *, MDNode *> Cache; auto GetUpdatedDIVariable = [&](DILocalVariable *OldVar) { @@ -1603,24 +1619,24 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc, auto UpdateDbgRecordsOnInst = [&](Instruction &I) -> void { for (DbgRecord &DR : I.getDbgRecordRange()) { - if (DPLabel *DPL = dyn_cast<DPLabel>(&DR)) { - UpdateDbgLabel(DPL); + if (DbgLabelRecord *DLR = dyn_cast<DbgLabelRecord>(&DR)) { + UpdateDbgLabel(DLR); continue; } - DPValue &DPV = cast<DPValue>(DR); + DbgVariableRecord &DVR = cast<DbgVariableRecord>(DR); // Apply the two updates that dbg.values get: invalid operands, and // variable metadata fixup. - if (any_of(DPV.location_ops(), IsInvalidLocation)) { - DPVsToDelete.push_back(&DPV); + if (any_of(DVR.location_ops(), IsInvalidLocation)) { + DVRsToDelete.push_back(&DVR); continue; } - if (DPV.isDbgAssign() && IsInvalidLocation(DPV.getAddress())) { - DPVsToDelete.push_back(&DPV); + if (DVR.isDbgAssign() && IsInvalidLocation(DVR.getAddress())) { + DVRsToDelete.push_back(&DVR); continue; } - if (!DPV.getDebugLoc().getInlinedAt()) - DPV.setVariable(GetUpdatedDIVariable(DPV.getVariable())); + if (!DVR.getDebugLoc().getInlinedAt()) + DVR.setVariable(GetUpdatedDIVariable(DVR.getVariable())); } }; @@ -1658,8 +1674,8 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc, for (auto *DII : DebugIntrinsicsToDelete) DII->eraseFromParent(); - for (auto *DPV : DPVsToDelete) - DPV->getMarker()->MarkedInstr->dropOneDbgRecord(DPV); + for (auto *DVR : DVRsToDelete) + DVR->getMarker()->MarkedInstr->dropOneDbgRecord(DVR); DIB.finalizeSubprogram(NewSP); // Fix up the scope information attached to the line locations in the new @@ -1735,7 +1751,7 @@ CodeExtractor::extractCodeRegion(const CodeExtractorAnalysisCache &CEAC, // Calculate the exit blocks for the extracted region and the total exit // weights for each of those blocks. DenseMap<BasicBlock *, BlockFrequency> ExitWeights; - SmallPtrSet<BasicBlock *, 1> ExitBlocks; + SetVector<BasicBlock *> ExitBlocks; for (BasicBlock *Block : Blocks) { for (BasicBlock *Succ : successors(Block)) { if (!Blocks.count(Succ)) { @@ -1895,16 +1911,6 @@ CodeExtractor::extractCodeRegion(const CodeExtractorAnalysisCache &CEAC, fixupDebugInfoPostExtraction(*oldFunction, *newFunction, *TheCall); - // Mark the new function `noreturn` if applicable. Terminators which resume - // exception propagation are treated as returning instructions. This is to - // avoid inserting traps after calls to outlined functions which unwind. - bool doesNotReturn = none_of(*newFunction, [](const BasicBlock &BB) { - const Instruction *Term = BB.getTerminator(); - return isa<ReturnInst>(Term) || isa<ResumeInst>(Term); - }); - if (doesNotReturn) - newFunction->setDoesNotReturn(); - LLVM_DEBUG(if (verifyFunction(*newFunction, &errs())) { newFunction->dump(); report_fatal_error("verification of newFunction failed!"); diff --git a/llvm/lib/Transforms/Utils/FunctionComparator.cpp b/llvm/lib/Transforms/Utils/FunctionComparator.cpp index 09e19be0d293baa09912368034df3ae9234a3b7f..8cfb8ed07d240ef66142fbebfd34bd86a1c26170 100644 --- a/llvm/lib/Transforms/Utils/FunctionComparator.cpp +++ b/llvm/lib/Transforms/Utils/FunctionComparator.cpp @@ -426,9 +426,19 @@ int FunctionComparator::cmpConstants(const Constant *L, return Res; if (int Res = cmpNumbers(GEPL->isInBounds(), GEPR->isInBounds())) return Res; - if (int Res = cmpNumbers(GEPL->getInRangeIndex().value_or(unsigned(-1)), - GEPR->getInRangeIndex().value_or(unsigned(-1)))) - return Res; + + std::optional<ConstantRange> InRangeL = GEPL->getInRange(); + std::optional<ConstantRange> InRangeR = GEPR->getInRange(); + if (InRangeL) { + if (!InRangeR) + return 1; + if (int Res = cmpAPInts(InRangeL->getLower(), InRangeR->getLower())) + return Res; + if (int Res = cmpAPInts(InRangeL->getUpper(), InRangeR->getUpper())) + return Res; + } else if (InRangeR) { + return -1; + } } if (auto *OBOL = dyn_cast<OverflowingBinaryOperator>(LE)) { auto *OBOR = cast<OverflowingBinaryOperator>(RE); diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp index 1bbe76a92187c8c2b3b6cb748c538d18a3db6541..833dcbec228b88d4fa598b92ea795e8969b315f2 100644 --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -1710,17 +1710,17 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI, }; // Helper-util for updating debug-info records attached to instructions. - auto UpdateDPV = [&](DbgRecord *DPV) { - assert(DPV->getDebugLoc() && "Debug Value must have debug loc"); + auto UpdateDVR = [&](DbgRecord *DVR) { + assert(DVR->getDebugLoc() && "Debug Value must have debug loc"); if (NoInlineLineTables) { - DPV->setDebugLoc(TheCallDL); + DVR->setDebugLoc(TheCallDL); return; } - DebugLoc DL = DPV->getDebugLoc(); + DebugLoc DL = DVR->getDebugLoc(); DebugLoc IDL = inlineDebugLoc(DL, InlinedAtNode, - DPV->getMarker()->getParent()->getContext(), IANodes); - DPV->setDebugLoc(IDL); + DVR->getMarker()->getParent()->getContext(), IANodes); + DVR->setDebugLoc(IDL); }; // Iterate over all instructions, updating metadata and debug-info records. @@ -1728,8 +1728,8 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI, for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) { UpdateInst(*BI); - for (DbgRecord &DPV : BI->getDbgRecordRange()) { - UpdateDPV(&DPV); + for (DbgRecord &DVR : BI->getDbgRecordRange()) { + UpdateDVR(&DVR); } } @@ -1797,7 +1797,7 @@ static at::StorageToVarsMap collectEscapedLocals(const DataLayout &DL, EscapedLocals[Base].insert(at::VarRecord(DbgAssign)); }; for_each(at::getAssignmentMarkers(Base), CollectAssignsForStorage); - for_each(at::getDPVAssignmentMarkers(Base), CollectAssignsForStorage); + for_each(at::getDVRAssignmentMarkers(Base), CollectAssignsForStorage); } return EscapedLocals; } @@ -1829,9 +1829,9 @@ static void fixupAssignments(Function::iterator Start, Function::iterator End) { // attachment or use, replace it with a new version. for (auto BBI = Start; BBI != End; ++BBI) { for (Instruction &I : *BBI) { - for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) { - if (DPV.isDbgAssign()) - DPV.setAssignId(GetNewID(DPV.getAssignID())); + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { + if (DVR.isDbgAssign()) + DVR.setAssignId(GetNewID(DVR.getAssignID())); } if (auto *ID = I.getMetadata(LLVMContext::MD_DIAssignID)) I.setMetadata(LLVMContext::MD_DIAssignID, GetNewID(ID)); diff --git a/llvm/lib/Transforms/Utils/LCSSA.cpp b/llvm/lib/Transforms/Utils/LCSSA.cpp index 5e0c312fe149e73ed9df89086eb44b657528ea21..ab1edf47d8db0a06d1b5669217341c1229597069 100644 --- a/llvm/lib/Transforms/Utils/LCSSA.cpp +++ b/llvm/lib/Transforms/Utils/LCSSA.cpp @@ -242,8 +242,8 @@ bool llvm::formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist, } SmallVector<DbgValueInst *, 4> DbgValues; - SmallVector<DPValue *, 4> DPValues; - llvm::findDbgValues(DbgValues, I, &DPValues); + SmallVector<DbgVariableRecord *, 4> DbgVariableRecords; + llvm::findDbgValues(DbgValues, I, &DbgVariableRecords); // Update pre-existing debug value uses that reside outside the loop. for (auto *DVI : DbgValues) { @@ -261,8 +261,8 @@ bool llvm::formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist, // RemoveDIs: copy-paste of block above, using non-instruction debug-info // records. - for (DPValue *DPV : DPValues) { - BasicBlock *UserBB = DPV->getMarker()->getParent(); + for (DbgVariableRecord *DVR : DbgVariableRecords) { + BasicBlock *UserBB = DVR->getMarker()->getParent(); if (InstBB == UserBB || L->contains(UserBB)) continue; // We currently only handle debug values residing in blocks that were @@ -271,7 +271,7 @@ bool llvm::formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist, Value *V = AddedPHIs.size() == 1 ? AddedPHIs[0] : SSAUpdate.FindValueForBlock(UserBB); if (V) - DPV->replaceVariableLocationOp(I, V); + DVR->replaceVariableLocationOp(I, V); } // SSAUpdater might have inserted phi-nodes inside other loops. We'll need diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index 7b74caac9e0840743eefbb3dcac7a9279d8650ea..380bac9c6180771d3dfe7a72c6deb8b1c4d3859c 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -475,6 +475,12 @@ bool llvm::wouldInstructionBeTriviallyDead(const Instruction *I, II->getIntrinsicID() == Intrinsic::launder_invariant_group) return true; + // Intrinsics declare sideeffects to prevent them from moving, but they are + // nops without users. + if (II->getIntrinsicID() == Intrinsic::allow_runtime_check || + II->getIntrinsicID() == Intrinsic::allow_ubsan_check) + return true; + if (II->isLifetimeStartOrEnd()) { auto *Arg = II->getArgOperand(1); // Lifetime intrinsics are dead when their right-hand is undef. @@ -609,12 +615,12 @@ void llvm::RecursivelyDeleteTriviallyDeadInstructions( bool llvm::replaceDbgUsesWithUndef(Instruction *I) { SmallVector<DbgVariableIntrinsic *, 1> DbgUsers; - SmallVector<DPValue *, 1> DPUsers; + SmallVector<DbgVariableRecord *, 1> DPUsers; findDbgUsers(DbgUsers, I, &DPUsers); for (auto *DII : DbgUsers) DII->setKillLocation(); - for (auto *DPV : DPUsers) - DPV->setKillLocation(); + for (auto *DVR : DPUsers) + DVR->setKillLocation(); return !DbgUsers.empty() || !DPUsers.empty(); } @@ -1570,16 +1576,16 @@ static bool PhiHasDebugValue(DILocalVariable *DIVar, // is removed by LowerDbgDeclare(), we need to make sure that we are // not inserting the same dbg.value intrinsic over and over. SmallVector<DbgValueInst *, 1> DbgValues; - SmallVector<DPValue *, 1> DPValues; - findDbgValues(DbgValues, APN, &DPValues); + SmallVector<DbgVariableRecord *, 1> DbgVariableRecords; + findDbgValues(DbgValues, APN, &DbgVariableRecords); for (auto *DVI : DbgValues) { assert(is_contained(DVI->getValues(), APN)); if ((DVI->getVariable() == DIVar) && (DVI->getExpression() == DIExpr)) return true; } - for (auto *DPV : DPValues) { - assert(is_contained(DPV->location_ops(), APN)); - if ((DPV->getVariable() == DIVar) && (DPV->getExpression() == DIExpr)) + for (auto *DVR : DbgVariableRecords) { + assert(is_contained(DVR->location_ops(), APN)); + if ((DVR->getVariable() == DIVar) && (DVR->getExpression() == DIExpr)) return true; } return false; @@ -1617,23 +1623,23 @@ static bool valueCoversEntireFragment(Type *ValTy, DbgVariableIntrinsic *DII) { // Could not determine size of variable. Conservatively return false. return false; } -// RemoveDIs: duplicate implementation of the above, using DPValues, the -// replacement for dbg.values. -static bool valueCoversEntireFragment(Type *ValTy, DPValue *DPV) { - const DataLayout &DL = DPV->getModule()->getDataLayout(); +// RemoveDIs: duplicate implementation of the above, using DbgVariableRecords, +// the replacement for dbg.values. +static bool valueCoversEntireFragment(Type *ValTy, DbgVariableRecord *DVR) { + const DataLayout &DL = DVR->getModule()->getDataLayout(); TypeSize ValueSize = DL.getTypeAllocSizeInBits(ValTy); - if (std::optional<uint64_t> FragmentSize = DPV->getFragmentSizeInBits()) + if (std::optional<uint64_t> FragmentSize = DVR->getFragmentSizeInBits()) return TypeSize::isKnownGE(ValueSize, TypeSize::getFixed(*FragmentSize)); // We can't always calculate the size of the DI variable (e.g. if it is a // VLA). Try to use the size of the alloca that the dbg intrinsic describes // intead. - if (DPV->isAddressOfVariable()) { - // DPV should have exactly 1 location when it is an address. - assert(DPV->getNumVariableLocationOps() == 1 && + if (DVR->isAddressOfVariable()) { + // DVR should have exactly 1 location when it is an address. + assert(DVR->getNumVariableLocationOps() == 1 && "address of variable must have exactly 1 location operand."); if (auto *AI = - dyn_cast_or_null<AllocaInst>(DPV->getVariableLocationOp(0))) { + dyn_cast_or_null<AllocaInst>(DVR->getVariableLocationOp(0))) { if (std::optional<TypeSize> FragmentSize = AI->getAllocationSizeInBits(DL)) { return TypeSize::isKnownGE(ValueSize, *FragmentSize); } @@ -1643,38 +1649,38 @@ static bool valueCoversEntireFragment(Type *ValTy, DPValue *DPV) { return false; } -static void insertDbgValueOrDPValue(DIBuilder &Builder, Value *DV, - DILocalVariable *DIVar, - DIExpression *DIExpr, - const DebugLoc &NewLoc, - BasicBlock::iterator Instr) { +static void insertDbgValueOrDbgVariableRecord(DIBuilder &Builder, Value *DV, + DILocalVariable *DIVar, + DIExpression *DIExpr, + const DebugLoc &NewLoc, + BasicBlock::iterator Instr) { if (!UseNewDbgInfoFormat) { auto DbgVal = Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, NewLoc, (Instruction *)nullptr); DbgVal.get<Instruction *>()->insertBefore(Instr); } else { // RemoveDIs: if we're using the new debug-info format, allocate a - // DPValue directly instead of a dbg.value intrinsic. + // DbgVariableRecord directly instead of a dbg.value intrinsic. ValueAsMetadata *DVAM = ValueAsMetadata::get(DV); - DPValue *DV = new DPValue(DVAM, DIVar, DIExpr, NewLoc.get()); + DbgVariableRecord *DV = + new DbgVariableRecord(DVAM, DIVar, DIExpr, NewLoc.get()); Instr->getParent()->insertDbgRecordBefore(DV, Instr); } } -static void insertDbgValueOrDPValueAfter(DIBuilder &Builder, Value *DV, - DILocalVariable *DIVar, - DIExpression *DIExpr, - const DebugLoc &NewLoc, - BasicBlock::iterator Instr) { +static void insertDbgValueOrDbgVariableRecordAfter( + DIBuilder &Builder, Value *DV, DILocalVariable *DIVar, DIExpression *DIExpr, + const DebugLoc &NewLoc, BasicBlock::iterator Instr) { if (!UseNewDbgInfoFormat) { auto DbgVal = Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, NewLoc, (Instruction *)nullptr); DbgVal.get<Instruction *>()->insertAfter(&*Instr); } else { // RemoveDIs: if we're using the new debug-info format, allocate a - // DPValue directly instead of a dbg.value intrinsic. + // DbgVariableRecord directly instead of a dbg.value intrinsic. ValueAsMetadata *DVAM = ValueAsMetadata::get(DV); - DPValue *DV = new DPValue(DVAM, DIVar, DIExpr, NewLoc.get()); + DbgVariableRecord *DV = + new DbgVariableRecord(DVAM, DIVar, DIExpr, NewLoc.get()); Instr->getParent()->insertDbgRecordAfter(DV, &*Instr); } } @@ -1707,8 +1713,8 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, DIExpr->isDeref() || (!DIExpr->startsWithDeref() && valueCoversEntireFragment(DV->getType(), DII)); if (CanConvert) { - insertDbgValueOrDPValue(Builder, DV, DIVar, DIExpr, NewLoc, - SI->getIterator()); + insertDbgValueOrDbgVariableRecord(Builder, DV, DIVar, DIExpr, NewLoc, + SI->getIterator()); return; } @@ -1720,8 +1726,8 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, // know which part) we insert an dbg.value intrinsic to indicate that we // know nothing about the variable's content. DV = UndefValue::get(DV->getType()); - insertDbgValueOrDPValue(Builder, DV, DIVar, DIExpr, NewLoc, - SI->getIterator()); + insertDbgValueOrDbgVariableRecord(Builder, DV, DIVar, DIExpr, NewLoc, + SI->getIterator()); } /// Inserts a llvm.dbg.value intrinsic before a load of an alloca'd value @@ -1747,19 +1753,19 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, // future if multi-location support is added to the IR, it might be // preferable to keep tracking both the loaded value and the original // address in case the alloca can not be elided. - insertDbgValueOrDPValueAfter(Builder, LI, DIVar, DIExpr, NewLoc, - LI->getIterator()); + insertDbgValueOrDbgVariableRecordAfter(Builder, LI, DIVar, DIExpr, NewLoc, + LI->getIterator()); } -void llvm::ConvertDebugDeclareToDebugValue(DPValue *DPV, StoreInst *SI, - DIBuilder &Builder) { - assert(DPV->isAddressOfVariable() || DPV->isDbgAssign()); - auto *DIVar = DPV->getVariable(); +void llvm::ConvertDebugDeclareToDebugValue(DbgVariableRecord *DVR, + StoreInst *SI, DIBuilder &Builder) { + assert(DVR->isAddressOfVariable() || DVR->isDbgAssign()); + auto *DIVar = DVR->getVariable(); assert(DIVar && "Missing variable"); - auto *DIExpr = DPV->getExpression(); + auto *DIExpr = DVR->getExpression(); Value *DV = SI->getValueOperand(); - DebugLoc NewLoc = getDebugValueLoc(DPV); + DebugLoc NewLoc = getDebugValueLoc(DVR); // If the alloca describes the variable itself, i.e. the expression in the // dbg.declare doesn't start with a dereference, we can perform the @@ -1775,16 +1781,16 @@ void llvm::ConvertDebugDeclareToDebugValue(DPValue *DPV, StoreInst *SI, // deref expression. bool CanConvert = DIExpr->isDeref() || (!DIExpr->startsWithDeref() && - valueCoversEntireFragment(DV->getType(), DPV)); + valueCoversEntireFragment(DV->getType(), DVR)); if (CanConvert) { - insertDbgValueOrDPValue(Builder, DV, DIVar, DIExpr, NewLoc, - SI->getIterator()); + insertDbgValueOrDbgVariableRecord(Builder, DV, DIVar, DIExpr, NewLoc, + SI->getIterator()); return; } // FIXME: If storing to a part of the variable described by the dbg.declare, // then we want to insert a dbg.value for the corresponding fragment. - LLVM_DEBUG(dbgs() << "Failed to convert dbg.declare to dbg.value: " << *DPV + LLVM_DEBUG(dbgs() << "Failed to convert dbg.declare to dbg.value: " << *DVR << '\n'); assert(UseNewDbgInfoFormat); @@ -1793,8 +1799,9 @@ void llvm::ConvertDebugDeclareToDebugValue(DPValue *DPV, StoreInst *SI, // know nothing about the variable's content. DV = UndefValue::get(DV->getType()); ValueAsMetadata *DVAM = ValueAsMetadata::get(DV); - DPValue *NewDPV = new DPValue(DVAM, DIVar, DIExpr, NewLoc.get()); - SI->getParent()->insertDbgRecordBefore(NewDPV, SI->getIterator()); + DbgVariableRecord *NewDVR = + new DbgVariableRecord(DVAM, DIVar, DIExpr, NewLoc.get()); + SI->getParent()->insertDbgRecordBefore(NewDVR, SI->getIterator()); } /// Inserts a llvm.dbg.value intrinsic after a phi that has an associated @@ -1826,26 +1833,27 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, // insertion point. // FIXME: Insert dbg.value markers in the successors when appropriate. if (InsertionPt != BB->end()) { - insertDbgValueOrDPValue(Builder, APN, DIVar, DIExpr, NewLoc, InsertionPt); + insertDbgValueOrDbgVariableRecord(Builder, APN, DIVar, DIExpr, NewLoc, + InsertionPt); } } -void llvm::ConvertDebugDeclareToDebugValue(DPValue *DPV, LoadInst *LI, +void llvm::ConvertDebugDeclareToDebugValue(DbgVariableRecord *DVR, LoadInst *LI, DIBuilder &Builder) { - auto *DIVar = DPV->getVariable(); - auto *DIExpr = DPV->getExpression(); + auto *DIVar = DVR->getVariable(); + auto *DIExpr = DVR->getExpression(); assert(DIVar && "Missing variable"); - if (!valueCoversEntireFragment(LI->getType(), DPV)) { + if (!valueCoversEntireFragment(LI->getType(), DVR)) { // FIXME: If only referring to a part of the variable described by the - // dbg.declare, then we want to insert a DPValue for the corresponding - // fragment. - LLVM_DEBUG(dbgs() << "Failed to convert dbg.declare to DPValue: " << *DPV - << '\n'); + // dbg.declare, then we want to insert a DbgVariableRecord for the + // corresponding fragment. + LLVM_DEBUG(dbgs() << "Failed to convert dbg.declare to DbgVariableRecord: " + << *DVR << '\n'); return; } - DebugLoc NewLoc = getDebugValueLoc(DPV); + DebugLoc NewLoc = getDebugValueLoc(DVR); // We are now tracking the loaded value instead of the address. In the // future if multi-location support is added to the IR, it might be @@ -1853,9 +1861,10 @@ void llvm::ConvertDebugDeclareToDebugValue(DPValue *DPV, LoadInst *LI, // address in case the alloca can not be elided. assert(UseNewDbgInfoFormat); - // Create a DPValue directly and insert. + // Create a DbgVariableRecord directly and insert. ValueAsMetadata *LIVAM = ValueAsMetadata::get(LI); - DPValue *DV = new DPValue(LIVAM, DIVar, DIExpr, NewLoc.get()); + DbgVariableRecord *DV = + new DbgVariableRecord(LIVAM, DIVar, DIExpr, NewLoc.get()); LI->getParent()->insertDbgRecordAfter(DV, LI); } @@ -1869,34 +1878,35 @@ static bool isArray(AllocaInst *AI) { static bool isStructure(AllocaInst *AI) { return AI->getAllocatedType() && AI->getAllocatedType()->isStructTy(); } -void llvm::ConvertDebugDeclareToDebugValue(DPValue *DPV, PHINode *APN, +void llvm::ConvertDebugDeclareToDebugValue(DbgVariableRecord *DVR, PHINode *APN, DIBuilder &Builder) { - auto *DIVar = DPV->getVariable(); - auto *DIExpr = DPV->getExpression(); + auto *DIVar = DVR->getVariable(); + auto *DIExpr = DVR->getExpression(); assert(DIVar && "Missing variable"); if (PhiHasDebugValue(DIVar, DIExpr, APN)) return; - if (!valueCoversEntireFragment(APN->getType(), DPV)) { + if (!valueCoversEntireFragment(APN->getType(), DVR)) { // FIXME: If only referring to a part of the variable described by the - // dbg.declare, then we want to insert a DPValue for the corresponding - // fragment. - LLVM_DEBUG(dbgs() << "Failed to convert dbg.declare to DPValue: " << *DPV - << '\n'); + // dbg.declare, then we want to insert a DbgVariableRecord for the + // corresponding fragment. + LLVM_DEBUG(dbgs() << "Failed to convert dbg.declare to DbgVariableRecord: " + << *DVR << '\n'); return; } BasicBlock *BB = APN->getParent(); auto InsertionPt = BB->getFirstInsertionPt(); - DebugLoc NewLoc = getDebugValueLoc(DPV); + DebugLoc NewLoc = getDebugValueLoc(DVR); // The block may be a catchswitch block, which does not have a valid // insertion point. - // FIXME: Insert DPValue markers in the successors when appropriate. + // FIXME: Insert DbgVariableRecord markers in the successors when appropriate. if (InsertionPt != BB->end()) { - insertDbgValueOrDPValue(Builder, APN, DIVar, DIExpr, NewLoc, InsertionPt); + insertDbgValueOrDbgVariableRecord(Builder, APN, DIVar, DIExpr, NewLoc, + InsertionPt); } } @@ -1906,19 +1916,19 @@ bool llvm::LowerDbgDeclare(Function &F) { bool Changed = false; DIBuilder DIB(*F.getParent(), /*AllowUnresolved*/ false); SmallVector<DbgDeclareInst *, 4> Dbgs; - SmallVector<DPValue *> DPVs; + SmallVector<DbgVariableRecord *> DVRs; for (auto &FI : F) { for (Instruction &BI : FI) { if (auto *DDI = dyn_cast<DbgDeclareInst>(&BI)) Dbgs.push_back(DDI); - for (DPValue &DPV : DPValue::filter(BI.getDbgRecordRange())) { - if (DPV.getType() == DPValue::LocationType::Declare) - DPVs.push_back(&DPV); + for (DbgVariableRecord &DVR : filterDbgVars(BI.getDbgRecordRange())) { + if (DVR.getType() == DbgVariableRecord::LocationType::Declare) + DVRs.push_back(&DVR); } } } - if (Dbgs.empty() && DPVs.empty()) + if (Dbgs.empty() && DVRs.empty()) return Changed; auto LowerOne = [&](auto *DDI) { @@ -1962,8 +1972,9 @@ bool llvm::LowerDbgDeclare(Function &F) { DebugLoc NewLoc = getDebugValueLoc(DDI); auto *DerefExpr = DIExpression::append(DDI->getExpression(), dwarf::DW_OP_deref); - insertDbgValueOrDPValue(DIB, AI, DDI->getVariable(), DerefExpr, - NewLoc, CI->getIterator()); + insertDbgValueOrDbgVariableRecord(DIB, AI, DDI->getVariable(), + DerefExpr, NewLoc, + CI->getIterator()); } } else if (BitCastInst *BI = dyn_cast<BitCastInst>(U)) { if (BI->getType()->isPointerTy()) @@ -1976,7 +1987,7 @@ bool llvm::LowerDbgDeclare(Function &F) { }; for_each(Dbgs, LowerOne); - for_each(DPVs, LowerOne); + for_each(DVRs, LowerOne); if (Changed) for (BasicBlock &BB : F) @@ -1986,35 +1997,39 @@ bool llvm::LowerDbgDeclare(Function &F) { } // RemoveDIs: re-implementation of insertDebugValuesForPHIs, but which pulls the -// debug-info out of the block's DPValues rather than dbg.value intrinsics. -static void insertDPValuesForPHIs(BasicBlock *BB, - SmallVectorImpl<PHINode *> &InsertedPHIs) { - assert(BB && "No BasicBlock to clone DPValue(s) from."); +// debug-info out of the block's DbgVariableRecords rather than dbg.value +// intrinsics. +static void +insertDbgVariableRecordsForPHIs(BasicBlock *BB, + SmallVectorImpl<PHINode *> &InsertedPHIs) { + assert(BB && "No BasicBlock to clone DbgVariableRecord(s) from."); if (InsertedPHIs.size() == 0) return; - // Map existing PHI nodes to their DPValues. - DenseMap<Value *, DPValue *> DbgValueMap; + // Map existing PHI nodes to their DbgVariableRecords. + DenseMap<Value *, DbgVariableRecord *> DbgValueMap; for (auto &I : *BB) { - for (DPValue &DPV : DPValue::filter(I.getDbgRecordRange())) { - for (Value *V : DPV.location_ops()) + for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { + for (Value *V : DVR.location_ops()) if (auto *Loc = dyn_cast_or_null<PHINode>(V)) - DbgValueMap.insert({Loc, &DPV}); + DbgValueMap.insert({Loc, &DVR}); } } if (DbgValueMap.size() == 0) return; - // Map a pair of the destination BB and old DPValue to the new DPValue, - // so that if a DPValue is being rewritten to use more than one of the - // inserted PHIs in the same destination BB, we can update the same DPValue - // with all the new PHIs instead of creating one copy for each. - MapVector<std::pair<BasicBlock *, DPValue *>, DPValue *> NewDbgValueMap; + // Map a pair of the destination BB and old DbgVariableRecord to the new + // DbgVariableRecord, so that if a DbgVariableRecord is being rewritten to use + // more than one of the inserted PHIs in the same destination BB, we can + // update the same DbgVariableRecord with all the new PHIs instead of creating + // one copy for each. + MapVector<std::pair<BasicBlock *, DbgVariableRecord *>, DbgVariableRecord *> + NewDbgValueMap; // Then iterate through the new PHIs and look to see if they use one of the - // previously mapped PHIs. If so, create a new DPValue that will propagate - // the info through the new PHI. If we use more than one new PHI in a single - // destination BB with the same old dbg.value, merge the updates so that we - // get a single new DPValue with all the new PHIs. + // previously mapped PHIs. If so, create a new DbgVariableRecord that will + // propagate the info through the new PHI. If we use more than one new PHI in + // a single destination BB with the same old dbg.value, merge the updates so + // that we get a single new DbgVariableRecord with all the new PHIs. for (auto PHI : InsertedPHIs) { BasicBlock *Parent = PHI->getParent(); // Avoid inserting a debug-info record into an EH block. @@ -2023,13 +2038,13 @@ static void insertDPValuesForPHIs(BasicBlock *BB, for (auto VI : PHI->operand_values()) { auto V = DbgValueMap.find(VI); if (V != DbgValueMap.end()) { - DPValue *DbgII = cast<DPValue>(V->second); + DbgVariableRecord *DbgII = cast<DbgVariableRecord>(V->second); auto NewDI = NewDbgValueMap.find({Parent, DbgII}); if (NewDI == NewDbgValueMap.end()) { - DPValue *NewDbgII = DbgII->clone(); + DbgVariableRecord *NewDbgII = DbgII->clone(); NewDI = NewDbgValueMap.insert({{Parent, DbgII}, NewDbgII}).first; } - DPValue *NewDbgII = NewDI->second; + DbgVariableRecord *NewDbgII = NewDI->second; // If PHI contains VI as an operand more than once, we may // replaced it in NewDbgII; confirm that it is present. if (is_contained(NewDbgII->location_ops(), VI)) @@ -2037,10 +2052,10 @@ static void insertDPValuesForPHIs(BasicBlock *BB, } } } - // Insert the new DPValues into their destination blocks. + // Insert the new DbgVariableRecords into their destination blocks. for (auto DI : NewDbgValueMap) { BasicBlock *Parent = DI.first.first; - DPValue *NewDbgII = DI.second; + DbgVariableRecord *NewDbgII = DI.second; auto InsertionPt = Parent->getFirstInsertionPt(); assert(InsertionPt != Parent->end() && "Ill-formed basic block"); @@ -2055,7 +2070,7 @@ void llvm::insertDebugValuesForPHIs(BasicBlock *BB, if (InsertedPHIs.size() == 0) return; - insertDPValuesForPHIs(BB, InsertedPHIs); + insertDbgVariableRecordsForPHIs(BB, InsertedPHIs); // Map existing PHI nodes to their dbg.values. ValueToValueMapTy DbgValueMap; @@ -2117,7 +2132,7 @@ bool llvm::replaceDbgDeclare(Value *Address, Value *NewAddress, DIBuilder &Builder, uint8_t DIExprFlags, int Offset) { TinyPtrVector<DbgDeclareInst *> DbgDeclares = findDbgDeclares(Address); - TinyPtrVector<DPValue *> DPVDeclares = findDPVDeclares(Address); + TinyPtrVector<DbgVariableRecord *> DVRDeclares = findDVRDeclares(Address); auto ReplaceOne = [&](auto *DII) { assert(DII->getVariable() && "Missing variable"); @@ -2128,21 +2143,22 @@ bool llvm::replaceDbgDeclare(Value *Address, Value *NewAddress, }; for_each(DbgDeclares, ReplaceOne); - for_each(DPVDeclares, ReplaceOne); + for_each(DVRDeclares, ReplaceOne); - return !DbgDeclares.empty() || !DPVDeclares.empty(); + return !DbgDeclares.empty() || !DVRDeclares.empty(); } static void updateOneDbgValueForAlloca(const DebugLoc &Loc, DILocalVariable *DIVar, DIExpression *DIExpr, Value *NewAddress, - DbgValueInst *DVI, DPValue *DPV, + DbgValueInst *DVI, + DbgVariableRecord *DVR, DIBuilder &Builder, int Offset) { assert(DIVar && "Missing variable"); - // This is an alloca-based dbg.value/DPValue. The first thing it should do - // with the alloca pointer is dereference it. Otherwise we don't know how to - // handle it and give up. + // This is an alloca-based dbg.value/DbgVariableRecord. The first thing it + // should do with the alloca pointer is dereference it. Otherwise we don't + // know how to handle it and give up. if (!DIExpr || DIExpr->getNumElements() < 1 || DIExpr->getElement(0) != dwarf::DW_OP_deref) return; @@ -2155,16 +2171,16 @@ static void updateOneDbgValueForAlloca(const DebugLoc &Loc, DVI->setExpression(DIExpr); DVI->replaceVariableLocationOp(0u, NewAddress); } else { - assert(DPV); - DPV->setExpression(DIExpr); - DPV->replaceVariableLocationOp(0u, NewAddress); + assert(DVR); + DVR->setExpression(DIExpr); + DVR->replaceVariableLocationOp(0u, NewAddress); } } void llvm::replaceDbgValueForAlloca(AllocaInst *AI, Value *NewAllocaAddress, DIBuilder &Builder, int Offset) { SmallVector<DbgValueInst *, 1> DbgUsers; - SmallVector<DPValue *, 1> DPUsers; + SmallVector<DbgVariableRecord *, 1> DPUsers; findDbgValues(DbgUsers, AI, &DPUsers); // Attempt to replace dbg.values that use this alloca. @@ -2173,18 +2189,18 @@ void llvm::replaceDbgValueForAlloca(AllocaInst *AI, Value *NewAllocaAddress, DVI->getExpression(), NewAllocaAddress, DVI, nullptr, Builder, Offset); - // Replace any DPValues that use this alloca. - for (DPValue *DPV : DPUsers) - updateOneDbgValueForAlloca(DPV->getDebugLoc(), DPV->getVariable(), - DPV->getExpression(), NewAllocaAddress, nullptr, - DPV, Builder, Offset); + // Replace any DbgVariableRecords that use this alloca. + for (DbgVariableRecord *DVR : DPUsers) + updateOneDbgValueForAlloca(DVR->getDebugLoc(), DVR->getVariable(), + DVR->getExpression(), NewAllocaAddress, nullptr, + DVR, Builder, Offset); } /// Where possible to salvage debug information for \p I do so. /// If not possible mark undef. void llvm::salvageDebugInfo(Instruction &I) { SmallVector<DbgVariableIntrinsic *, 1> DbgUsers; - SmallVector<DPValue *, 1> DPUsers; + SmallVector<DbgVariableRecord *, 1> DPUsers; findDbgUsers(DbgUsers, &I, &DPUsers); salvageDebugInfoForDbgValues(I, DbgUsers, DPUsers); } @@ -2224,7 +2240,7 @@ template <typename T> static void salvageDbgAssignAddress(T *Assign) { void llvm::salvageDebugInfoForDbgValues( Instruction &I, ArrayRef<DbgVariableIntrinsic *> DbgUsers, - ArrayRef<DPValue *> DPUsers) { + ArrayRef<DbgVariableRecord *> DPUsers) { // These are arbitrary chosen limits on the maximum number of values and the // maximum size of a debug expression we can salvage up to, used for // performance reasons. @@ -2290,67 +2306,68 @@ void llvm::salvageDebugInfoForDbgValues( LLVM_DEBUG(dbgs() << "SALVAGE: " << *DII << '\n'); Salvaged = true; } - // Duplicate of above block for DPValues. - for (auto *DPV : DPUsers) { - if (DPV->isDbgAssign()) { - if (DPV->getAddress() == &I) { - salvageDbgAssignAddress(DPV); + // Duplicate of above block for DbgVariableRecords. + for (auto *DVR : DPUsers) { + if (DVR->isDbgAssign()) { + if (DVR->getAddress() == &I) { + salvageDbgAssignAddress(DVR); Salvaged = true; } - if (DPV->getValue() != &I) + if (DVR->getValue() != &I) continue; } // Do not add DW_OP_stack_value for DbgDeclare and DbgAddr, because they // are implicitly pointing out the value as a DWARF memory location // description. - bool StackValue = DPV->getType() != DPValue::LocationType::Declare; - auto DPVLocation = DPV->location_ops(); + bool StackValue = + DVR->getType() != DbgVariableRecord::LocationType::Declare; + auto DVRLocation = DVR->location_ops(); assert( - is_contained(DPVLocation, &I) && + is_contained(DVRLocation, &I) && "DbgVariableIntrinsic must use salvaged instruction as its location"); SmallVector<Value *, 4> AdditionalValues; - // 'I' may appear more than once in DPV's location ops, and each use of 'I' + // 'I' may appear more than once in DVR's location ops, and each use of 'I' // must be updated in the DIExpression and potentially have additional // values added; thus we call salvageDebugInfoImpl for each 'I' instance in - // DPVLocation. + // DVRLocation. Value *Op0 = nullptr; - DIExpression *SalvagedExpr = DPV->getExpression(); - auto LocItr = find(DPVLocation, &I); - while (SalvagedExpr && LocItr != DPVLocation.end()) { + DIExpression *SalvagedExpr = DVR->getExpression(); + auto LocItr = find(DVRLocation, &I); + while (SalvagedExpr && LocItr != DVRLocation.end()) { SmallVector<uint64_t, 16> Ops; - unsigned LocNo = std::distance(DPVLocation.begin(), LocItr); + unsigned LocNo = std::distance(DVRLocation.begin(), LocItr); uint64_t CurrentLocOps = SalvagedExpr->getNumLocationOperands(); Op0 = salvageDebugInfoImpl(I, CurrentLocOps, Ops, AdditionalValues); if (!Op0) break; SalvagedExpr = DIExpression::appendOpsToArg(SalvagedExpr, Ops, LocNo, StackValue); - LocItr = std::find(++LocItr, DPVLocation.end(), &I); + LocItr = std::find(++LocItr, DVRLocation.end(), &I); } // salvageDebugInfoImpl should fail on examining the first element of // DbgUsers, or none of them. if (!Op0) break; - DPV->replaceVariableLocationOp(&I, Op0); + DVR->replaceVariableLocationOp(&I, Op0); bool IsValidSalvageExpr = SalvagedExpr->getNumElements() <= MaxExpressionSize; if (AdditionalValues.empty() && IsValidSalvageExpr) { - DPV->setExpression(SalvagedExpr); - } else if (DPV->getType() != DPValue::LocationType::Declare && + DVR->setExpression(SalvagedExpr); + } else if (DVR->getType() != DbgVariableRecord::LocationType::Declare && IsValidSalvageExpr && - DPV->getNumVariableLocationOps() + AdditionalValues.size() <= + DVR->getNumVariableLocationOps() + AdditionalValues.size() <= MaxDebugArgs) { - DPV->addVariableLocationOps(AdditionalValues, SalvagedExpr); + DVR->addVariableLocationOps(AdditionalValues, SalvagedExpr); } else { // Do not salvage using DIArgList for dbg.addr/dbg.declare, as it is // currently only valid for stack value expressions. // Also do not salvage if the resulting DIArgList would contain an // unreasonably large number of values. - DPV->setKillLocation(); + DVR->setKillLocation(); } - LLVM_DEBUG(dbgs() << "SALVAGE: " << DPV << '\n'); + LLVM_DEBUG(dbgs() << "SALVAGE: " << DVR << '\n'); Salvaged = true; } @@ -2360,8 +2377,8 @@ void llvm::salvageDebugInfoForDbgValues( for (auto *DII : DbgUsers) DII->setKillLocation(); - for (auto *DPV : DPUsers) - DPV->setKillLocation(); + for (auto *DVR : DPUsers) + DVR->setKillLocation(); } Value *getSalvageOpsForGEP(GetElementPtrInst *GEP, const DataLayout &DL, @@ -2577,10 +2594,10 @@ using DbgValReplacement = std::optional<DIExpression *>; static bool rewriteDebugUsers( Instruction &From, Value &To, Instruction &DomPoint, DominatorTree &DT, function_ref<DbgValReplacement(DbgVariableIntrinsic &DII)> RewriteExpr, - function_ref<DbgValReplacement(DPValue &DPV)> RewriteDPVExpr) { + function_ref<DbgValReplacement(DbgVariableRecord &DVR)> RewriteDVRExpr) { // Find debug users of From. SmallVector<DbgVariableIntrinsic *, 1> Users; - SmallVector<DPValue *, 1> DPUsers; + SmallVector<DbgVariableRecord *, 1> DPUsers; findDbgUsers(Users, &From, &DPUsers); if (Users.empty() && DPUsers.empty()) return false; @@ -2589,7 +2606,7 @@ static bool rewriteDebugUsers( bool Changed = false; SmallPtrSet<DbgVariableIntrinsic *, 1> UndefOrSalvage; - SmallPtrSet<DPValue *, 1> UndefOrSalvageDPV; + SmallPtrSet<DbgVariableRecord *, 1> UndefOrSalvageDVR; if (isa<Instruction>(&To)) { bool DomPointAfterFrom = From.getNextNonDebugInstruction() == &DomPoint; @@ -2608,22 +2625,22 @@ static bool rewriteDebugUsers( } } - // DPValue implementation of the above. - for (auto *DPV : DPUsers) { - Instruction *MarkedInstr = DPV->getMarker()->MarkedInstr; + // DbgVariableRecord implementation of the above. + for (auto *DVR : DPUsers) { + Instruction *MarkedInstr = DVR->getMarker()->MarkedInstr; Instruction *NextNonDebug = MarkedInstr; // The next instruction might still be a dbg.declare, skip over it. if (isa<DbgVariableIntrinsic>(NextNonDebug)) NextNonDebug = NextNonDebug->getNextNonDebugInstruction(); if (DomPointAfterFrom && NextNonDebug == &DomPoint) { - LLVM_DEBUG(dbgs() << "MOVE: " << *DPV << '\n'); - DPV->removeFromParent(); + LLVM_DEBUG(dbgs() << "MOVE: " << *DVR << '\n'); + DVR->removeFromParent(); // Ensure there's a marker. - DomPoint.getParent()->insertDbgRecordAfter(DPV, &DomPoint); + DomPoint.getParent()->insertDbgRecordAfter(DVR, &DomPoint); Changed = true; } else if (!DT.dominates(&DomPoint, MarkedInstr)) { - UndefOrSalvageDPV.insert(DPV); + UndefOrSalvageDVR.insert(DVR); } } } @@ -2633,30 +2650,30 @@ static bool rewriteDebugUsers( if (UndefOrSalvage.count(DII)) continue; - DbgValReplacement DVR = RewriteExpr(*DII); - if (!DVR) + DbgValReplacement DVRepl = RewriteExpr(*DII); + if (!DVRepl) continue; DII->replaceVariableLocationOp(&From, &To); - DII->setExpression(*DVR); + DII->setExpression(*DVRepl); LLVM_DEBUG(dbgs() << "REWRITE: " << *DII << '\n'); Changed = true; } - for (auto *DPV : DPUsers) { - if (UndefOrSalvageDPV.count(DPV)) + for (auto *DVR : DPUsers) { + if (UndefOrSalvageDVR.count(DVR)) continue; - DbgValReplacement DVR = RewriteDPVExpr(*DPV); - if (!DVR) + DbgValReplacement DVRepl = RewriteDVRExpr(*DVR); + if (!DVRepl) continue; - DPV->replaceVariableLocationOp(&From, &To); - DPV->setExpression(*DVR); - LLVM_DEBUG(dbgs() << "REWRITE: " << DPV << '\n'); + DVR->replaceVariableLocationOp(&From, &To); + DVR->setExpression(*DVRepl); + LLVM_DEBUG(dbgs() << "REWRITE: " << DVR << '\n'); Changed = true; } - if (!UndefOrSalvage.empty() || !UndefOrSalvageDPV.empty()) { + if (!UndefOrSalvage.empty() || !UndefOrSalvageDVR.empty()) { // Try to salvage the remaining debug users. salvageDebugInfo(From); Changed = true; @@ -2704,15 +2721,15 @@ bool llvm::replaceAllDbgUsesWith(Instruction &From, Value &To, auto Identity = [&](DbgVariableIntrinsic &DII) -> DbgValReplacement { return DII.getExpression(); }; - auto IdentityDPV = [&](DPValue &DPV) -> DbgValReplacement { - return DPV.getExpression(); + auto IdentityDVR = [&](DbgVariableRecord &DVR) -> DbgValReplacement { + return DVR.getExpression(); }; // Handle no-op conversions. Module &M = *From.getModule(); const DataLayout &DL = M.getDataLayout(); if (isBitCastSemanticsPreserving(DL, FromTy, ToTy)) - return rewriteDebugUsers(From, To, DomPoint, DT, Identity, IdentityDPV); + return rewriteDebugUsers(From, To, DomPoint, DT, Identity, IdentityDVR); // Handle integer-to-integer widening and narrowing. // FIXME: Use DW_OP_convert when it's available everywhere. @@ -2724,7 +2741,7 @@ bool llvm::replaceAllDbgUsesWith(Instruction &From, Value &To, // When the width of the result grows, assume that a debugger will only // access the low `FromBits` bits when inspecting the source variable. if (FromBits < ToBits) - return rewriteDebugUsers(From, To, DomPoint, DT, Identity, IdentityDPV); + return rewriteDebugUsers(From, To, DomPoint, DT, Identity, IdentityDVR); // The width of the result has shrunk. Use sign/zero extension to describe // the source variable's high bits. @@ -2740,10 +2757,10 @@ bool llvm::replaceAllDbgUsesWith(Instruction &From, Value &To, return DIExpression::appendExt(DII.getExpression(), ToBits, FromBits, Signed); }; - // RemoveDIs: duplicate implementation working on DPValues rather than on - // dbg.value intrinsics. - auto SignOrZeroExtDPV = [&](DPValue &DPV) -> DbgValReplacement { - DILocalVariable *Var = DPV.getVariable(); + // RemoveDIs: duplicate implementation working on DbgVariableRecords rather + // than on dbg.value intrinsics. + auto SignOrZeroExtDVR = [&](DbgVariableRecord &DVR) -> DbgValReplacement { + DILocalVariable *Var = DVR.getVariable(); // Without knowing signedness, sign/zero extension isn't possible. auto Signedness = Var->getSignedness(); @@ -2751,11 +2768,11 @@ bool llvm::replaceAllDbgUsesWith(Instruction &From, Value &To, return std::nullopt; bool Signed = *Signedness == DIBasicType::Signedness::Signed; - return DIExpression::appendExt(DPV.getExpression(), ToBits, FromBits, + return DIExpression::appendExt(DVR.getExpression(), ToBits, FromBits, Signed); }; return rewriteDebugUsers(From, To, DomPoint, DT, SignOrZeroExt, - SignOrZeroExtDPV); + SignOrZeroExtDVR); } // TODO: Floating-point conversions, vectors. @@ -2795,8 +2812,8 @@ llvm::removeAllNonTerminatorAndEHPadInstructions(BasicBlock *BB) { if (!Inst->use_empty() && !Inst->getType()->isTokenTy()) Inst->replaceAllUsesWith(PoisonValue::get(Inst->getType())); if (Inst->isEHPad() || Inst->getType()->isTokenTy()) { - // EHPads can't have DPValues attached to them, but it might be possible - // for things with token type. + // EHPads can't have DbgVariableRecords attached to them, but it might be + // possible for things with token type. Inst->dropDbgRecords(); EndInst = Inst; continue; @@ -2848,7 +2865,7 @@ unsigned llvm::changeToUnreachable(Instruction *I, bool PreserveLCSSA, Updates.push_back({DominatorTree::Delete, BB, UniqueSuccessor}); DTU->applyUpdates(Updates); } - BB->flushTerminatorDbgValues(); + BB->flushTerminatorDbgRecords(); return NumInstrsRemoved; } @@ -3544,12 +3561,12 @@ void llvm::copyRangeMetadata(const DataLayout &DL, const LoadInst &OldLI, void llvm::dropDebugUsers(Instruction &I) { SmallVector<DbgVariableIntrinsic *, 1> DbgUsers; - SmallVector<DPValue *, 1> DPUsers; + SmallVector<DbgVariableRecord *, 1> DPUsers; findDbgUsers(DbgUsers, &I, &DPUsers); for (auto *DII : DbgUsers) DII->eraseFromParent(); - for (auto *DPV : DPUsers) - DPV->eraseFromParent(); + for (auto *DVR : DPUsers) + DVR->eraseFromParent(); } void llvm::hoistAllInstructionsInto(BasicBlock *DomBlock, Instruction *InsertPt, diff --git a/llvm/lib/Transforms/Utils/LoopConstrainer.cpp b/llvm/lib/Transforms/Utils/LoopConstrainer.cpp index 81545ef375219c3ddc2093ca95b191166a089ae6..d9832eeb0697e6ebf84399d3d0c61f8f8fcac130 100644 --- a/llvm/lib/Transforms/Utils/LoopConstrainer.cpp +++ b/llvm/lib/Transforms/Utils/LoopConstrainer.cpp @@ -42,8 +42,11 @@ static bool isSafeDecreasingBound(const SCEV *Start, const SCEV *BoundSCEV, ICmpInst::Predicate BoundPred = IsSigned ? CmpInst::ICMP_SGT : CmpInst::ICMP_UGT; + auto StartLG = SE.applyLoopGuards(Start, L); + auto BoundLG = SE.applyLoopGuards(BoundSCEV, L); + if (LatchBrExitIdx == 1) - return SE.isLoopEntryGuardedByCond(L, BoundPred, Start, BoundSCEV); + return SE.isLoopEntryGuardedByCond(L, BoundPred, StartLG, BoundLG); assert(LatchBrExitIdx == 0 && "LatchBrExitIdx should be either 0 or 1"); @@ -54,10 +57,10 @@ static bool isSafeDecreasingBound(const SCEV *Start, const SCEV *BoundSCEV, const SCEV *Limit = SE.getMinusSCEV(SE.getConstant(Min), StepPlusOne); const SCEV *MinusOne = - SE.getMinusSCEV(BoundSCEV, SE.getOne(BoundSCEV->getType())); + SE.getMinusSCEV(BoundLG, SE.getOne(BoundLG->getType())); - return SE.isLoopEntryGuardedByCond(L, BoundPred, Start, MinusOne) && - SE.isLoopEntryGuardedByCond(L, BoundPred, BoundSCEV, Limit); + return SE.isLoopEntryGuardedByCond(L, BoundPred, StartLG, MinusOne) && + SE.isLoopEntryGuardedByCond(L, BoundPred, BoundLG, Limit); } /// Given a loop with an increasing induction variable, is it possible to @@ -86,8 +89,11 @@ static bool isSafeIncreasingBound(const SCEV *Start, const SCEV *BoundSCEV, ICmpInst::Predicate BoundPred = IsSigned ? CmpInst::ICMP_SLT : CmpInst::ICMP_ULT; + auto StartLG = SE.applyLoopGuards(Start, L); + auto BoundLG = SE.applyLoopGuards(BoundSCEV, L); + if (LatchBrExitIdx == 1) - return SE.isLoopEntryGuardedByCond(L, BoundPred, Start, BoundSCEV); + return SE.isLoopEntryGuardedByCond(L, BoundPred, StartLG, BoundLG); assert(LatchBrExitIdx == 0 && "LatchBrExitIdx should be 0 or 1"); @@ -97,9 +103,9 @@ static bool isSafeIncreasingBound(const SCEV *Start, const SCEV *BoundSCEV, : APInt::getMaxValue(BitWidth); const SCEV *Limit = SE.getMinusSCEV(SE.getConstant(Max), StepMinusOne); - return (SE.isLoopEntryGuardedByCond(L, BoundPred, Start, - SE.getAddExpr(BoundSCEV, Step)) && - SE.isLoopEntryGuardedByCond(L, BoundPred, BoundSCEV, Limit)); + return (SE.isLoopEntryGuardedByCond(L, BoundPred, StartLG, + SE.getAddExpr(BoundLG, Step)) && + SE.isLoopEntryGuardedByCond(L, BoundPred, BoundLG, Limit)); } /// Returns estimate for max latch taken count of the loop of the narrowest diff --git a/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp b/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp index 8c6af7afa875c9e27d5518950efb6aabddf105af..0f55af3b6eddf8ad4568179ee519546d13f9e752 100644 --- a/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp +++ b/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp @@ -159,8 +159,8 @@ static void RewriteUsesOfClonedInstructions(BasicBlock *OrigHeader, // Replace MetadataAsValue(ValueAsMetadata(OrigHeaderVal)) uses in debug // intrinsics. SmallVector<DbgValueInst *, 1> DbgValues; - SmallVector<DPValue *, 1> DPValues; - llvm::findDbgValues(DbgValues, OrigHeaderVal, &DPValues); + SmallVector<DbgVariableRecord *, 1> DbgVariableRecords; + llvm::findDbgValues(DbgValues, OrigHeaderVal, &DbgVariableRecords); for (auto &DbgValue : DbgValues) { // The original users in the OrigHeader are already using the original // definitions. @@ -183,11 +183,11 @@ static void RewriteUsesOfClonedInstructions(BasicBlock *OrigHeader, } // RemoveDIs: duplicate implementation for non-instruction debug-info - // storage in DPValues. - for (DPValue *DPV : DPValues) { + // storage in DbgVariableRecords. + for (DbgVariableRecord *DVR : DbgVariableRecords) { // The original users in the OrigHeader are already using the original // definitions. - BasicBlock *UserBB = DPV->getMarker()->getParent(); + BasicBlock *UserBB = DVR->getMarker()->getParent(); if (UserBB == OrigHeader) continue; @@ -202,7 +202,7 @@ static void RewriteUsesOfClonedInstructions(BasicBlock *OrigHeader, NewVal = SSA.GetValueInMiddleOfBlock(UserBB); else NewVal = UndefValue::get(OrigHeaderVal->getType()); - DPV->replaceVariableLocationOp(OrigHeaderVal, NewVal); + DVR->replaceVariableLocationOp(OrigHeaderVal, NewVal); } } } @@ -347,9 +347,19 @@ static void updateBranchWeights(BranchInst &PreHeaderBI, BranchInst &LoopBI, // probabilities as if there are only 0-trip and 1-trip cases. ExitWeight0 = OrigLoopExitWeight - OrigLoopBackedgeWeight; } + } else { + // Theoretically, if the loop body must be executed at least once, the + // backedge count must be not less than exit count. However the branch + // weight collected by sampling-based PGO may be not very accurate due to + // sampling. Therefore this workaround is required here to avoid underflow + // of unsigned in following update of branch weight. + if (OrigLoopExitWeight > OrigLoopBackedgeWeight) + OrigLoopBackedgeWeight = OrigLoopExitWeight; } + assert(OrigLoopExitWeight >= ExitWeight0 && "Bad branch weight"); ExitWeight1 = OrigLoopExitWeight - ExitWeight0; EnterWeight = ExitWeight1; + assert(OrigLoopBackedgeWeight >= EnterWeight && "Bad branch weight"); LoopBackWeight = OrigLoopBackedgeWeight - EnterWeight; } else if (OrigLoopExitWeight == 0) { if (OrigLoopBackedgeWeight == 0) { @@ -552,20 +562,22 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) { for (Instruction &I : llvm::drop_begin(llvm::reverse(*OrigPreheader))) { if (auto *DII = dyn_cast<DbgVariableIntrinsic>(&I)) { DbgIntrinsics.insert(makeHash(DII)); - // Until RemoveDIs supports dbg.declares in DPValue format, we'll need - // to collect DPValues attached to any other debug intrinsics. - for (const DPValue &DPV : DPValue::filter(DII->getDbgRecordRange())) - DbgIntrinsics.insert(makeHash(&DPV)); + // Until RemoveDIs supports dbg.declares in DbgVariableRecord format, + // we'll need to collect DbgVariableRecords attached to any other debug + // intrinsics. + for (const DbgVariableRecord &DVR : + filterDbgVars(DII->getDbgRecordRange())) + DbgIntrinsics.insert(makeHash(&DVR)); } else { break; } } - // Build DPValue hashes for DPValues attached to the terminator, which isn't - // considered in the loop above. - for (const DPValue &DPV : - DPValue::filter(OrigPreheader->getTerminator()->getDbgRecordRange())) - DbgIntrinsics.insert(makeHash(&DPV)); + // Build DbgVariableRecord hashes for DbgVariableRecords attached to the + // terminator, which isn't considered in the loop above. + for (const DbgVariableRecord &DVR : + filterDbgVars(OrigPreheader->getTerminator()->getDbgRecordRange())) + DbgIntrinsics.insert(makeHash(&DVR)); // Remember the local noalias scope declarations in the header. After the // rotation, they must be duplicated and the scope must be cloned. This @@ -577,29 +589,29 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) { Module *M = OrigHeader->getModule(); - // Track the next DPValue to clone. If we have a sequence where an + // Track the next DbgRecord to clone. If we have a sequence where an // instruction is hoisted instead of being cloned: - // DPValue blah + // DbgRecord blah // %foo = add i32 0, 0 - // DPValue xyzzy + // DbgRecord xyzzy // %bar = call i32 @foobar() - // where %foo is hoisted, then the DPValue "blah" will be seen twice, once + // where %foo is hoisted, then the DbgRecord "blah" will be seen twice, once // attached to %foo, then when %foo his hoisted it will "fall down" onto the // function call: - // DPValue blah - // DPValue xyzzy + // DbgRecord blah + // DbgRecord xyzzy // %bar = call i32 @foobar() // causing it to appear attached to the call too. // // To avoid this, cloneDebugInfoFrom takes an optional "start cloning from - // here" position to account for this behaviour. We point it at any DPValues - // on the next instruction, here labelled xyzzy, before we hoist %foo. - // Later, we only only clone DPValues from that position (xyzzy) onwards, - // which avoids cloning DPValue "blah" multiple times. - // (Stored as a range because it gives us a natural way of testing whether - // there were DPValues on the next instruction before we hoisted things). - iterator_range<DPValue::self_iterator> NextDbgInsts = - (I != E) ? I->getDbgRecordRange() : DPMarker::getEmptyDbgRecordRange(); + // here" position to account for this behaviour. We point it at any + // DbgRecords on the next instruction, here labelled xyzzy, before we hoist + // %foo. Later, we only only clone DbgRecords from that position (xyzzy) + // onwards, which avoids cloning DbgRecord "blah" multiple times. (Stored as + // a range because it gives us a natural way of testing whether + // there were DbgRecords on the next instruction before we hoisted things). + iterator_range<DbgRecord::self_iterator> NextDbgInsts = + (I != E) ? I->getDbgRecordRange() : DbgMarker::getEmptyDbgRecordRange(); while (I != E) { Instruction *Inst = &*I++; @@ -627,13 +639,14 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) { !NextDbgInsts.empty()) { auto DbgValueRange = LoopEntryBranch->cloneDebugInfoFrom(Inst, NextDbgInsts.begin()); - RemapDPValueRange(M, DbgValueRange, ValueMap, - RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); + RemapDbgVariableRecordRange(M, DbgValueRange, ValueMap, + RF_NoModuleLevelChanges | + RF_IgnoreMissingLocals); // Erase anything we've seen before. - for (DPValue &DPV : - make_early_inc_range(DPValue::filter(DbgValueRange))) - if (DbgIntrinsics.count(makeHash(&DPV))) - DPV.eraseFromParent(); + for (DbgVariableRecord &DVR : + make_early_inc_range(filterDbgVars(DbgValueRange))) + if (DbgIntrinsics.count(makeHash(&DVR))) + DVR.eraseFromParent(); } NextDbgInsts = I->getDbgRecordRange(); @@ -653,13 +666,15 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) { if (LoopEntryBranch->getParent()->IsNewDbgInfoFormat && !NextDbgInsts.empty()) { auto Range = C->cloneDebugInfoFrom(Inst, NextDbgInsts.begin()); - RemapDPValueRange(M, Range, ValueMap, - RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); - NextDbgInsts = DPMarker::getEmptyDbgRecordRange(); + RemapDbgVariableRecordRange(M, Range, ValueMap, + RF_NoModuleLevelChanges | + RF_IgnoreMissingLocals); + NextDbgInsts = DbgMarker::getEmptyDbgRecordRange(); // Erase anything we've seen before. - for (DPValue &DPV : make_early_inc_range(DPValue::filter(Range))) - if (DbgIntrinsics.count(makeHash(&DPV))) - DPV.eraseFromParent(); + for (DbgVariableRecord &DVR : + make_early_inc_range(filterDbgVars(Range))) + if (DbgIntrinsics.count(makeHash(&DVR))) + DVR.eraseFromParent(); } // Eagerly remap the operands of the instruction. @@ -777,7 +792,7 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) { // OrigPreHeader's old terminator (the original branch into the loop), and // remove the corresponding incoming values from the PHI nodes in OrigHeader. LoopEntryBranch->eraseFromParent(); - OrigPreheader->flushTerminatorDbgValues(); + OrigPreheader->flushTerminatorDbgRecords(); // Update MemorySSA before the rewrite call below changes the 1:1 // instruction:cloned_instruction_or_value mapping. diff --git a/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp b/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp index ecd76b7c1fbfb20ec0ac63252ad73ad1abc60481..2d5b5f967ffbc0803e96ec8129eaacb2f0fc329a 100644 --- a/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp +++ b/llvm/lib/Transforms/Utils/LoopUnrollRuntime.cpp @@ -917,8 +917,9 @@ bool llvm::UnrollRuntimeLoopRemainder( for (Instruction &I : *BB) { RemapInstruction(&I, VMap, RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); - RemapDPValueRange(M, I.getDbgRecordRange(), VMap, - RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); + RemapDbgVariableRecordRange(M, I.getDbgRecordRange(), VMap, + RF_NoModuleLevelChanges | + RF_IgnoreMissingLocals); } } diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp index 05b02a42c58a664e0a0f4bc0c5a6a51ef393c526..73c5d636782294d7118d61887de9a6851e6be13d 100644 --- a/llvm/lib/Transforms/Utils/LoopUtils.cpp +++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp @@ -605,7 +605,7 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE, // Use a map to unique and a vector to guarantee deterministic ordering. llvm::SmallDenseSet<DebugVariable, 4> DeadDebugSet; llvm::SmallVector<DbgVariableIntrinsic *, 4> DeadDebugInst; - llvm::SmallVector<DPValue *, 4> DeadDPValues; + llvm::SmallVector<DbgVariableRecord *, 4> DeadDbgVariableRecords; if (ExitBlock) { // Given LCSSA form is satisfied, we should not have users of instructions @@ -631,17 +631,17 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE, U.set(Poison); } - // RemoveDIs: do the same as below for DPValues. + // RemoveDIs: do the same as below for DbgVariableRecords. if (Block->IsNewDbgInfoFormat) { - for (DPValue &DPV : llvm::make_early_inc_range( - DPValue::filter(I.getDbgRecordRange()))) { - DebugVariable Key(DPV.getVariable(), DPV.getExpression(), - DPV.getDebugLoc().get()); + for (DbgVariableRecord &DVR : llvm::make_early_inc_range( + filterDbgVars(I.getDbgRecordRange()))) { + DebugVariable Key(DVR.getVariable(), DVR.getExpression(), + DVR.getDebugLoc().get()); if (!DeadDebugSet.insert(Key).second) continue; - // Unlinks the DPV from it's container, for later insertion. - DPV.removeFromParent(); - DeadDPValues.push_back(&DPV); + // Unlinks the DVR from it's container, for later insertion. + DVR.removeFromParent(); + DeadDbgVariableRecords.push_back(&DVR); } } @@ -673,11 +673,11 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE, DVI->moveBefore(*ExitBlock, InsertDbgValueBefore); // Due to the "head" bit in BasicBlock::iterator, we're going to insert - // each DPValue right at the start of the block, wheras dbg.values would be - // repeatedly inserted before the first instruction. To replicate this - // behaviour, do it backwards. - for (DPValue *DPV : llvm::reverse(DeadDPValues)) - ExitBlock->insertDbgRecordBefore(DPV, InsertDbgValueBefore); + // each DbgVariableRecord right at the start of the block, wheras dbg.values + // would be repeatedly inserted before the first instruction. To replicate + // this behaviour, do it backwards. + for (DbgVariableRecord *DVR : llvm::reverse(DeadDbgVariableRecords)) + ExitBlock->insertDbgRecordBefore(DVR, InsertDbgValueBefore); } // Remove the block from the reference counting scheme, so that we can diff --git a/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp b/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp index d671a9373bf026d72d05ae2947f6c0b7b1a92ab3..8f55d7bbd3182a5c53820a7d3992d81f7610afa0 100644 --- a/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp +++ b/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp @@ -332,7 +332,7 @@ void MemoryOpRemark::visitVariable(const Value *V, } }; for_each(findDbgDeclares(const_cast<Value *>(V)), FindDI); - for_each(findDPVDeclares(const_cast<Value *>(V)), FindDI); + for_each(findDVRDeclares(const_cast<Value *>(V)), FindDI); if (FoundDI) { assert(!Result.empty()); diff --git a/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp b/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp index ed06d3e7f452c0181bf7906081d816d42efe8504..7b1eb70168d894f8f26b715bdc0116bfb1095332 100644 --- a/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp +++ b/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp @@ -18,7 +18,9 @@ #include "llvm/Analysis/StackSafetyAnalysis.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/BasicBlock.h" +#include "llvm/IR/IRBuilder.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/TargetParser/Triple.h" #include "llvm/Transforms/Utils/PromoteMemToReg.h" namespace llvm { @@ -110,21 +112,21 @@ Instruction *getUntagLocationIfFunctionExit(Instruction &Inst) { void StackInfoBuilder::visit(Instruction &Inst) { // Visit non-intrinsic debug-info records attached to Inst. - for (DPValue &DPV : DPValue::filter(Inst.getDbgRecordRange())) { + for (DbgVariableRecord &DVR : filterDbgVars(Inst.getDbgRecordRange())) { auto AddIfInteresting = [&](Value *V) { if (auto *AI = dyn_cast_or_null<AllocaInst>(V)) { if (!isInterestingAlloca(*AI)) return; AllocaInfo &AInfo = Info.AllocasToInstrument[AI]; - auto &DPVVec = AInfo.DbgVariableRecords; - if (DPVVec.empty() || DPVVec.back() != &DPV) - DPVVec.push_back(&DPV); + auto &DVRVec = AInfo.DbgVariableRecords; + if (DVRVec.empty() || DVRVec.back() != &DVR) + DVRVec.push_back(&DVR); } }; - for_each(DPV.location_ops(), AddIfInteresting); - if (DPV.isDbgAssign()) - AddIfInteresting(DPV.getAddress()); + for_each(DVR.location_ops(), AddIfInteresting); + if (DVR.isDbgAssign()) + AddIfInteresting(DVR.getAddress()); } if (CallInst *CI = dyn_cast<CallInst>(&Inst)) { @@ -236,5 +238,50 @@ void alignAndPadAlloca(memtag::AllocaInfo &Info, llvm::Align Alignment) { Info.AI = NewAI; } +bool isLifetimeIntrinsic(Value *V) { + auto *II = dyn_cast<IntrinsicInst>(V); + return II && II->isLifetimeStartOrEnd(); +} + +Value *readRegister(IRBuilder<> &IRB, StringRef Name) { + Module *M = IRB.GetInsertBlock()->getParent()->getParent(); + Function *ReadRegister = Intrinsic::getDeclaration( + M, Intrinsic::read_register, IRB.getIntPtrTy(M->getDataLayout())); + MDNode *MD = + MDNode::get(M->getContext(), {MDString::get(M->getContext(), Name)}); + Value *Args[] = {MetadataAsValue::get(M->getContext(), MD)}; + return IRB.CreateCall(ReadRegister, Args); +} + +Value *getPC(const Triple &TargetTriple, IRBuilder<> &IRB) { + Module *M = IRB.GetInsertBlock()->getParent()->getParent(); + if (TargetTriple.getArch() == Triple::aarch64) + return memtag::readRegister(IRB, "pc"); + return IRB.CreatePtrToInt(IRB.GetInsertBlock()->getParent(), + IRB.getIntPtrTy(M->getDataLayout())); +} + +Value *getFP(IRBuilder<> &IRB) { + Function *F = IRB.GetInsertBlock()->getParent(); + Module *M = F->getParent(); + auto *GetStackPointerFn = Intrinsic::getDeclaration( + M, Intrinsic::frameaddress, + IRB.getPtrTy(M->getDataLayout().getAllocaAddrSpace())); + return IRB.CreatePtrToInt( + IRB.CreateCall(GetStackPointerFn, + {Constant::getNullValue(IRB.getInt32Ty())}), + IRB.getIntPtrTy(M->getDataLayout())); +} + +Value *getAndroidSlotPtr(IRBuilder<> &IRB, int Slot) { + Module *M = IRB.GetInsertBlock()->getParent()->getParent(); + // Android provides a fixed TLS slot for sanitizers. See TLS_SLOT_SANITIZER + // in Bionic's libc/private/bionic_tls.h. + Function *ThreadPointerFunc = + Intrinsic::getDeclaration(M, Intrinsic::thread_pointer); + return IRB.CreateConstGEP1_32(IRB.getInt8Ty(), + IRB.CreateCall(ThreadPointerFunc), 8 * Slot); +} + } // namespace memtag } // namespace llvm diff --git a/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp index b462803bad38c374f61bde767af58d5414c08af8..adcf161b313b2b11d45b222e08d15923bdebac12 100644 --- a/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +++ b/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp @@ -104,11 +104,13 @@ namespace { static void createDebugValue(DIBuilder &DIB, Value *NewValue, DILocalVariable *Variable, DIExpression *Expression, const DILocation *DI, - DPValue *InsertBefore) { - // FIXME: Merge these two functions now that DIBuilder supports DPValues. - // We neeed the API to accept DPValues as an insert point for that to work. + DbgVariableRecord *InsertBefore) { + // FIXME: Merge these two functions now that DIBuilder supports + // DbgVariableRecords. We neeed the API to accept DbgVariableRecords as an + // insert point for that to work. (void)DIB; - DPValue::createDPValue(NewValue, Variable, Expression, DI, *InsertBefore); + DbgVariableRecord::createDbgVariableRecord(NewValue, Variable, Expression, DI, + *InsertBefore); } static void createDebugValue(DIBuilder &DIB, Value *NewValue, DILocalVariable *Variable, @@ -123,7 +125,7 @@ class AssignmentTrackingInfo { /// fragment. (i.e. not be a comprehensive set if there are multiple /// dbg.assigns for one variable fragment). SmallVector<DbgVariableIntrinsic *> DbgAssigns; - SmallVector<DPValue *> DPVAssigns; + SmallVector<DbgVariableRecord *> DVRAssigns; public: void init(AllocaInst *AI) { @@ -132,21 +134,21 @@ public: if (Vars.insert(DebugVariable(DAI)).second) DbgAssigns.push_back(DAI); } - for (DPValue *DPV : at::getDPVAssignmentMarkers(AI)) { - if (Vars.insert(DebugVariable(DPV)).second) - DPVAssigns.push_back(DPV); + for (DbgVariableRecord *DVR : at::getDVRAssignmentMarkers(AI)) { + if (Vars.insert(DebugVariable(DVR)).second) + DVRAssigns.push_back(DVR); } } /// Update assignment tracking debug info given for the to-be-deleted store /// \p ToDelete that stores to this alloca. - void - updateForDeletedStore(StoreInst *ToDelete, DIBuilder &DIB, - SmallSet<DbgAssignIntrinsic *, 8> *DbgAssignsToDelete, - SmallSet<DPValue *, 8> *DPVAssignsToDelete) const { + void updateForDeletedStore( + StoreInst *ToDelete, DIBuilder &DIB, + SmallSet<DbgAssignIntrinsic *, 8> *DbgAssignsToDelete, + SmallSet<DbgVariableRecord *, 8> *DVRAssignsToDelete) const { // There's nothing to do if the alloca doesn't have any variables using // assignment tracking. - if (DbgAssigns.empty() && DPVAssigns.empty()) + if (DbgAssigns.empty() && DVRAssigns.empty()) return; // Insert a dbg.value where the linked dbg.assign is and remember to delete @@ -165,8 +167,8 @@ public: }; for (auto *Assign : at::getAssignmentMarkers(ToDelete)) InsertValueForAssign(Assign, DbgAssignsToDelete); - for (auto *Assign : at::getDPVAssignmentMarkers(ToDelete)) - InsertValueForAssign(Assign, DPVAssignsToDelete); + for (auto *Assign : at::getDVRAssignmentMarkers(ToDelete)) + InsertValueForAssign(Assign, DVRAssignsToDelete); // It's possible for variables using assignment tracking to have no // dbg.assign linked to this store. These are variables in DbgAssigns that @@ -182,7 +184,7 @@ public: ConvertDebugDeclareToDebugValue(Assign, ToDelete, DIB); }; for_each(DbgAssigns, ConvertUnlinkedAssignToValue); - for_each(DPVAssigns, ConvertUnlinkedAssignToValue); + for_each(DVRAssigns, ConvertUnlinkedAssignToValue); } /// Update assignment tracking debug info given for the newly inserted PHI \p @@ -193,20 +195,20 @@ public: // debug-phi. for (auto *DAI : DbgAssigns) ConvertDebugDeclareToDebugValue(DAI, NewPhi, DIB); - for (auto *DPV : DPVAssigns) - ConvertDebugDeclareToDebugValue(DPV, NewPhi, DIB); + for (auto *DVR : DVRAssigns) + ConvertDebugDeclareToDebugValue(DVR, NewPhi, DIB); } void clear() { DbgAssigns.clear(); - DPVAssigns.clear(); + DVRAssigns.clear(); } - bool empty() { return DbgAssigns.empty() && DPVAssigns.empty(); } + bool empty() { return DbgAssigns.empty() && DVRAssigns.empty(); } }; struct AllocaInfo { using DbgUserVec = SmallVector<DbgVariableIntrinsic *, 1>; - using DPUserVec = SmallVector<DPValue *, 1>; + using DPUserVec = SmallVector<DbgVariableRecord *, 1>; SmallVector<BasicBlock *, 32> DefiningBlocks; SmallVector<BasicBlock *, 32> UsingBlocks; @@ -262,7 +264,7 @@ struct AllocaInfo { } } DbgUserVec AllDbgUsers; - SmallVector<DPValue *> AllDPUsers; + SmallVector<DbgVariableRecord *> AllDPUsers; findDbgUsers(AllDbgUsers, AI, &AllDPUsers); std::copy_if(AllDbgUsers.begin(), AllDbgUsers.end(), std::back_inserter(DbgUsers), [](DbgVariableIntrinsic *DII) { @@ -270,7 +272,7 @@ struct AllocaInfo { }); std::copy_if(AllDPUsers.begin(), AllDPUsers.end(), std::back_inserter(DPUsers), - [](DPValue *DPV) { return !DPV->isDbgAssign(); }); + [](DbgVariableRecord *DVR) { return !DVR->isDbgAssign(); }); AssignmentTracking.init(AI); } }; @@ -378,7 +380,7 @@ struct PromoteMem2Reg { /// A set of dbg.assigns to delete because they've been demoted to /// dbg.values. Call cleanUpDbgAssigns to delete them. SmallSet<DbgAssignIntrinsic *, 8> DbgAssignsToDelete; - SmallSet<DPValue *, 8> DPVAssignsToDelete; + SmallSet<DbgVariableRecord *, 8> DVRAssignsToDelete; /// The set of basic blocks the renamer has already visited. SmallPtrSet<BasicBlock *, 16> Visited; @@ -428,9 +430,9 @@ private: for (auto *DAI : DbgAssignsToDelete) DAI->eraseFromParent(); DbgAssignsToDelete.clear(); - for (auto *DPV : DPVAssignsToDelete) - DPV->eraseFromParent(); - DPVAssignsToDelete.clear(); + for (auto *DVR : DVRAssignsToDelete) + DVR->eraseFromParent(); + DVRAssignsToDelete.clear(); } }; @@ -508,7 +510,7 @@ rewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info, LargeBlockInfo &LBI, const DataLayout &DL, DominatorTree &DT, AssumptionCache *AC, SmallSet<DbgAssignIntrinsic *, 8> *DbgAssignsToDelete, - SmallSet<DPValue *, 8> *DPVAssignsToDelete) { + SmallSet<DbgVariableRecord *, 8> *DVRAssignsToDelete) { StoreInst *OnlyStore = Info.OnlyStore; bool StoringGlobalVal = !isa<Instruction>(OnlyStore->getOperand(0)); BasicBlock *StoreBB = OnlyStore->getParent(); @@ -569,7 +571,7 @@ rewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info, LargeBlockInfo &LBI, DIBuilder DIB(*AI->getModule(), /*AllowUnresolved*/ false); // Update assignment tracking info for the store we're going to delete. Info.AssignmentTracking.updateForDeletedStore( - Info.OnlyStore, DIB, DbgAssignsToDelete, DPVAssignsToDelete); + Info.OnlyStore, DIB, DbgAssignsToDelete, DVRAssignsToDelete); // Record debuginfo for the store and remove the declaration's // debuginfo. @@ -618,7 +620,7 @@ promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info, LargeBlockInfo &LBI, const DataLayout &DL, DominatorTree &DT, AssumptionCache *AC, SmallSet<DbgAssignIntrinsic *, 8> *DbgAssignsToDelete, - SmallSet<DPValue *, 8> *DPVAssignsToDelete) { + SmallSet<DbgVariableRecord *, 8> *DVRAssignsToDelete) { // The trickiest case to handle is when we have large blocks. Because of this, // this code is optimized assuming that large blocks happen. This does not // significantly pessimize the small block case. This uses LargeBlockInfo to @@ -683,7 +685,7 @@ promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info, StoreInst *SI = cast<StoreInst>(AI->user_back()); // Update assignment tracking info for the store we're going to delete. Info.AssignmentTracking.updateForDeletedStore(SI, DIB, DbgAssignsToDelete, - DPVAssignsToDelete); + DVRAssignsToDelete); // Record debuginfo for the store before removing it. auto DbgUpdateForStore = [&](auto &Container) { for (auto *DbgItem : Container) { @@ -755,7 +757,7 @@ void PromoteMem2Reg::run() { // it that are directly dominated by the definition with the value stored. if (Info.DefiningBlocks.size() == 1) { if (rewriteSingleStoreAlloca(AI, Info, LBI, SQ.DL, DT, AC, - &DbgAssignsToDelete, &DPVAssignsToDelete)) { + &DbgAssignsToDelete, &DVRAssignsToDelete)) { // The alloca has been processed, move on. RemoveFromAllocasList(AllocaNum); ++NumSingleStore; @@ -767,7 +769,7 @@ void PromoteMem2Reg::run() { // linear sweep over the block to eliminate it. if (Info.OnlyUsedInOneBlock && promoteSingleBlockAlloca(AI, Info, LBI, SQ.DL, DT, AC, - &DbgAssignsToDelete, &DPVAssignsToDelete)) { + &DbgAssignsToDelete, &DVRAssignsToDelete)) { // The alloca has been processed, move on. RemoveFromAllocasList(AllocaNum); continue; @@ -1174,7 +1176,7 @@ NextIteration: // Record debuginfo for the store before removing it. IncomingLocs[AllocaNo] = SI->getDebugLoc(); AllocaATInfo[AllocaNo].updateForDeletedStore(SI, DIB, &DbgAssignsToDelete, - &DPVAssignsToDelete); + &DVRAssignsToDelete); auto ConvertDbgDeclares = [&](auto &Container) { for (auto *DbgItem : Container) if (DbgItem->isAddressOfVariable()) diff --git a/llvm/lib/Transforms/Utils/SCCPSolver.cpp b/llvm/lib/Transforms/Utils/SCCPSolver.cpp index a185e8cd371c60f6122757ba73fa8b61fc64d57d..38fc7763c5b204e44805bb2ac1500be01a6d324f 100644 --- a/llvm/lib/Transforms/Utils/SCCPSolver.cpp +++ b/llvm/lib/Transforms/Utils/SCCPSolver.cpp @@ -1486,7 +1486,13 @@ void SCCPInstVisitor::visitBinaryOperator(Instruction &I) { // Try to simplify to a constant range. ConstantRange A = getConstantRange(V1State, I.getType()); ConstantRange B = getConstantRange(V2State, I.getType()); - ConstantRange R = A.binaryOp(cast<BinaryOperator>(&I)->getOpcode(), B); + + auto *BO = cast<BinaryOperator>(&I); + ConstantRange R = ConstantRange::getEmpty(I.getType()->getScalarSizeInBits()); + if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(BO)) + R = A.overflowingBinaryOp(BO->getOpcode(), B, OBO->getNoWrapKind()); + else + R = A.binaryOp(BO->getOpcode(), B); mergeInValue(&I, ValueLatticeElement::getRange(R)); // TODO: Currently we do not exploit special values that produce something diff --git a/llvm/lib/Transforms/Utils/SSAUpdater.cpp b/llvm/lib/Transforms/Utils/SSAUpdater.cpp index fc21fb552137d70aff94c2a07f5d336710577e8f..38df20c949c2ecbc0ccfb86a0ef120068aca03ec 100644 --- a/llvm/lib/Transforms/Utils/SSAUpdater.cpp +++ b/llvm/lib/Transforms/Utils/SSAUpdater.cpp @@ -199,17 +199,17 @@ void SSAUpdater::RewriteUse(Use &U) { void SSAUpdater::UpdateDebugValues(Instruction *I) { SmallVector<DbgValueInst *, 4> DbgValues; - SmallVector<DPValue *, 4> DPValues; - llvm::findDbgValues(DbgValues, I, &DPValues); + SmallVector<DbgVariableRecord *, 4> DbgVariableRecords; + llvm::findDbgValues(DbgValues, I, &DbgVariableRecords); for (auto &DbgValue : DbgValues) { if (DbgValue->getParent() == I->getParent()) continue; UpdateDebugValue(I, DbgValue); } - for (auto &DPV : DPValues) { - if (DPV->getParent() == I->getParent()) + for (auto &DVR : DbgVariableRecords) { + if (DVR->getParent() == I->getParent()) continue; - UpdateDebugValue(I, DPV); + UpdateDebugValue(I, DVR); } } @@ -220,10 +220,10 @@ void SSAUpdater::UpdateDebugValues(Instruction *I, } } -void SSAUpdater::UpdateDebugValues(Instruction *I, - SmallVectorImpl<DPValue *> &DPValues) { - for (auto &DPV : DPValues) { - UpdateDebugValue(I, DPV); +void SSAUpdater::UpdateDebugValues( + Instruction *I, SmallVectorImpl<DbgVariableRecord *> &DbgVariableRecords) { + for (auto &DVR : DbgVariableRecords) { + UpdateDebugValue(I, DVR); } } @@ -236,13 +236,13 @@ void SSAUpdater::UpdateDebugValue(Instruction *I, DbgValueInst *DbgValue) { DbgValue->setKillLocation(); } -void SSAUpdater::UpdateDebugValue(Instruction *I, DPValue *DPV) { - BasicBlock *UserBB = DPV->getParent(); +void SSAUpdater::UpdateDebugValue(Instruction *I, DbgVariableRecord *DVR) { + BasicBlock *UserBB = DVR->getParent(); if (HasValueForBlock(UserBB)) { Value *NewVal = GetValueAtEndOfBlock(UserBB); - DPV->replaceVariableLocationOp(I, NewVal); + DVR->replaceVariableLocationOp(I, NewVal); } else - DPV->setKillLocation(); + DVR->setKillLocation(); } void SSAUpdater::RewriteUseAfterInsertions(Use &U) { diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp index 3a3bcde7c3dcddaf36bd145edc1b81df30f33ed3..74cffbc005c82dd3872c95fb7dfd573dfa95509b 100644 --- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp +++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp @@ -59,6 +59,10 @@ PoisonFlags::PoisonFlags(const Instruction *I) { Disjoint = PDI->isDisjoint(); if (auto *PNI = dyn_cast<PossiblyNonNegInst>(I)) NNeg = PNI->hasNonNeg(); + if (auto *TI = dyn_cast<TruncInst>(I)) { + NUW = TI->hasNoUnsignedWrap(); + NSW = TI->hasNoSignedWrap(); + } } void PoisonFlags::apply(Instruction *I) { @@ -72,6 +76,10 @@ void PoisonFlags::apply(Instruction *I) { PDI->setIsDisjoint(Disjoint); if (auto *PNI = dyn_cast<PossiblyNonNegInst>(I)) PNI->setNonNeg(NNeg); + if (isa<TruncInst>(I)) { + I->setHasNoUnsignedWrap(NUW); + I->setHasNoSignedWrap(NSW); + } } /// ReuseOrCreateCast - Arrange for there to be a cast of V to Ty at IP, diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 0f3d1403481dfca666c24384ad7d958d11f8598d..55bbffb18879fb7a19fda673c2b1d6a9066326d8 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -1126,8 +1126,9 @@ static void CloneInstructionsIntoPredecessorBlockAndUpdateSSAUses( NewBonusInst->insertInto(PredBlock, PTI->getIterator()); auto Range = NewBonusInst->cloneDebugInfoFrom(&BonusInst); - RemapDPValueRange(NewBonusInst->getModule(), Range, VMap, - RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); + RemapDbgVariableRecordRange(NewBonusInst->getModule(), Range, VMap, + RF_NoModuleLevelChanges | + RF_IgnoreMissingLocals); if (isa<DbgInfoIntrinsic>(BonusInst)) continue; @@ -1526,15 +1527,15 @@ static bool shouldHoistCommonInstructions(Instruction *I1, Instruction *I2, return true; } -/// Hoists DPValues from \p I1 and \p OtherInstrs that are identical in -/// lock-step to \p TI. This matches how dbg.* intrinsics are hoisting in +/// Hoists DbgVariableRecords from \p I1 and \p OtherInstrs that are identical +/// in lock-step to \p TI. This matches how dbg.* intrinsics are hoisting in /// hoistCommonCodeFromSuccessors. e.g. The input: -/// I1 DPVs: { x, z }, -/// OtherInsts: { I2 DPVs: { x, y, z } } -/// would result in hoisting only DPValue x. -static void -hoistLockstepIdenticalDPValues(Instruction *TI, Instruction *I1, - SmallVectorImpl<Instruction *> &OtherInsts) { +/// I1 DVRs: { x, z }, +/// OtherInsts: { I2 DVRs: { x, y, z } } +/// would result in hoisting only DbgVariableRecord x. +static void hoistLockstepIdenticalDbgVariableRecords( + Instruction *TI, Instruction *I1, + SmallVectorImpl<Instruction *> &OtherInsts) { if (!I1->hasDbgRecords()) return; using CurrentAndEndIt = @@ -1570,11 +1571,12 @@ hoistLockstepIdenticalDPValues(Instruction *TI, Instruction *I1, // This replicates the dbg.* intrinsic behaviour in // hoistCommonCodeFromSuccessors. while (none_of(Itrs, atEnd)) { - bool HoistDPVs = allIdentical(Itrs); + bool HoistDVRs = allIdentical(Itrs); for (CurrentAndEndIt &Pair : Itrs) { - // Increment Current iterator now as we may be about to move the DPValue. + // Increment Current iterator now as we may be about to move the + // DbgRecord. DbgRecord &DR = *Pair.first++; - if (HoistDPVs) { + if (HoistDVRs) { DR.removeFromParent(); TI->getParent()->insertDbgRecordBefore(&DR, TI->getIterator()); } @@ -1690,7 +1692,7 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB, // at the beginning of the loop, we can hoist the terminator instruction. // If any instructions remain in the block, we cannot hoist terminators. if (NumSkipped || !AllInstsAreIdentical) { - hoistLockstepIdenticalDPValues(TI, I1, OtherInsts); + hoistLockstepIdenticalDbgVariableRecords(TI, I1, OtherInsts); return Changed; } @@ -1720,9 +1722,9 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB, // The debug location is an integral part of a debug info intrinsic // and can't be separated from it or replaced. Instead of attempting // to merge locations, simply hoist both copies of the intrinsic. - hoistLockstepIdenticalDPValues(TI, I1, OtherInsts); - // We've just hoisted DPValues; move I1 after them (before TI) and - // leave any that were not hoisted behind (by calling moveBefore + hoistLockstepIdenticalDbgVariableRecords(TI, I1, OtherInsts); + // We've just hoisted DbgVariableRecords; move I1 after them (before TI) + // and leave any that were not hoisted behind (by calling moveBefore // rather than moveBeforePreserving). I1->moveBefore(TI); for (auto &SuccIter : OtherSuccIterRange) { @@ -1734,9 +1736,9 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB, // For a normal instruction, we just move one to right before the // branch, then replace all uses of the other with the first. Finally, // we remove the now redundant second instruction. - hoistLockstepIdenticalDPValues(TI, I1, OtherInsts); - // We've just hoisted DPValues; move I1 after them (before TI) and - // leave any that were not hoisted behind (by calling moveBefore + hoistLockstepIdenticalDbgVariableRecords(TI, I1, OtherInsts); + // We've just hoisted DbgVariableRecords; move I1 after them (before TI) + // and leave any that were not hoisted behind (by calling moveBefore // rather than moveBeforePreserving). I1->moveBefore(TI); for (auto &SuccIter : OtherSuccIterRange) { @@ -1758,7 +1760,7 @@ bool SimplifyCFGOpt::hoistCommonCodeFromSuccessors(BasicBlock *BB, NumHoistCommonInstrs += SuccIterPairs.size(); } else { if (NumSkipped >= HoistCommonSkipLimit) { - hoistLockstepIdenticalDPValues(TI, I1, OtherInsts); + hoistLockstepIdenticalDbgVariableRecords(TI, I1, OtherInsts); return Changed; } // We are about to skip over a pair of non-identical instructions. Record @@ -1821,9 +1823,9 @@ bool SimplifyCFGOpt::hoistSuccIdenticalTerminatorToSwitchOrIf( } } - // Hoist DPValues attached to the terminator to match dbg.* intrinsic hoisting - // behaviour in hoistCommonCodeFromSuccessors. - hoistLockstepIdenticalDPValues(TI, I1, OtherSuccTIs); + // Hoist DbgVariableRecords attached to the terminator to match dbg.* + // intrinsic hoisting behaviour in hoistCommonCodeFromSuccessors. + hoistLockstepIdenticalDbgVariableRecords(TI, I1, OtherSuccTIs); // Clone the terminator and hoist it into the pred, without any debug info. Instruction *NT = I1->clone(); NT->insertInto(TIParent, TI->getIterator()); @@ -3178,7 +3180,7 @@ bool SimplifyCFGOpt::SpeculativelyExecuteBB(BranchInst *BI, DbgAssign->replaceVariableLocationOp(OrigV, S); }; for_each(at::getAssignmentMarkers(SpeculatedStore), replaceVariable); - for_each(at::getDPVAssignmentMarkers(SpeculatedStore), replaceVariable); + for_each(at::getDVRAssignmentMarkers(SpeculatedStore), replaceVariable); } // Metadata can be dependent on the condition we are hoisting above. @@ -3203,13 +3205,15 @@ bool SimplifyCFGOpt::SpeculativelyExecuteBB(BranchInst *BI, } // Hoist the instructions. - // In "RemoveDIs" non-instr debug-info mode, drop DPValues attached to these - // instructions, in the same way that dbg.value intrinsics are dropped at the - // end of this block. + // In "RemoveDIs" non-instr debug-info mode, drop DbgVariableRecords attached + // to these instructions, in the same way that dbg.value intrinsics are + // dropped at the end of this block. for (auto &It : make_range(ThenBB->begin(), ThenBB->end())) for (DbgRecord &DR : make_early_inc_range(It.getDbgRecordRange())) - // Drop all records except assign-kind DPValues (dbg.assign equivalent). - if (DPValue *DPV = dyn_cast<DPValue>(&DR); !DPV || !DPV->isDbgAssign()) + // Drop all records except assign-kind DbgVariableRecords (dbg.assign + // equivalent). + if (DbgVariableRecord *DVR = dyn_cast<DbgVariableRecord>(&DR); + !DVR || !DVR->isDbgAssign()) It.dropOneDbgRecord(&DR); BB->splice(BI->getIterator(), ThenBB, ThenBB->begin(), std::prev(ThenBB->end())); @@ -3384,7 +3388,7 @@ FoldCondBranchOnValueKnownInPredecessorImpl(BranchInst *BI, DomTreeUpdater *DTU, TranslateMap[Cond] = CB; // RemoveDIs: track instructions that we optimise away while folding, so - // that we can copy DPValues from them later. + // that we can copy DbgVariableRecords from them later. BasicBlock::iterator SrcDbgCursor = BB->begin(); for (BasicBlock::iterator BBI = BB->begin(); &*BBI != BI; ++BBI) { if (PHINode *PN = dyn_cast<PHINode>(BBI)) { @@ -3848,10 +3852,10 @@ static bool performBranchToCommonDestFolding(BranchInst *BI, BranchInst *PBI, if (PredBlock->IsNewDbgInfoFormat) { PredBlock->getTerminator()->cloneDebugInfoFrom(BB->getTerminator()); - for (DPValue &DPV : - DPValue::filter(PredBlock->getTerminator()->getDbgRecordRange())) { - RemapDPValue(M, &DPV, VMap, - RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); + for (DbgVariableRecord &DVR : + filterDbgVars(PredBlock->getTerminator()->getDbgRecordRange())) { + RemapDbgVariableRecord(M, &DVR, VMap, + RF_NoModuleLevelChanges | RF_IgnoreMissingLocals); } } @@ -5304,7 +5308,7 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) { // Ensure that any debug-info records that used to occur after the Unreachable // are moved to in front of it -- otherwise they'll "dangle" at the end of // the block. - BB->flushTerminatorDbgValues(); + BB->flushTerminatorDbgRecords(); // Debug-info records on the unreachable inst itself should be deleted, as // below we delete everything past the final executable instruction. @@ -5326,8 +5330,8 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) { // block will be the unwind edges of Invoke/CatchSwitch/CleanupReturn, // and we can therefore guarantee this block will be erased. - // If we're deleting this, we're deleting any subsequent dbg.values, so - // delete DPValue records of variable information. + // If we're deleting this, we're deleting any subsequent debug info, so + // delete DbgRecords. BBI->dropDbgRecords(); // Delete this instruction (any uses are guaranteed to be dead) diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp index b8fa985fa3462e0b4ce654ea5dc6c7f3919b2ca7..f6d72265305d7d7afe93331a779052d6a0bdf1db 100644 --- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp @@ -1381,6 +1381,77 @@ const SCEV *WidenIV::getSCEVByOpCode(const SCEV *LHS, const SCEV *RHS, }; } +namespace { + +// Represents a interesting integer binary operation for +// getExtendedOperandRecurrence. This may be a shl that is being treated as a +// multiply or a 'or disjoint' that is being treated as 'add nsw nuw'. +struct BinaryOp { + unsigned Opcode; + std::array<Value *, 2> Operands; + bool IsNSW = false; + bool IsNUW = false; + + explicit BinaryOp(Instruction *Op) + : Opcode(Op->getOpcode()), + Operands({Op->getOperand(0), Op->getOperand(1)}) { + if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(Op)) { + IsNSW = OBO->hasNoSignedWrap(); + IsNUW = OBO->hasNoUnsignedWrap(); + } + } + + explicit BinaryOp(Instruction::BinaryOps Opcode, Value *LHS, Value *RHS, + bool IsNSW = false, bool IsNUW = false) + : Opcode(Opcode), Operands({LHS, RHS}), IsNSW(IsNSW), IsNUW(IsNUW) {} +}; + +} // end anonymous namespace + +static std::optional<BinaryOp> matchBinaryOp(Instruction *Op) { + switch (Op->getOpcode()) { + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + return BinaryOp(Op); + case Instruction::Or: { + // Convert or disjoint into add nuw nsw. + if (cast<PossiblyDisjointInst>(Op)->isDisjoint()) + return BinaryOp(Instruction::Add, Op->getOperand(0), Op->getOperand(1), + /*IsNSW=*/true, /*IsNUW=*/true); + break; + } + case Instruction::Shl: { + if (ConstantInt *SA = dyn_cast<ConstantInt>(Op->getOperand(1))) { + unsigned BitWidth = cast<IntegerType>(SA->getType())->getBitWidth(); + + // If the shift count is not less than the bitwidth, the result of + // the shift is undefined. Don't try to analyze it, because the + // resolution chosen here may differ from the resolution chosen in + // other parts of the compiler. + if (SA->getValue().ult(BitWidth)) { + // We can safely preserve the nuw flag in all cases. It's also safe to + // turn a nuw nsw shl into a nuw nsw mul. However, nsw in isolation + // requires special handling. It can be preserved as long as we're not + // left shifting by bitwidth - 1. + bool IsNUW = Op->hasNoUnsignedWrap(); + bool IsNSW = Op->hasNoSignedWrap() && + (IsNUW || SA->getValue().ult(BitWidth - 1)); + + ConstantInt *X = + ConstantInt::get(Op->getContext(), + APInt::getOneBitSet(BitWidth, SA->getZExtValue())); + return BinaryOp(Instruction::Mul, Op->getOperand(0), X, IsNSW, IsNUW); + } + } + + break; + } + } + + return std::nullopt; +} + /// No-wrap operations can transfer sign extension of their result to their /// operands. Generate the SCEV value for the widened operation without /// actually modifying the IR yet. If the expression after extending the @@ -1388,24 +1459,22 @@ const SCEV *WidenIV::getSCEVByOpCode(const SCEV *LHS, const SCEV *RHS, /// extension used. WidenIV::WidenedRecTy WidenIV::getExtendedOperandRecurrence(WidenIV::NarrowIVDefUse DU) { - // Handle the common case of add<nsw/nuw> - const unsigned OpCode = DU.NarrowUse->getOpcode(); - // Only Add/Sub/Mul instructions supported yet. - if (OpCode != Instruction::Add && OpCode != Instruction::Sub && - OpCode != Instruction::Mul) + auto Op = matchBinaryOp(DU.NarrowUse); + if (!Op) return {nullptr, ExtendKind::Unknown}; + assert((Op->Opcode == Instruction::Add || Op->Opcode == Instruction::Sub || + Op->Opcode == Instruction::Mul) && + "Unexpected opcode"); + // One operand (NarrowDef) has already been extended to WideDef. Now determine // if extending the other will lead to a recurrence. - const unsigned ExtendOperIdx = - DU.NarrowUse->getOperand(0) == DU.NarrowDef ? 1 : 0; - assert(DU.NarrowUse->getOperand(1-ExtendOperIdx) == DU.NarrowDef && "bad DU"); + const unsigned ExtendOperIdx = Op->Operands[0] == DU.NarrowDef ? 1 : 0; + assert(Op->Operands[1 - ExtendOperIdx] == DU.NarrowDef && "bad DU"); - const OverflowingBinaryOperator *OBO = - cast<OverflowingBinaryOperator>(DU.NarrowUse); ExtendKind ExtKind = getExtendKind(DU.NarrowDef); - if (!(ExtKind == ExtendKind::Sign && OBO->hasNoSignedWrap()) && - !(ExtKind == ExtendKind::Zero && OBO->hasNoUnsignedWrap())) { + if (!(ExtKind == ExtendKind::Sign && Op->IsNSW) && + !(ExtKind == ExtendKind::Zero && Op->IsNUW)) { ExtKind = ExtendKind::Unknown; // For a non-negative NarrowDef, we can choose either type of @@ -1413,16 +1482,15 @@ WidenIV::getExtendedOperandRecurrence(WidenIV::NarrowIVDefUse DU) { // (see above), and we only hit this code if we need to check // the opposite case. if (DU.NeverNegative) { - if (OBO->hasNoSignedWrap()) { + if (Op->IsNSW) { ExtKind = ExtendKind::Sign; - } else if (OBO->hasNoUnsignedWrap()) { + } else if (Op->IsNUW) { ExtKind = ExtendKind::Zero; } } } - const SCEV *ExtendOperExpr = - SE->getSCEV(DU.NarrowUse->getOperand(ExtendOperIdx)); + const SCEV *ExtendOperExpr = SE->getSCEV(Op->Operands[ExtendOperIdx]); if (ExtKind == ExtendKind::Sign) ExtendOperExpr = SE->getSignExtendExpr(ExtendOperExpr, WideType); else if (ExtKind == ExtendKind::Zero) @@ -1443,7 +1511,7 @@ WidenIV::getExtendedOperandRecurrence(WidenIV::NarrowIVDefUse DU) { if (ExtendOperIdx == 0) std::swap(lhs, rhs); const SCEVAddRecExpr *AddRec = - dyn_cast<SCEVAddRecExpr>(getSCEVByOpCode(lhs, rhs, OpCode)); + dyn_cast<SCEVAddRecExpr>(getSCEVByOpCode(lhs, rhs, Op->Opcode)); if (!AddRec || AddRec->getLoop() != L) return {nullptr, ExtendKind::Unknown}; diff --git a/llvm/lib/Transforms/Utils/ValueMapper.cpp b/llvm/lib/Transforms/Utils/ValueMapper.cpp index 3da161043d6c8c075fa448e024c963684124c48a..6ebdd85d37b431630bfa3947a53e74d2ad40d916 100644 --- a/llvm/lib/Transforms/Utils/ValueMapper.cpp +++ b/llvm/lib/Transforms/Utils/ValueMapper.cpp @@ -146,7 +146,7 @@ public: Value *mapValue(const Value *V); void remapInstruction(Instruction *I); void remapFunction(Function &F); - void remapDPValue(DbgRecord &DPV); + void remapDbgRecord(DbgRecord &DVR); Constant *mapConstant(const Constant *C) { return cast_or_null<Constant>(mapValue(C)); @@ -537,13 +537,13 @@ Value *Mapper::mapValue(const Value *V) { return getVM()[V] = ConstantPointerNull::get(cast<PointerType>(NewTy)); } -void Mapper::remapDPValue(DbgRecord &DR) { - if (DPLabel *DPL = dyn_cast<DPLabel>(&DR)) { - DPL->setLabel(cast<DILabel>(mapMetadata(DPL->getLabel()))); +void Mapper::remapDbgRecord(DbgRecord &DR) { + if (DbgLabelRecord *DLR = dyn_cast<DbgLabelRecord>(&DR)) { + DLR->setLabel(cast<DILabel>(mapMetadata(DLR->getLabel()))); return; } - DPValue &V = cast<DPValue>(DR); + DbgVariableRecord &V = cast<DbgVariableRecord>(DR); // Remap variables and DILocations. auto *MappedVar = mapMetadata(V.getVariable()); auto *MappedDILoc = mapMetadata(V.getDebugLoc()); @@ -1067,7 +1067,7 @@ void Mapper::remapFunction(Function &F) { for (Instruction &I : BB) { remapInstruction(&I); for (DbgRecord &DR : I.getDbgRecordRange()) - remapDPValue(DR); + remapDbgRecord(DR); } } } @@ -1233,14 +1233,14 @@ void ValueMapper::remapInstruction(Instruction &I) { FlushingMapper(pImpl)->remapInstruction(&I); } -void ValueMapper::remapDPValue(Module *M, DPValue &V) { - FlushingMapper(pImpl)->remapDPValue(V); +void ValueMapper::remapDbgVariableRecord(Module *M, DbgVariableRecord &V) { + FlushingMapper(pImpl)->remapDbgRecord(V); } -void ValueMapper::remapDPValueRange( +void ValueMapper::remapDbgVariableRecordRange( Module *M, iterator_range<DbgRecord::self_iterator> Range) { - for (DPValue &DPV : DPValue::filter(Range)) { - remapDPValue(M, DPV); + for (DbgVariableRecord &DVR : filterDbgVars(Range)) { + remapDbgVariableRecord(M, DVR); } } diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h index a7ebf78e54ceb612bcce06b960b0e812bf447118..ebca2d855a4676b93ee5549b5600213485a2506e 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h +++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h @@ -68,6 +68,9 @@ class VPBuilder { public: VPBuilder() = default; VPBuilder(VPBasicBlock *InsertBB) { setInsertPoint(InsertBB); } + VPBuilder(VPRecipeBase *InsertPt) { + setInsertPoint(InsertPt->getParent(), InsertPt->getIterator()); + } /// Clear the insertion point: created instructions will not be inserted into /// a block. @@ -79,6 +82,13 @@ public: VPBasicBlock *getInsertBlock() const { return BB; } VPBasicBlock::iterator getInsertPoint() const { return InsertPt; } + /// Create a VPBuilder to insert after \p R. + static VPBuilder getToInsertAfter(VPRecipeBase *R) { + VPBuilder B; + B.setInsertPoint(R->getParent(), std::next(R->getIterator())); + return B; + } + /// InsertPoint - A saved insertion point. class VPInsertPoint { VPBasicBlock *Block = nullptr; @@ -131,8 +141,9 @@ public: /// Create an N-ary operation with \p Opcode, \p Operands and set \p Inst as /// its underlying Instruction. - VPValue *createNaryOp(unsigned Opcode, ArrayRef<VPValue *> Operands, - Instruction *Inst = nullptr, const Twine &Name = "") { + VPInstruction *createNaryOp(unsigned Opcode, ArrayRef<VPValue *> Operands, + Instruction *Inst = nullptr, + const Twine &Name = "") { DebugLoc DL; if (Inst) DL = Inst->getDebugLoc(); @@ -140,8 +151,8 @@ public: NewVPInst->setUnderlyingValue(Inst); return NewVPInst; } - VPValue *createNaryOp(unsigned Opcode, ArrayRef<VPValue *> Operands, - DebugLoc DL, const Twine &Name = "") { + VPInstruction *createNaryOp(unsigned Opcode, ArrayRef<VPValue *> Operands, + DebugLoc DL, const Twine &Name = "") { return createInstruction(Opcode, Operands, DL, Name); } @@ -164,7 +175,10 @@ public: VPValue *createOr(VPValue *LHS, VPValue *RHS, DebugLoc DL = {}, const Twine &Name = "") { - return createInstruction(Instruction::BinaryOps::Or, {LHS, RHS}, DL, Name); + + return tryInsertInstruction(new VPInstruction( + Instruction::BinaryOps::Or, {LHS, RHS}, + VPRecipeWithIRFlags::DisjointFlagsTy(false), DL, Name)); } VPValue *createSelect(VPValue *Cond, VPValue *TrueVal, VPValue *FalseVal, diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index edaad4d033bdf06261a6272c4ec1fb841c8382a0..0834865173b2f1afb73eb8a1bb7b5e8b5902c4b2 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -6911,25 +6911,10 @@ LoopVectorizationCostModel::getInstructionCost(Instruction *I, ElementCount VF, Op2Info.Kind = TargetTransformInfo::OK_UniformValue; SmallVector<const Value *, 4> Operands(I->operand_values()); - auto InstrCost = TTI.getArithmeticInstrCost( + return TTI.getArithmeticInstrCost( I->getOpcode(), VectorTy, CostKind, {TargetTransformInfo::OK_AnyValue, TargetTransformInfo::OP_None}, - Op2Info, Operands, I); - - // Some targets can replace frem with vector library calls. - InstructionCost VecCallCost = InstructionCost::getInvalid(); - if (I->getOpcode() == Instruction::FRem) { - LibFunc Func; - if (TLI->getLibFunc(I->getOpcode(), I->getType(), Func) && - TLI->isFunctionVectorizable(TLI->getName(Func), VF)) { - SmallVector<Type *, 4> OpTypes; - for (auto &Op : I->operands()) - OpTypes.push_back(Op->getType()); - VecCallCost = - TTI.getCallInstrCost(nullptr, VectorTy, OpTypes, CostKind); - } - } - return std::min(InstrCost, VecCallCost); + Op2Info, Operands, I, TLI); } case Instruction::FNeg: { return TTI.getArithmeticInstrCost( @@ -7913,8 +7898,19 @@ void LoopVectorizationPlanner::buildVPlans(ElementCount MinVF, } } -VPValue *VPRecipeBuilder::createEdgeMask(BasicBlock *Src, BasicBlock *Dst, - VPlan &Plan) { +iterator_range<mapped_iterator<Use *, std::function<VPValue *(Value *)>>> +VPRecipeBuilder::mapToVPValues(User::op_range Operands) { + std::function<VPValue *(Value *)> Fn = [this](Value *Op) { + if (auto *I = dyn_cast<Instruction>(Op)) { + if (auto *R = Ingredient2Recipe.lookup(I)) + return R->getVPSingleValue(); + } + return Plan.getOrAddLiveIn(Op); + }; + return map_range(Operands, Fn); +} + +VPValue *VPRecipeBuilder::createEdgeMask(BasicBlock *Src, BasicBlock *Dst) { assert(is_contained(predecessors(Dst), Src) && "Invalid edge"); // Look for cached value. @@ -7938,7 +7934,7 @@ VPValue *VPRecipeBuilder::createEdgeMask(BasicBlock *Src, BasicBlock *Dst, if (OrigLoop->isLoopExiting(Src)) return EdgeMaskCache[Edge] = SrcMask; - VPValue *EdgeMask = Plan.getVPValueOrAddLiveIn(BI->getCondition()); + VPValue *EdgeMask = getVPValueOrAddLiveIn(BI->getCondition(), Plan); assert(EdgeMask && "No Edge Mask found for condition"); if (BI->getSuccessor(0) != Dst) @@ -7949,7 +7945,7 @@ VPValue *VPRecipeBuilder::createEdgeMask(BasicBlock *Src, BasicBlock *Dst, // 'select i1 SrcMask, i1 EdgeMask, i1 false'. // The select version does not introduce new UB if SrcMask is false and // EdgeMask is poison. Using 'and' here introduces undefined behavior. - VPValue *False = Plan.getVPValueOrAddLiveIn( + VPValue *False = Plan.getOrAddLiveIn( ConstantInt::getFalse(BI->getCondition()->getType())); EdgeMask = Builder.createSelect(SrcMask, EdgeMask, False, BI->getDebugLoc()); @@ -7969,7 +7965,7 @@ VPValue *VPRecipeBuilder::getEdgeMask(BasicBlock *Src, BasicBlock *Dst) const { return ECEntryIt->second; } -void VPRecipeBuilder::createHeaderMask(VPlan &Plan) { +void VPRecipeBuilder::createHeaderMask() { BasicBlock *Header = OrigLoop->getHeader(); // When not folding the tail, use nullptr to model all-true mask. @@ -8004,7 +8000,7 @@ VPValue *VPRecipeBuilder::getBlockInMask(BasicBlock *BB) const { return BCEntryIt->second; } -void VPRecipeBuilder::createBlockInMask(BasicBlock *BB, VPlan &Plan) { +void VPRecipeBuilder::createBlockInMask(BasicBlock *BB) { assert(OrigLoop->contains(BB) && "Block is not a part of a loop"); assert(BlockMaskCache.count(BB) == 0 && "Mask for block already computed"); assert(OrigLoop->getHeader() != BB && @@ -8015,7 +8011,7 @@ void VPRecipeBuilder::createBlockInMask(BasicBlock *BB, VPlan &Plan) { VPValue *BlockMask = nullptr; // This is the block mask. We OR all incoming edges. for (auto *Predecessor : predecessors(BB)) { - VPValue *EdgeMask = createEdgeMask(Predecessor, BB, Plan); + VPValue *EdgeMask = createEdgeMask(Predecessor, BB); if (!EdgeMask) { // Mask of predecessor is all-one so mask of block is too. BlockMaskCache[BB] = EdgeMask; return; @@ -8034,7 +8030,7 @@ void VPRecipeBuilder::createBlockInMask(BasicBlock *BB, VPlan &Plan) { VPWidenMemoryInstructionRecipe * VPRecipeBuilder::tryToWidenMemory(Instruction *I, ArrayRef<VPValue *> Operands, - VFRange &Range, VPlanPtr &Plan) { + VFRange &Range) { assert((isa<LoadInst>(I) || isa<StoreInst>(I)) && "Must be called with either a load or store"); @@ -8078,11 +8074,11 @@ VPRecipeBuilder::tryToWidenMemory(Instruction *I, ArrayRef<VPValue *> Operands, } if (LoadInst *Load = dyn_cast<LoadInst>(I)) return new VPWidenMemoryInstructionRecipe(*Load, Ptr, Mask, Consecutive, - Reverse); + Reverse, I->getDebugLoc()); StoreInst *Store = cast<StoreInst>(I); - return new VPWidenMemoryInstructionRecipe(*Store, Ptr, Operands[0], Mask, - Consecutive, Reverse); + return new VPWidenMemoryInstructionRecipe( + *Store, Ptr, Operands[0], Mask, Consecutive, Reverse, I->getDebugLoc()); } /// Creates a VPWidenIntOrFpInductionRecpipe for \p Phi. If needed, it will also @@ -8107,7 +8103,7 @@ createWidenInductionRecipes(PHINode *Phi, Instruction *PhiOrTrunc, } VPHeaderPHIRecipe *VPRecipeBuilder::tryToOptimizeInductionPHI( - PHINode *Phi, ArrayRef<VPValue *> Operands, VPlan &Plan, VFRange &Range) { + PHINode *Phi, ArrayRef<VPValue *> Operands, VFRange &Range) { // Check if this is an integer or fp induction. If so, build the recipe that // produces its scalar and vector values. @@ -8131,7 +8127,7 @@ VPHeaderPHIRecipe *VPRecipeBuilder::tryToOptimizeInductionPHI( } VPWidenIntOrFpInductionRecipe *VPRecipeBuilder::tryToOptimizeInductionTruncate( - TruncInst *I, ArrayRef<VPValue *> Operands, VFRange &Range, VPlan &Plan) { + TruncInst *I, ArrayRef<VPValue *> Operands, VFRange &Range) { // Optimize the special case where the source is a constant integer // induction variable. Notice that we can only optimize the 'trunc' case // because (a) FP conversions lose precision, (b) sext/zext may wrap, and @@ -8151,7 +8147,7 @@ VPWidenIntOrFpInductionRecipe *VPRecipeBuilder::tryToOptimizeInductionTruncate( auto *Phi = cast<PHINode>(I->getOperand(0)); const InductionDescriptor &II = *Legal->getIntOrFpInductionDescriptor(Phi); - VPValue *Start = Plan.getVPValueOrAddLiveIn(II.getStartValue()); + VPValue *Start = Plan.getOrAddLiveIn(II.getStartValue()); return createWidenInductionRecipes(Phi, I, Start, II, Plan, *PSE.getSE(), *OrigLoop, Range); } @@ -8159,8 +8155,7 @@ VPWidenIntOrFpInductionRecipe *VPRecipeBuilder::tryToOptimizeInductionTruncate( } VPBlendRecipe *VPRecipeBuilder::tryToBlend(PHINode *Phi, - ArrayRef<VPValue *> Operands, - VPlanPtr &Plan) { + ArrayRef<VPValue *> Operands) { unsigned NumIncoming = Phi->getNumIncomingValues(); // We know that all PHIs in non-header blocks are converted into selects, so @@ -8173,7 +8168,7 @@ VPBlendRecipe *VPRecipeBuilder::tryToBlend(PHINode *Phi, for (unsigned In = 0; In < NumIncoming; In++) { OperandsWithMask.push_back(Operands[In]); VPValue *EdgeMask = - createEdgeMask(Phi->getIncomingBlock(In), Phi->getParent(), *Plan); + createEdgeMask(Phi->getIncomingBlock(In), Phi->getParent()); if (!EdgeMask) { assert(In == 0 && "Both null and non-null edge masks found"); assert(all_equal(Operands) && @@ -8187,8 +8182,7 @@ VPBlendRecipe *VPRecipeBuilder::tryToBlend(PHINode *Phi, VPWidenCallRecipe *VPRecipeBuilder::tryToWidenCall(CallInst *CI, ArrayRef<VPValue *> Operands, - VFRange &Range, - VPlanPtr &Plan) { + VFRange &Range) { bool IsPredicated = LoopVectorizationPlanner::getDecisionAndClampRange( [this, CI](ElementCount VF) { return CM.isScalarWithPredication(CI, VF); @@ -8263,7 +8257,7 @@ VPWidenCallRecipe *VPRecipeBuilder::tryToWidenCall(CallInst *CI, if (Legal->isMaskRequired(CI)) Mask = getBlockInMask(CI->getParent()); else - Mask = Plan->getVPValueOrAddLiveIn(ConstantInt::getTrue( + Mask = Plan.getOrAddLiveIn(ConstantInt::getTrue( IntegerType::getInt1Ty(Variant->getFunctionType()->getContext()))); Ops.insert(Ops.begin() + *MaskPos, Mask); @@ -8293,7 +8287,7 @@ bool VPRecipeBuilder::shouldWiden(Instruction *I, VFRange &Range) const { VPWidenRecipe *VPRecipeBuilder::tryToWiden(Instruction *I, ArrayRef<VPValue *> Operands, - VPBasicBlock *VPBB, VPlanPtr &Plan) { + VPBasicBlock *VPBB) { switch (I->getOpcode()) { default: return nullptr; @@ -8306,8 +8300,8 @@ VPWidenRecipe *VPRecipeBuilder::tryToWiden(Instruction *I, if (CM.isPredicatedInst(I)) { SmallVector<VPValue *> Ops(Operands.begin(), Operands.end()); VPValue *Mask = getBlockInMask(I->getParent()); - VPValue *One = Plan->getVPValueOrAddLiveIn( - ConstantInt::get(I->getType(), 1u, false)); + VPValue *One = + Plan.getOrAddLiveIn(ConstantInt::get(I->getType(), 1u, false)); auto *SafeRHS = new VPInstruction(Instruction::Select, {Mask, Ops[1], One}, I->getDebugLoc()); @@ -8351,8 +8345,7 @@ void VPRecipeBuilder::fixHeaderPhis() { } VPReplicateRecipe *VPRecipeBuilder::handleReplication(Instruction *I, - VFRange &Range, - VPlan &Plan) { + VFRange &Range) { bool IsUniform = LoopVectorizationPlanner::getDecisionAndClampRange( [&](ElementCount VF) { return CM.isUniformAfterVectorization(I, VF); }, Range); @@ -8402,26 +8395,23 @@ VPReplicateRecipe *VPRecipeBuilder::handleReplication(Instruction *I, BlockInMask = getBlockInMask(I->getParent()); } - auto *Recipe = new VPReplicateRecipe(I, Plan.mapToVPValues(I->operands()), + auto *Recipe = new VPReplicateRecipe(I, mapToVPValues(I->operands()), IsUniform, BlockInMask); return Recipe; } -VPRecipeBase *VPRecipeBuilder::tryToCreateWidenRecipe( - Instruction *Instr, ArrayRef<VPValue *> Operands, VFRange &Range, - VPBasicBlock *VPBB, VPlanPtr &Plan) { +VPRecipeBase * +VPRecipeBuilder::tryToCreateWidenRecipe(Instruction *Instr, + ArrayRef<VPValue *> Operands, + VFRange &Range, VPBasicBlock *VPBB) { // First, check for specific widening recipes that deal with inductions, Phi // nodes, calls and memory operations. VPRecipeBase *Recipe; if (auto Phi = dyn_cast<PHINode>(Instr)) { if (Phi->getParent() != OrigLoop->getHeader()) - return tryToBlend(Phi, Operands, Plan); + return tryToBlend(Phi, Operands); - // Always record recipes for header phis. Later first-order recurrence phis - // can have earlier phis as incoming values. - recordRecipeOf(Phi); - - if ((Recipe = tryToOptimizeInductionPHI(Phi, Operands, *Plan, Range))) + if ((Recipe = tryToOptimizeInductionPHI(Phi, Operands, Range))) return Recipe; VPHeaderPHIRecipe *PhiRecipe = nullptr; @@ -8445,21 +8435,12 @@ VPRecipeBase *VPRecipeBuilder::tryToCreateWidenRecipe( PhiRecipe = new VPFirstOrderRecurrencePHIRecipe(Phi, *StartV); } - // Record the incoming value from the backedge, so we can add the incoming - // value from the backedge after all recipes have been created. - auto *Inc = cast<Instruction>( - Phi->getIncomingValueForBlock(OrigLoop->getLoopLatch())); - auto RecipeIter = Ingredient2Recipe.find(Inc); - if (RecipeIter == Ingredient2Recipe.end()) - recordRecipeOf(Inc); - PhisToFix.push_back(PhiRecipe); return PhiRecipe; } - if (isa<TruncInst>(Instr) && - (Recipe = tryToOptimizeInductionTruncate(cast<TruncInst>(Instr), Operands, - Range, *Plan))) + if (isa<TruncInst>(Instr) && (Recipe = tryToOptimizeInductionTruncate( + cast<TruncInst>(Instr), Operands, Range))) return Recipe; // All widen recipes below deal only with VF > 1. @@ -8468,10 +8449,10 @@ VPRecipeBase *VPRecipeBuilder::tryToCreateWidenRecipe( return nullptr; if (auto *CI = dyn_cast<CallInst>(Instr)) - return tryToWidenCall(CI, Operands, Range, Plan); + return tryToWidenCall(CI, Operands, Range); if (isa<LoadInst>(Instr) || isa<StoreInst>(Instr)) - return tryToWidenMemory(Instr, Operands, Range, Plan); + return tryToWidenMemory(Instr, Operands, Range); if (!shouldWiden(Instr, Range)) return nullptr; @@ -8490,7 +8471,7 @@ VPRecipeBase *VPRecipeBuilder::tryToCreateWidenRecipe( *CI); } - return tryToWiden(Instr, Operands, VPBB, Plan); + return tryToWiden(Instr, Operands, VPBB); } void LoopVectorizationPlanner::buildVPlansWithVPRecipes(ElementCount MinVF, @@ -8518,7 +8499,7 @@ void LoopVectorizationPlanner::buildVPlansWithVPRecipes(ElementCount MinVF, static void addCanonicalIVRecipes(VPlan &Plan, Type *IdxTy, bool HasNUW, DebugLoc DL) { Value *StartIdx = ConstantInt::get(IdxTy, 0); - auto *StartV = Plan.getVPValueOrAddLiveIn(StartIdx); + auto *StartV = Plan.getOrAddLiveIn(StartIdx); // Add a VPCanonicalIVPHIRecipe starting at 0 to the header. auto *CanonicalIVPHI = new VPCanonicalIVPHIRecipe(StartV, DL); @@ -8541,7 +8522,7 @@ static void addCanonicalIVRecipes(VPlan &Plan, Type *IdxTy, bool HasNUW, // Add exit values to \p Plan. VPLiveOuts are added for each LCSSA phi in the // original exit block. static void addUsersInExitBlock(VPBasicBlock *HeaderVPBB, Loop *OrigLoop, - VPlan &Plan) { + VPRecipeBuilder &Builder, VPlan &Plan) { BasicBlock *ExitBB = OrigLoop->getUniqueExitBlock(); BasicBlock *ExitingBB = OrigLoop->getExitingBlock(); // Only handle single-exit loops with unique exit blocks for now. @@ -8552,7 +8533,7 @@ static void addUsersInExitBlock(VPBasicBlock *HeaderVPBB, Loop *OrigLoop, for (PHINode &ExitPhi : ExitBB->phis()) { Value *IncomingValue = ExitPhi.getIncomingValueForBlock(ExitingBB); - VPValue *V = Plan.getVPValueOrAddLiveIn(IncomingValue); + VPValue *V = Builder.getVPValueOrAddLiveIn(IncomingValue, Plan); Plan.addLiveOut(&ExitPhi, V); } } @@ -8562,37 +8543,6 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) { SmallPtrSet<const InterleaveGroup<Instruction> *, 1> InterleaveGroups; - VPRecipeBuilder RecipeBuilder(OrigLoop, TLI, Legal, CM, PSE, Builder); - - // --------------------------------------------------------------------------- - // Pre-construction: record ingredients whose recipes we'll need to further - // process after constructing the initial VPlan. - // --------------------------------------------------------------------------- - - // For each interleave group which is relevant for this (possibly trimmed) - // Range, add it to the set of groups to be later applied to the VPlan and add - // placeholders for its members' Recipes which we'll be replacing with a - // single VPInterleaveRecipe. - for (InterleaveGroup<Instruction> *IG : IAI.getInterleaveGroups()) { - auto applyIG = [IG, this](ElementCount VF) -> bool { - bool Result = (VF.isVector() && // Query is illegal for VF == 1 - CM.getWideningDecision(IG->getInsertPos(), VF) == - LoopVectorizationCostModel::CM_Interleave); - // For scalable vectors, the only interleave factor currently supported - // is 2 since we require the (de)interleave2 intrinsics instead of - // shufflevectors. - assert((!Result || !VF.isScalable() || IG->getFactor() == 2) && - "Unsupported interleave factor for scalable vectors"); - return Result; - }; - if (!getDecisionAndClampRange(applyIG, Range)) - continue; - InterleaveGroups.insert(IG); - for (unsigned i = 0; i < IG->getFactor(); i++) - if (Instruction *Member = IG->getMember(i)) - RecipeBuilder.recordRecipeOf(Member); - }; - // --------------------------------------------------------------------------- // Build initial VPlan: Scan the body of the loop in a topological order to // visit each basic block after having visited its predecessor basic blocks. @@ -8627,6 +8577,38 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) { bool HasNUW = Style == TailFoldingStyle::None; addCanonicalIVRecipes(*Plan, Legal->getWidestInductionType(), HasNUW, DL); + VPRecipeBuilder RecipeBuilder(*Plan, OrigLoop, TLI, Legal, CM, PSE, Builder); + + // --------------------------------------------------------------------------- + // Pre-construction: record ingredients whose recipes we'll need to further + // process after constructing the initial VPlan. + // --------------------------------------------------------------------------- + + // For each interleave group which is relevant for this (possibly trimmed) + // Range, add it to the set of groups to be later applied to the VPlan and add + // placeholders for its members' Recipes which we'll be replacing with a + // single VPInterleaveRecipe. + for (InterleaveGroup<Instruction> *IG : IAI.getInterleaveGroups()) { + auto applyIG = [IG, this](ElementCount VF) -> bool { + bool Result = (VF.isVector() && // Query is illegal for VF == 1 + CM.getWideningDecision(IG->getInsertPos(), VF) == + LoopVectorizationCostModel::CM_Interleave); + // For scalable vectors, the only interleave factor currently supported + // is 2 since we require the (de)interleave2 intrinsics instead of + // shufflevectors. + assert((!Result || !VF.isScalable() || IG->getFactor() == 2) && + "Unsupported interleave factor for scalable vectors"); + return Result; + }; + if (!getDecisionAndClampRange(applyIG, Range)) + continue; + InterleaveGroups.insert(IG); + }; + + // --------------------------------------------------------------------------- + // Construct recipes for the instructions in the loop + // --------------------------------------------------------------------------- + // Scan the body of the loop in a topological order to visit each basic block // after having visited its predecessor basic blocks. LoopBlocksDFS DFS(OrigLoop); @@ -8648,9 +8630,9 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) { Builder.setInsertPoint(VPBB); if (VPBB == HeaderVPBB) - RecipeBuilder.createHeaderMask(*Plan); + RecipeBuilder.createHeaderMask(); else if (NeedsMasks) - RecipeBuilder.createBlockInMask(BB, *Plan); + RecipeBuilder.createBlockInMask(BB); // Introduce each ingredient into VPlan. // TODO: Model and preserve debug intrinsics in VPlan. @@ -8659,10 +8641,10 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) { SmallVector<VPValue *, 4> Operands; auto *Phi = dyn_cast<PHINode>(Instr); if (Phi && Phi->getParent() == HeaderBB) { - Operands.push_back(Plan->getVPValueOrAddLiveIn( + Operands.push_back(Plan->getOrAddLiveIn( Phi->getIncomingValueForBlock(OrigLoop->getLoopPreheader()))); } else { - auto OpRange = Plan->mapToVPValues(Instr->operands()); + auto OpRange = RecipeBuilder.mapToVPValues(Instr->operands()); Operands = {OpRange.begin(), OpRange.end()}; } @@ -8673,14 +8655,10 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) { Legal->isInvariantAddressOfReduction(SI->getPointerOperand())) continue; - VPRecipeBase *Recipe = RecipeBuilder.tryToCreateWidenRecipe( - Instr, Operands, Range, VPBB, Plan); + VPRecipeBase *Recipe = + RecipeBuilder.tryToCreateWidenRecipe(Instr, Operands, Range, VPBB); if (!Recipe) - Recipe = RecipeBuilder.handleReplication(Instr, Range, *Plan); - for (auto *Def : Recipe->definedValues()) { - auto *UV = Def->getUnderlyingValue(); - Plan->addVPValue(UV, Def); - } + Recipe = RecipeBuilder.handleReplication(Instr, Range); RecipeBuilder.setRecipe(Instr, Recipe); if (isa<VPHeaderPHIRecipe>(Recipe)) { @@ -8712,7 +8690,7 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) { // and there is nothing to fix from vector loop; phis should have incoming // from scalar loop only. } else - addUsersInExitBlock(HeaderVPBB, OrigLoop, *Plan); + addUsersInExitBlock(HeaderVPBB, OrigLoop, RecipeBuilder, *Plan); assert(isa<VPRegionBlock>(Plan->getVectorLoopRegion()) && !Plan->getVectorLoopRegion()->getEntryBasicBlock()->empty() && @@ -8774,16 +8752,12 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) { continue; Constant *CI = ConstantInt::get(Stride->getType(), ScevStride->getAPInt()); - auto *ConstVPV = Plan->getVPValueOrAddLiveIn(CI); + auto *ConstVPV = Plan->getOrAddLiveIn(CI); // The versioned value may not be used in the loop directly, so just add a // new live-in in those cases. - Plan->getVPValueOrAddLiveIn(StrideV)->replaceAllUsesWith(ConstVPV); + Plan->getOrAddLiveIn(StrideV)->replaceAllUsesWith(ConstVPV); } - // From this point onwards, VPlan-to-VPlan transformations may change the plan - // in ways that accessing values using original IR values is incorrect. - Plan->disableValue2VPValue(); - VPlanTransforms::dropPoisonGeneratingRecipes(*Plan, [this](BasicBlock *BB) { return Legal->blockNeedsPredication(BB); }); @@ -9137,42 +9111,11 @@ void VPWidenPointerInductionRecipe::execute(VPTransformState &State) { "Not a pointer induction according to InductionDescriptor!"); assert(cast<PHINode>(getUnderlyingInstr())->getType()->isPointerTy() && "Unexpected type."); + assert(!onlyScalarsGenerated(State.VF.isScalable()) && + "Recipe should have been replaced"); auto *IVR = getParent()->getPlan()->getCanonicalIV(); PHINode *CanonicalIV = cast<PHINode>(State.get(IVR, 0, /*IsScalar*/ true)); - - if (onlyScalarsGenerated(State.VF.isScalable())) { - // This is the normalized GEP that starts counting at zero. - Value *PtrInd = State.Builder.CreateSExtOrTrunc( - CanonicalIV, IndDesc.getStep()->getType()); - // Determine the number of scalars we need to generate for each unroll - // iteration. If the instruction is uniform, we only need to generate the - // first lane. Otherwise, we generate all VF values. - bool IsUniform = vputils::onlyFirstLaneUsed(this); - assert((IsUniform || !State.VF.isScalable()) && - "Cannot scalarize a scalable VF"); - unsigned Lanes = IsUniform ? 1 : State.VF.getFixedValue(); - - for (unsigned Part = 0; Part < State.UF; ++Part) { - Value *PartStart = - createStepForVF(State.Builder, PtrInd->getType(), State.VF, Part); - - for (unsigned Lane = 0; Lane < Lanes; ++Lane) { - Value *Idx = State.Builder.CreateAdd( - PartStart, ConstantInt::get(PtrInd->getType(), Lane)); - Value *GlobalIdx = State.Builder.CreateAdd(PtrInd, Idx); - - Value *Step = State.get(getOperand(1), VPIteration(Part, Lane)); - Value *SclrGep = emitTransformedIndex( - State.Builder, GlobalIdx, IndDesc.getStartValue(), Step, - IndDesc.getKind(), IndDesc.getInductionBinOp()); - SclrGep->setName("next.gep"); - State.set(this, SclrGep, VPIteration(Part, Lane)); - } - } - return; - } - Type *PhiType = IndDesc.getStep()->getType(); // Build a pointer phi @@ -9397,7 +9340,7 @@ void VPWidenMemoryInstructionRecipe::execute(VPTransformState &State) { // Handle Stores: if (SI) { - State.setDebugLocFrom(SI->getDebugLoc()); + State.setDebugLocFrom(getDebugLoc()); for (unsigned Part = 0; Part < State.UF; ++Part) { Instruction *NewSI = nullptr; @@ -9429,7 +9372,7 @@ void VPWidenMemoryInstructionRecipe::execute(VPTransformState &State) { // Handle loads. assert(LI && "Must have a load instruction"); - State.setDebugLocFrom(LI->getDebugLoc()); + State.setDebugLocFrom(getDebugLoc()); for (unsigned Part = 0; Part < State.UF; ++Part) { Value *NewLI; if (CreateGatherScatter) { @@ -10082,7 +10025,7 @@ bool LoopVectorizePass::processLoop(Loop *L) { EpilogILV.setTripCount(MainILV.getTripCount()); for (auto &R : make_early_inc_range(*BestEpiPlan.getPreheader())) { auto *ExpandR = cast<VPExpandSCEVRecipe>(&R); - auto *ExpandedVal = BestEpiPlan.getVPValueOrAddLiveIn( + auto *ExpandedVal = BestEpiPlan.getOrAddLiveIn( ExpandedSCEVs.find(ExpandR->getSCEV())->second); ExpandR->replaceAllUsesWith(ExpandedVal); if (BestEpiPlan.getTripCount() == ExpandR) @@ -10123,7 +10066,7 @@ bool LoopVectorizePass::processLoop(Loop *L) { {EPI.MainLoopIterationCountCheck}); } assert(ResumeV && "Must have a resume value"); - VPValue *StartVal = BestEpiPlan.getVPValueOrAddLiveIn(ResumeV); + VPValue *StartVal = BestEpiPlan.getOrAddLiveIn(ResumeV); cast<VPHeaderPHIRecipe>(&R)->setStartValue(StartVal); } diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index b8b67609d755fdf31afa7c6fd974c7f6930eb9c7..6e7dcb9fc63ed12508cc39834b7967d9cd07f892 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -458,8 +458,7 @@ static SmallBitVector isUndefVector(const Value *V, /// ShuffleVectorInst/getShuffleCost? static std::optional<TargetTransformInfo::ShuffleKind> isFixedVectorShuffle(ArrayRef<Value *> VL, SmallVectorImpl<int> &Mask) { - const auto *It = - find_if(VL, [](Value *V) { return isa<ExtractElementInst>(V); }); + const auto *It = find_if(VL, IsaPred<ExtractElementInst>); if (It == VL.end()) return std::nullopt; auto *EI0 = cast<ExtractElementInst>(*It); @@ -1001,8 +1000,9 @@ public: TargetLibraryInfo *TLi, AAResults *Aa, LoopInfo *Li, DominatorTree *Dt, AssumptionCache *AC, DemandedBits *DB, const DataLayout *DL, OptimizationRemarkEmitter *ORE) - : BatchAA(*Aa), F(Func), SE(Se), TTI(Tti), TLI(TLi), LI(Li), - DT(Dt), AC(AC), DB(DB), DL(DL), ORE(ORE), Builder(Se->getContext()) { + : BatchAA(*Aa), F(Func), SE(Se), TTI(Tti), TLI(TLi), LI(Li), DT(Dt), + AC(AC), DB(DB), DL(DL), ORE(ORE), + Builder(Se->getContext(), TargetFolder(*DL)) { CodeMetrics::collectEphemeralValues(F, AC, EphValues); // Use the vector register size specified by the target unless overridden // by a command-line option. @@ -1085,6 +1085,9 @@ public: BS->clear(); } MinBWs.clear(); + ReductionBitWidth = 0; + CastMaxMinBWSizes.reset(); + TruncNodes.clear(); InstrElementSize.clear(); UserIgnoreList = nullptr; PostponedGathers.clear(); @@ -2018,9 +2021,8 @@ public: public: /// Initialize with all the operands of the instruction vector \p RootVL. - VLOperands(ArrayRef<Value *> RootVL, const TargetLibraryInfo &TLI, - const DataLayout &DL, ScalarEvolution &SE, const BoUpSLP &R) - : TLI(TLI), DL(DL), SE(SE), R(R) { + VLOperands(ArrayRef<Value *> RootVL, const BoUpSLP &R) + : TLI(*R.TLI), DL(*R.DL), SE(*R.SE), R(R) { // Append all the operands of RootVL. appendOperandsOfVL(RootVL); } @@ -2235,7 +2237,7 @@ public: /// of the cost, considered to be good enough score. std::optional<int> findBestRootPair(ArrayRef<std::pair<Value *, Value *>> Candidates, - int Limit = LookAheadHeuristics::ScoreFail) { + int Limit = LookAheadHeuristics::ScoreFail) const { LookAheadHeuristics LookAhead(*TLI, *DL, *SE, *this, /*NumLanes=*/2, RootLookAheadMaxDepth); int BestScore = Limit; @@ -2287,6 +2289,7 @@ public: void clearReductionData() { AnalyzedReductionsRoots.clear(); AnalyzedReductionVals.clear(); + AnalyzedMinBWVals.clear(); } /// Checks if the given value is gathered in one of the nodes. bool isAnyGathered(const SmallDenseSet<Value *> &Vals) const { @@ -2307,9 +2310,11 @@ private: /// constant and to be demoted. Required to correctly identify constant nodes /// to be demoted. bool collectValuesToDemote( - Value *V, SmallVectorImpl<Value *> &ToDemote, + Value *V, bool IsProfitableToDemoteRoot, unsigned &BitWidth, + SmallVectorImpl<Value *> &ToDemote, DenseMap<Instruction *, SmallVector<unsigned>> &DemotedConsts, - SmallVectorImpl<Value *> &Roots, DenseSet<Value *> &Visited) const; + DenseSet<Value *> &Visited, unsigned &MaxDepthLevel, + bool &IsProfitableToDemote, bool IsTruncRoot) const; /// Check if the operands on the edges \p Edges of the \p UserTE allows /// reordering (i.e. the operands can be reordered because they have only one @@ -2375,6 +2380,10 @@ private: /// \ returns the graph entry for the \p Idx operand of the \p E entry. const TreeEntry *getOperandEntry(const TreeEntry *E, unsigned Idx) const; + /// \returns Cast context for the given graph node. + TargetTransformInfo::CastContextHint + getCastContextHint(const TreeEntry &TE) const; + /// \returns the cost of the vectorizable entry. InstructionCost getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals, @@ -2495,10 +2504,10 @@ private: /// Reorder commutative or alt operands to get better probability of /// generating vectorized code. - static void reorderInputsAccordingToOpcode( - ArrayRef<Value *> VL, SmallVectorImpl<Value *> &Left, - SmallVectorImpl<Value *> &Right, const TargetLibraryInfo &TLI, - const DataLayout &DL, ScalarEvolution &SE, const BoUpSLP &R); + static void reorderInputsAccordingToOpcode(ArrayRef<Value *> VL, + SmallVectorImpl<Value *> &Left, + SmallVectorImpl<Value *> &Right, + const BoUpSLP &R); /// Helper for `findExternalStoreUsersReorderIndices()`. It iterates over the /// users of \p TE and collects the stores. It returns the map from the store @@ -2925,11 +2934,18 @@ private: } assert(!BundleMember && "Bundle and VL out of sync"); } else { - MustGather.insert(VL.begin(), VL.end()); // Build a map for gathered scalars to the nodes where they are used. + bool AllConstsOrCasts = true; for (Value *V : VL) - if (!isConstant(V)) + if (!isConstant(V)) { + auto *I = dyn_cast<CastInst>(V); + AllConstsOrCasts &= I && I->getType()->isIntegerTy(); ValueToGatherNodes.try_emplace(V).first->getSecond().insert(Last); + } + if (AllConstsOrCasts) + CastMaxMinBWSizes = + std::make_pair(std::numeric_limits<unsigned>::max(), 1); + MustGather.insert(VL.begin(), VL.end()); } if (UserTreeIdx.UserTE) @@ -3054,6 +3070,10 @@ private: /// Set of hashes for the list of reduction values already being analyzed. DenseSet<size_t> AnalyzedReductionVals; + /// Values, already been analyzed for mininmal bitwidth and found to be + /// non-profitable. + DenseSet<Value *> AnalyzedMinBWVals; + /// A list of values that need to extracted out of the tree. /// This list holds pairs of (Internal Scalar : External User). External User /// can be nullptr, it means that this Internal Scalar will be used later, @@ -3621,7 +3641,7 @@ private: unsigned MinVecRegSize; // Set by cl::opt (default: 128). /// Instruction builder to construct the vectorized tree. - IRBuilder<> Builder; + IRBuilder<TargetFolder> Builder; /// A map of scalar integer values to the smallest bit width with which they /// can legally be represented. The values map to (width, signed) pairs, @@ -3629,6 +3649,18 @@ private: /// value must be signed-extended, rather than zero-extended, back to its /// original width. DenseMap<const TreeEntry *, std::pair<uint64_t, bool>> MinBWs; + + /// Final size of the reduced vector, if the current graph represents the + /// input for the reduction and it was possible to narrow the size of the + /// reduction. + unsigned ReductionBitWidth = 0; + + /// If the tree contains any zext/sext/trunc nodes, contains max-min pair of + /// type sizes, used in the tree. + std::optional<std::pair<unsigned, unsigned>> CastMaxMinBWSizes; + + /// Indices of the vectorized trunc nodes. + DenseSet<unsigned> TruncNodes; }; } // end namespace slpvectorizer @@ -4295,9 +4327,12 @@ BoUpSLP::LoadsState BoUpSLP::canVectorizeLoads( llvm_unreachable( "Expected only consecutive, strided or masked gather loads."); } + SmallVector<int> ShuffleMask(VL.size()); + for (int Idx : seq<int>(0, VL.size())) + ShuffleMask[Idx] = Idx / VF == I ? VL.size() + Idx % VF : Idx; VecLdCost += TTI.getShuffleCost(TTI ::SK_InsertSubvector, VecTy, - std::nullopt, CostKind, I * VF, SubVecTy); + ShuffleMask, CostKind, I * VF, SubVecTy); } // If masked gather cost is higher - better to vectorize, so // consider it as a gather node. It will be better estimated @@ -4313,9 +4348,10 @@ BoUpSLP::LoadsState BoUpSLP::canVectorizeLoads( // increases the cost. Loop *L = LI->getLoopFor(cast<LoadInst>(VL0)->getParent()); bool ProfitableGatherPointers = - L && Sz > 2 && count_if(PointerOps, [L](Value *V) { - return L->isLoopInvariant(V); - }) <= Sz / 2; + L && Sz > 2 && + static_cast<unsigned>(count_if(PointerOps, [L](Value *V) { + return L->isLoopInvariant(V); + })) <= Sz / 2; if (ProfitableGatherPointers || all_of(PointerOps, [IsSorted](Value *P) { auto *GEP = dyn_cast<GetElementPtrInst>(P); return (IsSorted && !GEP && doesNotNeedToBeScheduled(P)) || @@ -4658,12 +4694,8 @@ BoUpSLP::getReorderingData(const TreeEntry &TE, bool TopToBottom) { // TODO: add analysis of other gather nodes with extractelement // instructions and other values/instructions, not only undefs. if ((TE.getOpcode() == Instruction::ExtractElement || - (all_of(TE.Scalars, - [](Value *V) { - return isa<UndefValue, ExtractElementInst>(V); - }) && - any_of(TE.Scalars, - [](Value *V) { return isa<ExtractElementInst>(V); }))) && + (all_of(TE.Scalars, IsaPred<UndefValue, ExtractElementInst>) && + any_of(TE.Scalars, IsaPred<ExtractElementInst>))) && all_of(TE.Scalars, [](Value *V) { auto *EE = dyn_cast<ExtractElementInst>(V); return !EE || isa<FixedVectorType>(EE->getVectorOperandType()); @@ -4684,7 +4716,7 @@ BoUpSLP::getReorderingData(const TreeEntry &TE, bool TopToBottom) { // might be transformed. int Sz = TE.Scalars.size(); if (isSplat(TE.Scalars) && !allConstant(TE.Scalars) && - count_if(TE.Scalars, UndefValue::classof) == Sz - 1) { + count_if(TE.Scalars, IsaPred<UndefValue>) == Sz - 1) { const auto *It = find_if(TE.Scalars, [](Value *V) { return !isConstant(V); }); if (It == TE.Scalars.begin()) @@ -6308,11 +6340,10 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth, UserTreeIdx.UserTE->State == TreeEntry::ScatterVectorize && !(S.getOpcode() && allSameBlock(VL))) { assert(S.OpValue->getType()->isPointerTy() && - count_if(VL, [](Value *V) { return isa<GetElementPtrInst>(V); }) >= - 2 && + count_if(VL, IsaPred<GetElementPtrInst>) >= 2 && "Expected pointers only."); // Reset S to make it GetElementPtr kind of node. - const auto *It = find_if(VL, [](Value *V) { return isa<GetElementPtrInst>(V); }); + const auto *It = find_if(VL, IsaPred<GetElementPtrInst>); assert(It != VL.end() && "Expected at least one GEP."); S = getSameOpcode(*It, *TLI); } @@ -6539,6 +6570,26 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth, case Instruction::Trunc: case Instruction::FPTrunc: case Instruction::BitCast: { + auto [PrevMaxBW, PrevMinBW] = CastMaxMinBWSizes.value_or( + std::make_pair(std::numeric_limits<unsigned>::min(), + std::numeric_limits<unsigned>::max())); + if (ShuffleOrOp == Instruction::ZExt || + ShuffleOrOp == Instruction::SExt) { + CastMaxMinBWSizes = std::make_pair( + std::max<unsigned>(DL->getTypeSizeInBits(VL0->getType()), + PrevMaxBW), + std::min<unsigned>( + DL->getTypeSizeInBits(VL0->getOperand(0)->getType()), + PrevMinBW)); + } else if (ShuffleOrOp == Instruction::Trunc) { + CastMaxMinBWSizes = std::make_pair( + std::max<unsigned>( + DL->getTypeSizeInBits(VL0->getOperand(0)->getType()), + PrevMaxBW), + std::min<unsigned>(DL->getTypeSizeInBits(VL0->getType()), + PrevMinBW)); + TruncNodes.insert(VectorizableTree.size()); + } TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx, ReuseShuffleIndicies); LLVM_DEBUG(dbgs() << "SLP: added a vector of casts.\n"); @@ -6568,7 +6619,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth, // so that each side is more likely to have the same opcode. assert(P0 == CmpInst::getSwappedPredicate(P0) && "Commutative Predicate mismatch"); - reorderInputsAccordingToOpcode(VL, Left, Right, *TLI, *DL, *SE, *this); + reorderInputsAccordingToOpcode(VL, Left, Right, *this); } else { // Collect operands - commute if it uses the swapped predicate. for (Value *V : VL) { @@ -6615,7 +6666,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth, // have the same opcode. if (isa<BinaryOperator>(VL0) && VL0->isCommutative()) { ValueList Left, Right; - reorderInputsAccordingToOpcode(VL, Left, Right, *TLI, *DL, *SE, *this); + reorderInputsAccordingToOpcode(VL, Left, Right, *this); TE->setOperand(0, Left); TE->setOperand(1, Right); buildTree_rec(Left, Depth + 1, {TE, 0}); @@ -6752,8 +6803,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth, if (!CI || all_of(VL, [](Value *V) { return cast<CmpInst>(V)->isCommutative(); })) { - reorderInputsAccordingToOpcode(VL, Left, Right, *TLI, *DL, *SE, - *this); + reorderInputsAccordingToOpcode(VL, Left, Right, *this); } else { auto *MainCI = cast<CmpInst>(S.MainOp); auto *AltCI = cast<CmpInst>(S.AltOp); @@ -6837,17 +6887,12 @@ unsigned BoUpSLP::canMapToVector(Type *T) const { bool BoUpSLP::canReuseExtract(ArrayRef<Value *> VL, Value *OpValue, SmallVectorImpl<unsigned> &CurrentOrder, bool ResizeAllowed) const { - const auto *It = find_if(VL, [](Value *V) { - return isa<ExtractElementInst, ExtractValueInst>(V); - }); + const auto *It = find_if(VL, IsaPred<ExtractElementInst, ExtractValueInst>); assert(It != VL.end() && "Expected at least one extract instruction."); auto *E0 = cast<Instruction>(*It); - assert(all_of(VL, - [](Value *V) { - return isa<UndefValue, ExtractElementInst, ExtractValueInst>( - V); - }) && - "Invalid opcode"); + assert( + all_of(VL, IsaPred<UndefValue, ExtractElementInst, ExtractValueInst>) && + "Invalid opcode"); // Check if all of the extracts come from the same vector and from the // correct offset. Value *Vec = E0->getOperand(0); @@ -7400,7 +7445,7 @@ getShuffleCost(const TargetTransformInfo &TTI, TTI::ShuffleKind Kind, Index + NumSrcElts <= static_cast<int>(Mask.size())) return TTI.getShuffleCost( TTI::SK_InsertSubvector, - FixedVectorType::get(Tp->getElementType(), Mask.size()), std::nullopt, + FixedVectorType::get(Tp->getElementType(), Mask.size()), Mask, TTI::TCK_RecipThroughput, Index, Tp); } return TTI.getShuffleCost(Kind, Tp, Mask, CostKind, Index, SubTp, Args); @@ -7519,7 +7564,7 @@ class BoUpSLP::ShuffleCostEstimator : public BaseShuffleAnalysis { } InstructionCost getBuildVectorCost(ArrayRef<Value *> VL, Value *Root) { - if ((!Root && allConstant(VL)) || all_of(VL, UndefValue::classof)) + if ((!Root && allConstant(VL)) || all_of(VL, IsaPred<UndefValue>)) return TTI::TCC_Free; auto *VecTy = FixedVectorType::get(VL.front()->getType(), VL.size()); InstructionCost GatherCost = 0; @@ -7673,9 +7718,13 @@ class BoUpSLP::ShuffleCostEstimator : public BaseShuffleAnalysis { } if (NeedInsertSubvectorAnalysis) { // Add the cost for the subvectors insert. - for (int I = VF, E = VL.size(); I < E; I += VF) + SmallVector<int> ShuffleMask(VL.size()); + for (unsigned I = VF, E = VL.size(); I < E; I += VF) { + for (unsigned Idx : seq<unsigned>(0, E)) + ShuffleMask[Idx] = Idx / VF == I ? E + Idx % VF : Idx; GatherCost += TTI.getShuffleCost(TTI::SK_InsertSubvector, VecTy, - std::nullopt, CostKind, I, LoadTy); + ShuffleMask, CostKind, I, LoadTy); + } } GatherCost -= ScalarsCost; } @@ -7683,26 +7732,31 @@ class BoUpSLP::ShuffleCostEstimator : public BaseShuffleAnalysis { } else if (!Root && isSplat(VL)) { // Found the broadcasting of the single scalar, calculate the cost as // the broadcast. - const auto *It = - find_if(VL, [](Value *V) { return !isa<UndefValue>(V); }); + const auto *It = find_if_not(VL, IsaPred<UndefValue>); assert(It != VL.end() && "Expected at least one non-undef value."); // Add broadcast for non-identity shuffle only. bool NeedShuffle = count(VL, *It) > 1 && - (VL.front() != *It || !all_of(VL.drop_front(), UndefValue::classof)); + (VL.front() != *It || !all_of(VL.drop_front(), IsaPred<UndefValue>)); + if (!NeedShuffle) + return TTI.getVectorInstrCost(Instruction::InsertElement, VecTy, + CostKind, std::distance(VL.begin(), It), + PoisonValue::get(VecTy), *It); + + SmallVector<int> ShuffleMask(VL.size(), PoisonMaskElem); + transform(VL, ShuffleMask.begin(), [](Value *V) { + return isa<PoisonValue>(V) ? PoisonMaskElem : 0; + }); InstructionCost InsertCost = TTI.getVectorInstrCost( - Instruction::InsertElement, VecTy, CostKind, - NeedShuffle ? 0 : std::distance(VL.begin(), It), + Instruction::InsertElement, VecTy, CostKind, 0, PoisonValue::get(VecTy), *It); return InsertCost + - (NeedShuffle ? TTI.getShuffleCost( - TargetTransformInfo::SK_Broadcast, VecTy, - /*Mask=*/std::nullopt, CostKind, /*Index=*/0, - /*SubTp=*/nullptr, /*Args=*/*It) - : TTI::TCC_Free); + TTI.getShuffleCost(TargetTransformInfo::SK_Broadcast, VecTy, + ShuffleMask, CostKind, /*Index=*/0, + /*SubTp=*/nullptr, /*Args=*/*It); } return GatherCost + - (all_of(Gathers, UndefValue::classof) + (all_of(Gathers, IsaPred<UndefValue>) ? TTI::TCC_Free : R.getGatherCost(Gathers, !Root && VL.equals(Gathers))); }; @@ -7719,7 +7773,9 @@ class BoUpSLP::ShuffleCostEstimator : public BaseShuffleAnalysis { auto *EE = dyn_cast<ExtractElementInst>(V); if (!EE) return Sz; - auto *VecTy = cast<FixedVectorType>(EE->getVectorOperandType()); + auto *VecTy = dyn_cast<FixedVectorType>(EE->getVectorOperandType()); + if (!VecTy) + return Sz; return std::max(Sz, VecTy->getNumElements()); }); unsigned NumSrcRegs = TTI.getNumberOfParts( @@ -8112,9 +8168,8 @@ public: // Take credit for instruction that will become dead. if (EE->hasOneUse() || !PrevNodeFound) { Instruction *Ext = EE->user_back(); - if (isa<SExtInst, ZExtInst>(Ext) && all_of(Ext->users(), [](User *U) { - return isa<GetElementPtrInst>(U); - })) { + if (isa<SExtInst, ZExtInst>(Ext) && + all_of(Ext->users(), IsaPred<GetElementPtrInst>)) { // Use getExtractWithExtendCost() to calculate the cost of // extractelement/ext pair. Cost -= @@ -8362,6 +8417,22 @@ const BoUpSLP::TreeEntry *BoUpSLP::getOperandEntry(const TreeEntry *E, return It->get(); } +TTI::CastContextHint BoUpSLP::getCastContextHint(const TreeEntry &TE) const { + if (TE.State == TreeEntry::ScatterVectorize || + TE.State == TreeEntry::StridedVectorize) + return TTI::CastContextHint::GatherScatter; + if (TE.State == TreeEntry::Vectorize && TE.getOpcode() == Instruction::Load && + !TE.isAltShuffle()) { + if (TE.ReorderIndices.empty()) + return TTI::CastContextHint::Normal; + SmallVector<int> Mask; + inversePermutation(TE.ReorderIndices, Mask); + if (ShuffleVectorInst::isReverseMask(Mask, Mask.size())) + return TTI::CastContextHint::Reversed; + } + return TTI::CastContextHint::None; +} + InstructionCost BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals, SmallPtrSetImpl<Value *> &CheckedExtracts) { @@ -8384,6 +8455,7 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals, // If we have computed a smaller type for the expression, update VecTy so // that the costs will be accurate. auto It = MinBWs.find(E); + Type *OrigScalarTy = ScalarTy; if (It != MinBWs.end()) { ScalarTy = IntegerType::get(F->getContext(), It->second.first); VecTy = FixedVectorType::get(ScalarTy, VL.size()); @@ -8441,24 +8513,11 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals, UsedScalars.set(I); } auto GetCastContextHint = [&](Value *V) { - if (const TreeEntry *OpTE = getTreeEntry(V)) { - if (OpTE->State == TreeEntry::ScatterVectorize || - OpTE->State == TreeEntry::StridedVectorize) - return TTI::CastContextHint::GatherScatter; - if (OpTE->State == TreeEntry::Vectorize && - OpTE->getOpcode() == Instruction::Load && !OpTE->isAltShuffle()) { - if (OpTE->ReorderIndices.empty()) - return TTI::CastContextHint::Normal; - SmallVector<int> Mask; - inversePermutation(OpTE->ReorderIndices, Mask); - if (ShuffleVectorInst::isReverseMask(Mask, Mask.size())) - return TTI::CastContextHint::Reversed; - } - } else { - InstructionsState SrcState = getSameOpcode(E->getOperand(0), *TLI); - if (SrcState.getOpcode() == Instruction::Load && !SrcState.isAltShuffle()) - return TTI::CastContextHint::GatherScatter; - } + if (const TreeEntry *OpTE = getTreeEntry(V)) + return getCastContextHint(*OpTE); + InstructionsState SrcState = getSameOpcode(E->getOperand(0), *TLI); + if (SrcState.getOpcode() == Instruction::Load && !SrcState.isAltShuffle()) + return TTI::CastContextHint::GatherScatter; return TTI::CastContextHint::None; }; auto GetCostDiff = @@ -8507,8 +8566,6 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals, TTI::CastContextHint CCH = GetCastContextHint(VL0); VecCost += TTI->getCastInstrCost(VecOpcode, UserVecTy, VecTy, CCH, CostKind); - ScalarCost += Sz * TTI->getCastInstrCost(VecOpcode, UserScalarTy, - ScalarTy, CCH, CostKind); } } } @@ -8525,7 +8582,7 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals, InstructionCost ScalarCost = 0; InstructionCost VecCost = 0; std::tie(ScalarCost, VecCost) = getGEPCosts( - *TTI, Ptrs, BasePtr, E->getOpcode(), CostKind, ScalarTy, VecTy); + *TTI, Ptrs, BasePtr, E->getOpcode(), CostKind, OrigScalarTy, VecTy); LLVM_DEBUG(dumpTreeCosts(E, 0, VecCost, ScalarCost, "Calculated GEPs cost for Tree")); @@ -8572,13 +8629,12 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals, NumElts = ATy->getNumElements(); else NumElts = AggregateTy->getStructNumElements(); - SrcVecTy = FixedVectorType::get(ScalarTy, NumElts); + SrcVecTy = FixedVectorType::get(OrigScalarTy, NumElts); } if (I->hasOneUse()) { Instruction *Ext = I->user_back(); if ((isa<SExtInst>(Ext) || isa<ZExtInst>(Ext)) && - all_of(Ext->users(), - [](User *U) { return isa<GetElementPtrInst>(U); })) { + all_of(Ext->users(), IsaPred<GetElementPtrInst>)) { // Use getExtractWithExtendCost() to calculate the cost of // extractelement/ext pair. InstructionCost Cost = TTI->getExtractWithExtendCost( @@ -8737,16 +8793,14 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals, } else if (It != MinBWs.end()) { assert(BWSz > SrcBWSz && "Invalid cast!"); VecOpcode = It->second.second ? Instruction::SExt : Instruction::ZExt; + } else if (SrcIt != MinBWs.end()) { + assert(BWSz > SrcBWSz && "Invalid cast!"); + VecOpcode = + SrcIt->second.second ? Instruction::SExt : Instruction::ZExt; } } auto GetScalarCost = [&](unsigned Idx) -> InstructionCost { - // Do not count cost here if minimum bitwidth is in effect and it is just - // a bitcast (here it is just a noop). - if (VecOpcode != Opcode && VecOpcode == Instruction::BitCast) - return TTI::TCC_Free; - auto *VI = VL0->getOpcode() == Opcode - ? cast<Instruction>(UniqueValues[Idx]) - : nullptr; + auto *VI = cast<Instruction>(UniqueValues[Idx]); return TTI->getCastInstrCost(Opcode, VL0->getType(), VL0->getOperand(0)->getType(), TTI::getCastContextHint(VI), CostKind, VI); @@ -8789,7 +8843,7 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals, ? CmpInst::BAD_FCMP_PREDICATE : CmpInst::BAD_ICMP_PREDICATE; - return TTI->getCmpSelInstrCost(E->getOpcode(), ScalarTy, + return TTI->getCmpSelInstrCost(E->getOpcode(), OrigScalarTy, Builder.getInt1Ty(), CurrentPred, CostKind, VI); }; @@ -8844,7 +8898,7 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals, TTI::OperandValueInfo Op2Info = TTI::getOperandInfo(VI->getOperand(OpIdx)); SmallVector<const Value *> Operands(VI->operand_values()); - return TTI->getArithmeticInstrCost(ShuffleOrOp, ScalarTy, CostKind, + return TTI->getArithmeticInstrCost(ShuffleOrOp, OrigScalarTy, CostKind, Op1Info, Op2Info, Operands, VI); }; auto GetVectorCost = [=](InstructionCost CommonCost) { @@ -8852,7 +8906,7 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals, TTI::OperandValueInfo Op1Info = getOperandInfo(E->getOperand(0)); TTI::OperandValueInfo Op2Info = getOperandInfo(E->getOperand(OpIdx)); return TTI->getArithmeticInstrCost(ShuffleOrOp, VecTy, CostKind, Op1Info, - Op2Info) + + Op2Info, std::nullopt, nullptr, TLI) + CommonCost; }; return GetCostDiff(GetScalarCost, GetVectorCost); @@ -8863,9 +8917,9 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals, case Instruction::Load: { auto GetScalarCost = [&](unsigned Idx) { auto *VI = cast<LoadInst>(UniqueValues[Idx]); - return TTI->getMemoryOpCost(Instruction::Load, ScalarTy, VI->getAlign(), - VI->getPointerAddressSpace(), CostKind, - TTI::OperandValueInfo(), VI); + return TTI->getMemoryOpCost(Instruction::Load, OrigScalarTy, + VI->getAlign(), VI->getPointerAddressSpace(), + CostKind, TTI::OperandValueInfo(), VI); }; auto *LI0 = cast<LoadInst>(VL0); auto GetVectorCost = [&](InstructionCost CommonCost) { @@ -8908,9 +8962,9 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals, auto GetScalarCost = [=](unsigned Idx) { auto *VI = cast<StoreInst>(VL[Idx]); TTI::OperandValueInfo OpInfo = TTI::getOperandInfo(VI->getValueOperand()); - return TTI->getMemoryOpCost(Instruction::Store, ScalarTy, VI->getAlign(), - VI->getPointerAddressSpace(), CostKind, - OpInfo, VI); + return TTI->getMemoryOpCost(Instruction::Store, OrigScalarTy, + VI->getAlign(), VI->getPointerAddressSpace(), + CostKind, OpInfo, VI); }; auto *BaseSI = cast<StoreInst>(IsReorder ? VL[E->ReorderIndices.front()] : VL0); @@ -9013,6 +9067,17 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals, Type *Src1SclTy = E->getAltOp()->getOperand(0)->getType(); auto *Src0Ty = FixedVectorType::get(Src0SclTy, VL.size()); auto *Src1Ty = FixedVectorType::get(Src1SclTy, VL.size()); + if (It != MinBWs.end()) { + if (!MinBWs.contains(getOperandEntry(E, 0))) + VecCost = + TTIRef.getCastInstrCost(Instruction::Trunc, VecTy, Src0Ty, + TTI::CastContextHint::None, CostKind); + LLVM_DEBUG({ + dbgs() << "SLP: alternate extension, which should be truncated.\n"; + E->dump(); + }); + return VecCost; + } VecCost = TTIRef.getCastInstrCost(E->getOpcode(), VecTy, Src0Ty, TTI::CastContextHint::None, CostKind); VecCost += @@ -9068,10 +9133,7 @@ bool BoUpSLP::isFullyVectorizableTinyTree(bool ForReduction) const { (allConstant(TE->Scalars) || isSplat(TE->Scalars) || TE->Scalars.size() < Limit || ((TE->getOpcode() == Instruction::ExtractElement || - all_of(TE->Scalars, - [](Value *V) { - return isa<ExtractElementInst, UndefValue>(V); - })) && + all_of(TE->Scalars, IsaPred<ExtractElementInst, UndefValue>)) && isFixedVectorShuffle(TE->Scalars, Mask)) || (TE->State == TreeEntry::NeedToGather && TE->getOpcode() == Instruction::Load && !TE->isAltShuffle())); @@ -9192,9 +9254,7 @@ bool BoUpSLP::isTreeTinyAndNotFullyVectorizable(bool ForReduction) const { all_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) { return (TE->State == TreeEntry::NeedToGather && TE->getOpcode() != Instruction::ExtractElement && - count_if(TE->Scalars, - [](Value *V) { return isa<ExtractElementInst>(V); }) <= - Limit) || + count_if(TE->Scalars, IsaPred<ExtractElementInst>) <= Limit) || TE->getOpcode() == Instruction::PHI; })) return true; @@ -9211,14 +9271,19 @@ bool BoUpSLP::isTreeTinyAndNotFullyVectorizable(bool ForReduction) const { // Check if any of the gather node forms an insertelement buildvector // somewhere. - if (any_of(VectorizableTree, [](const std::unique_ptr<TreeEntry> &TE) { + bool IsAllowedSingleBVNode = + VectorizableTree.size() > 1 || + (VectorizableTree.size() == 1 && VectorizableTree.front()->getOpcode() && + VectorizableTree.front()->getOpcode() != Instruction::PHI && + VectorizableTree.front()->getOpcode() != Instruction::GetElementPtr && + allSameBlock(VectorizableTree.front()->Scalars)); + if (any_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) { return TE->State == TreeEntry::NeedToGather && - all_of(TE->Scalars, [](Value *V) { + all_of(TE->Scalars, [&](Value *V) { return isa<ExtractElementInst, UndefValue>(V) || - (!V->hasNUsesOrMore(UsesLimit) && - any_of(V->users(), [](User *U) { - return isa<InsertElementInst>(U); - })); + (IsAllowedSingleBVNode && + !V->hasNUsesOrMore(UsesLimit) && + any_of(V->users(), IsaPred<InsertElementInst>)); }); })) return false; @@ -9772,6 +9837,44 @@ InstructionCost BoUpSLP::getTreeCost(ArrayRef<Value *> VectorizedVals) { Cost -= InsertCost; } + // Add the cost for reduced value resize (if required). + if (ReductionBitWidth != 0) { + assert(UserIgnoreList && "Expected reduction tree."); + const TreeEntry &E = *VectorizableTree.front().get(); + auto It = MinBWs.find(&E); + if (It != MinBWs.end() && It->second.first != ReductionBitWidth) { + unsigned SrcSize = It->second.first; + unsigned DstSize = ReductionBitWidth; + unsigned Opcode = Instruction::Trunc; + if (SrcSize < DstSize) + Opcode = It->second.second ? Instruction::SExt : Instruction::ZExt; + auto *SrcVecTy = + FixedVectorType::get(Builder.getIntNTy(SrcSize), E.getVectorFactor()); + auto *DstVecTy = + FixedVectorType::get(Builder.getIntNTy(DstSize), E.getVectorFactor()); + TTI::CastContextHint CCH = getCastContextHint(E); + InstructionCost CastCost; + switch (E.getOpcode()) { + case Instruction::SExt: + case Instruction::ZExt: + case Instruction::Trunc: { + const TreeEntry *OpTE = getOperandEntry(&E, 0); + CCH = getCastContextHint(*OpTE); + break; + } + default: + break; + } + CastCost += TTI->getCastInstrCost(Opcode, DstVecTy, SrcVecTy, CCH, + TTI::TCK_RecipThroughput); + Cost += CastCost; + LLVM_DEBUG(dbgs() << "SLP: Adding cost " << CastCost + << " for final resize for reduction from " << SrcVecTy + << " to " << DstVecTy << "\n"; + dbgs() << "SLP: Current total cost = " << Cost << "\n"); + } + } + #ifndef NDEBUG SmallString<256> Str; { @@ -10053,11 +10156,6 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry( Instruction &LastBundleInst = getLastInstructionInBundle(VTE); if (&LastBundleInst == TEInsertPt || !CheckOrdering(&LastBundleInst)) continue; - auto It = MinBWs.find(VTE); - // If vectorize node is demoted - do not match. - if (It != MinBWs.end() && - It->second.first != DL->getTypeSizeInBits(V->getType())) - continue; VToTEs.insert(VTE); } if (VToTEs.empty()) @@ -10182,7 +10280,7 @@ BoUpSLP::isGatherShuffledSingleRegisterEntry( } } - bool IsSplatOrUndefs = isSplat(VL) || all_of(VL, UndefValue::classof); + bool IsSplatOrUndefs = isSplat(VL) || all_of(VL, IsaPred<UndefValue>); // Checks if the 2 PHIs are compatible in terms of high possibility to be // vectorized. auto AreCompatiblePHIs = [&](Value *V, Value *V1) { @@ -10374,7 +10472,7 @@ InstructionCost BoUpSLP::getGatherCost(ArrayRef<Value *> VL, // Check if the same elements are inserted several times and count them as // shuffle candidates. APInt ShuffledElements = APInt::getZero(VL.size()); - DenseSet<Value *> UniqueElements; + DenseMap<Value *, unsigned> UniqueElements; constexpr TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput; InstructionCost Cost; auto EstimateInsertCost = [&](unsigned I, Value *V) { @@ -10383,39 +10481,46 @@ InstructionCost BoUpSLP::getGatherCost(ArrayRef<Value *> VL, TTI->getVectorInstrCost(Instruction::InsertElement, VecTy, CostKind, I, Constant::getNullValue(VecTy), V); }; + SmallVector<int> ShuffleMask(VL.size(), PoisonMaskElem); for (unsigned I = 0, E = VL.size(); I < E; ++I) { Value *V = VL[I]; // No need to shuffle duplicates for constants. if ((ForPoisonSrc && isConstant(V)) || isa<UndefValue>(V)) { ShuffledElements.setBit(I); + ShuffleMask[I] = isa<PoisonValue>(V) ? PoisonMaskElem : I; continue; } - if (!UniqueElements.insert(V).second) { - DuplicateNonConst = true; - ShuffledElements.setBit(I); + + auto Res = UniqueElements.try_emplace(V, I); + if (Res.second) { + EstimateInsertCost(I, V); + ShuffleMask[I] = I; continue; } - EstimateInsertCost(I, V); + + DuplicateNonConst = true; + ShuffledElements.setBit(I); + ShuffleMask[I] = Res.first->second; } if (ForPoisonSrc) Cost = TTI->getScalarizationOverhead(VecTy, ~ShuffledElements, /*Insert*/ true, /*Extract*/ false, CostKind); if (DuplicateNonConst) - Cost += - TTI->getShuffleCost(TargetTransformInfo::SK_PermuteSingleSrc, VecTy); + Cost += TTI->getShuffleCost(TargetTransformInfo::SK_PermuteSingleSrc, + VecTy, ShuffleMask); return Cost; } // Perform operand reordering on the instructions in VL and return the reordered // operands in Left and Right. -void BoUpSLP::reorderInputsAccordingToOpcode( - ArrayRef<Value *> VL, SmallVectorImpl<Value *> &Left, - SmallVectorImpl<Value *> &Right, const TargetLibraryInfo &TLI, - const DataLayout &DL, ScalarEvolution &SE, const BoUpSLP &R) { +void BoUpSLP::reorderInputsAccordingToOpcode(ArrayRef<Value *> VL, + SmallVectorImpl<Value *> &Left, + SmallVectorImpl<Value *> &Right, + const BoUpSLP &R) { if (VL.empty()) return; - VLOperands Ops(VL, TLI, DL, SE, R); + VLOperands Ops(VL, R); // Reorder the operands in place. Ops.reorder(); Left = Ops.getVL(0); @@ -10614,8 +10719,20 @@ Value *BoUpSLP::gather(ArrayRef<Value *> VL, Value *Root) { PostponedInsts.emplace_back(Inst, I); } - auto &&CreateInsertElement = [this](Value *Vec, Value *V, unsigned Pos) { - Vec = Builder.CreateInsertElement(Vec, V, Builder.getInt32(Pos)); + auto &&CreateInsertElement = [this](Value *Vec, Value *V, unsigned Pos, + Type *Ty) { + Value *Scalar = V; + if (cast<VectorType>(Vec->getType())->getElementType() != Ty) { + assert(V->getType()->isIntegerTy() && Ty->isIntegerTy() && + "Expected integer types only."); + Vec = Builder.CreateIntCast( + Vec, + VectorType::get(Ty, + cast<VectorType>(Vec->getType())->getElementCount()), + !isKnownNonNegative(Vec, SimplifyQuery(*DL))); + } + + Vec = Builder.CreateInsertElement(Vec, Scalar, Builder.getInt32(Pos)); auto *InsElt = dyn_cast<InsertElementInst>(Vec); if (!InsElt) return Vec; @@ -10625,15 +10742,25 @@ Value *BoUpSLP::gather(ArrayRef<Value *> VL, Value *Root) { if (isa<Instruction>(V)) { if (TreeEntry *Entry = getTreeEntry(V)) { // Find which lane we need to extract. - unsigned FoundLane = Entry->findLaneForValue(V); - ExternalUses.emplace_back(V, InsElt, FoundLane); + User *UserOp = nullptr; + if (Scalar != V) { + if (auto *SI = dyn_cast<Instruction>(Scalar)) + UserOp = SI; + } else { + UserOp = InsElt; + } + if (UserOp) { + unsigned FoundLane = Entry->findLaneForValue(V); + ExternalUses.emplace_back(V, UserOp, FoundLane); + } } } return Vec; }; Value *Val0 = isa<StoreInst>(VL[0]) ? cast<StoreInst>(VL[0])->getValueOperand() : VL[0]; - FixedVectorType *VecTy = FixedVectorType::get(Val0->getType(), VL.size()); + Type *ScalarTy = Val0->getType(); + FixedVectorType *VecTy = FixedVectorType::get(ScalarTy, VL.size()); Value *Vec = Root ? Root : PoisonValue::get(VecTy); SmallVector<int> NonConsts; // Insert constant values at first. @@ -10656,15 +10783,15 @@ Value *BoUpSLP::gather(ArrayRef<Value *> VL, Value *Root) { continue; } } - Vec = CreateInsertElement(Vec, VL[I], I); + Vec = CreateInsertElement(Vec, VL[I], I, ScalarTy); } // Insert non-constant values. for (int I : NonConsts) - Vec = CreateInsertElement(Vec, VL[I], I); + Vec = CreateInsertElement(Vec, VL[I], I, ScalarTy); // Append instructions, which are/may be part of the loop, in the end to make // it possible to hoist non-loop-based instructions. for (const std::pair<Value *, unsigned> &Pair : PostponedInsts) - Vec = CreateInsertElement(Vec, Pair.first, Pair.second); + Vec = CreateInsertElement(Vec, Pair.first, Pair.second, ScalarTy); return Vec; } @@ -10721,16 +10848,35 @@ class BoUpSLP::ShuffleInstructionBuilder final : public BaseShuffleAnalysis { SetVector<Instruction *> &GatherShuffleExtractSeq; /// A list of blocks that we are going to CSE. DenseSet<BasicBlock *> &CSEBlocks; + /// Data layout. + const DataLayout &DL; public: ShuffleIRBuilder(IRBuilderBase &Builder, SetVector<Instruction *> &GatherShuffleExtractSeq, - DenseSet<BasicBlock *> &CSEBlocks) + DenseSet<BasicBlock *> &CSEBlocks, const DataLayout &DL) : Builder(Builder), GatherShuffleExtractSeq(GatherShuffleExtractSeq), - CSEBlocks(CSEBlocks) {} + CSEBlocks(CSEBlocks), DL(DL) {} ~ShuffleIRBuilder() = default; /// Creates shufflevector for the 2 operands with the given mask. Value *createShuffleVector(Value *V1, Value *V2, ArrayRef<int> Mask) { + if (V1->getType() != V2->getType()) { + assert(V1->getType()->isIntOrIntVectorTy() && + V1->getType()->isIntOrIntVectorTy() && + "Expected integer vector types only."); + if (V1->getType() != V2->getType()) { + if (cast<VectorType>(V2->getType()) + ->getElementType() + ->getIntegerBitWidth() < cast<VectorType>(V1->getType()) + ->getElementType() + ->getIntegerBitWidth()) + V2 = Builder.CreateIntCast( + V2, V1->getType(), !isKnownNonNegative(V2, SimplifyQuery(DL))); + else + V1 = Builder.CreateIntCast( + V1, V2->getType(), !isKnownNonNegative(V1, SimplifyQuery(DL))); + } + } Value *Vec = Builder.CreateShuffleVector(V1, V2, Mask); if (auto *I = dyn_cast<Instruction>(Vec)) { GatherShuffleExtractSeq.insert(I); @@ -10789,7 +10935,7 @@ class BoUpSLP::ShuffleInstructionBuilder final : public BaseShuffleAnalysis { Value *createShuffle(Value *V1, Value *V2, ArrayRef<int> Mask) { assert(V1 && "Expected at least one vector value."); ShuffleIRBuilder ShuffleBuilder(Builder, R.GatherShuffleExtractSeq, - R.CSEBlocks); + R.CSEBlocks, *R.DL); return BaseShuffleAnalysis::createShuffle<Value *>(V1, V2, Mask, ShuffleBuilder); } @@ -11111,8 +11257,7 @@ Value *BoUpSLP::vectorizeOperand(TreeEntry *E, unsigned NodeIdx, InstructionsState S = getSameOpcode(VL, *TLI); // Special processing for GEPs bundle, which may include non-gep values. if (!S.getOpcode() && VL.front()->getType()->isPointerTy()) { - const auto *It = - find_if(VL, [](Value *V) { return isa<GetElementPtrInst>(V); }); + const auto *It = find_if(VL, IsaPred<GetElementPtrInst>); if (It != VL.end()) S = getSameOpcode(*It, *TLI); } @@ -11282,7 +11427,7 @@ ResTy BoUpSLP::processBuildVector(const TreeEntry *E, Args &...Params) { unsigned NumParts = TTI->getNumberOfParts(VecTy); if (NumParts == 0 || NumParts >= GatheredScalars.size()) NumParts = 1; - if (!all_of(GatheredScalars, UndefValue::classof)) { + if (!all_of(GatheredScalars, IsaPred<UndefValue>)) { // Check for gathered extracts. bool Resized = false; ExtractShuffles = @@ -11607,7 +11752,7 @@ ResTy BoUpSLP::processBuildVector(const TreeEntry *E, Args &...Params) { GatheredScalars[I] = PoisonValue::get(ScalarTy); } // Generate constants for final shuffle and build a mask for them. - if (!all_of(GatheredScalars, PoisonValue::classof)) { + if (!all_of(GatheredScalars, IsaPred<PoisonValue>)) { SmallVector<int> BVMask(GatheredScalars.size(), PoisonMaskElem); TryPackScalars(GatheredScalars, BVMask, /*IsRootPoison=*/true); Value *BV = ShuffleBuilder.gather(GatheredScalars, BVMask.size()); @@ -11656,7 +11801,7 @@ Value *BoUpSLP::createBuildVector(const TreeEntry *E) { } Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { - IRBuilder<>::InsertPointGuard Guard(Builder); + IRBuilderBase::InsertPointGuard Guard(Builder); if (E->VectorizedValue && (E->State != TreeEntry::Vectorize || E->getOpcode() != Instruction::PHI || @@ -11675,10 +11820,7 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { } bool IsReverseOrder = isReverseOrder(E->ReorderIndices); - auto FinalShuffle = [&](Value *V, const TreeEntry *E, VectorType *VecTy, - bool IsSigned) { - if (V->getType() != VecTy) - V = Builder.CreateIntCast(V, VecTy, IsSigned); + auto FinalShuffle = [&](Value *V, const TreeEntry *E, VectorType *VecTy) { ShuffleInstructionBuilder ShuffleBuilder(Builder, *this); if (E->getOpcode() == Instruction::Store) { ArrayRef<int> Mask = @@ -11705,12 +11847,21 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { ScalarTy = Store->getValueOperand()->getType(); else if (auto *IE = dyn_cast<InsertElementInst>(VL0)) ScalarTy = IE->getOperand(1)->getType(); - bool IsSigned = false; auto It = MinBWs.find(E); - if (It != MinBWs.end()) { + if (It != MinBWs.end()) ScalarTy = IntegerType::get(F->getContext(), It->second.first); - IsSigned = It->second.second; - } + auto GetOperandSignedness = [&](unsigned Idx) { + const TreeEntry *OpE = getOperandEntry(E, Idx); + bool IsSigned = false; + auto It = MinBWs.find(OpE); + if (It != MinBWs.end()) + IsSigned = It->second.second; + else + IsSigned = any_of(OpE->Scalars, [&](Value *R) { + return !isKnownNonNegative(R, SimplifyQuery(*DL)); + }); + return IsSigned; + }; auto *VecTy = FixedVectorType::get(ScalarTy, E->Scalars.size()); switch (ShuffleOrOp) { case Instruction::PHI: { @@ -11734,7 +11885,7 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { PH->getParent()->getFirstInsertionPt()); Builder.SetCurrentDebugLocation(PH->getDebugLoc()); - V = FinalShuffle(V, E, VecTy, IsSigned); + V = FinalShuffle(V, E, VecTy); E->VectorizedValue = V; if (PostponedPHIs) @@ -11768,9 +11919,11 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { Builder.SetCurrentDebugLocation(PH->getDebugLoc()); Value *Vec = vectorizeOperand(E, I, /*PostponedPHIs=*/true); if (VecTy != Vec->getType()) { - assert(MinBWs.contains(getOperandEntry(E, I)) && + assert((It != MinBWs.end() || + getOperandEntry(E, I)->State == TreeEntry::NeedToGather || + MinBWs.contains(getOperandEntry(E, I))) && "Expected item in MinBWs."); - Vec = Builder.CreateIntCast(Vec, VecTy, It->second.second); + Vec = Builder.CreateIntCast(Vec, VecTy, GetOperandSignedness(I)); } NewPhi->addIncoming(Vec, IBB); } @@ -11785,7 +11938,7 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { if (const TreeEntry *TE = getTreeEntry(V)) V = TE->VectorizedValue; setInsertPointAfterBundle(E); - V = FinalShuffle(V, E, VecTy, IsSigned); + V = FinalShuffle(V, E, VecTy); E->VectorizedValue = V; return V; } @@ -11795,7 +11948,7 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { Value *Ptr = LI->getPointerOperand(); LoadInst *V = Builder.CreateAlignedLoad(VecTy, Ptr, LI->getAlign()); Value *NewV = propagateMetadata(V, E->Scalars); - NewV = FinalShuffle(NewV, E, VecTy, IsSigned); + NewV = FinalShuffle(NewV, E, VecTy); E->VectorizedValue = NewV; return NewV; } @@ -11981,10 +12134,11 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { auto *CI = cast<CastInst>(VL0); Instruction::CastOps VecOpcode = CI->getOpcode(); - Type *SrcScalarTy = VL0->getOperand(0)->getType(); + Type *SrcScalarTy = cast<VectorType>(InVec->getType())->getElementType(); auto SrcIt = MinBWs.find(getOperandEntry(E, 0)); if (!ScalarTy->isFloatingPointTy() && !SrcScalarTy->isFloatingPointTy() && - (SrcIt != MinBWs.end() || It != MinBWs.end())) { + (SrcIt != MinBWs.end() || It != MinBWs.end() || + SrcScalarTy != CI->getOperand(0)->getType())) { // Check if the values are candidates to demote. unsigned SrcBWSz = DL->getTypeSizeInBits(SrcScalarTy); if (SrcIt != MinBWs.end()) @@ -11994,6 +12148,9 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { VecOpcode = Instruction::BitCast; } else if (BWSz < SrcBWSz) { VecOpcode = Instruction::Trunc; + } else if (It != MinBWs.end()) { + assert(BWSz > SrcBWSz && "Invalid cast!"); + VecOpcode = It->second.second ? Instruction::SExt : Instruction::ZExt; } else if (SrcIt != MinBWs.end()) { assert(BWSz > SrcBWSz && "Invalid cast!"); VecOpcode = @@ -12003,7 +12160,7 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { Value *V = (VecOpcode != ShuffleOrOp && VecOpcode == Instruction::BitCast) ? InVec : Builder.CreateCast(VecOpcode, InVec, VecTy); - V = FinalShuffle(V, E, VecTy, IsSigned); + V = FinalShuffle(V, E, VecTy); E->VectorizedValue = V; ++NumVectorInstructions; @@ -12024,11 +12181,22 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { return E->VectorizedValue; } if (L->getType() != R->getType()) { - assert((MinBWs.contains(getOperandEntry(E, 0)) || + assert((getOperandEntry(E, 0)->State == TreeEntry::NeedToGather || + getOperandEntry(E, 1)->State == TreeEntry::NeedToGather || + MinBWs.contains(getOperandEntry(E, 0)) || MinBWs.contains(getOperandEntry(E, 1))) && "Expected item in MinBWs."); - L = Builder.CreateIntCast(L, VecTy, IsSigned); - R = Builder.CreateIntCast(R, VecTy, IsSigned); + if (cast<VectorType>(L->getType()) + ->getElementType() + ->getIntegerBitWidth() < cast<VectorType>(R->getType()) + ->getElementType() + ->getIntegerBitWidth()) { + Type *CastTy = R->getType(); + L = Builder.CreateIntCast(L, CastTy, GetOperandSignedness(0)); + } else { + Type *CastTy = L->getType(); + R = Builder.CreateIntCast(R, CastTy, GetOperandSignedness(1)); + } } CmpInst::Predicate P0 = cast<CmpInst>(VL0)->getPredicate(); @@ -12036,7 +12204,7 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { propagateIRFlags(V, E->Scalars, VL0); // Do not cast for cmps. VecTy = cast<FixedVectorType>(V->getType()); - V = FinalShuffle(V, E, VecTy, IsSigned); + V = FinalShuffle(V, E, VecTy); E->VectorizedValue = V; ++NumVectorInstructions; @@ -12060,16 +12228,21 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { LLVM_DEBUG(dbgs() << "SLP: Diamond merged for " << *VL0 << ".\n"); return E->VectorizedValue; } - if (True->getType() != False->getType()) { - assert((MinBWs.contains(getOperandEntry(E, 1)) || + if (True->getType() != VecTy || False->getType() != VecTy) { + assert((It != MinBWs.end() || + getOperandEntry(E, 1)->State == TreeEntry::NeedToGather || + getOperandEntry(E, 2)->State == TreeEntry::NeedToGather || + MinBWs.contains(getOperandEntry(E, 1)) || MinBWs.contains(getOperandEntry(E, 2))) && "Expected item in MinBWs."); - True = Builder.CreateIntCast(True, VecTy, IsSigned); - False = Builder.CreateIntCast(False, VecTy, IsSigned); + if (True->getType() != VecTy) + True = Builder.CreateIntCast(True, VecTy, GetOperandSignedness(1)); + if (False->getType() != VecTy) + False = Builder.CreateIntCast(False, VecTy, GetOperandSignedness(2)); } Value *V = Builder.CreateSelect(Cond, True, False); - V = FinalShuffle(V, E, VecTy, IsSigned); + V = FinalShuffle(V, E, VecTy); E->VectorizedValue = V; ++NumVectorInstructions; @@ -12091,7 +12264,7 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { if (auto *I = dyn_cast<Instruction>(V)) V = propagateMetadata(I, E->Scalars); - V = FinalShuffle(V, E, VecTy, IsSigned); + V = FinalShuffle(V, E, VecTy); E->VectorizedValue = V; ++NumVectorInstructions; @@ -12128,22 +12301,27 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { LLVM_DEBUG(dbgs() << "SLP: Diamond merged for " << *VL0 << ".\n"); return E->VectorizedValue; } - if (LHS->getType() != RHS->getType()) { - assert((MinBWs.contains(getOperandEntry(E, 0)) || + if (LHS->getType() != VecTy || RHS->getType() != VecTy) { + assert((It != MinBWs.end() || + getOperandEntry(E, 0)->State == TreeEntry::NeedToGather || + getOperandEntry(E, 1)->State == TreeEntry::NeedToGather || + MinBWs.contains(getOperandEntry(E, 0)) || MinBWs.contains(getOperandEntry(E, 1))) && "Expected item in MinBWs."); - LHS = Builder.CreateIntCast(LHS, VecTy, IsSigned); - RHS = Builder.CreateIntCast(RHS, VecTy, IsSigned); + if (LHS->getType() != VecTy) + LHS = Builder.CreateIntCast(LHS, VecTy, GetOperandSignedness(0)); + if (RHS->getType() != VecTy) + RHS = Builder.CreateIntCast(RHS, VecTy, GetOperandSignedness(1)); } Value *V = Builder.CreateBinOp( static_cast<Instruction::BinaryOps>(E->getOpcode()), LHS, RHS); - propagateIRFlags(V, E->Scalars, VL0, !MinBWs.contains(E)); + propagateIRFlags(V, E->Scalars, VL0, It == MinBWs.end()); if (auto *I = dyn_cast<Instruction>(V)) V = propagateMetadata(I, E->Scalars); - V = FinalShuffle(V, E, VecTy, IsSigned); + V = FinalShuffle(V, E, VecTy); E->VectorizedValue = V; ++NumVectorInstructions; @@ -12214,7 +12392,7 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { } Value *V = propagateMetadata(NewLI, E->Scalars); - V = FinalShuffle(V, E, VecTy, IsSigned); + V = FinalShuffle(V, E, VecTy); E->VectorizedValue = V; ++NumVectorInstructions; return V; @@ -12225,7 +12403,10 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { setInsertPointAfterBundle(E); Value *VecValue = vectorizeOperand(E, 0, PostponedPHIs); - VecValue = FinalShuffle(VecValue, E, VecTy, IsSigned); + if (VecValue->getType() != VecTy) + VecValue = + Builder.CreateIntCast(VecValue, VecTy, GetOperandSignedness(0)); + VecValue = FinalShuffle(VecValue, E, VecTy); Value *Ptr = SI->getPointerOperand(); StoreInst *ST = @@ -12267,7 +12448,7 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { V = propagateMetadata(I, GEPs); } - V = FinalShuffle(V, E, VecTy, IsSigned); + V = FinalShuffle(V, E, VecTy); E->VectorizedValue = V; ++NumVectorInstructions; @@ -12291,12 +12472,12 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { if (UseIntrinsic && isVectorIntrinsicWithOverloadTypeAtArg(ID, -1)) TysForDecl.push_back( FixedVectorType::get(CI->getType(), E->Scalars.size())); + auto *CEI = cast<CallInst>(VL0); for (unsigned I : seq<unsigned>(0, CI->arg_size())) { ValueList OpVL; // Some intrinsics have scalar arguments. This argument should not be // vectorized. if (UseIntrinsic && isVectorIntrinsicWithScalarOpAtArg(ID, I)) { - CallInst *CEI = cast<CallInst>(VL0); ScalarArg = CEI->getArgOperand(I); OpVecs.push_back(CEI->getArgOperand(I)); if (isVectorIntrinsicWithOverloadTypeAtArg(ID, I)) @@ -12309,6 +12490,13 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { LLVM_DEBUG(dbgs() << "SLP: Diamond merged for " << *VL0 << ".\n"); return E->VectorizedValue; } + ScalarArg = CEI->getArgOperand(I); + if (cast<VectorType>(OpVec->getType())->getElementType() != + ScalarArg->getType()) { + auto *CastTy = FixedVectorType::get(ScalarArg->getType(), + VecTy->getNumElements()); + OpVec = Builder.CreateIntCast(OpVec, CastTy, GetOperandSignedness(I)); + } LLVM_DEBUG(dbgs() << "SLP: OpVec[" << I << "]: " << *OpVec << "\n"); OpVecs.push_back(OpVec); if (UseIntrinsic && isVectorIntrinsicWithOverloadTypeAtArg(ID, I)) @@ -12332,7 +12520,7 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { Value *V = Builder.CreateCall(CF, OpVecs, OpBundles); propagateIRFlags(V, E->Scalars, VL0); - V = FinalShuffle(V, E, VecTy, IsSigned); + V = FinalShuffle(V, E, VecTy); E->VectorizedValue = V; ++NumVectorInstructions; @@ -12364,12 +12552,31 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { LLVM_DEBUG(dbgs() << "SLP: Diamond merged for " << *VL0 << ".\n"); return E->VectorizedValue; } - if (LHS && RHS && LHS->getType() != RHS->getType()) { - assert((MinBWs.contains(getOperandEntry(E, 0)) || + if (LHS && RHS && + ((Instruction::isBinaryOp(E->getOpcode()) && + (LHS->getType() != VecTy || RHS->getType() != VecTy)) || + (isa<CmpInst>(VL0) && LHS->getType() != RHS->getType()))) { + assert((It != MinBWs.end() || + getOperandEntry(E, 0)->State == TreeEntry::NeedToGather || + getOperandEntry(E, 1)->State == TreeEntry::NeedToGather || + MinBWs.contains(getOperandEntry(E, 0)) || MinBWs.contains(getOperandEntry(E, 1))) && "Expected item in MinBWs."); - LHS = Builder.CreateIntCast(LHS, VecTy, IsSigned); - RHS = Builder.CreateIntCast(RHS, VecTy, IsSigned); + Type *CastTy = VecTy; + if (isa<CmpInst>(VL0) && LHS->getType() != RHS->getType()) { + if (cast<VectorType>(LHS->getType()) + ->getElementType() + ->getIntegerBitWidth() < cast<VectorType>(RHS->getType()) + ->getElementType() + ->getIntegerBitWidth()) + CastTy = RHS->getType(); + else + CastTy = LHS->getType(); + } + if (LHS->getType() != CastTy) + LHS = Builder.CreateIntCast(LHS, CastTy, GetOperandSignedness(0)); + if (RHS->getType() != CastTy) + RHS = Builder.CreateIntCast(RHS, CastTy, GetOperandSignedness(1)); } Value *V0, *V1; @@ -12384,6 +12591,16 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { CmpInst::Predicate AltPred = AltCI->getPredicate(); V1 = Builder.CreateCmp(AltPred, LHS, RHS); } else { + if (It != MinBWs.end()) { + if (!MinBWs.contains(getOperandEntry(E, 0))) + LHS = Builder.CreateIntCast(LHS, VecTy, It->second.first); + assert(LHS->getType() == VecTy && "Expected same type as operand."); + if (auto *I = dyn_cast<Instruction>(LHS)) + LHS = propagateMetadata(I, E->Scalars); + E->VectorizedValue = LHS; + ++NumVectorInstructions; + return LHS; + } V0 = Builder.CreateCast( static_cast<Instruction::CastOps>(E->getOpcode()), LHS, VecTy); V1 = Builder.CreateCast( @@ -12411,8 +12628,8 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { }, Mask, &OpScalars, &AltScalars); - propagateIRFlags(V0, OpScalars); - propagateIRFlags(V1, AltScalars); + propagateIRFlags(V0, OpScalars, E->getMainOp(), It == MinBWs.end()); + propagateIRFlags(V1, AltScalars, E->getAltOp(), It == MinBWs.end()); Value *V = Builder.CreateShuffleVector(V0, V1, Mask); if (auto *I = dyn_cast<Instruction>(V)) { @@ -12421,9 +12638,6 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) { CSEBlocks.insert(I->getParent()); } - if (V->getType() != VecTy && !isa<CmpInst>(VL0)) - V = Builder.CreateIntCast( - V, FixedVectorType::get(ScalarTy, E->getVectorFactor()), IsSigned); E->VectorizedValue = V; ++NumVectorInstructions; @@ -12519,6 +12733,15 @@ Value *BoUpSLP::vectorizeTree( } Builder.SetCurrentDebugLocation(UserI->getDebugLoc()); Value *Vec = vectorizeTree(TE, /*PostponedPHIs=*/false); + if (Vec->getType() != PrevVec->getType()) { + assert(Vec->getType()->isIntOrIntVectorTy() && + PrevVec->getType()->isIntOrIntVectorTy() && + "Expected integer vector types only."); + assert(MinBWs.contains(TE->UserTreeIndices.front().UserTE) && + "Expected user in MinBWs."); + bool IsSigned = MinBWs.lookup(TE->UserTreeIndices.front().UserTE).second; + Vec = Builder.CreateIntCast(Vec, PrevVec->getType(), IsSigned); + } PrevVec->replaceAllUsesWith(Vec); PostponedValues.try_emplace(Vec).first->second.push_back(TE); // Replace the stub vector node, if it was used before for one of the @@ -12539,7 +12762,9 @@ Value *BoUpSLP::vectorizeTree( DenseMap<Value *, InsertElementInst *> VectorToInsertElement; // Maps extract Scalar to the corresponding extractelement instruction in the // basic block. Only one extractelement per block should be emitted. - DenseMap<Value *, DenseMap<BasicBlock *, Instruction *>> ScalarToEEs; + DenseMap<Value *, + DenseMap<BasicBlock *, std::pair<Instruction *, Instruction *>>> + ScalarToEEs; SmallDenseSet<Value *, 4> UsedInserts; DenseMap<std::pair<Value *, Type *>, Value *> VectorCasts; SmallDenseSet<Value *, 4> ScalarsWithNullptrUser; @@ -12568,18 +12793,23 @@ Value *BoUpSLP::vectorizeTree( auto ExtractAndExtendIfNeeded = [&](Value *Vec) { if (Scalar->getType() != Vec->getType()) { Value *Ex = nullptr; + Value *ExV = nullptr; auto It = ScalarToEEs.find(Scalar); if (It != ScalarToEEs.end()) { // No need to emit many extracts, just move the only one in the // current block. auto EEIt = It->second.find(Builder.GetInsertBlock()); if (EEIt != It->second.end()) { - Instruction *I = EEIt->second; + Instruction *I = EEIt->second.first; if (Builder.GetInsertPoint() != Builder.GetInsertBlock()->end() && - Builder.GetInsertPoint()->comesBefore(I)) + Builder.GetInsertPoint()->comesBefore(I)) { I->moveBefore(*Builder.GetInsertPoint()->getParent(), Builder.GetInsertPoint()); + if (auto *CI = EEIt->second.second) + CI->moveAfter(I); + } Ex = I; + ExV = EEIt->second.second ? EEIt->second.second : Ex; } } if (!Ex) { @@ -12592,8 +12822,16 @@ Value *BoUpSLP::vectorizeTree( } else { Ex = Builder.CreateExtractElement(Vec, Lane); } + // If necessary, sign-extend or zero-extend ScalarRoot + // to the larger type. + ExV = Ex; + if (Scalar->getType() != Ex->getType()) + ExV = Builder.CreateIntCast(Ex, Scalar->getType(), + MinBWs.find(E)->second.second); if (auto *I = dyn_cast<Instruction>(Ex)) - ScalarToEEs[Scalar].try_emplace(Builder.GetInsertBlock(), I); + ScalarToEEs[Scalar].try_emplace( + Builder.GetInsertBlock(), + std::make_pair(I, cast<Instruction>(ExV))); } // The then branch of the previous if may produce constants, since 0 // operand might be a constant. @@ -12601,12 +12839,7 @@ Value *BoUpSLP::vectorizeTree( GatherShuffleExtractSeq.insert(ExI); CSEBlocks.insert(ExI->getParent()); } - // If necessary, sign-extend or zero-extend ScalarRoot - // to the larger type. - if (Scalar->getType() != Ex->getType()) - return Builder.CreateIntCast(Ex, Scalar->getType(), - MinBWs.find(E)->second.second); - return Ex; + return ExV; } assert(isa<FixedVectorType>(Scalar->getType()) && isa<InsertElementInst>(Scalar) && @@ -12669,7 +12902,7 @@ Value *BoUpSLP::vectorizeTree( auto Key = std::make_pair(Vec, ScalarTy); auto VecIt = VectorCasts.find(Key); if (VecIt == VectorCasts.end()) { - IRBuilder<>::InsertPointGuard Guard(Builder); + IRBuilderBase::InsertPointGuard Guard(Builder); if (auto *IVec = dyn_cast<Instruction>(Vec)) Builder.SetInsertPoint(IVec->getNextNonDebugInstruction()); Vec = Builder.CreateIntCast( @@ -12928,7 +13161,21 @@ Value *BoUpSLP::vectorizeTree( Builder.ClearInsertionPoint(); InstrElementSize.clear(); - return VectorizableTree[0]->VectorizedValue; + const TreeEntry &RootTE = *VectorizableTree.front().get(); + Value *Vec = RootTE.VectorizedValue; + if (auto It = MinBWs.find(&RootTE); ReductionBitWidth != 0 && + It != MinBWs.end() && + ReductionBitWidth != It->second.first) { + IRBuilder<>::InsertPointGuard Guard(Builder); + Builder.SetInsertPoint(ReductionRoot->getParent(), + ReductionRoot->getIterator()); + Vec = Builder.CreateIntCast( + Vec, + VectorType::get(Builder.getIntNTy(ReductionBitWidth), + cast<VectorType>(Vec->getType())->getElementCount()), + It->second.second); + } + return Vec; } void BoUpSLP::optimizeGatherSequence() { @@ -13687,26 +13934,29 @@ unsigned BoUpSLP::getVectorElementSize(Value *V) { // that feed it. The type of the loaded value may indicate a more suitable // width than V's type. We want to base the vector element size on the width // of memory operations where possible. - SmallVector<std::pair<Instruction *, BasicBlock *>, 16> Worklist; + SmallVector<std::tuple<Instruction *, BasicBlock *, unsigned>> Worklist; SmallPtrSet<Instruction *, 16> Visited; if (auto *I = dyn_cast<Instruction>(V)) { - Worklist.emplace_back(I, I->getParent()); + Worklist.emplace_back(I, I->getParent(), 0); Visited.insert(I); } // Traverse the expression tree in bottom-up order looking for loads. If we // encounter an instruction we don't yet handle, we give up. auto Width = 0u; + Value *FirstNonBool = nullptr; while (!Worklist.empty()) { - Instruction *I; - BasicBlock *Parent; - std::tie(I, Parent) = Worklist.pop_back_val(); + auto [I, Parent, Level] = Worklist.pop_back_val(); // We should only be looking at scalar instructions here. If the current // instruction has a vector type, skip. auto *Ty = I->getType(); if (isa<VectorType>(Ty)) continue; + if (Ty != Builder.getInt1Ty() && !FirstNonBool) + FirstNonBool = I; + if (Level > RecursionMaxDepth) + continue; // If the current instruction is a load, update MaxWidth to reflect the // width of the loaded value. @@ -13719,11 +13969,16 @@ unsigned BoUpSLP::getVectorElementSize(Value *V) { // user or the use is a PHI node, we add it to the worklist. else if (isa<PHINode, CastInst, GetElementPtrInst, CmpInst, SelectInst, BinaryOperator, UnaryOperator>(I)) { - for (Use &U : I->operands()) + for (Use &U : I->operands()) { if (auto *J = dyn_cast<Instruction>(U.get())) if (Visited.insert(J).second && - (isa<PHINode>(I) || J->getParent() == Parent)) - Worklist.emplace_back(J, J->getParent()); + (isa<PHINode>(I) || J->getParent() == Parent)) { + Worklist.emplace_back(J, J->getParent(), Level + 1); + continue; + } + if (!FirstNonBool && U.get()->getType() != Builder.getInt1Ty()) + FirstNonBool = U.get(); + } } else { break; } @@ -13733,8 +13988,8 @@ unsigned BoUpSLP::getVectorElementSize(Value *V) { // gave up for some reason, just return the width of V. Otherwise, return the // maximum width we found. if (!Width) { - if (auto *CI = dyn_cast<CmpInst>(V)) - V = CI->getOperand(0); + if (V->getType() == Builder.getInt1Ty() && FirstNonBool) + V = FirstNonBool; Width = DL->getTypeSizeInBits(V->getType()); } @@ -13748,36 +14003,118 @@ unsigned BoUpSLP::getVectorElementSize(Value *V) { // smaller type with a truncation. We collect the values that will be demoted // in ToDemote and additional roots that require investigating in Roots. bool BoUpSLP::collectValuesToDemote( - Value *V, SmallVectorImpl<Value *> &ToDemote, + Value *V, bool IsProfitableToDemoteRoot, unsigned &BitWidth, + SmallVectorImpl<Value *> &ToDemote, DenseMap<Instruction *, SmallVector<unsigned>> &DemotedConsts, - SmallVectorImpl<Value *> &Roots, DenseSet<Value *> &Visited) const { + DenseSet<Value *> &Visited, unsigned &MaxDepthLevel, + bool &IsProfitableToDemote, bool IsTruncRoot) const { // We can always demote constants. if (isa<Constant>(V)) return true; + if (DL->getTypeSizeInBits(V->getType()) == BitWidth) { + MaxDepthLevel = 1; + return true; + } + // If the value is not a vectorized instruction in the expression and not used // by the insertelement instruction and not used in multiple vector nodes, it // cannot be demoted. + auto IsPotentiallyTruncated = [&](Value *V, unsigned &BitWidth) -> bool { + if (MultiNodeScalars.contains(V)) + return false; + uint32_t OrigBitWidth = DL->getTypeSizeInBits(V->getType()); + if (OrigBitWidth > BitWidth) { + APInt Mask = APInt::getBitsSetFrom(OrigBitWidth, BitWidth); + if (MaskedValueIsZero(V, Mask, SimplifyQuery(*DL))) + return true; + } + auto NumSignBits = ComputeNumSignBits(V, *DL, 0, AC, nullptr, DT); + unsigned BitWidth1 = OrigBitWidth - NumSignBits; + if (!isKnownNonNegative(V, SimplifyQuery(*DL))) + ++BitWidth1; + BitWidth = std::max(BitWidth, BitWidth1); + return BitWidth > 0 && OrigBitWidth >= (BitWidth * 2); + }; + auto FinalAnalysis = [&](const TreeEntry *ITE = nullptr) { + if (!IsProfitableToDemote) + return false; + return (ITE && ITE->UserTreeIndices.size() > 1) || + IsPotentiallyTruncated(V, BitWidth); + }; + // TODO: improve handling of gathered values and others. auto *I = dyn_cast<Instruction>(V); - if (!I || !getTreeEntry(I) || MultiNodeScalars.contains(I) || - !Visited.insert(I).second || all_of(I->users(), [&](User *U) { + const TreeEntry *ITE = I ? getTreeEntry(I) : nullptr; + if (!ITE || !Visited.insert(I).second || MultiNodeScalars.contains(I) || + all_of(I->users(), [&](User *U) { return isa<InsertElementInst>(U) && !getTreeEntry(U); })) - return false; + return FinalAnalysis(); unsigned Start = 0; unsigned End = I->getNumOperands(); + + auto ProcessOperands = [&](ArrayRef<Value *> Operands, bool &NeedToExit) { + NeedToExit = false; + unsigned InitLevel = MaxDepthLevel; + for (Value *IncValue : Operands) { + unsigned Level = InitLevel; + if (!collectValuesToDemote(IncValue, IsProfitableToDemoteRoot, BitWidth, + ToDemote, DemotedConsts, Visited, Level, + IsProfitableToDemote, IsTruncRoot)) { + if (!IsProfitableToDemote) + return false; + NeedToExit = true; + if (!FinalAnalysis(ITE)) + return false; + continue; + } + MaxDepthLevel = std::max(MaxDepthLevel, Level); + } + return true; + }; + auto AttemptCheckBitwidth = + [&](function_ref<bool(unsigned, unsigned)> Checker, bool &NeedToExit) { + // Try all bitwidth < OrigBitWidth. + NeedToExit = false; + uint32_t OrigBitWidth = DL->getTypeSizeInBits(I->getType()); + unsigned BestFailBitwidth = 0; + for (; BitWidth < OrigBitWidth; BitWidth *= 2) { + if (Checker(BitWidth, OrigBitWidth)) + return true; + if (BestFailBitwidth == 0 && FinalAnalysis()) + BestFailBitwidth = BitWidth; + } + if (BitWidth >= OrigBitWidth) { + if (BestFailBitwidth == 0) { + BitWidth = OrigBitWidth; + return false; + } + MaxDepthLevel = 1; + BitWidth = BestFailBitwidth; + NeedToExit = true; + return true; + } + return false; + }; + bool NeedToExit = false; switch (I->getOpcode()) { // We can always demote truncations and extensions. Since truncations can // seed additional demotion, we save the truncated value. case Instruction::Trunc: - Roots.push_back(I->getOperand(0)); + if (!IsTruncRoot) + MaxDepthLevel = 1; + if (IsProfitableToDemoteRoot) + IsProfitableToDemote = true; + (void)IsPotentiallyTruncated(V, BitWidth); break; case Instruction::ZExt: case Instruction::SExt: - if (isa<ExtractElementInst, InsertElementInst>(I->getOperand(0))) - return false; + if (!IsTruncRoot) + MaxDepthLevel = 1; + IsProfitableToDemote = true; + (void)IsPotentiallyTruncated(V, BitWidth); break; // We can demote certain binary operations if we can demote both of their @@ -13787,22 +14124,108 @@ bool BoUpSLP::collectValuesToDemote( case Instruction::Mul: case Instruction::And: case Instruction::Or: - case Instruction::Xor: - if (!collectValuesToDemote(I->getOperand(0), ToDemote, DemotedConsts, Roots, - Visited) || - !collectValuesToDemote(I->getOperand(1), ToDemote, DemotedConsts, Roots, - Visited)) + case Instruction::Xor: { + if (ITE->UserTreeIndices.size() > 1 && !IsPotentiallyTruncated(I, BitWidth)) + return false; + if (!ProcessOperands({I->getOperand(0), I->getOperand(1)}, NeedToExit)) + return false; + break; + } + case Instruction::Shl: { + // Several vectorized uses? Check if we can truncate it, otherwise - exit. + if (ITE->UserTreeIndices.size() > 1 && !IsPotentiallyTruncated(I, BitWidth)) + return false; + // If we are truncating the result of this SHL, and if it's a shift of an + // inrange amount, we can always perform a SHL in a smaller type. + if (!AttemptCheckBitwidth( + [&](unsigned BitWidth, unsigned) { + KnownBits AmtKnownBits = computeKnownBits(I->getOperand(1), *DL); + return AmtKnownBits.getMaxValue().ult(BitWidth); + }, + NeedToExit)) + return false; + if (NeedToExit) + return true; + if (!ProcessOperands({I->getOperand(0), I->getOperand(1)}, NeedToExit)) + return false; + break; + } + case Instruction::LShr: { + // Several vectorized uses? Check if we can truncate it, otherwise - exit. + if (ITE->UserTreeIndices.size() > 1 && !IsPotentiallyTruncated(I, BitWidth)) + return false; + // If this is a truncate of a logical shr, we can truncate it to a smaller + // lshr iff we know that the bits we would otherwise be shifting in are + // already zeros. + if (!AttemptCheckBitwidth( + [&](unsigned BitWidth, unsigned OrigBitWidth) { + KnownBits AmtKnownBits = computeKnownBits(I->getOperand(1), *DL); + APInt ShiftedBits = APInt::getBitsSetFrom(OrigBitWidth, BitWidth); + return AmtKnownBits.getMaxValue().ult(BitWidth) && + MaskedValueIsZero(I->getOperand(0), ShiftedBits, + SimplifyQuery(*DL)); + }, + NeedToExit)) + return false; + if (NeedToExit) + return true; + if (!ProcessOperands({I->getOperand(0), I->getOperand(1)}, NeedToExit)) + return false; + break; + } + case Instruction::AShr: { + // Several vectorized uses? Check if we can truncate it, otherwise - exit. + if (ITE->UserTreeIndices.size() > 1 && !IsPotentiallyTruncated(I, BitWidth)) + return false; + // If this is a truncate of an arithmetic shr, we can truncate it to a + // smaller ashr iff we know that all the bits from the sign bit of the + // original type and the sign bit of the truncate type are similar. + if (!AttemptCheckBitwidth( + [&](unsigned BitWidth, unsigned OrigBitWidth) { + KnownBits AmtKnownBits = computeKnownBits(I->getOperand(1), *DL); + unsigned ShiftedBits = OrigBitWidth - BitWidth; + return AmtKnownBits.getMaxValue().ult(BitWidth) && + ShiftedBits < ComputeNumSignBits(I->getOperand(0), *DL, 0, + AC, nullptr, DT); + }, + NeedToExit)) + return false; + if (NeedToExit) + return true; + if (!ProcessOperands({I->getOperand(0), I->getOperand(1)}, NeedToExit)) + return false; + break; + } + case Instruction::UDiv: + case Instruction::URem: { + if (ITE->UserTreeIndices.size() > 1 && !IsPotentiallyTruncated(I, BitWidth)) + return false; + // UDiv and URem can be truncated if all the truncated bits are zero. + if (!AttemptCheckBitwidth( + [&](unsigned BitWidth, unsigned OrigBitWidth) { + assert(BitWidth <= OrigBitWidth && "Unexpected bitwidths!"); + APInt Mask = APInt::getBitsSetFrom(OrigBitWidth, BitWidth); + return MaskedValueIsZero(I->getOperand(0), Mask, + SimplifyQuery(*DL)) && + MaskedValueIsZero(I->getOperand(1), Mask, + SimplifyQuery(*DL)); + }, + NeedToExit)) + return false; + if (NeedToExit) + return true; + if (!ProcessOperands({I->getOperand(0), I->getOperand(1)}, NeedToExit)) return false; break; + } // We can demote selects if we can demote their true and false values. case Instruction::Select: { + if (ITE->UserTreeIndices.size() > 1 && !IsPotentiallyTruncated(I, BitWidth)) + return false; Start = 1; - SelectInst *SI = cast<SelectInst>(I); - if (!collectValuesToDemote(SI->getTrueValue(), ToDemote, DemotedConsts, - Roots, Visited) || - !collectValuesToDemote(SI->getFalseValue(), ToDemote, DemotedConsts, - Roots, Visited)) + auto *SI = cast<SelectInst>(I); + if (!ProcessOperands({SI->getTrueValue(), SI->getFalseValue()}, NeedToExit)) return false; break; } @@ -13811,172 +14234,289 @@ bool BoUpSLP::collectValuesToDemote( // we don't need to worry about cycles since we ensure single use above. case Instruction::PHI: { PHINode *PN = cast<PHINode>(I); - for (Value *IncValue : PN->incoming_values()) - if (!collectValuesToDemote(IncValue, ToDemote, DemotedConsts, Roots, - Visited)) - return false; + if (ITE->UserTreeIndices.size() > 1 && !IsPotentiallyTruncated(I, BitWidth)) + return false; + SmallVector<Value *> Ops(PN->incoming_values().begin(), + PN->incoming_values().end()); + if (!ProcessOperands(Ops, NeedToExit)) + return false; break; } // Otherwise, conservatively give up. default: - return false; + MaxDepthLevel = 1; + return FinalAnalysis(); } + if (NeedToExit) + return true; + ++MaxDepthLevel; // Gather demoted constant operands. for (unsigned Idx : seq<unsigned>(Start, End)) if (isa<Constant>(I->getOperand(Idx))) DemotedConsts.try_emplace(I).first->getSecond().push_back(Idx); // Record the value that we can demote. ToDemote.push_back(V); - return true; + return IsProfitableToDemote; } void BoUpSLP::computeMinimumValueSizes() { // We only attempt to truncate integer expressions. - auto &TreeRoot = VectorizableTree[0]->Scalars; - auto *TreeRootIT = dyn_cast<IntegerType>(TreeRoot[0]->getType()); - if (!TreeRootIT || VectorizableTree.front()->State == TreeEntry::NeedToGather) + bool IsStoreOrInsertElt = + VectorizableTree.front()->getOpcode() == Instruction::Store || + VectorizableTree.front()->getOpcode() == Instruction::InsertElement; + if ((IsStoreOrInsertElt || UserIgnoreList) && TruncNodes.size() <= 1 && + (!CastMaxMinBWSizes || CastMaxMinBWSizes->second == 0 || + CastMaxMinBWSizes->first / CastMaxMinBWSizes->second <= 2)) return; + unsigned NodeIdx = 0; + if (IsStoreOrInsertElt && + VectorizableTree.front()->State != TreeEntry::NeedToGather) + NodeIdx = 1; + // Ensure the roots of the vectorizable tree don't form a cycle. - if (!VectorizableTree.front()->UserTreeIndices.empty()) + if (VectorizableTree[NodeIdx]->State == TreeEntry::NeedToGather || + (NodeIdx == 0 && !VectorizableTree[NodeIdx]->UserTreeIndices.empty()) || + (NodeIdx != 0 && any_of(VectorizableTree[NodeIdx]->UserTreeIndices, + [NodeIdx](const EdgeInfo &EI) { + return EI.UserTE->Idx > + static_cast<int>(NodeIdx); + }))) return; - // Conservatively determine if we can actually truncate the roots of the - // expression. Collect the values that can be demoted in ToDemote and - // additional roots that require investigating in Roots. - SmallVector<Value *, 32> ToDemote; - DenseMap<Instruction *, SmallVector<unsigned>> DemotedConsts; - SmallVector<Value *, 4> Roots; - for (auto *Root : TreeRoot) { - DenseSet<Value *> Visited; - if (!collectValuesToDemote(Root, ToDemote, DemotedConsts, Roots, Visited)) - return; - } - - // The maximum bit width required to represent all the values that can be - // demoted without loss of precision. It would be safe to truncate the roots - // of the expression to this width. - auto MaxBitWidth = 1u; - - // We first check if all the bits of the roots are demanded. If they're not, - // we can truncate the roots to this narrower type. - for (auto *Root : TreeRoot) { - auto Mask = DB->getDemandedBits(cast<Instruction>(Root)); - MaxBitWidth = std::max<unsigned>(Mask.getBitWidth() - Mask.countl_zero(), - MaxBitWidth); - } - - // True if the roots can be zero-extended back to their original type, rather - // than sign-extended. We know that if the leading bits are not demanded, we - // can safely zero-extend. So we initialize IsKnownPositive to True. - bool IsKnownPositive = true; - - // If all the bits of the roots are demanded, we can try a little harder to - // compute a narrower type. This can happen, for example, if the roots are - // getelementptr indices. InstCombine promotes these indices to the pointer - // width. Thus, all their bits are technically demanded even though the - // address computation might be vectorized in a smaller type. - // - // We start by looking at each entry that can be demoted. We compute the - // maximum bit width required to store the scalar by using ValueTracking to - // compute the number of high-order bits we can truncate. - if (MaxBitWidth == DL->getTypeSizeInBits(TreeRoot[0]->getType()) && - all_of(TreeRoot, [](Value *V) { - return all_of(V->users(), - [](User *U) { return isa<GetElementPtrInst>(U); }); - })) { - MaxBitWidth = 8u; + // The first value node for store/insertelement is sext/zext/trunc? Skip it, + // resize to the final type. + bool IsTruncRoot = false; + bool IsProfitableToDemoteRoot = !IsStoreOrInsertElt; + SmallVector<unsigned> RootDemotes; + if (NodeIdx != 0 && + VectorizableTree[NodeIdx]->State == TreeEntry::Vectorize && + VectorizableTree[NodeIdx]->getOpcode() == Instruction::Trunc) { + assert(IsStoreOrInsertElt && "Expected store/insertelement seeded graph."); + IsTruncRoot = true; + RootDemotes.push_back(NodeIdx); + IsProfitableToDemoteRoot = true; + ++NodeIdx; + } + + // Analyzed in reduction already and not profitable - exit. + if (AnalyzedMinBWVals.contains(VectorizableTree[NodeIdx]->Scalars.front())) + return; + SmallVector<Value *> ToDemote; + DenseMap<Instruction *, SmallVector<unsigned>> DemotedConsts; + auto ComputeMaxBitWidth = [&](ArrayRef<Value *> TreeRoot, unsigned VF, + bool IsTopRoot, bool IsProfitableToDemoteRoot, + unsigned Opcode, unsigned Limit, bool IsTruncRoot) { + ToDemote.clear(); + auto *TreeRootIT = dyn_cast<IntegerType>(TreeRoot[0]->getType()); + if (!TreeRootIT || !Opcode) + return 0u; + + if (AnalyzedMinBWVals.contains(TreeRoot.front())) + return 0u; + + unsigned NumParts = TTI->getNumberOfParts( + FixedVectorType::get(TreeRoot.front()->getType(), VF)); + + // The maximum bit width required to represent all the values that can be + // demoted without loss of precision. It would be safe to truncate the roots + // of the expression to this width. + unsigned MaxBitWidth = 1u; + + // True if the roots can be zero-extended back to their original type, + // rather than sign-extended. We know that if the leading bits are not + // demanded, we can safely zero-extend. So we initialize IsKnownPositive to + // True. // Determine if the sign bit of all the roots is known to be zero. If not, // IsKnownPositive is set to False. - IsKnownPositive = llvm::all_of(TreeRoot, [&](Value *R) { + bool IsKnownPositive = all_of(TreeRoot, [&](Value *R) { KnownBits Known = computeKnownBits(R, *DL); return Known.isNonNegative(); }); - // Determine the maximum number of bits required to store the scalar - // values. - for (auto *Scalar : ToDemote) { - auto NumSignBits = ComputeNumSignBits(Scalar, *DL, 0, AC, nullptr, DT); - auto NumTypeBits = DL->getTypeSizeInBits(Scalar->getType()); - MaxBitWidth = std::max<unsigned>(NumTypeBits - NumSignBits, MaxBitWidth); - } - - // If we can't prove that the sign bit is zero, we must add one to the - // maximum bit width to account for the unknown sign bit. This preserves - // the existing sign bit so we can safely sign-extend the root back to the - // original type. Otherwise, if we know the sign bit is zero, we will - // zero-extend the root instead. - // - // FIXME: This is somewhat suboptimal, as there will be cases where adding - // one to the maximum bit width will yield a larger-than-necessary - // type. In general, we need to add an extra bit only if we can't - // prove that the upper bit of the original type is equal to the - // upper bit of the proposed smaller type. If these two bits are the - // same (either zero or one) we know that sign-extending from the - // smaller type will result in the same value. Here, since we can't - // yet prove this, we are just making the proposed smaller type - // larger to ensure correctness. - if (!IsKnownPositive) - ++MaxBitWidth; - } - - // Round MaxBitWidth up to the next power-of-two. - MaxBitWidth = llvm::bit_ceil(MaxBitWidth); - - // If the maximum bit width we compute is less than the with of the roots' - // type, we can proceed with the narrowing. Otherwise, do nothing. - if (MaxBitWidth >= TreeRootIT->getBitWidth()) - return; + // We first check if all the bits of the roots are demanded. If they're not, + // we can truncate the roots to this narrower type. + for (auto *Root : TreeRoot) { + unsigned NumSignBits = ComputeNumSignBits(Root, *DL, 0, AC, nullptr, DT); + TypeSize NumTypeBits = DL->getTypeSizeInBits(Root->getType()); + unsigned BitWidth1 = NumTypeBits - NumSignBits; + // If we can't prove that the sign bit is zero, we must add one to the + // maximum bit width to account for the unknown sign bit. This preserves + // the existing sign bit so we can safely sign-extend the root back to the + // original type. Otherwise, if we know the sign bit is zero, we will + // zero-extend the root instead. + // + // FIXME: This is somewhat suboptimal, as there will be cases where adding + // one to the maximum bit width will yield a larger-than-necessary + // type. In general, we need to add an extra bit only if we can't + // prove that the upper bit of the original type is equal to the + // upper bit of the proposed smaller type. If these two bits are + // the same (either zero or one) we know that sign-extending from + // the smaller type will result in the same value. Here, since we + // can't yet prove this, we are just making the proposed smaller + // type larger to ensure correctness. + if (!IsKnownPositive) + ++BitWidth1; + + APInt Mask = DB->getDemandedBits(cast<Instruction>(Root)); + unsigned BitWidth2 = Mask.getBitWidth() - Mask.countl_zero(); + MaxBitWidth = + std::max<unsigned>(std::min(BitWidth1, BitWidth2), MaxBitWidth); + } + + if (MaxBitWidth < 8 && MaxBitWidth > 1) + MaxBitWidth = 8; + + // If the original type is large, but reduced type does not improve the reg + // use - ignore it. + if (NumParts > 1 && + NumParts == + TTI->getNumberOfParts(FixedVectorType::get( + IntegerType::get(F->getContext(), bit_ceil(MaxBitWidth)), VF))) + return 0u; + + bool IsProfitableToDemote = Opcode == Instruction::Trunc || + Opcode == Instruction::SExt || + Opcode == Instruction::ZExt || NumParts > 1; + // Conservatively determine if we can actually truncate the roots of the + // expression. Collect the values that can be demoted in ToDemote and + // additional roots that require investigating in Roots. + for (auto *Root : TreeRoot) { + DenseSet<Value *> Visited; + unsigned MaxDepthLevel = IsTruncRoot ? Limit : 1; + bool NeedToDemote = IsProfitableToDemote; + + if (!collectValuesToDemote(Root, IsProfitableToDemoteRoot, MaxBitWidth, + ToDemote, DemotedConsts, Visited, + MaxDepthLevel, NeedToDemote, IsTruncRoot) || + (MaxDepthLevel <= Limit && + !(((Opcode == Instruction::SExt || Opcode == Instruction::ZExt) && + (!IsTopRoot || !(IsStoreOrInsertElt || UserIgnoreList) || + DL->getTypeSizeInBits(Root->getType()) / + DL->getTypeSizeInBits( + cast<Instruction>(Root)->getOperand(0)->getType()) > + 2))))) + return 0u; + } + // Round MaxBitWidth up to the next power-of-two. + MaxBitWidth = bit_ceil(MaxBitWidth); + + return MaxBitWidth; + }; // If we can truncate the root, we must collect additional values that might // be demoted as a result. That is, those seeded by truncations we will // modify. - while (!Roots.empty()) { - DenseSet<Value *> Visited; - collectValuesToDemote(Roots.pop_back_val(), ToDemote, DemotedConsts, Roots, - Visited); - } - - // Check that all users are marked for demotion. - DenseSet<Value *> Demoted(ToDemote.begin(), ToDemote.end()); - DenseSet<const TreeEntry *> Visited; - for (Value *V: ToDemote) { - const TreeEntry *TE = getTreeEntry(V); - assert(TE && "Expected vectorized scalar."); - if (!Visited.insert(TE).second) - continue; - if (!all_of(TE->UserTreeIndices, [&](const EdgeInfo &EI) { - return all_of(EI.UserTE->Scalars, - [&](Value *V) { return Demoted.contains(V); }); - })) - return; - } - // Finally, map the values we can demote to the maximum bit with we computed. - for (auto *Scalar : ToDemote) { - auto *TE = getTreeEntry(Scalar); - assert(TE && "Expected vectorized scalar."); - if (MinBWs.contains(TE)) + // Add reduction ops sizes, if any. + if (UserIgnoreList && + isa<IntegerType>(VectorizableTree.front()->Scalars.front()->getType())) { + for (Value *V : *UserIgnoreList) { + auto NumSignBits = ComputeNumSignBits(V, *DL, 0, AC, nullptr, DT); + auto NumTypeBits = DL->getTypeSizeInBits(V->getType()); + unsigned BitWidth1 = NumTypeBits - NumSignBits; + if (!isKnownNonNegative(V, SimplifyQuery(*DL))) + ++BitWidth1; + auto Mask = DB->getDemandedBits(cast<Instruction>(V)); + unsigned BitWidth2 = Mask.getBitWidth() - Mask.countl_zero(); + ReductionBitWidth = + std::max(std::min(BitWidth1, BitWidth2), ReductionBitWidth); + } + if (ReductionBitWidth < 8 && ReductionBitWidth > 1) + ReductionBitWidth = 8; + + ReductionBitWidth = bit_ceil(ReductionBitWidth); + } + bool IsTopRoot = NodeIdx == 0; + while (NodeIdx < VectorizableTree.size() && + VectorizableTree[NodeIdx]->State == TreeEntry::Vectorize && + VectorizableTree[NodeIdx]->getOpcode() == Instruction::Trunc) { + RootDemotes.push_back(NodeIdx); + ++NodeIdx; + IsTruncRoot = true; + } + while (NodeIdx < VectorizableTree.size()) { + ArrayRef<Value *> TreeRoot = VectorizableTree[NodeIdx]->Scalars; + unsigned Limit = 2; + unsigned Opcode = VectorizableTree[NodeIdx]->getOpcode(); + if (IsTopRoot && + ReductionBitWidth == + DL->getTypeSizeInBits( + VectorizableTree.front()->Scalars.front()->getType())) + Limit = 3; + unsigned MaxBitWidth = ComputeMaxBitWidth( + TreeRoot, VectorizableTree[NodeIdx]->getVectorFactor(), IsTopRoot, + IsProfitableToDemoteRoot, Opcode, Limit, IsTruncRoot); + if (ReductionBitWidth != 0 && (IsTopRoot || !RootDemotes.empty())) { + if (MaxBitWidth != 0 && ReductionBitWidth < MaxBitWidth) + ReductionBitWidth = bit_ceil(MaxBitWidth); + else if (MaxBitWidth == 0) + ReductionBitWidth = 0; + } + + for (unsigned Idx : RootDemotes) { + Value *V = VectorizableTree[Idx]->Scalars.front(); + uint32_t OrigBitWidth = DL->getTypeSizeInBits(V->getType()); + if (OrigBitWidth > MaxBitWidth) { + APInt Mask = APInt::getBitsSetFrom(OrigBitWidth, MaxBitWidth); + if (MaskedValueIsZero(V, Mask, SimplifyQuery(*DL))) + ToDemote.push_back(V); + } + } + RootDemotes.clear(); + IsTopRoot = false; + IsProfitableToDemoteRoot = true; + + if (TruncNodes.empty()) { + NodeIdx = VectorizableTree.size(); + } else { + unsigned NewIdx = 0; + do { + NewIdx = *TruncNodes.begin() + 1; + TruncNodes.erase(TruncNodes.begin()); + } while (NewIdx <= NodeIdx && !TruncNodes.empty()); + NodeIdx = NewIdx; + IsTruncRoot = true; + } + + // If the maximum bit width we compute is less than the with of the roots' + // type, we can proceed with the narrowing. Otherwise, do nothing. + if (MaxBitWidth == 0 || + MaxBitWidth >= + cast<IntegerType>(TreeRoot.front()->getType())->getBitWidth()) { + if (UserIgnoreList) + AnalyzedMinBWVals.insert(TreeRoot.begin(), TreeRoot.end()); continue; - bool IsSigned = any_of(TE->Scalars, [&](Value *R) { - KnownBits Known = computeKnownBits(R, *DL); - return !Known.isNonNegative(); - }); - MinBWs.try_emplace(TE, MaxBitWidth, IsSigned); - const auto *I = cast<Instruction>(Scalar); - auto DCIt = DemotedConsts.find(I); - if (DCIt != DemotedConsts.end()) { - for (unsigned Idx : DCIt->getSecond()) { - // Check that all instructions operands are demoted. - if (all_of(TE->Scalars, [&](Value *V) { - auto SIt = DemotedConsts.find(cast<Instruction>(V)); - return SIt != DemotedConsts.end() && - is_contained(SIt->getSecond(), Idx); - })) { + } + + // Finally, map the values we can demote to the maximum bit with we + // computed. + for (Value *Scalar : ToDemote) { + TreeEntry *TE = getTreeEntry(Scalar); + assert(TE && "Expected vectorized scalar."); + if (MinBWs.contains(TE)) + continue; + bool IsSigned = TE->getOpcode() == Instruction::SExt || + any_of(TE->Scalars, [&](Value *R) { + return !isKnownNonNegative(R, SimplifyQuery(*DL)); + }); + MinBWs.try_emplace(TE, MaxBitWidth, IsSigned); + const auto *I = cast<Instruction>(Scalar); + auto DCIt = DemotedConsts.find(I); + if (DCIt != DemotedConsts.end()) { + for (unsigned Idx : DCIt->getSecond()) { + // Check that all instructions operands are demoted. const TreeEntry *CTE = getOperandEntry(TE, Idx); - MinBWs.try_emplace(CTE, MaxBitWidth, IsSigned); + if (all_of(TE->Scalars, + [&](Value *V) { + auto SIt = DemotedConsts.find(cast<Instruction>(V)); + return SIt != DemotedConsts.end() && + is_contained(SIt->getSecond(), Idx); + }) || + all_of(CTE->Scalars, IsaPred<Constant>)) + MinBWs.try_emplace(CTE, MaxBitWidth, IsSigned); } } } @@ -14658,10 +15198,9 @@ class HorizontalReduction { } /// Creates reduction operation with the current opcode. - static Value *createOp(IRBuilder<> &Builder, RecurKind Kind, Value *LHS, + static Value *createOp(IRBuilderBase &Builder, RecurKind Kind, Value *LHS, Value *RHS, const Twine &Name, bool UseSelect) { unsigned RdxOpcode = RecurrenceDescriptor::getOpcode(Kind); - bool IsConstant = isConstant(LHS) && isConstant(RHS); switch (Kind) { case RecurKind::Or: if (UseSelect && @@ -14683,49 +15222,33 @@ class HorizontalReduction { return Builder.CreateBinOp((Instruction::BinaryOps)RdxOpcode, LHS, RHS, Name); case RecurKind::FMax: - if (IsConstant) - return ConstantFP::get(LHS->getType(), - maxnum(cast<ConstantFP>(LHS)->getValueAPF(), - cast<ConstantFP>(RHS)->getValueAPF())); return Builder.CreateBinaryIntrinsic(Intrinsic::maxnum, LHS, RHS); case RecurKind::FMin: - if (IsConstant) - return ConstantFP::get(LHS->getType(), - minnum(cast<ConstantFP>(LHS)->getValueAPF(), - cast<ConstantFP>(RHS)->getValueAPF())); return Builder.CreateBinaryIntrinsic(Intrinsic::minnum, LHS, RHS); case RecurKind::FMaximum: - if (IsConstant) - return ConstantFP::get(LHS->getType(), - maximum(cast<ConstantFP>(LHS)->getValueAPF(), - cast<ConstantFP>(RHS)->getValueAPF())); return Builder.CreateBinaryIntrinsic(Intrinsic::maximum, LHS, RHS); case RecurKind::FMinimum: - if (IsConstant) - return ConstantFP::get(LHS->getType(), - minimum(cast<ConstantFP>(LHS)->getValueAPF(), - cast<ConstantFP>(RHS)->getValueAPF())); return Builder.CreateBinaryIntrinsic(Intrinsic::minimum, LHS, RHS); case RecurKind::SMax: - if (IsConstant || UseSelect) { + if (UseSelect) { Value *Cmp = Builder.CreateICmpSGT(LHS, RHS, Name); return Builder.CreateSelect(Cmp, LHS, RHS, Name); } return Builder.CreateBinaryIntrinsic(Intrinsic::smax, LHS, RHS); case RecurKind::SMin: - if (IsConstant || UseSelect) { + if (UseSelect) { Value *Cmp = Builder.CreateICmpSLT(LHS, RHS, Name); return Builder.CreateSelect(Cmp, LHS, RHS, Name); } return Builder.CreateBinaryIntrinsic(Intrinsic::smin, LHS, RHS); case RecurKind::UMax: - if (IsConstant || UseSelect) { + if (UseSelect) { Value *Cmp = Builder.CreateICmpUGT(LHS, RHS, Name); return Builder.CreateSelect(Cmp, LHS, RHS, Name); } return Builder.CreateBinaryIntrinsic(Intrinsic::umax, LHS, RHS); case RecurKind::UMin: - if (IsConstant || UseSelect) { + if (UseSelect) { Value *Cmp = Builder.CreateICmpULT(LHS, RHS, Name); return Builder.CreateSelect(Cmp, LHS, RHS, Name); } @@ -14737,15 +15260,13 @@ class HorizontalReduction { /// Creates reduction operation with the current opcode with the IR flags /// from \p ReductionOps, dropping nuw/nsw flags. - static Value *createOp(IRBuilder<> &Builder, RecurKind RdxKind, Value *LHS, + static Value *createOp(IRBuilderBase &Builder, RecurKind RdxKind, Value *LHS, Value *RHS, const Twine &Name, const ReductionOpsListType &ReductionOps) { - bool UseSelect = - ReductionOps.size() == 2 || - // Logical or/and. - (ReductionOps.size() == 1 && any_of(ReductionOps.front(), [](Value *V) { - return isa<SelectInst>(V); - })); + bool UseSelect = ReductionOps.size() == 2 || + // Logical or/and. + (ReductionOps.size() == 1 && + any_of(ReductionOps.front(), IsaPred<SelectInst>)); assert((!UseSelect || ReductionOps.size() != 2 || isa<SelectInst>(ReductionOps[1][0])) && "Expected cmp + select pairs for reduction"); @@ -14984,7 +15505,7 @@ public: !hasRequiredNumberOfUses(IsCmpSelMinMax, EdgeInst) || !isVectorizable(RdxKind, EdgeInst) || (R.isAnalyzedReductionRoot(EdgeInst) && - all_of(EdgeInst->operands(), Constant::classof))) { + all_of(EdgeInst->operands(), IsaPred<Constant>))) { PossibleReducedVals.push_back(EdgeVal); continue; } @@ -15119,7 +15640,7 @@ public: } /// Attempt to vectorize the tree found by matchAssociativeReduction. - Value *tryToReduce(BoUpSLP &V, TargetTransformInfo *TTI, + Value *tryToReduce(BoUpSLP &V, const DataLayout &DL, TargetTransformInfo *TTI, const TargetLibraryInfo &TLI) { constexpr int ReductionLimit = 4; constexpr unsigned RegMaxNumber = 4; @@ -15145,7 +15666,9 @@ public: return nullptr; } - IRBuilder<> Builder(cast<Instruction>(ReductionRoot)); + IRBuilder<TargetFolder> Builder(ReductionRoot->getContext(), + TargetFolder(DL)); + Builder.SetInsertPoint(cast<Instruction>(ReductionRoot)); // Track the reduced values in case if they are replaced by extractelement // because of the vectorization. @@ -15353,7 +15876,9 @@ public: RegMaxNumber * llvm::bit_floor(MaxVecRegSize / EltSize); unsigned ReduxWidth = std::min<unsigned>( - llvm::bit_floor(NumReducedVals), std::max(RedValsMaxNumber, MaxElts)); + llvm::bit_floor(NumReducedVals), + std::clamp<unsigned>(MaxElts, RedValsMaxNumber, + RegMaxNumber * RedValsMaxNumber)); unsigned Start = 0; unsigned Pos = Start; // Restarts vectorization attempt with lower vector factor. @@ -15495,7 +16020,7 @@ public: LLVM_DEBUG(dbgs() << "SLP: Found cost = " << Cost << " for reduction\n"); if (!Cost.isValid()) - return nullptr; + break; if (Cost >= -SLPCostThreshold) { V.getORE()->emit([&]() { return OptimizationRemarkMissed( @@ -15826,7 +16351,7 @@ private: } /// Emit a horizontal reduction of the vectorized value. - Value *emitReduction(Value *VectorizedValue, IRBuilder<> &Builder, + Value *emitReduction(Value *VectorizedValue, IRBuilderBase &Builder, unsigned ReduxWidth, const TargetTransformInfo *TTI) { assert(VectorizedValue && "Need to have a vectorized tree node"); assert(isPowerOf2_32(ReduxWidth) && @@ -16241,7 +16766,7 @@ bool SLPVectorizerPass::vectorizeHorReduction( HorizontalReduction HorRdx; if (!HorRdx.matchAssociativeReduction(R, Inst, *SE, *DL, *TLI)) return nullptr; - return HorRdx.tryToReduce(R, TTI, *TLI); + return HorRdx.tryToReduce(R, *DL, TTI, *TLI); }; auto TryAppendToPostponedInsts = [&](Instruction *FutureSeed) { if (TryOperandsAsNewSeeds && FutureSeed == Root) { @@ -16336,9 +16861,7 @@ bool SLPVectorizerPass::vectorizeInsertElementInst(InsertElementInst *IEI, SmallVector<Value *, 16> BuildVectorOpds; SmallVector<int> Mask; if (!findBuildAggregate(IEI, TTI, BuildVectorOpds, BuildVectorInsts) || - (llvm::all_of( - BuildVectorOpds, - [](Value *V) { return isa<ExtractElementInst, UndefValue>(V); }) && + (llvm::all_of(BuildVectorOpds, IsaPred<ExtractElementInst, UndefValue>) && isFixedVectorShuffle(BuildVectorOpds, Mask))) return false; @@ -16559,10 +17082,7 @@ bool SLPVectorizerPass::vectorizeCmpInsts(iterator_range<ItT> CmpInsts, bool SLPVectorizerPass::vectorizeInserts(InstSetVector &Instructions, BasicBlock *BB, BoUpSLP &R) { - assert(all_of(Instructions, - [](auto *I) { - return isa<InsertElementInst, InsertValueInst>(I); - }) && + assert(all_of(Instructions, IsaPred<InsertElementInst, InsertValueInst>) && "This function only accepts Insert instructions"); bool OpsChanged = false; SmallVector<WeakTrackingVH> PostponedInsts; diff --git a/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h b/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h index b1498026adadfef30852a5ccaa959b7fdbea7e13..605b47fa0a46b8c2e2a66242388968b58ff21e91 100644 --- a/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h +++ b/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h @@ -23,6 +23,9 @@ class TargetLibraryInfo; /// Helper class to create VPRecipies from IR instructions. class VPRecipeBuilder { + /// The VPlan new recipes are added to. + VPlan &Plan; + /// The loop that we evaluate. Loop *OrigLoop; @@ -49,9 +52,8 @@ class VPRecipeBuilder { EdgeMaskCacheTy EdgeMaskCache; BlockMaskCacheTy BlockMaskCache; - // VPlan-VPlan transformations support: Hold a mapping from ingredients to - // their recipe. To save on memory, only do so for selected ingredients, - // marked by having a nullptr entry in this map. + // VPlan construction support: Hold a mapping from ingredients to + // their recipe. DenseMap<Instruction *, VPRecipeBase *> Ingredient2Recipe; /// Cross-iteration reduction & first-order recurrence phis for which we need @@ -69,91 +71,77 @@ class VPRecipeBuilder { /// recipe that takes an additional VPInstruction for the mask. VPWidenMemoryInstructionRecipe *tryToWidenMemory(Instruction *I, ArrayRef<VPValue *> Operands, - VFRange &Range, - VPlanPtr &Plan); + VFRange &Range); /// Check if an induction recipe should be constructed for \p Phi. If so build /// and return it. If not, return null. VPHeaderPHIRecipe *tryToOptimizeInductionPHI(PHINode *Phi, ArrayRef<VPValue *> Operands, - VPlan &Plan, VFRange &Range); + VFRange &Range); /// Optimize the special case where the operand of \p I is a constant integer /// induction variable. VPWidenIntOrFpInductionRecipe * tryToOptimizeInductionTruncate(TruncInst *I, ArrayRef<VPValue *> Operands, - VFRange &Range, VPlan &Plan); + VFRange &Range); /// Handle non-loop phi nodes. Return a new VPBlendRecipe otherwise. Currently /// all such phi nodes are turned into a sequence of select instructions as /// the vectorizer currently performs full if-conversion. - VPBlendRecipe *tryToBlend(PHINode *Phi, ArrayRef<VPValue *> Operands, - VPlanPtr &Plan); + VPBlendRecipe *tryToBlend(PHINode *Phi, ArrayRef<VPValue *> Operands); /// Handle call instructions. If \p CI can be widened for \p Range.Start, /// return a new VPWidenCallRecipe. Range.End may be decreased to ensure same /// decision from \p Range.Start to \p Range.End. VPWidenCallRecipe *tryToWidenCall(CallInst *CI, ArrayRef<VPValue *> Operands, - VFRange &Range, VPlanPtr &Plan); + VFRange &Range); /// Check if \p I has an opcode that can be widened and return a VPWidenRecipe /// if it can. The function should only be called if the cost-model indicates /// that widening should be performed. VPWidenRecipe *tryToWiden(Instruction *I, ArrayRef<VPValue *> Operands, - VPBasicBlock *VPBB, VPlanPtr &Plan); + VPBasicBlock *VPBB); public: - VPRecipeBuilder(Loop *OrigLoop, const TargetLibraryInfo *TLI, + VPRecipeBuilder(VPlan &Plan, Loop *OrigLoop, const TargetLibraryInfo *TLI, LoopVectorizationLegality *Legal, LoopVectorizationCostModel &CM, PredicatedScalarEvolution &PSE, VPBuilder &Builder) - : OrigLoop(OrigLoop), TLI(TLI), Legal(Legal), CM(CM), PSE(PSE), - Builder(Builder) {} + : Plan(Plan), OrigLoop(OrigLoop), TLI(TLI), Legal(Legal), CM(CM), + PSE(PSE), Builder(Builder) {} /// Create and return a widened recipe for \p I if one can be created within /// the given VF \p Range. VPRecipeBase *tryToCreateWidenRecipe(Instruction *Instr, ArrayRef<VPValue *> Operands, - VFRange &Range, VPBasicBlock *VPBB, - VPlanPtr &Plan); + VFRange &Range, VPBasicBlock *VPBB); - /// Set the recipe created for given ingredient. This operation is a no-op for - /// ingredients that were not marked using a nullptr entry in the map. + /// Set the recipe created for given ingredient. void setRecipe(Instruction *I, VPRecipeBase *R) { - if (!Ingredient2Recipe.count(I)) - return; - assert(Ingredient2Recipe[I] == nullptr && - "Recipe already set for ingredient"); + assert(!Ingredient2Recipe.contains(I) && + "Cannot reset recipe for instruction."); Ingredient2Recipe[I] = R; } /// Create the mask for the vector loop header block. - void createHeaderMask(VPlan &Plan); + void createHeaderMask(); /// A helper function that computes the predicate of the block BB, assuming /// that the header block of the loop is set to True or the loop mask when /// tail folding. - void createBlockInMask(BasicBlock *BB, VPlan &Plan); + void createBlockInMask(BasicBlock *BB); /// Returns the *entry* mask for the block \p BB. VPValue *getBlockInMask(BasicBlock *BB) const; /// A helper function that computes the predicate of the edge between SRC /// and DST. - VPValue *createEdgeMask(BasicBlock *Src, BasicBlock *Dst, VPlan &Plan); + VPValue *createEdgeMask(BasicBlock *Src, BasicBlock *Dst); /// A helper that returns the previously computed predicate of the edge /// between SRC and DST. VPValue *getEdgeMask(BasicBlock *Src, BasicBlock *Dst) const; - /// Mark given ingredient for recording its recipe once one is created for - /// it. - void recordRecipeOf(Instruction *I) { - assert((!Ingredient2Recipe.count(I) || Ingredient2Recipe[I] == nullptr) && - "Recipe already set for ingredient"); - Ingredient2Recipe[I] = nullptr; - } - /// Return the recipe created for given ingredient. VPRecipeBase *getRecipe(Instruction *I) { assert(Ingredient2Recipe.count(I) && @@ -166,12 +154,24 @@ public: /// Build a VPReplicationRecipe for \p I. If it is predicated, add the mask as /// last operand. Range.End may be decreased to ensure same recipe behavior /// from \p Range.Start to \p Range.End. - VPReplicateRecipe *handleReplication(Instruction *I, VFRange &Range, - VPlan &Plan); + VPReplicateRecipe *handleReplication(Instruction *I, VFRange &Range); /// Add the incoming values from the backedge to reduction & first-order /// recurrence cross-iteration phis. void fixHeaderPhis(); + + /// Returns a range mapping the values of the range \p Operands to their + /// corresponding VPValues. + iterator_range<mapped_iterator<Use *, std::function<VPValue *(Value *)>>> + mapToVPValues(User::op_range Operands); + + VPValue *getVPValueOrAddLiveIn(Value *V, VPlan &Plan) { + if (auto *I = dyn_cast<Instruction>(V)) { + if (auto *R = Ingredient2Recipe.lookup(I)) + return R->getVPSingleValue(); + } + return Plan.getOrAddLiveIn(V); + } }; } // end namespace llvm diff --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp index 9768e4b7aa0a8ac7e73a89e87c0b79ed36c74bb9..9a8f53c8dbe441d7026d835b640f656daef315cd 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp @@ -812,7 +812,7 @@ void VPlan::prepareToExecute(Value *TripCountV, Value *VectorTripCountV, // needs to be changed from zero to the value after the main vector loop. // FIXME: Improve modeling for canonical IV start values in the epilogue loop. if (CanonicalIVStartValue) { - VPValue *VPV = getVPValueOrAddLiveIn(CanonicalIVStartValue); + VPValue *VPV = getOrAddLiveIn(CanonicalIVStartValue); auto *IV = getCanonicalIV(); assert(all_of(IV->users(), [](const VPUser *U) { @@ -860,11 +860,8 @@ void VPlan::execute(VPTransformState *State) { Phi = cast<PHINode>(State->get(R.getVPSingleValue(), 0)); } else { auto *WidenPhi = cast<VPWidenPointerInductionRecipe>(&R); - // TODO: Split off the case that all users of a pointer phi are scalar - // from the VPWidenPointerInductionRecipe. - if (WidenPhi->onlyScalarsGenerated(State->VF.isScalable())) - continue; - + assert(!WidenPhi->onlyScalarsGenerated(State->VF.isScalable()) && + "recipe generating only scalars should have been replaced"); auto *GEP = cast<GetElementPtrInst>(State->get(WidenPhi, 0)); Phi = cast<PHINode>(GEP->getPointerOperand()); } @@ -1091,7 +1088,7 @@ VPlan *VPlan::duplicate() { DenseMap<VPValue *, VPValue *> Old2NewVPValues; for (VPValue *OldLiveIn : VPLiveInsToFree) { Old2NewVPValues[OldLiveIn] = - NewPlan->getVPValueOrAddLiveIn(OldLiveIn->getLiveInIRValue()); + NewPlan->getOrAddLiveIn(OldLiveIn->getLiveInIRValue()); } Old2NewVPValues[&VectorTripCount] = &NewPlan->VectorTripCount; Old2NewVPValues[&VFxUF] = &NewPlan->VFxUF; @@ -1102,7 +1099,7 @@ VPlan *VPlan::duplicate() { assert(TripCount && "trip count must be set"); if (TripCount->isLiveIn()) Old2NewVPValues[TripCount] = - NewPlan->getVPValueOrAddLiveIn(TripCount->getLiveInIRValue()); + NewPlan->getOrAddLiveIn(TripCount->getLiveInIRValue()); // else NewTripCount will be created and inserted into Old2NewVPValues when // TripCount is cloned. In any case NewPlan->TripCount is updated below. @@ -1425,9 +1422,9 @@ VPValue *vputils::getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr, return Expanded; VPValue *Expanded = nullptr; if (auto *E = dyn_cast<SCEVConstant>(Expr)) - Expanded = Plan.getVPValueOrAddLiveIn(E->getValue()); + Expanded = Plan.getOrAddLiveIn(E->getValue()); else if (auto *E = dyn_cast<SCEVUnknown>(Expr)) - Expanded = Plan.getVPValueOrAddLiveIn(E->getValue()); + Expanded = Plan.getOrAddLiveIn(E->getValue()); else { Expanded = new VPExpandSCEVRecipe(Expr, SE); Plan.getPreheader()->appendRecipe(Expanded->getDefiningRecipe()); diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h index af6d0081bffebc4c59d0543725b0455e1747d79e..707a826ecdc25684a4066e981933a1eae034cba5 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -913,6 +913,11 @@ public: WrapFlagsTy(bool HasNUW, bool HasNSW) : HasNUW(HasNUW), HasNSW(HasNSW) {} }; + struct DisjointFlagsTy { + char IsDisjoint : 1; + DisjointFlagsTy(bool IsDisjoint) : IsDisjoint(IsDisjoint) {} + }; + protected: struct GEPFlagsTy { char IsInBounds : 1; @@ -920,9 +925,6 @@ protected: }; private: - struct DisjointFlagsTy { - char IsDisjoint : 1; - }; struct ExactFlagsTy { char IsExact : 1; }; @@ -1016,6 +1018,12 @@ public: : VPSingleDefRecipe(SC, Operands, DL), OpType(OperationType::FPMathOp), FMFs(FMFs) {} + template <typename IterT> + VPRecipeWithIRFlags(const unsigned char SC, IterT Operands, + DisjointFlagsTy DisjointFlags, DebugLoc DL = {}) + : VPSingleDefRecipe(SC, Operands, DL), OpType(OperationType::DisjointOp), + DisjointFlags(DisjointFlags) {} + protected: template <typename IterT> VPRecipeWithIRFlags(const unsigned char SC, IterT Operands, @@ -1127,6 +1135,12 @@ public: return WrapFlags.HasNSW; } + bool isDisjoint() const { + assert(OpType == OperationType::DisjointOp && + "recipe cannot have a disjoing flag"); + return DisjointFlags.IsDisjoint; + } + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void printFlags(raw_ostream &O) const; #endif @@ -1155,6 +1169,10 @@ public: BranchOnCount, BranchOnCond, ComputeReductionResult, + // Add an offset in bytes (second operand) to a base pointer (first + // operand). Only generates scalar values (either for the first lane only or + // for all lanes, depending on its uses). + PtrAdd, }; private: @@ -1164,11 +1182,28 @@ private: /// An optional name that can be used for the generated IR instruction. const std::string Name; - /// Utility method serving execute(): generates a single instance of the - /// modeled instruction. \returns the generated value for \p Part. - /// In some cases an existing value is returned rather than a generated + /// Returns true if this VPInstruction generates scalar values for all lanes. + /// Most VPInstructions generate a single value per part, either vector or + /// scalar. VPReplicateRecipe takes care of generating multiple (scalar) + /// values per all lanes, stemming from an original ingredient. This method + /// identifies the (rare) cases of VPInstructions that do so as well, w/o an + /// underlying ingredient. + bool doesGeneratePerAllLanes() const; + + /// Returns true if we can generate a scalar for the first lane only if + /// needed. + bool canGenerateScalarForFirstLane() const; + + /// Utility methods serving execute(): generates a single instance of the + /// modeled instruction for a given part. \returns the generated value for \p + /// Part. In some cases an existing value is returned rather than a generated /// one. - Value *generateInstruction(VPTransformState &State, unsigned Part); + Value *generatePerPart(VPTransformState &State, unsigned Part); + + /// Utility methods serving execute(): generates a scalar single instance of + /// the modeled instruction for a given lane. \returns the scalar generated + /// value for lane \p Lane. + Value *generatePerLane(VPTransformState &State, const VPIteration &Lane); #if !defined(NDEBUG) /// Return true if the VPInstruction is a floating point math operation, i.e. @@ -1194,6 +1229,14 @@ public: : VPRecipeWithIRFlags(VPDef::VPInstructionSC, Operands, WrapFlags, DL), Opcode(Opcode), Name(Name.str()) {} + VPInstruction(unsigned Opcode, std::initializer_list<VPValue *> Operands, + DisjointFlagsTy DisjointFlag, DebugLoc DL = {}, + const Twine &Name = "") + : VPRecipeWithIRFlags(VPDef::VPInstructionSC, Operands, DisjointFlag, DL), + Opcode(Opcode), Name(Name.str()) { + assert(Opcode == Instruction::Or && "only OR opcodes can be disjoint"); + } + VPInstruction(unsigned Opcode, std::initializer_list<VPValue *> Operands, FastMathFlags FMFs, DebugLoc DL = {}, const Twine &Name = ""); @@ -1265,6 +1308,7 @@ public: default: return false; case VPInstruction::BranchOnCount: + case VPInstruction::CanonicalIVIncrementForPart: return true; }; llvm_unreachable("switch should return"); @@ -2136,6 +2180,8 @@ public: assert(isPredicated() && "Trying to get the mask of a unpredicated recipe"); return getOperand(getNumOperands() - 1); } + + unsigned getOpcode() const { return getUnderlyingInstr()->getOpcode(); } }; /// A recipe for generating conditional branches on the bits of a mask. @@ -2248,8 +2294,8 @@ class VPWidenMemoryInstructionRecipe : public VPRecipeBase { public: VPWidenMemoryInstructionRecipe(LoadInst &Load, VPValue *Addr, VPValue *Mask, - bool Consecutive, bool Reverse) - : VPRecipeBase(VPDef::VPWidenMemoryInstructionSC, {Addr}), + bool Consecutive, bool Reverse, DebugLoc DL) + : VPRecipeBase(VPDef::VPWidenMemoryInstructionSC, {Addr}, DL), Ingredient(Load), Consecutive(Consecutive), Reverse(Reverse) { assert((Consecutive || !Reverse) && "Reverse implies consecutive"); new VPValue(this, &Load); @@ -2258,8 +2304,9 @@ public: VPWidenMemoryInstructionRecipe(StoreInst &Store, VPValue *Addr, VPValue *StoredValue, VPValue *Mask, - bool Consecutive, bool Reverse) - : VPRecipeBase(VPDef::VPWidenMemoryInstructionSC, {Addr, StoredValue}), + bool Consecutive, bool Reverse, DebugLoc DL) + : VPRecipeBase(VPDef::VPWidenMemoryInstructionSC, {Addr, StoredValue}, + DL), Ingredient(Store), Consecutive(Consecutive), Reverse(Reverse) { assert((Consecutive || !Reverse) && "Reverse implies consecutive"); setMask(Mask); @@ -2269,10 +2316,11 @@ public: if (isStore()) return new VPWidenMemoryInstructionRecipe( cast<StoreInst>(Ingredient), getAddr(), getStoredValue(), getMask(), - Consecutive, Reverse); + Consecutive, Reverse, getDebugLoc()); - return new VPWidenMemoryInstructionRecipe( - cast<LoadInst>(Ingredient), getAddr(), getMask(), Consecutive, Reverse); + return new VPWidenMemoryInstructionRecipe(cast<LoadInst>(Ingredient), + getAddr(), getMask(), Consecutive, + Reverse, getDebugLoc()); } VP_CLASSOF_IMPL(VPDef::VPWidenMemoryInstructionSC) @@ -2488,12 +2536,6 @@ class VPDerivedIVRecipe : public VPSingleDefRecipe { /// for floating point inductions. const FPMathOperator *FPBinOp; - VPDerivedIVRecipe(InductionDescriptor::InductionKind Kind, - const FPMathOperator *FPBinOp, VPValue *Start, - VPCanonicalIVPHIRecipe *CanonicalIV, VPValue *Step) - : VPSingleDefRecipe(VPDef::VPDerivedIVSC, {Start, CanonicalIV, Step}), - Kind(Kind), FPBinOp(FPBinOp) {} - public: VPDerivedIVRecipe(const InductionDescriptor &IndDesc, VPValue *Start, VPCanonicalIVPHIRecipe *CanonicalIV, VPValue *Step) @@ -2502,6 +2544,12 @@ public: dyn_cast_or_null<FPMathOperator>(IndDesc.getInductionBinOp()), Start, CanonicalIV, Step) {} + VPDerivedIVRecipe(InductionDescriptor::InductionKind Kind, + const FPMathOperator *FPBinOp, VPValue *Start, + VPCanonicalIVPHIRecipe *CanonicalIV, VPValue *Step) + : VPSingleDefRecipe(VPDef::VPDerivedIVSC, {Start, CanonicalIV, Step}), + Kind(Kind), FPBinOp(FPBinOp) {} + ~VPDerivedIVRecipe() override = default; VPRecipeBase *clone() override { @@ -2870,10 +2918,6 @@ class VPlan { /// definitions are VPValues that hold a pointer to their underlying IR. SmallVector<VPValue *, 16> VPLiveInsToFree; - /// Indicates whether it is safe use the Value2VPValue mapping or if the - /// mapping cannot be used any longer, because it is stale. - bool Value2VPValueEnabled = true; - /// Values used outside the plan. MapVector<PHINode *, VPLiveOut *> LiveOuts; @@ -2952,10 +2996,6 @@ public: /// Returns VF * UF of the vector loop region. VPValue &getVFxUF() { return VFxUF; } - /// Mark the plan to indicate that using Value2VPValue is not safe any - /// longer, because it may be stale. - void disableValue2VPValue() { Value2VPValueEnabled = false; } - void addVF(ElementCount VF) { VFs.insert(VF); } void setVF(ElementCount VF) { @@ -2984,34 +3024,22 @@ public: void setName(const Twine &newName) { Name = newName.str(); } - void addVPValue(Value *V, VPValue *VPV) { - assert((Value2VPValueEnabled || VPV->isLiveIn()) && - "Value2VPValue mapping may be out of date!"); - assert(V && "Trying to add a null Value to VPlan"); - assert(!Value2VPValue.count(V) && "Value already exists in VPlan"); - Value2VPValue[V] = VPV; - } - - /// Returns the VPValue for \p V. - VPValue *getVPValue(Value *V) { - assert(V && "Trying to get the VPValue of a null Value"); - assert(Value2VPValue.count(V) && "Value does not exist in VPlan"); - assert((Value2VPValueEnabled || Value2VPValue[V]->isLiveIn()) && - "Value2VPValue mapping may be out of date!"); - return Value2VPValue[V]; - } - - /// Gets the VPValue for \p V or adds a new live-in (if none exists yet) for - /// \p V. - VPValue *getVPValueOrAddLiveIn(Value *V) { + /// Gets the live-in VPValue for \p V or adds a new live-in (if none exists + /// yet) for \p V. + VPValue *getOrAddLiveIn(Value *V) { assert(V && "Trying to get or add the VPValue of a null Value"); if (!Value2VPValue.count(V)) { VPValue *VPV = new VPValue(V); VPLiveInsToFree.push_back(VPV); - addVPValue(V, VPV); + assert(VPV->isLiveIn() && "VPV must be a live-in."); + assert(!Value2VPValue.count(V) && "Value already exists in VPlan"); + Value2VPValue[V] = VPV; } - return getVPValue(V); + assert(Value2VPValue.count(V) && "Value does not exist in VPlan"); + assert(Value2VPValue[V]->isLiveIn() && + "Only live-ins should be in mapping"); + return Value2VPValue[V]; } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) @@ -3028,16 +3056,6 @@ public: LLVM_DUMP_METHOD void dump() const; #endif - /// Returns a range mapping the values the range \p Operands to their - /// corresponding VPValues. - iterator_range<mapped_iterator<Use *, std::function<VPValue *(Value *)>>> - mapToVPValues(User::op_range Operands) { - std::function<VPValue *(Value *)> Fn = [this](Value *Op) { - return getVPValueOrAddLiveIn(Op); - }; - return map_range(Operands, Fn); - } - /// Returns the VPRegionBlock of the vector loop. VPRegionBlock *getVectorLoopRegion() { return cast<VPRegionBlock>(getEntry()->getSingleSuccessor()); diff --git a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp index f55beac2047c94e326ba3706c3897157adc0857c..04e30312dc23a7c2f4d52620881d80b9846f0fe7 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp @@ -44,6 +44,9 @@ Type *VPTypeAnalysis::inferScalarTypeForRecipe(const VPInstruction *R) { CachedTypes[OtherV] = ResTy; return ResTy; } + case VPInstruction::PtrAdd: + // Return the type based on the pointer argument (i.e. first operand). + return inferScalarType(R->getOperand(0)); default: break; } diff --git a/llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp b/llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp index 6474a9697dce893df68d5c11e3c5936aeb44d7e7..b57ff2840a72921aa7d38c2f23527fb1a49f0f82 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp @@ -272,7 +272,7 @@ VPValue *PlainCFGBuilder::getOrCreateVPOperand(Value *IRVal) { // A and B: Create VPValue and add it to the pool of external definitions and // to the Value->VPValue map. - VPValue *NewVPVal = Plan.getVPValueOrAddLiveIn(IRVal); + VPValue *NewVPVal = Plan.getOrAddLiveIn(IRVal); IRDef2VPValue[IRVal] = NewVPVal; return NewVPVal; } @@ -296,8 +296,7 @@ void PlainCFGBuilder::createVPInstructionsForVPBB(VPBasicBlock *VPBB, // recipes. if (Br->isConditional()) { VPValue *Cond = getOrCreateVPOperand(Br->getCondition()); - VPBB->appendRecipe( - new VPInstruction(VPInstruction::BranchOnCond, {Cond})); + VPIRBuilder.createNaryOp(VPInstruction::BranchOnCond, {Cond}, Inst); } // Skip the rest of the Instruction processing for Branch instructions. @@ -362,7 +361,7 @@ void PlainCFGBuilder::buildPlainCFG() { for (auto &I : *ThePreheaderBB) { if (I.getType()->isVoidTy()) continue; - IRDef2VPValue[&I] = Plan.getVPValueOrAddLiveIn(&I); + IRDef2VPValue[&I] = Plan.getOrAddLiveIn(&I); } LoopBlocksRPO RPO(TheLoop); diff --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h index b90c588b6075642daa4cf3124f92633beaf80fa1..a03a408686ef13d5e7798681e31e4e97491f76c7 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h +++ b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h @@ -50,13 +50,82 @@ template <typename Class> struct bind_ty { } }; +/// Match a specified integer value or vector of all elements of that +/// value. +struct specific_intval { + APInt Val; + + specific_intval(APInt V) : Val(std::move(V)) {} + + bool match(VPValue *VPV) { + if (!VPV->isLiveIn()) + return false; + Value *V = VPV->getLiveInIRValue(); + const auto *CI = dyn_cast<ConstantInt>(V); + if (!CI && V->getType()->isVectorTy()) + if (const auto *C = dyn_cast<Constant>(V)) + CI = dyn_cast_or_null<ConstantInt>( + C->getSplatValue(/*UndefsAllowed=*/false)); + + return CI && APInt::isSameValue(CI->getValue(), Val); + } +}; + +inline specific_intval m_SpecificInt(uint64_t V) { + return specific_intval(APInt(64, V)); +} + +/// Matching combinators +template <typename LTy, typename RTy> struct match_combine_or { + LTy L; + RTy R; + + match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) {} + + template <typename ITy> bool match(ITy *V) { + if (L.match(V)) + return true; + if (R.match(V)) + return true; + return false; + } +}; + +template <typename LTy, typename RTy> +inline match_combine_or<LTy, RTy> m_CombineOr(const LTy &L, const RTy &R) { + return match_combine_or<LTy, RTy>(L, R); +} + /// Match a VPValue, capturing it if we match. inline bind_ty<VPValue> m_VPValue(VPValue *&V) { return V; } -template <typename Op0_t, unsigned Opcode> struct UnaryVPInstruction_match { +namespace detail { + +/// A helper to match an opcode against multiple recipe types. +template <unsigned Opcode, typename...> struct MatchRecipeAndOpcode {}; + +template <unsigned Opcode, typename RecipeTy> +struct MatchRecipeAndOpcode<Opcode, RecipeTy> { + static bool match(const VPRecipeBase *R) { + auto *DefR = dyn_cast<RecipeTy>(R); + return DefR && DefR->getOpcode() == Opcode; + } +}; + +template <unsigned Opcode, typename RecipeTy, typename... RecipeTys> +struct MatchRecipeAndOpcode<Opcode, RecipeTy, RecipeTys...> { + static bool match(const VPRecipeBase *R) { + return MatchRecipeAndOpcode<Opcode, RecipeTy>::match(R) || + MatchRecipeAndOpcode<Opcode, RecipeTys...>::match(R); + } +}; +} // namespace detail + +template <typename Op0_t, unsigned Opcode, typename... RecipeTys> +struct UnaryRecipe_match { Op0_t Op0; - UnaryVPInstruction_match(Op0_t Op0) : Op0(Op0) {} + UnaryRecipe_match(Op0_t Op0) : Op0(Op0) {} bool match(const VPValue *V) { auto *DefR = V->getDefiningRecipe(); @@ -64,37 +133,58 @@ template <typename Op0_t, unsigned Opcode> struct UnaryVPInstruction_match { } bool match(const VPRecipeBase *R) { - auto *DefR = dyn_cast<VPInstruction>(R); - if (!DefR || DefR->getOpcode() != Opcode) + if (!detail::MatchRecipeAndOpcode<Opcode, RecipeTys...>::match(R)) return false; - assert(DefR->getNumOperands() == 1 && + assert(R->getNumOperands() == 1 && "recipe with matched opcode does not have 1 operands"); - return Op0.match(DefR->getOperand(0)); + return Op0.match(R->getOperand(0)); } }; -template <typename Op0_t, typename Op1_t, unsigned Opcode> -struct BinaryVPInstruction_match { +template <typename Op0_t, unsigned Opcode> +using UnaryVPInstruction_match = + UnaryRecipe_match<Op0_t, Opcode, VPInstruction>; + +template <typename Op0_t, unsigned Opcode> +using AllUnaryRecipe_match = + UnaryRecipe_match<Op0_t, Opcode, VPWidenRecipe, VPReplicateRecipe, + VPWidenCastRecipe, VPInstruction>; + +template <typename Op0_t, typename Op1_t, unsigned Opcode, + typename... RecipeTys> +struct BinaryRecipe_match { Op0_t Op0; Op1_t Op1; - BinaryVPInstruction_match(Op0_t Op0, Op1_t Op1) : Op0(Op0), Op1(Op1) {} + BinaryRecipe_match(Op0_t Op0, Op1_t Op1) : Op0(Op0), Op1(Op1) {} bool match(const VPValue *V) { auto *DefR = V->getDefiningRecipe(); return DefR && match(DefR); } + bool match(const VPSingleDefRecipe *R) { + return match(static_cast<const VPRecipeBase *>(R)); + } + bool match(const VPRecipeBase *R) { - auto *DefR = dyn_cast<VPInstruction>(R); - if (!DefR || DefR->getOpcode() != Opcode) + if (!detail::MatchRecipeAndOpcode<Opcode, RecipeTys...>::match(R)) return false; - assert(DefR->getNumOperands() == 2 && + assert(R->getNumOperands() == 2 && "recipe with matched opcode does not have 2 operands"); - return Op0.match(DefR->getOperand(0)) && Op1.match(DefR->getOperand(1)); + return Op0.match(R->getOperand(0)) && Op1.match(R->getOperand(1)); } }; +template <typename Op0_t, typename Op1_t, unsigned Opcode> +using BinaryVPInstruction_match = + BinaryRecipe_match<Op0_t, Op1_t, Opcode, VPInstruction>; + +template <typename Op0_t, typename Op1_t, unsigned Opcode> +using AllBinaryRecipe_match = + BinaryRecipe_match<Op0_t, Op1_t, Opcode, VPWidenRecipe, VPReplicateRecipe, + VPWidenCastRecipe, VPInstruction>; + template <unsigned Opcode, typename Op0_t> inline UnaryVPInstruction_match<Op0_t, Opcode> m_VPInstruction(const Op0_t &Op0) { @@ -130,6 +220,52 @@ inline BinaryVPInstruction_match<Op0_t, Op1_t, VPInstruction::BranchOnCount> m_BranchOnCount(const Op0_t &Op0, const Op1_t &Op1) { return m_VPInstruction<VPInstruction::BranchOnCount>(Op0, Op1); } + +template <unsigned Opcode, typename Op0_t> +inline AllUnaryRecipe_match<Op0_t, Opcode> m_Unary(const Op0_t &Op0) { + return AllUnaryRecipe_match<Op0_t, Opcode>(Op0); +} + +template <typename Op0_t> +inline AllUnaryRecipe_match<Op0_t, Instruction::Trunc> +m_Trunc(const Op0_t &Op0) { + return m_Unary<Instruction::Trunc, Op0_t>(Op0); +} + +template <typename Op0_t> +inline AllUnaryRecipe_match<Op0_t, Instruction::ZExt> m_ZExt(const Op0_t &Op0) { + return m_Unary<Instruction::ZExt, Op0_t>(Op0); +} + +template <typename Op0_t> +inline AllUnaryRecipe_match<Op0_t, Instruction::SExt> m_SExt(const Op0_t &Op0) { + return m_Unary<Instruction::SExt, Op0_t>(Op0); +} + +template <typename Op0_t> +inline match_combine_or<AllUnaryRecipe_match<Op0_t, Instruction::ZExt>, + AllUnaryRecipe_match<Op0_t, Instruction::SExt>> +m_ZExtOrSExt(const Op0_t &Op0) { + return m_CombineOr(m_ZExt(Op0), m_SExt(Op0)); +} + +template <unsigned Opcode, typename Op0_t, typename Op1_t> +inline AllBinaryRecipe_match<Op0_t, Op1_t, Opcode> m_Binary(const Op0_t &Op0, + const Op1_t &Op1) { + return AllBinaryRecipe_match<Op0_t, Op1_t, Opcode>(Op0, Op1); +} + +template <typename Op0_t, typename Op1_t> +inline AllBinaryRecipe_match<Op0_t, Op1_t, Instruction::Mul> +m_Mul(const Op0_t &Op0, const Op1_t &Op1) { + return m_Binary<Instruction::Mul, Op0_t, Op1_t>(Op0, Op1); +} + +template <typename Op0_t, typename Op1_t> +inline AllBinaryRecipe_match<Op0_t, Op1_t, Instruction::Or> +m_Or(const Op0_t &Op0, const Op1_t &Op1) { + return m_Binary<Instruction::Or, Op0_t, Op1_t>(Op0, Op1); +} } // namespace VPlanPatternMatch } // namespace llvm diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp index d75e322a74cfa639bc16319fecb03c5fbf801150..124ae3108d8a0702c577109419fe0bb2f1b2dd3e 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp @@ -127,6 +127,7 @@ bool VPRecipeBase::mayHaveSideEffects() const { case VPInstruction::Not: case VPInstruction::CalculateTripCountMinusVF: case VPInstruction::CanonicalIVIncrementForPart: + case VPInstruction::PtrAdd: return false; default: return true; @@ -270,10 +271,39 @@ VPInstruction::VPInstruction(unsigned Opcode, assert(isFPMathOp() && "this op can't take fast-math flags"); } -Value *VPInstruction::generateInstruction(VPTransformState &State, - unsigned Part) { +bool VPInstruction::doesGeneratePerAllLanes() const { + return Opcode == VPInstruction::PtrAdd && !vputils::onlyFirstLaneUsed(this); +} + +bool VPInstruction::canGenerateScalarForFirstLane() const { + if (Instruction::isBinaryOp(getOpcode())) + return true; + + switch (Opcode) { + case VPInstruction::BranchOnCond: + case VPInstruction::BranchOnCount: + case VPInstruction::CalculateTripCountMinusVF: + case VPInstruction::CanonicalIVIncrementForPart: + case VPInstruction::ComputeReductionResult: + case VPInstruction::PtrAdd: + return true; + default: + return false; + } +} + +Value *VPInstruction::generatePerLane(VPTransformState &State, + const VPIteration &Lane) { + IRBuilderBase &Builder = State.Builder; + + assert(getOpcode() == VPInstruction::PtrAdd && + "only PtrAdd opcodes are supported for now"); + return Builder.CreatePtrAdd(State.get(getOperand(0), Lane), + State.get(getOperand(1), Lane), Name); +} + +Value *VPInstruction::generatePerPart(VPTransformState &State, unsigned Part) { IRBuilderBase &Builder = State.Builder; - Builder.SetCurrentDebugLocation(getDebugLoc()); if (Instruction::isBinaryOp(getOpcode())) { bool OnlyFirstLaneUsed = vputils::onlyFirstLaneUsed(this); @@ -345,6 +375,9 @@ Value *VPInstruction::generateInstruction(VPTransformState &State, return Builder.CreateVectorSplice(PartMinus1, V2, -1, Name); } case VPInstruction::CalculateTripCountMinusVF: { + if (Part != 0) + return State.get(this, 0, /*IsScalar*/ true); + Value *ScalarTC = State.get(getOperand(0), {0, 0}); Value *Step = createStepForVF(Builder, ScalarTC->getType(), State.VF, State.UF); @@ -422,8 +455,6 @@ Value *VPInstruction::generateInstruction(VPTransformState &State, RecurKind RK = RdxDesc.getRecurrenceKind(); - State.setDebugLocFrom(getDebugLoc()); - VPValue *LoopExitingDef = getOperand(1); Type *PhiTy = OrigPhi->getType(); VectorParts RdxParts(State.UF); @@ -487,6 +518,13 @@ Value *VPInstruction::generateInstruction(VPTransformState &State, return ReducedPartRdx; } + case VPInstruction::PtrAdd: { + assert(vputils::onlyFirstLaneUsed(this) && + "can only generate first lane for PtrAdd"); + Value *Ptr = State.get(getOperand(0), Part, /* IsScalar */ true); + Value *Addend = State.get(getOperand(1), Part, /* IsScalar */ true); + return Builder.CreatePtrAdd(Ptr, Addend, Name); + } default: llvm_unreachable("Unsupported opcode for instruction"); } @@ -511,17 +549,33 @@ void VPInstruction::execute(VPTransformState &State) { "Recipe not a FPMathOp but has fast-math flags?"); if (hasFastMathFlags()) State.Builder.setFastMathFlags(getFastMathFlags()); + State.setDebugLocFrom(getDebugLoc()); + bool GeneratesPerFirstLaneOnly = + canGenerateScalarForFirstLane() && + (vputils::onlyFirstLaneUsed(this) || + getOpcode() == VPInstruction::ComputeReductionResult); + bool GeneratesPerAllLanes = doesGeneratePerAllLanes(); for (unsigned Part = 0; Part < State.UF; ++Part) { - Value *GeneratedValue = generateInstruction(State, Part); - if (!hasResult()) + if (GeneratesPerAllLanes) { + for (unsigned Lane = 0, NumLanes = State.VF.getKnownMinValue(); + Lane != NumLanes; ++Lane) { + Value *GeneratedValue = generatePerLane(State, VPIteration(Part, Lane)); + assert(GeneratedValue && "generatePerLane must produce a value"); + State.set(this, GeneratedValue, VPIteration(Part, Lane)); + } continue; - assert(GeneratedValue && "generateInstruction must produce a value"); + } - bool IsVector = GeneratedValue->getType()->isVectorTy(); - State.set(this, GeneratedValue, Part, !IsVector); - assert((IsVector || getOpcode() == VPInstruction::ComputeReductionResult || - State.VF.isScalar() || vputils::onlyFirstLaneUsed(this)) && - "scalar value but not only first lane used"); + Value *GeneratedValue = generatePerPart(State, Part); + if (!hasResult()) + continue; + assert(GeneratedValue && "generatePerPart must produce a value"); + assert((GeneratedValue->getType()->isVectorTy() == + !GeneratesPerFirstLaneOnly || + State.VF.isScalar()) && + "scalar value but not only first lane defined"); + State.set(this, GeneratedValue, Part, + /*IsScalar*/ GeneratesPerFirstLaneOnly); } } @@ -534,6 +588,7 @@ bool VPInstruction::onlyFirstLaneUsed(const VPValue *Op) const { default: return false; case Instruction::ICmp: + case VPInstruction::PtrAdd: // TODO: Cover additional opcodes. return vputils::onlyFirstLaneUsed(this); case VPInstruction::ActiveLaneMask: @@ -591,6 +646,9 @@ void VPInstruction::print(raw_ostream &O, const Twine &Indent, case VPInstruction::ComputeReductionResult: O << "compute-reduction-result"; break; + case VPInstruction::PtrAdd: + O << "ptradd"; + break; default: O << Instruction::getOpcodeName(getOpcode()); } diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp index f6b564ad931ca9e66e1ded64630a76691ffbf179..957c97cdea5d02dcff14fc74e286335810677cb4 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp @@ -48,15 +48,14 @@ void VPlanTransforms::VPInstructionsToVPRecipes( VPRecipeBase *NewRecipe = nullptr; if (auto *VPPhi = dyn_cast<VPWidenPHIRecipe>(&Ingredient)) { auto *Phi = cast<PHINode>(VPPhi->getUnderlyingValue()); - if (const auto *II = GetIntOrFpInductionDescriptor(Phi)) { - VPValue *Start = Plan->getVPValueOrAddLiveIn(II->getStartValue()); - VPValue *Step = - vputils::getOrCreateVPValueForSCEVExpr(*Plan, II->getStep(), SE); - NewRecipe = new VPWidenIntOrFpInductionRecipe(Phi, Start, Step, *II); - } else { - Plan->addVPValue(Phi, VPPhi); + const auto *II = GetIntOrFpInductionDescriptor(Phi); + if (!II) continue; - } + + VPValue *Start = Plan->getOrAddLiveIn(II->getStartValue()); + VPValue *Step = + vputils::getOrCreateVPValueForSCEVExpr(*Plan, II->getStep(), SE); + NewRecipe = new VPWidenIntOrFpInductionRecipe(Phi, Start, Step, *II); } else { assert(isa<VPInstruction>(&Ingredient) && "only VPInstructions expected here"); @@ -65,11 +64,13 @@ void VPlanTransforms::VPInstructionsToVPRecipes( if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) { NewRecipe = new VPWidenMemoryInstructionRecipe( *Load, Ingredient.getOperand(0), nullptr /*Mask*/, - false /*Consecutive*/, false /*Reverse*/); + false /*Consecutive*/, false /*Reverse*/, + Ingredient.getDebugLoc()); } else if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) { NewRecipe = new VPWidenMemoryInstructionRecipe( *Store, Ingredient.getOperand(1), Ingredient.getOperand(0), - nullptr /*Mask*/, false /*Consecutive*/, false /*Reverse*/); + nullptr /*Mask*/, false /*Consecutive*/, false /*Reverse*/, + Ingredient.getDebugLoc()); } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Inst)) { NewRecipe = new VPWidenGEPRecipe(GEP, Ingredient.operands()); } else if (CallInst *CI = dyn_cast<CallInst>(Inst)) { @@ -156,8 +157,7 @@ static bool sinkScalarOperands(VPlan &Plan) { if (NeedsDuplicating) { if (ScalarVFOnly) continue; - Instruction *I = cast<Instruction>( - cast<VPReplicateRecipe>(SinkCandidate)->getUnderlyingValue()); + Instruction *I = SinkCandidate->getUnderlyingInstr(); auto *Clone = new VPReplicateRecipe(I, SinkCandidate->operands(), true); // TODO: add ".cloned" suffix to name of Clone's VPValue. @@ -500,15 +500,18 @@ static void removeDeadRecipes(VPlan &Plan) { } } -static VPValue *createScalarIVSteps(VPlan &Plan, const InductionDescriptor &ID, +static VPValue *createScalarIVSteps(VPlan &Plan, + InductionDescriptor::InductionKind Kind, + Instruction::BinaryOps InductionOpcode, + FPMathOperator *FPBinOp, ScalarEvolution &SE, Instruction *TruncI, VPValue *StartV, VPValue *Step, VPBasicBlock::iterator IP) { VPBasicBlock *HeaderVPBB = Plan.getVectorLoopRegion()->getEntryBasicBlock(); VPCanonicalIVPHIRecipe *CanonicalIV = Plan.getCanonicalIV(); VPSingleDefRecipe *BaseIV = CanonicalIV; - if (!CanonicalIV->isCanonical(ID.getKind(), StartV, Step)) { - BaseIV = new VPDerivedIVRecipe(ID, StartV, CanonicalIV, Step); + if (!CanonicalIV->isCanonical(Kind, StartV, Step)) { + BaseIV = new VPDerivedIVRecipe(Kind, FPBinOp, StartV, CanonicalIV, Step); HeaderVPBB->insert(BaseIV, IP); } @@ -538,21 +541,56 @@ static VPValue *createScalarIVSteps(VPlan &Plan, const InductionDescriptor &ID, VecPreheader->appendRecipe(Step->getDefiningRecipe()); } - VPScalarIVStepsRecipe *Steps = new VPScalarIVStepsRecipe(ID, BaseIV, Step); + VPScalarIVStepsRecipe *Steps = new VPScalarIVStepsRecipe( + BaseIV, Step, InductionOpcode, + FPBinOp ? FPBinOp->getFastMathFlags() : FastMathFlags()); HeaderVPBB->insert(Steps, IP); return Steps; } -/// If any user of a VPWidenIntOrFpInductionRecipe needs scalar values, -/// provide them by building scalar steps off of the canonical scalar IV and -/// update the original IV's users. This is an optional optimization to reduce -/// the needs of vector extracts. -static void optimizeInductions(VPlan &Plan, ScalarEvolution &SE) { +/// Legalize VPWidenPointerInductionRecipe, by replacing it with a PtrAdd +/// (IndStart, ScalarIVSteps (0, Step)) if only its scalar values are used, as +/// VPWidenPointerInductionRecipe will generate vectors only. If some users +/// require vectors while other require scalars, the scalar uses need to extract +/// the scalars from the generated vectors (Note that this is different to how +/// int/fp inductions are handled). Also optimize VPWidenIntOrFpInductionRecipe, +/// if any of its users needs scalar values, by providing them scalar steps +/// built on the canonical scalar IV and update the original IV's users. This is +/// an optional optimization to reduce the needs of vector extracts. +static void legalizeAndOptimizeInductions(VPlan &Plan, ScalarEvolution &SE) { SmallVector<VPRecipeBase *> ToRemove; VPBasicBlock *HeaderVPBB = Plan.getVectorLoopRegion()->getEntryBasicBlock(); bool HasOnlyVectorVFs = !Plan.hasVF(ElementCount::getFixed(1)); VPBasicBlock::iterator InsertPt = HeaderVPBB->getFirstNonPhi(); for (VPRecipeBase &Phi : HeaderVPBB->phis()) { + // Replace wide pointer inductions which have only their scalars used by + // PtrAdd(IndStart, ScalarIVSteps (0, Step)). + if (auto *PtrIV = dyn_cast<VPWidenPointerInductionRecipe>(&Phi)) { + if (!PtrIV->onlyScalarsGenerated(Plan.hasScalableVF())) + continue; + + const InductionDescriptor &ID = PtrIV->getInductionDescriptor(); + VPValue *StartV = + Plan.getOrAddLiveIn(ConstantInt::get(ID.getStep()->getType(), 0)); + VPValue *StepV = PtrIV->getOperand(1); + VPRecipeBase *Steps = + createScalarIVSteps(Plan, InductionDescriptor::IK_IntInduction, + Instruction::Add, nullptr, SE, nullptr, StartV, + StepV, InsertPt) + ->getDefiningRecipe(); + + auto *Recipe = + new VPInstruction(VPInstruction::PtrAdd, + {PtrIV->getStartValue(), Steps->getVPSingleValue()}, + PtrIV->getDebugLoc(), "next.gep"); + + Recipe->insertAfter(Steps); + PtrIV->replaceAllUsesWith(Recipe); + continue; + } + + // Replace widened induction with scalar steps for users that only use + // scalars. auto *WideIV = dyn_cast<VPWidenIntOrFpInductionRecipe>(&Phi); if (!WideIV) continue; @@ -562,9 +600,11 @@ static void optimizeInductions(VPlan &Plan, ScalarEvolution &SE) { continue; const InductionDescriptor &ID = WideIV->getInductionDescriptor(); - VPValue *Steps = createScalarIVSteps(Plan, ID, SE, WideIV->getTruncInst(), - WideIV->getStartValue(), - WideIV->getStepValue(), InsertPt); + VPValue *Steps = createScalarIVSteps( + Plan, ID.getKind(), ID.getInductionOpcode(), + dyn_cast_or_null<FPMathOperator>(ID.getInductionBinOp()), SE, + WideIV->getTruncInst(), WideIV->getStartValue(), WideIV->getStepValue(), + InsertPt); // Update scalar users of IV to use Step instead. if (!HasOnlyVectorVFs) @@ -625,9 +665,9 @@ void VPlanTransforms::optimizeForVFAndUF(VPlan &Plan, ElementCount BestVF, return; LLVMContext &Ctx = SE.getContext(); - auto *BOC = new VPInstruction( - VPInstruction::BranchOnCond, - {Plan.getVPValueOrAddLiveIn(ConstantInt::getTrue(Ctx))}); + auto *BOC = + new VPInstruction(VPInstruction::BranchOnCond, + {Plan.getOrAddLiveIn(ConstantInt::getTrue(Ctx))}); Term->eraseFromParent(); ExitingVPBB->appendRecipe(BOC); Plan.setVF(BestVF); @@ -815,27 +855,6 @@ void VPlanTransforms::clearReductionWrapFlags(VPlan &Plan) { } } -/// Returns true is \p V is constant one. -static bool isConstantOne(VPValue *V) { - if (!V->isLiveIn()) - return false; - auto *C = dyn_cast<ConstantInt>(V->getLiveInIRValue()); - return C && C->isOne(); -} - -/// Returns the llvm::Instruction opcode for \p R. -static unsigned getOpcodeForRecipe(VPRecipeBase &R) { - if (auto *WidenR = dyn_cast<VPWidenRecipe>(&R)) - return WidenR->getUnderlyingInstr()->getOpcode(); - if (auto *WidenC = dyn_cast<VPWidenCastRecipe>(&R)) - return WidenC->getOpcode(); - if (auto *RepR = dyn_cast<VPReplicateRecipe>(&R)) - return RepR->getUnderlyingInstr()->getOpcode(); - if (auto *VPI = dyn_cast<VPInstruction>(&R)) - return VPI->getOpcode(); - return 0; -} - /// Try to simplify recipe \p R. static void simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) { // Try to remove redundant blend recipes. @@ -849,24 +868,9 @@ static void simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) { return; } - switch (getOpcodeForRecipe(R)) { - case Instruction::Mul: { - VPValue *A = R.getOperand(0); - VPValue *B = R.getOperand(1); - if (isConstantOne(A)) - return R.getVPSingleValue()->replaceAllUsesWith(B); - if (isConstantOne(B)) - return R.getVPSingleValue()->replaceAllUsesWith(A); - break; - } - case Instruction::Trunc: { - VPRecipeBase *Ext = R.getOperand(0)->getDefiningRecipe(); - if (!Ext) - break; - unsigned ExtOpcode = getOpcodeForRecipe(*Ext); - if (ExtOpcode != Instruction::ZExt && ExtOpcode != Instruction::SExt) - break; - VPValue *A = Ext->getOperand(0); + using namespace llvm::VPlanPatternMatch; + VPValue *A; + if (match(&R, m_Trunc(m_ZExtOrSExt(m_VPValue(A))))) { VPValue *Trunc = R.getVPSingleValue(); Type *TruncTy = TypeInfo.inferScalarType(Trunc); Type *ATy = TypeInfo.inferScalarType(A); @@ -875,8 +879,12 @@ static void simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) { } else { // Don't replace a scalarizing recipe with a widened cast. if (isa<VPReplicateRecipe>(&R)) - break; + return; if (ATy->getScalarSizeInBits() < TruncTy->getScalarSizeInBits()) { + + unsigned ExtOpcode = match(R.getOperand(0), m_SExt(m_VPValue())) + ? Instruction::SExt + : Instruction::ZExt; auto *VPC = new VPWidenCastRecipe(Instruction::CastOps(ExtOpcode), A, TruncTy); VPC->insertBefore(&R); @@ -902,11 +910,11 @@ static void simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) { assert(TypeInfo.inferScalarType(VPV) == TypeInfo2.inferScalarType(VPV)); } #endif - break; - } - default: - break; } + + if (match(&R, m_CombineOr(m_Mul(m_VPValue(A), m_SpecificInt(1)), + m_Mul(m_SpecificInt(1), m_VPValue(A))))) + return R.getVPSingleValue()->replaceAllUsesWith(A); } /// Try to simplify the recipes in \p Plan. @@ -1059,7 +1067,7 @@ void VPlanTransforms::optimize(VPlan &Plan, ScalarEvolution &SE) { removeRedundantInductionCasts(Plan); simplifyRecipes(Plan, SE.getContext()); - optimizeInductions(Plan, SE); + legalizeAndOptimizeInductions(Plan, SE); removeDeadRecipes(Plan); createAndOptimizeReplicateRegions(Plan); @@ -1192,10 +1200,10 @@ void VPlanTransforms::addActiveLaneMask( LaneMask = addVPLaneMaskPhiAndUpdateExitBranch( Plan, DataAndControlFlowWithoutRuntimeCheck); } else { - LaneMask = new VPInstruction(VPInstruction::ActiveLaneMask, - {WideCanonicalIV, Plan.getTripCount()}, - nullptr, "active.lane.mask"); - LaneMask->insertAfter(WideCanonicalIV); + VPBuilder B = VPBuilder::getToInsertAfter(WideCanonicalIV); + LaneMask = B.createNaryOp(VPInstruction::ActiveLaneMask, + {WideCanonicalIV, Plan.getTripCount()}, nullptr, + "active.lane.mask"); } // Walk users of WideCanonicalIV and replace all compares of the form @@ -1249,7 +1257,24 @@ void VPlanTransforms::dropPoisonGeneratingRecipes( // load/store. If the underlying instruction has poison-generating flags, // drop them directly. if (auto *RecWithFlags = dyn_cast<VPRecipeWithIRFlags>(CurRec)) { - RecWithFlags->dropPoisonGeneratingFlags(); + VPValue *A, *B; + using namespace llvm::VPlanPatternMatch; + // Dropping disjoint from an OR may yield incorrect results, as some + // analysis may have converted it to an Add implicitly (e.g. SCEV used + // for dependence analysis). Instead, replace it with an equivalent Add. + // This is possible as all users of the disjoint OR only access lanes + // where the operands are disjoint or poison otherwise. + if (match(RecWithFlags, m_Or(m_VPValue(A), m_VPValue(B))) && + RecWithFlags->isDisjoint()) { + VPBuilder Builder(RecWithFlags); + VPInstruction *New = Builder.createOverflowingOp( + Instruction::Add, {A, B}, {false, false}, + RecWithFlags->getDebugLoc()); + RecWithFlags->replaceAllUsesWith(New); + RecWithFlags->eraseFromParent(); + CurRec = New; + } else + RecWithFlags->dropPoisonGeneratingFlags(); } else { Instruction *Instr = dyn_cast_or_null<Instruction>( CurRec->getVPSingleValue()->getUnderlyingValue()); diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp index dc669e314a0d9ac9162fa8959843a54aeddfe58b..af5e7c9bc385ca75337ae7a8561e001792a3f0e8 100644 --- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp +++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp @@ -66,8 +66,8 @@ class VectorCombine { public: VectorCombine(Function &F, const TargetTransformInfo &TTI, const DominatorTree &DT, AAResults &AA, AssumptionCache &AC, - bool TryEarlyFoldsOnly) - : F(F), Builder(F.getContext()), TTI(TTI), DT(DT), AA(AA), AC(AC), + const DataLayout *DL, bool TryEarlyFoldsOnly) + : F(F), Builder(F.getContext()), TTI(TTI), DT(DT), AA(AA), AC(AC), DL(DL), TryEarlyFoldsOnly(TryEarlyFoldsOnly) {} bool run(); @@ -79,6 +79,7 @@ private: const DominatorTree &DT; AAResults &AA; AssumptionCache &AC; + const DataLayout *DL; /// If true, only perform beneficial early IR transforms. Do not introduce new /// vector operations. @@ -134,6 +135,14 @@ private: }; } // namespace +/// Return the source operand of a potentially bitcasted value. If there is no +/// bitcast, return the input value itself. +static Value *peekThroughBitcasts(Value *V) { + while (auto *BitCast = dyn_cast<BitCastInst>(V)) + V = BitCast->getOperand(0); + return V; +} + static bool canWidenLoad(LoadInst *Load, const TargetTransformInfo &TTI) { // Do not widen load if atomic/volatile or under asan/hwasan/memtag/tsan. // The widened load may load data from dirty regions or create data races @@ -181,7 +190,6 @@ bool VectorCombine::vectorizeLoadInsert(Instruction &I) { // We use minimal alignment (maximum flexibility) because we only care about // the dereferenceable region. When calculating cost and creating a new op, // we may use a larger value based on alignment attributes. - const DataLayout &DL = I.getModule()->getDataLayout(); Value *SrcPtr = Load->getPointerOperand()->stripPointerCasts(); assert(isa<PointerType>(SrcPtr->getType()) && "Expected a pointer type"); @@ -189,15 +197,15 @@ bool VectorCombine::vectorizeLoadInsert(Instruction &I) { auto *MinVecTy = VectorType::get(ScalarTy, MinVecNumElts, false); unsigned OffsetEltIndex = 0; Align Alignment = Load->getAlign(); - if (!isSafeToLoadUnconditionally(SrcPtr, MinVecTy, Align(1), DL, Load, &AC, + if (!isSafeToLoadUnconditionally(SrcPtr, MinVecTy, Align(1), *DL, Load, &AC, &DT)) { // It is not safe to load directly from the pointer, but we can still peek // through gep offsets and check if it safe to load from a base address with // updated alignment. If it is, we can shuffle the element(s) into place // after loading. - unsigned OffsetBitWidth = DL.getIndexTypeSizeInBits(SrcPtr->getType()); + unsigned OffsetBitWidth = DL->getIndexTypeSizeInBits(SrcPtr->getType()); APInt Offset(OffsetBitWidth, 0); - SrcPtr = SrcPtr->stripAndAccumulateInBoundsConstantOffsets(DL, Offset); + SrcPtr = SrcPtr->stripAndAccumulateInBoundsConstantOffsets(*DL, Offset); // We want to shuffle the result down from a high element of a vector, so // the offset must be positive. @@ -215,7 +223,7 @@ bool VectorCombine::vectorizeLoadInsert(Instruction &I) { if (OffsetEltIndex >= MinVecNumElts) return false; - if (!isSafeToLoadUnconditionally(SrcPtr, MinVecTy, Align(1), DL, Load, &AC, + if (!isSafeToLoadUnconditionally(SrcPtr, MinVecTy, Align(1), *DL, Load, &AC, &DT)) return false; @@ -227,7 +235,7 @@ bool VectorCombine::vectorizeLoadInsert(Instruction &I) { // Original pattern: insertelt undef, load [free casts of] PtrOp, 0 // Use the greater of the alignment on the load or its source pointer. - Alignment = std::max(SrcPtr->getPointerAlignment(DL), Alignment); + Alignment = std::max(SrcPtr->getPointerAlignment(*DL), Alignment); Type *LoadTy = Load->getType(); unsigned AS = Load->getPointerAddressSpace(); InstructionCost OldCost = @@ -298,14 +306,13 @@ bool VectorCombine::widenSubvectorLoad(Instruction &I) { // the dereferenceable region. When calculating cost and creating a new op, // we may use a larger value based on alignment attributes. auto *Ty = cast<FixedVectorType>(I.getType()); - const DataLayout &DL = I.getModule()->getDataLayout(); Value *SrcPtr = Load->getPointerOperand()->stripPointerCasts(); assert(isa<PointerType>(SrcPtr->getType()) && "Expected a pointer type"); Align Alignment = Load->getAlign(); - if (!isSafeToLoadUnconditionally(SrcPtr, Ty, Align(1), DL, Load, &AC, &DT)) + if (!isSafeToLoadUnconditionally(SrcPtr, Ty, Align(1), *DL, Load, &AC, &DT)) return false; - Alignment = std::max(SrcPtr->getPointerAlignment(DL), Alignment); + Alignment = std::max(SrcPtr->getPointerAlignment(*DL), Alignment); Type *LoadTy = Load->getType(); unsigned AS = Load->getPointerAddressSpace(); @@ -684,10 +691,10 @@ bool VectorCombine::foldInsExtFNeg(Instruction &I) { /// destination type followed by shuffle. This can enable further transforms by /// moving bitcasts or shuffles together. bool VectorCombine::foldBitcastShuffle(Instruction &I) { - Value *V; + Value *V0, *V1; ArrayRef<int> Mask; - if (!match(&I, m_BitCast( - m_OneUse(m_Shuffle(m_Value(V), m_Undef(), m_Mask(Mask)))))) + if (!match(&I, m_BitCast(m_OneUse( + m_Shuffle(m_Value(V0), m_Value(V1), m_Mask(Mask)))))) return false; // 1) Do not fold bitcast shuffle for scalable type. First, shuffle cost for @@ -696,7 +703,7 @@ bool VectorCombine::foldBitcastShuffle(Instruction &I) { // 2) Disallow non-vector casts. // TODO: We could allow any shuffle. auto *DestTy = dyn_cast<FixedVectorType>(I.getType()); - auto *SrcTy = dyn_cast<FixedVectorType>(V->getType()); + auto *SrcTy = dyn_cast<FixedVectorType>(V0->getType()); if (!DestTy || !SrcTy) return false; @@ -724,21 +731,37 @@ bool VectorCombine::foldBitcastShuffle(Instruction &I) { // Bitcast the shuffle src - keep its original width but using the destination // scalar type. unsigned NumSrcElts = SrcTy->getPrimitiveSizeInBits() / DestEltSize; - auto *ShuffleTy = FixedVectorType::get(DestTy->getScalarType(), NumSrcElts); - - // The new shuffle must not cost more than the old shuffle. The bitcast is - // moved ahead of the shuffle, so assume that it has the same cost as before. - InstructionCost DestCost = TTI.getShuffleCost( - TargetTransformInfo::SK_PermuteSingleSrc, ShuffleTy, NewMask); + auto *NewShuffleTy = + FixedVectorType::get(DestTy->getScalarType(), NumSrcElts); + auto *OldShuffleTy = + FixedVectorType::get(SrcTy->getScalarType(), Mask.size()); + bool IsUnary = isa<UndefValue>(V1); + unsigned NumOps = IsUnary ? 1 : 2; + + // The new shuffle must not cost more than the old shuffle. + TargetTransformInfo::TargetCostKind CK = + TargetTransformInfo::TCK_RecipThroughput; + TargetTransformInfo::ShuffleKind SK = + IsUnary ? TargetTransformInfo::SK_PermuteSingleSrc + : TargetTransformInfo::SK_PermuteTwoSrc; + + InstructionCost DestCost = + TTI.getShuffleCost(SK, NewShuffleTy, NewMask, CK) + + (NumOps * TTI.getCastInstrCost(Instruction::BitCast, NewShuffleTy, SrcTy, + TargetTransformInfo::CastContextHint::None, + CK)); InstructionCost SrcCost = - TTI.getShuffleCost(TargetTransformInfo::SK_PermuteSingleSrc, SrcTy, Mask); + TTI.getShuffleCost(SK, SrcTy, Mask, CK) + + TTI.getCastInstrCost(Instruction::BitCast, DestTy, OldShuffleTy, + TargetTransformInfo::CastContextHint::None, CK); if (DestCost > SrcCost || !DestCost.isValid()) return false; - // bitcast (shuf V, MaskC) --> shuf (bitcast V), MaskC' + // bitcast (shuf V0, V1, MaskC) --> shuf (bitcast V0), (bitcast V1), MaskC' ++NumShufOfBitcast; - Value *CastV = Builder.CreateBitCast(V, ShuffleTy); - Value *Shuf = Builder.CreateShuffleVector(CastV, NewMask); + Value *CastV0 = Builder.CreateBitCast(peekThroughBitcasts(V0), NewShuffleTy); + Value *CastV1 = Builder.CreateBitCast(peekThroughBitcasts(V1), NewShuffleTy); + Value *Shuf = Builder.CreateShuffleVector(CastV0, CastV1, NewMask); replaceValue(I, *Shuf); return true; } @@ -786,9 +809,12 @@ bool VectorCombine::scalarizeVPIntrinsic(Instruction &I) { // intrinsic VectorType *VecTy = cast<VectorType>(VPI.getType()); TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput; + SmallVector<int> Mask; + if (auto *FVTy = dyn_cast<FixedVectorType>(VecTy)) + Mask.resize(FVTy->getNumElements(), 0); InstructionCost SplatCost = TTI.getVectorInstrCost(Instruction::InsertElement, VecTy, CostKind, 0) + - TTI.getShuffleCost(TargetTransformInfo::SK_Broadcast, VecTy); + TTI.getShuffleCost(TargetTransformInfo::SK_Broadcast, VecTy, Mask); // Calculate the cost of the VP Intrinsic SmallVector<Type *, 4> Args; @@ -835,7 +861,6 @@ bool VectorCombine::scalarizeVPIntrinsic(Instruction &I) { // Scalarize the intrinsic ElementCount EC = cast<VectorType>(Op0->getType())->getElementCount(); Value *EVL = VPI.getArgOperand(3); - const DataLayout &DL = VPI.getModule()->getDataLayout(); // If the VP op might introduce UB or poison, we can scalarize it provided // that we know the EVL > 0: If the EVL is zero, then the original VP op @@ -848,7 +873,7 @@ bool VectorCombine::scalarizeVPIntrinsic(Instruction &I) { else SafeToSpeculate = isSafeToSpeculativelyExecuteWithOpcode( *FunctionalOpcode, &VPI, nullptr, &AC, &DT); - if (!SafeToSpeculate && !isKnownNonZero(EVL, DL, 0, &AC, &VPI, &DT)) + if (!SafeToSpeculate && !isKnownNonZero(EVL, *DL, 0, &AC, &VPI, &DT)) return false; Value *ScalarVal = @@ -1227,12 +1252,11 @@ bool VectorCombine::foldSingleElementStore(Instruction &I) { if (auto *Load = dyn_cast<LoadInst>(Source)) { auto VecTy = cast<VectorType>(SI->getValueOperand()->getType()); - const DataLayout &DL = I.getModule()->getDataLayout(); Value *SrcAddr = Load->getPointerOperand()->stripPointerCasts(); // Don't optimize for atomic/volatile load or store. Ensure memory is not // modified between, vector type matches store size, and index is inbounds. if (!Load->isSimple() || Load->getParent() != SI->getParent() || - !DL.typeSizeEqualsStoreSize(Load->getType()->getScalarType()) || + !DL->typeSizeEqualsStoreSize(Load->getType()->getScalarType()) || SrcAddr != SI->getPointerOperand()->stripPointerCasts()) return false; @@ -1251,7 +1275,7 @@ bool VectorCombine::foldSingleElementStore(Instruction &I) { NSI->copyMetadata(*SI); Align ScalarOpAlignment = computeAlignmentAfterScalarization( std::max(SI->getAlign(), Load->getAlign()), NewElement->getType(), Idx, - DL); + *DL); NSI->setAlignment(ScalarOpAlignment); replaceValue(I, *NSI); eraseInstruction(I); @@ -1269,8 +1293,7 @@ bool VectorCombine::scalarizeLoadExtract(Instruction &I) { auto *VecTy = cast<VectorType>(I.getType()); auto *LI = cast<LoadInst>(&I); - const DataLayout &DL = I.getModule()->getDataLayout(); - if (LI->isVolatile() || !DL.typeSizeEqualsStoreSize(VecTy->getScalarType())) + if (LI->isVolatile() || !DL->typeSizeEqualsStoreSize(VecTy->getScalarType())) return false; InstructionCost OriginalCost = @@ -1348,7 +1371,7 @@ bool VectorCombine::scalarizeLoadExtract(Instruction &I) { VecTy->getElementType(), GEP, EI->getName() + ".scalar")); Align ScalarOpAlignment = computeAlignmentAfterScalarization( - LI->getAlign(), VecTy->getElementType(), Idx, DL); + LI->getAlign(), VecTy->getElementType(), Idx, *DL); NewLoad->setAlignment(ScalarOpAlignment); replaceValue(*EI, *NewLoad); @@ -2023,7 +2046,8 @@ PreservedAnalyses VectorCombinePass::run(Function &F, TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F); DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F); AAResults &AA = FAM.getResult<AAManager>(F); - VectorCombine Combiner(F, TTI, DT, AA, AC, TryEarlyFoldsOnly); + const DataLayout *DL = &F.getParent()->getDataLayout(); + VectorCombine Combiner(F, TTI, DT, AA, AC, DL, TryEarlyFoldsOnly); if (!Combiner.run()) return PreservedAnalyses::all(); PreservedAnalyses PA; diff --git a/llvm/runtimes/CMakeLists.txt b/llvm/runtimes/CMakeLists.txt index 54ec8bd28d4ca604f4f8bab5d28a3b520a23206e..8159d7f8a0a104008526f6f9ddaf083ff4e335d0 100644 --- a/llvm/runtimes/CMakeLists.txt +++ b/llvm/runtimes/CMakeLists.txt @@ -425,8 +425,17 @@ if(runtimes) # together in a single CMake invocation. set(extra_deps "") if("openmp" IN_LIST LLVM_ENABLE_RUNTIMES) + if (${LLVM_TOOL_FLANG_BUILD}) + message(STATUS "Configuring build of omp_lib.mod and omp_lib_kinds.mod via flang-new") + set(LIBOMP_FORTRAN_MODULES_COMPILER "${CMAKE_BINARY_DIR}/bin/flang-new") + set(LIBOMP_MODULES_INSTALL_PATH "${CMAKE_INSTALL_INCLUDEDIR}/flang") + # TODO: This is a workaround until flang becomes a first-class project + # in llvm/CMakeList.txt. Until then, this line ensures that flang-new is + # built before "openmp" is built as a runtime project. + list(APPEND extra_deps "flang-new") + endif() foreach(dep opt llvm-link llvm-extract clang clang-offload-packager) - if(TARGET ${dep} AND OPENMP_ENABLE_LIBOMPTARGET) + if(TARGET ${dep}) list(APPEND extra_deps ${dep}) endif() endforeach() @@ -522,7 +531,7 @@ if(runtimes) check_apple_target(${name} runtime) runtime_register_target(${name} - DEPENDS ${builtins_dep_name} ${hdrgen_deps} + DEPENDS ${builtins_dep_name} ${extra_deps} CMAKE_ARGS -DLLVM_DEFAULT_TARGET_TRIPLE=${name} ${libc_cmake_args} EXTRA_ARGS TARGET_TRIPLE ${name}) endforeach() diff --git a/llvm/test/Analysis/AliasSet/intrinsics.ll b/llvm/test/Analysis/AliasSet/intrinsics.ll index aeb5424ca919b42bd649ebac4e76e36b322861c6..0dc802ca7e0aaf5167f14029691925119c2d6723 100644 --- a/llvm/test/Analysis/AliasSet/intrinsics.ll +++ b/llvm/test/Analysis/AliasSet/intrinsics.ll @@ -1,9 +1,8 @@ -; RUN: opt -passes=print-alias-sets -S -o - < %s 2>&1 | FileCheck %s +; RUN: opt -passes=print-alias-sets -S -o - < %s 2>&1 | FileCheck %s --implicit-check-not="Unknown instructions" ; CHECK: Alias sets for function 'test1': ; CHECK: Alias Set Tracker: 2 alias sets for 2 pointer values. ; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Memory locations: (ptr %a, LocationSize::precise(1)) -; CHECK-NOT: 1 Unknown instruction ; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Memory locations: (ptr %b, LocationSize::precise(1)) define void @test1(i32 %c) { entry: @@ -64,7 +63,6 @@ entry: ; CHECK: Alias sets for function 'test5': ; CHECK: Alias Set Tracker: 2 alias sets for 2 pointer values. ; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Memory locations: (ptr %a, LocationSize::precise(1)) -; CHECK-NOT: 1 Unknown instruction ; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Memory locations: (ptr %b, LocationSize::precise(1)) define void @test5() { entry: @@ -76,6 +74,36 @@ entry: ret void } +; CHECK: Alias sets for function 'test_runtime': +; CHECK: Alias Set Tracker: 2 alias sets for 2 pointer values. +; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Memory locations: (ptr %a, LocationSize::precise(1)) +; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Memory locations: (ptr %b, LocationSize::precise(1)) +define i1 @test_runtime() local_unnamed_addr { +entry: + %a = alloca i8, align 1 + %b = alloca i8, align 1 + store i8 1, ptr %a, align 1 + %allow = call i1 @llvm.allow.runtime.check(metadata !"test_check") + store i8 1, ptr %b, align 1 + ret i1 %allow +} + +; CHECK: Alias sets for function 'test_ubsan': +; CHECK: Alias Set Tracker: 2 alias sets for 2 pointer values. +; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Memory locations: (ptr %a, LocationSize::precise(1)) +; CHECK: AliasSet[0x{{[0-9a-f]+}}, 1] must alias, Mod Memory locations: (ptr %b, LocationSize::precise(1)) +define i1 @test_ubsan() local_unnamed_addr { +entry: + %a = alloca i8, align 1 + %b = alloca i8, align 1 + store i8 1, ptr %a, align 1 + %allow = call i1 @llvm.allow.ubsan.check(i8 7) + store i8 1, ptr %b, align 1 + ret i1 %allow +} + +declare i1 @llvm.allow.ubsan.check(i8) +declare i1 @llvm.allow.runtime.check(metadata) declare void @llvm.assume(i1) declare void @llvm.experimental.guard(i1, ...) declare void @llvm.experimental.noalias.scope.decl(metadata) diff --git a/llvm/test/Analysis/CostModel/ARM/intrinsic-cost-kinds.ll b/llvm/test/Analysis/CostModel/ARM/intrinsic-cost-kinds.ll index d58f3348e41fedc4425a901a1e2a15945b8ed3bf..2823ab4b4f78ee5ab342f4f087da093b246d9556 100644 --- a/llvm/test/Analysis/CostModel/ARM/intrinsic-cost-kinds.ll +++ b/llvm/test/Analysis/CostModel/ARM/intrinsic-cost-kinds.ll @@ -124,7 +124,7 @@ define void @log2(float %a, <16 x float> %va) { ret void } -define void @constrained_fadd(float %a, <16 x float> %va) { +define void @constrained_fadd(float %a, <16 x float> %va) strictfp { ; THRU-LABEL: 'constrained_fadd' ; THRU-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %s = call float @llvm.experimental.constrained.fadd.f32(float %a, float %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") ; THRU-NEXT: Cost Model: Found an estimated cost of 48 for instruction: %t = call <16 x float> @llvm.experimental.constrained.fadd.v16f32(<16 x float> %va, <16 x float> %va, metadata !"round.dynamic", metadata !"fpexcept.ignore") diff --git a/llvm/test/Analysis/CostModel/RISCV/cast.ll b/llvm/test/Analysis/CostModel/RISCV/cast.ll index bd26c19c2f2c3c99fe7bb2bb6d9d56a9f1fca7d9..6ddd57a24c51f53945e848934821babc1f32e00b 100644 --- a/llvm/test/Analysis/CostModel/RISCV/cast.ll +++ b/llvm/test/Analysis/CostModel/RISCV/cast.ll @@ -16,74 +16,74 @@ define void @sext() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i1_v2i64 = sext <2 x i1> undef to <2 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i16 = sext <4 x i8> undef to <4 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i32 = sext <4 x i8> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i64 = sext <4 x i8> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4i64 = sext <4 x i8> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i32 = sext <4 x i16> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i64 = sext <4 x i16> undef to <4 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4i64 = sext <4 x i32> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16_v4i64 = sext <4 x i16> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4i64 = sext <4 x i32> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i8 = sext <4 x i1> undef to <4 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i16 = sext <4 x i1> undef to <4 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i32 = sext <4 x i1> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i64 = sext <4 x i1> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4i64 = sext <4 x i1> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i16 = sext <8 x i8> undef to <8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i32 = sext <8 x i8> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i64 = sext <8 x i8> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i32 = sext <8 x i16> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i64 = sext <8 x i16> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i32_v8i64 = sext <8 x i32> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_v8i32 = sext <8 x i8> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i8_v8i64 = sext <8 x i8> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8i32 = sext <8 x i16> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16_v8i64 = sext <8 x i16> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8i64 = sext <8 x i32> undef to <8 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i8 = sext <8 x i1> undef to <8 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i16 = sext <8 x i1> undef to <8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i32 = sext <8 x i1> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i64 = sext <8 x i1> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i16 = sext <16 x i8> undef to <16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i32 = sext <16 x i8> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i64 = sext <16 x i8> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i32 = sext <16 x i16> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i64 = sext <16 x i16> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i32_v16i64 = sext <16 x i32> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8i32 = sext <8 x i1> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8i64 = sext <8 x i1> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i8_v16i16 = sext <16 x i8> undef to <16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8_v16i32 = sext <16 x i8> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i8_v16i64 = sext <16 x i8> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16i32 = sext <16 x i16> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16_v16i64 = sext <16 x i16> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16i64 = sext <16 x i32> undef to <16 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i8 = sext <16 x i1> undef to <16 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i16 = sext <16 x i1> undef to <16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i32 = sext <16 x i1> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i64 = sext <16 x i1> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i16 = sext <32 x i8> undef to <32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i32 = sext <32 x i8> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i8_v32i64 = sext <32 x i8> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i16_v32i32 = sext <32 x i16> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i16_v32i64 = sext <32 x i16> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i32_v32i64 = sext <32 x i32> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i8 = sext <32 x i1> undef to <32 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i16 = sext <32 x i1> undef to <32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i32 = sext <32 x i1> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_v32i64 = sext <32 x i1> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i8_v64i16 = sext <64 x i8> undef to <64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i8_v64i32 = sext <64 x i8> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i8_v64i64 = sext <64 x i8> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i16_v64i32 = sext <64 x i16> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i16_v64i64 = sext <64 x i16> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64i32_v64i64 = sext <64 x i32> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i8 = sext <64 x i1> undef to <64 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i16 = sext <64 x i1> undef to <64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i1_v64i32 = sext <64 x i1> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64i1_v64i64 = sext <64 x i1> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i8_v128i16 = sext <128 x i8> undef to <128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v128i8_v128i32 = sext <128 x i8> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v128i8_v128i64 = sext <128 x i8> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128i16_v128i32 = sext <128 x i16> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v128i16_v128i64 = sext <128 x i16> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128i32_v128i64 = sext <128 x i32> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v128i1_v128i8 = sext <128 x i1> undef to <128 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v128i1_v128i16 = sext <128 x i1> undef to <128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i1_v128i32 = sext <128 x i1> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %v128i1_v128i64 = sext <128 x i1> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i8_v256i16 = sext <256 x i8> undef to <256 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v256i8_v256i32 = sext <256 x i8> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %v256i8_v256i64 = sext <256 x i8> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v256i16_v256i32 = sext <256 x i16> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v256i16_v256i64 = sext <256 x i16> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %v256i32_v256i64 = sext <256 x i32> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v256i1_v256i8 = sext <256 x i1> undef to <256 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v256i1_v256i16 = sext <256 x i1> undef to <256 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i1_v256i32 = sext <256 x i1> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 46 for instruction: %v256i1_v256i64 = sext <256 x i1> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_v16i16 = sext <16 x i1> undef to <16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16i32 = sext <16 x i1> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16i64 = sext <16 x i1> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i8_v32i16 = sext <32 x i8> undef to <32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i8_v32i32 = sext <32 x i8> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i8_v32i64 = sext <32 x i8> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32i32 = sext <32 x i16> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i16_v32i64 = sext <32 x i16> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32i64 = sext <32 x i32> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_v32i8 = sext <32 x i1> undef to <32 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_v32i16 = sext <32 x i1> undef to <32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32i32 = sext <32 x i1> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32i64 = sext <32 x i1> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i8_v64i16 = sext <64 x i8> undef to <64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i8_v64i32 = sext <64 x i8> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i8_v64i64 = sext <64 x i8> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64i32 = sext <64 x i16> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i16_v64i64 = sext <64 x i16> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64i64 = sext <64 x i32> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i1_v64i8 = sext <64 x i1> undef to <64 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i1_v64i16 = sext <64 x i1> undef to <64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64i32 = sext <64 x i1> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64i64 = sext <64 x i1> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v128i8_v128i16 = sext <128 x i8> undef to <128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v128i8_v128i32 = sext <128 x i8> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %v128i8_v128i64 = sext <128 x i8> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128i32 = sext <128 x i16> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v128i16_v128i64 = sext <128 x i16> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128i64 = sext <128 x i32> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v128i1_v128i8 = sext <128 x i1> undef to <128 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v128i1_v128i16 = sext <128 x i1> undef to <128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128i32 = sext <128 x i1> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128i64 = sext <128 x i1> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v256i8_v256i16 = sext <256 x i8> undef to <256 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v256i8_v256i32 = sext <256 x i8> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 142 for instruction: %v256i8_v256i64 = sext <256 x i8> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v256i16_v256i32 = sext <256 x i16> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 140 for instruction: %v256i16_v256i64 = sext <256 x i16> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 136 for instruction: %v256i32_v256i64 = sext <256 x i32> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v256i1_v256i8 = sext <256 x i1> undef to <256 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %v256i1_v256i16 = sext <256 x i1> undef to <256 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %v256i1_v256i32 = sext <256 x i1> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 270 for instruction: %v256i1_v256i64 = sext <256 x i1> undef to <256 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i16 = sext <vscale x 1 x i8> undef to <vscale x 1 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i32 = sext <vscale x 1 x i8> undef to <vscale x 1 x i32> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i64 = sext <vscale x 1 x i8> undef to <vscale x 1 x i64> @@ -96,73 +96,73 @@ define void @sext() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i1_nxv1i64 = sext <vscale x 1 x i1> undef to <vscale x 1 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i16 = sext <vscale x 2 x i8> undef to <vscale x 2 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i32 = sext <vscale x 2 x i8> undef to <vscale x 2 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i64 = sext <vscale x 2 x i8> undef to <vscale x 2 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2i64 = sext <vscale x 2 x i8> undef to <vscale x 2 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i32 = sext <vscale x 2 x i16> undef to <vscale x 2 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i64 = sext <vscale x 2 x i16> undef to <vscale x 2 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2i64 = sext <vscale x 2 x i32> undef to <vscale x 2 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i16_nxv2i64 = sext <vscale x 2 x i16> undef to <vscale x 2 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2i64 = sext <vscale x 2 x i32> undef to <vscale x 2 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i8 = sext <vscale x 2 x i1> undef to <vscale x 2 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i16 = sext <vscale x 2 x i1> undef to <vscale x 2 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i32 = sext <vscale x 2 x i1> undef to <vscale x 2 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i64 = sext <vscale x 2 x i1> undef to <vscale x 2 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2i64 = sext <vscale x 2 x i1> undef to <vscale x 2 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i16 = sext <vscale x 4 x i8> undef to <vscale x 4 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i32 = sext <vscale x 4 x i8> undef to <vscale x 4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i64 = sext <vscale x 4 x i8> undef to <vscale x 4 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i32 = sext <vscale x 4 x i16> undef to <vscale x 4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i64 = sext <vscale x 4 x i16> undef to <vscale x 4 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i32_nxv4i64 = sext <vscale x 4 x i32> undef to <vscale x 4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i8_nxv4i32 = sext <vscale x 4 x i8> undef to <vscale x 4 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i8_nxv4i64 = sext <vscale x 4 x i8> undef to <vscale x 4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4i32 = sext <vscale x 4 x i16> undef to <vscale x 4 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i16_nxv4i64 = sext <vscale x 4 x i16> undef to <vscale x 4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4i64 = sext <vscale x 4 x i32> undef to <vscale x 4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i8 = sext <vscale x 4 x i1> undef to <vscale x 4 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i16 = sext <vscale x 4 x i1> undef to <vscale x 4 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i32 = sext <vscale x 4 x i1> undef to <vscale x 4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i64 = sext <vscale x 4 x i1> undef to <vscale x 4 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i16 = sext <vscale x 8 x i8> undef to <vscale x 8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i32 = sext <vscale x 8 x i8> undef to <vscale x 8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i64 = sext <vscale x 8 x i8> undef to <vscale x 8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i32 = sext <vscale x 8 x i16> undef to <vscale x 8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i64 = sext <vscale x 8 x i16> undef to <vscale x 8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i32_nxv8i64 = sext <vscale x 8 x i32> undef to <vscale x 8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4i32 = sext <vscale x 4 x i1> undef to <vscale x 4 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4i64 = sext <vscale x 4 x i1> undef to <vscale x 4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i8_nxv8i16 = sext <vscale x 8 x i8> undef to <vscale x 8 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i8_nxv8i32 = sext <vscale x 8 x i8> undef to <vscale x 8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i8_nxv8i64 = sext <vscale x 8 x i8> undef to <vscale x 8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8i32 = sext <vscale x 8 x i16> undef to <vscale x 8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i16_nxv8i64 = sext <vscale x 8 x i16> undef to <vscale x 8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8i64 = sext <vscale x 8 x i32> undef to <vscale x 8 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i8 = sext <vscale x 8 x i1> undef to <vscale x 8 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i16 = sext <vscale x 8 x i1> undef to <vscale x 8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i32 = sext <vscale x 8 x i1> undef to <vscale x 8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i64 = sext <vscale x 8 x i1> undef to <vscale x 8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i16 = sext <vscale x 16 x i8> undef to <vscale x 16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i32 = sext <vscale x 16 x i8> undef to <vscale x 16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i8_nxv16i64 = sext <vscale x 16 x i8> undef to <vscale x 16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i16_nxv16i32 = sext <vscale x 16 x i16> undef to <vscale x 16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i16_nxv16i64 = sext <vscale x 16 x i16> undef to <vscale x 16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i32_nxv16i64 = sext <vscale x 16 x i32> undef to <vscale x 16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i8 = sext <vscale x 16 x i1> undef to <vscale x 16 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i16 = sext <vscale x 16 x i1> undef to <vscale x 16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i32 = sext <vscale x 16 x i1> undef to <vscale x 16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_nxv16i64 = sext <vscale x 16 x i1> undef to <vscale x 16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv32i8_nxv32i16 = sext <vscale x 32 x i8> undef to <vscale x 32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i8_nxv32i32 = sext <vscale x 32 x i8> undef to <vscale x 32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i8_nxv32i64 = sext <vscale x 32 x i8> undef to <vscale x 32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i16_nxv32i32 = sext <vscale x 32 x i16> undef to <vscale x 32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i16_nxv32i64 = sext <vscale x 32 x i16> undef to <vscale x 32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i32_nxv32i64 = sext <vscale x 32 x i32> undef to <vscale x 32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i8 = sext <vscale x 32 x i1> undef to <vscale x 32 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i16 = sext <vscale x 32 x i1> undef to <vscale x 32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_nxv32i32 = sext <vscale x 32 x i1> undef to <vscale x 32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_nxv32i64 = sext <vscale x 32 x i1> undef to <vscale x 32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv64i8_nxv64i16 = sext <vscale x 64 x i8> undef to <vscale x 64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv64i8_nxv64i32 = sext <vscale x 64 x i8> undef to <vscale x 64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_nxv8i16 = sext <vscale x 8 x i1> undef to <vscale x 8 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8i32 = sext <vscale x 8 x i1> undef to <vscale x 8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8i64 = sext <vscale x 8 x i1> undef to <vscale x 8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i8_nxv16i16 = sext <vscale x 16 x i8> undef to <vscale x 16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i8_nxv16i32 = sext <vscale x 16 x i8> undef to <vscale x 16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i8_nxv16i64 = sext <vscale x 16 x i8> undef to <vscale x 16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16i32 = sext <vscale x 16 x i16> undef to <vscale x 16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i16_nxv16i64 = sext <vscale x 16 x i16> undef to <vscale x 16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16i64 = sext <vscale x 16 x i32> undef to <vscale x 16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_nxv16i8 = sext <vscale x 16 x i1> undef to <vscale x 16 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_nxv16i16 = sext <vscale x 16 x i1> undef to <vscale x 16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16i32 = sext <vscale x 16 x i1> undef to <vscale x 16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16i64 = sext <vscale x 16 x i1> undef to <vscale x 16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i8_nxv32i16 = sext <vscale x 32 x i8> undef to <vscale x 32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i8_nxv32i32 = sext <vscale x 32 x i8> undef to <vscale x 32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i8_nxv32i64 = sext <vscale x 32 x i8> undef to <vscale x 32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32i32 = sext <vscale x 32 x i16> undef to <vscale x 32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i16_nxv32i64 = sext <vscale x 32 x i16> undef to <vscale x 32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32i64 = sext <vscale x 32 x i32> undef to <vscale x 32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i1_nxv32i8 = sext <vscale x 32 x i1> undef to <vscale x 32 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv32i1_nxv32i16 = sext <vscale x 32 x i1> undef to <vscale x 32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32i32 = sext <vscale x 32 x i1> undef to <vscale x 32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32i64 = sext <vscale x 32 x i1> undef to <vscale x 32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv64i8_nxv64i16 = sext <vscale x 64 x i8> undef to <vscale x 64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv64i8_nxv64i32 = sext <vscale x 64 x i8> undef to <vscale x 64 x i32> ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv64i8_nxv64i64 = sext <vscale x 64 x i8> undef to <vscale x 64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64i16_nxv64i32 = sext <vscale x 64 x i16> undef to <vscale x 64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv64i16_nxv64i64 = sext <vscale x 64 x i16> undef to <vscale x 64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv64i32_nxv64i64 = sext <vscale x 64 x i32> undef to <vscale x 64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv64i1_nxv64i8 = sext <vscale x 64 x i1> undef to <vscale x 64 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv64i1_nxv64i16 = sext <vscale x 64 x i1> undef to <vscale x 64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i1_nxv64i32 = sext <vscale x 64 x i1> undef to <vscale x 64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64i32 = sext <vscale x 64 x i16> undef to <vscale x 64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %nxv64i16_nxv64i64 = sext <vscale x 64 x i16> undef to <vscale x 64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 69 for instruction: %nxv64i32_nxv64i64 = sext <vscale x 64 x i32> undef to <vscale x 64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv64i1_nxv64i8 = sext <vscale x 64 x i1> undef to <vscale x 64 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv64i1_nxv64i16 = sext <vscale x 64 x i1> undef to <vscale x 64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64i32 = sext <vscale x 64 x i1> undef to <vscale x 64 x i32> ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv64i1_nxv64i64 = sext <vscale x 64 x i1> undef to <vscale x 64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv128i8_nxv128i16 = sext <vscale x 128 x i8> undef to <vscale x 128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv128i8_nxv128i32 = sext <vscale x 128 x i8> undef to <vscale x 128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv128i8_nxv128i16 = sext <vscale x 128 x i8> undef to <vscale x 128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv128i8_nxv128i32 = sext <vscale x 128 x i8> undef to <vscale x 128 x i32> ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i8_nxv128i128 = sext <vscale x 128 x i8> undef to <vscale x 128 x i128> -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv128i16_nxv128i32 = sext <vscale x 128 x i16> undef to <vscale x 128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv128i16_nxv128i32 = sext <vscale x 128 x i16> undef to <vscale x 128 x i32> ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i16_nxv128i128 = sext <vscale x 128 x i16> undef to <vscale x 128 x i128> ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i32_nxv128i128 = sext <vscale x 128 x i32> undef to <vscale x 128 x i128> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv128i1_nxv128i8 = sext <vscale x 128 x i1> undef to <vscale x 128 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv128i1_nxv128i16 = sext <vscale x 128 x i1> undef to <vscale x 128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv128i1_nxv128i32 = sext <vscale x 128 x i1> undef to <vscale x 128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %nxv128i1_nxv128i8 = sext <vscale x 128 x i1> undef to <vscale x 128 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %nxv128i1_nxv128i16 = sext <vscale x 128 x i1> undef to <vscale x 128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %nxv128i1_nxv128i32 = sext <vscale x 128 x i1> undef to <vscale x 128 x i32> ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i1_nxv128i128 = sext <vscale x 128 x i1> undef to <vscale x 128 x i128> ; RV32-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; @@ -179,74 +179,74 @@ define void @sext() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i1_v2i64 = sext <2 x i1> undef to <2 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i16 = sext <4 x i8> undef to <4 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i32 = sext <4 x i8> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i64 = sext <4 x i8> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4i64 = sext <4 x i8> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i32 = sext <4 x i16> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i64 = sext <4 x i16> undef to <4 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4i64 = sext <4 x i32> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16_v4i64 = sext <4 x i16> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4i64 = sext <4 x i32> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i8 = sext <4 x i1> undef to <4 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i16 = sext <4 x i1> undef to <4 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i32 = sext <4 x i1> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i64 = sext <4 x i1> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4i64 = sext <4 x i1> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i16 = sext <8 x i8> undef to <8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i32 = sext <8 x i8> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i64 = sext <8 x i8> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i32 = sext <8 x i16> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i64 = sext <8 x i16> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i32_v8i64 = sext <8 x i32> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_v8i32 = sext <8 x i8> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i8_v8i64 = sext <8 x i8> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8i32 = sext <8 x i16> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16_v8i64 = sext <8 x i16> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8i64 = sext <8 x i32> undef to <8 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i8 = sext <8 x i1> undef to <8 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i16 = sext <8 x i1> undef to <8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i32 = sext <8 x i1> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i64 = sext <8 x i1> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i16 = sext <16 x i8> undef to <16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i32 = sext <16 x i8> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i64 = sext <16 x i8> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i32 = sext <16 x i16> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i64 = sext <16 x i16> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i32_v16i64 = sext <16 x i32> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8i32 = sext <8 x i1> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8i64 = sext <8 x i1> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i8_v16i16 = sext <16 x i8> undef to <16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8_v16i32 = sext <16 x i8> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i8_v16i64 = sext <16 x i8> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16i32 = sext <16 x i16> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16_v16i64 = sext <16 x i16> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16i64 = sext <16 x i32> undef to <16 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i8 = sext <16 x i1> undef to <16 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i16 = sext <16 x i1> undef to <16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i32 = sext <16 x i1> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i64 = sext <16 x i1> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i16 = sext <32 x i8> undef to <32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i32 = sext <32 x i8> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i8_v32i64 = sext <32 x i8> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i16_v32i32 = sext <32 x i16> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i16_v32i64 = sext <32 x i16> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i32_v32i64 = sext <32 x i32> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i8 = sext <32 x i1> undef to <32 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i16 = sext <32 x i1> undef to <32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i32 = sext <32 x i1> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_v32i64 = sext <32 x i1> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i8_v64i16 = sext <64 x i8> undef to <64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i8_v64i32 = sext <64 x i8> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i8_v64i64 = sext <64 x i8> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i16_v64i32 = sext <64 x i16> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i16_v64i64 = sext <64 x i16> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64i32_v64i64 = sext <64 x i32> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i8 = sext <64 x i1> undef to <64 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i16 = sext <64 x i1> undef to <64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i1_v64i32 = sext <64 x i1> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64i1_v64i64 = sext <64 x i1> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i8_v128i16 = sext <128 x i8> undef to <128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v128i8_v128i32 = sext <128 x i8> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v128i8_v128i64 = sext <128 x i8> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128i16_v128i32 = sext <128 x i16> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v128i16_v128i64 = sext <128 x i16> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128i32_v128i64 = sext <128 x i32> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v128i1_v128i8 = sext <128 x i1> undef to <128 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v128i1_v128i16 = sext <128 x i1> undef to <128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i1_v128i32 = sext <128 x i1> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %v128i1_v128i64 = sext <128 x i1> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i8_v256i16 = sext <256 x i8> undef to <256 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v256i8_v256i32 = sext <256 x i8> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %v256i8_v256i64 = sext <256 x i8> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v256i16_v256i32 = sext <256 x i16> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v256i16_v256i64 = sext <256 x i16> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %v256i32_v256i64 = sext <256 x i32> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v256i1_v256i8 = sext <256 x i1> undef to <256 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v256i1_v256i16 = sext <256 x i1> undef to <256 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i1_v256i32 = sext <256 x i1> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 46 for instruction: %v256i1_v256i64 = sext <256 x i1> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_v16i16 = sext <16 x i1> undef to <16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16i32 = sext <16 x i1> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16i64 = sext <16 x i1> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i8_v32i16 = sext <32 x i8> undef to <32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i8_v32i32 = sext <32 x i8> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i8_v32i64 = sext <32 x i8> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32i32 = sext <32 x i16> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i16_v32i64 = sext <32 x i16> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32i64 = sext <32 x i32> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_v32i8 = sext <32 x i1> undef to <32 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_v32i16 = sext <32 x i1> undef to <32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32i32 = sext <32 x i1> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32i64 = sext <32 x i1> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i8_v64i16 = sext <64 x i8> undef to <64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i8_v64i32 = sext <64 x i8> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i8_v64i64 = sext <64 x i8> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64i32 = sext <64 x i16> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i16_v64i64 = sext <64 x i16> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64i64 = sext <64 x i32> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i1_v64i8 = sext <64 x i1> undef to <64 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i1_v64i16 = sext <64 x i1> undef to <64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64i32 = sext <64 x i1> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64i64 = sext <64 x i1> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v128i8_v128i16 = sext <128 x i8> undef to <128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v128i8_v128i32 = sext <128 x i8> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %v128i8_v128i64 = sext <128 x i8> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128i32 = sext <128 x i16> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v128i16_v128i64 = sext <128 x i16> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128i64 = sext <128 x i32> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v128i1_v128i8 = sext <128 x i1> undef to <128 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v128i1_v128i16 = sext <128 x i1> undef to <128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128i32 = sext <128 x i1> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128i64 = sext <128 x i1> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v256i8_v256i16 = sext <256 x i8> undef to <256 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v256i8_v256i32 = sext <256 x i8> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 142 for instruction: %v256i8_v256i64 = sext <256 x i8> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v256i16_v256i32 = sext <256 x i16> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 140 for instruction: %v256i16_v256i64 = sext <256 x i16> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 136 for instruction: %v256i32_v256i64 = sext <256 x i32> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v256i1_v256i8 = sext <256 x i1> undef to <256 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %v256i1_v256i16 = sext <256 x i1> undef to <256 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %v256i1_v256i32 = sext <256 x i1> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 270 for instruction: %v256i1_v256i64 = sext <256 x i1> undef to <256 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i16 = sext <vscale x 1 x i8> undef to <vscale x 1 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i32 = sext <vscale x 1 x i8> undef to <vscale x 1 x i32> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i64 = sext <vscale x 1 x i8> undef to <vscale x 1 x i64> @@ -259,73 +259,73 @@ define void @sext() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i1_nxv1i64 = sext <vscale x 1 x i1> undef to <vscale x 1 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i16 = sext <vscale x 2 x i8> undef to <vscale x 2 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i32 = sext <vscale x 2 x i8> undef to <vscale x 2 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i64 = sext <vscale x 2 x i8> undef to <vscale x 2 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2i64 = sext <vscale x 2 x i8> undef to <vscale x 2 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i32 = sext <vscale x 2 x i16> undef to <vscale x 2 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i64 = sext <vscale x 2 x i16> undef to <vscale x 2 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2i64 = sext <vscale x 2 x i32> undef to <vscale x 2 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i16_nxv2i64 = sext <vscale x 2 x i16> undef to <vscale x 2 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2i64 = sext <vscale x 2 x i32> undef to <vscale x 2 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i8 = sext <vscale x 2 x i1> undef to <vscale x 2 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i16 = sext <vscale x 2 x i1> undef to <vscale x 2 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i32 = sext <vscale x 2 x i1> undef to <vscale x 2 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i64 = sext <vscale x 2 x i1> undef to <vscale x 2 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2i64 = sext <vscale x 2 x i1> undef to <vscale x 2 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i16 = sext <vscale x 4 x i8> undef to <vscale x 4 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i32 = sext <vscale x 4 x i8> undef to <vscale x 4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i64 = sext <vscale x 4 x i8> undef to <vscale x 4 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i32 = sext <vscale x 4 x i16> undef to <vscale x 4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i64 = sext <vscale x 4 x i16> undef to <vscale x 4 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i32_nxv4i64 = sext <vscale x 4 x i32> undef to <vscale x 4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i8_nxv4i32 = sext <vscale x 4 x i8> undef to <vscale x 4 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i8_nxv4i64 = sext <vscale x 4 x i8> undef to <vscale x 4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4i32 = sext <vscale x 4 x i16> undef to <vscale x 4 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i16_nxv4i64 = sext <vscale x 4 x i16> undef to <vscale x 4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4i64 = sext <vscale x 4 x i32> undef to <vscale x 4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i8 = sext <vscale x 4 x i1> undef to <vscale x 4 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i16 = sext <vscale x 4 x i1> undef to <vscale x 4 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i32 = sext <vscale x 4 x i1> undef to <vscale x 4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i64 = sext <vscale x 4 x i1> undef to <vscale x 4 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i16 = sext <vscale x 8 x i8> undef to <vscale x 8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i32 = sext <vscale x 8 x i8> undef to <vscale x 8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i64 = sext <vscale x 8 x i8> undef to <vscale x 8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i32 = sext <vscale x 8 x i16> undef to <vscale x 8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i64 = sext <vscale x 8 x i16> undef to <vscale x 8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i32_nxv8i64 = sext <vscale x 8 x i32> undef to <vscale x 8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4i32 = sext <vscale x 4 x i1> undef to <vscale x 4 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4i64 = sext <vscale x 4 x i1> undef to <vscale x 4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i8_nxv8i16 = sext <vscale x 8 x i8> undef to <vscale x 8 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i8_nxv8i32 = sext <vscale x 8 x i8> undef to <vscale x 8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i8_nxv8i64 = sext <vscale x 8 x i8> undef to <vscale x 8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8i32 = sext <vscale x 8 x i16> undef to <vscale x 8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i16_nxv8i64 = sext <vscale x 8 x i16> undef to <vscale x 8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8i64 = sext <vscale x 8 x i32> undef to <vscale x 8 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i8 = sext <vscale x 8 x i1> undef to <vscale x 8 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i16 = sext <vscale x 8 x i1> undef to <vscale x 8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i32 = sext <vscale x 8 x i1> undef to <vscale x 8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i64 = sext <vscale x 8 x i1> undef to <vscale x 8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i16 = sext <vscale x 16 x i8> undef to <vscale x 16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i32 = sext <vscale x 16 x i8> undef to <vscale x 16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i8_nxv16i64 = sext <vscale x 16 x i8> undef to <vscale x 16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i16_nxv16i32 = sext <vscale x 16 x i16> undef to <vscale x 16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i16_nxv16i64 = sext <vscale x 16 x i16> undef to <vscale x 16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i32_nxv16i64 = sext <vscale x 16 x i32> undef to <vscale x 16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i8 = sext <vscale x 16 x i1> undef to <vscale x 16 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i16 = sext <vscale x 16 x i1> undef to <vscale x 16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i32 = sext <vscale x 16 x i1> undef to <vscale x 16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_nxv16i64 = sext <vscale x 16 x i1> undef to <vscale x 16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv32i8_nxv32i16 = sext <vscale x 32 x i8> undef to <vscale x 32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i8_nxv32i32 = sext <vscale x 32 x i8> undef to <vscale x 32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i8_nxv32i64 = sext <vscale x 32 x i8> undef to <vscale x 32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i16_nxv32i32 = sext <vscale x 32 x i16> undef to <vscale x 32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i16_nxv32i64 = sext <vscale x 32 x i16> undef to <vscale x 32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i32_nxv32i64 = sext <vscale x 32 x i32> undef to <vscale x 32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i8 = sext <vscale x 32 x i1> undef to <vscale x 32 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i16 = sext <vscale x 32 x i1> undef to <vscale x 32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_nxv32i32 = sext <vscale x 32 x i1> undef to <vscale x 32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_nxv32i64 = sext <vscale x 32 x i1> undef to <vscale x 32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv64i8_nxv64i16 = sext <vscale x 64 x i8> undef to <vscale x 64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv64i8_nxv64i32 = sext <vscale x 64 x i8> undef to <vscale x 64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv64i8_nxv64i64 = sext <vscale x 64 x i8> undef to <vscale x 64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64i16_nxv64i32 = sext <vscale x 64 x i16> undef to <vscale x 64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv64i16_nxv64i64 = sext <vscale x 64 x i16> undef to <vscale x 64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv64i32_nxv64i64 = sext <vscale x 64 x i32> undef to <vscale x 64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv64i1_nxv64i8 = sext <vscale x 64 x i1> undef to <vscale x 64 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv64i1_nxv64i16 = sext <vscale x 64 x i1> undef to <vscale x 64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i1_nxv64i32 = sext <vscale x 64 x i1> undef to <vscale x 64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %nxv64i1_nxv64i64 = sext <vscale x 64 x i1> undef to <vscale x 64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv128i8_nxv128i16 = sext <vscale x 128 x i8> undef to <vscale x 128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv128i8_nxv128i32 = sext <vscale x 128 x i8> undef to <vscale x 128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_nxv8i16 = sext <vscale x 8 x i1> undef to <vscale x 8 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8i32 = sext <vscale x 8 x i1> undef to <vscale x 8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8i64 = sext <vscale x 8 x i1> undef to <vscale x 8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i8_nxv16i16 = sext <vscale x 16 x i8> undef to <vscale x 16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i8_nxv16i32 = sext <vscale x 16 x i8> undef to <vscale x 16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i8_nxv16i64 = sext <vscale x 16 x i8> undef to <vscale x 16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16i32 = sext <vscale x 16 x i16> undef to <vscale x 16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i16_nxv16i64 = sext <vscale x 16 x i16> undef to <vscale x 16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16i64 = sext <vscale x 16 x i32> undef to <vscale x 16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_nxv16i8 = sext <vscale x 16 x i1> undef to <vscale x 16 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_nxv16i16 = sext <vscale x 16 x i1> undef to <vscale x 16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16i32 = sext <vscale x 16 x i1> undef to <vscale x 16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16i64 = sext <vscale x 16 x i1> undef to <vscale x 16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i8_nxv32i16 = sext <vscale x 32 x i8> undef to <vscale x 32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i8_nxv32i32 = sext <vscale x 32 x i8> undef to <vscale x 32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i8_nxv32i64 = sext <vscale x 32 x i8> undef to <vscale x 32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32i32 = sext <vscale x 32 x i16> undef to <vscale x 32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i16_nxv32i64 = sext <vscale x 32 x i16> undef to <vscale x 32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32i64 = sext <vscale x 32 x i32> undef to <vscale x 32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i1_nxv32i8 = sext <vscale x 32 x i1> undef to <vscale x 32 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv32i1_nxv32i16 = sext <vscale x 32 x i1> undef to <vscale x 32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32i32 = sext <vscale x 32 x i1> undef to <vscale x 32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32i64 = sext <vscale x 32 x i1> undef to <vscale x 32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv64i8_nxv64i16 = sext <vscale x 64 x i8> undef to <vscale x 64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv64i8_nxv64i32 = sext <vscale x 64 x i8> undef to <vscale x 64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %nxv64i8_nxv64i64 = sext <vscale x 64 x i8> undef to <vscale x 64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64i32 = sext <vscale x 64 x i16> undef to <vscale x 64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv64i16_nxv64i64 = sext <vscale x 64 x i16> undef to <vscale x 64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64i32_nxv64i64 = sext <vscale x 64 x i32> undef to <vscale x 64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv64i1_nxv64i8 = sext <vscale x 64 x i1> undef to <vscale x 64 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv64i1_nxv64i16 = sext <vscale x 64 x i1> undef to <vscale x 64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64i32 = sext <vscale x 64 x i1> undef to <vscale x 64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %nxv64i1_nxv64i64 = sext <vscale x 64 x i1> undef to <vscale x 64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv128i8_nxv128i16 = sext <vscale x 128 x i8> undef to <vscale x 128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv128i8_nxv128i32 = sext <vscale x 128 x i8> undef to <vscale x 128 x i32> ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i8_nxv128i128 = sext <vscale x 128 x i8> undef to <vscale x 128 x i128> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv128i16_nxv128i32 = sext <vscale x 128 x i16> undef to <vscale x 128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv128i16_nxv128i32 = sext <vscale x 128 x i16> undef to <vscale x 128 x i32> ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i16_nxv128i128 = sext <vscale x 128 x i16> undef to <vscale x 128 x i128> ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i32_nxv128i128 = sext <vscale x 128 x i32> undef to <vscale x 128 x i128> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv128i1_nxv128i8 = sext <vscale x 128 x i1> undef to <vscale x 128 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv128i1_nxv128i16 = sext <vscale x 128 x i1> undef to <vscale x 128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv128i1_nxv128i32 = sext <vscale x 128 x i1> undef to <vscale x 128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %nxv128i1_nxv128i8 = sext <vscale x 128 x i1> undef to <vscale x 128 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %nxv128i1_nxv128i16 = sext <vscale x 128 x i1> undef to <vscale x 128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %nxv128i1_nxv128i32 = sext <vscale x 128 x i1> undef to <vscale x 128 x i32> ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i1_nxv128i128 = sext <vscale x 128 x i1> undef to <vscale x 128 x i128> ; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; @@ -522,74 +522,74 @@ define void @zext() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i1_v2i64 = zext <2 x i1> undef to <2 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i16 = zext <4 x i8> undef to <4 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i32 = zext <4 x i8> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i64 = zext <4 x i8> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4i64 = zext <4 x i8> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i32 = zext <4 x i16> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i64 = zext <4 x i16> undef to <4 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4i64 = zext <4 x i32> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16_v4i64 = zext <4 x i16> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4i64 = zext <4 x i32> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i8 = zext <4 x i1> undef to <4 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i16 = zext <4 x i1> undef to <4 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i32 = zext <4 x i1> undef to <4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i64 = zext <4 x i1> undef to <4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4i64 = zext <4 x i1> undef to <4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i16 = zext <8 x i8> undef to <8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i32 = zext <8 x i8> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i64 = zext <8 x i8> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i32 = zext <8 x i16> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i64 = zext <8 x i16> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i32_v8i64 = zext <8 x i32> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_v8i32 = zext <8 x i8> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i8_v8i64 = zext <8 x i8> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8i32 = zext <8 x i16> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16_v8i64 = zext <8 x i16> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8i64 = zext <8 x i32> undef to <8 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i8 = zext <8 x i1> undef to <8 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i16 = zext <8 x i1> undef to <8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i32 = zext <8 x i1> undef to <8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i64 = zext <8 x i1> undef to <8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i16 = zext <16 x i8> undef to <16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i32 = zext <16 x i8> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i64 = zext <16 x i8> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i32 = zext <16 x i16> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i64 = zext <16 x i16> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i32_v16i64 = zext <16 x i32> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8i32 = zext <8 x i1> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8i64 = zext <8 x i1> undef to <8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i8_v16i16 = zext <16 x i8> undef to <16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8_v16i32 = zext <16 x i8> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i8_v16i64 = zext <16 x i8> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16i32 = zext <16 x i16> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16_v16i64 = zext <16 x i16> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16i64 = zext <16 x i32> undef to <16 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i8 = zext <16 x i1> undef to <16 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i16 = zext <16 x i1> undef to <16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i32 = zext <16 x i1> undef to <16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i64 = zext <16 x i1> undef to <16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i16 = zext <32 x i8> undef to <32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i32 = zext <32 x i8> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i8_v32i64 = zext <32 x i8> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i16_v32i32 = zext <32 x i16> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i16_v32i64 = zext <32 x i16> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i32_v32i64 = zext <32 x i32> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i8 = zext <32 x i1> undef to <32 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i16 = zext <32 x i1> undef to <32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i32 = zext <32 x i1> undef to <32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_v32i64 = zext <32 x i1> undef to <32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i8_v64i16 = zext <64 x i8> undef to <64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i8_v64i32 = zext <64 x i8> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i8_v64i64 = zext <64 x i8> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i16_v64i32 = zext <64 x i16> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i16_v64i64 = zext <64 x i16> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64i32_v64i64 = zext <64 x i32> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i8 = zext <64 x i1> undef to <64 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i16 = zext <64 x i1> undef to <64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i1_v64i32 = zext <64 x i1> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64i1_v64i64 = zext <64 x i1> undef to <64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i8_v128i16 = zext <128 x i8> undef to <128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v128i8_v128i32 = zext <128 x i8> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v128i8_v128i64 = zext <128 x i8> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128i16_v128i32 = zext <128 x i16> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v128i16_v128i64 = zext <128 x i16> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128i32_v128i64 = zext <128 x i32> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v128i1_v128i8 = zext <128 x i1> undef to <128 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v128i1_v128i16 = zext <128 x i1> undef to <128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i1_v128i32 = zext <128 x i1> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %v128i1_v128i64 = zext <128 x i1> undef to <128 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i8_v256i16 = zext <256 x i8> undef to <256 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v256i8_v256i32 = zext <256 x i8> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %v256i8_v256i64 = zext <256 x i8> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v256i16_v256i32 = zext <256 x i16> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v256i16_v256i64 = zext <256 x i16> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %v256i32_v256i64 = zext <256 x i32> undef to <256 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v256i1_v256i8 = zext <256 x i1> undef to <256 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v256i1_v256i16 = zext <256 x i1> undef to <256 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i1_v256i32 = zext <256 x i1> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 46 for instruction: %v256i1_v256i64 = zext <256 x i1> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_v16i16 = zext <16 x i1> undef to <16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16i32 = zext <16 x i1> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16i64 = zext <16 x i1> undef to <16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i8_v32i16 = zext <32 x i8> undef to <32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i8_v32i32 = zext <32 x i8> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i8_v32i64 = zext <32 x i8> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32i32 = zext <32 x i16> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i16_v32i64 = zext <32 x i16> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32i64 = zext <32 x i32> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_v32i8 = zext <32 x i1> undef to <32 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_v32i16 = zext <32 x i1> undef to <32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32i32 = zext <32 x i1> undef to <32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32i64 = zext <32 x i1> undef to <32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i8_v64i16 = zext <64 x i8> undef to <64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i8_v64i32 = zext <64 x i8> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i8_v64i64 = zext <64 x i8> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64i32 = zext <64 x i16> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i16_v64i64 = zext <64 x i16> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64i64 = zext <64 x i32> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i1_v64i8 = zext <64 x i1> undef to <64 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i1_v64i16 = zext <64 x i1> undef to <64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64i32 = zext <64 x i1> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64i64 = zext <64 x i1> undef to <64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v128i8_v128i16 = zext <128 x i8> undef to <128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v128i8_v128i32 = zext <128 x i8> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %v128i8_v128i64 = zext <128 x i8> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128i32 = zext <128 x i16> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v128i16_v128i64 = zext <128 x i16> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128i64 = zext <128 x i32> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v128i1_v128i8 = zext <128 x i1> undef to <128 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v128i1_v128i16 = zext <128 x i1> undef to <128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128i32 = zext <128 x i1> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128i64 = zext <128 x i1> undef to <128 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v256i8_v256i16 = zext <256 x i8> undef to <256 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v256i8_v256i32 = zext <256 x i8> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 142 for instruction: %v256i8_v256i64 = zext <256 x i8> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v256i16_v256i32 = zext <256 x i16> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 140 for instruction: %v256i16_v256i64 = zext <256 x i16> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 136 for instruction: %v256i32_v256i64 = zext <256 x i32> undef to <256 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v256i1_v256i8 = zext <256 x i1> undef to <256 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %v256i1_v256i16 = zext <256 x i1> undef to <256 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %v256i1_v256i32 = zext <256 x i1> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 270 for instruction: %v256i1_v256i64 = zext <256 x i1> undef to <256 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i16 = zext <vscale x 1 x i8> undef to <vscale x 1 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i32 = zext <vscale x 1 x i8> undef to <vscale x 1 x i32> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i64 = zext <vscale x 1 x i8> undef to <vscale x 1 x i64> @@ -602,73 +602,73 @@ define void @zext() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i1_nxv1i64 = zext <vscale x 1 x i1> undef to <vscale x 1 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i16 = zext <vscale x 2 x i8> undef to <vscale x 2 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i32 = zext <vscale x 2 x i8> undef to <vscale x 2 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i64 = zext <vscale x 2 x i8> undef to <vscale x 2 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2i64 = zext <vscale x 2 x i8> undef to <vscale x 2 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i32 = zext <vscale x 2 x i16> undef to <vscale x 2 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i64 = zext <vscale x 2 x i16> undef to <vscale x 2 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2i64 = zext <vscale x 2 x i32> undef to <vscale x 2 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i16_nxv2i64 = zext <vscale x 2 x i16> undef to <vscale x 2 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2i64 = zext <vscale x 2 x i32> undef to <vscale x 2 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i8 = zext <vscale x 2 x i1> undef to <vscale x 2 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i16 = zext <vscale x 2 x i1> undef to <vscale x 2 x i16> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i32 = zext <vscale x 2 x i1> undef to <vscale x 2 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i64 = zext <vscale x 2 x i1> undef to <vscale x 2 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2i64 = zext <vscale x 2 x i1> undef to <vscale x 2 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i16 = zext <vscale x 4 x i8> undef to <vscale x 4 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i32 = zext <vscale x 4 x i8> undef to <vscale x 4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i64 = zext <vscale x 4 x i8> undef to <vscale x 4 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i32 = zext <vscale x 4 x i16> undef to <vscale x 4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i64 = zext <vscale x 4 x i16> undef to <vscale x 4 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i32_nxv4i64 = zext <vscale x 4 x i32> undef to <vscale x 4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i8_nxv4i32 = zext <vscale x 4 x i8> undef to <vscale x 4 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i8_nxv4i64 = zext <vscale x 4 x i8> undef to <vscale x 4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4i32 = zext <vscale x 4 x i16> undef to <vscale x 4 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i16_nxv4i64 = zext <vscale x 4 x i16> undef to <vscale x 4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4i64 = zext <vscale x 4 x i32> undef to <vscale x 4 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i8 = zext <vscale x 4 x i1> undef to <vscale x 4 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i16 = zext <vscale x 4 x i1> undef to <vscale x 4 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i32 = zext <vscale x 4 x i1> undef to <vscale x 4 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i64 = zext <vscale x 4 x i1> undef to <vscale x 4 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i16 = zext <vscale x 8 x i8> undef to <vscale x 8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i32 = zext <vscale x 8 x i8> undef to <vscale x 8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i64 = zext <vscale x 8 x i8> undef to <vscale x 8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i32 = zext <vscale x 8 x i16> undef to <vscale x 8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i64 = zext <vscale x 8 x i16> undef to <vscale x 8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i32_nxv8i64 = zext <vscale x 8 x i32> undef to <vscale x 8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4i32 = zext <vscale x 4 x i1> undef to <vscale x 4 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4i64 = zext <vscale x 4 x i1> undef to <vscale x 4 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i8_nxv8i16 = zext <vscale x 8 x i8> undef to <vscale x 8 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i8_nxv8i32 = zext <vscale x 8 x i8> undef to <vscale x 8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i8_nxv8i64 = zext <vscale x 8 x i8> undef to <vscale x 8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8i32 = zext <vscale x 8 x i16> undef to <vscale x 8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i16_nxv8i64 = zext <vscale x 8 x i16> undef to <vscale x 8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8i64 = zext <vscale x 8 x i32> undef to <vscale x 8 x i64> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i8 = zext <vscale x 8 x i1> undef to <vscale x 8 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i16 = zext <vscale x 8 x i1> undef to <vscale x 8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i32 = zext <vscale x 8 x i1> undef to <vscale x 8 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i64 = zext <vscale x 8 x i1> undef to <vscale x 8 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i16 = zext <vscale x 16 x i8> undef to <vscale x 16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i32 = zext <vscale x 16 x i8> undef to <vscale x 16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i8_nxv16i64 = zext <vscale x 16 x i8> undef to <vscale x 16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i16_nxv16i32 = zext <vscale x 16 x i16> undef to <vscale x 16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i16_nxv16i64 = zext <vscale x 16 x i16> undef to <vscale x 16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i32_nxv16i64 = zext <vscale x 16 x i32> undef to <vscale x 16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i8 = zext <vscale x 16 x i1> undef to <vscale x 16 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i16 = zext <vscale x 16 x i1> undef to <vscale x 16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i32 = zext <vscale x 16 x i1> undef to <vscale x 16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_nxv16i64 = zext <vscale x 16 x i1> undef to <vscale x 16 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv32i8_nxv32i16 = zext <vscale x 32 x i8> undef to <vscale x 32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i8_nxv32i32 = zext <vscale x 32 x i8> undef to <vscale x 32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i8_nxv32i64 = zext <vscale x 32 x i8> undef to <vscale x 32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i16_nxv32i32 = zext <vscale x 32 x i16> undef to <vscale x 32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i16_nxv32i64 = zext <vscale x 32 x i16> undef to <vscale x 32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i32_nxv32i64 = zext <vscale x 32 x i32> undef to <vscale x 32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i8 = zext <vscale x 32 x i1> undef to <vscale x 32 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i16 = zext <vscale x 32 x i1> undef to <vscale x 32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_nxv32i32 = zext <vscale x 32 x i1> undef to <vscale x 32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_nxv32i64 = zext <vscale x 32 x i1> undef to <vscale x 32 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv64i8_nxv64i16 = zext <vscale x 64 x i8> undef to <vscale x 64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv64i8_nxv64i32 = zext <vscale x 64 x i8> undef to <vscale x 64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_nxv8i16 = zext <vscale x 8 x i1> undef to <vscale x 8 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8i32 = zext <vscale x 8 x i1> undef to <vscale x 8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8i64 = zext <vscale x 8 x i1> undef to <vscale x 8 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i8_nxv16i16 = zext <vscale x 16 x i8> undef to <vscale x 16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i8_nxv16i32 = zext <vscale x 16 x i8> undef to <vscale x 16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i8_nxv16i64 = zext <vscale x 16 x i8> undef to <vscale x 16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16i32 = zext <vscale x 16 x i16> undef to <vscale x 16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i16_nxv16i64 = zext <vscale x 16 x i16> undef to <vscale x 16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16i64 = zext <vscale x 16 x i32> undef to <vscale x 16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_nxv16i8 = zext <vscale x 16 x i1> undef to <vscale x 16 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_nxv16i16 = zext <vscale x 16 x i1> undef to <vscale x 16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16i32 = zext <vscale x 16 x i1> undef to <vscale x 16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16i64 = zext <vscale x 16 x i1> undef to <vscale x 16 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i8_nxv32i16 = zext <vscale x 32 x i8> undef to <vscale x 32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i8_nxv32i32 = zext <vscale x 32 x i8> undef to <vscale x 32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i8_nxv32i64 = zext <vscale x 32 x i8> undef to <vscale x 32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32i32 = zext <vscale x 32 x i16> undef to <vscale x 32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i16_nxv32i64 = zext <vscale x 32 x i16> undef to <vscale x 32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32i64 = zext <vscale x 32 x i32> undef to <vscale x 32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i1_nxv32i8 = zext <vscale x 32 x i1> undef to <vscale x 32 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv32i1_nxv32i16 = zext <vscale x 32 x i1> undef to <vscale x 32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32i32 = zext <vscale x 32 x i1> undef to <vscale x 32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32i64 = zext <vscale x 32 x i1> undef to <vscale x 32 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv64i8_nxv64i16 = zext <vscale x 64 x i8> undef to <vscale x 64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv64i8_nxv64i32 = zext <vscale x 64 x i8> undef to <vscale x 64 x i32> ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv64i8_nxv64i64 = zext <vscale x 64 x i8> undef to <vscale x 64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64i16_nxv64i32 = zext <vscale x 64 x i16> undef to <vscale x 64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv64i16_nxv64i64 = zext <vscale x 64 x i16> undef to <vscale x 64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv64i32_nxv64i64 = zext <vscale x 64 x i32> undef to <vscale x 64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv64i1_nxv64i8 = zext <vscale x 64 x i1> undef to <vscale x 64 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv64i1_nxv64i16 = zext <vscale x 64 x i1> undef to <vscale x 64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i1_nxv64i32 = zext <vscale x 64 x i1> undef to <vscale x 64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64i32 = zext <vscale x 64 x i16> undef to <vscale x 64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %nxv64i16_nxv64i64 = zext <vscale x 64 x i16> undef to <vscale x 64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 69 for instruction: %nxv64i32_nxv64i64 = zext <vscale x 64 x i32> undef to <vscale x 64 x i64> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv64i1_nxv64i8 = zext <vscale x 64 x i1> undef to <vscale x 64 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv64i1_nxv64i16 = zext <vscale x 64 x i1> undef to <vscale x 64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64i32 = zext <vscale x 64 x i1> undef to <vscale x 64 x i32> ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv64i1_nxv64i64 = zext <vscale x 64 x i1> undef to <vscale x 64 x i64> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv128i8_nxv128i16 = zext <vscale x 128 x i8> undef to <vscale x 128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv128i8_nxv128i32 = zext <vscale x 128 x i8> undef to <vscale x 128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv128i8_nxv128i16 = zext <vscale x 128 x i8> undef to <vscale x 128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv128i8_nxv128i32 = zext <vscale x 128 x i8> undef to <vscale x 128 x i32> ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i8_nxv128i128 = zext <vscale x 128 x i8> undef to <vscale x 128 x i128> -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv128i16_nxv128i32 = zext <vscale x 128 x i16> undef to <vscale x 128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv128i16_nxv128i32 = zext <vscale x 128 x i16> undef to <vscale x 128 x i32> ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i16_nxv128i128 = zext <vscale x 128 x i16> undef to <vscale x 128 x i128> ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i32_nxv128i128 = zext <vscale x 128 x i32> undef to <vscale x 128 x i128> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv128i1_nxv128i8 = zext <vscale x 128 x i1> undef to <vscale x 128 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv128i1_nxv128i16 = zext <vscale x 128 x i1> undef to <vscale x 128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv128i1_nxv128i32 = zext <vscale x 128 x i1> undef to <vscale x 128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %nxv128i1_nxv128i8 = zext <vscale x 128 x i1> undef to <vscale x 128 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %nxv128i1_nxv128i16 = zext <vscale x 128 x i1> undef to <vscale x 128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %nxv128i1_nxv128i32 = zext <vscale x 128 x i1> undef to <vscale x 128 x i32> ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv128i1_nxv128i128 = zext <vscale x 128 x i1> undef to <vscale x 128 x i128> ; RV32-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; @@ -685,74 +685,74 @@ define void @zext() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i1_v2i64 = zext <2 x i1> undef to <2 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i16 = zext <4 x i8> undef to <4 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i32 = zext <4 x i8> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_v4i64 = zext <4 x i8> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4i64 = zext <4 x i8> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i32 = zext <4 x i16> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i16_v4i64 = zext <4 x i16> undef to <4 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i32_v4i64 = zext <4 x i32> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16_v4i64 = zext <4 x i16> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4i64 = zext <4 x i32> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i8 = zext <4 x i1> undef to <4 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i16 = zext <4 x i1> undef to <4 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i32 = zext <4 x i1> undef to <4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i1_v4i64 = zext <4 x i1> undef to <4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_v4i64 = zext <4 x i1> undef to <4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i16 = zext <8 x i8> undef to <8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i32 = zext <8 x i8> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_v8i64 = zext <8 x i8> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i32 = zext <8 x i16> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i64 = zext <8 x i16> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i32_v8i64 = zext <8 x i32> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_v8i32 = zext <8 x i8> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i8_v8i64 = zext <8 x i8> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8i32 = zext <8 x i16> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i16_v8i64 = zext <8 x i16> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8i64 = zext <8 x i32> undef to <8 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i8 = zext <8 x i1> undef to <8 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i16 = zext <8 x i1> undef to <8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i32 = zext <8 x i1> undef to <8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i1_v8i64 = zext <8 x i1> undef to <8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i16 = zext <16 x i8> undef to <16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i32 = zext <16 x i8> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i8_v16i64 = zext <16 x i8> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i32 = zext <16 x i16> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i64 = zext <16 x i16> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i32_v16i64 = zext <16 x i32> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_v8i32 = zext <8 x i1> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i1_v8i64 = zext <8 x i1> undef to <8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i8_v16i16 = zext <16 x i8> undef to <16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i8_v16i32 = zext <16 x i8> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i8_v16i64 = zext <16 x i8> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i16_v16i32 = zext <16 x i16> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i16_v16i64 = zext <16 x i16> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i32_v16i64 = zext <16 x i32> undef to <16 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i8 = zext <16 x i1> undef to <16 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i16 = zext <16 x i1> undef to <16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i32 = zext <16 x i1> undef to <16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i1_v16i64 = zext <16 x i1> undef to <16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i16 = zext <32 x i8> undef to <32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i8_v32i32 = zext <32 x i8> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i8_v32i64 = zext <32 x i8> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i16_v32i32 = zext <32 x i16> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i16_v32i64 = zext <32 x i16> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i32_v32i64 = zext <32 x i32> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i8 = zext <32 x i1> undef to <32 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i16 = zext <32 x i1> undef to <32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i1_v32i32 = zext <32 x i1> undef to <32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_v32i64 = zext <32 x i1> undef to <32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i8_v64i16 = zext <64 x i8> undef to <64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i8_v64i32 = zext <64 x i8> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i8_v64i64 = zext <64 x i8> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i16_v64i32 = zext <64 x i16> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v64i16_v64i64 = zext <64 x i16> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64i32_v64i64 = zext <64 x i32> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i8 = zext <64 x i1> undef to <64 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i1_v64i16 = zext <64 x i1> undef to <64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i1_v64i32 = zext <64 x i1> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64i1_v64i64 = zext <64 x i1> undef to <64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i8_v128i16 = zext <128 x i8> undef to <128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v128i8_v128i32 = zext <128 x i8> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v128i8_v128i64 = zext <128 x i8> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128i16_v128i32 = zext <128 x i16> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v128i16_v128i64 = zext <128 x i16> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128i32_v128i64 = zext <128 x i32> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v128i1_v128i8 = zext <128 x i1> undef to <128 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v128i1_v128i16 = zext <128 x i1> undef to <128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i1_v128i32 = zext <128 x i1> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %v128i1_v128i64 = zext <128 x i1> undef to <128 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i8_v256i16 = zext <256 x i8> undef to <256 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %v256i8_v256i32 = zext <256 x i8> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 30 for instruction: %v256i8_v256i64 = zext <256 x i8> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v256i16_v256i32 = zext <256 x i16> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 28 for instruction: %v256i16_v256i64 = zext <256 x i16> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %v256i32_v256i64 = zext <256 x i32> undef to <256 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v256i1_v256i8 = zext <256 x i1> undef to <256 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v256i1_v256i16 = zext <256 x i1> undef to <256 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i1_v256i32 = zext <256 x i1> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 46 for instruction: %v256i1_v256i64 = zext <256 x i1> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_v16i16 = zext <16 x i1> undef to <16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16i1_v16i32 = zext <16 x i1> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v16i1_v16i64 = zext <16 x i1> undef to <16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i8_v32i16 = zext <32 x i8> undef to <32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i8_v32i32 = zext <32 x i8> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i8_v32i64 = zext <32 x i8> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i16_v32i32 = zext <32 x i16> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i16_v32i64 = zext <32 x i16> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i32_v32i64 = zext <32 x i32> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_v32i8 = zext <32 x i1> undef to <32 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i1_v32i16 = zext <32 x i1> undef to <32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i1_v32i32 = zext <32 x i1> undef to <32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v32i1_v32i64 = zext <32 x i1> undef to <32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i8_v64i16 = zext <64 x i8> undef to <64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i8_v64i32 = zext <64 x i8> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i8_v64i64 = zext <64 x i8> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64i16_v64i32 = zext <64 x i16> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v64i16_v64i64 = zext <64 x i16> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64i32_v64i64 = zext <64 x i32> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i1_v64i8 = zext <64 x i1> undef to <64 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i1_v64i16 = zext <64 x i1> undef to <64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i1_v64i32 = zext <64 x i1> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v64i1_v64i64 = zext <64 x i1> undef to <64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v128i8_v128i16 = zext <128 x i8> undef to <128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %v128i8_v128i32 = zext <128 x i8> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %v128i8_v128i64 = zext <128 x i8> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128i16_v128i32 = zext <128 x i16> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v128i16_v128i64 = zext <128 x i16> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128i32_v128i64 = zext <128 x i32> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v128i1_v128i8 = zext <128 x i1> undef to <128 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v128i1_v128i16 = zext <128 x i1> undef to <128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i1_v128i32 = zext <128 x i1> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %v128i1_v128i64 = zext <128 x i1> undef to <128 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v256i8_v256i16 = zext <256 x i8> undef to <256 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %v256i8_v256i32 = zext <256 x i8> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 142 for instruction: %v256i8_v256i64 = zext <256 x i8> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v256i16_v256i32 = zext <256 x i16> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 140 for instruction: %v256i16_v256i64 = zext <256 x i16> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 136 for instruction: %v256i32_v256i64 = zext <256 x i32> undef to <256 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v256i1_v256i8 = zext <256 x i1> undef to <256 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %v256i1_v256i16 = zext <256 x i1> undef to <256 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %v256i1_v256i32 = zext <256 x i1> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 270 for instruction: %v256i1_v256i64 = zext <256 x i1> undef to <256 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i16 = zext <vscale x 1 x i8> undef to <vscale x 1 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i32 = zext <vscale x 1 x i8> undef to <vscale x 1 x i32> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i8_nxv1i64 = zext <vscale x 1 x i8> undef to <vscale x 1 x i64> @@ -765,73 +765,73 @@ define void @zext() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i1_nxv1i64 = zext <vscale x 1 x i1> undef to <vscale x 1 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i16 = zext <vscale x 2 x i8> undef to <vscale x 2 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i32 = zext <vscale x 2 x i8> undef to <vscale x 2 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i8_nxv2i64 = zext <vscale x 2 x i8> undef to <vscale x 2 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2i64 = zext <vscale x 2 x i8> undef to <vscale x 2 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i32 = zext <vscale x 2 x i16> undef to <vscale x 2 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i16_nxv2i64 = zext <vscale x 2 x i16> undef to <vscale x 2 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2i32_nxv2i64 = zext <vscale x 2 x i32> undef to <vscale x 2 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i16_nxv2i64 = zext <vscale x 2 x i16> undef to <vscale x 2 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2i64 = zext <vscale x 2 x i32> undef to <vscale x 2 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i8 = zext <vscale x 2 x i1> undef to <vscale x 2 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i16 = zext <vscale x 2 x i1> undef to <vscale x 2 x i16> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i32 = zext <vscale x 2 x i1> undef to <vscale x 2 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i1_nxv2i64 = zext <vscale x 2 x i1> undef to <vscale x 2 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_nxv2i64 = zext <vscale x 2 x i1> undef to <vscale x 2 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i16 = zext <vscale x 4 x i8> undef to <vscale x 4 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i32 = zext <vscale x 4 x i8> undef to <vscale x 4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i8_nxv4i64 = zext <vscale x 4 x i8> undef to <vscale x 4 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i32 = zext <vscale x 4 x i16> undef to <vscale x 4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i64 = zext <vscale x 4 x i16> undef to <vscale x 4 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i32_nxv4i64 = zext <vscale x 4 x i32> undef to <vscale x 4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i8_nxv4i32 = zext <vscale x 4 x i8> undef to <vscale x 4 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i8_nxv4i64 = zext <vscale x 4 x i8> undef to <vscale x 4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4i32 = zext <vscale x 4 x i16> undef to <vscale x 4 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i16_nxv4i64 = zext <vscale x 4 x i16> undef to <vscale x 4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4i64 = zext <vscale x 4 x i32> undef to <vscale x 4 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i8 = zext <vscale x 4 x i1> undef to <vscale x 4 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i16 = zext <vscale x 4 x i1> undef to <vscale x 4 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i32 = zext <vscale x 4 x i1> undef to <vscale x 4 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i1_nxv4i64 = zext <vscale x 4 x i1> undef to <vscale x 4 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i16 = zext <vscale x 8 x i8> undef to <vscale x 8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i32 = zext <vscale x 8 x i8> undef to <vscale x 8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i8_nxv8i64 = zext <vscale x 8 x i8> undef to <vscale x 8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i32 = zext <vscale x 8 x i16> undef to <vscale x 8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i64 = zext <vscale x 8 x i16> undef to <vscale x 8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i32_nxv8i64 = zext <vscale x 8 x i32> undef to <vscale x 8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_nxv4i32 = zext <vscale x 4 x i1> undef to <vscale x 4 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i1_nxv4i64 = zext <vscale x 4 x i1> undef to <vscale x 4 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i8_nxv8i16 = zext <vscale x 8 x i8> undef to <vscale x 8 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i8_nxv8i32 = zext <vscale x 8 x i8> undef to <vscale x 8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i8_nxv8i64 = zext <vscale x 8 x i8> undef to <vscale x 8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8i32 = zext <vscale x 8 x i16> undef to <vscale x 8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i16_nxv8i64 = zext <vscale x 8 x i16> undef to <vscale x 8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8i64 = zext <vscale x 8 x i32> undef to <vscale x 8 x i64> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i8 = zext <vscale x 8 x i1> undef to <vscale x 8 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i16 = zext <vscale x 8 x i1> undef to <vscale x 8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i32 = zext <vscale x 8 x i1> undef to <vscale x 8 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i1_nxv8i64 = zext <vscale x 8 x i1> undef to <vscale x 8 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i16 = zext <vscale x 16 x i8> undef to <vscale x 16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i8_nxv16i32 = zext <vscale x 16 x i8> undef to <vscale x 16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i8_nxv16i64 = zext <vscale x 16 x i8> undef to <vscale x 16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i16_nxv16i32 = zext <vscale x 16 x i16> undef to <vscale x 16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i16_nxv16i64 = zext <vscale x 16 x i16> undef to <vscale x 16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i32_nxv16i64 = zext <vscale x 16 x i32> undef to <vscale x 16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i8 = zext <vscale x 16 x i1> undef to <vscale x 16 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i16 = zext <vscale x 16 x i1> undef to <vscale x 16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i1_nxv16i32 = zext <vscale x 16 x i1> undef to <vscale x 16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_nxv16i64 = zext <vscale x 16 x i1> undef to <vscale x 16 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv32i8_nxv32i16 = zext <vscale x 32 x i8> undef to <vscale x 32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i8_nxv32i32 = zext <vscale x 32 x i8> undef to <vscale x 32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i8_nxv32i64 = zext <vscale x 32 x i8> undef to <vscale x 32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i16_nxv32i32 = zext <vscale x 32 x i16> undef to <vscale x 32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i16_nxv32i64 = zext <vscale x 32 x i16> undef to <vscale x 32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i32_nxv32i64 = zext <vscale x 32 x i32> undef to <vscale x 32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i8 = zext <vscale x 32 x i1> undef to <vscale x 32 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i1_nxv32i16 = zext <vscale x 32 x i1> undef to <vscale x 32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_nxv32i32 = zext <vscale x 32 x i1> undef to <vscale x 32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i1_nxv32i64 = zext <vscale x 32 x i1> undef to <vscale x 32 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv64i8_nxv64i16 = zext <vscale x 64 x i8> undef to <vscale x 64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv64i8_nxv64i32 = zext <vscale x 64 x i8> undef to <vscale x 64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv64i8_nxv64i64 = zext <vscale x 64 x i8> undef to <vscale x 64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64i16_nxv64i32 = zext <vscale x 64 x i16> undef to <vscale x 64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv64i16_nxv64i64 = zext <vscale x 64 x i16> undef to <vscale x 64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv64i32_nxv64i64 = zext <vscale x 64 x i32> undef to <vscale x 64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv64i1_nxv64i8 = zext <vscale x 64 x i1> undef to <vscale x 64 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv64i1_nxv64i16 = zext <vscale x 64 x i1> undef to <vscale x 64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i1_nxv64i32 = zext <vscale x 64 x i1> undef to <vscale x 64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %nxv64i1_nxv64i64 = zext <vscale x 64 x i1> undef to <vscale x 64 x i64> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv128i8_nxv128i16 = zext <vscale x 128 x i8> undef to <vscale x 128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %nxv128i8_nxv128i32 = zext <vscale x 128 x i8> undef to <vscale x 128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_nxv8i16 = zext <vscale x 8 x i1> undef to <vscale x 8 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i1_nxv8i32 = zext <vscale x 8 x i1> undef to <vscale x 8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i1_nxv8i64 = zext <vscale x 8 x i1> undef to <vscale x 8 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i8_nxv16i16 = zext <vscale x 16 x i8> undef to <vscale x 16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i8_nxv16i32 = zext <vscale x 16 x i8> undef to <vscale x 16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i8_nxv16i64 = zext <vscale x 16 x i8> undef to <vscale x 16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16i32 = zext <vscale x 16 x i16> undef to <vscale x 16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i16_nxv16i64 = zext <vscale x 16 x i16> undef to <vscale x 16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16i32_nxv16i64 = zext <vscale x 16 x i32> undef to <vscale x 16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_nxv16i8 = zext <vscale x 16 x i1> undef to <vscale x 16 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i1_nxv16i16 = zext <vscale x 16 x i1> undef to <vscale x 16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i1_nxv16i32 = zext <vscale x 16 x i1> undef to <vscale x 16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i1_nxv16i64 = zext <vscale x 16 x i1> undef to <vscale x 16 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i8_nxv32i16 = zext <vscale x 32 x i8> undef to <vscale x 32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i8_nxv32i32 = zext <vscale x 32 x i8> undef to <vscale x 32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i8_nxv32i64 = zext <vscale x 32 x i8> undef to <vscale x 32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i16_nxv32i32 = zext <vscale x 32 x i16> undef to <vscale x 32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv32i16_nxv32i64 = zext <vscale x 32 x i16> undef to <vscale x 32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32i32_nxv32i64 = zext <vscale x 32 x i32> undef to <vscale x 32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i1_nxv32i8 = zext <vscale x 32 x i1> undef to <vscale x 32 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv32i1_nxv32i16 = zext <vscale x 32 x i1> undef to <vscale x 32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i1_nxv32i32 = zext <vscale x 32 x i1> undef to <vscale x 32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i1_nxv32i64 = zext <vscale x 32 x i1> undef to <vscale x 32 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv64i8_nxv64i16 = zext <vscale x 64 x i8> undef to <vscale x 64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 35 for instruction: %nxv64i8_nxv64i32 = zext <vscale x 64 x i8> undef to <vscale x 64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 71 for instruction: %nxv64i8_nxv64i64 = zext <vscale x 64 x i8> undef to <vscale x 64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64i16_nxv64i32 = zext <vscale x 64 x i16> undef to <vscale x 64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv64i16_nxv64i64 = zext <vscale x 64 x i16> undef to <vscale x 64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64i32_nxv64i64 = zext <vscale x 64 x i32> undef to <vscale x 64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv64i1_nxv64i8 = zext <vscale x 64 x i1> undef to <vscale x 64 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv64i1_nxv64i16 = zext <vscale x 64 x i1> undef to <vscale x 64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i1_nxv64i32 = zext <vscale x 64 x i1> undef to <vscale x 64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %nxv64i1_nxv64i64 = zext <vscale x 64 x i1> undef to <vscale x 64 x i64> +; RV64-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv128i8_nxv128i16 = zext <vscale x 128 x i8> undef to <vscale x 128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 70 for instruction: %nxv128i8_nxv128i32 = zext <vscale x 128 x i8> undef to <vscale x 128 x i32> ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i8_nxv128i128 = zext <vscale x 128 x i8> undef to <vscale x 128 x i128> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv128i16_nxv128i32 = zext <vscale x 128 x i16> undef to <vscale x 128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv128i16_nxv128i32 = zext <vscale x 128 x i16> undef to <vscale x 128 x i32> ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i16_nxv128i128 = zext <vscale x 128 x i16> undef to <vscale x 128 x i128> ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i32_nxv128i128 = zext <vscale x 128 x i32> undef to <vscale x 128 x i128> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv128i1_nxv128i8 = zext <vscale x 128 x i1> undef to <vscale x 128 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv128i1_nxv128i16 = zext <vscale x 128 x i1> undef to <vscale x 128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv128i1_nxv128i32 = zext <vscale x 128 x i1> undef to <vscale x 128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %nxv128i1_nxv128i8 = zext <vscale x 128 x i1> undef to <vscale x 128 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %nxv128i1_nxv128i16 = zext <vscale x 128 x i1> undef to <vscale x 128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %nxv128i1_nxv128i32 = zext <vscale x 128 x i1> undef to <vscale x 128 x i32> ; RV64-NEXT: Cost Model: Invalid cost for instruction: %nxv128i1_nxv128i128 = zext <vscale x 128 x i1> undef to <vscale x 128 x i128> ; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; @@ -1035,17 +1035,17 @@ define void @trunc() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4i1 = trunc <4 x i8> undef to <4 x i1> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16_v4i1 = trunc <4 x i16> undef to <4 x i1> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4i1 = trunc <4 x i32> undef to <4 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i64_v4i1 = trunc <4 x i64> undef to <4 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i64_v4i1 = trunc <4 x i64> undef to <4 x i1> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i8 = trunc <8 x i16> undef to <8 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_v8i8 = trunc <8 x i32> undef to <8 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i64_v8i8 = trunc <8 x i64> undef to <8 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i64_v8i8 = trunc <8 x i64> undef to <8 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i32_v8i16 = trunc <8 x i32> undef to <8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i64_v8i16 = trunc <8 x i64> undef to <8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i64_v8i32 = trunc <8 x i64> undef to <8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i64_v8i16 = trunc <8 x i64> undef to <8 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i64_v8i32 = trunc <8 x i64> undef to <8 x i32> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_v8i1 = trunc <8 x i8> undef to <8 x i1> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8i1 = trunc <8 x i16> undef to <8 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_v8i1 = trunc <8 x i32> undef to <8 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i64_v8i1 = trunc <8 x i64> undef to <8 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8i1 = trunc <8 x i32> undef to <8 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i64_v8i1 = trunc <8 x i64> undef to <8 x i1> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i8 = trunc <2 x i16> undef to <2 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i32_v16i8 = trunc <2 x i32> undef to <2 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16i64_v16i8 = trunc <2 x i64> undef to <2 x i8> @@ -1057,44 +1057,44 @@ define void @trunc() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i32_v16i1 = trunc <2 x i32> undef to <2 x i1> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i64_v16i1 = trunc <2 x i64> undef to <2 x i1> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i16_v32i8 = trunc <16 x i16> undef to <16 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i32_v32i8 = trunc <16 x i32> undef to <16 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i64_v32i8 = trunc <16 x i64> undef to <16 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i32_v32i16 = trunc <16 x i32> undef to <16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i64_v32i16 = trunc <16 x i64> undef to <16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i64_v32i32 = trunc <16 x i64> undef to <16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i32_v32i8 = trunc <16 x i32> undef to <16 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i64_v32i8 = trunc <16 x i64> undef to <16 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i32_v32i16 = trunc <16 x i32> undef to <16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i64_v32i16 = trunc <16 x i64> undef to <16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i64_v32i32 = trunc <16 x i64> undef to <16 x i32> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i8_v32i1 = trunc <16 x i8> undef to <16 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i16_v32i1 = trunc <16 x i16> undef to <16 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i32_v32i1 = trunc <16 x i32> undef to <16 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i64_v32i1 = trunc <16 x i64> undef to <16 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i16_v64i8 = trunc <64 x i16> undef to <64 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i32_v64i8 = trunc <64 x i32> undef to <64 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v64i64_v64i8 = trunc <64 x i64> undef to <64 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i32_v64i16 = trunc <64 x i32> undef to <64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64i64_v64i16 = trunc <64 x i64> undef to <64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64i64_v64i32 = trunc <64 x i64> undef to <64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i8_v64i1 = trunc <64 x i8> undef to <64 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i16_v64i1 = trunc <64 x i16> undef to <64 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i32_v64i1 = trunc <64 x i32> undef to <64 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i16_v32i1 = trunc <16 x i16> undef to <16 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i32_v32i1 = trunc <16 x i32> undef to <16 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i64_v32i1 = trunc <16 x i64> undef to <16 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v64i16_v64i8 = trunc <64 x i16> undef to <64 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v64i32_v64i8 = trunc <64 x i32> undef to <64 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v64i64_v64i8 = trunc <64 x i64> undef to <64 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v64i32_v64i16 = trunc <64 x i32> undef to <64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %v64i64_v64i16 = trunc <64 x i64> undef to <64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v64i64_v64i32 = trunc <64 x i64> undef to <64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i8_v64i1 = trunc <64 x i8> undef to <64 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i16_v64i1 = trunc <64 x i16> undef to <64 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v64i32_v64i1 = trunc <64 x i32> undef to <64 x i1> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i64_v64i1 = trunc <64 x i64> undef to <64 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i16_v128i8 = trunc <128 x i16> undef to <128 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i32_v128i8 = trunc <128 x i32> undef to <128 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v128i64_v128i8 = trunc <128 x i64> undef to <128 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128i32_v128i16 = trunc <128 x i32> undef to <128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v128i64_v128i16 = trunc <128 x i64> undef to <128 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128i64_v128i32 = trunc <128 x i64> undef to <128 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v128i8_v128i1 = trunc <128 x i8> undef to <128 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v128i16_v128i1 = trunc <128 x i16> undef to <128 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i32_v128i1 = trunc <128 x i32> undef to <128 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v128i16_v128i8 = trunc <128 x i16> undef to <128 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %v128i32_v128i8 = trunc <128 x i32> undef to <128 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v128i64_v128i8 = trunc <128 x i64> undef to <128 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v128i32_v128i16 = trunc <128 x i32> undef to <128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %v128i64_v128i16 = trunc <128 x i64> undef to <128 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %v128i64_v128i32 = trunc <128 x i64> undef to <128 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v128i8_v128i1 = trunc <128 x i8> undef to <128 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v128i16_v128i1 = trunc <128 x i16> undef to <128 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %v128i32_v128i1 = trunc <128 x i32> undef to <128 x i1> ; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i64_v128i1 = trunc <128 x i64> undef to <128 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i16_v256i8 = trunc <256 x i16> undef to <256 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i32_v256i8 = trunc <256 x i32> undef to <256 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 62 for instruction: %v256i64_v256i8 = trunc <256 x i64> undef to <256 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v256i32_v256i16 = trunc <256 x i32> undef to <256 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 44 for instruction: %v256i64_v256i16 = trunc <256 x i64> undef to <256 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %v256i64_v256i32 = trunc <256 x i64> undef to <256 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v256i8_v256i1 = trunc <256 x i8> undef to <256 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v256i16_v256i1 = trunc <256 x i16> undef to <256 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i32_v256i1 = trunc <256 x i32> undef to <256 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v256i16_v256i8 = trunc <256 x i16> undef to <256 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %v256i32_v256i8 = trunc <256 x i32> undef to <256 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 126 for instruction: %v256i64_v256i8 = trunc <256 x i64> undef to <256 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %v256i32_v256i16 = trunc <256 x i32> undef to <256 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 108 for instruction: %v256i64_v256i16 = trunc <256 x i64> undef to <256 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 72 for instruction: %v256i64_v256i32 = trunc <256 x i64> undef to <256 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v256i8_v256i1 = trunc <256 x i8> undef to <256 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %v256i16_v256i1 = trunc <256 x i16> undef to <256 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 134 for instruction: %v256i32_v256i1 = trunc <256 x i32> undef to <256 x i1> ; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i64_v256i1 = trunc <256 x i64> undef to <256 x i1> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i16_nxv1i8 = trunc <vscale x 1 x i16> undef to <vscale x 1 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1i32_nxv1i8 = trunc <vscale x 1 x i32> undef to <vscale x 1 x i8> @@ -1115,56 +1115,56 @@ define void @trunc() { ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2i1 = trunc <vscale x 2 x i8> undef to <vscale x 2 x i1> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i16_nxv2i1 = trunc <vscale x 2 x i16> undef to <vscale x 2 x i1> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2i1 = trunc <vscale x 2 x i32> undef to <vscale x 2 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i64_nxv2i1 = trunc <vscale x 2 x i64> undef to <vscale x 2 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i64_nxv2i1 = trunc <vscale x 2 x i64> undef to <vscale x 2 x i1> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i8 = trunc <vscale x 4 x i16> undef to <vscale x 4 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i32_nxv4i8 = trunc <vscale x 4 x i32> undef to <vscale x 4 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i64_nxv4i8 = trunc <vscale x 4 x i64> undef to <vscale x 4 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i64_nxv4i8 = trunc <vscale x 4 x i64> undef to <vscale x 4 x i8> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i32_nxv4i16 = trunc <vscale x 4 x i32> undef to <vscale x 4 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i64_nxv4i16 = trunc <vscale x 4 x i64> undef to <vscale x 4 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i64_nxv4i32 = trunc <vscale x 4 x i64> undef to <vscale x 4 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i64_nxv4i16 = trunc <vscale x 4 x i64> undef to <vscale x 4 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i64_nxv4i32 = trunc <vscale x 4 x i64> undef to <vscale x 4 x i32> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i8_nxv4i1 = trunc <vscale x 4 x i8> undef to <vscale x 4 x i1> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4i1 = trunc <vscale x 4 x i16> undef to <vscale x 4 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i32_nxv4i1 = trunc <vscale x 4 x i32> undef to <vscale x 4 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i64_nxv4i1 = trunc <vscale x 4 x i64> undef to <vscale x 4 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4i1 = trunc <vscale x 4 x i32> undef to <vscale x 4 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i64_nxv4i1 = trunc <vscale x 4 x i64> undef to <vscale x 4 x i1> ; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i8 = trunc <vscale x 8 x i16> undef to <vscale x 8 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i32_nxv8i8 = trunc <vscale x 8 x i32> undef to <vscale x 8 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i64_nxv8i8 = trunc <vscale x 8 x i64> undef to <vscale x 8 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i32_nxv8i16 = trunc <vscale x 8 x i32> undef to <vscale x 8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i64_nxv8i16 = trunc <vscale x 8 x i64> undef to <vscale x 8 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i64_nxv8i32 = trunc <vscale x 8 x i64> undef to <vscale x 8 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i32_nxv8i8 = trunc <vscale x 8 x i32> undef to <vscale x 8 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8i64_nxv8i8 = trunc <vscale x 8 x i64> undef to <vscale x 8 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i32_nxv8i16 = trunc <vscale x 8 x i32> undef to <vscale x 8 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i64_nxv8i16 = trunc <vscale x 8 x i64> undef to <vscale x 8 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i64_nxv8i32 = trunc <vscale x 8 x i64> undef to <vscale x 8 x i32> ; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i8_nxv8i1 = trunc <vscale x 8 x i8> undef to <vscale x 8 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i16_nxv8i1 = trunc <vscale x 8 x i16> undef to <vscale x 8 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i32_nxv8i1 = trunc <vscale x 8 x i32> undef to <vscale x 8 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i64_nxv8i1 = trunc <vscale x 8 x i64> undef to <vscale x 8 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i16_nxv16i8 = trunc <vscale x 16 x i16> undef to <vscale x 16 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i32_nxv16i8 = trunc <vscale x 16 x i32> undef to <vscale x 16 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i64_nxv16i8 = trunc <vscale x 16 x i64> undef to <vscale x 16 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i32_nxv16i16 = trunc <vscale x 16 x i32> undef to <vscale x 16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i64_nxv16i16 = trunc <vscale x 16 x i64> undef to <vscale x 16 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i64_nxv16i32 = trunc <vscale x 16 x i64> undef to <vscale x 16 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i8_nxv16i1 = trunc <vscale x 16 x i8> undef to <vscale x 16 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i16_nxv16i1 = trunc <vscale x 16 x i16> undef to <vscale x 16 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i32_nxv16i1 = trunc <vscale x 16 x i32> undef to <vscale x 16 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i64_nxv16i1 = trunc <vscale x 16 x i64> undef to <vscale x 16 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv32i16_nxv32i8 = trunc <vscale x 32 x i16> undef to <vscale x 32 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i32_nxv32i8 = trunc <vscale x 32 x i32> undef to <vscale x 32 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv32i64_nxv32i8 = trunc <vscale x 32 x i64> undef to <vscale x 32 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i32_nxv32i16 = trunc <vscale x 32 x i32> undef to <vscale x 32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i64_nxv32i16 = trunc <vscale x 32 x i64> undef to <vscale x 32 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i64_nxv32i32 = trunc <vscale x 32 x i64> undef to <vscale x 32 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i8_nxv32i1 = trunc <vscale x 32 x i8> undef to <vscale x 32 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i16_nxv32i1 = trunc <vscale x 32 x i16> undef to <vscale x 32 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i32_nxv32i1 = trunc <vscale x 32 x i32> undef to <vscale x 32 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i64_nxv32i1 = trunc <vscale x 32 x i64> undef to <vscale x 32 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv64i16_nxv64i8 = trunc <vscale x 64 x i16> undef to <vscale x 64 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i32_nxv64i8 = trunc <vscale x 64 x i32> undef to <vscale x 64 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8i1 = trunc <vscale x 8 x i16> undef to <vscale x 8 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8i1 = trunc <vscale x 8 x i32> undef to <vscale x 8 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i64_nxv8i1 = trunc <vscale x 8 x i64> undef to <vscale x 8 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i16_nxv16i8 = trunc <vscale x 16 x i16> undef to <vscale x 16 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i32_nxv16i8 = trunc <vscale x 16 x i32> undef to <vscale x 16 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv16i64_nxv16i8 = trunc <vscale x 16 x i64> undef to <vscale x 16 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i32_nxv16i16 = trunc <vscale x 16 x i32> undef to <vscale x 16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv16i64_nxv16i16 = trunc <vscale x 16 x i64> undef to <vscale x 16 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i64_nxv16i32 = trunc <vscale x 16 x i64> undef to <vscale x 16 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i8_nxv16i1 = trunc <vscale x 16 x i8> undef to <vscale x 16 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16i1 = trunc <vscale x 16 x i16> undef to <vscale x 16 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i32_nxv16i1 = trunc <vscale x 16 x i32> undef to <vscale x 16 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i64_nxv16i1 = trunc <vscale x 16 x i64> undef to <vscale x 16 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i16_nxv32i8 = trunc <vscale x 32 x i16> undef to <vscale x 32 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv32i32_nxv32i8 = trunc <vscale x 32 x i32> undef to <vscale x 32 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %nxv32i64_nxv32i8 = trunc <vscale x 32 x i64> undef to <vscale x 32 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32i32_nxv32i16 = trunc <vscale x 32 x i32> undef to <vscale x 32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %nxv32i64_nxv32i16 = trunc <vscale x 32 x i64> undef to <vscale x 32 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv32i64_nxv32i32 = trunc <vscale x 32 x i64> undef to <vscale x 32 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i8_nxv32i1 = trunc <vscale x 32 x i8> undef to <vscale x 32 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv32i16_nxv32i1 = trunc <vscale x 32 x i16> undef to <vscale x 32 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i32_nxv32i1 = trunc <vscale x 32 x i32> undef to <vscale x 32 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i64_nxv32i1 = trunc <vscale x 32 x i64> undef to <vscale x 32 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv64i16_nxv64i8 = trunc <vscale x 64 x i16> undef to <vscale x 64 x i8> +; RV32-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %nxv64i32_nxv64i8 = trunc <vscale x 64 x i32> undef to <vscale x 64 x i8> ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv64i64_nxv64i8 = trunc <vscale x 64 x i64> undef to <vscale x 64 x i8> -; RV32-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64i32_nxv64i16 = trunc <vscale x 64 x i32> undef to <vscale x 64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %nxv64i64_nxv64i16 = trunc <vscale x 64 x i64> undef to <vscale x 64 x i16> -; RV32-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv64i64_nxv64i32 = trunc <vscale x 64 x i64> undef to <vscale x 64 x i32> -; RV32-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv64i8_nxv64i1 = trunc <vscale x 64 x i8> undef to <vscale x 64 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv64i16_nxv64i1 = trunc <vscale x 64 x i16> undef to <vscale x 64 x i1> -; RV32-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i32_nxv64i1 = trunc <vscale x 64 x i32> undef to <vscale x 64 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv64i32_nxv64i16 = trunc <vscale x 64 x i32> undef to <vscale x 64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 55 for instruction: %nxv64i64_nxv64i16 = trunc <vscale x 64 x i64> undef to <vscale x 64 x i16> +; RV32-NEXT: Cost Model: Found an estimated cost of 37 for instruction: %nxv64i64_nxv64i32 = trunc <vscale x 64 x i64> undef to <vscale x 64 x i32> +; RV32-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv64i8_nxv64i1 = trunc <vscale x 64 x i8> undef to <vscale x 64 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv64i16_nxv64i1 = trunc <vscale x 64 x i16> undef to <vscale x 64 x i1> +; RV32-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i32_nxv64i1 = trunc <vscale x 64 x i32> undef to <vscale x 64 x i1> ; RV32-NEXT: Cost Model: Invalid cost for instruction: %nxv64i64_nxv64i1 = trunc <vscale x 64 x i64> undef to <vscale x 64 x i1> ; RV32-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; @@ -1188,17 +1188,17 @@ define void @trunc() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_v4i1 = trunc <4 x i8> undef to <4 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i16_v4i1 = trunc <4 x i16> undef to <4 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i32_v4i1 = trunc <4 x i32> undef to <4 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i64_v4i1 = trunc <4 x i64> undef to <4 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i64_v4i1 = trunc <4 x i64> undef to <4 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i16_v8i8 = trunc <8 x i16> undef to <8 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_v8i8 = trunc <8 x i32> undef to <8 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i64_v8i8 = trunc <8 x i64> undef to <8 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i64_v8i8 = trunc <8 x i64> undef to <8 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i32_v8i16 = trunc <8 x i32> undef to <8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i64_v8i16 = trunc <8 x i64> undef to <8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i64_v8i32 = trunc <8 x i64> undef to <8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i64_v8i16 = trunc <8 x i64> undef to <8 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i64_v8i32 = trunc <8 x i64> undef to <8 x i32> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_v8i1 = trunc <8 x i8> undef to <8 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i16_v8i1 = trunc <8 x i16> undef to <8 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i32_v8i1 = trunc <8 x i32> undef to <8 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i64_v8i1 = trunc <8 x i64> undef to <8 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i32_v8i1 = trunc <8 x i32> undef to <8 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v8i64_v8i1 = trunc <8 x i64> undef to <8 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16i16_v16i8 = trunc <2 x i16> undef to <2 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i32_v16i8 = trunc <2 x i32> undef to <2 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16i64_v16i8 = trunc <2 x i64> undef to <2 x i8> @@ -1210,43 +1210,43 @@ define void @trunc() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i32_v16i1 = trunc <2 x i32> undef to <2 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16i64_v16i1 = trunc <2 x i64> undef to <2 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i16_v32i8 = trunc <16 x i16> undef to <16 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i32_v32i8 = trunc <16 x i32> undef to <16 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i64_v32i8 = trunc <16 x i64> undef to <16 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i32_v32i16 = trunc <16 x i32> undef to <16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i64_v32i16 = trunc <16 x i64> undef to <16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32i64_v32i32 = trunc <16 x i64> undef to <16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i32_v32i8 = trunc <16 x i32> undef to <16 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i64_v32i8 = trunc <16 x i64> undef to <16 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i32_v32i16 = trunc <16 x i32> undef to <16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i64_v32i16 = trunc <16 x i64> undef to <16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i64_v32i32 = trunc <16 x i64> undef to <16 x i32> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i8_v32i1 = trunc <16 x i8> undef to <16 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i16_v32i1 = trunc <16 x i16> undef to <16 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i32_v32i1 = trunc <16 x i32> undef to <16 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v32i64_v32i1 = trunc <16 x i64> undef to <16 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v64i16_v64i8 = trunc <64 x i16> undef to <64 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v64i32_v64i8 = trunc <64 x i32> undef to <64 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %v64i64_v64i8 = trunc <64 x i64> undef to <64 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64i32_v64i16 = trunc <64 x i32> undef to <64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64i64_v64i16 = trunc <64 x i64> undef to <64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64i64_v64i32 = trunc <64 x i64> undef to <64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i8_v64i1 = trunc <64 x i8> undef to <64 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v64i16_v64i1 = trunc <64 x i16> undef to <64 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i16_v32i1 = trunc <16 x i16> undef to <16 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32i32_v32i1 = trunc <16 x i32> undef to <16 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v32i64_v32i1 = trunc <16 x i64> undef to <16 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v64i16_v64i8 = trunc <64 x i16> undef to <64 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v64i32_v64i8 = trunc <64 x i32> undef to <64 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v64i64_v64i8 = trunc <64 x i64> undef to <64 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v64i32_v64i16 = trunc <64 x i32> undef to <64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %v64i64_v64i16 = trunc <64 x i64> undef to <64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v64i64_v64i32 = trunc <64 x i64> undef to <64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v64i8_v64i1 = trunc <64 x i8> undef to <64 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v64i16_v64i1 = trunc <64 x i16> undef to <64 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v64i32_v64i1 = trunc <64 x i32> undef to <64 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %v64i64_v64i1 = trunc <64 x i64> undef to <64 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v128i16_v128i8 = trunc <128 x i16> undef to <128 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v128i32_v128i8 = trunc <128 x i32> undef to <128 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %v128i64_v128i8 = trunc <128 x i64> undef to <128 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128i32_v128i16 = trunc <128 x i32> undef to <128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v128i64_v128i16 = trunc <128 x i64> undef to <128 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128i64_v128i32 = trunc <128 x i64> undef to <128 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v128i8_v128i1 = trunc <128 x i8> undef to <128 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v128i16_v128i1 = trunc <128 x i16> undef to <128 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v128i16_v128i8 = trunc <128 x i16> undef to <128 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %v128i32_v128i8 = trunc <128 x i32> undef to <128 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %v128i64_v128i8 = trunc <128 x i64> undef to <128 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v128i32_v128i16 = trunc <128 x i32> undef to <128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %v128i64_v128i16 = trunc <128 x i64> undef to <128 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %v128i64_v128i32 = trunc <128 x i64> undef to <128 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %v128i8_v128i1 = trunc <128 x i8> undef to <128 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %v128i16_v128i1 = trunc <128 x i16> undef to <128 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v128i32_v128i1 = trunc <128 x i32> undef to <128 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v128i64_v128i1 = trunc <128 x i64> undef to <128 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v256i16_v256i8 = trunc <256 x i16> undef to <256 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v256i32_v256i8 = trunc <256 x i32> undef to <256 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 62 for instruction: %v256i64_v256i8 = trunc <256 x i64> undef to <256 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v256i32_v256i16 = trunc <256 x i32> undef to <256 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 44 for instruction: %v256i64_v256i16 = trunc <256 x i64> undef to <256 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %v256i64_v256i32 = trunc <256 x i64> undef to <256 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v256i8_v256i1 = trunc <256 x i8> undef to <256 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v256i16_v256i1 = trunc <256 x i16> undef to <256 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v256i16_v256i8 = trunc <256 x i16> undef to <256 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %v256i32_v256i8 = trunc <256 x i32> undef to <256 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 126 for instruction: %v256i64_v256i8 = trunc <256 x i64> undef to <256 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %v256i32_v256i16 = trunc <256 x i32> undef to <256 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 108 for instruction: %v256i64_v256i16 = trunc <256 x i64> undef to <256 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 72 for instruction: %v256i64_v256i32 = trunc <256 x i64> undef to <256 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 32 for instruction: %v256i8_v256i1 = trunc <256 x i8> undef to <256 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 66 for instruction: %v256i16_v256i1 = trunc <256 x i16> undef to <256 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v256i32_v256i1 = trunc <256 x i32> undef to <256 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v256i64_v256i1 = trunc <256 x i64> undef to <256 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1i16_nxv1i8 = trunc <vscale x 1 x i16> undef to <vscale x 1 x i8> @@ -1268,57 +1268,57 @@ define void @trunc() { ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i8_nxv2i1 = trunc <vscale x 2 x i8> undef to <vscale x 2 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i16_nxv2i1 = trunc <vscale x 2 x i16> undef to <vscale x 2 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i32_nxv2i1 = trunc <vscale x 2 x i32> undef to <vscale x 2 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2i64_nxv2i1 = trunc <vscale x 2 x i64> undef to <vscale x 2 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i64_nxv2i1 = trunc <vscale x 2 x i64> undef to <vscale x 2 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i16_nxv4i8 = trunc <vscale x 4 x i16> undef to <vscale x 4 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i32_nxv4i8 = trunc <vscale x 4 x i32> undef to <vscale x 4 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i64_nxv4i8 = trunc <vscale x 4 x i64> undef to <vscale x 4 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i64_nxv4i8 = trunc <vscale x 4 x i64> undef to <vscale x 4 x i8> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i32_nxv4i16 = trunc <vscale x 4 x i32> undef to <vscale x 4 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i64_nxv4i16 = trunc <vscale x 4 x i64> undef to <vscale x 4 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4i64_nxv4i32 = trunc <vscale x 4 x i64> undef to <vscale x 4 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i64_nxv4i16 = trunc <vscale x 4 x i64> undef to <vscale x 4 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i64_nxv4i32 = trunc <vscale x 4 x i64> undef to <vscale x 4 x i32> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i8_nxv4i1 = trunc <vscale x 4 x i8> undef to <vscale x 4 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i16_nxv4i1 = trunc <vscale x 4 x i16> undef to <vscale x 4 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i32_nxv4i1 = trunc <vscale x 4 x i32> undef to <vscale x 4 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4i64_nxv4i1 = trunc <vscale x 4 x i64> undef to <vscale x 4 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i32_nxv4i1 = trunc <vscale x 4 x i32> undef to <vscale x 4 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv4i64_nxv4i1 = trunc <vscale x 4 x i64> undef to <vscale x 4 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i16_nxv8i8 = trunc <vscale x 8 x i16> undef to <vscale x 8 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i32_nxv8i8 = trunc <vscale x 8 x i32> undef to <vscale x 8 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i64_nxv8i8 = trunc <vscale x 8 x i64> undef to <vscale x 8 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i32_nxv8i16 = trunc <vscale x 8 x i32> undef to <vscale x 8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i64_nxv8i16 = trunc <vscale x 8 x i64> undef to <vscale x 8 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8i64_nxv8i32 = trunc <vscale x 8 x i64> undef to <vscale x 8 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i32_nxv8i8 = trunc <vscale x 8 x i32> undef to <vscale x 8 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8i64_nxv8i8 = trunc <vscale x 8 x i64> undef to <vscale x 8 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i32_nxv8i16 = trunc <vscale x 8 x i32> undef to <vscale x 8 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i64_nxv8i16 = trunc <vscale x 8 x i64> undef to <vscale x 8 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i64_nxv8i32 = trunc <vscale x 8 x i64> undef to <vscale x 8 x i32> ; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i8_nxv8i1 = trunc <vscale x 8 x i8> undef to <vscale x 8 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i16_nxv8i1 = trunc <vscale x 8 x i16> undef to <vscale x 8 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i32_nxv8i1 = trunc <vscale x 8 x i32> undef to <vscale x 8 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8i64_nxv8i1 = trunc <vscale x 8 x i64> undef to <vscale x 8 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i16_nxv16i8 = trunc <vscale x 16 x i16> undef to <vscale x 16 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i32_nxv16i8 = trunc <vscale x 16 x i32> undef to <vscale x 16 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i64_nxv16i8 = trunc <vscale x 16 x i64> undef to <vscale x 16 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16i32_nxv16i16 = trunc <vscale x 16 x i32> undef to <vscale x 16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i64_nxv16i16 = trunc <vscale x 16 x i64> undef to <vscale x 16 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i64_nxv16i32 = trunc <vscale x 16 x i64> undef to <vscale x 16 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i8_nxv16i1 = trunc <vscale x 16 x i8> undef to <vscale x 16 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i16_nxv16i1 = trunc <vscale x 16 x i16> undef to <vscale x 16 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i32_nxv16i1 = trunc <vscale x 16 x i32> undef to <vscale x 16 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i64_nxv16i1 = trunc <vscale x 16 x i64> undef to <vscale x 16 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv32i16_nxv32i8 = trunc <vscale x 32 x i16> undef to <vscale x 32 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i32_nxv32i8 = trunc <vscale x 32 x i32> undef to <vscale x 32 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv32i64_nxv32i8 = trunc <vscale x 32 x i64> undef to <vscale x 32 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i32_nxv32i16 = trunc <vscale x 32 x i32> undef to <vscale x 32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i64_nxv32i16 = trunc <vscale x 32 x i64> undef to <vscale x 32 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i64_nxv32i32 = trunc <vscale x 32 x i64> undef to <vscale x 32 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i8_nxv32i1 = trunc <vscale x 32 x i8> undef to <vscale x 32 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv32i16_nxv32i1 = trunc <vscale x 32 x i16> undef to <vscale x 32 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i32_nxv32i1 = trunc <vscale x 32 x i32> undef to <vscale x 32 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32i64_nxv32i1 = trunc <vscale x 32 x i64> undef to <vscale x 32 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv64i16_nxv64i8 = trunc <vscale x 64 x i16> undef to <vscale x 64 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i32_nxv64i8 = trunc <vscale x 64 x i32> undef to <vscale x 64 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %nxv64i64_nxv64i8 = trunc <vscale x 64 x i64> undef to <vscale x 64 x i8> -; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64i32_nxv64i16 = trunc <vscale x 64 x i32> undef to <vscale x 64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv64i64_nxv64i16 = trunc <vscale x 64 x i64> undef to <vscale x 64 x i16> -; RV64-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv64i64_nxv64i32 = trunc <vscale x 64 x i64> undef to <vscale x 64 x i32> -; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv64i8_nxv64i1 = trunc <vscale x 64 x i8> undef to <vscale x 64 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv64i16_nxv64i1 = trunc <vscale x 64 x i16> undef to <vscale x 64 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv64i32_nxv64i1 = trunc <vscale x 64 x i32> undef to <vscale x 64 x i1> -; RV64-NEXT: Cost Model: Found an estimated cost of 23 for instruction: %nxv64i64_nxv64i1 = trunc <vscale x 64 x i64> undef to <vscale x 64 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i16_nxv8i1 = trunc <vscale x 8 x i16> undef to <vscale x 8 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8i32_nxv8i1 = trunc <vscale x 8 x i32> undef to <vscale x 8 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv8i64_nxv8i1 = trunc <vscale x 8 x i64> undef to <vscale x 8 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv16i16_nxv16i8 = trunc <vscale x 16 x i16> undef to <vscale x 16 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i32_nxv16i8 = trunc <vscale x 16 x i32> undef to <vscale x 16 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %nxv16i64_nxv16i8 = trunc <vscale x 16 x i64> undef to <vscale x 16 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i32_nxv16i16 = trunc <vscale x 16 x i32> undef to <vscale x 16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv16i64_nxv16i16 = trunc <vscale x 16 x i64> undef to <vscale x 16 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i64_nxv16i32 = trunc <vscale x 16 x i64> undef to <vscale x 16 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i8_nxv16i1 = trunc <vscale x 16 x i8> undef to <vscale x 16 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16i16_nxv16i1 = trunc <vscale x 16 x i16> undef to <vscale x 16 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv16i32_nxv16i1 = trunc <vscale x 16 x i32> undef to <vscale x 16 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv16i64_nxv16i1 = trunc <vscale x 16 x i64> undef to <vscale x 16 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i16_nxv32i8 = trunc <vscale x 32 x i16> undef to <vscale x 32 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv32i32_nxv32i8 = trunc <vscale x 32 x i32> undef to <vscale x 32 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %nxv32i64_nxv32i8 = trunc <vscale x 32 x i64> undef to <vscale x 32 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32i32_nxv32i16 = trunc <vscale x 32 x i32> undef to <vscale x 32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %nxv32i64_nxv32i16 = trunc <vscale x 32 x i64> undef to <vscale x 32 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv32i64_nxv32i32 = trunc <vscale x 32 x i64> undef to <vscale x 32 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv32i8_nxv32i1 = trunc <vscale x 32 x i8> undef to <vscale x 32 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv32i16_nxv32i1 = trunc <vscale x 32 x i16> undef to <vscale x 32 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv32i32_nxv32i1 = trunc <vscale x 32 x i32> undef to <vscale x 32 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv32i64_nxv32i1 = trunc <vscale x 32 x i64> undef to <vscale x 32 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv64i16_nxv64i8 = trunc <vscale x 64 x i16> undef to <vscale x 64 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %nxv64i32_nxv64i8 = trunc <vscale x 64 x i32> undef to <vscale x 64 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 63 for instruction: %nxv64i64_nxv64i8 = trunc <vscale x 64 x i64> undef to <vscale x 64 x i8> +; RV64-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv64i32_nxv64i16 = trunc <vscale x 64 x i32> undef to <vscale x 64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %nxv64i64_nxv64i16 = trunc <vscale x 64 x i64> undef to <vscale x 64 x i16> +; RV64-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %nxv64i64_nxv64i32 = trunc <vscale x 64 x i64> undef to <vscale x 64 x i32> +; RV64-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %nxv64i8_nxv64i1 = trunc <vscale x 64 x i8> undef to <vscale x 64 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %nxv64i16_nxv64i1 = trunc <vscale x 64 x i16> undef to <vscale x 64 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 67 for instruction: %nxv64i32_nxv64i1 = trunc <vscale x 64 x i32> undef to <vscale x 64 x i1> +; RV64-NEXT: Cost Model: Found an estimated cost of 135 for instruction: %nxv64i64_nxv64i1 = trunc <vscale x 64 x i64> undef to <vscale x 64 x i1> ; RV64-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; %v2i16_v2i8 = trunc <2 x i16> undef to <2 x i8> @@ -1495,44 +1495,44 @@ define void @fpext() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2f16_v2f64 = fpext <2 x half> undef to <2 x double> ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2f32_v2f64 = fpext <2 x float> undef to <2 x double> ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f16_v4f32 = fpext <4 x half> undef to <4 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f16_v4f64 = fpext <4 x half> undef to <4 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f32_v4f64 = fpext <4 x float> undef to <4 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8f16_v8f32 = fpext <8 x half> undef to <8 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f16_v8f64 = fpext <8 x half> undef to <8 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8f32_v8f64 = fpext <8 x float> undef to <8 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16f16_v16f32 = fpext <16 x half> undef to <16 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16f16_v16f64 = fpext <16 x half> undef to <16 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16f32_v16f64 = fpext <16 x float> undef to <16 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32f16_v32f32 = fpext <32 x half> undef to <32 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32f16_v32f64 = fpext <32 x half> undef to <32 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32f32_v32f64 = fpext <32 x float> undef to <32 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64f16_v64f32 = fpext <64 x half> undef to <64 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64f16_v64f64 = fpext <64 x half> undef to <64 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64f32_v64f64 = fpext <64 x float> undef to <64 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128f16_v128f32 = fpext <128 x half> undef to <128 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v128f16_v128f64 = fpext <128 x half> undef to <128 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128f32_v128f64 = fpext <128 x float> undef to <128 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4f16_v4f64 = fpext <4 x half> undef to <4 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f32_v4f64 = fpext <4 x float> undef to <4 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f16_v8f32 = fpext <8 x half> undef to <8 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8f16_v8f64 = fpext <8 x half> undef to <8 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8f32_v8f64 = fpext <8 x float> undef to <8 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16f16_v16f32 = fpext <16 x half> undef to <16 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v16f16_v16f64 = fpext <16 x half> undef to <16 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v16f32_v16f64 = fpext <16 x float> undef to <16 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %v32f16_v32f32 = fpext <32 x half> undef to <32 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %v32f16_v32f64 = fpext <32 x half> undef to <32 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32f32_v32f64 = fpext <32 x float> undef to <32 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v64f16_v64f32 = fpext <64 x half> undef to <64 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %v64f16_v64f64 = fpext <64 x half> undef to <64 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v64f32_v64f64 = fpext <64 x float> undef to <64 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %v128f16_v128f32 = fpext <128 x half> undef to <128 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %v128f16_v128f64 = fpext <128 x half> undef to <128 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %v128f32_v128f64 = fpext <128 x float> undef to <128 x double> ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f16_nxv1f32 = fpext <vscale x 1 x half> undef to <vscale x 1 x float> ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1f16_nxv1f64 = fpext <vscale x 1 x half> undef to <vscale x 1 x double> ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f32_nxv1f64 = fpext <vscale x 1 x float> undef to <vscale x 1 x double> ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f16_nxv2f32 = fpext <vscale x 2 x half> undef to <vscale x 2 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f16_nxv2f64 = fpext <vscale x 2 x half> undef to <vscale x 2 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f32_nxv2f64 = fpext <vscale x 2 x float> undef to <vscale x 2 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4f16_nxv4f32 = fpext <vscale x 4 x half> undef to <vscale x 4 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f16_nxv4f64 = fpext <vscale x 4 x half> undef to <vscale x 4 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4f32_nxv4f64 = fpext <vscale x 4 x float> undef to <vscale x 4 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8f16_nxv8f32 = fpext <vscale x 8 x half> undef to <vscale x 8 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8f16_nxv8f64 = fpext <vscale x 8 x half> undef to <vscale x 8 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8f32_nxv8f64 = fpext <vscale x 8 x float> undef to <vscale x 8 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16f16_nxv16f32 = fpext <vscale x 16 x half> undef to <vscale x 16 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16f16_nxv16f64 = fpext <vscale x 16 x half> undef to <vscale x 16 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16f32_nxv16f64 = fpext <vscale x 16 x float> undef to <vscale x 16 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32f16_nxv32f32 = fpext <vscale x 32 x half> undef to <vscale x 32 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32f16_nxv32f64 = fpext <vscale x 32 x half> undef to <vscale x 32 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32f32_nxv32f64 = fpext <vscale x 32 x float> undef to <vscale x 32 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64f16_nxv64f32 = fpext <vscale x 64 x half> undef to <vscale x 64 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv64f16_nxv64f64 = fpext <vscale x 64 x half> undef to <vscale x 64 x double> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv64f32_nxv64f64 = fpext <vscale x 64 x float> undef to <vscale x 64 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2f16_nxv2f64 = fpext <vscale x 2 x half> undef to <vscale x 2 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f32_nxv2f64 = fpext <vscale x 2 x float> undef to <vscale x 2 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f16_nxv4f32 = fpext <vscale x 4 x half> undef to <vscale x 4 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4f16_nxv4f64 = fpext <vscale x 4 x half> undef to <vscale x 4 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4f32_nxv4f64 = fpext <vscale x 4 x float> undef to <vscale x 4 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8f16_nxv8f32 = fpext <vscale x 8 x half> undef to <vscale x 8 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv8f16_nxv8f64 = fpext <vscale x 8 x half> undef to <vscale x 8 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv8f32_nxv8f64 = fpext <vscale x 8 x float> undef to <vscale x 8 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %nxv16f16_nxv16f32 = fpext <vscale x 16 x half> undef to <vscale x 16 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 25 for instruction: %nxv16f16_nxv16f64 = fpext <vscale x 16 x half> undef to <vscale x 16 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv16f32_nxv16f64 = fpext <vscale x 16 x float> undef to <vscale x 16 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32f16_nxv32f32 = fpext <vscale x 32 x half> undef to <vscale x 32 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 51 for instruction: %nxv32f16_nxv32f64 = fpext <vscale x 32 x half> undef to <vscale x 32 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv32f32_nxv32f64 = fpext <vscale x 32 x float> undef to <vscale x 32 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 34 for instruction: %nxv64f16_nxv64f32 = fpext <vscale x 64 x half> undef to <vscale x 64 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 102 for instruction: %nxv64f16_nxv64f64 = fpext <vscale x 64 x half> undef to <vscale x 64 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 68 for instruction: %nxv64f32_nxv64f64 = fpext <vscale x 64 x float> undef to <vscale x 64 x double> ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; %v2f16_v2f32 = fpext <2 x half> undef to <2 x float> @@ -1603,20 +1603,20 @@ define void @fptrunc() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4f64_v4f16 = fptrunc <4 x double> undef to <4 x half> ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4f64_v4f32 = fptrunc <4 x double> undef to <4 x float> ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8f32_v8f16 = fptrunc <8 x float> undef to <8 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f64_v8f16 = fptrunc <8 x double> undef to <8 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8f64_v8f32 = fptrunc <8 x double> undef to <8 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16f32_v16f16 = fptrunc <16 x float> undef to <16 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16f64_v16f16 = fptrunc <16 x double> undef to <16 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v16f64_v16f32 = fptrunc <16 x double> undef to <16 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v32f32_v32f16 = fptrunc <32 x float> undef to <32 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32f64_v32f16 = fptrunc <32 x double> undef to <32 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32f64_v32f32 = fptrunc <32 x double> undef to <32 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v64f32_v64f16 = fptrunc <64 x float> undef to <64 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v64f64_v64f16 = fptrunc <64 x double> undef to <64 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v64f64_v64f32 = fptrunc <64 x double> undef to <64 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v128f32_v128f16 = fptrunc <128 x float> undef to <128 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %v128f64_v128f16 = fptrunc <128 x double> undef to <128 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %v128f64_v128f32 = fptrunc <128 x double> undef to <128 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8f64_v8f16 = fptrunc <8 x double> undef to <8 x half> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8f64_v8f32 = fptrunc <8 x double> undef to <8 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v16f32_v16f16 = fptrunc <16 x float> undef to <16 x half> +; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16f64_v16f16 = fptrunc <16 x double> undef to <16 x half> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16f64_v16f32 = fptrunc <16 x double> undef to <16 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32f32_v32f16 = fptrunc <32 x float> undef to <32 x half> +; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %v32f64_v32f16 = fptrunc <32 x double> undef to <32 x half> +; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32f64_v32f32 = fptrunc <32 x double> undef to <32 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v64f32_v64f16 = fptrunc <64 x float> undef to <64 x half> +; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %v64f64_v64f16 = fptrunc <64 x double> undef to <64 x half> +; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v64f64_v64f32 = fptrunc <64 x double> undef to <64 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v128f32_v128f16 = fptrunc <128 x float> undef to <128 x half> +; CHECK-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %v128f64_v128f16 = fptrunc <128 x double> undef to <128 x half> +; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %v128f64_v128f32 = fptrunc <128 x double> undef to <128 x float> ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f32_nxv1f16 = fptrunc <vscale x 1 x float> undef to <vscale x 1 x half> ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv1f64_nxv1f16 = fptrunc <vscale x 1 x double> undef to <vscale x 1 x half> ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv1f64_nxv1f32 = fptrunc <vscale x 1 x double> undef to <vscale x 1 x float> @@ -1624,20 +1624,20 @@ define void @fptrunc() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv2f64_nxv1f16 = fptrunc <vscale x 2 x double> undef to <vscale x 2 x half> ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv2f64_nxv1f32 = fptrunc <vscale x 2 x double> undef to <vscale x 2 x float> ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4f32_nxv4f16 = fptrunc <vscale x 4 x float> undef to <vscale x 4 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f64_nxv4f16 = fptrunc <vscale x 4 x double> undef to <vscale x 4 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv4f64_nxv4f32 = fptrunc <vscale x 4 x double> undef to <vscale x 4 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8f32_nxv8f16 = fptrunc <vscale x 8 x float> undef to <vscale x 8 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8f64_nxv8f16 = fptrunc <vscale x 8 x double> undef to <vscale x 8 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv8f64_nxv8f32 = fptrunc <vscale x 8 x double> undef to <vscale x 8 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %nxv16f32_nxv16f16 = fptrunc <vscale x 16 x float> undef to <vscale x 16 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16f64_nxv16f16 = fptrunc <vscale x 16 x double> undef to <vscale x 16 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16f64_nxv16f32 = fptrunc <vscale x 16 x double> undef to <vscale x 16 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32f32_nxv32f16 = fptrunc <vscale x 32 x float> undef to <vscale x 32 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv32f64_nxv32f16 = fptrunc <vscale x 32 x double> undef to <vscale x 32 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32f64_nxv32f32 = fptrunc <vscale x 32 x double> undef to <vscale x 32 x float> -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv64f32_nxv64f16 = fptrunc <vscale x 64 x float> undef to <vscale x 64 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 22 for instruction: %nxv64f64_nxv64f16 = fptrunc <vscale x 64 x double> undef to <vscale x 64 x half> -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %nxv64f64_nxv64f32 = fptrunc <vscale x 64 x double> undef to <vscale x 64 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4f64_nxv4f16 = fptrunc <vscale x 4 x double> undef to <vscale x 4 x half> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv4f64_nxv4f32 = fptrunc <vscale x 4 x double> undef to <vscale x 4 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %nxv8f32_nxv8f16 = fptrunc <vscale x 8 x float> undef to <vscale x 8 x half> +; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8f64_nxv8f16 = fptrunc <vscale x 8 x double> undef to <vscale x 8 x half> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8f64_nxv8f32 = fptrunc <vscale x 8 x double> undef to <vscale x 8 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16f32_nxv16f16 = fptrunc <vscale x 16 x float> undef to <vscale x 16 x half> +; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %nxv16f64_nxv16f16 = fptrunc <vscale x 16 x double> undef to <vscale x 16 x half> +; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16f64_nxv16f32 = fptrunc <vscale x 16 x double> undef to <vscale x 16 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32f32_nxv32f16 = fptrunc <vscale x 32 x float> undef to <vscale x 32 x half> +; CHECK-NEXT: Cost Model: Found an estimated cost of 27 for instruction: %nxv32f64_nxv32f16 = fptrunc <vscale x 32 x double> undef to <vscale x 32 x half> +; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv32f64_nxv32f32 = fptrunc <vscale x 32 x double> undef to <vscale x 32 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv64f32_nxv64f16 = fptrunc <vscale x 64 x float> undef to <vscale x 64 x half> +; CHECK-NEXT: Cost Model: Found an estimated cost of 54 for instruction: %nxv64f64_nxv64f16 = fptrunc <vscale x 64 x double> undef to <vscale x 64 x half> +; CHECK-NEXT: Cost Model: Found an estimated cost of 36 for instruction: %nxv64f64_nxv64f32 = fptrunc <vscale x 64 x double> undef to <vscale x 64 x float> ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; %v2f32_v2f16 = fptrunc <2 x float> undef to <2 x half> diff --git a/llvm/test/Analysis/CostModel/RISCV/int-min-max.ll b/llvm/test/Analysis/CostModel/RISCV/int-min-max.ll index ec669c986c1503960533322ffaafcd87af32f6b6..79cf1c84ed494e3f471de5f4cf7ebb3c33a85127 100644 --- a/llvm/test/Analysis/CostModel/RISCV/int-min-max.ll +++ b/llvm/test/Analysis/CostModel/RISCV/int-min-max.ll @@ -12,36 +12,36 @@ define void @smax() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = call <vscale x 2 x i8> @llvm.smax.nxv2i8(<vscale x 2 x i8> undef, <vscale x 2 x i8> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = call <vscale x 4 x i8> @llvm.smax.nxv4i8(<vscale x 4 x i8> undef, <vscale x 4 x i8> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = call <vscale x 8 x i8> @llvm.smax.nxv8i8(<vscale x 8 x i8> undef, <vscale x 8 x i8> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = call <vscale x 16 x i8> @llvm.smax.nxv16i8(<vscale x 16 x i8> undef, <vscale x 16 x i8> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %10 = call <vscale x 16 x i8> @llvm.smax.nxv16i8(<vscale x 16 x i8> undef, <vscale x 16 x i8> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %11 = call i16 @llvm.smax.i16(i16 undef, i16 undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = call <2 x i16> @llvm.smax.v2i16(<2 x i16> undef, <2 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = call <4 x i16> @llvm.smax.v4i16(<4 x i16> undef, <4 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = call <8 x i16> @llvm.smax.v8i16(<8 x i16> undef, <8 x i16> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %15 = call <16 x i16> @llvm.smax.v16i16(<16 x i16> undef, <16 x i16> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %15 = call <16 x i16> @llvm.smax.v16i16(<16 x i16> undef, <16 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %16 = call <vscale x 1 x i16> @llvm.smax.nxv1i16(<vscale x 1 x i16> undef, <vscale x 1 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = call <vscale x 2 x i16> @llvm.smax.nxv2i16(<vscale x 2 x i16> undef, <vscale x 2 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = call <vscale x 4 x i16> @llvm.smax.nxv4i16(<vscale x 4 x i16> undef, <vscale x 4 x i16> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = call <vscale x 8 x i16> @llvm.smax.nxv8i16(<vscale x 8 x i16> undef, <vscale x 8 x i16> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %20 = call <vscale x 16 x i16> @llvm.smax.nxv16i16(<vscale x 16 x i16> undef, <vscale x 16 x i16> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %19 = call <vscale x 8 x i16> @llvm.smax.nxv8i16(<vscale x 8 x i16> undef, <vscale x 8 x i16> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %20 = call <vscale x 16 x i16> @llvm.smax.nxv16i16(<vscale x 16 x i16> undef, <vscale x 16 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %21 = call i32 @llvm.smax.i32(i32 undef, i32 undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = call <2 x i32> @llvm.smax.v2i32(<2 x i32> undef, <2 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = call <4 x i32> @llvm.smax.v4i32(<4 x i32> undef, <4 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %24 = call <8 x i32> @llvm.smax.v8i32(<8 x i32> undef, <8 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %25 = call <16 x i32> @llvm.smax.v16i32(<16 x i32> undef, <16 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %24 = call <8 x i32> @llvm.smax.v8i32(<8 x i32> undef, <8 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %25 = call <16 x i32> @llvm.smax.v16i32(<16 x i32> undef, <16 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = call <vscale x 1 x i32> @llvm.smax.nxv1i32(<vscale x 1 x i32> undef, <vscale x 1 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = call <vscale x 2 x i32> @llvm.smax.nxv2i32(<vscale x 2 x i32> undef, <vscale x 2 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = call <vscale x 4 x i32> @llvm.smax.nxv4i32(<vscale x 4 x i32> undef, <vscale x 4 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = call <vscale x 8 x i32> @llvm.smax.nxv8i32(<vscale x 8 x i32> undef, <vscale x 8 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = call <vscale x 16 x i32> @llvm.smax.nxv16i32(<vscale x 16 x i32> undef, <vscale x 16 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %28 = call <vscale x 4 x i32> @llvm.smax.nxv4i32(<vscale x 4 x i32> undef, <vscale x 4 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %29 = call <vscale x 8 x i32> @llvm.smax.nxv8i32(<vscale x 8 x i32> undef, <vscale x 8 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %30 = call <vscale x 16 x i32> @llvm.smax.nxv16i32(<vscale x 16 x i32> undef, <vscale x 16 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %31 = call i64 @llvm.smax.i64(i64 undef, i64 undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = call <2 x i64> @llvm.smax.v2i64(<2 x i64> undef, <2 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = call <4 x i64> @llvm.smax.v4i64(<4 x i64> undef, <4 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %34 = call <8 x i64> @llvm.smax.v8i64(<8 x i64> undef, <8 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %35 = call <16 x i64> @llvm.smax.v16i64(<16 x i64> undef, <16 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %33 = call <4 x i64> @llvm.smax.v4i64(<4 x i64> undef, <4 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %34 = call <8 x i64> @llvm.smax.v8i64(<8 x i64> undef, <8 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %35 = call <16 x i64> @llvm.smax.v16i64(<16 x i64> undef, <16 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %36 = call <vscale x 1 x i64> @llvm.smax.nxv1i64(<vscale x 1 x i64> undef, <vscale x 1 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %37 = call <vscale x 2 x i64> @llvm.smax.nxv2i64(<vscale x 2 x i64> undef, <vscale x 2 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = call <vscale x 4 x i64> @llvm.smax.nxv4i64(<vscale x 4 x i64> undef, <vscale x 4 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %39 = call <vscale x 8 x i64> @llvm.smax.nxv8i64(<vscale x 8 x i64> undef, <vscale x 8 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %37 = call <vscale x 2 x i64> @llvm.smax.nxv2i64(<vscale x 2 x i64> undef, <vscale x 2 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %38 = call <vscale x 4 x i64> @llvm.smax.nxv4i64(<vscale x 4 x i64> undef, <vscale x 4 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %39 = call <vscale x 8 x i64> @llvm.smax.nxv8i64(<vscale x 8 x i64> undef, <vscale x 8 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; call i8 @llvm.smax.i8(i8 undef, i8 undef) @@ -97,36 +97,36 @@ define void @smin() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = call <vscale x 2 x i8> @llvm.smin.nxv2i8(<vscale x 2 x i8> undef, <vscale x 2 x i8> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = call <vscale x 4 x i8> @llvm.smin.nxv4i8(<vscale x 4 x i8> undef, <vscale x 4 x i8> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = call <vscale x 8 x i8> @llvm.smin.nxv8i8(<vscale x 8 x i8> undef, <vscale x 8 x i8> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = call <vscale x 16 x i8> @llvm.smin.nxv16i8(<vscale x 16 x i8> undef, <vscale x 16 x i8> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %10 = call <vscale x 16 x i8> @llvm.smin.nxv16i8(<vscale x 16 x i8> undef, <vscale x 16 x i8> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %11 = call i16 @llvm.smin.i16(i16 undef, i16 undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = call <2 x i16> @llvm.smin.v2i16(<2 x i16> undef, <2 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = call <4 x i16> @llvm.smin.v4i16(<4 x i16> undef, <4 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = call <8 x i16> @llvm.smin.v8i16(<8 x i16> undef, <8 x i16> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %15 = call <16 x i16> @llvm.smin.v16i16(<16 x i16> undef, <16 x i16> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %15 = call <16 x i16> @llvm.smin.v16i16(<16 x i16> undef, <16 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %16 = call <vscale x 1 x i16> @llvm.smin.nxv1i16(<vscale x 1 x i16> undef, <vscale x 1 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = call <vscale x 2 x i16> @llvm.smin.nxv2i16(<vscale x 2 x i16> undef, <vscale x 2 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = call <vscale x 4 x i16> @llvm.smin.nxv4i16(<vscale x 4 x i16> undef, <vscale x 4 x i16> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = call <vscale x 8 x i16> @llvm.smin.nxv8i16(<vscale x 8 x i16> undef, <vscale x 8 x i16> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %20 = call <vscale x 16 x i16> @llvm.smin.nxv16i16(<vscale x 16 x i16> undef, <vscale x 16 x i16> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %19 = call <vscale x 8 x i16> @llvm.smin.nxv8i16(<vscale x 8 x i16> undef, <vscale x 8 x i16> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %20 = call <vscale x 16 x i16> @llvm.smin.nxv16i16(<vscale x 16 x i16> undef, <vscale x 16 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %21 = call i32 @llvm.smin.i32(i32 undef, i32 undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = call <2 x i32> @llvm.smin.v2i32(<2 x i32> undef, <2 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = call <4 x i32> @llvm.smin.v4i32(<4 x i32> undef, <4 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %24 = call <8 x i32> @llvm.smin.v8i32(<8 x i32> undef, <8 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %25 = call <16 x i32> @llvm.smin.v16i32(<16 x i32> undef, <16 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %24 = call <8 x i32> @llvm.smin.v8i32(<8 x i32> undef, <8 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %25 = call <16 x i32> @llvm.smin.v16i32(<16 x i32> undef, <16 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = call <vscale x 1 x i32> @llvm.smin.nxv1i32(<vscale x 1 x i32> undef, <vscale x 1 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = call <vscale x 2 x i32> @llvm.smin.nxv2i32(<vscale x 2 x i32> undef, <vscale x 2 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = call <vscale x 4 x i32> @llvm.smin.nxv4i32(<vscale x 4 x i32> undef, <vscale x 4 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = call <vscale x 8 x i32> @llvm.smin.nxv8i32(<vscale x 8 x i32> undef, <vscale x 8 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = call <vscale x 16 x i32> @llvm.smin.nxv16i32(<vscale x 16 x i32> undef, <vscale x 16 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %28 = call <vscale x 4 x i32> @llvm.smin.nxv4i32(<vscale x 4 x i32> undef, <vscale x 4 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %29 = call <vscale x 8 x i32> @llvm.smin.nxv8i32(<vscale x 8 x i32> undef, <vscale x 8 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %30 = call <vscale x 16 x i32> @llvm.smin.nxv16i32(<vscale x 16 x i32> undef, <vscale x 16 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %31 = call i64 @llvm.smin.i64(i64 undef, i64 undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = call <2 x i64> @llvm.smin.v2i64(<2 x i64> undef, <2 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = call <4 x i64> @llvm.smin.v4i64(<4 x i64> undef, <4 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %34 = call <8 x i64> @llvm.smin.v8i64(<8 x i64> undef, <8 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %35 = call <16 x i64> @llvm.smin.v16i64(<16 x i64> undef, <16 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %33 = call <4 x i64> @llvm.smin.v4i64(<4 x i64> undef, <4 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %34 = call <8 x i64> @llvm.smin.v8i64(<8 x i64> undef, <8 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %35 = call <16 x i64> @llvm.smin.v16i64(<16 x i64> undef, <16 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %36 = call <vscale x 1 x i64> @llvm.smin.nxv1i64(<vscale x 1 x i64> undef, <vscale x 1 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %37 = call <vscale x 2 x i64> @llvm.smin.nxv2i64(<vscale x 2 x i64> undef, <vscale x 2 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = call <vscale x 4 x i64> @llvm.smin.nxv4i64(<vscale x 4 x i64> undef, <vscale x 4 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %39 = call <vscale x 8 x i64> @llvm.smin.nxv8i64(<vscale x 8 x i64> undef, <vscale x 8 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %37 = call <vscale x 2 x i64> @llvm.smin.nxv2i64(<vscale x 2 x i64> undef, <vscale x 2 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %38 = call <vscale x 4 x i64> @llvm.smin.nxv4i64(<vscale x 4 x i64> undef, <vscale x 4 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %39 = call <vscale x 8 x i64> @llvm.smin.nxv8i64(<vscale x 8 x i64> undef, <vscale x 8 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; call i8 @llvm.smin.i8(i8 undef, i8 undef) @@ -182,36 +182,36 @@ define void @umax() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = call <vscale x 2 x i8> @llvm.umax.nxv2i8(<vscale x 2 x i8> undef, <vscale x 2 x i8> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = call <vscale x 4 x i8> @llvm.umax.nxv4i8(<vscale x 4 x i8> undef, <vscale x 4 x i8> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = call <vscale x 8 x i8> @llvm.umax.nxv8i8(<vscale x 8 x i8> undef, <vscale x 8 x i8> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = call <vscale x 16 x i8> @llvm.umax.nxv16i8(<vscale x 16 x i8> undef, <vscale x 16 x i8> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %10 = call <vscale x 16 x i8> @llvm.umax.nxv16i8(<vscale x 16 x i8> undef, <vscale x 16 x i8> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %11 = call i16 @llvm.umax.i16(i16 undef, i16 undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = call <2 x i16> @llvm.umax.v2i16(<2 x i16> undef, <2 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = call <4 x i16> @llvm.umax.v4i16(<4 x i16> undef, <4 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = call <8 x i16> @llvm.umax.v8i16(<8 x i16> undef, <8 x i16> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %15 = call <16 x i16> @llvm.umax.v16i16(<16 x i16> undef, <16 x i16> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %15 = call <16 x i16> @llvm.umax.v16i16(<16 x i16> undef, <16 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %16 = call <vscale x 1 x i16> @llvm.umax.nxv1i16(<vscale x 1 x i16> undef, <vscale x 1 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = call <vscale x 2 x i16> @llvm.umax.nxv2i16(<vscale x 2 x i16> undef, <vscale x 2 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = call <vscale x 4 x i16> @llvm.umax.nxv4i16(<vscale x 4 x i16> undef, <vscale x 4 x i16> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = call <vscale x 8 x i16> @llvm.umax.nxv8i16(<vscale x 8 x i16> undef, <vscale x 8 x i16> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %20 = call <vscale x 16 x i16> @llvm.umax.nxv16i16(<vscale x 16 x i16> undef, <vscale x 16 x i16> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %19 = call <vscale x 8 x i16> @llvm.umax.nxv8i16(<vscale x 8 x i16> undef, <vscale x 8 x i16> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %20 = call <vscale x 16 x i16> @llvm.umax.nxv16i16(<vscale x 16 x i16> undef, <vscale x 16 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %21 = call i32 @llvm.umax.i32(i32 undef, i32 undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = call <2 x i32> @llvm.umax.v2i32(<2 x i32> undef, <2 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = call <4 x i32> @llvm.umax.v4i32(<4 x i32> undef, <4 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %24 = call <8 x i32> @llvm.umax.v8i32(<8 x i32> undef, <8 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %25 = call <16 x i32> @llvm.umax.v16i32(<16 x i32> undef, <16 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %24 = call <8 x i32> @llvm.umax.v8i32(<8 x i32> undef, <8 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %25 = call <16 x i32> @llvm.umax.v16i32(<16 x i32> undef, <16 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = call <vscale x 1 x i32> @llvm.umax.nxv1i32(<vscale x 1 x i32> undef, <vscale x 1 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = call <vscale x 2 x i32> @llvm.umax.nxv2i32(<vscale x 2 x i32> undef, <vscale x 2 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = call <vscale x 4 x i32> @llvm.umax.nxv4i32(<vscale x 4 x i32> undef, <vscale x 4 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = call <vscale x 8 x i32> @llvm.umax.nxv8i32(<vscale x 8 x i32> undef, <vscale x 8 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = call <vscale x 16 x i32> @llvm.umax.nxv16i32(<vscale x 16 x i32> undef, <vscale x 16 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %28 = call <vscale x 4 x i32> @llvm.umax.nxv4i32(<vscale x 4 x i32> undef, <vscale x 4 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %29 = call <vscale x 8 x i32> @llvm.umax.nxv8i32(<vscale x 8 x i32> undef, <vscale x 8 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %30 = call <vscale x 16 x i32> @llvm.umax.nxv16i32(<vscale x 16 x i32> undef, <vscale x 16 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %31 = call i64 @llvm.umax.i64(i64 undef, i64 undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = call <2 x i64> @llvm.umax.v2i64(<2 x i64> undef, <2 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = call <4 x i64> @llvm.umax.v4i64(<4 x i64> undef, <4 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %34 = call <8 x i64> @llvm.umax.v8i64(<8 x i64> undef, <8 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %35 = call <16 x i64> @llvm.umax.v16i64(<16 x i64> undef, <16 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %33 = call <4 x i64> @llvm.umax.v4i64(<4 x i64> undef, <4 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %34 = call <8 x i64> @llvm.umax.v8i64(<8 x i64> undef, <8 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %35 = call <16 x i64> @llvm.umax.v16i64(<16 x i64> undef, <16 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %36 = call <vscale x 1 x i64> @llvm.umax.nxv1i64(<vscale x 1 x i64> undef, <vscale x 1 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %37 = call <vscale x 2 x i64> @llvm.umax.nxv2i64(<vscale x 2 x i64> undef, <vscale x 2 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = call <vscale x 4 x i64> @llvm.umax.nxv4i64(<vscale x 4 x i64> undef, <vscale x 4 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %39 = call <vscale x 8 x i64> @llvm.umax.nxv8i64(<vscale x 8 x i64> undef, <vscale x 8 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %37 = call <vscale x 2 x i64> @llvm.umax.nxv2i64(<vscale x 2 x i64> undef, <vscale x 2 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %38 = call <vscale x 4 x i64> @llvm.umax.nxv4i64(<vscale x 4 x i64> undef, <vscale x 4 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %39 = call <vscale x 8 x i64> @llvm.umax.nxv8i64(<vscale x 8 x i64> undef, <vscale x 8 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; call i8 @llvm.umax.i8(i8 undef, i8 undef) @@ -267,36 +267,36 @@ define void @umin() { ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %7 = call <vscale x 2 x i8> @llvm.umin.nxv2i8(<vscale x 2 x i8> undef, <vscale x 2 x i8> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %8 = call <vscale x 4 x i8> @llvm.umin.nxv4i8(<vscale x 4 x i8> undef, <vscale x 4 x i8> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %9 = call <vscale x 8 x i8> @llvm.umin.nxv8i8(<vscale x 8 x i8> undef, <vscale x 8 x i8> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %10 = call <vscale x 16 x i8> @llvm.umin.nxv16i8(<vscale x 16 x i8> undef, <vscale x 16 x i8> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %10 = call <vscale x 16 x i8> @llvm.umin.nxv16i8(<vscale x 16 x i8> undef, <vscale x 16 x i8> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %11 = call i16 @llvm.umin.i16(i16 undef, i16 undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %12 = call <2 x i16> @llvm.umin.v2i16(<2 x i16> undef, <2 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %13 = call <4 x i16> @llvm.umin.v4i16(<4 x i16> undef, <4 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %14 = call <8 x i16> @llvm.umin.v8i16(<8 x i16> undef, <8 x i16> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %15 = call <16 x i16> @llvm.umin.v16i16(<16 x i16> undef, <16 x i16> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %15 = call <16 x i16> @llvm.umin.v16i16(<16 x i16> undef, <16 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %16 = call <vscale x 1 x i16> @llvm.umin.nxv1i16(<vscale x 1 x i16> undef, <vscale x 1 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %17 = call <vscale x 2 x i16> @llvm.umin.nxv2i16(<vscale x 2 x i16> undef, <vscale x 2 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %18 = call <vscale x 4 x i16> @llvm.umin.nxv4i16(<vscale x 4 x i16> undef, <vscale x 4 x i16> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %19 = call <vscale x 8 x i16> @llvm.umin.nxv8i16(<vscale x 8 x i16> undef, <vscale x 8 x i16> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %20 = call <vscale x 16 x i16> @llvm.umin.nxv16i16(<vscale x 16 x i16> undef, <vscale x 16 x i16> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %19 = call <vscale x 8 x i16> @llvm.umin.nxv8i16(<vscale x 8 x i16> undef, <vscale x 8 x i16> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %20 = call <vscale x 16 x i16> @llvm.umin.nxv16i16(<vscale x 16 x i16> undef, <vscale x 16 x i16> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %21 = call i32 @llvm.umin.i32(i32 undef, i32 undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %22 = call <2 x i32> @llvm.umin.v2i32(<2 x i32> undef, <2 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %23 = call <4 x i32> @llvm.umin.v4i32(<4 x i32> undef, <4 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %24 = call <8 x i32> @llvm.umin.v8i32(<8 x i32> undef, <8 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %25 = call <16 x i32> @llvm.umin.v16i32(<16 x i32> undef, <16 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %24 = call <8 x i32> @llvm.umin.v8i32(<8 x i32> undef, <8 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %25 = call <16 x i32> @llvm.umin.v16i32(<16 x i32> undef, <16 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %26 = call <vscale x 1 x i32> @llvm.umin.nxv1i32(<vscale x 1 x i32> undef, <vscale x 1 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %27 = call <vscale x 2 x i32> @llvm.umin.nxv2i32(<vscale x 2 x i32> undef, <vscale x 2 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %28 = call <vscale x 4 x i32> @llvm.umin.nxv4i32(<vscale x 4 x i32> undef, <vscale x 4 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %29 = call <vscale x 8 x i32> @llvm.umin.nxv8i32(<vscale x 8 x i32> undef, <vscale x 8 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %30 = call <vscale x 16 x i32> @llvm.umin.nxv16i32(<vscale x 16 x i32> undef, <vscale x 16 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %28 = call <vscale x 4 x i32> @llvm.umin.nxv4i32(<vscale x 4 x i32> undef, <vscale x 4 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %29 = call <vscale x 8 x i32> @llvm.umin.nxv8i32(<vscale x 8 x i32> undef, <vscale x 8 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %30 = call <vscale x 16 x i32> @llvm.umin.nxv16i32(<vscale x 16 x i32> undef, <vscale x 16 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %31 = call i64 @llvm.umin.i64(i64 undef, i64 undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %32 = call <2 x i64> @llvm.umin.v2i64(<2 x i64> undef, <2 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %33 = call <4 x i64> @llvm.umin.v4i64(<4 x i64> undef, <4 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %34 = call <8 x i64> @llvm.umin.v8i64(<8 x i64> undef, <8 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %35 = call <16 x i64> @llvm.umin.v16i64(<16 x i64> undef, <16 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %33 = call <4 x i64> @llvm.umin.v4i64(<4 x i64> undef, <4 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %34 = call <8 x i64> @llvm.umin.v8i64(<8 x i64> undef, <8 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %35 = call <16 x i64> @llvm.umin.v16i64(<16 x i64> undef, <16 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %36 = call <vscale x 1 x i64> @llvm.umin.nxv1i64(<vscale x 1 x i64> undef, <vscale x 1 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %37 = call <vscale x 2 x i64> @llvm.umin.nxv2i64(<vscale x 2 x i64> undef, <vscale x 2 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %38 = call <vscale x 4 x i64> @llvm.umin.nxv4i64(<vscale x 4 x i64> undef, <vscale x 4 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %39 = call <vscale x 8 x i64> @llvm.umin.nxv8i64(<vscale x 8 x i64> undef, <vscale x 8 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %37 = call <vscale x 2 x i64> @llvm.umin.nxv2i64(<vscale x 2 x i64> undef, <vscale x 2 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %38 = call <vscale x 4 x i64> @llvm.umin.nxv4i64(<vscale x 4 x i64> undef, <vscale x 4 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %39 = call <vscale x 8 x i64> @llvm.umin.nxv8i64(<vscale x 8 x i64> undef, <vscale x 8 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void ; call i8 @llvm.umin.i8(i8 undef, i8 undef) diff --git a/llvm/test/Analysis/CostModel/RISCV/reduce-fmaximum.ll b/llvm/test/Analysis/CostModel/RISCV/reduce-fmaximum.ll index 1618c3833a9722c6bb718e9427ac0c09a1435597..f91f13b2d9ec615629a5a8c4442e971e8291bcdc 100644 --- a/llvm/test/Analysis/CostModel/RISCV/reduce-fmaximum.ll +++ b/llvm/test/Analysis/CostModel/RISCV/reduce-fmaximum.ll @@ -6,23 +6,37 @@ define float @reduce_fmaximum_f32(float %arg) { ; CHECK-LABEL: 'reduce_fmaximum_f32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call float @llvm.vector.reduce.fmaximum.v2f32(<2 x float> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V4 = call float @llvm.vector.reduce.fmaximum.v4f32(<4 x float> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %V8 = call float @llvm.vector.reduce.fmaximum.v8f32(<8 x float> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V16 = call float @llvm.vector.reduce.fmaximum.v16f32(<16 x float> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V32 = call float @llvm.vector.reduce.fmaximum.v32f32(<32 x float> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %V64 = call float @llvm.vector.reduce.fmaximum.v64f32(<64 x float> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %V128 = call float @llvm.vector.reduce.fmaximum.v128f32(<128 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V2 = call float @llvm.vector.reduce.fmaximum.v2f32(<2 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V4 = call float @llvm.vector.reduce.fmaximum.v4f32(<4 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %V8 = call float @llvm.vector.reduce.fmaximum.v8f32(<8 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %V16 = call float @llvm.vector.reduce.fmaximum.v16f32(<16 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %V32 = call float @llvm.vector.reduce.fmaximum.v32f32(<32 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %V64 = call float @llvm.vector.reduce.fmaximum.v64f32(<64 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %V128 = call float @llvm.vector.reduce.fmaximum.v128f32(<128 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %1 = call fast float @llvm.vector.reduce.fmaximum.v2f32(<2 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %2 = call fast float @llvm.vector.reduce.fmaximum.v4f32(<4 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %3 = call fast float @llvm.vector.reduce.fmaximum.v8f32(<8 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %4 = call fast float @llvm.vector.reduce.fmaximum.v16f32(<16 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %5 = call fast float @llvm.vector.reduce.fmaximum.v32f32(<32 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %6 = call fast float @llvm.vector.reduce.fmaximum.v64f32(<64 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %7 = call fast float @llvm.vector.reduce.fmaximum.v128f32(<128 x float> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float undef ; ; SIZE-LABEL: 'reduce_fmaximum_f32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call float @llvm.vector.reduce.fmaximum.v2f32(<2 x float> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call float @llvm.vector.reduce.fmaximum.v4f32(<4 x float> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call float @llvm.vector.reduce.fmaximum.v8f32(<8 x float> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call float @llvm.vector.reduce.fmaximum.v16f32(<16 x float> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call float @llvm.vector.reduce.fmaximum.v32f32(<32 x float> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V64 = call float @llvm.vector.reduce.fmaximum.v64f32(<64 x float> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V128 = call float @llvm.vector.reduce.fmaximum.v128f32(<128 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V2 = call float @llvm.vector.reduce.fmaximum.v2f32(<2 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V4 = call float @llvm.vector.reduce.fmaximum.v4f32(<4 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V8 = call float @llvm.vector.reduce.fmaximum.v8f32(<8 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V16 = call float @llvm.vector.reduce.fmaximum.v16f32(<16 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V32 = call float @llvm.vector.reduce.fmaximum.v32f32(<32 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V64 = call float @llvm.vector.reduce.fmaximum.v64f32(<64 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V128 = call float @llvm.vector.reduce.fmaximum.v128f32(<128 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %1 = call fast float @llvm.vector.reduce.fmaximum.v2f32(<2 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %2 = call fast float @llvm.vector.reduce.fmaximum.v4f32(<4 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %3 = call fast float @llvm.vector.reduce.fmaximum.v8f32(<8 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %4 = call fast float @llvm.vector.reduce.fmaximum.v16f32(<16 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %5 = call fast float @llvm.vector.reduce.fmaximum.v32f32(<32 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %6 = call fast float @llvm.vector.reduce.fmaximum.v64f32(<64 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %7 = call fast float @llvm.vector.reduce.fmaximum.v128f32(<128 x float> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret float undef ; %V2 = call float @llvm.vector.reduce.fmaximum.v2f32(<2 x float> undef) @@ -32,6 +46,13 @@ define float @reduce_fmaximum_f32(float %arg) { %V32 = call float @llvm.vector.reduce.fmaximum.v32f32(<32 x float> undef) %V64 = call float @llvm.vector.reduce.fmaximum.v64f32(<64 x float> undef) %V128 = call float @llvm.vector.reduce.fmaximum.v128f32(<128 x float> undef) +call fast float @llvm.vector.reduce.fmaximum.v2f32(<2 x float> undef) +call fast float @llvm.vector.reduce.fmaximum.v4f32(<4 x float> undef) +call fast float @llvm.vector.reduce.fmaximum.v8f32(<8 x float> undef) +call fast float @llvm.vector.reduce.fmaximum.v16f32(<16 x float> undef) +call fast float @llvm.vector.reduce.fmaximum.v32f32(<32 x float> undef) +call fast float @llvm.vector.reduce.fmaximum.v64f32(<64 x float> undef) +call fast float @llvm.vector.reduce.fmaximum.v128f32(<128 x float> undef) ret float undef } declare float @llvm.vector.reduce.fmaximum.v2f32(<2 x float>) @@ -44,21 +65,33 @@ declare float @llvm.vector.reduce.fmaximum.v128f32(<128 x float>) define double @reduce_fmaximum_f64(double %arg) { ; CHECK-LABEL: 'reduce_fmaximum_f64' -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call double @llvm.vector.reduce.fmaximum.v2f64(<2 x double> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V4 = call double @llvm.vector.reduce.fmaximum.v4f64(<4 x double> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %V8 = call double @llvm.vector.reduce.fmaximum.v8f64(<8 x double> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V16 = call double @llvm.vector.reduce.fmaximum.v16f64(<16 x double> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V32 = call double @llvm.vector.reduce.fmaximum.v32f64(<32 x double> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %V64 = call double @llvm.vector.reduce.fmaximum.v64f64(<64 x double> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V2 = call double @llvm.vector.reduce.fmaximum.v2f64(<2 x double> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V4 = call double @llvm.vector.reduce.fmaximum.v4f64(<4 x double> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %V8 = call double @llvm.vector.reduce.fmaximum.v8f64(<8 x double> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %V16 = call double @llvm.vector.reduce.fmaximum.v16f64(<16 x double> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %V32 = call double @llvm.vector.reduce.fmaximum.v32f64(<32 x double> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %V64 = call double @llvm.vector.reduce.fmaximum.v64f64(<64 x double> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %1 = call fast double @llvm.vector.reduce.fmaximum.v2f64(<2 x double> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %2 = call fast double @llvm.vector.reduce.fmaximum.v4f64(<4 x double> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %3 = call fast double @llvm.vector.reduce.fmaximum.v8f64(<8 x double> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %4 = call fast double @llvm.vector.reduce.fmaximum.v16f64(<16 x double> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %5 = call fast double @llvm.vector.reduce.fmaximum.v32f64(<32 x double> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %6 = call fast double @llvm.vector.reduce.fmaximum.v64f64(<64 x double> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret double undef ; ; SIZE-LABEL: 'reduce_fmaximum_f64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call double @llvm.vector.reduce.fmaximum.v2f64(<2 x double> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call double @llvm.vector.reduce.fmaximum.v4f64(<4 x double> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call double @llvm.vector.reduce.fmaximum.v8f64(<8 x double> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call double @llvm.vector.reduce.fmaximum.v16f64(<16 x double> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call double @llvm.vector.reduce.fmaximum.v32f64(<32 x double> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V64 = call double @llvm.vector.reduce.fmaximum.v64f64(<64 x double> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V2 = call double @llvm.vector.reduce.fmaximum.v2f64(<2 x double> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V4 = call double @llvm.vector.reduce.fmaximum.v4f64(<4 x double> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V8 = call double @llvm.vector.reduce.fmaximum.v8f64(<8 x double> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V16 = call double @llvm.vector.reduce.fmaximum.v16f64(<16 x double> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V32 = call double @llvm.vector.reduce.fmaximum.v32f64(<32 x double> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V64 = call double @llvm.vector.reduce.fmaximum.v64f64(<64 x double> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %1 = call fast double @llvm.vector.reduce.fmaximum.v2f64(<2 x double> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %2 = call fast double @llvm.vector.reduce.fmaximum.v4f64(<4 x double> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %3 = call fast double @llvm.vector.reduce.fmaximum.v8f64(<8 x double> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %4 = call fast double @llvm.vector.reduce.fmaximum.v16f64(<16 x double> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %5 = call fast double @llvm.vector.reduce.fmaximum.v32f64(<32 x double> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %6 = call fast double @llvm.vector.reduce.fmaximum.v64f64(<64 x double> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret double undef ; %V2 = call double @llvm.vector.reduce.fmaximum.v2f64(<2 x double> undef) @@ -67,6 +100,12 @@ define double @reduce_fmaximum_f64(double %arg) { %V16 = call double @llvm.vector.reduce.fmaximum.v16f64(<16 x double> undef) %V32 = call double @llvm.vector.reduce.fmaximum.v32f64(<32 x double> undef) %V64 = call double @llvm.vector.reduce.fmaximum.v64f64(<64 x double> undef) +call fast double @llvm.vector.reduce.fmaximum.v2f64(<2 x double> undef) +call fast double @llvm.vector.reduce.fmaximum.v4f64(<4 x double> undef) +call fast double @llvm.vector.reduce.fmaximum.v8f64(<8 x double> undef) +call fast double @llvm.vector.reduce.fmaximum.v16f64(<16 x double> undef) +call fast double @llvm.vector.reduce.fmaximum.v32f64(<32 x double> undef) +call fast double @llvm.vector.reduce.fmaximum.v64f64(<64 x double> undef) ret double undef } declare double @llvm.vector.reduce.fmaximum.v2f64(<2 x double>) diff --git a/llvm/test/Analysis/CostModel/RISCV/reduce-fminimum.ll b/llvm/test/Analysis/CostModel/RISCV/reduce-fminimum.ll index 35b18645b1f2de0a7e35cf6d57550e8c5e4d5d28..86b84025ad5418bcceac4d3cc2eba086e5a33b3e 100644 --- a/llvm/test/Analysis/CostModel/RISCV/reduce-fminimum.ll +++ b/llvm/test/Analysis/CostModel/RISCV/reduce-fminimum.ll @@ -6,23 +6,23 @@ define float @reduce_fmaximum_f32(float %arg) { ; CHECK-LABEL: 'reduce_fmaximum_f32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call float @llvm.vector.reduce.fminimum.v2f32(<2 x float> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V4 = call float @llvm.vector.reduce.fminimum.v4f32(<4 x float> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %V8 = call float @llvm.vector.reduce.fminimum.v8f32(<8 x float> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V16 = call float @llvm.vector.reduce.fminimum.v16f32(<16 x float> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V32 = call float @llvm.vector.reduce.fminimum.v32f32(<32 x float> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %V64 = call float @llvm.vector.reduce.fminimum.v64f32(<64 x float> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %V128 = call float @llvm.vector.reduce.fminimum.v128f32(<128 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V2 = call float @llvm.vector.reduce.fminimum.v2f32(<2 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V4 = call float @llvm.vector.reduce.fminimum.v4f32(<4 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %V8 = call float @llvm.vector.reduce.fminimum.v8f32(<8 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %V16 = call float @llvm.vector.reduce.fminimum.v16f32(<16 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 13 for instruction: %V32 = call float @llvm.vector.reduce.fminimum.v32f32(<32 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %V64 = call float @llvm.vector.reduce.fminimum.v64f32(<64 x float> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %V128 = call float @llvm.vector.reduce.fminimum.v128f32(<128 x float> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float undef ; ; SIZE-LABEL: 'reduce_fmaximum_f32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call float @llvm.vector.reduce.fminimum.v2f32(<2 x float> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call float @llvm.vector.reduce.fminimum.v4f32(<4 x float> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call float @llvm.vector.reduce.fminimum.v8f32(<8 x float> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call float @llvm.vector.reduce.fminimum.v16f32(<16 x float> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call float @llvm.vector.reduce.fminimum.v32f32(<32 x float> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V64 = call float @llvm.vector.reduce.fminimum.v64f32(<64 x float> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V128 = call float @llvm.vector.reduce.fminimum.v128f32(<128 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V2 = call float @llvm.vector.reduce.fminimum.v2f32(<2 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V4 = call float @llvm.vector.reduce.fminimum.v4f32(<4 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V8 = call float @llvm.vector.reduce.fminimum.v8f32(<8 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V16 = call float @llvm.vector.reduce.fminimum.v16f32(<16 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V32 = call float @llvm.vector.reduce.fminimum.v32f32(<32 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V64 = call float @llvm.vector.reduce.fminimum.v64f32(<64 x float> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V128 = call float @llvm.vector.reduce.fminimum.v128f32(<128 x float> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret float undef ; %V2 = call float @llvm.vector.reduce.fminimum.v2f32(<2 x float> undef) @@ -44,21 +44,21 @@ declare float @llvm.vector.reduce.fminimum.v128f32(<128 x float>) define double @reduce_fmaximum_f64(double %arg) { ; CHECK-LABEL: 'reduce_fmaximum_f64' -; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call double @llvm.vector.reduce.fminimum.v2f64(<2 x double> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V4 = call double @llvm.vector.reduce.fminimum.v4f64(<4 x double> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %V8 = call double @llvm.vector.reduce.fminimum.v8f64(<8 x double> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V16 = call double @llvm.vector.reduce.fminimum.v16f64(<16 x double> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V32 = call double @llvm.vector.reduce.fminimum.v32f64(<32 x double> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %V64 = call double @llvm.vector.reduce.fminimum.v64f64(<64 x double> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V2 = call double @llvm.vector.reduce.fminimum.v2f64(<2 x double> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V4 = call double @llvm.vector.reduce.fminimum.v4f64(<4 x double> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %V8 = call double @llvm.vector.reduce.fminimum.v8f64(<8 x double> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %V16 = call double @llvm.vector.reduce.fminimum.v16f64(<16 x double> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %V32 = call double @llvm.vector.reduce.fminimum.v32f64(<32 x double> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %V64 = call double @llvm.vector.reduce.fminimum.v64f64(<64 x double> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret double undef ; ; SIZE-LABEL: 'reduce_fmaximum_f64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call double @llvm.vector.reduce.fminimum.v2f64(<2 x double> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call double @llvm.vector.reduce.fminimum.v4f64(<4 x double> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call double @llvm.vector.reduce.fminimum.v8f64(<8 x double> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call double @llvm.vector.reduce.fminimum.v16f64(<16 x double> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call double @llvm.vector.reduce.fminimum.v32f64(<32 x double> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V64 = call double @llvm.vector.reduce.fminimum.v64f64(<64 x double> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V2 = call double @llvm.vector.reduce.fminimum.v2f64(<2 x double> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V4 = call double @llvm.vector.reduce.fminimum.v4f64(<4 x double> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V8 = call double @llvm.vector.reduce.fminimum.v8f64(<8 x double> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V16 = call double @llvm.vector.reduce.fminimum.v16f64(<16 x double> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V32 = call double @llvm.vector.reduce.fminimum.v32f64(<32 x double> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V64 = call double @llvm.vector.reduce.fminimum.v64f64(<64 x double> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret double undef ; %V2 = call double @llvm.vector.reduce.fminimum.v2f64(<2 x double> undef) diff --git a/llvm/test/Analysis/CostModel/RISCV/reduce-max.ll b/llvm/test/Analysis/CostModel/RISCV/reduce-max.ll index f3436b54df90ab2d92ffa1a293ca2fcf43ae79a9..533a77dbd9f71795e9ac128de8cff51d33b12402 100644 --- a/llvm/test/Analysis/CostModel/RISCV/reduce-max.ll +++ b/llvm/test/Analysis/CostModel/RISCV/reduce-max.ll @@ -51,14 +51,14 @@ define i32 @reduce_umax_i8(i32 %arg) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIZE-LABEL: 'reduce_umax_i8' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1 = call i8 @llvm.vector.reduce.umax.v1i8(<1 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call i8 @llvm.vector.reduce.umax.v2i8(<2 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call i8 @llvm.vector.reduce.umax.v4i8(<4 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call i8 @llvm.vector.reduce.umax.v8i8(<8 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call i8 @llvm.vector.reduce.umax.v16i8(<16 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call i8 @llvm.vector.reduce.umax.v32i8(<32 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V64 = call i8 @llvm.vector.reduce.umax.v64i8(<64 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V128 = call i8 @llvm.vector.reduce.umax.v128i8(<128 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V1 = call i8 @llvm.vector.reduce.umax.v1i8(<1 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call i8 @llvm.vector.reduce.umax.v2i8(<2 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V4 = call i8 @llvm.vector.reduce.umax.v4i8(<4 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V8 = call i8 @llvm.vector.reduce.umax.v8i8(<8 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V16 = call i8 @llvm.vector.reduce.umax.v16i8(<16 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V32 = call i8 @llvm.vector.reduce.umax.v32i8(<32 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V64 = call i8 @llvm.vector.reduce.umax.v64i8(<64 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V128 = call i8 @llvm.vector.reduce.umax.v128i8(<128 x i8> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; %V1 = call i8 @llvm.vector.reduce.umax.v1i8(<1 x i8> undef) @@ -85,14 +85,14 @@ define i32 @reduce_umax_i16(i32 %arg) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIZE-LABEL: 'reduce_umax_i16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1 = call i16 @llvm.vector.reduce.umax.v1i16(<1 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call i16 @llvm.vector.reduce.umax.v2i16(<2 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call i16 @llvm.vector.reduce.umax.v4i16(<4 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call i16 @llvm.vector.reduce.umax.v8i16(<8 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call i16 @llvm.vector.reduce.umax.v16i16(<16 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call i16 @llvm.vector.reduce.umax.v32i16(<32 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V64 = call i16 @llvm.vector.reduce.umax.v64i16(<64 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V128 = call i16 @llvm.vector.reduce.umax.v128i16(<128 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V1 = call i16 @llvm.vector.reduce.umax.v1i16(<1 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call i16 @llvm.vector.reduce.umax.v2i16(<2 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V4 = call i16 @llvm.vector.reduce.umax.v4i16(<4 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V8 = call i16 @llvm.vector.reduce.umax.v8i16(<8 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V16 = call i16 @llvm.vector.reduce.umax.v16i16(<16 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V32 = call i16 @llvm.vector.reduce.umax.v32i16(<32 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V64 = call i16 @llvm.vector.reduce.umax.v64i16(<64 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V128 = call i16 @llvm.vector.reduce.umax.v128i16(<128 x i16> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; %V1 = call i16 @llvm.vector.reduce.umax.v1i16(<1 x i16> undef) @@ -115,18 +115,18 @@ define i32 @reduce_umax_i32(i32 %arg) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V16 = call i32 @llvm.vector.reduce.umax.v16i32(<16 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V32 = call i32 @llvm.vector.reduce.umax.v32i32(<32 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %V64 = call i32 @llvm.vector.reduce.umax.v64i32(<64 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %V128 = call i32 @llvm.vector.reduce.umax.v128i32(<128 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %V128 = call i32 @llvm.vector.reduce.umax.v128i32(<128 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIZE-LABEL: 'reduce_umax_i32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1 = call i32 @llvm.vector.reduce.umax.v1i32(<1 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call i32 @llvm.vector.reduce.umax.v2i32(<2 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call i32 @llvm.vector.reduce.umax.v8i32(<8 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call i32 @llvm.vector.reduce.umax.v16i32(<16 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call i32 @llvm.vector.reduce.umax.v32i32(<32 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V64 = call i32 @llvm.vector.reduce.umax.v64i32(<64 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V128 = call i32 @llvm.vector.reduce.umax.v128i32(<128 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V1 = call i32 @llvm.vector.reduce.umax.v1i32(<1 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call i32 @llvm.vector.reduce.umax.v2i32(<2 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V4 = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V8 = call i32 @llvm.vector.reduce.umax.v8i32(<8 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V16 = call i32 @llvm.vector.reduce.umax.v16i32(<16 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V32 = call i32 @llvm.vector.reduce.umax.v32i32(<32 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V64 = call i32 @llvm.vector.reduce.umax.v64i32(<64 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V128 = call i32 @llvm.vector.reduce.umax.v128i32(<128 x i32> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; %V1 = call i32 @llvm.vector.reduce.umax.v1i32(<1 x i32> undef) @@ -148,19 +148,19 @@ define i32 @reduce_umax_i64(i32 %arg) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %V8 = call i64 @llvm.vector.reduce.umax.v8i64(<8 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V16 = call i64 @llvm.vector.reduce.umax.v16i64(<16 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V32 = call i64 @llvm.vector.reduce.umax.v32i64(<32 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %V64 = call i64 @llvm.vector.reduce.umax.v64i64(<64 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %V128 = call i64 @llvm.vector.reduce.umax.v128i64(<128 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %V64 = call i64 @llvm.vector.reduce.umax.v64i64(<64 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %V128 = call i64 @llvm.vector.reduce.umax.v128i64(<128 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIZE-LABEL: 'reduce_umax_i64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1 = call i64 @llvm.vector.reduce.umax.v1i64(<1 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call i64 @llvm.vector.reduce.umax.v2i64(<2 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call i64 @llvm.vector.reduce.umax.v4i64(<4 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call i64 @llvm.vector.reduce.umax.v8i64(<8 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call i64 @llvm.vector.reduce.umax.v16i64(<16 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call i64 @llvm.vector.reduce.umax.v32i64(<32 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V64 = call i64 @llvm.vector.reduce.umax.v64i64(<64 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %V128 = call i64 @llvm.vector.reduce.umax.v128i64(<128 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V1 = call i64 @llvm.vector.reduce.umax.v1i64(<1 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call i64 @llvm.vector.reduce.umax.v2i64(<2 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V4 = call i64 @llvm.vector.reduce.umax.v4i64(<4 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V8 = call i64 @llvm.vector.reduce.umax.v8i64(<8 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V16 = call i64 @llvm.vector.reduce.umax.v16i64(<16 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V32 = call i64 @llvm.vector.reduce.umax.v32i64(<32 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V64 = call i64 @llvm.vector.reduce.umax.v64i64(<64 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V128 = call i64 @llvm.vector.reduce.umax.v128i64(<128 x i64> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; %V1 = call i64 @llvm.vector.reduce.umax.v1i64(<1 x i64> undef) @@ -221,14 +221,14 @@ define i32 @reduce_smax_i8(i32 %arg) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIZE-LABEL: 'reduce_smax_i8' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1 = call i8 @llvm.vector.reduce.smax.v1i8(<1 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call i8 @llvm.vector.reduce.smax.v2i8(<2 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call i8 @llvm.vector.reduce.smax.v4i8(<4 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call i8 @llvm.vector.reduce.smax.v8i8(<8 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call i8 @llvm.vector.reduce.smax.v16i8(<16 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call i8 @llvm.vector.reduce.smax.v32i8(<32 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V64 = call i8 @llvm.vector.reduce.smax.v64i8(<64 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V128 = call i8 @llvm.vector.reduce.smax.v128i8(<128 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V1 = call i8 @llvm.vector.reduce.smax.v1i8(<1 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call i8 @llvm.vector.reduce.smax.v2i8(<2 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V4 = call i8 @llvm.vector.reduce.smax.v4i8(<4 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V8 = call i8 @llvm.vector.reduce.smax.v8i8(<8 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V16 = call i8 @llvm.vector.reduce.smax.v16i8(<16 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V32 = call i8 @llvm.vector.reduce.smax.v32i8(<32 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V64 = call i8 @llvm.vector.reduce.smax.v64i8(<64 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V128 = call i8 @llvm.vector.reduce.smax.v128i8(<128 x i8> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; %V1 = call i8 @llvm.vector.reduce.smax.v1i8(<1 x i8> undef) @@ -255,14 +255,14 @@ define i32 @reduce_smax_i16(i32 %arg) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIZE-LABEL: 'reduce_smax_i16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1 = call i16 @llvm.vector.reduce.smax.v1i16(<1 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call i16 @llvm.vector.reduce.smax.v2i16(<2 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call i16 @llvm.vector.reduce.smax.v4i16(<4 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call i16 @llvm.vector.reduce.smax.v8i16(<8 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call i16 @llvm.vector.reduce.smax.v16i16(<16 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call i16 @llvm.vector.reduce.smax.v32i16(<32 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V64 = call i16 @llvm.vector.reduce.smax.v64i16(<64 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V128 = call i16 @llvm.vector.reduce.smax.v128i16(<128 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V1 = call i16 @llvm.vector.reduce.smax.v1i16(<1 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call i16 @llvm.vector.reduce.smax.v2i16(<2 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V4 = call i16 @llvm.vector.reduce.smax.v4i16(<4 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V8 = call i16 @llvm.vector.reduce.smax.v8i16(<8 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V16 = call i16 @llvm.vector.reduce.smax.v16i16(<16 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V32 = call i16 @llvm.vector.reduce.smax.v32i16(<32 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V64 = call i16 @llvm.vector.reduce.smax.v64i16(<64 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V128 = call i16 @llvm.vector.reduce.smax.v128i16(<128 x i16> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; %V1 = call i16 @llvm.vector.reduce.smax.v1i16(<1 x i16> undef) @@ -285,18 +285,18 @@ define i32 @reduce_smax_i32(i32 %arg) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V16 = call i32 @llvm.vector.reduce.smax.v16i32(<16 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V32 = call i32 @llvm.vector.reduce.smax.v32i32(<32 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %V64 = call i32 @llvm.vector.reduce.smax.v64i32(<64 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %V128 = call i32 @llvm.vector.reduce.smax.v128i32(<128 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %V128 = call i32 @llvm.vector.reduce.smax.v128i32(<128 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIZE-LABEL: 'reduce_smax_i32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1 = call i32 @llvm.vector.reduce.smax.v1i32(<1 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call i32 @llvm.vector.reduce.smax.v2i32(<2 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call i32 @llvm.vector.reduce.smax.v4i32(<4 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call i32 @llvm.vector.reduce.smax.v8i32(<8 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call i32 @llvm.vector.reduce.smax.v16i32(<16 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call i32 @llvm.vector.reduce.smax.v32i32(<32 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V64 = call i32 @llvm.vector.reduce.smax.v64i32(<64 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V128 = call i32 @llvm.vector.reduce.smax.v128i32(<128 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V1 = call i32 @llvm.vector.reduce.smax.v1i32(<1 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call i32 @llvm.vector.reduce.smax.v2i32(<2 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V4 = call i32 @llvm.vector.reduce.smax.v4i32(<4 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V8 = call i32 @llvm.vector.reduce.smax.v8i32(<8 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V16 = call i32 @llvm.vector.reduce.smax.v16i32(<16 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V32 = call i32 @llvm.vector.reduce.smax.v32i32(<32 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V64 = call i32 @llvm.vector.reduce.smax.v64i32(<64 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V128 = call i32 @llvm.vector.reduce.smax.v128i32(<128 x i32> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; %V1 = call i32 @llvm.vector.reduce.smax.v1i32(<1 x i32> undef) @@ -318,19 +318,19 @@ define i32 @reduce_smax_i64(i32 %arg) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %V8 = call i64 @llvm.vector.reduce.smax.v8i64(<8 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V16 = call i64 @llvm.vector.reduce.smax.v16i64(<16 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V32 = call i64 @llvm.vector.reduce.smax.v32i64(<32 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %V64 = call i64 @llvm.vector.reduce.smax.v64i64(<64 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %V128 = call i64 @llvm.vector.reduce.smax.v128i64(<128 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %V64 = call i64 @llvm.vector.reduce.smax.v64i64(<64 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %V128 = call i64 @llvm.vector.reduce.smax.v128i64(<128 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIZE-LABEL: 'reduce_smax_i64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1 = call i64 @llvm.vector.reduce.smax.v1i64(<1 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call i64 @llvm.vector.reduce.smax.v2i64(<2 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call i64 @llvm.vector.reduce.smax.v4i64(<4 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call i64 @llvm.vector.reduce.smax.v8i64(<8 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call i64 @llvm.vector.reduce.smax.v16i64(<16 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call i64 @llvm.vector.reduce.smax.v32i64(<32 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V64 = call i64 @llvm.vector.reduce.smax.v64i64(<64 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %V128 = call i64 @llvm.vector.reduce.smax.v128i64(<128 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V1 = call i64 @llvm.vector.reduce.smax.v1i64(<1 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call i64 @llvm.vector.reduce.smax.v2i64(<2 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V4 = call i64 @llvm.vector.reduce.smax.v4i64(<4 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V8 = call i64 @llvm.vector.reduce.smax.v8i64(<8 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V16 = call i64 @llvm.vector.reduce.smax.v16i64(<16 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V32 = call i64 @llvm.vector.reduce.smax.v32i64(<32 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V64 = call i64 @llvm.vector.reduce.smax.v64i64(<64 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V128 = call i64 @llvm.vector.reduce.smax.v128i64(<128 x i64> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; %V1 = call i64 @llvm.vector.reduce.smax.v1i64(<1 x i64> undef) diff --git a/llvm/test/Analysis/CostModel/RISCV/reduce-min.ll b/llvm/test/Analysis/CostModel/RISCV/reduce-min.ll index 1964e35b81b1a657fa554866400087e79913c145..ae99118d4d3af93cc45cbf8acccafc29fe6a135c 100644 --- a/llvm/test/Analysis/CostModel/RISCV/reduce-min.ll +++ b/llvm/test/Analysis/CostModel/RISCV/reduce-min.ll @@ -51,14 +51,14 @@ define i32 @reduce_umin_i8(i32 %arg) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIZE-LABEL: 'reduce_umin_i8' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1 = call i8 @llvm.vector.reduce.umin.v1i8(<1 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call i8 @llvm.vector.reduce.umin.v2i8(<2 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call i8 @llvm.vector.reduce.umin.v4i8(<4 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call i8 @llvm.vector.reduce.umin.v8i8(<8 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call i8 @llvm.vector.reduce.umin.v16i8(<16 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call i8 @llvm.vector.reduce.umin.v32i8(<32 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V64 = call i8 @llvm.vector.reduce.umin.v64i8(<64 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V128 = call i8 @llvm.vector.reduce.umin.v128i8(<128 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V1 = call i8 @llvm.vector.reduce.umin.v1i8(<1 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call i8 @llvm.vector.reduce.umin.v2i8(<2 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V4 = call i8 @llvm.vector.reduce.umin.v4i8(<4 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V8 = call i8 @llvm.vector.reduce.umin.v8i8(<8 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V16 = call i8 @llvm.vector.reduce.umin.v16i8(<16 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V32 = call i8 @llvm.vector.reduce.umin.v32i8(<32 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V64 = call i8 @llvm.vector.reduce.umin.v64i8(<64 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V128 = call i8 @llvm.vector.reduce.umin.v128i8(<128 x i8> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; %V1 = call i8 @llvm.vector.reduce.umin.v1i8(<1 x i8> undef) @@ -85,14 +85,14 @@ define i32 @reduce_umin_i16(i32 %arg) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIZE-LABEL: 'reduce_umin_i16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1 = call i16 @llvm.vector.reduce.umin.v1i16(<1 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call i16 @llvm.vector.reduce.umin.v2i16(<2 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call i16 @llvm.vector.reduce.umin.v4i16(<4 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call i16 @llvm.vector.reduce.umin.v8i16(<8 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call i16 @llvm.vector.reduce.umin.v16i16(<16 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call i16 @llvm.vector.reduce.umin.v32i16(<32 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V64 = call i16 @llvm.vector.reduce.umin.v64i16(<64 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V128 = call i16 @llvm.vector.reduce.umin.v128i16(<128 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V1 = call i16 @llvm.vector.reduce.umin.v1i16(<1 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call i16 @llvm.vector.reduce.umin.v2i16(<2 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V4 = call i16 @llvm.vector.reduce.umin.v4i16(<4 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V8 = call i16 @llvm.vector.reduce.umin.v8i16(<8 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V16 = call i16 @llvm.vector.reduce.umin.v16i16(<16 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V32 = call i16 @llvm.vector.reduce.umin.v32i16(<32 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V64 = call i16 @llvm.vector.reduce.umin.v64i16(<64 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V128 = call i16 @llvm.vector.reduce.umin.v128i16(<128 x i16> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; %V1 = call i16 @llvm.vector.reduce.umin.v1i16(<1 x i16> undef) @@ -115,18 +115,18 @@ define i32 @reduce_umin_i32(i32 %arg) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V16 = call i32 @llvm.vector.reduce.umin.v16i32(<16 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V32 = call i32 @llvm.vector.reduce.umin.v32i32(<32 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %V64 = call i32 @llvm.vector.reduce.umin.v64i32(<64 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %V128 = call i32 @llvm.vector.reduce.umin.v128i32(<128 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %V128 = call i32 @llvm.vector.reduce.umin.v128i32(<128 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIZE-LABEL: 'reduce_umin_i32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1 = call i32 @llvm.vector.reduce.umin.v1i32(<1 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call i32 @llvm.vector.reduce.umin.v2i32(<2 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call i32 @llvm.vector.reduce.umin.v8i32(<8 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call i32 @llvm.vector.reduce.umin.v16i32(<16 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call i32 @llvm.vector.reduce.umin.v32i32(<32 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V64 = call i32 @llvm.vector.reduce.umin.v64i32(<64 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V128 = call i32 @llvm.vector.reduce.umin.v128i32(<128 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V1 = call i32 @llvm.vector.reduce.umin.v1i32(<1 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call i32 @llvm.vector.reduce.umin.v2i32(<2 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V4 = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V8 = call i32 @llvm.vector.reduce.umin.v8i32(<8 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V16 = call i32 @llvm.vector.reduce.umin.v16i32(<16 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V32 = call i32 @llvm.vector.reduce.umin.v32i32(<32 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V64 = call i32 @llvm.vector.reduce.umin.v64i32(<64 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V128 = call i32 @llvm.vector.reduce.umin.v128i32(<128 x i32> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; %V1 = call i32 @llvm.vector.reduce.umin.v1i32(<1 x i32> undef) @@ -148,19 +148,19 @@ define i32 @reduce_umin_i64(i32 %arg) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %V8 = call i64 @llvm.vector.reduce.umin.v8i64(<8 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V16 = call i64 @llvm.vector.reduce.umin.v16i64(<16 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V32 = call i64 @llvm.vector.reduce.umin.v32i64(<32 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %V64 = call i64 @llvm.vector.reduce.umin.v64i64(<64 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %V128 = call i64 @llvm.vector.reduce.umin.v128i64(<128 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %V64 = call i64 @llvm.vector.reduce.umin.v64i64(<64 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %V128 = call i64 @llvm.vector.reduce.umin.v128i64(<128 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIZE-LABEL: 'reduce_umin_i64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1 = call i64 @llvm.vector.reduce.umin.v1i64(<1 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call i64 @llvm.vector.reduce.umin.v2i64(<2 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call i64 @llvm.vector.reduce.umin.v4i64(<4 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call i64 @llvm.vector.reduce.umin.v8i64(<8 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call i64 @llvm.vector.reduce.umin.v16i64(<16 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call i64 @llvm.vector.reduce.umin.v32i64(<32 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V64 = call i64 @llvm.vector.reduce.umin.v64i64(<64 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %V128 = call i64 @llvm.vector.reduce.umin.v128i64(<128 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V1 = call i64 @llvm.vector.reduce.umin.v1i64(<1 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call i64 @llvm.vector.reduce.umin.v2i64(<2 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V4 = call i64 @llvm.vector.reduce.umin.v4i64(<4 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V8 = call i64 @llvm.vector.reduce.umin.v8i64(<8 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V16 = call i64 @llvm.vector.reduce.umin.v16i64(<16 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V32 = call i64 @llvm.vector.reduce.umin.v32i64(<32 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V64 = call i64 @llvm.vector.reduce.umin.v64i64(<64 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V128 = call i64 @llvm.vector.reduce.umin.v128i64(<128 x i64> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; %V1 = call i64 @llvm.vector.reduce.umin.v1i64(<1 x i64> undef) @@ -221,14 +221,14 @@ define i32 @reduce_smin_i8(i32 %arg) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIZE-LABEL: 'reduce_smin_i8' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1 = call i8 @llvm.vector.reduce.smin.v1i8(<1 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call i8 @llvm.vector.reduce.smin.v2i8(<2 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call i8 @llvm.vector.reduce.smin.v4i8(<4 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call i8 @llvm.vector.reduce.smin.v8i8(<8 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call i8 @llvm.vector.reduce.smin.v16i8(<16 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call i8 @llvm.vector.reduce.smin.v32i8(<32 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V64 = call i8 @llvm.vector.reduce.smin.v64i8(<64 x i8> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V128 = call i8 @llvm.vector.reduce.smin.v128i8(<128 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V1 = call i8 @llvm.vector.reduce.smin.v1i8(<1 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call i8 @llvm.vector.reduce.smin.v2i8(<2 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V4 = call i8 @llvm.vector.reduce.smin.v4i8(<4 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V8 = call i8 @llvm.vector.reduce.smin.v8i8(<8 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V16 = call i8 @llvm.vector.reduce.smin.v16i8(<16 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V32 = call i8 @llvm.vector.reduce.smin.v32i8(<32 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V64 = call i8 @llvm.vector.reduce.smin.v64i8(<64 x i8> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V128 = call i8 @llvm.vector.reduce.smin.v128i8(<128 x i8> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; %V1 = call i8 @llvm.vector.reduce.smin.v1i8(<1 x i8> undef) @@ -255,14 +255,14 @@ define i32 @reduce_smin_i16(i32 %arg) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIZE-LABEL: 'reduce_smin_i16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1 = call i16 @llvm.vector.reduce.smin.v1i16(<1 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call i16 @llvm.vector.reduce.smin.v2i16(<2 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call i16 @llvm.vector.reduce.smin.v4i16(<4 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call i16 @llvm.vector.reduce.smin.v8i16(<8 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call i16 @llvm.vector.reduce.smin.v16i16(<16 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call i16 @llvm.vector.reduce.smin.v32i16(<32 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V64 = call i16 @llvm.vector.reduce.smin.v64i16(<64 x i16> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V128 = call i16 @llvm.vector.reduce.smin.v128i16(<128 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V1 = call i16 @llvm.vector.reduce.smin.v1i16(<1 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call i16 @llvm.vector.reduce.smin.v2i16(<2 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V4 = call i16 @llvm.vector.reduce.smin.v4i16(<4 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V8 = call i16 @llvm.vector.reduce.smin.v8i16(<8 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V16 = call i16 @llvm.vector.reduce.smin.v16i16(<16 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V32 = call i16 @llvm.vector.reduce.smin.v32i16(<32 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V64 = call i16 @llvm.vector.reduce.smin.v64i16(<64 x i16> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V128 = call i16 @llvm.vector.reduce.smin.v128i16(<128 x i16> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; %V1 = call i16 @llvm.vector.reduce.smin.v1i16(<1 x i16> undef) @@ -285,18 +285,18 @@ define i32 @reduce_smin_i32(i32 %arg) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V16 = call i32 @llvm.vector.reduce.smin.v16i32(<16 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V32 = call i32 @llvm.vector.reduce.smin.v32i32(<32 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %V64 = call i32 @llvm.vector.reduce.smin.v64i32(<64 x i32> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %V128 = call i32 @llvm.vector.reduce.smin.v128i32(<128 x i32> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %V128 = call i32 @llvm.vector.reduce.smin.v128i32(<128 x i32> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIZE-LABEL: 'reduce_smin_i32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1 = call i32 @llvm.vector.reduce.smin.v1i32(<1 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call i32 @llvm.vector.reduce.smin.v2i32(<2 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call i32 @llvm.vector.reduce.smin.v4i32(<4 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call i32 @llvm.vector.reduce.smin.v8i32(<8 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call i32 @llvm.vector.reduce.smin.v16i32(<16 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call i32 @llvm.vector.reduce.smin.v32i32(<32 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V64 = call i32 @llvm.vector.reduce.smin.v64i32(<64 x i32> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V128 = call i32 @llvm.vector.reduce.smin.v128i32(<128 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V1 = call i32 @llvm.vector.reduce.smin.v1i32(<1 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call i32 @llvm.vector.reduce.smin.v2i32(<2 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V4 = call i32 @llvm.vector.reduce.smin.v4i32(<4 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V8 = call i32 @llvm.vector.reduce.smin.v8i32(<8 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V16 = call i32 @llvm.vector.reduce.smin.v16i32(<16 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V32 = call i32 @llvm.vector.reduce.smin.v32i32(<32 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V64 = call i32 @llvm.vector.reduce.smin.v64i32(<64 x i32> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V128 = call i32 @llvm.vector.reduce.smin.v128i32(<128 x i32> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; %V1 = call i32 @llvm.vector.reduce.smin.v1i32(<1 x i32> undef) @@ -318,19 +318,19 @@ define i32 @reduce_smin_i64(i32 %arg) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %V8 = call i64 @llvm.vector.reduce.smin.v8i64(<8 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V16 = call i64 @llvm.vector.reduce.smin.v16i64(<16 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %V32 = call i64 @llvm.vector.reduce.smin.v32i64(<32 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %V64 = call i64 @llvm.vector.reduce.smin.v64i64(<64 x i64> undef) -; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %V128 = call i64 @llvm.vector.reduce.smin.v128i64(<128 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %V64 = call i64 @llvm.vector.reduce.smin.v64i64(<64 x i64> undef) +; CHECK-NEXT: Cost Model: Found an estimated cost of 31 for instruction: %V128 = call i64 @llvm.vector.reduce.smin.v128i64(<128 x i64> undef) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 undef ; ; SIZE-LABEL: 'reduce_smin_i64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V1 = call i64 @llvm.vector.reduce.smin.v1i64(<1 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V2 = call i64 @llvm.vector.reduce.smin.v2i64(<2 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V4 = call i64 @llvm.vector.reduce.smin.v4i64(<4 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V8 = call i64 @llvm.vector.reduce.smin.v8i64(<8 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V16 = call i64 @llvm.vector.reduce.smin.v16i64(<16 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %V32 = call i64 @llvm.vector.reduce.smin.v32i64(<32 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V64 = call i64 @llvm.vector.reduce.smin.v64i64(<64 x i64> undef) -; SIZE-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %V128 = call i64 @llvm.vector.reduce.smin.v128i64(<128 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V1 = call i64 @llvm.vector.reduce.smin.v1i64(<1 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V2 = call i64 @llvm.vector.reduce.smin.v2i64(<2 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V4 = call i64 @llvm.vector.reduce.smin.v4i64(<4 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V8 = call i64 @llvm.vector.reduce.smin.v8i64(<8 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V16 = call i64 @llvm.vector.reduce.smin.v16i64(<16 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %V32 = call i64 @llvm.vector.reduce.smin.v32i64(<32 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %V64 = call i64 @llvm.vector.reduce.smin.v64i64(<64 x i64> undef) +; SIZE-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %V128 = call i64 @llvm.vector.reduce.smin.v128i64(<128 x i64> undef) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; %V1 = call i64 @llvm.vector.reduce.smin.v1i64(<1 x i64> undef) diff --git a/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-fp.ll b/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-fp.ll index 0dd3e3cf53e1cade81febeb0d33a353ab2426a56..a9a5f4d2de5419ac8f7aec17b6ed76761f131a14 100644 --- a/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-fp.ll +++ b/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-fp.ll @@ -238,7 +238,7 @@ define float @vreduce_ord_fadd_nxv4f32(<vscale x 4 x float> %v, float %s) { define float @vreduce_fwadd_nxv4f32(<vscale x 4 x half> %v, float %s) { ; CHECK-LABEL: 'vreduce_fwadd_nxv4f32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = fpext <vscale x 4 x half> %v to <vscale x 4 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = fpext <vscale x 4 x half> %v to <vscale x 4 x float> ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %red = call reassoc float @llvm.vector.reduce.fadd.nxv4f32(float %s, <vscale x 4 x float> %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float %red ; @@ -254,7 +254,7 @@ define float @vreduce_fwadd_nxv4f32(<vscale x 4 x half> %v, float %s) { define float @vreduce_ord_fwadd_nxv4f32(<vscale x 4 x half> %v, float %s) { ; CHECK-LABEL: 'vreduce_ord_fwadd_nxv4f32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = fpext <vscale x 4 x half> %v to <vscale x 4 x float> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = fpext <vscale x 4 x half> %v to <vscale x 4 x float> ; CHECK-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %red = call float @llvm.vector.reduce.fadd.nxv4f32(float %s, <vscale x 4 x float> %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float %red ; @@ -358,7 +358,7 @@ define double @vreduce_ord_fadd_nxv2f64(<vscale x 2 x double> %v, double %s) { define double @vreduce_fwadd_nxv2f64(<vscale x 2 x float> %v, double %s) { ; CHECK-LABEL: 'vreduce_fwadd_nxv2f64' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = fpext <vscale x 2 x float> %v to <vscale x 2 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = fpext <vscale x 2 x float> %v to <vscale x 2 x double> ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %red = call reassoc double @llvm.vector.reduce.fadd.nxv2f64(double %s, <vscale x 2 x double> %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret double %red ; @@ -374,7 +374,7 @@ define double @vreduce_fwadd_nxv2f64(<vscale x 2 x float> %v, double %s) { define double @vreduce_ord_fwadd_nxv2f64(<vscale x 2 x float> %v, double %s) { ; CHECK-LABEL: 'vreduce_ord_fwadd_nxv2f64' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = fpext <vscale x 2 x float> %v to <vscale x 2 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = fpext <vscale x 2 x float> %v to <vscale x 2 x double> ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %red = call double @llvm.vector.reduce.fadd.nxv2f64(double %s, <vscale x 2 x double> %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret double %red ; @@ -418,7 +418,7 @@ define double @vreduce_ord_fadd_nxv4f64(<vscale x 4 x double> %v, double %s) { define double @vreduce_fwadd_nxv4f64(<vscale x 4 x float> %v, double %s) { ; CHECK-LABEL: 'vreduce_fwadd_nxv4f64' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = fpext <vscale x 4 x float> %v to <vscale x 4 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %e = fpext <vscale x 4 x float> %v to <vscale x 4 x double> ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %red = call reassoc double @llvm.vector.reduce.fadd.nxv4f64(double %s, <vscale x 4 x double> %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret double %red ; @@ -434,7 +434,7 @@ define double @vreduce_fwadd_nxv4f64(<vscale x 4 x float> %v, double %s) { define double @vreduce_ord_fwadd_nxv4f64(<vscale x 4 x float> %v, double %s) { ; CHECK-LABEL: 'vreduce_ord_fwadd_nxv4f64' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = fpext <vscale x 4 x float> %v to <vscale x 4 x double> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %e = fpext <vscale x 4 x float> %v to <vscale x 4 x double> ; CHECK-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %red = call double @llvm.vector.reduce.fadd.nxv4f64(double %s, <vscale x 4 x double> %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret double %red ; @@ -456,7 +456,7 @@ define half @vreduce_fmin_nxv1f16(<vscale x 1 x half> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret half %red ; ; SIZE-LABEL: 'vreduce_fmin_nxv1f16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call half @llvm.vector.reduce.fmin.nxv1f16(<vscale x 1 x half> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call half @llvm.vector.reduce.fmin.nxv1f16(<vscale x 1 x half> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret half %red ; %red = call half @llvm.vector.reduce.fmin.nxv1f16(<vscale x 1 x half> %v) @@ -469,7 +469,7 @@ define half @vreduce_fmin_nxv1f16_nonans(<vscale x 1 x half> %v) #0 { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret half %red ; ; SIZE-LABEL: 'vreduce_fmin_nxv1f16_nonans' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call nnan half @llvm.vector.reduce.fmin.nxv1f16(<vscale x 1 x half> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call nnan half @llvm.vector.reduce.fmin.nxv1f16(<vscale x 1 x half> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret half %red ; %red = call nnan half @llvm.vector.reduce.fmin.nxv1f16(<vscale x 1 x half> %v) @@ -482,7 +482,7 @@ define half @vreduce_fmin_nxv1f16_nonans_noinfs(<vscale x 1 x half> %v) #1 { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret half %red ; ; SIZE-LABEL: 'vreduce_fmin_nxv1f16_nonans_noinfs' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call nnan ninf half @llvm.vector.reduce.fmin.nxv1f16(<vscale x 1 x half> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call nnan ninf half @llvm.vector.reduce.fmin.nxv1f16(<vscale x 1 x half> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret half %red ; %red = call nnan ninf half @llvm.vector.reduce.fmin.nxv1f16(<vscale x 1 x half> %v) @@ -497,7 +497,7 @@ define half @vreduce_fmin_nxv2f16(<vscale x 2 x half> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret half %red ; ; SIZE-LABEL: 'vreduce_fmin_nxv2f16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call half @llvm.vector.reduce.fmin.nxv2f16(<vscale x 2 x half> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call half @llvm.vector.reduce.fmin.nxv2f16(<vscale x 2 x half> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret half %red ; %red = call half @llvm.vector.reduce.fmin.nxv2f16(<vscale x 2 x half> %v) @@ -512,7 +512,7 @@ define half @vreduce_fmin_nxv4f16(<vscale x 4 x half> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret half %red ; ; SIZE-LABEL: 'vreduce_fmin_nxv4f16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call half @llvm.vector.reduce.fmin.nxv4f16(<vscale x 4 x half> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call half @llvm.vector.reduce.fmin.nxv4f16(<vscale x 4 x half> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret half %red ; %red = call half @llvm.vector.reduce.fmin.nxv4f16(<vscale x 4 x half> %v) @@ -523,11 +523,11 @@ declare half @llvm.vector.reduce.fmin.nxv64f16(<vscale x 64 x half>) define half @vreduce_fmin_nxv64f16(<vscale x 64 x half> %v) { ; CHECK-LABEL: 'vreduce_fmin_nxv64f16' -; CHECK-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %red = call half @llvm.vector.reduce.fmin.nxv64f16(<vscale x 64 x half> %v) +; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %red = call half @llvm.vector.reduce.fmin.nxv64f16(<vscale x 64 x half> %v) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret half %red ; ; SIZE-LABEL: 'vreduce_fmin_nxv64f16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call half @llvm.vector.reduce.fmin.nxv64f16(<vscale x 64 x half> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %red = call half @llvm.vector.reduce.fmin.nxv64f16(<vscale x 64 x half> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret half %red ; %red = call half @llvm.vector.reduce.fmin.nxv64f16(<vscale x 64 x half> %v) @@ -542,7 +542,7 @@ define float @vreduce_fmin_nxv1f32(<vscale x 1 x float> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float %red ; ; SIZE-LABEL: 'vreduce_fmin_nxv1f32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call float @llvm.vector.reduce.fmin.nxv1f32(<vscale x 1 x float> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call float @llvm.vector.reduce.fmin.nxv1f32(<vscale x 1 x float> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret float %red ; %red = call float @llvm.vector.reduce.fmin.nxv1f32(<vscale x 1 x float> %v) @@ -555,7 +555,7 @@ define float @vreduce_fmin_nxv1f32_nonans(<vscale x 1 x float> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float %red ; ; SIZE-LABEL: 'vreduce_fmin_nxv1f32_nonans' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call nnan float @llvm.vector.reduce.fmin.nxv1f32(<vscale x 1 x float> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call nnan float @llvm.vector.reduce.fmin.nxv1f32(<vscale x 1 x float> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret float %red ; %red = call nnan float @llvm.vector.reduce.fmin.nxv1f32(<vscale x 1 x float> %v) @@ -568,7 +568,7 @@ define float @vreduce_fmin_nxv1f32_nonans_noinfs(<vscale x 1 x float> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float %red ; ; SIZE-LABEL: 'vreduce_fmin_nxv1f32_nonans_noinfs' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call nnan ninf float @llvm.vector.reduce.fmin.nxv1f32(<vscale x 1 x float> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call nnan ninf float @llvm.vector.reduce.fmin.nxv1f32(<vscale x 1 x float> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret float %red ; %red = call nnan ninf float @llvm.vector.reduce.fmin.nxv1f32(<vscale x 1 x float> %v) @@ -583,7 +583,7 @@ define float @vreduce_fmin_nxv2f32(<vscale x 2 x float> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float %red ; ; SIZE-LABEL: 'vreduce_fmin_nxv2f32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call float @llvm.vector.reduce.fmin.nxv2f32(<vscale x 2 x float> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call float @llvm.vector.reduce.fmin.nxv2f32(<vscale x 2 x float> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret float %red ; %red = call float @llvm.vector.reduce.fmin.nxv2f32(<vscale x 2 x float> %v) @@ -598,7 +598,7 @@ define float @vreduce_fmin_nxv4f32(<vscale x 4 x float> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float %red ; ; SIZE-LABEL: 'vreduce_fmin_nxv4f32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call float @llvm.vector.reduce.fmin.nxv4f32(<vscale x 4 x float> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call float @llvm.vector.reduce.fmin.nxv4f32(<vscale x 4 x float> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret float %red ; %red = call float @llvm.vector.reduce.fmin.nxv4f32(<vscale x 4 x float> %v) @@ -609,11 +609,11 @@ declare float @llvm.vector.reduce.fmin.nxv32f32(<vscale x 32 x float>) define float @vreduce_fmin_nxv32f32(<vscale x 32 x float> %v) { ; CHECK-LABEL: 'vreduce_fmin_nxv32f32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %red = call float @llvm.vector.reduce.fmin.nxv32f32(<vscale x 32 x float> %v) +; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %red = call float @llvm.vector.reduce.fmin.nxv32f32(<vscale x 32 x float> %v) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float %red ; ; SIZE-LABEL: 'vreduce_fmin_nxv32f32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call float @llvm.vector.reduce.fmin.nxv32f32(<vscale x 32 x float> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %red = call float @llvm.vector.reduce.fmin.nxv32f32(<vscale x 32 x float> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret float %red ; %red = call float @llvm.vector.reduce.fmin.nxv32f32(<vscale x 32 x float> %v) @@ -628,7 +628,7 @@ define double @vreduce_fmin_nxv1f64(<vscale x 1 x double> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret double %red ; ; SIZE-LABEL: 'vreduce_fmin_nxv1f64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call double @llvm.vector.reduce.fmin.nxv1f64(<vscale x 1 x double> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call double @llvm.vector.reduce.fmin.nxv1f64(<vscale x 1 x double> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret double %red ; %red = call double @llvm.vector.reduce.fmin.nxv1f64(<vscale x 1 x double> %v) @@ -641,7 +641,7 @@ define double @vreduce_fmin_nxv1f64_nonans(<vscale x 1 x double> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret double %red ; ; SIZE-LABEL: 'vreduce_fmin_nxv1f64_nonans' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call nnan double @llvm.vector.reduce.fmin.nxv1f64(<vscale x 1 x double> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call nnan double @llvm.vector.reduce.fmin.nxv1f64(<vscale x 1 x double> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret double %red ; %red = call nnan double @llvm.vector.reduce.fmin.nxv1f64(<vscale x 1 x double> %v) @@ -654,7 +654,7 @@ define double @vreduce_fmin_nxv1f64_nonans_noinfs(<vscale x 1 x double> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret double %red ; ; SIZE-LABEL: 'vreduce_fmin_nxv1f64_nonans_noinfs' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call nnan ninf double @llvm.vector.reduce.fmin.nxv1f64(<vscale x 1 x double> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call nnan ninf double @llvm.vector.reduce.fmin.nxv1f64(<vscale x 1 x double> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret double %red ; %red = call nnan ninf double @llvm.vector.reduce.fmin.nxv1f64(<vscale x 1 x double> %v) @@ -669,7 +669,7 @@ define double @vreduce_fmin_nxv2f64(<vscale x 2 x double> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret double %red ; ; SIZE-LABEL: 'vreduce_fmin_nxv2f64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call double @llvm.vector.reduce.fmin.nxv2f64(<vscale x 2 x double> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call double @llvm.vector.reduce.fmin.nxv2f64(<vscale x 2 x double> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret double %red ; %red = call double @llvm.vector.reduce.fmin.nxv2f64(<vscale x 2 x double> %v) @@ -684,7 +684,7 @@ define double @vreduce_fmin_nxv4f64(<vscale x 4 x double> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret double %red ; ; SIZE-LABEL: 'vreduce_fmin_nxv4f64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call double @llvm.vector.reduce.fmin.nxv4f64(<vscale x 4 x double> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call double @llvm.vector.reduce.fmin.nxv4f64(<vscale x 4 x double> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret double %red ; %red = call double @llvm.vector.reduce.fmin.nxv4f64(<vscale x 4 x double> %v) @@ -695,11 +695,11 @@ declare double @llvm.vector.reduce.fmin.nxv16f64(<vscale x 16 x double>) define double @vreduce_fmin_nxv16f64(<vscale x 16 x double> %v) { ; CHECK-LABEL: 'vreduce_fmin_nxv16f64' -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %red = call double @llvm.vector.reduce.fmin.nxv16f64(<vscale x 16 x double> %v) +; CHECK-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %red = call double @llvm.vector.reduce.fmin.nxv16f64(<vscale x 16 x double> %v) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret double %red ; ; SIZE-LABEL: 'vreduce_fmin_nxv16f64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call double @llvm.vector.reduce.fmin.nxv16f64(<vscale x 16 x double> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %red = call double @llvm.vector.reduce.fmin.nxv16f64(<vscale x 16 x double> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret double %red ; %red = call double @llvm.vector.reduce.fmin.nxv16f64(<vscale x 16 x double> %v) @@ -714,7 +714,7 @@ define half @vreduce_fmax_nxv1f16(<vscale x 1 x half> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret half %red ; ; SIZE-LABEL: 'vreduce_fmax_nxv1f16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call half @llvm.vector.reduce.fmax.nxv1f16(<vscale x 1 x half> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call half @llvm.vector.reduce.fmax.nxv1f16(<vscale x 1 x half> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret half %red ; %red = call half @llvm.vector.reduce.fmax.nxv1f16(<vscale x 1 x half> %v) @@ -727,7 +727,7 @@ define half @vreduce_fmax_nxv1f16_nonans(<vscale x 1 x half> %v) #0 { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret half %red ; ; SIZE-LABEL: 'vreduce_fmax_nxv1f16_nonans' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call nnan half @llvm.vector.reduce.fmax.nxv1f16(<vscale x 1 x half> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call nnan half @llvm.vector.reduce.fmax.nxv1f16(<vscale x 1 x half> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret half %red ; %red = call nnan half @llvm.vector.reduce.fmax.nxv1f16(<vscale x 1 x half> %v) @@ -740,7 +740,7 @@ define half @vreduce_fmax_nxv1f16_nonans_noinfs(<vscale x 1 x half> %v) #1 { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret half %red ; ; SIZE-LABEL: 'vreduce_fmax_nxv1f16_nonans_noinfs' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call nnan ninf half @llvm.vector.reduce.fmax.nxv1f16(<vscale x 1 x half> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call nnan ninf half @llvm.vector.reduce.fmax.nxv1f16(<vscale x 1 x half> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret half %red ; %red = call nnan ninf half @llvm.vector.reduce.fmax.nxv1f16(<vscale x 1 x half> %v) @@ -755,7 +755,7 @@ define half @vreduce_fmax_nxv2f16(<vscale x 2 x half> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret half %red ; ; SIZE-LABEL: 'vreduce_fmax_nxv2f16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call half @llvm.vector.reduce.fmax.nxv2f16(<vscale x 2 x half> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call half @llvm.vector.reduce.fmax.nxv2f16(<vscale x 2 x half> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret half %red ; %red = call half @llvm.vector.reduce.fmax.nxv2f16(<vscale x 2 x half> %v) @@ -770,7 +770,7 @@ define half @vreduce_fmax_nxv4f16(<vscale x 4 x half> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret half %red ; ; SIZE-LABEL: 'vreduce_fmax_nxv4f16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call half @llvm.vector.reduce.fmax.nxv4f16(<vscale x 4 x half> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call half @llvm.vector.reduce.fmax.nxv4f16(<vscale x 4 x half> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret half %red ; %red = call half @llvm.vector.reduce.fmax.nxv4f16(<vscale x 4 x half> %v) @@ -781,11 +781,11 @@ declare half @llvm.vector.reduce.fmax.nxv64f16(<vscale x 64 x half>) define half @vreduce_fmax_nxv64f16(<vscale x 64 x half> %v) { ; CHECK-LABEL: 'vreduce_fmax_nxv64f16' -; CHECK-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %red = call half @llvm.vector.reduce.fmax.nxv64f16(<vscale x 64 x half> %v) +; CHECK-NEXT: Cost Model: Found an estimated cost of 16 for instruction: %red = call half @llvm.vector.reduce.fmax.nxv64f16(<vscale x 64 x half> %v) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret half %red ; ; SIZE-LABEL: 'vreduce_fmax_nxv64f16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call half @llvm.vector.reduce.fmax.nxv64f16(<vscale x 64 x half> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %red = call half @llvm.vector.reduce.fmax.nxv64f16(<vscale x 64 x half> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret half %red ; %red = call half @llvm.vector.reduce.fmax.nxv64f16(<vscale x 64 x half> %v) @@ -800,7 +800,7 @@ define float @vreduce_fmax_nxv1f32(<vscale x 1 x float> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float %red ; ; SIZE-LABEL: 'vreduce_fmax_nxv1f32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call float @llvm.vector.reduce.fmax.nxv1f32(<vscale x 1 x float> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call float @llvm.vector.reduce.fmax.nxv1f32(<vscale x 1 x float> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret float %red ; %red = call float @llvm.vector.reduce.fmax.nxv1f32(<vscale x 1 x float> %v) @@ -813,7 +813,7 @@ define float @vreduce_fmax_nxv1f32_nonans(<vscale x 1 x float> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float %red ; ; SIZE-LABEL: 'vreduce_fmax_nxv1f32_nonans' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call nnan float @llvm.vector.reduce.fmax.nxv1f32(<vscale x 1 x float> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call nnan float @llvm.vector.reduce.fmax.nxv1f32(<vscale x 1 x float> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret float %red ; %red = call nnan float @llvm.vector.reduce.fmax.nxv1f32(<vscale x 1 x float> %v) @@ -826,7 +826,7 @@ define float @vreduce_fmax_nxv1f32_nonans_noinfs(<vscale x 1 x float> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float %red ; ; SIZE-LABEL: 'vreduce_fmax_nxv1f32_nonans_noinfs' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call nnan ninf float @llvm.vector.reduce.fmax.nxv1f32(<vscale x 1 x float> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call nnan ninf float @llvm.vector.reduce.fmax.nxv1f32(<vscale x 1 x float> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret float %red ; %red = call nnan ninf float @llvm.vector.reduce.fmax.nxv1f32(<vscale x 1 x float> %v) @@ -841,7 +841,7 @@ define float @vreduce_fmax_nxv2f32(<vscale x 2 x float> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float %red ; ; SIZE-LABEL: 'vreduce_fmax_nxv2f32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call float @llvm.vector.reduce.fmax.nxv2f32(<vscale x 2 x float> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call float @llvm.vector.reduce.fmax.nxv2f32(<vscale x 2 x float> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret float %red ; %red = call float @llvm.vector.reduce.fmax.nxv2f32(<vscale x 2 x float> %v) @@ -856,7 +856,7 @@ define float @vreduce_fmax_nxv4f32(<vscale x 4 x float> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float %red ; ; SIZE-LABEL: 'vreduce_fmax_nxv4f32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call float @llvm.vector.reduce.fmax.nxv4f32(<vscale x 4 x float> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call float @llvm.vector.reduce.fmax.nxv4f32(<vscale x 4 x float> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret float %red ; %red = call float @llvm.vector.reduce.fmax.nxv4f32(<vscale x 4 x float> %v) @@ -867,11 +867,11 @@ declare float @llvm.vector.reduce.fmax.nxv32f32(<vscale x 32 x float>) define float @vreduce_fmax_nxv32f32(<vscale x 32 x float> %v) { ; CHECK-LABEL: 'vreduce_fmax_nxv32f32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %red = call float @llvm.vector.reduce.fmax.nxv32f32(<vscale x 32 x float> %v) +; CHECK-NEXT: Cost Model: Found an estimated cost of 15 for instruction: %red = call float @llvm.vector.reduce.fmax.nxv32f32(<vscale x 32 x float> %v) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret float %red ; ; SIZE-LABEL: 'vreduce_fmax_nxv32f32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call float @llvm.vector.reduce.fmax.nxv32f32(<vscale x 32 x float> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %red = call float @llvm.vector.reduce.fmax.nxv32f32(<vscale x 32 x float> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret float %red ; %red = call float @llvm.vector.reduce.fmax.nxv32f32(<vscale x 32 x float> %v) @@ -886,7 +886,7 @@ define double @vreduce_fmax_nxv1f64(<vscale x 1 x double> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret double %red ; ; SIZE-LABEL: 'vreduce_fmax_nxv1f64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call double @llvm.vector.reduce.fmax.nxv1f64(<vscale x 1 x double> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call double @llvm.vector.reduce.fmax.nxv1f64(<vscale x 1 x double> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret double %red ; %red = call double @llvm.vector.reduce.fmax.nxv1f64(<vscale x 1 x double> %v) @@ -899,7 +899,7 @@ define double @vreduce_fmax_nxv1f64_nonans(<vscale x 1 x double> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret double %red ; ; SIZE-LABEL: 'vreduce_fmax_nxv1f64_nonans' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call nnan double @llvm.vector.reduce.fmax.nxv1f64(<vscale x 1 x double> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call nnan double @llvm.vector.reduce.fmax.nxv1f64(<vscale x 1 x double> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret double %red ; %red = call nnan double @llvm.vector.reduce.fmax.nxv1f64(<vscale x 1 x double> %v) @@ -912,7 +912,7 @@ define double @vreduce_fmax_nxv1f64_nonans_noinfs(<vscale x 1 x double> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret double %red ; ; SIZE-LABEL: 'vreduce_fmax_nxv1f64_nonans_noinfs' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call nnan ninf double @llvm.vector.reduce.fmax.nxv1f64(<vscale x 1 x double> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call nnan ninf double @llvm.vector.reduce.fmax.nxv1f64(<vscale x 1 x double> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret double %red ; %red = call nnan ninf double @llvm.vector.reduce.fmax.nxv1f64(<vscale x 1 x double> %v) @@ -927,7 +927,7 @@ define double @vreduce_fmax_nxv2f64(<vscale x 2 x double> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret double %red ; ; SIZE-LABEL: 'vreduce_fmax_nxv2f64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call double @llvm.vector.reduce.fmax.nxv2f64(<vscale x 2 x double> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call double @llvm.vector.reduce.fmax.nxv2f64(<vscale x 2 x double> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret double %red ; %red = call double @llvm.vector.reduce.fmax.nxv2f64(<vscale x 2 x double> %v) @@ -942,7 +942,7 @@ define double @vreduce_fmax_nxv4f64(<vscale x 4 x double> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret double %red ; ; SIZE-LABEL: 'vreduce_fmax_nxv4f64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call double @llvm.vector.reduce.fmax.nxv4f64(<vscale x 4 x double> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call double @llvm.vector.reduce.fmax.nxv4f64(<vscale x 4 x double> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret double %red ; %red = call double @llvm.vector.reduce.fmax.nxv4f64(<vscale x 4 x double> %v) @@ -953,11 +953,11 @@ declare double @llvm.vector.reduce.fmax.nxv16f64(<vscale x 16 x double>) define double @vreduce_fmax_nxv16f64(<vscale x 16 x double> %v) { ; CHECK-LABEL: 'vreduce_fmax_nxv16f64' -; CHECK-NEXT: Cost Model: Found an estimated cost of 8 for instruction: %red = call double @llvm.vector.reduce.fmax.nxv16f64(<vscale x 16 x double> %v) +; CHECK-NEXT: Cost Model: Found an estimated cost of 14 for instruction: %red = call double @llvm.vector.reduce.fmax.nxv16f64(<vscale x 16 x double> %v) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret double %red ; ; SIZE-LABEL: 'vreduce_fmax_nxv16f64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call double @llvm.vector.reduce.fmax.nxv16f64(<vscale x 16 x double> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %red = call double @llvm.vector.reduce.fmax.nxv16f64(<vscale x 16 x double> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret double %red ; %red = call double @llvm.vector.reduce.fmax.nxv16f64(<vscale x 16 x double> %v) diff --git a/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-int.ll b/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-int.ll index 80efe912c86985e192088ac4790a5f911e9af978..2807f7526760f818398e2c9ae0121cf087a38fe2 100644 --- a/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-int.ll +++ b/llvm/test/Analysis/CostModel/RISCV/reduce-scalable-int.ll @@ -27,7 +27,7 @@ define signext i8 @vreduce_umax_nxv1i8(<vscale x 1 x i8> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i8 %red ; ; SIZE-LABEL: 'vreduce_umax_nxv1i8' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i8 @llvm.vector.reduce.umax.nxv1i8(<vscale x 1 x i8> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i8 @llvm.vector.reduce.umax.nxv1i8(<vscale x 1 x i8> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i8 %red ; %red = call i8 @llvm.vector.reduce.umax.nxv1i8(<vscale x 1 x i8> %v) @@ -42,7 +42,7 @@ define signext i8 @vreduce_smax_nxv1i8(<vscale x 1 x i8> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i8 %red ; ; SIZE-LABEL: 'vreduce_smax_nxv1i8' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i8 @llvm.vector.reduce.smax.nxv1i8(<vscale x 1 x i8> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i8 @llvm.vector.reduce.smax.nxv1i8(<vscale x 1 x i8> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i8 %red ; %red = call i8 @llvm.vector.reduce.smax.nxv1i8(<vscale x 1 x i8> %v) @@ -57,7 +57,7 @@ define signext i8 @vreduce_umin_nxv1i8(<vscale x 1 x i8> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i8 %red ; ; SIZE-LABEL: 'vreduce_umin_nxv1i8' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i8 @llvm.vector.reduce.umin.nxv1i8(<vscale x 1 x i8> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i8 @llvm.vector.reduce.umin.nxv1i8(<vscale x 1 x i8> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i8 %red ; %red = call i8 @llvm.vector.reduce.umin.nxv1i8(<vscale x 1 x i8> %v) @@ -72,7 +72,7 @@ define signext i8 @vreduce_smin_nxv1i8(<vscale x 1 x i8> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i8 %red ; ; SIZE-LABEL: 'vreduce_smin_nxv1i8' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i8 @llvm.vector.reduce.smin.nxv1i8(<vscale x 1 x i8> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i8 @llvm.vector.reduce.smin.nxv1i8(<vscale x 1 x i8> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i8 %red ; %red = call i8 @llvm.vector.reduce.smin.nxv1i8(<vscale x 1 x i8> %v) @@ -147,7 +147,7 @@ define signext i8 @vreduce_umax_nxv2i8(<vscale x 2 x i8> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i8 %red ; ; SIZE-LABEL: 'vreduce_umax_nxv2i8' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i8 @llvm.vector.reduce.umax.nxv2i8(<vscale x 2 x i8> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i8 @llvm.vector.reduce.umax.nxv2i8(<vscale x 2 x i8> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i8 %red ; %red = call i8 @llvm.vector.reduce.umax.nxv2i8(<vscale x 2 x i8> %v) @@ -162,7 +162,7 @@ define signext i8 @vreduce_smax_nxv2i8(<vscale x 2 x i8> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i8 %red ; ; SIZE-LABEL: 'vreduce_smax_nxv2i8' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i8 @llvm.vector.reduce.smax.nxv2i8(<vscale x 2 x i8> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i8 @llvm.vector.reduce.smax.nxv2i8(<vscale x 2 x i8> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i8 %red ; %red = call i8 @llvm.vector.reduce.smax.nxv2i8(<vscale x 2 x i8> %v) @@ -177,7 +177,7 @@ define signext i8 @vreduce_umin_nxv2i8(<vscale x 2 x i8> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i8 %red ; ; SIZE-LABEL: 'vreduce_umin_nxv2i8' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i8 @llvm.vector.reduce.umin.nxv2i8(<vscale x 2 x i8> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i8 @llvm.vector.reduce.umin.nxv2i8(<vscale x 2 x i8> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i8 %red ; %red = call i8 @llvm.vector.reduce.umin.nxv2i8(<vscale x 2 x i8> %v) @@ -192,7 +192,7 @@ define signext i8 @vreduce_smin_nxv2i8(<vscale x 2 x i8> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i8 %red ; ; SIZE-LABEL: 'vreduce_smin_nxv2i8' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i8 @llvm.vector.reduce.smin.nxv2i8(<vscale x 2 x i8> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i8 @llvm.vector.reduce.smin.nxv2i8(<vscale x 2 x i8> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i8 %red ; %red = call i8 @llvm.vector.reduce.smin.nxv2i8(<vscale x 2 x i8> %v) @@ -267,7 +267,7 @@ define signext i8 @vreduce_umax_nxv4i8(<vscale x 4 x i8> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i8 %red ; ; SIZE-LABEL: 'vreduce_umax_nxv4i8' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i8 @llvm.vector.reduce.umax.nxv4i8(<vscale x 4 x i8> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i8 @llvm.vector.reduce.umax.nxv4i8(<vscale x 4 x i8> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i8 %red ; %red = call i8 @llvm.vector.reduce.umax.nxv4i8(<vscale x 4 x i8> %v) @@ -282,7 +282,7 @@ define signext i8 @vreduce_smax_nxv4i8(<vscale x 4 x i8> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i8 %red ; ; SIZE-LABEL: 'vreduce_smax_nxv4i8' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i8 @llvm.vector.reduce.smax.nxv4i8(<vscale x 4 x i8> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i8 @llvm.vector.reduce.smax.nxv4i8(<vscale x 4 x i8> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i8 %red ; %red = call i8 @llvm.vector.reduce.smax.nxv4i8(<vscale x 4 x i8> %v) @@ -297,7 +297,7 @@ define signext i8 @vreduce_umin_nxv4i8(<vscale x 4 x i8> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i8 %red ; ; SIZE-LABEL: 'vreduce_umin_nxv4i8' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i8 @llvm.vector.reduce.umin.nxv4i8(<vscale x 4 x i8> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i8 @llvm.vector.reduce.umin.nxv4i8(<vscale x 4 x i8> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i8 %red ; %red = call i8 @llvm.vector.reduce.umin.nxv4i8(<vscale x 4 x i8> %v) @@ -312,7 +312,7 @@ define signext i8 @vreduce_smin_nxv4i8(<vscale x 4 x i8> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i8 %red ; ; SIZE-LABEL: 'vreduce_smin_nxv4i8' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i8 @llvm.vector.reduce.smin.nxv4i8(<vscale x 4 x i8> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i8 @llvm.vector.reduce.smin.nxv4i8(<vscale x 4 x i8> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i8 %red ; %red = call i8 @llvm.vector.reduce.smin.nxv4i8(<vscale x 4 x i8> %v) @@ -419,7 +419,7 @@ define signext i16 @vreduce_umax_nxv1i16(<vscale x 1 x i16> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i16 %red ; ; SIZE-LABEL: 'vreduce_umax_nxv1i16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i16 @llvm.vector.reduce.umax.nxv1i16(<vscale x 1 x i16> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i16 @llvm.vector.reduce.umax.nxv1i16(<vscale x 1 x i16> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i16 %red ; %red = call i16 @llvm.vector.reduce.umax.nxv1i16(<vscale x 1 x i16> %v) @@ -434,7 +434,7 @@ define signext i16 @vreduce_smax_nxv1i16(<vscale x 1 x i16> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i16 %red ; ; SIZE-LABEL: 'vreduce_smax_nxv1i16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i16 @llvm.vector.reduce.smax.nxv1i16(<vscale x 1 x i16> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i16 @llvm.vector.reduce.smax.nxv1i16(<vscale x 1 x i16> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i16 %red ; %red = call i16 @llvm.vector.reduce.smax.nxv1i16(<vscale x 1 x i16> %v) @@ -449,7 +449,7 @@ define signext i16 @vreduce_umin_nxv1i16(<vscale x 1 x i16> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i16 %red ; ; SIZE-LABEL: 'vreduce_umin_nxv1i16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i16 @llvm.vector.reduce.umin.nxv1i16(<vscale x 1 x i16> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i16 @llvm.vector.reduce.umin.nxv1i16(<vscale x 1 x i16> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i16 %red ; %red = call i16 @llvm.vector.reduce.umin.nxv1i16(<vscale x 1 x i16> %v) @@ -464,7 +464,7 @@ define signext i16 @vreduce_smin_nxv1i16(<vscale x 1 x i16> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i16 %red ; ; SIZE-LABEL: 'vreduce_smin_nxv1i16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i16 @llvm.vector.reduce.smin.nxv1i16(<vscale x 1 x i16> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i16 @llvm.vector.reduce.smin.nxv1i16(<vscale x 1 x i16> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i16 %red ; %red = call i16 @llvm.vector.reduce.smin.nxv1i16(<vscale x 1 x i16> %v) @@ -571,7 +571,7 @@ define signext i16 @vreduce_umax_nxv2i16(<vscale x 2 x i16> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i16 %red ; ; SIZE-LABEL: 'vreduce_umax_nxv2i16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i16 @llvm.vector.reduce.umax.nxv2i16(<vscale x 2 x i16> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i16 @llvm.vector.reduce.umax.nxv2i16(<vscale x 2 x i16> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i16 %red ; %red = call i16 @llvm.vector.reduce.umax.nxv2i16(<vscale x 2 x i16> %v) @@ -586,7 +586,7 @@ define signext i16 @vreduce_smax_nxv2i16(<vscale x 2 x i16> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i16 %red ; ; SIZE-LABEL: 'vreduce_smax_nxv2i16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i16 @llvm.vector.reduce.smax.nxv2i16(<vscale x 2 x i16> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i16 @llvm.vector.reduce.smax.nxv2i16(<vscale x 2 x i16> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i16 %red ; %red = call i16 @llvm.vector.reduce.smax.nxv2i16(<vscale x 2 x i16> %v) @@ -601,7 +601,7 @@ define signext i16 @vreduce_umin_nxv2i16(<vscale x 2 x i16> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i16 %red ; ; SIZE-LABEL: 'vreduce_umin_nxv2i16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i16 @llvm.vector.reduce.umin.nxv2i16(<vscale x 2 x i16> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i16 @llvm.vector.reduce.umin.nxv2i16(<vscale x 2 x i16> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i16 %red ; %red = call i16 @llvm.vector.reduce.umin.nxv2i16(<vscale x 2 x i16> %v) @@ -616,7 +616,7 @@ define signext i16 @vreduce_smin_nxv2i16(<vscale x 2 x i16> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i16 %red ; ; SIZE-LABEL: 'vreduce_smin_nxv2i16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i16 @llvm.vector.reduce.smin.nxv2i16(<vscale x 2 x i16> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i16 @llvm.vector.reduce.smin.nxv2i16(<vscale x 2 x i16> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i16 %red ; %red = call i16 @llvm.vector.reduce.smin.nxv2i16(<vscale x 2 x i16> %v) @@ -723,7 +723,7 @@ define signext i16 @vreduce_umax_nxv4i16(<vscale x 4 x i16> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i16 %red ; ; SIZE-LABEL: 'vreduce_umax_nxv4i16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i16 @llvm.vector.reduce.umax.nxv4i16(<vscale x 4 x i16> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i16 @llvm.vector.reduce.umax.nxv4i16(<vscale x 4 x i16> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i16 %red ; %red = call i16 @llvm.vector.reduce.umax.nxv4i16(<vscale x 4 x i16> %v) @@ -738,7 +738,7 @@ define signext i16 @vreduce_smax_nxv4i16(<vscale x 4 x i16> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i16 %red ; ; SIZE-LABEL: 'vreduce_smax_nxv4i16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i16 @llvm.vector.reduce.smax.nxv4i16(<vscale x 4 x i16> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i16 @llvm.vector.reduce.smax.nxv4i16(<vscale x 4 x i16> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i16 %red ; %red = call i16 @llvm.vector.reduce.smax.nxv4i16(<vscale x 4 x i16> %v) @@ -753,7 +753,7 @@ define signext i16 @vreduce_umin_nxv4i16(<vscale x 4 x i16> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i16 %red ; ; SIZE-LABEL: 'vreduce_umin_nxv4i16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i16 @llvm.vector.reduce.umin.nxv4i16(<vscale x 4 x i16> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i16 @llvm.vector.reduce.umin.nxv4i16(<vscale x 4 x i16> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i16 %red ; %red = call i16 @llvm.vector.reduce.umin.nxv4i16(<vscale x 4 x i16> %v) @@ -768,7 +768,7 @@ define signext i16 @vreduce_smin_nxv4i16(<vscale x 4 x i16> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i16 %red ; ; SIZE-LABEL: 'vreduce_smin_nxv4i16' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i16 @llvm.vector.reduce.smin.nxv4i16(<vscale x 4 x i16> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i16 @llvm.vector.reduce.smin.nxv4i16(<vscale x 4 x i16> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i16 %red ; %red = call i16 @llvm.vector.reduce.smin.nxv4i16(<vscale x 4 x i16> %v) @@ -875,7 +875,7 @@ define signext i32 @vreduce_umax_nxv1i32(<vscale x 1 x i32> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; ; SIZE-LABEL: 'vreduce_umax_nxv1i32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i32 @llvm.vector.reduce.umax.nxv1i32(<vscale x 1 x i32> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i32 @llvm.vector.reduce.umax.nxv1i32(<vscale x 1 x i32> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %red ; %red = call i32 @llvm.vector.reduce.umax.nxv1i32(<vscale x 1 x i32> %v) @@ -890,7 +890,7 @@ define signext i32 @vreduce_smax_nxv1i32(<vscale x 1 x i32> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; ; SIZE-LABEL: 'vreduce_smax_nxv1i32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i32 @llvm.vector.reduce.smax.nxv1i32(<vscale x 1 x i32> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i32 @llvm.vector.reduce.smax.nxv1i32(<vscale x 1 x i32> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %red ; %red = call i32 @llvm.vector.reduce.smax.nxv1i32(<vscale x 1 x i32> %v) @@ -905,7 +905,7 @@ define signext i32 @vreduce_umin_nxv1i32(<vscale x 1 x i32> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; ; SIZE-LABEL: 'vreduce_umin_nxv1i32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i32 @llvm.vector.reduce.umin.nxv1i32(<vscale x 1 x i32> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i32 @llvm.vector.reduce.umin.nxv1i32(<vscale x 1 x i32> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %red ; %red = call i32 @llvm.vector.reduce.umin.nxv1i32(<vscale x 1 x i32> %v) @@ -920,7 +920,7 @@ define signext i32 @vreduce_smin_nxv1i32(<vscale x 1 x i32> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; ; SIZE-LABEL: 'vreduce_smin_nxv1i32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i32 @llvm.vector.reduce.smin.nxv1i32(<vscale x 1 x i32> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i32 @llvm.vector.reduce.smin.nxv1i32(<vscale x 1 x i32> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %red ; %red = call i32 @llvm.vector.reduce.smin.nxv1i32(<vscale x 1 x i32> %v) @@ -1027,7 +1027,7 @@ define signext i32 @vreduce_umax_nxv2i32(<vscale x 2 x i32> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; ; SIZE-LABEL: 'vreduce_umax_nxv2i32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i32 @llvm.vector.reduce.umax.nxv2i32(<vscale x 2 x i32> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i32 @llvm.vector.reduce.umax.nxv2i32(<vscale x 2 x i32> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %red ; %red = call i32 @llvm.vector.reduce.umax.nxv2i32(<vscale x 2 x i32> %v) @@ -1042,7 +1042,7 @@ define signext i32 @vreduce_smax_nxv2i32(<vscale x 2 x i32> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; ; SIZE-LABEL: 'vreduce_smax_nxv2i32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i32 @llvm.vector.reduce.smax.nxv2i32(<vscale x 2 x i32> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i32 @llvm.vector.reduce.smax.nxv2i32(<vscale x 2 x i32> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %red ; %red = call i32 @llvm.vector.reduce.smax.nxv2i32(<vscale x 2 x i32> %v) @@ -1057,7 +1057,7 @@ define signext i32 @vreduce_umin_nxv2i32(<vscale x 2 x i32> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; ; SIZE-LABEL: 'vreduce_umin_nxv2i32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i32 @llvm.vector.reduce.umin.nxv2i32(<vscale x 2 x i32> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i32 @llvm.vector.reduce.umin.nxv2i32(<vscale x 2 x i32> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %red ; %red = call i32 @llvm.vector.reduce.umin.nxv2i32(<vscale x 2 x i32> %v) @@ -1072,7 +1072,7 @@ define signext i32 @vreduce_smin_nxv2i32(<vscale x 2 x i32> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; ; SIZE-LABEL: 'vreduce_smin_nxv2i32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i32 @llvm.vector.reduce.smin.nxv2i32(<vscale x 2 x i32> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i32 @llvm.vector.reduce.smin.nxv2i32(<vscale x 2 x i32> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %red ; %red = call i32 @llvm.vector.reduce.smin.nxv2i32(<vscale x 2 x i32> %v) @@ -1141,7 +1141,7 @@ define signext i32 @vreduce_add_nxv4i32(<vscale x 4 x i32> %v) { define signext i32 @vwreduce_add_nxv4i16(<vscale x 4 x i16> %v) { ; CHECK-LABEL: 'vwreduce_add_nxv4i16' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = sext <vscale x 4 x i16> %v to <vscale x 4 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = sext <vscale x 4 x i16> %v to <vscale x 4 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %red = call i32 @llvm.vector.reduce.add.nxv4i32(<vscale x 4 x i32> %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; @@ -1157,7 +1157,7 @@ define signext i32 @vwreduce_add_nxv4i16(<vscale x 4 x i16> %v) { define signext i32 @vwreduce_uadd_nxv4i16(<vscale x 4 x i16> %v) { ; CHECK-LABEL: 'vwreduce_uadd_nxv4i16' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = zext <vscale x 4 x i16> %v to <vscale x 4 x i32> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = zext <vscale x 4 x i16> %v to <vscale x 4 x i32> ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %red = call i32 @llvm.vector.reduce.add.nxv4i32(<vscale x 4 x i32> %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; @@ -1179,7 +1179,7 @@ define signext i32 @vreduce_umax_nxv4i32(<vscale x 4 x i32> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; ; SIZE-LABEL: 'vreduce_umax_nxv4i32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i32 @llvm.vector.reduce.umax.nxv4i32(<vscale x 4 x i32> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i32 @llvm.vector.reduce.umax.nxv4i32(<vscale x 4 x i32> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %red ; %red = call i32 @llvm.vector.reduce.umax.nxv4i32(<vscale x 4 x i32> %v) @@ -1194,7 +1194,7 @@ define signext i32 @vreduce_smax_nxv4i32(<vscale x 4 x i32> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; ; SIZE-LABEL: 'vreduce_smax_nxv4i32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i32 @llvm.vector.reduce.smax.nxv4i32(<vscale x 4 x i32> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i32 @llvm.vector.reduce.smax.nxv4i32(<vscale x 4 x i32> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %red ; %red = call i32 @llvm.vector.reduce.smax.nxv4i32(<vscale x 4 x i32> %v) @@ -1209,7 +1209,7 @@ define signext i32 @vreduce_umin_nxv4i32(<vscale x 4 x i32> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; ; SIZE-LABEL: 'vreduce_umin_nxv4i32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i32 @llvm.vector.reduce.umin.nxv4i32(<vscale x 4 x i32> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i32 @llvm.vector.reduce.umin.nxv4i32(<vscale x 4 x i32> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %red ; %red = call i32 @llvm.vector.reduce.umin.nxv4i32(<vscale x 4 x i32> %v) @@ -1224,7 +1224,7 @@ define signext i32 @vreduce_smin_nxv4i32(<vscale x 4 x i32> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i32 %red ; ; SIZE-LABEL: 'vreduce_smin_nxv4i32' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i32 @llvm.vector.reduce.smin.nxv4i32(<vscale x 4 x i32> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i32 @llvm.vector.reduce.smin.nxv4i32(<vscale x 4 x i32> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 %red ; %red = call i32 @llvm.vector.reduce.smin.nxv4i32(<vscale x 4 x i32> %v) @@ -1331,7 +1331,7 @@ define i64 @vreduce_umax_nxv1i64(<vscale x 1 x i64> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; ; SIZE-LABEL: 'vreduce_umax_nxv1i64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i64 @llvm.vector.reduce.umax.nxv1i64(<vscale x 1 x i64> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i64 @llvm.vector.reduce.umax.nxv1i64(<vscale x 1 x i64> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i64 %red ; %red = call i64 @llvm.vector.reduce.umax.nxv1i64(<vscale x 1 x i64> %v) @@ -1346,7 +1346,7 @@ define i64 @vreduce_smax_nxv1i64(<vscale x 1 x i64> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; ; SIZE-LABEL: 'vreduce_smax_nxv1i64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i64 @llvm.vector.reduce.smax.nxv1i64(<vscale x 1 x i64> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i64 @llvm.vector.reduce.smax.nxv1i64(<vscale x 1 x i64> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i64 %red ; %red = call i64 @llvm.vector.reduce.smax.nxv1i64(<vscale x 1 x i64> %v) @@ -1361,7 +1361,7 @@ define i64 @vreduce_umin_nxv1i64(<vscale x 1 x i64> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; ; SIZE-LABEL: 'vreduce_umin_nxv1i64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i64 @llvm.vector.reduce.umin.nxv1i64(<vscale x 1 x i64> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i64 @llvm.vector.reduce.umin.nxv1i64(<vscale x 1 x i64> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i64 %red ; %red = call i64 @llvm.vector.reduce.umin.nxv1i64(<vscale x 1 x i64> %v) @@ -1376,7 +1376,7 @@ define i64 @vreduce_smin_nxv1i64(<vscale x 1 x i64> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; ; SIZE-LABEL: 'vreduce_smin_nxv1i64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i64 @llvm.vector.reduce.smin.nxv1i64(<vscale x 1 x i64> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i64 @llvm.vector.reduce.smin.nxv1i64(<vscale x 1 x i64> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i64 %red ; %red = call i64 @llvm.vector.reduce.smin.nxv1i64(<vscale x 1 x i64> %v) @@ -1445,7 +1445,7 @@ define i64 @vreduce_add_nxv2i64(<vscale x 2 x i64> %v) { define i64 @vwreduce_add_nxv2i32(<vscale x 2 x i32> %v) { ; CHECK-LABEL: 'vwreduce_add_nxv2i32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = sext <vscale x 2 x i32> %v to <vscale x 2 x i64> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = sext <vscale x 2 x i32> %v to <vscale x 2 x i64> ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %red = call i64 @llvm.vector.reduce.add.nxv2i64(<vscale x 2 x i64> %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; @@ -1461,7 +1461,7 @@ define i64 @vwreduce_add_nxv2i32(<vscale x 2 x i32> %v) { define i64 @vwreduce_uadd_nxv2i32(<vscale x 2 x i32> %v) { ; CHECK-LABEL: 'vwreduce_uadd_nxv2i32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = zext <vscale x 2 x i32> %v to <vscale x 2 x i64> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %e = zext <vscale x 2 x i32> %v to <vscale x 2 x i64> ; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %red = call i64 @llvm.vector.reduce.add.nxv2i64(<vscale x 2 x i64> %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; @@ -1483,7 +1483,7 @@ define i64 @vreduce_umax_nxv2i64(<vscale x 2 x i64> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; ; SIZE-LABEL: 'vreduce_umax_nxv2i64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i64 @llvm.vector.reduce.umax.nxv2i64(<vscale x 2 x i64> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i64 @llvm.vector.reduce.umax.nxv2i64(<vscale x 2 x i64> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i64 %red ; %red = call i64 @llvm.vector.reduce.umax.nxv2i64(<vscale x 2 x i64> %v) @@ -1498,7 +1498,7 @@ define i64 @vreduce_smax_nxv2i64(<vscale x 2 x i64> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; ; SIZE-LABEL: 'vreduce_smax_nxv2i64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i64 @llvm.vector.reduce.smax.nxv2i64(<vscale x 2 x i64> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i64 @llvm.vector.reduce.smax.nxv2i64(<vscale x 2 x i64> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i64 %red ; %red = call i64 @llvm.vector.reduce.smax.nxv2i64(<vscale x 2 x i64> %v) @@ -1513,7 +1513,7 @@ define i64 @vreduce_umin_nxv2i64(<vscale x 2 x i64> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; ; SIZE-LABEL: 'vreduce_umin_nxv2i64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i64 @llvm.vector.reduce.umin.nxv2i64(<vscale x 2 x i64> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i64 @llvm.vector.reduce.umin.nxv2i64(<vscale x 2 x i64> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i64 %red ; %red = call i64 @llvm.vector.reduce.umin.nxv2i64(<vscale x 2 x i64> %v) @@ -1528,7 +1528,7 @@ define i64 @vreduce_smin_nxv2i64(<vscale x 2 x i64> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; ; SIZE-LABEL: 'vreduce_smin_nxv2i64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i64 @llvm.vector.reduce.smin.nxv2i64(<vscale x 2 x i64> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i64 @llvm.vector.reduce.smin.nxv2i64(<vscale x 2 x i64> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i64 %red ; %red = call i64 @llvm.vector.reduce.smin.nxv2i64(<vscale x 2 x i64> %v) @@ -1597,7 +1597,7 @@ define i64 @vreduce_add_nxv4i64(<vscale x 4 x i64> %v) { define i64 @vwreduce_add_nxv4i32(<vscale x 4 x i32> %v) { ; CHECK-LABEL: 'vwreduce_add_nxv4i32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = sext <vscale x 4 x i32> %v to <vscale x 4 x i64> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %e = sext <vscale x 4 x i32> %v to <vscale x 4 x i64> ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %red = call i64 @llvm.vector.reduce.add.nxv4i64(<vscale x 4 x i64> %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; @@ -1613,7 +1613,7 @@ define i64 @vwreduce_add_nxv4i32(<vscale x 4 x i32> %v) { define i64 @vwreduce_uadd_nxv4i32(<vscale x 4 x i32> %v) { ; CHECK-LABEL: 'vwreduce_uadd_nxv4i32' -; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %e = zext <vscale x 4 x i32> %v to <vscale x 4 x i64> +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %e = zext <vscale x 4 x i32> %v to <vscale x 4 x i64> ; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %red = call i64 @llvm.vector.reduce.add.nxv4i64(<vscale x 4 x i64> %e) ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; @@ -1635,7 +1635,7 @@ define i64 @vreduce_umax_nxv4i64(<vscale x 4 x i64> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; ; SIZE-LABEL: 'vreduce_umax_nxv4i64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i64 @llvm.vector.reduce.umax.nxv4i64(<vscale x 4 x i64> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i64 @llvm.vector.reduce.umax.nxv4i64(<vscale x 4 x i64> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i64 %red ; %red = call i64 @llvm.vector.reduce.umax.nxv4i64(<vscale x 4 x i64> %v) @@ -1650,7 +1650,7 @@ define i64 @vreduce_smax_nxv4i64(<vscale x 4 x i64> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; ; SIZE-LABEL: 'vreduce_smax_nxv4i64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i64 @llvm.vector.reduce.smax.nxv4i64(<vscale x 4 x i64> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i64 @llvm.vector.reduce.smax.nxv4i64(<vscale x 4 x i64> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i64 %red ; %red = call i64 @llvm.vector.reduce.smax.nxv4i64(<vscale x 4 x i64> %v) @@ -1665,7 +1665,7 @@ define i64 @vreduce_umin_nxv4i64(<vscale x 4 x i64> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; ; SIZE-LABEL: 'vreduce_umin_nxv4i64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i64 @llvm.vector.reduce.umin.nxv4i64(<vscale x 4 x i64> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i64 @llvm.vector.reduce.umin.nxv4i64(<vscale x 4 x i64> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i64 %red ; %red = call i64 @llvm.vector.reduce.umin.nxv4i64(<vscale x 4 x i64> %v) @@ -1680,7 +1680,7 @@ define i64 @vreduce_smin_nxv4i64(<vscale x 4 x i64> %v) { ; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %red ; ; SIZE-LABEL: 'vreduce_smin_nxv4i64' -; SIZE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %red = call i64 @llvm.vector.reduce.smin.nxv4i64(<vscale x 4 x i64> %v) +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %red = call i64 @llvm.vector.reduce.smin.nxv4i64(<vscale x 4 x i64> %v) ; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i64 %red ; %red = call i64 @llvm.vector.reduce.smin.nxv4i64(<vscale x 4 x i64> %v) diff --git a/llvm/test/Analysis/CostModel/RISCV/rvv-extractelement.ll b/llvm/test/Analysis/CostModel/RISCV/rvv-extractelement.ll index 225bad6da5915c08a8be123ab9429671b4a3101b..aa7a90bece33900f468d53ce5e2d860c83cf1fcd 100644 --- a/llvm/test/Analysis/CostModel/RISCV/rvv-extractelement.ll +++ b/llvm/test/Analysis/CostModel/RISCV/rvv-extractelement.ll @@ -12,12 +12,12 @@ define void @extractelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_0 = extractelement <4 x i1> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i1_0 = extractelement <8 x i1> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_0 = extractelement <vscale x 2 x i1> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i1_0 = extractelement <vscale x 4 x i1> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i1_0 = extractelement <vscale x 8 x i1> undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i1_0 = extractelement <vscale x 16 x i1> undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i1_0 = extractelement <vscale x 32 x i1> undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = extractelement <vscale x 16 x i1> undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32i1_0 = extractelement <vscale x 32 x i1> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = extractelement <2 x i8> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = extractelement <4 x i8> undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = extractelement <8 x i8> undef, i32 0 @@ -66,12 +66,12 @@ define void @extractelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_1 = extractelement <4 x i1> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_1 = extractelement <8 x i1> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_1 = extractelement <vscale x 2 x i1> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_1 = extractelement <vscale x 4 x i1> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_1 = extractelement <vscale x 8 x i1> undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_1 = extractelement <vscale x 16 x i1> undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_1 = extractelement <vscale x 32 x i1> undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = extractelement <vscale x 16 x i1> undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_1 = extractelement <vscale x 32 x i1> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = extractelement <2 x i8> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = extractelement <4 x i8> undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = extractelement <8 x i8> undef, i32 1 @@ -120,12 +120,12 @@ define void @extractelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_x = extractelement <4 x i1> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_x = extractelement <8 x i1> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_x = extractelement <vscale x 2 x i1> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_x = extractelement <vscale x 4 x i1> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_x = extractelement <vscale x 8 x i1> undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_x = extractelement <vscale x 16 x i1> undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_x = extractelement <vscale x 32 x i1> undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_x = extractelement <vscale x 16 x i1> undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_x = extractelement <vscale x 32 x i1> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_x = extractelement <2 x i8> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_x = extractelement <4 x i8> undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_x = extractelement <8 x i8> undef, i32 %x @@ -177,12 +177,12 @@ define void @extractelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_0 = extractelement <4 x i1> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i1_0 = extractelement <8 x i1> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_0 = extractelement <vscale x 2 x i1> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i1_0 = extractelement <vscale x 4 x i1> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i1_0 = extractelement <vscale x 8 x i1> undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i1_0 = extractelement <vscale x 16 x i1> undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i1_0 = extractelement <vscale x 32 x i1> undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = extractelement <vscale x 16 x i1> undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32i1_0 = extractelement <vscale x 32 x i1> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = extractelement <2 x i8> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = extractelement <4 x i8> undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = extractelement <8 x i8> undef, i32 0 @@ -231,12 +231,12 @@ define void @extractelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_1 = extractelement <4 x i1> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_1 = extractelement <8 x i1> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_1 = extractelement <vscale x 2 x i1> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_1 = extractelement <vscale x 4 x i1> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_1 = extractelement <vscale x 8 x i1> undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_1 = extractelement <vscale x 16 x i1> undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_1 = extractelement <vscale x 32 x i1> undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = extractelement <vscale x 16 x i1> undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_1 = extractelement <vscale x 32 x i1> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = extractelement <2 x i8> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = extractelement <4 x i8> undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = extractelement <8 x i8> undef, i32 1 @@ -285,12 +285,12 @@ define void @extractelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_x = extractelement <4 x i1> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_x = extractelement <8 x i1> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_x = extractelement <vscale x 2 x i1> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_x = extractelement <vscale x 4 x i1> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_x = extractelement <vscale x 8 x i1> undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_x = extractelement <vscale x 16 x i1> undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_x = extractelement <vscale x 32 x i1> undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_x = extractelement <vscale x 16 x i1> undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_x = extractelement <vscale x 32 x i1> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_x = extractelement <2 x i8> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_x = extractelement <4 x i8> undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_x = extractelement <8 x i8> undef, i32 %x @@ -341,13 +341,13 @@ define void @extractelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_0 = extractelement <2 x i1> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_0 = extractelement <4 x i1> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i1_0 = extractelement <8 x i1> undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_0 = extractelement <vscale x 2 x i1> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i1_0 = extractelement <vscale x 4 x i1> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i1_0 = extractelement <vscale x 8 x i1> undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i1_0 = extractelement <vscale x 16 x i1> undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i1_0 = extractelement <vscale x 32 x i1> undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = extractelement <vscale x 16 x i1> undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32i1_0 = extractelement <vscale x 32 x i1> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = extractelement <2 x i8> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = extractelement <4 x i8> undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = extractelement <8 x i8> undef, i32 0 @@ -395,13 +395,13 @@ define void @extractelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i1_1 = extractelement <2 x i1> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_1 = extractelement <4 x i1> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_1 = extractelement <8 x i1> undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_1 = extractelement <vscale x 2 x i1> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_1 = extractelement <vscale x 4 x i1> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_1 = extractelement <vscale x 8 x i1> undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_1 = extractelement <vscale x 16 x i1> undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_1 = extractelement <vscale x 32 x i1> undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = extractelement <vscale x 16 x i1> undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_1 = extractelement <vscale x 32 x i1> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = extractelement <2 x i8> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = extractelement <4 x i8> undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = extractelement <8 x i8> undef, i32 1 @@ -449,13 +449,13 @@ define void @extractelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i1_x = extractelement <2 x i1> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_x = extractelement <4 x i1> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_x = extractelement <8 x i1> undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_x = extractelement <vscale x 2 x i1> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_x = extractelement <vscale x 4 x i1> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_x = extractelement <vscale x 8 x i1> undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_x = extractelement <vscale x 16 x i1> undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_x = extractelement <vscale x 32 x i1> undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_x = extractelement <vscale x 16 x i1> undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_x = extractelement <vscale x 32 x i1> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_x = extractelement <2 x i8> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_x = extractelement <4 x i8> undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_x = extractelement <8 x i8> undef, i32 %x @@ -506,13 +506,13 @@ define void @extractelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i1_0 = extractelement <2 x i1> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i1_0 = extractelement <4 x i1> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i1_0 = extractelement <8 x i1> undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = extractelement <16 x i1> undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i1_0 = extractelement <32 x i1> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv2i1_0 = extractelement <vscale x 2 x i1> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv4i1_0 = extractelement <vscale x 4 x i1> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv8i1_0 = extractelement <vscale x 8 x i1> undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv16i1_0 = extractelement <vscale x 16 x i1> undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %nxv32i1_0 = extractelement <vscale x 32 x i1> undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = extractelement <vscale x 16 x i1> undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv32i1_0 = extractelement <vscale x 32 x i1> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = extractelement <2 x i8> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = extractelement <4 x i8> undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = extractelement <8 x i8> undef, i32 0 @@ -560,13 +560,13 @@ define void @extractelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i1_1 = extractelement <2 x i1> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_1 = extractelement <4 x i1> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_1 = extractelement <8 x i1> undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = extractelement <16 x i1> undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v32i1_1 = extractelement <32 x i1> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_1 = extractelement <vscale x 2 x i1> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_1 = extractelement <vscale x 4 x i1> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_1 = extractelement <vscale x 8 x i1> undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_1 = extractelement <vscale x 16 x i1> undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_1 = extractelement <vscale x 32 x i1> undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = extractelement <vscale x 16 x i1> undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_1 = extractelement <vscale x 32 x i1> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = extractelement <2 x i8> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = extractelement <4 x i8> undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = extractelement <8 x i8> undef, i32 1 @@ -614,13 +614,13 @@ define void @extractelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v2i1_x = extractelement <2 x i1> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v4i1_x = extractelement <4 x i1> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v8i1_x = extractelement <8 x i1> undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_x = extractelement <16 x i1> undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v32i1_x = extractelement <32 x i1> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv2i1_x = extractelement <vscale x 2 x i1> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv4i1_x = extractelement <vscale x 4 x i1> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv8i1_x = extractelement <vscale x 8 x i1> undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv16i1_x = extractelement <vscale x 16 x i1> undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %nxv32i1_x = extractelement <vscale x 32 x i1> undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_x = extractelement <vscale x 16 x i1> undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv32i1_x = extractelement <vscale x 32 x i1> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_x = extractelement <2 x i8> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_x = extractelement <4 x i8> undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_x = extractelement <8 x i8> undef, i32 %x diff --git a/llvm/test/Analysis/CostModel/RISCV/rvv-insertelement.ll b/llvm/test/Analysis/CostModel/RISCV/rvv-insertelement.ll index 5387c8dc35940eaa5e988e464bbfad7fc6eb75da..8b68480788f79ea019f64ae9217e0c3bad005513 100644 --- a/llvm/test/Analysis/CostModel/RISCV/rvv-insertelement.ll +++ b/llvm/test/Analysis/CostModel/RISCV/rvv-insertelement.ll @@ -12,12 +12,12 @@ define void @insertelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v4i1_0 = insertelement <4 x i1> undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v8i1_0 = insertelement <8 x i1> undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv2i1_0 = insertelement <vscale x 2 x i1> undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv4i1_0 = insertelement <vscale x 4 x i1> undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv8i1_0 = insertelement <vscale x 8 x i1> undef, i1 undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = insertelement <vscale x 16 x i1> undef, i1 undef, i32 0 -; RV32V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_0 = insertelement <vscale x 32 x i1> undef, i1 undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i1_0 = insertelement <vscale x 16 x i1> undef, i1 undef, i32 0 +; RV32V-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i1_0 = insertelement <vscale x 32 x i1> undef, i1 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = insertelement <2 x i8> undef, i8 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = insertelement <4 x i8> undef, i8 undef, i32 0 ; RV32V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = insertelement <8 x i8> undef, i8 undef, i32 0 @@ -66,12 +66,12 @@ define void @insertelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i1_1 = insertelement <4 x i1> undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i1_1 = insertelement <8 x i1> undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv2i1_1 = insertelement <vscale x 2 x i1> undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i1_1 = insertelement <vscale x 4 x i1> undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i1_1 = insertelement <vscale x 8 x i1> undef, i1 undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = insertelement <vscale x 16 x i1> undef, i1 undef, i32 1 -; RV32V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i1_1 = insertelement <vscale x 32 x i1> undef, i1 undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv16i1_1 = insertelement <vscale x 16 x i1> undef, i1 undef, i32 1 +; RV32V-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv32i1_1 = insertelement <vscale x 32 x i1> undef, i1 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = insertelement <2 x i8> undef, i8 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = insertelement <4 x i8> undef, i8 undef, i32 1 ; RV32V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = insertelement <8 x i8> undef, i8 undef, i32 1 @@ -120,12 +120,12 @@ define void @insertelement_int(i32 %x) { ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_x = insertelement <4 x i1> undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i1_x = insertelement <8 x i1> undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv2i1_x = insertelement <vscale x 2 x i1> undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv4i1_x = insertelement <vscale x 4 x i1> undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8i1_x = insertelement <vscale x 8 x i1> undef, i1 undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_x = insertelement <vscale x 16 x i1> undef, i1 undef, i32 %x -; RV32V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i1_x = insertelement <vscale x 32 x i1> undef, i1 undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv16i1_x = insertelement <vscale x 16 x i1> undef, i1 undef, i32 %x +; RV32V-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %nxv32i1_x = insertelement <vscale x 32 x i1> undef, i1 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_x = insertelement <2 x i8> undef, i8 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_x = insertelement <4 x i8> undef, i8 undef, i32 %x ; RV32V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_x = insertelement <8 x i8> undef, i8 undef, i32 %x @@ -177,12 +177,12 @@ define void @insertelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v4i1_0 = insertelement <4 x i1> undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v8i1_0 = insertelement <8 x i1> undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv2i1_0 = insertelement <vscale x 2 x i1> undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv4i1_0 = insertelement <vscale x 4 x i1> undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv8i1_0 = insertelement <vscale x 8 x i1> undef, i1 undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = insertelement <vscale x 16 x i1> undef, i1 undef, i32 0 -; RV64V-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_0 = insertelement <vscale x 32 x i1> undef, i1 undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i1_0 = insertelement <vscale x 16 x i1> undef, i1 undef, i32 0 +; RV64V-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i1_0 = insertelement <vscale x 32 x i1> undef, i1 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = insertelement <2 x i8> undef, i8 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = insertelement <4 x i8> undef, i8 undef, i32 0 ; RV64V-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = insertelement <8 x i8> undef, i8 undef, i32 0 @@ -231,12 +231,12 @@ define void @insertelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i1_1 = insertelement <4 x i1> undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i1_1 = insertelement <8 x i1> undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv2i1_1 = insertelement <vscale x 2 x i1> undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i1_1 = insertelement <vscale x 4 x i1> undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i1_1 = insertelement <vscale x 8 x i1> undef, i1 undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = insertelement <vscale x 16 x i1> undef, i1 undef, i32 1 -; RV64V-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i1_1 = insertelement <vscale x 32 x i1> undef, i1 undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv16i1_1 = insertelement <vscale x 16 x i1> undef, i1 undef, i32 1 +; RV64V-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv32i1_1 = insertelement <vscale x 32 x i1> undef, i1 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = insertelement <2 x i8> undef, i8 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = insertelement <4 x i8> undef, i8 undef, i32 1 ; RV64V-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = insertelement <8 x i8> undef, i8 undef, i32 1 @@ -285,12 +285,12 @@ define void @insertelement_int(i32 %x) { ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_x = insertelement <4 x i1> undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i1_x = insertelement <8 x i1> undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv2i1_x = insertelement <vscale x 2 x i1> undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv4i1_x = insertelement <vscale x 4 x i1> undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8i1_x = insertelement <vscale x 8 x i1> undef, i1 undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_x = insertelement <vscale x 16 x i1> undef, i1 undef, i32 %x -; RV64V-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i1_x = insertelement <vscale x 32 x i1> undef, i1 undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv16i1_x = insertelement <vscale x 16 x i1> undef, i1 undef, i32 %x +; RV64V-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %nxv32i1_x = insertelement <vscale x 32 x i1> undef, i1 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_x = insertelement <2 x i8> undef, i8 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_x = insertelement <4 x i8> undef, i8 undef, i32 %x ; RV64V-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_x = insertelement <8 x i8> undef, i8 undef, i32 %x @@ -341,13 +341,13 @@ define void @insertelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v2i1_0 = insertelement <2 x i1> undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v4i1_0 = insertelement <4 x i1> undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v8i1_0 = insertelement <8 x i1> undef, i1 undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv2i1_0 = insertelement <vscale x 2 x i1> undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv4i1_0 = insertelement <vscale x 4 x i1> undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv8i1_0 = insertelement <vscale x 8 x i1> undef, i1 undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = insertelement <vscale x 16 x i1> undef, i1 undef, i32 0 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_0 = insertelement <vscale x 32 x i1> undef, i1 undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i1_0 = insertelement <vscale x 16 x i1> undef, i1 undef, i32 0 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i1_0 = insertelement <vscale x 32 x i1> undef, i1 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = insertelement <2 x i8> undef, i8 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = insertelement <4 x i8> undef, i8 undef, i32 0 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = insertelement <8 x i8> undef, i8 undef, i32 0 @@ -395,13 +395,13 @@ define void @insertelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v2i1_1 = insertelement <2 x i1> undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i1_1 = insertelement <4 x i1> undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i1_1 = insertelement <8 x i1> undef, i1 undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv2i1_1 = insertelement <vscale x 2 x i1> undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i1_1 = insertelement <vscale x 4 x i1> undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i1_1 = insertelement <vscale x 8 x i1> undef, i1 undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = insertelement <vscale x 16 x i1> undef, i1 undef, i32 1 -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i1_1 = insertelement <vscale x 32 x i1> undef, i1 undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv16i1_1 = insertelement <vscale x 16 x i1> undef, i1 undef, i32 1 +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv32i1_1 = insertelement <vscale x 32 x i1> undef, i1 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = insertelement <2 x i8> undef, i8 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = insertelement <4 x i8> undef, i8 undef, i32 1 ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = insertelement <8 x i8> undef, i8 undef, i32 1 @@ -449,13 +449,13 @@ define void @insertelement_int(i32 %x) { ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2i1_x = insertelement <2 x i1> undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_x = insertelement <4 x i1> undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i1_x = insertelement <8 x i1> undef, i1 undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv2i1_x = insertelement <vscale x 2 x i1> undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv4i1_x = insertelement <vscale x 4 x i1> undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8i1_x = insertelement <vscale x 8 x i1> undef, i1 undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_x = insertelement <vscale x 16 x i1> undef, i1 undef, i32 %x -; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i1_x = insertelement <vscale x 32 x i1> undef, i1 undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv16i1_x = insertelement <vscale x 16 x i1> undef, i1 undef, i32 %x +; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %nxv32i1_x = insertelement <vscale x 32 x i1> undef, i1 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_x = insertelement <2 x i8> undef, i8 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_x = insertelement <4 x i8> undef, i8 undef, i32 %x ; RV32ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_x = insertelement <8 x i8> undef, i8 undef, i32 %x @@ -506,13 +506,13 @@ define void @insertelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v2i1_0 = insertelement <2 x i1> undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v4i1_0 = insertelement <4 x i1> undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v8i1_0 = insertelement <8 x i1> undef, i1 undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %v16i1_0 = insertelement <16 x i1> undef, i1 undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %v32i1_0 = insertelement <32 x i1> undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv2i1_0 = insertelement <vscale x 2 x i1> undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv4i1_0 = insertelement <vscale x 4 x i1> undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv8i1_0 = insertelement <vscale x 8 x i1> undef, i1 undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv16i1_0 = insertelement <vscale x 16 x i1> undef, i1 undef, i32 0 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %nxv32i1_0 = insertelement <vscale x 32 x i1> undef, i1 undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 9 for instruction: %nxv16i1_0 = insertelement <vscale x 16 x i1> undef, i1 undef, i32 0 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 17 for instruction: %nxv32i1_0 = insertelement <vscale x 32 x i1> undef, i1 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v2i8_0 = insertelement <2 x i8> undef, i8 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v4i8_0 = insertelement <4 x i8> undef, i8 undef, i32 0 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %v8i8_0 = insertelement <8 x i8> undef, i8 undef, i32 0 @@ -560,13 +560,13 @@ define void @insertelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v2i1_1 = insertelement <2 x i1> undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v4i1_1 = insertelement <4 x i1> undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v8i1_1 = insertelement <8 x i1> undef, i1 undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %v16i1_1 = insertelement <16 x i1> undef, i1 undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %v32i1_1 = insertelement <32 x i1> undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv2i1_1 = insertelement <vscale x 2 x i1> undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv4i1_1 = insertelement <vscale x 4 x i1> undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv8i1_1 = insertelement <vscale x 8 x i1> undef, i1 undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv16i1_1 = insertelement <vscale x 16 x i1> undef, i1 undef, i32 1 -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %nxv32i1_1 = insertelement <vscale x 32 x i1> undef, i1 undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 10 for instruction: %nxv16i1_1 = insertelement <vscale x 16 x i1> undef, i1 undef, i32 1 +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 18 for instruction: %nxv32i1_1 = insertelement <vscale x 32 x i1> undef, i1 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v2i8_1 = insertelement <2 x i8> undef, i8 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v4i8_1 = insertelement <4 x i8> undef, i8 undef, i32 1 ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %v8i8_1 = insertelement <8 x i8> undef, i8 undef, i32 1 @@ -614,13 +614,13 @@ define void @insertelement_int(i32 %x) { ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v2i1_x = insertelement <2 x i1> undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v4i1_x = insertelement <4 x i1> undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v8i1_x = insertelement <8 x i1> undef, i1 undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %v16i1_x = insertelement <16 x i1> undef, i1 undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %v32i1_x = insertelement <32 x i1> undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv2i1_x = insertelement <vscale x 2 x i1> undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv4i1_x = insertelement <vscale x 4 x i1> undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv8i1_x = insertelement <vscale x 8 x i1> undef, i1 undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv16i1_x = insertelement <vscale x 16 x i1> undef, i1 undef, i32 %x -; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 7 for instruction: %nxv32i1_x = insertelement <vscale x 32 x i1> undef, i1 undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %nxv16i1_x = insertelement <vscale x 16 x i1> undef, i1 undef, i32 %x +; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %nxv32i1_x = insertelement <vscale x 32 x i1> undef, i1 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v2i8_x = insertelement <2 x i8> undef, i8 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v4i8_x = insertelement <4 x i8> undef, i8 undef, i32 %x ; RV64ZVE64X-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %v8i8_x = insertelement <8 x i8> undef, i8 undef, i32 %x diff --git a/llvm/test/Analysis/CostModel/RISCV/shuffle-broadcast.ll b/llvm/test/Analysis/CostModel/RISCV/shuffle-broadcast.ll index 46bf3152ac5bd380f67b1b982e4ee4233fea9e74..79ba1562d0f8843d0f33cc624a622fef533917b4 100644 --- a/llvm/test/Analysis/CostModel/RISCV/shuffle-broadcast.ll +++ b/llvm/test/Analysis/CostModel/RISCV/shuffle-broadcast.ll @@ -197,7 +197,7 @@ define void @broadcast_fixed() #0{ ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %41 = shufflevector <32 x i1> undef, <32 x i1> undef, <32 x i32> zeroinitializer ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %42 = shufflevector <64 x i1> undef, <64 x i1> undef, <64 x i32> zeroinitializer ; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %43 = shufflevector <128 x i1> undef, <128 x i1> undef, <128 x i32> zeroinitializer -; CHECK-NEXT: Cost Model: Found an estimated cost of 5 for instruction: %ins1 = insertelement <128 x i1> poison, i1 poison, i32 0 +; CHECK-NEXT: Cost Model: Found an estimated cost of 33 for instruction: %ins1 = insertelement <128 x i1> poison, i1 poison, i32 0 ; CHECK-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %44 = shufflevector <128 x i1> %ins1, <128 x i1> poison, <128 x i32> zeroinitializer ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ins2 = insertelement <2 x i8> poison, i8 3, i32 0 ; CHECK-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %45 = shufflevector <2 x i8> %ins2, <2 x i8> undef, <2 x i32> zeroinitializer diff --git a/llvm/test/Analysis/CostModel/RISCV/shuffle-insert_subvector.ll b/llvm/test/Analysis/CostModel/RISCV/shuffle-insert_subvector.ll index 9a333dc8b8ddda556a3932af0d242b728c5bf139..a91d562b3f6f115923cb5084e3e221a130bd760a 100644 --- a/llvm/test/Analysis/CostModel/RISCV/shuffle-insert_subvector.ll +++ b/llvm/test/Analysis/CostModel/RISCV/shuffle-insert_subvector.ll @@ -520,3 +520,69 @@ define void @test_vXi8(<2 x i8> %src16, <4 x i8> %src32, <8 x i8> %src64, <16x i ret void } + +define void @fixed_m1_in_m2_notail(<8 x i32> %src, <8 x i32> %passthru) vscale_range(2) { +; CHECK-LABEL: 'fixed_m1_in_m2_notail' +; CHECK-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %1 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %2 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 0, i32 8, i32 9, i32 10, i32 11, i32 5, i32 6, i32 7> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %3 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 0, i32 1, i32 8, i32 9, i32 10, i32 11, i32 6, i32 7> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %4 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 0, i32 1, i32 2, i32 8, i32 9, i32 10, i32 11, i32 7> +; CHECK-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %5 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11> +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; +; SIZE-LABEL: 'fixed_m1_in_m2_notail' +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %1 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7> +; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %2 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 0, i32 8, i32 9, i32 10, i32 11, i32 5, i32 6, i32 7> +; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %3 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 0, i32 1, i32 8, i32 9, i32 10, i32 11, i32 6, i32 7> +; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %4 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 0, i32 1, i32 2, i32 8, i32 9, i32 10, i32 11, i32 7> +; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %5 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11> +; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void +; + shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7> + shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 0, i32 8, i32 9, i32 10, i32 11, i32 5, i32 6, i32 7> + shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 0, i32 1, i32 8, i32 9, i32 10, i32 11, i32 6, i32 7> + shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 0, i32 1, i32 2, i32 8, i32 9, i32 10, i32 11, i32 7> + shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11> + ret void +} + +define void @fixed_m2_in_m4_notail(<8 x i64> %src, <8 x i64> %passthru) vscale_range(2) { +; CHECK-LABEL: 'fixed_m2_in_m4_notail' +; CHECK-NEXT: Cost Model: Found an estimated cost of 6 for instruction: %1 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7> +; CHECK-NEXT: Cost Model: Found an estimated cost of 41 for instruction: %2 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> <i32 0, i32 8, i32 8, i32 10, i32 11, i32 5, i32 6, i32 7> +; CHECK-NEXT: Cost Model: Found an estimated cost of 41 for instruction: %3 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> <i32 0, i32 1, i32 8, i32 8, i32 10, i32 11, i32 6, i32 7> +; CHECK-NEXT: Cost Model: Found an estimated cost of 41 for instruction: %4 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> <i32 0, i32 1, i32 2, i32 8, i32 8, i32 10, i32 11, i32 7> +; CHECK-NEXT: Cost Model: Found an estimated cost of 41 for instruction: %5 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 8, i32 10, i32 11> +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; +; SIZE-LABEL: 'fixed_m2_in_m4_notail' +; SIZE-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %1 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7> +; SIZE-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %2 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> <i32 0, i32 8, i32 8, i32 10, i32 11, i32 5, i32 6, i32 7> +; SIZE-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %3 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> <i32 0, i32 1, i32 8, i32 8, i32 10, i32 11, i32 6, i32 7> +; SIZE-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %4 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> <i32 0, i32 1, i32 2, i32 8, i32 8, i32 10, i32 11, i32 7> +; SIZE-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %5 = shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 8, i32 10, i32 11> +; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void +; + shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7> + shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> <i32 0, i32 8, i32 8, i32 10, i32 11, i32 5, i32 6, i32 7> + shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> <i32 0, i32 1, i32 8, i32 8, i32 10, i32 11, i32 6, i32 7> + shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> <i32 0, i32 1, i32 2, i32 8, i32 8, i32 10, i32 11, i32 7> + shufflevector <8 x i64> %src, <8 x i64> %passthru, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 8, i32 10, i32 11> + ret void +} + +define void @fixed_m1_in_m2_tail(<8 x i32> %src, <8 x i32> %passthru) vscale_range(2) { +; CHECK-LABEL: 'fixed_m1_in_m2_tail' +; CHECK-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %1 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 8, i32 9, i32 10, i32 4, i32 4, i32 5, i32 6, i32 8> +; CHECK-NEXT: Cost Model: Found an estimated cost of 19 for instruction: %2 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 8, i32 10, i32 7> +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret void +; +; SIZE-LABEL: 'fixed_m1_in_m2_tail' +; SIZE-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %1 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 8, i32 9, i32 10, i32 4, i32 4, i32 5, i32 6, i32 8> +; SIZE-NEXT: Cost Model: Found an estimated cost of 11 for instruction: %2 = shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 8, i32 10, i32 7> +; SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret void +; + shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 8, i32 9, i32 10, i32 4, i32 4, i32 5, i32 6, i32 8> + shufflevector <8 x i32> %src, <8 x i32> %passthru, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 8, i32 10, i32 7> + ret void +} diff --git a/llvm/test/Analysis/CostModel/X86/intrinsic-cost-kinds.ll b/llvm/test/Analysis/CostModel/X86/intrinsic-cost-kinds.ll index f5936a78f932f1b04fe98d1d3d522080380724dc..10786e1f7a4a4c66f5027c2a7a93fc8f97943cc6 100644 --- a/llvm/test/Analysis/CostModel/X86/intrinsic-cost-kinds.ll +++ b/llvm/test/Analysis/CostModel/X86/intrinsic-cost-kinds.ll @@ -178,7 +178,7 @@ define void @log2(float %a, <16 x float> %va) { ret void } -define void @constrained_fadd(float %a, <16 x float> %va) { +define void @constrained_fadd(float %a, <16 x float> %va) strictfp { ; THRU-LABEL: 'constrained_fadd' ; THRU-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %s = call float @llvm.experimental.constrained.fadd.f32(float %a, float %a, metadata !"round.dynamic", metadata !"fpexcept.ignore") ; THRU-NEXT: Cost Model: Found an estimated cost of 40 for instruction: %t = call <16 x float> @llvm.experimental.constrained.fadd.v16f32(<16 x float> %va, <16 x float> %va, metadata !"round.dynamic", metadata !"fpexcept.ignore") diff --git a/llvm/test/Analysis/CostModel/free-intrinsics-datalayout.ll b/llvm/test/Analysis/CostModel/free-intrinsics-datalayout.ll index 4ebb1e314ba183509abb791ef7b774a2841acdb0..09fbd68d95e920685e4e68b184cdd19e2ed86548 100644 --- a/llvm/test/Analysis/CostModel/free-intrinsics-datalayout.ll +++ b/llvm/test/Analysis/CostModel/free-intrinsics-datalayout.ll @@ -25,6 +25,8 @@ define i32 @trivially_free() { ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) +; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a7 = call i1 @llvm.allow.ubsan.check(i8 123) +; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a8 = call i1 @llvm.allow.runtime.check(metadata !"test_check") ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; @@ -45,6 +47,8 @@ define i32 @trivially_free() { ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.lifetime.end.p0(i64 1, ptr undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) +; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a7 = call i1 @llvm.allow.ubsan.check(i8 123) +; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a8 = call i1 @llvm.allow.runtime.check(metadata !"test_check") ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; @@ -65,6 +69,8 @@ define i32 @trivially_free() { call void @llvm.lifetime.end.p0(i64 1, ptr undef) %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 1, i1 1, i1 1) %a6 = call ptr @llvm.ptr.annotation.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) + %a7 = call i1 @llvm.allow.ubsan.check(i8 123) + %a8 = call i1 @llvm.allow.runtime.check(metadata !"test_check") call void @llvm.var.annotation(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ret i32 undef } diff --git a/llvm/test/Analysis/CostModel/free-intrinsics-no_info.ll b/llvm/test/Analysis/CostModel/free-intrinsics-no_info.ll index 5d47e48944271fdc314a6b50cb6bba08d38dd08a..3e78c62a6fe2555da69ca912c0dcd868b867e259 100644 --- a/llvm/test/Analysis/CostModel/free-intrinsics-no_info.ll +++ b/llvm/test/Analysis/CostModel/free-intrinsics-no_info.ll @@ -24,6 +24,8 @@ define i32 @trivially_free() { ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) +; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a7 = call i1 @llvm.allow.ubsan.check(i8 123) +; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a8 = call i1 @llvm.allow.runtime.check(metadata !"test_check") ; CHECK-SIZE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; ; CHECK-THROUGHPUT-LABEL: 'trivially_free' @@ -44,6 +46,8 @@ define i32 @trivially_free() { ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 true, i1 true, i1 true) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a6 = call ptr @llvm.ptr.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: call void @llvm.var.annotation.p0.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) +; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a7 = call i1 @llvm.allow.ubsan.check(i8 123) +; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 0 for instruction: %a8 = call i1 @llvm.allow.runtime.check(metadata !"test_check") ; CHECK-THROUGHPUT-NEXT: Cost Model: Found an estimated cost of 1 for instruction: ret i32 undef ; %a0 = call i32 @llvm.annotation.i32(i32 undef, ptr undef, ptr undef, i32 undef) @@ -64,6 +68,8 @@ define i32 @trivially_free() { %a5 = call i64 @llvm.objectsize.i64.p0(ptr undef, i1 1, i1 1, i1 1) %a6 = call ptr @llvm.ptr.annotation.p0(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) call void @llvm.var.annotation(ptr undef, ptr undef, ptr undef, i32 undef, ptr undef) + %a7 = call i1 @llvm.allow.ubsan.check(i8 123) + %a8 = call i1 @llvm.allow.runtime.check(metadata !"test_check") ret i32 undef } diff --git a/llvm/test/Analysis/Lint/crash_empty_iterator.ll b/llvm/test/Analysis/Lint/crash_empty_iterator.ll new file mode 100644 index 0000000000000000000000000000000000000000..2fbecbcef5cfb4362949587d7fe72d7d7d7c4063 --- /dev/null +++ b/llvm/test/Analysis/Lint/crash_empty_iterator.ll @@ -0,0 +1,22 @@ +; RUN: opt -passes="lint" -S < %s | FileCheck %s + +; After 2fe81edef6f0b +; [NFC][RemoveDIs] Insert instruction using iterators in Transforms/ +; this crashed in FindInsertedValue when dereferencing an empty +; optional iterator. +; Just see that it doesn't crash anymore. + +; CHECK-LABEL: @test1 + +%struct = type { i32, i32 } + +define void @test1() { +entry: + %.fca.1.insert = insertvalue %struct zeroinitializer, i32 0, 1 + %0 = extractvalue %struct %.fca.1.insert, 0 + %1 = tail call %struct @foo(i32 %0) + ret void +} + +declare %struct @foo(i32) + diff --git a/llvm/test/Analysis/MemorySSA/allow-check.ll b/llvm/test/Analysis/MemorySSA/allow-check.ll new file mode 100644 index 0000000000000000000000000000000000000000..dcdad001ca6f5b905d2e44c612d57440119c4f57 --- /dev/null +++ b/llvm/test/Analysis/MemorySSA/allow-check.ll @@ -0,0 +1,29 @@ +; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s --implicit-check-not=MemoryDef +; +; Ensures that allow.*.check are treated as not reading or writing memory. + +target triple = "aarch64-linux" + +define i1 @test_runtime(ptr %a) local_unnamed_addr { +entry: +; CHECK: 1 = MemoryDef(liveOnEntry) + store i32 4, ptr %a, align 4 + %allow = call i1 @llvm.allow.runtime.check(metadata !"test_check") + %0 = load i32, ptr %a, align 4 +; CHECK: MemoryUse(1) + ret i1 %allow +} + +declare i1 @llvm.allow.runtime.check(metadata) + +define i1 @test_ubsan(ptr %a) local_unnamed_addr { +entry: +; CHECK: 1 = MemoryDef(liveOnEntry) + store i32 4, ptr %a, align 4 + %allow = call i1 @llvm.allow.ubsan.check(i8 7) + %0 = load i32, ptr %a, align 4 +; CHECK: MemoryUse(1) + ret i1 %allow +} + +declare i1 @llvm.allow.ubsan.check(i8) diff --git a/llvm/test/Analysis/UniformityAnalysis/AMDGPU/intrinsics.ll b/llvm/test/Analysis/UniformityAnalysis/AMDGPU/intrinsics.ll index 333ec6dcaf488aef77f5f6844a951b791064223c..26c85e83b53adc905ea90a249ae0cd3eb7a10589 100644 --- a/llvm/test/Analysis/UniformityAnalysis/AMDGPU/intrinsics.ll +++ b/llvm/test/Analysis/UniformityAnalysis/AMDGPU/intrinsics.ll @@ -197,78 +197,38 @@ bb: ret void } -; CHECK: DIVERGENT: %tmp0 = call <2 x i32> @llvm.amdgcn.global.load.tr.v2i32(ptr addrspace(1) %gep) +; CHECK: DIVERGENT: %tmp0 = call <2 x i32> @llvm.amdgcn.global.load.tr.b64.v2i32(ptr addrspace(1) %addr) define amdgpu_kernel void @global_load_tr_b64_v2i32(ptr addrspace(1) %addr, ptr addrspace(1) %out) { bb: - %gep = getelementptr i64, ptr addrspace(1) %addr, i32 4 - %tmp0 = call <2 x i32> @llvm.amdgcn.global.load.tr.v2i32(ptr addrspace(1) %gep) + %tmp0 = call <2 x i32> @llvm.amdgcn.global.load.tr.b64.v2i32(ptr addrspace(1) %addr) store <2 x i32> %tmp0, ptr addrspace(1) %out, align 8 ret void } -; CHECK: DIVERGENT: %tmp0 = call <8 x i16> @llvm.amdgcn.global.load.tr.v8i16(ptr addrspace(1) %gep) +; CHECK: DIVERGENT: %tmp0 = call <8 x i16> @llvm.amdgcn.global.load.tr.b128.v8i16(ptr addrspace(1) %addr) define amdgpu_kernel void @global_load_tr_b128_v8i16(ptr addrspace(1) %addr, ptr addrspace(1) %out) { bb: - %gep = getelementptr i64, ptr addrspace(1) %addr, i32 4 - %tmp0 = call <8 x i16> @llvm.amdgcn.global.load.tr.v8i16(ptr addrspace(1) %gep) + %tmp0 = call <8 x i16> @llvm.amdgcn.global.load.tr.b128.v8i16(ptr addrspace(1) %addr) store <8 x i16> %tmp0, ptr addrspace(1) %out, align 16 ret void } -; CHECK: DIVERGENT: %tmp0 = call <8 x half> @llvm.amdgcn.global.load.tr.v8f16(ptr addrspace(1) %gep) -define amdgpu_kernel void @global_load_tr_b128_v8f16(ptr addrspace(1) %addr, ptr addrspace(1) %out) { -bb: - %gep = getelementptr i64, ptr addrspace(1) %addr, i32 4 - %tmp0 = call <8 x half> @llvm.amdgcn.global.load.tr.v8f16(ptr addrspace(1) %gep) - store <8 x half> %tmp0, ptr addrspace(1) %out, align 16 - ret void -} - -; CHECK: DIVERGENT: %tmp0 = call <8 x bfloat> @llvm.amdgcn.global.load.tr.v8bf16(ptr addrspace(1) %gep) -define amdgpu_kernel void @global_load_tr_b128_v8bf16(ptr addrspace(1) %addr, ptr addrspace(1) %out) { -bb: - %gep = getelementptr i64, ptr addrspace(1) %addr, i32 4 - %tmp0 = call <8 x bfloat> @llvm.amdgcn.global.load.tr.v8bf16(ptr addrspace(1) %gep) - store <8 x bfloat> %tmp0, ptr addrspace(1) %out, align 16 - ret void -} - -; CHECK: DIVERGENT: %tmp0 = call i32 @llvm.amdgcn.global.load.tr.i32(ptr addrspace(1) %gep) +; CHECK: DIVERGENT: %tmp0 = call i32 @llvm.amdgcn.global.load.tr.b64.i32(ptr addrspace(1) %addr) define amdgpu_kernel void @global_load_tr_b64_i32(ptr addrspace(1) %addr, ptr addrspace(1) %out) { bb: - %gep = getelementptr i64, ptr addrspace(1) %addr, i32 4 - %tmp0 = call i32 @llvm.amdgcn.global.load.tr.i32(ptr addrspace(1) %gep) + %tmp0 = call i32 @llvm.amdgcn.global.load.tr.b64.i32(ptr addrspace(1) %addr) store i32 %tmp0, ptr addrspace(1) %out, align 4 ret void } -; CHECK: DIVERGENT: %tmp0 = call <4 x i16> @llvm.amdgcn.global.load.tr.v4i16(ptr addrspace(1) %gep) -define amdgpu_kernel void @global_load_tr_b128_v4i16_(ptr addrspace(1) %addr, ptr addrspace(1) %out) { +; CHECK: DIVERGENT: %tmp0 = call <4 x i16> @llvm.amdgcn.global.load.tr.b128.v4i16(ptr addrspace(1) %addr) +define amdgpu_kernel void @global_load_tr_b128_v4i16(ptr addrspace(1) %addr, ptr addrspace(1) %out) { bb: - %gep = getelementptr i64, ptr addrspace(1) %addr, i32 4 - %tmp0 = call <4 x i16> @llvm.amdgcn.global.load.tr.v4i16(ptr addrspace(1) %gep) + %tmp0 = call <4 x i16> @llvm.amdgcn.global.load.tr.b128.v4i16(ptr addrspace(1) %addr) store <4 x i16> %tmp0, ptr addrspace(1) %out, align 8 ret void } -; CHECK: DIVERGENT: %tmp0 = call <4 x half> @llvm.amdgcn.global.load.tr.v4f16(ptr addrspace(1) %gep) -define amdgpu_kernel void @global_load_tr_b128_v4f16(ptr addrspace(1) %addr, ptr addrspace(1) %out) { -bb: - %gep = getelementptr i64, ptr addrspace(1) %addr, i32 4 - %tmp0 = call <4 x half> @llvm.amdgcn.global.load.tr.v4f16(ptr addrspace(1) %gep) - store <4 x half> %tmp0, ptr addrspace(1) %out, align 8 - ret void -} - -; CHECK: DIVERGENT: %tmp0 = call <4 x bfloat> @llvm.amdgcn.global.load.tr.v4bf16(ptr addrspace(1) %gep) -define amdgpu_kernel void @global_load_tr_b128_v4bf16(ptr addrspace(1) %addr, ptr addrspace(1) %out) { -bb: - %gep = getelementptr i64, ptr addrspace(1) %addr, i32 4 - %tmp0 = call <4 x bfloat> @llvm.amdgcn.global.load.tr.v4bf16(ptr addrspace(1) %gep) - store <4 x bfloat> %tmp0, ptr addrspace(1) %out, align 8 - ret void -} - declare i32 @llvm.amdgcn.ds.swizzle(i32, i32) #1 declare i32 @llvm.amdgcn.permlane16(i32, i32, i32, i32, i1, i1) #1 declare i32 @llvm.amdgcn.permlanex16(i32, i32, i32, i32, i1, i1) #1 @@ -296,14 +256,10 @@ declare <8 x float> @llvm.amdgcn.swmmac.f32.16x16x32.fp8.bf8(<2 x i32>, <4 x i32 declare <8 x float> @llvm.amdgcn.swmmac.f32.16x16x32.bf8.fp8(<2 x i32>, <4 x i32>, <8 x float>, i16) declare <8 x float> @llvm.amdgcn.swmmac.f32.16x16x32.bf8.bf8(<2 x i32>, <4 x i32>, <8 x float>, i16) -declare <2 x i32> @llvm.amdgcn.global.load.tr.v2i32(ptr addrspace(1)) -declare <8 x i16> @llvm.amdgcn.global.load.tr.v8i16(ptr addrspace(1)) -declare <8 x half> @llvm.amdgcn.global.load.tr.v8f16(ptr addrspace(1)) -declare <8 x bfloat> @llvm.amdgcn.global.load.tr.v8bf16(ptr addrspace(1)) -declare i32 @llvm.amdgcn.global.load.tr.i32(ptr addrspace(1)) -declare <4 x i16> @llvm.amdgcn.global.load.tr.v4i16(ptr addrspace(1)) -declare <4 x half> @llvm.amdgcn.global.load.tr.v4f16(ptr addrspace(1)) -declare <4 x bfloat> @llvm.amdgcn.global.load.tr.v4bf16(ptr addrspace(1)) +declare <2 x i32> @llvm.amdgcn.global.load.tr.b64.v2i32(ptr addrspace(1)) +declare <8 x i16> @llvm.amdgcn.global.load.tr.b128.v8i16(ptr addrspace(1)) +declare i32 @llvm.amdgcn.global.load.tr.b64.i32(ptr addrspace(1)) +declare <4 x i16> @llvm.amdgcn.global.load.tr.b128.v4i16(ptr addrspace(1)) attributes #0 = { nounwind convergent } attributes #1 = { nounwind readnone convergent } diff --git a/llvm/test/Analysis/ValueTracking/known-non-zero.ll b/llvm/test/Analysis/ValueTracking/known-non-zero.ll index d804fe96649039c03842736e5225d5851acee5a4..0159050d925c3eec0d8fa803d9d84b7f4bfe04ca 100644 --- a/llvm/test/Analysis/ValueTracking/known-non-zero.ll +++ b/llvm/test/Analysis/ValueTracking/known-non-zero.ll @@ -1292,4 +1292,162 @@ true: false: ret i1 %ne } + +define <2 x i1> @range_metadata_vec(ptr %p, <2 x i32> %x) { +; CHECK-LABEL: @range_metadata_vec( +; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true> +; + %v = load <2 x i32>, ptr %p, !range !{i32 1, i32 100} + %or = or <2 x i32> %v, %x + %cmp = icmp ne <2 x i32> %or, zeroinitializer + ret <2 x i1> %cmp +} + +define i1 @range_attr(i8 range(i8 1, 0) %x, i8 %y) { +; CHECK-LABEL: @range_attr( +; CHECK-NEXT: ret i1 false +; + %or = or i8 %y, %x + %cmp = icmp eq i8 %or, 0 + ret i1 %cmp +} + +define i1 @neg_range_attr(i8 range(i8 -1, 1) %x, i8 %y) { +; CHECK-LABEL: @neg_range_attr( +; CHECK-NEXT: [[I:%.*]] = or i8 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[I]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +; + %or = or i8 %y, %x + %cmp = icmp eq i8 %or, 0 + ret i1 %cmp +} + +declare range(i8 1, 0) i8 @returns_non_zero_range_helper() +declare range(i8 -1, 1) i8 @returns_contain_zero_range_helper() + +define i1 @range_return(i8 %y) { +; CHECK-LABEL: @range_return( +; CHECK-NEXT: [[I:%.*]] = call i8 @returns_non_zero_range_helper() +; CHECK-NEXT: ret i1 false +; + %x = call i8 @returns_non_zero_range_helper() + %or = or i8 %y, %x + %cmp = icmp eq i8 %or, 0 + ret i1 %cmp +} + +define i1 @neg_range_return(i8 %y) { +; CHECK-LABEL: @neg_range_return( +; CHECK-NEXT: [[I:%.*]] = call i8 @returns_contain_zero_range_helper() +; CHECK-NEXT: [[OR:%.*]] = or i8 [[Y:%.*]], [[I]] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[OR]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +; + %x = call i8 @returns_contain_zero_range_helper() + %or = or i8 %y, %x + %cmp = icmp eq i8 %or, 0 + ret i1 %cmp +} + +declare i8 @returns_i8_helper() + +define i1 @range_call(i8 %y) { +; CHECK-LABEL: @range_call( +; CHECK-NEXT: [[I:%.*]] = call range(i8 1, 0) i8 @returns_i8_helper() +; CHECK-NEXT: ret i1 false +; + %x = call range(i8 1, 0) i8 @returns_i8_helper() + %or = or i8 %y, %x + %cmp = icmp eq i8 %or, 0 + ret i1 %cmp +} + +define i1 @neg_range_call(i8 %y) { +; CHECK-LABEL: @neg_range_call( +; CHECK-NEXT: [[I:%.*]] = call range(i8 -1, 1) i8 @returns_i8_helper() +; CHECK-NEXT: [[OR:%.*]] = or i8 [[Y:%.*]], [[I]] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[OR]], 0 +; CHECK-NEXT: ret i1 [[CMP]] +; + %x = call range(i8 -1, 1) i8 @returns_i8_helper() + %or = or i8 %y, %x + %cmp = icmp eq i8 %or, 0 + ret i1 %cmp +} + +define <2 x i1> @range_attr_vec(<2 x i8> range(i8 1, 0) %x, <2 x i8> %y) { +; CHECK-LABEL: @range_attr_vec( +; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true> +; + %or = or <2 x i8> %y, %x + %cmp = icmp ne <2 x i8> %or, zeroinitializer + ret <2 x i1> %cmp +} + +define <2 x i1> @neg_range_attr_vec(<2 x i8> range(i8 -1, 1) %x, <2 x i8> %y) { +; CHECK-LABEL: @neg_range_attr_vec( +; CHECK-NEXT: [[OR:%.*]] = or <2 x i8> [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i8> [[OR]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %or = or <2 x i8> %y, %x + %cmp = icmp ne <2 x i8> %or, zeroinitializer + ret <2 x i1> %cmp +} + +declare range(i8 1, 0) <2 x i8> @returns_non_zero_range_helper_vec() +declare range(i8 -1, 1) <2 x i8> @returns_contain_zero_range_helper_vec() + +define <2 x i1> @range_return_vec(<2 x i8> %y) { +; CHECK-LABEL: @range_return_vec( +; CHECK-NEXT: [[I:%.*]] = call <2 x i8> @returns_non_zero_range_helper_vec() +; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true> +; + %x = call <2 x i8> @returns_non_zero_range_helper_vec() + %or = or <2 x i8> %y, %x + %cmp = icmp ne <2 x i8> %or, zeroinitializer + ret <2 x i1> %cmp +} + +define <2 x i1> @neg_range_return_vec(<2 x i8> %y) { +; CHECK-LABEL: @neg_range_return_vec( +; CHECK-NEXT: [[I:%.*]] = call <2 x i8> @returns_contain_zero_range_helper_vec() +; CHECK-NEXT: [[OR:%.*]] = or <2 x i8> [[Y:%.*]], [[I]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i8> [[OR]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %x = call <2 x i8> @returns_contain_zero_range_helper_vec() + %or = or <2 x i8> %y, %x + %cmp = icmp ne <2 x i8> %or, zeroinitializer + ret <2 x i1> %cmp +} + +declare <2 x i8> @returns_i8_helper_vec() + +define <2 x i1> @range_call_vec(<2 x i8> %y) { +; CHECK-LABEL: @range_call_vec( +; CHECK-NEXT: [[I:%.*]] = call range(i8 1, 0) <2 x i8> @returns_i8_helper_vec() +; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true> +; + %x = call range(i8 1, 0) <2 x i8> @returns_i8_helper_vec() + %or = or <2 x i8> %y, %x + %cmp = icmp ne <2 x i8> %or, zeroinitializer + ret <2 x i1> %cmp +} + +define <2 x i1> @neg_range_call_vec(<2 x i8> %y) { +; CHECK-LABEL: @neg_range_call_vec( +; CHECK-NEXT: [[I:%.*]] = call range(i8 -1, 1) <2 x i8> @returns_i8_helper_vec() +; CHECK-NEXT: [[OR:%.*]] = or <2 x i8> [[Y:%.*]], [[I]] +; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i8> [[OR]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %x = call range(i8 -1, 1) <2 x i8> @returns_i8_helper_vec() + %or = or <2 x i8> %y, %x + %cmp = icmp ne <2 x i8> %or, zeroinitializer + ret <2 x i1> %cmp +} + + declare i32 @llvm.experimental.get.vector.length.i32(i32, i32, i1) diff --git a/llvm/test/Analysis/ValueTracking/knownbits-select-from-cond.ll b/llvm/test/Analysis/ValueTracking/knownbits-select-from-cond.ll new file mode 100644 index 0000000000000000000000000000000000000000..c3343edfb4c9b35c030a7bdc13c55f6a7296bbe0 --- /dev/null +++ b/llvm/test/Analysis/ValueTracking/knownbits-select-from-cond.ll @@ -0,0 +1,81 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes=instcombine -S < %s | FileCheck %s + +define i8 @select_condition_implies_highbits_op1(i8 %xx, i8 noundef %y) { +; CHECK-LABEL: @select_condition_implies_highbits_op1( +; CHECK-NEXT: [[X:%.*]] = and i8 [[XX:%.*]], 15 +; CHECK-NEXT: [[COND:%.*]] = icmp ult i8 [[Y:%.*]], 3 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], i8 [[Y]], i8 [[X]] +; CHECK-NEXT: [[R:%.*]] = or disjoint i8 [[SEL]], 32 +; CHECK-NEXT: ret i8 [[R]] +; + %x = and i8 %xx, 15 + %cond = icmp ult i8 %y, 3 + %sel = select i1 %cond, i8 %y, i8 %x + %r = add i8 %sel, 32 + ret i8 %r +} + +define i8 @select_condition_implies_highbits_op1_maybe_undef_fail(i8 %xx, i8 %y) { +; CHECK-LABEL: @select_condition_implies_highbits_op1_maybe_undef_fail( +; CHECK-NEXT: [[X:%.*]] = and i8 [[XX:%.*]], 15 +; CHECK-NEXT: [[COND:%.*]] = icmp ult i8 [[Y:%.*]], 3 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], i8 [[Y]], i8 [[X]] +; CHECK-NEXT: [[R:%.*]] = add i8 [[SEL]], 32 +; CHECK-NEXT: ret i8 [[R]] +; + %x = and i8 %xx, 15 + %cond = icmp ult i8 %y, 3 + %sel = select i1 %cond, i8 %y, i8 %x + %r = add i8 %sel, 32 + ret i8 %r +} + +define i8 @select_condition_implies_highbits_op2(i8 %xx, i8 noundef %y) { +; CHECK-LABEL: @select_condition_implies_highbits_op2( +; CHECK-NEXT: [[X:%.*]] = and i8 [[XX:%.*]], 15 +; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[Y:%.*]], 3 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], i8 [[X]], i8 [[Y]] +; CHECK-NEXT: [[R:%.*]] = or disjoint i8 [[SEL]], 32 +; CHECK-NEXT: ret i8 [[R]] +; + %x = and i8 %xx, 15 + %cond = icmp ugt i8 %y, 3 + %sel = select i1 %cond, i8 %x, i8 %y + %r = add i8 %sel, 32 + ret i8 %r +} + +define i8 @select_condition_implies_highbits_op1_and(i8 %xx, i8 noundef %y, i1 %other_cond) { +; CHECK-LABEL: @select_condition_implies_highbits_op1_and( +; CHECK-NEXT: [[X:%.*]] = and i8 [[XX:%.*]], 15 +; CHECK-NEXT: [[COND0:%.*]] = icmp ult i8 [[Y:%.*]], 3 +; CHECK-NEXT: [[COND:%.*]] = and i1 [[COND0]], [[OTHER_COND:%.*]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], i8 [[Y]], i8 [[X]] +; CHECK-NEXT: [[R:%.*]] = or disjoint i8 [[SEL]], 32 +; CHECK-NEXT: ret i8 [[R]] +; + %x = and i8 %xx, 15 + %cond0 = icmp ult i8 %y, 3 + %cond = and i1 %cond0, %other_cond + %sel = select i1 %cond, i8 %y, i8 %x + %r = add i8 %sel, 32 + ret i8 %r +} + +define i8 @select_condition_implies_highbits_op2_or(i8 %xx, i8 noundef %y, i1 %other_cond) { +; CHECK-LABEL: @select_condition_implies_highbits_op2_or( +; CHECK-NEXT: [[X:%.*]] = and i8 [[XX:%.*]], 15 +; CHECK-NEXT: [[COND0:%.*]] = icmp ugt i8 [[Y:%.*]], 3 +; CHECK-NEXT: [[COND:%.*]] = or i1 [[COND0]], [[OTHER_COND:%.*]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], i8 [[X]], i8 [[Y]] +; CHECK-NEXT: [[R:%.*]] = or disjoint i8 [[SEL]], 32 +; CHECK-NEXT: ret i8 [[R]] +; + %x = and i8 %xx, 15 + %cond0 = icmp ugt i8 %y, 3 + %cond = or i1 %cond0, %other_cond + %sel = select i1 %cond, i8 %x, i8 %y + %r = add i8 %sel, 32 + ret i8 %r +} diff --git a/llvm/test/Assembler/debug-info.ll b/llvm/test/Assembler/debug-info.ll index 419623a2cb7d14e7f50651fe1e9f37c01846d633..06144b261373f42df9c7a438b68889e361ca0946 100644 --- a/llvm/test/Assembler/debug-info.ll +++ b/llvm/test/Assembler/debug-info.ll @@ -1,8 +1,8 @@ ; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s ; RUN: verify-uselistorder %s -; CHECK: !named = !{!0, !0, !1, !2, !3, !4, !5, !6, !7, !8, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38, !39} -!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38, !39, !40, !41, !42} +; CHECK: !named = !{!0, !0, !1, !2, !3, !4, !5, !6, !7, !8, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38, !39, !40, !41, !42, !43} +!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38, !39, !40, !41, !42, !43, !44, !45, !46} ; CHECK: !0 = !DISubrange(count: 3, lowerBound: 0) ; CHECK-NEXT: !1 = !DISubrange(count: 3, lowerBound: 4) @@ -99,3 +99,15 @@ ; CHECK-NEXT: !39 = !DIBasicType(name: "u64.le", size: 64, align: 1, encoding: DW_ATE_unsigned, flags: DIFlagLittleEndian) !41 = !DIBasicType(name: "u64.be", size: 64, align: 1, encoding: DW_ATE_unsigned, flags: DIFlagBigEndian) !42 = !DIBasicType(name: "u64.le", size: 64, align: 1, encoding: DW_ATE_unsigned, flags: DIFlagLittleEndian) + +; CHECK: !DIDerivedType(tag: DW_TAG_LLVM_ptrauth_type, baseType: !13, ptrAuthKey: 2, ptrAuthIsAddressDiscriminated: true, ptrAuthExtraDiscriminator: 1234, ptrAuthIsaPointer: false, ptrAuthAuthenticatesNullValues: false) +!43 = !DIDerivedType(tag: DW_TAG_LLVM_ptrauth_type, baseType: !15, ptrAuthKey: 2, ptrAuthIsAddressDiscriminated: true, ptrAuthExtraDiscriminator: 1234) + +; CHECK: !DIDerivedType(tag: DW_TAG_LLVM_ptrauth_type, baseType: !13, ptrAuthKey: 2, ptrAuthIsAddressDiscriminated: true, ptrAuthExtraDiscriminator: 1234, ptrAuthIsaPointer: true, ptrAuthAuthenticatesNullValues: false) +!44 = !DIDerivedType(tag: DW_TAG_LLVM_ptrauth_type, baseType: !15, ptrAuthKey: 2, ptrAuthIsAddressDiscriminated: true, ptrAuthExtraDiscriminator: 1234, ptrAuthIsaPointer: true) + +; CHECK: !DIDerivedType(tag: DW_TAG_LLVM_ptrauth_type, baseType: !13, ptrAuthKey: 2, ptrAuthIsAddressDiscriminated: true, ptrAuthExtraDiscriminator: 1234, ptrAuthIsaPointer: false, ptrAuthAuthenticatesNullValues: true) +!45 = !DIDerivedType(tag: DW_TAG_LLVM_ptrauth_type, baseType: !15, ptrAuthKey: 2, ptrAuthIsAddressDiscriminated: true, ptrAuthExtraDiscriminator: 1234, ptrAuthAuthenticatesNullValues: true) + +; CHECK: !DIDerivedType(tag: DW_TAG_LLVM_ptrauth_type, baseType: !13, ptrAuthKey: 2, ptrAuthIsAddressDiscriminated: true, ptrAuthExtraDiscriminator: 1234, ptrAuthIsaPointer: true, ptrAuthAuthenticatesNullValues: true) +!46 = !DIDerivedType(tag: DW_TAG_LLVM_ptrauth_type, baseType: !15, ptrAuthKey: 2, ptrAuthIsAddressDiscriminated: true, ptrAuthExtraDiscriminator: 1234, ptrAuthIsaPointer: true, ptrAuthAuthenticatesNullValues: true) diff --git a/llvm/test/Assembler/flags.ll b/llvm/test/Assembler/flags.ll index 04bddd02f50c814ed0911c6210dcee317a885c8d..d75b0cb0ea8246ab94c63dd659310d0466b6c6b7 100644 --- a/llvm/test/Assembler/flags.ll +++ b/llvm/test/Assembler/flags.ll @@ -261,3 +261,51 @@ define i64 @test_or(i64 %a, i64 %b) { %res = or disjoint i64 %a, %b ret i64 %res } + +define i32 @test_trunc_signed(i64 %a) { +; CHECK: %res = trunc nsw i64 %a to i32 + %res = trunc nsw i64 %a to i32 + ret i32 %res +} + +define i32 @test_trunc_unsigned(i64 %a) { +; CHECK: %res = trunc nuw i64 %a to i32 + %res = trunc nuw i64 %a to i32 + ret i32 %res +} + +define i32 @test_trunc_both(i64 %a) { +; CHECK: %res = trunc nuw nsw i64 %a to i32 + %res = trunc nuw nsw i64 %a to i32 + ret i32 %res +} + +define i32 @test_trunc_both_reversed(i64 %a) { +; CHECK: %res = trunc nuw nsw i64 %a to i32 + %res = trunc nsw nuw i64 %a to i32 + ret i32 %res +} + +define <2 x i32> @test_trunc_signed_vector(<2 x i64> %a) { +; CHECK: %res = trunc nsw <2 x i64> %a to <2 x i32> + %res = trunc nsw <2 x i64> %a to <2 x i32> + ret <2 x i32> %res +} + +define <2 x i32> @test_trunc_unsigned_vector(<2 x i64> %a) { +; CHECK: %res = trunc nuw <2 x i64> %a to <2 x i32> + %res = trunc nuw <2 x i64> %a to <2 x i32> + ret <2 x i32> %res +} + +define <2 x i32> @test_trunc_both_vector(<2 x i64> %a) { +; CHECK: %res = trunc nuw nsw <2 x i64> %a to <2 x i32> + %res = trunc nuw nsw <2 x i64> %a to <2 x i32> + ret <2 x i32> %res +} + +define <2 x i32> @test_trunc_both_reversed_vector(<2 x i64> %a) { +; CHECK: %res = trunc nuw nsw <2 x i64> %a to <2 x i32> + %res = trunc nsw nuw <2 x i64> %a to <2 x i32> + ret <2 x i32> %res +} diff --git a/llvm/test/Assembler/getelementptr.ll b/llvm/test/Assembler/getelementptr.ll index 50695a65abb3338e927be4ac076a763bd5d42f66..45c6a2d00cc346d56bd16b7ff381e6c95e325a4f 100644 --- a/llvm/test/Assembler/getelementptr.ll +++ b/llvm/test/Assembler/getelementptr.ll @@ -23,24 +23,26 @@ @PR23753_b = global ptr getelementptr (i8, ptr @PR23753_a, i64 ptrtoint (ptr @PR23753_a to i64)) ; CHECK: @PR23753_b = global ptr getelementptr (i8, ptr @PR23753_a, i64 ptrtoint (ptr @PR23753_a to i64)) -; Verify that inrange on an index inhibits over-indexed getelementptr folding. +; Verify that inrange doesn't inhibit over-indexed getelementptr folding, +; but does inhibit combining two GEPs where the inner one has inrange (this +; will be done when DataLayout is available instead). @nestedarray = global [2 x [4 x ptr]] zeroinitializer -; CHECK: @nestedarray.1 = alias ptr, getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, inrange i32 0, i64 1, i32 0) -@nestedarray.1 = alias ptr, getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, inrange i32 0, i32 0, i32 4) +; CHECK: @nestedarray.1 = alias ptr, getelementptr inbounds inrange(-32, 32) ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i64 1, i32 0) +@nestedarray.1 = alias ptr, getelementptr inbounds inrange(-32, 32) ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i32 0, i32 4) -; CHECK: @nestedarray.2 = alias ptr, getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, i32 0, inrange i32 0, i32 4) -@nestedarray.2 = alias ptr, getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, i32 0, inrange i32 0, i32 4) +; CHECK: @nestedarray.2 = alias ptr, getelementptr inbounds inrange(0, 1) ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i64 1, i32 0) +@nestedarray.2 = alias ptr, getelementptr inbounds inrange(0, 1) ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i32 0, i32 4) -; CHECK: @nestedarray.3 = alias ptr, getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, i32 0, inrange i32 0) -@nestedarray.3 = alias ptr, getelementptr inbounds ([4 x ptr], ptr getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, i32 0, inrange i32 0), i32 0, i32 0) +; CHECK: @nestedarray.3 = alias ptr, getelementptr inbounds inrange(0, 4) ([4 x ptr], ptr @nestedarray, i32 0, i32 0) +@nestedarray.3 = alias ptr, getelementptr inbounds inrange(0, 4) ([4 x ptr], ptr getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i32 0), i32 0, i32 0) -; CHECK: @nestedarray.4 = alias ptr, getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i32 1, i32 0) -@nestedarray.4 = alias ptr, getelementptr inbounds ([4 x ptr], ptr getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, i32 0, inrange i32 0), i32 1, i32 0) +; CHECK: @nestedarray.4 = alias ptr, getelementptr inbounds ([4 x ptr], ptr getelementptr inbounds inrange(0, 4) ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i32 0), i32 1, i32 0) +@nestedarray.4 = alias ptr, getelementptr inbounds ([4 x ptr], ptr getelementptr inbounds inrange(0, 4) ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i32 0), i32 1, i32 0) -; CHECK: @nestedarray.5 = alias ptr, getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, inrange i32 0, i32 1, i32 0) -@nestedarray.5 = alias ptr, getelementptr inbounds ([4 x ptr], ptr getelementptr inbounds ([2 x [4 x ptr]], ptr @nestedarray, inrange i32 0, i32 0), i32 1, i32 0) +; CHECK: @nestedarray.5 = alias ptr, getelementptr inbounds ([4 x ptr], ptr getelementptr inbounds inrange(0, 32) ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i32 0), i32 1, i32 0) +@nestedarray.5 = alias ptr, getelementptr inbounds ([4 x ptr], ptr getelementptr inbounds inrange(0, 32) ([2 x [4 x ptr]], ptr @nestedarray, i32 0, i32 0), i32 1, i32 0) ; See if i92 indices work too. define ptr @test(ptr %t, i92 %n) { diff --git a/llvm/test/Assembler/inrange-errors.ll b/llvm/test/Assembler/inrange-errors.ll new file mode 100644 index 0000000000000000000000000000000000000000..128c21983ca6176ac130abadf2e067a000bf2ec5 --- /dev/null +++ b/llvm/test/Assembler/inrange-errors.ll @@ -0,0 +1,46 @@ +; RUN: split-file %s %t +; RUN: not llvm-as < %t/parse-error-1.ll -o /dev/null 2>&1 | FileCheck --check-prefix=PARSE-ERROR-1 %s +; RUN: not llvm-as < %t/parse-error-2.ll -o /dev/null 2>&1 | FileCheck --check-prefix=PARSE-ERROR-2 %s +; RUN: not llvm-as < %t/parse-error-3.ll -o /dev/null 2>&1 | FileCheck --check-prefix=PARSE-ERROR-3 %s +; RUN: not llvm-as < %t/parse-error-4.ll -o /dev/null 2>&1 | FileCheck --check-prefix=PARSE-ERROR-4 %s +; RUN: not llvm-as < %t/end-not-larger-start.ll -o /dev/null 2>&1 | FileCheck --check-prefix=END-NOT-LARGER-START %s + +;--- parse-error-1.ll + +; PARSE-ERROR-1: error: expected integer +@g = external global i8 +define ptr @test() { + ret ptr getelementptr inrange (i8, ptr @g, i64 8) +} + +;--- parse-error-2.ll + +; PARSE-ERROR-2: error: expected ',' +@g = external global i8 +define ptr @test() { + ret ptr getelementptr inrange(42 (i8, ptr @g, i64 8) +} + +;--- parse-error-3.ll + +; PARSE-ERROR-3: error: expected integer +@g = external global i8 +define ptr @test() { + ret ptr getelementptr inrange(42, (i8, ptr @g, i64 8) +} + +;--- parse-error-4.ll + +; PARSE-ERROR-4: error: expected ')' +@g = external global i8 +define ptr @test() { + ret ptr getelementptr inrange(42, 123 (i8, ptr @g, i64 8) +} + +;--- end-not-larger-start.ll + +; END-NOT-LARGER-START: error: expected end to be larger than start +@g = external global i8 +define ptr @test() { + ret ptr getelementptr inrange(42, 42) (i8, ptr @g, i64 8) +} diff --git a/llvm/test/Bindings/OCaml/core.ml b/llvm/test/Bindings/OCaml/core.ml index a9abc9d17fe46e920c20f9e5793d6917efcc53e0..64bfa8ee412dfe727f68752dd53f9d5683515a2f 100644 --- a/llvm/test/Bindings/OCaml/core.ml +++ b/llvm/test/Bindings/OCaml/core.ml @@ -252,7 +252,7 @@ let test_constants () = group "constant arithmetic"; (* CHECK: @const_neg = global i64 sub * CHECK: @const_nsw_neg = global i64 sub nsw - * CHECK: @const_nuw_neg = global i64 sub nuw + * CHECK: @const_nuw_neg = global i64 sub * CHECK: @const_not = global i64 xor * CHECK: @const_add = global i64 add * CHECK: @const_nsw_add = global i64 add nsw diff --git a/llvm/test/Bindings/OCaml/debuginfo.ml b/llvm/test/Bindings/OCaml/debuginfo.ml index d469d4715b0034b1e1469b7a83cd5749e5415986..f95800dfcb025d18e5391e3e395fdd08c7d8ac3c 100644 --- a/llvm/test/Bindings/OCaml/debuginfo.ml +++ b/llvm/test/Bindings/OCaml/debuginfo.ml @@ -39,6 +39,8 @@ let prepare_target llmod = let new_module () = let m = Llvm.create_module context module_name in let () = prepare_target m in + let () = Llvm_debuginfo.set_is_new_dbg_info_format m true in + insist (Llvm_debuginfo.is_new_dbg_info_format m); m let test_get_module () = @@ -285,8 +287,8 @@ let test_variables f dibuilder file_di fun_di = ~var_info:auto_var ~expr:(Llvm_debuginfo.dibuild_expression dibuilder [||]) ~location ~instr:entry_term in - let () = Printf.printf "%s\n" (Llvm.string_of_llvalue vdi) in - (* CHECK: call void @llvm.dbg.declare(metadata ptr %my_alloca, metadata {{![0-9]+}}, metadata !DIExpression()), !dbg {{\![0-9]+}} + let () = Printf.printf "%s\n" (Llvm.string_of_lldbgrecord vdi) in + (* CHECK: dbg_declare(ptr %my_alloca, ![[#]], !DIExpression(), ![[#]]) *) let arg0 = (Llvm.params f).(0) in let arg_var = Llvm_debuginfo.dibuild_create_parameter_variable dibuilder ~scope:fun_di @@ -297,8 +299,8 @@ let test_variables f dibuilder file_di fun_di = ~var_info:arg_var ~expr:(Llvm_debuginfo.dibuild_expression dibuilder [||]) ~location ~instr:entry_term in - let () = Printf.printf "%s\n" (Llvm.string_of_llvalue argdi) in - (* CHECK: call void @llvm.dbg.declare(metadata i32 %0, metadata {{![0-9]+}}, metadata !DIExpression()), !dbg {{\![0-9]+}} + let () = Printf.printf "%s\n" (Llvm.string_of_lldbgrecord argdi) in + (* CHECK: dbg_declare(i32 %0, ![[#]], !DIExpression(), ![[#]]) *) () diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll index be0207599478b815fb01870a8b375ef1c29f3cc1..953a16b7e624e1b3e24104e80140de0b383d08b8 100644 --- a/llvm/test/Bindings/llvm-c/echo.ll +++ b/llvm/test/Bindings/llvm-c/echo.ll @@ -334,6 +334,20 @@ define void @test_fast_math_flags_call_outer(float %a) { ret void } +define void @test_func_prefix_data_01() prefix i32 123 { + ret void +} + +define void @test_func_prefix_data_02() prefix i64 2000 { + ret void +} + +%func_prolog_struct = type <{ i8, i8, ptr }> + +define void @test_func_prologue_data_01() prologue %func_prolog_struct <{ i8 235, i8 8, ptr zeroinitializer}> { + ret void +} + !llvm.dbg.cu = !{!0, !2} !llvm.module.flags = !{!3} diff --git a/llvm/test/Bitcode/DIExpression-aggresult.ll b/llvm/test/Bitcode/DIExpression-aggresult.ll index 0b89454aa2f9420c120edab8868bf67e285f92a9..017218277d02bf19f2a969469fc2aa08f552e2b5 100644 --- a/llvm/test/Bitcode/DIExpression-aggresult.ll +++ b/llvm/test/Bitcode/DIExpression-aggresult.ll @@ -1,4 +1,5 @@ ; RUN: llvm-dis -o - %s.bc | FileCheck %s +; RUN: llvm-dis -o - %s.bc --load-bitcode-into-experimental-debuginfo-iterators=true | FileCheck %s %class.A = type { i32, i32, i32, i32 } define void @_Z3fooi(%class.A* sret(%class.A) %agg.result) #0 !dbg !3 { diff --git a/llvm/test/Bitcode/compatibility-3.6.ll b/llvm/test/Bitcode/compatibility-3.6.ll index b1f4abf7b8c554ec9b14302ae6a4cccc6b3955ff..2190e2fbccf28868b602a7db4cba1733f5b4cc3c 100644 --- a/llvm/test/Bitcode/compatibility-3.6.ll +++ b/llvm/test/Bitcode/compatibility-3.6.ll @@ -1061,16 +1061,16 @@ define void @instructions.va_arg(i8* %v, ...) { %ap2 = bitcast i8** %ap to i8* call void @llvm.va_start(i8* %ap2) - ; CHECK: call void @llvm.va_start(ptr %ap2) + ; CHECK: call void @llvm.va_start.p0(ptr %ap2) va_arg i8* %ap2, i32 ; CHECK: va_arg ptr %ap2, i32 call void @llvm.va_copy(i8* %v, i8* %ap2) - ; CHECK: call void @llvm.va_copy(ptr %v, ptr %ap2) + ; CHECK: call void @llvm.va_copy.p0(ptr %v, ptr %ap2) call void @llvm.va_end(i8* %ap2) - ; CHECK: call void @llvm.va_end(ptr %ap2) + ; CHECK: call void @llvm.va_end.p0(ptr %ap2) ret void } @@ -1178,11 +1178,11 @@ define void @intrinsics.codegen() { ; CHECK: attributes #27 = { uwtable } ; CHECK: attributes #28 = { "cpu"="cortex-a8" } ; CHECK: attributes #29 = { nocallback nofree nosync nounwind willreturn memory(none) } -; CHECK: attributes #30 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #31 = { nounwind memory(argmem: read) } -; CHECK: attributes #32 = { nounwind memory(argmem: readwrite) } -; CHECK: attributes #33 = { nocallback nofree nosync nounwind willreturn memory(read) } -; CHECK: attributes #34 = { nocallback nounwind } +; CHECK: attributes #30 = { nounwind memory(argmem: read) } +; CHECK: attributes #31 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #32 = { nocallback nofree nosync nounwind willreturn memory(read) } +; CHECK: attributes #33 = { nocallback nounwind } +; CHECK: attributes #34 = { nocallback nofree nosync nounwind willreturn } ; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #36 = { builtin } diff --git a/llvm/test/Bitcode/compatibility-3.7.ll b/llvm/test/Bitcode/compatibility-3.7.ll index 91e55f6eda59f99dd44790cc5f379f937a07aaea..7e59b5c1be6e2f0c80c2ac77173a79a0dc4a79ff 100644 --- a/llvm/test/Bitcode/compatibility-3.7.ll +++ b/llvm/test/Bitcode/compatibility-3.7.ll @@ -1092,16 +1092,16 @@ define void @instructions.va_arg(i8* %v, ...) { %ap2 = bitcast i8** %ap to i8* call void @llvm.va_start(i8* %ap2) - ; CHECK: call void @llvm.va_start(ptr %ap2) + ; CHECK: call void @llvm.va_start.p0(ptr %ap2) va_arg i8* %ap2, i32 ; CHECK: va_arg ptr %ap2, i32 call void @llvm.va_copy(i8* %v, i8* %ap2) - ; CHECK: call void @llvm.va_copy(ptr %v, ptr %ap2) + ; CHECK: call void @llvm.va_copy.p0(ptr %v, ptr %ap2) call void @llvm.va_end(i8* %ap2) - ; CHECK: call void @llvm.va_end(ptr %ap2) + ; CHECK: call void @llvm.va_end.p0(ptr %ap2) ret void } @@ -1241,11 +1241,11 @@ define void @misc.metadata() { ; CHECK: attributes #30 = { uwtable } ; CHECK: attributes #31 = { "cpu"="cortex-a8" } ; CHECK: attributes #32 = { nocallback nofree nosync nounwind willreturn memory(none) } -; CHECK: attributes #33 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #34 = { nounwind memory(argmem: read) } -; CHECK: attributes #35 = { nounwind memory(argmem: readwrite) } -; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn memory(read) } -; CHECK: attributes #37 = { nocallback nounwind } +; CHECK: attributes #33 = { nounwind memory(argmem: read) } +; CHECK: attributes #34 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(read) } +; CHECK: attributes #36 = { nocallback nounwind } +; CHECK: attributes #37 = { nocallback nofree nosync nounwind willreturn } ; CHECK: attributes #38 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #39 = { builtin } diff --git a/llvm/test/Bitcode/compatibility-3.8.ll b/llvm/test/Bitcode/compatibility-3.8.ll index aa4d8b14968c6e2764c270bc9ccdbf649994d7c0..ebd1f2fff8c94c8343bee3afd5d25c3910edfb15 100644 --- a/llvm/test/Bitcode/compatibility-3.8.ll +++ b/llvm/test/Bitcode/compatibility-3.8.ll @@ -1247,16 +1247,16 @@ define void @instructions.va_arg(i8* %v, ...) { %ap2 = bitcast i8** %ap to i8* call void @llvm.va_start(i8* %ap2) - ; CHECK: call void @llvm.va_start(ptr %ap2) + ; CHECK: call void @llvm.va_start.p0(ptr %ap2) va_arg i8* %ap2, i32 ; CHECK: va_arg ptr %ap2, i32 call void @llvm.va_copy(i8* %v, i8* %ap2) - ; CHECK: call void @llvm.va_copy(ptr %v, ptr %ap2) + ; CHECK: call void @llvm.va_copy.p0(ptr %v, ptr %ap2) call void @llvm.va_end(i8* %ap2) - ; CHECK: call void @llvm.va_end(ptr %ap2) + ; CHECK: call void @llvm.va_end.p0(ptr %ap2) ret void } @@ -1551,11 +1551,11 @@ normal: ; CHECK: attributes #33 = { memory(inaccessiblemem: readwrite) } ; CHECK: attributes #34 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(none) } -; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #37 = { nounwind memory(argmem: read) } -; CHECK: attributes #38 = { nounwind memory(argmem: readwrite) } -; CHECK: attributes #39 = { nocallback nofree nosync nounwind willreturn memory(read) } -; CHECK: attributes #40 = { nocallback nounwind } +; CHECK: attributes #36 = { nounwind memory(argmem: read) } +; CHECK: attributes #37 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #38 = { nocallback nofree nosync nounwind willreturn memory(read) } +; CHECK: attributes #39 = { nocallback nounwind } +; CHECK: attributes #40 = { nocallback nofree nosync nounwind willreturn } ; CHECK: attributes #41 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #42 = { builtin } diff --git a/llvm/test/Bitcode/compatibility-3.9.ll b/llvm/test/Bitcode/compatibility-3.9.ll index e3c84f6e60071498279c9cb69fee2f569dd1656e..c34f04ceb0de39b1744f01b4c09efb5063736d96 100644 --- a/llvm/test/Bitcode/compatibility-3.9.ll +++ b/llvm/test/Bitcode/compatibility-3.9.ll @@ -1318,16 +1318,16 @@ define void @instructions.va_arg(i8* %v, ...) { %ap2 = bitcast i8** %ap to i8* call void @llvm.va_start(i8* %ap2) - ; CHECK: call void @llvm.va_start(ptr %ap2) + ; CHECK: call void @llvm.va_start.p0(ptr %ap2) va_arg i8* %ap2, i32 ; CHECK: va_arg ptr %ap2, i32 call void @llvm.va_copy(i8* %v, i8* %ap2) - ; CHECK: call void @llvm.va_copy(ptr %v, ptr %ap2) + ; CHECK: call void @llvm.va_copy.p0(ptr %v, ptr %ap2) call void @llvm.va_end(i8* %ap2) - ; CHECK: call void @llvm.va_end(ptr %ap2) + ; CHECK: call void @llvm.va_end.p0(ptr %ap2) ret void } @@ -1624,11 +1624,11 @@ declare void @f.writeonly() writeonly ; CHECK: attributes #33 = { memory(inaccessiblemem: readwrite) } ; CHECK: attributes #34 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(none) } -; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #37 = { nounwind memory(argmem: read) } -; CHECK: attributes #38 = { nounwind memory(argmem: readwrite) } -; CHECK: attributes #39 = { nocallback nofree nosync nounwind willreturn memory(read) } -; CHECK: attributes #40 = { nocallback nounwind } +; CHECK: attributes #36 = { nounwind memory(argmem: read) } +; CHECK: attributes #37 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #38 = { nocallback nofree nosync nounwind willreturn memory(read) } +; CHECK: attributes #39 = { nocallback nounwind } +; CHECK: attributes #40 = { nocallback nofree nosync nounwind willreturn } ; CHECK: attributes #41 = { memory(write) } ; CHECK: attributes #42 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #43 = { builtin } diff --git a/llvm/test/Bitcode/compatibility-4.0.ll b/llvm/test/Bitcode/compatibility-4.0.ll index da5ea0e19639c1b2285d88b92bd8e20d2fb359fb..05bffda1d117a364ec30e966668c8db90df7dddc 100644 --- a/llvm/test/Bitcode/compatibility-4.0.ll +++ b/llvm/test/Bitcode/compatibility-4.0.ll @@ -1318,16 +1318,16 @@ define void @instructions.va_arg(i8* %v, ...) { %ap2 = bitcast i8** %ap to i8* call void @llvm.va_start(i8* %ap2) - ; CHECK: call void @llvm.va_start(ptr %ap2) + ; CHECK: call void @llvm.va_start.p0(ptr %ap2) va_arg i8* %ap2, i32 ; CHECK: va_arg ptr %ap2, i32 call void @llvm.va_copy(i8* %v, i8* %ap2) - ; CHECK: call void @llvm.va_copy(ptr %v, ptr %ap2) + ; CHECK: call void @llvm.va_copy.p0(ptr %v, ptr %ap2) call void @llvm.va_end(i8* %ap2) - ; CHECK: call void @llvm.va_end(ptr %ap2) + ; CHECK: call void @llvm.va_end.p0(ptr %ap2) ret void } @@ -1609,7 +1609,7 @@ declare void @f.writeonly() writeonly ;; Constant Expressions define i8** @constexpr() { - ; CHECK: ret ptr getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, inrange i32 1, i32 2) + ; CHECK: ret ptr getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, i32 1, i32 2) ret i8** getelementptr inbounds ({ [4 x i8*], [4 x i8*] }, { [4 x i8*], [4 x i8*] }* null, i32 0, inrange i32 1, i32 2) } @@ -1649,11 +1649,11 @@ define i8** @constexpr() { ; CHECK: attributes #33 = { memory(inaccessiblemem: readwrite) } ; CHECK: attributes #34 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(none) } -; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #37 = { nounwind memory(argmem: read) } -; CHECK: attributes #38 = { nounwind memory(argmem: readwrite) } -; CHECK: attributes #39 = { nocallback nofree nosync nounwind willreturn memory(read) } -; CHECK: attributes #40 = { nocallback nounwind } +; CHECK: attributes #36 = { nounwind memory(argmem: read) } +; CHECK: attributes #37 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #38 = { nocallback nofree nosync nounwind willreturn memory(read) } +; CHECK: attributes #39 = { nocallback nounwind } +; CHECK: attributes #40 = { nocallback nofree nosync nounwind willreturn } ; CHECK: attributes #41 = { memory(write) } ; CHECK: attributes #42 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #43 = { builtin } diff --git a/llvm/test/Bitcode/compatibility-5.0.ll b/llvm/test/Bitcode/compatibility-5.0.ll index 7a39ae6256b80598eb150557c777879483f133cb..0c872289c62ba8fe4abebcc79648ec3b34e8dcf5 100644 --- a/llvm/test/Bitcode/compatibility-5.0.ll +++ b/llvm/test/Bitcode/compatibility-5.0.ll @@ -1330,16 +1330,16 @@ define void @instructions.va_arg(i8* %v, ...) { %ap2 = bitcast i8** %ap to i8* call void @llvm.va_start(i8* %ap2) - ; CHECK: call void @llvm.va_start(ptr %ap2) + ; CHECK: call void @llvm.va_start.p0(ptr %ap2) va_arg i8* %ap2, i32 ; CHECK: va_arg ptr %ap2, i32 call void @llvm.va_copy(i8* %v, i8* %ap2) - ; CHECK: call void @llvm.va_copy(ptr %v, ptr %ap2) + ; CHECK: call void @llvm.va_copy.p0(ptr %v, ptr %ap2) call void @llvm.va_end(i8* %ap2) - ; CHECK: call void @llvm.va_end(ptr %ap2) + ; CHECK: call void @llvm.va_end.p0(ptr %ap2) ret void } @@ -1624,7 +1624,7 @@ declare void @f.speculatable() speculatable ;; Constant Expressions define i8** @constexpr() { - ; CHECK: ret ptr getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, inrange i32 1, i32 2) + ; CHECK: ret ptr getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, i32 1, i32 2) ret i8** getelementptr inbounds ({ [4 x i8*], [4 x i8*] }, { [4 x i8*], [4 x i8*] }* null, i32 0, inrange i32 1, i32 2) } @@ -1664,11 +1664,11 @@ define i8** @constexpr() { ; CHECK: attributes #33 = { memory(inaccessiblemem: readwrite) } ; CHECK: attributes #34 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(none) } -; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #37 = { nounwind memory(argmem: read) } -; CHECK: attributes #38 = { nounwind memory(argmem: readwrite) } -; CHECK: attributes #39 = { nocallback nofree nosync nounwind willreturn memory(read) } -; CHECK: attributes #40 = { nocallback nounwind } +; CHECK: attributes #36 = { nounwind memory(argmem: read) } +; CHECK: attributes #37 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #38 = { nocallback nofree nosync nounwind willreturn memory(read) } +; CHECK: attributes #39 = { nocallback nounwind } +; CHECK: attributes #40 = { nocallback nofree nosync nounwind willreturn } ; CHECK: attributes #41 = { memory(write) } ; CHECK: attributes #42 = { speculatable } ; CHECK: attributes #43 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } diff --git a/llvm/test/Bitcode/compatibility-6.0.ll b/llvm/test/Bitcode/compatibility-6.0.ll index 4cb1f3bd123cb10bb815d068ca03f74e70d4bbb9..44c680885be34ff4e91fb3b05a10effa3201a28e 100644 --- a/llvm/test/Bitcode/compatibility-6.0.ll +++ b/llvm/test/Bitcode/compatibility-6.0.ll @@ -1340,16 +1340,16 @@ define void @instructions.va_arg(i8* %v, ...) { %ap2 = bitcast i8** %ap to i8* call void @llvm.va_start(i8* %ap2) - ; CHECK: call void @llvm.va_start(ptr %ap2) + ; CHECK: call void @llvm.va_start.p0(ptr %ap2) va_arg i8* %ap2, i32 ; CHECK: va_arg ptr %ap2, i32 call void @llvm.va_copy(i8* %v, i8* %ap2) - ; CHECK: call void @llvm.va_copy(ptr %v, ptr %ap2) + ; CHECK: call void @llvm.va_copy.p0(ptr %v, ptr %ap2) call void @llvm.va_end(i8* %ap2) - ; CHECK: call void @llvm.va_end(ptr %ap2) + ; CHECK: call void @llvm.va_end.p0(ptr %ap2) ret void } @@ -1634,7 +1634,7 @@ declare void @f.speculatable() speculatable ;; Constant Expressions define i8** @constexpr() { - ; CHECK: ret ptr getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, inrange i32 1, i32 2) + ; CHECK: ret ptr getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, i32 1, i32 2) ret i8** getelementptr inbounds ({ [4 x i8*], [4 x i8*] }, { [4 x i8*], [4 x i8*] }* null, i32 0, inrange i32 1, i32 2) } @@ -1674,11 +1674,11 @@ define i8** @constexpr() { ; CHECK: attributes #33 = { memory(inaccessiblemem: readwrite) } ; CHECK: attributes #34 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(none) } -; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #37 = { nounwind memory(argmem: read) } -; CHECK: attributes #38 = { nounwind memory(argmem: readwrite) } -; CHECK: attributes #39 = { nocallback nofree nosync nounwind willreturn memory(read) } -; CHECK: attributes #40 = { nocallback nounwind } +; CHECK: attributes #36 = { nounwind memory(argmem: read) } +; CHECK: attributes #37 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #38 = { nocallback nofree nosync nounwind willreturn memory(read) } +; CHECK: attributes #39 = { nocallback nounwind } +; CHECK: attributes #40 = { nocallback nofree nosync nounwind willreturn } ; CHECK: attributes #41 = { memory(write) } ; CHECK: attributes #42 = { speculatable } ; CHECK: attributes #43 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } diff --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll index ce6a6571ec144cca799d5759e9eda0330d519ceb..b374924516d665640aef187ec189f0db7d4f8fa8 100644 --- a/llvm/test/Bitcode/compatibility.ll +++ b/llvm/test/Bitcode/compatibility.ll @@ -1648,16 +1648,16 @@ define void @instructions.va_arg(ptr %v, ...) { %ap = alloca ptr call void @llvm.va_start(ptr %ap) - ; CHECK: call void @llvm.va_start(ptr %ap) + ; CHECK: call void @llvm.va_start.p0(ptr %ap) va_arg ptr %ap, i32 ; CHECK: va_arg ptr %ap, i32 call void @llvm.va_copy(ptr %v, ptr %ap) - ; CHECK: call void @llvm.va_copy(ptr %v, ptr %ap) + ; CHECK: call void @llvm.va_copy.p0(ptr %v, ptr %ap) call void @llvm.va_end(ptr %ap) - ; CHECK: call void @llvm.va_end(ptr %ap) + ; CHECK: call void @llvm.va_end.p0(ptr %ap) ret void } @@ -1941,8 +1941,8 @@ declare void @f.speculatable() speculatable ;; Constant Expressions define ptr @constexpr() { - ; CHECK: ret ptr getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, inrange i32 1, i32 2) - ret ptr getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, inrange i32 1, i32 2) + ; CHECK: ret ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, i32 1, i32 2) + ret ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [4 x ptr] }, ptr null, i32 0, i32 1, i32 2) } define void @instructions.strictfp() strictfp { @@ -2091,12 +2091,12 @@ define float @nofpclass_callsites(float %arg) { ; CHECK: attributes #33 = { memory(inaccessiblemem: readwrite) } ; CHECK: attributes #34 = { memory(argmem: readwrite, inaccessiblemem: readwrite) } ; CHECK: attributes #35 = { nocallback nofree nosync nounwind willreturn memory(none) } -; CHECK: attributes #36 = { nocallback nofree nosync nounwind willreturn } -; CHECK: attributes #37 = { nounwind memory(argmem: read) } -; CHECK: attributes #38 = { nounwind memory(argmem: readwrite) } -; CHECK: attributes #39 = { nocallback nofree nosync nounwind willreturn memory(read) } -; CHECK: attributes #40 = { nocallback nounwind } -; CHECK: attributes #41 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } +; CHECK: attributes #36 = { nounwind memory(argmem: read) } +; CHECK: attributes #37 = { nounwind memory(argmem: readwrite) } +; CHECK: attributes #38 = { nocallback nofree nosync nounwind willreturn memory(read) } +; CHECK: attributes #39 = { nocallback nounwind } +; CHECK: attributes #40 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite, inaccessiblemem: readwrite) } +; CHECK: attributes #41 = { nocallback nofree nosync nounwind willreturn } ; CHECK: attributes #42 = { memory(write) } ; CHECK: attributes #43 = { speculatable } ; CHECK: attributes #44 = { strictfp } diff --git a/llvm/test/Bitcode/dbg-record-roundtrip.ll b/llvm/test/Bitcode/dbg-record-roundtrip.ll new file mode 100644 index 0000000000000000000000000000000000000000..bd347cac72067748e0b158ea4383b0af5b969aa3 --- /dev/null +++ b/llvm/test/Bitcode/dbg-record-roundtrip.ll @@ -0,0 +1,172 @@ +;; Roundtrip tests. + +;; Load RemoveDIs mode in llvm-dis but write out debug intrinsics. +; RUN: llvm-as --write-experimental-debuginfo-iterators-to-bitcode=true %s -o - \ +; RUN: | llvm-dis --load-bitcode-into-experimental-debuginfo-iterators=true --write-experimental-debuginfo=false \ +; RUN: | FileCheck %s + +;; Load and write RemoveDIs mode in llvm-dis. +; RUN: llvm-as --write-experimental-debuginfo-iterators-to-bitcode=true %s -o - \ +; RUN: | llvm-dis --load-bitcode-into-experimental-debuginfo-iterators=true --write-experimental-debuginfo=true \ +; RUN: | FileCheck %s --check-prefixes=RECORDS + +;; Load intrinsics directly into the new format (auto-upgrade). +; RUN: llvm-as --write-experimental-debuginfo-iterators-to-bitcode=false %s -o - \ +; RUN: | llvm-dis --load-bitcode-into-experimental-debuginfo-iterators=true --write-experimental-debuginfo=true \ +; RUN: | FileCheck %s --check-prefixes=RECORDS + +;; Check that verify-uselistorder passes regardless of input format. +; RUN: llvm-as %s --write-experimental-debuginfo-iterators-to-bitcode=true -o - | verify-uselistorder +; RUN: verify-uselistorder %s + +;; Confirm we're producing RemoveDI records from various tools. +; RUN: opt %s -o - --write-experimental-debuginfo-iterators-to-bitcode=true | llvm-bcanalyzer - | FileCheck %s --check-prefix=BITCODE +; RUN: llvm-as %s -o - --write-experimental-debuginfo-iterators-to-bitcode=true | llvm-bcanalyzer - | FileCheck %s --check-prefix=BITCODE +; BITCODE-DAG: DEBUG_RECORD_LABEL +; BITCODE-DAG: DEBUG_RECORD_VALUE +; BITCODE-DAG: DEBUG_RECORD_ASSIGN +; BITCODE-DAG: DEBUG_RECORD_DECLARE + +;; Check that llvm-link doesn't explode if we give it different formats to +;; link. +;; NOTE: This test fails intermittently on linux if the llvm-as output is piped +;; into llvm-link in the RUN lines below, unless the verify-uselistorder RUN +;; lines above are removed. Write to a temporary file to avoid that weirdness. +;; NOTE2: Unfortunately, the above only stopped it occuring on my machine. +;; It failed again intermittently here: +;; https://lab.llvm.org/buildbot/#/builders/245/builds/21930 +;; Allow this test to fail-over twice, until this strangeness is understood. +; ALLOW_RETRIES: 2 +; RUN: llvm-as %s --experimental-debuginfo-iterators=true --write-experimental-debuginfo-iterators-to-bitcode=true -o %t +; RUN: llvm-link %t %s --experimental-debuginfo-iterators=false -o /dev/null +; RUN: llvm-as %s --experimental-debuginfo-iterators=false -o %t +; RUN: llvm-link %t %s --experimental-debuginfo-iterators=true + +;; Checks inline. + +@g = internal dso_local global i32 0, align 4, !dbg !0 + +define internal dso_local noundef i32 @_Z3funv(i32 %p, ptr %storage) !dbg !13 { +entry: +;; Dbg record at top of block, check dbg.value configurations. +; CHECK: entry: +; CHECK-NEXT: dbg.value(metadata i32 %p, metadata ![[e:[0-9]+]], metadata !DIExpression()), !dbg ![[dbg:[0-9]+]] +; CHECK-NEXT: dbg.value(metadata ![[empty:[0-9]+]], metadata ![[e]], metadata !DIExpression()), !dbg ![[dbg]] +; CHECK-NEXT: dbg.value(metadata i32 poison, metadata ![[e]], metadata !DIExpression()), !dbg ![[dbg]] +; CHECK-NEXT: dbg.value(metadata i32 1, metadata ![[f:[0-9]+]], metadata !DIExpression()), !dbg ![[dbg]] +; RECORDS: entry: +; RECORDS-NEXT: dbg_value(i32 %p, ![[e:[0-9]+]], !DIExpression(), ![[dbg:[0-9]+]]) +; RECORDS-NEXT: dbg_value(![[empty:[0-9]+]], ![[e]], !DIExpression(), ![[dbg]]) +; RECORDS-NEXT: dbg_value(i32 poison, ![[e]], !DIExpression(), ![[dbg]]) +; RECORDS-NEXT: dbg_value(i32 1, ![[f:[0-9]+]], !DIExpression(), ![[dbg]]) + tail call void @llvm.dbg.value(metadata i32 %p, metadata !32, metadata !DIExpression()), !dbg !19 + tail call void @llvm.dbg.value(metadata !29, metadata !32, metadata !DIExpression()), !dbg !19 + tail call void @llvm.dbg.value(metadata i32 poison, metadata !32, metadata !DIExpression()), !dbg !19 + tail call void @llvm.dbg.value(metadata i32 1, metadata !33, metadata !DIExpression()), !dbg !19 +;; Arglist with an argument, constant, local use before def, poison. +; CHECK-NEXT: dbg.value(metadata !DIArgList(i32 %p, i32 0, i32 %0, i32 poison), metadata ![[f]], metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_LLVM_arg, 2, DW_OP_LLVM_arg, 3, DW_OP_plus, DW_OP_minus)), !dbg ![[dbg]] +; RECORDS-NEXT: dbg_value(!DIArgList(i32 %p, i32 0, i32 %0, i32 poison), ![[f]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_LLVM_arg, 2, DW_OP_LLVM_arg, 3, DW_OP_plus, DW_OP_minus), ![[dbg]]) + tail call void @llvm.dbg.value(metadata !DIArgList(i32 %p, i32 0, i32 %0, i32 poison), metadata !33, metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_LLVM_arg, 2, DW_OP_LLVM_arg, 3, DW_OP_plus, DW_OP_minus)), !dbg !19 +;; Check dbg.assign use before def (value, addr and ID). Check expression order too. +; CHECK: dbg.assign(metadata i32 %0, metadata ![[i:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 0), +; CHECK-SAME: metadata ![[ID:[0-9]+]], metadata ptr %a, metadata !DIExpression(DW_OP_plus_uconst, 1)), !dbg ![[dbg]] +; RECORDS: dbg_assign(i32 %0, ![[i:[0-9]+]], !DIExpression(DW_OP_plus_uconst, 0), +; RECORDS-SAME: ![[ID:[0-9]+]], ptr %a, !DIExpression(DW_OP_plus_uconst, 1), ![[dbg]]) + tail call void @llvm.dbg.assign(metadata i32 %0, metadata !36, metadata !DIExpression(DW_OP_plus_uconst, 0), metadata !37, metadata ptr %a, metadata !DIExpression(DW_OP_plus_uconst, 1)), !dbg !19 + %a = alloca i32, align 4, !DIAssignID !37 +; CHECK: %a = alloca i32, align 4, !DIAssignID ![[ID]] +;; Check dbg.declare configurations. +; CHECK-NEXT: dbg.declare(metadata ptr %a, metadata ![[a:[0-9]+]], metadata !DIExpression()), !dbg ![[dbg]] +; CHECK-NEXT: dbg.declare(metadata ![[empty:[0-9]+]], metadata ![[b:[0-9]+]], metadata !DIExpression()), !dbg ![[dbg]] +; CHECK-NEXT: dbg.declare(metadata ptr poison, metadata ![[c:[0-9]+]], metadata !DIExpression()), !dbg ![[dbg]] +; CHECK-NEXT: dbg.declare(metadata ptr null, metadata ![[d:[0-9]+]], metadata !DIExpression()), !dbg ![[dbg]] +; CHECK-NEXT: dbg.declare(metadata ptr @g, metadata ![[h:[0-9]+]], metadata !DIExpression()), !dbg ![[dbg]] +; RECORDS: %a = alloca i32, align 4, !DIAssignID ![[ID]] +;; Check dbg.declare configurations. +; RECORDS-NEXT: dbg_declare(ptr %a, ![[a:[0-9]+]], !DIExpression(), ![[dbg]]) +; RECORDS-NEXT: dbg_declare(![[empty:[0-9]+]], ![[b:[0-9]+]], !DIExpression(), ![[dbg]]) +; RECORDS-NEXT: dbg_declare(ptr poison, ![[c:[0-9]+]], !DIExpression(), ![[dbg]]) +; RECORDS-NEXT: dbg_declare(ptr null, ![[d:[0-9]+]], !DIExpression(), ![[dbg]]) +; RECORDS-NEXT: dbg_declare(ptr @g, ![[h:[0-9]+]], !DIExpression(), ![[dbg]]) + tail call void @llvm.dbg.declare(metadata ptr %a, metadata !17, metadata !DIExpression()), !dbg !19 + tail call void @llvm.dbg.declare(metadata !29, metadata !28, metadata !DIExpression()), !dbg !19 + tail call void @llvm.dbg.declare(metadata ptr poison, metadata !30, metadata !DIExpression()), !dbg !19 + tail call void @llvm.dbg.declare(metadata ptr null, metadata !31, metadata !DIExpression()), !dbg !19 + tail call void @llvm.dbg.declare(metadata ptr @g, metadata !35, metadata !DIExpression()), !dbg !19 +;; Argument value dbg.declare. +; CHECK: dbg.declare(metadata ptr %storage, metadata ![[g:[0-9]+]], metadata !DIExpression()), !dbg ![[dbg]] +; RECORDS: dbg_declare(ptr %storage, ![[g:[0-9]+]], !DIExpression(), ![[dbg]]) + tail call void @llvm.dbg.declare(metadata ptr %storage, metadata !34, metadata !DIExpression()), !dbg !19 +;; Use before def dbg.value. +; CHECK: dbg.value(metadata i32 %0, metadata ![[e]], metadata !DIExpression()), !dbg ![[dbg]] +; RECORDS: dbg_value(i32 %0, ![[e]], !DIExpression(), ![[dbg]]) + tail call void @llvm.dbg.value(metadata i32 %0, metadata !32, metadata !DIExpression()), !dbg !19 + %0 = load i32, ptr @g, align 4, !dbg !20 +;; Non-argument local value dbg.value. +; CHECK: dbg.value(metadata i32 %0, metadata ![[e]], metadata !DIExpression()), !dbg ![[dbg]] +; RECORDS: dbg_value(i32 %0, ![[e]], !DIExpression(), ![[dbg]]) + tail call void @llvm.dbg.value(metadata i32 %0, metadata !32, metadata !DIExpression()), !dbg !19 + store i32 %0, ptr %a, align 4, !dbg !19 + %1 = load i32, ptr %a, align 4, !dbg !25 +; CHECK: dbg.label(metadata ![[label:[0-9]+]]), !dbg ![[dbg]] +; RECORDS: dbg_label(![[label:[0-9]+]], ![[dbg]]) + tail call void @llvm.dbg.label(metadata !38), !dbg !19 + ret i32 %1, !dbg !27 +} + +; CHECK-DAG: ![[a]] = !DILocalVariable(name: "a", +; CHECK-DAG: ![[b]] = !DILocalVariable(name: "b", +; CHECK-DAG: ![[c]] = !DILocalVariable(name: "c", +; CHECK-DAG: ![[d]] = !DILocalVariable(name: "d", +; CHECK-DAG: ![[e]] = !DILocalVariable(name: "e", +; CHECK-DAG: ![[f]] = !DILocalVariable(name: "f", +; CHECK-DAG: ![[g]] = !DILocalVariable(name: "g", +; CHECK-DAG: ![[h]] = !DILocalVariable(name: "h", +; CHECK-DAG: ![[i]] = !DILocalVariable(name: "i", +; CHECK-DAG: ![[empty]] = !{} +; CHECK-DAG: ![[label]] = !DILabel + +declare void @llvm.dbg.declare(metadata, metadata, metadata) +declare void @llvm.dbg.value(metadata, metadata, metadata) +declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) +declare void @llvm.dbg.label(metadata) + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!6, !7, !8, !9, !10, !11} +!llvm.ident = !{!12} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 1, type: !5, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 19.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "test.cpp", directory: "/") +!4 = !{!0} +!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!6 = !{i32 7, !"Dwarf Version", i32 5} +!7 = !{i32 2, !"Debug Info Version", i32 3} +!8 = !{i32 1, !"wchar_size", i32 4} +!9 = !{i32 8, !"PIC Level", i32 2} +!10 = !{i32 7, !"PIE Level", i32 2} +!11 = !{i32 7, !"uwtable", i32 2} +!12 = !{!"clang version 19.0.0"} +!13 = distinct !DISubprogram(name: "fun", linkageName: "_Z3funv", scope: !3, file: !3, line: 2, type: !14, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !16) +!14 = !DISubroutineType(types: !15) +!15 = !{!5} +!16 = !{!17} +!17 = !DILocalVariable(name: "a", scope: !13, file: !3, line: 3, type: !5) +!18 = !DILocation(line: 3, column: 3, scope: !13) +!19 = !DILocation(line: 3, column: 7, scope: !13) +!20 = !DILocation(line: 3, column: 11, scope: !13) +!25 = !DILocation(line: 4, column: 12, scope: !13) +!26 = !DILocation(line: 5, column: 1, scope: !13) +!27 = !DILocation(line: 4, column: 5, scope: !13) +!28 = !DILocalVariable(name: "b", scope: !13, file: !3, line: 3, type: !5) +!29 = !{} +!30 = !DILocalVariable(name: "c", scope: !13, file: !3, line: 3, type: !5) +!31 = !DILocalVariable(name: "d", scope: !13, file: !3, line: 3, type: !5) +!32 = !DILocalVariable(name: "e", scope: !13, file: !3, line: 3, type: !5) +!33 = !DILocalVariable(name: "f", scope: !13, file: !3, line: 3, type: !5) +!34 = !DILocalVariable(name: "g", scope: !13, file: !3, line: 3, type: !5) +!35 = !DILocalVariable(name: "h", scope: !13, file: !3, line: 3, type: !5) +!36 = !DILocalVariable(name: "i", scope: !13, file: !3, line: 3, type: !5) +!37 = distinct !DIAssignID() +!38 = !DILabel(scope: !13, name: "label", file: !3, line: 1) diff --git a/llvm/test/Bitcode/flags.ll b/llvm/test/Bitcode/flags.ll index e3fc827d865d7e2adda715e37c84662cb2965682..96995ec570c9357e372492b4d6b0367eeb243ec2 100644 --- a/llvm/test/Bitcode/flags.ll +++ b/llvm/test/Bitcode/flags.ll @@ -20,17 +20,34 @@ second: ; preds = %first %ll = zext i32 %s to i64 %jj = or disjoint i32 %a, 0 %oo = or i32 %a, 0 + %tu = trunc nuw i32 %a to i16 + %ts = trunc nsw i32 %a to i16 + %tus = trunc nuw nsw i32 %a to i16 + %t = trunc i32 %a to i16 + %tuv = trunc nuw <2 x i32> %aa to <2 x i16> + %tsv = trunc nsw <2 x i32> %aa to <2 x i16> + %tusv = trunc nuw nsw <2 x i32> %aa to <2 x i16> + %tv = trunc <2 x i32> %aa to <2 x i16> unreachable -first: ; preds = %entry - %a = bitcast i32 0 to i32 ; <i32> [#uses=8] - %uu = add nuw i32 %a, 0 ; <i32> [#uses=0] - %ss = add nsw i32 %a, 0 ; <i32> [#uses=0] - %uuss = add nuw nsw i32 %a, 0 ; <i32> [#uses=0] - %zz = add i32 %a, 0 ; <i32> [#uses=0] +first: ; preds = %entry + %aa = bitcast <2 x i32> <i32 0, i32 0> to <2 x i32> + %a = bitcast i32 0 to i32 ; <i32> [#uses=8] + %uu = add nuw i32 %a, 0 ; <i32> [#uses=0] + %ss = add nsw i32 %a, 0 ; <i32> [#uses=0] + %uuss = add nuw nsw i32 %a, 0 ; <i32> [#uses=0] + %zz = add i32 %a, 0 ; <i32> [#uses=0] %kk = zext nneg i32 %a to i64 %rr = zext i32 %ss to i64 %mm = or disjoint i32 %a, 0 %nn = or i32 %a, 0 + %tuu = trunc nuw i32 %a to i16 + %tss = trunc nsw i32 %a to i16 + %tuss = trunc nuw nsw i32 %a to i16 + %tt = trunc i32 %a to i16 + %ttuv = trunc nuw <2 x i32> %aa to <2 x i16> + %ttsv = trunc nsw <2 x i32> %aa to <2 x i16> + %ttusv = trunc nuw nsw <2 x i32> %aa to <2 x i16> + %ttv = trunc <2 x i32> %aa to <2 x i16> br label %second } diff --git a/llvm/test/Bitcode/thinlto-func-summary-vtableref-pgo.ll b/llvm/test/Bitcode/thinlto-func-summary-vtableref-pgo.ll new file mode 100644 index 0000000000000000000000000000000000000000..ba3ce9a75ee83213804ae2eb2be3e79d96269d24 --- /dev/null +++ b/llvm/test/Bitcode/thinlto-func-summary-vtableref-pgo.ll @@ -0,0 +1,74 @@ +; Promote at most one function and annotate at most one vtable. +; As a result, only one value (of each relevant kind) shows up in the function +; summary. + +; RUN: opt -module-summary -icp-max-num-vtables=1 -icp-max-prom=1 %s -o %t.o + +; RUN: llvm-bcanalyzer -dump %t.o | FileCheck %s + +; RUN: llvm-dis -o - %t.o | FileCheck %s --check-prefix=DIS +; Round trip it through llvm-as +; RUN: llvm-dis -o - %t.o | llvm-as -o - | llvm-dis -o - | FileCheck %s --check-prefix=DIS + +; CHECK: <GLOBALVAL_SUMMARY_BLOCK +; CHECK-NEXT: <VERSION op0=9/> +; CHECK-NEXT: <FLAGS op0=0/> +; The `VALUE_GUID` below represents the "_ZTV4Base" referenced by the instruction +; that loads vtable pointers. +; CHECK-NEXT: <VALUE_GUID op0=21 op1=1960855528937986108/> +; The `VALUE_GUID` below represents the "_ZN4Base4funcEv" referenced by the +; indirect call instruction. +; CHECK-NEXT: <VALUE_GUID op0=20 op1=5459407273543877811/> +; NOTE vtables and functions from Derived class is dropped because +; `-icp-max-num-vtables` and `-icp-max-prom` are both set to one. +; <PERMODULE_PROFILE> has the format [valueid, flags, instcount, funcflags, +; numrefs, rorefcnt, worefcnt, +; m x valueid, +; n x (valueid, hotness+tailcall)] +; CHECK-NEXT: <PERMODULE_PROFILE abbrevid=4 op0=0 op1=0 op2=4 op3=256 op4=1 op5=1 op6=0 op7=21 op8=20 op9=3/> +; CHECK-NEXT: </GLOBALVAL_SUMMARY_BLOCK> + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; Function has one BB and an entry count of 150, so the BB is hot according to +; ProfileSummary and reflected so in the bitcode (see llvm-dis output). +define i32 @_Z4testP4Base(ptr %0) !prof !15 { + %2 = load ptr, ptr %0, !prof !16 + %3 = load ptr, ptr %2 + %4 = tail call i32 %3(ptr %0), !prof !17 + ret i32 %4 +} + +!llvm.module.flags = !{!1} + +!1 = !{i32 1, !"ProfileSummary", !2} +!2 = !{!3, !4, !5, !6, !7, !8, !9, !10} +!3 = !{!"ProfileFormat", !"InstrProf"} +!4 = !{!"TotalCount", i64 10000} +!5 = !{!"MaxCount", i64 200} +!6 = !{!"MaxInternalCount", i64 200} +!7 = !{!"MaxFunctionCount", i64 200} +!8 = !{!"NumCounts", i64 3} +!9 = !{!"NumFunctions", i64 3} +!10 = !{!"DetailedSummary", !11} +!11 = !{!12, !13, !14} +!12 = !{i32 10000, i64 100, i32 1} +!13 = !{i32 990000, i64 100, i32 1} +!14 = !{i32 999999, i64 1, i32 2} + +!15 = !{!"function_entry_count", i32 150} +; 1960855528937986108 is the MD5 hash of _ZTV4Base, and +; 13870436605473471591 is the MD5 hash of _ZTV7Derived +!16 = !{!"VP", i32 2, i64 150, i64 1960855528937986108, i64 100, i64 13870436605473471591, i64 50} +; 5459407273543877811 is the MD5 hash of _ZN4Base4funcEv, and +; 6174874150489409711 is the MD5 hash of _ZN7Derived4funcEv +!17 = !{!"VP", i32 0, i64 150, i64 5459407273543877811, i64 100, i64 6174874150489409711, i64 50} + +; ModuleSummaryIndex stores <guid, global-value summary> map in std::map; so +; global value summares are printed out in the order that gv's guid increases. +; DIS: ^0 = module: (path: "{{.*}}", hash: (0, 0, 0, 0, 0)) +; DIS: ^1 = gv: (guid: 1960855528937986108) +; DIS: ^2 = gv: (guid: 5459407273543877811) +; DIS: ^3 = gv: (name: "_Z4testP4Base", summaries: (function: (module: ^0, flags: (linkage: external, visibility: default, notEligibleToImport: 0, live: 0, dsoLocal: 0, canAutoHide: 0), insts: 4, funcFlags: (readNone: 0, readOnly: 0, noRecurse: 0, returnDoesNotAlias: 0, noInline: 0, alwaysInline: 0, noUnwind: 0, mayThrow: 0, hasUnknownCall: 1, mustBeUnreachable: 0), calls: ((callee: ^2, hotness: hot)), refs: (readonly ^1)))) ; guid = 15857150948103218965 +; DIS: ^4 = blockcount: 0 diff --git a/llvm/test/Bitcode/thinlto-function-summary.ll b/llvm/test/Bitcode/thinlto-function-summary.ll index 799759ebcac1ad43a4d1174e9fab593d16815aa1..13c6611843d651e340f1e9d6f1631947316646a6 100644 --- a/llvm/test/Bitcode/thinlto-function-summary.ll +++ b/llvm/test/Bitcode/thinlto-function-summary.ll @@ -13,9 +13,9 @@ ; "variadic" ; BC-NEXT: <FUNCTION op0=46 op1=8 ; "llvm.va_start" -; BC-NEXT: <FUNCTION op0=54 op1=13 +; BC-NEXT: <FUNCTION op0=54 op1=16 ; "f" -; BC-NEXT: <ALIAS op0=67 op1=1 +; BC-NEXT: <ALIAS op0=70 op1=1 ; BC: <GLOBALVAL_SUMMARY_BLOCK ; BC-NEXT: <VERSION ; BC-NEXT: <FLAGS @@ -26,7 +26,7 @@ ; BC-NEXT: <ALIAS {{.*}} op0=6 op1=0 op2=3 ; BC-NEXT: </GLOBALVAL_SUMMARY_BLOCK ; BC: <STRTAB_BLOCK -; BC-NEXT: blob data = 'hfoobaranon.{{................................}}.0variadicllvm.va_startf{{.*}}' +; BC-NEXT: blob data = 'hfoobaranon.{{................................}}.0variadicllvm.va_start.p{{[0-9]+}}f{{.*}}' ; RUN: opt -passes=name-anon-globals -module-summary < %s | llvm-dis | FileCheck %s diff --git a/llvm/test/Bitcode/upgrade-dbg-addr.ll b/llvm/test/Bitcode/upgrade-dbg-addr.ll index 40fd7db18948b5704842092020aff5420bf37c90..06a411c2c83486f34837011b9b9ea8fc21b1540c 100644 --- a/llvm/test/Bitcode/upgrade-dbg-addr.ll +++ b/llvm/test/Bitcode/upgrade-dbg-addr.ll @@ -1,6 +1,7 @@ ; Test upgrade of dbg.addr intrinsics into dbg.value with DW_OP_deref appended ; ; RUN: llvm-dis < %s.bc | FileCheck %s +; RUN: llvm-dis < %s.bc --load-bitcode-into-experimental-debuginfo-iterators --write-experimental-debuginfo=false | FileCheck %s ; RUN: verify-uselistorder < %s.bc define i32 @example(i32 %num) { diff --git a/llvm/test/Bitcode/variableArgumentIntrinsic.3.2.ll b/llvm/test/Bitcode/variableArgumentIntrinsic.3.2.ll index fad7b8ea6a58b9ff5558e8905d413048845a5c9d..fd3f500de7918c73ba20f644b22594b0e2d49235 100644 --- a/llvm/test/Bitcode/variableArgumentIntrinsic.3.2.ll +++ b/llvm/test/Bitcode/variableArgumentIntrinsic.3.2.ll @@ -10,7 +10,7 @@ define i32 @varArgIntrinsic(i32 %X, ...) { %ap = alloca i8* %ap2 = bitcast i8** %ap to i8* -; CHECK: call void @llvm.va_start(ptr %ap2) +; CHECK: call void @llvm.va_start.p0(ptr %ap2) call void @llvm.va_start(i8* %ap2) ; CHECK-NEXT: %tmp = va_arg ptr %ap, i32 @@ -19,12 +19,12 @@ define i32 @varArgIntrinsic(i32 %X, ...) { %aq = alloca i8* %aq2 = bitcast i8** %aq to i8* -; CHECK: call void @llvm.va_copy(ptr %aq2, ptr %ap2) +; CHECK: call void @llvm.va_copy.p0(ptr %aq2, ptr %ap2) call void @llvm.va_copy(i8* %aq2, i8* %ap2) -; CHECK-NEXT: call void @llvm.va_end(ptr %aq2) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr %aq2) call void @llvm.va_end(i8* %aq2) -; CHECK-NEXT: call void @llvm.va_end(ptr %ap2) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr %ap2) call void @llvm.va_end(i8* %ap2) ret i32 %tmp } diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-atomic.ll b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-atomic.ll index 458c2cb76d9e34729a203a5b00bd8ba01e7fdd99..7163da0dc02436fa7d94c0428c4294b98da864c0 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-atomic.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-atomic.ll @@ -512,9 +512,9 @@ define i32 @fetch_and_nand(ptr %p) #0 { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB6_2 ; CHECK-NOLSE-O0-NEXT: LBB6_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB6_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs w8, w9, w8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str w9, [sp, #28] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB6_1 ; CHECK-NOLSE-O0-NEXT: b LBB6_5 @@ -540,9 +540,9 @@ define i32 @fetch_and_nand(ptr %p) #0 { ; CHECK-OUTLINE-O0-NEXT: mvn w1, w8 ; CHECK-OUTLINE-O0-NEXT: bl ___aarch64_cas4_rel ; CHECK-OUTLINE-O0-NEXT: ldr w8, [sp, #8] ; 4-byte Folded Reload -; CHECK-OUTLINE-O0-NEXT: str w0, [sp, #12] ; 4-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: subs w8, w0, w8 ; CHECK-OUTLINE-O0-NEXT: cset w8, eq +; CHECK-OUTLINE-O0-NEXT: str w0, [sp, #12] ; 4-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: str w0, [sp, #28] ; 4-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: tbz w8, #0, LBB6_1 ; CHECK-OUTLINE-O0-NEXT: b LBB6_2 @@ -582,9 +582,9 @@ define i32 @fetch_and_nand(ptr %p) #0 { ; CHECK-LSE-O0-NEXT: mvn w10, w9 ; CHECK-LSE-O0-NEXT: mov x9, x8 ; CHECK-LSE-O0-NEXT: casl w9, w10, [x11] -; CHECK-LSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-LSE-O0-NEXT: subs w8, w9, w8 ; CHECK-LSE-O0-NEXT: cset w8, eq +; CHECK-LSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-LSE-O0-NEXT: str w9, [sp, #28] ; 4-byte Folded Spill ; CHECK-LSE-O0-NEXT: tbz w8, #0, LBB6_1 ; CHECK-LSE-O0-NEXT: b LBB6_2 @@ -649,9 +649,9 @@ define i64 @fetch_and_nand_64(ptr %p) #0 { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB7_2 ; CHECK-NOLSE-O0-NEXT: LBB7_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB7_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str x9, [sp, #8] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs x8, x9, x8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str x9, [sp, #8] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str x9, [sp, #24] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB7_1 ; CHECK-NOLSE-O0-NEXT: b LBB7_5 @@ -677,9 +677,9 @@ define i64 @fetch_and_nand_64(ptr %p) #0 { ; CHECK-OUTLINE-O0-NEXT: mvn x1, x8 ; CHECK-OUTLINE-O0-NEXT: bl ___aarch64_cas8_acq_rel ; CHECK-OUTLINE-O0-NEXT: ldr x8, [sp] ; 8-byte Folded Reload -; CHECK-OUTLINE-O0-NEXT: str x0, [sp, #8] ; 8-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: subs x8, x0, x8 ; CHECK-OUTLINE-O0-NEXT: cset w8, eq +; CHECK-OUTLINE-O0-NEXT: str x0, [sp, #8] ; 8-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: str x0, [sp, #24] ; 8-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: tbz w8, #0, LBB7_1 ; CHECK-OUTLINE-O0-NEXT: b LBB7_2 @@ -719,9 +719,9 @@ define i64 @fetch_and_nand_64(ptr %p) #0 { ; CHECK-LSE-O0-NEXT: mvn x10, x9 ; CHECK-LSE-O0-NEXT: mov x9, x8 ; CHECK-LSE-O0-NEXT: casal x9, x10, [x11] -; CHECK-LSE-O0-NEXT: str x9, [sp, #8] ; 8-byte Folded Spill ; CHECK-LSE-O0-NEXT: subs x8, x9, x8 ; CHECK-LSE-O0-NEXT: cset w8, eq +; CHECK-LSE-O0-NEXT: str x9, [sp, #8] ; 8-byte Folded Spill ; CHECK-LSE-O0-NEXT: str x9, [sp, #24] ; 8-byte Folded Spill ; CHECK-LSE-O0-NEXT: tbz w8, #0, LBB7_1 ; CHECK-LSE-O0-NEXT: b LBB7_2 @@ -782,9 +782,9 @@ define i32 @fetch_and_or(ptr %p) #0 { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB8_2 ; CHECK-NOLSE-O0-NEXT: LBB8_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB8_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs w8, w9, w8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str w9, [sp, #28] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB8_1 ; CHECK-NOLSE-O0-NEXT: b LBB8_5 @@ -855,9 +855,9 @@ define i64 @fetch_and_or_64(ptr %p) #0 { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB9_2 ; CHECK-NOLSE-O0-NEXT: LBB9_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB9_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str x9, [sp, #8] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs x8, x9, x8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str x9, [sp, #8] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str x9, [sp, #24] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB9_1 ; CHECK-NOLSE-O0-NEXT: b LBB9_5 @@ -4005,9 +4005,9 @@ define i32 @atomicrmw_add_i32(ptr %ptr, i32 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB47_2 ; CHECK-NOLSE-O0-NEXT: LBB47_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB47_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs w8, w9, w8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str w9, [sp, #28] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB47_1 ; CHECK-NOLSE-O0-NEXT: b LBB47_5 @@ -4097,9 +4097,9 @@ define i32 @atomicrmw_xchg_i32(ptr %ptr, i32 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB48_2 ; CHECK-NOLSE-O0-NEXT: LBB48_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB48_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs w8, w9, w8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str w9, [sp, #28] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB48_1 ; CHECK-NOLSE-O0-NEXT: b LBB48_5 @@ -4190,9 +4190,9 @@ define i32 @atomicrmw_sub_i32(ptr %ptr, i32 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB49_2 ; CHECK-NOLSE-O0-NEXT: LBB49_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB49_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs w8, w9, w8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str w9, [sp, #28] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB49_1 ; CHECK-NOLSE-O0-NEXT: b LBB49_5 @@ -4287,9 +4287,9 @@ define i32 @atomicrmw_and_i32(ptr %ptr, i32 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB50_2 ; CHECK-NOLSE-O0-NEXT: LBB50_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB50_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs w8, w9, w8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str w9, [sp, #28] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB50_1 ; CHECK-NOLSE-O0-NEXT: b LBB50_5 @@ -4384,9 +4384,9 @@ define i32 @atomicrmw_or_i32(ptr %ptr, i32 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB51_2 ; CHECK-NOLSE-O0-NEXT: LBB51_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB51_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs w8, w9, w8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str w9, [sp, #28] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB51_1 ; CHECK-NOLSE-O0-NEXT: b LBB51_5 @@ -4477,9 +4477,9 @@ define i32 @atomicrmw_xor_i32(ptr %ptr, i32 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB52_2 ; CHECK-NOLSE-O0-NEXT: LBB52_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB52_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs w8, w9, w8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str w9, [sp, #28] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB52_1 ; CHECK-NOLSE-O0-NEXT: b LBB52_5 @@ -4572,9 +4572,9 @@ define i32 @atomicrmw_min_i32(ptr %ptr, i32 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB53_2 ; CHECK-NOLSE-O0-NEXT: LBB53_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB53_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs w8, w9, w8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str w9, [sp, #28] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB53_1 ; CHECK-NOLSE-O0-NEXT: b LBB53_5 @@ -4605,9 +4605,9 @@ define i32 @atomicrmw_min_i32(ptr %ptr, i32 %rhs) { ; CHECK-OUTLINE-O0-NEXT: csel w1, w0, w8, le ; CHECK-OUTLINE-O0-NEXT: bl ___aarch64_cas4_acq ; CHECK-OUTLINE-O0-NEXT: ldr w8, [sp, #8] ; 4-byte Folded Reload -; CHECK-OUTLINE-O0-NEXT: str w0, [sp, #12] ; 4-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: subs w8, w0, w8 ; CHECK-OUTLINE-O0-NEXT: cset w8, eq +; CHECK-OUTLINE-O0-NEXT: str w0, [sp, #12] ; 4-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: str w0, [sp, #28] ; 4-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: tbz w8, #0, LBB53_1 ; CHECK-OUTLINE-O0-NEXT: b LBB53_2 @@ -4686,9 +4686,9 @@ define i32 @atomicrmw_max_i32(ptr %ptr, i32 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB54_2 ; CHECK-NOLSE-O0-NEXT: LBB54_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB54_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs w8, w9, w8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str w9, [sp, #28] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB54_1 ; CHECK-NOLSE-O0-NEXT: b LBB54_5 @@ -4719,9 +4719,9 @@ define i32 @atomicrmw_max_i32(ptr %ptr, i32 %rhs) { ; CHECK-OUTLINE-O0-NEXT: csel w1, w0, w8, gt ; CHECK-OUTLINE-O0-NEXT: bl ___aarch64_cas4_rel ; CHECK-OUTLINE-O0-NEXT: ldr w8, [sp, #8] ; 4-byte Folded Reload -; CHECK-OUTLINE-O0-NEXT: str w0, [sp, #12] ; 4-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: subs w8, w0, w8 ; CHECK-OUTLINE-O0-NEXT: cset w8, eq +; CHECK-OUTLINE-O0-NEXT: str w0, [sp, #12] ; 4-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: str w0, [sp, #28] ; 4-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: tbz w8, #0, LBB54_1 ; CHECK-OUTLINE-O0-NEXT: b LBB54_2 @@ -4800,9 +4800,9 @@ define i32 @atomicrmw_umin_i32(ptr %ptr, i32 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB55_2 ; CHECK-NOLSE-O0-NEXT: LBB55_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB55_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs w8, w9, w8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str w9, [sp, #28] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB55_1 ; CHECK-NOLSE-O0-NEXT: b LBB55_5 @@ -4833,9 +4833,9 @@ define i32 @atomicrmw_umin_i32(ptr %ptr, i32 %rhs) { ; CHECK-OUTLINE-O0-NEXT: csel w1, w0, w8, ls ; CHECK-OUTLINE-O0-NEXT: bl ___aarch64_cas4_acq_rel ; CHECK-OUTLINE-O0-NEXT: ldr w8, [sp, #8] ; 4-byte Folded Reload -; CHECK-OUTLINE-O0-NEXT: str w0, [sp, #12] ; 4-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: subs w8, w0, w8 ; CHECK-OUTLINE-O0-NEXT: cset w8, eq +; CHECK-OUTLINE-O0-NEXT: str w0, [sp, #12] ; 4-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: str w0, [sp, #28] ; 4-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: tbz w8, #0, LBB55_1 ; CHECK-OUTLINE-O0-NEXT: b LBB55_2 @@ -4914,9 +4914,9 @@ define i32 @atomicrmw_umax_i32(ptr %ptr, i32 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB56_2 ; CHECK-NOLSE-O0-NEXT: LBB56_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB56_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs w8, w9, w8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str w9, [sp, #12] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str w9, [sp, #28] ; 4-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB56_1 ; CHECK-NOLSE-O0-NEXT: b LBB56_5 @@ -4947,9 +4947,9 @@ define i32 @atomicrmw_umax_i32(ptr %ptr, i32 %rhs) { ; CHECK-OUTLINE-O0-NEXT: csel w1, w0, w8, hi ; CHECK-OUTLINE-O0-NEXT: bl ___aarch64_cas4_relax ; CHECK-OUTLINE-O0-NEXT: ldr w8, [sp, #8] ; 4-byte Folded Reload -; CHECK-OUTLINE-O0-NEXT: str w0, [sp, #12] ; 4-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: subs w8, w0, w8 ; CHECK-OUTLINE-O0-NEXT: cset w8, eq +; CHECK-OUTLINE-O0-NEXT: str w0, [sp, #12] ; 4-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: str w0, [sp, #28] ; 4-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: tbz w8, #0, LBB56_1 ; CHECK-OUTLINE-O0-NEXT: b LBB56_2 @@ -5026,9 +5026,9 @@ define i64 @atomicrmw_add_i64(ptr %ptr, i64 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB57_2 ; CHECK-NOLSE-O0-NEXT: LBB57_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB57_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs x8, x9, x8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str x9, [sp, #24] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB57_1 ; CHECK-NOLSE-O0-NEXT: b LBB57_5 @@ -5117,9 +5117,9 @@ define i64 @atomicrmw_xchg_i64(ptr %ptr, i64 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB58_2 ; CHECK-NOLSE-O0-NEXT: LBB58_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB58_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs x8, x9, x8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str x9, [sp, #24] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB58_1 ; CHECK-NOLSE-O0-NEXT: b LBB58_5 @@ -5210,9 +5210,9 @@ define i64 @atomicrmw_sub_i64(ptr %ptr, i64 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB59_2 ; CHECK-NOLSE-O0-NEXT: LBB59_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB59_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs x8, x9, x8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str x9, [sp, #24] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB59_1 ; CHECK-NOLSE-O0-NEXT: b LBB59_5 @@ -5307,9 +5307,9 @@ define i64 @atomicrmw_and_i64(ptr %ptr, i64 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB60_2 ; CHECK-NOLSE-O0-NEXT: LBB60_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB60_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs x8, x9, x8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str x9, [sp, #24] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB60_1 ; CHECK-NOLSE-O0-NEXT: b LBB60_5 @@ -5404,9 +5404,9 @@ define i64 @atomicrmw_or_i64(ptr %ptr, i64 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB61_2 ; CHECK-NOLSE-O0-NEXT: LBB61_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB61_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs x8, x9, x8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str x9, [sp, #24] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB61_1 ; CHECK-NOLSE-O0-NEXT: b LBB61_5 @@ -5497,9 +5497,9 @@ define i64 @atomicrmw_xor_i64(ptr %ptr, i64 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB62_2 ; CHECK-NOLSE-O0-NEXT: LBB62_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB62_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs x8, x9, x8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str x9, [sp, #24] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB62_1 ; CHECK-NOLSE-O0-NEXT: b LBB62_5 @@ -5592,9 +5592,9 @@ define i64 @atomicrmw_min_i64(ptr %ptr, i64 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB63_2 ; CHECK-NOLSE-O0-NEXT: LBB63_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB63_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs x8, x9, x8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str x9, [sp, #24] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB63_1 ; CHECK-NOLSE-O0-NEXT: b LBB63_5 @@ -5625,9 +5625,9 @@ define i64 @atomicrmw_min_i64(ptr %ptr, i64 %rhs) { ; CHECK-OUTLINE-O0-NEXT: csel x1, x0, x8, le ; CHECK-OUTLINE-O0-NEXT: bl ___aarch64_cas8_acq ; CHECK-OUTLINE-O0-NEXT: ldr x8, [sp, #8] ; 8-byte Folded Reload -; CHECK-OUTLINE-O0-NEXT: str x0, [sp, #16] ; 8-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: subs x8, x0, x8 ; CHECK-OUTLINE-O0-NEXT: cset w8, eq +; CHECK-OUTLINE-O0-NEXT: str x0, [sp, #16] ; 8-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: str x0, [sp, #40] ; 8-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: tbz w8, #0, LBB63_1 ; CHECK-OUTLINE-O0-NEXT: b LBB63_2 @@ -5706,9 +5706,9 @@ define i64 @atomicrmw_max_i64(ptr %ptr, i64 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB64_2 ; CHECK-NOLSE-O0-NEXT: LBB64_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB64_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs x8, x9, x8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str x9, [sp, #24] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB64_1 ; CHECK-NOLSE-O0-NEXT: b LBB64_5 @@ -5739,9 +5739,9 @@ define i64 @atomicrmw_max_i64(ptr %ptr, i64 %rhs) { ; CHECK-OUTLINE-O0-NEXT: csel x1, x0, x8, gt ; CHECK-OUTLINE-O0-NEXT: bl ___aarch64_cas8_rel ; CHECK-OUTLINE-O0-NEXT: ldr x8, [sp, #8] ; 8-byte Folded Reload -; CHECK-OUTLINE-O0-NEXT: str x0, [sp, #16] ; 8-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: subs x8, x0, x8 ; CHECK-OUTLINE-O0-NEXT: cset w8, eq +; CHECK-OUTLINE-O0-NEXT: str x0, [sp, #16] ; 8-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: str x0, [sp, #40] ; 8-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: tbz w8, #0, LBB64_1 ; CHECK-OUTLINE-O0-NEXT: b LBB64_2 @@ -5820,9 +5820,9 @@ define i64 @atomicrmw_umin_i64(ptr %ptr, i64 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB65_2 ; CHECK-NOLSE-O0-NEXT: LBB65_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB65_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs x8, x9, x8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str x9, [sp, #24] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB65_1 ; CHECK-NOLSE-O0-NEXT: b LBB65_5 @@ -5853,9 +5853,9 @@ define i64 @atomicrmw_umin_i64(ptr %ptr, i64 %rhs) { ; CHECK-OUTLINE-O0-NEXT: csel x1, x0, x8, ls ; CHECK-OUTLINE-O0-NEXT: bl ___aarch64_cas8_acq_rel ; CHECK-OUTLINE-O0-NEXT: ldr x8, [sp, #8] ; 8-byte Folded Reload -; CHECK-OUTLINE-O0-NEXT: str x0, [sp, #16] ; 8-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: subs x8, x0, x8 ; CHECK-OUTLINE-O0-NEXT: cset w8, eq +; CHECK-OUTLINE-O0-NEXT: str x0, [sp, #16] ; 8-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: str x0, [sp, #40] ; 8-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: tbz w8, #0, LBB65_1 ; CHECK-OUTLINE-O0-NEXT: b LBB65_2 @@ -5934,9 +5934,9 @@ define i64 @atomicrmw_umax_i64(ptr %ptr, i64 %rhs) { ; CHECK-NOLSE-O0-NEXT: cbnz w10, LBB66_2 ; CHECK-NOLSE-O0-NEXT: LBB66_4: ; %atomicrmw.start ; CHECK-NOLSE-O0-NEXT: ; in Loop: Header=BB66_1 Depth=1 -; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: subs x8, x9, x8 ; CHECK-NOLSE-O0-NEXT: cset w8, eq +; CHECK-NOLSE-O0-NEXT: str x9, [sp] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: str x9, [sp, #24] ; 8-byte Folded Spill ; CHECK-NOLSE-O0-NEXT: tbz w8, #0, LBB66_1 ; CHECK-NOLSE-O0-NEXT: b LBB66_5 @@ -5967,9 +5967,9 @@ define i64 @atomicrmw_umax_i64(ptr %ptr, i64 %rhs) { ; CHECK-OUTLINE-O0-NEXT: csel x1, x0, x8, hi ; CHECK-OUTLINE-O0-NEXT: bl ___aarch64_cas8_relax ; CHECK-OUTLINE-O0-NEXT: ldr x8, [sp, #8] ; 8-byte Folded Reload -; CHECK-OUTLINE-O0-NEXT: str x0, [sp, #16] ; 8-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: subs x8, x0, x8 ; CHECK-OUTLINE-O0-NEXT: cset w8, eq +; CHECK-OUTLINE-O0-NEXT: str x0, [sp, #16] ; 8-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: str x0, [sp, #40] ; 8-byte Folded Spill ; CHECK-OUTLINE-O0-NEXT: tbz w8, #0, LBB66_1 ; CHECK-OUTLINE-O0-NEXT: b LBB66_2 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-extract-vec-elt.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-extract-vec-elt.mir index a2116ccc7671120bbaa2342fcc456605d13190ab..c2a38e26676cf999c41e4fe62fd339b41c41c098 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-extract-vec-elt.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-extract-vec-elt.mir @@ -192,8 +192,8 @@ body: | ... --- +# This test checks that this combine runs after the insertvec->build_vector name: extract_from_insert -alignment: 4 tracksRegLiveness: true liveins: - { reg: '$x0' } @@ -203,8 +203,6 @@ frameInfo: body: | bb.1: liveins: $x0, $x1 - ; This test checks that this combine runs after the insertvec->build_vector - ; combine. ; CHECK-LABEL: name: extract_from_insert ; CHECK: liveins: $x0, $x1 ; CHECK-NEXT: {{ $}} @@ -247,3 +245,298 @@ body: | RET_ReallyLR implicit $x0 ... +--- +name: extract_from_vector_undef +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_from_vector_undef + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %extract:_(s64) = G_IMPLICIT_DEF + ; CHECK-NEXT: $x0 = COPY %extract(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %vec:_(<2 x s64>) = G_IMPLICIT_DEF + %idx:_(s32) = G_CONSTANT i32 -2 + %extract:_(s64) = G_EXTRACT_VECTOR_ELT %vec(<2 x s64>), %idx(s32) + $x0 = COPY %extract(s64) + RET_ReallyLR implicit $x0 + +... +--- +name: extract_from_index_undef +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + ; CHECK-LABEL: name: extract_from_index_undef + ; CHECK: %extract:_(s64) = G_IMPLICIT_DEF + ; CHECK-NEXT: $x0 = COPY %extract(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %vec:_(<2 x s64>) = COPY $q0 + %idx:_(s32) = G_IMPLICIT_DEF + %extract:_(s64) = G_EXTRACT_VECTOR_ELT %vec(<2 x s64>), %idx(s32) + $x0 = COPY %extract(s64) + RET_ReallyLR implicit $x0 + +... +--- +name: extract_from_index_too_large +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_from_index_too_large + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %extract:_(s64) = G_IMPLICIT_DEF + ; CHECK-NEXT: $x0 = COPY %extract(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %vec:_(<2 x s64>) = COPY $q0 + %idx:_(s32) = G_CONSTANT i32 3000 + %extract:_(s64) = G_EXTRACT_VECTOR_ELT %vec(<2 x s64>), %idx(s32) + $x0 = COPY %extract(s64) + RET_ReallyLR implicit $x0 + +... +--- +name: extract_with_freeze +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_with_freeze + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %vec:_(<2 x s64>) = COPY $q0 + ; CHECK-NEXT: %idx:_(s32) = COPY $w1 + ; CHECK-NEXT: [[EVEC:%[0-9]+]]:_(s64) = G_EXTRACT_VECTOR_ELT %vec(<2 x s64>), %idx(s32) + ; CHECK-NEXT: %extract:_(s64) = G_FREEZE [[EVEC]] + ; CHECK-NEXT: $x0 = COPY %extract(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %vec:_(<2 x s64>) = COPY $q0 + %idx:_(s32) = COPY $w1 + %fvec:_(<2 x s64>) = G_FREEZE %vec + %extract:_(s64) = G_EXTRACT_VECTOR_ELT %fvec(<2 x s64>), %idx(s32) + $x0 = COPY %extract(s64) + RET_ReallyLR implicit $x0 + +... +--- +name: extract_from_insert_symmetry +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_from_insert_symmetry + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %element:_(s64) = COPY $x1 + ; CHECK-NEXT: $x0 = COPY %element(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %vec:_(<2 x s64>) = COPY $q0 + %idx:_(s32) = COPY $w1 + %element:_(s64) = COPY $x1 + %invec:_(<2 x s64>) = G_INSERT_VECTOR_ELT %vec(<2 x s64>), %element(s64), %idx(s32) + %extract:_(s64) = G_EXTRACT_VECTOR_ELT %invec(<2 x s64>), %idx(s32) + $x0 = COPY %extract(s64) + RET_ReallyLR implicit $x0 + +... +--- +name: extract_from_insert_with_different_consts +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_from_insert_with_different_consts + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %vec:_(<2 x s64>) = COPY $q0 + ; CHECK-NEXT: %idx2:_(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: %extract:_(s64) = G_EXTRACT_VECTOR_ELT %vec(<2 x s64>), %idx2(s32) + ; CHECK-NEXT: $x0 = COPY %extract(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %vec:_(<2 x s64>) = COPY $q0 + %idx:_(s32) = G_CONSTANT i32 0 + %idx2:_(s32) = G_CONSTANT i32 1 + %element:_(s64) = COPY $x1 + %invec:_(<2 x s64>) = G_INSERT_VECTOR_ELT %vec(<2 x s64>), %element(s64), %idx(s32) + %extract:_(s64) = G_EXTRACT_VECTOR_ELT %invec(<2 x s64>), %idx2(s32) + $x0 = COPY %extract(s64) + RET_ReallyLR implicit $x0 + +... +--- +name: extract_from_build_vector_non_const +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_from_build_vector_non_const + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %idx:_(s32) = COPY $w0 + ; CHECK-NEXT: %arg1:_(s64) = COPY $x0 + ; CHECK-NEXT: %arg2:_(s64) = COPY $x1 + ; CHECK-NEXT: %bv:_(<2 x s64>) = G_BUILD_VECTOR %arg1(s64), %arg2(s64) + ; CHECK-NEXT: %extract:_(s64) = G_EXTRACT_VECTOR_ELT %bv(<2 x s64>), %idx(s32) + ; CHECK-NEXT: $x0 = COPY %extract(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %vec:_(<2 x s64>) = COPY $q0 + %idx:_(s32) = COPY $w0 + %arg1:_(s64) = COPY $x0 + %arg2:_(s64) = COPY $x1 + %bv:_(<2 x s64>) = G_BUILD_VECTOR %arg1(s64), %arg2(s64) + %extract:_(s64) = G_EXTRACT_VECTOR_ELT %bv(<2 x s64>), %idx(s32) + $x0 = COPY %extract(s64) + RET_ReallyLR implicit $x0 + +... +--- +name: extract_from_build_vector_const +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_from_build_vector_const + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %arg1:_(s64) = COPY $x0 + ; CHECK-NEXT: $x0 = COPY %arg1(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %vec:_(<2 x s64>) = COPY $q0 + %idx:_(s32) = G_CONSTANT i32 0 + %arg1:_(s64) = COPY $x0 + %arg2:_(s64) = COPY $x1 + %bv:_(<2 x s64>) = G_BUILD_VECTOR %arg1(s64), %arg2(s64) + %extract:_(s64) = G_EXTRACT_VECTOR_ELT %bv(<2 x s64>), %idx(s32) + $x0 = COPY %extract(s64) + RET_ReallyLR implicit $x0 + +... +--- +name: extract_from_build_vector_trunc_const2 +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_from_build_vector_trunc_const2 + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %arg1:_(s64) = COPY $x0 + ; CHECK-NEXT: %extract:_(s32) = G_TRUNC %arg1(s64) + ; CHECK-NEXT: $w0 = COPY %extract(s32) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %vec:_(<2 x s64>) = COPY $q0 + %arg1:_(s64) = COPY $x0 + %arg2:_(s64) = COPY $x1 + %arg3:_(s64) = COPY $x0 + %arg4:_(s64) = COPY $x1 + %idx:_(s32) = G_CONSTANT i32 0 + %bv:_(<4 x s32>) = G_BUILD_VECTOR_TRUNC %arg1(s64), %arg2(s64), %arg3(s64), %arg4(s64) + %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<4 x s32>), %idx(s32) + $w0 = COPY %extract(s32) + RET_ReallyLR implicit $x0 +... +--- +name: extract_from_build_vector_trunc2 +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_from_build_vector_trunc2 + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %arg1:_(s64) = COPY $x0 + ; CHECK-NEXT: %arg2:_(s64) = COPY $x1 + ; CHECK-NEXT: %idx:_(s32) = COPY $w0 + ; CHECK-NEXT: %bv:_(<2 x s32>) = G_BUILD_VECTOR_TRUNC %arg1(s64), %arg2(s64) + ; CHECK-NEXT: %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %idx(s32) + ; CHECK-NEXT: $w0 = COPY %extract(s32) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %arg1:_(s64) = COPY $x0 + %arg2:_(s64) = COPY $x1 + %idx:_(s32) = COPY $w0 + %bv:_(<2 x s32>) = G_BUILD_VECTOR_TRUNC %arg1(s64), %arg2(s64) + %extract:_(s32) = G_EXTRACT_VECTOR_ELT %bv(<2 x s32>), %idx(s32) + $w0 = COPY %extract(s32) + RET_ReallyLR implicit $x0 +... +--- +name: extract_from_build_vector_trunc_const3 +alignment: 4 +liveins: + - { reg: '$x0' } + - { reg: '$x1' } +frameInfo: + maxAlignment: 1 +body: | + bb.1: + liveins: $x0, $x1 + ; CHECK-LABEL: name: extract_from_build_vector_trunc_const3 + ; CHECK: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %arg1:_(s128) = COPY $q0 + ; CHECK-NEXT: %extract:_(s64) = G_TRUNC %arg1(s128) + ; CHECK-NEXT: $x0 = COPY %extract(s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 + %arg1:_(s128) = COPY $q0 + %arg2:_(s128) = COPY $q1 + %idx:_(s32) = G_CONSTANT i32 0 + %bv:_(<2 x s64>) = G_BUILD_VECTOR_TRUNC %arg1(s128), %arg2(s128) + %extract:_(s64) = G_EXTRACT_VECTOR_ELT %bv(<2 x s64>), %idx(s32) + $x0 = COPY %extract(s64) + RET_ReallyLR implicit $x0 +... +--- diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-overflow.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-overflow.mir new file mode 100644 index 0000000000000000000000000000000000000000..ec66892b98fc7d3975cb231f9086298134c55655 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-overflow.mir @@ -0,0 +1,178 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -run-pass=aarch64-prelegalizer-combiner -mtriple aarch64-unknown-unknown %s -o - | FileCheck %s + +--- +name: add_unused +body: | + bb.0: + liveins: $w0, $w1 + ; CHECK-LABEL: name: add_unused + ; CHECK: liveins: $w0, $w1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1 + ; CHECK-NEXT: %add:_(s32) = G_ADD [[COPY]], [[COPY1]] + ; CHECK-NEXT: $w0 = COPY %add(s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 + %0:_(s32) = COPY $w0 + %1:_(s32) = COPY $w1 + %add:_(s32), %o:_(s1) = G_SADDO %0, %1 + $w0 = COPY %add(s32) + RET_ReallyLR implicit $w0 +... +--- +name: add_canon +body: | + bb.0: + liveins: $w0, $w1 + ; CHECK-LABEL: name: add_canon + ; CHECK: liveins: $w0, $w1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w1 + ; CHECK-NEXT: %const:_(s32) = G_CONSTANT i32 10 + ; CHECK-NEXT: %add:_(s32), %o:_(s1) = G_SADDO [[COPY]], %const + ; CHECK-NEXT: %o_wide:_(s32) = G_ZEXT %o(s1) + ; CHECK-NEXT: $w0 = COPY %add(s32) + ; CHECK-NEXT: $w1 = COPY %o_wide(s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 + %0:_(s32) = COPY $w0 + %1:_(s32) = COPY $w1 + %const:_(s32) = G_CONSTANT i32 10 + %add:_(s32), %o:_(s1) = G_SADDO %const, %1 + %o_wide:_(s32) = G_ZEXT %o(s1) + $w0 = COPY %add(s32) + $w1 = COPY %o_wide + RET_ReallyLR implicit $w0 +... +--- +name: add_const_fold +body: | + bb.0: + liveins: $w0, $w1 + ; CHECK-LABEL: name: add_const_fold + ; CHECK: liveins: $w0, $w1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: %add:_(s32) = G_CONSTANT i32 21 + ; CHECK-NEXT: %o_wide:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: $w0 = COPY %add(s32) + ; CHECK-NEXT: $w1 = COPY %o_wide(s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 + %0:_(s32) = COPY $w0 + %1:_(s32) = COPY $w1 + %const:_(s32) = G_CONSTANT i32 10 + %const1:_(s32) = G_CONSTANT i32 11 + %add:_(s32), %o:_(s1) = G_UADDO %const, %const1 + %o_wide:_(s32) = G_ZEXT %o(s1) + $w0 = COPY %add(s32) + $w1 = COPY %o_wide + RET_ReallyLR implicit $w0 +... +--- +name: add_add_zero +body: | + bb.0: + liveins: $w0, $w1 + ; CHECK-LABEL: name: add_add_zero + ; CHECK: liveins: $w0, $w1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w2 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: $w0 = COPY [[COPY]](s32) + ; CHECK-NEXT: $w1 = COPY [[C]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 + %0:_(s32) = COPY $w0 + %1:_(s32) = COPY $w1 + %2:_(s32) = COPY $w2 + %const:_(s32) = G_CONSTANT i32 10 + %addl:_(s32) = nsw G_ADD %2, %const + %const1:_(s32) = G_CONSTANT i32 -10 + %add:_(s32), %o:_(s1) = G_SADDO %addl, %const1 + %o_wide:_(s32) = G_ZEXT %o(s1) + $w0 = COPY %add(s32) + $w1 = COPY %o_wide + RET_ReallyLR implicit $w0 +... +--- +name: add_multiuse +body: | + bb.0: + liveins: $w0, $w1 + ; CHECK-LABEL: name: add_multiuse + ; CHECK: liveins: $w0, $w1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 + ; CHECK-NEXT: %const:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: $w0 = COPY [[COPY]](s32) + ; CHECK-NEXT: $w1 = COPY [[COPY]](s32) + ; CHECK-NEXT: $w2 = COPY %const(s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 + %0:_(s32) = COPY $w0 + %const:_(s32) = G_CONSTANT i32 0 + %add:_(s32), %o:_(s1) = G_SADDO %0, %const + %o_wide:_(s32) = G_ZEXT %o(s1) + $w0 = COPY %add(s32) + $w1 = COPY %add(s32) + $w2 = COPY %o_wide + RET_ReallyLR implicit $w0 +... +--- +name: add_vector +body: | + bb.0: + liveins: $w0, $w1 + ; CHECK-LABEL: name: add_vector + ; CHECK: liveins: $w0, $w1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1 + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2 + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $w3 + ; CHECK-NEXT: %bv0:_(<4 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[COPY1]](s32), [[COPY]](s32), [[COPY1]](s32) + ; CHECK-NEXT: %bv1:_(<4 x s32>) = G_BUILD_VECTOR [[COPY2]](s32), [[COPY3]](s32), [[COPY2]](s32), [[COPY3]](s32) + ; CHECK-NEXT: %add:_(<4 x s32>), %o:_(<4 x s1>) = G_UADDO %bv0, %bv1 + ; CHECK-NEXT: %o_wide:_(<4 x s32>) = G_ZEXT %o(<4 x s1>) + ; CHECK-NEXT: $q0 = COPY %add(<4 x s32>) + ; CHECK-NEXT: $q1 = COPY %o_wide(<4 x s32>) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 + %0:_(s32) = COPY $w0 + %1:_(s32) = COPY $w1 + %2:_(s32) = COPY $w2 + %3:_(s32) = COPY $w3 + %bv0:_(<4 x s32>) = G_BUILD_VECTOR %0:_(s32), %1:_(s32), %0:_(s32), %1:_(s32) + %bv1:_(<4 x s32>) = G_BUILD_VECTOR %2:_(s32), %3:_(s32), %2:_(s32), %3:_(s32) + %add:_(<4 x s32>), %o:_(<4 x s1>) = G_UADDO %bv0, %bv1 + %o_wide:_(<4 x s32>) = G_ZEXT %o(<4 x s1>) + $q0 = COPY %add(<4 x s32>) + $q1 = COPY %o_wide + RET_ReallyLR implicit $w0 +... +--- +name: add_splat_vector +body: | + bb.0: + liveins: $w0, $w1 + ; CHECK-LABEL: name: add_splat_vector + ; CHECK: liveins: $w0, $w1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1 + ; CHECK-NEXT: %bv0:_(<4 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[COPY1]](s32), [[COPY]](s32), [[COPY1]](s32) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s1) = G_CONSTANT i1 false + ; CHECK-NEXT: %o:_(<4 x s1>) = G_BUILD_VECTOR [[C]](s1), [[C]](s1), [[C]](s1), [[C]](s1) + ; CHECK-NEXT: %o_wide:_(<4 x s32>) = G_ZEXT %o(<4 x s1>) + ; CHECK-NEXT: $q0 = COPY %bv0(<4 x s32>) + ; CHECK-NEXT: $q1 = COPY %o_wide(<4 x s32>) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 + %0:_(s32) = COPY $w0 + %1:_(s32) = COPY $w1 + %2:_(s32) = COPY $w2 + %3:_(s32) = COPY $w3 + %const:_(s32) = G_CONSTANT i32 0 + %bv0:_(<4 x s32>) = G_BUILD_VECTOR %0:_(s32), %1:_(s32), %0:_(s32), %1:_(s32) + %bv1:_(<4 x s32>) = G_BUILD_VECTOR %const:_(s32), %const:_(s32), %const:_(s32), %const:_(s32) + %add:_(<4 x s32>), %o:_(<4 x s1>) = G_SADDO %bv0, %bv1 + %o_wide:_(<4 x s32>) = G_ZEXT %o(<4 x s1>) + $q0 = COPY %add(<4 x s32>) + $q1 = COPY %o_wide + RET_ReallyLR implicit $w0 +... diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-udiv.ll b/llvm/test/CodeGen/AArch64/GlobalISel/combine-udiv.ll index 8aea944b55c2d0b3c3a42d1cd43fee02484ef95a..ceef0c49a45ec758db3896b54476be7d5477233d 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-udiv.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-udiv.ll @@ -65,22 +65,17 @@ define <8 x i16> @combine_vec_udiv_nonuniform(<8 x i16> %x) { ; GISEL-NEXT: ushl v1.8h, v0.8h, v1.8h ; GISEL-NEXT: umull2 v3.4s, v1.8h, v2.8h ; GISEL-NEXT: umull v1.4s, v1.4h, v2.4h -; GISEL-NEXT: uzp2 v1.8h, v1.8h, v3.8h -; GISEL-NEXT: ldr q3, [x8, :lo12:.LCPI1_1] +; GISEL-NEXT: ldr q2, [x8, :lo12:.LCPI1_1] ; GISEL-NEXT: adrp x8, .LCPI1_0 -; GISEL-NEXT: sub v2.8h, v0.8h, v1.8h -; GISEL-NEXT: umull2 v4.4s, v2.8h, v3.8h -; GISEL-NEXT: umull v2.4s, v2.4h, v3.4h -; GISEL-NEXT: ldr q3, [x8, :lo12:.LCPI1_0] -; GISEL-NEXT: adrp x8, .LCPI1_4 -; GISEL-NEXT: uzp2 v2.8h, v2.8h, v4.8h -; GISEL-NEXT: ldr q4, [x8, :lo12:.LCPI1_4] -; GISEL-NEXT: add v1.8h, v2.8h, v1.8h -; GISEL-NEXT: neg v2.8h, v3.8h -; GISEL-NEXT: movi v3.8h, #1 -; GISEL-NEXT: ushl v1.8h, v1.8h, v2.8h -; GISEL-NEXT: cmeq v2.8h, v4.8h, v3.8h -; GISEL-NEXT: bif v0.16b, v1.16b, v2.16b +; GISEL-NEXT: uzp2 v1.8h, v1.8h, v3.8h +; GISEL-NEXT: sub v0.8h, v0.8h, v1.8h +; GISEL-NEXT: umull2 v3.4s, v0.8h, v2.8h +; GISEL-NEXT: umull v0.4s, v0.4h, v2.4h +; GISEL-NEXT: ldr q2, [x8, :lo12:.LCPI1_0] +; GISEL-NEXT: uzp2 v0.8h, v0.8h, v3.8h +; GISEL-NEXT: add v0.8h, v0.8h, v1.8h +; GISEL-NEXT: neg v1.8h, v2.8h +; GISEL-NEXT: ushl v0.8h, v0.8h, v1.8h ; GISEL-NEXT: ret %1 = udiv <8 x i16> %x, <i16 23, i16 34, i16 -23, i16 56, i16 128, i16 -1, i16 -256, i16 -32768> ret <8 x i16> %1 @@ -107,21 +102,16 @@ define <8 x i16> @combine_vec_udiv_nonuniform2(<8 x i16> %x) { ; GISEL-NEXT: adrp x8, .LCPI2_2 ; GISEL-NEXT: ldr q1, [x8, :lo12:.LCPI2_2] ; GISEL-NEXT: adrp x8, .LCPI2_1 -; GISEL-NEXT: ldr q2, [x8, :lo12:.LCPI2_1] +; GISEL-NEXT: neg v1.8h, v1.8h +; GISEL-NEXT: ushl v0.8h, v0.8h, v1.8h +; GISEL-NEXT: ldr q1, [x8, :lo12:.LCPI2_1] ; GISEL-NEXT: adrp x8, .LCPI2_0 +; GISEL-NEXT: umull2 v2.4s, v0.8h, v1.8h +; GISEL-NEXT: umull v0.4s, v0.4h, v1.4h +; GISEL-NEXT: ldr q1, [x8, :lo12:.LCPI2_0] ; GISEL-NEXT: neg v1.8h, v1.8h -; GISEL-NEXT: ushl v1.8h, v0.8h, v1.8h -; GISEL-NEXT: umull2 v3.4s, v1.8h, v2.8h -; GISEL-NEXT: umull v1.4s, v1.4h, v2.4h -; GISEL-NEXT: ldr q2, [x8, :lo12:.LCPI2_0] -; GISEL-NEXT: adrp x8, .LCPI2_3 -; GISEL-NEXT: neg v2.8h, v2.8h -; GISEL-NEXT: ldr q4, [x8, :lo12:.LCPI2_3] -; GISEL-NEXT: uzp2 v1.8h, v1.8h, v3.8h -; GISEL-NEXT: movi v3.8h, #1 -; GISEL-NEXT: ushl v1.8h, v1.8h, v2.8h -; GISEL-NEXT: cmeq v2.8h, v4.8h, v3.8h -; GISEL-NEXT: bif v0.16b, v1.16b, v2.16b +; GISEL-NEXT: uzp2 v0.8h, v0.8h, v2.8h +; GISEL-NEXT: ushl v0.8h, v0.8h, v1.8h ; GISEL-NEXT: ret %1 = udiv <8 x i16> %x, <i16 -34, i16 35, i16 36, i16 -37, i16 38, i16 -39, i16 40, i16 -41> ret <8 x i16> %1 @@ -145,21 +135,16 @@ define <8 x i16> @combine_vec_udiv_nonuniform3(<8 x i16> %x) { ; GISEL-LABEL: combine_vec_udiv_nonuniform3: ; GISEL: // %bb.0: ; GISEL-NEXT: adrp x8, .LCPI3_1 -; GISEL-NEXT: movi v3.8h, #1 ; GISEL-NEXT: ldr q1, [x8, :lo12:.LCPI3_1] ; GISEL-NEXT: adrp x8, .LCPI3_0 ; GISEL-NEXT: umull2 v2.4s, v0.8h, v1.8h ; GISEL-NEXT: umull v1.4s, v0.4h, v1.4h ; GISEL-NEXT: uzp2 v1.8h, v1.8h, v2.8h -; GISEL-NEXT: sub v2.8h, v0.8h, v1.8h -; GISEL-NEXT: usra v1.8h, v2.8h, #1 -; GISEL-NEXT: ldr q2, [x8, :lo12:.LCPI3_0] -; GISEL-NEXT: adrp x8, .LCPI3_2 -; GISEL-NEXT: ldr q4, [x8, :lo12:.LCPI3_2] -; GISEL-NEXT: neg v2.8h, v2.8h -; GISEL-NEXT: ushl v1.8h, v1.8h, v2.8h -; GISEL-NEXT: cmeq v2.8h, v4.8h, v3.8h -; GISEL-NEXT: bif v0.16b, v1.16b, v2.16b +; GISEL-NEXT: sub v0.8h, v0.8h, v1.8h +; GISEL-NEXT: usra v1.8h, v0.8h, #1 +; GISEL-NEXT: ldr q0, [x8, :lo12:.LCPI3_0] +; GISEL-NEXT: neg v0.8h, v0.8h +; GISEL-NEXT: ushl v0.8h, v1.8h, v0.8h ; GISEL-NEXT: ret %1 = udiv <8 x i16> %x, <i16 7, i16 23, i16 25, i16 27, i16 31, i16 47, i16 63, i16 127> ret <8 x i16> %1 @@ -184,19 +169,19 @@ define <16 x i8> @combine_vec_udiv_nonuniform4(<16 x i8> %x) { ; ; GISEL-LABEL: combine_vec_udiv_nonuniform4: ; GISEL: // %bb.0: +; GISEL-NEXT: adrp x8, .LCPI4_2 +; GISEL-NEXT: ldr q1, [x8, :lo12:.LCPI4_2] ; GISEL-NEXT: adrp x8, .LCPI4_1 -; GISEL-NEXT: ldr q1, [x8, :lo12:.LCPI4_1] +; GISEL-NEXT: ldr q3, [x8, :lo12:.LCPI4_1] ; GISEL-NEXT: adrp x8, .LCPI4_0 -; GISEL-NEXT: ldr q3, [x8, :lo12:.LCPI4_0] -; GISEL-NEXT: adrp x8, .LCPI4_2 ; GISEL-NEXT: umull2 v2.8h, v0.16b, v1.16b ; GISEL-NEXT: umull v1.8h, v0.8b, v1.8b -; GISEL-NEXT: ldr q4, [x8, :lo12:.LCPI4_2] +; GISEL-NEXT: ldr q4, [x8, :lo12:.LCPI4_0] ; GISEL-NEXT: uzp2 v1.16b, v1.16b, v2.16b ; GISEL-NEXT: neg v2.16b, v3.16b -; GISEL-NEXT: movi v3.16b, #1 +; GISEL-NEXT: shl v3.16b, v4.16b, #7 ; GISEL-NEXT: ushl v1.16b, v1.16b, v2.16b -; GISEL-NEXT: cmeq v2.16b, v4.16b, v3.16b +; GISEL-NEXT: sshr v2.16b, v3.16b, #7 ; GISEL-NEXT: bif v0.16b, v1.16b, v2.16b ; GISEL-NEXT: ret %div = udiv <16 x i8> %x, <i8 -64, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> @@ -232,10 +217,10 @@ define <8 x i16> @pr38477(<8 x i16> %a0) { ; ; GISEL-LABEL: pr38477: ; GISEL: // %bb.0: +; GISEL-NEXT: adrp x8, .LCPI5_3 +; GISEL-NEXT: ldr q1, [x8, :lo12:.LCPI5_3] ; GISEL-NEXT: adrp x8, .LCPI5_2 -; GISEL-NEXT: ldr q1, [x8, :lo12:.LCPI5_2] -; GISEL-NEXT: adrp x8, .LCPI5_1 -; GISEL-NEXT: ldr q3, [x8, :lo12:.LCPI5_1] +; GISEL-NEXT: ldr q3, [x8, :lo12:.LCPI5_2] ; GISEL-NEXT: adrp x8, .LCPI5_0 ; GISEL-NEXT: umull2 v2.4s, v0.8h, v1.8h ; GISEL-NEXT: umull v1.4s, v0.4h, v1.4h @@ -243,15 +228,16 @@ define <8 x i16> @pr38477(<8 x i16> %a0) { ; GISEL-NEXT: sub v2.8h, v0.8h, v1.8h ; GISEL-NEXT: umull2 v4.4s, v2.8h, v3.8h ; GISEL-NEXT: umull v2.4s, v2.4h, v3.4h -; GISEL-NEXT: ldr q3, [x8, :lo12:.LCPI5_0] -; GISEL-NEXT: adrp x8, .LCPI5_3 +; GISEL-NEXT: ldr d3, [x8, :lo12:.LCPI5_0] +; GISEL-NEXT: adrp x8, .LCPI5_1 +; GISEL-NEXT: ushll v3.8h, v3.8b, #0 ; GISEL-NEXT: uzp2 v2.8h, v2.8h, v4.8h -; GISEL-NEXT: ldr q4, [x8, :lo12:.LCPI5_3] +; GISEL-NEXT: ldr q4, [x8, :lo12:.LCPI5_1] +; GISEL-NEXT: shl v3.8h, v3.8h, #15 ; GISEL-NEXT: add v1.8h, v2.8h, v1.8h -; GISEL-NEXT: neg v2.8h, v3.8h -; GISEL-NEXT: movi v3.8h, #1 +; GISEL-NEXT: neg v2.8h, v4.8h ; GISEL-NEXT: ushl v1.8h, v1.8h, v2.8h -; GISEL-NEXT: cmeq v2.8h, v4.8h, v3.8h +; GISEL-NEXT: sshr v2.8h, v3.8h, #15 ; GISEL-NEXT: bif v0.16b, v1.16b, v2.16b ; GISEL-NEXT: ret %1 = udiv <8 x i16> %a0, <i16 1, i16 119, i16 73, i16 -111, i16 -3, i16 118, i16 32, i16 31> diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-udiv.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-udiv.mir index ee33b9c50cbea7173ec6095e358e5f590c7ddd77..02233b9f498bd84529daed0b0518c32f61c3b93b 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-udiv.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-udiv.mir @@ -6,7 +6,9 @@ body: | bb.1: liveins: $w0 ; CHECK-LABEL: name: udiv_by_scalar_const - ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 + ; CHECK: liveins: $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 818089009 ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 @@ -68,44 +70,32 @@ body: | ; CHECK: liveins: $q0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<8 x s16>) = COPY $q0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 23 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s16) = G_CONSTANT i16 34 - ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s16) = G_CONSTANT i16 -23 - ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s16) = G_CONSTANT i16 56 - ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s16) = G_CONSTANT i16 128 - ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s16) = G_CONSTANT i16 -1 - ; CHECK-NEXT: [[C6:%[0-9]+]]:_(s16) = G_CONSTANT i16 -256 - ; CHECK-NEXT: [[C7:%[0-9]+]]:_(s16) = G_CONSTANT i16 -32768 - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C]](s16), [[C1]](s16), [[C2]](s16), [[C3]](s16), [[C4]](s16), [[C5]](s16), [[C6]](s16), [[C7]](s16) - ; CHECK-NEXT: [[C8:%[0-9]+]]:_(s16) = G_CONSTANT i16 0 - ; CHECK-NEXT: [[C9:%[0-9]+]]:_(s16) = G_CONSTANT i16 25645 - ; CHECK-NEXT: [[C10:%[0-9]+]]:_(s16) = G_CONSTANT i16 4 - ; CHECK-NEXT: [[C11:%[0-9]+]]:_(s16) = G_CONSTANT i16 -3855 - ; CHECK-NEXT: [[C12:%[0-9]+]]:_(s16) = G_CONSTANT i16 5 - ; CHECK-NEXT: [[C13:%[0-9]+]]:_(s16) = G_CONSTANT i16 8195 - ; CHECK-NEXT: [[C14:%[0-9]+]]:_(s16) = G_CONSTANT i16 13 - ; CHECK-NEXT: [[C15:%[0-9]+]]:_(s16) = G_CONSTANT i16 3 - ; CHECK-NEXT: [[C16:%[0-9]+]]:_(s16) = G_CONSTANT i16 9363 - ; CHECK-NEXT: [[C17:%[0-9]+]]:_(s16) = G_CONSTANT i16 512 - ; CHECK-NEXT: [[C18:%[0-9]+]]:_(s16) = G_CONSTANT i16 -32767 - ; CHECK-NEXT: [[C19:%[0-9]+]]:_(s16) = G_CONSTANT i16 15 - ; CHECK-NEXT: [[C20:%[0-9]+]]:_(s16) = G_CONSTANT i16 -32639 - ; CHECK-NEXT: [[C21:%[0-9]+]]:_(s16) = G_CONSTANT i16 2 - ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C8]](s16), [[C8]](s16), [[C8]](s16), [[C15]](s16), [[C8]](s16), [[C8]](s16), [[C8]](s16), [[C8]](s16) - ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C9]](s16), [[C11]](s16), [[C13]](s16), [[C16]](s16), [[C17]](s16), [[C18]](s16), [[C20]](s16), [[C21]](s16) - ; CHECK-NEXT: [[BUILD_VECTOR3:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C7]](s16), [[C8]](s16), [[C8]](s16), [[C8]](s16), [[C8]](s16), [[C8]](s16), [[C8]](s16), [[C8]](s16) - ; CHECK-NEXT: [[BUILD_VECTOR4:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C10]](s16), [[C12]](s16), [[C14]](s16), [[C8]](s16), [[C8]](s16), [[C19]](s16), [[C19]](s16), [[C8]](s16) - ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(<8 x s16>) = G_LSHR [[COPY]], [[BUILD_VECTOR1]](<8 x s16>) - ; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(<8 x s16>) = G_UMULH [[LSHR]], [[BUILD_VECTOR2]] + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 -32768 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s16) = G_CONSTANT i16 0 + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s16) = G_CONSTANT i16 25645 + ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s16) = G_CONSTANT i16 4 + ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s16) = G_CONSTANT i16 -3855 + ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s16) = G_CONSTANT i16 5 + ; CHECK-NEXT: [[C6:%[0-9]+]]:_(s16) = G_CONSTANT i16 8195 + ; CHECK-NEXT: [[C7:%[0-9]+]]:_(s16) = G_CONSTANT i16 13 + ; CHECK-NEXT: [[C8:%[0-9]+]]:_(s16) = G_CONSTANT i16 3 + ; CHECK-NEXT: [[C9:%[0-9]+]]:_(s16) = G_CONSTANT i16 9363 + ; CHECK-NEXT: [[C10:%[0-9]+]]:_(s16) = G_CONSTANT i16 512 + ; CHECK-NEXT: [[C11:%[0-9]+]]:_(s16) = G_CONSTANT i16 -32767 + ; CHECK-NEXT: [[C12:%[0-9]+]]:_(s16) = G_CONSTANT i16 15 + ; CHECK-NEXT: [[C13:%[0-9]+]]:_(s16) = G_CONSTANT i16 -32639 + ; CHECK-NEXT: [[C14:%[0-9]+]]:_(s16) = G_CONSTANT i16 2 + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C1]](s16), [[C1]](s16), [[C1]](s16), [[C8]](s16), [[C1]](s16), [[C1]](s16), [[C1]](s16), [[C1]](s16) + ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C2]](s16), [[C4]](s16), [[C6]](s16), [[C9]](s16), [[C10]](s16), [[C11]](s16), [[C13]](s16), [[C14]](s16) + ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C]](s16), [[C1]](s16), [[C1]](s16), [[C1]](s16), [[C1]](s16), [[C1]](s16), [[C1]](s16), [[C1]](s16) + ; CHECK-NEXT: [[BUILD_VECTOR3:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C3]](s16), [[C5]](s16), [[C7]](s16), [[C1]](s16), [[C1]](s16), [[C12]](s16), [[C12]](s16), [[C1]](s16) + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(<8 x s16>) = G_LSHR [[COPY]], [[BUILD_VECTOR]](<8 x s16>) + ; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(<8 x s16>) = G_UMULH [[LSHR]], [[BUILD_VECTOR1]] ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(<8 x s16>) = G_SUB [[COPY]], [[UMULH]] - ; CHECK-NEXT: [[UMULH1:%[0-9]+]]:_(<8 x s16>) = G_UMULH [[SUB]], [[BUILD_VECTOR3]] + ; CHECK-NEXT: [[UMULH1:%[0-9]+]]:_(<8 x s16>) = G_UMULH [[SUB]], [[BUILD_VECTOR2]] ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(<8 x s16>) = G_ADD [[UMULH1]], [[UMULH]] - ; CHECK-NEXT: [[LSHR1:%[0-9]+]]:_(<8 x s16>) = G_LSHR [[ADD]], [[BUILD_VECTOR4]](<8 x s16>) - ; CHECK-NEXT: [[C22:%[0-9]+]]:_(s16) = G_CONSTANT i16 1 - ; CHECK-NEXT: [[BUILD_VECTOR5:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C22]](s16), [[C22]](s16), [[C22]](s16), [[C22]](s16), [[C22]](s16), [[C22]](s16), [[C22]](s16), [[C22]](s16) - ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(<8 x s1>) = G_ICMP intpred(eq), [[BUILD_VECTOR]](<8 x s16>), [[BUILD_VECTOR5]] - ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<8 x s16>) = G_SELECT [[ICMP]](<8 x s1>), [[COPY]], [[LSHR1]] - ; CHECK-NEXT: $q0 = COPY [[SELECT]](<8 x s16>) + ; CHECK-NEXT: [[LSHR1:%[0-9]+]]:_(<8 x s16>) = G_LSHR [[ADD]], [[BUILD_VECTOR3]](<8 x s16>) + ; CHECK-NEXT: $q0 = COPY [[LSHR1]](<8 x s16>) ; CHECK-NEXT: RET_ReallyLR implicit $q0 %0:_(<8 x s16>) = COPY $q0 %2:_(s16) = G_CONSTANT i16 23 @@ -136,38 +126,26 @@ body: | ; CHECK: liveins: $q0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<8 x s16>) = COPY $q0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 -34 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s16) = G_CONSTANT i16 35 - ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s16) = G_CONSTANT i16 36 - ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s16) = G_CONSTANT i16 -37 - ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s16) = G_CONSTANT i16 38 - ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s16) = G_CONSTANT i16 -39 - ; CHECK-NEXT: [[C6:%[0-9]+]]:_(s16) = G_CONSTANT i16 40 - ; CHECK-NEXT: [[C7:%[0-9]+]]:_(s16) = G_CONSTANT i16 -41 - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C]](s16), [[C1]](s16), [[C2]](s16), [[C3]](s16), [[C4]](s16), [[C5]](s16), [[C6]](s16), [[C7]](s16) - ; CHECK-NEXT: [[C8:%[0-9]+]]:_(s16) = G_CONSTANT i16 1 - ; CHECK-NEXT: [[C9:%[0-9]+]]:_(s16) = G_CONSTANT i16 16393 - ; CHECK-NEXT: [[C10:%[0-9]+]]:_(s16) = G_CONSTANT i16 0 - ; CHECK-NEXT: [[C11:%[0-9]+]]:_(s16) = G_CONSTANT i16 13 - ; CHECK-NEXT: [[C12:%[0-9]+]]:_(s16) = G_CONSTANT i16 -5617 - ; CHECK-NEXT: [[C13:%[0-9]+]]:_(s16) = G_CONSTANT i16 5 - ; CHECK-NEXT: [[C14:%[0-9]+]]:_(s16) = G_CONSTANT i16 -7281 - ; CHECK-NEXT: [[C15:%[0-9]+]]:_(s16) = G_CONSTANT i16 -32749 - ; CHECK-NEXT: [[C16:%[0-9]+]]:_(s16) = G_CONSTANT i16 15 - ; CHECK-NEXT: [[C17:%[0-9]+]]:_(s16) = G_CONSTANT i16 -10347 - ; CHECK-NEXT: [[C18:%[0-9]+]]:_(s16) = G_CONSTANT i16 8197 - ; CHECK-NEXT: [[C19:%[0-9]+]]:_(s16) = G_CONSTANT i16 -13107 - ; CHECK-NEXT: [[C20:%[0-9]+]]:_(s16) = G_CONSTANT i16 -32747 - ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C8]](s16), [[C10]](s16), [[C10]](s16), [[C10]](s16), [[C10]](s16), [[C10]](s16), [[C10]](s16), [[C10]](s16) - ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C9]](s16), [[C12]](s16), [[C14]](s16), [[C15]](s16), [[C17]](s16), [[C18]](s16), [[C19]](s16), [[C20]](s16) - ; CHECK-NEXT: [[BUILD_VECTOR3:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C11]](s16), [[C13]](s16), [[C13]](s16), [[C16]](s16), [[C13]](s16), [[C11]](s16), [[C13]](s16), [[C16]](s16) - ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(<8 x s16>) = G_LSHR [[COPY]], [[BUILD_VECTOR1]](<8 x s16>) - ; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(<8 x s16>) = G_UMULH [[LSHR]], [[BUILD_VECTOR2]] - ; CHECK-NEXT: [[LSHR1:%[0-9]+]]:_(<8 x s16>) = G_LSHR [[UMULH]], [[BUILD_VECTOR3]](<8 x s16>) - ; CHECK-NEXT: [[BUILD_VECTOR4:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C8]](s16), [[C8]](s16), [[C8]](s16), [[C8]](s16), [[C8]](s16), [[C8]](s16), [[C8]](s16), [[C8]](s16) - ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(<8 x s1>) = G_ICMP intpred(eq), [[BUILD_VECTOR]](<8 x s16>), [[BUILD_VECTOR4]] - ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<8 x s16>) = G_SELECT [[ICMP]](<8 x s1>), [[COPY]], [[LSHR1]] - ; CHECK-NEXT: $q0 = COPY [[SELECT]](<8 x s16>) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 1 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s16) = G_CONSTANT i16 16393 + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s16) = G_CONSTANT i16 0 + ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s16) = G_CONSTANT i16 13 + ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s16) = G_CONSTANT i16 -5617 + ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s16) = G_CONSTANT i16 5 + ; CHECK-NEXT: [[C6:%[0-9]+]]:_(s16) = G_CONSTANT i16 -7281 + ; CHECK-NEXT: [[C7:%[0-9]+]]:_(s16) = G_CONSTANT i16 -32749 + ; CHECK-NEXT: [[C8:%[0-9]+]]:_(s16) = G_CONSTANT i16 15 + ; CHECK-NEXT: [[C9:%[0-9]+]]:_(s16) = G_CONSTANT i16 -10347 + ; CHECK-NEXT: [[C10:%[0-9]+]]:_(s16) = G_CONSTANT i16 8197 + ; CHECK-NEXT: [[C11:%[0-9]+]]:_(s16) = G_CONSTANT i16 -13107 + ; CHECK-NEXT: [[C12:%[0-9]+]]:_(s16) = G_CONSTANT i16 -32747 + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C]](s16), [[C2]](s16), [[C2]](s16), [[C2]](s16), [[C2]](s16), [[C2]](s16), [[C2]](s16), [[C2]](s16) + ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C1]](s16), [[C4]](s16), [[C6]](s16), [[C7]](s16), [[C9]](s16), [[C10]](s16), [[C11]](s16), [[C12]](s16) + ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C3]](s16), [[C5]](s16), [[C5]](s16), [[C8]](s16), [[C5]](s16), [[C3]](s16), [[C5]](s16), [[C8]](s16) + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(<8 x s16>) = G_LSHR [[COPY]], [[BUILD_VECTOR]](<8 x s16>) + ; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(<8 x s16>) = G_UMULH [[LSHR]], [[BUILD_VECTOR1]] + ; CHECK-NEXT: [[LSHR1:%[0-9]+]]:_(<8 x s16>) = G_LSHR [[UMULH]], [[BUILD_VECTOR2]](<8 x s16>) + ; CHECK-NEXT: $q0 = COPY [[LSHR1]](<8 x s16>) ; CHECK-NEXT: RET_ReallyLR implicit $q0 %0:_(<8 x s16>) = COPY $q0 %2:_(s16) = G_CONSTANT i16 -34 @@ -198,39 +176,28 @@ body: | ; CHECK: liveins: $q0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<8 x s16>) = COPY $q0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 7 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s16) = G_CONSTANT i16 23 - ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s16) = G_CONSTANT i16 25 - ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s16) = G_CONSTANT i16 27 - ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s16) = G_CONSTANT i16 31 - ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s16) = G_CONSTANT i16 47 - ; CHECK-NEXT: [[C6:%[0-9]+]]:_(s16) = G_CONSTANT i16 63 - ; CHECK-NEXT: [[C7:%[0-9]+]]:_(s16) = G_CONSTANT i16 127 - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C]](s16), [[C1]](s16), [[C2]](s16), [[C3]](s16), [[C4]](s16), [[C5]](s16), [[C6]](s16), [[C7]](s16) - ; CHECK-NEXT: [[C8:%[0-9]+]]:_(s16) = G_CONSTANT i16 9363 - ; CHECK-NEXT: [[C9:%[0-9]+]]:_(s16) = G_CONSTANT i16 2 - ; CHECK-NEXT: [[C10:%[0-9]+]]:_(s16) = G_CONSTANT i16 25645 - ; CHECK-NEXT: [[C11:%[0-9]+]]:_(s16) = G_CONSTANT i16 4 - ; CHECK-NEXT: [[C12:%[0-9]+]]:_(s16) = G_CONSTANT i16 18351 - ; CHECK-NEXT: [[C13:%[0-9]+]]:_(s16) = G_CONSTANT i16 12137 - ; CHECK-NEXT: [[C14:%[0-9]+]]:_(s16) = G_CONSTANT i16 2115 - ; CHECK-NEXT: [[C15:%[0-9]+]]:_(s16) = G_CONSTANT i16 23705 - ; CHECK-NEXT: [[C16:%[0-9]+]]:_(s16) = G_CONSTANT i16 5 - ; CHECK-NEXT: [[C17:%[0-9]+]]:_(s16) = G_CONSTANT i16 1041 - ; CHECK-NEXT: [[C18:%[0-9]+]]:_(s16) = G_CONSTANT i16 517 - ; CHECK-NEXT: [[C19:%[0-9]+]]:_(s16) = G_CONSTANT i16 6 - ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C8]](s16), [[C10]](s16), [[C12]](s16), [[C13]](s16), [[C14]](s16), [[C15]](s16), [[C17]](s16), [[C18]](s16) - ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C9]](s16), [[C11]](s16), [[C11]](s16), [[C11]](s16), [[C11]](s16), [[C16]](s16), [[C16]](s16), [[C19]](s16) - ; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(<8 x s16>) = G_UMULH [[COPY]], [[BUILD_VECTOR1]] + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 9363 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s16) = G_CONSTANT i16 2 + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s16) = G_CONSTANT i16 25645 + ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s16) = G_CONSTANT i16 4 + ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s16) = G_CONSTANT i16 18351 + ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s16) = G_CONSTANT i16 12137 + ; CHECK-NEXT: [[C6:%[0-9]+]]:_(s16) = G_CONSTANT i16 2115 + ; CHECK-NEXT: [[C7:%[0-9]+]]:_(s16) = G_CONSTANT i16 23705 + ; CHECK-NEXT: [[C8:%[0-9]+]]:_(s16) = G_CONSTANT i16 5 + ; CHECK-NEXT: [[C9:%[0-9]+]]:_(s16) = G_CONSTANT i16 1041 + ; CHECK-NEXT: [[C10:%[0-9]+]]:_(s16) = G_CONSTANT i16 517 + ; CHECK-NEXT: [[C11:%[0-9]+]]:_(s16) = G_CONSTANT i16 6 + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C]](s16), [[C2]](s16), [[C4]](s16), [[C5]](s16), [[C6]](s16), [[C7]](s16), [[C9]](s16), [[C10]](s16) + ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C1]](s16), [[C3]](s16), [[C3]](s16), [[C3]](s16), [[C3]](s16), [[C8]](s16), [[C8]](s16), [[C11]](s16) + ; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(<8 x s16>) = G_UMULH [[COPY]], [[BUILD_VECTOR]] ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(<8 x s16>) = G_SUB [[COPY]], [[UMULH]] - ; CHECK-NEXT: [[C20:%[0-9]+]]:_(s16) = G_CONSTANT i16 1 - ; CHECK-NEXT: [[BUILD_VECTOR3:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C20]](s16), [[C20]](s16), [[C20]](s16), [[C20]](s16), [[C20]](s16), [[C20]](s16), [[C20]](s16), [[C20]](s16) - ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(<8 x s16>) = G_LSHR [[SUB]], [[BUILD_VECTOR3]](<8 x s16>) + ; CHECK-NEXT: [[C12:%[0-9]+]]:_(s16) = G_CONSTANT i16 1 + ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C12]](s16), [[C12]](s16), [[C12]](s16), [[C12]](s16), [[C12]](s16), [[C12]](s16), [[C12]](s16), [[C12]](s16) + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(<8 x s16>) = G_LSHR [[SUB]], [[BUILD_VECTOR2]](<8 x s16>) ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(<8 x s16>) = G_ADD [[LSHR]], [[UMULH]] - ; CHECK-NEXT: [[LSHR1:%[0-9]+]]:_(<8 x s16>) = G_LSHR [[ADD]], [[BUILD_VECTOR2]](<8 x s16>) - ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(<8 x s1>) = G_ICMP intpred(eq), [[BUILD_VECTOR]](<8 x s16>), [[BUILD_VECTOR3]] - ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<8 x s16>) = G_SELECT [[ICMP]](<8 x s1>), [[COPY]], [[LSHR1]] - ; CHECK-NEXT: $q0 = COPY [[SELECT]](<8 x s16>) + ; CHECK-NEXT: [[LSHR1:%[0-9]+]]:_(<8 x s16>) = G_LSHR [[ADD]], [[BUILD_VECTOR1]](<8 x s16>) + ; CHECK-NEXT: $q0 = COPY [[LSHR1]](<8 x s16>) ; CHECK-NEXT: RET_ReallyLR implicit $q0 %0:_(<8 x s16>) = COPY $q0 %2:_(s16) = G_CONSTANT i16 7 @@ -261,19 +228,17 @@ body: | ; CHECK: liveins: $q0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<16 x s8>) = COPY $q0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s8) = G_CONSTANT i8 -64 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s8) = G_CONSTANT i8 1 - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<16 x s8>) = G_BUILD_VECTOR [[C]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8) - ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s8) = G_CONSTANT i8 0 - ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s8) = G_CONSTANT i8 -85 - ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s8) = G_CONSTANT i8 7 - ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<16 x s8>) = G_BUILD_VECTOR [[C3]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8) - ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<16 x s8>) = G_BUILD_VECTOR [[C4]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8) - ; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(<16 x s8>) = G_UMULH [[COPY]], [[BUILD_VECTOR1]] - ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(<16 x s8>) = G_LSHR [[UMULH]], [[BUILD_VECTOR2]](<16 x s8>) - ; CHECK-NEXT: [[BUILD_VECTOR3:%[0-9]+]]:_(<16 x s8>) = G_BUILD_VECTOR [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8), [[C1]](s8) - ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(<16 x s1>) = G_ICMP intpred(eq), [[BUILD_VECTOR]](<16 x s8>), [[BUILD_VECTOR3]] - ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<16 x s8>) = G_SELECT [[ICMP]](<16 x s1>), [[COPY]], [[LSHR]] + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s8) = G_CONSTANT i8 0 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s8) = G_CONSTANT i8 -85 + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s8) = G_CONSTANT i8 7 + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<16 x s8>) = G_BUILD_VECTOR [[C1]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8) + ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<16 x s8>) = G_BUILD_VECTOR [[C2]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8), [[C]](s8) + ; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(<16 x s8>) = G_UMULH [[COPY]], [[BUILD_VECTOR]] + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(<16 x s8>) = G_LSHR [[UMULH]], [[BUILD_VECTOR1]](<16 x s8>) + ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s1) = G_CONSTANT i1 false + ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s1) = G_CONSTANT i1 true + ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<16 x s1>) = G_BUILD_VECTOR [[C3]](s1), [[C4]](s1), [[C4]](s1), [[C4]](s1), [[C4]](s1), [[C4]](s1), [[C4]](s1), [[C4]](s1), [[C4]](s1), [[C4]](s1), [[C4]](s1), [[C4]](s1), [[C4]](s1), [[C4]](s1), [[C4]](s1), [[C4]](s1) + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<16 x s8>) = G_SELECT [[BUILD_VECTOR2]](<16 x s1>), [[COPY]], [[LSHR]] ; CHECK-NEXT: $q0 = COPY [[SELECT]](<16 x s8>) ; CHECK-NEXT: RET_ReallyLR implicit $q0 %0:_(<16 x s8>) = COPY $q0 @@ -299,39 +264,31 @@ body: | ; CHECK: liveins: $q0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<8 x s16>) = COPY $q0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 1 - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s16) = G_CONSTANT i16 119 - ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s16) = G_CONSTANT i16 73 - ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s16) = G_CONSTANT i16 -111 - ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s16) = G_CONSTANT i16 -3 - ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s16) = G_CONSTANT i16 118 - ; CHECK-NEXT: [[C6:%[0-9]+]]:_(s16) = G_CONSTANT i16 32 - ; CHECK-NEXT: [[C7:%[0-9]+]]:_(s16) = G_CONSTANT i16 31 - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C]](s16), [[C1]](s16), [[C2]](s16), [[C3]](s16), [[C4]](s16), [[C5]](s16), [[C6]](s16), [[C7]](s16) - ; CHECK-NEXT: [[C8:%[0-9]+]]:_(s16) = G_CONSTANT i16 0 - ; CHECK-NEXT: [[C9:%[0-9]+]]:_(s16) = G_CONSTANT i16 4957 - ; CHECK-NEXT: [[C10:%[0-9]+]]:_(s16) = G_CONSTANT i16 -32768 - ; CHECK-NEXT: [[C11:%[0-9]+]]:_(s16) = G_CONSTANT i16 6 - ; CHECK-NEXT: [[C12:%[0-9]+]]:_(s16) = G_CONSTANT i16 -8079 - ; CHECK-NEXT: [[C13:%[0-9]+]]:_(s16) = G_CONSTANT i16 4103 - ; CHECK-NEXT: [[C14:%[0-9]+]]:_(s16) = G_CONSTANT i16 12 - ; CHECK-NEXT: [[C15:%[0-9]+]]:_(s16) = G_CONSTANT i16 16385 - ; CHECK-NEXT: [[C16:%[0-9]+]]:_(s16) = G_CONSTANT i16 14 - ; CHECK-NEXT: [[C17:%[0-9]+]]:_(s16) = G_CONSTANT i16 -29991 - ; CHECK-NEXT: [[C18:%[0-9]+]]:_(s16) = G_CONSTANT i16 2048 - ; CHECK-NEXT: [[C19:%[0-9]+]]:_(s16) = G_CONSTANT i16 2115 - ; CHECK-NEXT: [[C20:%[0-9]+]]:_(s16) = G_CONSTANT i16 4 - ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C8]](s16), [[C9]](s16), [[C12]](s16), [[C13]](s16), [[C15]](s16), [[C17]](s16), [[C18]](s16), [[C19]](s16) - ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C8]](s16), [[C10]](s16), [[C8]](s16), [[C8]](s16), [[C8]](s16), [[C8]](s16), [[C8]](s16), [[C10]](s16) - ; CHECK-NEXT: [[BUILD_VECTOR3:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C8]](s16), [[C11]](s16), [[C11]](s16), [[C14]](s16), [[C16]](s16), [[C11]](s16), [[C8]](s16), [[C20]](s16) - ; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(<8 x s16>) = G_UMULH [[COPY]], [[BUILD_VECTOR1]] + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 0 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s16) = G_CONSTANT i16 4957 + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s16) = G_CONSTANT i16 -32768 + ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s16) = G_CONSTANT i16 6 + ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s16) = G_CONSTANT i16 -8079 + ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s16) = G_CONSTANT i16 4103 + ; CHECK-NEXT: [[C6:%[0-9]+]]:_(s16) = G_CONSTANT i16 12 + ; CHECK-NEXT: [[C7:%[0-9]+]]:_(s16) = G_CONSTANT i16 16385 + ; CHECK-NEXT: [[C8:%[0-9]+]]:_(s16) = G_CONSTANT i16 14 + ; CHECK-NEXT: [[C9:%[0-9]+]]:_(s16) = G_CONSTANT i16 -29991 + ; CHECK-NEXT: [[C10:%[0-9]+]]:_(s16) = G_CONSTANT i16 2048 + ; CHECK-NEXT: [[C11:%[0-9]+]]:_(s16) = G_CONSTANT i16 2115 + ; CHECK-NEXT: [[C12:%[0-9]+]]:_(s16) = G_CONSTANT i16 4 + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C]](s16), [[C1]](s16), [[C4]](s16), [[C5]](s16), [[C7]](s16), [[C9]](s16), [[C10]](s16), [[C11]](s16) + ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C]](s16), [[C2]](s16), [[C]](s16), [[C]](s16), [[C]](s16), [[C]](s16), [[C]](s16), [[C2]](s16) + ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C]](s16), [[C3]](s16), [[C3]](s16), [[C6]](s16), [[C8]](s16), [[C3]](s16), [[C]](s16), [[C12]](s16) + ; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(<8 x s16>) = G_UMULH [[COPY]], [[BUILD_VECTOR]] ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(<8 x s16>) = G_SUB [[COPY]], [[UMULH]] - ; CHECK-NEXT: [[UMULH1:%[0-9]+]]:_(<8 x s16>) = G_UMULH [[SUB]], [[BUILD_VECTOR2]] + ; CHECK-NEXT: [[UMULH1:%[0-9]+]]:_(<8 x s16>) = G_UMULH [[SUB]], [[BUILD_VECTOR1]] ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(<8 x s16>) = G_ADD [[UMULH1]], [[UMULH]] - ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(<8 x s16>) = G_LSHR [[ADD]], [[BUILD_VECTOR3]](<8 x s16>) - ; CHECK-NEXT: [[BUILD_VECTOR4:%[0-9]+]]:_(<8 x s16>) = G_BUILD_VECTOR [[C]](s16), [[C]](s16), [[C]](s16), [[C]](s16), [[C]](s16), [[C]](s16), [[C]](s16), [[C]](s16) - ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(<8 x s1>) = G_ICMP intpred(eq), [[BUILD_VECTOR]](<8 x s16>), [[BUILD_VECTOR4]] - ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<8 x s16>) = G_SELECT [[ICMP]](<8 x s1>), [[COPY]], [[LSHR]] + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(<8 x s16>) = G_LSHR [[ADD]], [[BUILD_VECTOR2]](<8 x s16>) + ; CHECK-NEXT: [[C13:%[0-9]+]]:_(s1) = G_CONSTANT i1 true + ; CHECK-NEXT: [[C14:%[0-9]+]]:_(s1) = G_CONSTANT i1 false + ; CHECK-NEXT: [[BUILD_VECTOR3:%[0-9]+]]:_(<8 x s1>) = G_BUILD_VECTOR [[C13]](s1), [[C14]](s1), [[C14]](s1), [[C14]](s1), [[C14]](s1), [[C14]](s1), [[C14]](s1), [[C14]](s1) + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<8 x s16>) = G_SELECT [[BUILD_VECTOR3]](<8 x s1>), [[COPY]], [[LSHR]] ; CHECK-NEXT: $q0 = COPY [[SELECT]](<8 x s16>) ; CHECK-NEXT: RET_ReallyLR implicit $q0 %0:_(<8 x s16>) = COPY $q0 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-nneg-disjoint.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-nneg-disjoint.ll new file mode 100644 index 0000000000000000000000000000000000000000..32c742316b872a01021b38029a5f49833642bcf4 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-nneg-disjoint.ll @@ -0,0 +1,135 @@ +; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple=aarch64-linux-gnu -O0 -stop-after=irtranslator -global-isel -verify-machineinstrs %s -o - 2>&1 | FileCheck %s + +define i32 @call_nneg(i16 %a) { + ; CHECK-LABEL: name: call_nneg + ; CHECK: bb.1.entry: + ; CHECK-NEXT: liveins: $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; CHECK-NEXT: %2:_(s32) = nneg G_ZEXT [[TRUNC]](s16) + ; CHECK-NEXT: $w0 = COPY %2(s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 +entry: + %result = zext nneg i16 %a to i32 + ret i32 %result +} + +define i32 @call_not_nneg(i16 %a) { + ; CHECK-LABEL: name: call_not_nneg + ; CHECK: bb.1.entry: + ; CHECK-NEXT: liveins: $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s16) + ; CHECK-NEXT: $w0 = COPY [[ZEXT]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 +entry: + %result = zext i16 %a to i32 + ret i32 %result +} + +define i32 @call_disjoint(i32 %a, i32 %b) { + ; CHECK-LABEL: name: call_disjoint + ; CHECK: bb.1.entry: + ; CHECK-NEXT: liveins: $w0, $w1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1 + ; CHECK-NEXT: %2:_(s32) = disjoint G_OR [[COPY]], [[COPY1]] + ; CHECK-NEXT: $w0 = COPY %2(s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 +entry: + %result = or disjoint i32 %a, %b + ret i32 %result +} + +define i32 @call_add(i32 %a, i32 %b) { + ; CHECK-LABEL: name: call_add + ; CHECK: bb.1.entry: + ; CHECK-NEXT: liveins: $w0, $w1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1 + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = nsw G_ADD [[COPY]], [[COPY1]] + ; CHECK-NEXT: $w0 = COPY [[ADD]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 +entry: + %result = add nsw i32 %a, %b + ret i32 %result +} + +define i32 @call_not_disjoint(i32 %a, i32 %b) { + ; CHECK-LABEL: name: call_not_disjoint + ; CHECK: bb.1.entry: + ; CHECK-NEXT: liveins: $w0, $w1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1 + ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[COPY]], [[COPY1]] + ; CHECK-NEXT: $w0 = COPY [[OR]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 +entry: + %result = or i32 %a, %b + ret i32 %result +} + +define <2 x i64> @call_not_disjoint_vector(<2 x i64> %a, <2 x i64> %b) { + ; CHECK-LABEL: name: call_not_disjoint_vector + ; CHECK: bb.1.entry: + ; CHECK-NEXT: liveins: $q0, $q1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $q0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $q1 + ; CHECK-NEXT: [[OR:%[0-9]+]]:_(<2 x s64>) = G_OR [[COPY]], [[COPY1]] + ; CHECK-NEXT: $q0 = COPY [[OR]](<2 x s64>) + ; CHECK-NEXT: RET_ReallyLR implicit $q0 +entry: + %result = or <2 x i64> %a, %b + ret <2 x i64> %result +} + +define <2 x i64> @call_disjoint_vector(<2 x i64> %a, <2 x i64> %b) { + ; CHECK-LABEL: name: call_disjoint_vector + ; CHECK: bb.1.entry: + ; CHECK-NEXT: liveins: $q0, $q1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $q0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $q1 + ; CHECK-NEXT: %2:_(<2 x s64>) = disjoint G_OR [[COPY]], [[COPY1]] + ; CHECK-NEXT: $q0 = COPY %2(<2 x s64>) + ; CHECK-NEXT: RET_ReallyLR implicit $q0 +entry: + %result = or disjoint <2 x i64> %a, %b + ret <2 x i64> %result +} + +define <2 x i64> @call_nneg_vector(<2 x i32> %a) { + ; CHECK-LABEL: name: call_nneg_vector + ; CHECK: bb.1.entry: + ; CHECK-NEXT: liveins: $d0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0 + ; CHECK-NEXT: %1:_(<2 x s64>) = nneg G_ZEXT [[COPY]](<2 x s32>) + ; CHECK-NEXT: $q0 = COPY %1(<2 x s64>) + ; CHECK-NEXT: RET_ReallyLR implicit $q0 +entry: + %result = zext nneg <2 x i32> %a to <2 x i64> + ret <2 x i64> %result +} + +define <2 x i64> @call_not_nneg_vector(<2 x i32> %a) { + ; CHECK-LABEL: name: call_not_nneg_vector + ; CHECK: bb.1.entry: + ; CHECK-NEXT: liveins: $d0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0 + ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(<2 x s64>) = G_ZEXT [[COPY]](<2 x s32>) + ; CHECK-NEXT: $q0 = COPY [[ZEXT]](<2 x s64>) + ; CHECK-NEXT: RET_ReallyLR implicit $q0 +entry: + %result = zext <2 x i32> %a to <2 x i64> + ret <2 x i64> %result +} diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-trunc.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-trunc.ll new file mode 100644 index 0000000000000000000000000000000000000000..d87e9c4b18550b901c65b65105e0d60ae8043d14 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-trunc.ll @@ -0,0 +1,90 @@ +; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +; RUN: llc -O0 -mtriple=aarch64-linux-gnu -global-isel -stop-after=irtranslator %s -o - | FileCheck %s + +define i32 @call_trunc_no_flags(i64 %a) { + ; CHECK-LABEL: name: call_trunc_no_flags + ; CHECK: bb.1.entry: + ; CHECK-NEXT: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) + ; CHECK-NEXT: $w0 = COPY [[TRUNC]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 +entry: + %result = trunc i64 %a to i32 + ret i32 %result +} + +define i32 @call_trunc_nsw_flags(i64 %a) { + ; CHECK-LABEL: name: call_trunc_nsw_flags + ; CHECK: bb.1.entry: + ; CHECK-NEXT: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = nsw G_TRUNC [[COPY]](s64) + ; CHECK-NEXT: $w0 = COPY [[TRUNC]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 +entry: + %result = trunc nsw i64 %a to i32 + ret i32 %result +} + +define i32 @call_trunc_nuw_flags(i64 %a) { + ; CHECK-LABEL: name: call_trunc_nuw_flags + ; CHECK: bb.1.entry: + ; CHECK-NEXT: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = nuw G_TRUNC [[COPY]](s64) + ; CHECK-NEXT: $w0 = COPY [[TRUNC]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 +entry: + %result = trunc nuw i64 %a to i32 + ret i32 %result +} + +define i32 @call_trunc_all_flags(i64 %a) { + ; CHECK-LABEL: name: call_trunc_all_flags + ; CHECK: bb.1.entry: + ; CHECK-NEXT: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = nuw nsw G_TRUNC [[COPY]](s64) + ; CHECK-NEXT: $w0 = COPY [[TRUNC]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 +entry: + %result = trunc nsw nuw i64 %a to i32 + ret i32 %result +} + +define <2 x i64> @call_trunc_noop_signed_vector(<2 x i64> %a) { + ; CHECK-LABEL: name: call_trunc_noop_signed_vector + ; CHECK: bb.1.entry: + ; CHECK-NEXT: liveins: $q0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $q0 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<2 x s32>) = nsw G_TRUNC [[COPY]](<2 x s64>) + ; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(<2 x s64>) = G_SEXT [[TRUNC]](<2 x s32>) + ; CHECK-NEXT: $q0 = COPY [[SEXT]](<2 x s64>) + ; CHECK-NEXT: RET_ReallyLR implicit $q0 +entry: + %truncate = trunc nsw <2 x i64> %a to <2 x i32> + %result = sext <2 x i32> %truncate to <2 x i64> + ret <2 x i64> %result +} + +define <2 x i64> @call_trunc_noop_unsigned_vector(<2 x i64> %a) { + ; CHECK-LABEL: name: call_trunc_noop_unsigned_vector + ; CHECK: bb.1.entry: + ; CHECK-NEXT: liveins: $q0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $q0 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<2 x s32>) = nuw G_TRUNC [[COPY]](<2 x s64>) + ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(<2 x s64>) = G_ZEXT [[TRUNC]](<2 x s32>) + ; CHECK-NEXT: $q0 = COPY [[ZEXT]](<2 x s64>) + ; CHECK-NEXT: RET_ReallyLR implicit $q0 +entry: + %truncate = trunc nuw <2 x i64> %a to <2 x i32> + %result = zext <2 x i32> %truncate to <2 x i64> + ret <2 x i64> %result +} diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-unreachable.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-unreachable.ll index fe9427d2678a161065ffedb2f54195785576526f..edae903fae848fcbab064111f590f3d30e2c2605 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-unreachable.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-unreachable.ll @@ -6,7 +6,7 @@ declare void @llvm.trap() define void @unreachable() { ; CHECK-LABEL: name: unreachable ; CHECK: bb.1 (%ir-block.0): - ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + ; CHECK-NEXT: G_TRAP unreachable ret void } diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-vector-deinterleave2.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-vector-deinterleave2.ll new file mode 100644 index 0000000000000000000000000000000000000000..10882a06af1b403e8717672bdcf237e19712868b --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-vector-deinterleave2.ll @@ -0,0 +1,34 @@ +; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -O0 -mtriple=aarch64-- --global-isel --global-isel-abort=2 --verify-machineinstrs --stop-after=irtranslator %s -o - | FileCheck %s + +define void @vector_deinterleave2_v4i32(<4 x i32> %a) { + ; CHECK-LABEL: name: vector_deinterleave2_v4i32 + ; CHECK: bb.1 (%ir-block.0): + ; CHECK-NEXT: liveins: $q0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0 + ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(<4 x s32>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SHUF:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[COPY]](<4 x s32>), [[DEF]], shufflemask(0, 2) + ; CHECK-NEXT: [[SHUF1:%[0-9]+]]:_(<2 x s32>) = G_SHUFFLE_VECTOR [[COPY]](<4 x s32>), [[DEF]], shufflemask(1, 3) + ; CHECK-NEXT: RET_ReallyLR + %res = call {<2 x i32>, <2 x i32>} @llvm.experimental.vector.deinterleave2.v4i32(<4 x i32> %a) + ret void +} + +define void @vector_deinterleave2_v8f32(<8 x float> %a) { + ; CHECK-LABEL: name: vector_deinterleave2_v8f32 + ; CHECK: bb.1 (%ir-block.0): + ; CHECK-NEXT: liveins: $q0, $q1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $q0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $q1 + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<4 x s32>) = G_BITCAST [[COPY]](<2 x s64>) + ; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<4 x s32>) = G_BITCAST [[COPY1]](<2 x s64>) + ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<8 x s32>) = G_CONCAT_VECTORS [[BITCAST]](<4 x s32>), [[BITCAST1]](<4 x s32>) + ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(<8 x s32>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SHUF:%[0-9]+]]:_(<4 x s32>) = G_SHUFFLE_VECTOR [[CONCAT_VECTORS]](<8 x s32>), [[DEF]], shufflemask(0, 2, 4, 6) + ; CHECK-NEXT: [[SHUF1:%[0-9]+]]:_(<4 x s32>) = G_SHUFFLE_VECTOR [[CONCAT_VECTORS]](<8 x s32>), [[DEF]], shufflemask(1, 3, 5, 7) + ; CHECK-NEXT: RET_ReallyLR + %res = call {<4 x float>, <4 x float>} @llvm.experimental.vector.deinterleave2.v8f32(<8 x float> %a) + ret void +} diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-vector-interleave2.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-vector-interleave2.ll new file mode 100644 index 0000000000000000000000000000000000000000..f51e47a428d10ed7fbad1aa66832cf82802a7354 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-vector-interleave2.ll @@ -0,0 +1,30 @@ +; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -O0 -mtriple=aarch64-- --global-isel --global-isel-abort=2 --verify-machineinstrs --stop-after=irtranslator %s -o - | FileCheck %s + +define void @vector_interleave2_v4i32(<2 x i32> %a, <2 x i32> %b) { + ; CHECK-LABEL: name: vector_interleave2_v4i32 + ; CHECK: bb.1 (%ir-block.0): + ; CHECK-NEXT: liveins: $d0, $d1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $d1 + ; CHECK-NEXT: [[SHUF:%[0-9]+]]:_(<4 x s32>) = G_SHUFFLE_VECTOR [[COPY]](<2 x s32>), [[COPY1]], shufflemask(0, 2, 1, 3) + ; CHECK-NEXT: RET_ReallyLR + %res = call <4 x i32> @llvm.experimental.vector.interleave2.v4i32(<2 x i32> %a, <2 x i32> %b) + ret void +} + +define void @vector_interleave2_v8f32(<4 x float> %a, <4 x float> %b) { + ; CHECK-LABEL: name: vector_interleave2_v8f32 + ; CHECK: bb.1 (%ir-block.0): + ; CHECK-NEXT: liveins: $q0, $q1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $q0 + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<4 x s32>) = G_BITCAST [[COPY]](<2 x s64>) + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $q1 + ; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<4 x s32>) = G_BITCAST [[COPY1]](<2 x s64>) + ; CHECK-NEXT: [[SHUF:%[0-9]+]]:_(<8 x s32>) = G_SHUFFLE_VECTOR [[BITCAST]](<4 x s32>), [[BITCAST1]], shufflemask(0, 4, 1, 5, 2, 6, 3, 7) + ; CHECK-NEXT: RET_ReallyLR + %res = call <8 x float> @llvm.experimental.vector.interleave2.v8f32(<4 x float> %a, <4 x float> %b) + ret void +} diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-abs.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-abs.mir index 3123e304116fe589dbac4d6481e4ca03d314676e..0d429ae384026623941713715221b24af0317559 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-abs.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-abs.mir @@ -8,11 +8,12 @@ body: | bb.0: ; CHECK-LABEL: name: abs_s32 ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 31 - ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[COPY]], [[C]](s64) - ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[ASHR]] - ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ADD]], [[ASHR]] - ; CHECK-NEXT: $w0 = COPY [[XOR]](s32) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[C]], [[COPY]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(sgt), [[COPY]](s32), [[C]] + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP]](s32), [[COPY]], [[SUB]] + ; CHECK-NEXT: $w0 = COPY [[SELECT]](s32) + ; ; CHECK-CSSC-LABEL: name: abs_s32 ; CHECK-CSSC: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 ; CHECK-CSSC-NEXT: [[ABS:%[0-9]+]]:_(s32) = G_ABS [[COPY]] @@ -28,11 +29,12 @@ body: | bb.0: ; CHECK-LABEL: name: abs_s64 ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 63 - ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY]], [[C]](s64) - ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[COPY]], [[ASHR]] - ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s64) = G_XOR [[ADD]], [[ASHR]] - ; CHECK-NEXT: $x0 = COPY [[XOR]](s64) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB [[C]], [[COPY]] + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(sgt), [[COPY]](s64), [[C]] + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[ICMP]](s32), [[COPY]], [[SUB]] + ; CHECK-NEXT: $x0 = COPY [[SELECT]](s64) + ; ; CHECK-CSSC-LABEL: name: abs_s64 ; CHECK-CSSC: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 ; CHECK-CSSC-NEXT: [[ABS:%[0-9]+]]:_(s64) = G_ABS [[COPY]] @@ -55,6 +57,7 @@ body: | ; CHECK-NEXT: [[ABS:%[0-9]+]]:_(<4 x s16>) = G_ABS [[COPY]] ; CHECK-NEXT: $d0 = COPY [[ABS]](<4 x s16>) ; CHECK-NEXT: RET_ReallyLR implicit $d0 + ; ; CHECK-CSSC-LABEL: name: abs_v4s16 ; CHECK-CSSC: liveins: $d0 ; CHECK-CSSC-NEXT: {{ $}} @@ -82,6 +85,7 @@ body: | ; CHECK-NEXT: [[ABS:%[0-9]+]]:_(<8 x s16>) = G_ABS [[COPY]] ; CHECK-NEXT: $q0 = COPY [[ABS]](<8 x s16>) ; CHECK-NEXT: RET_ReallyLR implicit $q0 + ; ; CHECK-CSSC-LABEL: name: abs_v8s16 ; CHECK-CSSC: liveins: $q0 ; CHECK-CSSC-NEXT: {{ $}} @@ -109,6 +113,7 @@ body: | ; CHECK-NEXT: [[ABS:%[0-9]+]]:_(<2 x s32>) = G_ABS [[COPY]] ; CHECK-NEXT: $d0 = COPY [[ABS]](<2 x s32>) ; CHECK-NEXT: RET_ReallyLR implicit $d0 + ; ; CHECK-CSSC-LABEL: name: abs_v2s32 ; CHECK-CSSC: liveins: $d0 ; CHECK-CSSC-NEXT: {{ $}} @@ -136,6 +141,7 @@ body: | ; CHECK-NEXT: [[ABS:%[0-9]+]]:_(<4 x s32>) = G_ABS [[COPY]] ; CHECK-NEXT: $q0 = COPY [[ABS]](<4 x s32>) ; CHECK-NEXT: RET_ReallyLR implicit $q0 + ; ; CHECK-CSSC-LABEL: name: abs_v4s32 ; CHECK-CSSC: liveins: $q0 ; CHECK-CSSC-NEXT: {{ $}} @@ -163,6 +169,7 @@ body: | ; CHECK-NEXT: [[ABS:%[0-9]+]]:_(<8 x s8>) = G_ABS [[COPY]] ; CHECK-NEXT: $d0 = COPY [[ABS]](<8 x s8>) ; CHECK-NEXT: RET_ReallyLR implicit $d0 + ; ; CHECK-CSSC-LABEL: name: abs_v4s8 ; CHECK-CSSC: liveins: $d0 ; CHECK-CSSC-NEXT: {{ $}} @@ -190,6 +197,7 @@ body: | ; CHECK-NEXT: [[ABS:%[0-9]+]]:_(<16 x s8>) = G_ABS [[COPY]] ; CHECK-NEXT: $q0 = COPY [[ABS]](<16 x s8>) ; CHECK-NEXT: RET_ReallyLR implicit $q0 + ; ; CHECK-CSSC-LABEL: name: abs_v16s8 ; CHECK-CSSC: liveins: $q0 ; CHECK-CSSC-NEXT: {{ $}} diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-build-vector.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-build-vector.mir index c9556e27c6349a9c929325edab316f87a0062447..a63d8b9c1377258bf5d4f0409479abbb06fcfef4 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-build-vector.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-build-vector.mir @@ -121,10 +121,11 @@ body: | ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s16) = COPY $h0 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s16) = COPY $h1 - ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[COPY]](s16) - ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[COPY1]](s16) - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[ANYEXT]](s32), [[ANYEXT1]](s32) - ; CHECK-NEXT: $d0 = COPY [[BUILD_VECTOR]](<2 x s32>) + ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[COPY]](s16), [[COPY1]](s16), [[DEF]](s16), [[DEF]](s16) + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(<4 x s32>) = G_ANYEXT [[BUILD_VECTOR]](<4 x s16>) + ; CHECK-NEXT: [[UV:%[0-9]+]]:_(<2 x s32>), [[UV1:%[0-9]+]]:_(<2 x s32>) = G_UNMERGE_VALUES [[ANYEXT]](<4 x s32>) + ; CHECK-NEXT: $d0 = COPY [[UV]](<2 x s32>) ; CHECK-NEXT: RET_ReallyLR %0:_(s16) = COPY $h0 %1:_(s16) = COPY $h1 @@ -141,8 +142,8 @@ body: | ; CHECK-LABEL: name: widen_v2s8 ; CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY [[DEF]](s32) - ; CHECK-NEXT: %3:_(<2 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[DEF]](s32) - ; CHECK-NEXT: $d0 = COPY %3(<2 x s32>) + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[DEF]](s32) + ; CHECK-NEXT: $d0 = COPY [[BUILD_VECTOR]](<2 x s32>) ; CHECK-NEXT: RET_ReallyLR %0:_(s8) = G_IMPLICIT_DEF %1:_(s8) = G_IMPLICIT_DEF @@ -157,12 +158,14 @@ name: widen_v4s8 body: | bb.0: ; CHECK-LABEL: name: widen_v4s8 - ; CHECK: [[DEF:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF - ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s16) = COPY [[DEF]](s16) - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s16) = COPY [[DEF]](s16) - ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s16) = COPY [[DEF]](s16) - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[COPY]](s16), [[COPY1]](s16), [[COPY2]](s16), [[DEF]](s16) - ; CHECK-NEXT: $d0 = COPY [[BUILD_VECTOR]](<4 x s16>) + ; CHECK: [[DEF:%[0-9]+]]:_(s8) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(s8) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF2:%[0-9]+]]:_(s8) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF3:%[0-9]+]]:_(s8) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<8 x s8>) = G_BUILD_VECTOR [[DEF]](s8), [[DEF1]](s8), [[DEF2]](s8), [[DEF3]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF]](s8) + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(<8 x s16>) = G_ANYEXT [[BUILD_VECTOR]](<8 x s8>) + ; CHECK-NEXT: [[UV:%[0-9]+]]:_(<4 x s16>), [[UV1:%[0-9]+]]:_(<4 x s16>) = G_UNMERGE_VALUES [[ANYEXT]](<8 x s16>) + ; CHECK-NEXT: $d0 = COPY [[UV]](<4 x s16>) ; CHECK-NEXT: RET_ReallyLR %0:_(s8) = G_IMPLICIT_DEF %1:_(s8) = G_IMPLICIT_DEF diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-cmpxchg-128.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-cmpxchg-128.mir index 6a6e0b63b103a1bb2e09b27a9ff325d86a88121c..26230efbbe863fd2ba742a5219e5b031e60a65e9 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-cmpxchg-128.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-cmpxchg-128.mir @@ -12,22 +12,6 @@ body: | liveins: $x0, $x1, $x2, $x3, $x4 - ; CHECK-LABEL: name: compare_swap_128 - ; CHECK: liveins: $x0_x1, $x1, $x0, $x1, $x2, $x3, $x4 - ; CHECK: [[COPY:%[0-9]+]]:gpr64(p0) = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1 - ; CHECK: [[COPY2:%[0-9]+]]:_(s64) = COPY $x2 - ; CHECK: [[COPY3:%[0-9]+]]:_(s64) = COPY $x3 - ; CHECK: [[COPY4:%[0-9]+]]:_(s64) = COPY $x4 - ; CHECK: [[COPY5:%[0-9]+]]:gpr64(s64) = COPY [[COPY1]](s64) - ; CHECK: [[COPY6:%[0-9]+]]:gpr64(s64) = COPY [[COPY2]](s64) - ; CHECK: [[COPY7:%[0-9]+]]:gpr64(s64) = COPY [[COPY3]](s64) - ; CHECK: [[COPY8:%[0-9]+]]:gpr64(s64) = COPY [[COPY4]](s64) - ; CHECK: early-clobber %13:gpr64(s64), early-clobber %14:gpr64(s64), early-clobber %16:gpr32common = CMP_SWAP_128_ACQUIRE [[COPY]](p0), [[COPY5]](s64), [[COPY6]](s64), [[COPY7]](s64), [[COPY8]](s64) :: (load store acquire acquire 16) - ; CHECK: [[COPY9:%[0-9]+]]:gpr64 = COPY %16 - ; CHECK: [[MV:%[0-9]+]]:_(s128) = G_MERGE_VALUES %13(s64), %14(s64) - ; CHECK: G_STORE [[MV]](s128), [[COPY]](p0) :: (store 16) - ; CHECK: RET_ReallyLR ; CHECK-NOLSE-LABEL: name: compare_swap_128 ; CHECK-NOLSE: liveins: $x0_x1, $x1, $x0, $x1, $x2, $x3, $x4 ; CHECK-NOLSE-NEXT: {{ $}} @@ -40,11 +24,13 @@ body: | ; CHECK-NOLSE-NEXT: [[COPY6:%[0-9]+]]:gpr64(s64) = COPY [[COPY2]](s64) ; CHECK-NOLSE-NEXT: [[COPY7:%[0-9]+]]:gpr64(s64) = COPY [[COPY3]](s64) ; CHECK-NOLSE-NEXT: [[COPY8:%[0-9]+]]:gpr64(s64) = COPY [[COPY4]](s64) - ; CHECK-NOLSE-NEXT: early-clobber %13:gpr64common(s64), early-clobber %14:gpr64common(s64), early-clobber %16:gpr32common = CMP_SWAP_128_ACQUIRE [[COPY]](p0), [[COPY5]](s64), [[COPY6]](s64), [[COPY7]](s64), [[COPY8]](s64) :: (load store acquire acquire (s128)) - ; CHECK-NOLSE-NEXT: [[COPY9:%[0-9]+]]:gpr64 = COPY %16 - ; CHECK-NOLSE-NEXT: [[MV:%[0-9]+]]:_(s128) = G_MERGE_VALUES %13(s64), %14(s64) - ; CHECK-NOLSE-NEXT: G_STORE [[MV]](s128), [[COPY]](p0) :: (store (s128)) + ; CHECK-NOLSE-NEXT: early-clobber %14:gpr64common(s64), early-clobber %15:gpr64common(s64), early-clobber %17:gpr32common = CMP_SWAP_128_ACQUIRE [[COPY]](p0), [[COPY5]](s64), [[COPY6]](s64), [[COPY7]](s64), [[COPY8]](s64) :: (load store acquire acquire (s128)) + ; CHECK-NOLSE-NEXT: [[COPY9:%[0-9]+]]:gpr64 = COPY %17 + ; CHECK-NOLSE-NEXT: [[MV:%[0-9]+]]:_(s128) = G_MERGE_VALUES %14(s64), %15(s64) + ; CHECK-NOLSE-NEXT: [[COPY10:%[0-9]+]]:_(s128) = COPY [[MV]](s128) + ; CHECK-NOLSE-NEXT: G_STORE [[COPY10]](s128), [[COPY]](p0) :: (store (s128)) ; CHECK-NOLSE-NEXT: RET_ReallyLR + ; ; CHECK-LSE-LABEL: name: compare_swap_128 ; CHECK-LSE: liveins: $x0_x1, $x1, $x0, $x1, $x2, $x3, $x4 ; CHECK-LSE-NEXT: {{ $}} @@ -59,7 +45,8 @@ body: | ; CHECK-LSE-NEXT: [[EXTRACT:%[0-9]+]]:_(s64) = G_EXTRACT [[CASPAX]](s128), 0 ; CHECK-LSE-NEXT: [[EXTRACT1:%[0-9]+]]:_(s64) = G_EXTRACT [[CASPAX]](s128), 64 ; CHECK-LSE-NEXT: [[MV:%[0-9]+]]:_(s128) = G_MERGE_VALUES [[EXTRACT]](s64), [[EXTRACT1]](s64) - ; CHECK-LSE-NEXT: G_STORE [[MV]](s128), [[COPY]](p0) :: (store (s128)) + ; CHECK-LSE-NEXT: [[COPY5:%[0-9]+]]:_(s128) = COPY [[MV]](s128) + ; CHECK-LSE-NEXT: G_STORE [[COPY5]](s128), [[COPY]](p0) :: (store (s128)) ; CHECK-LSE-NEXT: RET_ReallyLR %0:_(p0) = COPY $x0 %3:_(s64) = COPY $x1 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-cmpxchg-with-success.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-cmpxchg-with-success.mir index 3c010789a2b7f97e8098b89ebfd5c9179a114d6b..05e6212af0620a19822063dd6506292d55ce564a 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-cmpxchg-with-success.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-cmpxchg-with-success.mir @@ -16,13 +16,16 @@ body: | liveins: $x0 ; CHECK-LABEL: name: cmpxchg_i32 - ; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 - ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 - ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 - ; CHECK: [[ATOMIC_CMPXCHG:%[0-9]+]]:_(s32) = G_ATOMIC_CMPXCHG [[COPY]](p0), [[C]], [[C1]] :: (load store monotonic (s64) on %ir.addr) - ; CHECK: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[ATOMIC_CMPXCHG]](s32), [[C]] - ; CHECK: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[ATOMIC_CMPXCHG]], [[ICMP]] - ; CHECK: $w0 = COPY [[MUL]](s32) + ; CHECK: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: [[ATOMIC_CMPXCHG:%[0-9]+]]:_(s32) = G_ATOMIC_CMPXCHG [[COPY]](p0), [[C]], [[C1]] :: (load store monotonic (s64) on %ir.addr) + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[ATOMIC_CMPXCHG]](s32), [[C]] + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY [[ATOMIC_CMPXCHG]](s32) + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[COPY1]], [[ICMP]] + ; CHECK-NEXT: $w0 = COPY [[MUL]](s32) %0:_(p0) = COPY $x0 %1:_(s32) = G_CONSTANT i32 0 %2:_(s32) = G_CONSTANT i32 1 @@ -40,14 +43,17 @@ body: | liveins: $x0 ; CHECK-LABEL: name: cmpxchg_i64 - ; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 - ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 - ; CHECK: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 - ; CHECK: [[ATOMIC_CMPXCHG:%[0-9]+]]:_(s64) = G_ATOMIC_CMPXCHG [[COPY]](p0), [[C]], [[C1]] :: (load store monotonic (s64) on %ir.addr) - ; CHECK: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[ATOMIC_CMPXCHG]](s64), [[C]] - ; CHECK: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[ICMP]](s32) - ; CHECK: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[ATOMIC_CMPXCHG]], [[ANYEXT]] - ; CHECK: $x0 = COPY [[MUL]](s64) + ; CHECK: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 + ; CHECK-NEXT: [[ATOMIC_CMPXCHG:%[0-9]+]]:_(s64) = G_ATOMIC_CMPXCHG [[COPY]](p0), [[C]], [[C1]] :: (load store monotonic (s64) on %ir.addr) + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[ATOMIC_CMPXCHG]](s64), [[C]] + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY [[ATOMIC_CMPXCHG]](s64) + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[ICMP]](s32) + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[COPY1]], [[ANYEXT]] + ; CHECK-NEXT: $x0 = COPY [[MUL]](s64) %0:_(p0) = COPY $x0 %1:_(s64) = G_CONSTANT i64 0 %2:_(s64) = G_CONSTANT i64 1 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-ctpop-no-implicit-float.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-ctpop-no-implicit-float.mir index d2352be81503dfff79caeaf8fd1347cb555dd866..27f2f0bafa95a96e2c7a1c771e84de9350c2e6cc 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-ctpop-no-implicit-float.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-ctpop-no-implicit-float.mir @@ -37,6 +37,7 @@ body: | ; CHECK-NEXT: %ctpop:_(s32) = G_LSHR [[MUL]], [[C7]](s64) ; CHECK-NEXT: $w0 = COPY %ctpop(s32) ; CHECK-NEXT: RET_ReallyLR implicit $w0 + ; ; CHECK-CSSC-LABEL: name: s32 ; CHECK-CSSC: liveins: $w0 ; CHECK-CSSC-NEXT: {{ $}} @@ -77,11 +78,12 @@ body: | ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s64) = G_CONSTANT i64 1085102592571150095 ; CHECK-NEXT: [[AND3:%[0-9]+]]:_(s64) = G_AND [[ADD1]], [[C5]] ; CHECK-NEXT: [[C6:%[0-9]+]]:_(s64) = G_CONSTANT i64 72340172838076673 - ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[AND3]], [[C6]] ; CHECK-NEXT: [[C7:%[0-9]+]]:_(s64) = G_CONSTANT i64 56 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[AND3]], [[C6]] ; CHECK-NEXT: %ctpop:_(s64) = G_LSHR [[MUL]], [[C7]](s64) ; CHECK-NEXT: $x0 = COPY %ctpop(s64) ; CHECK-NEXT: RET_ReallyLR implicit $x0 + ; ; CHECK-CSSC-LABEL: name: s64 ; CHECK-CSSC: liveins: $x0 ; CHECK-CSSC-NEXT: {{ $}} diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-exceptions.ll b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-exceptions.ll index 5662de4cbdca527e841ca208989f04010a734321..f7550ceb2799a59219767a4cbfb147ddbacd90d4 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-exceptions.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-exceptions.ll @@ -48,7 +48,7 @@ define void @bar() personality ptr @__gxx_personality_v0 { ; CHECK-NEXT: $x0 = COPY [[LOAD]](p0) ; CHECK-NEXT: BL @_Unwind_Resume, csr_darwin_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x0 ; CHECK-NEXT: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp - ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + ; CHECK-NEXT: G_TRAP %exn.slot = alloca ptr %ehselector.slot = alloca i32 %1 = invoke i32 @foo(i32 42) to label %continue unwind label %cleanup diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-insert-vector-elt.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-insert-vector-elt.mir index e12353c7ef5bec2d78464990d771a62dff035fe0..d3db2432e84cbc8dfcdc940fdc28d850c1467c57 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-insert-vector-elt.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-insert-vector-elt.mir @@ -235,31 +235,32 @@ body: | ; CHECK-NEXT: successors: %bb.1(0x80000000) ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) + ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY2]](s32) + ; CHECK-NEXT: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[COPY3]](s32) ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(s8) = G_IMPLICIT_DEF - ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) - ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY2]](s32) - ; CHECK-NEXT: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[COPY3]](s32) - ; CHECK-NEXT: [[DEF2:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[TRUNC]](s16), [[TRUNC1]](s16), [[TRUNC2]](s16), [[DEF2]](s16) + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<8 x s8>) = G_BUILD_VECTOR [[TRUNC]](s8), [[TRUNC1]](s8), [[TRUNC2]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8) + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(<8 x s16>) = G_ANYEXT [[BUILD_VECTOR]](<8 x s8>) + ; CHECK-NEXT: [[UV:%[0-9]+]]:_(<4 x s16>), [[UV1:%[0-9]+]]:_(<4 x s16>) = G_UNMERGE_VALUES [[ANYEXT]](<8 x s16>) ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s16) = G_CONSTANT i16 0 - ; CHECK-NEXT: [[IVEC:%[0-9]+]]:_(<4 x s16>) = G_INSERT_VECTOR_ELT [[BUILD_VECTOR]], [[C2]](s16), [[C1]](s64) - ; CHECK-NEXT: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[IVEC]](<4 x s16>) - ; CHECK-NEXT: [[TRUNC3:%[0-9]+]]:_(s8) = G_TRUNC [[UV]](s16) - ; CHECK-NEXT: [[TRUNC4:%[0-9]+]]:_(s8) = G_TRUNC [[UV1]](s16) - ; CHECK-NEXT: [[TRUNC5:%[0-9]+]]:_(s8) = G_TRUNC [[UV2]](s16) + ; CHECK-NEXT: [[IVEC:%[0-9]+]]:_(<4 x s16>) = G_INSERT_VECTOR_ELT [[UV]], [[C2]](s16), [[C1]](s64) + ; CHECK-NEXT: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[IVEC]](<4 x s16>) + ; CHECK-NEXT: [[TRUNC3:%[0-9]+]]:_(s8) = G_TRUNC [[UV2]](s16) + ; CHECK-NEXT: [[TRUNC4:%[0-9]+]]:_(s8) = G_TRUNC [[UV3]](s16) + ; CHECK-NEXT: [[TRUNC5:%[0-9]+]]:_(s8) = G_TRUNC [[UV4]](s16) ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<16 x s8>) = G_BUILD_VECTOR [[TRUNC3]](s8), [[TRUNC4]](s8), [[TRUNC5]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8) ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<16 x s8>) = G_BUILD_VECTOR [[C]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8) ; CHECK-NEXT: [[SHUF:%[0-9]+]]:_(<16 x s8>) = G_SHUFFLE_VECTOR [[BUILD_VECTOR1]](<16 x s8>), [[BUILD_VECTOR2]], shufflemask(0, 16, 16, 16, 1, 16, 16, 16, 2, 16, 16, 16, undef, undef, undef, undef) ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<4 x s32>) = G_BITCAST [[SHUF]](<16 x s8>) ; CHECK-NEXT: [[UITOFP:%[0-9]+]]:_(<4 x s32>) = G_UITOFP [[BITCAST]](<4 x s32>) - ; CHECK-NEXT: [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32), [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[UITOFP]](<4 x s32>) - ; CHECK-NEXT: G_STORE [[UV4]](s32), [[COPY]](p0) :: (store (s32), align 16) + ; CHECK-NEXT: [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32), [[UV8:%[0-9]+]]:_(s32), [[UV9:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[UITOFP]](<4 x s32>) + ; CHECK-NEXT: G_STORE [[UV6]](s32), [[COPY]](p0) :: (store (s32), align 16) ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 4 ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C3]](s64) - ; CHECK-NEXT: G_STORE [[UV5]](s32), [[PTR_ADD]](p0) :: (store (s32) into unknown-address + 4) + ; CHECK-NEXT: G_STORE [[UV7]](s32), [[PTR_ADD]](p0) :: (store (s32) into unknown-address + 4) ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s64) = G_CONSTANT i64 8 ; CHECK-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C4]](s64) - ; CHECK-NEXT: G_STORE [[UV6]](s32), [[PTR_ADD1]](p0) :: (store (s32) into unknown-address + 8, align 8) + ; CHECK-NEXT: G_STORE [[UV8]](s32), [[PTR_ADD1]](p0) :: (store (s32) into unknown-address + 8, align 8) ; CHECK-NEXT: G_BR %bb.1 bb.1: liveins: $w1, $w2, $w3, $x0 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir index 5cbb8649d158b0e76799181d9c97ef47808553f0..b8328eda9a66189703685833e3c86ba7fe39ae3f 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir @@ -607,9 +607,11 @@ body: | ; CHECK-NEXT: [[LOAD1:%[0-9]+]]:_(s16) = G_LOAD [[PTR_ADD]](p0) :: (load (s16) from unknown-address + 2) ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[LOAD]](s16) ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[LOAD1]](s16) - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[ANYEXT]](s32), [[ANYEXT1]](s32) - ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<2 x s16>) = G_TRUNC [[BUILD_VECTOR]](<2 x s32>) - ; CHECK-NEXT: $s0 = COPY [[TRUNC]](<2 x s16>) + ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[ANYEXT]](s32), [[ANYEXT1]](s32), [[DEF]](s32), [[DEF]](s32) + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<4 x s16>) = G_TRUNC [[BUILD_VECTOR]](<4 x s32>) + ; CHECK-NEXT: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[TRUNC]](<4 x s16>) + ; CHECK-NEXT: $s0 = COPY [[UV]](<2 x s16>) ; CHECK-NEXT: RET_ReallyLR %0:_(p0) = COPY $x0 %1(<2 x s16>) = G_LOAD %0(p0) :: (load (<2 x s16>)) @@ -711,33 +713,24 @@ body: | ; CHECK: liveins: $x0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: %ptr:_(p0) = COPY $x0 - ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD %ptr(p0) :: (load (p0), align 64) - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 8 + ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(<2 x s64>) = G_LOAD %ptr(p0) :: (load (<2 x s64>), align 64) + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[LOAD]](<2 x s64>) + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 16 ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD %ptr, [[C]](s64) - ; CHECK-NEXT: [[LOAD1:%[0-9]+]]:_(p0) = G_LOAD [[PTR_ADD]](p0) :: (load (p0) from unknown-address + 8) - ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 16 + ; CHECK-NEXT: [[LOAD1:%[0-9]+]]:_(<2 x s64>) = G_LOAD [[PTR_ADD]](p0) :: (load (<2 x s64>) from unknown-address + 16) + ; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[LOAD1]](<2 x s64>) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 32 ; CHECK-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD %ptr, [[C1]](s64) - ; CHECK-NEXT: [[LOAD2:%[0-9]+]]:_(p0) = G_LOAD [[PTR_ADD1]](p0) :: (load (p0) from unknown-address + 16, align 16) - ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 24 - ; CHECK-NEXT: [[PTR_ADD2:%[0-9]+]]:_(p0) = G_PTR_ADD %ptr, [[C2]](s64) - ; CHECK-NEXT: [[LOAD3:%[0-9]+]]:_(p0) = G_LOAD [[PTR_ADD2]](p0) :: (load (p0) from unknown-address + 24) - ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 32 - ; CHECK-NEXT: [[PTR_ADD3:%[0-9]+]]:_(p0) = G_PTR_ADD %ptr, [[C3]](s64) - ; CHECK-NEXT: [[LOAD4:%[0-9]+]]:_(p0) = G_LOAD [[PTR_ADD3]](p0) :: (load (p0) from unknown-address + 32, align 32) - ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s64) = G_CONSTANT i64 40 - ; CHECK-NEXT: [[PTR_ADD4:%[0-9]+]]:_(p0) = G_PTR_ADD %ptr, [[C4]](s64) - ; CHECK-NEXT: [[LOAD5:%[0-9]+]]:_(p0) = G_LOAD [[PTR_ADD4]](p0) :: (load (p0) from unknown-address + 40) - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x p0>) = G_BUILD_VECTOR [[LOAD]](p0), [[LOAD1]](p0) - ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<2 x p0>) = G_BUILD_VECTOR [[LOAD2]](p0), [[LOAD3]](p0) - ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<2 x p0>) = G_BUILD_VECTOR [[LOAD4]](p0), [[LOAD5]](p0) - ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<2 x s64>) = G_BITCAST [[BUILD_VECTOR]](<2 x p0>) - ; CHECK-NEXT: G_STORE [[BITCAST]](<2 x s64>), %ptr(p0) :: (store (<2 x s64>), align 64) - ; CHECK-NEXT: [[PTR_ADD5:%[0-9]+]]:_(p0) = G_PTR_ADD %ptr, [[C1]](s64) - ; CHECK-NEXT: [[BITCAST1:%[0-9]+]]:_(<2 x s64>) = G_BITCAST [[BUILD_VECTOR1]](<2 x p0>) - ; CHECK-NEXT: G_STORE [[BITCAST1]](<2 x s64>), [[PTR_ADD5]](p0) :: (store (<2 x s64>) into unknown-address + 16) - ; CHECK-NEXT: [[PTR_ADD6:%[0-9]+]]:_(p0) = G_PTR_ADD %ptr, [[C3]](s64) - ; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<2 x s64>) = G_BITCAST [[BUILD_VECTOR2]](<2 x p0>) - ; CHECK-NEXT: G_STORE [[BITCAST2]](<2 x s64>), [[PTR_ADD6]](p0) :: (store (<2 x s64>) into unknown-address + 32, align 32) + ; CHECK-NEXT: [[LOAD2:%[0-9]+]]:_(<2 x s64>) = G_LOAD [[PTR_ADD1]](p0) :: (load (<2 x s64>) from unknown-address + 32, align 32) + ; CHECK-NEXT: [[BITCAST2:%[0-9]+]]:_(<2 x p0>) = G_BITCAST [[LOAD2]](<2 x s64>) + ; CHECK-NEXT: [[BITCAST3:%[0-9]+]]:_(<2 x s64>) = G_BITCAST [[BITCAST]](<2 x p0>) + ; CHECK-NEXT: G_STORE [[BITCAST3]](<2 x s64>), %ptr(p0) :: (store (<2 x s64>), align 64) + ; CHECK-NEXT: [[PTR_ADD2:%[0-9]+]]:_(p0) = G_PTR_ADD %ptr, [[C]](s64) + ; CHECK-NEXT: [[BITCAST4:%[0-9]+]]:_(<2 x s64>) = G_BITCAST [[BITCAST1]](<2 x p0>) + ; CHECK-NEXT: G_STORE [[BITCAST4]](<2 x s64>), [[PTR_ADD2]](p0) :: (store (<2 x s64>) into unknown-address + 16) + ; CHECK-NEXT: [[PTR_ADD3:%[0-9]+]]:_(p0) = G_PTR_ADD %ptr, [[C1]](s64) + ; CHECK-NEXT: [[BITCAST5:%[0-9]+]]:_(<2 x s64>) = G_BITCAST [[BITCAST2]](<2 x p0>) + ; CHECK-NEXT: G_STORE [[BITCAST5]](<2 x s64>), [[PTR_ADD3]](p0) :: (store (<2 x s64>) into unknown-address + 32, align 32) ; CHECK-NEXT: RET_ReallyLR %ptr:_(p0) = COPY $x0 %val:_(<6 x p0>) = G_LOAD %ptr(p0) :: (load (<6 x p0>)) diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-select.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-select.mir index 63a26dcfea4762ea4a93f2e98e4b7de63b09cdbb..e49a94c12ed468b0dedea4a432f2c215c36fd1e0 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-select.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-select.mir @@ -293,41 +293,44 @@ body: | ; CHECK-NEXT: [[ICMP2:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), %w0(s32), [[C]] ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[ICMP2]], 1 ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s8) = G_IMPLICIT_DEF - ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF - ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s16) = COPY [[DEF1]](s16) - ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s16) = COPY [[DEF1]](s16) - ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s16) = COPY [[DEF1]](s16) - ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[COPY]](s16), [[COPY1]](s16), [[COPY2]](s16), [[DEF1]](s16) ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(s8) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<8 x s8>) = G_BUILD_VECTOR [[DEF]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8) + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(<8 x s16>) = G_ANYEXT [[BUILD_VECTOR]](<8 x s8>) + ; CHECK-NEXT: [[UV:%[0-9]+]]:_(<4 x s16>), [[UV1:%[0-9]+]]:_(<4 x s16>) = G_UNMERGE_VALUES [[ANYEXT]](<8 x s16>) ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[SEXT_INREG]](s32) - ; CHECK-NEXT: [[IVEC:%[0-9]+]]:_(<4 x s16>) = G_INSERT_VECTOR_ELT [[BUILD_VECTOR]], [[TRUNC]](s16), [[C1]](s64) - ; CHECK-NEXT: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[IVEC]](<4 x s16>) - ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[UV]](s16) - ; CHECK-NEXT: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[UV1]](s16) - ; CHECK-NEXT: [[TRUNC3:%[0-9]+]]:_(s8) = G_TRUNC [[UV2]](s16) - ; CHECK-NEXT: [[TRUNC4:%[0-9]+]]:_(s8) = G_TRUNC [[UV3]](s16) - ; CHECK-NEXT: [[DEF2:%[0-9]+]]:_(s8) = G_IMPLICIT_DEF - ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<8 x s8>) = G_BUILD_VECTOR [[TRUNC1]](s8), [[TRUNC2]](s8), [[TRUNC3]](s8), [[TRUNC4]](s8), [[DEF2]](s8), [[DEF2]](s8), [[DEF2]](s8), [[DEF2]](s8) - ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<8 x s8>) = G_BUILD_VECTOR [[DEF]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF2]](s8), [[DEF2]](s8), [[DEF2]](s8), [[DEF2]](s8) + ; CHECK-NEXT: [[IVEC:%[0-9]+]]:_(<4 x s16>) = G_INSERT_VECTOR_ELT [[UV]], [[TRUNC]](s16), [[C1]](s64) + ; CHECK-NEXT: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[IVEC]](<4 x s16>) + ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[UV2]](s16) + ; CHECK-NEXT: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[UV3]](s16) + ; CHECK-NEXT: [[TRUNC3:%[0-9]+]]:_(s8) = G_TRUNC [[UV4]](s16) + ; CHECK-NEXT: [[TRUNC4:%[0-9]+]]:_(s8) = G_TRUNC [[UV5]](s16) + ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<8 x s8>) = G_BUILD_VECTOR [[TRUNC1]](s8), [[TRUNC2]](s8), [[TRUNC3]](s8), [[TRUNC4]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8) + ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<8 x s8>) = G_BUILD_VECTOR [[DEF]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8) ; CHECK-NEXT: [[SHUF:%[0-9]+]]:_(<8 x s8>) = G_SHUFFLE_VECTOR [[BUILD_VECTOR1]](<8 x s8>), [[BUILD_VECTOR2]], shufflemask(0, 0, 0, 0, undef, undef, undef, undef) - ; CHECK-NEXT: [[UV4:%[0-9]+]]:_(<4 x s8>), [[UV5:%[0-9]+]]:_(<4 x s8>) = G_UNMERGE_VALUES [[SHUF]](<8 x s8>) - ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s16) = G_CONSTANT i16 1 - ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s16) = COPY [[C2]](s16) - ; CHECK-NEXT: [[COPY4:%[0-9]+]]:_(s16) = COPY [[C2]](s16) - ; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(s16) = COPY [[C2]](s16) - ; CHECK-NEXT: [[BUILD_VECTOR3:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[COPY3]](s16), [[COPY4]](s16), [[COPY5]](s16), [[C2]](s16) - ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(<4 x s16>) = G_ANYEXT [[UV4]](<4 x s8>) - ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(<4 x s16>) = G_XOR [[ANYEXT]], [[BUILD_VECTOR3]] + ; CHECK-NEXT: [[UV6:%[0-9]+]]:_(<4 x s8>), [[UV7:%[0-9]+]]:_(<4 x s8>) = G_UNMERGE_VALUES [[SHUF]](<8 x s8>) + ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s8) = G_CONSTANT i8 1 + ; CHECK-NEXT: [[UV8:%[0-9]+]]:_(s8), [[UV9:%[0-9]+]]:_(s8), [[UV10:%[0-9]+]]:_(s8), [[UV11:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[UV6]](<4 x s8>) + ; CHECK-NEXT: [[BUILD_VECTOR3:%[0-9]+]]:_(<8 x s8>) = G_BUILD_VECTOR [[UV8]](s8), [[UV9]](s8), [[UV10]](s8), [[UV11]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8) + ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(<8 x s16>) = G_ANYEXT [[BUILD_VECTOR3]](<8 x s8>) + ; CHECK-NEXT: [[UV12:%[0-9]+]]:_(<4 x s16>), [[UV13:%[0-9]+]]:_(<4 x s16>) = G_UNMERGE_VALUES [[ANYEXT1]](<8 x s16>) + ; CHECK-NEXT: [[BUILD_VECTOR4:%[0-9]+]]:_(<8 x s8>) = G_BUILD_VECTOR [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8) + ; CHECK-NEXT: [[ANYEXT2:%[0-9]+]]:_(<8 x s16>) = G_ANYEXT [[BUILD_VECTOR4]](<8 x s8>) + ; CHECK-NEXT: [[UV14:%[0-9]+]]:_(<4 x s16>), [[UV15:%[0-9]+]]:_(<4 x s16>) = G_UNMERGE_VALUES [[ANYEXT2]](<8 x s16>) + ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(<4 x s16>) = G_XOR [[UV12]], [[UV14]] ; CHECK-NEXT: [[TRUNC5:%[0-9]+]]:_(<4 x s16>) = G_TRUNC [[ICMP]](<4 x s32>) - ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(<4 x s16>) = G_ANYEXT [[UV4]](<4 x s8>) - ; CHECK-NEXT: [[AND:%[0-9]+]]:_(<4 x s16>) = G_AND [[TRUNC5]], [[ANYEXT1]] + ; CHECK-NEXT: [[UV16:%[0-9]+]]:_(s8), [[UV17:%[0-9]+]]:_(s8), [[UV18:%[0-9]+]]:_(s8), [[UV19:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[UV6]](<4 x s8>) + ; CHECK-NEXT: [[BUILD_VECTOR5:%[0-9]+]]:_(<8 x s8>) = G_BUILD_VECTOR [[UV16]](s8), [[UV17]](s8), [[UV18]](s8), [[UV19]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8) + ; CHECK-NEXT: [[ANYEXT3:%[0-9]+]]:_(<8 x s16>) = G_ANYEXT [[BUILD_VECTOR5]](<8 x s8>) + ; CHECK-NEXT: [[UV20:%[0-9]+]]:_(<4 x s16>), [[UV21:%[0-9]+]]:_(<4 x s16>) = G_UNMERGE_VALUES [[ANYEXT3]](<8 x s16>) + ; CHECK-NEXT: [[AND:%[0-9]+]]:_(<4 x s16>) = G_AND [[TRUNC5]], [[UV20]] ; CHECK-NEXT: [[TRUNC6:%[0-9]+]]:_(<4 x s16>) = G_TRUNC [[ICMP1]](<4 x s32>) ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(<4 x s16>) = G_AND [[TRUNC6]], [[XOR]] ; CHECK-NEXT: [[OR:%[0-9]+]]:_(<4 x s16>) = G_OR [[AND]], [[AND1]] - ; CHECK-NEXT: [[ANYEXT2:%[0-9]+]]:_(<4 x s32>) = G_ANYEXT [[OR]](<4 x s16>) + ; CHECK-NEXT: [[ANYEXT4:%[0-9]+]]:_(<4 x s32>) = G_ANYEXT [[OR]](<4 x s16>) ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 - ; CHECK-NEXT: [[BUILD_VECTOR4:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C3]](s32), [[C3]](s32), [[C3]](s32), [[C3]](s32) - ; CHECK-NEXT: %zext_select:_(<4 x s32>) = G_AND [[ANYEXT2]], [[BUILD_VECTOR4]] + ; CHECK-NEXT: [[BUILD_VECTOR6:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C3]](s32), [[C3]](s32), [[C3]](s32), [[C3]](s32) + ; CHECK-NEXT: %zext_select:_(<4 x s32>) = G_AND [[ANYEXT4]], [[BUILD_VECTOR6]] ; CHECK-NEXT: $q0 = COPY %zext_select(<4 x s32>) ; CHECK-NEXT: RET_ReallyLR implicit $q0 %w0:_(s32) = COPY $w0 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-shuffle-vector-widen-crash.ll b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-shuffle-vector-widen-crash.ll index 42a8f51002f20072f93090e56fcb9e91b26f8fc6..f7efaeaa507053fe0d62db6e7ba5872bdb4d5dac 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-shuffle-vector-widen-crash.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-shuffle-vector-widen-crash.ll @@ -1,16 +1,24 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 -; RUN: llc -global-isel-abort=2 -global-isel -o - %s | FileCheck %s +; RUN: llc -global-isel -o - %s | FileCheck %s target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" target triple = "arm64-apple-macosx11.0.0" declare i32 @llvm.aarch64.neon.uaddv.i32.v4i32(<4 x i32>) #0 -; This test currently falls back but ensures we don't crash. - define i32 @bar() { ; CHECK-LABEL: bar: ; CHECK: ; %bb.0: ; %bb ; CHECK-NEXT: movi.2d v0, #0000000000000000 +; CHECK-NEXT: mov b1, v0[1] +; CHECK-NEXT: mov b2, v0[2] +; CHECK-NEXT: mov b3, v0[3] +; CHECK-NEXT: mov.h v0[1], v1[0] +; CHECK-NEXT: mov.h v2[1], v3[0] +; CHECK-NEXT: ushll.4s v0, v0, #0 +; CHECK-NEXT: ushll.4s v1, v2, #0 +; CHECK-NEXT: mov.d v0[1], v1[0] +; CHECK-NEXT: movi.4s v1, #1 +; CHECK-NEXT: and.16b v0, v0, v1 ; CHECK-NEXT: addv.4s s0, v0 ; CHECK-NEXT: fmov w0, s0 ; CHECK-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-xtn.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-xtn.mir index 661265173ae82b6bdfb0a6ced20cfc74607690ac..e729f027baa71581f43d5f1c1eaecd876958d587 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-xtn.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-xtn.mir @@ -540,10 +540,14 @@ body: | ; CHECK: liveins: $d0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d0 - ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(<2 x s8>) = G_TRUNC [[COPY]](<2 x s32>) - ; CHECK-NEXT: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x s8>) = G_CONCAT_VECTORS [[TRUNC]](<2 x s8>), [[TRUNC]](<2 x s8>) - ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(<4 x s16>) = G_ANYEXT [[CONCAT_VECTORS]](<4 x s8>) - ; CHECK-NEXT: $d0 = COPY [[ANYEXT]](<4 x s16>) + ; CHECK-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[UV]](s32) + ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[UV1]](s32) + ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s8) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<8 x s8>) = G_BUILD_VECTOR [[TRUNC]](s8), [[TRUNC1]](s8), [[TRUNC]](s8), [[TRUNC1]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF]](s8), [[DEF]](s8) + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(<8 x s16>) = G_ANYEXT [[BUILD_VECTOR]](<8 x s8>) + ; CHECK-NEXT: [[UV2:%[0-9]+]]:_(<4 x s16>), [[UV3:%[0-9]+]]:_(<4 x s16>) = G_UNMERGE_VALUES [[ANYEXT]](<8 x s16>) + ; CHECK-NEXT: $d0 = COPY [[UV2]](<4 x s16>) ; CHECK-NEXT: RET_ReallyLR implicit $d0 %0:_(<2 x s32>) = COPY $d0 %1:_(<2 x s8>) = G_TRUNC %0(<2 x s32>) diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir index c9e5f8924f8a0e7222399afbae0e29307a0f0a28..ac3c47c8001d4a4764c1ea78200828d173b9c848 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir @@ -752,6 +752,15 @@ # DEBUG-NEXT: G_BZERO (opcode {{[0-9]+}}): 2 type indices, 1 imm index # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected +# DEBUG-NEXT: G_TRAP (opcode {{[0-9]+}}): 0 type indices, 0 imm indices +# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined +# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined +# DEBUG-NEXT: G_DEBUGTRAP (opcode {{[0-9]+}}): 0 type indices, 0 imm indices +# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined +# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined +# DEBUG-NEXT: G_UBSANTRAP (opcode {{[0-9]+}}): 0 type indices, 0 imm indices +# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined +# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined # DEBUG-NEXT: G_VECREDUCE_SEQ_FADD (opcode {{[0-9]+}}): 3 type indices, 0 imm indices # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/load-addressing-modes.mir b/llvm/test/CodeGen/AArch64/GlobalISel/load-addressing-modes.mir index 0cf9602adbb09472737e350a15e7962fef0b3f42..499c08fa4966f97eff9bb7d3f7fd47ee48922ff4 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/load-addressing-modes.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/load-addressing-modes.mir @@ -40,11 +40,12 @@ body: | ; CHECK-LABEL: name: ldrxrox_breg_oreg ; CHECK: liveins: $x0, $x1 - ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY]], [[COPY1]], 0, 0 :: (load (s64) from %ir.addr) - ; CHECK: $x0 = COPY [[LDRXroX]] - ; CHECK: RET_ReallyLR implicit $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY]], [[COPY1]], 0, 0 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $x0 = COPY [[LDRXroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $x0 %0:gpr(p0) = COPY $x0 %1:gpr(s64) = COPY $x1 %2:gpr(p0) = G_PTR_ADD %0, %1 @@ -65,11 +66,12 @@ body: | liveins: $d0, $x1 ; CHECK-LABEL: name: ldrdrox_breg_oreg ; CHECK: liveins: $d0, $x1 - ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $d0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY]], [[COPY1]], 0, 0 :: (load (s64) from %ir.addr) - ; CHECK: $d0 = COPY [[LDRDroX]] - ; CHECK: RET_ReallyLR implicit $d0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64sp = COPY $d0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY]], [[COPY1]], 0, 0 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $d0 = COPY [[LDRDroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $d0 %0:gpr(p0) = COPY $d0 %1:gpr(s64) = COPY $x1 %2:gpr(p0) = G_PTR_ADD %0, %1 @@ -78,6 +80,9 @@ body: | RET_ReallyLR implicit $d0 ... --- +# This shouldn't be folded, since we reuse the result of the G_PTR_ADD outside +# the G_LOAD + name: more_than_one_use alignment: 4 legalized: true @@ -87,18 +92,17 @@ machineFunctionInfo: {} body: | bb.0: liveins: $x0, $x1 - ; This shouldn't be folded, since we reuse the result of the G_PTR_ADD outside - ; the G_LOAD ; CHECK-LABEL: name: more_than_one_use ; CHECK: liveins: $x0, $x1 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[ADDXrr:%[0-9]+]]:gpr64common = ADDXrr [[COPY]], [[COPY1]] - ; CHECK: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADDXrr]], 0 :: (load (s64) from %ir.addr) - ; CHECK: [[COPY2:%[0-9]+]]:gpr64 = COPY [[ADDXrr]] - ; CHECK: [[ADDXrr1:%[0-9]+]]:gpr64 = ADDXrr [[COPY2]], [[LDRXui]] - ; CHECK: $x0 = COPY [[ADDXrr1]] - ; CHECK: RET_ReallyLR implicit $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[ADDXrr:%[0-9]+]]:gpr64common = ADDXrr [[COPY]], [[COPY1]] + ; CHECK-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADDXrr]], 0 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr64 = COPY [[ADDXrr]] + ; CHECK-NEXT: [[ADDXrr1:%[0-9]+]]:gpr64 = ADDXrr [[COPY2]], [[LDRXui]] + ; CHECK-NEXT: $x0 = COPY [[ADDXrr1]] + ; CHECK-NEXT: RET_ReallyLR implicit $x0 %0:gpr(p0) = COPY $x0 %1:gpr(s64) = COPY $x1 %2:gpr(p0) = G_PTR_ADD %0, %1 @@ -121,11 +125,12 @@ body: | liveins: $x0, $x1, $x2 ; CHECK-LABEL: name: ldrxrox_shl ; CHECK: liveins: $x0, $x1, $x2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) - ; CHECK: $x2 = COPY [[LDRXroX]] - ; CHECK: RET_ReallyLR implicit $x2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $x2 = COPY [[LDRXroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $x2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 3 %2:gpr(s64) = G_SHL %0, %1(s64) @@ -148,11 +153,12 @@ body: | liveins: $x0, $x1, $d2 ; CHECK-LABEL: name: ldrdrox_shl ; CHECK: liveins: $x0, $x1, $d2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) - ; CHECK: $d2 = COPY [[LDRDroX]] - ; CHECK: RET_ReallyLR implicit $d2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $d2 = COPY [[LDRDroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $d2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 3 %2:gpr(s64) = G_SHL %0, %1(s64) @@ -175,11 +181,12 @@ body: | liveins: $x0, $x1, $x2 ; CHECK-LABEL: name: ldrxrox_mul_rhs ; CHECK: liveins: $x0, $x1, $x2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) - ; CHECK: $x2 = COPY [[LDRXroX]] - ; CHECK: RET_ReallyLR implicit $x2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $x2 = COPY [[LDRXroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $x2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 8 %2:gpr(s64) = G_MUL %0, %1(s64) @@ -202,11 +209,12 @@ body: | liveins: $x0, $x1, $d2 ; CHECK-LABEL: name: ldrdrox_mul_rhs ; CHECK: liveins: $x0, $x1, $d2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) - ; CHECK: $d2 = COPY [[LDRDroX]] - ; CHECK: RET_ReallyLR implicit $d2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $d2 = COPY [[LDRDroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $d2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 8 %2:gpr(s64) = G_MUL %0, %1(s64) @@ -229,11 +237,12 @@ body: | liveins: $x0, $x1, $x2 ; CHECK-LABEL: name: ldrxrox_mul_lhs ; CHECK: liveins: $x0, $x1, $x2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) - ; CHECK: $x2 = COPY [[LDRXroX]] - ; CHECK: RET_ReallyLR implicit $x2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $x2 = COPY [[LDRXroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $x2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 8 %2:gpr(s64) = G_MUL %1, %0(s64) @@ -256,11 +265,12 @@ body: | liveins: $x0, $x1, $d2 ; CHECK-LABEL: name: ldrdrox_mul_lhs ; CHECK: liveins: $x0, $x1, $d2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) - ; CHECK: $d2 = COPY [[LDRDroX]] - ; CHECK: RET_ReallyLR implicit $d2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $d2 = COPY [[LDRDroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $d2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 8 %2:gpr(s64) = G_MUL %1, %0(s64) @@ -272,6 +282,9 @@ body: | ... --- +# Show that we don't get a shifted load from a mul when we don't have a +# power of 2. (The bit isn't set on the load.) + name: mul_not_pow_2 alignment: 4 legalized: true @@ -280,19 +293,18 @@ tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: - ; Show that we don't get a shifted load from a mul when we don't have a - ; power of 2. (The bit isn't set on the load.) liveins: $x0, $x1, $d2 ; CHECK-LABEL: name: mul_not_pow_2 ; CHECK: liveins: $x0, $x1, $d2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 7 - ; CHECK: [[SUBREG_TO_REG:%[0-9]+]]:gpr64 = SUBREG_TO_REG 0, [[MOVi32imm]], %subreg.sub_32 - ; CHECK: [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[SUBREG_TO_REG]], [[COPY]], $xzr - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[MADDXrrr]], 0, 0 :: (load (s64) from %ir.addr) - ; CHECK: $d2 = COPY [[LDRDroX]] - ; CHECK: RET_ReallyLR implicit $d2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 7 + ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gpr64 = SUBREG_TO_REG 0, [[MOVi32imm]], %subreg.sub_32 + ; CHECK-NEXT: [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[SUBREG_TO_REG]], [[COPY]], $xzr + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[MADDXrrr]], 0, 0 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $d2 = COPY [[LDRDroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $d2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 7 %2:gpr(s64) = G_MUL %1, %0(s64) @@ -304,6 +316,9 @@ body: | ... --- +# Show that we don't get a shifted load from a mul when we don't have +# the right power of 2. (The bit isn't set on the load.) + name: mul_wrong_pow_2 alignment: 4 legalized: true @@ -312,19 +327,18 @@ tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: - ; Show that we don't get a shifted load from a mul when we don't have - ; the right power of 2. (The bit isn't set on the load.) liveins: $x0, $x1, $d2 ; CHECK-LABEL: name: mul_wrong_pow_2 ; CHECK: liveins: $x0, $x1, $d2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 16 - ; CHECK: [[SUBREG_TO_REG:%[0-9]+]]:gpr64 = SUBREG_TO_REG 0, [[MOVi32imm]], %subreg.sub_32 - ; CHECK: [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[SUBREG_TO_REG]], [[COPY]], $xzr - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[MADDXrrr]], 0, 0 :: (load (s64) from %ir.addr) - ; CHECK: $d2 = COPY [[LDRDroX]] - ; CHECK: RET_ReallyLR implicit $d2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 16 + ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gpr64 = SUBREG_TO_REG 0, [[MOVi32imm]], %subreg.sub_32 + ; CHECK-NEXT: [[MADDXrrr:%[0-9]+]]:gpr64 = MADDXrrr [[SUBREG_TO_REG]], [[COPY]], $xzr + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRDroX:%[0-9]+]]:fpr64 = LDRDroX [[COPY1]], [[MADDXrrr]], 0, 0 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: $d2 = COPY [[LDRDroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $d2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 16 %2:gpr(s64) = G_MUL %1, %0(s64) @@ -336,6 +350,9 @@ body: | ... --- +# Show that we can still fall back to the register-register addressing +# mode when we fail to pull in the shift. + name: more_than_one_use_shl_1 alignment: 4 legalized: true @@ -344,19 +361,18 @@ tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: - ; Show that we can still fall back to the register-register addressing - ; mode when we fail to pull in the shift. liveins: $x0, $x1, $x2 ; CHECK-LABEL: name: more_than_one_use_shl_1 ; CHECK: liveins: $x0, $x1, $x2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[UBFMXri:%[0-9]+]]:gpr64common = UBFMXri [[COPY]], 61, 60 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[UBFMXri]], 0, 0 :: (load (s64) from %ir.addr) - ; CHECK: [[ADDXri:%[0-9]+]]:gpr64common = ADDXri [[UBFMXri]], 3, 0 - ; CHECK: [[ADDXrr:%[0-9]+]]:gpr64 = ADDXrr [[LDRXroX]], [[ADDXri]] - ; CHECK: $x2 = COPY [[ADDXrr]] - ; CHECK: RET_ReallyLR implicit $x2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[UBFMXri:%[0-9]+]]:gpr64common = UBFMXri [[COPY]], 61, 60 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[UBFMXri]], 0, 0 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: [[ADDXri:%[0-9]+]]:gpr64common = ADDXri [[UBFMXri]], 3, 0 + ; CHECK-NEXT: [[ADDXrr:%[0-9]+]]:gpr64 = ADDXrr [[LDRXroX]], [[ADDXri]] + ; CHECK-NEXT: $x2 = COPY [[ADDXrr]] + ; CHECK-NEXT: RET_ReallyLR implicit $x2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 3 %2:gpr(s64) = G_SHL %0, %1(s64) @@ -370,6 +386,9 @@ body: | ... --- +# Show that when the GEP is used outside a memory op, we don't do any +# folding at all. + name: more_than_one_use_shl_2 alignment: 4 legalized: true @@ -378,22 +397,21 @@ tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: - ; Show that when the GEP is used outside a memory op, we don't do any - ; folding at all. liveins: $x0, $x1, $x2 ; CHECK-LABEL: name: more_than_one_use_shl_2 ; CHECK: liveins: $x0, $x1, $x2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[UBFMXri:%[0-9]+]]:gpr64common = UBFMXri [[COPY]], 61, 60 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[ADDXrr:%[0-9]+]]:gpr64common = ADDXrr [[COPY1]], [[UBFMXri]] - ; CHECK: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADDXrr]], 0 :: (load (s64) from %ir.addr) - ; CHECK: [[ADDXri:%[0-9]+]]:gpr64common = ADDXri [[UBFMXri]], 3, 0 - ; CHECK: [[ADDXrr1:%[0-9]+]]:gpr64 = ADDXrr [[LDRXui]], [[ADDXri]] - ; CHECK: [[COPY2:%[0-9]+]]:gpr64 = COPY [[ADDXrr]] - ; CHECK: [[ADDXrr2:%[0-9]+]]:gpr64 = ADDXrr [[COPY2]], [[ADDXrr1]] - ; CHECK: $x2 = COPY [[ADDXrr2]] - ; CHECK: RET_ReallyLR implicit $x2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[UBFMXri:%[0-9]+]]:gpr64common = UBFMXri [[COPY]], 61, 60 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[ADDXrr:%[0-9]+]]:gpr64common = ADDXrr [[COPY1]], [[UBFMXri]] + ; CHECK-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADDXrr]], 0 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: [[ADDXri:%[0-9]+]]:gpr64common = ADDXri [[UBFMXri]], 3, 0 + ; CHECK-NEXT: [[ADDXrr1:%[0-9]+]]:gpr64 = ADDXrr [[LDRXui]], [[ADDXri]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr64 = COPY [[ADDXrr]] + ; CHECK-NEXT: [[ADDXrr2:%[0-9]+]]:gpr64 = ADDXrr [[COPY2]], [[ADDXrr1]] + ; CHECK-NEXT: $x2 = COPY [[ADDXrr2]] + ; CHECK-NEXT: RET_ReallyLR implicit $x2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 3 %2:gpr(s64) = G_SHL %0, %1(s64) @@ -409,6 +427,9 @@ body: | ... --- +# Show that when we have a fastpath for shift-left, we perform the folding +# if it has more than one use. + name: more_than_one_use_shl_lsl_fast alignment: 4 legalized: true @@ -417,18 +438,17 @@ tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: - ; Show that when we have a fastpath for shift-left, we perform the folding - ; if it has more than one use. liveins: $x0, $x1, $x2 ; CHECK-LABEL: name: more_than_one_use_shl_lsl_fast ; CHECK: liveins: $x0, $x1, $x2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 - ; CHECK: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) - ; CHECK: [[LDRXroX1:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) - ; CHECK: [[ADDXrr:%[0-9]+]]:gpr64 = ADDXrr [[LDRXroX]], [[LDRXroX1]] - ; CHECK: $x2 = COPY [[ADDXrr]] - ; CHECK: RET_ReallyLR implicit $x2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64sp = COPY $x1 + ; CHECK-NEXT: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: [[LDRXroX1:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: [[ADDXrr:%[0-9]+]]:gpr64 = ADDXrr [[LDRXroX]], [[LDRXroX1]] + ; CHECK-NEXT: $x2 = COPY [[ADDXrr]] + ; CHECK-NEXT: RET_ReallyLR implicit $x2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 3 %2:gpr(s64) = G_SHL %0, %1(s64) @@ -442,6 +462,9 @@ body: | ... --- +# Show that we don't fold into multiple memory ops when we don't have a +# fastpath for shift-left. + name: more_than_one_use_shl_lsl_slow alignment: 4 legalized: true @@ -450,19 +473,18 @@ tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: - ; Show that we don't fold into multiple memory ops when we don't have a - ; fastpath for shift-left. liveins: $x0, $x1, $x2 ; CHECK-LABEL: name: more_than_one_use_shl_lsl_slow ; CHECK: liveins: $x0, $x1, $x2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[ADDXrs:%[0-9]+]]:gpr64common = ADDXrs [[COPY1]], [[COPY]], 3 - ; CHECK: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADDXrs]], 0 :: (load (s64) from %ir.addr) - ; CHECK: [[LDRXui1:%[0-9]+]]:gpr64 = LDRXui [[ADDXrs]], 0 :: (load (s64) from %ir.addr) - ; CHECK: [[ADDXrr:%[0-9]+]]:gpr64 = ADDXrr [[LDRXui]], [[LDRXui1]] - ; CHECK: $x2 = COPY [[ADDXrr]] - ; CHECK: RET_ReallyLR implicit $x2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[ADDXrs:%[0-9]+]]:gpr64common = ADDXrs [[COPY1]], [[COPY]], 3 + ; CHECK-NEXT: [[LDRXui:%[0-9]+]]:gpr64 = LDRXui [[ADDXrs]], 0 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: [[LDRXui1:%[0-9]+]]:gpr64 = LDRXui [[ADDXrs]], 0 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: [[ADDXrr:%[0-9]+]]:gpr64 = ADDXrr [[LDRXui]], [[LDRXui1]] + ; CHECK-NEXT: $x2 = COPY [[ADDXrr]] + ; CHECK-NEXT: RET_ReallyLR implicit $x2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 3 %2:gpr(s64) = G_SHL %0, %1(s64) @@ -476,6 +498,9 @@ body: | ... --- +# Show that when we're optimizing for size, we'll do the folding no matter +# what. + name: more_than_one_use_shl_minsize alignment: 4 legalized: true @@ -484,22 +509,21 @@ tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: - ; Show that when we're optimizing for size, we'll do the folding no matter - ; what. liveins: $x0, $x1, $x2 ; CHECK-LABEL: name: more_than_one_use_shl_minsize ; CHECK: liveins: $x0, $x1, $x2 - ; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 - ; CHECK: [[UBFMXri:%[0-9]+]]:gpr64common = UBFMXri [[COPY]], 61, 60 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64common = COPY $x1 - ; CHECK: [[COPY2:%[0-9]+]]:gpr64 = COPY [[COPY1]] - ; CHECK: [[ADDXrs:%[0-9]+]]:gpr64 = ADDXrs [[COPY2]], [[COPY]], 3 - ; CHECK: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) - ; CHECK: [[ADDXri:%[0-9]+]]:gpr64common = ADDXri [[UBFMXri]], 3, 0 - ; CHECK: [[ADDXrr:%[0-9]+]]:gpr64 = ADDXrr [[LDRXroX]], [[ADDXri]] - ; CHECK: [[ADDXrr1:%[0-9]+]]:gpr64 = ADDXrr [[ADDXrs]], [[ADDXrr]] - ; CHECK: $x2 = COPY [[ADDXrr1]] - ; CHECK: RET_ReallyLR implicit $x2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[UBFMXri:%[0-9]+]]:gpr64common = UBFMXri [[COPY]], 61, 60 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64common = COPY $x1 + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr64 = COPY [[COPY1]] + ; CHECK-NEXT: [[ADDXrs:%[0-9]+]]:gpr64 = ADDXrs [[COPY2]], [[COPY]], 3 + ; CHECK-NEXT: [[LDRXroX:%[0-9]+]]:gpr64 = LDRXroX [[COPY1]], [[COPY]], 0, 1 :: (load (s64) from %ir.addr) + ; CHECK-NEXT: [[ADDXri:%[0-9]+]]:gpr64common = ADDXri [[UBFMXri]], 3, 0 + ; CHECK-NEXT: [[ADDXrr:%[0-9]+]]:gpr64 = ADDXrr [[LDRXroX]], [[ADDXri]] + ; CHECK-NEXT: [[ADDXrr1:%[0-9]+]]:gpr64 = ADDXrr [[ADDXrs]], [[ADDXrr]] + ; CHECK-NEXT: $x2 = COPY [[ADDXrr1]] + ; CHECK-NEXT: RET_ReallyLR implicit $x2 %0:gpr(s64) = COPY $x0 %1:gpr(s64) = G_CONSTANT i64 3 %2:gpr(s64) = G_SHL %0, %1(s64) @@ -525,11 +549,12 @@ body: | liveins: $x0, $x1 ; CHECK-LABEL: name: ldrwrox ; CHECK: liveins: $x0, $x1 - ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[LDRWroX:%[0-9]+]]:gpr32 = LDRWroX [[COPY]], [[COPY1]], 0, 0 :: (load (s32) from %ir.addr) - ; CHECK: $w2 = COPY [[LDRWroX]] - ; CHECK: RET_ReallyLR implicit $w2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[LDRWroX:%[0-9]+]]:gpr32 = LDRWroX [[COPY]], [[COPY1]], 0, 0 :: (load (s32) from %ir.addr) + ; CHECK-NEXT: $w2 = COPY [[LDRWroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $w2 %0:gpr(p0) = COPY $x0 %1:gpr(s64) = COPY $x1 %2:gpr(p0) = G_PTR_ADD %0, %1 @@ -549,11 +574,12 @@ body: | liveins: $d0, $x1 ; CHECK-LABEL: name: ldrsrox ; CHECK: liveins: $d0, $x1 - ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $d0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[LDRSroX:%[0-9]+]]:fpr32 = LDRSroX [[COPY]], [[COPY1]], 0, 0 :: (load (s32) from %ir.addr) - ; CHECK: $s2 = COPY [[LDRSroX]] - ; CHECK: RET_ReallyLR implicit $h2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64sp = COPY $d0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[LDRSroX:%[0-9]+]]:fpr32 = LDRSroX [[COPY]], [[COPY1]], 0, 0 :: (load (s32) from %ir.addr) + ; CHECK-NEXT: $s2 = COPY [[LDRSroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $h2 %0:gpr(p0) = COPY $d0 %1:gpr(s64) = COPY $x1 %2:gpr(p0) = G_PTR_ADD %0, %1 @@ -573,11 +599,12 @@ body: | liveins: $x0, $x1 ; CHECK-LABEL: name: ldrhrox ; CHECK: liveins: $x0, $x1 - ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[LDRHroX:%[0-9]+]]:fpr16 = LDRHroX [[COPY]], [[COPY1]], 0, 0 :: (load (s16) from %ir.addr) - ; CHECK: $h2 = COPY [[LDRHroX]] - ; CHECK: RET_ReallyLR implicit $h2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[LDRHroX:%[0-9]+]]:fpr16 = LDRHroX [[COPY]], [[COPY1]], 0, 0 :: (load (s16) from %ir.addr) + ; CHECK-NEXT: $h2 = COPY [[LDRHroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $h2 %0:gpr(p0) = COPY $x0 %1:gpr(s64) = COPY $x1 %2:gpr(p0) = G_PTR_ADD %0, %1 @@ -597,11 +624,12 @@ body: | liveins: $x0, $x1 ; CHECK-LABEL: name: ldbbrox ; CHECK: liveins: $x0, $x1 - ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[LDRBBroX:%[0-9]+]]:gpr32 = LDRBBroX [[COPY]], [[COPY1]], 0, 0 :: (load (s8) from %ir.addr) - ; CHECK: $w2 = COPY [[LDRBBroX]] - ; CHECK: RET_ReallyLR implicit $w2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64sp = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[LDRBBroX:%[0-9]+]]:gpr32 = LDRBBroX [[COPY]], [[COPY1]], 0, 0 :: (load (s8) from %ir.addr) + ; CHECK-NEXT: $w2 = COPY [[LDRBBroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $w2 %0:gpr(p0) = COPY $x0 %1:gpr(s64) = COPY $x1 %2:gpr(p0) = G_PTR_ADD %0, %1 @@ -621,11 +649,12 @@ body: | liveins: $d0, $x1 ; CHECK-LABEL: name: ldrqrox ; CHECK: liveins: $d0, $x1 - ; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $d0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 - ; CHECK: [[LDRQroX:%[0-9]+]]:fpr128 = LDRQroX [[COPY]], [[COPY1]], 0, 0 :: (load (<2 x s64>) from %ir.addr) - ; CHECK: $q0 = COPY [[LDRQroX]] - ; CHECK: RET_ReallyLR implicit $q0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64sp = COPY $d0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[LDRQroX:%[0-9]+]]:fpr128 = LDRQroX [[COPY]], [[COPY1]], 0, 0 :: (load (<2 x s64>) from %ir.addr) + ; CHECK-NEXT: $q0 = COPY [[LDRQroX]] + ; CHECK-NEXT: RET_ReallyLR implicit $q0 %0:gpr(p0) = COPY $d0 %1:gpr(s64) = COPY $x1 %2:gpr(p0) = G_PTR_ADD %0, %1 diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-addo-zero.mir b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-addo-zero.mir index 94f56e5650b22f7a122ccf677ecf3e1d72b82a5e..9483cbf06f4057ffde10948345a630ece97877f8 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-addo-zero.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-addo-zero.mir @@ -1,5 +1,5 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py -# RUN: llc -mtriple aarch64 -debugify-and-strip-all-safe -run-pass=aarch64-prelegalizer-combiner --aarch64prelegalizercombiner-only-enable-rule="addo_by_0" -global-isel -verify-machineinstrs %s -o - | FileCheck %s +# RUN: llc -mtriple aarch64 -debugify-and-strip-all-safe -run-pass=aarch64-prelegalizer-combiner --aarch64prelegalizercombiner-only-enable-rule="match_addos" -global-isel -verify-machineinstrs %s -o - | FileCheck %s # REQUIRES: asserts # (G_*ADDO x, 0) -> x + no carry diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-trap.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-trap.mir index ad66fa5623e3daad37c5cbe992f9d0367b4b0a50..25ecce4dd92bf89857da990ecfe43dabde7d296d 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/select-trap.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-trap.mir @@ -26,7 +26,7 @@ body: | ; CHECK-LABEL: name: foo ; CHECK: BRK 1 ; CHECK: RET_ReallyLR - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + G_TRAP RET_ReallyLR ... diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select.mir index bcdd77ac57570dddc979f1aa0ab68f360233acd8..b3613f52c4ec6e36ba9c59eb40583f0d7a040775 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/select.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select.mir @@ -1,3 +1,4 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4 # RUN: llc -O0 -mtriple=aarch64-apple-ios -run-pass=instruction-select -global-isel-abort=1 -verify-machineinstrs %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=IOS # RUN: llc -O0 -mtriple=aarch64-linux-gnu -relocation-model=pic -run-pass=instruction-select -global-isel-abort=1 -verify-machineinstrs %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=LINUX-PIC @@ -26,40 +27,35 @@ ... --- -# CHECK-LABEL: name: frame_index name: frame_index legalized: true regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64sp, preferred-register: '' } -registers: - - { id: 0, class: gpr } - stack: - { id: 0, name: ptr0, offset: 0, size: 8, alignment: 8 } - -# CHECK: body: -# CHECK: %0:gpr64sp = ADDXri %stack.0.ptr0, 0, 0 body: | bb.0: - %0(p0) = G_FRAME_INDEX %stack.0.ptr0 + ; CHECK-LABEL: name: frame_index + ; CHECK: [[ADDXri:%[0-9]+]]:gpr64sp = ADDXri %stack.0.ptr0, 0, 0 + ; CHECK-NEXT: $x0 = COPY [[ADDXri]] + %0:gpr(p0) = G_FRAME_INDEX %stack.0.ptr0 $x0 = COPY %0(p0) ... --- --- -# CHECK-LABEL: name: ptr_mask name: ptr_mask legalized: true regBankSelected: true - -# CHECK: body: -# CHECK: %2:gpr64sp = ANDXri %0, 8060 body: | bb.0: liveins: $x0 + ; CHECK-LABEL: name: ptr_mask + ; CHECK: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[ANDXri:%[0-9]+]]:gpr64sp = ANDXri [[COPY]], 8060 + ; CHECK-NEXT: $x0 = COPY [[ANDXri]] %0:gpr(p0) = COPY $x0 %const:gpr(s64) = G_CONSTANT i64 -8 %1:gpr(p0) = G_PTRMASK %0, %const @@ -68,180 +64,171 @@ body: | --- # Global defined in the same linkage unit so no GOT is needed -# CHECK-LABEL: name: global_local name: global_local legalized: true regBankSelected: true -registers: - - { id: 0, class: gpr } - -# CHECK: body: -# IOS: %0:gpr64common = MOVaddr target-flags(aarch64-page) @var_local, target-flags(aarch64-pageoff, aarch64-nc) @var_local -# LINUX-PIC: %0:gpr64common = LOADgot target-flags(aarch64-got) @var_local body: | bb.0: - %0(p0) = G_GLOBAL_VALUE @var_local + ; IOS-LABEL: name: global_local + ; IOS: [[MOVaddr:%[0-9]+]]:gpr64common = MOVaddr target-flags(aarch64-page) @var_local, target-flags(aarch64-pageoff, aarch64-nc) @var_local + ; IOS-NEXT: $x0 = COPY [[MOVaddr]] + ; + ; LINUX-PIC-LABEL: name: global_local + ; LINUX-PIC: [[LOADgot:%[0-9]+]]:gpr64common = LOADgot target-flags(aarch64-got) @var_local + ; LINUX-PIC-NEXT: $x0 = COPY [[LOADgot]] + %0:gpr(p0) = G_GLOBAL_VALUE @var_local $x0 = COPY %0(p0) ... --- -# CHECK-LABEL: name: global_got name: global_got legalized: true regBankSelected: true -registers: - - { id: 0, class: gpr } - -# CHECK: body: -# IOS: %0:gpr64common = LOADgot target-flags(aarch64-got) @var_got -# LINUX-PIC: %0:gpr64common = LOADgot target-flags(aarch64-got) @var_got body: | bb.0: - %0(p0) = G_GLOBAL_VALUE @var_got + ; CHECK-LABEL: name: global_got + ; CHECK: [[LOADgot:%[0-9]+]]:gpr64common = LOADgot target-flags(aarch64-got) @var_got + ; CHECK-NEXT: $x0 = COPY [[LOADgot]] + %0:gpr(p0) = G_GLOBAL_VALUE @var_got $x0 = COPY %0(p0) ... --- -# CHECK-LABEL: name: icmp name: icmp legalized: true regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32, preferred-register: '' } -# CHECK-NEXT: - { id: 1, class: gpr32, preferred-register: '' } -# CHECK-NEXT: - { id: 2, class: gpr64, preferred-register: '' } -# CHECK-NEXT: - { id: 3, class: gpr32, preferred-register: '' } -# CHECK-NEXT: - { id: 4, class: gpr64, preferred-register: '' } -# CHECK-NEXT: - { id: 5, class: gpr32, preferred-register: '' } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - - { id: 3, class: gpr } - - { id: 4, class: gpr } - - { id: 5, class: gpr } - - { id: 6, class: gpr } - - { id: 7, class: gpr } - - { id: 8, class: gpr } - - { id: 9, class: gpr } - - { id: 10, class: gpr } - - { id: 11, class: gpr } - -# CHECK: body: -# CHECK: SUBSWrr %0, %0, implicit-def $nzcv -# CHECK: %1:gpr32 = CSINCWr $wzr, $wzr, 1, implicit $nzcv - -# CHECK: SUBSXrr %2, %2, implicit-def $nzcv -# CHECK: %3:gpr32 = CSINCWr $wzr, $wzr, 3, implicit $nzcv - -# CHECK: SUBSXrr %4, %4, implicit-def $nzcv -# CHECK: %5:gpr32 = CSINCWr $wzr, $wzr, 0, implicit $nzcv - body: | bb.0: liveins: $w0, $x0 - %0(s32) = COPY $w0 - %1(s32) = G_ICMP intpred(eq), %0, %0 - %6(s8) = G_TRUNC %1(s32) - %9(s32) = G_ANYEXT %6 + ; CHECK-LABEL: name: icmp + ; CHECK: liveins: $w0, $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $w0 + ; CHECK-NEXT: [[SUBSWrr:%[0-9]+]]:gpr32 = SUBSWrr [[COPY]], [[COPY]], implicit-def $nzcv + ; CHECK-NEXT: [[CSINCWr:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 1, implicit $nzcv + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32all = COPY [[CSINCWr]] + ; CHECK-NEXT: $w0 = COPY [[COPY1]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[SUBSXrr:%[0-9]+]]:gpr64 = SUBSXrr [[COPY2]], [[COPY2]], implicit-def $nzcv + ; CHECK-NEXT: [[CSINCWr1:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 3, implicit $nzcv + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr32all = COPY [[CSINCWr1]] + ; CHECK-NEXT: $w0 = COPY [[COPY3]] + ; CHECK-NEXT: [[COPY4:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[SUBSXrr1:%[0-9]+]]:gpr64 = SUBSXrr [[COPY4]], [[COPY4]], implicit-def $nzcv + ; CHECK-NEXT: [[CSINCWr2:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 0, implicit $nzcv + ; CHECK-NEXT: [[COPY5:%[0-9]+]]:gpr32all = COPY [[CSINCWr2]] + ; CHECK-NEXT: $w0 = COPY [[COPY5]] + %0:gpr(s32) = COPY $w0 + %1:gpr(s32) = G_ICMP intpred(eq), %0, %0 + %6:gpr(s8) = G_TRUNC %1(s32) + %9:gpr(s32) = G_ANYEXT %6 $w0 = COPY %9(s32) - %2(s64) = COPY $x0 - %3(s32) = G_ICMP intpred(uge), %2, %2 - %7(s8) = G_TRUNC %3(s32) - %10(s32) = G_ANYEXT %7 + %2:gpr(s64) = COPY $x0 + %3:gpr(s32) = G_ICMP intpred(uge), %2, %2 + %7:gpr(s8) = G_TRUNC %3(s32) + %10:gpr(s32) = G_ANYEXT %7 $w0 = COPY %10(s32) - %4(p0) = COPY $x0 - %5(s32) = G_ICMP intpred(ne), %4, %4 - %8(s8) = G_TRUNC %5(s32) - %11(s32) = G_ANYEXT %8 + %4:gpr(p0) = COPY $x0 + %5:gpr(s32) = G_ICMP intpred(ne), %4, %4 + %8:gpr(s8) = G_TRUNC %5(s32) + %11:gpr(s32) = G_ANYEXT %8 $w0 = COPY %11(s32) ... --- -# CHECK-LABEL: name: fcmp name: fcmp legalized: true regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr32, preferred-register: '' } -# CHECK-NEXT: - { id: 1, class: gpr32, preferred-register: '' } -# CHECK-NEXT: - { id: 2, class: fpr64, preferred-register: '' } -# CHECK-NEXT: - { id: 3, class: gpr32, preferred-register: '' } -# CHECK-NEXT: - { id: 4, class: gpr32, preferred-register: '' } -# CHECK-NEXT: - { id: 5, class: gpr32, preferred-register: '' } -registers: - - { id: 0, class: fpr } - - { id: 1, class: gpr } - - { id: 2, class: fpr } - - { id: 3, class: gpr } - - { id: 4, class: gpr } - - { id: 5, class: gpr } - - { id: 6, class: gpr } - - { id: 7, class: gpr } - -# CHECK: body: -# CHECK: nofpexcept FCMPSrr %0, %0, implicit-def $nzcv -# CHECK: [[TST_MI:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 5, implicit $nzcv -# CHECK: [[TST_GT:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 13, implicit $nzcv -# CHECK: %1:gpr32 = ORRWrr [[TST_MI]], [[TST_GT]] - -# CHECK: nofpexcept FCMPDrr %2, %2, implicit-def $nzcv -# CHECK: %3:gpr32 = CSINCWr $wzr, $wzr, 4, implicit $nzcv - body: | bb.0: liveins: $w0, $x0 - %0(s32) = COPY $s0 - %1(s32) = G_FCMP floatpred(one), %0, %0 - %4(s8) = G_TRUNC %1(s32) - %6(s32) = G_ANYEXT %4 - $w0 = COPY %6(s32) + ; CHECK-LABEL: name: fcmp + ; CHECK: liveins: $w0, $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr32 = COPY $s0 + ; CHECK-NEXT: nofpexcept FCMPSrr [[COPY]], [[COPY]], implicit-def $nzcv, implicit $fpcr + ; CHECK-NEXT: [[CSINCWr:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 5, implicit $nzcv + ; CHECK-NEXT: [[CSINCWr1:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 13, implicit $nzcv + ; CHECK-NEXT: [[ORRWrr:%[0-9]+]]:gpr32 = ORRWrr [[CSINCWr]], [[CSINCWr1]] + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32all = COPY [[ORRWrr]] + ; CHECK-NEXT: $w0 = COPY [[COPY1]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:fpr64 = COPY $d0 + ; CHECK-NEXT: nofpexcept FCMPDrr [[COPY2]], [[COPY2]], implicit-def $nzcv, implicit $fpcr + ; CHECK-NEXT: [[CSINCWr2:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 4, implicit $nzcv + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr32all = COPY [[CSINCWr2]] + ; CHECK-NEXT: $w0 = COPY [[COPY3]] + ; CHECK-NEXT: [[COPY4:%[0-9]+]]:fpr32 = COPY $s0 + ; CHECK-NEXT: nofpexcept FCMPSrr [[COPY4]], [[COPY4]], implicit-def $nzcv, implicit $fpcr + ; CHECK-NEXT: [[CSINCWr3:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 15, implicit $nzcv + ; CHECK-NEXT: [[COPY5:%[0-9]+]]:gpr32all = COPY [[CSINCWr3]] + ; CHECK-NEXT: $w0 = COPY [[COPY5]] + ; CHECK-NEXT: [[COPY6:%[0-9]+]]:fpr64 = COPY $d0 + ; CHECK-NEXT: nofpexcept FCMPDrr [[COPY6]], [[COPY6]], implicit-def $nzcv, implicit $fpcr + ; CHECK-NEXT: [[CSINCWr4:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 14, implicit $nzcv + ; CHECK-NEXT: [[COPY7:%[0-9]+]]:gpr32all = COPY [[CSINCWr4]] + ; CHECK-NEXT: $w0 = COPY [[COPY7]] + %0:fpr(s32) = COPY $s0 + %1:gpr(s32) = G_FCMP floatpred(one), %0, %0 + %2:gpr(s8) = G_TRUNC %1(s32) + %3:gpr(s32) = G_ANYEXT %2 + $w0 = COPY %3(s32) - %2(s64) = COPY $d0 - %3(s32) = G_FCMP floatpred(uge), %2, %2 - %5(s8) = G_TRUNC %3(s32) - %7(s32) = G_ANYEXT %5 + %4:fpr(s64) = COPY $d0 + %5:gpr(s32) = G_FCMP floatpred(uge), %4, %4 + %6:gpr(s8) = G_TRUNC %5(s32) + %7:gpr(s32) = G_ANYEXT %6 $w0 = COPY %7(s32) + %8:fpr(s32) = COPY $s0 + %9:gpr(s32) = G_FCMP floatpred(true), %8, %8 + %10:gpr(s8) = G_TRUNC %9(s32) + %11:gpr(s32) = G_ANYEXT %10 + $w0 = COPY %11(s32) + + %12:fpr(s64) = COPY $d0 + %13:gpr(s32) = G_FCMP floatpred(false), %12, %12 + %14:gpr(s8) = G_TRUNC %13(s32) + %15:gpr(s32) = G_ANYEXT %14 + $w0 = COPY %15(s32) + ... --- -# CHECK-LABEL: name: phi name: phi legalized: true regBankSelected: true tracksRegLiveness: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: fpr32, preferred-register: '' } -# CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' } -# CHECK-NEXT: - { id: 2, class: fpr32, preferred-register: '' } -# CHECK-NEXT: - { id: 3, class: gpr32, preferred-register: '' } -registers: - - { id: 0, class: fpr } - - { id: 1, class: gpr } - - { id: 2, class: fpr } - -# CHECK: body: -# CHECK: bb.1: -# CHECK: %2:fpr32 = PHI %0, %bb.0, %2, %bb.1 - body: | + ; CHECK-LABEL: name: phi + ; CHECK: bb.0: + ; CHECK-NEXT: successors: %bb.1(0x80000000) + ; CHECK-NEXT: liveins: $s0, $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr32 = COPY $s0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.1: + ; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000) + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[PHI:%[0-9]+]]:fpr32 = PHI [[COPY]], %bb.0, [[PHI]], %bb.1 + ; CHECK-NEXT: TBNZW [[COPY1]], 0, %bb.1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.2: + ; CHECK-NEXT: $s0 = COPY [[PHI]] + ; CHECK-NEXT: RET_ReallyLR implicit $s0 bb.0: liveins: $s0, $w0 successors: %bb.1 - %0(s32) = COPY $s0 + %0:fpr(s32) = COPY $s0 %3:gpr(s32) = COPY $w0 bb.1: successors: %bb.1, %bb.2 - %2(s32) = PHI %0, %bb.0, %2, %bb.1 + %2:fpr(s32) = PHI %0, %bb.0, %2, %bb.1 G_BRCOND %3, %bb.1 bb.2: @@ -250,60 +237,46 @@ body: | ... --- -# CHECK-LABEL: name: select name: select legalized: true regBankSelected: true tracksRegLiveness: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr, preferred-register: '' } -# CHECK-NEXT: - { id: 1, class: gpr32, preferred-register: '' } -# CHECK-NEXT: - { id: 2, class: gpr32, preferred-register: '' } -# CHECK-NEXT: - { id: 3, class: gpr32, preferred-register: '' } -# CHECK-NEXT: - { id: 4, class: gpr64, preferred-register: '' } -# CHECK-NEXT: - { id: 5, class: gpr64, preferred-register: '' } -# CHECK-NEXT: - { id: 6, class: gpr64, preferred-register: '' } -# CHECK-NEXT: - { id: 7, class: gpr64, preferred-register: '' } -# CHECK-NEXT: - { id: 8, class: gpr64, preferred-register: '' } -# CHECK-NEXT: - { id: 9, class: gpr64, preferred-register: '' } -# CHECK-NEXT: - { id: 10, class: gpr32, preferred-register: '' } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - - { id: 3, class: gpr } - - { id: 4, class: gpr } - - { id: 5, class: gpr } - - { id: 6, class: gpr } - - { id: 7, class: gpr } - - { id: 8, class: gpr } - - { id: 9, class: gpr } - -# CHECK: body: -# CHECK: ANDSWri %10, 0, implicit-def $nzcv -# CHECK: %3:gpr32 = CSELWr %1, %2, 1, implicit $nzcv -# CHECK: ANDSWri %10, 0, implicit-def $nzcv -# CHECK: %6:gpr64 = CSELXr %4, %5, 1, implicit $nzcv -# CHECK: ANDSWri %10, 0, implicit-def $nzcv -# CHECK: %9:gpr64 = CSELXr %7, %8, 1, implicit $nzcv body: | bb.0: liveins: $w0, $w1, $w2 + ; CHECK-LABEL: name: select + ; CHECK: liveins: $w0, $w1, $w2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32 = COPY $w0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY $w1 + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr32 = COPY $w2 + ; CHECK-NEXT: [[ANDSWri:%[0-9]+]]:gpr32 = ANDSWri [[COPY]], 0, implicit-def $nzcv + ; CHECK-NEXT: [[CSELWr:%[0-9]+]]:gpr32 = CSELWr [[COPY1]], [[COPY2]], 1, implicit $nzcv + ; CHECK-NEXT: $w0 = COPY [[CSELWr]] + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY4:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[ANDSWri1:%[0-9]+]]:gpr32 = ANDSWri [[COPY]], 0, implicit-def $nzcv + ; CHECK-NEXT: [[CSELXr:%[0-9]+]]:gpr64 = CSELXr [[COPY3]], [[COPY4]], 1, implicit $nzcv + ; CHECK-NEXT: $x0 = COPY [[CSELXr]] + ; CHECK-NEXT: [[COPY5:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: [[COPY6:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[ANDSWri2:%[0-9]+]]:gpr32 = ANDSWri [[COPY]], 0, implicit-def $nzcv + ; CHECK-NEXT: [[CSELXr1:%[0-9]+]]:gpr64 = CSELXr [[COPY5]], [[COPY6]], 1, implicit $nzcv + ; CHECK-NEXT: $x0 = COPY [[CSELXr1]] %10:gpr(s32) = COPY $w0 - %1(s32) = COPY $w1 - %2(s32) = COPY $w2 - %3(s32) = G_SELECT %10, %1, %2 + %1:gpr(s32) = COPY $w1 + %2:gpr(s32) = COPY $w2 + %3:gpr(s32) = G_SELECT %10, %1, %2 $w0 = COPY %3(s32) - %4(s64) = COPY $x0 - %5(s64) = COPY $x1 - %6(s64) = G_SELECT %10, %4, %5 + %4:gpr(s64) = COPY $x0 + %5:gpr(s64) = COPY $x1 + %6:gpr(s64) = G_SELECT %10, %4, %5 $x0 = COPY %6(s64) - %7(p0) = COPY $x0 - %8(p0) = COPY $x1 - %9(p0) = G_SELECT %10, %7, %8 + %7:gpr(p0) = COPY $x0 + %8:gpr(p0) = COPY $x1 + %9:gpr(p0) = G_SELECT %10, %7, %8 $x0 = COPY %9(p0) ... diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/uaddo-8-16-bits.mir b/llvm/test/CodeGen/AArch64/GlobalISel/uaddo-8-16-bits.mir index f4366fb7888ead763479cea9dd3546afcf76857b..b242c68e3b07f5b6af88d3a5a6ccb4cb5f24c449 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/uaddo-8-16-bits.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/uaddo-8-16-bits.mir @@ -26,7 +26,7 @@ body: | ; CHECK-NEXT: bb.1: ; CHECK-NEXT: successors: ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + ; CHECK-NEXT: G_TRAP ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.2: ; CHECK-NEXT: $w0 = COPY [[ADD]](s32) @@ -48,7 +48,7 @@ body: | bb.2: successors: - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + G_TRAP bb.3: %8:_(s32) = G_ZEXT %6(s8) @@ -80,7 +80,7 @@ body: | ; CHECK-NEXT: bb.1: ; CHECK-NEXT: successors: ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + ; CHECK-NEXT: G_TRAP ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.2: ; CHECK-NEXT: $w0 = COPY [[ADD]](s32) @@ -102,7 +102,7 @@ body: | bb.2: successors: - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + G_TRAP bb.3: %8:_(s32) = G_ZEXT %6(s16) @@ -134,7 +134,7 @@ body: | ; CHECK-NEXT: bb.1: ; CHECK-NEXT: successors: ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + ; CHECK-NEXT: G_TRAP ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.2: ; CHECK-NEXT: liveins: $x2 @@ -165,7 +165,7 @@ body: | bb.2: successors: - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + G_TRAP bb.3: liveins: $x2 @@ -206,7 +206,7 @@ body: | ; CHECK-NEXT: bb.1: ; CHECK-NEXT: successors: ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + ; CHECK-NEXT: G_TRAP ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.2: ; CHECK-NEXT: $w0 = COPY [[ADD]](s32) @@ -228,7 +228,7 @@ body: | bb.2: successors: - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + G_TRAP bb.3: %8:_(s32) = G_ANYEXT %6(s16) @@ -261,7 +261,7 @@ body: | ; CHECK-NEXT: bb.1: ; CHECK-NEXT: successors: ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + ; CHECK-NEXT: G_TRAP ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.2: ; CHECK-NEXT: $w0 = COPY [[ADD]](s32) @@ -284,7 +284,7 @@ body: | bb.2: successors: - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + G_TRAP bb.3: %8:_(s32) = G_ZEXT %6(s16) @@ -317,7 +317,7 @@ body: | ; CHECK-NEXT: bb.1: ; CHECK-NEXT: successors: ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + ; CHECK-NEXT: G_TRAP ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.2: ; CHECK-NEXT: $w0 = COPY [[ADD]](s32) @@ -340,7 +340,7 @@ body: | bb.2: successors: - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + G_TRAP bb.3: %8:_(s32) = G_ZEXT %6(s16) @@ -377,7 +377,7 @@ body: | ; CHECK-NEXT: bb.1: ; CHECK-NEXT: successors: ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + ; CHECK-NEXT: G_TRAP ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.2: ; CHECK-NEXT: liveins: $x2 @@ -410,7 +410,7 @@ body: | bb.2: successors: - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + G_TRAP bb.3: liveins: $x2 @@ -512,7 +512,7 @@ body: | ; CHECK-NEXT: bb.2: ; CHECK-NEXT: successors: ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + ; CHECK-NEXT: G_TRAP ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.3: ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UADDO]](s16) @@ -544,7 +544,7 @@ body: | bb.2: successors: - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + G_TRAP bb.3: %9:_(s32) = G_ZEXT %6(s16) @@ -577,7 +577,7 @@ body: | ; CHECK-NEXT: bb.1: ; CHECK-NEXT: successors: ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + ; CHECK-NEXT: G_TRAP ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.2: ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UADDO]](s8) @@ -601,7 +601,7 @@ body: | bb.2: successors: - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + G_TRAP bb.3: %9:_(s32) = G_ZEXT %7(s8) @@ -634,7 +634,7 @@ body: | ; CHECK-NEXT: bb.1: ; CHECK-NEXT: successors: ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + ; CHECK-NEXT: G_TRAP ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.2: ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UADDO]](s8) @@ -658,7 +658,7 @@ body: | bb.2: successors: - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + G_TRAP bb.3: %9:_(s32) = G_ZEXT %7(s8) @@ -692,7 +692,7 @@ body: | ; CHECK-NEXT: bb.1: ; CHECK-NEXT: successors: ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + ; CHECK-NEXT: G_TRAP ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.2: ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UADDO]](s8) @@ -717,7 +717,7 @@ body: | bb.2: successors: - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + G_TRAP bb.3: %10:_(s32) = G_ZEXT %8(s8) @@ -783,7 +783,7 @@ body: | ; CHECK-NEXT: bb.1: ; CHECK-NEXT: successors: ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + ; CHECK-NEXT: G_TRAP ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.2: ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDO]](s16) @@ -804,7 +804,7 @@ body: | bb.2: successors: - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + G_TRAP bb.3: %6:_(s32) = G_ANYEXT %4(s16) @@ -839,7 +839,7 @@ body: | ; CHECK-NEXT: RET_ReallyLR implicit $w0 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.2: - ; CHECK-NEXT: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + ; CHECK-NEXT: G_TRAP bb.1: successors: %bb.2(0x7ffff800), %bb.3(0x00000800) liveins: $w0, $w1 @@ -860,6 +860,6 @@ body: | RET_ReallyLR implicit $w0 bb.3: - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + G_TRAP ... diff --git a/llvm/test/CodeGen/AArch64/aarch64-sme2-asm.ll b/llvm/test/CodeGen/AArch64/aarch64-sme2-asm.ll index 58299696e78fc2d77d1150fac02db38f8839844c..d4d803a91cfa14e37292f5fbf7af4f156f58b41b 100644 --- a/llvm/test/CodeGen/AArch64/aarch64-sme2-asm.ll +++ b/llvm/test/CodeGen/AArch64/aarch64-sme2-asm.ll @@ -3,7 +3,7 @@ define void @UphPNR(target("aarch64.svcount") %predcnt) { entry: ; CHECK: %0:ppr = COPY $p0 -; CHECK: STR_PXI %0, %stack.0.predcnt.addr, 0 :: (store unknown-size into %ir.predcnt.addr, align 2) +; CHECK: STR_PXI %0, %stack.0.predcnt.addr, 0 :: (store (<vscale x 1 x s16>) into %ir.predcnt.addr) ; CHECK: %1:pnr_p8to15 = COPY %0 ; CHECK: INLINEASM &"ld1w {z0.s,z1.s,z2.s,z3.s}, $0/z, [x10]", 1 /* sideeffect attdialect */, {{[0-9]+}} /* reguse:PNR_p8to15 */, %1 ; CHECK: RET_ReallyLR @@ -17,7 +17,7 @@ entry: define void @UpaPNR(target("aarch64.svcount") %predcnt) { entry: ; CHECK: %0:ppr = COPY $p0 -; CHECK: STR_PXI %0, %stack.0.predcnt.addr, 0 :: (store unknown-size into %ir.predcnt.addr, align 2) +; CHECK: STR_PXI %0, %stack.0.predcnt.addr, 0 :: (store (<vscale x 1 x s16>) into %ir.predcnt.addr) ; CHECK: %1:pnr = COPY %0 ; CHECK: INLINEASM &"ld1w {z0.s,z1.s,z2.s,z3.s}, $0/z, [x10]", 1 /* sideeffect attdialect */, {{[0-9]+}} /* reguse:PNR */, %1 ; CHECK: RET_ReallyLR @@ -31,7 +31,7 @@ entry: define void @UplPNR(target("aarch64.svcount") %predcnt) { entry: ; CHECK: %0:ppr = COPY $p0 -; CHECK: STR_PXI %0, %stack.0.predcnt.addr, 0 :: (store unknown-size into %ir.predcnt.addr, align 2) +; CHECK: STR_PXI %0, %stack.0.predcnt.addr, 0 :: (store (<vscale x 1 x s16>) into %ir.predcnt.addr) ; CHECK: %1:pnr_3b = COPY %0 ; CHECK: INLINEASM &"fadd z0.h, $0/m, z0.h, #0.5", 1 /* sideeffect attdialect */, {{[0-9]+}} /* reguse:PNR_3b */, %1 ; CHECK: RET_ReallyLR diff --git a/llvm/test/CodeGen/AArch64/aarch64-smull.ll b/llvm/test/CodeGen/AArch64/aarch64-smull.ll index dbc5417e23133da6b82786066f6d6e5e72c02461..61a4f64ac2bfcb3da13d37ee6cb4dbf6ed2b26b5 100644 --- a/llvm/test/CodeGen/AArch64/aarch64-smull.ll +++ b/llvm/test/CodeGen/AArch64/aarch64-smull.ll @@ -3,8 +3,7 @@ ; RUN: llc -mtriple=aarch64-none-linux-gnu -mattr=+sve < %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SVE ; RUN: llc -mtriple=aarch64 -global-isel -global-isel-abort=2 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI -; CHECK-GI: warning: Instruction selection used fallback path for smull_zext_v4i16_v4i32 -; CHECK-GI-NEXT: warning: Instruction selection used fallback path for pmlsl2_v8i16_uzp1 +; CHECK-GI: warning: Instruction selection used fallback path for pmlsl2_v8i16_uzp1 ; CHECK-GI-NEXT: warning: Instruction selection used fallback path for smlsl2_v8i16_uzp1 ; CHECK-GI-NEXT: warning: Instruction selection used fallback path for umlsl2_v8i16_uzp1 ; CHECK-GI-NEXT: warning: Instruction selection used fallback path for smlsl2_v4i32_uzp1 @@ -189,13 +188,49 @@ define <8 x i32> @smull_zext_v8i8_v8i32_top_bit_is_1(ptr %A, ptr %B) nounwind { } define <4 x i32> @smull_zext_v4i16_v4i32(ptr %A, ptr %B) nounwind { -; CHECK-LABEL: smull_zext_v4i16_v4i32: -; CHECK: // %bb.0: -; CHECK-NEXT: ldr s0, [x0] -; CHECK-NEXT: ldr d1, [x1] -; CHECK-NEXT: ushll v0.8h, v0.8b, #0 -; CHECK-NEXT: smull v0.4s, v0.4h, v1.4h -; CHECK-NEXT: ret +; CHECK-NEON-LABEL: smull_zext_v4i16_v4i32: +; CHECK-NEON: // %bb.0: +; CHECK-NEON-NEXT: ldr s0, [x0] +; CHECK-NEON-NEXT: ldr d1, [x1] +; CHECK-NEON-NEXT: ushll v0.8h, v0.8b, #0 +; CHECK-NEON-NEXT: smull v0.4s, v0.4h, v1.4h +; CHECK-NEON-NEXT: ret +; +; CHECK-SVE-LABEL: smull_zext_v4i16_v4i32: +; CHECK-SVE: // %bb.0: +; CHECK-SVE-NEXT: ldr s0, [x0] +; CHECK-SVE-NEXT: ldr d1, [x1] +; CHECK-SVE-NEXT: ushll v0.8h, v0.8b, #0 +; CHECK-SVE-NEXT: smull v0.4s, v0.4h, v1.4h +; CHECK-SVE-NEXT: ret +; +; CHECK-GI-LABEL: smull_zext_v4i16_v4i32: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: ldr w8, [x0] +; CHECK-GI-NEXT: fmov s0, w8 +; CHECK-GI-NEXT: uxtb w8, w8 +; CHECK-GI-NEXT: mov b1, v0.b[1] +; CHECK-GI-NEXT: mov b2, v0.b[2] +; CHECK-GI-NEXT: mov b3, v0.b[3] +; CHECK-GI-NEXT: fmov s0, w8 +; CHECK-GI-NEXT: fmov w9, s1 +; CHECK-GI-NEXT: fmov w10, s2 +; CHECK-GI-NEXT: fmov w11, s3 +; CHECK-GI-NEXT: uxtb w9, w9 +; CHECK-GI-NEXT: uxtb w10, w10 +; CHECK-GI-NEXT: uxtb w11, w11 +; CHECK-GI-NEXT: fmov s1, w9 +; CHECK-GI-NEXT: fmov s2, w10 +; CHECK-GI-NEXT: fmov s3, w11 +; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NEXT: mov v2.h[1], v3.h[0] +; CHECK-GI-NEXT: ushll v0.4s, v0.4h, #0 +; CHECK-GI-NEXT: ushll v1.4s, v2.4h, #0 +; CHECK-GI-NEXT: ldr d2, [x1] +; CHECK-GI-NEXT: mov v0.d[1], v1.d[0] +; CHECK-GI-NEXT: sshll v1.4s, v2.4h, #0 +; CHECK-GI-NEXT: mul v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: ret %load.A = load <4 x i8>, ptr %A %load.B = load <4 x i16>, ptr %B %zext.A = zext <4 x i8> %load.A to <4 x i32> diff --git a/llvm/test/CodeGen/AArch64/aarch64-split-and-bitmask-immediate.ll b/llvm/test/CodeGen/AArch64/aarch64-split-and-bitmask-immediate.ll index cf9ed4d5f0e16a0c47509658c77d2e2553883d80..573f921e638cf8d94c9b6b2ea3c84b2626f596b7 100644 --- a/llvm/test/CodeGen/AArch64/aarch64-split-and-bitmask-immediate.ll +++ b/llvm/test/CodeGen/AArch64/aarch64-split-and-bitmask-immediate.ll @@ -20,7 +20,7 @@ entry: define i8 @test2(i32 %a) { ; CHECK-LABEL: test2: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #135 +; CHECK-NEXT: mov w8, #135 // =0x87 ; CHECK-NEXT: and w8, w0, w8 ; CHECK-NEXT: cmp w8, #1024 ; CHECK-NEXT: cset w0, eq @@ -37,7 +37,7 @@ entry: define i8 @test3(i32 %a) { ; CHECK-LABEL: test3: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #1024 +; CHECK-NEXT: mov w8, #1024 // =0x400 ; CHECK-NEXT: movk w8, #33, lsl #16 ; CHECK-NEXT: and w8, w0, w8 ; CHECK-NEXT: cmp w8, #1024 @@ -84,7 +84,7 @@ entry: define i8 @test6(i64 %a) { ; CHECK-LABEL: test6: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #135 +; CHECK-NEXT: mov w8, #135 // =0x87 ; CHECK-NEXT: and x8, x0, x8 ; CHECK-NEXT: cmp x8, #1024 ; CHECK-NEXT: cset w0, eq @@ -101,7 +101,7 @@ entry: define i8 @test7(i64 %a) { ; CHECK-LABEL: test7: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #1024 +; CHECK-NEXT: mov w8, #1024 // =0x400 ; CHECK-NEXT: movk w8, #33, lsl #16 ; CHECK-NEXT: and x8, x0, x8 ; CHECK-NEXT: cmp x8, #1024 @@ -175,7 +175,7 @@ define i32 @test9(ptr nocapture %x, ptr nocapture readonly %y, i32 %n) { ; CHECK-NEXT: cmp w2, #1 ; CHECK-NEXT: b.lt .LBB8_3 ; CHECK-NEXT: // %bb.1: // %for.body.preheader -; CHECK-NEXT: mov w9, #1024 +; CHECK-NEXT: mov w9, #1024 // =0x400 ; CHECK-NEXT: mov w8, w2 ; CHECK-NEXT: movk w9, #32, lsl #16 ; CHECK-NEXT: .LBB8_2: // %for.body @@ -226,7 +226,7 @@ define void @test10(ptr nocapture %x, ptr nocapture readonly %y, ptr nocapture % ; CHECK-LABEL: test10: ; CHECK: // %bb.0: // %entry ; CHECK-NEXT: ldr w8, [x1] -; CHECK-NEXT: mov w9, #1024 +; CHECK-NEXT: mov w9, #1024 // =0x400 ; CHECK-NEXT: movk w9, #32, lsl #16 ; CHECK-NEXT: and w8, w8, w9 ; CHECK-NEXT: str w8, [x0] @@ -253,7 +253,7 @@ entry: define i8 @test11(i64 %a) { ; CHECK-LABEL: test11: ; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w8, #-1610612736 +; CHECK-NEXT: mov w8, #-1610612736 // =0xa0000000 ; CHECK-NEXT: and x8, x0, x8 ; CHECK-NEXT: cmp x8, #1024 ; CHECK-NEXT: cset w0, eq diff --git a/llvm/test/CodeGen/AArch64/abs.ll b/llvm/test/CodeGen/AArch64/abs.ll index e00f70b94e3b42b45a0115115fda913b80d84e11..78c1ff7b993706aed410cee0863dd0e3bcca976c 100644 --- a/llvm/test/CodeGen/AArch64/abs.ll +++ b/llvm/test/CodeGen/AArch64/abs.ll @@ -15,9 +15,8 @@ define i8 @abs_i8(i8 %a){ ; CHECK-GI-LABEL: abs_i8: ; CHECK-GI: // %bb.0: // %entry ; CHECK-GI-NEXT: sxtb w8, w0 -; CHECK-GI-NEXT: asr w8, w8, #7 -; CHECK-GI-NEXT: add w9, w0, w8 -; CHECK-GI-NEXT: eor w0, w9, w8 +; CHECK-GI-NEXT: cmp w8, #0 +; CHECK-GI-NEXT: cneg w0, w0, le ; CHECK-GI-NEXT: ret entry: %res = call i8 @llvm.abs.i8(i8 %a, i1 0) @@ -36,9 +35,8 @@ define i16 @abs_i16(i16 %a){ ; CHECK-GI-LABEL: abs_i16: ; CHECK-GI: // %bb.0: // %entry ; CHECK-GI-NEXT: sxth w8, w0 -; CHECK-GI-NEXT: asr w8, w8, #15 -; CHECK-GI-NEXT: add w9, w0, w8 -; CHECK-GI-NEXT: eor w0, w9, w8 +; CHECK-GI-NEXT: cmp w8, #0 +; CHECK-GI-NEXT: cneg w0, w0, le ; CHECK-GI-NEXT: ret entry: %res = call i16 @llvm.abs.i16(i16 %a, i1 0) @@ -55,9 +53,8 @@ define i32 @abs_i32(i32 %a){ ; ; CHECK-GI-LABEL: abs_i32: ; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: asr w8, w0, #31 -; CHECK-GI-NEXT: add w9, w0, w8 -; CHECK-GI-NEXT: eor w0, w9, w8 +; CHECK-GI-NEXT: cmp w0, #0 +; CHECK-GI-NEXT: cneg w0, w0, le ; CHECK-GI-NEXT: ret entry: %res = call i32 @llvm.abs.i32(i32 %a, i1 0) @@ -74,9 +71,8 @@ define i64 @abs_i64(i64 %a){ ; ; CHECK-GI-LABEL: abs_i64: ; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: asr x8, x0, #63 -; CHECK-GI-NEXT: add x9, x0, x8 -; CHECK-GI-NEXT: eor x0, x9, x8 +; CHECK-GI-NEXT: cmp x0, #0 +; CHECK-GI-NEXT: cneg x0, x0, le ; CHECK-GI-NEXT: ret entry: %res = call i64 @llvm.abs.i64(i64 %a, i1 0) @@ -248,9 +244,9 @@ define <1 x i32> @abs_v1i32(<1 x i32> %a){ ; CHECK-GI-LABEL: abs_v1i32: ; CHECK-GI: // %bb.0: // %entry ; CHECK-GI-NEXT: fmov w8, s0 -; CHECK-GI-NEXT: asr w9, w8, #31 -; CHECK-GI-NEXT: add w8, w8, w9 -; CHECK-GI-NEXT: eor w8, w8, w9 +; CHECK-GI-NEXT: fmov w9, s0 +; CHECK-GI-NEXT: cmp w8, #0 +; CHECK-GI-NEXT: cneg w8, w9, le ; CHECK-GI-NEXT: fmov s0, w8 ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-array.ll b/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-array.ll index 9a4e01a29ecb6dae8b8703a78e0c0760b5376705..7244ac949ab88c3074f26938b94cca1b85341eab 100644 --- a/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-array.ll +++ b/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-array.ll @@ -14,12 +14,12 @@ define void @array_1D(ptr %addr) #0 { ; CHECK-NEXT: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 24 * VG ; CHECK-NEXT: .cfi_offset w29, -16 ; CHECK-NEXT: ptrue p0.d -; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0, #2, mul vl] -; CHECK-NEXT: ld1d { z1.d }, p0/z, [x0, #1, mul vl] -; CHECK-NEXT: ld1d { z2.d }, p0/z, [x0] -; CHECK-NEXT: st1d { z0.d }, p0, [sp, #2, mul vl] -; CHECK-NEXT: st1d { z1.d }, p0, [sp, #1, mul vl] -; CHECK-NEXT: st1d { z2.d }, p0, [sp] +; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0] +; CHECK-NEXT: ld1d { z1.d }, p0/z, [x0, #2, mul vl] +; CHECK-NEXT: ld1d { z2.d }, p0/z, [x0, #1, mul vl] +; CHECK-NEXT: st1d { z0.d }, p0, [sp] +; CHECK-NEXT: st1d { z1.d }, p0, [sp, #2, mul vl] +; CHECK-NEXT: st1d { z2.d }, p0, [sp, #1, mul vl] ; CHECK-NEXT: addvl sp, sp, #3 ; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret @@ -81,18 +81,18 @@ define void @array_2D(ptr %addr) #0 { ; CHECK-NEXT: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x30, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 48 * VG ; CHECK-NEXT: .cfi_offset w29, -16 ; CHECK-NEXT: ptrue p0.d -; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0, #5, mul vl] -; CHECK-NEXT: ld1d { z1.d }, p0/z, [x0, #4, mul vl] -; CHECK-NEXT: ld1d { z2.d }, p0/z, [x0] -; CHECK-NEXT: ld1d { z3.d }, p0/z, [x0, #3, mul vl] -; CHECK-NEXT: ld1d { z4.d }, p0/z, [x0, #1, mul vl] -; CHECK-NEXT: ld1d { z5.d }, p0/z, [x0, #2, mul vl] -; CHECK-NEXT: st1d { z0.d }, p0, [sp, #5, mul vl] -; CHECK-NEXT: st1d { z1.d }, p0, [sp, #4, mul vl] -; CHECK-NEXT: st1d { z3.d }, p0, [sp, #3, mul vl] -; CHECK-NEXT: st1d { z5.d }, p0, [sp, #2, mul vl] -; CHECK-NEXT: st1d { z4.d }, p0, [sp, #1, mul vl] -; CHECK-NEXT: st1d { z2.d }, p0, [sp] +; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0] +; CHECK-NEXT: ld1d { z1.d }, p0/z, [x0, #5, mul vl] +; CHECK-NEXT: ld1d { z2.d }, p0/z, [x0, #1, mul vl] +; CHECK-NEXT: ld1d { z3.d }, p0/z, [x0, #4, mul vl] +; CHECK-NEXT: ld1d { z4.d }, p0/z, [x0, #2, mul vl] +; CHECK-NEXT: ld1d { z5.d }, p0/z, [x0, #3, mul vl] +; CHECK-NEXT: st1d { z0.d }, p0, [sp] +; CHECK-NEXT: st1d { z1.d }, p0, [sp, #5, mul vl] +; CHECK-NEXT: st1d { z3.d }, p0, [sp, #4, mul vl] +; CHECK-NEXT: st1d { z5.d }, p0, [sp, #3, mul vl] +; CHECK-NEXT: st1d { z4.d }, p0, [sp, #2, mul vl] +; CHECK-NEXT: st1d { z2.d }, p0, [sp, #1, mul vl] ; CHECK-NEXT: addvl sp, sp, #6 ; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-struct.ll b/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-struct.ll index 7292d52aaf4765abac03da9b193fc7e14a00fd83..f03a6f018d34d0cc4412b6a8e995abbce8024ae9 100644 --- a/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-struct.ll +++ b/llvm/test/CodeGen/AArch64/alloca-load-store-scalable-struct.ll @@ -13,12 +13,12 @@ define void @test(ptr %addr) #0 { ; CHECK-NEXT: .cfi_escape 0x0f, 0x0c, 0x8f, 0x00, 0x11, 0x10, 0x22, 0x11, 0x18, 0x92, 0x2e, 0x00, 0x1e, 0x22 // sp + 16 + 24 * VG ; CHECK-NEXT: .cfi_offset w29, -16 ; CHECK-NEXT: ptrue p0.d -; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0, #2, mul vl] -; CHECK-NEXT: ld1d { z1.d }, p0/z, [x0, #1, mul vl] -; CHECK-NEXT: ld1d { z2.d }, p0/z, [x0] -; CHECK-NEXT: st1d { z0.d }, p0, [sp, #2, mul vl] -; CHECK-NEXT: st1d { z1.d }, p0, [sp, #1, mul vl] -; CHECK-NEXT: st1d { z2.d }, p0, [sp] +; CHECK-NEXT: ld1d { z0.d }, p0/z, [x0] +; CHECK-NEXT: ld1d { z1.d }, p0/z, [x0, #2, mul vl] +; CHECK-NEXT: ld1d { z2.d }, p0/z, [x0, #1, mul vl] +; CHECK-NEXT: st1d { z0.d }, p0, [sp] +; CHECK-NEXT: st1d { z1.d }, p0, [sp, #2, mul vl] +; CHECK-NEXT: st1d { z2.d }, p0, [sp, #1, mul vl] ; CHECK-NEXT: addvl sp, sp, #3 ; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/allow-check.ll b/llvm/test/CodeGen/AArch64/allow-check.ll new file mode 100644 index 0000000000000000000000000000000000000000..9e4a47357906c63d46b36595de98b486073ff0ff --- /dev/null +++ b/llvm/test/CodeGen/AArch64/allow-check.ll @@ -0,0 +1,30 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=aarch64 -global-isel=0 -fast-isel=0 | FileCheck %s +; RUN: llc < %s -mtriple=aarch64 -global-isel=1 -fast-isel=0 | FileCheck %s +; RUN: llc < %s -mtriple=aarch64 -global-isel=0 -fast-isel=1 | FileCheck %s + +target triple = "aarch64-linux" + +define i1 @test_runtime() local_unnamed_addr { +; CHECK-LABEL: test_runtime: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov w0, #1 // =0x1 +; CHECK-NEXT: ret +entry: + %allow = call i1 @llvm.allow.runtime.check(metadata !"test_check") + ret i1 %allow +} + +declare i1 @llvm.allow.runtime.check(metadata) nounwind + +define i1 @test_ubsan() local_unnamed_addr { +; CHECK-LABEL: test_ubsan: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov w0, #1 // =0x1 +; CHECK-NEXT: ret +entry: + %allow = call i1 @llvm.allow.ubsan.check(i8 7) + ret i1 %allow +} + +declare i1 @llvm.allow.ubsan.check(i8) nounwind diff --git a/llvm/test/CodeGen/AArch64/and-sink.ll b/llvm/test/CodeGen/AArch64/and-sink.ll index 4d085869de244f7c49d6e090993cc663b824b6a7..f298a55dab721ec276b4a368367de29d411f1ab3 100644 --- a/llvm/test/CodeGen/AArch64/and-sink.ll +++ b/llvm/test/CodeGen/AArch64/and-sink.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 ; RUN: llc -mtriple=aarch64-linux-gnu -verify-machineinstrs < %s | FileCheck %s ; RUN: opt -S -passes='require<profile-summary>,function(codegenprepare)' -mtriple=aarch64-linux %s | FileCheck --check-prefix=CHECK-CGP %s ; RUN: opt -S -passes='require<profile-summary>,function(codegenprepare)' -cgpp-huge-func=0 -mtriple=aarch64-linux %s | FileCheck --check-prefix=CHECK-CGP %s @@ -9,9 +10,18 @@ ; Test that and is sunk into cmp block to form tbz. define dso_local i32 @and_sink1(i32 %a, i1 %c) { ; CHECK-LABEL: and_sink1: -; CHECK: tbz w1, #0 -; CHECK: str wzr, [x{{[0-9]+}}, :lo12:A] -; CHECK: tbnz {{w[0-9]+}}, #2 +; CHECK: // %bb.0: +; CHECK-NEXT: tbz w1, #0, .LBB0_3 +; CHECK-NEXT: // %bb.1: // %bb0 +; CHECK-NEXT: adrp x8, A +; CHECK-NEXT: str wzr, [x8, :lo12:A] +; CHECK-NEXT: tbnz w0, #2, .LBB0_3 +; CHECK-NEXT: // %bb.2: +; CHECK-NEXT: mov w0, #1 // =0x1 +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB0_3: // %bb2 +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: ret ; CHECK-CGP-LABEL: @and_sink1( ; CHECK-CGP-NOT: and i32 @@ -35,12 +45,30 @@ bb2: ; Test that both 'and' and cmp get sunk to form tbz. define dso_local i32 @and_sink2(i32 %a, i1 %c, i1 %c2) { ; CHECK-LABEL: and_sink2: -; CHECK: str wzr, [x{{[0-9]+}}, :lo12:A] -; CHECK: tbz w1, #0 -; CHECK: str wzr, [x{{[0-9]+}}, :lo12:B] -; CHECK: tbz w2, #0 -; CHECK: str wzr, [x{{[0-9]+}}, :lo12:C] -; CHECK: tbnz {{w[0-9]+}}, #2 +; CHECK: // %bb.0: +; CHECK-NEXT: mov w8, wzr +; CHECK-NEXT: adrp x9, A +; CHECK-NEXT: str wzr, [x9, :lo12:A] +; CHECK-NEXT: tbz w1, #0, .LBB1_5 +; CHECK-NEXT: // %bb.1: // %bb0.preheader +; CHECK-NEXT: adrp x8, B +; CHECK-NEXT: adrp x9, C +; CHECK-NEXT: .LBB1_2: // %bb0 +; CHECK-NEXT: // =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: str wzr, [x8, :lo12:B] +; CHECK-NEXT: tbz w2, #0, .LBB1_6 +; CHECK-NEXT: // %bb.3: // %bb1 +; CHECK-NEXT: // in Loop: Header=BB1_2 Depth=1 +; CHECK-NEXT: str wzr, [x9, :lo12:C] +; CHECK-NEXT: tbnz w0, #2, .LBB1_2 +; CHECK-NEXT: // %bb.4: +; CHECK-NEXT: mov w8, #1 // =0x1 +; CHECK-NEXT: .LBB1_5: // %common.ret +; CHECK-NEXT: mov w0, w8 +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB1_6: +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: ret ; CHECK-CGP-LABEL: @and_sink2( ; CHECK-CGP-NOT: and i32 @@ -71,10 +99,16 @@ bb3: ; Test that 'and' is not sunk since cbz is a better alternative. define dso_local i32 @and_sink3(i32 %a) { ; CHECK-LABEL: and_sink3: -; CHECK: and [[REG:w[0-9]+]], w0, #0x3 -; CHECK: [[LOOP:.L[A-Z0-9_]+]]: -; CHECK: str wzr, [x{{[0-9]+}}, :lo12:A] -; CHECK: cbz [[REG]], [[LOOP]] +; CHECK: // %bb.0: +; CHECK-NEXT: adrp x8, A +; CHECK-NEXT: and w9, w0, #0x3 +; CHECK-NEXT: .LBB2_1: // %bb0 +; CHECK-NEXT: // =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: str wzr, [x8, :lo12:A] +; CHECK-NEXT: cbz w9, .LBB2_1 +; CHECK-NEXT: // %bb.2: // %bb2 +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: ret ; CHECK-CGP-LABEL: @and_sink3( ; CHECK-CGP-NEXT: and i32 diff --git a/llvm/test/CodeGen/AArch64/arm64-anyregcc.ll b/llvm/test/CodeGen/AArch64/arm64-anyregcc.ll index 225d4c602f181f82d72e21d15b9f83951057c082..cb6586718450a2c43db079438f8a11d6b993d143 100644 --- a/llvm/test/CodeGen/AArch64/arm64-anyregcc.ll +++ b/llvm/test/CodeGen/AArch64/arm64-anyregcc.ll @@ -1,6 +1,6 @@ ; RUN: llc < %s -debug-entry-values -mtriple=arm64-apple-darwin | FileCheck %s -; Stackmap Header: no constants - 6 callsites +; Stackmap Header: no constants - 18 callsites ; CHECK-LABEL: .section __LLVM_STACKMAPS,__llvm_stackmaps ; CHECK-NEXT: __LLVM_StackMaps: ; Header @@ -8,11 +8,11 @@ ; CHECK-NEXT: .byte 0 ; CHECK-NEXT: .short 0 ; Num Functions -; CHECK-NEXT: .long 8 +; CHECK-NEXT: .long 18 ; Num LargeConstants ; CHECK-NEXT: .long 0 ; Num Callsites -; CHECK-NEXT: .long 8 +; CHECK-NEXT: .long 18 ; Functions and stack size ; CHECK-NEXT: .quad _test @@ -39,6 +39,36 @@ ; CHECK-NEXT: .quad _patchpoint_spillargs ; CHECK-NEXT: .quad 128 ; CHECK-NEXT: .quad 1 +; CHECK-NEXT: .quad _generic_test_i32 +; CHECK-NEXT: .quad 16 +; CHECK-NEXT: .quad 1 +; CHECK-NEXT: .quad _generic_test_i64 +; CHECK-NEXT: .quad 16 +; CHECK-NEXT: .quad 1 +; CHECK-NEXT: .quad _generic_test_p0 +; CHECK-NEXT: .quad 16 +; CHECK-NEXT: .quad 1 +; CHECK-NEXT: .quad _generic_test_f16 +; CHECK-NEXT: .quad 16 +; CHECK-NEXT: .quad 1 +; CHECK-NEXT: .quad _generic_test_f32 +; CHECK-NEXT: .quad 16 +; CHECK-NEXT: .quad 1 +; CHECK-NEXT: .quad _generic_test_f64 +; CHECK-NEXT: .quad 16 +; CHECK-NEXT: .quad 1 +; CHECK-NEXT: .quad _generic_test_v16i8 +; CHECK-NEXT: .quad 16 +; CHECK-NEXT: .quad 1 +; CHECK-NEXT: .quad _generic_test_v4i32 +; CHECK-NEXT: .quad 16 +; CHECK-NEXT: .quad 1 +; CHECK-NEXT: .quad _generic_test_v4f32 +; CHECK-NEXT: .quad 16 +; CHECK-NEXT: .quad 1 +; CHECK-NEXT: .quad _generic_test_v2f64 +; CHECK-NEXT: .quad 16 +; CHECK-NEXT: .quad 1 ; test @@ -457,5 +487,194 @@ entry: ret i64 %result } +; generic_test_i32 +; CHECK-LABEL: .long L{{.*}}-_generic_test_i32 +; CHECK-NEXT: .short 0 +; 1 location +; CHECK-NEXT: .short 1 +; Loc 0: Register <-- this is the return register +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .short 4 +; CHECK-NEXT: .short {{[0-9]+}} +; CHECK-NEXT: .short 0 +; CHECK-NEXT: .long 0 +define i32 @generic_test_i32() nounwind ssp uwtable { +entry: + %ret = call anyregcc i32 (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.i32(i64 14, i32 20, ptr null, i32 0) + ret i32 %ret +} + +; generic_test_i64 +; CHECK-LABEL: .long L{{.*}}-_generic_test_i64 +; CHECK-NEXT: .short 0 +; 1 location +; CHECK-NEXT: .short 1 +; Loc 0: Register <-- this is the return register +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .short 8 +; CHECK-NEXT: .short {{[0-9]+}} +; CHECK-NEXT: .short 0 +; CHECK-NEXT: .long 0 +define i64 @generic_test_i64() nounwind ssp uwtable { +entry: + %ret = call anyregcc i64 (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.i64(i64 14, i32 20, ptr null, i32 0) + ret i64 %ret +} + +; generic_test_p0 +; CHECK-LABEL: .long L{{.*}}-_generic_test_p0 +; CHECK-NEXT: .short 0 +; 1 location +; CHECK-NEXT: .short 1 +; Loc 0: Register <-- this is the return register +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .short 8 +; CHECK-NEXT: .short {{[0-9]+}} +; CHECK-NEXT: .short 0 +; CHECK-NEXT: .long 0 +define ptr @generic_test_p0() nounwind ssp uwtable { +entry: + %ret = call anyregcc ptr (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.p0(i64 14, i32 20, ptr null, i32 0) + ret ptr %ret +} + +; generic_test_f16 +; CHECK-LABEL: .long L{{.*}}-_generic_test_f16 +; CHECK-NEXT: .short 0 +; 1 location +; CHECK-NEXT: .short 1 +; Loc 0: Register <-- this is the return register +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .short 2 +; CHECK-NEXT: .short {{[0-9]+}} +; CHECK-NEXT: .short 0 +; CHECK-NEXT: .long 0 +define half @generic_test_f16() nounwind ssp uwtable { +entry: + %ret = call anyregcc half (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.f16(i64 14, i32 20, ptr null, i32 0) + ret half %ret +} + +; generic_test_f32 +; CHECK-LABEL: .long L{{.*}}-_generic_test_f32 +; CHECK-NEXT: .short 0 +; 1 location +; CHECK-NEXT: .short 1 +; Loc 0: Register <-- this is the return register +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .short 4 +; CHECK-NEXT: .short {{[0-9]+}} +; CHECK-NEXT: .short 0 +; CHECK-NEXT: .long 0 +define float @generic_test_f32() nounwind ssp uwtable { +entry: + %ret = call anyregcc float (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.f32(i64 14, i32 20, ptr null, i32 0) + ret float %ret +} + +; generic_test_f64 +; CHECK-LABEL: .long L{{.*}}-_generic_test_f64 +; CHECK-NEXT: .short 0 +; 1 location +; CHECK-NEXT: .short 1 +; Loc 0: Register <-- this is the return register +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .short 8 +; CHECK-NEXT: .short {{[0-9]+}} +; CHECK-NEXT: .short 0 +; CHECK-NEXT: .long 0 +define double @generic_test_f64() nounwind ssp uwtable { +entry: + %ret = call anyregcc double (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.f64(i64 14, i32 20, ptr null, i32 0) + ret double %ret +} + +; generic_test_v16i8 +; CHECK-LABEL: .long L{{.*}}-_generic_test_v16i8 +; CHECK-NEXT: .short 0 +; 1 location +; CHECK-NEXT: .short 1 +; Loc 0: Register <-- this is the return register +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .short 16 +; CHECK-NEXT: .short {{[0-9]+}} +; CHECK-NEXT: .short 0 +; CHECK-NEXT: .long 0 +define <16 x i8> @generic_test_v16i8() nounwind ssp uwtable { +entry: + %ret = call anyregcc <16 x i8> (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.v16i8(i64 14, i32 20, ptr null, i32 0) + ret <16 x i8> %ret +} + +; generic_test_v4i32 +; CHECK-LABEL: .long L{{.*}}-_generic_test_v4i32 +; CHECK-NEXT: .short 0 +; 1 location +; CHECK-NEXT: .short 1 +; Loc 0: Register <-- this is the return register +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .short 16 +; CHECK-NEXT: .short {{[0-9]+}} +; CHECK-NEXT: .short 0 +; CHECK-NEXT: .long 0 +define <4 x i32> @generic_test_v4i32() nounwind ssp uwtable { +entry: + %ret = call anyregcc <4 x i32> (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.v4i32(i64 14, i32 20, ptr null, i32 0) + ret <4 x i32> %ret +} + +; generic_test_v4f32 +; CHECK-LABEL: .long L{{.*}}-_generic_test_v4f32 +; CHECK-NEXT: .short 0 +; 1 location +; CHECK-NEXT: .short 1 +; Loc 0: Register <-- this is the return register +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .short 16 +; CHECK-NEXT: .short {{[0-9]+}} +; CHECK-NEXT: .short 0 +; CHECK-NEXT: .long 0 +define <4 x float> @generic_test_v4f32() nounwind ssp uwtable { +entry: + %ret = call anyregcc <4 x float> (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.v4f32(i64 14, i32 20, ptr null, i32 0) + ret <4 x float> %ret +} + +; generic_test_v2f64 +; CHECK-LABEL: .long L{{.*}}-_generic_test_v2f64 +; CHECK-NEXT: .short 0 +; 1 location +; CHECK-NEXT: .short 1 +; Loc 0: Register <-- this is the return register +; CHECK-NEXT: .byte 1 +; CHECK-NEXT: .byte 0 +; CHECK-NEXT: .short 16 +; CHECK-NEXT: .short {{[0-9]+}} +; CHECK-NEXT: .short 0 +; CHECK-NEXT: .long 0 +define <2 x double> @generic_test_v2f64() nounwind ssp uwtable { +entry: + %ret = call anyregcc <2 x double> (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.v2f64(i64 14, i32 20, ptr null, i32 0) + ret <2 x double> %ret +} + declare void @llvm.experimental.patchpoint.void(i64, i32, ptr, i32, ...) +declare i32 @llvm.experimental.patchpoint.i32(i64, i32, ptr, i32, ...) declare i64 @llvm.experimental.patchpoint.i64(i64, i32, ptr, i32, ...) +declare ptr @llvm.experimental.patchpoint.p0(i64, i32, ptr, i32, ...) +declare half @llvm.experimental.patchpoint.f16(i64, i32, ptr, i32, ...) +declare float @llvm.experimental.patchpoint.f32(i64, i32, ptr, i32, ...) +declare double @llvm.experimental.patchpoint.f64(i64, i32, ptr, i32, ...) +declare <16 x i8> @llvm.experimental.patchpoint.v16i8(i64, i32, ptr, i32, ...) +declare <4 x i32> @llvm.experimental.patchpoint.v4i32(i64, i32, ptr, i32, ...) +declare <4 x float> @llvm.experimental.patchpoint.v4f32(i64, i32, ptr, i32, ...) +declare <2 x double> @llvm.experimental.patchpoint.v2f64(i64, i32, ptr, i32, ...) diff --git a/llvm/test/CodeGen/AArch64/arm64-convert-v4f64.ll b/llvm/test/CodeGen/AArch64/arm64-convert-v4f64.ll index 49325299f74a129510cbfa630f50e9937bc6bc98..3007e7ce771e62a853ec41a46410b5b2c87ee715 100644 --- a/llvm/test/CodeGen/AArch64/arm64-convert-v4f64.ll +++ b/llvm/test/CodeGen/AArch64/arm64-convert-v4f64.ll @@ -8,9 +8,8 @@ define <4 x i16> @fptosi_v4f64_to_v4i16(ptr %ptr) { ; CHECK-NEXT: ldp q0, q1, [x0] ; CHECK-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-NEXT: xtn v1.2s, v1.2d -; CHECK-NEXT: xtn v0.2s, v0.2d -; CHECK-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-NEXT: xtn v0.4h, v0.4s ; CHECK-NEXT: ret %tmp1 = load <4 x double>, ptr %ptr %tmp2 = fptosi <4 x double> %tmp1 to <4 x i16> @@ -26,13 +25,10 @@ define <8 x i8> @fptosi_v4f64_to_v4i8(ptr %ptr) { ; CHECK-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-NEXT: fcvtzs v3.2d, v3.2d ; CHECK-NEXT: fcvtzs v2.2d, v2.2d -; CHECK-NEXT: xtn v0.2s, v0.2d -; CHECK-NEXT: xtn v1.2s, v1.2d -; CHECK-NEXT: xtn v3.2s, v3.2d -; CHECK-NEXT: xtn v2.2s, v2.2d -; CHECK-NEXT: uzp1 v0.4h, v1.4h, v0.4h -; CHECK-NEXT: uzp1 v1.4h, v2.4h, v3.4h -; CHECK-NEXT: uzp1 v0.8b, v1.8b, v0.8b +; CHECK-NEXT: uzp1 v0.4s, v1.4s, v0.4s +; CHECK-NEXT: uzp1 v1.4s, v2.4s, v3.4s +; CHECK-NEXT: uzp1 v0.8h, v1.8h, v0.8h +; CHECK-NEXT: xtn v0.8b, v0.8h ; CHECK-NEXT: ret %tmp1 = load <8 x double>, ptr %ptr %tmp2 = fptosi <8 x double> %tmp1 to <8 x i8> @@ -96,9 +92,8 @@ define <4 x i16> @fptoui_v4f64_to_v4i16(ptr %ptr) { ; CHECK-NEXT: ldp q0, q1, [x0] ; CHECK-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-NEXT: xtn v1.2s, v1.2d -; CHECK-NEXT: xtn v0.2s, v0.2d -; CHECK-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-NEXT: xtn v0.4h, v0.4s ; CHECK-NEXT: ret %tmp1 = load <4 x double>, ptr %ptr %tmp2 = fptoui <4 x double> %tmp1 to <4 x i16> diff --git a/llvm/test/CodeGen/AArch64/arm64-extract-insert-varidx.ll b/llvm/test/CodeGen/AArch64/arm64-extract-insert-varidx.ll index a1e06936852726caea2eda0c5be0cec4ff662464..bc399c8d4ff07111c644a3d6d57f87536de6cd40 100644 --- a/llvm/test/CodeGen/AArch64/arm64-extract-insert-varidx.ll +++ b/llvm/test/CodeGen/AArch64/arm64-extract-insert-varidx.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 ; RUN: llc < %s -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -mattr=+neon -fp-contract=fast -aarch64-enable-sink-fold=true | FileCheck %s --check-prefix=CHECK-SDAG -; RUN: llc < %s -global-isel -global-isel-abort=2 -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -mattr=+neon -fp-contract=fast -aarch64-enable-sink-fold=true | FileCheck %s --check-prefix=CHECK-GISEL +; RUN: llc < %s -global-isel -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -mattr=+neon -fp-contract=fast -aarch64-enable-sink-fold=true | FileCheck %s --check-prefix=CHECK-GISEL define <4 x i8> @test_varidx_extract_v8s8(<8 x i8> %x, i32 %idx) { ; CHECK-SDAG-LABEL: test_varidx_extract_v8s8: @@ -29,20 +29,20 @@ define <4 x i8> @test_varidx_extract_v8s8(<8 x i8> %x, i32 %idx) { ; CHECK-GISEL-NEXT: .cfi_def_cfa_offset 16 ; CHECK-GISEL-NEXT: mov w9, w0 ; CHECK-GISEL-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GISEL-NEXT: mov b1, v0.b[1] ; CHECK-GISEL-NEXT: add x8, sp, #8 -; CHECK-GISEL-NEXT: str d0, [sp, #8] ; CHECK-GISEL-NEXT: and x9, x9, #0x7 -; CHECK-GISEL-NEXT: mov b2, v0.b[1] +; CHECK-GISEL-NEXT: str d0, [sp, #8] ; CHECK-GISEL-NEXT: mov b3, v0.b[2] ; CHECK-GISEL-NEXT: lsl x10, x9, #1 ; CHECK-GISEL-NEXT: mov b0, v0.b[3] ; CHECK-GISEL-NEXT: sub x9, x10, x9 -; CHECK-GISEL-NEXT: ldrb w8, [x8, x9] -; CHECK-GISEL-NEXT: fmov s1, w8 -; CHECK-GISEL-NEXT: mov v1.h[1], v2.h[0] -; CHECK-GISEL-NEXT: mov v1.h[2], v3.h[0] -; CHECK-GISEL-NEXT: mov v1.h[3], v0.h[0] -; CHECK-GISEL-NEXT: fmov d0, d1 +; CHECK-GISEL-NEXT: ldr b2, [x8, x9] +; CHECK-GISEL-NEXT: mov v2.b[1], v1.b[0] +; CHECK-GISEL-NEXT: mov v2.b[2], v3.b[0] +; CHECK-GISEL-NEXT: mov v2.b[3], v0.b[0] +; CHECK-GISEL-NEXT: ushll v0.8h, v2.8b, #0 +; CHECK-GISEL-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GISEL-NEXT: add sp, sp, #16 ; CHECK-GISEL-NEXT: ret %tmp = extractelement <8 x i8> %x, i32 %idx @@ -176,17 +176,15 @@ define <2 x i16> @test_varidx_extract_v4s16(<4 x i16> %x, i32 %idx) { ; CHECK-GISEL: // %bb.0: ; CHECK-GISEL-NEXT: sub sp, sp, #16 ; CHECK-GISEL-NEXT: .cfi_def_cfa_offset 16 -; CHECK-GISEL-NEXT: mov w9, w0 -; CHECK-GISEL-NEXT: mov w8, #2 // =0x2 -; CHECK-GISEL-NEXT: add x10, sp, #8 -; CHECK-GISEL-NEXT: and x9, x9, #0x3 ; CHECK-GISEL-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GISEL-NEXT: mov w9, w0 +; CHECK-GISEL-NEXT: mov h1, v0.h[1] +; CHECK-GISEL-NEXT: add x8, sp, #8 ; CHECK-GISEL-NEXT: str d0, [sp, #8] -; CHECK-GISEL-NEXT: madd x8, x9, x8, x10 -; CHECK-GISEL-NEXT: umov w9, v0.h[1] -; CHECK-GISEL-NEXT: fmov s1, w9 -; CHECK-GISEL-NEXT: ldr h0, [x8] -; CHECK-GISEL-NEXT: mov v0.s[1], v1.s[0] +; CHECK-GISEL-NEXT: and x9, x9, #0x3 +; CHECK-GISEL-NEXT: ldr h0, [x8, x9, lsl #1] +; CHECK-GISEL-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GISEL-NEXT: ushll v0.4s, v0.4h, #0 ; CHECK-GISEL-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GISEL-NEXT: add sp, sp, #16 ; CHECK-GISEL-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/arm64-patchpoint.ll b/llvm/test/CodeGen/AArch64/arm64-patchpoint.ll index c58f4b10290974a536327b6493fd455e88b2589e..f948d78723e90ed23ee79e0709cb5063e1973be0 100644 --- a/llvm/test/CodeGen/AArch64/arm64-patchpoint.ll +++ b/llvm/test/CodeGen/AArch64/arm64-patchpoint.ll @@ -79,6 +79,145 @@ entry: ret void } +; Test register allocation for an i32 result value of patchpoint. +define i32 @generic_patchpoint_i32() { +entry: +; CHECK-LABEL: generic_patchpoint_i32: +; CHECK: Ltmp +; CHECK-NEXT: nop +; The return value is already in w0. +; CHECK-NEXT: ldp +; CHECK-NEXT: ret + %result = tail call i32 (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.i32(i64 5, i32 4, ptr null, i32 0) + ret i32 %result +} + +; Test register allocation for an i64 result value of patchpoint. +define i64 @generic_patchpoint_i64() { +entry: +; CHECK-LABEL: generic_patchpoint_i64: +; CHECK: Ltmp +; CHECK-NEXT: nop +; The return value is already in x0. +; CHECK-NEXT: ldp +; CHECK-NEXT: ret + %result = tail call i64 (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.i64(i64 5, i32 4, ptr null, i32 0) + ret i64 %result +} + +; Test register allocation for a ptr result value of patchpoint. +define ptr @generic_patchpoint_p0() { +entry: +; CHECK-LABEL: generic_patchpoint_p0: +; CHECK: Ltmp +; CHECK-NEXT: nop +; The return value is already in x0. +; CHECK-NEXT: ldp +; CHECK-NEXT: ret + %result = tail call ptr (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.p0(i64 5, i32 4, ptr null, i32 0) + ret ptr %result +} + +; Test register allocation for a half result value of patchpoint. +define half @generic_patchpoint_f16() { +entry: +; CHECK-LABEL: generic_patchpoint_f16: +; CHECK: Ltmp +; CHECK-NEXT: nop +; The return value is already in h0. +; CHECK-NEXT: ldp +; CHECK-NEXT: ret + %result = tail call half (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.f16(i64 5, i32 4, ptr null, i32 0) + ret half %result +} + +; Test register allocation for a float result value of patchpoint. +define float @generic_patchpoint_f32() { +entry: +; CHECK-LABEL: generic_patchpoint_f32: +; CHECK: Ltmp +; CHECK-NEXT: nop +; The return value is already in s0. +; CHECK-NEXT: ldp +; CHECK-NEXT: ret + %result = tail call float (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.f32(i64 5, i32 4, ptr null, i32 0) + ret float %result +} + +; Test register allocation for a double result value of patchpoint. +define double @generic_patchpoint_f64() { +entry: +; CHECK-LABEL: generic_patchpoint_f64: +; CHECK: Ltmp +; CHECK-NEXT: nop +; The return value is already in d0. +; CHECK-NEXT: ldp +; CHECK-NEXT: ret + %result = tail call double (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.f64(i64 5, i32 4, ptr null, i32 0) + ret double %result +} + +; Test register allocation for a <16 x i8> result value of patchpoint. +define <16 x i8> @generic_patchpoint_v16i8() { +entry: +; CHECK-LABEL: generic_patchpoint_v16i8: +; CHECK: Ltmp +; CHECK-NEXT: nop +; The return value is already in v0.16b. +; CHECK-NEXT: ldp +; CHECK-NEXT: ret + %result = tail call <16 x i8> (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.v16i8(i64 5, i32 4, ptr null, i32 0) + ret <16 x i8> %result +} + +; Test register allocation for a <4 x i32> result value of patchpoint. +define <4 x i32> @generic_patchpoint_v4i32() { +entry: +; CHECK-LABEL: generic_patchpoint_v4i32: +; CHECK: Ltmp +; CHECK-NEXT: nop +; The return value is already in v0.4s. +; CHECK-NEXT: ldp +; CHECK-NEXT: ret + %result = tail call <4 x i32> (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.v4i32(i64 5, i32 4, ptr null, i32 0) + ret <4 x i32> %result +} + +; Test register allocation for a <4 x float> result value of patchpoint. +define <4 x float> @generic_patchpoint_v4f32() { +entry: +; CHECK-LABEL: generic_patchpoint_v4f32: +; CHECK: Ltmp +; CHECK-NEXT: nop +; The return value is already in v0.4s. +; CHECK-NEXT: ldp +; CHECK-NEXT: ret + %result = tail call <4 x float> (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.v4f32(i64 5, i32 4, ptr null, i32 0) + ret <4 x float> %result +} + +; Test register allocation for a <2 x double> result value of patchpoint. +define <2 x double> @generic_patchpoint_v2f64() { +entry: +; CHECK-LABEL: generic_patchpoint_v2f64: +; CHECK: Ltmp +; CHECK-NEXT: nop +; The return value is already in v0.2d. +; CHECK-NEXT: ldp +; CHECK-NEXT: ret + %result = tail call <2 x double> (i64, i32, ptr, i32, ...) @llvm.experimental.patchpoint.v2f64(i64 5, i32 4, ptr null, i32 0) + ret <2 x double> %result +} + declare void @llvm.experimental.stackmap(i64, i32, ...) declare void @llvm.experimental.patchpoint.void(i64, i32, ptr, i32, ...) +declare i32 @llvm.experimental.patchpoint.i32(i64, i32, ptr, i32, ...) declare i64 @llvm.experimental.patchpoint.i64(i64, i32, ptr, i32, ...) +declare ptr @llvm.experimental.patchpoint.p0(i64, i32, ptr, i32, ...) +declare half @llvm.experimental.patchpoint.f16(i64, i32, ptr, i32, ...) +declare float @llvm.experimental.patchpoint.f32(i64, i32, ptr, i32, ...) +declare double @llvm.experimental.patchpoint.f64(i64, i32, ptr, i32, ...) +declare <16 x i8> @llvm.experimental.patchpoint.v16i8(i64, i32, ptr, i32, ...) +declare <4 x i32> @llvm.experimental.patchpoint.v4i32(i64, i32, ptr, i32, ...) +declare <4 x float> @llvm.experimental.patchpoint.v4f32(i64, i32, ptr, i32, ...) +declare <2 x double> @llvm.experimental.patchpoint.v2f64(i64, i32, ptr, i32, ...) diff --git a/llvm/test/CodeGen/AArch64/arm64-xaluo.ll b/llvm/test/CodeGen/AArch64/arm64-xaluo.ll index 77c70668b65a01d4fdf305e15f345cdbc5d5fca5..0ec2d763685e91b26154409a1cf18ccbab381d27 100644 --- a/llvm/test/CodeGen/AArch64/arm64-xaluo.ll +++ b/llvm/test/CodeGen/AArch64/arm64-xaluo.ll @@ -2643,8 +2643,7 @@ define i8 @pr60530() { ; ; GISEL-LABEL: pr60530: ; GISEL: // %bb.0: -; GISEL-NEXT: mov w8, #1 // =0x1 -; GISEL-NEXT: sbfx w0, w8, #0, #1 +; GISEL-NEXT: mov w0, #255 // =0xff ; GISEL-NEXT: ret %1 = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 0, i8 1) %2 = extractvalue { i8, i1 } %1, 1 diff --git a/llvm/test/CodeGen/AArch64/avoid-zero-copy.mir b/llvm/test/CodeGen/AArch64/avoid-zero-copy.mir index 859be2d3374762f17ae19af93f1f907d3833b792..b940734c6988cb3f53743d8585ffe152579b0c90 100644 --- a/llvm/test/CodeGen/AArch64/avoid-zero-copy.mir +++ b/llvm/test/CodeGen/AArch64/avoid-zero-copy.mir @@ -19,6 +19,8 @@ ... --- name: foo +frameInfo: + adjustsStack: true body: | bb.0 (%ir-block.0): ; CHECK-LABEL: name: foo diff --git a/llvm/test/CodeGen/AArch64/bitcast.ll b/llvm/test/CodeGen/AArch64/bitcast.ll index bccfdb93d786f39a14af8e28d7dc3c98a6b842ab..e0851fd8739ec9d66def59fbe0815e9fd74f6d5a 100644 --- a/llvm/test/CodeGen/AArch64/bitcast.ll +++ b/llvm/test/CodeGen/AArch64/bitcast.ll @@ -1,16 +1,9 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 ; RUN: llc -mtriple=aarch64 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-SD -; RUN: llc -mtriple=aarch64 -global-isel -global-isel-abort=2 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI +; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI ; PR23065: SCALAR_TO_VECTOR implies the top elements 1 to N-1 of the N-element vector are undefined. -; CHECK-GI: warning: Instruction selection used fallback path for bitcast_v4i8_i32 -; CHECK-GI-NEXT: warning: Instruction selection used fallback path for bitcast_i32_v4i8 -; CHECK-GI-NEXT: warning: Instruction selection used fallback path for bitcast_v2i16_i32 -; CHECK-GI-NEXT: warning: Instruction selection used fallback path for bitcast_i32_v2i16 -; CHECK-GI-NEXT: warning: Instruction selection used fallback path for bitcast_v2i16_v4i8 -; CHECK-GI-NEXT: warning: Instruction selection used fallback path for bitcast_v4i8_v2i16 - define <4 x i16> @foo1(<2 x i32> %a) { ; CHECK-SD-LABEL: foo1: ; CHECK-SD: // %bb.0: @@ -54,58 +47,104 @@ define <4 x i16> @foo2(<2 x i32> %a) { ; ===== To and From Scalar Types ===== define i32 @bitcast_v4i8_i32(<4 x i8> %a, <4 x i8> %b){ -; CHECK-LABEL: bitcast_v4i8_i32: -; CHECK: // %bb.0: -; CHECK-NEXT: sub sp, sp, #16 -; CHECK-NEXT: .cfi_def_cfa_offset 16 -; CHECK-NEXT: add v0.4h, v0.4h, v1.4h -; CHECK-NEXT: xtn v0.8b, v0.8h -; CHECK-NEXT: fmov w0, s0 -; CHECK-NEXT: add sp, sp, #16 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: bitcast_v4i8_i32: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: add v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v0.8b +; CHECK-SD-NEXT: fmov w0, s0 +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: bitcast_v4i8_i32: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: add v0.4h, v0.4h, v1.4h +; CHECK-GI-NEXT: mov h1, v0.h[1] +; CHECK-GI-NEXT: mov h2, v0.h[2] +; CHECK-GI-NEXT: mov h3, v0.h[3] +; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NEXT: mov v0.h[2], v2.h[0] +; CHECK-GI-NEXT: mov v0.h[3], v3.h[0] +; CHECK-GI-NEXT: xtn v0.8b, v0.8h +; CHECK-GI-NEXT: fmov w0, s0 +; CHECK-GI-NEXT: ret %c = add <4 x i8> %a, %b %d = bitcast <4 x i8> %c to i32 ret i32 %d } define <4 x i8> @bitcast_i32_v4i8(i32 %a, i32 %b){ -; CHECK-LABEL: bitcast_i32_v4i8: -; CHECK: // %bb.0: -; CHECK-NEXT: add w8, w0, w1 -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: zip1 v0.8b, v0.8b, v0.8b -; CHECK-NEXT: ret +; CHECK-SD-LABEL: bitcast_i32_v4i8: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: add w8, w0, w1 +; CHECK-SD-NEXT: fmov s0, w8 +; CHECK-SD-NEXT: zip1 v0.8b, v0.8b, v0.8b +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: bitcast_i32_v4i8: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: add w8, w0, w1 +; CHECK-GI-NEXT: fmov s0, w8 +; CHECK-GI-NEXT: mov b1, v0.b[1] +; CHECK-GI-NEXT: mov b2, v0.b[2] +; CHECK-GI-NEXT: mov b3, v0.b[3] +; CHECK-GI-NEXT: mov v0.b[1], v1.b[0] +; CHECK-GI-NEXT: mov v0.b[2], v2.b[0] +; CHECK-GI-NEXT: mov v0.b[3], v3.b[0] +; CHECK-GI-NEXT: ushll v0.8h, v0.8b, #0 +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-GI-NEXT: ret %c = add i32 %a, %b %d = bitcast i32 %c to <4 x i8> ret <4 x i8> %d } define i32 @bitcast_v2i16_i32(<2 x i16> %a, <2 x i16> %b){ -; CHECK-LABEL: bitcast_v2i16_i32: -; CHECK: // %bb.0: -; CHECK-NEXT: sub sp, sp, #16 -; CHECK-NEXT: .cfi_def_cfa_offset 16 -; CHECK-NEXT: add v0.2s, v0.2s, v1.2s -; CHECK-NEXT: mov w8, v0.s[1] -; CHECK-NEXT: fmov w9, s0 -; CHECK-NEXT: strh w9, [sp, #12] -; CHECK-NEXT: strh w8, [sp, #14] -; CHECK-NEXT: ldr w0, [sp, #12] -; CHECK-NEXT: add sp, sp, #16 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: bitcast_v2i16_i32: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: add v0.2s, v0.2s, v1.2s +; CHECK-SD-NEXT: mov w8, v0.s[1] +; CHECK-SD-NEXT: fmov w9, s0 +; CHECK-SD-NEXT: strh w9, [sp, #12] +; CHECK-SD-NEXT: strh w8, [sp, #14] +; CHECK-SD-NEXT: ldr w0, [sp, #12] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: bitcast_v2i16_i32: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: add v0.2s, v0.2s, v1.2s +; CHECK-GI-NEXT: mov s1, v0.s[1] +; CHECK-GI-NEXT: mov v0.s[1], v1.s[0] +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: fmov w0, s0 +; CHECK-GI-NEXT: ret %c = add <2 x i16> %a, %b %d = bitcast <2 x i16> %c to i32 ret i32 %d } define <2 x i16> @bitcast_i32_v2i16(i32 %a, i32 %b){ -; CHECK-LABEL: bitcast_i32_v2i16: -; CHECK: // %bb.0: -; CHECK-NEXT: add w8, w0, w1 -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: ushll v0.4s, v0.4h, #0 -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: bitcast_i32_v2i16: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: add w8, w0, w1 +; CHECK-SD-NEXT: fmov s0, w8 +; CHECK-SD-NEXT: ushll v0.4s, v0.4h, #0 +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: bitcast_i32_v2i16: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: add w8, w0, w1 +; CHECK-GI-NEXT: fmov s0, w8 +; CHECK-GI-NEXT: mov h1, v0.h[1] +; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NEXT: ushll v0.4s, v0.4h, #0 +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-GI-NEXT: ret %c = add i32 %a, %b %d = bitcast i32 %c to <2 x i16> ret <2 x i16> %d @@ -362,40 +401,72 @@ define <8 x i16> @bitcast_v16i8_v8i16(<16 x i8> %a, <16 x i8> %b){ ; ===== Smaller/Larger Width Vectors with Legal Element Sizes ===== define <4 x i8> @bitcast_v2i16_v4i8(<2 x i16> %a, <2 x i16> %b){ -; CHECK-LABEL: bitcast_v2i16_v4i8: -; CHECK: // %bb.0: -; CHECK-NEXT: sub sp, sp, #16 -; CHECK-NEXT: .cfi_def_cfa_offset 16 -; CHECK-NEXT: add v0.2s, v0.2s, v1.2s -; CHECK-NEXT: mov w8, v0.s[1] -; CHECK-NEXT: fmov w9, s0 -; CHECK-NEXT: strh w9, [sp, #12] -; CHECK-NEXT: strh w8, [sp, #14] -; CHECK-NEXT: ldr s0, [sp, #12] -; CHECK-NEXT: ushll v0.8h, v0.8b, #0 -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 -; CHECK-NEXT: add sp, sp, #16 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: bitcast_v2i16_v4i8: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: add v0.2s, v0.2s, v1.2s +; CHECK-SD-NEXT: mov w8, v0.s[1] +; CHECK-SD-NEXT: fmov w9, s0 +; CHECK-SD-NEXT: strh w9, [sp, #12] +; CHECK-SD-NEXT: strh w8, [sp, #14] +; CHECK-SD-NEXT: ldr s0, [sp, #12] +; CHECK-SD-NEXT: ushll v0.8h, v0.8b, #0 +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: bitcast_v2i16_v4i8: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: add v0.2s, v0.2s, v1.2s +; CHECK-GI-NEXT: mov s1, v0.s[1] +; CHECK-GI-NEXT: mov v0.s[1], v1.s[0] +; CHECK-GI-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-NEXT: mov b1, v0.b[1] +; CHECK-GI-NEXT: mov b2, v0.b[2] +; CHECK-GI-NEXT: mov b3, v0.b[3] +; CHECK-GI-NEXT: mov v0.b[1], v1.b[0] +; CHECK-GI-NEXT: mov v0.b[2], v2.b[0] +; CHECK-GI-NEXT: mov v0.b[3], v3.b[0] +; CHECK-GI-NEXT: ushll v0.8h, v0.8b, #0 +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-GI-NEXT: ret %c = add <2 x i16> %a, %b %d = bitcast <2 x i16> %c to <4 x i8> ret <4 x i8> %d } define <2 x i16> @bitcast_v4i8_v2i16(<4 x i8> %a, <4 x i8> %b){ -; CHECK-LABEL: bitcast_v4i8_v2i16: -; CHECK: // %bb.0: -; CHECK-NEXT: sub sp, sp, #16 -; CHECK-NEXT: .cfi_def_cfa_offset 16 -; CHECK-NEXT: add v0.4h, v0.4h, v1.4h -; CHECK-NEXT: add x8, sp, #12 -; CHECK-NEXT: xtn v0.8b, v0.8h -; CHECK-NEXT: str s0, [sp, #12] -; CHECK-NEXT: ld1 { v0.h }[0], [x8] -; CHECK-NEXT: orr x8, x8, #0x2 -; CHECK-NEXT: ld1 { v0.h }[2], [x8] -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 -; CHECK-NEXT: add sp, sp, #16 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: bitcast_v4i8_v2i16: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: add v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: add x8, sp, #12 +; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v0.8b +; CHECK-SD-NEXT: str s0, [sp, #12] +; CHECK-SD-NEXT: ld1 { v0.h }[0], [x8] +; CHECK-SD-NEXT: orr x8, x8, #0x2 +; CHECK-SD-NEXT: ld1 { v0.h }[2], [x8] +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: bitcast_v4i8_v2i16: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: add v0.4h, v0.4h, v1.4h +; CHECK-GI-NEXT: mov h1, v0.h[1] +; CHECK-GI-NEXT: mov h2, v0.h[2] +; CHECK-GI-NEXT: mov h3, v0.h[3] +; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NEXT: mov v0.h[2], v2.h[0] +; CHECK-GI-NEXT: mov v0.h[3], v3.h[0] +; CHECK-GI-NEXT: xtn v0.8b, v0.8h +; CHECK-GI-NEXT: mov h1, v0.h[1] +; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NEXT: ushll v0.4s, v0.4h, #0 +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-GI-NEXT: ret %c = add <4 x i8> %a, %b %d = bitcast <4 x i8> %c to <2 x i16> ret <2 x i16> %d diff --git a/llvm/test/CodeGen/AArch64/bswap.ll b/llvm/test/CodeGen/AArch64/bswap.ll index f4221accfcbc527f5deea82ef74efd6cb7e686ce..071613b9cc011e87a2102b5b25b46e84273fb6bb 100644 --- a/llvm/test/CodeGen/AArch64/bswap.ll +++ b/llvm/test/CodeGen/AArch64/bswap.ll @@ -1,8 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 ; RUN: llc -mtriple=aarch64 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD -; RUN: llc -mtriple=aarch64 -global-isel -global-isel-abort=2 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI - -; CHECK-GI: warning: Instruction selection used fallback path for bswap_v2i16 +; RUN: llc -mtriple=aarch64 -global-isel %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI ; ====== Scalar Tests ===== define i16 @bswap_i16(i16 %a){ @@ -103,11 +101,23 @@ declare <2 x i64> @llvm.bswap.v2i64(<2 x i64>) ; ===== Smaller/Larger Width Vectors with Legal Element Sizes ===== define <2 x i16> @bswap_v2i16(<2 x i16> %a){ -; CHECK-LABEL: bswap_v2i16: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: rev32 v0.8b, v0.8b -; CHECK-NEXT: ushr v0.2s, v0.2s, #16 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: bswap_v2i16: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: rev32 v0.8b, v0.8b +; CHECK-SD-NEXT: ushr v0.2s, v0.2s, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: bswap_v2i16: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-NEXT: mov s1, v0.s[1] +; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NEXT: rev16 v0.8b, v0.8b +; CHECK-GI-NEXT: mov h1, v0.h[1] +; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NEXT: ushll v0.4s, v0.4h, #0 +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-GI-NEXT: ret entry: %res = call <2 x i16> @llvm.bswap.v2i16(<2 x i16> %a) ret <2 x i16> %res diff --git a/llvm/test/CodeGen/AArch64/clear-dead-implicit-def-impdef.mir b/llvm/test/CodeGen/AArch64/clear-dead-implicit-def-impdef.mir index 9040937d027df48574ec081115d71224658ca110..1592c86e267f5ca4869006a9a8a2d6b8b9f24672 100644 --- a/llvm/test/CodeGen/AArch64/clear-dead-implicit-def-impdef.mir +++ b/llvm/test/CodeGen/AArch64/clear-dead-implicit-def-impdef.mir @@ -3,6 +3,8 @@ --- name: func tracksRegLiveness: true +frameInfo: + adjustsStack: true body: | bb.0: liveins: $x0, $x1, $x2, $x3, $x4, $x5, $x6 diff --git a/llvm/test/CodeGen/AArch64/complex-deinterleaving-f16-add.ll b/llvm/test/CodeGen/AArch64/complex-deinterleaving-f16-add.ll index 7b8448de2331b44d92e4b522715ff32fe2ea7688..7cdb10e7159f03e509bcfe2b934f5b684b47a4b8 100644 --- a/llvm/test/CodeGen/AArch64/complex-deinterleaving-f16-add.ll +++ b/llvm/test/CodeGen/AArch64/complex-deinterleaving-f16-add.ll @@ -1,23 +1,42 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s --mattr=+complxnum,+neon,+fullfp16 -o - | FileCheck %s -; RUN: llc < %s --mattr=+complxnum,+neon,+fullfp16,+sve -o - | FileCheck %s -; RUN: llc < %s --mattr=+complxnum,+neon,+fullfp16,+sve2 -o - | FileCheck %s +; RUN: llc < %s --mattr=+complxnum,+neon,+fullfp16 -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD +; RUN: llc < %s --mattr=+complxnum,+neon,+fullfp16,+sve -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD +; RUN: llc < %s --mattr=+complxnum,+neon,+fullfp16,+sve2 -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD +; RUN: llc < %s --global-isel --global-isel-abort=2 --mattr=+complxnum,+neon,+fullfp16 -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI +; RUN: llc < %s --global-isel --global-isel-abort=2 --mattr=+complxnum,+neon,+fullfp16,+sve -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI +; RUN: llc < %s --global-isel --global-isel-abort=2 --mattr=+complxnum,+neon,+fullfp16,+sve2 -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI target triple = "aarch64" +; CHECK-GI: warning: Instruction selection used fallback path for complex_add_v16f16 +; CHECK-GI-NEXT: warning: Instruction selection used fallback path for complex_add_v32f16 +; CHECK-GI-NEXT: warning: Instruction selection used fallback path for complex_add_v16f16_with_intrinsic + ; Expected to not transform define <2 x half> @complex_add_v2f16(<2 x half> %a, <2 x half> %b) { -; CHECK-LABEL: complex_add_v2f16: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: mov h2, v0.h[1] -; CHECK-NEXT: mov h3, v1.h[1] -; CHECK-NEXT: fsub h1, h1, h2 -; CHECK-NEXT: fadd h0, h3, h0 -; CHECK-NEXT: mov v1.h[1], v0.h[0] -; CHECK-NEXT: fmov d0, d1 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: complex_add_v2f16: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-SD-NEXT: mov h2, v0.h[1] +; CHECK-SD-NEXT: mov h3, v1.h[1] +; CHECK-SD-NEXT: fsub h1, h1, h2 +; CHECK-SD-NEXT: fadd h0, h3, h0 +; CHECK-SD-NEXT: mov v1.h[1], v0.h[0] +; CHECK-SD-NEXT: fmov d0, d1 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: complex_add_v2f16: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-GI-NEXT: mov h2, v0.h[1] +; CHECK-GI-NEXT: mov h3, v1.h[1] +; CHECK-GI-NEXT: fsub h1, h1, h2 +; CHECK-GI-NEXT: fadd h0, h3, h0 +; CHECK-GI-NEXT: mov v1.h[1], v0.h[0] +; CHECK-GI-NEXT: fmov d0, d1 +; CHECK-GI-NEXT: ret entry: %a.real = shufflevector <2 x half> %a, <2 x half> zeroinitializer, <1 x i32> <i32 0> %a.imag = shufflevector <2 x half> %a, <2 x half> zeroinitializer, <1 x i32> <i32 1> @@ -162,17 +181,29 @@ entry: ; Expected not to transform as it is integer define <16 x i16> @complex_add_v16i16(<16 x i16> %a, <16 x i16> %b) { -; CHECK-LABEL: complex_add_v16i16: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: uzp1 v4.8h, v2.8h, v3.8h -; CHECK-NEXT: uzp1 v5.8h, v0.8h, v1.8h -; CHECK-NEXT: uzp2 v0.8h, v0.8h, v1.8h -; CHECK-NEXT: uzp2 v1.8h, v2.8h, v3.8h -; CHECK-NEXT: sub v2.8h, v4.8h, v0.8h -; CHECK-NEXT: add v1.8h, v1.8h, v5.8h -; CHECK-NEXT: zip1 v0.8h, v2.8h, v1.8h -; CHECK-NEXT: zip2 v1.8h, v2.8h, v1.8h -; CHECK-NEXT: ret +; CHECK-SD-LABEL: complex_add_v16i16: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: uzp1 v4.8h, v2.8h, v3.8h +; CHECK-SD-NEXT: uzp1 v5.8h, v0.8h, v1.8h +; CHECK-SD-NEXT: uzp2 v0.8h, v0.8h, v1.8h +; CHECK-SD-NEXT: uzp2 v1.8h, v2.8h, v3.8h +; CHECK-SD-NEXT: sub v2.8h, v4.8h, v0.8h +; CHECK-SD-NEXT: add v1.8h, v1.8h, v5.8h +; CHECK-SD-NEXT: zip1 v0.8h, v2.8h, v1.8h +; CHECK-SD-NEXT: zip2 v1.8h, v2.8h, v1.8h +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: complex_add_v16i16: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: uzp1 v4.8h, v0.8h, v1.8h +; CHECK-GI-NEXT: uzp2 v0.8h, v0.8h, v1.8h +; CHECK-GI-NEXT: uzp1 v1.8h, v2.8h, v3.8h +; CHECK-GI-NEXT: uzp2 v2.8h, v2.8h, v3.8h +; CHECK-GI-NEXT: sub v1.8h, v1.8h, v0.8h +; CHECK-GI-NEXT: add v2.8h, v2.8h, v4.8h +; CHECK-GI-NEXT: zip1 v0.8h, v1.8h, v2.8h +; CHECK-GI-NEXT: zip2 v1.8h, v1.8h, v2.8h +; CHECK-GI-NEXT: ret entry: %a.real = shufflevector <16 x i16> %a, <16 x i16> zeroinitializer, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14> %a.imag = shufflevector <16 x i16> %a, <16 x i16> zeroinitializer, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15> diff --git a/llvm/test/CodeGen/AArch64/dllexport.ll b/llvm/test/CodeGen/AArch64/dllexport.ll index 81ba674a0dedc153749b385ce25d5d2718004161..580fb5fd9e79ee385e752dafa83ff578fc0f3805 100644 --- a/llvm/test/CodeGen/AArch64/dllexport.ll +++ b/llvm/test/CodeGen/AArch64/dllexport.ll @@ -1,5 +1,7 @@ ; RUN: llc -mtriple aarch64-windows-gnu -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-GNU ; RUN: llc -mtriple aarch64-windows-msvc -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-MSVC +; RUN: llc -mtriple arm64ec-windows-gnu -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-GNU-EC +; RUN: llc -mtriple arm64ec-windows-msvc -filetype asm -o - %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-MSVC-EC define void @f() { ret void @@ -71,3 +73,40 @@ define weak_odr dllexport void @l() { ; CHECK-MSVC: .ascii " /EXPORT:s" ; CHECK-MSVC: .ascii " /EXPORT:t" ; CHECK-MSVC: .ascii " /EXPORT:u" + +; CHECK-GNU-EC-NOT: -export:f +; CHECK-GNU-EC-NOT: -export:#f,EXPORTAS,f +; CHECK-GNU-EC: .ascii " -export:#g,EXPORTAS,g +; CHECK-GNU-EC: .ascii " -export:#h,EXPORTAS,h +; CHECK-GNU-EC-NOT: -export:i +; CHECK-GNU-EC-NOT: -export:#i,EXPORTAS,i +; CHECK-GNU-EC: .ascii " -export:#j,EXPORTAS,j" +; CHECK-GNU-EC: .ascii " -export:#k,EXPORTAS,k" +; CHECK-GNU-EC: .ascii " -export:#l,EXPORTAS,l" +; CHECK-GNU-EC: .ascii " -export:m,data" +; CHECK-GNU-EC: .ascii " -export:n,data" +; CHECK-GNU-EC: .ascii " -export:o,data" +; CHECK-GNU-EC: .ascii " -export:p,data" +; CHECK-GNU-EC: .ascii " -export:q,data" +; CHECK-GNU-EC: .ascii " -export:r" +; CHECK-GNU-EC: .ascii " -export:s" +; CHECK-GNU-EC: .ascii " -export:t" +; CHECK-GNU-EC: .ascii " -export:u" +; CHECK-MSVC-EC-NOT: /EXPORT:f +; CHECK-MSVC-EC-NOT: /EXPORT:#f,EXPORTAS,f +; CHECK-MSVC-EC: .ascii " /EXPORT:#g,EXPORTAS,g" +; CHECK-MSVC-EC: .ascii " /EXPORT:#h,EXPORTAS,h" +; CHECK-MSVC-EC-NOT: /EXPORT:i +; CHECK-MSVC-EC-NOT: /EXPORT:#i,EXPORTAS,i +; CHECK-MSVC-EC: .ascii " /EXPORT:#j,EXPORTAS,j" +; CHECK-MSVC-EC: .ascii " /EXPORT:#k,EXPORTAS,k" +; CHECK-MSVC-EC: .ascii " /EXPORT:#l,EXPORTAS,l" +; CHECK-MSVC-EC: .ascii " /EXPORT:m,DATA" +; CHECK-MSVC-EC: .ascii " /EXPORT:n,DATA" +; CHECK-MSVC-EC: .ascii " /EXPORT:o,DATA" +; CHECK-MSVC-EC: .ascii " /EXPORT:p,DATA" +; CHECK-MSVC-EC: .ascii " /EXPORT:q,DATA" +; CHECK-MSVC-EC: .ascii " /EXPORT:r" +; CHECK-MSVC-EC: .ascii " /EXPORT:s" +; CHECK-MSVC-EC: .ascii " /EXPORT:t" +; CHECK-MSVC-EC: .ascii " /EXPORT:u" diff --git a/llvm/test/CodeGen/AArch64/extbinopload.ll b/llvm/test/CodeGen/AArch64/extbinopload.ll index 1f68c77611e10d43c265a584df5ff044742e8cf8..dff4831330deb0510c2ca898d71fa90e5128f309 100644 --- a/llvm/test/CodeGen/AArch64/extbinopload.ll +++ b/llvm/test/CodeGen/AArch64/extbinopload.ll @@ -650,7 +650,7 @@ define <16 x i32> @extrause_load(ptr %p, ptr %q, ptr %r, ptr %s, ptr %z) { ; CHECK-NEXT: add x11, x3, #12 ; CHECK-NEXT: str s1, [x4] ; CHECK-NEXT: ushll v1.8h, v1.8b, #0 -; CHECK-NEXT: ldp s0, s5, [x2] +; CHECK-NEXT: ldp s0, s4, [x2] ; CHECK-NEXT: ushll v2.8h, v0.8b, #0 ; CHECK-NEXT: umov w9, v2.h[0] ; CHECK-NEXT: umov w10, v2.h[1] @@ -662,24 +662,25 @@ define <16 x i32> @extrause_load(ptr %p, ptr %q, ptr %r, ptr %s, ptr %z) { ; CHECK-NEXT: ushll v2.8h, v2.8b, #0 ; CHECK-NEXT: mov v0.b[10], w9 ; CHECK-NEXT: add x9, x1, #4 -; CHECK-NEXT: uzp1 v1.8b, v1.8b, v2.8b +; CHECK-NEXT: mov v1.d[1], v2.d[0] ; CHECK-NEXT: mov v0.b[11], w10 ; CHECK-NEXT: add x10, x1, #12 +; CHECK-NEXT: bic v1.8h, #255, lsl #8 ; CHECK-NEXT: ld1 { v0.s }[3], [x3], #4 -; CHECK-NEXT: ldr s4, [x0, #12] -; CHECK-NEXT: ldp s3, s16, [x0, #4] -; CHECK-NEXT: ld1 { v5.s }[1], [x3] -; CHECK-NEXT: ldp s6, s7, [x2, #8] -; CHECK-NEXT: ld1 { v4.s }[1], [x10] -; CHECK-NEXT: ld1 { v3.s }[1], [x9] -; CHECK-NEXT: ld1 { v6.s }[1], [x8] -; CHECK-NEXT: ld1 { v7.s }[1], [x11] +; CHECK-NEXT: ldr s3, [x0, #12] +; CHECK-NEXT: ldp s2, s7, [x0, #4] +; CHECK-NEXT: ld1 { v4.s }[1], [x3] +; CHECK-NEXT: ldp s5, s6, [x2, #8] +; CHECK-NEXT: ld1 { v3.s }[1], [x10] +; CHECK-NEXT: ld1 { v2.s }[1], [x9] +; CHECK-NEXT: ld1 { v5.s }[1], [x8] +; CHECK-NEXT: ld1 { v6.s }[1], [x11] ; CHECK-NEXT: add x8, x1, #8 -; CHECK-NEXT: ld1 { v16.s }[1], [x8] -; CHECK-NEXT: uaddl v2.8h, v3.8b, v4.8b -; CHECK-NEXT: ushll v3.8h, v6.8b, #0 -; CHECK-NEXT: uaddl v4.8h, v5.8b, v7.8b -; CHECK-NEXT: uaddl v1.8h, v1.8b, v16.8b +; CHECK-NEXT: ld1 { v7.s }[1], [x8] +; CHECK-NEXT: uaddl v2.8h, v2.8b, v3.8b +; CHECK-NEXT: ushll v3.8h, v5.8b, #0 +; CHECK-NEXT: uaddl v4.8h, v4.8b, v6.8b +; CHECK-NEXT: uaddw v1.8h, v1.8h, v7.8b ; CHECK-NEXT: uaddw2 v5.8h, v3.8h, v0.16b ; CHECK-NEXT: ushll v0.4s, v2.4h, #3 ; CHECK-NEXT: ushll2 v2.4s, v2.8h, #3 diff --git a/llvm/test/CodeGen/AArch64/extract-vector-elt.ll b/llvm/test/CodeGen/AArch64/extract-vector-elt.ll new file mode 100644 index 0000000000000000000000000000000000000000..504222e0036e2229dd06ac1ec142801aa9121cab --- /dev/null +++ b/llvm/test/CodeGen/AArch64/extract-vector-elt.ll @@ -0,0 +1,1114 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple=aarch64 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD +; RUN: llc -mtriple=aarch64 -global-isel -global-isel-abort=2 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI + +; CHECK-GI: warning: Instruction selection used fallback path for extract_v4i32_vector_insert +; CHECK-GI-NEXT: warning: Instruction selection used fallback path for extract_v4i32_vector_insert_const +; CHECK-GI-NEXT: warning: Instruction selection used fallback path for extract_v4i32_vector_extract +; CHECK-GI-NEXT: warning: Instruction selection used fallback path for extract_v4i32_vector_extract_const + +define i64 @extract_v2i64_undef_index(<2 x i64> %a, i32 %c) { +; CHECK-SD-LABEL: extract_v2i64_undef_index: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: fmov x0, d0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v2i64_undef_index: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: str q0, [sp, #-16]! +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: ldr x0, [sp], #16 +; CHECK-GI-NEXT: ret +entry: + %d = extractelement <2 x i64> %a, i32 undef + ret i64 %d +} + +define i64 @extract_v2i64_undef_vector(<2 x i64> %a, i32 %c) { +; CHECK-LABEL: extract_v2i64_undef_vector: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: ret +entry: + %d = extractelement <2 x i64> undef, i32 %c + ret i64 %d +} + +define i64 @extract_v2i64_opaque(<2 x i64> %a, i32 %c) { +; CHECK-SD-LABEL: extract_v2i64_opaque: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: str q0, [sp] +; CHECK-SD-NEXT: bfi x8, x0, #3, #1 +; CHECK-SD-NEXT: ldr x0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v2i64_opaque: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: mov w9, w0 +; CHECK-GI-NEXT: mov x8, sp +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: and x9, x9, #0x1 +; CHECK-GI-NEXT: ldr x0, [x8, x9, lsl #3] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %d = extractelement <2 x i64> %a, i32 %c + ret i64 %d +} + +define i64 @extract_v2i64_oob(<2 x i64> %a, i32 %c) { +; CHECK-LABEL: extract_v2i64_oob: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: ret +entry: + %d = extractelement <2 x i64> %a, i32 5 + ret i64 %d +} + +define i64 @extract_v2i64_freeze(<2 x i64> %a, i32 %c) { +; CHECK-SD-LABEL: extract_v2i64_freeze: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: str q0, [sp] +; CHECK-SD-NEXT: bfi x8, x0, #3, #1 +; CHECK-SD-NEXT: ldr x0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v2i64_freeze: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: mov w9, w0 +; CHECK-GI-NEXT: mov x8, sp +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: and x9, x9, #0x1 +; CHECK-GI-NEXT: ldr x0, [x8, x9, lsl #3] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %fvector = freeze <2 x i64> %a + %d = extractelement <2 x i64> %fvector, i32 %c + ret i64 %d +} + +define i64 @extract_v2i64_extract_of_insert(<2 x i64> %a, i64 %element, i64 %c) { +; CHECK-LABEL: extract_v2i64_extract_of_insert: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: ret +entry: + %vector = insertelement <2 x i64> %a, i64 %element, i64 %c + %d = extractelement <2 x i64> %vector, i64 %c + ret i64 %d +} + +define i64 @extract_v2i64_extract_of_insert_different_const(<2 x i64> %a, i64 %element) { +; CHECK-SD-LABEL: extract_v2i64_extract_of_insert_different_const: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: mov x0, v0.d[1] +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v2i64_extract_of_insert_different_const: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: mov d0, v0.d[1] +; CHECK-GI-NEXT: fmov x0, d0 +; CHECK-GI-NEXT: ret +entry: + %vector = insertelement <2 x i64> %a, i64 %element, i64 0 + %d = extractelement <2 x i64> %vector, i64 1 + ret i64 %d +} + +define i64 @extract_v2i64_extract_build_vector_const(<2 x i64> %a, i32 %c) { +; CHECK-LABEL: extract_v2i64_extract_build_vector_const: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov w0, #11 // =0xb +; CHECK-NEXT: ret +entry: + %d = extractelement <2 x i64> <i64 42, i64 11>, i32 1 + ret i64 %d +} + +define i64 @extract_v2i64_extract_build_vector_opaque(<2 x i64> %a, i32 %c) { +; CHECK-SD-LABEL: extract_v2i64_extract_build_vector_opaque: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: adrp x8, .LCPI8_0 +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: ldr q0, [x8, :lo12:.LCPI8_0] +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: bfi x8, x0, #3, #1 +; CHECK-SD-NEXT: str q0, [sp] +; CHECK-SD-NEXT: ldr x0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v2i64_extract_build_vector_opaque: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: adrp x8, .LCPI8_0 +; CHECK-GI-NEXT: mov x9, sp +; CHECK-GI-NEXT: ldr q0, [x8, :lo12:.LCPI8_0] +; CHECK-GI-NEXT: mov w8, w0 +; CHECK-GI-NEXT: and x8, x8, #0x1 +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: ldr x0, [x9, x8, lsl #3] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %d = extractelement <2 x i64> <i64 42, i64 11>, i32 %c + ret i64 %d +} + + +define i64 @extract_v2i32_zext(<2 x i32> %a, i32 %c) { +; CHECK-SD-LABEL: extract_v2i32_zext: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: ushll v0.2d, v0.2s, #0 +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: bfi x8, x0, #3, #1 +; CHECK-SD-NEXT: str q0, [sp] +; CHECK-SD-NEXT: ldr x0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v2i32_zext: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: ushll v0.2d, v0.2s, #0 +; CHECK-GI-NEXT: mov w9, w0 +; CHECK-GI-NEXT: mov x8, sp +; CHECK-GI-NEXT: and x9, x9, #0x1 +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: ldr x0, [x8, x9, lsl #3] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %zvector = zext <2 x i32> %a to <2 x i64> + %d = extractelement <2 x i64> %zvector, i32 %c + ret i64 %d +} + +define i64 @extract_v2double_fptosi(<2 x double> %a, i32 %c) { +; CHECK-SD-LABEL: extract_v2double_fptosi: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: bfi x8, x0, #3, #1 +; CHECK-SD-NEXT: str q0, [sp] +; CHECK-SD-NEXT: ldr x0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v2double_fptosi: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: fcvtzs v0.2d, v0.2d +; CHECK-GI-NEXT: mov w9, w0 +; CHECK-GI-NEXT: mov x8, sp +; CHECK-GI-NEXT: and x9, x9, #0x1 +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: ldr x0, [x8, x9, lsl #3] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %vector = fptosi <2 x double> %a to <2 x i64> + %d = extractelement <2 x i64> %vector, i32 %c + ret i64 %d +} + +define double @extract_v2double_fneg(<2 x double> %a, i32 %c) { +; CHECK-SD-LABEL: extract_v2double_fneg: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: fneg v0.2d, v0.2d +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: bfi x8, x0, #3, #1 +; CHECK-SD-NEXT: str q0, [sp] +; CHECK-SD-NEXT: ldr d0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v2double_fneg: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: fneg v0.2d, v0.2d +; CHECK-GI-NEXT: mov w9, w0 +; CHECK-GI-NEXT: mov x8, sp +; CHECK-GI-NEXT: and x9, x9, #0x1 +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: ldr d0, [x8, x9, lsl #3] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %vector = fneg <2 x double> %a + %d = extractelement <2 x double> %vector, i32 %c + ret double %d +} + +define i32 @extract_v4i32_add(<4 x i32> %a, <4 x i32> %b, i32 %c) { +; CHECK-SD-LABEL: extract_v4i32_add: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: adrp x8, .LCPI12_0 +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: ldr q1, [x8, :lo12:.LCPI12_0] +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: bfi x8, x0, #2, #2 +; CHECK-SD-NEXT: add v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: str q0, [sp] +; CHECK-SD-NEXT: ldr w0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_add: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: adrp x8, .LCPI12_0 +; CHECK-GI-NEXT: mov x9, sp +; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI12_0] +; CHECK-GI-NEXT: mov w8, w0 +; CHECK-GI-NEXT: and x8, x8, #0x3 +; CHECK-GI-NEXT: add v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: ldr w0, [x9, x8, lsl #2] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %vector = add <4 x i32> %a, <i32 42, i32 11, i32 17, i32 6> + %d = extractelement <4 x i32> %vector, i32 %c + ret i32 %d +} + +define float @extract_v4i32_minimum(<4 x float> %a, <4 x float> %b, i32 %c) { +; CHECK-SD-LABEL: extract_v4i32_minimum: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: fmin v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: bfi x8, x0, #2, #2 +; CHECK-SD-NEXT: str q0, [sp] +; CHECK-SD-NEXT: ldr s0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_minimum: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: fmin v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: mov w8, w0 +; CHECK-GI-NEXT: mov x9, sp +; CHECK-GI-NEXT: and x8, x8, #0x3 +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: ldr s0, [x9, x8, lsl #2] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %vector = call <4 x float> @llvm.minimum.v4float(<4 x float> %a, <4 x float> %b) + %d = extractelement <4 x float> %vector, i32 %c + ret float %d +} + +define float @extract_v4i32_minimum_build_vector(<4 x float> %a, <4 x float> %b, i32 %c) { +; CHECK-SD-LABEL: extract_v4i32_minimum_build_vector: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: adrp x8, .LCPI14_0 +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: ldr q1, [x8, :lo12:.LCPI14_0] +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: bfi x8, x0, #2, #2 +; CHECK-SD-NEXT: fmin v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: str q0, [sp] +; CHECK-SD-NEXT: ldr s0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_minimum_build_vector: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: adrp x8, .LCPI14_0 +; CHECK-GI-NEXT: mov x9, sp +; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI14_0] +; CHECK-GI-NEXT: mov w8, w0 +; CHECK-GI-NEXT: and x8, x8, #0x3 +; CHECK-GI-NEXT: fmin v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: ldr s0, [x9, x8, lsl #2] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %vector = call <4 x float> @llvm.minimum.v4float(<4 x float> %a, <4 x float> <float 42.0, float 11.0, float 17.0, float 6.0>) + %d = extractelement <4 x float> %vector, i32 %c + ret float %d +} + +define float @extract_v4i32_minimum_build_vector_const(<4 x float> %a, <4 x float> %b, i32 %c) { +; CHECK-LABEL: extract_v4i32_minimum_build_vector_const: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: adrp x8, .LCPI15_0 +; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI15_0] +; CHECK-NEXT: fmin v0.4s, v0.4s, v1.4s +; CHECK-NEXT: mov s0, v0.s[1] +; CHECK-NEXT: ret +entry: + %vector = call <4 x float> @llvm.minimum.v4float(<4 x float> %a, <4 x float> <float 42.0, float 11.0, float 17.0, float 6.0>) + %d = extractelement <4 x float> %vector, i32 1 + ret float %d +} + +define float @extract_v4i32_copysign_build_vector(<4 x float> %a, <4 x float> %b, i32 %c) { +; CHECK-SD-LABEL: extract_v4i32_copysign_build_vector: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: adrp x8, .LCPI16_0 +; CHECK-SD-NEXT: mvni v1.4s, #128, lsl #24 +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: ldr q2, [x8, :lo12:.LCPI16_0] +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: bfi x8, x0, #2, #2 +; CHECK-SD-NEXT: bif v0.16b, v2.16b, v1.16b +; CHECK-SD-NEXT: str q0, [sp] +; CHECK-SD-NEXT: ldr s0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_copysign_build_vector: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: mvni v1.4s, #128, lsl #24 +; CHECK-GI-NEXT: mov w8, w0 +; CHECK-GI-NEXT: mov x9, sp +; CHECK-GI-NEXT: and x8, x8, #0x3 +; CHECK-GI-NEXT: and v0.16b, v0.16b, v1.16b +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: ldr s0, [x9, x8, lsl #2] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %vector = call <4 x float> @llvm.copysign.v4float(<4 x float> %a, <4 x float> <float 42.0, float 11.0, float 17.0, float 6.0>) + %d = extractelement <4 x float> %vector, i32 %c + ret float %d +} + +define float @extract_v4i32_copysign_build_vector_const(<4 x float> %a, <4 x float> %b, i32 %c) { +; CHECK-SD-LABEL: extract_v4i32_copysign_build_vector_const: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: adrp x8, .LCPI17_0 +; CHECK-SD-NEXT: mvni v1.4s, #128, lsl #24 +; CHECK-SD-NEXT: ldr q2, [x8, :lo12:.LCPI17_0] +; CHECK-SD-NEXT: bif v0.16b, v2.16b, v1.16b +; CHECK-SD-NEXT: mov s0, v0.s[2] +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_copysign_build_vector_const: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: mvni v1.4s, #128, lsl #24 +; CHECK-GI-NEXT: and v0.16b, v0.16b, v1.16b +; CHECK-GI-NEXT: mov s0, v0.s[2] +; CHECK-GI-NEXT: ret +entry: + %vector = call <4 x float> @llvm.copysign.v4float(<4 x float> %a, <4 x float> <float 42.0, float 11.0, float 17.0, float 6.0>) + %d = extractelement <4 x float> %vector, i32 2 + ret float %d +} + + +define i32 @extract_v4i32_icmp(<4 x i32> %a, <4 x i32> %b, i32 %c) { +; CHECK-SD-LABEL: extract_v4i32_icmp: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: adrp x8, .LCPI18_0 +; CHECK-SD-NEXT: movi v2.4s, #1 +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: ldr q1, [x8, :lo12:.LCPI18_0] +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: bfi x8, x0, #2, #2 +; CHECK-SD-NEXT: cmge v0.4s, v1.4s, v0.4s +; CHECK-SD-NEXT: and v0.16b, v0.16b, v2.16b +; CHECK-SD-NEXT: str q0, [sp] +; CHECK-SD-NEXT: ldr w0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_icmp: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: adrp x8, .LCPI18_0 +; CHECK-GI-NEXT: movi v2.4s, #1 +; CHECK-GI-NEXT: mov x9, sp +; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI18_0] +; CHECK-GI-NEXT: mov w8, w0 +; CHECK-GI-NEXT: and x8, x8, #0x3 +; CHECK-GI-NEXT: cmge v0.4s, v1.4s, v0.4s +; CHECK-GI-NEXT: and v0.16b, v0.16b, v2.16b +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: ldr w0, [x9, x8, lsl #2] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %vector = icmp sle <4 x i32> %a, <i32 42, i32 11, i32 17, i32 6> + %zvector = zext <4 x i1> %vector to <4 x i32> + %d = extractelement <4 x i32> %zvector, i32 %c + ret i32 %d +} + +define i32 @extract_v4i32_icmp_const(<4 x i32> %a, <4 x i32> %b, i32 %c) { +; CHECK-SD-LABEL: extract_v4i32_icmp_const: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: adrp x8, .LCPI19_0 +; CHECK-SD-NEXT: movi v2.4s, #1 +; CHECK-SD-NEXT: ldr q1, [x8, :lo12:.LCPI19_0] +; CHECK-SD-NEXT: cmge v0.4s, v1.4s, v0.4s +; CHECK-SD-NEXT: and v0.16b, v0.16b, v2.16b +; CHECK-SD-NEXT: mov w0, v0.s[2] +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_icmp_const: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: adrp x8, .LCPI19_0 +; CHECK-GI-NEXT: movi v2.4s, #1 +; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI19_0] +; CHECK-GI-NEXT: cmge v0.4s, v1.4s, v0.4s +; CHECK-GI-NEXT: and v0.16b, v0.16b, v2.16b +; CHECK-GI-NEXT: mov s0, v0.s[2] +; CHECK-GI-NEXT: fmov w0, s0 +; CHECK-GI-NEXT: ret +entry: + %vector = icmp sle <4 x i32> %a, <i32 42, i32 11, i32 17, i32 6> + %zvector = zext <4 x i1> %vector to <4 x i32> + %d = extractelement <4 x i32> %zvector, i32 2 + ret i32 %d +} + +define i32 @extract_v4float_fcmp(<4 x float> %a, <4 x float> %b, i32 %c) { +; CHECK-SD-LABEL: extract_v4float_fcmp: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: movi v1.4s, #1 +; CHECK-SD-NEXT: fcmeq v0.4s, v0.4s, v0.4s +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: bfi x8, x0, #2, #2 +; CHECK-SD-NEXT: bic v0.16b, v1.16b, v0.16b +; CHECK-SD-NEXT: str q0, [sp] +; CHECK-SD-NEXT: ldr w0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4float_fcmp: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: fmov v1.4s, #1.00000000 +; CHECK-GI-NEXT: mov w8, w0 +; CHECK-GI-NEXT: mov x9, sp +; CHECK-GI-NEXT: and x8, x8, #0x3 +; CHECK-GI-NEXT: fcmge v2.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: fcmgt v0.4s, v1.4s, v0.4s +; CHECK-GI-NEXT: movi v1.4s, #1 +; CHECK-GI-NEXT: orr v0.16b, v0.16b, v2.16b +; CHECK-GI-NEXT: bic v0.16b, v1.16b, v0.16b +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: ldr w0, [x9, x8, lsl #2] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %vector = fcmp uno <4 x float> %a, <float 1.0, float 1.0, float 1.0, float 1.0> + %zvector = zext <4 x i1> %vector to <4 x i32> + %d = extractelement <4 x i32> %zvector, i32 %c + ret i32 %d +} + +define i32 @extract_v4float_fcmp_const(<4 x float> %a, <4 x float> %b, i32 %c) { +; CHECK-SD-LABEL: extract_v4float_fcmp_const: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: movi v1.4s, #1 +; CHECK-SD-NEXT: fcmeq v0.4s, v0.4s, v0.4s +; CHECK-SD-NEXT: bic v0.16b, v1.16b, v0.16b +; CHECK-SD-NEXT: mov w0, v0.s[1] +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4float_fcmp_const: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: fmov v1.4s, #1.00000000 +; CHECK-GI-NEXT: fcmge v2.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: fcmgt v0.4s, v1.4s, v0.4s +; CHECK-GI-NEXT: movi v1.4s, #1 +; CHECK-GI-NEXT: orr v0.16b, v0.16b, v2.16b +; CHECK-GI-NEXT: bic v0.16b, v1.16b, v0.16b +; CHECK-GI-NEXT: mov s0, v0.s[1] +; CHECK-GI-NEXT: fmov w0, s0 +; CHECK-GI-NEXT: ret +entry: + %vector = fcmp uno <4 x float> %a, <float 1.0, float 1.0, float 1.0, float 1.0> + %zvector = zext <4 x i1> %vector to <4 x i32> + %d = extractelement <4 x i32> %zvector, i32 1 + ret i32 %d +} + +define i32 @extract_v4i32_select(<4 x i32> %a, <4 x i32> %b, i32 %c, <4 x i1> %cond) { +; CHECK-SD-LABEL: extract_v4i32_select: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: ushll v1.4s, v2.4h, #0 +; CHECK-SD-NEXT: adrp x8, .LCPI22_0 +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: ldr q2, [x8, :lo12:.LCPI22_0] +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: bfi x8, x0, #2, #2 +; CHECK-SD-NEXT: shl v1.4s, v1.4s, #31 +; CHECK-SD-NEXT: cmlt v1.4s, v1.4s, #0 +; CHECK-SD-NEXT: bif v0.16b, v2.16b, v1.16b +; CHECK-SD-NEXT: str q0, [sp] +; CHECK-SD-NEXT: ldr w0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_select: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: ushll v1.4s, v2.4h, #0 +; CHECK-GI-NEXT: adrp x8, .LCPI22_0 +; CHECK-GI-NEXT: mov x9, sp +; CHECK-GI-NEXT: ldr q2, [x8, :lo12:.LCPI22_0] +; CHECK-GI-NEXT: mov w8, w0 +; CHECK-GI-NEXT: and x8, x8, #0x3 +; CHECK-GI-NEXT: shl v1.4s, v1.4s, #31 +; CHECK-GI-NEXT: sshr v1.4s, v1.4s, #31 +; CHECK-GI-NEXT: bif v0.16b, v2.16b, v1.16b +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: ldr w0, [x9, x8, lsl #2] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %vector = select <4 x i1> %cond, <4 x i32> %a, <4 x i32> <i32 42, i32 11, i32 17, i32 6> + %d = extractelement <4 x i32> %vector, i32 %c + ret i32 %d +} + +define i32 @extract_v4i32_select_const(<4 x i32> %a, <4 x i32> %b, i32 %c, <4 x i1> %cond) { +; CHECK-SD-LABEL: extract_v4i32_select_const: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: ushll v1.4s, v2.4h, #0 +; CHECK-SD-NEXT: movi v2.4s, #17 +; CHECK-SD-NEXT: shl v1.4s, v1.4s, #31 +; CHECK-SD-NEXT: cmlt v1.4s, v1.4s, #0 +; CHECK-SD-NEXT: bif v0.16b, v2.16b, v1.16b +; CHECK-SD-NEXT: mov w0, v0.s[2] +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_select_const: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: ushll v1.4s, v2.4h, #0 +; CHECK-GI-NEXT: adrp x8, .LCPI23_0 +; CHECK-GI-NEXT: ldr q2, [x8, :lo12:.LCPI23_0] +; CHECK-GI-NEXT: shl v1.4s, v1.4s, #31 +; CHECK-GI-NEXT: sshr v1.4s, v1.4s, #31 +; CHECK-GI-NEXT: bif v0.16b, v2.16b, v1.16b +; CHECK-GI-NEXT: mov s0, v0.s[2] +; CHECK-GI-NEXT: fmov w0, s0 +; CHECK-GI-NEXT: ret +entry: + %vector = select <4 x i1> %cond, <4 x i32> %a, <4 x i32> <i32 42, i32 11, i32 17, i32 6> + %d = extractelement <4 x i32> %vector, i32 2 + ret i32 %d +} + +define i32 @extract_v4i32_abs(<4 x float> %a, i32 %c) { +; CHECK-SD-LABEL: extract_v4i32_abs: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: frintp v0.4s, v0.4s +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: bfi x8, x0, #2, #2 +; CHECK-SD-NEXT: frintm v0.4s, v0.4s +; CHECK-SD-NEXT: fabs v0.4s, v0.4s +; CHECK-SD-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-SD-NEXT: abs v0.4s, v0.4s +; CHECK-SD-NEXT: str q0, [sp] +; CHECK-SD-NEXT: ldr w0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_abs: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: frintp v0.4s, v0.4s +; CHECK-GI-NEXT: mov w9, w0 +; CHECK-GI-NEXT: mov x8, sp +; CHECK-GI-NEXT: and x9, x9, #0x3 +; CHECK-GI-NEXT: frintm v0.4s, v0.4s +; CHECK-GI-NEXT: fabs v0.4s, v0.4s +; CHECK-GI-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-GI-NEXT: abs v0.4s, v0.4s +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: ldr w0, [x8, x9, lsl #2] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %ceil = call <4 x float> @llvm.ceil.v4float(<4 x float> %a) + %floor = call <4 x float> @llvm.floor.v4float(<4 x float> %ceil) + %fabs = call <4 x float> @llvm.fabs.v4float(<4 x float> %floor) + %abs = fptosi <4 x float> %fabs to <4 x i32> + %vector = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %abs, i1 0) + %d = extractelement <4 x i32> %vector, i32 %c + ret i32 %d +} + +define i32 @extract_v4i32_abs_const(<4 x float> %a, i32 %c) { +; CHECK-SD-LABEL: extract_v4i32_abs_const: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: mov w0, #4 // =0x4 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_abs_const: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: adrp x8, .LCPI25_0 +; CHECK-GI-NEXT: ldr q0, [x8, :lo12:.LCPI25_0] +; CHECK-GI-NEXT: frintp v0.4s, v0.4s +; CHECK-GI-NEXT: frintm v0.4s, v0.4s +; CHECK-GI-NEXT: fabs v0.4s, v0.4s +; CHECK-GI-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-GI-NEXT: abs v0.4s, v0.4s +; CHECK-GI-NEXT: mov s0, v0.s[1] +; CHECK-GI-NEXT: fmov w0, s0 +; CHECK-GI-NEXT: ret +entry: + %ceil = call <4 x float> @llvm.ceil.v4float(<4 x float> <float 1.0, float 4.0, float 3.0, float 2.0>) + %floor = call <4 x float> @llvm.floor.v4float(<4 x float> %ceil) + %fabs = call <4 x float> @llvm.fabs.v4float(<4 x float> %floor) + %abs = fptosi <4 x float> %fabs to <4 x i32> + %vector = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %abs, i1 0) + %d = extractelement <4 x i32> %vector, i32 1 + ret i32 %d +} + +define i32 @extract_v4i32_abs_half_const(<4 x float> %a, i32 %c) { +; CHECK-SD-LABEL: extract_v4i32_abs_half_const: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: adrp x8, .LCPI26_0 +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: ldr q0, [x8, :lo12:.LCPI26_0] +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: bfi x8, x0, #2, #2 +; CHECK-SD-NEXT: str q0, [sp] +; CHECK-SD-NEXT: ldr w0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_abs_half_const: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: adrp x8, .LCPI26_0 +; CHECK-GI-NEXT: mov x9, sp +; CHECK-GI-NEXT: ldr q0, [x8, :lo12:.LCPI26_0] +; CHECK-GI-NEXT: mov w8, w0 +; CHECK-GI-NEXT: and x8, x8, #0x3 +; CHECK-GI-NEXT: frintp v0.4s, v0.4s +; CHECK-GI-NEXT: frintm v0.4s, v0.4s +; CHECK-GI-NEXT: fabs v0.4s, v0.4s +; CHECK-GI-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-GI-NEXT: abs v0.4s, v0.4s +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: ldr w0, [x9, x8, lsl #2] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %ceil = call <4 x float> @llvm.ceil.v4float(<4 x float> <float 1.0, float 4.0, float 3.0, float 2.0>) + %floor = call <4 x float> @llvm.floor.v4float(<4 x float> %ceil) + %fabs = call <4 x float> @llvm.fabs.v4float(<4 x float> %floor) + %abs = fptosi <4 x float> %fabs to <4 x i32> + %vector = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %abs, i1 0) + %d = extractelement <4 x i32> %vector, i32 %c + ret i32 %d +} + +define i32 @extract_v4i32_vector_insert(<4 x i32> %a, <2 x i32> %b, i32 %c) { +; CHECK-LABEL: extract_v4i32_vector_insert: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #16 +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: ext v0.16b, v0.16b, v0.16b, #8 +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-NEXT: bfi x8, x0, #2, #2 +; CHECK-NEXT: mov v1.d[1], v0.d[0] +; CHECK-NEXT: str q1, [sp] +; CHECK-NEXT: ldr w0, [x8] +; CHECK-NEXT: add sp, sp, #16 +; CHECK-NEXT: ret +entry: + %vector = call <4 x i32> @llvm.vector.insert.v4i32.v2i32(<4 x i32> %a, <2 x i32> %b, i64 0) + %d = extractelement <4 x i32> %vector, i32 %c + ret i32 %d +} + +define i32 @extract_v4i32_vector_insert_const(<4 x i32> %a, <2 x i32> %b, i32 %c) { +; CHECK-LABEL: extract_v4i32_vector_insert_const: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: mov w0, v1.s[1] +; CHECK-NEXT: ret +entry: + %vector = call <4 x i32> @llvm.vector.insert.v4i32.v2i32(<4 x i32> %a, <2 x i32> %b, i64 0) + %d = extractelement <4 x i32> %vector, i32 1 + ret i32 %d +} + +define i32 @extract_v4i32_vector_extract(<4 x i32> %a, <2 x i32> %b, i32 %c) { +; CHECK-LABEL: extract_v4i32_vector_extract: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #16 +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-NEXT: str q0, [sp] +; CHECK-NEXT: bfi x8, x0, #2, #2 +; CHECK-NEXT: ldr w0, [x8] +; CHECK-NEXT: add sp, sp, #16 +; CHECK-NEXT: ret +entry: + %vector = call <4 x i32> @llvm.vector.extract.v2i32.v4i32(<4 x i32> %a, i64 0) + %d = extractelement <4 x i32> %vector, i32 %c + ret i32 %d +} + +define i32 @extract_v4i32_vector_extract_const(<4 x i32> %a, <2 x i32> %b, i32 %c) { +; CHECK-LABEL: extract_v4i32_vector_extract_const: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: fmov w0, s0 +; CHECK-NEXT: ret +entry: + %vector = call <4 x i32> @llvm.vector.extract.v2i32.v4i32(<4 x i32> %a, i64 0) + %d = extractelement <4 x i32> %vector, i32 0 + ret i32 %d +} + +define i32 @extract_v4i32_load(<4 x i32> %a, <2 x i32> %b, i32 %c, ptr %arg) { +; CHECK-SD-LABEL: extract_v4i32_load: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: and x8, x0, #0x3 +; CHECK-SD-NEXT: ldr w0, [x1, x8, lsl #2] +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_load: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: mov w8, w0 +; CHECK-GI-NEXT: and x8, x8, #0x3 +; CHECK-GI-NEXT: ldr w0, [x1, x8, lsl #2] +; CHECK-GI-NEXT: ret +entry: + %vector = load <4 x i32>, ptr %arg + %d = extractelement <4 x i32> %vector, i32 %c + ret i32 %d +} + +define i32 @extract_v4i32_load_const(<4 x i32> %a, <2 x i32> %b, i32 %c, ptr %arg) { +; CHECK-LABEL: extract_v4i32_load_const: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: ldr w0, [x1] +; CHECK-NEXT: ret +entry: + %vector = load <4 x i32>, ptr %arg + %d = extractelement <4 x i32> %vector, i32 0 + ret i32 %d +} + +define double @extract_v4i32_bitcast(<4 x i32> %a, i32 %c) { +; CHECK-SD-LABEL: extract_v4i32_bitcast: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: str q0, [sp] +; CHECK-SD-NEXT: bfi x8, x0, #3, #1 +; CHECK-SD-NEXT: ldr d0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_bitcast: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: mov w9, w0 +; CHECK-GI-NEXT: mov x8, sp +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: and x9, x9, #0x1 +; CHECK-GI-NEXT: ldr d0, [x8, x9, lsl #3] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %vector = bitcast <4 x i32> %a to <2 x double> + %d = extractelement <2 x double> %vector, i32 %c + ret double %d +} + +define double @extract_v4i32_bitcast_const(<4 x i32> %a, i32 %c) { +; CHECK-LABEL: extract_v4i32_bitcast_const: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-NEXT: ret +entry: + %vector = bitcast <4 x i32> %a to <2 x double> + %d = extractelement <2 x double> %vector, i32 0 + ret double %d +} + +define i32 @extract_v4i32_shuffle(<4 x i32> %a, <4 x i32> %b, i32 %c) { +; CHECK-SD-LABEL: extract_v4i32_shuffle: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: uzp1 v1.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: bfi x8, x0, #2, #2 +; CHECK-SD-NEXT: mov v1.s[3], v0.s[3] +; CHECK-SD-NEXT: str q1, [sp] +; CHECK-SD-NEXT: ldr w0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_shuffle: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: adrp x8, .LCPI35_0 +; CHECK-GI-NEXT: // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1 +; CHECK-GI-NEXT: mov x9, sp +; CHECK-GI-NEXT: ldr q2, [x8, :lo12:.LCPI35_0] +; CHECK-GI-NEXT: // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1 +; CHECK-GI-NEXT: mov w8, w0 +; CHECK-GI-NEXT: and x8, x8, #0x3 +; CHECK-GI-NEXT: tbl v0.16b, { v0.16b, v1.16b }, v2.16b +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: ldr w0, [x9, x8, lsl #2] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %vector = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 3> + %d = extractelement <4 x i32> %vector, i32 %c + ret i32 %d +} + +define i32 @extract_v4i32_shuffle_const(<4 x i32> %a, <4 x i32> %b, i32 %c) { +; CHECK-SD-LABEL: extract_v4i32_shuffle_const: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: fmov w0, s1 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_shuffle_const: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: adrp x8, .LCPI36_0 +; CHECK-GI-NEXT: // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1 +; CHECK-GI-NEXT: ldr q2, [x8, :lo12:.LCPI36_0] +; CHECK-GI-NEXT: // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1 +; CHECK-GI-NEXT: tbl v0.16b, { v0.16b, v1.16b }, v2.16b +; CHECK-GI-NEXT: mov s0, v0.s[2] +; CHECK-GI-NEXT: fmov w0, s0 +; CHECK-GI-NEXT: ret +entry: + %vector = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 2, i32 4, i32 3> + %d = extractelement <4 x i32> %vector, i32 2 + ret i32 %d +} + +define i32 @extract_v4i32_splat(<4 x i32> %a, <2 x i32> %b, i32 %c) { +; CHECK-SD-LABEL: extract_v4i32_splat: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: movi v0.4s, #11 +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: bfi x8, x0, #2, #2 +; CHECK-SD-NEXT: str q0, [sp] +; CHECK-SD-NEXT: ldr w0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_splat: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: movi v0.4s, #11 +; CHECK-GI-NEXT: mov w8, w0 +; CHECK-GI-NEXT: mov x9, sp +; CHECK-GI-NEXT: and x8, x8, #0x3 +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: ldr w0, [x9, x8, lsl #2] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %d = extractelement <4 x i32> splat (i32 11), i32 %c + ret i32 %d +} + +define i32 @extract_v4i32_splat_const(<4 x i32> %a, <2 x i32> %b, i32 %c) { +; CHECK-LABEL: extract_v4i32_splat_const: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov w0, #11 // =0xb +; CHECK-NEXT: ret +entry: + %d = extractelement <4 x i32> splat (i32 11), i32 0 + ret i32 %d +} + +define i32 @extract_v4i32_vp_add(<4 x i32> %a, <4 x i32> %b, i32 %c, <4 x i1> %mask, i32 %evl) { +; CHECK-SD-LABEL: extract_v4i32_vp_add: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: sub sp, sp, #16 +; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 +; CHECK-SD-NEXT: add v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: mov x8, sp +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-SD-NEXT: bfi x8, x0, #2, #2 +; CHECK-SD-NEXT: str q0, [sp] +; CHECK-SD-NEXT: ldr w0, [x8] +; CHECK-SD-NEXT: add sp, sp, #16 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_vp_add: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: sub sp, sp, #16 +; CHECK-GI-NEXT: .cfi_def_cfa_offset 16 +; CHECK-GI-NEXT: add v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: mov w8, w0 +; CHECK-GI-NEXT: mov x9, sp +; CHECK-GI-NEXT: and x8, x8, #0x3 +; CHECK-GI-NEXT: str q0, [sp] +; CHECK-GI-NEXT: ldr w0, [x9, x8, lsl #2] +; CHECK-GI-NEXT: add sp, sp, #16 +; CHECK-GI-NEXT: ret +entry: + %vector = call <4 x i32> @llvm.vp.add.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl) + %d = extractelement <4 x i32> %vector, i32 %c + ret i32 %d +} + +define i32 @extract_v4i32_vp_add_const(<4 x i32> %a, <4 x i32> %b, i32 %c, <4 x i1> %mask, i32 %evl) { +; CHECK-SD-LABEL: extract_v4i32_vp_add_const: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: add v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: mov w0, v0.s[3] +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_vp_add_const: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: add v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: mov s0, v0.s[3] +; CHECK-GI-NEXT: fmov w0, s0 +; CHECK-GI-NEXT: ret +entry: + %vector = call <4 x i32> @llvm.vp.add.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i1> %mask, i32 %evl) + %d = extractelement <4 x i32> %vector, i32 3 + ret i32 %d +} + +define i32 @extract_v4i32_phi(i64 %val, i32 %limit, ptr %ptr) { +; CHECK-SD-LABEL: extract_v4i32_phi: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: dup v1.2s, w0 +; CHECK-SD-NEXT: adrp x8, .LCPI41_0 +; CHECK-SD-NEXT: movi v0.2s, #16 +; CHECK-SD-NEXT: ldr d2, [x8, :lo12:.LCPI41_0] +; CHECK-SD-NEXT: add v1.2s, v1.2s, v2.2s +; CHECK-SD-NEXT: .LBB41_1: // %loop +; CHECK-SD-NEXT: // =>This Inner Loop Header: Depth=1 +; CHECK-SD-NEXT: fmov w8, s1 +; CHECK-SD-NEXT: add v1.2s, v1.2s, v0.2s +; CHECK-SD-NEXT: cmp w8, w1 +; CHECK-SD-NEXT: add w0, w8, #10 +; CHECK-SD-NEXT: str w0, [x2, w8, sxtw #2] +; CHECK-SD-NEXT: b.lo .LBB41_1 +; CHECK-SD-NEXT: // %bb.2: // %ret +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: extract_v4i32_phi: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: adrp x8, .LCPI41_0 +; CHECK-GI-NEXT: dup v0.2d, x0 +; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI41_0] +; CHECK-GI-NEXT: add v1.2d, v0.2d, v1.2d +; CHECK-GI-NEXT: movi v0.2s, #16 +; CHECK-GI-NEXT: xtn v1.2s, v1.2d +; CHECK-GI-NEXT: .LBB41_1: // %loop +; CHECK-GI-NEXT: // =>This Inner Loop Header: Depth=1 +; CHECK-GI-NEXT: fmov w8, s1 +; CHECK-GI-NEXT: fmov w9, s1 +; CHECK-GI-NEXT: add v1.2s, v1.2s, v0.2s +; CHECK-GI-NEXT: cmp w8, w1 +; CHECK-GI-NEXT: add w0, w9, #10 +; CHECK-GI-NEXT: str w0, [x2, w8, sxtw #2] +; CHECK-GI-NEXT: b.lo .LBB41_1 +; CHECK-GI-NEXT: // %bb.2: // %ret +; CHECK-GI-NEXT: ret +entry: + %tempvector = insertelement <2 x i64> undef, i64 %val, i32 0 + %vector = shufflevector <2 x i64> %tempvector, <2 x i64> undef, <2 x i32> zeroinitializer + %0 = add <2 x i64> %vector, <i64 1, i64 2> + %1 = trunc <2 x i64> %0 to <2 x i32> + br label %loop + +loop: + %2 = phi <2 x i32> [ %1, %entry ], [ %inc, %loop ] + %elt = extractelement <2 x i32> %2, i32 0 + %end = icmp ult i32 %elt, %limit + %3 = add i32 10, %elt + %4 = sext i32 %elt to i64 + %5 = getelementptr i32, ptr %ptr, i64 %4 + store i32 %3, ptr %5 + %inc = add <2 x i32> %2, <i32 16, i32 16> + br i1 %end, label %loop, label %ret + +ret: + ret i32 %3 +} + + diff --git a/llvm/test/CodeGen/AArch64/extractvector-oob-load.mir b/llvm/test/CodeGen/AArch64/extractvector-oob-load.mir index e8c5819e75e0904200e2d1bf110355422a81a63d..e7e8c939910941d5aa287755041190912f2c75fd 100644 --- a/llvm/test/CodeGen/AArch64/extractvector-oob-load.mir +++ b/llvm/test/CodeGen/AArch64/extractvector-oob-load.mir @@ -22,11 +22,8 @@ body: | ; CHECK-LABEL: name: f ; CHECK: liveins: $x0 ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 16 - ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C]](s64) - ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[PTR_ADD]](p0) :: (load (s64)) - ; CHECK-NEXT: $x0 = COPY [[LOAD]](s64) + ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF + ; CHECK-NEXT: $x0 = COPY [[DEF]](s64) ; CHECK-NEXT: RET_ReallyLR implicit $x0 %0:_(p0) = COPY $x0 %3:_(s64) = G_CONSTANT i64 224567957 diff --git a/llvm/test/CodeGen/AArch64/fcmp.ll b/llvm/test/CodeGen/AArch64/fcmp.ll index 2d0b5574cdd7ba29e2900cd6b8b81bfd359a0dac..9916aeeab1cad17a52d6cc6c4dba5255eb25ee41 100644 --- a/llvm/test/CodeGen/AArch64/fcmp.ll +++ b/llvm/test/CodeGen/AArch64/fcmp.ll @@ -1108,61 +1108,54 @@ define <7 x i32> @v7f16_i32(<7 x half> %a, <7 x half> %b, <7 x i32> %d, <7 x i32 ; ; CHECK-GI-FP16-LABEL: v7f16_i32: ; CHECK-GI-FP16: // %bb.0: // %entry -; CHECK-GI-FP16-NEXT: fcmgt v1.8h, v1.8h, v0.8h -; CHECK-GI-FP16-NEXT: mov w12, #31 // =0x1f -; CHECK-GI-FP16-NEXT: ldr s4, [sp] -; CHECK-GI-FP16-NEXT: fmov s2, w12 +; CHECK-GI-FP16-NEXT: fcmgt v0.8h, v1.8h, v0.8h +; CHECK-GI-FP16-NEXT: mov w10, #31 // =0x1f +; CHECK-GI-FP16-NEXT: ldr s3, [sp] +; CHECK-GI-FP16-NEXT: fmov s1, w10 ; CHECK-GI-FP16-NEXT: fmov s6, w0 -; CHECK-GI-FP16-NEXT: ldr s5, [sp, #8] +; CHECK-GI-FP16-NEXT: ldr s4, [sp, #8] ; CHECK-GI-FP16-NEXT: ldr s7, [sp, #24] ; CHECK-GI-FP16-NEXT: ldr s16, [sp, #32] -; CHECK-GI-FP16-NEXT: umov w9, v1.h[4] -; CHECK-GI-FP16-NEXT: umov w8, v1.h[0] -; CHECK-GI-FP16-NEXT: umov w11, v1.h[5] -; CHECK-GI-FP16-NEXT: umov w10, v1.h[1] -; CHECK-GI-FP16-NEXT: mov v2.s[1], w12 -; CHECK-GI-FP16-NEXT: umov w13, v1.h[2] +; CHECK-GI-FP16-NEXT: umov w8, v0.h[4] +; CHECK-GI-FP16-NEXT: umov w9, v0.h[5] +; CHECK-GI-FP16-NEXT: mov v1.s[1], w10 ; CHECK-GI-FP16-NEXT: mov v6.s[1], w1 ; CHECK-GI-FP16-NEXT: mov v7.s[1], v16.s[0] ; CHECK-GI-FP16-NEXT: ldr s16, [sp, #40] -; CHECK-GI-FP16-NEXT: fmov s3, w9 -; CHECK-GI-FP16-NEXT: fmov s0, w8 -; CHECK-GI-FP16-NEXT: umov w8, v1.h[6] -; CHECK-GI-FP16-NEXT: mov v2.s[2], w12 -; CHECK-GI-FP16-NEXT: umov w9, v1.h[3] +; CHECK-GI-FP16-NEXT: fmov s2, w8 +; CHECK-GI-FP16-NEXT: umov w8, v0.h[6] +; CHECK-GI-FP16-NEXT: mov v1.s[2], w10 +; CHECK-GI-FP16-NEXT: ushll v0.4s, v0.4h, #0 ; CHECK-GI-FP16-NEXT: mov v6.s[2], w2 ; CHECK-GI-FP16-NEXT: mov v7.s[2], v16.s[0] -; CHECK-GI-FP16-NEXT: mov v3.s[1], w11 -; CHECK-GI-FP16-NEXT: mov v0.s[1], w10 -; CHECK-GI-FP16-NEXT: mov w10, #-1 // =0xffffffff -; CHECK-GI-FP16-NEXT: fmov s1, w10 -; CHECK-GI-FP16-NEXT: neg v17.4s, v2.4s +; CHECK-GI-FP16-NEXT: mov v2.s[1], w9 +; CHECK-GI-FP16-NEXT: mov w9, #-1 // =0xffffffff +; CHECK-GI-FP16-NEXT: fmov s5, w9 +; CHECK-GI-FP16-NEXT: neg v17.4s, v1.4s +; CHECK-GI-FP16-NEXT: shl v0.4s, v0.4s, #31 ; CHECK-GI-FP16-NEXT: mov v6.s[3], w3 +; CHECK-GI-FP16-NEXT: mov v2.s[2], w8 +; CHECK-GI-FP16-NEXT: fmov w8, s3 +; CHECK-GI-FP16-NEXT: fmov s3, w7 +; CHECK-GI-FP16-NEXT: mov v5.s[1], w9 +; CHECK-GI-FP16-NEXT: sshr v0.4s, v0.4s, #31 +; CHECK-GI-FP16-NEXT: mov v3.s[1], w8 +; CHECK-GI-FP16-NEXT: fmov w8, s4 +; CHECK-GI-FP16-NEXT: ldr s4, [sp, #16] +; CHECK-GI-FP16-NEXT: ushl v1.4s, v2.4s, v1.4s +; CHECK-GI-FP16-NEXT: fmov s2, w4 +; CHECK-GI-FP16-NEXT: mov v5.s[2], w9 +; CHECK-GI-FP16-NEXT: mov v2.s[1], w5 ; CHECK-GI-FP16-NEXT: mov v3.s[2], w8 +; CHECK-GI-FP16-NEXT: sshl v1.4s, v1.4s, v17.4s ; CHECK-GI-FP16-NEXT: fmov w8, s4 -; CHECK-GI-FP16-NEXT: fmov s4, w7 -; CHECK-GI-FP16-NEXT: mov v0.s[2], w13 -; CHECK-GI-FP16-NEXT: mov v1.s[1], w10 -; CHECK-GI-FP16-NEXT: mov v4.s[1], w8 -; CHECK-GI-FP16-NEXT: fmov w8, s5 -; CHECK-GI-FP16-NEXT: ldr s5, [sp, #16] -; CHECK-GI-FP16-NEXT: ushl v2.4s, v3.4s, v2.4s -; CHECK-GI-FP16-NEXT: fmov s3, w4 -; CHECK-GI-FP16-NEXT: mov v0.s[3], w9 -; CHECK-GI-FP16-NEXT: mov v1.s[2], w10 -; CHECK-GI-FP16-NEXT: mov v3.s[1], w5 -; CHECK-GI-FP16-NEXT: mov v4.s[2], w8 -; CHECK-GI-FP16-NEXT: sshl v2.4s, v2.4s, v17.4s -; CHECK-GI-FP16-NEXT: fmov w8, s5 -; CHECK-GI-FP16-NEXT: shl v0.4s, v0.4s, #31 -; CHECK-GI-FP16-NEXT: eor v1.16b, v2.16b, v1.16b -; CHECK-GI-FP16-NEXT: mov v3.s[2], w6 -; CHECK-GI-FP16-NEXT: mov v4.s[3], w8 -; CHECK-GI-FP16-NEXT: sshr v0.4s, v0.4s, #31 -; CHECK-GI-FP16-NEXT: and v1.16b, v7.16b, v1.16b -; CHECK-GI-FP16-NEXT: and v2.16b, v3.16b, v2.16b -; CHECK-GI-FP16-NEXT: bsl v0.16b, v6.16b, v4.16b -; CHECK-GI-FP16-NEXT: orr v1.16b, v2.16b, v1.16b +; CHECK-GI-FP16-NEXT: eor v4.16b, v1.16b, v5.16b +; CHECK-GI-FP16-NEXT: mov v2.s[2], w6 +; CHECK-GI-FP16-NEXT: mov v3.s[3], w8 +; CHECK-GI-FP16-NEXT: and v1.16b, v2.16b, v1.16b +; CHECK-GI-FP16-NEXT: and v2.16b, v7.16b, v4.16b +; CHECK-GI-FP16-NEXT: bsl v0.16b, v6.16b, v3.16b +; CHECK-GI-FP16-NEXT: orr v1.16b, v1.16b, v2.16b ; CHECK-GI-FP16-NEXT: mov s2, v0.s[1] ; CHECK-GI-FP16-NEXT: mov s3, v0.s[2] ; CHECK-GI-FP16-NEXT: mov s4, v0.s[3] diff --git a/llvm/test/CodeGen/AArch64/fexplog.ll b/llvm/test/CodeGen/AArch64/fexplog.ll index 519a2978d8604b9b50363d73816c4e3877b68482..93d3d96d67b650f9e815b9eea0f2e54f403383e3 100644 --- a/llvm/test/CodeGen/AArch64/fexplog.ll +++ b/llvm/test/CodeGen/AArch64/fexplog.ll @@ -36,6 +36,19 @@ entry: ret half %c } +define <1 x double> @exp_v1f64(<1 x double> %x) { +; CHECK-LABEL: exp_v1f64: +; CHECK: // %bb.0: +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset w30, -16 +; CHECK-NEXT: bl exp +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ret + %c = call <1 x double> @llvm.exp.v1f64(<1 x double> %x) + ret <1 x double> %c +} + define <2 x double> @exp_v2f64(<2 x double> %a) { ; CHECK-SD-LABEL: exp_v2f64: ; CHECK-SD: // %bb.0: // %entry @@ -1293,6 +1306,19 @@ entry: ret half %c } +define <1 x double> @exp2_v1f64(<1 x double> %x) { +; CHECK-LABEL: exp2_v1f64: +; CHECK: // %bb.0: +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset w30, -16 +; CHECK-NEXT: bl exp2 +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ret + %c = call <1 x double> @llvm.exp2.v1f64(<1 x double> %x) + ret <1 x double> %c +} + define <2 x double> @exp2_v2f64(<2 x double> %a) { ; CHECK-SD-LABEL: exp2_v2f64: ; CHECK-SD: // %bb.0: // %entry @@ -2550,6 +2576,19 @@ entry: ret half %c } +define <1 x double> @log_v1f64(<1 x double> %x) { +; CHECK-LABEL: log_v1f64: +; CHECK: // %bb.0: +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset w30, -16 +; CHECK-NEXT: bl log +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ret + %c = call <1 x double> @llvm.log.v1f64(<1 x double> %x) + ret <1 x double> %c +} + define <2 x double> @log_v2f64(<2 x double> %a) { ; CHECK-SD-LABEL: log_v2f64: ; CHECK-SD: // %bb.0: // %entry @@ -3807,6 +3846,19 @@ entry: ret half %c } +define <1 x double> @log2_v1f64(<1 x double> %x) { +; CHECK-LABEL: log2_v1f64: +; CHECK: // %bb.0: +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset w30, -16 +; CHECK-NEXT: bl log2 +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ret + %c = call <1 x double> @llvm.log2.v1f64(<1 x double> %x) + ret <1 x double> %c +} + define <2 x double> @log2_v2f64(<2 x double> %a) { ; CHECK-SD-LABEL: log2_v2f64: ; CHECK-SD: // %bb.0: // %entry @@ -5064,6 +5116,19 @@ entry: ret half %c } +define <1 x double> @log10_v1f64(<1 x double> %x) { +; CHECK-LABEL: log10_v1f64: +; CHECK: // %bb.0: +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset w30, -16 +; CHECK-NEXT: bl log10 +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ret + %c = call <1 x double> @llvm.log10.v1f64(<1 x double> %x) + ret <1 x double> %c +} + define <2 x double> @log10_v2f64(<2 x double> %a) { ; CHECK-SD-LABEL: log10_v2f64: ; CHECK-SD: // %bb.0: // %entry diff --git a/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll b/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll index 1b1cfead0f97aca1921be34f2468402656140f7a..2ad5623b6551767a7e6ffa64cb427665ec7e9bfc 100644 --- a/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll +++ b/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll @@ -1,29 +1,50 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -mtriple=aarch64-linux-gnu | FileCheck %s +; RUN: llc -mtriple=aarch64-none-linux-gnu %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD +; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel -global-isel-abort=2 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI define {<2 x half>, <2 x half>} @vector_deinterleave_v2f16_v4f16(<4 x half> %vec) { -; CHECK-LABEL: vector_deinterleave_v2f16_v4f16: -; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: dup v2.2s, v0.s[1] -; CHECK-NEXT: mov v1.16b, v2.16b -; CHECK-NEXT: mov v1.h[0], v0.h[1] -; CHECK-NEXT: mov v0.h[1], v2.h[0] -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 -; CHECK-NEXT: // kill: def $d1 killed $d1 killed $q1 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: vector_deinterleave_v2f16_v4f16: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-SD-NEXT: dup v2.2s, v0.s[1] +; CHECK-SD-NEXT: mov v1.16b, v2.16b +; CHECK-SD-NEXT: mov v1.h[0], v0.h[1] +; CHECK-SD-NEXT: mov v0.h[1], v2.h[0] +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-SD-NEXT: // kill: def $d1 killed $d1 killed $q1 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: vector_deinterleave_v2f16_v4f16: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: uzp1 v2.4h, v0.4h, v0.4h +; CHECK-GI-NEXT: uzp2 v1.4h, v0.4h, v0.4h +; CHECK-GI-NEXT: mov h0, v2.h[1] +; CHECK-GI-NEXT: mov h3, v1.h[1] +; CHECK-GI-NEXT: mov v2.h[1], v0.h[0] +; CHECK-GI-NEXT: mov v1.h[1], v3.h[0] +; CHECK-GI-NEXT: // kill: def $d1 killed $d1 killed $q1 +; CHECK-GI-NEXT: fmov d0, d2 +; CHECK-GI-NEXT: ret %retval = call {<2 x half>, <2 x half>} @llvm.experimental.vector.deinterleave2.v4f16(<4 x half> %vec) ret {<2 x half>, <2 x half>} %retval } define {<4 x half>, <4 x half>} @vector_deinterleave_v4f16_v8f16(<8 x half> %vec) { -; CHECK-LABEL: vector_deinterleave_v4f16_v8f16: -; CHECK: // %bb.0: -; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: uzp1 v2.4h, v0.4h, v1.4h -; CHECK-NEXT: uzp2 v1.4h, v0.4h, v1.4h -; CHECK-NEXT: fmov d0, d2 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: vector_deinterleave_v4f16_v8f16: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: ext v1.16b, v0.16b, v0.16b, #8 +; CHECK-SD-NEXT: uzp1 v2.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp2 v1.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: fmov d0, d2 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: vector_deinterleave_v4f16_v8f16: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: uzp1 v2.8h, v0.8h, v0.8h +; CHECK-GI-NEXT: uzp2 v1.8h, v0.8h, v0.8h +; CHECK-GI-NEXT: // kill: def $d1 killed $d1 killed $q1 +; CHECK-GI-NEXT: fmov d0, d2 +; CHECK-GI-NEXT: ret %retval = call {<4 x half>, <4 x half>} @llvm.experimental.vector.deinterleave2.v8f16(<8 x half> %vec) ret {<4 x half>, <4 x half>} %retval } @@ -40,13 +61,21 @@ define {<8 x half>, <8 x half>} @vector_deinterleave_v8f16_v16f16(<16 x half> %v } define {<2 x float>, <2 x float>} @vector_deinterleave_v2f32_v4f32(<4 x float> %vec) { -; CHECK-LABEL: vector_deinterleave_v2f32_v4f32: -; CHECK: // %bb.0: -; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: zip1 v2.2s, v0.2s, v1.2s -; CHECK-NEXT: zip2 v1.2s, v0.2s, v1.2s -; CHECK-NEXT: fmov d0, d2 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: vector_deinterleave_v2f32_v4f32: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: ext v1.16b, v0.16b, v0.16b, #8 +; CHECK-SD-NEXT: zip1 v2.2s, v0.2s, v1.2s +; CHECK-SD-NEXT: zip2 v1.2s, v0.2s, v1.2s +; CHECK-SD-NEXT: fmov d0, d2 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: vector_deinterleave_v2f32_v4f32: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: uzp1 v2.4s, v0.4s, v0.4s +; CHECK-GI-NEXT: uzp2 v1.4s, v0.4s, v0.4s +; CHECK-GI-NEXT: // kill: def $d1 killed $d1 killed $q1 +; CHECK-GI-NEXT: fmov d0, d2 +; CHECK-GI-NEXT: ret %retval = call {<2 x float>, <2 x float>} @llvm.experimental.vector.deinterleave2.v4f32(<4 x float> %vec) ret {<2 x float>, <2 x float>} %retval } diff --git a/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll b/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll index 071c1ffdbb45dcf19ac6c9c25c41f9007361b387..eb81aff33e496383e0dd0f4146d827dbb775f2ed 100644 --- a/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll +++ b/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -mtriple=aarch64-linux-gnu | FileCheck %s +; RUN: llc -mtriple=aarch64-none-linux-gnu %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD +; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel -global-isel-abort=2 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI define <4 x half> @interleave2_v4f16(<2 x half> %vec0, <2 x half> %vec1) { ; CHECK-LABEL: interleave2_v4f16: @@ -11,15 +12,22 @@ define <4 x half> @interleave2_v4f16(<2 x half> %vec0, <2 x half> %vec1) { } define <8 x half> @interleave2_v8f16(<4 x half> %vec0, <4 x half> %vec1) { -; CHECK-LABEL: interleave2_v8f16: -; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 -; CHECK-NEXT: adrp x8, .LCPI1_0 -; CHECK-NEXT: mov v0.d[1], v1.d[0] -; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI1_0] -; CHECK-NEXT: tbl v0.16b, { v0.16b }, v1.16b -; CHECK-NEXT: ret +; CHECK-SD-LABEL: interleave2_v8f16: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-SD-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-SD-NEXT: adrp x8, .LCPI1_0 +; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] +; CHECK-SD-NEXT: ldr q1, [x8, :lo12:.LCPI1_0] +; CHECK-SD-NEXT: tbl v0.16b, { v0.16b }, v1.16b +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: interleave2_v8f16: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-GI-NEXT: zip1 v0.8h, v0.8h, v1.8h +; CHECK-GI-NEXT: ret %retval = call <8 x half> @llvm.experimental.vector.interleave2.v8f16(<4 x half> %vec0, <4 x half> %vec1) ret <8 x half> %retval } @@ -36,14 +44,21 @@ define <16 x half> @interleave2_v16f16(<8 x half> %vec0, <8 x half> %vec1) { } define <4 x float> @interleave2_v4f32(<2 x float> %vec0, <2 x float> %vec1) { -; CHECK-LABEL: interleave2_v4f32: -; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 -; CHECK-NEXT: mov v0.d[1], v1.d[0] -; CHECK-NEXT: rev64 v1.4s, v0.4s -; CHECK-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-NEXT: ret +; CHECK-SD-LABEL: interleave2_v4f32: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-SD-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] +; CHECK-SD-NEXT: rev64 v1.4s, v0.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: interleave2_v4f32: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-GI-NEXT: zip1 v0.4s, v0.4s, v1.4s +; CHECK-GI-NEXT: ret %retval = call <4 x float> @llvm.experimental.vector.interleave2.v4f32(<2 x float> %vec0, <2 x float> %vec1) ret <4 x float> %retval } diff --git a/llvm/test/CodeGen/AArch64/fold-global-offsets.ll b/llvm/test/CodeGen/AArch64/fold-global-offsets.ll index 897d35a78495b11504688ac891e8343834fc8f2a..8de0f0d121f90a706301406dca303565fd99d6c2 100644 --- a/llvm/test/CodeGen/AArch64/fold-global-offsets.ll +++ b/llvm/test/CodeGen/AArch64/fold-global-offsets.ll @@ -131,7 +131,7 @@ define i32 @f7() { ; GISEL-NEXT: ret entry: - %lshr = lshr i128 bitcast (<2 x i64> <i64 undef, i64 ptrtoint (ptr getelementptr inbounds ({ [9 x ptr], [8 x ptr] }, ptr @x3, i64 0, inrange i32 1, i64 2) to i64)> to i128), 64 + %lshr = lshr i128 bitcast (<2 x i64> <i64 undef, i64 ptrtoint (ptr getelementptr inbounds ({ [9 x ptr], [8 x ptr] }, ptr @x3, i64 0, i32 1, i64 2) to i64)> to i128), 64 %trunc = trunc i128 %lshr to i64 %inttoptr = inttoptr i64 %trunc to ptr %gep = getelementptr i32, ptr %inttoptr, i64 5 diff --git a/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll b/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll index 1ea87bb6b04b513aa92d38deb1ee5e16b41c2ce1..0a3b9a070c2b32174023f450597b9ec9861ba480 100644 --- a/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll +++ b/llvm/test/CodeGen/AArch64/fp-conversion-to-tbl.ll @@ -73,9 +73,8 @@ define void @fptoui_v8f32_to_v8i8_no_loop(ptr %A, ptr %dst) { ; CHECK-NEXT: ldp q0, q1, [x0] ; CHECK-NEXT: fcvtzs.4s v1, v1 ; CHECK-NEXT: fcvtzs.4s v0, v0 -; CHECK-NEXT: xtn.4h v1, v1 -; CHECK-NEXT: xtn.4h v0, v0 -; CHECK-NEXT: uzp1.8b v0, v0, v1 +; CHECK-NEXT: uzp1.8h v0, v0, v1 +; CHECK-NEXT: xtn.8b v0, v0 ; CHECK-NEXT: str d0, [x1] ; CHECK-NEXT: ret entry: diff --git a/llvm/test/CodeGen/AArch64/fp-intrinsics.ll b/llvm/test/CodeGen/AArch64/fp-intrinsics.ll index f80a8df18a03a239061651ecce71d4cc319b2261..685efbb7cad43127f351d43609f7541396a46371 100644 --- a/llvm/test/CodeGen/AArch64/fp-intrinsics.ll +++ b/llvm/test/CodeGen/AArch64/fp-intrinsics.ll @@ -1477,6 +1477,61 @@ define fp128 @fpext_f128_f64(double %x) #0 { ret fp128 %val } +; CHECK-LABEL: sin_v1f64: +; CHECK: bl sin +define <1 x double> @sin_v1f64(<1 x double> %x, <1 x double> %y) #0 { + %val = call <1 x double> @llvm.experimental.constrained.sin.v1f64(<1 x double> %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 + ret <1 x double> %val +} + +; CHECK-LABEL: cos_v1f64: +; CHECK: bl cos +define <1 x double> @cos_v1f64(<1 x double> %x, <1 x double> %y) #0 { + %val = call <1 x double> @llvm.experimental.constrained.cos.v1f64(<1 x double> %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 + ret <1 x double> %val +} + +; CHECK-LABEL: pow_v1f64: +; CHECK: bl pow +define <1 x double> @pow_v1f64(<1 x double> %x, <1 x double> %y) #0 { + %val = call <1 x double> @llvm.experimental.constrained.pow.v1f64(<1 x double> %x, <1 x double> %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 + ret <1 x double> %val +} + +; CHECK-LABEL: log_v1f64: +; CHECK: bl log +define <1 x double> @log_v1f64(<1 x double> %x, <1 x double> %y) #0 { + %val = call <1 x double> @llvm.experimental.constrained.log.v1f64(<1 x double> %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 + ret <1 x double> %val +} + +; CHECK-LABEL: log2_v1f64: +; CHECK: bl log2 +define <1 x double> @log2_v1f64(<1 x double> %x, <1 x double> %y) #0 { + %val = call <1 x double> @llvm.experimental.constrained.log2.v1f64(<1 x double> %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 + ret <1 x double> %val +} + +; CHECK-LABEL: log10_v1f64: +; CHECK: bl log10 +define <1 x double> @log10_v1f64(<1 x double> %x, <1 x double> %y) #0 { + %val = call <1 x double> @llvm.experimental.constrained.log10.v1f64(<1 x double> %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 + ret <1 x double> %val +} + +; CHECK-LABEL: exp_v1f64: +; CHECK: bl exp +define <1 x double> @exp_v1f64(<1 x double> %x, <1 x double> %y) #0 { + %val = call <1 x double> @llvm.experimental.constrained.exp.v1f64(<1 x double> %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 + ret <1 x double> %val +} + +; CHECK-LABEL: exp2_v1f64: +; CHECK: bl exp2 +define <1 x double> @exp2_v1f64(<1 x double> %x, <1 x double> %y) #0 { + %val = call <1 x double> @llvm.experimental.constrained.exp2.v1f64(<1 x double> %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 + ret <1 x double> %val +} attributes #0 = { strictfp } diff --git a/llvm/test/CodeGen/AArch64/fpow.ll b/llvm/test/CodeGen/AArch64/fpow.ll index c2ad1aafd65fc48ee4432160cf240893af9309d0..8d40121ad4543f1bc12d5ef40ff346bd651503dd 100644 --- a/llvm/test/CodeGen/AArch64/fpow.ll +++ b/llvm/test/CodeGen/AArch64/fpow.ll @@ -37,6 +37,21 @@ entry: ret half %c } +define <1 x double> @pow_v1f64(<1 x double> %x) { +; CHECK-LABEL: pow_v1f64: +; CHECK: // %bb.0: +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset w30, -16 +; CHECK-NEXT: adrp x8, .LCPI3_0 +; CHECK-NEXT: ldr d1, [x8, :lo12:.LCPI3_0] +; CHECK-NEXT: bl pow +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ret + %c = call <1 x double> @llvm.pow.v1f64(<1 x double> %x, <1 x double> <double 3.140000e+00>) + ret <1 x double> %c +} + define <2 x double> @pow_v2f64(<2 x double> %a, <2 x double> %b) { ; CHECK-SD-LABEL: pow_v2f64: ; CHECK-SD: // %bb.0: // %entry diff --git a/llvm/test/CodeGen/AArch64/fptoi.ll b/llvm/test/CodeGen/AArch64/fptoi.ll index 67190e8596c46c9ba10febc5426d767f9a7523f8..01585d02adcb139dd9c6346e01d9fe959e7d0c21 100644 --- a/llvm/test/CodeGen/AArch64/fptoi.ll +++ b/llvm/test/CodeGen/AArch64/fptoi.ll @@ -1,13 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 ; RUN: llc -mtriple=aarch64 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD,CHECK-SD-NOFP16 ; RUN: llc -mtriple=aarch64 -mattr=+fullfp16 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD,CHECK-SD-FP16 -; RUN: llc -mtriple=aarch64 -global-isel -global-isel-abort=2 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI,CHECK-GI-NOFP16 -; RUN: llc -mtriple=aarch64 -mattr=+fullfp16 -global-isel -global-isel-abort=2 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI,CHECK-GI-FP16 - -; CHECK-GI-FP16: warning: Instruction selection used fallback path for fptos_v2f16_v2i16 -; CHECK-GI-FP16-NEXT: warning: Instruction selection used fallback path for fptou_v2f16_v2i16 -; CHECK-GI-FP16-NEXT: warning: Instruction selection used fallback path for fptos_v2f16_v2i8 -; CHECK-GI-FP16-NEXT: warning: Instruction selection used fallback path for fptou_v2f16_v2i8 +; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI,CHECK-GI-NOFP16 +; RUN: llc -mtriple=aarch64 -mattr=+fullfp16 -global-isel -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI,CHECK-GI-FP16 define i64 @fptos_f64_i64(double %a) { ; CHECK-LABEL: fptos_f64_i64: @@ -1096,30 +1091,17 @@ entry: } define <3 x i16> @fptos_v3f64_v3i16(<3 x double> %a) { -; CHECK-SD-LABEL: fptos_v3f64_v3i16: -; CHECK-SD: // %bb.0: // %entry -; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-SD-NEXT: // kill: def $d1 killed $d1 def $q1 -; CHECK-SD-NEXT: // kill: def $d2 killed $d2 def $q2 -; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] -; CHECK-SD-NEXT: fcvtzs v1.2d, v2.2d -; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: fptos_v3f64_v3i16: -; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 -; CHECK-GI-NEXT: // kill: def $d2 killed $d2 def $q2 -; CHECK-GI-NEXT: mov v0.d[1], v1.d[0] -; CHECK-GI-NEXT: fcvtzs v1.2d, v2.2d -; CHECK-GI-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-GI-NEXT: uzp1 v0.4s, v0.4s, v1.4s -; CHECK-GI-NEXT: xtn v0.4h, v0.4s -; CHECK-GI-NEXT: ret +; CHECK-LABEL: fptos_v3f64_v3i16: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: // kill: def $d2 killed $d2 def $q2 +; CHECK-NEXT: mov v0.d[1], v1.d[0] +; CHECK-NEXT: fcvtzs v1.2d, v2.2d +; CHECK-NEXT: fcvtzs v0.2d, v0.2d +; CHECK-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-NEXT: xtn v0.4h, v0.4s +; CHECK-NEXT: ret entry: %c = fptosi <3 x double> %a to <3 x i16> ret <3 x i16> %c @@ -1134,9 +1116,8 @@ define <3 x i16> @fptou_v3f64_v3i16(<3 x double> %a) { ; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] ; CHECK-SD-NEXT: fcvtzs v1.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v3f64_v3i16: @@ -1160,9 +1141,8 @@ define <4 x i16> @fptos_v4f64_v4i16(<4 x double> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v4f64_v4i16: @@ -1182,9 +1162,8 @@ define <4 x i16> @fptou_v4f64_v4i16(<4 x double> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v4f64_v4i16: @@ -1600,9 +1579,8 @@ define <3 x i8> @fptos_v3f64_v3i8(<3 x double> %a) { ; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] ; CHECK-SD-NEXT: fcvtzs v1.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: umov w0, v0.h[0] ; CHECK-SD-NEXT: umov w1, v0.h[1] ; CHECK-SD-NEXT: umov w2, v0.h[2] @@ -1638,9 +1616,8 @@ define <3 x i8> @fptou_v3f64_v3i8(<3 x double> %a) { ; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] ; CHECK-SD-NEXT: fcvtzs v1.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: umov w0, v0.h[0] ; CHECK-SD-NEXT: umov w1, v0.h[1] ; CHECK-SD-NEXT: umov w2, v0.h[2] @@ -1672,9 +1649,8 @@ define <4 x i8> @fptos_v4f64_v4i8(<4 x double> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v4f64_v4i8: @@ -1694,9 +1670,8 @@ define <4 x i8> @fptou_v4f64_v4i8(<4 x double> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: xtn v0.4h, v0.4s ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v4f64_v4i8: @@ -1718,13 +1693,10 @@ define <8 x i8> @fptos_v8f64_v8i8(<8 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v2.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v3.2s, v3.2d -; CHECK-SD-NEXT: xtn v2.2s, v2.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v2.8b +; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h +; CHECK-SD-NEXT: xtn v0.8b, v0.8h ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v8f64_v8i8: @@ -1750,13 +1722,10 @@ define <8 x i8> @fptou_v8f64_v8i8(<8 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v2.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v3.2s, v3.2d -; CHECK-SD-NEXT: xtn v2.2s, v2.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v2.8b +; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h +; CHECK-SD-NEXT: xtn v0.8b, v0.8h ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v8f64_v8i8: @@ -1786,21 +1755,13 @@ define <16 x i8> @fptos_v16f64_v16i8(<16 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v2.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v7.2s, v7.2d -; CHECK-SD-NEXT: xtn v6.2s, v6.2d -; CHECK-SD-NEXT: xtn v5.2s, v5.2d -; CHECK-SD-NEXT: xtn v4.2s, v4.2d -; CHECK-SD-NEXT: xtn v3.2s, v3.2d -; CHECK-SD-NEXT: xtn v2.2s, v2.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v6.4h, v6.4h, v7.4h -; CHECK-SD-NEXT: uzp1 v4.4h, v4.4h, v5.4h -; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: mov v4.d[1], v6.d[0] -; CHECK-SD-NEXT: mov v0.d[1], v2.d[0] -; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v4.16b +; CHECK-SD-NEXT: uzp1 v6.4s, v6.4s, v7.4s +; CHECK-SD-NEXT: uzp1 v4.4s, v4.4s, v5.4s +; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: uzp1 v1.8h, v4.8h, v6.8h +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h +; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v1.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v16f64_v16i8: @@ -1837,21 +1798,13 @@ define <16 x i8> @fptou_v16f64_v16i8(<16 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v2.2d, v2.2d ; CHECK-SD-NEXT: fcvtzs v1.2d, v1.2d ; CHECK-SD-NEXT: fcvtzs v0.2d, v0.2d -; CHECK-SD-NEXT: xtn v7.2s, v7.2d -; CHECK-SD-NEXT: xtn v6.2s, v6.2d -; CHECK-SD-NEXT: xtn v5.2s, v5.2d -; CHECK-SD-NEXT: xtn v4.2s, v4.2d -; CHECK-SD-NEXT: xtn v3.2s, v3.2d -; CHECK-SD-NEXT: xtn v2.2s, v2.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: uzp1 v6.4h, v6.4h, v7.4h -; CHECK-SD-NEXT: uzp1 v4.4h, v4.4h, v5.4h -; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: mov v4.d[1], v6.d[0] -; CHECK-SD-NEXT: mov v0.d[1], v2.d[0] -; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v4.16b +; CHECK-SD-NEXT: uzp1 v6.4s, v6.4s, v7.4s +; CHECK-SD-NEXT: uzp1 v4.4s, v4.4s, v5.4s +; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: uzp1 v1.8h, v4.8h, v6.8h +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h +; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v1.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v16f64_v16i8: @@ -1900,36 +1853,20 @@ define <32 x i8> @fptos_v32f64_v32i8(<32 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v18.2d, v18.2d ; CHECK-SD-NEXT: fcvtzs v17.2d, v17.2d ; CHECK-SD-NEXT: fcvtzs v16.2d, v16.2d -; CHECK-SD-NEXT: xtn v7.2s, v7.2d -; CHECK-SD-NEXT: xtn v6.2s, v6.2d -; CHECK-SD-NEXT: xtn v5.2s, v5.2d -; CHECK-SD-NEXT: xtn v4.2s, v4.2d -; CHECK-SD-NEXT: xtn v3.2s, v3.2d -; CHECK-SD-NEXT: xtn v2.2s, v2.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: xtn v23.2s, v23.2d -; CHECK-SD-NEXT: xtn v22.2s, v22.2d -; CHECK-SD-NEXT: xtn v21.2s, v21.2d -; CHECK-SD-NEXT: xtn v20.2s, v20.2d -; CHECK-SD-NEXT: xtn v19.2s, v19.2d -; CHECK-SD-NEXT: xtn v18.2s, v18.2d -; CHECK-SD-NEXT: xtn v17.2s, v17.2d -; CHECK-SD-NEXT: xtn v16.2s, v16.2d -; CHECK-SD-NEXT: uzp1 v6.4h, v6.4h, v7.4h -; CHECK-SD-NEXT: uzp1 v4.4h, v4.4h, v5.4h -; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: uzp1 v1.4h, v22.4h, v23.4h -; CHECK-SD-NEXT: uzp1 v3.4h, v20.4h, v21.4h -; CHECK-SD-NEXT: uzp1 v5.4h, v18.4h, v19.4h -; CHECK-SD-NEXT: uzp1 v7.4h, v16.4h, v17.4h -; CHECK-SD-NEXT: mov v4.d[1], v6.d[0] -; CHECK-SD-NEXT: mov v0.d[1], v2.d[0] -; CHECK-SD-NEXT: mov v3.d[1], v1.d[0] -; CHECK-SD-NEXT: mov v7.d[1], v5.d[0] +; CHECK-SD-NEXT: uzp1 v6.4s, v6.4s, v7.4s +; CHECK-SD-NEXT: uzp1 v4.4s, v4.4s, v5.4s +; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: uzp1 v3.4s, v20.4s, v21.4s +; CHECK-SD-NEXT: uzp1 v1.4s, v22.4s, v23.4s +; CHECK-SD-NEXT: uzp1 v5.4s, v18.4s, v19.4s +; CHECK-SD-NEXT: uzp1 v7.4s, v16.4s, v17.4s +; CHECK-SD-NEXT: uzp1 v4.8h, v4.8h, v6.8h +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h +; CHECK-SD-NEXT: uzp1 v1.8h, v3.8h, v1.8h +; CHECK-SD-NEXT: uzp1 v2.8h, v7.8h, v5.8h ; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v4.16b -; CHECK-SD-NEXT: uzp1 v1.16b, v7.16b, v3.16b +; CHECK-SD-NEXT: uzp1 v1.16b, v2.16b, v1.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v32f64_v32i8: @@ -1997,36 +1934,20 @@ define <32 x i8> @fptou_v32f64_v32i8(<32 x double> %a) { ; CHECK-SD-NEXT: fcvtzs v18.2d, v18.2d ; CHECK-SD-NEXT: fcvtzs v17.2d, v17.2d ; CHECK-SD-NEXT: fcvtzs v16.2d, v16.2d -; CHECK-SD-NEXT: xtn v7.2s, v7.2d -; CHECK-SD-NEXT: xtn v6.2s, v6.2d -; CHECK-SD-NEXT: xtn v5.2s, v5.2d -; CHECK-SD-NEXT: xtn v4.2s, v4.2d -; CHECK-SD-NEXT: xtn v3.2s, v3.2d -; CHECK-SD-NEXT: xtn v2.2s, v2.2d -; CHECK-SD-NEXT: xtn v1.2s, v1.2d -; CHECK-SD-NEXT: xtn v0.2s, v0.2d -; CHECK-SD-NEXT: xtn v23.2s, v23.2d -; CHECK-SD-NEXT: xtn v22.2s, v22.2d -; CHECK-SD-NEXT: xtn v21.2s, v21.2d -; CHECK-SD-NEXT: xtn v20.2s, v20.2d -; CHECK-SD-NEXT: xtn v19.2s, v19.2d -; CHECK-SD-NEXT: xtn v18.2s, v18.2d -; CHECK-SD-NEXT: xtn v17.2s, v17.2d -; CHECK-SD-NEXT: xtn v16.2s, v16.2d -; CHECK-SD-NEXT: uzp1 v6.4h, v6.4h, v7.4h -; CHECK-SD-NEXT: uzp1 v4.4h, v4.4h, v5.4h -; CHECK-SD-NEXT: uzp1 v2.4h, v2.4h, v3.4h -; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h -; CHECK-SD-NEXT: uzp1 v1.4h, v22.4h, v23.4h -; CHECK-SD-NEXT: uzp1 v3.4h, v20.4h, v21.4h -; CHECK-SD-NEXT: uzp1 v5.4h, v18.4h, v19.4h -; CHECK-SD-NEXT: uzp1 v7.4h, v16.4h, v17.4h -; CHECK-SD-NEXT: mov v4.d[1], v6.d[0] -; CHECK-SD-NEXT: mov v0.d[1], v2.d[0] -; CHECK-SD-NEXT: mov v3.d[1], v1.d[0] -; CHECK-SD-NEXT: mov v7.d[1], v5.d[0] +; CHECK-SD-NEXT: uzp1 v6.4s, v6.4s, v7.4s +; CHECK-SD-NEXT: uzp1 v4.4s, v4.4s, v5.4s +; CHECK-SD-NEXT: uzp1 v2.4s, v2.4s, v3.4s +; CHECK-SD-NEXT: uzp1 v0.4s, v0.4s, v1.4s +; CHECK-SD-NEXT: uzp1 v3.4s, v20.4s, v21.4s +; CHECK-SD-NEXT: uzp1 v1.4s, v22.4s, v23.4s +; CHECK-SD-NEXT: uzp1 v5.4s, v18.4s, v19.4s +; CHECK-SD-NEXT: uzp1 v7.4s, v16.4s, v17.4s +; CHECK-SD-NEXT: uzp1 v4.8h, v4.8h, v6.8h +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v2.8h +; CHECK-SD-NEXT: uzp1 v1.8h, v3.8h, v1.8h +; CHECK-SD-NEXT: uzp1 v2.8h, v7.8h, v5.8h ; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v4.16b -; CHECK-SD-NEXT: uzp1 v1.16b, v7.16b, v3.16b +; CHECK-SD-NEXT: uzp1 v1.16b, v2.16b, v1.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v32f64_v32i8: @@ -3026,9 +2947,8 @@ define <8 x i8> @fptos_v8f32_v8i8(<8 x float> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.4s, v1.4s ; CHECK-SD-NEXT: fcvtzs v0.4s, v0.4s -; CHECK-SD-NEXT: xtn v1.4h, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v1.8b +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v1.8h +; CHECK-SD-NEXT: xtn v0.8b, v0.8h ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v8f32_v8i8: @@ -3048,9 +2968,8 @@ define <8 x i8> @fptou_v8f32_v8i8(<8 x float> %a) { ; CHECK-SD: // %bb.0: // %entry ; CHECK-SD-NEXT: fcvtzs v1.4s, v1.4s ; CHECK-SD-NEXT: fcvtzs v0.4s, v0.4s -; CHECK-SD-NEXT: xtn v1.4h, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v1.8b +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v1.8h +; CHECK-SD-NEXT: xtn v0.8b, v0.8h ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptou_v8f32_v8i8: @@ -3072,12 +2991,8 @@ define <16 x i8> @fptos_v16f32_v16i8(<16 x float> %a) { ; CHECK-SD-NEXT: fcvtzs v2.4s, v2.4s ; CHECK-SD-NEXT: fcvtzs v1.4s, v1.4s ; CHECK-SD-NEXT: fcvtzs v0.4s, v0.4s -; CHECK-SD-NEXT: xtn v3.4h, v3.4s -; CHECK-SD-NEXT: xtn v2.4h, v2.4s -; CHECK-SD-NEXT: xtn v1.4h, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: mov v2.d[1], v3.d[0] -; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] +; CHECK-SD-NEXT: uzp1 v2.8h, v2.8h, v3.8h +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v1.8h ; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v2.16b ; CHECK-SD-NEXT: ret ; @@ -3134,20 +3049,12 @@ define <32 x i8> @fptos_v32f32_v32i8(<32 x float> %a) { ; CHECK-SD-NEXT: fcvtzs v6.4s, v6.4s ; CHECK-SD-NEXT: fcvtzs v5.4s, v5.4s ; CHECK-SD-NEXT: fcvtzs v4.4s, v4.4s -; CHECK-SD-NEXT: xtn v3.4h, v3.4s -; CHECK-SD-NEXT: xtn v2.4h, v2.4s -; CHECK-SD-NEXT: xtn v1.4h, v1.4s -; CHECK-SD-NEXT: xtn v0.4h, v0.4s -; CHECK-SD-NEXT: xtn v7.4h, v7.4s -; CHECK-SD-NEXT: xtn v6.4h, v6.4s -; CHECK-SD-NEXT: xtn v5.4h, v5.4s -; CHECK-SD-NEXT: xtn v4.4h, v4.4s -; CHECK-SD-NEXT: mov v2.d[1], v3.d[0] -; CHECK-SD-NEXT: mov v0.d[1], v1.d[0] -; CHECK-SD-NEXT: mov v6.d[1], v7.d[0] -; CHECK-SD-NEXT: mov v4.d[1], v5.d[0] +; CHECK-SD-NEXT: uzp1 v2.8h, v2.8h, v3.8h +; CHECK-SD-NEXT: uzp1 v0.8h, v0.8h, v1.8h +; CHECK-SD-NEXT: uzp1 v1.8h, v6.8h, v7.8h +; CHECK-SD-NEXT: uzp1 v3.8h, v4.8h, v5.8h ; CHECK-SD-NEXT: uzp1 v0.16b, v0.16b, v2.16b -; CHECK-SD-NEXT: uzp1 v1.16b, v4.16b, v6.16b +; CHECK-SD-NEXT: uzp1 v1.16b, v3.16b, v1.16b ; CHECK-SD-NEXT: ret ; ; CHECK-GI-LABEL: fptos_v32f32_v32i8: @@ -5272,8 +5179,13 @@ define <2 x i16> @fptos_v2f16_v2i16(<2 x half> %a) { ; ; CHECK-GI-FP16-LABEL: fptos_v2f16_v2i16: ; CHECK-GI-FP16: // %bb.0: // %entry -; CHECK-GI-FP16-NEXT: fcvtl v0.4s, v0.4h -; CHECK-GI-FP16-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-FP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-FP16-NEXT: fcvtzs v0.4h, v0.4h +; CHECK-GI-FP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-FP16-NEXT: ushll v0.4s, v0.4h, #0 ; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-FP16-NEXT: ret entry: @@ -5300,8 +5212,13 @@ define <2 x i16> @fptou_v2f16_v2i16(<2 x half> %a) { ; ; CHECK-GI-FP16-LABEL: fptou_v2f16_v2i16: ; CHECK-GI-FP16: // %bb.0: // %entry -; CHECK-GI-FP16-NEXT: fcvtl v0.4s, v0.4h -; CHECK-GI-FP16-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-FP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-FP16-NEXT: fcvtzu v0.4h, v0.4h +; CHECK-GI-FP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-FP16-NEXT: ushll v0.4s, v0.4h, #0 ; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-FP16-NEXT: ret entry: @@ -5746,8 +5663,13 @@ define <2 x i8> @fptos_v2f16_v2i8(<2 x half> %a) { ; ; CHECK-GI-FP16-LABEL: fptos_v2f16_v2i8: ; CHECK-GI-FP16: // %bb.0: // %entry -; CHECK-GI-FP16-NEXT: fcvtl v0.4s, v0.4h -; CHECK-GI-FP16-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-FP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-FP16-NEXT: fcvtzs v0.4h, v0.4h +; CHECK-GI-FP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-FP16-NEXT: ushll v0.4s, v0.4h, #0 ; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-FP16-NEXT: ret entry: @@ -5774,8 +5696,13 @@ define <2 x i8> @fptou_v2f16_v2i8(<2 x half> %a) { ; ; CHECK-GI-FP16-LABEL: fptou_v2f16_v2i8: ; CHECK-GI-FP16: // %bb.0: // %entry -; CHECK-GI-FP16-NEXT: fcvtl v0.4s, v0.4h -; CHECK-GI-FP16-NEXT: fcvtzs v0.4s, v0.4s +; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-FP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-FP16-NEXT: fcvtzu v0.4h, v0.4h +; CHECK-GI-FP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-FP16-NEXT: ushll v0.4s, v0.4h, #0 ; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-FP16-NEXT: ret entry: diff --git a/llvm/test/CodeGen/AArch64/fsincos.ll b/llvm/test/CodeGen/AArch64/fsincos.ll index 2ab1610edcc7f1f2175514d5703a232fd55bcb41..0b34f9570fa77beb92cb1d0f96f531cd26721a81 100644 --- a/llvm/test/CodeGen/AArch64/fsincos.ll +++ b/llvm/test/CodeGen/AArch64/fsincos.ll @@ -36,6 +36,19 @@ entry: ret half %c } +define <1 x double> @sin_v1f64(<1 x double> %x) { +; CHECK-LABEL: sin_v1f64: +; CHECK: // %bb.0: +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset w30, -16 +; CHECK-NEXT: bl sin +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ret + %c = call <1 x double> @llvm.sin.v1f64(<1 x double> %x) + ret <1 x double> %c +} + define <2 x double> @sin_v2f64(<2 x double> %a) { ; CHECK-SD-LABEL: sin_v2f64: ; CHECK-SD: // %bb.0: // %entry @@ -1293,6 +1306,19 @@ entry: ret half %c } +define <1 x double> @cos_v1f64(<1 x double> %x) { +; CHECK-LABEL: cos_v1f64: +; CHECK: // %bb.0: +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset w30, -16 +; CHECK-NEXT: bl cos +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ret + %c = call <1 x double> @llvm.cos.v1f64(<1 x double> %x) + ret <1 x double> %c +} + define <2 x double> @cos_v2f64(<2 x double> %a) { ; CHECK-SD-LABEL: cos_v2f64: ; CHECK-SD: // %bb.0: // %entry diff --git a/llvm/test/CodeGen/AArch64/hadd-combine.ll b/llvm/test/CodeGen/AArch64/hadd-combine.ll index 2269d75cdbb9ede2d94bdfc043ca5613471dd91a..491bf40ea4aab005cb82faf12eb81c23e41d8c8b 100644 --- a/llvm/test/CodeGen/AArch64/hadd-combine.ll +++ b/llvm/test/CodeGen/AArch64/hadd-combine.ll @@ -329,9 +329,29 @@ define <8 x i16> @hadds_i_undef(<8 x i16> %t, <8 x i16> %src1) { ret <8 x i16> %result } +define <8 x i16> @sub_fixedwidth_v4i32(<8 x i16> %a0, <8 x i16> %a1) { +; CHECK-LABEL: sub_fixedwidth_v4i32: +; CHECK: // %bb.0: +; CHECK-NEXT: urhadd v0.8h, v0.8h, v1.8h +; CHECK-NEXT: ret + %or = or <8 x i16> %a0, %a1 + %xor = xor <8 x i16> %a0, %a1 + %srl = lshr <8 x i16> %xor, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = sub <8 x i16> %or, %srl + ret <8 x i16> %res +} - - +define <8 x i16> @srhadd_fixedwidth_v8i16(<8 x i16> %a0, <8 x i16> %a1) { +; CHECK-LABEL: srhadd_fixedwidth_v8i16: +; CHECK: // %bb.0: +; CHECK-NEXT: srhadd v0.8h, v0.8h, v1.8h +; CHECK-NEXT: ret + %or = or <8 x i16> %a0, %a1 + %xor = xor <8 x i16> %a0, %a1 + %srl = ashr <8 x i16> %xor, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = sub <8 x i16> %or, %srl + ret <8 x i16> %res +} define <8 x i16> @rhaddu_base(<8 x i16> %src1, <8 x i16> %src2) { ; CHECK-LABEL: rhaddu_base: @@ -859,6 +879,30 @@ define <4 x i32> @urhadd_v4i32(<4 x i32> %x) { ret <4 x i32> %r } +define <8 x i16> @uhadd_fixedwidth_v4i32(<8 x i16> %a0, <8 x i16> %a1) { +; CHECK-LABEL: uhadd_fixedwidth_v4i32: +; CHECK: // %bb.0: +; CHECK-NEXT: uhadd v0.8h, v0.8h, v1.8h +; CHECK-NEXT: ret + %and = and <8 x i16> %a0, %a1 + %xor = xor <8 x i16> %a0, %a1 + %srl = lshr <8 x i16> %xor, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = add <8 x i16> %and, %srl + ret <8 x i16> %res +} + +define <8 x i16> @shadd_fixedwidth_v8i16(<8 x i16> %a0, <8 x i16> %a1) { +; CHECK-LABEL: shadd_fixedwidth_v8i16: +; CHECK: // %bb.0: +; CHECK-NEXT: shadd v0.8h, v0.8h, v1.8h +; CHECK-NEXT: ret + %and = and <8 x i16> %a0, %a1 + %xor = xor <8 x i16> %a0, %a1 + %srl = ashr <8 x i16> %xor, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = add <8 x i16> %and, %srl + ret <8 x i16> %res +} + declare <8 x i8> @llvm.aarch64.neon.shadd.v8i8(<8 x i8>, <8 x i8>) declare <4 x i16> @llvm.aarch64.neon.shadd.v4i16(<4 x i16>, <4 x i16>) declare <2 x i32> @llvm.aarch64.neon.shadd.v2i32(<2 x i32>, <2 x i32>) diff --git a/llvm/test/CodeGen/AArch64/implicit-def-remat-requires-impdef-check.mir b/llvm/test/CodeGen/AArch64/implicit-def-remat-requires-impdef-check.mir index aa94a03786f54acc7372c117cea6f8a7115bd54a..47aa34e3c01156e92cffb510d2fdba7be51b48d7 100644 --- a/llvm/test/CodeGen/AArch64/implicit-def-remat-requires-impdef-check.mir +++ b/llvm/test/CodeGen/AArch64/implicit-def-remat-requires-impdef-check.mir @@ -22,6 +22,7 @@ name: inst_stores_to_dead_spill_implicit_def_impdef tracksRegLiveness: true frameInfo: + adjustsStack: true hasCalls: true body: | bb.0: @@ -59,6 +60,7 @@ body: | name: inst_stores_to_dead_spill_movimm_impdef tracksRegLiveness: true frameInfo: + adjustsStack: true hasCalls: true body: | bb.0: diff --git a/llvm/test/CodeGen/AArch64/implicit-def-with-impdef-greedy-assert.mir b/llvm/test/CodeGen/AArch64/implicit-def-with-impdef-greedy-assert.mir index e5395b20afd4266d053b75bf5bbc6c1093db9ff8..a5d74ef75f0a0a7597053624fa138f810cafe379 100644 --- a/llvm/test/CodeGen/AArch64/implicit-def-with-impdef-greedy-assert.mir +++ b/llvm/test/CodeGen/AArch64/implicit-def-with-impdef-greedy-assert.mir @@ -4,6 +4,8 @@ --- name: widget tracksRegLiveness: true +frameInfo: + adjustsStack: true jumpTable: kind: label-difference32 entries: diff --git a/llvm/test/CodeGen/AArch64/insert-subvector.ll b/llvm/test/CodeGen/AArch64/insert-subvector.ll index d7656e1cd341f66388025969d1c2a9131717ae27..6828fa9f1508c8b3d2134613175f6b0a55813623 100644 --- a/llvm/test/CodeGen/AArch64/insert-subvector.ll +++ b/llvm/test/CodeGen/AArch64/insert-subvector.ll @@ -374,18 +374,115 @@ define <16 x i8> @load_v16i8_8_2(float %tmp, <16 x i8> %b, ptr %a) { ret <16 x i8> %s2 } +define <8 x i8> @load_v8i8_2_1(float %tmp, <8 x i8> %b, ptr %a) { +; CHECK-LABEL: load_v8i8_2_1: +; CHECK: // %bb.0: +; CHECK-NEXT: fmov d0, d1 +; CHECK-NEXT: ldr h2, [x0] +; CHECK-NEXT: mov v0.h[0], v2.h[0] +; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-NEXT: ret + %l = load <2 x i8>, ptr %a + %s1 = shufflevector <2 x i8> %l, <2 x i8> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> + %s2 = shufflevector <8 x i8> %s1, <8 x i8> %b, <8 x i32> <i32 0, i32 1, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> + ret <8 x i8> %s2 +} + +define <8 x i8> @load_v8i8_2_15(float %tmp, <8 x i8> %b, ptr %a) { +; CHECK-LABEL: load_v8i8_2_15: +; CHECK: // %bb.0: +; CHECK-NEXT: ldr h0, [x0] +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: adrp x8, .LCPI33_0 +; CHECK-NEXT: mov v0.d[1], v1.d[0] +; CHECK-NEXT: ldr d1, [x8, :lo12:.LCPI33_0] +; CHECK-NEXT: tbl v0.8b, { v0.16b }, v1.8b +; CHECK-NEXT: ret + %l = load <2 x i8>, ptr %a + %s1 = shufflevector <2 x i8> %l, <2 x i8> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> + %s2 = shufflevector <8 x i8> %s1, <8 x i8> %b, <8 x i32> <i32 8, i32 0, i32 1, i32 11, i32 12, i32 13, i32 14, i32 15> + ret <8 x i8> %s2 +} + +define <8 x i8> @load_v8i8_2_2(float %tmp, <8 x i8> %b, ptr %a) { +; CHECK-LABEL: load_v8i8_2_2: +; CHECK: // %bb.0: +; CHECK-NEXT: fmov d0, d1 +; CHECK-NEXT: ldr h2, [x0] +; CHECK-NEXT: mov v0.h[1], v2.h[0] +; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-NEXT: ret + %l = load <2 x i8>, ptr %a + %s1 = shufflevector <2 x i8> %l, <2 x i8> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> + %s2 = shufflevector <8 x i8> %s1, <8 x i8> %b, <8 x i32> <i32 8, i32 9, i32 0, i32 1, i32 12, i32 13, i32 14, i32 15> + ret <8 x i8> %s2 +} + +define <8 x i8> @load_v8i8_2_3(float %tmp, <8 x i8> %b, ptr %a) { +; CHECK-LABEL: load_v8i8_2_3: +; CHECK: // %bb.0: +; CHECK-NEXT: fmov d0, d1 +; CHECK-NEXT: ldr h2, [x0] +; CHECK-NEXT: mov v0.h[2], v2.h[0] +; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-NEXT: ret + %l = load <2 x i8>, ptr %a + %s1 = shufflevector <2 x i8> %l, <2 x i8> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> + %s2 = shufflevector <8 x i8> %s1, <8 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 0, i32 1, i32 14, i32 15> + ret <8 x i8> %s2 +} + +define <8 x i8> @load_v8i8_2_4(float %tmp, <8 x i8> %b, ptr %a) { +; CHECK-LABEL: load_v8i8_2_4: +; CHECK: // %bb.0: +; CHECK-NEXT: fmov d0, d1 +; CHECK-NEXT: ldr h2, [x0] +; CHECK-NEXT: mov v0.h[3], v2.h[0] +; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-NEXT: ret + %l = load <2 x i8>, ptr %a + %s1 = shufflevector <2 x i8> %l, <2 x i8> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> + %s2 = shufflevector <8 x i8> %s1, <8 x i8> %b, <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 0, i32 1> + ret <8 x i8> %s2 +} + +define <4 x i8> @load_v4i8_2_1(float %tmp, <4 x i8> %b, ptr %a) { +; CHECK-LABEL: load_v4i8_2_1: +; CHECK: // %bb.0: +; CHECK-NEXT: ldr h0, [x0] +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: zip1 v0.8b, v0.8b, v0.8b +; CHECK-NEXT: mov v0.s[1], v1.s[1] +; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-NEXT: ret + %l = load <2 x i8>, ptr %a + %s1 = shufflevector <2 x i8> %l, <2 x i8> poison, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef> + %s2 = shufflevector <4 x i8> %s1, <4 x i8> %b, <4 x i32> <i32 0, i32 1, i32 6, i32 7> + ret <4 x i8> %s2 +} + +define <4 x i8> @load_v4i8_2_2(float %tmp, <4 x i8> %b, ptr %a) { +; CHECK-LABEL: load_v4i8_2_2: +; CHECK: // %bb.0: +; CHECK-NEXT: ldr h0, [x0] +; CHECK-NEXT: zip1 v2.8b, v0.8b, v0.8b +; CHECK-NEXT: fmov d0, d1 +; CHECK-NEXT: mov v0.s[1], v2.s[0] +; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-NEXT: ret + %l = load <2 x i8>, ptr %a + %s1 = shufflevector <2 x i8> %l, <2 x i8> poison, <4 x i32> <i32 0, i32 1, i32 undef, i32 undef> + %s2 = shufflevector <4 x i8> %s1, <4 x i8> %b, <4 x i32> <i32 4, i32 5, i32 0, i32 1> + ret <4 x i8> %s2 +} + ; i16 define <8 x i16> @load_v8i16_2_1(float %tmp, <8 x i16> %b, ptr %a) { ; CHECK-LABEL: load_v8i16_2_1: ; CHECK: // %bb.0: -; CHECK-NEXT: ldrh w8, [x0] -; CHECK-NEXT: add x9, x0, #2 -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: ld1 { v0.h }[2], [x9] -; CHECK-NEXT: xtn v2.4h, v0.4s ; CHECK-NEXT: mov v0.16b, v1.16b -; CHECK-NEXT: mov v0.s[0], v2.s[0] +; CHECK-NEXT: ld1 { v0.s }[0], [x0] ; CHECK-NEXT: ret %l = load <2 x i16>, ptr %a %s1 = shufflevector <2 x i16> %l, <2 x i16> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> @@ -396,14 +493,10 @@ define <8 x i16> @load_v8i16_2_1(float %tmp, <8 x i16> %b, ptr %a) { define <8 x i16> @load_v8i16_2_15(float %tmp, <8 x i16> %b, ptr %a) { ; CHECK-LABEL: load_v8i16_2_15: ; CHECK: // %bb.0: -; CHECK-NEXT: ldrh w8, [x0] -; CHECK-NEXT: add x9, x0, #2 ; CHECK-NEXT: // kill: def $q1 killed $q1 def $q0_q1 -; CHECK-NEXT: fmov s2, w8 -; CHECK-NEXT: adrp x8, .LCPI33_0 -; CHECK-NEXT: ld1 { v2.h }[2], [x9] -; CHECK-NEXT: xtn v0.4h, v2.4s -; CHECK-NEXT: ldr q2, [x8, :lo12:.LCPI33_0] +; CHECK-NEXT: adrp x8, .LCPI40_0 +; CHECK-NEXT: ldr s0, [x0] +; CHECK-NEXT: ldr q2, [x8, :lo12:.LCPI40_0] ; CHECK-NEXT: tbl v0.16b, { v0.16b, v1.16b }, v2.16b ; CHECK-NEXT: ret %l = load <2 x i16>, ptr %a @@ -415,13 +508,8 @@ define <8 x i16> @load_v8i16_2_15(float %tmp, <8 x i16> %b, ptr %a) { define <8 x i16> @load_v8i16_2_2(float %tmp, <8 x i16> %b, ptr %a) { ; CHECK-LABEL: load_v8i16_2_2: ; CHECK: // %bb.0: -; CHECK-NEXT: ldrh w8, [x0] -; CHECK-NEXT: add x9, x0, #2 -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: ld1 { v0.h }[2], [x9] -; CHECK-NEXT: xtn v2.4h, v0.4s ; CHECK-NEXT: mov v0.16b, v1.16b -; CHECK-NEXT: mov v0.s[1], v2.s[0] +; CHECK-NEXT: ld1 { v0.s }[1], [x0] ; CHECK-NEXT: ret %l = load <2 x i16>, ptr %a %s1 = shufflevector <2 x i16> %l, <2 x i16> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> @@ -432,13 +520,8 @@ define <8 x i16> @load_v8i16_2_2(float %tmp, <8 x i16> %b, ptr %a) { define <8 x i16> @load_v8i16_2_3(float %tmp, <8 x i16> %b, ptr %a) { ; CHECK-LABEL: load_v8i16_2_3: ; CHECK: // %bb.0: -; CHECK-NEXT: ldrh w8, [x0] -; CHECK-NEXT: add x9, x0, #2 -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: ld1 { v0.h }[2], [x9] -; CHECK-NEXT: xtn v2.4h, v0.4s ; CHECK-NEXT: mov v0.16b, v1.16b -; CHECK-NEXT: mov v0.s[2], v2.s[0] +; CHECK-NEXT: ld1 { v0.s }[2], [x0] ; CHECK-NEXT: ret %l = load <2 x i16>, ptr %a %s1 = shufflevector <2 x i16> %l, <2 x i16> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> @@ -449,13 +532,8 @@ define <8 x i16> @load_v8i16_2_3(float %tmp, <8 x i16> %b, ptr %a) { define <8 x i16> @load_v8i16_2_4(float %tmp, <8 x i16> %b, ptr %a) { ; CHECK-LABEL: load_v8i16_2_4: ; CHECK: // %bb.0: -; CHECK-NEXT: ldrh w8, [x0] -; CHECK-NEXT: add x9, x0, #2 -; CHECK-NEXT: fmov s0, w8 -; CHECK-NEXT: ld1 { v0.h }[2], [x9] -; CHECK-NEXT: xtn v2.4h, v0.4s ; CHECK-NEXT: mov v0.16b, v1.16b -; CHECK-NEXT: mov v0.s[3], v2.s[0] +; CHECK-NEXT: ld1 { v0.s }[3], [x0] ; CHECK-NEXT: ret %l = load <2 x i16>, ptr %a %s1 = shufflevector <2 x i16> %l, <2 x i16> poison, <8 x i32> <i32 0, i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> @@ -466,11 +544,8 @@ define <8 x i16> @load_v8i16_2_4(float %tmp, <8 x i16> %b, ptr %a) { define <4 x i16> @load_v4i16_2_1(float %tmp, <4 x i16> %b, ptr %a) { ; CHECK-LABEL: load_v4i16_2_1: ; CHECK: // %bb.0: -; CHECK-NEXT: ld1 { v0.h }[0], [x0] -; CHECK-NEXT: add x8, x0, #2 +; CHECK-NEXT: ldr s0, [x0] ; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 -; CHECK-NEXT: ld1 { v0.h }[2], [x8] -; CHECK-NEXT: uzp1 v0.4h, v0.4h, v0.4h ; CHECK-NEXT: mov v0.s[1], v1.s[1] ; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-NEXT: ret @@ -483,11 +558,8 @@ define <4 x i16> @load_v4i16_2_1(float %tmp, <4 x i16> %b, ptr %a) { define <4 x i16> @load_v4i16_2_2(float %tmp, <4 x i16> %b, ptr %a) { ; CHECK-LABEL: load_v4i16_2_2: ; CHECK: // %bb.0: -; CHECK-NEXT: ld1 { v0.h }[0], [x0] -; CHECK-NEXT: add x8, x0, #2 -; CHECK-NEXT: ld1 { v0.h }[2], [x8] -; CHECK-NEXT: uzp1 v2.4h, v0.4h, v0.4h ; CHECK-NEXT: fmov d0, d1 +; CHECK-NEXT: ldr s2, [x0] ; CHECK-NEXT: mov v0.s[1], v2.s[0] ; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/isinf.ll b/llvm/test/CodeGen/AArch64/isinf.ll index 458bd7eeba16cfff977cee304740ee586554b07e..834417b98743a8497023bf97a799cfc095be9eba 100644 --- a/llvm/test/CodeGen/AArch64/isinf.ll +++ b/llvm/test/CodeGen/AArch64/isinf.ll @@ -58,22 +58,14 @@ define i32 @replace_isinf_call_f64(double %x) { define i32 @replace_isinf_call_f128(fp128 %x) { ; CHECK-LABEL: replace_isinf_call_f128: ; CHECK: // %bb.0: -; CHECK-NEXT: sub sp, sp, #32 -; CHECK-NEXT: str x30, [sp, #16] // 8-byte Folded Spill -; CHECK-NEXT: .cfi_def_cfa_offset 32 -; CHECK-NEXT: .cfi_offset w30, -16 -; CHECK-NEXT: str q0, [sp] -; CHECK-NEXT: ldrb w8, [sp, #15] -; CHECK-NEXT: and w8, w8, #0x7f -; CHECK-NEXT: strb w8, [sp, #15] -; CHECK-NEXT: adrp x8, .LCPI3_0 -; CHECK-NEXT: ldr q0, [sp] -; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI3_0] -; CHECK-NEXT: bl __eqtf2 -; CHECK-NEXT: cmp w0, #0 -; CHECK-NEXT: ldr x30, [sp, #16] // 8-byte Folded Reload +; CHECK-NEXT: str q0, [sp, #-16]! +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: ldp x9, x8, [sp], #16 +; CHECK-NEXT: and x8, x8, #0x7fffffffffffffff +; CHECK-NEXT: eor x8, x8, #0x7fff000000000000 +; CHECK-NEXT: orr x8, x9, x8 +; CHECK-NEXT: cmp x8, #0 ; CHECK-NEXT: cset w0, eq -; CHECK-NEXT: add sp, sp, #32 ; CHECK-NEXT: ret %abs = tail call fp128 @llvm.fabs.f128(fp128 %x) %cmpinf = fcmp oeq fp128 %abs, 0xL00000000000000007FFF000000000000 diff --git a/llvm/test/CodeGen/AArch64/itofp.ll b/llvm/test/CodeGen/AArch64/itofp.ll index 2164c2aad20111a308bbe3031e9e7047659a2910..f5a7b5dc9f4922b13417d4585fb00d9681c128a4 100644 --- a/llvm/test/CodeGen/AArch64/itofp.ll +++ b/llvm/test/CodeGen/AArch64/itofp.ll @@ -4,13 +4,6 @@ ; RUN: llc -mtriple=aarch64 -global-isel -global-isel-abort=2 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI,CHECK-GI-NOFP16 ; RUN: llc -mtriple=aarch64 -mattr=+fullfp16 -global-isel -global-isel-abort=2 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI,CHECK-GI-FP16 -; CHECK-GI: warning: Instruction selection used fallback path for stofp_v3i8_v3f64 -; CHECK-GI-NEXT: warning: Instruction selection used fallback path for utofp_v3i8_v3f64 -; CHECK-GI-NEXT: warning: Instruction selection used fallback path for stofp_v3i8_v3f32 -; CHECK-GI-NEXT: warning: Instruction selection used fallback path for utofp_v3i8_v3f32 -; CHECK-GI-NOFP16-NEXT: warning: Instruction selection used fallback path for stofp_v3i8_v3f16 -; CHECK-GI-NOFP16-NEXT: warning: Instruction selection used fallback path for utofp_v3i8_v3f16 - define double @stofp_i64_f64(i64 %a) { ; CHECK-LABEL: stofp_i64_f64: ; CHECK: // %bb.0: // %entry @@ -1754,47 +1747,109 @@ entry: } define <3 x double> @stofp_v3i8_v3f64(<3 x i8> %a) { -; CHECK-LABEL: stofp_v3i8_v3f64: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: fmov s0, w0 -; CHECK-NEXT: fmov s1, w2 -; CHECK-NEXT: mov v0.s[1], w1 -; CHECK-NEXT: shl v1.2s, v1.2s, #24 -; CHECK-NEXT: sshr v1.2s, v1.2s, #24 -; CHECK-NEXT: shl v0.2s, v0.2s, #24 -; CHECK-NEXT: sshll v1.2d, v1.2s, #0 -; CHECK-NEXT: sshr v0.2s, v0.2s, #24 -; CHECK-NEXT: scvtf v2.2d, v1.2d -; CHECK-NEXT: sshll v0.2d, v0.2s, #0 -; CHECK-NEXT: // kill: def $d2 killed $d2 killed $q2 -; CHECK-NEXT: scvtf v0.2d, v0.2d -; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 -; CHECK-NEXT: // kill: def $d1 killed $d1 killed $q1 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: stofp_v3i8_v3f64: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: fmov s0, w0 +; CHECK-SD-NEXT: fmov s1, w2 +; CHECK-SD-NEXT: mov v0.s[1], w1 +; CHECK-SD-NEXT: shl v1.2s, v1.2s, #24 +; CHECK-SD-NEXT: sshr v1.2s, v1.2s, #24 +; CHECK-SD-NEXT: shl v0.2s, v0.2s, #24 +; CHECK-SD-NEXT: sshll v1.2d, v1.2s, #0 +; CHECK-SD-NEXT: sshr v0.2s, v0.2s, #24 +; CHECK-SD-NEXT: scvtf v2.2d, v1.2d +; CHECK-SD-NEXT: sshll v0.2d, v0.2s, #0 +; CHECK-SD-NEXT: // kill: def $d2 killed $d2 killed $q2 +; CHECK-SD-NEXT: scvtf v0.2d, v0.2d +; CHECK-SD-NEXT: ext v1.16b, v0.16b, v0.16b, #8 +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-SD-NEXT: // kill: def $d1 killed $d1 killed $q1 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: stofp_v3i8_v3f64: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: fmov s0, w0 +; CHECK-GI-NEXT: fmov s1, w1 +; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NEXT: fmov s1, w2 +; CHECK-GI-NEXT: mov v0.h[2], v1.h[0] +; CHECK-GI-NEXT: shl v0.4h, v0.4h, #8 +; CHECK-GI-NEXT: sshr v0.4h, v0.4h, #8 +; CHECK-GI-NEXT: mov h2, v0.h[1] +; CHECK-GI-NEXT: mov s1, v0.s[1] +; CHECK-GI-NEXT: mov v0.h[1], v2.h[0] +; CHECK-GI-NEXT: mov h2, v1.h[1] +; CHECK-GI-NEXT: sshll v0.4s, v0.4h, #0 +; CHECK-GI-NEXT: mov v1.h[1], v2.h[0] +; CHECK-GI-NEXT: smov x8, v0.s[0] +; CHECK-GI-NEXT: smov x9, v0.s[1] +; CHECK-GI-NEXT: sshll v0.4s, v1.4h, #0 +; CHECK-GI-NEXT: fmov d1, x8 +; CHECK-GI-NEXT: smov x8, v0.s[0] +; CHECK-GI-NEXT: mov v1.d[1], x9 +; CHECK-GI-NEXT: smov x9, v0.s[1] +; CHECK-GI-NEXT: fmov d2, x8 +; CHECK-GI-NEXT: scvtf v0.2d, v1.2d +; CHECK-GI-NEXT: mov v2.d[1], x9 +; CHECK-GI-NEXT: mov d1, v0.d[1] +; CHECK-GI-NEXT: scvtf v2.2d, v2.2d +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-GI-NEXT: // kill: def $d2 killed $d2 killed $q2 +; CHECK-GI-NEXT: ret entry: %c = sitofp <3 x i8> %a to <3 x double> ret <3 x double> %c } define <3 x double> @utofp_v3i8_v3f64(<3 x i8> %a) { -; CHECK-LABEL: utofp_v3i8_v3f64: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: fmov s0, w0 -; CHECK-NEXT: movi d1, #0x0000ff000000ff -; CHECK-NEXT: fmov s2, w2 -; CHECK-NEXT: mov v0.s[1], w1 -; CHECK-NEXT: and v0.8b, v0.8b, v1.8b -; CHECK-NEXT: and v1.8b, v2.8b, v1.8b -; CHECK-NEXT: ushll v0.2d, v0.2s, #0 -; CHECK-NEXT: ushll v1.2d, v1.2s, #0 -; CHECK-NEXT: ucvtf v0.2d, v0.2d -; CHECK-NEXT: ucvtf v2.2d, v1.2d -; CHECK-NEXT: // kill: def $d2 killed $d2 killed $q2 -; CHECK-NEXT: ext v1.16b, v0.16b, v0.16b, #8 -; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 -; CHECK-NEXT: // kill: def $d1 killed $d1 killed $q1 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: utofp_v3i8_v3f64: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: fmov s0, w0 +; CHECK-SD-NEXT: movi d1, #0x0000ff000000ff +; CHECK-SD-NEXT: fmov s2, w2 +; CHECK-SD-NEXT: mov v0.s[1], w1 +; CHECK-SD-NEXT: and v0.8b, v0.8b, v1.8b +; CHECK-SD-NEXT: and v1.8b, v2.8b, v1.8b +; CHECK-SD-NEXT: ushll v0.2d, v0.2s, #0 +; CHECK-SD-NEXT: ushll v1.2d, v1.2s, #0 +; CHECK-SD-NEXT: ucvtf v0.2d, v0.2d +; CHECK-SD-NEXT: ucvtf v2.2d, v1.2d +; CHECK-SD-NEXT: // kill: def $d2 killed $d2 killed $q2 +; CHECK-SD-NEXT: ext v1.16b, v0.16b, v0.16b, #8 +; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-SD-NEXT: // kill: def $d1 killed $d1 killed $q1 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: utofp_v3i8_v3f64: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: fmov s0, w0 +; CHECK-GI-NEXT: fmov s1, w1 +; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NEXT: fmov s1, w2 +; CHECK-GI-NEXT: mov v0.h[2], v1.h[0] +; CHECK-GI-NEXT: movi d1, #0xff00ff00ff00ff +; CHECK-GI-NEXT: and v0.8b, v0.8b, v1.8b +; CHECK-GI-NEXT: mov h2, v0.h[1] +; CHECK-GI-NEXT: mov s1, v0.s[1] +; CHECK-GI-NEXT: mov v0.h[1], v2.h[0] +; CHECK-GI-NEXT: mov h2, v1.h[1] +; CHECK-GI-NEXT: ushll v0.4s, v0.4h, #0 +; CHECK-GI-NEXT: mov v1.h[1], v2.h[0] +; CHECK-GI-NEXT: mov w8, v0.s[0] +; CHECK-GI-NEXT: mov w9, v0.s[1] +; CHECK-GI-NEXT: ushll v0.4s, v1.4h, #0 +; CHECK-GI-NEXT: fmov d1, x8 +; CHECK-GI-NEXT: mov w8, v0.s[0] +; CHECK-GI-NEXT: mov v1.d[1], x9 +; CHECK-GI-NEXT: mov w9, v0.s[1] +; CHECK-GI-NEXT: fmov d2, x8 +; CHECK-GI-NEXT: ucvtf v0.2d, v1.2d +; CHECK-GI-NEXT: mov v2.d[1], x9 +; CHECK-GI-NEXT: mov d1, v0.d[1] +; CHECK-GI-NEXT: ucvtf v2.2d, v2.2d +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-GI-NEXT: // kill: def $d2 killed $d2 killed $q2 +; CHECK-GI-NEXT: ret entry: %c = uitofp <3 x i8> %a to <3 x double> ret <3 x double> %c @@ -3372,31 +3427,71 @@ entry: } define <3 x float> @stofp_v3i8_v3f32(<3 x i8> %a) { -; CHECK-LABEL: stofp_v3i8_v3f32: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: fmov s0, w0 -; CHECK-NEXT: mov v0.h[1], w1 -; CHECK-NEXT: mov v0.h[2], w2 -; CHECK-NEXT: shl v0.4h, v0.4h, #8 -; CHECK-NEXT: sshr v0.4h, v0.4h, #8 -; CHECK-NEXT: sshll v0.4s, v0.4h, #0 -; CHECK-NEXT: scvtf v0.4s, v0.4s -; CHECK-NEXT: ret +; CHECK-SD-LABEL: stofp_v3i8_v3f32: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: fmov s0, w0 +; CHECK-SD-NEXT: mov v0.h[1], w1 +; CHECK-SD-NEXT: mov v0.h[2], w2 +; CHECK-SD-NEXT: shl v0.4h, v0.4h, #8 +; CHECK-SD-NEXT: sshr v0.4h, v0.4h, #8 +; CHECK-SD-NEXT: sshll v0.4s, v0.4h, #0 +; CHECK-SD-NEXT: scvtf v0.4s, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: stofp_v3i8_v3f32: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: fmov s0, w0 +; CHECK-GI-NEXT: fmov s1, w1 +; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NEXT: fmov s1, w2 +; CHECK-GI-NEXT: mov v0.h[2], v1.h[0] +; CHECK-GI-NEXT: shl v0.4h, v0.4h, #8 +; CHECK-GI-NEXT: sshr v0.4h, v0.4h, #8 +; CHECK-GI-NEXT: mov s1, v0.s[1] +; CHECK-GI-NEXT: mov h2, v0.h[1] +; CHECK-GI-NEXT: mov h3, v1.h[1] +; CHECK-GI-NEXT: mov v0.h[1], v2.h[0] +; CHECK-GI-NEXT: mov v1.h[1], v3.h[0] +; CHECK-GI-NEXT: sshll v0.4s, v0.4h, #0 +; CHECK-GI-NEXT: sshll v1.4s, v1.4h, #0 +; CHECK-GI-NEXT: mov v0.d[1], v1.d[0] +; CHECK-GI-NEXT: scvtf v0.4s, v0.4s +; CHECK-GI-NEXT: ret entry: %c = sitofp <3 x i8> %a to <3 x float> ret <3 x float> %c } define <3 x float> @utofp_v3i8_v3f32(<3 x i8> %a) { -; CHECK-LABEL: utofp_v3i8_v3f32: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: fmov s0, w0 -; CHECK-NEXT: mov v0.h[1], w1 -; CHECK-NEXT: mov v0.h[2], w2 -; CHECK-NEXT: bic v0.4h, #255, lsl #8 -; CHECK-NEXT: ushll v0.4s, v0.4h, #0 -; CHECK-NEXT: ucvtf v0.4s, v0.4s -; CHECK-NEXT: ret +; CHECK-SD-LABEL: utofp_v3i8_v3f32: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: fmov s0, w0 +; CHECK-SD-NEXT: mov v0.h[1], w1 +; CHECK-SD-NEXT: mov v0.h[2], w2 +; CHECK-SD-NEXT: bic v0.4h, #255, lsl #8 +; CHECK-SD-NEXT: ushll v0.4s, v0.4h, #0 +; CHECK-SD-NEXT: ucvtf v0.4s, v0.4s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: utofp_v3i8_v3f32: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: fmov s0, w0 +; CHECK-GI-NEXT: fmov s1, w1 +; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NEXT: fmov s1, w2 +; CHECK-GI-NEXT: mov v0.h[2], v1.h[0] +; CHECK-GI-NEXT: movi d1, #0xff00ff00ff00ff +; CHECK-GI-NEXT: and v0.8b, v0.8b, v1.8b +; CHECK-GI-NEXT: mov s1, v0.s[1] +; CHECK-GI-NEXT: mov h2, v0.h[1] +; CHECK-GI-NEXT: mov h3, v1.h[1] +; CHECK-GI-NEXT: mov v0.h[1], v2.h[0] +; CHECK-GI-NEXT: mov v1.h[1], v3.h[0] +; CHECK-GI-NEXT: ushll v0.4s, v0.4h, #0 +; CHECK-GI-NEXT: ushll v1.4s, v1.4h, #0 +; CHECK-GI-NEXT: mov v0.d[1], v1.d[0] +; CHECK-GI-NEXT: ucvtf v0.4s, v0.4s +; CHECK-GI-NEXT: ret entry: %c = uitofp <3 x i8> %a to <3 x float> ret <3 x float> %c @@ -5521,7 +5616,8 @@ define <2 x half> @stofp_v2i8_v2f16(<2 x i8> %a) { ; CHECK-GI-FP16: // %bb.0: // %entry ; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 ; CHECK-GI-FP16-NEXT: mov s1, v0.s[1] -; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-FP16-NEXT: mov v0.s[1], v1.s[0] +; CHECK-GI-FP16-NEXT: xtn v0.4h, v0.4s ; CHECK-GI-FP16-NEXT: shl v0.4h, v0.4h, #8 ; CHECK-GI-FP16-NEXT: sshr v0.4h, v0.4h, #8 ; CHECK-GI-FP16-NEXT: mov h1, v0.h[1] @@ -5580,7 +5676,14 @@ define <2 x half> @utofp_v2i8_v2f16(<2 x i8> %a) { ; ; CHECK-GI-FP16-LABEL: utofp_v2i8_v2f16: ; CHECK-GI-FP16: // %bb.0: // %entry +; CHECK-GI-FP16-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-FP16-NEXT: mov s1, v0.s[1] +; CHECK-GI-FP16-NEXT: mov v0.s[1], v1.s[0] +; CHECK-GI-FP16-NEXT: xtn v0.4h, v0.4s +; CHECK-GI-FP16-NEXT: mov h1, v0.h[1] +; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] ; CHECK-GI-FP16-NEXT: movi d1, #0x0000ff000000ff +; CHECK-GI-FP16-NEXT: ushll v0.4s, v0.4h, #0 ; CHECK-GI-FP16-NEXT: and v0.8b, v0.8b, v1.8b ; CHECK-GI-FP16-NEXT: mov s1, v0.s[1] ; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] @@ -5620,11 +5723,20 @@ define <3 x half> @stofp_v3i8_v3f16(<3 x i8> %a) { ; CHECK-GI-NOFP16-LABEL: stofp_v3i8_v3f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry ; CHECK-GI-NOFP16-NEXT: fmov s0, w0 -; CHECK-GI-NOFP16-NEXT: mov v0.h[1], w1 -; CHECK-GI-NOFP16-NEXT: mov v0.h[2], w2 +; CHECK-GI-NOFP16-NEXT: fmov s1, w1 +; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NOFP16-NEXT: fmov s1, w2 +; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v1.h[0] ; CHECK-GI-NOFP16-NEXT: shl v0.4h, v0.4h, #8 ; CHECK-GI-NOFP16-NEXT: sshr v0.4h, v0.4h, #8 +; CHECK-GI-NOFP16-NEXT: mov s1, v0.s[1] +; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[1] +; CHECK-GI-NOFP16-NEXT: mov h3, v1.h[1] +; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v2.h[0] +; CHECK-GI-NOFP16-NEXT: mov v1.h[1], v3.h[0] ; CHECK-GI-NOFP16-NEXT: sshll v0.4s, v0.4h, #0 +; CHECK-GI-NOFP16-NEXT: sshll v1.4s, v1.4h, #0 +; CHECK-GI-NOFP16-NEXT: mov v0.d[1], v1.d[0] ; CHECK-GI-NOFP16-NEXT: scvtf v0.4s, v0.4s ; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v0.4s ; CHECK-GI-NOFP16-NEXT: ret @@ -5633,11 +5745,10 @@ define <3 x half> @stofp_v3i8_v3f16(<3 x i8> %a) { ; CHECK-GI-FP16: // %bb.0: // %entry ; CHECK-GI-FP16-NEXT: fmov s0, w0 ; CHECK-GI-FP16-NEXT: fmov s1, w1 -; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-FP16-NEXT: mov v0.b[1], v1.b[0] ; CHECK-GI-FP16-NEXT: fmov s1, w2 -; CHECK-GI-FP16-NEXT: mov v0.h[2], v1.h[0] -; CHECK-GI-FP16-NEXT: shl v0.4h, v0.4h, #8 -; CHECK-GI-FP16-NEXT: sshr v0.4h, v0.4h, #8 +; CHECK-GI-FP16-NEXT: mov v0.b[2], v1.b[0] +; CHECK-GI-FP16-NEXT: sshll v0.8h, v0.8b, #0 ; CHECK-GI-FP16-NEXT: scvtf v0.4h, v0.4h ; CHECK-GI-FP16-NEXT: ret entry: @@ -5669,10 +5780,20 @@ define <3 x half> @utofp_v3i8_v3f16(<3 x i8> %a) { ; CHECK-GI-NOFP16-LABEL: utofp_v3i8_v3f16: ; CHECK-GI-NOFP16: // %bb.0: // %entry ; CHECK-GI-NOFP16-NEXT: fmov s0, w0 -; CHECK-GI-NOFP16-NEXT: mov v0.h[1], w1 -; CHECK-GI-NOFP16-NEXT: mov v0.h[2], w2 -; CHECK-GI-NOFP16-NEXT: bic v0.4h, #255, lsl #8 +; CHECK-GI-NOFP16-NEXT: fmov s1, w1 +; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NOFP16-NEXT: fmov s1, w2 +; CHECK-GI-NOFP16-NEXT: mov v0.h[2], v1.h[0] +; CHECK-GI-NOFP16-NEXT: movi d1, #0xff00ff00ff00ff +; CHECK-GI-NOFP16-NEXT: and v0.8b, v0.8b, v1.8b +; CHECK-GI-NOFP16-NEXT: mov s1, v0.s[1] +; CHECK-GI-NOFP16-NEXT: mov h2, v0.h[1] +; CHECK-GI-NOFP16-NEXT: mov h3, v1.h[1] +; CHECK-GI-NOFP16-NEXT: mov v0.h[1], v2.h[0] +; CHECK-GI-NOFP16-NEXT: mov v1.h[1], v3.h[0] ; CHECK-GI-NOFP16-NEXT: ushll v0.4s, v0.4h, #0 +; CHECK-GI-NOFP16-NEXT: ushll v1.4s, v1.4h, #0 +; CHECK-GI-NOFP16-NEXT: mov v0.d[1], v1.d[0] ; CHECK-GI-NOFP16-NEXT: ucvtf v0.4s, v0.4s ; CHECK-GI-NOFP16-NEXT: fcvtn v0.4h, v0.4s ; CHECK-GI-NOFP16-NEXT: ret @@ -5681,11 +5802,10 @@ define <3 x half> @utofp_v3i8_v3f16(<3 x i8> %a) { ; CHECK-GI-FP16: // %bb.0: // %entry ; CHECK-GI-FP16-NEXT: fmov s0, w0 ; CHECK-GI-FP16-NEXT: fmov s1, w1 -; CHECK-GI-FP16-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-FP16-NEXT: mov v0.b[1], v1.b[0] ; CHECK-GI-FP16-NEXT: fmov s1, w2 -; CHECK-GI-FP16-NEXT: mov v0.h[2], v1.h[0] -; CHECK-GI-FP16-NEXT: movi d1, #0xff00ff00ff00ff -; CHECK-GI-FP16-NEXT: and v0.8b, v0.8b, v1.8b +; CHECK-GI-FP16-NEXT: mov v0.b[2], v1.b[0] +; CHECK-GI-FP16-NEXT: ushll v0.8h, v0.8b, #0 ; CHECK-GI-FP16-NEXT: ucvtf v0.4h, v0.4h ; CHECK-GI-FP16-NEXT: ret entry: diff --git a/llvm/test/CodeGen/AArch64/llvm.exp10.ll b/llvm/test/CodeGen/AArch64/llvm.exp10.ll index 56f4272c4363c8cbf8fce4c4dfb46e51bcf19422..51d17ad0644f1504ba58987ebb796e120a26412f 100644 --- a/llvm/test/CodeGen/AArch64/llvm.exp10.ll +++ b/llvm/test/CodeGen/AArch64/llvm.exp10.ll @@ -532,11 +532,18 @@ define double @exp10_f64(double %x) { ret double %r } -; FIXME: Broken -; define <1 x double> @exp10_v1f64(<1 x double> %x) { -; %r = call <1 x double> @llvm.exp10.v1f64(<1 x double> %x) -; ret <1 x double> %r -; } +define <1 x double> @exp10_v1f64(<1 x double> %x) { +; CHECK-LABEL: exp10_v1f64: +; CHECK: // %bb.0: +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset w30, -16 +; CHECK-NEXT: bl exp10 +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: ret + %r = call <1 x double> @llvm.exp10.v1f64(<1 x double> %x) + ret <1 x double> %r +} define <2 x double> @exp10_v2f64(<2 x double> %x) { ; SDAG-LABEL: exp10_v2f64: diff --git a/llvm/test/CodeGen/AArch64/load.ll b/llvm/test/CodeGen/AArch64/load.ll index 39143e5c53ffd172a16aa6da7192c0eb22d09708..c3c0ec5e3d9d8dbac3fb1d615637910ffab82d4e 100644 --- a/llvm/test/CodeGen/AArch64/load.ll +++ b/llvm/test/CodeGen/AArch64/load.ll @@ -159,7 +159,8 @@ define <2 x i16> @load_v2i16(ptr %ptr){ ; CHECK-GI: // %bb.0: ; CHECK-GI-NEXT: ldr h0, [x0] ; CHECK-GI-NEXT: ldr h1, [x0, #2] -; CHECK-GI-NEXT: mov v0.s[1], v1.s[0] +; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NEXT: ushll v0.4s, v0.4h, #0 ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret %a = load <2 x i16>, ptr %ptr diff --git a/llvm/test/CodeGen/AArch64/machine-cp-sub-reg.mir b/llvm/test/CodeGen/AArch64/machine-cp-sub-reg.mir index 23cf1dcda839e3072af578a617e5823cb3fbff2d..5b379c2bd562929cb06956b25af33ddea8e1a91f 100644 --- a/llvm/test/CodeGen/AArch64/machine-cp-sub-reg.mir +++ b/llvm/test/CodeGen/AArch64/machine-cp-sub-reg.mir @@ -10,7 +10,6 @@ body: | ; CHECK-NEXT: successors: %bb.1(0x80000000) ; CHECK-NEXT: liveins: $w0 ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: $x8 = ORRXrs $xzr, $x0, 0, implicit $w0 ; CHECK-NEXT: $w8 = ORRWrs $wzr, $w0, 0, implicit-def $x8 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.1: diff --git a/llvm/test/CodeGen/AArch64/misched-bundle.mir b/llvm/test/CodeGen/AArch64/misched-bundle.mir new file mode 100644 index 0000000000000000000000000000000000000000..a947c04a4229e60912c63f4b2fdbeb81cc819857 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/misched-bundle.mir @@ -0,0 +1,195 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4 +# RUN: llc -mtriple=aarch64-none-linux-gnu -mcpu=cortex-a510 -run-pass=machine-scheduler -debug-only=machine-scheduler %s -o - 2>&1 | FileCheck %s +# REQUIRES: asserts + +# CHECK: SU(0): renamable $z0 = LD1H renamable $p0, renamable $x1, renamable $x10 :: (load unknown-size, align 1) +# CHECK-NEXT: # preds left : 0 +# CHECK-NEXT: # succs left : 4 +# CHECK-NEXT: # rdefs left : 0 +# CHECK-NEXT: Latency : 3 +# CHECK-NEXT: Depth : 0 +# CHECK-NEXT: Height : 7 +# CHECK-NEXT: Successors: +# CHECK-NEXT: SU(6): Out Latency=1 +# CHECK-NEXT: SU(6): Data Latency=3 Reg=$z0 +# CHECK-NEXT: SU(9): Ord Latency=0 Memory +# CHECK-NEXT: SU(8): Ord Latency=0 Memory +# CHECK-NEXT: Single Issue : false; +# CHECK-NEXT: SU(1): renamable $z1 = LD1H renamable $p0, renamable $x2, renamable $x10 :: (load unknown-size, align 1) +# CHECK-NEXT: # preds left : 0 +# CHECK-NEXT: # succs left : 4 +# CHECK-NEXT: # rdefs left : 0 +# CHECK-NEXT: Latency : 3 +# CHECK-NEXT: Depth : 0 +# CHECK-NEXT: Height : 7 +# CHECK-NEXT: Successors: +# CHECK-NEXT: SU(7): Out Latency=1 +# CHECK-NEXT: SU(6): Data Latency=3 Reg=$z1 +# CHECK-NEXT: SU(9): Ord Latency=0 Memory +# CHECK-NEXT: SU(8): Ord Latency=0 Memory +# CHECK-NEXT: Single Issue : false; +# CHECK-NEXT: SU(2): renamable $z2 = LD1H renamable $p0, renamable $x0, renamable $x10 :: (load unknown-size, align 1) +# CHECK-NEXT: # preds left : 0 +# CHECK-NEXT: # succs left : 3 +# CHECK-NEXT: # rdefs left : 0 +# CHECK-NEXT: Latency : 3 +# CHECK-NEXT: Depth : 0 +# CHECK-NEXT: Height : 7 +# CHECK-NEXT: Successors: +# CHECK-NEXT: SU(6): Data Latency=3 Reg=$z2 +# CHECK-NEXT: SU(9): Ord Latency=0 Memory +# CHECK-NEXT: SU(8): Ord Latency=0 Memory +# CHECK-NEXT: Single Issue : false; +# CHECK-NEXT: SU(3): renamable $z3 = LD1H renamable $p0, renamable $x11, renamable $x10 :: (load unknown-size, align 1) +# CHECK-NEXT: # preds left : 0 +# CHECK-NEXT: # succs left : 3 +# CHECK-NEXT: # rdefs left : 0 +# CHECK-NEXT: Latency : 3 +# CHECK-NEXT: Depth : 0 +# CHECK-NEXT: Height : 0 +# CHECK-NEXT: Successors: +# CHECK-NEXT: SU(7): Data Latency=0 Reg=$z3 +# CHECK-NEXT: SU(9): Ord Latency=0 Memory +# CHECK-NEXT: SU(8): Ord Latency=0 Memory +# CHECK-NEXT: Single Issue : false; +# CHECK-NEXT: SU(4): renamable $z4 = LD1H renamable $p0, renamable $x12, renamable $x10 :: (load unknown-size, align 1) +# CHECK-NEXT: # preds left : 0 +# CHECK-NEXT: # succs left : 3 +# CHECK-NEXT: # rdefs left : 0 +# CHECK-NEXT: Latency : 3 +# CHECK-NEXT: Depth : 0 +# CHECK-NEXT: Height : 0 +# CHECK-NEXT: Successors: +# CHECK-NEXT: SU(7): Data Latency=0 Reg=$z4 +# CHECK-NEXT: SU(9): Ord Latency=0 Memory +# CHECK-NEXT: SU(8): Ord Latency=0 Memory +# CHECK-NEXT: Single Issue : false; +# CHECK-NEXT: SU(5): renamable $z5 = LD1H renamable $p0, renamable $x13, renamable $x10 :: (load unknown-size, align 1) +# CHECK-NEXT: # preds left : 0 +# CHECK-NEXT: # succs left : 3 +# CHECK-NEXT: # rdefs left : 0 +# CHECK-NEXT: Latency : 3 +# CHECK-NEXT: Depth : 0 +# CHECK-NEXT: Height : 0 +# CHECK-NEXT: Successors: +# CHECK-NEXT: SU(7): Data Latency=0 Reg=$z5 +# CHECK-NEXT: SU(9): Ord Latency=0 Memory +# CHECK-NEXT: SU(8): Ord Latency=0 Memory +# CHECK-NEXT: Single Issue : false; +# CHECK-NEXT: SU(6): $z0 = FMAD_ZPmZZ_H renamable $p0, killed $z0(tied-def 0), killed renamable $z1, killed renamable $z2 +# CHECK-NEXT: # preds left : 4 +# CHECK-NEXT: # succs left : 2 +# CHECK-NEXT: # rdefs left : 0 +# CHECK-NEXT: Latency : 4 +# CHECK-NEXT: Depth : 3 +# CHECK-NEXT: Height : 4 +# CHECK-NEXT: Predecessors: +# CHECK-NEXT: SU(2): Data Latency=3 Reg=$z2 +# CHECK-NEXT: SU(1): Data Latency=3 Reg=$z1 +# CHECK-NEXT: SU(0): Out Latency=1 +# CHECK-NEXT: SU(0): Data Latency=3 Reg=$z0 +# CHECK-NEXT: Successors: +# CHECK-NEXT: SU(8): Data Latency=4 Reg=$z0 +# CHECK-NEXT: SU(7): Anti Latency=0 +# CHECK-NEXT: Single Issue : false; +# CHECK-NEXT: SU(7): BUNDLE implicit-def $z1, implicit-def $q1, implicit-def $d1, implicit-def $s1, implicit-def $h1, implicit-def $b1, implicit $z5, implicit $p0, implicit killed $z4, implicit killed $z3 +# CHECK-NEXT: # preds left : 5 +# CHECK-NEXT: # succs left : 1 +# CHECK-NEXT: # rdefs left : 0 +# CHECK-NEXT: Latency : 1 +# CHECK-NEXT: Depth : 3 +# CHECK-NEXT: Height : 0 +# CHECK-NEXT: Predecessors: +# CHECK-NEXT: SU(6): Anti Latency=0 +# CHECK-NEXT: SU(5): Data Latency=0 Reg=$z5 +# CHECK-NEXT: SU(4): Data Latency=0 Reg=$z4 +# CHECK-NEXT: SU(3): Data Latency=0 Reg=$z3 +# CHECK-NEXT: SU(1): Out Latency=1 +# CHECK-NEXT: Successors: +# CHECK-NEXT: SU(9): Data Latency=0 Reg=$z1 +# CHECK-NEXT: Single Issue : false; +# CHECK-NEXT: SU(8): ST1H killed renamable $z0, renamable $p0, renamable $x0, renamable $x10 :: (store unknown-size, align 1) +# CHECK-NEXT: # preds left : 7 +# CHECK-NEXT: # succs left : 1 +# CHECK-NEXT: # rdefs left : 0 +# CHECK-NEXT: Latency : 1 +# CHECK-NEXT: Depth : 7 +# CHECK-NEXT: Height : 0 +# CHECK-NEXT: Predecessors: +# CHECK-NEXT: SU(6): Data Latency=4 Reg=$z0 +# CHECK-NEXT: SU(5): Ord Latency=0 Memory +# CHECK-NEXT: SU(4): Ord Latency=0 Memory +# CHECK-NEXT: SU(3): Ord Latency=0 Memory +# CHECK-NEXT: SU(2): Ord Latency=0 Memory +# CHECK-NEXT: SU(1): Ord Latency=0 Memory +# CHECK-NEXT: SU(0): Ord Latency=0 Memory +# CHECK-NEXT: Successors: +# CHECK-NEXT: SU(9): Ord Latency=0 Memory +# CHECK-NEXT: Single Issue : false; +# CHECK-NEXT: SU(9): ST1H killed renamable $z1, renamable $p0, renamable $x13, renamable $x10 :: (store unknown-size, align 1) +# CHECK-NEXT: # preds left : 8 +# CHECK-NEXT: # succs left : 0 +# CHECK-NEXT: # rdefs left : 0 +# CHECK-NEXT: Latency : 1 +# CHECK-NEXT: Depth : 7 +# CHECK-NEXT: Height : 0 +# CHECK-NEXT: Predecessors: +# CHECK-NEXT: SU(8): Ord Latency=0 Memory +# CHECK-NEXT: SU(7): Data Latency=0 Reg=$z1 +# CHECK-NEXT: SU(5): Ord Latency=0 Memory +# CHECK-NEXT: SU(4): Ord Latency=0 Memory +# CHECK-NEXT: SU(3): Ord Latency=0 Memory +# CHECK-NEXT: SU(2): Ord Latency=0 Memory +# CHECK-NEXT: SU(1): Ord Latency=0 Memory +# CHECK-NEXT: SU(0): Ord Latency=0 Memory +# CHECK-NEXT: Single Issue : false; +# CHECK-NEXT: ExitSU: RET_ReallyLR +# CHECK-NEXT: # preds left : 0 +# CHECK-NEXT: # succs left : 0 +# CHECK-NEXT: # rdefs left : 0 +# CHECK-NEXT: Latency : 0 +# CHECK-NEXT: Depth : 0 +# CHECK-NEXT: Height : 0 + +--- +name: test +alignment: 4 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $p0, $x0, $x1, $x2, $x10, $x11, $x12, $x13 + + ; CHECK-LABEL: name: test + ; CHECK: liveins: $p0, $x0, $x1, $x2, $x10, $x11, $x12, $x13 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $z0 = LD1H renamable $p0, renamable $x1, renamable $x10 :: (load unknown-size, align 1) + ; CHECK-NEXT: renamable $z1 = LD1H renamable $p0, renamable $x2, renamable $x10 :: (load unknown-size, align 1) + ; CHECK-NEXT: renamable $z2 = LD1H renamable $p0, renamable $x0, renamable $x10 :: (load unknown-size, align 1) + ; CHECK-NEXT: $z0 = FMAD_ZPmZZ_H renamable $p0, killed $z0, renamable $z1, killed renamable $z2 + ; CHECK-NEXT: renamable $z3 = LD1H renamable $p0, renamable $x11, renamable $x10 :: (load unknown-size, align 1) + ; CHECK-NEXT: renamable $z4 = LD1H renamable $p0, renamable $x12, renamable $x10 :: (load unknown-size, align 1) + ; CHECK-NEXT: renamable $z5 = LD1H renamable $p0, renamable $x13, renamable $x10 :: (load unknown-size, align 1) + ; CHECK-NEXT: ST1H killed renamable $z0, renamable $p0, renamable $x0, renamable $x10 :: (store unknown-size, align 1) + ; CHECK-NEXT: BUNDLE implicit-def $z1, implicit-def $q1, implicit-def $d1, implicit-def $s1, implicit-def $h1, implicit-def $b1, implicit $z5, implicit $p0, implicit $z4, implicit $z3 { + ; CHECK-NEXT: $z1 = MOVPRFX_ZZ $z5 + ; CHECK-NEXT: $z1 = FMLA_ZPmZZ_H renamable $p0, internal $z1, renamable $z4, renamable $z3 + ; CHECK-NEXT: } + ; CHECK-NEXT: ST1H renamable $z1, renamable $p0, renamable $x13, renamable $x10 :: (store unknown-size, align 1) + ; CHECK-NEXT: RET_ReallyLR + + renamable $z0 = LD1H renamable $p0, renamable $x1, renamable $x10 :: (load unknown-size) + renamable $z1 = LD1H renamable $p0, renamable $x2, renamable $x10 :: (load unknown-size) + renamable $z2 = LD1H renamable $p0, renamable $x0, renamable $x10 :: (load unknown-size) + renamable $z3 = LD1H renamable $p0, renamable $x11, renamable $x10 :: (load unknown-size) + renamable $z4 = LD1H renamable $p0, renamable $x12, renamable $x10 :: (load unknown-size) + renamable $z5 = LD1H renamable $p0, renamable $x13, renamable $x10 :: (load unknown-size) + $z0 = FMAD_ZPmZZ_H renamable $p0, killed $z0, killed renamable $z1, killed renamable $z2 + BUNDLE implicit-def $z1, implicit-def $q1, implicit-def $d1, implicit-def $s1, implicit-def $h1, implicit-def $b1, implicit $z5, implicit $p0, implicit killed $z4, implicit killed $z3 { + $z1 = MOVPRFX_ZZ $z5 + $z1 = FMLA_ZPmZZ_H renamable $p0, internal killed $z1, killed renamable $z4, killed renamable $z3 + } + ST1H killed renamable $z0, renamable $p0, renamable $x0, renamable $x10 :: (store unknown-size) + ST1H killed renamable $z1, renamable $p0, renamable $x13, renamable $x10 :: (store unknown-size) + RET_ReallyLR + +... diff --git a/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll b/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll index 01620652301ed4b63f11b129195b949f1c6949dc..57f220f621cf8bb5cda1d2fad90946f4ca556669 100644 --- a/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll +++ b/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll @@ -1117,8 +1117,15 @@ define <4 x i16> @vselect_constant_cond_zero_v4i16(<4 x i16> %a) { ; ; CHECK-GI-LABEL: vselect_constant_cond_zero_v4i16: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: adrp x8, .LCPI84_0 -; CHECK-GI-NEXT: ldr d1, [x8, :lo12:.LCPI84_0] +; CHECK-GI-NEXT: mov w8, #1 // =0x1 +; CHECK-GI-NEXT: mov w9, #0 // =0x0 +; CHECK-GI-NEXT: fmov s1, w8 +; CHECK-GI-NEXT: fmov s2, w9 +; CHECK-GI-NEXT: mov v3.16b, v1.16b +; CHECK-GI-NEXT: mov v3.b[1], v2.b[0] +; CHECK-GI-NEXT: mov v3.b[2], v2.b[0] +; CHECK-GI-NEXT: mov v3.b[3], v1.b[0] +; CHECK-GI-NEXT: ushll v1.8h, v3.8b, #0 ; CHECK-GI-NEXT: shl v1.4h, v1.4h, #15 ; CHECK-GI-NEXT: sshr v1.4h, v1.4h, #15 ; CHECK-GI-NEXT: and v0.8b, v0.8b, v1.8b @@ -1137,8 +1144,16 @@ define <4 x i32> @vselect_constant_cond_zero_v4i32(<4 x i32> %a) { ; ; CHECK-GI-LABEL: vselect_constant_cond_zero_v4i32: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: adrp x8, .LCPI85_0 -; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI85_0] +; CHECK-GI-NEXT: mov w8, #1 // =0x1 +; CHECK-GI-NEXT: mov w9, #0 // =0x0 +; CHECK-GI-NEXT: fmov s1, w8 +; CHECK-GI-NEXT: fmov s2, w9 +; CHECK-GI-NEXT: mov v3.16b, v1.16b +; CHECK-GI-NEXT: mov v3.h[1], v2.h[0] +; CHECK-GI-NEXT: mov v2.h[1], v1.h[0] +; CHECK-GI-NEXT: ushll v1.4s, v3.4h, #0 +; CHECK-GI-NEXT: ushll v2.4s, v2.4h, #0 +; CHECK-GI-NEXT: mov v1.d[1], v2.d[0] ; CHECK-GI-NEXT: shl v1.4s, v1.4s, #31 ; CHECK-GI-NEXT: sshr v1.4s, v1.4s, #31 ; CHECK-GI-NEXT: and v0.16b, v0.16b, v1.16b @@ -1181,8 +1196,15 @@ define <4 x i16> @vselect_constant_cond_v4i16(<4 x i16> %a, <4 x i16> %b) { ; ; CHECK-GI-LABEL: vselect_constant_cond_v4i16: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: adrp x8, .LCPI87_0 -; CHECK-GI-NEXT: ldr d2, [x8, :lo12:.LCPI87_0] +; CHECK-GI-NEXT: mov w8, #1 // =0x1 +; CHECK-GI-NEXT: mov w9, #0 // =0x0 +; CHECK-GI-NEXT: fmov s2, w8 +; CHECK-GI-NEXT: fmov s3, w9 +; CHECK-GI-NEXT: mov v4.16b, v2.16b +; CHECK-GI-NEXT: mov v4.b[1], v3.b[0] +; CHECK-GI-NEXT: mov v4.b[2], v3.b[0] +; CHECK-GI-NEXT: mov v4.b[3], v2.b[0] +; CHECK-GI-NEXT: ushll v2.8h, v4.8b, #0 ; CHECK-GI-NEXT: shl v2.4h, v2.4h, #15 ; CHECK-GI-NEXT: sshr v2.4h, v2.4h, #15 ; CHECK-GI-NEXT: bif v0.8b, v1.8b, v2.8b @@ -1201,8 +1223,16 @@ define <4 x i32> @vselect_constant_cond_v4i32(<4 x i32> %a, <4 x i32> %b) { ; ; CHECK-GI-LABEL: vselect_constant_cond_v4i32: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: adrp x8, .LCPI88_0 -; CHECK-GI-NEXT: ldr q2, [x8, :lo12:.LCPI88_0] +; CHECK-GI-NEXT: mov w8, #1 // =0x1 +; CHECK-GI-NEXT: mov w9, #0 // =0x0 +; CHECK-GI-NEXT: fmov s2, w8 +; CHECK-GI-NEXT: fmov s3, w9 +; CHECK-GI-NEXT: mov v4.16b, v2.16b +; CHECK-GI-NEXT: mov v4.h[1], v3.h[0] +; CHECK-GI-NEXT: mov v3.h[1], v2.h[0] +; CHECK-GI-NEXT: ushll v2.4s, v4.4h, #0 +; CHECK-GI-NEXT: ushll v3.4s, v3.4h, #0 +; CHECK-GI-NEXT: mov v2.d[1], v3.d[0] ; CHECK-GI-NEXT: shl v2.4s, v2.4s, #31 ; CHECK-GI-NEXT: sshr v2.4s, v2.4s, #31 ; CHECK-GI-NEXT: bif v0.16b, v1.16b, v2.16b diff --git a/llvm/test/CodeGen/AArch64/neon-compare-instructions.ll b/llvm/test/CodeGen/AArch64/neon-compare-instructions.ll index 632b6b326250223497603fa1f51f9efa594932a9..dbb5dfebd44abca4f1fc87759d1d4883e77c5108 100644 --- a/llvm/test/CodeGen/AArch64/neon-compare-instructions.ll +++ b/llvm/test/CodeGen/AArch64/neon-compare-instructions.ll @@ -2870,6 +2870,107 @@ define <2 x i64> @fcmune2xdouble(<2 x double> %A, <2 x double> %B) { ret <2 x i64> %tmp4 } +define <2 x i32> @fcmal2xfloat(<2 x float> %A, <2 x float> %B) { +; CHECK-SD-LABEL: fcmal2xfloat: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: movi v0.2d, #0xffffffffffffffff +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: fcmal2xfloat: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: movi v0.2s, #1 +; CHECK-GI-NEXT: shl v0.2s, v0.2s, #31 +; CHECK-GI-NEXT: sshr v0.2s, v0.2s, #31 +; CHECK-GI-NEXT: ret + %tmp3 = fcmp true <2 x float> %A, %B + %tmp4 = sext <2 x i1> %tmp3 to <2 x i32> + ret <2 x i32> %tmp4 +} + +define <4 x i32> @fcmal4xfloat(<4 x float> %A, <4 x float> %B) { +; CHECK-SD-LABEL: fcmal4xfloat: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: movi v0.2d, #0xffffffffffffffff +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: fcmal4xfloat: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: mov w8, #1 // =0x1 +; CHECK-GI-NEXT: fmov s0, w8 +; CHECK-GI-NEXT: mov v1.16b, v0.16b +; CHECK-GI-NEXT: mov v1.h[1], v0.h[0] +; CHECK-GI-NEXT: mov v0.h[1], v0.h[0] +; CHECK-GI-NEXT: ushll v1.4s, v1.4h, #0 +; CHECK-GI-NEXT: ushll v0.4s, v0.4h, #0 +; CHECK-GI-NEXT: mov v1.d[1], v0.d[0] +; CHECK-GI-NEXT: shl v0.4s, v1.4s, #31 +; CHECK-GI-NEXT: sshr v0.4s, v0.4s, #31 +; CHECK-GI-NEXT: ret + %tmp3 = fcmp true <4 x float> %A, %B + %tmp4 = sext <4 x i1> %tmp3 to <4 x i32> + ret <4 x i32> %tmp4 +} +define <2 x i64> @fcmal2xdouble(<2 x double> %A, <2 x double> %B) { +; CHECK-SD-LABEL: fcmal2xdouble: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: movi v0.2d, #0xffffffffffffffff +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: fcmal2xdouble: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: adrp x8, .LCPI221_0 +; CHECK-GI-NEXT: ldr q0, [x8, :lo12:.LCPI221_0] +; CHECK-GI-NEXT: shl v0.2d, v0.2d, #63 +; CHECK-GI-NEXT: sshr v0.2d, v0.2d, #63 +; CHECK-GI-NEXT: ret + %tmp3 = fcmp true <2 x double> %A, %B + %tmp4 = sext <2 x i1> %tmp3 to <2 x i64> + ret <2 x i64> %tmp4 +} + +define <2 x i32> @fcmnv2xfloat(<2 x float> %A, <2 x float> %B) { +; CHECK-LABEL: fcmnv2xfloat: +; CHECK: // %bb.0: +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: ret + %tmp3 = fcmp false <2 x float> %A, %B + %tmp4 = sext <2 x i1> %tmp3 to <2 x i32> + ret <2 x i32> %tmp4 +} + +define <4 x i32> @fcmnv4xfloat(<4 x float> %A, <4 x float> %B) { +; CHECK-SD-LABEL: fcmnv4xfloat: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: movi v0.2d, #0000000000000000 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: fcmnv4xfloat: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: mov w8, #0 // =0x0 +; CHECK-GI-NEXT: fmov s0, w8 +; CHECK-GI-NEXT: mov v1.16b, v0.16b +; CHECK-GI-NEXT: mov v1.h[1], v0.h[0] +; CHECK-GI-NEXT: mov v0.h[1], v0.h[0] +; CHECK-GI-NEXT: ushll v1.4s, v1.4h, #0 +; CHECK-GI-NEXT: ushll v0.4s, v0.4h, #0 +; CHECK-GI-NEXT: mov v1.d[1], v0.d[0] +; CHECK-GI-NEXT: shl v0.4s, v1.4s, #31 +; CHECK-GI-NEXT: sshr v0.4s, v0.4s, #31 +; CHECK-GI-NEXT: ret + %tmp3 = fcmp false <4 x float> %A, %B + %tmp4 = sext <4 x i1> %tmp3 to <4 x i32> + ret <4 x i32> %tmp4 +} +define <2 x i64> @fcmnv2xdouble(<2 x double> %A, <2 x double> %B) { +; CHECK-LABEL: fcmnv2xdouble: +; CHECK: // %bb.0: +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: ret + %tmp3 = fcmp false <2 x double> %A, %B + %tmp4 = sext <2 x i1> %tmp3 to <2 x i64> + ret <2 x i64> %tmp4 +} + define <2 x i32> @fcmoeqz2xfloat(<2 x float> %A) { ; CHECK-LABEL: fcmoeqz2xfloat: ; CHECK: // %bb.0: diff --git a/llvm/test/CodeGen/AArch64/neon-truncstore.ll b/llvm/test/CodeGen/AArch64/neon-truncstore.ll index b677d077b98c14814e611431910a7770c8b9c818..5d78ad24eb333dff76c41ae782c990ca2b40e10e 100644 --- a/llvm/test/CodeGen/AArch64/neon-truncstore.ll +++ b/llvm/test/CodeGen/AArch64/neon-truncstore.ll @@ -104,7 +104,7 @@ define void @v4i32_v4i8(<4 x i32> %a, ptr %result) { ; CHECK-LABEL: v4i32_v4i8: ; CHECK: // %bb.0: ; CHECK-NEXT: xtn v0.4h, v0.4s -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [x0] ; CHECK-NEXT: ret %b = trunc <4 x i32> %a to <4 x i8> @@ -170,8 +170,7 @@ define void @v2i16_v2i8(<2 x i16> %a, ptr %result) { define void @v4i16_v4i8(<4 x i16> %a, ptr %result) { ; CHECK-LABEL: v4i16_v4i8: ; CHECK: // %bb.0: -; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [x0] ; CHECK-NEXT: ret %b = trunc <4 x i16> %a to <4 x i8> diff --git a/llvm/test/CodeGen/AArch64/overflow.ll b/llvm/test/CodeGen/AArch64/overflow.ll index 444aaeb0f3fe75e588c73dbf22890ce28d6b057d..977141f2b84f4fdaf5bf1f4ccd8efc0f909e7d64 100644 --- a/llvm/test/CodeGen/AArch64/overflow.ll +++ b/llvm/test/CodeGen/AArch64/overflow.ll @@ -19,20 +19,12 @@ entry: } define zeroext i1 @saddo1.i32.fold(i32 %v1, i32 %v2, ptr %res) { -; SDAG-LABEL: saddo1.i32.fold: -; SDAG: // %bb.0: // %entry -; SDAG-NEXT: mov w8, #20 // =0x14 -; SDAG-NEXT: mov w0, wzr -; SDAG-NEXT: str w8, [x2] -; SDAG-NEXT: ret -; -; GISEL-LABEL: saddo1.i32.fold: -; GISEL: // %bb.0: // %entry -; GISEL-NEXT: mov w8, #9 // =0x9 -; GISEL-NEXT: adds w8, w8, #11 -; GISEL-NEXT: cset w0, vs -; GISEL-NEXT: str w8, [x2] -; GISEL-NEXT: ret +; CHECK-LABEL: saddo1.i32.fold: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov w8, #20 // =0x14 +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: str w8, [x2] +; CHECK-NEXT: ret entry: %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 9, i32 11) %val = extractvalue {i32, i1} %t, 0 @@ -72,21 +64,10 @@ entry: } define i32 @saddo.select.i64(i32 %v1, i32 %v2, i1 %v3, i64 %v4, i64 %v5) { -; SDAG-LABEL: saddo.select.i64: -; SDAG: // %bb.0: // %entry -; SDAG-NEXT: mov w0, w1 -; SDAG-NEXT: ret -; -; GISEL-LABEL: saddo.select.i64: -; GISEL: // %bb.0: // %entry -; GISEL-NEXT: mov w8, #13 // =0xd -; GISEL-NEXT: and x9, x3, #0xc -; GISEL-NEXT: and x8, x4, x8 -; GISEL-NEXT: cmn x9, x8 -; GISEL-NEXT: cset w8, vs -; GISEL-NEXT: tst w8, #0x1 -; GISEL-NEXT: csel w0, w0, w1, ne -; GISEL-NEXT: ret +; CHECK-LABEL: saddo.select.i64: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov w0, w1 +; CHECK-NEXT: ret entry: %lhs = and i64 %v4, 12 %rhs = and i64 %v5, 13 @@ -97,22 +78,10 @@ entry: } define i32 @uaddo.select.i64(i32 %v1, i32 %v2, i1 %v3, i64 %v4, i64 %v5) { -; SDAG-LABEL: uaddo.select.i64: -; SDAG: // %bb.0: // %entry -; SDAG-NEXT: mov w0, w1 -; SDAG-NEXT: ret -; -; GISEL-LABEL: uaddo.select.i64: -; GISEL: // %bb.0: // %entry -; GISEL-NEXT: mov w8, #9 // =0x9 -; GISEL-NEXT: mov w9, #10 // =0xa -; GISEL-NEXT: and x8, x3, x8 -; GISEL-NEXT: and x9, x4, x9 -; GISEL-NEXT: cmn x8, x9 -; GISEL-NEXT: cset w8, hs -; GISEL-NEXT: tst w8, #0x1 -; GISEL-NEXT: csel w0, w0, w1, ne -; GISEL-NEXT: ret +; CHECK-LABEL: uaddo.select.i64: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov w0, w1 +; CHECK-NEXT: ret entry: %lhs = and i64 %v4, 9 %rhs = and i64 %v5, 10 @@ -123,18 +92,11 @@ entry: } define zeroext i1 @saddo.canon.i32(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) { -; SDAG-LABEL: saddo.canon.i32: -; SDAG: // %bb.0: // %entry -; SDAG-NEXT: mov w0, wzr -; SDAG-NEXT: str w4, [x5] -; SDAG-NEXT: ret -; -; GISEL-LABEL: saddo.canon.i32: -; GISEL: // %bb.0: // %entry -; GISEL-NEXT: adds w8, wzr, w4 -; GISEL-NEXT: cset w0, vs -; GISEL-NEXT: str w8, [x5] -; GISEL-NEXT: ret +; CHECK-LABEL: saddo.canon.i32: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: str w4, [x5] +; CHECK-NEXT: ret entry: %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 0, i32 %v5) %val = extractvalue {i32, i1} %t, 0 @@ -143,13 +105,19 @@ entry: ret i1 %obit } define zeroext i1 @saddo.add.i32(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) { -; CHECK-LABEL: saddo.add.i32: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: add w8, w4, #100 -; CHECK-NEXT: subs w8, w8, #100 -; CHECK-NEXT: cset w0, vs -; CHECK-NEXT: str w8, [x5] -; CHECK-NEXT: ret +; SDAG-LABEL: saddo.add.i32: +; SDAG: // %bb.0: // %entry +; SDAG-NEXT: add w8, w4, #100 +; SDAG-NEXT: subs w8, w8, #100 +; SDAG-NEXT: cset w0, vs +; SDAG-NEXT: str w8, [x5] +; SDAG-NEXT: ret +; +; GISEL-LABEL: saddo.add.i32: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: mov w0, wzr +; GISEL-NEXT: str w4, [x5] +; GISEL-NEXT: ret entry: %lhs = add nsw i32 %v5, 100 %t = call {i32, i1} @llvm.sadd.with.overflow.i32(i32 %lhs, i32 -100) @@ -160,13 +128,20 @@ entry: } define zeroext i1 @uaddo.add.i32(i32 %v1, i32 %v2, i32 %v3, i32 %v4, i32 %v5, ptr %res) { -; CHECK-LABEL: uaddo.add.i32: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: add w8, w4, #5 -; CHECK-NEXT: adds w8, w8, #5 -; CHECK-NEXT: cset w0, hs -; CHECK-NEXT: str w8, [x5] -; CHECK-NEXT: ret +; SDAG-LABEL: uaddo.add.i32: +; SDAG: // %bb.0: // %entry +; SDAG-NEXT: add w8, w4, #5 +; SDAG-NEXT: adds w8, w8, #5 +; SDAG-NEXT: cset w0, hs +; SDAG-NEXT: str w8, [x5] +; SDAG-NEXT: ret +; +; GISEL-LABEL: uaddo.add.i32: +; GISEL: // %bb.0: // %entry +; GISEL-NEXT: adds w8, w4, #10 +; GISEL-NEXT: cset w0, hs +; GISEL-NEXT: str w8, [x5] +; GISEL-NEXT: ret entry: %lhs = add nuw i32 %v5, 5 %t = call {i32, i1} @llvm.uadd.with.overflow.i32(i32 %lhs, i32 5) diff --git a/llvm/test/CodeGen/AArch64/peephole-movd.mir b/llvm/test/CodeGen/AArch64/peephole-movd.mir new file mode 100644 index 0000000000000000000000000000000000000000..bd7f0ab3f044e7e7d79f5dd06ba5784daf994ddb --- /dev/null +++ b/llvm/test/CodeGen/AArch64/peephole-movd.mir @@ -0,0 +1,60 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -run-pass=aarch64-mi-peephole-opt -o - -mtriple=aarch64-unknown-linux -verify-machineinstrs %s | FileCheck %s + +--- +name: remove_kill_flags +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $w0 + ; CHECK-LABEL: name: remove_kill_flags + ; CHECK: liveins: $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[MOVIv2d_ns:%[0-9]+]]:fpr128 = MOVIv2d_ns 0 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY [[MOVIv2d_ns]].dsub + ; CHECK-NEXT: [[UQSHLv8i8_shift:%[0-9]+]]:fpr64 = UQSHLv8i8_shift killed [[COPY]], 1 + ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:fpr128 = SUBREG_TO_REG 0, [[UQSHLv8i8_shift]], %subreg.dsub + ; CHECK-NEXT: [[TBLv8i8One:%[0-9]+]]:fpr64 = TBLv8i8One killed [[SUBREG_TO_REG]], [[UQSHLv8i8_shift]] + ; CHECK-NEXT: [[DEF:%[0-9]+]]:fpr128 = IMPLICIT_DEF + ; CHECK-NEXT: [[INSERT_SUBREG:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF]], [[UQSHLv8i8_shift]], %subreg.dsub + ; CHECK-NEXT: RET_ReallyLR implicit $w0 + %0:fpr128 = MOVIv2d_ns 0 + %1:fpr64 = COPY %0.dsub:fpr128 + %2:fpr64 = UQSHLv8i8_shift killed %1:fpr64, 1 + %3:fpr64 = FMOVDr %2:fpr64 + %4:fpr128 = SUBREG_TO_REG 0, killed %3:fpr64, %subreg.dsub + %5:fpr64 = TBLv8i8One killed %4:fpr128, %2:fpr64 + %7:fpr128 = IMPLICIT_DEF + %6:fpr128 = INSERT_SUBREG %7:fpr128, killed %2:fpr64, %subreg.dsub + RET_ReallyLR implicit $w0 +... +--- +name: remove_kill_flags2 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $w0 + ; CHECK-LABEL: name: remove_kill_flags2 + ; CHECK: liveins: $w0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[MOVIv2d_ns:%[0-9]+]]:fpr128 = MOVIv2d_ns 0 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY [[MOVIv2d_ns]].dsub + ; CHECK-NEXT: [[UQSHLv8i8_shift:%[0-9]+]]:fpr64 = UQSHLv8i8_shift killed [[COPY]], 1 + ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:fpr128 = SUBREG_TO_REG 0, [[UQSHLv8i8_shift]], %subreg.dsub + ; CHECK-NEXT: [[DEF:%[0-9]+]]:fpr128 = IMPLICIT_DEF + ; CHECK-NEXT: [[INSERT_SUBREG:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF]], [[UQSHLv8i8_shift]], %subreg.dsub + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:fpr128 = IMPLICIT_DEF + ; CHECK-NEXT: [[INSERT_SUBREG1:%[0-9]+]]:fpr128 = INSERT_SUBREG [[DEF1]], [[UQSHLv8i8_shift]], %subreg.dsub + ; CHECK-NEXT: RET_ReallyLR implicit $w0 + %0:fpr128 = MOVIv2d_ns 0 + %1:fpr64 = COPY %0.dsub:fpr128 + %2:fpr64 = UQSHLv8i8_shift killed %1:fpr64, 1 + %3:fpr64 = FMOVDr %2:fpr64 + %4:fpr128 = SUBREG_TO_REG 0, %3:fpr64, %subreg.dsub + %7:fpr128 = IMPLICIT_DEF + %6:fpr128 = INSERT_SUBREG %7:fpr128, killed %2:fpr64, %subreg.dsub + %9:fpr128 = IMPLICIT_DEF + %8:fpr128 = INSERT_SUBREG %9:fpr128, killed %3:fpr64, %subreg.dsub + RET_ReallyLR implicit $w0 +... + diff --git a/llvm/test/CodeGen/AArch64/pr86717.ll b/llvm/test/CodeGen/AArch64/pr86717.ll new file mode 100644 index 0000000000000000000000000000000000000000..aa8be954be72d0cedb97667383df0aa790bcee02 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/pr86717.ll @@ -0,0 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=aarch64 | FileCheck %s + +define <16 x i8> @f(i32 %0) { +; CHECK-LABEL: f: +; CHECK: // %bb.0: +; CHECK-NEXT: sub sp, sp, #16 +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: movi v0.2d, #0000000000000000 +; CHECK-NEXT: mov w8, #1 // =0x1 +; CHECK-NEXT: mov x9, sp +; CHECK-NEXT: sub w8, w8, w0 +; CHECK-NEXT: bfxil x9, x8, #0, #4 +; CHECK-NEXT: mov w8, #3 // =0x3 +; CHECK-NEXT: str q0, [sp] +; CHECK-NEXT: strb w8, [x9] +; CHECK-NEXT: ldr q0, [sp], #16 +; CHECK-NEXT: ret + %2 = sub nuw i32 1, %0 + %3 = insertelement <16 x i8> zeroinitializer, i8 3, i32 %2 + ret <16 x i8> %3 +} diff --git a/llvm/test/CodeGen/AArch64/ragreedy-local-interval-cost.ll b/llvm/test/CodeGen/AArch64/ragreedy-local-interval-cost.ll index 932b230726a3a7bc8d314157f3ee158a93be7308..934ff44900c046c8984bc9077f5437853538ab65 100644 --- a/llvm/test/CodeGen/AArch64/ragreedy-local-interval-cost.ll +++ b/llvm/test/CodeGen/AArch64/ragreedy-local-interval-cost.ll @@ -147,10 +147,10 @@ define dso_local void @run_test() local_unnamed_addr uwtable { ; CHECK-NEXT: mov v19.16b, v23.16b ; CHECK-NEXT: mov v3.d[1], x20 ; CHECK-NEXT: mov v23.16b, v27.16b -; CHECK-NEXT: mov v27.16b, v9.16b -; CHECK-NEXT: mul x15, x4, x5 ; CHECK-NEXT: add v27.2d, v9.2d, v1.2d +; CHECK-NEXT: mul x15, x4, x5 ; CHECK-NEXT: str q11, [sp, #80] // 16-byte Folded Spill +; CHECK-NEXT: mov v11.16b, v15.16b ; CHECK-NEXT: mov v4.d[1], x22 ; CHECK-NEXT: add v19.2d, v19.2d, v1.2d ; CHECK-NEXT: add v7.2d, v7.2d, v1.2d @@ -171,9 +171,7 @@ define dso_local void @run_test() local_unnamed_addr uwtable { ; CHECK-NEXT: mov v10.16b, v26.16b ; CHECK-NEXT: mov v14.d[1], x13 ; CHECK-NEXT: mov v22.16b, v31.16b -; CHECK-NEXT: mov v20.16b, v8.16b ; CHECK-NEXT: ldp q26, q31, [sp] // 32-byte Folded Reload -; CHECK-NEXT: mov v11.16b, v15.16b ; CHECK-NEXT: mov v0.d[1], x12 ; CHECK-NEXT: add v13.2d, v13.2d, v14.2d ; CHECK-NEXT: add v31.2d, v31.2d, v14.2d diff --git a/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll b/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll index 5f905d94e3573c7e310c3286a11ecb28fcd5c211..6f1ae023bf25a16c6c995cf5770cc0642e74bdc0 100644 --- a/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll +++ b/llvm/test/CodeGen/AArch64/sadd_sat_vec.ll @@ -145,7 +145,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind { ; CHECK-NEXT: shl v0.4h, v0.4h, #8 ; CHECK-NEXT: sqadd v0.4h, v0.4h, v1.4h ; CHECK-NEXT: sshr v0.4h, v0.4h, #8 -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [x2] ; CHECK-NEXT: ret %x = load <4 x i8>, ptr %px diff --git a/llvm/test/CodeGen/AArch64/setcc_knownbits.ll b/llvm/test/CodeGen/AArch64/setcc_knownbits.ll index bb9546af8bb7b69b10992cd5b6a35ad8a71f9ebd..8be63b04d8ce588d24b9d31bf309d14462383ebb 100644 --- a/llvm/test/CodeGen/AArch64/setcc_knownbits.ll +++ b/llvm/test/CodeGen/AArch64/setcc_knownbits.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 -; RUN: llc < %s -mtriple=aarch64 | FileCheck %s +; RUN: llc < %s -mtriple=aarch64 | FileCheck %s --check-prefixes=CHECK,CHECK-SD +; RUN: llc < %s -mtriple=aarch64 -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI define i1 @load_bv_v4i8(i1 zeroext %a) { ; CHECK-LABEL: load_bv_v4i8: @@ -11,18 +12,31 @@ define i1 @load_bv_v4i8(i1 zeroext %a) { } define noundef i1 @logger(i32 noundef %logLevel, ptr %ea, ptr %pll) { -; CHECK-LABEL: logger: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: ldr w8, [x2] -; CHECK-NEXT: cmp w8, w0 -; CHECK-NEXT: b.ls .LBB1_2 -; CHECK-NEXT: // %bb.1: -; CHECK-NEXT: mov w0, wzr -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB1_2: // %land.rhs -; CHECK-NEXT: ldr x8, [x1] -; CHECK-NEXT: ldrb w0, [x8] -; CHECK-NEXT: ret +; CHECK-SD-LABEL: logger: +; CHECK-SD: // %bb.0: // %entry +; CHECK-SD-NEXT: ldr w8, [x2] +; CHECK-SD-NEXT: cmp w8, w0 +; CHECK-SD-NEXT: b.ls .LBB1_2 +; CHECK-SD-NEXT: // %bb.1: +; CHECK-SD-NEXT: mov w0, wzr +; CHECK-SD-NEXT: ret +; CHECK-SD-NEXT: .LBB1_2: // %land.rhs +; CHECK-SD-NEXT: ldr x8, [x1] +; CHECK-SD-NEXT: ldrb w0, [x8] +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: logger: +; CHECK-GI: // %bb.0: // %entry +; CHECK-GI-NEXT: ldr w8, [x2] +; CHECK-GI-NEXT: cmp w8, w0 +; CHECK-GI-NEXT: mov w0, wzr +; CHECK-GI-NEXT: b.hi .LBB1_2 +; CHECK-GI-NEXT: // %bb.1: // %land.rhs +; CHECK-GI-NEXT: ldr x8, [x1] +; CHECK-GI-NEXT: ldrb w8, [x8] +; CHECK-GI-NEXT: and w0, w8, #0x1 +; CHECK-GI-NEXT: .LBB1_2: // %land.end +; CHECK-GI-NEXT: ret entry: %0 = load i32, ptr %pll, align 4 %cmp.not = icmp ugt i32 %0, %logLevel @@ -44,12 +58,18 @@ land.end: ; preds = %land.rhs, %entry declare i64 @llvm.ctlz.i64(i64 %in, i1) define i1 @lshr_ctlz_undef_cmpeq_one_i64(i64 %in) { -; CHECK-LABEL: lshr_ctlz_undef_cmpeq_one_i64: -; CHECK: // %bb.0: -; CHECK-NEXT: clz x8, x0 -; CHECK-NEXT: lsr x0, x8, #6 -; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0 -; CHECK-NEXT: ret +; CHECK-SD-LABEL: lshr_ctlz_undef_cmpeq_one_i64: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: clz x8, x0 +; CHECK-SD-NEXT: lsr x0, x8, #6 +; CHECK-SD-NEXT: // kill: def $w0 killed $w0 killed $x0 +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: lshr_ctlz_undef_cmpeq_one_i64: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: clz x8, x0 +; CHECK-GI-NEXT: lsr w0, w8, #6 +; CHECK-GI-NEXT: ret %ctlz = call i64 @llvm.ctlz.i64(i64 %in, i1 -1) %lshr = lshr i64 %ctlz, 6 %icmp = icmp eq i64 %lshr, 1 @@ -57,17 +77,30 @@ define i1 @lshr_ctlz_undef_cmpeq_one_i64(i64 %in) { } define i32 @PR17487(i1 %tobool) { -; CHECK-LABEL: PR17487: -; CHECK: // %bb.0: -; CHECK-NEXT: dup v0.2s, w0 -; CHECK-NEXT: mov w8, #1 // =0x1 -; CHECK-NEXT: dup v1.2d, x8 -; CHECK-NEXT: ushll v0.2d, v0.2s, #0 -; CHECK-NEXT: bic v0.16b, v1.16b, v0.16b -; CHECK-NEXT: mov x8, v0.d[1] -; CHECK-NEXT: cmp x8, #1 -; CHECK-NEXT: cset w0, ne -; CHECK-NEXT: ret +; CHECK-SD-LABEL: PR17487: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: dup v0.2s, w0 +; CHECK-SD-NEXT: mov w8, #1 // =0x1 +; CHECK-SD-NEXT: dup v1.2d, x8 +; CHECK-SD-NEXT: ushll v0.2d, v0.2s, #0 +; CHECK-SD-NEXT: bic v0.16b, v1.16b, v0.16b +; CHECK-SD-NEXT: mov x8, v0.d[1] +; CHECK-SD-NEXT: cmp x8, #1 +; CHECK-SD-NEXT: cset w0, ne +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: PR17487: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: // kill: def $w0 killed $w0 def $x0 +; CHECK-GI-NEXT: mov v0.d[1], x0 +; CHECK-GI-NEXT: adrp x8, .LCPI3_0 +; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI3_0] +; CHECK-GI-NEXT: bic v0.16b, v1.16b, v0.16b +; CHECK-GI-NEXT: mov d0, v0.d[1] +; CHECK-GI-NEXT: fmov x8, d0 +; CHECK-GI-NEXT: cmp x8, #1 +; CHECK-GI-NEXT: cset w0, ne +; CHECK-GI-NEXT: ret %tmp = insertelement <2 x i1> undef, i1 %tobool, i32 1 %tmp1 = zext <2 x i1> %tmp to <2 x i64> %tmp2 = xor <2 x i64> %tmp1, <i64 1, i64 1> diff --git a/llvm/test/CodeGen/AArch64/sext.ll b/llvm/test/CodeGen/AArch64/sext.ll index 61f04fbf0484f70048ca38017374a40e87137b04..3e0d5dd875097f83e3ced8ac7a36341ae6c838d7 100644 --- a/llvm/test/CodeGen/AArch64/sext.ll +++ b/llvm/test/CodeGen/AArch64/sext.ll @@ -280,13 +280,12 @@ define <3 x i64> @sext_v3i8_v3i64(<3 x i8> %a) { ; ; CHECK-GI-LABEL: sext_v3i8_v3i64: ; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: // kill: def $w0 killed $w0 def $x0 -; CHECK-GI-NEXT: fmov d0, x0 -; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1 +; CHECK-GI-NEXT: fmov s0, w0 ; CHECK-GI-NEXT: // kill: def $w2 killed $w2 def $x2 ; CHECK-GI-NEXT: sxtb x8, w2 ; CHECK-GI-NEXT: fmov d2, x8 -; CHECK-GI-NEXT: mov v0.d[1], x1 +; CHECK-GI-NEXT: mov v0.s[1], w1 +; CHECK-GI-NEXT: ushll v0.2d, v0.2s, #0 ; CHECK-GI-NEXT: shl v0.2d, v0.2d, #56 ; CHECK-GI-NEXT: sshr v0.2d, v0.2d, #56 ; CHECK-GI-NEXT: mov d1, v0.d[1] @@ -444,13 +443,12 @@ define <3 x i64> @sext_v3i10_v3i64(<3 x i10> %a) { ; ; CHECK-GI-LABEL: sext_v3i10_v3i64: ; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: // kill: def $w0 killed $w0 def $x0 -; CHECK-GI-NEXT: fmov d0, x0 -; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1 +; CHECK-GI-NEXT: fmov s0, w0 ; CHECK-GI-NEXT: // kill: def $w2 killed $w2 def $x2 ; CHECK-GI-NEXT: sbfx x8, x2, #0, #10 ; CHECK-GI-NEXT: fmov d2, x8 -; CHECK-GI-NEXT: mov v0.d[1], x1 +; CHECK-GI-NEXT: mov v0.s[1], w1 +; CHECK-GI-NEXT: ushll v0.2d, v0.2s, #0 ; CHECK-GI-NEXT: shl v0.2d, v0.2d, #54 ; CHECK-GI-NEXT: sshr v0.2d, v0.2d, #54 ; CHECK-GI-NEXT: mov d1, v0.d[1] diff --git a/llvm/test/CodeGen/AArch64/shift.ll b/llvm/test/CodeGen/AArch64/shift.ll index 5287839ee7b7053ef9d2eb6e53c0efd62da7e9e2..9c8d3e0f07de877ba2d54791cab0231cc60bedde 100644 --- a/llvm/test/CodeGen/AArch64/shift.ll +++ b/llvm/test/CodeGen/AArch64/shift.ll @@ -1,13 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 ; RUN: llc -mtriple=aarch64 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-SD -; RUN: llc -mtriple=aarch64 -global-isel -global-isel-abort=2 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI - -; CHECK-GI: warning: Instruction selection used fallback path for shl_v4i8 -; CHECK-GI-NEXT: warning: Instruction selection used fallback path for shl_v2i16 -; CHECK-GI-NEXT: warning: Instruction selection used fallback path for ashr_v4i8 -; CHECK-GI-NEXT: warning: Instruction selection used fallback path for ashr_v2i16 -; CHECK-GI-NEXT: warning: Instruction selection used fallback path for lshr_v4i8 -; CHECK-GI-NEXT: warning: Instruction selection used fallback path for lshr_v2i16 +; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI define i1 @shl_i1(i1 %0, i1 %1){ ; CHECK-SD-LABEL: shl_i1: @@ -530,11 +523,38 @@ define <2 x i64> @lshr_v2i64(<2 x i64> %0, <2 x i64> %1){ ; ===== Vector Larger/Smaller than Legal ===== define <4 x i8> @shl_v4i8(<4 x i8> %0, <4 x i8> %1){ -; CHECK-LABEL: shl_v4i8: -; CHECK: // %bb.0: -; CHECK-NEXT: bic v1.4h, #255, lsl #8 -; CHECK-NEXT: ushl v0.4h, v0.4h, v1.4h -; CHECK-NEXT: ret +; CHECK-SD-LABEL: shl_v4i8: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: bic v1.4h, #255, lsl #8 +; CHECK-SD-NEXT: ushl v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: shl_v4i8: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-GI-NEXT: mov h2, v0.h[1] +; CHECK-GI-NEXT: mov h3, v1.h[1] +; CHECK-GI-NEXT: mov h4, v0.h[2] +; CHECK-GI-NEXT: mov h5, v0.h[3] +; CHECK-GI-NEXT: mov h6, v1.h[3] +; CHECK-GI-NEXT: mov v0.b[1], v2.b[0] +; CHECK-GI-NEXT: mov h2, v1.h[2] +; CHECK-GI-NEXT: mov v1.b[1], v3.b[0] +; CHECK-GI-NEXT: mov v0.b[2], v4.b[0] +; CHECK-GI-NEXT: mov v1.b[2], v2.b[0] +; CHECK-GI-NEXT: mov v0.b[3], v5.b[0] +; CHECK-GI-NEXT: mov v1.b[3], v6.b[0] +; CHECK-GI-NEXT: ushl v0.8b, v0.8b, v1.8b +; CHECK-GI-NEXT: mov b1, v0.b[1] +; CHECK-GI-NEXT: mov b2, v0.b[2] +; CHECK-GI-NEXT: mov b3, v0.b[3] +; CHECK-GI-NEXT: mov v0.b[1], v1.b[0] +; CHECK-GI-NEXT: mov v0.b[2], v2.b[0] +; CHECK-GI-NEXT: mov v0.b[3], v3.b[0] +; CHECK-GI-NEXT: ushll v0.8h, v0.8b, #0 +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-GI-NEXT: ret %3 = shl <4 x i8> %0, %1 ret <4 x i8> %3 } @@ -556,12 +576,27 @@ define <32 x i8> @shl_v32i8(<32 x i8> %0, <32 x i8> %1){ } define <2 x i16> @shl_v2i16(<2 x i16> %0, <2 x i16> %1){ -; CHECK-LABEL: shl_v2i16: -; CHECK: // %bb.0: -; CHECK-NEXT: movi d2, #0x00ffff0000ffff -; CHECK-NEXT: and v1.8b, v1.8b, v2.8b -; CHECK-NEXT: ushl v0.2s, v0.2s, v1.2s -; CHECK-NEXT: ret +; CHECK-SD-LABEL: shl_v2i16: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: movi d2, #0x00ffff0000ffff +; CHECK-SD-NEXT: and v1.8b, v1.8b, v2.8b +; CHECK-SD-NEXT: ushl v0.2s, v0.2s, v1.2s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: shl_v2i16: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-GI-NEXT: mov s2, v0.s[1] +; CHECK-GI-NEXT: mov s3, v1.s[1] +; CHECK-GI-NEXT: mov v0.h[1], v2.h[0] +; CHECK-GI-NEXT: mov v1.h[1], v3.h[0] +; CHECK-GI-NEXT: ushl v0.4h, v0.4h, v1.4h +; CHECK-GI-NEXT: mov h1, v0.h[1] +; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NEXT: ushll v0.4s, v0.4h, #0 +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-GI-NEXT: ret %3 = shl <2 x i16> %0, %1 ret <2 x i16> %3 } @@ -633,14 +668,42 @@ define <4 x i64> @shl_v4i64(<4 x i64> %0, <4 x i64> %1){ } define <4 x i8> @ashr_v4i8(<4 x i8> %0, <4 x i8> %1){ -; CHECK-LABEL: ashr_v4i8: -; CHECK: // %bb.0: -; CHECK-NEXT: shl v0.4h, v0.4h, #8 -; CHECK-NEXT: bic v1.4h, #255, lsl #8 -; CHECK-NEXT: sshr v0.4h, v0.4h, #8 -; CHECK-NEXT: neg v1.4h, v1.4h -; CHECK-NEXT: sshl v0.4h, v0.4h, v1.4h -; CHECK-NEXT: ret +; CHECK-SD-LABEL: ashr_v4i8: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: shl v0.4h, v0.4h, #8 +; CHECK-SD-NEXT: bic v1.4h, #255, lsl #8 +; CHECK-SD-NEXT: sshr v0.4h, v0.4h, #8 +; CHECK-SD-NEXT: neg v1.4h, v1.4h +; CHECK-SD-NEXT: sshl v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: ashr_v4i8: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-GI-NEXT: mov h2, v1.h[1] +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-NEXT: mov h3, v0.h[1] +; CHECK-GI-NEXT: mov h4, v1.h[2] +; CHECK-GI-NEXT: mov h5, v1.h[3] +; CHECK-GI-NEXT: mov h6, v0.h[3] +; CHECK-GI-NEXT: mov v1.b[1], v2.b[0] +; CHECK-GI-NEXT: mov h2, v0.h[2] +; CHECK-GI-NEXT: mov v0.b[1], v3.b[0] +; CHECK-GI-NEXT: mov v1.b[2], v4.b[0] +; CHECK-GI-NEXT: mov v0.b[2], v2.b[0] +; CHECK-GI-NEXT: mov v1.b[3], v5.b[0] +; CHECK-GI-NEXT: mov v0.b[3], v6.b[0] +; CHECK-GI-NEXT: neg v1.8b, v1.8b +; CHECK-GI-NEXT: sshl v0.8b, v0.8b, v1.8b +; CHECK-GI-NEXT: mov b1, v0.b[1] +; CHECK-GI-NEXT: mov b2, v0.b[2] +; CHECK-GI-NEXT: mov b3, v0.b[3] +; CHECK-GI-NEXT: mov v0.b[1], v1.b[0] +; CHECK-GI-NEXT: mov v0.b[2], v2.b[0] +; CHECK-GI-NEXT: mov v0.b[3], v3.b[0] +; CHECK-GI-NEXT: ushll v0.8h, v0.8b, #0 +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-GI-NEXT: ret %3 = ashr <4 x i8> %0, %1 ret <4 x i8> %3 } @@ -658,15 +721,31 @@ define <32 x i8> @ashr_v32i8(<32 x i8> %0, <32 x i8> %1){ } define <2 x i16> @ashr_v2i16(<2 x i16> %0, <2 x i16> %1){ -; CHECK-LABEL: ashr_v2i16: -; CHECK: // %bb.0: -; CHECK-NEXT: movi d2, #0x00ffff0000ffff -; CHECK-NEXT: shl v0.2s, v0.2s, #16 -; CHECK-NEXT: sshr v0.2s, v0.2s, #16 -; CHECK-NEXT: and v1.8b, v1.8b, v2.8b -; CHECK-NEXT: neg v1.2s, v1.2s -; CHECK-NEXT: sshl v0.2s, v0.2s, v1.2s -; CHECK-NEXT: ret +; CHECK-SD-LABEL: ashr_v2i16: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: movi d2, #0x00ffff0000ffff +; CHECK-SD-NEXT: shl v0.2s, v0.2s, #16 +; CHECK-SD-NEXT: sshr v0.2s, v0.2s, #16 +; CHECK-SD-NEXT: and v1.8b, v1.8b, v2.8b +; CHECK-SD-NEXT: neg v1.2s, v1.2s +; CHECK-SD-NEXT: sshl v0.2s, v0.2s, v1.2s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: ashr_v2i16: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-GI-NEXT: mov s2, v1.s[1] +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-NEXT: mov s3, v0.s[1] +; CHECK-GI-NEXT: mov v1.h[1], v2.h[0] +; CHECK-GI-NEXT: mov v0.h[1], v3.h[0] +; CHECK-GI-NEXT: neg v1.4h, v1.4h +; CHECK-GI-NEXT: sshl v0.4h, v0.4h, v1.4h +; CHECK-GI-NEXT: mov h1, v0.h[1] +; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NEXT: ushll v0.4s, v0.4h, #0 +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-GI-NEXT: ret %3 = ashr <2 x i16> %0, %1 ret <2 x i16> %3 } @@ -727,13 +806,41 @@ define <4 x i64> @ashr_v4i64(<4 x i64> %0, <4 x i64> %1){ } define <4 x i8> @lshr_v4i8(<4 x i8> %0, <4 x i8> %1){ -; CHECK-LABEL: lshr_v4i8: -; CHECK: // %bb.0: -; CHECK-NEXT: bic v1.4h, #255, lsl #8 -; CHECK-NEXT: bic v0.4h, #255, lsl #8 -; CHECK-NEXT: neg v1.4h, v1.4h -; CHECK-NEXT: ushl v0.4h, v0.4h, v1.4h -; CHECK-NEXT: ret +; CHECK-SD-LABEL: lshr_v4i8: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: bic v1.4h, #255, lsl #8 +; CHECK-SD-NEXT: bic v0.4h, #255, lsl #8 +; CHECK-SD-NEXT: neg v1.4h, v1.4h +; CHECK-SD-NEXT: ushl v0.4h, v0.4h, v1.4h +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: lshr_v4i8: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-GI-NEXT: mov h2, v1.h[1] +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-NEXT: mov h3, v0.h[1] +; CHECK-GI-NEXT: mov h4, v1.h[2] +; CHECK-GI-NEXT: mov h5, v1.h[3] +; CHECK-GI-NEXT: mov h6, v0.h[3] +; CHECK-GI-NEXT: mov v1.b[1], v2.b[0] +; CHECK-GI-NEXT: mov h2, v0.h[2] +; CHECK-GI-NEXT: mov v0.b[1], v3.b[0] +; CHECK-GI-NEXT: mov v1.b[2], v4.b[0] +; CHECK-GI-NEXT: mov v0.b[2], v2.b[0] +; CHECK-GI-NEXT: mov v1.b[3], v5.b[0] +; CHECK-GI-NEXT: mov v0.b[3], v6.b[0] +; CHECK-GI-NEXT: neg v1.8b, v1.8b +; CHECK-GI-NEXT: ushl v0.8b, v0.8b, v1.8b +; CHECK-GI-NEXT: mov b1, v0.b[1] +; CHECK-GI-NEXT: mov b2, v0.b[2] +; CHECK-GI-NEXT: mov b3, v0.b[3] +; CHECK-GI-NEXT: mov v0.b[1], v1.b[0] +; CHECK-GI-NEXT: mov v0.b[2], v2.b[0] +; CHECK-GI-NEXT: mov v0.b[3], v3.b[0] +; CHECK-GI-NEXT: ushll v0.8h, v0.8b, #0 +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-GI-NEXT: ret %3 = lshr <4 x i8> %0, %1 ret <4 x i8> %3 } @@ -751,14 +858,30 @@ define <32 x i8> @lshr_v32i8(<32 x i8> %0, <32 x i8> %1){ } define <2 x i16> @lshr_v2i16(<2 x i16> %0, <2 x i16> %1){ -; CHECK-LABEL: lshr_v2i16: -; CHECK: // %bb.0: -; CHECK-NEXT: movi d2, #0x00ffff0000ffff -; CHECK-NEXT: and v1.8b, v1.8b, v2.8b -; CHECK-NEXT: and v0.8b, v0.8b, v2.8b -; CHECK-NEXT: neg v1.2s, v1.2s -; CHECK-NEXT: ushl v0.2s, v0.2s, v1.2s -; CHECK-NEXT: ret +; CHECK-SD-LABEL: lshr_v2i16: +; CHECK-SD: // %bb.0: +; CHECK-SD-NEXT: movi d2, #0x00ffff0000ffff +; CHECK-SD-NEXT: and v1.8b, v1.8b, v2.8b +; CHECK-SD-NEXT: and v0.8b, v0.8b, v2.8b +; CHECK-SD-NEXT: neg v1.2s, v1.2s +; CHECK-SD-NEXT: ushl v0.2s, v0.2s, v1.2s +; CHECK-SD-NEXT: ret +; +; CHECK-GI-LABEL: lshr_v2i16: +; CHECK-GI: // %bb.0: +; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-GI-NEXT: mov s2, v1.s[1] +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0 +; CHECK-GI-NEXT: mov s3, v0.s[1] +; CHECK-GI-NEXT: mov v1.h[1], v2.h[0] +; CHECK-GI-NEXT: mov v0.h[1], v3.h[0] +; CHECK-GI-NEXT: neg v1.4h, v1.4h +; CHECK-GI-NEXT: ushl v0.4h, v0.4h, v1.4h +; CHECK-GI-NEXT: mov h1, v0.h[1] +; CHECK-GI-NEXT: mov v0.h[1], v1.h[0] +; CHECK-GI-NEXT: ushll v0.4s, v0.4h, #0 +; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 +; CHECK-GI-NEXT: ret %3 = lshr <2 x i16> %0, %1 ret <2 x i16> %3 } diff --git a/llvm/test/CodeGen/AArch64/shuffle-tbl34.ll b/llvm/test/CodeGen/AArch64/shuffle-tbl34.ll index 0ef64789ad9724be19c172e5687e0ab8615ae791..fb571eff39fe5098049106d5574de6161aec5e34 100644 --- a/llvm/test/CodeGen/AArch64/shuffle-tbl34.ll +++ b/llvm/test/CodeGen/AArch64/shuffle-tbl34.ll @@ -353,13 +353,17 @@ define <8 x i8> @shuffle4_v8i8_v8i8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c, <8 x define <8 x i16> @shuffle4_v4i8_zext(<4 x i8> %a, <4 x i8> %b, <4 x i8> %c, <4 x i8> %d) { ; CHECK-LABEL: shuffle4_v4i8_zext: ; CHECK: // %bb.0: -; CHECK-NEXT: uzp1 v0.8b, v0.8b, v1.8b -; CHECK-NEXT: uzp1 v1.8b, v2.8b, v3.8b +; CHECK-NEXT: fmov d5, d2 +; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 +; CHECK-NEXT: // kill: def $d3 killed $d3 def $q3 ; CHECK-NEXT: adrp x8, .LCPI8_0 -; CHECK-NEXT: ushll v2.8h, v0.8b, #0 +; CHECK-NEXT: fmov d4, d0 ; CHECK-NEXT: ldr q0, [x8, :lo12:.LCPI8_0] -; CHECK-NEXT: ushll v3.8h, v1.8b, #0 -; CHECK-NEXT: tbl v0.16b, { v2.16b, v3.16b }, v0.16b +; CHECK-NEXT: mov v4.d[1], v1.d[0] +; CHECK-NEXT: mov v5.d[1], v3.d[0] +; CHECK-NEXT: bic v4.8h, #255, lsl #8 +; CHECK-NEXT: bic v5.8h, #255, lsl #8 +; CHECK-NEXT: tbl v0.16b, { v4.16b, v5.16b }, v0.16b ; CHECK-NEXT: ret %x = shufflevector <4 x i8> %a, <4 x i8> %b, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> %y = shufflevector <4 x i8> %c, <4 x i8> %d, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> diff --git a/llvm/test/CodeGen/AArch64/shufflevector.ll b/llvm/test/CodeGen/AArch64/shufflevector.ll index d79f3ae11167f3952a777c8ae513456cf4f3de6c..b1131f287fe9a9ff1ee61524abe02106fef2f997 100644 --- a/llvm/test/CodeGen/AArch64/shufflevector.ll +++ b/llvm/test/CodeGen/AArch64/shufflevector.ll @@ -202,7 +202,7 @@ define i32 @shufflevector_v4i8(<4 x i8> %a, <4 x i8> %b){ ; CHECK-SD-NEXT: ext v0.8b, v1.8b, v0.8b, #6 ; CHECK-SD-NEXT: zip1 v1.4h, v1.4h, v0.4h ; CHECK-SD-NEXT: ext v0.8b, v0.8b, v1.8b, #4 -; CHECK-SD-NEXT: xtn v0.8b, v0.8h +; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-SD-NEXT: fmov w0, s0 ; CHECK-SD-NEXT: add sp, sp, #16 ; CHECK-SD-NEXT: ret @@ -390,7 +390,7 @@ define i32 @shufflevector_v4i8_zeroes(<4 x i8> %a, <4 x i8> %b){ ; CHECK-SD-NEXT: .cfi_def_cfa_offset 16 ; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0 ; CHECK-SD-NEXT: dup v0.4h, v0.h[0] -; CHECK-SD-NEXT: xtn v0.8b, v0.8h +; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-SD-NEXT: fmov w0, s0 ; CHECK-SD-NEXT: add sp, sp, #16 ; CHECK-SD-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/sme-avoid-coalescing-locally-streaming.ll b/llvm/test/CodeGen/AArch64/sme-avoid-coalescing-locally-streaming.ll new file mode 100644 index 0000000000000000000000000000000000000000..cd5046a9a64752cea8c8f2c70e4e7d3645685bc0 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/sme-avoid-coalescing-locally-streaming.ll @@ -0,0 +1,120 @@ +; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mattr=+sme -stop-after=finalize-isel < %s | FileCheck %s --check-prefix=CHECK-COALESCER-BARRIER +; RUN: llc -mattr=+sme -stop-after=virtregrewriter < %s | FileCheck %s --check-prefix=CHECK-REGALLOC + +target triple = "aarch64" + +define void @dont_coalesce_args(<2 x i64> %a) "aarch64_pstate_sm_body" nounwind { + ; CHECK-COALESCER-BARRIER-LABEL: name: dont_coalesce_args + ; CHECK-COALESCER-BARRIER: bb.0 (%ir-block.0): + ; CHECK-COALESCER-BARRIER-NEXT: liveins: $q0 + ; CHECK-COALESCER-BARRIER-NEXT: {{ $}} + ; CHECK-COALESCER-BARRIER-NEXT: [[COPY:%[0-9]+]]:fpr128 = COPY $q0 + ; CHECK-COALESCER-BARRIER-NEXT: [[COALESCER_BARRIER_FPR128_:%[0-9]+]]:fpr128 = COALESCER_BARRIER_FPR128 [[COPY]] + ; CHECK-COALESCER-BARRIER-NEXT: MSRpstatesvcrImm1 1, 1, csr_aarch64_smstartstop, implicit-def dead $nzcv, implicit $vg, implicit-def $vg + ; CHECK-COALESCER-BARRIER-NEXT: [[DEF:%[0-9]+]]:zpr = IMPLICIT_DEF + ; CHECK-COALESCER-BARRIER-NEXT: [[INSERT_SUBREG:%[0-9]+]]:zpr = INSERT_SUBREG [[DEF]], [[COALESCER_BARRIER_FPR128_]], %subreg.zsub + ; CHECK-COALESCER-BARRIER-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp + ; CHECK-COALESCER-BARRIER-NEXT: $z0 = COPY [[INSERT_SUBREG]] + ; CHECK-COALESCER-BARRIER-NEXT: BL @scalable_args, csr_aarch64_sve_aapcs, implicit-def dead $lr, implicit $sp, implicit $z0, implicit-def $sp + ; CHECK-COALESCER-BARRIER-NEXT: ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp + ; CHECK-COALESCER-BARRIER-NEXT: MSRpstatesvcrImm1 1, 0, csr_aarch64_smstartstop, implicit-def dead $nzcv, implicit $vg, implicit-def $vg + ; CHECK-COALESCER-BARRIER-NEXT: RET_ReallyLR + ; + ; CHECK-REGALLOC-LABEL: name: dont_coalesce_args + ; CHECK-REGALLOC: bb.0 (%ir-block.0): + ; CHECK-REGALLOC-NEXT: liveins: $q0 + ; CHECK-REGALLOC-NEXT: {{ $}} + ; CHECK-REGALLOC-NEXT: renamable $q0 = COALESCER_BARRIER_FPR128 killed renamable $q0 + ; CHECK-REGALLOC-NEXT: STRQui killed renamable $q0, %stack.0, 0 :: (store (s128) into %stack.0) + ; CHECK-REGALLOC-NEXT: MSRpstatesvcrImm1 1, 1, csr_aarch64_smstartstop, implicit-def dead $nzcv, implicit $vg, implicit-def $vg + ; CHECK-REGALLOC-NEXT: renamable $q0 = LDRQui %stack.0, 0 :: (load (s128) from %stack.0) + ; CHECK-REGALLOC-NEXT: renamable $q0 = KILL killed renamable $q0, implicit-def $z0 + ; CHECK-REGALLOC-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp + ; CHECK-REGALLOC-NEXT: BL @scalable_args, csr_aarch64_sve_aapcs, implicit-def dead $lr, implicit $sp, implicit $z0, implicit-def $sp + ; CHECK-REGALLOC-NEXT: ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp + ; CHECK-REGALLOC-NEXT: MSRpstatesvcrImm1 1, 0, csr_aarch64_smstartstop, implicit-def dead $nzcv, implicit $vg, implicit-def $vg + ; CHECK-REGALLOC-NEXT: RET_ReallyLR + %sa = call <vscale x 2 x i64> @llvm.vector.insert.nxv2i64.v2i64(<vscale x 2 x i64> poison, <2 x i64> %a, i64 0) + call void @scalable_args(<vscale x 2 x i64> %sa) + ret void +} + +define <2 x i64> @dont_coalesce_res() "aarch64_pstate_sm_body" nounwind { + ; CHECK-COALESCER-BARRIER-LABEL: name: dont_coalesce_res + ; CHECK-COALESCER-BARRIER: bb.0 (%ir-block.0): + ; CHECK-COALESCER-BARRIER-NEXT: MSRpstatesvcrImm1 1, 1, csr_aarch64_smstartstop, implicit-def dead $nzcv, implicit $vg, implicit-def $vg + ; CHECK-COALESCER-BARRIER-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp + ; CHECK-COALESCER-BARRIER-NEXT: BL @scalable_res, csr_aarch64_sve_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def $z0 + ; CHECK-COALESCER-BARRIER-NEXT: ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp + ; CHECK-COALESCER-BARRIER-NEXT: [[COPY:%[0-9]+]]:zpr = COPY $z0 + ; CHECK-COALESCER-BARRIER-NEXT: [[COPY1:%[0-9]+]]:fpr128 = COPY [[COPY]].zsub + ; CHECK-COALESCER-BARRIER-NEXT: [[COALESCER_BARRIER_FPR128_:%[0-9]+]]:fpr128 = COALESCER_BARRIER_FPR128 [[COPY1]] + ; CHECK-COALESCER-BARRIER-NEXT: MSRpstatesvcrImm1 1, 0, csr_aarch64_smstartstop, implicit-def dead $nzcv, implicit-def $q0, implicit $vg, implicit-def $vg + ; CHECK-COALESCER-BARRIER-NEXT: $q0 = COPY [[COALESCER_BARRIER_FPR128_]] + ; CHECK-COALESCER-BARRIER-NEXT: RET_ReallyLR implicit $q0 + ; + ; CHECK-REGALLOC-LABEL: name: dont_coalesce_res + ; CHECK-REGALLOC: bb.0 (%ir-block.0): + ; CHECK-REGALLOC-NEXT: MSRpstatesvcrImm1 1, 1, csr_aarch64_smstartstop, implicit-def dead $nzcv, implicit $vg, implicit-def $vg + ; CHECK-REGALLOC-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp + ; CHECK-REGALLOC-NEXT: BL @scalable_res, csr_aarch64_sve_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp, implicit-def $z0 + ; CHECK-REGALLOC-NEXT: ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp + ; CHECK-REGALLOC-NEXT: renamable $q0 = KILL renamable $q0, implicit killed $z0 + ; CHECK-REGALLOC-NEXT: renamable $q0 = COALESCER_BARRIER_FPR128 killed renamable $q0 + ; CHECK-REGALLOC-NEXT: STRQui killed renamable $q0, %stack.0, 0 :: (store (s128) into %stack.0) + ; CHECK-REGALLOC-NEXT: MSRpstatesvcrImm1 1, 0, csr_aarch64_smstartstop, implicit-def dead $nzcv, implicit-def dead $q0, implicit $vg, implicit-def $vg + ; CHECK-REGALLOC-NEXT: $q0 = LDRQui %stack.0, 0 :: (load (s128) from %stack.0) + ; CHECK-REGALLOC-NEXT: RET_ReallyLR implicit $q0 + %sa = call <vscale x 2 x i64> @scalable_res() + %res = call <2 x i64> @llvm.vector.extract.v2i64.nxv2i64(<vscale x 2 x i64> %sa, i64 0) + ret <2 x i64> %res +} + +define <2 x i64> @dont_coalesce_arg_that_is_also_res(<2 x i64> %a) "aarch64_pstate_sm_body" nounwind { + ; CHECK-COALESCER-BARRIER-LABEL: name: dont_coalesce_arg_that_is_also_res + ; CHECK-COALESCER-BARRIER: bb.0 (%ir-block.0): + ; CHECK-COALESCER-BARRIER-NEXT: liveins: $q0 + ; CHECK-COALESCER-BARRIER-NEXT: {{ $}} + ; CHECK-COALESCER-BARRIER-NEXT: [[COPY:%[0-9]+]]:fpr128 = COPY $q0 + ; CHECK-COALESCER-BARRIER-NEXT: [[COALESCER_BARRIER_FPR128_:%[0-9]+]]:fpr128 = COALESCER_BARRIER_FPR128 [[COPY]] + ; CHECK-COALESCER-BARRIER-NEXT: MSRpstatesvcrImm1 1, 1, csr_aarch64_smstartstop, implicit-def dead $nzcv, implicit $vg, implicit-def $vg + ; CHECK-COALESCER-BARRIER-NEXT: [[DEF:%[0-9]+]]:zpr = IMPLICIT_DEF + ; CHECK-COALESCER-BARRIER-NEXT: [[INSERT_SUBREG:%[0-9]+]]:zpr = INSERT_SUBREG [[DEF]], [[COALESCER_BARRIER_FPR128_]], %subreg.zsub + ; CHECK-COALESCER-BARRIER-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp + ; CHECK-COALESCER-BARRIER-NEXT: $z0 = COPY [[INSERT_SUBREG]] + ; CHECK-COALESCER-BARRIER-NEXT: BL @scalable_args, csr_aarch64_sve_aapcs, implicit-def dead $lr, implicit $sp, implicit $z0, implicit-def $sp + ; CHECK-COALESCER-BARRIER-NEXT: ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp + ; CHECK-COALESCER-BARRIER-NEXT: [[COALESCER_BARRIER_FPR128_1:%[0-9]+]]:fpr128 = COALESCER_BARRIER_FPR128 [[COALESCER_BARRIER_FPR128_]] + ; CHECK-COALESCER-BARRIER-NEXT: MSRpstatesvcrImm1 1, 0, csr_aarch64_smstartstop, implicit-def dead $nzcv, implicit-def $q0, implicit $vg, implicit-def $vg + ; CHECK-COALESCER-BARRIER-NEXT: $q0 = COPY [[COALESCER_BARRIER_FPR128_1]] + ; CHECK-COALESCER-BARRIER-NEXT: RET_ReallyLR implicit $q0 + ; + ; CHECK-REGALLOC-LABEL: name: dont_coalesce_arg_that_is_also_res + ; CHECK-REGALLOC: bb.0 (%ir-block.0): + ; CHECK-REGALLOC-NEXT: liveins: $q0 + ; CHECK-REGALLOC-NEXT: {{ $}} + ; CHECK-REGALLOC-NEXT: renamable $q0 = COALESCER_BARRIER_FPR128 killed renamable $q0 + ; CHECK-REGALLOC-NEXT: STRQui killed renamable $q0, %stack.0, 0 :: (store (s128) into %stack.0) + ; CHECK-REGALLOC-NEXT: MSRpstatesvcrImm1 1, 1, csr_aarch64_smstartstop, implicit-def dead $nzcv, implicit $vg, implicit-def $vg + ; CHECK-REGALLOC-NEXT: renamable $q0 = LDRQui %stack.0, 0 :: (load (s128) from %stack.0) + ; CHECK-REGALLOC-NEXT: renamable $q0 = KILL killed renamable $q0, implicit-def $z0 + ; CHECK-REGALLOC-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp + ; CHECK-REGALLOC-NEXT: BL @scalable_args, csr_aarch64_sve_aapcs, implicit-def dead $lr, implicit $sp, implicit $z0, implicit-def $sp + ; CHECK-REGALLOC-NEXT: ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp + ; CHECK-REGALLOC-NEXT: renamable $q0 = LDRQui %stack.0, 0 :: (load (s128) from %stack.0) + ; CHECK-REGALLOC-NEXT: renamable $q0 = COALESCER_BARRIER_FPR128 killed renamable $q0 + ; CHECK-REGALLOC-NEXT: STRQui killed renamable $q0, %stack.0, 0 :: (store (s128) into %stack.0) + ; CHECK-REGALLOC-NEXT: MSRpstatesvcrImm1 1, 0, csr_aarch64_smstartstop, implicit-def dead $nzcv, implicit-def dead $q0, implicit $vg, implicit-def $vg + ; CHECK-REGALLOC-NEXT: $q0 = LDRQui %stack.0, 0 :: (load (s128) from %stack.0) + ; CHECK-REGALLOC-NEXT: RET_ReallyLR implicit $q0 + %sa = call <vscale x 2 x i64> @llvm.vector.insert.nxv2i64.v2i64(<vscale x 2 x i64> poison, <2 x i64> %a, i64 0) + call void @scalable_args(<vscale x 2 x i64> %sa) + ret <2 x i64> %a +} + +declare void @scalable_args(<vscale x 2 x i64>) "aarch64_pstate_sm_enabled" +declare <vscale x 2 x i64> @llvm.vector.insert.nxv2i64.v2i64(<vscale x 2 x i64>, <2 x i64>, i64) + +declare <vscale x 2 x i64> @scalable_res() "aarch64_pstate_sm_enabled" +declare <2 x i64> @llvm.vector.extract.v2i64.nxv2i64(<vscale x 2 x i64>, i64) diff --git a/llvm/test/CodeGen/AArch64/sme-call-streaming-compatible-to-normal-fn-wihout-sme-attr.ll b/llvm/test/CodeGen/AArch64/sme-call-streaming-compatible-to-normal-fn-wihout-sme-attr.ll index 3fa1ee5b9b011401ae338365332d913e73d16a9e..dba3227459b9065e2e57b2d182e25efdb9cf1d1a 100644 --- a/llvm/test/CodeGen/AArch64/sme-call-streaming-compatible-to-normal-fn-wihout-sme-attr.ll +++ b/llvm/test/CodeGen/AArch64/sme-call-streaming-compatible-to-normal-fn-wihout-sme-attr.ll @@ -38,4 +38,43 @@ define void @streaming_compatible() #0 { declare void @non_streaming() + +; Verify that COALESCER_BARRIER is also supported without +sme. + +define void @streaming_compatible_arg(float %f) #0 { +; CHECK-LABEL: streaming_compatible_arg: +; CHECK: // %bb.0: +; CHECK-NEXT: sub sp, sp, #96 +; CHECK-NEXT: stp d15, d14, [sp, #16] // 16-byte Folded Spill +; CHECK-NEXT: stp d13, d12, [sp, #32] // 16-byte Folded Spill +; CHECK-NEXT: stp d11, d10, [sp, #48] // 16-byte Folded Spill +; CHECK-NEXT: stp d9, d8, [sp, #64] // 16-byte Folded Spill +; CHECK-NEXT: stp x30, x19, [sp, #80] // 16-byte Folded Spill +; CHECK-NEXT: str s0, [sp, #12] // 4-byte Folded Spill +; CHECK-NEXT: bl __arm_sme_state +; CHECK-NEXT: ldr s0, [sp, #12] // 4-byte Folded Reload +; CHECK-NEXT: and x19, x0, #0x1 +; CHECK-NEXT: str s0, [sp, #12] // 4-byte Folded Spill +; CHECK-NEXT: tbz w19, #0, .LBB1_2 +; CHECK-NEXT: // %bb.1: +; CHECK-NEXT: smstop sm +; CHECK-NEXT: .LBB1_2: +; CHECK-NEXT: ldr s0, [sp, #12] // 4-byte Folded Reload +; CHECK-NEXT: bl non_streaming +; CHECK-NEXT: tbz w19, #0, .LBB1_4 +; CHECK-NEXT: // %bb.3: +; CHECK-NEXT: smstart sm +; CHECK-NEXT: .LBB1_4: +; CHECK-NEXT: ldp x30, x19, [sp, #80] // 16-byte Folded Reload +; CHECK-NEXT: ldp d9, d8, [sp, #64] // 16-byte Folded Reload +; CHECK-NEXT: ldp d11, d10, [sp, #48] // 16-byte Folded Reload +; CHECK-NEXT: ldp d13, d12, [sp, #32] // 16-byte Folded Reload +; CHECK-NEXT: ldp d15, d14, [sp, #16] // 16-byte Folded Reload +; CHECK-NEXT: add sp, sp, #96 +; CHECK-NEXT: ret + call void @non_streaming(float %f) + ret void +} + + attributes #0 = { nounwind "aarch64_pstate_sm_compatible" } diff --git a/llvm/test/CodeGen/AArch64/sme-machine-licm-vg.mir b/llvm/test/CodeGen/AArch64/sme-machine-licm-vg.mir new file mode 100644 index 0000000000000000000000000000000000000000..e6cce9af0daf0e842b3cdee36f0aec07f78adcbf --- /dev/null +++ b/llvm/test/CodeGen/AArch64/sme-machine-licm-vg.mir @@ -0,0 +1,64 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4 +# RUN: llc -mtriple=aarch64--linux-gnu -run-pass=early-machinelicm %s -verify-machineinstrs -o - | FileCheck %s +--- +name: test_should_hoist_pfalse +tracksRegLiveness: true +body: | + ; CHECK-LABEL: name: test_should_hoist_pfalse + ; CHECK: bb.0: + ; CHECK-NEXT: successors: %bb.1(0x80000000) + ; CHECK-NEXT: liveins: $x0, $x1 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x1 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64 = COPY $x0 + ; CHECK-NEXT: MSRpstatesvcrImm1 1, 1, csr_aarch64_smstartstop, implicit-def dead $nzcv, implicit $vg, implicit-def $vg + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr64all = COPY [[COPY1]] + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr64all = COPY [[COPY]] + ; CHECK-NEXT: [[PFALSE:%[0-9]+]]:ppr = PFALSE implicit $vg + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.1: + ; CHECK-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000) + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[PHI:%[0-9]+]]:gpr64common = PHI [[COPY2]], %bb.0, %5, %bb.1 + ; CHECK-NEXT: [[PHI1:%[0-9]+]]:gpr64sp = PHI [[COPY3]], %bb.0, %7, %bb.1 + ; CHECK-NEXT: STR_PXI [[PFALSE]], [[PHI]], 0 + ; CHECK-NEXT: [[SUBSXri:%[0-9]+]]:gpr64 = SUBSXri [[PHI1]], 1, 0, implicit-def $nzcv + ; CHECK-NEXT: [[COPY4:%[0-9]+]]:gpr64all = COPY [[SUBSXri]] + ; CHECK-NEXT: [[INCD_XPiI:%[0-9]+]]:gpr64 = INCD_XPiI [[PHI]], 31, 1 + ; CHECK-NEXT: [[COPY5:%[0-9]+]]:gpr64all = COPY [[INCD_XPiI]] + ; CHECK-NEXT: Bcc 1, %bb.1, implicit $nzcv + ; CHECK-NEXT: B %bb.2 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: bb.2: + ; CHECK-NEXT: MSRpstatesvcrImm1 1, 0, csr_aarch64_smstartstop, implicit-def dead $nzcv, implicit $vg, implicit-def $vg + ; CHECK-NEXT: RET_ReallyLR + bb.0: + successors: %bb.1 + liveins: $x0, $x1 + + %5:gpr64 = COPY $x1 + %4:gpr64 = COPY $x0 + MSRpstatesvcrImm1 1, 1, csr_aarch64_smstartstop, implicit-def dead $nzcv, implicit $vg, implicit-def $vg + %6:gpr64all = COPY %4 + %7:gpr64all = COPY %5 + + bb.1: + successors: %bb.2, %bb.1 + + %0:gpr64common = PHI %6, %bb.0, %3, %bb.1 + %1:gpr64sp = PHI %7, %bb.0, %2, %bb.1 + %8:ppr = PFALSE implicit $vg + STR_PXI killed %8, %0, 0 + %9:gpr64 = SUBSXri %1, 1, 0, implicit-def $nzcv + %2:gpr64all = COPY %9 + %10:gpr64 = INCD_XPiI %0, 31, 1 + %3:gpr64all = COPY %10 + + + Bcc 1, %bb.1, implicit $nzcv + B %bb.2 + + bb.2: + MSRpstatesvcrImm1 1, 0, csr_aarch64_smstartstop, implicit-def dead $nzcv, implicit $vg, implicit-def $vg + RET_ReallyLR +... diff --git a/llvm/test/CodeGen/AArch64/sme-streaming-body-streaming-compatible-interface.ll b/llvm/test/CodeGen/AArch64/sme-streaming-body-streaming-compatible-interface.ll index d67573384ca959bcf68a4dce159503cabab6d219..6e262cc0786e41a59eb74af4e202924393b58ff7 100644 --- a/llvm/test/CodeGen/AArch64/sme-streaming-body-streaming-compatible-interface.ll +++ b/llvm/test/CodeGen/AArch64/sme-streaming-body-streaming-compatible-interface.ll @@ -8,27 +8,31 @@ declare void @streaming_compatible_callee() "aarch64_pstate_sm_compatible"; define float @sm_body_sm_compatible_simple() "aarch64_pstate_sm_compatible" "aarch64_pstate_sm_body" nounwind { ; CHECK-LABEL: sm_body_sm_compatible_simple: ; CHECK: // %bb.0: -; CHECK-NEXT: stp d15, d14, [sp, #-80]! // 16-byte Folded Spill -; CHECK-NEXT: stp d13, d12, [sp, #16] // 16-byte Folded Spill -; CHECK-NEXT: stp d11, d10, [sp, #32] // 16-byte Folded Spill -; CHECK-NEXT: stp d9, d8, [sp, #48] // 16-byte Folded Spill -; CHECK-NEXT: str x30, [sp, #64] // 8-byte Folded Spill +; CHECK-NEXT: sub sp, sp, #96 +; CHECK-NEXT: stp d15, d14, [sp, #16] // 16-byte Folded Spill +; CHECK-NEXT: stp d13, d12, [sp, #32] // 16-byte Folded Spill +; CHECK-NEXT: stp d11, d10, [sp, #48] // 16-byte Folded Spill +; CHECK-NEXT: stp d9, d8, [sp, #64] // 16-byte Folded Spill +; CHECK-NEXT: str x30, [sp, #80] // 8-byte Folded Spill ; CHECK-NEXT: bl __arm_sme_state ; CHECK-NEXT: and x8, x0, #0x1 ; CHECK-NEXT: tbnz w8, #0, .LBB0_2 ; CHECK-NEXT: // %bb.1: ; CHECK-NEXT: smstart sm ; CHECK-NEXT: .LBB0_2: +; CHECK-NEXT: fmov s0, wzr +; CHECK-NEXT: str s0, [sp, #12] // 4-byte Folded Spill ; CHECK-NEXT: tbnz w8, #0, .LBB0_4 ; CHECK-NEXT: // %bb.3: ; CHECK-NEXT: smstop sm ; CHECK-NEXT: .LBB0_4: -; CHECK-NEXT: ldp d9, d8, [sp, #48] // 16-byte Folded Reload -; CHECK-NEXT: fmov s0, wzr -; CHECK-NEXT: ldp d11, d10, [sp, #32] // 16-byte Folded Reload -; CHECK-NEXT: ldr x30, [sp, #64] // 8-byte Folded Reload -; CHECK-NEXT: ldp d13, d12, [sp, #16] // 16-byte Folded Reload -; CHECK-NEXT: ldp d15, d14, [sp], #80 // 16-byte Folded Reload +; CHECK-NEXT: ldp d9, d8, [sp, #64] // 16-byte Folded Reload +; CHECK-NEXT: ldr s0, [sp, #12] // 4-byte Folded Reload +; CHECK-NEXT: ldp d11, d10, [sp, #48] // 16-byte Folded Reload +; CHECK-NEXT: ldr x30, [sp, #80] // 8-byte Folded Reload +; CHECK-NEXT: ldp d13, d12, [sp, #32] // 16-byte Folded Reload +; CHECK-NEXT: ldp d15, d14, [sp, #16] // 16-byte Folded Reload +; CHECK-NEXT: add sp, sp, #96 ; CHECK-NEXT: ret ret float zeroinitializer } diff --git a/llvm/test/CodeGen/AArch64/sme-streaming-body.ll b/llvm/test/CodeGen/AArch64/sme-streaming-body.ll index 93875549cffc86f6e70af7d9e1ef7e874423fbce..08dec228d2f756ff4e09848c86a2de9918486df1 100644 --- a/llvm/test/CodeGen/AArch64/sme-streaming-body.ll +++ b/llvm/test/CodeGen/AArch64/sme-streaming-body.ll @@ -87,29 +87,27 @@ if.end: define <2 x i64> @locally_streaming_caller_no_callee(<2 x i64> %a) "aarch64_pstate_sm_body" nounwind { ; CHECK-LABEL: locally_streaming_caller_no_callee: ; CHECK: // %bb.0: -; CHECK-NEXT: stp d15, d14, [sp, #-80]! // 16-byte Folded Spill -; CHECK-NEXT: stp d13, d12, [sp, #16] // 16-byte Folded Spill -; CHECK-NEXT: stp d11, d10, [sp, #32] // 16-byte Folded Spill -; CHECK-NEXT: stp d9, d8, [sp, #48] // 16-byte Folded Spill -; CHECK-NEXT: str x29, [sp, #64] // 8-byte Folded Spill -; CHECK-NEXT: addsvl sp, sp, #-1 -; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0 -; CHECK-NEXT: str z0, [sp] // 16-byte Folded Spill +; CHECK-NEXT: sub sp, sp, #80 +; CHECK-NEXT: stp d15, d14, [sp, #16] // 16-byte Folded Spill +; CHECK-NEXT: stp d13, d12, [sp, #32] // 16-byte Folded Spill +; CHECK-NEXT: stp d11, d10, [sp, #48] // 16-byte Folded Spill +; CHECK-NEXT: stp d9, d8, [sp, #64] // 16-byte Folded Spill +; CHECK-NEXT: str q0, [sp] // 16-byte Folded Spill ; CHECK-NEXT: smstart sm ; CHECK-NEXT: index z0.d, #0, #1 -; CHECK-NEXT: ldr z1, [sp] // 16-byte Folded Reload +; CHECK-NEXT: ldr q1, [sp] // 16-byte Folded Reload +; CHECK-NEXT: // kill: def $q1 killed $q1 def $z1 ; CHECK-NEXT: add z0.d, z0.d, z1.d ; CHECK-NEXT: add z0.d, z0.d, #41 // =0x29 -; CHECK-NEXT: str z0, [sp] // 16-byte Folded Spill -; CHECK-NEXT: smstop sm -; CHECK-NEXT: ldr z0, [sp] // 16-byte Folded Reload ; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0 -; CHECK-NEXT: addsvl sp, sp, #1 -; CHECK-NEXT: ldp d9, d8, [sp, #48] // 16-byte Folded Reload -; CHECK-NEXT: ldr x29, [sp, #64] // 8-byte Folded Reload -; CHECK-NEXT: ldp d11, d10, [sp, #32] // 16-byte Folded Reload -; CHECK-NEXT: ldp d13, d12, [sp, #16] // 16-byte Folded Reload -; CHECK-NEXT: ldp d15, d14, [sp], #80 // 16-byte Folded Reload +; CHECK-NEXT: str q0, [sp] // 16-byte Folded Spill +; CHECK-NEXT: smstop sm +; CHECK-NEXT: ldp d9, d8, [sp, #64] // 16-byte Folded Reload +; CHECK-NEXT: ldr q0, [sp] // 16-byte Folded Reload +; CHECK-NEXT: ldp d11, d10, [sp, #48] // 16-byte Folded Reload +; CHECK-NEXT: ldp d13, d12, [sp, #32] // 16-byte Folded Reload +; CHECK-NEXT: ldp d15, d14, [sp, #16] // 16-byte Folded Reload +; CHECK-NEXT: add sp, sp, #80 ; CHECK-NEXT: ret %add = add <2 x i64> %a, <i64 41, i64 42>; diff --git a/llvm/test/CodeGen/AArch64/sme-write-vg.ll b/llvm/test/CodeGen/AArch64/sme-write-vg.ll new file mode 100644 index 0000000000000000000000000000000000000000..577606d45484f13b0a72c11f72f03c956184be4d --- /dev/null +++ b/llvm/test/CodeGen/AArch64/sme-write-vg.ll @@ -0,0 +1,24 @@ +; RUN: llc -mattr=+sme -stop-after=finalize-isel < %s | FileCheck %s + +target triple = "aarch64" + +; Check that we don't define VG for 'smstart za' and 'smstop za' +define void @smstart_za() "aarch64_new_za" nounwind { + ; CHECK-LABEL: name: smstart_za + ; CHECK-NOT: implicit-def {{[^,]*}}$vg + ret void +} + +; Check that we do define VG for 'smstart sm' and 'smstop sm' +define void @smstart_sm() nounwind { + ; CHECK-LABEL: name: smstart_sm + ; CHECK: MSRpstatesvcrImm1 1, 1, + ; CHECK-SAME: implicit-def {{[^,]*}}$vg + ; CHECK: MSRpstatesvcrImm1 1, 0, + ; CHECK-SAME: implicit-def {{[^,]*}}$vg + call void @require_sm() + ret void +} + +declare void @require_sm() "aarch64_pstate_sm_enabled" +declare void @require_za() "aarch64_inout_za" diff --git a/llvm/test/CodeGen/AArch64/soft-float-abi.ll b/llvm/test/CodeGen/AArch64/soft-float-abi.ll new file mode 100644 index 0000000000000000000000000000000000000000..291c3875c2488d18e14920ad06968de63a535769 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/soft-float-abi.ll @@ -0,0 +1,161 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc --mtriple aarch64-none-eabi < %s -mattr=-fp-armv8 | FileCheck %s + +; See also clang/test/CodeGen/aarch64-soft-float-abi.c, which tests the clang +; parts of the soft-float ABI. + +; FP types up to 64-bit are passed in a general purpose register. +define half @test0(half %a, half %b) { +; CHECK-LABEL: test0: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov w0, w1 +; CHECK-NEXT: ret +entry: + ret half %b +} + +define bfloat @test1(i32 %a, bfloat %b) { +; CHECK-LABEL: test1: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov w0, w1 +; CHECK-NEXT: ret +entry: + ret bfloat %b +} + +define float @test2(i64 %a, float %b) { +; CHECK-LABEL: test2: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov w0, w1 +; CHECK-NEXT: ret +entry: + ret float %b +} + +define double @test3(half %a, double %b) { +; CHECK-LABEL: test3: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov x0, x1 +; CHECK-NEXT: ret +entry: + ret double %b +} + +; fp128 is passed in a pair of GPRs. +define fp128 @test4(fp128 %a, fp128 %b) { +; CHECK-LABEL: test4: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov x1, x3 +; CHECK-NEXT: mov x0, x2 +; CHECK-NEXT: ret +entry: + ret fp128 %b +} + +; fp128 is passed in an aligned pair of GPRs, leaving one register unused is +; necessary. +define fp128 @test5(float %a, fp128 %b) { +; CHECK-LABEL: test5: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov x1, x3 +; CHECK-NEXT: mov x0, x2 +; CHECK-NEXT: ret +entry: + ret fp128 %b +} + +; If the alignment of an fp128 leaves a register unused, it remains unused even +; if a later argument could fit in it. +define i64 @test6(i64 %a, fp128 %b, i64 %c) { +; CHECK-LABEL: test6: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: mov x0, x4 +; CHECK-NEXT: ret +entry: + ret i64 %c +} + +; HFAs are all bit-casted to integer types in the frontend when using the +; soft-float ABI, so they get passed in the same way as non-homeogeneous +; aggregates. The IR is identical to the equivalent integer types, so nothing +; to test here. + +; The PCS for vector and HVA types is not defined by the soft-float ABI because +; these types are only defined by the ACLE when vector hardware is available, +; so nothing to test here. + +; The front-end generates IR for va_arg which always reads from the integer +; register save area, and never the floating-point register save area. The +; layout of the va_list type remains the same, the floating-point related +; fields are unused. The only change needed in the backend is in va_start, to +; not attempt to save the floating-point registers or set the FP fields in the +; va_list. +%struct.__va_list = type { ptr, ptr, ptr, i32, i32 } +declare void @llvm.va_start(ptr) +define double @test20(i32 %a, ...) { +; CHECK-LABEL: test20: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: sub sp, sp, #96 +; CHECK-NEXT: .cfi_def_cfa_offset 96 +; CHECK-NEXT: mov w8, #-56 // =0xffffffc8 +; CHECK-NEXT: add x10, sp, #8 +; CHECK-NEXT: add x9, sp, #96 +; CHECK-NEXT: str x8, [sp, #88] +; CHECK-NEXT: add x10, x10, #56 +; CHECK-NEXT: ldrsw x8, [sp, #88] +; CHECK-NEXT: stp x1, x2, [sp, #8] +; CHECK-NEXT: stp x3, x4, [sp, #24] +; CHECK-NEXT: stp x5, x6, [sp, #40] +; CHECK-NEXT: stp x7, x9, [sp, #56] +; CHECK-NEXT: str x10, [sp, #72] +; CHECK-NEXT: tbz w8, #31, .LBB7_3 +; CHECK-NEXT: // %bb.1: // %vaarg.maybe_reg +; CHECK-NEXT: add w9, w8, #8 +; CHECK-NEXT: cmn w8, #8 +; CHECK-NEXT: str w9, [sp, #88] +; CHECK-NEXT: b.gt .LBB7_3 +; CHECK-NEXT: // %bb.2: // %vaarg.in_reg +; CHECK-NEXT: ldr x9, [sp, #72] +; CHECK-NEXT: add x8, x9, x8 +; CHECK-NEXT: b .LBB7_4 +; CHECK-NEXT: .LBB7_3: // %vaarg.on_stack +; CHECK-NEXT: ldr x8, [sp, #64] +; CHECK-NEXT: add x9, x8, #8 +; CHECK-NEXT: str x9, [sp, #64] +; CHECK-NEXT: .LBB7_4: // %vaarg.end +; CHECK-NEXT: ldr x0, [x8] +; CHECK-NEXT: add sp, sp, #96 +; CHECK-NEXT: ret +entry: + %vl = alloca %struct.__va_list, align 8 + call void @llvm.va_start(ptr nonnull %vl) + %gr_offs_p = getelementptr inbounds %struct.__va_list, ptr %vl, i64 0, i32 3 + %gr_offs = load i32, ptr %gr_offs_p, align 8 + %0 = icmp sgt i32 %gr_offs, -1 + br i1 %0, label %vaarg.on_stack, label %vaarg.maybe_reg + +vaarg.maybe_reg: ; preds = %entry + %new_reg_offs = add nsw i32 %gr_offs, 8 + store i32 %new_reg_offs, ptr %gr_offs_p, align 8 + %inreg = icmp slt i32 %gr_offs, -7 + br i1 %inreg, label %vaarg.in_reg, label %vaarg.on_stack + +vaarg.in_reg: ; preds = %vaarg.maybe_reg + %reg_top_p = getelementptr inbounds %struct.__va_list, ptr %vl, i64 0, i32 1 + %reg_top = load ptr, ptr %reg_top_p, align 8 + %1 = sext i32 %gr_offs to i64 + %2 = getelementptr inbounds i8, ptr %reg_top, i64 %1 + br label %vaarg.end + +vaarg.on_stack: ; preds = %vaarg.maybe_reg, %entry + %stack = load ptr, ptr %vl, align 8 + %new_stack = getelementptr inbounds i8, ptr %stack, i64 8 + store ptr %new_stack, ptr %vl, align 8 + br label %vaarg.end + +vaarg.end: ; preds = %vaarg.on_stack, %vaarg.in_reg + %vaargs.addr = phi ptr [ %2, %vaarg.in_reg ], [ %stack, %vaarg.on_stack ] + %3 = load double, ptr %vaargs.addr, align 8 + ret double %3 +} + diff --git a/llvm/test/CodeGen/AArch64/srem-vec-crash.ll b/llvm/test/CodeGen/AArch64/srem-vec-crash.ll new file mode 100644 index 0000000000000000000000000000000000000000..0fce8de30d4d4b6231f0b420da26c780663e51fb --- /dev/null +++ b/llvm/test/CodeGen/AArch64/srem-vec-crash.ll @@ -0,0 +1,15 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple=aarch64-unknown-unknown < %s | FileCheck %s + +define i32 @pr84830(i1 %arg) { +; CHECK-LABEL: pr84830: +; CHECK: // %bb.0: // %bb +; CHECK-NEXT: mov w0, #1 // =0x1 +; CHECK-NEXT: ret +bb: + %new0 = srem i1 %arg, true + %last = zext i1 %new0 to i32 + %i = icmp ne i32 %last, 0 + %i1 = select i1 %i, i32 0, i32 1 + ret i32 %i1 +} diff --git a/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll b/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll index acec3e74d3e93f7a3aa0651a63610f3151a550bc..d1f843a09f749d5e7ca2ccfbb76127c9c705bcbe 100644 --- a/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll +++ b/llvm/test/CodeGen/AArch64/ssub_sat_vec.ll @@ -146,7 +146,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind { ; CHECK-NEXT: shl v0.4h, v0.4h, #8 ; CHECK-NEXT: sqsub v0.4h, v0.4h, v1.4h ; CHECK-NEXT: sshr v0.4h, v0.4h, #8 -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [x2] ; CHECK-NEXT: ret %x = load <4 x i8>, ptr %px diff --git a/llvm/test/CodeGen/AArch64/stack-probing-no-scratch-reg.mir b/llvm/test/CodeGen/AArch64/stack-probing-no-scratch-reg.mir index f2d79bd72069087232df096e8aa24c5c9160b164..a9c9b5ff60e451cd15d01f628686b4334ea62200 100644 --- a/llvm/test/CodeGen/AArch64/stack-probing-no-scratch-reg.mir +++ b/llvm/test/CodeGen/AArch64/stack-probing-no-scratch-reg.mir @@ -29,6 +29,7 @@ tracksRegLiveness: true liveins: - { reg: '$w0', virtual-reg: '' } frameInfo: + adjustsStack: true localFrameSize: 150000 stack: - { id: 0, name: a, type: default, offset: 0, size: 150000, alignment: 8, diff --git a/llvm/test/CodeGen/AArch64/stack-probing-shrink-wrap.mir b/llvm/test/CodeGen/AArch64/stack-probing-shrink-wrap.mir index 83aa90d389a4a2bae0b92fcf67227e70b9a6d33f..985ec352139708d31e11c787aef330c65ddca7de 100644 --- a/llvm/test/CodeGen/AArch64/stack-probing-shrink-wrap.mir +++ b/llvm/test/CodeGen/AArch64/stack-probing-shrink-wrap.mir @@ -31,6 +31,7 @@ tracksRegLiveness: true liveins: - { reg: '$w0', virtual-reg: '' } frameInfo: + adjustsStack: true localFrameSize: 150000 stack: - { id: 0, name: a, type: default, offset: 0, size: 150000, alignment: 8, diff --git a/llvm/test/CodeGen/AArch64/stack-tagging-initializer-merge.ll b/llvm/test/CodeGen/AArch64/stack-tagging-initializer-merge.ll index d8969fc9bebdbf469399f04e398af404009109c3..22d177ca3267e95975bb1100ec2fe73c8887066d 100644 --- a/llvm/test/CodeGen/AArch64/stack-tagging-initializer-merge.ll +++ b/llvm/test/CodeGen/AArch64/stack-tagging-initializer-merge.ll @@ -20,10 +20,10 @@ entry: ; CHECK-LABEL: define void @OneVarNoInit( ; CHECK-DAG: [[X:%.*]] = alloca { i32, [12 x i8] }, align 16 ; CHECK-DAG: [[TX:%.*]] = call ptr @llvm.aarch64.tagp.{{.*}}(ptr [[X]], {{.*}}, i64 0) -; CHECK-DAG: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[TX]]) +; CHECK-DAG: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[X]]) ; CHECK-DAG: call void @llvm.aarch64.settag(ptr [[TX]], i64 16) ; CHECK-DAG: call void @use(ptr nonnull [[TX]]) -; CHECK-DAG: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[TX]]) +; CHECK-DAG: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[X]]) define void @OneVarInitConst() sanitize_memtag { entry: diff --git a/llvm/test/CodeGen/AArch64/stack-tagging-stack-coloring.ll b/llvm/test/CodeGen/AArch64/stack-tagging-stack-coloring.ll index 6eb72013fb0ed0990b04f4b8e4d8f9c7da6f217a..5d1c91e434dca2a7044ce53f91d87066d14d9598 100644 --- a/llvm/test/CodeGen/AArch64/stack-tagging-stack-coloring.ll +++ b/llvm/test/CodeGen/AArch64/stack-tagging-stack-coloring.ll @@ -1,20 +1,18 @@ ; Test that storage for allocas with disjoint lifetimes is reused with stack ; tagging. -; RUN: opt -S -aarch64-stack-tagging %s -o - | \ -; RUN: llc -no-stack-coloring=false -o - | \ +; RUN: llc --mattr=+mte -no-stack-coloring=false -stack-tagging-use-stack-safety=0 -o - %s | \ ; RUN: FileCheck %s --check-prefix=COLOR -; RUN: opt -S -aarch64-stack-tagging %s -o - | \ -; RUN: llc -no-stack-coloring=true -o - | \ +; RUN: llc --mattr=+mte -no-stack-coloring=true -stack-tagging-use-stack-safety=0 -o - %s | \ ; RUN: FileCheck %s --check-prefix=NOCOLOR target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" -target triple = "aarch64-unknown-linux-android29" +target triple = "aarch64" ; COLOR: sub sp, sp, #192 -; NOCOLOR: sub sp, sp, #320 +; NOCOLOR: sub sp, sp, #336 -define i32 @myCall_w2(i32 %in) sanitize_hwaddress { +define i32 @myCall_w2(i32 %in) sanitize_memtag { entry: %a = alloca [17 x ptr], align 8 %a2 = alloca [16 x ptr], align 8 diff --git a/llvm/test/CodeGen/AArch64/stack-tagging-untag-placement.ll b/llvm/test/CodeGen/AArch64/stack-tagging-untag-placement.ll index 06f8cd5241ebfb7361ae8f740add883499135e76..aa9cccc58712da898cd6c64108607931f77cc9f8 100644 --- a/llvm/test/CodeGen/AArch64/stack-tagging-untag-placement.ll +++ b/llvm/test/CodeGen/AArch64/stack-tagging-untag-placement.ll @@ -27,7 +27,7 @@ S1: ; CHECK: call void @llvm.aarch64.settag(ptr %w, i64 48) ; CHECK-NOT: settag{{.*}}%v call void @llvm.lifetime.end.p0(i64 48, ptr nonnull %w) #1 -; CHECK: call void @llvm.lifetime.end.p0(i64 48, ptr nonnull %w.tag) +; CHECK: call void @llvm.lifetime.end.p0(i64 48, ptr nonnull %w) %b1 = icmp eq i32 %t1, 0 br i1 %b1, label %S2, label %S3 ; CHECK-NOT: settag diff --git a/llvm/test/CodeGen/AArch64/stackmap.ll b/llvm/test/CodeGen/AArch64/stackmap.ll index ce7dcc4a59e9a7340c8de881c95d0995074af136..995d2545c63590df77bd0b104c97aa9f6284df33 100644 --- a/llvm/test/CodeGen/AArch64/stackmap.ll +++ b/llvm/test/CodeGen/AArch64/stackmap.ll @@ -9,11 +9,11 @@ ; CHECK-NEXT: .byte 0 ; CHECK-NEXT: .hword 0 ; Num Functions -; CHECK-NEXT: .word 14 +; CHECK-NEXT: .word 15 ; Num LargeConstants ; CHECK-NEXT: .word 4 ; Num Callsites -; CHECK-NEXT: .word 18 +; CHECK-NEXT: .word 22 ; Functions and stack size ; CHECK-NEXT: .xword constantargs @@ -49,6 +49,9 @@ ; CHECK-NEXT: .xword longid ; CHECK-NEXT: .xword 16 ; CHECK-NEXT: .xword 4 +; CHECK-NEXT: .xword statepoint_longid +; CHECK-NEXT: .xword 16 +; CHECK-NEXT: .xword 4 ; CHECK-NEXT: .xword clobberLR ; CHECK-NEXT: .xword 112 ; CHECK-NEXT: .xword 1 @@ -443,6 +446,26 @@ entry: ret void } +; Test a 64-bit ID for statepoint. +; +; CHECK: .xword 4294967295 +; CHECK-LABEL: .word .L{{.*}}-statepoint_longid +; CHECK: .xword 4294967296 +; CHECK-LABEL: .word .L{{.*}}-statepoint_longid +; CHECK: .xword 9223372036854775807 +; CHECK-LABEL: .word .L{{.*}}-statepoint_longid +; CHECK: .xword -1 +; CHECK-LABEL: .word .L{{.*}}-statepoint_longid +define void @statepoint_longid() gc "statepoint-example" { +entry: + %safepoint_token1 = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 4294967295, i32 0, ptr elementtype(void ()) @return_void, i32 0, i32 0, i32 0, i32 0) + %safepoint_token2 = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 4294967296, i32 0, ptr elementtype(void ()) @return_void, i32 0, i32 0, i32 0, i32 0) + %safepoint_token3 = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 9223372036854775807, i32 0, ptr elementtype(void ()) @return_void, i32 0, i32 0, i32 0, i32 0) + %safepoint_token4 = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 -1, i32 0, ptr elementtype(void ()) @return_void, i32 0, i32 0, i32 0, i32 0) + ret void +} +declare void @return_void() + ; Map a value when R11 is the only free register. ; The scratch register should not be used for a live stackmap value. ; @@ -463,8 +486,8 @@ define void @clobberLR(i32 %a) { ret void } -; A stack frame which needs to be realigned at runtime (to meet alignment -; criteria for values on the stack) does not have a fixed frame size. +; A stack frame which needs to be realigned at runtime (to meet alignment +; criteria for values on the stack) does not have a fixed frame size. ; CHECK-LABEL: .word .L{{.*}}-needsStackRealignment ; CHECK-NEXT: .hword 0 ; 0 locations @@ -537,3 +560,4 @@ define void @floats(float %f, double %g) { declare void @llvm.experimental.stackmap(i64, i32, ...) declare void @llvm.experimental.patchpoint.void(i64, i32, ptr, i32, ...) declare i64 @llvm.experimental.patchpoint.i64(i64, i32, ptr, i32, ...) +declare token @llvm.experimental.gc.statepoint.p0(i64, i32, ptr, i32, i32, ...) diff --git a/llvm/test/CodeGen/AArch64/strictfp_f16_abi_promote.ll b/llvm/test/CodeGen/AArch64/strictfp_f16_abi_promote.ll index 9fa5208cc8db68ac53a1b3b40e0c964821c34b1c..3db802a2bc35500f8152bfd257859ccb68d41c09 100644 --- a/llvm/test/CodeGen/AArch64/strictfp_f16_abi_promote.ll +++ b/llvm/test/CodeGen/AArch64/strictfp_f16_abi_promote.ll @@ -273,7 +273,7 @@ define void @outgoing_v4f16_return(ptr %ptr) #0 { ; NOFP16-NEXT: strh w0, [x19] ; NOFP16-NEXT: ldp x30, x19, [sp], #16 // 16-byte Folded Reload ; NOFP16-NEXT: ret - %val = call <4 x half> @v4f16_result() + %val = call <4 x half> @v4f16_result() #0 store <4 x half> %val, ptr %ptr ret void } @@ -297,7 +297,7 @@ define void @outgoing_v8f16_return(ptr %ptr) #0 { ; NOFP16-NEXT: strh w0, [x19] ; NOFP16-NEXT: ldp x30, x19, [sp], #16 // 16-byte Folded Reload ; NOFP16-NEXT: ret - %val = call <8 x half> @v8f16_result() + %val = call <8 x half> @v8f16_result() #0 store <8 x half> %val, ptr %ptr ret void } @@ -312,7 +312,7 @@ define half @call_split_type_used_outside_block_v8f16() #0 { ; NOFP16-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload ; NOFP16-NEXT: ret bb0: - %split.ret.type = call <8 x half> @v8f16_result() + %split.ret.type = call <8 x half> @v8f16_result() #0 br label %bb1 bb1: diff --git a/llvm/test/CodeGen/AArch64/tbl-loops.ll b/llvm/test/CodeGen/AArch64/tbl-loops.ll index 4f8a4f7aede3ebaabf230c16fbd78acd13c42fb3..0ad990086551843b2f775a7ee6a0606f1917dbe0 100644 --- a/llvm/test/CodeGen/AArch64/tbl-loops.ll +++ b/llvm/test/CodeGen/AArch64/tbl-loops.ll @@ -41,8 +41,8 @@ define void @loop1(ptr noalias nocapture noundef writeonly %dst, ptr nocapture n ; CHECK-NEXT: fcvtzs v2.4s, v2.4s ; CHECK-NEXT: xtn v1.4h, v1.4s ; CHECK-NEXT: xtn v2.4h, v2.4s -; CHECK-NEXT: xtn v1.8b, v1.8h -; CHECK-NEXT: xtn v2.8b, v2.8h +; CHECK-NEXT: uzp1 v1.8b, v1.8b, v0.8b +; CHECK-NEXT: uzp1 v2.8b, v2.8b, v0.8b ; CHECK-NEXT: mov v1.s[1], v2.s[0] ; CHECK-NEXT: stur d1, [x12, #-4] ; CHECK-NEXT: add x12, x12, #8 diff --git a/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll b/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll index ba367b0dbfde345ac76287e06f3d321f1dd00841..18cd4cc2111a429a387a5cbf2002ca13bd856ff0 100644 --- a/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll +++ b/llvm/test/CodeGen/AArch64/trunc-to-tbl.ll @@ -710,23 +710,23 @@ define void @trunc_v11i64_to_v11i8_in_loop(ptr %A, ptr %dst) { ; CHECK-NEXT: LBB6_1: ; %loop ; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: ldp q4, q1, [x0, #48] -; CHECK-NEXT: add x9, x1, #8 -; CHECK-NEXT: ldp q3, q2, [x0] -; CHECK-NEXT: subs x8, x8, #1 +; CHECK-NEXT: add x9, x1, #10 ; CHECK-NEXT: ldr d0, [x0, #80] +; CHECK-NEXT: ldp q3, q2, [x0] ; CHECK-NEXT: ldr q5, [x0, #32] +; CHECK-NEXT: subs x8, x8, #1 ; CHECK-NEXT: add x0, x0, #128 -; CHECK-NEXT: uzp1.4s v4, v5, v4 -; CHECK-NEXT: uzp1.4s v2, v3, v2 ; CHECK-NEXT: uzp1.4s v0, v1, v0 -; CHECK-NEXT: uzp1.8h v1, v2, v4 +; CHECK-NEXT: uzp1.4s v1, v5, v4 +; CHECK-NEXT: uzp1.4s v2, v3, v2 ; CHECK-NEXT: xtn.4h v0, v0 -; CHECK-NEXT: uzp1.16b v1, v1, v0 -; CHECK-NEXT: xtn.8b v0, v0 -; CHECK-NEXT: st1.h { v1 }[4], [x9] -; CHECK-NEXT: add x9, x1, #10 -; CHECK-NEXT: st1.b { v0 }[2], [x9] -; CHECK-NEXT: str d1, [x1], #16 +; CHECK-NEXT: uzp1.8h v1, v2, v1 +; CHECK-NEXT: uzp1.8b v2, v0, v0 +; CHECK-NEXT: uzp1.16b v0, v1, v0 +; CHECK-NEXT: st1.b { v2 }[2], [x9] +; CHECK-NEXT: add x9, x1, #8 +; CHECK-NEXT: st1.h { v0 }[4], [x9] +; CHECK-NEXT: str d0, [x1], #16 ; CHECK-NEXT: b.eq LBB6_1 ; CHECK-NEXT: ; %bb.2: ; %exit ; CHECK-NEXT: ret @@ -755,7 +755,7 @@ define void @trunc_v11i64_to_v11i8_in_loop(ptr %A, ptr %dst) { ; CHECK-BE-NEXT: xtn v0.4h, v0.4s ; CHECK-BE-NEXT: uzp1 v1.8h, v1.8h, v2.8h ; CHECK-BE-NEXT: uzp1 v1.16b, v1.16b, v0.16b -; CHECK-BE-NEXT: xtn v0.8b, v0.8h +; CHECK-BE-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-BE-NEXT: rev16 v2.16b, v1.16b ; CHECK-BE-NEXT: rev64 v1.16b, v1.16b ; CHECK-BE-NEXT: st1 { v0.b }[2], [x9] @@ -790,7 +790,7 @@ define void @trunc_v11i64_to_v11i8_in_loop(ptr %A, ptr %dst) { ; CHECK-DISABLE-NEXT: xtn v0.4h, v0.4s ; CHECK-DISABLE-NEXT: uzp1 v1.8h, v1.8h, v2.8h ; CHECK-DISABLE-NEXT: uzp1 v1.16b, v1.16b, v0.16b -; CHECK-DISABLE-NEXT: xtn v0.8b, v0.8h +; CHECK-DISABLE-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-DISABLE-NEXT: rev16 v2.16b, v1.16b ; CHECK-DISABLE-NEXT: rev64 v1.16b, v1.16b ; CHECK-DISABLE-NEXT: st1 { v0.b }[2], [x9] diff --git a/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll b/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll index e05c65daf50aae04b5bc175ebbfe32ad91d58f02..f0bbed59405e3f69cc3aad3a8e32e88471302409 100644 --- a/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll +++ b/llvm/test/CodeGen/AArch64/uadd_sat_vec.ll @@ -142,7 +142,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind { ; CHECK-NEXT: movi d0, #0xff00ff00ff00ff ; CHECK-NEXT: uaddl v1.8h, v1.8b, v2.8b ; CHECK-NEXT: umin v0.4h, v1.4h, v0.4h -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [x2] ; CHECK-NEXT: ret %x = load <4 x i8>, ptr %px diff --git a/llvm/test/CodeGen/AArch64/usub_sat_vec.ll b/llvm/test/CodeGen/AArch64/usub_sat_vec.ll index 05f43e7d8427b7b75040002a86cc6b3175ce7949..82c0327219f50421c9850d0e595efff19d2243e7 100644 --- a/llvm/test/CodeGen/AArch64/usub_sat_vec.ll +++ b/llvm/test/CodeGen/AArch64/usub_sat_vec.ll @@ -143,7 +143,7 @@ define void @v4i8(ptr %px, ptr %py, ptr %pz) nounwind { ; CHECK-NEXT: ushll v0.8h, v0.8b, #0 ; CHECK-NEXT: ushll v1.8h, v1.8b, #0 ; CHECK-NEXT: uqsub v0.4h, v0.4h, v1.4h -; CHECK-NEXT: xtn v0.8b, v0.8h +; CHECK-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; CHECK-NEXT: str s0, [x2] ; CHECK-NEXT: ret %x = load <4 x i8>, ptr %px diff --git a/llvm/test/CodeGen/AArch64/vcvt-oversize.ll b/llvm/test/CodeGen/AArch64/vcvt-oversize.ll index 380bdbcc7f74081d6385c4f9e484a519c8518c59..611940546bc1a2ec3c1bcf2236d842256dbbded0 100644 --- a/llvm/test/CodeGen/AArch64/vcvt-oversize.ll +++ b/llvm/test/CodeGen/AArch64/vcvt-oversize.ll @@ -9,9 +9,8 @@ define <8 x i8> @float_to_i8(ptr %in) { ; CHECK-NEXT: fadd v0.4s, v0.4s, v0.4s ; CHECK-NEXT: fcvtzs v0.4s, v0.4s ; CHECK-NEXT: fcvtzs v1.4s, v1.4s -; CHECK-NEXT: xtn v0.4h, v0.4s -; CHECK-NEXT: xtn v1.4h, v1.4s -; CHECK-NEXT: uzp1 v0.8b, v1.8b, v0.8b +; CHECK-NEXT: uzp1 v0.8h, v1.8h, v0.8h +; CHECK-NEXT: xtn v0.8b, v0.8h ; CHECK-NEXT: ret %l = load <8 x float>, ptr %in %scale = fmul <8 x float> %l, <float 2.0, float 2.0, float 2.0, float 2.0, float 2.0, float 2.0, float 2.0, float 2.0> diff --git a/llvm/test/CodeGen/AArch64/vec-combine-compare-truncate-store.ll b/llvm/test/CodeGen/AArch64/vec-combine-compare-truncate-store.ll index 9c6ab8da0fa756e2edb446d3a29316f04e873f80..dd7a9c6d7768bc3b83d2f3947eca3dfc3e94e9fe 100644 --- a/llvm/test/CodeGen/AArch64/vec-combine-compare-truncate-store.ll +++ b/llvm/test/CodeGen/AArch64/vec-combine-compare-truncate-store.ll @@ -210,7 +210,7 @@ define void @no_combine_for_non_bool_truncate(<4 x i32> %vec, ptr %out) { ; CHECK-LABEL: no_combine_for_non_bool_truncate: ; CHECK: ; %bb.0: ; CHECK-NEXT: xtn.4h v0, v0 -; CHECK-NEXT: xtn.8b v0, v0 +; CHECK-NEXT: uzp1.8b v0, v0, v0 ; CHECK-NEXT: str s0, [x0] ; CHECK-NEXT: ret diff --git a/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll b/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll index 90328f73f86b5154686ec2864ef1d5afadf38329..71d55df6651768521963736dd7d0fed696fc25fb 100644 --- a/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll +++ b/llvm/test/CodeGen/AArch64/vec3-loads-ext-trunc-stores.ll @@ -410,7 +410,7 @@ define void @store_trunc_from_64bits(ptr %src, ptr %dst) { ; BE-NEXT: ldrh w8, [x0, #4] ; BE-NEXT: rev32 v0.4h, v0.4h ; BE-NEXT: mov v0.h[2], w8 -; BE-NEXT: xtn v0.8b, v0.8h +; BE-NEXT: uzp1 v0.8b, v0.8b, v0.8b ; BE-NEXT: rev32 v0.16b, v0.16b ; BE-NEXT: str s0, [sp, #12] ; BE-NEXT: ldrh w9, [sp, #12] @@ -456,7 +456,7 @@ define void @store_trunc_add_from_64bits(ptr %src, ptr %dst) { ; BE-NEXT: add x8, x8, :lo12:.LCPI11_0 ; BE-NEXT: ld1 { v1.4h }, [x8] ; BE-NEXT: add v0.4h, v0.4h, v1.4h -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -638,7 +638,7 @@ define void @shift_trunc_store(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -672,7 +672,7 @@ define void @shift_trunc_store_default_align(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -706,7 +706,7 @@ define void @shift_trunc_store_align_4(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -741,7 +741,7 @@ define void @shift_trunc_store_const_offset_1(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -777,7 +777,7 @@ define void @shift_trunc_store_const_offset_3(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -801,7 +801,7 @@ define void @shift_trunc_volatile_store(ptr %src, ptr %dst) { ; CHECK-NEXT: .cfi_def_cfa_offset 16 ; CHECK-NEXT: ldr q0, [x0] ; CHECK-NEXT: shrn.4h v0, v0, #16 -; CHECK-NEXT: xtn.8b v1, v0 +; CHECK-NEXT: uzp1.8b v1, v0, v0 ; CHECK-NEXT: umov.h w8, v0[2] ; CHECK-NEXT: str s1, [sp, #12] ; CHECK-NEXT: ldrh w9, [sp, #12] @@ -816,7 +816,7 @@ define void @shift_trunc_volatile_store(ptr %src, ptr %dst) { ; BE-NEXT: .cfi_def_cfa_offset 16 ; BE-NEXT: ld1 { v0.4s }, [x0] ; BE-NEXT: shrn v0.4h, v0.4s, #16 -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #12] @@ -868,7 +868,7 @@ define void @load_v3i8_zext_to_3xi32_add_trunc_store(ptr %src) { ; BE-NEXT: ushll v0.8h, v0.8b, #0 ; BE-NEXT: ld1 { v0.b }[4], [x9] ; BE-NEXT: add v0.4h, v0.4h, v1.4h -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #8] @@ -921,7 +921,7 @@ define void @load_v3i8_sext_to_3xi32_add_trunc_store(ptr %src) { ; BE-NEXT: ushll v0.8h, v0.8b, #0 ; BE-NEXT: ld1 { v0.b }[4], [x9] ; BE-NEXT: add v0.4h, v0.4h, v1.4h -; BE-NEXT: xtn v1.8b, v0.8h +; BE-NEXT: uzp1 v1.8b, v0.8b, v0.8b ; BE-NEXT: umov w8, v0.h[2] ; BE-NEXT: rev32 v1.16b, v1.16b ; BE-NEXT: str s1, [sp, #8] diff --git a/llvm/test/CodeGen/AArch64/vecreduce-add.ll b/llvm/test/CodeGen/AArch64/vecreduce-add.ll index 66b49466cc73612ff55c0e8369827cdddf9c1386..66ef436f48c6373e67ec5a1500772cd2319a70b2 100644 --- a/llvm/test/CodeGen/AArch64/vecreduce-add.ll +++ b/llvm/test/CodeGen/AArch64/vecreduce-add.ll @@ -4,11 +4,6 @@ ; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel -global-isel-abort=2 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI,CHECK-GI-BASE ; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel -global-isel-abort=2 %s -o - -mattr=+dotprod 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI,CHECK-GI-DOT -; CHECK-GI-BASE: warning: Instruction selection used fallback path for test_udot_v24i8 -; CHECK-GI-BASE-NEXT: warning: Instruction selection used fallback path for test_udot_v48i8 -; CHECK-GI-BASE-NEXT: warning: Instruction selection used fallback path for test_sdot_v24i8 -; CHECK-GI-BASE-NEXT: warning: Instruction selection used fallback path for test_sdot_v48i8 - define i32 @addv_v2i32(<2 x i32> %a) { ; CHECK-LABEL: addv_v2i32: ; CHECK: // %bb.0: // %entry @@ -2070,126 +2065,50 @@ define i32 @test_udot_v24i8(ptr %p1, ptr %p2) { ; CHECK-GI-BASE: // %bb.0: // %entry ; CHECK-GI-BASE-NEXT: ldr q0, [x0] ; CHECK-GI-BASE-NEXT: ldr q1, [x1] -; CHECK-GI-BASE-NEXT: ldr d4, [x0, #16] -; CHECK-GI-BASE-NEXT: ldr d5, [x1, #16] -; CHECK-GI-BASE-NEXT: ushll v2.8h, v0.8b, #0 -; CHECK-GI-BASE-NEXT: ushll v3.8h, v1.8b, #0 +; CHECK-GI-BASE-NEXT: ldr d2, [x0, #16] +; CHECK-GI-BASE-NEXT: ldr d3, [x1, #16] +; CHECK-GI-BASE-NEXT: ushll v4.8h, v0.8b, #0 ; CHECK-GI-BASE-NEXT: ushll2 v0.8h, v0.16b, #0 +; CHECK-GI-BASE-NEXT: ushll v5.8h, v1.8b, #0 +; CHECK-GI-BASE-NEXT: ushll v2.8h, v2.8b, #0 ; CHECK-GI-BASE-NEXT: ushll2 v1.8h, v1.16b, #0 -; CHECK-GI-BASE-NEXT: umull v6.4s, v3.4h, v2.4h -; CHECK-GI-BASE-NEXT: umull2 v2.4s, v3.8h, v2.8h -; CHECK-GI-BASE-NEXT: ushll v3.8h, v4.8b, #0 -; CHECK-GI-BASE-NEXT: ushll v4.8h, v5.8b, #0 -; CHECK-GI-BASE-NEXT: umlal2 v2.4s, v4.8h, v3.8h -; CHECK-GI-BASE-NEXT: umlal v6.4s, v4.4h, v3.4h -; CHECK-GI-BASE-NEXT: umlal2 v2.4s, v1.8h, v0.8h -; CHECK-GI-BASE-NEXT: umlal v6.4s, v1.4h, v0.4h -; CHECK-GI-BASE-NEXT: add v0.4s, v6.4s, v2.4s +; CHECK-GI-BASE-NEXT: ushll v3.8h, v3.8b, #0 +; CHECK-GI-BASE-NEXT: umull v6.4s, v5.4h, v4.4h +; CHECK-GI-BASE-NEXT: umull2 v4.4s, v5.8h, v4.8h +; CHECK-GI-BASE-NEXT: umull2 v5.4s, v1.8h, v0.8h +; CHECK-GI-BASE-NEXT: umull v7.4s, v3.4h, v2.4h +; CHECK-GI-BASE-NEXT: umull v0.4s, v1.4h, v0.4h +; CHECK-GI-BASE-NEXT: umull2 v1.4s, v3.8h, v2.8h +; CHECK-GI-BASE-NEXT: addv s2, v6.4s +; CHECK-GI-BASE-NEXT: addv s3, v4.4s +; CHECK-GI-BASE-NEXT: addv s4, v5.4s +; CHECK-GI-BASE-NEXT: addv s5, v7.4s ; CHECK-GI-BASE-NEXT: addv s0, v0.4s -; CHECK-GI-BASE-NEXT: fmov w0, s0 +; CHECK-GI-BASE-NEXT: addv s1, v1.4s +; CHECK-GI-BASE-NEXT: fmov w8, s2 +; CHECK-GI-BASE-NEXT: fmov w9, s3 +; CHECK-GI-BASE-NEXT: fmov w10, s4 +; CHECK-GI-BASE-NEXT: fmov w11, s5 +; CHECK-GI-BASE-NEXT: add w8, w8, w9 +; CHECK-GI-BASE-NEXT: fmov w9, s0 +; CHECK-GI-BASE-NEXT: add w10, w10, w11 +; CHECK-GI-BASE-NEXT: fmov w11, s1 +; CHECK-GI-BASE-NEXT: add w8, w8, w9 +; CHECK-GI-BASE-NEXT: add w9, w10, w11 +; CHECK-GI-BASE-NEXT: add w0, w8, w9 ; CHECK-GI-BASE-NEXT: ret ; ; CHECK-GI-DOT-LABEL: test_udot_v24i8: ; CHECK-GI-DOT: // %bb.0: // %entry -; CHECK-GI-DOT-NEXT: ldr b1, [x0] -; CHECK-GI-DOT-NEXT: ldr b3, [x0, #1] ; CHECK-GI-DOT-NEXT: movi v0.2d, #0000000000000000 -; CHECK-GI-DOT-NEXT: ldr b2, [x1] -; CHECK-GI-DOT-NEXT: ldr b4, [x1, #1] -; CHECK-GI-DOT-NEXT: ldr b5, [x0, #8] -; CHECK-GI-DOT-NEXT: mov v1.b[1], v3.b[0] -; CHECK-GI-DOT-NEXT: ldr b3, [x0, #2] -; CHECK-GI-DOT-NEXT: ldr b6, [x1, #8] -; CHECK-GI-DOT-NEXT: mov v2.b[1], v4.b[0] -; CHECK-GI-DOT-NEXT: ldr b4, [x1, #2] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #17] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #17] -; CHECK-GI-DOT-NEXT: mov v1.b[2], v3.b[0] -; CHECK-GI-DOT-NEXT: ldr b3, [x0, #3] -; CHECK-GI-DOT-NEXT: mov v2.b[2], v4.b[0] -; CHECK-GI-DOT-NEXT: ldr b4, [x1, #3] -; CHECK-GI-DOT-NEXT: mov v1.b[3], v3.b[0] -; CHECK-GI-DOT-NEXT: ldr b3, [x0, #4] -; CHECK-GI-DOT-NEXT: mov v2.b[3], v4.b[0] -; CHECK-GI-DOT-NEXT: ldr b4, [x1, #4] -; CHECK-GI-DOT-NEXT: mov v1.b[4], v3.b[0] -; CHECK-GI-DOT-NEXT: ldr b3, [x0, #5] -; CHECK-GI-DOT-NEXT: mov v2.b[4], v4.b[0] -; CHECK-GI-DOT-NEXT: ldr b4, [x1, #5] -; CHECK-GI-DOT-NEXT: mov v1.b[5], v3.b[0] -; CHECK-GI-DOT-NEXT: ldr b3, [x0, #6] -; CHECK-GI-DOT-NEXT: mov v2.b[5], v4.b[0] -; CHECK-GI-DOT-NEXT: ldr b4, [x1, #6] -; CHECK-GI-DOT-NEXT: mov v1.b[6], v3.b[0] -; CHECK-GI-DOT-NEXT: ldr b3, [x0, #7] -; CHECK-GI-DOT-NEXT: mov v2.b[6], v4.b[0] -; CHECK-GI-DOT-NEXT: ldr b4, [x1, #7] -; CHECK-GI-DOT-NEXT: mov v1.b[7], v3.b[0] -; CHECK-GI-DOT-NEXT: ldr b3, [x0, #16] -; CHECK-GI-DOT-NEXT: mov v2.b[7], v4.b[0] -; CHECK-GI-DOT-NEXT: ldr b4, [x1, #16] -; CHECK-GI-DOT-NEXT: mov v3.b[1], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #18] -; CHECK-GI-DOT-NEXT: mov v4.b[1], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #18] -; CHECK-GI-DOT-NEXT: mov v1.b[8], v5.b[0] -; CHECK-GI-DOT-NEXT: ldr b5, [x0, #9] -; CHECK-GI-DOT-NEXT: mov v2.b[8], v6.b[0] -; CHECK-GI-DOT-NEXT: ldr b6, [x1, #9] -; CHECK-GI-DOT-NEXT: mov v3.b[2], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #19] -; CHECK-GI-DOT-NEXT: mov v4.b[2], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #19] -; CHECK-GI-DOT-NEXT: mov v1.b[9], v5.b[0] -; CHECK-GI-DOT-NEXT: ldr b5, [x0, #10] -; CHECK-GI-DOT-NEXT: mov v2.b[9], v6.b[0] -; CHECK-GI-DOT-NEXT: ldr b6, [x1, #10] -; CHECK-GI-DOT-NEXT: mov v3.b[3], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #20] -; CHECK-GI-DOT-NEXT: mov v4.b[3], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #20] -; CHECK-GI-DOT-NEXT: mov v1.b[10], v5.b[0] -; CHECK-GI-DOT-NEXT: ldr b5, [x0, #11] -; CHECK-GI-DOT-NEXT: mov v2.b[10], v6.b[0] -; CHECK-GI-DOT-NEXT: ldr b6, [x1, #11] -; CHECK-GI-DOT-NEXT: mov v3.b[4], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #21] -; CHECK-GI-DOT-NEXT: mov v4.b[4], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #21] -; CHECK-GI-DOT-NEXT: mov v1.b[11], v5.b[0] -; CHECK-GI-DOT-NEXT: ldr b5, [x0, #12] -; CHECK-GI-DOT-NEXT: mov v2.b[11], v6.b[0] -; CHECK-GI-DOT-NEXT: ldr b6, [x1, #12] -; CHECK-GI-DOT-NEXT: mov v3.b[5], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #22] -; CHECK-GI-DOT-NEXT: mov v4.b[5], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #22] -; CHECK-GI-DOT-NEXT: mov v1.b[12], v5.b[0] -; CHECK-GI-DOT-NEXT: ldr b5, [x0, #13] -; CHECK-GI-DOT-NEXT: mov v2.b[12], v6.b[0] -; CHECK-GI-DOT-NEXT: ldr b6, [x1, #13] -; CHECK-GI-DOT-NEXT: mov v3.b[6], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #23] -; CHECK-GI-DOT-NEXT: mov v4.b[6], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #23] -; CHECK-GI-DOT-NEXT: mov v1.b[13], v5.b[0] -; CHECK-GI-DOT-NEXT: ldr b5, [x0, #14] -; CHECK-GI-DOT-NEXT: mov v2.b[13], v6.b[0] -; CHECK-GI-DOT-NEXT: ldr b6, [x1, #14] -; CHECK-GI-DOT-NEXT: mov v3.b[7], v7.b[0] -; CHECK-GI-DOT-NEXT: mov v4.b[7], v16.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[14], v5.b[0] -; CHECK-GI-DOT-NEXT: ldr b5, [x0, #15] -; CHECK-GI-DOT-NEXT: mov v2.b[14], v6.b[0] -; CHECK-GI-DOT-NEXT: ldr b6, [x1, #15] -; CHECK-GI-DOT-NEXT: fmov d3, d3 -; CHECK-GI-DOT-NEXT: fmov d4, d4 -; CHECK-GI-DOT-NEXT: mov v1.b[15], v5.b[0] -; CHECK-GI-DOT-NEXT: movi v5.2d, #0000000000000000 -; CHECK-GI-DOT-NEXT: mov v2.b[15], v6.b[0] -; CHECK-GI-DOT-NEXT: udot v0.4s, v4.16b, v3.16b -; CHECK-GI-DOT-NEXT: udot v5.4s, v2.16b, v1.16b -; CHECK-GI-DOT-NEXT: add v0.4s, v5.4s, v0.4s +; CHECK-GI-DOT-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-DOT-NEXT: ldr q2, [x0] +; CHECK-GI-DOT-NEXT: ldr d3, [x0, #16] +; CHECK-GI-DOT-NEXT: ldr q4, [x1] +; CHECK-GI-DOT-NEXT: ldr d5, [x1, #16] +; CHECK-GI-DOT-NEXT: udot v1.4s, v4.16b, v2.16b +; CHECK-GI-DOT-NEXT: udot v0.4s, v5.16b, v3.16b +; CHECK-GI-DOT-NEXT: add v0.4s, v1.4s, v0.4s ; CHECK-GI-DOT-NEXT: addv s0, v0.4s ; CHECK-GI-DOT-NEXT: fmov w0, s0 ; CHECK-GI-DOT-NEXT: ret @@ -2257,243 +2176,91 @@ define i32 @test_udot_v48i8(ptr %p1, ptr %p2) { ; ; CHECK-GI-BASE-LABEL: test_udot_v48i8: ; CHECK-GI-BASE: // %bb.0: // %entry -; CHECK-GI-BASE-NEXT: ldp q0, q4, [x1] -; CHECK-GI-BASE-NEXT: ldr q2, [x0, #32] -; CHECK-GI-BASE-NEXT: ldp q1, q3, [x0] -; CHECK-GI-BASE-NEXT: ldr q7, [x1, #32] -; CHECK-GI-BASE-NEXT: ushll2 v16.8h, v2.16b, #0 -; CHECK-GI-BASE-NEXT: ushll2 v6.8h, v0.16b, #0 -; CHECK-GI-BASE-NEXT: ushll v0.8h, v0.8b, #0 -; CHECK-GI-BASE-NEXT: ushll2 v17.8h, v7.16b, #0 -; CHECK-GI-BASE-NEXT: ushll2 v5.8h, v1.16b, #0 -; CHECK-GI-BASE-NEXT: ushll v1.8h, v1.8b, #0 -; CHECK-GI-BASE-NEXT: umull2 v18.4s, v6.8h, v5.8h -; CHECK-GI-BASE-NEXT: umull v19.4s, v0.4h, v1.4h -; CHECK-GI-BASE-NEXT: umull v5.4s, v6.4h, v5.4h -; CHECK-GI-BASE-NEXT: umull2 v0.4s, v0.8h, v1.8h -; CHECK-GI-BASE-NEXT: ushll v1.8h, v2.8b, #0 -; CHECK-GI-BASE-NEXT: ushll v2.8h, v7.8b, #0 -; CHECK-GI-BASE-NEXT: ushll2 v6.8h, v3.16b, #0 -; CHECK-GI-BASE-NEXT: ushll2 v7.8h, v4.16b, #0 -; CHECK-GI-BASE-NEXT: umlal2 v18.4s, v17.8h, v16.8h -; CHECK-GI-BASE-NEXT: umlal v5.4s, v17.4h, v16.4h -; CHECK-GI-BASE-NEXT: umlal v19.4s, v2.4h, v1.4h -; CHECK-GI-BASE-NEXT: umlal2 v0.4s, v2.8h, v1.8h -; CHECK-GI-BASE-NEXT: ushll v1.8h, v3.8b, #0 -; CHECK-GI-BASE-NEXT: ushll v2.8h, v4.8b, #0 -; CHECK-GI-BASE-NEXT: umlal2 v18.4s, v7.8h, v6.8h -; CHECK-GI-BASE-NEXT: umlal v5.4s, v7.4h, v6.4h -; CHECK-GI-BASE-NEXT: umlal v19.4s, v2.4h, v1.4h -; CHECK-GI-BASE-NEXT: umlal2 v0.4s, v2.8h, v1.8h -; CHECK-GI-BASE-NEXT: add v1.4s, v19.4s, v5.4s -; CHECK-GI-BASE-NEXT: add v0.4s, v0.4s, v18.4s -; CHECK-GI-BASE-NEXT: add v0.4s, v1.4s, v0.4s +; CHECK-GI-BASE-NEXT: ldp q0, q3, [x1] +; CHECK-GI-BASE-NEXT: ldr q6, [x1, #32] +; CHECK-GI-BASE-NEXT: ldp q1, q2, [x0] +; CHECK-GI-BASE-NEXT: ldr q17, [x0, #32] +; CHECK-GI-BASE-NEXT: ushll v4.8h, v0.8b, #0 +; CHECK-GI-BASE-NEXT: ushll2 v0.8h, v0.16b, #0 +; CHECK-GI-BASE-NEXT: ushll v7.8h, v3.8b, #0 +; CHECK-GI-BASE-NEXT: ushll v5.8h, v1.8b, #0 +; CHECK-GI-BASE-NEXT: ushll2 v1.8h, v1.16b, #0 +; CHECK-GI-BASE-NEXT: ushll v16.8h, v2.8b, #0 +; CHECK-GI-BASE-NEXT: ushll2 v3.8h, v3.16b, #0 +; CHECK-GI-BASE-NEXT: ushll2 v2.8h, v2.16b, #0 +; CHECK-GI-BASE-NEXT: umull v18.4s, v4.4h, v5.4h +; CHECK-GI-BASE-NEXT: umull2 v4.4s, v4.8h, v5.8h +; CHECK-GI-BASE-NEXT: umull2 v19.4s, v0.8h, v1.8h +; CHECK-GI-BASE-NEXT: umull v20.4s, v7.4h, v16.4h +; CHECK-GI-BASE-NEXT: umull v0.4s, v0.4h, v1.4h +; CHECK-GI-BASE-NEXT: ushll v5.8h, v6.8b, #0 +; CHECK-GI-BASE-NEXT: ushll v1.8h, v17.8b, #0 +; CHECK-GI-BASE-NEXT: umull2 v7.4s, v7.8h, v16.8h +; CHECK-GI-BASE-NEXT: ushll2 v6.8h, v6.16b, #0 +; CHECK-GI-BASE-NEXT: ushll2 v17.8h, v17.16b, #0 +; CHECK-GI-BASE-NEXT: addv s16, v18.4s +; CHECK-GI-BASE-NEXT: addv s4, v4.4s +; CHECK-GI-BASE-NEXT: umull v18.4s, v3.4h, v2.4h +; CHECK-GI-BASE-NEXT: umull2 v2.4s, v3.8h, v2.8h +; CHECK-GI-BASE-NEXT: addv s3, v19.4s +; CHECK-GI-BASE-NEXT: umull v19.4s, v5.4h, v1.4h +; CHECK-GI-BASE-NEXT: umull2 v1.4s, v5.8h, v1.8h +; CHECK-GI-BASE-NEXT: addv s5, v20.4s ; CHECK-GI-BASE-NEXT: addv s0, v0.4s -; CHECK-GI-BASE-NEXT: fmov w0, s0 +; CHECK-GI-BASE-NEXT: addv s7, v7.4s +; CHECK-GI-BASE-NEXT: umull v20.4s, v6.4h, v17.4h +; CHECK-GI-BASE-NEXT: umull2 v6.4s, v6.8h, v17.8h +; CHECK-GI-BASE-NEXT: fmov w8, s16 +; CHECK-GI-BASE-NEXT: fmov w9, s4 +; CHECK-GI-BASE-NEXT: fmov w10, s3 +; CHECK-GI-BASE-NEXT: addv s3, v18.4s +; CHECK-GI-BASE-NEXT: addv s2, v2.4s +; CHECK-GI-BASE-NEXT: fmov w11, s5 +; CHECK-GI-BASE-NEXT: addv s4, v19.4s +; CHECK-GI-BASE-NEXT: add w8, w8, w9 +; CHECK-GI-BASE-NEXT: fmov w9, s0 +; CHECK-GI-BASE-NEXT: addv s0, v1.4s +; CHECK-GI-BASE-NEXT: addv s1, v20.4s +; CHECK-GI-BASE-NEXT: addv s5, v6.4s +; CHECK-GI-BASE-NEXT: add w10, w10, w11 +; CHECK-GI-BASE-NEXT: fmov w11, s3 +; CHECK-GI-BASE-NEXT: fmov w12, s2 +; CHECK-GI-BASE-NEXT: add w8, w8, w9 +; CHECK-GI-BASE-NEXT: fmov w9, s7 +; CHECK-GI-BASE-NEXT: add w9, w10, w9 +; CHECK-GI-BASE-NEXT: add w10, w11, w12 +; CHECK-GI-BASE-NEXT: fmov w11, s4 +; CHECK-GI-BASE-NEXT: add w8, w8, w9 +; CHECK-GI-BASE-NEXT: add w9, w10, w11 +; CHECK-GI-BASE-NEXT: fmov w10, s0 +; CHECK-GI-BASE-NEXT: fmov w11, s5 +; CHECK-GI-BASE-NEXT: add w9, w9, w10 +; CHECK-GI-BASE-NEXT: fmov w10, s1 +; CHECK-GI-BASE-NEXT: add w8, w8, w9 +; CHECK-GI-BASE-NEXT: add w9, w10, w11 +; CHECK-GI-BASE-NEXT: add w0, w8, w9 ; CHECK-GI-BASE-NEXT: ret ; ; CHECK-GI-DOT-LABEL: test_udot_v48i8: ; CHECK-GI-DOT: // %bb.0: // %entry -; CHECK-GI-DOT-NEXT: ldr b1, [x0] -; CHECK-GI-DOT-NEXT: ldr b5, [x0, #1] ; CHECK-GI-DOT-NEXT: movi v0.2d, #0000000000000000 -; CHECK-GI-DOT-NEXT: ldr b2, [x0, #16] -; CHECK-GI-DOT-NEXT: ldr b6, [x0, #17] -; CHECK-GI-DOT-NEXT: ldr b4, [x1] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #1] -; CHECK-GI-DOT-NEXT: mov v1.b[1], v5.b[0] -; CHECK-GI-DOT-NEXT: ldr b5, [x1, #16] -; CHECK-GI-DOT-NEXT: ldr b18, [x1, #17] -; CHECK-GI-DOT-NEXT: mov v2.b[1], v6.b[0] -; CHECK-GI-DOT-NEXT: ldr b3, [x0, #32] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #33] -; CHECK-GI-DOT-NEXT: mov v4.b[1], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b6, [x1, #32] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #33] -; CHECK-GI-DOT-NEXT: mov v5.b[1], v18.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x0, #2] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #18] -; CHECK-GI-DOT-NEXT: mov v3.b[1], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #2] -; CHECK-GI-DOT-NEXT: mov v6.b[1], v16.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[2], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #18] -; CHECK-GI-DOT-NEXT: ldr b17, [x0, #34] -; CHECK-GI-DOT-NEXT: mov v2.b[2], v18.b[0] -; CHECK-GI-DOT-NEXT: ldr b18, [x1, #34] -; CHECK-GI-DOT-NEXT: mov v4.b[2], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #3] -; CHECK-GI-DOT-NEXT: mov v5.b[2], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x0, #19] -; CHECK-GI-DOT-NEXT: mov v3.b[2], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #19] -; CHECK-GI-DOT-NEXT: mov v6.b[2], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[3], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #3] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #35] -; CHECK-GI-DOT-NEXT: mov v2.b[3], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #35] -; CHECK-GI-DOT-NEXT: mov v4.b[3], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #4] -; CHECK-GI-DOT-NEXT: mov v5.b[3], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x0, #20] -; CHECK-GI-DOT-NEXT: mov v3.b[3], v18.b[0] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #36] -; CHECK-GI-DOT-NEXT: mov v6.b[3], v16.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[4], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #4] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #20] -; CHECK-GI-DOT-NEXT: mov v2.b[4], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #36] -; CHECK-GI-DOT-NEXT: mov v4.b[4], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #5] -; CHECK-GI-DOT-NEXT: mov v5.b[4], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x0, #21] -; CHECK-GI-DOT-NEXT: mov v3.b[4], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[4], v17.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[5], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #5] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #21] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #37] -; CHECK-GI-DOT-NEXT: mov v2.b[5], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #37] -; CHECK-GI-DOT-NEXT: mov v4.b[5], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #6] -; CHECK-GI-DOT-NEXT: mov v5.b[5], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x0, #22] -; CHECK-GI-DOT-NEXT: mov v3.b[5], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[5], v16.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[6], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #6] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #22] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #38] -; CHECK-GI-DOT-NEXT: mov v2.b[6], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #38] -; CHECK-GI-DOT-NEXT: mov v4.b[6], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #7] -; CHECK-GI-DOT-NEXT: mov v5.b[6], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x0, #23] -; CHECK-GI-DOT-NEXT: mov v3.b[6], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[6], v17.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[7], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #7] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #23] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #39] -; CHECK-GI-DOT-NEXT: mov v2.b[7], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #39] -; CHECK-GI-DOT-NEXT: mov v4.b[7], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #8] -; CHECK-GI-DOT-NEXT: mov v5.b[7], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x0, #24] -; CHECK-GI-DOT-NEXT: mov v3.b[7], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[7], v16.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[8], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #8] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #24] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #40] -; CHECK-GI-DOT-NEXT: mov v2.b[8], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #40] -; CHECK-GI-DOT-NEXT: mov v4.b[8], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #9] -; CHECK-GI-DOT-NEXT: mov v5.b[8], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x0, #25] -; CHECK-GI-DOT-NEXT: mov v3.b[8], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[8], v17.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[9], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #9] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #25] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #41] -; CHECK-GI-DOT-NEXT: mov v2.b[9], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #41] -; CHECK-GI-DOT-NEXT: mov v4.b[9], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #10] -; CHECK-GI-DOT-NEXT: mov v5.b[9], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x0, #26] -; CHECK-GI-DOT-NEXT: mov v3.b[9], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[9], v16.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[10], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #10] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #26] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #42] -; CHECK-GI-DOT-NEXT: mov v2.b[10], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #42] -; CHECK-GI-DOT-NEXT: mov v4.b[10], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #11] -; CHECK-GI-DOT-NEXT: mov v5.b[10], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x0, #27] -; CHECK-GI-DOT-NEXT: mov v3.b[10], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[10], v17.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[11], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #11] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #27] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #43] -; CHECK-GI-DOT-NEXT: mov v2.b[11], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #43] -; CHECK-GI-DOT-NEXT: mov v4.b[11], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #12] -; CHECK-GI-DOT-NEXT: mov v5.b[11], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x0, #28] -; CHECK-GI-DOT-NEXT: mov v3.b[11], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[11], v16.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[12], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #12] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #28] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #44] -; CHECK-GI-DOT-NEXT: mov v2.b[12], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #44] -; CHECK-GI-DOT-NEXT: mov v4.b[12], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #13] -; CHECK-GI-DOT-NEXT: mov v5.b[12], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x0, #29] -; CHECK-GI-DOT-NEXT: mov v3.b[12], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[12], v17.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[13], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #13] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #29] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #45] -; CHECK-GI-DOT-NEXT: mov v2.b[13], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #45] -; CHECK-GI-DOT-NEXT: mov v4.b[13], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #14] -; CHECK-GI-DOT-NEXT: mov v5.b[13], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x0, #30] -; CHECK-GI-DOT-NEXT: mov v3.b[13], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[13], v16.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[14], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #14] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #30] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #46] -; CHECK-GI-DOT-NEXT: mov v2.b[14], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #46] -; CHECK-GI-DOT-NEXT: mov v4.b[14], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #15] -; CHECK-GI-DOT-NEXT: mov v5.b[14], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x0, #31] -; CHECK-GI-DOT-NEXT: mov v3.b[14], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[14], v17.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[15], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #15] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #31] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #47] -; CHECK-GI-DOT-NEXT: mov v2.b[15], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #47] -; CHECK-GI-DOT-NEXT: mov v4.b[15], v7.b[0] -; CHECK-GI-DOT-NEXT: movi v7.2d, #0000000000000000 -; CHECK-GI-DOT-NEXT: mov v5.b[15], v17.b[0] -; CHECK-GI-DOT-NEXT: mov v3.b[15], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[15], v16.b[0] -; CHECK-GI-DOT-NEXT: movi v16.2d, #0000000000000000 -; CHECK-GI-DOT-NEXT: udot v0.4s, v4.16b, v1.16b -; CHECK-GI-DOT-NEXT: udot v7.4s, v5.16b, v2.16b -; CHECK-GI-DOT-NEXT: udot v16.4s, v6.16b, v3.16b +; CHECK-GI-DOT-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-DOT-NEXT: ldr q7, [x0, #32] +; CHECK-GI-DOT-NEXT: ldp q3, q4, [x0] +; CHECK-GI-DOT-NEXT: movi v2.2d, #0000000000000000 +; CHECK-GI-DOT-NEXT: ldp q5, q6, [x1] +; CHECK-GI-DOT-NEXT: ldr q16, [x1, #32] +; CHECK-GI-DOT-NEXT: udot v0.4s, v5.16b, v3.16b +; CHECK-GI-DOT-NEXT: udot v1.4s, v6.16b, v4.16b +; CHECK-GI-DOT-NEXT: udot v2.4s, v16.16b, v7.16b ; CHECK-GI-DOT-NEXT: addv s0, v0.4s -; CHECK-GI-DOT-NEXT: addv s1, v7.4s -; CHECK-GI-DOT-NEXT: addv s2, v16.4s +; CHECK-GI-DOT-NEXT: addv s1, v1.4s +; CHECK-GI-DOT-NEXT: addv s2, v2.4s ; CHECK-GI-DOT-NEXT: fmov w8, s0 ; CHECK-GI-DOT-NEXT: fmov w9, s1 -; CHECK-GI-DOT-NEXT: fmov w10, s2 ; CHECK-GI-DOT-NEXT: add w8, w8, w9 -; CHECK-GI-DOT-NEXT: add w0, w8, w10 +; CHECK-GI-DOT-NEXT: fmov w9, s2 +; CHECK-GI-DOT-NEXT: add w0, w8, w9 ; CHECK-GI-DOT-NEXT: ret entry: %a = load <48 x i8>, ptr %p1 @@ -2648,126 +2415,50 @@ define i32 @test_sdot_v24i8(ptr %p1, ptr %p2) { ; CHECK-GI-BASE: // %bb.0: // %entry ; CHECK-GI-BASE-NEXT: ldr q0, [x0] ; CHECK-GI-BASE-NEXT: ldr q1, [x1] -; CHECK-GI-BASE-NEXT: ldr d4, [x0, #16] -; CHECK-GI-BASE-NEXT: ldr d5, [x1, #16] -; CHECK-GI-BASE-NEXT: sshll v2.8h, v0.8b, #0 -; CHECK-GI-BASE-NEXT: sshll v3.8h, v1.8b, #0 +; CHECK-GI-BASE-NEXT: ldr d2, [x0, #16] +; CHECK-GI-BASE-NEXT: ldr d3, [x1, #16] +; CHECK-GI-BASE-NEXT: sshll v4.8h, v0.8b, #0 ; CHECK-GI-BASE-NEXT: sshll2 v0.8h, v0.16b, #0 +; CHECK-GI-BASE-NEXT: sshll v5.8h, v1.8b, #0 +; CHECK-GI-BASE-NEXT: sshll v2.8h, v2.8b, #0 ; CHECK-GI-BASE-NEXT: sshll2 v1.8h, v1.16b, #0 -; CHECK-GI-BASE-NEXT: smull v6.4s, v3.4h, v2.4h -; CHECK-GI-BASE-NEXT: smull2 v2.4s, v3.8h, v2.8h -; CHECK-GI-BASE-NEXT: sshll v3.8h, v4.8b, #0 -; CHECK-GI-BASE-NEXT: sshll v4.8h, v5.8b, #0 -; CHECK-GI-BASE-NEXT: smlal2 v2.4s, v4.8h, v3.8h -; CHECK-GI-BASE-NEXT: smlal v6.4s, v4.4h, v3.4h -; CHECK-GI-BASE-NEXT: smlal2 v2.4s, v1.8h, v0.8h -; CHECK-GI-BASE-NEXT: smlal v6.4s, v1.4h, v0.4h -; CHECK-GI-BASE-NEXT: add v0.4s, v6.4s, v2.4s +; CHECK-GI-BASE-NEXT: sshll v3.8h, v3.8b, #0 +; CHECK-GI-BASE-NEXT: smull v6.4s, v5.4h, v4.4h +; CHECK-GI-BASE-NEXT: smull2 v4.4s, v5.8h, v4.8h +; CHECK-GI-BASE-NEXT: smull2 v5.4s, v1.8h, v0.8h +; CHECK-GI-BASE-NEXT: smull v7.4s, v3.4h, v2.4h +; CHECK-GI-BASE-NEXT: smull v0.4s, v1.4h, v0.4h +; CHECK-GI-BASE-NEXT: smull2 v1.4s, v3.8h, v2.8h +; CHECK-GI-BASE-NEXT: addv s2, v6.4s +; CHECK-GI-BASE-NEXT: addv s3, v4.4s +; CHECK-GI-BASE-NEXT: addv s4, v5.4s +; CHECK-GI-BASE-NEXT: addv s5, v7.4s ; CHECK-GI-BASE-NEXT: addv s0, v0.4s -; CHECK-GI-BASE-NEXT: fmov w0, s0 +; CHECK-GI-BASE-NEXT: addv s1, v1.4s +; CHECK-GI-BASE-NEXT: fmov w8, s2 +; CHECK-GI-BASE-NEXT: fmov w9, s3 +; CHECK-GI-BASE-NEXT: fmov w10, s4 +; CHECK-GI-BASE-NEXT: fmov w11, s5 +; CHECK-GI-BASE-NEXT: add w8, w8, w9 +; CHECK-GI-BASE-NEXT: fmov w9, s0 +; CHECK-GI-BASE-NEXT: add w10, w10, w11 +; CHECK-GI-BASE-NEXT: fmov w11, s1 +; CHECK-GI-BASE-NEXT: add w8, w8, w9 +; CHECK-GI-BASE-NEXT: add w9, w10, w11 +; CHECK-GI-BASE-NEXT: add w0, w8, w9 ; CHECK-GI-BASE-NEXT: ret ; ; CHECK-GI-DOT-LABEL: test_sdot_v24i8: ; CHECK-GI-DOT: // %bb.0: // %entry -; CHECK-GI-DOT-NEXT: ldr b1, [x0] -; CHECK-GI-DOT-NEXT: ldr b3, [x0, #1] ; CHECK-GI-DOT-NEXT: movi v0.2d, #0000000000000000 -; CHECK-GI-DOT-NEXT: ldr b2, [x1] -; CHECK-GI-DOT-NEXT: ldr b4, [x1, #1] -; CHECK-GI-DOT-NEXT: ldr b5, [x0, #8] -; CHECK-GI-DOT-NEXT: mov v1.b[1], v3.b[0] -; CHECK-GI-DOT-NEXT: ldr b3, [x0, #2] -; CHECK-GI-DOT-NEXT: ldr b6, [x1, #8] -; CHECK-GI-DOT-NEXT: mov v2.b[1], v4.b[0] -; CHECK-GI-DOT-NEXT: ldr b4, [x1, #2] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #17] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #17] -; CHECK-GI-DOT-NEXT: mov v1.b[2], v3.b[0] -; CHECK-GI-DOT-NEXT: ldr b3, [x0, #3] -; CHECK-GI-DOT-NEXT: mov v2.b[2], v4.b[0] -; CHECK-GI-DOT-NEXT: ldr b4, [x1, #3] -; CHECK-GI-DOT-NEXT: mov v1.b[3], v3.b[0] -; CHECK-GI-DOT-NEXT: ldr b3, [x0, #4] -; CHECK-GI-DOT-NEXT: mov v2.b[3], v4.b[0] -; CHECK-GI-DOT-NEXT: ldr b4, [x1, #4] -; CHECK-GI-DOT-NEXT: mov v1.b[4], v3.b[0] -; CHECK-GI-DOT-NEXT: ldr b3, [x0, #5] -; CHECK-GI-DOT-NEXT: mov v2.b[4], v4.b[0] -; CHECK-GI-DOT-NEXT: ldr b4, [x1, #5] -; CHECK-GI-DOT-NEXT: mov v1.b[5], v3.b[0] -; CHECK-GI-DOT-NEXT: ldr b3, [x0, #6] -; CHECK-GI-DOT-NEXT: mov v2.b[5], v4.b[0] -; CHECK-GI-DOT-NEXT: ldr b4, [x1, #6] -; CHECK-GI-DOT-NEXT: mov v1.b[6], v3.b[0] -; CHECK-GI-DOT-NEXT: ldr b3, [x0, #7] -; CHECK-GI-DOT-NEXT: mov v2.b[6], v4.b[0] -; CHECK-GI-DOT-NEXT: ldr b4, [x1, #7] -; CHECK-GI-DOT-NEXT: mov v1.b[7], v3.b[0] -; CHECK-GI-DOT-NEXT: ldr b3, [x0, #16] -; CHECK-GI-DOT-NEXT: mov v2.b[7], v4.b[0] -; CHECK-GI-DOT-NEXT: ldr b4, [x1, #16] -; CHECK-GI-DOT-NEXT: mov v3.b[1], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #18] -; CHECK-GI-DOT-NEXT: mov v4.b[1], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #18] -; CHECK-GI-DOT-NEXT: mov v1.b[8], v5.b[0] -; CHECK-GI-DOT-NEXT: ldr b5, [x0, #9] -; CHECK-GI-DOT-NEXT: mov v2.b[8], v6.b[0] -; CHECK-GI-DOT-NEXT: ldr b6, [x1, #9] -; CHECK-GI-DOT-NEXT: mov v3.b[2], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #19] -; CHECK-GI-DOT-NEXT: mov v4.b[2], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #19] -; CHECK-GI-DOT-NEXT: mov v1.b[9], v5.b[0] -; CHECK-GI-DOT-NEXT: ldr b5, [x0, #10] -; CHECK-GI-DOT-NEXT: mov v2.b[9], v6.b[0] -; CHECK-GI-DOT-NEXT: ldr b6, [x1, #10] -; CHECK-GI-DOT-NEXT: mov v3.b[3], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #20] -; CHECK-GI-DOT-NEXT: mov v4.b[3], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #20] -; CHECK-GI-DOT-NEXT: mov v1.b[10], v5.b[0] -; CHECK-GI-DOT-NEXT: ldr b5, [x0, #11] -; CHECK-GI-DOT-NEXT: mov v2.b[10], v6.b[0] -; CHECK-GI-DOT-NEXT: ldr b6, [x1, #11] -; CHECK-GI-DOT-NEXT: mov v3.b[4], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #21] -; CHECK-GI-DOT-NEXT: mov v4.b[4], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #21] -; CHECK-GI-DOT-NEXT: mov v1.b[11], v5.b[0] -; CHECK-GI-DOT-NEXT: ldr b5, [x0, #12] -; CHECK-GI-DOT-NEXT: mov v2.b[11], v6.b[0] -; CHECK-GI-DOT-NEXT: ldr b6, [x1, #12] -; CHECK-GI-DOT-NEXT: mov v3.b[5], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #22] -; CHECK-GI-DOT-NEXT: mov v4.b[5], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #22] -; CHECK-GI-DOT-NEXT: mov v1.b[12], v5.b[0] -; CHECK-GI-DOT-NEXT: ldr b5, [x0, #13] -; CHECK-GI-DOT-NEXT: mov v2.b[12], v6.b[0] -; CHECK-GI-DOT-NEXT: ldr b6, [x1, #13] -; CHECK-GI-DOT-NEXT: mov v3.b[6], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #23] -; CHECK-GI-DOT-NEXT: mov v4.b[6], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #23] -; CHECK-GI-DOT-NEXT: mov v1.b[13], v5.b[0] -; CHECK-GI-DOT-NEXT: ldr b5, [x0, #14] -; CHECK-GI-DOT-NEXT: mov v2.b[13], v6.b[0] -; CHECK-GI-DOT-NEXT: ldr b6, [x1, #14] -; CHECK-GI-DOT-NEXT: mov v3.b[7], v7.b[0] -; CHECK-GI-DOT-NEXT: mov v4.b[7], v16.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[14], v5.b[0] -; CHECK-GI-DOT-NEXT: ldr b5, [x0, #15] -; CHECK-GI-DOT-NEXT: mov v2.b[14], v6.b[0] -; CHECK-GI-DOT-NEXT: ldr b6, [x1, #15] -; CHECK-GI-DOT-NEXT: fmov d3, d3 -; CHECK-GI-DOT-NEXT: fmov d4, d4 -; CHECK-GI-DOT-NEXT: mov v1.b[15], v5.b[0] -; CHECK-GI-DOT-NEXT: movi v5.2d, #0000000000000000 -; CHECK-GI-DOT-NEXT: mov v2.b[15], v6.b[0] -; CHECK-GI-DOT-NEXT: sdot v0.4s, v4.16b, v3.16b -; CHECK-GI-DOT-NEXT: sdot v5.4s, v2.16b, v1.16b -; CHECK-GI-DOT-NEXT: add v0.4s, v5.4s, v0.4s +; CHECK-GI-DOT-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-DOT-NEXT: ldr q2, [x0] +; CHECK-GI-DOT-NEXT: ldr d3, [x0, #16] +; CHECK-GI-DOT-NEXT: ldr q4, [x1] +; CHECK-GI-DOT-NEXT: ldr d5, [x1, #16] +; CHECK-GI-DOT-NEXT: sdot v1.4s, v4.16b, v2.16b +; CHECK-GI-DOT-NEXT: sdot v0.4s, v5.16b, v3.16b +; CHECK-GI-DOT-NEXT: add v0.4s, v1.4s, v0.4s ; CHECK-GI-DOT-NEXT: addv s0, v0.4s ; CHECK-GI-DOT-NEXT: fmov w0, s0 ; CHECK-GI-DOT-NEXT: ret @@ -2835,243 +2526,91 @@ define i32 @test_sdot_v48i8(ptr %p1, ptr %p2) { ; ; CHECK-GI-BASE-LABEL: test_sdot_v48i8: ; CHECK-GI-BASE: // %bb.0: // %entry -; CHECK-GI-BASE-NEXT: ldp q0, q4, [x1] -; CHECK-GI-BASE-NEXT: ldr q2, [x0, #32] -; CHECK-GI-BASE-NEXT: ldp q1, q3, [x0] -; CHECK-GI-BASE-NEXT: ldr q7, [x1, #32] -; CHECK-GI-BASE-NEXT: sshll2 v16.8h, v2.16b, #0 -; CHECK-GI-BASE-NEXT: sshll2 v6.8h, v0.16b, #0 -; CHECK-GI-BASE-NEXT: sshll v0.8h, v0.8b, #0 -; CHECK-GI-BASE-NEXT: sshll2 v17.8h, v7.16b, #0 -; CHECK-GI-BASE-NEXT: sshll2 v5.8h, v1.16b, #0 -; CHECK-GI-BASE-NEXT: sshll v1.8h, v1.8b, #0 -; CHECK-GI-BASE-NEXT: smull2 v18.4s, v6.8h, v5.8h -; CHECK-GI-BASE-NEXT: smull v19.4s, v0.4h, v1.4h -; CHECK-GI-BASE-NEXT: smull v5.4s, v6.4h, v5.4h -; CHECK-GI-BASE-NEXT: smull2 v0.4s, v0.8h, v1.8h -; CHECK-GI-BASE-NEXT: sshll v1.8h, v2.8b, #0 -; CHECK-GI-BASE-NEXT: sshll v2.8h, v7.8b, #0 -; CHECK-GI-BASE-NEXT: sshll2 v6.8h, v3.16b, #0 -; CHECK-GI-BASE-NEXT: sshll2 v7.8h, v4.16b, #0 -; CHECK-GI-BASE-NEXT: smlal2 v18.4s, v17.8h, v16.8h -; CHECK-GI-BASE-NEXT: smlal v5.4s, v17.4h, v16.4h -; CHECK-GI-BASE-NEXT: smlal v19.4s, v2.4h, v1.4h -; CHECK-GI-BASE-NEXT: smlal2 v0.4s, v2.8h, v1.8h -; CHECK-GI-BASE-NEXT: sshll v1.8h, v3.8b, #0 -; CHECK-GI-BASE-NEXT: sshll v2.8h, v4.8b, #0 -; CHECK-GI-BASE-NEXT: smlal2 v18.4s, v7.8h, v6.8h -; CHECK-GI-BASE-NEXT: smlal v5.4s, v7.4h, v6.4h -; CHECK-GI-BASE-NEXT: smlal v19.4s, v2.4h, v1.4h -; CHECK-GI-BASE-NEXT: smlal2 v0.4s, v2.8h, v1.8h -; CHECK-GI-BASE-NEXT: add v1.4s, v19.4s, v5.4s -; CHECK-GI-BASE-NEXT: add v0.4s, v0.4s, v18.4s -; CHECK-GI-BASE-NEXT: add v0.4s, v1.4s, v0.4s +; CHECK-GI-BASE-NEXT: ldp q0, q3, [x1] +; CHECK-GI-BASE-NEXT: ldr q6, [x1, #32] +; CHECK-GI-BASE-NEXT: ldp q1, q2, [x0] +; CHECK-GI-BASE-NEXT: ldr q17, [x0, #32] +; CHECK-GI-BASE-NEXT: sshll v4.8h, v0.8b, #0 +; CHECK-GI-BASE-NEXT: sshll2 v0.8h, v0.16b, #0 +; CHECK-GI-BASE-NEXT: sshll v7.8h, v3.8b, #0 +; CHECK-GI-BASE-NEXT: sshll v5.8h, v1.8b, #0 +; CHECK-GI-BASE-NEXT: sshll2 v1.8h, v1.16b, #0 +; CHECK-GI-BASE-NEXT: sshll v16.8h, v2.8b, #0 +; CHECK-GI-BASE-NEXT: sshll2 v3.8h, v3.16b, #0 +; CHECK-GI-BASE-NEXT: sshll2 v2.8h, v2.16b, #0 +; CHECK-GI-BASE-NEXT: smull v18.4s, v4.4h, v5.4h +; CHECK-GI-BASE-NEXT: smull2 v4.4s, v4.8h, v5.8h +; CHECK-GI-BASE-NEXT: smull2 v19.4s, v0.8h, v1.8h +; CHECK-GI-BASE-NEXT: smull v20.4s, v7.4h, v16.4h +; CHECK-GI-BASE-NEXT: smull v0.4s, v0.4h, v1.4h +; CHECK-GI-BASE-NEXT: sshll v5.8h, v6.8b, #0 +; CHECK-GI-BASE-NEXT: sshll v1.8h, v17.8b, #0 +; CHECK-GI-BASE-NEXT: smull2 v7.4s, v7.8h, v16.8h +; CHECK-GI-BASE-NEXT: sshll2 v6.8h, v6.16b, #0 +; CHECK-GI-BASE-NEXT: sshll2 v17.8h, v17.16b, #0 +; CHECK-GI-BASE-NEXT: addv s16, v18.4s +; CHECK-GI-BASE-NEXT: addv s4, v4.4s +; CHECK-GI-BASE-NEXT: smull v18.4s, v3.4h, v2.4h +; CHECK-GI-BASE-NEXT: smull2 v2.4s, v3.8h, v2.8h +; CHECK-GI-BASE-NEXT: addv s3, v19.4s +; CHECK-GI-BASE-NEXT: smull v19.4s, v5.4h, v1.4h +; CHECK-GI-BASE-NEXT: smull2 v1.4s, v5.8h, v1.8h +; CHECK-GI-BASE-NEXT: addv s5, v20.4s ; CHECK-GI-BASE-NEXT: addv s0, v0.4s -; CHECK-GI-BASE-NEXT: fmov w0, s0 +; CHECK-GI-BASE-NEXT: addv s7, v7.4s +; CHECK-GI-BASE-NEXT: smull v20.4s, v6.4h, v17.4h +; CHECK-GI-BASE-NEXT: smull2 v6.4s, v6.8h, v17.8h +; CHECK-GI-BASE-NEXT: fmov w8, s16 +; CHECK-GI-BASE-NEXT: fmov w9, s4 +; CHECK-GI-BASE-NEXT: fmov w10, s3 +; CHECK-GI-BASE-NEXT: addv s3, v18.4s +; CHECK-GI-BASE-NEXT: addv s2, v2.4s +; CHECK-GI-BASE-NEXT: fmov w11, s5 +; CHECK-GI-BASE-NEXT: addv s4, v19.4s +; CHECK-GI-BASE-NEXT: add w8, w8, w9 +; CHECK-GI-BASE-NEXT: fmov w9, s0 +; CHECK-GI-BASE-NEXT: addv s0, v1.4s +; CHECK-GI-BASE-NEXT: addv s1, v20.4s +; CHECK-GI-BASE-NEXT: addv s5, v6.4s +; CHECK-GI-BASE-NEXT: add w10, w10, w11 +; CHECK-GI-BASE-NEXT: fmov w11, s3 +; CHECK-GI-BASE-NEXT: fmov w12, s2 +; CHECK-GI-BASE-NEXT: add w8, w8, w9 +; CHECK-GI-BASE-NEXT: fmov w9, s7 +; CHECK-GI-BASE-NEXT: add w9, w10, w9 +; CHECK-GI-BASE-NEXT: add w10, w11, w12 +; CHECK-GI-BASE-NEXT: fmov w11, s4 +; CHECK-GI-BASE-NEXT: add w8, w8, w9 +; CHECK-GI-BASE-NEXT: add w9, w10, w11 +; CHECK-GI-BASE-NEXT: fmov w10, s0 +; CHECK-GI-BASE-NEXT: fmov w11, s5 +; CHECK-GI-BASE-NEXT: add w9, w9, w10 +; CHECK-GI-BASE-NEXT: fmov w10, s1 +; CHECK-GI-BASE-NEXT: add w8, w8, w9 +; CHECK-GI-BASE-NEXT: add w9, w10, w11 +; CHECK-GI-BASE-NEXT: add w0, w8, w9 ; CHECK-GI-BASE-NEXT: ret ; ; CHECK-GI-DOT-LABEL: test_sdot_v48i8: ; CHECK-GI-DOT: // %bb.0: // %entry -; CHECK-GI-DOT-NEXT: ldr b1, [x0] -; CHECK-GI-DOT-NEXT: ldr b5, [x0, #1] ; CHECK-GI-DOT-NEXT: movi v0.2d, #0000000000000000 -; CHECK-GI-DOT-NEXT: ldr b2, [x0, #16] -; CHECK-GI-DOT-NEXT: ldr b6, [x0, #17] -; CHECK-GI-DOT-NEXT: ldr b4, [x1] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #1] -; CHECK-GI-DOT-NEXT: mov v1.b[1], v5.b[0] -; CHECK-GI-DOT-NEXT: ldr b5, [x1, #16] -; CHECK-GI-DOT-NEXT: ldr b18, [x1, #17] -; CHECK-GI-DOT-NEXT: mov v2.b[1], v6.b[0] -; CHECK-GI-DOT-NEXT: ldr b3, [x0, #32] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #33] -; CHECK-GI-DOT-NEXT: mov v4.b[1], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b6, [x1, #32] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #33] -; CHECK-GI-DOT-NEXT: mov v5.b[1], v18.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x0, #2] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #18] -; CHECK-GI-DOT-NEXT: mov v3.b[1], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #2] -; CHECK-GI-DOT-NEXT: mov v6.b[1], v16.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[2], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #18] -; CHECK-GI-DOT-NEXT: ldr b17, [x0, #34] -; CHECK-GI-DOT-NEXT: mov v2.b[2], v18.b[0] -; CHECK-GI-DOT-NEXT: ldr b18, [x1, #34] -; CHECK-GI-DOT-NEXT: mov v4.b[2], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #3] -; CHECK-GI-DOT-NEXT: mov v5.b[2], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x0, #19] -; CHECK-GI-DOT-NEXT: mov v3.b[2], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #19] -; CHECK-GI-DOT-NEXT: mov v6.b[2], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[3], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #3] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #35] -; CHECK-GI-DOT-NEXT: mov v2.b[3], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #35] -; CHECK-GI-DOT-NEXT: mov v4.b[3], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #4] -; CHECK-GI-DOT-NEXT: mov v5.b[3], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x0, #20] -; CHECK-GI-DOT-NEXT: mov v3.b[3], v18.b[0] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #36] -; CHECK-GI-DOT-NEXT: mov v6.b[3], v16.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[4], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #4] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #20] -; CHECK-GI-DOT-NEXT: mov v2.b[4], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #36] -; CHECK-GI-DOT-NEXT: mov v4.b[4], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #5] -; CHECK-GI-DOT-NEXT: mov v5.b[4], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x0, #21] -; CHECK-GI-DOT-NEXT: mov v3.b[4], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[4], v17.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[5], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #5] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #21] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #37] -; CHECK-GI-DOT-NEXT: mov v2.b[5], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #37] -; CHECK-GI-DOT-NEXT: mov v4.b[5], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #6] -; CHECK-GI-DOT-NEXT: mov v5.b[5], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x0, #22] -; CHECK-GI-DOT-NEXT: mov v3.b[5], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[5], v16.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[6], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #6] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #22] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #38] -; CHECK-GI-DOT-NEXT: mov v2.b[6], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #38] -; CHECK-GI-DOT-NEXT: mov v4.b[6], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #7] -; CHECK-GI-DOT-NEXT: mov v5.b[6], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x0, #23] -; CHECK-GI-DOT-NEXT: mov v3.b[6], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[6], v17.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[7], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #7] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #23] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #39] -; CHECK-GI-DOT-NEXT: mov v2.b[7], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #39] -; CHECK-GI-DOT-NEXT: mov v4.b[7], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #8] -; CHECK-GI-DOT-NEXT: mov v5.b[7], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x0, #24] -; CHECK-GI-DOT-NEXT: mov v3.b[7], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[7], v16.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[8], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #8] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #24] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #40] -; CHECK-GI-DOT-NEXT: mov v2.b[8], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #40] -; CHECK-GI-DOT-NEXT: mov v4.b[8], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #9] -; CHECK-GI-DOT-NEXT: mov v5.b[8], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x0, #25] -; CHECK-GI-DOT-NEXT: mov v3.b[8], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[8], v17.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[9], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #9] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #25] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #41] -; CHECK-GI-DOT-NEXT: mov v2.b[9], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #41] -; CHECK-GI-DOT-NEXT: mov v4.b[9], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #10] -; CHECK-GI-DOT-NEXT: mov v5.b[9], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x0, #26] -; CHECK-GI-DOT-NEXT: mov v3.b[9], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[9], v16.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[10], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #10] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #26] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #42] -; CHECK-GI-DOT-NEXT: mov v2.b[10], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #42] -; CHECK-GI-DOT-NEXT: mov v4.b[10], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #11] -; CHECK-GI-DOT-NEXT: mov v5.b[10], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x0, #27] -; CHECK-GI-DOT-NEXT: mov v3.b[10], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[10], v17.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[11], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #11] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #27] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #43] -; CHECK-GI-DOT-NEXT: mov v2.b[11], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #43] -; CHECK-GI-DOT-NEXT: mov v4.b[11], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #12] -; CHECK-GI-DOT-NEXT: mov v5.b[11], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x0, #28] -; CHECK-GI-DOT-NEXT: mov v3.b[11], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[11], v16.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[12], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #12] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #28] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #44] -; CHECK-GI-DOT-NEXT: mov v2.b[12], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #44] -; CHECK-GI-DOT-NEXT: mov v4.b[12], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #13] -; CHECK-GI-DOT-NEXT: mov v5.b[12], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x0, #29] -; CHECK-GI-DOT-NEXT: mov v3.b[12], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[12], v17.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[13], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #13] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #29] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #45] -; CHECK-GI-DOT-NEXT: mov v2.b[13], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #45] -; CHECK-GI-DOT-NEXT: mov v4.b[13], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #14] -; CHECK-GI-DOT-NEXT: mov v5.b[13], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x0, #30] -; CHECK-GI-DOT-NEXT: mov v3.b[13], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[13], v16.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[14], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #14] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #30] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #46] -; CHECK-GI-DOT-NEXT: mov v2.b[14], v17.b[0] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #46] -; CHECK-GI-DOT-NEXT: mov v4.b[14], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x0, #15] -; CHECK-GI-DOT-NEXT: mov v5.b[14], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x0, #31] -; CHECK-GI-DOT-NEXT: mov v3.b[14], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[14], v17.b[0] -; CHECK-GI-DOT-NEXT: mov v1.b[15], v7.b[0] -; CHECK-GI-DOT-NEXT: ldr b7, [x1, #15] -; CHECK-GI-DOT-NEXT: ldr b17, [x1, #31] -; CHECK-GI-DOT-NEXT: ldr b18, [x0, #47] -; CHECK-GI-DOT-NEXT: mov v2.b[15], v16.b[0] -; CHECK-GI-DOT-NEXT: ldr b16, [x1, #47] -; CHECK-GI-DOT-NEXT: mov v4.b[15], v7.b[0] -; CHECK-GI-DOT-NEXT: movi v7.2d, #0000000000000000 -; CHECK-GI-DOT-NEXT: mov v5.b[15], v17.b[0] -; CHECK-GI-DOT-NEXT: mov v3.b[15], v18.b[0] -; CHECK-GI-DOT-NEXT: mov v6.b[15], v16.b[0] -; CHECK-GI-DOT-NEXT: movi v16.2d, #0000000000000000 -; CHECK-GI-DOT-NEXT: sdot v0.4s, v4.16b, v1.16b -; CHECK-GI-DOT-NEXT: sdot v7.4s, v5.16b, v2.16b -; CHECK-GI-DOT-NEXT: sdot v16.4s, v6.16b, v3.16b +; CHECK-GI-DOT-NEXT: movi v1.2d, #0000000000000000 +; CHECK-GI-DOT-NEXT: ldr q7, [x0, #32] +; CHECK-GI-DOT-NEXT: ldp q3, q4, [x0] +; CHECK-GI-DOT-NEXT: movi v2.2d, #0000000000000000 +; CHECK-GI-DOT-NEXT: ldp q5, q6, [x1] +; CHECK-GI-DOT-NEXT: ldr q16, [x1, #32] +; CHECK-GI-DOT-NEXT: sdot v0.4s, v5.16b, v3.16b +; CHECK-GI-DOT-NEXT: sdot v1.4s, v6.16b, v4.16b +; CHECK-GI-DOT-NEXT: sdot v2.4s, v16.16b, v7.16b ; CHECK-GI-DOT-NEXT: addv s0, v0.4s -; CHECK-GI-DOT-NEXT: addv s1, v7.4s -; CHECK-GI-DOT-NEXT: addv s2, v16.4s +; CHECK-GI-DOT-NEXT: addv s1, v1.4s +; CHECK-GI-DOT-NEXT: addv s2, v2.4s ; CHECK-GI-DOT-NEXT: fmov w8, s0 ; CHECK-GI-DOT-NEXT: fmov w9, s1 -; CHECK-GI-DOT-NEXT: fmov w10, s2 ; CHECK-GI-DOT-NEXT: add w8, w8, w9 -; CHECK-GI-DOT-NEXT: add w0, w8, w10 +; CHECK-GI-DOT-NEXT: fmov w9, s2 +; CHECK-GI-DOT-NEXT: add w0, w8, w9 ; CHECK-GI-DOT-NEXT: ret entry: %a = load <48 x i8>, ptr %p1 diff --git a/llvm/test/CodeGen/AArch64/wrong-callee-save-size-after-livedebugvariables.mir b/llvm/test/CodeGen/AArch64/wrong-callee-save-size-after-livedebugvariables.mir index 53a8612a7fae76c906e9d9e86beedc05593e8074..8e1142474447ed3d1c7a74acd9490387a89ad9e7 100644 --- a/llvm/test/CodeGen/AArch64/wrong-callee-save-size-after-livedebugvariables.mir +++ b/llvm/test/CodeGen/AArch64/wrong-callee-save-size-after-livedebugvariables.mir @@ -64,6 +64,7 @@ name: foo tracksRegLiveness: true frameInfo: + adjustsStack: true hasCalls: true fixedStack: [] stack: diff --git a/llvm/test/CodeGen/AArch64/xor.ll b/llvm/test/CodeGen/AArch64/xor.ll index d92402cf43b33ed0bbb5842aac94b681e1d65faa..7d7f7bfdbf38e8ed4acd4d50a0b21b720e719d5f 100644 --- a/llvm/test/CodeGen/AArch64/xor.ll +++ b/llvm/test/CodeGen/AArch64/xor.ll @@ -51,7 +51,7 @@ define <4 x i32> @vec_add_of_not_decrement(<4 x i32> %x, <4 x i32> %y) { ; CHECK-LABEL: vec_add_of_not_decrement: ; CHECK: // %bb.0: ; CHECK-NEXT: mvn v1.16b, v1.16b -; CHECK-NEXT: add v0.4s, v1.4s, v0.4s +; CHECK-NEXT: add v0.4s, v0.4s, v1.4s ; CHECK-NEXT: ret %t0 = sub <4 x i32> %x, %y %r = sub <4 x i32> %t0, <i32 1, i32 1, i32 1, i32 1> diff --git a/llvm/test/CodeGen/AArch64/zext.ll b/llvm/test/CodeGen/AArch64/zext.ll index 54b29be2132cdd1b46e52cc8f91d9286fed080dd..716d2398996be26e99a96610acdde6206a408e05 100644 --- a/llvm/test/CodeGen/AArch64/zext.ll +++ b/llvm/test/CodeGen/AArch64/zext.ll @@ -305,15 +305,14 @@ define <3 x i64> @zext_v3i8_v3i64(<3 x i8> %a) { ; ; CHECK-GI-LABEL: zext_v3i8_v3i64: ; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: // kill: def $w0 killed $w0 def $x0 -; CHECK-GI-NEXT: fmov d1, x0 -; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1 -; CHECK-GI-NEXT: movi v0.2d, #0x000000000000ff +; CHECK-GI-NEXT: fmov s0, w0 +; CHECK-GI-NEXT: movi v1.2d, #0x000000000000ff ; CHECK-GI-NEXT: // kill: def $w2 killed $w2 def $x2 ; CHECK-GI-NEXT: and x8, x2, #0xff ; CHECK-GI-NEXT: fmov d2, x8 -; CHECK-GI-NEXT: mov v1.d[1], x1 -; CHECK-GI-NEXT: and v0.16b, v1.16b, v0.16b +; CHECK-GI-NEXT: mov v0.s[1], w1 +; CHECK-GI-NEXT: ushll v0.2d, v0.2s, #0 +; CHECK-GI-NEXT: and v0.16b, v0.16b, v1.16b ; CHECK-GI-NEXT: mov d1, v0.d[1] ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 ; CHECK-GI-NEXT: ret @@ -470,15 +469,14 @@ define <3 x i64> @zext_v3i10_v3i64(<3 x i10> %a) { ; ; CHECK-GI-LABEL: zext_v3i10_v3i64: ; CHECK-GI: // %bb.0: // %entry -; CHECK-GI-NEXT: // kill: def $w0 killed $w0 def $x0 -; CHECK-GI-NEXT: fmov d0, x0 -; CHECK-GI-NEXT: // kill: def $w1 killed $w1 def $x1 +; CHECK-GI-NEXT: fmov s0, w0 ; CHECK-GI-NEXT: adrp x8, .LCPI27_0 ; CHECK-GI-NEXT: // kill: def $w2 killed $w2 def $x2 ; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI27_0] ; CHECK-GI-NEXT: and x8, x2, #0x3ff ; CHECK-GI-NEXT: fmov d2, x8 -; CHECK-GI-NEXT: mov v0.d[1], x1 +; CHECK-GI-NEXT: mov v0.s[1], w1 +; CHECK-GI-NEXT: ushll v0.2d, v0.2s, #0 ; CHECK-GI-NEXT: and v0.16b, v0.16b, v1.16b ; CHECK-GI-NEXT: mov d1, v0.d[1] ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/fp64-atomics-gfx90a.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/fp64-atomics-gfx90a.ll index 255c6dedbd6e1e5bfbe5d8dbb715ed0118cb789c..1a76f8cf87ffbeca984a6642221f3b55f8cb51a6 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/fp64-atomics-gfx90a.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/fp64-atomics-gfx90a.ll @@ -1090,18 +1090,29 @@ main_body: define amdgpu_kernel void @global_atomic_fadd_f64_noret_pat(ptr addrspace(1) %ptr) #1 { ; GFX90A-LABEL: global_atomic_fadd_f64_noret_pat: ; GFX90A: ; %bb.0: ; %main_body +; GFX90A-NEXT: s_mov_b64 s[2:3], exec +; GFX90A-NEXT: s_mov_b32 s4, s3 +; GFX90A-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX90A-NEXT: v_mbcnt_hi_u32_b32 v0, s4, v0 +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX90A-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX90A-NEXT: s_cbranch_execz .LBB39_3 +; GFX90A-NEXT: ; %bb.1: ; GFX90A-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX90A-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s2 +; GFX90A-NEXT: v_mul_f64 v[4:5], v[0:1], 4.0 ; GFX90A-NEXT: s_mov_b64 s[2:3], 0 -; GFX90A-NEXT: v_mov_b32_e32 v4, 0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX90A-NEXT: v_mov_b32_e32 v6, 0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: v_pk_mov_b32 v[2:3], s[4:5], s[4:5] op_sel:[0,1] -; GFX90A-NEXT: .LBB39_1: ; %atomicrmw.start +; GFX90A-NEXT: .LBB39_2: ; %atomicrmw.start ; GFX90A-NEXT: ; =>This Inner Loop Header: Depth=1 -; GFX90A-NEXT: v_add_f64 v[0:1], v[2:3], 4.0 +; GFX90A-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] ; GFX90A-NEXT: buffer_wbl2 -; GFX90A-NEXT: global_atomic_cmpswap_x2 v[0:1], v4, v[0:3], s[0:1] glc +; GFX90A-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc ; GFX90A-NEXT: s_waitcnt vmcnt(0) ; GFX90A-NEXT: buffer_invl2 ; GFX90A-NEXT: buffer_wbinvl1_vol @@ -1109,20 +1120,31 @@ define amdgpu_kernel void @global_atomic_fadd_f64_noret_pat(ptr addrspace(1) %pt ; GFX90A-NEXT: s_or_b64 s[2:3], vcc, s[2:3] ; GFX90A-NEXT: v_pk_mov_b32 v[2:3], v[0:1], v[0:1] op_sel:[0,1] ; GFX90A-NEXT: s_andn2_b64 exec, exec, s[2:3] -; GFX90A-NEXT: s_cbranch_execnz .LBB39_1 -; GFX90A-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX90A-NEXT: s_cbranch_execnz .LBB39_2 +; GFX90A-NEXT: .LBB39_3: ; GFX90A-NEXT: s_endpgm ; ; GFX940-LABEL: global_atomic_fadd_f64_noret_pat: ; GFX940: ; %bb.0: ; %main_body +; GFX940-NEXT: s_mov_b64 s[2:3], exec +; GFX940-NEXT: s_mov_b32 s4, s3 +; GFX940-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX940-NEXT: v_mbcnt_hi_u32_b32 v0, s4, v0 +; GFX940-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX940-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX940-NEXT: s_cbranch_execz .LBB39_2 +; GFX940-NEXT: ; %bb.1: ; GFX940-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 -; GFX940-NEXT: v_mov_b64_e32 v[0:1], 4.0 +; GFX940-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s2 +; GFX940-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX940-NEXT: v_mov_b32_e32 v2, 0 ; GFX940-NEXT: buffer_wbl2 sc0 sc1 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) ; GFX940-NEXT: global_atomic_add_f64 v2, v[0:1], s[0:1] sc1 ; GFX940-NEXT: s_waitcnt vmcnt(0) ; GFX940-NEXT: buffer_inv sc0 sc1 +; GFX940-NEXT: .LBB39_2: ; GFX940-NEXT: s_endpgm main_body: %ret = atomicrmw fadd ptr addrspace(1) %ptr, double 4.0 seq_cst @@ -1132,26 +1154,47 @@ main_body: define amdgpu_kernel void @global_atomic_fadd_f64_noret_pat_agent(ptr addrspace(1) %ptr) #1 { ; GFX90A-LABEL: global_atomic_fadd_f64_noret_pat_agent: ; GFX90A: ; %bb.0: ; %main_body +; GFX90A-NEXT: s_mov_b64 s[2:3], exec +; GFX90A-NEXT: s_mov_b32 s4, s3 +; GFX90A-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX90A-NEXT: v_mbcnt_hi_u32_b32 v0, s4, v0 +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX90A-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX90A-NEXT: s_cbranch_execz .LBB40_2 +; GFX90A-NEXT: ; %bb.1: ; GFX90A-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 -; GFX90A-NEXT: v_mov_b32_e32 v0, 0 -; GFX90A-NEXT: v_mov_b32_e32 v1, 0x40100000 +; GFX90A-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s2 +; GFX90A-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX90A-NEXT: v_mov_b32_e32 v2, 0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: global_atomic_add_f64 v2, v[0:1], s[0:1] ; GFX90A-NEXT: s_waitcnt vmcnt(0) ; GFX90A-NEXT: buffer_wbinvl1_vol +; GFX90A-NEXT: .LBB40_2: ; GFX90A-NEXT: s_endpgm ; ; GFX940-LABEL: global_atomic_fadd_f64_noret_pat_agent: ; GFX940: ; %bb.0: ; %main_body +; GFX940-NEXT: s_mov_b64 s[2:3], exec +; GFX940-NEXT: s_mov_b32 s4, s3 +; GFX940-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX940-NEXT: v_mbcnt_hi_u32_b32 v0, s4, v0 +; GFX940-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX940-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX940-NEXT: s_cbranch_execz .LBB40_2 +; GFX940-NEXT: ; %bb.1: ; GFX940-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 -; GFX940-NEXT: v_mov_b64_e32 v[0:1], 4.0 +; GFX940-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s2 +; GFX940-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX940-NEXT: v_mov_b32_e32 v2, 0 ; GFX940-NEXT: buffer_wbl2 sc1 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) ; GFX940-NEXT: global_atomic_add_f64 v2, v[0:1], s[0:1] ; GFX940-NEXT: s_waitcnt vmcnt(0) ; GFX940-NEXT: buffer_inv sc1 +; GFX940-NEXT: .LBB40_2: ; GFX940-NEXT: s_endpgm main_body: %ret = atomicrmw fadd ptr addrspace(1) %ptr, double 4.0 syncscope("agent") seq_cst @@ -1161,18 +1204,29 @@ main_body: define amdgpu_kernel void @global_atomic_fadd_f64_noret_pat_system(ptr addrspace(1) %ptr) #1 { ; GFX90A-LABEL: global_atomic_fadd_f64_noret_pat_system: ; GFX90A: ; %bb.0: ; %main_body +; GFX90A-NEXT: s_mov_b64 s[2:3], exec +; GFX90A-NEXT: s_mov_b32 s4, s3 +; GFX90A-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX90A-NEXT: v_mbcnt_hi_u32_b32 v0, s4, v0 +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX90A-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX90A-NEXT: s_cbranch_execz .LBB41_3 +; GFX90A-NEXT: ; %bb.1: ; GFX90A-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX90A-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s2 +; GFX90A-NEXT: v_mul_f64 v[4:5], v[0:1], 4.0 ; GFX90A-NEXT: s_mov_b64 s[2:3], 0 -; GFX90A-NEXT: v_mov_b32_e32 v4, 0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX90A-NEXT: v_mov_b32_e32 v6, 0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: v_pk_mov_b32 v[2:3], s[4:5], s[4:5] op_sel:[0,1] -; GFX90A-NEXT: .LBB41_1: ; %atomicrmw.start +; GFX90A-NEXT: .LBB41_2: ; %atomicrmw.start ; GFX90A-NEXT: ; =>This Inner Loop Header: Depth=1 -; GFX90A-NEXT: v_add_f64 v[0:1], v[2:3], 4.0 +; GFX90A-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] ; GFX90A-NEXT: buffer_wbl2 -; GFX90A-NEXT: global_atomic_cmpswap_x2 v[0:1], v4, v[0:3], s[0:1] glc +; GFX90A-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc ; GFX90A-NEXT: s_waitcnt vmcnt(0) ; GFX90A-NEXT: buffer_invl2 ; GFX90A-NEXT: buffer_wbinvl1_vol @@ -1180,20 +1234,31 @@ define amdgpu_kernel void @global_atomic_fadd_f64_noret_pat_system(ptr addrspace ; GFX90A-NEXT: s_or_b64 s[2:3], vcc, s[2:3] ; GFX90A-NEXT: v_pk_mov_b32 v[2:3], v[0:1], v[0:1] op_sel:[0,1] ; GFX90A-NEXT: s_andn2_b64 exec, exec, s[2:3] -; GFX90A-NEXT: s_cbranch_execnz .LBB41_1 -; GFX90A-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX90A-NEXT: s_cbranch_execnz .LBB41_2 +; GFX90A-NEXT: .LBB41_3: ; GFX90A-NEXT: s_endpgm ; ; GFX940-LABEL: global_atomic_fadd_f64_noret_pat_system: ; GFX940: ; %bb.0: ; %main_body +; GFX940-NEXT: s_mov_b64 s[2:3], exec +; GFX940-NEXT: s_mov_b32 s4, s3 +; GFX940-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX940-NEXT: v_mbcnt_hi_u32_b32 v0, s4, v0 +; GFX940-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX940-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX940-NEXT: s_cbranch_execz .LBB41_2 +; GFX940-NEXT: ; %bb.1: ; GFX940-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 -; GFX940-NEXT: v_mov_b64_e32 v[0:1], 4.0 +; GFX940-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s2 +; GFX940-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX940-NEXT: v_mov_b32_e32 v2, 0 ; GFX940-NEXT: buffer_wbl2 sc0 sc1 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) ; GFX940-NEXT: global_atomic_add_f64 v2, v[0:1], s[0:1] sc1 ; GFX940-NEXT: s_waitcnt vmcnt(0) ; GFX940-NEXT: buffer_inv sc0 sc1 +; GFX940-NEXT: .LBB41_2: ; GFX940-NEXT: s_endpgm main_body: %ret = atomicrmw fadd ptr addrspace(1) %ptr, double 4.0 syncscope("one-as") seq_cst @@ -1203,26 +1268,47 @@ main_body: define amdgpu_kernel void @global_atomic_fadd_f64_noret_pat_flush(ptr addrspace(1) %ptr) #0 { ; GFX90A-LABEL: global_atomic_fadd_f64_noret_pat_flush: ; GFX90A: ; %bb.0: ; %main_body +; GFX90A-NEXT: s_mov_b64 s[2:3], exec +; GFX90A-NEXT: s_mov_b32 s4, s3 +; GFX90A-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX90A-NEXT: v_mbcnt_hi_u32_b32 v0, s4, v0 +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX90A-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX90A-NEXT: s_cbranch_execz .LBB42_2 +; GFX90A-NEXT: ; %bb.1: ; GFX90A-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 -; GFX90A-NEXT: v_mov_b32_e32 v0, 0 -; GFX90A-NEXT: v_mov_b32_e32 v1, 0x40100000 +; GFX90A-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s2 +; GFX90A-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX90A-NEXT: v_mov_b32_e32 v2, 0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: global_atomic_add_f64 v2, v[0:1], s[0:1] ; GFX90A-NEXT: s_waitcnt vmcnt(0) ; GFX90A-NEXT: buffer_wbinvl1_vol +; GFX90A-NEXT: .LBB42_2: ; GFX90A-NEXT: s_endpgm ; ; GFX940-LABEL: global_atomic_fadd_f64_noret_pat_flush: ; GFX940: ; %bb.0: ; %main_body +; GFX940-NEXT: s_mov_b64 s[2:3], exec +; GFX940-NEXT: s_mov_b32 s4, s3 +; GFX940-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX940-NEXT: v_mbcnt_hi_u32_b32 v0, s4, v0 +; GFX940-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX940-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX940-NEXT: s_cbranch_execz .LBB42_2 +; GFX940-NEXT: ; %bb.1: ; GFX940-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 -; GFX940-NEXT: v_mov_b64_e32 v[0:1], 4.0 +; GFX940-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s2 +; GFX940-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX940-NEXT: v_mov_b32_e32 v2, 0 ; GFX940-NEXT: buffer_wbl2 sc1 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) ; GFX940-NEXT: global_atomic_add_f64 v2, v[0:1], s[0:1] ; GFX940-NEXT: s_waitcnt vmcnt(0) ; GFX940-NEXT: buffer_inv sc1 +; GFX940-NEXT: .LBB42_2: ; GFX940-NEXT: s_endpgm main_body: %ret = atomicrmw fadd ptr addrspace(1) %ptr, double 4.0 syncscope("agent") seq_cst @@ -1394,37 +1480,59 @@ main_body: define amdgpu_kernel void @global_atomic_fadd_f64_noret_pat_agent_safe(ptr addrspace(1) %ptr) { ; GFX90A-LABEL: global_atomic_fadd_f64_noret_pat_agent_safe: ; GFX90A: ; %bb.0: ; %main_body +; GFX90A-NEXT: s_mov_b64 s[2:3], exec +; GFX90A-NEXT: s_mov_b32 s4, s3 +; GFX90A-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX90A-NEXT: v_mbcnt_hi_u32_b32 v0, s4, v0 +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX90A-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX90A-NEXT: s_cbranch_execz .LBB49_3 +; GFX90A-NEXT: ; %bb.1: ; GFX90A-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX90A-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s2 +; GFX90A-NEXT: v_mul_f64 v[4:5], v[0:1], 4.0 ; GFX90A-NEXT: s_mov_b64 s[2:3], 0 -; GFX90A-NEXT: v_mov_b32_e32 v4, 0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX90A-NEXT: v_mov_b32_e32 v6, 0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: v_pk_mov_b32 v[2:3], s[4:5], s[4:5] op_sel:[0,1] -; GFX90A-NEXT: .LBB49_1: ; %atomicrmw.start +; GFX90A-NEXT: .LBB49_2: ; %atomicrmw.start ; GFX90A-NEXT: ; =>This Inner Loop Header: Depth=1 -; GFX90A-NEXT: v_add_f64 v[0:1], v[2:3], 4.0 -; GFX90A-NEXT: global_atomic_cmpswap_x2 v[0:1], v4, v[0:3], s[0:1] glc +; GFX90A-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX90A-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc ; GFX90A-NEXT: s_waitcnt vmcnt(0) ; GFX90A-NEXT: buffer_wbinvl1_vol ; GFX90A-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] ; GFX90A-NEXT: s_or_b64 s[2:3], vcc, s[2:3] ; GFX90A-NEXT: v_pk_mov_b32 v[2:3], v[0:1], v[0:1] op_sel:[0,1] ; GFX90A-NEXT: s_andn2_b64 exec, exec, s[2:3] -; GFX90A-NEXT: s_cbranch_execnz .LBB49_1 -; GFX90A-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX90A-NEXT: s_cbranch_execnz .LBB49_2 +; GFX90A-NEXT: .LBB49_3: ; GFX90A-NEXT: s_endpgm ; ; GFX940-LABEL: global_atomic_fadd_f64_noret_pat_agent_safe: ; GFX940: ; %bb.0: ; %main_body +; GFX940-NEXT: s_mov_b64 s[2:3], exec +; GFX940-NEXT: s_mov_b32 s4, s3 +; GFX940-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX940-NEXT: v_mbcnt_hi_u32_b32 v0, s4, v0 +; GFX940-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX940-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX940-NEXT: s_cbranch_execz .LBB49_2 +; GFX940-NEXT: ; %bb.1: ; GFX940-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 -; GFX940-NEXT: v_mov_b64_e32 v[0:1], 4.0 +; GFX940-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s2 +; GFX940-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX940-NEXT: v_mov_b32_e32 v2, 0 ; GFX940-NEXT: buffer_wbl2 sc1 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) ; GFX940-NEXT: global_atomic_add_f64 v2, v[0:1], s[0:1] ; GFX940-NEXT: s_waitcnt vmcnt(0) ; GFX940-NEXT: buffer_inv sc1 +; GFX940-NEXT: .LBB49_2: ; GFX940-NEXT: s_endpgm main_body: %ret = atomicrmw fadd ptr addrspace(1) %ptr, double 4.0 syncscope("agent") seq_cst @@ -1866,23 +1974,44 @@ main_body: define amdgpu_kernel void @local_atomic_fadd_f64_noret_pat(ptr addrspace(3) %ptr) #1 { ; GFX90A-LABEL: local_atomic_fadd_f64_noret_pat: ; GFX90A: ; %bb.0: ; %main_body +; GFX90A-NEXT: s_mov_b64 s[2:3], exec +; GFX90A-NEXT: s_mov_b32 s4, s3 +; GFX90A-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX90A-NEXT: v_mbcnt_hi_u32_b32 v0, s4, v0 +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX90A-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX90A-NEXT: s_cbranch_execz .LBB65_2 +; GFX90A-NEXT: ; %bb.1: ; GFX90A-NEXT: s_load_dword s0, s[0:1], 0x24 -; GFX90A-NEXT: v_mov_b32_e32 v0, 0 -; GFX90A-NEXT: v_mov_b32_e32 v1, 0x40100000 +; GFX90A-NEXT: s_bcnt1_i32_b64 s1, s[2:3] +; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s1 +; GFX90A-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: v_mov_b32_e32 v2, s0 ; GFX90A-NEXT: ds_add_f64 v2, v[0:1] ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) +; GFX90A-NEXT: .LBB65_2: ; GFX90A-NEXT: s_endpgm ; ; GFX940-LABEL: local_atomic_fadd_f64_noret_pat: ; GFX940: ; %bb.0: ; %main_body +; GFX940-NEXT: s_mov_b64 s[2:3], exec +; GFX940-NEXT: s_mov_b32 s4, s3 +; GFX940-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX940-NEXT: v_mbcnt_hi_u32_b32 v0, s4, v0 +; GFX940-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX940-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX940-NEXT: s_cbranch_execz .LBB65_2 +; GFX940-NEXT: ; %bb.1: ; GFX940-NEXT: s_load_dword s0, s[0:1], 0x24 -; GFX940-NEXT: v_mov_b64_e32 v[0:1], 4.0 +; GFX940-NEXT: s_bcnt1_i32_b64 s1, s[2:3] +; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s1 +; GFX940-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) ; GFX940-NEXT: v_mov_b32_e32 v2, s0 ; GFX940-NEXT: ds_add_f64 v2, v[0:1] ; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: .LBB65_2: ; GFX940-NEXT: s_endpgm main_body: %ret = atomicrmw fadd ptr addrspace(3) %ptr, double 4.0 seq_cst @@ -1892,23 +2021,44 @@ main_body: define amdgpu_kernel void @local_atomic_fadd_f64_noret_pat_flush(ptr addrspace(3) %ptr) #0 { ; GFX90A-LABEL: local_atomic_fadd_f64_noret_pat_flush: ; GFX90A: ; %bb.0: ; %main_body +; GFX90A-NEXT: s_mov_b64 s[2:3], exec +; GFX90A-NEXT: s_mov_b32 s4, s3 +; GFX90A-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX90A-NEXT: v_mbcnt_hi_u32_b32 v0, s4, v0 +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX90A-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX90A-NEXT: s_cbranch_execz .LBB66_2 +; GFX90A-NEXT: ; %bb.1: ; GFX90A-NEXT: s_load_dword s0, s[0:1], 0x24 -; GFX90A-NEXT: v_mov_b32_e32 v0, 0 -; GFX90A-NEXT: v_mov_b32_e32 v1, 0x40100000 +; GFX90A-NEXT: s_bcnt1_i32_b64 s1, s[2:3] +; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s1 +; GFX90A-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: v_mov_b32_e32 v2, s0 ; GFX90A-NEXT: ds_add_f64 v2, v[0:1] ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) +; GFX90A-NEXT: .LBB66_2: ; GFX90A-NEXT: s_endpgm ; ; GFX940-LABEL: local_atomic_fadd_f64_noret_pat_flush: ; GFX940: ; %bb.0: ; %main_body +; GFX940-NEXT: s_mov_b64 s[2:3], exec +; GFX940-NEXT: s_mov_b32 s4, s3 +; GFX940-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX940-NEXT: v_mbcnt_hi_u32_b32 v0, s4, v0 +; GFX940-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX940-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX940-NEXT: s_cbranch_execz .LBB66_2 +; GFX940-NEXT: ; %bb.1: ; GFX940-NEXT: s_load_dword s0, s[0:1], 0x24 -; GFX940-NEXT: v_mov_b64_e32 v[0:1], 4.0 +; GFX940-NEXT: s_bcnt1_i32_b64 s1, s[2:3] +; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s1 +; GFX940-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) ; GFX940-NEXT: v_mov_b32_e32 v2, s0 ; GFX940-NEXT: ds_add_f64 v2, v[0:1] ; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: .LBB66_2: ; GFX940-NEXT: s_endpgm main_body: %ret = atomicrmw fadd ptr addrspace(3) %ptr, double 4.0 seq_cst @@ -1918,44 +2068,66 @@ main_body: define amdgpu_kernel void @local_atomic_fadd_f64_noret_pat_flush_safe(ptr addrspace(3) %ptr) #4 { ; GFX90A-LABEL: local_atomic_fadd_f64_noret_pat_flush_safe: ; GFX90A: ; %bb.0: ; %main_body +; GFX90A-NEXT: s_mov_b64 s[2:3], exec +; GFX90A-NEXT: s_mov_b32 s4, s3 +; GFX90A-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX90A-NEXT: v_mbcnt_hi_u32_b32 v0, s4, v0 +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX90A-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX90A-NEXT: s_cbranch_execz .LBB67_3 +; GFX90A-NEXT: ; %bb.1: ; GFX90A-NEXT: s_load_dword s0, s[0:1], 0x24 +; GFX90A-NEXT: s_bcnt1_i32_b64 s1, s[2:3] +; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s1 +; GFX90A-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) -; GFX90A-NEXT: v_mov_b32_e32 v2, s0 -; GFX90A-NEXT: ds_read_b64 v[0:1], v2 +; GFX90A-NEXT: v_mov_b32_e32 v4, s0 +; GFX90A-NEXT: ds_read_b64 v[2:3], v4 ; GFX90A-NEXT: s_mov_b64 s[0:1], 0 -; GFX90A-NEXT: .LBB67_1: ; %atomicrmw.start +; GFX90A-NEXT: .LBB67_2: ; %atomicrmw.start ; GFX90A-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) -; GFX90A-NEXT: v_add_f64 v[4:5], v[0:1], 4.0 -; GFX90A-NEXT: ds_cmpst_rtn_b64 v[4:5], v2, v[0:1], v[4:5] +; GFX90A-NEXT: v_add_f64 v[6:7], v[2:3], v[0:1] +; GFX90A-NEXT: ds_cmpst_rtn_b64 v[6:7], v4, v[2:3], v[6:7] ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) -; GFX90A-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[0:1] +; GFX90A-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[2:3] ; GFX90A-NEXT: s_or_b64 s[0:1], vcc, s[0:1] -; GFX90A-NEXT: v_pk_mov_b32 v[0:1], v[4:5], v[4:5] op_sel:[0,1] +; GFX90A-NEXT: v_pk_mov_b32 v[2:3], v[6:7], v[6:7] op_sel:[0,1] ; GFX90A-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GFX90A-NEXT: s_cbranch_execnz .LBB67_1 -; GFX90A-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX90A-NEXT: s_cbranch_execnz .LBB67_2 +; GFX90A-NEXT: .LBB67_3: ; GFX90A-NEXT: s_endpgm ; ; GFX940-LABEL: local_atomic_fadd_f64_noret_pat_flush_safe: ; GFX940: ; %bb.0: ; %main_body +; GFX940-NEXT: s_mov_b64 s[2:3], exec +; GFX940-NEXT: s_mov_b32 s4, s3 +; GFX940-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX940-NEXT: v_mbcnt_hi_u32_b32 v0, s4, v0 +; GFX940-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX940-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX940-NEXT: s_cbranch_execz .LBB67_3 +; GFX940-NEXT: ; %bb.1: ; GFX940-NEXT: s_load_dword s0, s[0:1], 0x24 +; GFX940-NEXT: s_bcnt1_i32_b64 s1, s[2:3] +; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s1 +; GFX940-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-NEXT: v_mov_b32_e32 v2, s0 -; GFX940-NEXT: ds_read_b64 v[0:1], v2 +; GFX940-NEXT: v_mov_b32_e32 v4, s0 +; GFX940-NEXT: ds_read_b64 v[2:3], v4 ; GFX940-NEXT: s_mov_b64 s[0:1], 0 -; GFX940-NEXT: .LBB67_1: ; %atomicrmw.start +; GFX940-NEXT: .LBB67_2: ; %atomicrmw.start ; GFX940-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-NEXT: v_add_f64 v[4:5], v[0:1], 4.0 -; GFX940-NEXT: ds_cmpst_rtn_b64 v[4:5], v2, v[0:1], v[4:5] +; GFX940-NEXT: v_add_f64 v[6:7], v[2:3], v[0:1] +; GFX940-NEXT: ds_cmpst_rtn_b64 v[6:7], v4, v[2:3], v[6:7] ; GFX940-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[0:1] +; GFX940-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[2:3] ; GFX940-NEXT: s_or_b64 s[0:1], vcc, s[0:1] -; GFX940-NEXT: v_mov_b64_e32 v[0:1], v[4:5] +; GFX940-NEXT: v_mov_b64_e32 v[2:3], v[6:7] ; GFX940-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GFX940-NEXT: s_cbranch_execnz .LBB67_1 -; GFX940-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX940-NEXT: s_cbranch_execnz .LBB67_2 +; GFX940-NEXT: .LBB67_3: ; GFX940-NEXT: s_endpgm main_body: %ret = atomicrmw fadd ptr addrspace(3) %ptr, double 4.0 seq_cst diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-atomic-cmpxchg-with-success.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-atomic-cmpxchg-with-success.mir index e288d9d5ab3c095d1b7563751c5ca2bc279a56e7..eafd1e15e2cb3f5d6e9a442de12188a67f7dffac 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-atomic-cmpxchg-with-success.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-atomic-cmpxchg-with-success.mir @@ -16,7 +16,8 @@ body: | ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[COPY2]](s32), [[COPY1]](s32) ; CHECK-NEXT: [[AMDGPU_ATOMIC_CMPXCHG:%[0-9]+]]:_(s32) = G_AMDGPU_ATOMIC_CMPXCHG [[COPY]](p1), [[BUILD_VECTOR]] :: (load store syncscope("agent-one-as") monotonic monotonic (s32), addrspace 1) ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[AMDGPU_ATOMIC_CMPXCHG]](s32), [[COPY1]] - ; CHECK-NEXT: S_ENDPGM 0, implicit [[AMDGPU_ATOMIC_CMPXCHG]](s32), implicit [[ICMP]](s1) + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY [[AMDGPU_ATOMIC_CMPXCHG]](s32) + ; CHECK-NEXT: S_ENDPGM 0, implicit [[COPY3]](s32), implicit [[ICMP]](s1) %0:_(p1) = COPY $vgpr0_vgpr1 %1:_(s32) = COPY $vgpr2 %2:_(s32) = COPY $vgpr3 @@ -40,7 +41,8 @@ body: | ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[COPY2]](s32), [[COPY1]](s32) ; CHECK-NEXT: [[AMDGPU_ATOMIC_CMPXCHG:%[0-9]+]]:_(s32) = G_AMDGPU_ATOMIC_CMPXCHG [[COPY]](p0), [[BUILD_VECTOR]] :: (load store syncscope("agent-one-as") monotonic monotonic (s32)) ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[AMDGPU_ATOMIC_CMPXCHG]](s32), [[COPY1]] - ; CHECK-NEXT: S_ENDPGM 0, implicit [[AMDGPU_ATOMIC_CMPXCHG]](s32), implicit [[ICMP]](s1) + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY [[AMDGPU_ATOMIC_CMPXCHG]](s32) + ; CHECK-NEXT: S_ENDPGM 0, implicit [[COPY3]](s32), implicit [[ICMP]](s1) %0:_(p0) = COPY $vgpr0_vgpr1 %1:_(s32) = COPY $vgpr2 %2:_(s32) = COPY $vgpr3 @@ -63,7 +65,8 @@ body: | ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2 ; CHECK-NEXT: [[ATOMIC_CMPXCHG:%[0-9]+]]:_(s32) = G_ATOMIC_CMPXCHG [[COPY]](p3), [[COPY1]], [[COPY2]] :: (load store syncscope("agent-one-as") monotonic monotonic (s32), addrspace 3) ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[ATOMIC_CMPXCHG]](s32), [[COPY1]] - ; CHECK-NEXT: S_ENDPGM 0, implicit [[ATOMIC_CMPXCHG]](s32), implicit [[ICMP]](s1) + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY [[ATOMIC_CMPXCHG]](s32) + ; CHECK-NEXT: S_ENDPGM 0, implicit [[COPY3]](s32), implicit [[ICMP]](s1) %0:_(p3) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 %2:_(s32) = COPY $vgpr2 @@ -87,7 +90,8 @@ body: | ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[COPY2]](s64), [[COPY1]](s64) ; CHECK-NEXT: [[AMDGPU_ATOMIC_CMPXCHG:%[0-9]+]]:_(s64) = G_AMDGPU_ATOMIC_CMPXCHG [[COPY]](p1), [[BUILD_VECTOR]] :: (load store syncscope("agent-one-as") monotonic monotonic (s64), addrspace 1) ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[AMDGPU_ATOMIC_CMPXCHG]](s64), [[COPY1]] - ; CHECK-NEXT: S_ENDPGM 0, implicit [[AMDGPU_ATOMIC_CMPXCHG]](s64), implicit [[ICMP]](s1) + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s64) = COPY [[AMDGPU_ATOMIC_CMPXCHG]](s64) + ; CHECK-NEXT: S_ENDPGM 0, implicit [[COPY3]](s64), implicit [[ICMP]](s1) %0:_(p1) = COPY $vgpr0_vgpr1 %1:_(s64) = COPY $vgpr2_vgpr3 %2:_(s64) = COPY $vgpr4_vgpr5 @@ -110,7 +114,8 @@ body: | ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY $vgpr3_vgpr4 ; CHECK-NEXT: [[ATOMIC_CMPXCHG:%[0-9]+]]:_(s64) = G_ATOMIC_CMPXCHG [[COPY]](p3), [[COPY1]], [[COPY2]] :: (load store syncscope("agent-one-as") monotonic monotonic (s64), addrspace 3) ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[ATOMIC_CMPXCHG]](s64), [[COPY1]] - ; CHECK-NEXT: S_ENDPGM 0, implicit [[ATOMIC_CMPXCHG]](s64), implicit [[ICMP]](s1) + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s64) = COPY [[ATOMIC_CMPXCHG]](s64) + ; CHECK-NEXT: S_ENDPGM 0, implicit [[COPY3]](s64), implicit [[ICMP]](s1) %0:_(p3) = COPY $vgpr0 %1:_(s64) = COPY $vgpr1_vgpr2 %2:_(s64) = COPY $vgpr3_vgpr4 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ctlz-zero-undef.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ctlz-zero-undef.mir index e9f8180aae66bb0a27550c0b3673c7610c3fb173..fed277d7d10d0826f5988d78fea02992ec5ee19f 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ctlz-zero-undef.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ctlz-zero-undef.mir @@ -64,9 +64,7 @@ body: | ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF [[COPY]](s32) - ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 - ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[CTLZ_ZERO_UNDEF]], [[C]] - ; CHECK-NEXT: $vgpr0 = COPY [[AND]](s32) + ; CHECK-NEXT: $vgpr0 = COPY [[CTLZ_ZERO_UNDEF]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s16) = G_CTLZ_ZERO_UNDEF %0 %2:_(s32) = G_ZEXT %1 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddo.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddo.mir index dba20e128237cdc748136f16d954d6acd04ba925..eb86a981c9f1e0e33099997356a316df1c4f6a53 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddo.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddo.mir @@ -86,8 +86,9 @@ body: | ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[ADD]](s32), [[COPY]] ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY1]](s32), [[C]] ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR [[ICMP1]], [[ICMP]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[XOR]](s1) - ; CHECK-NEXT: $vgpr0 = COPY [[ADD]](s32) + ; CHECK-NEXT: $vgpr0 = COPY [[COPY2]](s32) ; CHECK-NEXT: $vgpr1 = COPY [[ZEXT]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 @@ -117,8 +118,9 @@ body: | ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV]](s64), [[COPY]] ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY1]](s64), [[C]] ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR [[ICMP1]], [[ICMP]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[MV]](s64) ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[XOR]](s1) - ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[MV]](s64) + ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[COPY2]](s64) ; CHECK-NEXT: $vgpr2 = COPY [[ZEXT]](s32) %0:_(s64) = COPY $vgpr0_vgpr1 %1:_(s64) = COPY $vgpr2_vgpr3 @@ -172,11 +174,12 @@ body: | ; CHECK-NEXT: [[XOR1:%[0-9]+]]:_(s1) = G_XOR [[ICMP3]], [[ICMP1]] ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[XOR]](s1) ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[XOR1]](s1) + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(<2 x s16>) = COPY [[BITCAST2]](<2 x s16>) ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[ANYEXT]], [[C3]] ; CHECK-NEXT: [[AND3:%[0-9]+]]:_(s32) = G_AND [[ANYEXT1]], [[C3]] ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[AND2]](s32), [[AND3]](s32) - ; CHECK-NEXT: $vgpr0 = COPY [[BITCAST2]](<2 x s16>) + ; CHECK-NEXT: $vgpr0 = COPY [[COPY3]](<2 x s16>) ; CHECK-NEXT: $vgpr1_vgpr2 = COPY [[BUILD_VECTOR]](<2 x s32>) %0:_(<2 x s16>) = COPY $vgpr0 %1:_(<2 x s16>) = COPY $vgpr1 @@ -360,13 +363,14 @@ body: | ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[XOR1]](s1) ; CHECK-NEXT: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[XOR2]](s1) ; CHECK-NEXT: [[ANYEXT3:%[0-9]+]]:_(s32) = G_ANYEXT [[XOR3]](s1) + ; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(<4 x s16>) = COPY [[CONCAT_VECTORS]](<4 x s16>) ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 ; CHECK-NEXT: [[AND4:%[0-9]+]]:_(s32) = G_AND [[ANYEXT]], [[C3]] ; CHECK-NEXT: [[AND5:%[0-9]+]]:_(s32) = G_AND [[ANYEXT1]], [[C3]] ; CHECK-NEXT: [[AND6:%[0-9]+]]:_(s32) = G_AND [[ANYEXT2]], [[C3]] ; CHECK-NEXT: [[AND7:%[0-9]+]]:_(s32) = G_AND [[ANYEXT3]], [[C3]] ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[AND4]](s32), [[AND5]](s32), [[AND6]](s32), [[AND7]](s32) - ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[CONCAT_VECTORS]](<4 x s16>) + ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[COPY5]](<4 x s16>) ; CHECK-NEXT: $vgpr2_vgpr3_vgpr4_vgpr5 = COPY [[BUILD_VECTOR]](<4 x s32>) %0:_(<4 x s16>) = COPY $vgpr0_vgpr1 %1:_(<4 x s16>) = COPY $vgpr1_vgpr2 @@ -403,11 +407,12 @@ body: | ; CHECK-NEXT: [[XOR1:%[0-9]+]]:_(s1) = G_XOR [[ICMP3]], [[ICMP1]] ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[XOR]](s1) ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[XOR1]](s1) + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(<2 x s32>) = COPY [[BUILD_VECTOR]](<2 x s32>) ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ANYEXT]], [[C1]] ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[ANYEXT1]], [[C1]] ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[AND]](s32), [[AND1]](s32) - ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) + ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[COPY2]](<2 x s32>) ; CHECK-NEXT: $vgpr2_vgpr3 = COPY [[BUILD_VECTOR1]](<2 x s32>) %0:_(<2 x s32>) = COPY $vgpr0_vgpr1 %1:_(<2 x s32>) = COPY $vgpr2_vgpr3 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddsat.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddsat.mir index 93d00714158be5a16295892aaaaf7e18574bf789..80b3166108ad8e48f34195f73fec6940334ba6c9 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddsat.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddsat.mir @@ -955,15 +955,16 @@ body: | ; GFX6-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV]](s64), [[COPY]] ; GFX6-NEXT: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY1]](s64), [[C]] ; GFX6-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR [[ICMP1]], [[ICMP]] + ; GFX6-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[MV]](s64) ; GFX6-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 63 - ; GFX6-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[MV]], [[C1]](s32) + ; GFX6-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY2]], [[C1]](s32) ; GFX6-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808 ; GFX6-NEXT: [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ASHR]](s64) ; GFX6-NEXT: [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) ; GFX6-NEXT: [[UADDO2:%[0-9]+]]:_(s32), [[UADDO3:%[0-9]+]]:_(s1) = G_UADDO [[UV4]], [[UV6]] ; GFX6-NEXT: [[UADDE2:%[0-9]+]]:_(s32), [[UADDE3:%[0-9]+]]:_(s1) = G_UADDE [[UV5]], [[UV7]], [[UADDO3]] ; GFX6-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[UADDO2]](s32), [[UADDE2]](s32) - ; GFX6-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[MV]] + ; GFX6-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[COPY2]] ; GFX6-NEXT: $vgpr0_vgpr1 = COPY [[SELECT]](s64) ; ; GFX8-LABEL: name: saddsat_s64 @@ -980,15 +981,16 @@ body: | ; GFX8-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV]](s64), [[COPY]] ; GFX8-NEXT: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY1]](s64), [[C]] ; GFX8-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR [[ICMP1]], [[ICMP]] + ; GFX8-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[MV]](s64) ; GFX8-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 63 - ; GFX8-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[MV]], [[C1]](s32) + ; GFX8-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY2]], [[C1]](s32) ; GFX8-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808 ; GFX8-NEXT: [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ASHR]](s64) ; GFX8-NEXT: [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) ; GFX8-NEXT: [[UADDO2:%[0-9]+]]:_(s32), [[UADDO3:%[0-9]+]]:_(s1) = G_UADDO [[UV4]], [[UV6]] ; GFX8-NEXT: [[UADDE2:%[0-9]+]]:_(s32), [[UADDE3:%[0-9]+]]:_(s1) = G_UADDE [[UV5]], [[UV7]], [[UADDO3]] ; GFX8-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[UADDO2]](s32), [[UADDE2]](s32) - ; GFX8-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[MV]] + ; GFX8-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[COPY2]] ; GFX8-NEXT: $vgpr0_vgpr1 = COPY [[SELECT]](s64) ; ; GFX9-LABEL: name: saddsat_s64 @@ -1005,15 +1007,16 @@ body: | ; GFX9-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV]](s64), [[COPY]] ; GFX9-NEXT: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[COPY1]](s64), [[C]] ; GFX9-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR [[ICMP1]], [[ICMP]] + ; GFX9-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[MV]](s64) ; GFX9-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 63 - ; GFX9-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[MV]], [[C1]](s32) + ; GFX9-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY2]], [[C1]](s32) ; GFX9-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808 ; GFX9-NEXT: [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ASHR]](s64) ; GFX9-NEXT: [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) ; GFX9-NEXT: [[UADDO2:%[0-9]+]]:_(s32), [[UADDO3:%[0-9]+]]:_(s1) = G_UADDO [[UV4]], [[UV6]] ; GFX9-NEXT: [[UADDE2:%[0-9]+]]:_(s32), [[UADDE3:%[0-9]+]]:_(s1) = G_UADDE [[UV5]], [[UV7]], [[UADDO3]] ; GFX9-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[UADDO2]](s32), [[UADDE2]](s32) - ; GFX9-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[MV]] + ; GFX9-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[COPY2]] ; GFX9-NEXT: $vgpr0_vgpr1 = COPY [[SELECT]](s64) %0:_(s64) = COPY $vgpr0_vgpr1 %1:_(s64) = COPY $vgpr2_vgpr3 @@ -1043,15 +1046,16 @@ body: | ; GFX6-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV]](s64), [[UV]] ; GFX6-NEXT: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[UV2]](s64), [[C]] ; GFX6-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR [[ICMP1]], [[ICMP]] + ; GFX6-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[MV]](s64) ; GFX6-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 63 - ; GFX6-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[MV]], [[C1]](s32) + ; GFX6-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY2]], [[C1]](s32) ; GFX6-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808 ; GFX6-NEXT: [[UV8:%[0-9]+]]:_(s32), [[UV9:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ASHR]](s64) ; GFX6-NEXT: [[UV10:%[0-9]+]]:_(s32), [[UV11:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) ; GFX6-NEXT: [[UADDO2:%[0-9]+]]:_(s32), [[UADDO3:%[0-9]+]]:_(s1) = G_UADDO [[UV8]], [[UV10]] ; GFX6-NEXT: [[UADDE2:%[0-9]+]]:_(s32), [[UADDE3:%[0-9]+]]:_(s1) = G_UADDE [[UV9]], [[UV11]], [[UADDO3]] ; GFX6-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[UADDO2]](s32), [[UADDE2]](s32) - ; GFX6-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[MV]] + ; GFX6-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[COPY2]] ; GFX6-NEXT: [[UV12:%[0-9]+]]:_(s32), [[UV13:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[UV1]](s64) ; GFX6-NEXT: [[UV14:%[0-9]+]]:_(s32), [[UV15:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[UV3]](s64) ; GFX6-NEXT: [[UADDO4:%[0-9]+]]:_(s32), [[UADDO5:%[0-9]+]]:_(s1) = G_UADDO [[UV12]], [[UV14]] @@ -1060,13 +1064,14 @@ body: | ; GFX6-NEXT: [[ICMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV2]](s64), [[UV1]] ; GFX6-NEXT: [[ICMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[UV3]](s64), [[C]] ; GFX6-NEXT: [[XOR1:%[0-9]+]]:_(s1) = G_XOR [[ICMP3]], [[ICMP2]] - ; GFX6-NEXT: [[ASHR1:%[0-9]+]]:_(s64) = G_ASHR [[MV2]], [[C1]](s32) + ; GFX6-NEXT: [[COPY3:%[0-9]+]]:_(s64) = COPY [[MV2]](s64) + ; GFX6-NEXT: [[ASHR1:%[0-9]+]]:_(s64) = G_ASHR [[COPY3]], [[C1]](s32) ; GFX6-NEXT: [[UV16:%[0-9]+]]:_(s32), [[UV17:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ASHR1]](s64) ; GFX6-NEXT: [[UV18:%[0-9]+]]:_(s32), [[UV19:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) ; GFX6-NEXT: [[UADDO6:%[0-9]+]]:_(s32), [[UADDO7:%[0-9]+]]:_(s1) = G_UADDO [[UV16]], [[UV18]] ; GFX6-NEXT: [[UADDE6:%[0-9]+]]:_(s32), [[UADDE7:%[0-9]+]]:_(s1) = G_UADDE [[UV17]], [[UV19]], [[UADDO7]] ; GFX6-NEXT: [[MV3:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[UADDO6]](s32), [[UADDE6]](s32) - ; GFX6-NEXT: [[SELECT1:%[0-9]+]]:_(s64) = G_SELECT [[XOR1]](s1), [[MV3]], [[MV2]] + ; GFX6-NEXT: [[SELECT1:%[0-9]+]]:_(s64) = G_SELECT [[XOR1]](s1), [[MV3]], [[COPY3]] ; GFX6-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[SELECT]](s64), [[SELECT1]](s64) ; GFX6-NEXT: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x s64>) ; @@ -1086,15 +1091,16 @@ body: | ; GFX8-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV]](s64), [[UV]] ; GFX8-NEXT: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[UV2]](s64), [[C]] ; GFX8-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR [[ICMP1]], [[ICMP]] + ; GFX8-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[MV]](s64) ; GFX8-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 63 - ; GFX8-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[MV]], [[C1]](s32) + ; GFX8-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY2]], [[C1]](s32) ; GFX8-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808 ; GFX8-NEXT: [[UV8:%[0-9]+]]:_(s32), [[UV9:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ASHR]](s64) ; GFX8-NEXT: [[UV10:%[0-9]+]]:_(s32), [[UV11:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) ; GFX8-NEXT: [[UADDO2:%[0-9]+]]:_(s32), [[UADDO3:%[0-9]+]]:_(s1) = G_UADDO [[UV8]], [[UV10]] ; GFX8-NEXT: [[UADDE2:%[0-9]+]]:_(s32), [[UADDE3:%[0-9]+]]:_(s1) = G_UADDE [[UV9]], [[UV11]], [[UADDO3]] ; GFX8-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[UADDO2]](s32), [[UADDE2]](s32) - ; GFX8-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[MV]] + ; GFX8-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[COPY2]] ; GFX8-NEXT: [[UV12:%[0-9]+]]:_(s32), [[UV13:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[UV1]](s64) ; GFX8-NEXT: [[UV14:%[0-9]+]]:_(s32), [[UV15:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[UV3]](s64) ; GFX8-NEXT: [[UADDO4:%[0-9]+]]:_(s32), [[UADDO5:%[0-9]+]]:_(s1) = G_UADDO [[UV12]], [[UV14]] @@ -1103,13 +1109,14 @@ body: | ; GFX8-NEXT: [[ICMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV2]](s64), [[UV1]] ; GFX8-NEXT: [[ICMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[UV3]](s64), [[C]] ; GFX8-NEXT: [[XOR1:%[0-9]+]]:_(s1) = G_XOR [[ICMP3]], [[ICMP2]] - ; GFX8-NEXT: [[ASHR1:%[0-9]+]]:_(s64) = G_ASHR [[MV2]], [[C1]](s32) + ; GFX8-NEXT: [[COPY3:%[0-9]+]]:_(s64) = COPY [[MV2]](s64) + ; GFX8-NEXT: [[ASHR1:%[0-9]+]]:_(s64) = G_ASHR [[COPY3]], [[C1]](s32) ; GFX8-NEXT: [[UV16:%[0-9]+]]:_(s32), [[UV17:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ASHR1]](s64) ; GFX8-NEXT: [[UV18:%[0-9]+]]:_(s32), [[UV19:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) ; GFX8-NEXT: [[UADDO6:%[0-9]+]]:_(s32), [[UADDO7:%[0-9]+]]:_(s1) = G_UADDO [[UV16]], [[UV18]] ; GFX8-NEXT: [[UADDE6:%[0-9]+]]:_(s32), [[UADDE7:%[0-9]+]]:_(s1) = G_UADDE [[UV17]], [[UV19]], [[UADDO7]] ; GFX8-NEXT: [[MV3:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[UADDO6]](s32), [[UADDE6]](s32) - ; GFX8-NEXT: [[SELECT1:%[0-9]+]]:_(s64) = G_SELECT [[XOR1]](s1), [[MV3]], [[MV2]] + ; GFX8-NEXT: [[SELECT1:%[0-9]+]]:_(s64) = G_SELECT [[XOR1]](s1), [[MV3]], [[COPY3]] ; GFX8-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[SELECT]](s64), [[SELECT1]](s64) ; GFX8-NEXT: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x s64>) ; @@ -1129,15 +1136,16 @@ body: | ; GFX9-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV]](s64), [[UV]] ; GFX9-NEXT: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[UV2]](s64), [[C]] ; GFX9-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR [[ICMP1]], [[ICMP]] + ; GFX9-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[MV]](s64) ; GFX9-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 63 - ; GFX9-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[MV]], [[C1]](s32) + ; GFX9-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY2]], [[C1]](s32) ; GFX9-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808 ; GFX9-NEXT: [[UV8:%[0-9]+]]:_(s32), [[UV9:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ASHR]](s64) ; GFX9-NEXT: [[UV10:%[0-9]+]]:_(s32), [[UV11:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) ; GFX9-NEXT: [[UADDO2:%[0-9]+]]:_(s32), [[UADDO3:%[0-9]+]]:_(s1) = G_UADDO [[UV8]], [[UV10]] ; GFX9-NEXT: [[UADDE2:%[0-9]+]]:_(s32), [[UADDE3:%[0-9]+]]:_(s1) = G_UADDE [[UV9]], [[UV11]], [[UADDO3]] ; GFX9-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[UADDO2]](s32), [[UADDE2]](s32) - ; GFX9-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[MV]] + ; GFX9-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[COPY2]] ; GFX9-NEXT: [[UV12:%[0-9]+]]:_(s32), [[UV13:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[UV1]](s64) ; GFX9-NEXT: [[UV14:%[0-9]+]]:_(s32), [[UV15:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[UV3]](s64) ; GFX9-NEXT: [[UADDO4:%[0-9]+]]:_(s32), [[UADDO5:%[0-9]+]]:_(s1) = G_UADDO [[UV12]], [[UV14]] @@ -1146,13 +1154,14 @@ body: | ; GFX9-NEXT: [[ICMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV2]](s64), [[UV1]] ; GFX9-NEXT: [[ICMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[UV3]](s64), [[C]] ; GFX9-NEXT: [[XOR1:%[0-9]+]]:_(s1) = G_XOR [[ICMP3]], [[ICMP2]] - ; GFX9-NEXT: [[ASHR1:%[0-9]+]]:_(s64) = G_ASHR [[MV2]], [[C1]](s32) + ; GFX9-NEXT: [[COPY3:%[0-9]+]]:_(s64) = COPY [[MV2]](s64) + ; GFX9-NEXT: [[ASHR1:%[0-9]+]]:_(s64) = G_ASHR [[COPY3]], [[C1]](s32) ; GFX9-NEXT: [[UV16:%[0-9]+]]:_(s32), [[UV17:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ASHR1]](s64) ; GFX9-NEXT: [[UV18:%[0-9]+]]:_(s32), [[UV19:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) ; GFX9-NEXT: [[UADDO6:%[0-9]+]]:_(s32), [[UADDO7:%[0-9]+]]:_(s1) = G_UADDO [[UV16]], [[UV18]] ; GFX9-NEXT: [[UADDE6:%[0-9]+]]:_(s32), [[UADDE7:%[0-9]+]]:_(s1) = G_UADDE [[UV17]], [[UV19]], [[UADDO7]] ; GFX9-NEXT: [[MV3:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[UADDO6]](s32), [[UADDE6]](s32) - ; GFX9-NEXT: [[SELECT1:%[0-9]+]]:_(s64) = G_SELECT [[XOR1]](s1), [[MV3]], [[MV2]] + ; GFX9-NEXT: [[SELECT1:%[0-9]+]]:_(s64) = G_SELECT [[XOR1]](s1), [[MV3]], [[COPY3]] ; GFX9-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[SELECT]](s64), [[SELECT1]](s64) ; GFX9-NEXT: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x s64>) %0:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubo.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubo.mir index 57b1ab9b194ec507422879efe9027bbc0722986b..220450c5e4ec68196e94b52c251e56ceef84756e 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubo.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubo.mir @@ -86,8 +86,9 @@ body: | ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[SUB]](s32), [[COPY]] ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), [[COPY1]](s32), [[C]] ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR [[ICMP1]], [[ICMP]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY [[SUB]](s32) ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[XOR]](s1) - ; CHECK-NEXT: $vgpr0 = COPY [[SUB]](s32) + ; CHECK-NEXT: $vgpr0 = COPY [[COPY2]](s32) ; CHECK-NEXT: $vgpr1 = COPY [[ZEXT]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 @@ -117,8 +118,9 @@ body: | ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV]](s64), [[COPY]] ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), [[COPY1]](s64), [[C]] ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR [[ICMP1]], [[ICMP]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[MV]](s64) ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[XOR]](s1) - ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[MV]](s64) + ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[COPY2]](s64) ; CHECK-NEXT: $vgpr2 = COPY [[ZEXT]](s32) %0:_(s64) = COPY $vgpr0_vgpr1 %1:_(s64) = COPY $vgpr2_vgpr3 @@ -172,11 +174,12 @@ body: | ; CHECK-NEXT: [[XOR1:%[0-9]+]]:_(s1) = G_XOR [[ICMP3]], [[ICMP1]] ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[XOR]](s1) ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[XOR1]](s1) + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(<2 x s16>) = COPY [[BITCAST2]](<2 x s16>) ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[ANYEXT]], [[C3]] ; CHECK-NEXT: [[AND3:%[0-9]+]]:_(s32) = G_AND [[ANYEXT1]], [[C3]] ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[AND2]](s32), [[AND3]](s32) - ; CHECK-NEXT: $vgpr0 = COPY [[BITCAST2]](<2 x s16>) + ; CHECK-NEXT: $vgpr0 = COPY [[COPY3]](<2 x s16>) ; CHECK-NEXT: $vgpr1_vgpr2 = COPY [[BUILD_VECTOR]](<2 x s32>) %0:_(<2 x s16>) = COPY $vgpr0 %1:_(<2 x s16>) = COPY $vgpr1 @@ -360,13 +363,14 @@ body: | ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[XOR1]](s1) ; CHECK-NEXT: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[XOR2]](s1) ; CHECK-NEXT: [[ANYEXT3:%[0-9]+]]:_(s32) = G_ANYEXT [[XOR3]](s1) + ; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(<4 x s16>) = COPY [[CONCAT_VECTORS]](<4 x s16>) ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 ; CHECK-NEXT: [[AND4:%[0-9]+]]:_(s32) = G_AND [[ANYEXT]], [[C3]] ; CHECK-NEXT: [[AND5:%[0-9]+]]:_(s32) = G_AND [[ANYEXT1]], [[C3]] ; CHECK-NEXT: [[AND6:%[0-9]+]]:_(s32) = G_AND [[ANYEXT2]], [[C3]] ; CHECK-NEXT: [[AND7:%[0-9]+]]:_(s32) = G_AND [[ANYEXT3]], [[C3]] ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[AND4]](s32), [[AND5]](s32), [[AND6]](s32), [[AND7]](s32) - ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[CONCAT_VECTORS]](<4 x s16>) + ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[COPY5]](<4 x s16>) ; CHECK-NEXT: $vgpr2_vgpr3_vgpr4_vgpr5 = COPY [[BUILD_VECTOR]](<4 x s32>) %0:_(<4 x s16>) = COPY $vgpr0_vgpr1 %1:_(<4 x s16>) = COPY $vgpr1_vgpr2 @@ -403,11 +407,12 @@ body: | ; CHECK-NEXT: [[XOR1:%[0-9]+]]:_(s1) = G_XOR [[ICMP3]], [[ICMP1]] ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[XOR]](s1) ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[XOR1]](s1) + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(<2 x s32>) = COPY [[BUILD_VECTOR]](<2 x s32>) ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ANYEXT]], [[C1]] ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[ANYEXT1]], [[C1]] ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[AND]](s32), [[AND1]](s32) - ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) + ; CHECK-NEXT: $vgpr0_vgpr1 = COPY [[COPY2]](<2 x s32>) ; CHECK-NEXT: $vgpr2_vgpr3 = COPY [[BUILD_VECTOR1]](<2 x s32>) %0:_(<2 x s32>) = COPY $vgpr0_vgpr1 %1:_(<2 x s32>) = COPY $vgpr2_vgpr3 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubsat.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubsat.mir index 33a8cda8e84b3e3628b075bb453b96326274b752..49fb6e9bdaf35cd1cf900485ba06301309c35c45 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubsat.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubsat.mir @@ -955,15 +955,16 @@ body: | ; GFX6-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV]](s64), [[COPY]] ; GFX6-NEXT: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), [[COPY1]](s64), [[C]] ; GFX6-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR [[ICMP1]], [[ICMP]] + ; GFX6-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[MV]](s64) ; GFX6-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 63 - ; GFX6-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[MV]], [[C1]](s32) + ; GFX6-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY2]], [[C1]](s32) ; GFX6-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808 ; GFX6-NEXT: [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ASHR]](s64) ; GFX6-NEXT: [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) ; GFX6-NEXT: [[UADDO:%[0-9]+]]:_(s32), [[UADDO1:%[0-9]+]]:_(s1) = G_UADDO [[UV4]], [[UV6]] ; GFX6-NEXT: [[UADDE:%[0-9]+]]:_(s32), [[UADDE1:%[0-9]+]]:_(s1) = G_UADDE [[UV5]], [[UV7]], [[UADDO1]] ; GFX6-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[UADDO]](s32), [[UADDE]](s32) - ; GFX6-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[MV]] + ; GFX6-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[COPY2]] ; GFX6-NEXT: $vgpr0_vgpr1 = COPY [[SELECT]](s64) ; ; GFX8-LABEL: name: ssubsat_s64 @@ -980,15 +981,16 @@ body: | ; GFX8-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV]](s64), [[COPY]] ; GFX8-NEXT: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), [[COPY1]](s64), [[C]] ; GFX8-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR [[ICMP1]], [[ICMP]] + ; GFX8-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[MV]](s64) ; GFX8-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 63 - ; GFX8-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[MV]], [[C1]](s32) + ; GFX8-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY2]], [[C1]](s32) ; GFX8-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808 ; GFX8-NEXT: [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ASHR]](s64) ; GFX8-NEXT: [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) ; GFX8-NEXT: [[UADDO:%[0-9]+]]:_(s32), [[UADDO1:%[0-9]+]]:_(s1) = G_UADDO [[UV4]], [[UV6]] ; GFX8-NEXT: [[UADDE:%[0-9]+]]:_(s32), [[UADDE1:%[0-9]+]]:_(s1) = G_UADDE [[UV5]], [[UV7]], [[UADDO1]] ; GFX8-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[UADDO]](s32), [[UADDE]](s32) - ; GFX8-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[MV]] + ; GFX8-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[COPY2]] ; GFX8-NEXT: $vgpr0_vgpr1 = COPY [[SELECT]](s64) ; ; GFX9-LABEL: name: ssubsat_s64 @@ -1005,15 +1007,16 @@ body: | ; GFX9-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV]](s64), [[COPY]] ; GFX9-NEXT: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), [[COPY1]](s64), [[C]] ; GFX9-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR [[ICMP1]], [[ICMP]] + ; GFX9-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[MV]](s64) ; GFX9-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 63 - ; GFX9-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[MV]], [[C1]](s32) + ; GFX9-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY2]], [[C1]](s32) ; GFX9-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808 ; GFX9-NEXT: [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ASHR]](s64) ; GFX9-NEXT: [[UV6:%[0-9]+]]:_(s32), [[UV7:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) ; GFX9-NEXT: [[UADDO:%[0-9]+]]:_(s32), [[UADDO1:%[0-9]+]]:_(s1) = G_UADDO [[UV4]], [[UV6]] ; GFX9-NEXT: [[UADDE:%[0-9]+]]:_(s32), [[UADDE1:%[0-9]+]]:_(s1) = G_UADDE [[UV5]], [[UV7]], [[UADDO1]] ; GFX9-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[UADDO]](s32), [[UADDE]](s32) - ; GFX9-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[MV]] + ; GFX9-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[COPY2]] ; GFX9-NEXT: $vgpr0_vgpr1 = COPY [[SELECT]](s64) %0:_(s64) = COPY $vgpr0_vgpr1 %1:_(s64) = COPY $vgpr2_vgpr3 @@ -1043,15 +1046,16 @@ body: | ; GFX6-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV]](s64), [[UV]] ; GFX6-NEXT: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), [[UV2]](s64), [[C]] ; GFX6-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR [[ICMP1]], [[ICMP]] + ; GFX6-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[MV]](s64) ; GFX6-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 63 - ; GFX6-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[MV]], [[C1]](s32) + ; GFX6-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY2]], [[C1]](s32) ; GFX6-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808 ; GFX6-NEXT: [[UV8:%[0-9]+]]:_(s32), [[UV9:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ASHR]](s64) ; GFX6-NEXT: [[UV10:%[0-9]+]]:_(s32), [[UV11:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) ; GFX6-NEXT: [[UADDO:%[0-9]+]]:_(s32), [[UADDO1:%[0-9]+]]:_(s1) = G_UADDO [[UV8]], [[UV10]] ; GFX6-NEXT: [[UADDE:%[0-9]+]]:_(s32), [[UADDE1:%[0-9]+]]:_(s1) = G_UADDE [[UV9]], [[UV11]], [[UADDO1]] ; GFX6-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[UADDO]](s32), [[UADDE]](s32) - ; GFX6-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[MV]] + ; GFX6-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[COPY2]] ; GFX6-NEXT: [[UV12:%[0-9]+]]:_(s32), [[UV13:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[UV1]](s64) ; GFX6-NEXT: [[UV14:%[0-9]+]]:_(s32), [[UV15:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[UV3]](s64) ; GFX6-NEXT: [[USUBO2:%[0-9]+]]:_(s32), [[USUBO3:%[0-9]+]]:_(s1) = G_USUBO [[UV12]], [[UV14]] @@ -1060,13 +1064,14 @@ body: | ; GFX6-NEXT: [[ICMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV2]](s64), [[UV1]] ; GFX6-NEXT: [[ICMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), [[UV3]](s64), [[C]] ; GFX6-NEXT: [[XOR1:%[0-9]+]]:_(s1) = G_XOR [[ICMP3]], [[ICMP2]] - ; GFX6-NEXT: [[ASHR1:%[0-9]+]]:_(s64) = G_ASHR [[MV2]], [[C1]](s32) + ; GFX6-NEXT: [[COPY3:%[0-9]+]]:_(s64) = COPY [[MV2]](s64) + ; GFX6-NEXT: [[ASHR1:%[0-9]+]]:_(s64) = G_ASHR [[COPY3]], [[C1]](s32) ; GFX6-NEXT: [[UV16:%[0-9]+]]:_(s32), [[UV17:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ASHR1]](s64) ; GFX6-NEXT: [[UV18:%[0-9]+]]:_(s32), [[UV19:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) ; GFX6-NEXT: [[UADDO2:%[0-9]+]]:_(s32), [[UADDO3:%[0-9]+]]:_(s1) = G_UADDO [[UV16]], [[UV18]] ; GFX6-NEXT: [[UADDE2:%[0-9]+]]:_(s32), [[UADDE3:%[0-9]+]]:_(s1) = G_UADDE [[UV17]], [[UV19]], [[UADDO3]] ; GFX6-NEXT: [[MV3:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[UADDO2]](s32), [[UADDE2]](s32) - ; GFX6-NEXT: [[SELECT1:%[0-9]+]]:_(s64) = G_SELECT [[XOR1]](s1), [[MV3]], [[MV2]] + ; GFX6-NEXT: [[SELECT1:%[0-9]+]]:_(s64) = G_SELECT [[XOR1]](s1), [[MV3]], [[COPY3]] ; GFX6-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[SELECT]](s64), [[SELECT1]](s64) ; GFX6-NEXT: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x s64>) ; @@ -1086,15 +1091,16 @@ body: | ; GFX8-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV]](s64), [[UV]] ; GFX8-NEXT: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), [[UV2]](s64), [[C]] ; GFX8-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR [[ICMP1]], [[ICMP]] + ; GFX8-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[MV]](s64) ; GFX8-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 63 - ; GFX8-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[MV]], [[C1]](s32) + ; GFX8-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY2]], [[C1]](s32) ; GFX8-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808 ; GFX8-NEXT: [[UV8:%[0-9]+]]:_(s32), [[UV9:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ASHR]](s64) ; GFX8-NEXT: [[UV10:%[0-9]+]]:_(s32), [[UV11:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) ; GFX8-NEXT: [[UADDO:%[0-9]+]]:_(s32), [[UADDO1:%[0-9]+]]:_(s1) = G_UADDO [[UV8]], [[UV10]] ; GFX8-NEXT: [[UADDE:%[0-9]+]]:_(s32), [[UADDE1:%[0-9]+]]:_(s1) = G_UADDE [[UV9]], [[UV11]], [[UADDO1]] ; GFX8-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[UADDO]](s32), [[UADDE]](s32) - ; GFX8-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[MV]] + ; GFX8-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[COPY2]] ; GFX8-NEXT: [[UV12:%[0-9]+]]:_(s32), [[UV13:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[UV1]](s64) ; GFX8-NEXT: [[UV14:%[0-9]+]]:_(s32), [[UV15:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[UV3]](s64) ; GFX8-NEXT: [[USUBO2:%[0-9]+]]:_(s32), [[USUBO3:%[0-9]+]]:_(s1) = G_USUBO [[UV12]], [[UV14]] @@ -1103,13 +1109,14 @@ body: | ; GFX8-NEXT: [[ICMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV2]](s64), [[UV1]] ; GFX8-NEXT: [[ICMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), [[UV3]](s64), [[C]] ; GFX8-NEXT: [[XOR1:%[0-9]+]]:_(s1) = G_XOR [[ICMP3]], [[ICMP2]] - ; GFX8-NEXT: [[ASHR1:%[0-9]+]]:_(s64) = G_ASHR [[MV2]], [[C1]](s32) + ; GFX8-NEXT: [[COPY3:%[0-9]+]]:_(s64) = COPY [[MV2]](s64) + ; GFX8-NEXT: [[ASHR1:%[0-9]+]]:_(s64) = G_ASHR [[COPY3]], [[C1]](s32) ; GFX8-NEXT: [[UV16:%[0-9]+]]:_(s32), [[UV17:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ASHR1]](s64) ; GFX8-NEXT: [[UV18:%[0-9]+]]:_(s32), [[UV19:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) ; GFX8-NEXT: [[UADDO2:%[0-9]+]]:_(s32), [[UADDO3:%[0-9]+]]:_(s1) = G_UADDO [[UV16]], [[UV18]] ; GFX8-NEXT: [[UADDE2:%[0-9]+]]:_(s32), [[UADDE3:%[0-9]+]]:_(s1) = G_UADDE [[UV17]], [[UV19]], [[UADDO3]] ; GFX8-NEXT: [[MV3:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[UADDO2]](s32), [[UADDE2]](s32) - ; GFX8-NEXT: [[SELECT1:%[0-9]+]]:_(s64) = G_SELECT [[XOR1]](s1), [[MV3]], [[MV2]] + ; GFX8-NEXT: [[SELECT1:%[0-9]+]]:_(s64) = G_SELECT [[XOR1]](s1), [[MV3]], [[COPY3]] ; GFX8-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[SELECT]](s64), [[SELECT1]](s64) ; GFX8-NEXT: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x s64>) ; @@ -1129,15 +1136,16 @@ body: | ; GFX9-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV]](s64), [[UV]] ; GFX9-NEXT: [[ICMP1:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), [[UV2]](s64), [[C]] ; GFX9-NEXT: [[XOR:%[0-9]+]]:_(s1) = G_XOR [[ICMP1]], [[ICMP]] + ; GFX9-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[MV]](s64) ; GFX9-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 63 - ; GFX9-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[MV]], [[C1]](s32) + ; GFX9-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY2]], [[C1]](s32) ; GFX9-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775808 ; GFX9-NEXT: [[UV8:%[0-9]+]]:_(s32), [[UV9:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ASHR]](s64) ; GFX9-NEXT: [[UV10:%[0-9]+]]:_(s32), [[UV11:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) ; GFX9-NEXT: [[UADDO:%[0-9]+]]:_(s32), [[UADDO1:%[0-9]+]]:_(s1) = G_UADDO [[UV8]], [[UV10]] ; GFX9-NEXT: [[UADDE:%[0-9]+]]:_(s32), [[UADDE1:%[0-9]+]]:_(s1) = G_UADDE [[UV9]], [[UV11]], [[UADDO1]] ; GFX9-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[UADDO]](s32), [[UADDE]](s32) - ; GFX9-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[MV]] + ; GFX9-NEXT: [[SELECT:%[0-9]+]]:_(s64) = G_SELECT [[XOR]](s1), [[MV1]], [[COPY2]] ; GFX9-NEXT: [[UV12:%[0-9]+]]:_(s32), [[UV13:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[UV1]](s64) ; GFX9-NEXT: [[UV14:%[0-9]+]]:_(s32), [[UV15:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[UV3]](s64) ; GFX9-NEXT: [[USUBO2:%[0-9]+]]:_(s32), [[USUBO3:%[0-9]+]]:_(s1) = G_USUBO [[UV12]], [[UV14]] @@ -1146,13 +1154,14 @@ body: | ; GFX9-NEXT: [[ICMP2:%[0-9]+]]:_(s1) = G_ICMP intpred(slt), [[MV2]](s64), [[UV1]] ; GFX9-NEXT: [[ICMP3:%[0-9]+]]:_(s1) = G_ICMP intpred(sgt), [[UV3]](s64), [[C]] ; GFX9-NEXT: [[XOR1:%[0-9]+]]:_(s1) = G_XOR [[ICMP3]], [[ICMP2]] - ; GFX9-NEXT: [[ASHR1:%[0-9]+]]:_(s64) = G_ASHR [[MV2]], [[C1]](s32) + ; GFX9-NEXT: [[COPY3:%[0-9]+]]:_(s64) = COPY [[MV2]](s64) + ; GFX9-NEXT: [[ASHR1:%[0-9]+]]:_(s64) = G_ASHR [[COPY3]], [[C1]](s32) ; GFX9-NEXT: [[UV16:%[0-9]+]]:_(s32), [[UV17:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ASHR1]](s64) ; GFX9-NEXT: [[UV18:%[0-9]+]]:_(s32), [[UV19:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C2]](s64) ; GFX9-NEXT: [[UADDO2:%[0-9]+]]:_(s32), [[UADDO3:%[0-9]+]]:_(s1) = G_UADDO [[UV16]], [[UV18]] ; GFX9-NEXT: [[UADDE2:%[0-9]+]]:_(s32), [[UADDE3:%[0-9]+]]:_(s1) = G_UADDE [[UV17]], [[UV19]], [[UADDO3]] ; GFX9-NEXT: [[MV3:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[UADDO2]](s32), [[UADDE2]](s32) - ; GFX9-NEXT: [[SELECT1:%[0-9]+]]:_(s64) = G_SELECT [[XOR1]](s1), [[MV3]], [[MV2]] + ; GFX9-NEXT: [[SELECT1:%[0-9]+]]:_(s64) = G_SELECT [[XOR1]](s1), [[MV3]], [[COPY3]] ; GFX9-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[SELECT]](s64), [[SELECT1]](s64) ; GFX9-NEXT: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x s64>) %0:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-trap.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-trap.mir index b4bc64812b532ac6da4cedd285d474a8c2d6eb43..305eca792cfbccd8d43b2e20826fa319f977fe1a 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-trap.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-trap.mir @@ -24,7 +24,7 @@ body: | bb.0: %0:_(s8) = G_CONSTANT i8 0 %1:_(p1) = G_CONSTANT i64 0 - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + G_TRAP bb.1: G_STORE %0, %1 :: (store 1, addrspace 1) @@ -55,7 +55,7 @@ body: | ; GCN-NEXT: S_ENDPGM 0 bb.0: %0:_(s8) = G_CONSTANT i8 0 - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + G_TRAP %1:_(p1) = G_CONSTANT i64 0 bb.1: diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.interp.inreg.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.interp.inreg.ll index 623360f6b1d9c5559f4c817d07aa87856b6e5d19..de46037e96e80249ed3882e4df5bb2aeb1a63f92 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.interp.inreg.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.interp.inreg.ll @@ -147,6 +147,34 @@ main_body: ret half %res } +define amdgpu_ps half @v_interp_rtz_f16(float inreg %i, float inreg %j, i32 inreg %m0) #0 { +; GCN-LABEL: v_interp_rtz_f16: +; GCN: ; %bb.0: ; %main_body +; GCN-NEXT: s_mov_b32 s3, exec_lo +; GCN-NEXT: s_wqm_b32 exec_lo, exec_lo +; GCN-NEXT: s_mov_b32 m0, s2 +; GCN-NEXT: lds_param_load v1, attr0.x wait_vdst:15 +; GCN-NEXT: s_mov_b32 exec_lo, s3 +; GCN-NEXT: v_mov_b32_e32 v0, s0 +; GCN-NEXT: v_mov_b32_e32 v2, s1 +; GCN-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(SKIP_1) | instid1(VALU_DEP_2) +; GCN-NEXT: v_interp_p10_rtz_f16_f32 v3, v1, v0, v1 wait_exp:0 +; GCN-NEXT: v_interp_p10_rtz_f16_f32 v0, v1, v0, v1 op_sel:[1,0,1,0] wait_exp:7 +; GCN-NEXT: v_interp_p2_rtz_f16_f32 v3, v1, v2, v3 wait_exp:7 +; GCN-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_1) +; GCN-NEXT: v_interp_p2_rtz_f16_f32 v0, v1, v2, v0 op_sel:[1,0,0,0] wait_exp:7 +; GCN-NEXT: v_add_f16_e32 v0, v3, v0 +; GCN-NEXT: ; return to shader part epilog +main_body: + %p0 = call float @llvm.amdgcn.lds.param.load(i32 0, i32 0, i32 %m0) + %l_p0 = call float @llvm.amdgcn.interp.p10.rtz.f16(float %p0, float %i, float %p0, i1 0) + %l_p1 = call half @llvm.amdgcn.interp.p2.rtz.f16(float %p0, float %j, float %l_p0, i1 0) + %h_p0 = call float @llvm.amdgcn.interp.p10.rtz.f16(float %p0, float %i, float %p0, i1 1) + %h_p1 = call half @llvm.amdgcn.interp.p2.rtz.f16(float %p0, float %j, float %h_p0, i1 1) + %res = fadd half %l_p1, %h_p1 + ret half %res +} + define amdgpu_ps half @v_interp_f16_imm_params(float inreg %i, float inreg %j) #0 { ; GCN-LABEL: v_interp_f16_imm_params: ; GCN: ; %bb.0: ; %main_body @@ -172,6 +200,8 @@ declare float @llvm.amdgcn.interp.inreg.p10(float, float, float) #0 declare float @llvm.amdgcn.interp.inreg.p2(float, float, float) #0 declare float @llvm.amdgcn.interp.inreg.p10.f16(float, float, float, i1) #0 declare half @llvm.amdgcn.interp.inreg.p2.f16(float, float, float, i1) #0 +declare float @llvm.amdgcn.interp.p10.rtz.f16(float, float, float, i1) #0 +declare half @llvm.amdgcn.interp.p2.rtz.f16(float, float, float, i1) #0 declare void @llvm.amdgcn.exp.f32(i32, i32, float, float, float, float, i1, i1) #0 declare void @llvm.amdgcn.exp.f16(i32, i32, float, float, float, float, i1, i1) #0 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.sbfe.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.sbfe.ll index 6eed92ba1d71ccc54450381566b2b6e78c446559..6d4aa3b04d7612c65758d9dab182c0bfd0294d00 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.sbfe.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.sbfe.ll @@ -670,36 +670,19 @@ define amdgpu_kernel void @bfe_sext_in_reg_i24(ptr addrspace(1) %out, ptr addrsp define amdgpu_kernel void @simplify_demanded_bfe_sdiv(ptr addrspace(1) %out, ptr addrspace(1) %in) #0 { ; GFX6-LABEL: simplify_demanded_bfe_sdiv: ; GFX6: ; %bb.0: -; GFX6-NEXT: v_rcp_iflag_f32_e32 v0, 2.0 -; GFX6-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x0 -; GFX6-NEXT: v_mul_f32_e32 v0, 0x4f7ffffe, v0 -; GFX6-NEXT: v_cvt_u32_f32_e32 v0, v0 +; GFX6-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x0 ; GFX6-NEXT: s_waitcnt lgkmcnt(0) -; GFX6-NEXT: s_load_dword s0, s[6:7], 0x0 -; GFX6-NEXT: s_mov_b32 s6, -1 -; GFX6-NEXT: s_mov_b32 s7, 0xf000 -; GFX6-NEXT: v_mul_lo_u32 v1, v0, -2 -; GFX6-NEXT: s_waitcnt lgkmcnt(0) -; GFX6-NEXT: s_bfe_i32 s0, s0, 0x100001 -; GFX6-NEXT: s_ashr_i32 s2, s0, 31 -; GFX6-NEXT: v_mul_hi_u32 v1, v0, v1 -; GFX6-NEXT: s_add_i32 s0, s0, s2 -; GFX6-NEXT: s_xor_b32 s0, s0, s2 -; GFX6-NEXT: v_add_i32_e32 v0, vcc, v0, v1 -; GFX6-NEXT: v_mul_hi_u32 v0, s0, v0 -; GFX6-NEXT: v_lshlrev_b32_e32 v1, 1, v0 -; GFX6-NEXT: v_add_i32_e32 v2, vcc, 1, v0 -; GFX6-NEXT: v_sub_i32_e32 v1, vcc, s0, v1 -; GFX6-NEXT: v_cmp_le_u32_e32 vcc, 2, v1 -; GFX6-NEXT: v_cndmask_b32_e32 v0, v0, v2, vcc -; GFX6-NEXT: v_subrev_i32_e64 v2, s[0:1], 2, v1 -; GFX6-NEXT: v_cndmask_b32_e32 v1, v1, v2, vcc -; GFX6-NEXT: v_add_i32_e32 v2, vcc, 1, v0 -; GFX6-NEXT: v_cmp_le_u32_e32 vcc, 2, v1 -; GFX6-NEXT: v_cndmask_b32_e32 v0, v0, v2, vcc -; GFX6-NEXT: v_xor_b32_e32 v0, s2, v0 -; GFX6-NEXT: v_subrev_i32_e32 v0, vcc, s2, v0 -; GFX6-NEXT: buffer_store_dword v0, off, s[4:7], 0 +; GFX6-NEXT: s_load_dword s3, s[2:3], 0x0 +; GFX6-NEXT: s_mov_b32 s2, -1 +; GFX6-NEXT: s_waitcnt lgkmcnt(0) +; GFX6-NEXT: s_bfe_i32 s3, s3, 0x100001 +; GFX6-NEXT: s_ashr_i32 s4, s3, 31 +; GFX6-NEXT: s_lshr_b32 s4, s4, 31 +; GFX6-NEXT: s_add_i32 s3, s3, s4 +; GFX6-NEXT: s_ashr_i32 s3, s3, 1 +; GFX6-NEXT: v_mov_b32_e32 v0, s3 +; GFX6-NEXT: s_mov_b32 s3, 0xf000 +; GFX6-NEXT: buffer_store_dword v0, off, s[0:3], 0 ; GFX6-NEXT: s_endpgm %src = load i32, ptr addrspace(1) %in, align 4 %bfe = call i32 @llvm.amdgcn.sbfe.i32(i32 %src, i32 1, i32 16) diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.struct.buffer.load.format.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.struct.buffer.load.format.ll index 686b849ff58f9554f01fca69bb0991cfa4dcf47e..06bd45a45cceda8ad6b9c2bb57e8eeef386c19ba 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.struct.buffer.load.format.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.struct.buffer.load.format.ll @@ -1,6 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py ; RUN: llc -global-isel -mtriple=amdgcn-mesa-mesa3d -mcpu=fiji -stop-after=instruction-select -verify-machineinstrs -o - %s | FileCheck -check-prefix=GFX8 %s ; RUN: llc -global-isel -mtriple=amdgcn-mesa-mesa3d -mcpu=gfx1200 -stop-after=instruction-select -verify-machineinstrs -o - %s | FileCheck -check-prefix=GFX12 %s +; Note that TFE instructions don't have the result initialization to zero due to stopping before finalize-isel - which is where that's inserted define amdgpu_ps float @struct_buffer_load_format_f32__sgpr_rsrc__vgpr_vindex__vgpr_voffset__sgpr_soffset(<4 x i32> inreg %rsrc, i32 %vindex, i32 %voffset, i32 inreg %soffset) { ; GFX8-LABEL: name: struct_buffer_load_format_f32__sgpr_rsrc__vgpr_vindex__vgpr_voffset__sgpr_soffset diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.struct.ptr.buffer.load.format.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.struct.ptr.buffer.load.format.ll index 9edc245549113c0478c8a824de80bb7eb959c916..1e3f94a5e39cb1533e2e06175f85c41baa25f612 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.struct.ptr.buffer.load.format.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.struct.ptr.buffer.load.format.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py ; RUN: llc -global-isel -mtriple=amdgcn-mesa-mesa3d -mcpu=fiji -stop-after=instruction-select -verify-machineinstrs -o - %s | FileCheck %s +; Note that TFE instructions don't have the result initialization to zero due to stopping before finalize-isel - which is where that's inserted define amdgpu_ps float @struct_ptr_buffer_load_format_f32__sgpr_rsrc__vgpr_vindex__vgpr_voffset__sgpr_soffset(ptr addrspace(8) inreg %rsrc, i32 %vindex, i32 %voffset, i32 inreg %soffset) { ; CHECK-LABEL: name: struct_ptr_buffer_load_format_f32__sgpr_rsrc__vgpr_vindex__vgpr_voffset__sgpr_soffset diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/saddsat.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/saddsat.ll index d36f5c0ea89d98a838762f0d0f18414add587899..a6f9bb7ee055d412678e702bad66a0413e328cff 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/saddsat.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/saddsat.ll @@ -4142,11 +4142,11 @@ define i48 @v_saddsat_i48(i48 %lhs, i48 %rhs) { ; GFX9-NEXT: v_lshlrev_b64 v[2:3], 16, v[2:3] ; GFX9-NEXT: v_add_co_u32_e32 v4, vcc, v0, v2 ; GFX9-NEXT: v_addc_co_u32_e32 v5, vcc, v1, v3, vcc -; GFX9-NEXT: v_cmp_lt_i64_e64 s[4:5], v[4:5], v[0:1] -; GFX9-NEXT: v_cmp_gt_i64_e64 s[6:7], 0, v[2:3] +; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, v[4:5], v[0:1] +; GFX9-NEXT: v_cmp_gt_i64_e64 s[4:5], 0, v[2:3] ; GFX9-NEXT: v_ashrrev_i32_e32 v0, 31, v5 -; GFX9-NEXT: v_add_co_u32_e32 v1, vcc, 0x80000000, v0 -; GFX9-NEXT: s_xor_b64 vcc, s[6:7], s[4:5] +; GFX9-NEXT: v_add_u32_e32 v1, 0x80000000, v0 +; GFX9-NEXT: s_xor_b64 vcc, s[4:5], vcc ; GFX9-NEXT: v_cndmask_b32_e32 v0, v4, v0, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v5, v1, vcc ; GFX9-NEXT: v_ashrrev_i64 v[0:1], 16, v[0:1] @@ -4162,7 +4162,7 @@ define i48 @v_saddsat_i48(i48 %lhs, i48 %rhs) { ; GFX10-NEXT: v_cmp_gt_i64_e32 vcc_lo, 0, v[2:3] ; GFX10-NEXT: v_ashrrev_i32_e32 v6, 31, v5 ; GFX10-NEXT: v_cmp_lt_i64_e64 s4, v[4:5], v[0:1] -; GFX10-NEXT: v_add_co_u32 v1, s5, 0x80000000, v6 +; GFX10-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v6 ; GFX10-NEXT: s_xor_b32 vcc_lo, vcc_lo, s4 ; GFX10-NEXT: v_cndmask_b32_e32 v0, v4, v6, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v1, v5, v1, vcc_lo @@ -4179,7 +4179,7 @@ define i48 @v_saddsat_i48(i48 %lhs, i48 %rhs) { ; GFX11-NEXT: v_cmp_gt_i64_e32 vcc_lo, 0, v[2:3] ; GFX11-NEXT: v_ashrrev_i32_e32 v6, 31, v5 ; GFX11-NEXT: v_cmp_lt_i64_e64 s0, v[4:5], v[0:1] -; GFX11-NEXT: v_add_co_u32 v1, null, 0x80000000, v6 +; GFX11-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v6 ; GFX11-NEXT: s_xor_b32 vcc_lo, vcc_lo, s0 ; GFX11-NEXT: v_dual_cndmask_b32 v0, v4, v6 :: v_dual_cndmask_b32 v1, v5, v1 ; GFX11-NEXT: v_ashrrev_i64 v[0:1], 16, v[0:1] @@ -4202,7 +4202,7 @@ define amdgpu_ps i48 @s_saddsat_i48(i48 inreg %lhs, i48 inreg %rhs) { ; GFX6-NEXT: v_cmp_lt_i64_e64 s[0:1], s[0:1], 0 ; GFX6-NEXT: s_ashr_i32 s2, s7, 31 ; GFX6-NEXT: s_ashr_i32 s5, s7, 15 -; GFX6-NEXT: s_add_u32 s2, s2, 0xffff8000 +; GFX6-NEXT: s_addk_i32 s2, 0x8000 ; GFX6-NEXT: v_mov_b32_e32 v0, s5 ; GFX6-NEXT: v_mov_b32_e32 v1, s2 ; GFX6-NEXT: v_mov_b32_e32 v2, s4 @@ -4227,7 +4227,7 @@ define amdgpu_ps i48 @s_saddsat_i48(i48 inreg %lhs, i48 inreg %rhs) { ; GFX8-NEXT: v_cmp_lt_i64_e64 s[0:1], s[0:1], 0 ; GFX8-NEXT: s_ashr_i32 s2, s7, 31 ; GFX8-NEXT: s_ashr_i32 s5, s7, 15 -; GFX8-NEXT: s_add_u32 s2, s2, 0xffff8000 +; GFX8-NEXT: s_addk_i32 s2, 0x8000 ; GFX8-NEXT: v_mov_b32_e32 v0, s5 ; GFX8-NEXT: v_mov_b32_e32 v1, s2 ; GFX8-NEXT: v_mov_b32_e32 v2, s4 @@ -4250,7 +4250,7 @@ define amdgpu_ps i48 @s_saddsat_i48(i48 inreg %lhs, i48 inreg %rhs) { ; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, s[4:5], v[0:1] ; GFX9-NEXT: v_cmp_lt_i64_e64 s[0:1], s[2:3], 0 ; GFX9-NEXT: s_ashr_i32 s2, s5, 31 -; GFX9-NEXT: s_add_u32 s3, s2, 0x80000000 +; GFX9-NEXT: s_add_i32 s3, s2, 0x80000000 ; GFX9-NEXT: v_mov_b32_e32 v0, s2 ; GFX9-NEXT: v_mov_b32_e32 v1, s3 ; GFX9-NEXT: v_mov_b32_e32 v2, s4 @@ -4274,7 +4274,7 @@ define amdgpu_ps i48 @s_saddsat_i48(i48 inreg %lhs, i48 inreg %rhs) { ; GFX10-NEXT: v_cmp_lt_i64_e64 s1, s[2:3], 0 ; GFX10-NEXT: v_mov_b32_e32 v1, s5 ; GFX10-NEXT: s_ashr_i32 s2, s5, 31 -; GFX10-NEXT: s_add_u32 s3, s2, 0x80000000 +; GFX10-NEXT: s_add_i32 s3, s2, 0x80000000 ; GFX10-NEXT: s_xor_b32 s0, s1, s0 ; GFX10-NEXT: v_cndmask_b32_e64 v0, v0, s2, s0 ; GFX10-NEXT: v_cndmask_b32_e64 v1, v1, s3, s0 @@ -4293,7 +4293,7 @@ define amdgpu_ps i48 @s_saddsat_i48(i48 inreg %lhs, i48 inreg %rhs) { ; GFX11-NEXT: v_cmp_lt_i64_e64 s0, s[4:5], s[0:1] ; GFX11-NEXT: v_cmp_lt_i64_e64 s1, s[2:3], 0 ; GFX11-NEXT: s_ashr_i32 s2, s5, 31 -; GFX11-NEXT: s_add_u32 s3, s2, 0x80000000 +; GFX11-NEXT: s_add_i32 s3, s2, 0x80000000 ; GFX11-NEXT: s_xor_b32 s0, s1, s0 ; GFX11-NEXT: v_cndmask_b32_e64 v0, v0, s2, s0 ; GFX11-NEXT: v_cndmask_b32_e64 v1, v1, s3, s0 @@ -4351,11 +4351,11 @@ define amdgpu_ps <2 x float> @saddsat_i48_sv(i48 inreg %lhs, i48 %rhs) { ; GFX9-NEXT: v_mov_b32_e32 v3, s1 ; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, s0, v0 ; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, v3, v1, vcc -; GFX9-NEXT: v_cmp_gt_i64_e64 s[0:1], s[0:1], v[2:3] -; GFX9-NEXT: v_cmp_gt_i64_e64 s[2:3], 0, v[0:1] +; GFX9-NEXT: v_cmp_gt_i64_e32 vcc, s[0:1], v[2:3] +; GFX9-NEXT: v_cmp_gt_i64_e64 s[0:1], 0, v[0:1] ; GFX9-NEXT: v_ashrrev_i32_e32 v0, 31, v3 -; GFX9-NEXT: v_add_co_u32_e32 v1, vcc, 0x80000000, v0 -; GFX9-NEXT: s_xor_b64 vcc, s[2:3], s[0:1] +; GFX9-NEXT: v_add_u32_e32 v1, 0x80000000, v0 +; GFX9-NEXT: s_xor_b64 vcc, s[0:1], vcc ; GFX9-NEXT: v_cndmask_b32_e32 v0, v2, v0, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc ; GFX9-NEXT: v_ashrrev_i64 v[0:1], 16, v[0:1] @@ -4371,7 +4371,7 @@ define amdgpu_ps <2 x float> @saddsat_i48_sv(i48 inreg %lhs, i48 %rhs) { ; GFX10-NEXT: v_ashrrev_i32_e32 v4, 31, v3 ; GFX10-NEXT: v_cmp_gt_i64_e32 vcc_lo, s[0:1], v[2:3] ; GFX10-NEXT: v_cmp_gt_i64_e64 s0, 0, v[0:1] -; GFX10-NEXT: v_add_co_u32 v1, s1, 0x80000000, v4 +; GFX10-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v4 ; GFX10-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v0, v2, v4, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc_lo @@ -4388,7 +4388,7 @@ define amdgpu_ps <2 x float> @saddsat_i48_sv(i48 inreg %lhs, i48 %rhs) { ; GFX11-NEXT: v_ashrrev_i32_e32 v4, 31, v3 ; GFX11-NEXT: v_cmp_gt_i64_e32 vcc_lo, s[0:1], v[2:3] ; GFX11-NEXT: v_cmp_gt_i64_e64 s0, 0, v[0:1] -; GFX11-NEXT: v_add_co_u32 v1, null, 0x80000000, v4 +; GFX11-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v4 ; GFX11-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX11-NEXT: v_dual_cndmask_b32 v0, v2, v4 :: v_dual_cndmask_b32 v1, v3, v1 ; GFX11-NEXT: v_ashrrev_i64 v[0:1], 16, v[0:1] @@ -4442,15 +4442,15 @@ define amdgpu_ps <2 x float> @saddsat_i48_vs(i48 %lhs, i48 inreg %rhs) { ; GFX9-LABEL: saddsat_i48_vs: ; GFX9: ; %bb.0: ; GFX9-NEXT: v_lshlrev_b64 v[0:1], 16, v[0:1] -; GFX9-NEXT: s_lshl_b64 s[2:3], s[0:1], 16 -; GFX9-NEXT: v_mov_b32_e32 v3, s3 -; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, s2, v0 +; GFX9-NEXT: s_lshl_b64 s[0:1], s[0:1], 16 +; GFX9-NEXT: v_mov_b32_e32 v3, s1 +; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, s0, v0 ; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, v1, v3, vcc -; GFX9-NEXT: v_cmp_lt_i64_e64 s[0:1], v[2:3], v[0:1] -; GFX9-NEXT: v_cmp_lt_i64_e64 s[2:3], s[2:3], 0 +; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, v[2:3], v[0:1] +; GFX9-NEXT: v_cmp_lt_i64_e64 s[0:1], s[0:1], 0 ; GFX9-NEXT: v_ashrrev_i32_e32 v0, 31, v3 -; GFX9-NEXT: v_add_co_u32_e32 v1, vcc, 0x80000000, v0 -; GFX9-NEXT: s_xor_b64 vcc, s[2:3], s[0:1] +; GFX9-NEXT: v_add_u32_e32 v1, 0x80000000, v0 +; GFX9-NEXT: s_xor_b64 vcc, s[0:1], vcc ; GFX9-NEXT: v_cndmask_b32_e32 v0, v2, v0, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc ; GFX9-NEXT: v_ashrrev_i64 v[0:1], 16, v[0:1] @@ -4466,7 +4466,7 @@ define amdgpu_ps <2 x float> @saddsat_i48_vs(i48 %lhs, i48 inreg %rhs) { ; GFX10-NEXT: v_cmp_lt_i64_e64 s0, s[0:1], 0 ; GFX10-NEXT: v_ashrrev_i32_e32 v4, 31, v3 ; GFX10-NEXT: v_cmp_lt_i64_e32 vcc_lo, v[2:3], v[0:1] -; GFX10-NEXT: v_add_co_u32 v1, s1, 0x80000000, v4 +; GFX10-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v4 ; GFX10-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v0, v2, v4, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc_lo @@ -4483,7 +4483,7 @@ define amdgpu_ps <2 x float> @saddsat_i48_vs(i48 %lhs, i48 inreg %rhs) { ; GFX11-NEXT: v_cmp_lt_i64_e64 s0, s[0:1], 0 ; GFX11-NEXT: v_ashrrev_i32_e32 v4, 31, v3 ; GFX11-NEXT: v_cmp_lt_i64_e32 vcc_lo, v[2:3], v[0:1] -; GFX11-NEXT: v_add_co_u32 v1, null, 0x80000000, v4 +; GFX11-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v4 ; GFX11-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX11-NEXT: v_dual_cndmask_b32 v0, v2, v4 :: v_dual_cndmask_b32 v1, v3, v1 ; GFX11-NEXT: v_ashrrev_i64 v[0:1], 16, v[0:1] @@ -4529,11 +4529,11 @@ define i64 @v_saddsat_i64(i64 %lhs, i64 %rhs) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: v_add_co_u32_e32 v4, vcc, v0, v2 ; GFX9-NEXT: v_addc_co_u32_e32 v5, vcc, v1, v3, vcc -; GFX9-NEXT: v_cmp_lt_i64_e64 s[4:5], v[4:5], v[0:1] -; GFX9-NEXT: v_cmp_gt_i64_e64 s[6:7], 0, v[2:3] +; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, v[4:5], v[0:1] +; GFX9-NEXT: v_cmp_gt_i64_e64 s[4:5], 0, v[2:3] ; GFX9-NEXT: v_ashrrev_i32_e32 v0, 31, v5 -; GFX9-NEXT: v_add_co_u32_e32 v1, vcc, 0x80000000, v0 -; GFX9-NEXT: s_xor_b64 vcc, s[6:7], s[4:5] +; GFX9-NEXT: v_add_u32_e32 v1, 0x80000000, v0 +; GFX9-NEXT: s_xor_b64 vcc, s[4:5], vcc ; GFX9-NEXT: v_cndmask_b32_e32 v0, v4, v0, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v5, v1, vcc ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -4546,7 +4546,7 @@ define i64 @v_saddsat_i64(i64 %lhs, i64 %rhs) { ; GFX10-NEXT: v_cmp_gt_i64_e64 s4, 0, v[2:3] ; GFX10-NEXT: v_ashrrev_i32_e32 v6, 31, v5 ; GFX10-NEXT: v_cmp_lt_i64_e32 vcc_lo, v[4:5], v[0:1] -; GFX10-NEXT: v_add_co_u32 v1, s5, 0x80000000, v6 +; GFX10-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v6 ; GFX10-NEXT: s_xor_b32 vcc_lo, s4, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v0, v4, v6, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v1, v5, v1, vcc_lo @@ -4560,7 +4560,7 @@ define i64 @v_saddsat_i64(i64 %lhs, i64 %rhs) { ; GFX11-NEXT: v_cmp_gt_i64_e64 s0, 0, v[2:3] ; GFX11-NEXT: v_ashrrev_i32_e32 v6, 31, v5 ; GFX11-NEXT: v_cmp_lt_i64_e32 vcc_lo, v[4:5], v[0:1] -; GFX11-NEXT: v_add_co_u32 v1, null, 0x80000000, v6 +; GFX11-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v6 ; GFX11-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX11-NEXT: v_dual_cndmask_b32 v0, v4, v6 :: v_dual_cndmask_b32 v1, v5, v1 ; GFX11-NEXT: s_setpc_b64 s[30:31] @@ -4578,7 +4578,7 @@ define amdgpu_ps i64 @s_saddsat_i64(i64 inreg %lhs, i64 inreg %rhs) { ; GFX6-NEXT: v_cmp_lt_i64_e32 vcc, s[4:5], v[0:1] ; GFX6-NEXT: v_cmp_lt_i64_e64 s[0:1], s[2:3], 0 ; GFX6-NEXT: s_ashr_i32 s2, s5, 31 -; GFX6-NEXT: s_add_u32 s3, s2, 0x80000000 +; GFX6-NEXT: s_add_i32 s3, s2, 0x80000000 ; GFX6-NEXT: v_mov_b32_e32 v0, s2 ; GFX6-NEXT: v_mov_b32_e32 v1, s3 ; GFX6-NEXT: v_mov_b32_e32 v2, s4 @@ -4599,7 +4599,7 @@ define amdgpu_ps i64 @s_saddsat_i64(i64 inreg %lhs, i64 inreg %rhs) { ; GFX8-NEXT: v_cmp_lt_i64_e32 vcc, s[4:5], v[0:1] ; GFX8-NEXT: v_cmp_lt_i64_e64 s[0:1], s[2:3], 0 ; GFX8-NEXT: s_ashr_i32 s2, s5, 31 -; GFX8-NEXT: s_add_u32 s3, s2, 0x80000000 +; GFX8-NEXT: s_add_i32 s3, s2, 0x80000000 ; GFX8-NEXT: v_mov_b32_e32 v0, s2 ; GFX8-NEXT: v_mov_b32_e32 v1, s3 ; GFX8-NEXT: v_mov_b32_e32 v2, s4 @@ -4620,7 +4620,7 @@ define amdgpu_ps i64 @s_saddsat_i64(i64 inreg %lhs, i64 inreg %rhs) { ; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, s[4:5], v[0:1] ; GFX9-NEXT: v_cmp_lt_i64_e64 s[0:1], s[2:3], 0 ; GFX9-NEXT: s_ashr_i32 s2, s5, 31 -; GFX9-NEXT: s_add_u32 s3, s2, 0x80000000 +; GFX9-NEXT: s_add_i32 s3, s2, 0x80000000 ; GFX9-NEXT: v_mov_b32_e32 v0, s2 ; GFX9-NEXT: v_mov_b32_e32 v1, s3 ; GFX9-NEXT: v_mov_b32_e32 v2, s4 @@ -4641,7 +4641,7 @@ define amdgpu_ps i64 @s_saddsat_i64(i64 inreg %lhs, i64 inreg %rhs) { ; GFX10-NEXT: v_cmp_lt_i64_e64 s1, s[2:3], 0 ; GFX10-NEXT: v_mov_b32_e32 v1, s5 ; GFX10-NEXT: s_ashr_i32 s2, s5, 31 -; GFX10-NEXT: s_add_u32 s3, s2, 0x80000000 +; GFX10-NEXT: s_add_i32 s3, s2, 0x80000000 ; GFX10-NEXT: s_xor_b32 s0, s1, s0 ; GFX10-NEXT: v_cndmask_b32_e64 v0, v0, s2, s0 ; GFX10-NEXT: v_cndmask_b32_e64 v1, v1, s3, s0 @@ -4657,7 +4657,7 @@ define amdgpu_ps i64 @s_saddsat_i64(i64 inreg %lhs, i64 inreg %rhs) { ; GFX11-NEXT: v_cmp_lt_i64_e64 s0, s[4:5], s[0:1] ; GFX11-NEXT: v_cmp_lt_i64_e64 s1, s[2:3], 0 ; GFX11-NEXT: s_ashr_i32 s2, s5, 31 -; GFX11-NEXT: s_add_u32 s3, s2, 0x80000000 +; GFX11-NEXT: s_add_i32 s3, s2, 0x80000000 ; GFX11-NEXT: s_xor_b32 s0, s1, s0 ; GFX11-NEXT: v_cndmask_b32_e64 v0, v0, s2, s0 ; GFX11-NEXT: v_cndmask_b32_e64 v1, v1, s3, s0 @@ -4702,11 +4702,11 @@ define amdgpu_ps <2 x float> @saddsat_i64_sv(i64 inreg %lhs, i64 %rhs) { ; GFX9-NEXT: v_mov_b32_e32 v3, s1 ; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, s0, v0 ; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, v3, v1, vcc -; GFX9-NEXT: v_cmp_gt_i64_e64 s[0:1], s[0:1], v[2:3] -; GFX9-NEXT: v_cmp_gt_i64_e64 s[2:3], 0, v[0:1] +; GFX9-NEXT: v_cmp_gt_i64_e32 vcc, s[0:1], v[2:3] +; GFX9-NEXT: v_cmp_gt_i64_e64 s[0:1], 0, v[0:1] ; GFX9-NEXT: v_ashrrev_i32_e32 v0, 31, v3 -; GFX9-NEXT: v_add_co_u32_e32 v1, vcc, 0x80000000, v0 -; GFX9-NEXT: s_xor_b64 vcc, s[2:3], s[0:1] +; GFX9-NEXT: v_add_u32_e32 v1, 0x80000000, v0 +; GFX9-NEXT: s_xor_b64 vcc, s[0:1], vcc ; GFX9-NEXT: v_cndmask_b32_e32 v0, v2, v0, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc ; GFX9-NEXT: ; return to shader part epilog @@ -4718,7 +4718,7 @@ define amdgpu_ps <2 x float> @saddsat_i64_sv(i64 inreg %lhs, i64 %rhs) { ; GFX10-NEXT: v_ashrrev_i32_e32 v4, 31, v3 ; GFX10-NEXT: v_cmp_gt_i64_e32 vcc_lo, s[0:1], v[2:3] ; GFX10-NEXT: v_cmp_gt_i64_e64 s0, 0, v[0:1] -; GFX10-NEXT: v_add_co_u32 v1, s1, 0x80000000, v4 +; GFX10-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v4 ; GFX10-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v0, v2, v4, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc_lo @@ -4731,7 +4731,7 @@ define amdgpu_ps <2 x float> @saddsat_i64_sv(i64 inreg %lhs, i64 %rhs) { ; GFX11-NEXT: v_ashrrev_i32_e32 v4, 31, v3 ; GFX11-NEXT: v_cmp_gt_i64_e32 vcc_lo, s[0:1], v[2:3] ; GFX11-NEXT: v_cmp_gt_i64_e64 s0, 0, v[0:1] -; GFX11-NEXT: v_add_co_u32 v1, null, 0x80000000, v4 +; GFX11-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v4 ; GFX11-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX11-NEXT: v_dual_cndmask_b32 v0, v2, v4 :: v_dual_cndmask_b32 v1, v3, v1 ; GFX11-NEXT: ; return to shader part epilog @@ -4774,11 +4774,11 @@ define amdgpu_ps <2 x float> @saddsat_i64_vs(i64 %lhs, i64 inreg %rhs) { ; GFX9-NEXT: v_mov_b32_e32 v3, s1 ; GFX9-NEXT: v_add_co_u32_e32 v2, vcc, s0, v0 ; GFX9-NEXT: v_addc_co_u32_e32 v3, vcc, v1, v3, vcc -; GFX9-NEXT: v_cmp_lt_i64_e64 s[2:3], v[2:3], v[0:1] +; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, v[2:3], v[0:1] ; GFX9-NEXT: v_cmp_lt_i64_e64 s[0:1], s[0:1], 0 ; GFX9-NEXT: v_ashrrev_i32_e32 v0, 31, v3 -; GFX9-NEXT: v_add_co_u32_e32 v1, vcc, 0x80000000, v0 -; GFX9-NEXT: s_xor_b64 vcc, s[0:1], s[2:3] +; GFX9-NEXT: v_add_u32_e32 v1, 0x80000000, v0 +; GFX9-NEXT: s_xor_b64 vcc, s[0:1], vcc ; GFX9-NEXT: v_cndmask_b32_e32 v0, v2, v0, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc ; GFX9-NEXT: ; return to shader part epilog @@ -4790,7 +4790,7 @@ define amdgpu_ps <2 x float> @saddsat_i64_vs(i64 %lhs, i64 inreg %rhs) { ; GFX10-NEXT: v_cmp_lt_i64_e64 s0, s[0:1], 0 ; GFX10-NEXT: v_ashrrev_i32_e32 v4, 31, v3 ; GFX10-NEXT: v_cmp_lt_i64_e32 vcc_lo, v[2:3], v[0:1] -; GFX10-NEXT: v_add_co_u32 v1, s1, 0x80000000, v4 +; GFX10-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v4 ; GFX10-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v0, v2, v4, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc_lo @@ -4803,7 +4803,7 @@ define amdgpu_ps <2 x float> @saddsat_i64_vs(i64 %lhs, i64 inreg %rhs) { ; GFX11-NEXT: v_cmp_lt_i64_e64 s0, s[0:1], 0 ; GFX11-NEXT: v_ashrrev_i32_e32 v4, 31, v3 ; GFX11-NEXT: v_cmp_lt_i64_e32 vcc_lo, v[2:3], v[0:1] -; GFX11-NEXT: v_add_co_u32 v1, null, 0x80000000, v4 +; GFX11-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v4 ; GFX11-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX11-NEXT: v_dual_cndmask_b32 v0, v2, v4 :: v_dual_cndmask_b32 v1, v3, v1 ; GFX11-NEXT: ; return to shader part epilog @@ -4866,21 +4866,20 @@ define <2 x i64> @v_saddsat_v2i64(<2 x i64> %lhs, <2 x i64> %rhs) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: v_add_co_u32_e32 v8, vcc, v0, v4 ; GFX9-NEXT: v_addc_co_u32_e32 v9, vcc, v1, v5, vcc -; GFX9-NEXT: v_cmp_lt_i64_e64 s[4:5], v[8:9], v[0:1] -; GFX9-NEXT: v_cmp_gt_i64_e64 s[6:7], 0, v[4:5] +; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, v[8:9], v[0:1] +; GFX9-NEXT: v_cmp_gt_i64_e64 s[4:5], 0, v[4:5] ; GFX9-NEXT: v_ashrrev_i32_e32 v0, 31, v9 -; GFX9-NEXT: v_bfrev_b32_e32 v1, 1 -; GFX9-NEXT: v_add_co_u32_e32 v1, vcc, v0, v1 -; GFX9-NEXT: s_xor_b64 vcc, s[6:7], s[4:5] +; GFX9-NEXT: v_add_u32_e32 v1, 0x80000000, v0 +; GFX9-NEXT: s_xor_b64 vcc, s[4:5], vcc ; GFX9-NEXT: v_cndmask_b32_e32 v0, v8, v0, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v9, v1, vcc ; GFX9-NEXT: v_add_co_u32_e32 v4, vcc, v2, v6 ; GFX9-NEXT: v_addc_co_u32_e32 v5, vcc, v3, v7, vcc -; GFX9-NEXT: v_cmp_lt_i64_e64 s[4:5], v[4:5], v[2:3] -; GFX9-NEXT: v_cmp_gt_i64_e64 s[6:7], 0, v[6:7] +; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, v[4:5], v[2:3] +; GFX9-NEXT: v_cmp_gt_i64_e64 s[4:5], 0, v[6:7] ; GFX9-NEXT: v_ashrrev_i32_e32 v2, 31, v5 -; GFX9-NEXT: v_add_co_u32_e32 v3, vcc, 0x80000000, v2 -; GFX9-NEXT: s_xor_b64 vcc, s[6:7], s[4:5] +; GFX9-NEXT: v_add_u32_e32 v3, 0x80000000, v2 +; GFX9-NEXT: s_xor_b64 vcc, s[4:5], vcc ; GFX9-NEXT: v_cndmask_b32_e32 v2, v4, v2, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v3, v5, v3, vcc ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -4896,10 +4895,10 @@ define <2 x i64> @v_saddsat_v2i64(<2 x i64> %lhs, <2 x i64> %rhs) { ; GFX10-NEXT: v_cmp_lt_i64_e32 vcc_lo, v[8:9], v[0:1] ; GFX10-NEXT: v_cmp_gt_i64_e64 s4, 0, v[4:5] ; GFX10-NEXT: v_ashrrev_i32_e32 v4, 31, v11 -; GFX10-NEXT: v_cmp_gt_i64_e64 s6, 0, v[6:7] -; GFX10-NEXT: v_add_co_u32 v1, s5, 0x80000000, v12 ; GFX10-NEXT: v_cmp_lt_i64_e64 s5, v[10:11], v[2:3] -; GFX10-NEXT: v_add_co_u32 v3, s7, 0x80000000, v4 +; GFX10-NEXT: v_cmp_gt_i64_e64 s6, 0, v[6:7] +; GFX10-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v12 +; GFX10-NEXT: v_add_nc_u32_e32 v3, 0x80000000, v4 ; GFX10-NEXT: s_xor_b32 vcc_lo, s4, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v0, v8, v12, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v1, v9, v1, vcc_lo @@ -4921,8 +4920,8 @@ define <2 x i64> @v_saddsat_v2i64(<2 x i64> %lhs, <2 x i64> %rhs) { ; GFX11-NEXT: v_ashrrev_i32_e32 v4, 31, v11 ; GFX11-NEXT: v_cmp_lt_i64_e64 s1, v[10:11], v[2:3] ; GFX11-NEXT: v_cmp_gt_i64_e64 s2, 0, v[6:7] -; GFX11-NEXT: v_add_co_u32 v1, null, 0x80000000, v12 -; GFX11-NEXT: v_add_co_u32 v3, null, 0x80000000, v4 +; GFX11-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v12 +; GFX11-NEXT: v_add_nc_u32_e32 v3, 0x80000000, v4 ; GFX11-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX11-NEXT: v_dual_cndmask_b32 v0, v8, v12 :: v_dual_cndmask_b32 v1, v9, v1 ; GFX11-NEXT: s_xor_b32 vcc_lo, s2, s1 @@ -4942,7 +4941,7 @@ define amdgpu_ps <2 x i64> @s_saddsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX6-NEXT: v_cmp_lt_i64_e32 vcc, s[8:9], v[0:1] ; GFX6-NEXT: v_cmp_lt_i64_e64 s[0:1], s[4:5], 0 ; GFX6-NEXT: s_ashr_i32 s4, s9, 31 -; GFX6-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX6-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX6-NEXT: v_mov_b32_e32 v0, s4 ; GFX6-NEXT: v_mov_b32_e32 v1, s5 ; GFX6-NEXT: v_mov_b32_e32 v2, s8 @@ -4957,7 +4956,7 @@ define amdgpu_ps <2 x i64> @s_saddsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX6-NEXT: v_cmp_lt_i64_e32 vcc, s[0:1], v[0:1] ; GFX6-NEXT: v_cmp_lt_i64_e64 s[2:3], s[6:7], 0 ; GFX6-NEXT: s_ashr_i32 s4, s1, 31 -; GFX6-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX6-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX6-NEXT: v_mov_b32_e32 v0, s4 ; GFX6-NEXT: v_mov_b32_e32 v1, s5 ; GFX6-NEXT: v_mov_b32_e32 v4, s0 @@ -4980,7 +4979,7 @@ define amdgpu_ps <2 x i64> @s_saddsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX8-NEXT: v_cmp_lt_i64_e32 vcc, s[8:9], v[0:1] ; GFX8-NEXT: v_cmp_lt_i64_e64 s[0:1], s[4:5], 0 ; GFX8-NEXT: s_ashr_i32 s4, s9, 31 -; GFX8-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX8-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX8-NEXT: v_mov_b32_e32 v0, s4 ; GFX8-NEXT: v_mov_b32_e32 v1, s5 ; GFX8-NEXT: v_mov_b32_e32 v2, s8 @@ -4995,7 +4994,7 @@ define amdgpu_ps <2 x i64> @s_saddsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX8-NEXT: v_cmp_lt_i64_e32 vcc, s[0:1], v[0:1] ; GFX8-NEXT: v_cmp_lt_i64_e64 s[2:3], s[6:7], 0 ; GFX8-NEXT: s_ashr_i32 s4, s1, 31 -; GFX8-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX8-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX8-NEXT: v_mov_b32_e32 v0, s4 ; GFX8-NEXT: v_mov_b32_e32 v1, s5 ; GFX8-NEXT: v_mov_b32_e32 v4, s0 @@ -5018,7 +5017,7 @@ define amdgpu_ps <2 x i64> @s_saddsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, s[8:9], v[0:1] ; GFX9-NEXT: v_cmp_lt_i64_e64 s[0:1], s[4:5], 0 ; GFX9-NEXT: s_ashr_i32 s4, s9, 31 -; GFX9-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX9-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX9-NEXT: v_mov_b32_e32 v0, s4 ; GFX9-NEXT: v_mov_b32_e32 v1, s5 ; GFX9-NEXT: v_mov_b32_e32 v2, s8 @@ -5033,7 +5032,7 @@ define amdgpu_ps <2 x i64> @s_saddsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, s[0:1], v[0:1] ; GFX9-NEXT: v_cmp_lt_i64_e64 s[2:3], s[6:7], 0 ; GFX9-NEXT: s_ashr_i32 s4, s1, 31 -; GFX9-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX9-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX9-NEXT: v_mov_b32_e32 v0, s4 ; GFX9-NEXT: v_mov_b32_e32 v1, s5 ; GFX9-NEXT: v_mov_b32_e32 v4, s0 @@ -5056,7 +5055,7 @@ define amdgpu_ps <2 x i64> @s_saddsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX10-NEXT: v_cmp_lt_i64_e64 s1, s[4:5], 0 ; GFX10-NEXT: s_ashr_i32 s4, s9, 31 ; GFX10-NEXT: v_mov_b32_e32 v1, s9 -; GFX10-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX10-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX10-NEXT: s_xor_b32 s8, s1, s0 ; GFX10-NEXT: s_add_u32 s0, s2, s6 ; GFX10-NEXT: s_addc_u32 s1, s3, s7 @@ -5067,7 +5066,7 @@ define amdgpu_ps <2 x i64> @s_saddsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX10-NEXT: v_cndmask_b32_e64 v0, v0, s4, s8 ; GFX10-NEXT: s_ashr_i32 s4, s1, 31 ; GFX10-NEXT: v_cndmask_b32_e64 v1, v1, s5, s8 -; GFX10-NEXT: s_add_u32 s0, s4, 0x80000000 +; GFX10-NEXT: s_add_i32 s0, s4, 0x80000000 ; GFX10-NEXT: s_xor_b32 s1, s3, s2 ; GFX10-NEXT: v_cndmask_b32_e64 v2, v2, s4, s1 ; GFX10-NEXT: v_cndmask_b32_e64 v3, v3, s0, s1 @@ -5085,7 +5084,7 @@ define amdgpu_ps <2 x i64> @s_saddsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX11-NEXT: v_cmp_lt_i64_e64 s0, s[8:9], s[0:1] ; GFX11-NEXT: v_cmp_lt_i64_e64 s1, s[4:5], 0 ; GFX11-NEXT: s_ashr_i32 s4, s9, 31 -; GFX11-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX11-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX11-NEXT: s_xor_b32 s8, s1, s0 ; GFX11-NEXT: s_add_u32 s0, s2, s6 ; GFX11-NEXT: s_addc_u32 s1, s3, s7 @@ -5095,7 +5094,7 @@ define amdgpu_ps <2 x i64> @s_saddsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX11-NEXT: v_cndmask_b32_e64 v0, v0, s4, s8 ; GFX11-NEXT: s_ashr_i32 s4, s1, 31 ; GFX11-NEXT: v_cndmask_b32_e64 v1, v1, s5, s8 -; GFX11-NEXT: s_add_u32 s0, s4, 0x80000000 +; GFX11-NEXT: s_add_i32 s0, s4, 0x80000000 ; GFX11-NEXT: s_xor_b32 s1, s3, s2 ; GFX11-NEXT: v_cndmask_b32_e64 v2, v2, s4, s1 ; GFX11-NEXT: v_cndmask_b32_e64 v3, v3, s0, s1 @@ -5132,7 +5131,7 @@ define amdgpu_ps i128 @s_saddsat_i128(i128 inreg %lhs, i128 inreg %rhs) { ; GFX6-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX6-NEXT: s_ashr_i32 s0, s9, 31 ; GFX6-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX6-NEXT: s_add_u32 s1, s0, 0x80000000 +; GFX6-NEXT: s_add_i32 s1, s0, 0x80000000 ; GFX6-NEXT: v_mov_b32_e32 v1, s0 ; GFX6-NEXT: v_mov_b32_e32 v2, s4 ; GFX6-NEXT: v_mov_b32_e32 v3, s5 @@ -5179,7 +5178,7 @@ define amdgpu_ps i128 @s_saddsat_i128(i128 inreg %lhs, i128 inreg %rhs) { ; GFX8-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX8-NEXT: s_ashr_i32 s0, s9, 31 ; GFX8-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX8-NEXT: s_add_u32 s1, s0, 0x80000000 +; GFX8-NEXT: s_add_i32 s1, s0, 0x80000000 ; GFX8-NEXT: v_mov_b32_e32 v1, s0 ; GFX8-NEXT: v_mov_b32_e32 v2, s4 ; GFX8-NEXT: v_mov_b32_e32 v3, s5 @@ -5226,7 +5225,7 @@ define amdgpu_ps i128 @s_saddsat_i128(i128 inreg %lhs, i128 inreg %rhs) { ; GFX9-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX9-NEXT: s_ashr_i32 s0, s9, 31 ; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX9-NEXT: s_add_u32 s1, s0, 0x80000000 +; GFX9-NEXT: s_add_i32 s1, s0, 0x80000000 ; GFX9-NEXT: v_mov_b32_e32 v1, s0 ; GFX9-NEXT: v_mov_b32_e32 v2, s4 ; GFX9-NEXT: v_mov_b32_e32 v3, s5 @@ -5269,7 +5268,7 @@ define amdgpu_ps i128 @s_saddsat_i128(i128 inreg %lhs, i128 inreg %rhs) { ; GFX10-NEXT: v_cndmask_b32_e64 v1, v2, 0, s0 ; GFX10-NEXT: v_mov_b32_e32 v2, s5 ; GFX10-NEXT: s_ashr_i32 s0, s9, 31 -; GFX10-NEXT: s_add_u32 s1, s0, 0x80000000 +; GFX10-NEXT: s_add_i32 s1, s0, 0x80000000 ; GFX10-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX10-NEXT: v_mov_b32_e32 v1, s4 ; GFX10-NEXT: v_and_b32_e32 v0, 1, v0 @@ -5310,7 +5309,7 @@ define amdgpu_ps i128 @s_saddsat_i128(i128 inreg %lhs, i128 inreg %rhs) { ; GFX11-NEXT: v_cndmask_b32_e64 v1, v2, 0, s0 ; GFX11-NEXT: v_mov_b32_e32 v2, s5 ; GFX11-NEXT: s_ashr_i32 s0, s9, 31 -; GFX11-NEXT: s_add_u32 s1, s0, 0x80000000 +; GFX11-NEXT: s_add_i32 s1, s0, 0x80000000 ; GFX11-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX11-NEXT: v_dual_mov_b32 v1, s4 :: v_dual_and_b32 v0, 1, v0 ; GFX11-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v0 @@ -5412,9 +5411,8 @@ define amdgpu_ps <4 x float> @saddsat_i128_sv(i128 inreg %lhs, i128 %rhs) { ; GFX9-NEXT: v_ashrrev_i32_e32 v3, 31, v5 ; GFX9-NEXT: v_cndmask_b32_e64 v2, v7, 0, vcc ; GFX9-NEXT: v_xor_b32_e32 v2, v2, v6 -; GFX9-NEXT: v_bfrev_b32_e32 v6, 1 -; GFX9-NEXT: v_add_co_u32_e32 v6, vcc, v3, v6 ; GFX9-NEXT: v_and_b32_e32 v2, 1, v2 +; GFX9-NEXT: v_add_u32_e32 v6, 0x80000000, v3 ; GFX9-NEXT: v_cmp_ne_u32_e32 vcc, 0, v2 ; GFX9-NEXT: v_cndmask_b32_e32 v0, v0, v3, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v1, v3, vcc @@ -5440,7 +5438,7 @@ define amdgpu_ps <4 x float> @saddsat_i128_sv(i128 inreg %lhs, i128 %rhs) { ; GFX10-NEXT: v_ashrrev_i32_e32 v3, 31, v5 ; GFX10-NEXT: v_cndmask_b32_e64 v2, v8, 0, vcc_lo ; GFX10-NEXT: v_xor_b32_e32 v2, v2, v6 -; GFX10-NEXT: v_add_co_u32 v6, s0, 0x80000000, v3 +; GFX10-NEXT: v_add_nc_u32_e32 v6, 0x80000000, v3 ; GFX10-NEXT: v_and_b32_e32 v2, 1, v2 ; GFX10-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v2 ; GFX10-NEXT: v_cndmask_b32_e32 v0, v0, v3, vcc_lo @@ -5467,7 +5465,7 @@ define amdgpu_ps <4 x float> @saddsat_i128_sv(i128 inreg %lhs, i128 %rhs) { ; GFX11-NEXT: v_ashrrev_i32_e32 v3, 31, v5 ; GFX11-NEXT: v_cndmask_b32_e64 v2, v8, 0, vcc_lo ; GFX11-NEXT: v_xor_b32_e32 v2, v2, v6 -; GFX11-NEXT: v_add_co_u32 v6, null, 0x80000000, v3 +; GFX11-NEXT: v_add_nc_u32_e32 v6, 0x80000000, v3 ; GFX11-NEXT: v_and_b32_e32 v2, 1, v2 ; GFX11-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v2 ; GFX11-NEXT: v_cndmask_b32_e32 v1, v1, v3, vcc_lo @@ -5569,9 +5567,8 @@ define amdgpu_ps <4 x float> @saddsat_i128_vs(i128 %lhs, i128 inreg %rhs) { ; GFX9-NEXT: v_cndmask_b32_e64 v1, v1, 0, s[0:1] ; GFX9-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX9-NEXT: v_ashrrev_i32_e32 v2, 31, v7 -; GFX9-NEXT: v_bfrev_b32_e32 v1, 1 -; GFX9-NEXT: v_add_co_u32_e32 v3, vcc, v2, v1 ; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_add_u32_e32 v3, 0x80000000, v2 ; GFX9-NEXT: v_cmp_ne_u32_e32 vcc, 0, v0 ; GFX9-NEXT: v_cndmask_b32_e32 v0, v4, v2, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v5, v2, vcc @@ -5597,9 +5594,9 @@ define amdgpu_ps <4 x float> @saddsat_i128_vs(i128 %lhs, i128 inreg %rhs) { ; GFX10-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc_lo ; GFX10-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[6:7], v[2:3] ; GFX10-NEXT: v_ashrrev_i32_e32 v2, 31, v7 +; GFX10-NEXT: v_add_nc_u32_e32 v3, 0x80000000, v2 ; GFX10-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e64 v1, v8, 0, s0 -; GFX10-NEXT: v_add_co_u32 v3, s0, 0x80000000, v2 ; GFX10-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX10-NEXT: v_and_b32_e32 v0, 1, v0 ; GFX10-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v0 @@ -5627,15 +5624,14 @@ define amdgpu_ps <4 x float> @saddsat_i128_vs(i128 %lhs, i128 inreg %rhs) { ; GFX11-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc_lo ; GFX11-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[6:7], v[2:3] ; GFX11-NEXT: v_ashrrev_i32_e32 v2, 31, v7 -; GFX11-NEXT: v_add_co_u32 v3, null, 0x80000000, v2 -; GFX11-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc_lo +; GFX11-NEXT: v_dual_cndmask_b32 v0, v1, v0 :: v_dual_add_nc_u32 v3, 0x80000000, v2 ; GFX11-NEXT: v_cndmask_b32_e64 v1, v8, 0, s0 ; GFX11-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX11-NEXT: v_and_b32_e32 v0, 1, v0 ; GFX11-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v0 ; GFX11-NEXT: v_cndmask_b32_e32 v1, v5, v2, vcc_lo -; GFX11-NEXT: v_cndmask_b32_e32 v0, v4, v2, vcc_lo -; GFX11-NEXT: v_dual_cndmask_b32 v2, v6, v2 :: v_dual_cndmask_b32 v3, v7, v3 +; GFX11-NEXT: v_dual_cndmask_b32 v0, v4, v2 :: v_dual_cndmask_b32 v3, v7, v3 +; GFX11-NEXT: v_cndmask_b32_e32 v2, v6, v2, vcc_lo ; GFX11-NEXT: ; return to shader part epilog %result = call i128 @llvm.sadd.sat.i128(i128 %lhs, i128 %rhs) %cast = bitcast i128 %result to <4 x float> @@ -5762,12 +5758,11 @@ define <2 x i128> @v_saddsat_v2i128(<2 x i128> %lhs, <2 x i128> %rhs) { ; GFX9-NEXT: v_ashrrev_i32_e32 v2, 31, v17 ; GFX9-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc ; GFX9-NEXT: v_cmp_gt_i64_e32 vcc, 0, v[10:11] +; GFX9-NEXT: v_add_u32_e32 v3, 0x80000000, v2 ; GFX9-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[10:11] ; GFX9-NEXT: v_cndmask_b32_e64 v1, v1, 0, vcc ; GFX9-NEXT: v_xor_b32_e32 v0, v1, v0 -; GFX9-NEXT: v_bfrev_b32_e32 v1, 1 -; GFX9-NEXT: v_add_co_u32_e32 v3, vcc, v2, v1 ; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 ; GFX9-NEXT: v_cmp_ne_u32_e32 vcc, 0, v0 ; GFX9-NEXT: v_cndmask_b32_e32 v0, v8, v2, vcc @@ -5786,11 +5781,11 @@ define <2 x i128> @v_saddsat_v2i128(<2 x i128> %lhs, <2 x i128> %rhs) { ; GFX9-NEXT: v_ashrrev_i32_e32 v6, 31, v11 ; GFX9-NEXT: v_cndmask_b32_e32 v4, v5, v4, vcc ; GFX9-NEXT: v_cmp_gt_i64_e32 vcc, 0, v[14:15] +; GFX9-NEXT: v_add_u32_e32 v7, 0x80000000, v6 ; GFX9-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc ; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[14:15] ; GFX9-NEXT: v_cndmask_b32_e64 v5, v5, 0, vcc ; GFX9-NEXT: v_xor_b32_e32 v4, v5, v4 -; GFX9-NEXT: v_add_co_u32_e32 v7, vcc, 0x80000000, v6 ; GFX9-NEXT: v_and_b32_e32 v4, 1, v4 ; GFX9-NEXT: v_cmp_ne_u32_e32 vcc, 0, v4 ; GFX9-NEXT: v_cndmask_b32_e32 v4, v8, v6, vcc @@ -5832,18 +5827,18 @@ define <2 x i128> @v_saddsat_v2i128(<2 x i128> %lhs, <2 x i128> %rhs) { ; GFX10-NEXT: v_ashrrev_i32_e32 v6, 31, v19 ; GFX10-NEXT: v_cndmask_b32_e32 v1, v3, v2, vcc_lo ; GFX10-NEXT: v_cmp_eq_u64_e32 vcc_lo, 0, v[14:15] -; GFX10-NEXT: v_ashrrev_i32_e32 v3, 31, v17 -; GFX10-NEXT: v_add_co_u32 v7, s5, 0x80000000, v6 +; GFX10-NEXT: v_add_nc_u32_e32 v7, 0x80000000, v6 ; GFX10-NEXT: v_cndmask_b32_e64 v2, v4, 0, vcc_lo -; GFX10-NEXT: v_add_co_u32 v4, s4, 0x80000000, v3 ; GFX10-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v0 ; GFX10-NEXT: v_xor_b32_e32 v1, v2, v1 -; GFX10-NEXT: v_cndmask_b32_e32 v0, v8, v3, vcc_lo -; GFX10-NEXT: v_cndmask_b32_e32 v2, v16, v3, vcc_lo -; GFX10-NEXT: v_and_b32_e32 v5, 1, v1 -; GFX10-NEXT: v_cndmask_b32_e32 v1, v9, v3, vcc_lo +; GFX10-NEXT: v_ashrrev_i32_e32 v2, 31, v17 +; GFX10-NEXT: v_and_b32_e32 v3, 1, v1 +; GFX10-NEXT: v_add_nc_u32_e32 v4, 0x80000000, v2 +; GFX10-NEXT: v_cndmask_b32_e32 v0, v8, v2, vcc_lo +; GFX10-NEXT: v_cndmask_b32_e32 v1, v9, v2, vcc_lo +; GFX10-NEXT: v_cndmask_b32_e32 v2, v16, v2, vcc_lo +; GFX10-NEXT: v_cmp_ne_u32_e64 s4, 0, v3 ; GFX10-NEXT: v_cndmask_b32_e32 v3, v17, v4, vcc_lo -; GFX10-NEXT: v_cmp_ne_u32_e64 s4, 0, v5 ; GFX10-NEXT: v_cndmask_b32_e64 v4, v12, v6, s4 ; GFX10-NEXT: v_cndmask_b32_e64 v5, v13, v6, s4 ; GFX10-NEXT: v_cndmask_b32_e64 v6, v18, v6, s4 @@ -5882,18 +5877,17 @@ define <2 x i128> @v_saddsat_v2i128(<2 x i128> %lhs, <2 x i128> %rhs) { ; GFX11-NEXT: v_ashrrev_i32_e32 v6, 31, v19 ; GFX11-NEXT: v_cndmask_b32_e32 v1, v3, v2, vcc_lo ; GFX11-NEXT: v_cmp_eq_u64_e32 vcc_lo, 0, v[14:15] -; GFX11-NEXT: v_ashrrev_i32_e32 v3, 31, v17 -; GFX11-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX11-NEXT: v_add_co_u32 v7, null, 0x80000000, v6 +; GFX11-NEXT: v_add_nc_u32_e32 v7, 0x80000000, v6 ; GFX11-NEXT: v_cndmask_b32_e64 v2, v4, 0, vcc_lo -; GFX11-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v0 -; GFX11-NEXT: v_add_co_u32 v4, null, 0x80000000, v3 ; GFX11-NEXT: v_xor_b32_e32 v1, v2, v1 -; GFX11-NEXT: v_cndmask_b32_e32 v0, v8, v3, vcc_lo -; GFX11-NEXT: v_dual_cndmask_b32 v2, v16, v3 :: v_dual_and_b32 v5, 1, v1 -; GFX11-NEXT: v_cndmask_b32_e32 v1, v9, v3, vcc_lo -; GFX11-NEXT: v_cndmask_b32_e32 v3, v17, v4, vcc_lo -; GFX11-NEXT: v_cmp_ne_u32_e64 s0, 0, v5 +; GFX11-NEXT: v_ashrrev_i32_e32 v2, 31, v17 +; GFX11-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX11-NEXT: v_add_nc_u32_e32 v4, 0x80000000, v2 +; GFX11-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v0 +; GFX11-NEXT: v_dual_cndmask_b32 v0, v8, v2 :: v_dual_and_b32 v3, 1, v1 +; GFX11-NEXT: v_cmp_ne_u32_e64 s0, 0, v3 +; GFX11-NEXT: v_cndmask_b32_e32 v1, v9, v2, vcc_lo +; GFX11-NEXT: v_dual_cndmask_b32 v2, v16, v2 :: v_dual_cndmask_b32 v3, v17, v4 ; GFX11-NEXT: v_cndmask_b32_e64 v4, v12, v6, s0 ; GFX11-NEXT: v_cndmask_b32_e64 v5, v13, v6, s0 ; GFX11-NEXT: v_cndmask_b32_e64 v6, v18, v6, s0 @@ -5927,7 +5921,7 @@ define amdgpu_ps <2 x i128> @s_saddsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX6-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX6-NEXT: s_ashr_i32 s0, s17, 31 ; GFX6-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX6-NEXT: s_add_u32 s1, s0, 0x80000000 +; GFX6-NEXT: s_add_i32 s1, s0, 0x80000000 ; GFX6-NEXT: v_mov_b32_e32 v1, s0 ; GFX6-NEXT: v_mov_b32_e32 v2, s8 ; GFX6-NEXT: v_mov_b32_e32 v3, s9 @@ -5960,7 +5954,7 @@ define amdgpu_ps <2 x i128> @s_saddsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX6-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX6-NEXT: s_ashr_i32 s4, s3, 31 ; GFX6-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX6-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX6-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX6-NEXT: v_mov_b32_e32 v1, s4 ; GFX6-NEXT: v_mov_b32_e32 v2, s0 ; GFX6-NEXT: v_mov_b32_e32 v3, s1 @@ -6011,7 +6005,7 @@ define amdgpu_ps <2 x i128> @s_saddsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX8-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX8-NEXT: s_ashr_i32 s0, s17, 31 ; GFX8-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX8-NEXT: s_add_u32 s1, s0, 0x80000000 +; GFX8-NEXT: s_add_i32 s1, s0, 0x80000000 ; GFX8-NEXT: v_mov_b32_e32 v1, s0 ; GFX8-NEXT: v_mov_b32_e32 v2, s8 ; GFX8-NEXT: v_mov_b32_e32 v3, s9 @@ -6050,7 +6044,7 @@ define amdgpu_ps <2 x i128> @s_saddsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX8-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX8-NEXT: s_ashr_i32 s4, s3, 31 ; GFX8-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX8-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX8-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX8-NEXT: v_mov_b32_e32 v1, s4 ; GFX8-NEXT: v_mov_b32_e32 v2, s0 ; GFX8-NEXT: v_mov_b32_e32 v3, s1 @@ -6101,7 +6095,7 @@ define amdgpu_ps <2 x i128> @s_saddsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX9-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX9-NEXT: s_ashr_i32 s0, s17, 31 ; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX9-NEXT: s_add_u32 s1, s0, 0x80000000 +; GFX9-NEXT: s_add_i32 s1, s0, 0x80000000 ; GFX9-NEXT: v_mov_b32_e32 v1, s0 ; GFX9-NEXT: v_mov_b32_e32 v2, s8 ; GFX9-NEXT: v_mov_b32_e32 v3, s9 @@ -6140,7 +6134,7 @@ define amdgpu_ps <2 x i128> @s_saddsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX9-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX9-NEXT: s_ashr_i32 s4, s3, 31 ; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX9-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX9-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX9-NEXT: v_mov_b32_e32 v1, s4 ; GFX9-NEXT: v_mov_b32_e32 v2, s0 ; GFX9-NEXT: v_mov_b32_e32 v3, s1 @@ -6184,7 +6178,7 @@ define amdgpu_ps <2 x i128> @s_saddsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX10-NEXT: s_and_b32 s1, 1, s1 ; GFX10-NEXT: s_ashr_i32 s10, s17, 31 ; GFX10-NEXT: v_cmp_ne_u32_e64 s0, 0, s1 -; GFX10-NEXT: s_add_u32 s11, s10, 0x80000000 +; GFX10-NEXT: s_add_i32 s11, s10, 0x80000000 ; GFX10-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e64 v1, v2, 0, s0 ; GFX10-NEXT: s_add_u32 s0, s4, s12 @@ -6221,7 +6215,7 @@ define amdgpu_ps <2 x i128> @s_saddsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX10-NEXT: v_xor_b32_e32 v1, v2, v1 ; GFX10-NEXT: v_mov_b32_e32 v2, s17 ; GFX10-NEXT: v_cndmask_b32_e64 v3, v3, s10, vcc_lo -; GFX10-NEXT: s_add_u32 s0, s4, 0x80000000 +; GFX10-NEXT: s_add_i32 s0, s4, 0x80000000 ; GFX10-NEXT: v_readfirstlane_b32 s1, v4 ; GFX10-NEXT: v_and_b32_e32 v1, 1, v1 ; GFX10-NEXT: v_cndmask_b32_e64 v2, v2, s11, vcc_lo @@ -6261,7 +6255,7 @@ define amdgpu_ps <2 x i128> @s_saddsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX11-NEXT: s_and_b32 s1, 1, s1 ; GFX11-NEXT: s_ashr_i32 s10, s17, 31 ; GFX11-NEXT: v_cmp_ne_u32_e64 s0, 0, s1 -; GFX11-NEXT: s_add_u32 s11, s10, 0x80000000 +; GFX11-NEXT: s_add_i32 s11, s10, 0x80000000 ; GFX11-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc_lo ; GFX11-NEXT: v_cndmask_b32_e64 v1, v2, 0, s0 ; GFX11-NEXT: s_add_u32 s0, s4, s12 @@ -6299,7 +6293,7 @@ define amdgpu_ps <2 x i128> @s_saddsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX11-NEXT: v_and_b32_e32 v1, 1, v1 ; GFX11-NEXT: v_cndmask_b32_e64 v4, v4, s10, vcc_lo ; GFX11-NEXT: v_cndmask_b32_e64 v2, v2, s11, vcc_lo -; GFX11-NEXT: s_add_u32 s0, s4, 0x80000000 +; GFX11-NEXT: s_add_i32 s0, s4, 0x80000000 ; GFX11-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v1 ; GFX11-NEXT: v_mov_b32_e32 v1, s2 ; GFX11-NEXT: v_readfirstlane_b32 s1, v4 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/sdiv.i32.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/sdiv.i32.ll index 1061f0003bd48961b56e528f99301689f1a852b7..2c2f8e914447d1d000f40bfd9c2a875d6d0772fb 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/sdiv.i32.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/sdiv.i32.ll @@ -279,125 +279,27 @@ define i32 @v_sdiv_i32_pow2k_denom(i32 %num) { ; CHECK: ; %bb.0: ; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; CHECK-NEXT: v_ashrrev_i32_e32 v1, 31, v0 -; CHECK-NEXT: v_rcp_iflag_f32_e32 v2, 0x45800000 -; CHECK-NEXT: v_mov_b32_e32 v3, 0xfffff000 -; CHECK-NEXT: v_mov_b32_e32 v4, 0x1000 +; CHECK-NEXT: v_lshrrev_b32_e32 v1, 20, v1 ; CHECK-NEXT: v_add_i32_e32 v0, vcc, v0, v1 -; CHECK-NEXT: v_mul_f32_e32 v2, 0x4f7ffffe, v2 -; CHECK-NEXT: v_xor_b32_e32 v0, v0, v1 -; CHECK-NEXT: v_cvt_u32_f32_e32 v2, v2 -; CHECK-NEXT: v_mul_lo_u32 v3, v2, v3 -; CHECK-NEXT: v_mul_hi_u32 v3, v2, v3 -; CHECK-NEXT: v_add_i32_e32 v2, vcc, v2, v3 -; CHECK-NEXT: v_mul_hi_u32 v2, v0, v2 -; CHECK-NEXT: v_lshlrev_b32_e32 v3, 12, v2 -; CHECK-NEXT: v_add_i32_e32 v5, vcc, 1, v2 -; CHECK-NEXT: v_sub_i32_e32 v0, vcc, v0, v3 -; CHECK-NEXT: v_cmp_ge_u32_e64 s[4:5], v0, v4 -; CHECK-NEXT: v_cndmask_b32_e64 v2, v2, v5, s[4:5] -; CHECK-NEXT: v_subrev_i32_e32 v3, vcc, 0x1000, v0 -; CHECK-NEXT: v_cndmask_b32_e64 v0, v0, v3, s[4:5] -; CHECK-NEXT: v_add_i32_e32 v3, vcc, 1, v2 -; CHECK-NEXT: v_cmp_ge_u32_e32 vcc, v0, v4 -; CHECK-NEXT: v_cndmask_b32_e32 v0, v2, v3, vcc -; CHECK-NEXT: v_xor_b32_e32 v0, v0, v1 -; CHECK-NEXT: v_sub_i32_e32 v0, vcc, v0, v1 +; CHECK-NEXT: v_ashrrev_i32_e32 v0, 12, v0 ; CHECK-NEXT: s_setpc_b64 s[30:31] %result = sdiv i32 %num, 4096 ret i32 %result } define <2 x i32> @v_sdiv_v2i32_pow2k_denom(<2 x i32> %num) { -; GISEL-LABEL: v_sdiv_v2i32_pow2k_denom: -; GISEL: ; %bb.0: -; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GISEL-NEXT: v_ashrrev_i32_e32 v2, 31, v0 -; GISEL-NEXT: v_mov_b32_e32 v3, 0x1000 -; GISEL-NEXT: v_cvt_f32_u32_e32 v4, 0x1000 -; GISEL-NEXT: v_mov_b32_e32 v5, 0xfffff000 -; GISEL-NEXT: v_ashrrev_i32_e32 v6, 31, v1 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v2 -; GISEL-NEXT: v_rcp_iflag_f32_e32 v4, v4 -; GISEL-NEXT: v_add_i32_e32 v1, vcc, v1, v6 -; GISEL-NEXT: v_xor_b32_e32 v0, v0, v2 -; GISEL-NEXT: v_mul_f32_e32 v4, 0x4f7ffffe, v4 -; GISEL-NEXT: v_xor_b32_e32 v1, v1, v6 -; GISEL-NEXT: v_cvt_u32_f32_e32 v4, v4 -; GISEL-NEXT: v_mul_lo_u32 v5, v4, v5 -; GISEL-NEXT: v_mul_hi_u32 v5, v4, v5 -; GISEL-NEXT: v_add_i32_e32 v4, vcc, v4, v5 -; GISEL-NEXT: v_mul_hi_u32 v5, v0, v4 -; GISEL-NEXT: v_mul_hi_u32 v4, v1, v4 -; GISEL-NEXT: v_lshlrev_b32_e32 v7, 12, v5 -; GISEL-NEXT: v_add_i32_e32 v8, vcc, 1, v5 -; GISEL-NEXT: v_lshlrev_b32_e32 v9, 12, v4 -; GISEL-NEXT: v_add_i32_e32 v10, vcc, 1, v4 -; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v0, v7 -; GISEL-NEXT: v_sub_i32_e32 v1, vcc, v1, v9 -; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v0, v3 -; GISEL-NEXT: v_cndmask_b32_e64 v5, v5, v8, s[4:5] -; GISEL-NEXT: v_sub_i32_e32 v7, vcc, v0, v3 -; GISEL-NEXT: v_cmp_ge_u32_e64 s[6:7], v1, v3 -; GISEL-NEXT: v_cndmask_b32_e64 v4, v4, v10, s[6:7] -; GISEL-NEXT: v_subrev_i32_e32 v8, vcc, 0x1000, v1 -; GISEL-NEXT: v_cndmask_b32_e64 v0, v0, v7, s[4:5] -; GISEL-NEXT: v_add_i32_e32 v7, vcc, 1, v5 -; GISEL-NEXT: v_cndmask_b32_e64 v1, v1, v8, s[6:7] -; GISEL-NEXT: v_add_i32_e32 v8, vcc, 1, v4 -; GISEL-NEXT: v_cmp_ge_u32_e32 vcc, v0, v3 -; GISEL-NEXT: v_cndmask_b32_e32 v0, v5, v7, vcc -; GISEL-NEXT: v_cmp_ge_u32_e32 vcc, v1, v3 -; GISEL-NEXT: v_cndmask_b32_e32 v1, v4, v8, vcc -; GISEL-NEXT: v_xor_b32_e32 v0, v0, v2 -; GISEL-NEXT: v_xor_b32_e32 v1, v1, v6 -; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v0, v2 -; GISEL-NEXT: v_sub_i32_e32 v1, vcc, v1, v6 -; GISEL-NEXT: s_setpc_b64 s[30:31] -; -; CGP-LABEL: v_sdiv_v2i32_pow2k_denom: -; CGP: ; %bb.0: -; CGP-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; CGP-NEXT: v_ashrrev_i32_e32 v2, 31, v0 -; CGP-NEXT: v_rcp_iflag_f32_e32 v3, 0x45800000 -; CGP-NEXT: v_mov_b32_e32 v4, 0xfffff000 -; CGP-NEXT: v_mov_b32_e32 v5, 0x1000 -; CGP-NEXT: v_ashrrev_i32_e32 v6, 31, v1 -; CGP-NEXT: v_add_i32_e32 v0, vcc, v0, v2 -; CGP-NEXT: v_mul_f32_e32 v3, 0x4f7ffffe, v3 -; CGP-NEXT: v_add_i32_e32 v1, vcc, v1, v6 -; CGP-NEXT: v_xor_b32_e32 v0, v0, v2 -; CGP-NEXT: v_cvt_u32_f32_e32 v3, v3 -; CGP-NEXT: v_xor_b32_e32 v1, v1, v6 -; CGP-NEXT: v_mul_lo_u32 v4, v3, v4 -; CGP-NEXT: v_mul_hi_u32 v4, v3, v4 -; CGP-NEXT: v_add_i32_e32 v3, vcc, v3, v4 -; CGP-NEXT: v_mul_hi_u32 v4, v0, v3 -; CGP-NEXT: v_mul_hi_u32 v3, v1, v3 -; CGP-NEXT: v_lshlrev_b32_e32 v7, 12, v4 -; CGP-NEXT: v_add_i32_e32 v8, vcc, 1, v4 -; CGP-NEXT: v_lshlrev_b32_e32 v9, 12, v3 -; CGP-NEXT: v_add_i32_e32 v10, vcc, 1, v3 -; CGP-NEXT: v_sub_i32_e32 v0, vcc, v0, v7 -; CGP-NEXT: v_sub_i32_e32 v1, vcc, v1, v9 -; CGP-NEXT: v_cmp_ge_u32_e64 s[4:5], v0, v5 -; CGP-NEXT: v_cndmask_b32_e64 v4, v4, v8, s[4:5] -; CGP-NEXT: v_sub_i32_e32 v7, vcc, v0, v5 -; CGP-NEXT: v_cmp_ge_u32_e64 s[6:7], v1, v5 -; CGP-NEXT: v_cndmask_b32_e64 v3, v3, v10, s[6:7] -; CGP-NEXT: v_subrev_i32_e32 v8, vcc, 0x1000, v1 -; CGP-NEXT: v_cndmask_b32_e64 v0, v0, v7, s[4:5] -; CGP-NEXT: v_add_i32_e32 v7, vcc, 1, v4 -; CGP-NEXT: v_cndmask_b32_e64 v1, v1, v8, s[6:7] -; CGP-NEXT: v_add_i32_e32 v8, vcc, 1, v3 -; CGP-NEXT: v_cmp_ge_u32_e32 vcc, v0, v5 -; CGP-NEXT: v_cndmask_b32_e32 v0, v4, v7, vcc -; CGP-NEXT: v_cmp_ge_u32_e32 vcc, v1, v5 -; CGP-NEXT: v_cndmask_b32_e32 v1, v3, v8, vcc -; CGP-NEXT: v_xor_b32_e32 v0, v0, v2 -; CGP-NEXT: v_xor_b32_e32 v1, v1, v6 -; CGP-NEXT: v_sub_i32_e32 v0, vcc, v0, v2 -; CGP-NEXT: v_sub_i32_e32 v1, vcc, v1, v6 -; CGP-NEXT: s_setpc_b64 s[30:31] +; CHECK-LABEL: v_sdiv_v2i32_pow2k_denom: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_ashrrev_i32_e32 v2, 31, v0 +; CHECK-NEXT: v_ashrrev_i32_e32 v3, 31, v1 +; CHECK-NEXT: v_lshrrev_b32_e32 v2, 20, v2 +; CHECK-NEXT: v_lshrrev_b32_e32 v3, 20, v3 +; CHECK-NEXT: v_add_i32_e32 v0, vcc, v0, v2 +; CHECK-NEXT: v_add_i32_e32 v1, vcc, v1, v3 +; CHECK-NEXT: v_ashrrev_i32_e32 v0, 12, v0 +; CHECK-NEXT: v_ashrrev_i32_e32 v1, 12, v1 +; CHECK-NEXT: s_setpc_b64 s[30:31] %result = sdiv <2 x i32> %num, <i32 4096, i32 4096> ret <2 x i32> %result } @@ -884,3 +786,24 @@ define <2 x i32> @v_sdiv_v2i32_24bit(<2 x i32> %num, <2 x i32> %den) { %result = sdiv <2 x i32> %num.mask, %den.mask ret <2 x i32> %result } + +define i32 @v_sdiv_i32_exact(i32 %num) { +; CHECK-LABEL: v_sdiv_i32_exact: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_ashrrev_i32_e32 v0, 12, v0 +; CHECK-NEXT: s_setpc_b64 s[30:31] + %result = sdiv exact i32 %num, 4096 + ret i32 %result +} + +define <2 x i32> @v_sdiv_v2i32_exact(<2 x i32> %num) { +; CHECK-LABEL: v_sdiv_v2i32_exact: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_ashrrev_i32_e32 v0, 12, v0 +; CHECK-NEXT: v_ashrrev_i32_e32 v1, 10, v1 +; CHECK-NEXT: s_setpc_b64 s[30:31] + %result = sdiv exact <2 x i32> %num, <i32 4096, i32 1024> + ret <2 x i32> %result +} diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/sdiv.i64.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/sdiv.i64.ll index 0a6b7af2f78d4c44a81e3adb279fb03837ece1cd..377fa24cb475598350a1ed3d911bc27dcec7078a 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/sdiv.i64.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/sdiv.i64.ll @@ -999,602 +999,45 @@ define i64 @v_sdiv_i64_pow2k_denom(i64 %num) { ; CHECK-LABEL: v_sdiv_i64_pow2k_denom: ; CHECK: ; %bb.0: ; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; CHECK-NEXT: v_cvt_f32_u32_e32 v2, 0x1000 -; CHECK-NEXT: v_cvt_f32_ubyte0_e32 v3, 0 -; CHECK-NEXT: v_mov_b32_e32 v6, 0xfffff000 -; CHECK-NEXT: v_mac_f32_e32 v2, 0x4f800000, v3 -; CHECK-NEXT: v_rcp_iflag_f32_e32 v2, v2 -; CHECK-NEXT: v_mul_f32_e32 v2, 0x5f7ffffc, v2 -; CHECK-NEXT: v_mul_f32_e32 v3, 0x2f800000, v2 -; CHECK-NEXT: v_trunc_f32_e32 v4, v3 -; CHECK-NEXT: v_mac_f32_e32 v2, 0xcf800000, v4 -; CHECK-NEXT: v_cvt_u32_f32_e32 v5, v2 -; CHECK-NEXT: v_cvt_u32_f32_e32 v7, v4 -; CHECK-NEXT: v_mad_u64_u32 v[2:3], s[4:5], v6, v5, 0 -; CHECK-NEXT: v_mad_u64_u32 v[3:4], s[4:5], v6, v7, v[3:4] -; CHECK-NEXT: v_mul_hi_u32 v8, v5, v2 -; CHECK-NEXT: v_mad_u64_u32 v[3:4], s[4:5], -1, v5, v[3:4] -; CHECK-NEXT: v_mul_lo_u32 v4, v7, v2 -; CHECK-NEXT: v_mul_hi_u32 v2, v7, v2 -; CHECK-NEXT: v_mul_lo_u32 v9, v5, v3 -; CHECK-NEXT: v_mul_lo_u32 v10, v7, v3 -; CHECK-NEXT: v_mul_hi_u32 v11, v5, v3 -; CHECK-NEXT: v_mul_hi_u32 v3, v7, v3 -; CHECK-NEXT: v_add_i32_e32 v4, vcc, v4, v9 -; CHECK-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc -; CHECK-NEXT: v_add_i32_e32 v2, vcc, v10, v2 -; CHECK-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc -; CHECK-NEXT: v_add_i32_e32 v4, vcc, v4, v8 -; CHECK-NEXT: v_cndmask_b32_e64 v4, 0, 1, vcc -; CHECK-NEXT: v_add_i32_e32 v4, vcc, v9, v4 -; CHECK-NEXT: v_add_i32_e32 v2, vcc, v2, v11 -; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc -; CHECK-NEXT: v_add_i32_e32 v8, vcc, v10, v8 -; CHECK-NEXT: v_add_i32_e32 v2, vcc, v2, v4 -; CHECK-NEXT: v_cndmask_b32_e64 v4, 0, 1, vcc -; CHECK-NEXT: v_add_i32_e32 v4, vcc, v8, v4 -; CHECK-NEXT: v_add_i32_e32 v3, vcc, v3, v4 -; CHECK-NEXT: v_add_i32_e32 v5, vcc, v5, v2 -; CHECK-NEXT: v_addc_u32_e32 v7, vcc, v7, v3, vcc -; CHECK-NEXT: v_mad_u64_u32 v[2:3], s[4:5], v6, v5, 0 -; CHECK-NEXT: v_mad_u64_u32 v[3:4], s[4:5], v6, v7, v[3:4] -; CHECK-NEXT: v_ashrrev_i32_e32 v6, 31, v1 -; CHECK-NEXT: v_add_i32_e32 v0, vcc, v0, v6 -; CHECK-NEXT: v_mad_u64_u32 v[3:4], s[4:5], -1, v5, v[3:4] -; CHECK-NEXT: v_addc_u32_e32 v1, vcc, v1, v6, vcc -; CHECK-NEXT: v_xor_b32_e32 v4, v0, v6 -; CHECK-NEXT: v_mul_lo_u32 v0, v7, v2 -; CHECK-NEXT: v_mul_lo_u32 v8, v5, v3 -; CHECK-NEXT: v_xor_b32_e32 v9, v1, v6 -; CHECK-NEXT: v_mul_hi_u32 v1, v5, v2 -; CHECK-NEXT: v_mul_hi_u32 v2, v7, v2 -; CHECK-NEXT: v_add_i32_e32 v0, vcc, v0, v8 -; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc -; CHECK-NEXT: v_add_i32_e32 v0, vcc, v0, v1 -; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc -; CHECK-NEXT: v_mul_lo_u32 v1, v7, v3 -; CHECK-NEXT: v_add_i32_e32 v0, vcc, v8, v0 -; CHECK-NEXT: v_mul_hi_u32 v8, v5, v3 -; CHECK-NEXT: v_add_i32_e32 v1, vcc, v1, v2 -; CHECK-NEXT: v_cndmask_b32_e64 v2, 0, 1, vcc -; CHECK-NEXT: v_add_i32_e32 v1, vcc, v1, v8 -; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc -; CHECK-NEXT: v_add_i32_e32 v2, vcc, v2, v8 -; CHECK-NEXT: v_mul_hi_u32 v3, v7, v3 -; CHECK-NEXT: v_add_i32_e32 v0, vcc, v1, v0 -; CHECK-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc -; CHECK-NEXT: v_add_i32_e32 v1, vcc, v2, v1 -; CHECK-NEXT: v_add_i32_e32 v1, vcc, v3, v1 -; CHECK-NEXT: v_add_i32_e32 v0, vcc, v5, v0 -; CHECK-NEXT: v_addc_u32_e32 v1, vcc, v7, v1, vcc -; CHECK-NEXT: v_mul_lo_u32 v2, v9, v0 -; CHECK-NEXT: v_mul_lo_u32 v3, v4, v1 -; CHECK-NEXT: v_mul_hi_u32 v7, v4, v0 -; CHECK-NEXT: v_mul_hi_u32 v0, v9, v0 -; CHECK-NEXT: v_mov_b32_e32 v5, 0x1000 -; CHECK-NEXT: v_add_i32_e32 v2, vcc, v2, v3 -; CHECK-NEXT: v_cndmask_b32_e64 v3, 0, 1, vcc -; CHECK-NEXT: v_add_i32_e32 v2, vcc, v2, v7 -; CHECK-NEXT: v_cndmask_b32_e64 v2, 0, 1, vcc -; CHECK-NEXT: v_mul_lo_u32 v7, v9, v1 -; CHECK-NEXT: v_add_i32_e32 v2, vcc, v3, v2 -; CHECK-NEXT: v_mul_hi_u32 v3, v4, v1 -; CHECK-NEXT: v_add_i32_e32 v0, vcc, v7, v0 -; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc -; CHECK-NEXT: v_add_i32_e32 v0, vcc, v0, v3 -; CHECK-NEXT: v_cndmask_b32_e64 v3, 0, 1, vcc -; CHECK-NEXT: v_add_i32_e32 v3, vcc, v7, v3 -; CHECK-NEXT: v_add_i32_e32 v7, vcc, v0, v2 -; CHECK-NEXT: v_mul_hi_u32 v8, v9, v1 -; CHECK-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v5, v7, 0 -; CHECK-NEXT: v_cndmask_b32_e64 v2, 0, 1, vcc -; CHECK-NEXT: v_add_i32_e32 v2, vcc, v3, v2 -; CHECK-NEXT: v_add_i32_e32 v3, vcc, v8, v2 -; CHECK-NEXT: v_mad_u64_u32 v[1:2], s[4:5], v5, v3, v[1:2] -; CHECK-NEXT: v_sub_i32_e32 v0, vcc, v4, v0 -; CHECK-NEXT: v_subb_u32_e64 v2, s[4:5], v9, v1, vcc -; CHECK-NEXT: v_sub_i32_e64 v1, s[4:5], v9, v1 -; CHECK-NEXT: v_subbrev_u32_e32 v1, vcc, 0, v1, vcc -; CHECK-NEXT: v_cmp_ge_u32_e64 s[4:5], v0, v5 -; CHECK-NEXT: v_sub_i32_e32 v0, vcc, v0, v5 -; CHECK-NEXT: v_cndmask_b32_e64 v4, 0, -1, s[4:5] -; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v2 -; CHECK-NEXT: v_subbrev_u32_e32 v1, vcc, 0, v1, vcc -; CHECK-NEXT: v_cndmask_b32_e64 v2, -1, v4, s[4:5] -; CHECK-NEXT: v_add_i32_e32 v4, vcc, 1, v7 -; CHECK-NEXT: v_addc_u32_e32 v8, vcc, 0, v3, vcc -; CHECK-NEXT: v_cmp_ge_u32_e32 vcc, v0, v5 -; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, -1, vcc -; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 0, v1 -; CHECK-NEXT: v_cndmask_b32_e32 v0, -1, v0, vcc -; CHECK-NEXT: v_add_i32_e32 v1, vcc, 1, v4 -; CHECK-NEXT: v_addc_u32_e32 v5, vcc, 0, v8, vcc -; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v0 -; CHECK-NEXT: v_cndmask_b32_e32 v0, v4, v1, vcc -; CHECK-NEXT: v_cndmask_b32_e32 v1, v8, v5, vcc -; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v2 -; CHECK-NEXT: v_cndmask_b32_e32 v0, v7, v0, vcc -; CHECK-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc -; CHECK-NEXT: v_xor_b32_e32 v0, v0, v6 -; CHECK-NEXT: v_xor_b32_e32 v1, v1, v6 -; CHECK-NEXT: v_sub_i32_e32 v0, vcc, v0, v6 -; CHECK-NEXT: v_subb_u32_e32 v1, vcc, v1, v6, vcc -; CHECK-NEXT: s_setpc_b64 s[30:31] - %result = sdiv i64 %num, 4096 - ret i64 %result -} - -define <2 x i64> @v_sdiv_v2i64_pow2k_denom(<2 x i64> %num) { -; GISEL-LABEL: v_sdiv_v2i64_pow2k_denom: -; GISEL: ; %bb.0: -; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GISEL-NEXT: v_cvt_f32_u32_e32 v4, 0x1000 -; GISEL-NEXT: v_cvt_f32_ubyte0_e32 v5, 0 -; GISEL-NEXT: s_sub_u32 s6, 0, 0x1000 -; GISEL-NEXT: s_subb_u32 s7, 0, 0 -; GISEL-NEXT: v_mac_f32_e32 v4, 0x4f800000, v5 -; GISEL-NEXT: v_rcp_iflag_f32_e32 v4, v4 -; GISEL-NEXT: v_mul_f32_e32 v4, 0x5f7ffffc, v4 -; GISEL-NEXT: v_mul_f32_e32 v5, 0x2f800000, v4 -; GISEL-NEXT: v_trunc_f32_e32 v7, v5 -; GISEL-NEXT: v_mac_f32_e32 v4, 0xcf800000, v7 -; GISEL-NEXT: v_cvt_u32_f32_e32 v6, v4 -; GISEL-NEXT: v_cvt_u32_f32_e32 v7, v7 -; GISEL-NEXT: v_mad_u64_u32 v[4:5], s[4:5], s6, v6, 0 -; GISEL-NEXT: v_mad_u64_u32 v[8:9], s[4:5], s6, v7, v[5:6] -; GISEL-NEXT: v_mul_lo_u32 v5, v7, v4 -; GISEL-NEXT: v_mad_u64_u32 v[8:9], s[4:5], s7, v6, v[8:9] -; GISEL-NEXT: v_mul_hi_u32 v9, v6, v4 -; GISEL-NEXT: v_mul_hi_u32 v4, v7, v4 -; GISEL-NEXT: v_mul_lo_u32 v10, v6, v8 -; GISEL-NEXT: v_mul_lo_u32 v11, v7, v8 -; GISEL-NEXT: v_mul_hi_u32 v12, v6, v8 -; GISEL-NEXT: v_mul_hi_u32 v8, v7, v8 -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v10 -; GISEL-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v9 -; GISEL-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v10, v5 -; GISEL-NEXT: v_add_i32_e32 v4, vcc, v11, v4 -; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v4, vcc, v4, v12 -; GISEL-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v9, vcc, v9, v10 -; GISEL-NEXT: v_add_i32_e32 v4, vcc, v4, v5 -; GISEL-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v9, v5 -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v8, v5 -; GISEL-NEXT: v_add_i32_e32 v11, vcc, v6, v4 -; GISEL-NEXT: v_mad_u64_u32 v[8:9], s[4:5], s6, v11, 0 -; GISEL-NEXT: v_addc_u32_e32 v5, vcc, v7, v5, vcc -; GISEL-NEXT: v_mov_b32_e32 v4, v9 -; GISEL-NEXT: v_mad_u64_u32 v[9:10], s[4:5], s6, v5, v[4:5] -; GISEL-NEXT: v_ashrrev_i32_e32 v4, 31, v1 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v4 -; GISEL-NEXT: v_mad_u64_u32 v[9:10], s[4:5], s7, v11, v[9:10] -; GISEL-NEXT: v_addc_u32_e32 v1, vcc, v1, v4, vcc -; GISEL-NEXT: v_xor_b32_e32 v10, v0, v4 -; GISEL-NEXT: v_mul_lo_u32 v0, v5, v8 -; GISEL-NEXT: v_mul_lo_u32 v12, v11, v9 -; GISEL-NEXT: v_xor_b32_e32 v13, v1, v4 -; GISEL-NEXT: v_mul_hi_u32 v1, v11, v8 -; GISEL-NEXT: v_mul_hi_u32 v8, v5, v8 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v12 -; GISEL-NEXT: v_cndmask_b32_e64 v12, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v1 -; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc -; GISEL-NEXT: v_mul_lo_u32 v1, v5, v9 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v12, v0 -; GISEL-NEXT: v_mul_hi_u32 v12, v11, v9 -; GISEL-NEXT: v_add_i32_e32 v1, vcc, v1, v8 -; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v1, vcc, v1, v12 -; GISEL-NEXT: v_cndmask_b32_e64 v12, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v8, vcc, v8, v12 -; GISEL-NEXT: v_mul_hi_u32 v9, v5, v9 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v1, v0 -; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v1, vcc, v8, v1 -; GISEL-NEXT: v_add_i32_e32 v1, vcc, v9, v1 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v11, v0 -; GISEL-NEXT: v_addc_u32_e32 v1, vcc, v5, v1, vcc -; GISEL-NEXT: v_mul_lo_u32 v8, v13, v0 -; GISEL-NEXT: v_mul_lo_u32 v9, v10, v1 -; GISEL-NEXT: v_mul_hi_u32 v11, v10, v0 -; GISEL-NEXT: v_mul_hi_u32 v0, v13, v0 -; GISEL-NEXT: v_mov_b32_e32 v5, 0x1000 -; GISEL-NEXT: v_add_i32_e32 v8, vcc, v8, v9 -; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v8, vcc, v8, v11 -; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc -; GISEL-NEXT: v_mul_lo_u32 v11, v13, v1 -; GISEL-NEXT: v_add_i32_e32 v8, vcc, v9, v8 -; GISEL-NEXT: v_mul_hi_u32 v9, v10, v1 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v11, v0 -; GISEL-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v9 -; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v9, vcc, v11, v9 -; GISEL-NEXT: v_add_i32_e32 v11, vcc, v0, v8 -; GISEL-NEXT: v_mul_hi_u32 v12, v13, v1 -; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v5, v11, 0 -; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v8, vcc, v9, v8 -; GISEL-NEXT: v_add_i32_e32 v12, vcc, v12, v8 -; GISEL-NEXT: v_mad_u64_u32 v[8:9], s[4:5], v5, v12, v[1:2] -; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v10, v0 -; GISEL-NEXT: v_mad_u64_u32 v[8:9], s[4:5], 0, v11, v[8:9] -; GISEL-NEXT: s_sub_u32 s6, 0, 0x1000 -; GISEL-NEXT: s_subb_u32 s7, 0, 0 -; GISEL-NEXT: v_subb_u32_e64 v1, s[4:5], v13, v8, vcc -; GISEL-NEXT: v_sub_i32_e64 v8, s[4:5], v13, v8 -; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v0, v5 -; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, -1, s[4:5] -; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v1 -; GISEL-NEXT: v_subbrev_u32_e32 v1, vcc, 0, v8, vcc -; GISEL-NEXT: v_sub_i32_e32 v8, vcc, v0, v5 -; GISEL-NEXT: v_cndmask_b32_e64 v10, -1, v9, s[4:5] -; GISEL-NEXT: v_subbrev_u32_e32 v9, vcc, 0, v1, vcc -; GISEL-NEXT: v_add_i32_e32 v13, vcc, 1, v11 -; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[4:5], s6, v6, 0 -; GISEL-NEXT: v_addc_u32_e32 v14, vcc, 0, v12, vcc -; GISEL-NEXT: v_cmp_ge_u32_e32 vcc, v8, v5 -; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, -1, vcc -; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v9 -; GISEL-NEXT: v_cndmask_b32_e32 v15, -1, v8, vcc -; GISEL-NEXT: v_mad_u64_u32 v[8:9], s[4:5], s6, v7, v[1:2] -; GISEL-NEXT: v_add_i32_e32 v1, vcc, 1, v13 -; GISEL-NEXT: v_mad_u64_u32 v[8:9], s[4:5], s7, v6, v[8:9] -; GISEL-NEXT: v_addc_u32_e32 v16, vcc, 0, v14, vcc -; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v15 -; GISEL-NEXT: v_cndmask_b32_e32 v9, v13, v1, vcc -; GISEL-NEXT: v_mul_lo_u32 v1, v7, v0 -; GISEL-NEXT: v_mul_lo_u32 v13, v6, v8 -; GISEL-NEXT: v_mul_hi_u32 v15, v6, v0 -; GISEL-NEXT: v_cndmask_b32_e32 v14, v14, v16, vcc -; GISEL-NEXT: v_mul_hi_u32 v0, v7, v0 -; GISEL-NEXT: v_add_i32_e32 v1, vcc, v1, v13 -; GISEL-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v1, vcc, v1, v15 -; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc -; GISEL-NEXT: v_mul_lo_u32 v15, v7, v8 -; GISEL-NEXT: v_add_i32_e32 v1, vcc, v13, v1 -; GISEL-NEXT: v_mul_hi_u32 v13, v6, v8 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v15, v0 -; GISEL-NEXT: v_cndmask_b32_e64 v15, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v13 -; GISEL-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v13, vcc, v15, v13 -; GISEL-NEXT: v_mul_hi_u32 v8, v7, v8 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v1 -; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v1, vcc, v13, v1 -; GISEL-NEXT: v_add_i32_e32 v1, vcc, v8, v1 -; GISEL-NEXT: v_add_i32_e32 v8, vcc, v6, v0 -; GISEL-NEXT: v_addc_u32_e32 v13, vcc, v7, v1, vcc -; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[4:5], s6, v8, 0 -; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v10 -; GISEL-NEXT: v_cndmask_b32_e32 v9, v11, v9, vcc -; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[4:5], s6, v13, v[1:2] -; GISEL-NEXT: v_xor_b32_e32 v1, v9, v4 -; GISEL-NEXT: v_ashrrev_i32_e32 v9, 31, v3 -; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[4:5], s7, v8, v[6:7] -; GISEL-NEXT: v_cndmask_b32_e32 v10, v12, v14, vcc -; GISEL-NEXT: v_add_i32_e32 v2, vcc, v2, v9 -; GISEL-NEXT: v_addc_u32_e32 v3, vcc, v3, v9, vcc -; GISEL-NEXT: v_xor_b32_e32 v11, v2, v9 -; GISEL-NEXT: v_mul_lo_u32 v2, v13, v0 -; GISEL-NEXT: v_mul_lo_u32 v7, v8, v6 -; GISEL-NEXT: v_xor_b32_e32 v12, v3, v9 -; GISEL-NEXT: v_mul_hi_u32 v3, v8, v0 -; GISEL-NEXT: v_mul_hi_u32 v0, v13, v0 -; GISEL-NEXT: v_add_i32_e32 v2, vcc, v2, v7 -; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v2, vcc, v2, v3 -; GISEL-NEXT: v_cndmask_b32_e64 v2, 0, 1, vcc -; GISEL-NEXT: v_mul_lo_u32 v3, v13, v6 -; GISEL-NEXT: v_add_i32_e32 v2, vcc, v7, v2 -; GISEL-NEXT: v_mul_hi_u32 v7, v8, v6 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v3, v0 -; GISEL-NEXT: v_cndmask_b32_e64 v3, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v7 -; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v3, vcc, v3, v7 -; GISEL-NEXT: v_mul_hi_u32 v6, v13, v6 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v2 -; GISEL-NEXT: v_cndmask_b32_e64 v2, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v2, vcc, v3, v2 -; GISEL-NEXT: v_add_i32_e32 v2, vcc, v6, v2 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v8, v0 -; GISEL-NEXT: v_addc_u32_e32 v2, vcc, v13, v2, vcc -; GISEL-NEXT: v_mul_lo_u32 v3, v12, v0 -; GISEL-NEXT: v_mul_lo_u32 v6, v11, v2 -; GISEL-NEXT: v_mul_hi_u32 v7, v11, v0 -; GISEL-NEXT: v_mul_hi_u32 v0, v12, v0 -; GISEL-NEXT: v_xor_b32_e32 v8, v10, v4 -; GISEL-NEXT: v_add_i32_e32 v3, vcc, v3, v6 -; GISEL-NEXT: v_cndmask_b32_e64 v6, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v3, vcc, v3, v7 -; GISEL-NEXT: v_cndmask_b32_e64 v3, 0, 1, vcc -; GISEL-NEXT: v_mul_lo_u32 v7, v12, v2 -; GISEL-NEXT: v_add_i32_e32 v3, vcc, v6, v3 -; GISEL-NEXT: v_mul_hi_u32 v6, v11, v2 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v7, v0 -; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v6 -; GISEL-NEXT: v_cndmask_b32_e64 v6, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v6, vcc, v7, v6 -; GISEL-NEXT: v_add_i32_e32 v10, vcc, v0, v3 -; GISEL-NEXT: v_mul_hi_u32 v7, v12, v2 -; GISEL-NEXT: v_mad_u64_u32 v[2:3], s[4:5], v5, v10, 0 -; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v6, v0 -; GISEL-NEXT: v_add_i32_e32 v13, vcc, v7, v0 -; GISEL-NEXT: v_mov_b32_e32 v0, v3 -; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[4:5], v5, v13, v[0:1] -; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v1, v4 -; GISEL-NEXT: v_subb_u32_e32 v1, vcc, v8, v4, vcc -; GISEL-NEXT: v_mad_u64_u32 v[3:4], s[4:5], 0, v10, v[6:7] -; GISEL-NEXT: v_sub_i32_e32 v2, vcc, v11, v2 -; GISEL-NEXT: v_subb_u32_e64 v4, s[4:5], v12, v3, vcc -; GISEL-NEXT: v_sub_i32_e64 v3, s[4:5], v12, v3 -; GISEL-NEXT: v_subbrev_u32_e32 v3, vcc, 0, v3, vcc -; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v2, v5 -; GISEL-NEXT: v_sub_i32_e32 v2, vcc, v2, v5 -; GISEL-NEXT: v_cndmask_b32_e64 v6, 0, -1, s[4:5] -; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v4 -; GISEL-NEXT: v_subbrev_u32_e32 v3, vcc, 0, v3, vcc -; GISEL-NEXT: v_cndmask_b32_e64 v4, -1, v6, s[4:5] -; GISEL-NEXT: v_add_i32_e32 v6, vcc, 1, v10 -; GISEL-NEXT: v_addc_u32_e32 v7, vcc, 0, v13, vcc -; GISEL-NEXT: v_cmp_ge_u32_e32 vcc, v2, v5 -; GISEL-NEXT: v_cndmask_b32_e64 v2, 0, -1, vcc -; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v3 -; GISEL-NEXT: v_cndmask_b32_e32 v2, -1, v2, vcc -; GISEL-NEXT: v_add_i32_e32 v3, vcc, 1, v6 -; GISEL-NEXT: v_addc_u32_e32 v5, vcc, 0, v7, vcc -; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v2 -; GISEL-NEXT: v_cndmask_b32_e32 v2, v6, v3, vcc -; GISEL-NEXT: v_cndmask_b32_e32 v3, v7, v5, vcc -; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v4 -; GISEL-NEXT: v_cndmask_b32_e32 v2, v10, v2, vcc -; GISEL-NEXT: v_cndmask_b32_e32 v3, v13, v3, vcc -; GISEL-NEXT: v_xor_b32_e32 v2, v2, v9 -; GISEL-NEXT: v_xor_b32_e32 v3, v3, v9 -; GISEL-NEXT: v_sub_i32_e32 v2, vcc, v2, v9 -; GISEL-NEXT: v_subb_u32_e32 v3, vcc, v3, v9, vcc -; GISEL-NEXT: s_setpc_b64 s[30:31] -; -; CGP-LABEL: v_sdiv_v2i64_pow2k_denom: -; CGP: ; %bb.0: -; CGP-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; CGP-NEXT: v_cvt_f32_u32_e32 v4, 0x1000 -; CGP-NEXT: v_cvt_f32_ubyte0_e32 v5, 0 -; CGP-NEXT: v_mov_b32_e32 v6, 0xfffff000 -; CGP-NEXT: v_mac_f32_e32 v4, 0x4f800000, v5 -; CGP-NEXT: v_rcp_iflag_f32_e32 v4, v4 -; CGP-NEXT: v_mul_f32_e32 v4, 0x5f7ffffc, v4 -; CGP-NEXT: v_mul_f32_e32 v5, 0x2f800000, v4 -; CGP-NEXT: v_trunc_f32_e32 v7, v5 -; CGP-NEXT: v_mac_f32_e32 v4, 0xcf800000, v7 -; CGP-NEXT: v_cvt_u32_f32_e32 v8, v4 -; CGP-NEXT: v_cvt_u32_f32_e32 v9, v7 -; CGP-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v6, v8, 0 -; CGP-NEXT: v_mov_b32_e32 v7, v5 -; CGP-NEXT: v_mad_u64_u32 v[10:11], s[4:5], v6, v9, v[7:8] -; CGP-NEXT: v_mul_hi_u32 v12, v9, v4 -; CGP-NEXT: v_mad_u64_u32 v[13:14], s[4:5], -1, v8, v[10:11] -; CGP-NEXT: v_mul_lo_u32 v10, v9, v4 -; CGP-NEXT: v_mul_hi_u32 v11, v8, v4 -; CGP-NEXT: v_mul_lo_u32 v4, v8, v13 -; CGP-NEXT: v_mul_lo_u32 v7, v9, v13 -; CGP-NEXT: v_mul_hi_u32 v14, v8, v13 -; CGP-NEXT: v_mul_hi_u32 v13, v9, v13 -; CGP-NEXT: v_add_i32_e32 v4, vcc, v10, v4 -; CGP-NEXT: v_cndmask_b32_e64 v15, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v4, vcc, v4, v11 -; CGP-NEXT: v_cndmask_b32_e64 v4, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v4, vcc, v15, v4 -; CGP-NEXT: v_add_i32_e32 v7, vcc, v7, v12 -; CGP-NEXT: v_cndmask_b32_e64 v15, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v7, vcc, v7, v14 -; CGP-NEXT: v_cndmask_b32_e64 v14, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v14, vcc, v15, v14 -; CGP-NEXT: v_add_i32_e32 v4, vcc, v7, v4 -; CGP-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v7, vcc, v14, v7 -; CGP-NEXT: v_add_i32_e32 v7, vcc, v13, v7 -; CGP-NEXT: v_add_i32_e32 v16, vcc, v8, v4 -; CGP-NEXT: v_mad_u64_u32 v[13:14], s[4:5], v6, v16, 0 -; CGP-NEXT: v_addc_u32_e32 v17, vcc, v9, v7, vcc -; CGP-NEXT: v_mov_b32_e32 v4, v14 -; CGP-NEXT: v_mad_u64_u32 v[14:15], s[4:5], v6, v17, v[4:5] -; CGP-NEXT: v_ashrrev_i32_e32 v7, 31, v1 -; CGP-NEXT: v_add_i32_e32 v0, vcc, v0, v7 -; CGP-NEXT: v_mad_u64_u32 v[14:15], s[4:5], -1, v16, v[14:15] -; CGP-NEXT: v_addc_u32_e32 v1, vcc, v1, v7, vcc -; CGP-NEXT: v_xor_b32_e32 v15, v0, v7 -; CGP-NEXT: v_mul_lo_u32 v0, v17, v13 -; CGP-NEXT: v_mul_lo_u32 v4, v16, v14 -; CGP-NEXT: v_xor_b32_e32 v18, v1, v7 -; CGP-NEXT: v_mul_hi_u32 v1, v16, v13 -; CGP-NEXT: v_mul_hi_u32 v13, v17, v13 -; CGP-NEXT: v_add_i32_e32 v0, vcc, v0, v4 -; CGP-NEXT: v_cndmask_b32_e64 v4, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v0, vcc, v0, v1 -; CGP-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc -; CGP-NEXT: v_mul_lo_u32 v1, v17, v14 -; CGP-NEXT: v_add_i32_e32 v0, vcc, v4, v0 -; CGP-NEXT: v_mul_hi_u32 v4, v16, v14 -; CGP-NEXT: v_add_i32_e32 v1, vcc, v1, v13 -; CGP-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v1, vcc, v1, v4 -; CGP-NEXT: v_cndmask_b32_e64 v4, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v4, vcc, v13, v4 -; CGP-NEXT: v_mul_hi_u32 v13, v17, v14 -; CGP-NEXT: v_add_i32_e32 v0, vcc, v1, v0 -; CGP-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v1, vcc, v4, v1 -; CGP-NEXT: v_add_i32_e32 v1, vcc, v13, v1 -; CGP-NEXT: v_add_i32_e32 v0, vcc, v16, v0 -; CGP-NEXT: v_addc_u32_e32 v1, vcc, v17, v1, vcc -; CGP-NEXT: v_mul_lo_u32 v13, v18, v0 -; CGP-NEXT: v_mul_lo_u32 v14, v15, v1 -; CGP-NEXT: v_mul_hi_u32 v16, v15, v0 -; CGP-NEXT: v_mul_hi_u32 v0, v18, v0 -; CGP-NEXT: v_mov_b32_e32 v4, 0x1000 -; CGP-NEXT: v_add_i32_e32 v13, vcc, v13, v14 -; CGP-NEXT: v_cndmask_b32_e64 v14, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v13, vcc, v13, v16 -; CGP-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc -; CGP-NEXT: v_mul_lo_u32 v16, v18, v1 -; CGP-NEXT: v_add_i32_e32 v13, vcc, v14, v13 -; CGP-NEXT: v_mul_hi_u32 v14, v15, v1 -; CGP-NEXT: v_add_i32_e32 v0, vcc, v16, v0 -; CGP-NEXT: v_cndmask_b32_e64 v16, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v0, vcc, v0, v14 -; CGP-NEXT: v_cndmask_b32_e64 v14, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v14, vcc, v16, v14 -; CGP-NEXT: v_add_i32_e32 v16, vcc, v0, v13 -; CGP-NEXT: v_mul_hi_u32 v17, v18, v1 -; CGP-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v4, v16, 0 -; CGP-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v13, vcc, v14, v13 -; CGP-NEXT: v_add_i32_e32 v17, vcc, v17, v13 -; CGP-NEXT: v_mad_u64_u32 v[13:14], s[4:5], v4, v17, v[1:2] -; CGP-NEXT: v_sub_i32_e32 v0, vcc, v15, v0 -; CGP-NEXT: v_subb_u32_e64 v1, s[4:5], v18, v13, vcc -; CGP-NEXT: v_sub_i32_e64 v13, s[4:5], v18, v13 -; CGP-NEXT: v_cmp_ge_u32_e64 s[4:5], v0, v4 -; CGP-NEXT: v_cndmask_b32_e64 v14, 0, -1, s[4:5] -; CGP-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v1 -; CGP-NEXT: v_subbrev_u32_e32 v1, vcc, 0, v13, vcc -; CGP-NEXT: v_sub_i32_e32 v0, vcc, v0, v4 -; CGP-NEXT: v_subbrev_u32_e32 v13, vcc, 0, v1, vcc -; CGP-NEXT: v_add_i32_e32 v15, vcc, 1, v16 -; CGP-NEXT: v_addc_u32_e32 v18, vcc, 0, v17, vcc -; CGP-NEXT: v_cmp_ge_u32_e32 vcc, v0, v4 -; CGP-NEXT: v_mov_b32_e32 v0, v5 -; CGP-NEXT: v_cndmask_b32_e64 v14, -1, v14, s[4:5] -; CGP-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v6, v9, v[0:1] -; CGP-NEXT: v_cndmask_b32_e64 v19, 0, -1, vcc -; CGP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v13 -; CGP-NEXT: v_mad_u64_u32 v[0:1], s[4:5], -1, v8, v[0:1] -; CGP-NEXT: v_cndmask_b32_e32 v5, -1, v19, vcc -; CGP-NEXT: v_add_i32_e32 v1, vcc, 1, v15 -; CGP-NEXT: v_mul_lo_u32 v19, v8, v0 -; CGP-NEXT: v_addc_u32_e32 v13, vcc, 0, v18, vcc -; CGP-NEXT: v_cmp_ne_u32_e32 vcc, 0, v5 -; CGP-NEXT: v_cndmask_b32_e32 v5, v15, v1, vcc -; CGP-NEXT: v_cndmask_b32_e32 v13, v18, v13, vcc -; CGP-NEXT: v_add_i32_e32 v1, vcc, v10, v19 -; CGP-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v1, vcc, v1, v11 -; CGP-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc -; CGP-NEXT: v_mul_lo_u32 v11, v9, v0 -; CGP-NEXT: v_add_i32_e32 v1, vcc, v10, v1 -; CGP-NEXT: v_mul_hi_u32 v10, v8, v0 -; CGP-NEXT: v_add_i32_e32 v11, vcc, v11, v12 -; CGP-NEXT: v_cndmask_b32_e64 v12, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v10, vcc, v11, v10 -; CGP-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v11, vcc, v12, v11 -; CGP-NEXT: v_mul_hi_u32 v0, v9, v0 -; CGP-NEXT: v_add_i32_e32 v1, vcc, v10, v1 -; CGP-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v10, vcc, v11, v10 -; CGP-NEXT: v_add_i32_e32 v0, vcc, v0, v10 -; CGP-NEXT: v_add_i32_e32 v8, vcc, v8, v1 -; CGP-NEXT: v_addc_u32_e32 v9, vcc, v9, v0, vcc -; CGP-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v6, v8, 0 -; CGP-NEXT: v_cmp_ne_u32_e32 vcc, 0, v14 -; CGP-NEXT: v_cndmask_b32_e32 v5, v16, v5, vcc -; CGP-NEXT: v_xor_b32_e32 v11, v5, v7 -; CGP-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v6, v9, v[1:2] -; CGP-NEXT: v_cndmask_b32_e32 v10, v17, v13, vcc -; CGP-NEXT: v_xor_b32_e32 v1, v10, v7 -; CGP-NEXT: v_mad_u64_u32 v[5:6], s[4:5], -1, v8, v[5:6] -; CGP-NEXT: v_ashrrev_i32_e32 v10, 31, v3 -; CGP-NEXT: v_add_i32_e32 v2, vcc, v2, v10 -; CGP-NEXT: v_addc_u32_e32 v3, vcc, v3, v10, vcc -; CGP-NEXT: v_xor_b32_e32 v12, v2, v10 -; CGP-NEXT: v_mul_lo_u32 v2, v9, v0 -; CGP-NEXT: v_mul_lo_u32 v6, v8, v5 -; CGP-NEXT: v_xor_b32_e32 v13, v3, v10 -; CGP-NEXT: v_mul_hi_u32 v3, v8, v0 -; CGP-NEXT: v_mul_hi_u32 v0, v9, v0 -; CGP-NEXT: v_add_i32_e32 v2, vcc, v2, v6 -; CGP-NEXT: v_cndmask_b32_e64 v6, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v2, vcc, v2, v3 -; CGP-NEXT: v_cndmask_b32_e64 v2, 0, 1, vcc -; CGP-NEXT: v_mul_lo_u32 v3, v9, v5 -; CGP-NEXT: v_add_i32_e32 v2, vcc, v6, v2 -; CGP-NEXT: v_mul_hi_u32 v6, v8, v5 -; CGP-NEXT: v_add_i32_e32 v0, vcc, v3, v0 -; CGP-NEXT: v_cndmask_b32_e64 v3, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v0, vcc, v0, v6 -; CGP-NEXT: v_cndmask_b32_e64 v6, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v3, vcc, v3, v6 -; CGP-NEXT: v_mul_hi_u32 v5, v9, v5 -; CGP-NEXT: v_add_i32_e32 v0, vcc, v0, v2 -; CGP-NEXT: v_cndmask_b32_e64 v2, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v2, vcc, v3, v2 -; CGP-NEXT: v_add_i32_e32 v2, vcc, v5, v2 -; CGP-NEXT: v_add_i32_e32 v3, vcc, v8, v0 -; CGP-NEXT: v_addc_u32_e32 v2, vcc, v9, v2, vcc -; CGP-NEXT: v_mul_lo_u32 v5, v13, v3 -; CGP-NEXT: v_mul_lo_u32 v6, v12, v2 -; CGP-NEXT: v_sub_i32_e32 v0, vcc, v11, v7 -; CGP-NEXT: v_subb_u32_e32 v1, vcc, v1, v7, vcc -; CGP-NEXT: v_mul_hi_u32 v7, v12, v3 -; CGP-NEXT: v_add_i32_e32 v5, vcc, v5, v6 -; CGP-NEXT: v_cndmask_b32_e64 v6, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v5, vcc, v5, v7 -; CGP-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc -; CGP-NEXT: v_mul_lo_u32 v7, v13, v2 -; CGP-NEXT: v_mul_hi_u32 v3, v13, v3 -; CGP-NEXT: v_add_i32_e32 v5, vcc, v6, v5 -; CGP-NEXT: v_mul_hi_u32 v6, v12, v2 -; CGP-NEXT: v_add_i32_e32 v3, vcc, v7, v3 -; CGP-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v3, vcc, v3, v6 -; CGP-NEXT: v_cndmask_b32_e64 v6, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v6, vcc, v7, v6 -; CGP-NEXT: v_add_i32_e32 v7, vcc, v3, v5 -; CGP-NEXT: v_mul_hi_u32 v8, v13, v2 -; CGP-NEXT: v_mad_u64_u32 v[2:3], s[4:5], v4, v7, 0 -; CGP-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc -; CGP-NEXT: v_add_i32_e32 v5, vcc, v6, v5 -; CGP-NEXT: v_add_i32_e32 v8, vcc, v8, v5 -; CGP-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v4, v8, v[3:4] -; CGP-NEXT: v_sub_i32_e32 v2, vcc, v12, v2 -; CGP-NEXT: v_subb_u32_e64 v3, s[4:5], v13, v5, vcc -; CGP-NEXT: v_sub_i32_e64 v5, s[4:5], v13, v5 -; CGP-NEXT: v_subbrev_u32_e32 v5, vcc, 0, v5, vcc -; CGP-NEXT: v_cmp_ge_u32_e64 s[4:5], v2, v4 -; CGP-NEXT: v_sub_i32_e32 v2, vcc, v2, v4 -; CGP-NEXT: v_cndmask_b32_e64 v6, 0, -1, s[4:5] -; CGP-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v3 -; CGP-NEXT: v_subbrev_u32_e32 v5, vcc, 0, v5, vcc -; CGP-NEXT: v_cndmask_b32_e64 v3, -1, v6, s[4:5] -; CGP-NEXT: v_add_i32_e32 v6, vcc, 1, v7 -; CGP-NEXT: v_addc_u32_e32 v9, vcc, 0, v8, vcc -; CGP-NEXT: v_cmp_ge_u32_e32 vcc, v2, v4 -; CGP-NEXT: v_cndmask_b32_e64 v2, 0, -1, vcc -; CGP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v5 -; CGP-NEXT: v_cndmask_b32_e32 v2, -1, v2, vcc -; CGP-NEXT: v_add_i32_e32 v4, vcc, 1, v6 -; CGP-NEXT: v_addc_u32_e32 v5, vcc, 0, v9, vcc -; CGP-NEXT: v_cmp_ne_u32_e32 vcc, 0, v2 -; CGP-NEXT: v_cndmask_b32_e32 v2, v6, v4, vcc -; CGP-NEXT: v_cndmask_b32_e32 v4, v9, v5, vcc -; CGP-NEXT: v_cmp_ne_u32_e32 vcc, 0, v3 -; CGP-NEXT: v_cndmask_b32_e32 v2, v7, v2, vcc -; CGP-NEXT: v_cndmask_b32_e32 v3, v8, v4, vcc -; CGP-NEXT: v_xor_b32_e32 v2, v2, v10 -; CGP-NEXT: v_xor_b32_e32 v3, v3, v10 -; CGP-NEXT: v_sub_i32_e32 v2, vcc, v2, v10 -; CGP-NEXT: v_subb_u32_e32 v3, vcc, v3, v10, vcc +; CHECK-NEXT: v_ashrrev_i32_e32 v2, 31, v1 +; CHECK-NEXT: v_lshrrev_b32_e32 v2, 20, v2 +; CHECK-NEXT: v_add_i32_e32 v0, vcc, v0, v2 +; CHECK-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; CHECK-NEXT: v_ashr_i64 v[0:1], v[0:1], 12 +; CHECK-NEXT: s_setpc_b64 s[30:31] + %result = sdiv i64 %num, 4096 + ret i64 %result +} + +define <2 x i64> @v_sdiv_v2i64_pow2k_denom(<2 x i64> %num) { +; GISEL-LABEL: v_sdiv_v2i64_pow2k_denom: +; GISEL: ; %bb.0: +; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-NEXT: v_ashrrev_i32_e32 v4, 31, v1 +; GISEL-NEXT: v_lshrrev_b32_e32 v4, 20, v4 +; GISEL-NEXT: v_ashrrev_i32_e32 v5, 31, v3 +; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v4 +; GISEL-NEXT: v_lshrrev_b32_e32 v5, 20, v5 +; GISEL-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; GISEL-NEXT: v_add_i32_e32 v2, vcc, v2, v5 +; GISEL-NEXT: v_addc_u32_e32 v3, vcc, 0, v3, vcc +; GISEL-NEXT: v_ashr_i64 v[0:1], v[0:1], 12 +; GISEL-NEXT: v_ashr_i64 v[2:3], v[2:3], 12 +; GISEL-NEXT: s_setpc_b64 s[30:31] +; +; CGP-LABEL: v_sdiv_v2i64_pow2k_denom: +; CGP: ; %bb.0: +; CGP-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CGP-NEXT: v_ashrrev_i32_e32 v4, 31, v1 +; CGP-NEXT: v_lshrrev_b32_e32 v4, 20, v4 +; CGP-NEXT: v_add_i32_e32 v0, vcc, v0, v4 +; CGP-NEXT: v_ashrrev_i32_e32 v4, 31, v3 +; CGP-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc +; CGP-NEXT: v_lshrrev_b32_e32 v4, 20, v4 +; CGP-NEXT: v_add_i32_e32 v2, vcc, v2, v4 +; CGP-NEXT: v_addc_u32_e32 v3, vcc, 0, v3, vcc +; CGP-NEXT: v_ashr_i64 v[0:1], v[0:1], 12 +; CGP-NEXT: v_ashr_i64 v[2:3], v[2:3], 12 ; CGP-NEXT: s_setpc_b64 s[30:31] %result = sdiv <2 x i64> %num, <i64 4096, i64 4096> ret <2 x i64> %result @@ -3091,253 +2534,252 @@ define <2 x i64> @v_sdiv_v2i64_24bit(<2 x i64> %num, <2 x i64> %den) { ; GISEL: ; %bb.0: ; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GISEL-NEXT: v_and_b32_e32 v1, 0xffffff, v4 -; GISEL-NEXT: v_add_i32_e32 v3, vcc, 0, v1 -; GISEL-NEXT: v_addc_u32_e64 v1, s[4:5], 0, 0, vcc -; GISEL-NEXT: v_cvt_f32_u32_e32 v4, v3 +; GISEL-NEXT: v_add_i32_e64 v3, s[4:5], 0, 0 +; GISEL-NEXT: v_add_i32_e32 v1, vcc, 0, v1 ; GISEL-NEXT: v_cvt_f32_u32_e32 v5, v1 -; GISEL-NEXT: v_sub_i32_e32 v10, vcc, 0, v3 -; GISEL-NEXT: v_subb_u32_e32 v11, vcc, 0, v1, vcc -; GISEL-NEXT: v_mac_f32_e32 v4, 0x4f800000, v5 -; GISEL-NEXT: v_rcp_iflag_f32_e32 v4, v4 +; GISEL-NEXT: v_cvt_f32_u32_e32 v4, v3 +; GISEL-NEXT: v_sub_i32_e32 v11, vcc, 0, v1 +; GISEL-NEXT: v_subb_u32_e32 v12, vcc, 0, v3, vcc +; GISEL-NEXT: v_mac_f32_e32 v5, 0x4f800000, v4 +; GISEL-NEXT: v_rcp_iflag_f32_e32 v5, v5 ; GISEL-NEXT: v_and_b32_e32 v0, 0xffffff, v0 -; GISEL-NEXT: v_mul_f32_e32 v4, 0x5f7ffffc, v4 -; GISEL-NEXT: v_mul_f32_e32 v5, 0x2f800000, v4 -; GISEL-NEXT: v_trunc_f32_e32 v7, v5 -; GISEL-NEXT: v_mac_f32_e32 v4, 0xcf800000, v7 -; GISEL-NEXT: v_cvt_u32_f32_e32 v9, v4 -; GISEL-NEXT: v_cvt_u32_f32_e32 v12, v7 -; GISEL-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v10, v9, 0 -; GISEL-NEXT: v_mad_u64_u32 v[7:8], s[4:5], v10, v12, v[5:6] -; GISEL-NEXT: v_mul_lo_u32 v5, v12, v4 -; GISEL-NEXT: v_mul_hi_u32 v13, v9, v4 -; GISEL-NEXT: v_mad_u64_u32 v[7:8], s[4:5], v11, v9, v[7:8] -; GISEL-NEXT: v_mul_hi_u32 v4, v12, v4 -; GISEL-NEXT: v_mul_lo_u32 v8, v9, v7 -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v8 -; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v13 -; GISEL-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc -; GISEL-NEXT: v_mul_lo_u32 v13, v12, v7 -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v8, v5 -; GISEL-NEXT: v_mul_hi_u32 v8, v9, v7 -; GISEL-NEXT: v_add_i32_e32 v4, vcc, v13, v4 -; GISEL-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v4, vcc, v4, v8 -; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v8, vcc, v13, v8 -; GISEL-NEXT: v_mul_hi_u32 v7, v12, v7 -; GISEL-NEXT: v_add_i32_e32 v4, vcc, v4, v5 +; GISEL-NEXT: v_mul_f32_e32 v5, 0x5f7ffffc, v5 +; GISEL-NEXT: v_mul_f32_e32 v7, 0x2f800000, v5 +; GISEL-NEXT: v_trunc_f32_e32 v9, v7 +; GISEL-NEXT: v_mac_f32_e32 v5, 0xcf800000, v9 +; GISEL-NEXT: v_cvt_u32_f32_e32 v10, v5 +; GISEL-NEXT: v_cvt_u32_f32_e32 v13, v9 +; GISEL-NEXT: v_mad_u64_u32 v[7:8], s[4:5], v11, v10, 0 +; GISEL-NEXT: v_mov_b32_e32 v5, v8 +; GISEL-NEXT: v_mad_u64_u32 v[8:9], s[4:5], v11, v13, v[5:6] +; GISEL-NEXT: v_mul_lo_u32 v5, v13, v7 +; GISEL-NEXT: v_mul_hi_u32 v14, v10, v7 +; GISEL-NEXT: v_mad_u64_u32 v[8:9], s[4:5], v12, v10, v[8:9] +; GISEL-NEXT: v_mul_hi_u32 v7, v13, v7 +; GISEL-NEXT: v_mul_lo_u32 v9, v10, v8 +; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v9 +; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v14 ; GISEL-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v8, v5 +; GISEL-NEXT: v_mul_lo_u32 v14, v13, v8 +; GISEL-NEXT: v_add_i32_e32 v5, vcc, v9, v5 +; GISEL-NEXT: v_mul_hi_u32 v9, v10, v8 +; GISEL-NEXT: v_add_i32_e32 v7, vcc, v14, v7 +; GISEL-NEXT: v_cndmask_b32_e64 v14, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v7, vcc, v7, v9 +; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v9, vcc, v14, v9 +; GISEL-NEXT: v_mul_hi_u32 v8, v13, v8 ; GISEL-NEXT: v_add_i32_e32 v5, vcc, v7, v5 -; GISEL-NEXT: v_add_i32_e32 v9, vcc, v9, v4 -; GISEL-NEXT: v_addc_u32_e32 v12, vcc, v12, v5, vcc -; GISEL-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v10, v9, 0 -; GISEL-NEXT: v_mad_u64_u32 v[7:8], s[4:5], v10, v12, v[5:6] -; GISEL-NEXT: v_mul_lo_u32 v5, v12, v4 -; GISEL-NEXT: v_add_i32_e32 v10, vcc, 0, v0 -; GISEL-NEXT: v_mad_u64_u32 v[7:8], s[4:5], v11, v9, v[7:8] -; GISEL-NEXT: v_mul_hi_u32 v0, v9, v4 -; GISEL-NEXT: v_addc_u32_e64 v11, s[4:5], 0, 0, vcc -; GISEL-NEXT: v_mul_lo_u32 v8, v9, v7 -; GISEL-NEXT: v_mul_hi_u32 v4, v12, v4 -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v8 -; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v7, vcc, v9, v7 +; GISEL-NEXT: v_add_i32_e32 v7, vcc, v8, v7 +; GISEL-NEXT: v_add_i32_e32 v10, vcc, v10, v5 +; GISEL-NEXT: v_addc_u32_e32 v13, vcc, v13, v7, vcc +; GISEL-NEXT: v_mad_u64_u32 v[7:8], s[4:5], v11, v10, 0 +; GISEL-NEXT: v_mov_b32_e32 v5, v8 +; GISEL-NEXT: v_mad_u64_u32 v[8:9], s[4:5], v11, v13, v[5:6] +; GISEL-NEXT: v_mul_lo_u32 v5, v13, v7 +; GISEL-NEXT: v_add_i32_e32 v11, vcc, 0, v0 +; GISEL-NEXT: v_mad_u64_u32 v[8:9], s[4:5], v12, v10, v[8:9] +; GISEL-NEXT: v_mul_hi_u32 v0, v10, v7 +; GISEL-NEXT: v_mul_hi_u32 v7, v13, v7 +; GISEL-NEXT: v_mul_lo_u32 v9, v10, v8 +; GISEL-NEXT: v_and_b32_e32 v12, 0xffffff, v2 +; GISEL-NEXT: v_and_b32_e32 v2, 0xffffff, v6 +; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v9 +; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc ; GISEL-NEXT: v_add_i32_e32 v0, vcc, v5, v0 ; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc -; GISEL-NEXT: v_mul_lo_u32 v5, v12, v7 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v8, v0 -; GISEL-NEXT: v_mul_hi_u32 v8, v9, v7 -; GISEL-NEXT: v_add_i32_e32 v4, vcc, v5, v4 -; GISEL-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v4, vcc, v4, v8 -; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v8 -; GISEL-NEXT: v_mul_hi_u32 v7, v12, v7 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v4, v0 -; GISEL-NEXT: v_cndmask_b32_e64 v4, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v4, vcc, v5, v4 -; GISEL-NEXT: v_add_i32_e32 v4, vcc, v7, v4 +; GISEL-NEXT: v_mul_lo_u32 v5, v13, v8 ; GISEL-NEXT: v_add_i32_e32 v0, vcc, v9, v0 -; GISEL-NEXT: v_addc_u32_e32 v4, vcc, v12, v4, vcc -; GISEL-NEXT: v_mul_lo_u32 v5, v11, v0 -; GISEL-NEXT: v_mul_lo_u32 v7, v10, v4 -; GISEL-NEXT: v_mul_hi_u32 v8, v10, v0 -; GISEL-NEXT: v_mul_hi_u32 v0, v11, v0 -; GISEL-NEXT: v_and_b32_e32 v12, 0xffffff, v2 +; GISEL-NEXT: v_mul_hi_u32 v9, v10, v8 ; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v7 ; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v8 +; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v9 +; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v7, vcc, v7, v9 +; GISEL-NEXT: v_mul_hi_u32 v8, v13, v8 +; GISEL-NEXT: v_add_i32_e32 v0, vcc, v5, v0 ; GISEL-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc -; GISEL-NEXT: v_mul_lo_u32 v8, v11, v4 ; GISEL-NEXT: v_add_i32_e32 v5, vcc, v7, v5 -; GISEL-NEXT: v_mul_hi_u32 v7, v10, v4 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v8, v0 +; GISEL-NEXT: v_add_i32_e32 v5, vcc, v8, v5 +; GISEL-NEXT: v_add_i32_e32 v0, vcc, v10, v0 +; GISEL-NEXT: v_addc_u32_e32 v5, vcc, v13, v5, vcc +; GISEL-NEXT: v_mul_lo_u32 v7, v3, v0 +; GISEL-NEXT: v_mul_lo_u32 v8, v11, v5 +; GISEL-NEXT: v_mul_hi_u32 v9, v11, v0 +; GISEL-NEXT: v_mul_hi_u32 v0, v3, v0 +; GISEL-NEXT: v_add_i32_e32 v7, vcc, v7, v8 ; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v7 +; GISEL-NEXT: v_add_i32_e32 v7, vcc, v7, v9 ; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc +; GISEL-NEXT: v_mul_lo_u32 v9, v3, v5 ; GISEL-NEXT: v_add_i32_e32 v7, vcc, v8, v7 -; GISEL-NEXT: v_add_i32_e32 v9, vcc, v0, v5 -; GISEL-NEXT: v_mul_hi_u32 v8, v11, v4 -; GISEL-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v3, v9, 0 +; GISEL-NEXT: v_mul_hi_u32 v8, v11, v5 +; GISEL-NEXT: v_add_i32_e32 v0, vcc, v9, v0 +; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v8 +; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v9, vcc, v9, v8 +; GISEL-NEXT: v_add_i32_e32 v10, vcc, v0, v7 +; GISEL-NEXT: v_mul_hi_u32 v5, v3, v5 +; GISEL-NEXT: v_mad_u64_u32 v[7:8], s[4:5], v1, v10, 0 ; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v7, v0 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v8, v0 -; GISEL-NEXT: v_mad_u64_u32 v[7:8], s[4:5], v3, v0, v[5:6] -; GISEL-NEXT: v_and_b32_e32 v2, 0xffffff, v6 -; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v1, v9, v[7:8] -; GISEL-NEXT: v_sub_i32_e32 v6, vcc, v10, v4 -; GISEL-NEXT: v_subb_u32_e64 v7, s[4:5], v11, v5, vcc -; GISEL-NEXT: v_sub_i32_e64 v5, s[4:5], v11, v5 -; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v7, v1 +; GISEL-NEXT: v_add_i32_e32 v0, vcc, v9, v0 +; GISEL-NEXT: v_add_i32_e32 v0, vcc, v5, v0 +; GISEL-NEXT: v_mov_b32_e32 v5, v8 +; GISEL-NEXT: v_mad_u64_u32 v[8:9], s[4:5], v1, v0, v[5:6] +; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v3, v10, v[8:9] +; GISEL-NEXT: v_sub_i32_e32 v6, vcc, v11, v7 +; GISEL-NEXT: v_subb_u32_e64 v7, s[4:5], v3, v5, vcc +; GISEL-NEXT: v_sub_i32_e64 v5, s[4:5], v3, v5 +; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v7, v3 ; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, -1, s[4:5] -; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v6, v3 -; GISEL-NEXT: v_cndmask_b32_e64 v10, 0, -1, s[4:5] -; GISEL-NEXT: v_add_i32_e64 v4, s[4:5], 0, v2 -; GISEL-NEXT: v_addc_u32_e64 v2, s[4:5], 0, 0, s[4:5] -; GISEL-NEXT: v_cvt_f32_u32_e32 v11, v4 -; GISEL-NEXT: v_cvt_f32_u32_e32 v13, v2 -; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], v7, v1 -; GISEL-NEXT: v_subb_u32_e32 v5, vcc, v5, v1, vcc -; GISEL-NEXT: v_mac_f32_e32 v11, 0x4f800000, v13 -; GISEL-NEXT: v_rcp_iflag_f32_e32 v7, v11 -; GISEL-NEXT: v_cndmask_b32_e64 v8, v8, v10, s[4:5] -; GISEL-NEXT: v_sub_i32_e32 v10, vcc, v6, v3 -; GISEL-NEXT: v_subbrev_u32_e32 v11, vcc, 0, v5, vcc -; GISEL-NEXT: v_mul_f32_e32 v5, 0x5f7ffffc, v7 -; GISEL-NEXT: v_mul_f32_e32 v6, 0x2f800000, v5 -; GISEL-NEXT: v_trunc_f32_e32 v6, v6 -; GISEL-NEXT: v_mac_f32_e32 v5, 0xcf800000, v6 +; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v6, v1 +; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, -1, s[4:5] +; GISEL-NEXT: v_add_i32_e64 v2, s[4:5], 0, v2 +; GISEL-NEXT: v_cvt_f32_u32_e32 v11, v2 +; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], v7, v3 +; GISEL-NEXT: v_subb_u32_e32 v5, vcc, v5, v3, vcc +; GISEL-NEXT: v_mac_f32_e32 v11, 0x4f800000, v4 +; GISEL-NEXT: v_rcp_iflag_f32_e32 v4, v11 +; GISEL-NEXT: v_cndmask_b32_e64 v7, v8, v9, s[4:5] +; GISEL-NEXT: v_sub_i32_e32 v8, vcc, v6, v1 +; GISEL-NEXT: v_mul_f32_e32 v4, 0x5f7ffffc, v4 +; GISEL-NEXT: v_subbrev_u32_e32 v9, vcc, 0, v5, vcc +; GISEL-NEXT: v_mul_f32_e32 v5, 0x2f800000, v4 +; GISEL-NEXT: v_trunc_f32_e32 v5, v5 +; GISEL-NEXT: v_mac_f32_e32 v4, 0xcf800000, v5 +; GISEL-NEXT: v_cvt_u32_f32_e32 v11, v4 +; GISEL-NEXT: v_sub_i32_e32 v14, vcc, 0, v2 ; GISEL-NEXT: v_cvt_u32_f32_e32 v13, v5 -; GISEL-NEXT: v_sub_i32_e32 v15, vcc, 0, v4 -; GISEL-NEXT: v_cvt_u32_f32_e32 v14, v6 -; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v15, v13, 0 -; GISEL-NEXT: v_subb_u32_e32 v16, vcc, 0, v2, vcc -; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[4:5], v15, v14, v[6:7] -; GISEL-NEXT: v_add_i32_e32 v17, vcc, 1, v9 -; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[4:5], v16, v13, v[6:7] -; GISEL-NEXT: v_addc_u32_e32 v18, vcc, 0, v0, vcc -; GISEL-NEXT: v_cmp_ge_u32_e32 vcc, v11, v1 -; GISEL-NEXT: v_cndmask_b32_e64 v19, 0, -1, vcc -; GISEL-NEXT: v_cmp_ge_u32_e32 vcc, v10, v3 -; GISEL-NEXT: v_mul_lo_u32 v7, v14, v5 -; GISEL-NEXT: v_mul_lo_u32 v10, v13, v6 -; GISEL-NEXT: v_cndmask_b32_e64 v3, 0, -1, vcc -; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, v11, v1 -; GISEL-NEXT: v_mul_hi_u32 v1, v13, v5 -; GISEL-NEXT: v_cndmask_b32_e32 v3, v19, v3, vcc -; GISEL-NEXT: v_add_i32_e32 v7, vcc, v7, v10 -; GISEL-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v1, vcc, v7, v1 +; GISEL-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v14, v11, 0 +; GISEL-NEXT: v_subb_u32_e32 v15, vcc, 0, v3, vcc +; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v14, v13, v[5:6] +; GISEL-NEXT: v_add_i32_e32 v16, vcc, 1, v10 +; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v15, v11, v[5:6] +; GISEL-NEXT: v_addc_u32_e32 v17, vcc, 0, v0, vcc +; GISEL-NEXT: v_cmp_ge_u32_e32 vcc, v9, v3 +; GISEL-NEXT: v_cndmask_b32_e64 v18, 0, -1, vcc +; GISEL-NEXT: v_cmp_ge_u32_e32 vcc, v8, v1 +; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, -1, vcc +; GISEL-NEXT: v_mul_lo_u32 v6, v13, v4 +; GISEL-NEXT: v_mul_lo_u32 v8, v11, v5 +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, v9, v3 +; GISEL-NEXT: v_cndmask_b32_e32 v9, v18, v1, vcc +; GISEL-NEXT: v_mul_hi_u32 v1, v11, v4 +; GISEL-NEXT: v_add_i32_e32 v6, vcc, v6, v8 +; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v1, vcc, v6, v1 ; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc -; GISEL-NEXT: v_mul_lo_u32 v7, v14, v6 -; GISEL-NEXT: v_mul_hi_u32 v5, v14, v5 -; GISEL-NEXT: v_add_i32_e32 v1, vcc, v10, v1 -; GISEL-NEXT: v_mul_hi_u32 v10, v13, v6 -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v7, v5 -; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v10 -; GISEL-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v7, vcc, v7, v10 -; GISEL-NEXT: v_mul_hi_u32 v6, v14, v6 -; GISEL-NEXT: v_add_i32_e32 v1, vcc, v5, v1 -; GISEL-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v7, v5 -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v6, v5 -; GISEL-NEXT: v_add_i32_e32 v10, vcc, v13, v1 -; GISEL-NEXT: v_addc_u32_e32 v11, vcc, v14, v5, vcc -; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v15, v10, 0 -; GISEL-NEXT: v_add_i32_e32 v13, vcc, 1, v17 -; GISEL-NEXT: v_mov_b32_e32 v1, v6 -; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[4:5], v15, v11, v[1:2] -; GISEL-NEXT: v_addc_u32_e32 v14, vcc, 0, v18, vcc -; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[4:5], v16, v10, v[6:7] -; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v3 -; GISEL-NEXT: v_cndmask_b32_e32 v1, v17, v13, vcc -; GISEL-NEXT: v_cndmask_b32_e32 v3, v18, v14, vcc -; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8 -; GISEL-NEXT: v_mul_lo_u32 v7, v11, v5 -; GISEL-NEXT: v_mul_lo_u32 v8, v10, v6 -; GISEL-NEXT: v_mul_hi_u32 v13, v10, v5 -; GISEL-NEXT: v_cndmask_b32_e32 v1, v9, v1, vcc -; GISEL-NEXT: v_add_i32_e64 v9, s[4:5], 0, v12 -; GISEL-NEXT: v_addc_u32_e64 v12, s[4:5], 0, 0, s[4:5] -; GISEL-NEXT: v_add_i32_e64 v7, s[4:5], v7, v8 -; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, s[4:5] -; GISEL-NEXT: v_add_i32_e64 v7, s[4:5], v7, v13 +; GISEL-NEXT: v_mul_lo_u32 v6, v13, v5 +; GISEL-NEXT: v_mul_hi_u32 v4, v13, v4 +; GISEL-NEXT: v_add_i32_e32 v1, vcc, v8, v1 +; GISEL-NEXT: v_mul_hi_u32 v8, v11, v5 +; GISEL-NEXT: v_add_i32_e32 v4, vcc, v6, v4 +; GISEL-NEXT: v_cndmask_b32_e64 v6, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v4, vcc, v4, v8 +; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v6, vcc, v6, v8 +; GISEL-NEXT: v_mul_hi_u32 v5, v13, v5 +; GISEL-NEXT: v_add_i32_e32 v1, vcc, v4, v1 +; GISEL-NEXT: v_cndmask_b32_e64 v4, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v4, vcc, v6, v4 +; GISEL-NEXT: v_add_i32_e32 v4, vcc, v5, v4 +; GISEL-NEXT: v_add_i32_e32 v8, vcc, v11, v1 +; GISEL-NEXT: v_addc_u32_e32 v11, vcc, v13, v4, vcc +; GISEL-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v14, v8, 0 +; GISEL-NEXT: v_add_i32_e32 v13, vcc, 1, v16 +; GISEL-NEXT: v_mov_b32_e32 v1, v5 +; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v14, v11, v[1:2] +; GISEL-NEXT: v_addc_u32_e32 v18, vcc, 0, v17, vcc +; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v15, v8, v[5:6] +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v9 +; GISEL-NEXT: v_cndmask_b32_e32 v1, v16, v13, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v9, v17, v18, vcc +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7 +; GISEL-NEXT: v_mul_lo_u32 v6, v11, v4 +; GISEL-NEXT: v_mul_lo_u32 v7, v8, v5 +; GISEL-NEXT: v_cndmask_b32_e32 v1, v10, v1, vcc +; GISEL-NEXT: v_add_i32_e64 v10, s[4:5], 0, v12 +; GISEL-NEXT: v_mul_hi_u32 v12, v8, v4 +; GISEL-NEXT: v_add_i32_e64 v6, s[4:5], v6, v7 ; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, s[4:5] -; GISEL-NEXT: v_mul_lo_u32 v13, v11, v6 -; GISEL-NEXT: v_mul_hi_u32 v5, v11, v5 -; GISEL-NEXT: v_add_i32_e64 v7, s[4:5], v8, v7 -; GISEL-NEXT: v_mul_hi_u32 v8, v10, v6 -; GISEL-NEXT: v_add_i32_e64 v5, s[4:5], v13, v5 -; GISEL-NEXT: v_cndmask_b32_e64 v13, 0, 1, s[4:5] -; GISEL-NEXT: v_add_i32_e64 v5, s[4:5], v5, v8 -; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, s[4:5] -; GISEL-NEXT: v_add_i32_e64 v8, s[4:5], v13, v8 -; GISEL-NEXT: v_mul_hi_u32 v6, v11, v6 -; GISEL-NEXT: v_add_i32_e64 v5, s[4:5], v5, v7 +; GISEL-NEXT: v_add_i32_e64 v6, s[4:5], v6, v12 +; GISEL-NEXT: v_cndmask_b32_e64 v6, 0, 1, s[4:5] +; GISEL-NEXT: v_mul_lo_u32 v12, v11, v5 +; GISEL-NEXT: v_mul_hi_u32 v4, v11, v4 +; GISEL-NEXT: v_add_i32_e64 v6, s[4:5], v7, v6 +; GISEL-NEXT: v_mul_hi_u32 v7, v8, v5 +; GISEL-NEXT: v_add_i32_e64 v4, s[4:5], v12, v4 +; GISEL-NEXT: v_cndmask_b32_e64 v12, 0, 1, s[4:5] +; GISEL-NEXT: v_add_i32_e64 v4, s[4:5], v4, v7 ; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, s[4:5] -; GISEL-NEXT: v_add_i32_e64 v7, s[4:5], v8, v7 -; GISEL-NEXT: v_add_i32_e64 v6, s[4:5], v6, v7 -; GISEL-NEXT: v_add_i32_e64 v5, s[4:5], v10, v5 -; GISEL-NEXT: v_addc_u32_e64 v6, s[4:5], v11, v6, s[4:5] -; GISEL-NEXT: v_mul_lo_u32 v7, v12, v5 -; GISEL-NEXT: v_mul_lo_u32 v8, v9, v6 -; GISEL-NEXT: v_cndmask_b32_e32 v3, v0, v3, vcc -; GISEL-NEXT: v_mul_hi_u32 v0, v9, v5 -; GISEL-NEXT: v_mul_hi_u32 v5, v12, v5 -; GISEL-NEXT: v_add_i32_e32 v7, vcc, v7, v8 -; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v7, v0 -; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc -; GISEL-NEXT: v_mul_lo_u32 v7, v12, v6 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v8, v0 -; GISEL-NEXT: v_mul_hi_u32 v8, v9, v6 -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v7, v5 +; GISEL-NEXT: v_add_i32_e64 v7, s[4:5], v12, v7 +; GISEL-NEXT: v_mul_hi_u32 v5, v11, v5 +; GISEL-NEXT: v_add_i32_e64 v4, s[4:5], v4, v6 +; GISEL-NEXT: v_cndmask_b32_e64 v6, 0, 1, s[4:5] +; GISEL-NEXT: v_add_i32_e64 v6, s[4:5], v7, v6 +; GISEL-NEXT: v_add_i32_e64 v5, s[4:5], v5, v6 +; GISEL-NEXT: v_add_i32_e64 v4, s[4:5], v8, v4 +; GISEL-NEXT: v_addc_u32_e64 v5, s[4:5], v11, v5, s[4:5] +; GISEL-NEXT: v_mul_lo_u32 v6, v3, v4 +; GISEL-NEXT: v_mul_lo_u32 v7, v10, v5 +; GISEL-NEXT: v_cndmask_b32_e32 v8, v0, v9, vcc +; GISEL-NEXT: v_mul_hi_u32 v0, v10, v4 +; GISEL-NEXT: v_mul_hi_u32 v4, v3, v4 +; GISEL-NEXT: v_add_i32_e32 v6, vcc, v6, v7 ; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v8 -; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v7, vcc, v7, v8 -; GISEL-NEXT: v_add_i32_e32 v8, vcc, v5, v0 -; GISEL-NEXT: v_mul_hi_u32 v10, v12, v6 -; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v4, v8, 0 +; GISEL-NEXT: v_add_i32_e32 v0, vcc, v6, v0 ; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; GISEL-NEXT: v_mul_lo_u32 v6, v3, v5 ; GISEL-NEXT: v_add_i32_e32 v0, vcc, v7, v0 -; GISEL-NEXT: v_add_i32_e32 v10, vcc, v10, v0 -; GISEL-NEXT: v_mov_b32_e32 v0, v6 -; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[4:5], v4, v10, v[0:1] +; GISEL-NEXT: v_mul_hi_u32 v7, v10, v5 +; GISEL-NEXT: v_add_i32_e32 v4, vcc, v6, v4 +; GISEL-NEXT: v_cndmask_b32_e64 v6, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v4, vcc, v4, v7 +; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v6, vcc, v6, v7 +; GISEL-NEXT: v_add_i32_e32 v7, vcc, v4, v0 +; GISEL-NEXT: v_mul_hi_u32 v9, v3, v5 +; GISEL-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v2, v7, 0 +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v0, vcc, v6, v0 +; GISEL-NEXT: v_add_i32_e32 v9, vcc, v9, v0 +; GISEL-NEXT: v_mov_b32_e32 v0, v5 +; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v2, v9, v[0:1] ; GISEL-NEXT: v_subrev_i32_e32 v0, vcc, 0, v1 -; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[4:5], v2, v8, v[6:7] -; GISEL-NEXT: v_subbrev_u32_e32 v1, vcc, 0, v3, vcc -; GISEL-NEXT: v_sub_i32_e32 v3, vcc, v9, v5 -; GISEL-NEXT: v_subb_u32_e64 v5, s[4:5], v12, v6, vcc -; GISEL-NEXT: v_sub_i32_e64 v6, s[4:5], v12, v6 -; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v5, v2 -; GISEL-NEXT: v_subb_u32_e32 v6, vcc, v6, v2, vcc -; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, -1, s[4:5] -; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v3, v4 -; GISEL-NEXT: v_sub_i32_e32 v3, vcc, v3, v4 -; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, -1, s[4:5] -; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], v5, v2 -; GISEL-NEXT: v_subbrev_u32_e32 v6, vcc, 0, v6, vcc -; GISEL-NEXT: v_cndmask_b32_e64 v5, v7, v9, s[4:5] -; GISEL-NEXT: v_add_i32_e32 v7, vcc, 1, v8 -; GISEL-NEXT: v_addc_u32_e32 v9, vcc, 0, v10, vcc -; GISEL-NEXT: v_cmp_ge_u32_e32 vcc, v6, v2 +; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v3, v7, v[5:6] +; GISEL-NEXT: v_subbrev_u32_e32 v1, vcc, 0, v8, vcc +; GISEL-NEXT: v_sub_i32_e32 v4, vcc, v10, v4 +; GISEL-NEXT: v_subb_u32_e64 v6, s[4:5], v3, v5, vcc +; GISEL-NEXT: v_sub_i32_e64 v5, s[4:5], v3, v5 +; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v6, v3 +; GISEL-NEXT: v_subb_u32_e32 v5, vcc, v5, v3, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, -1, s[4:5] +; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v4, v2 +; GISEL-NEXT: v_sub_i32_e32 v4, vcc, v4, v2 +; GISEL-NEXT: v_cndmask_b32_e64 v10, 0, -1, s[4:5] +; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], v6, v3 +; GISEL-NEXT: v_subbrev_u32_e32 v5, vcc, 0, v5, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v6, v8, v10, s[4:5] +; GISEL-NEXT: v_add_i32_e32 v8, vcc, 1, v7 +; GISEL-NEXT: v_addc_u32_e32 v10, vcc, 0, v9, vcc +; GISEL-NEXT: v_cmp_ge_u32_e32 vcc, v5, v3 ; GISEL-NEXT: v_cndmask_b32_e64 v11, 0, -1, vcc -; GISEL-NEXT: v_cmp_ge_u32_e32 vcc, v3, v4 -; GISEL-NEXT: v_cndmask_b32_e64 v3, 0, -1, vcc -; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, v6, v2 -; GISEL-NEXT: v_cndmask_b32_e32 v2, v11, v3, vcc -; GISEL-NEXT: v_add_i32_e32 v3, vcc, 1, v7 -; GISEL-NEXT: v_addc_u32_e32 v4, vcc, 0, v9, vcc +; GISEL-NEXT: v_cmp_ge_u32_e32 vcc, v4, v2 +; GISEL-NEXT: v_cndmask_b32_e64 v2, 0, -1, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, v5, v3 +; GISEL-NEXT: v_cndmask_b32_e32 v2, v11, v2, vcc +; GISEL-NEXT: v_add_i32_e32 v3, vcc, 1, v8 +; GISEL-NEXT: v_addc_u32_e32 v4, vcc, 0, v10, vcc ; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v2 -; GISEL-NEXT: v_cndmask_b32_e32 v2, v7, v3, vcc -; GISEL-NEXT: v_cndmask_b32_e32 v3, v9, v4, vcc -; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v5 -; GISEL-NEXT: v_cndmask_b32_e32 v2, v8, v2, vcc -; GISEL-NEXT: v_cndmask_b32_e32 v3, v10, v3, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v2, v8, v3, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v3, v10, v4, vcc +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v6 +; GISEL-NEXT: v_cndmask_b32_e32 v2, v7, v2, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v3, v9, v3, vcc ; GISEL-NEXT: v_subrev_i32_e32 v2, vcc, 0, v2 ; GISEL-NEXT: v_subbrev_u32_e32 v3, vcc, 0, v3, vcc ; GISEL-NEXT: s_setpc_b64 s[30:31] @@ -3399,3 +2841,24 @@ define <2 x i64> @v_sdiv_v2i64_24bit(<2 x i64> %num, <2 x i64> %den) { %result = sdiv <2 x i64> %num.mask, %den.mask ret <2 x i64> %result } + +define i64 @v_sdiv_i64_exact(i64 %num) { +; CHECK-LABEL: v_sdiv_i64_exact: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_ashr_i64 v[0:1], v[0:1], 12 +; CHECK-NEXT: s_setpc_b64 s[30:31] + %result = sdiv exact i64 %num, 4096 + ret i64 %result +} + +define <2 x i64> @v_sdiv_v2i64_exact(<2 x i64> %num) { +; CHECK-LABEL: v_sdiv_v2i64_exact: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_ashr_i64 v[0:1], v[0:1], 12 +; CHECK-NEXT: v_ashr_i64 v[2:3], v[2:3], 10 +; CHECK-NEXT: s_setpc_b64 s[30:31] + %result = sdiv exact <2 x i64> %num, <i64 4096, i64 1024> + ret <2 x i64> %result +} diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/srem.i64.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/srem.i64.ll index c455b24313ddc277fbcb9a423e4f91f48b4ea48d..83ebc84e1f84a21e22674a2c8aaeaca37a897da2 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/srem.i64.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/srem.i64.ll @@ -3034,253 +3034,251 @@ define <2 x i64> @v_srem_v2i64_24bit(<2 x i64> %num, <2 x i64> %den) { ; GISEL: ; %bb.0: ; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GISEL-NEXT: v_and_b32_e32 v1, 0xffffff, v4 +; GISEL-NEXT: v_add_i32_e64 v3, s[4:5], 0, 0 ; GISEL-NEXT: v_add_i32_e32 v1, vcc, 0, v1 -; GISEL-NEXT: v_addc_u32_e64 v3, s[4:5], 0, 0, vcc -; GISEL-NEXT: v_cvt_f32_u32_e32 v4, v1 -; GISEL-NEXT: v_cvt_f32_u32_e32 v5, v3 -; GISEL-NEXT: v_sub_i32_e32 v10, vcc, 0, v1 -; GISEL-NEXT: v_subb_u32_e32 v11, vcc, 0, v3, vcc -; GISEL-NEXT: v_mac_f32_e32 v4, 0x4f800000, v5 -; GISEL-NEXT: v_rcp_iflag_f32_e32 v4, v4 +; GISEL-NEXT: v_cvt_f32_u32_e32 v5, v1 +; GISEL-NEXT: v_cvt_f32_u32_e32 v4, v3 +; GISEL-NEXT: v_sub_i32_e32 v11, vcc, 0, v1 +; GISEL-NEXT: v_subb_u32_e32 v12, vcc, 0, v3, vcc +; GISEL-NEXT: v_mac_f32_e32 v5, 0x4f800000, v4 +; GISEL-NEXT: v_rcp_iflag_f32_e32 v5, v5 ; GISEL-NEXT: v_and_b32_e32 v0, 0xffffff, v0 -; GISEL-NEXT: v_mul_f32_e32 v4, 0x5f7ffffc, v4 -; GISEL-NEXT: v_mul_f32_e32 v5, 0x2f800000, v4 -; GISEL-NEXT: v_trunc_f32_e32 v7, v5 -; GISEL-NEXT: v_mac_f32_e32 v4, 0xcf800000, v7 -; GISEL-NEXT: v_cvt_u32_f32_e32 v9, v4 -; GISEL-NEXT: v_cvt_u32_f32_e32 v12, v7 -; GISEL-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v10, v9, 0 -; GISEL-NEXT: v_mad_u64_u32 v[7:8], s[4:5], v10, v12, v[5:6] -; GISEL-NEXT: v_mul_lo_u32 v5, v12, v4 -; GISEL-NEXT: v_mul_hi_u32 v13, v9, v4 -; GISEL-NEXT: v_mad_u64_u32 v[7:8], s[4:5], v11, v9, v[7:8] -; GISEL-NEXT: v_mul_hi_u32 v4, v12, v4 -; GISEL-NEXT: v_mul_lo_u32 v8, v9, v7 -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v8 -; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v13 -; GISEL-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc -; GISEL-NEXT: v_mul_lo_u32 v13, v12, v7 -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v8, v5 -; GISEL-NEXT: v_mul_hi_u32 v8, v9, v7 -; GISEL-NEXT: v_add_i32_e32 v4, vcc, v13, v4 -; GISEL-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v4, vcc, v4, v8 -; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v8, vcc, v13, v8 -; GISEL-NEXT: v_mul_hi_u32 v7, v12, v7 -; GISEL-NEXT: v_add_i32_e32 v4, vcc, v4, v5 +; GISEL-NEXT: v_mul_f32_e32 v5, 0x5f7ffffc, v5 +; GISEL-NEXT: v_mul_f32_e32 v7, 0x2f800000, v5 +; GISEL-NEXT: v_trunc_f32_e32 v9, v7 +; GISEL-NEXT: v_mac_f32_e32 v5, 0xcf800000, v9 +; GISEL-NEXT: v_cvt_u32_f32_e32 v10, v5 +; GISEL-NEXT: v_cvt_u32_f32_e32 v13, v9 +; GISEL-NEXT: v_mad_u64_u32 v[7:8], s[4:5], v11, v10, 0 +; GISEL-NEXT: v_mov_b32_e32 v5, v8 +; GISEL-NEXT: v_mad_u64_u32 v[8:9], s[4:5], v11, v13, v[5:6] +; GISEL-NEXT: v_mul_lo_u32 v5, v13, v7 +; GISEL-NEXT: v_mul_hi_u32 v14, v10, v7 +; GISEL-NEXT: v_mad_u64_u32 v[8:9], s[4:5], v12, v10, v[8:9] +; GISEL-NEXT: v_mul_hi_u32 v7, v13, v7 +; GISEL-NEXT: v_mul_lo_u32 v9, v10, v8 +; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v9 +; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v14 ; GISEL-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v8, v5 +; GISEL-NEXT: v_mul_lo_u32 v14, v13, v8 +; GISEL-NEXT: v_add_i32_e32 v5, vcc, v9, v5 +; GISEL-NEXT: v_mul_hi_u32 v9, v10, v8 +; GISEL-NEXT: v_add_i32_e32 v7, vcc, v14, v7 +; GISEL-NEXT: v_cndmask_b32_e64 v14, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v7, vcc, v7, v9 +; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v9, vcc, v14, v9 +; GISEL-NEXT: v_mul_hi_u32 v8, v13, v8 ; GISEL-NEXT: v_add_i32_e32 v5, vcc, v7, v5 -; GISEL-NEXT: v_add_i32_e32 v9, vcc, v9, v4 -; GISEL-NEXT: v_addc_u32_e32 v12, vcc, v12, v5, vcc -; GISEL-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v10, v9, 0 -; GISEL-NEXT: v_mad_u64_u32 v[7:8], s[4:5], v10, v12, v[5:6] -; GISEL-NEXT: v_mul_lo_u32 v5, v12, v4 -; GISEL-NEXT: v_add_i32_e32 v10, vcc, 0, v0 -; GISEL-NEXT: v_mad_u64_u32 v[7:8], s[4:5], v11, v9, v[7:8] -; GISEL-NEXT: v_mul_hi_u32 v0, v9, v4 -; GISEL-NEXT: v_addc_u32_e64 v11, s[4:5], 0, 0, vcc -; GISEL-NEXT: v_mul_lo_u32 v8, v9, v7 -; GISEL-NEXT: v_mul_hi_u32 v4, v12, v4 -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v8 -; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v7, vcc, v9, v7 +; GISEL-NEXT: v_add_i32_e32 v7, vcc, v8, v7 +; GISEL-NEXT: v_add_i32_e32 v10, vcc, v10, v5 +; GISEL-NEXT: v_addc_u32_e32 v13, vcc, v13, v7, vcc +; GISEL-NEXT: v_mad_u64_u32 v[7:8], s[4:5], v11, v10, 0 +; GISEL-NEXT: v_mov_b32_e32 v5, v8 +; GISEL-NEXT: v_mad_u64_u32 v[8:9], s[4:5], v11, v13, v[5:6] +; GISEL-NEXT: v_mul_lo_u32 v5, v13, v7 +; GISEL-NEXT: v_add_i32_e32 v11, vcc, 0, v0 +; GISEL-NEXT: v_mad_u64_u32 v[8:9], s[4:5], v12, v10, v[8:9] +; GISEL-NEXT: v_mul_hi_u32 v0, v10, v7 +; GISEL-NEXT: v_mul_hi_u32 v7, v13, v7 +; GISEL-NEXT: v_mul_lo_u32 v9, v10, v8 +; GISEL-NEXT: v_and_b32_e32 v12, 0xffffff, v2 +; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v9 +; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc ; GISEL-NEXT: v_add_i32_e32 v0, vcc, v5, v0 ; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc -; GISEL-NEXT: v_mul_lo_u32 v5, v12, v7 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v8, v0 -; GISEL-NEXT: v_mul_hi_u32 v8, v9, v7 -; GISEL-NEXT: v_add_i32_e32 v4, vcc, v5, v4 -; GISEL-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v4, vcc, v4, v8 -; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v8 -; GISEL-NEXT: v_mul_hi_u32 v7, v12, v7 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v4, v0 -; GISEL-NEXT: v_cndmask_b32_e64 v4, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v4, vcc, v5, v4 -; GISEL-NEXT: v_add_i32_e32 v4, vcc, v7, v4 +; GISEL-NEXT: v_mul_lo_u32 v5, v13, v8 ; GISEL-NEXT: v_add_i32_e32 v0, vcc, v9, v0 -; GISEL-NEXT: v_addc_u32_e32 v4, vcc, v12, v4, vcc -; GISEL-NEXT: v_mul_lo_u32 v5, v11, v0 -; GISEL-NEXT: v_mul_lo_u32 v7, v10, v4 -; GISEL-NEXT: v_mul_hi_u32 v8, v10, v0 -; GISEL-NEXT: v_mul_hi_u32 v0, v11, v0 -; GISEL-NEXT: v_and_b32_e32 v12, 0xffffff, v2 +; GISEL-NEXT: v_mul_hi_u32 v9, v10, v8 ; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v7 ; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v8 +; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v9 +; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v7, vcc, v7, v9 +; GISEL-NEXT: v_mul_hi_u32 v8, v13, v8 +; GISEL-NEXT: v_add_i32_e32 v0, vcc, v5, v0 ; GISEL-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc -; GISEL-NEXT: v_mul_lo_u32 v8, v11, v4 ; GISEL-NEXT: v_add_i32_e32 v5, vcc, v7, v5 -; GISEL-NEXT: v_mul_hi_u32 v7, v10, v4 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v8, v0 +; GISEL-NEXT: v_add_i32_e32 v5, vcc, v8, v5 +; GISEL-NEXT: v_add_i32_e32 v0, vcc, v10, v0 +; GISEL-NEXT: v_addc_u32_e32 v5, vcc, v13, v5, vcc +; GISEL-NEXT: v_mul_lo_u32 v7, v3, v0 +; GISEL-NEXT: v_mul_lo_u32 v8, v11, v5 +; GISEL-NEXT: v_mul_hi_u32 v9, v11, v0 +; GISEL-NEXT: v_mul_hi_u32 v0, v3, v0 +; GISEL-NEXT: v_add_i32_e32 v7, vcc, v7, v8 ; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v7 +; GISEL-NEXT: v_add_i32_e32 v7, vcc, v7, v9 ; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc +; GISEL-NEXT: v_mul_lo_u32 v9, v3, v5 ; GISEL-NEXT: v_add_i32_e32 v7, vcc, v8, v7 -; GISEL-NEXT: v_add_i32_e32 v9, vcc, v0, v5 -; GISEL-NEXT: v_mul_hi_u32 v8, v11, v4 -; GISEL-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v1, v9, 0 +; GISEL-NEXT: v_mul_hi_u32 v8, v11, v5 +; GISEL-NEXT: v_add_i32_e32 v0, vcc, v9, v0 +; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v8 +; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v9, vcc, v9, v8 +; GISEL-NEXT: v_add_i32_e32 v10, vcc, v0, v7 +; GISEL-NEXT: v_mul_hi_u32 v5, v3, v5 +; GISEL-NEXT: v_mad_u64_u32 v[7:8], s[4:5], v1, v10, 0 ; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v7, v0 -; GISEL-NEXT: v_add_i32_e32 v7, vcc, v8, v0 -; GISEL-NEXT: v_mov_b32_e32 v0, v5 -; GISEL-NEXT: v_mad_u64_u32 v[7:8], s[4:5], v1, v7, v[0:1] +; GISEL-NEXT: v_add_i32_e32 v0, vcc, v9, v0 +; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v0 +; GISEL-NEXT: v_mov_b32_e32 v0, v8 +; GISEL-NEXT: v_mad_u64_u32 v[8:9], s[4:5], v1, v5, v[0:1] ; GISEL-NEXT: v_and_b32_e32 v0, 0xffffff, v6 -; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v3, v9, v[7:8] -; GISEL-NEXT: v_sub_i32_e32 v8, vcc, v10, v4 -; GISEL-NEXT: v_subb_u32_e64 v9, s[4:5], v11, v5, vcc -; GISEL-NEXT: v_sub_i32_e64 v5, s[4:5], v11, v5 -; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v9, v3 +; GISEL-NEXT: v_sub_i32_e32 v7, vcc, v11, v7 +; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v3, v10, v[8:9] +; GISEL-NEXT: v_subb_u32_e64 v8, s[4:5], v3, v5, vcc +; GISEL-NEXT: v_sub_i32_e64 v5, s[4:5], v3, v5 +; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v8, v3 ; GISEL-NEXT: v_cndmask_b32_e64 v6, 0, -1, s[4:5] -; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v8, v1 -; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, -1, s[4:5] +; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v7, v1 +; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, -1, s[4:5] ; GISEL-NEXT: v_add_i32_e64 v2, s[4:5], 0, v0 -; GISEL-NEXT: v_addc_u32_e64 v4, s[4:5], 0, 0, s[4:5] ; GISEL-NEXT: v_cvt_f32_u32_e32 v0, v2 -; GISEL-NEXT: v_cvt_f32_u32_e32 v10, v4 -; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], v9, v3 -; GISEL-NEXT: v_subb_u32_e32 v13, vcc, v5, v3, vcc -; GISEL-NEXT: v_mac_f32_e32 v0, 0x4f800000, v10 +; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], v8, v3 +; GISEL-NEXT: v_cndmask_b32_e64 v9, v6, v9, s[4:5] +; GISEL-NEXT: v_subb_u32_e32 v10, vcc, v5, v3, vcc +; GISEL-NEXT: v_mac_f32_e32 v0, 0x4f800000, v4 ; GISEL-NEXT: v_rcp_iflag_f32_e32 v0, v0 -; GISEL-NEXT: v_cndmask_b32_e64 v11, v6, v7, s[4:5] -; GISEL-NEXT: v_sub_i32_e32 v10, vcc, v8, v1 +; GISEL-NEXT: v_sub_i32_e32 v11, vcc, v7, v1 +; GISEL-NEXT: v_subbrev_u32_e64 v13, s[4:5], 0, v10, vcc ; GISEL-NEXT: v_mul_f32_e32 v0, 0x5f7ffffc, v0 -; GISEL-NEXT: v_mul_f32_e32 v5, 0x2f800000, v0 -; GISEL-NEXT: v_trunc_f32_e32 v7, v5 -; GISEL-NEXT: v_mac_f32_e32 v0, 0xcf800000, v7 -; GISEL-NEXT: v_cvt_u32_f32_e32 v15, v0 -; GISEL-NEXT: v_subbrev_u32_e64 v14, s[4:5], 0, v13, vcc -; GISEL-NEXT: v_sub_i32_e64 v16, s[4:5], 0, v2 -; GISEL-NEXT: v_subb_u32_e64 v17, s[4:5], 0, v4, s[4:5] -; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v16, v15, 0 -; GISEL-NEXT: v_cvt_u32_f32_e32 v18, v7 -; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v14, v3 -; GISEL-NEXT: v_mov_b32_e32 v0, v6 -; GISEL-NEXT: v_cndmask_b32_e64 v19, 0, -1, s[4:5] -; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[4:5], v16, v18, v[0:1] -; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v10, v1 +; GISEL-NEXT: v_mul_f32_e32 v4, 0x2f800000, v0 +; GISEL-NEXT: v_trunc_f32_e32 v6, v4 +; GISEL-NEXT: v_mac_f32_e32 v0, 0xcf800000, v6 +; GISEL-NEXT: v_cvt_u32_f32_e32 v14, v0 +; GISEL-NEXT: v_sub_i32_e64 v15, s[4:5], 0, v2 +; GISEL-NEXT: v_subb_u32_e64 v16, s[4:5], 0, v3, s[4:5] +; GISEL-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v15, v14, 0 +; GISEL-NEXT: v_cvt_u32_f32_e32 v17, v6 +; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v13, v3 +; GISEL-NEXT: v_mov_b32_e32 v0, v5 +; GISEL-NEXT: v_cndmask_b32_e64 v18, 0, -1, s[4:5] +; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v15, v17, v[0:1] +; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v11, v1 ; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, -1, s[4:5] -; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[4:5], v17, v15, v[6:7] -; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], v14, v3 -; GISEL-NEXT: v_cndmask_b32_e64 v7, v19, v0, s[4:5] -; GISEL-NEXT: v_mul_lo_u32 v0, v18, v5 -; GISEL-NEXT: v_mul_lo_u32 v19, v15, v6 -; GISEL-NEXT: v_subb_u32_e32 v3, vcc, v13, v3, vcc -; GISEL-NEXT: v_mul_hi_u32 v13, v15, v5 +; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v16, v14, v[5:6] +; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], v13, v3 +; GISEL-NEXT: v_cndmask_b32_e64 v6, v18, v0, s[4:5] +; GISEL-NEXT: v_mul_lo_u32 v0, v17, v4 +; GISEL-NEXT: v_mul_lo_u32 v18, v14, v5 +; GISEL-NEXT: v_mul_hi_u32 v19, v14, v4 +; GISEL-NEXT: v_subb_u32_e32 v10, vcc, v10, v3, vcc +; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v18 +; GISEL-NEXT: v_cndmask_b32_e64 v18, 0, 1, vcc ; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v19 -; GISEL-NEXT: v_cndmask_b32_e64 v19, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v13 ; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc -; GISEL-NEXT: v_mul_lo_u32 v13, v18, v6 -; GISEL-NEXT: v_mul_hi_u32 v5, v18, v5 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v19, v0 -; GISEL-NEXT: v_mul_hi_u32 v19, v15, v6 -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v13, v5 -; GISEL-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v19 +; GISEL-NEXT: v_mul_lo_u32 v19, v17, v5 +; GISEL-NEXT: v_mul_hi_u32 v4, v17, v4 +; GISEL-NEXT: v_add_i32_e32 v0, vcc, v18, v0 +; GISEL-NEXT: v_mul_hi_u32 v18, v14, v5 +; GISEL-NEXT: v_add_i32_e32 v4, vcc, v19, v4 ; GISEL-NEXT: v_cndmask_b32_e64 v19, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v13, vcc, v13, v19 -; GISEL-NEXT: v_mul_hi_u32 v6, v18, v6 -; GISEL-NEXT: v_add_i32_e32 v0, vcc, v5, v0 -; GISEL-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v13, v5 -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v6, v5 -; GISEL-NEXT: v_add_i32_e32 v13, vcc, v15, v0 -; GISEL-NEXT: v_addc_u32_e32 v15, vcc, v18, v5, vcc -; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v16, v13, 0 -; GISEL-NEXT: v_sub_i32_e32 v18, vcc, v10, v1 -; GISEL-NEXT: v_mov_b32_e32 v0, v6 -; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v16, v15, v[0:1] -; GISEL-NEXT: v_subbrev_u32_e32 v3, vcc, 0, v3, vcc -; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v17, v13, v[0:1] -; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7 -; GISEL-NEXT: v_cndmask_b32_e32 v6, v10, v18, vcc -; GISEL-NEXT: v_cndmask_b32_e32 v3, v14, v3, vcc -; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v11 -; GISEL-NEXT: v_cndmask_b32_e32 v1, v8, v6, vcc -; GISEL-NEXT: v_mul_lo_u32 v6, v15, v5 -; GISEL-NEXT: v_mul_lo_u32 v7, v13, v0 -; GISEL-NEXT: v_mul_hi_u32 v11, v13, v5 -; GISEL-NEXT: v_add_i32_e64 v8, s[4:5], 0, v12 -; GISEL-NEXT: v_addc_u32_e64 v10, s[4:5], 0, 0, s[4:5] -; GISEL-NEXT: v_add_i32_e64 v6, s[4:5], v6, v7 -; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, s[4:5] -; GISEL-NEXT: v_add_i32_e64 v6, s[4:5], v6, v11 -; GISEL-NEXT: v_cndmask_b32_e64 v6, 0, 1, s[4:5] -; GISEL-NEXT: v_mul_lo_u32 v11, v15, v0 -; GISEL-NEXT: v_mul_hi_u32 v5, v15, v5 -; GISEL-NEXT: v_add_i32_e64 v6, s[4:5], v7, v6 -; GISEL-NEXT: v_mul_hi_u32 v7, v13, v0 -; GISEL-NEXT: v_add_i32_e64 v5, s[4:5], v11, v5 -; GISEL-NEXT: v_cndmask_b32_e64 v11, 0, 1, s[4:5] +; GISEL-NEXT: v_add_i32_e32 v4, vcc, v4, v18 +; GISEL-NEXT: v_cndmask_b32_e64 v18, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v18, vcc, v19, v18 +; GISEL-NEXT: v_mul_hi_u32 v5, v17, v5 +; GISEL-NEXT: v_add_i32_e32 v0, vcc, v4, v0 +; GISEL-NEXT: v_cndmask_b32_e64 v4, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v4, vcc, v18, v4 +; GISEL-NEXT: v_add_i32_e32 v4, vcc, v5, v4 +; GISEL-NEXT: v_add_i32_e32 v14, vcc, v14, v0 +; GISEL-NEXT: v_addc_u32_e32 v17, vcc, v17, v4, vcc +; GISEL-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v15, v14, 0 +; GISEL-NEXT: v_sub_i32_e32 v18, vcc, v11, v1 +; GISEL-NEXT: v_mov_b32_e32 v0, v5 +; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v15, v17, v[0:1] +; GISEL-NEXT: v_subbrev_u32_e32 v10, vcc, 0, v10, vcc +; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v16, v14, v[0:1] +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v6 +; GISEL-NEXT: v_cndmask_b32_e32 v5, v11, v18, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v6, v13, v10, vcc +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v9 +; GISEL-NEXT: v_cndmask_b32_e32 v1, v7, v5, vcc +; GISEL-NEXT: v_mul_lo_u32 v5, v17, v4 +; GISEL-NEXT: v_mul_lo_u32 v7, v14, v0 +; GISEL-NEXT: v_mul_hi_u32 v10, v14, v4 +; GISEL-NEXT: v_add_i32_e64 v9, s[4:5], 0, v12 ; GISEL-NEXT: v_add_i32_e64 v5, s[4:5], v5, v7 ; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, s[4:5] -; GISEL-NEXT: v_add_i32_e64 v7, s[4:5], v11, v7 -; GISEL-NEXT: v_mul_hi_u32 v0, v15, v0 -; GISEL-NEXT: v_add_i32_e64 v5, s[4:5], v5, v6 -; GISEL-NEXT: v_cndmask_b32_e64 v6, 0, 1, s[4:5] -; GISEL-NEXT: v_add_i32_e64 v6, s[4:5], v7, v6 -; GISEL-NEXT: v_add_i32_e64 v0, s[4:5], v0, v6 -; GISEL-NEXT: v_add_i32_e64 v5, s[4:5], v13, v5 -; GISEL-NEXT: v_addc_u32_e64 v0, s[4:5], v15, v0, s[4:5] -; GISEL-NEXT: v_mul_lo_u32 v6, v10, v5 -; GISEL-NEXT: v_mul_lo_u32 v7, v8, v0 -; GISEL-NEXT: v_cndmask_b32_e32 v3, v9, v3, vcc -; GISEL-NEXT: v_mul_hi_u32 v9, v8, v5 -; GISEL-NEXT: v_mul_hi_u32 v5, v10, v5 -; GISEL-NEXT: v_add_i32_e32 v6, vcc, v6, v7 +; GISEL-NEXT: v_add_i32_e64 v5, s[4:5], v5, v10 +; GISEL-NEXT: v_cndmask_b32_e64 v5, 0, 1, s[4:5] +; GISEL-NEXT: v_mul_lo_u32 v10, v17, v0 +; GISEL-NEXT: v_mul_hi_u32 v4, v17, v4 +; GISEL-NEXT: v_add_i32_e64 v5, s[4:5], v7, v5 +; GISEL-NEXT: v_mul_hi_u32 v7, v14, v0 +; GISEL-NEXT: v_add_i32_e64 v4, s[4:5], v10, v4 +; GISEL-NEXT: v_cndmask_b32_e64 v10, 0, 1, s[4:5] +; GISEL-NEXT: v_add_i32_e64 v4, s[4:5], v4, v7 +; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, s[4:5] +; GISEL-NEXT: v_add_i32_e64 v7, s[4:5], v10, v7 +; GISEL-NEXT: v_mul_hi_u32 v0, v17, v0 +; GISEL-NEXT: v_add_i32_e64 v4, s[4:5], v4, v5 +; GISEL-NEXT: v_cndmask_b32_e64 v5, 0, 1, s[4:5] +; GISEL-NEXT: v_add_i32_e64 v5, s[4:5], v7, v5 +; GISEL-NEXT: v_add_i32_e64 v0, s[4:5], v0, v5 +; GISEL-NEXT: v_add_i32_e64 v4, s[4:5], v14, v4 +; GISEL-NEXT: v_addc_u32_e64 v0, s[4:5], v17, v0, s[4:5] +; GISEL-NEXT: v_mul_lo_u32 v5, v3, v4 +; GISEL-NEXT: v_mul_lo_u32 v7, v9, v0 +; GISEL-NEXT: v_cndmask_b32_e32 v8, v8, v6, vcc +; GISEL-NEXT: v_mul_hi_u32 v6, v9, v4 +; GISEL-NEXT: v_mul_hi_u32 v4, v3, v4 +; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v7 ; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v6, vcc, v6, v9 +; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v6 +; GISEL-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc +; GISEL-NEXT: v_mul_lo_u32 v6, v3, v0 +; GISEL-NEXT: v_add_i32_e32 v5, vcc, v7, v5 +; GISEL-NEXT: v_mul_hi_u32 v7, v9, v0 +; GISEL-NEXT: v_add_i32_e32 v4, vcc, v6, v4 ; GISEL-NEXT: v_cndmask_b32_e64 v6, 0, 1, vcc -; GISEL-NEXT: v_mul_lo_u32 v9, v10, v0 -; GISEL-NEXT: v_add_i32_e32 v6, vcc, v7, v6 -; GISEL-NEXT: v_mul_hi_u32 v7, v8, v0 -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v9, v5 -; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v5, vcc, v5, v7 +; GISEL-NEXT: v_add_i32_e32 v4, vcc, v4, v7 ; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v7, vcc, v9, v7 -; GISEL-NEXT: v_add_i32_e32 v9, vcc, v5, v6 -; GISEL-NEXT: v_mul_hi_u32 v0, v10, v0 -; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v2, v9, 0 -; GISEL-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v7, vcc, v7, v11 -; GISEL-NEXT: v_add_i32_e32 v7, vcc, v0, v7 -; GISEL-NEXT: v_mov_b32_e32 v0, v6 -; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[4:5], v2, v7, v[0:1] +; GISEL-NEXT: v_add_i32_e32 v6, vcc, v6, v7 +; GISEL-NEXT: v_add_i32_e32 v7, vcc, v4, v5 +; GISEL-NEXT: v_mul_hi_u32 v0, v3, v0 +; GISEL-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v2, v7, 0 +; GISEL-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc +; GISEL-NEXT: v_add_i32_e32 v6, vcc, v6, v10 +; GISEL-NEXT: v_add_i32_e32 v6, vcc, v0, v6 +; GISEL-NEXT: v_mov_b32_e32 v0, v5 +; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v2, v6, v[0:1] ; GISEL-NEXT: v_subrev_i32_e32 v0, vcc, 0, v1 -; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[4:5], v4, v9, v[6:7] -; GISEL-NEXT: v_subbrev_u32_e32 v1, vcc, 0, v3, vcc -; GISEL-NEXT: v_sub_i32_e32 v3, vcc, v8, v5 -; GISEL-NEXT: v_subb_u32_e64 v5, s[4:5], v10, v6, vcc -; GISEL-NEXT: v_sub_i32_e64 v6, s[4:5], v10, v6 -; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v5, v4 +; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v3, v7, v[5:6] +; GISEL-NEXT: v_subbrev_u32_e32 v1, vcc, 0, v8, vcc +; GISEL-NEXT: v_sub_i32_e32 v4, vcc, v9, v4 +; GISEL-NEXT: v_subb_u32_e64 v6, s[4:5], v3, v5, vcc +; GISEL-NEXT: v_sub_i32_e64 v5, s[4:5], v3, v5 +; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v6, v3 ; GISEL-NEXT: v_cndmask_b32_e64 v7, 0, -1, s[4:5] -; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v3, v2 +; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v4, v2 ; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, -1, s[4:5] -; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], v5, v4 -; GISEL-NEXT: v_subb_u32_e32 v6, vcc, v6, v4, vcc +; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], v6, v3 +; GISEL-NEXT: v_subb_u32_e32 v5, vcc, v5, v3, vcc ; GISEL-NEXT: v_cndmask_b32_e64 v7, v7, v8, s[4:5] -; GISEL-NEXT: v_sub_i32_e32 v8, vcc, v3, v2 -; GISEL-NEXT: v_subbrev_u32_e64 v9, s[4:5], 0, v6, vcc -; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v9, v4 +; GISEL-NEXT: v_sub_i32_e32 v8, vcc, v4, v2 +; GISEL-NEXT: v_subbrev_u32_e64 v9, s[4:5], 0, v5, vcc +; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v9, v3 ; GISEL-NEXT: v_cndmask_b32_e64 v10, 0, -1, s[4:5] ; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v8, v2 ; GISEL-NEXT: v_cndmask_b32_e64 v11, 0, -1, s[4:5] -; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], v9, v4 -; GISEL-NEXT: v_subb_u32_e32 v4, vcc, v6, v4, vcc +; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], v9, v3 +; GISEL-NEXT: v_subb_u32_e32 v3, vcc, v5, v3, vcc ; GISEL-NEXT: v_sub_i32_e32 v2, vcc, v8, v2 ; GISEL-NEXT: v_cndmask_b32_e64 v10, v10, v11, s[4:5] -; GISEL-NEXT: v_subbrev_u32_e32 v4, vcc, 0, v4, vcc +; GISEL-NEXT: v_subbrev_u32_e32 v3, vcc, 0, v3, vcc ; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v10 ; GISEL-NEXT: v_cndmask_b32_e32 v2, v8, v2, vcc -; GISEL-NEXT: v_cndmask_b32_e32 v4, v9, v4, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v3, v9, v3, vcc ; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v7 -; GISEL-NEXT: v_cndmask_b32_e32 v2, v3, v2, vcc -; GISEL-NEXT: v_cndmask_b32_e32 v3, v5, v4, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v2, v4, v2, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v3, v6, v3, vcc ; GISEL-NEXT: v_subrev_i32_e32 v2, vcc, 0, v2 ; GISEL-NEXT: v_subbrev_u32_e32 v3, vcc, 0, v3, vcc ; GISEL-NEXT: s_setpc_b64 s[30:31] diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/ssubsat.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/ssubsat.ll index 61e1e67b7ae360e64e84a638f8ac2d2cd4d61ab9..320dfbb4980e4c1680cec09c71a226f6c320b167 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/ssubsat.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/ssubsat.ll @@ -4142,11 +4142,11 @@ define i48 @v_ssubsat_i48(i48 %lhs, i48 %rhs) { ; GFX9-NEXT: v_lshlrev_b64 v[2:3], 16, v[2:3] ; GFX9-NEXT: v_sub_co_u32_e32 v4, vcc, v0, v2 ; GFX9-NEXT: v_subb_co_u32_e32 v5, vcc, v1, v3, vcc -; GFX9-NEXT: v_cmp_lt_i64_e64 s[4:5], v[4:5], v[0:1] -; GFX9-NEXT: v_cmp_lt_i64_e64 s[6:7], 0, v[2:3] +; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, v[4:5], v[0:1] +; GFX9-NEXT: v_cmp_lt_i64_e64 s[4:5], 0, v[2:3] ; GFX9-NEXT: v_ashrrev_i32_e32 v0, 31, v5 -; GFX9-NEXT: v_add_co_u32_e32 v1, vcc, 0x80000000, v0 -; GFX9-NEXT: s_xor_b64 vcc, s[6:7], s[4:5] +; GFX9-NEXT: v_add_u32_e32 v1, 0x80000000, v0 +; GFX9-NEXT: s_xor_b64 vcc, s[4:5], vcc ; GFX9-NEXT: v_cndmask_b32_e32 v0, v4, v0, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v5, v1, vcc ; GFX9-NEXT: v_ashrrev_i64 v[0:1], 16, v[0:1] @@ -4162,7 +4162,7 @@ define i48 @v_ssubsat_i48(i48 %lhs, i48 %rhs) { ; GFX10-NEXT: v_cmp_lt_i64_e32 vcc_lo, 0, v[2:3] ; GFX10-NEXT: v_ashrrev_i32_e32 v6, 31, v5 ; GFX10-NEXT: v_cmp_lt_i64_e64 s4, v[4:5], v[0:1] -; GFX10-NEXT: v_add_co_u32 v1, s5, 0x80000000, v6 +; GFX10-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v6 ; GFX10-NEXT: s_xor_b32 vcc_lo, vcc_lo, s4 ; GFX10-NEXT: v_cndmask_b32_e32 v0, v4, v6, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v1, v5, v1, vcc_lo @@ -4179,7 +4179,7 @@ define i48 @v_ssubsat_i48(i48 %lhs, i48 %rhs) { ; GFX11-NEXT: v_cmp_lt_i64_e32 vcc_lo, 0, v[2:3] ; GFX11-NEXT: v_ashrrev_i32_e32 v6, 31, v5 ; GFX11-NEXT: v_cmp_lt_i64_e64 s0, v[4:5], v[0:1] -; GFX11-NEXT: v_add_co_u32 v1, null, 0x80000000, v6 +; GFX11-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v6 ; GFX11-NEXT: s_xor_b32 vcc_lo, vcc_lo, s0 ; GFX11-NEXT: v_dual_cndmask_b32 v0, v4, v6 :: v_dual_cndmask_b32 v1, v5, v1 ; GFX11-NEXT: v_ashrrev_i64 v[0:1], 16, v[0:1] @@ -4202,7 +4202,7 @@ define amdgpu_ps i48 @s_ssubsat_i48(i48 inreg %lhs, i48 inreg %rhs) { ; GFX6-NEXT: v_cmp_gt_i64_e64 s[0:1], s[0:1], 0 ; GFX6-NEXT: s_ashr_i32 s2, s7, 31 ; GFX6-NEXT: s_ashr_i32 s5, s7, 15 -; GFX6-NEXT: s_add_u32 s2, s2, 0xffff8000 +; GFX6-NEXT: s_addk_i32 s2, 0x8000 ; GFX6-NEXT: v_mov_b32_e32 v0, s5 ; GFX6-NEXT: v_mov_b32_e32 v1, s2 ; GFX6-NEXT: v_mov_b32_e32 v2, s4 @@ -4227,7 +4227,7 @@ define amdgpu_ps i48 @s_ssubsat_i48(i48 inreg %lhs, i48 inreg %rhs) { ; GFX8-NEXT: v_cmp_gt_i64_e64 s[0:1], s[0:1], 0 ; GFX8-NEXT: s_ashr_i32 s2, s7, 31 ; GFX8-NEXT: s_ashr_i32 s5, s7, 15 -; GFX8-NEXT: s_add_u32 s2, s2, 0xffff8000 +; GFX8-NEXT: s_addk_i32 s2, 0x8000 ; GFX8-NEXT: v_mov_b32_e32 v0, s5 ; GFX8-NEXT: v_mov_b32_e32 v1, s2 ; GFX8-NEXT: v_mov_b32_e32 v2, s4 @@ -4250,7 +4250,7 @@ define amdgpu_ps i48 @s_ssubsat_i48(i48 inreg %lhs, i48 inreg %rhs) { ; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, s[4:5], v[0:1] ; GFX9-NEXT: v_cmp_gt_i64_e64 s[0:1], s[2:3], 0 ; GFX9-NEXT: s_ashr_i32 s2, s5, 31 -; GFX9-NEXT: s_add_u32 s3, s2, 0x80000000 +; GFX9-NEXT: s_add_i32 s3, s2, 0x80000000 ; GFX9-NEXT: v_mov_b32_e32 v0, s2 ; GFX9-NEXT: v_mov_b32_e32 v1, s3 ; GFX9-NEXT: v_mov_b32_e32 v2, s4 @@ -4274,7 +4274,7 @@ define amdgpu_ps i48 @s_ssubsat_i48(i48 inreg %lhs, i48 inreg %rhs) { ; GFX10-NEXT: v_cmp_gt_i64_e64 s1, s[2:3], 0 ; GFX10-NEXT: v_mov_b32_e32 v1, s5 ; GFX10-NEXT: s_ashr_i32 s2, s5, 31 -; GFX10-NEXT: s_add_u32 s3, s2, 0x80000000 +; GFX10-NEXT: s_add_i32 s3, s2, 0x80000000 ; GFX10-NEXT: s_xor_b32 s0, s1, s0 ; GFX10-NEXT: v_cndmask_b32_e64 v0, v0, s2, s0 ; GFX10-NEXT: v_cndmask_b32_e64 v1, v1, s3, s0 @@ -4293,7 +4293,7 @@ define amdgpu_ps i48 @s_ssubsat_i48(i48 inreg %lhs, i48 inreg %rhs) { ; GFX11-NEXT: v_cmp_lt_i64_e64 s0, s[4:5], s[0:1] ; GFX11-NEXT: v_cmp_gt_i64_e64 s1, s[2:3], 0 ; GFX11-NEXT: s_ashr_i32 s2, s5, 31 -; GFX11-NEXT: s_add_u32 s3, s2, 0x80000000 +; GFX11-NEXT: s_add_i32 s3, s2, 0x80000000 ; GFX11-NEXT: s_xor_b32 s0, s1, s0 ; GFX11-NEXT: v_cndmask_b32_e64 v0, v0, s2, s0 ; GFX11-NEXT: v_cndmask_b32_e64 v1, v1, s3, s0 @@ -4351,11 +4351,11 @@ define amdgpu_ps <2 x float> @ssubsat_i48_sv(i48 inreg %lhs, i48 %rhs) { ; GFX9-NEXT: v_mov_b32_e32 v3, s1 ; GFX9-NEXT: v_sub_co_u32_e32 v2, vcc, s0, v0 ; GFX9-NEXT: v_subb_co_u32_e32 v3, vcc, v3, v1, vcc -; GFX9-NEXT: v_cmp_gt_i64_e64 s[0:1], s[0:1], v[2:3] -; GFX9-NEXT: v_cmp_lt_i64_e64 s[2:3], 0, v[0:1] +; GFX9-NEXT: v_cmp_gt_i64_e32 vcc, s[0:1], v[2:3] +; GFX9-NEXT: v_cmp_lt_i64_e64 s[0:1], 0, v[0:1] ; GFX9-NEXT: v_ashrrev_i32_e32 v0, 31, v3 -; GFX9-NEXT: v_add_co_u32_e32 v1, vcc, 0x80000000, v0 -; GFX9-NEXT: s_xor_b64 vcc, s[2:3], s[0:1] +; GFX9-NEXT: v_add_u32_e32 v1, 0x80000000, v0 +; GFX9-NEXT: s_xor_b64 vcc, s[0:1], vcc ; GFX9-NEXT: v_cndmask_b32_e32 v0, v2, v0, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc ; GFX9-NEXT: v_ashrrev_i64 v[0:1], 16, v[0:1] @@ -4371,7 +4371,7 @@ define amdgpu_ps <2 x float> @ssubsat_i48_sv(i48 inreg %lhs, i48 %rhs) { ; GFX10-NEXT: v_ashrrev_i32_e32 v4, 31, v3 ; GFX10-NEXT: v_cmp_gt_i64_e32 vcc_lo, s[0:1], v[2:3] ; GFX10-NEXT: v_cmp_lt_i64_e64 s0, 0, v[0:1] -; GFX10-NEXT: v_add_co_u32 v1, s1, 0x80000000, v4 +; GFX10-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v4 ; GFX10-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v0, v2, v4, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc_lo @@ -4388,7 +4388,7 @@ define amdgpu_ps <2 x float> @ssubsat_i48_sv(i48 inreg %lhs, i48 %rhs) { ; GFX11-NEXT: v_ashrrev_i32_e32 v4, 31, v3 ; GFX11-NEXT: v_cmp_gt_i64_e32 vcc_lo, s[0:1], v[2:3] ; GFX11-NEXT: v_cmp_lt_i64_e64 s0, 0, v[0:1] -; GFX11-NEXT: v_add_co_u32 v1, null, 0x80000000, v4 +; GFX11-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v4 ; GFX11-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX11-NEXT: v_dual_cndmask_b32 v0, v2, v4 :: v_dual_cndmask_b32 v1, v3, v1 ; GFX11-NEXT: v_ashrrev_i64 v[0:1], 16, v[0:1] @@ -4442,15 +4442,15 @@ define amdgpu_ps <2 x float> @ssubsat_i48_vs(i48 %lhs, i48 inreg %rhs) { ; GFX9-LABEL: ssubsat_i48_vs: ; GFX9: ; %bb.0: ; GFX9-NEXT: v_lshlrev_b64 v[0:1], 16, v[0:1] -; GFX9-NEXT: s_lshl_b64 s[2:3], s[0:1], 16 -; GFX9-NEXT: v_mov_b32_e32 v3, s3 -; GFX9-NEXT: v_subrev_co_u32_e32 v2, vcc, s2, v0 +; GFX9-NEXT: s_lshl_b64 s[0:1], s[0:1], 16 +; GFX9-NEXT: v_mov_b32_e32 v3, s1 +; GFX9-NEXT: v_subrev_co_u32_e32 v2, vcc, s0, v0 ; GFX9-NEXT: v_subb_co_u32_e32 v3, vcc, v1, v3, vcc -; GFX9-NEXT: v_cmp_lt_i64_e64 s[0:1], v[2:3], v[0:1] -; GFX9-NEXT: v_cmp_gt_i64_e64 s[2:3], s[2:3], 0 +; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, v[2:3], v[0:1] +; GFX9-NEXT: v_cmp_gt_i64_e64 s[0:1], s[0:1], 0 ; GFX9-NEXT: v_ashrrev_i32_e32 v0, 31, v3 -; GFX9-NEXT: v_add_co_u32_e32 v1, vcc, 0x80000000, v0 -; GFX9-NEXT: s_xor_b64 vcc, s[2:3], s[0:1] +; GFX9-NEXT: v_add_u32_e32 v1, 0x80000000, v0 +; GFX9-NEXT: s_xor_b64 vcc, s[0:1], vcc ; GFX9-NEXT: v_cndmask_b32_e32 v0, v2, v0, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc ; GFX9-NEXT: v_ashrrev_i64 v[0:1], 16, v[0:1] @@ -4466,7 +4466,7 @@ define amdgpu_ps <2 x float> @ssubsat_i48_vs(i48 %lhs, i48 inreg %rhs) { ; GFX10-NEXT: v_cmp_gt_i64_e64 s0, s[0:1], 0 ; GFX10-NEXT: v_ashrrev_i32_e32 v4, 31, v3 ; GFX10-NEXT: v_cmp_lt_i64_e32 vcc_lo, v[2:3], v[0:1] -; GFX10-NEXT: v_add_co_u32 v1, s1, 0x80000000, v4 +; GFX10-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v4 ; GFX10-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v0, v2, v4, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc_lo @@ -4483,7 +4483,7 @@ define amdgpu_ps <2 x float> @ssubsat_i48_vs(i48 %lhs, i48 inreg %rhs) { ; GFX11-NEXT: v_cmp_gt_i64_e64 s0, s[0:1], 0 ; GFX11-NEXT: v_ashrrev_i32_e32 v4, 31, v3 ; GFX11-NEXT: v_cmp_lt_i64_e32 vcc_lo, v[2:3], v[0:1] -; GFX11-NEXT: v_add_co_u32 v1, null, 0x80000000, v4 +; GFX11-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v4 ; GFX11-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX11-NEXT: v_dual_cndmask_b32 v0, v2, v4 :: v_dual_cndmask_b32 v1, v3, v1 ; GFX11-NEXT: v_ashrrev_i64 v[0:1], 16, v[0:1] @@ -4529,11 +4529,11 @@ define i64 @v_ssubsat_i64(i64 %lhs, i64 %rhs) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: v_sub_co_u32_e32 v4, vcc, v0, v2 ; GFX9-NEXT: v_subb_co_u32_e32 v5, vcc, v1, v3, vcc -; GFX9-NEXT: v_cmp_lt_i64_e64 s[4:5], v[4:5], v[0:1] -; GFX9-NEXT: v_cmp_lt_i64_e64 s[6:7], 0, v[2:3] +; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, v[4:5], v[0:1] +; GFX9-NEXT: v_cmp_lt_i64_e64 s[4:5], 0, v[2:3] ; GFX9-NEXT: v_ashrrev_i32_e32 v0, 31, v5 -; GFX9-NEXT: v_add_co_u32_e32 v1, vcc, 0x80000000, v0 -; GFX9-NEXT: s_xor_b64 vcc, s[6:7], s[4:5] +; GFX9-NEXT: v_add_u32_e32 v1, 0x80000000, v0 +; GFX9-NEXT: s_xor_b64 vcc, s[4:5], vcc ; GFX9-NEXT: v_cndmask_b32_e32 v0, v4, v0, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v5, v1, vcc ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -4546,7 +4546,7 @@ define i64 @v_ssubsat_i64(i64 %lhs, i64 %rhs) { ; GFX10-NEXT: v_cmp_lt_i64_e64 s4, 0, v[2:3] ; GFX10-NEXT: v_ashrrev_i32_e32 v6, 31, v5 ; GFX10-NEXT: v_cmp_lt_i64_e32 vcc_lo, v[4:5], v[0:1] -; GFX10-NEXT: v_add_co_u32 v1, s5, 0x80000000, v6 +; GFX10-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v6 ; GFX10-NEXT: s_xor_b32 vcc_lo, s4, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v0, v4, v6, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v1, v5, v1, vcc_lo @@ -4560,7 +4560,7 @@ define i64 @v_ssubsat_i64(i64 %lhs, i64 %rhs) { ; GFX11-NEXT: v_cmp_lt_i64_e64 s0, 0, v[2:3] ; GFX11-NEXT: v_ashrrev_i32_e32 v6, 31, v5 ; GFX11-NEXT: v_cmp_lt_i64_e32 vcc_lo, v[4:5], v[0:1] -; GFX11-NEXT: v_add_co_u32 v1, null, 0x80000000, v6 +; GFX11-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v6 ; GFX11-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX11-NEXT: v_dual_cndmask_b32 v0, v4, v6 :: v_dual_cndmask_b32 v1, v5, v1 ; GFX11-NEXT: s_setpc_b64 s[30:31] @@ -4578,7 +4578,7 @@ define amdgpu_ps i64 @s_ssubsat_i64(i64 inreg %lhs, i64 inreg %rhs) { ; GFX6-NEXT: v_cmp_lt_i64_e32 vcc, s[4:5], v[0:1] ; GFX6-NEXT: v_cmp_gt_i64_e64 s[0:1], s[2:3], 0 ; GFX6-NEXT: s_ashr_i32 s2, s5, 31 -; GFX6-NEXT: s_add_u32 s3, s2, 0x80000000 +; GFX6-NEXT: s_add_i32 s3, s2, 0x80000000 ; GFX6-NEXT: v_mov_b32_e32 v0, s2 ; GFX6-NEXT: v_mov_b32_e32 v1, s3 ; GFX6-NEXT: v_mov_b32_e32 v2, s4 @@ -4599,7 +4599,7 @@ define amdgpu_ps i64 @s_ssubsat_i64(i64 inreg %lhs, i64 inreg %rhs) { ; GFX8-NEXT: v_cmp_lt_i64_e32 vcc, s[4:5], v[0:1] ; GFX8-NEXT: v_cmp_gt_i64_e64 s[0:1], s[2:3], 0 ; GFX8-NEXT: s_ashr_i32 s2, s5, 31 -; GFX8-NEXT: s_add_u32 s3, s2, 0x80000000 +; GFX8-NEXT: s_add_i32 s3, s2, 0x80000000 ; GFX8-NEXT: v_mov_b32_e32 v0, s2 ; GFX8-NEXT: v_mov_b32_e32 v1, s3 ; GFX8-NEXT: v_mov_b32_e32 v2, s4 @@ -4620,7 +4620,7 @@ define amdgpu_ps i64 @s_ssubsat_i64(i64 inreg %lhs, i64 inreg %rhs) { ; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, s[4:5], v[0:1] ; GFX9-NEXT: v_cmp_gt_i64_e64 s[0:1], s[2:3], 0 ; GFX9-NEXT: s_ashr_i32 s2, s5, 31 -; GFX9-NEXT: s_add_u32 s3, s2, 0x80000000 +; GFX9-NEXT: s_add_i32 s3, s2, 0x80000000 ; GFX9-NEXT: v_mov_b32_e32 v0, s2 ; GFX9-NEXT: v_mov_b32_e32 v1, s3 ; GFX9-NEXT: v_mov_b32_e32 v2, s4 @@ -4641,7 +4641,7 @@ define amdgpu_ps i64 @s_ssubsat_i64(i64 inreg %lhs, i64 inreg %rhs) { ; GFX10-NEXT: v_cmp_gt_i64_e64 s1, s[2:3], 0 ; GFX10-NEXT: v_mov_b32_e32 v1, s5 ; GFX10-NEXT: s_ashr_i32 s2, s5, 31 -; GFX10-NEXT: s_add_u32 s3, s2, 0x80000000 +; GFX10-NEXT: s_add_i32 s3, s2, 0x80000000 ; GFX10-NEXT: s_xor_b32 s0, s1, s0 ; GFX10-NEXT: v_cndmask_b32_e64 v0, v0, s2, s0 ; GFX10-NEXT: v_cndmask_b32_e64 v1, v1, s3, s0 @@ -4657,7 +4657,7 @@ define amdgpu_ps i64 @s_ssubsat_i64(i64 inreg %lhs, i64 inreg %rhs) { ; GFX11-NEXT: v_cmp_lt_i64_e64 s0, s[4:5], s[0:1] ; GFX11-NEXT: v_cmp_gt_i64_e64 s1, s[2:3], 0 ; GFX11-NEXT: s_ashr_i32 s2, s5, 31 -; GFX11-NEXT: s_add_u32 s3, s2, 0x80000000 +; GFX11-NEXT: s_add_i32 s3, s2, 0x80000000 ; GFX11-NEXT: s_xor_b32 s0, s1, s0 ; GFX11-NEXT: v_cndmask_b32_e64 v0, v0, s2, s0 ; GFX11-NEXT: v_cndmask_b32_e64 v1, v1, s3, s0 @@ -4702,11 +4702,11 @@ define amdgpu_ps <2 x float> @ssubsat_i64_sv(i64 inreg %lhs, i64 %rhs) { ; GFX9-NEXT: v_mov_b32_e32 v3, s1 ; GFX9-NEXT: v_sub_co_u32_e32 v2, vcc, s0, v0 ; GFX9-NEXT: v_subb_co_u32_e32 v3, vcc, v3, v1, vcc -; GFX9-NEXT: v_cmp_gt_i64_e64 s[0:1], s[0:1], v[2:3] -; GFX9-NEXT: v_cmp_lt_i64_e64 s[2:3], 0, v[0:1] +; GFX9-NEXT: v_cmp_gt_i64_e32 vcc, s[0:1], v[2:3] +; GFX9-NEXT: v_cmp_lt_i64_e64 s[0:1], 0, v[0:1] ; GFX9-NEXT: v_ashrrev_i32_e32 v0, 31, v3 -; GFX9-NEXT: v_add_co_u32_e32 v1, vcc, 0x80000000, v0 -; GFX9-NEXT: s_xor_b64 vcc, s[2:3], s[0:1] +; GFX9-NEXT: v_add_u32_e32 v1, 0x80000000, v0 +; GFX9-NEXT: s_xor_b64 vcc, s[0:1], vcc ; GFX9-NEXT: v_cndmask_b32_e32 v0, v2, v0, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc ; GFX9-NEXT: ; return to shader part epilog @@ -4718,7 +4718,7 @@ define amdgpu_ps <2 x float> @ssubsat_i64_sv(i64 inreg %lhs, i64 %rhs) { ; GFX10-NEXT: v_ashrrev_i32_e32 v4, 31, v3 ; GFX10-NEXT: v_cmp_gt_i64_e32 vcc_lo, s[0:1], v[2:3] ; GFX10-NEXT: v_cmp_lt_i64_e64 s0, 0, v[0:1] -; GFX10-NEXT: v_add_co_u32 v1, s1, 0x80000000, v4 +; GFX10-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v4 ; GFX10-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v0, v2, v4, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc_lo @@ -4731,7 +4731,7 @@ define amdgpu_ps <2 x float> @ssubsat_i64_sv(i64 inreg %lhs, i64 %rhs) { ; GFX11-NEXT: v_ashrrev_i32_e32 v4, 31, v3 ; GFX11-NEXT: v_cmp_gt_i64_e32 vcc_lo, s[0:1], v[2:3] ; GFX11-NEXT: v_cmp_lt_i64_e64 s0, 0, v[0:1] -; GFX11-NEXT: v_add_co_u32 v1, null, 0x80000000, v4 +; GFX11-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v4 ; GFX11-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX11-NEXT: v_dual_cndmask_b32 v0, v2, v4 :: v_dual_cndmask_b32 v1, v3, v1 ; GFX11-NEXT: ; return to shader part epilog @@ -4774,11 +4774,11 @@ define amdgpu_ps <2 x float> @ssubsat_i64_vs(i64 %lhs, i64 inreg %rhs) { ; GFX9-NEXT: v_mov_b32_e32 v3, s1 ; GFX9-NEXT: v_subrev_co_u32_e32 v2, vcc, s0, v0 ; GFX9-NEXT: v_subb_co_u32_e32 v3, vcc, v1, v3, vcc -; GFX9-NEXT: v_cmp_lt_i64_e64 s[2:3], v[2:3], v[0:1] +; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, v[2:3], v[0:1] ; GFX9-NEXT: v_cmp_gt_i64_e64 s[0:1], s[0:1], 0 ; GFX9-NEXT: v_ashrrev_i32_e32 v0, 31, v3 -; GFX9-NEXT: v_add_co_u32_e32 v1, vcc, 0x80000000, v0 -; GFX9-NEXT: s_xor_b64 vcc, s[0:1], s[2:3] +; GFX9-NEXT: v_add_u32_e32 v1, 0x80000000, v0 +; GFX9-NEXT: s_xor_b64 vcc, s[0:1], vcc ; GFX9-NEXT: v_cndmask_b32_e32 v0, v2, v0, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc ; GFX9-NEXT: ; return to shader part epilog @@ -4790,7 +4790,7 @@ define amdgpu_ps <2 x float> @ssubsat_i64_vs(i64 %lhs, i64 inreg %rhs) { ; GFX10-NEXT: v_cmp_gt_i64_e64 s0, s[0:1], 0 ; GFX10-NEXT: v_ashrrev_i32_e32 v4, 31, v3 ; GFX10-NEXT: v_cmp_lt_i64_e32 vcc_lo, v[2:3], v[0:1] -; GFX10-NEXT: v_add_co_u32 v1, s1, 0x80000000, v4 +; GFX10-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v4 ; GFX10-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v0, v2, v4, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc_lo @@ -4803,7 +4803,7 @@ define amdgpu_ps <2 x float> @ssubsat_i64_vs(i64 %lhs, i64 inreg %rhs) { ; GFX11-NEXT: v_cmp_gt_i64_e64 s0, s[0:1], 0 ; GFX11-NEXT: v_ashrrev_i32_e32 v4, 31, v3 ; GFX11-NEXT: v_cmp_lt_i64_e32 vcc_lo, v[2:3], v[0:1] -; GFX11-NEXT: v_add_co_u32 v1, null, 0x80000000, v4 +; GFX11-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v4 ; GFX11-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX11-NEXT: v_dual_cndmask_b32 v0, v2, v4 :: v_dual_cndmask_b32 v1, v3, v1 ; GFX11-NEXT: ; return to shader part epilog @@ -4866,21 +4866,20 @@ define <2 x i64> @v_ssubsat_v2i64(<2 x i64> %lhs, <2 x i64> %rhs) { ; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX9-NEXT: v_sub_co_u32_e32 v8, vcc, v0, v4 ; GFX9-NEXT: v_subb_co_u32_e32 v9, vcc, v1, v5, vcc -; GFX9-NEXT: v_cmp_lt_i64_e64 s[4:5], v[8:9], v[0:1] -; GFX9-NEXT: v_cmp_lt_i64_e64 s[6:7], 0, v[4:5] +; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, v[8:9], v[0:1] +; GFX9-NEXT: v_cmp_lt_i64_e64 s[4:5], 0, v[4:5] ; GFX9-NEXT: v_ashrrev_i32_e32 v0, 31, v9 -; GFX9-NEXT: v_bfrev_b32_e32 v1, 1 -; GFX9-NEXT: v_add_co_u32_e32 v1, vcc, v0, v1 -; GFX9-NEXT: s_xor_b64 vcc, s[6:7], s[4:5] +; GFX9-NEXT: v_add_u32_e32 v1, 0x80000000, v0 +; GFX9-NEXT: s_xor_b64 vcc, s[4:5], vcc ; GFX9-NEXT: v_cndmask_b32_e32 v0, v8, v0, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v9, v1, vcc ; GFX9-NEXT: v_sub_co_u32_e32 v4, vcc, v2, v6 ; GFX9-NEXT: v_subb_co_u32_e32 v5, vcc, v3, v7, vcc -; GFX9-NEXT: v_cmp_lt_i64_e64 s[4:5], v[4:5], v[2:3] -; GFX9-NEXT: v_cmp_lt_i64_e64 s[6:7], 0, v[6:7] +; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, v[4:5], v[2:3] +; GFX9-NEXT: v_cmp_lt_i64_e64 s[4:5], 0, v[6:7] ; GFX9-NEXT: v_ashrrev_i32_e32 v2, 31, v5 -; GFX9-NEXT: v_add_co_u32_e32 v3, vcc, 0x80000000, v2 -; GFX9-NEXT: s_xor_b64 vcc, s[6:7], s[4:5] +; GFX9-NEXT: v_add_u32_e32 v3, 0x80000000, v2 +; GFX9-NEXT: s_xor_b64 vcc, s[4:5], vcc ; GFX9-NEXT: v_cndmask_b32_e32 v2, v4, v2, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v3, v5, v3, vcc ; GFX9-NEXT: s_setpc_b64 s[30:31] @@ -4896,10 +4895,10 @@ define <2 x i64> @v_ssubsat_v2i64(<2 x i64> %lhs, <2 x i64> %rhs) { ; GFX10-NEXT: v_cmp_lt_i64_e32 vcc_lo, v[8:9], v[0:1] ; GFX10-NEXT: v_cmp_lt_i64_e64 s4, 0, v[4:5] ; GFX10-NEXT: v_ashrrev_i32_e32 v4, 31, v11 -; GFX10-NEXT: v_cmp_lt_i64_e64 s6, 0, v[6:7] -; GFX10-NEXT: v_add_co_u32 v1, s5, 0x80000000, v12 ; GFX10-NEXT: v_cmp_lt_i64_e64 s5, v[10:11], v[2:3] -; GFX10-NEXT: v_add_co_u32 v3, s7, 0x80000000, v4 +; GFX10-NEXT: v_cmp_lt_i64_e64 s6, 0, v[6:7] +; GFX10-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v12 +; GFX10-NEXT: v_add_nc_u32_e32 v3, 0x80000000, v4 ; GFX10-NEXT: s_xor_b32 vcc_lo, s4, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v0, v8, v12, vcc_lo ; GFX10-NEXT: v_cndmask_b32_e32 v1, v9, v1, vcc_lo @@ -4921,8 +4920,8 @@ define <2 x i64> @v_ssubsat_v2i64(<2 x i64> %lhs, <2 x i64> %rhs) { ; GFX11-NEXT: v_ashrrev_i32_e32 v4, 31, v11 ; GFX11-NEXT: v_cmp_lt_i64_e64 s1, v[10:11], v[2:3] ; GFX11-NEXT: v_cmp_lt_i64_e64 s2, 0, v[6:7] -; GFX11-NEXT: v_add_co_u32 v1, null, 0x80000000, v12 -; GFX11-NEXT: v_add_co_u32 v3, null, 0x80000000, v4 +; GFX11-NEXT: v_add_nc_u32_e32 v1, 0x80000000, v12 +; GFX11-NEXT: v_add_nc_u32_e32 v3, 0x80000000, v4 ; GFX11-NEXT: s_xor_b32 vcc_lo, s0, vcc_lo ; GFX11-NEXT: v_dual_cndmask_b32 v0, v8, v12 :: v_dual_cndmask_b32 v1, v9, v1 ; GFX11-NEXT: s_xor_b32 vcc_lo, s2, s1 @@ -4942,7 +4941,7 @@ define amdgpu_ps <2 x i64> @s_ssubsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX6-NEXT: v_cmp_lt_i64_e32 vcc, s[8:9], v[0:1] ; GFX6-NEXT: v_cmp_gt_i64_e64 s[0:1], s[4:5], 0 ; GFX6-NEXT: s_ashr_i32 s4, s9, 31 -; GFX6-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX6-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX6-NEXT: v_mov_b32_e32 v0, s4 ; GFX6-NEXT: v_mov_b32_e32 v1, s5 ; GFX6-NEXT: v_mov_b32_e32 v2, s8 @@ -4957,7 +4956,7 @@ define amdgpu_ps <2 x i64> @s_ssubsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX6-NEXT: v_cmp_lt_i64_e32 vcc, s[0:1], v[0:1] ; GFX6-NEXT: v_cmp_gt_i64_e64 s[2:3], s[6:7], 0 ; GFX6-NEXT: s_ashr_i32 s4, s1, 31 -; GFX6-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX6-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX6-NEXT: v_mov_b32_e32 v0, s4 ; GFX6-NEXT: v_mov_b32_e32 v1, s5 ; GFX6-NEXT: v_mov_b32_e32 v4, s0 @@ -4980,7 +4979,7 @@ define amdgpu_ps <2 x i64> @s_ssubsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX8-NEXT: v_cmp_lt_i64_e32 vcc, s[8:9], v[0:1] ; GFX8-NEXT: v_cmp_gt_i64_e64 s[0:1], s[4:5], 0 ; GFX8-NEXT: s_ashr_i32 s4, s9, 31 -; GFX8-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX8-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX8-NEXT: v_mov_b32_e32 v0, s4 ; GFX8-NEXT: v_mov_b32_e32 v1, s5 ; GFX8-NEXT: v_mov_b32_e32 v2, s8 @@ -4995,7 +4994,7 @@ define amdgpu_ps <2 x i64> @s_ssubsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX8-NEXT: v_cmp_lt_i64_e32 vcc, s[0:1], v[0:1] ; GFX8-NEXT: v_cmp_gt_i64_e64 s[2:3], s[6:7], 0 ; GFX8-NEXT: s_ashr_i32 s4, s1, 31 -; GFX8-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX8-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX8-NEXT: v_mov_b32_e32 v0, s4 ; GFX8-NEXT: v_mov_b32_e32 v1, s5 ; GFX8-NEXT: v_mov_b32_e32 v4, s0 @@ -5018,7 +5017,7 @@ define amdgpu_ps <2 x i64> @s_ssubsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, s[8:9], v[0:1] ; GFX9-NEXT: v_cmp_gt_i64_e64 s[0:1], s[4:5], 0 ; GFX9-NEXT: s_ashr_i32 s4, s9, 31 -; GFX9-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX9-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX9-NEXT: v_mov_b32_e32 v0, s4 ; GFX9-NEXT: v_mov_b32_e32 v1, s5 ; GFX9-NEXT: v_mov_b32_e32 v2, s8 @@ -5033,7 +5032,7 @@ define amdgpu_ps <2 x i64> @s_ssubsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX9-NEXT: v_cmp_lt_i64_e32 vcc, s[0:1], v[0:1] ; GFX9-NEXT: v_cmp_gt_i64_e64 s[2:3], s[6:7], 0 ; GFX9-NEXT: s_ashr_i32 s4, s1, 31 -; GFX9-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX9-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX9-NEXT: v_mov_b32_e32 v0, s4 ; GFX9-NEXT: v_mov_b32_e32 v1, s5 ; GFX9-NEXT: v_mov_b32_e32 v4, s0 @@ -5056,7 +5055,7 @@ define amdgpu_ps <2 x i64> @s_ssubsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX10-NEXT: v_cmp_gt_i64_e64 s1, s[4:5], 0 ; GFX10-NEXT: s_ashr_i32 s4, s9, 31 ; GFX10-NEXT: v_mov_b32_e32 v1, s9 -; GFX10-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX10-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX10-NEXT: s_xor_b32 s8, s1, s0 ; GFX10-NEXT: s_sub_u32 s0, s2, s6 ; GFX10-NEXT: s_subb_u32 s1, s3, s7 @@ -5067,7 +5066,7 @@ define amdgpu_ps <2 x i64> @s_ssubsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX10-NEXT: v_cndmask_b32_e64 v0, v0, s4, s8 ; GFX10-NEXT: s_ashr_i32 s4, s1, 31 ; GFX10-NEXT: v_cndmask_b32_e64 v1, v1, s5, s8 -; GFX10-NEXT: s_add_u32 s0, s4, 0x80000000 +; GFX10-NEXT: s_add_i32 s0, s4, 0x80000000 ; GFX10-NEXT: s_xor_b32 s1, s3, s2 ; GFX10-NEXT: v_cndmask_b32_e64 v2, v2, s4, s1 ; GFX10-NEXT: v_cndmask_b32_e64 v3, v3, s0, s1 @@ -5085,7 +5084,7 @@ define amdgpu_ps <2 x i64> @s_ssubsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX11-NEXT: v_cmp_lt_i64_e64 s0, s[8:9], s[0:1] ; GFX11-NEXT: v_cmp_gt_i64_e64 s1, s[4:5], 0 ; GFX11-NEXT: s_ashr_i32 s4, s9, 31 -; GFX11-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX11-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX11-NEXT: s_xor_b32 s8, s1, s0 ; GFX11-NEXT: s_sub_u32 s0, s2, s6 ; GFX11-NEXT: s_subb_u32 s1, s3, s7 @@ -5095,7 +5094,7 @@ define amdgpu_ps <2 x i64> @s_ssubsat_v2i64(<2 x i64> inreg %lhs, <2 x i64> inre ; GFX11-NEXT: v_cndmask_b32_e64 v0, v0, s4, s8 ; GFX11-NEXT: s_ashr_i32 s4, s1, 31 ; GFX11-NEXT: v_cndmask_b32_e64 v1, v1, s5, s8 -; GFX11-NEXT: s_add_u32 s0, s4, 0x80000000 +; GFX11-NEXT: s_add_i32 s0, s4, 0x80000000 ; GFX11-NEXT: s_xor_b32 s1, s3, s2 ; GFX11-NEXT: v_cndmask_b32_e64 v2, v2, s4, s1 ; GFX11-NEXT: v_cndmask_b32_e64 v3, v3, s0, s1 @@ -5134,7 +5133,7 @@ define amdgpu_ps i128 @s_ssubsat_i128(i128 inreg %lhs, i128 inreg %rhs) { ; GFX6-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX6-NEXT: s_ashr_i32 s0, s11, 31 ; GFX6-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX6-NEXT: s_add_u32 s1, s0, 0x80000000 +; GFX6-NEXT: s_add_i32 s1, s0, 0x80000000 ; GFX6-NEXT: v_mov_b32_e32 v1, s0 ; GFX6-NEXT: v_mov_b32_e32 v2, s8 ; GFX6-NEXT: v_mov_b32_e32 v3, s9 @@ -5183,7 +5182,7 @@ define amdgpu_ps i128 @s_ssubsat_i128(i128 inreg %lhs, i128 inreg %rhs) { ; GFX8-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX8-NEXT: s_ashr_i32 s0, s11, 31 ; GFX8-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX8-NEXT: s_add_u32 s1, s0, 0x80000000 +; GFX8-NEXT: s_add_i32 s1, s0, 0x80000000 ; GFX8-NEXT: v_mov_b32_e32 v1, s0 ; GFX8-NEXT: v_mov_b32_e32 v2, s8 ; GFX8-NEXT: v_mov_b32_e32 v3, s9 @@ -5232,7 +5231,7 @@ define amdgpu_ps i128 @s_ssubsat_i128(i128 inreg %lhs, i128 inreg %rhs) { ; GFX9-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX9-NEXT: s_ashr_i32 s0, s11, 31 ; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX9-NEXT: s_add_u32 s1, s0, 0x80000000 +; GFX9-NEXT: s_add_i32 s1, s0, 0x80000000 ; GFX9-NEXT: v_mov_b32_e32 v1, s0 ; GFX9-NEXT: v_mov_b32_e32 v2, s8 ; GFX9-NEXT: v_mov_b32_e32 v3, s9 @@ -5274,7 +5273,7 @@ define amdgpu_ps i128 @s_ssubsat_i128(i128 inreg %lhs, i128 inreg %rhs) { ; GFX10-NEXT: v_cndmask_b32_e64 v3, 0, 1, s2 ; GFX10-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc_lo ; GFX10-NEXT: v_cmp_ne_u32_e64 vcc_lo, 0, s1 -; GFX10-NEXT: s_add_u32 s1, s0, 0x80000000 +; GFX10-NEXT: s_add_i32 s1, s0, 0x80000000 ; GFX10-NEXT: v_cndmask_b32_e32 v1, v3, v2, vcc_lo ; GFX10-NEXT: v_mov_b32_e32 v2, s9 ; GFX10-NEXT: v_mov_b32_e32 v3, s11 @@ -5317,7 +5316,7 @@ define amdgpu_ps i128 @s_ssubsat_i128(i128 inreg %lhs, i128 inreg %rhs) { ; GFX11-NEXT: v_cndmask_b32_e64 v3, 0, 1, s2 ; GFX11-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc_lo ; GFX11-NEXT: v_cmp_ne_u32_e64 vcc_lo, 0, s1 -; GFX11-NEXT: s_add_u32 s1, s0, 0x80000000 +; GFX11-NEXT: s_add_i32 s1, s0, 0x80000000 ; GFX11-NEXT: v_dual_cndmask_b32 v1, v3, v2 :: v_dual_mov_b32 v2, s9 ; GFX11-NEXT: v_mov_b32_e32 v3, s11 ; GFX11-NEXT: v_xor_b32_e32 v0, v1, v0 @@ -5427,9 +5426,8 @@ define amdgpu_ps <4 x float> @ssubsat_i128_sv(i128 inreg %lhs, i128 %rhs) { ; GFX9-NEXT: v_ashrrev_i32_e32 v2, 31, v7 ; GFX9-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc ; GFX9-NEXT: v_xor_b32_e32 v0, v0, v8 -; GFX9-NEXT: v_bfrev_b32_e32 v1, 1 -; GFX9-NEXT: v_add_co_u32_e32 v3, vcc, v2, v1 ; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_add_u32_e32 v3, 0x80000000, v2 ; GFX9-NEXT: v_cmp_ne_u32_e32 vcc, 0, v0 ; GFX9-NEXT: v_cndmask_b32_e32 v0, v4, v2, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v5, v2, vcc @@ -5456,7 +5454,7 @@ define amdgpu_ps <4 x float> @ssubsat_i128_sv(i128 inreg %lhs, i128 %rhs) { ; GFX10-NEXT: v_cmp_eq_u64_e32 vcc_lo, 0, v[2:3] ; GFX10-NEXT: v_ashrrev_i32_e32 v2, 31, v7 ; GFX10-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc_lo -; GFX10-NEXT: v_add_co_u32 v3, s0, 0x80000000, v2 +; GFX10-NEXT: v_add_nc_u32_e32 v3, 0x80000000, v2 ; GFX10-NEXT: v_xor_b32_e32 v0, v0, v8 ; GFX10-NEXT: v_and_b32_e32 v0, 1, v0 ; GFX10-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v0 @@ -5484,8 +5482,7 @@ define amdgpu_ps <4 x float> @ssubsat_i128_sv(i128 inreg %lhs, i128 %rhs) { ; GFX11-NEXT: v_cndmask_b32_e32 v8, v9, v8, vcc_lo ; GFX11-NEXT: v_cmp_eq_u64_e32 vcc_lo, 0, v[2:3] ; GFX11-NEXT: v_ashrrev_i32_e32 v2, 31, v7 -; GFX11-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc_lo -; GFX11-NEXT: v_add_co_u32 v3, null, 0x80000000, v2 +; GFX11-NEXT: v_dual_cndmask_b32 v0, v1, v0 :: v_dual_add_nc_u32 v3, 0x80000000, v2 ; GFX11-NEXT: v_xor_b32_e32 v0, v0, v8 ; GFX11-NEXT: v_and_b32_e32 v0, 1, v0 ; GFX11-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v0 @@ -5594,9 +5591,8 @@ define amdgpu_ps <4 x float> @ssubsat_i128_vs(i128 %lhs, i128 inreg %rhs) { ; GFX9-NEXT: v_cndmask_b32_e32 v1, v2, v1, vcc ; GFX9-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX9-NEXT: v_ashrrev_i32_e32 v2, 31, v7 -; GFX9-NEXT: v_bfrev_b32_e32 v1, 1 -; GFX9-NEXT: v_add_co_u32_e32 v3, vcc, v2, v1 ; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_add_u32_e32 v3, 0x80000000, v2 ; GFX9-NEXT: v_cmp_ne_u32_e32 vcc, 0, v0 ; GFX9-NEXT: v_cndmask_b32_e32 v0, v4, v2, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v5, v2, vcc @@ -5625,7 +5621,7 @@ define amdgpu_ps <4 x float> @ssubsat_i128_vs(i128 %lhs, i128 inreg %rhs) { ; GFX10-NEXT: v_ashrrev_i32_e32 v2, 31, v7 ; GFX10-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc_lo ; GFX10-NEXT: v_cmp_ne_u32_e64 vcc_lo, 0, s0 -; GFX10-NEXT: v_add_co_u32 v3, s0, 0x80000000, v2 +; GFX10-NEXT: v_add_nc_u32_e32 v3, 0x80000000, v2 ; GFX10-NEXT: v_cndmask_b32_e32 v1, v9, v8, vcc_lo ; GFX10-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX10-NEXT: v_and_b32_e32 v0, 1, v0 @@ -5652,12 +5648,12 @@ define amdgpu_ps <4 x float> @ssubsat_i128_vs(i128 %lhs, i128 inreg %rhs) { ; GFX11-NEXT: v_cmp_gt_i64_e64 s0, s[2:3], 0 ; GFX11-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc_lo ; GFX11-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[6:7], v[2:3] -; GFX11-NEXT: v_ashrrev_i32_e32 v2, 31, v7 ; GFX11-NEXT: v_cndmask_b32_e64 v9, 0, 1, s0 ; GFX11-NEXT: s_and_b32 s0, 1, s4 -; GFX11-NEXT: v_add_co_u32 v3, null, 0x80000000, v2 +; GFX11-NEXT: v_ashrrev_i32_e32 v2, 31, v7 ; GFX11-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc_lo ; GFX11-NEXT: v_cmp_ne_u32_e64 vcc_lo, 0, s0 +; GFX11-NEXT: v_add_nc_u32_e32 v3, 0x80000000, v2 ; GFX11-NEXT: v_cndmask_b32_e32 v1, v9, v8, vcc_lo ; GFX11-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX11-NEXT: v_and_b32_e32 v0, 1, v0 @@ -5805,9 +5801,8 @@ define <2 x i128> @v_ssubsat_v2i128(<2 x i128> %lhs, <2 x i128> %rhs) { ; GFX9-NEXT: v_cndmask_b32_e32 v1, v2, v1, vcc ; GFX9-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX9-NEXT: v_ashrrev_i32_e32 v2, 31, v19 -; GFX9-NEXT: v_bfrev_b32_e32 v1, 1 -; GFX9-NEXT: v_add_co_u32_e32 v3, vcc, v2, v1 ; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_add_u32_e32 v3, 0x80000000, v2 ; GFX9-NEXT: v_cmp_ne_u32_e32 vcc, 0, v0 ; GFX9-NEXT: v_cndmask_b32_e32 v0, v16, v2, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v1, v17, v2, vcc @@ -5831,8 +5826,8 @@ define <2 x i128> @v_ssubsat_v2i128(<2 x i128> %lhs, <2 x i128> %rhs) { ; GFX9-NEXT: v_cndmask_b32_e32 v5, v6, v5, vcc ; GFX9-NEXT: v_xor_b32_e32 v4, v5, v4 ; GFX9-NEXT: v_ashrrev_i32_e32 v6, 31, v11 -; GFX9-NEXT: v_add_co_u32_e32 v7, vcc, 0x80000000, v6 ; GFX9-NEXT: v_and_b32_e32 v4, 1, v4 +; GFX9-NEXT: v_add_u32_e32 v7, 0x80000000, v6 ; GFX9-NEXT: v_cmp_ne_u32_e32 vcc, 0, v4 ; GFX9-NEXT: v_cndmask_b32_e32 v4, v8, v6, vcc ; GFX9-NEXT: v_cndmask_b32_e32 v5, v9, v6, vcc @@ -5877,18 +5872,18 @@ define <2 x i128> @v_ssubsat_v2i128(<2 x i128> %lhs, <2 x i128> %rhs) { ; GFX10-NEXT: v_ashrrev_i32_e32 v6, 31, v21 ; GFX10-NEXT: v_cndmask_b32_e32 v1, v3, v2, vcc_lo ; GFX10-NEXT: v_cmp_eq_u64_e32 vcc_lo, 0, v[14:15] -; GFX10-NEXT: v_ashrrev_i32_e32 v3, 31, v19 -; GFX10-NEXT: v_add_co_u32 v7, s5, 0x80000000, v6 +; GFX10-NEXT: v_add_nc_u32_e32 v7, 0x80000000, v6 ; GFX10-NEXT: v_cndmask_b32_e32 v2, v5, v4, vcc_lo -; GFX10-NEXT: v_add_co_u32 v4, s4, 0x80000000, v3 ; GFX10-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v0 ; GFX10-NEXT: v_xor_b32_e32 v1, v2, v1 -; GFX10-NEXT: v_cndmask_b32_e32 v0, v16, v3, vcc_lo -; GFX10-NEXT: v_cndmask_b32_e32 v2, v18, v3, vcc_lo -; GFX10-NEXT: v_and_b32_e32 v5, 1, v1 -; GFX10-NEXT: v_cndmask_b32_e32 v1, v17, v3, vcc_lo +; GFX10-NEXT: v_ashrrev_i32_e32 v2, 31, v19 +; GFX10-NEXT: v_and_b32_e32 v3, 1, v1 +; GFX10-NEXT: v_add_nc_u32_e32 v4, 0x80000000, v2 +; GFX10-NEXT: v_cndmask_b32_e32 v0, v16, v2, vcc_lo +; GFX10-NEXT: v_cndmask_b32_e32 v1, v17, v2, vcc_lo +; GFX10-NEXT: v_cndmask_b32_e32 v2, v18, v2, vcc_lo +; GFX10-NEXT: v_cmp_ne_u32_e64 s4, 0, v3 ; GFX10-NEXT: v_cndmask_b32_e32 v3, v19, v4, vcc_lo -; GFX10-NEXT: v_cmp_ne_u32_e64 s4, 0, v5 ; GFX10-NEXT: v_cndmask_b32_e64 v4, v8, v6, s4 ; GFX10-NEXT: v_cndmask_b32_e64 v5, v9, v6, s4 ; GFX10-NEXT: v_cndmask_b32_e64 v6, v20, v6, s4 @@ -5931,18 +5926,16 @@ define <2 x i128> @v_ssubsat_v2i128(<2 x i128> %lhs, <2 x i128> %rhs) { ; GFX11-NEXT: v_ashrrev_i32_e32 v6, 31, v21 ; GFX11-NEXT: v_cndmask_b32_e32 v1, v3, v2, vcc_lo ; GFX11-NEXT: v_cmp_eq_u64_e32 vcc_lo, 0, v[14:15] -; GFX11-NEXT: v_ashrrev_i32_e32 v3, 31, v19 +; GFX11-NEXT: v_dual_cndmask_b32 v2, v5, v4 :: v_dual_add_nc_u32 v7, 0x80000000, v6 +; GFX11-NEXT: v_xor_b32_e32 v1, v2, v1 +; GFX11-NEXT: v_ashrrev_i32_e32 v2, 31, v19 ; GFX11-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX11-NEXT: v_add_co_u32 v7, null, 0x80000000, v6 -; GFX11-NEXT: v_cndmask_b32_e32 v2, v5, v4, vcc_lo +; GFX11-NEXT: v_add_nc_u32_e32 v4, 0x80000000, v2 ; GFX11-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v0 -; GFX11-NEXT: v_add_co_u32 v4, null, 0x80000000, v3 -; GFX11-NEXT: v_xor_b32_e32 v1, v2, v1 -; GFX11-NEXT: v_cndmask_b32_e32 v0, v16, v3, vcc_lo -; GFX11-NEXT: v_dual_cndmask_b32 v2, v18, v3 :: v_dual_and_b32 v5, 1, v1 -; GFX11-NEXT: v_cndmask_b32_e32 v1, v17, v3, vcc_lo -; GFX11-NEXT: v_cndmask_b32_e32 v3, v19, v4, vcc_lo -; GFX11-NEXT: v_cmp_ne_u32_e64 s0, 0, v5 +; GFX11-NEXT: v_dual_cndmask_b32 v0, v16, v2 :: v_dual_and_b32 v3, 1, v1 +; GFX11-NEXT: v_cmp_ne_u32_e64 s0, 0, v3 +; GFX11-NEXT: v_cndmask_b32_e32 v1, v17, v2, vcc_lo +; GFX11-NEXT: v_dual_cndmask_b32 v2, v18, v2 :: v_dual_cndmask_b32 v3, v19, v4 ; GFX11-NEXT: v_cndmask_b32_e64 v4, v8, v6, s0 ; GFX11-NEXT: v_cndmask_b32_e64 v5, v9, v6, s0 ; GFX11-NEXT: v_cndmask_b32_e64 v6, v20, v6, s0 @@ -5978,7 +5971,7 @@ define amdgpu_ps <2 x i128> @s_ssubsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX6-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX6-NEXT: s_ashr_i32 s0, s19, 31 ; GFX6-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX6-NEXT: s_add_u32 s1, s0, 0x80000000 +; GFX6-NEXT: s_add_i32 s1, s0, 0x80000000 ; GFX6-NEXT: v_mov_b32_e32 v1, s0 ; GFX6-NEXT: v_mov_b32_e32 v2, s16 ; GFX6-NEXT: v_mov_b32_e32 v3, s17 @@ -6013,7 +6006,7 @@ define amdgpu_ps <2 x i128> @s_ssubsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX6-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX6-NEXT: s_ashr_i32 s4, s3, 31 ; GFX6-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX6-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX6-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX6-NEXT: v_mov_b32_e32 v1, s4 ; GFX6-NEXT: v_mov_b32_e32 v2, s0 ; GFX6-NEXT: v_mov_b32_e32 v3, s1 @@ -6066,7 +6059,7 @@ define amdgpu_ps <2 x i128> @s_ssubsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX8-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX8-NEXT: s_ashr_i32 s0, s19, 31 ; GFX8-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX8-NEXT: s_add_u32 s1, s0, 0x80000000 +; GFX8-NEXT: s_add_i32 s1, s0, 0x80000000 ; GFX8-NEXT: v_mov_b32_e32 v1, s0 ; GFX8-NEXT: v_mov_b32_e32 v2, s16 ; GFX8-NEXT: v_mov_b32_e32 v3, s17 @@ -6107,7 +6100,7 @@ define amdgpu_ps <2 x i128> @s_ssubsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX8-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX8-NEXT: s_ashr_i32 s4, s3, 31 ; GFX8-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX8-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX8-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX8-NEXT: v_mov_b32_e32 v1, s4 ; GFX8-NEXT: v_mov_b32_e32 v2, s0 ; GFX8-NEXT: v_mov_b32_e32 v3, s1 @@ -6160,7 +6153,7 @@ define amdgpu_ps <2 x i128> @s_ssubsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX9-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX9-NEXT: s_ashr_i32 s0, s19, 31 ; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX9-NEXT: s_add_u32 s1, s0, 0x80000000 +; GFX9-NEXT: s_add_i32 s1, s0, 0x80000000 ; GFX9-NEXT: v_mov_b32_e32 v1, s0 ; GFX9-NEXT: v_mov_b32_e32 v2, s16 ; GFX9-NEXT: v_mov_b32_e32 v3, s17 @@ -6201,7 +6194,7 @@ define amdgpu_ps <2 x i128> @s_ssubsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX9-NEXT: v_xor_b32_e32 v0, v1, v0 ; GFX9-NEXT: s_ashr_i32 s4, s3, 31 ; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 -; GFX9-NEXT: s_add_u32 s5, s4, 0x80000000 +; GFX9-NEXT: s_add_i32 s5, s4, 0x80000000 ; GFX9-NEXT: v_mov_b32_e32 v1, s4 ; GFX9-NEXT: v_mov_b32_e32 v2, s0 ; GFX9-NEXT: v_mov_b32_e32 v3, s1 @@ -6244,7 +6237,7 @@ define amdgpu_ps <2 x i128> @s_ssubsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX10-NEXT: s_cselect_b32 s1, 1, 0 ; GFX10-NEXT: s_ashr_i32 s8, s17, 31 ; GFX10-NEXT: s_and_b32 s1, 1, s1 -; GFX10-NEXT: s_add_u32 s9, s8, 0x80000000 +; GFX10-NEXT: s_add_i32 s9, s8, 0x80000000 ; GFX10-NEXT: v_cndmask_b32_e64 v3, 0, 1, s2 ; GFX10-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc_lo ; GFX10-NEXT: v_cmp_ne_u32_e64 vcc_lo, 0, s1 @@ -6273,7 +6266,7 @@ define amdgpu_ps <2 x i128> @s_ssubsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX10-NEXT: s_cselect_b32 s5, 1, 0 ; GFX10-NEXT: s_ashr_i32 s4, s3, 31 ; GFX10-NEXT: s_and_b32 s5, 1, s5 -; GFX10-NEXT: s_add_u32 s0, s4, 0x80000000 +; GFX10-NEXT: s_add_i32 s0, s4, 0x80000000 ; GFX10-NEXT: v_cndmask_b32_e64 v4, 0, 1, s6 ; GFX10-NEXT: v_cndmask_b32_e32 v1, v2, v1, vcc_lo ; GFX10-NEXT: v_cmp_ne_u32_e64 vcc_lo, 0, s5 @@ -6326,7 +6319,7 @@ define amdgpu_ps <2 x i128> @s_ssubsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX11-NEXT: s_cselect_b32 s1, 1, 0 ; GFX11-NEXT: s_ashr_i32 s8, s19, 31 ; GFX11-NEXT: s_and_b32 s1, 1, s1 -; GFX11-NEXT: s_add_u32 s9, s8, 0x80000000 +; GFX11-NEXT: s_add_i32 s9, s8, 0x80000000 ; GFX11-NEXT: v_cndmask_b32_e64 v3, 0, 1, s2 ; GFX11-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc_lo ; GFX11-NEXT: v_cmp_ne_u32_e64 vcc_lo, 0, s1 @@ -6357,7 +6350,7 @@ define amdgpu_ps <2 x i128> @s_ssubsat_v2i128(<2 x i128> inreg %lhs, <2 x i128> ; GFX11-NEXT: v_cndmask_b32_e32 v1, v2, v1, vcc_lo ; GFX11-NEXT: v_cndmask_b32_e64 v4, 0, 1, s6 ; GFX11-NEXT: v_cmp_ne_u32_e64 vcc_lo, 0, s5 -; GFX11-NEXT: s_add_u32 s0, s4, 0x80000000 +; GFX11-NEXT: s_add_i32 s0, s4, 0x80000000 ; GFX11-NEXT: v_dual_cndmask_b32 v2, v4, v3 :: v_dual_mov_b32 v3, s16 ; GFX11-NEXT: v_cmp_ne_u32_e32 vcc_lo, 0, v0 ; GFX11-NEXT: v_mov_b32_e32 v0, s18 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/udiv.i64.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/udiv.i64.ll index 887c43f5fce59ee69a34317301a7fb60bac81879..d15551365707b17c6d05d3041b8b84bc7ccd81da 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/udiv.i64.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/udiv.i64.ll @@ -2062,13 +2062,9 @@ define <2 x i64> @v_udiv_v2i64_24bit(<2 x i64> %num, <2 x i64> %den) { ; GISEL-NEXT: v_mul_hi_u32 v17, v2, v5 ; GISEL-NEXT: v_mul_hi_u32 v5, 0, v5 ; GISEL-NEXT: v_add_i32_e32 v8, vcc, v8, v12 -; GISEL-NEXT: v_cndmask_b32_e64 v12, 0, 1, vcc ; GISEL-NEXT: v_add_i32_e32 v6, vcc, v13, v6 -; GISEL-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc ; GISEL-NEXT: v_add_i32_e32 v10, vcc, v10, v15 -; GISEL-NEXT: v_cndmask_b32_e64 v15, 0, 1, vcc ; GISEL-NEXT: v_add_i32_e32 v7, vcc, v16, v7 -; GISEL-NEXT: v_cndmask_b32_e64 v16, 0, 1, vcc ; GISEL-NEXT: v_add_i32_e32 v8, vcc, v8, v9 ; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc ; GISEL-NEXT: v_add_i32_e32 v6, vcc, v6, v14 @@ -2077,10 +2073,6 @@ define <2 x i64> @v_udiv_v2i64_24bit(<2 x i64> %num, <2 x i64> %den) { ; GISEL-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc ; GISEL-NEXT: v_add_i32_e32 v7, vcc, v7, v17 ; GISEL-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v8, vcc, v12, v8 -; GISEL-NEXT: v_add_i32_e32 v9, vcc, v13, v9 -; GISEL-NEXT: v_add_i32_e32 v10, vcc, v15, v10 -; GISEL-NEXT: v_add_i32_e32 v11, vcc, v16, v11 ; GISEL-NEXT: v_add_i32_e32 v6, vcc, v6, v8 ; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc ; GISEL-NEXT: v_add_i32_e32 v7, vcc, v7, v10 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/urem.i64.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/urem.i64.ll index 5c6bb6dea1646624e29b819d156f5f0a5215edb3..07480a0ce0c2e7140b1a5bab99857f7f49c51ada 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/urem.i64.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/urem.i64.ll @@ -2480,13 +2480,9 @@ define <2 x i64> @v_urem_v2i64_24bit(<2 x i64> %num, <2 x i64> %den) { ; GISEL-NEXT: v_mul_hi_u32 v17, v2, v5 ; GISEL-NEXT: v_mul_hi_u32 v5, 0, v5 ; GISEL-NEXT: v_add_i32_e32 v8, vcc, v8, v12 -; GISEL-NEXT: v_cndmask_b32_e64 v12, 0, 1, vcc ; GISEL-NEXT: v_add_i32_e32 v6, vcc, v13, v6 -; GISEL-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc ; GISEL-NEXT: v_add_i32_e32 v10, vcc, v10, v15 -; GISEL-NEXT: v_cndmask_b32_e64 v15, 0, 1, vcc ; GISEL-NEXT: v_add_i32_e32 v7, vcc, v16, v7 -; GISEL-NEXT: v_cndmask_b32_e64 v16, 0, 1, vcc ; GISEL-NEXT: v_add_i32_e32 v8, vcc, v8, v9 ; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc ; GISEL-NEXT: v_add_i32_e32 v6, vcc, v6, v14 @@ -2495,10 +2491,6 @@ define <2 x i64> @v_urem_v2i64_24bit(<2 x i64> %num, <2 x i64> %den) { ; GISEL-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc ; GISEL-NEXT: v_add_i32_e32 v7, vcc, v7, v17 ; GISEL-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc -; GISEL-NEXT: v_add_i32_e32 v8, vcc, v12, v8 -; GISEL-NEXT: v_add_i32_e32 v9, vcc, v13, v9 -; GISEL-NEXT: v_add_i32_e32 v10, vcc, v15, v10 -; GISEL-NEXT: v_add_i32_e32 v11, vcc, v16, v11 ; GISEL-NEXT: v_add_i32_e32 v6, vcc, v6, v8 ; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc ; GISEL-NEXT: v_add_i32_e32 v7, vcc, v7, v10 diff --git a/llvm/test/CodeGen/AMDGPU/add_sub_u64_pseudos.mir b/llvm/test/CodeGen/AMDGPU/add_sub_u64_pseudos.mir new file mode 100644 index 0000000000000000000000000000000000000000..cba114c3568a50de883aee4cfb479063f9f91b4f --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/add_sub_u64_pseudos.mir @@ -0,0 +1,68 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=amdgcn -mcpu=gfx1100 -run-pass=finalize-isel -o - %s | FileCheck -check-prefix=GFX11 %s +# RUN: llc -mtriple=amdgcn -mcpu=gfx1200 -run-pass=finalize-isel -o - %s | FileCheck -check-prefix=GFX12 %s + +--- +name: reg_ops +tracksRegLiveness: true +body: | + bb.0: + ; GFX11-LABEL: name: reg_ops + ; GFX11: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF + ; GFX11-NEXT: [[DEF1:%[0-9]+]]:sreg_64 = IMPLICIT_DEF + ; GFX11-NEXT: [[COPY:%[0-9]+]]:sreg_32 = COPY [[DEF]].sub0 + ; GFX11-NEXT: [[COPY1:%[0-9]+]]:sreg_32 = COPY [[DEF]].sub1 + ; GFX11-NEXT: [[COPY2:%[0-9]+]]:sreg_32 = COPY [[DEF1]].sub0 + ; GFX11-NEXT: [[COPY3:%[0-9]+]]:sreg_32 = COPY [[DEF1]].sub1 + ; GFX11-NEXT: [[S_ADD_U32_:%[0-9]+]]:sreg_32 = S_ADD_U32 [[COPY]], [[COPY2]], implicit-def $scc + ; GFX11-NEXT: [[S_ADDC_U32_:%[0-9]+]]:sreg_32 = S_ADDC_U32 [[COPY1]], [[COPY3]], implicit-def $scc, implicit $scc + ; GFX11-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[S_ADD_U32_]], %subreg.sub0, [[S_ADDC_U32_]], %subreg.sub1 + ; + ; GFX12-LABEL: name: reg_ops + ; GFX12: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF + ; GFX12-NEXT: [[DEF1:%[0-9]+]]:sreg_64 = IMPLICIT_DEF + ; GFX12-NEXT: [[S_ADD_U64_:%[0-9]+]]:sreg_64 = S_ADD_U64 [[DEF]], [[DEF1]] + %0:sreg_64 = IMPLICIT_DEF + %1:sreg_64 = IMPLICIT_DEF + %2:sreg_64 = S_ADD_U64_PSEUDO %0, %1, implicit-def $scc +... + +--- +name: lhs_imm +tracksRegLiveness: true +body: | + bb.0: + ; GFX11-LABEL: name: lhs_imm + ; GFX11: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF + ; GFX11-NEXT: [[COPY:%[0-9]+]]:sreg_32 = COPY [[DEF]].sub0 + ; GFX11-NEXT: [[COPY1:%[0-9]+]]:sreg_32 = COPY [[DEF]].sub1 + ; GFX11-NEXT: [[S_ADD_U32_:%[0-9]+]]:sreg_32 = S_ADD_U32 6565, [[COPY]], implicit-def $scc + ; GFX11-NEXT: [[S_ADDC_U32_:%[0-9]+]]:sreg_32 = S_ADDC_U32 0, [[COPY1]], implicit-def $scc, implicit $scc + ; GFX11-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[S_ADD_U32_]], %subreg.sub0, [[S_ADDC_U32_]], %subreg.sub1 + ; + ; GFX12-LABEL: name: lhs_imm + ; GFX12: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF + ; GFX12-NEXT: [[S_ADD_U64_:%[0-9]+]]:sreg_64 = S_ADD_U64 6565, [[DEF]] + %0:sreg_64 = IMPLICIT_DEF + %1:sreg_64 = S_ADD_U64_PSEUDO 6565, %0, implicit-def $scc +... + +--- +name: rhs_imm +tracksRegLiveness: true +body: | + bb.0: + ; GFX11-LABEL: name: rhs_imm + ; GFX11: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF + ; GFX11-NEXT: [[COPY:%[0-9]+]]:sreg_32 = COPY [[DEF]].sub0 + ; GFX11-NEXT: [[COPY1:%[0-9]+]]:sreg_32 = COPY [[DEF]].sub1 + ; GFX11-NEXT: [[S_ADD_U32_:%[0-9]+]]:sreg_32 = S_ADD_U32 [[COPY]], 6565, implicit-def $scc + ; GFX11-NEXT: [[S_ADDC_U32_:%[0-9]+]]:sreg_32 = S_ADDC_U32 [[COPY1]], 0, implicit-def $scc, implicit $scc + ; GFX11-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[S_ADD_U32_]], %subreg.sub0, [[S_ADDC_U32_]], %subreg.sub1 + ; + ; GFX12-LABEL: name: rhs_imm + ; GFX12: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF + ; GFX12-NEXT: [[S_ADD_U64_:%[0-9]+]]:sreg_64 = S_ADD_U64 [[DEF]], 6565 + %0:sreg_64 = IMPLICIT_DEF + %1:sreg_64 = S_ADD_U64_PSEUDO %0, 6565, implicit-def $scc +... diff --git a/llvm/test/CodeGen/AMDGPU/addrspacecast-constantexpr.ll b/llvm/test/CodeGen/AMDGPU/addrspacecast-constantexpr.ll index 66034af5c351fd9f4501678e2a76bd176fda6376..cff9ce050667938fecdce8bf17dec4797818b0df 100644 --- a/llvm/test/CodeGen/AMDGPU/addrspacecast-constantexpr.ll +++ b/llvm/test/CodeGen/AMDGPU/addrspacecast-constantexpr.ll @@ -233,9 +233,9 @@ attributes #1 = { nounwind } ; AKF_HSA: attributes #[[ATTR1]] = { nounwind } ;. ; ATTRIBUTOR_HSA: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } -; ATTRIBUTOR_HSA: attributes #[[ATTR1]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR2]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR3]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR1]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR2]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR3]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } ;. ; AKF_HSA: [[META0:![0-9]+]] = !{i32 1, !"amdhsa_code_object_version", i32 500} ;. diff --git a/llvm/test/CodeGen/AMDGPU/allow-check.ll b/llvm/test/CodeGen/AMDGPU/allow-check.ll new file mode 100644 index 0000000000000000000000000000000000000000..d4f5621ce26a4b7fe644e1711d89c10c76306a35 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/allow-check.ll @@ -0,0 +1,30 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=amdgcn-amd-mesa3d -global-isel=0 -fast-isel=0 | FileCheck %s +; RUN: llc < %s -mtriple=amdgcn-amd-mesa3d -global-isel=1 -fast-isel=0 | FileCheck %s +; RUN: llc < %s -mtriple=amdgcn-amd-mesa3d -global-isel=0 -fast-isel=1 | FileCheck %s + +define i1 @test_runtime() local_unnamed_addr { +; CHECK-LABEL: test_runtime: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_mov_b32_e32 v0, 1 +; CHECK-NEXT: s_setpc_b64 s[30:31] +entry: + %allow = call i1 @llvm.allow.runtime.check(metadata !"test_check") + ret i1 %allow +} + +declare i1 @llvm.allow.runtime.check(metadata) nounwind + +define i1 @test_ubsan() local_unnamed_addr { +; CHECK-LABEL: test_ubsan: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_mov_b32_e32 v0, 1 +; CHECK-NEXT: s_setpc_b64 s[30:31] +entry: + %allow = call i1 @llvm.allow.ubsan.check(i8 7) + ret i1 %allow +} + +declare i1 @llvm.allow.ubsan.check(i8) nounwind diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-attributor-no-agpr.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-attributor-no-agpr.ll new file mode 100644 index 0000000000000000000000000000000000000000..33b1cc65dc569956964a7a76c162e97b2d46ee3a --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-attributor-no-agpr.ll @@ -0,0 +1,255 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --check-globals all --version 4 +; RUN: opt -S -mtriple=amdgcn-unknown-amdhsa -mcpu=gfx90a -passes=amdgpu-attributor %s | FileCheck %s + +define amdgpu_kernel void @kernel_uses_asm_virtreg() { +; CHECK-LABEL: define amdgpu_kernel void @kernel_uses_asm_virtreg( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: call void asm sideeffect " +; CHECK-NEXT: ret void +; + call void asm sideeffect "; use $0", "a"(i32 poison) + ret void +} + +define amdgpu_kernel void @kernel_uses_asm_virtreg_def() { +; CHECK-LABEL: define amdgpu_kernel void @kernel_uses_asm_virtreg_def( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: [[DEF:%.*]] = call i32 asm sideeffect " +; CHECK-NEXT: ret void +; + %def = call i32 asm sideeffect "; def $0", "=a"() + ret void +} + +define amdgpu_kernel void @kernel_uses_asm_physreg_def_tuple() { +; CHECK-LABEL: define amdgpu_kernel void @kernel_uses_asm_physreg_def_tuple( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: [[DEF:%.*]] = call i64 asm sideeffect " +; CHECK-NEXT: ret void +; + %def = call i64 asm sideeffect "; def $0", "={a[0:1]}"() + ret void +} + +define amdgpu_kernel void @kernel_uses_asm_virtreg_second_arg() { +; CHECK-LABEL: define amdgpu_kernel void @kernel_uses_asm_virtreg_second_arg( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: call void asm sideeffect " +; CHECK-NEXT: ret void +; + call void asm sideeffect "; use $0", "v,a"(i32 poison, i32 poison) + ret void +} + +define amdgpu_kernel void @kernel_uses_non_agpr_asm() { +; CHECK-LABEL: define amdgpu_kernel void @kernel_uses_non_agpr_asm( +; CHECK-SAME: ) #[[ATTR1:[0-9]+]] { +; CHECK-NEXT: call void asm sideeffect " +; CHECK-NEXT: ret void +; + call void asm sideeffect "; use $0", "v"(i32 poison) + ret void +} + +define amdgpu_kernel void @kernel_uses_asm_physreg() { +; CHECK-LABEL: define amdgpu_kernel void @kernel_uses_asm_physreg( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: call void asm sideeffect " +; CHECK-NEXT: ret void +; + call void asm sideeffect "; use $0", "{a0}"(i32 poison) + ret void +} + +define amdgpu_kernel void @kernel_uses_asm_physreg_tuple() { +; CHECK-LABEL: define amdgpu_kernel void @kernel_uses_asm_physreg_tuple( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: call void asm sideeffect " +; CHECK-NEXT: ret void +; + call void asm sideeffect "; use $0", "{a[0:1]}"(i64 poison) + ret void +} + +define void @func_uses_asm_virtreg_agpr() { +; CHECK-LABEL: define void @func_uses_asm_virtreg_agpr( +; CHECK-SAME: ) #[[ATTR2:[0-9]+]] { +; CHECK-NEXT: call void asm sideeffect " +; CHECK-NEXT: ret void +; + call void asm sideeffect "; use $0", "a"(i32 poison) + ret void +} + +define void @func_uses_asm_physreg_agpr() { +; CHECK-LABEL: define void @func_uses_asm_physreg_agpr( +; CHECK-SAME: ) #[[ATTR2]] { +; CHECK-NEXT: call void asm sideeffect " +; CHECK-NEXT: ret void +; + call void asm sideeffect "; use $0", "{a0}"(i32 poison) + ret void +} + +define void @func_uses_asm_physreg_agpr_tuple() { +; CHECK-LABEL: define void @func_uses_asm_physreg_agpr_tuple( +; CHECK-SAME: ) #[[ATTR2]] { +; CHECK-NEXT: call void asm sideeffect " +; CHECK-NEXT: ret void +; + call void asm sideeffect "; use $0", "{a[0:1]}"(i64 poison) + ret void +} + +declare void @unknown() + +define amdgpu_kernel void @kernel_calls_extern() { +; CHECK-LABEL: define amdgpu_kernel void @kernel_calls_extern( +; CHECK-SAME: ) #[[ATTR4:[0-9]+]] { +; CHECK-NEXT: call void @unknown() +; CHECK-NEXT: ret void +; + call void @unknown() + ret void +} + +define amdgpu_kernel void @kernel_calls_extern_marked_callsite() { +; CHECK-LABEL: define amdgpu_kernel void @kernel_calls_extern_marked_callsite( +; CHECK-SAME: ) #[[ATTR4]] { +; CHECK-NEXT: call void @unknown() #[[ATTR9:[0-9]+]] +; CHECK-NEXT: ret void +; + call void @unknown() #0 + ret void +} + +define amdgpu_kernel void @kernel_calls_indirect(ptr %indirect) { +; CHECK-LABEL: define amdgpu_kernel void @kernel_calls_indirect( +; CHECK-SAME: ptr [[INDIRECT:%.*]]) #[[ATTR4]] { +; CHECK-NEXT: call void [[INDIRECT]]() +; CHECK-NEXT: ret void +; + call void %indirect() + ret void +} + +define amdgpu_kernel void @kernel_calls_indirect_marked_callsite(ptr %indirect) { +; CHECK-LABEL: define amdgpu_kernel void @kernel_calls_indirect_marked_callsite( +; CHECK-SAME: ptr [[INDIRECT:%.*]]) #[[ATTR4]] { +; CHECK-NEXT: call void [[INDIRECT]]() #[[ATTR9]] +; CHECK-NEXT: ret void +; + call void %indirect() #0 + ret void +} + +define amdgpu_kernel void @kernel_transitively_uses_agpr_asm() { +; CHECK-LABEL: define amdgpu_kernel void @kernel_transitively_uses_agpr_asm( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: call void @func_uses_asm_physreg_agpr() +; CHECK-NEXT: ret void +; + call void @func_uses_asm_physreg_agpr() + ret void +} + +define void @empty() { +; CHECK-LABEL: define void @empty( +; CHECK-SAME: ) #[[ATTR5:[0-9]+]] { +; CHECK-NEXT: ret void +; + ret void +} + +define void @also_empty() { +; CHECK-LABEL: define void @also_empty( +; CHECK-SAME: ) #[[ATTR5]] { +; CHECK-NEXT: ret void +; + ret void +} + +define amdgpu_kernel void @kernel_calls_empty() { +; CHECK-LABEL: define amdgpu_kernel void @kernel_calls_empty( +; CHECK-SAME: ) #[[ATTR1]] { +; CHECK-NEXT: call void @empty() +; CHECK-NEXT: ret void +; + call void @empty() + ret void +} + +define amdgpu_kernel void @kernel_calls_non_agpr_and_agpr() { +; CHECK-LABEL: define amdgpu_kernel void @kernel_calls_non_agpr_and_agpr( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: call void @empty() +; CHECK-NEXT: call void @func_uses_asm_physreg_agpr() +; CHECK-NEXT: ret void +; + call void @empty() + call void @func_uses_asm_physreg_agpr() + ret void +} + +define amdgpu_kernel void @kernel_calls_generic_intrinsic(ptr %ptr0, ptr %ptr1, i64 %size) { +; CHECK-LABEL: define amdgpu_kernel void @kernel_calls_generic_intrinsic( +; CHECK-SAME: ptr [[PTR0:%.*]], ptr [[PTR1:%.*]], i64 [[SIZE:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[PTR0]], ptr [[PTR1]], i64 [[SIZE]], i1 false) +; CHECK-NEXT: ret void +; + call void @llvm.memcpy.p0.p0.i64(ptr %ptr0, ptr %ptr1, i64 %size, i1 false) + ret void +} + +declare <32 x float> @llvm.amdgcn.mfma.f32.32x32x1f32(float, float, <32 x float>, i32 immarg, i32 immarg, i32 immarg) + +define amdgpu_kernel void @kernel_calls_mfma.f32.32x32x1f32(ptr addrspace(1) %out, float %a, float %b, <32 x float> %c) { +; CHECK-LABEL: define amdgpu_kernel void @kernel_calls_mfma.f32.32x32x1f32( +; CHECK-SAME: ptr addrspace(1) [[OUT:%.*]], float [[A:%.*]], float [[B:%.*]], <32 x float> [[C:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[RESULT:%.*]] = call <32 x float> @llvm.amdgcn.mfma.f32.32x32x1f32(float [[A]], float [[B]], <32 x float> [[C]], i32 0, i32 0, i32 0) +; CHECK-NEXT: store <32 x float> [[RESULT]], ptr addrspace(1) [[OUT]], align 128 +; CHECK-NEXT: ret void +; + %result = call <32 x float> @llvm.amdgcn.mfma.f32.32x32x1f32(float %a, float %b, <32 x float> %c, i32 0, i32 0, i32 0) + store <32 x float> %result, ptr addrspace(1) %out + ret void +} + +define amdgpu_kernel void @kernel_calls_workitem_id_x(ptr addrspace(1) %out) { +; CHECK-LABEL: define amdgpu_kernel void @kernel_calls_workitem_id_x( +; CHECK-SAME: ptr addrspace(1) [[OUT:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: [[RESULT:%.*]] = call i32 @llvm.amdgcn.workitem.id.x() +; CHECK-NEXT: store i32 [[RESULT]], ptr addrspace(1) [[OUT]], align 4 +; CHECK-NEXT: ret void +; + %result = call i32 @llvm.amdgcn.workitem.id.x() + store i32 %result, ptr addrspace(1) %out + ret void +} + +define amdgpu_kernel void @indirect_calls_none_agpr(i1 %cond) { +; CHECK-LABEL: define amdgpu_kernel void @indirect_calls_none_agpr( +; CHECK-SAME: i1 [[COND:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[FPTR:%.*]] = select i1 [[COND]], ptr @empty, ptr @also_empty +; CHECK-NEXT: call void [[FPTR]]() +; CHECK-NEXT: ret void +; + %fptr = select i1 %cond, ptr @empty, ptr @also_empty + call void %fptr() + ret void +} + + +attributes #0 = { "amdgpu-no-agpr" } +;. +; CHECK: attributes #[[ATTR0]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "target-cpu"="gfx90a" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR1]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "target-cpu"="gfx90a" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR2]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,8" "target-cpu"="gfx90a" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR3:[0-9]+]] = { "amdgpu-waves-per-eu"="4,8" "target-cpu"="gfx90a" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR4]] = { "target-cpu"="gfx90a" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR5]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,8" "target-cpu"="gfx90a" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR6:[0-9]+]] = { convergent nocallback nofree nosync nounwind willreturn memory(none) "target-cpu"="gfx90a" } +; CHECK: attributes #[[ATTR7:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) "target-cpu"="gfx90a" } +; CHECK: attributes #[[ATTR8:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) "target-cpu"="gfx90a" } +; CHECK: attributes #[[ATTR9]] = { "amdgpu-no-agpr" } +;. diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-codegenprepare-break-large-phis.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-codegenprepare-break-large-phis.ll index 192bf7c249817be5df41a2c32d97e0a447777dd7..93b9aeac3cd3f3cd011f6db4f902711f41512073 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-codegenprepare-break-large-phis.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-codegenprepare-break-large-phis.ll @@ -1197,3 +1197,54 @@ reallyfinally: store <5 x double> %val, ptr %out, align 1 ret void } + +define amdgpu_kernel void @pr85718(i1 %Bool, ptr %Ptr, <4 x float> %Vec1, <4 x float> %Vec2) { +; OPT-LABEL: @pr85718( +; OPT-NEXT: BB0: +; OPT-NEXT: [[I:%.*]] = insertelement <4 x float> [[VEC1:%.*]], float 4.200000e+01, i1 true +; OPT-NEXT: br label [[BB1:%.*]] +; OPT: BB1: +; OPT-NEXT: [[TMP0:%.*]] = phi float [ [[LARGEPHI_EXTRACTSLICE0:%.*]], [[BB2:%.*]] ], [ [[LARGEPHI_EXTRACTSLICE1:%.*]], [[BB1]] ], [ 0.000000e+00, [[BB0:%.*]] ] +; OPT-NEXT: [[TMP1:%.*]] = phi float [ [[LARGEPHI_EXTRACTSLICE3:%.*]], [[BB2]] ], [ [[LARGEPHI_EXTRACTSLICE4:%.*]], [[BB1]] ], [ 0.000000e+00, [[BB0]] ] +; OPT-NEXT: [[TMP2:%.*]] = phi float [ [[LARGEPHI_EXTRACTSLICE6:%.*]], [[BB2]] ], [ [[LARGEPHI_EXTRACTSLICE7:%.*]], [[BB1]] ], [ 0.000000e+00, [[BB0]] ] +; OPT-NEXT: [[TMP3:%.*]] = phi float [ [[LARGEPHI_EXTRACTSLICE9:%.*]], [[BB2]] ], [ [[LARGEPHI_EXTRACTSLICE10:%.*]], [[BB1]] ], [ 0.000000e+00, [[BB0]] ] +; OPT-NEXT: [[LARGEPHI_INSERTSLICE0:%.*]] = insertelement <4 x float> poison, float [[TMP0]], i64 0 +; OPT-NEXT: [[LARGEPHI_INSERTSLICE1:%.*]] = insertelement <4 x float> [[LARGEPHI_INSERTSLICE0]], float [[TMP1]], i64 1 +; OPT-NEXT: [[LARGEPHI_INSERTSLICE2:%.*]] = insertelement <4 x float> [[LARGEPHI_INSERTSLICE1]], float [[TMP2]], i64 2 +; OPT-NEXT: [[LARGEPHI_INSERTSLICE3:%.*]] = insertelement <4 x float> [[LARGEPHI_INSERTSLICE2]], float [[TMP3]], i64 3 +; OPT-NEXT: store <4 x float> [[LARGEPHI_INSERTSLICE3]], ptr [[PTR:%.*]], align 128 +; OPT-NEXT: [[LARGEPHI_EXTRACTSLICE1]] = extractelement <4 x float> [[VEC2:%.*]], i64 0 +; OPT-NEXT: [[LARGEPHI_EXTRACTSLICE4]] = extractelement <4 x float> [[VEC2]], i64 1 +; OPT-NEXT: [[LARGEPHI_EXTRACTSLICE7]] = extractelement <4 x float> [[VEC2]], i64 2 +; OPT-NEXT: [[LARGEPHI_EXTRACTSLICE10]] = extractelement <4 x float> [[VEC2]], i64 3 +; OPT-NEXT: br i1 [[BOOL:%.*]], label [[BB1]], label [[BB2]] +; OPT: BB2: +; OPT-NEXT: [[LARGEPHI_EXTRACTSLICE0]] = extractelement <4 x float> [[I]], i64 0 +; OPT-NEXT: [[LARGEPHI_EXTRACTSLICE3]] = extractelement <4 x float> [[I]], i64 1 +; OPT-NEXT: [[LARGEPHI_EXTRACTSLICE6]] = extractelement <4 x float> [[I]], i64 2 +; OPT-NEXT: [[LARGEPHI_EXTRACTSLICE9]] = extractelement <4 x float> [[I]], i64 3 +; OPT-NEXT: br label [[BB1]] +; +; NOOPT-LABEL: @pr85718( +; NOOPT-NEXT: BB0: +; NOOPT-NEXT: [[I:%.*]] = insertelement <4 x float> [[VEC1:%.*]], float 4.200000e+01, i1 true +; NOOPT-NEXT: br label [[BB1:%.*]] +; NOOPT: BB1: +; NOOPT-NEXT: [[PHI:%.*]] = phi <4 x float> [ [[I]], [[BB2:%.*]] ], [ [[VEC2:%.*]], [[BB1]] ], [ zeroinitializer, [[BB0:%.*]] ] +; NOOPT-NEXT: store <4 x float> [[PHI]], ptr [[PTR:%.*]], align 128 +; NOOPT-NEXT: br i1 [[BOOL:%.*]], label [[BB1]], label [[BB2]] +; NOOPT: BB2: +; NOOPT-NEXT: br label [[BB1]] +; +BB0: + %I = insertelement <4 x float> %Vec1, float 4.200000e+01, i1 true + br label %BB1 + +BB1: ; preds = %BB0, %BB1, %BB2 + %PHI = phi <4 x float> [ %I, %BB2 ], [ %Vec2, %BB1 ], [ zeroinitializer, %BB0 ] + store <4 x float> %PHI, ptr %Ptr, align 128 + br i1 %Bool, label %BB1, label %BB2 + +BB2: ; preds = %BB1 + br label %BB1 +} diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-codegenprepare-idiv.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-codegenprepare-idiv.ll index d9001656f308e1d49d446cb9bbed85e8aee2b7b9..2ad28b8dd6ecf550349564518ab2b3b9f2fb88b8 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-codegenprepare-idiv.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-codegenprepare-idiv.ll @@ -10668,3 +10668,111 @@ define amdgpu_kernel void @srem_v2i64_pow2_shl_denom(ptr addrspace(1) %out, <2 x store <2 x i64> %r, ptr addrspace(1) %out ret void } + +define <2 x i32> @v_sdiv_i32_exact(<2 x i32> %num) { +; CHECK-LABEL: @v_sdiv_i32_exact( +; CHECK: %1 = extractelement <2 x i32> %num, i64 0 +; CHECK-NEXT: %2 = sdiv exact i32 %1, 4096 +; CHECK-NEXT: %3 = insertelement <2 x i32> poison, i32 %2, i64 0 +; CHECK-NEXT: %4 = extractelement <2 x i32> %num, i64 1 +; CHECK-NEXT: %5 = sdiv exact i32 %4, 1024 +; CHECK-NEXT: %6 = insertelement <2 x i32> %3, i32 %5, i64 1 +; CHECK-NEXT: ret <2 x i32> %6 +; +; GFX6-LABEL: v_sdiv_i32_exact: +; GFX6: ; %bb.0: +; GFX6-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX6-NEXT: v_ashrrev_i32_e32 v0, 12, v0 +; GFX6-NEXT: v_ashrrev_i32_e32 v1, 10, v1 +; GFX6-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: v_sdiv_i32_exact: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_ashrrev_i32_e32 v0, 12, v0 +; GFX9-NEXT: v_ashrrev_i32_e32 v1, 10, v1 +; GFX9-NEXT: s_setpc_b64 s[30:31] + %result = sdiv exact <2 x i32> %num, <i32 4096, i32 1024> + ret <2 x i32> %result +} + +define <2 x i64> @v_sdiv_i64_exact(<2 x i64> %num) { +; CHECK-LABEL: @v_sdiv_i64_exact( +; CHECK: %1 = extractelement <2 x i64> %num, i64 0 +; CHECK-NEXT: %2 = sdiv exact i64 %1, 4096 +; CHECK-NEXT: %3 = insertelement <2 x i64> poison, i64 %2, i64 0 +; CHECK-NEXT: %4 = extractelement <2 x i64> %num, i64 1 +; CHECK-NEXT: %5 = sdiv exact i64 %4, 1024 +; CHECK-NEXT: %6 = insertelement <2 x i64> %3, i64 %5, i64 1 +; CHECK-NEXT: ret <2 x i64> %6 +; +; GFX6-LABEL: v_sdiv_i64_exact: +; GFX6: ; %bb.0: +; GFX6-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX6-NEXT: v_ashr_i64 v[0:1], v[0:1], 12 +; GFX6-NEXT: v_ashr_i64 v[2:3], v[2:3], 10 +; GFX6-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: v_sdiv_i64_exact: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_ashrrev_i64 v[0:1], 12, v[0:1] +; GFX9-NEXT: v_ashrrev_i64 v[2:3], 10, v[2:3] +; GFX9-NEXT: s_setpc_b64 s[30:31] + %result = sdiv exact <2 x i64> %num, <i64 4096, i64 1024> + ret <2 x i64> %result +} + +define <2 x i32> @v_udiv_i32_exact(<2 x i32> %num) { +; CHECK-LABEL: @v_udiv_i32_exact( +; CHECK: %1 = extractelement <2 x i32> %num, i64 0 +; CHECK-NEXT: %2 = udiv exact i32 %1, 4096 +; CHECK-NEXT: %3 = insertelement <2 x i32> poison, i32 %2, i64 0 +; CHECK-NEXT: %4 = extractelement <2 x i32> %num, i64 1 +; CHECK-NEXT: %5 = udiv exact i32 %4, 1024 +; CHECK-NEXT: %6 = insertelement <2 x i32> %3, i32 %5, i64 1 +; CHECK-NEXT: ret <2 x i32> %6 +; +; GFX6-LABEL: v_udiv_i32_exact: +; GFX6: ; %bb.0: +; GFX6-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX6-NEXT: v_lshrrev_b32_e32 v0, 12, v0 +; GFX6-NEXT: v_lshrrev_b32_e32 v1, 10, v1 +; GFX6-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: v_udiv_i32_exact: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_lshrrev_b32_e32 v0, 12, v0 +; GFX9-NEXT: v_lshrrev_b32_e32 v1, 10, v1 +; GFX9-NEXT: s_setpc_b64 s[30:31] + %result = udiv exact <2 x i32> %num, <i32 4096, i32 1024> + ret <2 x i32> %result +} + +define <2 x i64> @v_udiv_i64_exact(<2 x i64> %num) { +; CHECK-LABEL: @v_udiv_i64_exact( +; CHECK: %1 = extractelement <2 x i64> %num, i64 0 +; CHECK-NEXT: %2 = udiv exact i64 %1, 4096 +; CHECK-NEXT: %3 = insertelement <2 x i64> poison, i64 %2, i64 0 +; CHECK-NEXT: %4 = extractelement <2 x i64> %num, i64 1 +; CHECK-NEXT: %5 = udiv exact i64 %4, 1024 +; CHECK-NEXT: %6 = insertelement <2 x i64> %3, i64 %5, i64 1 +; CHECK-NEXT: ret <2 x i64> %6 +; +; GFX6-LABEL: v_udiv_i64_exact: +; GFX6: ; %bb.0: +; GFX6-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX6-NEXT: v_lshr_b64 v[0:1], v[0:1], 12 +; GFX6-NEXT: v_lshr_b64 v[2:3], v[2:3], 10 +; GFX6-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: v_udiv_i64_exact: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_lshrrev_b64 v[0:1], 12, v[0:1] +; GFX9-NEXT: v_lshrrev_b64 v[2:3], 10, v[2:3] +; GFX9-NEXT: s_setpc_b64 s[30:31] + %result = udiv exact <2 x i64> %num, <i64 4096, i64 1024> + ret <2 x i64> %result +} diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll index 942f459ea6b8ca3a6ceee4510be4a595552560bf..8ddaf243db92c4ea5610e99ad616e89aa50ef81b 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll @@ -808,7 +808,7 @@ define float @test_pown_fast_f32_nobuiltin(float %x, i32 %y) { ; CHECK-LABEL: define float @test_pown_fast_f32_nobuiltin ; CHECK-SAME: (float [[X:%.*]], i32 [[Y:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call fast float @_Z4pownfi(float [[X]], i32 [[Y]]) #[[ATTR3:[0-9]+]] +; CHECK-NEXT: [[CALL:%.*]] = tail call fast float @_Z4pownfi(float [[X]], i32 [[Y]]) #[[ATTR4:[0-9]+]] ; CHECK-NEXT: ret float [[CALL]] ; entry: @@ -820,11 +820,11 @@ define float @test_pown_fast_f32_strictfp(float %x, i32 %y) #1 { ; CHECK-LABEL: define float @test_pown_fast_f32_strictfp ; CHECK-SAME: (float [[X:%.*]], i32 [[Y:%.*]]) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[__FABS:%.*]] = call fast float @llvm.fabs.f32(float [[X]]) -; CHECK-NEXT: [[__LOG2:%.*]] = call fast float @llvm.log2.f32(float [[__FABS]]) -; CHECK-NEXT: [[POWNI2F:%.*]] = sitofp i32 [[Y]] to float -; CHECK-NEXT: [[__YLOGX:%.*]] = fmul fast float [[__LOG2]], [[POWNI2F]] -; CHECK-NEXT: [[__EXP2:%.*]] = call fast float @llvm.exp2.f32(float [[__YLOGX]]) +; CHECK-NEXT: [[__FABS:%.*]] = call fast float @llvm.fabs.f32(float [[X]]) #[[ATTR0]] +; CHECK-NEXT: [[__LOG2:%.*]] = call fast float @llvm.log2.f32(float [[__FABS]]) #[[ATTR0]] +; CHECK-NEXT: [[POWNI2F:%.*]] = call fast float @llvm.experimental.constrained.sitofp.f32.i32(i32 [[Y]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] +; CHECK-NEXT: [[__YLOGX:%.*]] = call fast float @llvm.experimental.constrained.fmul.f32(float [[POWNI2F]], float [[__LOG2]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] +; CHECK-NEXT: [[__EXP2:%.*]] = call fast float @llvm.exp2.f32(float [[__YLOGX]]) #[[ATTR0]] ; CHECK-NEXT: [[__YEVEN:%.*]] = shl i32 [[Y]], 31 ; CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]] diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll index 2ffa647d1869a5af1a7573f1d292b19444418313..2e64a3456c2427b862e47ec4d23d31d3dcb29285 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-rootn.ll @@ -896,7 +896,7 @@ define float @test_rootn_f32__y_neg2__strictfp(float %x) #1 { ; CHECK-LABEL: define float @test_rootn_f32__y_neg2__strictfp( ; CHECK-SAME: float [[X:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = call float @_Z5rsqrtf(float [[X]]) +; CHECK-NEXT: [[__ROOTN2RSQRT:%.*]] = call float @_Z5rsqrtf(float [[X]]) #[[ATTR0]] ; CHECK-NEXT: ret float [[__ROOTN2RSQRT]] ; entry: diff --git a/llvm/test/CodeGen/AMDGPU/annotate-kernel-features-hsa-call.ll b/llvm/test/CodeGen/AMDGPU/annotate-kernel-features-hsa-call.ll index af0eb23d8e991bd037a548807c85dce8c24a62dc..3d4ae84d9c698e44ed088ed5799f28e4f3b8d569 100644 --- a/llvm/test/CodeGen/AMDGPU/annotate-kernel-features-hsa-call.ll +++ b/llvm/test/CodeGen/AMDGPU/annotate-kernel-features-hsa-call.ll @@ -1025,33 +1025,33 @@ attributes #6 = { "enqueued-block" } ; AKF_HSA: attributes #[[ATTR8]] = { "amdgpu-calls" } ;. ; ATTRIBUTOR_HSA: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } -; ATTRIBUTOR_HSA: attributes #[[ATTR1]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR2]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR3]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR4]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR5]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR6]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR7]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR8]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR9]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR10]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR11]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR12]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR13]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="gfx900" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR14]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="gfx900" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR15]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "target-cpu"="fiji" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR1]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR2]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR3]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR4]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR5]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR6]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR7]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR8]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR9]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR10]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR11]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR12]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="fiji" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR13]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="gfx900" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR14]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "target-cpu"="gfx900" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR15]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "target-cpu"="fiji" "uniform-work-group-size"="false" } ; ATTRIBUTOR_HSA: attributes #[[ATTR16]] = { nounwind "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR17]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR17]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } ; ATTRIBUTOR_HSA: attributes #[[ATTR18]] = { nounwind "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR19]] = { nounwind sanitize_address "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR20]] = { nounwind sanitize_address "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR21]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR22]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR19]] = { nounwind sanitize_address "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR20]] = { nounwind sanitize_address "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR21]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR22]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } ; ATTRIBUTOR_HSA: attributes #[[ATTR23:[0-9]+]] = { nounwind sanitize_address "amdgpu-no-implicitarg-ptr" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } ; ATTRIBUTOR_HSA: attributes #[[ATTR24:[0-9]+]] = { "amdgpu-waves-per-eu"="4,10" "enqueued-block" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR25]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "enqueued-block" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR25]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "enqueued-block" "uniform-work-group-size"="false" } ; ATTRIBUTOR_HSA: attributes #[[ATTR26]] = { "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR27]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR27]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } ; ATTRIBUTOR_HSA: attributes #[[ATTR28]] = { nounwind } ; ATTRIBUTOR_HSA: attributes #[[ATTR29]] = { "enqueued-block" } ;. diff --git a/llvm/test/CodeGen/AMDGPU/annotate-kernel-features-hsa.ll b/llvm/test/CodeGen/AMDGPU/annotate-kernel-features-hsa.ll index 9a9c28ac632f7df8142d9064a6754c3fc1c902a5..43cdf85ed3818c4c097d6bc7f1cf08f2b90c0fa9 100644 --- a/llvm/test/CodeGen/AMDGPU/annotate-kernel-features-hsa.ll +++ b/llvm/test/CodeGen/AMDGPU/annotate-kernel-features-hsa.ll @@ -643,19 +643,19 @@ attributes #1 = { nounwind } ; AKF_HSA: attributes #[[ATTR2]] = { nounwind "amdgpu-stack-objects" } ;. ; ATTRIBUTOR_HSA: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } -; ATTRIBUTOR_HSA: attributes #[[ATTR1]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR2]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR3]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR4]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR5]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR6]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR7]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR8]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR9]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workitem-id-x" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR10]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR11]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR12]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; ATTRIBUTOR_HSA: attributes #[[ATTR13]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR1]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR2]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR3]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR4]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR5]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR6]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR7]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR8]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR9]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workitem-id-x" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR10]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR11]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR12]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_HSA: attributes #[[ATTR13]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } ;. ; AKF_HSA: [[META0:![0-9]+]] = !{i32 1, !"amdhsa_code_object_version", i32 500} ;. diff --git a/llvm/test/CodeGen/AMDGPU/annotate-kernel-features.ll b/llvm/test/CodeGen/AMDGPU/annotate-kernel-features.ll index 6c5e58c74033945cfbd299101f1a8100ca6f1296..547ff69592ca0ee9b611aaaa0877f704b9bcdd83 100644 --- a/llvm/test/CodeGen/AMDGPU/annotate-kernel-features.ll +++ b/llvm/test/CodeGen/AMDGPU/annotate-kernel-features.ll @@ -393,17 +393,18 @@ define amdgpu_kernel void @use_get_local_size_z(ptr addrspace(1) %ptr) #1 { attributes #0 = { nounwind readnone } attributes #1 = { nounwind } +;. ; AKF_CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } ; AKF_CHECK: attributes #[[ATTR1]] = { nounwind } ;. ; ATTRIBUTOR_CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } -; ATTRIBUTOR_CHECK: attributes #[[ATTR1]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; ATTRIBUTOR_CHECK: attributes #[[ATTR2]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; ATTRIBUTOR_CHECK: attributes #[[ATTR3]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; ATTRIBUTOR_CHECK: attributes #[[ATTR4]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; ATTRIBUTOR_CHECK: attributes #[[ATTR5]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; ATTRIBUTOR_CHECK: attributes #[[ATTR6]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "uniform-work-group-size"="false" } -; ATTRIBUTOR_CHECK: attributes #[[ATTR7]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; ATTRIBUTOR_CHECK: attributes #[[ATTR8]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "uniform-work-group-size"="false" } -; ATTRIBUTOR_CHECK: attributes #[[ATTR9]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workitem-id-x" "uniform-work-group-size"="false" } +; ATTRIBUTOR_CHECK: attributes #[[ATTR1]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_CHECK: attributes #[[ATTR2]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_CHECK: attributes #[[ATTR3]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_CHECK: attributes #[[ATTR4]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_CHECK: attributes #[[ATTR5]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_CHECK: attributes #[[ATTR6]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "uniform-work-group-size"="false" } +; ATTRIBUTOR_CHECK: attributes #[[ATTR7]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; ATTRIBUTOR_CHECK: attributes #[[ATTR8]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "uniform-work-group-size"="false" } +; ATTRIBUTOR_CHECK: attributes #[[ATTR9]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workitem-id-x" "uniform-work-group-size"="false" } ;. diff --git a/llvm/test/CodeGen/AMDGPU/atomic_optimizations_pixelshader.ll b/llvm/test/CodeGen/AMDGPU/atomic_optimizations_pixelshader.ll index 1ebd864e7e03aa95a304f9e561d38397a16d0323..29704959fc1763c3b06e3133a77dd5c001bc7998 100644 --- a/llvm/test/CodeGen/AMDGPU/atomic_optimizations_pixelshader.ll +++ b/llvm/test/CodeGen/AMDGPU/atomic_optimizations_pixelshader.ll @@ -477,7 +477,6 @@ define amdgpu_ps void @add_i32_varying(ptr addrspace(8) inreg %out, ptr addrspac ; GFX1032-NEXT: s_cbranch_execz .LBB1_3 ; GFX1032-NEXT: ; %bb.2: ; GFX1032-NEXT: v_mov_b32_e32 v0, s11 -; GFX1032-NEXT: s_mov_b32 s10, s11 ; GFX1032-NEXT: buffer_atomic_add v0, off, s[4:7], 0 glc ; GFX1032-NEXT: .LBB1_3: ; GFX1032-NEXT: s_waitcnt_depctr 0xffe3 @@ -615,7 +614,6 @@ define amdgpu_ps void @add_i32_varying(ptr addrspace(8) inreg %out, ptr addrspac ; GFX1132-NEXT: s_cbranch_execz .LBB1_3 ; GFX1132-NEXT: ; %bb.2: ; GFX1132-NEXT: v_mov_b32_e32 v0, s11 -; GFX1132-NEXT: s_mov_b32 s10, s11 ; GFX1132-NEXT: buffer_atomic_add_u32 v0, off, s[4:7], 0 glc ; GFX1132-NEXT: .LBB1_3: ; GFX1132-NEXT: s_or_b32 exec_lo, exec_lo, s9 diff --git a/llvm/test/CodeGen/AMDGPU/av_spill_cross_bb_usage.mir b/llvm/test/CodeGen/AMDGPU/av_spill_cross_bb_usage.mir index c1da29ecc2c2f5bf138ae914a77a75a792a092de..3228962ed01f780d72ed69c9b7c757cefe842671 100644 --- a/llvm/test/CodeGen/AMDGPU/av_spill_cross_bb_usage.mir +++ b/llvm/test/CodeGen/AMDGPU/av_spill_cross_bb_usage.mir @@ -14,6 +14,8 @@ --- name: test_av_spill_cross_bb_usage tracksRegLiveness: true +frameInfo: + adjustsStack: true stack: - { id: 0, name: '', type: spill-slot, offset: 0, size: 4, alignment: 4 } machineFunctionInfo: diff --git a/llvm/test/CodeGen/AMDGPU/bf16-conversions.ll b/llvm/test/CodeGen/AMDGPU/bf16-conversions.ll new file mode 100644 index 0000000000000000000000000000000000000000..7108f3d65768cd67eebfdea435af9ddc59bdadba --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/bf16-conversions.ll @@ -0,0 +1,357 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -march=amdgcn -mcpu=gfx940 < %s | FileCheck --check-prefixes=GCN %s + +; TODO: Add global-isel when it can support bf16 + +define amdgpu_ps float @v_test_cvt_bf16_f32_v(bfloat %v) { +; GCN-LABEL: v_test_cvt_bf16_f32_v: +; GCN: ; %bb.0: +; GCN-NEXT: v_lshlrev_b32_e32 v0, 16, v0 +; GCN-NEXT: ; return to shader part epilog + %cvt = fpext bfloat %v to float + ret float %cvt +} + +define amdgpu_ps float @v_test_cvt_bf16_f32_s(bfloat inreg %v) { +; GCN-LABEL: v_test_cvt_bf16_f32_s: +; GCN: ; %bb.0: +; GCN-NEXT: s_lshl_b32 s0, s0, 16 +; GCN-NEXT: v_mov_b32_e32 v0, s0 +; GCN-NEXT: ; return to shader part epilog + %cvt = fpext bfloat %v to float + ret float %cvt +} + +define amdgpu_ps float @v_test_cvt_v2f32_v2bf16_v(<2 x float> %src) { +; GCN-LABEL: v_test_cvt_v2f32_v2bf16_v: +; GCN: ; %bb.0: +; GCN-NEXT: v_bfe_u32 v2, v0, 16, 1 +; GCN-NEXT: s_movk_i32 s0, 0x7fff +; GCN-NEXT: v_add3_u32 v2, v2, v0, s0 +; GCN-NEXT: v_or_b32_e32 v3, 0x400000, v0 +; GCN-NEXT: v_cmp_u_f32_e32 vcc, v0, v0 +; GCN-NEXT: s_nop 1 +; GCN-NEXT: v_cndmask_b32_e32 v0, v2, v3, vcc +; GCN-NEXT: v_bfe_u32 v2, v1, 16, 1 +; GCN-NEXT: v_add3_u32 v2, v2, v1, s0 +; GCN-NEXT: v_or_b32_e32 v3, 0x400000, v1 +; GCN-NEXT: v_cmp_u_f32_e32 vcc, v1, v1 +; GCN-NEXT: s_mov_b32 s0, 0x7060302 +; GCN-NEXT: s_nop 0 +; GCN-NEXT: v_cndmask_b32_e32 v1, v2, v3, vcc +; GCN-NEXT: v_perm_b32 v0, v1, v0, s0 +; GCN-NEXT: ; return to shader part epilog + %res = fptrunc <2 x float> %src to <2 x bfloat> + %cast = bitcast <2 x bfloat> %res to float + ret float %cast +} + +define amdgpu_ps float @v_test_cvt_v2f32_v2bf16_s(<2 x float> inreg %src) { +; GCN-LABEL: v_test_cvt_v2f32_v2bf16_s: +; GCN: ; %bb.0: +; GCN-NEXT: s_bfe_u32 s2, s1, 0x10010 +; GCN-NEXT: s_add_i32 s2, s2, s1 +; GCN-NEXT: s_or_b32 s4, s1, 0x400000 +; GCN-NEXT: s_add_i32 s5, s2, 0x7fff +; GCN-NEXT: v_cmp_u_f32_e64 s[2:3], s1, s1 +; GCN-NEXT: s_and_b64 s[2:3], s[2:3], exec +; GCN-NEXT: s_cselect_b32 s2, s4, s5 +; GCN-NEXT: s_bfe_u32 s1, s0, 0x10010 +; GCN-NEXT: s_add_i32 s1, s1, s0 +; GCN-NEXT: s_or_b32 s3, s0, 0x400000 +; GCN-NEXT: s_add_i32 s4, s1, 0x7fff +; GCN-NEXT: v_cmp_u_f32_e64 s[0:1], s0, s0 +; GCN-NEXT: s_and_b64 s[0:1], s[0:1], exec +; GCN-NEXT: s_cselect_b32 s0, s3, s4 +; GCN-NEXT: s_pack_hh_b32_b16 s0, s0, s2 +; GCN-NEXT: v_mov_b32_e32 v0, s0 +; GCN-NEXT: ; return to shader part epilog + %res = fptrunc <2 x float> %src to <2 x bfloat> + %cast = bitcast <2 x bfloat> %res to float + ret float %cast +} + +define amdgpu_ps float @v_test_cvt_f32_bf16_v(float %src) { +; GCN-LABEL: v_test_cvt_f32_bf16_v: +; GCN: ; %bb.0: +; GCN-NEXT: v_bfe_u32 v1, v0, 16, 1 +; GCN-NEXT: s_movk_i32 s0, 0x7fff +; GCN-NEXT: v_add3_u32 v1, v1, v0, s0 +; GCN-NEXT: v_or_b32_e32 v2, 0x400000, v0 +; GCN-NEXT: v_cmp_u_f32_e32 vcc, v0, v0 +; GCN-NEXT: s_nop 1 +; GCN-NEXT: v_cndmask_b32_e32 v0, v1, v2, vcc +; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 +; GCN-NEXT: ; return to shader part epilog + %trunc = fptrunc float %src to bfloat + %ext = fpext bfloat %trunc to float + ret float %ext +} + +define amdgpu_ps float @v_test_cvt_v2f64_v2bf16_v(<2 x double> %src) { +; GCN-LABEL: v_test_cvt_v2f64_v2bf16_v: +; GCN: ; %bb.0: +; GCN-NEXT: v_cvt_f32_f64_e64 v6, |v[0:1]| +; GCN-NEXT: v_cvt_f64_f32_e32 v[4:5], v6 +; GCN-NEXT: v_and_b32_e32 v7, 1, v6 +; GCN-NEXT: v_cmp_gt_f64_e64 s[2:3], |v[0:1]|, v[4:5] +; GCN-NEXT: v_cmp_nlg_f64_e64 s[0:1], |v[0:1]|, v[4:5] +; GCN-NEXT: v_cmp_eq_u32_e32 vcc, 1, v7 +; GCN-NEXT: v_cndmask_b32_e64 v4, -1, 1, s[2:3] +; GCN-NEXT: v_add_u32_e32 v4, v6, v4 +; GCN-NEXT: s_or_b64 vcc, s[0:1], vcc +; GCN-NEXT: v_cndmask_b32_e32 v4, v4, v6, vcc +; GCN-NEXT: s_brev_b32 s4, 1 +; GCN-NEXT: v_and_or_b32 v5, v1, s4, v4 +; GCN-NEXT: v_bfe_u32 v4, v4, 16, 1 +; GCN-NEXT: s_movk_i32 s5, 0x7fff +; GCN-NEXT: v_add3_u32 v4, v4, v5, s5 +; GCN-NEXT: v_or_b32_e32 v5, 0x400000, v5 +; GCN-NEXT: v_cmp_u_f64_e32 vcc, v[0:1], v[0:1] +; GCN-NEXT: s_nop 1 +; GCN-NEXT: v_cndmask_b32_e32 v4, v4, v5, vcc +; GCN-NEXT: v_cvt_f32_f64_e64 v5, |v[2:3]| +; GCN-NEXT: v_cvt_f64_f32_e32 v[0:1], v5 +; GCN-NEXT: v_and_b32_e32 v6, 1, v5 +; GCN-NEXT: v_cmp_gt_f64_e64 s[2:3], |v[2:3]|, v[0:1] +; GCN-NEXT: v_cmp_nlg_f64_e64 s[0:1], |v[2:3]|, v[0:1] +; GCN-NEXT: v_cmp_eq_u32_e32 vcc, 1, v6 +; GCN-NEXT: v_cndmask_b32_e64 v0, -1, 1, s[2:3] +; GCN-NEXT: v_add_u32_e32 v0, v5, v0 +; GCN-NEXT: s_or_b64 vcc, s[0:1], vcc +; GCN-NEXT: v_cndmask_b32_e32 v0, v0, v5, vcc +; GCN-NEXT: v_and_or_b32 v1, v3, s4, v0 +; GCN-NEXT: v_bfe_u32 v0, v0, 16, 1 +; GCN-NEXT: v_add3_u32 v0, v0, v1, s5 +; GCN-NEXT: v_or_b32_e32 v1, 0x400000, v1 +; GCN-NEXT: v_cmp_u_f64_e32 vcc, v[2:3], v[2:3] +; GCN-NEXT: s_mov_b32 s0, 0x7060302 +; GCN-NEXT: s_nop 0 +; GCN-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc +; GCN-NEXT: v_perm_b32 v0, v0, v4, s0 +; GCN-NEXT: ; return to shader part epilog + %res = fptrunc <2 x double> %src to <2 x bfloat> + %cast = bitcast <2 x bfloat> %res to float + ret float %cast +} + +define amdgpu_ps float @fptrunc_f32_f32_to_v2bf16(float %a, float %b) { +; GCN-LABEL: fptrunc_f32_f32_to_v2bf16: +; GCN: ; %bb.0: ; %entry +; GCN-NEXT: v_bfe_u32 v2, v0, 16, 1 +; GCN-NEXT: s_movk_i32 s0, 0x7fff +; GCN-NEXT: v_add3_u32 v2, v2, v0, s0 +; GCN-NEXT: v_or_b32_e32 v3, 0x400000, v0 +; GCN-NEXT: v_cmp_u_f32_e32 vcc, v0, v0 +; GCN-NEXT: s_nop 1 +; GCN-NEXT: v_cndmask_b32_e32 v0, v2, v3, vcc +; GCN-NEXT: v_bfe_u32 v2, v1, 16, 1 +; GCN-NEXT: v_add3_u32 v2, v2, v1, s0 +; GCN-NEXT: v_or_b32_e32 v3, 0x400000, v1 +; GCN-NEXT: v_cmp_u_f32_e32 vcc, v1, v1 +; GCN-NEXT: s_mov_b32 s0, 0x7060302 +; GCN-NEXT: s_nop 0 +; GCN-NEXT: v_cndmask_b32_e32 v1, v2, v3, vcc +; GCN-NEXT: v_perm_b32 v0, v1, v0, s0 +; GCN-NEXT: ; return to shader part epilog +entry: + %a.cvt = fptrunc float %a to bfloat + %b.cvt = fptrunc float %b to bfloat + %v2.1 = insertelement <2 x bfloat> undef, bfloat %a.cvt, i32 0 + %v2.2 = insertelement <2 x bfloat> %v2.1, bfloat %b.cvt, i32 1 + %ret = bitcast <2 x bfloat> %v2.2 to float + ret float %ret +} + +define amdgpu_ps float @fptrunc_f32_f32_to_v2bf16_mods(float %a, float %b) { +; GCN-LABEL: fptrunc_f32_f32_to_v2bf16_mods: +; GCN: ; %bb.0: ; %entry +; GCN-NEXT: v_xor_b32_e32 v2, 0x80000000, v0 +; GCN-NEXT: v_bfe_u32 v3, v2, 16, 1 +; GCN-NEXT: s_movk_i32 s0, 0x7fff +; GCN-NEXT: v_add3_u32 v3, v3, v2, s0 +; GCN-NEXT: v_or_b32_e32 v2, 0x400000, v2 +; GCN-NEXT: v_cmp_u_f32_e64 vcc, -v0, -v0 +; GCN-NEXT: s_nop 1 +; GCN-NEXT: v_cndmask_b32_e32 v0, v3, v2, vcc +; GCN-NEXT: v_and_b32_e32 v2, 0x7fffffff, v1 +; GCN-NEXT: v_bfe_u32 v3, v2, 16, 1 +; GCN-NEXT: v_add3_u32 v3, v3, v2, s0 +; GCN-NEXT: v_or_b32_e32 v2, 0x400000, v2 +; GCN-NEXT: v_cmp_u_f32_e64 vcc, |v1|, |v1| +; GCN-NEXT: s_mov_b32 s0, 0x7060302 +; GCN-NEXT: s_nop 0 +; GCN-NEXT: v_cndmask_b32_e32 v1, v3, v2, vcc +; GCN-NEXT: v_perm_b32 v0, v1, v0, s0 +; GCN-NEXT: ; return to shader part epilog +entry: + %a.neg = fneg float %a + %a.cvt = fptrunc float %a.neg to bfloat + %b.abs = call float @llvm.fabs.f32(float %b) + %b.cvt = fptrunc float %b.abs to bfloat + %v2.1 = insertelement <2 x bfloat> undef, bfloat %a.cvt, i32 0 + %v2.2 = insertelement <2 x bfloat> %v2.1, bfloat %b.cvt, i32 1 + %ret = bitcast <2 x bfloat> %v2.2 to float + ret float %ret +} + +define amdgpu_ps void @fptrunc_f32_to_bf16(float %a, ptr %out) { +; GCN-LABEL: fptrunc_f32_to_bf16: +; GCN: ; %bb.0: ; %entry +; GCN-NEXT: v_mov_b32_e32 v3, v2 +; GCN-NEXT: v_mov_b32_e32 v2, v1 +; GCN-NEXT: v_bfe_u32 v1, v0, 16, 1 +; GCN-NEXT: s_movk_i32 s0, 0x7fff +; GCN-NEXT: v_add3_u32 v1, v1, v0, s0 +; GCN-NEXT: v_or_b32_e32 v4, 0x400000, v0 +; GCN-NEXT: v_cmp_u_f32_e32 vcc, v0, v0 +; GCN-NEXT: s_nop 1 +; GCN-NEXT: v_cndmask_b32_e32 v0, v1, v4, vcc +; GCN-NEXT: flat_store_short_d16_hi v[2:3], v0 sc0 sc1 +; GCN-NEXT: s_endpgm +entry: + %a.cvt = fptrunc float %a to bfloat + store bfloat %a.cvt, ptr %out + ret void +} + +define amdgpu_ps void @fptrunc_f32_to_bf16_abs(float %a, ptr %out) { +; GCN-LABEL: fptrunc_f32_to_bf16_abs: +; GCN: ; %bb.0: ; %entry +; GCN-NEXT: v_mov_b32_e32 v3, v2 +; GCN-NEXT: v_mov_b32_e32 v2, v1 +; GCN-NEXT: v_and_b32_e32 v1, 0x7fffffff, v0 +; GCN-NEXT: v_bfe_u32 v4, v1, 16, 1 +; GCN-NEXT: s_movk_i32 s0, 0x7fff +; GCN-NEXT: v_add3_u32 v4, v4, v1, s0 +; GCN-NEXT: v_or_b32_e32 v1, 0x400000, v1 +; GCN-NEXT: v_cmp_u_f32_e64 vcc, |v0|, |v0| +; GCN-NEXT: s_nop 1 +; GCN-NEXT: v_cndmask_b32_e32 v0, v4, v1, vcc +; GCN-NEXT: flat_store_short_d16_hi v[2:3], v0 sc0 sc1 +; GCN-NEXT: s_endpgm +entry: + %a.abs = call float @llvm.fabs.f32(float %a) + %a.cvt = fptrunc float %a.abs to bfloat + store bfloat %a.cvt, ptr %out + ret void +} + +define amdgpu_ps void @fptrunc_f32_to_bf16_neg(float %a, ptr %out) { +; GCN-LABEL: fptrunc_f32_to_bf16_neg: +; GCN: ; %bb.0: ; %entry +; GCN-NEXT: v_mov_b32_e32 v3, v2 +; GCN-NEXT: v_mov_b32_e32 v2, v1 +; GCN-NEXT: v_xor_b32_e32 v1, 0x80000000, v0 +; GCN-NEXT: v_bfe_u32 v4, v1, 16, 1 +; GCN-NEXT: s_movk_i32 s0, 0x7fff +; GCN-NEXT: v_add3_u32 v4, v4, v1, s0 +; GCN-NEXT: v_or_b32_e32 v1, 0x400000, v1 +; GCN-NEXT: v_cmp_u_f32_e64 vcc, -v0, -v0 +; GCN-NEXT: s_nop 1 +; GCN-NEXT: v_cndmask_b32_e32 v0, v4, v1, vcc +; GCN-NEXT: flat_store_short_d16_hi v[2:3], v0 sc0 sc1 +; GCN-NEXT: s_endpgm +entry: + %a.neg = fneg float %a + %a.cvt = fptrunc float %a.neg to bfloat + store bfloat %a.cvt, ptr %out + ret void +} + +define amdgpu_ps void @fptrunc_f64_to_bf16(double %a, ptr %out) { +; GCN-LABEL: fptrunc_f64_to_bf16: +; GCN: ; %bb.0: ; %entry +; GCN-NEXT: v_cvt_f32_f64_e64 v6, |v[0:1]| +; GCN-NEXT: v_cvt_f64_f32_e32 v[4:5], v6 +; GCN-NEXT: v_and_b32_e32 v7, 1, v6 +; GCN-NEXT: v_cmp_gt_f64_e64 s[2:3], |v[0:1]|, v[4:5] +; GCN-NEXT: v_cmp_nlg_f64_e64 s[0:1], |v[0:1]|, v[4:5] +; GCN-NEXT: v_cmp_eq_u32_e32 vcc, 1, v7 +; GCN-NEXT: v_cndmask_b32_e64 v4, -1, 1, s[2:3] +; GCN-NEXT: v_add_u32_e32 v4, v6, v4 +; GCN-NEXT: s_or_b64 vcc, s[0:1], vcc +; GCN-NEXT: v_cndmask_b32_e32 v4, v4, v6, vcc +; GCN-NEXT: s_brev_b32 s0, 1 +; GCN-NEXT: v_and_or_b32 v5, v1, s0, v4 +; GCN-NEXT: v_bfe_u32 v4, v4, 16, 1 +; GCN-NEXT: s_movk_i32 s0, 0x7fff +; GCN-NEXT: v_add3_u32 v4, v4, v5, s0 +; GCN-NEXT: v_or_b32_e32 v5, 0x400000, v5 +; GCN-NEXT: v_cmp_u_f64_e32 vcc, v[0:1], v[0:1] +; GCN-NEXT: s_nop 1 +; GCN-NEXT: v_cndmask_b32_e32 v0, v4, v5, vcc +; GCN-NEXT: flat_store_short_d16_hi v[2:3], v0 sc0 sc1 +; GCN-NEXT: s_endpgm +entry: + %a.cvt = fptrunc double %a to bfloat + store bfloat %a.cvt, ptr %out + ret void +} + +define amdgpu_ps void @fptrunc_f64_to_bf16_neg(double %a, ptr %out) { +; GCN-LABEL: fptrunc_f64_to_bf16_neg: +; GCN: ; %bb.0: ; %entry +; GCN-NEXT: v_cvt_f32_f64_e64 v7, |v[0:1]| +; GCN-NEXT: v_cvt_f64_f32_e32 v[4:5], v7 +; GCN-NEXT: v_and_b32_e32 v8, 1, v7 +; GCN-NEXT: v_cmp_gt_f64_e64 s[2:3], |v[0:1]|, v[4:5] +; GCN-NEXT: v_cmp_nlg_f64_e64 s[0:1], |v[0:1]|, v[4:5] +; GCN-NEXT: v_cmp_eq_u32_e32 vcc, 1, v8 +; GCN-NEXT: v_cndmask_b32_e64 v4, -1, 1, s[2:3] +; GCN-NEXT: v_add_u32_e32 v4, v7, v4 +; GCN-NEXT: s_or_b64 vcc, s[0:1], vcc +; GCN-NEXT: s_brev_b32 s4, 1 +; GCN-NEXT: v_xor_b32_e32 v6, 0x80000000, v1 +; GCN-NEXT: v_cndmask_b32_e32 v4, v4, v7, vcc +; GCN-NEXT: v_and_or_b32 v5, v6, s4, v4 +; GCN-NEXT: v_bfe_u32 v4, v4, 16, 1 +; GCN-NEXT: s_movk_i32 s0, 0x7fff +; GCN-NEXT: v_add3_u32 v4, v4, v5, s0 +; GCN-NEXT: v_or_b32_e32 v5, 0x400000, v5 +; GCN-NEXT: v_cmp_u_f64_e64 vcc, -v[0:1], -v[0:1] +; GCN-NEXT: s_nop 1 +; GCN-NEXT: v_cndmask_b32_e32 v0, v4, v5, vcc +; GCN-NEXT: flat_store_short_d16_hi v[2:3], v0 sc0 sc1 +; GCN-NEXT: s_endpgm +entry: + %a.neg = fneg double %a + %a.cvt = fptrunc double %a.neg to bfloat + store bfloat %a.cvt, ptr %out + ret void +} + +define amdgpu_ps void @fptrunc_f64_to_bf16_abs(double %a, ptr %out) { +; GCN-LABEL: fptrunc_f64_to_bf16_abs: +; GCN: ; %bb.0: ; %entry +; GCN-NEXT: v_cvt_f32_f64_e64 v7, |v[0:1]| +; GCN-NEXT: v_cvt_f64_f32_e32 v[4:5], v7 +; GCN-NEXT: v_and_b32_e32 v8, 1, v7 +; GCN-NEXT: v_cmp_gt_f64_e64 s[2:3], |v[0:1]|, v[4:5] +; GCN-NEXT: v_cmp_nlg_f64_e64 s[0:1], |v[0:1]|, v[4:5] +; GCN-NEXT: v_cmp_eq_u32_e32 vcc, 1, v8 +; GCN-NEXT: v_cndmask_b32_e64 v4, -1, 1, s[2:3] +; GCN-NEXT: v_add_u32_e32 v4, v7, v4 +; GCN-NEXT: s_or_b64 vcc, s[0:1], vcc +; GCN-NEXT: v_and_b32_e32 v6, 0x7fffffff, v1 +; GCN-NEXT: v_cndmask_b32_e32 v4, v4, v7, vcc +; GCN-NEXT: s_brev_b32 s0, 1 +; GCN-NEXT: v_and_or_b32 v5, v6, s0, v4 +; GCN-NEXT: v_bfe_u32 v4, v4, 16, 1 +; GCN-NEXT: s_movk_i32 s0, 0x7fff +; GCN-NEXT: v_add3_u32 v4, v4, v5, s0 +; GCN-NEXT: v_or_b32_e32 v5, 0x400000, v5 +; GCN-NEXT: v_cmp_u_f64_e64 vcc, |v[0:1]|, |v[0:1]| +; GCN-NEXT: s_nop 1 +; GCN-NEXT: v_cndmask_b32_e32 v0, v4, v5, vcc +; GCN-NEXT: flat_store_short_d16_hi v[2:3], v0 sc0 sc1 +; GCN-NEXT: s_endpgm +entry: + %a.abs = call double @llvm.fabs.f64(double %a) + %a.cvt = fptrunc double %a.abs to bfloat + store bfloat %a.cvt, ptr %out + ret void +} + +declare float @llvm.fabs.f32(float) +declare double @llvm.fabs.f64(double) diff --git a/llvm/test/CodeGen/AMDGPU/bf16.ll b/llvm/test/CodeGen/AMDGPU/bf16.ll index ebb77c13c4af7b9472b905641d28ce666e3d298c..98658834e89784fd8482bbd91ef3e0b4366402d2 100644 --- a/llvm/test/CodeGen/AMDGPU/bf16.ll +++ b/llvm/test/CodeGen/AMDGPU/bf16.ll @@ -16968,7 +16968,7 @@ define bfloat @v_fabs_bf16(bfloat %a) { ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e64 v0, 1.0, |v0| +; GCN-NEXT: v_and_b32_e32 v0, 0x7fffffff, v0 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: s_setpc_b64 s[30:31] ; @@ -16977,7 +16977,7 @@ define bfloat @v_fabs_bf16(bfloat %a) { ; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e64 v0, 1.0, |v0| +; GFX7-NEXT: v_and_b32_e32 v0, 0x7fffffff, v0 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GFX7-NEXT: s_setpc_b64 s[30:31] ; @@ -17163,9 +17163,9 @@ define bfloat @v_fneg_fabs_bf16(bfloat %a) { ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e64 v0, 1.0, |v0| +; GCN-NEXT: v_and_b32_e32 v0, 0x7fffffff, v0 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v0, -1.0, v0 +; GCN-NEXT: v_xor_b32_e32 v0, 0x80000000, v0 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: s_setpc_b64 s[30:31] ; @@ -17174,9 +17174,9 @@ define bfloat @v_fneg_fabs_bf16(bfloat %a) { ; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e64 v0, 1.0, |v0| +; GFX7-NEXT: v_and_b32_e32 v0, 0x7fffffff, v0 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v0, -1.0, v0 +; GFX7-NEXT: v_xor_b32_e32 v0, 0x80000000, v0 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GFX7-NEXT: s_setpc_b64 s[30:31] ; @@ -17280,8 +17280,6 @@ define bfloat @v_minnum_bf16(bfloat %a, bfloat %b) { ; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_min_f32_e32 v0, v0, v1 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: s_setpc_b64 s[30:31] @@ -17293,8 +17291,6 @@ define bfloat @v_minnum_bf16(bfloat %a, bfloat %b) { ; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_min_f32_e32 v0, v0, v1 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GFX7-NEXT: s_setpc_b64 s[30:31] @@ -17375,10 +17371,6 @@ define <2 x bfloat> @v_minnum_v2bf16(<2 x bfloat> %a, <2 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_min_f32_e32 v1, v1, v3 ; GCN-NEXT: v_min_f32_e32 v0, v0, v2 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 @@ -17396,10 +17388,6 @@ define <2 x bfloat> @v_minnum_v2bf16(<2 x bfloat> %a, <2 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_min_f32_e32 v1, v1, v3 ; GFX7-NEXT: v_min_f32_e32 v0, v0, v2 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 @@ -17522,12 +17510,6 @@ define <3 x bfloat> @v_minnum_v3bf16(<3 x bfloat> %a, <3 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_min_f32_e32 v2, v2, v5 ; GCN-NEXT: v_min_f32_e32 v1, v1, v4 ; GCN-NEXT: v_min_f32_e32 v0, v0, v3 @@ -17551,12 +17533,6 @@ define <3 x bfloat> @v_minnum_v3bf16(<3 x bfloat> %a, <3 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_min_f32_e32 v2, v2, v5 ; GFX7-NEXT: v_min_f32_e32 v1, v1, v4 ; GFX7-NEXT: v_min_f32_e32 v0, v0, v3 @@ -17688,14 +17664,6 @@ define <4 x bfloat> @v_minnum_v4bf16(<4 x bfloat> %a, <4 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_min_f32_e32 v3, v3, v7 ; GCN-NEXT: v_min_f32_e32 v2, v2, v6 ; GCN-NEXT: v_min_f32_e32 v1, v1, v5 @@ -17725,14 +17693,6 @@ define <4 x bfloat> @v_minnum_v4bf16(<4 x bfloat> %a, <4 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_min_f32_e32 v3, v3, v7 ; GFX7-NEXT: v_min_f32_e32 v2, v2, v6 ; GFX7-NEXT: v_min_f32_e32 v1, v1, v5 @@ -17951,22 +17911,6 @@ define <8 x bfloat> @v_minnum_v8bf16(<8 x bfloat> %a, <8 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 -; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GCN-NEXT: v_mul_f32_e32 v14, 1.0, v14 -; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_min_f32_e32 v7, v7, v15 ; GCN-NEXT: v_min_f32_e32 v6, v6, v14 ; GCN-NEXT: v_min_f32_e32 v5, v5, v13 @@ -18020,22 +17964,6 @@ define <8 x bfloat> @v_minnum_v8bf16(<8 x bfloat> %a, <8 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 -; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: v_mul_f32_e32 v12, 1.0, v12 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GFX7-NEXT: v_mul_f32_e32 v11, 1.0, v11 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_min_f32_e32 v7, v7, v15 ; GFX7-NEXT: v_min_f32_e32 v6, v6, v14 ; GFX7-NEXT: v_min_f32_e32 v5, v5, v13 @@ -18382,71 +18310,51 @@ define <16 x bfloat> @v_minnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GCN-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GCN-NEXT: v_and_b32_e32 v30, 0xffff0000, v30 ; GCN-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 -; GCN-NEXT: v_mul_f32_e32 v30, 1.0, v30 -; GCN-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GCN-NEXT: v_min_f32_e32 v14, v14, v30 ; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GCN-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GCN-NEXT: v_and_b32_e32 v29, 0xffff0000, v29 ; GCN-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 -; GCN-NEXT: v_mul_f32_e32 v29, 1.0, v29 -; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GCN-NEXT: v_min_f32_e32 v13, v13, v29 ; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GCN-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GCN-NEXT: v_and_b32_e32 v28, 0xffff0000, v28 ; GCN-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 -; GCN-NEXT: v_mul_f32_e32 v28, 1.0, v28 -; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GCN-NEXT: v_min_f32_e32 v12, v12, v28 ; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GCN-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GCN-NEXT: v_and_b32_e32 v27, 0xffff0000, v27 ; GCN-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 -; GCN-NEXT: v_mul_f32_e32 v27, 1.0, v27 -; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GCN-NEXT: v_min_f32_e32 v11, v11, v27 ; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GCN-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GCN-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 ; GCN-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 -; GCN-NEXT: v_mul_f32_e32 v26, 1.0, v26 -; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GCN-NEXT: v_min_f32_e32 v10, v10, v26 ; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GCN-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GCN-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 ; GCN-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 -; GCN-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GCN-NEXT: v_min_f32_e32 v9, v9, v25 ; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GCN-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GCN-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 ; GCN-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 -; GCN-NEXT: v_mul_f32_e32 v24, 1.0, v24 -; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GCN-NEXT: v_min_f32_e32 v8, v8, v24 ; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GCN-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GCN-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 ; GCN-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 -; GCN-NEXT: v_mul_f32_e32 v23, 1.0, v23 -; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GCN-NEXT: v_min_f32_e32 v7, v7, v23 ; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GCN-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GCN-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 ; GCN-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 -; GCN-NEXT: v_mul_f32_e32 v22, 1.0, v22 -; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GCN-NEXT: v_min_f32_e32 v6, v6, v22 ; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GCN-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GCN-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 ; GCN-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 -; GCN-NEXT: v_mul_f32_e32 v21, 1.0, v21 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GCN-NEXT: v_min_f32_e32 v5, v5, v21 ; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 @@ -18461,8 +18369,6 @@ define <16 x bfloat> @v_minnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GCN-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 ; GCN-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 -; GCN-NEXT: v_mul_f32_e32 v20, 1.0, v20 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GCN-NEXT: v_min_f32_e32 v4, v4, v20 ; GCN-NEXT: buffer_load_dword v20, off, s[0:3], s32 ; GCN-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 @@ -18474,21 +18380,10 @@ define <16 x bfloat> @v_minnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 -; GCN-NEXT: v_mul_f32_e32 v19, 1.0, v19 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v18, 1.0, v18 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v17, 1.0, v17 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_min_f32_e32 v3, v3, v19 ; GCN-NEXT: v_min_f32_e32 v2, v2, v18 ; GCN-NEXT: v_min_f32_e32 v1, v1, v17 ; GCN-NEXT: v_min_f32_e32 v0, v0, v16 -; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v20 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 @@ -18503,8 +18398,9 @@ define <16 x bfloat> @v_minnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 ; GCN-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 ; GCN-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 +; GCN-NEXT: s_waitcnt vmcnt(0) +; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v20 ; GCN-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 -; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GCN-NEXT: v_min_f32_e32 v15, v15, v16 ; GCN-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 ; GCN-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 @@ -18513,14 +18409,12 @@ define <16 x bfloat> @v_minnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-LABEL: v_minnum_v16bf16: ; GFX7: ; %bb.0: ; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 -; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 -; GFX7-NEXT: v_min_f32_e32 v9, v9, v25 -; GFX7-NEXT: buffer_load_dword v25, off, s[0:3], s32 +; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 +; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 +; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 +; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 +; GFX7-NEXT: v_min_f32_e32 v6, v6, v22 +; GFX7-NEXT: buffer_load_dword v22, off, s[0:3], s32 ; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GFX7-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 @@ -18531,13 +18425,13 @@ define <16 x bfloat> @v_minnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GFX7-NEXT: v_mul_f32_e32 v26, 1.0, v26 -; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 +; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 +; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GFX7-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GFX7-NEXT: v_mul_f32_e32 v23, 1.0, v23 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 +; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GFX7-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 @@ -18560,13 +18454,13 @@ define <16 x bfloat> @v_minnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 ; GFX7-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 ; GFX7-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 -; GFX7-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 +; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 +; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 ; GFX7-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GFX7-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 ; GFX7-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 -; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 -; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 +; GFX7-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 ; GFX7-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 ; GFX7-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 ; GFX7-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 @@ -18579,48 +18473,14 @@ define <16 x bfloat> @v_minnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v30, 1.0, v30 -; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 -; GFX7-NEXT: v_mul_f32_e32 v29, 1.0, v29 -; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 -; GFX7-NEXT: v_mul_f32_e32 v28, 1.0, v28 -; GFX7-NEXT: v_mul_f32_e32 v12, 1.0, v12 -; GFX7-NEXT: v_mul_f32_e32 v27, 1.0, v27 -; GFX7-NEXT: v_mul_f32_e32 v11, 1.0, v11 -; GFX7-NEXT: v_mul_f32_e32 v26, 1.0, v26 -; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 -; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 -; GFX7-NEXT: v_mul_f32_e32 v24, 1.0, v24 -; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 -; GFX7-NEXT: v_mul_f32_e32 v23, 1.0, v23 -; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GFX7-NEXT: v_mul_f32_e32 v21, 1.0, v21 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: v_mul_f32_e32 v20, 1.0, v20 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GFX7-NEXT: s_waitcnt vmcnt(0) -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GFX7-NEXT: v_mul_f32_e32 v19, 1.0, v19 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v18, 1.0, v18 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v17, 1.0, v17 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v16, 1.0, v16 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_min_f32_e32 v14, v14, v30 ; GFX7-NEXT: v_min_f32_e32 v13, v13, v29 ; GFX7-NEXT: v_min_f32_e32 v12, v12, v28 ; GFX7-NEXT: v_min_f32_e32 v11, v11, v27 ; GFX7-NEXT: v_min_f32_e32 v10, v10, v26 -; GFX7-NEXT: v_min_f32_e32 v15, v15, v25 +; GFX7-NEXT: v_min_f32_e32 v9, v9, v25 ; GFX7-NEXT: v_min_f32_e32 v8, v8, v24 ; GFX7-NEXT: v_min_f32_e32 v7, v7, v23 -; GFX7-NEXT: v_min_f32_e32 v6, v6, v22 ; GFX7-NEXT: v_min_f32_e32 v5, v5, v21 ; GFX7-NEXT: v_min_f32_e32 v4, v4, v20 ; GFX7-NEXT: v_min_f32_e32 v3, v3, v19 @@ -18634,6 +18494,10 @@ define <16 x bfloat> @v_minnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 ; GFX7-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 ; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 +; GFX7-NEXT: s_waitcnt vmcnt(0) +; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 +; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 +; GFX7-NEXT: v_min_f32_e32 v15, v15, v22 ; GFX7-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 @@ -19267,287 +19131,223 @@ define <32 x bfloat> @v_minnum_v32bf16(<32 x bfloat> %a, <32 x bfloat> %b) { ; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 ; GCN-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 -; GCN-NEXT: v_mul_f32_e32 v31, 1.0, v31 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:124 ; GCN-NEXT: v_min_f32_e32 v31, v31, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:124 ; GCN-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GCN-NEXT: v_and_b32_e32 v30, 0xffff0000, v30 -; GCN-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:120 ; GCN-NEXT: v_min_f32_e32 v30, v30, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:120 ; GCN-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GCN-NEXT: v_and_b32_e32 v29, 0xffff0000, v29 -; GCN-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:116 ; GCN-NEXT: v_min_f32_e32 v29, v29, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:116 ; GCN-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GCN-NEXT: v_and_b32_e32 v28, 0xffff0000, v28 -; GCN-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:112 ; GCN-NEXT: v_min_f32_e32 v28, v28, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:112 ; GCN-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GCN-NEXT: v_and_b32_e32 v27, 0xffff0000, v27 -; GCN-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:108 ; GCN-NEXT: v_min_f32_e32 v27, v27, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:108 ; GCN-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GCN-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 -; GCN-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:104 ; GCN-NEXT: v_min_f32_e32 v26, v26, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:104 ; GCN-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GCN-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 -; GCN-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:100 ; GCN-NEXT: v_min_f32_e32 v25, v25, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:100 ; GCN-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GCN-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 -; GCN-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:96 ; GCN-NEXT: v_min_f32_e32 v24, v24, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:96 ; GCN-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GCN-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 -; GCN-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:92 ; GCN-NEXT: v_min_f32_e32 v23, v23, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:92 ; GCN-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GCN-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 -; GCN-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:88 ; GCN-NEXT: v_min_f32_e32 v22, v22, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:88 ; GCN-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GCN-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 -; GCN-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:84 ; GCN-NEXT: v_min_f32_e32 v21, v21, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:84 ; GCN-NEXT: v_mul_f32_e32 v20, 1.0, v20 ; GCN-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 -; GCN-NEXT: v_mul_f32_e32 v20, 1.0, v20 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:80 ; GCN-NEXT: v_min_f32_e32 v20, v20, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:80 ; GCN-NEXT: v_mul_f32_e32 v19, 1.0, v19 ; GCN-NEXT: v_and_b32_e32 v19, 0xffff0000, v19 -; GCN-NEXT: v_mul_f32_e32 v19, 1.0, v19 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:76 ; GCN-NEXT: v_min_f32_e32 v19, v19, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:76 ; GCN-NEXT: v_mul_f32_e32 v18, 1.0, v18 ; GCN-NEXT: v_and_b32_e32 v18, 0xffff0000, v18 -; GCN-NEXT: v_mul_f32_e32 v18, 1.0, v18 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:72 ; GCN-NEXT: v_min_f32_e32 v18, v18, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:72 ; GCN-NEXT: v_mul_f32_e32 v17, 1.0, v17 ; GCN-NEXT: v_and_b32_e32 v17, 0xffff0000, v17 -; GCN-NEXT: v_mul_f32_e32 v17, 1.0, v17 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:68 ; GCN-NEXT: v_min_f32_e32 v17, v17, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:68 ; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GCN-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 -; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:64 ; GCN-NEXT: v_min_f32_e32 v16, v16, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:64 ; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GCN-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 -; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:60 ; GCN-NEXT: v_min_f32_e32 v15, v15, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:60 ; GCN-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GCN-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 -; GCN-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:56 ; GCN-NEXT: v_min_f32_e32 v14, v14, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:56 ; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GCN-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 -; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:52 ; GCN-NEXT: v_min_f32_e32 v13, v13, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:52 ; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GCN-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 -; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:48 ; GCN-NEXT: v_min_f32_e32 v12, v12, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:48 ; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GCN-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 -; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:44 ; GCN-NEXT: v_min_f32_e32 v11, v11, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:44 ; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GCN-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 -; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:40 ; GCN-NEXT: v_min_f32_e32 v10, v10, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:40 ; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GCN-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 -; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:36 ; GCN-NEXT: v_min_f32_e32 v9, v9, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:36 ; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GCN-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 -; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:32 ; GCN-NEXT: v_min_f32_e32 v8, v8, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:32 ; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GCN-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 -; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:28 ; GCN-NEXT: v_min_f32_e32 v7, v7, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:28 ; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GCN-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 -; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:24 ; GCN-NEXT: v_min_f32_e32 v6, v6, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:24 ; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GCN-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:20 ; GCN-NEXT: v_min_f32_e32 v5, v5, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:20 ; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GCN-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:16 ; GCN-NEXT: v_min_f32_e32 v4, v4, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:16 ; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; GCN-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:12 ; GCN-NEXT: v_min_f32_e32 v3, v3, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:12 ; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 ; GCN-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:8 ; GCN-NEXT: v_min_f32_e32 v2, v2, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:8 ; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:4 ; GCN-NEXT: v_min_f32_e32 v1, v1, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:4 ; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GCN-NEXT: v_min_f32_e32 v0, v0, v32 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 @@ -19590,322 +19390,258 @@ define <32 x bfloat> @v_minnum_v32bf16(<32 x bfloat> %a, <32 x bfloat> %b) { ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:128 ; GFX7-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GFX7-NEXT: v_and_b32_e32 v30, 0xffff0000, v30 -; GFX7-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GFX7-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GFX7-NEXT: v_and_b32_e32 v29, 0xffff0000, v29 -; GFX7-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GFX7-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GFX7-NEXT: v_and_b32_e32 v28, 0xffff0000, v28 -; GFX7-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GFX7-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GFX7-NEXT: v_and_b32_e32 v27, 0xffff0000, v27 -; GFX7-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GFX7-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GFX7-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 -; GFX7-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GFX7-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GFX7-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 -; GFX7-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GFX7-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GFX7-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 -; GFX7-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 -; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GFX7-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GFX7-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 -; GFX7-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GFX7-NEXT: v_mul_f32_e32 v20, 1.0, v20 ; GFX7-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 -; GFX7-NEXT: v_mul_f32_e32 v20, 1.0, v20 ; GFX7-NEXT: v_mul_f32_e32 v19, 1.0, v19 ; GFX7-NEXT: v_and_b32_e32 v19, 0xffff0000, v19 -; GFX7-NEXT: v_mul_f32_e32 v19, 1.0, v19 ; GFX7-NEXT: v_mul_f32_e32 v18, 1.0, v18 ; GFX7-NEXT: v_and_b32_e32 v18, 0xffff0000, v18 -; GFX7-NEXT: v_mul_f32_e32 v18, 1.0, v18 ; GFX7-NEXT: v_mul_f32_e32 v17, 1.0, v17 ; GFX7-NEXT: v_and_b32_e32 v17, 0xffff0000, v17 -; GFX7-NEXT: v_mul_f32_e32 v17, 1.0, v17 ; GFX7-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GFX7-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 -; GFX7-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GFX7-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 -; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GFX7-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 -; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GFX7-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 -; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GFX7-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GFX7-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 -; GFX7-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GFX7-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GFX7-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 -; GFX7-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GFX7-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 -; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 -; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 -; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GFX7-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 -; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GFX7-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: s_waitcnt vmcnt(1) -; GFX7-NEXT: v_mul_f32_e32 v31, 1.0, v31 -; GFX7-NEXT: s_waitcnt vmcnt(0) -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 -; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 -; GFX7-NEXT: v_mul_f32_e32 v31, 1.0, v31 -; GFX7-NEXT: v_min_f32_e32 v31, v31, v32 -; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:124 ; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GFX7-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; GFX7-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 ; GFX7-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 ; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; GFX7-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 +; GFX7-NEXT: s_waitcnt vmcnt(1) +; GFX7-NEXT: v_mul_f32_e32 v31, 1.0, v31 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 +; GFX7-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 +; GFX7-NEXT: v_min_f32_e32 v31, v31, v32 +; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:124 +; GFX7-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 +; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 ; GFX7-NEXT: v_min_f32_e32 v30, v30, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:120 ; GFX7-NEXT: v_and_b32_e32 v30, 0xffff0000, v30 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v29, v29, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:116 ; GFX7-NEXT: v_and_b32_e32 v29, 0xffff0000, v29 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v28, v28, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:112 ; GFX7-NEXT: v_and_b32_e32 v28, 0xffff0000, v28 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v27, v27, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:108 ; GFX7-NEXT: v_and_b32_e32 v27, 0xffff0000, v27 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v26, v26, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:104 ; GFX7-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v25, v25, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:100 ; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v24, v24, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:96 ; GFX7-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v23, v23, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:92 ; GFX7-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v22, v22, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:88 ; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v21, v21, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:84 ; GFX7-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v20, v20, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:80 ; GFX7-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v19, v19, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:76 ; GFX7-NEXT: v_and_b32_e32 v19, 0xffff0000, v19 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v18, v18, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:72 ; GFX7-NEXT: v_and_b32_e32 v18, 0xffff0000, v18 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v17, v17, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:68 ; GFX7-NEXT: v_and_b32_e32 v17, 0xffff0000, v17 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v16, v16, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:64 ; GFX7-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v15, v15, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:60 ; GFX7-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v14, v14, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:56 ; GFX7-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v13, v13, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:52 ; GFX7-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v12, v12, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:48 ; GFX7-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v11, v11, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:44 ; GFX7-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v10, v10, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:40 ; GFX7-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v9, v9, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:36 ; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v8, v8, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:32 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v7, v7, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:28 ; GFX7-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v6, v6, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:24 ; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v5, v5, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:20 ; GFX7-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v4, v4, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:16 ; GFX7-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v3, v3, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:12 ; GFX7-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v2, v2, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:8 ; GFX7-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v1, v1, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:4 ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_min_f32_e32 v0, v0, v32 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GFX7-NEXT: s_setpc_b64 s[30:31] @@ -21097,8 +20833,6 @@ define bfloat @v_maxnum_bf16(bfloat %a, bfloat %b) { ; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_max_f32_e32 v0, v0, v1 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: s_setpc_b64 s[30:31] @@ -21110,8 +20844,6 @@ define bfloat @v_maxnum_bf16(bfloat %a, bfloat %b) { ; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_max_f32_e32 v0, v0, v1 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GFX7-NEXT: s_setpc_b64 s[30:31] @@ -21192,10 +20924,6 @@ define <2 x bfloat> @v_maxnum_v2bf16(<2 x bfloat> %a, <2 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_max_f32_e32 v1, v1, v3 ; GCN-NEXT: v_max_f32_e32 v0, v0, v2 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 @@ -21213,10 +20941,6 @@ define <2 x bfloat> @v_maxnum_v2bf16(<2 x bfloat> %a, <2 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_max_f32_e32 v1, v1, v3 ; GFX7-NEXT: v_max_f32_e32 v0, v0, v2 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 @@ -21339,12 +21063,6 @@ define <3 x bfloat> @v_maxnum_v3bf16(<3 x bfloat> %a, <3 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_max_f32_e32 v2, v2, v5 ; GCN-NEXT: v_max_f32_e32 v1, v1, v4 ; GCN-NEXT: v_max_f32_e32 v0, v0, v3 @@ -21368,12 +21086,6 @@ define <3 x bfloat> @v_maxnum_v3bf16(<3 x bfloat> %a, <3 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_max_f32_e32 v2, v2, v5 ; GFX7-NEXT: v_max_f32_e32 v1, v1, v4 ; GFX7-NEXT: v_max_f32_e32 v0, v0, v3 @@ -21505,14 +21217,6 @@ define <4 x bfloat> @v_maxnum_v4bf16(<4 x bfloat> %a, <4 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_max_f32_e32 v3, v3, v7 ; GCN-NEXT: v_max_f32_e32 v2, v2, v6 ; GCN-NEXT: v_max_f32_e32 v1, v1, v5 @@ -21542,14 +21246,6 @@ define <4 x bfloat> @v_maxnum_v4bf16(<4 x bfloat> %a, <4 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_max_f32_e32 v3, v3, v7 ; GFX7-NEXT: v_max_f32_e32 v2, v2, v6 ; GFX7-NEXT: v_max_f32_e32 v1, v1, v5 @@ -21768,22 +21464,6 @@ define <8 x bfloat> @v_maxnum_v8bf16(<8 x bfloat> %a, <8 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 -; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GCN-NEXT: v_mul_f32_e32 v14, 1.0, v14 -; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_max_f32_e32 v7, v7, v15 ; GCN-NEXT: v_max_f32_e32 v6, v6, v14 ; GCN-NEXT: v_max_f32_e32 v5, v5, v13 @@ -21837,22 +21517,6 @@ define <8 x bfloat> @v_maxnum_v8bf16(<8 x bfloat> %a, <8 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 -; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: v_mul_f32_e32 v12, 1.0, v12 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GFX7-NEXT: v_mul_f32_e32 v11, 1.0, v11 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_max_f32_e32 v7, v7, v15 ; GFX7-NEXT: v_max_f32_e32 v6, v6, v14 ; GFX7-NEXT: v_max_f32_e32 v5, v5, v13 @@ -22199,71 +21863,51 @@ define <16 x bfloat> @v_maxnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GCN-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GCN-NEXT: v_and_b32_e32 v30, 0xffff0000, v30 ; GCN-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 -; GCN-NEXT: v_mul_f32_e32 v30, 1.0, v30 -; GCN-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GCN-NEXT: v_max_f32_e32 v14, v14, v30 ; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GCN-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GCN-NEXT: v_and_b32_e32 v29, 0xffff0000, v29 ; GCN-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 -; GCN-NEXT: v_mul_f32_e32 v29, 1.0, v29 -; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GCN-NEXT: v_max_f32_e32 v13, v13, v29 ; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GCN-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GCN-NEXT: v_and_b32_e32 v28, 0xffff0000, v28 ; GCN-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 -; GCN-NEXT: v_mul_f32_e32 v28, 1.0, v28 -; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GCN-NEXT: v_max_f32_e32 v12, v12, v28 ; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GCN-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GCN-NEXT: v_and_b32_e32 v27, 0xffff0000, v27 ; GCN-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 -; GCN-NEXT: v_mul_f32_e32 v27, 1.0, v27 -; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GCN-NEXT: v_max_f32_e32 v11, v11, v27 ; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GCN-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GCN-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 ; GCN-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 -; GCN-NEXT: v_mul_f32_e32 v26, 1.0, v26 -; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GCN-NEXT: v_max_f32_e32 v10, v10, v26 ; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GCN-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GCN-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 ; GCN-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 -; GCN-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GCN-NEXT: v_max_f32_e32 v9, v9, v25 ; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GCN-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GCN-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 ; GCN-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 -; GCN-NEXT: v_mul_f32_e32 v24, 1.0, v24 -; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GCN-NEXT: v_max_f32_e32 v8, v8, v24 ; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GCN-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GCN-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 ; GCN-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 -; GCN-NEXT: v_mul_f32_e32 v23, 1.0, v23 -; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GCN-NEXT: v_max_f32_e32 v7, v7, v23 ; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GCN-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GCN-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 ; GCN-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 -; GCN-NEXT: v_mul_f32_e32 v22, 1.0, v22 -; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GCN-NEXT: v_max_f32_e32 v6, v6, v22 ; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GCN-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GCN-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 ; GCN-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 -; GCN-NEXT: v_mul_f32_e32 v21, 1.0, v21 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GCN-NEXT: v_max_f32_e32 v5, v5, v21 ; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 @@ -22278,8 +21922,6 @@ define <16 x bfloat> @v_maxnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GCN-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 ; GCN-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 -; GCN-NEXT: v_mul_f32_e32 v20, 1.0, v20 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GCN-NEXT: v_max_f32_e32 v4, v4, v20 ; GCN-NEXT: buffer_load_dword v20, off, s[0:3], s32 ; GCN-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 @@ -22291,21 +21933,10 @@ define <16 x bfloat> @v_maxnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 -; GCN-NEXT: v_mul_f32_e32 v19, 1.0, v19 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GCN-NEXT: v_mul_f32_e32 v18, 1.0, v18 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GCN-NEXT: v_mul_f32_e32 v17, 1.0, v17 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_max_f32_e32 v3, v3, v19 ; GCN-NEXT: v_max_f32_e32 v2, v2, v18 ; GCN-NEXT: v_max_f32_e32 v1, v1, v17 ; GCN-NEXT: v_max_f32_e32 v0, v0, v16 -; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v20 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GCN-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 @@ -22320,8 +21951,9 @@ define <16 x bfloat> @v_maxnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GCN-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 ; GCN-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 ; GCN-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 +; GCN-NEXT: s_waitcnt vmcnt(0) +; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v20 ; GCN-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 -; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GCN-NEXT: v_max_f32_e32 v15, v15, v16 ; GCN-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 ; GCN-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 @@ -22330,14 +21962,12 @@ define <16 x bfloat> @v_maxnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-LABEL: v_maxnum_v16bf16: ; GFX7: ; %bb.0: ; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 -; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 -; GFX7-NEXT: v_max_f32_e32 v9, v9, v25 -; GFX7-NEXT: buffer_load_dword v25, off, s[0:3], s32 +; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 +; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 +; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 +; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 +; GFX7-NEXT: v_max_f32_e32 v6, v6, v22 +; GFX7-NEXT: buffer_load_dword v22, off, s[0:3], s32 ; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GFX7-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 @@ -22348,13 +21978,13 @@ define <16 x bfloat> @v_maxnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GFX7-NEXT: v_mul_f32_e32 v26, 1.0, v26 -; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 +; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 +; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GFX7-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GFX7-NEXT: v_mul_f32_e32 v23, 1.0, v23 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 +; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GFX7-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 @@ -22377,13 +22007,13 @@ define <16 x bfloat> @v_maxnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 ; GFX7-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 ; GFX7-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 -; GFX7-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 +; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 +; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 ; GFX7-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GFX7-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 ; GFX7-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 -; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 -; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 +; GFX7-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 ; GFX7-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 ; GFX7-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 ; GFX7-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 @@ -22392,52 +22022,18 @@ define <16 x bfloat> @v_maxnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 ; GFX7-NEXT: v_and_b32_e32 v18, 0xffff0000, v18 ; GFX7-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 -; GFX7-NEXT: v_and_b32_e32 v17, 0xffff0000, v17 -; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 -; GFX7-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 -; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v30, 1.0, v30 -; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 -; GFX7-NEXT: v_mul_f32_e32 v29, 1.0, v29 -; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 -; GFX7-NEXT: v_mul_f32_e32 v28, 1.0, v28 -; GFX7-NEXT: v_mul_f32_e32 v12, 1.0, v12 -; GFX7-NEXT: v_mul_f32_e32 v27, 1.0, v27 -; GFX7-NEXT: v_mul_f32_e32 v11, 1.0, v11 -; GFX7-NEXT: v_mul_f32_e32 v26, 1.0, v26 -; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 -; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 -; GFX7-NEXT: v_mul_f32_e32 v24, 1.0, v24 -; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 -; GFX7-NEXT: v_mul_f32_e32 v23, 1.0, v23 -; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 -; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 -; GFX7-NEXT: v_mul_f32_e32 v21, 1.0, v21 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: v_mul_f32_e32 v20, 1.0, v20 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; GFX7-NEXT: s_waitcnt vmcnt(0) -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 -; GFX7-NEXT: v_mul_f32_e32 v19, 1.0, v19 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX7-NEXT: v_mul_f32_e32 v18, 1.0, v18 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX7-NEXT: v_mul_f32_e32 v17, 1.0, v17 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; GFX7-NEXT: v_mul_f32_e32 v16, 1.0, v16 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 +; GFX7-NEXT: v_and_b32_e32 v17, 0xffff0000, v17 +; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 +; GFX7-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 +; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GFX7-NEXT: v_max_f32_e32 v14, v14, v30 ; GFX7-NEXT: v_max_f32_e32 v13, v13, v29 ; GFX7-NEXT: v_max_f32_e32 v12, v12, v28 ; GFX7-NEXT: v_max_f32_e32 v11, v11, v27 ; GFX7-NEXT: v_max_f32_e32 v10, v10, v26 -; GFX7-NEXT: v_max_f32_e32 v15, v15, v25 +; GFX7-NEXT: v_max_f32_e32 v9, v9, v25 ; GFX7-NEXT: v_max_f32_e32 v8, v8, v24 ; GFX7-NEXT: v_max_f32_e32 v7, v7, v23 -; GFX7-NEXT: v_max_f32_e32 v6, v6, v22 ; GFX7-NEXT: v_max_f32_e32 v5, v5, v21 ; GFX7-NEXT: v_max_f32_e32 v4, v4, v20 ; GFX7-NEXT: v_max_f32_e32 v3, v3, v19 @@ -22451,6 +22047,10 @@ define <16 x bfloat> @v_maxnum_v16bf16(<16 x bfloat> %a, <16 x bfloat> %b) { ; GFX7-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 ; GFX7-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 ; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 +; GFX7-NEXT: s_waitcnt vmcnt(0) +; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 +; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 +; GFX7-NEXT: v_max_f32_e32 v15, v15, v22 ; GFX7-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 @@ -23084,287 +22684,223 @@ define <32 x bfloat> @v_maxnum_v32bf16(<32 x bfloat> %a, <32 x bfloat> %b) { ; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 ; GCN-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 -; GCN-NEXT: v_mul_f32_e32 v31, 1.0, v31 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:124 ; GCN-NEXT: v_max_f32_e32 v31, v31, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:124 ; GCN-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GCN-NEXT: v_and_b32_e32 v30, 0xffff0000, v30 -; GCN-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:120 ; GCN-NEXT: v_max_f32_e32 v30, v30, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:120 ; GCN-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GCN-NEXT: v_and_b32_e32 v29, 0xffff0000, v29 -; GCN-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:116 ; GCN-NEXT: v_max_f32_e32 v29, v29, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:116 ; GCN-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GCN-NEXT: v_and_b32_e32 v28, 0xffff0000, v28 -; GCN-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:112 ; GCN-NEXT: v_max_f32_e32 v28, v28, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:112 ; GCN-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GCN-NEXT: v_and_b32_e32 v27, 0xffff0000, v27 -; GCN-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:108 ; GCN-NEXT: v_max_f32_e32 v27, v27, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:108 ; GCN-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GCN-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 -; GCN-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:104 ; GCN-NEXT: v_max_f32_e32 v26, v26, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:104 ; GCN-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GCN-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 -; GCN-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:100 ; GCN-NEXT: v_max_f32_e32 v25, v25, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:100 ; GCN-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GCN-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 -; GCN-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:96 ; GCN-NEXT: v_max_f32_e32 v24, v24, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:96 ; GCN-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GCN-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 -; GCN-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:92 ; GCN-NEXT: v_max_f32_e32 v23, v23, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:92 ; GCN-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GCN-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 -; GCN-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:88 ; GCN-NEXT: v_max_f32_e32 v22, v22, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:88 ; GCN-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GCN-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 -; GCN-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:84 ; GCN-NEXT: v_max_f32_e32 v21, v21, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:84 ; GCN-NEXT: v_mul_f32_e32 v20, 1.0, v20 ; GCN-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 -; GCN-NEXT: v_mul_f32_e32 v20, 1.0, v20 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:80 ; GCN-NEXT: v_max_f32_e32 v20, v20, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:80 ; GCN-NEXT: v_mul_f32_e32 v19, 1.0, v19 ; GCN-NEXT: v_and_b32_e32 v19, 0xffff0000, v19 -; GCN-NEXT: v_mul_f32_e32 v19, 1.0, v19 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:76 ; GCN-NEXT: v_max_f32_e32 v19, v19, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:76 ; GCN-NEXT: v_mul_f32_e32 v18, 1.0, v18 ; GCN-NEXT: v_and_b32_e32 v18, 0xffff0000, v18 -; GCN-NEXT: v_mul_f32_e32 v18, 1.0, v18 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:72 ; GCN-NEXT: v_max_f32_e32 v18, v18, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:72 ; GCN-NEXT: v_mul_f32_e32 v17, 1.0, v17 ; GCN-NEXT: v_and_b32_e32 v17, 0xffff0000, v17 -; GCN-NEXT: v_mul_f32_e32 v17, 1.0, v17 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:68 ; GCN-NEXT: v_max_f32_e32 v17, v17, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:68 ; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GCN-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 -; GCN-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:64 ; GCN-NEXT: v_max_f32_e32 v16, v16, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:64 ; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GCN-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 -; GCN-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:60 ; GCN-NEXT: v_max_f32_e32 v15, v15, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:60 ; GCN-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GCN-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 -; GCN-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:56 ; GCN-NEXT: v_max_f32_e32 v14, v14, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:56 ; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GCN-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 -; GCN-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:52 ; GCN-NEXT: v_max_f32_e32 v13, v13, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:52 ; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GCN-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 -; GCN-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:48 ; GCN-NEXT: v_max_f32_e32 v12, v12, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:48 ; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GCN-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 -; GCN-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:44 ; GCN-NEXT: v_max_f32_e32 v11, v11, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:44 ; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GCN-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 -; GCN-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:40 ; GCN-NEXT: v_max_f32_e32 v10, v10, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:40 ; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GCN-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 -; GCN-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:36 ; GCN-NEXT: v_max_f32_e32 v9, v9, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:36 ; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GCN-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 -; GCN-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:32 ; GCN-NEXT: v_max_f32_e32 v8, v8, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:32 ; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GCN-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 -; GCN-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:28 ; GCN-NEXT: v_max_f32_e32 v7, v7, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:28 ; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GCN-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 -; GCN-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:24 ; GCN-NEXT: v_max_f32_e32 v6, v6, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:24 ; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GCN-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 -; GCN-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:20 ; GCN-NEXT: v_max_f32_e32 v5, v5, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:20 ; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GCN-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 -; GCN-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:16 ; GCN-NEXT: v_max_f32_e32 v4, v4, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:16 ; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; GCN-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 -; GCN-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:12 ; GCN-NEXT: v_max_f32_e32 v3, v3, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:12 ; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 ; GCN-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 -; GCN-NEXT: v_mul_f32_e32 v2, 1.0, v2 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:8 ; GCN-NEXT: v_max_f32_e32 v2, v2, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:8 ; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 -; GCN-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:4 ; GCN-NEXT: v_max_f32_e32 v1, v1, v32 -; GCN-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:4 ; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: s_waitcnt vmcnt(0) -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v33 ; GCN-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GCN-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GCN-NEXT: v_max_f32_e32 v0, v0, v32 ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 @@ -23407,322 +22943,258 @@ define <32 x bfloat> @v_maxnum_v32bf16(<32 x bfloat> %a, <32 x bfloat> %b) { ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:128 ; GFX7-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GFX7-NEXT: v_and_b32_e32 v30, 0xffff0000, v30 -; GFX7-NEXT: v_mul_f32_e32 v30, 1.0, v30 ; GFX7-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GFX7-NEXT: v_and_b32_e32 v29, 0xffff0000, v29 -; GFX7-NEXT: v_mul_f32_e32 v29, 1.0, v29 ; GFX7-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GFX7-NEXT: v_and_b32_e32 v28, 0xffff0000, v28 -; GFX7-NEXT: v_mul_f32_e32 v28, 1.0, v28 ; GFX7-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GFX7-NEXT: v_and_b32_e32 v27, 0xffff0000, v27 -; GFX7-NEXT: v_mul_f32_e32 v27, 1.0, v27 ; GFX7-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GFX7-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 -; GFX7-NEXT: v_mul_f32_e32 v26, 1.0, v26 ; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 -; GFX7-NEXT: v_mul_f32_e32 v25, 1.0, v25 ; GFX7-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GFX7-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 -; GFX7-NEXT: v_mul_f32_e32 v24, 1.0, v24 ; GFX7-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GFX7-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 -; GFX7-NEXT: v_mul_f32_e32 v23, 1.0, v23 ; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 -; GFX7-NEXT: v_mul_f32_e32 v22, 1.0, v22 ; GFX7-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GFX7-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 -; GFX7-NEXT: v_mul_f32_e32 v21, 1.0, v21 ; GFX7-NEXT: v_mul_f32_e32 v20, 1.0, v20 ; GFX7-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 -; GFX7-NEXT: v_mul_f32_e32 v20, 1.0, v20 ; GFX7-NEXT: v_mul_f32_e32 v19, 1.0, v19 ; GFX7-NEXT: v_and_b32_e32 v19, 0xffff0000, v19 -; GFX7-NEXT: v_mul_f32_e32 v19, 1.0, v19 ; GFX7-NEXT: v_mul_f32_e32 v18, 1.0, v18 ; GFX7-NEXT: v_and_b32_e32 v18, 0xffff0000, v18 -; GFX7-NEXT: v_mul_f32_e32 v18, 1.0, v18 ; GFX7-NEXT: v_mul_f32_e32 v17, 1.0, v17 ; GFX7-NEXT: v_and_b32_e32 v17, 0xffff0000, v17 -; GFX7-NEXT: v_mul_f32_e32 v17, 1.0, v17 ; GFX7-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GFX7-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 -; GFX7-NEXT: v_mul_f32_e32 v16, 1.0, v16 ; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GFX7-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 -; GFX7-NEXT: v_mul_f32_e32 v15, 1.0, v15 ; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GFX7-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 -; GFX7-NEXT: v_mul_f32_e32 v14, 1.0, v14 ; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GFX7-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 -; GFX7-NEXT: v_mul_f32_e32 v13, 1.0, v13 ; GFX7-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GFX7-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 -; GFX7-NEXT: v_mul_f32_e32 v12, 1.0, v12 ; GFX7-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GFX7-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 -; GFX7-NEXT: v_mul_f32_e32 v11, 1.0, v11 ; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GFX7-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 -; GFX7-NEXT: v_mul_f32_e32 v10, 1.0, v10 ; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 -; GFX7-NEXT: v_mul_f32_e32 v9, 1.0, v9 ; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 -; GFX7-NEXT: v_mul_f32_e32 v8, 1.0, v8 ; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GFX7-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 -; GFX7-NEXT: v_mul_f32_e32 v7, 1.0, v7 ; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 -; GFX7-NEXT: v_mul_f32_e32 v6, 1.0, v6 ; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 ; GFX7-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 -; GFX7-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; GFX7-NEXT: s_waitcnt vmcnt(1) -; GFX7-NEXT: v_mul_f32_e32 v31, 1.0, v31 -; GFX7-NEXT: s_waitcnt vmcnt(0) -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 -; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 -; GFX7-NEXT: v_mul_f32_e32 v31, 1.0, v31 -; GFX7-NEXT: v_max_f32_e32 v31, v31, v32 -; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:124 ; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GFX7-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 -; GFX7-NEXT: v_mul_f32_e32 v4, 1.0, v4 ; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; GFX7-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 -; GFX7-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 ; GFX7-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 -; GFX7-NEXT: v_mul_f32_e32 v2, 1.0, v2 ; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 -; GFX7-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 -; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; GFX7-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 +; GFX7-NEXT: s_waitcnt vmcnt(1) +; GFX7-NEXT: v_mul_f32_e32 v31, 1.0, v31 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 +; GFX7-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 +; GFX7-NEXT: v_max_f32_e32 v31, v31, v32 +; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:124 +; GFX7-NEXT: v_and_b32_e32 v31, 0xffff0000, v31 +; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 +; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 ; GFX7-NEXT: v_max_f32_e32 v30, v30, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:120 ; GFX7-NEXT: v_and_b32_e32 v30, 0xffff0000, v30 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v29, v29, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:116 ; GFX7-NEXT: v_and_b32_e32 v29, 0xffff0000, v29 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v28, v28, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:112 ; GFX7-NEXT: v_and_b32_e32 v28, 0xffff0000, v28 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v27, v27, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:108 ; GFX7-NEXT: v_and_b32_e32 v27, 0xffff0000, v27 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v26, v26, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:104 ; GFX7-NEXT: v_and_b32_e32 v26, 0xffff0000, v26 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v25, v25, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:100 ; GFX7-NEXT: v_and_b32_e32 v25, 0xffff0000, v25 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v24, v24, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:96 ; GFX7-NEXT: v_and_b32_e32 v24, 0xffff0000, v24 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v23, v23, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:92 ; GFX7-NEXT: v_and_b32_e32 v23, 0xffff0000, v23 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v22, v22, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:88 ; GFX7-NEXT: v_and_b32_e32 v22, 0xffff0000, v22 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v21, v21, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:84 ; GFX7-NEXT: v_and_b32_e32 v21, 0xffff0000, v21 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v20, v20, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:80 ; GFX7-NEXT: v_and_b32_e32 v20, 0xffff0000, v20 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v19, v19, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:76 ; GFX7-NEXT: v_and_b32_e32 v19, 0xffff0000, v19 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v18, v18, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:72 ; GFX7-NEXT: v_and_b32_e32 v18, 0xffff0000, v18 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v17, v17, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:68 ; GFX7-NEXT: v_and_b32_e32 v17, 0xffff0000, v17 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v16, v16, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:64 ; GFX7-NEXT: v_and_b32_e32 v16, 0xffff0000, v16 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v15, v15, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:60 ; GFX7-NEXT: v_and_b32_e32 v15, 0xffff0000, v15 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v14, v14, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:56 ; GFX7-NEXT: v_and_b32_e32 v14, 0xffff0000, v14 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v13, v13, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:52 ; GFX7-NEXT: v_and_b32_e32 v13, 0xffff0000, v13 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v12, v12, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:48 ; GFX7-NEXT: v_and_b32_e32 v12, 0xffff0000, v12 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v11, v11, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:44 ; GFX7-NEXT: v_and_b32_e32 v11, 0xffff0000, v11 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v10, v10, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:40 ; GFX7-NEXT: v_and_b32_e32 v10, 0xffff0000, v10 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v9, v9, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:36 ; GFX7-NEXT: v_and_b32_e32 v9, 0xffff0000, v9 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v8, v8, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:32 ; GFX7-NEXT: v_and_b32_e32 v8, 0xffff0000, v8 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v7, v7, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:28 ; GFX7-NEXT: v_and_b32_e32 v7, 0xffff0000, v7 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v6, v6, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:24 ; GFX7-NEXT: v_and_b32_e32 v6, 0xffff0000, v6 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v5, v5, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:20 ; GFX7-NEXT: v_and_b32_e32 v5, 0xffff0000, v5 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v4, v4, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:16 ; GFX7-NEXT: v_and_b32_e32 v4, 0xffff0000, v4 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v3, v3, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:12 ; GFX7-NEXT: v_and_b32_e32 v3, 0xffff0000, v3 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v2, v2, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:8 ; GFX7-NEXT: v_and_b32_e32 v2, 0xffff0000, v2 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v1, v1, v32 ; GFX7-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:4 ; GFX7-NEXT: v_and_b32_e32 v1, 0xffff0000, v1 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_and_b32_e32 v32, 0xffff0000, v32 -; GFX7-NEXT: v_mul_f32_e32 v32, 1.0, v32 ; GFX7-NEXT: v_max_f32_e32 v0, v0, v32 ; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GFX7-NEXT: s_setpc_b64 s[30:31] @@ -25176,7 +24648,6 @@ define { bfloat, i16 } @v_frexp_bf16_i16(bfloat %a) { ; GCN-NEXT: v_frexp_exp_i32_f32_e32 v2, v0 ; GCN-NEXT: v_cmp_lt_f32_e64 vcc, |v0|, s4 ; GCN-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc -; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GCN-NEXT: v_cndmask_b32_e32 v1, 0, v2, vcc ; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: s_setpc_b64 s[30:31] @@ -26818,11 +26289,17 @@ define bfloat @v_canonicalize_bf16(bfloat %a) { ; GCN-LABEL: v_canonicalize_bf16: ; GCN: ; %bb.0: ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN-NEXT: v_mul_f32_e32 v0, 1.0, v0 +; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 +; GCN-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GCN-NEXT: s_setpc_b64 s[30:31] ; ; GFX7-LABEL: v_canonicalize_bf16: ; GFX7: ; %bb.0: ; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX7-NEXT: v_mul_f32_e32 v0, 1.0, v0 +; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 +; GFX7-NEXT: v_and_b32_e32 v0, 0xffff0000, v0 ; GFX7-NEXT: s_setpc_b64 s[30:31] ; ; GFX8-LABEL: v_canonicalize_bf16: diff --git a/llvm/test/CodeGen/AMDGPU/clamp.ll b/llvm/test/CodeGen/AMDGPU/clamp.ll index dfadd8d205b04e1f660713950e6358711cdb0cc5..947284506a29705f8fd5f4cf472f6ec4c82c67be 100644 --- a/llvm/test/CodeGen/AMDGPU/clamp.ll +++ b/llvm/test/CodeGen/AMDGPU/clamp.ll @@ -2996,18 +2996,16 @@ define amdgpu_kernel void @v_clamp_v2f16_undef_elt(ptr addrspace(1) %out, ptr ad ; GFX6-NEXT: v_mov_b32_e32 v4, 0x7fc00000 ; GFX6-NEXT: s_mov_b64 s[2:3], s[6:7] ; GFX6-NEXT: s_waitcnt vmcnt(0) -; GFX6-NEXT: v_cvt_f32_f16_e32 v3, v2 -; GFX6-NEXT: v_lshrrev_b32_e32 v2, 16, v2 +; GFX6-NEXT: v_lshrrev_b32_e32 v3, 16, v2 ; GFX6-NEXT: v_cvt_f32_f16_e32 v2, v2 -; GFX6-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX6-NEXT: v_max_f32_e32 v3, 0x7fc00000, v3 -; GFX6-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX6-NEXT: v_med3_f32 v2, v2, 0, v4 -; GFX6-NEXT: v_cvt_f16_f32_e32 v2, v2 -; GFX6-NEXT: v_min_f32_e32 v3, 1.0, v3 +; GFX6-NEXT: v_cvt_f32_f16_e32 v3, v3 +; GFX6-NEXT: v_max_f32_e32 v2, 0x7fc00000, v2 +; GFX6-NEXT: v_med3_f32 v3, v3, 0, v4 ; GFX6-NEXT: v_cvt_f16_f32_e32 v3, v3 -; GFX6-NEXT: v_lshlrev_b32_e32 v2, 16, v2 -; GFX6-NEXT: v_or_b32_e32 v2, v3, v2 +; GFX6-NEXT: v_min_f32_e32 v2, 1.0, v2 +; GFX6-NEXT: v_cvt_f16_f32_e32 v2, v2 +; GFX6-NEXT: v_lshlrev_b32_e32 v3, 16, v3 +; GFX6-NEXT: v_or_b32_e32 v2, v2, v3 ; GFX6-NEXT: buffer_store_dword v2, v[0:1], s[0:3], 0 addr64 ; GFX6-NEXT: s_endpgm ; @@ -3095,16 +3093,15 @@ define amdgpu_kernel void @v_clamp_v2f16_not_zero(ptr addrspace(1) %out, ptr add ; GFX6-NEXT: buffer_load_dword v2, v[0:1], s[4:7], 0 addr64 ; GFX6-NEXT: s_mov_b64 s[2:3], s[6:7] ; GFX6-NEXT: s_waitcnt vmcnt(0) -; GFX6-NEXT: v_cvt_f32_f16_e32 v3, v2 -; GFX6-NEXT: v_lshrrev_b32_e32 v2, 16, v2 -; GFX6-NEXT: v_cvt_f32_f16_e64 v2, v2 clamp -; GFX6-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX6-NEXT: v_max_f32_e32 v3, 2.0, v3 -; GFX6-NEXT: v_cvt_f16_f32_e32 v2, v2 -; GFX6-NEXT: v_min_f32_e32 v3, 1.0, v3 +; GFX6-NEXT: v_lshrrev_b32_e32 v3, 16, v2 +; GFX6-NEXT: v_cvt_f32_f16_e32 v2, v2 +; GFX6-NEXT: v_cvt_f32_f16_e64 v3, v3 clamp +; GFX6-NEXT: v_max_f32_e32 v2, 2.0, v2 ; GFX6-NEXT: v_cvt_f16_f32_e32 v3, v3 -; GFX6-NEXT: v_lshlrev_b32_e32 v2, 16, v2 -; GFX6-NEXT: v_or_b32_e32 v2, v3, v2 +; GFX6-NEXT: v_min_f32_e32 v2, 1.0, v2 +; GFX6-NEXT: v_cvt_f16_f32_e32 v2, v2 +; GFX6-NEXT: v_lshlrev_b32_e32 v3, 16, v3 +; GFX6-NEXT: v_or_b32_e32 v2, v2, v3 ; GFX6-NEXT: buffer_store_dword v2, v[0:1], s[0:3], 0 addr64 ; GFX6-NEXT: s_endpgm ; @@ -3198,9 +3195,8 @@ define amdgpu_kernel void @v_clamp_v2f16_not_one(ptr addrspace(1) %out, ptr addr ; GFX6-NEXT: s_mov_b64 s[2:3], s[6:7] ; GFX6-NEXT: s_waitcnt vmcnt(0) ; GFX6-NEXT: v_lshrrev_b32_e32 v3, 16, v2 -; GFX6-NEXT: v_cvt_f32_f16_e32 v2, v2 ; GFX6-NEXT: v_cvt_f32_f16_e64 v3, v3 clamp -; GFX6-NEXT: v_mul_f32_e32 v2, 1.0, v2 +; GFX6-NEXT: v_cvt_f32_f16_e32 v2, v2 ; GFX6-NEXT: v_cvt_f16_f32_e32 v3, v3 ; GFX6-NEXT: v_med3_f32 v2, v2, 0, 0 ; GFX6-NEXT: v_cvt_f16_f32_e32 v2, v2 @@ -3760,19 +3756,17 @@ define amdgpu_kernel void @v_clamp_v2f16_undef_limit_elts0(ptr addrspace(1) %out ; GFX6-NEXT: s_waitcnt lgkmcnt(0) ; GFX6-NEXT: s_mov_b64 s[4:5], s[2:3] ; GFX6-NEXT: buffer_load_dword v2, v[0:1], s[4:7], 0 addr64 -; GFX6-NEXT: s_mov_b32 s2, 0x7fc00000 ; GFX6-NEXT: v_mov_b32_e32 v4, 0x7fc00000 +; GFX6-NEXT: s_mov_b64 s[2:3], s[6:7] ; GFX6-NEXT: s_waitcnt vmcnt(0) ; GFX6-NEXT: v_lshrrev_b32_e32 v3, 16, v2 ; GFX6-NEXT: v_cvt_f32_f16_e32 v3, v3 ; GFX6-NEXT: v_cvt_f32_f16_e32 v2, v2 -; GFX6-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX6-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX6-NEXT: v_med3_f32 v3, v3, s2, 1.0 +; GFX6-NEXT: v_max_f32_e32 v3, 0x7fc00000, v3 +; GFX6-NEXT: v_min_f32_e32 v3, 1.0, v3 ; GFX6-NEXT: v_cvt_f16_f32_e32 v3, v3 ; GFX6-NEXT: v_med3_f32 v2, v2, 0, v4 ; GFX6-NEXT: v_cvt_f16_f32_e32 v2, v2 -; GFX6-NEXT: s_mov_b64 s[2:3], s[6:7] ; GFX6-NEXT: v_lshlrev_b32_e32 v3, 16, v3 ; GFX6-NEXT: v_or_b32_e32 v2, v2, v3 ; GFX6-NEXT: buffer_store_dword v2, v[0:1], s[0:3], 0 addr64 @@ -3863,18 +3857,16 @@ define amdgpu_kernel void @v_clamp_v2f16_undef_limit_elts1(ptr addrspace(1) %out ; GFX6-NEXT: v_mov_b32_e32 v4, 0x7fc00000 ; GFX6-NEXT: s_mov_b64 s[2:3], s[6:7] ; GFX6-NEXT: s_waitcnt vmcnt(0) -; GFX6-NEXT: v_cvt_f32_f16_e32 v3, v2 -; GFX6-NEXT: v_lshrrev_b32_e32 v2, 16, v2 +; GFX6-NEXT: v_lshrrev_b32_e32 v3, 16, v2 ; GFX6-NEXT: v_cvt_f32_f16_e32 v2, v2 -; GFX6-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; GFX6-NEXT: v_max_f32_e32 v3, 0x7fc00000, v3 -; GFX6-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; GFX6-NEXT: v_med3_f32 v2, v2, 0, v4 -; GFX6-NEXT: v_cvt_f16_f32_e32 v2, v2 -; GFX6-NEXT: v_min_f32_e32 v3, 1.0, v3 +; GFX6-NEXT: v_cvt_f32_f16_e32 v3, v3 +; GFX6-NEXT: v_max_f32_e32 v2, 0x7fc00000, v2 +; GFX6-NEXT: v_med3_f32 v3, v3, 0, v4 ; GFX6-NEXT: v_cvt_f16_f32_e32 v3, v3 -; GFX6-NEXT: v_lshlrev_b32_e32 v2, 16, v2 -; GFX6-NEXT: v_or_b32_e32 v2, v3, v2 +; GFX6-NEXT: v_min_f32_e32 v2, 1.0, v2 +; GFX6-NEXT: v_cvt_f16_f32_e32 v2, v2 +; GFX6-NEXT: v_lshlrev_b32_e32 v3, 16, v3 +; GFX6-NEXT: v_or_b32_e32 v2, v2, v3 ; GFX6-NEXT: buffer_store_dword v2, v[0:1], s[0:3], 0 addr64 ; GFX6-NEXT: s_endpgm ; diff --git a/llvm/test/CodeGen/AMDGPU/convergence-tokens.ll b/llvm/test/CodeGen/AMDGPU/convergence-tokens.ll index 2ed6d7fd0f598d22ce841074fac57a42d111ae27..1c8725f52f7eb05397d1c72cc864d68e82f845d4 100644 --- a/llvm/test/CodeGen/AMDGPU/convergence-tokens.ll +++ b/llvm/test/CodeGen/AMDGPU/convergence-tokens.ll @@ -1,10 +1,12 @@ ; RUN: llc --amdgpu-disable-structurizer -stop-after=amdgpu-isel -mtriple=amdgcn-- -mcpu=gfx900 -verify-machineinstrs -o - %s | FileCheck --check-prefixes=CHECK,ISEL %s ; RUN: llc --amdgpu-disable-structurizer -stop-after=dead-mi-elimination -mtriple=amdgcn-- -mcpu=gfx900 -verify-machineinstrs -o - %s | FileCheck --check-prefixes=CHECK,DEADMI %s +; RUN: llc --amdgpu-disable-structurizer -global-isel -stop-after=irtranslator -mtriple=amdgcn-- -mcpu=gfx900 -verify-machineinstrs -o - %s | FileCheck %s --check-prefixes=CHECK,GISEL ; CHECK-LABEL: name: basic_call -; CHECK: [[TOKEN:%[0-9]+]]:sreg_64 = CONVERGENCECTRL_ENTRY -; ISEL: {{.*}} SI_CALL_ISEL {{.*}}, @foo, [[TOKEN]], csr_amdgpu, {{.*}} +; CHECK: [[TOKEN:%[0-9]+]]{{[^ ]*}} = CONVERGENCECTRL_ENTRY +; ISEL: {{.*}} SI_CALL_ISEL {{.*}}, @foo, csr_amdgpu, {{.*}}, implicit [[TOKEN]] ; DEADMI: {{.*}} SI_CALL {{.*}}, @foo, csr_amdgpu, {{.*}}, implicit [[TOKEN]] +; GISEL: {{.*}} G_SI_CALL {{.*}}, @foo, csr_amdgpu, {{.*}}, implicit [[TOKEN]] define i32 @basic_call(i32 %src) #0 { %t = call token @llvm.experimental.convergence.entry() %r = call i32 @foo(i32 %src) [ "convergencectrl"(token %t) ] @@ -12,10 +14,11 @@ define i32 @basic_call(i32 %src) #0 { } ; CHECK-LABEL: name: basic_intrinsic -; CHECK: [[TOKEN:%[0-9]+]]:sreg_64 = CONVERGENCECTRL_ANCHOR +; CHECK: [[TOKEN:%[0-9]+]]{{[^ ]*}} = CONVERGENCECTRL_ANCHOR ; ISEL: CONVERGENCECTRL_GLUE [[TOKEN]] ; DEADMI-NOT: CONVERGENCECTRL_GLUE -; CHECK: {{.*}} = V_READFIRSTLANE_B32 {{.*}}, implicit [[TOKEN]] +; ISEL: {{.*}} = V_READFIRSTLANE_B32 {{.*}}, implicit [[TOKEN]] +; GISEL: {{.*}} = G_INTRINSIC_CONVERGENT intrinsic(@llvm.amdgcn.readfirstlane){{.*}}, implicit [[TOKEN]] define i32 @basic_intrinsic(i32 %src) #0 { %t = call token @llvm.experimental.convergence.anchor() %r = call i32 @llvm.amdgcn.readfirstlane(i32 %src) [ "convergencectrl"(token %t) ] @@ -30,12 +33,13 @@ define i32 @uncontrolled_call(i32 %src) #0 { } ; CHECK-LABEL: name: basic_branch -; CHECK: bb.0.entry: -; CHECK: [[TOKEN:%[0-9]+]]:sreg_64 = CONVERGENCECTRL_ANCHOR -; CHECK: bb.1.then: +; CHECK: bb.[[#]].entry: +; CHECK: [[TOKEN:%[0-9]+]]{{[^ ]*}} = CONVERGENCECTRL_ANCHOR +; CHECK: bb.[[#]].then: ; ISEL: CONVERGENCECTRL_GLUE [[TOKEN]] ; DEADMI-NOT: CONVERGENCECTRL_GLUE -; CHECK: {{.*}} = V_READFIRSTLANE_B32 {{.*}}, implicit [[TOKEN]] +; ISEL: {{.*}} = V_READFIRSTLANE_B32 {{.*}}, implicit [[TOKEN]] +; GISEL: {{.*}} = G_INTRINSIC_CONVERGENT intrinsic(@llvm.amdgcn.readfirstlane){{.*}}, implicit [[TOKEN]] define i32 @basic_branch(i32 %src, i1 %cond) #0 { entry: %t = call token @llvm.experimental.convergence.anchor() @@ -52,12 +56,13 @@ else: } ; CHECK-LABEL: name: basic_loop -; CHECK: [[TOKEN:%[0-9]+]]:sreg_64 = CONVERGENCECTRL_ANCHOR -; CHECK: bb.1.loop: -; CHECK: [[LOOP:%[0-9]+]]:sreg_64 = CONVERGENCECTRL_LOOP [[TOKEN]] +; CHECK: [[TOKEN:%[0-9]+]]{{[^ ]*}} = CONVERGENCECTRL_ANCHOR +; CHECK: bb.[[#]].loop: +; CHECK: [[LOOP:%[0-9]+]]{{[^ ]*}} = CONVERGENCECTRL_LOOP [[TOKEN]] ; ISEL: CONVERGENCECTRL_GLUE [[LOOP]] ; DEADMI-NOT: CONVERGENCECTRL_GLUE -; CHECK: {{.*}} = V_READFIRSTLANE_B32 {{.*}}, implicit [[LOOP]] +; ISEL: {{.*}} = V_READFIRSTLANE_B32 {{.*}}, implicit [[LOOP]] +; GISEL: {{.*}} = G_INTRINSIC_CONVERGENT intrinsic(@llvm.amdgcn.readfirstlane){{.*}}, implicit [[LOOP]] define i32 @basic_loop(i32 %src, i1 %cond) #0 { %t1 = call token @llvm.experimental.convergence.anchor() br label %loop @@ -71,6 +76,32 @@ end: ret i32 %r } +; CHECK-LABEL: name: nested +; CHECK: [[ENTRY:%[0-9]+]]{{[^ ]*}} = CONVERGENCECTRL_ENTRY +; CHECK: [[ANCHOR:%[0-9]+]]{{[^ ]*}} = CONVERGENCECTRL_ANCHOR +; ISEL: {{.*}} = V_READFIRSTLANE_B32 {{.*}}, implicit [[ANCHOR]] +; GISEL: {{.*}} = G_INTRINSIC_CONVERGENT intrinsic(@llvm.amdgcn.readfirstlane){{.*}}, implicit [[ANCHOR]] +; ISEL: {{.*}} = V_READFIRSTLANE_B32 {{.*}}, implicit [[ENTRY]] +; GISEL: {{.*}} = G_INTRINSIC_CONVERGENT intrinsic(@llvm.amdgcn.readfirstlane){{.*}}, implicit [[ENTRY]] +define i32 @nested(i32 %src) #0 { + %t1 = call token @llvm.experimental.convergence.entry() + %t2 = call token @llvm.experimental.convergence.anchor() + %r2 = call i32 @llvm.amdgcn.readfirstlane(i32 %src) [ "convergencectrl"(token %t2) ] + %r1 = call i32 @llvm.amdgcn.readfirstlane(i32 %src) [ "convergencectrl"(token %t1) ] + %sum = add i32 %r1, %r2 + ret i32 %sum +} + +; CHECK-LABEL: name: tail_call_void_func_void +; CHECK: [[TOKEN:%[0-9]+]]{{[^ ]*}} = CONVERGENCECTRL_ENTRY +; CHECK: {{.*}} SI_TCRETURN {{.*}}, @external_void_func_void, 0, csr_amdgpu, {{.*}}implicit [[TOKEN]] +define void @tail_call_void_func_void() #0 { + %t1 = call token @llvm.experimental.convergence.entry() + tail call void @external_void_func_void() [ "convergencectrl"(token %t1) ] + ret void +} + +declare hidden void @external_void_func_void() #0 declare i32 @foo(i32 %x) #0 declare i32 @llvm.amdgcn.readfirstlane(i32) #0 diff --git a/llvm/test/CodeGen/AMDGPU/copy-vgpr-clobber-spill-vgpr.mir b/llvm/test/CodeGen/AMDGPU/copy-vgpr-clobber-spill-vgpr.mir index 895185cb41a39747e6bab9c5627fefe250fbaa1c..577d38e656685e259c234e594dd50210913df98c 100644 --- a/llvm/test/CodeGen/AMDGPU/copy-vgpr-clobber-spill-vgpr.mir +++ b/llvm/test/CodeGen/AMDGPU/copy-vgpr-clobber-spill-vgpr.mir @@ -333,7 +333,7 @@ ret void } - attributes #0 = { "amdgpu-waves-per-eu"="4,4" } + attributes #0 = { "amdgpu-waves-per-eu"="4,4" "amdgpu-no-agpr" } ... --- diff --git a/llvm/test/CodeGen/AMDGPU/direct-indirect-call.ll b/llvm/test/CodeGen/AMDGPU/direct-indirect-call.ll index 0c034192869b18427b3ab56dc4493df6f8a0415b..386f9cd3f9ce739a63282af813804c181f07ec71 100644 --- a/llvm/test/CodeGen/AMDGPU/direct-indirect-call.ll +++ b/llvm/test/CodeGen/AMDGPU/direct-indirect-call.ll @@ -35,6 +35,6 @@ define amdgpu_kernel void @test_direct_indirect_call() { ret void } ;. -; CHECK: attributes #[[ATTR0]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR0]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } ; CHECK: attributes #[[ATTR1]] = { "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } ;. diff --git a/llvm/test/CodeGen/AMDGPU/div_i128.ll b/llvm/test/CodeGen/AMDGPU/div_i128.ll index 2f3d5d9d140c2c79727572ead1e88d769b67b0d2..cf99b5d80e13a8764e53de94ab0d7b096059728e 100644 --- a/llvm/test/CodeGen/AMDGPU/div_i128.ll +++ b/llvm/test/CodeGen/AMDGPU/div_i128.ll @@ -1,10 +1,9 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 -; RUN: llc -global-isel=0 -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -o - %s | FileCheck -check-prefixes=GFX9,GFX9-SDAG %s -; RUN: llc -O0 -global-isel=0 -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -o - %s | FileCheck -check-prefixes=GFX9-O0,GFX9-SDAG-O0 %s +; RUN: llc -global-isel=0 -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -o - %s | FileCheck -check-prefixes=GFX9 %s +; RUN: llc -O0 -global-isel=0 -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -o - %s | FileCheck -check-prefixes=GFX9-O0 %s -; FIXME: GlobalISel missing the power-of-2 cases in legalization. https://github.com/llvm/llvm-project/issues/80671 -; xUN: llc -global-isel=1 -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -o - %s | FileCheck -check-prefixes=GFX9,GFX9 %s -; xUN: llc -O0 -global-isel=1 -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -o - %s | FileCheck -check-prefixes=GFX9-O0,GFX9-O0 %s +; RUN: llc -global-isel=1 -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -o - %s | FileCheck -check-prefixes=GFX9-G %s +; RUN: llc -O0 -global-isel=1 -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -o - %s | FileCheck -check-prefixes=GFX9-G-O0 %s define i128 @v_sdiv_i128_vv(i128 %lhs, i128 %rhs) { ; GFX9-LABEL: v_sdiv_i128_vv: @@ -1223,6 +1222,1158 @@ define i128 @v_sdiv_i128_vv(i128 %lhs, i128 %rhs) { ; GFX9-O0-NEXT: s_mov_b64 exec, s[4:5] ; GFX9-O0-NEXT: s_waitcnt vmcnt(0) ; GFX9-O0-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-G-LABEL: v_sdiv_i128_vv: +; GFX9-G: ; %bb.0: ; %_udiv-special-cases +; GFX9-G-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-G-NEXT: v_ashrrev_i32_e32 v16, 31, v3 +; GFX9-G-NEXT: v_xor_b32_e32 v0, v16, v0 +; GFX9-G-NEXT: v_xor_b32_e32 v1, v16, v1 +; GFX9-G-NEXT: v_sub_co_u32_e32 v10, vcc, v0, v16 +; GFX9-G-NEXT: v_xor_b32_e32 v2, v16, v2 +; GFX9-G-NEXT: v_subb_co_u32_e32 v11, vcc, v1, v16, vcc +; GFX9-G-NEXT: v_ashrrev_i32_e32 v17, 31, v7 +; GFX9-G-NEXT: v_xor_b32_e32 v3, v16, v3 +; GFX9-G-NEXT: v_subb_co_u32_e32 v12, vcc, v2, v16, vcc +; GFX9-G-NEXT: v_subb_co_u32_e32 v13, vcc, v3, v16, vcc +; GFX9-G-NEXT: v_xor_b32_e32 v0, v17, v4 +; GFX9-G-NEXT: v_xor_b32_e32 v1, v17, v5 +; GFX9-G-NEXT: v_sub_co_u32_e32 v18, vcc, v0, v17 +; GFX9-G-NEXT: v_xor_b32_e32 v2, v17, v6 +; GFX9-G-NEXT: v_subb_co_u32_e32 v19, vcc, v1, v17, vcc +; GFX9-G-NEXT: v_xor_b32_e32 v3, v17, v7 +; GFX9-G-NEXT: v_subb_co_u32_e32 v4, vcc, v2, v17, vcc +; GFX9-G-NEXT: v_subb_co_u32_e32 v5, vcc, v3, v17, vcc +; GFX9-G-NEXT: v_or_b32_e32 v0, v18, v4 +; GFX9-G-NEXT: v_or_b32_e32 v1, v19, v5 +; GFX9-G-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[0:1] +; GFX9-G-NEXT: v_or_b32_e32 v0, v10, v12 +; GFX9-G-NEXT: v_or_b32_e32 v1, v11, v13 +; GFX9-G-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[0:1] +; GFX9-G-NEXT: v_ffbh_u32_e32 v1, v18 +; GFX9-G-NEXT: v_ffbh_u32_e32 v0, v19 +; GFX9-G-NEXT: v_add_u32_e32 v1, 32, v1 +; GFX9-G-NEXT: v_ffbh_u32_e32 v2, v4 +; GFX9-G-NEXT: v_min_u32_e32 v0, v0, v1 +; GFX9-G-NEXT: v_ffbh_u32_e32 v1, v5 +; GFX9-G-NEXT: v_add_u32_e32 v2, 32, v2 +; GFX9-G-NEXT: v_cmp_eq_u64_e64 s[6:7], 0, v[4:5] +; GFX9-G-NEXT: v_add_u32_e32 v0, 64, v0 +; GFX9-G-NEXT: v_min_u32_e32 v1, v1, v2 +; GFX9-G-NEXT: v_ffbh_u32_e32 v2, v10 +; GFX9-G-NEXT: v_cndmask_b32_e64 v0, v1, v0, s[6:7] +; GFX9-G-NEXT: v_ffbh_u32_e32 v1, v11 +; GFX9-G-NEXT: v_add_u32_e32 v2, 32, v2 +; GFX9-G-NEXT: v_ffbh_u32_e32 v3, v12 +; GFX9-G-NEXT: v_min_u32_e32 v1, v1, v2 +; GFX9-G-NEXT: v_ffbh_u32_e32 v2, v13 +; GFX9-G-NEXT: v_add_u32_e32 v3, 32, v3 +; GFX9-G-NEXT: v_cmp_eq_u64_e64 s[6:7], 0, v[12:13] +; GFX9-G-NEXT: v_add_u32_e32 v1, 64, v1 +; GFX9-G-NEXT: v_min_u32_e32 v2, v2, v3 +; GFX9-G-NEXT: v_cndmask_b32_e64 v1, v2, v1, s[6:7] +; GFX9-G-NEXT: v_sub_co_u32_e64 v0, s[6:7], v0, v1 +; GFX9-G-NEXT: v_subb_co_u32_e64 v1, s[6:7], 0, 0, s[6:7] +; GFX9-G-NEXT: v_mov_b32_e32 v6, 0x7f +; GFX9-G-NEXT: v_subb_co_u32_e64 v2, s[6:7], 0, 0, s[6:7] +; GFX9-G-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-G-NEXT: v_subb_co_u32_e64 v3, s[6:7], 0, 0, s[6:7] +; GFX9-G-NEXT: v_cmp_gt_u64_e64 s[6:7], v[0:1], v[6:7] +; GFX9-G-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-G-NEXT: v_cndmask_b32_e64 v6, 0, 1, s[6:7] +; GFX9-G-NEXT: v_cmp_lt_u64_e64 s[6:7], 0, v[2:3] +; GFX9-G-NEXT: v_or_b32_e32 v15, v1, v3 +; GFX9-G-NEXT: v_cndmask_b32_e64 v7, 0, 1, s[6:7] +; GFX9-G-NEXT: v_cmp_eq_u64_e64 s[6:7], 0, v[2:3] +; GFX9-G-NEXT: s_mov_b64 s[8:9], 0 +; GFX9-G-NEXT: v_cndmask_b32_e64 v6, v7, v6, s[6:7] +; GFX9-G-NEXT: v_cndmask_b32_e64 v7, 0, 1, s[4:5] +; GFX9-G-NEXT: v_or_b32_e32 v20, v7, v6 +; GFX9-G-NEXT: v_xor_b32_e32 v6, 0x7f, v0 +; GFX9-G-NEXT: v_or_b32_e32 v14, v6, v2 +; GFX9-G-NEXT: v_and_b32_e32 v6, 1, v20 +; GFX9-G-NEXT: v_cmp_ne_u32_e32 vcc, 0, v6 +; GFX9-G-NEXT: v_cndmask_b32_e64 v6, v10, 0, vcc +; GFX9-G-NEXT: v_cndmask_b32_e64 v7, v11, 0, vcc +; GFX9-G-NEXT: v_cndmask_b32_e64 v8, v12, 0, vcc +; GFX9-G-NEXT: v_cndmask_b32_e64 v9, v13, 0, vcc +; GFX9-G-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[14:15] +; GFX9-G-NEXT: v_cndmask_b32_e64 v14, 0, 1, vcc +; GFX9-G-NEXT: v_or_b32_e32 v14, v20, v14 +; GFX9-G-NEXT: v_and_b32_e32 v14, 1, v14 +; GFX9-G-NEXT: v_cmp_ne_u32_e32 vcc, 0, v14 +; GFX9-G-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GFX9-G-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; GFX9-G-NEXT: s_cbranch_execz .LBB0_6 +; GFX9-G-NEXT: ; %bb.1: ; %udiv-bb1 +; GFX9-G-NEXT: v_add_co_u32_e32 v20, vcc, 1, v0 +; GFX9-G-NEXT: v_addc_co_u32_e32 v21, vcc, 0, v1, vcc +; GFX9-G-NEXT: v_addc_co_u32_e32 v22, vcc, 0, v2, vcc +; GFX9-G-NEXT: v_addc_co_u32_e32 v23, vcc, 0, v3, vcc +; GFX9-G-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GFX9-G-NEXT: v_sub_co_u32_e32 v8, vcc, 0x7f, v0 +; GFX9-G-NEXT: v_sub_u32_e32 v0, 64, v8 +; GFX9-G-NEXT: v_lshrrev_b64 v[0:1], v0, v[10:11] +; GFX9-G-NEXT: v_lshlrev_b64 v[2:3], v8, v[12:13] +; GFX9-G-NEXT: v_subrev_u32_e32 v9, 64, v8 +; GFX9-G-NEXT: v_lshlrev_b64 v[6:7], v8, v[10:11] +; GFX9-G-NEXT: v_or_b32_e32 v2, v0, v2 +; GFX9-G-NEXT: v_or_b32_e32 v3, v1, v3 +; GFX9-G-NEXT: v_lshlrev_b64 v[0:1], v9, v[10:11] +; GFX9-G-NEXT: v_cmp_gt_u32_e32 vcc, 64, v8 +; GFX9-G-NEXT: v_cndmask_b32_e32 v6, 0, v6, vcc +; GFX9-G-NEXT: v_cndmask_b32_e32 v7, 0, v7, vcc +; GFX9-G-NEXT: v_cndmask_b32_e32 v0, v0, v2, vcc +; GFX9-G-NEXT: v_cndmask_b32_e32 v1, v1, v3, vcc +; GFX9-G-NEXT: v_cmp_eq_u32_e32 vcc, 0, v8 +; GFX9-G-NEXT: v_cndmask_b32_e32 v8, v0, v12, vcc +; GFX9-G-NEXT: v_cndmask_b32_e32 v9, v1, v13, vcc +; GFX9-G-NEXT: s_mov_b64 s[10:11], s[8:9] +; GFX9-G-NEXT: v_mov_b32_e32 v0, s8 +; GFX9-G-NEXT: v_mov_b32_e32 v1, s9 +; GFX9-G-NEXT: v_mov_b32_e32 v2, s10 +; GFX9-G-NEXT: v_mov_b32_e32 v3, s11 +; GFX9-G-NEXT: s_and_saveexec_b64 s[8:9], s[4:5] +; GFX9-G-NEXT: s_xor_b64 s[12:13], exec, s[8:9] +; GFX9-G-NEXT: s_cbranch_execz .LBB0_5 +; GFX9-G-NEXT: ; %bb.2: ; %udiv-preheader +; GFX9-G-NEXT: v_sub_u32_e32 v2, 64, v20 +; GFX9-G-NEXT: v_lshrrev_b64 v[0:1], v20, v[10:11] +; GFX9-G-NEXT: v_lshlrev_b64 v[2:3], v2, v[12:13] +; GFX9-G-NEXT: v_subrev_u32_e32 v24, 64, v20 +; GFX9-G-NEXT: v_lshrrev_b64 v[14:15], v20, v[12:13] +; GFX9-G-NEXT: v_or_b32_e32 v2, v0, v2 +; GFX9-G-NEXT: v_or_b32_e32 v3, v1, v3 +; GFX9-G-NEXT: v_lshrrev_b64 v[0:1], v24, v[12:13] +; GFX9-G-NEXT: v_cmp_gt_u32_e32 vcc, 64, v20 +; GFX9-G-NEXT: v_cndmask_b32_e32 v0, v0, v2, vcc +; GFX9-G-NEXT: v_cndmask_b32_e32 v1, v1, v3, vcc +; GFX9-G-NEXT: v_cndmask_b32_e32 v14, 0, v14, vcc +; GFX9-G-NEXT: v_cndmask_b32_e32 v15, 0, v15, vcc +; GFX9-G-NEXT: v_add_co_u32_e32 v24, vcc, -1, v18 +; GFX9-G-NEXT: s_mov_b64 s[8:9], 0 +; GFX9-G-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v20 +; GFX9-G-NEXT: v_addc_co_u32_e32 v25, vcc, -1, v19, vcc +; GFX9-G-NEXT: v_cndmask_b32_e64 v12, v0, v10, s[4:5] +; GFX9-G-NEXT: v_cndmask_b32_e64 v13, v1, v11, s[4:5] +; GFX9-G-NEXT: v_addc_co_u32_e32 v26, vcc, -1, v4, vcc +; GFX9-G-NEXT: s_mov_b64 s[10:11], s[8:9] +; GFX9-G-NEXT: v_mov_b32_e32 v0, s8 +; GFX9-G-NEXT: v_addc_co_u32_e32 v27, vcc, -1, v5, vcc +; GFX9-G-NEXT: v_mov_b32_e32 v11, 0 +; GFX9-G-NEXT: v_mov_b32_e32 v1, s9 +; GFX9-G-NEXT: v_mov_b32_e32 v2, s10 +; GFX9-G-NEXT: v_mov_b32_e32 v3, s11 +; GFX9-G-NEXT: .LBB0_3: ; %udiv-do-while +; GFX9-G-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-G-NEXT: v_lshlrev_b64 v[2:3], 1, v[6:7] +; GFX9-G-NEXT: v_lshrrev_b32_e32 v10, 31, v7 +; GFX9-G-NEXT: v_or_b32_e32 v6, v0, v2 +; GFX9-G-NEXT: v_or_b32_e32 v7, v1, v3 +; GFX9-G-NEXT: v_lshlrev_b64 v[2:3], 1, v[12:13] +; GFX9-G-NEXT: v_lshrrev_b32_e32 v12, 31, v9 +; GFX9-G-NEXT: v_lshlrev_b64 v[0:1], 1, v[14:15] +; GFX9-G-NEXT: v_or_b32_e32 v2, v2, v12 +; GFX9-G-NEXT: v_lshrrev_b32_e32 v14, 31, v13 +; GFX9-G-NEXT: v_sub_co_u32_e32 v12, vcc, v24, v2 +; GFX9-G-NEXT: v_or_b32_e32 v0, v0, v14 +; GFX9-G-NEXT: v_subb_co_u32_e32 v12, vcc, v25, v3, vcc +; GFX9-G-NEXT: v_subb_co_u32_e32 v12, vcc, v26, v0, vcc +; GFX9-G-NEXT: v_subb_co_u32_e32 v12, vcc, v27, v1, vcc +; GFX9-G-NEXT: v_ashrrev_i32_e32 v28, 31, v12 +; GFX9-G-NEXT: v_and_b32_e32 v12, v28, v18 +; GFX9-G-NEXT: v_sub_co_u32_e32 v12, vcc, v2, v12 +; GFX9-G-NEXT: v_and_b32_e32 v2, v28, v19 +; GFX9-G-NEXT: v_subb_co_u32_e32 v13, vcc, v3, v2, vcc +; GFX9-G-NEXT: v_and_b32_e32 v2, v28, v4 +; GFX9-G-NEXT: v_subb_co_u32_e32 v14, vcc, v0, v2, vcc +; GFX9-G-NEXT: v_and_b32_e32 v0, v28, v5 +; GFX9-G-NEXT: v_subb_co_u32_e32 v15, vcc, v1, v0, vcc +; GFX9-G-NEXT: v_add_co_u32_e32 v20, vcc, -1, v20 +; GFX9-G-NEXT: v_addc_co_u32_e32 v21, vcc, -1, v21, vcc +; GFX9-G-NEXT: v_addc_co_u32_e32 v22, vcc, -1, v22, vcc +; GFX9-G-NEXT: v_addc_co_u32_e32 v23, vcc, -1, v23, vcc +; GFX9-G-NEXT: v_lshlrev_b64 v[8:9], 1, v[8:9] +; GFX9-G-NEXT: v_or_b32_e32 v0, v20, v22 +; GFX9-G-NEXT: v_or_b32_e32 v1, v21, v23 +; GFX9-G-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[0:1] +; GFX9-G-NEXT: v_or_b32_e32 v8, v8, v10 +; GFX9-G-NEXT: v_and_b32_e32 v10, 1, v28 +; GFX9-G-NEXT: v_mov_b32_e32 v0, v10 +; GFX9-G-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; GFX9-G-NEXT: v_mov_b32_e32 v1, v11 +; GFX9-G-NEXT: s_andn2_b64 exec, exec, s[8:9] +; GFX9-G-NEXT: s_cbranch_execnz .LBB0_3 +; GFX9-G-NEXT: ; %bb.4: ; %Flow +; GFX9-G-NEXT: s_or_b64 exec, exec, s[8:9] +; GFX9-G-NEXT: .LBB0_5: ; %Flow2 +; GFX9-G-NEXT: s_or_b64 exec, exec, s[12:13] +; GFX9-G-NEXT: v_lshlrev_b64 v[2:3], 1, v[6:7] +; GFX9-G-NEXT: v_lshlrev_b64 v[8:9], 1, v[8:9] +; GFX9-G-NEXT: v_lshrrev_b32_e32 v4, 31, v7 +; GFX9-G-NEXT: v_or_b32_e32 v8, v8, v4 +; GFX9-G-NEXT: v_or_b32_e32 v6, v0, v2 +; GFX9-G-NEXT: v_or_b32_e32 v7, v1, v3 +; GFX9-G-NEXT: .LBB0_6: ; %Flow3 +; GFX9-G-NEXT: s_or_b64 exec, exec, s[6:7] +; GFX9-G-NEXT: v_xor_b32_e32 v3, v17, v16 +; GFX9-G-NEXT: v_xor_b32_e32 v0, v6, v3 +; GFX9-G-NEXT: v_xor_b32_e32 v1, v7, v3 +; GFX9-G-NEXT: v_sub_co_u32_e32 v0, vcc, v0, v3 +; GFX9-G-NEXT: v_xor_b32_e32 v2, v8, v3 +; GFX9-G-NEXT: v_subb_co_u32_e32 v1, vcc, v1, v3, vcc +; GFX9-G-NEXT: v_xor_b32_e32 v4, v9, v3 +; GFX9-G-NEXT: v_subb_co_u32_e32 v2, vcc, v2, v3, vcc +; GFX9-G-NEXT: v_subb_co_u32_e32 v3, vcc, v4, v3, vcc +; GFX9-G-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-G-O0-LABEL: v_sdiv_i128_vv: +; GFX9-G-O0: ; %bb.0: ; %_udiv-special-cases +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-G-O0-NEXT: s_xor_saveexec_b64 s[4:5], -1 +; GFX9-G-O0-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:328 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:332 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:336 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v16, off, s[0:3], s32 offset:340 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v12, off, s[0:3], s32 offset:344 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[4:5] +; GFX9-G-O0-NEXT: ; implicit-def: $vgpr8 : SGPR spill to VGPR lane +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v0 +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[20:21], -1 +; GFX9-G-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[20:21] +; GFX9-G-O0-NEXT: ; kill: def $vgpr8 killed $vgpr8 def $vgpr8_vgpr9_vgpr10_vgpr11 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v2 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v3 +; GFX9-G-O0-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:84 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:88 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:92 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v11, off, s[0:3], s32 offset:96 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v7 +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:84 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:88 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v6, off, s[0:3], s32 offset:92 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v7, off, s[0:3], s32 offset:96 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: ; kill: def $vgpr13 killed $vgpr13 def $vgpr13_vgpr14_vgpr15_vgpr16 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v3 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, v2 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v16, v1 +; GFX9-G-O0-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-G-O0-NEXT: s_mov_b64 s[12:13], 0x7f +; GFX9-G-O0-NEXT: ; kill: def $vgpr1_vgpr2 killed $vgpr4_vgpr5 killed $exec +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v7 +; GFX9-G-O0-NEXT: ; kill: def $vgpr3 killed $vgpr1 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v2 +; GFX9-G-O0-NEXT: s_mov_b32 s6, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, s6 +; GFX9-G-O0-NEXT: v_ashrrev_i32_e64 v12, v3, v8 +; GFX9-G-O0-NEXT: ; kill: def $vgpr3 killed $vgpr1 killed $exec +; GFX9-G-O0-NEXT: ; kill: def $vgpr2 killed $vgpr2 killed $vgpr1_vgpr2 killed $exec +; GFX9-G-O0-NEXT: s_mov_b32 s6, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s6 +; GFX9-G-O0-NEXT: v_ashrrev_i32_e64 v10, v1, v2 +; GFX9-G-O0-NEXT: ; kill: def $vgpr1_vgpr2 killed $vgpr13_vgpr14 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v15 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v16 +; GFX9-G-O0-NEXT: ; kill: def $vgpr3 killed $vgpr1 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v2 +; GFX9-G-O0-NEXT: s_mov_b32 s6, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, s6 +; GFX9-G-O0-NEXT: v_ashrrev_i32_e64 v11, v3, v8 +; GFX9-G-O0-NEXT: ; kill: def $vgpr3 killed $vgpr1 killed $exec +; GFX9-G-O0-NEXT: ; kill: def $vgpr2 killed $vgpr2 killed $vgpr1_vgpr2 killed $exec +; GFX9-G-O0-NEXT: s_mov_b32 s6, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s6 +; GFX9-G-O0-NEXT: v_ashrrev_i32_e64 v9, v1, v2 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v2 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v3 +; GFX9-G-O0-NEXT: v_xor_b32_e64 v1, v12, v1 +; GFX9-G-O0-NEXT: v_xor_b32_e64 v4, v12, v2 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v6 +; GFX9-G-O0-NEXT: v_xor_b32_e64 v3, v10, v3 +; GFX9-G-O0-NEXT: v_xor_b32_e64 v2, v10, v2 +; GFX9-G-O0-NEXT: v_sub_co_u32_e64 v1, s[6:7], v1, v12 +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v7, s[6:7], v4, v12, s[6:7] +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v6, s[6:7], v3, v10, s[6:7] +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v5, s[6:7], v2, v10, s[6:7] +; GFX9-G-O0-NEXT: ; kill: def $vgpr1 killed $vgpr1 def $vgpr1_vgpr2_vgpr3_vgpr4 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v5 +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:68 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:72 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:76 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:80 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v14 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v15 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v16 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v7 +; GFX9-G-O0-NEXT: v_xor_b32_e64 v5, v11, v5 +; GFX9-G-O0-NEXT: v_xor_b32_e64 v8, v11, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v14 +; GFX9-G-O0-NEXT: v_xor_b32_e64 v7, v9, v7 +; GFX9-G-O0-NEXT: v_xor_b32_e64 v6, v9, v6 +; GFX9-G-O0-NEXT: v_sub_co_u32_e64 v5, s[6:7], v5, v11 +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v15, s[6:7], v8, v11, s[6:7] +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v14, s[6:7], v7, v9, s[6:7] +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v13, s[6:7], v6, v9, s[6:7] +; GFX9-G-O0-NEXT: ; kill: def $vgpr5 killed $vgpr5 def $vgpr5_vgpr6_vgpr7_vgpr8 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v15 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v14 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v13 +; GFX9-G-O0-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:52 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v6, off, s[0:3], s32 offset:56 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:60 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:64 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_xor_b32_e64 v13, v11, v12 +; GFX9-G-O0-NEXT: buffer_store_dword v13, off, s[0:3], s32 offset:48 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_xor_b32_e64 v11, v11, v12 +; GFX9-G-O0-NEXT: buffer_store_dword v11, off, s[0:3], s32 offset:44 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_xor_b32_e64 v11, v9, v10 +; GFX9-G-O0-NEXT: buffer_store_dword v11, off, s[0:3], s32 offset:40 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_xor_b32_e64 v9, v9, v10 +; GFX9-G-O0-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:36 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v11 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v14 +; GFX9-G-O0-NEXT: v_or_b32_e64 v9, v9, v12 +; GFX9-G-O0-NEXT: v_or_b32_e64 v11, v10, v11 +; GFX9-G-O0-NEXT: ; kill: def $vgpr9 killed $vgpr9 def $vgpr9_vgpr10 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v11 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, s4 +; GFX9-G-O0-NEXT: v_cmp_eq_u64_e64 s[6:7], v[9:10], v[11:12] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v2 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v3 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v11 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v14 +; GFX9-G-O0-NEXT: v_or_b32_e64 v9, v9, v12 +; GFX9-G-O0-NEXT: v_or_b32_e64 v11, v10, v11 +; GFX9-G-O0-NEXT: ; kill: def $vgpr9 killed $vgpr9 def $vgpr9_vgpr10 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v11 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, s4 +; GFX9-G-O0-NEXT: v_cmp_eq_u64_e64 s[8:9], v[9:10], v[11:12] +; GFX9-G-O0-NEXT: s_or_b64 s[6:7], s[6:7], s[8:9] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, s4 +; GFX9-G-O0-NEXT: v_cmp_eq_u64_e64 s[8:9], v[8:9], v[5:6] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v11 +; GFX9-G-O0-NEXT: v_ffbh_u32_e64 v5, v5 +; GFX9-G-O0-NEXT: v_ffbh_u32_e64 v6, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, 32 +; GFX9-G-O0-NEXT: v_add_u32_e64 v6, v6, v7 +; GFX9-G-O0-NEXT: v_min_u32_e64 v5, v5, v6 +; GFX9-G-O0-NEXT: s_mov_b32 s10, 64 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, s10 +; GFX9-G-O0-NEXT: v_add_u32_e64 v6, v5, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v9 +; GFX9-G-O0-NEXT: v_ffbh_u32_e64 v5, v5 +; GFX9-G-O0-NEXT: v_ffbh_u32_e64 v7, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, 32 +; GFX9-G-O0-NEXT: v_add_u32_e64 v7, v7, v8 +; GFX9-G-O0-NEXT: v_min_u32_e64 v5, v5, v7 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v5, v5, v6, s[8:9] +; GFX9-G-O0-NEXT: s_mov_b32 s16, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, v2 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v3 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, s4 +; GFX9-G-O0-NEXT: v_cmp_eq_u64_e64 s[8:9], v[9:10], v[6:7] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v11 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v12 +; GFX9-G-O0-NEXT: v_ffbh_u32_e64 v6, v6 +; GFX9-G-O0-NEXT: v_ffbh_u32_e64 v7, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, 32 +; GFX9-G-O0-NEXT: v_add_u32_e64 v7, v7, v8 +; GFX9-G-O0-NEXT: v_min_u32_e64 v6, v6, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, s10 +; GFX9-G-O0-NEXT: v_add_u32_e64 v7, v6, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v9 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v10 +; GFX9-G-O0-NEXT: v_ffbh_u32_e64 v6, v6 +; GFX9-G-O0-NEXT: v_ffbh_u32_e64 v8, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, 32 +; GFX9-G-O0-NEXT: v_add_u32_e64 v8, v8, v9 +; GFX9-G-O0-NEXT: v_min_u32_e64 v6, v6, v8 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v6, v6, v7, s[8:9] +; GFX9-G-O0-NEXT: s_mov_b32 s15, 0 +; GFX9-G-O0-NEXT: s_mov_b32 s11, 0 +; GFX9-G-O0-NEXT: s_mov_b32 s14, 0 +; GFX9-G-O0-NEXT: s_mov_b32 s10, 0 +; GFX9-G-O0-NEXT: v_sub_co_u32_e64 v6, s[8:9], v5, v6 +; GFX9-G-O0-NEXT: buffer_store_dword v6, off, s[0:3], s32 offset:32 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, s16 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, s16 +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v7, s[8:9], v5, v7, s[8:9] +; GFX9-G-O0-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:28 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, s15 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, s14 +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v9, s[8:9], v5, v8, s[8:9] +; GFX9-G-O0-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:24 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, s11 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, s10 +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v8, s[8:9], v5, v8, s[8:9] +; GFX9-G-O0-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:20 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, v9 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, s4 +; GFX9-G-O0-NEXT: v_cmp_gt_u64_e64 s[10:11], v[12:13], v[14:15] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, s4 +; GFX9-G-O0-NEXT: v_cmp_eq_u64_e64 s[8:9], v[12:13], v[14:15] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, s12 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, s13 +; GFX9-G-O0-NEXT: v_cmp_gt_u64_e64 s[12:13], v[10:11], v[12:13] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, 1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, 0 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v10, v5, v10, s[12:13] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, 1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, 0 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v5, v5, v11, s[10:11] +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v10, v5, v10, s[8:9] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, 1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, 0 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v5, v5, v11, s[6:7] +; GFX9-G-O0-NEXT: v_or_b32_e64 v5, v5, v10 +; GFX9-G-O0-NEXT: s_mov_b32 s7, 0x7f +; GFX9-G-O0-NEXT: s_mov_b32 s6, 0 +; GFX9-G-O0-NEXT: v_xor_b32_e64 v6, v6, s7 +; GFX9-G-O0-NEXT: v_xor_b32_e64 v7, v7, s6 +; GFX9-G-O0-NEXT: v_or_b32_e64 v6, v6, v9 +; GFX9-G-O0-NEXT: v_or_b32_e64 v8, v7, v8 +; GFX9-G-O0-NEXT: ; kill: def $vgpr6 killed $vgpr6 def $vgpr6_vgpr7 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, s4 +; GFX9-G-O0-NEXT: v_cmp_eq_u64_e64 s[4:5], v[6:7], v[8:9] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v2 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v3 +; GFX9-G-O0-NEXT: v_and_b32_e32 v1, 1, v5 +; GFX9-G-O0-NEXT: v_cmp_ne_u32_e64 s[6:7], 0, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v7 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v1, v1, v4, s[6:7] +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v3, v2, v3, s[6:7] +; GFX9-G-O0-NEXT: ; kill: def $vgpr1 killed $vgpr1 def $vgpr1_vgpr2 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v3 +; GFX9-G-O0-NEXT: v_and_b32_e32 v3, 1, v5 +; GFX9-G-O0-NEXT: v_cmp_ne_u32_e64 s[6:7], 0, v3 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v9 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v6, v6, v7, s[6:7] +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v3, v3, v4, s[6:7] +; GFX9-G-O0-NEXT: ; kill: def $vgpr6 killed $vgpr6 def $vgpr6_vgpr7 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v3 +; GFX9-G-O0-NEXT: ; kill: def $vgpr1_vgpr2 killed $vgpr1_vgpr2 def $vgpr1_vgpr2_vgpr3_vgpr4 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, 1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v6, v6, v7, s[4:5] +; GFX9-G-O0-NEXT: v_or_b32_e64 v5, v5, v6 +; GFX9-G-O0-NEXT: v_and_b32_e32 v5, 1, v5 +; GFX9-G-O0-NEXT: v_cmp_ne_u32_e64 s[4:5], 0, v5 +; GFX9-G-O0-NEXT: s_mov_b64 s[6:7], -1 +; GFX9-G-O0-NEXT: s_xor_b64 s[6:7], s[4:5], s[6:7] +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:4 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:8 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:12 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:16 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 s[4:5], exec +; GFX9-G-O0-NEXT: v_writelane_b32 v0, s4, 0 +; GFX9-G-O0-NEXT: v_writelane_b32 v0, s5, 1 +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[20:21], -1 +; GFX9-G-O0-NEXT: buffer_store_dword v0, off, s[0:3], s32 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[20:21] +; GFX9-G-O0-NEXT: s_and_b64 s[4:5], s[4:5], s[6:7] +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[4:5] +; GFX9-G-O0-NEXT: s_cbranch_execz .LBB0_3 +; GFX9-G-O0-NEXT: s_branch .LBB0_8 +; GFX9-G-O0-NEXT: .LBB0_1: ; %Flow +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[20:21], -1 +; GFX9-G-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[20:21] +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: v_readlane_b32 s4, v0, 2 +; GFX9-G-O0-NEXT: v_readlane_b32 s5, v0, 3 +; GFX9-G-O0-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-G-O0-NEXT: ; %bb.2: ; %Flow +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:132 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:136 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v6, off, s[0:3], s32 offset:140 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v7, off, s[0:3], s32 offset:144 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:148 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:152 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v2, off, s[0:3], s32 offset:156 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v3, off, s[0:3], s32 offset:160 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(4) +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:116 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:120 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v6, off, s[0:3], s32 offset:124 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:128 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:100 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:104 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:108 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:112 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_branch .LBB0_5 +; GFX9-G-O0-NEXT: .LBB0_3: ; %Flow2 +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[20:21], -1 +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[20:21] +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: v_readlane_b32 s4, v4, 0 +; GFX9-G-O0-NEXT: v_readlane_b32 s5, v4, 1 +; GFX9-G-O0-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-G-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:4 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:8 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v2, off, s[0:3], s32 offset:12 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v3, off, s[0:3], s32 offset:16 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:164 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:168 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:172 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:176 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_branch .LBB0_9 +; GFX9-G-O0-NEXT: .LBB0_4: ; %udiv-loop-exit +; GFX9-G-O0-NEXT: buffer_load_dword v14, off, s[0:3], s32 offset:180 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v15, off, s[0:3], s32 offset:184 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v16, off, s[0:3], s32 offset:188 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v17, off, s[0:3], s32 offset:192 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:196 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:200 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v6, off, s[0:3], s32 offset:204 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v7, off, s[0:3], s32 offset:208 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v7 +; GFX9-G-O0-NEXT: s_mov_b32 s4, 1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, s4 +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[10:11], v0, v[2:3] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, s4 +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[0:1], v0, v[4:5] +; GFX9-G-O0-NEXT: ; kill: def $vgpr4 killed $vgpr2 killed $exec +; GFX9-G-O0-NEXT: ; kill: def $vgpr3 killed $vgpr3 killed $vgpr2_vgpr3 killed $exec +; GFX9-G-O0-NEXT: s_mov_b32 s4, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-G-O0-NEXT: v_lshrrev_b32_e64 v6, v2, v3 +; GFX9-G-O0-NEXT: s_mov_b32 s4, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, s4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, v14 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v15 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v16 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v17 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, v12 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v11 +; GFX9-G-O0-NEXT: v_or_b32_e64 v0, v0, v7 +; GFX9-G-O0-NEXT: v_or_b32_e64 v5, v1, v5 +; GFX9-G-O0-NEXT: ; kill: def $vgpr0 killed $vgpr0 def $vgpr0_vgpr1 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v9 +; GFX9-G-O0-NEXT: v_or3_b32 v4, v4, v6, v7 +; GFX9-G-O0-NEXT: v_or3_b32 v2, v2, v3, v5 +; GFX9-G-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 def $vgpr4_vgpr5 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v2 +; GFX9-G-O0-NEXT: ; kill: def $vgpr0_vgpr1 killed $vgpr0_vgpr1 def $vgpr0_vgpr1_vgpr2_vgpr3 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v5 +; GFX9-G-O0-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:4 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:8 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:12 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:16 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_branch .LBB0_3 +; GFX9-G-O0-NEXT: .LBB0_5: ; %Flow1 +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[20:21], -1 +; GFX9-G-O0-NEXT: buffer_load_dword v8, off, s[0:3], s32 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[20:21] +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: v_readlane_b32 s4, v8, 4 +; GFX9-G-O0-NEXT: v_readlane_b32 s5, v8, 5 +; GFX9-G-O0-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-G-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:116 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:120 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v2, off, s[0:3], s32 offset:124 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v3, off, s[0:3], s32 offset:128 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:100 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:104 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v6, off, s[0:3], s32 offset:108 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v7, off, s[0:3], s32 offset:112 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:180 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:184 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v6, off, s[0:3], s32 offset:188 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:192 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:196 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:200 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:204 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:208 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_branch .LBB0_4 +; GFX9-G-O0-NEXT: .LBB0_6: ; %udiv-do-while +; GFX9-G-O0-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[20:21], -1 +; GFX9-G-O0-NEXT: buffer_load_dword v16, off, s[0:3], s32 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[20:21] +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: v_readlane_b32 s6, v16, 6 +; GFX9-G-O0-NEXT: v_readlane_b32 s7, v16, 7 +; GFX9-G-O0-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:212 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:216 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v14, off, s[0:3], s32 offset:220 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v15, off, s[0:3], s32 offset:224 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v2, off, s[0:3], s32 offset:228 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v3, off, s[0:3], s32 offset:232 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:236 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:240 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v17, off, s[0:3], s32 offset:244 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v18, off, s[0:3], s32 offset:248 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v19, off, s[0:3], s32 offset:252 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v20, off, s[0:3], s32 offset:256 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v31, off, s[0:3], s32 offset:260 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:264 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:268 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v34, off, s[0:3], s32 offset:272 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:52 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:56 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:60 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:64 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v6, off, s[0:3], s32 offset:276 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v8, off, s[0:3], s32 offset:280 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v10, off, s[0:3], s32 offset:284 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v11, off, s[0:3], s32 offset:288 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(16) +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, v2 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v3 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v5 +; GFX9-G-O0-NEXT: s_mov_b32 s8, 1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, s8 +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[21:22], v2, v[0:1] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, s8 +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[4:5], v2, v[3:4] +; GFX9-G-O0-NEXT: ; kill: def $vgpr2 killed $vgpr0 killed $exec +; GFX9-G-O0-NEXT: ; kill: def $vgpr1 killed $vgpr1 killed $vgpr0_vgpr1 killed $exec +; GFX9-G-O0-NEXT: s_mov_b32 s9, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, s9 +; GFX9-G-O0-NEXT: v_lshrrev_b32_e64 v3, v0, v1 +; GFX9-G-O0-NEXT: s_mov_b32 s9, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s9 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, v5 +; GFX9-G-O0-NEXT: v_or_b32_e64 v7, v2, v3 +; GFX9-G-O0-NEXT: v_or_b32_e64 v5, v0, v1 +; GFX9-G-O0-NEXT: ; kill: def $vgpr0_vgpr1 killed $vgpr12_vgpr13 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, v14 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v15 +; GFX9-G-O0-NEXT: ; kill: def $vgpr2 killed $vgpr0 killed $exec +; GFX9-G-O0-NEXT: ; kill: def $vgpr1 killed $vgpr1 killed $vgpr0_vgpr1 killed $exec +; GFX9-G-O0-NEXT: s_mov_b32 s9, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, s9 +; GFX9-G-O0-NEXT: v_lshrrev_b32_e64 v3, v0, v1 +; GFX9-G-O0-NEXT: s_mov_b32 s9, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s9 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v21 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, v22 +; GFX9-G-O0-NEXT: v_or_b32_e64 v4, v2, v3 +; GFX9-G-O0-NEXT: v_or_b32_e64 v9, v0, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v12 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, v14 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v15 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, s8 +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[23:24], v0, v[2:3] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, s8 +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[0:1], v0, v[12:13] +; GFX9-G-O0-NEXT: ; kill: def $vgpr12 killed $vgpr2 killed $exec +; GFX9-G-O0-NEXT: ; kill: def $vgpr3 killed $vgpr3 killed $vgpr2_vgpr3 killed $exec +; GFX9-G-O0-NEXT: s_mov_b32 s8, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, s8 +; GFX9-G-O0-NEXT: v_lshrrev_b32_e64 v14, v2, v3 +; GFX9-G-O0-NEXT: s_mov_b32 s8, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, s8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, v0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v1 +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(8) +; GFX9-G-O0-NEXT: v_mov_b32_e32 v29, v31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v30, v32 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v21, v33 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v22, v34 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, v29 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v30 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, v23 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v24 +; GFX9-G-O0-NEXT: v_or_b32_e64 v0, v0, v15 +; GFX9-G-O0-NEXT: v_or_b32_e64 v13, v1, v13 +; GFX9-G-O0-NEXT: ; kill: def $vgpr0 killed $vgpr0 def $vgpr0_vgpr1 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, v21 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v22 +; GFX9-G-O0-NEXT: v_or3_b32 v12, v12, v14, v15 +; GFX9-G-O0-NEXT: v_or3_b32 v2, v2, v3, v13 +; GFX9-G-O0-NEXT: ; kill: def $vgpr12 killed $vgpr12 def $vgpr12_vgpr13 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v2 +; GFX9-G-O0-NEXT: ; kill: def $vgpr0_vgpr1 killed $vgpr0_vgpr1 def $vgpr0_vgpr1_vgpr2_vgpr3 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v12 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v13 +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: v_sub_co_u32_e64 v11, s[8:9], v11, v4 +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v10, s[8:9], v10, v9, s[8:9] +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v8, s[8:9], v8, v7, s[8:9] +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v10, s[8:9], v6, v5, s[8:9] +; GFX9-G-O0-NEXT: s_mov_b32 s8, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, s8 +; GFX9-G-O0-NEXT: v_ashrrev_i32_e64 v8, v6, v10 +; GFX9-G-O0-NEXT: s_mov_b32 s8, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, s8 +; GFX9-G-O0-NEXT: v_ashrrev_i32_e64 v6, v6, v10 +; GFX9-G-O0-NEXT: s_mov_b32 s9, 1 +; GFX9-G-O0-NEXT: s_mov_b32 s8, 0 +; GFX9-G-O0-NEXT: v_and_b32_e64 v12, v8, s9 +; GFX9-G-O0-NEXT: v_and_b32_e64 v10, v8, s8 +; GFX9-G-O0-NEXT: ; kill: def $vgpr12 killed $vgpr12 def $vgpr12_vgpr13 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, s4 +; GFX9-G-O0-NEXT: ; kill: def $vgpr12_vgpr13 killed $vgpr12_vgpr13 def $vgpr12_vgpr13_vgpr14_vgpr15 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, v11 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v23, v25 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v24, v26 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v21, v27 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v22, v28 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v23 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v24 +; GFX9-G-O0-NEXT: v_and_b32_e64 v11, v8, v11 +; GFX9-G-O0-NEXT: v_and_b32_e64 v10, v8, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v21 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v21, v22 +; GFX9-G-O0-NEXT: v_and_b32_e64 v8, v6, v8 +; GFX9-G-O0-NEXT: v_and_b32_e64 v6, v6, v21 +; GFX9-G-O0-NEXT: v_sub_co_u32_e64 v4, s[8:9], v4, v11 +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v10, s[8:9], v9, v10, s[8:9] +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v9, s[8:9], v7, v8, s[8:9] +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v8, s[8:9], v5, v6, s[8:9] +; GFX9-G-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 def $vgpr4_vgpr5_vgpr6_vgpr7 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v9 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v17 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v18 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v19 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v20 +; GFX9-G-O0-NEXT: s_mov_b32 s8, -1 +; GFX9-G-O0-NEXT: s_mov_b32 s12, -1 +; GFX9-G-O0-NEXT: s_mov_b32 s11, -1 +; GFX9-G-O0-NEXT: s_mov_b32 s10, -1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v17, s8 +; GFX9-G-O0-NEXT: v_add_co_u32_e64 v17, s[8:9], v11, v17 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, s12 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v18, s[8:9], v10, v11, s[8:9] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, s11 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v20, s[8:9], v9, v10, s[8:9] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, s10 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v19, s[8:9], v8, v9, s[8:9] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v17 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v18 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v20 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v19 +; GFX9-G-O0-NEXT: v_or_b32_e64 v17, v17, v20 +; GFX9-G-O0-NEXT: v_or_b32_e64 v19, v18, v19 +; GFX9-G-O0-NEXT: ; kill: def $vgpr17 killed $vgpr17 def $vgpr17_vgpr18 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v18, v19 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v20, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v19, s4 +; GFX9-G-O0-NEXT: v_cmp_eq_u64_e64 s[4:5], v[17:18], v[19:20] +; GFX9-G-O0-NEXT: s_or_b64 s[4:5], s[4:5], s[6:7] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v20, v3 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v19, v2 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v18, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v17, v0 +; GFX9-G-O0-NEXT: buffer_store_dword v17, off, s[0:3], s32 offset:132 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v18, off, s[0:3], s32 offset:136 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v19, off, s[0:3], s32 offset:140 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v20, off, s[0:3], s32 offset:144 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v20, v15 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v19, v14 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v18, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v17, v12 +; GFX9-G-O0-NEXT: buffer_store_dword v17, off, s[0:3], s32 offset:148 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v18, off, s[0:3], s32 offset:152 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v19, off, s[0:3], s32 offset:156 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v20, off, s[0:3], s32 offset:160 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 s[6:7], s[4:5] +; GFX9-G-O0-NEXT: v_writelane_b32 v16, s6, 2 +; GFX9-G-O0-NEXT: v_writelane_b32 v16, s7, 3 +; GFX9-G-O0-NEXT: s_mov_b64 s[6:7], s[4:5] +; GFX9-G-O0-NEXT: v_writelane_b32 v16, s6, 6 +; GFX9-G-O0-NEXT: v_writelane_b32 v16, s7, 7 +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[20:21], -1 +; GFX9-G-O0-NEXT: buffer_store_dword v16, off, s[0:3], s32 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[20:21] +; GFX9-G-O0-NEXT: buffer_store_dword v12, off, s[0:3], s32 offset:260 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v13, off, s[0:3], s32 offset:264 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v14, off, s[0:3], s32 offset:268 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v15, off, s[0:3], s32 offset:272 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:244 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:248 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:252 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v11, off, s[0:3], s32 offset:256 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:228 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:232 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v6, off, s[0:3], s32 offset:236 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:240 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:212 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:216 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:220 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:224 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-G-O0-NEXT: s_cbranch_execnz .LBB0_6 +; GFX9-G-O0-NEXT: s_branch .LBB0_1 +; GFX9-G-O0-NEXT: .LBB0_7: ; %udiv-preheader +; GFX9-G-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:292 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:296 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v2, off, s[0:3], s32 offset:300 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v3, off, s[0:3], s32 offset:304 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v8, off, s[0:3], s32 offset:308 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v9, off, s[0:3], s32 offset:312 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v10, off, s[0:3], s32 offset:316 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v11, off, s[0:3], s32 offset:320 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[20:21], -1 +; GFX9-G-O0-NEXT: buffer_load_dword v12, off, s[0:3], s32 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[20:21] +; GFX9-G-O0-NEXT: buffer_load_dword v17, off, s[0:3], s32 offset:52 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v18, off, s[0:3], s32 offset:56 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v19, off, s[0:3], s32 offset:60 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v20, off, s[0:3], s32 offset:64 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:324 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:68 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:72 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v6, off, s[0:3], s32 offset:76 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v7, off, s[0:3], s32 offset:80 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b32 s4, 64 +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: v_mov_b32_e32 v16, v5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v22, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v21, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, s4 +; GFX9-G-O0-NEXT: v_sub_u32_e64 v4, v13, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, s4 +; GFX9-G-O0-NEXT: v_sub_u32_e64 v5, v5, v13 +; GFX9-G-O0-NEXT: s_mov_b32 s6, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, s4 +; GFX9-G-O0-NEXT: v_cmp_lt_u32_e64 s[4:5], v13, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, s6 +; GFX9-G-O0-NEXT: v_cmp_eq_u32_e64 s[6:7], v13, v6 +; GFX9-G-O0-NEXT: v_lshrrev_b64 v[6:7], v13, v[21:22] +; GFX9-G-O0-NEXT: v_lshrrev_b64 v[26:27], v13, v[15:16] +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[24:25], v5, v[21:22] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v26 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v27 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v23, v24 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v25 +; GFX9-G-O0-NEXT: v_or_b32_e64 v14, v14, v23 +; GFX9-G-O0-NEXT: v_or_b32_e64 v13, v5, v13 +; GFX9-G-O0-NEXT: s_mov_b64 s[8:9], 0 +; GFX9-G-O0-NEXT: v_lshrrev_b64 v[21:22], v4, v[21:22] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v21 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v22 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v4, v4, v14, s[4:5] +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v5, v5, v13, s[4:5] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v15 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v16 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v4, v4, v14, s[6:7] +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v13, v5, v13, s[6:7] +; GFX9-G-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 def $vgpr4_vgpr5 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v6 +; GFX9-G-O0-NEXT: ; kill: def $vgpr7 killed $vgpr7 killed $vgpr6_vgpr7 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v13, v13, v14, s[4:5] +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v6, v6, v7, s[4:5] +; GFX9-G-O0-NEXT: ; kill: def $vgpr13 killed $vgpr13 def $vgpr13_vgpr14 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v6 +; GFX9-G-O0-NEXT: ; kill: def $vgpr4_vgpr5 killed $vgpr4_vgpr5 def $vgpr4_vgpr5_vgpr6_vgpr7 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v14 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v16, v17 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, v18 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v19 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v20 +; GFX9-G-O0-NEXT: s_mov_b32 s4, -1 +; GFX9-G-O0-NEXT: s_mov_b32 s10, -1 +; GFX9-G-O0-NEXT: s_mov_b32 s7, -1 +; GFX9-G-O0-NEXT: s_mov_b32 s6, -1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v17, s4 +; GFX9-G-O0-NEXT: v_add_co_u32_e64 v16, s[4:5], v16, v17 +; GFX9-G-O0-NEXT: buffer_store_dword v16, off, s[0:3], s32 offset:288 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v16, s10 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v15, s[4:5], v15, v16, s[4:5] +; GFX9-G-O0-NEXT: buffer_store_dword v15, off, s[0:3], s32 offset:284 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, s7 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v14, s[4:5], v14, v15, s[4:5] +; GFX9-G-O0-NEXT: buffer_store_dword v14, off, s[0:3], s32 offset:280 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, s6 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v13, s[4:5], v13, v14, s[4:5] +; GFX9-G-O0-NEXT: buffer_store_dword v13, off, s[0:3], s32 offset:276 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 s[4:5], s[8:9] +; GFX9-G-O0-NEXT: s_mov_b64 s[6:7], s[8:9] +; GFX9-G-O0-NEXT: v_writelane_b32 v12, s8, 6 +; GFX9-G-O0-NEXT: v_writelane_b32 v12, s9, 7 +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[20:21], -1 +; GFX9-G-O0-NEXT: buffer_store_dword v12, off, s[0:3], s32 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[20:21] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, s7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, s6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, s4 +; GFX9-G-O0-NEXT: buffer_store_dword v12, off, s[0:3], s32 offset:260 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v13, off, s[0:3], s32 offset:264 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v14, off, s[0:3], s32 offset:268 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v15, off, s[0:3], s32 offset:272 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:244 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:248 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:252 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v11, off, s[0:3], s32 offset:256 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:228 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:232 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v6, off, s[0:3], s32 offset:236 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:240 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:212 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:216 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:220 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:224 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_branch .LBB0_6 +; GFX9-G-O0-NEXT: .LBB0_8: ; %udiv-bb1 +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[20:21], -1 +; GFX9-G-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[20:21] +; GFX9-G-O0-NEXT: buffer_load_dword v9, off, s[0:3], s32 offset:68 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v10, off, s[0:3], s32 offset:72 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v11, off, s[0:3], s32 offset:76 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:80 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v2, off, s[0:3], s32 offset:32 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:20 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v3, off, s[0:3], s32 offset:24 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:28 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-G-O0-NEXT: s_mov_b32 s6, 1 +; GFX9-G-O0-NEXT: s_mov_b32 s10, 0 +; GFX9-G-O0-NEXT: s_mov_b32 s9, 0 +; GFX9-G-O0-NEXT: s_mov_b32 s8, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, s6 +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(3) +; GFX9-G-O0-NEXT: v_add_co_u32_e64 v5, s[6:7], v2, v5 +; GFX9-G-O0-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:324 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, s10 +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(1) +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v6, s[6:7], v4, v6, s[6:7] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, s9 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v8, s[6:7], v3, v4, s[6:7] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, s8 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v7, s[6:7], v1, v3, s[6:7] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v16, v7 +; GFX9-G-O0-NEXT: buffer_store_dword v13, off, s[0:3], s32 offset:308 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v14, off, s[0:3], s32 offset:312 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v15, off, s[0:3], s32 offset:316 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v16, off, s[0:3], s32 offset:320 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b32 s6, 0x7f +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s6 +; GFX9-G-O0-NEXT: v_sub_co_u32_e64 v4, s[6:7], v1, v2 +; GFX9-G-O0-NEXT: s_mov_b32 s7, 64 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v9 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s7 +; GFX9-G-O0-NEXT: v_sub_u32_e64 v3, v4, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s7 +; GFX9-G-O0-NEXT: v_sub_u32_e64 v9, v1, v4 +; GFX9-G-O0-NEXT: s_mov_b32 s6, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s7 +; GFX9-G-O0-NEXT: v_cmp_lt_u32_e64 s[8:9], v4, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s6 +; GFX9-G-O0-NEXT: v_cmp_eq_u32_e64 s[6:7], v4, v1 +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[1:2], v4, v[13:14] +; GFX9-G-O0-NEXT: v_lshrrev_b64 v[18:19], v9, v[13:14] +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[16:17], v4, v[11:12] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v18 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v19 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, v16 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v17 +; GFX9-G-O0-NEXT: v_or_b32_e64 v10, v10, v15 +; GFX9-G-O0-NEXT: v_or_b32_e64 v4, v4, v9 +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[13:14], v3, v[13:14] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v2 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, 0 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v1, v1, v9, s[8:9] +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v3, v2, v3, s[8:9] +; GFX9-G-O0-NEXT: ; kill: def $vgpr1 killed $vgpr1 def $vgpr1_vgpr2 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v3 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v14 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v9, v9, v10, s[8:9] +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v3, v3, v4, s[8:9] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v11 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v12 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v9, v9, v10, s[6:7] +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v3, v3, v4, s[6:7] +; GFX9-G-O0-NEXT: ; kill: def $vgpr9 killed $vgpr9 def $vgpr9_vgpr10 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v3 +; GFX9-G-O0-NEXT: ; kill: def $vgpr1_vgpr2 killed $vgpr1_vgpr2 def $vgpr1_vgpr2_vgpr3_vgpr4 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v9 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v10 +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:292 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:296 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:300 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:304 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 s[8:9], s[4:5] +; GFX9-G-O0-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX9-G-O0-NEXT: v_or_b32_e64 v5, v5, v8 +; GFX9-G-O0-NEXT: v_or_b32_e64 v7, v6, v7 +; GFX9-G-O0-NEXT: ; kill: def $vgpr5 killed $vgpr5 def $vgpr5_vgpr6 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, s4 +; GFX9-G-O0-NEXT: v_cmp_ne_u64_e64 s[4:5], v[5:6], v[7:8] +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:116 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:120 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:124 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:128 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, s9 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, s10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, s11 +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:100 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:104 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:108 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:112 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 s[6:7], exec +; GFX9-G-O0-NEXT: s_and_b64 s[4:5], s[6:7], s[4:5] +; GFX9-G-O0-NEXT: s_xor_b64 s[6:7], s[4:5], s[6:7] +; GFX9-G-O0-NEXT: v_writelane_b32 v0, s6, 4 +; GFX9-G-O0-NEXT: v_writelane_b32 v0, s7, 5 +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[20:21], -1 +; GFX9-G-O0-NEXT: buffer_store_dword v0, off, s[0:3], s32 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[20:21] +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[4:5] +; GFX9-G-O0-NEXT: s_cbranch_execz .LBB0_5 +; GFX9-G-O0-NEXT: s_branch .LBB0_7 +; GFX9-G-O0-NEXT: .LBB0_9: ; %udiv-end +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[20:21], -1 +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[20:21] +; GFX9-G-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:36 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v6, off, s[0:3], s32 offset:40 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v7, off, s[0:3], s32 offset:44 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v8, off, s[0:3], s32 offset:48 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v9, off, s[0:3], s32 offset:164 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v10, off, s[0:3], s32 offset:168 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v11, off, s[0:3], s32 offset:172 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:176 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v9 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v11 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v12 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v2 +; GFX9-G-O0-NEXT: v_xor_b32_e64 v0, v0, v8 +; GFX9-G-O0-NEXT: v_xor_b32_e64 v1, v1, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v9 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v10 +; GFX9-G-O0-NEXT: v_xor_b32_e64 v2, v2, v6 +; GFX9-G-O0-NEXT: v_xor_b32_e64 v3, v3, v5 +; GFX9-G-O0-NEXT: v_sub_co_u32_e64 v0, s[4:5], v0, v8 +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v1, s[4:5], v1, v7, s[4:5] +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v2, s[4:5], v2, v6, s[4:5] +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v3, s[4:5], v3, v5, s[4:5] +; GFX9-G-O0-NEXT: ; kill: killed $vgpr4 +; GFX9-G-O0-NEXT: s_xor_saveexec_b64 s[4:5], -1 +; GFX9-G-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:328 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_nop 0 +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:332 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v8, off, s[0:3], s32 offset:336 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v16, off, s[0:3], s32 offset:340 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:344 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[4:5] +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: s_setpc_b64 s[30:31] %div = sdiv i128 %lhs, %rhs ret i128 %div } @@ -2306,6 +3457,1043 @@ define i128 @v_udiv_i128_vv(i128 %lhs, i128 %rhs) { ; GFX9-O0-NEXT: s_mov_b64 exec, s[4:5] ; GFX9-O0-NEXT: s_waitcnt vmcnt(0) ; GFX9-O0-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-G-LABEL: v_udiv_i128_vv: +; GFX9-G: ; %bb.0: ; %_udiv-special-cases +; GFX9-G-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-G-NEXT: v_or_b32_e32 v8, v4, v6 +; GFX9-G-NEXT: v_or_b32_e32 v9, v5, v7 +; GFX9-G-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[8:9] +; GFX9-G-NEXT: v_or_b32_e32 v8, v0, v2 +; GFX9-G-NEXT: v_or_b32_e32 v9, v1, v3 +; GFX9-G-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[8:9] +; GFX9-G-NEXT: v_ffbh_u32_e32 v9, v4 +; GFX9-G-NEXT: v_ffbh_u32_e32 v8, v5 +; GFX9-G-NEXT: v_add_u32_e32 v9, 32, v9 +; GFX9-G-NEXT: v_ffbh_u32_e32 v10, v6 +; GFX9-G-NEXT: v_min_u32_e32 v8, v8, v9 +; GFX9-G-NEXT: v_ffbh_u32_e32 v9, v7 +; GFX9-G-NEXT: v_add_u32_e32 v10, 32, v10 +; GFX9-G-NEXT: v_cmp_eq_u64_e64 s[6:7], 0, v[6:7] +; GFX9-G-NEXT: v_add_u32_e32 v8, 64, v8 +; GFX9-G-NEXT: v_min_u32_e32 v9, v9, v10 +; GFX9-G-NEXT: v_ffbh_u32_e32 v10, v0 +; GFX9-G-NEXT: v_cndmask_b32_e64 v8, v9, v8, s[6:7] +; GFX9-G-NEXT: v_ffbh_u32_e32 v9, v1 +; GFX9-G-NEXT: v_add_u32_e32 v10, 32, v10 +; GFX9-G-NEXT: v_ffbh_u32_e32 v11, v2 +; GFX9-G-NEXT: v_min_u32_e32 v9, v9, v10 +; GFX9-G-NEXT: v_ffbh_u32_e32 v10, v3 +; GFX9-G-NEXT: v_add_u32_e32 v11, 32, v11 +; GFX9-G-NEXT: v_cmp_eq_u64_e64 s[6:7], 0, v[2:3] +; GFX9-G-NEXT: v_add_u32_e32 v9, 64, v9 +; GFX9-G-NEXT: v_min_u32_e32 v10, v10, v11 +; GFX9-G-NEXT: v_cndmask_b32_e64 v9, v10, v9, s[6:7] +; GFX9-G-NEXT: v_sub_co_u32_e64 v12, s[6:7], v8, v9 +; GFX9-G-NEXT: v_subb_co_u32_e64 v13, s[6:7], 0, 0, s[6:7] +; GFX9-G-NEXT: v_mov_b32_e32 v8, 0x7f +; GFX9-G-NEXT: v_subb_co_u32_e64 v14, s[6:7], 0, 0, s[6:7] +; GFX9-G-NEXT: v_mov_b32_e32 v9, 0 +; GFX9-G-NEXT: v_subb_co_u32_e64 v15, s[6:7], 0, 0, s[6:7] +; GFX9-G-NEXT: v_cmp_gt_u64_e64 s[6:7], v[12:13], v[8:9] +; GFX9-G-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX9-G-NEXT: v_cndmask_b32_e64 v8, 0, 1, s[6:7] +; GFX9-G-NEXT: v_cmp_lt_u64_e64 s[6:7], 0, v[14:15] +; GFX9-G-NEXT: v_or_b32_e32 v17, v13, v15 +; GFX9-G-NEXT: v_cndmask_b32_e64 v9, 0, 1, s[6:7] +; GFX9-G-NEXT: v_cmp_eq_u64_e64 s[6:7], 0, v[14:15] +; GFX9-G-NEXT: s_mov_b64 s[8:9], 0 +; GFX9-G-NEXT: v_cndmask_b32_e64 v8, v9, v8, s[6:7] +; GFX9-G-NEXT: v_cndmask_b32_e64 v9, 0, 1, s[4:5] +; GFX9-G-NEXT: v_or_b32_e32 v18, v9, v8 +; GFX9-G-NEXT: v_xor_b32_e32 v8, 0x7f, v12 +; GFX9-G-NEXT: v_or_b32_e32 v16, v8, v14 +; GFX9-G-NEXT: v_and_b32_e32 v8, 1, v18 +; GFX9-G-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8 +; GFX9-G-NEXT: v_cndmask_b32_e64 v10, v0, 0, vcc +; GFX9-G-NEXT: v_cndmask_b32_e64 v11, v1, 0, vcc +; GFX9-G-NEXT: v_cndmask_b32_e64 v8, v2, 0, vcc +; GFX9-G-NEXT: v_cndmask_b32_e64 v9, v3, 0, vcc +; GFX9-G-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[16:17] +; GFX9-G-NEXT: v_cndmask_b32_e64 v16, 0, 1, vcc +; GFX9-G-NEXT: v_or_b32_e32 v16, v18, v16 +; GFX9-G-NEXT: v_and_b32_e32 v16, 1, v16 +; GFX9-G-NEXT: v_cmp_ne_u32_e32 vcc, 0, v16 +; GFX9-G-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GFX9-G-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; GFX9-G-NEXT: s_cbranch_execz .LBB1_6 +; GFX9-G-NEXT: ; %bb.1: ; %udiv-bb1 +; GFX9-G-NEXT: v_add_co_u32_e32 v18, vcc, 1, v12 +; GFX9-G-NEXT: v_addc_co_u32_e32 v19, vcc, 0, v13, vcc +; GFX9-G-NEXT: v_addc_co_u32_e32 v20, vcc, 0, v14, vcc +; GFX9-G-NEXT: v_addc_co_u32_e32 v21, vcc, 0, v15, vcc +; GFX9-G-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GFX9-G-NEXT: v_sub_co_u32_e32 v16, vcc, 0x7f, v12 +; GFX9-G-NEXT: v_sub_u32_e32 v8, 64, v16 +; GFX9-G-NEXT: v_lshrrev_b64 v[8:9], v8, v[0:1] +; GFX9-G-NEXT: v_lshlrev_b64 v[10:11], v16, v[2:3] +; GFX9-G-NEXT: v_subrev_u32_e32 v14, 64, v16 +; GFX9-G-NEXT: v_lshlrev_b64 v[12:13], v16, v[0:1] +; GFX9-G-NEXT: v_or_b32_e32 v10, v8, v10 +; GFX9-G-NEXT: v_or_b32_e32 v11, v9, v11 +; GFX9-G-NEXT: v_lshlrev_b64 v[8:9], v14, v[0:1] +; GFX9-G-NEXT: v_cmp_gt_u32_e32 vcc, 64, v16 +; GFX9-G-NEXT: s_mov_b64 s[10:11], s[8:9] +; GFX9-G-NEXT: v_cndmask_b32_e32 v14, 0, v12, vcc +; GFX9-G-NEXT: v_cndmask_b32_e32 v15, 0, v13, vcc +; GFX9-G-NEXT: v_cndmask_b32_e32 v8, v8, v10, vcc +; GFX9-G-NEXT: v_cndmask_b32_e32 v9, v9, v11, vcc +; GFX9-G-NEXT: v_cmp_eq_u32_e32 vcc, 0, v16 +; GFX9-G-NEXT: v_mov_b32_e32 v13, s11 +; GFX9-G-NEXT: v_cndmask_b32_e32 v8, v8, v2, vcc +; GFX9-G-NEXT: v_cndmask_b32_e32 v9, v9, v3, vcc +; GFX9-G-NEXT: v_mov_b32_e32 v11, s9 +; GFX9-G-NEXT: v_mov_b32_e32 v10, s8 +; GFX9-G-NEXT: v_mov_b32_e32 v12, s10 +; GFX9-G-NEXT: s_and_saveexec_b64 s[8:9], s[4:5] +; GFX9-G-NEXT: s_xor_b64 s[12:13], exec, s[8:9] +; GFX9-G-NEXT: s_cbranch_execz .LBB1_5 +; GFX9-G-NEXT: ; %bb.2: ; %udiv-preheader +; GFX9-G-NEXT: v_sub_u32_e32 v12, 64, v18 +; GFX9-G-NEXT: v_subrev_u32_e32 v22, 64, v18 +; GFX9-G-NEXT: v_lshrrev_b64 v[10:11], v18, v[0:1] +; GFX9-G-NEXT: v_lshlrev_b64 v[12:13], v12, v[2:3] +; GFX9-G-NEXT: v_lshrrev_b64 v[16:17], v18, v[2:3] +; GFX9-G-NEXT: v_lshrrev_b64 v[2:3], v22, v[2:3] +; GFX9-G-NEXT: v_or_b32_e32 v10, v10, v12 +; GFX9-G-NEXT: v_or_b32_e32 v11, v11, v13 +; GFX9-G-NEXT: v_cmp_gt_u32_e32 vcc, 64, v18 +; GFX9-G-NEXT: s_mov_b64 s[8:9], 0 +; GFX9-G-NEXT: v_cndmask_b32_e32 v2, v2, v10, vcc +; GFX9-G-NEXT: v_cndmask_b32_e32 v3, v3, v11, vcc +; GFX9-G-NEXT: v_cndmask_b32_e32 v16, 0, v16, vcc +; GFX9-G-NEXT: v_cndmask_b32_e32 v17, 0, v17, vcc +; GFX9-G-NEXT: v_add_co_u32_e32 v22, vcc, -1, v4 +; GFX9-G-NEXT: v_addc_co_u32_e32 v23, vcc, -1, v5, vcc +; GFX9-G-NEXT: s_mov_b64 s[10:11], s[8:9] +; GFX9-G-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v18 +; GFX9-G-NEXT: v_addc_co_u32_e32 v24, vcc, -1, v6, vcc +; GFX9-G-NEXT: v_mov_b32_e32 v13, s11 +; GFX9-G-NEXT: v_cndmask_b32_e64 v2, v2, v0, s[4:5] +; GFX9-G-NEXT: v_cndmask_b32_e64 v3, v3, v1, s[4:5] +; GFX9-G-NEXT: v_addc_co_u32_e32 v25, vcc, -1, v7, vcc +; GFX9-G-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-G-NEXT: v_mov_b32_e32 v11, s9 +; GFX9-G-NEXT: v_mov_b32_e32 v10, s8 +; GFX9-G-NEXT: v_mov_b32_e32 v12, s10 +; GFX9-G-NEXT: .LBB1_3: ; %udiv-do-while +; GFX9-G-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-G-NEXT: v_lshlrev_b64 v[12:13], 1, v[14:15] +; GFX9-G-NEXT: v_lshrrev_b32_e32 v0, 31, v15 +; GFX9-G-NEXT: v_or_b32_e32 v14, v10, v12 +; GFX9-G-NEXT: v_or_b32_e32 v15, v11, v13 +; GFX9-G-NEXT: v_lshlrev_b64 v[12:13], 1, v[16:17] +; GFX9-G-NEXT: v_lshlrev_b64 v[10:11], 1, v[2:3] +; GFX9-G-NEXT: v_lshrrev_b32_e32 v2, 31, v3 +; GFX9-G-NEXT: v_or_b32_e32 v12, v12, v2 +; GFX9-G-NEXT: v_lshrrev_b32_e32 v2, 31, v9 +; GFX9-G-NEXT: v_lshlrev_b64 v[8:9], 1, v[8:9] +; GFX9-G-NEXT: v_or_b32_e32 v2, v10, v2 +; GFX9-G-NEXT: v_or_b32_e32 v8, v8, v0 +; GFX9-G-NEXT: v_sub_co_u32_e32 v0, vcc, v22, v2 +; GFX9-G-NEXT: v_subb_co_u32_e32 v0, vcc, v23, v11, vcc +; GFX9-G-NEXT: v_subb_co_u32_e32 v0, vcc, v24, v12, vcc +; GFX9-G-NEXT: v_subb_co_u32_e32 v0, vcc, v25, v13, vcc +; GFX9-G-NEXT: v_add_co_u32_e64 v18, s[4:5], -1, v18 +; GFX9-G-NEXT: v_ashrrev_i32_e32 v3, 31, v0 +; GFX9-G-NEXT: v_addc_co_u32_e64 v19, s[4:5], -1, v19, s[4:5] +; GFX9-G-NEXT: v_and_b32_e32 v10, v3, v4 +; GFX9-G-NEXT: v_addc_co_u32_e64 v20, s[4:5], -1, v20, s[4:5] +; GFX9-G-NEXT: v_and_b32_e32 v16, v3, v5 +; GFX9-G-NEXT: v_sub_co_u32_e32 v2, vcc, v2, v10 +; GFX9-G-NEXT: v_addc_co_u32_e64 v21, s[4:5], -1, v21, s[4:5] +; GFX9-G-NEXT: v_and_b32_e32 v0, 1, v3 +; GFX9-G-NEXT: v_and_b32_e32 v17, v3, v6 +; GFX9-G-NEXT: v_and_b32_e32 v26, v3, v7 +; GFX9-G-NEXT: v_subb_co_u32_e32 v3, vcc, v11, v16, vcc +; GFX9-G-NEXT: v_or_b32_e32 v10, v18, v20 +; GFX9-G-NEXT: v_or_b32_e32 v11, v19, v21 +; GFX9-G-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[10:11] +; GFX9-G-NEXT: v_subb_co_u32_e32 v16, vcc, v12, v17, vcc +; GFX9-G-NEXT: v_mov_b32_e32 v11, v1 +; GFX9-G-NEXT: v_subb_co_u32_e32 v17, vcc, v13, v26, vcc +; GFX9-G-NEXT: s_or_b64 s[8:9], s[4:5], s[8:9] +; GFX9-G-NEXT: v_mov_b32_e32 v10, v0 +; GFX9-G-NEXT: s_andn2_b64 exec, exec, s[8:9] +; GFX9-G-NEXT: s_cbranch_execnz .LBB1_3 +; GFX9-G-NEXT: ; %bb.4: ; %Flow +; GFX9-G-NEXT: s_or_b64 exec, exec, s[8:9] +; GFX9-G-NEXT: .LBB1_5: ; %Flow2 +; GFX9-G-NEXT: s_or_b64 exec, exec, s[12:13] +; GFX9-G-NEXT: v_lshlrev_b64 v[0:1], 1, v[14:15] +; GFX9-G-NEXT: v_lshlrev_b64 v[8:9], 1, v[8:9] +; GFX9-G-NEXT: v_lshrrev_b32_e32 v2, 31, v15 +; GFX9-G-NEXT: v_or_b32_e32 v8, v8, v2 +; GFX9-G-NEXT: v_or_b32_e32 v10, v10, v0 +; GFX9-G-NEXT: v_or_b32_e32 v11, v11, v1 +; GFX9-G-NEXT: .LBB1_6: ; %Flow3 +; GFX9-G-NEXT: s_or_b64 exec, exec, s[6:7] +; GFX9-G-NEXT: v_mov_b32_e32 v0, v10 +; GFX9-G-NEXT: v_mov_b32_e32 v1, v11 +; GFX9-G-NEXT: v_mov_b32_e32 v2, v8 +; GFX9-G-NEXT: v_mov_b32_e32 v3, v9 +; GFX9-G-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-G-O0-LABEL: v_udiv_i128_vv: +; GFX9-G-O0: ; %bb.0: ; %_udiv-special-cases +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-G-O0-NEXT: s_xor_saveexec_b64 s[4:5], -1 +; GFX9-G-O0-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:300 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:304 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:308 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v16, off, s[0:3], s32 offset:312 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v12, off, s[0:3], s32 offset:316 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[4:5] +; GFX9-G-O0-NEXT: ; implicit-def: $vgpr8 : SGPR spill to VGPR lane +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v0 +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[18:19], -1 +; GFX9-G-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[18:19] +; GFX9-G-O0-NEXT: ; kill: def $vgpr8 killed $vgpr8 def $vgpr8_vgpr9_vgpr10_vgpr11 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v2 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v3 +; GFX9-G-O0-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:56 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:60 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:64 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v11, off, s[0:3], s32 offset:68 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v4 +; GFX9-G-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:56 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v2, off, s[0:3], s32 offset:60 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v3, off, s[0:3], s32 offset:64 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:68 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_nop 0 +; GFX9-G-O0-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:52 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v5 +; GFX9-G-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:52 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v7 +; GFX9-G-O0-NEXT: ; kill: def $vgpr5 killed $vgpr5 def $vgpr5_vgpr6_vgpr7_vgpr8 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v11 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v9 +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:36 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v6, off, s[0:3], s32 offset:40 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:44 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:48 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v11 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v14 +; GFX9-G-O0-NEXT: v_or_b32_e64 v9, v9, v12 +; GFX9-G-O0-NEXT: v_or_b32_e64 v11, v10, v11 +; GFX9-G-O0-NEXT: ; kill: def $vgpr9 killed $vgpr9 def $vgpr9_vgpr10 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v11 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, s4 +; GFX9-G-O0-NEXT: v_cmp_eq_u64_e64 s[6:7], v[9:10], v[11:12] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v2 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v3 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v11 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v14 +; GFX9-G-O0-NEXT: v_or_b32_e64 v9, v9, v12 +; GFX9-G-O0-NEXT: v_or_b32_e64 v11, v10, v11 +; GFX9-G-O0-NEXT: ; kill: def $vgpr9 killed $vgpr9 def $vgpr9_vgpr10 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v11 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, s4 +; GFX9-G-O0-NEXT: v_cmp_eq_u64_e64 s[8:9], v[9:10], v[11:12] +; GFX9-G-O0-NEXT: s_or_b64 s[6:7], s[6:7], s[8:9] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, s4 +; GFX9-G-O0-NEXT: v_cmp_eq_u64_e64 s[8:9], v[8:9], v[5:6] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v11 +; GFX9-G-O0-NEXT: v_ffbh_u32_e64 v5, v5 +; GFX9-G-O0-NEXT: v_ffbh_u32_e64 v6, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, 32 +; GFX9-G-O0-NEXT: v_add_u32_e64 v6, v6, v7 +; GFX9-G-O0-NEXT: v_min_u32_e64 v5, v5, v6 +; GFX9-G-O0-NEXT: s_mov_b32 s10, 64 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, s10 +; GFX9-G-O0-NEXT: v_add_u32_e64 v6, v5, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v9 +; GFX9-G-O0-NEXT: v_ffbh_u32_e64 v5, v5 +; GFX9-G-O0-NEXT: v_ffbh_u32_e64 v7, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, 32 +; GFX9-G-O0-NEXT: v_add_u32_e64 v7, v7, v8 +; GFX9-G-O0-NEXT: v_min_u32_e64 v5, v5, v7 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v5, v5, v6, s[8:9] +; GFX9-G-O0-NEXT: s_mov_b32 s14, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, v2 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v3 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, s4 +; GFX9-G-O0-NEXT: v_cmp_eq_u64_e64 s[8:9], v[9:10], v[6:7] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v11 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v12 +; GFX9-G-O0-NEXT: v_ffbh_u32_e64 v6, v6 +; GFX9-G-O0-NEXT: v_ffbh_u32_e64 v7, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, 32 +; GFX9-G-O0-NEXT: v_add_u32_e64 v7, v7, v8 +; GFX9-G-O0-NEXT: v_min_u32_e64 v6, v6, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, s10 +; GFX9-G-O0-NEXT: v_add_u32_e64 v7, v6, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v9 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v10 +; GFX9-G-O0-NEXT: v_ffbh_u32_e64 v6, v6 +; GFX9-G-O0-NEXT: v_ffbh_u32_e64 v8, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, 32 +; GFX9-G-O0-NEXT: v_add_u32_e64 v8, v8, v9 +; GFX9-G-O0-NEXT: v_min_u32_e64 v6, v6, v8 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v6, v6, v7, s[8:9] +; GFX9-G-O0-NEXT: s_mov_b32 s13, 0 +; GFX9-G-O0-NEXT: s_mov_b32 s11, 0 +; GFX9-G-O0-NEXT: s_mov_b32 s12, 0 +; GFX9-G-O0-NEXT: s_mov_b32 s10, 0 +; GFX9-G-O0-NEXT: v_sub_co_u32_e64 v6, s[8:9], v5, v6 +; GFX9-G-O0-NEXT: buffer_store_dword v6, off, s[0:3], s32 offset:32 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, s14 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, s14 +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v7, s[8:9], v5, v7, s[8:9] +; GFX9-G-O0-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:28 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, s13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, s12 +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v9, s[8:9], v5, v8, s[8:9] +; GFX9-G-O0-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:24 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, s11 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, s10 +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v8, s[8:9], v5, v8, s[8:9] +; GFX9-G-O0-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:20 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 s[12:13], 0x7f +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, v9 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, s4 +; GFX9-G-O0-NEXT: v_cmp_gt_u64_e64 s[10:11], v[12:13], v[14:15] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, s4 +; GFX9-G-O0-NEXT: v_cmp_eq_u64_e64 s[8:9], v[12:13], v[14:15] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, s12 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, s13 +; GFX9-G-O0-NEXT: v_cmp_gt_u64_e64 s[12:13], v[10:11], v[12:13] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, 1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, 0 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v10, v5, v10, s[12:13] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, 1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, 0 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v5, v5, v11, s[10:11] +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v10, v5, v10, s[8:9] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, 1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, 0 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v5, v5, v11, s[6:7] +; GFX9-G-O0-NEXT: v_or_b32_e64 v5, v5, v10 +; GFX9-G-O0-NEXT: s_mov_b32 s7, 0x7f +; GFX9-G-O0-NEXT: s_mov_b32 s6, 0 +; GFX9-G-O0-NEXT: v_xor_b32_e64 v6, v6, s7 +; GFX9-G-O0-NEXT: v_xor_b32_e64 v7, v7, s6 +; GFX9-G-O0-NEXT: v_or_b32_e64 v6, v6, v9 +; GFX9-G-O0-NEXT: v_or_b32_e64 v8, v7, v8 +; GFX9-G-O0-NEXT: ; kill: def $vgpr6 killed $vgpr6 def $vgpr6_vgpr7 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, s4 +; GFX9-G-O0-NEXT: v_cmp_eq_u64_e64 s[4:5], v[6:7], v[8:9] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v2 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v3 +; GFX9-G-O0-NEXT: v_and_b32_e32 v1, 1, v5 +; GFX9-G-O0-NEXT: v_cmp_ne_u32_e64 s[6:7], 0, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v7 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v1, v1, v4, s[6:7] +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v3, v2, v3, s[6:7] +; GFX9-G-O0-NEXT: ; kill: def $vgpr1 killed $vgpr1 def $vgpr1_vgpr2 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v3 +; GFX9-G-O0-NEXT: v_and_b32_e32 v3, 1, v5 +; GFX9-G-O0-NEXT: v_cmp_ne_u32_e64 s[6:7], 0, v3 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v9 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v6, v6, v7, s[6:7] +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v3, v3, v4, s[6:7] +; GFX9-G-O0-NEXT: ; kill: def $vgpr6 killed $vgpr6 def $vgpr6_vgpr7 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v3 +; GFX9-G-O0-NEXT: ; kill: def $vgpr1_vgpr2 killed $vgpr1_vgpr2 def $vgpr1_vgpr2_vgpr3_vgpr4 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, 1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v6, v6, v7, s[4:5] +; GFX9-G-O0-NEXT: v_or_b32_e64 v5, v5, v6 +; GFX9-G-O0-NEXT: v_and_b32_e32 v5, 1, v5 +; GFX9-G-O0-NEXT: v_cmp_ne_u32_e64 s[4:5], 0, v5 +; GFX9-G-O0-NEXT: s_mov_b64 s[6:7], -1 +; GFX9-G-O0-NEXT: s_xor_b64 s[6:7], s[4:5], s[6:7] +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:4 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:8 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:12 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:16 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 s[4:5], exec +; GFX9-G-O0-NEXT: v_writelane_b32 v0, s4, 0 +; GFX9-G-O0-NEXT: v_writelane_b32 v0, s5, 1 +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[18:19], -1 +; GFX9-G-O0-NEXT: buffer_store_dword v0, off, s[0:3], s32 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[18:19] +; GFX9-G-O0-NEXT: s_and_b64 s[4:5], s[4:5], s[6:7] +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[4:5] +; GFX9-G-O0-NEXT: s_cbranch_execz .LBB1_3 +; GFX9-G-O0-NEXT: s_branch .LBB1_8 +; GFX9-G-O0-NEXT: .LBB1_1: ; %Flow +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[18:19], -1 +; GFX9-G-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[18:19] +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: v_readlane_b32 s4, v0, 2 +; GFX9-G-O0-NEXT: v_readlane_b32 s5, v0, 3 +; GFX9-G-O0-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-G-O0-NEXT: ; %bb.2: ; %Flow +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:104 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:108 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v6, off, s[0:3], s32 offset:112 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v7, off, s[0:3], s32 offset:116 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:120 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:124 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v2, off, s[0:3], s32 offset:128 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v3, off, s[0:3], s32 offset:132 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(4) +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:88 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:92 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v6, off, s[0:3], s32 offset:96 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:100 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:72 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:76 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:80 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:84 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_branch .LBB1_5 +; GFX9-G-O0-NEXT: .LBB1_3: ; %Flow2 +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[18:19], -1 +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[18:19] +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: v_readlane_b32 s4, v4, 0 +; GFX9-G-O0-NEXT: v_readlane_b32 s5, v4, 1 +; GFX9-G-O0-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-G-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:4 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:8 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v2, off, s[0:3], s32 offset:12 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v3, off, s[0:3], s32 offset:16 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:136 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:140 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:144 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:148 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_branch .LBB1_9 +; GFX9-G-O0-NEXT: .LBB1_4: ; %udiv-loop-exit +; GFX9-G-O0-NEXT: buffer_load_dword v14, off, s[0:3], s32 offset:152 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v15, off, s[0:3], s32 offset:156 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v16, off, s[0:3], s32 offset:160 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v17, off, s[0:3], s32 offset:164 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:168 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:172 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v6, off, s[0:3], s32 offset:176 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v7, off, s[0:3], s32 offset:180 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v7 +; GFX9-G-O0-NEXT: s_mov_b32 s4, 1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, s4 +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[10:11], v0, v[2:3] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, s4 +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[0:1], v0, v[4:5] +; GFX9-G-O0-NEXT: ; kill: def $vgpr4 killed $vgpr2 killed $exec +; GFX9-G-O0-NEXT: ; kill: def $vgpr3 killed $vgpr3 killed $vgpr2_vgpr3 killed $exec +; GFX9-G-O0-NEXT: s_mov_b32 s4, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-G-O0-NEXT: v_lshrrev_b32_e64 v6, v2, v3 +; GFX9-G-O0-NEXT: s_mov_b32 s4, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, s4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, v14 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v15 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v16 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v17 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, v12 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v11 +; GFX9-G-O0-NEXT: v_or_b32_e64 v0, v0, v7 +; GFX9-G-O0-NEXT: v_or_b32_e64 v5, v1, v5 +; GFX9-G-O0-NEXT: ; kill: def $vgpr0 killed $vgpr0 def $vgpr0_vgpr1 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v9 +; GFX9-G-O0-NEXT: v_or3_b32 v4, v4, v6, v7 +; GFX9-G-O0-NEXT: v_or3_b32 v2, v2, v3, v5 +; GFX9-G-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 def $vgpr4_vgpr5 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v2 +; GFX9-G-O0-NEXT: ; kill: def $vgpr0_vgpr1 killed $vgpr0_vgpr1 def $vgpr0_vgpr1_vgpr2_vgpr3 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v5 +; GFX9-G-O0-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:4 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:8 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:12 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:16 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_branch .LBB1_3 +; GFX9-G-O0-NEXT: .LBB1_5: ; %Flow1 +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[18:19], -1 +; GFX9-G-O0-NEXT: buffer_load_dword v8, off, s[0:3], s32 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[18:19] +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: v_readlane_b32 s4, v8, 4 +; GFX9-G-O0-NEXT: v_readlane_b32 s5, v8, 5 +; GFX9-G-O0-NEXT: s_or_b64 exec, exec, s[4:5] +; GFX9-G-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:88 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:92 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v2, off, s[0:3], s32 offset:96 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v3, off, s[0:3], s32 offset:100 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:72 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:76 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v6, off, s[0:3], s32 offset:80 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v7, off, s[0:3], s32 offset:84 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:152 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:156 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v6, off, s[0:3], s32 offset:160 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:164 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:168 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:172 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:176 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:180 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_branch .LBB1_4 +; GFX9-G-O0-NEXT: .LBB1_6: ; %udiv-do-while +; GFX9-G-O0-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[18:19], -1 +; GFX9-G-O0-NEXT: buffer_load_dword v16, off, s[0:3], s32 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[18:19] +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: v_readlane_b32 s6, v16, 6 +; GFX9-G-O0-NEXT: v_readlane_b32 s7, v16, 7 +; GFX9-G-O0-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:184 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:188 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v14, off, s[0:3], s32 offset:192 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v15, off, s[0:3], s32 offset:196 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v2, off, s[0:3], s32 offset:200 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v3, off, s[0:3], s32 offset:204 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:208 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:212 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v17, off, s[0:3], s32 offset:216 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v18, off, s[0:3], s32 offset:220 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v19, off, s[0:3], s32 offset:224 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v20, off, s[0:3], s32 offset:228 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v31, off, s[0:3], s32 offset:232 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:236 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:240 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v34, off, s[0:3], s32 offset:244 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:36 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:40 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:44 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:48 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v6, off, s[0:3], s32 offset:248 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v8, off, s[0:3], s32 offset:252 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v10, off, s[0:3], s32 offset:256 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v11, off, s[0:3], s32 offset:260 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(16) +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, v2 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v3 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v5 +; GFX9-G-O0-NEXT: s_mov_b32 s8, 1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, s8 +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[21:22], v2, v[0:1] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, s8 +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[4:5], v2, v[3:4] +; GFX9-G-O0-NEXT: ; kill: def $vgpr2 killed $vgpr0 killed $exec +; GFX9-G-O0-NEXT: ; kill: def $vgpr1 killed $vgpr1 killed $vgpr0_vgpr1 killed $exec +; GFX9-G-O0-NEXT: s_mov_b32 s9, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, s9 +; GFX9-G-O0-NEXT: v_lshrrev_b32_e64 v3, v0, v1 +; GFX9-G-O0-NEXT: s_mov_b32 s9, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s9 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, v5 +; GFX9-G-O0-NEXT: v_or_b32_e64 v7, v2, v3 +; GFX9-G-O0-NEXT: v_or_b32_e64 v5, v0, v1 +; GFX9-G-O0-NEXT: ; kill: def $vgpr0_vgpr1 killed $vgpr12_vgpr13 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, v14 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v15 +; GFX9-G-O0-NEXT: ; kill: def $vgpr2 killed $vgpr0 killed $exec +; GFX9-G-O0-NEXT: ; kill: def $vgpr1 killed $vgpr1 killed $vgpr0_vgpr1 killed $exec +; GFX9-G-O0-NEXT: s_mov_b32 s9, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, s9 +; GFX9-G-O0-NEXT: v_lshrrev_b32_e64 v3, v0, v1 +; GFX9-G-O0-NEXT: s_mov_b32 s9, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s9 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v21 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, v22 +; GFX9-G-O0-NEXT: v_or_b32_e64 v4, v2, v3 +; GFX9-G-O0-NEXT: v_or_b32_e64 v9, v0, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v12 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, v14 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v15 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, s8 +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[23:24], v0, v[2:3] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, s8 +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[0:1], v0, v[12:13] +; GFX9-G-O0-NEXT: ; kill: def $vgpr12 killed $vgpr2 killed $exec +; GFX9-G-O0-NEXT: ; kill: def $vgpr3 killed $vgpr3 killed $vgpr2_vgpr3 killed $exec +; GFX9-G-O0-NEXT: s_mov_b32 s8, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, s8 +; GFX9-G-O0-NEXT: v_lshrrev_b32_e64 v14, v2, v3 +; GFX9-G-O0-NEXT: s_mov_b32 s8, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, s8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, v0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v1 +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(8) +; GFX9-G-O0-NEXT: v_mov_b32_e32 v29, v31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v30, v32 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v21, v33 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v22, v34 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, v29 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v30 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, v23 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v24 +; GFX9-G-O0-NEXT: v_or_b32_e64 v0, v0, v15 +; GFX9-G-O0-NEXT: v_or_b32_e64 v13, v1, v13 +; GFX9-G-O0-NEXT: ; kill: def $vgpr0 killed $vgpr0 def $vgpr0_vgpr1 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, v21 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v22 +; GFX9-G-O0-NEXT: v_or3_b32 v12, v12, v14, v15 +; GFX9-G-O0-NEXT: v_or3_b32 v2, v2, v3, v13 +; GFX9-G-O0-NEXT: ; kill: def $vgpr12 killed $vgpr12 def $vgpr12_vgpr13 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v2 +; GFX9-G-O0-NEXT: ; kill: def $vgpr0_vgpr1 killed $vgpr0_vgpr1 def $vgpr0_vgpr1_vgpr2_vgpr3 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v12 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v13 +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: v_sub_co_u32_e64 v11, s[8:9], v11, v4 +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v10, s[8:9], v10, v9, s[8:9] +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v8, s[8:9], v8, v7, s[8:9] +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v10, s[8:9], v6, v5, s[8:9] +; GFX9-G-O0-NEXT: s_mov_b32 s8, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, s8 +; GFX9-G-O0-NEXT: v_ashrrev_i32_e64 v8, v6, v10 +; GFX9-G-O0-NEXT: s_mov_b32 s8, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, s8 +; GFX9-G-O0-NEXT: v_ashrrev_i32_e64 v6, v6, v10 +; GFX9-G-O0-NEXT: s_mov_b32 s9, 1 +; GFX9-G-O0-NEXT: s_mov_b32 s8, 0 +; GFX9-G-O0-NEXT: v_and_b32_e64 v12, v8, s9 +; GFX9-G-O0-NEXT: v_and_b32_e64 v10, v8, s8 +; GFX9-G-O0-NEXT: ; kill: def $vgpr12 killed $vgpr12 def $vgpr12_vgpr13 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, s4 +; GFX9-G-O0-NEXT: ; kill: def $vgpr12_vgpr13 killed $vgpr12_vgpr13 def $vgpr12_vgpr13_vgpr14_vgpr15 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, v11 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v23, v25 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v24, v26 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v21, v27 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v22, v28 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v23 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v24 +; GFX9-G-O0-NEXT: v_and_b32_e64 v11, v8, v11 +; GFX9-G-O0-NEXT: v_and_b32_e64 v10, v8, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v21 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v21, v22 +; GFX9-G-O0-NEXT: v_and_b32_e64 v8, v6, v8 +; GFX9-G-O0-NEXT: v_and_b32_e64 v6, v6, v21 +; GFX9-G-O0-NEXT: v_sub_co_u32_e64 v4, s[8:9], v4, v11 +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v10, s[8:9], v9, v10, s[8:9] +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v9, s[8:9], v7, v8, s[8:9] +; GFX9-G-O0-NEXT: v_subb_co_u32_e64 v8, s[8:9], v5, v6, s[8:9] +; GFX9-G-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 def $vgpr4_vgpr5_vgpr6_vgpr7 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v9 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v17 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v18 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v19 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v20 +; GFX9-G-O0-NEXT: s_mov_b32 s8, -1 +; GFX9-G-O0-NEXT: s_mov_b32 s12, -1 +; GFX9-G-O0-NEXT: s_mov_b32 s11, -1 +; GFX9-G-O0-NEXT: s_mov_b32 s10, -1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v17, s8 +; GFX9-G-O0-NEXT: v_add_co_u32_e64 v17, s[8:9], v11, v17 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, s12 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v18, s[8:9], v10, v11, s[8:9] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, s11 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v20, s[8:9], v9, v10, s[8:9] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, s10 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v19, s[8:9], v8, v9, s[8:9] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, v17 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v18 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v20 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v11, v19 +; GFX9-G-O0-NEXT: v_or_b32_e64 v17, v17, v20 +; GFX9-G-O0-NEXT: v_or_b32_e64 v19, v18, v19 +; GFX9-G-O0-NEXT: ; kill: def $vgpr17 killed $vgpr17 def $vgpr17_vgpr18 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v18, v19 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v20, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v19, s4 +; GFX9-G-O0-NEXT: v_cmp_eq_u64_e64 s[4:5], v[17:18], v[19:20] +; GFX9-G-O0-NEXT: s_or_b64 s[4:5], s[4:5], s[6:7] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v20, v3 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v19, v2 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v18, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v17, v0 +; GFX9-G-O0-NEXT: buffer_store_dword v17, off, s[0:3], s32 offset:104 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v18, off, s[0:3], s32 offset:108 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v19, off, s[0:3], s32 offset:112 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v20, off, s[0:3], s32 offset:116 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v20, v15 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v19, v14 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v18, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v17, v12 +; GFX9-G-O0-NEXT: buffer_store_dword v17, off, s[0:3], s32 offset:120 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v18, off, s[0:3], s32 offset:124 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v19, off, s[0:3], s32 offset:128 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v20, off, s[0:3], s32 offset:132 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 s[6:7], s[4:5] +; GFX9-G-O0-NEXT: v_writelane_b32 v16, s6, 2 +; GFX9-G-O0-NEXT: v_writelane_b32 v16, s7, 3 +; GFX9-G-O0-NEXT: s_mov_b64 s[6:7], s[4:5] +; GFX9-G-O0-NEXT: v_writelane_b32 v16, s6, 6 +; GFX9-G-O0-NEXT: v_writelane_b32 v16, s7, 7 +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[18:19], -1 +; GFX9-G-O0-NEXT: buffer_store_dword v16, off, s[0:3], s32 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[18:19] +; GFX9-G-O0-NEXT: buffer_store_dword v12, off, s[0:3], s32 offset:232 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v13, off, s[0:3], s32 offset:236 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v14, off, s[0:3], s32 offset:240 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v15, off, s[0:3], s32 offset:244 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:216 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:220 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:224 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v11, off, s[0:3], s32 offset:228 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:200 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:204 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v6, off, s[0:3], s32 offset:208 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:212 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:184 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:188 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:192 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:196 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX9-G-O0-NEXT: s_cbranch_execnz .LBB1_6 +; GFX9-G-O0-NEXT: s_branch .LBB1_1 +; GFX9-G-O0-NEXT: .LBB1_7: ; %udiv-preheader +; GFX9-G-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:264 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:268 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v2, off, s[0:3], s32 offset:272 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v3, off, s[0:3], s32 offset:276 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v8, off, s[0:3], s32 offset:280 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v9, off, s[0:3], s32 offset:284 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v10, off, s[0:3], s32 offset:288 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v11, off, s[0:3], s32 offset:292 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[18:19], -1 +; GFX9-G-O0-NEXT: buffer_load_dword v12, off, s[0:3], s32 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[18:19] +; GFX9-G-O0-NEXT: buffer_load_dword v17, off, s[0:3], s32 offset:36 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v18, off, s[0:3], s32 offset:40 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v19, off, s[0:3], s32 offset:44 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v20, off, s[0:3], s32 offset:48 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v13, off, s[0:3], s32 offset:296 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:56 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:60 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v6, off, s[0:3], s32 offset:64 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v7, off, s[0:3], s32 offset:68 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b32 s4, 64 +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: v_mov_b32_e32 v16, v5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v22, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v21, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, s4 +; GFX9-G-O0-NEXT: v_sub_u32_e64 v4, v13, v4 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, s4 +; GFX9-G-O0-NEXT: v_sub_u32_e64 v5, v5, v13 +; GFX9-G-O0-NEXT: s_mov_b32 s6, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, s4 +; GFX9-G-O0-NEXT: v_cmp_lt_u32_e64 s[4:5], v13, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, s6 +; GFX9-G-O0-NEXT: v_cmp_eq_u32_e64 s[6:7], v13, v6 +; GFX9-G-O0-NEXT: v_lshrrev_b64 v[6:7], v13, v[21:22] +; GFX9-G-O0-NEXT: v_lshrrev_b64 v[26:27], v13, v[15:16] +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[24:25], v5, v[21:22] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v26 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v27 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v23, v24 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v25 +; GFX9-G-O0-NEXT: v_or_b32_e64 v14, v14, v23 +; GFX9-G-O0-NEXT: v_or_b32_e64 v13, v5, v13 +; GFX9-G-O0-NEXT: s_mov_b64 s[8:9], 0 +; GFX9-G-O0-NEXT: v_lshrrev_b64 v[21:22], v4, v[21:22] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v21 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v22 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v4, v4, v14, s[4:5] +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v5, v5, v13, s[4:5] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v15 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v16 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v4, v4, v14, s[6:7] +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v13, v5, v13, s[6:7] +; GFX9-G-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 def $vgpr4_vgpr5 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v6 +; GFX9-G-O0-NEXT: ; kill: def $vgpr7 killed $vgpr7 killed $vgpr6_vgpr7 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v13, v13, v14, s[4:5] +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v6, v6, v7, s[4:5] +; GFX9-G-O0-NEXT: ; kill: def $vgpr13 killed $vgpr13 def $vgpr13_vgpr14 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v6 +; GFX9-G-O0-NEXT: ; kill: def $vgpr4_vgpr5 killed $vgpr4_vgpr5 def $vgpr4_vgpr5_vgpr6_vgpr7 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, v14 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v16, v17 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, v18 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v19 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v20 +; GFX9-G-O0-NEXT: s_mov_b32 s4, -1 +; GFX9-G-O0-NEXT: s_mov_b32 s10, -1 +; GFX9-G-O0-NEXT: s_mov_b32 s7, -1 +; GFX9-G-O0-NEXT: s_mov_b32 s6, -1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v17, s4 +; GFX9-G-O0-NEXT: v_add_co_u32_e64 v16, s[4:5], v16, v17 +; GFX9-G-O0-NEXT: buffer_store_dword v16, off, s[0:3], s32 offset:260 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v16, s10 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v15, s[4:5], v15, v16, s[4:5] +; GFX9-G-O0-NEXT: buffer_store_dword v15, off, s[0:3], s32 offset:256 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, s7 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v14, s[4:5], v14, v15, s[4:5] +; GFX9-G-O0-NEXT: buffer_store_dword v14, off, s[0:3], s32 offset:252 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, s6 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v13, s[4:5], v13, v14, s[4:5] +; GFX9-G-O0-NEXT: buffer_store_dword v13, off, s[0:3], s32 offset:248 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 s[4:5], s[8:9] +; GFX9-G-O0-NEXT: s_mov_b64 s[6:7], s[8:9] +; GFX9-G-O0-NEXT: v_writelane_b32 v12, s8, 6 +; GFX9-G-O0-NEXT: v_writelane_b32 v12, s9, 7 +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[18:19], -1 +; GFX9-G-O0-NEXT: buffer_store_dword v12, off, s[0:3], s32 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[18:19] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, s7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, s6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v12, s4 +; GFX9-G-O0-NEXT: buffer_store_dword v12, off, s[0:3], s32 offset:232 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v13, off, s[0:3], s32 offset:236 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v14, off, s[0:3], s32 offset:240 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v15, off, s[0:3], s32 offset:244 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v8, off, s[0:3], s32 offset:216 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v9, off, s[0:3], s32 offset:220 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v10, off, s[0:3], s32 offset:224 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v11, off, s[0:3], s32 offset:228 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:200 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:204 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v6, off, s[0:3], s32 offset:208 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v7, off, s[0:3], s32 offset:212 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v0, off, s[0:3], s32 offset:184 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:188 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:192 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:196 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_branch .LBB1_6 +; GFX9-G-O0-NEXT: .LBB1_8: ; %udiv-bb1 +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[18:19], -1 +; GFX9-G-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[18:19] +; GFX9-G-O0-NEXT: buffer_load_dword v9, off, s[0:3], s32 offset:56 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v10, off, s[0:3], s32 offset:60 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v11, off, s[0:3], s32 offset:64 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:68 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v2, off, s[0:3], s32 offset:32 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v1, off, s[0:3], s32 offset:20 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v3, off, s[0:3], s32 offset:24 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:28 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 s[4:5], 0 +; GFX9-G-O0-NEXT: s_mov_b32 s6, 1 +; GFX9-G-O0-NEXT: s_mov_b32 s10, 0 +; GFX9-G-O0-NEXT: s_mov_b32 s9, 0 +; GFX9-G-O0-NEXT: s_mov_b32 s8, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, s6 +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(3) +; GFX9-G-O0-NEXT: v_add_co_u32_e64 v5, s[6:7], v2, v5 +; GFX9-G-O0-NEXT: buffer_store_dword v5, off, s[0:3], s32 offset:296 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, s10 +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(1) +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v6, s[6:7], v4, v6, s[6:7] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, s9 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v8, s[6:7], v3, v4, s[6:7] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, s8 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v7, s[6:7], v1, v3, s[6:7] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, v8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v16, v7 +; GFX9-G-O0-NEXT: buffer_store_dword v13, off, s[0:3], s32 offset:280 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v14, off, s[0:3], s32 offset:284 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v15, off, s[0:3], s32 offset:288 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v16, off, s[0:3], s32 offset:292 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b32 s6, 0x7f +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s6 +; GFX9-G-O0-NEXT: v_sub_co_u32_e64 v4, s[6:7], v1, v2 +; GFX9-G-O0-NEXT: s_mov_b32 s7, 64 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v14, v10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v13, v9 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s7 +; GFX9-G-O0-NEXT: v_sub_u32_e64 v3, v4, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s7 +; GFX9-G-O0-NEXT: v_sub_u32_e64 v9, v1, v4 +; GFX9-G-O0-NEXT: s_mov_b32 s6, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s7 +; GFX9-G-O0-NEXT: v_cmp_lt_u32_e64 s[8:9], v4, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s6 +; GFX9-G-O0-NEXT: v_cmp_eq_u32_e64 s[6:7], v4, v1 +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[1:2], v4, v[13:14] +; GFX9-G-O0-NEXT: v_lshrrev_b64 v[18:19], v9, v[13:14] +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[16:17], v4, v[11:12] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v18 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v19 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v15, v16 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v17 +; GFX9-G-O0-NEXT: v_or_b32_e64 v10, v10, v15 +; GFX9-G-O0-NEXT: v_or_b32_e64 v4, v4, v9 +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[13:14], v3, v[13:14] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v2 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, 0 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v1, v1, v9, s[8:9] +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v3, v2, v3, s[8:9] +; GFX9-G-O0-NEXT: ; kill: def $vgpr1 killed $vgpr1 def $vgpr1_vgpr2 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v3 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v9, v13 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v14 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v9, v9, v10, s[8:9] +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v3, v3, v4, s[8:9] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v11 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v12 +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v9, v9, v10, s[6:7] +; GFX9-G-O0-NEXT: v_cndmask_b32_e64 v3, v3, v4, s[6:7] +; GFX9-G-O0-NEXT: ; kill: def $vgpr9 killed $vgpr9 def $vgpr9_vgpr10 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v10, v3 +; GFX9-G-O0-NEXT: ; kill: def $vgpr1_vgpr2 killed $vgpr1_vgpr2 def $vgpr1_vgpr2_vgpr3_vgpr4 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v9 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v10 +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:264 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:268 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:272 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:276 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 s[8:9], s[4:5] +; GFX9-G-O0-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX9-G-O0-NEXT: v_or_b32_e64 v5, v5, v8 +; GFX9-G-O0-NEXT: v_or_b32_e64 v7, v6, v7 +; GFX9-G-O0-NEXT: ; kill: def $vgpr5 killed $vgpr5 def $vgpr5_vgpr6 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v8, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v7, s4 +; GFX9-G-O0-NEXT: v_cmp_ne_u64_e64 s[4:5], v[5:6], v[7:8] +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:88 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:92 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:96 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:100 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s8 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, s9 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, s10 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, s11 +; GFX9-G-O0-NEXT: buffer_store_dword v1, off, s[0:3], s32 offset:72 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: buffer_store_dword v2, off, s[0:3], s32 offset:76 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v3, off, s[0:3], s32 offset:80 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: buffer_store_dword v4, off, s[0:3], s32 offset:84 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 s[6:7], exec +; GFX9-G-O0-NEXT: s_and_b64 s[4:5], s[6:7], s[4:5] +; GFX9-G-O0-NEXT: s_xor_b64 s[6:7], s[4:5], s[6:7] +; GFX9-G-O0-NEXT: v_writelane_b32 v0, s6, 4 +; GFX9-G-O0-NEXT: v_writelane_b32 v0, s7, 5 +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[18:19], -1 +; GFX9-G-O0-NEXT: buffer_store_dword v0, off, s[0:3], s32 ; 4-byte Folded Spill +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[18:19] +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[4:5] +; GFX9-G-O0-NEXT: s_cbranch_execz .LBB1_5 +; GFX9-G-O0-NEXT: s_branch .LBB1_7 +; GFX9-G-O0-NEXT: .LBB1_9: ; %udiv-end +; GFX9-G-O0-NEXT: s_or_saveexec_b64 s[18:19], -1 +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[18:19] +; GFX9-G-O0-NEXT: buffer_load_dword v5, off, s[0:3], s32 offset:136 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v6, off, s[0:3], s32 offset:140 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v7, off, s[0:3], s32 offset:144 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v8, off, s[0:3], s32 offset:148 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, v5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v7 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v8 +; GFX9-G-O0-NEXT: ; kill: killed $vgpr4 +; GFX9-G-O0-NEXT: s_xor_saveexec_b64 s[4:5], -1 +; GFX9-G-O0-NEXT: buffer_load_dword v0, off, s[0:3], s32 offset:300 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_nop 0 +; GFX9-G-O0-NEXT: buffer_load_dword v4, off, s[0:3], s32 offset:304 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v8, off, s[0:3], s32 offset:308 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v16, off, s[0:3], s32 offset:312 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: buffer_load_dword v12, off, s[0:3], s32 offset:316 ; 4-byte Folded Reload +; GFX9-G-O0-NEXT: s_mov_b64 exec, s[4:5] +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) +; GFX9-G-O0-NEXT: s_setpc_b64 s[30:31] %div = udiv i128 %lhs, %rhs ret i128 %div } @@ -2388,6 +4576,66 @@ define i128 @v_sdiv_i128_v_pow2k(i128 %lhs) { ; GFX9-O0-NEXT: v_lshrrev_b64 v[3:4], s4, v[3:4] ; GFX9-O0-NEXT: ; kill: def $vgpr3 killed $vgpr3 killed $vgpr3_vgpr4 killed $exec ; GFX9-O0-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-G-LABEL: v_sdiv_i128_v_pow2k: +; GFX9-G: ; %bb.0: +; GFX9-G-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-G-NEXT: v_ashrrev_i32_e32 v4, 31, v3 +; GFX9-G-NEXT: v_mov_b32_e32 v5, v4 +; GFX9-G-NEXT: v_lshrrev_b64 v[4:5], 31, v[4:5] +; GFX9-G-NEXT: v_add_co_u32_e32 v0, vcc, v0, v4 +; GFX9-G-NEXT: v_addc_co_u32_e32 v4, vcc, v1, v5, vcc +; GFX9-G-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v2, vcc +; GFX9-G-NEXT: v_addc_co_u32_e32 v2, vcc, 0, v3, vcc +; GFX9-G-NEXT: v_lshlrev_b64 v[0:1], 31, v[1:2] +; GFX9-G-NEXT: v_lshrrev_b32_e32 v3, 1, v4 +; GFX9-G-NEXT: v_or_b32_e32 v0, v3, v0 +; GFX9-G-NEXT: v_ashrrev_i32_e32 v3, 31, v2 +; GFX9-G-NEXT: v_ashrrev_i32_e32 v2, 1, v2 +; GFX9-G-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-G-O0-LABEL: v_sdiv_i128_v_pow2k: +; GFX9-G-O0: ; %bb.0: +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v0 +; GFX9-G-O0-NEXT: s_mov_b32 s4, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, s4 +; GFX9-G-O0-NEXT: v_ashrrev_i32_e64 v0, v0, v3 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v0 +; GFX9-G-O0-NEXT: s_mov_b32 s4, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, s4 +; GFX9-G-O0-NEXT: v_lshrrev_b64 v[6:7], v0, v[5:6] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v6 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, v7 +; GFX9-G-O0-NEXT: s_mov_b32 s8, 0 +; GFX9-G-O0-NEXT: s_mov_b32 s5, 0 +; GFX9-G-O0-NEXT: v_add_co_u32_e64 v4, s[6:7], v4, v5 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v1, s[6:7], v1, v0, s[6:7] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, s8 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v5, s[6:7], v2, v0, s[6:7] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, s5 +; GFX9-G-O0-NEXT: v_addc_co_u32_e64 v4, s[6:7], v3, v0, s[6:7] +; GFX9-G-O0-NEXT: ; kill: def $vgpr5 killed $vgpr5 def $vgpr5_vgpr6 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v6, v4 +; GFX9-G-O0-NEXT: s_mov_b32 s5, 1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, s5 +; GFX9-G-O0-NEXT: v_lshrrev_b32_e64 v0, v0, v1 +; GFX9-G-O0-NEXT: s_mov_b32 s5, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[5:6], v2, v[5:6] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, v5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v6 +; GFX9-G-O0-NEXT: v_or_b32_e64 v0, v0, v3 +; GFX9-G-O0-NEXT: v_or_b32_e64 v1, v1, v2 +; GFX9-G-O0-NEXT: s_mov_b32 s4, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-G-O0-NEXT: v_ashrrev_i32_e64 v3, v2, v4 +; GFX9-G-O0-NEXT: s_mov_b32 s4, 1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-G-O0-NEXT: v_ashrrev_i32_e64 v2, v2, v4 +; GFX9-G-O0-NEXT: s_setpc_b64 s[30:31] %div = sdiv i128 %lhs, 8589934592 ret i128 %div } @@ -2434,10 +4682,42 @@ define i128 @v_udiv_i128_v_pow2k(i128 %lhs) { ; GFX9-O0-NEXT: ; kill: def $vgpr2 killed $vgpr2 killed $vgpr2_vgpr3 killed $exec ; GFX9-O0-NEXT: v_mov_b32_e32 v3, 0 ; GFX9-O0-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-G-LABEL: v_udiv_i128_v_pow2k: +; GFX9-G: ; %bb.0: +; GFX9-G-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-G-NEXT: v_mov_b32_e32 v4, v1 +; GFX9-G-NEXT: v_lshlrev_b64 v[0:1], 31, v[2:3] +; GFX9-G-NEXT: v_lshrrev_b32_e32 v2, 1, v4 +; GFX9-G-NEXT: v_or_b32_e32 v0, v2, v0 +; GFX9-G-NEXT: v_lshrrev_b32_e32 v2, 1, v3 +; GFX9-G-NEXT: v_mov_b32_e32 v3, 0 +; GFX9-G-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-G-O0-LABEL: v_udiv_i128_v_pow2k: +; GFX9-G-O0: ; %bb.0: +; GFX9-G-O0-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v2 +; GFX9-G-O0-NEXT: ; kill: def $vgpr4 killed $vgpr4 def $vgpr4_vgpr5 killed $exec +; GFX9-G-O0-NEXT: v_mov_b32_e32 v5, v3 +; GFX9-G-O0-NEXT: s_mov_b32 s4, 1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v0, s4 +; GFX9-G-O0-NEXT: v_lshrrev_b32_e64 v0, v0, v1 +; GFX9-G-O0-NEXT: s_mov_b32 s4, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v1, s4 +; GFX9-G-O0-NEXT: s_mov_b32 s4, 31 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-G-O0-NEXT: v_lshlrev_b64 v[5:6], v2, v[4:5] +; GFX9-G-O0-NEXT: v_mov_b32_e32 v4, v5 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, v6 +; GFX9-G-O0-NEXT: v_or_b32_e64 v0, v0, v4 +; GFX9-G-O0-NEXT: v_or_b32_e64 v1, v1, v2 +; GFX9-G-O0-NEXT: s_mov_b32 s4, 1 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-G-O0-NEXT: v_lshrrev_b32_e64 v2, v2, v3 +; GFX9-G-O0-NEXT: s_mov_b32 s4, 0 +; GFX9-G-O0-NEXT: v_mov_b32_e32 v3, s4 +; GFX9-G-O0-NEXT: s_setpc_b64 s[30:31] %div = udiv i128 %lhs, 8589934592 ret i128 %div } - -;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: -; GFX9-SDAG: {{.*}} -; GFX9-SDAG-O0: {{.*}} diff --git a/llvm/test/CodeGen/AMDGPU/div_v2i128.ll b/llvm/test/CodeGen/AMDGPU/div_v2i128.ll index 46e2632e45a1907075f3e42915c2ddaff982ff01..16a03badcb1329adedbccdab9c9561a4054bb8d2 100644 --- a/llvm/test/CodeGen/AMDGPU/div_v2i128.ll +++ b/llvm/test/CodeGen/AMDGPU/div_v2i128.ll @@ -1,25 +1,3248 @@ -; RUN: not --crash llc -global-isel=0 -mtriple=amdgcn-amd-amdhsa -verify-machineinstrs -o - %s 2>&1 | FileCheck -check-prefix=SDAG-ERR %s -; RUN: not --crash llc -global-isel=1 -mtriple=amdgcn-amd-amdhsa -verify-machineinstrs -o - %s 2>&1 | FileCheck -check-prefix=GISEL-ERR %s - -; SDAG-ERR: LLVM ERROR: unsupported libcall legalization -; GISEL-ERR: LLVM ERROR: unable to legalize instruction: %{{[0-9]+}}:_(s128) = G_SDIV %{{[0-9]+}}:_, %{{[0-9]+}}:_ (in function: v_sdiv_v2i128_vv) +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -global-isel=0 -mtriple=amdgcn-amd-amdhsa -verify-machineinstrs -o - %s | FileCheck -check-prefix=SDAG %s +; RUN: llc -global-isel=1 -mtriple=amdgcn-amd-amdhsa -verify-machineinstrs -o - %s | FileCheck -check-prefix=GISEL %s define <2 x i128> @v_sdiv_v2i128_vv(<2 x i128> %lhs, <2 x i128> %rhs) { +; SDAG-LABEL: v_sdiv_v2i128_vv: +; SDAG: ; %bb.0: ; %_udiv-special-cases_udiv-special-cases +; SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-NEXT: v_ashrrev_i32_e32 v24, 31, v3 +; SDAG-NEXT: v_ashrrev_i32_e32 v25, 31, v11 +; SDAG-NEXT: v_mov_b32_e32 v16, 0 +; SDAG-NEXT: s_mov_b64 s[10:11], 0x7f +; SDAG-NEXT: v_mov_b32_e32 v26, v24 +; SDAG-NEXT: v_mov_b32_e32 v27, v25 +; SDAG-NEXT: v_xor_b32_e32 v17, v24, v3 +; SDAG-NEXT: v_xor_b32_e32 v18, v24, v2 +; SDAG-NEXT: v_xor_b32_e32 v1, v24, v1 +; SDAG-NEXT: v_xor_b32_e32 v0, v24, v0 +; SDAG-NEXT: v_xor_b32_e32 v19, v25, v11 +; SDAG-NEXT: v_xor_b32_e32 v20, v25, v10 +; SDAG-NEXT: v_xor_b32_e32 v9, v25, v9 +; SDAG-NEXT: v_xor_b32_e32 v8, v25, v8 +; SDAG-NEXT: v_sub_i32_e32 v2, vcc, v0, v24 +; SDAG-NEXT: v_subb_u32_e32 v3, vcc, v1, v24, vcc +; SDAG-NEXT: v_ffbh_u32_e32 v0, v2 +; SDAG-NEXT: v_subb_u32_e32 v10, vcc, v18, v24, vcc +; SDAG-NEXT: v_add_i32_e64 v1, s[4:5], 32, v0 +; SDAG-NEXT: v_ffbh_u32_e32 v18, v3 +; SDAG-NEXT: v_subb_u32_e32 v11, vcc, v17, v24, vcc +; SDAG-NEXT: v_or_b32_e32 v0, v2, v10 +; SDAG-NEXT: v_ffbh_u32_e32 v17, v10 +; SDAG-NEXT: v_min_u32_e32 v18, v1, v18 +; SDAG-NEXT: v_sub_i32_e32 v28, vcc, v8, v25 +; SDAG-NEXT: v_or_b32_e32 v1, v3, v11 +; SDAG-NEXT: v_add_i32_e64 v8, s[4:5], 32, v17 +; SDAG-NEXT: v_ffbh_u32_e32 v17, v11 +; SDAG-NEXT: v_add_i32_e64 v18, s[4:5], 64, v18 +; SDAG-NEXT: v_addc_u32_e64 v21, s[4:5], 0, 0, s[4:5] +; SDAG-NEXT: v_subb_u32_e32 v29, vcc, v9, v25, vcc +; SDAG-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[0:1] +; SDAG-NEXT: v_ffbh_u32_e32 v1, v28 +; SDAG-NEXT: v_min_u32_e32 v8, v8, v17 +; SDAG-NEXT: v_cmp_ne_u64_e64 s[6:7], 0, v[10:11] +; SDAG-NEXT: v_cndmask_b32_e64 v17, v21, 0, s[6:7] +; SDAG-NEXT: v_subb_u32_e32 v0, vcc, v20, v25, vcc +; SDAG-NEXT: v_add_i32_e64 v9, s[8:9], 32, v1 +; SDAG-NEXT: v_ffbh_u32_e32 v20, v29 +; SDAG-NEXT: v_cndmask_b32_e64 v18, v18, v8, s[6:7] +; SDAG-NEXT: v_subb_u32_e32 v1, vcc, v19, v25, vcc +; SDAG-NEXT: v_or_b32_e32 v8, v28, v0 +; SDAG-NEXT: v_ffbh_u32_e32 v19, v0 +; SDAG-NEXT: v_min_u32_e32 v20, v9, v20 +; SDAG-NEXT: v_or_b32_e32 v9, v29, v1 +; SDAG-NEXT: v_add_i32_e32 v19, vcc, 32, v19 +; SDAG-NEXT: v_ffbh_u32_e32 v21, v1 +; SDAG-NEXT: v_add_i32_e32 v20, vcc, 64, v20 +; SDAG-NEXT: v_addc_u32_e64 v22, s[6:7], 0, 0, vcc +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[8:9] +; SDAG-NEXT: v_min_u32_e32 v8, v19, v21 +; SDAG-NEXT: v_cmp_ne_u64_e64 s[6:7], 0, v[0:1] +; SDAG-NEXT: v_cndmask_b32_e64 v9, v22, 0, s[6:7] +; SDAG-NEXT: s_or_b64 s[8:9], vcc, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v8, v20, v8, s[6:7] +; SDAG-NEXT: v_sub_i32_e32 v8, vcc, v8, v18 +; SDAG-NEXT: v_subb_u32_e32 v9, vcc, v9, v17, vcc +; SDAG-NEXT: v_xor_b32_e32 v17, 0x7f, v8 +; SDAG-NEXT: v_subbrev_u32_e32 v18, vcc, 0, v16, vcc +; SDAG-NEXT: v_cmp_lt_u64_e64 s[4:5], s[10:11], v[8:9] +; SDAG-NEXT: v_cndmask_b32_e64 v20, 0, 1, s[4:5] +; SDAG-NEXT: v_subbrev_u32_e32 v19, vcc, 0, v16, vcc +; SDAG-NEXT: v_or_b32_e32 v16, v17, v18 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[18:19] +; SDAG-NEXT: v_cndmask_b32_e64 v21, 0, 1, vcc +; SDAG-NEXT: v_or_b32_e32 v17, v9, v19 +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[18:19] +; SDAG-NEXT: v_cndmask_b32_e32 v20, v21, v20, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[16:17] +; SDAG-NEXT: v_and_b32_e32 v16, 1, v20 +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 1, v16 +; SDAG-NEXT: s_or_b64 s[4:5], s[8:9], s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v20, v11, 0, s[4:5] +; SDAG-NEXT: s_xor_b64 s[6:7], s[4:5], -1 +; SDAG-NEXT: v_cndmask_b32_e64 v17, v10, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v21, v3, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v16, v2, 0, s[4:5] +; SDAG-NEXT: s_and_b64 s[4:5], s[6:7], vcc +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB0_6 +; SDAG-NEXT: ; %bb.1: ; %udiv-bb15 +; SDAG-NEXT: v_add_i32_e32 v30, vcc, 1, v8 +; SDAG-NEXT: v_sub_i32_e64 v20, s[4:5], 63, v8 +; SDAG-NEXT: v_mov_b32_e32 v16, 0 +; SDAG-NEXT: v_mov_b32_e32 v17, 0 +; SDAG-NEXT: v_addc_u32_e32 v31, vcc, 0, v9, vcc +; SDAG-NEXT: v_lshl_b64 v[20:21], v[2:3], v20 +; SDAG-NEXT: v_addc_u32_e32 v32, vcc, 0, v18, vcc +; SDAG-NEXT: v_addc_u32_e32 v33, vcc, 0, v19, vcc +; SDAG-NEXT: v_or_b32_e32 v18, v30, v32 +; SDAG-NEXT: v_sub_i32_e32 v34, vcc, 0x7f, v8 +; SDAG-NEXT: v_or_b32_e32 v19, v31, v33 +; SDAG-NEXT: v_lshl_b64 v[8:9], v[10:11], v34 +; SDAG-NEXT: v_sub_i32_e32 v35, vcc, 64, v34 +; SDAG-NEXT: v_lshl_b64 v[22:23], v[2:3], v34 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[18:19] +; SDAG-NEXT: v_lshr_b64 v[18:19], v[2:3], v35 +; SDAG-NEXT: v_or_b32_e32 v9, v9, v19 +; SDAG-NEXT: v_or_b32_e32 v8, v8, v18 +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v34 +; SDAG-NEXT: v_cndmask_b32_e64 v9, v21, v9, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v8, v20, v8, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v21, 0, v23, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v20, 0, v22, s[4:5] +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v34 +; SDAG-NEXT: v_cndmask_b32_e64 v9, v9, v11, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v8, v8, v10, s[4:5] +; SDAG-NEXT: v_mov_b32_e32 v18, 0 +; SDAG-NEXT: v_mov_b32_e32 v19, 0 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[8:9], exec, s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB0_5 +; SDAG-NEXT: ; %bb.2: ; %udiv-preheader4 +; SDAG-NEXT: v_lshr_b64 v[16:17], v[2:3], v30 +; SDAG-NEXT: v_sub_i32_e32 v35, vcc, 64, v30 +; SDAG-NEXT: v_subrev_i32_e32 v36, vcc, 64, v30 +; SDAG-NEXT: v_lshr_b64 v[37:38], v[10:11], v30 +; SDAG-NEXT: v_add_i32_e32 v34, vcc, -1, v28 +; SDAG-NEXT: s_mov_b64 s[10:11], 0 +; SDAG-NEXT: v_mov_b32_e32 v22, 0 +; SDAG-NEXT: v_mov_b32_e32 v23, 0 +; SDAG-NEXT: v_mov_b32_e32 v18, 0 +; SDAG-NEXT: v_mov_b32_e32 v19, 0 +; SDAG-NEXT: v_lshl_b64 v[48:49], v[10:11], v35 +; SDAG-NEXT: v_lshr_b64 v[10:11], v[10:11], v36 +; SDAG-NEXT: v_addc_u32_e32 v35, vcc, -1, v29, vcc +; SDAG-NEXT: v_or_b32_e32 v17, v17, v49 +; SDAG-NEXT: v_or_b32_e32 v16, v16, v48 +; SDAG-NEXT: v_addc_u32_e32 v36, vcc, -1, v0, vcc +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v30 +; SDAG-NEXT: v_cndmask_b32_e64 v17, v11, v17, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v16, v10, v16, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v11, 0, v38, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v10, 0, v37, s[4:5] +; SDAG-NEXT: v_addc_u32_e32 v37, vcc, -1, v1, vcc +; SDAG-NEXT: v_cmp_eq_u32_e32 vcc, 0, v30 +; SDAG-NEXT: v_cndmask_b32_e32 v3, v17, v3, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v2, v16, v2, vcc +; SDAG-NEXT: v_mov_b32_e32 v17, 0 +; SDAG-NEXT: .LBB0_3: ; %udiv-do-while3 +; SDAG-NEXT: ; =>This Inner Loop Header: Depth=1 +; SDAG-NEXT: v_lshl_b64 v[10:11], v[10:11], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v16, 31, v3 +; SDAG-NEXT: v_lshl_b64 v[2:3], v[2:3], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v38, 31, v9 +; SDAG-NEXT: v_lshl_b64 v[8:9], v[8:9], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v39, 31, v21 +; SDAG-NEXT: v_lshl_b64 v[20:21], v[20:21], 1 +; SDAG-NEXT: v_or_b32_e32 v10, v10, v16 +; SDAG-NEXT: v_or_b32_e32 v2, v2, v38 +; SDAG-NEXT: v_or_b32_e32 v8, v8, v39 +; SDAG-NEXT: v_or_b32_e32 v9, v19, v9 +; SDAG-NEXT: v_sub_i32_e32 v16, vcc, v34, v2 +; SDAG-NEXT: v_or_b32_e32 v8, v18, v8 +; SDAG-NEXT: v_subb_u32_e32 v16, vcc, v35, v3, vcc +; SDAG-NEXT: v_subb_u32_e32 v16, vcc, v36, v10, vcc +; SDAG-NEXT: v_subb_u32_e32 v16, vcc, v37, v11, vcc +; SDAG-NEXT: v_ashrrev_i32_e32 v38, 31, v16 +; SDAG-NEXT: v_and_b32_e32 v39, v38, v28 +; SDAG-NEXT: v_and_b32_e32 v48, v38, v29 +; SDAG-NEXT: v_and_b32_e32 v49, v38, v0 +; SDAG-NEXT: v_and_b32_e32 v16, 1, v38 +; SDAG-NEXT: v_and_b32_e32 v38, v38, v1 +; SDAG-NEXT: v_sub_i32_e32 v2, vcc, v2, v39 +; SDAG-NEXT: v_subb_u32_e32 v3, vcc, v3, v48, vcc +; SDAG-NEXT: v_subb_u32_e32 v10, vcc, v10, v49, vcc +; SDAG-NEXT: v_subb_u32_e32 v11, vcc, v11, v38, vcc +; SDAG-NEXT: v_add_i32_e32 v30, vcc, -1, v30 +; SDAG-NEXT: v_addc_u32_e32 v31, vcc, -1, v31, vcc +; SDAG-NEXT: v_addc_u32_e32 v32, vcc, -1, v32, vcc +; SDAG-NEXT: v_addc_u32_e32 v33, vcc, -1, v33, vcc +; SDAG-NEXT: v_or_b32_e32 v38, v30, v32 +; SDAG-NEXT: v_or_b32_e32 v39, v31, v33 +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[38:39] +; SDAG-NEXT: v_or_b32_e32 v21, v23, v21 +; SDAG-NEXT: s_or_b64 s[10:11], vcc, s[10:11] +; SDAG-NEXT: v_or_b32_e32 v20, v22, v20 +; SDAG-NEXT: v_mov_b32_e32 v23, v17 +; SDAG-NEXT: v_mov_b32_e32 v22, v16 +; SDAG-NEXT: s_andn2_b64 exec, exec, s[10:11] +; SDAG-NEXT: s_cbranch_execnz .LBB0_3 +; SDAG-NEXT: ; %bb.4: ; %Flow13 +; SDAG-NEXT: s_or_b64 exec, exec, s[10:11] +; SDAG-NEXT: .LBB0_5: ; %Flow14 +; SDAG-NEXT: s_or_b64 exec, exec, s[8:9] +; SDAG-NEXT: v_lshl_b64 v[0:1], v[8:9], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v8, 31, v21 +; SDAG-NEXT: v_lshl_b64 v[2:3], v[20:21], 1 +; SDAG-NEXT: v_or_b32_e32 v0, v0, v8 +; SDAG-NEXT: v_or_b32_e32 v20, v19, v1 +; SDAG-NEXT: v_or_b32_e32 v21, v17, v3 +; SDAG-NEXT: v_or_b32_e32 v17, v18, v0 +; SDAG-NEXT: v_or_b32_e32 v16, v16, v2 +; SDAG-NEXT: .LBB0_6: ; %Flow16 +; SDAG-NEXT: s_or_b64 exec, exec, s[6:7] +; SDAG-NEXT: v_ashrrev_i32_e32 v18, 31, v7 +; SDAG-NEXT: v_ashrrev_i32_e32 v19, 31, v15 +; SDAG-NEXT: v_mov_b32_e32 v9, 0 +; SDAG-NEXT: s_mov_b64 s[10:11], 0x7f +; SDAG-NEXT: v_mov_b32_e32 v22, v18 +; SDAG-NEXT: v_mov_b32_e32 v23, v19 +; SDAG-NEXT: v_xor_b32_e32 v0, v18, v7 +; SDAG-NEXT: v_xor_b32_e32 v1, v18, v6 +; SDAG-NEXT: v_xor_b32_e32 v3, v18, v5 +; SDAG-NEXT: v_xor_b32_e32 v2, v18, v4 +; SDAG-NEXT: v_xor_b32_e32 v6, v19, v15 +; SDAG-NEXT: v_xor_b32_e32 v7, v19, v14 +; SDAG-NEXT: v_xor_b32_e32 v8, v19, v13 +; SDAG-NEXT: v_xor_b32_e32 v10, v19, v12 +; SDAG-NEXT: v_sub_i32_e32 v2, vcc, v2, v18 +; SDAG-NEXT: v_subb_u32_e32 v3, vcc, v3, v18, vcc +; SDAG-NEXT: v_ffbh_u32_e32 v5, v2 +; SDAG-NEXT: v_subb_u32_e32 v4, vcc, v1, v18, vcc +; SDAG-NEXT: v_add_i32_e64 v1, s[4:5], 32, v5 +; SDAG-NEXT: v_ffbh_u32_e32 v11, v3 +; SDAG-NEXT: v_subb_u32_e32 v5, vcc, v0, v18, vcc +; SDAG-NEXT: v_or_b32_e32 v0, v2, v4 +; SDAG-NEXT: v_ffbh_u32_e32 v12, v4 +; SDAG-NEXT: v_min_u32_e32 v11, v1, v11 +; SDAG-NEXT: v_sub_i32_e32 v28, vcc, v10, v19 +; SDAG-NEXT: v_or_b32_e32 v1, v3, v5 +; SDAG-NEXT: v_add_i32_e64 v10, s[4:5], 32, v12 +; SDAG-NEXT: v_ffbh_u32_e32 v12, v5 +; SDAG-NEXT: v_add_i32_e64 v11, s[4:5], 64, v11 +; SDAG-NEXT: v_addc_u32_e64 v13, s[4:5], 0, 0, s[4:5] +; SDAG-NEXT: v_subb_u32_e32 v29, vcc, v8, v19, vcc +; SDAG-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[0:1] +; SDAG-NEXT: v_ffbh_u32_e32 v1, v28 +; SDAG-NEXT: v_min_u32_e32 v8, v10, v12 +; SDAG-NEXT: v_cmp_ne_u64_e64 s[6:7], 0, v[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v10, v13, 0, s[6:7] +; SDAG-NEXT: v_subb_u32_e32 v0, vcc, v7, v19, vcc +; SDAG-NEXT: v_add_i32_e64 v7, s[8:9], 32, v1 +; SDAG-NEXT: v_ffbh_u32_e32 v12, v29 +; SDAG-NEXT: v_cndmask_b32_e64 v8, v11, v8, s[6:7] +; SDAG-NEXT: v_subb_u32_e32 v1, vcc, v6, v19, vcc +; SDAG-NEXT: v_or_b32_e32 v6, v28, v0 +; SDAG-NEXT: v_ffbh_u32_e32 v11, v0 +; SDAG-NEXT: v_min_u32_e32 v12, v7, v12 +; SDAG-NEXT: v_or_b32_e32 v7, v29, v1 +; SDAG-NEXT: v_add_i32_e32 v11, vcc, 32, v11 +; SDAG-NEXT: v_ffbh_u32_e32 v13, v1 +; SDAG-NEXT: v_add_i32_e32 v12, vcc, 64, v12 +; SDAG-NEXT: v_addc_u32_e64 v14, s[6:7], 0, 0, vcc +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[6:7] +; SDAG-NEXT: v_min_u32_e32 v6, v11, v13 +; SDAG-NEXT: v_cmp_ne_u64_e64 s[6:7], 0, v[0:1] +; SDAG-NEXT: v_cndmask_b32_e64 v7, v14, 0, s[6:7] +; SDAG-NEXT: s_or_b64 s[8:9], vcc, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v6, v12, v6, s[6:7] +; SDAG-NEXT: v_sub_i32_e32 v6, vcc, v6, v8 +; SDAG-NEXT: v_subb_u32_e32 v7, vcc, v7, v10, vcc +; SDAG-NEXT: v_xor_b32_e32 v10, 0x7f, v6 +; SDAG-NEXT: v_subbrev_u32_e32 v8, vcc, 0, v9, vcc +; SDAG-NEXT: v_cmp_lt_u64_e64 s[4:5], s[10:11], v[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v12, 0, 1, s[4:5] +; SDAG-NEXT: v_subbrev_u32_e32 v9, vcc, 0, v9, vcc +; SDAG-NEXT: v_or_b32_e32 v10, v10, v8 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[8:9] +; SDAG-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc +; SDAG-NEXT: v_or_b32_e32 v11, v7, v9 +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[8:9] +; SDAG-NEXT: v_cndmask_b32_e32 v12, v13, v12, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[10:11] +; SDAG-NEXT: v_and_b32_e32 v10, 1, v12 +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 1, v10 +; SDAG-NEXT: s_or_b64 s[4:5], s[8:9], s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v13, v5, 0, s[4:5] +; SDAG-NEXT: s_xor_b64 s[6:7], s[4:5], -1 +; SDAG-NEXT: v_cndmask_b32_e64 v11, v4, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v14, v3, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v10, v2, 0, s[4:5] +; SDAG-NEXT: s_and_b64 s[4:5], s[6:7], vcc +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB0_12 +; SDAG-NEXT: ; %bb.7: ; %udiv-bb1 +; SDAG-NEXT: v_add_i32_e32 v30, vcc, 1, v6 +; SDAG-NEXT: v_sub_i32_e64 v12, s[4:5], 63, v6 +; SDAG-NEXT: v_mov_b32_e32 v10, 0 +; SDAG-NEXT: v_mov_b32_e32 v11, 0 +; SDAG-NEXT: v_addc_u32_e32 v31, vcc, 0, v7, vcc +; SDAG-NEXT: v_lshl_b64 v[12:13], v[2:3], v12 +; SDAG-NEXT: v_addc_u32_e32 v32, vcc, 0, v8, vcc +; SDAG-NEXT: v_addc_u32_e32 v33, vcc, 0, v9, vcc +; SDAG-NEXT: v_or_b32_e32 v7, v30, v32 +; SDAG-NEXT: v_sub_i32_e32 v9, vcc, 0x7f, v6 +; SDAG-NEXT: v_or_b32_e32 v8, v31, v33 +; SDAG-NEXT: v_lshl_b64 v[14:15], v[4:5], v9 +; SDAG-NEXT: v_sub_i32_e32 v6, vcc, 64, v9 +; SDAG-NEXT: v_lshl_b64 v[34:35], v[2:3], v9 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[7:8] +; SDAG-NEXT: v_lshr_b64 v[6:7], v[2:3], v6 +; SDAG-NEXT: v_or_b32_e32 v7, v15, v7 +; SDAG-NEXT: v_or_b32_e32 v6, v14, v6 +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v9 +; SDAG-NEXT: v_cndmask_b32_e64 v8, v13, v7, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v12, v12, v6, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v7, 0, v35, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v6, 0, v34, s[4:5] +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v9 +; SDAG-NEXT: v_cndmask_b32_e64 v9, v8, v5, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v8, v12, v4, s[4:5] +; SDAG-NEXT: v_mov_b32_e32 v12, 0 +; SDAG-NEXT: v_mov_b32_e32 v13, 0 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[8:9], exec, s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB0_11 +; SDAG-NEXT: ; %bb.8: ; %udiv-preheader +; SDAG-NEXT: v_lshr_b64 v[10:11], v[2:3], v30 +; SDAG-NEXT: v_sub_i32_e32 v35, vcc, 64, v30 +; SDAG-NEXT: v_subrev_i32_e32 v36, vcc, 64, v30 +; SDAG-NEXT: v_lshr_b64 v[37:38], v[4:5], v30 +; SDAG-NEXT: v_add_i32_e32 v34, vcc, -1, v28 +; SDAG-NEXT: s_mov_b64 s[10:11], 0 +; SDAG-NEXT: v_mov_b32_e32 v14, 0 +; SDAG-NEXT: v_mov_b32_e32 v15, 0 +; SDAG-NEXT: v_mov_b32_e32 v12, 0 +; SDAG-NEXT: v_mov_b32_e32 v13, 0 +; SDAG-NEXT: v_lshl_b64 v[48:49], v[4:5], v35 +; SDAG-NEXT: v_lshr_b64 v[4:5], v[4:5], v36 +; SDAG-NEXT: v_addc_u32_e32 v35, vcc, -1, v29, vcc +; SDAG-NEXT: v_or_b32_e32 v11, v11, v49 +; SDAG-NEXT: v_or_b32_e32 v10, v10, v48 +; SDAG-NEXT: v_addc_u32_e32 v36, vcc, -1, v0, vcc +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v30 +; SDAG-NEXT: v_cndmask_b32_e64 v11, v5, v11, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v10, v4, v10, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v5, 0, v38, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v4, 0, v37, s[4:5] +; SDAG-NEXT: v_addc_u32_e32 v37, vcc, -1, v1, vcc +; SDAG-NEXT: v_cmp_eq_u32_e32 vcc, 0, v30 +; SDAG-NEXT: v_cndmask_b32_e32 v3, v11, v3, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v2, v10, v2, vcc +; SDAG-NEXT: v_mov_b32_e32 v11, 0 +; SDAG-NEXT: .LBB0_9: ; %udiv-do-while +; SDAG-NEXT: ; =>This Inner Loop Header: Depth=1 +; SDAG-NEXT: v_lshl_b64 v[4:5], v[4:5], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v10, 31, v3 +; SDAG-NEXT: v_lshl_b64 v[2:3], v[2:3], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v38, 31, v9 +; SDAG-NEXT: v_lshl_b64 v[8:9], v[8:9], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v39, 31, v7 +; SDAG-NEXT: v_lshl_b64 v[6:7], v[6:7], 1 +; SDAG-NEXT: v_or_b32_e32 v4, v4, v10 +; SDAG-NEXT: v_or_b32_e32 v2, v2, v38 +; SDAG-NEXT: v_or_b32_e32 v8, v8, v39 +; SDAG-NEXT: v_or_b32_e32 v9, v13, v9 +; SDAG-NEXT: v_or_b32_e32 v7, v15, v7 +; SDAG-NEXT: v_or_b32_e32 v8, v12, v8 +; SDAG-NEXT: v_sub_i32_e32 v10, vcc, v34, v2 +; SDAG-NEXT: v_subb_u32_e32 v10, vcc, v35, v3, vcc +; SDAG-NEXT: v_subb_u32_e32 v10, vcc, v36, v4, vcc +; SDAG-NEXT: v_subb_u32_e32 v10, vcc, v37, v5, vcc +; SDAG-NEXT: v_ashrrev_i32_e32 v15, 31, v10 +; SDAG-NEXT: v_and_b32_e32 v10, 1, v15 +; SDAG-NEXT: v_and_b32_e32 v38, v15, v1 +; SDAG-NEXT: v_and_b32_e32 v39, v15, v0 +; SDAG-NEXT: v_and_b32_e32 v48, v15, v29 +; SDAG-NEXT: v_and_b32_e32 v15, v15, v28 +; SDAG-NEXT: v_sub_i32_e32 v2, vcc, v2, v15 +; SDAG-NEXT: v_subb_u32_e32 v3, vcc, v3, v48, vcc +; SDAG-NEXT: v_subb_u32_e32 v4, vcc, v4, v39, vcc +; SDAG-NEXT: v_subb_u32_e32 v5, vcc, v5, v38, vcc +; SDAG-NEXT: v_add_i32_e32 v30, vcc, -1, v30 +; SDAG-NEXT: v_addc_u32_e32 v31, vcc, -1, v31, vcc +; SDAG-NEXT: v_addc_u32_e32 v32, vcc, -1, v32, vcc +; SDAG-NEXT: v_addc_u32_e32 v33, vcc, -1, v33, vcc +; SDAG-NEXT: v_or_b32_e32 v39, v31, v33 +; SDAG-NEXT: v_or_b32_e32 v38, v30, v32 +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[38:39] +; SDAG-NEXT: s_or_b64 s[10:11], vcc, s[10:11] +; SDAG-NEXT: v_or_b32_e32 v6, v14, v6 +; SDAG-NEXT: v_mov_b32_e32 v15, v11 +; SDAG-NEXT: v_mov_b32_e32 v14, v10 +; SDAG-NEXT: s_andn2_b64 exec, exec, s[10:11] +; SDAG-NEXT: s_cbranch_execnz .LBB0_9 +; SDAG-NEXT: ; %bb.10: ; %Flow +; SDAG-NEXT: s_or_b64 exec, exec, s[10:11] +; SDAG-NEXT: .LBB0_11: ; %Flow11 +; SDAG-NEXT: s_or_b64 exec, exec, s[8:9] +; SDAG-NEXT: v_lshl_b64 v[0:1], v[8:9], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v4, 31, v7 +; SDAG-NEXT: v_lshl_b64 v[2:3], v[6:7], 1 +; SDAG-NEXT: v_or_b32_e32 v0, v0, v4 +; SDAG-NEXT: v_or_b32_e32 v13, v13, v1 +; SDAG-NEXT: v_or_b32_e32 v14, v11, v3 +; SDAG-NEXT: v_or_b32_e32 v11, v12, v0 +; SDAG-NEXT: v_or_b32_e32 v10, v10, v2 +; SDAG-NEXT: .LBB0_12: ; %Flow12 +; SDAG-NEXT: s_or_b64 exec, exec, s[6:7] +; SDAG-NEXT: v_xor_b32_e32 v3, v27, v26 +; SDAG-NEXT: v_xor_b32_e32 v2, v25, v24 +; SDAG-NEXT: v_xor_b32_e32 v7, v23, v22 +; SDAG-NEXT: v_xor_b32_e32 v6, v19, v18 +; SDAG-NEXT: v_xor_b32_e32 v4, v20, v3 +; SDAG-NEXT: v_xor_b32_e32 v5, v17, v2 +; SDAG-NEXT: v_xor_b32_e32 v1, v21, v3 +; SDAG-NEXT: v_xor_b32_e32 v0, v16, v2 +; SDAG-NEXT: v_xor_b32_e32 v8, v13, v7 +; SDAG-NEXT: v_xor_b32_e32 v9, v11, v6 +; SDAG-NEXT: v_xor_b32_e32 v11, v14, v7 +; SDAG-NEXT: v_sub_i32_e32 v0, vcc, v0, v2 +; SDAG-NEXT: v_subb_u32_e32 v1, vcc, v1, v3, vcc +; SDAG-NEXT: v_subb_u32_e32 v2, vcc, v5, v2, vcc +; SDAG-NEXT: v_subb_u32_e32 v3, vcc, v4, v3, vcc +; SDAG-NEXT: v_xor_b32_e32 v4, v10, v6 +; SDAG-NEXT: v_sub_i32_e32 v4, vcc, v4, v6 +; SDAG-NEXT: v_subb_u32_e32 v5, vcc, v11, v7, vcc +; SDAG-NEXT: v_subb_u32_e32 v6, vcc, v9, v6, vcc +; SDAG-NEXT: v_subb_u32_e32 v7, vcc, v8, v7, vcc +; SDAG-NEXT: s_setpc_b64 s[30:31] +; +; GISEL-LABEL: v_sdiv_v2i128_vv: +; GISEL: ; %bb.0: ; %_udiv-special-cases_udiv-special-cases +; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-NEXT: s_mov_b64 s[8:9], 0 +; GISEL-NEXT: v_ashrrev_i32_e32 v24, 31, v3 +; GISEL-NEXT: v_ashrrev_i32_e32 v25, 31, v11 +; GISEL-NEXT: v_mov_b32_e32 v20, 0x7f +; GISEL-NEXT: v_mov_b32_e32 v21, 0 +; GISEL-NEXT: v_xor_b32_e32 v0, v24, v0 +; GISEL-NEXT: v_xor_b32_e32 v1, v24, v1 +; GISEL-NEXT: v_xor_b32_e32 v2, v24, v2 +; GISEL-NEXT: v_xor_b32_e32 v3, v24, v3 +; GISEL-NEXT: v_xor_b32_e32 v8, v25, v8 +; GISEL-NEXT: v_xor_b32_e32 v9, v25, v9 +; GISEL-NEXT: v_xor_b32_e32 v10, v25, v10 +; GISEL-NEXT: v_xor_b32_e32 v11, v25, v11 +; GISEL-NEXT: v_sub_i32_e32 v16, vcc, v0, v24 +; GISEL-NEXT: v_subb_u32_e32 v17, vcc, v1, v24, vcc +; GISEL-NEXT: v_sub_i32_e64 v26, s[4:5], v8, v25 +; GISEL-NEXT: v_subb_u32_e64 v27, s[4:5], v9, v25, s[4:5] +; GISEL-NEXT: v_subb_u32_e32 v18, vcc, v2, v24, vcc +; GISEL-NEXT: v_subb_u32_e32 v19, vcc, v3, v24, vcc +; GISEL-NEXT: v_subb_u32_e64 v10, vcc, v10, v25, s[4:5] +; GISEL-NEXT: v_subb_u32_e32 v11, vcc, v11, v25, vcc +; GISEL-NEXT: v_ffbh_u32_e32 v8, v27 +; GISEL-NEXT: v_ffbh_u32_e32 v9, v26 +; GISEL-NEXT: v_ffbh_u32_e32 v22, v17 +; GISEL-NEXT: v_ffbh_u32_e32 v23, v16 +; GISEL-NEXT: v_or_b32_e32 v0, v26, v10 +; GISEL-NEXT: v_or_b32_e32 v1, v27, v11 +; GISEL-NEXT: v_or_b32_e32 v2, v16, v18 +; GISEL-NEXT: v_or_b32_e32 v3, v17, v19 +; GISEL-NEXT: v_add_i32_e32 v9, vcc, 32, v9 +; GISEL-NEXT: v_ffbh_u32_e32 v28, v11 +; GISEL-NEXT: v_ffbh_u32_e32 v29, v10 +; GISEL-NEXT: v_add_i32_e32 v23, vcc, 32, v23 +; GISEL-NEXT: v_ffbh_u32_e32 v30, v19 +; GISEL-NEXT: v_ffbh_u32_e32 v31, v18 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[0:1] +; GISEL-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[2:3] +; GISEL-NEXT: v_min_u32_e32 v0, v8, v9 +; GISEL-NEXT: v_add_i32_e64 v1, s[6:7], 32, v29 +; GISEL-NEXT: v_min_u32_e32 v2, v22, v23 +; GISEL-NEXT: v_add_i32_e64 v3, s[6:7], 32, v31 +; GISEL-NEXT: v_add_i32_e64 v0, s[6:7], 64, v0 +; GISEL-NEXT: v_min_u32_e32 v1, v28, v1 +; GISEL-NEXT: v_add_i32_e64 v2, s[6:7], 64, v2 +; GISEL-NEXT: v_min_u32_e32 v3, v30, v3 +; GISEL-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v22, 0, 1, s[4:5] +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[10:11] +; GISEL-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[18:19] +; GISEL-NEXT: v_cndmask_b32_e32 v1, v3, v2, vcc +; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v0, v1 +; GISEL-NEXT: v_subb_u32_e64 v1, s[4:5], 0, 0, vcc +; GISEL-NEXT: v_subb_u32_e64 v2, s[4:5], 0, 0, s[4:5] +; GISEL-NEXT: v_subb_u32_e64 v3, s[4:5], 0, 0, s[4:5] +; GISEL-NEXT: v_cmp_gt_u64_e32 vcc, v[0:1], v[20:21] +; GISEL-NEXT: v_cndmask_b32_e64 v20, 0, 1, vcc +; GISEL-NEXT: v_xor_b32_e32 v8, 0x7f, v0 +; GISEL-NEXT: v_cmp_lt_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: v_cndmask_b32_e64 v21, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v8, v8, v2 +; GISEL-NEXT: v_or_b32_e32 v9, v1, v3 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: v_cndmask_b32_e32 v20, v21, v20, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[8:9] +; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v9, v22, v20 +; GISEL-NEXT: v_and_b32_e32 v20, 1, v9 +; GISEL-NEXT: v_or_b32_e32 v8, v9, v8 +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v20 +; GISEL-NEXT: v_cndmask_b32_e64 v20, v16, 0, vcc +; GISEL-NEXT: v_and_b32_e32 v22, 1, v8 +; GISEL-NEXT: v_cndmask_b32_e64 v21, v17, 0, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v8, v18, 0, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v9, v19, 0, vcc +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v22 +; GISEL-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GISEL-NEXT: s_and_saveexec_b64 s[12:13], s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB0_6 +; GISEL-NEXT: ; %bb.1: ; %udiv-bb15 +; GISEL-NEXT: v_add_i32_e32 v28, vcc, 1, v0 +; GISEL-NEXT: v_addc_u32_e64 v29, s[4:5], 0, v1, vcc +; GISEL-NEXT: v_sub_i32_e32 v32, vcc, 0x7f, v0 +; GISEL-NEXT: v_addc_u32_e64 v30, vcc, 0, v2, s[4:5] +; GISEL-NEXT: v_addc_u32_e32 v31, vcc, 0, v3, vcc +; GISEL-NEXT: v_subrev_i32_e64 v20, s[4:5], 64, v32 +; GISEL-NEXT: v_sub_i32_e64 v8, s[4:5], 64, v32 +; GISEL-NEXT: v_lshl_b64 v[0:1], v[16:17], v32 +; GISEL-NEXT: v_lshl_b64 v[2:3], v[18:19], v32 +; GISEL-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GISEL-NEXT: v_lshr_b64 v[8:9], v[16:17], v8 +; GISEL-NEXT: v_lshl_b64 v[22:23], v[16:17], v20 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v32 +; GISEL-NEXT: v_cndmask_b32_e32 v20, 0, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v21, 0, v1, vcc +; GISEL-NEXT: v_or_b32_e32 v0, v8, v2 +; GISEL-NEXT: v_or_b32_e32 v1, v9, v3 +; GISEL-NEXT: v_cndmask_b32_e32 v0, v22, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v1, v23, v1, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v32 +; GISEL-NEXT: v_cndmask_b32_e32 v8, v0, v18, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v9, v1, v19, vcc +; GISEL-NEXT: s_mov_b64 s[10:11], s[8:9] +; GISEL-NEXT: v_mov_b32_e32 v0, s8 +; GISEL-NEXT: v_mov_b32_e32 v1, s9 +; GISEL-NEXT: v_mov_b32_e32 v2, s10 +; GISEL-NEXT: v_mov_b32_e32 v3, s11 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; GISEL-NEXT: s_xor_b64 s[14:15], exec, s[6:7] +; GISEL-NEXT: s_cbranch_execz .LBB0_5 +; GISEL-NEXT: ; %bb.2: ; %udiv-preheader4 +; GISEL-NEXT: v_subrev_i32_e32 v34, vcc, 64, v28 +; GISEL-NEXT: v_sub_i32_e32 v22, vcc, 64, v28 +; GISEL-NEXT: v_lshr_b64 v[0:1], v[18:19], v28 +; GISEL-NEXT: v_lshr_b64 v[2:3], v[16:17], v28 +; GISEL-NEXT: v_add_i32_e32 v32, vcc, -1, v26 +; GISEL-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v28 +; GISEL-NEXT: v_cmp_eq_u32_e64 s[6:7], 0, v28 +; GISEL-NEXT: v_addc_u32_e32 v33, vcc, -1, v27, vcc +; GISEL-NEXT: v_lshl_b64 v[22:23], v[18:19], v22 +; GISEL-NEXT: v_lshr_b64 v[36:37], v[18:19], v34 +; GISEL-NEXT: s_mov_b64 s[10:11], s[8:9] +; GISEL-NEXT: v_cndmask_b32_e64 v18, 0, v0, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v19, 0, v1, s[4:5] +; GISEL-NEXT: v_addc_u32_e32 v34, vcc, -1, v10, vcc +; GISEL-NEXT: v_or_b32_e32 v0, v2, v22 +; GISEL-NEXT: v_or_b32_e32 v1, v3, v23 +; GISEL-NEXT: v_addc_u32_e32 v35, vcc, -1, v11, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v0, v36, v0, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v1, v37, v1, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v22, v0, v16, s[6:7] +; GISEL-NEXT: v_cndmask_b32_e64 v23, v1, v17, s[6:7] +; GISEL-NEXT: v_mov_b32_e32 v17, 0 +; GISEL-NEXT: v_mov_b32_e32 v0, s8 +; GISEL-NEXT: v_mov_b32_e32 v1, s9 +; GISEL-NEXT: v_mov_b32_e32 v2, s10 +; GISEL-NEXT: v_mov_b32_e32 v3, s11 +; GISEL-NEXT: .LBB0_3: ; %udiv-do-while3 +; GISEL-NEXT: ; =>This Inner Loop Header: Depth=1 +; GISEL-NEXT: v_lshrrev_b32_e32 v16, 31, v21 +; GISEL-NEXT: v_lshl_b64 v[2:3], v[20:21], 1 +; GISEL-NEXT: v_lshl_b64 v[36:37], v[22:23], 1 +; GISEL-NEXT: v_lshl_b64 v[18:19], v[18:19], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v22, 31, v23 +; GISEL-NEXT: v_lshrrev_b32_e32 v23, 31, v9 +; GISEL-NEXT: v_add_i32_e32 v28, vcc, -1, v28 +; GISEL-NEXT: v_addc_u32_e32 v29, vcc, -1, v29, vcc +; GISEL-NEXT: v_lshl_b64 v[8:9], v[8:9], 1 +; GISEL-NEXT: v_or_b32_e32 v20, v0, v2 +; GISEL-NEXT: v_or_b32_e32 v21, v1, v3 +; GISEL-NEXT: v_or_b32_e32 v2, v18, v22 +; GISEL-NEXT: v_or_b32_e32 v3, v36, v23 +; GISEL-NEXT: v_addc_u32_e32 v30, vcc, -1, v30, vcc +; GISEL-NEXT: v_addc_u32_e32 v31, vcc, -1, v31, vcc +; GISEL-NEXT: v_or_b32_e32 v8, v8, v16 +; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v32, v3 +; GISEL-NEXT: v_subb_u32_e32 v0, vcc, v33, v37, vcc +; GISEL-NEXT: v_or_b32_e32 v0, v28, v30 +; GISEL-NEXT: v_or_b32_e32 v1, v29, v31 +; GISEL-NEXT: v_subb_u32_e32 v16, vcc, v34, v2, vcc +; GISEL-NEXT: v_subb_u32_e32 v16, vcc, v35, v19, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[0:1] +; GISEL-NEXT: v_ashrrev_i32_e32 v0, 31, v16 +; GISEL-NEXT: s_or_b64 s[8:9], vcc, s[8:9] +; GISEL-NEXT: v_and_b32_e32 v1, v0, v26 +; GISEL-NEXT: v_and_b32_e32 v18, v0, v27 +; GISEL-NEXT: v_and_b32_e32 v16, 1, v0 +; GISEL-NEXT: v_and_b32_e32 v36, v0, v10 +; GISEL-NEXT: v_and_b32_e32 v0, v0, v11 +; GISEL-NEXT: v_sub_i32_e32 v22, vcc, v3, v1 +; GISEL-NEXT: v_subb_u32_e32 v23, vcc, v37, v18, vcc +; GISEL-NEXT: v_subb_u32_e32 v18, vcc, v2, v36, vcc +; GISEL-NEXT: v_subb_u32_e32 v19, vcc, v19, v0, vcc +; GISEL-NEXT: v_mov_b32_e32 v0, v16 +; GISEL-NEXT: v_mov_b32_e32 v1, v17 +; GISEL-NEXT: s_andn2_b64 exec, exec, s[8:9] +; GISEL-NEXT: s_cbranch_execnz .LBB0_3 +; GISEL-NEXT: ; %bb.4: ; %Flow13 +; GISEL-NEXT: s_or_b64 exec, exec, s[8:9] +; GISEL-NEXT: .LBB0_5: ; %Flow14 +; GISEL-NEXT: s_or_b64 exec, exec, s[14:15] +; GISEL-NEXT: v_lshl_b64 v[2:3], v[20:21], 1 +; GISEL-NEXT: v_lshl_b64 v[8:9], v[8:9], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v10, 31, v21 +; GISEL-NEXT: v_or_b32_e32 v8, v8, v10 +; GISEL-NEXT: v_or_b32_e32 v20, v0, v2 +; GISEL-NEXT: v_or_b32_e32 v21, v1, v3 +; GISEL-NEXT: .LBB0_6: ; %Flow16 +; GISEL-NEXT: s_or_b64 exec, exec, s[12:13] +; GISEL-NEXT: s_mov_b64 s[8:9], 0 +; GISEL-NEXT: v_ashrrev_i32_e32 v18, 31, v7 +; GISEL-NEXT: v_ashrrev_i32_e32 v19, 31, v15 +; GISEL-NEXT: v_mov_b32_e32 v10, 0x7f +; GISEL-NEXT: v_mov_b32_e32 v11, 0 +; GISEL-NEXT: v_xor_b32_e32 v0, v18, v4 +; GISEL-NEXT: v_xor_b32_e32 v1, v18, v5 +; GISEL-NEXT: v_xor_b32_e32 v2, v18, v6 +; GISEL-NEXT: v_xor_b32_e32 v3, v18, v7 +; GISEL-NEXT: v_xor_b32_e32 v4, v19, v12 +; GISEL-NEXT: v_xor_b32_e32 v5, v19, v13 +; GISEL-NEXT: v_xor_b32_e32 v14, v19, v14 +; GISEL-NEXT: v_xor_b32_e32 v15, v19, v15 +; GISEL-NEXT: v_sub_i32_e32 v6, vcc, v0, v18 +; GISEL-NEXT: v_subb_u32_e32 v7, vcc, v1, v18, vcc +; GISEL-NEXT: v_sub_i32_e64 v22, s[4:5], v4, v19 +; GISEL-NEXT: v_subb_u32_e64 v23, s[4:5], v5, v19, s[4:5] +; GISEL-NEXT: v_subb_u32_e32 v12, vcc, v2, v18, vcc +; GISEL-NEXT: v_subb_u32_e32 v13, vcc, v3, v18, vcc +; GISEL-NEXT: v_subb_u32_e64 v4, vcc, v14, v19, s[4:5] +; GISEL-NEXT: v_subb_u32_e32 v5, vcc, v15, v19, vcc +; GISEL-NEXT: v_ffbh_u32_e32 v14, v23 +; GISEL-NEXT: v_ffbh_u32_e32 v15, v22 +; GISEL-NEXT: v_ffbh_u32_e32 v16, v7 +; GISEL-NEXT: v_ffbh_u32_e32 v17, v6 +; GISEL-NEXT: v_or_b32_e32 v0, v22, v4 +; GISEL-NEXT: v_or_b32_e32 v1, v23, v5 +; GISEL-NEXT: v_or_b32_e32 v2, v6, v12 +; GISEL-NEXT: v_or_b32_e32 v3, v7, v13 +; GISEL-NEXT: v_add_i32_e32 v15, vcc, 32, v15 +; GISEL-NEXT: v_ffbh_u32_e32 v26, v5 +; GISEL-NEXT: v_ffbh_u32_e32 v27, v4 +; GISEL-NEXT: v_add_i32_e32 v17, vcc, 32, v17 +; GISEL-NEXT: v_ffbh_u32_e32 v28, v13 +; GISEL-NEXT: v_ffbh_u32_e32 v29, v12 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[0:1] +; GISEL-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[2:3] +; GISEL-NEXT: v_min_u32_e32 v0, v14, v15 +; GISEL-NEXT: v_add_i32_e64 v1, s[6:7], 32, v27 +; GISEL-NEXT: v_min_u32_e32 v2, v16, v17 +; GISEL-NEXT: v_add_i32_e64 v3, s[6:7], 32, v29 +; GISEL-NEXT: v_add_i32_e64 v0, s[6:7], 64, v0 +; GISEL-NEXT: v_min_u32_e32 v1, v26, v1 +; GISEL-NEXT: v_add_i32_e64 v2, s[6:7], 64, v2 +; GISEL-NEXT: v_min_u32_e32 v3, v28, v3 +; GISEL-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v14, 0, 1, s[4:5] +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[4:5] +; GISEL-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[12:13] +; GISEL-NEXT: v_cndmask_b32_e32 v1, v3, v2, vcc +; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v0, v1 +; GISEL-NEXT: v_subb_u32_e64 v1, s[4:5], 0, 0, vcc +; GISEL-NEXT: v_subb_u32_e64 v2, s[4:5], 0, 0, s[4:5] +; GISEL-NEXT: v_subb_u32_e64 v3, s[4:5], 0, 0, s[4:5] +; GISEL-NEXT: v_cmp_gt_u64_e32 vcc, v[0:1], v[10:11] +; GISEL-NEXT: v_cndmask_b32_e64 v15, 0, 1, vcc +; GISEL-NEXT: v_xor_b32_e32 v10, 0x7f, v0 +; GISEL-NEXT: v_cmp_lt_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: v_cndmask_b32_e64 v16, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v10, v10, v2 +; GISEL-NEXT: v_or_b32_e32 v11, v1, v3 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: v_cndmask_b32_e32 v15, v16, v15, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[10:11] +; GISEL-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v11, v14, v15 +; GISEL-NEXT: v_and_b32_e32 v14, 1, v11 +; GISEL-NEXT: v_or_b32_e32 v10, v11, v10 +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v14 +; GISEL-NEXT: v_cndmask_b32_e64 v14, v6, 0, vcc +; GISEL-NEXT: v_and_b32_e32 v16, 1, v10 +; GISEL-NEXT: v_cndmask_b32_e64 v15, v7, 0, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v10, v12, 0, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v11, v13, 0, vcc +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v16 +; GISEL-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GISEL-NEXT: s_and_saveexec_b64 s[12:13], s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB0_12 +; GISEL-NEXT: ; %bb.7: ; %udiv-bb1 +; GISEL-NEXT: v_add_i32_e32 v26, vcc, 1, v0 +; GISEL-NEXT: v_addc_u32_e64 v27, s[4:5], 0, v1, vcc +; GISEL-NEXT: v_sub_i32_e32 v30, vcc, 0x7f, v0 +; GISEL-NEXT: v_addc_u32_e64 v28, vcc, 0, v2, s[4:5] +; GISEL-NEXT: v_addc_u32_e32 v29, vcc, 0, v3, vcc +; GISEL-NEXT: v_subrev_i32_e64 v14, s[4:5], 64, v30 +; GISEL-NEXT: v_sub_i32_e64 v10, s[4:5], 64, v30 +; GISEL-NEXT: v_lshl_b64 v[0:1], v[6:7], v30 +; GISEL-NEXT: v_lshl_b64 v[2:3], v[12:13], v30 +; GISEL-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GISEL-NEXT: v_lshr_b64 v[10:11], v[6:7], v10 +; GISEL-NEXT: v_lshl_b64 v[16:17], v[6:7], v14 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v30 +; GISEL-NEXT: v_cndmask_b32_e32 v14, 0, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v15, 0, v1, vcc +; GISEL-NEXT: v_or_b32_e32 v0, v10, v2 +; GISEL-NEXT: v_or_b32_e32 v1, v11, v3 +; GISEL-NEXT: v_cndmask_b32_e32 v0, v16, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v1, v17, v1, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v30 +; GISEL-NEXT: v_cndmask_b32_e32 v10, v0, v12, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v11, v1, v13, vcc +; GISEL-NEXT: s_mov_b64 s[10:11], s[8:9] +; GISEL-NEXT: v_mov_b32_e32 v0, s8 +; GISEL-NEXT: v_mov_b32_e32 v1, s9 +; GISEL-NEXT: v_mov_b32_e32 v2, s10 +; GISEL-NEXT: v_mov_b32_e32 v3, s11 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; GISEL-NEXT: s_xor_b64 s[8:9], exec, s[6:7] +; GISEL-NEXT: s_cbranch_execz .LBB0_11 +; GISEL-NEXT: ; %bb.8: ; %udiv-preheader +; GISEL-NEXT: v_subrev_i32_e32 v32, vcc, 64, v26 +; GISEL-NEXT: v_sub_i32_e32 v16, vcc, 64, v26 +; GISEL-NEXT: v_lshr_b64 v[0:1], v[12:13], v26 +; GISEL-NEXT: v_lshr_b64 v[2:3], v[6:7], v26 +; GISEL-NEXT: s_mov_b64 s[4:5], 0 +; GISEL-NEXT: v_add_i32_e32 v30, vcc, -1, v22 +; GISEL-NEXT: v_addc_u32_e32 v31, vcc, -1, v23, vcc +; GISEL-NEXT: v_lshl_b64 v[16:17], v[12:13], v16 +; GISEL-NEXT: v_lshr_b64 v[12:13], v[12:13], v32 +; GISEL-NEXT: v_addc_u32_e32 v32, vcc, -1, v4, vcc +; GISEL-NEXT: v_addc_u32_e32 v33, vcc, -1, v5, vcc +; GISEL-NEXT: s_mov_b64 s[6:7], s[4:5] +; GISEL-NEXT: v_or_b32_e32 v2, v2, v16 +; GISEL-NEXT: v_or_b32_e32 v3, v3, v17 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v26 +; GISEL-NEXT: v_cndmask_b32_e32 v2, v12, v2, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v3, v13, v3, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v16, 0, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v17, 0, v1, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v26 +; GISEL-NEXT: v_cndmask_b32_e32 v12, v2, v6, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v13, v3, v7, vcc +; GISEL-NEXT: v_mov_b32_e32 v7, 0 +; GISEL-NEXT: v_mov_b32_e32 v0, s4 +; GISEL-NEXT: v_mov_b32_e32 v1, s5 +; GISEL-NEXT: v_mov_b32_e32 v2, s6 +; GISEL-NEXT: v_mov_b32_e32 v3, s7 +; GISEL-NEXT: .LBB0_9: ; %udiv-do-while +; GISEL-NEXT: ; =>This Inner Loop Header: Depth=1 +; GISEL-NEXT: v_lshl_b64 v[2:3], v[12:13], 1 +; GISEL-NEXT: v_lshl_b64 v[16:17], v[16:17], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v6, 31, v13 +; GISEL-NEXT: v_lshrrev_b32_e32 v34, 31, v11 +; GISEL-NEXT: v_lshl_b64 v[12:13], v[14:15], 1 +; GISEL-NEXT: v_lshl_b64 v[10:11], v[10:11], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v14, 31, v15 +; GISEL-NEXT: v_add_i32_e32 v26, vcc, -1, v26 +; GISEL-NEXT: v_addc_u32_e32 v27, vcc, -1, v27, vcc +; GISEL-NEXT: v_or_b32_e32 v16, v16, v6 +; GISEL-NEXT: v_or_b32_e32 v2, v2, v34 +; GISEL-NEXT: v_or_b32_e32 v10, v10, v14 +; GISEL-NEXT: v_or_b32_e32 v14, v0, v12 +; GISEL-NEXT: v_or_b32_e32 v15, v1, v13 +; GISEL-NEXT: v_addc_u32_e32 v28, vcc, -1, v28, vcc +; GISEL-NEXT: v_addc_u32_e32 v29, vcc, -1, v29, vcc +; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v30, v2 +; GISEL-NEXT: v_subb_u32_e32 v0, vcc, v31, v3, vcc +; GISEL-NEXT: v_or_b32_e32 v0, v26, v28 +; GISEL-NEXT: v_or_b32_e32 v1, v27, v29 +; GISEL-NEXT: v_subb_u32_e32 v6, vcc, v32, v16, vcc +; GISEL-NEXT: v_subb_u32_e32 v6, vcc, v33, v17, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[0:1] +; GISEL-NEXT: v_ashrrev_i32_e32 v0, 31, v6 +; GISEL-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GISEL-NEXT: v_and_b32_e32 v6, 1, v0 +; GISEL-NEXT: v_and_b32_e32 v12, v0, v22 +; GISEL-NEXT: v_and_b32_e32 v13, v0, v23 +; GISEL-NEXT: v_and_b32_e32 v34, v0, v4 +; GISEL-NEXT: v_and_b32_e32 v35, v0, v5 +; GISEL-NEXT: v_mov_b32_e32 v0, v6 +; GISEL-NEXT: v_mov_b32_e32 v1, v7 +; GISEL-NEXT: v_sub_i32_e32 v12, vcc, v2, v12 +; GISEL-NEXT: v_subb_u32_e32 v13, vcc, v3, v13, vcc +; GISEL-NEXT: v_subb_u32_e32 v16, vcc, v16, v34, vcc +; GISEL-NEXT: v_subb_u32_e32 v17, vcc, v17, v35, vcc +; GISEL-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GISEL-NEXT: s_cbranch_execnz .LBB0_9 +; GISEL-NEXT: ; %bb.10: ; %Flow +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: .LBB0_11: ; %Flow11 +; GISEL-NEXT: s_or_b64 exec, exec, s[8:9] +; GISEL-NEXT: v_lshl_b64 v[2:3], v[14:15], 1 +; GISEL-NEXT: v_lshl_b64 v[10:11], v[10:11], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v4, 31, v15 +; GISEL-NEXT: v_or_b32_e32 v10, v10, v4 +; GISEL-NEXT: v_or_b32_e32 v14, v0, v2 +; GISEL-NEXT: v_or_b32_e32 v15, v1, v3 +; GISEL-NEXT: .LBB0_12: ; %Flow12 +; GISEL-NEXT: s_or_b64 exec, exec, s[12:13] +; GISEL-NEXT: v_xor_b32_e32 v3, v25, v24 +; GISEL-NEXT: v_xor_b32_e32 v7, v19, v18 +; GISEL-NEXT: v_xor_b32_e32 v0, v20, v3 +; GISEL-NEXT: v_xor_b32_e32 v1, v21, v3 +; GISEL-NEXT: v_xor_b32_e32 v2, v8, v3 +; GISEL-NEXT: v_xor_b32_e32 v6, v9, v3 +; GISEL-NEXT: v_xor_b32_e32 v4, v14, v7 +; GISEL-NEXT: v_xor_b32_e32 v5, v15, v7 +; GISEL-NEXT: v_xor_b32_e32 v8, v10, v7 +; GISEL-NEXT: v_xor_b32_e32 v9, v11, v7 +; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v0, v3 +; GISEL-NEXT: v_subb_u32_e32 v1, vcc, v1, v3, vcc +; GISEL-NEXT: v_sub_i32_e64 v4, s[4:5], v4, v7 +; GISEL-NEXT: v_subb_u32_e64 v5, s[4:5], v5, v7, s[4:5] +; GISEL-NEXT: v_subb_u32_e32 v2, vcc, v2, v3, vcc +; GISEL-NEXT: v_subb_u32_e32 v3, vcc, v6, v3, vcc +; GISEL-NEXT: v_subb_u32_e64 v6, vcc, v8, v7, s[4:5] +; GISEL-NEXT: v_subb_u32_e32 v7, vcc, v9, v7, vcc +; GISEL-NEXT: s_setpc_b64 s[30:31] %shl = sdiv <2 x i128> %lhs, %rhs ret <2 x i128> %shl } define <2 x i128> @v_udiv_v2i128_vv(<2 x i128> %lhs, <2 x i128> %rhs) { +; SDAG-LABEL: v_udiv_v2i128_vv: +; SDAG: ; %bb.0: ; %_udiv-special-cases_udiv-special-cases +; SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-NEXT: v_or_b32_e32 v17, v9, v11 +; SDAG-NEXT: v_or_b32_e32 v16, v8, v10 +; SDAG-NEXT: v_or_b32_e32 v19, v1, v3 +; SDAG-NEXT: v_or_b32_e32 v18, v0, v2 +; SDAG-NEXT: v_ffbh_u32_e32 v20, v10 +; SDAG-NEXT: v_ffbh_u32_e32 v21, v11 +; SDAG-NEXT: v_ffbh_u32_e32 v22, v8 +; SDAG-NEXT: v_ffbh_u32_e32 v23, v9 +; SDAG-NEXT: v_ffbh_u32_e32 v24, v2 +; SDAG-NEXT: v_ffbh_u32_e32 v25, v3 +; SDAG-NEXT: v_ffbh_u32_e32 v26, v0 +; SDAG-NEXT: v_ffbh_u32_e32 v27, v1 +; SDAG-NEXT: v_mov_b32_e32 v28, 0 +; SDAG-NEXT: s_mov_b64 s[8:9], 0x7f +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[16:17] +; SDAG-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[18:19] +; SDAG-NEXT: v_add_i32_e64 v16, s[6:7], 32, v20 +; SDAG-NEXT: v_add_i32_e64 v17, s[6:7], 32, v22 +; SDAG-NEXT: v_add_i32_e64 v18, s[6:7], 32, v24 +; SDAG-NEXT: v_add_i32_e64 v19, s[6:7], 32, v26 +; SDAG-NEXT: s_or_b64 s[6:7], vcc, s[4:5] +; SDAG-NEXT: v_min_u32_e32 v16, v16, v21 +; SDAG-NEXT: v_min_u32_e32 v17, v17, v23 +; SDAG-NEXT: v_min_u32_e32 v18, v18, v25 +; SDAG-NEXT: v_min_u32_e32 v19, v19, v27 +; SDAG-NEXT: v_add_i32_e32 v17, vcc, 64, v17 +; SDAG-NEXT: v_addc_u32_e64 v20, s[4:5], 0, 0, vcc +; SDAG-NEXT: v_add_i32_e32 v19, vcc, 64, v19 +; SDAG-NEXT: v_addc_u32_e64 v21, s[4:5], 0, 0, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[10:11] +; SDAG-NEXT: v_cndmask_b32_e64 v20, v20, 0, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v16, v17, v16, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[2:3] +; SDAG-NEXT: v_cndmask_b32_e64 v17, v21, 0, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v18, v19, v18, vcc +; SDAG-NEXT: v_sub_i32_e32 v23, vcc, v16, v18 +; SDAG-NEXT: v_subb_u32_e32 v24, vcc, v20, v17, vcc +; SDAG-NEXT: v_xor_b32_e32 v16, 0x7f, v23 +; SDAG-NEXT: v_subbrev_u32_e32 v25, vcc, 0, v28, vcc +; SDAG-NEXT: v_cmp_lt_u64_e64 s[4:5], s[8:9], v[23:24] +; SDAG-NEXT: v_cndmask_b32_e64 v18, 0, 1, s[4:5] +; SDAG-NEXT: v_subbrev_u32_e32 v26, vcc, 0, v28, vcc +; SDAG-NEXT: v_or_b32_e32 v16, v16, v25 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[25:26] +; SDAG-NEXT: v_cndmask_b32_e64 v19, 0, 1, vcc +; SDAG-NEXT: v_or_b32_e32 v17, v24, v26 +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[25:26] +; SDAG-NEXT: v_cndmask_b32_e32 v18, v19, v18, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[16:17] +; SDAG-NEXT: v_and_b32_e32 v16, 1, v18 +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 1, v16 +; SDAG-NEXT: s_or_b64 s[4:5], s[6:7], s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v16, v3, 0, s[4:5] +; SDAG-NEXT: s_xor_b64 s[6:7], s[4:5], -1 +; SDAG-NEXT: v_cndmask_b32_e64 v17, v2, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v18, v1, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v19, v0, 0, s[4:5] +; SDAG-NEXT: s_and_b64 s[4:5], s[6:7], vcc +; SDAG-NEXT: s_and_saveexec_b64 s[8:9], s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB1_6 +; SDAG-NEXT: ; %bb.1: ; %udiv-bb15 +; SDAG-NEXT: v_add_i32_e32 v18, vcc, 1, v23 +; SDAG-NEXT: v_sub_i32_e64 v16, s[4:5], 63, v23 +; SDAG-NEXT: v_mov_b32_e32 v21, 0 +; SDAG-NEXT: v_mov_b32_e32 v22, 0 +; SDAG-NEXT: v_addc_u32_e32 v27, vcc, 0, v24, vcc +; SDAG-NEXT: v_lshl_b64 v[16:17], v[0:1], v16 +; SDAG-NEXT: v_addc_u32_e32 v28, vcc, 0, v25, vcc +; SDAG-NEXT: v_addc_u32_e32 v29, vcc, 0, v26, vcc +; SDAG-NEXT: v_or_b32_e32 v19, v18, v28 +; SDAG-NEXT: v_sub_i32_e32 v30, vcc, 0x7f, v23 +; SDAG-NEXT: v_or_b32_e32 v20, v27, v29 +; SDAG-NEXT: v_lshl_b64 v[23:24], v[2:3], v30 +; SDAG-NEXT: v_sub_i32_e32 v31, vcc, 64, v30 +; SDAG-NEXT: v_lshl_b64 v[25:26], v[0:1], v30 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[19:20] +; SDAG-NEXT: v_lshr_b64 v[19:20], v[0:1], v31 +; SDAG-NEXT: v_or_b32_e32 v20, v24, v20 +; SDAG-NEXT: v_or_b32_e32 v19, v23, v19 +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v30 +; SDAG-NEXT: v_cndmask_b32_e64 v17, v17, v20, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v16, v16, v19, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v24, 0, v26, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v23, 0, v25, s[4:5] +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v30 +; SDAG-NEXT: v_cndmask_b32_e64 v17, v17, v3, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v16, v16, v2, s[4:5] +; SDAG-NEXT: v_mov_b32_e32 v19, 0 +; SDAG-NEXT: v_mov_b32_e32 v20, 0 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[10:11], exec, s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB1_5 +; SDAG-NEXT: ; %bb.2: ; %udiv-preheader4 +; SDAG-NEXT: v_lshr_b64 v[21:22], v[0:1], v18 +; SDAG-NEXT: v_sub_i32_e32 v31, vcc, 64, v18 +; SDAG-NEXT: v_subrev_i32_e32 v36, vcc, 64, v18 +; SDAG-NEXT: v_lshr_b64 v[32:33], v[2:3], v18 +; SDAG-NEXT: v_add_i32_e32 v30, vcc, -1, v8 +; SDAG-NEXT: s_mov_b64 s[12:13], 0 +; SDAG-NEXT: v_mov_b32_e32 v25, 0 +; SDAG-NEXT: v_mov_b32_e32 v26, 0 +; SDAG-NEXT: v_mov_b32_e32 v19, 0 +; SDAG-NEXT: v_mov_b32_e32 v20, 0 +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v18 +; SDAG-NEXT: v_cmp_eq_u32_e64 s[6:7], 0, v18 +; SDAG-NEXT: v_lshl_b64 v[34:35], v[2:3], v31 +; SDAG-NEXT: v_lshr_b64 v[36:37], v[2:3], v36 +; SDAG-NEXT: v_addc_u32_e32 v31, vcc, -1, v9, vcc +; SDAG-NEXT: v_cndmask_b32_e64 v3, 0, v33, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v2, 0, v32, s[4:5] +; SDAG-NEXT: v_or_b32_e32 v22, v22, v35 +; SDAG-NEXT: v_or_b32_e32 v21, v21, v34 +; SDAG-NEXT: v_addc_u32_e32 v32, vcc, -1, v10, vcc +; SDAG-NEXT: v_cndmask_b32_e64 v22, v37, v22, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v21, v36, v21, s[4:5] +; SDAG-NEXT: v_addc_u32_e32 v33, vcc, -1, v11, vcc +; SDAG-NEXT: v_cndmask_b32_e64 v1, v22, v1, s[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v0, v21, v0, s[6:7] +; SDAG-NEXT: v_mov_b32_e32 v22, 0 +; SDAG-NEXT: .LBB1_3: ; %udiv-do-while3 +; SDAG-NEXT: ; =>This Inner Loop Header: Depth=1 +; SDAG-NEXT: v_lshrrev_b32_e32 v21, 31, v24 +; SDAG-NEXT: v_lshl_b64 v[23:24], v[23:24], 1 +; SDAG-NEXT: v_lshl_b64 v[2:3], v[2:3], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v34, 31, v1 +; SDAG-NEXT: v_lshl_b64 v[0:1], v[0:1], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v35, 31, v17 +; SDAG-NEXT: v_lshl_b64 v[16:17], v[16:17], 1 +; SDAG-NEXT: v_or_b32_e32 v24, v26, v24 +; SDAG-NEXT: v_or_b32_e32 v23, v25, v23 +; SDAG-NEXT: v_or_b32_e32 v2, v2, v34 +; SDAG-NEXT: v_or_b32_e32 v0, v0, v35 +; SDAG-NEXT: v_or_b32_e32 v16, v16, v21 +; SDAG-NEXT: v_sub_i32_e32 v21, vcc, v30, v0 +; SDAG-NEXT: v_subb_u32_e32 v21, vcc, v31, v1, vcc +; SDAG-NEXT: v_subb_u32_e32 v21, vcc, v32, v2, vcc +; SDAG-NEXT: v_subb_u32_e32 v21, vcc, v33, v3, vcc +; SDAG-NEXT: v_ashrrev_i32_e32 v21, 31, v21 +; SDAG-NEXT: v_and_b32_e32 v25, v21, v8 +; SDAG-NEXT: v_and_b32_e32 v26, v21, v9 +; SDAG-NEXT: v_and_b32_e32 v34, v21, v10 +; SDAG-NEXT: v_and_b32_e32 v35, v21, v11 +; SDAG-NEXT: v_and_b32_e32 v21, 1, v21 +; SDAG-NEXT: v_sub_i32_e32 v0, vcc, v0, v25 +; SDAG-NEXT: v_subb_u32_e32 v1, vcc, v1, v26, vcc +; SDAG-NEXT: v_subb_u32_e32 v2, vcc, v2, v34, vcc +; SDAG-NEXT: v_subb_u32_e32 v3, vcc, v3, v35, vcc +; SDAG-NEXT: v_add_i32_e32 v18, vcc, -1, v18 +; SDAG-NEXT: v_addc_u32_e32 v27, vcc, -1, v27, vcc +; SDAG-NEXT: v_addc_u32_e32 v28, vcc, -1, v28, vcc +; SDAG-NEXT: v_addc_u32_e32 v29, vcc, -1, v29, vcc +; SDAG-NEXT: v_or_b32_e32 v25, v18, v28 +; SDAG-NEXT: v_or_b32_e32 v26, v27, v29 +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[25:26] +; SDAG-NEXT: v_or_b32_e32 v17, v20, v17 +; SDAG-NEXT: s_or_b64 s[12:13], vcc, s[12:13] +; SDAG-NEXT: v_or_b32_e32 v16, v19, v16 +; SDAG-NEXT: v_mov_b32_e32 v26, v22 +; SDAG-NEXT: v_mov_b32_e32 v25, v21 +; SDAG-NEXT: s_andn2_b64 exec, exec, s[12:13] +; SDAG-NEXT: s_cbranch_execnz .LBB1_3 +; SDAG-NEXT: ; %bb.4: ; %Flow13 +; SDAG-NEXT: s_or_b64 exec, exec, s[12:13] +; SDAG-NEXT: .LBB1_5: ; %Flow14 +; SDAG-NEXT: s_or_b64 exec, exec, s[10:11] +; SDAG-NEXT: v_lshl_b64 v[0:1], v[16:17], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v8, 31, v24 +; SDAG-NEXT: v_lshl_b64 v[2:3], v[23:24], 1 +; SDAG-NEXT: v_or_b32_e32 v0, v0, v8 +; SDAG-NEXT: v_or_b32_e32 v16, v20, v1 +; SDAG-NEXT: v_or_b32_e32 v18, v22, v3 +; SDAG-NEXT: v_or_b32_e32 v17, v19, v0 +; SDAG-NEXT: v_or_b32_e32 v19, v21, v2 +; SDAG-NEXT: .LBB1_6: ; %Flow16 +; SDAG-NEXT: s_or_b64 exec, exec, s[8:9] +; SDAG-NEXT: v_or_b32_e32 v1, v13, v15 +; SDAG-NEXT: v_or_b32_e32 v0, v12, v14 +; SDAG-NEXT: v_or_b32_e32 v3, v5, v7 +; SDAG-NEXT: v_or_b32_e32 v2, v4, v6 +; SDAG-NEXT: v_ffbh_u32_e32 v8, v14 +; SDAG-NEXT: v_ffbh_u32_e32 v9, v15 +; SDAG-NEXT: v_ffbh_u32_e32 v10, v12 +; SDAG-NEXT: v_ffbh_u32_e32 v11, v13 +; SDAG-NEXT: v_ffbh_u32_e32 v20, v6 +; SDAG-NEXT: v_ffbh_u32_e32 v21, v7 +; SDAG-NEXT: v_ffbh_u32_e32 v22, v4 +; SDAG-NEXT: v_ffbh_u32_e32 v23, v5 +; SDAG-NEXT: v_mov_b32_e32 v24, 0 +; SDAG-NEXT: s_mov_b64 s[8:9], 0x7f +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[0:1] +; SDAG-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[2:3] +; SDAG-NEXT: v_add_i32_e64 v0, s[6:7], 32, v8 +; SDAG-NEXT: v_add_i32_e64 v1, s[6:7], 32, v10 +; SDAG-NEXT: v_add_i32_e64 v2, s[6:7], 32, v20 +; SDAG-NEXT: v_add_i32_e64 v3, s[6:7], 32, v22 +; SDAG-NEXT: s_or_b64 s[6:7], vcc, s[4:5] +; SDAG-NEXT: v_min_u32_e32 v0, v0, v9 +; SDAG-NEXT: v_min_u32_e32 v1, v1, v11 +; SDAG-NEXT: v_min_u32_e32 v2, v2, v21 +; SDAG-NEXT: v_min_u32_e32 v3, v3, v23 +; SDAG-NEXT: v_add_i32_e32 v1, vcc, 64, v1 +; SDAG-NEXT: v_addc_u32_e64 v8, s[4:5], 0, 0, vcc +; SDAG-NEXT: v_add_i32_e32 v3, vcc, 64, v3 +; SDAG-NEXT: v_addc_u32_e64 v9, s[4:5], 0, 0, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[14:15] +; SDAG-NEXT: v_cndmask_b32_e64 v8, v8, 0, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v1, v9, 0, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v2, v3, v2, vcc +; SDAG-NEXT: v_sub_i32_e32 v0, vcc, v0, v2 +; SDAG-NEXT: v_subb_u32_e32 v1, vcc, v8, v1, vcc +; SDAG-NEXT: v_xor_b32_e32 v8, 0x7f, v0 +; SDAG-NEXT: v_subbrev_u32_e32 v2, vcc, 0, v24, vcc +; SDAG-NEXT: v_cmp_lt_u64_e64 s[4:5], s[8:9], v[0:1] +; SDAG-NEXT: v_cndmask_b32_e64 v10, 0, 1, s[4:5] +; SDAG-NEXT: v_subbrev_u32_e32 v3, vcc, 0, v24, vcc +; SDAG-NEXT: v_or_b32_e32 v8, v8, v2 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[2:3] +; SDAG-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc +; SDAG-NEXT: v_or_b32_e32 v9, v1, v3 +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[2:3] +; SDAG-NEXT: v_cndmask_b32_e32 v10, v11, v10, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[8:9] +; SDAG-NEXT: v_and_b32_e32 v8, 1, v10 +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 1, v8 +; SDAG-NEXT: s_or_b64 s[4:5], s[6:7], s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v8, v7, 0, s[4:5] +; SDAG-NEXT: s_xor_b64 s[6:7], s[4:5], -1 +; SDAG-NEXT: v_cndmask_b32_e64 v9, v6, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v10, v5, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v11, v4, 0, s[4:5] +; SDAG-NEXT: s_and_b64 s[4:5], s[6:7], vcc +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB1_12 +; SDAG-NEXT: ; %bb.7: ; %udiv-bb1 +; SDAG-NEXT: v_add_i32_e32 v8, vcc, 1, v0 +; SDAG-NEXT: v_sub_i32_e64 v9, s[4:5], 63, v0 +; SDAG-NEXT: v_mov_b32_e32 v20, 0 +; SDAG-NEXT: v_mov_b32_e32 v21, 0 +; SDAG-NEXT: v_addc_u32_e32 v11, vcc, 0, v1, vcc +; SDAG-NEXT: v_lshl_b64 v[9:10], v[4:5], v9 +; SDAG-NEXT: v_addc_u32_e32 v24, vcc, 0, v2, vcc +; SDAG-NEXT: v_addc_u32_e32 v25, vcc, 0, v3, vcc +; SDAG-NEXT: v_or_b32_e32 v1, v8, v24 +; SDAG-NEXT: v_sub_i32_e32 v3, vcc, 0x7f, v0 +; SDAG-NEXT: v_or_b32_e32 v2, v11, v25 +; SDAG-NEXT: v_lshl_b64 v[22:23], v[6:7], v3 +; SDAG-NEXT: v_sub_i32_e32 v0, vcc, 64, v3 +; SDAG-NEXT: v_lshl_b64 v[26:27], v[4:5], v3 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[1:2] +; SDAG-NEXT: v_lshr_b64 v[0:1], v[4:5], v0 +; SDAG-NEXT: v_or_b32_e32 v1, v23, v1 +; SDAG-NEXT: v_or_b32_e32 v0, v22, v0 +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v3 +; SDAG-NEXT: v_cndmask_b32_e64 v2, v10, v1, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v9, v9, v0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v1, 0, v27, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v0, 0, v26, s[4:5] +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v3 +; SDAG-NEXT: v_cndmask_b32_e64 v3, v2, v7, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v2, v9, v6, s[4:5] +; SDAG-NEXT: v_mov_b32_e32 v9, 0 +; SDAG-NEXT: v_mov_b32_e32 v10, 0 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[8:9], exec, s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB1_11 +; SDAG-NEXT: ; %bb.8: ; %udiv-preheader +; SDAG-NEXT: v_lshr_b64 v[20:21], v[4:5], v8 +; SDAG-NEXT: v_sub_i32_e32 v27, vcc, 64, v8 +; SDAG-NEXT: v_subrev_i32_e32 v28, vcc, 64, v8 +; SDAG-NEXT: v_lshr_b64 v[29:30], v[6:7], v8 +; SDAG-NEXT: v_add_i32_e32 v26, vcc, -1, v12 +; SDAG-NEXT: s_mov_b64 s[10:11], 0 +; SDAG-NEXT: v_mov_b32_e32 v22, 0 +; SDAG-NEXT: v_mov_b32_e32 v23, 0 +; SDAG-NEXT: v_mov_b32_e32 v9, 0 +; SDAG-NEXT: v_mov_b32_e32 v10, 0 +; SDAG-NEXT: v_lshl_b64 v[31:32], v[6:7], v27 +; SDAG-NEXT: v_lshr_b64 v[6:7], v[6:7], v28 +; SDAG-NEXT: v_addc_u32_e32 v27, vcc, -1, v13, vcc +; SDAG-NEXT: v_or_b32_e32 v21, v21, v32 +; SDAG-NEXT: v_or_b32_e32 v20, v20, v31 +; SDAG-NEXT: v_addc_u32_e32 v28, vcc, -1, v14, vcc +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v8 +; SDAG-NEXT: v_cndmask_b32_e64 v21, v7, v21, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v20, v6, v20, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v7, 0, v30, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v6, 0, v29, s[4:5] +; SDAG-NEXT: v_addc_u32_e32 v29, vcc, -1, v15, vcc +; SDAG-NEXT: v_cmp_eq_u32_e32 vcc, 0, v8 +; SDAG-NEXT: v_cndmask_b32_e32 v5, v21, v5, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v4, v20, v4, vcc +; SDAG-NEXT: v_mov_b32_e32 v21, 0 +; SDAG-NEXT: .LBB1_9: ; %udiv-do-while +; SDAG-NEXT: ; =>This Inner Loop Header: Depth=1 +; SDAG-NEXT: v_lshl_b64 v[6:7], v[6:7], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v20, 31, v5 +; SDAG-NEXT: v_lshl_b64 v[4:5], v[4:5], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v30, 31, v3 +; SDAG-NEXT: v_lshl_b64 v[2:3], v[2:3], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v31, 31, v1 +; SDAG-NEXT: v_lshl_b64 v[0:1], v[0:1], 1 +; SDAG-NEXT: v_or_b32_e32 v6, v6, v20 +; SDAG-NEXT: v_or_b32_e32 v4, v4, v30 +; SDAG-NEXT: v_or_b32_e32 v2, v2, v31 +; SDAG-NEXT: v_or_b32_e32 v3, v10, v3 +; SDAG-NEXT: v_or_b32_e32 v1, v23, v1 +; SDAG-NEXT: v_or_b32_e32 v2, v9, v2 +; SDAG-NEXT: v_sub_i32_e32 v20, vcc, v26, v4 +; SDAG-NEXT: v_subb_u32_e32 v20, vcc, v27, v5, vcc +; SDAG-NEXT: v_subb_u32_e32 v20, vcc, v28, v6, vcc +; SDAG-NEXT: v_subb_u32_e32 v20, vcc, v29, v7, vcc +; SDAG-NEXT: v_ashrrev_i32_e32 v23, 31, v20 +; SDAG-NEXT: v_and_b32_e32 v20, 1, v23 +; SDAG-NEXT: v_and_b32_e32 v30, v23, v15 +; SDAG-NEXT: v_and_b32_e32 v31, v23, v14 +; SDAG-NEXT: v_and_b32_e32 v32, v23, v13 +; SDAG-NEXT: v_and_b32_e32 v23, v23, v12 +; SDAG-NEXT: v_sub_i32_e32 v4, vcc, v4, v23 +; SDAG-NEXT: v_subb_u32_e32 v5, vcc, v5, v32, vcc +; SDAG-NEXT: v_subb_u32_e32 v6, vcc, v6, v31, vcc +; SDAG-NEXT: v_subb_u32_e32 v7, vcc, v7, v30, vcc +; SDAG-NEXT: v_add_i32_e32 v8, vcc, -1, v8 +; SDAG-NEXT: v_addc_u32_e32 v11, vcc, -1, v11, vcc +; SDAG-NEXT: v_addc_u32_e32 v24, vcc, -1, v24, vcc +; SDAG-NEXT: v_addc_u32_e32 v25, vcc, -1, v25, vcc +; SDAG-NEXT: v_or_b32_e32 v31, v11, v25 +; SDAG-NEXT: v_or_b32_e32 v30, v8, v24 +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[30:31] +; SDAG-NEXT: s_or_b64 s[10:11], vcc, s[10:11] +; SDAG-NEXT: v_or_b32_e32 v0, v22, v0 +; SDAG-NEXT: v_mov_b32_e32 v23, v21 +; SDAG-NEXT: v_mov_b32_e32 v22, v20 +; SDAG-NEXT: s_andn2_b64 exec, exec, s[10:11] +; SDAG-NEXT: s_cbranch_execnz .LBB1_9 +; SDAG-NEXT: ; %bb.10: ; %Flow +; SDAG-NEXT: s_or_b64 exec, exec, s[10:11] +; SDAG-NEXT: .LBB1_11: ; %Flow11 +; SDAG-NEXT: s_or_b64 exec, exec, s[8:9] +; SDAG-NEXT: v_lshl_b64 v[2:3], v[2:3], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v4, 31, v1 +; SDAG-NEXT: v_lshl_b64 v[0:1], v[0:1], 1 +; SDAG-NEXT: v_or_b32_e32 v2, v2, v4 +; SDAG-NEXT: v_or_b32_e32 v8, v10, v3 +; SDAG-NEXT: v_or_b32_e32 v10, v21, v1 +; SDAG-NEXT: v_or_b32_e32 v9, v9, v2 +; SDAG-NEXT: v_or_b32_e32 v11, v20, v0 +; SDAG-NEXT: .LBB1_12: ; %Flow12 +; SDAG-NEXT: s_or_b64 exec, exec, s[6:7] +; SDAG-NEXT: v_mov_b32_e32 v0, v19 +; SDAG-NEXT: v_mov_b32_e32 v1, v18 +; SDAG-NEXT: v_mov_b32_e32 v2, v17 +; SDAG-NEXT: v_mov_b32_e32 v3, v16 +; SDAG-NEXT: v_mov_b32_e32 v4, v11 +; SDAG-NEXT: v_mov_b32_e32 v5, v10 +; SDAG-NEXT: v_mov_b32_e32 v6, v9 +; SDAG-NEXT: v_mov_b32_e32 v7, v8 +; SDAG-NEXT: s_setpc_b64 s[30:31] +; +; GISEL-LABEL: v_udiv_v2i128_vv: +; GISEL: ; %bb.0: ; %_udiv-special-cases_udiv-special-cases +; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-NEXT: v_mov_b32_e32 v16, v2 +; GISEL-NEXT: v_mov_b32_e32 v17, v3 +; GISEL-NEXT: s_mov_b64 s[8:9], 0 +; GISEL-NEXT: v_or_b32_e32 v2, v8, v10 +; GISEL-NEXT: v_or_b32_e32 v3, v9, v11 +; GISEL-NEXT: v_or_b32_e32 v18, v0, v16 +; GISEL-NEXT: v_or_b32_e32 v19, v1, v17 +; GISEL-NEXT: v_ffbh_u32_e32 v20, v9 +; GISEL-NEXT: v_ffbh_u32_e32 v21, v8 +; GISEL-NEXT: v_ffbh_u32_e32 v22, v11 +; GISEL-NEXT: v_ffbh_u32_e32 v23, v10 +; GISEL-NEXT: v_ffbh_u32_e32 v26, v1 +; GISEL-NEXT: v_ffbh_u32_e32 v27, v0 +; GISEL-NEXT: v_ffbh_u32_e32 v28, v17 +; GISEL-NEXT: v_ffbh_u32_e32 v29, v16 +; GISEL-NEXT: v_mov_b32_e32 v24, 0x7f +; GISEL-NEXT: v_mov_b32_e32 v25, 0 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[18:19] +; GISEL-NEXT: v_add_i32_e64 v2, s[6:7], 32, v21 +; GISEL-NEXT: v_add_i32_e64 v3, s[6:7], 32, v23 +; GISEL-NEXT: v_add_i32_e64 v18, s[6:7], 32, v27 +; GISEL-NEXT: v_add_i32_e64 v19, s[6:7], 32, v29 +; GISEL-NEXT: v_min_u32_e32 v2, v20, v2 +; GISEL-NEXT: v_min_u32_e32 v3, v22, v3 +; GISEL-NEXT: v_min_u32_e32 v18, v26, v18 +; GISEL-NEXT: v_min_u32_e32 v19, v28, v19 +; GISEL-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v26, 0, 1, s[4:5] +; GISEL-NEXT: v_add_i32_e32 v2, vcc, 64, v2 +; GISEL-NEXT: v_add_i32_e32 v18, vcc, 64, v18 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[10:11] +; GISEL-NEXT: v_cndmask_b32_e32 v2, v3, v2, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[16:17] +; GISEL-NEXT: v_cndmask_b32_e32 v3, v19, v18, vcc +; GISEL-NEXT: v_sub_i32_e32 v20, vcc, v2, v3 +; GISEL-NEXT: v_subb_u32_e64 v21, s[4:5], 0, 0, vcc +; GISEL-NEXT: v_subb_u32_e64 v22, s[4:5], 0, 0, s[4:5] +; GISEL-NEXT: v_subb_u32_e64 v23, s[4:5], 0, 0, s[4:5] +; GISEL-NEXT: v_cmp_gt_u64_e32 vcc, v[20:21], v[24:25] +; GISEL-NEXT: v_cndmask_b32_e64 v18, 0, 1, vcc +; GISEL-NEXT: v_xor_b32_e32 v2, 0x7f, v20 +; GISEL-NEXT: v_cmp_lt_u64_e32 vcc, 0, v[22:23] +; GISEL-NEXT: v_cndmask_b32_e64 v19, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v2, v2, v22 +; GISEL-NEXT: v_or_b32_e32 v3, v21, v23 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[22:23] +; GISEL-NEXT: v_cndmask_b32_e32 v18, v19, v18, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: v_cndmask_b32_e64 v2, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v3, v26, v18 +; GISEL-NEXT: v_and_b32_e32 v18, 1, v3 +; GISEL-NEXT: v_or_b32_e32 v2, v3, v2 +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v18 +; GISEL-NEXT: v_cndmask_b32_e64 v18, v0, 0, vcc +; GISEL-NEXT: v_and_b32_e32 v24, 1, v2 +; GISEL-NEXT: v_cndmask_b32_e64 v19, v1, 0, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v2, v16, 0, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v3, v17, 0, vcc +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v24 +; GISEL-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GISEL-NEXT: s_and_saveexec_b64 s[12:13], s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB1_6 +; GISEL-NEXT: ; %bb.1: ; %udiv-bb15 +; GISEL-NEXT: v_add_i32_e32 v26, vcc, 1, v20 +; GISEL-NEXT: v_addc_u32_e64 v27, s[4:5], 0, v21, vcc +; GISEL-NEXT: v_sub_i32_e32 v30, vcc, 0x7f, v20 +; GISEL-NEXT: v_addc_u32_e64 v28, vcc, 0, v22, s[4:5] +; GISEL-NEXT: v_addc_u32_e32 v29, vcc, 0, v23, vcc +; GISEL-NEXT: v_subrev_i32_e64 v22, s[4:5], 64, v30 +; GISEL-NEXT: v_sub_i32_e64 v20, s[4:5], 64, v30 +; GISEL-NEXT: v_lshl_b64 v[2:3], v[0:1], v30 +; GISEL-NEXT: v_lshl_b64 v[18:19], v[16:17], v30 +; GISEL-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GISEL-NEXT: v_lshr_b64 v[20:21], v[0:1], v20 +; GISEL-NEXT: v_lshl_b64 v[24:25], v[0:1], v22 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v30 +; GISEL-NEXT: v_cndmask_b32_e32 v22, 0, v2, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v23, 0, v3, vcc +; GISEL-NEXT: v_or_b32_e32 v2, v20, v18 +; GISEL-NEXT: v_or_b32_e32 v3, v21, v19 +; GISEL-NEXT: v_cndmask_b32_e32 v2, v24, v2, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v3, v25, v3, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v30 +; GISEL-NEXT: v_cndmask_b32_e32 v2, v2, v16, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v3, v3, v17, vcc +; GISEL-NEXT: s_mov_b64 s[10:11], s[8:9] +; GISEL-NEXT: v_mov_b32_e32 v21, s11 +; GISEL-NEXT: v_mov_b32_e32 v20, s10 +; GISEL-NEXT: v_mov_b32_e32 v19, s9 +; GISEL-NEXT: v_mov_b32_e32 v18, s8 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; GISEL-NEXT: s_xor_b64 s[8:9], exec, s[6:7] +; GISEL-NEXT: s_cbranch_execz .LBB1_5 +; GISEL-NEXT: ; %bb.2: ; %udiv-preheader4 +; GISEL-NEXT: v_subrev_i32_e32 v32, vcc, 64, v26 +; GISEL-NEXT: v_sub_i32_e32 v24, vcc, 64, v26 +; GISEL-NEXT: v_lshr_b64 v[18:19], v[16:17], v26 +; GISEL-NEXT: v_lshr_b64 v[20:21], v[0:1], v26 +; GISEL-NEXT: s_mov_b64 s[4:5], 0 +; GISEL-NEXT: v_add_i32_e32 v30, vcc, -1, v8 +; GISEL-NEXT: v_addc_u32_e32 v31, vcc, -1, v9, vcc +; GISEL-NEXT: v_lshl_b64 v[24:25], v[16:17], v24 +; GISEL-NEXT: v_lshr_b64 v[16:17], v[16:17], v32 +; GISEL-NEXT: v_addc_u32_e32 v32, vcc, -1, v10, vcc +; GISEL-NEXT: v_addc_u32_e32 v33, vcc, -1, v11, vcc +; GISEL-NEXT: s_mov_b64 s[6:7], s[4:5] +; GISEL-NEXT: v_or_b32_e32 v20, v20, v24 +; GISEL-NEXT: v_or_b32_e32 v21, v21, v25 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v26 +; GISEL-NEXT: v_cndmask_b32_e32 v20, v16, v20, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v21, v17, v21, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v16, 0, v18, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v17, 0, v19, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v26 +; GISEL-NEXT: v_cndmask_b32_e32 v24, v20, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v25, v21, v1, vcc +; GISEL-NEXT: v_mov_b32_e32 v1, 0 +; GISEL-NEXT: v_mov_b32_e32 v21, s7 +; GISEL-NEXT: v_mov_b32_e32 v20, s6 +; GISEL-NEXT: v_mov_b32_e32 v19, s5 +; GISEL-NEXT: v_mov_b32_e32 v18, s4 +; GISEL-NEXT: .LBB1_3: ; %udiv-do-while3 +; GISEL-NEXT: ; =>This Inner Loop Header: Depth=1 +; GISEL-NEXT: v_lshrrev_b32_e32 v34, 31, v23 +; GISEL-NEXT: v_lshl_b64 v[20:21], v[22:23], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v0, 31, v25 +; GISEL-NEXT: v_lshl_b64 v[24:25], v[24:25], 1 +; GISEL-NEXT: v_lshl_b64 v[16:17], v[16:17], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v35, 31, v3 +; GISEL-NEXT: v_add_i32_e32 v26, vcc, -1, v26 +; GISEL-NEXT: v_addc_u32_e32 v27, vcc, -1, v27, vcc +; GISEL-NEXT: v_lshl_b64 v[2:3], v[2:3], 1 +; GISEL-NEXT: v_or_b32_e32 v22, v18, v20 +; GISEL-NEXT: v_or_b32_e32 v23, v19, v21 +; GISEL-NEXT: v_or_b32_e32 v16, v16, v0 +; GISEL-NEXT: v_or_b32_e32 v20, v24, v35 +; GISEL-NEXT: v_addc_u32_e32 v28, vcc, -1, v28, vcc +; GISEL-NEXT: v_addc_u32_e32 v29, vcc, -1, v29, vcc +; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v30, v20 +; GISEL-NEXT: v_subb_u32_e32 v0, vcc, v31, v25, vcc +; GISEL-NEXT: v_or_b32_e32 v18, v26, v28 +; GISEL-NEXT: v_or_b32_e32 v19, v27, v29 +; GISEL-NEXT: v_subb_u32_e32 v0, vcc, v32, v16, vcc +; GISEL-NEXT: v_subb_u32_e32 v0, vcc, v33, v17, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[18:19] +; GISEL-NEXT: v_ashrrev_i32_e32 v0, 31, v0 +; GISEL-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GISEL-NEXT: v_and_b32_e32 v18, v0, v8 +; GISEL-NEXT: v_and_b32_e32 v19, v0, v9 +; GISEL-NEXT: v_and_b32_e32 v21, v0, v10 +; GISEL-NEXT: v_and_b32_e32 v35, v0, v11 +; GISEL-NEXT: v_and_b32_e32 v0, 1, v0 +; GISEL-NEXT: v_sub_i32_e32 v24, vcc, v20, v18 +; GISEL-NEXT: v_subb_u32_e32 v25, vcc, v25, v19, vcc +; GISEL-NEXT: v_subb_u32_e32 v16, vcc, v16, v21, vcc +; GISEL-NEXT: v_subb_u32_e32 v17, vcc, v17, v35, vcc +; GISEL-NEXT: v_or_b32_e32 v2, v2, v34 +; GISEL-NEXT: v_mov_b32_e32 v19, v1 +; GISEL-NEXT: v_mov_b32_e32 v18, v0 +; GISEL-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GISEL-NEXT: s_cbranch_execnz .LBB1_3 +; GISEL-NEXT: ; %bb.4: ; %Flow13 +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: .LBB1_5: ; %Flow14 +; GISEL-NEXT: s_or_b64 exec, exec, s[8:9] +; GISEL-NEXT: v_lshl_b64 v[0:1], v[22:23], 1 +; GISEL-NEXT: v_lshl_b64 v[2:3], v[2:3], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v8, 31, v23 +; GISEL-NEXT: v_or_b32_e32 v2, v2, v8 +; GISEL-NEXT: v_or_b32_e32 v18, v18, v0 +; GISEL-NEXT: v_or_b32_e32 v19, v19, v1 +; GISEL-NEXT: .LBB1_6: ; %Flow16 +; GISEL-NEXT: s_or_b64 exec, exec, s[12:13] +; GISEL-NEXT: s_mov_b64 s[8:9], 0 +; GISEL-NEXT: v_or_b32_e32 v0, v12, v14 +; GISEL-NEXT: v_or_b32_e32 v1, v13, v15 +; GISEL-NEXT: v_or_b32_e32 v8, v4, v6 +; GISEL-NEXT: v_or_b32_e32 v9, v5, v7 +; GISEL-NEXT: v_ffbh_u32_e32 v16, v13 +; GISEL-NEXT: v_ffbh_u32_e32 v17, v12 +; GISEL-NEXT: v_ffbh_u32_e32 v20, v15 +; GISEL-NEXT: v_ffbh_u32_e32 v21, v14 +; GISEL-NEXT: v_ffbh_u32_e32 v22, v5 +; GISEL-NEXT: v_ffbh_u32_e32 v23, v4 +; GISEL-NEXT: v_ffbh_u32_e32 v24, v7 +; GISEL-NEXT: v_ffbh_u32_e32 v25, v6 +; GISEL-NEXT: v_mov_b32_e32 v10, 0x7f +; GISEL-NEXT: v_mov_b32_e32 v11, 0 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[0:1] +; GISEL-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[8:9] +; GISEL-NEXT: v_add_i32_e64 v0, s[6:7], 32, v17 +; GISEL-NEXT: v_add_i32_e64 v1, s[6:7], 32, v21 +; GISEL-NEXT: v_add_i32_e64 v8, s[6:7], 32, v23 +; GISEL-NEXT: v_add_i32_e64 v9, s[6:7], 32, v25 +; GISEL-NEXT: v_min_u32_e32 v0, v16, v0 +; GISEL-NEXT: v_min_u32_e32 v1, v20, v1 +; GISEL-NEXT: v_min_u32_e32 v8, v22, v8 +; GISEL-NEXT: v_min_u32_e32 v9, v24, v9 +; GISEL-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v20, 0, 1, s[4:5] +; GISEL-NEXT: v_add_i32_e32 v0, vcc, 64, v0 +; GISEL-NEXT: v_add_i32_e32 v8, vcc, 64, v8 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[14:15] +; GISEL-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[6:7] +; GISEL-NEXT: v_cndmask_b32_e32 v1, v9, v8, vcc +; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v0, v1 +; GISEL-NEXT: v_subb_u32_e64 v1, s[4:5], 0, 0, vcc +; GISEL-NEXT: v_subb_u32_e64 v16, s[4:5], 0, 0, s[4:5] +; GISEL-NEXT: v_subb_u32_e64 v17, s[4:5], 0, 0, s[4:5] +; GISEL-NEXT: v_cmp_gt_u64_e32 vcc, v[0:1], v[10:11] +; GISEL-NEXT: v_cndmask_b32_e64 v10, 0, 1, vcc +; GISEL-NEXT: v_xor_b32_e32 v8, 0x7f, v0 +; GISEL-NEXT: v_cmp_lt_u64_e32 vcc, 0, v[16:17] +; GISEL-NEXT: v_cndmask_b32_e64 v11, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v8, v8, v16 +; GISEL-NEXT: v_or_b32_e32 v9, v1, v17 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[16:17] +; GISEL-NEXT: v_cndmask_b32_e32 v10, v11, v10, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[8:9] +; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v9, v20, v10 +; GISEL-NEXT: v_and_b32_e32 v10, 1, v9 +; GISEL-NEXT: v_or_b32_e32 v8, v9, v8 +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v10 +; GISEL-NEXT: v_cndmask_b32_e64 v10, v4, 0, vcc +; GISEL-NEXT: v_and_b32_e32 v20, 1, v8 +; GISEL-NEXT: v_cndmask_b32_e64 v11, v5, 0, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v8, v6, 0, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v9, v7, 0, vcc +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v20 +; GISEL-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GISEL-NEXT: s_and_saveexec_b64 s[12:13], s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB1_12 +; GISEL-NEXT: ; %bb.7: ; %udiv-bb1 +; GISEL-NEXT: v_add_i32_e32 v8, vcc, 1, v0 +; GISEL-NEXT: v_addc_u32_e64 v11, s[4:5], 0, v1, vcc +; GISEL-NEXT: v_sub_i32_e32 v26, vcc, 0x7f, v0 +; GISEL-NEXT: v_addc_u32_e64 v24, vcc, 0, v16, s[4:5] +; GISEL-NEXT: v_addc_u32_e32 v25, vcc, 0, v17, vcc +; GISEL-NEXT: v_subrev_i32_e64 v9, s[4:5], 64, v26 +; GISEL-NEXT: v_sub_i32_e64 v10, s[4:5], 64, v26 +; GISEL-NEXT: v_lshl_b64 v[0:1], v[4:5], v26 +; GISEL-NEXT: v_lshl_b64 v[16:17], v[6:7], v26 +; GISEL-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GISEL-NEXT: v_lshr_b64 v[20:21], v[4:5], v10 +; GISEL-NEXT: v_lshl_b64 v[22:23], v[4:5], v9 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v26 +; GISEL-NEXT: v_cndmask_b32_e32 v9, 0, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v10, 0, v1, vcc +; GISEL-NEXT: v_or_b32_e32 v0, v20, v16 +; GISEL-NEXT: v_or_b32_e32 v1, v21, v17 +; GISEL-NEXT: v_cndmask_b32_e32 v0, v22, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v1, v23, v1, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v26 +; GISEL-NEXT: v_cndmask_b32_e32 v0, v0, v6, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v1, v1, v7, vcc +; GISEL-NEXT: s_mov_b64 s[10:11], s[8:9] +; GISEL-NEXT: v_mov_b32_e32 v23, s11 +; GISEL-NEXT: v_mov_b32_e32 v22, s10 +; GISEL-NEXT: v_mov_b32_e32 v21, s9 +; GISEL-NEXT: v_mov_b32_e32 v20, s8 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; GISEL-NEXT: s_xor_b64 s[8:9], exec, s[6:7] +; GISEL-NEXT: s_cbranch_execz .LBB1_11 +; GISEL-NEXT: ; %bb.8: ; %udiv-preheader +; GISEL-NEXT: v_subrev_i32_e32 v28, vcc, 64, v8 +; GISEL-NEXT: v_sub_i32_e32 v22, vcc, 64, v8 +; GISEL-NEXT: v_lshr_b64 v[16:17], v[6:7], v8 +; GISEL-NEXT: v_lshr_b64 v[20:21], v[4:5], v8 +; GISEL-NEXT: s_mov_b64 s[4:5], 0 +; GISEL-NEXT: v_add_i32_e32 v26, vcc, -1, v12 +; GISEL-NEXT: v_addc_u32_e32 v27, vcc, -1, v13, vcc +; GISEL-NEXT: v_lshl_b64 v[22:23], v[6:7], v22 +; GISEL-NEXT: v_lshr_b64 v[6:7], v[6:7], v28 +; GISEL-NEXT: v_addc_u32_e32 v28, vcc, -1, v14, vcc +; GISEL-NEXT: v_addc_u32_e32 v29, vcc, -1, v15, vcc +; GISEL-NEXT: s_mov_b64 s[6:7], s[4:5] +; GISEL-NEXT: v_or_b32_e32 v20, v20, v22 +; GISEL-NEXT: v_or_b32_e32 v21, v21, v23 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v8 +; GISEL-NEXT: v_cndmask_b32_e32 v6, v6, v20, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v7, v7, v21, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v16, 0, v16, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v17, 0, v17, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v8 +; GISEL-NEXT: v_cndmask_b32_e32 v6, v6, v4, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v7, v7, v5, vcc +; GISEL-NEXT: v_mov_b32_e32 v5, 0 +; GISEL-NEXT: v_mov_b32_e32 v23, s7 +; GISEL-NEXT: v_mov_b32_e32 v22, s6 +; GISEL-NEXT: v_mov_b32_e32 v21, s5 +; GISEL-NEXT: v_mov_b32_e32 v20, s4 +; GISEL-NEXT: .LBB1_9: ; %udiv-do-while +; GISEL-NEXT: ; =>This Inner Loop Header: Depth=1 +; GISEL-NEXT: v_lshl_b64 v[22:23], v[6:7], 1 +; GISEL-NEXT: v_lshl_b64 v[16:17], v[16:17], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v4, 31, v7 +; GISEL-NEXT: v_lshrrev_b32_e32 v30, 31, v1 +; GISEL-NEXT: v_lshl_b64 v[6:7], v[9:10], 1 +; GISEL-NEXT: v_lshl_b64 v[0:1], v[0:1], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v9, 31, v10 +; GISEL-NEXT: v_add_i32_e32 v8, vcc, -1, v8 +; GISEL-NEXT: v_addc_u32_e32 v11, vcc, -1, v11, vcc +; GISEL-NEXT: v_or_b32_e32 v16, v16, v4 +; GISEL-NEXT: v_or_b32_e32 v22, v22, v30 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v9 +; GISEL-NEXT: v_or_b32_e32 v9, v20, v6 +; GISEL-NEXT: v_or_b32_e32 v10, v21, v7 +; GISEL-NEXT: v_addc_u32_e32 v24, vcc, -1, v24, vcc +; GISEL-NEXT: v_addc_u32_e32 v25, vcc, -1, v25, vcc +; GISEL-NEXT: v_sub_i32_e32 v4, vcc, v26, v22 +; GISEL-NEXT: v_subb_u32_e32 v4, vcc, v27, v23, vcc +; GISEL-NEXT: v_or_b32_e32 v6, v8, v24 +; GISEL-NEXT: v_or_b32_e32 v7, v11, v25 +; GISEL-NEXT: v_subb_u32_e32 v4, vcc, v28, v16, vcc +; GISEL-NEXT: v_subb_u32_e32 v4, vcc, v29, v17, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[6:7] +; GISEL-NEXT: v_ashrrev_i32_e32 v6, 31, v4 +; GISEL-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GISEL-NEXT: v_and_b32_e32 v4, 1, v6 +; GISEL-NEXT: v_and_b32_e32 v7, v6, v12 +; GISEL-NEXT: v_and_b32_e32 v30, v6, v13 +; GISEL-NEXT: v_and_b32_e32 v31, v6, v14 +; GISEL-NEXT: v_and_b32_e32 v32, v6, v15 +; GISEL-NEXT: v_mov_b32_e32 v21, v5 +; GISEL-NEXT: v_mov_b32_e32 v20, v4 +; GISEL-NEXT: v_sub_i32_e32 v6, vcc, v22, v7 +; GISEL-NEXT: v_subb_u32_e32 v7, vcc, v23, v30, vcc +; GISEL-NEXT: v_subb_u32_e32 v16, vcc, v16, v31, vcc +; GISEL-NEXT: v_subb_u32_e32 v17, vcc, v17, v32, vcc +; GISEL-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GISEL-NEXT: s_cbranch_execnz .LBB1_9 +; GISEL-NEXT: ; %bb.10: ; %Flow +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: .LBB1_11: ; %Flow11 +; GISEL-NEXT: s_or_b64 exec, exec, s[8:9] +; GISEL-NEXT: v_lshl_b64 v[4:5], v[9:10], 1 +; GISEL-NEXT: v_lshl_b64 v[8:9], v[0:1], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v0, 31, v10 +; GISEL-NEXT: v_or_b32_e32 v8, v8, v0 +; GISEL-NEXT: v_or_b32_e32 v10, v20, v4 +; GISEL-NEXT: v_or_b32_e32 v11, v21, v5 +; GISEL-NEXT: .LBB1_12: ; %Flow12 +; GISEL-NEXT: s_or_b64 exec, exec, s[12:13] +; GISEL-NEXT: v_mov_b32_e32 v0, v18 +; GISEL-NEXT: v_mov_b32_e32 v1, v19 +; GISEL-NEXT: v_mov_b32_e32 v4, v10 +; GISEL-NEXT: v_mov_b32_e32 v5, v11 +; GISEL-NEXT: v_mov_b32_e32 v6, v8 +; GISEL-NEXT: v_mov_b32_e32 v7, v9 +; GISEL-NEXT: s_setpc_b64 s[30:31] %shl = udiv <2 x i128> %lhs, %rhs ret <2 x i128> %shl } define <2 x i128> @v_srem_v2i128_vv(<2 x i128> %lhs, <2 x i128> %rhs) { +; SDAG-LABEL: v_srem_v2i128_vv: +; SDAG: ; %bb.0: ; %_udiv-special-cases_udiv-special-cases +; SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-NEXT: buffer_store_dword v40, off, s[0:3], s32 ; 4-byte Folded Spill +; SDAG-NEXT: v_ashrrev_i32_e32 v28, 31, v3 +; SDAG-NEXT: v_ashrrev_i32_e32 v16, 31, v11 +; SDAG-NEXT: v_mov_b32_e32 v17, 0 +; SDAG-NEXT: s_mov_b64 s[10:11], 0x7f +; SDAG-NEXT: v_mov_b32_e32 v29, v28 +; SDAG-NEXT: v_xor_b32_e32 v18, v3, v28 +; SDAG-NEXT: v_xor_b32_e32 v19, v2, v28 +; SDAG-NEXT: v_xor_b32_e32 v1, v1, v28 +; SDAG-NEXT: v_xor_b32_e32 v0, v0, v28 +; SDAG-NEXT: v_xor_b32_e32 v11, v11, v16 +; SDAG-NEXT: v_xor_b32_e32 v10, v10, v16 +; SDAG-NEXT: v_xor_b32_e32 v20, v9, v16 +; SDAG-NEXT: v_xor_b32_e32 v9, v8, v16 +; SDAG-NEXT: v_sub_i32_e32 v2, vcc, v0, v28 +; SDAG-NEXT: v_subb_u32_e32 v3, vcc, v1, v28, vcc +; SDAG-NEXT: v_ffbh_u32_e32 v1, v2 +; SDAG-NEXT: v_subb_u32_e32 v0, vcc, v19, v28, vcc +; SDAG-NEXT: v_add_i32_e64 v19, s[4:5], 32, v1 +; SDAG-NEXT: v_ffbh_u32_e32 v21, v3 +; SDAG-NEXT: v_subb_u32_e32 v1, vcc, v18, v28, vcc +; SDAG-NEXT: v_or_b32_e32 v8, v2, v0 +; SDAG-NEXT: v_ffbh_u32_e32 v18, v0 +; SDAG-NEXT: v_min_u32_e32 v19, v19, v21 +; SDAG-NEXT: v_sub_i32_e32 v31, vcc, v9, v16 +; SDAG-NEXT: v_or_b32_e32 v9, v3, v1 +; SDAG-NEXT: v_add_i32_e64 v18, s[4:5], 32, v18 +; SDAG-NEXT: v_ffbh_u32_e32 v21, v1 +; SDAG-NEXT: v_add_i32_e64 v19, s[4:5], 64, v19 +; SDAG-NEXT: v_addc_u32_e64 v22, s[4:5], 0, 0, s[4:5] +; SDAG-NEXT: v_subb_u32_e32 v30, vcc, v20, v16, vcc +; SDAG-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[8:9] +; SDAG-NEXT: v_ffbh_u32_e32 v9, v31 +; SDAG-NEXT: v_min_u32_e32 v18, v18, v21 +; SDAG-NEXT: v_cmp_ne_u64_e64 s[6:7], 0, v[0:1] +; SDAG-NEXT: v_cndmask_b32_e64 v20, v22, 0, s[6:7] +; SDAG-NEXT: v_subb_u32_e32 v8, vcc, v10, v16, vcc +; SDAG-NEXT: v_add_i32_e64 v21, s[8:9], 32, v9 +; SDAG-NEXT: v_ffbh_u32_e32 v22, v30 +; SDAG-NEXT: v_cndmask_b32_e64 v18, v19, v18, s[6:7] +; SDAG-NEXT: v_subb_u32_e32 v9, vcc, v11, v16, vcc +; SDAG-NEXT: v_or_b32_e32 v10, v31, v8 +; SDAG-NEXT: v_ffbh_u32_e32 v16, v8 +; SDAG-NEXT: v_min_u32_e32 v19, v21, v22 +; SDAG-NEXT: v_or_b32_e32 v11, v30, v9 +; SDAG-NEXT: v_add_i32_e32 v16, vcc, 32, v16 +; SDAG-NEXT: v_ffbh_u32_e32 v21, v9 +; SDAG-NEXT: v_add_i32_e32 v19, vcc, 64, v19 +; SDAG-NEXT: v_addc_u32_e64 v22, s[6:7], 0, 0, vcc +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[10:11] +; SDAG-NEXT: v_min_u32_e32 v10, v16, v21 +; SDAG-NEXT: v_cmp_ne_u64_e64 s[6:7], 0, v[8:9] +; SDAG-NEXT: v_cndmask_b32_e64 v11, v22, 0, s[6:7] +; SDAG-NEXT: s_or_b64 s[8:9], vcc, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v10, v19, v10, s[6:7] +; SDAG-NEXT: v_sub_i32_e32 v10, vcc, v10, v18 +; SDAG-NEXT: v_subb_u32_e32 v11, vcc, v11, v20, vcc +; SDAG-NEXT: v_xor_b32_e32 v16, 0x7f, v10 +; SDAG-NEXT: v_subbrev_u32_e32 v18, vcc, 0, v17, vcc +; SDAG-NEXT: v_cmp_lt_u64_e64 s[4:5], s[10:11], v[10:11] +; SDAG-NEXT: v_cndmask_b32_e64 v20, 0, 1, s[4:5] +; SDAG-NEXT: v_subbrev_u32_e32 v19, vcc, 0, v17, vcc +; SDAG-NEXT: v_or_b32_e32 v16, v16, v18 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[18:19] +; SDAG-NEXT: v_cndmask_b32_e64 v21, 0, 1, vcc +; SDAG-NEXT: v_or_b32_e32 v17, v11, v19 +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[18:19] +; SDAG-NEXT: v_cndmask_b32_e32 v20, v21, v20, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[16:17] +; SDAG-NEXT: v_and_b32_e32 v16, 1, v20 +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 1, v16 +; SDAG-NEXT: s_or_b64 s[4:5], s[8:9], s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v35, v1, 0, s[4:5] +; SDAG-NEXT: s_xor_b64 s[6:7], s[4:5], -1 +; SDAG-NEXT: v_cndmask_b32_e64 v32, v0, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v27, v3, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v33, v2, 0, s[4:5] +; SDAG-NEXT: s_and_b64 s[4:5], s[6:7], vcc +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB2_6 +; SDAG-NEXT: ; %bb.1: ; %udiv-bb15 +; SDAG-NEXT: v_add_i32_e32 v32, vcc, 1, v10 +; SDAG-NEXT: v_sub_i32_e64 v20, s[4:5], 63, v10 +; SDAG-NEXT: v_mov_b32_e32 v16, 0 +; SDAG-NEXT: v_mov_b32_e32 v17, 0 +; SDAG-NEXT: v_addc_u32_e32 v33, vcc, 0, v11, vcc +; SDAG-NEXT: v_lshl_b64 v[20:21], v[2:3], v20 +; SDAG-NEXT: v_addc_u32_e32 v34, vcc, 0, v18, vcc +; SDAG-NEXT: v_addc_u32_e32 v35, vcc, 0, v19, vcc +; SDAG-NEXT: v_or_b32_e32 v18, v32, v34 +; SDAG-NEXT: v_sub_i32_e32 v24, vcc, 0x7f, v10 +; SDAG-NEXT: v_or_b32_e32 v19, v33, v35 +; SDAG-NEXT: v_lshl_b64 v[10:11], v[0:1], v24 +; SDAG-NEXT: v_sub_i32_e32 v25, vcc, 64, v24 +; SDAG-NEXT: v_lshl_b64 v[22:23], v[2:3], v24 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[18:19] +; SDAG-NEXT: v_lshr_b64 v[18:19], v[2:3], v25 +; SDAG-NEXT: v_or_b32_e32 v11, v11, v19 +; SDAG-NEXT: v_or_b32_e32 v10, v10, v18 +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v24 +; SDAG-NEXT: v_cndmask_b32_e64 v11, v21, v11, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v10, v20, v10, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v21, 0, v23, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v20, 0, v22, s[4:5] +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v24 +; SDAG-NEXT: v_cndmask_b32_e64 v11, v11, v1, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v10, v10, v0, s[4:5] +; SDAG-NEXT: v_mov_b32_e32 v18, 0 +; SDAG-NEXT: v_mov_b32_e32 v19, 0 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[8:9], exec, s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB2_5 +; SDAG-NEXT: ; %bb.2: ; %udiv-preheader4 +; SDAG-NEXT: v_lshr_b64 v[16:17], v[2:3], v32 +; SDAG-NEXT: v_sub_i32_e32 v26, vcc, 64, v32 +; SDAG-NEXT: v_subrev_i32_e32 v37, vcc, 64, v32 +; SDAG-NEXT: v_lshr_b64 v[24:25], v[0:1], v32 +; SDAG-NEXT: v_add_i32_e32 v36, vcc, -1, v31 +; SDAG-NEXT: s_mov_b64 s[10:11], 0 +; SDAG-NEXT: v_mov_b32_e32 v22, 0 +; SDAG-NEXT: v_mov_b32_e32 v23, 0 +; SDAG-NEXT: v_mov_b32_e32 v18, 0 +; SDAG-NEXT: v_mov_b32_e32 v19, 0 +; SDAG-NEXT: v_lshl_b64 v[26:27], v[0:1], v26 +; SDAG-NEXT: v_lshr_b64 v[48:49], v[0:1], v37 +; SDAG-NEXT: v_addc_u32_e32 v37, vcc, -1, v30, vcc +; SDAG-NEXT: v_or_b32_e32 v17, v17, v27 +; SDAG-NEXT: v_or_b32_e32 v16, v16, v26 +; SDAG-NEXT: v_addc_u32_e32 v38, vcc, -1, v8, vcc +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v32 +; SDAG-NEXT: v_cndmask_b32_e64 v17, v49, v17, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v16, v48, v16, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v27, 0, v25, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v26, 0, v24, s[4:5] +; SDAG-NEXT: v_addc_u32_e32 v39, vcc, -1, v9, vcc +; SDAG-NEXT: v_cmp_eq_u32_e32 vcc, 0, v32 +; SDAG-NEXT: v_cndmask_b32_e32 v25, v17, v3, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v24, v16, v2, vcc +; SDAG-NEXT: v_mov_b32_e32 v17, 0 +; SDAG-NEXT: .LBB2_3: ; %udiv-do-while3 +; SDAG-NEXT: ; =>This Inner Loop Header: Depth=1 +; SDAG-NEXT: v_lshl_b64 v[26:27], v[26:27], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v16, 31, v25 +; SDAG-NEXT: v_lshl_b64 v[24:25], v[24:25], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v48, 31, v11 +; SDAG-NEXT: v_lshl_b64 v[10:11], v[10:11], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v49, 31, v21 +; SDAG-NEXT: v_lshl_b64 v[20:21], v[20:21], 1 +; SDAG-NEXT: v_or_b32_e32 v26, v26, v16 +; SDAG-NEXT: v_or_b32_e32 v24, v24, v48 +; SDAG-NEXT: v_or_b32_e32 v10, v10, v49 +; SDAG-NEXT: v_or_b32_e32 v11, v19, v11 +; SDAG-NEXT: v_sub_i32_e32 v16, vcc, v36, v24 +; SDAG-NEXT: v_or_b32_e32 v10, v18, v10 +; SDAG-NEXT: v_subb_u32_e32 v16, vcc, v37, v25, vcc +; SDAG-NEXT: v_subb_u32_e32 v16, vcc, v38, v26, vcc +; SDAG-NEXT: v_subb_u32_e32 v16, vcc, v39, v27, vcc +; SDAG-NEXT: v_ashrrev_i32_e32 v16, 31, v16 +; SDAG-NEXT: v_and_b32_e32 v48, v16, v31 +; SDAG-NEXT: v_and_b32_e32 v49, v16, v30 +; SDAG-NEXT: v_and_b32_e32 v50, v16, v8 +; SDAG-NEXT: v_and_b32_e32 v51, v16, v9 +; SDAG-NEXT: v_and_b32_e32 v16, 1, v16 +; SDAG-NEXT: v_sub_i32_e32 v24, vcc, v24, v48 +; SDAG-NEXT: v_subb_u32_e32 v25, vcc, v25, v49, vcc +; SDAG-NEXT: v_subb_u32_e32 v26, vcc, v26, v50, vcc +; SDAG-NEXT: v_subb_u32_e32 v27, vcc, v27, v51, vcc +; SDAG-NEXT: v_add_i32_e32 v32, vcc, -1, v32 +; SDAG-NEXT: v_addc_u32_e32 v33, vcc, -1, v33, vcc +; SDAG-NEXT: v_addc_u32_e32 v34, vcc, -1, v34, vcc +; SDAG-NEXT: v_addc_u32_e32 v35, vcc, -1, v35, vcc +; SDAG-NEXT: v_or_b32_e32 v48, v32, v34 +; SDAG-NEXT: v_or_b32_e32 v49, v33, v35 +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[48:49] +; SDAG-NEXT: v_or_b32_e32 v21, v23, v21 +; SDAG-NEXT: s_or_b64 s[10:11], vcc, s[10:11] +; SDAG-NEXT: v_or_b32_e32 v20, v22, v20 +; SDAG-NEXT: v_mov_b32_e32 v23, v17 +; SDAG-NEXT: v_mov_b32_e32 v22, v16 +; SDAG-NEXT: s_andn2_b64 exec, exec, s[10:11] +; SDAG-NEXT: s_cbranch_execnz .LBB2_3 +; SDAG-NEXT: ; %bb.4: ; %Flow13 +; SDAG-NEXT: s_or_b64 exec, exec, s[10:11] +; SDAG-NEXT: .LBB2_5: ; %Flow14 +; SDAG-NEXT: s_or_b64 exec, exec, s[8:9] +; SDAG-NEXT: v_lshl_b64 v[10:11], v[10:11], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v22, 31, v21 +; SDAG-NEXT: v_lshl_b64 v[20:21], v[20:21], 1 +; SDAG-NEXT: v_or_b32_e32 v10, v10, v22 +; SDAG-NEXT: v_or_b32_e32 v35, v19, v11 +; SDAG-NEXT: v_or_b32_e32 v27, v17, v21 +; SDAG-NEXT: v_or_b32_e32 v32, v18, v10 +; SDAG-NEXT: v_or_b32_e32 v33, v16, v20 +; SDAG-NEXT: .LBB2_6: ; %Flow16 +; SDAG-NEXT: s_or_b64 exec, exec, s[6:7] +; SDAG-NEXT: v_ashrrev_i32_e32 v26, 31, v7 +; SDAG-NEXT: v_ashrrev_i32_e32 v16, 31, v15 +; SDAG-NEXT: v_mov_b32_e32 v17, 0 +; SDAG-NEXT: s_mov_b64 s[10:11], 0x7f +; SDAG-NEXT: v_mov_b32_e32 v34, v26 +; SDAG-NEXT: v_xor_b32_e32 v10, v7, v26 +; SDAG-NEXT: v_xor_b32_e32 v11, v6, v26 +; SDAG-NEXT: v_xor_b32_e32 v5, v5, v26 +; SDAG-NEXT: v_xor_b32_e32 v4, v4, v26 +; SDAG-NEXT: v_xor_b32_e32 v15, v15, v16 +; SDAG-NEXT: v_xor_b32_e32 v14, v14, v16 +; SDAG-NEXT: v_xor_b32_e32 v13, v13, v16 +; SDAG-NEXT: v_xor_b32_e32 v12, v12, v16 +; SDAG-NEXT: v_sub_i32_e32 v6, vcc, v4, v26 +; SDAG-NEXT: v_subb_u32_e32 v7, vcc, v5, v26, vcc +; SDAG-NEXT: v_ffbh_u32_e32 v5, v6 +; SDAG-NEXT: v_subb_u32_e32 v4, vcc, v11, v26, vcc +; SDAG-NEXT: v_add_i32_e64 v11, s[4:5], 32, v5 +; SDAG-NEXT: v_ffbh_u32_e32 v18, v7 +; SDAG-NEXT: v_subb_u32_e32 v5, vcc, v10, v26, vcc +; SDAG-NEXT: v_or_b32_e32 v10, v6, v4 +; SDAG-NEXT: v_ffbh_u32_e32 v19, v4 +; SDAG-NEXT: v_min_u32_e32 v18, v11, v18 +; SDAG-NEXT: v_sub_i32_e32 v37, vcc, v12, v16 +; SDAG-NEXT: v_or_b32_e32 v11, v7, v5 +; SDAG-NEXT: v_add_i32_e64 v12, s[4:5], 32, v19 +; SDAG-NEXT: v_ffbh_u32_e32 v19, v5 +; SDAG-NEXT: v_add_i32_e64 v18, s[4:5], 64, v18 +; SDAG-NEXT: v_addc_u32_e64 v20, s[4:5], 0, 0, s[4:5] +; SDAG-NEXT: v_subb_u32_e32 v36, vcc, v13, v16, vcc +; SDAG-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[10:11] +; SDAG-NEXT: v_ffbh_u32_e32 v11, v37 +; SDAG-NEXT: v_min_u32_e32 v12, v12, v19 +; SDAG-NEXT: v_cmp_ne_u64_e64 s[6:7], 0, v[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v19, v20, 0, s[6:7] +; SDAG-NEXT: v_subb_u32_e32 v10, vcc, v14, v16, vcc +; SDAG-NEXT: v_add_i32_e64 v13, s[8:9], 32, v11 +; SDAG-NEXT: v_ffbh_u32_e32 v14, v36 +; SDAG-NEXT: v_cndmask_b32_e64 v18, v18, v12, s[6:7] +; SDAG-NEXT: v_subb_u32_e32 v11, vcc, v15, v16, vcc +; SDAG-NEXT: v_or_b32_e32 v12, v37, v10 +; SDAG-NEXT: v_ffbh_u32_e32 v15, v10 +; SDAG-NEXT: v_min_u32_e32 v14, v13, v14 +; SDAG-NEXT: v_or_b32_e32 v13, v36, v11 +; SDAG-NEXT: v_add_i32_e32 v15, vcc, 32, v15 +; SDAG-NEXT: v_ffbh_u32_e32 v16, v11 +; SDAG-NEXT: v_add_i32_e32 v14, vcc, 64, v14 +; SDAG-NEXT: v_addc_u32_e64 v20, s[6:7], 0, 0, vcc +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[12:13] +; SDAG-NEXT: v_min_u32_e32 v12, v15, v16 +; SDAG-NEXT: v_cmp_ne_u64_e64 s[6:7], 0, v[10:11] +; SDAG-NEXT: v_cndmask_b32_e64 v13, v20, 0, s[6:7] +; SDAG-NEXT: s_or_b64 s[8:9], vcc, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v12, v14, v12, s[6:7] +; SDAG-NEXT: v_sub_i32_e32 v12, vcc, v12, v18 +; SDAG-NEXT: v_subb_u32_e32 v13, vcc, v13, v19, vcc +; SDAG-NEXT: v_xor_b32_e32 v16, 0x7f, v12 +; SDAG-NEXT: v_subbrev_u32_e32 v14, vcc, 0, v17, vcc +; SDAG-NEXT: v_cmp_lt_u64_e64 s[4:5], s[10:11], v[12:13] +; SDAG-NEXT: v_cndmask_b32_e64 v18, 0, 1, s[4:5] +; SDAG-NEXT: v_subbrev_u32_e32 v15, vcc, 0, v17, vcc +; SDAG-NEXT: v_or_b32_e32 v16, v16, v14 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[14:15] +; SDAG-NEXT: v_cndmask_b32_e64 v19, 0, 1, vcc +; SDAG-NEXT: v_or_b32_e32 v17, v13, v15 +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[14:15] +; SDAG-NEXT: v_cndmask_b32_e32 v18, v19, v18, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[16:17] +; SDAG-NEXT: v_and_b32_e32 v16, 1, v18 +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 1, v16 +; SDAG-NEXT: s_or_b64 s[4:5], s[8:9], s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v19, v5, 0, s[4:5] +; SDAG-NEXT: s_xor_b64 s[6:7], s[4:5], -1 +; SDAG-NEXT: v_cndmask_b32_e64 v18, v4, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v17, v7, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v16, v6, 0, s[4:5] +; SDAG-NEXT: s_and_b64 s[4:5], s[6:7], vcc +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB2_12 +; SDAG-NEXT: ; %bb.7: ; %udiv-bb1 +; SDAG-NEXT: v_add_i32_e32 v38, vcc, 1, v12 +; SDAG-NEXT: v_sub_i32_e64 v18, s[4:5], 63, v12 +; SDAG-NEXT: v_mov_b32_e32 v16, 0 +; SDAG-NEXT: v_mov_b32_e32 v17, 0 +; SDAG-NEXT: v_addc_u32_e32 v39, vcc, 0, v13, vcc +; SDAG-NEXT: v_lshl_b64 v[18:19], v[6:7], v18 +; SDAG-NEXT: v_addc_u32_e32 v48, vcc, 0, v14, vcc +; SDAG-NEXT: v_addc_u32_e32 v49, vcc, 0, v15, vcc +; SDAG-NEXT: v_or_b32_e32 v13, v38, v48 +; SDAG-NEXT: v_sub_i32_e32 v15, vcc, 0x7f, v12 +; SDAG-NEXT: v_or_b32_e32 v14, v39, v49 +; SDAG-NEXT: v_lshl_b64 v[20:21], v[4:5], v15 +; SDAG-NEXT: v_sub_i32_e32 v12, vcc, 64, v15 +; SDAG-NEXT: v_lshl_b64 v[22:23], v[6:7], v15 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[13:14] +; SDAG-NEXT: v_lshr_b64 v[12:13], v[6:7], v12 +; SDAG-NEXT: v_or_b32_e32 v13, v21, v13 +; SDAG-NEXT: v_or_b32_e32 v12, v20, v12 +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v15 +; SDAG-NEXT: v_cndmask_b32_e64 v14, v19, v13, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v18, v18, v12, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v13, 0, v23, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v12, 0, v22, s[4:5] +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v15 +; SDAG-NEXT: v_cndmask_b32_e64 v15, v14, v5, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v14, v18, v4, s[4:5] +; SDAG-NEXT: v_mov_b32_e32 v18, 0 +; SDAG-NEXT: v_mov_b32_e32 v19, 0 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[8:9], exec, s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB2_11 +; SDAG-NEXT: ; %bb.8: ; %udiv-preheader +; SDAG-NEXT: v_lshr_b64 v[16:17], v[6:7], v38 +; SDAG-NEXT: v_sub_i32_e32 v24, vcc, 64, v38 +; SDAG-NEXT: v_subrev_i32_e32 v51, vcc, 64, v38 +; SDAG-NEXT: v_lshr_b64 v[22:23], v[4:5], v38 +; SDAG-NEXT: v_add_i32_e32 v50, vcc, -1, v37 +; SDAG-NEXT: s_mov_b64 s[10:11], 0 +; SDAG-NEXT: v_mov_b32_e32 v20, 0 +; SDAG-NEXT: v_mov_b32_e32 v21, 0 +; SDAG-NEXT: v_mov_b32_e32 v18, 0 +; SDAG-NEXT: v_mov_b32_e32 v19, 0 +; SDAG-NEXT: v_lshl_b64 v[24:25], v[4:5], v24 +; SDAG-NEXT: v_lshr_b64 v[53:54], v[4:5], v51 +; SDAG-NEXT: v_addc_u32_e32 v51, vcc, -1, v36, vcc +; SDAG-NEXT: v_or_b32_e32 v17, v17, v25 +; SDAG-NEXT: v_or_b32_e32 v16, v16, v24 +; SDAG-NEXT: v_addc_u32_e32 v52, vcc, -1, v10, vcc +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v38 +; SDAG-NEXT: v_cndmask_b32_e64 v17, v54, v17, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v16, v53, v16, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v25, 0, v23, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v24, 0, v22, s[4:5] +; SDAG-NEXT: v_addc_u32_e32 v53, vcc, -1, v11, vcc +; SDAG-NEXT: v_cmp_eq_u32_e32 vcc, 0, v38 +; SDAG-NEXT: v_cndmask_b32_e32 v23, v17, v7, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v22, v16, v6, vcc +; SDAG-NEXT: v_mov_b32_e32 v17, 0 +; SDAG-NEXT: .LBB2_9: ; %udiv-do-while +; SDAG-NEXT: ; =>This Inner Loop Header: Depth=1 +; SDAG-NEXT: v_lshl_b64 v[24:25], v[24:25], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v16, 31, v23 +; SDAG-NEXT: v_lshl_b64 v[22:23], v[22:23], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v54, 31, v15 +; SDAG-NEXT: v_lshl_b64 v[14:15], v[14:15], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v55, 31, v13 +; SDAG-NEXT: v_lshl_b64 v[12:13], v[12:13], 1 +; SDAG-NEXT: v_or_b32_e32 v24, v24, v16 +; SDAG-NEXT: v_or_b32_e32 v22, v22, v54 +; SDAG-NEXT: v_or_b32_e32 v14, v14, v55 +; SDAG-NEXT: v_or_b32_e32 v15, v19, v15 +; SDAG-NEXT: v_or_b32_e32 v13, v21, v13 +; SDAG-NEXT: v_or_b32_e32 v14, v18, v14 +; SDAG-NEXT: v_sub_i32_e32 v16, vcc, v50, v22 +; SDAG-NEXT: v_subb_u32_e32 v16, vcc, v51, v23, vcc +; SDAG-NEXT: v_subb_u32_e32 v16, vcc, v52, v24, vcc +; SDAG-NEXT: v_subb_u32_e32 v16, vcc, v53, v25, vcc +; SDAG-NEXT: v_ashrrev_i32_e32 v21, 31, v16 +; SDAG-NEXT: v_and_b32_e32 v16, 1, v21 +; SDAG-NEXT: v_and_b32_e32 v54, v21, v11 +; SDAG-NEXT: v_and_b32_e32 v55, v21, v10 +; SDAG-NEXT: v_and_b32_e32 v40, v21, v36 +; SDAG-NEXT: v_and_b32_e32 v21, v21, v37 +; SDAG-NEXT: v_sub_i32_e32 v22, vcc, v22, v21 +; SDAG-NEXT: v_subb_u32_e32 v23, vcc, v23, v40, vcc +; SDAG-NEXT: v_subb_u32_e32 v24, vcc, v24, v55, vcc +; SDAG-NEXT: v_subb_u32_e32 v25, vcc, v25, v54, vcc +; SDAG-NEXT: v_add_i32_e32 v38, vcc, -1, v38 +; SDAG-NEXT: v_addc_u32_e32 v39, vcc, -1, v39, vcc +; SDAG-NEXT: v_addc_u32_e32 v48, vcc, -1, v48, vcc +; SDAG-NEXT: v_addc_u32_e32 v49, vcc, -1, v49, vcc +; SDAG-NEXT: v_or_b32_e32 v55, v39, v49 +; SDAG-NEXT: v_or_b32_e32 v54, v38, v48 +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[54:55] +; SDAG-NEXT: s_or_b64 s[10:11], vcc, s[10:11] +; SDAG-NEXT: v_or_b32_e32 v12, v20, v12 +; SDAG-NEXT: v_mov_b32_e32 v21, v17 +; SDAG-NEXT: v_mov_b32_e32 v20, v16 +; SDAG-NEXT: s_andn2_b64 exec, exec, s[10:11] +; SDAG-NEXT: s_cbranch_execnz .LBB2_9 +; SDAG-NEXT: ; %bb.10: ; %Flow +; SDAG-NEXT: s_or_b64 exec, exec, s[10:11] +; SDAG-NEXT: .LBB2_11: ; %Flow11 +; SDAG-NEXT: s_or_b64 exec, exec, s[8:9] +; SDAG-NEXT: v_lshl_b64 v[14:15], v[14:15], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v20, 31, v13 +; SDAG-NEXT: v_lshl_b64 v[12:13], v[12:13], 1 +; SDAG-NEXT: v_or_b32_e32 v14, v14, v20 +; SDAG-NEXT: v_or_b32_e32 v19, v19, v15 +; SDAG-NEXT: v_or_b32_e32 v17, v17, v13 +; SDAG-NEXT: v_or_b32_e32 v18, v18, v14 +; SDAG-NEXT: v_or_b32_e32 v16, v16, v12 +; SDAG-NEXT: .LBB2_12: ; %Flow12 +; SDAG-NEXT: s_or_b64 exec, exec, s[6:7] +; SDAG-NEXT: v_mul_lo_u32 v14, v33, v9 +; SDAG-NEXT: v_mad_u64_u32 v[12:13], s[4:5], v33, v8, 0 +; SDAG-NEXT: v_mul_lo_u32 v24, v27, v8 +; SDAG-NEXT: v_mul_lo_u32 v25, v35, v31 +; SDAG-NEXT: v_mul_lo_u32 v35, v32, v30 +; SDAG-NEXT: v_mad_u64_u32 v[8:9], s[4:5], v31, v33, 0 +; SDAG-NEXT: v_mov_b32_e32 v15, 0 +; SDAG-NEXT: v_mul_lo_u32 v38, v16, v11 +; SDAG-NEXT: v_mad_u64_u32 v[20:21], s[4:5], v16, v10, 0 +; SDAG-NEXT: v_mul_lo_u32 v39, v17, v10 +; SDAG-NEXT: v_mul_lo_u32 v19, v19, v37 +; SDAG-NEXT: v_mul_lo_u32 v48, v18, v36 +; SDAG-NEXT: v_mad_u64_u32 v[10:11], s[4:5], v37, v16, 0 +; SDAG-NEXT: v_add_i32_e32 v13, vcc, v13, v14 +; SDAG-NEXT: v_mov_b32_e32 v14, v9 +; SDAG-NEXT: v_mad_u64_u32 v[22:23], s[4:5], v30, v33, v[14:15] +; SDAG-NEXT: v_sub_i32_e32 v2, vcc, v2, v8 +; SDAG-NEXT: v_add_i32_e64 v14, s[4:5], v21, v38 +; SDAG-NEXT: v_add_i32_e64 v13, s[4:5], v13, v24 +; SDAG-NEXT: v_mov_b32_e32 v24, v23 +; SDAG-NEXT: v_mov_b32_e32 v23, v15 +; SDAG-NEXT: v_mad_u64_u32 v[8:9], s[4:5], v31, v27, v[22:23] +; SDAG-NEXT: v_xor_b32_e32 v33, v2, v28 +; SDAG-NEXT: v_add_i32_e64 v21, s[4:5], v14, v39 +; SDAG-NEXT: v_mov_b32_e32 v14, v11 +; SDAG-NEXT: v_mad_u64_u32 v[22:23], s[4:5], v36, v16, v[14:15] +; SDAG-NEXT: v_mad_u64_u32 v[11:12], s[4:5], v32, v31, v[12:13] +; SDAG-NEXT: v_mov_b32_e32 v2, v9 +; SDAG-NEXT: v_add_i32_e64 v13, s[4:5], v24, v2 +; SDAG-NEXT: v_addc_u32_e64 v14, s[4:5], 0, 0, s[4:5] +; SDAG-NEXT: v_mov_b32_e32 v2, v8 +; SDAG-NEXT: v_subb_u32_e32 v16, vcc, v3, v2, vcc +; SDAG-NEXT: v_mad_u64_u32 v[2:3], s[4:5], v18, v37, v[20:21] +; SDAG-NEXT: v_mov_b32_e32 v18, v23 +; SDAG-NEXT: v_mov_b32_e32 v23, v15 +; SDAG-NEXT: v_mad_u64_u32 v[8:9], s[4:5], v37, v17, v[22:23] +; SDAG-NEXT: v_add_i32_e64 v20, s[4:5], v25, v12 +; SDAG-NEXT: v_mad_u64_u32 v[12:13], s[4:5], v30, v27, v[13:14] +; SDAG-NEXT: v_xor_b32_e32 v16, v16, v29 +; SDAG-NEXT: v_add_i32_e64 v3, s[4:5], v19, v3 +; SDAG-NEXT: v_add_i32_e64 v14, s[4:5], v18, v9 +; SDAG-NEXT: v_addc_u32_e64 v15, s[4:5], 0, 0, s[4:5] +; SDAG-NEXT: v_mov_b32_e32 v18, v8 +; SDAG-NEXT: v_add_i32_e64 v19, s[4:5], v35, v20 +; SDAG-NEXT: v_add_i32_e64 v3, s[4:5], v48, v3 +; SDAG-NEXT: v_mad_u64_u32 v[8:9], s[4:5], v36, v17, v[14:15] +; SDAG-NEXT: v_add_i32_e64 v11, s[4:5], v12, v11 +; SDAG-NEXT: v_addc_u32_e64 v12, s[4:5], v13, v19, s[4:5] +; SDAG-NEXT: v_subb_u32_e32 v0, vcc, v0, v11, vcc +; SDAG-NEXT: v_add_i32_e64 v8, s[4:5], v8, v2 +; SDAG-NEXT: v_addc_u32_e64 v9, s[4:5], v9, v3, s[4:5] +; SDAG-NEXT: v_subb_u32_e32 v1, vcc, v1, v12, vcc +; SDAG-NEXT: v_xor_b32_e32 v2, v0, v28 +; SDAG-NEXT: v_xor_b32_e32 v3, v1, v29 +; SDAG-NEXT: v_sub_i32_e32 v0, vcc, v33, v28 +; SDAG-NEXT: v_subb_u32_e32 v1, vcc, v16, v29, vcc +; SDAG-NEXT: v_subb_u32_e32 v2, vcc, v2, v28, vcc +; SDAG-NEXT: v_subb_u32_e32 v3, vcc, v3, v29, vcc +; SDAG-NEXT: v_sub_i32_e32 v6, vcc, v6, v10 +; SDAG-NEXT: v_subb_u32_e32 v7, vcc, v7, v18, vcc +; SDAG-NEXT: v_xor_b32_e32 v6, v6, v26 +; SDAG-NEXT: v_subb_u32_e32 v4, vcc, v4, v8, vcc +; SDAG-NEXT: v_xor_b32_e32 v7, v7, v34 +; SDAG-NEXT: v_subb_u32_e32 v5, vcc, v5, v9, vcc +; SDAG-NEXT: v_xor_b32_e32 v8, v4, v26 +; SDAG-NEXT: v_xor_b32_e32 v9, v5, v34 +; SDAG-NEXT: v_sub_i32_e32 v4, vcc, v6, v26 +; SDAG-NEXT: v_subb_u32_e32 v5, vcc, v7, v34, vcc +; SDAG-NEXT: v_subb_u32_e32 v6, vcc, v8, v26, vcc +; SDAG-NEXT: v_subb_u32_e32 v7, vcc, v9, v34, vcc +; SDAG-NEXT: buffer_load_dword v40, off, s[0:3], s32 ; 4-byte Folded Reload +; SDAG-NEXT: s_waitcnt vmcnt(0) +; SDAG-NEXT: s_setpc_b64 s[30:31] +; +; GISEL-LABEL: v_srem_v2i128_vv: +; GISEL: ; %bb.0: ; %_udiv-special-cases_udiv-special-cases +; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-NEXT: s_mov_b64 s[8:9], 0 +; GISEL-NEXT: v_ashrrev_i32_e32 v28, 31, v3 +; GISEL-NEXT: v_ashrrev_i32_e32 v20, 31, v11 +; GISEL-NEXT: v_mov_b32_e32 v18, 0x7f +; GISEL-NEXT: v_mov_b32_e32 v19, 0 +; GISEL-NEXT: v_xor_b32_e32 v0, v0, v28 +; GISEL-NEXT: v_xor_b32_e32 v1, v1, v28 +; GISEL-NEXT: v_xor_b32_e32 v2, v2, v28 +; GISEL-NEXT: v_xor_b32_e32 v3, v3, v28 +; GISEL-NEXT: v_xor_b32_e32 v8, v8, v20 +; GISEL-NEXT: v_xor_b32_e32 v9, v9, v20 +; GISEL-NEXT: v_xor_b32_e32 v10, v10, v20 +; GISEL-NEXT: v_xor_b32_e32 v11, v11, v20 +; GISEL-NEXT: v_sub_i32_e32 v16, vcc, v0, v28 +; GISEL-NEXT: v_subb_u32_e32 v17, vcc, v1, v28, vcc +; GISEL-NEXT: v_sub_i32_e64 v30, s[4:5], v8, v20 +; GISEL-NEXT: v_subb_u32_e64 v29, s[4:5], v9, v20, s[4:5] +; GISEL-NEXT: v_subb_u32_e32 v8, vcc, v2, v28, vcc +; GISEL-NEXT: v_subb_u32_e32 v9, vcc, v3, v28, vcc +; GISEL-NEXT: v_subb_u32_e64 v10, vcc, v10, v20, s[4:5] +; GISEL-NEXT: v_subb_u32_e32 v11, vcc, v11, v20, vcc +; GISEL-NEXT: v_ffbh_u32_e32 v20, v29 +; GISEL-NEXT: v_ffbh_u32_e32 v21, v30 +; GISEL-NEXT: v_ffbh_u32_e32 v22, v17 +; GISEL-NEXT: v_ffbh_u32_e32 v23, v16 +; GISEL-NEXT: v_or_b32_e32 v0, v30, v10 +; GISEL-NEXT: v_or_b32_e32 v1, v29, v11 +; GISEL-NEXT: v_or_b32_e32 v2, v16, v8 +; GISEL-NEXT: v_or_b32_e32 v3, v17, v9 +; GISEL-NEXT: v_add_i32_e32 v21, vcc, 32, v21 +; GISEL-NEXT: v_ffbh_u32_e32 v24, v11 +; GISEL-NEXT: v_ffbh_u32_e32 v25, v10 +; GISEL-NEXT: v_add_i32_e32 v23, vcc, 32, v23 +; GISEL-NEXT: v_ffbh_u32_e32 v26, v9 +; GISEL-NEXT: v_ffbh_u32_e32 v27, v8 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[0:1] +; GISEL-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[2:3] +; GISEL-NEXT: v_min_u32_e32 v0, v20, v21 +; GISEL-NEXT: v_add_i32_e64 v1, s[6:7], 32, v25 +; GISEL-NEXT: v_min_u32_e32 v2, v22, v23 +; GISEL-NEXT: v_add_i32_e64 v3, s[6:7], 32, v27 +; GISEL-NEXT: v_add_i32_e64 v0, s[6:7], 64, v0 +; GISEL-NEXT: v_min_u32_e32 v1, v24, v1 +; GISEL-NEXT: v_add_i32_e64 v2, s[6:7], 64, v2 +; GISEL-NEXT: v_min_u32_e32 v3, v26, v3 +; GISEL-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v20, 0, 1, s[4:5] +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[10:11] +; GISEL-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[8:9] +; GISEL-NEXT: v_cndmask_b32_e32 v1, v3, v2, vcc +; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v0, v1 +; GISEL-NEXT: v_subb_u32_e64 v1, s[4:5], 0, 0, vcc +; GISEL-NEXT: v_subb_u32_e64 v2, s[4:5], 0, 0, s[4:5] +; GISEL-NEXT: v_subb_u32_e64 v3, s[4:5], 0, 0, s[4:5] +; GISEL-NEXT: v_cmp_gt_u64_e32 vcc, v[0:1], v[18:19] +; GISEL-NEXT: v_cndmask_b32_e64 v21, 0, 1, vcc +; GISEL-NEXT: v_xor_b32_e32 v18, 0x7f, v0 +; GISEL-NEXT: v_cmp_lt_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: v_cndmask_b32_e64 v22, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v18, v18, v2 +; GISEL-NEXT: v_or_b32_e32 v19, v1, v3 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: v_cndmask_b32_e32 v21, v22, v21, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[18:19] +; GISEL-NEXT: v_cndmask_b32_e64 v18, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v19, v20, v21 +; GISEL-NEXT: v_and_b32_e32 v20, 1, v19 +; GISEL-NEXT: v_or_b32_e32 v18, v19, v18 +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v20 +; GISEL-NEXT: v_cndmask_b32_e64 v31, v16, 0, vcc +; GISEL-NEXT: v_and_b32_e32 v20, 1, v18 +; GISEL-NEXT: v_cndmask_b32_e64 v32, v17, 0, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v18, v8, 0, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v19, v9, 0, vcc +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v20 +; GISEL-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GISEL-NEXT: s_and_saveexec_b64 s[12:13], s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB2_6 +; GISEL-NEXT: ; %bb.1: ; %udiv-bb15 +; GISEL-NEXT: v_add_i32_e32 v31, vcc, 1, v0 +; GISEL-NEXT: v_addc_u32_e64 v32, s[4:5], 0, v1, vcc +; GISEL-NEXT: v_sub_i32_e32 v24, vcc, 0x7f, v0 +; GISEL-NEXT: v_addc_u32_e64 v33, vcc, 0, v2, s[4:5] +; GISEL-NEXT: v_addc_u32_e32 v34, vcc, 0, v3, vcc +; GISEL-NEXT: v_subrev_i32_e64 v20, s[4:5], 64, v24 +; GISEL-NEXT: v_sub_i32_e64 v18, s[4:5], 64, v24 +; GISEL-NEXT: v_lshl_b64 v[0:1], v[16:17], v24 +; GISEL-NEXT: v_lshl_b64 v[2:3], v[8:9], v24 +; GISEL-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GISEL-NEXT: v_lshr_b64 v[18:19], v[16:17], v18 +; GISEL-NEXT: v_lshl_b64 v[22:23], v[16:17], v20 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v24 +; GISEL-NEXT: v_cndmask_b32_e32 v20, 0, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v21, 0, v1, vcc +; GISEL-NEXT: v_or_b32_e32 v0, v18, v2 +; GISEL-NEXT: v_or_b32_e32 v1, v19, v3 +; GISEL-NEXT: v_cndmask_b32_e32 v0, v22, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v1, v23, v1, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v24 +; GISEL-NEXT: v_cndmask_b32_e32 v18, v0, v8, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v19, v1, v9, vcc +; GISEL-NEXT: s_mov_b64 s[10:11], s[8:9] +; GISEL-NEXT: v_mov_b32_e32 v0, s8 +; GISEL-NEXT: v_mov_b32_e32 v1, s9 +; GISEL-NEXT: v_mov_b32_e32 v2, s10 +; GISEL-NEXT: v_mov_b32_e32 v3, s11 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; GISEL-NEXT: s_xor_b64 s[8:9], exec, s[6:7] +; GISEL-NEXT: s_cbranch_execz .LBB2_5 +; GISEL-NEXT: ; %bb.2: ; %udiv-preheader4 +; GISEL-NEXT: v_subrev_i32_e32 v24, vcc, 64, v31 +; GISEL-NEXT: v_sub_i32_e32 v22, vcc, 64, v31 +; GISEL-NEXT: v_lshr_b64 v[0:1], v[8:9], v31 +; GISEL-NEXT: v_lshr_b64 v[2:3], v[16:17], v31 +; GISEL-NEXT: s_mov_b64 s[4:5], 0 +; GISEL-NEXT: v_add_i32_e32 v35, vcc, -1, v30 +; GISEL-NEXT: v_addc_u32_e32 v36, vcc, -1, v29, vcc +; GISEL-NEXT: v_lshl_b64 v[22:23], v[8:9], v22 +; GISEL-NEXT: v_lshr_b64 v[24:25], v[8:9], v24 +; GISEL-NEXT: v_addc_u32_e32 v37, vcc, -1, v10, vcc +; GISEL-NEXT: v_addc_u32_e32 v38, vcc, -1, v11, vcc +; GISEL-NEXT: s_mov_b64 s[6:7], s[4:5] +; GISEL-NEXT: v_or_b32_e32 v2, v2, v22 +; GISEL-NEXT: v_or_b32_e32 v3, v3, v23 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v31 +; GISEL-NEXT: v_cndmask_b32_e32 v2, v24, v2, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v3, v25, v3, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v26, 0, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v27, 0, v1, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v31 +; GISEL-NEXT: v_cndmask_b32_e32 v24, v2, v16, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v25, v3, v17, vcc +; GISEL-NEXT: v_mov_b32_e32 v23, 0 +; GISEL-NEXT: v_mov_b32_e32 v0, s4 +; GISEL-NEXT: v_mov_b32_e32 v1, s5 +; GISEL-NEXT: v_mov_b32_e32 v2, s6 +; GISEL-NEXT: v_mov_b32_e32 v3, s7 +; GISEL-NEXT: .LBB2_3: ; %udiv-do-while3 +; GISEL-NEXT: ; =>This Inner Loop Header: Depth=1 +; GISEL-NEXT: v_lshl_b64 v[2:3], v[20:21], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v22, 31, v21 +; GISEL-NEXT: v_lshl_b64 v[48:49], v[24:25], 1 +; GISEL-NEXT: v_lshl_b64 v[26:27], v[26:27], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v24, 31, v25 +; GISEL-NEXT: v_lshrrev_b32_e32 v25, 31, v19 +; GISEL-NEXT: v_lshl_b64 v[18:19], v[18:19], 1 +; GISEL-NEXT: v_add_i32_e32 v31, vcc, -1, v31 +; GISEL-NEXT: v_addc_u32_e32 v32, vcc, -1, v32, vcc +; GISEL-NEXT: v_or_b32_e32 v20, v0, v2 +; GISEL-NEXT: v_or_b32_e32 v21, v1, v3 +; GISEL-NEXT: v_or_b32_e32 v2, v26, v24 +; GISEL-NEXT: v_or_b32_e32 v3, v48, v25 +; GISEL-NEXT: v_or_b32_e32 v18, v18, v22 +; GISEL-NEXT: v_addc_u32_e32 v33, vcc, -1, v33, vcc +; GISEL-NEXT: v_addc_u32_e32 v34, vcc, -1, v34, vcc +; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v35, v3 +; GISEL-NEXT: v_subb_u32_e32 v0, vcc, v36, v49, vcc +; GISEL-NEXT: v_or_b32_e32 v0, v31, v33 +; GISEL-NEXT: v_or_b32_e32 v1, v32, v34 +; GISEL-NEXT: v_subb_u32_e32 v22, vcc, v37, v2, vcc +; GISEL-NEXT: v_subb_u32_e32 v22, vcc, v38, v27, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[0:1] +; GISEL-NEXT: v_ashrrev_i32_e32 v0, 31, v22 +; GISEL-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GISEL-NEXT: v_and_b32_e32 v22, 1, v0 +; GISEL-NEXT: v_and_b32_e32 v1, v0, v30 +; GISEL-NEXT: v_and_b32_e32 v25, v0, v29 +; GISEL-NEXT: v_and_b32_e32 v26, v0, v10 +; GISEL-NEXT: v_and_b32_e32 v0, v0, v11 +; GISEL-NEXT: v_sub_i32_e32 v24, vcc, v3, v1 +; GISEL-NEXT: v_subb_u32_e32 v25, vcc, v49, v25, vcc +; GISEL-NEXT: v_subb_u32_e32 v26, vcc, v2, v26, vcc +; GISEL-NEXT: v_subb_u32_e32 v27, vcc, v27, v0, vcc +; GISEL-NEXT: v_mov_b32_e32 v0, v22 +; GISEL-NEXT: v_mov_b32_e32 v1, v23 +; GISEL-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GISEL-NEXT: s_cbranch_execnz .LBB2_3 +; GISEL-NEXT: ; %bb.4: ; %Flow13 +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: .LBB2_5: ; %Flow14 +; GISEL-NEXT: s_or_b64 exec, exec, s[8:9] +; GISEL-NEXT: v_lshl_b64 v[2:3], v[20:21], 1 +; GISEL-NEXT: v_lshl_b64 v[18:19], v[18:19], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v20, 31, v21 +; GISEL-NEXT: v_or_b32_e32 v18, v18, v20 +; GISEL-NEXT: v_or_b32_e32 v31, v0, v2 +; GISEL-NEXT: v_or_b32_e32 v32, v1, v3 +; GISEL-NEXT: .LBB2_6: ; %Flow16 +; GISEL-NEXT: s_or_b64 exec, exec, s[12:13] +; GISEL-NEXT: s_mov_b64 s[8:9], 0 +; GISEL-NEXT: v_ashrrev_i32_e32 v33, 31, v7 +; GISEL-NEXT: v_ashrrev_i32_e32 v0, 31, v15 +; GISEL-NEXT: v_mov_b32_e32 v2, 0x7f +; GISEL-NEXT: v_mov_b32_e32 v3, 0 +; GISEL-NEXT: v_xor_b32_e32 v1, v4, v33 +; GISEL-NEXT: v_xor_b32_e32 v4, v5, v33 +; GISEL-NEXT: v_xor_b32_e32 v5, v6, v33 +; GISEL-NEXT: v_xor_b32_e32 v7, v7, v33 +; GISEL-NEXT: v_xor_b32_e32 v6, v12, v0 +; GISEL-NEXT: v_xor_b32_e32 v20, v13, v0 +; GISEL-NEXT: v_xor_b32_e32 v14, v14, v0 +; GISEL-NEXT: v_xor_b32_e32 v15, v15, v0 +; GISEL-NEXT: v_sub_i32_e32 v12, vcc, v1, v33 +; GISEL-NEXT: v_subb_u32_e32 v13, vcc, v4, v33, vcc +; GISEL-NEXT: v_sub_i32_e64 v35, s[4:5], v6, v0 +; GISEL-NEXT: v_subb_u32_e64 v34, s[4:5], v20, v0, s[4:5] +; GISEL-NEXT: v_subb_u32_e32 v6, vcc, v5, v33, vcc +; GISEL-NEXT: v_subb_u32_e32 v7, vcc, v7, v33, vcc +; GISEL-NEXT: v_subb_u32_e64 v4, vcc, v14, v0, s[4:5] +; GISEL-NEXT: v_subb_u32_e32 v5, vcc, v15, v0, vcc +; GISEL-NEXT: v_ffbh_u32_e32 v20, v34 +; GISEL-NEXT: v_ffbh_u32_e32 v21, v35 +; GISEL-NEXT: v_ffbh_u32_e32 v22, v13 +; GISEL-NEXT: v_ffbh_u32_e32 v23, v12 +; GISEL-NEXT: v_or_b32_e32 v0, v35, v4 +; GISEL-NEXT: v_or_b32_e32 v1, v34, v5 +; GISEL-NEXT: v_or_b32_e32 v14, v12, v6 +; GISEL-NEXT: v_or_b32_e32 v15, v13, v7 +; GISEL-NEXT: v_add_i32_e32 v21, vcc, 32, v21 +; GISEL-NEXT: v_ffbh_u32_e32 v24, v5 +; GISEL-NEXT: v_ffbh_u32_e32 v25, v4 +; GISEL-NEXT: v_add_i32_e32 v23, vcc, 32, v23 +; GISEL-NEXT: v_ffbh_u32_e32 v26, v7 +; GISEL-NEXT: v_ffbh_u32_e32 v27, v6 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[0:1] +; GISEL-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[14:15] +; GISEL-NEXT: v_min_u32_e32 v0, v20, v21 +; GISEL-NEXT: v_add_i32_e64 v1, s[6:7], 32, v25 +; GISEL-NEXT: v_min_u32_e32 v14, v22, v23 +; GISEL-NEXT: v_add_i32_e64 v15, s[6:7], 32, v27 +; GISEL-NEXT: v_add_i32_e64 v0, s[6:7], 64, v0 +; GISEL-NEXT: v_min_u32_e32 v1, v24, v1 +; GISEL-NEXT: v_add_i32_e64 v14, s[6:7], 64, v14 +; GISEL-NEXT: v_min_u32_e32 v15, v26, v15 +; GISEL-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v20, 0, 1, s[4:5] +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[4:5] +; GISEL-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[6:7] +; GISEL-NEXT: v_cndmask_b32_e32 v1, v15, v14, vcc +; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v0, v1 +; GISEL-NEXT: v_subb_u32_e64 v1, s[4:5], 0, 0, vcc +; GISEL-NEXT: v_subb_u32_e64 v14, s[4:5], 0, 0, s[4:5] +; GISEL-NEXT: v_subb_u32_e64 v15, s[4:5], 0, 0, s[4:5] +; GISEL-NEXT: v_cmp_gt_u64_e32 vcc, v[0:1], v[2:3] +; GISEL-NEXT: v_cndmask_b32_e64 v21, 0, 1, vcc +; GISEL-NEXT: v_xor_b32_e32 v2, 0x7f, v0 +; GISEL-NEXT: v_cmp_lt_u64_e32 vcc, 0, v[14:15] +; GISEL-NEXT: v_cndmask_b32_e64 v22, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v2, v2, v14 +; GISEL-NEXT: v_or_b32_e32 v3, v1, v15 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[14:15] +; GISEL-NEXT: v_cndmask_b32_e32 v21, v22, v21, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: v_cndmask_b32_e64 v2, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v3, v20, v21 +; GISEL-NEXT: v_and_b32_e32 v20, 1, v3 +; GISEL-NEXT: v_or_b32_e32 v2, v3, v2 +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v20 +; GISEL-NEXT: v_cndmask_b32_e64 v20, v12, 0, vcc +; GISEL-NEXT: v_and_b32_e32 v22, 1, v2 +; GISEL-NEXT: v_cndmask_b32_e64 v21, v13, 0, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v2, v6, 0, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v3, v7, 0, vcc +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v22 +; GISEL-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GISEL-NEXT: s_and_saveexec_b64 s[12:13], s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB2_12 +; GISEL-NEXT: ; %bb.7: ; %udiv-bb1 +; GISEL-NEXT: v_add_i32_e32 v36, vcc, 1, v0 +; GISEL-NEXT: v_addc_u32_e64 v37, s[4:5], 0, v1, vcc +; GISEL-NEXT: v_sub_i32_e32 v24, vcc, 0x7f, v0 +; GISEL-NEXT: v_addc_u32_e64 v38, vcc, 0, v14, s[4:5] +; GISEL-NEXT: v_addc_u32_e32 v39, vcc, 0, v15, vcc +; GISEL-NEXT: v_subrev_i32_e64 v20, s[4:5], 64, v24 +; GISEL-NEXT: v_sub_i32_e64 v14, s[4:5], 64, v24 +; GISEL-NEXT: v_lshl_b64 v[0:1], v[12:13], v24 +; GISEL-NEXT: v_lshl_b64 v[2:3], v[6:7], v24 +; GISEL-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GISEL-NEXT: v_lshr_b64 v[14:15], v[12:13], v14 +; GISEL-NEXT: v_lshl_b64 v[22:23], v[12:13], v20 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v24 +; GISEL-NEXT: v_cndmask_b32_e32 v20, 0, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v21, 0, v1, vcc +; GISEL-NEXT: v_or_b32_e32 v0, v14, v2 +; GISEL-NEXT: v_or_b32_e32 v1, v15, v3 +; GISEL-NEXT: v_cndmask_b32_e32 v0, v22, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v1, v23, v1, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v24 +; GISEL-NEXT: v_cndmask_b32_e32 v14, v0, v6, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v15, v1, v7, vcc +; GISEL-NEXT: s_mov_b64 s[10:11], s[8:9] +; GISEL-NEXT: v_mov_b32_e32 v0, s8 +; GISEL-NEXT: v_mov_b32_e32 v1, s9 +; GISEL-NEXT: v_mov_b32_e32 v2, s10 +; GISEL-NEXT: v_mov_b32_e32 v3, s11 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; GISEL-NEXT: s_xor_b64 s[8:9], exec, s[6:7] +; GISEL-NEXT: s_cbranch_execz .LBB2_11 +; GISEL-NEXT: ; %bb.8: ; %udiv-preheader +; GISEL-NEXT: v_subrev_i32_e32 v24, vcc, 64, v36 +; GISEL-NEXT: v_sub_i32_e32 v22, vcc, 64, v36 +; GISEL-NEXT: v_lshr_b64 v[0:1], v[6:7], v36 +; GISEL-NEXT: v_lshr_b64 v[2:3], v[12:13], v36 +; GISEL-NEXT: s_mov_b64 s[4:5], 0 +; GISEL-NEXT: v_add_i32_e32 v48, vcc, -1, v35 +; GISEL-NEXT: v_addc_u32_e32 v49, vcc, -1, v34, vcc +; GISEL-NEXT: v_lshl_b64 v[22:23], v[6:7], v22 +; GISEL-NEXT: v_lshr_b64 v[24:25], v[6:7], v24 +; GISEL-NEXT: v_addc_u32_e32 v50, vcc, -1, v4, vcc +; GISEL-NEXT: v_addc_u32_e32 v51, vcc, -1, v5, vcc +; GISEL-NEXT: s_mov_b64 s[6:7], s[4:5] +; GISEL-NEXT: v_or_b32_e32 v2, v2, v22 +; GISEL-NEXT: v_or_b32_e32 v3, v3, v23 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v36 +; GISEL-NEXT: v_cndmask_b32_e32 v2, v24, v2, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v3, v25, v3, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v26, 0, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v27, 0, v1, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v36 +; GISEL-NEXT: v_cndmask_b32_e32 v24, v2, v12, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v25, v3, v13, vcc +; GISEL-NEXT: v_mov_b32_e32 v23, 0 +; GISEL-NEXT: v_mov_b32_e32 v0, s4 +; GISEL-NEXT: v_mov_b32_e32 v1, s5 +; GISEL-NEXT: v_mov_b32_e32 v2, s6 +; GISEL-NEXT: v_mov_b32_e32 v3, s7 +; GISEL-NEXT: .LBB2_9: ; %udiv-do-while +; GISEL-NEXT: ; =>This Inner Loop Header: Depth=1 +; GISEL-NEXT: v_lshl_b64 v[2:3], v[20:21], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v22, 31, v21 +; GISEL-NEXT: v_lshl_b64 v[52:53], v[24:25], 1 +; GISEL-NEXT: v_lshl_b64 v[26:27], v[26:27], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v24, 31, v25 +; GISEL-NEXT: v_lshrrev_b32_e32 v25, 31, v15 +; GISEL-NEXT: v_lshl_b64 v[14:15], v[14:15], 1 +; GISEL-NEXT: v_add_i32_e32 v36, vcc, -1, v36 +; GISEL-NEXT: v_addc_u32_e32 v37, vcc, -1, v37, vcc +; GISEL-NEXT: v_or_b32_e32 v20, v0, v2 +; GISEL-NEXT: v_or_b32_e32 v21, v1, v3 +; GISEL-NEXT: v_or_b32_e32 v2, v26, v24 +; GISEL-NEXT: v_or_b32_e32 v3, v52, v25 +; GISEL-NEXT: v_or_b32_e32 v14, v14, v22 +; GISEL-NEXT: v_addc_u32_e32 v38, vcc, -1, v38, vcc +; GISEL-NEXT: v_addc_u32_e32 v39, vcc, -1, v39, vcc +; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v48, v3 +; GISEL-NEXT: v_subb_u32_e32 v0, vcc, v49, v53, vcc +; GISEL-NEXT: v_or_b32_e32 v0, v36, v38 +; GISEL-NEXT: v_or_b32_e32 v1, v37, v39 +; GISEL-NEXT: v_subb_u32_e32 v22, vcc, v50, v2, vcc +; GISEL-NEXT: v_subb_u32_e32 v22, vcc, v51, v27, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[0:1] +; GISEL-NEXT: v_ashrrev_i32_e32 v0, 31, v22 +; GISEL-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GISEL-NEXT: v_and_b32_e32 v22, 1, v0 +; GISEL-NEXT: v_and_b32_e32 v1, v0, v35 +; GISEL-NEXT: v_and_b32_e32 v25, v0, v34 +; GISEL-NEXT: v_and_b32_e32 v26, v0, v4 +; GISEL-NEXT: v_and_b32_e32 v52, v0, v5 +; GISEL-NEXT: v_sub_i32_e32 v24, vcc, v3, v1 +; GISEL-NEXT: v_subb_u32_e32 v25, vcc, v53, v25, vcc +; GISEL-NEXT: v_mov_b32_e32 v0, v22 +; GISEL-NEXT: v_mov_b32_e32 v1, v23 +; GISEL-NEXT: v_subb_u32_e32 v26, vcc, v2, v26, vcc +; GISEL-NEXT: v_subb_u32_e32 v27, vcc, v27, v52, vcc +; GISEL-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GISEL-NEXT: s_cbranch_execnz .LBB2_9 +; GISEL-NEXT: ; %bb.10: ; %Flow +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: .LBB2_11: ; %Flow11 +; GISEL-NEXT: s_or_b64 exec, exec, s[8:9] +; GISEL-NEXT: v_lshl_b64 v[22:23], v[20:21], 1 +; GISEL-NEXT: v_lshl_b64 v[2:3], v[14:15], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v14, 31, v21 +; GISEL-NEXT: v_or_b32_e32 v2, v2, v14 +; GISEL-NEXT: v_or_b32_e32 v20, v0, v22 +; GISEL-NEXT: v_or_b32_e32 v21, v1, v23 +; GISEL-NEXT: .LBB2_12: ; %Flow12 +; GISEL-NEXT: s_or_b64 exec, exec, s[12:13] +; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v30, v31, 0 +; GISEL-NEXT: v_mad_u64_u32 v[14:15], s[4:5], v30, v18, 0 +; GISEL-NEXT: v_mul_lo_u32 v24, v30, v19 +; GISEL-NEXT: v_mul_lo_u32 v25, v29, v18 +; GISEL-NEXT: v_mad_u64_u32 v[18:19], s[4:5], v35, v20, 0 +; GISEL-NEXT: v_mad_u64_u32 v[22:23], s[4:5], v35, v2, 0 +; GISEL-NEXT: v_mul_lo_u32 v26, v35, v3 +; GISEL-NEXT: v_mul_lo_u32 v27, v34, v2 +; GISEL-NEXT: v_mad_u64_u32 v[2:3], s[4:5], v29, v32, v[14:15] +; GISEL-NEXT: v_mad_u64_u32 v[14:15], s[4:5], v34, v21, v[22:23] +; GISEL-NEXT: v_mov_b32_e32 v22, v19 +; GISEL-NEXT: v_mad_u64_u32 v[2:3], s[4:5], v10, v31, v[2:3] +; GISEL-NEXT: v_mad_u64_u32 v[14:15], s[4:5], v4, v20, v[14:15] +; GISEL-NEXT: v_mad_u64_u32 v[1:2], vcc, v30, v32, v[1:2] +; GISEL-NEXT: v_mov_b32_e32 v23, v14 +; GISEL-NEXT: v_mad_u64_u32 v[22:23], s[4:5], v35, v21, v[22:23] +; GISEL-NEXT: v_mad_u64_u32 v[1:2], s[6:7], v29, v31, v[1:2] +; GISEL-NEXT: v_addc_u32_e64 v3, s[6:7], v3, v24, s[6:7] +; GISEL-NEXT: v_mad_u64_u32 v[22:23], s[6:7], v34, v20, v[22:23] +; GISEL-NEXT: v_addc_u32_e64 v14, s[6:7], v15, v26, s[6:7] +; GISEL-NEXT: v_addc_u32_e32 v3, vcc, v3, v25, vcc +; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v16, v0 +; GISEL-NEXT: v_subb_u32_e32 v1, vcc, v17, v1, vcc +; GISEL-NEXT: v_xor_b32_e32 v15, v0, v28 +; GISEL-NEXT: v_addc_u32_e64 v0, s[4:5], v14, v27, s[4:5] +; GISEL-NEXT: v_sub_i32_e64 v12, s[4:5], v12, v18 +; GISEL-NEXT: v_subb_u32_e64 v14, s[4:5], v13, v22, s[4:5] +; GISEL-NEXT: v_xor_b32_e32 v16, v12, v33 +; GISEL-NEXT: v_mad_u64_u32 v[12:13], s[6:7], v10, v32, v[3:4] +; GISEL-NEXT: v_xor_b32_e32 v1, v1, v28 +; GISEL-NEXT: v_mad_u64_u32 v[3:4], s[6:7], v4, v21, v[0:1] +; GISEL-NEXT: v_xor_b32_e32 v14, v14, v33 +; GISEL-NEXT: v_mad_u64_u32 v[10:11], s[6:7], v11, v31, v[12:13] +; GISEL-NEXT: v_sub_i32_e64 v0, s[6:7], v15, v28 +; GISEL-NEXT: v_subb_u32_e64 v1, s[6:7], v1, v28, s[6:7] +; GISEL-NEXT: v_mad_u64_u32 v[3:4], s[8:9], v5, v20, v[3:4] +; GISEL-NEXT: v_sub_i32_e64 v4, s[8:9], v16, v33 +; GISEL-NEXT: v_subb_u32_e64 v5, s[8:9], v14, v33, s[8:9] +; GISEL-NEXT: v_subb_u32_e32 v2, vcc, v8, v2, vcc +; GISEL-NEXT: v_subb_u32_e32 v8, vcc, v9, v10, vcc +; GISEL-NEXT: v_xor_b32_e32 v2, v2, v28 +; GISEL-NEXT: v_subb_u32_e64 v6, vcc, v6, v23, s[4:5] +; GISEL-NEXT: v_subb_u32_e32 v3, vcc, v7, v3, vcc +; GISEL-NEXT: v_xor_b32_e32 v6, v6, v33 +; GISEL-NEXT: v_xor_b32_e32 v7, v8, v28 +; GISEL-NEXT: v_xor_b32_e32 v8, v3, v33 +; GISEL-NEXT: v_subb_u32_e64 v2, vcc, v2, v28, s[6:7] +; GISEL-NEXT: v_subb_u32_e32 v3, vcc, v7, v28, vcc +; GISEL-NEXT: v_subb_u32_e64 v6, vcc, v6, v33, s[8:9] +; GISEL-NEXT: v_subb_u32_e32 v7, vcc, v8, v33, vcc +; GISEL-NEXT: s_setpc_b64 s[30:31] %shl = srem <2 x i128> %lhs, %rhs ret <2 x i128> %shl } define <2 x i128> @v_urem_v2i128_vv(<2 x i128> %lhs, <2 x i128> %rhs) { +; SDAG-LABEL: v_urem_v2i128_vv: +; SDAG: ; %bb.0: ; %_udiv-special-cases_udiv-special-cases +; SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-NEXT: v_or_b32_e32 v17, v9, v11 +; SDAG-NEXT: v_or_b32_e32 v16, v8, v10 +; SDAG-NEXT: v_or_b32_e32 v19, v1, v3 +; SDAG-NEXT: v_or_b32_e32 v18, v0, v2 +; SDAG-NEXT: v_ffbh_u32_e32 v20, v10 +; SDAG-NEXT: v_ffbh_u32_e32 v21, v11 +; SDAG-NEXT: v_ffbh_u32_e32 v22, v8 +; SDAG-NEXT: v_ffbh_u32_e32 v23, v9 +; SDAG-NEXT: v_ffbh_u32_e32 v24, v2 +; SDAG-NEXT: v_ffbh_u32_e32 v25, v3 +; SDAG-NEXT: v_ffbh_u32_e32 v26, v0 +; SDAG-NEXT: v_ffbh_u32_e32 v27, v1 +; SDAG-NEXT: v_mov_b32_e32 v28, 0 +; SDAG-NEXT: s_mov_b64 s[8:9], 0x7f +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[16:17] +; SDAG-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[18:19] +; SDAG-NEXT: v_add_i32_e64 v16, s[6:7], 32, v20 +; SDAG-NEXT: v_add_i32_e64 v17, s[6:7], 32, v22 +; SDAG-NEXT: v_add_i32_e64 v18, s[6:7], 32, v24 +; SDAG-NEXT: v_add_i32_e64 v19, s[6:7], 32, v26 +; SDAG-NEXT: s_or_b64 s[6:7], vcc, s[4:5] +; SDAG-NEXT: v_min_u32_e32 v16, v16, v21 +; SDAG-NEXT: v_min_u32_e32 v17, v17, v23 +; SDAG-NEXT: v_min_u32_e32 v18, v18, v25 +; SDAG-NEXT: v_min_u32_e32 v19, v19, v27 +; SDAG-NEXT: v_add_i32_e32 v17, vcc, 64, v17 +; SDAG-NEXT: v_addc_u32_e64 v20, s[4:5], 0, 0, vcc +; SDAG-NEXT: v_add_i32_e32 v19, vcc, 64, v19 +; SDAG-NEXT: v_addc_u32_e64 v21, s[4:5], 0, 0, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[10:11] +; SDAG-NEXT: v_cndmask_b32_e64 v20, v20, 0, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v16, v17, v16, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[2:3] +; SDAG-NEXT: v_cndmask_b32_e64 v17, v21, 0, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v18, v19, v18, vcc +; SDAG-NEXT: v_sub_i32_e32 v16, vcc, v16, v18 +; SDAG-NEXT: v_subb_u32_e32 v17, vcc, v20, v17, vcc +; SDAG-NEXT: v_xor_b32_e32 v18, 0x7f, v16 +; SDAG-NEXT: v_subbrev_u32_e32 v20, vcc, 0, v28, vcc +; SDAG-NEXT: v_cmp_lt_u64_e64 s[4:5], s[8:9], v[16:17] +; SDAG-NEXT: v_cndmask_b32_e64 v22, 0, 1, s[4:5] +; SDAG-NEXT: v_subbrev_u32_e32 v21, vcc, 0, v28, vcc +; SDAG-NEXT: v_or_b32_e32 v18, v18, v20 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[20:21] +; SDAG-NEXT: v_cndmask_b32_e64 v23, 0, 1, vcc +; SDAG-NEXT: v_or_b32_e32 v19, v17, v21 +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[20:21] +; SDAG-NEXT: v_cndmask_b32_e32 v22, v23, v22, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[18:19] +; SDAG-NEXT: v_and_b32_e32 v18, 1, v22 +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 1, v18 +; SDAG-NEXT: s_or_b64 s[4:5], s[6:7], s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v33, v3, 0, s[4:5] +; SDAG-NEXT: s_xor_b64 s[6:7], s[4:5], -1 +; SDAG-NEXT: v_cndmask_b32_e64 v31, v2, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v30, v1, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v32, v0, 0, s[4:5] +; SDAG-NEXT: s_and_b64 s[4:5], s[6:7], vcc +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB3_6 +; SDAG-NEXT: ; %bb.1: ; %udiv-bb15 +; SDAG-NEXT: v_add_i32_e32 v30, vcc, 1, v16 +; SDAG-NEXT: v_sub_i32_e64 v22, s[4:5], 63, v16 +; SDAG-NEXT: v_mov_b32_e32 v18, 0 +; SDAG-NEXT: v_mov_b32_e32 v19, 0 +; SDAG-NEXT: v_addc_u32_e32 v31, vcc, 0, v17, vcc +; SDAG-NEXT: v_lshl_b64 v[22:23], v[0:1], v22 +; SDAG-NEXT: v_addc_u32_e32 v32, vcc, 0, v20, vcc +; SDAG-NEXT: v_addc_u32_e32 v33, vcc, 0, v21, vcc +; SDAG-NEXT: v_or_b32_e32 v20, v30, v32 +; SDAG-NEXT: v_sub_i32_e32 v26, vcc, 0x7f, v16 +; SDAG-NEXT: v_or_b32_e32 v21, v31, v33 +; SDAG-NEXT: v_lshl_b64 v[16:17], v[2:3], v26 +; SDAG-NEXT: v_sub_i32_e32 v27, vcc, 64, v26 +; SDAG-NEXT: v_lshl_b64 v[24:25], v[0:1], v26 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[20:21] +; SDAG-NEXT: v_lshr_b64 v[20:21], v[0:1], v27 +; SDAG-NEXT: v_or_b32_e32 v17, v17, v21 +; SDAG-NEXT: v_or_b32_e32 v16, v16, v20 +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v26 +; SDAG-NEXT: v_cndmask_b32_e64 v17, v23, v17, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v16, v22, v16, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v23, 0, v25, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v22, 0, v24, s[4:5] +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v26 +; SDAG-NEXT: v_cndmask_b32_e64 v17, v17, v3, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v16, v16, v2, s[4:5] +; SDAG-NEXT: v_mov_b32_e32 v20, 0 +; SDAG-NEXT: v_mov_b32_e32 v21, 0 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[8:9], exec, s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB3_5 +; SDAG-NEXT: ; %bb.2: ; %udiv-preheader4 +; SDAG-NEXT: v_lshr_b64 v[18:19], v[0:1], v30 +; SDAG-NEXT: v_sub_i32_e32 v28, vcc, 64, v30 +; SDAG-NEXT: v_subrev_i32_e32 v35, vcc, 64, v30 +; SDAG-NEXT: v_lshr_b64 v[26:27], v[2:3], v30 +; SDAG-NEXT: v_add_i32_e32 v34, vcc, -1, v8 +; SDAG-NEXT: s_mov_b64 s[10:11], 0 +; SDAG-NEXT: v_mov_b32_e32 v24, 0 +; SDAG-NEXT: v_mov_b32_e32 v25, 0 +; SDAG-NEXT: v_mov_b32_e32 v20, 0 +; SDAG-NEXT: v_mov_b32_e32 v21, 0 +; SDAG-NEXT: v_lshl_b64 v[28:29], v[2:3], v28 +; SDAG-NEXT: v_lshr_b64 v[37:38], v[2:3], v35 +; SDAG-NEXT: v_addc_u32_e32 v35, vcc, -1, v9, vcc +; SDAG-NEXT: v_or_b32_e32 v19, v19, v29 +; SDAG-NEXT: v_or_b32_e32 v18, v18, v28 +; SDAG-NEXT: v_addc_u32_e32 v36, vcc, -1, v10, vcc +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v30 +; SDAG-NEXT: v_cndmask_b32_e64 v19, v38, v19, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v18, v37, v18, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v29, 0, v27, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v28, 0, v26, s[4:5] +; SDAG-NEXT: v_addc_u32_e32 v37, vcc, -1, v11, vcc +; SDAG-NEXT: v_cmp_eq_u32_e32 vcc, 0, v30 +; SDAG-NEXT: v_cndmask_b32_e32 v27, v19, v1, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v26, v18, v0, vcc +; SDAG-NEXT: v_mov_b32_e32 v19, 0 +; SDAG-NEXT: .LBB3_3: ; %udiv-do-while3 +; SDAG-NEXT: ; =>This Inner Loop Header: Depth=1 +; SDAG-NEXT: v_lshl_b64 v[28:29], v[28:29], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v18, 31, v27 +; SDAG-NEXT: v_lshl_b64 v[26:27], v[26:27], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v38, 31, v17 +; SDAG-NEXT: v_lshl_b64 v[16:17], v[16:17], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v39, 31, v23 +; SDAG-NEXT: v_lshl_b64 v[22:23], v[22:23], 1 +; SDAG-NEXT: v_or_b32_e32 v28, v28, v18 +; SDAG-NEXT: v_or_b32_e32 v26, v26, v38 +; SDAG-NEXT: v_or_b32_e32 v16, v16, v39 +; SDAG-NEXT: v_or_b32_e32 v17, v21, v17 +; SDAG-NEXT: v_sub_i32_e32 v18, vcc, v34, v26 +; SDAG-NEXT: v_or_b32_e32 v16, v20, v16 +; SDAG-NEXT: v_subb_u32_e32 v18, vcc, v35, v27, vcc +; SDAG-NEXT: v_subb_u32_e32 v18, vcc, v36, v28, vcc +; SDAG-NEXT: v_subb_u32_e32 v18, vcc, v37, v29, vcc +; SDAG-NEXT: v_ashrrev_i32_e32 v38, 31, v18 +; SDAG-NEXT: v_and_b32_e32 v39, v38, v8 +; SDAG-NEXT: v_and_b32_e32 v48, v38, v9 +; SDAG-NEXT: v_and_b32_e32 v49, v38, v10 +; SDAG-NEXT: v_and_b32_e32 v18, 1, v38 +; SDAG-NEXT: v_and_b32_e32 v38, v38, v11 +; SDAG-NEXT: v_sub_i32_e32 v26, vcc, v26, v39 +; SDAG-NEXT: v_subb_u32_e32 v27, vcc, v27, v48, vcc +; SDAG-NEXT: v_subb_u32_e32 v28, vcc, v28, v49, vcc +; SDAG-NEXT: v_subb_u32_e32 v29, vcc, v29, v38, vcc +; SDAG-NEXT: v_add_i32_e32 v30, vcc, -1, v30 +; SDAG-NEXT: v_addc_u32_e32 v31, vcc, -1, v31, vcc +; SDAG-NEXT: v_addc_u32_e32 v32, vcc, -1, v32, vcc +; SDAG-NEXT: v_addc_u32_e32 v33, vcc, -1, v33, vcc +; SDAG-NEXT: v_or_b32_e32 v38, v30, v32 +; SDAG-NEXT: v_or_b32_e32 v39, v31, v33 +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[38:39] +; SDAG-NEXT: v_or_b32_e32 v23, v25, v23 +; SDAG-NEXT: s_or_b64 s[10:11], vcc, s[10:11] +; SDAG-NEXT: v_or_b32_e32 v22, v24, v22 +; SDAG-NEXT: v_mov_b32_e32 v25, v19 +; SDAG-NEXT: v_mov_b32_e32 v24, v18 +; SDAG-NEXT: s_andn2_b64 exec, exec, s[10:11] +; SDAG-NEXT: s_cbranch_execnz .LBB3_3 +; SDAG-NEXT: ; %bb.4: ; %Flow13 +; SDAG-NEXT: s_or_b64 exec, exec, s[10:11] +; SDAG-NEXT: .LBB3_5: ; %Flow14 +; SDAG-NEXT: s_or_b64 exec, exec, s[8:9] +; SDAG-NEXT: v_lshl_b64 v[16:17], v[16:17], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v24, 31, v23 +; SDAG-NEXT: v_lshl_b64 v[22:23], v[22:23], 1 +; SDAG-NEXT: v_or_b32_e32 v16, v16, v24 +; SDAG-NEXT: v_or_b32_e32 v33, v21, v17 +; SDAG-NEXT: v_or_b32_e32 v30, v19, v23 +; SDAG-NEXT: v_or_b32_e32 v31, v20, v16 +; SDAG-NEXT: v_or_b32_e32 v32, v18, v22 +; SDAG-NEXT: .LBB3_6: ; %Flow16 +; SDAG-NEXT: s_or_b64 exec, exec, s[6:7] +; SDAG-NEXT: v_or_b32_e32 v17, v13, v15 +; SDAG-NEXT: v_or_b32_e32 v16, v12, v14 +; SDAG-NEXT: v_or_b32_e32 v19, v5, v7 +; SDAG-NEXT: v_or_b32_e32 v18, v4, v6 +; SDAG-NEXT: v_ffbh_u32_e32 v20, v14 +; SDAG-NEXT: v_ffbh_u32_e32 v21, v15 +; SDAG-NEXT: v_ffbh_u32_e32 v22, v12 +; SDAG-NEXT: v_ffbh_u32_e32 v23, v13 +; SDAG-NEXT: v_ffbh_u32_e32 v24, v6 +; SDAG-NEXT: v_ffbh_u32_e32 v25, v7 +; SDAG-NEXT: v_ffbh_u32_e32 v26, v4 +; SDAG-NEXT: v_ffbh_u32_e32 v27, v5 +; SDAG-NEXT: v_mov_b32_e32 v28, 0 +; SDAG-NEXT: s_mov_b64 s[8:9], 0x7f +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[16:17] +; SDAG-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[18:19] +; SDAG-NEXT: v_add_i32_e64 v16, s[6:7], 32, v20 +; SDAG-NEXT: v_add_i32_e64 v17, s[6:7], 32, v22 +; SDAG-NEXT: v_add_i32_e64 v18, s[6:7], 32, v24 +; SDAG-NEXT: v_add_i32_e64 v19, s[6:7], 32, v26 +; SDAG-NEXT: s_or_b64 s[6:7], vcc, s[4:5] +; SDAG-NEXT: v_min_u32_e32 v16, v16, v21 +; SDAG-NEXT: v_min_u32_e32 v17, v17, v23 +; SDAG-NEXT: v_min_u32_e32 v18, v18, v25 +; SDAG-NEXT: v_min_u32_e32 v19, v19, v27 +; SDAG-NEXT: v_add_i32_e32 v17, vcc, 64, v17 +; SDAG-NEXT: v_addc_u32_e64 v20, s[4:5], 0, 0, vcc +; SDAG-NEXT: v_add_i32_e32 v19, vcc, 64, v19 +; SDAG-NEXT: v_addc_u32_e64 v21, s[4:5], 0, 0, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[14:15] +; SDAG-NEXT: v_cndmask_b32_e64 v20, v20, 0, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v16, v17, v16, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v17, v21, 0, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v18, v19, v18, vcc +; SDAG-NEXT: v_sub_i32_e32 v16, vcc, v16, v18 +; SDAG-NEXT: v_subb_u32_e32 v17, vcc, v20, v17, vcc +; SDAG-NEXT: v_xor_b32_e32 v20, 0x7f, v16 +; SDAG-NEXT: v_subbrev_u32_e32 v18, vcc, 0, v28, vcc +; SDAG-NEXT: v_cmp_lt_u64_e64 s[4:5], s[8:9], v[16:17] +; SDAG-NEXT: v_cndmask_b32_e64 v22, 0, 1, s[4:5] +; SDAG-NEXT: v_subbrev_u32_e32 v19, vcc, 0, v28, vcc +; SDAG-NEXT: v_or_b32_e32 v20, v20, v18 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[18:19] +; SDAG-NEXT: v_cndmask_b32_e64 v23, 0, 1, vcc +; SDAG-NEXT: v_or_b32_e32 v21, v17, v19 +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[18:19] +; SDAG-NEXT: v_cndmask_b32_e32 v22, v23, v22, vcc +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[20:21] +; SDAG-NEXT: v_and_b32_e32 v20, 1, v22 +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 1, v20 +; SDAG-NEXT: s_or_b64 s[4:5], s[6:7], s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v23, v7, 0, s[4:5] +; SDAG-NEXT: s_xor_b64 s[6:7], s[4:5], -1 +; SDAG-NEXT: v_cndmask_b32_e64 v22, v6, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v21, v5, 0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v20, v4, 0, s[4:5] +; SDAG-NEXT: s_and_b64 s[4:5], s[6:7], vcc +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB3_12 +; SDAG-NEXT: ; %bb.7: ; %udiv-bb1 +; SDAG-NEXT: v_add_i32_e32 v34, vcc, 1, v16 +; SDAG-NEXT: v_sub_i32_e64 v22, s[4:5], 63, v16 +; SDAG-NEXT: v_mov_b32_e32 v20, 0 +; SDAG-NEXT: v_mov_b32_e32 v21, 0 +; SDAG-NEXT: v_addc_u32_e32 v35, vcc, 0, v17, vcc +; SDAG-NEXT: v_lshl_b64 v[22:23], v[4:5], v22 +; SDAG-NEXT: v_addc_u32_e32 v36, vcc, 0, v18, vcc +; SDAG-NEXT: v_addc_u32_e32 v37, vcc, 0, v19, vcc +; SDAG-NEXT: v_or_b32_e32 v17, v34, v36 +; SDAG-NEXT: v_sub_i32_e32 v19, vcc, 0x7f, v16 +; SDAG-NEXT: v_or_b32_e32 v18, v35, v37 +; SDAG-NEXT: v_lshl_b64 v[24:25], v[6:7], v19 +; SDAG-NEXT: v_sub_i32_e32 v16, vcc, 64, v19 +; SDAG-NEXT: v_lshl_b64 v[26:27], v[4:5], v19 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[17:18] +; SDAG-NEXT: v_lshr_b64 v[16:17], v[4:5], v16 +; SDAG-NEXT: v_or_b32_e32 v17, v25, v17 +; SDAG-NEXT: v_or_b32_e32 v16, v24, v16 +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v19 +; SDAG-NEXT: v_cndmask_b32_e64 v18, v23, v17, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v22, v22, v16, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v17, 0, v27, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v16, 0, v26, s[4:5] +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v19 +; SDAG-NEXT: v_cndmask_b32_e64 v19, v18, v7, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v18, v22, v6, s[4:5] +; SDAG-NEXT: v_mov_b32_e32 v22, 0 +; SDAG-NEXT: v_mov_b32_e32 v23, 0 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[8:9], exec, s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB3_11 +; SDAG-NEXT: ; %bb.8: ; %udiv-preheader +; SDAG-NEXT: v_lshr_b64 v[20:21], v[4:5], v34 +; SDAG-NEXT: v_sub_i32_e32 v28, vcc, 64, v34 +; SDAG-NEXT: v_subrev_i32_e32 v39, vcc, 64, v34 +; SDAG-NEXT: v_lshr_b64 v[26:27], v[6:7], v34 +; SDAG-NEXT: v_add_i32_e32 v38, vcc, -1, v12 +; SDAG-NEXT: s_mov_b64 s[10:11], 0 +; SDAG-NEXT: v_mov_b32_e32 v24, 0 +; SDAG-NEXT: v_mov_b32_e32 v25, 0 +; SDAG-NEXT: v_mov_b32_e32 v22, 0 +; SDAG-NEXT: v_mov_b32_e32 v23, 0 +; SDAG-NEXT: v_lshl_b64 v[28:29], v[6:7], v28 +; SDAG-NEXT: v_lshr_b64 v[49:50], v[6:7], v39 +; SDAG-NEXT: v_addc_u32_e32 v39, vcc, -1, v13, vcc +; SDAG-NEXT: v_or_b32_e32 v21, v21, v29 +; SDAG-NEXT: v_or_b32_e32 v20, v20, v28 +; SDAG-NEXT: v_addc_u32_e32 v48, vcc, -1, v14, vcc +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v34 +; SDAG-NEXT: v_cndmask_b32_e64 v21, v50, v21, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v20, v49, v20, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v29, 0, v27, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v28, 0, v26, s[4:5] +; SDAG-NEXT: v_addc_u32_e32 v49, vcc, -1, v15, vcc +; SDAG-NEXT: v_cmp_eq_u32_e32 vcc, 0, v34 +; SDAG-NEXT: v_cndmask_b32_e32 v27, v21, v5, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v26, v20, v4, vcc +; SDAG-NEXT: v_mov_b32_e32 v21, 0 +; SDAG-NEXT: .LBB3_9: ; %udiv-do-while +; SDAG-NEXT: ; =>This Inner Loop Header: Depth=1 +; SDAG-NEXT: v_lshl_b64 v[28:29], v[28:29], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v20, 31, v27 +; SDAG-NEXT: v_lshl_b64 v[26:27], v[26:27], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v50, 31, v19 +; SDAG-NEXT: v_lshl_b64 v[18:19], v[18:19], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v51, 31, v17 +; SDAG-NEXT: v_lshl_b64 v[16:17], v[16:17], 1 +; SDAG-NEXT: v_or_b32_e32 v28, v28, v20 +; SDAG-NEXT: v_or_b32_e32 v26, v26, v50 +; SDAG-NEXT: v_or_b32_e32 v18, v18, v51 +; SDAG-NEXT: v_or_b32_e32 v19, v23, v19 +; SDAG-NEXT: v_or_b32_e32 v17, v25, v17 +; SDAG-NEXT: v_or_b32_e32 v18, v22, v18 +; SDAG-NEXT: v_sub_i32_e32 v20, vcc, v38, v26 +; SDAG-NEXT: v_subb_u32_e32 v20, vcc, v39, v27, vcc +; SDAG-NEXT: v_subb_u32_e32 v20, vcc, v48, v28, vcc +; SDAG-NEXT: v_subb_u32_e32 v20, vcc, v49, v29, vcc +; SDAG-NEXT: v_ashrrev_i32_e32 v25, 31, v20 +; SDAG-NEXT: v_and_b32_e32 v20, 1, v25 +; SDAG-NEXT: v_and_b32_e32 v50, v25, v15 +; SDAG-NEXT: v_and_b32_e32 v51, v25, v14 +; SDAG-NEXT: v_and_b32_e32 v52, v25, v13 +; SDAG-NEXT: v_and_b32_e32 v25, v25, v12 +; SDAG-NEXT: v_sub_i32_e32 v26, vcc, v26, v25 +; SDAG-NEXT: v_subb_u32_e32 v27, vcc, v27, v52, vcc +; SDAG-NEXT: v_subb_u32_e32 v28, vcc, v28, v51, vcc +; SDAG-NEXT: v_subb_u32_e32 v29, vcc, v29, v50, vcc +; SDAG-NEXT: v_add_i32_e32 v34, vcc, -1, v34 +; SDAG-NEXT: v_addc_u32_e32 v35, vcc, -1, v35, vcc +; SDAG-NEXT: v_addc_u32_e32 v36, vcc, -1, v36, vcc +; SDAG-NEXT: v_addc_u32_e32 v37, vcc, -1, v37, vcc +; SDAG-NEXT: v_or_b32_e32 v51, v35, v37 +; SDAG-NEXT: v_or_b32_e32 v50, v34, v36 +; SDAG-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[50:51] +; SDAG-NEXT: s_or_b64 s[10:11], vcc, s[10:11] +; SDAG-NEXT: v_or_b32_e32 v16, v24, v16 +; SDAG-NEXT: v_mov_b32_e32 v25, v21 +; SDAG-NEXT: v_mov_b32_e32 v24, v20 +; SDAG-NEXT: s_andn2_b64 exec, exec, s[10:11] +; SDAG-NEXT: s_cbranch_execnz .LBB3_9 +; SDAG-NEXT: ; %bb.10: ; %Flow +; SDAG-NEXT: s_or_b64 exec, exec, s[10:11] +; SDAG-NEXT: .LBB3_11: ; %Flow11 +; SDAG-NEXT: s_or_b64 exec, exec, s[8:9] +; SDAG-NEXT: v_lshl_b64 v[18:19], v[18:19], 1 +; SDAG-NEXT: v_lshrrev_b32_e32 v24, 31, v17 +; SDAG-NEXT: v_lshl_b64 v[16:17], v[16:17], 1 +; SDAG-NEXT: v_or_b32_e32 v18, v18, v24 +; SDAG-NEXT: v_or_b32_e32 v23, v23, v19 +; SDAG-NEXT: v_or_b32_e32 v21, v21, v17 +; SDAG-NEXT: v_or_b32_e32 v22, v22, v18 +; SDAG-NEXT: v_or_b32_e32 v20, v20, v16 +; SDAG-NEXT: .LBB3_12: ; %Flow12 +; SDAG-NEXT: s_or_b64 exec, exec, s[6:7] +; SDAG-NEXT: v_mul_lo_u32 v18, v32, v11 +; SDAG-NEXT: v_mad_u64_u32 v[16:17], s[4:5], v32, v10, 0 +; SDAG-NEXT: v_mul_lo_u32 v28, v30, v10 +; SDAG-NEXT: v_mul_lo_u32 v29, v33, v8 +; SDAG-NEXT: v_mul_lo_u32 v33, v31, v9 +; SDAG-NEXT: v_mad_u64_u32 v[10:11], s[4:5], v8, v32, 0 +; SDAG-NEXT: v_mov_b32_e32 v19, 0 +; SDAG-NEXT: v_mul_lo_u32 v34, v20, v15 +; SDAG-NEXT: v_mad_u64_u32 v[24:25], s[4:5], v20, v14, 0 +; SDAG-NEXT: v_mul_lo_u32 v35, v21, v14 +; SDAG-NEXT: v_mul_lo_u32 v23, v23, v12 +; SDAG-NEXT: v_mul_lo_u32 v36, v22, v13 +; SDAG-NEXT: v_mad_u64_u32 v[14:15], s[4:5], v12, v20, 0 +; SDAG-NEXT: v_add_i32_e32 v17, vcc, v17, v18 +; SDAG-NEXT: v_mov_b32_e32 v18, v11 +; SDAG-NEXT: v_mad_u64_u32 v[26:27], s[4:5], v9, v32, v[18:19] +; SDAG-NEXT: v_sub_i32_e32 v0, vcc, v0, v10 +; SDAG-NEXT: v_add_i32_e64 v18, s[4:5], v25, v34 +; SDAG-NEXT: v_add_i32_e64 v17, s[4:5], v17, v28 +; SDAG-NEXT: v_mov_b32_e32 v28, v27 +; SDAG-NEXT: v_mov_b32_e32 v27, v19 +; SDAG-NEXT: v_mad_u64_u32 v[10:11], s[4:5], v8, v30, v[26:27] +; SDAG-NEXT: v_add_i32_e64 v25, s[4:5], v18, v35 +; SDAG-NEXT: v_mov_b32_e32 v18, v15 +; SDAG-NEXT: v_mad_u64_u32 v[26:27], s[4:5], v13, v20, v[18:19] +; SDAG-NEXT: v_mad_u64_u32 v[15:16], s[4:5], v31, v8, v[16:17] +; SDAG-NEXT: v_mov_b32_e32 v8, v11 +; SDAG-NEXT: v_add_i32_e64 v17, s[4:5], v28, v8 +; SDAG-NEXT: v_addc_u32_e64 v18, s[4:5], 0, 0, s[4:5] +; SDAG-NEXT: v_mov_b32_e32 v8, v10 +; SDAG-NEXT: v_subb_u32_e32 v1, vcc, v1, v8, vcc +; SDAG-NEXT: v_mad_u64_u32 v[10:11], s[4:5], v22, v12, v[24:25] +; SDAG-NEXT: v_mov_b32_e32 v22, v27 +; SDAG-NEXT: v_mov_b32_e32 v27, v19 +; SDAG-NEXT: v_mad_u64_u32 v[19:20], s[4:5], v12, v21, v[26:27] +; SDAG-NEXT: v_add_i32_e64 v16, s[4:5], v29, v16 +; SDAG-NEXT: v_mad_u64_u32 v[8:9], s[4:5], v9, v30, v[17:18] +; SDAG-NEXT: v_add_i32_e64 v17, s[4:5], v23, v11 +; SDAG-NEXT: v_mov_b32_e32 v11, v20 +; SDAG-NEXT: v_add_i32_e64 v11, s[4:5], v22, v11 +; SDAG-NEXT: v_addc_u32_e64 v12, s[4:5], 0, 0, s[4:5] +; SDAG-NEXT: v_add_i32_e64 v16, s[4:5], v33, v16 +; SDAG-NEXT: v_add_i32_e64 v17, s[4:5], v36, v17 +; SDAG-NEXT: v_mad_u64_u32 v[11:12], s[4:5], v13, v21, v[11:12] +; SDAG-NEXT: v_add_i32_e64 v8, s[4:5], v8, v15 +; SDAG-NEXT: v_addc_u32_e64 v9, s[4:5], v9, v16, s[4:5] +; SDAG-NEXT: v_subb_u32_e32 v2, vcc, v2, v8, vcc +; SDAG-NEXT: v_subb_u32_e32 v3, vcc, v3, v9, vcc +; SDAG-NEXT: v_add_i32_e32 v8, vcc, v11, v10 +; SDAG-NEXT: v_addc_u32_e32 v9, vcc, v12, v17, vcc +; SDAG-NEXT: v_mov_b32_e32 v10, v19 +; SDAG-NEXT: v_sub_i32_e32 v4, vcc, v4, v14 +; SDAG-NEXT: v_subb_u32_e32 v5, vcc, v5, v10, vcc +; SDAG-NEXT: v_subb_u32_e32 v6, vcc, v6, v8, vcc +; SDAG-NEXT: v_subb_u32_e32 v7, vcc, v7, v9, vcc +; SDAG-NEXT: s_setpc_b64 s[30:31] +; +; GISEL-LABEL: v_urem_v2i128_vv: +; GISEL: ; %bb.0: ; %_udiv-special-cases_udiv-special-cases +; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-NEXT: s_mov_b64 s[8:9], 0 +; GISEL-NEXT: v_or_b32_e32 v16, v8, v10 +; GISEL-NEXT: v_or_b32_e32 v17, v9, v11 +; GISEL-NEXT: v_or_b32_e32 v18, v0, v2 +; GISEL-NEXT: v_or_b32_e32 v19, v1, v3 +; GISEL-NEXT: v_ffbh_u32_e32 v22, v9 +; GISEL-NEXT: v_ffbh_u32_e32 v23, v8 +; GISEL-NEXT: v_ffbh_u32_e32 v24, v11 +; GISEL-NEXT: v_ffbh_u32_e32 v25, v10 +; GISEL-NEXT: v_ffbh_u32_e32 v26, v1 +; GISEL-NEXT: v_ffbh_u32_e32 v27, v0 +; GISEL-NEXT: v_ffbh_u32_e32 v28, v3 +; GISEL-NEXT: v_ffbh_u32_e32 v29, v2 +; GISEL-NEXT: v_mov_b32_e32 v20, 0x7f +; GISEL-NEXT: v_mov_b32_e32 v21, 0 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[16:17] +; GISEL-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[18:19] +; GISEL-NEXT: v_add_i32_e64 v16, s[6:7], 32, v23 +; GISEL-NEXT: v_add_i32_e64 v17, s[6:7], 32, v25 +; GISEL-NEXT: v_add_i32_e64 v18, s[6:7], 32, v27 +; GISEL-NEXT: v_add_i32_e64 v19, s[6:7], 32, v29 +; GISEL-NEXT: v_min_u32_e32 v16, v22, v16 +; GISEL-NEXT: v_min_u32_e32 v17, v24, v17 +; GISEL-NEXT: v_min_u32_e32 v18, v26, v18 +; GISEL-NEXT: v_min_u32_e32 v19, v28, v19 +; GISEL-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v22, 0, 1, s[4:5] +; GISEL-NEXT: v_add_i32_e32 v16, vcc, 64, v16 +; GISEL-NEXT: v_add_i32_e32 v18, vcc, 64, v18 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[10:11] +; GISEL-NEXT: v_cndmask_b32_e32 v16, v17, v16, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: v_cndmask_b32_e32 v17, v19, v18, vcc +; GISEL-NEXT: v_sub_i32_e32 v16, vcc, v16, v17 +; GISEL-NEXT: v_subb_u32_e64 v17, s[4:5], 0, 0, vcc +; GISEL-NEXT: v_subb_u32_e64 v18, s[4:5], 0, 0, s[4:5] +; GISEL-NEXT: v_subb_u32_e64 v19, s[4:5], 0, 0, s[4:5] +; GISEL-NEXT: v_cmp_gt_u64_e32 vcc, v[16:17], v[20:21] +; GISEL-NEXT: v_cndmask_b32_e64 v23, 0, 1, vcc +; GISEL-NEXT: v_xor_b32_e32 v20, 0x7f, v16 +; GISEL-NEXT: v_cmp_lt_u64_e32 vcc, 0, v[18:19] +; GISEL-NEXT: v_cndmask_b32_e64 v24, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v20, v20, v18 +; GISEL-NEXT: v_or_b32_e32 v21, v17, v19 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[18:19] +; GISEL-NEXT: v_cndmask_b32_e32 v23, v24, v23, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[20:21] +; GISEL-NEXT: v_cndmask_b32_e64 v20, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v21, v22, v23 +; GISEL-NEXT: v_and_b32_e32 v22, 1, v21 +; GISEL-NEXT: v_or_b32_e32 v20, v21, v20 +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v22 +; GISEL-NEXT: v_cndmask_b32_e64 v32, v0, 0, vcc +; GISEL-NEXT: v_and_b32_e32 v22, 1, v20 +; GISEL-NEXT: v_cndmask_b32_e64 v33, v1, 0, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v20, v2, 0, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v21, v3, 0, vcc +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v22 +; GISEL-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GISEL-NEXT: s_and_saveexec_b64 s[12:13], s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB3_6 +; GISEL-NEXT: ; %bb.1: ; %udiv-bb15 +; GISEL-NEXT: v_add_i32_e32 v30, vcc, 1, v16 +; GISEL-NEXT: v_addc_u32_e64 v31, s[4:5], 0, v17, vcc +; GISEL-NEXT: v_sub_i32_e32 v26, vcc, 0x7f, v16 +; GISEL-NEXT: v_addc_u32_e64 v32, vcc, 0, v18, s[4:5] +; GISEL-NEXT: v_addc_u32_e32 v33, vcc, 0, v19, vcc +; GISEL-NEXT: v_subrev_i32_e64 v22, s[4:5], 64, v26 +; GISEL-NEXT: v_sub_i32_e64 v20, s[4:5], 64, v26 +; GISEL-NEXT: v_lshl_b64 v[16:17], v[0:1], v26 +; GISEL-NEXT: v_lshl_b64 v[18:19], v[2:3], v26 +; GISEL-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GISEL-NEXT: v_lshr_b64 v[20:21], v[0:1], v20 +; GISEL-NEXT: v_lshl_b64 v[24:25], v[0:1], v22 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v26 +; GISEL-NEXT: v_cndmask_b32_e32 v22, 0, v16, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v23, 0, v17, vcc +; GISEL-NEXT: v_or_b32_e32 v16, v20, v18 +; GISEL-NEXT: v_or_b32_e32 v17, v21, v19 +; GISEL-NEXT: v_cndmask_b32_e32 v16, v24, v16, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v17, v25, v17, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v26 +; GISEL-NEXT: v_cndmask_b32_e32 v20, v16, v2, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v21, v17, v3, vcc +; GISEL-NEXT: s_mov_b64 s[10:11], s[8:9] +; GISEL-NEXT: v_mov_b32_e32 v19, s11 +; GISEL-NEXT: v_mov_b32_e32 v18, s10 +; GISEL-NEXT: v_mov_b32_e32 v17, s9 +; GISEL-NEXT: v_mov_b32_e32 v16, s8 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; GISEL-NEXT: s_xor_b64 s[8:9], exec, s[6:7] +; GISEL-NEXT: s_cbranch_execz .LBB3_5 +; GISEL-NEXT: ; %bb.2: ; %udiv-preheader4 +; GISEL-NEXT: v_subrev_i32_e32 v26, vcc, 64, v30 +; GISEL-NEXT: v_sub_i32_e32 v24, vcc, 64, v30 +; GISEL-NEXT: v_lshr_b64 v[16:17], v[2:3], v30 +; GISEL-NEXT: v_lshr_b64 v[18:19], v[0:1], v30 +; GISEL-NEXT: s_mov_b64 s[4:5], 0 +; GISEL-NEXT: v_add_i32_e32 v34, vcc, -1, v8 +; GISEL-NEXT: v_addc_u32_e32 v35, vcc, -1, v9, vcc +; GISEL-NEXT: v_lshl_b64 v[24:25], v[2:3], v24 +; GISEL-NEXT: v_lshr_b64 v[26:27], v[2:3], v26 +; GISEL-NEXT: v_addc_u32_e32 v36, vcc, -1, v10, vcc +; GISEL-NEXT: v_addc_u32_e32 v37, vcc, -1, v11, vcc +; GISEL-NEXT: s_mov_b64 s[6:7], s[4:5] +; GISEL-NEXT: v_or_b32_e32 v18, v18, v24 +; GISEL-NEXT: v_or_b32_e32 v19, v19, v25 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v30 +; GISEL-NEXT: v_cndmask_b32_e32 v18, v26, v18, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v19, v27, v19, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v28, 0, v16, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v29, 0, v17, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v30 +; GISEL-NEXT: v_cndmask_b32_e32 v26, v18, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v27, v19, v1, vcc +; GISEL-NEXT: v_mov_b32_e32 v25, 0 +; GISEL-NEXT: v_mov_b32_e32 v19, s7 +; GISEL-NEXT: v_mov_b32_e32 v18, s6 +; GISEL-NEXT: v_mov_b32_e32 v17, s5 +; GISEL-NEXT: v_mov_b32_e32 v16, s4 +; GISEL-NEXT: .LBB3_3: ; %udiv-do-while3 +; GISEL-NEXT: ; =>This Inner Loop Header: Depth=1 +; GISEL-NEXT: v_lshl_b64 v[18:19], v[22:23], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v24, 31, v23 +; GISEL-NEXT: v_lshl_b64 v[38:39], v[26:27], 1 +; GISEL-NEXT: v_lshl_b64 v[28:29], v[28:29], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v26, 31, v27 +; GISEL-NEXT: v_lshrrev_b32_e32 v27, 31, v21 +; GISEL-NEXT: v_lshl_b64 v[20:21], v[20:21], 1 +; GISEL-NEXT: v_add_i32_e32 v30, vcc, -1, v30 +; GISEL-NEXT: v_addc_u32_e32 v31, vcc, -1, v31, vcc +; GISEL-NEXT: v_or_b32_e32 v22, v16, v18 +; GISEL-NEXT: v_or_b32_e32 v23, v17, v19 +; GISEL-NEXT: v_or_b32_e32 v18, v28, v26 +; GISEL-NEXT: v_or_b32_e32 v19, v38, v27 +; GISEL-NEXT: v_or_b32_e32 v20, v20, v24 +; GISEL-NEXT: v_addc_u32_e32 v32, vcc, -1, v32, vcc +; GISEL-NEXT: v_addc_u32_e32 v33, vcc, -1, v33, vcc +; GISEL-NEXT: v_sub_i32_e32 v16, vcc, v34, v19 +; GISEL-NEXT: v_subb_u32_e32 v16, vcc, v35, v39, vcc +; GISEL-NEXT: v_or_b32_e32 v16, v30, v32 +; GISEL-NEXT: v_or_b32_e32 v17, v31, v33 +; GISEL-NEXT: v_subb_u32_e32 v24, vcc, v36, v18, vcc +; GISEL-NEXT: v_subb_u32_e32 v24, vcc, v37, v29, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[16:17] +; GISEL-NEXT: v_ashrrev_i32_e32 v16, 31, v24 +; GISEL-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GISEL-NEXT: v_and_b32_e32 v24, 1, v16 +; GISEL-NEXT: v_and_b32_e32 v17, v16, v8 +; GISEL-NEXT: v_and_b32_e32 v27, v16, v9 +; GISEL-NEXT: v_and_b32_e32 v28, v16, v10 +; GISEL-NEXT: v_and_b32_e32 v16, v16, v11 +; GISEL-NEXT: v_sub_i32_e32 v26, vcc, v19, v17 +; GISEL-NEXT: v_subb_u32_e32 v27, vcc, v39, v27, vcc +; GISEL-NEXT: v_subb_u32_e32 v28, vcc, v18, v28, vcc +; GISEL-NEXT: v_subb_u32_e32 v29, vcc, v29, v16, vcc +; GISEL-NEXT: v_mov_b32_e32 v16, v24 +; GISEL-NEXT: v_mov_b32_e32 v17, v25 +; GISEL-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GISEL-NEXT: s_cbranch_execnz .LBB3_3 +; GISEL-NEXT: ; %bb.4: ; %Flow13 +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: .LBB3_5: ; %Flow14 +; GISEL-NEXT: s_or_b64 exec, exec, s[8:9] +; GISEL-NEXT: v_lshl_b64 v[18:19], v[22:23], 1 +; GISEL-NEXT: v_lshl_b64 v[20:21], v[20:21], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v22, 31, v23 +; GISEL-NEXT: v_or_b32_e32 v20, v20, v22 +; GISEL-NEXT: v_or_b32_e32 v32, v16, v18 +; GISEL-NEXT: v_or_b32_e32 v33, v17, v19 +; GISEL-NEXT: .LBB3_6: ; %Flow16 +; GISEL-NEXT: s_or_b64 exec, exec, s[12:13] +; GISEL-NEXT: s_mov_b64 s[8:9], 0 +; GISEL-NEXT: v_or_b32_e32 v16, v12, v14 +; GISEL-NEXT: v_or_b32_e32 v17, v13, v15 +; GISEL-NEXT: v_or_b32_e32 v18, v4, v6 +; GISEL-NEXT: v_or_b32_e32 v19, v5, v7 +; GISEL-NEXT: v_ffbh_u32_e32 v22, v13 +; GISEL-NEXT: v_ffbh_u32_e32 v23, v12 +; GISEL-NEXT: v_ffbh_u32_e32 v26, v15 +; GISEL-NEXT: v_ffbh_u32_e32 v27, v14 +; GISEL-NEXT: v_ffbh_u32_e32 v28, v5 +; GISEL-NEXT: v_ffbh_u32_e32 v29, v4 +; GISEL-NEXT: v_ffbh_u32_e32 v30, v7 +; GISEL-NEXT: v_ffbh_u32_e32 v31, v6 +; GISEL-NEXT: v_mov_b32_e32 v24, 0x7f +; GISEL-NEXT: v_mov_b32_e32 v25, 0 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[16:17] +; GISEL-NEXT: v_cmp_eq_u64_e64 s[4:5], 0, v[18:19] +; GISEL-NEXT: v_add_i32_e64 v16, s[6:7], 32, v23 +; GISEL-NEXT: v_add_i32_e64 v17, s[6:7], 32, v27 +; GISEL-NEXT: v_add_i32_e64 v18, s[6:7], 32, v29 +; GISEL-NEXT: v_add_i32_e64 v19, s[6:7], 32, v31 +; GISEL-NEXT: v_min_u32_e32 v16, v22, v16 +; GISEL-NEXT: v_min_u32_e32 v17, v26, v17 +; GISEL-NEXT: v_min_u32_e32 v18, v28, v18 +; GISEL-NEXT: v_min_u32_e32 v19, v30, v19 +; GISEL-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v26, 0, 1, s[4:5] +; GISEL-NEXT: v_add_i32_e32 v16, vcc, 64, v16 +; GISEL-NEXT: v_add_i32_e32 v18, vcc, 64, v18 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[14:15] +; GISEL-NEXT: v_cndmask_b32_e32 v16, v17, v16, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[6:7] +; GISEL-NEXT: v_cndmask_b32_e32 v17, v19, v18, vcc +; GISEL-NEXT: v_sub_i32_e32 v16, vcc, v16, v17 +; GISEL-NEXT: v_subb_u32_e64 v17, s[4:5], 0, 0, vcc +; GISEL-NEXT: v_subb_u32_e64 v22, s[4:5], 0, 0, s[4:5] +; GISEL-NEXT: v_subb_u32_e64 v23, s[4:5], 0, 0, s[4:5] +; GISEL-NEXT: v_cmp_gt_u64_e32 vcc, v[16:17], v[24:25] +; GISEL-NEXT: v_cndmask_b32_e64 v24, 0, 1, vcc +; GISEL-NEXT: v_xor_b32_e32 v18, 0x7f, v16 +; GISEL-NEXT: v_cmp_lt_u64_e32 vcc, 0, v[22:23] +; GISEL-NEXT: v_cndmask_b32_e64 v25, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v18, v18, v22 +; GISEL-NEXT: v_or_b32_e32 v19, v17, v23 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[22:23] +; GISEL-NEXT: v_cndmask_b32_e32 v24, v25, v24, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[18:19] +; GISEL-NEXT: v_cndmask_b32_e64 v18, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v19, v26, v24 +; GISEL-NEXT: v_and_b32_e32 v24, 1, v19 +; GISEL-NEXT: v_or_b32_e32 v18, v19, v18 +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v24 +; GISEL-NEXT: v_cndmask_b32_e64 v24, v4, 0, vcc +; GISEL-NEXT: v_and_b32_e32 v26, 1, v18 +; GISEL-NEXT: v_cndmask_b32_e64 v25, v5, 0, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v18, v6, 0, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v19, v7, 0, vcc +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v26 +; GISEL-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GISEL-NEXT: s_and_saveexec_b64 s[12:13], s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB3_12 +; GISEL-NEXT: ; %bb.7: ; %udiv-bb1 +; GISEL-NEXT: v_add_i32_e32 v34, vcc, 1, v16 +; GISEL-NEXT: v_addc_u32_e64 v35, s[4:5], 0, v17, vcc +; GISEL-NEXT: v_sub_i32_e32 v28, vcc, 0x7f, v16 +; GISEL-NEXT: v_addc_u32_e64 v36, vcc, 0, v22, s[4:5] +; GISEL-NEXT: v_addc_u32_e32 v37, vcc, 0, v23, vcc +; GISEL-NEXT: v_subrev_i32_e64 v24, s[4:5], 64, v28 +; GISEL-NEXT: v_sub_i32_e64 v22, s[4:5], 64, v28 +; GISEL-NEXT: v_lshl_b64 v[16:17], v[4:5], v28 +; GISEL-NEXT: v_lshl_b64 v[18:19], v[6:7], v28 +; GISEL-NEXT: s_xor_b64 s[4:5], vcc, -1 +; GISEL-NEXT: v_lshr_b64 v[22:23], v[4:5], v22 +; GISEL-NEXT: v_lshl_b64 v[26:27], v[4:5], v24 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v28 +; GISEL-NEXT: v_cndmask_b32_e32 v24, 0, v16, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v25, 0, v17, vcc +; GISEL-NEXT: v_or_b32_e32 v16, v22, v18 +; GISEL-NEXT: v_or_b32_e32 v17, v23, v19 +; GISEL-NEXT: v_cndmask_b32_e32 v16, v26, v16, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v17, v27, v17, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v28 +; GISEL-NEXT: v_cndmask_b32_e32 v22, v16, v6, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v23, v17, v7, vcc +; GISEL-NEXT: s_mov_b64 s[10:11], s[8:9] +; GISEL-NEXT: v_mov_b32_e32 v19, s11 +; GISEL-NEXT: v_mov_b32_e32 v18, s10 +; GISEL-NEXT: v_mov_b32_e32 v17, s9 +; GISEL-NEXT: v_mov_b32_e32 v16, s8 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; GISEL-NEXT: s_xor_b64 s[8:9], exec, s[6:7] +; GISEL-NEXT: s_cbranch_execz .LBB3_11 +; GISEL-NEXT: ; %bb.8: ; %udiv-preheader +; GISEL-NEXT: v_subrev_i32_e32 v28, vcc, 64, v34 +; GISEL-NEXT: v_sub_i32_e32 v26, vcc, 64, v34 +; GISEL-NEXT: v_lshr_b64 v[16:17], v[6:7], v34 +; GISEL-NEXT: v_lshr_b64 v[18:19], v[4:5], v34 +; GISEL-NEXT: s_mov_b64 s[4:5], 0 +; GISEL-NEXT: v_add_i32_e32 v38, vcc, -1, v12 +; GISEL-NEXT: v_addc_u32_e32 v39, vcc, -1, v13, vcc +; GISEL-NEXT: v_lshl_b64 v[26:27], v[6:7], v26 +; GISEL-NEXT: v_lshr_b64 v[28:29], v[6:7], v28 +; GISEL-NEXT: v_addc_u32_e32 v48, vcc, -1, v14, vcc +; GISEL-NEXT: v_addc_u32_e32 v49, vcc, -1, v15, vcc +; GISEL-NEXT: s_mov_b64 s[6:7], s[4:5] +; GISEL-NEXT: v_or_b32_e32 v18, v18, v26 +; GISEL-NEXT: v_or_b32_e32 v19, v19, v27 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v34 +; GISEL-NEXT: v_cndmask_b32_e32 v18, v28, v18, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v19, v29, v19, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v30, 0, v16, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v31, 0, v17, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v34 +; GISEL-NEXT: v_cndmask_b32_e32 v28, v18, v4, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v29, v19, v5, vcc +; GISEL-NEXT: v_mov_b32_e32 v27, 0 +; GISEL-NEXT: v_mov_b32_e32 v19, s7 +; GISEL-NEXT: v_mov_b32_e32 v18, s6 +; GISEL-NEXT: v_mov_b32_e32 v17, s5 +; GISEL-NEXT: v_mov_b32_e32 v16, s4 +; GISEL-NEXT: .LBB3_9: ; %udiv-do-while +; GISEL-NEXT: ; =>This Inner Loop Header: Depth=1 +; GISEL-NEXT: v_lshl_b64 v[18:19], v[24:25], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v26, 31, v25 +; GISEL-NEXT: v_lshl_b64 v[50:51], v[28:29], 1 +; GISEL-NEXT: v_lshl_b64 v[30:31], v[30:31], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v28, 31, v29 +; GISEL-NEXT: v_lshrrev_b32_e32 v29, 31, v23 +; GISEL-NEXT: v_lshl_b64 v[22:23], v[22:23], 1 +; GISEL-NEXT: v_add_i32_e32 v34, vcc, -1, v34 +; GISEL-NEXT: v_addc_u32_e32 v35, vcc, -1, v35, vcc +; GISEL-NEXT: v_or_b32_e32 v24, v16, v18 +; GISEL-NEXT: v_or_b32_e32 v25, v17, v19 +; GISEL-NEXT: v_or_b32_e32 v18, v30, v28 +; GISEL-NEXT: v_or_b32_e32 v19, v50, v29 +; GISEL-NEXT: v_or_b32_e32 v22, v22, v26 +; GISEL-NEXT: v_addc_u32_e32 v36, vcc, -1, v36, vcc +; GISEL-NEXT: v_addc_u32_e32 v37, vcc, -1, v37, vcc +; GISEL-NEXT: v_sub_i32_e32 v16, vcc, v38, v19 +; GISEL-NEXT: v_subb_u32_e32 v16, vcc, v39, v51, vcc +; GISEL-NEXT: v_or_b32_e32 v16, v34, v36 +; GISEL-NEXT: v_or_b32_e32 v17, v35, v37 +; GISEL-NEXT: v_subb_u32_e32 v26, vcc, v48, v18, vcc +; GISEL-NEXT: v_subb_u32_e32 v26, vcc, v49, v31, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[16:17] +; GISEL-NEXT: v_ashrrev_i32_e32 v16, 31, v26 +; GISEL-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GISEL-NEXT: v_and_b32_e32 v26, 1, v16 +; GISEL-NEXT: v_and_b32_e32 v17, v16, v12 +; GISEL-NEXT: v_and_b32_e32 v29, v16, v13 +; GISEL-NEXT: v_and_b32_e32 v30, v16, v14 +; GISEL-NEXT: v_and_b32_e32 v50, v16, v15 +; GISEL-NEXT: v_sub_i32_e32 v28, vcc, v19, v17 +; GISEL-NEXT: v_subb_u32_e32 v29, vcc, v51, v29, vcc +; GISEL-NEXT: v_mov_b32_e32 v16, v26 +; GISEL-NEXT: v_mov_b32_e32 v17, v27 +; GISEL-NEXT: v_subb_u32_e32 v30, vcc, v18, v30, vcc +; GISEL-NEXT: v_subb_u32_e32 v31, vcc, v31, v50, vcc +; GISEL-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GISEL-NEXT: s_cbranch_execnz .LBB3_9 +; GISEL-NEXT: ; %bb.10: ; %Flow +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: .LBB3_11: ; %Flow11 +; GISEL-NEXT: s_or_b64 exec, exec, s[8:9] +; GISEL-NEXT: v_lshl_b64 v[26:27], v[24:25], 1 +; GISEL-NEXT: v_lshl_b64 v[18:19], v[22:23], 1 +; GISEL-NEXT: v_lshrrev_b32_e32 v22, 31, v25 +; GISEL-NEXT: v_or_b32_e32 v18, v18, v22 +; GISEL-NEXT: v_or_b32_e32 v24, v16, v26 +; GISEL-NEXT: v_or_b32_e32 v25, v17, v27 +; GISEL-NEXT: .LBB3_12: ; %Flow12 +; GISEL-NEXT: s_or_b64 exec, exec, s[12:13] +; GISEL-NEXT: v_mad_u64_u32 v[16:17], s[4:5], v8, v32, 0 +; GISEL-NEXT: v_mad_u64_u32 v[22:23], s[4:5], v8, v20, 0 +; GISEL-NEXT: v_mul_lo_u32 v28, v8, v21 +; GISEL-NEXT: v_mul_lo_u32 v29, v9, v20 +; GISEL-NEXT: v_mad_u64_u32 v[20:21], s[4:5], v12, v24, 0 +; GISEL-NEXT: v_mad_u64_u32 v[26:27], s[4:5], v12, v18, 0 +; GISEL-NEXT: v_mul_lo_u32 v30, v12, v19 +; GISEL-NEXT: v_mul_lo_u32 v31, v13, v18 +; GISEL-NEXT: v_mad_u64_u32 v[18:19], s[4:5], v9, v33, v[22:23] +; GISEL-NEXT: v_mad_u64_u32 v[22:23], s[4:5], v13, v25, v[26:27] +; GISEL-NEXT: v_mad_u64_u32 v[18:19], s[4:5], v10, v32, v[18:19] +; GISEL-NEXT: v_mad_u64_u32 v[22:23], s[4:5], v14, v24, v[22:23] +; GISEL-NEXT: v_mad_u64_u32 v[17:18], vcc, v8, v33, v[17:18] +; GISEL-NEXT: v_mad_u64_u32 v[21:22], s[4:5], v12, v25, v[21:22] +; GISEL-NEXT: v_mad_u64_u32 v[8:9], s[6:7], v9, v32, v[17:18] +; GISEL-NEXT: v_addc_u32_e64 v17, s[6:7], v19, v28, s[6:7] +; GISEL-NEXT: v_mad_u64_u32 v[12:13], s[6:7], v13, v24, v[21:22] +; GISEL-NEXT: v_addc_u32_e64 v18, s[6:7], v23, v30, s[6:7] +; GISEL-NEXT: v_addc_u32_e32 v17, vcc, v17, v29, vcc +; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v0, v16 +; GISEL-NEXT: v_subb_u32_e32 v1, vcc, v1, v8, vcc +; GISEL-NEXT: v_addc_u32_e64 v8, s[4:5], v18, v31, s[4:5] +; GISEL-NEXT: v_sub_i32_e64 v4, s[4:5], v4, v20 +; GISEL-NEXT: v_subb_u32_e64 v5, s[4:5], v5, v12, s[4:5] +; GISEL-NEXT: v_mad_u64_u32 v[16:17], s[6:7], v10, v33, v[17:18] +; GISEL-NEXT: v_mad_u64_u32 v[18:19], s[6:7], v14, v25, v[8:9] +; GISEL-NEXT: v_mad_u64_u32 v[10:11], s[6:7], v11, v32, v[16:17] +; GISEL-NEXT: v_mad_u64_u32 v[11:12], s[6:7], v15, v24, v[18:19] +; GISEL-NEXT: v_subb_u32_e32 v2, vcc, v2, v9, vcc +; GISEL-NEXT: v_subb_u32_e32 v3, vcc, v3, v10, vcc +; GISEL-NEXT: v_subb_u32_e64 v6, vcc, v6, v13, s[4:5] +; GISEL-NEXT: v_subb_u32_e32 v7, vcc, v7, v11, vcc +; GISEL-NEXT: s_setpc_b64 s[30:31] %shl = urem <2 x i128> %lhs, %rhs ret <2 x i128> %shl } diff --git a/llvm/test/CodeGen/AMDGPU/duplicate-attribute-indirect.ll b/llvm/test/CodeGen/AMDGPU/duplicate-attribute-indirect.ll index 0069370cc9721caf73a3349549b83a7ff1d8d4dc..05558c555c581e3fb64bfd1e65cf55edefcb712f 100644 --- a/llvm/test/CodeGen/AMDGPU/duplicate-attribute-indirect.ll +++ b/llvm/test/CodeGen/AMDGPU/duplicate-attribute-indirect.ll @@ -42,6 +42,6 @@ attributes #0 = { "amdgpu-no-dispatch-id" } ;. ; AKF_GCN: attributes #[[ATTR0]] = { "amdgpu-calls" "amdgpu-no-dispatch-id" "amdgpu-stack-objects" } ;. -; ATTRIBUTOR_GCN: attributes #[[ATTR0]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; ATTRIBUTOR_GCN: attributes #[[ATTR0]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } ; ATTRIBUTOR_GCN: attributes #[[ATTR1]] = { "amdgpu-no-dispatch-id" "uniform-work-group-size"="false" } ;. diff --git a/llvm/test/CodeGen/AMDGPU/fcanonicalize-elimination.ll b/llvm/test/CodeGen/AMDGPU/fcanonicalize-elimination.ll index 4ed1b8a520b8b53c82f3368f8985fc9e8fa8a1af..e1981972f58d1b227cb00ce5f70848feca6e5cc7 100644 --- a/llvm/test/CodeGen/AMDGPU/fcanonicalize-elimination.ll +++ b/llvm/test/CodeGen/AMDGPU/fcanonicalize-elimination.ll @@ -471,25 +471,15 @@ define amdgpu_kernel void @test_fold_canonicalize_minnum_value_from_load_f32_iee ret void } -; GCN-LABEL: test_fold_canonicalize_minnum_value_from_load_f32_nnan_ieee_mode: -; VI-FLUSH: v_mul_f32_e32 v{{[0-9]+}}, 1.0, v{{[0-9]+}} -; GCN-DENORM-NOT: v_max -; GCN-DENORM-NOT: v_mul - -; GCN: v_min_f32_e32 v{{[0-9]+}}, 0, v{{[0-9]+}} -; GCN-DENORM-NOT: v_max -; GCN-DENORM-NOT: v_mul - -; GFX9: {{flat|global}}_store_dword -define amdgpu_kernel void @test_fold_canonicalize_minnum_value_from_load_f32_nnan_ieee_mode(ptr addrspace(1) %arg) #1 { - %id = tail call i32 @llvm.amdgcn.workitem.id.x() - %gep = getelementptr inbounds float, ptr addrspace(1) %arg, i32 %id - %load = load float, ptr addrspace(1) %gep, align 4 - %v = tail call float @llvm.minnum.f32(float %load, float 0.0) - %canonicalized = tail call float @llvm.canonicalize.f32(float %v) - store float %canonicalized, ptr addrspace(1) %gep, align 4 - ret void -} +; define amdgpu_kernel void @test_fold_canonicalize_minnum_value_from_load_f32_nnan_ieee_mode(ptr addrspace(1) %arg) #1 { +; %id = tail call i32 @llvm.amdgcn.workitem.id.x() +; %gep = getelementptr inbounds float, ptr addrspace(1) %arg, i32 %id +; %load = load float, ptr addrspace(1) %gep, align 4 +; %v = tail call float @llvm.minnum.f32(float %load, float 0.0) +; %canonicalized = tail call float @llvm.canonicalize.f32(float %v) +; store float %canonicalized, ptr addrspace(1) %gep, align 4 +; ret void +; } ; GCN-LABEL: test_fold_canonicalize_minnum_value_f32: ; GCN: v_min_f32_e32 [[V:v[0-9]+]], 0, v{{[0-9]+}} @@ -523,32 +513,15 @@ define amdgpu_kernel void @test_fold_canonicalize_sNaN_value_f32(ptr addrspace(1 ret void } -; GCN-LABEL: test_fold_canonicalize_denorm_value_f32: -; GCN: {{flat|global}}_load_dword [[VAL:v[0-9]+]] - -; GFX9-DENORM: v_max_f32_e32 [[QUIET:v[0-9]+]], [[VAL]], [[VAL]] -; GFX9-DENORM: v_min_f32_e32 [[RESULT:v[0-9]+]], 0x7fffff, [[QUIET]] - -; GFX9-FLUSH: v_max_f32_e32 [[QUIET:v[0-9]+]], [[VAL]], [[VAL]] -; GFX9-FLUSH: v_min_f32_e32 [[RESULT:v[0-9]+]], 0, [[QUIET]] - -; VI-FLUSH: v_mul_f32_e32 [[QUIET_V0:v[0-9]+]], 1.0, [[VAL]] -; VI-FLUSH: v_min_f32_e32 [[RESULT:v[0-9]+]], 0, [[QUIET_V0]] - -; VI-DENORM: v_min_f32_e32 [[RESULT:v[0-9]+]], 0x7fffff, [[VAL]] - -; GCN-NOT: v_mul -; GCN-NOT: v_max -; GCN: {{flat|global}}_store_dword v{{.+}}, [[RESULT]] -define amdgpu_kernel void @test_fold_canonicalize_denorm_value_f32(ptr addrspace(1) %arg) { - %id = tail call i32 @llvm.amdgcn.workitem.id.x() - %gep = getelementptr inbounds float, ptr addrspace(1) %arg, i32 %id - %load = load float, ptr addrspace(1) %gep, align 4 - %v = tail call float @llvm.minnum.f32(float %load, float bitcast (i32 8388607 to float)) - %canonicalized = tail call float @llvm.canonicalize.f32(float %v) - store float %canonicalized, ptr addrspace(1) %gep, align 4 - ret void -} +; define amdgpu_kernel void @test_fold_canonicalize_denorm_value_f32(ptr addrspace(1) %arg) { +; %id = tail call i32 @llvm.amdgcn.workitem.id.x() +; %gep = getelementptr inbounds float, ptr addrspace(1) %arg, i32 %id +; %load = load float, ptr addrspace(1) %gep, align 4 +; %v = tail call float @llvm.minnum.f32(float %load, float bitcast (i32 8388607 to float)) +; %canonicalized = tail call float @llvm.canonicalize.f32(float %v) +; store float %canonicalized, ptr addrspace(1) %gep, align 4 +; ret void +; } ; GCN-LABEL: test_fold_canonicalize_maxnum_value_from_load_f32_ieee_mode: ; GCN: {{flat|global}}_load_dword [[VAL:v[0-9]+]] @@ -674,10 +647,9 @@ define amdgpu_kernel void @test_fold_canonicalize_load_nnan_value_f64(ptr addrsp } ; GCN-LABEL: {{^}}test_fold_canonicalize_load_nnan_value_f16 -; GCN: {{flat|global}}_load_ushort [[V:v[0-9]+]], -; GCN-NOT: v_mul -; GCN-NOT: v_max -; GCN: {{flat|global}}_store_short v{{.+}}, [[V]] +; GCN: {{flat|global}}_load_ushort [[V1:v[0-9]+]], +; GCN: v_max_f16_e32 [[V2:v[0-9]+]], [[V1]], [[V1]] +; GCN: {{flat|global}}_store_short v{{.+}}, [[V2]] define amdgpu_kernel void @test_fold_canonicalize_load_nnan_value_f16(ptr addrspace(1) %arg, ptr addrspace(1) %out) #1 { %id = tail call i32 @llvm.amdgcn.workitem.id.x() %gep = getelementptr inbounds half, ptr addrspace(1) %arg, i32 %id @@ -807,18 +779,13 @@ define half @v_test_canonicalize_extract_element_v2f16(<2 x half> %vec) { ret half %canonicalized } -; GCN-LABEL: {{^}}v_test_canonicalize_insertelement_v2f16: -; GFX9: v_mul_f16_e32 -; GFX9: v_pk_mul_f16 -; GFX9-NOT: v_max -; GFX9-NOT: v_pk_max -define <2 x half> @v_test_canonicalize_insertelement_v2f16(<2 x half> %vec, half %val, i32 %idx) { - %vec.op = fmul <2 x half> %vec, <half 4.0, half 4.0> - %ins.op = fmul half %val, 8.0 - %ins = insertelement <2 x half> %vec.op, half %ins.op, i32 %idx - %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins) - ret <2 x half> %canonicalized -} +; define <2 x half> @v_test_canonicalize_insertelement_v2f16(<2 x half> %vec, half %val, i32 %idx) { +; %vec.op = fmul <2 x half> %vec, <half 4.0, half 4.0> +; %ins.op = fmul half %val, 8.0 +; %ins = insertelement <2 x half> %vec.op, half %ins.op, i32 %idx +; %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins) +; ret <2 x half> %canonicalized +; } ; GCN-LABEL: {{^}}v_test_canonicalize_insertelement_noncanon_vec_v2f16: ; GFX9: v_mul_f16 @@ -842,15 +809,11 @@ define <2 x half> @v_test_canonicalize_insertelement_noncanon_insval_v2f16(<2 x ret <2 x half> %canonicalized } -; GCN-LABEL: {{^}}v_test_canonicalize_cvt_pkrtz: -; GCN: s_waitcnt -; GCN-NEXT: v_cvt_pkrtz_f16_f32 v0, v0, v1 -; GCN-NEXT: s_setpc_b64 -define <2 x half> @v_test_canonicalize_cvt_pkrtz(float %a, float %b) { - %cvt = call <2 x half> @llvm.amdgcn.cvt.pkrtz(float %a, float %b) - %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %cvt) - ret <2 x half> %canonicalized -} +; define <2 x half> @v_test_canonicalize_cvt_pkrtz(float %a, float %b) { +; %cvt = call <2 x half> @llvm.amdgcn.cvt.pkrtz(float %a, float %b) +; %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %cvt) +; ret <2 x half> %canonicalized +; } ; GCN-LABEL: {{^}}v_test_canonicalize_cubeid: ; GCN: s_waitcnt diff --git a/llvm/test/CodeGen/AMDGPU/fcanonicalize.f16.ll b/llvm/test/CodeGen/AMDGPU/fcanonicalize.f16.ll index 274621307f540d4c20dad406c4c93c4e89be8ac0..581b7b4cff9ed0963b3ac3e4bf74cc67bbb48f8b 100644 --- a/llvm/test/CodeGen/AMDGPU/fcanonicalize.f16.ll +++ b/llvm/test/CodeGen/AMDGPU/fcanonicalize.f16.ll @@ -94,7 +94,6 @@ define amdgpu_kernel void @v_test_canonicalize_var_f16(ptr addrspace(1) %out) #1 ; CI-NEXT: buffer_load_ushort v0, off, s[0:3], 0 ; CI-NEXT: s_waitcnt vmcnt(0) ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: buffer_store_short v0, off, s[0:3], 0 ; CI-NEXT: s_endpgm @@ -147,7 +146,6 @@ define amdgpu_kernel void @s_test_canonicalize_var_f16(ptr addrspace(1) %out, i1 ; CI-NEXT: s_waitcnt lgkmcnt(0) ; CI-NEXT: v_cvt_f32_f16_e32 v0, s2 ; CI-NEXT: s_mov_b32 s2, -1 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: buffer_store_short v0, off, s[0:3], 0 ; CI-NEXT: s_endpgm @@ -170,6 +168,35 @@ define amdgpu_kernel void @s_test_canonicalize_var_f16(ptr addrspace(1) %out, i1 ret void } +define half @s_test_canonicalize_arg(half %x) #1 { +; VI-LABEL: s_test_canonicalize_arg: +; VI: ; %bb.0: +; VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; VI-NEXT: v_max_f16_e32 v0, v0, v0 +; VI-NEXT: s_setpc_b64 s[30:31] +; +; GFX9-LABEL: s_test_canonicalize_arg: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX9-NEXT: v_max_f16_e32 v0, v0, v0 +; GFX9-NEXT: s_setpc_b64 s[30:31] +; +; CI-LABEL: s_test_canonicalize_arg: +; CI: ; %bb.0: +; CI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 +; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 +; CI-NEXT: s_setpc_b64 s[30:31] +; +; GFX11-LABEL: s_test_canonicalize_arg: +; GFX11: ; %bb.0: +; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GFX11-NEXT: v_max_f16_e32 v0, v0, v0 +; GFX11-NEXT: s_setpc_b64 s[30:31] + %canonicalized = call half @llvm.canonicalize.f16(half %x) + ret half %canonicalized +} + define <2 x half> @v_test_canonicalize_build_vector_v2f16(half %lo, half %hi) #1 { ; VI-LABEL: v_test_canonicalize_build_vector_v2f16: ; VI: ; %bb.0: @@ -242,7 +269,6 @@ define amdgpu_kernel void @v_test_canonicalize_fabs_var_f16(ptr addrspace(1) %ou ; CI-NEXT: buffer_load_ushort v0, off, s[0:3], 0 ; CI-NEXT: s_waitcnt vmcnt(0) ; CI-NEXT: v_cvt_f32_f16_e64 v0, |v0| -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: buffer_store_short v0, off, s[0:3], 0 ; CI-NEXT: s_endpgm @@ -299,7 +325,6 @@ define amdgpu_kernel void @v_test_canonicalize_fneg_fabs_var_f16(ptr addrspace(1 ; CI-NEXT: buffer_load_ushort v0, off, s[0:3], 0 ; CI-NEXT: s_waitcnt vmcnt(0) ; CI-NEXT: v_cvt_f32_f16_e64 v0, -|v0| -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: buffer_store_short v0, off, s[0:3], 0 ; CI-NEXT: s_endpgm @@ -357,7 +382,6 @@ define amdgpu_kernel void @v_test_canonicalize_fneg_var_f16(ptr addrspace(1) %ou ; CI-NEXT: buffer_load_ushort v0, off, s[0:3], 0 ; CI-NEXT: s_waitcnt vmcnt(0) ; CI-NEXT: v_cvt_f32_f16_e64 v0, -v0 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: buffer_store_short v0, off, s[0:3], 0 ; CI-NEXT: s_endpgm @@ -414,7 +438,6 @@ define amdgpu_kernel void @v_test_no_denormals_canonicalize_fneg_var_f16(ptr add ; CI-NEXT: buffer_load_ushort v0, off, s[0:3], 0 ; CI-NEXT: s_waitcnt vmcnt(0) ; CI-NEXT: v_cvt_f32_f16_e64 v0, -v0 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: buffer_store_short v0, off, s[0:3], 0 ; CI-NEXT: s_endpgm @@ -471,7 +494,6 @@ define amdgpu_kernel void @v_test_no_denormals_canonicalize_fneg_fabs_var_f16(pt ; CI-NEXT: buffer_load_ushort v0, off, s[0:3], 0 ; CI-NEXT: s_waitcnt vmcnt(0) ; CI-NEXT: v_cvt_f32_f16_e64 v0, -|v0| -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: buffer_store_short v0, off, s[0:3], 0 ; CI-NEXT: s_endpgm @@ -1246,9 +1268,7 @@ define amdgpu_kernel void @v_test_canonicalize_var_v2f16(ptr addrspace(1) %out) ; CI-NEXT: v_lshrrev_b32_e32 v1, 16, v0 ; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; CI-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 ; CI-NEXT: v_or_b32_e32 v0, v0, v1 @@ -1323,9 +1343,7 @@ define amdgpu_kernel void @v_test_canonicalize_fabs_var_v2f16(ptr addrspace(1) % ; CI-NEXT: v_lshrrev_b32_e32 v1, 16, v0 ; CI-NEXT: v_cvt_f32_f16_e64 v1, |v1| ; CI-NEXT: v_cvt_f32_f16_e64 v0, |v0| -; CI-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 ; CI-NEXT: v_or_b32_e32 v0, v0, v1 @@ -1404,9 +1422,7 @@ define amdgpu_kernel void @v_test_canonicalize_fneg_fabs_var_v2f16(ptr addrspace ; CI-NEXT: v_lshrrev_b32_e32 v1, 16, v0 ; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; CI-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 ; CI-NEXT: v_or_b32_e32 v0, v0, v1 @@ -1485,9 +1501,7 @@ define amdgpu_kernel void @v_test_canonicalize_fneg_var_v2f16(ptr addrspace(1) % ; CI-NEXT: v_lshrrev_b32_e32 v1, 16, v0 ; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; CI-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 ; CI-NEXT: v_or_b32_e32 v0, v0, v1 @@ -1551,9 +1565,7 @@ define amdgpu_kernel void @s_test_canonicalize_var_v2f16(ptr addrspace(1) %out, ; CI-NEXT: v_cvt_f32_f16_e32 v1, s2 ; CI-NEXT: s_mov_b32 s3, 0xf000 ; CI-NEXT: s_mov_b32 s2, -1 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; CI-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; CI-NEXT: v_lshlrev_b32_e32 v0, 16, v0 ; CI-NEXT: v_or_b32_e32 v0, v1, v0 @@ -2424,7 +2436,6 @@ define <2 x half> @v_test_canonicalize_reg_undef_v2f16(half %val) #1 { ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_mov_b32_e32 v1, 0x7fc00000 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: s_setpc_b64 s[30:31] ; ; GFX11-LABEL: v_test_canonicalize_reg_undef_v2f16: @@ -2456,8 +2467,7 @@ define <2 x half> @v_test_canonicalize_undef_reg_v2f16(half %val) #1 { ; CI: ; %bb.0: ; CI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; CI-NEXT: v_mul_f32_e32 v1, 1.0, v0 +; CI-NEXT: v_cvt_f32_f16_e32 v1, v0 ; CI-NEXT: v_mov_b32_e32 v0, 0x7fc00000 ; CI-NEXT: s_setpc_b64 s[30:31] ; @@ -2738,7 +2748,6 @@ define <4 x half> @v_test_canonicalize_reg_undef_undef_undef_v4f16(half %val) #1 ; CI-NEXT: v_mov_b32_e32 v2, 0x7fc00000 ; CI-NEXT: v_mov_b32_e32 v3, 0x7fc00000 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; CI-NEXT: s_setpc_b64 s[30:31] ; ; GFX11-LABEL: v_test_canonicalize_reg_undef_undef_undef_v4f16: @@ -2782,8 +2791,6 @@ define <4 x half> @v_test_canonicalize_reg_reg_undef_undef_v4f16(half %val0, hal ; CI-NEXT: v_mov_b32_e32 v3, 0x7fc00000 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; CI-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; CI-NEXT: s_setpc_b64 s[30:31] ; ; GFX11-LABEL: v_test_canonicalize_reg_reg_undef_undef_v4f16: @@ -2826,13 +2833,10 @@ define <4 x half> @v_test_canonicalize_reg_undef_reg_reg_v4f16(half %val0, half ; CI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 -; CI-NEXT: v_cvt_f16_f32_e32 v2, v2 +; CI-NEXT: v_cvt_f16_f32_e32 v3, v2 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 -; CI-NEXT: v_cvt_f32_f16_e32 v3, v2 -; CI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; CI-NEXT: v_mul_f32_e32 v2, 1.0, v1 -; CI-NEXT: v_mul_f32_e32 v3, 1.0, v3 +; CI-NEXT: v_cvt_f32_f16_e32 v2, v1 +; CI-NEXT: v_cvt_f32_f16_e32 v3, v3 ; CI-NEXT: v_mov_b32_e32 v1, 0x7fc00000 ; CI-NEXT: s_setpc_b64 s[30:31] ; @@ -2878,18 +2882,18 @@ define <6 x half> @v_test_canonicalize_var_v6f16(<6 x half> %val) #1 { ; CI-LABEL: v_test_canonicalize_var_v6f16: ; CI: ; %bb.0: ; CI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 +; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; CI-NEXT: v_cvt_f16_f32_e32 v3, v3 -; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 -; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 +; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 +; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; CI-NEXT: v_cvt_f32_f16_e32 v2, v2 ; CI-NEXT: v_cvt_f32_f16_e32 v3, v3 -; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 -; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 ; CI-NEXT: s_setpc_b64 s[30:31] ; ; GFX11-LABEL: v_test_canonicalize_var_v6f16: @@ -2933,22 +2937,22 @@ define <8 x half> @v_test_canonicalize_var_v8f16(<8 x half> %val) #1 { ; CI-LABEL: v_test_canonicalize_var_v8f16: ; CI: ; %bb.0: ; CI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 +; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 +; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 +; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; CI-NEXT: v_cvt_f16_f32_e32 v3, v3 -; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 -; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 -; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 -; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 +; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 +; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 +; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 +; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; CI-NEXT: v_cvt_f32_f16_e32 v2, v2 ; CI-NEXT: v_cvt_f32_f16_e32 v3, v3 -; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 -; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 -; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 -; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 ; CI-NEXT: s_setpc_b64 s[30:31] ; ; GFX11-LABEL: v_test_canonicalize_var_v8f16: @@ -3001,30 +3005,30 @@ define <12 x half> @v_test_canonicalize_var_v12f16(<12 x half> %val) #1 { ; CI-LABEL: v_test_canonicalize_var_v12f16: ; CI: ; %bb.0: ; CI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CI-NEXT: v_cvt_f16_f32_e32 v11, v11 +; CI-NEXT: v_cvt_f16_f32_e32 v10, v10 +; CI-NEXT: v_cvt_f16_f32_e32 v9, v9 +; CI-NEXT: v_cvt_f16_f32_e32 v8, v8 +; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 +; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 +; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 +; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; CI-NEXT: v_cvt_f16_f32_e32 v3, v3 -; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 -; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 -; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 -; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 -; CI-NEXT: v_cvt_f16_f32_e32 v8, v8 -; CI-NEXT: v_cvt_f16_f32_e32 v9, v9 -; CI-NEXT: v_cvt_f16_f32_e32 v10, v10 -; CI-NEXT: v_cvt_f16_f32_e32 v11, v11 +; CI-NEXT: v_cvt_f32_f16_e32 v11, v11 +; CI-NEXT: v_cvt_f32_f16_e32 v10, v10 +; CI-NEXT: v_cvt_f32_f16_e32 v9, v9 +; CI-NEXT: v_cvt_f32_f16_e32 v8, v8 +; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 +; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 +; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 +; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; CI-NEXT: v_cvt_f32_f16_e32 v2, v2 ; CI-NEXT: v_cvt_f32_f16_e32 v3, v3 -; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 -; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 -; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 -; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 -; CI-NEXT: v_cvt_f32_f16_e32 v8, v8 -; CI-NEXT: v_cvt_f32_f16_e32 v9, v9 -; CI-NEXT: v_cvt_f32_f16_e32 v10, v10 -; CI-NEXT: v_cvt_f32_f16_e32 v11, v11 ; CI-NEXT: s_setpc_b64 s[30:31] ; ; GFX11-LABEL: v_test_canonicalize_var_v12f16: @@ -3087,38 +3091,38 @@ define <16 x half> @v_test_canonicalize_var_v16f16(<16 x half> %val) #1 { ; CI-LABEL: v_test_canonicalize_var_v16f16: ; CI: ; %bb.0: ; CI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CI-NEXT: v_cvt_f16_f32_e32 v15, v15 +; CI-NEXT: v_cvt_f16_f32_e32 v14, v14 +; CI-NEXT: v_cvt_f16_f32_e32 v13, v13 +; CI-NEXT: v_cvt_f16_f32_e32 v12, v12 +; CI-NEXT: v_cvt_f16_f32_e32 v11, v11 +; CI-NEXT: v_cvt_f16_f32_e32 v10, v10 +; CI-NEXT: v_cvt_f16_f32_e32 v9, v9 +; CI-NEXT: v_cvt_f16_f32_e32 v8, v8 +; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 +; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 +; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 +; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; CI-NEXT: v_cvt_f16_f32_e32 v3, v3 -; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 -; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 -; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 -; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 -; CI-NEXT: v_cvt_f16_f32_e32 v8, v8 -; CI-NEXT: v_cvt_f16_f32_e32 v9, v9 -; CI-NEXT: v_cvt_f16_f32_e32 v10, v10 -; CI-NEXT: v_cvt_f16_f32_e32 v11, v11 -; CI-NEXT: v_cvt_f16_f32_e32 v12, v12 -; CI-NEXT: v_cvt_f16_f32_e32 v13, v13 -; CI-NEXT: v_cvt_f16_f32_e32 v14, v14 -; CI-NEXT: v_cvt_f16_f32_e32 v15, v15 +; CI-NEXT: v_cvt_f32_f16_e32 v15, v15 +; CI-NEXT: v_cvt_f32_f16_e32 v14, v14 +; CI-NEXT: v_cvt_f32_f16_e32 v13, v13 +; CI-NEXT: v_cvt_f32_f16_e32 v12, v12 +; CI-NEXT: v_cvt_f32_f16_e32 v11, v11 +; CI-NEXT: v_cvt_f32_f16_e32 v10, v10 +; CI-NEXT: v_cvt_f32_f16_e32 v9, v9 +; CI-NEXT: v_cvt_f32_f16_e32 v8, v8 +; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 +; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 +; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 +; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; CI-NEXT: v_cvt_f32_f16_e32 v2, v2 ; CI-NEXT: v_cvt_f32_f16_e32 v3, v3 -; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 -; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 -; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 -; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 -; CI-NEXT: v_cvt_f32_f16_e32 v8, v8 -; CI-NEXT: v_cvt_f32_f16_e32 v9, v9 -; CI-NEXT: v_cvt_f32_f16_e32 v10, v10 -; CI-NEXT: v_cvt_f32_f16_e32 v11, v11 -; CI-NEXT: v_cvt_f32_f16_e32 v12, v12 -; CI-NEXT: v_cvt_f32_f16_e32 v13, v13 -; CI-NEXT: v_cvt_f32_f16_e32 v14, v14 -; CI-NEXT: v_cvt_f32_f16_e32 v15, v15 ; CI-NEXT: s_setpc_b64 s[30:31] ; ; GFX11-LABEL: v_test_canonicalize_var_v16f16: @@ -3216,68 +3220,68 @@ define <32 x half> @v_test_canonicalize_var_v32f16(<32 x half> %val) #1 { ; CI: ; %bb.0: ; CI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; CI-NEXT: buffer_load_dword v31, off, s[0:3], s32 +; CI-NEXT: v_cvt_f16_f32_e32 v30, v30 +; CI-NEXT: v_cvt_f16_f32_e32 v29, v29 +; CI-NEXT: v_cvt_f16_f32_e32 v28, v28 +; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 +; CI-NEXT: v_cvt_f16_f32_e32 v26, v26 +; CI-NEXT: v_cvt_f16_f32_e32 v25, v25 +; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 +; CI-NEXT: v_cvt_f16_f32_e32 v23, v23 +; CI-NEXT: v_cvt_f16_f32_e32 v22, v22 +; CI-NEXT: v_cvt_f16_f32_e32 v21, v21 +; CI-NEXT: v_cvt_f16_f32_e32 v20, v20 +; CI-NEXT: v_cvt_f16_f32_e32 v19, v19 +; CI-NEXT: v_cvt_f16_f32_e32 v18, v18 +; CI-NEXT: v_cvt_f16_f32_e32 v17, v17 +; CI-NEXT: v_cvt_f16_f32_e32 v16, v16 +; CI-NEXT: v_cvt_f16_f32_e32 v15, v15 +; CI-NEXT: v_cvt_f16_f32_e32 v14, v14 +; CI-NEXT: v_cvt_f16_f32_e32 v13, v13 +; CI-NEXT: v_cvt_f16_f32_e32 v12, v12 +; CI-NEXT: v_cvt_f16_f32_e32 v11, v11 +; CI-NEXT: v_cvt_f16_f32_e32 v10, v10 +; CI-NEXT: v_cvt_f16_f32_e32 v9, v9 +; CI-NEXT: v_cvt_f16_f32_e32 v8, v8 +; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 +; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 +; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 +; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 ; CI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; CI-NEXT: v_cvt_f16_f32_e32 v3, v3 -; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 -; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 -; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 -; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 -; CI-NEXT: v_cvt_f16_f32_e32 v8, v8 -; CI-NEXT: v_cvt_f16_f32_e32 v9, v9 -; CI-NEXT: v_cvt_f16_f32_e32 v10, v10 -; CI-NEXT: v_cvt_f16_f32_e32 v11, v11 -; CI-NEXT: v_cvt_f16_f32_e32 v12, v12 -; CI-NEXT: v_cvt_f16_f32_e32 v13, v13 -; CI-NEXT: v_cvt_f16_f32_e32 v14, v14 -; CI-NEXT: v_cvt_f16_f32_e32 v15, v15 -; CI-NEXT: v_cvt_f16_f32_e32 v16, v16 -; CI-NEXT: v_cvt_f16_f32_e32 v17, v17 -; CI-NEXT: v_cvt_f16_f32_e32 v18, v18 -; CI-NEXT: v_cvt_f16_f32_e32 v19, v19 -; CI-NEXT: v_cvt_f16_f32_e32 v20, v20 -; CI-NEXT: v_cvt_f16_f32_e32 v21, v21 -; CI-NEXT: v_cvt_f16_f32_e32 v22, v22 -; CI-NEXT: v_cvt_f16_f32_e32 v23, v23 -; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 -; CI-NEXT: v_cvt_f16_f32_e32 v25, v25 -; CI-NEXT: v_cvt_f16_f32_e32 v26, v26 -; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 -; CI-NEXT: v_cvt_f16_f32_e32 v28, v28 -; CI-NEXT: v_cvt_f16_f32_e32 v29, v29 -; CI-NEXT: v_cvt_f16_f32_e32 v30, v30 +; CI-NEXT: v_cvt_f32_f16_e32 v30, v30 +; CI-NEXT: v_cvt_f32_f16_e32 v29, v29 +; CI-NEXT: v_cvt_f32_f16_e32 v28, v28 +; CI-NEXT: v_cvt_f32_f16_e32 v27, v27 +; CI-NEXT: v_cvt_f32_f16_e32 v26, v26 +; CI-NEXT: v_cvt_f32_f16_e32 v25, v25 +; CI-NEXT: v_cvt_f32_f16_e32 v24, v24 +; CI-NEXT: v_cvt_f32_f16_e32 v23, v23 +; CI-NEXT: v_cvt_f32_f16_e32 v22, v22 +; CI-NEXT: v_cvt_f32_f16_e32 v21, v21 +; CI-NEXT: v_cvt_f32_f16_e32 v20, v20 +; CI-NEXT: v_cvt_f32_f16_e32 v19, v19 +; CI-NEXT: v_cvt_f32_f16_e32 v18, v18 +; CI-NEXT: v_cvt_f32_f16_e32 v17, v17 +; CI-NEXT: v_cvt_f32_f16_e32 v16, v16 +; CI-NEXT: v_cvt_f32_f16_e32 v15, v15 +; CI-NEXT: v_cvt_f32_f16_e32 v14, v14 +; CI-NEXT: v_cvt_f32_f16_e32 v13, v13 +; CI-NEXT: v_cvt_f32_f16_e32 v12, v12 +; CI-NEXT: v_cvt_f32_f16_e32 v11, v11 +; CI-NEXT: v_cvt_f32_f16_e32 v10, v10 +; CI-NEXT: v_cvt_f32_f16_e32 v9, v9 +; CI-NEXT: v_cvt_f32_f16_e32 v8, v8 +; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 +; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 +; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 +; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 ; CI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; CI-NEXT: v_cvt_f32_f16_e32 v2, v2 ; CI-NEXT: v_cvt_f32_f16_e32 v3, v3 -; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 -; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 -; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 -; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 -; CI-NEXT: v_cvt_f32_f16_e32 v8, v8 -; CI-NEXT: v_cvt_f32_f16_e32 v9, v9 -; CI-NEXT: v_cvt_f32_f16_e32 v10, v10 -; CI-NEXT: v_cvt_f32_f16_e32 v11, v11 -; CI-NEXT: v_cvt_f32_f16_e32 v12, v12 -; CI-NEXT: v_cvt_f32_f16_e32 v13, v13 -; CI-NEXT: v_cvt_f32_f16_e32 v14, v14 -; CI-NEXT: v_cvt_f32_f16_e32 v15, v15 -; CI-NEXT: v_cvt_f32_f16_e32 v16, v16 -; CI-NEXT: v_cvt_f32_f16_e32 v17, v17 -; CI-NEXT: v_cvt_f32_f16_e32 v18, v18 -; CI-NEXT: v_cvt_f32_f16_e32 v19, v19 -; CI-NEXT: v_cvt_f32_f16_e32 v20, v20 -; CI-NEXT: v_cvt_f32_f16_e32 v21, v21 -; CI-NEXT: v_cvt_f32_f16_e32 v22, v22 -; CI-NEXT: v_cvt_f32_f16_e32 v23, v23 -; CI-NEXT: v_cvt_f32_f16_e32 v24, v24 -; CI-NEXT: v_cvt_f32_f16_e32 v25, v25 -; CI-NEXT: v_cvt_f32_f16_e32 v26, v26 -; CI-NEXT: v_cvt_f32_f16_e32 v27, v27 -; CI-NEXT: v_cvt_f32_f16_e32 v28, v28 -; CI-NEXT: v_cvt_f32_f16_e32 v29, v29 -; CI-NEXT: v_cvt_f32_f16_e32 v30, v30 ; CI-NEXT: s_waitcnt vmcnt(0) ; CI-NEXT: v_cvt_f16_f32_e32 v31, v31 ; CI-NEXT: v_cvt_f32_f16_e32 v31, v31 @@ -3456,228 +3460,354 @@ define <64 x half> @v_test_canonicalize_var_v64f16(<64 x half> %val) #1 { ; CI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; CI-NEXT: v_cvt_f16_f32_e32 v3, v3 +; CI-NEXT: buffer_load_dword v31, off, s[0:3], s32 offset:104 +; CI-NEXT: buffer_load_dword v32, off, s[0:3], s32 offset:108 +; CI-NEXT: v_cvt_f32_f16_e32 v2, v2 +; CI-NEXT: v_cvt_f32_f16_e32 v1, v1 +; CI-NEXT: v_cvt_f32_f16_e32 v3, v3 +; CI-NEXT: v_cvt_f16_f32_e32 v2, v2 +; CI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; CI-NEXT: v_cvt_f16_f32_e32 v3, v3 ; CI-NEXT: v_lshlrev_b32_e32 v2, 16, v2 ; CI-NEXT: v_or_b32_e32 v1, v1, v2 ; CI-NEXT: v_cvt_f16_f32_e32 v2, v4 ; CI-NEXT: v_cvt_f16_f32_e32 v4, v5 ; CI-NEXT: v_cvt_f16_f32_e32 v5, v7 ; CI-NEXT: v_cvt_f16_f32_e32 v7, v9 +; CI-NEXT: v_cvt_f32_f16_e32 v2, v2 +; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 +; CI-NEXT: v_cvt_f32_f16_e32 v5, v5 +; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 +; CI-NEXT: v_cvt_f16_f32_e32 v2, v2 +; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 +; CI-NEXT: v_cvt_f16_f32_e32 v5, v5 +; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 ; CI-NEXT: v_lshlrev_b32_e32 v2, 16, v2 ; CI-NEXT: v_or_b32_e32 v2, v3, v2 ; CI-NEXT: v_cvt_f16_f32_e32 v3, v6 ; CI-NEXT: v_cvt_f16_f32_e32 v6, v10 ; CI-NEXT: v_cvt_f16_f32_e32 v9, v13 -; CI-NEXT: v_cvt_f16_f32_e32 v10, v18 +; CI-NEXT: v_cvt_f16_f32_e32 v10, v16 +; CI-NEXT: v_cvt_f32_f16_e32 v3, v3 +; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 +; CI-NEXT: v_cvt_f32_f16_e32 v9, v9 +; CI-NEXT: v_cvt_f16_f32_e32 v13, v17 +; CI-NEXT: v_cvt_f16_f32_e32 v3, v3 +; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 +; CI-NEXT: v_cvt_f16_f32_e32 v9, v9 +; CI-NEXT: v_cvt_f32_f16_e32 v13, v13 ; CI-NEXT: v_lshlrev_b32_e32 v3, 16, v3 ; CI-NEXT: v_or_b32_e32 v3, v4, v3 ; CI-NEXT: v_cvt_f16_f32_e32 v4, v8 ; CI-NEXT: v_cvt_f16_f32_e32 v8, v14 -; CI-NEXT: v_cvt_f16_f32_e32 v13, v21 -; CI-NEXT: v_cvt_f16_f32_e32 v14, v26 +; CI-NEXT: buffer_load_dword v14, off, s[0:3], s32 +; CI-NEXT: buffer_load_dword v33, off, s[0:3], s32 offset:4 +; CI-NEXT: v_cvt_f16_f32_e32 v17, v23 +; CI-NEXT: v_cvt_f32_f16_e32 v4, v4 +; CI-NEXT: v_cvt_f32_f16_e32 v8, v8 +; CI-NEXT: v_cvt_f32_f16_e32 v17, v17 +; CI-NEXT: v_cvt_f16_f32_e32 v4, v4 +; CI-NEXT: v_cvt_f16_f32_e32 v8, v8 ; CI-NEXT: v_lshlrev_b32_e32 v4, 16, v4 ; CI-NEXT: v_or_b32_e32 v4, v5, v4 ; CI-NEXT: v_lshlrev_b32_e32 v5, 16, v6 ; CI-NEXT: v_cvt_f16_f32_e32 v6, v12 ; CI-NEXT: v_or_b32_e32 v5, v7, v5 ; CI-NEXT: v_cvt_f16_f32_e32 v7, v11 -; CI-NEXT: v_cvt_f16_f32_e32 v11, v17 +; CI-NEXT: v_cvt_f16_f32_e32 v11, v15 +; CI-NEXT: v_cvt_f32_f16_e32 v6, v6 +; CI-NEXT: v_cvt_f16_f32_e32 v15, v21 +; CI-NEXT: v_cvt_f32_f16_e32 v7, v7 +; CI-NEXT: v_cvt_f16_f32_e32 v6, v6 +; CI-NEXT: v_cvt_f16_f32_e32 v7, v7 ; CI-NEXT: v_lshlrev_b32_e32 v6, 16, v6 -; CI-NEXT: v_cvt_f16_f32_e32 v12, v22 ; CI-NEXT: v_or_b32_e32 v6, v7, v6 ; CI-NEXT: v_lshlrev_b32_e32 v7, 16, v8 -; CI-NEXT: v_cvt_f16_f32_e32 v8, v16 +; CI-NEXT: v_cvt_f16_f32_e32 v8, v19 ; CI-NEXT: v_or_b32_e32 v7, v9, v7 -; CI-NEXT: v_cvt_f16_f32_e32 v9, v15 -; CI-NEXT: v_cvt_f16_f32_e32 v15, v25 +; CI-NEXT: v_cvt_f16_f32_e32 v9, v20 +; CI-NEXT: v_cvt_f32_f16_e32 v12, v8 +; CI-NEXT: v_cvt_f32_f16_e32 v8, v10 +; CI-NEXT: v_cvt_f32_f16_e32 v10, v11 +; CI-NEXT: v_cvt_f16_f32_e32 v11, v18 +; CI-NEXT: buffer_load_dword v18, off, s[0:3], s32 offset:124 +; CI-NEXT: buffer_load_dword v19, off, s[0:3], s32 offset:112 +; CI-NEXT: buffer_load_dword v20, off, s[0:3], s32 offset:116 +; CI-NEXT: v_cvt_f16_f32_e32 v8, v8 +; CI-NEXT: v_cvt_f16_f32_e32 v10, v10 +; CI-NEXT: v_cvt_f32_f16_e32 v11, v11 +; CI-NEXT: v_cvt_f32_f16_e32 v9, v9 ; CI-NEXT: v_lshlrev_b32_e32 v8, 16, v8 -; CI-NEXT: v_cvt_f16_f32_e32 v25, v29 -; CI-NEXT: v_or_b32_e32 v8, v9, v8 +; CI-NEXT: v_or_b32_e32 v8, v10, v8 +; CI-NEXT: v_cvt_f16_f32_e32 v10, v11 +; CI-NEXT: v_cvt_f16_f32_e32 v11, v13 +; CI-NEXT: v_cvt_f16_f32_e32 v13, v9 +; CI-NEXT: v_cvt_f16_f32_e32 v12, v12 ; CI-NEXT: v_lshlrev_b32_e32 v9, 16, v10 -; CI-NEXT: v_cvt_f16_f32_e32 v10, v20 ; CI-NEXT: v_or_b32_e32 v9, v11, v9 -; CI-NEXT: v_cvt_f16_f32_e32 v11, v19 -; CI-NEXT: buffer_load_dword v16, off, s[0:3], s32 offset:4 -; CI-NEXT: buffer_load_dword v17, off, s[0:3], s32 -; CI-NEXT: buffer_load_dword v18, off, s[0:3], s32 offset:12 -; CI-NEXT: buffer_load_dword v19, off, s[0:3], s32 offset:8 -; CI-NEXT: v_lshlrev_b32_e32 v10, 16, v10 -; CI-NEXT: v_or_b32_e32 v10, v11, v10 -; CI-NEXT: v_lshlrev_b32_e32 v11, 16, v12 -; CI-NEXT: v_cvt_f16_f32_e32 v12, v24 +; CI-NEXT: v_lshlrev_b32_e32 v10, 16, v13 +; CI-NEXT: v_cvt_f16_f32_e32 v11, v25 +; CI-NEXT: v_cvt_f16_f32_e32 v13, v22 +; CI-NEXT: v_or_b32_e32 v10, v12, v10 +; CI-NEXT: v_cvt_f16_f32_e32 v12, v26 +; CI-NEXT: v_cvt_f32_f16_e32 v16, v11 +; CI-NEXT: v_cvt_f32_f16_e32 v11, v13 +; CI-NEXT: v_cvt_f32_f16_e32 v13, v15 +; CI-NEXT: v_cvt_f16_f32_e32 v15, v24 +; CI-NEXT: v_cvt_f32_f16_e32 v12, v12 +; CI-NEXT: v_cvt_f16_f32_e32 v11, v11 +; CI-NEXT: v_cvt_f16_f32_e32 v13, v13 +; CI-NEXT: v_cvt_f32_f16_e32 v15, v15 +; CI-NEXT: v_cvt_f16_f32_e32 v22, v30 +; CI-NEXT: v_lshlrev_b32_e32 v11, 16, v11 ; CI-NEXT: v_or_b32_e32 v11, v13, v11 -; CI-NEXT: v_cvt_f16_f32_e32 v13, v23 -; CI-NEXT: buffer_load_dword v20, off, s[0:3], s32 offset:20 -; CI-NEXT: buffer_load_dword v21, off, s[0:3], s32 offset:16 -; CI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:28 -; CI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:24 -; CI-NEXT: v_lshlrev_b32_e32 v12, 16, v12 -; CI-NEXT: v_cvt_f16_f32_e32 v24, v30 -; CI-NEXT: v_or_b32_e32 v12, v13, v12 -; CI-NEXT: v_lshlrev_b32_e32 v13, 16, v14 -; CI-NEXT: v_or_b32_e32 v13, v15, v13 -; CI-NEXT: v_cvt_f16_f32_e32 v14, v28 +; CI-NEXT: v_cvt_f16_f32_e32 v13, v15 +; CI-NEXT: v_cvt_f16_f32_e32 v15, v17 +; CI-NEXT: v_cvt_f16_f32_e32 v17, v12 +; CI-NEXT: v_cvt_f16_f32_e32 v25, v29 +; CI-NEXT: v_lshlrev_b32_e32 v12, 16, v13 +; CI-NEXT: v_or_b32_e32 v12, v15, v12 +; CI-NEXT: s_waitcnt vmcnt(6) +; CI-NEXT: v_cvt_f16_f32_e32 v15, v31 +; CI-NEXT: v_lshlrev_b32_e32 v13, 16, v17 +; CI-NEXT: buffer_load_dword v17, off, s[0:3], s32 offset:128 +; CI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:132 +; CI-NEXT: buffer_load_dword v34, off, s[0:3], s32 offset:120 +; CI-NEXT: v_cvt_f32_f16_e32 v22, v22 +; CI-NEXT: v_cvt_f32_f16_e32 v23, v15 ; CI-NEXT: v_cvt_f16_f32_e32 v15, v27 -; CI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:36 -; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:32 -; CI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:44 -; CI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:40 +; CI-NEXT: v_cvt_f32_f16_e32 v25, v25 +; CI-NEXT: s_waitcnt vmcnt(7) +; CI-NEXT: v_cvt_f16_f32_e32 v14, v14 +; CI-NEXT: s_waitcnt vmcnt(6) +; CI-NEXT: v_cvt_f16_f32_e32 v21, v33 +; CI-NEXT: v_cvt_f32_f16_e32 v15, v15 +; CI-NEXT: v_cvt_f16_f32_e32 v22, v22 +; CI-NEXT: v_cvt_f32_f16_e32 v24, v14 +; CI-NEXT: v_cvt_f16_f32_e32 v14, v28 +; CI-NEXT: v_cvt_f16_f32_e32 v15, v15 +; CI-NEXT: v_cvt_f32_f16_e32 v21, v21 +; CI-NEXT: v_cvt_f16_f32_e32 v25, v25 +; CI-NEXT: v_cvt_f32_f16_e32 v14, v14 +; CI-NEXT: v_cvt_f16_f32_e32 v16, v16 +; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 +; CI-NEXT: v_cvt_f16_f32_e32 v28, v23 +; CI-NEXT: v_cvt_f16_f32_e32 v14, v14 +; CI-NEXT: v_or_b32_e32 v13, v16, v13 +; CI-NEXT: v_cvt_f16_f32_e32 v16, v32 +; CI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:12 ; CI-NEXT: v_lshlrev_b32_e32 v14, 16, v14 ; CI-NEXT: v_or_b32_e32 v14, v15, v14 -; CI-NEXT: v_lshlrev_b32_e32 v15, 16, v24 +; CI-NEXT: v_lshlrev_b32_e32 v15, 16, v22 ; CI-NEXT: v_or_b32_e32 v15, v25, v15 -; CI-NEXT: s_waitcnt vmcnt(11) -; CI-NEXT: v_cvt_f16_f32_e32 v16, v16 -; CI-NEXT: s_waitcnt vmcnt(10) -; CI-NEXT: v_cvt_f16_f32_e32 v17, v17 +; CI-NEXT: v_cvt_f16_f32_e32 v25, v21 +; CI-NEXT: buffer_load_dword v21, off, s[0:3], s32 offset:96 +; CI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:100 +; CI-NEXT: v_cvt_f32_f16_e32 v16, v16 +; CI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:64 +; CI-NEXT: v_lshlrev_b32_e32 v25, 16, v25 +; CI-NEXT: v_cvt_f16_f32_e32 v27, v16 +; CI-NEXT: v_or_b32_e32 v16, v24, v25 +; CI-NEXT: v_lshlrev_b32_e32 v24, 16, v27 +; CI-NEXT: v_or_b32_e32 v25, v28, v24 ; CI-NEXT: s_waitcnt vmcnt(9) ; CI-NEXT: v_cvt_f16_f32_e32 v18, v18 ; CI-NEXT: s_waitcnt vmcnt(8) ; CI-NEXT: v_cvt_f16_f32_e32 v19, v19 -; CI-NEXT: v_lshlrev_b32_e32 v16, 16, v16 -; CI-NEXT: v_or_b32_e32 v16, v17, v16 -; CI-NEXT: v_lshlrev_b32_e32 v17, 16, v18 -; CI-NEXT: v_or_b32_e32 v17, v19, v17 ; CI-NEXT: s_waitcnt vmcnt(7) -; CI-NEXT: v_cvt_f16_f32_e32 v18, v20 +; CI-NEXT: v_cvt_f16_f32_e32 v20, v20 +; CI-NEXT: v_cvt_f32_f16_e32 v18, v18 +; CI-NEXT: v_cvt_f32_f16_e32 v19, v19 +; CI-NEXT: v_cvt_f32_f16_e32 v20, v20 +; CI-NEXT: v_cvt_f16_f32_e32 v18, v18 +; CI-NEXT: v_cvt_f16_f32_e32 v19, v19 +; CI-NEXT: v_cvt_f16_f32_e32 v20, v20 +; CI-NEXT: v_lshlrev_b32_e32 v18, 16, v18 +; CI-NEXT: v_lshlrev_b32_e32 v20, 16, v20 +; CI-NEXT: v_or_b32_e32 v20, v19, v20 +; CI-NEXT: buffer_load_dword v19, off, s[0:3], s32 offset:20 +; CI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:8 +; CI-NEXT: s_waitcnt vmcnt(8) +; CI-NEXT: v_cvt_f16_f32_e32 v17, v17 +; CI-NEXT: s_waitcnt vmcnt(7) +; CI-NEXT: v_cvt_f16_f32_e32 v26, v26 ; CI-NEXT: s_waitcnt vmcnt(6) -; CI-NEXT: v_cvt_f16_f32_e32 v19, v21 -; CI-NEXT: s_waitcnt vmcnt(5) +; CI-NEXT: v_cvt_f16_f32_e32 v27, v34 +; CI-NEXT: v_cvt_f32_f16_e32 v17, v17 +; CI-NEXT: v_cvt_f32_f16_e32 v26, v26 +; CI-NEXT: v_cvt_f32_f16_e32 v27, v27 +; CI-NEXT: v_cvt_f16_f32_e32 v17, v17 +; CI-NEXT: v_cvt_f16_f32_e32 v26, v26 +; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 +; CI-NEXT: v_lshlrev_b32_e32 v26, 16, v26 +; CI-NEXT: v_or_b32_e32 v17, v17, v26 +; CI-NEXT: v_add_i32_e32 v26, vcc, 0x7c, v0 +; CI-NEXT: v_or_b32_e32 v18, v27, v18 +; CI-NEXT: buffer_store_dword v17, v26, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x78, v0 +; CI-NEXT: buffer_store_dword v18, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x74, v0 +; CI-NEXT: buffer_store_dword v20, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x70, v0 +; CI-NEXT: buffer_store_dword v25, v17, s[0:3], 0 offen +; CI-NEXT: s_waitcnt vmcnt(8) +; CI-NEXT: v_cvt_f16_f32_e32 v21, v21 +; CI-NEXT: s_waitcnt vmcnt(7) ; CI-NEXT: v_cvt_f16_f32_e32 v20, v22 -; CI-NEXT: s_waitcnt vmcnt(4) -; CI-NEXT: v_cvt_f16_f32_e32 v21, v23 -; CI-NEXT: v_lshlrev_b32_e32 v18, 16, v18 -; CI-NEXT: v_or_b32_e32 v18, v19, v18 -; CI-NEXT: v_lshlrev_b32_e32 v19, 16, v20 -; CI-NEXT: v_or_b32_e32 v19, v21, v19 -; CI-NEXT: s_waitcnt vmcnt(3) -; CI-NEXT: v_cvt_f16_f32_e32 v20, v26 -; CI-NEXT: s_waitcnt vmcnt(2) -; CI-NEXT: v_cvt_f16_f32_e32 v21, v27 -; CI-NEXT: s_waitcnt vmcnt(1) -; CI-NEXT: v_cvt_f16_f32_e32 v26, v28 -; CI-NEXT: s_waitcnt vmcnt(0) -; CI-NEXT: v_cvt_f16_f32_e32 v27, v29 +; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:88 +; CI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:92 +; CI-NEXT: buffer_load_dword v17, off, s[0:3], s32 offset:80 +; CI-NEXT: buffer_load_dword v18, off, s[0:3], s32 offset:84 +; CI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:72 +; CI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:76 +; CI-NEXT: v_cvt_f16_f32_e32 v22, v23 +; CI-NEXT: v_cvt_f32_f16_e32 v21, v21 +; CI-NEXT: v_cvt_f32_f16_e32 v20, v20 +; CI-NEXT: s_waitcnt vmcnt(12) +; CI-NEXT: v_cvt_f16_f32_e32 v29, v29 +; CI-NEXT: v_cvt_f32_f16_e32 v22, v22 +; CI-NEXT: v_cvt_f16_f32_e32 v21, v21 +; CI-NEXT: v_cvt_f16_f32_e32 v20, v20 +; CI-NEXT: v_cvt_f32_f16_e32 v29, v29 +; CI-NEXT: v_cvt_f16_f32_e32 v22, v22 ; CI-NEXT: v_lshlrev_b32_e32 v20, 16, v20 ; CI-NEXT: v_or_b32_e32 v20, v21, v20 -; CI-NEXT: v_lshlrev_b32_e32 v21, 16, v26 -; CI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:52 -; CI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:48 -; CI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:60 -; CI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:56 -; CI-NEXT: v_or_b32_e32 v21, v27, v21 -; CI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:132 -; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:128 -; CI-NEXT: s_waitcnt vmcnt(5) -; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 -; CI-NEXT: s_waitcnt vmcnt(4) -; CI-NEXT: v_cvt_f16_f32_e32 v25, v25 -; CI-NEXT: s_waitcnt vmcnt(3) +; CI-NEXT: v_add_i32_e32 v21, vcc, 0x6c, v0 +; CI-NEXT: buffer_store_dword v20, v21, s[0:3], 0 offen +; CI-NEXT: v_lshlrev_b32_e32 v20, 16, v22 +; CI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:24 +; CI-NEXT: v_cvt_f16_f32_e32 v29, v29 +; CI-NEXT: s_waitcnt vmcnt(13) +; CI-NEXT: v_cvt_f16_f32_e32 v19, v19 +; CI-NEXT: s_waitcnt vmcnt(12) +; CI-NEXT: v_cvt_f16_f32_e32 v23, v24 +; CI-NEXT: buffer_load_dword v21, off, s[0:3], s32 offset:28 +; CI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:16 +; CI-NEXT: v_cvt_f32_f16_e32 v19, v19 +; CI-NEXT: v_cvt_f32_f16_e32 v23, v23 +; CI-NEXT: v_cvt_f16_f32_e32 v19, v19 ; CI-NEXT: v_cvt_f16_f32_e32 v23, v23 -; CI-NEXT: s_waitcnt vmcnt(2) -; CI-NEXT: v_cvt_f16_f32_e32 v22, v22 -; CI-NEXT: s_waitcnt vmcnt(1) +; CI-NEXT: v_lshlrev_b32_e32 v19, 16, v19 +; CI-NEXT: v_or_b32_e32 v20, v23, v20 +; CI-NEXT: s_waitcnt vmcnt(9) +; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 +; CI-NEXT: s_waitcnt vmcnt(8) +; CI-NEXT: v_cvt_f16_f32_e32 v23, v28 +; CI-NEXT: s_waitcnt vmcnt(7) +; CI-NEXT: v_cvt_f16_f32_e32 v17, v17 +; CI-NEXT: s_waitcnt vmcnt(6) +; CI-NEXT: v_cvt_f16_f32_e32 v18, v18 +; CI-NEXT: v_cvt_f32_f16_e32 v27, v27 +; CI-NEXT: v_cvt_f32_f16_e32 v23, v23 +; CI-NEXT: s_waitcnt vmcnt(4) ; CI-NEXT: v_cvt_f16_f32_e32 v26, v26 -; CI-NEXT: s_waitcnt vmcnt(0) +; CI-NEXT: v_cvt_f16_f32_e32 v25, v25 ; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 -; CI-NEXT: v_lshlrev_b32_e32 v24, 16, v24 -; CI-NEXT: v_or_b32_e32 v24, v25, v24 -; CI-NEXT: v_lshlrev_b32_e32 v26, 16, v26 -; CI-NEXT: v_or_b32_e32 v26, v27, v26 -; CI-NEXT: v_add_i32_e32 v27, vcc, 0x7c, v0 -; CI-NEXT: buffer_store_dword v26, v27, s[0:3], 0 offen -; CI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:124 -; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:120 +; CI-NEXT: v_cvt_f16_f32_e32 v23, v23 +; CI-NEXT: v_cvt_f32_f16_e32 v18, v18 +; CI-NEXT: v_cvt_f32_f16_e32 v26, v26 +; CI-NEXT: v_cvt_f32_f16_e32 v17, v17 ; CI-NEXT: v_lshlrev_b32_e32 v23, 16, v23 -; CI-NEXT: v_or_b32_e32 v22, v22, v23 -; CI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:88 -; CI-NEXT: s_waitcnt vmcnt(2) +; CI-NEXT: v_or_b32_e32 v23, v27, v23 +; CI-NEXT: v_add_i32_e32 v27, vcc, 0x68, v0 +; CI-NEXT: buffer_store_dword v23, v27, s[0:3], 0 offen +; CI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:32 +; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:36 +; CI-NEXT: v_cvt_f32_f16_e32 v25, v25 +; CI-NEXT: v_cvt_f16_f32_e32 v18, v18 ; CI-NEXT: v_cvt_f16_f32_e32 v26, v26 -; CI-NEXT: s_waitcnt vmcnt(1) -; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 +; CI-NEXT: v_cvt_f16_f32_e32 v17, v17 +; CI-NEXT: v_cvt_f16_f32_e32 v25, v25 +; CI-NEXT: v_lshlrev_b32_e32 v18, 16, v18 ; CI-NEXT: v_lshlrev_b32_e32 v26, 16, v26 -; CI-NEXT: v_or_b32_e32 v26, v27, v26 -; CI-NEXT: v_add_i32_e32 v27, vcc, 0x78, v0 -; CI-NEXT: buffer_store_dword v26, v27, s[0:3], 0 offen -; CI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:116 -; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:112 -; CI-NEXT: s_waitcnt vmcnt(3) +; CI-NEXT: v_or_b32_e32 v17, v17, v18 +; CI-NEXT: v_add_i32_e32 v18, vcc, 0x64, v0 +; CI-NEXT: v_or_b32_e32 v25, v25, v26 +; CI-NEXT: buffer_store_dword v17, v18, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x60, v0 +; CI-NEXT: buffer_store_dword v25, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x5c, v0 +; CI-NEXT: s_waitcnt vmcnt(5) +; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 +; CI-NEXT: v_cvt_f16_f32_e32 v21, v21 +; CI-NEXT: v_cvt_f32_f16_e32 v24, v24 +; CI-NEXT: v_cvt_f32_f16_e32 v21, v21 +; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 +; CI-NEXT: v_cvt_f16_f32_e32 v21, v21 +; CI-NEXT: v_or_b32_e32 v19, v24, v19 +; CI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:44 +; CI-NEXT: v_cvt_f16_f32_e32 v22, v22 +; CI-NEXT: v_lshlrev_b32_e32 v21, 16, v21 +; CI-NEXT: v_cvt_f32_f16_e32 v22, v22 +; CI-NEXT: v_cvt_f16_f32_e32 v22, v22 +; CI-NEXT: v_or_b32_e32 v21, v22, v21 +; CI-NEXT: buffer_load_dword v22, off, s[0:3], s32 offset:40 +; CI-NEXT: s_waitcnt vmcnt(5) +; CI-NEXT: v_cvt_f16_f32_e32 v23, v23 +; CI-NEXT: s_waitcnt vmcnt(4) +; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 +; CI-NEXT: v_cvt_f32_f16_e32 v23, v23 +; CI-NEXT: v_cvt_f32_f16_e32 v27, v27 ; CI-NEXT: v_cvt_f16_f32_e32 v23, v23 +; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 +; CI-NEXT: v_lshlrev_b32_e32 v27, 16, v27 ; CI-NEXT: s_waitcnt vmcnt(1) -; CI-NEXT: v_cvt_f16_f32_e32 v26, v26 +; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 +; CI-NEXT: v_cvt_f32_f16_e32 v24, v24 +; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 ; CI-NEXT: s_waitcnt vmcnt(0) +; CI-NEXT: v_cvt_f16_f32_e32 v22, v22 +; CI-NEXT: v_cvt_f32_f16_e32 v22, v22 +; CI-NEXT: v_cvt_f16_f32_e32 v28, v22 +; CI-NEXT: v_or_b32_e32 v22, v23, v27 +; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:52 +; CI-NEXT: v_lshlrev_b32_e32 v23, 16, v24 +; CI-NEXT: v_or_b32_e32 v23, v28, v23 +; CI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:56 +; CI-NEXT: buffer_load_dword v24, off, s[0:3], s32 offset:48 +; CI-NEXT: s_waitcnt vmcnt(2) ; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 -; CI-NEXT: v_lshlrev_b32_e32 v26, 16, v26 -; CI-NEXT: v_or_b32_e32 v26, v27, v26 -; CI-NEXT: v_add_i32_e32 v27, vcc, 0x74, v0 -; CI-NEXT: buffer_store_dword v26, v27, s[0:3], 0 offen -; CI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:108 -; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:104 ; CI-NEXT: s_waitcnt vmcnt(1) -; CI-NEXT: v_cvt_f16_f32_e32 v25, v26 +; CI-NEXT: v_cvt_f16_f32_e32 v28, v28 ; CI-NEXT: s_waitcnt vmcnt(0) -; CI-NEXT: v_cvt_f16_f32_e32 v26, v27 -; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:92 -; CI-NEXT: v_lshlrev_b32_e32 v25, 16, v25 -; CI-NEXT: v_or_b32_e32 v25, v26, v25 -; CI-NEXT: v_add_i32_e32 v26, vcc, 0x70, v0 -; CI-NEXT: buffer_store_dword v25, v26, s[0:3], 0 offen -; CI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:100 -; CI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:96 -; CI-NEXT: s_waitcnt vmcnt(3) +; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 +; CI-NEXT: v_cvt_f32_f16_e32 v27, v27 +; CI-NEXT: v_cvt_f32_f16_e32 v28, v28 +; CI-NEXT: v_cvt_f32_f16_e32 v24, v24 ; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 +; CI-NEXT: v_cvt_f16_f32_e32 v28, v28 +; CI-NEXT: v_cvt_f16_f32_e32 v24, v24 ; CI-NEXT: v_lshlrev_b32_e32 v27, 16, v27 -; CI-NEXT: v_or_b32_e32 v23, v23, v27 -; CI-NEXT: s_waitcnt vmcnt(1) -; CI-NEXT: v_cvt_f16_f32_e32 v25, v25 +; CI-NEXT: v_or_b32_e32 v24, v24, v27 +; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:60 ; CI-NEXT: s_waitcnt vmcnt(0) -; CI-NEXT: v_cvt_f16_f32_e32 v26, v26 -; CI-NEXT: v_add_i32_e32 v27, vcc, 0x68, v0 -; CI-NEXT: v_lshlrev_b32_e32 v25, 16, v25 -; CI-NEXT: v_or_b32_e32 v25, v26, v25 -; CI-NEXT: v_add_i32_e32 v26, vcc, 0x6c, v0 -; CI-NEXT: buffer_store_dword v25, v26, s[0:3], 0 offen -; CI-NEXT: buffer_load_dword v25, off, s[0:3], s32 offset:68 -; CI-NEXT: buffer_load_dword v26, off, s[0:3], s32 offset:64 -; CI-NEXT: buffer_store_dword v23, v27, s[0:3], 0 offen -; CI-NEXT: buffer_load_dword v23, off, s[0:3], s32 offset:76 -; CI-NEXT: buffer_load_dword v27, off, s[0:3], s32 offset:72 -; CI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:84 -; CI-NEXT: buffer_load_dword v29, off, s[0:3], s32 offset:80 -; CI-NEXT: s_waitcnt vmcnt(3) -; CI-NEXT: v_cvt_f16_f32_e32 v23, v23 -; CI-NEXT: v_cvt_f16_f32_e32 v25, v25 -; CI-NEXT: v_cvt_f16_f32_e32 v26, v26 -; CI-NEXT: v_lshlrev_b32_e32 v23, 16, v23 -; CI-NEXT: v_lshlrev_b32_e32 v25, 16, v25 -; CI-NEXT: v_or_b32_e32 v25, v26, v25 -; CI-NEXT: s_waitcnt vmcnt(2) -; CI-NEXT: v_cvt_f16_f32_e32 v26, v27 +; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 +; CI-NEXT: v_cvt_f32_f16_e32 v27, v27 +; CI-NEXT: v_cvt_f16_f32_e32 v27, v27 +; CI-NEXT: v_lshlrev_b32_e32 v27, 16, v27 +; CI-NEXT: v_or_b32_e32 v27, v28, v27 +; CI-NEXT: buffer_load_dword v28, off, s[0:3], s32 offset:68 ; CI-NEXT: s_waitcnt vmcnt(0) -; CI-NEXT: v_cvt_f16_f32_e32 v27, v29 -; CI-NEXT: v_or_b32_e32 v23, v26, v23 -; CI-NEXT: v_cvt_f16_f32_e32 v26, v28 -; CI-NEXT: v_lshlrev_b32_e32 v26, 16, v26 -; CI-NEXT: v_or_b32_e32 v26, v27, v26 -; CI-NEXT: v_add_i32_e32 v27, vcc, 0x64, v0 -; CI-NEXT: buffer_store_dword v26, v27, s[0:3], 0 offen -; CI-NEXT: v_add_i32_e32 v26, vcc, 0x60, v0 -; CI-NEXT: buffer_store_dword v23, v26, s[0:3], 0 offen -; CI-NEXT: v_add_i32_e32 v23, vcc, 0x5c, v0 -; CI-NEXT: buffer_store_dword v25, v23, s[0:3], 0 offen -; CI-NEXT: v_add_i32_e32 v23, vcc, 0x58, v0 -; CI-NEXT: buffer_store_dword v22, v23, s[0:3], 0 offen -; CI-NEXT: v_add_i32_e32 v22, vcc, 0x54, v0 -; CI-NEXT: buffer_store_dword v24, v22, s[0:3], 0 offen -; CI-NEXT: v_add_i32_e32 v22, vcc, 0x50, v0 -; CI-NEXT: buffer_store_dword v21, v22, s[0:3], 0 offen -; CI-NEXT: v_add_i32_e32 v21, vcc, 0x4c, v0 -; CI-NEXT: buffer_store_dword v20, v21, s[0:3], 0 offen -; CI-NEXT: v_add_i32_e32 v20, vcc, 0x48, v0 -; CI-NEXT: buffer_store_dword v19, v20, s[0:3], 0 offen -; CI-NEXT: v_add_i32_e32 v19, vcc, 0x44, v0 -; CI-NEXT: buffer_store_dword v18, v19, s[0:3], 0 offen -; CI-NEXT: v_add_i32_e32 v18, vcc, 64, v0 -; CI-NEXT: buffer_store_dword v17, v18, s[0:3], 0 offen +; CI-NEXT: v_cvt_f16_f32_e32 v28, v28 +; CI-NEXT: v_cvt_f32_f16_e32 v28, v28 +; CI-NEXT: v_cvt_f16_f32_e32 v28, v28 +; CI-NEXT: v_lshlrev_b32_e32 v28, 16, v28 +; CI-NEXT: v_or_b32_e32 v28, v29, v28 +; CI-NEXT: buffer_store_dword v28, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x58, v0 +; CI-NEXT: buffer_store_dword v27, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x54, v0 +; CI-NEXT: buffer_store_dword v24, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x50, v0 +; CI-NEXT: buffer_store_dword v23, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x4c, v0 +; CI-NEXT: buffer_store_dword v22, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x48, v0 +; CI-NEXT: buffer_store_dword v21, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 0x44, v0 +; CI-NEXT: buffer_store_dword v19, v17, s[0:3], 0 offen +; CI-NEXT: v_add_i32_e32 v17, vcc, 64, v0 +; CI-NEXT: buffer_store_dword v20, v17, s[0:3], 0 offen ; CI-NEXT: v_add_i32_e32 v17, vcc, 60, v0 ; CI-NEXT: buffer_store_dword v16, v17, s[0:3], 0 offen ; CI-NEXT: v_add_i32_e32 v16, vcc, 56, v0 diff --git a/llvm/test/CodeGen/AMDGPU/fcanonicalize.ll b/llvm/test/CodeGen/AMDGPU/fcanonicalize.ll index c1093a1e89c8861bc77c26776ba56f96de736821..d53c0411ad88c1c5b8a7f8ec38a787f17eba9b5f 100644 --- a/llvm/test/CodeGen/AMDGPU/fcanonicalize.ll +++ b/llvm/test/CodeGen/AMDGPU/fcanonicalize.ll @@ -2389,7 +2389,6 @@ define amdgpu_kernel void @test_canonicalize_value_f16_flush(ptr addrspace(1) %a ; GFX6-NEXT: v_mov_b32_e32 v1, s3 ; GFX6-NEXT: s_waitcnt vmcnt(0) ; GFX6-NEXT: v_cvt_f32_f16_e32 v0, v0 -; GFX6-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX6-NEXT: v_cvt_f16_f32_e32 v3, v0 ; GFX6-NEXT: v_add_i32_e32 v0, vcc, s2, v2 ; GFX6-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc @@ -2471,15 +2470,13 @@ define amdgpu_kernel void @test_canonicalize_value_v2f16_flush(ptr addrspace(1) ; GFX6-NEXT: flat_load_dword v0, v[0:1] ; GFX6-NEXT: v_mov_b32_e32 v3, s3 ; GFX6-NEXT: s_waitcnt vmcnt(0) -; GFX6-NEXT: v_cvt_f32_f16_e32 v1, v0 -; GFX6-NEXT: v_lshrrev_b32_e32 v0, 16, v0 +; GFX6-NEXT: v_lshrrev_b32_e32 v1, 16, v0 +; GFX6-NEXT: v_cvt_f32_f16_e32 v1, v1 ; GFX6-NEXT: v_cvt_f32_f16_e32 v0, v0 -; GFX6-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GFX6-NEXT: v_cvt_f16_f32_e32 v1, v1 -; GFX6-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX6-NEXT: v_cvt_f16_f32_e32 v0, v0 -; GFX6-NEXT: v_lshlrev_b32_e32 v0, 16, v0 -; GFX6-NEXT: v_or_b32_e32 v4, v1, v0 +; GFX6-NEXT: v_lshlrev_b32_e32 v1, 16, v1 +; GFX6-NEXT: v_or_b32_e32 v4, v0, v1 ; GFX6-NEXT: v_add_i32_e32 v0, vcc, s2, v2 ; GFX6-NEXT: v_addc_u32_e32 v1, vcc, 0, v3, vcc ; GFX6-NEXT: flat_store_dword v[0:1], v4 @@ -2724,7 +2721,6 @@ define amdgpu_kernel void @test_canonicalize_value_f16_denorm(ptr addrspace(1) % ; GFX6-NEXT: v_mov_b32_e32 v1, s3 ; GFX6-NEXT: s_waitcnt vmcnt(0) ; GFX6-NEXT: v_cvt_f32_f16_e32 v0, v0 -; GFX6-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX6-NEXT: v_cvt_f16_f32_e32 v3, v0 ; GFX6-NEXT: v_add_i32_e32 v0, vcc, s2, v2 ; GFX6-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc @@ -2807,15 +2803,13 @@ define amdgpu_kernel void @test_canonicalize_value_v2f16_denorm(ptr addrspace(1) ; GFX6-NEXT: flat_load_dword v0, v[0:1] ; GFX6-NEXT: v_mov_b32_e32 v3, s3 ; GFX6-NEXT: s_waitcnt vmcnt(0) -; GFX6-NEXT: v_cvt_f32_f16_e32 v1, v0 -; GFX6-NEXT: v_lshrrev_b32_e32 v0, 16, v0 +; GFX6-NEXT: v_lshrrev_b32_e32 v1, 16, v0 +; GFX6-NEXT: v_cvt_f32_f16_e32 v1, v1 ; GFX6-NEXT: v_cvt_f32_f16_e32 v0, v0 -; GFX6-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; GFX6-NEXT: v_cvt_f16_f32_e32 v1, v1 -; GFX6-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; GFX6-NEXT: v_cvt_f16_f32_e32 v0, v0 -; GFX6-NEXT: v_lshlrev_b32_e32 v0, 16, v0 -; GFX6-NEXT: v_or_b32_e32 v4, v1, v0 +; GFX6-NEXT: v_lshlrev_b32_e32 v1, 16, v1 +; GFX6-NEXT: v_or_b32_e32 v4, v0, v1 ; GFX6-NEXT: v_add_i32_e32 v0, vcc, s2, v2 ; GFX6-NEXT: v_addc_u32_e32 v1, vcc, 0, v3, vcc ; GFX6-NEXT: flat_store_dword v[0:1], v4 diff --git a/llvm/test/CodeGen/AMDGPU/fneg-combines.f16.ll b/llvm/test/CodeGen/AMDGPU/fneg-combines.f16.ll index 78fb89c71e2e6a4bcf90b1180ca1932879814c3d..b32630a97b3ad01f64560dbdc931e20d0a7bb93f 100644 --- a/llvm/test/CodeGen/AMDGPU/fneg-combines.f16.ll +++ b/llvm/test/CodeGen/AMDGPU/fneg-combines.f16.ll @@ -951,8 +951,6 @@ define half @v_fneg_minnum_f16_ieee(half %a, half %b) #0 { ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, v0, v1 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1056,7 +1054,6 @@ define half @v_fneg_posk_minnum_f16_ieee(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, -4.0, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1110,7 +1107,6 @@ define half @v_fneg_negk_minnum_f16_ieee(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 4.0, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1193,7 +1189,6 @@ define half @v_fneg_neg0_minnum_f16_ieee(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 0, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1222,7 +1217,6 @@ define half @v_fneg_inv2pi_minnum_f16(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 0xbe230000, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1253,7 +1247,6 @@ define half @v_fneg_neg_inv2pi_minnum_f16(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 0xbe230000, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1311,7 +1304,6 @@ define half @v_fneg_0_minnum_foldable_use_f16_ieee(half %a, half %b) #0 { ; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; SI-NEXT: v_cvt_f32_f16_e32 v1, v1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_min_f32_e32 v0, 0, v0 ; SI-NEXT: v_mul_f32_e64 v0, -v0, v1 ; SI-NEXT: s_setpc_b64 s[30:31] @@ -1346,7 +1338,6 @@ define half @v_fneg_inv2pi_minnum_foldable_use_f16(half %a, half %b) #0 { ; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; SI-NEXT: v_cvt_f32_f16_e32 v1, v1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 0xbe230000, v0 ; SI-NEXT: v_mul_f32_e32 v0, v0, v1 ; SI-NEXT: s_setpc_b64 s[30:31] @@ -1413,8 +1404,6 @@ define { half, half } @v_fneg_minnum_multi_use_minnum_f16_ieee(half %a, half %b) ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: v_cvt_f32_f16_e64 v1, -v1 ; SI-NEXT: v_cvt_f32_f16_e64 v0, -v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, v0, v1 ; SI-NEXT: v_mul_f32_e32 v1, -4.0, v0 ; SI-NEXT: s_setpc_b64 s[30:31] @@ -1494,8 +1483,6 @@ define half @v_fneg_maxnum_f16_ieee(half %a, half %b) #0 { ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_min_f32_e32 v0, v0, v1 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1599,7 +1586,6 @@ define half @v_fneg_posk_maxnum_f16_ieee(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_min_f32_e32 v0, -4.0, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1653,7 +1639,6 @@ define half @v_fneg_negk_maxnum_f16_ieee(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_min_f32_e32 v0, 4.0, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1736,7 +1721,6 @@ define half @v_fneg_neg0_maxnum_f16_ieee(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_min_f32_e32 v0, 0, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1792,7 +1776,6 @@ define half @v_fneg_0_maxnum_foldable_use_f16_ieee(half %a, half %b) #0 { ; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; SI-NEXT: v_cvt_f32_f16_e32 v1, v1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 0, v0 ; SI-NEXT: v_mul_f32_e64 v0, -v0, v1 ; SI-NEXT: s_setpc_b64 s[30:31] @@ -1859,8 +1842,6 @@ define { half, half } @v_fneg_maxnum_multi_use_maxnum_f16_ieee(half %a, half %b) ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: v_cvt_f32_f16_e64 v1, -v1 ; SI-NEXT: v_cvt_f32_f16_e64 v0, -v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_min_f32_e32 v0, v0, v1 ; SI-NEXT: v_mul_f32_e32 v1, -4.0, v0 ; SI-NEXT: s_setpc_b64 s[30:31] @@ -3980,7 +3961,8 @@ define half @v_fneg_canonicalize_f16(half %a) #0 { ; SI-LABEL: v_fneg_canonicalize_f16: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; SI-NEXT: v_xor_b32_e32 v0, 0x80000000, v0 +; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 +; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; ; VI-LABEL: v_fneg_canonicalize_f16: diff --git a/llvm/test/CodeGen/AMDGPU/fneg-combines.new.ll b/llvm/test/CodeGen/AMDGPU/fneg-combines.new.ll index 17f67615c29f2e70c92cdf834b99576b831ca4a4..b5440b9c38c9f2ea75d7dda18f8553bc193186f3 100644 --- a/llvm/test/CodeGen/AMDGPU/fneg-combines.new.ll +++ b/llvm/test/CodeGen/AMDGPU/fneg-combines.new.ll @@ -1021,7 +1021,6 @@ define half @v_fneg_inv2pi_minnum_f16(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 0xbe230000, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; @@ -1043,7 +1042,6 @@ define half @v_fneg_neg_inv2pi_minnum_f16(half %a) #0 { ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SI-NEXT: v_cvt_f16_f32_e64 v0, -v0 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 0x3e230000, v0 ; SI-NEXT: s_setpc_b64 s[30:31] ; diff --git a/llvm/test/CodeGen/AMDGPU/fold-restore-undef-use.mir b/llvm/test/CodeGen/AMDGPU/fold-restore-undef-use.mir index 3616d617f84a0dd3fb9cdcc2d0f83d8d2c2e056b..5ef8a94eeaa7c6ef9cd806af987737a3a28f70ab 100644 --- a/llvm/test/CodeGen/AMDGPU/fold-restore-undef-use.mir +++ b/llvm/test/CodeGen/AMDGPU/fold-restore-undef-use.mir @@ -8,6 +8,8 @@ --- name: restore_undef_copy_use tracksRegLiveness: true +frameInfo: + adjustsStack: true machineFunctionInfo: maxKernArgAlign: 1 isEntryFunction: true diff --git a/llvm/test/CodeGen/AMDGPU/fp-classify.ll b/llvm/test/CodeGen/AMDGPU/fp-classify.ll index 6fa7df913812a32f3fe3e398dda2d2e4b9caad52..18d2e52e8f9002bfda90d63f2dd24fd01f8a37b1 100644 --- a/llvm/test/CodeGen/AMDGPU/fp-classify.ll +++ b/llvm/test/CodeGen/AMDGPU/fp-classify.ll @@ -618,16 +618,16 @@ define amdgpu_kernel void @test_not_isfinite_pattern_4_wrong_ord_test(ptr addrsp define amdgpu_kernel void @test_isinf_pattern_f16(ptr addrspace(1) nocapture %out, half %x) #0 { ; SI-LABEL: test_isinf_pattern_f16: ; SI: ; %bb.0: -; SI-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x9 -; SI-NEXT: s_load_dword s0, s[0:1], 0xb -; SI-NEXT: s_mov_b32 s7, 0xf000 -; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: s_mov_b32 s1, 0x7f800000 +; SI-NEXT: s_load_dword s4, s[0:1], 0xb +; SI-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x9 +; SI-NEXT: s_mov_b32 s3, 0xf000 +; SI-NEXT: s_mov_b32 s2, -1 ; SI-NEXT: s_waitcnt lgkmcnt(0) -; SI-NEXT: v_cvt_f32_f16_e64 v0, |s0| -; SI-NEXT: v_cmp_eq_f32_e32 vcc, s1, v0 -; SI-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc -; SI-NEXT: buffer_store_dword v0, off, s[4:7], 0 +; SI-NEXT: s_and_b32 s4, s4, 0x7fff +; SI-NEXT: s_cmpk_eq_i32 s4, 0x7c00 +; SI-NEXT: s_cselect_b64 s[4:5], -1, 0 +; SI-NEXT: v_cndmask_b32_e64 v0, 0, 1, s[4:5] +; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0 ; SI-NEXT: s_endpgm ; ; VI-LABEL: test_isinf_pattern_f16: @@ -667,16 +667,19 @@ define amdgpu_kernel void @test_isinf_pattern_f16(ptr addrspace(1) nocapture %ou define amdgpu_kernel void @test_isfinite_pattern_0_f16(ptr addrspace(1) nocapture %out, half %x) #0 { ; SI-LABEL: test_isfinite_pattern_0_f16: ; SI: ; %bb.0: -; SI-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x9 -; SI-NEXT: s_load_dword s0, s[0:1], 0xb -; SI-NEXT: s_mov_b32 s7, 0xf000 -; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: s_movk_i32 s1, 0x1f8 +; SI-NEXT: s_load_dword s4, s[0:1], 0xb +; SI-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x9 +; SI-NEXT: s_mov_b32 s3, 0xf000 +; SI-NEXT: s_mov_b32 s2, -1 ; SI-NEXT: s_waitcnt lgkmcnt(0) -; SI-NEXT: v_cvt_f32_f16_e32 v0, s0 -; SI-NEXT: v_cmp_class_f32_e64 s[0:1], v0, s1 -; SI-NEXT: v_cndmask_b32_e64 v0, 0, 1, s[0:1] -; SI-NEXT: buffer_store_dword v0, off, s[4:7], 0 +; SI-NEXT: v_cvt_f32_f16_e32 v0, s4 +; SI-NEXT: s_and_b32 s4, s4, 0x7fff +; SI-NEXT: v_cmp_o_f32_e32 vcc, v0, v0 +; SI-NEXT: s_cmpk_lg_i32 s4, 0x7c00 +; SI-NEXT: s_cselect_b64 s[4:5], -1, 0 +; SI-NEXT: s_and_b64 s[4:5], vcc, s[4:5] +; SI-NEXT: v_cndmask_b32_e64 v0, 0, 1, s[4:5] +; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0 ; SI-NEXT: s_endpgm ; ; VI-LABEL: test_isfinite_pattern_0_f16: @@ -718,16 +721,19 @@ define amdgpu_kernel void @test_isfinite_pattern_0_f16(ptr addrspace(1) nocaptur define amdgpu_kernel void @test_isfinite_pattern_4_f16(ptr addrspace(1) nocapture %out, half %x) #0 { ; SI-LABEL: test_isfinite_pattern_4_f16: ; SI: ; %bb.0: -; SI-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x9 -; SI-NEXT: s_load_dword s0, s[0:1], 0xb -; SI-NEXT: s_mov_b32 s7, 0xf000 -; SI-NEXT: s_mov_b32 s6, -1 -; SI-NEXT: s_movk_i32 s1, 0x1f8 +; SI-NEXT: s_load_dword s4, s[0:1], 0xb +; SI-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x9 +; SI-NEXT: s_mov_b32 s3, 0xf000 +; SI-NEXT: s_mov_b32 s2, -1 ; SI-NEXT: s_waitcnt lgkmcnt(0) -; SI-NEXT: v_cvt_f32_f16_e32 v0, s0 -; SI-NEXT: v_cmp_class_f32_e64 s[0:1], v0, s1 -; SI-NEXT: v_cndmask_b32_e64 v0, 0, 1, s[0:1] -; SI-NEXT: buffer_store_dword v0, off, s[4:7], 0 +; SI-NEXT: v_cvt_f32_f16_e32 v0, s4 +; SI-NEXT: s_and_b32 s4, s4, 0x7fff +; SI-NEXT: v_cmp_o_f32_e32 vcc, v0, v0 +; SI-NEXT: s_cmpk_lt_i32 s4, 0x7c00 +; SI-NEXT: s_cselect_b64 s[4:5], -1, 0 +; SI-NEXT: s_and_b64 s[4:5], vcc, s[4:5] +; SI-NEXT: v_cndmask_b32_e64 v0, 0, 1, s[4:5] +; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0 ; SI-NEXT: s_endpgm ; ; VI-LABEL: test_isfinite_pattern_4_f16: diff --git a/llvm/test/CodeGen/AMDGPU/fp64-atomics-gfx90a.ll b/llvm/test/CodeGen/AMDGPU/fp64-atomics-gfx90a.ll index 767d347bcfaa15118096e3abbea2c3fad99c7177..a948fab8f1c1b9cb4aef23c95138909d804e3488 100644 --- a/llvm/test/CodeGen/AMDGPU/fp64-atomics-gfx90a.ll +++ b/llvm/test/CodeGen/AMDGPU/fp64-atomics-gfx90a.ll @@ -1181,18 +1181,28 @@ main_body: define amdgpu_kernel void @global_atomic_fadd_f64_noret_pat(ptr addrspace(1) %ptr) #1 { ; GFX90A-LABEL: global_atomic_fadd_f64_noret_pat: ; GFX90A: ; %bb.0: ; %main_body +; GFX90A-NEXT: s_mov_b64 s[2:3], exec +; GFX90A-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX90A-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX90A-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX90A-NEXT: s_cbranch_execz .LBB42_3 +; GFX90A-NEXT: ; %bb.1: ; GFX90A-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX90A-NEXT: s_bcnt1_i32_b64 s6, s[2:3] +; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s6 ; GFX90A-NEXT: s_mov_b64 s[2:3], 0 -; GFX90A-NEXT: v_mov_b32_e32 v4, 0 +; GFX90A-NEXT: v_mul_f64 v[4:5], v[0:1], 4.0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX90A-NEXT: v_mov_b32_e32 v6, 0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: v_pk_mov_b32 v[2:3], s[4:5], s[4:5] op_sel:[0,1] -; GFX90A-NEXT: .LBB42_1: ; %atomicrmw.start +; GFX90A-NEXT: .LBB42_2: ; %atomicrmw.start ; GFX90A-NEXT: ; =>This Inner Loop Header: Depth=1 -; GFX90A-NEXT: v_add_f64 v[0:1], v[2:3], 4.0 +; GFX90A-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] ; GFX90A-NEXT: buffer_wbl2 -; GFX90A-NEXT: global_atomic_cmpswap_x2 v[0:1], v4, v[0:3], s[0:1] glc +; GFX90A-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc ; GFX90A-NEXT: s_waitcnt vmcnt(0) ; GFX90A-NEXT: buffer_invl2 ; GFX90A-NEXT: buffer_wbinvl1_vol @@ -1200,20 +1210,30 @@ define amdgpu_kernel void @global_atomic_fadd_f64_noret_pat(ptr addrspace(1) %pt ; GFX90A-NEXT: s_or_b64 s[2:3], vcc, s[2:3] ; GFX90A-NEXT: v_pk_mov_b32 v[2:3], v[0:1], v[0:1] op_sel:[0,1] ; GFX90A-NEXT: s_andn2_b64 exec, exec, s[2:3] -; GFX90A-NEXT: s_cbranch_execnz .LBB42_1 -; GFX90A-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX90A-NEXT: s_cbranch_execnz .LBB42_2 +; GFX90A-NEXT: .LBB42_3: ; GFX90A-NEXT: s_endpgm ; ; GFX940-LABEL: global_atomic_fadd_f64_noret_pat: ; GFX940: ; %bb.0: ; %main_body +; GFX940-NEXT: s_mov_b64 s[2:3], exec +; GFX940-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX940-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX940-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX940-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX940-NEXT: s_cbranch_execz .LBB42_2 +; GFX940-NEXT: ; %bb.1: ; GFX940-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX940-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s2 ; GFX940-NEXT: v_mov_b32_e32 v2, 0 -; GFX940-NEXT: v_mov_b64_e32 v[0:1], 4.0 +; GFX940-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX940-NEXT: buffer_wbl2 sc0 sc1 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) ; GFX940-NEXT: global_atomic_add_f64 v2, v[0:1], s[0:1] sc1 ; GFX940-NEXT: s_waitcnt vmcnt(0) ; GFX940-NEXT: buffer_inv sc0 sc1 +; GFX940-NEXT: .LBB42_2: ; GFX940-NEXT: s_endpgm main_body: %ret = atomicrmw fadd ptr addrspace(1) %ptr, double 4.0 seq_cst @@ -1223,26 +1243,45 @@ main_body: define amdgpu_kernel void @global_atomic_fadd_f64_noret_pat_agent(ptr addrspace(1) %ptr) #1 { ; GFX90A-LABEL: global_atomic_fadd_f64_noret_pat_agent: ; GFX90A: ; %bb.0: ; %main_body +; GFX90A-NEXT: s_mov_b64 s[2:3], exec +; GFX90A-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX90A-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX90A-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX90A-NEXT: s_cbranch_execz .LBB43_2 +; GFX90A-NEXT: ; %bb.1: ; GFX90A-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 -; GFX90A-NEXT: v_mov_b32_e32 v0, 0 +; GFX90A-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s2 ; GFX90A-NEXT: v_mov_b32_e32 v2, 0 -; GFX90A-NEXT: v_mov_b32_e32 v1, 0x40100000 +; GFX90A-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: global_atomic_add_f64 v2, v[0:1], s[0:1] ; GFX90A-NEXT: s_waitcnt vmcnt(0) ; GFX90A-NEXT: buffer_wbinvl1_vol +; GFX90A-NEXT: .LBB43_2: ; GFX90A-NEXT: s_endpgm ; ; GFX940-LABEL: global_atomic_fadd_f64_noret_pat_agent: ; GFX940: ; %bb.0: ; %main_body +; GFX940-NEXT: s_mov_b64 s[2:3], exec +; GFX940-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX940-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX940-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX940-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX940-NEXT: s_cbranch_execz .LBB43_2 +; GFX940-NEXT: ; %bb.1: ; GFX940-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX940-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s2 ; GFX940-NEXT: v_mov_b32_e32 v2, 0 -; GFX940-NEXT: v_mov_b64_e32 v[0:1], 4.0 +; GFX940-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX940-NEXT: buffer_wbl2 sc1 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) ; GFX940-NEXT: global_atomic_add_f64 v2, v[0:1], s[0:1] ; GFX940-NEXT: s_waitcnt vmcnt(0) ; GFX940-NEXT: buffer_inv sc1 +; GFX940-NEXT: .LBB43_2: ; GFX940-NEXT: s_endpgm main_body: %ret = atomicrmw fadd ptr addrspace(1) %ptr, double 4.0 syncscope("agent") seq_cst @@ -1252,18 +1291,28 @@ main_body: define amdgpu_kernel void @global_atomic_fadd_f64_noret_pat_system(ptr addrspace(1) %ptr) #1 { ; GFX90A-LABEL: global_atomic_fadd_f64_noret_pat_system: ; GFX90A: ; %bb.0: ; %main_body +; GFX90A-NEXT: s_mov_b64 s[2:3], exec +; GFX90A-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX90A-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX90A-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX90A-NEXT: s_cbranch_execz .LBB44_3 +; GFX90A-NEXT: ; %bb.1: ; GFX90A-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX90A-NEXT: s_bcnt1_i32_b64 s6, s[2:3] +; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s6 ; GFX90A-NEXT: s_mov_b64 s[2:3], 0 -; GFX90A-NEXT: v_mov_b32_e32 v4, 0 +; GFX90A-NEXT: v_mul_f64 v[4:5], v[0:1], 4.0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX90A-NEXT: v_mov_b32_e32 v6, 0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: v_pk_mov_b32 v[2:3], s[4:5], s[4:5] op_sel:[0,1] -; GFX90A-NEXT: .LBB44_1: ; %atomicrmw.start +; GFX90A-NEXT: .LBB44_2: ; %atomicrmw.start ; GFX90A-NEXT: ; =>This Inner Loop Header: Depth=1 -; GFX90A-NEXT: v_add_f64 v[0:1], v[2:3], 4.0 +; GFX90A-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] ; GFX90A-NEXT: buffer_wbl2 -; GFX90A-NEXT: global_atomic_cmpswap_x2 v[0:1], v4, v[0:3], s[0:1] glc +; GFX90A-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc ; GFX90A-NEXT: s_waitcnt vmcnt(0) ; GFX90A-NEXT: buffer_invl2 ; GFX90A-NEXT: buffer_wbinvl1_vol @@ -1271,20 +1320,30 @@ define amdgpu_kernel void @global_atomic_fadd_f64_noret_pat_system(ptr addrspace ; GFX90A-NEXT: s_or_b64 s[2:3], vcc, s[2:3] ; GFX90A-NEXT: v_pk_mov_b32 v[2:3], v[0:1], v[0:1] op_sel:[0,1] ; GFX90A-NEXT: s_andn2_b64 exec, exec, s[2:3] -; GFX90A-NEXT: s_cbranch_execnz .LBB44_1 -; GFX90A-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX90A-NEXT: s_cbranch_execnz .LBB44_2 +; GFX90A-NEXT: .LBB44_3: ; GFX90A-NEXT: s_endpgm ; ; GFX940-LABEL: global_atomic_fadd_f64_noret_pat_system: ; GFX940: ; %bb.0: ; %main_body +; GFX940-NEXT: s_mov_b64 s[2:3], exec +; GFX940-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX940-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX940-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX940-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX940-NEXT: s_cbranch_execz .LBB44_2 +; GFX940-NEXT: ; %bb.1: ; GFX940-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX940-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s2 ; GFX940-NEXT: v_mov_b32_e32 v2, 0 -; GFX940-NEXT: v_mov_b64_e32 v[0:1], 4.0 +; GFX940-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX940-NEXT: buffer_wbl2 sc0 sc1 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) ; GFX940-NEXT: global_atomic_add_f64 v2, v[0:1], s[0:1] sc1 ; GFX940-NEXT: s_waitcnt vmcnt(0) ; GFX940-NEXT: buffer_inv sc0 sc1 +; GFX940-NEXT: .LBB44_2: ; GFX940-NEXT: s_endpgm main_body: %ret = atomicrmw fadd ptr addrspace(1) %ptr, double 4.0 syncscope("one-as") seq_cst @@ -1294,26 +1353,45 @@ main_body: define amdgpu_kernel void @global_atomic_fadd_f64_noret_pat_flush(ptr addrspace(1) %ptr) #0 { ; GFX90A-LABEL: global_atomic_fadd_f64_noret_pat_flush: ; GFX90A: ; %bb.0: ; %main_body +; GFX90A-NEXT: s_mov_b64 s[2:3], exec +; GFX90A-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX90A-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX90A-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX90A-NEXT: s_cbranch_execz .LBB45_2 +; GFX90A-NEXT: ; %bb.1: ; GFX90A-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 -; GFX90A-NEXT: v_mov_b32_e32 v0, 0 +; GFX90A-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s2 ; GFX90A-NEXT: v_mov_b32_e32 v2, 0 -; GFX90A-NEXT: v_mov_b32_e32 v1, 0x40100000 +; GFX90A-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: global_atomic_add_f64 v2, v[0:1], s[0:1] ; GFX90A-NEXT: s_waitcnt vmcnt(0) ; GFX90A-NEXT: buffer_wbinvl1_vol +; GFX90A-NEXT: .LBB45_2: ; GFX90A-NEXT: s_endpgm ; ; GFX940-LABEL: global_atomic_fadd_f64_noret_pat_flush: ; GFX940: ; %bb.0: ; %main_body +; GFX940-NEXT: s_mov_b64 s[2:3], exec +; GFX940-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX940-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX940-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX940-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX940-NEXT: s_cbranch_execz .LBB45_2 +; GFX940-NEXT: ; %bb.1: ; GFX940-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX940-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s2 ; GFX940-NEXT: v_mov_b32_e32 v2, 0 -; GFX940-NEXT: v_mov_b64_e32 v[0:1], 4.0 +; GFX940-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX940-NEXT: buffer_wbl2 sc1 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) ; GFX940-NEXT: global_atomic_add_f64 v2, v[0:1], s[0:1] ; GFX940-NEXT: s_waitcnt vmcnt(0) ; GFX940-NEXT: buffer_inv sc1 +; GFX940-NEXT: .LBB45_2: ; GFX940-NEXT: s_endpgm main_body: %ret = atomicrmw fadd ptr addrspace(1) %ptr, double 4.0 syncscope("agent") seq_cst @@ -1485,37 +1563,57 @@ main_body: define amdgpu_kernel void @global_atomic_fadd_f64_noret_pat_agent_safe(ptr addrspace(1) %ptr) { ; GFX90A-LABEL: global_atomic_fadd_f64_noret_pat_agent_safe: ; GFX90A: ; %bb.0: ; %main_body +; GFX90A-NEXT: s_mov_b64 s[2:3], exec +; GFX90A-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX90A-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX90A-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX90A-NEXT: s_cbranch_execz .LBB52_3 +; GFX90A-NEXT: ; %bb.1: ; GFX90A-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX90A-NEXT: s_bcnt1_i32_b64 s6, s[2:3] +; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s6 ; GFX90A-NEXT: s_mov_b64 s[2:3], 0 -; GFX90A-NEXT: v_mov_b32_e32 v4, 0 +; GFX90A-NEXT: v_mul_f64 v[4:5], v[0:1], 4.0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX90A-NEXT: v_mov_b32_e32 v6, 0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: v_pk_mov_b32 v[2:3], s[4:5], s[4:5] op_sel:[0,1] -; GFX90A-NEXT: .LBB52_1: ; %atomicrmw.start +; GFX90A-NEXT: .LBB52_2: ; %atomicrmw.start ; GFX90A-NEXT: ; =>This Inner Loop Header: Depth=1 -; GFX90A-NEXT: v_add_f64 v[0:1], v[2:3], 4.0 -; GFX90A-NEXT: global_atomic_cmpswap_x2 v[0:1], v4, v[0:3], s[0:1] glc +; GFX90A-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX90A-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc ; GFX90A-NEXT: s_waitcnt vmcnt(0) ; GFX90A-NEXT: buffer_wbinvl1_vol ; GFX90A-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] ; GFX90A-NEXT: s_or_b64 s[2:3], vcc, s[2:3] ; GFX90A-NEXT: v_pk_mov_b32 v[2:3], v[0:1], v[0:1] op_sel:[0,1] ; GFX90A-NEXT: s_andn2_b64 exec, exec, s[2:3] -; GFX90A-NEXT: s_cbranch_execnz .LBB52_1 -; GFX90A-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX90A-NEXT: s_cbranch_execnz .LBB52_2 +; GFX90A-NEXT: .LBB52_3: ; GFX90A-NEXT: s_endpgm ; ; GFX940-LABEL: global_atomic_fadd_f64_noret_pat_agent_safe: ; GFX940: ; %bb.0: ; %main_body +; GFX940-NEXT: s_mov_b64 s[2:3], exec +; GFX940-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX940-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX940-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX940-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX940-NEXT: s_cbranch_execz .LBB52_2 +; GFX940-NEXT: ; %bb.1: ; GFX940-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX940-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s2 ; GFX940-NEXT: v_mov_b32_e32 v2, 0 -; GFX940-NEXT: v_mov_b64_e32 v[0:1], 4.0 +; GFX940-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX940-NEXT: buffer_wbl2 sc1 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) ; GFX940-NEXT: global_atomic_add_f64 v2, v[0:1], s[0:1] ; GFX940-NEXT: s_waitcnt vmcnt(0) ; GFX940-NEXT: buffer_inv sc1 +; GFX940-NEXT: .LBB52_2: ; GFX940-NEXT: s_endpgm main_body: %ret = atomicrmw fadd ptr addrspace(1) %ptr, double 4.0 syncscope("agent") seq_cst @@ -2020,23 +2118,42 @@ main_body: define amdgpu_kernel void @local_atomic_fadd_f64_noret_pat(ptr addrspace(3) %ptr) #1 { ; GFX90A-LABEL: local_atomic_fadd_f64_noret_pat: ; GFX90A: ; %bb.0: ; %main_body +; GFX90A-NEXT: s_mov_b64 s[2:3], exec +; GFX90A-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX90A-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX90A-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX90A-NEXT: s_cbranch_execz .LBB70_2 +; GFX90A-NEXT: ; %bb.1: ; GFX90A-NEXT: s_load_dword s0, s[0:1], 0x24 -; GFX90A-NEXT: v_mov_b32_e32 v0, 0 -; GFX90A-NEXT: v_mov_b32_e32 v1, 0x40100000 +; GFX90A-NEXT: s_bcnt1_i32_b64 s1, s[2:3] +; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s1 +; GFX90A-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: v_mov_b32_e32 v2, s0 ; GFX90A-NEXT: ds_add_f64 v2, v[0:1] ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) +; GFX90A-NEXT: .LBB70_2: ; GFX90A-NEXT: s_endpgm ; ; GFX940-LABEL: local_atomic_fadd_f64_noret_pat: ; GFX940: ; %bb.0: ; %main_body +; GFX940-NEXT: s_mov_b64 s[2:3], exec +; GFX940-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX940-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX940-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX940-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX940-NEXT: s_cbranch_execz .LBB70_2 +; GFX940-NEXT: ; %bb.1: ; GFX940-NEXT: s_load_dword s0, s[0:1], 0x24 -; GFX940-NEXT: v_mov_b64_e32 v[0:1], 4.0 +; GFX940-NEXT: s_bcnt1_i32_b64 s1, s[2:3] +; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s1 +; GFX940-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) ; GFX940-NEXT: v_mov_b32_e32 v2, s0 ; GFX940-NEXT: ds_add_f64 v2, v[0:1] ; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: .LBB70_2: ; GFX940-NEXT: s_endpgm main_body: %ret = atomicrmw fadd ptr addrspace(3) %ptr, double 4.0 seq_cst @@ -2046,23 +2163,42 @@ main_body: define amdgpu_kernel void @local_atomic_fadd_f64_noret_pat_flush(ptr addrspace(3) %ptr) #0 { ; GFX90A-LABEL: local_atomic_fadd_f64_noret_pat_flush: ; GFX90A: ; %bb.0: ; %main_body +; GFX90A-NEXT: s_mov_b64 s[2:3], exec +; GFX90A-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX90A-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX90A-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX90A-NEXT: s_cbranch_execz .LBB71_2 +; GFX90A-NEXT: ; %bb.1: ; GFX90A-NEXT: s_load_dword s0, s[0:1], 0x24 -; GFX90A-NEXT: v_mov_b32_e32 v0, 0 -; GFX90A-NEXT: v_mov_b32_e32 v1, 0x40100000 +; GFX90A-NEXT: s_bcnt1_i32_b64 s1, s[2:3] +; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s1 +; GFX90A-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) ; GFX90A-NEXT: v_mov_b32_e32 v2, s0 ; GFX90A-NEXT: ds_add_f64 v2, v[0:1] ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) +; GFX90A-NEXT: .LBB71_2: ; GFX90A-NEXT: s_endpgm ; ; GFX940-LABEL: local_atomic_fadd_f64_noret_pat_flush: ; GFX940: ; %bb.0: ; %main_body +; GFX940-NEXT: s_mov_b64 s[2:3], exec +; GFX940-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX940-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX940-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX940-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX940-NEXT: s_cbranch_execz .LBB71_2 +; GFX940-NEXT: ; %bb.1: ; GFX940-NEXT: s_load_dword s0, s[0:1], 0x24 -; GFX940-NEXT: v_mov_b64_e32 v[0:1], 4.0 +; GFX940-NEXT: s_bcnt1_i32_b64 s1, s[2:3] +; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s1 +; GFX940-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) ; GFX940-NEXT: v_mov_b32_e32 v2, s0 ; GFX940-NEXT: ds_add_f64 v2, v[0:1] ; GFX940-NEXT: s_waitcnt lgkmcnt(0) +; GFX940-NEXT: .LBB71_2: ; GFX940-NEXT: s_endpgm main_body: %ret = atomicrmw fadd ptr addrspace(3) %ptr, double 4.0 seq_cst @@ -2072,46 +2208,66 @@ main_body: define amdgpu_kernel void @local_atomic_fadd_f64_noret_pat_flush_safe(ptr addrspace(3) %ptr) #4 { ; GFX90A-LABEL: local_atomic_fadd_f64_noret_pat_flush_safe: ; GFX90A: ; %bb.0: ; %main_body -; GFX90A-NEXT: s_load_dword s2, s[0:1], 0x24 -; GFX90A-NEXT: s_mov_b64 s[0:1], 0 +; GFX90A-NEXT: s_mov_b64 s[2:3], exec +; GFX90A-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX90A-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX90A-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX90A-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX90A-NEXT: s_cbranch_execz .LBB72_3 +; GFX90A-NEXT: ; %bb.1: +; GFX90A-NEXT: s_load_dword s4, s[0:1], 0x24 +; GFX90A-NEXT: s_bcnt1_i32_b64 s0, s[2:3] ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) -; GFX90A-NEXT: v_mov_b32_e32 v0, s2 -; GFX90A-NEXT: ds_read_b64 v[0:1], v0 -; GFX90A-NEXT: v_mov_b32_e32 v2, s2 -; GFX90A-NEXT: .LBB72_1: ; %atomicrmw.start +; GFX90A-NEXT: v_mov_b32_e32 v0, s4 +; GFX90A-NEXT: ds_read_b64 v[2:3], v0 +; GFX90A-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX90A-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 +; GFX90A-NEXT: s_mov_b64 s[0:1], 0 +; GFX90A-NEXT: v_mov_b32_e32 v4, s4 +; GFX90A-NEXT: .LBB72_2: ; %atomicrmw.start ; GFX90A-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) -; GFX90A-NEXT: v_add_f64 v[4:5], v[0:1], 4.0 -; GFX90A-NEXT: ds_cmpst_rtn_b64 v[4:5], v2, v[0:1], v[4:5] +; GFX90A-NEXT: v_add_f64 v[6:7], v[2:3], v[0:1] +; GFX90A-NEXT: ds_cmpst_rtn_b64 v[6:7], v4, v[2:3], v[6:7] ; GFX90A-NEXT: s_waitcnt lgkmcnt(0) -; GFX90A-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[0:1] +; GFX90A-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[2:3] ; GFX90A-NEXT: s_or_b64 s[0:1], vcc, s[0:1] -; GFX90A-NEXT: v_pk_mov_b32 v[0:1], v[4:5], v[4:5] op_sel:[0,1] +; GFX90A-NEXT: v_pk_mov_b32 v[2:3], v[6:7], v[6:7] op_sel:[0,1] ; GFX90A-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GFX90A-NEXT: s_cbranch_execnz .LBB72_1 -; GFX90A-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX90A-NEXT: s_cbranch_execnz .LBB72_2 +; GFX90A-NEXT: .LBB72_3: ; GFX90A-NEXT: s_endpgm ; ; GFX940-LABEL: local_atomic_fadd_f64_noret_pat_flush_safe: ; GFX940: ; %bb.0: ; %main_body -; GFX940-NEXT: s_load_dword s2, s[0:1], 0x24 -; GFX940-NEXT: s_mov_b64 s[0:1], 0 +; GFX940-NEXT: s_mov_b64 s[2:3], exec +; GFX940-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX940-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX940-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX940-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX940-NEXT: s_cbranch_execz .LBB72_3 +; GFX940-NEXT: ; %bb.1: +; GFX940-NEXT: s_load_dword s4, s[0:1], 0x24 +; GFX940-NEXT: s_bcnt1_i32_b64 s0, s[2:3] ; GFX940-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-NEXT: v_mov_b32_e32 v0, s2 -; GFX940-NEXT: ds_read_b64 v[0:1], v0 -; GFX940-NEXT: v_mov_b32_e32 v2, s2 -; GFX940-NEXT: .LBB72_1: ; %atomicrmw.start +; GFX940-NEXT: v_mov_b32_e32 v0, s4 +; GFX940-NEXT: ds_read_b64 v[2:3], v0 +; GFX940-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX940-NEXT: v_mul_f64 v[0:1], v[0:1], 4.0 +; GFX940-NEXT: s_mov_b64 s[0:1], 0 +; GFX940-NEXT: v_mov_b32_e32 v4, s4 +; GFX940-NEXT: .LBB72_2: ; %atomicrmw.start ; GFX940-NEXT: ; =>This Inner Loop Header: Depth=1 ; GFX940-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-NEXT: v_add_f64 v[4:5], v[0:1], 4.0 -; GFX940-NEXT: ds_cmpst_rtn_b64 v[4:5], v2, v[0:1], v[4:5] +; GFX940-NEXT: v_add_f64 v[6:7], v[2:3], v[0:1] +; GFX940-NEXT: ds_cmpst_rtn_b64 v[6:7], v4, v[2:3], v[6:7] ; GFX940-NEXT: s_waitcnt lgkmcnt(0) -; GFX940-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[0:1] +; GFX940-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[2:3] ; GFX940-NEXT: s_or_b64 s[0:1], vcc, s[0:1] -; GFX940-NEXT: v_mov_b64_e32 v[0:1], v[4:5] +; GFX940-NEXT: v_mov_b64_e32 v[2:3], v[6:7] ; GFX940-NEXT: s_andn2_b64 exec, exec, s[0:1] -; GFX940-NEXT: s_cbranch_execnz .LBB72_1 -; GFX940-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX940-NEXT: s_cbranch_execnz .LBB72_2 +; GFX940-NEXT: .LBB72_3: ; GFX940-NEXT: s_endpgm main_body: %ret = atomicrmw fadd ptr addrspace(3) %ptr, double 4.0 seq_cst diff --git a/llvm/test/CodeGen/AMDGPU/fptoi.i128.ll b/llvm/test/CodeGen/AMDGPU/fptoi.i128.ll new file mode 100644 index 0000000000000000000000000000000000000000..66bf0d5abb732adca3964ce2395808b64b648fa5 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/fptoi.i128.ll @@ -0,0 +1,1502 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -global-isel=0 -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 < %s | FileCheck -check-prefixes=GCN,SDAG %s +; RUN: llc -global-isel=1 -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 < %s | FileCheck -check-prefixes=GCN,GISEL %s + +define i128 @fptosi_f64_to_i128(double %x) { +; SDAG-LABEL: fptosi_f64_to_i128: +; SDAG: ; %bb.0: ; %fp-to-i-entry +; SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-NEXT: v_mov_b32_e32 v5, v1 +; SDAG-NEXT: v_bfe_u32 v6, v5, 20, 11 +; SDAG-NEXT: v_mov_b32_e32 v7, 0 +; SDAG-NEXT: s_mov_b64 s[4:5], 0x3fe +; SDAG-NEXT: v_mov_b32_e32 v4, v0 +; SDAG-NEXT: v_cmp_lt_u64_e32 vcc, s[4:5], v[6:7] +; SDAG-NEXT: v_mov_b32_e32 v0, 0 +; SDAG-NEXT: v_mov_b32_e32 v2, 0 +; SDAG-NEXT: v_mov_b32_e32 v1, 0 +; SDAG-NEXT: v_mov_b32_e32 v3, 0 +; SDAG-NEXT: s_and_saveexec_b64 s[8:9], vcc +; SDAG-NEXT: s_cbranch_execz .LBB0_10 +; SDAG-NEXT: ; %bb.1: ; %fp-to-i-if-end +; SDAG-NEXT: v_add_co_u32_e32 v0, vcc, 0xfffffb81, v6 +; SDAG-NEXT: v_addc_co_u32_e32 v1, vcc, -1, v7, vcc +; SDAG-NEXT: v_addc_co_u32_e32 v2, vcc, -1, v7, vcc +; SDAG-NEXT: s_movk_i32 s4, 0xff7f +; SDAG-NEXT: v_addc_co_u32_e32 v3, vcc, -1, v7, vcc +; SDAG-NEXT: s_mov_b32 s5, -1 +; SDAG-NEXT: v_cmp_lt_u64_e64 s[4:5], s[4:5], v[0:1] +; SDAG-NEXT: v_cmp_eq_u64_e64 s[6:7], -1, v[2:3] +; SDAG-NEXT: v_cmp_lt_i64_e32 vcc, -1, v[4:5] +; SDAG-NEXT: s_and_b64 s[4:5], s[6:7], s[4:5] +; SDAG-NEXT: ; implicit-def: $vgpr0_vgpr1 +; SDAG-NEXT: ; implicit-def: $vgpr2_vgpr3 +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; SDAG-NEXT: s_xor_b64 s[10:11], exec, s[6:7] +; SDAG-NEXT: s_cbranch_execz .LBB0_7 +; SDAG-NEXT: ; %bb.2: ; %fp-to-i-if-end9 +; SDAG-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; SDAG-NEXT: v_add_co_u32_e64 v9, s[4:5], -1, v0 +; SDAG-NEXT: v_addc_co_u32_e64 v10, s[4:5], 0, -1, s[4:5] +; SDAG-NEXT: s_mov_b64 s[4:5], 0x432 +; SDAG-NEXT: v_and_b32_e32 v0, 0xfffff, v5 +; SDAG-NEXT: v_cmp_lt_u64_e64 s[4:5], s[4:5], v[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v8, -1, 0, vcc +; SDAG-NEXT: v_cndmask_b32_e64 v11, -1, 1, vcc +; SDAG-NEXT: v_or_b32_e32 v5, 0x100000, v0 +; SDAG-NEXT: ; implicit-def: $vgpr0_vgpr1 +; SDAG-NEXT: ; implicit-def: $vgpr2_vgpr3 +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; SDAG-NEXT: s_xor_b64 s[12:13], exec, s[6:7] +; SDAG-NEXT: s_cbranch_execz .LBB0_4 +; SDAG-NEXT: ; %bb.3: ; %fp-to-i-if-else +; SDAG-NEXT: v_sub_u32_e32 v0, 0x473, v6 +; SDAG-NEXT: v_add_u32_e32 v2, 0xfffffb8d, v6 +; SDAG-NEXT: v_add_u32_e32 v7, 0xfffffbcd, v6 +; SDAG-NEXT: v_lshrrev_b64 v[0:1], v0, v[4:5] +; SDAG-NEXT: v_lshlrev_b64 v[2:3], v2, v[4:5] +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v7 +; SDAG-NEXT: v_cndmask_b32_e64 v1, v3, v1, s[4:5] +; SDAG-NEXT: v_cmp_ne_u32_e64 s[6:7], 0, v7 +; SDAG-NEXT: v_cndmask_b32_e64 v6, 0, v1, s[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v2, v2, v0, s[4:5] +; SDAG-NEXT: v_lshlrev_b64 v[0:1], v7, v[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v2, 0, v2, s[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v12, 0, v0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v7, 0, v1, s[4:5] +; SDAG-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v12, v11, 0 +; SDAG-NEXT: v_mov_b32_e32 v3, 0 +; SDAG-NEXT: v_mul_lo_u32 v13, v8, v2 +; SDAG-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v11, v2, 0 +; SDAG-NEXT: v_mov_b32_e32 v2, v1 +; SDAG-NEXT: v_mul_lo_u32 v6, v11, v6 +; SDAG-NEXT: v_mad_u64_u32 v[1:2], s[4:5], v7, v11, v[2:3] +; SDAG-NEXT: v_mul_lo_u32 v10, v10, v12 +; SDAG-NEXT: v_add3_u32 v5, v5, v6, v13 +; SDAG-NEXT: v_mov_b32_e32 v6, v2 +; SDAG-NEXT: v_mov_b32_e32 v2, v3 +; SDAG-NEXT: v_mad_u64_u32 v[1:2], s[4:5], v12, v8, v[1:2] +; SDAG-NEXT: v_mad_u64_u32 v[3:4], s[4:5], v9, v12, v[4:5] +; SDAG-NEXT: v_add_co_u32_e64 v5, s[4:5], v6, v2 +; SDAG-NEXT: v_addc_co_u32_e64 v6, s[4:5], 0, 0, s[4:5] +; SDAG-NEXT: v_mul_lo_u32 v9, v9, v7 +; SDAG-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v7, v8, v[5:6] +; SDAG-NEXT: ; implicit-def: $vgpr11 +; SDAG-NEXT: ; implicit-def: $vgpr8 +; SDAG-NEXT: v_add3_u32 v4, v10, v4, v9 +; SDAG-NEXT: v_add_co_u32_e64 v2, s[4:5], v5, v3 +; SDAG-NEXT: v_addc_co_u32_e64 v3, s[4:5], v6, v4, s[4:5] +; SDAG-NEXT: ; implicit-def: $vgpr6_vgpr7 +; SDAG-NEXT: ; implicit-def: $vgpr4_vgpr5 +; SDAG-NEXT: ; implicit-def: $vgpr9 +; SDAG-NEXT: ; implicit-def: $vgpr10 +; SDAG-NEXT: .LBB0_4: ; %Flow +; SDAG-NEXT: s_andn2_saveexec_b64 s[12:13], s[12:13] +; SDAG-NEXT: s_cbranch_execz .LBB0_6 +; SDAG-NEXT: ; %bb.5: ; %fp-to-i-if-then12 +; SDAG-NEXT: v_sub_u32_e32 v2, 0x433, v6 +; SDAG-NEXT: v_lshrrev_b64 v[0:1], v2, v[4:5] +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v2 +; SDAG-NEXT: v_cmp_eq_u32_e64 s[6:7], 0, v2 +; SDAG-NEXT: v_cndmask_b32_e64 v0, 0, v0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v1, 0, v1, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v6, v0, v4, s[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v5, v1, v5, s[6:7] +; SDAG-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v6, v11, 0 +; SDAG-NEXT: v_mov_b32_e32 v2, 0 +; SDAG-NEXT: v_mad_u64_u32 v[3:4], s[4:5], v5, v11, v[1:2] +; SDAG-NEXT: v_mov_b32_e32 v7, v4 +; SDAG-NEXT: v_mov_b32_e32 v4, v2 +; SDAG-NEXT: v_mad_u64_u32 v[1:2], s[4:5], v6, v8, v[3:4] +; SDAG-NEXT: v_add_co_u32_e64 v2, s[4:5], v7, v2 +; SDAG-NEXT: v_addc_co_u32_e64 v3, s[4:5], 0, 0, s[4:5] +; SDAG-NEXT: v_mad_u64_u32 v[2:3], s[4:5], v5, v8, v[2:3] +; SDAG-NEXT: v_mad_u64_u32 v[2:3], s[4:5], v9, v6, v[2:3] +; SDAG-NEXT: v_mad_u64_u32 v[3:4], s[4:5], v10, v6, v[3:4] +; SDAG-NEXT: v_mad_i32_i24 v3, v9, v5, v3 +; SDAG-NEXT: .LBB0_6: ; %Flow1 +; SDAG-NEXT: s_or_b64 exec, exec, s[12:13] +; SDAG-NEXT: .LBB0_7: ; %Flow2 +; SDAG-NEXT: s_andn2_saveexec_b64 s[4:5], s[10:11] +; SDAG-NEXT: ; %bb.8: ; %fp-to-i-if-then5 +; SDAG-NEXT: v_bfrev_b32_e32 v0, 1 +; SDAG-NEXT: v_bfrev_b32_e32 v1, -2 +; SDAG-NEXT: v_cndmask_b32_e64 v2, 0, -1, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v3, v0, v1, vcc +; SDAG-NEXT: v_mov_b32_e32 v0, v2 +; SDAG-NEXT: v_mov_b32_e32 v1, v2 +; SDAG-NEXT: ; %bb.9: ; %Flow3 +; SDAG-NEXT: s_or_b64 exec, exec, s[4:5] +; SDAG-NEXT: .LBB0_10: ; %fp-to-i-cleanup +; SDAG-NEXT: s_or_b64 exec, exec, s[8:9] +; SDAG-NEXT: s_setpc_b64 s[30:31] +; +; GISEL-LABEL: fptosi_f64_to_i128: +; GISEL: ; %bb.0: ; %fp-to-i-entry +; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-NEXT: v_mov_b32_e32 v5, v1 +; GISEL-NEXT: v_mov_b32_e32 v4, v0 +; GISEL-NEXT: v_lshrrev_b32_e32 v0, 20, v5 +; GISEL-NEXT: v_and_b32_e32 v6, 0x7ff, v0 +; GISEL-NEXT: v_mov_b32_e32 v0, 0x3ff +; GISEL-NEXT: s_mov_b64 s[4:5], 0 +; GISEL-NEXT: v_mov_b32_e32 v1, 0 +; GISEL-NEXT: v_mov_b32_e32 v7, 0 +; GISEL-NEXT: v_cmp_ge_u64_e32 vcc, v[6:7], v[0:1] +; GISEL-NEXT: s_mov_b64 s[6:7], s[4:5] +; GISEL-NEXT: v_mov_b32_e32 v0, s4 +; GISEL-NEXT: v_mov_b32_e32 v1, s5 +; GISEL-NEXT: v_mov_b32_e32 v2, s6 +; GISEL-NEXT: v_mov_b32_e32 v3, s7 +; GISEL-NEXT: s_and_saveexec_b64 s[12:13], vcc +; GISEL-NEXT: s_cbranch_execz .LBB0_10 +; GISEL-NEXT: ; %bb.1: ; %fp-to-i-if-end +; GISEL-NEXT: v_add_co_u32_e32 v0, vcc, 0xfffffb81, v6 +; GISEL-NEXT: v_mov_b32_e32 v2, 0xffffff80 +; GISEL-NEXT: v_addc_co_u32_e64 v1, s[6:7], 0, -1, vcc +; GISEL-NEXT: v_mov_b32_e32 v3, -1 +; GISEL-NEXT: v_addc_co_u32_e64 v8, s[6:7], 0, -1, s[6:7] +; GISEL-NEXT: v_cmp_ge_u64_e32 vcc, v[0:1], v[2:3] +; GISEL-NEXT: v_addc_co_u32_e64 v9, s[6:7], 0, -1, s[6:7] +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; GISEL-NEXT: v_cmp_le_u64_e32 vcc, -1, v[8:9] +; GISEL-NEXT: v_cmp_lt_i64_e64 s[4:5], -1, v[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, -1, v[8:9] +; GISEL-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc +; GISEL-NEXT: v_and_b32_e32 v0, 1, v0 +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v0 +; GISEL-NEXT: ; implicit-def: $vgpr0_vgpr1_vgpr2_vgpr3 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], vcc +; GISEL-NEXT: s_xor_b64 s[14:15], exec, s[6:7] +; GISEL-NEXT: s_cbranch_execz .LBB0_7 +; GISEL-NEXT: ; %bb.2: ; %fp-to-i-if-end9 +; GISEL-NEXT: s_xor_b64 s[6:7], s[4:5], -1 +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, -1, s[6:7] +; GISEL-NEXT: v_and_b32_e32 v0, 1, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v2, 1, v0 +; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, 1, s[6:7] +; GISEL-NEXT: v_lshlrev_b16_e32 v3, 2, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v8, 3, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v9, 4, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v10, 5, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v11, 6, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v12, 7, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v13, 8, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v14, 9, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v15, 10, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v16, 11, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v17, 12, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v18, 13, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v19, 14, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v20, 15, v0 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v2 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v2 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v3 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v3 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v8 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v8 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v9 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v9 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v10 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v10 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v11 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v11 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v12 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v12 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v13 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v13 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v14 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v14 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v15 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v15 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v16 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v16 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v17 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v17 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v18 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v18 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v19 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v19 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v20 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v20 +; GISEL-NEXT: v_and_b32_e32 v0, 0xffff, v0 +; GISEL-NEXT: v_and_b32_e32 v1, 0xffff, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v2, 16, v0 +; GISEL-NEXT: v_lshl_or_b32 v10, v0, 16, v0 +; GISEL-NEXT: v_or3_b32 v8, v1, v2, 1 +; GISEL-NEXT: v_or3_b32 v9, v0, v2, 0 +; GISEL-NEXT: v_mov_b32_e32 v0, 0x433 +; GISEL-NEXT: v_mov_b32_e32 v1, 0 +; GISEL-NEXT: v_and_b32_e32 v2, 0xfffff, v5 +; GISEL-NEXT: v_cmp_ge_u64_e32 vcc, v[6:7], v[0:1] +; GISEL-NEXT: v_or_b32_e32 v5, 0x100000, v2 +; GISEL-NEXT: ; implicit-def: $vgpr0_vgpr1_vgpr2_vgpr3 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], vcc +; GISEL-NEXT: s_xor_b64 s[16:17], exec, s[6:7] +; GISEL-NEXT: s_cbranch_execz .LBB0_4 +; GISEL-NEXT: ; %bb.3: ; %fp-to-i-if-else +; GISEL-NEXT: v_add_u32_e32 v6, 0xfffffbcd, v6 +; GISEL-NEXT: v_lshlrev_b64 v[0:1], v6, v[4:5] +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v6 +; GISEL-NEXT: v_cndmask_b32_e32 v11, 0, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v12, 0, v1, vcc +; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[6:7], v11, v10, 0 +; GISEL-NEXT: v_subrev_u32_e32 v7, 64, v6 +; GISEL-NEXT: v_sub_u32_e32 v2, 64, v6 +; GISEL-NEXT: v_lshrrev_b64 v[2:3], v2, v[4:5] +; GISEL-NEXT: v_lshlrev_b64 v[4:5], v7, v[4:5] +; GISEL-NEXT: v_cmp_eq_u32_e64 s[6:7], 0, v6 +; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[8:9], v12, v9, v[0:1] +; GISEL-NEXT: v_cndmask_b32_e32 v2, v4, v2, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v13, v2, 0, s[6:7] +; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[8:9], v13, v8, v[6:7] +; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[8:9], v11, v8, 0 +; GISEL-NEXT: v_mov_b32_e32 v2, v6 +; GISEL-NEXT: v_mul_lo_u32 v6, v11, v10 +; GISEL-NEXT: v_mad_u64_u32 v[1:2], s[8:9], v11, v9, v[1:2] +; GISEL-NEXT: v_mul_lo_u32 v4, v12, v10 +; GISEL-NEXT: v_cndmask_b32_e32 v3, v5, v3, vcc +; GISEL-NEXT: v_mad_u64_u32 v[1:2], s[10:11], v12, v8, v[1:2] +; GISEL-NEXT: v_addc_co_u32_e64 v6, s[10:11], v7, v6, s[10:11] +; GISEL-NEXT: v_addc_co_u32_e64 v4, s[8:9], v6, v4, s[8:9] +; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[8:9], v13, v9, v[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v3, v3, 0, s[6:7] +; GISEL-NEXT: ; implicit-def: $vgpr10 +; GISEL-NEXT: ; implicit-def: $vgpr9 +; GISEL-NEXT: v_mad_u64_u32 v[3:4], s[6:7], v3, v8, v[6:7] +; GISEL-NEXT: ; implicit-def: $vgpr6 +; GISEL-NEXT: ; implicit-def: $vgpr4_vgpr5 +; GISEL-NEXT: ; implicit-def: $vgpr8 +; GISEL-NEXT: .LBB0_4: ; %Flow +; GISEL-NEXT: s_andn2_saveexec_b64 s[8:9], s[16:17] +; GISEL-NEXT: s_cbranch_execz .LBB0_6 +; GISEL-NEXT: ; %bb.5: ; %fp-to-i-if-then12 +; GISEL-NEXT: v_sub_co_u32_e32 v6, vcc, 0x433, v6 +; GISEL-NEXT: v_subrev_u32_e32 v2, 64, v6 +; GISEL-NEXT: v_lshrrev_b64 v[0:1], v6, v[4:5] +; GISEL-NEXT: v_lshrrev_b64 v[2:3], v2, 0 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v6 +; GISEL-NEXT: v_cndmask_b32_e32 v0, v2, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v6 +; GISEL-NEXT: v_cndmask_b32_e32 v4, v0, v4, vcc +; GISEL-NEXT: v_mad_u64_u32 v[2:3], s[6:7], v4, v10, 0 +; GISEL-NEXT: v_cndmask_b32_e32 v5, v1, v5, vcc +; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[6:7], v4, v8, 0 +; GISEL-NEXT: v_mad_u64_u32 v[2:3], s[6:7], v5, v9, v[2:3] +; GISEL-NEXT: v_mul_lo_u32 v6, v5, v10 +; GISEL-NEXT: v_mad_u64_u32 v[1:2], vcc, v4, v9, v[1:2] +; GISEL-NEXT: v_mul_lo_u32 v4, v4, v10 +; GISEL-NEXT: v_mad_u64_u32 v[1:2], s[6:7], v5, v8, v[1:2] +; GISEL-NEXT: v_addc_co_u32_e64 v3, s[6:7], v3, v4, s[6:7] +; GISEL-NEXT: v_addc_co_u32_e32 v3, vcc, v3, v6, vcc +; GISEL-NEXT: .LBB0_6: ; %Flow1 +; GISEL-NEXT: s_or_b64 exec, exec, s[8:9] +; GISEL-NEXT: .LBB0_7: ; %Flow2 +; GISEL-NEXT: s_andn2_saveexec_b64 s[6:7], s[14:15] +; GISEL-NEXT: s_cbranch_execz .LBB0_9 +; GISEL-NEXT: ; %bb.8: ; %fp-to-i-if-then5 +; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, -1, s[4:5] +; GISEL-NEXT: v_and_b32_e32 v1, 1, v1 +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, s[4:5] +; GISEL-NEXT: v_lshlrev_b32_e32 v2, 1, v1 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v2 +; GISEL-NEXT: v_lshlrev_b32_e32 v3, 2, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v4, 3, v1 +; GISEL-NEXT: v_or_b32_e32 v2, v1, v2 +; GISEL-NEXT: v_or3_b32 v0, v0, v3, v4 +; GISEL-NEXT: v_lshlrev_b32_e32 v5, 4, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v6, 5, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v3, v4 +; GISEL-NEXT: v_or3_b32 v0, v0, v5, v6 +; GISEL-NEXT: v_lshlrev_b32_e32 v7, 6, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v8, 7, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v5, v6 +; GISEL-NEXT: v_or3_b32 v0, v0, v7, v8 +; GISEL-NEXT: v_lshlrev_b32_e32 v9, 8, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v10, 9, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v7, v8 +; GISEL-NEXT: v_or3_b32 v0, v0, v9, v10 +; GISEL-NEXT: v_lshlrev_b32_e32 v11, 10, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v12, 11, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v9, v10 +; GISEL-NEXT: v_or3_b32 v0, v0, v11, v12 +; GISEL-NEXT: v_lshlrev_b32_e32 v13, 12, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v14, 13, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v11, v12 +; GISEL-NEXT: v_or3_b32 v0, v0, v13, v14 +; GISEL-NEXT: v_lshlrev_b32_e32 v15, 14, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v16, 15, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v13, v14 +; GISEL-NEXT: v_or3_b32 v0, v0, v15, v16 +; GISEL-NEXT: v_lshlrev_b32_e32 v17, 16, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v18, 17, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v15, v16 +; GISEL-NEXT: v_or3_b32 v0, v0, v17, v18 +; GISEL-NEXT: v_lshlrev_b32_e32 v19, 18, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v20, 19, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v17, v18 +; GISEL-NEXT: v_or3_b32 v0, v0, v19, v20 +; GISEL-NEXT: v_lshlrev_b32_e32 v3, 20, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v4, 21, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v19, v20 +; GISEL-NEXT: v_or3_b32 v0, v0, v3, v4 +; GISEL-NEXT: v_lshlrev_b32_e32 v5, 22, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v6, 23, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v3, v4 +; GISEL-NEXT: v_or3_b32 v0, v0, v5, v6 +; GISEL-NEXT: v_lshlrev_b32_e32 v7, 24, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v8, 25, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v5, v6 +; GISEL-NEXT: v_or3_b32 v0, v0, v7, v8 +; GISEL-NEXT: v_lshlrev_b32_e32 v9, 26, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v10, 27, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v7, v8 +; GISEL-NEXT: v_or3_b32 v0, v0, v9, v10 +; GISEL-NEXT: v_lshlrev_b32_e32 v11, 28, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v12, 29, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v9, v10 +; GISEL-NEXT: v_or3_b32 v0, v0, v11, v12 +; GISEL-NEXT: v_lshlrev_b32_e32 v13, 30, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v1, 31, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v11, v12 +; GISEL-NEXT: v_or3_b32 v0, v0, v13, v1 +; GISEL-NEXT: v_or3_b32 v1, v2, v13, v1 +; GISEL-NEXT: v_add_u32_e32 v3, 0x80000000, v1 +; GISEL-NEXT: v_mov_b32_e32 v2, v1 +; GISEL-NEXT: .LBB0_9: ; %Flow3 +; GISEL-NEXT: s_or_b64 exec, exec, s[6:7] +; GISEL-NEXT: .LBB0_10: ; %fp-to-i-cleanup +; GISEL-NEXT: s_or_b64 exec, exec, s[12:13] +; GISEL-NEXT: s_setpc_b64 s[30:31] + %cvt = fptosi double %x to i128 + ret i128 %cvt +} + +define i128 @fptoui_f64_to_i128(double %x) { +; SDAG-LABEL: fptoui_f64_to_i128: +; SDAG: ; %bb.0: ; %fp-to-i-entry +; SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-NEXT: v_mov_b32_e32 v5, v1 +; SDAG-NEXT: v_bfe_u32 v6, v5, 20, 11 +; SDAG-NEXT: v_mov_b32_e32 v7, 0 +; SDAG-NEXT: s_mov_b64 s[4:5], 0x3fe +; SDAG-NEXT: v_mov_b32_e32 v4, v0 +; SDAG-NEXT: v_cmp_lt_u64_e32 vcc, s[4:5], v[6:7] +; SDAG-NEXT: v_mov_b32_e32 v0, 0 +; SDAG-NEXT: v_mov_b32_e32 v2, 0 +; SDAG-NEXT: v_mov_b32_e32 v1, 0 +; SDAG-NEXT: v_mov_b32_e32 v3, 0 +; SDAG-NEXT: s_and_saveexec_b64 s[8:9], vcc +; SDAG-NEXT: s_cbranch_execz .LBB1_10 +; SDAG-NEXT: ; %bb.1: ; %fp-to-i-if-end +; SDAG-NEXT: v_add_co_u32_e32 v0, vcc, 0xfffffb81, v6 +; SDAG-NEXT: v_addc_co_u32_e32 v1, vcc, -1, v7, vcc +; SDAG-NEXT: v_addc_co_u32_e32 v2, vcc, -1, v7, vcc +; SDAG-NEXT: s_movk_i32 s4, 0xff7f +; SDAG-NEXT: v_addc_co_u32_e32 v3, vcc, -1, v7, vcc +; SDAG-NEXT: s_mov_b32 s5, -1 +; SDAG-NEXT: v_cmp_lt_u64_e64 s[4:5], s[4:5], v[0:1] +; SDAG-NEXT: v_cmp_eq_u64_e64 s[6:7], -1, v[2:3] +; SDAG-NEXT: v_cmp_lt_i64_e32 vcc, -1, v[4:5] +; SDAG-NEXT: s_and_b64 s[4:5], s[6:7], s[4:5] +; SDAG-NEXT: ; implicit-def: $vgpr0_vgpr1 +; SDAG-NEXT: ; implicit-def: $vgpr2_vgpr3 +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; SDAG-NEXT: s_xor_b64 s[10:11], exec, s[6:7] +; SDAG-NEXT: s_cbranch_execz .LBB1_7 +; SDAG-NEXT: ; %bb.2: ; %fp-to-i-if-end9 +; SDAG-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; SDAG-NEXT: v_add_co_u32_e64 v9, s[4:5], -1, v0 +; SDAG-NEXT: v_addc_co_u32_e64 v10, s[4:5], 0, -1, s[4:5] +; SDAG-NEXT: s_mov_b64 s[4:5], 0x432 +; SDAG-NEXT: v_and_b32_e32 v0, 0xfffff, v5 +; SDAG-NEXT: v_cmp_lt_u64_e64 s[4:5], s[4:5], v[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v8, -1, 0, vcc +; SDAG-NEXT: v_cndmask_b32_e64 v11, -1, 1, vcc +; SDAG-NEXT: v_or_b32_e32 v5, 0x100000, v0 +; SDAG-NEXT: ; implicit-def: $vgpr0_vgpr1 +; SDAG-NEXT: ; implicit-def: $vgpr2_vgpr3 +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; SDAG-NEXT: s_xor_b64 s[12:13], exec, s[6:7] +; SDAG-NEXT: s_cbranch_execz .LBB1_4 +; SDAG-NEXT: ; %bb.3: ; %fp-to-i-if-else +; SDAG-NEXT: v_sub_u32_e32 v0, 0x473, v6 +; SDAG-NEXT: v_add_u32_e32 v2, 0xfffffb8d, v6 +; SDAG-NEXT: v_add_u32_e32 v7, 0xfffffbcd, v6 +; SDAG-NEXT: v_lshrrev_b64 v[0:1], v0, v[4:5] +; SDAG-NEXT: v_lshlrev_b64 v[2:3], v2, v[4:5] +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v7 +; SDAG-NEXT: v_cndmask_b32_e64 v1, v3, v1, s[4:5] +; SDAG-NEXT: v_cmp_ne_u32_e64 s[6:7], 0, v7 +; SDAG-NEXT: v_cndmask_b32_e64 v6, 0, v1, s[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v2, v2, v0, s[4:5] +; SDAG-NEXT: v_lshlrev_b64 v[0:1], v7, v[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v2, 0, v2, s[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v12, 0, v0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v7, 0, v1, s[4:5] +; SDAG-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v12, v11, 0 +; SDAG-NEXT: v_mov_b32_e32 v3, 0 +; SDAG-NEXT: v_mul_lo_u32 v13, v8, v2 +; SDAG-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v11, v2, 0 +; SDAG-NEXT: v_mov_b32_e32 v2, v1 +; SDAG-NEXT: v_mul_lo_u32 v6, v11, v6 +; SDAG-NEXT: v_mad_u64_u32 v[1:2], s[4:5], v7, v11, v[2:3] +; SDAG-NEXT: v_mul_lo_u32 v10, v10, v12 +; SDAG-NEXT: v_add3_u32 v5, v5, v6, v13 +; SDAG-NEXT: v_mov_b32_e32 v6, v2 +; SDAG-NEXT: v_mov_b32_e32 v2, v3 +; SDAG-NEXT: v_mad_u64_u32 v[1:2], s[4:5], v12, v8, v[1:2] +; SDAG-NEXT: v_mad_u64_u32 v[3:4], s[4:5], v9, v12, v[4:5] +; SDAG-NEXT: v_add_co_u32_e64 v5, s[4:5], v6, v2 +; SDAG-NEXT: v_addc_co_u32_e64 v6, s[4:5], 0, 0, s[4:5] +; SDAG-NEXT: v_mul_lo_u32 v9, v9, v7 +; SDAG-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v7, v8, v[5:6] +; SDAG-NEXT: ; implicit-def: $vgpr11 +; SDAG-NEXT: ; implicit-def: $vgpr8 +; SDAG-NEXT: v_add3_u32 v4, v10, v4, v9 +; SDAG-NEXT: v_add_co_u32_e64 v2, s[4:5], v5, v3 +; SDAG-NEXT: v_addc_co_u32_e64 v3, s[4:5], v6, v4, s[4:5] +; SDAG-NEXT: ; implicit-def: $vgpr6_vgpr7 +; SDAG-NEXT: ; implicit-def: $vgpr4_vgpr5 +; SDAG-NEXT: ; implicit-def: $vgpr9 +; SDAG-NEXT: ; implicit-def: $vgpr10 +; SDAG-NEXT: .LBB1_4: ; %Flow +; SDAG-NEXT: s_andn2_saveexec_b64 s[12:13], s[12:13] +; SDAG-NEXT: s_cbranch_execz .LBB1_6 +; SDAG-NEXT: ; %bb.5: ; %fp-to-i-if-then12 +; SDAG-NEXT: v_sub_u32_e32 v2, 0x433, v6 +; SDAG-NEXT: v_lshrrev_b64 v[0:1], v2, v[4:5] +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v2 +; SDAG-NEXT: v_cmp_eq_u32_e64 s[6:7], 0, v2 +; SDAG-NEXT: v_cndmask_b32_e64 v0, 0, v0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v1, 0, v1, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v6, v0, v4, s[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v5, v1, v5, s[6:7] +; SDAG-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v6, v11, 0 +; SDAG-NEXT: v_mov_b32_e32 v2, 0 +; SDAG-NEXT: v_mad_u64_u32 v[3:4], s[4:5], v5, v11, v[1:2] +; SDAG-NEXT: v_mov_b32_e32 v7, v4 +; SDAG-NEXT: v_mov_b32_e32 v4, v2 +; SDAG-NEXT: v_mad_u64_u32 v[1:2], s[4:5], v6, v8, v[3:4] +; SDAG-NEXT: v_add_co_u32_e64 v2, s[4:5], v7, v2 +; SDAG-NEXT: v_addc_co_u32_e64 v3, s[4:5], 0, 0, s[4:5] +; SDAG-NEXT: v_mad_u64_u32 v[2:3], s[4:5], v5, v8, v[2:3] +; SDAG-NEXT: v_mad_u64_u32 v[2:3], s[4:5], v9, v6, v[2:3] +; SDAG-NEXT: v_mad_u64_u32 v[3:4], s[4:5], v10, v6, v[3:4] +; SDAG-NEXT: v_mad_i32_i24 v3, v9, v5, v3 +; SDAG-NEXT: .LBB1_6: ; %Flow1 +; SDAG-NEXT: s_or_b64 exec, exec, s[12:13] +; SDAG-NEXT: .LBB1_7: ; %Flow2 +; SDAG-NEXT: s_andn2_saveexec_b64 s[4:5], s[10:11] +; SDAG-NEXT: ; %bb.8: ; %fp-to-i-if-then5 +; SDAG-NEXT: v_bfrev_b32_e32 v0, 1 +; SDAG-NEXT: v_bfrev_b32_e32 v1, -2 +; SDAG-NEXT: v_cndmask_b32_e64 v2, 0, -1, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v3, v0, v1, vcc +; SDAG-NEXT: v_mov_b32_e32 v0, v2 +; SDAG-NEXT: v_mov_b32_e32 v1, v2 +; SDAG-NEXT: ; %bb.9: ; %Flow3 +; SDAG-NEXT: s_or_b64 exec, exec, s[4:5] +; SDAG-NEXT: .LBB1_10: ; %fp-to-i-cleanup +; SDAG-NEXT: s_or_b64 exec, exec, s[8:9] +; SDAG-NEXT: s_setpc_b64 s[30:31] +; +; GISEL-LABEL: fptoui_f64_to_i128: +; GISEL: ; %bb.0: ; %fp-to-i-entry +; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-NEXT: v_mov_b32_e32 v5, v1 +; GISEL-NEXT: v_mov_b32_e32 v4, v0 +; GISEL-NEXT: v_lshrrev_b32_e32 v0, 20, v5 +; GISEL-NEXT: v_and_b32_e32 v6, 0x7ff, v0 +; GISEL-NEXT: v_mov_b32_e32 v0, 0x3ff +; GISEL-NEXT: s_mov_b64 s[4:5], 0 +; GISEL-NEXT: v_mov_b32_e32 v1, 0 +; GISEL-NEXT: v_mov_b32_e32 v7, 0 +; GISEL-NEXT: v_cmp_ge_u64_e32 vcc, v[6:7], v[0:1] +; GISEL-NEXT: s_mov_b64 s[6:7], s[4:5] +; GISEL-NEXT: v_mov_b32_e32 v0, s4 +; GISEL-NEXT: v_mov_b32_e32 v1, s5 +; GISEL-NEXT: v_mov_b32_e32 v2, s6 +; GISEL-NEXT: v_mov_b32_e32 v3, s7 +; GISEL-NEXT: s_and_saveexec_b64 s[12:13], vcc +; GISEL-NEXT: s_cbranch_execz .LBB1_10 +; GISEL-NEXT: ; %bb.1: ; %fp-to-i-if-end +; GISEL-NEXT: v_add_co_u32_e32 v0, vcc, 0xfffffb81, v6 +; GISEL-NEXT: v_mov_b32_e32 v2, 0xffffff80 +; GISEL-NEXT: v_addc_co_u32_e64 v1, s[6:7], 0, -1, vcc +; GISEL-NEXT: v_mov_b32_e32 v3, -1 +; GISEL-NEXT: v_addc_co_u32_e64 v8, s[6:7], 0, -1, s[6:7] +; GISEL-NEXT: v_cmp_ge_u64_e32 vcc, v[0:1], v[2:3] +; GISEL-NEXT: v_addc_co_u32_e64 v9, s[6:7], 0, -1, s[6:7] +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; GISEL-NEXT: v_cmp_le_u64_e32 vcc, -1, v[8:9] +; GISEL-NEXT: v_cmp_lt_i64_e64 s[4:5], -1, v[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, -1, v[8:9] +; GISEL-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc +; GISEL-NEXT: v_and_b32_e32 v0, 1, v0 +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v0 +; GISEL-NEXT: ; implicit-def: $vgpr0_vgpr1_vgpr2_vgpr3 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], vcc +; GISEL-NEXT: s_xor_b64 s[14:15], exec, s[6:7] +; GISEL-NEXT: s_cbranch_execz .LBB1_7 +; GISEL-NEXT: ; %bb.2: ; %fp-to-i-if-end9 +; GISEL-NEXT: s_xor_b64 s[6:7], s[4:5], -1 +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, -1, s[6:7] +; GISEL-NEXT: v_and_b32_e32 v0, 1, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v2, 1, v0 +; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, 1, s[6:7] +; GISEL-NEXT: v_lshlrev_b16_e32 v3, 2, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v8, 3, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v9, 4, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v10, 5, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v11, 6, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v12, 7, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v13, 8, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v14, 9, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v15, 10, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v16, 11, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v17, 12, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v18, 13, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v19, 14, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v20, 15, v0 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v2 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v2 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v3 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v3 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v8 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v8 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v9 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v9 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v10 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v10 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v11 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v11 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v12 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v12 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v13 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v13 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v14 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v14 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v15 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v15 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v16 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v16 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v17 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v17 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v18 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v18 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v19 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v19 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v20 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v20 +; GISEL-NEXT: v_and_b32_e32 v0, 0xffff, v0 +; GISEL-NEXT: v_and_b32_e32 v1, 0xffff, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v2, 16, v0 +; GISEL-NEXT: v_lshl_or_b32 v10, v0, 16, v0 +; GISEL-NEXT: v_or3_b32 v8, v1, v2, 1 +; GISEL-NEXT: v_or3_b32 v9, v0, v2, 0 +; GISEL-NEXT: v_mov_b32_e32 v0, 0x433 +; GISEL-NEXT: v_mov_b32_e32 v1, 0 +; GISEL-NEXT: v_and_b32_e32 v2, 0xfffff, v5 +; GISEL-NEXT: v_cmp_ge_u64_e32 vcc, v[6:7], v[0:1] +; GISEL-NEXT: v_or_b32_e32 v5, 0x100000, v2 +; GISEL-NEXT: ; implicit-def: $vgpr0_vgpr1_vgpr2_vgpr3 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], vcc +; GISEL-NEXT: s_xor_b64 s[16:17], exec, s[6:7] +; GISEL-NEXT: s_cbranch_execz .LBB1_4 +; GISEL-NEXT: ; %bb.3: ; %fp-to-i-if-else +; GISEL-NEXT: v_add_u32_e32 v6, 0xfffffbcd, v6 +; GISEL-NEXT: v_lshlrev_b64 v[0:1], v6, v[4:5] +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v6 +; GISEL-NEXT: v_cndmask_b32_e32 v11, 0, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v12, 0, v1, vcc +; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[6:7], v11, v10, 0 +; GISEL-NEXT: v_subrev_u32_e32 v7, 64, v6 +; GISEL-NEXT: v_sub_u32_e32 v2, 64, v6 +; GISEL-NEXT: v_lshrrev_b64 v[2:3], v2, v[4:5] +; GISEL-NEXT: v_lshlrev_b64 v[4:5], v7, v[4:5] +; GISEL-NEXT: v_cmp_eq_u32_e64 s[6:7], 0, v6 +; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[8:9], v12, v9, v[0:1] +; GISEL-NEXT: v_cndmask_b32_e32 v2, v4, v2, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v13, v2, 0, s[6:7] +; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[8:9], v13, v8, v[6:7] +; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[8:9], v11, v8, 0 +; GISEL-NEXT: v_mov_b32_e32 v2, v6 +; GISEL-NEXT: v_mul_lo_u32 v6, v11, v10 +; GISEL-NEXT: v_mad_u64_u32 v[1:2], s[8:9], v11, v9, v[1:2] +; GISEL-NEXT: v_mul_lo_u32 v4, v12, v10 +; GISEL-NEXT: v_cndmask_b32_e32 v3, v5, v3, vcc +; GISEL-NEXT: v_mad_u64_u32 v[1:2], s[10:11], v12, v8, v[1:2] +; GISEL-NEXT: v_addc_co_u32_e64 v6, s[10:11], v7, v6, s[10:11] +; GISEL-NEXT: v_addc_co_u32_e64 v4, s[8:9], v6, v4, s[8:9] +; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[8:9], v13, v9, v[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v3, v3, 0, s[6:7] +; GISEL-NEXT: ; implicit-def: $vgpr10 +; GISEL-NEXT: ; implicit-def: $vgpr9 +; GISEL-NEXT: v_mad_u64_u32 v[3:4], s[6:7], v3, v8, v[6:7] +; GISEL-NEXT: ; implicit-def: $vgpr6 +; GISEL-NEXT: ; implicit-def: $vgpr4_vgpr5 +; GISEL-NEXT: ; implicit-def: $vgpr8 +; GISEL-NEXT: .LBB1_4: ; %Flow +; GISEL-NEXT: s_andn2_saveexec_b64 s[8:9], s[16:17] +; GISEL-NEXT: s_cbranch_execz .LBB1_6 +; GISEL-NEXT: ; %bb.5: ; %fp-to-i-if-then12 +; GISEL-NEXT: v_sub_co_u32_e32 v6, vcc, 0x433, v6 +; GISEL-NEXT: v_subrev_u32_e32 v2, 64, v6 +; GISEL-NEXT: v_lshrrev_b64 v[0:1], v6, v[4:5] +; GISEL-NEXT: v_lshrrev_b64 v[2:3], v2, 0 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v6 +; GISEL-NEXT: v_cndmask_b32_e32 v0, v2, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v1, v3, v1, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v6 +; GISEL-NEXT: v_cndmask_b32_e32 v4, v0, v4, vcc +; GISEL-NEXT: v_mad_u64_u32 v[2:3], s[6:7], v4, v10, 0 +; GISEL-NEXT: v_cndmask_b32_e32 v5, v1, v5, vcc +; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[6:7], v4, v8, 0 +; GISEL-NEXT: v_mad_u64_u32 v[2:3], s[6:7], v5, v9, v[2:3] +; GISEL-NEXT: v_mul_lo_u32 v6, v5, v10 +; GISEL-NEXT: v_mad_u64_u32 v[1:2], vcc, v4, v9, v[1:2] +; GISEL-NEXT: v_mul_lo_u32 v4, v4, v10 +; GISEL-NEXT: v_mad_u64_u32 v[1:2], s[6:7], v5, v8, v[1:2] +; GISEL-NEXT: v_addc_co_u32_e64 v3, s[6:7], v3, v4, s[6:7] +; GISEL-NEXT: v_addc_co_u32_e32 v3, vcc, v3, v6, vcc +; GISEL-NEXT: .LBB1_6: ; %Flow1 +; GISEL-NEXT: s_or_b64 exec, exec, s[8:9] +; GISEL-NEXT: .LBB1_7: ; %Flow2 +; GISEL-NEXT: s_andn2_saveexec_b64 s[6:7], s[14:15] +; GISEL-NEXT: s_cbranch_execz .LBB1_9 +; GISEL-NEXT: ; %bb.8: ; %fp-to-i-if-then5 +; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, -1, s[4:5] +; GISEL-NEXT: v_and_b32_e32 v1, 1, v1 +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, s[4:5] +; GISEL-NEXT: v_lshlrev_b32_e32 v2, 1, v1 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v2 +; GISEL-NEXT: v_lshlrev_b32_e32 v3, 2, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v4, 3, v1 +; GISEL-NEXT: v_or_b32_e32 v2, v1, v2 +; GISEL-NEXT: v_or3_b32 v0, v0, v3, v4 +; GISEL-NEXT: v_lshlrev_b32_e32 v5, 4, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v6, 5, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v3, v4 +; GISEL-NEXT: v_or3_b32 v0, v0, v5, v6 +; GISEL-NEXT: v_lshlrev_b32_e32 v7, 6, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v8, 7, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v5, v6 +; GISEL-NEXT: v_or3_b32 v0, v0, v7, v8 +; GISEL-NEXT: v_lshlrev_b32_e32 v9, 8, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v10, 9, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v7, v8 +; GISEL-NEXT: v_or3_b32 v0, v0, v9, v10 +; GISEL-NEXT: v_lshlrev_b32_e32 v11, 10, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v12, 11, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v9, v10 +; GISEL-NEXT: v_or3_b32 v0, v0, v11, v12 +; GISEL-NEXT: v_lshlrev_b32_e32 v13, 12, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v14, 13, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v11, v12 +; GISEL-NEXT: v_or3_b32 v0, v0, v13, v14 +; GISEL-NEXT: v_lshlrev_b32_e32 v15, 14, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v16, 15, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v13, v14 +; GISEL-NEXT: v_or3_b32 v0, v0, v15, v16 +; GISEL-NEXT: v_lshlrev_b32_e32 v17, 16, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v18, 17, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v15, v16 +; GISEL-NEXT: v_or3_b32 v0, v0, v17, v18 +; GISEL-NEXT: v_lshlrev_b32_e32 v19, 18, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v20, 19, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v17, v18 +; GISEL-NEXT: v_or3_b32 v0, v0, v19, v20 +; GISEL-NEXT: v_lshlrev_b32_e32 v3, 20, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v4, 21, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v19, v20 +; GISEL-NEXT: v_or3_b32 v0, v0, v3, v4 +; GISEL-NEXT: v_lshlrev_b32_e32 v5, 22, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v6, 23, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v3, v4 +; GISEL-NEXT: v_or3_b32 v0, v0, v5, v6 +; GISEL-NEXT: v_lshlrev_b32_e32 v7, 24, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v8, 25, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v5, v6 +; GISEL-NEXT: v_or3_b32 v0, v0, v7, v8 +; GISEL-NEXT: v_lshlrev_b32_e32 v9, 26, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v10, 27, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v7, v8 +; GISEL-NEXT: v_or3_b32 v0, v0, v9, v10 +; GISEL-NEXT: v_lshlrev_b32_e32 v11, 28, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v12, 29, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v9, v10 +; GISEL-NEXT: v_or3_b32 v0, v0, v11, v12 +; GISEL-NEXT: v_lshlrev_b32_e32 v13, 30, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v1, 31, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v11, v12 +; GISEL-NEXT: v_or3_b32 v0, v0, v13, v1 +; GISEL-NEXT: v_or3_b32 v1, v2, v13, v1 +; GISEL-NEXT: v_add_u32_e32 v3, 0x80000000, v1 +; GISEL-NEXT: v_mov_b32_e32 v2, v1 +; GISEL-NEXT: .LBB1_9: ; %Flow3 +; GISEL-NEXT: s_or_b64 exec, exec, s[6:7] +; GISEL-NEXT: .LBB1_10: ; %fp-to-i-cleanup +; GISEL-NEXT: s_or_b64 exec, exec, s[12:13] +; GISEL-NEXT: s_setpc_b64 s[30:31] + %cvt = fptoui double %x to i128 + ret i128 %cvt +} + +define i128 @fptosi_f32_to_i128(float %x) { +; SDAG-LABEL: fptosi_f32_to_i128: +; SDAG: ; %bb.0: ; %fp-to-i-entry +; SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-NEXT: v_mov_b32_e32 v4, v0 +; SDAG-NEXT: v_bfe_u32 v5, v4, 23, 8 +; SDAG-NEXT: s_movk_i32 s4, 0x7e +; SDAG-NEXT: v_mov_b32_e32 v0, 0 +; SDAG-NEXT: v_mov_b32_e32 v2, 0 +; SDAG-NEXT: v_mov_b32_e32 v6, 0 +; SDAG-NEXT: v_mov_b32_e32 v1, 0 +; SDAG-NEXT: v_mov_b32_e32 v3, 0 +; SDAG-NEXT: v_cmp_lt_u32_e32 vcc, s4, v5 +; SDAG-NEXT: s_and_saveexec_b64 s[8:9], vcc +; SDAG-NEXT: s_cbranch_execz .LBB2_10 +; SDAG-NEXT: ; %bb.1: ; %fp-to-i-if-end +; SDAG-NEXT: v_add_co_u32_e32 v0, vcc, 0xffffff01, v5 +; SDAG-NEXT: v_addc_co_u32_e32 v1, vcc, -1, v6, vcc +; SDAG-NEXT: v_addc_co_u32_e32 v2, vcc, -1, v6, vcc +; SDAG-NEXT: s_movk_i32 s4, 0xff7f +; SDAG-NEXT: v_addc_co_u32_e32 v3, vcc, -1, v6, vcc +; SDAG-NEXT: s_mov_b32 s5, -1 +; SDAG-NEXT: v_cmp_lt_u64_e64 s[4:5], s[4:5], v[0:1] +; SDAG-NEXT: v_cmp_eq_u64_e64 s[6:7], -1, v[2:3] +; SDAG-NEXT: v_cmp_lt_i32_e32 vcc, -1, v4 +; SDAG-NEXT: s_and_b64 s[4:5], s[6:7], s[4:5] +; SDAG-NEXT: ; implicit-def: $vgpr0_vgpr1 +; SDAG-NEXT: ; implicit-def: $vgpr2_vgpr3 +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; SDAG-NEXT: s_xor_b64 s[10:11], exec, s[6:7] +; SDAG-NEXT: s_cbranch_execz .LBB2_7 +; SDAG-NEXT: ; %bb.2: ; %fp-to-i-if-end9 +; SDAG-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; SDAG-NEXT: v_add_co_u32_e64 v9, s[4:5], -1, v0 +; SDAG-NEXT: v_addc_co_u32_e64 v11, s[4:5], 0, -1, s[4:5] +; SDAG-NEXT: s_mov_b64 s[4:5], 0x95 +; SDAG-NEXT: v_and_b32_e32 v0, 0x7fffff, v4 +; SDAG-NEXT: v_cmp_lt_u64_e64 s[4:5], s[4:5], v[5:6] +; SDAG-NEXT: v_mov_b32_e32 v7, 0 +; SDAG-NEXT: v_cndmask_b32_e64 v8, -1, 0, vcc +; SDAG-NEXT: v_cndmask_b32_e64 v10, -1, 1, vcc +; SDAG-NEXT: v_or_b32_e32 v6, 0x800000, v0 +; SDAG-NEXT: ; implicit-def: $vgpr0_vgpr1 +; SDAG-NEXT: ; implicit-def: $vgpr2_vgpr3 +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; SDAG-NEXT: s_xor_b64 s[12:13], exec, s[6:7] +; SDAG-NEXT: s_cbranch_execz .LBB2_4 +; SDAG-NEXT: ; %bb.3: ; %fp-to-i-if-else +; SDAG-NEXT: v_sub_u32_e32 v0, 0xd6, v5 +; SDAG-NEXT: v_add_u32_e32 v2, 0xffffff2a, v5 +; SDAG-NEXT: v_add_u32_e32 v4, 0xffffff6a, v5 +; SDAG-NEXT: v_lshrrev_b64 v[0:1], v0, v[6:7] +; SDAG-NEXT: v_lshlrev_b64 v[2:3], v2, v[6:7] +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v4 +; SDAG-NEXT: v_cndmask_b32_e64 v1, v3, v1, s[4:5] +; SDAG-NEXT: v_cmp_ne_u32_e64 s[6:7], 0, v4 +; SDAG-NEXT: v_cndmask_b32_e64 v3, 0, v1, s[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v2, v2, v0, s[4:5] +; SDAG-NEXT: v_lshlrev_b64 v[0:1], v4, v[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v2, 0, v2, s[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v13, 0, v0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v12, 0, v1, s[4:5] +; SDAG-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v13, v10, 0 +; SDAG-NEXT: v_mul_lo_u32 v14, v8, v2 +; SDAG-NEXT: v_mul_lo_u32 v15, v10, v3 +; SDAG-NEXT: v_mov_b32_e32 v6, v1 +; SDAG-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v12, v10, v[6:7] +; SDAG-NEXT: v_mad_u64_u32 v[2:3], s[4:5], v10, v2, 0 +; SDAG-NEXT: v_mov_b32_e32 v6, v5 +; SDAG-NEXT: v_mov_b32_e32 v5, v7 +; SDAG-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v13, v8, v[4:5] +; SDAG-NEXT: v_add3_u32 v3, v3, v15, v14 +; SDAG-NEXT: v_mad_u64_u32 v[1:2], s[4:5], v9, v13, v[2:3] +; SDAG-NEXT: v_add_co_u32_e64 v5, s[4:5], v6, v5 +; SDAG-NEXT: v_addc_co_u32_e64 v6, s[4:5], 0, 0, s[4:5] +; SDAG-NEXT: v_mul_lo_u32 v3, v9, v12 +; SDAG-NEXT: v_mul_lo_u32 v7, v11, v13 +; SDAG-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v12, v8, v[5:6] +; SDAG-NEXT: ; implicit-def: $vgpr10 +; SDAG-NEXT: ; implicit-def: $vgpr8 +; SDAG-NEXT: ; implicit-def: $vgpr9 +; SDAG-NEXT: v_add3_u32 v3, v7, v2, v3 +; SDAG-NEXT: v_add_co_u32_e64 v2, s[4:5], v5, v1 +; SDAG-NEXT: v_addc_co_u32_e64 v3, s[4:5], v6, v3, s[4:5] +; SDAG-NEXT: ; implicit-def: $vgpr5_vgpr6 +; SDAG-NEXT: v_mov_b32_e32 v1, v4 +; SDAG-NEXT: ; implicit-def: $vgpr6_vgpr7 +; SDAG-NEXT: .LBB2_4: ; %Flow +; SDAG-NEXT: s_andn2_saveexec_b64 s[6:7], s[12:13] +; SDAG-NEXT: s_cbranch_execz .LBB2_6 +; SDAG-NEXT: ; %bb.5: ; %fp-to-i-if-then12 +; SDAG-NEXT: v_sub_u32_e32 v2, 0x96, v5 +; SDAG-NEXT: v_lshrrev_b64 v[0:1], v2, v[6:7] +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v2 +; SDAG-NEXT: v_cndmask_b32_e64 v0, 0, v0, s[4:5] +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v2 +; SDAG-NEXT: v_cndmask_b32_e64 v3, v0, v6, s[4:5] +; SDAG-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v3, v10, 0 +; SDAG-NEXT: v_mov_b32_e32 v2, 0 +; SDAG-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v3, v8, v[1:2] +; SDAG-NEXT: v_mov_b32_e32 v1, v5 +; SDAG-NEXT: v_mad_i64_i32 v[2:3], s[4:5], v9, v3, v[1:2] +; SDAG-NEXT: v_mov_b32_e32 v1, v4 +; SDAG-NEXT: .LBB2_6: ; %Flow1 +; SDAG-NEXT: s_or_b64 exec, exec, s[6:7] +; SDAG-NEXT: .LBB2_7: ; %Flow2 +; SDAG-NEXT: s_andn2_saveexec_b64 s[4:5], s[10:11] +; SDAG-NEXT: ; %bb.8: ; %fp-to-i-if-then5 +; SDAG-NEXT: v_bfrev_b32_e32 v0, 1 +; SDAG-NEXT: v_bfrev_b32_e32 v1, -2 +; SDAG-NEXT: v_cndmask_b32_e64 v2, 0, -1, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v3, v0, v1, vcc +; SDAG-NEXT: v_mov_b32_e32 v0, v2 +; SDAG-NEXT: v_mov_b32_e32 v1, v2 +; SDAG-NEXT: ; %bb.9: ; %Flow3 +; SDAG-NEXT: s_or_b64 exec, exec, s[4:5] +; SDAG-NEXT: .LBB2_10: ; %fp-to-i-cleanup +; SDAG-NEXT: s_or_b64 exec, exec, s[8:9] +; SDAG-NEXT: s_setpc_b64 s[30:31] +; +; GISEL-LABEL: fptosi_f32_to_i128: +; GISEL: ; %bb.0: ; %fp-to-i-entry +; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-NEXT: v_mov_b32_e32 v4, v0 +; GISEL-NEXT: v_mov_b32_e32 v5, 0 +; GISEL-NEXT: v_lshrrev_b64 v[0:1], 23, v[4:5] +; GISEL-NEXT: s_mov_b64 s[4:5], 0 +; GISEL-NEXT: v_bfe_u32 v6, v0, 0, 8 +; GISEL-NEXT: v_mov_b32_e32 v0, 0x7f +; GISEL-NEXT: v_mov_b32_e32 v1, 0 +; GISEL-NEXT: v_mov_b32_e32 v7, v5 +; GISEL-NEXT: v_cmp_ge_u64_e32 vcc, v[6:7], v[0:1] +; GISEL-NEXT: s_mov_b64 s[6:7], s[4:5] +; GISEL-NEXT: v_mov_b32_e32 v0, s4 +; GISEL-NEXT: v_mov_b32_e32 v1, s5 +; GISEL-NEXT: v_mov_b32_e32 v2, s6 +; GISEL-NEXT: v_mov_b32_e32 v3, s7 +; GISEL-NEXT: s_and_saveexec_b64 s[12:13], vcc +; GISEL-NEXT: s_cbranch_execz .LBB2_10 +; GISEL-NEXT: ; %bb.1: ; %fp-to-i-if-end +; GISEL-NEXT: v_add_co_u32_e32 v0, vcc, 0xffffff01, v6 +; GISEL-NEXT: v_mov_b32_e32 v2, 0xffffff80 +; GISEL-NEXT: v_addc_co_u32_e64 v1, s[6:7], 0, -1, vcc +; GISEL-NEXT: v_mov_b32_e32 v3, -1 +; GISEL-NEXT: v_addc_co_u32_e64 v8, s[6:7], 0, -1, s[6:7] +; GISEL-NEXT: v_cmp_ge_u64_e32 vcc, v[0:1], v[2:3] +; GISEL-NEXT: v_addc_co_u32_e64 v9, s[6:7], 0, -1, s[6:7] +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; GISEL-NEXT: v_cmp_le_u64_e32 vcc, -1, v[8:9] +; GISEL-NEXT: v_cmp_lt_i32_e64 s[4:5], -1, v4 +; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, -1, v[8:9] +; GISEL-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc +; GISEL-NEXT: v_and_b32_e32 v0, 1, v0 +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v0 +; GISEL-NEXT: ; implicit-def: $vgpr0_vgpr1_vgpr2_vgpr3 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], vcc +; GISEL-NEXT: s_xor_b64 s[14:15], exec, s[6:7] +; GISEL-NEXT: s_cbranch_execz .LBB2_7 +; GISEL-NEXT: ; %bb.2: ; %fp-to-i-if-end9 +; GISEL-NEXT: s_xor_b64 s[6:7], s[4:5], -1 +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, -1, s[6:7] +; GISEL-NEXT: v_and_b32_e32 v0, 1, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v2, 1, v0 +; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, 1, s[6:7] +; GISEL-NEXT: v_lshlrev_b16_e32 v3, 2, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v5, 3, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v8, 4, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v9, 5, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v10, 6, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v11, 7, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v12, 8, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v13, 9, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v14, 10, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v15, 11, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v16, 12, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v17, 13, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v18, 14, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v19, 15, v0 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v2 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v2 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v3 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v3 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v5 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v5 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v8 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v8 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v9 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v9 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v10 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v10 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v11 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v11 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v12 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v12 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v13 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v13 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v14 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v14 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v15 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v15 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v16 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v16 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v17 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v17 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v18 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v18 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v19 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v19 +; GISEL-NEXT: v_and_b32_e32 v0, 0xffff, v0 +; GISEL-NEXT: v_and_b32_e32 v1, 0xffff, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v2, 16, v0 +; GISEL-NEXT: v_lshl_or_b32 v10, v0, 16, v0 +; GISEL-NEXT: v_or3_b32 v9, v1, v2, 1 +; GISEL-NEXT: v_or3_b32 v8, v0, v2, 0 +; GISEL-NEXT: v_mov_b32_e32 v0, 0x96 +; GISEL-NEXT: v_mov_b32_e32 v1, 0 +; GISEL-NEXT: v_and_b32_e32 v2, 0x7fffff, v4 +; GISEL-NEXT: v_cmp_ge_u64_e32 vcc, v[6:7], v[0:1] +; GISEL-NEXT: v_or_b32_e32 v4, 0x800000, v2 +; GISEL-NEXT: v_mov_b32_e32 v5, 0 +; GISEL-NEXT: ; implicit-def: $vgpr0_vgpr1_vgpr2_vgpr3 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], vcc +; GISEL-NEXT: s_xor_b64 s[16:17], exec, s[6:7] +; GISEL-NEXT: s_cbranch_execz .LBB2_4 +; GISEL-NEXT: ; %bb.3: ; %fp-to-i-if-else +; GISEL-NEXT: v_add_u32_e32 v6, 0xffffff6a, v6 +; GISEL-NEXT: v_lshlrev_b64 v[0:1], v6, v[4:5] +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v6 +; GISEL-NEXT: v_cndmask_b32_e32 v11, 0, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v12, 0, v1, vcc +; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[6:7], v11, v10, 0 +; GISEL-NEXT: v_subrev_u32_e32 v7, 64, v6 +; GISEL-NEXT: v_sub_u32_e32 v2, 64, v6 +; GISEL-NEXT: v_lshrrev_b64 v[2:3], v2, v[4:5] +; GISEL-NEXT: v_lshlrev_b64 v[4:5], v7, v[4:5] +; GISEL-NEXT: v_cmp_eq_u32_e64 s[6:7], 0, v6 +; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[8:9], v12, v8, v[0:1] +; GISEL-NEXT: v_cndmask_b32_e32 v2, v4, v2, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v13, v2, 0, s[6:7] +; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[8:9], v13, v9, v[6:7] +; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[8:9], v11, v9, 0 +; GISEL-NEXT: v_mov_b32_e32 v2, v6 +; GISEL-NEXT: v_mul_lo_u32 v6, v11, v10 +; GISEL-NEXT: v_mad_u64_u32 v[1:2], s[8:9], v11, v8, v[1:2] +; GISEL-NEXT: v_mul_lo_u32 v4, v12, v10 +; GISEL-NEXT: v_cndmask_b32_e32 v3, v5, v3, vcc +; GISEL-NEXT: v_mad_u64_u32 v[1:2], s[10:11], v12, v9, v[1:2] +; GISEL-NEXT: v_addc_co_u32_e64 v6, s[10:11], v7, v6, s[10:11] +; GISEL-NEXT: v_addc_co_u32_e64 v4, s[8:9], v6, v4, s[8:9] +; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[8:9], v13, v8, v[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v3, v3, 0, s[6:7] +; GISEL-NEXT: ; implicit-def: $vgpr10 +; GISEL-NEXT: ; implicit-def: $vgpr8 +; GISEL-NEXT: v_mad_u64_u32 v[3:4], s[6:7], v3, v9, v[6:7] +; GISEL-NEXT: ; implicit-def: $vgpr6 +; GISEL-NEXT: ; implicit-def: $vgpr4_vgpr5 +; GISEL-NEXT: ; implicit-def: $vgpr9 +; GISEL-NEXT: .LBB2_4: ; %Flow +; GISEL-NEXT: s_andn2_saveexec_b64 s[6:7], s[16:17] +; GISEL-NEXT: s_cbranch_execz .LBB2_6 +; GISEL-NEXT: ; %bb.5: ; %fp-to-i-if-then12 +; GISEL-NEXT: v_sub_co_u32_e32 v3, vcc, 0x96, v6 +; GISEL-NEXT: v_subrev_u32_e32 v2, 64, v3 +; GISEL-NEXT: v_lshrrev_b64 v[0:1], v3, v[4:5] +; GISEL-NEXT: v_lshrrev_b64 v[1:2], v2, 0 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v3 +; GISEL-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v3 +; GISEL-NEXT: v_cndmask_b32_e32 v4, v0, v4, vcc +; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[8:9], v4, v9, 0 +; GISEL-NEXT: v_mad_u64_u32 v[2:3], s[8:9], v4, v10, 0 +; GISEL-NEXT: v_mul_lo_u32 v5, v4, v10 +; GISEL-NEXT: v_mad_u64_u32 v[1:2], vcc, v4, v8, v[1:2] +; GISEL-NEXT: v_addc_co_u32_e32 v3, vcc, v3, v5, vcc +; GISEL-NEXT: .LBB2_6: ; %Flow1 +; GISEL-NEXT: s_or_b64 exec, exec, s[6:7] +; GISEL-NEXT: .LBB2_7: ; %Flow2 +; GISEL-NEXT: s_andn2_saveexec_b64 s[6:7], s[14:15] +; GISEL-NEXT: s_cbranch_execz .LBB2_9 +; GISEL-NEXT: ; %bb.8: ; %fp-to-i-if-then5 +; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, -1, s[4:5] +; GISEL-NEXT: v_and_b32_e32 v1, 1, v1 +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, s[4:5] +; GISEL-NEXT: v_lshlrev_b32_e32 v2, 1, v1 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v2 +; GISEL-NEXT: v_lshlrev_b32_e32 v3, 2, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v4, 3, v1 +; GISEL-NEXT: v_or_b32_e32 v2, v1, v2 +; GISEL-NEXT: v_or3_b32 v0, v0, v3, v4 +; GISEL-NEXT: v_lshlrev_b32_e32 v5, 4, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v6, 5, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v3, v4 +; GISEL-NEXT: v_or3_b32 v0, v0, v5, v6 +; GISEL-NEXT: v_lshlrev_b32_e32 v7, 6, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v8, 7, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v5, v6 +; GISEL-NEXT: v_or3_b32 v0, v0, v7, v8 +; GISEL-NEXT: v_lshlrev_b32_e32 v9, 8, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v10, 9, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v7, v8 +; GISEL-NEXT: v_or3_b32 v0, v0, v9, v10 +; GISEL-NEXT: v_lshlrev_b32_e32 v11, 10, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v12, 11, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v9, v10 +; GISEL-NEXT: v_or3_b32 v0, v0, v11, v12 +; GISEL-NEXT: v_lshlrev_b32_e32 v13, 12, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v14, 13, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v11, v12 +; GISEL-NEXT: v_or3_b32 v0, v0, v13, v14 +; GISEL-NEXT: v_lshlrev_b32_e32 v15, 14, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v16, 15, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v13, v14 +; GISEL-NEXT: v_or3_b32 v0, v0, v15, v16 +; GISEL-NEXT: v_lshlrev_b32_e32 v17, 16, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v18, 17, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v15, v16 +; GISEL-NEXT: v_or3_b32 v0, v0, v17, v18 +; GISEL-NEXT: v_lshlrev_b32_e32 v19, 18, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v20, 19, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v17, v18 +; GISEL-NEXT: v_or3_b32 v0, v0, v19, v20 +; GISEL-NEXT: v_lshlrev_b32_e32 v3, 20, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v4, 21, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v19, v20 +; GISEL-NEXT: v_or3_b32 v0, v0, v3, v4 +; GISEL-NEXT: v_lshlrev_b32_e32 v5, 22, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v6, 23, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v3, v4 +; GISEL-NEXT: v_or3_b32 v0, v0, v5, v6 +; GISEL-NEXT: v_lshlrev_b32_e32 v7, 24, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v8, 25, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v5, v6 +; GISEL-NEXT: v_or3_b32 v0, v0, v7, v8 +; GISEL-NEXT: v_lshlrev_b32_e32 v9, 26, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v10, 27, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v7, v8 +; GISEL-NEXT: v_or3_b32 v0, v0, v9, v10 +; GISEL-NEXT: v_lshlrev_b32_e32 v11, 28, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v12, 29, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v9, v10 +; GISEL-NEXT: v_or3_b32 v0, v0, v11, v12 +; GISEL-NEXT: v_lshlrev_b32_e32 v13, 30, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v1, 31, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v11, v12 +; GISEL-NEXT: v_or3_b32 v0, v0, v13, v1 +; GISEL-NEXT: v_or3_b32 v1, v2, v13, v1 +; GISEL-NEXT: v_add_u32_e32 v3, 0x80000000, v1 +; GISEL-NEXT: v_mov_b32_e32 v2, v1 +; GISEL-NEXT: .LBB2_9: ; %Flow3 +; GISEL-NEXT: s_or_b64 exec, exec, s[6:7] +; GISEL-NEXT: .LBB2_10: ; %fp-to-i-cleanup +; GISEL-NEXT: s_or_b64 exec, exec, s[12:13] +; GISEL-NEXT: s_setpc_b64 s[30:31] + %cvt = fptosi float %x to i128 + ret i128 %cvt +} + +define i128 @fptoui_f32_to_i128(float %x) { +; SDAG-LABEL: fptoui_f32_to_i128: +; SDAG: ; %bb.0: ; %fp-to-i-entry +; SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-NEXT: v_mov_b32_e32 v4, v0 +; SDAG-NEXT: v_bfe_u32 v5, v4, 23, 8 +; SDAG-NEXT: s_movk_i32 s4, 0x7e +; SDAG-NEXT: v_mov_b32_e32 v0, 0 +; SDAG-NEXT: v_mov_b32_e32 v2, 0 +; SDAG-NEXT: v_mov_b32_e32 v6, 0 +; SDAG-NEXT: v_mov_b32_e32 v1, 0 +; SDAG-NEXT: v_mov_b32_e32 v3, 0 +; SDAG-NEXT: v_cmp_lt_u32_e32 vcc, s4, v5 +; SDAG-NEXT: s_and_saveexec_b64 s[8:9], vcc +; SDAG-NEXT: s_cbranch_execz .LBB3_10 +; SDAG-NEXT: ; %bb.1: ; %fp-to-i-if-end +; SDAG-NEXT: v_add_co_u32_e32 v0, vcc, 0xffffff01, v5 +; SDAG-NEXT: v_addc_co_u32_e32 v1, vcc, -1, v6, vcc +; SDAG-NEXT: v_addc_co_u32_e32 v2, vcc, -1, v6, vcc +; SDAG-NEXT: s_movk_i32 s4, 0xff7f +; SDAG-NEXT: v_addc_co_u32_e32 v3, vcc, -1, v6, vcc +; SDAG-NEXT: s_mov_b32 s5, -1 +; SDAG-NEXT: v_cmp_lt_u64_e64 s[4:5], s[4:5], v[0:1] +; SDAG-NEXT: v_cmp_eq_u64_e64 s[6:7], -1, v[2:3] +; SDAG-NEXT: v_cmp_lt_i32_e32 vcc, -1, v4 +; SDAG-NEXT: s_and_b64 s[4:5], s[6:7], s[4:5] +; SDAG-NEXT: ; implicit-def: $vgpr0_vgpr1 +; SDAG-NEXT: ; implicit-def: $vgpr2_vgpr3 +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; SDAG-NEXT: s_xor_b64 s[10:11], exec, s[6:7] +; SDAG-NEXT: s_cbranch_execz .LBB3_7 +; SDAG-NEXT: ; %bb.2: ; %fp-to-i-if-end9 +; SDAG-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; SDAG-NEXT: v_add_co_u32_e64 v9, s[4:5], -1, v0 +; SDAG-NEXT: v_addc_co_u32_e64 v11, s[4:5], 0, -1, s[4:5] +; SDAG-NEXT: s_mov_b64 s[4:5], 0x95 +; SDAG-NEXT: v_and_b32_e32 v0, 0x7fffff, v4 +; SDAG-NEXT: v_cmp_lt_u64_e64 s[4:5], s[4:5], v[5:6] +; SDAG-NEXT: v_mov_b32_e32 v7, 0 +; SDAG-NEXT: v_cndmask_b32_e64 v8, -1, 0, vcc +; SDAG-NEXT: v_cndmask_b32_e64 v10, -1, 1, vcc +; SDAG-NEXT: v_or_b32_e32 v6, 0x800000, v0 +; SDAG-NEXT: ; implicit-def: $vgpr0_vgpr1 +; SDAG-NEXT: ; implicit-def: $vgpr2_vgpr3 +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], s[4:5] +; SDAG-NEXT: s_xor_b64 s[12:13], exec, s[6:7] +; SDAG-NEXT: s_cbranch_execz .LBB3_4 +; SDAG-NEXT: ; %bb.3: ; %fp-to-i-if-else +; SDAG-NEXT: v_sub_u32_e32 v0, 0xd6, v5 +; SDAG-NEXT: v_add_u32_e32 v2, 0xffffff2a, v5 +; SDAG-NEXT: v_add_u32_e32 v4, 0xffffff6a, v5 +; SDAG-NEXT: v_lshrrev_b64 v[0:1], v0, v[6:7] +; SDAG-NEXT: v_lshlrev_b64 v[2:3], v2, v[6:7] +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v4 +; SDAG-NEXT: v_cndmask_b32_e64 v1, v3, v1, s[4:5] +; SDAG-NEXT: v_cmp_ne_u32_e64 s[6:7], 0, v4 +; SDAG-NEXT: v_cndmask_b32_e64 v3, 0, v1, s[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v2, v2, v0, s[4:5] +; SDAG-NEXT: v_lshlrev_b64 v[0:1], v4, v[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v2, 0, v2, s[6:7] +; SDAG-NEXT: v_cndmask_b32_e64 v13, 0, v0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v12, 0, v1, s[4:5] +; SDAG-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v13, v10, 0 +; SDAG-NEXT: v_mul_lo_u32 v14, v8, v2 +; SDAG-NEXT: v_mul_lo_u32 v15, v10, v3 +; SDAG-NEXT: v_mov_b32_e32 v6, v1 +; SDAG-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v12, v10, v[6:7] +; SDAG-NEXT: v_mad_u64_u32 v[2:3], s[4:5], v10, v2, 0 +; SDAG-NEXT: v_mov_b32_e32 v6, v5 +; SDAG-NEXT: v_mov_b32_e32 v5, v7 +; SDAG-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v13, v8, v[4:5] +; SDAG-NEXT: v_add3_u32 v3, v3, v15, v14 +; SDAG-NEXT: v_mad_u64_u32 v[1:2], s[4:5], v9, v13, v[2:3] +; SDAG-NEXT: v_add_co_u32_e64 v5, s[4:5], v6, v5 +; SDAG-NEXT: v_addc_co_u32_e64 v6, s[4:5], 0, 0, s[4:5] +; SDAG-NEXT: v_mul_lo_u32 v3, v9, v12 +; SDAG-NEXT: v_mul_lo_u32 v7, v11, v13 +; SDAG-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v12, v8, v[5:6] +; SDAG-NEXT: ; implicit-def: $vgpr10 +; SDAG-NEXT: ; implicit-def: $vgpr8 +; SDAG-NEXT: ; implicit-def: $vgpr9 +; SDAG-NEXT: v_add3_u32 v3, v7, v2, v3 +; SDAG-NEXT: v_add_co_u32_e64 v2, s[4:5], v5, v1 +; SDAG-NEXT: v_addc_co_u32_e64 v3, s[4:5], v6, v3, s[4:5] +; SDAG-NEXT: ; implicit-def: $vgpr5_vgpr6 +; SDAG-NEXT: v_mov_b32_e32 v1, v4 +; SDAG-NEXT: ; implicit-def: $vgpr6_vgpr7 +; SDAG-NEXT: .LBB3_4: ; %Flow +; SDAG-NEXT: s_andn2_saveexec_b64 s[6:7], s[12:13] +; SDAG-NEXT: s_cbranch_execz .LBB3_6 +; SDAG-NEXT: ; %bb.5: ; %fp-to-i-if-then12 +; SDAG-NEXT: v_sub_u32_e32 v2, 0x96, v5 +; SDAG-NEXT: v_lshrrev_b64 v[0:1], v2, v[6:7] +; SDAG-NEXT: v_cmp_gt_u32_e64 s[4:5], 64, v2 +; SDAG-NEXT: v_cndmask_b32_e64 v0, 0, v0, s[4:5] +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v2 +; SDAG-NEXT: v_cndmask_b32_e64 v3, v0, v6, s[4:5] +; SDAG-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v3, v10, 0 +; SDAG-NEXT: v_mov_b32_e32 v2, 0 +; SDAG-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v3, v8, v[1:2] +; SDAG-NEXT: v_mov_b32_e32 v1, v5 +; SDAG-NEXT: v_mad_i64_i32 v[2:3], s[4:5], v9, v3, v[1:2] +; SDAG-NEXT: v_mov_b32_e32 v1, v4 +; SDAG-NEXT: .LBB3_6: ; %Flow1 +; SDAG-NEXT: s_or_b64 exec, exec, s[6:7] +; SDAG-NEXT: .LBB3_7: ; %Flow2 +; SDAG-NEXT: s_andn2_saveexec_b64 s[4:5], s[10:11] +; SDAG-NEXT: ; %bb.8: ; %fp-to-i-if-then5 +; SDAG-NEXT: v_bfrev_b32_e32 v0, 1 +; SDAG-NEXT: v_bfrev_b32_e32 v1, -2 +; SDAG-NEXT: v_cndmask_b32_e64 v2, 0, -1, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v3, v0, v1, vcc +; SDAG-NEXT: v_mov_b32_e32 v0, v2 +; SDAG-NEXT: v_mov_b32_e32 v1, v2 +; SDAG-NEXT: ; %bb.9: ; %Flow3 +; SDAG-NEXT: s_or_b64 exec, exec, s[4:5] +; SDAG-NEXT: .LBB3_10: ; %fp-to-i-cleanup +; SDAG-NEXT: s_or_b64 exec, exec, s[8:9] +; SDAG-NEXT: s_setpc_b64 s[30:31] +; +; GISEL-LABEL: fptoui_f32_to_i128: +; GISEL: ; %bb.0: ; %fp-to-i-entry +; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-NEXT: v_mov_b32_e32 v4, v0 +; GISEL-NEXT: v_mov_b32_e32 v5, 0 +; GISEL-NEXT: v_lshrrev_b64 v[0:1], 23, v[4:5] +; GISEL-NEXT: s_mov_b64 s[4:5], 0 +; GISEL-NEXT: v_bfe_u32 v6, v0, 0, 8 +; GISEL-NEXT: v_mov_b32_e32 v0, 0x7f +; GISEL-NEXT: v_mov_b32_e32 v1, 0 +; GISEL-NEXT: v_mov_b32_e32 v7, v5 +; GISEL-NEXT: v_cmp_ge_u64_e32 vcc, v[6:7], v[0:1] +; GISEL-NEXT: s_mov_b64 s[6:7], s[4:5] +; GISEL-NEXT: v_mov_b32_e32 v0, s4 +; GISEL-NEXT: v_mov_b32_e32 v1, s5 +; GISEL-NEXT: v_mov_b32_e32 v2, s6 +; GISEL-NEXT: v_mov_b32_e32 v3, s7 +; GISEL-NEXT: s_and_saveexec_b64 s[12:13], vcc +; GISEL-NEXT: s_cbranch_execz .LBB3_10 +; GISEL-NEXT: ; %bb.1: ; %fp-to-i-if-end +; GISEL-NEXT: v_add_co_u32_e32 v0, vcc, 0xffffff01, v6 +; GISEL-NEXT: v_mov_b32_e32 v2, 0xffffff80 +; GISEL-NEXT: v_addc_co_u32_e64 v1, s[6:7], 0, -1, vcc +; GISEL-NEXT: v_mov_b32_e32 v3, -1 +; GISEL-NEXT: v_addc_co_u32_e64 v8, s[6:7], 0, -1, s[6:7] +; GISEL-NEXT: v_cmp_ge_u64_e32 vcc, v[0:1], v[2:3] +; GISEL-NEXT: v_addc_co_u32_e64 v9, s[6:7], 0, -1, s[6:7] +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; GISEL-NEXT: v_cmp_le_u64_e32 vcc, -1, v[8:9] +; GISEL-NEXT: v_cmp_lt_i32_e64 s[4:5], -1, v4 +; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, -1, v[8:9] +; GISEL-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc +; GISEL-NEXT: v_and_b32_e32 v0, 1, v0 +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v0 +; GISEL-NEXT: ; implicit-def: $vgpr0_vgpr1_vgpr2_vgpr3 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], vcc +; GISEL-NEXT: s_xor_b64 s[14:15], exec, s[6:7] +; GISEL-NEXT: s_cbranch_execz .LBB3_7 +; GISEL-NEXT: ; %bb.2: ; %fp-to-i-if-end9 +; GISEL-NEXT: s_xor_b64 s[6:7], s[4:5], -1 +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, -1, s[6:7] +; GISEL-NEXT: v_and_b32_e32 v0, 1, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v2, 1, v0 +; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, 1, s[6:7] +; GISEL-NEXT: v_lshlrev_b16_e32 v3, 2, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v5, 3, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v8, 4, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v9, 5, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v10, 6, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v11, 7, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v12, 8, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v13, 9, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v14, 10, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v15, 11, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v16, 12, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v17, 13, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v18, 14, v0 +; GISEL-NEXT: v_lshlrev_b16_e32 v19, 15, v0 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v2 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v2 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v3 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v3 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v5 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v5 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v8 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v8 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v9 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v9 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v10 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v10 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v11 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v11 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v12 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v12 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v13 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v13 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v14 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v14 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v15 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v15 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v16 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v16 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v17 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v17 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v18 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v18 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v19 +; GISEL-NEXT: v_or_b32_e32 v1, v1, v19 +; GISEL-NEXT: v_and_b32_e32 v0, 0xffff, v0 +; GISEL-NEXT: v_and_b32_e32 v1, 0xffff, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v2, 16, v0 +; GISEL-NEXT: v_lshl_or_b32 v10, v0, 16, v0 +; GISEL-NEXT: v_or3_b32 v9, v1, v2, 1 +; GISEL-NEXT: v_or3_b32 v8, v0, v2, 0 +; GISEL-NEXT: v_mov_b32_e32 v0, 0x96 +; GISEL-NEXT: v_mov_b32_e32 v1, 0 +; GISEL-NEXT: v_and_b32_e32 v2, 0x7fffff, v4 +; GISEL-NEXT: v_cmp_ge_u64_e32 vcc, v[6:7], v[0:1] +; GISEL-NEXT: v_or_b32_e32 v4, 0x800000, v2 +; GISEL-NEXT: v_mov_b32_e32 v5, 0 +; GISEL-NEXT: ; implicit-def: $vgpr0_vgpr1_vgpr2_vgpr3 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], vcc +; GISEL-NEXT: s_xor_b64 s[16:17], exec, s[6:7] +; GISEL-NEXT: s_cbranch_execz .LBB3_4 +; GISEL-NEXT: ; %bb.3: ; %fp-to-i-if-else +; GISEL-NEXT: v_add_u32_e32 v6, 0xffffff6a, v6 +; GISEL-NEXT: v_lshlrev_b64 v[0:1], v6, v[4:5] +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v6 +; GISEL-NEXT: v_cndmask_b32_e32 v11, 0, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v12, 0, v1, vcc +; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[6:7], v11, v10, 0 +; GISEL-NEXT: v_subrev_u32_e32 v7, 64, v6 +; GISEL-NEXT: v_sub_u32_e32 v2, 64, v6 +; GISEL-NEXT: v_lshrrev_b64 v[2:3], v2, v[4:5] +; GISEL-NEXT: v_lshlrev_b64 v[4:5], v7, v[4:5] +; GISEL-NEXT: v_cmp_eq_u32_e64 s[6:7], 0, v6 +; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[8:9], v12, v8, v[0:1] +; GISEL-NEXT: v_cndmask_b32_e32 v2, v4, v2, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v13, v2, 0, s[6:7] +; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[8:9], v13, v9, v[6:7] +; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[8:9], v11, v9, 0 +; GISEL-NEXT: v_mov_b32_e32 v2, v6 +; GISEL-NEXT: v_mul_lo_u32 v6, v11, v10 +; GISEL-NEXT: v_mad_u64_u32 v[1:2], s[8:9], v11, v8, v[1:2] +; GISEL-NEXT: v_mul_lo_u32 v4, v12, v10 +; GISEL-NEXT: v_cndmask_b32_e32 v3, v5, v3, vcc +; GISEL-NEXT: v_mad_u64_u32 v[1:2], s[10:11], v12, v9, v[1:2] +; GISEL-NEXT: v_addc_co_u32_e64 v6, s[10:11], v7, v6, s[10:11] +; GISEL-NEXT: v_addc_co_u32_e64 v4, s[8:9], v6, v4, s[8:9] +; GISEL-NEXT: v_mad_u64_u32 v[6:7], s[8:9], v13, v8, v[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v3, v3, 0, s[6:7] +; GISEL-NEXT: ; implicit-def: $vgpr10 +; GISEL-NEXT: ; implicit-def: $vgpr8 +; GISEL-NEXT: v_mad_u64_u32 v[3:4], s[6:7], v3, v9, v[6:7] +; GISEL-NEXT: ; implicit-def: $vgpr6 +; GISEL-NEXT: ; implicit-def: $vgpr4_vgpr5 +; GISEL-NEXT: ; implicit-def: $vgpr9 +; GISEL-NEXT: .LBB3_4: ; %Flow +; GISEL-NEXT: s_andn2_saveexec_b64 s[6:7], s[16:17] +; GISEL-NEXT: s_cbranch_execz .LBB3_6 +; GISEL-NEXT: ; %bb.5: ; %fp-to-i-if-then12 +; GISEL-NEXT: v_sub_co_u32_e32 v3, vcc, 0x96, v6 +; GISEL-NEXT: v_subrev_u32_e32 v2, 64, v3 +; GISEL-NEXT: v_lshrrev_b64 v[0:1], v3, v[4:5] +; GISEL-NEXT: v_lshrrev_b64 v[1:2], v2, 0 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v3 +; GISEL-NEXT: v_cndmask_b32_e32 v0, v1, v0, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v3 +; GISEL-NEXT: v_cndmask_b32_e32 v4, v0, v4, vcc +; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[8:9], v4, v9, 0 +; GISEL-NEXT: v_mad_u64_u32 v[2:3], s[8:9], v4, v10, 0 +; GISEL-NEXT: v_mul_lo_u32 v5, v4, v10 +; GISEL-NEXT: v_mad_u64_u32 v[1:2], vcc, v4, v8, v[1:2] +; GISEL-NEXT: v_addc_co_u32_e32 v3, vcc, v3, v5, vcc +; GISEL-NEXT: .LBB3_6: ; %Flow1 +; GISEL-NEXT: s_or_b64 exec, exec, s[6:7] +; GISEL-NEXT: .LBB3_7: ; %Flow2 +; GISEL-NEXT: s_andn2_saveexec_b64 s[6:7], s[14:15] +; GISEL-NEXT: s_cbranch_execz .LBB3_9 +; GISEL-NEXT: ; %bb.8: ; %fp-to-i-if-then5 +; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, -1, s[4:5] +; GISEL-NEXT: v_and_b32_e32 v1, 1, v1 +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, s[4:5] +; GISEL-NEXT: v_lshlrev_b32_e32 v2, 1, v1 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v2 +; GISEL-NEXT: v_lshlrev_b32_e32 v3, 2, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v4, 3, v1 +; GISEL-NEXT: v_or_b32_e32 v2, v1, v2 +; GISEL-NEXT: v_or3_b32 v0, v0, v3, v4 +; GISEL-NEXT: v_lshlrev_b32_e32 v5, 4, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v6, 5, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v3, v4 +; GISEL-NEXT: v_or3_b32 v0, v0, v5, v6 +; GISEL-NEXT: v_lshlrev_b32_e32 v7, 6, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v8, 7, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v5, v6 +; GISEL-NEXT: v_or3_b32 v0, v0, v7, v8 +; GISEL-NEXT: v_lshlrev_b32_e32 v9, 8, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v10, 9, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v7, v8 +; GISEL-NEXT: v_or3_b32 v0, v0, v9, v10 +; GISEL-NEXT: v_lshlrev_b32_e32 v11, 10, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v12, 11, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v9, v10 +; GISEL-NEXT: v_or3_b32 v0, v0, v11, v12 +; GISEL-NEXT: v_lshlrev_b32_e32 v13, 12, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v14, 13, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v11, v12 +; GISEL-NEXT: v_or3_b32 v0, v0, v13, v14 +; GISEL-NEXT: v_lshlrev_b32_e32 v15, 14, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v16, 15, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v13, v14 +; GISEL-NEXT: v_or3_b32 v0, v0, v15, v16 +; GISEL-NEXT: v_lshlrev_b32_e32 v17, 16, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v18, 17, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v15, v16 +; GISEL-NEXT: v_or3_b32 v0, v0, v17, v18 +; GISEL-NEXT: v_lshlrev_b32_e32 v19, 18, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v20, 19, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v17, v18 +; GISEL-NEXT: v_or3_b32 v0, v0, v19, v20 +; GISEL-NEXT: v_lshlrev_b32_e32 v3, 20, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v4, 21, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v19, v20 +; GISEL-NEXT: v_or3_b32 v0, v0, v3, v4 +; GISEL-NEXT: v_lshlrev_b32_e32 v5, 22, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v6, 23, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v3, v4 +; GISEL-NEXT: v_or3_b32 v0, v0, v5, v6 +; GISEL-NEXT: v_lshlrev_b32_e32 v7, 24, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v8, 25, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v5, v6 +; GISEL-NEXT: v_or3_b32 v0, v0, v7, v8 +; GISEL-NEXT: v_lshlrev_b32_e32 v9, 26, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v10, 27, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v7, v8 +; GISEL-NEXT: v_or3_b32 v0, v0, v9, v10 +; GISEL-NEXT: v_lshlrev_b32_e32 v11, 28, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v12, 29, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v9, v10 +; GISEL-NEXT: v_or3_b32 v0, v0, v11, v12 +; GISEL-NEXT: v_lshlrev_b32_e32 v13, 30, v1 +; GISEL-NEXT: v_lshlrev_b32_e32 v1, 31, v1 +; GISEL-NEXT: v_or3_b32 v2, v2, v11, v12 +; GISEL-NEXT: v_or3_b32 v0, v0, v13, v1 +; GISEL-NEXT: v_or3_b32 v1, v2, v13, v1 +; GISEL-NEXT: v_add_u32_e32 v3, 0x80000000, v1 +; GISEL-NEXT: v_mov_b32_e32 v2, v1 +; GISEL-NEXT: .LBB3_9: ; %Flow3 +; GISEL-NEXT: s_or_b64 exec, exec, s[6:7] +; GISEL-NEXT: .LBB3_10: ; %fp-to-i-cleanup +; GISEL-NEXT: s_or_b64 exec, exec, s[12:13] +; GISEL-NEXT: s_setpc_b64 s[30:31] + %cvt = fptoui float %x to i128 + ret i128 %cvt +} + +define i128 @fptosi_f16_to_i128(half %x) { +; GCN-LABEL: fptosi_f16_to_i128: +; GCN: ; %bb.0: +; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN-NEXT: v_cvt_f32_f16_e32 v0, v0 +; GCN-NEXT: v_cvt_i32_f32_e32 v0, v0 +; GCN-NEXT: v_ashrrev_i32_e32 v1, 31, v0 +; GCN-NEXT: v_mov_b32_e32 v2, v1 +; GCN-NEXT: v_mov_b32_e32 v3, v1 +; GCN-NEXT: s_setpc_b64 s[30:31] + %cvt = fptosi half %x to i128 + ret i128 %cvt +} + +define i128 @fptoui_f16_to_i128(half %x) { +; GCN-LABEL: fptoui_f16_to_i128: +; GCN: ; %bb.0: +; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GCN-NEXT: v_cvt_f32_f16_e32 v0, v0 +; GCN-NEXT: v_mov_b32_e32 v1, 0 +; GCN-NEXT: v_mov_b32_e32 v2, 0 +; GCN-NEXT: v_mov_b32_e32 v3, 0 +; GCN-NEXT: v_cvt_u32_f32_e32 v0, v0 +; GCN-NEXT: s_setpc_b64 s[30:31] + %cvt = fptoui half %x to i128 + ret i128 %cvt +} + +; FIXME: ExpandLargeFpConvert asserts on bfloat +; define i128 @fptosi_bf16_to_i128(bfloat %x) { +; %cvt = fptosi bfloat %x to i128 +; ret i128 %cvt +; } + +; define i128 @fptoui_bf16_to_i128(bfloat %x) { +; %cvt = fptoui bfloat %x to i128 +; ret i128 %cvt +; } diff --git a/llvm/test/CodeGen/AMDGPU/fract-match.ll b/llvm/test/CodeGen/AMDGPU/fract-match.ll index 3a0b8259d0849659d049bfcb58d1161c2f731696..e361aa4db2aa948d3ccefba788f5b3d69daafd55 100644 --- a/llvm/test/CodeGen/AMDGPU/fract-match.ll +++ b/llvm/test/CodeGen/AMDGPU/fract-match.ll @@ -1705,16 +1705,16 @@ define <2 x float> @safe_math_fract_v2f32(<2 x float> %x, ptr addrspace(1) nocap ; GFX6-NEXT: v_min_f32_e32 v7, 0x3f7fffff, v7 ; GFX6-NEXT: v_cndmask_b32_e32 v6, v6, v1, vcc ; GFX6-NEXT: v_cmp_u_f32_e32 vcc, v0, v0 -; GFX6-NEXT: s_movk_i32 s10, 0x204 +; GFX6-NEXT: v_mov_b32_e32 v8, 0x204 ; GFX6-NEXT: v_cndmask_b32_e32 v7, v7, v0, vcc -; GFX6-NEXT: v_cmp_class_f32_e64 s[8:9], v0, s10 +; GFX6-NEXT: v_cmp_class_f32_e32 vcc, v0, v8 ; GFX6-NEXT: s_mov_b32 s6, 0 -; GFX6-NEXT: v_cndmask_b32_e64 v0, v7, 0, s[8:9] -; GFX6-NEXT: v_cmp_class_f32_e64 s[8:9], v1, s10 +; GFX6-NEXT: v_cndmask_b32_e64 v0, v7, 0, vcc +; GFX6-NEXT: v_cmp_class_f32_e32 vcc, v1, v8 ; GFX6-NEXT: s_mov_b32 s7, 0xf000 ; GFX6-NEXT: s_mov_b32 s4, s6 ; GFX6-NEXT: s_mov_b32 s5, s6 -; GFX6-NEXT: v_cndmask_b32_e64 v1, v6, 0, s[8:9] +; GFX6-NEXT: v_cndmask_b32_e64 v1, v6, 0, vcc ; GFX6-NEXT: buffer_store_dwordx2 v[4:5], v[2:3], s[4:7], 0 addr64 ; GFX6-NEXT: s_waitcnt vmcnt(0) expcnt(0) ; GFX6-NEXT: s_setpc_b64 s[30:31] @@ -1722,19 +1722,19 @@ define <2 x float> @safe_math_fract_v2f32(<2 x float> %x, ptr addrspace(1) nocap ; GFX7-LABEL: safe_math_fract_v2f32: ; GFX7: ; %bb.0: ; %entry ; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX7-NEXT: s_mov_b32 s8, 0x7f800000 +; GFX7-NEXT: v_mov_b32_e32 v8, 0x204 ; GFX7-NEXT: v_fract_f32_e32 v6, v0 -; GFX7-NEXT: v_cmp_neq_f32_e64 vcc, |v0|, s8 +; GFX7-NEXT: v_cmp_class_f32_e32 vcc, v0, v8 ; GFX7-NEXT: s_mov_b32 s6, 0 ; GFX7-NEXT: v_floor_f32_e32 v4, v0 ; GFX7-NEXT: v_fract_f32_e32 v7, v1 -; GFX7-NEXT: v_cndmask_b32_e32 v0, 0, v6, vcc -; GFX7-NEXT: v_cmp_neq_f32_e64 vcc, |v1|, s8 +; GFX7-NEXT: v_cndmask_b32_e64 v0, v6, 0, vcc +; GFX7-NEXT: v_cmp_class_f32_e32 vcc, v1, v8 ; GFX7-NEXT: s_mov_b32 s7, 0xf000 ; GFX7-NEXT: s_mov_b32 s4, s6 ; GFX7-NEXT: s_mov_b32 s5, s6 ; GFX7-NEXT: v_floor_f32_e32 v5, v1 -; GFX7-NEXT: v_cndmask_b32_e32 v1, 0, v7, vcc +; GFX7-NEXT: v_cndmask_b32_e64 v1, v7, 0, vcc ; GFX7-NEXT: buffer_store_dwordx2 v[4:5], v[2:3], s[4:7], 0 addr64 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: s_setpc_b64 s[30:31] @@ -1742,15 +1742,15 @@ define <2 x float> @safe_math_fract_v2f32(<2 x float> %x, ptr addrspace(1) nocap ; GFX8-LABEL: safe_math_fract_v2f32: ; GFX8: ; %bb.0: ; %entry ; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX8-NEXT: s_mov_b32 s4, 0x7f800000 +; GFX8-NEXT: v_mov_b32_e32 v8, 0x204 ; GFX8-NEXT: v_fract_f32_e32 v6, v0 -; GFX8-NEXT: v_cmp_neq_f32_e64 vcc, |v0|, s4 +; GFX8-NEXT: v_cmp_class_f32_e32 vcc, v0, v8 ; GFX8-NEXT: v_floor_f32_e32 v4, v0 ; GFX8-NEXT: v_fract_f32_e32 v7, v1 -; GFX8-NEXT: v_cndmask_b32_e32 v0, 0, v6, vcc -; GFX8-NEXT: v_cmp_neq_f32_e64 vcc, |v1|, s4 +; GFX8-NEXT: v_cndmask_b32_e64 v0, v6, 0, vcc +; GFX8-NEXT: v_cmp_class_f32_e32 vcc, v1, v8 ; GFX8-NEXT: v_floor_f32_e32 v5, v1 -; GFX8-NEXT: v_cndmask_b32_e32 v1, 0, v7, vcc +; GFX8-NEXT: v_cndmask_b32_e64 v1, v7, 0, vcc ; GFX8-NEXT: global_store_dwordx2 v[2:3], v[4:5], off ; GFX8-NEXT: s_waitcnt vmcnt(0) ; GFX8-NEXT: s_setpc_b64 s[30:31] @@ -1759,14 +1759,15 @@ define <2 x float> @safe_math_fract_v2f32(<2 x float> %x, ptr addrspace(1) nocap ; GFX11: ; %bb.0: ; %entry ; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX11-NEXT: v_fract_f32_e32 v6, v0 -; GFX11-NEXT: v_cmp_neq_f32_e64 vcc_lo, 0x7f800000, |v0| +; GFX11-NEXT: v_cmp_class_f32_e64 s0, v0, 0x204 ; GFX11-NEXT: v_fract_f32_e32 v7, v1 ; GFX11-NEXT: v_floor_f32_e32 v4, v0 ; GFX11-NEXT: v_floor_f32_e32 v5, v1 -; GFX11-NEXT: v_cndmask_b32_e32 v0, 0, v6, vcc_lo -; GFX11-NEXT: v_cmp_neq_f32_e64 vcc_lo, 0x7f800000, |v1| +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_4) +; GFX11-NEXT: v_cndmask_b32_e64 v0, v6, 0, s0 +; GFX11-NEXT: v_cmp_class_f32_e64 s0, v1, 0x204 ; GFX11-NEXT: global_store_b64 v[2:3], v[4:5], off -; GFX11-NEXT: v_cndmask_b32_e32 v1, 0, v7, vcc_lo +; GFX11-NEXT: v_cndmask_b32_e64 v1, v7, 0, s0 ; GFX11-NEXT: s_setpc_b64 s[30:31] entry: %floor = tail call <2 x float> @llvm.floor.v2f32(<2 x float> %x) @@ -1937,21 +1938,22 @@ define half @safe_math_fract_f16(half %x, ptr addrspace(1) nocapture writeonly % ; GFX6: ; %bb.0: ; %entry ; GFX6-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX6-NEXT: v_cvt_f16_f32_e32 v0, v0 -; GFX6-NEXT: s_mov_b32 s8, 0x7f800000 +; GFX6-NEXT: s_movk_i32 s8, 0x7c00 ; GFX6-NEXT: s_mov_b32 s6, 0 ; GFX6-NEXT: s_mov_b32 s7, 0xf000 -; GFX6-NEXT: v_cvt_f32_f16_e32 v0, v0 +; GFX6-NEXT: v_cvt_f32_f16_e32 v3, v0 +; GFX6-NEXT: v_and_b32_e32 v0, 0x7fff, v0 ; GFX6-NEXT: s_mov_b32 s4, s6 ; GFX6-NEXT: s_mov_b32 s5, s6 -; GFX6-NEXT: v_floor_f32_e32 v3, v0 -; GFX6-NEXT: v_sub_f32_e32 v4, v0, v3 -; GFX6-NEXT: v_cvt_f16_f32_e32 v3, v3 -; GFX6-NEXT: v_min_f32_e32 v4, 0x3f7fe000, v4 -; GFX6-NEXT: v_cmp_u_f32_e32 vcc, v0, v0 -; GFX6-NEXT: v_cndmask_b32_e32 v4, v4, v0, vcc -; GFX6-NEXT: v_cmp_neq_f32_e64 vcc, |v0|, s8 -; GFX6-NEXT: v_cndmask_b32_e32 v0, 0, v4, vcc -; GFX6-NEXT: buffer_store_short v3, v[1:2], s[4:7], 0 addr64 +; GFX6-NEXT: v_floor_f32_e32 v4, v3 +; GFX6-NEXT: v_sub_f32_e32 v5, v3, v4 +; GFX6-NEXT: v_cvt_f16_f32_e32 v4, v4 +; GFX6-NEXT: v_min_f32_e32 v5, 0x3f7fe000, v5 +; GFX6-NEXT: v_cmp_u_f32_e32 vcc, v3, v3 +; GFX6-NEXT: v_cndmask_b32_e32 v3, v5, v3, vcc +; GFX6-NEXT: v_cmp_ne_u32_e32 vcc, s8, v0 +; GFX6-NEXT: v_cndmask_b32_e32 v0, 0, v3, vcc +; GFX6-NEXT: buffer_store_short v4, v[1:2], s[4:7], 0 addr64 ; GFX6-NEXT: s_waitcnt vmcnt(0) expcnt(0) ; GFX6-NEXT: s_setpc_b64 s[30:31] ; @@ -1959,21 +1961,22 @@ define half @safe_math_fract_f16(half %x, ptr addrspace(1) nocapture writeonly % ; GFX7: ; %bb.0: ; %entry ; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX7-NEXT: v_cvt_f16_f32_e32 v0, v0 -; GFX7-NEXT: s_mov_b32 s8, 0x7f800000 +; GFX7-NEXT: s_movk_i32 s8, 0x7c00 ; GFX7-NEXT: s_mov_b32 s6, 0 ; GFX7-NEXT: s_mov_b32 s7, 0xf000 -; GFX7-NEXT: v_cvt_f32_f16_e32 v0, v0 +; GFX7-NEXT: v_cvt_f32_f16_e32 v3, v0 +; GFX7-NEXT: v_and_b32_e32 v0, 0x7fff, v0 ; GFX7-NEXT: s_mov_b32 s4, s6 ; GFX7-NEXT: s_mov_b32 s5, s6 -; GFX7-NEXT: v_floor_f32_e32 v3, v0 -; GFX7-NEXT: v_sub_f32_e32 v4, v0, v3 -; GFX7-NEXT: v_cvt_f16_f32_e32 v3, v3 -; GFX7-NEXT: v_min_f32_e32 v4, 0x3f7fe000, v4 -; GFX7-NEXT: v_cmp_u_f32_e32 vcc, v0, v0 -; GFX7-NEXT: v_cndmask_b32_e32 v4, v4, v0, vcc -; GFX7-NEXT: v_cmp_neq_f32_e64 vcc, |v0|, s8 -; GFX7-NEXT: v_cndmask_b32_e32 v0, 0, v4, vcc -; GFX7-NEXT: buffer_store_short v3, v[1:2], s[4:7], 0 addr64 +; GFX7-NEXT: v_floor_f32_e32 v4, v3 +; GFX7-NEXT: v_sub_f32_e32 v5, v3, v4 +; GFX7-NEXT: v_cvt_f16_f32_e32 v4, v4 +; GFX7-NEXT: v_min_f32_e32 v5, 0x3f7fe000, v5 +; GFX7-NEXT: v_cmp_u_f32_e32 vcc, v3, v3 +; GFX7-NEXT: v_cndmask_b32_e32 v3, v5, v3, vcc +; GFX7-NEXT: v_cmp_ne_u32_e32 vcc, s8, v0 +; GFX7-NEXT: v_cndmask_b32_e32 v0, 0, v3, vcc +; GFX7-NEXT: buffer_store_short v4, v[1:2], s[4:7], 0 addr64 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: s_setpc_b64 s[30:31] ; @@ -2062,12 +2065,12 @@ define <2 x half> @safe_math_fract_v2f16(<2 x half> %x, ptr addrspace(1) nocaptu ; GFX6-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX6-NEXT: v_cvt_f16_f32_e32 v1, v1 ; GFX6-NEXT: v_cvt_f16_f32_e32 v0, v0 -; GFX6-NEXT: s_mov_b32 s8, 0x7f800000 +; GFX6-NEXT: s_movk_i32 s8, 0x7c00 ; GFX6-NEXT: s_mov_b32 s6, 0 ; GFX6-NEXT: v_cvt_f32_f16_e32 v4, v1 ; GFX6-NEXT: v_cvt_f32_f16_e32 v5, v0 -; GFX6-NEXT: v_cvt_f32_f16_e64 v0, |v0| -; GFX6-NEXT: v_cvt_f32_f16_e64 v1, |v1| +; GFX6-NEXT: v_and_b32_e32 v0, 0x7fff, v0 +; GFX6-NEXT: v_and_b32_e32 v1, 0x7fff, v1 ; GFX6-NEXT: v_floor_f32_e32 v6, v4 ; GFX6-NEXT: v_cvt_f16_f32_e32 v7, v6 ; GFX6-NEXT: v_floor_f32_e32 v8, v5 @@ -2080,10 +2083,10 @@ define <2 x half> @safe_math_fract_v2f16(<2 x half> %x, ptr addrspace(1) nocaptu ; GFX6-NEXT: v_cndmask_b32_e32 v4, v6, v4, vcc ; GFX6-NEXT: v_cmp_u_f32_e32 vcc, v5, v5 ; GFX6-NEXT: v_cndmask_b32_e32 v5, v8, v5, vcc -; GFX6-NEXT: v_cmp_neq_f32_e32 vcc, s8, v0 +; GFX6-NEXT: v_cmp_ne_u32_e32 vcc, s8, v0 ; GFX6-NEXT: v_lshlrev_b32_e32 v7, 16, v7 ; GFX6-NEXT: v_cndmask_b32_e32 v0, 0, v5, vcc -; GFX6-NEXT: v_cmp_neq_f32_e32 vcc, s8, v1 +; GFX6-NEXT: v_cmp_ne_u32_e32 vcc, s8, v1 ; GFX6-NEXT: s_mov_b32 s7, 0xf000 ; GFX6-NEXT: s_mov_b32 s4, s6 ; GFX6-NEXT: s_mov_b32 s5, s6 @@ -2098,12 +2101,12 @@ define <2 x half> @safe_math_fract_v2f16(<2 x half> %x, ptr addrspace(1) nocaptu ; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX7-NEXT: v_cvt_f16_f32_e32 v1, v1 ; GFX7-NEXT: v_cvt_f16_f32_e32 v0, v0 -; GFX7-NEXT: s_mov_b32 s8, 0x7f800000 +; GFX7-NEXT: s_movk_i32 s8, 0x7c00 ; GFX7-NEXT: s_mov_b32 s6, 0 ; GFX7-NEXT: v_cvt_f32_f16_e32 v4, v1 ; GFX7-NEXT: v_cvt_f32_f16_e32 v5, v0 -; GFX7-NEXT: v_cvt_f32_f16_e64 v0, |v0| -; GFX7-NEXT: v_cvt_f32_f16_e64 v1, |v1| +; GFX7-NEXT: v_and_b32_e32 v0, 0x7fff, v0 +; GFX7-NEXT: v_and_b32_e32 v1, 0x7fff, v1 ; GFX7-NEXT: v_floor_f32_e32 v6, v4 ; GFX7-NEXT: v_cvt_f16_f32_e32 v7, v6 ; GFX7-NEXT: v_floor_f32_e32 v8, v5 @@ -2116,10 +2119,10 @@ define <2 x half> @safe_math_fract_v2f16(<2 x half> %x, ptr addrspace(1) nocaptu ; GFX7-NEXT: v_cndmask_b32_e32 v4, v6, v4, vcc ; GFX7-NEXT: v_cmp_u_f32_e32 vcc, v5, v5 ; GFX7-NEXT: v_cndmask_b32_e32 v5, v8, v5, vcc -; GFX7-NEXT: v_cmp_neq_f32_e32 vcc, s8, v0 +; GFX7-NEXT: v_cmp_ne_u32_e32 vcc, s8, v0 ; GFX7-NEXT: v_lshlrev_b32_e32 v7, 16, v7 ; GFX7-NEXT: v_cndmask_b32_e32 v0, 0, v5, vcc -; GFX7-NEXT: v_cmp_neq_f32_e32 vcc, s8, v1 +; GFX7-NEXT: v_cmp_ne_u32_e32 vcc, s8, v1 ; GFX7-NEXT: s_mov_b32 s7, 0xf000 ; GFX7-NEXT: s_mov_b32 s4, s6 ; GFX7-NEXT: s_mov_b32 s5, s6 @@ -2133,16 +2136,16 @@ define <2 x half> @safe_math_fract_v2f16(<2 x half> %x, ptr addrspace(1) nocaptu ; GFX8: ; %bb.0: ; %entry ; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; GFX8-NEXT: v_lshrrev_b32_e32 v3, 16, v0 -; GFX8-NEXT: s_movk_i32 s6, 0x204 +; GFX8-NEXT: v_mov_b32_e32 v7, 0x204 ; GFX8-NEXT: v_floor_f16_e32 v4, v3 ; GFX8-NEXT: v_floor_f16_e32 v5, v0 ; GFX8-NEXT: v_fract_f16_e32 v6, v3 -; GFX8-NEXT: v_cmp_class_f16_e64 s[4:5], v3, s6 +; GFX8-NEXT: v_cmp_class_f16_e32 vcc, v3, v7 ; GFX8-NEXT: v_pack_b32_f16 v4, v5, v4 ; GFX8-NEXT: v_fract_f16_e32 v5, v0 -; GFX8-NEXT: v_cndmask_b32_e64 v3, v6, 0, s[4:5] -; GFX8-NEXT: v_cmp_class_f16_e64 s[4:5], v0, s6 -; GFX8-NEXT: v_cndmask_b32_e64 v0, v5, 0, s[4:5] +; GFX8-NEXT: v_cndmask_b32_e64 v3, v6, 0, vcc +; GFX8-NEXT: v_cmp_class_f16_e32 vcc, v0, v7 +; GFX8-NEXT: v_cndmask_b32_e64 v0, v5, 0, vcc ; GFX8-NEXT: v_pack_b32_f16 v0, v0, v3 ; GFX8-NEXT: global_store_dword v[1:2], v4, off ; GFX8-NEXT: s_waitcnt vmcnt(0) @@ -2237,19 +2240,19 @@ define <2 x double> @safe_math_fract_v2f64(<2 x double> %x, ptr addrspace(1) noc ; GFX6-NEXT: v_cndmask_b32_e32 v11, v11, v3, vcc ; GFX6-NEXT: v_cndmask_b32_e32 v10, v10, v2, vcc ; GFX6-NEXT: v_cmp_u_f64_e32 vcc, v[0:1], v[0:1] -; GFX6-NEXT: s_movk_i32 s10, 0x204 -; GFX6-NEXT: v_cmp_class_f64_e64 s[8:9], v[0:1], s10 +; GFX6-NEXT: v_mov_b32_e32 v14, 0x204 ; GFX6-NEXT: v_cndmask_b32_e32 v13, v13, v1, vcc ; GFX6-NEXT: v_cndmask_b32_e32 v12, v12, v0, vcc -; GFX6-NEXT: v_cndmask_b32_e64 v0, v12, 0, s[8:9] -; GFX6-NEXT: v_cndmask_b32_e64 v1, v13, 0, s[8:9] -; GFX6-NEXT: v_cmp_class_f64_e64 s[8:9], v[2:3], s10 +; GFX6-NEXT: v_cmp_class_f64_e32 vcc, v[0:1], v14 ; GFX6-NEXT: s_mov_b32 s6, 0 +; GFX6-NEXT: v_cndmask_b32_e64 v0, v12, 0, vcc +; GFX6-NEXT: v_cndmask_b32_e64 v1, v13, 0, vcc +; GFX6-NEXT: v_cmp_class_f64_e32 vcc, v[2:3], v14 ; GFX6-NEXT: s_mov_b32 s7, 0xf000 ; GFX6-NEXT: s_mov_b32 s4, s6 ; GFX6-NEXT: s_mov_b32 s5, s6 -; GFX6-NEXT: v_cndmask_b32_e64 v2, v10, 0, s[8:9] -; GFX6-NEXT: v_cndmask_b32_e64 v3, v11, 0, s[8:9] +; GFX6-NEXT: v_cndmask_b32_e64 v2, v10, 0, vcc +; GFX6-NEXT: v_cndmask_b32_e64 v3, v11, 0, vcc ; GFX6-NEXT: buffer_store_dwordx4 v[6:9], v[4:5], s[4:7], 0 addr64 ; GFX6-NEXT: s_waitcnt vmcnt(0) expcnt(0) ; GFX6-NEXT: s_setpc_b64 s[30:31] @@ -2257,39 +2260,39 @@ define <2 x double> @safe_math_fract_v2f64(<2 x double> %x, ptr addrspace(1) noc ; GFX7-LABEL: safe_math_fract_v2f64: ; GFX7: ; %bb.0: ; %entry ; GFX7-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX7-NEXT: s_movk_i32 s4, 0x204 +; GFX7-NEXT: v_mov_b32_e32 v6, 0x204 ; GFX7-NEXT: v_fract_f64_e32 v[10:11], v[0:1] -; GFX7-NEXT: v_cmp_class_f64_e64 s[8:9], v[0:1], s4 +; GFX7-NEXT: v_cmp_class_f64_e32 vcc, v[0:1], v6 ; GFX7-NEXT: v_fract_f64_e32 v[12:13], v[2:3] -; GFX7-NEXT: v_cmp_class_f64_e64 s[10:11], v[2:3], s4 +; GFX7-NEXT: v_cmp_class_f64_e64 s[4:5], v[2:3], v6 ; GFX7-NEXT: v_floor_f64_e32 v[8:9], v[2:3] ; GFX7-NEXT: v_floor_f64_e32 v[6:7], v[0:1] -; GFX7-NEXT: s_mov_b32 s6, 0 -; GFX7-NEXT: s_mov_b32 s7, 0xf000 -; GFX7-NEXT: s_mov_b32 s4, s6 -; GFX7-NEXT: s_mov_b32 s5, s6 -; GFX7-NEXT: v_cndmask_b32_e64 v0, v10, 0, s[8:9] -; GFX7-NEXT: v_cndmask_b32_e64 v1, v11, 0, s[8:9] -; GFX7-NEXT: v_cndmask_b32_e64 v2, v12, 0, s[10:11] -; GFX7-NEXT: v_cndmask_b32_e64 v3, v13, 0, s[10:11] -; GFX7-NEXT: buffer_store_dwordx4 v[6:9], v[4:5], s[4:7], 0 addr64 +; GFX7-NEXT: s_mov_b32 s10, 0 +; GFX7-NEXT: s_mov_b32 s11, 0xf000 +; GFX7-NEXT: s_mov_b32 s8, s10 +; GFX7-NEXT: s_mov_b32 s9, s10 +; GFX7-NEXT: v_cndmask_b32_e64 v0, v10, 0, vcc +; GFX7-NEXT: v_cndmask_b32_e64 v1, v11, 0, vcc +; GFX7-NEXT: v_cndmask_b32_e64 v2, v12, 0, s[4:5] +; GFX7-NEXT: v_cndmask_b32_e64 v3, v13, 0, s[4:5] +; GFX7-NEXT: buffer_store_dwordx4 v[6:9], v[4:5], s[8:11], 0 addr64 ; GFX7-NEXT: s_waitcnt vmcnt(0) ; GFX7-NEXT: s_setpc_b64 s[30:31] ; ; GFX8-LABEL: safe_math_fract_v2f64: ; GFX8: ; %bb.0: ; %entry ; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX8-NEXT: s_movk_i32 s6, 0x204 +; GFX8-NEXT: v_mov_b32_e32 v6, 0x204 ; GFX8-NEXT: v_fract_f64_e32 v[10:11], v[0:1] -; GFX8-NEXT: v_cmp_class_f64_e64 s[4:5], v[0:1], s6 +; GFX8-NEXT: v_cmp_class_f64_e32 vcc, v[0:1], v6 ; GFX8-NEXT: v_fract_f64_e32 v[12:13], v[2:3] -; GFX8-NEXT: v_cmp_class_f64_e64 s[6:7], v[2:3], s6 +; GFX8-NEXT: v_cmp_class_f64_e64 s[4:5], v[2:3], v6 ; GFX8-NEXT: v_floor_f64_e32 v[8:9], v[2:3] ; GFX8-NEXT: v_floor_f64_e32 v[6:7], v[0:1] -; GFX8-NEXT: v_cndmask_b32_e64 v0, v10, 0, s[4:5] -; GFX8-NEXT: v_cndmask_b32_e64 v1, v11, 0, s[4:5] -; GFX8-NEXT: v_cndmask_b32_e64 v2, v12, 0, s[6:7] -; GFX8-NEXT: v_cndmask_b32_e64 v3, v13, 0, s[6:7] +; GFX8-NEXT: v_cndmask_b32_e64 v0, v10, 0, vcc +; GFX8-NEXT: v_cndmask_b32_e64 v1, v11, 0, vcc +; GFX8-NEXT: v_cndmask_b32_e64 v2, v12, 0, s[4:5] +; GFX8-NEXT: v_cndmask_b32_e64 v3, v13, 0, s[4:5] ; GFX8-NEXT: global_store_dwordx4 v[4:5], v[6:9], off ; GFX8-NEXT: s_waitcnt vmcnt(0) ; GFX8-NEXT: s_setpc_b64 s[30:31] diff --git a/llvm/test/CodeGen/AMDGPU/global_atomic_optimizer_fp_rtn.ll b/llvm/test/CodeGen/AMDGPU/global_atomic_optimizer_fp_rtn.ll index e3fada3459a07f39cfd1d0df561b8c90499d5ca6..b71728096093cde1372000a2d4cd779bdcd316e1 100644 --- a/llvm/test/CodeGen/AMDGPU/global_atomic_optimizer_fp_rtn.ll +++ b/llvm/test/CodeGen/AMDGPU/global_atomic_optimizer_fp_rtn.ll @@ -1,71 +1,43 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -mtriple=amdgcn-- -mcpu=gfx906 -amdgpu-atomic-optimizer-strategy=Iterative -passes='amdgpu-atomic-optimizer,verify<domtree>' %s | FileCheck -check-prefix=IR-ITERATIVE %s -; RUN: opt -S -mtriple=amdgcn-- -mcpu=gfx906 -amdgpu-atomic-optimizer-strategy=DPP -passes='amdgpu-atomic-optimizer,verify<domtree>' %s | FileCheck -check-prefix=IR-DPP %s +; RUN: opt -S -mtriple=amdgcn-- -mcpu=gfx906 -passes='amdgpu-atomic-optimizer<strategy=iterative>,verify<domtree>' %s | FileCheck --check-prefixes=IR,IR-ITERATIVE %s +; RUN: opt -S -mtriple=amdgcn-- -mcpu=gfx906 -passes='amdgpu-atomic-optimizer<strategy=dpp>,verify<domtree>' %s | FileCheck --check-prefixes=IR,IR-DPP %s + +; Tests various combinations of uniform/divergent address and uniform/divergent value inputs of various types for atomic operations. +; Optimization remains same for Iterative and DPP strategies when value in uniform. These different scan/reduction +; strategies are valid for only divergent values. This optimization is valid for divergent addresses. Test also covers different scopes. define amdgpu_ps float @global_atomic_fadd_uni_address_uni_value_agent_scope_unsafe(ptr addrspace(1) inreg %ptr, float inreg %val) #0 { -; IR-ITERATIVE-LABEL: @global_atomic_fadd_uni_address_uni_value_agent_scope_unsafe( -; IR-ITERATIVE-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() -; IR-ITERATIVE-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP24:%.*]] -; IR-ITERATIVE: 2: -; IR-ITERATIVE-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) -; IR-ITERATIVE-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 -; IR-ITERATIVE-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 -; IR-ITERATIVE-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 -; IR-ITERATIVE-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) -; IR-ITERATIVE-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) -; IR-ITERATIVE-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) -; IR-ITERATIVE-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 -; IR-ITERATIVE-NEXT: [[TMP11:%.*]] = uitofp i32 [[TMP10]] to float -; IR-ITERATIVE-NEXT: [[TMP12:%.*]] = fmul float [[VAL:%.*]], [[TMP11]] -; IR-ITERATIVE-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 -; IR-ITERATIVE-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] -; IR-ITERATIVE: 14: -; IR-ITERATIVE-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[TMP12]] syncscope("agent") monotonic, align 4 -; IR-ITERATIVE-NEXT: br label [[TMP16]] -; IR-ITERATIVE: 16: -; IR-ITERATIVE-NEXT: [[TMP17:%.*]] = phi float [ poison, [[TMP2]] ], [ [[TMP15]], [[TMP14]] ] -; IR-ITERATIVE-NEXT: [[TMP18:%.*]] = bitcast float [[TMP17]] to i32 -; IR-ITERATIVE-NEXT: [[TMP19:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP18]]) -; IR-ITERATIVE-NEXT: [[TMP20:%.*]] = bitcast i32 [[TMP19]] to float -; IR-ITERATIVE-NEXT: [[TMP21:%.*]] = uitofp i32 [[TMP8]] to float -; IR-ITERATIVE-NEXT: [[TMP22:%.*]] = fmul float [[VAL]], [[TMP21]] -; IR-ITERATIVE-NEXT: [[TMP23:%.*]] = fadd float [[TMP20]], [[TMP22]] -; IR-ITERATIVE-NEXT: br label [[TMP24]] -; IR-ITERATIVE: 24: -; IR-ITERATIVE-NEXT: [[TMP25:%.*]] = phi float [ poison, [[TMP0:%.*]] ], [ [[TMP23]], [[TMP16]] ] -; IR-ITERATIVE-NEXT: ret float [[TMP25]] -; -; IR-DPP-LABEL: @global_atomic_fadd_uni_address_uni_value_agent_scope_unsafe( -; IR-DPP-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() -; IR-DPP-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP24:%.*]] -; IR-DPP: 2: -; IR-DPP-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) -; IR-DPP-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 -; IR-DPP-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 -; IR-DPP-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 -; IR-DPP-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) -; IR-DPP-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) -; IR-DPP-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) -; IR-DPP-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 -; IR-DPP-NEXT: [[TMP11:%.*]] = uitofp i32 [[TMP10]] to float -; IR-DPP-NEXT: [[TMP12:%.*]] = fmul float [[VAL:%.*]], [[TMP11]] -; IR-DPP-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 -; IR-DPP-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] -; IR-DPP: 14: -; IR-DPP-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[TMP12]] syncscope("agent") monotonic, align 4 -; IR-DPP-NEXT: br label [[TMP16]] -; IR-DPP: 16: -; IR-DPP-NEXT: [[TMP17:%.*]] = phi float [ poison, [[TMP2]] ], [ [[TMP15]], [[TMP14]] ] -; IR-DPP-NEXT: [[TMP18:%.*]] = bitcast float [[TMP17]] to i32 -; IR-DPP-NEXT: [[TMP19:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP18]]) -; IR-DPP-NEXT: [[TMP20:%.*]] = bitcast i32 [[TMP19]] to float -; IR-DPP-NEXT: [[TMP21:%.*]] = uitofp i32 [[TMP8]] to float -; IR-DPP-NEXT: [[TMP22:%.*]] = fmul float [[VAL]], [[TMP21]] -; IR-DPP-NEXT: [[TMP23:%.*]] = fadd float [[TMP20]], [[TMP22]] -; IR-DPP-NEXT: br label [[TMP24]] -; IR-DPP: 24: -; IR-DPP-NEXT: [[TMP25:%.*]] = phi float [ poison, [[TMP0:%.*]] ], [ [[TMP23]], [[TMP16]] ] -; IR-DPP-NEXT: ret float [[TMP25]] +; IR-LABEL: @global_atomic_fadd_uni_address_uni_value_agent_scope_unsafe( +; IR-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() +; IR-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP24:%.*]] +; IR: 2: +; IR-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) +; IR-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) +; IR-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) +; IR-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) +; IR-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 +; IR-NEXT: [[TMP11:%.*]] = uitofp i32 [[TMP10]] to float +; IR-NEXT: [[TMP12:%.*]] = fmul float [[VAL:%.*]], [[TMP11]] +; IR-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] +; IR: 14: +; IR-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[TMP12]] syncscope("agent") monotonic, align 4 +; IR-NEXT: br label [[TMP16]] +; IR: 16: +; IR-NEXT: [[TMP17:%.*]] = phi float [ poison, [[TMP2]] ], [ [[TMP15]], [[TMP14]] ] +; IR-NEXT: [[TMP18:%.*]] = bitcast float [[TMP17]] to i32 +; IR-NEXT: [[TMP19:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP18]]) +; IR-NEXT: [[TMP20:%.*]] = bitcast i32 [[TMP19]] to float +; IR-NEXT: [[TMP21:%.*]] = uitofp i32 [[TMP8]] to float +; IR-NEXT: [[TMP22:%.*]] = fmul float [[VAL]], [[TMP21]] +; IR-NEXT: [[TMP23:%.*]] = fadd float [[TMP20]], [[TMP22]] +; IR-NEXT: br label [[TMP24]] +; IR: 24: +; IR-NEXT: [[TMP25:%.*]] = phi float [ poison, [[TMP0:%.*]] ], [ [[TMP23]], [[TMP16]] ] +; IR-NEXT: ret float [[TMP25]] ; %result = atomicrmw fadd ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic, align 4 ret float %result @@ -411,7 +383,6 @@ define amdgpu_ps float @global_atomic_fsub_uni_address_uni_value_agent_scope_str ret float %result } - define amdgpu_ps float @global_atomic_fsub_uni_address_div_value_agent_scope_strictfp(ptr addrspace(1) inreg %ptr, float %val) #2 { ; IR-ITERATIVE-LABEL: @global_atomic_fsub_uni_address_div_value_agent_scope_strictfp( ; IR-ITERATIVE-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() #[[ATTR7]] @@ -514,61 +485,33 @@ define amdgpu_ps float @global_atomic_fsub_uni_address_div_value_agent_scope_str } define amdgpu_ps float @global_atomic_fmin_uni_address_uni_value_agent_scope_unsafe(ptr addrspace(1) inreg %ptr, float inreg %val) #0 { -; IR-ITERATIVE-LABEL: @global_atomic_fmin_uni_address_uni_value_agent_scope_unsafe( -; IR-ITERATIVE-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() -; IR-ITERATIVE-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP20:%.*]] -; IR-ITERATIVE: 2: -; IR-ITERATIVE-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) -; IR-ITERATIVE-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 -; IR-ITERATIVE-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 -; IR-ITERATIVE-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 -; IR-ITERATIVE-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) -; IR-ITERATIVE-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) -; IR-ITERATIVE-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0 -; IR-ITERATIVE-NEXT: br i1 [[TMP9]], label [[TMP10:%.*]], label [[TMP12:%.*]] -; IR-ITERATIVE: 10: -; IR-ITERATIVE-NEXT: [[TMP11:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-ITERATIVE-NEXT: br label [[TMP12]] -; IR-ITERATIVE: 12: -; IR-ITERATIVE-NEXT: [[TMP13:%.*]] = phi float [ poison, [[TMP2]] ], [ [[TMP11]], [[TMP10]] ] -; IR-ITERATIVE-NEXT: [[TMP14:%.*]] = bitcast float [[TMP13]] to i32 -; IR-ITERATIVE-NEXT: [[TMP15:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP14]]) -; IR-ITERATIVE-NEXT: [[TMP16:%.*]] = bitcast i32 [[TMP15]] to float -; IR-ITERATIVE-NEXT: [[TMP17:%.*]] = uitofp i32 [[TMP8]] to float -; IR-ITERATIVE-NEXT: [[TMP18:%.*]] = select i1 [[TMP9]], float 0x7FF0000000000000, float [[VAL]] -; IR-ITERATIVE-NEXT: [[TMP19:%.*]] = call float @llvm.minnum.f32(float [[TMP16]], float [[TMP18]]) -; IR-ITERATIVE-NEXT: br label [[TMP20]] -; IR-ITERATIVE: 20: -; IR-ITERATIVE-NEXT: [[TMP21:%.*]] = phi float [ poison, [[TMP0:%.*]] ], [ [[TMP19]], [[TMP12]] ] -; IR-ITERATIVE-NEXT: ret float [[TMP21]] -; -; IR-DPP-LABEL: @global_atomic_fmin_uni_address_uni_value_agent_scope_unsafe( -; IR-DPP-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() -; IR-DPP-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP20:%.*]] -; IR-DPP: 2: -; IR-DPP-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) -; IR-DPP-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 -; IR-DPP-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 -; IR-DPP-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 -; IR-DPP-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) -; IR-DPP-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) -; IR-DPP-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0 -; IR-DPP-NEXT: br i1 [[TMP9]], label [[TMP10:%.*]], label [[TMP12:%.*]] -; IR-DPP: 10: -; IR-DPP-NEXT: [[TMP11:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-DPP-NEXT: br label [[TMP12]] -; IR-DPP: 12: -; IR-DPP-NEXT: [[TMP13:%.*]] = phi float [ poison, [[TMP2]] ], [ [[TMP11]], [[TMP10]] ] -; IR-DPP-NEXT: [[TMP14:%.*]] = bitcast float [[TMP13]] to i32 -; IR-DPP-NEXT: [[TMP15:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP14]]) -; IR-DPP-NEXT: [[TMP16:%.*]] = bitcast i32 [[TMP15]] to float -; IR-DPP-NEXT: [[TMP17:%.*]] = uitofp i32 [[TMP8]] to float -; IR-DPP-NEXT: [[TMP18:%.*]] = select i1 [[TMP9]], float 0x7FF0000000000000, float [[VAL]] -; IR-DPP-NEXT: [[TMP19:%.*]] = call float @llvm.minnum.f32(float [[TMP16]], float [[TMP18]]) -; IR-DPP-NEXT: br label [[TMP20]] -; IR-DPP: 20: -; IR-DPP-NEXT: [[TMP21:%.*]] = phi float [ poison, [[TMP0:%.*]] ], [ [[TMP19]], [[TMP12]] ] -; IR-DPP-NEXT: ret float [[TMP21]] +; IR-LABEL: @global_atomic_fmin_uni_address_uni_value_agent_scope_unsafe( +; IR-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() +; IR-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP20:%.*]] +; IR: 2: +; IR-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) +; IR-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) +; IR-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) +; IR-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-NEXT: br i1 [[TMP9]], label [[TMP10:%.*]], label [[TMP12:%.*]] +; IR: 10: +; IR-NEXT: [[TMP11:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: br label [[TMP12]] +; IR: 12: +; IR-NEXT: [[TMP13:%.*]] = phi float [ poison, [[TMP2]] ], [ [[TMP11]], [[TMP10]] ] +; IR-NEXT: [[TMP14:%.*]] = bitcast float [[TMP13]] to i32 +; IR-NEXT: [[TMP15:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP14]]) +; IR-NEXT: [[TMP16:%.*]] = bitcast i32 [[TMP15]] to float +; IR-NEXT: [[TMP17:%.*]] = uitofp i32 [[TMP8]] to float +; IR-NEXT: [[TMP18:%.*]] = select i1 [[TMP9]], float 0x7FF0000000000000, float [[VAL]] +; IR-NEXT: [[TMP19:%.*]] = call float @llvm.minnum.f32(float [[TMP16]], float [[TMP18]]) +; IR-NEXT: br label [[TMP20]] +; IR: 20: +; IR-NEXT: [[TMP21:%.*]] = phi float [ poison, [[TMP0:%.*]] ], [ [[TMP19]], [[TMP12]] ] +; IR-NEXT: ret float [[TMP21]] ; %result = atomicrmw fmin ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic ret float %result @@ -1007,164 +950,674 @@ define amdgpu_ps float @global_atomic_fadd_uni_address_div_value_system_scope_st ret float %result } - define amdgpu_ps float @global_atomic_fadd_div_address_uni_value_agent_scope_unsafe(ptr addrspace(1) %ptr, float inreg %val) #0 { -; IR-ITERATIVE-LABEL: @global_atomic_fadd_div_address_uni_value_agent_scope_unsafe( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-ITERATIVE-NEXT: ret float [[RESULT]] -; -; IR-DPP-LABEL: @global_atomic_fadd_div_address_uni_value_agent_scope_unsafe( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-DPP-NEXT: ret float [[RESULT]] +; IR-LABEL: @global_atomic_fadd_div_address_uni_value_agent_scope_unsafe( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret float [[RESULT]] ; %result = atomicrmw fadd ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic, align 4 ret float %result } define amdgpu_ps float @global_atomic_fadd_div_address_div_value_agent_scope_unsafe(ptr addrspace(1) %ptr, float %val) #0 { -; IR-ITERATIVE-LABEL: @global_atomic_fadd_div_address_div_value_agent_scope_unsafe( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-ITERATIVE-NEXT: ret float [[RESULT]] -; -; IR-DPP-LABEL: @global_atomic_fadd_div_address_div_value_agent_scope_unsafe( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-DPP-NEXT: ret float [[RESULT]] +; IR-LABEL: @global_atomic_fadd_div_address_div_value_agent_scope_unsafe( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret float [[RESULT]] ; %result = atomicrmw fadd ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic, align 4 ret float %result } define amdgpu_ps float @global_atomic_fadd_div_address_uni_value_one_as_scope_unsafe_structfp(ptr addrspace(1) %ptr, float inreg %val) #1 { -; IR-ITERATIVE-LABEL: @global_atomic_fadd_div_address_uni_value_one_as_scope_unsafe_structfp( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("one-as") monotonic, align 4 -; IR-ITERATIVE-NEXT: ret float [[RESULT]] -; -; IR-DPP-LABEL: @global_atomic_fadd_div_address_uni_value_one_as_scope_unsafe_structfp( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("one-as") monotonic, align 4 -; IR-DPP-NEXT: ret float [[RESULT]] +; IR-LABEL: @global_atomic_fadd_div_address_uni_value_one_as_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("one-as") monotonic, align 4 +; IR-NEXT: ret float [[RESULT]] ; %result = atomicrmw fadd ptr addrspace(1) %ptr, float %val syncscope("one-as") monotonic ret float %result } define amdgpu_ps float @global_atomic_fadd_div_address_div_value_one_as_scope_unsafe_structfp(ptr addrspace(1) %ptr, float %val) #1 { -; IR-ITERATIVE-LABEL: @global_atomic_fadd_div_address_div_value_one_as_scope_unsafe_structfp( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("one-as") monotonic, align 4 -; IR-ITERATIVE-NEXT: ret float [[RESULT]] -; -; IR-DPP-LABEL: @global_atomic_fadd_div_address_div_value_one_as_scope_unsafe_structfp( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("one-as") monotonic, align 4 -; IR-DPP-NEXT: ret float [[RESULT]] +; IR-LABEL: @global_atomic_fadd_div_address_div_value_one_as_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("one-as") monotonic, align 4 +; IR-NEXT: ret float [[RESULT]] ; %result = atomicrmw fadd ptr addrspace(1) %ptr, float %val syncscope("one-as") monotonic ret float %result } define amdgpu_ps float @global_atomic_fsub_div_address_uni_value_agent_scope_strictfp(ptr addrspace(1) %ptr, float inreg %val) #2 { -; IR-ITERATIVE-LABEL: @global_atomic_fsub_div_address_uni_value_agent_scope_strictfp( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-ITERATIVE-NEXT: ret float [[RESULT]] -; -; IR-DPP-LABEL: @global_atomic_fsub_div_address_uni_value_agent_scope_strictfp( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-DPP-NEXT: ret float [[RESULT]] +; IR-LABEL: @global_atomic_fsub_div_address_uni_value_agent_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret float [[RESULT]] ; %result = atomicrmw fadd ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic ret float %result } - define amdgpu_ps float @global_atomic_fsub_div_address_div_value_agent_scope_strictfp(ptr addrspace(1) %ptr, float %val) #2 { -; IR-ITERATIVE-LABEL: @global_atomic_fsub_div_address_div_value_agent_scope_strictfp( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fsub ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-ITERATIVE-NEXT: ret float [[RESULT]] -; -; IR-DPP-LABEL: @global_atomic_fsub_div_address_div_value_agent_scope_strictfp( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fsub ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-DPP-NEXT: ret float [[RESULT]] +; IR-LABEL: @global_atomic_fsub_div_address_div_value_agent_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fsub ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret float [[RESULT]] ; %result = atomicrmw fsub ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic ret float %result } define amdgpu_ps float @global_atomic_fmin_div_address_uni_value_agent_scope(ptr addrspace(1) %ptr, float inreg %val) #0 { -; IR-ITERATIVE-LABEL: @global_atomic_fmin_div_address_uni_value_agent_scope( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-ITERATIVE-NEXT: ret float [[RESULT]] -; -; IR-DPP-LABEL: @global_atomic_fmin_div_address_uni_value_agent_scope( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-DPP-NEXT: ret float [[RESULT]] +; IR-LABEL: @global_atomic_fmin_div_address_uni_value_agent_scope( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret float [[RESULT]] ; %result = atomicrmw fmin ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic ret float %result } define amdgpu_ps float @global_atomic_fmin_div_address_div_value_agent_scope(ptr addrspace(1) %ptr, float %val) #0 { -; IR-ITERATIVE-LABEL: @global_atomic_fmin_div_address_div_value_agent_scope( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-ITERATIVE-NEXT: ret float [[RESULT]] -; -; IR-DPP-LABEL: @global_atomic_fmin_div_address_div_value_agent_scope( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-DPP-NEXT: ret float [[RESULT]] +; IR-LABEL: @global_atomic_fmin_div_address_div_value_agent_scope( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret float [[RESULT]] ; %result = atomicrmw fmin ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic ret float %result } define amdgpu_ps float @global_atomic_fmax_div_address_uni_value_agent_scope_unsafe_structfp(ptr addrspace(1) %ptr, float inreg %val) #1{ -; IR-ITERATIVE-LABEL: @global_atomic_fmax_div_address_uni_value_agent_scope_unsafe_structfp( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-ITERATIVE-NEXT: ret float [[RESULT]] -; -; IR-DPP-LABEL: @global_atomic_fmax_div_address_uni_value_agent_scope_unsafe_structfp( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-DPP-NEXT: ret float [[RESULT]] +; IR-LABEL: @global_atomic_fmax_div_address_uni_value_agent_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret float [[RESULT]] ; %result = atomicrmw fmax ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic ret float %result } define amdgpu_ps float @global_atomic_fmax_div_address_div_value_agent_scope_unsafe_structfp(ptr addrspace(1) %ptr, float %val) #1{ -; IR-ITERATIVE-LABEL: @global_atomic_fmax_div_address_div_value_agent_scope_unsafe_structfp( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-ITERATIVE-NEXT: ret float [[RESULT]] -; -; IR-DPP-LABEL: @global_atomic_fmax_div_address_div_value_agent_scope_unsafe_structfp( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-DPP-NEXT: ret float [[RESULT]] +; IR-LABEL: @global_atomic_fmax_div_address_div_value_agent_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret float [[RESULT]] ; %result = atomicrmw fmax ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic ret float %result } define amdgpu_ps float @global_atomic_fadd_div_address_uni_value_system_scope_strictfp(ptr addrspace(1) %ptr, float inreg %val) #2 { -; IR-ITERATIVE-LABEL: @global_atomic_fadd_div_address_uni_value_system_scope_strictfp( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] monotonic, align 4 -; IR-ITERATIVE-NEXT: ret float [[RESULT]] -; -; IR-DPP-LABEL: @global_atomic_fadd_div_address_uni_value_system_scope_strictfp( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] monotonic, align 4 -; IR-DPP-NEXT: ret float [[RESULT]] +; IR-LABEL: @global_atomic_fadd_div_address_uni_value_system_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] monotonic, align 4 +; IR-NEXT: ret float [[RESULT]] ; %result = atomicrmw fadd ptr addrspace(1) %ptr, float %val monotonic, align 4 ret float %result } define amdgpu_ps float @global_atomic_fadd_div_address_div_value_system_scope_strictfp(ptr addrspace(1) %ptr, float %val) #2 { -; IR-ITERATIVE-LABEL: @global_atomic_fadd_div_address_div_value_system_scope_strictfp( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] monotonic, align 4 -; IR-ITERATIVE-NEXT: ret float [[RESULT]] -; -; IR-DPP-LABEL: @global_atomic_fadd_div_address_div_value_system_scope_strictfp( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] monotonic, align 4 -; IR-DPP-NEXT: ret float [[RESULT]] +; IR-LABEL: @global_atomic_fadd_div_address_div_value_system_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] monotonic, align 4 +; IR-NEXT: ret float [[RESULT]] ; %result = atomicrmw fadd ptr addrspace(1) %ptr, float %val monotonic, align 4 ret float %result } +define amdgpu_ps double @global_atomic_fadd_double_uni_address_uni_value_agent_scope_unsafe(ptr addrspace(1) inreg %ptr, double inreg %val) #0 { +; IR-LABEL: @global_atomic_fadd_double_uni_address_uni_value_agent_scope_unsafe( +; IR-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() +; IR-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP30:%.*]] +; IR: 2: +; IR-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) +; IR-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) +; IR-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) +; IR-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) +; IR-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 +; IR-NEXT: [[TMP11:%.*]] = uitofp i32 [[TMP10]] to double +; IR-NEXT: [[TMP12:%.*]] = fmul double [[VAL:%.*]], [[TMP11]] +; IR-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] +; IR: 14: +; IR-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[TMP12]] syncscope("agent") monotonic, align 4 +; IR-NEXT: br label [[TMP16]] +; IR: 16: +; IR-NEXT: [[TMP17:%.*]] = phi double [ poison, [[TMP2]] ], [ [[TMP15]], [[TMP14]] ] +; IR-NEXT: [[TMP18:%.*]] = bitcast double [[TMP17]] to i64 +; IR-NEXT: [[TMP19:%.*]] = trunc i64 [[TMP18]] to i32 +; IR-NEXT: [[TMP20:%.*]] = lshr i64 [[TMP18]], 32 +; IR-NEXT: [[TMP21:%.*]] = trunc i64 [[TMP20]] to i32 +; IR-NEXT: [[TMP22:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP19]]) +; IR-NEXT: [[TMP23:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP21]]) +; IR-NEXT: [[TMP24:%.*]] = insertelement <2 x i32> poison, i32 [[TMP22]], i32 0 +; IR-NEXT: [[TMP25:%.*]] = insertelement <2 x i32> [[TMP24]], i32 [[TMP23]], i32 1 +; IR-NEXT: [[TMP26:%.*]] = bitcast <2 x i32> [[TMP25]] to double +; IR-NEXT: [[TMP27:%.*]] = uitofp i32 [[TMP8]] to double +; IR-NEXT: [[TMP28:%.*]] = fmul double [[VAL]], [[TMP27]] +; IR-NEXT: [[TMP29:%.*]] = fadd double [[TMP26]], [[TMP28]] +; IR-NEXT: br label [[TMP30]] +; IR: 30: +; IR-NEXT: [[TMP31:%.*]] = phi double [ poison, [[TMP0:%.*]] ], [ [[TMP29]], [[TMP16]] ] +; IR-NEXT: ret double [[TMP31]] +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic, align 4 + ret double %result +} + +define amdgpu_ps double @global_atomic_fadd_double_uni_address_div_value_scope_agent_scope_unsafe(ptr addrspace(1) inreg %ptr, double %val) #0 { +; IR-LABEL: @global_atomic_fadd_double_uni_address_div_value_scope_agent_scope_unsafe( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret double [[RESULT]] +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic, align 4 + ret double %result +} + +define amdgpu_ps double @global_atomic_fadd_double_uni_address_uni_value_one_as_scope_unsafe_structfp(ptr addrspace(1) inreg %ptr, double inreg %val) #1 { +; IR-ITERATIVE-LABEL: @global_atomic_fadd_double_uni_address_uni_value_one_as_scope_unsafe_structfp( +; IR-ITERATIVE-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() #[[ATTR7]] +; IR-ITERATIVE-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP30:%.*]] +; IR-ITERATIVE: 2: +; IR-ITERATIVE-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-ITERATIVE-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-ITERATIVE-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-ITERATIVE-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 +; IR-ITERATIVE-NEXT: [[TMP11:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP10]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP12:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[VAL:%.*]], double [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-ITERATIVE-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] +; IR-ITERATIVE: 14: +; IR-ITERATIVE-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[TMP12]] syncscope("one-as") monotonic, align 8 +; IR-ITERATIVE-NEXT: br label [[TMP16]] +; IR-ITERATIVE: 16: +; IR-ITERATIVE-NEXT: [[TMP17:%.*]] = phi double [ poison, [[TMP2]] ], [ [[TMP15]], [[TMP14]] ] +; IR-ITERATIVE-NEXT: [[TMP18:%.*]] = bitcast double [[TMP17]] to i64 +; IR-ITERATIVE-NEXT: [[TMP19:%.*]] = trunc i64 [[TMP18]] to i32 +; IR-ITERATIVE-NEXT: [[TMP20:%.*]] = lshr i64 [[TMP18]], 32 +; IR-ITERATIVE-NEXT: [[TMP21:%.*]] = trunc i64 [[TMP20]] to i32 +; IR-ITERATIVE-NEXT: [[TMP22:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP19]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP23:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP21]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP24:%.*]] = insertelement <2 x i32> poison, i32 [[TMP22]], i32 0 +; IR-ITERATIVE-NEXT: [[TMP25:%.*]] = insertelement <2 x i32> [[TMP24]], i32 [[TMP23]], i32 1 +; IR-ITERATIVE-NEXT: [[TMP26:%.*]] = bitcast <2 x i32> [[TMP25]] to double +; IR-ITERATIVE-NEXT: [[TMP27:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP8]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP28:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[VAL]], double [[TMP27]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP29:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP26]], double [[TMP28]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: br label [[TMP30]] +; IR-ITERATIVE: 30: +; IR-ITERATIVE-NEXT: [[TMP31:%.*]] = phi double [ poison, [[TMP0:%.*]] ], [ [[TMP29]], [[TMP16]] ] +; IR-ITERATIVE-NEXT: ret double [[TMP31]] +; +; IR-DPP-LABEL: @global_atomic_fadd_double_uni_address_uni_value_one_as_scope_unsafe_structfp( +; IR-DPP-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() #[[ATTR8]] +; IR-DPP-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP30:%.*]] +; IR-DPP: 2: +; IR-DPP-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-DPP-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-DPP-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-DPP-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 +; IR-DPP-NEXT: [[TMP11:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP10]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP12:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[VAL:%.*]], double [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-DPP-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] +; IR-DPP: 14: +; IR-DPP-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[TMP12]] syncscope("one-as") monotonic, align 8 +; IR-DPP-NEXT: br label [[TMP16]] +; IR-DPP: 16: +; IR-DPP-NEXT: [[TMP17:%.*]] = phi double [ poison, [[TMP2]] ], [ [[TMP15]], [[TMP14]] ] +; IR-DPP-NEXT: [[TMP18:%.*]] = bitcast double [[TMP17]] to i64 +; IR-DPP-NEXT: [[TMP19:%.*]] = trunc i64 [[TMP18]] to i32 +; IR-DPP-NEXT: [[TMP20:%.*]] = lshr i64 [[TMP18]], 32 +; IR-DPP-NEXT: [[TMP21:%.*]] = trunc i64 [[TMP20]] to i32 +; IR-DPP-NEXT: [[TMP22:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP19]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP23:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP21]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP24:%.*]] = insertelement <2 x i32> poison, i32 [[TMP22]], i32 0 +; IR-DPP-NEXT: [[TMP25:%.*]] = insertelement <2 x i32> [[TMP24]], i32 [[TMP23]], i32 1 +; IR-DPP-NEXT: [[TMP26:%.*]] = bitcast <2 x i32> [[TMP25]] to double +; IR-DPP-NEXT: [[TMP27:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP8]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP28:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[VAL]], double [[TMP27]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP29:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP26]], double [[TMP28]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: br label [[TMP30]] +; IR-DPP: 30: +; IR-DPP-NEXT: [[TMP31:%.*]] = phi double [ poison, [[TMP0:%.*]] ], [ [[TMP29]], [[TMP16]] ] +; IR-DPP-NEXT: ret double [[TMP31]] +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("one-as") monotonic + ret double %result +} + +define amdgpu_ps double @global_atomic_fadd_double_uni_address_div_value_one_as_scope_unsafe_structfp(ptr addrspace(1) inreg %ptr, double %val) #1 { +; IR-LABEL: @global_atomic_fadd_double_uni_address_div_value_one_as_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("one-as") monotonic, align 8 +; IR-NEXT: ret double [[RESULT]] +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("one-as") monotonic + ret double %result +} + +define amdgpu_ps double @global_atomic_fsub_double_uni_address_uni_value_agent_scope_strictfp(ptr addrspace(1) inreg %ptr, double inreg %val) #2 { +; IR-ITERATIVE-LABEL: @global_atomic_fsub_double_uni_address_uni_value_agent_scope_strictfp( +; IR-ITERATIVE-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() #[[ATTR7]] +; IR-ITERATIVE-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP30:%.*]] +; IR-ITERATIVE: 2: +; IR-ITERATIVE-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-ITERATIVE-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-ITERATIVE-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-ITERATIVE-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 +; IR-ITERATIVE-NEXT: [[TMP11:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP10]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP12:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[VAL:%.*]], double [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-ITERATIVE-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] +; IR-ITERATIVE: 14: +; IR-ITERATIVE-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[TMP12]] syncscope("agent") monotonic, align 8 +; IR-ITERATIVE-NEXT: br label [[TMP16]] +; IR-ITERATIVE: 16: +; IR-ITERATIVE-NEXT: [[TMP17:%.*]] = phi double [ poison, [[TMP2]] ], [ [[TMP15]], [[TMP14]] ] +; IR-ITERATIVE-NEXT: [[TMP18:%.*]] = bitcast double [[TMP17]] to i64 +; IR-ITERATIVE-NEXT: [[TMP19:%.*]] = trunc i64 [[TMP18]] to i32 +; IR-ITERATIVE-NEXT: [[TMP20:%.*]] = lshr i64 [[TMP18]], 32 +; IR-ITERATIVE-NEXT: [[TMP21:%.*]] = trunc i64 [[TMP20]] to i32 +; IR-ITERATIVE-NEXT: [[TMP22:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP19]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP23:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP21]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP24:%.*]] = insertelement <2 x i32> poison, i32 [[TMP22]], i32 0 +; IR-ITERATIVE-NEXT: [[TMP25:%.*]] = insertelement <2 x i32> [[TMP24]], i32 [[TMP23]], i32 1 +; IR-ITERATIVE-NEXT: [[TMP26:%.*]] = bitcast <2 x i32> [[TMP25]] to double +; IR-ITERATIVE-NEXT: [[TMP27:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP8]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP28:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[VAL]], double [[TMP27]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP29:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP26]], double [[TMP28]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: br label [[TMP30]] +; IR-ITERATIVE: 30: +; IR-ITERATIVE-NEXT: [[TMP31:%.*]] = phi double [ poison, [[TMP0:%.*]] ], [ [[TMP29]], [[TMP16]] ] +; IR-ITERATIVE-NEXT: ret double [[TMP31]] +; +; IR-DPP-LABEL: @global_atomic_fsub_double_uni_address_uni_value_agent_scope_strictfp( +; IR-DPP-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() #[[ATTR8]] +; IR-DPP-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP30:%.*]] +; IR-DPP: 2: +; IR-DPP-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-DPP-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-DPP-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-DPP-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 +; IR-DPP-NEXT: [[TMP11:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP10]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP12:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[VAL:%.*]], double [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-DPP-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] +; IR-DPP: 14: +; IR-DPP-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[TMP12]] syncscope("agent") monotonic, align 8 +; IR-DPP-NEXT: br label [[TMP16]] +; IR-DPP: 16: +; IR-DPP-NEXT: [[TMP17:%.*]] = phi double [ poison, [[TMP2]] ], [ [[TMP15]], [[TMP14]] ] +; IR-DPP-NEXT: [[TMP18:%.*]] = bitcast double [[TMP17]] to i64 +; IR-DPP-NEXT: [[TMP19:%.*]] = trunc i64 [[TMP18]] to i32 +; IR-DPP-NEXT: [[TMP20:%.*]] = lshr i64 [[TMP18]], 32 +; IR-DPP-NEXT: [[TMP21:%.*]] = trunc i64 [[TMP20]] to i32 +; IR-DPP-NEXT: [[TMP22:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP19]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP23:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP21]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP24:%.*]] = insertelement <2 x i32> poison, i32 [[TMP22]], i32 0 +; IR-DPP-NEXT: [[TMP25:%.*]] = insertelement <2 x i32> [[TMP24]], i32 [[TMP23]], i32 1 +; IR-DPP-NEXT: [[TMP26:%.*]] = bitcast <2 x i32> [[TMP25]] to double +; IR-DPP-NEXT: [[TMP27:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP8]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP28:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[VAL]], double [[TMP27]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP29:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP26]], double [[TMP28]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: br label [[TMP30]] +; IR-DPP: 30: +; IR-DPP-NEXT: [[TMP31:%.*]] = phi double [ poison, [[TMP0:%.*]] ], [ [[TMP29]], [[TMP16]] ] +; IR-DPP-NEXT: ret double [[TMP31]] +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret double %result +} + +define amdgpu_ps double @global_atomic_fsub_double_uni_address_div_value_agent_scope_strictfp(ptr addrspace(1) inreg %ptr, double %val) #2 { +; IR-LABEL: @global_atomic_fsub_double_uni_address_div_value_agent_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fsub ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: ret double [[RESULT]] +; + %result = atomicrmw fsub ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret double %result +} + +define amdgpu_ps double @global_atomic_fmin_double_uni_address_uni_value_agent_scope_unsafe(ptr addrspace(1) inreg %ptr, double inreg %val) #0 { +; IR-LABEL: @global_atomic_fmin_double_uni_address_uni_value_agent_scope_unsafe( +; IR-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() +; IR-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP26:%.*]] +; IR: 2: +; IR-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) +; IR-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) +; IR-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) +; IR-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-NEXT: br i1 [[TMP9]], label [[TMP10:%.*]], label [[TMP12:%.*]] +; IR: 10: +; IR-NEXT: [[TMP11:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: br label [[TMP12]] +; IR: 12: +; IR-NEXT: [[TMP13:%.*]] = phi double [ poison, [[TMP2]] ], [ [[TMP11]], [[TMP10]] ] +; IR-NEXT: [[TMP14:%.*]] = bitcast double [[TMP13]] to i64 +; IR-NEXT: [[TMP15:%.*]] = trunc i64 [[TMP14]] to i32 +; IR-NEXT: [[TMP16:%.*]] = lshr i64 [[TMP14]], 32 +; IR-NEXT: [[TMP17:%.*]] = trunc i64 [[TMP16]] to i32 +; IR-NEXT: [[TMP18:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP15]]) +; IR-NEXT: [[TMP19:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP17]]) +; IR-NEXT: [[TMP20:%.*]] = insertelement <2 x i32> poison, i32 [[TMP18]], i32 0 +; IR-NEXT: [[TMP21:%.*]] = insertelement <2 x i32> [[TMP20]], i32 [[TMP19]], i32 1 +; IR-NEXT: [[TMP22:%.*]] = bitcast <2 x i32> [[TMP21]] to double +; IR-NEXT: [[TMP23:%.*]] = uitofp i32 [[TMP8]] to double +; IR-NEXT: [[TMP24:%.*]] = select i1 [[TMP9]], double 0x7FF0000000000000, double [[VAL]] +; IR-NEXT: [[TMP25:%.*]] = call double @llvm.minnum.f64(double [[TMP22]], double [[TMP24]]) +; IR-NEXT: br label [[TMP26]] +; IR: 26: +; IR-NEXT: [[TMP27:%.*]] = phi double [ poison, [[TMP0:%.*]] ], [ [[TMP25]], [[TMP12]] ] +; IR-NEXT: ret double [[TMP27]] +; + %result = atomicrmw fmin ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret double %result +} + +define amdgpu_ps double @global_atomic_fmin_double_uni_address_div_value_agent_scope_unsafe(ptr addrspace(1) inreg %ptr, double %val) #0 { +; IR-LABEL: @global_atomic_fmin_double_uni_address_div_value_agent_scope_unsafe( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: ret double [[RESULT]] +; + %result = atomicrmw fmin ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret double %result +} + +define amdgpu_ps double @global_atomic__fmax_double_uni_address_uni_value_agent_scope_unsafe_structfp(ptr addrspace(1) inreg %ptr, double inreg %val) #1{ +; IR-ITERATIVE-LABEL: @global_atomic__fmax_double_uni_address_uni_value_agent_scope_unsafe_structfp( +; IR-ITERATIVE-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() #[[ATTR7]] +; IR-ITERATIVE-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP26:%.*]] +; IR-ITERATIVE: 2: +; IR-ITERATIVE-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-ITERATIVE-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-ITERATIVE-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-ITERATIVE-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-ITERATIVE-NEXT: br i1 [[TMP9]], label [[TMP10:%.*]], label [[TMP12:%.*]] +; IR-ITERATIVE: 10: +; IR-ITERATIVE-NEXT: [[TMP11:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-ITERATIVE-NEXT: br label [[TMP12]] +; IR-ITERATIVE: 12: +; IR-ITERATIVE-NEXT: [[TMP13:%.*]] = phi double [ poison, [[TMP2]] ], [ [[TMP11]], [[TMP10]] ] +; IR-ITERATIVE-NEXT: [[TMP14:%.*]] = bitcast double [[TMP13]] to i64 +; IR-ITERATIVE-NEXT: [[TMP15:%.*]] = trunc i64 [[TMP14]] to i32 +; IR-ITERATIVE-NEXT: [[TMP16:%.*]] = lshr i64 [[TMP14]], 32 +; IR-ITERATIVE-NEXT: [[TMP17:%.*]] = trunc i64 [[TMP16]] to i32 +; IR-ITERATIVE-NEXT: [[TMP18:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP15]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP19:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP17]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP20:%.*]] = insertelement <2 x i32> poison, i32 [[TMP18]], i32 0 +; IR-ITERATIVE-NEXT: [[TMP21:%.*]] = insertelement <2 x i32> [[TMP20]], i32 [[TMP19]], i32 1 +; IR-ITERATIVE-NEXT: [[TMP22:%.*]] = bitcast <2 x i32> [[TMP21]] to double +; IR-ITERATIVE-NEXT: [[TMP23:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP8]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP24:%.*]] = select i1 [[TMP9]], double 0xFFF0000000000000, double [[VAL]] +; IR-ITERATIVE-NEXT: [[TMP25:%.*]] = call double @llvm.experimental.constrained.maxnum.f64(double [[TMP22]], double [[TMP24]], metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: br label [[TMP26]] +; IR-ITERATIVE: 26: +; IR-ITERATIVE-NEXT: [[TMP27:%.*]] = phi double [ poison, [[TMP0:%.*]] ], [ [[TMP25]], [[TMP12]] ] +; IR-ITERATIVE-NEXT: ret double [[TMP27]] +; +; IR-DPP-LABEL: @global_atomic__fmax_double_uni_address_uni_value_agent_scope_unsafe_structfp( +; IR-DPP-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() #[[ATTR8]] +; IR-DPP-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP26:%.*]] +; IR-DPP: 2: +; IR-DPP-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-DPP-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-DPP-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-DPP-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-DPP-NEXT: br i1 [[TMP9]], label [[TMP10:%.*]], label [[TMP12:%.*]] +; IR-DPP: 10: +; IR-DPP-NEXT: [[TMP11:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-DPP-NEXT: br label [[TMP12]] +; IR-DPP: 12: +; IR-DPP-NEXT: [[TMP13:%.*]] = phi double [ poison, [[TMP2]] ], [ [[TMP11]], [[TMP10]] ] +; IR-DPP-NEXT: [[TMP14:%.*]] = bitcast double [[TMP13]] to i64 +; IR-DPP-NEXT: [[TMP15:%.*]] = trunc i64 [[TMP14]] to i32 +; IR-DPP-NEXT: [[TMP16:%.*]] = lshr i64 [[TMP14]], 32 +; IR-DPP-NEXT: [[TMP17:%.*]] = trunc i64 [[TMP16]] to i32 +; IR-DPP-NEXT: [[TMP18:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP15]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP19:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP17]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP20:%.*]] = insertelement <2 x i32> poison, i32 [[TMP18]], i32 0 +; IR-DPP-NEXT: [[TMP21:%.*]] = insertelement <2 x i32> [[TMP20]], i32 [[TMP19]], i32 1 +; IR-DPP-NEXT: [[TMP22:%.*]] = bitcast <2 x i32> [[TMP21]] to double +; IR-DPP-NEXT: [[TMP23:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP8]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP24:%.*]] = select i1 [[TMP9]], double 0xFFF0000000000000, double [[VAL]] +; IR-DPP-NEXT: [[TMP25:%.*]] = call double @llvm.experimental.constrained.maxnum.f64(double [[TMP22]], double [[TMP24]], metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: br label [[TMP26]] +; IR-DPP: 26: +; IR-DPP-NEXT: [[TMP27:%.*]] = phi double [ poison, [[TMP0:%.*]] ], [ [[TMP25]], [[TMP12]] ] +; IR-DPP-NEXT: ret double [[TMP27]] +; + %result = atomicrmw fmax ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret double %result +} + +define amdgpu_ps double @global_atomic__fmax_double_uni_address_div_value_agent_scope_unsafe_structfp(ptr addrspace(1) inreg %ptr, double %val) #1{ +; IR-LABEL: @global_atomic__fmax_double_uni_address_div_value_agent_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: ret double [[RESULT]] +; + %result = atomicrmw fmax ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret double %result +} + +define amdgpu_ps double @global_atomic_fadd_double_uni_address_uni_value_system_scope_strictfp(ptr addrspace(1) inreg %ptr, double inreg %val) #2 { +; IR-ITERATIVE-LABEL: @global_atomic_fadd_double_uni_address_uni_value_system_scope_strictfp( +; IR-ITERATIVE-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() #[[ATTR7]] +; IR-ITERATIVE-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP30:%.*]] +; IR-ITERATIVE: 2: +; IR-ITERATIVE-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-ITERATIVE-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-ITERATIVE-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-ITERATIVE-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 +; IR-ITERATIVE-NEXT: [[TMP11:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP10]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP12:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[VAL:%.*]], double [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-ITERATIVE-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] +; IR-ITERATIVE: 14: +; IR-ITERATIVE-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[TMP12]] monotonic, align 4 +; IR-ITERATIVE-NEXT: br label [[TMP16]] +; IR-ITERATIVE: 16: +; IR-ITERATIVE-NEXT: [[TMP17:%.*]] = phi double [ poison, [[TMP2]] ], [ [[TMP15]], [[TMP14]] ] +; IR-ITERATIVE-NEXT: [[TMP18:%.*]] = bitcast double [[TMP17]] to i64 +; IR-ITERATIVE-NEXT: [[TMP19:%.*]] = trunc i64 [[TMP18]] to i32 +; IR-ITERATIVE-NEXT: [[TMP20:%.*]] = lshr i64 [[TMP18]], 32 +; IR-ITERATIVE-NEXT: [[TMP21:%.*]] = trunc i64 [[TMP20]] to i32 +; IR-ITERATIVE-NEXT: [[TMP22:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP19]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP23:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP21]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP24:%.*]] = insertelement <2 x i32> poison, i32 [[TMP22]], i32 0 +; IR-ITERATIVE-NEXT: [[TMP25:%.*]] = insertelement <2 x i32> [[TMP24]], i32 [[TMP23]], i32 1 +; IR-ITERATIVE-NEXT: [[TMP26:%.*]] = bitcast <2 x i32> [[TMP25]] to double +; IR-ITERATIVE-NEXT: [[TMP27:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP8]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP28:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[VAL]], double [[TMP27]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP29:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP26]], double [[TMP28]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: br label [[TMP30]] +; IR-ITERATIVE: 30: +; IR-ITERATIVE-NEXT: [[TMP31:%.*]] = phi double [ poison, [[TMP0:%.*]] ], [ [[TMP29]], [[TMP16]] ] +; IR-ITERATIVE-NEXT: ret double [[TMP31]] +; +; IR-DPP-LABEL: @global_atomic_fadd_double_uni_address_uni_value_system_scope_strictfp( +; IR-DPP-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() #[[ATTR8]] +; IR-DPP-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP30:%.*]] +; IR-DPP: 2: +; IR-DPP-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-DPP-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-DPP-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-DPP-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 +; IR-DPP-NEXT: [[TMP11:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP10]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP12:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[VAL:%.*]], double [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-DPP-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] +; IR-DPP: 14: +; IR-DPP-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[TMP12]] monotonic, align 4 +; IR-DPP-NEXT: br label [[TMP16]] +; IR-DPP: 16: +; IR-DPP-NEXT: [[TMP17:%.*]] = phi double [ poison, [[TMP2]] ], [ [[TMP15]], [[TMP14]] ] +; IR-DPP-NEXT: [[TMP18:%.*]] = bitcast double [[TMP17]] to i64 +; IR-DPP-NEXT: [[TMP19:%.*]] = trunc i64 [[TMP18]] to i32 +; IR-DPP-NEXT: [[TMP20:%.*]] = lshr i64 [[TMP18]], 32 +; IR-DPP-NEXT: [[TMP21:%.*]] = trunc i64 [[TMP20]] to i32 +; IR-DPP-NEXT: [[TMP22:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP19]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP23:%.*]] = call i32 @llvm.amdgcn.readfirstlane(i32 [[TMP21]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP24:%.*]] = insertelement <2 x i32> poison, i32 [[TMP22]], i32 0 +; IR-DPP-NEXT: [[TMP25:%.*]] = insertelement <2 x i32> [[TMP24]], i32 [[TMP23]], i32 1 +; IR-DPP-NEXT: [[TMP26:%.*]] = bitcast <2 x i32> [[TMP25]] to double +; IR-DPP-NEXT: [[TMP27:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP8]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP28:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[VAL]], double [[TMP27]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP29:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double [[TMP26]], double [[TMP28]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: br label [[TMP30]] +; IR-DPP: 30: +; IR-DPP-NEXT: [[TMP31:%.*]] = phi double [ poison, [[TMP0:%.*]] ], [ [[TMP29]], [[TMP16]] ] +; IR-DPP-NEXT: ret double [[TMP31]] +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val monotonic, align 4 + ret double %result +} + +define amdgpu_ps double @global_atomic_fadd_double_uni_address_div_value_system_scope_strictfp(ptr addrspace(1) inreg %ptr, double %val) #2 { +; IR-LABEL: @global_atomic_fadd_double_uni_address_div_value_system_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] monotonic, align 4 +; IR-NEXT: ret double [[RESULT]] +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val monotonic, align 4 + ret double %result +} + +define amdgpu_ps double @global_atomic_fadd_double_div_address_uni_value_agent_scope_unsafe(ptr addrspace(1) %ptr, double inreg %val) #0 { +; IR-LABEL: @global_atomic_fadd_double_div_address_uni_value_agent_scope_unsafe( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret double [[RESULT]] +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic, align 4 + ret double %result +} + +define amdgpu_ps double @global_atomic_fadd_double_div_address_div_value_agent_scope_unsafe(ptr addrspace(1) %ptr, double %val) #0 { +; IR-LABEL: @global_atomic_fadd_double_div_address_div_value_agent_scope_unsafe( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret double [[RESULT]] +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic, align 4 + ret double %result +} + +define amdgpu_ps double @global_atomic_fadd_double_div_address_uni_value_one_as_scope_unsafe_structfp(ptr addrspace(1) %ptr, double inreg %val) #1 { +; IR-LABEL: @global_atomic_fadd_double_div_address_uni_value_one_as_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("one-as") monotonic, align 8 +; IR-NEXT: ret double [[RESULT]] +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("one-as") monotonic + ret double %result +} + +define amdgpu_ps double @global_atomic_fadd_double_div_address_div_value_one_as_scope_unsafe_structfp(ptr addrspace(1) %ptr, double %val) #1 { +; IR-LABEL: @global_atomic_fadd_double_div_address_div_value_one_as_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("one-as") monotonic, align 8 +; IR-NEXT: ret double [[RESULT]] +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("one-as") monotonic + ret double %result +} + +define amdgpu_ps double @global_atomic_fsub_double_div_address_uni_value_agent_scope_strictfp(ptr addrspace(1) %ptr, double inreg %val) #2 { +; IR-LABEL: @global_atomic_fsub_double_div_address_uni_value_agent_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: ret double [[RESULT]] +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret double %result +} + +define amdgpu_ps double @global_atomic_fsub_double_div_address_div_value_agent_scope_strictfp(ptr addrspace(1) %ptr, double %val) #2 { +; IR-LABEL: @global_atomic_fsub_double_div_address_div_value_agent_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fsub ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: ret double [[RESULT]] +; + %result = atomicrmw fsub ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret double %result +} + +define amdgpu_ps double @global_atomic_fmin_double_div_address_uni_value_agent_scope(ptr addrspace(1) %ptr, double inreg %val) #0 { +; IR-LABEL: @global_atomic_fmin_double_div_address_uni_value_agent_scope( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: ret double [[RESULT]] +; + %result = atomicrmw fmin ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret double %result +} + +define amdgpu_ps double @global_atomic_fmin_double_div_address_div_value_agent_scope(ptr addrspace(1) %ptr, double %val) #0 { +; IR-LABEL: @global_atomic_fmin_double_div_address_div_value_agent_scope( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: ret double [[RESULT]] +; + %result = atomicrmw fmin ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret double %result +} + +define amdgpu_ps double @global_atomic__fmax_double_div_address_uni_value_agent_scope_unsafe_structfp(ptr addrspace(1) %ptr, double inreg %val) #1{ +; IR-LABEL: @global_atomic__fmax_double_div_address_uni_value_agent_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: ret double [[RESULT]] +; + %result = atomicrmw fmax ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret double %result +} + +define amdgpu_ps double @global_atomic__fmax_double_div_address_div_value_agent_scope_unsafe_structfp(ptr addrspace(1) %ptr, double %val) #1{ +; IR-LABEL: @global_atomic__fmax_double_div_address_div_value_agent_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: ret double [[RESULT]] +; + %result = atomicrmw fmax ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret double %result +} + +define amdgpu_ps double @global_atomic_fadd_double_div_address_uni_value_system_scope_strictfp(ptr addrspace(1) %ptr, double inreg %val) #2 { +; IR-LABEL: @global_atomic_fadd_double_div_address_uni_value_system_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] monotonic, align 4 +; IR-NEXT: ret double [[RESULT]] +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val monotonic, align 4 + ret double %result +} + +define amdgpu_ps double @global_atomic_fadd_double_div_address_div_value_system_scope_strictfp(ptr addrspace(1) %ptr, double %val) #2 { +; IR-LABEL: @global_atomic_fadd_double_div_address_div_value_system_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] monotonic, align 4 +; IR-NEXT: ret double [[RESULT]] +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val monotonic, align 4 + ret double %result +} + attributes #0 = { "denormal-fp-math-f32"="preserve-sign,preserve-sign" "amdgpu-unsafe-fp-atomics"="true" } attributes #1 = { strictfp "denormal-fp-math-f32"="preserve-sign,preserve-sign" "amdgpu-unsafe-fp-atomics"="true" } attributes #2 = { strictfp } diff --git a/llvm/test/CodeGen/AMDGPU/global_atomics_i32_system.ll b/llvm/test/CodeGen/AMDGPU/global_atomics_i32_system.ll index 76ec1cc84f55b2a35375e788d5ee6b29d2d7d4ac..99d02ffaa523d5128d37ac6a8a9b41481a9d9783 100644 --- a/llvm/test/CodeGen/AMDGPU/global_atomics_i32_system.ll +++ b/llvm/test/CodeGen/AMDGPU/global_atomics_i32_system.ll @@ -358,65 +358,6 @@ define amdgpu_gfx i32 @global_atomic_xchg_i32_ret_offset_scalar(ptr addrspace(1) ; --------------------------------------------------------------------- define void @global_atomic_xchg_f32_noret(ptr addrspace(1) %ptr, float %in) { -; GCN1-LABEL: global_atomic_xchg_f32_noret: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_load_dword v3, v[0:1] -; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB0_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: v_mov_b32_e32 v3, v4 -; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB0_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f32_noret: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_load_dword v3, v[0:1] -; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB0_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: v_mov_b32_e32 v3, v4 -; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB0_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f32_noret: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_load_dword v3, v[0:1] -; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB0_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN3-NEXT: v_mov_b32_e32 v3, v4 -; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB0_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f32_noret: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -450,69 +391,6 @@ define void @global_atomic_xchg_f32_noret(ptr addrspace(1) %ptr, float %in) { } define void @global_atomic_xchg_f32_noret_offset(ptr addrspace(1) %out, float %in) { -; GCN1-LABEL: global_atomic_xchg_f32_noret_offset: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_add_f32_e32 v0, vcc, 16, v0 -; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc -; GCN1-NEXT: global_load_dword v3, v[0:1] -; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB1_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: v_mov_b32_e32 v3, v4 -; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB1_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f32_noret_offset: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_add_u32_e32 v0, vcc, 16, v0 -; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc -; GCN2-NEXT: global_load_dword v3, v[0:1] -; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB1_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: v_mov_b32_e32 v3, v4 -; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB1_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f32_noret_offset: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_load_dword v3, v[0:1] offset:16 -; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB1_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] offset:16 glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN3-NEXT: v_mov_b32_e32 v3, v4 -; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB1_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f32_noret_offset: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -549,71 +427,6 @@ define void @global_atomic_xchg_f32_noret_offset(ptr addrspace(1) %out, float %i } define float @global_atomic_xchg_f32_ret(ptr addrspace(1) %ptr, float %in) { -; GCN1-LABEL: global_atomic_xchg_f32_ret: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_load_dword v4, v[0:1] -; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB2_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v3, v4 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB2_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN1-NEXT: v_mov_b32_e32 v0, v4 -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f32_ret: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_load_dword v4, v[0:1] -; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB2_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v3, v4 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB2_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN2-NEXT: v_mov_b32_e32 v0, v4 -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f32_ret: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_load_dword v4, v[0:1] -; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB2_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v3, v4 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB2_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN3-NEXT: v_mov_b32_e32 v0, v4 -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f32_ret: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -648,73 +461,6 @@ define float @global_atomic_xchg_f32_ret(ptr addrspace(1) %ptr, float %in) { } define float @global_atomic_xchg_f32_ret_offset(ptr addrspace(1) %out, float %in) { -; GCN1-LABEL: global_atomic_xchg_f32_ret_offset: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_add_f32_e32 v4, vcc, 16, v0 -; GCN1-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc -; GCN1-NEXT: global_load_dword v0, v[4:5] -; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB3_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v3, v0 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[4:5], v[2:3] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 -; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB3_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f32_ret_offset: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_add_u32_e32 v4, vcc, 16, v0 -; GCN2-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc -; GCN2-NEXT: global_load_dword v0, v[4:5] -; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB3_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v3, v0 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[4:5], v[2:3] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 -; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB3_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f32_ret_offset: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_load_dword v4, v[0:1] offset:16 -; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB3_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v3, v4 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] offset:16 glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB3_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN3-NEXT: v_mov_b32_e32 v0, v4 -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f32_ret_offset: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -752,80 +498,6 @@ define float @global_atomic_xchg_f32_ret_offset(ptr addrspace(1) %out, float %in } define amdgpu_gfx void @global_atomic_xchg_f32_noret_scalar(ptr addrspace(1) inreg %ptr, float inreg %in) { -; GCN1-LABEL: global_atomic_xchg_f32_noret_scalar: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v0, s4 -; GCN1-NEXT: v_mov_b32_e32 v1, s5 -; GCN1-NEXT: global_load_dword v1, v[0:1] -; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB4_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: v_mov_b32_e32 v2, s4 -; GCN1-NEXT: v_mov_b32_e32 v0, s6 -; GCN1-NEXT: v_mov_b32_e32 v3, s5 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN1-NEXT: v_mov_b32_e32 v1, v0 -; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB4_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f32_noret_scalar: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v0, s4 -; GCN2-NEXT: v_mov_b32_e32 v1, s5 -; GCN2-NEXT: global_load_dword v1, v[0:1] -; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB4_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: v_mov_b32_e32 v2, s4 -; GCN2-NEXT: v_mov_b32_e32 v0, s6 -; GCN2-NEXT: v_mov_b32_e32 v3, s5 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN2-NEXT: v_mov_b32_e32 v1, v0 -; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB4_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f32_noret_scalar: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v0, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s5 -; GCN3-NEXT: global_load_dword v1, v[0:1] -; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB4_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: v_mov_b32_e32 v2, s4 -; GCN3-NEXT: v_mov_b32_e32 v0, s6 -; GCN3-NEXT: v_mov_b32_e32 v3, s5 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN3-NEXT: v_mov_b32_e32 v1, v0 -; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB4_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f32_noret_scalar: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -876,84 +548,6 @@ define amdgpu_gfx void @global_atomic_xchg_f32_noret_scalar(ptr addrspace(1) inr } define amdgpu_gfx void @global_atomic_xchg_f32_noret_offset_scalar(ptr addrspace(1) inreg %out, float inreg %in) { -; GCN1-LABEL: global_atomic_xchg_f32_noret_offset_scalar: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: s_add_u32 s34, s4, 16 -; GCN1-NEXT: s_addc_u32 s35, s5, 0 -; GCN1-NEXT: v_mov_b32_e32 v0, s34 -; GCN1-NEXT: v_mov_b32_e32 v1, s35 -; GCN1-NEXT: global_load_dword v1, v[0:1] -; GCN1-NEXT: s_mov_b64 s[36:37], 0 -; GCN1-NEXT: .LBB5_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: v_mov_b32_e32 v2, s34 -; GCN1-NEXT: v_mov_b32_e32 v0, s6 -; GCN1-NEXT: v_mov_b32_e32 v3, s35 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN1-NEXT: s_or_b64 s[36:37], vcc, s[36:37] -; GCN1-NEXT: v_mov_b32_e32 v1, v0 -; GCN1-NEXT: s_andn2_b64 exec, exec, s[36:37] -; GCN1-NEXT: s_cbranch_execnz .LBB5_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[36:37] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f32_noret_offset_scalar: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: s_add_u32 s34, s4, 16 -; GCN2-NEXT: s_addc_u32 s35, s5, 0 -; GCN2-NEXT: v_mov_b32_e32 v0, s34 -; GCN2-NEXT: v_mov_b32_e32 v1, s35 -; GCN2-NEXT: global_load_dword v1, v[0:1] -; GCN2-NEXT: s_mov_b64 s[36:37], 0 -; GCN2-NEXT: .LBB5_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: v_mov_b32_e32 v2, s34 -; GCN2-NEXT: v_mov_b32_e32 v0, s6 -; GCN2-NEXT: v_mov_b32_e32 v3, s35 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN2-NEXT: s_or_b64 s[36:37], vcc, s[36:37] -; GCN2-NEXT: v_mov_b32_e32 v1, v0 -; GCN2-NEXT: s_andn2_b64 exec, exec, s[36:37] -; GCN2-NEXT: s_cbranch_execnz .LBB5_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[36:37] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f32_noret_offset_scalar: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v0, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s5 -; GCN3-NEXT: global_load_dword v1, v[0:1] offset:16 -; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB5_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: v_mov_b32_e32 v2, s4 -; GCN3-NEXT: v_mov_b32_e32 v0, s6 -; GCN3-NEXT: v_mov_b32_e32 v3, s5 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] offset:16 glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN3-NEXT: v_mov_b32_e32 v1, v0 -; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB5_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f32_noret_offset_scalar: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -1007,83 +601,6 @@ define amdgpu_gfx void @global_atomic_xchg_f32_noret_offset_scalar(ptr addrspace } define amdgpu_gfx float @global_atomic_xchg_f32_ret_scalar(ptr addrspace(1) inreg %ptr, float inreg %in) { -; GCN1-LABEL: global_atomic_xchg_f32_ret_scalar: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v0, s4 -; GCN1-NEXT: v_mov_b32_e32 v1, s5 -; GCN1-NEXT: global_load_dword v0, v[0:1] -; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB6_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: v_mov_b32_e32 v3, s4 -; GCN1-NEXT: v_mov_b32_e32 v1, s6 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v2, v0 -; GCN1-NEXT: v_mov_b32_e32 v4, s5 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB6_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f32_ret_scalar: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v0, s4 -; GCN2-NEXT: v_mov_b32_e32 v1, s5 -; GCN2-NEXT: global_load_dword v0, v[0:1] -; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB6_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: v_mov_b32_e32 v3, s4 -; GCN2-NEXT: v_mov_b32_e32 v1, s6 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v2, v0 -; GCN2-NEXT: v_mov_b32_e32 v4, s5 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB6_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f32_ret_scalar: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v0, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s5 -; GCN3-NEXT: global_load_dword v0, v[0:1] -; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB6_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: v_mov_b32_e32 v3, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s6 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v2, v0 -; GCN3-NEXT: v_mov_b32_e32 v4, s5 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB6_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f32_ret_scalar: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -1134,87 +651,6 @@ define amdgpu_gfx float @global_atomic_xchg_f32_ret_scalar(ptr addrspace(1) inre } define amdgpu_gfx float @global_atomic_xchg_f32_ret_offset_scalar(ptr addrspace(1) inreg %out, float inreg %in) { -; GCN1-LABEL: global_atomic_xchg_f32_ret_offset_scalar: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: s_add_u32 s34, s4, 16 -; GCN1-NEXT: s_addc_u32 s35, s5, 0 -; GCN1-NEXT: v_mov_b32_e32 v0, s34 -; GCN1-NEXT: v_mov_b32_e32 v1, s35 -; GCN1-NEXT: global_load_dword v0, v[0:1] -; GCN1-NEXT: s_mov_b64 s[36:37], 0 -; GCN1-NEXT: .LBB7_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: v_mov_b32_e32 v3, s34 -; GCN1-NEXT: v_mov_b32_e32 v1, s6 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v2, v0 -; GCN1-NEXT: v_mov_b32_e32 v4, s35 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN1-NEXT: s_or_b64 s[36:37], vcc, s[36:37] -; GCN1-NEXT: s_andn2_b64 exec, exec, s[36:37] -; GCN1-NEXT: s_cbranch_execnz .LBB7_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[36:37] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f32_ret_offset_scalar: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: s_add_u32 s34, s4, 16 -; GCN2-NEXT: s_addc_u32 s35, s5, 0 -; GCN2-NEXT: v_mov_b32_e32 v0, s34 -; GCN2-NEXT: v_mov_b32_e32 v1, s35 -; GCN2-NEXT: global_load_dword v0, v[0:1] -; GCN2-NEXT: s_mov_b64 s[36:37], 0 -; GCN2-NEXT: .LBB7_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: v_mov_b32_e32 v3, s34 -; GCN2-NEXT: v_mov_b32_e32 v1, s6 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v2, v0 -; GCN2-NEXT: v_mov_b32_e32 v4, s35 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN2-NEXT: s_or_b64 s[36:37], vcc, s[36:37] -; GCN2-NEXT: s_andn2_b64 exec, exec, s[36:37] -; GCN2-NEXT: s_cbranch_execnz .LBB7_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[36:37] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f32_ret_offset_scalar: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v0, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s5 -; GCN3-NEXT: global_load_dword v0, v[0:1] offset:16 -; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB7_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: v_mov_b32_e32 v3, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s6 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v2, v0 -; GCN3-NEXT: v_mov_b32_e32 v4, s5 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] offset:16 glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB7_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f32_ret_offset_scalar: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) diff --git a/llvm/test/CodeGen/AMDGPU/global_atomics_i64_system.ll b/llvm/test/CodeGen/AMDGPU/global_atomics_i64_system.ll index d137f471910dc6a51c3faedcd869c372ee19d343..380ce7f3b939880e90bd6ba46819b1eee26f467d 100644 --- a/llvm/test/CodeGen/AMDGPU/global_atomics_i64_system.ll +++ b/llvm/test/CodeGen/AMDGPU/global_atomics_i64_system.ll @@ -372,65 +372,6 @@ define amdgpu_gfx i64 @global_atomic_xchg_i64_ret_offset_scalar(ptr addrspace(1) ; --------------------------------------------------------------------- define void @global_atomic_xchg_f64_noret(ptr addrspace(1) %ptr, double %in) { -; GCN1-LABEL: global_atomic_xchg_f64_noret: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_load_dword v3, v[0:1] -; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB0_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: v_mov_b32_e32 v3, v4 -; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB0_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f64_noret: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_load_dword v3, v[0:1] -; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB0_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: v_mov_b32_e32 v3, v4 -; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB0_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f64_noret: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_load_dword v3, v[0:1] -; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB0_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN3-NEXT: v_mov_b32_e32 v3, v4 -; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB0_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f64_noret: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -464,69 +405,6 @@ define void @global_atomic_xchg_f64_noret(ptr addrspace(1) %ptr, double %in) { } define void @global_atomic_xchg_f64_noret_offset(ptr addrspace(1) %out, double %in) { -; GCN1-LABEL: global_atomic_xchg_f64_noret_offset: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_add_f64_e32 v0, vcc, 16, v0 -; GCN1-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc -; GCN1-NEXT: global_load_dword v3, v[0:1] -; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB1_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: v_mov_b32_e32 v3, v4 -; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB1_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f64_noret_offset: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_add_u32_e32 v0, vcc, 16, v0 -; GCN2-NEXT: v_addc_u32_e32 v1, vcc, 0, v1, vcc -; GCN2-NEXT: global_load_dword v3, v[0:1] -; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB1_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: v_mov_b32_e32 v3, v4 -; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB1_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f64_noret_offset: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_load_dword v3, v[0:1] offset:16 -; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB1_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] offset:16 glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN3-NEXT: v_mov_b32_e32 v3, v4 -; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB1_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f64_noret_offset: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -563,71 +441,6 @@ define void @global_atomic_xchg_f64_noret_offset(ptr addrspace(1) %out, double % } define double @global_atomic_xchg_f64_ret(ptr addrspace(1) %ptr, double %in) { -; GCN1-LABEL: global_atomic_xchg_f64_ret: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_load_dword v4, v[0:1] -; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB2_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v3, v4 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB2_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN1-NEXT: v_mov_b32_e32 v0, v4 -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f64_ret: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_load_dword v4, v[0:1] -; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB2_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v3, v4 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB2_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN2-NEXT: v_mov_b32_e32 v0, v4 -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f64_ret: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_load_dword v4, v[0:1] -; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB2_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v3, v4 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB2_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN3-NEXT: v_mov_b32_e32 v0, v4 -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f64_ret: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -663,73 +476,6 @@ define double @global_atomic_xchg_f64_ret(ptr addrspace(1) %ptr, double %in) { } define double @global_atomic_xchg_f64_ret_offset(ptr addrspace(1) %out, double %in) { -; GCN1-LABEL: global_atomic_xchg_f64_ret_offset: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_add_f64_e32 v4, vcc, 16, v0 -; GCN1-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc -; GCN1-NEXT: global_load_dword v0, v[4:5] -; GCN1-NEXT: s_mov_b64 s[4:5], 0 -; GCN1-NEXT: .LBB3_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v3, v0 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[4:5], v[2:3] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 -; GCN1-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN1-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_cbranch_execnz .LBB3_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f64_ret_offset: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_add_u32_e32 v4, vcc, 16, v0 -; GCN2-NEXT: v_addc_u32_e32 v5, vcc, 0, v1, vcc -; GCN2-NEXT: global_load_dword v0, v[4:5] -; GCN2-NEXT: s_mov_b64 s[4:5], 0 -; GCN2-NEXT: .LBB3_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v3, v0 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[4:5], v[2:3] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v3 -; GCN2-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN2-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_cbranch_execnz .LBB3_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f64_ret_offset: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_load_dword v4, v[0:1] offset:16 -; GCN3-NEXT: s_mov_b64 s[4:5], 0 -; GCN3-NEXT: .LBB3_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v3, v4 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v4, v[0:1], v[2:3] offset:16 glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v4, v3 -; GCN3-NEXT: s_or_b64 s[4:5], vcc, s[4:5] -; GCN3-NEXT: s_andn2_b64 exec, exec, s[4:5] -; GCN3-NEXT: s_cbranch_execnz .LBB3_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[4:5] -; GCN3-NEXT: v_mov_b32_e32 v0, v4 -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f64_ret_offset: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -768,80 +514,6 @@ define double @global_atomic_xchg_f64_ret_offset(ptr addrspace(1) %out, double % } define amdgpu_gfx void @global_atomic_xchg_f64_noret_scalar(ptr addrspace(1) inreg %ptr, double inreg %in) { -; GCN1-LABEL: global_atomic_xchg_f64_noret_scalar: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v0, s4 -; GCN1-NEXT: v_mov_b32_e32 v1, s5 -; GCN1-NEXT: global_load_dword v1, v[0:1] -; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB4_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: v_mov_b32_e32 v2, s4 -; GCN1-NEXT: v_mov_b32_e32 v0, s6 -; GCN1-NEXT: v_mov_b32_e32 v3, s5 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN1-NEXT: v_mov_b32_e32 v1, v0 -; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB4_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f64_noret_scalar: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v0, s4 -; GCN2-NEXT: v_mov_b32_e32 v1, s5 -; GCN2-NEXT: global_load_dword v1, v[0:1] -; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB4_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: v_mov_b32_e32 v2, s4 -; GCN2-NEXT: v_mov_b32_e32 v0, s6 -; GCN2-NEXT: v_mov_b32_e32 v3, s5 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN2-NEXT: v_mov_b32_e32 v1, v0 -; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB4_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f64_noret_scalar: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v0, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s5 -; GCN3-NEXT: global_load_dword v1, v[0:1] -; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB4_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: v_mov_b32_e32 v2, s4 -; GCN3-NEXT: v_mov_b32_e32 v0, s6 -; GCN3-NEXT: v_mov_b32_e32 v3, s5 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN3-NEXT: v_mov_b32_e32 v1, v0 -; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB4_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f64_noret_scalar: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -896,84 +568,6 @@ define amdgpu_gfx void @global_atomic_xchg_f64_noret_scalar(ptr addrspace(1) inr } define amdgpu_gfx void @global_atomic_xchg_f64_noret_offset_scalar(ptr addrspace(1) inreg %out, double inreg %in) { -; GCN1-LABEL: global_atomic_xchg_f64_noret_offset_scalar: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: s_add_u32 s34, s4, 16 -; GCN1-NEXT: s_addc_u32 s35, s5, 0 -; GCN1-NEXT: v_mov_b32_e32 v0, s34 -; GCN1-NEXT: v_mov_b32_e32 v1, s35 -; GCN1-NEXT: global_load_dword v1, v[0:1] -; GCN1-NEXT: s_mov_b64 s[36:37], 0 -; GCN1-NEXT: .LBB5_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: v_mov_b32_e32 v2, s34 -; GCN1-NEXT: v_mov_b32_e32 v0, s6 -; GCN1-NEXT: v_mov_b32_e32 v3, s35 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN1-NEXT: s_or_b64 s[36:37], vcc, s[36:37] -; GCN1-NEXT: v_mov_b32_e32 v1, v0 -; GCN1-NEXT: s_andn2_b64 exec, exec, s[36:37] -; GCN1-NEXT: s_cbranch_execnz .LBB5_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[36:37] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f64_noret_offset_scalar: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: s_add_u32 s34, s4, 16 -; GCN2-NEXT: s_addc_u32 s35, s5, 0 -; GCN2-NEXT: v_mov_b32_e32 v0, s34 -; GCN2-NEXT: v_mov_b32_e32 v1, s35 -; GCN2-NEXT: global_load_dword v1, v[0:1] -; GCN2-NEXT: s_mov_b64 s[36:37], 0 -; GCN2-NEXT: .LBB5_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: v_mov_b32_e32 v2, s34 -; GCN2-NEXT: v_mov_b32_e32 v0, s6 -; GCN2-NEXT: v_mov_b32_e32 v3, s35 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN2-NEXT: s_or_b64 s[36:37], vcc, s[36:37] -; GCN2-NEXT: v_mov_b32_e32 v1, v0 -; GCN2-NEXT: s_andn2_b64 exec, exec, s[36:37] -; GCN2-NEXT: s_cbranch_execnz .LBB5_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[36:37] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f64_noret_offset_scalar: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v0, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s5 -; GCN3-NEXT: global_load_dword v1, v[0:1] offset:16 -; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB5_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: v_mov_b32_e32 v2, s4 -; GCN3-NEXT: v_mov_b32_e32 v0, s6 -; GCN3-NEXT: v_mov_b32_e32 v3, s5 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v0, v[2:3], v[0:1] offset:16 glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v1 -; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN3-NEXT: v_mov_b32_e32 v1, v0 -; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB5_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f64_noret_offset_scalar: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -1029,83 +623,6 @@ define amdgpu_gfx void @global_atomic_xchg_f64_noret_offset_scalar(ptr addrspace } define amdgpu_gfx double @global_atomic_xchg_f64_ret_scalar(ptr addrspace(1) inreg %ptr, double inreg %in) { -; GCN1-LABEL: global_atomic_xchg_f64_ret_scalar: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v0, s4 -; GCN1-NEXT: v_mov_b32_e32 v1, s5 -; GCN1-NEXT: global_load_dword v0, v[0:1] -; GCN1-NEXT: s_mov_b64 s[34:35], 0 -; GCN1-NEXT: .LBB6_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: v_mov_b32_e32 v3, s4 -; GCN1-NEXT: v_mov_b32_e32 v1, s6 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v2, v0 -; GCN1-NEXT: v_mov_b32_e32 v4, s5 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN1-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN1-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_cbranch_execnz .LBB6_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f64_ret_scalar: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v0, s4 -; GCN2-NEXT: v_mov_b32_e32 v1, s5 -; GCN2-NEXT: global_load_dword v0, v[0:1] -; GCN2-NEXT: s_mov_b64 s[34:35], 0 -; GCN2-NEXT: .LBB6_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: v_mov_b32_e32 v3, s4 -; GCN2-NEXT: v_mov_b32_e32 v1, s6 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v2, v0 -; GCN2-NEXT: v_mov_b32_e32 v4, s5 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN2-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN2-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_cbranch_execnz .LBB6_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f64_ret_scalar: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v0, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s5 -; GCN3-NEXT: global_load_dword v0, v[0:1] -; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB6_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: v_mov_b32_e32 v3, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s6 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v2, v0 -; GCN3-NEXT: v_mov_b32_e32 v4, s5 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB6_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f64_ret_scalar: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) @@ -1160,87 +677,6 @@ define amdgpu_gfx double @global_atomic_xchg_f64_ret_scalar(ptr addrspace(1) inr } define amdgpu_gfx double @global_atomic_xchg_f64_ret_offset_scalar(ptr addrspace(1) inreg %out, double inreg %in) { -; GCN1-LABEL: global_atomic_xchg_f64_ret_offset_scalar: -; GCN1: ; %bb.0: -; GCN1-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN1-NEXT: s_add_u32 s34, s4, 16 -; GCN1-NEXT: s_addc_u32 s35, s5, 0 -; GCN1-NEXT: v_mov_b32_e32 v0, s34 -; GCN1-NEXT: v_mov_b32_e32 v1, s35 -; GCN1-NEXT: global_load_dword v0, v[0:1] -; GCN1-NEXT: s_mov_b64 s[36:37], 0 -; GCN1-NEXT: .LBB7_1: ; %atomicrmw.start -; GCN1-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN1-NEXT: v_mov_b32_e32 v3, s34 -; GCN1-NEXT: v_mov_b32_e32 v1, s6 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: v_mov_b32_e32 v2, v0 -; GCN1-NEXT: v_mov_b32_e32 v4, s35 -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN1-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN1-NEXT: buffer_wbinvl1_vol -; GCN1-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN1-NEXT: s_or_b64 s[36:37], vcc, s[36:37] -; GCN1-NEXT: s_andn2_b64 exec, exec, s[36:37] -; GCN1-NEXT: s_cbranch_execnz .LBB7_1 -; GCN1-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN1-NEXT: s_or_b64 exec, exec, s[36:37] -; GCN1-NEXT: s_setpc_b64 s[30:31] -; -; GCN2-LABEL: global_atomic_xchg_f64_ret_offset_scalar: -; GCN2: ; %bb.0: -; GCN2-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN2-NEXT: s_add_u32 s34, s4, 16 -; GCN2-NEXT: s_addc_u32 s35, s5, 0 -; GCN2-NEXT: v_mov_b32_e32 v0, s34 -; GCN2-NEXT: v_mov_b32_e32 v1, s35 -; GCN2-NEXT: global_load_dword v0, v[0:1] -; GCN2-NEXT: s_mov_b64 s[36:37], 0 -; GCN2-NEXT: .LBB7_1: ; %atomicrmw.start -; GCN2-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN2-NEXT: v_mov_b32_e32 v3, s34 -; GCN2-NEXT: v_mov_b32_e32 v1, s6 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: v_mov_b32_e32 v2, v0 -; GCN2-NEXT: v_mov_b32_e32 v4, s35 -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] glc -; GCN2-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN2-NEXT: buffer_wbinvl1_vol -; GCN2-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN2-NEXT: s_or_b64 s[36:37], vcc, s[36:37] -; GCN2-NEXT: s_andn2_b64 exec, exec, s[36:37] -; GCN2-NEXT: s_cbranch_execnz .LBB7_1 -; GCN2-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN2-NEXT: s_or_b64 exec, exec, s[36:37] -; GCN2-NEXT: s_setpc_b64 s[30:31] -; -; GCN3-LABEL: global_atomic_xchg_f64_ret_offset_scalar: -; GCN3: ; %bb.0: -; GCN3-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v0, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s5 -; GCN3-NEXT: global_load_dword v0, v[0:1] offset:16 -; GCN3-NEXT: s_mov_b64 s[34:35], 0 -; GCN3-NEXT: .LBB7_1: ; %atomicrmw.start -; GCN3-NEXT: ; =>This Inner Loop Header: Depth=1 -; GCN3-NEXT: v_mov_b32_e32 v3, s4 -; GCN3-NEXT: v_mov_b32_e32 v1, s6 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: v_mov_b32_e32 v2, v0 -; GCN3-NEXT: v_mov_b32_e32 v4, s5 -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: global_atomic_cmpswap v0, v[3:4], v[1:2] offset:16 glc -; GCN3-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) -; GCN3-NEXT: buffer_wbinvl1_vol -; GCN3-NEXT: v_cmp_eq_u32_e32 vcc, v0, v2 -; GCN3-NEXT: s_or_b64 s[34:35], vcc, s[34:35] -; GCN3-NEXT: s_andn2_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_cbranch_execnz .LBB7_1 -; GCN3-NEXT: ; %bb.2: ; %atomicrmw.end -; GCN3-NEXT: s_or_b64 exec, exec, s[34:35] -; GCN3-NEXT: s_setpc_b64 s[30:31] ; SI-LABEL: global_atomic_xchg_f64_ret_offset_scalar: ; SI: ; %bb.0: ; SI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) diff --git a/llvm/test/CodeGen/AMDGPU/global_atomics_iterative_scan_fp.ll b/llvm/test/CodeGen/AMDGPU/global_atomics_iterative_scan_fp.ll index fab24e10f810ff21f419f50455ccd3e6b10bb1fe..86e3d9338e07803e7dd0d204f4e6f9ba848bb78a 100644 --- a/llvm/test/CodeGen/AMDGPU/global_atomics_iterative_scan_fp.ll +++ b/llvm/test/CodeGen/AMDGPU/global_atomics_iterative_scan_fp.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -mtriple=amdgcn-- -amdgpu-atomic-optimizer-strategy=Iterative -passes='amdgpu-atomic-optimizer,verify<domtree>' %s | FileCheck -check-prefix=IR-ITERATIVE %s -; RUN: opt -S -mtriple=amdgcn-- -amdgpu-atomic-optimizer-strategy=DPP -passes='amdgpu-atomic-optimizer,verify<domtree>' %s | FileCheck -check-prefix=IR-DPP %s +; RUN: opt -S -mtriple=amdgcn-- -passes='amdgpu-atomic-optimizer<strategy=iterative>,verify<domtree>' %s | FileCheck -check-prefix=IR-ITERATIVE %s +; RUN: opt -S -mtriple=amdgcn-- -passes='amdgpu-atomic-optimizer<strategy=dpp>,verify<domtree>' %s | FileCheck -check-prefix=IR-DPP %s declare i32 @llvm.amdgcn.workitem.id.x() define amdgpu_kernel void @global_atomic_fadd_uni_value(ptr addrspace(1) %ptr) #0 { ; IR-ITERATIVE-LABEL: @global_atomic_fadd_uni_value( diff --git a/llvm/test/CodeGen/AMDGPU/global_atomics_optimizer_fp_no_rtn.ll b/llvm/test/CodeGen/AMDGPU/global_atomics_optimizer_fp_no_rtn.ll index f87932b9361ed9cdc21ab31ae877e295cfa6786f..b9234f47df19281c7060f2541895850243609aa2 100644 --- a/llvm/test/CodeGen/AMDGPU/global_atomics_optimizer_fp_no_rtn.ll +++ b/llvm/test/CodeGen/AMDGPU/global_atomics_optimizer_fp_no_rtn.ll @@ -1,55 +1,35 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -mtriple=amdgcn-- -mcpu=gfx906 -amdgpu-atomic-optimizer-strategy=Iterative -passes='amdgpu-atomic-optimizer,verify<domtree>' %s | FileCheck -check-prefix=IR-ITERATIVE %s -; RUN: opt -S -mtriple=amdgcn-- -mcpu=gfx906 -amdgpu-atomic-optimizer-strategy=DPP -passes='amdgpu-atomic-optimizer,verify<domtree>' %s | FileCheck -check-prefix=IR-DPP %s +; RUN: opt -S -mtriple=amdgcn-- -mcpu=gfx906 -passes='amdgpu-atomic-optimizer<strategy=iterative>,verify<domtree>' %s | FileCheck --check-prefixes=IR,IR-ITERATIVE %s +; RUN: opt -S -mtriple=amdgcn-- -mcpu=gfx906 -passes='amdgpu-atomic-optimizer<strategy=dpp>,verify<domtree>' %s | FileCheck --check-prefixes=IR,IR-DPP %s + +; Tests various combinations of uniform/divergent address and uniform/divergent value inputs of various types for atomic operations. +; Optimization remains same for Iterative and DPP strategies when value in uniform. These different scan/reduction +; strategies are valid for only divergent values. This optimization is valid for divergent addresses. Test also covers different scopes. define amdgpu_ps void @global_atomic_fadd_uni_address_uni_value_agent_scope_unsafe(ptr addrspace(1) inreg %ptr, float inreg %val) #0 { -; IR-ITERATIVE-LABEL: @global_atomic_fadd_uni_address_uni_value_agent_scope_unsafe( -; IR-ITERATIVE-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() -; IR-ITERATIVE-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP17:%.*]] -; IR-ITERATIVE: 2: -; IR-ITERATIVE-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) -; IR-ITERATIVE-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 -; IR-ITERATIVE-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 -; IR-ITERATIVE-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 -; IR-ITERATIVE-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) -; IR-ITERATIVE-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) -; IR-ITERATIVE-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) -; IR-ITERATIVE-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 -; IR-ITERATIVE-NEXT: [[TMP11:%.*]] = uitofp i32 [[TMP10]] to float -; IR-ITERATIVE-NEXT: [[TMP12:%.*]] = fmul float [[VAL:%.*]], [[TMP11]] -; IR-ITERATIVE-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 -; IR-ITERATIVE-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] -; IR-ITERATIVE: 14: -; IR-ITERATIVE-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[TMP12]] syncscope("agent") monotonic, align 4 -; IR-ITERATIVE-NEXT: br label [[TMP16]] -; IR-ITERATIVE: 16: -; IR-ITERATIVE-NEXT: br label [[TMP17]] -; IR-ITERATIVE: 17: -; IR-ITERATIVE-NEXT: ret void -; -; IR-DPP-LABEL: @global_atomic_fadd_uni_address_uni_value_agent_scope_unsafe( -; IR-DPP-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() -; IR-DPP-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP17:%.*]] -; IR-DPP: 2: -; IR-DPP-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) -; IR-DPP-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 -; IR-DPP-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 -; IR-DPP-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 -; IR-DPP-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) -; IR-DPP-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) -; IR-DPP-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) -; IR-DPP-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 -; IR-DPP-NEXT: [[TMP11:%.*]] = uitofp i32 [[TMP10]] to float -; IR-DPP-NEXT: [[TMP12:%.*]] = fmul float [[VAL:%.*]], [[TMP11]] -; IR-DPP-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 -; IR-DPP-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] -; IR-DPP: 14: -; IR-DPP-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[TMP12]] syncscope("agent") monotonic, align 4 -; IR-DPP-NEXT: br label [[TMP16]] -; IR-DPP: 16: -; IR-DPP-NEXT: br label [[TMP17]] -; IR-DPP: 17: -; IR-DPP-NEXT: ret void +; IR-LABEL: @global_atomic_fadd_uni_address_uni_value_agent_scope_unsafe( +; IR-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() +; IR-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP17:%.*]] +; IR: 2: +; IR-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) +; IR-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) +; IR-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) +; IR-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) +; IR-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 +; IR-NEXT: [[TMP11:%.*]] = uitofp i32 [[TMP10]] to float +; IR-NEXT: [[TMP12:%.*]] = fmul float [[VAL:%.*]], [[TMP11]] +; IR-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] +; IR: 14: +; IR-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[TMP12]] syncscope("agent") monotonic, align 4 +; IR-NEXT: br label [[TMP16]] +; IR: 16: +; IR-NEXT: br label [[TMP17]] +; IR: 17: +; IR-NEXT: ret void ; %result = atomicrmw fadd ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic, align 4 ret void @@ -325,7 +305,6 @@ define amdgpu_ps void @global_atomic_fsub_uni_address_uni_value_agent_scope_stri ret void } - define amdgpu_ps void @global_atomic_fsub_uni_address_div_value_agent_scope_strictfp(ptr addrspace(1) inreg %ptr, float %val) #2 { ; IR-ITERATIVE-LABEL: @global_atomic_fsub_uni_address_div_value_agent_scope_strictfp( ; IR-ITERATIVE-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() #[[ATTR7]] @@ -409,45 +388,25 @@ define amdgpu_ps void @global_atomic_fsub_uni_address_div_value_agent_scope_stri } define amdgpu_ps void @global_atomic_fmin_uni_address_uni_value_agent_scope_unsafe(ptr addrspace(1) inreg %ptr, float inreg %val) #0 { -; IR-ITERATIVE-LABEL: @global_atomic_fmin_uni_address_uni_value_agent_scope_unsafe( -; IR-ITERATIVE-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() -; IR-ITERATIVE-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP13:%.*]] -; IR-ITERATIVE: 2: -; IR-ITERATIVE-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) -; IR-ITERATIVE-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 -; IR-ITERATIVE-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 -; IR-ITERATIVE-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 -; IR-ITERATIVE-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) -; IR-ITERATIVE-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) -; IR-ITERATIVE-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0 -; IR-ITERATIVE-NEXT: br i1 [[TMP9]], label [[TMP10:%.*]], label [[TMP12:%.*]] -; IR-ITERATIVE: 10: -; IR-ITERATIVE-NEXT: [[TMP11:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-ITERATIVE-NEXT: br label [[TMP12]] -; IR-ITERATIVE: 12: -; IR-ITERATIVE-NEXT: br label [[TMP13]] -; IR-ITERATIVE: 13: -; IR-ITERATIVE-NEXT: ret void -; -; IR-DPP-LABEL: @global_atomic_fmin_uni_address_uni_value_agent_scope_unsafe( -; IR-DPP-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() -; IR-DPP-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP13:%.*]] -; IR-DPP: 2: -; IR-DPP-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) -; IR-DPP-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 -; IR-DPP-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 -; IR-DPP-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 -; IR-DPP-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) -; IR-DPP-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) -; IR-DPP-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0 -; IR-DPP-NEXT: br i1 [[TMP9]], label [[TMP10:%.*]], label [[TMP12:%.*]] -; IR-DPP: 10: -; IR-DPP-NEXT: [[TMP11:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-DPP-NEXT: br label [[TMP12]] -; IR-DPP: 12: -; IR-DPP-NEXT: br label [[TMP13]] -; IR-DPP: 13: -; IR-DPP-NEXT: ret void +; IR-LABEL: @global_atomic_fmin_uni_address_uni_value_agent_scope_unsafe( +; IR-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() +; IR-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP13:%.*]] +; IR: 2: +; IR-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) +; IR-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) +; IR-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) +; IR-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-NEXT: br i1 [[TMP9]], label [[TMP10:%.*]], label [[TMP12:%.*]] +; IR: 10: +; IR-NEXT: [[TMP11:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: br label [[TMP12]] +; IR: 12: +; IR-NEXT: br label [[TMP13]] +; IR: 13: +; IR-NEXT: ret void ; %result = atomicrmw fmin ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic ret void @@ -797,161 +756,531 @@ define amdgpu_ps void @global_atomic_fadd_uni_address_div_value_system_scope_str ret void } - define amdgpu_ps void @global_atomic_fadd_div_address_uni_value_agent_scope_unsafe(ptr addrspace(1) %ptr, float inreg %val) #0 { -; IR-ITERATIVE-LABEL: @global_atomic_fadd_div_address_uni_value_agent_scope_unsafe( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-ITERATIVE-NEXT: ret void -; -; IR-DPP-LABEL: @global_atomic_fadd_div_address_uni_value_agent_scope_unsafe( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-DPP-NEXT: ret void +; IR-LABEL: @global_atomic_fadd_div_address_uni_value_agent_scope_unsafe( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret void ; %result = atomicrmw fadd ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic, align 4 ret void } define amdgpu_ps void @global_atomic_fadd_div_address_div_value_agent_scope_unsafe(ptr addrspace(1) %ptr, float %val) #0 { -; IR-ITERATIVE-LABEL: @global_atomic_fadd_div_address_div_value_agent_scope_unsafe( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-ITERATIVE-NEXT: ret void -; -; IR-DPP-LABEL: @global_atomic_fadd_div_address_div_value_agent_scope_unsafe( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-DPP-NEXT: ret void +; IR-LABEL: @global_atomic_fadd_div_address_div_value_agent_scope_unsafe( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret void ; %result = atomicrmw fadd ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic, align 4 ret void } define amdgpu_ps void @global_atomic_fadd_div_address_uni_value_one_as_scope_unsafe_structfp(ptr addrspace(1) %ptr, float inreg %val) #1 { -; IR-ITERATIVE-LABEL: @global_atomic_fadd_div_address_uni_value_one_as_scope_unsafe_structfp( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("one-as") monotonic, align 4 -; IR-ITERATIVE-NEXT: ret void -; -; IR-DPP-LABEL: @global_atomic_fadd_div_address_uni_value_one_as_scope_unsafe_structfp( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("one-as") monotonic, align 4 -; IR-DPP-NEXT: ret void +; IR-LABEL: @global_atomic_fadd_div_address_uni_value_one_as_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("one-as") monotonic, align 4 +; IR-NEXT: ret void ; %result = atomicrmw fadd ptr addrspace(1) %ptr, float %val syncscope("one-as") monotonic ret void } define amdgpu_ps void @global_atomic_fadd_div_address_div_value_one_as_scope_unsafe_structfp(ptr addrspace(1) %ptr, float %val) #1 { -; IR-ITERATIVE-LABEL: @global_atomic_fadd_div_address_div_value_one_as_scope_unsafe_structfp( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("one-as") monotonic, align 4 -; IR-ITERATIVE-NEXT: ret void -; -; IR-DPP-LABEL: @global_atomic_fadd_div_address_div_value_one_as_scope_unsafe_structfp( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("one-as") monotonic, align 4 -; IR-DPP-NEXT: ret void +; IR-LABEL: @global_atomic_fadd_div_address_div_value_one_as_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("one-as") monotonic, align 4 +; IR-NEXT: ret void ; %result = atomicrmw fadd ptr addrspace(1) %ptr, float %val syncscope("one-as") monotonic ret void } define amdgpu_ps void @global_atomic_fsub_div_address_uni_value_agent_scope_strictfp(ptr addrspace(1) %ptr, float inreg %val) #2 { -; IR-ITERATIVE-LABEL: @global_atomic_fsub_div_address_uni_value_agent_scope_strictfp( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-ITERATIVE-NEXT: ret void -; -; IR-DPP-LABEL: @global_atomic_fsub_div_address_uni_value_agent_scope_strictfp( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-DPP-NEXT: ret void +; IR-LABEL: @global_atomic_fsub_div_address_uni_value_agent_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret void ; %result = atomicrmw fadd ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic ret void } - define amdgpu_ps void @global_atomic_fsub_div_address_div_value_agent_scope_strictfp(ptr addrspace(1) %ptr, float %val) #2 { -; IR-ITERATIVE-LABEL: @global_atomic_fsub_div_address_div_value_agent_scope_strictfp( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fsub ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-ITERATIVE-NEXT: ret void -; -; IR-DPP-LABEL: @global_atomic_fsub_div_address_div_value_agent_scope_strictfp( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fsub ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-DPP-NEXT: ret void +; IR-LABEL: @global_atomic_fsub_div_address_div_value_agent_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fsub ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret void ; %result = atomicrmw fsub ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic ret void } define amdgpu_ps void @global_atomic_fmin_div_address_uni_value_agent_scope(ptr addrspace(1) %ptr, float inreg %val) #0 { -; IR-ITERATIVE-LABEL: @global_atomic_fmin_div_address_uni_value_agent_scope( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-ITERATIVE-NEXT: ret void -; -; IR-DPP-LABEL: @global_atomic_fmin_div_address_uni_value_agent_scope( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-DPP-NEXT: ret void +; IR-LABEL: @global_atomic_fmin_div_address_uni_value_agent_scope( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret void ; %result = atomicrmw fmin ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic ret void } define amdgpu_ps void @global_atomic_fmin_div_address_div_value_agent_scope(ptr addrspace(1) %ptr, float %val) #0 { -; IR-ITERATIVE-LABEL: @global_atomic_fmin_div_address_div_value_agent_scope( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-ITERATIVE-NEXT: ret void -; -; IR-DPP-LABEL: @global_atomic_fmin_div_address_div_value_agent_scope( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 -; IR-DPP-NEXT: ret void +; IR-LABEL: @global_atomic_fmin_div_address_div_value_agent_scope( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret void ; %result = atomicrmw fmin ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic ret void } define amdgpu_ps void @global_atomic_fmax_div_address_uni_value_agent_scope_unsafe_structfp(ptr addrspace(1) %ptr, float inreg %val) #1{ -; IR-ITERATIVE-LABEL: @global_atomic_fmax_div_address_uni_value_agent_scope_unsafe_structfp( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-LABEL: @global_atomic_fmax_div_address_uni_value_agent_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret void +; + %result = atomicrmw fmax ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic + ret void +} + +define amdgpu_ps void @global_atomic_fmax_div_address_div_value_agent_scope_unsafe_structfp(ptr addrspace(1) %ptr, float %val) #1{ +; IR-LABEL: @global_atomic_fmax_div_address_div_value_agent_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret void +; + %result = atomicrmw fmax ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic + ret void +} + +define amdgpu_ps void @global_atomic_fadd_div_address_uni_value_system_scope_strictfp(ptr addrspace(1) %ptr, float inreg %val) #2 { +; IR-LABEL: @global_atomic_fadd_div_address_uni_value_system_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] monotonic, align 4 +; IR-NEXT: ret void +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, float %val monotonic, align 4 + ret void +} + +define amdgpu_ps void @global_atomic_fadd_div_address_div_value_system_scope_strictfp(ptr addrspace(1) %ptr, float %val) #2 { +; IR-LABEL: @global_atomic_fadd_div_address_div_value_system_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] monotonic, align 4 +; IR-NEXT: ret void +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, float %val monotonic, align 4 + ret void +} + +define amdgpu_ps void @global_atomic_fadd_double_uni_address_uni_value_agent_scope_unsafe(ptr addrspace(1) inreg %ptr, double inreg %val) #0 { +; IR-LABEL: @global_atomic_fadd_double_uni_address_uni_value_agent_scope_unsafe( +; IR-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() +; IR-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP17:%.*]] +; IR: 2: +; IR-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) +; IR-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) +; IR-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) +; IR-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) +; IR-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 +; IR-NEXT: [[TMP11:%.*]] = uitofp i32 [[TMP10]] to double +; IR-NEXT: [[TMP12:%.*]] = fmul double [[VAL:%.*]], [[TMP11]] +; IR-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] +; IR: 14: +; IR-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[TMP12]] syncscope("agent") monotonic, align 4 +; IR-NEXT: br label [[TMP16]] +; IR: 16: +; IR-NEXT: br label [[TMP17]] +; IR: 17: +; IR-NEXT: ret void +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic, align 4 + ret void +} + +define amdgpu_ps void @global_atomic_fadd_double_uni_address_div_value_scope_agent_scope_unsafe(ptr addrspace(1) inreg %ptr, double %val) #0 { +; IR-LABEL: @global_atomic_fadd_double_uni_address_div_value_scope_agent_scope_unsafe( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret void +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic, align 4 + ret void +} + +define amdgpu_ps void @global_atomic_fadd_double_uni_address_uni_value_one_as_scope_unsafe_structfp(ptr addrspace(1) inreg %ptr, double inreg %val) #1 { +; IR-ITERATIVE-LABEL: @global_atomic_fadd_double_uni_address_uni_value_one_as_scope_unsafe_structfp( +; IR-ITERATIVE-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() #[[ATTR7]] +; IR-ITERATIVE-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP17:%.*]] +; IR-ITERATIVE: 2: +; IR-ITERATIVE-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-ITERATIVE-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-ITERATIVE-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-ITERATIVE-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 +; IR-ITERATIVE-NEXT: [[TMP11:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP10]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP12:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[VAL:%.*]], double [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-ITERATIVE-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] +; IR-ITERATIVE: 14: +; IR-ITERATIVE-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[TMP12]] syncscope("one-as") monotonic, align 8 +; IR-ITERATIVE-NEXT: br label [[TMP16]] +; IR-ITERATIVE: 16: +; IR-ITERATIVE-NEXT: br label [[TMP17]] +; IR-ITERATIVE: 17: ; IR-ITERATIVE-NEXT: ret void ; -; IR-DPP-LABEL: @global_atomic_fmax_div_address_uni_value_agent_scope_unsafe_structfp( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-DPP-LABEL: @global_atomic_fadd_double_uni_address_uni_value_one_as_scope_unsafe_structfp( +; IR-DPP-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() #[[ATTR8]] +; IR-DPP-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP17:%.*]] +; IR-DPP: 2: +; IR-DPP-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-DPP-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-DPP-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-DPP-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 +; IR-DPP-NEXT: [[TMP11:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP10]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP12:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[VAL:%.*]], double [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-DPP-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] +; IR-DPP: 14: +; IR-DPP-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[TMP12]] syncscope("one-as") monotonic, align 8 +; IR-DPP-NEXT: br label [[TMP16]] +; IR-DPP: 16: +; IR-DPP-NEXT: br label [[TMP17]] +; IR-DPP: 17: ; IR-DPP-NEXT: ret void ; - %result = atomicrmw fmax ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("one-as") monotonic ret void } -define amdgpu_ps void @global_atomic_fmax_div_address_div_value_agent_scope_unsafe_structfp(ptr addrspace(1) %ptr, float %val) #1{ -; IR-ITERATIVE-LABEL: @global_atomic_fmax_div_address_div_value_agent_scope_unsafe_structfp( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +define amdgpu_ps void @global_atomic_fadd_double_uni_address_div_value_one_as_scope_unsafe_structfp(ptr addrspace(1) inreg %ptr, double %val) #1 { +; IR-LABEL: @global_atomic_fadd_double_uni_address_div_value_one_as_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("one-as") monotonic, align 8 +; IR-NEXT: ret void +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("one-as") monotonic + ret void +} + +define amdgpu_ps void @global_atomic_fsub_double_uni_address_uni_value_agent_scope_strictfp(ptr addrspace(1) inreg %ptr, double inreg %val) #2 { +; IR-ITERATIVE-LABEL: @global_atomic_fsub_double_uni_address_uni_value_agent_scope_strictfp( +; IR-ITERATIVE-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() #[[ATTR7]] +; IR-ITERATIVE-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP17:%.*]] +; IR-ITERATIVE: 2: +; IR-ITERATIVE-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-ITERATIVE-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-ITERATIVE-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-ITERATIVE-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 +; IR-ITERATIVE-NEXT: [[TMP11:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP10]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP12:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[VAL:%.*]], double [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-ITERATIVE-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] +; IR-ITERATIVE: 14: +; IR-ITERATIVE-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[TMP12]] syncscope("agent") monotonic, align 8 +; IR-ITERATIVE-NEXT: br label [[TMP16]] +; IR-ITERATIVE: 16: +; IR-ITERATIVE-NEXT: br label [[TMP17]] +; IR-ITERATIVE: 17: ; IR-ITERATIVE-NEXT: ret void ; -; IR-DPP-LABEL: @global_atomic_fmax_div_address_div_value_agent_scope_unsafe_structfp( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-DPP-LABEL: @global_atomic_fsub_double_uni_address_uni_value_agent_scope_strictfp( +; IR-DPP-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() #[[ATTR8]] +; IR-DPP-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP17:%.*]] +; IR-DPP: 2: +; IR-DPP-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-DPP-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-DPP-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-DPP-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 +; IR-DPP-NEXT: [[TMP11:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP10]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP12:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[VAL:%.*]], double [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-DPP-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] +; IR-DPP: 14: +; IR-DPP-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[TMP12]] syncscope("agent") monotonic, align 8 +; IR-DPP-NEXT: br label [[TMP16]] +; IR-DPP: 16: +; IR-DPP-NEXT: br label [[TMP17]] +; IR-DPP: 17: ; IR-DPP-NEXT: ret void ; - %result = atomicrmw fmax ptr addrspace(1) %ptr, float %val syncscope("agent") monotonic + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic ret void } -define amdgpu_ps void @global_atomic_fadd_div_address_uni_value_system_scope_strictfp(ptr addrspace(1) %ptr, float inreg %val) #2 { -; IR-ITERATIVE-LABEL: @global_atomic_fadd_div_address_uni_value_system_scope_strictfp( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] monotonic, align 4 +define amdgpu_ps void @global_atomic_fsub_double_uni_address_div_value_agent_scope_strictfp(ptr addrspace(1) inreg %ptr, double %val) #2 { +; IR-LABEL: @global_atomic_fsub_double_uni_address_div_value_agent_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fsub ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: ret void +; + %result = atomicrmw fsub ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret void +} + +define amdgpu_ps void @global_atomic_fmin_double_uni_address_uni_value_agent_scope_unsafe(ptr addrspace(1) inreg %ptr, double inreg %val) #0 { +; IR-LABEL: @global_atomic_fmin_double_uni_address_uni_value_agent_scope_unsafe( +; IR-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() +; IR-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP13:%.*]] +; IR: 2: +; IR-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) +; IR-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) +; IR-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) +; IR-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-NEXT: br i1 [[TMP9]], label [[TMP10:%.*]], label [[TMP12:%.*]] +; IR: 10: +; IR-NEXT: [[TMP11:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: br label [[TMP12]] +; IR: 12: +; IR-NEXT: br label [[TMP13]] +; IR: 13: +; IR-NEXT: ret void +; + %result = atomicrmw fmin ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret void +} + +define amdgpu_ps void @global_atomic_fmin_double_uni_address_div_value_agent_scope_unsafe(ptr addrspace(1) inreg %ptr, double %val) #0 { +; IR-LABEL: @global_atomic_fmin_double_uni_address_div_value_agent_scope_unsafe( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: ret void +; + %result = atomicrmw fmin ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret void +} + +define amdgpu_ps void @global_atomic_fmax_double_uni_address_uni_value_agent_scope_unsafe_structfp(ptr addrspace(1) inreg %ptr, double inreg %val) #1{ +; IR-ITERATIVE-LABEL: @global_atomic_fmax_double_uni_address_uni_value_agent_scope_unsafe_structfp( +; IR-ITERATIVE-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() #[[ATTR7]] +; IR-ITERATIVE-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP13:%.*]] +; IR-ITERATIVE: 2: +; IR-ITERATIVE-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-ITERATIVE-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-ITERATIVE-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-ITERATIVE-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-ITERATIVE-NEXT: br i1 [[TMP9]], label [[TMP10:%.*]], label [[TMP12:%.*]] +; IR-ITERATIVE: 10: +; IR-ITERATIVE-NEXT: [[TMP11:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-ITERATIVE-NEXT: br label [[TMP12]] +; IR-ITERATIVE: 12: +; IR-ITERATIVE-NEXT: br label [[TMP13]] +; IR-ITERATIVE: 13: ; IR-ITERATIVE-NEXT: ret void ; -; IR-DPP-LABEL: @global_atomic_fadd_div_address_uni_value_system_scope_strictfp( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] monotonic, align 4 +; IR-DPP-LABEL: @global_atomic_fmax_double_uni_address_uni_value_agent_scope_unsafe_structfp( +; IR-DPP-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() #[[ATTR8]] +; IR-DPP-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP13:%.*]] +; IR-DPP: 2: +; IR-DPP-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-DPP-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-DPP-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-DPP-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-DPP-NEXT: br i1 [[TMP9]], label [[TMP10:%.*]], label [[TMP12:%.*]] +; IR-DPP: 10: +; IR-DPP-NEXT: [[TMP11:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-DPP-NEXT: br label [[TMP12]] +; IR-DPP: 12: +; IR-DPP-NEXT: br label [[TMP13]] +; IR-DPP: 13: ; IR-DPP-NEXT: ret void ; - %result = atomicrmw fadd ptr addrspace(1) %ptr, float %val monotonic, align 4 + %result = atomicrmw fmax ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic ret void } -define amdgpu_ps void @global_atomic_fadd_div_address_div_value_system_scope_strictfp(ptr addrspace(1) %ptr, float %val) #2 { -; IR-ITERATIVE-LABEL: @global_atomic_fadd_div_address_div_value_system_scope_strictfp( -; IR-ITERATIVE-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] monotonic, align 4 +define amdgpu_ps void @global_atomic_fmax_double_uni_address_div_value_agent_scope_unsafe_structfp(ptr addrspace(1) inreg %ptr, double %val) #1{ +; IR-LABEL: @global_atomic_fmax_double_uni_address_div_value_agent_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: ret void +; + %result = atomicrmw fmax ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret void +} + +define amdgpu_ps void @global_atomic_fadd_double_uni_address_uni_value_system_scope_strictfp(ptr addrspace(1) inreg %ptr, double inreg %val) #2 { +; IR-ITERATIVE-LABEL: @global_atomic_fadd_double_uni_address_uni_value_system_scope_strictfp( +; IR-ITERATIVE-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() #[[ATTR7]] +; IR-ITERATIVE-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP17:%.*]] +; IR-ITERATIVE: 2: +; IR-ITERATIVE-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-ITERATIVE-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-ITERATIVE-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-ITERATIVE-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 +; IR-ITERATIVE-NEXT: [[TMP11:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP10]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP12:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[VAL:%.*]], double [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR7]] +; IR-ITERATIVE-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-ITERATIVE-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] +; IR-ITERATIVE: 14: +; IR-ITERATIVE-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[TMP12]] monotonic, align 4 +; IR-ITERATIVE-NEXT: br label [[TMP16]] +; IR-ITERATIVE: 16: +; IR-ITERATIVE-NEXT: br label [[TMP17]] +; IR-ITERATIVE: 17: ; IR-ITERATIVE-NEXT: ret void ; -; IR-DPP-LABEL: @global_atomic_fadd_div_address_div_value_system_scope_strictfp( -; IR-DPP-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], float [[VAL:%.*]] monotonic, align 4 +; IR-DPP-LABEL: @global_atomic_fadd_double_uni_address_uni_value_system_scope_strictfp( +; IR-DPP-NEXT: [[TMP1:%.*]] = call i1 @llvm.amdgcn.ps.live() #[[ATTR8]] +; IR-DPP-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP17:%.*]] +; IR-DPP: 2: +; IR-DPP-NEXT: [[TMP3:%.*]] = call i64 @llvm.amdgcn.ballot.i64(i1 true) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i32 +; IR-DPP-NEXT: [[TMP5:%.*]] = lshr i64 [[TMP3]], 32 +; IR-DPP-NEXT: [[TMP6:%.*]] = trunc i64 [[TMP5]] to i32 +; IR-DPP-NEXT: [[TMP7:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 [[TMP4]], i32 0) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.mbcnt.hi(i32 [[TMP6]], i32 [[TMP7]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP9:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP3]]) #[[ATTR8]] +; IR-DPP-NEXT: [[TMP10:%.*]] = trunc i64 [[TMP9]] to i32 +; IR-DPP-NEXT: [[TMP11:%.*]] = call double @llvm.experimental.constrained.uitofp.f64.i32(i32 [[TMP10]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP12:%.*]] = call double @llvm.experimental.constrained.fmul.f64(double [[VAL:%.*]], double [[TMP11]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR8]] +; IR-DPP-NEXT: [[TMP13:%.*]] = icmp eq i32 [[TMP8]], 0 +; IR-DPP-NEXT: br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP16:%.*]] +; IR-DPP: 14: +; IR-DPP-NEXT: [[TMP15:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[TMP12]] monotonic, align 4 +; IR-DPP-NEXT: br label [[TMP16]] +; IR-DPP: 16: +; IR-DPP-NEXT: br label [[TMP17]] +; IR-DPP: 17: ; IR-DPP-NEXT: ret void ; - %result = atomicrmw fadd ptr addrspace(1) %ptr, float %val monotonic, align 4 + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val monotonic, align 4 + ret void +} + +define amdgpu_ps void @global_atomic_fadd_double_uni_address_div_value_system_scope_strictfp(ptr addrspace(1) inreg %ptr, double %val) #2 { +; IR-LABEL: @global_atomic_fadd_double_uni_address_div_value_system_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] monotonic, align 4 +; IR-NEXT: ret void +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val monotonic, align 4 + ret void +} + +define amdgpu_ps void @global_atomic_fadd_double_div_address_uni_value_agent_scope_unsafe(ptr addrspace(1) %ptr, double inreg %val) #0 { +; IR-LABEL: @global_atomic_fadd_double_div_address_uni_value_agent_scope_unsafe( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret void +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic, align 4 + ret void +} + +define amdgpu_ps void @global_atomic_fadd_double_div_address_div_value_agent_scope_unsafe(ptr addrspace(1) %ptr, double %val) #0 { +; IR-LABEL: @global_atomic_fadd_double_div_address_div_value_agent_scope_unsafe( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 4 +; IR-NEXT: ret void +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic, align 4 + ret void +} + +define amdgpu_ps void @global_atomic_fadd_double_div_address_uni_value_one_as_scope_unsafe_structfp(ptr addrspace(1) %ptr, double inreg %val) #1 { +; IR-LABEL: @global_atomic_fadd_double_div_address_uni_value_one_as_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("one-as") monotonic, align 8 +; IR-NEXT: ret void +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("one-as") monotonic + ret void +} + +define amdgpu_ps void @global_atomic_fadd_double_div_address_div_value_one_as_scope_unsafe_structfp(ptr addrspace(1) %ptr, double %val) #1 { +; IR-LABEL: @global_atomic_fadd_double_div_address_div_value_one_as_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("one-as") monotonic, align 8 +; IR-NEXT: ret void +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("one-as") monotonic + ret void +} + +define amdgpu_ps void @global_atomic_fsub_double_div_address_uni_value_agent_scope_strictfp(ptr addrspace(1) %ptr, double inreg %val) #2 { +; IR-LABEL: @global_atomic_fsub_double_div_address_uni_value_agent_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: ret void +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret void +} + +define amdgpu_ps void @global_atomic_fsub_double_div_address_div_value_agent_scope_strictfp(ptr addrspace(1) %ptr, double %val) #2 { +; IR-LABEL: @global_atomic_fsub_double_div_address_div_value_agent_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fsub ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: ret void +; + %result = atomicrmw fsub ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret void +} + +define amdgpu_ps void @global_atomic_fmin_double_div_address_uni_value_agent_scope(ptr addrspace(1) %ptr, double inreg %val) #0 { +; IR-LABEL: @global_atomic_fmin_double_div_address_uni_value_agent_scope( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: ret void +; + %result = atomicrmw fmin ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret void +} + +define amdgpu_ps void @global_atomic_fmin_double_div_address_div_value_agent_scope(ptr addrspace(1) %ptr, double %val) #0 { +; IR-LABEL: @global_atomic_fmin_double_div_address_div_value_agent_scope( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmin ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: ret void +; + %result = atomicrmw fmin ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret void +} + +define amdgpu_ps void @global_atomic_fmax_double_div_address_uni_value_agent_scope_unsafe_structfp(ptr addrspace(1) %ptr, double inreg %val) #1{ +; IR-LABEL: @global_atomic_fmax_double_div_address_uni_value_agent_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: ret void +; + %result = atomicrmw fmax ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret void +} + +define amdgpu_ps void @global_atomic_fmax_double_div_address_div_value_agent_scope_unsafe_structfp(ptr addrspace(1) %ptr, double %val) #1{ +; IR-LABEL: @global_atomic_fmax_double_div_address_div_value_agent_scope_unsafe_structfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fmax ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] syncscope("agent") monotonic, align 8 +; IR-NEXT: ret void +; + %result = atomicrmw fmax ptr addrspace(1) %ptr, double %val syncscope("agent") monotonic + ret void +} + +define amdgpu_ps void @global_atomic_fadd_double_div_address_uni_value_system_scope_strictfp(ptr addrspace(1) %ptr, double inreg %val) #2 { +; IR-LABEL: @global_atomic_fadd_double_div_address_uni_value_system_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] monotonic, align 4 +; IR-NEXT: ret void +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val monotonic, align 4 + ret void +} + +define amdgpu_ps void @global_atomic_fadd_double_div_address_div_value_system_scope_strictfp(ptr addrspace(1) %ptr, double %val) #2 { +; IR-LABEL: @global_atomic_fadd_double_div_address_div_value_system_scope_strictfp( +; IR-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr addrspace(1) [[PTR:%.*]], double [[VAL:%.*]] monotonic, align 4 +; IR-NEXT: ret void +; + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %val monotonic, align 4 ret void } diff --git a/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fadd.ll b/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fadd.ll index 96c615b974ce17576258faf9ada08a9daad4e4aa..4f00d48551bed0af6edea77e424c053149535391 100644 --- a/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fadd.ll +++ b/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fadd.ll @@ -13,6 +13,7 @@ ; RUN: llc -mtriple=amdgcn -mcpu=gfx1100 -mattr=+wavefrontsize32,-wavefrontsize64 -amdgpu-atomic-optimizer-strategy=DPP -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GFX1132-DPP %s declare float @div.float.value() +declare double @div.double.value() define amdgpu_kernel void @global_atomic_fadd_uni_address_uni_value_agent_scope_unsafe(ptr addrspace(1) %ptr) #0 { ; GFX7LESS-LABEL: global_atomic_fadd_uni_address_uni_value_agent_scope_unsafe: @@ -5408,6 +5409,5583 @@ define amdgpu_kernel void @global_atomic_fadd_uni_address_div_value_defalut_scop ret void } +define amdgpu_kernel void @global_atomic_fadd_double_uni_address_uni_value_agent_scope_unsafe(ptr addrspace(1) %ptr) #0 { +; GFX7LESS-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_unsafe: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_movk_i32 s32, 0x800 +; GFX7LESS-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s42, -1 +; GFX7LESS-NEXT: s_mov_b32 s43, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s40, s40, s3 +; GFX7LESS-NEXT: s_addc_u32 s41, s41, 0 +; GFX7LESS-NEXT: s_mov_b32 s33, s2 +; GFX7LESS-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX7LESS-NEXT: v_mov_b32_e32 v40, v0 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], exec +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, s0, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, s1, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB9_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x9 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dwordx2 s[2:3], s[36:37], 0x0 +; GFX7LESS-NEXT: s_bcnt1_i32_b64 s0, s[0:1] +; GFX7LESS-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX7LESS-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX7LESS-NEXT: s_mov_b64 s[38:39], 0 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, s2 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, s3 +; GFX7LESS-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_add_f64 v[2:3], v[0:1], v[41:42] +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[40:43], 0 offset:4 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[40:43], 0 +; GFX7LESS-NEXT: s_add_u32 s8, s34, 44 +; GFX7LESS-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:12 +; GFX7LESS-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:8 +; GFX7LESS-NEXT: s_addc_u32 s9, s35, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX7LESS-NEXT: s_waitcnt expcnt(2) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v4, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, 0 +; GFX7LESS-NEXT: s_mov_b32 s12, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v40 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s36 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s37 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX7LESS-NEXT: v_and_b32_e32 v2, 1, v0 +; GFX7LESS-NEXT: buffer_load_dword v0, off, s[40:43], 0 +; GFX7LESS-NEXT: buffer_load_dword v1, off, s[40:43], 0 offset:4 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 1, v2 +; GFX7LESS-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB9_2 +; GFX7LESS-NEXT: .LBB9_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_unsafe: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s42, -1 +; GFX9-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX9-NEXT: s_mov_b64 s[0:1], exec +; GFX9-NEXT: s_mov_b32 s43, 0xe00000 +; GFX9-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, s0, 0 +; GFX9-NEXT: s_add_u32 s40, s40, s3 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, s1, v0 +; GFX9-NEXT: s_addc_u32 s41, s41, 0 +; GFX9-NEXT: s_mov_b32 s33, s2 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_movk_i32 s32, 0x800 +; GFX9-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-NEXT: s_cbranch_execz .LBB9_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: s_bcnt1_i32_b64 s0, s[0:1] +; GFX9-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX9-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX9-NEXT: s_mov_b64 s[38:39], 0 +; GFX9-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, s1 +; GFX9-NEXT: v_mov_b32_e32 v1, s0 +; GFX9-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX9-NEXT: s_add_u32 s8, s34, 44 +; GFX9-NEXT: s_addc_u32 s9, s35, 0 +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX9-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX9-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX9-NEXT: s_mov_b32 s12, s33 +; GFX9-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX9-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX9-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX9-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: v_mov_b32_e32 v2, s36 +; GFX9-NEXT: v_mov_b32_e32 v3, s37 +; GFX9-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX9-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX9-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX9-NEXT: s_cbranch_execnz .LBB9_2 +; GFX9-NEXT: .LBB9_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s42, -1 +; GFX1064-NEXT: s_mov_b32 s43, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s40, s40, s3 +; GFX1064-NEXT: s_mov_b32 s33, s2 +; GFX1064-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-NEXT: s_addc_u32 s41, s41, 0 +; GFX1064-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1064-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB9_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_bcnt1_i32_b64 s0, s[2:3] +; GFX1064-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1064-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX1064-NEXT: s_mov_b64 s[38:39], 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1064-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v2, s1 +; GFX1064-NEXT: v_mov_b32_e32 v1, s0 +; GFX1064-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1064-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1064-NEXT: s_mov_b32 s12, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1064-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1064-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1064-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1064-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-NEXT: v_mov_b32_e32 v2, s36 +; GFX1064-NEXT: v_mov_b32_e32 v3, s37 +; GFX1064-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1064-NEXT: s_clause 0x1 +; GFX1064-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1064-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX1064-NEXT: s_cbranch_execnz .LBB9_2 +; GFX1064-NEXT: .LBB9_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s33, s2 +; GFX1032-NEXT: s_mov_b32 s2, exec_lo +; GFX1032-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1032-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s42, -1 +; GFX1032-NEXT: s_mov_b32 s43, 0x31c16000 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_add_u32 s40, s40, s3 +; GFX1032-NEXT: s_addc_u32 s41, s41, 0 +; GFX1032-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1032-NEXT: s_mov_b32 s38, 0 +; GFX1032-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-NEXT: s_and_saveexec_b32 s0, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB9_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_bcnt1_i32_b32 s0, s2 +; GFX1032-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1032-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1032-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v2, s1 +; GFX1032-NEXT: v_mov_b32_e32 v1, s0 +; GFX1032-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1032-NEXT: s_mov_b32 s12, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1032-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1032-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1032-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1032-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-NEXT: v_mov_b32_e32 v2, s36 +; GFX1032-NEXT: v_mov_b32_e32 v3, s37 +; GFX1032-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1032-NEXT: s_clause 0x1 +; GFX1032-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1032-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s38 +; GFX1032-NEXT: s_cbranch_execnz .LBB9_2 +; GFX1032-NEXT: .LBB9_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b32 s33, s2 +; GFX1164-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1164-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1164-NEXT: s_mov_b32 s32, 32 +; GFX1164-NEXT: s_mov_b64 s[0:1], exec +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-NEXT: s_cbranch_execz .LBB9_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_bcnt1_i32_b64 s0, s[2:3] +; GFX1164-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1164-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX1164-NEXT: s_mov_b64 s[38:39], 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v2, s1 +; GFX1164-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-NEXT: .p2align 6 +; GFX1164-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-NEXT: s_mov_b32 s12, s33 +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-NEXT: v_mov_b32_e32 v2, s36 +; GFX1164-NEXT: v_mov_b32_e32 v3, s37 +; GFX1164-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[38:39] +; GFX1164-NEXT: s_cbranch_execnz .LBB9_2 +; GFX1164-NEXT: .LBB9_3: +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_mov_b32 s2, exec_lo +; GFX1132-NEXT: v_mov_b32_e32 v40, v0 +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1132-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1132-NEXT: s_mov_b32 s38, 0 +; GFX1132-NEXT: s_mov_b32 s32, 32 +; GFX1132-NEXT: s_mov_b32 s0, exec_lo +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-NEXT: s_cbranch_execz .LBB9_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_bcnt1_i32_b32 s0, s2 +; GFX1132-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1132-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX1132-NEXT: s_mov_b32 s33, s15 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: v_dual_mov_b32 v2, s1 :: v_dual_mov_b32 v1, s0 +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-NEXT: .p2align 6 +; GFX1132-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-NEXT: v_dual_mov_b32 v31, v40 :: v_dual_mov_b32 v0, 8 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-NEXT: s_mov_b32 s12, s33 +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s36 +; GFX1132-NEXT: v_dual_mov_b32 v3, s37 :: v_dual_mov_b32 v4, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s38 +; GFX1132-NEXT: s_cbranch_execnz .LBB9_2 +; GFX1132-NEXT: .LBB9_3: +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_unsafe: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s42, -1 +; GFX9-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], exec +; GFX9-DPP-NEXT: s_mov_b32 s43, 0xe00000 +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s0, 0 +; GFX9-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s1, v0 +; GFX9-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX9-DPP-NEXT: s_mov_b32 s33, s2 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB9_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: s_bcnt1_i32_b64 s0, s[0:1] +; GFX9-DPP-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX9-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX9-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX9-DPP-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX9-DPP-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX9-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX9-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX9-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX9-DPP-NEXT: s_mov_b32 s12, s33 +; GFX9-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX9-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX9-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX9-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX9-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB9_2 +; GFX9-DPP-NEXT: .LBB9_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s42, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s43, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX1064-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1064-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB9_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_bcnt1_i32_b64 s0, s[2:3] +; GFX1064-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1064-DPP-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX1064-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1064-DPP-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1064-DPP-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1064-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1064-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1064-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1064-DPP-NEXT: s_clause 0x1 +; GFX1064-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1064-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB9_2 +; GFX1064-DPP-NEXT: .LBB9_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1032-DPP-NEXT: s_mov_b32 s2, exec_lo +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s42, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s43, 0x31c16000 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX1032-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1032-DPP-NEXT: s_mov_b32 s38, 0 +; GFX1032-DPP-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s0, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB9_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_bcnt1_i32_b32 s0, s2 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1032-DPP-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1032-DPP-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1032-DPP-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1032-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1032-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1032-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1032-DPP-NEXT: s_clause 0x1 +; GFX1032-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1032-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s38 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB9_2 +; GFX1032-DPP-NEXT: .LBB9_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1164-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1164-DPP-NEXT: s_mov_b64 s[0:1], exec +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB9_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_bcnt1_i32_b64 s0, s[2:3] +; GFX1164-DPP-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1164-DPP-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX1164-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-DPP-NEXT: .p2align 6 +; GFX1164-DPP-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[38:39] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB9_2 +; GFX1164-DPP-NEXT: .LBB9_3: +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_mov_b32 s2, exec_lo +; GFX1132-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s38, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1132-DPP-NEXT: s_mov_b32 s0, exec_lo +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB9_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_bcnt1_i32_b32 s0, s2 +; GFX1132-DPP-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1132-DPP-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX1132-DPP-NEXT: s_mov_b32 s33, s15 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v2, s1 :: v_dual_mov_b32 v1, s0 +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-DPP-NEXT: .p2align 6 +; GFX1132-DPP-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v31, v40 :: v_dual_mov_b32 v0, 8 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s36 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, s37 :: v_dual_mov_b32 v4, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s38 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB9_2 +; GFX1132-DPP-NEXT: .LBB9_3: +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fadd ptr addrspace(1) %ptr, double 4.0 syncscope("agent") monotonic, align 4 + ret void +} + +define amdgpu_kernel void @global_atomic_fadd_double_uni_address_div_value_agent_scope_align4_unsafe(ptr addrspace(1) %ptr) #0 { +; GFX7LESS-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_movk_i32 s32, 0x800 +; GFX7LESS-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s50, -1 +; GFX7LESS-NEXT: s_mov_b32 s51, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s48, s48, s9 +; GFX7LESS-NEXT: s_addc_u32 s49, s49, 0 +; GFX7LESS-NEXT: s_mov_b32 s33, s8 +; GFX7LESS-NEXT: s_mov_b32 s40, s7 +; GFX7LESS-NEXT: s_mov_b32 s41, s6 +; GFX7LESS-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX7LESS-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX7LESS-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX7LESS-NEXT: s_load_dwordx2 s[44:45], s[2:3], 0x9 +; GFX7LESS-NEXT: s_mov_b32 s47, 0xf000 +; GFX7LESS-NEXT: s_mov_b32 s46, -1 +; GFX7LESS-NEXT: s_add_u32 s8, s36, 44 +; GFX7LESS-NEXT: s_addc_u32 s9, s37, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v0, v0, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v42, v0, v2 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX7LESS-NEXT: s_mov_b32 s12, s41 +; GFX7LESS-NEXT: s_mov_b32 s13, s40 +; GFX7LESS-NEXT: s_mov_b32 s14, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v42 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX7LESS-NEXT: v_mov_b32_e32 v40, v0 +; GFX7LESS-NEXT: v_mov_b32_e32 v41, v1 +; GFX7LESS-NEXT: buffer_load_dwordx2 v[0:1], off, s[44:47], 0 +; GFX7LESS-NEXT: s_mov_b64 s[42:43], 0 +; GFX7LESS-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_add_f64 v[2:3], v[0:1], v[40:41] +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:4 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[48:51], 0 +; GFX7LESS-NEXT: s_add_u32 s8, s36, 44 +; GFX7LESS-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:12 +; GFX7LESS-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:8 +; GFX7LESS-NEXT: s_addc_u32 s9, s37, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX7LESS-NEXT: s_waitcnt expcnt(2) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v4, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, 0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX7LESS-NEXT: s_mov_b32 s12, s41 +; GFX7LESS-NEXT: s_mov_b32 s13, s40 +; GFX7LESS-NEXT: s_mov_b32 s14, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v42 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s44 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s45 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX7LESS-NEXT: v_and_b32_e32 v2, 1, v0 +; GFX7LESS-NEXT: buffer_load_dword v0, off, s[48:51], 0 +; GFX7LESS-NEXT: buffer_load_dword v1, off, s[48:51], 0 offset:4 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 1, v2 +; GFX7LESS-NEXT: s_or_b64 s[42:43], vcc, s[42:43] +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[42:43] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB10_1 +; GFX7LESS-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s50, -1 +; GFX9-NEXT: s_mov_b32 s51, 0xe00000 +; GFX9-NEXT: s_add_u32 s48, s48, s9 +; GFX9-NEXT: s_addc_u32 s49, s49, 0 +; GFX9-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX9-NEXT: s_mov_b32 s33, s8 +; GFX9-NEXT: s_add_u32 s8, s36, 44 +; GFX9-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX9-NEXT: s_mov_b32 s40, s7 +; GFX9-NEXT: s_mov_b32 s41, s6 +; GFX9-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX9-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX9-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-NEXT: s_mov_b32 s12, s41 +; GFX9-NEXT: s_mov_b32 s13, s40 +; GFX9-NEXT: s_mov_b32 s14, s33 +; GFX9-NEXT: v_mov_b32_e32 v31, v42 +; GFX9-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-NEXT: s_movk_i32 s32, 0x800 +; GFX9-NEXT: v_mov_b32_e32 v43, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-NEXT: v_mov_b32_e32 v41, v1 +; GFX9-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX9-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-NEXT: s_mov_b64 s[44:45], 0 +; GFX9-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX9-NEXT: s_add_u32 s8, s36, 44 +; GFX9-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX9-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX9-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX9-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX9-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-NEXT: s_mov_b32 s12, s41 +; GFX9-NEXT: s_mov_b32 s13, s40 +; GFX9-NEXT: s_mov_b32 s14, s33 +; GFX9-NEXT: v_mov_b32_e32 v31, v42 +; GFX9-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: v_mov_b32_e32 v2, s42 +; GFX9-NEXT: v_mov_b32_e32 v3, s43 +; GFX9-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX9-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX9-NEXT: s_cbranch_execnz .LBB10_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s50, -1 +; GFX1064-NEXT: s_mov_b32 s51, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s48, s48, s9 +; GFX1064-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1064-NEXT: s_addc_u32 s49, s49, 0 +; GFX1064-NEXT: s_mov_b32 s33, s8 +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1064-NEXT: s_mov_b32 s40, s7 +; GFX1064-NEXT: s_mov_b32 s41, s6 +; GFX1064-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1064-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1064-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX1064-NEXT: s_mov_b32 s12, s41 +; GFX1064-NEXT: s_mov_b32 s13, s40 +; GFX1064-NEXT: s_mov_b32 s14, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-NEXT: v_mov_b32_e32 v31, v42 +; GFX1064-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-NEXT: v_mov_b32_e32 v43, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-NEXT: v_mov_b32_e32 v41, v1 +; GFX1064-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX1064-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-NEXT: s_mov_b64 s[44:45], 0 +; GFX1064-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX1064-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX1064-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-NEXT: v_mov_b32_e32 v31, v42 +; GFX1064-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-NEXT: v_mov_b32_e32 v2, s42 +; GFX1064-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-NEXT: s_mov_b32 s12, s41 +; GFX1064-NEXT: s_mov_b32 s13, s40 +; GFX1064-NEXT: s_mov_b32 s14, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX1064-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX1064-NEXT: v_mov_b32_e32 v3, s43 +; GFX1064-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-NEXT: s_clause 0x1 +; GFX1064-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX1064-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX1064-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX1064-NEXT: s_cbranch_execnz .LBB10_1 +; GFX1064-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s50, -1 +; GFX1032-NEXT: s_mov_b32 s51, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s48, s48, s9 +; GFX1032-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1032-NEXT: s_addc_u32 s49, s49, 0 +; GFX1032-NEXT: s_mov_b32 s33, s8 +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1032-NEXT: s_mov_b32 s40, s7 +; GFX1032-NEXT: s_mov_b32 s41, s6 +; GFX1032-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1032-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1032-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX1032-NEXT: s_mov_b32 s12, s41 +; GFX1032-NEXT: s_mov_b32 s13, s40 +; GFX1032-NEXT: s_mov_b32 s14, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-NEXT: v_mov_b32_e32 v31, v42 +; GFX1032-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-NEXT: v_mov_b32_e32 v43, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-NEXT: v_mov_b32_e32 v41, v1 +; GFX1032-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX1032-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-NEXT: s_mov_b32 s44, 0 +; GFX1032-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX1032-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX1032-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-NEXT: v_mov_b32_e32 v31, v42 +; GFX1032-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-NEXT: v_mov_b32_e32 v2, s42 +; GFX1032-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-NEXT: s_mov_b32 s12, s41 +; GFX1032-NEXT: s_mov_b32 s13, s40 +; GFX1032-NEXT: s_mov_b32 s14, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX1032-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX1032-NEXT: v_mov_b32_e32 v3, s43 +; GFX1032-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-NEXT: s_clause 0x1 +; GFX1032-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX1032-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX1032-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s44 +; GFX1032-NEXT: s_cbranch_execnz .LBB10_1 +; GFX1032-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1164-NEXT: s_mov_b32 s33, s8 +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1164-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-NEXT: s_mov_b32 s12, s6 +; GFX1164-NEXT: s_mov_b32 s13, s7 +; GFX1164-NEXT: s_mov_b32 s14, s33 +; GFX1164-NEXT: s_mov_b32 s32, 32 +; GFX1164-NEXT: v_mov_b32_e32 v42, v0 +; GFX1164-NEXT: s_mov_b32 s40, s7 +; GFX1164-NEXT: s_mov_b32 s41, s6 +; GFX1164-NEXT: v_mov_b32_e32 v43, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: v_mov_b32_e32 v41, v1 +; GFX1164-NEXT: global_load_b64 v[1:2], v43, s[42:43] +; GFX1164-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-NEXT: s_mov_b64 s[44:45], 0 +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-NEXT: .p2align 6 +; GFX1164-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-NEXT: v_mov_b32_e32 v31, v42 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-NEXT: s_mov_b32 s12, s41 +; GFX1164-NEXT: s_mov_b32 s13, s40 +; GFX1164-NEXT: s_mov_b32 s14, s33 +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-NEXT: v_mov_b32_e32 v2, s42 +; GFX1164-NEXT: v_mov_b32_e32 v3, s43 +; GFX1164-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[44:45] +; GFX1164-NEXT: s_cbranch_execnz .LBB10_1 +; GFX1164-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1132-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1132-NEXT: v_mov_b32_e32 v31, v0 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1132-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1132-NEXT: s_mov_b32 s40, s14 +; GFX1132-NEXT: s_mov_b32 s41, s13 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-NEXT: s_mov_b32 s12, s13 +; GFX1132-NEXT: s_mov_b32 s13, s14 +; GFX1132-NEXT: s_mov_b32 s14, s15 +; GFX1132-NEXT: s_mov_b32 s32, 32 +; GFX1132-NEXT: s_mov_b32 s33, s15 +; GFX1132-NEXT: v_dual_mov_b32 v42, v0 :: v_dual_mov_b32 v43, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v41, v1 +; GFX1132-NEXT: global_load_b64 v[1:2], v43, s[42:43] +; GFX1132-NEXT: s_mov_b32 s44, 0 +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-NEXT: .p2align 6 +; GFX1132-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-NEXT: v_dual_mov_b32 v31, v42 :: v_dual_mov_b32 v0, 8 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-NEXT: s_mov_b32 s12, s41 +; GFX1132-NEXT: s_mov_b32 s13, s40 +; GFX1132-NEXT: s_mov_b32 s14, s33 +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s42 +; GFX1132-NEXT: v_dual_mov_b32 v3, s43 :: v_dual_mov_b32 v4, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s44 +; GFX1132-NEXT: s_cbranch_execnz .LBB10_1 +; GFX1132-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s50, -1 +; GFX9-DPP-NEXT: s_mov_b32 s51, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX9-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX9-DPP-NEXT: s_mov_b32 s33, s8 +; GFX9-DPP-NEXT: s_add_u32 s8, s36, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_mov_b32 s40, s7 +; GFX9-DPP-NEXT: s_mov_b32 s41, s6 +; GFX9-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-DPP-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX9-DPP-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-DPP-NEXT: s_mov_b32 s12, s41 +; GFX9-DPP-NEXT: s_mov_b32 s13, s40 +; GFX9-DPP-NEXT: s_mov_b32 s14, s33 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX9-DPP-NEXT: v_mov_b32_e32 v43, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-DPP-NEXT: v_mov_b32_e32 v41, v1 +; GFX9-DPP-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX9-DPP-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX9-DPP-NEXT: s_add_u32 s8, s36, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX9-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-DPP-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX9-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-DPP-NEXT: s_mov_b32 s12, s41 +; GFX9-DPP-NEXT: s_mov_b32 s13, s40 +; GFX9-DPP-NEXT: s_mov_b32 s14, s33 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-DPP-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX9-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX9-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB10_1 +; GFX9-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s50, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s51, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX1064-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1064-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1064-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-DPP-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX1064-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1064-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v43, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v41, v1 +; GFX1064-DPP-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX1064-DPP-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX1064-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-DPP-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX1064-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-DPP-NEXT: s_clause 0x1 +; GFX1064-DPP-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX1064-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX1064-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB10_1 +; GFX1064-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s50, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s51, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX1032-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1032-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1032-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-DPP-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX1032-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1032-DPP-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v43, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v41, v1 +; GFX1032-DPP-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-DPP-NEXT: s_mov_b32 s44, 0 +; GFX1032-DPP-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX1032-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-DPP-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX1032-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-DPP-NEXT: s_clause 0x1 +; GFX1032-DPP-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX1032-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX1032-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s44 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB10_1 +; GFX1032-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1164-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1164-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v42, v0 +; GFX1164-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v43, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v41, v1 +; GFX1164-DPP-NEXT: global_load_b64 v[1:2], v43, s[42:43] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-DPP-NEXT: .p2align 6 +; GFX1164-DPP-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1164-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[44:45] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB10_1 +; GFX1164-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1132-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1132-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1132-DPP-NEXT: s_mov_b32 s40, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s41, s13 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-DPP-NEXT: s_mov_b32 s12, s13 +; GFX1132-DPP-NEXT: s_mov_b32 s13, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s15 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1132-DPP-NEXT: s_mov_b32 s33, s15 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v42, v0 :: v_dual_mov_b32 v43, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v41, v1 +; GFX1132-DPP-NEXT: global_load_b64 v[1:2], v43, s[42:43] +; GFX1132-DPP-NEXT: s_mov_b32 s44, 0 +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-DPP-NEXT: .p2align 6 +; GFX1132-DPP-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v31, v42 :: v_dual_mov_b32 v0, 8 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1132-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s42 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, s43 :: v_dual_mov_b32 v4, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s44 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB10_1 +; GFX1132-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-DPP-NEXT: s_endpgm + %divValue = call double @div.float.value() + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %divValue syncscope("agent") monotonic, align 4 + ret void +} + +define amdgpu_kernel void @global_atomic_fadd_double_uni_address_uni_value_one_as_scope_unsafe_structfp(ptr addrspace(1) %ptr) #1 { +; GFX7LESS-LABEL: global_atomic_fadd_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_mov_b32 s12, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s13, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s14, -1 +; GFX7LESS-NEXT: s_mov_b32 s15, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s12, s12, s3 +; GFX7LESS-NEXT: s_addc_u32 s13, s13, 0 +; GFX7LESS-NEXT: s_mov_b64 s[2:3], exec +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, s2, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, s3, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB11_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x9 +; GFX7LESS-NEXT: s_bcnt1_i32_b64 s6, s[2:3] +; GFX7LESS-NEXT: s_mov_b32 s7, 0x43300000 +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0xc3300000 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dwordx2 s[8:9], s[0:1], 0x0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], 0 +; GFX7LESS-NEXT: s_mov_b32 s3, 0xf000 +; GFX7LESS-NEXT: v_add_f64 v[0:1], s[6:7], v[0:1] +; GFX7LESS-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s8 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s9 +; GFX7LESS-NEXT: s_mov_b32 s2, -1 +; GFX7LESS-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v9, v3 +; GFX7LESS-NEXT: v_mov_b32_e32 v8, v2 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, v1 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, v0 +; GFX7LESS-NEXT: buffer_atomic_cmpswap_x2 v[6:9], off, s[0:3], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[2:3] +; GFX7LESS-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX7LESS-NEXT: v_mov_b32_e32 v2, v6 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, v7 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB11_2 +; GFX7LESS-NEXT: .LBB11_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fadd_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s10, -1 +; GFX9-NEXT: s_mov_b32 s11, 0xe00000 +; GFX9-NEXT: s_add_u32 s8, s8, s3 +; GFX9-NEXT: s_mov_b64 s[2:3], exec +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX9-NEXT: s_addc_u32 s9, s9, 0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX9-NEXT: s_cbranch_execz .LBB11_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: v_mov_b32_e32 v0, 0 +; GFX9-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX9-NEXT: v_mov_b32_e32 v1, 0xc3300000 +; GFX9-NEXT: s_mov_b32 s3, 0x43300000 +; GFX9-NEXT: v_add_f64 v[0:1], s[2:3], v[0:1] +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-NEXT: v_mov_b32_e32 v3, s5 +; GFX9-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX9-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX9-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-NEXT: s_cbranch_execnz .LBB11_2 +; GFX9-NEXT: .LBB11_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fadd_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s10, -1 +; GFX1064-NEXT: s_mov_b32 s11, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s8, s8, s3 +; GFX1064-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-NEXT: s_addc_u32 s9, s9, 0 +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB11_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX1064-NEXT: s_mov_b32 s3, 0x43300000 +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-NEXT: v_add_f64 v[0:1], 0xc3300000, s[2:3] +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX1064-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v2, s2 +; GFX1064-NEXT: v_mov_b32_e32 v3, s3 +; GFX1064-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX1064-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1064-NEXT: v_mov_b32_e32 v3, v1 +; GFX1064-NEXT: v_mov_b32_e32 v2, v0 +; GFX1064-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-NEXT: s_cbranch_execnz .LBB11_2 +; GFX1064-NEXT: .LBB11_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fadd_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s10, -1 +; GFX1032-NEXT: s_mov_b32 s11, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s8, s8, s3 +; GFX1032-NEXT: s_mov_b32 s3, exec_lo +; GFX1032-NEXT: s_addc_u32 s9, s9, 0 +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, s3, 0 +; GFX1032-NEXT: s_mov_b32 s2, 0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_and_saveexec_b32 s4, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB11_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_bcnt1_i32_b32 s4, s3 +; GFX1032-NEXT: s_mov_b32 s5, 0x43300000 +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-NEXT: v_add_f64 v[0:1], 0xc3300000, s[4:5] +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v2, s4 +; GFX1032-NEXT: v_mov_b32_e32 v3, s5 +; GFX1032-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX1032-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1032-NEXT: v_mov_b32_e32 v3, v1 +; GFX1032-NEXT: v_mov_b32_e32 v2, v0 +; GFX1032-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-NEXT: s_cbranch_execnz .LBB11_2 +; GFX1032-NEXT: .LBB11_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fadd_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_bcnt1_i32_b64 s2, exec +; GFX1164-NEXT: v_mov_b32_e32 v0, 0x43300000 +; GFX1164-NEXT: v_mov_b32_e32 v1, s2 +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1164-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b32 off, v0, off offset:4 +; GFX1164-NEXT: scratch_store_b32 off, v1, off +; GFX1164-NEXT: scratch_load_b64 v[0:1], off, off +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v2, exec_hi, v2 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1164-NEXT: s_cbranch_execz .LBB11_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b64 s[2:3], s[0:1], 0x0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_2) +; GFX1164-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v2, s2 +; GFX1164-NEXT: v_mov_b32_e32 v3, s3 +; GFX1164-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX1164-NEXT: global_atomic_cmpswap_b64 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1164-NEXT: v_mov_b32_e32 v3, v1 +; GFX1164-NEXT: v_mov_b32_e32 v2, v0 +; GFX1164-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-NEXT: s_cbranch_execnz .LBB11_2 +; GFX1164-NEXT: .LBB11_3: +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fadd_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_bcnt1_i32_b32 s2, exec_lo +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: v_dual_mov_b32 v0, 0x43300000 :: v_dual_mov_b32 v1, s2 +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1132-NEXT: s_mov_b32 s2, 0 +; GFX1132-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b32 off, v0, off offset:4 +; GFX1132-NEXT: scratch_store_b32 off, v1, off +; GFX1132-NEXT: scratch_load_b64 v[0:1], off, off +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1132-NEXT: s_cbranch_execz .LBB11_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-NEXT: v_mov_b32_e32 v6, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b64 s[4:5], s[0:1], 0x0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_2) +; GFX1132-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: v_dual_mov_b32 v2, s4 :: v_dual_mov_b32 v3, s5 +; GFX1132-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX1132-NEXT: global_atomic_cmpswap_b64 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1132-NEXT: v_dual_mov_b32 v3, v1 :: v_dual_mov_b32 v2, v0 +; GFX1132-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-NEXT: s_cbranch_execnz .LBB11_2 +; GFX1132-NEXT: .LBB11_3: +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s10, -1 +; GFX9-DPP-NEXT: s_mov_b32 s11, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s8, s8, s3 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX9-DPP-NEXT: s_addc_u32 s9, s9, 0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB11_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 0 +; GFX9-DPP-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0xc3300000 +; GFX9-DPP-NEXT: s_mov_b32 s3, 0x43300000 +; GFX9-DPP-NEXT: v_add_f64 v[0:1], s[2:3], v[0:1] +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s5 +; GFX9-DPP-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX9-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB11_2 +; GFX9-DPP-NEXT: .LBB11_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s10, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s11, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s8, s8, s3 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-DPP-NEXT: s_addc_u32 s9, s9, 0 +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB11_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX1064-DPP-NEXT: s_mov_b32 s3, 0x43300000 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, s[2:3] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s2 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s3 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-DPP-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX1064-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB11_2 +; GFX1064-DPP-NEXT: .LBB11_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s10, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s11, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s8, s8, s3 +; GFX1032-DPP-NEXT: s_mov_b32 s3, exec_lo +; GFX1032-DPP-NEXT: s_addc_u32 s9, s9, 0 +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s3, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s4, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB11_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_bcnt1_i32_b32 s4, s3 +; GFX1032-DPP-NEXT: s_mov_b32 s5, 0x43300000 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, s[4:5] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s4 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s5 +; GFX1032-DPP-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX1032-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1032-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB11_2 +; GFX1032-DPP-NEXT: .LBB11_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_bcnt1_i32_b64 s2, exec +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 0x43300000 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s2 +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b32 off, v0, off offset:4 +; GFX1164-DPP-NEXT: scratch_store_b32 off, v1, off +; GFX1164-DPP-NEXT: scratch_load_b64 v[0:1], off, off +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v2, exec_hi, v2 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB11_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b64 s[2:3], s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_2) +; GFX1164-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s2 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s3 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-DPP-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b64 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB11_2 +; GFX1164-DPP-NEXT: .LBB11_3: +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_bcnt1_i32_b32 s2, exec_lo +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v0, 0x43300000 :: v_dual_mov_b32 v1, s2 +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b32 off, v0, off offset:4 +; GFX1132-DPP-NEXT: scratch_store_b32 off, v1, off +; GFX1132-DPP-NEXT: scratch_load_b64 v[0:1], off, off +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB11_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b64 s[4:5], s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_2) +; GFX1132-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v2, s4 :: v_dual_mov_b32 v3, s5 +; GFX1132-DPP-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b64 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, v1 :: v_dual_mov_b32 v2, v0 +; GFX1132-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB11_2 +; GFX1132-DPP-NEXT: .LBB11_3: +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fadd ptr addrspace(1) %ptr, double 4.0 syncscope("one-as") monotonic + ret void +} + +define amdgpu_kernel void @global_atomic_fadd_double_uni_address_div_value_one_as_scope_unsafe_structfp(ptr addrspace(1) %ptr) #1 { +; GFX7LESS-LABEL: global_atomic_fadd_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_mov_b32 s32, 0 +; GFX7LESS-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s42, -1 +; GFX7LESS-NEXT: s_mov_b32 s43, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s40, s40, s9 +; GFX7LESS-NEXT: s_addc_u32 s41, s41, 0 +; GFX7LESS-NEXT: s_mov_b32 s14, s8 +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX7LESS-NEXT: s_load_dwordx2 s[36:37], s[2:3], 0x9 +; GFX7LESS-NEXT: s_mov_b32 s39, 0xf000 +; GFX7LESS-NEXT: s_mov_b32 s38, -1 +; GFX7LESS-NEXT: s_add_u32 s8, s2, 44 +; GFX7LESS-NEXT: s_addc_u32 s9, s3, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[2:3] +; GFX7LESS-NEXT: s_add_u32 s2, s2, div.double.value@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s3, s3, div.double.value@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v0, v0, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v31, v0, v2 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX7LESS-NEXT: s_mov_b32 s12, s6 +; GFX7LESS-NEXT: s_mov_b32 s13, s7 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX7LESS-NEXT: buffer_load_dwordx2 v[4:5], off, s[36:39], 0 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], 0 +; GFX7LESS-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v9, v5 +; GFX7LESS-NEXT: v_mov_b32_e32 v8, v4 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, v3 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, v2 +; GFX7LESS-NEXT: buffer_atomic_cmpswap_x2 v[6:9], off, s[36:39], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[4:5] +; GFX7LESS-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX7LESS-NEXT: v_mov_b32_e32 v4, v6 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, v7 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB12_1 +; GFX7LESS-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fadd_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s38, -1 +; GFX9-NEXT: s_mov_b32 s39, 0xe00000 +; GFX9-NEXT: s_add_u32 s36, s36, s9 +; GFX9-NEXT: s_addc_u32 s37, s37, 0 +; GFX9-NEXT: s_mov_b32 s14, s8 +; GFX9-NEXT: s_add_u32 s8, s2, 44 +; GFX9-NEXT: s_addc_u32 s9, s3, 0 +; GFX9-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX9-NEXT: s_getpc_b64 s[2:3] +; GFX9-NEXT: s_add_u32 s2, s2, div.double.value@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s3, s3, div.double.value@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX9-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX9-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX9-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX9-NEXT: s_mov_b32 s12, s6 +; GFX9-NEXT: s_mov_b32 s13, s7 +; GFX9-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX9-NEXT: s_mov_b32 s32, 0 +; GFX9-NEXT: v_mov_b32_e32 v40, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX9-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX9-NEXT: s_mov_b64 s[0:1], 0 +; GFX9-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX9-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX9-NEXT: v_mov_b32_e32 v5, v3 +; GFX9-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX9-NEXT: v_mov_b32_e32 v4, v2 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX9-NEXT: s_cbranch_execnz .LBB12_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fadd_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s38, -1 +; GFX1064-NEXT: s_mov_b32 s39, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s36, s36, s9 +; GFX1064-NEXT: s_addc_u32 s37, s37, 0 +; GFX1064-NEXT: s_mov_b32 s14, s8 +; GFX1064-NEXT: s_add_u32 s8, s2, 44 +; GFX1064-NEXT: s_addc_u32 s9, s3, 0 +; GFX1064-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1064-NEXT: s_getpc_b64 s[4:5] +; GFX1064-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1064-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1064-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1064-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1064-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1064-NEXT: s_mov_b32 s12, s6 +; GFX1064-NEXT: s_mov_b32 s13, s7 +; GFX1064-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1064-NEXT: s_mov_b32 s32, 0 +; GFX1064-NEXT: v_mov_b32_e32 v40, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1064-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1064-NEXT: s_mov_b64 s[0:1], 0 +; GFX1064-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1064-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1064-NEXT: v_mov_b32_e32 v5, v3 +; GFX1064-NEXT: v_mov_b32_e32 v4, v2 +; GFX1064-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX1064-NEXT: s_cbranch_execnz .LBB12_1 +; GFX1064-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fadd_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s38, -1 +; GFX1032-NEXT: s_mov_b32 s39, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s36, s36, s9 +; GFX1032-NEXT: s_addc_u32 s37, s37, 0 +; GFX1032-NEXT: s_mov_b32 s14, s8 +; GFX1032-NEXT: s_add_u32 s8, s2, 44 +; GFX1032-NEXT: s_addc_u32 s9, s3, 0 +; GFX1032-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1032-NEXT: s_getpc_b64 s[4:5] +; GFX1032-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1032-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1032-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1032-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1032-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1032-NEXT: s_mov_b32 s12, s6 +; GFX1032-NEXT: s_mov_b32 s13, s7 +; GFX1032-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1032-NEXT: s_mov_b32 s32, 0 +; GFX1032-NEXT: v_mov_b32_e32 v40, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1032-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1032-NEXT: s_mov_b32 s0, 0 +; GFX1032-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1032-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1032-NEXT: v_mov_b32_e32 v5, v3 +; GFX1032-NEXT: v_mov_b32_e32 v4, v2 +; GFX1032-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s0 +; GFX1032-NEXT: s_cbranch_execnz .LBB12_1 +; GFX1032-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fadd_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b32 s14, s8 +; GFX1164-NEXT: s_add_u32 s8, s2, 44 +; GFX1164-NEXT: s_addc_u32 s9, s3, 0 +; GFX1164-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1164-NEXT: s_getpc_b64 s[4:5] +; GFX1164-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1164-NEXT: s_load_b64 s[16:17], s[4:5], 0x0 +; GFX1164-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1164-NEXT: s_mov_b32 s12, s6 +; GFX1164-NEXT: s_mov_b32 s13, s7 +; GFX1164-NEXT: s_mov_b32 s32, 0 +; GFX1164-NEXT: v_mov_b32_e32 v40, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1164-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1164-NEXT: s_mov_b64 s[0:1], 0 +; GFX1164-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1164-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1164-NEXT: v_mov_b32_e32 v5, v3 +; GFX1164-NEXT: v_mov_b32_e32 v4, v2 +; GFX1164-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[0:1] +; GFX1164-NEXT: s_cbranch_execnz .LBB12_1 +; GFX1164-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fadd_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_add_u32 s8, s2, 44 +; GFX1132-NEXT: s_addc_u32 s9, s3, 0 +; GFX1132-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1132-NEXT: s_getpc_b64 s[4:5] +; GFX1132-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1132-NEXT: s_load_b64 s[6:7], s[4:5], 0x0 +; GFX1132-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1132-NEXT: v_dual_mov_b32 v40, 0 :: v_dual_mov_b32 v31, v0 +; GFX1132-NEXT: s_mov_b32 s12, s13 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1132-NEXT: s_mov_b32 s13, s14 +; GFX1132-NEXT: s_mov_b32 s14, s15 +; GFX1132-NEXT: s_mov_b32 s32, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1132-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1132-NEXT: s_mov_b32 s0, 0 +; GFX1132-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1132-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1132-NEXT: v_dual_mov_b32 v5, v3 :: v_dual_mov_b32 v4, v2 +; GFX1132-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s0 +; GFX1132-NEXT: s_cbranch_execnz .LBB12_1 +; GFX1132-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s38, -1 +; GFX9-DPP-NEXT: s_mov_b32 s39, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX9-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX9-DPP-NEXT: s_mov_b32 s14, s8 +; GFX9-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX9-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX9-DPP-NEXT: s_getpc_b64 s[2:3] +; GFX9-DPP-NEXT: s_add_u32 s2, s2, div.double.value@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s3, s3, div.double.value@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX9-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX9-DPP-NEXT: s_mov_b32 s12, s6 +; GFX9-DPP-NEXT: s_mov_b32 s13, s7 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX9-DPP-NEXT: s_mov_b32 s32, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX9-DPP-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX9-DPP-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX9-DPP-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX9-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB12_1 +; GFX9-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s38, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s39, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX1064-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1064-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1064-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1064-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1064-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1064-DPP-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX1064-DPP-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1064-DPP-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX1064-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB12_1 +; GFX1064-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s38, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s39, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX1032-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1032-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1032-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1032-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1032-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1032-DPP-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1032-DPP-NEXT: s_mov_b32 s0, 0 +; GFX1032-DPP-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1032-DPP-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX1032-DPP-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s0 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB12_1 +; GFX1032-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1164-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1164-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1164-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: s_load_b64 s[16:17], s[4:5], 0x0 +; GFX1164-DPP-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1164-DPP-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1164-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX1164-DPP-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX1164-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[0:1] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB12_1 +; GFX1164-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1132-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1132-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: s_load_b64 s[6:7], s[4:5], 0x0 +; GFX1132-DPP-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v40, 0 :: v_dual_mov_b32 v31, v0 +; GFX1132-DPP-NEXT: s_mov_b32 s12, s13 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s13, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s15 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1132-DPP-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1132-DPP-NEXT: s_mov_b32 s0, 0 +; GFX1132-DPP-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, v3 :: v_dual_mov_b32 v4, v2 +; GFX1132-DPP-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s0 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB12_1 +; GFX1132-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-DPP-NEXT: s_endpgm + %divValue = call double @div.double.value() strictfp + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %divValue syncscope("one-as") monotonic + ret void +} + +define amdgpu_kernel void @global_atomic_fadd_double_uni_address_uni_value_agent_scope_strictfp(ptr addrspace(1) %ptr) #2{ +; GFX7LESS-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_strictfp: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_mov_b32 s12, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s13, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s14, -1 +; GFX7LESS-NEXT: s_mov_b32 s15, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s12, s12, s3 +; GFX7LESS-NEXT: s_addc_u32 s13, s13, 0 +; GFX7LESS-NEXT: s_mov_b64 s[2:3], exec +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, s2, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, s3, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB13_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x9 +; GFX7LESS-NEXT: s_bcnt1_i32_b64 s6, s[2:3] +; GFX7LESS-NEXT: s_mov_b32 s7, 0x43300000 +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0xc3300000 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dwordx2 s[8:9], s[0:1], 0x0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], 0 +; GFX7LESS-NEXT: s_mov_b32 s3, 0xf000 +; GFX7LESS-NEXT: v_add_f64 v[0:1], s[6:7], v[0:1] +; GFX7LESS-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s8 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s9 +; GFX7LESS-NEXT: s_mov_b32 s2, -1 +; GFX7LESS-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v9, v3 +; GFX7LESS-NEXT: v_mov_b32_e32 v8, v2 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, v1 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, v0 +; GFX7LESS-NEXT: buffer_atomic_cmpswap_x2 v[6:9], off, s[0:3], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[2:3] +; GFX7LESS-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX7LESS-NEXT: v_mov_b32_e32 v2, v6 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, v7 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB13_2 +; GFX7LESS-NEXT: .LBB13_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_strictfp: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s10, -1 +; GFX9-NEXT: s_mov_b32 s11, 0xe00000 +; GFX9-NEXT: s_add_u32 s8, s8, s3 +; GFX9-NEXT: s_mov_b64 s[2:3], exec +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX9-NEXT: s_addc_u32 s9, s9, 0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX9-NEXT: s_cbranch_execz .LBB13_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: v_mov_b32_e32 v0, 0 +; GFX9-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX9-NEXT: v_mov_b32_e32 v1, 0xc3300000 +; GFX9-NEXT: s_mov_b32 s3, 0x43300000 +; GFX9-NEXT: v_add_f64 v[0:1], s[2:3], v[0:1] +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-NEXT: v_mov_b32_e32 v3, s5 +; GFX9-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX9-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX9-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-NEXT: s_cbranch_execnz .LBB13_2 +; GFX9-NEXT: .LBB13_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_strictfp: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s10, -1 +; GFX1064-NEXT: s_mov_b32 s11, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s8, s8, s3 +; GFX1064-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-NEXT: s_addc_u32 s9, s9, 0 +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB13_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX1064-NEXT: s_mov_b32 s3, 0x43300000 +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-NEXT: v_add_f64 v[0:1], 0xc3300000, s[2:3] +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX1064-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v2, s2 +; GFX1064-NEXT: v_mov_b32_e32 v3, s3 +; GFX1064-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX1064-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1064-NEXT: v_mov_b32_e32 v3, v1 +; GFX1064-NEXT: v_mov_b32_e32 v2, v0 +; GFX1064-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1064-NEXT: .LBB13_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_strictfp: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s10, -1 +; GFX1032-NEXT: s_mov_b32 s11, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s8, s8, s3 +; GFX1032-NEXT: s_mov_b32 s3, exec_lo +; GFX1032-NEXT: s_addc_u32 s9, s9, 0 +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, s3, 0 +; GFX1032-NEXT: s_mov_b32 s2, 0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_and_saveexec_b32 s4, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB13_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_bcnt1_i32_b32 s4, s3 +; GFX1032-NEXT: s_mov_b32 s5, 0x43300000 +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-NEXT: v_add_f64 v[0:1], 0xc3300000, s[4:5] +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v2, s4 +; GFX1032-NEXT: v_mov_b32_e32 v3, s5 +; GFX1032-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX1032-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1032-NEXT: v_mov_b32_e32 v3, v1 +; GFX1032-NEXT: v_mov_b32_e32 v2, v0 +; GFX1032-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1032-NEXT: .LBB13_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_strictfp: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_bcnt1_i32_b64 s2, exec +; GFX1164-NEXT: v_mov_b32_e32 v0, 0x43300000 +; GFX1164-NEXT: v_mov_b32_e32 v1, s2 +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1164-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b32 off, v0, off offset:4 +; GFX1164-NEXT: scratch_store_b32 off, v1, off +; GFX1164-NEXT: scratch_load_b64 v[0:1], off, off +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v2, exec_hi, v2 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1164-NEXT: s_cbranch_execz .LBB13_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b64 s[2:3], s[0:1], 0x0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_2) +; GFX1164-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v2, s2 +; GFX1164-NEXT: v_mov_b32_e32 v3, s3 +; GFX1164-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX1164-NEXT: global_atomic_cmpswap_b64 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1164-NEXT: v_mov_b32_e32 v3, v1 +; GFX1164-NEXT: v_mov_b32_e32 v2, v0 +; GFX1164-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1164-NEXT: .LBB13_3: +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_strictfp: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_bcnt1_i32_b32 s2, exec_lo +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: v_dual_mov_b32 v0, 0x43300000 :: v_dual_mov_b32 v1, s2 +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1132-NEXT: s_mov_b32 s2, 0 +; GFX1132-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b32 off, v0, off offset:4 +; GFX1132-NEXT: scratch_store_b32 off, v1, off +; GFX1132-NEXT: scratch_load_b64 v[0:1], off, off +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1132-NEXT: s_cbranch_execz .LBB13_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-NEXT: v_mov_b32_e32 v6, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b64 s[4:5], s[0:1], 0x0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_2) +; GFX1132-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: v_dual_mov_b32 v2, s4 :: v_dual_mov_b32 v3, s5 +; GFX1132-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX1132-NEXT: global_atomic_cmpswap_b64 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1132-NEXT: v_dual_mov_b32 v3, v1 :: v_dual_mov_b32 v2, v0 +; GFX1132-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1132-NEXT: .LBB13_3: +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_strictfp: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s10, -1 +; GFX9-DPP-NEXT: s_mov_b32 s11, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s8, s8, s3 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX9-DPP-NEXT: s_addc_u32 s9, s9, 0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 0 +; GFX9-DPP-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0xc3300000 +; GFX9-DPP-NEXT: s_mov_b32 s3, 0x43300000 +; GFX9-DPP-NEXT: v_add_f64 v[0:1], s[2:3], v[0:1] +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s5 +; GFX9-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX9-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX9-DPP-NEXT: .LBB13_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_strictfp: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s10, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s11, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s8, s8, s3 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-DPP-NEXT: s_addc_u32 s9, s9, 0 +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX1064-DPP-NEXT: s_mov_b32 s3, 0x43300000 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, s[2:3] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s2 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s3 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX1064-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1064-DPP-NEXT: .LBB13_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_strictfp: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s10, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s11, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s8, s8, s3 +; GFX1032-DPP-NEXT: s_mov_b32 s3, exec_lo +; GFX1032-DPP-NEXT: s_addc_u32 s9, s9, 0 +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s3, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s4, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_bcnt1_i32_b32 s4, s3 +; GFX1032-DPP-NEXT: s_mov_b32 s5, 0x43300000 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, s[4:5] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s4 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s5 +; GFX1032-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX1032-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1032-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1032-DPP-NEXT: .LBB13_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_strictfp: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_bcnt1_i32_b64 s2, exec +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 0x43300000 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s2 +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b32 off, v0, off offset:4 +; GFX1164-DPP-NEXT: scratch_store_b32 off, v1, off +; GFX1164-DPP-NEXT: scratch_load_b64 v[0:1], off, off +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v2, exec_hi, v2 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b64 s[2:3], s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_2) +; GFX1164-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s2 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s3 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b64 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1164-DPP-NEXT: .LBB13_3: +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_agent_scope_strictfp: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_bcnt1_i32_b32 s2, exec_lo +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v0, 0x43300000 :: v_dual_mov_b32 v1, s2 +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b32 off, v0, off offset:4 +; GFX1132-DPP-NEXT: scratch_store_b32 off, v1, off +; GFX1132-DPP-NEXT: scratch_load_b64 v[0:1], off, off +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b64 s[4:5], s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_2) +; GFX1132-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v2, s4 :: v_dual_mov_b32 v3, s5 +; GFX1132-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_add_f64 v[0:1], v[2:3], v[4:5] +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b64 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, v1 :: v_dual_mov_b32 v2, v0 +; GFX1132-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1132-DPP-NEXT: .LBB13_3: +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fadd ptr addrspace(1) %ptr, double 4.0 syncscope("agent") monotonic + ret void +} + +define amdgpu_kernel void @global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe(ptr addrspace(1) %ptr) #0 { +; GFX7LESS-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_mov_b32 s32, 0 +; GFX7LESS-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s42, -1 +; GFX7LESS-NEXT: s_mov_b32 s43, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s40, s40, s9 +; GFX7LESS-NEXT: s_addc_u32 s41, s41, 0 +; GFX7LESS-NEXT: s_mov_b32 s14, s8 +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX7LESS-NEXT: s_load_dwordx2 s[36:37], s[2:3], 0x9 +; GFX7LESS-NEXT: s_mov_b32 s39, 0xf000 +; GFX7LESS-NEXT: s_mov_b32 s38, -1 +; GFX7LESS-NEXT: s_add_u32 s8, s2, 44 +; GFX7LESS-NEXT: s_addc_u32 s9, s3, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[2:3] +; GFX7LESS-NEXT: s_add_u32 s2, s2, div.double.value@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s3, s3, div.double.value@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v0, v0, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v31, v0, v2 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX7LESS-NEXT: s_mov_b32 s12, s6 +; GFX7LESS-NEXT: s_mov_b32 s13, s7 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX7LESS-NEXT: buffer_load_dwordx2 v[4:5], off, s[36:39], 0 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], 0 +; GFX7LESS-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v9, v5 +; GFX7LESS-NEXT: v_mov_b32_e32 v8, v4 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, v3 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, v2 +; GFX7LESS-NEXT: buffer_atomic_cmpswap_x2 v[6:9], off, s[36:39], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[4:5] +; GFX7LESS-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX7LESS-NEXT: v_mov_b32_e32 v4, v6 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, v7 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB14_1 +; GFX7LESS-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s38, -1 +; GFX9-NEXT: s_mov_b32 s39, 0xe00000 +; GFX9-NEXT: s_add_u32 s36, s36, s9 +; GFX9-NEXT: s_addc_u32 s37, s37, 0 +; GFX9-NEXT: s_mov_b32 s14, s8 +; GFX9-NEXT: s_add_u32 s8, s2, 44 +; GFX9-NEXT: s_addc_u32 s9, s3, 0 +; GFX9-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX9-NEXT: s_getpc_b64 s[2:3] +; GFX9-NEXT: s_add_u32 s2, s2, div.double.value@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s3, s3, div.double.value@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX9-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX9-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX9-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX9-NEXT: s_mov_b32 s12, s6 +; GFX9-NEXT: s_mov_b32 s13, s7 +; GFX9-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX9-NEXT: s_mov_b32 s32, 0 +; GFX9-NEXT: v_mov_b32_e32 v40, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX9-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX9-NEXT: s_mov_b64 s[0:1], 0 +; GFX9-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX9-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX9-NEXT: v_mov_b32_e32 v5, v3 +; GFX9-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX9-NEXT: v_mov_b32_e32 v4, v2 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX9-NEXT: s_cbranch_execnz .LBB14_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s38, -1 +; GFX1064-NEXT: s_mov_b32 s39, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s36, s36, s9 +; GFX1064-NEXT: s_addc_u32 s37, s37, 0 +; GFX1064-NEXT: s_mov_b32 s14, s8 +; GFX1064-NEXT: s_add_u32 s8, s2, 44 +; GFX1064-NEXT: s_addc_u32 s9, s3, 0 +; GFX1064-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1064-NEXT: s_getpc_b64 s[4:5] +; GFX1064-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1064-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1064-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1064-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1064-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1064-NEXT: s_mov_b32 s12, s6 +; GFX1064-NEXT: s_mov_b32 s13, s7 +; GFX1064-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1064-NEXT: s_mov_b32 s32, 0 +; GFX1064-NEXT: v_mov_b32_e32 v40, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1064-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1064-NEXT: s_mov_b64 s[0:1], 0 +; GFX1064-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1064-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1064-NEXT: v_mov_b32_e32 v5, v3 +; GFX1064-NEXT: v_mov_b32_e32 v4, v2 +; GFX1064-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX1064-NEXT: s_cbranch_execnz .LBB14_1 +; GFX1064-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s38, -1 +; GFX1032-NEXT: s_mov_b32 s39, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s36, s36, s9 +; GFX1032-NEXT: s_addc_u32 s37, s37, 0 +; GFX1032-NEXT: s_mov_b32 s14, s8 +; GFX1032-NEXT: s_add_u32 s8, s2, 44 +; GFX1032-NEXT: s_addc_u32 s9, s3, 0 +; GFX1032-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1032-NEXT: s_getpc_b64 s[4:5] +; GFX1032-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1032-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1032-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1032-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1032-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1032-NEXT: s_mov_b32 s12, s6 +; GFX1032-NEXT: s_mov_b32 s13, s7 +; GFX1032-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1032-NEXT: s_mov_b32 s32, 0 +; GFX1032-NEXT: v_mov_b32_e32 v40, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1032-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1032-NEXT: s_mov_b32 s0, 0 +; GFX1032-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1032-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1032-NEXT: v_mov_b32_e32 v5, v3 +; GFX1032-NEXT: v_mov_b32_e32 v4, v2 +; GFX1032-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s0 +; GFX1032-NEXT: s_cbranch_execnz .LBB14_1 +; GFX1032-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b32 s14, s8 +; GFX1164-NEXT: s_add_u32 s8, s2, 44 +; GFX1164-NEXT: s_addc_u32 s9, s3, 0 +; GFX1164-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1164-NEXT: s_getpc_b64 s[4:5] +; GFX1164-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1164-NEXT: s_load_b64 s[16:17], s[4:5], 0x0 +; GFX1164-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1164-NEXT: s_mov_b32 s12, s6 +; GFX1164-NEXT: s_mov_b32 s13, s7 +; GFX1164-NEXT: s_mov_b32 s32, 0 +; GFX1164-NEXT: v_mov_b32_e32 v40, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1164-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1164-NEXT: s_mov_b64 s[0:1], 0 +; GFX1164-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1164-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1164-NEXT: v_mov_b32_e32 v5, v3 +; GFX1164-NEXT: v_mov_b32_e32 v4, v2 +; GFX1164-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[0:1] +; GFX1164-NEXT: s_cbranch_execnz .LBB14_1 +; GFX1164-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_add_u32 s8, s2, 44 +; GFX1132-NEXT: s_addc_u32 s9, s3, 0 +; GFX1132-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1132-NEXT: s_getpc_b64 s[4:5] +; GFX1132-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1132-NEXT: s_load_b64 s[6:7], s[4:5], 0x0 +; GFX1132-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1132-NEXT: v_dual_mov_b32 v40, 0 :: v_dual_mov_b32 v31, v0 +; GFX1132-NEXT: s_mov_b32 s12, s13 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1132-NEXT: s_mov_b32 s13, s14 +; GFX1132-NEXT: s_mov_b32 s14, s15 +; GFX1132-NEXT: s_mov_b32 s32, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1132-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1132-NEXT: s_mov_b32 s0, 0 +; GFX1132-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1132-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1132-NEXT: v_dual_mov_b32 v5, v3 :: v_dual_mov_b32 v4, v2 +; GFX1132-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s0 +; GFX1132-NEXT: s_cbranch_execnz .LBB14_1 +; GFX1132-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s38, -1 +; GFX9-DPP-NEXT: s_mov_b32 s39, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX9-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX9-DPP-NEXT: s_mov_b32 s14, s8 +; GFX9-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX9-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX9-DPP-NEXT: s_getpc_b64 s[2:3] +; GFX9-DPP-NEXT: s_add_u32 s2, s2, div.double.value@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s3, s3, div.double.value@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX9-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX9-DPP-NEXT: s_mov_b32 s12, s6 +; GFX9-DPP-NEXT: s_mov_b32 s13, s7 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX9-DPP-NEXT: s_mov_b32 s32, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX9-DPP-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX9-DPP-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX9-DPP-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX9-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB14_1 +; GFX9-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s38, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s39, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX1064-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1064-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1064-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1064-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1064-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1064-DPP-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX1064-DPP-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1064-DPP-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX1064-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB14_1 +; GFX1064-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s38, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s39, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX1032-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1032-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1032-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1032-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1032-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1032-DPP-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1032-DPP-NEXT: s_mov_b32 s0, 0 +; GFX1032-DPP-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1032-DPP-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX1032-DPP-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s0 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB14_1 +; GFX1032-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1164-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1164-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1164-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: s_load_b64 s[16:17], s[4:5], 0x0 +; GFX1164-DPP-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1164-DPP-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1164-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX1164-DPP-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX1164-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[0:1] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB14_1 +; GFX1164-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1132-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1132-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: s_load_b64 s[6:7], s[4:5], 0x0 +; GFX1132-DPP-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v40, 0 :: v_dual_mov_b32 v31, v0 +; GFX1132-DPP-NEXT: s_mov_b32 s12, s13 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s13, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s15 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1132-DPP-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1132-DPP-NEXT: s_mov_b32 s0, 0 +; GFX1132-DPP-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, v3 :: v_dual_mov_b32 v4, v2 +; GFX1132-DPP-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s0 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB14_1 +; GFX1132-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-DPP-NEXT: s_endpgm + %divValue = call double @div.double.value() + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %divValue syncscope("agent") monotonic + ret void +} + +define amdgpu_kernel void @global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe_structfp(ptr addrspace(1) %ptr) #1 { +; GFX7LESS-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_mov_b32 s32, 0 +; GFX7LESS-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s42, -1 +; GFX7LESS-NEXT: s_mov_b32 s43, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s40, s40, s9 +; GFX7LESS-NEXT: s_addc_u32 s41, s41, 0 +; GFX7LESS-NEXT: s_mov_b32 s14, s8 +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX7LESS-NEXT: s_load_dwordx2 s[36:37], s[2:3], 0x9 +; GFX7LESS-NEXT: s_mov_b32 s39, 0xf000 +; GFX7LESS-NEXT: s_mov_b32 s38, -1 +; GFX7LESS-NEXT: s_add_u32 s8, s2, 44 +; GFX7LESS-NEXT: s_addc_u32 s9, s3, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[2:3] +; GFX7LESS-NEXT: s_add_u32 s2, s2, div.float.value@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s3, s3, div.float.value@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v0, v0, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v31, v0, v2 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX7LESS-NEXT: s_mov_b32 s12, s6 +; GFX7LESS-NEXT: s_mov_b32 s13, s7 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX7LESS-NEXT: buffer_load_dwordx2 v[4:5], off, s[36:39], 0 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], 0 +; GFX7LESS-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v9, v5 +; GFX7LESS-NEXT: v_mov_b32_e32 v8, v4 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, v3 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, v2 +; GFX7LESS-NEXT: buffer_atomic_cmpswap_x2 v[6:9], off, s[36:39], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[4:5] +; GFX7LESS-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX7LESS-NEXT: v_mov_b32_e32 v4, v6 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, v7 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB15_1 +; GFX7LESS-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s38, -1 +; GFX9-NEXT: s_mov_b32 s39, 0xe00000 +; GFX9-NEXT: s_add_u32 s36, s36, s9 +; GFX9-NEXT: s_addc_u32 s37, s37, 0 +; GFX9-NEXT: s_mov_b32 s14, s8 +; GFX9-NEXT: s_add_u32 s8, s2, 44 +; GFX9-NEXT: s_addc_u32 s9, s3, 0 +; GFX9-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX9-NEXT: s_getpc_b64 s[2:3] +; GFX9-NEXT: s_add_u32 s2, s2, div.float.value@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s3, s3, div.float.value@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX9-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX9-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX9-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX9-NEXT: s_mov_b32 s12, s6 +; GFX9-NEXT: s_mov_b32 s13, s7 +; GFX9-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX9-NEXT: s_mov_b32 s32, 0 +; GFX9-NEXT: v_mov_b32_e32 v40, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX9-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX9-NEXT: s_mov_b64 s[0:1], 0 +; GFX9-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX9-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX9-NEXT: v_mov_b32_e32 v5, v3 +; GFX9-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX9-NEXT: v_mov_b32_e32 v4, v2 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX9-NEXT: s_cbranch_execnz .LBB15_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s38, -1 +; GFX1064-NEXT: s_mov_b32 s39, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s36, s36, s9 +; GFX1064-NEXT: s_addc_u32 s37, s37, 0 +; GFX1064-NEXT: s_mov_b32 s14, s8 +; GFX1064-NEXT: s_add_u32 s8, s2, 44 +; GFX1064-NEXT: s_addc_u32 s9, s3, 0 +; GFX1064-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1064-NEXT: s_getpc_b64 s[4:5] +; GFX1064-NEXT: s_add_u32 s4, s4, div.float.value@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s5, s5, div.float.value@gotpcrel32@hi+12 +; GFX1064-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1064-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1064-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1064-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1064-NEXT: s_mov_b32 s12, s6 +; GFX1064-NEXT: s_mov_b32 s13, s7 +; GFX1064-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1064-NEXT: s_mov_b32 s32, 0 +; GFX1064-NEXT: v_mov_b32_e32 v40, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1064-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1064-NEXT: s_mov_b64 s[0:1], 0 +; GFX1064-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1064-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1064-NEXT: v_mov_b32_e32 v5, v3 +; GFX1064-NEXT: v_mov_b32_e32 v4, v2 +; GFX1064-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX1064-NEXT: s_cbranch_execnz .LBB15_1 +; GFX1064-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s38, -1 +; GFX1032-NEXT: s_mov_b32 s39, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s36, s36, s9 +; GFX1032-NEXT: s_addc_u32 s37, s37, 0 +; GFX1032-NEXT: s_mov_b32 s14, s8 +; GFX1032-NEXT: s_add_u32 s8, s2, 44 +; GFX1032-NEXT: s_addc_u32 s9, s3, 0 +; GFX1032-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1032-NEXT: s_getpc_b64 s[4:5] +; GFX1032-NEXT: s_add_u32 s4, s4, div.float.value@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s5, s5, div.float.value@gotpcrel32@hi+12 +; GFX1032-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1032-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1032-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1032-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1032-NEXT: s_mov_b32 s12, s6 +; GFX1032-NEXT: s_mov_b32 s13, s7 +; GFX1032-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1032-NEXT: s_mov_b32 s32, 0 +; GFX1032-NEXT: v_mov_b32_e32 v40, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1032-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1032-NEXT: s_mov_b32 s0, 0 +; GFX1032-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1032-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1032-NEXT: v_mov_b32_e32 v5, v3 +; GFX1032-NEXT: v_mov_b32_e32 v4, v2 +; GFX1032-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s0 +; GFX1032-NEXT: s_cbranch_execnz .LBB15_1 +; GFX1032-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b32 s14, s8 +; GFX1164-NEXT: s_add_u32 s8, s2, 44 +; GFX1164-NEXT: s_addc_u32 s9, s3, 0 +; GFX1164-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1164-NEXT: s_getpc_b64 s[4:5] +; GFX1164-NEXT: s_add_u32 s4, s4, div.float.value@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s5, s5, div.float.value@gotpcrel32@hi+12 +; GFX1164-NEXT: s_load_b64 s[16:17], s[4:5], 0x0 +; GFX1164-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1164-NEXT: s_mov_b32 s12, s6 +; GFX1164-NEXT: s_mov_b32 s13, s7 +; GFX1164-NEXT: s_mov_b32 s32, 0 +; GFX1164-NEXT: v_mov_b32_e32 v40, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1164-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1164-NEXT: s_mov_b64 s[0:1], 0 +; GFX1164-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1164-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1164-NEXT: v_mov_b32_e32 v5, v3 +; GFX1164-NEXT: v_mov_b32_e32 v4, v2 +; GFX1164-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[0:1] +; GFX1164-NEXT: s_cbranch_execnz .LBB15_1 +; GFX1164-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_add_u32 s8, s2, 44 +; GFX1132-NEXT: s_addc_u32 s9, s3, 0 +; GFX1132-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1132-NEXT: s_getpc_b64 s[4:5] +; GFX1132-NEXT: s_add_u32 s4, s4, div.float.value@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s5, s5, div.float.value@gotpcrel32@hi+12 +; GFX1132-NEXT: s_load_b64 s[6:7], s[4:5], 0x0 +; GFX1132-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1132-NEXT: v_dual_mov_b32 v40, 0 :: v_dual_mov_b32 v31, v0 +; GFX1132-NEXT: s_mov_b32 s12, s13 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1132-NEXT: s_mov_b32 s13, s14 +; GFX1132-NEXT: s_mov_b32 s14, s15 +; GFX1132-NEXT: s_mov_b32 s32, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1132-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1132-NEXT: s_mov_b32 s0, 0 +; GFX1132-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1132-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1132-NEXT: v_dual_mov_b32 v5, v3 :: v_dual_mov_b32 v4, v2 +; GFX1132-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s0 +; GFX1132-NEXT: s_cbranch_execnz .LBB15_1 +; GFX1132-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s38, -1 +; GFX9-DPP-NEXT: s_mov_b32 s39, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX9-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX9-DPP-NEXT: s_mov_b32 s14, s8 +; GFX9-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX9-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX9-DPP-NEXT: s_getpc_b64 s[2:3] +; GFX9-DPP-NEXT: s_add_u32 s2, s2, div.float.value@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s3, s3, div.float.value@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX9-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX9-DPP-NEXT: s_mov_b32 s12, s6 +; GFX9-DPP-NEXT: s_mov_b32 s13, s7 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX9-DPP-NEXT: s_mov_b32 s32, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX9-DPP-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX9-DPP-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX9-DPP-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX9-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB15_1 +; GFX9-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s38, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s39, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX1064-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1064-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1064-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1064-DPP-NEXT: s_add_u32 s4, s4, div.float.value@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s5, s5, div.float.value@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1064-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1064-DPP-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX1064-DPP-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1064-DPP-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX1064-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB15_1 +; GFX1064-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s38, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s39, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX1032-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1032-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1032-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1032-DPP-NEXT: s_add_u32 s4, s4, div.float.value@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s5, s5, div.float.value@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1032-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1032-DPP-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1032-DPP-NEXT: s_mov_b32 s0, 0 +; GFX1032-DPP-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1032-DPP-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX1032-DPP-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s0 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB15_1 +; GFX1032-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1164-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1164-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1164-DPP-NEXT: s_add_u32 s4, s4, div.float.value@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s5, s5, div.float.value@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: s_load_b64 s[16:17], s[4:5], 0x0 +; GFX1164-DPP-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1164-DPP-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1164-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX1164-DPP-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX1164-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[0:1] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB15_1 +; GFX1164-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1132-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1132-DPP-NEXT: s_add_u32 s4, s4, div.float.value@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s5, s5, div.float.value@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: s_load_b64 s[6:7], s[4:5], 0x0 +; GFX1132-DPP-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v40, 0 :: v_dual_mov_b32 v31, v0 +; GFX1132-DPP-NEXT: s_mov_b32 s12, s13 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s13, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s15 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1132-DPP-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1132-DPP-NEXT: s_mov_b32 s0, 0 +; GFX1132-DPP-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_add_f64 v[2:3], v[4:5], v[0:1] +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, v3 :: v_dual_mov_b32 v4, v2 +; GFX1132-DPP-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s0 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB15_1 +; GFX1132-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-DPP-NEXT: s_endpgm + %divValue = call double @div.float.value() strictfp + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %divValue syncscope("agent") monotonic + ret void +} + +define amdgpu_kernel void @global_atomic_fadd_double_uni_address_uni_value_defalut_scope_strictfp(ptr addrspace(1) %ptr) #2 { +; GFX7LESS-LABEL: global_atomic_fadd_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_movk_i32 s32, 0x800 +; GFX7LESS-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s42, -1 +; GFX7LESS-NEXT: s_mov_b32 s43, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s40, s40, s3 +; GFX7LESS-NEXT: s_addc_u32 s41, s41, 0 +; GFX7LESS-NEXT: s_mov_b32 s33, s2 +; GFX7LESS-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX7LESS-NEXT: v_mov_b32_e32 v40, v0 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], exec +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, s0, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, s1, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB16_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x9 +; GFX7LESS-NEXT: s_bcnt1_i32_b64 s0, s[0:1] +; GFX7LESS-NEXT: s_mov_b32 s1, 0x43300000 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dwordx2 s[2:3], s[36:37], 0x0 +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0xc3300000 +; GFX7LESS-NEXT: v_add_f64 v[0:1], s[0:1], v[0:1] +; GFX7LESS-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX7LESS-NEXT: s_mov_b64 s[38:39], 0 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, s2 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, s3 +; GFX7LESS-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_add_f64 v[2:3], v[0:1], v[41:42] +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[40:43], 0 offset:4 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[40:43], 0 +; GFX7LESS-NEXT: s_add_u32 s8, s34, 44 +; GFX7LESS-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:12 +; GFX7LESS-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:8 +; GFX7LESS-NEXT: s_addc_u32 s9, s35, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX7LESS-NEXT: s_waitcnt expcnt(2) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v4, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, 0 +; GFX7LESS-NEXT: s_mov_b32 s12, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v40 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s36 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s37 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX7LESS-NEXT: v_and_b32_e32 v2, 1, v0 +; GFX7LESS-NEXT: buffer_load_dword v0, off, s[40:43], 0 +; GFX7LESS-NEXT: buffer_load_dword v1, off, s[40:43], 0 offset:4 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 1, v2 +; GFX7LESS-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB16_2 +; GFX7LESS-NEXT: .LBB16_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fadd_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s42, -1 +; GFX9-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX9-NEXT: s_mov_b64 s[0:1], exec +; GFX9-NEXT: s_mov_b32 s43, 0xe00000 +; GFX9-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, s0, 0 +; GFX9-NEXT: s_add_u32 s40, s40, s3 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, s1, v0 +; GFX9-NEXT: s_addc_u32 s41, s41, 0 +; GFX9-NEXT: s_mov_b32 s33, s2 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_movk_i32 s32, 0x800 +; GFX9-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-NEXT: s_cbranch_execz .LBB16_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: v_mov_b32_e32 v0, 0 +; GFX9-NEXT: s_bcnt1_i32_b64 s0, s[0:1] +; GFX9-NEXT: v_mov_b32_e32 v1, 0xc3300000 +; GFX9-NEXT: s_mov_b32 s1, 0x43300000 +; GFX9-NEXT: v_add_f64 v[0:1], s[0:1], v[0:1] +; GFX9-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX9-NEXT: s_mov_b64 s[38:39], 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX9-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, s1 +; GFX9-NEXT: v_mov_b32_e32 v1, s0 +; GFX9-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX9-NEXT: s_add_u32 s8, s34, 44 +; GFX9-NEXT: s_addc_u32 s9, s35, 0 +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX9-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX9-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX9-NEXT: s_mov_b32 s12, s33 +; GFX9-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX9-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX9-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX9-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: v_mov_b32_e32 v2, s36 +; GFX9-NEXT: v_mov_b32_e32 v3, s37 +; GFX9-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX9-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX9-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX9-NEXT: s_cbranch_execnz .LBB16_2 +; GFX9-NEXT: .LBB16_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fadd_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s42, -1 +; GFX1064-NEXT: s_mov_b32 s43, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s40, s40, s3 +; GFX1064-NEXT: s_mov_b32 s33, s2 +; GFX1064-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-NEXT: s_addc_u32 s41, s41, 0 +; GFX1064-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1064-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB16_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_bcnt1_i32_b64 s0, s[2:3] +; GFX1064-NEXT: s_mov_b32 s1, 0x43300000 +; GFX1064-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1064-NEXT: v_add_f64 v[0:1], 0xc3300000, s[0:1] +; GFX1064-NEXT: s_mov_b64 s[38:39], 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1064-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v2, s1 +; GFX1064-NEXT: v_mov_b32_e32 v1, s0 +; GFX1064-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1064-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1064-NEXT: s_mov_b32 s12, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1064-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1064-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1064-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1064-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-NEXT: v_mov_b32_e32 v2, s36 +; GFX1064-NEXT: v_mov_b32_e32 v3, s37 +; GFX1064-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1064-NEXT: s_clause 0x1 +; GFX1064-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1064-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX1064-NEXT: s_cbranch_execnz .LBB16_2 +; GFX1064-NEXT: .LBB16_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fadd_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s33, s2 +; GFX1032-NEXT: s_mov_b32 s2, exec_lo +; GFX1032-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1032-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s42, -1 +; GFX1032-NEXT: s_mov_b32 s43, 0x31c16000 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_add_u32 s40, s40, s3 +; GFX1032-NEXT: s_addc_u32 s41, s41, 0 +; GFX1032-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1032-NEXT: s_mov_b32 s38, 0 +; GFX1032-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-NEXT: s_and_saveexec_b32 s0, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB16_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_bcnt1_i32_b32 s0, s2 +; GFX1032-NEXT: s_mov_b32 s1, 0x43300000 +; GFX1032-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1032-NEXT: v_add_f64 v[0:1], 0xc3300000, s[0:1] +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1032-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v2, s1 +; GFX1032-NEXT: v_mov_b32_e32 v1, s0 +; GFX1032-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1032-NEXT: s_mov_b32 s12, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1032-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1032-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1032-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1032-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-NEXT: v_mov_b32_e32 v2, s36 +; GFX1032-NEXT: v_mov_b32_e32 v3, s37 +; GFX1032-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1032-NEXT: s_clause 0x1 +; GFX1032-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1032-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s38 +; GFX1032-NEXT: s_cbranch_execnz .LBB16_2 +; GFX1032-NEXT: .LBB16_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fadd_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1164-NEXT: s_bcnt1_i32_b64 s0, exec +; GFX1164-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-NEXT: v_mov_b32_e32 v0, 0x43300000 +; GFX1164-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b32 off, v0, off offset:20 +; GFX1164-NEXT: scratch_store_b32 off, v1, off offset:16 +; GFX1164-NEXT: scratch_load_b64 v[0:1], off, off offset:16 +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v2, exec_hi, v2 +; GFX1164-NEXT: s_mov_b32 s32, 32 +; GFX1164-NEXT: s_mov_b64 s[0:1], exec +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1164-NEXT: s_cbranch_execz .LBB16_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1164-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1164-NEXT: s_mov_b32 s33, s2 +; GFX1164-NEXT: s_mov_b64 s[38:39], 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v2, s1 +; GFX1164-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-NEXT: .p2align 6 +; GFX1164-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-NEXT: s_mov_b32 s12, s33 +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-NEXT: v_mov_b32_e32 v2, s36 +; GFX1164-NEXT: v_mov_b32_e32 v3, s37 +; GFX1164-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[38:39] +; GFX1164-NEXT: s_cbranch_execnz .LBB16_2 +; GFX1164-NEXT: .LBB16_3: +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fadd_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1132-NEXT: s_bcnt1_i32_b32 s0, exec_lo +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v1, s0 +; GFX1132-NEXT: v_mov_b32_e32 v0, 0x43300000 +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b32 off, v0, off offset:20 +; GFX1132-NEXT: scratch_store_b32 off, v1, off offset:16 +; GFX1132-NEXT: scratch_load_b64 v[0:1], off, off offset:16 +; GFX1132-NEXT: s_mov_b32 s38, 0 +; GFX1132-NEXT: s_mov_b32 s32, 32 +; GFX1132-NEXT: s_mov_b32 s0, exec_lo +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1132-NEXT: s_cbranch_execz .LBB16_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1132-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1132-NEXT: s_mov_b32 s33, s15 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: v_dual_mov_b32 v2, s1 :: v_dual_mov_b32 v1, s0 +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-NEXT: .p2align 6 +; GFX1132-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-NEXT: v_dual_mov_b32 v31, v40 :: v_dual_mov_b32 v0, 8 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-NEXT: s_mov_b32 s12, s33 +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s36 +; GFX1132-NEXT: v_dual_mov_b32 v3, s37 :: v_dual_mov_b32 v4, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s38 +; GFX1132-NEXT: s_cbranch_execnz .LBB16_2 +; GFX1132-NEXT: .LBB16_3: +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s42, -1 +; GFX9-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], exec +; GFX9-DPP-NEXT: s_mov_b32 s43, 0xe00000 +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s0, 0 +; GFX9-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s1, v0 +; GFX9-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX9-DPP-NEXT: s_mov_b32 s33, s2 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB16_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 0 +; GFX9-DPP-NEXT: s_bcnt1_i32_b64 s0, s[0:1] +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0xc3300000 +; GFX9-DPP-NEXT: s_mov_b32 s1, 0x43300000 +; GFX9-DPP-NEXT: v_add_f64 v[0:1], s[0:1], v[0:1] +; GFX9-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX9-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX9-DPP-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX9-DPP-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX9-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX9-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX9-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX9-DPP-NEXT: s_mov_b32 s12, s33 +; GFX9-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX9-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX9-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX9-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX9-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB16_2 +; GFX9-DPP-NEXT: .LBB16_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s42, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s43, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX1064-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1064-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB16_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_bcnt1_i32_b64 s0, s[2:3] +; GFX1064-DPP-NEXT: s_mov_b32 s1, 0x43300000 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1064-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, s[0:1] +; GFX1064-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1064-DPP-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1064-DPP-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1064-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1064-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1064-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1064-DPP-NEXT: s_clause 0x1 +; GFX1064-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1064-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB16_2 +; GFX1064-DPP-NEXT: .LBB16_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1032-DPP-NEXT: s_mov_b32 s2, exec_lo +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s42, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s43, 0x31c16000 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX1032-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1032-DPP-NEXT: s_mov_b32 s38, 0 +; GFX1032-DPP-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s0, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB16_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_bcnt1_i32_b32 s0, s2 +; GFX1032-DPP-NEXT: s_mov_b32 s1, 0x43300000 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1032-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, s[0:1] +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1032-DPP-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1032-DPP-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1032-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1032-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1032-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1032-DPP-NEXT: s_clause 0x1 +; GFX1032-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1032-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s38 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB16_2 +; GFX1032-DPP-NEXT: .LBB16_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1164-DPP-NEXT: s_bcnt1_i32_b64 s0, exec +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 0x43300000 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b32 off, v0, off offset:20 +; GFX1164-DPP-NEXT: scratch_store_b32 off, v1, off offset:16 +; GFX1164-DPP-NEXT: scratch_load_b64 v[0:1], off, off offset:16 +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v2, exec_hi, v2 +; GFX1164-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1164-DPP-NEXT: s_mov_b64 s[0:1], exec +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB16_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1164-DPP-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1164-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1164-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-DPP-NEXT: .p2align 6 +; GFX1164-DPP-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[38:39] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB16_2 +; GFX1164-DPP-NEXT: .LBB16_3: +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fadd_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1132-DPP-NEXT: s_bcnt1_i32_b32 s0, exec_lo +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v1, s0 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v0, 0x43300000 +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b32 off, v0, off offset:20 +; GFX1132-DPP-NEXT: scratch_store_b32 off, v1, off offset:16 +; GFX1132-DPP-NEXT: scratch_load_b64 v[0:1], off, off offset:16 +; GFX1132-DPP-NEXT: s_mov_b32 s38, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1132-DPP-NEXT: s_mov_b32 s0, exec_lo +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB16_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1132-DPP-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1132-DPP-NEXT: s_mov_b32 s33, s15 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v2, s1 :: v_dual_mov_b32 v1, s0 +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-DPP-NEXT: .p2align 6 +; GFX1132-DPP-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[41:42] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v31, v40 :: v_dual_mov_b32 v0, 8 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s36 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, s37 :: v_dual_mov_b32 v4, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s38 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB16_2 +; GFX1132-DPP-NEXT: .LBB16_3: +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fadd ptr addrspace(1) %ptr, double 4.0 monotonic, align 4 + ret void +} + +define amdgpu_kernel void @global_atomic_fadd_double_uni_address_div_value_defalut_scope_strictfp(ptr addrspace(1) %ptr) #2 { +; GFX7LESS-LABEL: global_atomic_fadd_double_uni_address_div_value_defalut_scope_strictfp: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_movk_i32 s32, 0x800 +; GFX7LESS-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s50, -1 +; GFX7LESS-NEXT: s_mov_b32 s51, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s48, s48, s9 +; GFX7LESS-NEXT: s_addc_u32 s49, s49, 0 +; GFX7LESS-NEXT: s_mov_b32 s33, s8 +; GFX7LESS-NEXT: s_mov_b32 s40, s7 +; GFX7LESS-NEXT: s_mov_b32 s41, s6 +; GFX7LESS-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX7LESS-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX7LESS-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX7LESS-NEXT: s_load_dwordx2 s[44:45], s[2:3], 0x9 +; GFX7LESS-NEXT: s_mov_b32 s47, 0xf000 +; GFX7LESS-NEXT: s_mov_b32 s46, -1 +; GFX7LESS-NEXT: s_add_u32 s8, s36, 44 +; GFX7LESS-NEXT: s_addc_u32 s9, s37, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v0, v0, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v42, v0, v2 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX7LESS-NEXT: s_mov_b32 s12, s41 +; GFX7LESS-NEXT: s_mov_b32 s13, s40 +; GFX7LESS-NEXT: s_mov_b32 s14, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v42 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX7LESS-NEXT: v_mov_b32_e32 v40, v0 +; GFX7LESS-NEXT: v_mov_b32_e32 v41, v1 +; GFX7LESS-NEXT: buffer_load_dwordx2 v[0:1], off, s[44:47], 0 +; GFX7LESS-NEXT: s_mov_b64 s[42:43], 0 +; GFX7LESS-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_add_f64 v[2:3], v[0:1], v[40:41] +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:4 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[48:51], 0 +; GFX7LESS-NEXT: s_add_u32 s8, s36, 44 +; GFX7LESS-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:12 +; GFX7LESS-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:8 +; GFX7LESS-NEXT: s_addc_u32 s9, s37, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX7LESS-NEXT: s_waitcnt expcnt(2) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v4, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, 0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX7LESS-NEXT: s_mov_b32 s12, s41 +; GFX7LESS-NEXT: s_mov_b32 s13, s40 +; GFX7LESS-NEXT: s_mov_b32 s14, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v42 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s44 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s45 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX7LESS-NEXT: v_and_b32_e32 v2, 1, v0 +; GFX7LESS-NEXT: buffer_load_dword v0, off, s[48:51], 0 +; GFX7LESS-NEXT: buffer_load_dword v1, off, s[48:51], 0 offset:4 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 1, v2 +; GFX7LESS-NEXT: s_or_b64 s[42:43], vcc, s[42:43] +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[42:43] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB17_1 +; GFX7LESS-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fadd_double_uni_address_div_value_defalut_scope_strictfp: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s50, -1 +; GFX9-NEXT: s_mov_b32 s51, 0xe00000 +; GFX9-NEXT: s_add_u32 s48, s48, s9 +; GFX9-NEXT: s_addc_u32 s49, s49, 0 +; GFX9-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX9-NEXT: s_mov_b32 s33, s8 +; GFX9-NEXT: s_add_u32 s8, s36, 44 +; GFX9-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX9-NEXT: s_mov_b32 s40, s7 +; GFX9-NEXT: s_mov_b32 s41, s6 +; GFX9-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX9-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX9-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-NEXT: s_mov_b32 s12, s41 +; GFX9-NEXT: s_mov_b32 s13, s40 +; GFX9-NEXT: s_mov_b32 s14, s33 +; GFX9-NEXT: v_mov_b32_e32 v31, v42 +; GFX9-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-NEXT: s_movk_i32 s32, 0x800 +; GFX9-NEXT: v_mov_b32_e32 v43, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-NEXT: v_mov_b32_e32 v41, v1 +; GFX9-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX9-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-NEXT: s_mov_b64 s[44:45], 0 +; GFX9-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX9-NEXT: s_add_u32 s8, s36, 44 +; GFX9-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX9-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX9-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX9-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX9-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-NEXT: s_mov_b32 s12, s41 +; GFX9-NEXT: s_mov_b32 s13, s40 +; GFX9-NEXT: s_mov_b32 s14, s33 +; GFX9-NEXT: v_mov_b32_e32 v31, v42 +; GFX9-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: v_mov_b32_e32 v2, s42 +; GFX9-NEXT: v_mov_b32_e32 v3, s43 +; GFX9-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX9-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX9-NEXT: s_cbranch_execnz .LBB17_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fadd_double_uni_address_div_value_defalut_scope_strictfp: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s50, -1 +; GFX1064-NEXT: s_mov_b32 s51, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s48, s48, s9 +; GFX1064-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1064-NEXT: s_addc_u32 s49, s49, 0 +; GFX1064-NEXT: s_mov_b32 s33, s8 +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1064-NEXT: s_mov_b32 s40, s7 +; GFX1064-NEXT: s_mov_b32 s41, s6 +; GFX1064-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1064-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1064-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX1064-NEXT: s_mov_b32 s12, s41 +; GFX1064-NEXT: s_mov_b32 s13, s40 +; GFX1064-NEXT: s_mov_b32 s14, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-NEXT: v_mov_b32_e32 v31, v42 +; GFX1064-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-NEXT: v_mov_b32_e32 v43, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-NEXT: v_mov_b32_e32 v41, v1 +; GFX1064-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX1064-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-NEXT: s_mov_b64 s[44:45], 0 +; GFX1064-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX1064-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX1064-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-NEXT: v_mov_b32_e32 v31, v42 +; GFX1064-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-NEXT: v_mov_b32_e32 v2, s42 +; GFX1064-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-NEXT: s_mov_b32 s12, s41 +; GFX1064-NEXT: s_mov_b32 s13, s40 +; GFX1064-NEXT: s_mov_b32 s14, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX1064-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX1064-NEXT: v_mov_b32_e32 v3, s43 +; GFX1064-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-NEXT: s_clause 0x1 +; GFX1064-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX1064-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX1064-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX1064-NEXT: s_cbranch_execnz .LBB17_1 +; GFX1064-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fadd_double_uni_address_div_value_defalut_scope_strictfp: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s50, -1 +; GFX1032-NEXT: s_mov_b32 s51, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s48, s48, s9 +; GFX1032-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1032-NEXT: s_addc_u32 s49, s49, 0 +; GFX1032-NEXT: s_mov_b32 s33, s8 +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1032-NEXT: s_mov_b32 s40, s7 +; GFX1032-NEXT: s_mov_b32 s41, s6 +; GFX1032-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1032-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1032-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX1032-NEXT: s_mov_b32 s12, s41 +; GFX1032-NEXT: s_mov_b32 s13, s40 +; GFX1032-NEXT: s_mov_b32 s14, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-NEXT: v_mov_b32_e32 v31, v42 +; GFX1032-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-NEXT: v_mov_b32_e32 v43, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-NEXT: v_mov_b32_e32 v41, v1 +; GFX1032-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX1032-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-NEXT: s_mov_b32 s44, 0 +; GFX1032-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX1032-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX1032-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-NEXT: v_mov_b32_e32 v31, v42 +; GFX1032-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-NEXT: v_mov_b32_e32 v2, s42 +; GFX1032-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-NEXT: s_mov_b32 s12, s41 +; GFX1032-NEXT: s_mov_b32 s13, s40 +; GFX1032-NEXT: s_mov_b32 s14, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX1032-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX1032-NEXT: v_mov_b32_e32 v3, s43 +; GFX1032-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-NEXT: s_clause 0x1 +; GFX1032-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX1032-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX1032-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s44 +; GFX1032-NEXT: s_cbranch_execnz .LBB17_1 +; GFX1032-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fadd_double_uni_address_div_value_defalut_scope_strictfp: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1164-NEXT: s_mov_b32 s33, s8 +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1164-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-NEXT: s_mov_b32 s12, s6 +; GFX1164-NEXT: s_mov_b32 s13, s7 +; GFX1164-NEXT: s_mov_b32 s14, s33 +; GFX1164-NEXT: s_mov_b32 s32, 32 +; GFX1164-NEXT: v_mov_b32_e32 v42, v0 +; GFX1164-NEXT: s_mov_b32 s40, s7 +; GFX1164-NEXT: s_mov_b32 s41, s6 +; GFX1164-NEXT: v_mov_b32_e32 v43, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: v_mov_b32_e32 v41, v1 +; GFX1164-NEXT: global_load_b64 v[1:2], v43, s[42:43] +; GFX1164-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-NEXT: s_mov_b64 s[44:45], 0 +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-NEXT: .p2align 6 +; GFX1164-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-NEXT: v_mov_b32_e32 v31, v42 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-NEXT: s_mov_b32 s12, s41 +; GFX1164-NEXT: s_mov_b32 s13, s40 +; GFX1164-NEXT: s_mov_b32 s14, s33 +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-NEXT: v_mov_b32_e32 v2, s42 +; GFX1164-NEXT: v_mov_b32_e32 v3, s43 +; GFX1164-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[44:45] +; GFX1164-NEXT: s_cbranch_execnz .LBB17_1 +; GFX1164-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fadd_double_uni_address_div_value_defalut_scope_strictfp: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1132-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1132-NEXT: v_mov_b32_e32 v31, v0 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1132-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1132-NEXT: s_mov_b32 s40, s14 +; GFX1132-NEXT: s_mov_b32 s41, s13 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-NEXT: s_mov_b32 s12, s13 +; GFX1132-NEXT: s_mov_b32 s13, s14 +; GFX1132-NEXT: s_mov_b32 s14, s15 +; GFX1132-NEXT: s_mov_b32 s32, 32 +; GFX1132-NEXT: s_mov_b32 s33, s15 +; GFX1132-NEXT: v_dual_mov_b32 v42, v0 :: v_dual_mov_b32 v43, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v41, v1 +; GFX1132-NEXT: global_load_b64 v[1:2], v43, s[42:43] +; GFX1132-NEXT: s_mov_b32 s44, 0 +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-NEXT: .p2align 6 +; GFX1132-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-NEXT: v_dual_mov_b32 v31, v42 :: v_dual_mov_b32 v0, 8 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-NEXT: s_mov_b32 s12, s41 +; GFX1132-NEXT: s_mov_b32 s13, s40 +; GFX1132-NEXT: s_mov_b32 s14, s33 +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s42 +; GFX1132-NEXT: v_dual_mov_b32 v3, s43 :: v_dual_mov_b32 v4, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s44 +; GFX1132-NEXT: s_cbranch_execnz .LBB17_1 +; GFX1132-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_defalut_scope_strictfp: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s50, -1 +; GFX9-DPP-NEXT: s_mov_b32 s51, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX9-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX9-DPP-NEXT: s_mov_b32 s33, s8 +; GFX9-DPP-NEXT: s_add_u32 s8, s36, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_mov_b32 s40, s7 +; GFX9-DPP-NEXT: s_mov_b32 s41, s6 +; GFX9-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-DPP-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX9-DPP-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-DPP-NEXT: s_mov_b32 s12, s41 +; GFX9-DPP-NEXT: s_mov_b32 s13, s40 +; GFX9-DPP-NEXT: s_mov_b32 s14, s33 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX9-DPP-NEXT: v_mov_b32_e32 v43, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-DPP-NEXT: v_mov_b32_e32 v41, v1 +; GFX9-DPP-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX9-DPP-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX9-DPP-NEXT: s_add_u32 s8, s36, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX9-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-DPP-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX9-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-DPP-NEXT: s_mov_b32 s12, s41 +; GFX9-DPP-NEXT: s_mov_b32 s13, s40 +; GFX9-DPP-NEXT: s_mov_b32 s14, s33 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-DPP-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX9-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX9-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB17_1 +; GFX9-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_defalut_scope_strictfp: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s50, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s51, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX1064-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1064-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1064-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-DPP-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX1064-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1064-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v43, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v41, v1 +; GFX1064-DPP-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX1064-DPP-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX1064-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-DPP-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX1064-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-DPP-NEXT: s_clause 0x1 +; GFX1064-DPP-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX1064-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX1064-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB17_1 +; GFX1064-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_defalut_scope_strictfp: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s50, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s51, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX1032-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1032-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1032-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-DPP-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX1032-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1032-DPP-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v43, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v41, v1 +; GFX1032-DPP-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-DPP-NEXT: s_mov_b32 s44, 0 +; GFX1032-DPP-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX1032-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-DPP-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX1032-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-DPP-NEXT: s_clause 0x1 +; GFX1032-DPP-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX1032-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX1032-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s44 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB17_1 +; GFX1032-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_defalut_scope_strictfp: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1164-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1164-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v42, v0 +; GFX1164-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v43, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v41, v1 +; GFX1164-DPP-NEXT: global_load_b64 v[1:2], v43, s[42:43] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-DPP-NEXT: .p2align 6 +; GFX1164-DPP-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1164-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[44:45] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB17_1 +; GFX1164-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fadd_double_uni_address_div_value_defalut_scope_strictfp: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1132-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1132-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1132-DPP-NEXT: s_mov_b32 s40, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s41, s13 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-DPP-NEXT: s_mov_b32 s12, s13 +; GFX1132-DPP-NEXT: s_mov_b32 s13, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s15 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1132-DPP-NEXT: s_mov_b32 s33, s15 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v42, v0 :: v_dual_mov_b32 v43, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v41, v1 +; GFX1132-DPP-NEXT: global_load_b64 v[1:2], v43, s[42:43] +; GFX1132-DPP-NEXT: s_mov_b32 s44, 0 +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-DPP-NEXT: .p2align 6 +; GFX1132-DPP-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_add_f64 v[3:4], v[1:2], v[40:41] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v31, v42 :: v_dual_mov_b32 v0, 8 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1132-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s42 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, s43 :: v_dual_mov_b32 v4, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s44 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB17_1 +; GFX1132-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-DPP-NEXT: s_endpgm + %divValue = call double @div.float.value() strictfp + %result = atomicrmw fadd ptr addrspace(1) %ptr, double %divValue monotonic, align 4 + ret void +} + attributes #0 = { "denormal-fp-math-f32"="preserve-sign,preserve-sign" "amdgpu-unsafe-fp-atomics"="true" } attributes #1 = { strictfp "denormal-fp-math-f32"="preserve-sign,preserve-sign" "amdgpu-unsafe-fp-atomics"="true" } attributes #2 = { strictfp} diff --git a/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fmax.ll b/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fmax.ll index 3cc5a4cd1d0aa1fc120194d4ec9f9fee5c6d5c31..622be43e7442912e5005f43b3a179e84508a53e9 100644 --- a/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fmax.ll +++ b/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fmax.ll @@ -13,6 +13,7 @@ ; RUN: llc -mtriple=amdgcn -mcpu=gfx1100 -mattr=+wavefrontsize32,-wavefrontsize64 -amdgpu-atomic-optimizer-strategy=DPP -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GFX1132-DPP %s declare float @div.float.value() +declare float @div.double.value() define amdgpu_kernel void @global_atomic_fmax_uni_address_uni_value_agent_scope_unsafe(ptr addrspace(1) %ptr) #0 { ; GFX7LESS-LABEL: global_atomic_fmax_uni_address_uni_value_agent_scope_unsafe: @@ -3550,6 +3551,3965 @@ define amdgpu_kernel void @global_atomic_fmax_uni_address_div_value_defalut_scop ret void } +define amdgpu_kernel void @global_atomic_fmax_double_uni_address_uni_value_agent_scope_unsafe(ptr addrspace(1) %ptr) #0 { +; GFX7LESS-LABEL: global_atomic_fmax_double_uni_address_uni_value_agent_scope_unsafe: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_movk_i32 s32, 0x800 +; GFX7LESS-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s42, -1 +; GFX7LESS-NEXT: s_mov_b32 s43, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s40, s40, s3 +; GFX7LESS-NEXT: s_addc_u32 s41, s41, 0 +; GFX7LESS-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX7LESS-NEXT: v_mov_b32_e32 v40, v0 +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, exec_lo, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, exec_hi, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB6_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_mov_b32 s33, s2 +; GFX7LESS-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x9 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX7LESS-NEXT: s_mov_b64 s[38:39], 0 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, s0 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, s1 +; GFX7LESS-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_max_f64 v[2:3], v[0:1], v[0:1] +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[40:43], 0 offset:4 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[40:43], 0 +; GFX7LESS-NEXT: s_add_u32 s8, s34, 44 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_max_f64 v[0:1], v[2:3], 4.0 +; GFX7LESS-NEXT: s_addc_u32 s9, s35, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[40:43], 0 offset:12 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[40:43], 0 offset:8 +; GFX7LESS-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v4, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, 0 +; GFX7LESS-NEXT: s_mov_b32 s12, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v40 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s36 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s37 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX7LESS-NEXT: v_and_b32_e32 v2, 1, v0 +; GFX7LESS-NEXT: buffer_load_dword v0, off, s[40:43], 0 +; GFX7LESS-NEXT: buffer_load_dword v1, off, s[40:43], 0 offset:4 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 1, v2 +; GFX7LESS-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB6_2 +; GFX7LESS-NEXT: .LBB6_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fmax_double_uni_address_uni_value_agent_scope_unsafe: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s42, -1 +; GFX9-NEXT: s_mov_b32 s43, 0xe00000 +; GFX9-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-NEXT: s_add_u32 s40, s40, s3 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-NEXT: s_addc_u32 s41, s41, 0 +; GFX9-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_movk_i32 s32, 0x800 +; GFX9-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX9-NEXT: s_cbranch_execz .LBB6_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX9-NEXT: s_mov_b32 s33, s2 +; GFX9-NEXT: s_mov_b64 s[38:39], 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, s1 +; GFX9-NEXT: v_mov_b32_e32 v1, s0 +; GFX9-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX9-NEXT: s_add_u32 s8, s34, 44 +; GFX9-NEXT: s_addc_u32 s9, s35, 0 +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX9-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX9-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX9-NEXT: s_mov_b32 s12, s33 +; GFX9-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX9-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX9-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: v_mov_b32_e32 v2, s36 +; GFX9-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX9-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX9-NEXT: v_mov_b32_e32 v3, s37 +; GFX9-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX9-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX9-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX9-NEXT: s_cbranch_execnz .LBB6_2 +; GFX9-NEXT: .LBB6_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fmax_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s42, -1 +; GFX1064-NEXT: s_mov_b32 s43, 0x31e16000 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-NEXT: s_add_u32 s40, s40, s3 +; GFX1064-NEXT: s_addc_u32 s41, s41, 0 +; GFX1064-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1064-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB6_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1064-NEXT: s_mov_b32 s33, s2 +; GFX1064-NEXT: s_mov_b64 s[38:39], 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v2, s1 +; GFX1064-NEXT: v_mov_b32_e32 v1, s0 +; GFX1064-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1064-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1064-NEXT: s_mov_b32 s12, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1064-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX1064-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1064-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1064-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1064-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-NEXT: v_mov_b32_e32 v2, s36 +; GFX1064-NEXT: v_mov_b32_e32 v3, s37 +; GFX1064-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1064-NEXT: s_clause 0x1 +; GFX1064-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1064-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX1064-NEXT: s_cbranch_execnz .LBB6_2 +; GFX1064-NEXT: .LBB6_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fmax_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s42, -1 +; GFX1032-NEXT: s_mov_b32 s43, 0x31c16000 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_add_u32 s40, s40, s3 +; GFX1032-NEXT: s_addc_u32 s41, s41, 0 +; GFX1032-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1032-NEXT: s_mov_b32 s38, 0 +; GFX1032-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-NEXT: s_and_saveexec_b32 s0, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB6_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1032-NEXT: s_mov_b32 s33, s2 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v2, s1 +; GFX1032-NEXT: v_mov_b32_e32 v1, s0 +; GFX1032-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1032-NEXT: s_mov_b32 s12, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1032-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX1032-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1032-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1032-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1032-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-NEXT: v_mov_b32_e32 v2, s36 +; GFX1032-NEXT: v_mov_b32_e32 v3, s37 +; GFX1032-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1032-NEXT: s_clause 0x1 +; GFX1032-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1032-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s38 +; GFX1032-NEXT: s_cbranch_execnz .LBB6_2 +; GFX1032-NEXT: .LBB6_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fmax_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1164-NEXT: s_mov_b32 s32, 32 +; GFX1164-NEXT: s_mov_b64 s[0:1], exec +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-NEXT: s_cbranch_execz .LBB6_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1164-NEXT: s_mov_b32 s33, s2 +; GFX1164-NEXT: s_mov_b64 s[38:39], 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v2, s1 +; GFX1164-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-NEXT: .p2align 6 +; GFX1164-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-NEXT: s_mov_b32 s12, s33 +; GFX1164-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-NEXT: v_mov_b32_e32 v2, s36 +; GFX1164-NEXT: v_mov_b32_e32 v3, s37 +; GFX1164-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[38:39] +; GFX1164-NEXT: s_cbranch_execnz .LBB6_2 +; GFX1164-NEXT: .LBB6_3: +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fmax_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: v_mov_b32_e32 v40, v0 +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1132-NEXT: s_mov_b32 s38, 0 +; GFX1132-NEXT: s_mov_b32 s32, 32 +; GFX1132-NEXT: s_mov_b32 s0, exec_lo +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-NEXT: s_cbranch_execz .LBB6_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1132-NEXT: s_mov_b32 s33, s15 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: v_dual_mov_b32 v2, s1 :: v_dual_mov_b32 v1, s0 +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-NEXT: .p2align 6 +; GFX1132-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-NEXT: v_dual_mov_b32 v31, v40 :: v_dual_mov_b32 v0, 8 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-NEXT: s_mov_b32 s12, s33 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_4) +; GFX1132-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s36 +; GFX1132-NEXT: v_dual_mov_b32 v3, s37 :: v_dual_mov_b32 v4, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s38 +; GFX1132-NEXT: s_cbranch_execnz .LBB6_2 +; GFX1132-NEXT: .LBB6_3: +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fmax_double_uni_address_uni_value_agent_scope_unsafe: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s42, -1 +; GFX9-DPP-NEXT: s_mov_b32 s43, 0xe00000 +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB6_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX9-DPP-NEXT: s_mov_b32 s33, s2 +; GFX9-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX9-DPP-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX9-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX9-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX9-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX9-DPP-NEXT: s_mov_b32 s12, s33 +; GFX9-DPP-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX9-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX9-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX9-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX9-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB6_2 +; GFX9-DPP-NEXT: .LBB6_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fmax_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s42, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s43, 0x31e16000 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX1064-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1064-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB6_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1064-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1064-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1064-DPP-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1064-DPP-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX1064-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1064-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1064-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1064-DPP-NEXT: s_clause 0x1 +; GFX1064-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1064-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB6_2 +; GFX1064-DPP-NEXT: .LBB6_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fmax_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s42, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s43, 0x31c16000 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX1032-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1032-DPP-NEXT: s_mov_b32 s38, 0 +; GFX1032-DPP-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s0, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB6_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1032-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1032-DPP-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1032-DPP-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX1032-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1032-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1032-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1032-DPP-NEXT: s_clause 0x1 +; GFX1032-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1032-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s38 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB6_2 +; GFX1032-DPP-NEXT: .LBB6_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fmax_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1164-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1164-DPP-NEXT: s_mov_b64 s[0:1], exec +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB6_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1164-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1164-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-DPP-NEXT: .p2align 6 +; GFX1164-DPP-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1164-DPP-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[38:39] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB6_2 +; GFX1164-DPP-NEXT: .LBB6_3: +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fmax_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s38, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1132-DPP-NEXT: s_mov_b32 s0, exec_lo +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB6_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1132-DPP-NEXT: s_mov_b32 s33, s15 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v2, s1 :: v_dual_mov_b32 v1, s0 +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-DPP-NEXT: .p2align 6 +; GFX1132-DPP-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v31, v40 :: v_dual_mov_b32 v0, 8 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_4) +; GFX1132-DPP-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s36 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, s37 :: v_dual_mov_b32 v4, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s38 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB6_2 +; GFX1132-DPP-NEXT: .LBB6_3: +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fmax ptr addrspace(1) %ptr, double 4.0 syncscope("agent") monotonic, align 4 + ret void +} + +define amdgpu_kernel void @global_atomic_fmax_double_uni_address_div_value_agent_scope_unsafe(ptr addrspace(1) %ptr) #0 { +; GFX7LESS-LABEL: global_atomic_fmax_double_uni_address_div_value_agent_scope_unsafe: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_movk_i32 s32, 0x800 +; GFX7LESS-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s50, -1 +; GFX7LESS-NEXT: s_mov_b32 s51, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s48, s48, s9 +; GFX7LESS-NEXT: s_addc_u32 s49, s49, 0 +; GFX7LESS-NEXT: s_mov_b32 s33, s8 +; GFX7LESS-NEXT: s_mov_b32 s40, s7 +; GFX7LESS-NEXT: s_mov_b32 s41, s6 +; GFX7LESS-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX7LESS-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX7LESS-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX7LESS-NEXT: s_load_dwordx2 s[44:45], s[2:3], 0x9 +; GFX7LESS-NEXT: s_mov_b32 s47, 0xf000 +; GFX7LESS-NEXT: s_mov_b32 s46, -1 +; GFX7LESS-NEXT: s_add_u32 s8, s36, 44 +; GFX7LESS-NEXT: s_addc_u32 s9, s37, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v0, v0, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v40, v0, v2 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX7LESS-NEXT: s_mov_b32 s12, s41 +; GFX7LESS-NEXT: s_mov_b32 s13, s40 +; GFX7LESS-NEXT: s_mov_b32 s14, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v40 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX7LESS-NEXT: buffer_load_dwordx2 v[2:3], off, s[44:47], 0 +; GFX7LESS-NEXT: s_mov_b64 s[42:43], 0 +; GFX7LESS-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX7LESS-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX7LESS-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX7LESS-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX7LESS-NEXT: s_add_u32 s8, s36, 44 +; GFX7LESS-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX7LESS-NEXT: s_addc_u32 s9, s37, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX7LESS-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v4, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, 0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX7LESS-NEXT: s_mov_b32 s12, s41 +; GFX7LESS-NEXT: s_mov_b32 s13, s40 +; GFX7LESS-NEXT: s_mov_b32 s14, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v40 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s44 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s45 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX7LESS-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX7LESS-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX7LESS-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX7LESS-NEXT: s_or_b64 s[42:43], vcc, s[42:43] +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[42:43] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB7_1 +; GFX7LESS-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fmax_double_uni_address_div_value_agent_scope_unsafe: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s50, -1 +; GFX9-NEXT: s_mov_b32 s51, 0xe00000 +; GFX9-NEXT: s_add_u32 s48, s48, s9 +; GFX9-NEXT: s_addc_u32 s49, s49, 0 +; GFX9-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX9-NEXT: s_mov_b32 s33, s8 +; GFX9-NEXT: s_add_u32 s8, s36, 44 +; GFX9-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX9-NEXT: s_mov_b32 s40, s7 +; GFX9-NEXT: s_mov_b32 s41, s6 +; GFX9-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX9-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX9-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-NEXT: s_mov_b32 s12, s41 +; GFX9-NEXT: s_mov_b32 s13, s40 +; GFX9-NEXT: s_mov_b32 s14, s33 +; GFX9-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-NEXT: s_movk_i32 s32, 0x800 +; GFX9-NEXT: v_mov_b32_e32 v41, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX9-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX9-NEXT: s_mov_b64 s[44:45], 0 +; GFX9-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX9-NEXT: s_add_u32 s8, s36, 44 +; GFX9-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX9-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX9-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX9-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-NEXT: s_mov_b32 s12, s41 +; GFX9-NEXT: s_mov_b32 s13, s40 +; GFX9-NEXT: s_mov_b32 s14, s33 +; GFX9-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-NEXT: v_mov_b32_e32 v2, s42 +; GFX9-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX9-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX9-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: v_mov_b32_e32 v3, s43 +; GFX9-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX9-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX9-NEXT: s_cbranch_execnz .LBB7_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fmax_double_uni_address_div_value_agent_scope_unsafe: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s50, -1 +; GFX1064-NEXT: s_mov_b32 s51, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s48, s48, s9 +; GFX1064-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1064-NEXT: s_addc_u32 s49, s49, 0 +; GFX1064-NEXT: s_mov_b32 s33, s8 +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1064-NEXT: s_mov_b32 s40, s7 +; GFX1064-NEXT: s_mov_b32 s41, s6 +; GFX1064-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1064-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1064-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX1064-NEXT: s_mov_b32 s12, s41 +; GFX1064-NEXT: s_mov_b32 s13, s40 +; GFX1064-NEXT: s_mov_b32 s14, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-NEXT: v_mov_b32_e32 v41, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX1064-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1064-NEXT: s_mov_b64 s[44:45], 0 +; GFX1064-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX1064-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX1064-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-NEXT: v_mov_b32_e32 v2, s42 +; GFX1064-NEXT: v_mov_b32_e32 v3, s43 +; GFX1064-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-NEXT: s_mov_b32 s12, s41 +; GFX1064-NEXT: s_mov_b32 s13, s40 +; GFX1064-NEXT: s_mov_b32 s14, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX1064-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX1064-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX1064-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-NEXT: s_clause 0x1 +; GFX1064-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX1064-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX1064-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX1064-NEXT: s_cbranch_execnz .LBB7_1 +; GFX1064-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fmax_double_uni_address_div_value_agent_scope_unsafe: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s50, -1 +; GFX1032-NEXT: s_mov_b32 s51, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s48, s48, s9 +; GFX1032-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1032-NEXT: s_addc_u32 s49, s49, 0 +; GFX1032-NEXT: s_mov_b32 s33, s8 +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1032-NEXT: s_mov_b32 s40, s7 +; GFX1032-NEXT: s_mov_b32 s41, s6 +; GFX1032-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1032-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1032-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX1032-NEXT: s_mov_b32 s12, s41 +; GFX1032-NEXT: s_mov_b32 s13, s40 +; GFX1032-NEXT: s_mov_b32 s14, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-NEXT: v_mov_b32_e32 v41, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX1032-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1032-NEXT: s_mov_b32 s44, 0 +; GFX1032-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX1032-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX1032-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-NEXT: v_mov_b32_e32 v2, s42 +; GFX1032-NEXT: v_mov_b32_e32 v3, s43 +; GFX1032-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-NEXT: s_mov_b32 s12, s41 +; GFX1032-NEXT: s_mov_b32 s13, s40 +; GFX1032-NEXT: s_mov_b32 s14, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX1032-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX1032-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX1032-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-NEXT: s_clause 0x1 +; GFX1032-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX1032-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX1032-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s44 +; GFX1032-NEXT: s_cbranch_execnz .LBB7_1 +; GFX1032-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fmax_double_uni_address_div_value_agent_scope_unsafe: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1164-NEXT: s_mov_b32 s33, s8 +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1164-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-NEXT: s_mov_b32 s12, s6 +; GFX1164-NEXT: s_mov_b32 s13, s7 +; GFX1164-NEXT: s_mov_b32 s14, s33 +; GFX1164-NEXT: s_mov_b32 s32, 32 +; GFX1164-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-NEXT: s_mov_b32 s40, s7 +; GFX1164-NEXT: s_mov_b32 s41, s6 +; GFX1164-NEXT: v_mov_b32_e32 v41, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: global_load_b64 v[2:3], v41, s[42:43] +; GFX1164-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1164-NEXT: s_mov_b64 s[44:45], 0 +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-NEXT: .p2align 6 +; GFX1164-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-NEXT: s_mov_b32 s12, s41 +; GFX1164-NEXT: s_mov_b32 s13, s40 +; GFX1164-NEXT: s_mov_b32 s14, s33 +; GFX1164-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b64 off, v[2:3], off +; GFX1164-NEXT: scratch_store_b64 off, v[0:1], off offset:8 +; GFX1164-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-NEXT: v_mov_b32_e32 v2, s42 +; GFX1164-NEXT: v_mov_b32_e32 v3, s43 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: scratch_load_b64 v[2:3], off, off +; GFX1164-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[44:45] +; GFX1164-NEXT: s_cbranch_execnz .LBB7_1 +; GFX1164-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fmax_double_uni_address_div_value_agent_scope_unsafe: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1132-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1132-NEXT: v_mov_b32_e32 v31, v0 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1132-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1132-NEXT: s_mov_b32 s40, s14 +; GFX1132-NEXT: s_mov_b32 s41, s13 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-NEXT: s_mov_b32 s12, s13 +; GFX1132-NEXT: s_mov_b32 s13, s14 +; GFX1132-NEXT: s_mov_b32 s14, s15 +; GFX1132-NEXT: s_mov_b32 s32, 32 +; GFX1132-NEXT: s_mov_b32 s33, s15 +; GFX1132-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v41, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: global_load_b64 v[2:3], v41, s[42:43] +; GFX1132-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1132-NEXT: s_mov_b32 s44, 0 +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-NEXT: .p2align 6 +; GFX1132-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-NEXT: v_mov_b32_e32 v31, v40 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-NEXT: s_mov_b32 s12, s41 +; GFX1132-NEXT: s_mov_b32 s13, s40 +; GFX1132-NEXT: s_mov_b32 s14, s33 +; GFX1132-NEXT: v_mov_b32_e32 v4, 0 +; GFX1132-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b64 off, v[2:3], off +; GFX1132-NEXT: scratch_store_b64 off, v[0:1], off offset:8 +; GFX1132-NEXT: v_dual_mov_b32 v0, 8 :: v_dual_mov_b32 v1, 0 +; GFX1132-NEXT: v_dual_mov_b32 v2, s42 :: v_dual_mov_b32 v3, s43 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: scratch_load_b64 v[2:3], off, off +; GFX1132-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s44 +; GFX1132-NEXT: s_cbranch_execnz .LBB7_1 +; GFX1132-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fmax_double_uni_address_div_value_agent_scope_unsafe: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s50, -1 +; GFX9-DPP-NEXT: s_mov_b32 s51, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX9-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX9-DPP-NEXT: s_mov_b32 s33, s8 +; GFX9-DPP-NEXT: s_add_u32 s8, s36, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_mov_b32 s40, s7 +; GFX9-DPP-NEXT: s_mov_b32 s41, s6 +; GFX9-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-DPP-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX9-DPP-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-DPP-NEXT: s_mov_b32 s12, s41 +; GFX9-DPP-NEXT: s_mov_b32 s13, s40 +; GFX9-DPP-NEXT: s_mov_b32 s14, s33 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX9-DPP-NEXT: v_mov_b32_e32 v41, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-DPP-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX9-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX9-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX9-DPP-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX9-DPP-NEXT: s_add_u32 s8, s36, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX9-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-DPP-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-DPP-NEXT: s_mov_b32 s12, s41 +; GFX9-DPP-NEXT: s_mov_b32 s13, s40 +; GFX9-DPP-NEXT: s_mov_b32 s14, s33 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX9-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX9-DPP-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX9-DPP-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX9-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB7_1 +; GFX9-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fmax_double_uni_address_div_value_agent_scope_unsafe: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s50, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s51, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX1064-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1064-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1064-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-DPP-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX1064-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v41, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-DPP-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX1064-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1064-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX1064-DPP-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX1064-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-DPP-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX1064-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX1064-DPP-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-DPP-NEXT: s_clause 0x1 +; GFX1064-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX1064-DPP-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX1064-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB7_1 +; GFX1064-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fmax_double_uni_address_div_value_agent_scope_unsafe: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s50, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s51, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX1032-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1032-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1032-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-DPP-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX1032-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-DPP-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v41, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-DPP-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX1032-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1032-DPP-NEXT: s_mov_b32 s44, 0 +; GFX1032-DPP-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX1032-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-DPP-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX1032-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX1032-DPP-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-DPP-NEXT: s_clause 0x1 +; GFX1032-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX1032-DPP-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX1032-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s44 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB7_1 +; GFX1032-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fmax_double_uni_address_div_value_agent_scope_unsafe: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1164-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1164-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v41, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: global_load_b64 v[2:3], v41, s[42:43] +; GFX1164-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1164-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-DPP-NEXT: .p2align 6 +; GFX1164-DPP-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1164-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1164-DPP-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[2:3], off +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[0:1], off offset:8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: scratch_load_b64 v[2:3], off, off +; GFX1164-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[44:45] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB7_1 +; GFX1164-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fmax_double_uni_address_div_value_agent_scope_unsafe: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1132-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1132-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1132-DPP-NEXT: s_mov_b32 s40, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s41, s13 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-DPP-NEXT: s_mov_b32 s12, s13 +; GFX1132-DPP-NEXT: s_mov_b32 s13, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s15 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1132-DPP-NEXT: s_mov_b32 s33, s15 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v41, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: global_load_b64 v[2:3], v41, s[42:43] +; GFX1132-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s44, 0 +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-DPP-NEXT: .p2align 6 +; GFX1132-DPP-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1132-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1132-DPP-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[2:3], off +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[0:1], off offset:8 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v0, 8 :: v_dual_mov_b32 v1, 0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v2, s42 :: v_dual_mov_b32 v3, s43 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: scratch_load_b64 v[2:3], off, off +; GFX1132-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s44 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB7_1 +; GFX1132-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-DPP-NEXT: s_endpgm + %divValue = call double @div.double.value() + %result = atomicrmw fmax ptr addrspace(1) %ptr, double %divValue syncscope("agent") monotonic, align 4 + ret void +} + +define amdgpu_kernel void @global_atomic_fmax_double_uni_address_uni_value_one_as_scope_unsafe(ptr addrspace(1) %ptr) #0 { +; GFX7LESS-LABEL: global_atomic_fmax_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, exec_lo, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, exec_hi, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB8_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x9 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], 0 +; GFX7LESS-NEXT: s_mov_b32 s3, 0xf000 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s6 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s7 +; GFX7LESS-NEXT: s_mov_b32 s2, -1 +; GFX7LESS-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX7LESS-NEXT: v_max_f64 v[0:1], v[0:1], 4.0 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v7, v3 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, v2 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, v1 +; GFX7LESS-NEXT: v_mov_b32_e32 v4, v0 +; GFX7LESS-NEXT: buffer_atomic_cmpswap_x2 v[4:7], off, s[0:3], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[2:3] +; GFX7LESS-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX7LESS-NEXT: v_mov_b32_e32 v2, v4 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, v5 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB8_2 +; GFX7LESS-NEXT: .LBB8_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fmax_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-NEXT: s_cbranch_execz .LBB8_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-NEXT: v_mov_b32_e32 v3, s5 +; GFX9-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX9-NEXT: v_max_f64 v[0:1], v[0:1], 4.0 +; GFX9-NEXT: global_atomic_cmpswap_x2 v[0:1], v4, v[0:3], s[0:1] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX9-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-NEXT: s_cbranch_execnz .LBB8_2 +; GFX9-NEXT: .LBB8_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fmax_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB8_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v2, s2 +; GFX1064-NEXT: v_mov_b32_e32 v3, s3 +; GFX1064-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1064-NEXT: v_max_f64 v[0:1], v[0:1], 4.0 +; GFX1064-NEXT: global_atomic_cmpswap_x2 v[0:1], v4, v[0:3], s[0:1] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1064-NEXT: v_mov_b32_e32 v3, v1 +; GFX1064-NEXT: v_mov_b32_e32 v2, v0 +; GFX1064-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-NEXT: s_cbranch_execnz .LBB8_2 +; GFX1064-NEXT: .LBB8_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fmax_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-NEXT: s_mov_b32 s2, 0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_and_saveexec_b32 s3, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB8_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v2, s4 +; GFX1032-NEXT: v_mov_b32_e32 v3, s5 +; GFX1032-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1032-NEXT: v_max_f64 v[0:1], v[0:1], 4.0 +; GFX1032-NEXT: global_atomic_cmpswap_x2 v[0:1], v4, v[0:3], s[0:1] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1032-NEXT: v_mov_b32_e32 v3, v1 +; GFX1032-NEXT: v_mov_b32_e32 v2, v0 +; GFX1032-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-NEXT: s_cbranch_execnz .LBB8_2 +; GFX1032-NEXT: .LBB8_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fmax_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-NEXT: s_cbranch_execz .LBB8_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b64 s[2:3], s[0:1], 0x0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v2, s2 +; GFX1164-NEXT: v_mov_b32_e32 v3, s3 +; GFX1164-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1164-NEXT: v_max_f64 v[0:1], v[0:1], 4.0 +; GFX1164-NEXT: global_atomic_cmpswap_b64 v[0:1], v4, v[0:3], s[0:1] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1164-NEXT: v_mov_b32_e32 v3, v1 +; GFX1164-NEXT: v_mov_b32_e32 v2, v0 +; GFX1164-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-NEXT: s_cbranch_execnz .LBB8_2 +; GFX1164-NEXT: .LBB8_3: +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fmax_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-NEXT: s_mov_b32 s2, 0 +; GFX1132-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-NEXT: s_cbranch_execz .LBB8_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-NEXT: v_mov_b32_e32 v4, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b64 s[4:5], s[0:1], 0x0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: v_dual_mov_b32 v2, s4 :: v_dual_mov_b32 v3, s5 +; GFX1132-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1132-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1132-NEXT: v_max_f64 v[0:1], v[0:1], 4.0 +; GFX1132-NEXT: global_atomic_cmpswap_b64 v[0:1], v4, v[0:3], s[0:1] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1132-NEXT: v_dual_mov_b32 v3, v1 :: v_dual_mov_b32 v2, v0 +; GFX1132-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-NEXT: s_cbranch_execnz .LBB8_2 +; GFX1132-NEXT: .LBB8_3: +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fmax_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB8_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s5 +; GFX9-DPP-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX9-DPP-NEXT: v_max_f64 v[0:1], v[0:1], 4.0 +; GFX9-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v4, v[0:3], s[0:1] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB8_2 +; GFX9-DPP-NEXT: .LBB8_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fmax_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB8_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s2 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s3 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-DPP-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1064-DPP-NEXT: v_max_f64 v[0:1], v[0:1], 4.0 +; GFX1064-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v4, v[0:3], s[0:1] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB8_2 +; GFX1064-DPP-NEXT: .LBB8_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fmax_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s3, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB8_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s4 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s5 +; GFX1032-DPP-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1032-DPP-NEXT: v_max_f64 v[0:1], v[0:1], 4.0 +; GFX1032-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v4, v[0:3], s[0:1] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1032-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB8_2 +; GFX1032-DPP-NEXT: .LBB8_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fmax_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB8_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b64 s[2:3], s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s2 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s3 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-DPP-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1164-DPP-NEXT: v_max_f64 v[0:1], v[0:1], 4.0 +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b64 v[0:1], v4, v[0:3], s[0:1] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB8_2 +; GFX1164-DPP-NEXT: .LBB8_3: +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fmax_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB8_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b64 s[4:5], s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v2, s4 :: v_dual_mov_b32 v3, s5 +; GFX1132-DPP-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1132-DPP-NEXT: v_max_f64 v[0:1], v[0:1], 4.0 +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b64 v[0:1], v4, v[0:3], s[0:1] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, v1 :: v_dual_mov_b32 v2, v0 +; GFX1132-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB8_2 +; GFX1132-DPP-NEXT: .LBB8_3: +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fmax ptr addrspace(1) %ptr, double 4.0 syncscope("one-as") monotonic + ret void +} + +define amdgpu_kernel void @global_atomic_fmax_double_uni_address_div_value_one_as_scope_unsafe(ptr addrspace(1) %ptr) #0 { +; GFX7LESS-LABEL: global_atomic_fmax_double_uni_address_div_value_one_as_scope_unsafe: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_mov_b32 s32, 0 +; GFX7LESS-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s42, -1 +; GFX7LESS-NEXT: s_mov_b32 s43, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s40, s40, s9 +; GFX7LESS-NEXT: s_addc_u32 s41, s41, 0 +; GFX7LESS-NEXT: s_mov_b32 s14, s8 +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX7LESS-NEXT: s_load_dwordx2 s[36:37], s[2:3], 0x9 +; GFX7LESS-NEXT: s_mov_b32 s39, 0xf000 +; GFX7LESS-NEXT: s_mov_b32 s38, -1 +; GFX7LESS-NEXT: s_add_u32 s8, s2, 44 +; GFX7LESS-NEXT: s_addc_u32 s9, s3, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[2:3] +; GFX7LESS-NEXT: s_add_u32 s2, s2, div.double.value@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s3, s3, div.double.value@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v0, v0, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v31, v0, v2 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX7LESS-NEXT: s_mov_b32 s12, s6 +; GFX7LESS-NEXT: s_mov_b32 s13, s7 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX7LESS-NEXT: buffer_load_dwordx2 v[2:3], off, s[36:39], 0 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], 0 +; GFX7LESS-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX7LESS-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX7LESS-NEXT: v_max_f64 v[0:1], v[0:1], v[4:5] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v9, v3 +; GFX7LESS-NEXT: v_mov_b32_e32 v8, v2 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, v1 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, v0 +; GFX7LESS-NEXT: buffer_atomic_cmpswap_x2 v[6:9], off, s[36:39], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[2:3] +; GFX7LESS-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX7LESS-NEXT: v_mov_b32_e32 v2, v6 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, v7 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB9_1 +; GFX7LESS-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fmax_double_uni_address_div_value_one_as_scope_unsafe: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s38, -1 +; GFX9-NEXT: s_mov_b32 s39, 0xe00000 +; GFX9-NEXT: s_add_u32 s36, s36, s9 +; GFX9-NEXT: s_addc_u32 s37, s37, 0 +; GFX9-NEXT: s_mov_b32 s14, s8 +; GFX9-NEXT: s_add_u32 s8, s2, 44 +; GFX9-NEXT: s_addc_u32 s9, s3, 0 +; GFX9-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX9-NEXT: s_getpc_b64 s[2:3] +; GFX9-NEXT: s_add_u32 s2, s2, div.double.value@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s3, s3, div.double.value@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX9-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX9-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX9-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX9-NEXT: s_mov_b32 s12, s6 +; GFX9-NEXT: s_mov_b32 s13, s7 +; GFX9-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX9-NEXT: s_mov_b32 s32, 0 +; GFX9-NEXT: v_mov_b32_e32 v40, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX9-NEXT: global_load_dwordx2 v[2:3], v40, s[34:35] +; GFX9-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX9-NEXT: s_mov_b64 s[0:1], 0 +; GFX9-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX9-NEXT: v_max_f64 v[0:1], v[0:1], v[4:5] +; GFX9-NEXT: global_atomic_cmpswap_x2 v[0:1], v40, v[0:3], s[34:35] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX9-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX9-NEXT: s_cbranch_execnz .LBB9_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fmax_double_uni_address_div_value_one_as_scope_unsafe: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s38, -1 +; GFX1064-NEXT: s_mov_b32 s39, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s36, s36, s9 +; GFX1064-NEXT: s_addc_u32 s37, s37, 0 +; GFX1064-NEXT: s_mov_b32 s14, s8 +; GFX1064-NEXT: s_add_u32 s8, s2, 44 +; GFX1064-NEXT: s_addc_u32 s9, s3, 0 +; GFX1064-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1064-NEXT: s_getpc_b64 s[4:5] +; GFX1064-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1064-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1064-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1064-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1064-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1064-NEXT: s_mov_b32 s12, s6 +; GFX1064-NEXT: s_mov_b32 s13, s7 +; GFX1064-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1064-NEXT: s_mov_b32 s32, 0 +; GFX1064-NEXT: v_mov_b32_e32 v40, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1064-NEXT: global_load_dwordx2 v[2:3], v40, s[34:35] +; GFX1064-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX1064-NEXT: s_mov_b64 s[0:1], 0 +; GFX1064-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1064-NEXT: v_max_f64 v[0:1], v[0:1], v[4:5] +; GFX1064-NEXT: global_atomic_cmpswap_x2 v[0:1], v40, v[0:3], s[34:35] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1064-NEXT: v_mov_b32_e32 v3, v1 +; GFX1064-NEXT: v_mov_b32_e32 v2, v0 +; GFX1064-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX1064-NEXT: s_cbranch_execnz .LBB9_1 +; GFX1064-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fmax_double_uni_address_div_value_one_as_scope_unsafe: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s38, -1 +; GFX1032-NEXT: s_mov_b32 s39, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s36, s36, s9 +; GFX1032-NEXT: s_addc_u32 s37, s37, 0 +; GFX1032-NEXT: s_mov_b32 s14, s8 +; GFX1032-NEXT: s_add_u32 s8, s2, 44 +; GFX1032-NEXT: s_addc_u32 s9, s3, 0 +; GFX1032-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1032-NEXT: s_getpc_b64 s[4:5] +; GFX1032-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1032-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1032-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1032-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1032-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1032-NEXT: s_mov_b32 s12, s6 +; GFX1032-NEXT: s_mov_b32 s13, s7 +; GFX1032-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1032-NEXT: s_mov_b32 s32, 0 +; GFX1032-NEXT: v_mov_b32_e32 v40, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1032-NEXT: global_load_dwordx2 v[2:3], v40, s[34:35] +; GFX1032-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX1032-NEXT: s_mov_b32 s0, 0 +; GFX1032-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1032-NEXT: v_max_f64 v[0:1], v[0:1], v[4:5] +; GFX1032-NEXT: global_atomic_cmpswap_x2 v[0:1], v40, v[0:3], s[34:35] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1032-NEXT: v_mov_b32_e32 v3, v1 +; GFX1032-NEXT: v_mov_b32_e32 v2, v0 +; GFX1032-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s0 +; GFX1032-NEXT: s_cbranch_execnz .LBB9_1 +; GFX1032-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fmax_double_uni_address_div_value_one_as_scope_unsafe: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b32 s14, s8 +; GFX1164-NEXT: s_add_u32 s8, s2, 44 +; GFX1164-NEXT: s_addc_u32 s9, s3, 0 +; GFX1164-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1164-NEXT: s_getpc_b64 s[4:5] +; GFX1164-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1164-NEXT: s_load_b64 s[16:17], s[4:5], 0x0 +; GFX1164-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1164-NEXT: s_mov_b32 s12, s6 +; GFX1164-NEXT: s_mov_b32 s13, s7 +; GFX1164-NEXT: s_mov_b32 s32, 0 +; GFX1164-NEXT: v_mov_b32_e32 v40, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1164-NEXT: global_load_b64 v[2:3], v40, s[34:35] +; GFX1164-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX1164-NEXT: s_mov_b64 s[0:1], 0 +; GFX1164-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_max_f64 v[0:1], v[0:1], v[4:5] +; GFX1164-NEXT: global_atomic_cmpswap_b64 v[0:1], v40, v[0:3], s[34:35] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1164-NEXT: v_mov_b32_e32 v3, v1 +; GFX1164-NEXT: v_mov_b32_e32 v2, v0 +; GFX1164-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[0:1] +; GFX1164-NEXT: s_cbranch_execnz .LBB9_1 +; GFX1164-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fmax_double_uni_address_div_value_one_as_scope_unsafe: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_add_u32 s8, s2, 44 +; GFX1132-NEXT: s_addc_u32 s9, s3, 0 +; GFX1132-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1132-NEXT: s_getpc_b64 s[4:5] +; GFX1132-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1132-NEXT: s_load_b64 s[6:7], s[4:5], 0x0 +; GFX1132-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1132-NEXT: v_dual_mov_b32 v40, 0 :: v_dual_mov_b32 v31, v0 +; GFX1132-NEXT: s_mov_b32 s12, s13 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1132-NEXT: s_mov_b32 s13, s14 +; GFX1132-NEXT: s_mov_b32 s14, s15 +; GFX1132-NEXT: s_mov_b32 s32, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1132-NEXT: global_load_b64 v[2:3], v40, s[34:35] +; GFX1132-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX1132-NEXT: s_mov_b32 s0, 0 +; GFX1132-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_max_f64 v[0:1], v[0:1], v[4:5] +; GFX1132-NEXT: global_atomic_cmpswap_b64 v[0:1], v40, v[0:3], s[34:35] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1132-NEXT: v_dual_mov_b32 v3, v1 :: v_dual_mov_b32 v2, v0 +; GFX1132-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s0 +; GFX1132-NEXT: s_cbranch_execnz .LBB9_1 +; GFX1132-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fmax_double_uni_address_div_value_one_as_scope_unsafe: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s38, -1 +; GFX9-DPP-NEXT: s_mov_b32 s39, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX9-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX9-DPP-NEXT: s_mov_b32 s14, s8 +; GFX9-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX9-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX9-DPP-NEXT: s_getpc_b64 s[2:3] +; GFX9-DPP-NEXT: s_add_u32 s2, s2, div.double.value@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s3, s3, div.double.value@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX9-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX9-DPP-NEXT: s_mov_b32 s12, s6 +; GFX9-DPP-NEXT: s_mov_b32 s13, s7 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX9-DPP-NEXT: s_mov_b32 s32, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX9-DPP-NEXT: global_load_dwordx2 v[2:3], v40, s[34:35] +; GFX9-DPP-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX9-DPP-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX9-DPP-NEXT: v_max_f64 v[0:1], v[0:1], v[4:5] +; GFX9-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v40, v[0:3], s[34:35] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB9_1 +; GFX9-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fmax_double_uni_address_div_value_one_as_scope_unsafe: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s38, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s39, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX1064-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1064-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1064-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1064-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1064-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1064-DPP-NEXT: global_load_dwordx2 v[2:3], v40, s[34:35] +; GFX1064-DPP-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX1064-DPP-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1064-DPP-NEXT: v_max_f64 v[0:1], v[0:1], v[4:5] +; GFX1064-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v40, v[0:3], s[34:35] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB9_1 +; GFX1064-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fmax_double_uni_address_div_value_one_as_scope_unsafe: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s38, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s39, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX1032-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1032-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1032-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1032-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1032-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1032-DPP-NEXT: global_load_dwordx2 v[2:3], v40, s[34:35] +; GFX1032-DPP-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX1032-DPP-NEXT: s_mov_b32 s0, 0 +; GFX1032-DPP-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1032-DPP-NEXT: v_max_f64 v[0:1], v[0:1], v[4:5] +; GFX1032-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v40, v[0:3], s[34:35] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1032-DPP-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s0 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB9_1 +; GFX1032-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fmax_double_uni_address_div_value_one_as_scope_unsafe: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1164-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1164-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1164-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: s_load_b64 s[16:17], s[4:5], 0x0 +; GFX1164-DPP-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1164-DPP-NEXT: global_load_b64 v[2:3], v40, s[34:35] +; GFX1164-DPP-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX1164-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX1164-DPP-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_max_f64 v[0:1], v[0:1], v[4:5] +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b64 v[0:1], v40, v[0:3], s[34:35] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[0:1] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB9_1 +; GFX1164-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fmax_double_uni_address_div_value_one_as_scope_unsafe: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1132-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1132-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: s_load_b64 s[6:7], s[4:5], 0x0 +; GFX1132-DPP-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v40, 0 :: v_dual_mov_b32 v31, v0 +; GFX1132-DPP-NEXT: s_mov_b32 s12, s13 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s13, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s15 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1132-DPP-NEXT: global_load_b64 v[2:3], v40, s[34:35] +; GFX1132-DPP-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s0, 0 +; GFX1132-DPP-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_max_f64 v[0:1], v[0:1], v[4:5] +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b64 v[0:1], v40, v[0:3], s[34:35] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, v1 :: v_dual_mov_b32 v2, v0 +; GFX1132-DPP-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s0 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB9_1 +; GFX1132-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-DPP-NEXT: s_endpgm + %divValue = call double @div.double.value() + %result = atomicrmw fmax ptr addrspace(1) %ptr, double %divValue syncscope("one-as") monotonic + ret void +} + +define amdgpu_kernel void @global_atomic_fmax_double_uni_address_uni_value_defalut_scope_unsafe(ptr addrspace(1) %ptr) #0 { +; GFX7LESS-LABEL: global_atomic_fmax_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_movk_i32 s32, 0x800 +; GFX7LESS-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s42, -1 +; GFX7LESS-NEXT: s_mov_b32 s43, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s40, s40, s3 +; GFX7LESS-NEXT: s_addc_u32 s41, s41, 0 +; GFX7LESS-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX7LESS-NEXT: v_mov_b32_e32 v40, v0 +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, exec_lo, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, exec_hi, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB10_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_mov_b32 s33, s2 +; GFX7LESS-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x9 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX7LESS-NEXT: s_mov_b64 s[38:39], 0 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, s0 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, s1 +; GFX7LESS-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_max_f64 v[2:3], v[0:1], v[0:1] +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[40:43], 0 offset:4 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[40:43], 0 +; GFX7LESS-NEXT: s_add_u32 s8, s34, 44 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_max_f64 v[0:1], v[2:3], 4.0 +; GFX7LESS-NEXT: s_addc_u32 s9, s35, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[40:43], 0 offset:12 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[40:43], 0 offset:8 +; GFX7LESS-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v4, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, 0 +; GFX7LESS-NEXT: s_mov_b32 s12, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v40 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s36 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s37 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX7LESS-NEXT: v_and_b32_e32 v2, 1, v0 +; GFX7LESS-NEXT: buffer_load_dword v0, off, s[40:43], 0 +; GFX7LESS-NEXT: buffer_load_dword v1, off, s[40:43], 0 offset:4 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 1, v2 +; GFX7LESS-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB10_2 +; GFX7LESS-NEXT: .LBB10_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fmax_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s42, -1 +; GFX9-NEXT: s_mov_b32 s43, 0xe00000 +; GFX9-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-NEXT: s_add_u32 s40, s40, s3 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-NEXT: s_addc_u32 s41, s41, 0 +; GFX9-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_movk_i32 s32, 0x800 +; GFX9-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX9-NEXT: s_cbranch_execz .LBB10_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX9-NEXT: s_mov_b32 s33, s2 +; GFX9-NEXT: s_mov_b64 s[38:39], 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, s1 +; GFX9-NEXT: v_mov_b32_e32 v1, s0 +; GFX9-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX9-NEXT: s_add_u32 s8, s34, 44 +; GFX9-NEXT: s_addc_u32 s9, s35, 0 +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX9-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX9-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX9-NEXT: s_mov_b32 s12, s33 +; GFX9-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX9-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX9-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: v_mov_b32_e32 v2, s36 +; GFX9-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX9-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX9-NEXT: v_mov_b32_e32 v3, s37 +; GFX9-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX9-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX9-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX9-NEXT: s_cbranch_execnz .LBB10_2 +; GFX9-NEXT: .LBB10_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fmax_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s42, -1 +; GFX1064-NEXT: s_mov_b32 s43, 0x31e16000 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-NEXT: s_add_u32 s40, s40, s3 +; GFX1064-NEXT: s_addc_u32 s41, s41, 0 +; GFX1064-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1064-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB10_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1064-NEXT: s_mov_b32 s33, s2 +; GFX1064-NEXT: s_mov_b64 s[38:39], 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v2, s1 +; GFX1064-NEXT: v_mov_b32_e32 v1, s0 +; GFX1064-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1064-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1064-NEXT: s_mov_b32 s12, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1064-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX1064-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1064-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1064-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1064-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-NEXT: v_mov_b32_e32 v2, s36 +; GFX1064-NEXT: v_mov_b32_e32 v3, s37 +; GFX1064-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1064-NEXT: s_clause 0x1 +; GFX1064-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1064-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX1064-NEXT: s_cbranch_execnz .LBB10_2 +; GFX1064-NEXT: .LBB10_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fmax_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s42, -1 +; GFX1032-NEXT: s_mov_b32 s43, 0x31c16000 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_add_u32 s40, s40, s3 +; GFX1032-NEXT: s_addc_u32 s41, s41, 0 +; GFX1032-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1032-NEXT: s_mov_b32 s38, 0 +; GFX1032-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-NEXT: s_and_saveexec_b32 s0, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB10_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1032-NEXT: s_mov_b32 s33, s2 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v2, s1 +; GFX1032-NEXT: v_mov_b32_e32 v1, s0 +; GFX1032-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1032-NEXT: s_mov_b32 s12, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1032-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX1032-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1032-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1032-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1032-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-NEXT: v_mov_b32_e32 v2, s36 +; GFX1032-NEXT: v_mov_b32_e32 v3, s37 +; GFX1032-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1032-NEXT: s_clause 0x1 +; GFX1032-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1032-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s38 +; GFX1032-NEXT: s_cbranch_execnz .LBB10_2 +; GFX1032-NEXT: .LBB10_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fmax_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1164-NEXT: s_mov_b32 s32, 32 +; GFX1164-NEXT: s_mov_b64 s[0:1], exec +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-NEXT: s_cbranch_execz .LBB10_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1164-NEXT: s_mov_b32 s33, s2 +; GFX1164-NEXT: s_mov_b64 s[38:39], 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v2, s1 +; GFX1164-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-NEXT: .p2align 6 +; GFX1164-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-NEXT: s_mov_b32 s12, s33 +; GFX1164-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-NEXT: v_mov_b32_e32 v2, s36 +; GFX1164-NEXT: v_mov_b32_e32 v3, s37 +; GFX1164-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[38:39] +; GFX1164-NEXT: s_cbranch_execnz .LBB10_2 +; GFX1164-NEXT: .LBB10_3: +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fmax_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: v_mov_b32_e32 v40, v0 +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1132-NEXT: s_mov_b32 s38, 0 +; GFX1132-NEXT: s_mov_b32 s32, 32 +; GFX1132-NEXT: s_mov_b32 s0, exec_lo +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-NEXT: s_cbranch_execz .LBB10_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1132-NEXT: s_mov_b32 s33, s15 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: v_dual_mov_b32 v2, s1 :: v_dual_mov_b32 v1, s0 +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-NEXT: .p2align 6 +; GFX1132-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-NEXT: v_dual_mov_b32 v31, v40 :: v_dual_mov_b32 v0, 8 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-NEXT: s_mov_b32 s12, s33 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_4) +; GFX1132-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s36 +; GFX1132-NEXT: v_dual_mov_b32 v3, s37 :: v_dual_mov_b32 v4, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s38 +; GFX1132-NEXT: s_cbranch_execnz .LBB10_2 +; GFX1132-NEXT: .LBB10_3: +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fmax_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s42, -1 +; GFX9-DPP-NEXT: s_mov_b32 s43, 0xe00000 +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB10_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX9-DPP-NEXT: s_mov_b32 s33, s2 +; GFX9-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX9-DPP-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX9-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX9-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX9-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX9-DPP-NEXT: s_mov_b32 s12, s33 +; GFX9-DPP-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX9-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX9-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX9-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX9-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB10_2 +; GFX9-DPP-NEXT: .LBB10_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fmax_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s42, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s43, 0x31e16000 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX1064-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1064-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB10_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1064-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1064-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1064-DPP-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1064-DPP-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX1064-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1064-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1064-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1064-DPP-NEXT: s_clause 0x1 +; GFX1064-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1064-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB10_2 +; GFX1064-DPP-NEXT: .LBB10_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fmax_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s42, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s43, 0x31c16000 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX1032-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1032-DPP-NEXT: s_mov_b32 s38, 0 +; GFX1032-DPP-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s0, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB10_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1032-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1032-DPP-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1032-DPP-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX1032-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1032-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1032-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1032-DPP-NEXT: s_clause 0x1 +; GFX1032-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1032-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s38 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB10_2 +; GFX1032-DPP-NEXT: .LBB10_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fmax_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1164-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1164-DPP-NEXT: s_mov_b64 s[0:1], exec +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB10_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1164-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1164-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-DPP-NEXT: .p2align 6 +; GFX1164-DPP-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1164-DPP-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[38:39] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB10_2 +; GFX1164-DPP-NEXT: .LBB10_3: +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fmax_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s38, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1132-DPP-NEXT: s_mov_b32 s0, exec_lo +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB10_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1132-DPP-NEXT: s_mov_b32 s33, s15 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v2, s1 :: v_dual_mov_b32 v1, s0 +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-DPP-NEXT: .p2align 6 +; GFX1132-DPP-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v31, v40 :: v_dual_mov_b32 v0, 8 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_4) +; GFX1132-DPP-NEXT: v_max_f64 v[3:4], v[3:4], 4.0 +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s36 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, s37 :: v_dual_mov_b32 v4, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s38 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB10_2 +; GFX1132-DPP-NEXT: .LBB10_3: +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fmax ptr addrspace(1) %ptr, double 4.0 monotonic, align 4 + ret void +} + +define amdgpu_kernel void @global_atomic_fmax_double_uni_address_div_value_defalut_scope_unsafe(ptr addrspace(1) %ptr) #0 { +; GFX7LESS-LABEL: global_atomic_fmax_double_uni_address_div_value_defalut_scope_unsafe: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_movk_i32 s32, 0x800 +; GFX7LESS-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s50, -1 +; GFX7LESS-NEXT: s_mov_b32 s51, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s48, s48, s9 +; GFX7LESS-NEXT: s_addc_u32 s49, s49, 0 +; GFX7LESS-NEXT: s_mov_b32 s33, s8 +; GFX7LESS-NEXT: s_mov_b32 s40, s7 +; GFX7LESS-NEXT: s_mov_b32 s41, s6 +; GFX7LESS-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX7LESS-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX7LESS-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX7LESS-NEXT: s_load_dwordx2 s[44:45], s[2:3], 0x9 +; GFX7LESS-NEXT: s_mov_b32 s47, 0xf000 +; GFX7LESS-NEXT: s_mov_b32 s46, -1 +; GFX7LESS-NEXT: s_add_u32 s8, s36, 44 +; GFX7LESS-NEXT: s_addc_u32 s9, s37, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v0, v0, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v40, v0, v2 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX7LESS-NEXT: s_mov_b32 s12, s41 +; GFX7LESS-NEXT: s_mov_b32 s13, s40 +; GFX7LESS-NEXT: s_mov_b32 s14, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v40 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX7LESS-NEXT: buffer_load_dwordx2 v[2:3], off, s[44:47], 0 +; GFX7LESS-NEXT: s_mov_b64 s[42:43], 0 +; GFX7LESS-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX7LESS-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX7LESS-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX7LESS-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX7LESS-NEXT: s_add_u32 s8, s36, 44 +; GFX7LESS-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX7LESS-NEXT: s_addc_u32 s9, s37, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX7LESS-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v4, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, 0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX7LESS-NEXT: s_mov_b32 s12, s41 +; GFX7LESS-NEXT: s_mov_b32 s13, s40 +; GFX7LESS-NEXT: s_mov_b32 s14, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v40 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s44 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s45 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX7LESS-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX7LESS-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX7LESS-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX7LESS-NEXT: s_or_b64 s[42:43], vcc, s[42:43] +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[42:43] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB11_1 +; GFX7LESS-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fmax_double_uni_address_div_value_defalut_scope_unsafe: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s50, -1 +; GFX9-NEXT: s_mov_b32 s51, 0xe00000 +; GFX9-NEXT: s_add_u32 s48, s48, s9 +; GFX9-NEXT: s_addc_u32 s49, s49, 0 +; GFX9-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX9-NEXT: s_mov_b32 s33, s8 +; GFX9-NEXT: s_add_u32 s8, s36, 44 +; GFX9-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX9-NEXT: s_mov_b32 s40, s7 +; GFX9-NEXT: s_mov_b32 s41, s6 +; GFX9-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX9-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX9-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-NEXT: s_mov_b32 s12, s41 +; GFX9-NEXT: s_mov_b32 s13, s40 +; GFX9-NEXT: s_mov_b32 s14, s33 +; GFX9-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-NEXT: s_movk_i32 s32, 0x800 +; GFX9-NEXT: v_mov_b32_e32 v41, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX9-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX9-NEXT: s_mov_b64 s[44:45], 0 +; GFX9-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX9-NEXT: s_add_u32 s8, s36, 44 +; GFX9-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX9-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX9-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX9-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-NEXT: s_mov_b32 s12, s41 +; GFX9-NEXT: s_mov_b32 s13, s40 +; GFX9-NEXT: s_mov_b32 s14, s33 +; GFX9-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-NEXT: v_mov_b32_e32 v2, s42 +; GFX9-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX9-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX9-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: v_mov_b32_e32 v3, s43 +; GFX9-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX9-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX9-NEXT: s_cbranch_execnz .LBB11_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fmax_double_uni_address_div_value_defalut_scope_unsafe: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s50, -1 +; GFX1064-NEXT: s_mov_b32 s51, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s48, s48, s9 +; GFX1064-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1064-NEXT: s_addc_u32 s49, s49, 0 +; GFX1064-NEXT: s_mov_b32 s33, s8 +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1064-NEXT: s_mov_b32 s40, s7 +; GFX1064-NEXT: s_mov_b32 s41, s6 +; GFX1064-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1064-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1064-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX1064-NEXT: s_mov_b32 s12, s41 +; GFX1064-NEXT: s_mov_b32 s13, s40 +; GFX1064-NEXT: s_mov_b32 s14, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-NEXT: v_mov_b32_e32 v41, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX1064-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1064-NEXT: s_mov_b64 s[44:45], 0 +; GFX1064-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX1064-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX1064-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-NEXT: v_mov_b32_e32 v2, s42 +; GFX1064-NEXT: v_mov_b32_e32 v3, s43 +; GFX1064-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-NEXT: s_mov_b32 s12, s41 +; GFX1064-NEXT: s_mov_b32 s13, s40 +; GFX1064-NEXT: s_mov_b32 s14, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX1064-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX1064-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX1064-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-NEXT: s_clause 0x1 +; GFX1064-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX1064-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX1064-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX1064-NEXT: s_cbranch_execnz .LBB11_1 +; GFX1064-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fmax_double_uni_address_div_value_defalut_scope_unsafe: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s50, -1 +; GFX1032-NEXT: s_mov_b32 s51, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s48, s48, s9 +; GFX1032-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1032-NEXT: s_addc_u32 s49, s49, 0 +; GFX1032-NEXT: s_mov_b32 s33, s8 +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1032-NEXT: s_mov_b32 s40, s7 +; GFX1032-NEXT: s_mov_b32 s41, s6 +; GFX1032-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1032-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1032-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX1032-NEXT: s_mov_b32 s12, s41 +; GFX1032-NEXT: s_mov_b32 s13, s40 +; GFX1032-NEXT: s_mov_b32 s14, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-NEXT: v_mov_b32_e32 v41, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX1032-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1032-NEXT: s_mov_b32 s44, 0 +; GFX1032-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX1032-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX1032-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-NEXT: v_mov_b32_e32 v2, s42 +; GFX1032-NEXT: v_mov_b32_e32 v3, s43 +; GFX1032-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-NEXT: s_mov_b32 s12, s41 +; GFX1032-NEXT: s_mov_b32 s13, s40 +; GFX1032-NEXT: s_mov_b32 s14, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX1032-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX1032-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX1032-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-NEXT: s_clause 0x1 +; GFX1032-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX1032-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX1032-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s44 +; GFX1032-NEXT: s_cbranch_execnz .LBB11_1 +; GFX1032-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fmax_double_uni_address_div_value_defalut_scope_unsafe: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1164-NEXT: s_mov_b32 s33, s8 +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1164-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-NEXT: s_mov_b32 s12, s6 +; GFX1164-NEXT: s_mov_b32 s13, s7 +; GFX1164-NEXT: s_mov_b32 s14, s33 +; GFX1164-NEXT: s_mov_b32 s32, 32 +; GFX1164-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-NEXT: s_mov_b32 s40, s7 +; GFX1164-NEXT: s_mov_b32 s41, s6 +; GFX1164-NEXT: v_mov_b32_e32 v41, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: global_load_b64 v[2:3], v41, s[42:43] +; GFX1164-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1164-NEXT: s_mov_b64 s[44:45], 0 +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-NEXT: .p2align 6 +; GFX1164-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-NEXT: s_mov_b32 s12, s41 +; GFX1164-NEXT: s_mov_b32 s13, s40 +; GFX1164-NEXT: s_mov_b32 s14, s33 +; GFX1164-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b64 off, v[2:3], off +; GFX1164-NEXT: scratch_store_b64 off, v[0:1], off offset:8 +; GFX1164-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-NEXT: v_mov_b32_e32 v2, s42 +; GFX1164-NEXT: v_mov_b32_e32 v3, s43 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: scratch_load_b64 v[2:3], off, off +; GFX1164-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[44:45] +; GFX1164-NEXT: s_cbranch_execnz .LBB11_1 +; GFX1164-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fmax_double_uni_address_div_value_defalut_scope_unsafe: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1132-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1132-NEXT: v_mov_b32_e32 v31, v0 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1132-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1132-NEXT: s_mov_b32 s40, s14 +; GFX1132-NEXT: s_mov_b32 s41, s13 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-NEXT: s_mov_b32 s12, s13 +; GFX1132-NEXT: s_mov_b32 s13, s14 +; GFX1132-NEXT: s_mov_b32 s14, s15 +; GFX1132-NEXT: s_mov_b32 s32, 32 +; GFX1132-NEXT: s_mov_b32 s33, s15 +; GFX1132-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v41, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: global_load_b64 v[2:3], v41, s[42:43] +; GFX1132-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1132-NEXT: s_mov_b32 s44, 0 +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-NEXT: .p2align 6 +; GFX1132-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-NEXT: v_mov_b32_e32 v31, v40 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-NEXT: s_mov_b32 s12, s41 +; GFX1132-NEXT: s_mov_b32 s13, s40 +; GFX1132-NEXT: s_mov_b32 s14, s33 +; GFX1132-NEXT: v_mov_b32_e32 v4, 0 +; GFX1132-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b64 off, v[2:3], off +; GFX1132-NEXT: scratch_store_b64 off, v[0:1], off offset:8 +; GFX1132-NEXT: v_dual_mov_b32 v0, 8 :: v_dual_mov_b32 v1, 0 +; GFX1132-NEXT: v_dual_mov_b32 v2, s42 :: v_dual_mov_b32 v3, s43 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: scratch_load_b64 v[2:3], off, off +; GFX1132-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s44 +; GFX1132-NEXT: s_cbranch_execnz .LBB11_1 +; GFX1132-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fmax_double_uni_address_div_value_defalut_scope_unsafe: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s50, -1 +; GFX9-DPP-NEXT: s_mov_b32 s51, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX9-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX9-DPP-NEXT: s_mov_b32 s33, s8 +; GFX9-DPP-NEXT: s_add_u32 s8, s36, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_mov_b32 s40, s7 +; GFX9-DPP-NEXT: s_mov_b32 s41, s6 +; GFX9-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-DPP-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX9-DPP-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-DPP-NEXT: s_mov_b32 s12, s41 +; GFX9-DPP-NEXT: s_mov_b32 s13, s40 +; GFX9-DPP-NEXT: s_mov_b32 s14, s33 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX9-DPP-NEXT: v_mov_b32_e32 v41, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-DPP-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX9-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX9-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX9-DPP-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX9-DPP-NEXT: s_add_u32 s8, s36, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX9-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-DPP-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-DPP-NEXT: s_mov_b32 s12, s41 +; GFX9-DPP-NEXT: s_mov_b32 s13, s40 +; GFX9-DPP-NEXT: s_mov_b32 s14, s33 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX9-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX9-DPP-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX9-DPP-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX9-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB11_1 +; GFX9-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fmax_double_uni_address_div_value_defalut_scope_unsafe: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s50, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s51, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX1064-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1064-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1064-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-DPP-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX1064-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v41, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-DPP-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX1064-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1064-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX1064-DPP-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX1064-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-DPP-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX1064-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX1064-DPP-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-DPP-NEXT: s_clause 0x1 +; GFX1064-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX1064-DPP-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX1064-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB11_1 +; GFX1064-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fmax_double_uni_address_div_value_defalut_scope_unsafe: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s50, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s51, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX1032-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1032-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1032-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-DPP-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX1032-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-DPP-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v41, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-DPP-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX1032-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1032-DPP-NEXT: s_mov_b32 s44, 0 +; GFX1032-DPP-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX1032-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-DPP-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX1032-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX1032-DPP-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-DPP-NEXT: s_clause 0x1 +; GFX1032-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX1032-DPP-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX1032-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s44 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB11_1 +; GFX1032-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fmax_double_uni_address_div_value_defalut_scope_unsafe: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1164-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1164-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v41, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: global_load_b64 v[2:3], v41, s[42:43] +; GFX1164-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1164-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-DPP-NEXT: .p2align 6 +; GFX1164-DPP-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1164-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1164-DPP-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[2:3], off +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[0:1], off offset:8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: scratch_load_b64 v[2:3], off, off +; GFX1164-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[44:45] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB11_1 +; GFX1164-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fmax_double_uni_address_div_value_defalut_scope_unsafe: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1132-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1132-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1132-DPP-NEXT: s_mov_b32 s40, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s41, s13 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-DPP-NEXT: s_mov_b32 s12, s13 +; GFX1132-DPP-NEXT: s_mov_b32 s13, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s15 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1132-DPP-NEXT: s_mov_b32 s33, s15 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v41, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: global_load_b64 v[2:3], v41, s[42:43] +; GFX1132-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s44, 0 +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-DPP-NEXT: .p2align 6 +; GFX1132-DPP-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1132-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1132-DPP-NEXT: v_max_f64 v[0:1], v[0:1], v[41:42] +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[2:3], off +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[0:1], off offset:8 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v0, 8 :: v_dual_mov_b32 v1, 0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v2, s42 :: v_dual_mov_b32 v3, s43 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: scratch_load_b64 v[2:3], off, off +; GFX1132-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s44 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB11_1 +; GFX1132-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-DPP-NEXT: s_endpgm + %divValue = call double @div.double.value() + %result = atomicrmw fmax ptr addrspace(1) %ptr, double %divValue monotonic, align 4 + ret void +} + attributes #0 = { "denormal-fp-math-f32"="preserve-sign,preserve-sign" "amdgpu-unsafe-fp-atomics"="true" } !llvm.module.flags = !{!0} diff --git a/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fmin.ll b/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fmin.ll index 314c52a71d938f7e5302f86b279589df7e25e5cd..49d415c9eed7790b6fc70a7b7a97186102b4e964 100644 --- a/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fmin.ll +++ b/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fmin.ll @@ -13,6 +13,7 @@ ; RUN: llc -mtriple=amdgcn -mcpu=gfx1100 -mattr=+wavefrontsize32,-wavefrontsize64 -amdgpu-atomic-optimizer-strategy=DPP -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GFX1132-DPP %s declare float @div.float.value() +declare float @div.double.value() define amdgpu_kernel void @global_atomic_fmin_uni_address_uni_value_agent_scope_unsafe(ptr addrspace(1) %ptr) #0 { ; GFX7LESS-LABEL: global_atomic_fmin_uni_address_uni_value_agent_scope_unsafe: @@ -3550,6 +3551,3965 @@ define amdgpu_kernel void @global_atomic_fmin_uni_address_div_value_defalut_scop ret void } +define amdgpu_kernel void @global_atomic_fmin_double_uni_address_uni_value_agent_scope_unsafe(ptr addrspace(1) %ptr) #0 { +; GFX7LESS-LABEL: global_atomic_fmin_double_uni_address_uni_value_agent_scope_unsafe: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_movk_i32 s32, 0x800 +; GFX7LESS-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s42, -1 +; GFX7LESS-NEXT: s_mov_b32 s43, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s40, s40, s3 +; GFX7LESS-NEXT: s_addc_u32 s41, s41, 0 +; GFX7LESS-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX7LESS-NEXT: v_mov_b32_e32 v40, v0 +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, exec_lo, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, exec_hi, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB6_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_mov_b32 s33, s2 +; GFX7LESS-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x9 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX7LESS-NEXT: s_mov_b64 s[38:39], 0 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, s0 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, s1 +; GFX7LESS-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_max_f64 v[2:3], v[0:1], v[0:1] +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[40:43], 0 offset:4 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[40:43], 0 +; GFX7LESS-NEXT: s_add_u32 s8, s34, 44 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_min_f64 v[0:1], v[2:3], 4.0 +; GFX7LESS-NEXT: s_addc_u32 s9, s35, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[40:43], 0 offset:12 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[40:43], 0 offset:8 +; GFX7LESS-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v4, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, 0 +; GFX7LESS-NEXT: s_mov_b32 s12, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v40 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s36 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s37 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX7LESS-NEXT: v_and_b32_e32 v2, 1, v0 +; GFX7LESS-NEXT: buffer_load_dword v0, off, s[40:43], 0 +; GFX7LESS-NEXT: buffer_load_dword v1, off, s[40:43], 0 offset:4 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 1, v2 +; GFX7LESS-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB6_2 +; GFX7LESS-NEXT: .LBB6_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fmin_double_uni_address_uni_value_agent_scope_unsafe: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s42, -1 +; GFX9-NEXT: s_mov_b32 s43, 0xe00000 +; GFX9-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-NEXT: s_add_u32 s40, s40, s3 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-NEXT: s_addc_u32 s41, s41, 0 +; GFX9-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_movk_i32 s32, 0x800 +; GFX9-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX9-NEXT: s_cbranch_execz .LBB6_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX9-NEXT: s_mov_b32 s33, s2 +; GFX9-NEXT: s_mov_b64 s[38:39], 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, s1 +; GFX9-NEXT: v_mov_b32_e32 v1, s0 +; GFX9-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX9-NEXT: s_add_u32 s8, s34, 44 +; GFX9-NEXT: s_addc_u32 s9, s35, 0 +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX9-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX9-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX9-NEXT: s_mov_b32 s12, s33 +; GFX9-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX9-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX9-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: v_mov_b32_e32 v2, s36 +; GFX9-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX9-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX9-NEXT: v_mov_b32_e32 v3, s37 +; GFX9-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX9-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX9-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX9-NEXT: s_cbranch_execnz .LBB6_2 +; GFX9-NEXT: .LBB6_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fmin_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s42, -1 +; GFX1064-NEXT: s_mov_b32 s43, 0x31e16000 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-NEXT: s_add_u32 s40, s40, s3 +; GFX1064-NEXT: s_addc_u32 s41, s41, 0 +; GFX1064-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1064-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB6_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1064-NEXT: s_mov_b32 s33, s2 +; GFX1064-NEXT: s_mov_b64 s[38:39], 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v2, s1 +; GFX1064-NEXT: v_mov_b32_e32 v1, s0 +; GFX1064-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1064-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1064-NEXT: s_mov_b32 s12, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1064-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX1064-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1064-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1064-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1064-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-NEXT: v_mov_b32_e32 v2, s36 +; GFX1064-NEXT: v_mov_b32_e32 v3, s37 +; GFX1064-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1064-NEXT: s_clause 0x1 +; GFX1064-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1064-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX1064-NEXT: s_cbranch_execnz .LBB6_2 +; GFX1064-NEXT: .LBB6_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fmin_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s42, -1 +; GFX1032-NEXT: s_mov_b32 s43, 0x31c16000 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_add_u32 s40, s40, s3 +; GFX1032-NEXT: s_addc_u32 s41, s41, 0 +; GFX1032-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1032-NEXT: s_mov_b32 s38, 0 +; GFX1032-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-NEXT: s_and_saveexec_b32 s0, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB6_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1032-NEXT: s_mov_b32 s33, s2 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v2, s1 +; GFX1032-NEXT: v_mov_b32_e32 v1, s0 +; GFX1032-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1032-NEXT: s_mov_b32 s12, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1032-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX1032-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1032-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1032-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1032-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-NEXT: v_mov_b32_e32 v2, s36 +; GFX1032-NEXT: v_mov_b32_e32 v3, s37 +; GFX1032-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1032-NEXT: s_clause 0x1 +; GFX1032-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1032-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s38 +; GFX1032-NEXT: s_cbranch_execnz .LBB6_2 +; GFX1032-NEXT: .LBB6_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fmin_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1164-NEXT: s_mov_b32 s32, 32 +; GFX1164-NEXT: s_mov_b64 s[0:1], exec +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-NEXT: s_cbranch_execz .LBB6_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1164-NEXT: s_mov_b32 s33, s2 +; GFX1164-NEXT: s_mov_b64 s[38:39], 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v2, s1 +; GFX1164-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-NEXT: .p2align 6 +; GFX1164-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-NEXT: s_mov_b32 s12, s33 +; GFX1164-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-NEXT: v_mov_b32_e32 v2, s36 +; GFX1164-NEXT: v_mov_b32_e32 v3, s37 +; GFX1164-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[38:39] +; GFX1164-NEXT: s_cbranch_execnz .LBB6_2 +; GFX1164-NEXT: .LBB6_3: +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fmin_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: v_mov_b32_e32 v40, v0 +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1132-NEXT: s_mov_b32 s38, 0 +; GFX1132-NEXT: s_mov_b32 s32, 32 +; GFX1132-NEXT: s_mov_b32 s0, exec_lo +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-NEXT: s_cbranch_execz .LBB6_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1132-NEXT: s_mov_b32 s33, s15 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: v_dual_mov_b32 v2, s1 :: v_dual_mov_b32 v1, s0 +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-NEXT: .p2align 6 +; GFX1132-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-NEXT: v_dual_mov_b32 v31, v40 :: v_dual_mov_b32 v0, 8 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-NEXT: s_mov_b32 s12, s33 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_4) +; GFX1132-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s36 +; GFX1132-NEXT: v_dual_mov_b32 v3, s37 :: v_dual_mov_b32 v4, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s38 +; GFX1132-NEXT: s_cbranch_execnz .LBB6_2 +; GFX1132-NEXT: .LBB6_3: +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fmin_double_uni_address_uni_value_agent_scope_unsafe: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s42, -1 +; GFX9-DPP-NEXT: s_mov_b32 s43, 0xe00000 +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB6_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX9-DPP-NEXT: s_mov_b32 s33, s2 +; GFX9-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX9-DPP-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX9-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX9-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX9-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX9-DPP-NEXT: s_mov_b32 s12, s33 +; GFX9-DPP-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX9-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX9-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX9-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX9-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB6_2 +; GFX9-DPP-NEXT: .LBB6_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fmin_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s42, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s43, 0x31e16000 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX1064-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1064-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB6_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1064-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1064-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1064-DPP-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1064-DPP-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX1064-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1064-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1064-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1064-DPP-NEXT: s_clause 0x1 +; GFX1064-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1064-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB6_2 +; GFX1064-DPP-NEXT: .LBB6_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fmin_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s42, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s43, 0x31c16000 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX1032-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1032-DPP-NEXT: s_mov_b32 s38, 0 +; GFX1032-DPP-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s0, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB6_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1032-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1032-DPP-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1032-DPP-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX1032-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1032-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1032-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1032-DPP-NEXT: s_clause 0x1 +; GFX1032-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1032-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s38 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB6_2 +; GFX1032-DPP-NEXT: .LBB6_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fmin_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1164-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1164-DPP-NEXT: s_mov_b64 s[0:1], exec +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB6_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1164-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1164-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-DPP-NEXT: .p2align 6 +; GFX1164-DPP-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1164-DPP-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[38:39] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB6_2 +; GFX1164-DPP-NEXT: .LBB6_3: +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fmin_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s38, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1132-DPP-NEXT: s_mov_b32 s0, exec_lo +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB6_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1132-DPP-NEXT: s_mov_b32 s33, s15 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v2, s1 :: v_dual_mov_b32 v1, s0 +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-DPP-NEXT: .p2align 6 +; GFX1132-DPP-NEXT: .LBB6_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v31, v40 :: v_dual_mov_b32 v0, 8 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_4) +; GFX1132-DPP-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s36 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, s37 :: v_dual_mov_b32 v4, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s38 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB6_2 +; GFX1132-DPP-NEXT: .LBB6_3: +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fmin ptr addrspace(1) %ptr, double 4.0 syncscope("agent") monotonic, align 4 + ret void +} + +define amdgpu_kernel void @global_atomic_fmin_double_uni_address_div_value_agent_scope_unsafe(ptr addrspace(1) %ptr) #0 { +; GFX7LESS-LABEL: global_atomic_fmin_double_uni_address_div_value_agent_scope_unsafe: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_movk_i32 s32, 0x800 +; GFX7LESS-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s50, -1 +; GFX7LESS-NEXT: s_mov_b32 s51, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s48, s48, s9 +; GFX7LESS-NEXT: s_addc_u32 s49, s49, 0 +; GFX7LESS-NEXT: s_mov_b32 s33, s8 +; GFX7LESS-NEXT: s_mov_b32 s40, s7 +; GFX7LESS-NEXT: s_mov_b32 s41, s6 +; GFX7LESS-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX7LESS-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX7LESS-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX7LESS-NEXT: s_load_dwordx2 s[44:45], s[2:3], 0x9 +; GFX7LESS-NEXT: s_mov_b32 s47, 0xf000 +; GFX7LESS-NEXT: s_mov_b32 s46, -1 +; GFX7LESS-NEXT: s_add_u32 s8, s36, 44 +; GFX7LESS-NEXT: s_addc_u32 s9, s37, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v0, v0, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v40, v0, v2 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX7LESS-NEXT: s_mov_b32 s12, s41 +; GFX7LESS-NEXT: s_mov_b32 s13, s40 +; GFX7LESS-NEXT: s_mov_b32 s14, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v40 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX7LESS-NEXT: buffer_load_dwordx2 v[2:3], off, s[44:47], 0 +; GFX7LESS-NEXT: s_mov_b64 s[42:43], 0 +; GFX7LESS-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX7LESS-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX7LESS-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX7LESS-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX7LESS-NEXT: s_add_u32 s8, s36, 44 +; GFX7LESS-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX7LESS-NEXT: s_addc_u32 s9, s37, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX7LESS-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v4, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, 0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX7LESS-NEXT: s_mov_b32 s12, s41 +; GFX7LESS-NEXT: s_mov_b32 s13, s40 +; GFX7LESS-NEXT: s_mov_b32 s14, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v40 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s44 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s45 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX7LESS-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX7LESS-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX7LESS-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX7LESS-NEXT: s_or_b64 s[42:43], vcc, s[42:43] +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[42:43] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB7_1 +; GFX7LESS-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fmin_double_uni_address_div_value_agent_scope_unsafe: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s50, -1 +; GFX9-NEXT: s_mov_b32 s51, 0xe00000 +; GFX9-NEXT: s_add_u32 s48, s48, s9 +; GFX9-NEXT: s_addc_u32 s49, s49, 0 +; GFX9-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX9-NEXT: s_mov_b32 s33, s8 +; GFX9-NEXT: s_add_u32 s8, s36, 44 +; GFX9-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX9-NEXT: s_mov_b32 s40, s7 +; GFX9-NEXT: s_mov_b32 s41, s6 +; GFX9-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX9-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX9-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-NEXT: s_mov_b32 s12, s41 +; GFX9-NEXT: s_mov_b32 s13, s40 +; GFX9-NEXT: s_mov_b32 s14, s33 +; GFX9-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-NEXT: s_movk_i32 s32, 0x800 +; GFX9-NEXT: v_mov_b32_e32 v41, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX9-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX9-NEXT: s_mov_b64 s[44:45], 0 +; GFX9-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX9-NEXT: s_add_u32 s8, s36, 44 +; GFX9-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX9-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX9-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX9-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-NEXT: s_mov_b32 s12, s41 +; GFX9-NEXT: s_mov_b32 s13, s40 +; GFX9-NEXT: s_mov_b32 s14, s33 +; GFX9-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-NEXT: v_mov_b32_e32 v2, s42 +; GFX9-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX9-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX9-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: v_mov_b32_e32 v3, s43 +; GFX9-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX9-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX9-NEXT: s_cbranch_execnz .LBB7_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fmin_double_uni_address_div_value_agent_scope_unsafe: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s50, -1 +; GFX1064-NEXT: s_mov_b32 s51, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s48, s48, s9 +; GFX1064-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1064-NEXT: s_addc_u32 s49, s49, 0 +; GFX1064-NEXT: s_mov_b32 s33, s8 +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1064-NEXT: s_mov_b32 s40, s7 +; GFX1064-NEXT: s_mov_b32 s41, s6 +; GFX1064-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1064-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1064-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX1064-NEXT: s_mov_b32 s12, s41 +; GFX1064-NEXT: s_mov_b32 s13, s40 +; GFX1064-NEXT: s_mov_b32 s14, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-NEXT: v_mov_b32_e32 v41, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX1064-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1064-NEXT: s_mov_b64 s[44:45], 0 +; GFX1064-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX1064-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX1064-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-NEXT: v_mov_b32_e32 v2, s42 +; GFX1064-NEXT: v_mov_b32_e32 v3, s43 +; GFX1064-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-NEXT: s_mov_b32 s12, s41 +; GFX1064-NEXT: s_mov_b32 s13, s40 +; GFX1064-NEXT: s_mov_b32 s14, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX1064-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX1064-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX1064-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-NEXT: s_clause 0x1 +; GFX1064-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX1064-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX1064-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX1064-NEXT: s_cbranch_execnz .LBB7_1 +; GFX1064-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fmin_double_uni_address_div_value_agent_scope_unsafe: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s50, -1 +; GFX1032-NEXT: s_mov_b32 s51, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s48, s48, s9 +; GFX1032-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1032-NEXT: s_addc_u32 s49, s49, 0 +; GFX1032-NEXT: s_mov_b32 s33, s8 +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1032-NEXT: s_mov_b32 s40, s7 +; GFX1032-NEXT: s_mov_b32 s41, s6 +; GFX1032-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1032-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1032-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX1032-NEXT: s_mov_b32 s12, s41 +; GFX1032-NEXT: s_mov_b32 s13, s40 +; GFX1032-NEXT: s_mov_b32 s14, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-NEXT: v_mov_b32_e32 v41, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX1032-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1032-NEXT: s_mov_b32 s44, 0 +; GFX1032-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX1032-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX1032-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-NEXT: v_mov_b32_e32 v2, s42 +; GFX1032-NEXT: v_mov_b32_e32 v3, s43 +; GFX1032-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-NEXT: s_mov_b32 s12, s41 +; GFX1032-NEXT: s_mov_b32 s13, s40 +; GFX1032-NEXT: s_mov_b32 s14, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX1032-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX1032-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX1032-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-NEXT: s_clause 0x1 +; GFX1032-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX1032-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX1032-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s44 +; GFX1032-NEXT: s_cbranch_execnz .LBB7_1 +; GFX1032-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fmin_double_uni_address_div_value_agent_scope_unsafe: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1164-NEXT: s_mov_b32 s33, s8 +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1164-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-NEXT: s_mov_b32 s12, s6 +; GFX1164-NEXT: s_mov_b32 s13, s7 +; GFX1164-NEXT: s_mov_b32 s14, s33 +; GFX1164-NEXT: s_mov_b32 s32, 32 +; GFX1164-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-NEXT: s_mov_b32 s40, s7 +; GFX1164-NEXT: s_mov_b32 s41, s6 +; GFX1164-NEXT: v_mov_b32_e32 v41, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: global_load_b64 v[2:3], v41, s[42:43] +; GFX1164-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1164-NEXT: s_mov_b64 s[44:45], 0 +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-NEXT: .p2align 6 +; GFX1164-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-NEXT: s_mov_b32 s12, s41 +; GFX1164-NEXT: s_mov_b32 s13, s40 +; GFX1164-NEXT: s_mov_b32 s14, s33 +; GFX1164-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b64 off, v[2:3], off +; GFX1164-NEXT: scratch_store_b64 off, v[0:1], off offset:8 +; GFX1164-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-NEXT: v_mov_b32_e32 v2, s42 +; GFX1164-NEXT: v_mov_b32_e32 v3, s43 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: scratch_load_b64 v[2:3], off, off +; GFX1164-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[44:45] +; GFX1164-NEXT: s_cbranch_execnz .LBB7_1 +; GFX1164-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fmin_double_uni_address_div_value_agent_scope_unsafe: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1132-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1132-NEXT: v_mov_b32_e32 v31, v0 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1132-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1132-NEXT: s_mov_b32 s40, s14 +; GFX1132-NEXT: s_mov_b32 s41, s13 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-NEXT: s_mov_b32 s12, s13 +; GFX1132-NEXT: s_mov_b32 s13, s14 +; GFX1132-NEXT: s_mov_b32 s14, s15 +; GFX1132-NEXT: s_mov_b32 s32, 32 +; GFX1132-NEXT: s_mov_b32 s33, s15 +; GFX1132-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v41, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: global_load_b64 v[2:3], v41, s[42:43] +; GFX1132-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1132-NEXT: s_mov_b32 s44, 0 +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-NEXT: .p2align 6 +; GFX1132-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-NEXT: v_mov_b32_e32 v31, v40 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-NEXT: s_mov_b32 s12, s41 +; GFX1132-NEXT: s_mov_b32 s13, s40 +; GFX1132-NEXT: s_mov_b32 s14, s33 +; GFX1132-NEXT: v_mov_b32_e32 v4, 0 +; GFX1132-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b64 off, v[2:3], off +; GFX1132-NEXT: scratch_store_b64 off, v[0:1], off offset:8 +; GFX1132-NEXT: v_dual_mov_b32 v0, 8 :: v_dual_mov_b32 v1, 0 +; GFX1132-NEXT: v_dual_mov_b32 v2, s42 :: v_dual_mov_b32 v3, s43 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: scratch_load_b64 v[2:3], off, off +; GFX1132-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s44 +; GFX1132-NEXT: s_cbranch_execnz .LBB7_1 +; GFX1132-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fmin_double_uni_address_div_value_agent_scope_unsafe: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s50, -1 +; GFX9-DPP-NEXT: s_mov_b32 s51, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX9-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX9-DPP-NEXT: s_mov_b32 s33, s8 +; GFX9-DPP-NEXT: s_add_u32 s8, s36, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_mov_b32 s40, s7 +; GFX9-DPP-NEXT: s_mov_b32 s41, s6 +; GFX9-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-DPP-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX9-DPP-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-DPP-NEXT: s_mov_b32 s12, s41 +; GFX9-DPP-NEXT: s_mov_b32 s13, s40 +; GFX9-DPP-NEXT: s_mov_b32 s14, s33 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX9-DPP-NEXT: v_mov_b32_e32 v41, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-DPP-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX9-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX9-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX9-DPP-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX9-DPP-NEXT: s_add_u32 s8, s36, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX9-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-DPP-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-DPP-NEXT: s_mov_b32 s12, s41 +; GFX9-DPP-NEXT: s_mov_b32 s13, s40 +; GFX9-DPP-NEXT: s_mov_b32 s14, s33 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX9-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX9-DPP-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX9-DPP-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX9-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB7_1 +; GFX9-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fmin_double_uni_address_div_value_agent_scope_unsafe: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s50, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s51, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX1064-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1064-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1064-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-DPP-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX1064-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v41, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-DPP-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX1064-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1064-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX1064-DPP-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX1064-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-DPP-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX1064-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX1064-DPP-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-DPP-NEXT: s_clause 0x1 +; GFX1064-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX1064-DPP-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX1064-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB7_1 +; GFX1064-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fmin_double_uni_address_div_value_agent_scope_unsafe: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s50, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s51, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX1032-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1032-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1032-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-DPP-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX1032-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-DPP-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v41, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-DPP-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX1032-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1032-DPP-NEXT: s_mov_b32 s44, 0 +; GFX1032-DPP-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX1032-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-DPP-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX1032-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX1032-DPP-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-DPP-NEXT: s_clause 0x1 +; GFX1032-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX1032-DPP-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX1032-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s44 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB7_1 +; GFX1032-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fmin_double_uni_address_div_value_agent_scope_unsafe: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1164-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1164-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v41, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: global_load_b64 v[2:3], v41, s[42:43] +; GFX1164-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1164-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-DPP-NEXT: .p2align 6 +; GFX1164-DPP-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1164-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1164-DPP-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[2:3], off +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[0:1], off offset:8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: scratch_load_b64 v[2:3], off, off +; GFX1164-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[44:45] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB7_1 +; GFX1164-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fmin_double_uni_address_div_value_agent_scope_unsafe: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1132-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1132-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1132-DPP-NEXT: s_mov_b32 s40, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s41, s13 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-DPP-NEXT: s_mov_b32 s12, s13 +; GFX1132-DPP-NEXT: s_mov_b32 s13, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s15 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1132-DPP-NEXT: s_mov_b32 s33, s15 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v41, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: global_load_b64 v[2:3], v41, s[42:43] +; GFX1132-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s44, 0 +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-DPP-NEXT: .p2align 6 +; GFX1132-DPP-NEXT: .LBB7_1: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1132-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1132-DPP-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[2:3], off +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[0:1], off offset:8 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v0, 8 :: v_dual_mov_b32 v1, 0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v2, s42 :: v_dual_mov_b32 v3, s43 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: scratch_load_b64 v[2:3], off, off +; GFX1132-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s44 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB7_1 +; GFX1132-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-DPP-NEXT: s_endpgm + %divValue = call double @div.double.value() + %result = atomicrmw fmin ptr addrspace(1) %ptr, double %divValue syncscope("agent") monotonic, align 4 + ret void +} + +define amdgpu_kernel void @global_atomic_fmin_double_uni_address_uni_value_one_as_scope_unsafe(ptr addrspace(1) %ptr) #0 { +; GFX7LESS-LABEL: global_atomic_fmin_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, exec_lo, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, exec_hi, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB8_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x9 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], 0 +; GFX7LESS-NEXT: s_mov_b32 s3, 0xf000 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s6 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s7 +; GFX7LESS-NEXT: s_mov_b32 s2, -1 +; GFX7LESS-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX7LESS-NEXT: v_min_f64 v[0:1], v[0:1], 4.0 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v7, v3 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, v2 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, v1 +; GFX7LESS-NEXT: v_mov_b32_e32 v4, v0 +; GFX7LESS-NEXT: buffer_atomic_cmpswap_x2 v[4:7], off, s[0:3], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u64_e32 vcc, v[4:5], v[2:3] +; GFX7LESS-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX7LESS-NEXT: v_mov_b32_e32 v2, v4 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, v5 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB8_2 +; GFX7LESS-NEXT: .LBB8_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fmin_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-NEXT: s_cbranch_execz .LBB8_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-NEXT: v_mov_b32_e32 v3, s5 +; GFX9-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX9-NEXT: v_min_f64 v[0:1], v[0:1], 4.0 +; GFX9-NEXT: global_atomic_cmpswap_x2 v[0:1], v4, v[0:3], s[0:1] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX9-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-NEXT: s_cbranch_execnz .LBB8_2 +; GFX9-NEXT: .LBB8_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fmin_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB8_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v2, s2 +; GFX1064-NEXT: v_mov_b32_e32 v3, s3 +; GFX1064-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1064-NEXT: v_min_f64 v[0:1], v[0:1], 4.0 +; GFX1064-NEXT: global_atomic_cmpswap_x2 v[0:1], v4, v[0:3], s[0:1] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1064-NEXT: v_mov_b32_e32 v3, v1 +; GFX1064-NEXT: v_mov_b32_e32 v2, v0 +; GFX1064-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-NEXT: s_cbranch_execnz .LBB8_2 +; GFX1064-NEXT: .LBB8_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fmin_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-NEXT: s_mov_b32 s2, 0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_and_saveexec_b32 s3, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB8_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v2, s4 +; GFX1032-NEXT: v_mov_b32_e32 v3, s5 +; GFX1032-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1032-NEXT: v_min_f64 v[0:1], v[0:1], 4.0 +; GFX1032-NEXT: global_atomic_cmpswap_x2 v[0:1], v4, v[0:3], s[0:1] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1032-NEXT: v_mov_b32_e32 v3, v1 +; GFX1032-NEXT: v_mov_b32_e32 v2, v0 +; GFX1032-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-NEXT: s_cbranch_execnz .LBB8_2 +; GFX1032-NEXT: .LBB8_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fmin_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-NEXT: s_cbranch_execz .LBB8_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b64 s[2:3], s[0:1], 0x0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v2, s2 +; GFX1164-NEXT: v_mov_b32_e32 v3, s3 +; GFX1164-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1164-NEXT: v_min_f64 v[0:1], v[0:1], 4.0 +; GFX1164-NEXT: global_atomic_cmpswap_b64 v[0:1], v4, v[0:3], s[0:1] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1164-NEXT: v_mov_b32_e32 v3, v1 +; GFX1164-NEXT: v_mov_b32_e32 v2, v0 +; GFX1164-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-NEXT: s_cbranch_execnz .LBB8_2 +; GFX1164-NEXT: .LBB8_3: +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fmin_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-NEXT: s_mov_b32 s2, 0 +; GFX1132-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-NEXT: s_cbranch_execz .LBB8_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-NEXT: v_mov_b32_e32 v4, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b64 s[4:5], s[0:1], 0x0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: v_dual_mov_b32 v2, s4 :: v_dual_mov_b32 v3, s5 +; GFX1132-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1132-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1132-NEXT: v_min_f64 v[0:1], v[0:1], 4.0 +; GFX1132-NEXT: global_atomic_cmpswap_b64 v[0:1], v4, v[0:3], s[0:1] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1132-NEXT: v_dual_mov_b32 v3, v1 :: v_dual_mov_b32 v2, v0 +; GFX1132-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-NEXT: s_cbranch_execnz .LBB8_2 +; GFX1132-NEXT: .LBB8_3: +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fmin_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB8_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s5 +; GFX9-DPP-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX9-DPP-NEXT: v_min_f64 v[0:1], v[0:1], 4.0 +; GFX9-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v4, v[0:3], s[0:1] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB8_2 +; GFX9-DPP-NEXT: .LBB8_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fmin_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB8_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s2 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s3 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-DPP-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1064-DPP-NEXT: v_min_f64 v[0:1], v[0:1], 4.0 +; GFX1064-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v4, v[0:3], s[0:1] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB8_2 +; GFX1064-DPP-NEXT: .LBB8_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fmin_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s3, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB8_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s4 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s5 +; GFX1032-DPP-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1032-DPP-NEXT: v_min_f64 v[0:1], v[0:1], 4.0 +; GFX1032-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v4, v[0:3], s[0:1] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1032-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB8_2 +; GFX1032-DPP-NEXT: .LBB8_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fmin_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB8_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b64 s[2:3], s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s2 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s3 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-DPP-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1164-DPP-NEXT: v_min_f64 v[0:1], v[0:1], 4.0 +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b64 v[0:1], v4, v[0:3], s[0:1] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB8_2 +; GFX1164-DPP-NEXT: .LBB8_3: +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fmin_double_uni_address_uni_value_one_as_scope_unsafe: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB8_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b64 s[4:5], s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v2, s4 :: v_dual_mov_b32 v3, s5 +; GFX1132-DPP-NEXT: .LBB8_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1132-DPP-NEXT: v_min_f64 v[0:1], v[0:1], 4.0 +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b64 v[0:1], v4, v[0:3], s[0:1] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, v1 :: v_dual_mov_b32 v2, v0 +; GFX1132-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB8_2 +; GFX1132-DPP-NEXT: .LBB8_3: +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fmin ptr addrspace(1) %ptr, double 4.0 syncscope("one-as") monotonic + ret void +} + +define amdgpu_kernel void @global_atomic_fmin_double_uni_address_div_value_one_as_scope_unsafe(ptr addrspace(1) %ptr) #0 { +; GFX7LESS-LABEL: global_atomic_fmin_double_uni_address_div_value_one_as_scope_unsafe: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_mov_b32 s32, 0 +; GFX7LESS-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s42, -1 +; GFX7LESS-NEXT: s_mov_b32 s43, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s40, s40, s9 +; GFX7LESS-NEXT: s_addc_u32 s41, s41, 0 +; GFX7LESS-NEXT: s_mov_b32 s14, s8 +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX7LESS-NEXT: s_load_dwordx2 s[36:37], s[2:3], 0x9 +; GFX7LESS-NEXT: s_mov_b32 s39, 0xf000 +; GFX7LESS-NEXT: s_mov_b32 s38, -1 +; GFX7LESS-NEXT: s_add_u32 s8, s2, 44 +; GFX7LESS-NEXT: s_addc_u32 s9, s3, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[2:3] +; GFX7LESS-NEXT: s_add_u32 s2, s2, div.double.value@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s3, s3, div.double.value@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v0, v0, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v31, v0, v2 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX7LESS-NEXT: s_mov_b32 s12, s6 +; GFX7LESS-NEXT: s_mov_b32 s13, s7 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX7LESS-NEXT: buffer_load_dwordx2 v[2:3], off, s[36:39], 0 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], 0 +; GFX7LESS-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX7LESS-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX7LESS-NEXT: v_min_f64 v[0:1], v[0:1], v[4:5] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v9, v3 +; GFX7LESS-NEXT: v_mov_b32_e32 v8, v2 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, v1 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, v0 +; GFX7LESS-NEXT: buffer_atomic_cmpswap_x2 v[6:9], off, s[36:39], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[2:3] +; GFX7LESS-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX7LESS-NEXT: v_mov_b32_e32 v2, v6 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, v7 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB9_1 +; GFX7LESS-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fmin_double_uni_address_div_value_one_as_scope_unsafe: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s38, -1 +; GFX9-NEXT: s_mov_b32 s39, 0xe00000 +; GFX9-NEXT: s_add_u32 s36, s36, s9 +; GFX9-NEXT: s_addc_u32 s37, s37, 0 +; GFX9-NEXT: s_mov_b32 s14, s8 +; GFX9-NEXT: s_add_u32 s8, s2, 44 +; GFX9-NEXT: s_addc_u32 s9, s3, 0 +; GFX9-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX9-NEXT: s_getpc_b64 s[2:3] +; GFX9-NEXT: s_add_u32 s2, s2, div.double.value@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s3, s3, div.double.value@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX9-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX9-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX9-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX9-NEXT: s_mov_b32 s12, s6 +; GFX9-NEXT: s_mov_b32 s13, s7 +; GFX9-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX9-NEXT: s_mov_b32 s32, 0 +; GFX9-NEXT: v_mov_b32_e32 v40, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX9-NEXT: global_load_dwordx2 v[2:3], v40, s[34:35] +; GFX9-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX9-NEXT: s_mov_b64 s[0:1], 0 +; GFX9-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX9-NEXT: v_min_f64 v[0:1], v[0:1], v[4:5] +; GFX9-NEXT: global_atomic_cmpswap_x2 v[0:1], v40, v[0:3], s[34:35] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX9-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX9-NEXT: s_cbranch_execnz .LBB9_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fmin_double_uni_address_div_value_one_as_scope_unsafe: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s38, -1 +; GFX1064-NEXT: s_mov_b32 s39, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s36, s36, s9 +; GFX1064-NEXT: s_addc_u32 s37, s37, 0 +; GFX1064-NEXT: s_mov_b32 s14, s8 +; GFX1064-NEXT: s_add_u32 s8, s2, 44 +; GFX1064-NEXT: s_addc_u32 s9, s3, 0 +; GFX1064-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1064-NEXT: s_getpc_b64 s[4:5] +; GFX1064-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1064-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1064-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1064-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1064-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1064-NEXT: s_mov_b32 s12, s6 +; GFX1064-NEXT: s_mov_b32 s13, s7 +; GFX1064-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1064-NEXT: s_mov_b32 s32, 0 +; GFX1064-NEXT: v_mov_b32_e32 v40, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1064-NEXT: global_load_dwordx2 v[2:3], v40, s[34:35] +; GFX1064-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX1064-NEXT: s_mov_b64 s[0:1], 0 +; GFX1064-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1064-NEXT: v_min_f64 v[0:1], v[0:1], v[4:5] +; GFX1064-NEXT: global_atomic_cmpswap_x2 v[0:1], v40, v[0:3], s[34:35] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1064-NEXT: v_mov_b32_e32 v3, v1 +; GFX1064-NEXT: v_mov_b32_e32 v2, v0 +; GFX1064-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX1064-NEXT: s_cbranch_execnz .LBB9_1 +; GFX1064-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fmin_double_uni_address_div_value_one_as_scope_unsafe: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s38, -1 +; GFX1032-NEXT: s_mov_b32 s39, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s36, s36, s9 +; GFX1032-NEXT: s_addc_u32 s37, s37, 0 +; GFX1032-NEXT: s_mov_b32 s14, s8 +; GFX1032-NEXT: s_add_u32 s8, s2, 44 +; GFX1032-NEXT: s_addc_u32 s9, s3, 0 +; GFX1032-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1032-NEXT: s_getpc_b64 s[4:5] +; GFX1032-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1032-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1032-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1032-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1032-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1032-NEXT: s_mov_b32 s12, s6 +; GFX1032-NEXT: s_mov_b32 s13, s7 +; GFX1032-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1032-NEXT: s_mov_b32 s32, 0 +; GFX1032-NEXT: v_mov_b32_e32 v40, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1032-NEXT: global_load_dwordx2 v[2:3], v40, s[34:35] +; GFX1032-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX1032-NEXT: s_mov_b32 s0, 0 +; GFX1032-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1032-NEXT: v_min_f64 v[0:1], v[0:1], v[4:5] +; GFX1032-NEXT: global_atomic_cmpswap_x2 v[0:1], v40, v[0:3], s[34:35] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1032-NEXT: v_mov_b32_e32 v3, v1 +; GFX1032-NEXT: v_mov_b32_e32 v2, v0 +; GFX1032-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s0 +; GFX1032-NEXT: s_cbranch_execnz .LBB9_1 +; GFX1032-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fmin_double_uni_address_div_value_one_as_scope_unsafe: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b32 s14, s8 +; GFX1164-NEXT: s_add_u32 s8, s2, 44 +; GFX1164-NEXT: s_addc_u32 s9, s3, 0 +; GFX1164-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1164-NEXT: s_getpc_b64 s[4:5] +; GFX1164-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1164-NEXT: s_load_b64 s[16:17], s[4:5], 0x0 +; GFX1164-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1164-NEXT: s_mov_b32 s12, s6 +; GFX1164-NEXT: s_mov_b32 s13, s7 +; GFX1164-NEXT: s_mov_b32 s32, 0 +; GFX1164-NEXT: v_mov_b32_e32 v40, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1164-NEXT: global_load_b64 v[2:3], v40, s[34:35] +; GFX1164-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX1164-NEXT: s_mov_b64 s[0:1], 0 +; GFX1164-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_min_f64 v[0:1], v[0:1], v[4:5] +; GFX1164-NEXT: global_atomic_cmpswap_b64 v[0:1], v40, v[0:3], s[34:35] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1164-NEXT: v_mov_b32_e32 v3, v1 +; GFX1164-NEXT: v_mov_b32_e32 v2, v0 +; GFX1164-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[0:1] +; GFX1164-NEXT: s_cbranch_execnz .LBB9_1 +; GFX1164-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fmin_double_uni_address_div_value_one_as_scope_unsafe: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_add_u32 s8, s2, 44 +; GFX1132-NEXT: s_addc_u32 s9, s3, 0 +; GFX1132-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1132-NEXT: s_getpc_b64 s[4:5] +; GFX1132-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1132-NEXT: s_load_b64 s[6:7], s[4:5], 0x0 +; GFX1132-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1132-NEXT: v_dual_mov_b32 v40, 0 :: v_dual_mov_b32 v31, v0 +; GFX1132-NEXT: s_mov_b32 s12, s13 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1132-NEXT: s_mov_b32 s13, s14 +; GFX1132-NEXT: s_mov_b32 s14, s15 +; GFX1132-NEXT: s_mov_b32 s32, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1132-NEXT: global_load_b64 v[2:3], v40, s[34:35] +; GFX1132-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX1132-NEXT: s_mov_b32 s0, 0 +; GFX1132-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_min_f64 v[0:1], v[0:1], v[4:5] +; GFX1132-NEXT: global_atomic_cmpswap_b64 v[0:1], v40, v[0:3], s[34:35] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1132-NEXT: v_dual_mov_b32 v3, v1 :: v_dual_mov_b32 v2, v0 +; GFX1132-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s0 +; GFX1132-NEXT: s_cbranch_execnz .LBB9_1 +; GFX1132-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fmin_double_uni_address_div_value_one_as_scope_unsafe: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s38, -1 +; GFX9-DPP-NEXT: s_mov_b32 s39, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX9-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX9-DPP-NEXT: s_mov_b32 s14, s8 +; GFX9-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX9-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX9-DPP-NEXT: s_getpc_b64 s[2:3] +; GFX9-DPP-NEXT: s_add_u32 s2, s2, div.double.value@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s3, s3, div.double.value@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX9-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX9-DPP-NEXT: s_mov_b32 s12, s6 +; GFX9-DPP-NEXT: s_mov_b32 s13, s7 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX9-DPP-NEXT: s_mov_b32 s32, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX9-DPP-NEXT: global_load_dwordx2 v[2:3], v40, s[34:35] +; GFX9-DPP-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX9-DPP-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX9-DPP-NEXT: v_min_f64 v[0:1], v[0:1], v[4:5] +; GFX9-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v40, v[0:3], s[34:35] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB9_1 +; GFX9-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fmin_double_uni_address_div_value_one_as_scope_unsafe: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s38, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s39, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX1064-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1064-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1064-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1064-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1064-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1064-DPP-NEXT: global_load_dwordx2 v[2:3], v40, s[34:35] +; GFX1064-DPP-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX1064-DPP-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1064-DPP-NEXT: v_min_f64 v[0:1], v[0:1], v[4:5] +; GFX1064-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v40, v[0:3], s[34:35] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB9_1 +; GFX1064-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fmin_double_uni_address_div_value_one_as_scope_unsafe: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s38, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s39, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX1032-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1032-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1032-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1032-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1032-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1032-DPP-NEXT: global_load_dwordx2 v[2:3], v40, s[34:35] +; GFX1032-DPP-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX1032-DPP-NEXT: s_mov_b32 s0, 0 +; GFX1032-DPP-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1032-DPP-NEXT: v_min_f64 v[0:1], v[0:1], v[4:5] +; GFX1032-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v40, v[0:3], s[34:35] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1032-DPP-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s0 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB9_1 +; GFX1032-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fmin_double_uni_address_div_value_one_as_scope_unsafe: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1164-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1164-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1164-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: s_load_b64 s[16:17], s[4:5], 0x0 +; GFX1164-DPP-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1164-DPP-NEXT: global_load_b64 v[2:3], v40, s[34:35] +; GFX1164-DPP-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX1164-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX1164-DPP-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_min_f64 v[0:1], v[0:1], v[4:5] +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b64 v[0:1], v40, v[0:3], s[34:35] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[0:1] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB9_1 +; GFX1164-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fmin_double_uni_address_div_value_one_as_scope_unsafe: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1132-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1132-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: s_load_b64 s[6:7], s[4:5], 0x0 +; GFX1132-DPP-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v40, 0 :: v_dual_mov_b32 v31, v0 +; GFX1132-DPP-NEXT: s_mov_b32 s12, s13 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s13, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s15 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1132-DPP-NEXT: global_load_b64 v[2:3], v40, s[34:35] +; GFX1132-DPP-NEXT: v_max_f64 v[4:5], v[0:1], v[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s0, 0 +; GFX1132-DPP-NEXT: .LBB9_1: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_min_f64 v[0:1], v[0:1], v[4:5] +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b64 v[0:1], v40, v[0:3], s[34:35] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, v1 :: v_dual_mov_b32 v2, v0 +; GFX1132-DPP-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s0 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB9_1 +; GFX1132-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-DPP-NEXT: s_endpgm + %divValue = call double @div.double.value() + %result = atomicrmw fmin ptr addrspace(1) %ptr, double %divValue syncscope("one-as") monotonic + ret void +} + +define amdgpu_kernel void @global_atomic_fmin_double_uni_address_uni_value_defalut_scope_unsafe(ptr addrspace(1) %ptr) #0 { +; GFX7LESS-LABEL: global_atomic_fmin_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_movk_i32 s32, 0x800 +; GFX7LESS-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s42, -1 +; GFX7LESS-NEXT: s_mov_b32 s43, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s40, s40, s3 +; GFX7LESS-NEXT: s_addc_u32 s41, s41, 0 +; GFX7LESS-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX7LESS-NEXT: v_mov_b32_e32 v40, v0 +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, exec_lo, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, exec_hi, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB10_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_mov_b32 s33, s2 +; GFX7LESS-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x9 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX7LESS-NEXT: s_mov_b64 s[38:39], 0 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, s0 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, s1 +; GFX7LESS-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_max_f64 v[2:3], v[0:1], v[0:1] +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[40:43], 0 offset:4 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[40:43], 0 +; GFX7LESS-NEXT: s_add_u32 s8, s34, 44 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_min_f64 v[0:1], v[2:3], 4.0 +; GFX7LESS-NEXT: s_addc_u32 s9, s35, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[40:43], 0 offset:12 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[40:43], 0 offset:8 +; GFX7LESS-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v4, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, 0 +; GFX7LESS-NEXT: s_mov_b32 s12, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v40 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s36 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s37 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX7LESS-NEXT: v_and_b32_e32 v2, 1, v0 +; GFX7LESS-NEXT: buffer_load_dword v0, off, s[40:43], 0 +; GFX7LESS-NEXT: buffer_load_dword v1, off, s[40:43], 0 offset:4 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 1, v2 +; GFX7LESS-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB10_2 +; GFX7LESS-NEXT: .LBB10_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fmin_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s42, -1 +; GFX9-NEXT: s_mov_b32 s43, 0xe00000 +; GFX9-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-NEXT: s_add_u32 s40, s40, s3 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-NEXT: s_addc_u32 s41, s41, 0 +; GFX9-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_movk_i32 s32, 0x800 +; GFX9-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX9-NEXT: s_cbranch_execz .LBB10_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX9-NEXT: s_mov_b32 s33, s2 +; GFX9-NEXT: s_mov_b64 s[38:39], 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, s1 +; GFX9-NEXT: v_mov_b32_e32 v1, s0 +; GFX9-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX9-NEXT: s_add_u32 s8, s34, 44 +; GFX9-NEXT: s_addc_u32 s9, s35, 0 +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX9-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX9-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX9-NEXT: s_mov_b32 s12, s33 +; GFX9-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX9-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX9-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: v_mov_b32_e32 v2, s36 +; GFX9-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX9-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX9-NEXT: v_mov_b32_e32 v3, s37 +; GFX9-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX9-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX9-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX9-NEXT: s_cbranch_execnz .LBB10_2 +; GFX9-NEXT: .LBB10_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fmin_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s42, -1 +; GFX1064-NEXT: s_mov_b32 s43, 0x31e16000 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-NEXT: s_add_u32 s40, s40, s3 +; GFX1064-NEXT: s_addc_u32 s41, s41, 0 +; GFX1064-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1064-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB10_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1064-NEXT: s_mov_b32 s33, s2 +; GFX1064-NEXT: s_mov_b64 s[38:39], 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v2, s1 +; GFX1064-NEXT: v_mov_b32_e32 v1, s0 +; GFX1064-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1064-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1064-NEXT: s_mov_b32 s12, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1064-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX1064-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1064-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1064-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1064-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-NEXT: v_mov_b32_e32 v2, s36 +; GFX1064-NEXT: v_mov_b32_e32 v3, s37 +; GFX1064-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1064-NEXT: s_clause 0x1 +; GFX1064-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1064-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX1064-NEXT: s_cbranch_execnz .LBB10_2 +; GFX1064-NEXT: .LBB10_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fmin_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s42, -1 +; GFX1032-NEXT: s_mov_b32 s43, 0x31c16000 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_add_u32 s40, s40, s3 +; GFX1032-NEXT: s_addc_u32 s41, s41, 0 +; GFX1032-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1032-NEXT: s_mov_b32 s38, 0 +; GFX1032-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-NEXT: s_and_saveexec_b32 s0, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB10_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1032-NEXT: s_mov_b32 s33, s2 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v2, s1 +; GFX1032-NEXT: v_mov_b32_e32 v1, s0 +; GFX1032-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1032-NEXT: s_mov_b32 s12, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1032-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX1032-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1032-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1032-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1032-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-NEXT: v_mov_b32_e32 v2, s36 +; GFX1032-NEXT: v_mov_b32_e32 v3, s37 +; GFX1032-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1032-NEXT: s_clause 0x1 +; GFX1032-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1032-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s38 +; GFX1032-NEXT: s_cbranch_execnz .LBB10_2 +; GFX1032-NEXT: .LBB10_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fmin_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1164-NEXT: s_mov_b32 s32, 32 +; GFX1164-NEXT: s_mov_b64 s[0:1], exec +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-NEXT: s_cbranch_execz .LBB10_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1164-NEXT: s_mov_b32 s33, s2 +; GFX1164-NEXT: s_mov_b64 s[38:39], 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v2, s1 +; GFX1164-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-NEXT: .p2align 6 +; GFX1164-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-NEXT: s_mov_b32 s12, s33 +; GFX1164-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-NEXT: v_mov_b32_e32 v2, s36 +; GFX1164-NEXT: v_mov_b32_e32 v3, s37 +; GFX1164-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[38:39] +; GFX1164-NEXT: s_cbranch_execnz .LBB10_2 +; GFX1164-NEXT: .LBB10_3: +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fmin_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: v_mov_b32_e32 v40, v0 +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1132-NEXT: s_mov_b32 s38, 0 +; GFX1132-NEXT: s_mov_b32 s32, 32 +; GFX1132-NEXT: s_mov_b32 s0, exec_lo +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-NEXT: s_cbranch_execz .LBB10_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1132-NEXT: s_mov_b32 s33, s15 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: v_dual_mov_b32 v2, s1 :: v_dual_mov_b32 v1, s0 +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-NEXT: .p2align 6 +; GFX1132-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-NEXT: v_dual_mov_b32 v31, v40 :: v_dual_mov_b32 v0, 8 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-NEXT: s_mov_b32 s12, s33 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_4) +; GFX1132-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s36 +; GFX1132-NEXT: v_dual_mov_b32 v3, s37 :: v_dual_mov_b32 v4, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s38 +; GFX1132-NEXT: s_cbranch_execnz .LBB10_2 +; GFX1132-NEXT: .LBB10_3: +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fmin_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s42, -1 +; GFX9-DPP-NEXT: s_mov_b32 s43, 0xe00000 +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX9-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX9-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB10_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX9-DPP-NEXT: s_mov_b32 s33, s2 +; GFX9-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX9-DPP-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX9-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX9-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX9-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX9-DPP-NEXT: s_mov_b32 s12, s33 +; GFX9-DPP-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX9-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX9-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX9-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX9-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB10_2 +; GFX9-DPP-NEXT: .LBB10_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fmin_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s42, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s43, 0x31e16000 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1064-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX1064-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1064-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB10_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1064-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1064-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1064-DPP-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1064-DPP-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX1064-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1064-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1064-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1064-DPP-NEXT: s_clause 0x1 +; GFX1064-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1064-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB10_2 +; GFX1064-DPP-NEXT: .LBB10_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fmin_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s42, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s43, 0x31c16000 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX1032-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1032-DPP-NEXT: s_mov_b32 s38, 0 +; GFX1032-DPP-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s0, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB10_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1032-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1032-DPP-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1032-DPP-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX1032-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1032-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1032-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1032-DPP-NEXT: s_clause 0x1 +; GFX1032-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1032-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s38 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB10_2 +; GFX1032-DPP-NEXT: .LBB10_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fmin_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1164-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1164-DPP-NEXT: s_mov_b64 s[0:1], exec +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, exec_hi, v0 +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB10_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1164-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1164-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-DPP-NEXT: .p2align 6 +; GFX1164-DPP-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1164-DPP-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[38:39] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB10_2 +; GFX1164-DPP-NEXT: .LBB10_3: +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fmin_double_uni_address_uni_value_defalut_scope_unsafe: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, exec_lo, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s38, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1132-DPP-NEXT: s_mov_b32 s0, exec_lo +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB10_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1132-DPP-NEXT: s_mov_b32 s33, s15 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v2, s1 :: v_dual_mov_b32 v1, s0 +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-DPP-NEXT: .p2align 6 +; GFX1132-DPP-NEXT: .LBB10_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_max_f64 v[3:4], v[1:2], v[1:2] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v31, v40 :: v_dual_mov_b32 v0, 8 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_4) +; GFX1132-DPP-NEXT: v_min_f64 v[3:4], v[3:4], 4.0 +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s36 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, s37 :: v_dual_mov_b32 v4, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s38 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB10_2 +; GFX1132-DPP-NEXT: .LBB10_3: +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fmin ptr addrspace(1) %ptr, double 4.0 monotonic, align 4 + ret void +} + +define amdgpu_kernel void @global_atomic_fmin_double_uni_address_div_value_defalut_scope_unsafe(ptr addrspace(1) %ptr) #0 { +; GFX7LESS-LABEL: global_atomic_fmin_double_uni_address_div_value_defalut_scope_unsafe: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_movk_i32 s32, 0x800 +; GFX7LESS-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s50, -1 +; GFX7LESS-NEXT: s_mov_b32 s51, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s48, s48, s9 +; GFX7LESS-NEXT: s_addc_u32 s49, s49, 0 +; GFX7LESS-NEXT: s_mov_b32 s33, s8 +; GFX7LESS-NEXT: s_mov_b32 s40, s7 +; GFX7LESS-NEXT: s_mov_b32 s41, s6 +; GFX7LESS-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX7LESS-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX7LESS-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX7LESS-NEXT: s_load_dwordx2 s[44:45], s[2:3], 0x9 +; GFX7LESS-NEXT: s_mov_b32 s47, 0xf000 +; GFX7LESS-NEXT: s_mov_b32 s46, -1 +; GFX7LESS-NEXT: s_add_u32 s8, s36, 44 +; GFX7LESS-NEXT: s_addc_u32 s9, s37, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v0, v0, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v40, v0, v2 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX7LESS-NEXT: s_mov_b32 s12, s41 +; GFX7LESS-NEXT: s_mov_b32 s13, s40 +; GFX7LESS-NEXT: s_mov_b32 s14, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v40 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX7LESS-NEXT: buffer_load_dwordx2 v[2:3], off, s[44:47], 0 +; GFX7LESS-NEXT: s_mov_b64 s[42:43], 0 +; GFX7LESS-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX7LESS-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX7LESS-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX7LESS-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX7LESS-NEXT: s_add_u32 s8, s36, 44 +; GFX7LESS-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX7LESS-NEXT: s_addc_u32 s9, s37, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX7LESS-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v4, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, 0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX7LESS-NEXT: s_mov_b32 s12, s41 +; GFX7LESS-NEXT: s_mov_b32 s13, s40 +; GFX7LESS-NEXT: s_mov_b32 s14, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v40 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s44 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s45 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX7LESS-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX7LESS-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX7LESS-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX7LESS-NEXT: s_or_b64 s[42:43], vcc, s[42:43] +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[42:43] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB11_1 +; GFX7LESS-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fmin_double_uni_address_div_value_defalut_scope_unsafe: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s50, -1 +; GFX9-NEXT: s_mov_b32 s51, 0xe00000 +; GFX9-NEXT: s_add_u32 s48, s48, s9 +; GFX9-NEXT: s_addc_u32 s49, s49, 0 +; GFX9-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX9-NEXT: s_mov_b32 s33, s8 +; GFX9-NEXT: s_add_u32 s8, s36, 44 +; GFX9-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX9-NEXT: s_mov_b32 s40, s7 +; GFX9-NEXT: s_mov_b32 s41, s6 +; GFX9-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX9-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX9-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-NEXT: s_mov_b32 s12, s41 +; GFX9-NEXT: s_mov_b32 s13, s40 +; GFX9-NEXT: s_mov_b32 s14, s33 +; GFX9-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-NEXT: s_movk_i32 s32, 0x800 +; GFX9-NEXT: v_mov_b32_e32 v41, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX9-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX9-NEXT: s_mov_b64 s[44:45], 0 +; GFX9-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX9-NEXT: s_add_u32 s8, s36, 44 +; GFX9-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX9-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX9-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX9-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-NEXT: s_mov_b32 s12, s41 +; GFX9-NEXT: s_mov_b32 s13, s40 +; GFX9-NEXT: s_mov_b32 s14, s33 +; GFX9-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-NEXT: v_mov_b32_e32 v2, s42 +; GFX9-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX9-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX9-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: v_mov_b32_e32 v3, s43 +; GFX9-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX9-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX9-NEXT: s_cbranch_execnz .LBB11_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fmin_double_uni_address_div_value_defalut_scope_unsafe: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s50, -1 +; GFX1064-NEXT: s_mov_b32 s51, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s48, s48, s9 +; GFX1064-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1064-NEXT: s_addc_u32 s49, s49, 0 +; GFX1064-NEXT: s_mov_b32 s33, s8 +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1064-NEXT: s_mov_b32 s40, s7 +; GFX1064-NEXT: s_mov_b32 s41, s6 +; GFX1064-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1064-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1064-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX1064-NEXT: s_mov_b32 s12, s41 +; GFX1064-NEXT: s_mov_b32 s13, s40 +; GFX1064-NEXT: s_mov_b32 s14, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-NEXT: v_mov_b32_e32 v41, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX1064-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1064-NEXT: s_mov_b64 s[44:45], 0 +; GFX1064-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX1064-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX1064-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-NEXT: v_mov_b32_e32 v2, s42 +; GFX1064-NEXT: v_mov_b32_e32 v3, s43 +; GFX1064-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-NEXT: s_mov_b32 s12, s41 +; GFX1064-NEXT: s_mov_b32 s13, s40 +; GFX1064-NEXT: s_mov_b32 s14, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX1064-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX1064-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX1064-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-NEXT: s_clause 0x1 +; GFX1064-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX1064-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX1064-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX1064-NEXT: s_cbranch_execnz .LBB11_1 +; GFX1064-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fmin_double_uni_address_div_value_defalut_scope_unsafe: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s50, -1 +; GFX1032-NEXT: s_mov_b32 s51, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s48, s48, s9 +; GFX1032-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1032-NEXT: s_addc_u32 s49, s49, 0 +; GFX1032-NEXT: s_mov_b32 s33, s8 +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1032-NEXT: s_mov_b32 s40, s7 +; GFX1032-NEXT: s_mov_b32 s41, s6 +; GFX1032-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1032-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1032-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX1032-NEXT: s_mov_b32 s12, s41 +; GFX1032-NEXT: s_mov_b32 s13, s40 +; GFX1032-NEXT: s_mov_b32 s14, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-NEXT: v_mov_b32_e32 v41, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX1032-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1032-NEXT: s_mov_b32 s44, 0 +; GFX1032-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX1032-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX1032-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-NEXT: v_mov_b32_e32 v2, s42 +; GFX1032-NEXT: v_mov_b32_e32 v3, s43 +; GFX1032-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-NEXT: s_mov_b32 s12, s41 +; GFX1032-NEXT: s_mov_b32 s13, s40 +; GFX1032-NEXT: s_mov_b32 s14, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX1032-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX1032-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX1032-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-NEXT: s_clause 0x1 +; GFX1032-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX1032-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX1032-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s44 +; GFX1032-NEXT: s_cbranch_execnz .LBB11_1 +; GFX1032-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fmin_double_uni_address_div_value_defalut_scope_unsafe: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1164-NEXT: s_mov_b32 s33, s8 +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1164-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-NEXT: s_mov_b32 s12, s6 +; GFX1164-NEXT: s_mov_b32 s13, s7 +; GFX1164-NEXT: s_mov_b32 s14, s33 +; GFX1164-NEXT: s_mov_b32 s32, 32 +; GFX1164-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-NEXT: s_mov_b32 s40, s7 +; GFX1164-NEXT: s_mov_b32 s41, s6 +; GFX1164-NEXT: v_mov_b32_e32 v41, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: global_load_b64 v[2:3], v41, s[42:43] +; GFX1164-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1164-NEXT: s_mov_b64 s[44:45], 0 +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-NEXT: .p2align 6 +; GFX1164-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-NEXT: s_mov_b32 s12, s41 +; GFX1164-NEXT: s_mov_b32 s13, s40 +; GFX1164-NEXT: s_mov_b32 s14, s33 +; GFX1164-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b64 off, v[2:3], off +; GFX1164-NEXT: scratch_store_b64 off, v[0:1], off offset:8 +; GFX1164-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-NEXT: v_mov_b32_e32 v2, s42 +; GFX1164-NEXT: v_mov_b32_e32 v3, s43 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: scratch_load_b64 v[2:3], off, off +; GFX1164-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[44:45] +; GFX1164-NEXT: s_cbranch_execnz .LBB11_1 +; GFX1164-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fmin_double_uni_address_div_value_defalut_scope_unsafe: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1132-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1132-NEXT: v_mov_b32_e32 v31, v0 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1132-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1132-NEXT: s_mov_b32 s40, s14 +; GFX1132-NEXT: s_mov_b32 s41, s13 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-NEXT: s_mov_b32 s12, s13 +; GFX1132-NEXT: s_mov_b32 s13, s14 +; GFX1132-NEXT: s_mov_b32 s14, s15 +; GFX1132-NEXT: s_mov_b32 s32, 32 +; GFX1132-NEXT: s_mov_b32 s33, s15 +; GFX1132-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v41, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: global_load_b64 v[2:3], v41, s[42:43] +; GFX1132-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1132-NEXT: s_mov_b32 s44, 0 +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-NEXT: .p2align 6 +; GFX1132-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-NEXT: v_mov_b32_e32 v31, v40 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-NEXT: s_mov_b32 s12, s41 +; GFX1132-NEXT: s_mov_b32 s13, s40 +; GFX1132-NEXT: s_mov_b32 s14, s33 +; GFX1132-NEXT: v_mov_b32_e32 v4, 0 +; GFX1132-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b64 off, v[2:3], off +; GFX1132-NEXT: scratch_store_b64 off, v[0:1], off offset:8 +; GFX1132-NEXT: v_dual_mov_b32 v0, 8 :: v_dual_mov_b32 v1, 0 +; GFX1132-NEXT: v_dual_mov_b32 v2, s42 :: v_dual_mov_b32 v3, s43 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: scratch_load_b64 v[2:3], off, off +; GFX1132-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s44 +; GFX1132-NEXT: s_cbranch_execnz .LBB11_1 +; GFX1132-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fmin_double_uni_address_div_value_defalut_scope_unsafe: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s50, -1 +; GFX9-DPP-NEXT: s_mov_b32 s51, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX9-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX9-DPP-NEXT: s_mov_b32 s33, s8 +; GFX9-DPP-NEXT: s_add_u32 s8, s36, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_mov_b32 s40, s7 +; GFX9-DPP-NEXT: s_mov_b32 s41, s6 +; GFX9-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-DPP-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX9-DPP-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-DPP-NEXT: s_mov_b32 s12, s41 +; GFX9-DPP-NEXT: s_mov_b32 s13, s40 +; GFX9-DPP-NEXT: s_mov_b32 s14, s33 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX9-DPP-NEXT: v_mov_b32_e32 v41, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-DPP-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX9-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX9-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX9-DPP-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX9-DPP-NEXT: s_add_u32 s8, s36, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX9-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-DPP-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-DPP-NEXT: s_mov_b32 s12, s41 +; GFX9-DPP-NEXT: s_mov_b32 s13, s40 +; GFX9-DPP-NEXT: s_mov_b32 s14, s33 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX9-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX9-DPP-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX9-DPP-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX9-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB11_1 +; GFX9-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fmin_double_uni_address_div_value_defalut_scope_unsafe: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s50, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s51, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX1064-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1064-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1064-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-DPP-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX1064-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v41, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-DPP-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX1064-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1064-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX1064-DPP-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX1064-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-DPP-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX1064-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX1064-DPP-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-DPP-NEXT: s_clause 0x1 +; GFX1064-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX1064-DPP-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX1064-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB11_1 +; GFX1064-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fmin_double_uni_address_div_value_defalut_scope_unsafe: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s50, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s51, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX1032-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1032-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1032-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-DPP-NEXT: v_or3_b32 v40, v0, v1, v2 +; GFX1032-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-DPP-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v41, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-DPP-NEXT: global_load_dwordx2 v[2:3], v41, s[42:43] +; GFX1032-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1032-DPP-NEXT: s_mov_b32 s44, 0 +; GFX1032-DPP-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:4 +; GFX1032-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-DPP-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX1032-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:12 +; GFX1032-DPP-NEXT: buffer_store_dword v0, off, s[48:51], 0 offset:8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-DPP-NEXT: s_clause 0x1 +; GFX1032-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 +; GFX1032-DPP-NEXT: buffer_load_dword v3, off, s[48:51], 0 offset:4 +; GFX1032-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s44 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB11_1 +; GFX1032-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fmin_double_uni_address_div_value_defalut_scope_unsafe: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1164-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1164-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v41, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: global_load_b64 v[2:3], v41, s[42:43] +; GFX1164-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1164-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-DPP-NEXT: .p2align 6 +; GFX1164-DPP-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1164-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1164-DPP-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[2:3], off +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[0:1], off offset:8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: scratch_load_b64 v[2:3], off, off +; GFX1164-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[44:45] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB11_1 +; GFX1164-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fmin_double_uni_address_div_value_defalut_scope_unsafe: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1132-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, div.double.value@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, div.double.value@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1132-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1132-DPP-NEXT: s_mov_b32 s40, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s41, s13 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-DPP-NEXT: s_mov_b32 s12, s13 +; GFX1132-DPP-NEXT: s_mov_b32 s13, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s15 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1132-DPP-NEXT: s_mov_b32 s33, s15 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v41, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: global_load_b64 v[2:3], v41, s[42:43] +; GFX1132-DPP-NEXT: v_max_f64 v[41:42], v[0:1], v[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s44, 0 +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-DPP-NEXT: .p2align 6 +; GFX1132-DPP-NEXT: .LBB11_1: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_max_f64 v[0:1], v[2:3], v[2:3] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1132-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1132-DPP-NEXT: v_min_f64 v[0:1], v[0:1], v[41:42] +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[2:3], off +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[0:1], off offset:8 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v0, 8 :: v_dual_mov_b32 v1, 0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v2, s42 :: v_dual_mov_b32 v3, s43 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: scratch_load_b64 v[2:3], off, off +; GFX1132-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s44 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB11_1 +; GFX1132-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-DPP-NEXT: s_endpgm + %divValue = call double @div.double.value() + %result = atomicrmw fmin ptr addrspace(1) %ptr, double %divValue monotonic, align 4 + ret void +} + attributes #0 = { "denormal-fp-math-f32"="preserve-sign,preserve-sign" "amdgpu-unsafe-fp-atomics"="true" } !llvm.module.flags = !{!0} diff --git a/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fsub.ll b/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fsub.ll index bc9125e326c4d9bd0e421346ece8b263134a4572..7a7ddbe618b0bcc51ab7697e5ce4753dc6316958 100644 --- a/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fsub.ll +++ b/llvm/test/CodeGen/AMDGPU/global_atomics_scan_fsub.ll @@ -13,6 +13,7 @@ ; RUN: llc -mtriple=amdgcn -mcpu=gfx1100 -mattr=+wavefrontsize32,-wavefrontsize64 -amdgpu-atomic-optimizer-strategy=DPP -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GFX1132-DPP %s declare float @div.float.value() +declare double @div.double.value() define amdgpu_kernel void @global_atomic_fsub_uni_address_uni_value_agent_scope_unsafe(ptr addrspace(1) %ptr) #0 { ; GFX7LESS-LABEL: global_atomic_fsub_uni_address_uni_value_agent_scope_unsafe: @@ -5616,6 +5617,5581 @@ define amdgpu_kernel void @global_atomic_fsub_uni_address_div_value_defalut_scop ret void } +define amdgpu_kernel void @global_atomic_fsub_double_uni_address_uni_value_agent_scope_unsafe(ptr addrspace(1) %ptr) #0 { +; GFX7LESS-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_unsafe: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_movk_i32 s32, 0x800 +; GFX7LESS-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s42, -1 +; GFX7LESS-NEXT: s_mov_b32 s43, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s40, s40, s3 +; GFX7LESS-NEXT: s_addc_u32 s41, s41, 0 +; GFX7LESS-NEXT: s_mov_b32 s33, s2 +; GFX7LESS-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX7LESS-NEXT: v_mov_b32_e32 v40, v0 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], exec +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, s0, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, s1, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB9_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x9 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dwordx2 s[2:3], s[36:37], 0x0 +; GFX7LESS-NEXT: s_bcnt1_i32_b64 s0, s[0:1] +; GFX7LESS-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX7LESS-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX7LESS-NEXT: s_mov_b64 s[38:39], 0 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, s2 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, s3 +; GFX7LESS-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_add_f64 v[2:3], v[0:1], -v[41:42] +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[40:43], 0 offset:4 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[40:43], 0 +; GFX7LESS-NEXT: s_add_u32 s8, s34, 44 +; GFX7LESS-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:12 +; GFX7LESS-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:8 +; GFX7LESS-NEXT: s_addc_u32 s9, s35, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX7LESS-NEXT: s_waitcnt expcnt(2) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v4, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, 0 +; GFX7LESS-NEXT: s_mov_b32 s12, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v40 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s36 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s37 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX7LESS-NEXT: v_and_b32_e32 v2, 1, v0 +; GFX7LESS-NEXT: buffer_load_dword v0, off, s[40:43], 0 +; GFX7LESS-NEXT: buffer_load_dword v1, off, s[40:43], 0 offset:4 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 1, v2 +; GFX7LESS-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB9_2 +; GFX7LESS-NEXT: .LBB9_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_unsafe: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s42, -1 +; GFX9-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX9-NEXT: s_mov_b64 s[0:1], exec +; GFX9-NEXT: s_mov_b32 s43, 0xe00000 +; GFX9-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, s0, 0 +; GFX9-NEXT: s_add_u32 s40, s40, s3 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, s1, v0 +; GFX9-NEXT: s_addc_u32 s41, s41, 0 +; GFX9-NEXT: s_mov_b32 s33, s2 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_movk_i32 s32, 0x800 +; GFX9-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-NEXT: s_cbranch_execz .LBB9_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: s_bcnt1_i32_b64 s0, s[0:1] +; GFX9-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX9-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX9-NEXT: s_mov_b64 s[38:39], 0 +; GFX9-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, s1 +; GFX9-NEXT: v_mov_b32_e32 v1, s0 +; GFX9-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX9-NEXT: s_add_u32 s8, s34, 44 +; GFX9-NEXT: s_addc_u32 s9, s35, 0 +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX9-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX9-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX9-NEXT: s_mov_b32 s12, s33 +; GFX9-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX9-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX9-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX9-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: v_mov_b32_e32 v2, s36 +; GFX9-NEXT: v_mov_b32_e32 v3, s37 +; GFX9-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX9-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX9-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX9-NEXT: s_cbranch_execnz .LBB9_2 +; GFX9-NEXT: .LBB9_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s42, -1 +; GFX1064-NEXT: s_mov_b32 s43, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s40, s40, s3 +; GFX1064-NEXT: s_mov_b32 s33, s2 +; GFX1064-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-NEXT: s_addc_u32 s41, s41, 0 +; GFX1064-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1064-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB9_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_bcnt1_i32_b64 s0, s[2:3] +; GFX1064-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1064-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX1064-NEXT: s_mov_b64 s[38:39], 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1064-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v2, s1 +; GFX1064-NEXT: v_mov_b32_e32 v1, s0 +; GFX1064-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1064-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1064-NEXT: s_mov_b32 s12, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1064-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1064-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1064-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1064-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-NEXT: v_mov_b32_e32 v2, s36 +; GFX1064-NEXT: v_mov_b32_e32 v3, s37 +; GFX1064-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1064-NEXT: s_clause 0x1 +; GFX1064-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1064-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX1064-NEXT: s_cbranch_execnz .LBB9_2 +; GFX1064-NEXT: .LBB9_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s33, s2 +; GFX1032-NEXT: s_mov_b32 s2, exec_lo +; GFX1032-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1032-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s42, -1 +; GFX1032-NEXT: s_mov_b32 s43, 0x31c16000 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_add_u32 s40, s40, s3 +; GFX1032-NEXT: s_addc_u32 s41, s41, 0 +; GFX1032-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1032-NEXT: s_mov_b32 s38, 0 +; GFX1032-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-NEXT: s_and_saveexec_b32 s0, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB9_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_bcnt1_i32_b32 s0, s2 +; GFX1032-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1032-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1032-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v2, s1 +; GFX1032-NEXT: v_mov_b32_e32 v1, s0 +; GFX1032-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1032-NEXT: s_mov_b32 s12, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1032-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1032-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1032-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1032-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-NEXT: v_mov_b32_e32 v2, s36 +; GFX1032-NEXT: v_mov_b32_e32 v3, s37 +; GFX1032-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1032-NEXT: s_clause 0x1 +; GFX1032-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1032-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s38 +; GFX1032-NEXT: s_cbranch_execnz .LBB9_2 +; GFX1032-NEXT: .LBB9_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b32 s33, s2 +; GFX1164-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1164-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1164-NEXT: s_mov_b32 s32, 32 +; GFX1164-NEXT: s_mov_b64 s[0:1], exec +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-NEXT: s_cbranch_execz .LBB9_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_bcnt1_i32_b64 s0, s[2:3] +; GFX1164-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1164-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX1164-NEXT: s_mov_b64 s[38:39], 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v2, s1 +; GFX1164-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-NEXT: .p2align 6 +; GFX1164-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-NEXT: s_mov_b32 s12, s33 +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-NEXT: v_mov_b32_e32 v2, s36 +; GFX1164-NEXT: v_mov_b32_e32 v3, s37 +; GFX1164-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[38:39] +; GFX1164-NEXT: s_cbranch_execnz .LBB9_2 +; GFX1164-NEXT: .LBB9_3: +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_mov_b32 s2, exec_lo +; GFX1132-NEXT: v_mov_b32_e32 v40, v0 +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1132-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1132-NEXT: s_mov_b32 s38, 0 +; GFX1132-NEXT: s_mov_b32 s32, 32 +; GFX1132-NEXT: s_mov_b32 s0, exec_lo +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-NEXT: s_cbranch_execz .LBB9_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_bcnt1_i32_b32 s0, s2 +; GFX1132-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1132-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX1132-NEXT: s_mov_b32 s33, s15 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: v_dual_mov_b32 v2, s1 :: v_dual_mov_b32 v1, s0 +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-NEXT: .p2align 6 +; GFX1132-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-NEXT: v_dual_mov_b32 v31, v40 :: v_dual_mov_b32 v0, 8 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-NEXT: s_mov_b32 s12, s33 +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s36 +; GFX1132-NEXT: v_dual_mov_b32 v3, s37 :: v_dual_mov_b32 v4, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s38 +; GFX1132-NEXT: s_cbranch_execnz .LBB9_2 +; GFX1132-NEXT: .LBB9_3: +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_unsafe: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s42, -1 +; GFX9-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], exec +; GFX9-DPP-NEXT: s_mov_b32 s43, 0xe00000 +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s0, 0 +; GFX9-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s1, v0 +; GFX9-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX9-DPP-NEXT: s_mov_b32 s33, s2 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB9_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: s_bcnt1_i32_b64 s0, s[0:1] +; GFX9-DPP-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX9-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX9-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX9-DPP-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX9-DPP-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX9-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX9-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX9-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX9-DPP-NEXT: s_mov_b32 s12, s33 +; GFX9-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX9-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX9-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX9-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX9-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB9_2 +; GFX9-DPP-NEXT: .LBB9_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s42, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s43, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX1064-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1064-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB9_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_bcnt1_i32_b64 s0, s[2:3] +; GFX1064-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1064-DPP-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX1064-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1064-DPP-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1064-DPP-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1064-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1064-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1064-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1064-DPP-NEXT: s_clause 0x1 +; GFX1064-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1064-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB9_2 +; GFX1064-DPP-NEXT: .LBB9_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1032-DPP-NEXT: s_mov_b32 s2, exec_lo +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s42, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s43, 0x31c16000 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX1032-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1032-DPP-NEXT: s_mov_b32 s38, 0 +; GFX1032-DPP-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s0, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB9_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_bcnt1_i32_b32 s0, s2 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1032-DPP-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1032-DPP-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1032-DPP-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1032-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1032-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1032-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1032-DPP-NEXT: s_clause 0x1 +; GFX1032-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1032-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s38 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB9_2 +; GFX1032-DPP-NEXT: .LBB9_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1164-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1164-DPP-NEXT: s_mov_b64 s[0:1], exec +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB9_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_bcnt1_i32_b64 s0, s[2:3] +; GFX1164-DPP-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1164-DPP-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX1164-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-DPP-NEXT: .p2align 6 +; GFX1164-DPP-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[38:39] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB9_2 +; GFX1164-DPP-NEXT: .LBB9_3: +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_unsafe: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_mov_b32 s2, exec_lo +; GFX1132-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s38, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1132-DPP-NEXT: s_mov_b32 s0, exec_lo +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v0 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB9_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_bcnt1_i32_b32 s0, s2 +; GFX1132-DPP-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1132-DPP-NEXT: v_cvt_f64_u32_e32 v[0:1], s0 +; GFX1132-DPP-NEXT: s_mov_b32 s33, s15 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_mul_f64 v[41:42], v[0:1], 4.0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v2, s1 :: v_dual_mov_b32 v1, s0 +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-DPP-NEXT: .p2align 6 +; GFX1132-DPP-NEXT: .LBB9_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v31, v40 :: v_dual_mov_b32 v0, 8 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s36 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, s37 :: v_dual_mov_b32 v4, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s38 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB9_2 +; GFX1132-DPP-NEXT: .LBB9_3: +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fsub ptr addrspace(1) %ptr, double 4.0 syncscope("agent") monotonic, align 4 + ret void +} + +define amdgpu_kernel void @global_atomic_fsub_double_uni_address_div_value_agent_scope_align4_unsafe(ptr addrspace(1) %ptr) #0 { +; GFX7LESS-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_movk_i32 s32, 0x800 +; GFX7LESS-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s50, -1 +; GFX7LESS-NEXT: s_mov_b32 s51, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s48, s48, s9 +; GFX7LESS-NEXT: s_addc_u32 s49, s49, 0 +; GFX7LESS-NEXT: s_mov_b32 s33, s8 +; GFX7LESS-NEXT: s_mov_b32 s40, s7 +; GFX7LESS-NEXT: s_mov_b32 s41, s6 +; GFX7LESS-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX7LESS-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX7LESS-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX7LESS-NEXT: s_load_dwordx2 s[44:45], s[2:3], 0x9 +; GFX7LESS-NEXT: s_mov_b32 s47, 0xf000 +; GFX7LESS-NEXT: s_mov_b32 s46, -1 +; GFX7LESS-NEXT: s_add_u32 s8, s36, 44 +; GFX7LESS-NEXT: s_addc_u32 s9, s37, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v0, v0, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v42, v0, v2 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX7LESS-NEXT: s_mov_b32 s12, s41 +; GFX7LESS-NEXT: s_mov_b32 s13, s40 +; GFX7LESS-NEXT: s_mov_b32 s14, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v42 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX7LESS-NEXT: v_mov_b32_e32 v40, v0 +; GFX7LESS-NEXT: v_mov_b32_e32 v41, v1 +; GFX7LESS-NEXT: buffer_load_dwordx2 v[0:1], off, s[44:47], 0 +; GFX7LESS-NEXT: s_mov_b64 s[42:43], 0 +; GFX7LESS-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_add_f64 v[2:3], v[0:1], -v[40:41] +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:4 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[48:51], 0 +; GFX7LESS-NEXT: s_add_u32 s8, s36, 44 +; GFX7LESS-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:12 +; GFX7LESS-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:8 +; GFX7LESS-NEXT: s_addc_u32 s9, s37, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX7LESS-NEXT: s_waitcnt expcnt(2) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v4, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, 0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX7LESS-NEXT: s_mov_b32 s12, s41 +; GFX7LESS-NEXT: s_mov_b32 s13, s40 +; GFX7LESS-NEXT: s_mov_b32 s14, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v42 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s44 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s45 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX7LESS-NEXT: v_and_b32_e32 v2, 1, v0 +; GFX7LESS-NEXT: buffer_load_dword v0, off, s[48:51], 0 +; GFX7LESS-NEXT: buffer_load_dword v1, off, s[48:51], 0 offset:4 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 1, v2 +; GFX7LESS-NEXT: s_or_b64 s[42:43], vcc, s[42:43] +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[42:43] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB10_1 +; GFX7LESS-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s50, -1 +; GFX9-NEXT: s_mov_b32 s51, 0xe00000 +; GFX9-NEXT: s_add_u32 s48, s48, s9 +; GFX9-NEXT: s_addc_u32 s49, s49, 0 +; GFX9-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX9-NEXT: s_mov_b32 s33, s8 +; GFX9-NEXT: s_add_u32 s8, s36, 44 +; GFX9-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX9-NEXT: s_mov_b32 s40, s7 +; GFX9-NEXT: s_mov_b32 s41, s6 +; GFX9-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX9-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX9-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-NEXT: s_mov_b32 s12, s41 +; GFX9-NEXT: s_mov_b32 s13, s40 +; GFX9-NEXT: s_mov_b32 s14, s33 +; GFX9-NEXT: v_mov_b32_e32 v31, v42 +; GFX9-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-NEXT: s_movk_i32 s32, 0x800 +; GFX9-NEXT: v_mov_b32_e32 v43, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-NEXT: v_mov_b32_e32 v41, v1 +; GFX9-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX9-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-NEXT: s_mov_b64 s[44:45], 0 +; GFX9-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX9-NEXT: s_add_u32 s8, s36, 44 +; GFX9-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX9-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX9-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX9-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX9-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-NEXT: s_mov_b32 s12, s41 +; GFX9-NEXT: s_mov_b32 s13, s40 +; GFX9-NEXT: s_mov_b32 s14, s33 +; GFX9-NEXT: v_mov_b32_e32 v31, v42 +; GFX9-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: v_mov_b32_e32 v2, s42 +; GFX9-NEXT: v_mov_b32_e32 v3, s43 +; GFX9-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX9-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX9-NEXT: s_cbranch_execnz .LBB10_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s50, -1 +; GFX1064-NEXT: s_mov_b32 s51, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s48, s48, s9 +; GFX1064-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1064-NEXT: s_addc_u32 s49, s49, 0 +; GFX1064-NEXT: s_mov_b32 s33, s8 +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1064-NEXT: s_mov_b32 s40, s7 +; GFX1064-NEXT: s_mov_b32 s41, s6 +; GFX1064-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1064-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1064-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX1064-NEXT: s_mov_b32 s12, s41 +; GFX1064-NEXT: s_mov_b32 s13, s40 +; GFX1064-NEXT: s_mov_b32 s14, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-NEXT: v_mov_b32_e32 v31, v42 +; GFX1064-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-NEXT: v_mov_b32_e32 v43, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-NEXT: v_mov_b32_e32 v41, v1 +; GFX1064-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX1064-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-NEXT: s_mov_b64 s[44:45], 0 +; GFX1064-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX1064-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX1064-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-NEXT: v_mov_b32_e32 v31, v42 +; GFX1064-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-NEXT: v_mov_b32_e32 v2, s42 +; GFX1064-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-NEXT: s_mov_b32 s12, s41 +; GFX1064-NEXT: s_mov_b32 s13, s40 +; GFX1064-NEXT: s_mov_b32 s14, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX1064-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX1064-NEXT: v_mov_b32_e32 v3, s43 +; GFX1064-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-NEXT: s_clause 0x1 +; GFX1064-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX1064-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX1064-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX1064-NEXT: s_cbranch_execnz .LBB10_1 +; GFX1064-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s50, -1 +; GFX1032-NEXT: s_mov_b32 s51, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s48, s48, s9 +; GFX1032-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1032-NEXT: s_addc_u32 s49, s49, 0 +; GFX1032-NEXT: s_mov_b32 s33, s8 +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1032-NEXT: s_mov_b32 s40, s7 +; GFX1032-NEXT: s_mov_b32 s41, s6 +; GFX1032-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1032-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1032-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX1032-NEXT: s_mov_b32 s12, s41 +; GFX1032-NEXT: s_mov_b32 s13, s40 +; GFX1032-NEXT: s_mov_b32 s14, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-NEXT: v_mov_b32_e32 v31, v42 +; GFX1032-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-NEXT: v_mov_b32_e32 v43, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-NEXT: v_mov_b32_e32 v41, v1 +; GFX1032-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX1032-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-NEXT: s_mov_b32 s44, 0 +; GFX1032-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX1032-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX1032-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-NEXT: v_mov_b32_e32 v31, v42 +; GFX1032-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-NEXT: v_mov_b32_e32 v2, s42 +; GFX1032-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-NEXT: s_mov_b32 s12, s41 +; GFX1032-NEXT: s_mov_b32 s13, s40 +; GFX1032-NEXT: s_mov_b32 s14, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX1032-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX1032-NEXT: v_mov_b32_e32 v3, s43 +; GFX1032-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-NEXT: s_clause 0x1 +; GFX1032-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX1032-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX1032-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s44 +; GFX1032-NEXT: s_cbranch_execnz .LBB10_1 +; GFX1032-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1164-NEXT: s_mov_b32 s33, s8 +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1164-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-NEXT: s_mov_b32 s12, s6 +; GFX1164-NEXT: s_mov_b32 s13, s7 +; GFX1164-NEXT: s_mov_b32 s14, s33 +; GFX1164-NEXT: s_mov_b32 s32, 32 +; GFX1164-NEXT: v_mov_b32_e32 v42, v0 +; GFX1164-NEXT: s_mov_b32 s40, s7 +; GFX1164-NEXT: s_mov_b32 s41, s6 +; GFX1164-NEXT: v_mov_b32_e32 v43, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: v_mov_b32_e32 v41, v1 +; GFX1164-NEXT: global_load_b64 v[1:2], v43, s[42:43] +; GFX1164-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-NEXT: s_mov_b64 s[44:45], 0 +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-NEXT: .p2align 6 +; GFX1164-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-NEXT: v_mov_b32_e32 v31, v42 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-NEXT: s_mov_b32 s12, s41 +; GFX1164-NEXT: s_mov_b32 s13, s40 +; GFX1164-NEXT: s_mov_b32 s14, s33 +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-NEXT: v_mov_b32_e32 v2, s42 +; GFX1164-NEXT: v_mov_b32_e32 v3, s43 +; GFX1164-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[44:45] +; GFX1164-NEXT: s_cbranch_execnz .LBB10_1 +; GFX1164-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1132-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1132-NEXT: v_mov_b32_e32 v31, v0 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1132-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1132-NEXT: s_mov_b32 s40, s14 +; GFX1132-NEXT: s_mov_b32 s41, s13 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-NEXT: s_mov_b32 s12, s13 +; GFX1132-NEXT: s_mov_b32 s13, s14 +; GFX1132-NEXT: s_mov_b32 s14, s15 +; GFX1132-NEXT: s_mov_b32 s32, 32 +; GFX1132-NEXT: s_mov_b32 s33, s15 +; GFX1132-NEXT: v_dual_mov_b32 v42, v0 :: v_dual_mov_b32 v43, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v41, v1 +; GFX1132-NEXT: global_load_b64 v[1:2], v43, s[42:43] +; GFX1132-NEXT: s_mov_b32 s44, 0 +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-NEXT: .p2align 6 +; GFX1132-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-NEXT: v_dual_mov_b32 v31, v42 :: v_dual_mov_b32 v0, 8 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-NEXT: s_mov_b32 s12, s41 +; GFX1132-NEXT: s_mov_b32 s13, s40 +; GFX1132-NEXT: s_mov_b32 s14, s33 +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s42 +; GFX1132-NEXT: v_dual_mov_b32 v3, s43 :: v_dual_mov_b32 v4, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s44 +; GFX1132-NEXT: s_cbranch_execnz .LBB10_1 +; GFX1132-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s50, -1 +; GFX9-DPP-NEXT: s_mov_b32 s51, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX9-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX9-DPP-NEXT: s_mov_b32 s33, s8 +; GFX9-DPP-NEXT: s_add_u32 s8, s36, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_mov_b32 s40, s7 +; GFX9-DPP-NEXT: s_mov_b32 s41, s6 +; GFX9-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-DPP-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX9-DPP-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-DPP-NEXT: s_mov_b32 s12, s41 +; GFX9-DPP-NEXT: s_mov_b32 s13, s40 +; GFX9-DPP-NEXT: s_mov_b32 s14, s33 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX9-DPP-NEXT: v_mov_b32_e32 v43, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-DPP-NEXT: v_mov_b32_e32 v41, v1 +; GFX9-DPP-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX9-DPP-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX9-DPP-NEXT: s_add_u32 s8, s36, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX9-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-DPP-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX9-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-DPP-NEXT: s_mov_b32 s12, s41 +; GFX9-DPP-NEXT: s_mov_b32 s13, s40 +; GFX9-DPP-NEXT: s_mov_b32 s14, s33 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-DPP-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX9-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX9-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB10_1 +; GFX9-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s50, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s51, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX1064-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1064-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1064-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-DPP-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX1064-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1064-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v43, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v41, v1 +; GFX1064-DPP-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX1064-DPP-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX1064-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-DPP-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX1064-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-DPP-NEXT: s_clause 0x1 +; GFX1064-DPP-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX1064-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX1064-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB10_1 +; GFX1064-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s50, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s51, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX1032-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1032-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1032-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-DPP-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX1032-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1032-DPP-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v43, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v41, v1 +; GFX1032-DPP-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-DPP-NEXT: s_mov_b32 s44, 0 +; GFX1032-DPP-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX1032-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-DPP-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX1032-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-DPP-NEXT: s_clause 0x1 +; GFX1032-DPP-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX1032-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX1032-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s44 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB10_1 +; GFX1032-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1164-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1164-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v42, v0 +; GFX1164-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v43, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v41, v1 +; GFX1164-DPP-NEXT: global_load_b64 v[1:2], v43, s[42:43] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-DPP-NEXT: .p2align 6 +; GFX1164-DPP-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1164-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[44:45] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB10_1 +; GFX1164-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_align4_unsafe: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1132-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1132-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1132-DPP-NEXT: s_mov_b32 s40, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s41, s13 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-DPP-NEXT: s_mov_b32 s12, s13 +; GFX1132-DPP-NEXT: s_mov_b32 s13, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s15 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1132-DPP-NEXT: s_mov_b32 s33, s15 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v42, v0 :: v_dual_mov_b32 v43, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v41, v1 +; GFX1132-DPP-NEXT: global_load_b64 v[1:2], v43, s[42:43] +; GFX1132-DPP-NEXT: s_mov_b32 s44, 0 +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-DPP-NEXT: .p2align 6 +; GFX1132-DPP-NEXT: .LBB10_1: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v31, v42 :: v_dual_mov_b32 v0, 8 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1132-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s42 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, s43 :: v_dual_mov_b32 v4, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s44 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB10_1 +; GFX1132-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-DPP-NEXT: s_endpgm + %divValue = call double @div.float.value() + %result = atomicrmw fsub ptr addrspace(1) %ptr, double %divValue syncscope("agent") monotonic, align 4 + ret void +} + +define amdgpu_kernel void @global_atomic_fsub_double_uni_address_uni_value_one_as_scope_unsafe_structfp(ptr addrspace(1) %ptr) #1 { +; GFX7LESS-LABEL: global_atomic_fsub_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_mov_b32 s12, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s13, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s14, -1 +; GFX7LESS-NEXT: s_mov_b32 s15, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s12, s12, s3 +; GFX7LESS-NEXT: s_addc_u32 s13, s13, 0 +; GFX7LESS-NEXT: s_mov_b64 s[2:3], exec +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, s2, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, s3, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB11_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x9 +; GFX7LESS-NEXT: s_bcnt1_i32_b64 s6, s[2:3] +; GFX7LESS-NEXT: s_mov_b32 s7, 0x43300000 +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0xc3300000 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dwordx2 s[8:9], s[0:1], 0x0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], 0 +; GFX7LESS-NEXT: s_mov_b32 s3, 0xf000 +; GFX7LESS-NEXT: v_add_f64 v[0:1], s[6:7], v[0:1] +; GFX7LESS-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s8 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s9 +; GFX7LESS-NEXT: s_mov_b32 s2, -1 +; GFX7LESS-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v9, v3 +; GFX7LESS-NEXT: v_mov_b32_e32 v8, v2 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, v1 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, v0 +; GFX7LESS-NEXT: buffer_atomic_cmpswap_x2 v[6:9], off, s[0:3], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[2:3] +; GFX7LESS-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX7LESS-NEXT: v_mov_b32_e32 v2, v6 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, v7 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB11_2 +; GFX7LESS-NEXT: .LBB11_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fsub_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s10, -1 +; GFX9-NEXT: s_mov_b32 s11, 0xe00000 +; GFX9-NEXT: s_add_u32 s8, s8, s3 +; GFX9-NEXT: s_mov_b64 s[2:3], exec +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX9-NEXT: s_addc_u32 s9, s9, 0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX9-NEXT: s_cbranch_execz .LBB11_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: v_mov_b32_e32 v0, 0 +; GFX9-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX9-NEXT: v_mov_b32_e32 v1, 0xc3300000 +; GFX9-NEXT: s_mov_b32 s3, 0x43300000 +; GFX9-NEXT: v_add_f64 v[0:1], s[2:3], v[0:1] +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-NEXT: v_mov_b32_e32 v3, s5 +; GFX9-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX9-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX9-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-NEXT: s_cbranch_execnz .LBB11_2 +; GFX9-NEXT: .LBB11_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fsub_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s10, -1 +; GFX1064-NEXT: s_mov_b32 s11, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s8, s8, s3 +; GFX1064-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-NEXT: s_addc_u32 s9, s9, 0 +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB11_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX1064-NEXT: s_mov_b32 s3, 0x43300000 +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-NEXT: v_add_f64 v[0:1], 0xc3300000, s[2:3] +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX1064-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v2, s2 +; GFX1064-NEXT: v_mov_b32_e32 v3, s3 +; GFX1064-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX1064-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1064-NEXT: v_mov_b32_e32 v3, v1 +; GFX1064-NEXT: v_mov_b32_e32 v2, v0 +; GFX1064-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-NEXT: s_cbranch_execnz .LBB11_2 +; GFX1064-NEXT: .LBB11_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fsub_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s10, -1 +; GFX1032-NEXT: s_mov_b32 s11, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s8, s8, s3 +; GFX1032-NEXT: s_mov_b32 s3, exec_lo +; GFX1032-NEXT: s_addc_u32 s9, s9, 0 +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, s3, 0 +; GFX1032-NEXT: s_mov_b32 s2, 0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_and_saveexec_b32 s4, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB11_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_bcnt1_i32_b32 s4, s3 +; GFX1032-NEXT: s_mov_b32 s5, 0x43300000 +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-NEXT: v_add_f64 v[0:1], 0xc3300000, s[4:5] +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v2, s4 +; GFX1032-NEXT: v_mov_b32_e32 v3, s5 +; GFX1032-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX1032-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1032-NEXT: v_mov_b32_e32 v3, v1 +; GFX1032-NEXT: v_mov_b32_e32 v2, v0 +; GFX1032-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-NEXT: s_cbranch_execnz .LBB11_2 +; GFX1032-NEXT: .LBB11_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fsub_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_bcnt1_i32_b64 s2, exec +; GFX1164-NEXT: v_mov_b32_e32 v0, 0x43300000 +; GFX1164-NEXT: v_mov_b32_e32 v1, s2 +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1164-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b32 off, v0, off offset:4 +; GFX1164-NEXT: scratch_store_b32 off, v1, off +; GFX1164-NEXT: scratch_load_b64 v[0:1], off, off +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v2, exec_hi, v2 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1164-NEXT: s_cbranch_execz .LBB11_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b64 s[2:3], s[0:1], 0x0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_2) +; GFX1164-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v2, s2 +; GFX1164-NEXT: v_mov_b32_e32 v3, s3 +; GFX1164-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX1164-NEXT: global_atomic_cmpswap_b64 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1164-NEXT: v_mov_b32_e32 v3, v1 +; GFX1164-NEXT: v_mov_b32_e32 v2, v0 +; GFX1164-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-NEXT: s_cbranch_execnz .LBB11_2 +; GFX1164-NEXT: .LBB11_3: +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fsub_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_bcnt1_i32_b32 s2, exec_lo +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: v_dual_mov_b32 v0, 0x43300000 :: v_dual_mov_b32 v1, s2 +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1132-NEXT: s_mov_b32 s2, 0 +; GFX1132-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b32 off, v0, off offset:4 +; GFX1132-NEXT: scratch_store_b32 off, v1, off +; GFX1132-NEXT: scratch_load_b64 v[0:1], off, off +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1132-NEXT: s_cbranch_execz .LBB11_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-NEXT: v_mov_b32_e32 v6, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b64 s[4:5], s[0:1], 0x0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_2) +; GFX1132-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: v_dual_mov_b32 v2, s4 :: v_dual_mov_b32 v3, s5 +; GFX1132-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX1132-NEXT: global_atomic_cmpswap_b64 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1132-NEXT: v_dual_mov_b32 v3, v1 :: v_dual_mov_b32 v2, v0 +; GFX1132-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-NEXT: s_cbranch_execnz .LBB11_2 +; GFX1132-NEXT: .LBB11_3: +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s10, -1 +; GFX9-DPP-NEXT: s_mov_b32 s11, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s8, s8, s3 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX9-DPP-NEXT: s_addc_u32 s9, s9, 0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB11_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 0 +; GFX9-DPP-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0xc3300000 +; GFX9-DPP-NEXT: s_mov_b32 s3, 0x43300000 +; GFX9-DPP-NEXT: v_add_f64 v[0:1], s[2:3], v[0:1] +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s5 +; GFX9-DPP-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX9-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB11_2 +; GFX9-DPP-NEXT: .LBB11_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s10, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s11, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s8, s8, s3 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-DPP-NEXT: s_addc_u32 s9, s9, 0 +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB11_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX1064-DPP-NEXT: s_mov_b32 s3, 0x43300000 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, s[2:3] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s2 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s3 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-DPP-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX1064-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB11_2 +; GFX1064-DPP-NEXT: .LBB11_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s10, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s11, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s8, s8, s3 +; GFX1032-DPP-NEXT: s_mov_b32 s3, exec_lo +; GFX1032-DPP-NEXT: s_addc_u32 s9, s9, 0 +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s3, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s4, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB11_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_bcnt1_i32_b32 s4, s3 +; GFX1032-DPP-NEXT: s_mov_b32 s5, 0x43300000 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, s[4:5] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s4 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s5 +; GFX1032-DPP-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX1032-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1032-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB11_2 +; GFX1032-DPP-NEXT: .LBB11_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_bcnt1_i32_b64 s2, exec +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 0x43300000 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s2 +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b32 off, v0, off offset:4 +; GFX1164-DPP-NEXT: scratch_store_b32 off, v1, off +; GFX1164-DPP-NEXT: scratch_load_b64 v[0:1], off, off +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v2, exec_hi, v2 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB11_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b64 s[2:3], s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_2) +; GFX1164-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s2 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s3 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-DPP-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b64 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB11_2 +; GFX1164-DPP-NEXT: .LBB11_3: +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_one_as_scope_unsafe_structfp: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_bcnt1_i32_b32 s2, exec_lo +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v0, 0x43300000 :: v_dual_mov_b32 v1, s2 +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b32 off, v0, off offset:4 +; GFX1132-DPP-NEXT: scratch_store_b32 off, v1, off +; GFX1132-DPP-NEXT: scratch_load_b64 v[0:1], off, off +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB11_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b64 s[4:5], s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_2) +; GFX1132-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v2, s4 :: v_dual_mov_b32 v3, s5 +; GFX1132-DPP-NEXT: .LBB11_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b64 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, v1 :: v_dual_mov_b32 v2, v0 +; GFX1132-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB11_2 +; GFX1132-DPP-NEXT: .LBB11_3: +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fsub ptr addrspace(1) %ptr, double 4.0 syncscope("one-as") monotonic + ret void +} +define amdgpu_kernel void @global_atomic_fsub_double_uni_address_div_value_one_as_scope_unsafe_structfp(ptr addrspace(1) %ptr) #1 { +; GFX7LESS-LABEL: global_atomic_fsub_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_mov_b32 s32, 0 +; GFX7LESS-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s42, -1 +; GFX7LESS-NEXT: s_mov_b32 s43, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s40, s40, s9 +; GFX7LESS-NEXT: s_addc_u32 s41, s41, 0 +; GFX7LESS-NEXT: s_mov_b32 s14, s8 +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX7LESS-NEXT: s_load_dwordx2 s[36:37], s[2:3], 0x9 +; GFX7LESS-NEXT: s_mov_b32 s39, 0xf000 +; GFX7LESS-NEXT: s_mov_b32 s38, -1 +; GFX7LESS-NEXT: s_add_u32 s8, s2, 44 +; GFX7LESS-NEXT: s_addc_u32 s9, s3, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[2:3] +; GFX7LESS-NEXT: s_add_u32 s2, s2, div.double.value@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s3, s3, div.double.value@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v0, v0, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v31, v0, v2 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX7LESS-NEXT: s_mov_b32 s12, s6 +; GFX7LESS-NEXT: s_mov_b32 s13, s7 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX7LESS-NEXT: buffer_load_dwordx2 v[4:5], off, s[36:39], 0 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], 0 +; GFX7LESS-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v9, v5 +; GFX7LESS-NEXT: v_mov_b32_e32 v8, v4 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, v3 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, v2 +; GFX7LESS-NEXT: buffer_atomic_cmpswap_x2 v[6:9], off, s[36:39], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[4:5] +; GFX7LESS-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX7LESS-NEXT: v_mov_b32_e32 v4, v6 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, v7 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB12_1 +; GFX7LESS-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fsub_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s38, -1 +; GFX9-NEXT: s_mov_b32 s39, 0xe00000 +; GFX9-NEXT: s_add_u32 s36, s36, s9 +; GFX9-NEXT: s_addc_u32 s37, s37, 0 +; GFX9-NEXT: s_mov_b32 s14, s8 +; GFX9-NEXT: s_add_u32 s8, s2, 44 +; GFX9-NEXT: s_addc_u32 s9, s3, 0 +; GFX9-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX9-NEXT: s_getpc_b64 s[2:3] +; GFX9-NEXT: s_add_u32 s2, s2, div.double.value@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s3, s3, div.double.value@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX9-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX9-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX9-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX9-NEXT: s_mov_b32 s12, s6 +; GFX9-NEXT: s_mov_b32 s13, s7 +; GFX9-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX9-NEXT: s_mov_b32 s32, 0 +; GFX9-NEXT: v_mov_b32_e32 v40, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX9-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX9-NEXT: s_mov_b64 s[0:1], 0 +; GFX9-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX9-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX9-NEXT: v_mov_b32_e32 v5, v3 +; GFX9-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX9-NEXT: v_mov_b32_e32 v4, v2 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX9-NEXT: s_cbranch_execnz .LBB12_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fsub_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s38, -1 +; GFX1064-NEXT: s_mov_b32 s39, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s36, s36, s9 +; GFX1064-NEXT: s_addc_u32 s37, s37, 0 +; GFX1064-NEXT: s_mov_b32 s14, s8 +; GFX1064-NEXT: s_add_u32 s8, s2, 44 +; GFX1064-NEXT: s_addc_u32 s9, s3, 0 +; GFX1064-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1064-NEXT: s_getpc_b64 s[4:5] +; GFX1064-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1064-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1064-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1064-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1064-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1064-NEXT: s_mov_b32 s12, s6 +; GFX1064-NEXT: s_mov_b32 s13, s7 +; GFX1064-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1064-NEXT: s_mov_b32 s32, 0 +; GFX1064-NEXT: v_mov_b32_e32 v40, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1064-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1064-NEXT: s_mov_b64 s[0:1], 0 +; GFX1064-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1064-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1064-NEXT: v_mov_b32_e32 v5, v3 +; GFX1064-NEXT: v_mov_b32_e32 v4, v2 +; GFX1064-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX1064-NEXT: s_cbranch_execnz .LBB12_1 +; GFX1064-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fsub_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s38, -1 +; GFX1032-NEXT: s_mov_b32 s39, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s36, s36, s9 +; GFX1032-NEXT: s_addc_u32 s37, s37, 0 +; GFX1032-NEXT: s_mov_b32 s14, s8 +; GFX1032-NEXT: s_add_u32 s8, s2, 44 +; GFX1032-NEXT: s_addc_u32 s9, s3, 0 +; GFX1032-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1032-NEXT: s_getpc_b64 s[4:5] +; GFX1032-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1032-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1032-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1032-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1032-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1032-NEXT: s_mov_b32 s12, s6 +; GFX1032-NEXT: s_mov_b32 s13, s7 +; GFX1032-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1032-NEXT: s_mov_b32 s32, 0 +; GFX1032-NEXT: v_mov_b32_e32 v40, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1032-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1032-NEXT: s_mov_b32 s0, 0 +; GFX1032-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1032-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1032-NEXT: v_mov_b32_e32 v5, v3 +; GFX1032-NEXT: v_mov_b32_e32 v4, v2 +; GFX1032-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s0 +; GFX1032-NEXT: s_cbranch_execnz .LBB12_1 +; GFX1032-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fsub_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b32 s14, s8 +; GFX1164-NEXT: s_add_u32 s8, s2, 44 +; GFX1164-NEXT: s_addc_u32 s9, s3, 0 +; GFX1164-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1164-NEXT: s_getpc_b64 s[4:5] +; GFX1164-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1164-NEXT: s_load_b64 s[16:17], s[4:5], 0x0 +; GFX1164-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1164-NEXT: s_mov_b32 s12, s6 +; GFX1164-NEXT: s_mov_b32 s13, s7 +; GFX1164-NEXT: s_mov_b32 s32, 0 +; GFX1164-NEXT: v_mov_b32_e32 v40, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1164-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1164-NEXT: s_mov_b64 s[0:1], 0 +; GFX1164-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1164-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1164-NEXT: v_mov_b32_e32 v5, v3 +; GFX1164-NEXT: v_mov_b32_e32 v4, v2 +; GFX1164-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[0:1] +; GFX1164-NEXT: s_cbranch_execnz .LBB12_1 +; GFX1164-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fsub_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_add_u32 s8, s2, 44 +; GFX1132-NEXT: s_addc_u32 s9, s3, 0 +; GFX1132-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1132-NEXT: s_getpc_b64 s[4:5] +; GFX1132-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1132-NEXT: s_load_b64 s[6:7], s[4:5], 0x0 +; GFX1132-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1132-NEXT: v_dual_mov_b32 v40, 0 :: v_dual_mov_b32 v31, v0 +; GFX1132-NEXT: s_mov_b32 s12, s13 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1132-NEXT: s_mov_b32 s13, s14 +; GFX1132-NEXT: s_mov_b32 s14, s15 +; GFX1132-NEXT: s_mov_b32 s32, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1132-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1132-NEXT: s_mov_b32 s0, 0 +; GFX1132-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1132-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1132-NEXT: v_dual_mov_b32 v5, v3 :: v_dual_mov_b32 v4, v2 +; GFX1132-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s0 +; GFX1132-NEXT: s_cbranch_execnz .LBB12_1 +; GFX1132-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s38, -1 +; GFX9-DPP-NEXT: s_mov_b32 s39, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX9-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX9-DPP-NEXT: s_mov_b32 s14, s8 +; GFX9-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX9-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX9-DPP-NEXT: s_getpc_b64 s[2:3] +; GFX9-DPP-NEXT: s_add_u32 s2, s2, div.double.value@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s3, s3, div.double.value@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX9-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX9-DPP-NEXT: s_mov_b32 s12, s6 +; GFX9-DPP-NEXT: s_mov_b32 s13, s7 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX9-DPP-NEXT: s_mov_b32 s32, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX9-DPP-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX9-DPP-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX9-DPP-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX9-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB12_1 +; GFX9-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s38, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s39, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX1064-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1064-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1064-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1064-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1064-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1064-DPP-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX1064-DPP-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1064-DPP-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX1064-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB12_1 +; GFX1064-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s38, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s39, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX1032-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1032-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1032-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1032-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1032-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1032-DPP-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1032-DPP-NEXT: s_mov_b32 s0, 0 +; GFX1032-DPP-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1032-DPP-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX1032-DPP-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s0 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB12_1 +; GFX1032-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1164-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1164-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1164-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: s_load_b64 s[16:17], s[4:5], 0x0 +; GFX1164-DPP-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1164-DPP-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1164-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX1164-DPP-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX1164-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[0:1] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB12_1 +; GFX1164-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_one_as_scope_unsafe_structfp: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1132-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1132-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: s_load_b64 s[6:7], s[4:5], 0x0 +; GFX1132-DPP-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v40, 0 :: v_dual_mov_b32 v31, v0 +; GFX1132-DPP-NEXT: s_mov_b32 s12, s13 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s13, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s15 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1132-DPP-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1132-DPP-NEXT: s_mov_b32 s0, 0 +; GFX1132-DPP-NEXT: .LBB12_1: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, v3 :: v_dual_mov_b32 v4, v2 +; GFX1132-DPP-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s0 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB12_1 +; GFX1132-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-DPP-NEXT: s_endpgm + %divValue = call double @div.double.value() strictfp + %result = atomicrmw fsub ptr addrspace(1) %ptr, double %divValue syncscope("one-as") monotonic + ret void +} + +define amdgpu_kernel void @global_atomic_fsub_double_uni_address_uni_value_agent_scope_strictfp(ptr addrspace(1) %ptr) #2{ +; GFX7LESS-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_strictfp: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_mov_b32 s12, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s13, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s14, -1 +; GFX7LESS-NEXT: s_mov_b32 s15, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s12, s12, s3 +; GFX7LESS-NEXT: s_addc_u32 s13, s13, 0 +; GFX7LESS-NEXT: s_mov_b64 s[2:3], exec +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, s2, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, s3, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB13_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x9 +; GFX7LESS-NEXT: s_bcnt1_i32_b64 s6, s[2:3] +; GFX7LESS-NEXT: s_mov_b32 s7, 0x43300000 +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0xc3300000 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dwordx2 s[8:9], s[0:1], 0x0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], 0 +; GFX7LESS-NEXT: s_mov_b32 s3, 0xf000 +; GFX7LESS-NEXT: v_add_f64 v[0:1], s[6:7], v[0:1] +; GFX7LESS-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s8 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s9 +; GFX7LESS-NEXT: s_mov_b32 s2, -1 +; GFX7LESS-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v9, v3 +; GFX7LESS-NEXT: v_mov_b32_e32 v8, v2 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, v1 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, v0 +; GFX7LESS-NEXT: buffer_atomic_cmpswap_x2 v[6:9], off, s[0:3], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[2:3] +; GFX7LESS-NEXT: s_or_b64 s[4:5], vcc, s[4:5] +; GFX7LESS-NEXT: v_mov_b32_e32 v2, v6 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, v7 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[4:5] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB13_2 +; GFX7LESS-NEXT: .LBB13_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_strictfp: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s10, -1 +; GFX9-NEXT: s_mov_b32 s11, 0xe00000 +; GFX9-NEXT: s_add_u32 s8, s8, s3 +; GFX9-NEXT: s_mov_b64 s[2:3], exec +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX9-NEXT: s_addc_u32 s9, s9, 0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX9-NEXT: s_cbranch_execz .LBB13_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: v_mov_b32_e32 v0, 0 +; GFX9-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX9-NEXT: v_mov_b32_e32 v1, 0xc3300000 +; GFX9-NEXT: s_mov_b32 s3, 0x43300000 +; GFX9-NEXT: v_add_f64 v[0:1], s[2:3], v[0:1] +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-NEXT: v_mov_b32_e32 v3, s5 +; GFX9-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX9-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX9-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-NEXT: s_cbranch_execnz .LBB13_2 +; GFX9-NEXT: .LBB13_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_strictfp: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s10, -1 +; GFX1064-NEXT: s_mov_b32 s11, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s8, s8, s3 +; GFX1064-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-NEXT: s_addc_u32 s9, s9, 0 +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB13_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX1064-NEXT: s_mov_b32 s3, 0x43300000 +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-NEXT: v_add_f64 v[0:1], 0xc3300000, s[2:3] +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX1064-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v2, s2 +; GFX1064-NEXT: v_mov_b32_e32 v3, s3 +; GFX1064-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX1064-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1064-NEXT: v_mov_b32_e32 v3, v1 +; GFX1064-NEXT: v_mov_b32_e32 v2, v0 +; GFX1064-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1064-NEXT: .LBB13_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_strictfp: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s10, -1 +; GFX1032-NEXT: s_mov_b32 s11, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s8, s8, s3 +; GFX1032-NEXT: s_mov_b32 s3, exec_lo +; GFX1032-NEXT: s_addc_u32 s9, s9, 0 +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, s3, 0 +; GFX1032-NEXT: s_mov_b32 s2, 0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_and_saveexec_b32 s4, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB13_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_bcnt1_i32_b32 s4, s3 +; GFX1032-NEXT: s_mov_b32 s5, 0x43300000 +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-NEXT: v_add_f64 v[0:1], 0xc3300000, s[4:5] +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v2, s4 +; GFX1032-NEXT: v_mov_b32_e32 v3, s5 +; GFX1032-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX1032-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1032-NEXT: v_mov_b32_e32 v3, v1 +; GFX1032-NEXT: v_mov_b32_e32 v2, v0 +; GFX1032-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1032-NEXT: .LBB13_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_strictfp: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_bcnt1_i32_b64 s2, exec +; GFX1164-NEXT: v_mov_b32_e32 v0, 0x43300000 +; GFX1164-NEXT: v_mov_b32_e32 v1, s2 +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1164-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b32 off, v0, off offset:4 +; GFX1164-NEXT: scratch_store_b32 off, v1, off +; GFX1164-NEXT: scratch_load_b64 v[0:1], off, off +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v2, exec_hi, v2 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1164-NEXT: s_cbranch_execz .LBB13_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b64 s[2:3], s[0:1], 0x0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_2) +; GFX1164-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v2, s2 +; GFX1164-NEXT: v_mov_b32_e32 v3, s3 +; GFX1164-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX1164-NEXT: global_atomic_cmpswap_b64 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1164-NEXT: v_mov_b32_e32 v3, v1 +; GFX1164-NEXT: v_mov_b32_e32 v2, v0 +; GFX1164-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1164-NEXT: .LBB13_3: +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_strictfp: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_bcnt1_i32_b32 s2, exec_lo +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: v_dual_mov_b32 v0, 0x43300000 :: v_dual_mov_b32 v1, s2 +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1132-NEXT: s_mov_b32 s2, 0 +; GFX1132-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b32 off, v0, off offset:4 +; GFX1132-NEXT: scratch_store_b32 off, v1, off +; GFX1132-NEXT: scratch_load_b64 v[0:1], off, off +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1132-NEXT: s_cbranch_execz .LBB13_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-NEXT: v_mov_b32_e32 v6, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b64 s[4:5], s[0:1], 0x0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_2) +; GFX1132-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: v_dual_mov_b32 v2, s4 :: v_dual_mov_b32 v3, s5 +; GFX1132-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX1132-NEXT: global_atomic_cmpswap_b64 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1132-NEXT: v_dual_mov_b32 v3, v1 :: v_dual_mov_b32 v2, v0 +; GFX1132-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1132-NEXT: .LBB13_3: +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_strictfp: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s10, -1 +; GFX9-DPP-NEXT: s_mov_b32 s11, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s8, s8, s3 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX9-DPP-NEXT: s_addc_u32 s9, s9, 0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 0 +; GFX9-DPP-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0xc3300000 +; GFX9-DPP-NEXT: s_mov_b32 s3, 0x43300000 +; GFX9-DPP-NEXT: v_add_f64 v[0:1], s[2:3], v[0:1] +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s4 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s5 +; GFX9-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX9-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX9-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX9-DPP-NEXT: .LBB13_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_strictfp: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s10, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s11, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s8, s8, s3 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-DPP-NEXT: s_addc_u32 s9, s9, 0 +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_bcnt1_i32_b64 s2, s[2:3] +; GFX1064-DPP-NEXT: s_mov_b32 s3, 0x43300000 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1064-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, s[2:3] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s2 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s3 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1064-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX1064-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[2:3] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1064-DPP-NEXT: .LBB13_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_strictfp: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s8, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s9, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s10, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s11, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s8, s8, s3 +; GFX1032-DPP-NEXT: s_mov_b32 s3, exec_lo +; GFX1032-DPP-NEXT: s_addc_u32 s9, s9, 0 +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s3, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s4, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_bcnt1_i32_b32 s4, s3 +; GFX1032-DPP-NEXT: s_mov_b32 s5, 0x43300000 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x24 +; GFX1032-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, s[4:5] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s4 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s5 +; GFX1032-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX1032-DPP-NEXT: global_atomic_cmpswap_x2 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1032-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s2 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1032-DPP-NEXT: .LBB13_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_strictfp: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_bcnt1_i32_b64 s2, exec +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 0x43300000 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s2 +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b32 off, v0, off offset:4 +; GFX1164-DPP-NEXT: scratch_store_b32 off, v1, off +; GFX1164-DPP-NEXT: scratch_load_b64 v[0:1], off, off +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v2, exec_hi, v2 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b64 s[2:3], s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_2) +; GFX1164-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s2 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s3 +; GFX1164-DPP-NEXT: s_mov_b64 s[2:3], 0 +; GFX1164-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b64 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[0:1], v[2:3] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, v1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[2:3], vcc, s[2:3] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[2:3] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1164-DPP-NEXT: .LBB13_3: +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_agent_scope_strictfp: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_bcnt1_i32_b32 s2, exec_lo +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v0, 0x43300000 :: v_dual_mov_b32 v1, s2 +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s2, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s3, exec_lo +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b32 off, v0, off offset:4 +; GFX1132-DPP-NEXT: scratch_store_b32 off, v1, off +; GFX1132-DPP-NEXT: scratch_load_b64 v[0:1], off, off +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB13_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b64 s[4:5], s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_2) +; GFX1132-DPP-NEXT: v_mul_f64 v[4:5], 4.0, v[0:1] +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v2, s4 :: v_dual_mov_b32 v3, s5 +; GFX1132-DPP-NEXT: .LBB13_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_add_f64 v[0:1], v[2:3], -v[4:5] +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b64 v[0:1], v6, v[0:3], s[0:1] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[0:1], v[2:3] +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, v1 :: v_dual_mov_b32 v2, v0 +; GFX1132-DPP-NEXT: s_or_b32 s2, vcc_lo, s2 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s2 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB13_2 +; GFX1132-DPP-NEXT: .LBB13_3: +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fsub ptr addrspace(1) %ptr, double 4.0 syncscope("agent") monotonic + ret void +} + +define amdgpu_kernel void @global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe(ptr addrspace(1) %ptr) #0 { +; GFX7LESS-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_mov_b32 s32, 0 +; GFX7LESS-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s42, -1 +; GFX7LESS-NEXT: s_mov_b32 s43, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s40, s40, s9 +; GFX7LESS-NEXT: s_addc_u32 s41, s41, 0 +; GFX7LESS-NEXT: s_mov_b32 s14, s8 +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX7LESS-NEXT: s_load_dwordx2 s[36:37], s[2:3], 0x9 +; GFX7LESS-NEXT: s_mov_b32 s39, 0xf000 +; GFX7LESS-NEXT: s_mov_b32 s38, -1 +; GFX7LESS-NEXT: s_add_u32 s8, s2, 44 +; GFX7LESS-NEXT: s_addc_u32 s9, s3, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[2:3] +; GFX7LESS-NEXT: s_add_u32 s2, s2, div.double.value@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s3, s3, div.double.value@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v0, v0, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v31, v0, v2 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX7LESS-NEXT: s_mov_b32 s12, s6 +; GFX7LESS-NEXT: s_mov_b32 s13, s7 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX7LESS-NEXT: buffer_load_dwordx2 v[4:5], off, s[36:39], 0 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], 0 +; GFX7LESS-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v9, v5 +; GFX7LESS-NEXT: v_mov_b32_e32 v8, v4 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, v3 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, v2 +; GFX7LESS-NEXT: buffer_atomic_cmpswap_x2 v[6:9], off, s[36:39], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[4:5] +; GFX7LESS-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX7LESS-NEXT: v_mov_b32_e32 v4, v6 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, v7 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB14_1 +; GFX7LESS-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s38, -1 +; GFX9-NEXT: s_mov_b32 s39, 0xe00000 +; GFX9-NEXT: s_add_u32 s36, s36, s9 +; GFX9-NEXT: s_addc_u32 s37, s37, 0 +; GFX9-NEXT: s_mov_b32 s14, s8 +; GFX9-NEXT: s_add_u32 s8, s2, 44 +; GFX9-NEXT: s_addc_u32 s9, s3, 0 +; GFX9-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX9-NEXT: s_getpc_b64 s[2:3] +; GFX9-NEXT: s_add_u32 s2, s2, div.double.value@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s3, s3, div.double.value@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX9-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX9-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX9-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX9-NEXT: s_mov_b32 s12, s6 +; GFX9-NEXT: s_mov_b32 s13, s7 +; GFX9-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX9-NEXT: s_mov_b32 s32, 0 +; GFX9-NEXT: v_mov_b32_e32 v40, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX9-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX9-NEXT: s_mov_b64 s[0:1], 0 +; GFX9-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX9-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX9-NEXT: v_mov_b32_e32 v5, v3 +; GFX9-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX9-NEXT: v_mov_b32_e32 v4, v2 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX9-NEXT: s_cbranch_execnz .LBB14_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s38, -1 +; GFX1064-NEXT: s_mov_b32 s39, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s36, s36, s9 +; GFX1064-NEXT: s_addc_u32 s37, s37, 0 +; GFX1064-NEXT: s_mov_b32 s14, s8 +; GFX1064-NEXT: s_add_u32 s8, s2, 44 +; GFX1064-NEXT: s_addc_u32 s9, s3, 0 +; GFX1064-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1064-NEXT: s_getpc_b64 s[4:5] +; GFX1064-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1064-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1064-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1064-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1064-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1064-NEXT: s_mov_b32 s12, s6 +; GFX1064-NEXT: s_mov_b32 s13, s7 +; GFX1064-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1064-NEXT: s_mov_b32 s32, 0 +; GFX1064-NEXT: v_mov_b32_e32 v40, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1064-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1064-NEXT: s_mov_b64 s[0:1], 0 +; GFX1064-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1064-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1064-NEXT: v_mov_b32_e32 v5, v3 +; GFX1064-NEXT: v_mov_b32_e32 v4, v2 +; GFX1064-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX1064-NEXT: s_cbranch_execnz .LBB14_1 +; GFX1064-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s38, -1 +; GFX1032-NEXT: s_mov_b32 s39, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s36, s36, s9 +; GFX1032-NEXT: s_addc_u32 s37, s37, 0 +; GFX1032-NEXT: s_mov_b32 s14, s8 +; GFX1032-NEXT: s_add_u32 s8, s2, 44 +; GFX1032-NEXT: s_addc_u32 s9, s3, 0 +; GFX1032-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1032-NEXT: s_getpc_b64 s[4:5] +; GFX1032-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1032-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1032-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1032-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1032-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1032-NEXT: s_mov_b32 s12, s6 +; GFX1032-NEXT: s_mov_b32 s13, s7 +; GFX1032-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1032-NEXT: s_mov_b32 s32, 0 +; GFX1032-NEXT: v_mov_b32_e32 v40, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1032-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1032-NEXT: s_mov_b32 s0, 0 +; GFX1032-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1032-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1032-NEXT: v_mov_b32_e32 v5, v3 +; GFX1032-NEXT: v_mov_b32_e32 v4, v2 +; GFX1032-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s0 +; GFX1032-NEXT: s_cbranch_execnz .LBB14_1 +; GFX1032-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b32 s14, s8 +; GFX1164-NEXT: s_add_u32 s8, s2, 44 +; GFX1164-NEXT: s_addc_u32 s9, s3, 0 +; GFX1164-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1164-NEXT: s_getpc_b64 s[4:5] +; GFX1164-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1164-NEXT: s_load_b64 s[16:17], s[4:5], 0x0 +; GFX1164-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1164-NEXT: s_mov_b32 s12, s6 +; GFX1164-NEXT: s_mov_b32 s13, s7 +; GFX1164-NEXT: s_mov_b32 s32, 0 +; GFX1164-NEXT: v_mov_b32_e32 v40, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1164-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1164-NEXT: s_mov_b64 s[0:1], 0 +; GFX1164-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1164-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1164-NEXT: v_mov_b32_e32 v5, v3 +; GFX1164-NEXT: v_mov_b32_e32 v4, v2 +; GFX1164-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[0:1] +; GFX1164-NEXT: s_cbranch_execnz .LBB14_1 +; GFX1164-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_add_u32 s8, s2, 44 +; GFX1132-NEXT: s_addc_u32 s9, s3, 0 +; GFX1132-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1132-NEXT: s_getpc_b64 s[4:5] +; GFX1132-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1132-NEXT: s_load_b64 s[6:7], s[4:5], 0x0 +; GFX1132-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1132-NEXT: v_dual_mov_b32 v40, 0 :: v_dual_mov_b32 v31, v0 +; GFX1132-NEXT: s_mov_b32 s12, s13 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1132-NEXT: s_mov_b32 s13, s14 +; GFX1132-NEXT: s_mov_b32 s14, s15 +; GFX1132-NEXT: s_mov_b32 s32, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1132-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1132-NEXT: s_mov_b32 s0, 0 +; GFX1132-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1132-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1132-NEXT: v_dual_mov_b32 v5, v3 :: v_dual_mov_b32 v4, v2 +; GFX1132-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s0 +; GFX1132-NEXT: s_cbranch_execnz .LBB14_1 +; GFX1132-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s38, -1 +; GFX9-DPP-NEXT: s_mov_b32 s39, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX9-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX9-DPP-NEXT: s_mov_b32 s14, s8 +; GFX9-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX9-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX9-DPP-NEXT: s_getpc_b64 s[2:3] +; GFX9-DPP-NEXT: s_add_u32 s2, s2, div.double.value@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s3, s3, div.double.value@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX9-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX9-DPP-NEXT: s_mov_b32 s12, s6 +; GFX9-DPP-NEXT: s_mov_b32 s13, s7 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX9-DPP-NEXT: s_mov_b32 s32, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX9-DPP-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX9-DPP-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX9-DPP-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX9-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB14_1 +; GFX9-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s38, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s39, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX1064-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1064-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1064-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1064-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1064-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1064-DPP-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX1064-DPP-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1064-DPP-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX1064-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB14_1 +; GFX1064-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s38, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s39, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX1032-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1032-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1032-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1032-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1032-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1032-DPP-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1032-DPP-NEXT: s_mov_b32 s0, 0 +; GFX1032-DPP-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1032-DPP-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX1032-DPP-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s0 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB14_1 +; GFX1032-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1164-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1164-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1164-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: s_load_b64 s[16:17], s[4:5], 0x0 +; GFX1164-DPP-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1164-DPP-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1164-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX1164-DPP-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX1164-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[0:1] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB14_1 +; GFX1164-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1132-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1132-DPP-NEXT: s_add_u32 s4, s4, div.double.value@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s5, s5, div.double.value@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: s_load_b64 s[6:7], s[4:5], 0x0 +; GFX1132-DPP-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v40, 0 :: v_dual_mov_b32 v31, v0 +; GFX1132-DPP-NEXT: s_mov_b32 s12, s13 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s13, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s15 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1132-DPP-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1132-DPP-NEXT: s_mov_b32 s0, 0 +; GFX1132-DPP-NEXT: .LBB14_1: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, v3 :: v_dual_mov_b32 v4, v2 +; GFX1132-DPP-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s0 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB14_1 +; GFX1132-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-DPP-NEXT: s_endpgm + %divValue = call double @div.double.value() + %result = atomicrmw fsub ptr addrspace(1) %ptr, double %divValue syncscope("agent") monotonic + ret void +} + +define amdgpu_kernel void @global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe_structfp(ptr addrspace(1) %ptr) #1 { +; GFX7LESS-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_mov_b32 s32, 0 +; GFX7LESS-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s42, -1 +; GFX7LESS-NEXT: s_mov_b32 s43, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s40, s40, s9 +; GFX7LESS-NEXT: s_addc_u32 s41, s41, 0 +; GFX7LESS-NEXT: s_mov_b32 s14, s8 +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX7LESS-NEXT: s_load_dwordx2 s[36:37], s[2:3], 0x9 +; GFX7LESS-NEXT: s_mov_b32 s39, 0xf000 +; GFX7LESS-NEXT: s_mov_b32 s38, -1 +; GFX7LESS-NEXT: s_add_u32 s8, s2, 44 +; GFX7LESS-NEXT: s_addc_u32 s9, s3, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[2:3] +; GFX7LESS-NEXT: s_add_u32 s2, s2, div.float.value@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s3, s3, div.float.value@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v0, v0, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v31, v0, v2 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX7LESS-NEXT: s_mov_b32 s12, s6 +; GFX7LESS-NEXT: s_mov_b32 s13, s7 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX7LESS-NEXT: buffer_load_dwordx2 v[4:5], off, s[36:39], 0 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], 0 +; GFX7LESS-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v9, v5 +; GFX7LESS-NEXT: v_mov_b32_e32 v8, v4 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, v3 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, v2 +; GFX7LESS-NEXT: buffer_atomic_cmpswap_x2 v[6:9], off, s[36:39], 0 glc +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_cmp_eq_u64_e32 vcc, v[6:7], v[4:5] +; GFX7LESS-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX7LESS-NEXT: v_mov_b32_e32 v4, v6 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, v7 +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB15_1 +; GFX7LESS-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s38, -1 +; GFX9-NEXT: s_mov_b32 s39, 0xe00000 +; GFX9-NEXT: s_add_u32 s36, s36, s9 +; GFX9-NEXT: s_addc_u32 s37, s37, 0 +; GFX9-NEXT: s_mov_b32 s14, s8 +; GFX9-NEXT: s_add_u32 s8, s2, 44 +; GFX9-NEXT: s_addc_u32 s9, s3, 0 +; GFX9-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX9-NEXT: s_getpc_b64 s[2:3] +; GFX9-NEXT: s_add_u32 s2, s2, div.float.value@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s3, s3, div.float.value@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX9-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX9-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX9-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX9-NEXT: s_mov_b32 s12, s6 +; GFX9-NEXT: s_mov_b32 s13, s7 +; GFX9-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX9-NEXT: s_mov_b32 s32, 0 +; GFX9-NEXT: v_mov_b32_e32 v40, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX9-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX9-NEXT: s_mov_b64 s[0:1], 0 +; GFX9-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX9-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX9-NEXT: v_mov_b32_e32 v5, v3 +; GFX9-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX9-NEXT: v_mov_b32_e32 v4, v2 +; GFX9-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX9-NEXT: s_cbranch_execnz .LBB15_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s38, -1 +; GFX1064-NEXT: s_mov_b32 s39, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s36, s36, s9 +; GFX1064-NEXT: s_addc_u32 s37, s37, 0 +; GFX1064-NEXT: s_mov_b32 s14, s8 +; GFX1064-NEXT: s_add_u32 s8, s2, 44 +; GFX1064-NEXT: s_addc_u32 s9, s3, 0 +; GFX1064-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1064-NEXT: s_getpc_b64 s[4:5] +; GFX1064-NEXT: s_add_u32 s4, s4, div.float.value@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s5, s5, div.float.value@gotpcrel32@hi+12 +; GFX1064-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1064-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1064-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1064-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1064-NEXT: s_mov_b32 s12, s6 +; GFX1064-NEXT: s_mov_b32 s13, s7 +; GFX1064-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1064-NEXT: s_mov_b32 s32, 0 +; GFX1064-NEXT: v_mov_b32_e32 v40, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1064-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1064-NEXT: s_mov_b64 s[0:1], 0 +; GFX1064-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1064-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1064-NEXT: v_mov_b32_e32 v5, v3 +; GFX1064-NEXT: v_mov_b32_e32 v4, v2 +; GFX1064-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX1064-NEXT: s_cbranch_execnz .LBB15_1 +; GFX1064-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s38, -1 +; GFX1032-NEXT: s_mov_b32 s39, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s36, s36, s9 +; GFX1032-NEXT: s_addc_u32 s37, s37, 0 +; GFX1032-NEXT: s_mov_b32 s14, s8 +; GFX1032-NEXT: s_add_u32 s8, s2, 44 +; GFX1032-NEXT: s_addc_u32 s9, s3, 0 +; GFX1032-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1032-NEXT: s_getpc_b64 s[4:5] +; GFX1032-NEXT: s_add_u32 s4, s4, div.float.value@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s5, s5, div.float.value@gotpcrel32@hi+12 +; GFX1032-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1032-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1032-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1032-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1032-NEXT: s_mov_b32 s12, s6 +; GFX1032-NEXT: s_mov_b32 s13, s7 +; GFX1032-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1032-NEXT: s_mov_b32 s32, 0 +; GFX1032-NEXT: v_mov_b32_e32 v40, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1032-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1032-NEXT: s_mov_b32 s0, 0 +; GFX1032-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1032-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1032-NEXT: v_mov_b32_e32 v5, v3 +; GFX1032-NEXT: v_mov_b32_e32 v4, v2 +; GFX1032-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s0 +; GFX1032-NEXT: s_cbranch_execnz .LBB15_1 +; GFX1032-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b32 s14, s8 +; GFX1164-NEXT: s_add_u32 s8, s2, 44 +; GFX1164-NEXT: s_addc_u32 s9, s3, 0 +; GFX1164-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1164-NEXT: s_getpc_b64 s[4:5] +; GFX1164-NEXT: s_add_u32 s4, s4, div.float.value@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s5, s5, div.float.value@gotpcrel32@hi+12 +; GFX1164-NEXT: s_load_b64 s[16:17], s[4:5], 0x0 +; GFX1164-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1164-NEXT: s_mov_b32 s12, s6 +; GFX1164-NEXT: s_mov_b32 s13, s7 +; GFX1164-NEXT: s_mov_b32 s32, 0 +; GFX1164-NEXT: v_mov_b32_e32 v40, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1164-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1164-NEXT: s_mov_b64 s[0:1], 0 +; GFX1164-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1164-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1164-NEXT: v_mov_b32_e32 v5, v3 +; GFX1164-NEXT: v_mov_b32_e32 v4, v2 +; GFX1164-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1164-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[0:1] +; GFX1164-NEXT: s_cbranch_execnz .LBB15_1 +; GFX1164-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_add_u32 s8, s2, 44 +; GFX1132-NEXT: s_addc_u32 s9, s3, 0 +; GFX1132-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1132-NEXT: s_getpc_b64 s[4:5] +; GFX1132-NEXT: s_add_u32 s4, s4, div.float.value@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s5, s5, div.float.value@gotpcrel32@hi+12 +; GFX1132-NEXT: s_load_b64 s[6:7], s[4:5], 0x0 +; GFX1132-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1132-NEXT: v_dual_mov_b32 v40, 0 :: v_dual_mov_b32 v31, v0 +; GFX1132-NEXT: s_mov_b32 s12, s13 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1132-NEXT: s_mov_b32 s13, s14 +; GFX1132-NEXT: s_mov_b32 s14, s15 +; GFX1132-NEXT: s_mov_b32 s32, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1132-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1132-NEXT: s_mov_b32 s0, 0 +; GFX1132-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1132-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1132-NEXT: v_dual_mov_b32 v5, v3 :: v_dual_mov_b32 v4, v2 +; GFX1132-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s0 +; GFX1132-NEXT: s_cbranch_execnz .LBB15_1 +; GFX1132-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s38, -1 +; GFX9-DPP-NEXT: s_mov_b32 s39, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX9-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX9-DPP-NEXT: s_mov_b32 s14, s8 +; GFX9-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX9-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX9-DPP-NEXT: s_getpc_b64 s[2:3] +; GFX9-DPP-NEXT: s_add_u32 s2, s2, div.float.value@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s3, s3, div.float.value@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[16:17], s[2:3], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX9-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX9-DPP-NEXT: s_mov_b32 s12, s6 +; GFX9-DPP-NEXT: s_mov_b32 s13, s7 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX9-DPP-NEXT: s_mov_b32 s32, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX9-DPP-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX9-DPP-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX9-DPP-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX9-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB15_1 +; GFX9-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s38, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s39, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX1064-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1064-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1064-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1064-DPP-NEXT: s_add_u32 s4, s4, div.float.value@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s5, s5, div.float.value@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1064-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1064-DPP-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX1064-DPP-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1064-DPP-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX1064-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[0:1] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB15_1 +; GFX1064-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s36, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s37, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s38, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s39, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s36, s36, s9 +; GFX1032-DPP-NEXT: s_addc_u32 s37, s37, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1032-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1032-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1032-DPP-NEXT: s_add_u32 s4, s4, div.float.value@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s5, s5, div.float.value@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[16:17], s[4:5], 0x0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[34:35], s[2:3], 0x24 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[36:37] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1032-DPP-NEXT: v_or3_b32 v31, v0, v1, v2 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1032-DPP-NEXT: global_load_dwordx2 v[4:5], v40, s[34:35] +; GFX1032-DPP-NEXT: s_mov_b32 s0, 0 +; GFX1032-DPP-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1032-DPP-NEXT: global_atomic_cmpswap_x2 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX1032-DPP-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s0 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB15_1 +; GFX1032-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b32 s14, s8 +; GFX1164-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1164-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1164-DPP-NEXT: s_add_u32 s4, s4, div.float.value@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s5, s5, div.float.value@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: s_load_b64 s[16:17], s[4:5], 0x0 +; GFX1164-DPP-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[16:17] +; GFX1164-DPP-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1164-DPP-NEXT: s_mov_b64 s[0:1], 0 +; GFX1164-DPP-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1164-DPP-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_cmp_eq_u64_e32 vcc, v[2:3], v[4:5] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, v3 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, v2 +; GFX1164-DPP-NEXT: s_or_b64 s[0:1], vcc, s[0:1] +; GFX1164-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[0:1] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB15_1 +; GFX1164-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_agent_scope_unsafe_structfp: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_add_u32 s8, s2, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s3, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[4:5] +; GFX1132-DPP-NEXT: s_getpc_b64 s[4:5] +; GFX1132-DPP-NEXT: s_add_u32 s4, s4, div.float.value@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s5, s5, div.float.value@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: s_load_b64 s[6:7], s[4:5], 0x0 +; GFX1132-DPP-NEXT: s_load_b64 s[34:35], s[2:3], 0x24 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v40, 0 :: v_dual_mov_b32 v31, v0 +; GFX1132-DPP-NEXT: s_mov_b32 s12, s13 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[0:1] +; GFX1132-DPP-NEXT: s_mov_b32 s13, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s15 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1132-DPP-NEXT: global_load_b64 v[4:5], v40, s[34:35] +; GFX1132-DPP-NEXT: s_mov_b32 s0, 0 +; GFX1132-DPP-NEXT: .LBB15_1: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_add_f64 v[2:3], v[4:5], -v[0:1] +; GFX1132-DPP-NEXT: global_atomic_cmpswap_b64 v[2:3], v40, v[2:5], s[34:35] glc +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_cmp_eq_u64_e32 vcc_lo, v[2:3], v[4:5] +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, v3 :: v_dual_mov_b32 v4, v2 +; GFX1132-DPP-NEXT: s_or_b32 s0, vcc_lo, s0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s0 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB15_1 +; GFX1132-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-DPP-NEXT: s_endpgm + %divValue = call double @div.float.value() strictfp + %result = atomicrmw fsub ptr addrspace(1) %ptr, double %divValue syncscope("agent") monotonic + ret void +} +define amdgpu_kernel void @global_atomic_fsub_double_uni_address_uni_value_defalut_scope_strictfp(ptr addrspace(1) %ptr) #2 { +; GFX7LESS-LABEL: global_atomic_fsub_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_movk_i32 s32, 0x800 +; GFX7LESS-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s42, -1 +; GFX7LESS-NEXT: s_mov_b32 s43, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s40, s40, s3 +; GFX7LESS-NEXT: s_addc_u32 s41, s41, 0 +; GFX7LESS-NEXT: s_mov_b32 s33, s2 +; GFX7LESS-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX7LESS-NEXT: v_mov_b32_e32 v40, v0 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], exec +; GFX7LESS-NEXT: v_mbcnt_lo_u32_b32_e64 v0, s0, 0 +; GFX7LESS-NEXT: v_mbcnt_hi_u32_b32_e32 v0, s1, v0 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX7LESS-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX7LESS-NEXT: s_cbranch_execz .LBB16_3 +; GFX7LESS-NEXT: ; %bb.1: +; GFX7LESS-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x9 +; GFX7LESS-NEXT: s_bcnt1_i32_b64 s0, s[0:1] +; GFX7LESS-NEXT: s_mov_b32 s1, 0x43300000 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_load_dwordx2 s[2:3], s[36:37], 0x0 +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0xc3300000 +; GFX7LESS-NEXT: v_add_f64 v[0:1], s[0:1], v[0:1] +; GFX7LESS-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX7LESS-NEXT: s_mov_b64 s[38:39], 0 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, s2 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, s3 +; GFX7LESS-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_add_f64 v[2:3], v[0:1], -v[41:42] +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[40:43], 0 offset:4 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[40:43], 0 +; GFX7LESS-NEXT: s_add_u32 s8, s34, 44 +; GFX7LESS-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:12 +; GFX7LESS-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:8 +; GFX7LESS-NEXT: s_addc_u32 s9, s35, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX7LESS-NEXT: s_waitcnt expcnt(2) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v4, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, 0 +; GFX7LESS-NEXT: s_mov_b32 s12, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v40 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s36 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s37 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX7LESS-NEXT: v_and_b32_e32 v2, 1, v0 +; GFX7LESS-NEXT: buffer_load_dword v0, off, s[40:43], 0 +; GFX7LESS-NEXT: buffer_load_dword v1, off, s[40:43], 0 offset:4 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 1, v2 +; GFX7LESS-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB16_2 +; GFX7LESS-NEXT: .LBB16_3: +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fsub_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s42, -1 +; GFX9-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX9-NEXT: s_mov_b64 s[0:1], exec +; GFX9-NEXT: s_mov_b32 s43, 0xe00000 +; GFX9-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-NEXT: v_mbcnt_lo_u32_b32 v0, s0, 0 +; GFX9-NEXT: s_add_u32 s40, s40, s3 +; GFX9-NEXT: v_mbcnt_hi_u32_b32 v0, s1, v0 +; GFX9-NEXT: s_addc_u32 s41, s41, 0 +; GFX9-NEXT: s_mov_b32 s33, s2 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-NEXT: s_movk_i32 s32, 0x800 +; GFX9-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-NEXT: s_cbranch_execz .LBB16_3 +; GFX9-NEXT: ; %bb.1: +; GFX9-NEXT: v_mov_b32_e32 v0, 0 +; GFX9-NEXT: s_bcnt1_i32_b64 s0, s[0:1] +; GFX9-NEXT: v_mov_b32_e32 v1, 0xc3300000 +; GFX9-NEXT: s_mov_b32 s1, 0x43300000 +; GFX9-NEXT: v_add_f64 v[0:1], s[0:1], v[0:1] +; GFX9-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX9-NEXT: s_mov_b64 s[38:39], 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX9-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: v_mov_b32_e32 v2, s1 +; GFX9-NEXT: v_mov_b32_e32 v1, s0 +; GFX9-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX9-NEXT: s_add_u32 s8, s34, 44 +; GFX9-NEXT: s_addc_u32 s9, s35, 0 +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX9-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX9-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX9-NEXT: s_mov_b32 s12, s33 +; GFX9-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX9-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX9-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX9-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: v_mov_b32_e32 v2, s36 +; GFX9-NEXT: v_mov_b32_e32 v3, s37 +; GFX9-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX9-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX9-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX9-NEXT: s_cbranch_execnz .LBB16_2 +; GFX9-NEXT: .LBB16_3: +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fsub_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s42, -1 +; GFX1064-NEXT: s_mov_b32 s43, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s40, s40, s3 +; GFX1064-NEXT: s_mov_b32 s33, s2 +; GFX1064-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-NEXT: s_addc_u32 s41, s41, 0 +; GFX1064-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1064-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX1064-NEXT: s_cbranch_execz .LBB16_3 +; GFX1064-NEXT: ; %bb.1: +; GFX1064-NEXT: s_bcnt1_i32_b64 s0, s[2:3] +; GFX1064-NEXT: s_mov_b32 s1, 0x43300000 +; GFX1064-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1064-NEXT: v_add_f64 v[0:1], 0xc3300000, s[0:1] +; GFX1064-NEXT: s_mov_b64 s[38:39], 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1064-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: v_mov_b32_e32 v2, s1 +; GFX1064-NEXT: v_mov_b32_e32 v1, s0 +; GFX1064-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1064-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1064-NEXT: s_mov_b32 s12, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1064-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1064-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1064-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1064-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-NEXT: v_mov_b32_e32 v2, s36 +; GFX1064-NEXT: v_mov_b32_e32 v3, s37 +; GFX1064-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1064-NEXT: s_clause 0x1 +; GFX1064-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1064-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX1064-NEXT: s_cbranch_execnz .LBB16_2 +; GFX1064-NEXT: .LBB16_3: +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fsub_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s33, s2 +; GFX1032-NEXT: s_mov_b32 s2, exec_lo +; GFX1032-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1032-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s42, -1 +; GFX1032-NEXT: s_mov_b32 s43, 0x31c16000 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-NEXT: s_add_u32 s40, s40, s3 +; GFX1032-NEXT: s_addc_u32 s41, s41, 0 +; GFX1032-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1032-NEXT: s_mov_b32 s38, 0 +; GFX1032-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-NEXT: s_and_saveexec_b32 s0, vcc_lo +; GFX1032-NEXT: s_cbranch_execz .LBB16_3 +; GFX1032-NEXT: ; %bb.1: +; GFX1032-NEXT: s_bcnt1_i32_b32 s0, s2 +; GFX1032-NEXT: s_mov_b32 s1, 0x43300000 +; GFX1032-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1032-NEXT: v_add_f64 v[0:1], 0xc3300000, s[0:1] +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1032-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: v_mov_b32_e32 v2, s1 +; GFX1032-NEXT: v_mov_b32_e32 v1, s0 +; GFX1032-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1032-NEXT: s_mov_b32 s12, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1032-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1032-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1032-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1032-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-NEXT: v_mov_b32_e32 v2, s36 +; GFX1032-NEXT: v_mov_b32_e32 v3, s37 +; GFX1032-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1032-NEXT: s_clause 0x1 +; GFX1032-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1032-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s38 +; GFX1032-NEXT: s_cbranch_execnz .LBB16_2 +; GFX1032-NEXT: .LBB16_3: +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fsub_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1164-NEXT: s_bcnt1_i32_b64 s0, exec +; GFX1164-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-NEXT: v_mov_b32_e32 v0, 0x43300000 +; GFX1164-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b32 off, v0, off offset:20 +; GFX1164-NEXT: scratch_store_b32 off, v1, off offset:16 +; GFX1164-NEXT: scratch_load_b64 v[0:1], off, off offset:16 +; GFX1164-NEXT: v_mbcnt_hi_u32_b32 v2, exec_hi, v2 +; GFX1164-NEXT: s_mov_b32 s32, 32 +; GFX1164-NEXT: s_mov_b64 s[0:1], exec +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1164-NEXT: s_cbranch_execz .LBB16_3 +; GFX1164-NEXT: ; %bb.1: +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1164-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1164-NEXT: s_mov_b32 s33, s2 +; GFX1164-NEXT: s_mov_b64 s[38:39], 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: v_mov_b32_e32 v2, s1 +; GFX1164-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-NEXT: .p2align 6 +; GFX1164-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-NEXT: s_mov_b32 s12, s33 +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-NEXT: v_mov_b32_e32 v2, s36 +; GFX1164-NEXT: v_mov_b32_e32 v3, s37 +; GFX1164-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[38:39] +; GFX1164-NEXT: s_cbranch_execnz .LBB16_2 +; GFX1164-NEXT: .LBB16_3: +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fsub_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1132-NEXT: s_bcnt1_i32_b32 s0, exec_lo +; GFX1132-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v1, s0 +; GFX1132-NEXT: v_mov_b32_e32 v0, 0x43300000 +; GFX1132-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b32 off, v0, off offset:20 +; GFX1132-NEXT: scratch_store_b32 off, v1, off offset:16 +; GFX1132-NEXT: scratch_load_b64 v[0:1], off, off offset:16 +; GFX1132-NEXT: s_mov_b32 s38, 0 +; GFX1132-NEXT: s_mov_b32 s32, 32 +; GFX1132-NEXT: s_mov_b32 s0, exec_lo +; GFX1132-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1132-NEXT: s_cbranch_execz .LBB16_3 +; GFX1132-NEXT: ; %bb.1: +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1132-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1132-NEXT: s_mov_b32 s33, s15 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: v_dual_mov_b32 v2, s1 :: v_dual_mov_b32 v1, s0 +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-NEXT: .p2align 6 +; GFX1132-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-NEXT: v_dual_mov_b32 v31, v40 :: v_dual_mov_b32 v0, 8 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-NEXT: s_mov_b32 s12, s33 +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s36 +; GFX1132-NEXT: v_dual_mov_b32 v3, s37 :: v_dual_mov_b32 v4, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s38 +; GFX1132-NEXT: s_cbranch_execnz .LBB16_2 +; GFX1132-NEXT: .LBB16_3: +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s42, -1 +; GFX9-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], exec +; GFX9-DPP-NEXT: s_mov_b32 s43, 0xe00000 +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s0, 0 +; GFX9-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX9-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s1, v0 +; GFX9-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX9-DPP-NEXT: s_mov_b32 s33, s2 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX9-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX9-DPP-NEXT: s_and_saveexec_b64 s[2:3], vcc +; GFX9-DPP-NEXT: s_cbranch_execz .LBB16_3 +; GFX9-DPP-NEXT: ; %bb.1: +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 0 +; GFX9-DPP-NEXT: s_bcnt1_i32_b64 s0, s[0:1] +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0xc3300000 +; GFX9-DPP-NEXT: s_mov_b32 s1, 0x43300000 +; GFX9-DPP-NEXT: v_add_f64 v[0:1], s[0:1], v[0:1] +; GFX9-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX9-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX9-DPP-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX9-DPP-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX9-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX9-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX9-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX9-DPP-NEXT: s_mov_b32 s12, s33 +; GFX9-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX9-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX9-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX9-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX9-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB16_2 +; GFX9-DPP-NEXT: .LBB16_3: +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s42, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s43, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX1064-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], exec +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1064-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1064-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-DPP-NEXT: v_mbcnt_hi_u32_b32 v0, s3, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 +; GFX1064-DPP-NEXT: s_and_saveexec_b64 s[0:1], vcc +; GFX1064-DPP-NEXT: s_cbranch_execz .LBB16_3 +; GFX1064-DPP-NEXT: ; %bb.1: +; GFX1064-DPP-NEXT: s_bcnt1_i32_b64 s0, s[2:3] +; GFX1064-DPP-NEXT: s_mov_b32 s1, 0x43300000 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1064-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, s[0:1] +; GFX1064-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1064-DPP-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1064-DPP-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1064-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1064-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1064-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1064-DPP-NEXT: s_clause 0x1 +; GFX1064-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1064-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1064-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[38:39] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB16_2 +; GFX1064-DPP-NEXT: .LBB16_3: +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1032-DPP-NEXT: s_mov_b32 s2, exec_lo +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-DPP-NEXT: v_mbcnt_lo_u32_b32 v0, s2, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s40, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s41, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s42, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s43, 0x31c16000 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 +; GFX1032-DPP-NEXT: s_add_u32 s40, s40, s3 +; GFX1032-DPP-NEXT: s_addc_u32 s41, s41, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1032-DPP-NEXT: s_mov_b32 s38, 0 +; GFX1032-DPP-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-DPP-NEXT: s_and_saveexec_b32 s0, vcc_lo +; GFX1032-DPP-NEXT: s_cbranch_execz .LBB16_3 +; GFX1032-DPP-NEXT: ; %bb.1: +; GFX1032-DPP-NEXT: s_bcnt1_i32_b32 s0, s2 +; GFX1032-DPP-NEXT: s_mov_b32 s1, 0x43300000 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[36:37], s[34:35], 0x24 +; GFX1032-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, s[0:1] +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_load_dwordx2 s[0:1], s[36:37], 0x0 +; GFX1032-DPP-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1032-DPP-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[40:41] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[42:43] +; GFX1032-DPP-NEXT: buffer_store_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-DPP-NEXT: buffer_store_dword v1, off, s[40:43], 0 +; GFX1032-DPP-NEXT: buffer_store_dword v4, off, s[40:43], 0 offset:12 +; GFX1032-DPP-NEXT: buffer_store_dword v3, off, s[40:43], 0 offset:8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[4:5] +; GFX1032-DPP-NEXT: s_clause 0x1 +; GFX1032-DPP-NEXT: buffer_load_dword v1, off, s[40:43], 0 +; GFX1032-DPP-NEXT: buffer_load_dword v2, off, s[40:43], 0 offset:4 +; GFX1032-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s38 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB16_2 +; GFX1032-DPP-NEXT: .LBB16_3: +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1164-DPP-NEXT: s_bcnt1_i32_b64 s0, exec +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 0x43300000 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-DPP-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b32 off, v0, off offset:20 +; GFX1164-DPP-NEXT: scratch_store_b32 off, v1, off offset:16 +; GFX1164-DPP-NEXT: scratch_load_b64 v[0:1], off, off offset:16 +; GFX1164-DPP-NEXT: v_mbcnt_hi_u32_b32 v2, exec_hi, v2 +; GFX1164-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1164-DPP-NEXT: s_mov_b64 s[0:1], exec +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1164-DPP-NEXT: s_cbranch_execz .LBB16_3 +; GFX1164-DPP-NEXT: ; %bb.1: +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1164-DPP-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1164-DPP-NEXT: s_mov_b32 s33, s2 +; GFX1164-DPP-NEXT: s_mov_b64 s[38:39], 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s1 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, s0 +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-DPP-NEXT: .p2align 6 +; GFX1164-DPP-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v40 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s36 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s37 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[38:39], vcc, s[38:39] +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[38:39] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB16_2 +; GFX1164-DPP-NEXT: .LBB16_3: +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fsub_double_uni_address_uni_value_defalut_scope_strictfp: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_mov_b64 s[34:35], s[0:1] +; GFX1132-DPP-NEXT: s_bcnt1_i32_b32 s0, exec_lo +; GFX1132-DPP-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v1, s0 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v0, 0x43300000 +; GFX1132-DPP-NEXT: v_mbcnt_lo_u32_b32 v2, exec_lo, 0 +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b32 off, v0, off offset:20 +; GFX1132-DPP-NEXT: scratch_store_b32 off, v1, off offset:16 +; GFX1132-DPP-NEXT: scratch_load_b64 v[0:1], off, off offset:16 +; GFX1132-DPP-NEXT: s_mov_b32 s38, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1132-DPP-NEXT: s_mov_b32 s0, exec_lo +; GFX1132-DPP-NEXT: v_cmpx_eq_u32_e32 0, v2 +; GFX1132-DPP-NEXT: s_cbranch_execz .LBB16_3 +; GFX1132-DPP-NEXT: ; %bb.1: +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_add_f64 v[0:1], 0xc3300000, v[0:1] +; GFX1132-DPP-NEXT: s_load_b64 s[36:37], s[34:35], 0x24 +; GFX1132-DPP-NEXT: s_mov_b32 s33, s15 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[36:37], 0x0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_mul_f64 v[41:42], 4.0, v[0:1] +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: v_dual_mov_b32 v2, s1 :: v_dual_mov_b32 v1, s0 +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-DPP-NEXT: .p2align 6 +; GFX1132-DPP-NEXT: .LBB16_2: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1132-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[41:42] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v31, v40 :: v_dual_mov_b32 v0, 8 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-DPP-NEXT: s_mov_b32 s12, s33 +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s36 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, s37 :: v_dual_mov_b32 v4, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s38, vcc_lo, s38 +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s38 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB16_2 +; GFX1132-DPP-NEXT: .LBB16_3: +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-DPP-NEXT: s_endpgm + %result = atomicrmw fsub ptr addrspace(1) %ptr, double 4.0 monotonic, align 4 + ret void +} + +define amdgpu_kernel void @global_atomic_fsub_double_uni_address_div_value_defalut_scope_strictfp(ptr addrspace(1) %ptr) #2 { +; GFX7LESS-LABEL: global_atomic_fsub_double_uni_address_div_value_defalut_scope_strictfp: +; GFX7LESS: ; %bb.0: +; GFX7LESS-NEXT: s_movk_i32 s32, 0x800 +; GFX7LESS-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX7LESS-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX7LESS-NEXT: s_mov_b32 s50, -1 +; GFX7LESS-NEXT: s_mov_b32 s51, 0xe8f000 +; GFX7LESS-NEXT: s_add_u32 s48, s48, s9 +; GFX7LESS-NEXT: s_addc_u32 s49, s49, 0 +; GFX7LESS-NEXT: s_mov_b32 s33, s8 +; GFX7LESS-NEXT: s_mov_b32 s40, s7 +; GFX7LESS-NEXT: s_mov_b32 s41, s6 +; GFX7LESS-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX7LESS-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX7LESS-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX7LESS-NEXT: s_load_dwordx2 s[44:45], s[2:3], 0x9 +; GFX7LESS-NEXT: s_mov_b32 s47, 0xf000 +; GFX7LESS-NEXT: s_mov_b32 s46, -1 +; GFX7LESS-NEXT: s_add_u32 s8, s36, 44 +; GFX7LESS-NEXT: s_addc_u32 s9, s37, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX7LESS-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v0, v0, v1 +; GFX7LESS-NEXT: v_or_b32_e32 v42, v0, v2 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX7LESS-NEXT: s_mov_b32 s12, s41 +; GFX7LESS-NEXT: s_mov_b32 s13, s40 +; GFX7LESS-NEXT: s_mov_b32 s14, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v42 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX7LESS-NEXT: v_mov_b32_e32 v40, v0 +; GFX7LESS-NEXT: v_mov_b32_e32 v41, v1 +; GFX7LESS-NEXT: buffer_load_dwordx2 v[0:1], off, s[44:47], 0 +; GFX7LESS-NEXT: s_mov_b64 s[42:43], 0 +; GFX7LESS-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX7LESS-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX7LESS-NEXT: s_waitcnt vmcnt(0) +; GFX7LESS-NEXT: v_add_f64 v[2:3], v[0:1], -v[40:41] +; GFX7LESS-NEXT: buffer_store_dword v1, off, s[48:51], 0 offset:4 +; GFX7LESS-NEXT: buffer_store_dword v0, off, s[48:51], 0 +; GFX7LESS-NEXT: s_add_u32 s8, s36, 44 +; GFX7LESS-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:12 +; GFX7LESS-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:8 +; GFX7LESS-NEXT: s_addc_u32 s9, s37, 0 +; GFX7LESS-NEXT: s_getpc_b64 s[0:1] +; GFX7LESS-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX7LESS-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX7LESS-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX7LESS-NEXT: s_waitcnt expcnt(2) +; GFX7LESS-NEXT: v_mov_b32_e32 v0, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v1, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v4, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v5, 8 +; GFX7LESS-NEXT: v_mov_b32_e32 v6, 0 +; GFX7LESS-NEXT: v_mov_b32_e32 v7, 0 +; GFX7LESS-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX7LESS-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX7LESS-NEXT: s_mov_b32 s12, s41 +; GFX7LESS-NEXT: s_mov_b32 s13, s40 +; GFX7LESS-NEXT: s_mov_b32 s14, s33 +; GFX7LESS-NEXT: v_mov_b32_e32 v31, v42 +; GFX7LESS-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX7LESS-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX7LESS-NEXT: s_waitcnt expcnt(0) +; GFX7LESS-NEXT: v_mov_b32_e32 v2, s44 +; GFX7LESS-NEXT: v_mov_b32_e32 v3, s45 +; GFX7LESS-NEXT: s_waitcnt lgkmcnt(0) +; GFX7LESS-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX7LESS-NEXT: v_and_b32_e32 v2, 1, v0 +; GFX7LESS-NEXT: buffer_load_dword v0, off, s[48:51], 0 +; GFX7LESS-NEXT: buffer_load_dword v1, off, s[48:51], 0 offset:4 +; GFX7LESS-NEXT: v_cmp_eq_u32_e32 vcc, 1, v2 +; GFX7LESS-NEXT: s_or_b64 s[42:43], vcc, s[42:43] +; GFX7LESS-NEXT: s_andn2_b64 exec, exec, s[42:43] +; GFX7LESS-NEXT: s_cbranch_execnz .LBB17_1 +; GFX7LESS-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX7LESS-NEXT: s_endpgm +; +; GFX9-LABEL: global_atomic_fsub_double_uni_address_div_value_defalut_scope_strictfp: +; GFX9: ; %bb.0: +; GFX9-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX9-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX9-NEXT: s_mov_b32 s50, -1 +; GFX9-NEXT: s_mov_b32 s51, 0xe00000 +; GFX9-NEXT: s_add_u32 s48, s48, s9 +; GFX9-NEXT: s_addc_u32 s49, s49, 0 +; GFX9-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX9-NEXT: s_mov_b32 s33, s8 +; GFX9-NEXT: s_add_u32 s8, s36, 44 +; GFX9-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX9-NEXT: s_mov_b32 s40, s7 +; GFX9-NEXT: s_mov_b32 s41, s6 +; GFX9-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX9-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX9-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX9-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-NEXT: s_mov_b32 s12, s41 +; GFX9-NEXT: s_mov_b32 s13, s40 +; GFX9-NEXT: s_mov_b32 s14, s33 +; GFX9-NEXT: v_mov_b32_e32 v31, v42 +; GFX9-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-NEXT: s_movk_i32 s32, 0x800 +; GFX9-NEXT: v_mov_b32_e32 v43, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-NEXT: v_mov_b32_e32 v41, v1 +; GFX9-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX9-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-NEXT: s_mov_b64 s[44:45], 0 +; GFX9-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX9-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-NEXT: s_waitcnt vmcnt(0) +; GFX9-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX9-NEXT: s_add_u32 s8, s36, 44 +; GFX9-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-NEXT: s_getpc_b64 s[0:1] +; GFX9-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX9-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX9-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX9-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX9-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-NEXT: s_mov_b32 s12, s41 +; GFX9-NEXT: s_mov_b32 s13, s40 +; GFX9-NEXT: s_mov_b32 s14, s33 +; GFX9-NEXT: v_mov_b32_e32 v31, v42 +; GFX9-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-NEXT: v_mov_b32_e32 v2, s42 +; GFX9-NEXT: v_mov_b32_e32 v3, s43 +; GFX9-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX9-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX9-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX9-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX9-NEXT: s_cbranch_execnz .LBB17_1 +; GFX9-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-NEXT: s_endpgm +; +; GFX1064-LABEL: global_atomic_fsub_double_uni_address_div_value_defalut_scope_strictfp: +; GFX1064: ; %bb.0: +; GFX1064-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1064-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1064-NEXT: s_mov_b32 s50, -1 +; GFX1064-NEXT: s_mov_b32 s51, 0x31e16000 +; GFX1064-NEXT: s_add_u32 s48, s48, s9 +; GFX1064-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1064-NEXT: s_addc_u32 s49, s49, 0 +; GFX1064-NEXT: s_mov_b32 s33, s8 +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1064-NEXT: s_mov_b32 s40, s7 +; GFX1064-NEXT: s_mov_b32 s41, s6 +; GFX1064-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1064-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1064-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX1064-NEXT: s_mov_b32 s12, s41 +; GFX1064-NEXT: s_mov_b32 s13, s40 +; GFX1064-NEXT: s_mov_b32 s14, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-NEXT: v_mov_b32_e32 v31, v42 +; GFX1064-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-NEXT: v_mov_b32_e32 v43, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-NEXT: v_mov_b32_e32 v41, v1 +; GFX1064-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX1064-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-NEXT: s_mov_b64 s[44:45], 0 +; GFX1064-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX1064-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-NEXT: s_waitcnt vmcnt(0) +; GFX1064-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX1064-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-NEXT: s_getpc_b64 s[0:1] +; GFX1064-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX1064-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX1064-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-NEXT: v_mov_b32_e32 v31, v42 +; GFX1064-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-NEXT: v_mov_b32_e32 v2, s42 +; GFX1064-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-NEXT: s_mov_b32 s12, s41 +; GFX1064-NEXT: s_mov_b32 s13, s40 +; GFX1064-NEXT: s_mov_b32 s14, s33 +; GFX1064-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX1064-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX1064-NEXT: v_mov_b32_e32 v3, s43 +; GFX1064-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-NEXT: s_clause 0x1 +; GFX1064-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX1064-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX1064-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1064-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX1064-NEXT: s_cbranch_execnz .LBB17_1 +; GFX1064-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-NEXT: s_endpgm +; +; GFX1032-LABEL: global_atomic_fsub_double_uni_address_div_value_defalut_scope_strictfp: +; GFX1032: ; %bb.0: +; GFX1032-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1032-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1032-NEXT: s_mov_b32 s50, -1 +; GFX1032-NEXT: s_mov_b32 s51, 0x31c16000 +; GFX1032-NEXT: s_add_u32 s48, s48, s9 +; GFX1032-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1032-NEXT: s_addc_u32 s49, s49, 0 +; GFX1032-NEXT: s_mov_b32 s33, s8 +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1032-NEXT: s_mov_b32 s40, s7 +; GFX1032-NEXT: s_mov_b32 s41, s6 +; GFX1032-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1032-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1032-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX1032-NEXT: s_mov_b32 s12, s41 +; GFX1032-NEXT: s_mov_b32 s13, s40 +; GFX1032-NEXT: s_mov_b32 s14, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-NEXT: v_mov_b32_e32 v31, v42 +; GFX1032-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-NEXT: v_mov_b32_e32 v43, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-NEXT: v_mov_b32_e32 v41, v1 +; GFX1032-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX1032-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-NEXT: s_mov_b32 s44, 0 +; GFX1032-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX1032-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-NEXT: s_waitcnt vmcnt(0) +; GFX1032-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX1032-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-NEXT: s_getpc_b64 s[0:1] +; GFX1032-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX1032-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX1032-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-NEXT: v_mov_b32_e32 v31, v42 +; GFX1032-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-NEXT: v_mov_b32_e32 v2, s42 +; GFX1032-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-NEXT: s_mov_b32 s12, s41 +; GFX1032-NEXT: s_mov_b32 s13, s40 +; GFX1032-NEXT: s_mov_b32 s14, s33 +; GFX1032-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX1032-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX1032-NEXT: v_mov_b32_e32 v3, s43 +; GFX1032-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-NEXT: s_clause 0x1 +; GFX1032-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX1032-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX1032-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1032-NEXT: s_andn2_b32 exec_lo, exec_lo, s44 +; GFX1032-NEXT: s_cbranch_execnz .LBB17_1 +; GFX1032-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-NEXT: s_endpgm +; +; GFX1164-LABEL: global_atomic_fsub_double_uni_address_div_value_defalut_scope_strictfp: +; GFX1164: ; %bb.0: +; GFX1164-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1164-NEXT: s_mov_b32 s33, s8 +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1164-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1164-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-NEXT: s_mov_b32 s12, s6 +; GFX1164-NEXT: s_mov_b32 s13, s7 +; GFX1164-NEXT: s_mov_b32 s14, s33 +; GFX1164-NEXT: s_mov_b32 s32, 32 +; GFX1164-NEXT: v_mov_b32_e32 v42, v0 +; GFX1164-NEXT: s_mov_b32 s40, s7 +; GFX1164-NEXT: s_mov_b32 s41, s6 +; GFX1164-NEXT: v_mov_b32_e32 v43, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: v_mov_b32_e32 v41, v1 +; GFX1164-NEXT: global_load_b64 v[1:2], v43, s[42:43] +; GFX1164-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-NEXT: s_mov_b64 s[44:45], 0 +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-NEXT: .p2align 6 +; GFX1164-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX1164-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-NEXT: s_waitcnt vmcnt(0) +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX1164-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-NEXT: s_getpc_b64 s[0:1] +; GFX1164-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-NEXT: v_mov_b32_e32 v31, v42 +; GFX1164-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-NEXT: s_mov_b32 s12, s41 +; GFX1164-NEXT: s_mov_b32 s13, s40 +; GFX1164-NEXT: s_mov_b32 s14, s33 +; GFX1164-NEXT: s_clause 0x1 +; GFX1164-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-NEXT: v_mov_b32_e32 v2, s42 +; GFX1164-NEXT: v_mov_b32_e32 v3, s43 +; GFX1164-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1164-NEXT: s_and_not1_b64 exec, exec, s[44:45] +; GFX1164-NEXT: s_cbranch_execnz .LBB17_1 +; GFX1164-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-NEXT: s_endpgm +; +; GFX1132-LABEL: global_atomic_fsub_double_uni_address_div_value_defalut_scope_strictfp: +; GFX1132: ; %bb.0: +; GFX1132-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1132-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1132-NEXT: v_mov_b32_e32 v31, v0 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1132-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1132-NEXT: s_mov_b32 s40, s14 +; GFX1132-NEXT: s_mov_b32 s41, s13 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-NEXT: s_mov_b32 s12, s13 +; GFX1132-NEXT: s_mov_b32 s13, s14 +; GFX1132-NEXT: s_mov_b32 s14, s15 +; GFX1132-NEXT: s_mov_b32 s32, 32 +; GFX1132-NEXT: s_mov_b32 s33, s15 +; GFX1132-NEXT: v_dual_mov_b32 v42, v0 :: v_dual_mov_b32 v43, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v41, v1 +; GFX1132-NEXT: global_load_b64 v[1:2], v43, s[42:43] +; GFX1132-NEXT: s_mov_b32 s44, 0 +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-NEXT: .p2align 6 +; GFX1132-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX1132-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-NEXT: s_waitcnt vmcnt(0) +; GFX1132-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX1132-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-NEXT: s_getpc_b64 s[0:1] +; GFX1132-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-NEXT: v_dual_mov_b32 v31, v42 :: v_dual_mov_b32 v0, 8 +; GFX1132-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-NEXT: s_mov_b32 s12, s41 +; GFX1132-NEXT: s_mov_b32 s13, s40 +; GFX1132-NEXT: s_mov_b32 s14, s33 +; GFX1132-NEXT: s_clause 0x1 +; GFX1132-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s42 +; GFX1132-NEXT: v_dual_mov_b32 v3, s43 :: v_dual_mov_b32 v4, 0 +; GFX1132-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1132-NEXT: s_and_not1_b32 exec_lo, exec_lo, s44 +; GFX1132-NEXT: s_cbranch_execnz .LBB17_1 +; GFX1132-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-NEXT: s_endpgm +; +; GFX9-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_defalut_scope_strictfp: +; GFX9-DPP: ; %bb.0: +; GFX9-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX9-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX9-DPP-NEXT: s_mov_b32 s50, -1 +; GFX9-DPP-NEXT: s_mov_b32 s51, 0xe00000 +; GFX9-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX9-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[36:37], s[2:3] +; GFX9-DPP-NEXT: s_mov_b32 s33, s8 +; GFX9-DPP-NEXT: s_add_u32 s8, s36, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_mov_b32 s40, s7 +; GFX9-DPP-NEXT: s_mov_b32 s41, s6 +; GFX9-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX9-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX9-DPP-NEXT: s_mov_b64 s[34:35], s[4:5] +; GFX9-DPP-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-DPP-NEXT: s_mov_b32 s12, s41 +; GFX9-DPP-NEXT: s_mov_b32 s13, s40 +; GFX9-DPP-NEXT: s_mov_b32 s14, s33 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX9-DPP-NEXT: v_mov_b32_e32 v43, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-DPP-NEXT: v_mov_b32_e32 v41, v1 +; GFX9-DPP-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX9-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX9-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX9-DPP-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX9-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX9-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX9-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX9-DPP-NEXT: s_add_u32 s8, s36, 44 +; GFX9-DPP-NEXT: s_addc_u32 s9, s37, 0 +; GFX9-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX9-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX9-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX9-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX9-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX9-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX9-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX9-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX9-DPP-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX9-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX9-DPP-NEXT: s_mov_b64 s[10:11], s[34:35] +; GFX9-DPP-NEXT: s_mov_b32 s12, s41 +; GFX9-DPP-NEXT: s_mov_b32 s13, s40 +; GFX9-DPP-NEXT: s_mov_b32 s14, s33 +; GFX9-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX9-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX9-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX9-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX9-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX9-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX9-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX9-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX9-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX9-DPP-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX9-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX9-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX9-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX9-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX9-DPP-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX9-DPP-NEXT: s_cbranch_execnz .LBB17_1 +; GFX9-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX9-DPP-NEXT: s_endpgm +; +; GFX1064-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_defalut_scope_strictfp: +; GFX1064-DPP: ; %bb.0: +; GFX1064-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1064-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1064-DPP-NEXT: s_mov_b32 s50, -1 +; GFX1064-DPP-NEXT: s_mov_b32 s51, 0x31e16000 +; GFX1064-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX1064-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1064-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX1064-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1064-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1064-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1064-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-DPP-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX1064-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1064-DPP-NEXT: s_movk_i32 s32, 0x800 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v43, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v41, v1 +; GFX1064-DPP-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX1064-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1064-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX1064-DPP-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX1064-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1064-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1064-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX1064-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1064-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1064-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1064-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1064-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1064-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX1064-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX1064-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1064-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1064-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1064-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1064-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1064-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1064-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1064-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1064-DPP-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX1064-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1064-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1064-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1064-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1064-DPP-NEXT: s_clause 0x1 +; GFX1064-DPP-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX1064-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX1064-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1064-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1064-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1064-DPP-NEXT: s_andn2_b64 exec, exec, s[44:45] +; GFX1064-DPP-NEXT: s_cbranch_execnz .LBB17_1 +; GFX1064-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1064-DPP-NEXT: s_endpgm +; +; GFX1032-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_defalut_scope_strictfp: +; GFX1032-DPP: ; %bb.0: +; GFX1032-DPP-NEXT: s_mov_b32 s48, SCRATCH_RSRC_DWORD0 +; GFX1032-DPP-NEXT: s_mov_b32 s49, SCRATCH_RSRC_DWORD1 +; GFX1032-DPP-NEXT: s_mov_b32 s50, -1 +; GFX1032-DPP-NEXT: s_mov_b32 s51, 0x31c16000 +; GFX1032-DPP-NEXT: s_add_u32 s48, s48, s9 +; GFX1032-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1032-DPP-NEXT: s_addc_u32 s49, s49, 0 +; GFX1032-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1032-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[42:43], s[2:3], 0x24 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v2, 20, v2 +; GFX1032-DPP-NEXT: v_lshlrev_b32_e32 v1, 10, v1 +; GFX1032-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-DPP-NEXT: v_or3_b32 v42, v0, v1, v2 +; GFX1032-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1032-DPP-NEXT: s_movk_i32 s32, 0x400 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v43, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v41, v1 +; GFX1032-DPP-NEXT: global_load_dwordx2 v[1:2], v43, s[42:43] +; GFX1032-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1032-DPP-NEXT: s_mov_b32 s44, 0 +; GFX1032-DPP-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX1032-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1032-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1032-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX1032-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1032-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1032-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1032-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1032-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1032-DPP-NEXT: buffer_store_dword v2, off, s[48:51], 0 offset:4 +; GFX1032-DPP-NEXT: buffer_store_dword v1, off, s[48:51], 0 +; GFX1032-DPP-NEXT: s_load_dwordx2 s[6:7], s[0:1], 0x0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1032-DPP-NEXT: s_mov_b64 s[0:1], s[48:49] +; GFX1032-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1032-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1032-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1032-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1032-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1032-DPP-NEXT: s_mov_b64 s[2:3], s[50:51] +; GFX1032-DPP-NEXT: buffer_store_dword v4, off, s[48:51], 0 offset:12 +; GFX1032-DPP-NEXT: buffer_store_dword v3, off, s[48:51], 0 offset:8 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1032-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1032-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1032-DPP-NEXT: s_swappc_b64 s[30:31], s[6:7] +; GFX1032-DPP-NEXT: s_clause 0x1 +; GFX1032-DPP-NEXT: buffer_load_dword v1, off, s[48:51], 0 +; GFX1032-DPP-NEXT: buffer_load_dword v2, off, s[48:51], 0 offset:4 +; GFX1032-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1032-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1032-DPP-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1032-DPP-NEXT: s_andn2_b32 exec_lo, exec_lo, s44 +; GFX1032-DPP-NEXT: s_cbranch_execnz .LBB17_1 +; GFX1032-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1032-DPP-NEXT: s_endpgm +; +; GFX1164-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_defalut_scope_strictfp: +; GFX1164-DPP: ; %bb.0: +; GFX1164-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1164-DPP-NEXT: s_mov_b32 s33, s8 +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s6 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1164-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v42, v0 +; GFX1164-DPP-NEXT: s_mov_b32 s40, s7 +; GFX1164-DPP-NEXT: s_mov_b32 s41, s6 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v43, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v41, v1 +; GFX1164-DPP-NEXT: global_load_b64 v[1:2], v43, s[42:43] +; GFX1164-DPP-NEXT: v_mov_b32_e32 v40, v0 +; GFX1164-DPP-NEXT: s_mov_b64 s[44:45], 0 +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1164-DPP-NEXT: .p2align 6 +; GFX1164-DPP-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX1164-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1164-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX1164-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX1164-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1164-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1164-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1164-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1164-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v31, v42 +; GFX1164-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v0, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v5, 8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v6, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1164-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1164-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1164-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1164-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1164-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1164-DPP-NEXT: s_clause 0x1 +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1164-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v1, 0 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v2, s42 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v3, s43 +; GFX1164-DPP-NEXT: v_mov_b32_e32 v4, 0 +; GFX1164-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1164-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1164-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1164-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1164-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1164-DPP-NEXT: v_cmp_eq_u32_e32 vcc, 1, v0 +; GFX1164-DPP-NEXT: s_or_b64 s[44:45], vcc, s[44:45] +; GFX1164-DPP-NEXT: s_and_not1_b64 exec, exec, s[44:45] +; GFX1164-DPP-NEXT: s_cbranch_execnz .LBB17_1 +; GFX1164-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1164-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1164-DPP-NEXT: s_endpgm +; +; GFX1132-DPP-LABEL: global_atomic_fsub_double_uni_address_div_value_defalut_scope_strictfp: +; GFX1132-DPP: ; %bb.0: +; GFX1132-DPP-NEXT: s_mov_b64 s[34:35], s[2:3] +; GFX1132-DPP-NEXT: s_mov_b64 s[38:39], s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, div.float.value@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, div.float.value@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v31, v0 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: s_load_b64 s[42:43], s[2:3], 0x24 +; GFX1132-DPP-NEXT: s_mov_b64 s[36:37], s[4:5] +; GFX1132-DPP-NEXT: s_mov_b32 s40, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s41, s13 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-DPP-NEXT: s_mov_b32 s12, s13 +; GFX1132-DPP-NEXT: s_mov_b32 s13, s14 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s15 +; GFX1132-DPP-NEXT: s_mov_b32 s32, 32 +; GFX1132-DPP-NEXT: s_mov_b32 s33, s15 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v42, v0 :: v_dual_mov_b32 v43, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: v_dual_mov_b32 v40, v0 :: v_dual_mov_b32 v41, v1 +; GFX1132-DPP-NEXT: global_load_b64 v[1:2], v43, s[42:43] +; GFX1132-DPP-NEXT: s_mov_b32 s44, 0 +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x1 +; GFX1132-DPP-NEXT: .p2align 6 +; GFX1132-DPP-NEXT: .LBB17_1: ; %atomicrmw.start +; GFX1132-DPP-NEXT: ; =>This Inner Loop Header: Depth=1 +; GFX1132-DPP-NEXT: s_waitcnt vmcnt(0) +; GFX1132-DPP-NEXT: v_add_f64 v[3:4], v[1:2], -v[40:41] +; GFX1132-DPP-NEXT: s_add_u32 s8, s34, 44 +; GFX1132-DPP-NEXT: s_addc_u32 s9, s35, 0 +; GFX1132-DPP-NEXT: s_getpc_b64 s[0:1] +; GFX1132-DPP-NEXT: s_add_u32 s0, s0, __atomic_compare_exchange@gotpcrel32@lo+4 +; GFX1132-DPP-NEXT: s_addc_u32 s1, s1, __atomic_compare_exchange@gotpcrel32@hi+12 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v31, v42 :: v_dual_mov_b32 v0, 8 +; GFX1132-DPP-NEXT: s_load_b64 s[0:1], s[0:1], 0x0 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v5, 8 :: v_dual_mov_b32 v6, 0 +; GFX1132-DPP-NEXT: v_mov_b32_e32 v7, 0 +; GFX1132-DPP-NEXT: s_mov_b64 s[4:5], s[38:39] +; GFX1132-DPP-NEXT: s_mov_b64 s[10:11], s[36:37] +; GFX1132-DPP-NEXT: s_mov_b32 s12, s41 +; GFX1132-DPP-NEXT: s_mov_b32 s13, s40 +; GFX1132-DPP-NEXT: s_mov_b32 s14, s33 +; GFX1132-DPP-NEXT: s_clause 0x1 +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[1:2], off +; GFX1132-DPP-NEXT: scratch_store_b64 off, v[3:4], off offset:8 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v1, 0 :: v_dual_mov_b32 v2, s42 +; GFX1132-DPP-NEXT: v_dual_mov_b32 v3, s43 :: v_dual_mov_b32 v4, 0 +; GFX1132-DPP-NEXT: s_waitcnt lgkmcnt(0) +; GFX1132-DPP-NEXT: s_swappc_b64 s[30:31], s[0:1] +; GFX1132-DPP-NEXT: scratch_load_b64 v[1:2], off, off +; GFX1132-DPP-NEXT: v_and_b32_e32 v0, 1, v0 +; GFX1132-DPP-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1) +; GFX1132-DPP-NEXT: v_cmp_eq_u32_e32 vcc_lo, 1, v0 +; GFX1132-DPP-NEXT: s_or_b32 s44, vcc_lo, s44 +; GFX1132-DPP-NEXT: s_and_not1_b32 exec_lo, exec_lo, s44 +; GFX1132-DPP-NEXT: s_cbranch_execnz .LBB17_1 +; GFX1132-DPP-NEXT: ; %bb.2: ; %atomicrmw.end +; GFX1132-DPP-NEXT: s_set_inst_prefetch_distance 0x2 +; GFX1132-DPP-NEXT: s_endpgm + %divValue = call double @div.float.value() strictfp + %result = atomicrmw fsub ptr addrspace(1) %ptr, double %divValue monotonic, align 4 + ret void +} + attributes #0 = { "denormal-fp-math-f32"="preserve-sign,preserve-sign" "amdgpu-unsafe-fp-atomics"="true" } attributes #1 = { strictfp "denormal-fp-math-f32"="preserve-sign,preserve-sign" "amdgpu-unsafe-fp-atomics"="true" } attributes #2 = { strictfp} diff --git a/llvm/test/CodeGen/AMDGPU/greedy-alloc-fail-sgpr1024-spill.mir b/llvm/test/CodeGen/AMDGPU/greedy-alloc-fail-sgpr1024-spill.mir index bdd89a9077900efeece065721e3cddf5be6827c5..dde84af57ed25356a45621d3ad018f5012707443 100644 --- a/llvm/test/CodeGen/AMDGPU/greedy-alloc-fail-sgpr1024-spill.mir +++ b/llvm/test/CodeGen/AMDGPU/greedy-alloc-fail-sgpr1024-spill.mir @@ -13,6 +13,7 @@ name: greedy_fail_alloc_sgpr1024_spill tracksRegLiveness: true frameInfo: + adjustsStack: true hasCalls: true machineFunctionInfo: explicitKernArgSize: 16 diff --git a/llvm/test/CodeGen/AMDGPU/implicitarg-offset-attributes.ll b/llvm/test/CodeGen/AMDGPU/implicitarg-offset-attributes.ll index a5792bf29ddca1f56304cf61005bf42fa18ee611..4c21f87297455978947688e4fc63ddb61949f270 100644 --- a/llvm/test/CodeGen/AMDGPU/implicitarg-offset-attributes.ll +++ b/llvm/test/CodeGen/AMDGPU/implicitarg-offset-attributes.ll @@ -258,25 +258,25 @@ attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memo ;. ; V4: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } -; V4: attributes #[[ATTR1]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-multigrid-sync-arg" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } -; V4: attributes #[[ATTR2]] = { "amdgpu-no-completion-action" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } -; V4: attributes #[[ATTR3]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } -; V4: attributes #[[ATTR4]] = { "amdgpu-no-default-queue" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } -; V4: attributes #[[ATTR5]] = { "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } +; V4: attributes #[[ATTR1]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-multigrid-sync-arg" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; V4: attributes #[[ATTR2]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } +; V4: attributes #[[ATTR3]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } +; V4: attributes #[[ATTR4]] = { "amdgpu-no-agpr" "amdgpu-no-default-queue" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } +; V4: attributes #[[ATTR5]] = { "amdgpu-no-agpr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } ;. ; V5: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } -; V5: attributes #[[ATTR1]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } -; V5: attributes #[[ATTR2]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } -; V5: attributes #[[ATTR3]] = { "amdgpu-no-completion-action" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } -; V5: attributes #[[ATTR4]] = { "amdgpu-no-default-queue" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } -; V5: attributes #[[ATTR5]] = { "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } +; V5: attributes #[[ATTR1]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; V5: attributes #[[ATTR2]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } +; V5: attributes #[[ATTR3]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } +; V5: attributes #[[ATTR4]] = { "amdgpu-no-agpr" "amdgpu-no-default-queue" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } +; V5: attributes #[[ATTR5]] = { "amdgpu-no-agpr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } ;. ; V6: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } -; V6: attributes #[[ATTR1]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } -; V6: attributes #[[ATTR2]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } -; V6: attributes #[[ATTR3]] = { "amdgpu-no-completion-action" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } -; V6: attributes #[[ATTR4]] = { "amdgpu-no-default-queue" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } -; V6: attributes #[[ATTR5]] = { "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } +; V6: attributes #[[ATTR1]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; V6: attributes #[[ATTR2]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } +; V6: attributes #[[ATTR3]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } +; V6: attributes #[[ATTR4]] = { "amdgpu-no-agpr" "amdgpu-no-default-queue" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } +; V6: attributes #[[ATTR5]] = { "amdgpu-no-agpr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-multigrid-sync-arg" "uniform-work-group-size"="false" } ;. ; V4: [[META0:![0-9]+]] = !{i32 1, !"amdhsa_code_object_version", i32 400} ;. diff --git a/llvm/test/CodeGen/AMDGPU/isel-amdgpu-cs-chain-cc.ll b/llvm/test/CodeGen/AMDGPU/isel-amdgpu-cs-chain-cc.ll index e015095a4884a527a9fb179efd02a5e996218651..ab160ffc10ed07327f281b5d92020bf46748d2ac 100644 --- a/llvm/test/CodeGen/AMDGPU/isel-amdgpu-cs-chain-cc.ll +++ b/llvm/test/CodeGen/AMDGPU/isel-amdgpu-cs-chain-cc.ll @@ -92,7 +92,6 @@ define amdgpu_cs_chain void @amdgpu_cs_chain_cc(<4 x i32> inreg %a, <4 x i32> %b ; DAGISEL-GFX11-NEXT: $vgpr5 = COPY [[COPY2]] ; DAGISEL-GFX11-NEXT: $vgpr6 = COPY [[COPY1]] ; DAGISEL-GFX11-NEXT: $vgpr7 = COPY [[COPY]] - ; DAGISEL-GFX11-NEXT: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF ; DAGISEL-GFX11-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[S_LOAD_DWORDX2_IMM]], @use, csr_amdgpu_si_gfx, implicit $vgpr0, implicit $vgpr1, implicit $vgpr2, implicit $vgpr3, implicit $vgpr4, implicit $vgpr5, implicit $vgpr6, implicit $vgpr7 ; DAGISEL-GFX11-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 ; DAGISEL-GFX11-NEXT: S_ENDPGM 0 @@ -122,7 +121,6 @@ define amdgpu_cs_chain void @amdgpu_cs_chain_cc(<4 x i32> inreg %a, <4 x i32> %b ; DAGISEL-GFX10-NEXT: $vgpr5 = COPY [[COPY2]] ; DAGISEL-GFX10-NEXT: $vgpr6 = COPY [[COPY1]] ; DAGISEL-GFX10-NEXT: $vgpr7 = COPY [[COPY]] - ; DAGISEL-GFX10-NEXT: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF ; DAGISEL-GFX10-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[S_LOAD_DWORDX2_IMM]], @use, csr_amdgpu_si_gfx, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $vgpr0, implicit $vgpr1, implicit $vgpr2, implicit $vgpr3, implicit $vgpr4, implicit $vgpr5, implicit $vgpr6, implicit $vgpr7 ; DAGISEL-GFX10-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 ; DAGISEL-GFX10-NEXT: S_ENDPGM 0 @@ -234,7 +232,6 @@ define amdgpu_cs_chain void @amdgpu_cs_chain_cc_ptr(ptr inreg %a, ptr %b, ptr ad ; DAGISEL-GFX11-NEXT: $vgpr9 = COPY [[COPY2]] ; DAGISEL-GFX11-NEXT: $vgpr10 = COPY [[COPY1]] ; DAGISEL-GFX11-NEXT: $vgpr11 = COPY [[COPY]] - ; DAGISEL-GFX11-NEXT: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF ; DAGISEL-GFX11-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[S_LOAD_DWORDX2_IMM]], @use, csr_amdgpu_si_gfx, implicit $vgpr0, implicit $vgpr1, implicit $vgpr2, implicit $vgpr3, implicit $vgpr4, implicit $vgpr5, implicit $vgpr6, implicit $vgpr7, implicit $vgpr8, implicit $vgpr9, implicit $vgpr10, implicit $vgpr11 ; DAGISEL-GFX11-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 ; DAGISEL-GFX11-NEXT: S_ENDPGM 0 @@ -272,7 +269,6 @@ define amdgpu_cs_chain void @amdgpu_cs_chain_cc_ptr(ptr inreg %a, ptr %b, ptr ad ; DAGISEL-GFX10-NEXT: $vgpr9 = COPY [[COPY2]] ; DAGISEL-GFX10-NEXT: $vgpr10 = COPY [[COPY1]] ; DAGISEL-GFX10-NEXT: $vgpr11 = COPY [[COPY]] - ; DAGISEL-GFX10-NEXT: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF ; DAGISEL-GFX10-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[S_LOAD_DWORDX2_IMM]], @use, csr_amdgpu_si_gfx, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $vgpr0, implicit $vgpr1, implicit $vgpr2, implicit $vgpr3, implicit $vgpr4, implicit $vgpr5, implicit $vgpr6, implicit $vgpr7, implicit $vgpr8, implicit $vgpr9, implicit $vgpr10, implicit $vgpr11 ; DAGISEL-GFX10-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 ; DAGISEL-GFX10-NEXT: S_ENDPGM 0 @@ -404,7 +400,6 @@ define amdgpu_cs_chain void @amdgpu_cs_chain_cc_struct( {ptr, i32, <4 x i32>} in ; DAGISEL-GFX11-NEXT: $vgpr11 = COPY [[COPY2]] ; DAGISEL-GFX11-NEXT: $vgpr12 = COPY [[COPY1]] ; DAGISEL-GFX11-NEXT: $vgpr13 = COPY [[COPY]] - ; DAGISEL-GFX11-NEXT: [[DEF2:%[0-9]+]]:sreg_64 = IMPLICIT_DEF ; DAGISEL-GFX11-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[S_LOAD_DWORDX2_IMM]], @use, csr_amdgpu_si_gfx, implicit $vgpr0, implicit $vgpr1, implicit $vgpr2, implicit $vgpr3, implicit $vgpr4, implicit $vgpr5, implicit $vgpr6, implicit $vgpr7, implicit $vgpr8, implicit $vgpr9, implicit $vgpr10, implicit $vgpr11, implicit $vgpr12, implicit $vgpr13 ; DAGISEL-GFX11-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 ; DAGISEL-GFX11-NEXT: S_ENDPGM 0 @@ -454,7 +449,6 @@ define amdgpu_cs_chain void @amdgpu_cs_chain_cc_struct( {ptr, i32, <4 x i32>} in ; DAGISEL-GFX10-NEXT: $vgpr11 = COPY [[COPY2]] ; DAGISEL-GFX10-NEXT: $vgpr12 = COPY [[COPY1]] ; DAGISEL-GFX10-NEXT: $vgpr13 = COPY [[COPY]] - ; DAGISEL-GFX10-NEXT: [[DEF2:%[0-9]+]]:sreg_64 = IMPLICIT_DEF ; DAGISEL-GFX10-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[S_LOAD_DWORDX2_IMM]], @use, csr_amdgpu_si_gfx, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $vgpr0, implicit $vgpr1, implicit $vgpr2, implicit $vgpr3, implicit $vgpr4, implicit $vgpr5, implicit $vgpr6, implicit $vgpr7, implicit $vgpr8, implicit $vgpr9, implicit $vgpr10, implicit $vgpr11, implicit $vgpr12, implicit $vgpr13 ; DAGISEL-GFX10-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 ; DAGISEL-GFX10-NEXT: S_ENDPGM 0 @@ -506,7 +500,6 @@ define amdgpu_cs_chain void @amdgpu_cs_chain_cc_float(float inreg %a, float %b) ; DAGISEL-GFX11-NEXT: [[S_LOAD_DWORDX2_IMM:%[0-9]+]]:sreg_64_xexec = S_LOAD_DWORDX2_IMM killed [[SI_PC_ADD_REL_OFFSET]], 0, 0 :: (dereferenceable invariant load (s64) from got, addrspace 4) ; DAGISEL-GFX11-NEXT: $vgpr0 = COPY [[COPY1]] ; DAGISEL-GFX11-NEXT: $vgpr1 = COPY [[COPY]] - ; DAGISEL-GFX11-NEXT: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF ; DAGISEL-GFX11-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[S_LOAD_DWORDX2_IMM]], @use, csr_amdgpu_si_gfx, implicit $vgpr0, implicit $vgpr1 ; DAGISEL-GFX11-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 ; DAGISEL-GFX11-NEXT: S_ENDPGM 0 @@ -524,7 +517,6 @@ define amdgpu_cs_chain void @amdgpu_cs_chain_cc_float(float inreg %a, float %b) ; DAGISEL-GFX10-NEXT: $sgpr0_sgpr1_sgpr2_sgpr3 = COPY [[COPY2]] ; DAGISEL-GFX10-NEXT: $vgpr0 = COPY [[COPY1]] ; DAGISEL-GFX10-NEXT: $vgpr1 = COPY [[COPY]] - ; DAGISEL-GFX10-NEXT: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF ; DAGISEL-GFX10-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[S_LOAD_DWORDX2_IMM]], @use, csr_amdgpu_si_gfx, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $vgpr0, implicit $vgpr1 ; DAGISEL-GFX10-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 ; DAGISEL-GFX10-NEXT: S_ENDPGM 0 @@ -576,7 +568,6 @@ define amdgpu_cs_chain void @amdgpu_cs_chain_cc_half(half inreg %a, half %b) { ; DAGISEL-GFX11-NEXT: [[S_LOAD_DWORDX2_IMM:%[0-9]+]]:sreg_64_xexec = S_LOAD_DWORDX2_IMM killed [[SI_PC_ADD_REL_OFFSET]], 0, 0 :: (dereferenceable invariant load (s64) from got, addrspace 4) ; DAGISEL-GFX11-NEXT: $vgpr0 = COPY [[COPY1]] ; DAGISEL-GFX11-NEXT: $vgpr1 = COPY [[COPY]] - ; DAGISEL-GFX11-NEXT: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF ; DAGISEL-GFX11-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[S_LOAD_DWORDX2_IMM]], @use, csr_amdgpu_si_gfx, implicit $vgpr0, implicit $vgpr1 ; DAGISEL-GFX11-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 ; DAGISEL-GFX11-NEXT: S_ENDPGM 0 @@ -594,7 +585,6 @@ define amdgpu_cs_chain void @amdgpu_cs_chain_cc_half(half inreg %a, half %b) { ; DAGISEL-GFX10-NEXT: $sgpr0_sgpr1_sgpr2_sgpr3 = COPY [[COPY2]] ; DAGISEL-GFX10-NEXT: $vgpr0 = COPY [[COPY1]] ; DAGISEL-GFX10-NEXT: $vgpr1 = COPY [[COPY]] - ; DAGISEL-GFX10-NEXT: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF ; DAGISEL-GFX10-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[S_LOAD_DWORDX2_IMM]], @use, csr_amdgpu_si_gfx, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $vgpr0, implicit $vgpr1 ; DAGISEL-GFX10-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 ; DAGISEL-GFX10-NEXT: S_ENDPGM 0 @@ -646,7 +636,6 @@ define amdgpu_cs_chain void @amdgpu_cs_chain_cc_bfloat(bfloat inreg %a, bfloat % ; DAGISEL-GFX11-NEXT: [[S_LOAD_DWORDX2_IMM:%[0-9]+]]:sreg_64_xexec = S_LOAD_DWORDX2_IMM killed [[SI_PC_ADD_REL_OFFSET]], 0, 0 :: (dereferenceable invariant load (s64) from got, addrspace 4) ; DAGISEL-GFX11-NEXT: $vgpr0 = COPY [[COPY1]] ; DAGISEL-GFX11-NEXT: $vgpr1 = COPY [[COPY]] - ; DAGISEL-GFX11-NEXT: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF ; DAGISEL-GFX11-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[S_LOAD_DWORDX2_IMM]], @use, csr_amdgpu_si_gfx, implicit $vgpr0, implicit $vgpr1 ; DAGISEL-GFX11-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 ; DAGISEL-GFX11-NEXT: S_ENDPGM 0 @@ -664,7 +653,6 @@ define amdgpu_cs_chain void @amdgpu_cs_chain_cc_bfloat(bfloat inreg %a, bfloat % ; DAGISEL-GFX10-NEXT: $sgpr0_sgpr1_sgpr2_sgpr3 = COPY [[COPY2]] ; DAGISEL-GFX10-NEXT: $vgpr0 = COPY [[COPY1]] ; DAGISEL-GFX10-NEXT: $vgpr1 = COPY [[COPY]] - ; DAGISEL-GFX10-NEXT: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF ; DAGISEL-GFX10-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[S_LOAD_DWORDX2_IMM]], @use, csr_amdgpu_si_gfx, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $vgpr0, implicit $vgpr1 ; DAGISEL-GFX10-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 ; DAGISEL-GFX10-NEXT: S_ENDPGM 0 @@ -716,7 +704,6 @@ define amdgpu_cs_chain void @amdgpu_cs_chain_cc_i16(i16 inreg %a, i16 %b) { ; DAGISEL-GFX11-NEXT: [[S_LOAD_DWORDX2_IMM:%[0-9]+]]:sreg_64_xexec = S_LOAD_DWORDX2_IMM killed [[SI_PC_ADD_REL_OFFSET]], 0, 0 :: (dereferenceable invariant load (s64) from got, addrspace 4) ; DAGISEL-GFX11-NEXT: $vgpr0 = COPY [[COPY1]] ; DAGISEL-GFX11-NEXT: $vgpr1 = COPY [[COPY]] - ; DAGISEL-GFX11-NEXT: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF ; DAGISEL-GFX11-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[S_LOAD_DWORDX2_IMM]], @use, csr_amdgpu_si_gfx, implicit $vgpr0, implicit $vgpr1 ; DAGISEL-GFX11-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 ; DAGISEL-GFX11-NEXT: S_ENDPGM 0 @@ -734,7 +721,6 @@ define amdgpu_cs_chain void @amdgpu_cs_chain_cc_i16(i16 inreg %a, i16 %b) { ; DAGISEL-GFX10-NEXT: $sgpr0_sgpr1_sgpr2_sgpr3 = COPY [[COPY2]] ; DAGISEL-GFX10-NEXT: $vgpr0 = COPY [[COPY1]] ; DAGISEL-GFX10-NEXT: $vgpr1 = COPY [[COPY]] - ; DAGISEL-GFX10-NEXT: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF ; DAGISEL-GFX10-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[S_LOAD_DWORDX2_IMM]], @use, csr_amdgpu_si_gfx, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $vgpr0, implicit $vgpr1 ; DAGISEL-GFX10-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 ; DAGISEL-GFX10-NEXT: S_ENDPGM 0 @@ -870,7 +856,6 @@ define amdgpu_cs_chain void @amdgpu_cs_chain_cc_v16i16(<16 x i16> inreg %a, <16 ; DAGISEL-GFX11-NEXT: $vgpr13 = COPY [[COPY2]] ; DAGISEL-GFX11-NEXT: $vgpr14 = COPY [[COPY1]] ; DAGISEL-GFX11-NEXT: $vgpr15 = COPY [[COPY]] - ; DAGISEL-GFX11-NEXT: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF ; DAGISEL-GFX11-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[S_LOAD_DWORDX2_IMM]], @use, csr_amdgpu_si_gfx, implicit $vgpr0, implicit $vgpr1, implicit $vgpr2, implicit $vgpr3, implicit $vgpr4, implicit $vgpr5, implicit $vgpr6, implicit $vgpr7, implicit $vgpr8, implicit $vgpr9, implicit $vgpr10, implicit $vgpr11, implicit $vgpr12, implicit $vgpr13, implicit $vgpr14, implicit $vgpr15 ; DAGISEL-GFX11-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 ; DAGISEL-GFX11-NEXT: S_ENDPGM 0 @@ -916,7 +901,6 @@ define amdgpu_cs_chain void @amdgpu_cs_chain_cc_v16i16(<16 x i16> inreg %a, <16 ; DAGISEL-GFX10-NEXT: $vgpr13 = COPY [[COPY2]] ; DAGISEL-GFX10-NEXT: $vgpr14 = COPY [[COPY1]] ; DAGISEL-GFX10-NEXT: $vgpr15 = COPY [[COPY]] - ; DAGISEL-GFX10-NEXT: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF ; DAGISEL-GFX10-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[S_LOAD_DWORDX2_IMM]], @use, csr_amdgpu_si_gfx, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $vgpr0, implicit $vgpr1, implicit $vgpr2, implicit $vgpr3, implicit $vgpr4, implicit $vgpr5, implicit $vgpr6, implicit $vgpr7, implicit $vgpr8, implicit $vgpr9, implicit $vgpr10, implicit $vgpr11, implicit $vgpr12, implicit $vgpr13, implicit $vgpr14, implicit $vgpr15 ; DAGISEL-GFX10-NEXT: ADJCALLSTACKDOWN 0, 0, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 ; DAGISEL-GFX10-NEXT: S_ENDPGM 0 @@ -2480,7 +2464,6 @@ define amdgpu_cs_chain void @amdgpu_cs_chain_many_regs(<36 x i32> inreg %a, <128 ; DAGISEL-GFX11-NEXT: $vgpr29 = COPY [[COPY134]] ; DAGISEL-GFX11-NEXT: $vgpr30 = COPY [[COPY133]] ; DAGISEL-GFX11-NEXT: $vgpr31 = COPY [[COPY132]] - ; DAGISEL-GFX11-NEXT: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF ; DAGISEL-GFX11-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[S_LOAD_DWORDX2_IMM]], @use, csr_amdgpu_si_gfx, implicit $vgpr0, implicit $vgpr1, implicit $vgpr2, implicit $vgpr3, implicit $vgpr4, implicit $vgpr5, implicit $vgpr6, implicit $vgpr7, implicit $vgpr8, implicit $vgpr9, implicit $vgpr10, implicit $vgpr11, implicit $vgpr12, implicit $vgpr13, implicit $vgpr14, implicit $vgpr15, implicit $vgpr16, implicit $vgpr17, implicit $vgpr18, implicit $vgpr19, implicit $vgpr20, implicit $vgpr21, implicit $vgpr22, implicit $vgpr23, implicit $vgpr24, implicit $vgpr25, implicit $vgpr26, implicit $vgpr27, implicit $vgpr28, implicit $vgpr29, implicit $vgpr30, implicit $vgpr31 ; DAGISEL-GFX11-NEXT: ADJCALLSTACKDOWN 0, 528, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 ; DAGISEL-GFX11-NEXT: S_ENDPGM 0 @@ -2827,7 +2810,6 @@ define amdgpu_cs_chain void @amdgpu_cs_chain_many_regs(<36 x i32> inreg %a, <128 ; DAGISEL-GFX10-NEXT: $vgpr29 = COPY [[COPY134]] ; DAGISEL-GFX10-NEXT: $vgpr30 = COPY [[COPY133]] ; DAGISEL-GFX10-NEXT: $vgpr31 = COPY [[COPY132]] - ; DAGISEL-GFX10-NEXT: [[DEF:%[0-9]+]]:sreg_64 = IMPLICIT_DEF ; DAGISEL-GFX10-NEXT: $sgpr30_sgpr31 = SI_CALL killed [[S_LOAD_DWORDX2_IMM]], @use, csr_amdgpu_si_gfx, implicit $sgpr0_sgpr1_sgpr2_sgpr3, implicit $vgpr0, implicit $vgpr1, implicit $vgpr2, implicit $vgpr3, implicit $vgpr4, implicit $vgpr5, implicit $vgpr6, implicit $vgpr7, implicit $vgpr8, implicit $vgpr9, implicit $vgpr10, implicit $vgpr11, implicit $vgpr12, implicit $vgpr13, implicit $vgpr14, implicit $vgpr15, implicit $vgpr16, implicit $vgpr17, implicit $vgpr18, implicit $vgpr19, implicit $vgpr20, implicit $vgpr21, implicit $vgpr22, implicit $vgpr23, implicit $vgpr24, implicit $vgpr25, implicit $vgpr26, implicit $vgpr27, implicit $vgpr28, implicit $vgpr29, implicit $vgpr30, implicit $vgpr31 ; DAGISEL-GFX10-NEXT: ADJCALLSTACKDOWN 0, 528, implicit-def dead $scc, implicit-def $sgpr32, implicit $sgpr32 ; DAGISEL-GFX10-NEXT: S_ENDPGM 0 diff --git a/llvm/test/CodeGen/AMDGPU/itofp.i128.ll b/llvm/test/CodeGen/AMDGPU/itofp.i128.ll new file mode 100644 index 0000000000000000000000000000000000000000..bfeb214c5af8f4ab26e3b79103bd463e357c5a7d --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/itofp.i128.ll @@ -0,0 +1,1618 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -global-isel=0 -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 < %s | FileCheck -check-prefixes=GCN,SDAG %s +; RUN: llc -global-isel=1 -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 < %s | FileCheck -check-prefixes=GCN,GISEL %s + +define float @sitofp_i128_to_f32(i128 %x) { +; SDAG-LABEL: sitofp_i128_to_f32: +; SDAG: ; %bb.0: ; %itofp-entry +; SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-NEXT: v_or_b32_e32 v5, v1, v3 +; SDAG-NEXT: v_or_b32_e32 v4, v0, v2 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[4:5] +; SDAG-NEXT: v_mov_b32_e32 v4, 0 +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], vcc +; SDAG-NEXT: s_cbranch_execz .LBB0_14 +; SDAG-NEXT: ; %bb.1: ; %itofp-if-end +; SDAG-NEXT: v_ashrrev_i32_e32 v5, 31, v3 +; SDAG-NEXT: v_xor_b32_e32 v0, v5, v0 +; SDAG-NEXT: v_xor_b32_e32 v1, v5, v1 +; SDAG-NEXT: v_sub_co_u32_e32 v0, vcc, v0, v5 +; SDAG-NEXT: v_xor_b32_e32 v2, v5, v2 +; SDAG-NEXT: v_subb_co_u32_e32 v1, vcc, v1, v5, vcc +; SDAG-NEXT: v_xor_b32_e32 v6, v5, v3 +; SDAG-NEXT: v_subb_co_u32_e32 v4, vcc, v2, v5, vcc +; SDAG-NEXT: v_subb_co_u32_e32 v5, vcc, v6, v5, vcc +; SDAG-NEXT: v_ffbh_u32_e32 v2, v4 +; SDAG-NEXT: v_add_u32_e32 v2, 32, v2 +; SDAG-NEXT: v_ffbh_u32_e32 v6, v5 +; SDAG-NEXT: v_min_u32_e32 v2, v2, v6 +; SDAG-NEXT: v_ffbh_u32_e32 v6, v0 +; SDAG-NEXT: v_add_u32_e32 v6, 32, v6 +; SDAG-NEXT: v_ffbh_u32_e32 v7, v1 +; SDAG-NEXT: v_min_u32_e32 v6, v6, v7 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[4:5] +; SDAG-NEXT: v_add_u32_e32 v6, 64, v6 +; SDAG-NEXT: v_cndmask_b32_e32 v7, v6, v2, vcc +; SDAG-NEXT: v_sub_u32_e32 v6, 0x80, v7 +; SDAG-NEXT: v_sub_u32_e32 v2, 0x7f, v7 +; SDAG-NEXT: v_cmp_gt_i32_e32 vcc, 25, v6 +; SDAG-NEXT: ; implicit-def: $vgpr8 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[4:5], exec, s[4:5] +; SDAG-NEXT: ; %bb.2: ; %itofp-if-else +; SDAG-NEXT: v_add_u32_e32 v4, 0xffffff98, v7 +; SDAG-NEXT: v_lshlrev_b64 v[0:1], v4, v[0:1] +; SDAG-NEXT: v_cmp_gt_u32_e32 vcc, 64, v4 +; SDAG-NEXT: v_cndmask_b32_e32 v8, 0, v0, vcc +; SDAG-NEXT: ; implicit-def: $vgpr6 +; SDAG-NEXT: ; implicit-def: $vgpr0_vgpr1 +; SDAG-NEXT: ; implicit-def: $vgpr7 +; SDAG-NEXT: ; implicit-def: $vgpr4_vgpr5 +; SDAG-NEXT: ; %bb.3: ; %Flow3 +; SDAG-NEXT: s_andn2_saveexec_b64 s[8:9], s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB0_13 +; SDAG-NEXT: ; %bb.4: ; %NodeBlock +; SDAG-NEXT: v_cmp_lt_i32_e32 vcc, 25, v6 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[10:11], exec, s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB0_8 +; SDAG-NEXT: ; %bb.5: ; %LeafBlock +; SDAG-NEXT: v_cmp_ne_u32_e32 vcc, 26, v6 +; SDAG-NEXT: s_and_saveexec_b64 s[12:13], vcc +; SDAG-NEXT: s_cbranch_execz .LBB0_7 +; SDAG-NEXT: ; %bb.6: ; %itofp-sw-default +; SDAG-NEXT: v_sub_u32_e32 v12, 0x66, v7 +; SDAG-NEXT: v_sub_u32_e32 v10, 64, v12 +; SDAG-NEXT: v_lshrrev_b64 v[8:9], v12, v[0:1] +; SDAG-NEXT: v_lshlrev_b64 v[10:11], v10, v[4:5] +; SDAG-NEXT: v_sub_u32_e32 v13, 38, v7 +; SDAG-NEXT: v_or_b32_e32 v11, v9, v11 +; SDAG-NEXT: v_or_b32_e32 v10, v8, v10 +; SDAG-NEXT: v_lshrrev_b64 v[8:9], v13, v[4:5] +; SDAG-NEXT: v_cmp_gt_u32_e32 vcc, 64, v12 +; SDAG-NEXT: v_add_u32_e32 v14, 26, v7 +; SDAG-NEXT: v_cndmask_b32_e32 v9, v9, v11, vcc +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v12 +; SDAG-NEXT: v_cndmask_b32_e32 v8, v8, v10, vcc +; SDAG-NEXT: v_lshrrev_b64 v[10:11], v13, v[0:1] +; SDAG-NEXT: v_lshlrev_b64 v[12:13], v14, v[4:5] +; SDAG-NEXT: v_subrev_u32_e32 v7, 38, v7 +; SDAG-NEXT: v_cndmask_b32_e64 v15, v8, v0, s[4:5] +; SDAG-NEXT: v_lshlrev_b64 v[7:8], v7, v[0:1] +; SDAG-NEXT: v_cndmask_b32_e64 v9, v9, v1, s[4:5] +; SDAG-NEXT: v_or_b32_e32 v11, v13, v11 +; SDAG-NEXT: v_or_b32_e32 v10, v12, v10 +; SDAG-NEXT: v_cmp_gt_u32_e32 vcc, 64, v14 +; SDAG-NEXT: v_lshlrev_b64 v[0:1], v14, v[0:1] +; SDAG-NEXT: v_cndmask_b32_e32 v8, v8, v11, vcc +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v14 +; SDAG-NEXT: v_cndmask_b32_e32 v7, v7, v10, vcc +; SDAG-NEXT: v_cndmask_b32_e64 v5, v8, v5, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v4, v7, v4, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e32 v1, 0, v1, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v0, 0, v0, vcc +; SDAG-NEXT: v_or_b32_e32 v1, v1, v5 +; SDAG-NEXT: v_or_b32_e32 v0, v0, v4 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[0:1] +; SDAG-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; SDAG-NEXT: v_or_b32_e32 v8, v15, v0 +; SDAG-NEXT: v_mov_b32_e32 v0, v8 +; SDAG-NEXT: v_mov_b32_e32 v1, v9 +; SDAG-NEXT: .LBB0_7: ; %Flow1 +; SDAG-NEXT: s_or_b64 exec, exec, s[12:13] +; SDAG-NEXT: .LBB0_8: ; %Flow2 +; SDAG-NEXT: s_andn2_saveexec_b64 s[4:5], s[10:11] +; SDAG-NEXT: ; %bb.9: ; %itofp-sw-bb +; SDAG-NEXT: v_lshlrev_b64 v[0:1], 1, v[0:1] +; SDAG-NEXT: ; %bb.10: ; %itofp-sw-epilog +; SDAG-NEXT: s_or_b64 exec, exec, s[4:5] +; SDAG-NEXT: v_lshrrev_b32_e32 v4, 2, v0 +; SDAG-NEXT: v_and_or_b32 v0, v4, 1, v0 +; SDAG-NEXT: v_add_co_u32_e32 v0, vcc, 1, v0 +; SDAG-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; SDAG-NEXT: v_and_b32_e32 v4, 0x4000000, v0 +; SDAG-NEXT: v_cmp_ne_u32_e32 vcc, 0, v4 +; SDAG-NEXT: v_alignbit_b32 v8, v1, v0, 2 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: ; %bb.11: ; %itofp-if-then20 +; SDAG-NEXT: v_alignbit_b32 v8, v1, v0, 3 +; SDAG-NEXT: v_mov_b32_e32 v2, v6 +; SDAG-NEXT: ; %bb.12: ; %Flow +; SDAG-NEXT: s_or_b64 exec, exec, s[4:5] +; SDAG-NEXT: .LBB0_13: ; %Flow4 +; SDAG-NEXT: s_or_b64 exec, exec, s[8:9] +; SDAG-NEXT: v_and_b32_e32 v0, 0x80000000, v3 +; SDAG-NEXT: v_lshl_add_u32 v1, v2, 23, 1.0 +; SDAG-NEXT: v_and_b32_e32 v2, 0x7fffff, v8 +; SDAG-NEXT: v_or3_b32 v4, v2, v0, v1 +; SDAG-NEXT: .LBB0_14: ; %Flow5 +; SDAG-NEXT: s_or_b64 exec, exec, s[6:7] +; SDAG-NEXT: v_mov_b32_e32 v0, v4 +; SDAG-NEXT: s_setpc_b64 s[30:31] +; +; GISEL-LABEL: sitofp_i128_to_f32: +; GISEL: ; %bb.0: ; %itofp-entry +; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-NEXT: v_or_b32_e32 v4, v0, v2 +; GISEL-NEXT: v_or_b32_e32 v5, v1, v3 +; GISEL-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[4:5] +; GISEL-NEXT: s_mov_b32 s4, 0 +; GISEL-NEXT: v_mov_b32_e32 v4, s4 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], vcc +; GISEL-NEXT: s_cbranch_execz .LBB0_14 +; GISEL-NEXT: ; %bb.1: ; %itofp-if-end +; GISEL-NEXT: v_ashrrev_i32_e32 v6, 31, v3 +; GISEL-NEXT: v_xor_b32_e32 v0, v6, v0 +; GISEL-NEXT: v_xor_b32_e32 v1, v6, v1 +; GISEL-NEXT: v_sub_co_u32_e32 v0, vcc, v0, v6 +; GISEL-NEXT: v_xor_b32_e32 v2, v6, v2 +; GISEL-NEXT: v_subb_co_u32_e32 v1, vcc, v1, v6, vcc +; GISEL-NEXT: v_xor_b32_e32 v3, v6, v3 +; GISEL-NEXT: v_subb_co_u32_e32 v2, vcc, v2, v6, vcc +; GISEL-NEXT: v_ffbh_u32_e32 v5, v0 +; GISEL-NEXT: v_subb_co_u32_e32 v3, vcc, v3, v6, vcc +; GISEL-NEXT: v_ffbh_u32_e32 v4, v1 +; GISEL-NEXT: v_add_u32_e32 v5, 32, v5 +; GISEL-NEXT: v_ffbh_u32_e32 v7, v2 +; GISEL-NEXT: v_min_u32_e32 v4, v4, v5 +; GISEL-NEXT: v_ffbh_u32_e32 v5, v3 +; GISEL-NEXT: v_add_u32_e32 v7, 32, v7 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: v_add_u32_e32 v4, 64, v4 +; GISEL-NEXT: v_min_u32_e32 v5, v5, v7 +; GISEL-NEXT: v_cndmask_b32_e32 v5, v5, v4, vcc +; GISEL-NEXT: v_sub_u32_e32 v8, 0x80, v5 +; GISEL-NEXT: v_sub_u32_e32 v7, 0x7f, v5 +; GISEL-NEXT: v_cmp_ge_i32_e32 vcc, 24, v8 +; GISEL-NEXT: ; implicit-def: $vgpr4 +; GISEL-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GISEL-NEXT: s_xor_b64 s[4:5], exec, s[4:5] +; GISEL-NEXT: ; %bb.2: ; %itofp-if-else +; GISEL-NEXT: v_add_u32_e32 v2, 0xffffff98, v5 +; GISEL-NEXT: v_lshlrev_b64 v[0:1], v2, v[0:1] +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v2 +; GISEL-NEXT: v_cndmask_b32_e32 v4, 0, v0, vcc +; GISEL-NEXT: ; implicit-def: $vgpr8 +; GISEL-NEXT: ; implicit-def: $vgpr0 +; GISEL-NEXT: ; implicit-def: $vgpr5 +; GISEL-NEXT: ; implicit-def: $vgpr2 +; GISEL-NEXT: ; %bb.3: ; %Flow3 +; GISEL-NEXT: s_andn2_saveexec_b64 s[8:9], s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB0_13 +; GISEL-NEXT: ; %bb.4: ; %NodeBlock +; GISEL-NEXT: v_cmp_le_i32_e32 vcc, 26, v8 +; GISEL-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GISEL-NEXT: s_xor_b64 s[10:11], exec, s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB0_8 +; GISEL-NEXT: ; %bb.5: ; %LeafBlock +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 26, v8 +; GISEL-NEXT: s_and_saveexec_b64 s[12:13], vcc +; GISEL-NEXT: s_cbranch_execz .LBB0_7 +; GISEL-NEXT: ; %bb.6: ; %itofp-sw-default +; GISEL-NEXT: v_sub_u32_e32 v4, 0x66, v5 +; GISEL-NEXT: v_sub_u32_e32 v11, 64, v4 +; GISEL-NEXT: v_lshrrev_b64 v[9:10], v4, v[0:1] +; GISEL-NEXT: v_lshlrev_b64 v[11:12], v11, v[2:3] +; GISEL-NEXT: v_subrev_u32_e32 v13, 64, v4 +; GISEL-NEXT: v_or_b32_e32 v11, v9, v11 +; GISEL-NEXT: v_or_b32_e32 v12, v10, v12 +; GISEL-NEXT: v_lshrrev_b64 v[9:10], v13, v[2:3] +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v4 +; GISEL-NEXT: v_add_u32_e32 v5, 26, v5 +; GISEL-NEXT: v_cndmask_b32_e32 v9, v9, v11, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v10, v10, v12, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v4 +; GISEL-NEXT: v_sub_u32_e32 v11, 64, v5 +; GISEL-NEXT: v_cndmask_b32_e32 v13, v9, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v4, v10, v1, vcc +; GISEL-NEXT: v_lshrrev_b64 v[9:10], v5, -1 +; GISEL-NEXT: v_lshlrev_b64 v[11:12], v11, -1 +; GISEL-NEXT: v_subrev_u32_e32 v14, 64, v5 +; GISEL-NEXT: v_or_b32_e32 v15, v9, v11 +; GISEL-NEXT: v_or_b32_e32 v16, v10, v12 +; GISEL-NEXT: v_lshrrev_b64 v[11:12], v14, -1 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v5 +; GISEL-NEXT: v_cndmask_b32_e32 v11, v11, v15, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v12, v12, v16, vcc +; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v5 +; GISEL-NEXT: v_cndmask_b32_e32 v9, 0, v9, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v10, 0, v10, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v5, v11, -1, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v11, v12, -1, s[4:5] +; GISEL-NEXT: v_and_b32_e32 v2, v9, v2 +; GISEL-NEXT: v_and_b32_e32 v3, v10, v3 +; GISEL-NEXT: v_and_or_b32 v0, v5, v0, v2 +; GISEL-NEXT: v_and_or_b32 v1, v11, v1, v3 +; GISEL-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[0:1] +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v3, v13, v0 +; GISEL-NEXT: v_mov_b32_e32 v0, v3 +; GISEL-NEXT: v_mov_b32_e32 v1, v4 +; GISEL-NEXT: v_mov_b32_e32 v2, v5 +; GISEL-NEXT: v_mov_b32_e32 v3, v6 +; GISEL-NEXT: .LBB0_7: ; %Flow1 +; GISEL-NEXT: s_or_b64 exec, exec, s[12:13] +; GISEL-NEXT: .LBB0_8: ; %Flow2 +; GISEL-NEXT: s_andn2_saveexec_b64 s[4:5], s[10:11] +; GISEL-NEXT: ; %bb.9: ; %itofp-sw-bb +; GISEL-NEXT: v_lshlrev_b64 v[0:1], 1, v[0:1] +; GISEL-NEXT: ; %bb.10: ; %itofp-sw-epilog +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: v_bfe_u32 v2, v0, 2, 1 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v2 +; GISEL-NEXT: v_add_co_u32_e32 v0, vcc, 1, v0 +; GISEL-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; GISEL-NEXT: v_and_b32_e32 v2, 0x4000000, v0 +; GISEL-NEXT: v_mov_b32_e32 v3, 0 +; GISEL-NEXT: v_lshrrev_b64 v[4:5], 2, v[0:1] +; GISEL-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GISEL-NEXT: ; %bb.11: ; %itofp-if-then20 +; GISEL-NEXT: v_lshrrev_b64 v[4:5], 3, v[0:1] +; GISEL-NEXT: v_mov_b32_e32 v7, v8 +; GISEL-NEXT: ; %bb.12: ; %Flow +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: .LBB0_13: ; %Flow4 +; GISEL-NEXT: s_or_b64 exec, exec, s[8:9] +; GISEL-NEXT: v_and_b32_e32 v0, 0x80000000, v6 +; GISEL-NEXT: v_lshl_add_u32 v1, v7, 23, 1.0 +; GISEL-NEXT: v_and_b32_e32 v2, 0x7fffff, v4 +; GISEL-NEXT: v_or3_b32 v4, v2, v0, v1 +; GISEL-NEXT: .LBB0_14: ; %Flow5 +; GISEL-NEXT: s_or_b64 exec, exec, s[6:7] +; GISEL-NEXT: v_mov_b32_e32 v0, v4 +; GISEL-NEXT: s_setpc_b64 s[30:31] + %cvt = sitofp i128 %x to float + ret float %cvt +} + +define float @uitofp_i128_to_f32(i128 %x) { +; SDAG-LABEL: uitofp_i128_to_f32: +; SDAG: ; %bb.0: ; %itofp-entry +; SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-NEXT: v_or_b32_e32 v5, v1, v3 +; SDAG-NEXT: v_or_b32_e32 v4, v0, v2 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[4:5] +; SDAG-NEXT: v_mov_b32_e32 v4, 0 +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], vcc +; SDAG-NEXT: s_cbranch_execz .LBB1_14 +; SDAG-NEXT: ; %bb.1: ; %itofp-if-end +; SDAG-NEXT: v_ffbh_u32_e32 v4, v2 +; SDAG-NEXT: v_add_u32_e32 v4, 32, v4 +; SDAG-NEXT: v_ffbh_u32_e32 v5, v3 +; SDAG-NEXT: v_min_u32_e32 v4, v4, v5 +; SDAG-NEXT: v_ffbh_u32_e32 v5, v0 +; SDAG-NEXT: v_add_u32_e32 v5, 32, v5 +; SDAG-NEXT: v_ffbh_u32_e32 v6, v1 +; SDAG-NEXT: v_min_u32_e32 v5, v5, v6 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[2:3] +; SDAG-NEXT: v_add_u32_e32 v5, 64, v5 +; SDAG-NEXT: v_cndmask_b32_e32 v6, v5, v4, vcc +; SDAG-NEXT: v_sub_u32_e32 v5, 0x80, v6 +; SDAG-NEXT: v_sub_u32_e32 v4, 0x7f, v6 +; SDAG-NEXT: v_cmp_gt_i32_e32 vcc, 25, v5 +; SDAG-NEXT: ; implicit-def: $vgpr7 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[4:5], exec, s[4:5] +; SDAG-NEXT: ; %bb.2: ; %itofp-if-else +; SDAG-NEXT: v_add_u32_e32 v2, 0xffffff98, v6 +; SDAG-NEXT: v_lshlrev_b64 v[0:1], v2, v[0:1] +; SDAG-NEXT: v_cmp_gt_u32_e32 vcc, 64, v2 +; SDAG-NEXT: v_cndmask_b32_e32 v7, 0, v0, vcc +; SDAG-NEXT: ; implicit-def: $vgpr5 +; SDAG-NEXT: ; implicit-def: $vgpr0_vgpr1 +; SDAG-NEXT: ; implicit-def: $vgpr6 +; SDAG-NEXT: ; implicit-def: $vgpr2_vgpr3 +; SDAG-NEXT: ; %bb.3: ; %Flow3 +; SDAG-NEXT: s_andn2_saveexec_b64 s[8:9], s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB1_13 +; SDAG-NEXT: ; %bb.4: ; %NodeBlock +; SDAG-NEXT: v_cmp_lt_i32_e32 vcc, 25, v5 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[10:11], exec, s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB1_8 +; SDAG-NEXT: ; %bb.5: ; %LeafBlock +; SDAG-NEXT: v_cmp_ne_u32_e32 vcc, 26, v5 +; SDAG-NEXT: s_and_saveexec_b64 s[12:13], vcc +; SDAG-NEXT: s_cbranch_execz .LBB1_7 +; SDAG-NEXT: ; %bb.6: ; %itofp-sw-default +; SDAG-NEXT: v_sub_u32_e32 v11, 0x66, v6 +; SDAG-NEXT: v_sub_u32_e32 v9, 64, v11 +; SDAG-NEXT: v_lshrrev_b64 v[7:8], v11, v[0:1] +; SDAG-NEXT: v_lshlrev_b64 v[9:10], v9, v[2:3] +; SDAG-NEXT: v_sub_u32_e32 v12, 38, v6 +; SDAG-NEXT: v_or_b32_e32 v10, v8, v10 +; SDAG-NEXT: v_or_b32_e32 v9, v7, v9 +; SDAG-NEXT: v_lshrrev_b64 v[7:8], v12, v[2:3] +; SDAG-NEXT: v_cmp_gt_u32_e32 vcc, 64, v11 +; SDAG-NEXT: v_add_u32_e32 v13, 26, v6 +; SDAG-NEXT: v_cndmask_b32_e32 v8, v8, v10, vcc +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v11 +; SDAG-NEXT: v_cndmask_b32_e32 v7, v7, v9, vcc +; SDAG-NEXT: v_lshrrev_b64 v[9:10], v12, v[0:1] +; SDAG-NEXT: v_lshlrev_b64 v[11:12], v13, v[2:3] +; SDAG-NEXT: v_subrev_u32_e32 v6, 38, v6 +; SDAG-NEXT: v_cndmask_b32_e64 v14, v7, v0, s[4:5] +; SDAG-NEXT: v_lshlrev_b64 v[6:7], v6, v[0:1] +; SDAG-NEXT: v_cndmask_b32_e64 v8, v8, v1, s[4:5] +; SDAG-NEXT: v_or_b32_e32 v10, v12, v10 +; SDAG-NEXT: v_or_b32_e32 v9, v11, v9 +; SDAG-NEXT: v_cmp_gt_u32_e32 vcc, 64, v13 +; SDAG-NEXT: v_lshlrev_b64 v[0:1], v13, v[0:1] +; SDAG-NEXT: v_cndmask_b32_e32 v7, v7, v10, vcc +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v13 +; SDAG-NEXT: v_cndmask_b32_e32 v6, v6, v9, vcc +; SDAG-NEXT: v_cndmask_b32_e64 v3, v7, v3, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v2, v6, v2, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e32 v1, 0, v1, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v0, 0, v0, vcc +; SDAG-NEXT: v_or_b32_e32 v1, v1, v3 +; SDAG-NEXT: v_or_b32_e32 v0, v0, v2 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[0:1] +; SDAG-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; SDAG-NEXT: v_or_b32_e32 v7, v14, v0 +; SDAG-NEXT: v_mov_b32_e32 v0, v7 +; SDAG-NEXT: v_mov_b32_e32 v1, v8 +; SDAG-NEXT: .LBB1_7: ; %Flow1 +; SDAG-NEXT: s_or_b64 exec, exec, s[12:13] +; SDAG-NEXT: .LBB1_8: ; %Flow2 +; SDAG-NEXT: s_andn2_saveexec_b64 s[4:5], s[10:11] +; SDAG-NEXT: ; %bb.9: ; %itofp-sw-bb +; SDAG-NEXT: v_lshlrev_b64 v[0:1], 1, v[0:1] +; SDAG-NEXT: ; %bb.10: ; %itofp-sw-epilog +; SDAG-NEXT: s_or_b64 exec, exec, s[4:5] +; SDAG-NEXT: v_lshrrev_b32_e32 v2, 2, v0 +; SDAG-NEXT: v_and_or_b32 v0, v2, 1, v0 +; SDAG-NEXT: v_add_co_u32_e32 v0, vcc, 1, v0 +; SDAG-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; SDAG-NEXT: v_and_b32_e32 v2, 0x4000000, v0 +; SDAG-NEXT: v_cmp_ne_u32_e32 vcc, 0, v2 +; SDAG-NEXT: v_alignbit_b32 v7, v1, v0, 2 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: ; %bb.11: ; %itofp-if-then20 +; SDAG-NEXT: v_alignbit_b32 v7, v1, v0, 3 +; SDAG-NEXT: v_mov_b32_e32 v4, v5 +; SDAG-NEXT: ; %bb.12: ; %Flow +; SDAG-NEXT: s_or_b64 exec, exec, s[4:5] +; SDAG-NEXT: .LBB1_13: ; %Flow4 +; SDAG-NEXT: s_or_b64 exec, exec, s[8:9] +; SDAG-NEXT: v_and_b32_e32 v0, 0x7fffff, v7 +; SDAG-NEXT: v_lshl_or_b32 v0, v4, 23, v0 +; SDAG-NEXT: v_add_u32_e32 v4, 1.0, v0 +; SDAG-NEXT: .LBB1_14: ; %Flow5 +; SDAG-NEXT: s_or_b64 exec, exec, s[6:7] +; SDAG-NEXT: v_mov_b32_e32 v0, v4 +; SDAG-NEXT: s_setpc_b64 s[30:31] +; +; GISEL-LABEL: uitofp_i128_to_f32: +; GISEL: ; %bb.0: ; %itofp-entry +; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-NEXT: v_or_b32_e32 v4, v0, v2 +; GISEL-NEXT: v_or_b32_e32 v5, v1, v3 +; GISEL-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[4:5] +; GISEL-NEXT: s_mov_b32 s4, 0 +; GISEL-NEXT: v_mov_b32_e32 v4, s4 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], vcc +; GISEL-NEXT: s_cbranch_execz .LBB1_14 +; GISEL-NEXT: ; %bb.1: ; %itofp-if-end +; GISEL-NEXT: v_ffbh_u32_e32 v5, v0 +; GISEL-NEXT: v_ffbh_u32_e32 v4, v1 +; GISEL-NEXT: v_add_u32_e32 v5, 32, v5 +; GISEL-NEXT: v_ffbh_u32_e32 v6, v2 +; GISEL-NEXT: v_min_u32_e32 v4, v4, v5 +; GISEL-NEXT: v_ffbh_u32_e32 v5, v3 +; GISEL-NEXT: v_add_u32_e32 v6, 32, v6 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: v_add_u32_e32 v4, 64, v4 +; GISEL-NEXT: v_min_u32_e32 v5, v5, v6 +; GISEL-NEXT: v_cndmask_b32_e32 v5, v5, v4, vcc +; GISEL-NEXT: v_sub_u32_e32 v7, 0x80, v5 +; GISEL-NEXT: v_sub_u32_e32 v6, 0x7f, v5 +; GISEL-NEXT: v_cmp_ge_i32_e32 vcc, 24, v7 +; GISEL-NEXT: ; implicit-def: $vgpr4 +; GISEL-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GISEL-NEXT: s_xor_b64 s[4:5], exec, s[4:5] +; GISEL-NEXT: ; %bb.2: ; %itofp-if-else +; GISEL-NEXT: v_add_u32_e32 v2, 0xffffff98, v5 +; GISEL-NEXT: v_lshlrev_b64 v[0:1], v2, v[0:1] +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v2 +; GISEL-NEXT: v_cndmask_b32_e32 v4, 0, v0, vcc +; GISEL-NEXT: ; implicit-def: $vgpr7 +; GISEL-NEXT: ; implicit-def: $vgpr0 +; GISEL-NEXT: ; implicit-def: $vgpr5 +; GISEL-NEXT: ; implicit-def: $vgpr2 +; GISEL-NEXT: ; %bb.3: ; %Flow3 +; GISEL-NEXT: s_andn2_saveexec_b64 s[8:9], s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB1_13 +; GISEL-NEXT: ; %bb.4: ; %NodeBlock +; GISEL-NEXT: v_cmp_le_i32_e32 vcc, 26, v7 +; GISEL-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GISEL-NEXT: s_xor_b64 s[10:11], exec, s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB1_8 +; GISEL-NEXT: ; %bb.5: ; %LeafBlock +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 26, v7 +; GISEL-NEXT: s_and_saveexec_b64 s[12:13], vcc +; GISEL-NEXT: s_cbranch_execz .LBB1_7 +; GISEL-NEXT: ; %bb.6: ; %itofp-sw-default +; GISEL-NEXT: v_sub_u32_e32 v4, 0x66, v5 +; GISEL-NEXT: v_sub_u32_e32 v10, 64, v4 +; GISEL-NEXT: v_lshrrev_b64 v[8:9], v4, v[0:1] +; GISEL-NEXT: v_lshlrev_b64 v[10:11], v10, v[2:3] +; GISEL-NEXT: v_subrev_u32_e32 v12, 64, v4 +; GISEL-NEXT: v_or_b32_e32 v10, v8, v10 +; GISEL-NEXT: v_or_b32_e32 v11, v9, v11 +; GISEL-NEXT: v_lshrrev_b64 v[8:9], v12, v[2:3] +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v4 +; GISEL-NEXT: v_add_u32_e32 v5, 26, v5 +; GISEL-NEXT: v_cndmask_b32_e32 v8, v8, v10, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v9, v9, v11, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v4 +; GISEL-NEXT: v_sub_u32_e32 v10, 64, v5 +; GISEL-NEXT: v_cndmask_b32_e32 v12, v8, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v4, v9, v1, vcc +; GISEL-NEXT: v_lshrrev_b64 v[8:9], v5, -1 +; GISEL-NEXT: v_lshlrev_b64 v[10:11], v10, -1 +; GISEL-NEXT: v_subrev_u32_e32 v13, 64, v5 +; GISEL-NEXT: v_or_b32_e32 v14, v8, v10 +; GISEL-NEXT: v_or_b32_e32 v15, v9, v11 +; GISEL-NEXT: v_lshrrev_b64 v[10:11], v13, -1 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v5 +; GISEL-NEXT: v_cndmask_b32_e32 v10, v10, v14, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v11, v11, v15, vcc +; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v5 +; GISEL-NEXT: v_cndmask_b32_e32 v8, 0, v8, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v9, 0, v9, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v5, v10, -1, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v10, v11, -1, s[4:5] +; GISEL-NEXT: v_and_b32_e32 v2, v8, v2 +; GISEL-NEXT: v_and_b32_e32 v3, v9, v3 +; GISEL-NEXT: v_and_or_b32 v0, v5, v0, v2 +; GISEL-NEXT: v_and_or_b32 v1, v10, v1, v3 +; GISEL-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[0:1] +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v3, v12, v0 +; GISEL-NEXT: v_mov_b32_e32 v0, v3 +; GISEL-NEXT: v_mov_b32_e32 v1, v4 +; GISEL-NEXT: v_mov_b32_e32 v2, v5 +; GISEL-NEXT: v_mov_b32_e32 v3, v6 +; GISEL-NEXT: .LBB1_7: ; %Flow1 +; GISEL-NEXT: s_or_b64 exec, exec, s[12:13] +; GISEL-NEXT: .LBB1_8: ; %Flow2 +; GISEL-NEXT: s_andn2_saveexec_b64 s[4:5], s[10:11] +; GISEL-NEXT: ; %bb.9: ; %itofp-sw-bb +; GISEL-NEXT: v_lshlrev_b64 v[0:1], 1, v[0:1] +; GISEL-NEXT: ; %bb.10: ; %itofp-sw-epilog +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: v_bfe_u32 v2, v0, 2, 1 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v2 +; GISEL-NEXT: v_add_co_u32_e32 v0, vcc, 1, v0 +; GISEL-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; GISEL-NEXT: v_and_b32_e32 v2, 0x4000000, v0 +; GISEL-NEXT: v_mov_b32_e32 v3, 0 +; GISEL-NEXT: v_lshrrev_b64 v[4:5], 2, v[0:1] +; GISEL-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GISEL-NEXT: ; %bb.11: ; %itofp-if-then20 +; GISEL-NEXT: v_lshrrev_b64 v[4:5], 3, v[0:1] +; GISEL-NEXT: v_mov_b32_e32 v6, v7 +; GISEL-NEXT: ; %bb.12: ; %Flow +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: .LBB1_13: ; %Flow4 +; GISEL-NEXT: s_or_b64 exec, exec, s[8:9] +; GISEL-NEXT: v_lshl_add_u32 v0, v6, 23, 1.0 +; GISEL-NEXT: v_mov_b32_e32 v1, 0x7fffff +; GISEL-NEXT: v_and_or_b32 v4, v4, v1, v0 +; GISEL-NEXT: .LBB1_14: ; %Flow5 +; GISEL-NEXT: s_or_b64 exec, exec, s[6:7] +; GISEL-NEXT: v_mov_b32_e32 v0, v4 +; GISEL-NEXT: s_setpc_b64 s[30:31] + %cvt = uitofp i128 %x to float + ret float %cvt +} + +define double @sitofp_i128_to_f64(i128 %x) { +; SDAG-LABEL: sitofp_i128_to_f64: +; SDAG: ; %bb.0: ; %itofp-entry +; SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-NEXT: v_mov_b32_e32 v5, v1 +; SDAG-NEXT: v_mov_b32_e32 v4, v0 +; SDAG-NEXT: v_or_b32_e32 v1, v5, v3 +; SDAG-NEXT: v_or_b32_e32 v0, v4, v2 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[0:1] +; SDAG-NEXT: v_mov_b32_e32 v0, 0 +; SDAG-NEXT: v_mov_b32_e32 v1, 0 +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], vcc +; SDAG-NEXT: s_cbranch_execz .LBB2_14 +; SDAG-NEXT: ; %bb.1: ; %itofp-if-end +; SDAG-NEXT: v_ashrrev_i32_e32 v0, 31, v3 +; SDAG-NEXT: v_xor_b32_e32 v4, v0, v4 +; SDAG-NEXT: v_xor_b32_e32 v5, v0, v5 +; SDAG-NEXT: v_sub_co_u32_e32 v4, vcc, v4, v0 +; SDAG-NEXT: v_xor_b32_e32 v2, v0, v2 +; SDAG-NEXT: v_subb_co_u32_e32 v5, vcc, v5, v0, vcc +; SDAG-NEXT: v_xor_b32_e32 v1, v0, v3 +; SDAG-NEXT: v_subb_co_u32_e32 v6, vcc, v2, v0, vcc +; SDAG-NEXT: v_subb_co_u32_e32 v7, vcc, v1, v0, vcc +; SDAG-NEXT: v_ffbh_u32_e32 v0, v6 +; SDAG-NEXT: v_add_u32_e32 v0, 32, v0 +; SDAG-NEXT: v_ffbh_u32_e32 v1, v7 +; SDAG-NEXT: v_min_u32_e32 v0, v0, v1 +; SDAG-NEXT: v_ffbh_u32_e32 v1, v4 +; SDAG-NEXT: v_add_u32_e32 v1, 32, v1 +; SDAG-NEXT: v_ffbh_u32_e32 v2, v5 +; SDAG-NEXT: v_min_u32_e32 v1, v1, v2 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[6:7] +; SDAG-NEXT: v_add_u32_e32 v1, 64, v1 +; SDAG-NEXT: v_cndmask_b32_e32 v9, v1, v0, vcc +; SDAG-NEXT: v_sub_u32_e32 v8, 0x80, v9 +; SDAG-NEXT: v_sub_u32_e32 v2, 0x7f, v9 +; SDAG-NEXT: v_cmp_gt_i32_e32 vcc, 54, v8 +; SDAG-NEXT: ; implicit-def: $vgpr10 +; SDAG-NEXT: ; implicit-def: $vgpr0_vgpr1 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[4:5], exec, s[4:5] +; SDAG-NEXT: ; %bb.2: ; %itofp-if-else +; SDAG-NEXT: v_add_u32_e32 v6, 0xffffffb5, v9 +; SDAG-NEXT: v_lshlrev_b64 v[0:1], v6, v[4:5] +; SDAG-NEXT: v_cmp_gt_u32_e32 vcc, 64, v6 +; SDAG-NEXT: v_cndmask_b32_e32 v10, 0, v1, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v0, 0, v0, vcc +; SDAG-NEXT: ; implicit-def: $vgpr8 +; SDAG-NEXT: ; implicit-def: $vgpr6_vgpr7 +; SDAG-NEXT: ; implicit-def: $vgpr4_vgpr5 +; SDAG-NEXT: ; implicit-def: $vgpr9 +; SDAG-NEXT: ; %bb.3: ; %Flow3 +; SDAG-NEXT: s_andn2_saveexec_b64 s[8:9], s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB2_13 +; SDAG-NEXT: ; %bb.4: ; %NodeBlock +; SDAG-NEXT: v_cmp_lt_i32_e32 vcc, 54, v8 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[10:11], exec, s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB2_8 +; SDAG-NEXT: ; %bb.5: ; %LeafBlock +; SDAG-NEXT: v_cmp_ne_u32_e32 vcc, 55, v8 +; SDAG-NEXT: s_and_saveexec_b64 s[12:13], vcc +; SDAG-NEXT: s_cbranch_execz .LBB2_7 +; SDAG-NEXT: ; %bb.6: ; %itofp-sw-default +; SDAG-NEXT: v_sub_u32_e32 v12, 0x49, v9 +; SDAG-NEXT: v_sub_u32_e32 v10, 64, v12 +; SDAG-NEXT: v_lshrrev_b64 v[0:1], v12, v[4:5] +; SDAG-NEXT: v_lshlrev_b64 v[10:11], v10, v[6:7] +; SDAG-NEXT: v_sub_u32_e32 v13, 9, v9 +; SDAG-NEXT: v_or_b32_e32 v11, v1, v11 +; SDAG-NEXT: v_or_b32_e32 v10, v0, v10 +; SDAG-NEXT: v_lshrrev_b64 v[0:1], v13, v[6:7] +; SDAG-NEXT: v_cmp_gt_u32_e32 vcc, 64, v12 +; SDAG-NEXT: v_add_u32_e32 v16, 55, v9 +; SDAG-NEXT: v_cndmask_b32_e32 v1, v1, v11, vcc +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v12 +; SDAG-NEXT: v_cndmask_b32_e32 v0, v0, v10, vcc +; SDAG-NEXT: v_lshrrev_b64 v[10:11], v12, v[6:7] +; SDAG-NEXT: v_lshrrev_b64 v[12:13], v13, v[4:5] +; SDAG-NEXT: v_lshlrev_b64 v[14:15], v16, v[6:7] +; SDAG-NEXT: v_add_u32_e32 v9, -9, v9 +; SDAG-NEXT: v_or_b32_e32 v15, v15, v13 +; SDAG-NEXT: v_or_b32_e32 v14, v14, v12 +; SDAG-NEXT: v_lshlrev_b64 v[12:13], v9, v[4:5] +; SDAG-NEXT: v_cndmask_b32_e32 v11, 0, v11, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v10, 0, v10, vcc +; SDAG-NEXT: v_cmp_gt_u32_e32 vcc, 64, v16 +; SDAG-NEXT: v_cndmask_b32_e64 v1, v1, v5, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v0, v0, v4, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e32 v9, v13, v15, vcc +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v16 +; SDAG-NEXT: v_lshlrev_b64 v[4:5], v16, v[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v7, v9, v7, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e32 v9, v12, v14, vcc +; SDAG-NEXT: v_cndmask_b32_e64 v6, v9, v6, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e32 v5, 0, v5, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v4, 0, v4, vcc +; SDAG-NEXT: v_or_b32_e32 v5, v5, v7 +; SDAG-NEXT: v_or_b32_e32 v4, v4, v6 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[4:5] +; SDAG-NEXT: v_mov_b32_e32 v6, v10 +; SDAG-NEXT: v_cndmask_b32_e64 v4, 0, 1, vcc +; SDAG-NEXT: v_or_b32_e32 v0, v0, v4 +; SDAG-NEXT: v_mov_b32_e32 v5, v1 +; SDAG-NEXT: v_mov_b32_e32 v4, v0 +; SDAG-NEXT: v_mov_b32_e32 v7, v11 +; SDAG-NEXT: .LBB2_7: ; %Flow1 +; SDAG-NEXT: s_or_b64 exec, exec, s[12:13] +; SDAG-NEXT: .LBB2_8: ; %Flow2 +; SDAG-NEXT: s_andn2_saveexec_b64 s[4:5], s[10:11] +; SDAG-NEXT: ; %bb.9: ; %itofp-sw-bb +; SDAG-NEXT: v_lshlrev_b64 v[6:7], 1, v[6:7] +; SDAG-NEXT: v_lshrrev_b32_e32 v0, 31, v5 +; SDAG-NEXT: v_lshlrev_b64 v[4:5], 1, v[4:5] +; SDAG-NEXT: v_or_b32_e32 v6, v6, v0 +; SDAG-NEXT: ; %bb.10: ; %itofp-sw-epilog +; SDAG-NEXT: s_or_b64 exec, exec, s[4:5] +; SDAG-NEXT: v_lshrrev_b32_e32 v0, 2, v4 +; SDAG-NEXT: v_and_or_b32 v0, v0, 1, v4 +; SDAG-NEXT: v_add_co_u32_e32 v4, vcc, 1, v0 +; SDAG-NEXT: v_addc_co_u32_e32 v5, vcc, 0, v5, vcc +; SDAG-NEXT: v_addc_co_u32_e32 v6, vcc, 0, v6, vcc +; SDAG-NEXT: v_lshrrev_b64 v[0:1], 2, v[4:5] +; SDAG-NEXT: v_lshlrev_b32_e32 v7, 30, v6 +; SDAG-NEXT: v_or_b32_e32 v10, v1, v7 +; SDAG-NEXT: v_and_b32_e32 v1, 0x800000, v5 +; SDAG-NEXT: v_cmp_ne_u32_e32 vcc, 0, v1 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: ; %bb.11: ; %itofp-if-then20 +; SDAG-NEXT: v_lshrrev_b64 v[0:1], 3, v[4:5] +; SDAG-NEXT: v_lshlrev_b32_e32 v2, 29, v6 +; SDAG-NEXT: v_or_b32_e32 v10, v1, v2 +; SDAG-NEXT: v_mov_b32_e32 v2, v8 +; SDAG-NEXT: ; %bb.12: ; %Flow +; SDAG-NEXT: s_or_b64 exec, exec, s[4:5] +; SDAG-NEXT: .LBB2_13: ; %Flow4 +; SDAG-NEXT: s_or_b64 exec, exec, s[8:9] +; SDAG-NEXT: v_and_b32_e32 v1, 0x80000000, v3 +; SDAG-NEXT: v_mov_b32_e32 v3, 0x3ff00000 +; SDAG-NEXT: v_lshl_add_u32 v2, v2, 20, v3 +; SDAG-NEXT: v_and_b32_e32 v3, 0xfffff, v10 +; SDAG-NEXT: v_or3_b32 v1, v3, v1, v2 +; SDAG-NEXT: .LBB2_14: ; %Flow5 +; SDAG-NEXT: s_or_b64 exec, exec, s[6:7] +; SDAG-NEXT: s_setpc_b64 s[30:31] +; +; GISEL-LABEL: sitofp_i128_to_f64: +; GISEL: ; %bb.0: ; %itofp-entry +; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-NEXT: v_mov_b32_e32 v4, v0 +; GISEL-NEXT: v_mov_b32_e32 v5, v1 +; GISEL-NEXT: s_mov_b64 s[4:5], 0 +; GISEL-NEXT: v_or_b32_e32 v0, v4, v2 +; GISEL-NEXT: v_or_b32_e32 v1, v5, v3 +; GISEL-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[0:1] +; GISEL-NEXT: v_mov_b32_e32 v0, s4 +; GISEL-NEXT: v_mov_b32_e32 v1, s5 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], vcc +; GISEL-NEXT: s_cbranch_execz .LBB2_14 +; GISEL-NEXT: ; %bb.1: ; %itofp-if-end +; GISEL-NEXT: v_ashrrev_i32_e32 v6, 31, v3 +; GISEL-NEXT: v_xor_b32_e32 v0, v6, v4 +; GISEL-NEXT: v_xor_b32_e32 v1, v6, v5 +; GISEL-NEXT: v_sub_co_u32_e32 v0, vcc, v0, v6 +; GISEL-NEXT: v_xor_b32_e32 v2, v6, v2 +; GISEL-NEXT: v_subb_co_u32_e32 v1, vcc, v1, v6, vcc +; GISEL-NEXT: v_xor_b32_e32 v3, v6, v3 +; GISEL-NEXT: v_subb_co_u32_e32 v2, vcc, v2, v6, vcc +; GISEL-NEXT: v_ffbh_u32_e32 v5, v0 +; GISEL-NEXT: v_subb_co_u32_e32 v3, vcc, v3, v6, vcc +; GISEL-NEXT: v_ffbh_u32_e32 v4, v1 +; GISEL-NEXT: v_add_u32_e32 v5, 32, v5 +; GISEL-NEXT: v_ffbh_u32_e32 v7, v2 +; GISEL-NEXT: v_min_u32_e32 v4, v4, v5 +; GISEL-NEXT: v_ffbh_u32_e32 v5, v3 +; GISEL-NEXT: v_add_u32_e32 v7, 32, v7 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: v_add_u32_e32 v4, 64, v4 +; GISEL-NEXT: v_min_u32_e32 v5, v5, v7 +; GISEL-NEXT: v_cndmask_b32_e32 v9, v5, v4, vcc +; GISEL-NEXT: v_sub_u32_e32 v8, 0x80, v9 +; GISEL-NEXT: v_sub_u32_e32 v7, 0x7f, v9 +; GISEL-NEXT: v_cmp_ge_i32_e32 vcc, 53, v8 +; GISEL-NEXT: ; implicit-def: $vgpr10 +; GISEL-NEXT: ; implicit-def: $vgpr4_vgpr5 +; GISEL-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GISEL-NEXT: s_xor_b64 s[4:5], exec, s[4:5] +; GISEL-NEXT: ; %bb.2: ; %itofp-if-else +; GISEL-NEXT: v_add_u32_e32 v2, 0xffffffb5, v9 +; GISEL-NEXT: v_lshlrev_b64 v[0:1], v2, v[0:1] +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v2 +; GISEL-NEXT: v_cndmask_b32_e32 v4, 0, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v10, 0, v1, vcc +; GISEL-NEXT: ; implicit-def: $vgpr8 +; GISEL-NEXT: ; implicit-def: $vgpr0 +; GISEL-NEXT: ; implicit-def: $vgpr9 +; GISEL-NEXT: ; %bb.3: ; %Flow3 +; GISEL-NEXT: s_andn2_saveexec_b64 s[8:9], s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB2_13 +; GISEL-NEXT: ; %bb.4: ; %NodeBlock +; GISEL-NEXT: v_cmp_le_i32_e32 vcc, 55, v8 +; GISEL-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GISEL-NEXT: s_xor_b64 s[10:11], exec, s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB2_8 +; GISEL-NEXT: ; %bb.5: ; %LeafBlock +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 55, v8 +; GISEL-NEXT: s_and_saveexec_b64 s[12:13], vcc +; GISEL-NEXT: s_cbranch_execz .LBB2_7 +; GISEL-NEXT: ; %bb.6: ; %itofp-sw-default +; GISEL-NEXT: v_sub_u32_e32 v14, 0x49, v9 +; GISEL-NEXT: v_sub_u32_e32 v10, 64, v14 +; GISEL-NEXT: v_lshrrev_b64 v[4:5], v14, v[0:1] +; GISEL-NEXT: v_lshlrev_b64 v[10:11], v10, v[2:3] +; GISEL-NEXT: v_subrev_u32_e32 v15, 64, v14 +; GISEL-NEXT: v_or_b32_e32 v10, v4, v10 +; GISEL-NEXT: v_or_b32_e32 v11, v5, v11 +; GISEL-NEXT: v_lshrrev_b64 v[4:5], v15, v[2:3] +; GISEL-NEXT: v_lshrrev_b64 v[12:13], v14, v[2:3] +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v14 +; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v14 +; GISEL-NEXT: v_add_u32_e32 v14, 55, v9 +; GISEL-NEXT: v_cndmask_b32_e32 v4, v4, v10, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v5, v5, v11, vcc +; GISEL-NEXT: v_sub_u32_e32 v11, 64, v14 +; GISEL-NEXT: v_cndmask_b32_e64 v13, v4, v0, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v4, v5, v1, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e32 v5, 0, v12, vcc +; GISEL-NEXT: v_lshrrev_b64 v[9:10], v14, -1 +; GISEL-NEXT: v_lshlrev_b64 v[11:12], v11, -1 +; GISEL-NEXT: v_subrev_u32_e32 v15, 64, v14 +; GISEL-NEXT: v_or_b32_e32 v16, v9, v11 +; GISEL-NEXT: v_or_b32_e32 v17, v10, v12 +; GISEL-NEXT: v_lshrrev_b64 v[11:12], v15, -1 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v14 +; GISEL-NEXT: v_cndmask_b32_e32 v11, v11, v16, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v12, v12, v17, vcc +; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v14 +; GISEL-NEXT: v_cndmask_b32_e32 v9, 0, v9, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v10, 0, v10, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v11, v11, -1, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v12, v12, -1, s[4:5] +; GISEL-NEXT: v_and_b32_e32 v2, v9, v2 +; GISEL-NEXT: v_and_b32_e32 v3, v10, v3 +; GISEL-NEXT: v_and_or_b32 v0, v11, v0, v2 +; GISEL-NEXT: v_and_or_b32 v1, v12, v1, v3 +; GISEL-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[0:1] +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v3, v13, v0 +; GISEL-NEXT: v_mov_b32_e32 v0, v3 +; GISEL-NEXT: v_mov_b32_e32 v1, v4 +; GISEL-NEXT: v_mov_b32_e32 v2, v5 +; GISEL-NEXT: v_mov_b32_e32 v3, v6 +; GISEL-NEXT: .LBB2_7: ; %Flow1 +; GISEL-NEXT: s_or_b64 exec, exec, s[12:13] +; GISEL-NEXT: .LBB2_8: ; %Flow2 +; GISEL-NEXT: s_andn2_saveexec_b64 s[4:5], s[10:11] +; GISEL-NEXT: ; %bb.9: ; %itofp-sw-bb +; GISEL-NEXT: v_lshlrev_b64 v[9:10], 1, v[0:1] +; GISEL-NEXT: v_lshlrev_b64 v[2:3], 1, v[2:3] +; GISEL-NEXT: v_lshrrev_b32_e32 v0, 31, v1 +; GISEL-NEXT: v_or_b32_e32 v11, v2, v0 +; GISEL-NEXT: v_mov_b32_e32 v0, v9 +; GISEL-NEXT: v_mov_b32_e32 v1, v10 +; GISEL-NEXT: v_mov_b32_e32 v2, v11 +; GISEL-NEXT: v_mov_b32_e32 v3, v12 +; GISEL-NEXT: ; %bb.10: ; %itofp-sw-epilog +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: v_bfe_u32 v3, v0, 2, 1 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v3 +; GISEL-NEXT: v_add_co_u32_e32 v0, vcc, 1, v0 +; GISEL-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; GISEL-NEXT: v_addc_co_u32_e32 v2, vcc, 0, v2, vcc +; GISEL-NEXT: v_lshrrev_b64 v[4:5], 2, v[0:1] +; GISEL-NEXT: v_mov_b32_e32 v9, 0 +; GISEL-NEXT: v_and_b32_e32 v10, 0x800000, v1 +; GISEL-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[9:10] +; GISEL-NEXT: v_lshl_or_b32 v10, v2, 30, v5 +; GISEL-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GISEL-NEXT: ; %bb.11: ; %itofp-if-then20 +; GISEL-NEXT: v_lshrrev_b64 v[4:5], 3, v[0:1] +; GISEL-NEXT: v_mov_b32_e32 v7, v8 +; GISEL-NEXT: v_lshl_or_b32 v10, v2, 29, v5 +; GISEL-NEXT: ; %bb.12: ; %Flow +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: .LBB2_13: ; %Flow4 +; GISEL-NEXT: s_or_b64 exec, exec, s[8:9] +; GISEL-NEXT: v_and_b32_e32 v0, 0x80000000, v6 +; GISEL-NEXT: v_mov_b32_e32 v1, 0x3ff00000 +; GISEL-NEXT: v_mov_b32_e32 v2, 0xfffff +; GISEL-NEXT: v_lshl_add_u32 v1, v7, 20, v1 +; GISEL-NEXT: v_and_or_b32 v2, v10, v2, v0 +; GISEL-NEXT: v_and_or_b32 v0, v4, -1, 0 +; GISEL-NEXT: v_or3_b32 v1, v2, v1, 0 +; GISEL-NEXT: .LBB2_14: ; %Flow5 +; GISEL-NEXT: s_or_b64 exec, exec, s[6:7] +; GISEL-NEXT: s_setpc_b64 s[30:31] + %cvt = sitofp i128 %x to double + ret double %cvt +} + +define double @uitofp_i128_to_f64(i128 %x) { +; SDAG-LABEL: uitofp_i128_to_f64: +; SDAG: ; %bb.0: ; %itofp-entry +; SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-NEXT: v_or_b32_e32 v5, v1, v3 +; SDAG-NEXT: v_or_b32_e32 v4, v0, v2 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[4:5] +; SDAG-NEXT: v_mov_b32_e32 v4, 0 +; SDAG-NEXT: v_mov_b32_e32 v5, 0 +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], vcc +; SDAG-NEXT: s_cbranch_execz .LBB3_14 +; SDAG-NEXT: ; %bb.1: ; %itofp-if-end +; SDAG-NEXT: v_ffbh_u32_e32 v4, v2 +; SDAG-NEXT: v_add_u32_e32 v4, 32, v4 +; SDAG-NEXT: v_ffbh_u32_e32 v5, v3 +; SDAG-NEXT: v_min_u32_e32 v4, v4, v5 +; SDAG-NEXT: v_ffbh_u32_e32 v5, v0 +; SDAG-NEXT: v_add_u32_e32 v5, 32, v5 +; SDAG-NEXT: v_ffbh_u32_e32 v6, v1 +; SDAG-NEXT: v_min_u32_e32 v5, v5, v6 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[2:3] +; SDAG-NEXT: v_add_u32_e32 v5, 64, v5 +; SDAG-NEXT: v_cndmask_b32_e32 v8, v5, v4, vcc +; SDAG-NEXT: v_sub_u32_e32 v7, 0x80, v8 +; SDAG-NEXT: v_sub_u32_e32 v6, 0x7f, v8 +; SDAG-NEXT: v_cmp_gt_i32_e32 vcc, 54, v7 +; SDAG-NEXT: ; implicit-def: $vgpr9 +; SDAG-NEXT: ; implicit-def: $vgpr4_vgpr5 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[4:5], exec, s[4:5] +; SDAG-NEXT: ; %bb.2: ; %itofp-if-else +; SDAG-NEXT: v_add_u32_e32 v2, 0xffffffb5, v8 +; SDAG-NEXT: v_lshlrev_b64 v[0:1], v2, v[0:1] +; SDAG-NEXT: v_cmp_gt_u32_e32 vcc, 64, v2 +; SDAG-NEXT: v_cndmask_b32_e32 v9, 0, v1, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v4, 0, v0, vcc +; SDAG-NEXT: ; implicit-def: $vgpr7 +; SDAG-NEXT: ; implicit-def: $vgpr2_vgpr3 +; SDAG-NEXT: ; implicit-def: $vgpr0_vgpr1 +; SDAG-NEXT: ; implicit-def: $vgpr8 +; SDAG-NEXT: ; %bb.3: ; %Flow3 +; SDAG-NEXT: s_andn2_saveexec_b64 s[8:9], s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB3_13 +; SDAG-NEXT: ; %bb.4: ; %NodeBlock +; SDAG-NEXT: v_cmp_lt_i32_e32 vcc, 54, v7 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[10:11], exec, s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB3_8 +; SDAG-NEXT: ; %bb.5: ; %LeafBlock +; SDAG-NEXT: v_cmp_ne_u32_e32 vcc, 55, v7 +; SDAG-NEXT: s_and_saveexec_b64 s[12:13], vcc +; SDAG-NEXT: s_cbranch_execz .LBB3_7 +; SDAG-NEXT: ; %bb.6: ; %itofp-sw-default +; SDAG-NEXT: v_sub_u32_e32 v11, 0x49, v8 +; SDAG-NEXT: v_sub_u32_e32 v9, 64, v11 +; SDAG-NEXT: v_lshrrev_b64 v[4:5], v11, v[0:1] +; SDAG-NEXT: v_lshlrev_b64 v[9:10], v9, v[2:3] +; SDAG-NEXT: v_sub_u32_e32 v12, 9, v8 +; SDAG-NEXT: v_or_b32_e32 v10, v5, v10 +; SDAG-NEXT: v_or_b32_e32 v9, v4, v9 +; SDAG-NEXT: v_lshrrev_b64 v[4:5], v12, v[2:3] +; SDAG-NEXT: v_cmp_gt_u32_e32 vcc, 64, v11 +; SDAG-NEXT: v_add_u32_e32 v15, 55, v8 +; SDAG-NEXT: v_cndmask_b32_e32 v5, v5, v10, vcc +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v11 +; SDAG-NEXT: v_cndmask_b32_e32 v4, v4, v9, vcc +; SDAG-NEXT: v_lshrrev_b64 v[9:10], v11, v[2:3] +; SDAG-NEXT: v_lshrrev_b64 v[11:12], v12, v[0:1] +; SDAG-NEXT: v_lshlrev_b64 v[13:14], v15, v[2:3] +; SDAG-NEXT: v_add_u32_e32 v8, -9, v8 +; SDAG-NEXT: v_or_b32_e32 v14, v14, v12 +; SDAG-NEXT: v_or_b32_e32 v13, v13, v11 +; SDAG-NEXT: v_lshlrev_b64 v[11:12], v8, v[0:1] +; SDAG-NEXT: v_cndmask_b32_e32 v10, 0, v10, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v9, 0, v9, vcc +; SDAG-NEXT: v_cmp_gt_u32_e32 vcc, 64, v15 +; SDAG-NEXT: v_cndmask_b32_e64 v5, v5, v1, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v4, v4, v0, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e32 v8, v12, v14, vcc +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v15 +; SDAG-NEXT: v_lshlrev_b64 v[0:1], v15, v[0:1] +; SDAG-NEXT: v_cndmask_b32_e64 v3, v8, v3, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e32 v8, v11, v13, vcc +; SDAG-NEXT: v_cndmask_b32_e64 v2, v8, v2, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e32 v1, 0, v1, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v0, 0, v0, vcc +; SDAG-NEXT: v_or_b32_e32 v1, v1, v3 +; SDAG-NEXT: v_or_b32_e32 v0, v0, v2 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[0:1] +; SDAG-NEXT: v_mov_b32_e32 v2, v9 +; SDAG-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; SDAG-NEXT: v_or_b32_e32 v4, v4, v0 +; SDAG-NEXT: v_mov_b32_e32 v0, v4 +; SDAG-NEXT: v_mov_b32_e32 v1, v5 +; SDAG-NEXT: v_mov_b32_e32 v3, v10 +; SDAG-NEXT: .LBB3_7: ; %Flow1 +; SDAG-NEXT: s_or_b64 exec, exec, s[12:13] +; SDAG-NEXT: .LBB3_8: ; %Flow2 +; SDAG-NEXT: s_andn2_saveexec_b64 s[4:5], s[10:11] +; SDAG-NEXT: ; %bb.9: ; %itofp-sw-bb +; SDAG-NEXT: v_lshlrev_b64 v[2:3], 1, v[2:3] +; SDAG-NEXT: v_lshrrev_b32_e32 v3, 31, v1 +; SDAG-NEXT: v_lshlrev_b64 v[0:1], 1, v[0:1] +; SDAG-NEXT: v_or_b32_e32 v2, v2, v3 +; SDAG-NEXT: ; %bb.10: ; %itofp-sw-epilog +; SDAG-NEXT: s_or_b64 exec, exec, s[4:5] +; SDAG-NEXT: v_lshrrev_b32_e32 v3, 2, v0 +; SDAG-NEXT: v_and_or_b32 v0, v3, 1, v0 +; SDAG-NEXT: v_add_co_u32_e32 v0, vcc, 1, v0 +; SDAG-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; SDAG-NEXT: v_addc_co_u32_e32 v2, vcc, 0, v2, vcc +; SDAG-NEXT: v_lshrrev_b64 v[4:5], 2, v[0:1] +; SDAG-NEXT: v_and_b32_e32 v3, 0x800000, v1 +; SDAG-NEXT: v_cmp_ne_u32_e32 vcc, 0, v3 +; SDAG-NEXT: v_alignbit_b32 v9, v2, v1, 2 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: ; %bb.11: ; %itofp-if-then20 +; SDAG-NEXT: v_lshrrev_b64 v[4:5], 3, v[0:1] +; SDAG-NEXT: v_alignbit_b32 v9, v2, v1, 3 +; SDAG-NEXT: v_mov_b32_e32 v6, v7 +; SDAG-NEXT: ; %bb.12: ; %Flow +; SDAG-NEXT: s_or_b64 exec, exec, s[4:5] +; SDAG-NEXT: .LBB3_13: ; %Flow4 +; SDAG-NEXT: s_or_b64 exec, exec, s[8:9] +; SDAG-NEXT: v_and_b32_e32 v0, 0xfffff, v9 +; SDAG-NEXT: v_lshl_or_b32 v0, v6, 20, v0 +; SDAG-NEXT: v_add_u32_e32 v5, 0x3ff00000, v0 +; SDAG-NEXT: .LBB3_14: ; %Flow5 +; SDAG-NEXT: s_or_b64 exec, exec, s[6:7] +; SDAG-NEXT: v_mov_b32_e32 v0, v4 +; SDAG-NEXT: v_mov_b32_e32 v1, v5 +; SDAG-NEXT: s_setpc_b64 s[30:31] +; +; GISEL-LABEL: uitofp_i128_to_f64: +; GISEL: ; %bb.0: ; %itofp-entry +; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-NEXT: s_mov_b64 s[4:5], 0 +; GISEL-NEXT: v_or_b32_e32 v4, v0, v2 +; GISEL-NEXT: v_or_b32_e32 v5, v1, v3 +; GISEL-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[4:5] +; GISEL-NEXT: v_mov_b32_e32 v4, s4 +; GISEL-NEXT: v_mov_b32_e32 v5, s5 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], vcc +; GISEL-NEXT: s_cbranch_execz .LBB3_14 +; GISEL-NEXT: ; %bb.1: ; %itofp-if-end +; GISEL-NEXT: v_ffbh_u32_e32 v5, v0 +; GISEL-NEXT: v_ffbh_u32_e32 v4, v1 +; GISEL-NEXT: v_add_u32_e32 v5, 32, v5 +; GISEL-NEXT: v_ffbh_u32_e32 v6, v2 +; GISEL-NEXT: v_min_u32_e32 v4, v4, v5 +; GISEL-NEXT: v_ffbh_u32_e32 v5, v3 +; GISEL-NEXT: v_add_u32_e32 v6, 32, v6 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: v_add_u32_e32 v4, 64, v4 +; GISEL-NEXT: v_min_u32_e32 v5, v5, v6 +; GISEL-NEXT: v_cndmask_b32_e32 v8, v5, v4, vcc +; GISEL-NEXT: v_sub_u32_e32 v7, 0x80, v8 +; GISEL-NEXT: v_sub_u32_e32 v6, 0x7f, v8 +; GISEL-NEXT: v_cmp_ge_i32_e32 vcc, 53, v7 +; GISEL-NEXT: ; implicit-def: $vgpr9 +; GISEL-NEXT: ; implicit-def: $vgpr4_vgpr5 +; GISEL-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GISEL-NEXT: s_xor_b64 s[4:5], exec, s[4:5] +; GISEL-NEXT: ; %bb.2: ; %itofp-if-else +; GISEL-NEXT: v_add_u32_e32 v2, 0xffffffb5, v8 +; GISEL-NEXT: v_lshlrev_b64 v[0:1], v2, v[0:1] +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v2 +; GISEL-NEXT: v_cndmask_b32_e32 v4, 0, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v9, 0, v1, vcc +; GISEL-NEXT: ; implicit-def: $vgpr7 +; GISEL-NEXT: ; implicit-def: $vgpr0 +; GISEL-NEXT: ; implicit-def: $vgpr8 +; GISEL-NEXT: ; %bb.3: ; %Flow3 +; GISEL-NEXT: s_andn2_saveexec_b64 s[8:9], s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB3_13 +; GISEL-NEXT: ; %bb.4: ; %NodeBlock +; GISEL-NEXT: v_cmp_le_i32_e32 vcc, 55, v7 +; GISEL-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GISEL-NEXT: s_xor_b64 s[10:11], exec, s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB3_8 +; GISEL-NEXT: ; %bb.5: ; %LeafBlock +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 55, v7 +; GISEL-NEXT: s_and_saveexec_b64 s[12:13], vcc +; GISEL-NEXT: s_cbranch_execz .LBB3_7 +; GISEL-NEXT: ; %bb.6: ; %itofp-sw-default +; GISEL-NEXT: v_sub_u32_e32 v13, 0x49, v8 +; GISEL-NEXT: v_sub_u32_e32 v9, 64, v13 +; GISEL-NEXT: v_lshrrev_b64 v[4:5], v13, v[0:1] +; GISEL-NEXT: v_lshlrev_b64 v[9:10], v9, v[2:3] +; GISEL-NEXT: v_subrev_u32_e32 v14, 64, v13 +; GISEL-NEXT: v_lshrrev_b64 v[11:12], v13, v[2:3] +; GISEL-NEXT: v_or_b32_e32 v9, v4, v9 +; GISEL-NEXT: v_or_b32_e32 v10, v5, v10 +; GISEL-NEXT: v_lshrrev_b64 v[4:5], v14, v[2:3] +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v13 +; GISEL-NEXT: v_add_u32_e32 v8, 55, v8 +; GISEL-NEXT: v_cndmask_b32_e32 v4, v4, v9, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v5, v5, v10, vcc +; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v13 +; GISEL-NEXT: v_cndmask_b32_e32 v10, 0, v11, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v11, 0, v12, vcc +; GISEL-NEXT: v_sub_u32_e32 v12, 64, v8 +; GISEL-NEXT: v_cndmask_b32_e64 v14, v4, v0, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v9, v5, v1, s[4:5] +; GISEL-NEXT: v_lshrrev_b64 v[4:5], v8, -1 +; GISEL-NEXT: v_lshlrev_b64 v[12:13], v12, -1 +; GISEL-NEXT: v_subrev_u32_e32 v15, 64, v8 +; GISEL-NEXT: v_or_b32_e32 v16, v4, v12 +; GISEL-NEXT: v_or_b32_e32 v17, v5, v13 +; GISEL-NEXT: v_lshrrev_b64 v[12:13], v15, -1 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v8 +; GISEL-NEXT: v_cndmask_b32_e32 v12, v12, v16, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v13, v13, v17, vcc +; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v8 +; GISEL-NEXT: v_cndmask_b32_e32 v4, 0, v4, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v5, 0, v5, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v8, v12, -1, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v12, v13, -1, s[4:5] +; GISEL-NEXT: v_and_b32_e32 v2, v4, v2 +; GISEL-NEXT: v_and_b32_e32 v3, v5, v3 +; GISEL-NEXT: v_and_or_b32 v0, v8, v0, v2 +; GISEL-NEXT: v_and_or_b32 v1, v12, v1, v3 +; GISEL-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[0:1] +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v8, v14, v0 +; GISEL-NEXT: v_mov_b32_e32 v0, v8 +; GISEL-NEXT: v_mov_b32_e32 v1, v9 +; GISEL-NEXT: v_mov_b32_e32 v2, v10 +; GISEL-NEXT: v_mov_b32_e32 v3, v11 +; GISEL-NEXT: .LBB3_7: ; %Flow1 +; GISEL-NEXT: s_or_b64 exec, exec, s[12:13] +; GISEL-NEXT: .LBB3_8: ; %Flow2 +; GISEL-NEXT: s_andn2_saveexec_b64 s[4:5], s[10:11] +; GISEL-NEXT: ; %bb.9: ; %itofp-sw-bb +; GISEL-NEXT: v_lshlrev_b64 v[8:9], 1, v[0:1] +; GISEL-NEXT: v_lshlrev_b64 v[10:11], 1, v[2:3] +; GISEL-NEXT: v_lshrrev_b32_e32 v0, 31, v1 +; GISEL-NEXT: v_or_b32_e32 v10, v10, v0 +; GISEL-NEXT: v_mov_b32_e32 v0, v8 +; GISEL-NEXT: v_mov_b32_e32 v1, v9 +; GISEL-NEXT: v_mov_b32_e32 v2, v10 +; GISEL-NEXT: v_mov_b32_e32 v3, v11 +; GISEL-NEXT: ; %bb.10: ; %itofp-sw-epilog +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: v_bfe_u32 v4, v0, 2, 1 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v4 +; GISEL-NEXT: v_add_co_u32_e32 v0, vcc, 1, v0 +; GISEL-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; GISEL-NEXT: v_addc_co_u32_e32 v2, vcc, 0, v2, vcc +; GISEL-NEXT: v_addc_co_u32_e32 v3, vcc, 0, v3, vcc +; GISEL-NEXT: v_mov_b32_e32 v8, 0 +; GISEL-NEXT: v_and_b32_e32 v9, 0x800000, v1 +; GISEL-NEXT: v_lshrrev_b64 v[4:5], 2, v[0:1] +; GISEL-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[8:9] +; GISEL-NEXT: v_lshlrev_b64 v[8:9], 30, v[2:3] +; GISEL-NEXT: v_lshrrev_b32_e32 v5, 2, v1 +; GISEL-NEXT: v_or_b32_e32 v9, v5, v8 +; GISEL-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GISEL-NEXT: ; %bb.11: ; %itofp-if-then20 +; GISEL-NEXT: v_lshlrev_b64 v[2:3], 29, v[2:3] +; GISEL-NEXT: v_lshrrev_b64 v[4:5], 3, v[0:1] +; GISEL-NEXT: v_lshrrev_b32_e32 v0, 3, v1 +; GISEL-NEXT: v_or_b32_e32 v9, v0, v2 +; GISEL-NEXT: v_mov_b32_e32 v6, v7 +; GISEL-NEXT: ; %bb.12: ; %Flow +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: .LBB3_13: ; %Flow4 +; GISEL-NEXT: s_or_b64 exec, exec, s[8:9] +; GISEL-NEXT: v_mov_b32_e32 v0, 0x3ff00000 +; GISEL-NEXT: v_lshl_add_u32 v0, v6, 20, v0 +; GISEL-NEXT: v_and_b32_e32 v1, 0xfffff, v9 +; GISEL-NEXT: v_and_or_b32 v4, v4, -1, 0 +; GISEL-NEXT: v_or3_b32 v5, v1, v0, 0 +; GISEL-NEXT: .LBB3_14: ; %Flow5 +; GISEL-NEXT: s_or_b64 exec, exec, s[6:7] +; GISEL-NEXT: v_mov_b32_e32 v0, v4 +; GISEL-NEXT: v_mov_b32_e32 v1, v5 +; GISEL-NEXT: s_setpc_b64 s[30:31] + %cvt = uitofp i128 %x to double + ret double %cvt +} + +define half @sitofp_i128_to_f16(i128 %x) { +; SDAG-LABEL: sitofp_i128_to_f16: +; SDAG: ; %bb.0: ; %itofp-entry +; SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-NEXT: v_or_b32_e32 v5, v1, v3 +; SDAG-NEXT: v_or_b32_e32 v4, v0, v2 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[4:5] +; SDAG-NEXT: v_mov_b32_e32 v4, 0 +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], vcc +; SDAG-NEXT: s_cbranch_execz .LBB4_14 +; SDAG-NEXT: ; %bb.1: ; %itofp-if-end +; SDAG-NEXT: v_ashrrev_i32_e32 v5, 31, v3 +; SDAG-NEXT: v_xor_b32_e32 v0, v5, v0 +; SDAG-NEXT: v_xor_b32_e32 v1, v5, v1 +; SDAG-NEXT: v_sub_co_u32_e32 v0, vcc, v0, v5 +; SDAG-NEXT: v_xor_b32_e32 v2, v5, v2 +; SDAG-NEXT: v_subb_co_u32_e32 v1, vcc, v1, v5, vcc +; SDAG-NEXT: v_xor_b32_e32 v6, v5, v3 +; SDAG-NEXT: v_subb_co_u32_e32 v4, vcc, v2, v5, vcc +; SDAG-NEXT: v_subb_co_u32_e32 v5, vcc, v6, v5, vcc +; SDAG-NEXT: v_ffbh_u32_e32 v2, v4 +; SDAG-NEXT: v_add_u32_e32 v2, 32, v2 +; SDAG-NEXT: v_ffbh_u32_e32 v6, v5 +; SDAG-NEXT: v_min_u32_e32 v2, v2, v6 +; SDAG-NEXT: v_ffbh_u32_e32 v6, v0 +; SDAG-NEXT: v_add_u32_e32 v6, 32, v6 +; SDAG-NEXT: v_ffbh_u32_e32 v7, v1 +; SDAG-NEXT: v_min_u32_e32 v6, v6, v7 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[4:5] +; SDAG-NEXT: v_add_u32_e32 v6, 64, v6 +; SDAG-NEXT: v_cndmask_b32_e32 v7, v6, v2, vcc +; SDAG-NEXT: v_sub_u32_e32 v6, 0x80, v7 +; SDAG-NEXT: v_sub_u32_e32 v2, 0x7f, v7 +; SDAG-NEXT: v_cmp_gt_i32_e32 vcc, 25, v6 +; SDAG-NEXT: ; implicit-def: $vgpr8 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[4:5], exec, s[4:5] +; SDAG-NEXT: ; %bb.2: ; %itofp-if-else +; SDAG-NEXT: v_add_u32_e32 v4, 0xffffff98, v7 +; SDAG-NEXT: v_lshlrev_b64 v[0:1], v4, v[0:1] +; SDAG-NEXT: v_cmp_gt_u32_e32 vcc, 64, v4 +; SDAG-NEXT: v_cndmask_b32_e32 v8, 0, v0, vcc +; SDAG-NEXT: ; implicit-def: $vgpr6 +; SDAG-NEXT: ; implicit-def: $vgpr0_vgpr1 +; SDAG-NEXT: ; implicit-def: $vgpr7 +; SDAG-NEXT: ; implicit-def: $vgpr4_vgpr5 +; SDAG-NEXT: ; %bb.3: ; %Flow3 +; SDAG-NEXT: s_andn2_saveexec_b64 s[8:9], s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB4_13 +; SDAG-NEXT: ; %bb.4: ; %NodeBlock +; SDAG-NEXT: v_cmp_lt_i32_e32 vcc, 25, v6 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[10:11], exec, s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB4_8 +; SDAG-NEXT: ; %bb.5: ; %LeafBlock +; SDAG-NEXT: v_cmp_ne_u32_e32 vcc, 26, v6 +; SDAG-NEXT: s_and_saveexec_b64 s[12:13], vcc +; SDAG-NEXT: s_cbranch_execz .LBB4_7 +; SDAG-NEXT: ; %bb.6: ; %itofp-sw-default +; SDAG-NEXT: v_sub_u32_e32 v12, 0x66, v7 +; SDAG-NEXT: v_sub_u32_e32 v10, 64, v12 +; SDAG-NEXT: v_lshrrev_b64 v[8:9], v12, v[0:1] +; SDAG-NEXT: v_lshlrev_b64 v[10:11], v10, v[4:5] +; SDAG-NEXT: v_sub_u32_e32 v13, 38, v7 +; SDAG-NEXT: v_or_b32_e32 v11, v9, v11 +; SDAG-NEXT: v_or_b32_e32 v10, v8, v10 +; SDAG-NEXT: v_lshrrev_b64 v[8:9], v13, v[4:5] +; SDAG-NEXT: v_cmp_gt_u32_e32 vcc, 64, v12 +; SDAG-NEXT: v_add_u32_e32 v14, 26, v7 +; SDAG-NEXT: v_cndmask_b32_e32 v9, v9, v11, vcc +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v12 +; SDAG-NEXT: v_cndmask_b32_e32 v8, v8, v10, vcc +; SDAG-NEXT: v_lshrrev_b64 v[10:11], v13, v[0:1] +; SDAG-NEXT: v_lshlrev_b64 v[12:13], v14, v[4:5] +; SDAG-NEXT: v_subrev_u32_e32 v7, 38, v7 +; SDAG-NEXT: v_cndmask_b32_e64 v15, v8, v0, s[4:5] +; SDAG-NEXT: v_lshlrev_b64 v[7:8], v7, v[0:1] +; SDAG-NEXT: v_cndmask_b32_e64 v9, v9, v1, s[4:5] +; SDAG-NEXT: v_or_b32_e32 v11, v13, v11 +; SDAG-NEXT: v_or_b32_e32 v10, v12, v10 +; SDAG-NEXT: v_cmp_gt_u32_e32 vcc, 64, v14 +; SDAG-NEXT: v_lshlrev_b64 v[0:1], v14, v[0:1] +; SDAG-NEXT: v_cndmask_b32_e32 v8, v8, v11, vcc +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v14 +; SDAG-NEXT: v_cndmask_b32_e32 v7, v7, v10, vcc +; SDAG-NEXT: v_cndmask_b32_e64 v5, v8, v5, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v4, v7, v4, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e32 v1, 0, v1, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v0, 0, v0, vcc +; SDAG-NEXT: v_or_b32_e32 v1, v1, v5 +; SDAG-NEXT: v_or_b32_e32 v0, v0, v4 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[0:1] +; SDAG-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; SDAG-NEXT: v_or_b32_e32 v8, v15, v0 +; SDAG-NEXT: v_mov_b32_e32 v0, v8 +; SDAG-NEXT: v_mov_b32_e32 v1, v9 +; SDAG-NEXT: .LBB4_7: ; %Flow1 +; SDAG-NEXT: s_or_b64 exec, exec, s[12:13] +; SDAG-NEXT: .LBB4_8: ; %Flow2 +; SDAG-NEXT: s_andn2_saveexec_b64 s[4:5], s[10:11] +; SDAG-NEXT: ; %bb.9: ; %itofp-sw-bb +; SDAG-NEXT: v_lshlrev_b64 v[0:1], 1, v[0:1] +; SDAG-NEXT: ; %bb.10: ; %itofp-sw-epilog +; SDAG-NEXT: s_or_b64 exec, exec, s[4:5] +; SDAG-NEXT: v_lshrrev_b32_e32 v4, 2, v0 +; SDAG-NEXT: v_and_or_b32 v0, v4, 1, v0 +; SDAG-NEXT: v_add_co_u32_e32 v0, vcc, 1, v0 +; SDAG-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; SDAG-NEXT: v_and_b32_e32 v4, 0x4000000, v0 +; SDAG-NEXT: v_cmp_ne_u32_e32 vcc, 0, v4 +; SDAG-NEXT: v_alignbit_b32 v8, v1, v0, 2 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: ; %bb.11: ; %itofp-if-then20 +; SDAG-NEXT: v_alignbit_b32 v8, v1, v0, 3 +; SDAG-NEXT: v_mov_b32_e32 v2, v6 +; SDAG-NEXT: ; %bb.12: ; %Flow +; SDAG-NEXT: s_or_b64 exec, exec, s[4:5] +; SDAG-NEXT: .LBB4_13: ; %Flow4 +; SDAG-NEXT: s_or_b64 exec, exec, s[8:9] +; SDAG-NEXT: v_and_b32_e32 v0, 0x80000000, v3 +; SDAG-NEXT: v_lshl_add_u32 v1, v2, 23, 1.0 +; SDAG-NEXT: v_and_b32_e32 v2, 0x7fffff, v8 +; SDAG-NEXT: v_or3_b32 v0, v2, v0, v1 +; SDAG-NEXT: v_cvt_f16_f32_e32 v4, v0 +; SDAG-NEXT: .LBB4_14: ; %Flow5 +; SDAG-NEXT: s_or_b64 exec, exec, s[6:7] +; SDAG-NEXT: v_mov_b32_e32 v0, v4 +; SDAG-NEXT: s_setpc_b64 s[30:31] +; +; GISEL-LABEL: sitofp_i128_to_f16: +; GISEL: ; %bb.0: ; %itofp-entry +; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-NEXT: v_or_b32_e32 v4, v0, v2 +; GISEL-NEXT: v_or_b32_e32 v5, v1, v3 +; GISEL-NEXT: s_mov_b32 s4, 0 +; GISEL-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[4:5] +; GISEL-NEXT: v_mov_b32_e32 v4, s4 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], vcc +; GISEL-NEXT: s_cbranch_execz .LBB4_14 +; GISEL-NEXT: ; %bb.1: ; %itofp-if-end +; GISEL-NEXT: v_ashrrev_i32_e32 v6, 31, v3 +; GISEL-NEXT: v_xor_b32_e32 v0, v6, v0 +; GISEL-NEXT: v_xor_b32_e32 v1, v6, v1 +; GISEL-NEXT: v_sub_co_u32_e32 v0, vcc, v0, v6 +; GISEL-NEXT: v_xor_b32_e32 v2, v6, v2 +; GISEL-NEXT: v_subb_co_u32_e32 v1, vcc, v1, v6, vcc +; GISEL-NEXT: v_xor_b32_e32 v3, v6, v3 +; GISEL-NEXT: v_subb_co_u32_e32 v2, vcc, v2, v6, vcc +; GISEL-NEXT: v_ffbh_u32_e32 v5, v0 +; GISEL-NEXT: v_subb_co_u32_e32 v3, vcc, v3, v6, vcc +; GISEL-NEXT: v_ffbh_u32_e32 v4, v1 +; GISEL-NEXT: v_add_u32_e32 v5, 32, v5 +; GISEL-NEXT: v_ffbh_u32_e32 v7, v2 +; GISEL-NEXT: v_min_u32_e32 v4, v4, v5 +; GISEL-NEXT: v_ffbh_u32_e32 v5, v3 +; GISEL-NEXT: v_add_u32_e32 v7, 32, v7 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: v_add_u32_e32 v4, 64, v4 +; GISEL-NEXT: v_min_u32_e32 v5, v5, v7 +; GISEL-NEXT: v_cndmask_b32_e32 v5, v5, v4, vcc +; GISEL-NEXT: v_sub_u32_e32 v8, 0x80, v5 +; GISEL-NEXT: v_sub_u32_e32 v7, 0x7f, v5 +; GISEL-NEXT: v_cmp_ge_i32_e32 vcc, 24, v8 +; GISEL-NEXT: ; implicit-def: $vgpr4 +; GISEL-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GISEL-NEXT: s_xor_b64 s[4:5], exec, s[4:5] +; GISEL-NEXT: ; %bb.2: ; %itofp-if-else +; GISEL-NEXT: v_add_u32_e32 v2, 0xffffff98, v5 +; GISEL-NEXT: v_lshlrev_b64 v[0:1], v2, v[0:1] +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v2 +; GISEL-NEXT: v_cndmask_b32_e32 v4, 0, v0, vcc +; GISEL-NEXT: ; implicit-def: $vgpr8 +; GISEL-NEXT: ; implicit-def: $vgpr0 +; GISEL-NEXT: ; implicit-def: $vgpr5 +; GISEL-NEXT: ; implicit-def: $vgpr2 +; GISEL-NEXT: ; %bb.3: ; %Flow3 +; GISEL-NEXT: s_andn2_saveexec_b64 s[8:9], s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB4_13 +; GISEL-NEXT: ; %bb.4: ; %NodeBlock +; GISEL-NEXT: v_cmp_le_i32_e32 vcc, 26, v8 +; GISEL-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GISEL-NEXT: s_xor_b64 s[10:11], exec, s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB4_8 +; GISEL-NEXT: ; %bb.5: ; %LeafBlock +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 26, v8 +; GISEL-NEXT: s_and_saveexec_b64 s[12:13], vcc +; GISEL-NEXT: s_cbranch_execz .LBB4_7 +; GISEL-NEXT: ; %bb.6: ; %itofp-sw-default +; GISEL-NEXT: v_sub_u32_e32 v4, 0x66, v5 +; GISEL-NEXT: v_sub_u32_e32 v11, 64, v4 +; GISEL-NEXT: v_lshrrev_b64 v[9:10], v4, v[0:1] +; GISEL-NEXT: v_lshlrev_b64 v[11:12], v11, v[2:3] +; GISEL-NEXT: v_subrev_u32_e32 v13, 64, v4 +; GISEL-NEXT: v_or_b32_e32 v11, v9, v11 +; GISEL-NEXT: v_or_b32_e32 v12, v10, v12 +; GISEL-NEXT: v_lshrrev_b64 v[9:10], v13, v[2:3] +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v4 +; GISEL-NEXT: v_add_u32_e32 v5, 26, v5 +; GISEL-NEXT: v_cndmask_b32_e32 v9, v9, v11, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v10, v10, v12, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v4 +; GISEL-NEXT: v_sub_u32_e32 v11, 64, v5 +; GISEL-NEXT: v_cndmask_b32_e32 v13, v9, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v4, v10, v1, vcc +; GISEL-NEXT: v_lshrrev_b64 v[9:10], v5, -1 +; GISEL-NEXT: v_lshlrev_b64 v[11:12], v11, -1 +; GISEL-NEXT: v_subrev_u32_e32 v14, 64, v5 +; GISEL-NEXT: v_or_b32_e32 v15, v9, v11 +; GISEL-NEXT: v_or_b32_e32 v16, v10, v12 +; GISEL-NEXT: v_lshrrev_b64 v[11:12], v14, -1 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v5 +; GISEL-NEXT: v_cndmask_b32_e32 v11, v11, v15, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v12, v12, v16, vcc +; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v5 +; GISEL-NEXT: v_cndmask_b32_e32 v9, 0, v9, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v10, 0, v10, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v5, v11, -1, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v11, v12, -1, s[4:5] +; GISEL-NEXT: v_and_b32_e32 v2, v9, v2 +; GISEL-NEXT: v_and_b32_e32 v3, v10, v3 +; GISEL-NEXT: v_and_or_b32 v0, v5, v0, v2 +; GISEL-NEXT: v_and_or_b32 v1, v11, v1, v3 +; GISEL-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[0:1] +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v3, v13, v0 +; GISEL-NEXT: v_mov_b32_e32 v0, v3 +; GISEL-NEXT: v_mov_b32_e32 v1, v4 +; GISEL-NEXT: v_mov_b32_e32 v2, v5 +; GISEL-NEXT: v_mov_b32_e32 v3, v6 +; GISEL-NEXT: .LBB4_7: ; %Flow1 +; GISEL-NEXT: s_or_b64 exec, exec, s[12:13] +; GISEL-NEXT: .LBB4_8: ; %Flow2 +; GISEL-NEXT: s_andn2_saveexec_b64 s[4:5], s[10:11] +; GISEL-NEXT: ; %bb.9: ; %itofp-sw-bb +; GISEL-NEXT: v_lshlrev_b64 v[0:1], 1, v[0:1] +; GISEL-NEXT: ; %bb.10: ; %itofp-sw-epilog +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: v_bfe_u32 v2, v0, 2, 1 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v2 +; GISEL-NEXT: v_add_co_u32_e32 v0, vcc, 1, v0 +; GISEL-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; GISEL-NEXT: v_and_b32_e32 v2, 0x4000000, v0 +; GISEL-NEXT: v_mov_b32_e32 v3, 0 +; GISEL-NEXT: v_lshrrev_b64 v[4:5], 2, v[0:1] +; GISEL-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GISEL-NEXT: ; %bb.11: ; %itofp-if-then20 +; GISEL-NEXT: v_lshrrev_b64 v[4:5], 3, v[0:1] +; GISEL-NEXT: v_mov_b32_e32 v7, v8 +; GISEL-NEXT: ; %bb.12: ; %Flow +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: .LBB4_13: ; %Flow4 +; GISEL-NEXT: s_or_b64 exec, exec, s[8:9] +; GISEL-NEXT: v_and_b32_e32 v0, 0x80000000, v6 +; GISEL-NEXT: v_lshl_add_u32 v1, v7, 23, 1.0 +; GISEL-NEXT: v_and_b32_e32 v2, 0x7fffff, v4 +; GISEL-NEXT: v_or3_b32 v0, v2, v0, v1 +; GISEL-NEXT: v_cvt_f16_f32_e32 v4, v0 +; GISEL-NEXT: .LBB4_14: ; %Flow5 +; GISEL-NEXT: s_or_b64 exec, exec, s[6:7] +; GISEL-NEXT: v_mov_b32_e32 v0, v4 +; GISEL-NEXT: s_setpc_b64 s[30:31] + %cvt = sitofp i128 %x to half + ret half %cvt +} + +define half @uitofp_i128_to_f16(i128 %x) { +; SDAG-LABEL: uitofp_i128_to_f16: +; SDAG: ; %bb.0: ; %itofp-entry +; SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-NEXT: v_or_b32_e32 v5, v1, v3 +; SDAG-NEXT: v_or_b32_e32 v4, v0, v2 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[4:5] +; SDAG-NEXT: v_mov_b32_e32 v4, 0 +; SDAG-NEXT: s_and_saveexec_b64 s[6:7], vcc +; SDAG-NEXT: s_cbranch_execz .LBB5_14 +; SDAG-NEXT: ; %bb.1: ; %itofp-if-end +; SDAG-NEXT: v_ffbh_u32_e32 v4, v2 +; SDAG-NEXT: v_add_u32_e32 v4, 32, v4 +; SDAG-NEXT: v_ffbh_u32_e32 v5, v3 +; SDAG-NEXT: v_min_u32_e32 v4, v4, v5 +; SDAG-NEXT: v_ffbh_u32_e32 v5, v0 +; SDAG-NEXT: v_add_u32_e32 v5, 32, v5 +; SDAG-NEXT: v_ffbh_u32_e32 v6, v1 +; SDAG-NEXT: v_min_u32_e32 v5, v5, v6 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[2:3] +; SDAG-NEXT: v_add_u32_e32 v5, 64, v5 +; SDAG-NEXT: v_cndmask_b32_e32 v6, v5, v4, vcc +; SDAG-NEXT: v_sub_u32_e32 v5, 0x80, v6 +; SDAG-NEXT: v_sub_u32_e32 v4, 0x7f, v6 +; SDAG-NEXT: v_cmp_gt_i32_e32 vcc, 25, v5 +; SDAG-NEXT: ; implicit-def: $vgpr7 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[4:5], exec, s[4:5] +; SDAG-NEXT: ; %bb.2: ; %itofp-if-else +; SDAG-NEXT: v_add_u32_e32 v2, 0xffffff98, v6 +; SDAG-NEXT: v_lshlrev_b64 v[0:1], v2, v[0:1] +; SDAG-NEXT: v_cmp_gt_u32_e32 vcc, 64, v2 +; SDAG-NEXT: v_cndmask_b32_e32 v7, 0, v0, vcc +; SDAG-NEXT: ; implicit-def: $vgpr5 +; SDAG-NEXT: ; implicit-def: $vgpr0_vgpr1 +; SDAG-NEXT: ; implicit-def: $vgpr6 +; SDAG-NEXT: ; implicit-def: $vgpr2_vgpr3 +; SDAG-NEXT: ; %bb.3: ; %Flow3 +; SDAG-NEXT: s_andn2_saveexec_b64 s[8:9], s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB5_13 +; SDAG-NEXT: ; %bb.4: ; %NodeBlock +; SDAG-NEXT: v_cmp_lt_i32_e32 vcc, 25, v5 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: s_xor_b64 s[10:11], exec, s[4:5] +; SDAG-NEXT: s_cbranch_execz .LBB5_8 +; SDAG-NEXT: ; %bb.5: ; %LeafBlock +; SDAG-NEXT: v_cmp_ne_u32_e32 vcc, 26, v5 +; SDAG-NEXT: s_and_saveexec_b64 s[12:13], vcc +; SDAG-NEXT: s_cbranch_execz .LBB5_7 +; SDAG-NEXT: ; %bb.6: ; %itofp-sw-default +; SDAG-NEXT: v_sub_u32_e32 v11, 0x66, v6 +; SDAG-NEXT: v_sub_u32_e32 v9, 64, v11 +; SDAG-NEXT: v_lshrrev_b64 v[7:8], v11, v[0:1] +; SDAG-NEXT: v_lshlrev_b64 v[9:10], v9, v[2:3] +; SDAG-NEXT: v_sub_u32_e32 v12, 38, v6 +; SDAG-NEXT: v_or_b32_e32 v10, v8, v10 +; SDAG-NEXT: v_or_b32_e32 v9, v7, v9 +; SDAG-NEXT: v_lshrrev_b64 v[7:8], v12, v[2:3] +; SDAG-NEXT: v_cmp_gt_u32_e32 vcc, 64, v11 +; SDAG-NEXT: v_add_u32_e32 v13, 26, v6 +; SDAG-NEXT: v_cndmask_b32_e32 v8, v8, v10, vcc +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v11 +; SDAG-NEXT: v_cndmask_b32_e32 v7, v7, v9, vcc +; SDAG-NEXT: v_lshrrev_b64 v[9:10], v12, v[0:1] +; SDAG-NEXT: v_lshlrev_b64 v[11:12], v13, v[2:3] +; SDAG-NEXT: v_subrev_u32_e32 v6, 38, v6 +; SDAG-NEXT: v_cndmask_b32_e64 v14, v7, v0, s[4:5] +; SDAG-NEXT: v_lshlrev_b64 v[6:7], v6, v[0:1] +; SDAG-NEXT: v_cndmask_b32_e64 v8, v8, v1, s[4:5] +; SDAG-NEXT: v_or_b32_e32 v10, v12, v10 +; SDAG-NEXT: v_or_b32_e32 v9, v11, v9 +; SDAG-NEXT: v_cmp_gt_u32_e32 vcc, 64, v13 +; SDAG-NEXT: v_lshlrev_b64 v[0:1], v13, v[0:1] +; SDAG-NEXT: v_cndmask_b32_e32 v7, v7, v10, vcc +; SDAG-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v13 +; SDAG-NEXT: v_cndmask_b32_e32 v6, v6, v9, vcc +; SDAG-NEXT: v_cndmask_b32_e64 v3, v7, v3, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e64 v2, v6, v2, s[4:5] +; SDAG-NEXT: v_cndmask_b32_e32 v1, 0, v1, vcc +; SDAG-NEXT: v_cndmask_b32_e32 v0, 0, v0, vcc +; SDAG-NEXT: v_or_b32_e32 v1, v1, v3 +; SDAG-NEXT: v_or_b32_e32 v0, v0, v2 +; SDAG-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[0:1] +; SDAG-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; SDAG-NEXT: v_or_b32_e32 v7, v14, v0 +; SDAG-NEXT: v_mov_b32_e32 v0, v7 +; SDAG-NEXT: v_mov_b32_e32 v1, v8 +; SDAG-NEXT: .LBB5_7: ; %Flow1 +; SDAG-NEXT: s_or_b64 exec, exec, s[12:13] +; SDAG-NEXT: .LBB5_8: ; %Flow2 +; SDAG-NEXT: s_andn2_saveexec_b64 s[4:5], s[10:11] +; SDAG-NEXT: ; %bb.9: ; %itofp-sw-bb +; SDAG-NEXT: v_lshlrev_b64 v[0:1], 1, v[0:1] +; SDAG-NEXT: ; %bb.10: ; %itofp-sw-epilog +; SDAG-NEXT: s_or_b64 exec, exec, s[4:5] +; SDAG-NEXT: v_lshrrev_b32_e32 v2, 2, v0 +; SDAG-NEXT: v_and_or_b32 v0, v2, 1, v0 +; SDAG-NEXT: v_add_co_u32_e32 v0, vcc, 1, v0 +; SDAG-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; SDAG-NEXT: v_and_b32_e32 v2, 0x4000000, v0 +; SDAG-NEXT: v_cmp_ne_u32_e32 vcc, 0, v2 +; SDAG-NEXT: v_alignbit_b32 v7, v1, v0, 2 +; SDAG-NEXT: s_and_saveexec_b64 s[4:5], vcc +; SDAG-NEXT: ; %bb.11: ; %itofp-if-then20 +; SDAG-NEXT: v_alignbit_b32 v7, v1, v0, 3 +; SDAG-NEXT: v_mov_b32_e32 v4, v5 +; SDAG-NEXT: ; %bb.12: ; %Flow +; SDAG-NEXT: s_or_b64 exec, exec, s[4:5] +; SDAG-NEXT: .LBB5_13: ; %Flow4 +; SDAG-NEXT: s_or_b64 exec, exec, s[8:9] +; SDAG-NEXT: v_and_b32_e32 v0, 0x7fffff, v7 +; SDAG-NEXT: v_lshl_or_b32 v0, v4, 23, v0 +; SDAG-NEXT: v_add_u32_e32 v0, 1.0, v0 +; SDAG-NEXT: v_cvt_f16_f32_e32 v4, v0 +; SDAG-NEXT: .LBB5_14: ; %Flow5 +; SDAG-NEXT: s_or_b64 exec, exec, s[6:7] +; SDAG-NEXT: v_mov_b32_e32 v0, v4 +; SDAG-NEXT: s_setpc_b64 s[30:31] +; +; GISEL-LABEL: uitofp_i128_to_f16: +; GISEL: ; %bb.0: ; %itofp-entry +; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-NEXT: v_or_b32_e32 v4, v0, v2 +; GISEL-NEXT: v_or_b32_e32 v5, v1, v3 +; GISEL-NEXT: s_mov_b32 s4, 0 +; GISEL-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[4:5] +; GISEL-NEXT: v_mov_b32_e32 v4, s4 +; GISEL-NEXT: s_and_saveexec_b64 s[6:7], vcc +; GISEL-NEXT: s_cbranch_execz .LBB5_14 +; GISEL-NEXT: ; %bb.1: ; %itofp-if-end +; GISEL-NEXT: v_ffbh_u32_e32 v5, v0 +; GISEL-NEXT: v_ffbh_u32_e32 v4, v1 +; GISEL-NEXT: v_add_u32_e32 v5, 32, v5 +; GISEL-NEXT: v_ffbh_u32_e32 v6, v2 +; GISEL-NEXT: v_min_u32_e32 v4, v4, v5 +; GISEL-NEXT: v_ffbh_u32_e32 v5, v3 +; GISEL-NEXT: v_add_u32_e32 v6, 32, v6 +; GISEL-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: v_add_u32_e32 v4, 64, v4 +; GISEL-NEXT: v_min_u32_e32 v5, v5, v6 +; GISEL-NEXT: v_cndmask_b32_e32 v5, v5, v4, vcc +; GISEL-NEXT: v_sub_u32_e32 v7, 0x80, v5 +; GISEL-NEXT: v_sub_u32_e32 v6, 0x7f, v5 +; GISEL-NEXT: v_cmp_ge_i32_e32 vcc, 24, v7 +; GISEL-NEXT: ; implicit-def: $vgpr4 +; GISEL-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GISEL-NEXT: s_xor_b64 s[4:5], exec, s[4:5] +; GISEL-NEXT: ; %bb.2: ; %itofp-if-else +; GISEL-NEXT: v_add_u32_e32 v2, 0xffffff98, v5 +; GISEL-NEXT: v_lshlrev_b64 v[0:1], v2, v[0:1] +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v2 +; GISEL-NEXT: v_cndmask_b32_e32 v4, 0, v0, vcc +; GISEL-NEXT: ; implicit-def: $vgpr7 +; GISEL-NEXT: ; implicit-def: $vgpr0 +; GISEL-NEXT: ; implicit-def: $vgpr5 +; GISEL-NEXT: ; implicit-def: $vgpr2 +; GISEL-NEXT: ; %bb.3: ; %Flow3 +; GISEL-NEXT: s_andn2_saveexec_b64 s[8:9], s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB5_13 +; GISEL-NEXT: ; %bb.4: ; %NodeBlock +; GISEL-NEXT: v_cmp_le_i32_e32 vcc, 26, v7 +; GISEL-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GISEL-NEXT: s_xor_b64 s[10:11], exec, s[4:5] +; GISEL-NEXT: s_cbranch_execz .LBB5_8 +; GISEL-NEXT: ; %bb.5: ; %LeafBlock +; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 26, v7 +; GISEL-NEXT: s_and_saveexec_b64 s[12:13], vcc +; GISEL-NEXT: s_cbranch_execz .LBB5_7 +; GISEL-NEXT: ; %bb.6: ; %itofp-sw-default +; GISEL-NEXT: v_sub_u32_e32 v4, 0x66, v5 +; GISEL-NEXT: v_sub_u32_e32 v10, 64, v4 +; GISEL-NEXT: v_lshrrev_b64 v[8:9], v4, v[0:1] +; GISEL-NEXT: v_lshlrev_b64 v[10:11], v10, v[2:3] +; GISEL-NEXT: v_subrev_u32_e32 v12, 64, v4 +; GISEL-NEXT: v_or_b32_e32 v10, v8, v10 +; GISEL-NEXT: v_or_b32_e32 v11, v9, v11 +; GISEL-NEXT: v_lshrrev_b64 v[8:9], v12, v[2:3] +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v4 +; GISEL-NEXT: v_add_u32_e32 v5, 26, v5 +; GISEL-NEXT: v_cndmask_b32_e32 v8, v8, v10, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v9, v9, v11, vcc +; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v4 +; GISEL-NEXT: v_sub_u32_e32 v10, 64, v5 +; GISEL-NEXT: v_cndmask_b32_e32 v12, v8, v0, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v4, v9, v1, vcc +; GISEL-NEXT: v_lshrrev_b64 v[8:9], v5, -1 +; GISEL-NEXT: v_lshlrev_b64 v[10:11], v10, -1 +; GISEL-NEXT: v_subrev_u32_e32 v13, 64, v5 +; GISEL-NEXT: v_or_b32_e32 v14, v8, v10 +; GISEL-NEXT: v_or_b32_e32 v15, v9, v11 +; GISEL-NEXT: v_lshrrev_b64 v[10:11], v13, -1 +; GISEL-NEXT: v_cmp_gt_u32_e32 vcc, 64, v5 +; GISEL-NEXT: v_cndmask_b32_e32 v10, v10, v14, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v11, v11, v15, vcc +; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v5 +; GISEL-NEXT: v_cndmask_b32_e32 v8, 0, v8, vcc +; GISEL-NEXT: v_cndmask_b32_e32 v9, 0, v9, vcc +; GISEL-NEXT: v_cndmask_b32_e64 v5, v10, -1, s[4:5] +; GISEL-NEXT: v_cndmask_b32_e64 v10, v11, -1, s[4:5] +; GISEL-NEXT: v_and_b32_e32 v2, v8, v2 +; GISEL-NEXT: v_and_b32_e32 v3, v9, v3 +; GISEL-NEXT: v_and_or_b32 v0, v5, v0, v2 +; GISEL-NEXT: v_and_or_b32 v1, v10, v1, v3 +; GISEL-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[0:1] +; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc +; GISEL-NEXT: v_or_b32_e32 v3, v12, v0 +; GISEL-NEXT: v_mov_b32_e32 v0, v3 +; GISEL-NEXT: v_mov_b32_e32 v1, v4 +; GISEL-NEXT: v_mov_b32_e32 v2, v5 +; GISEL-NEXT: v_mov_b32_e32 v3, v6 +; GISEL-NEXT: .LBB5_7: ; %Flow1 +; GISEL-NEXT: s_or_b64 exec, exec, s[12:13] +; GISEL-NEXT: .LBB5_8: ; %Flow2 +; GISEL-NEXT: s_andn2_saveexec_b64 s[4:5], s[10:11] +; GISEL-NEXT: ; %bb.9: ; %itofp-sw-bb +; GISEL-NEXT: v_lshlrev_b64 v[0:1], 1, v[0:1] +; GISEL-NEXT: ; %bb.10: ; %itofp-sw-epilog +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: v_bfe_u32 v2, v0, 2, 1 +; GISEL-NEXT: v_or_b32_e32 v0, v0, v2 +; GISEL-NEXT: v_add_co_u32_e32 v0, vcc, 1, v0 +; GISEL-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; GISEL-NEXT: v_and_b32_e32 v2, 0x4000000, v0 +; GISEL-NEXT: v_mov_b32_e32 v3, 0 +; GISEL-NEXT: v_lshrrev_b64 v[4:5], 2, v[0:1] +; GISEL-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[2:3] +; GISEL-NEXT: s_and_saveexec_b64 s[4:5], vcc +; GISEL-NEXT: ; %bb.11: ; %itofp-if-then20 +; GISEL-NEXT: v_lshrrev_b64 v[4:5], 3, v[0:1] +; GISEL-NEXT: v_mov_b32_e32 v6, v7 +; GISEL-NEXT: ; %bb.12: ; %Flow +; GISEL-NEXT: s_or_b64 exec, exec, s[4:5] +; GISEL-NEXT: .LBB5_13: ; %Flow4 +; GISEL-NEXT: s_or_b64 exec, exec, s[8:9] +; GISEL-NEXT: v_lshl_add_u32 v0, v6, 23, 1.0 +; GISEL-NEXT: v_mov_b32_e32 v1, 0x7fffff +; GISEL-NEXT: v_and_or_b32 v0, v4, v1, v0 +; GISEL-NEXT: v_cvt_f16_f32_e32 v4, v0 +; GISEL-NEXT: .LBB5_14: ; %Flow5 +; GISEL-NEXT: s_or_b64 exec, exec, s[6:7] +; GISEL-NEXT: v_mov_b32_e32 v0, v4 +; GISEL-NEXT: s_setpc_b64 s[30:31] + %cvt = uitofp i128 %x to half + ret half %cvt +} + +; FIXME: ExpandLargeFpConvert asserts on bfloat +; define bfloat @sitofp_i128_to_bf16(i128 %x) { +; %cvt = sitofp i128 %x to bfloat +; ret bfloat %cvt +; } + +; define bfloat @uitofp_i128_to_bf16(i128 %x) { +; %cvt = uitofp i128 %x to bfloat +; ret bfloat %cvt +; } +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; GCN: {{.*}} diff --git a/llvm/test/CodeGen/AMDGPU/kernel-vgpr-spill-mubuf-with-voffset.ll b/llvm/test/CodeGen/AMDGPU/kernel-vgpr-spill-mubuf-with-voffset.ll index 1acbb0911828025b939c82993c46831a0425e0f7..fbf2ee1145ae94a17ba3621d3d23e45bdda8215a 100644 --- a/llvm/test/CodeGen/AMDGPU/kernel-vgpr-spill-mubuf-with-voffset.ll +++ b/llvm/test/CodeGen/AMDGPU/kernel-vgpr-spill-mubuf-with-voffset.ll @@ -60,7 +60,6 @@ define amdgpu_kernel void @test_kernel(i32 %val) #0 { ; CHECK-NEXT: ; implicit-def: $sgpr15 ; CHECK-NEXT: s_mov_b64 s[0:1], s[20:21] ; CHECK-NEXT: s_mov_b64 s[2:3], s[22:23] -; CHECK-NEXT: ; implicit-def: $sgpr18_sgpr19 ; CHECK-NEXT: s_waitcnt lgkmcnt(0) ; CHECK-NEXT: s_swappc_b64 s[30:31], s[16:17] ; CHECK-NEXT: s_or_saveexec_b64 s[34:35], -1 diff --git a/llvm/test/CodeGen/AMDGPU/lds-mixed-absolute-addresses-unused.ll b/llvm/test/CodeGen/AMDGPU/lds-mixed-absolute-addresses-unused.ll new file mode 100644 index 0000000000000000000000000000000000000000..d101d8da5e0fa2ab25ae543aae0697dbee6a27cb --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/lds-mixed-absolute-addresses-unused.ll @@ -0,0 +1,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -mtriple=amdgcn-- -amdgpu-lower-module-lds < %s 2>&1 | FileCheck %s +; RUN: opt -S -mtriple=amdgcn-- -passes=amdgpu-lower-module-lds < %s 2>&1 | FileCheck %s + +; This looks like a partially lowered module, but the non-lowered GV isn't used by any kernels. +; In such cases, LowerModuleLDS is free to leave it in and ignore it, and we want to make sure +; LowerModuleLDS doesn't crash if it re-runs on such modules. +@notLowered = addrspace(3) global i32 poison +@lowered = addrspace(3) global i32 poison, !absolute_symbol !0 + +@llvm.compiler.used = appending addrspace(1) global [1 x ptr] [ptr addrspacecast (ptr addrspace(3) @notLowered to ptr)], section "llvm.metadata" + +define amdgpu_kernel void @kern(i32 %val0) { +; CHECK-LABEL: define amdgpu_kernel void @kern( +; CHECK-SAME: i32 [[VAL0:%.*]]) { +; CHECK-NEXT: [[VAL1:%.*]] = add i32 [[VAL0]], 4 +; CHECK-NEXT: store i32 [[VAL1]], ptr addrspace(3) @lowered, align 4 +; CHECK-NEXT: ret void +; + %val1 = add i32 %val0, 4 + store i32 %val1, ptr addrspace(3) @lowered + ret void +} + + +!0 = !{i32 0, i32 1} diff --git a/llvm/test/CodeGen/AMDGPU/lds-reject-mixed-absolute-addresses.ll b/llvm/test/CodeGen/AMDGPU/lds-reject-mixed-absolute-addresses.ll index b512a43aa102220e5fdebbcb4daf7e352e8f6a26..b1f4f2ef1ef535e12c4438523381e89c81278fc1 100644 --- a/llvm/test/CodeGen/AMDGPU/lds-reject-mixed-absolute-addresses.ll +++ b/llvm/test/CodeGen/AMDGPU/lds-reject-mixed-absolute-addresses.ll @@ -8,7 +8,7 @@ define amdgpu_kernel void @kern() { %val0 = load i32, ptr addrspace(3) @var1 %val1 = add i32 %val0, 4 - store i32 %val1, ptr addrspace(3) @var1 + store i32 %val1, ptr addrspace(3) @var2 ret void } diff --git a/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll b/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll index 5007f77316f5b442cbc3f1cb06cc63b17595b769..0ff5dd3680dfab9b06380e1be55068ee436a2983 100644 --- a/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll +++ b/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll @@ -195,13 +195,13 @@ ; GCN-O1-NEXT: Uniformity Analysis ; GCN-O1-NEXT: AMDGPU atomic optimizations ; GCN-O1-NEXT: Expand Atomic instructions -; GCN-O1-NEXT: AMDGPU Promote Alloca ; GCN-O1-NEXT: Dominator Tree Construction +; GCN-O1-NEXT: Natural Loop Information +; GCN-O1-NEXT: AMDGPU Promote Alloca ; GCN-O1-NEXT: Cycle Info Analysis ; GCN-O1-NEXT: Uniformity Analysis ; GCN-O1-NEXT: AMDGPU IR optimizations ; GCN-O1-NEXT: Basic Alias Analysis (stateless AA impl) -; GCN-O1-NEXT: Natural Loop Information ; GCN-O1-NEXT: Canonicalize natural loops ; GCN-O1-NEXT: Scalar Evolution Analysis ; GCN-O1-NEXT: Loop Pass Manager @@ -470,9 +470,9 @@ ; GCN-O1-OPTS-NEXT: Uniformity Analysis ; GCN-O1-OPTS-NEXT: AMDGPU atomic optimizations ; GCN-O1-OPTS-NEXT: Expand Atomic instructions -; GCN-O1-OPTS-NEXT: AMDGPU Promote Alloca ; GCN-O1-OPTS-NEXT: Dominator Tree Construction ; GCN-O1-OPTS-NEXT: Natural Loop Information +; GCN-O1-OPTS-NEXT: AMDGPU Promote Alloca ; GCN-O1-OPTS-NEXT: Canonicalize natural loops ; GCN-O1-OPTS-NEXT: Lazy Branch Probability Analysis ; GCN-O1-OPTS-NEXT: Lazy Block Frequency Analysis @@ -775,9 +775,9 @@ ; GCN-O2-NEXT: Uniformity Analysis ; GCN-O2-NEXT: AMDGPU atomic optimizations ; GCN-O2-NEXT: Expand Atomic instructions -; GCN-O2-NEXT: AMDGPU Promote Alloca ; GCN-O2-NEXT: Dominator Tree Construction ; GCN-O2-NEXT: Natural Loop Information +; GCN-O2-NEXT: AMDGPU Promote Alloca ; GCN-O2-NEXT: Split GEPs to a variadic base and a constant offset for better CSE ; GCN-O2-NEXT: Scalar Evolution Analysis ; GCN-O2-NEXT: Straight line strength reduction @@ -1084,9 +1084,9 @@ ; GCN-O3-NEXT: Uniformity Analysis ; GCN-O3-NEXT: AMDGPU atomic optimizations ; GCN-O3-NEXT: Expand Atomic instructions -; GCN-O3-NEXT: AMDGPU Promote Alloca ; GCN-O3-NEXT: Dominator Tree Construction ; GCN-O3-NEXT: Natural Loop Information +; GCN-O3-NEXT: AMDGPU Promote Alloca ; GCN-O3-NEXT: Split GEPs to a variadic base and a constant offset for better CSE ; GCN-O3-NEXT: Scalar Evolution Analysis ; GCN-O3-NEXT: Straight line strength reduction diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.global.load.tr-w32.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.global.load.tr-w32.ll index b4415c12926ac3db8f1df7d0dcacf477f7bb77e2..f6197e0770213c2125a50f8da2925dfb8f030f7e 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.global.load.tr-w32.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.global.load.tr-w32.ll @@ -1,132 +1,44 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -global-isel=0 -mtriple=amdgcn -mcpu=gfx1200 -verify-machineinstrs -mattr=+wavefrontsize32,-wavefrontsize64 < %s | FileCheck -check-prefixes=GFX12-SDAG-W32 %s -; RUN: llc -global-isel=1 -mtriple=amdgcn -mcpu=gfx1200 -verify-machineinstrs -mattr=+wavefrontsize32,-wavefrontsize64 < %s | FileCheck -check-prefixes=GFX12-GISEL-W32 %s +; RUN: llc -global-isel=0 -mtriple=amdgcn -mcpu=gfx1200 -verify-machineinstrs -mattr=+wavefrontsize32,-wavefrontsize64 < %s | FileCheck -check-prefix=GFX12 %s +; RUN: llc -global-isel=1 -mtriple=amdgcn -mcpu=gfx1200 -verify-machineinstrs -mattr=+wavefrontsize32,-wavefrontsize64 < %s | FileCheck -check-prefix=GFX12 %s -declare <2 x i32> @llvm.amdgcn.global.load.tr.v2i32.p1(ptr addrspace(1)) -declare <8 x i16> @llvm.amdgcn.global.load.tr.v8i16.p1(ptr addrspace(1)) -declare <8 x half> @llvm.amdgcn.global.load.tr.v8f16.p1(ptr addrspace(1)) -declare <8 x bfloat> @llvm.amdgcn.global.load.tr.v8bf16.p1(ptr addrspace(1)) +declare <2 x i32> @llvm.amdgcn.global.load.tr.b64.v2i32.p1(ptr addrspace(1)) +declare <8 x i16> @llvm.amdgcn.global.load.tr.b128.v8i16.p1(ptr addrspace(1)) define amdgpu_kernel void @global_load_tr_b64(ptr addrspace(1) %addr, ptr addrspace(1) %use) { -; GFX12-SDAG-W32-LABEL: global_load_tr_b64: -; GFX12-SDAG-W32: ; %bb.0: ; %entry -; GFX12-SDAG-W32-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 -; GFX12-SDAG-W32-NEXT: v_mov_b32_e32 v2, 0 -; GFX12-SDAG-W32-NEXT: s_wait_kmcnt 0x0 -; GFX12-SDAG-W32-NEXT: global_load_tr_b64 v[0:1], v2, s[0:1] offset:32 -; GFX12-SDAG-W32-NEXT: s_wait_loadcnt 0x0 -; GFX12-SDAG-W32-NEXT: global_store_b64 v2, v[0:1], s[2:3] -; GFX12-SDAG-W32-NEXT: s_nop 0 -; GFX12-SDAG-W32-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) -; GFX12-SDAG-W32-NEXT: s_endpgm -; -; GFX12-GISEL-W32-LABEL: global_load_tr_b64: -; GFX12-GISEL-W32: ; %bb.0: ; %entry -; GFX12-GISEL-W32-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 -; GFX12-GISEL-W32-NEXT: v_mov_b32_e32 v2, 0 -; GFX12-GISEL-W32-NEXT: s_wait_kmcnt 0x0 -; GFX12-GISEL-W32-NEXT: global_load_tr_b64 v[0:1], v2, s[0:1] offset:32 -; GFX12-GISEL-W32-NEXT: s_wait_loadcnt 0x0 -; GFX12-GISEL-W32-NEXT: global_store_b64 v2, v[0:1], s[2:3] -; GFX12-GISEL-W32-NEXT: s_nop 0 -; GFX12-GISEL-W32-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) -; GFX12-GISEL-W32-NEXT: s_endpgm +; GFX12-LABEL: global_load_tr_b64: +; GFX12: ; %bb.0: ; %entry +; GFX12-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 +; GFX12-NEXT: v_mov_b32_e32 v2, 0 +; GFX12-NEXT: s_wait_kmcnt 0x0 +; GFX12-NEXT: global_load_tr_b64 v[0:1], v2, s[0:1] offset:32 +; GFX12-NEXT: s_wait_loadcnt 0x0 +; GFX12-NEXT: global_store_b64 v2, v[0:1], s[2:3] +; GFX12-NEXT: s_nop 0 +; GFX12-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) +; GFX12-NEXT: s_endpgm entry: %gep = getelementptr i64, ptr addrspace(1) %addr, i32 4 - %val = call <2 x i32> @llvm.amdgcn.global.load.tr.v2i32.p1(ptr addrspace(1) %gep) + %val = call <2 x i32> @llvm.amdgcn.global.load.tr.b64.v2i32.p1(ptr addrspace(1) %gep) store <2 x i32> %val, ptr addrspace(1) %use ret void } -define amdgpu_kernel void @global_load_tr_b128_i16(ptr addrspace(1) %addr, ptr addrspace(1) %use) { -; GFX12-SDAG-W32-LABEL: global_load_tr_b128_i16: -; GFX12-SDAG-W32: ; %bb.0: ; %entry -; GFX12-SDAG-W32-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 -; GFX12-SDAG-W32-NEXT: v_mov_b32_e32 v4, 0 -; GFX12-SDAG-W32-NEXT: s_wait_kmcnt 0x0 -; GFX12-SDAG-W32-NEXT: global_load_tr_b128 v[0:3], v4, s[0:1] offset:32 -; GFX12-SDAG-W32-NEXT: s_wait_loadcnt 0x0 -; GFX12-SDAG-W32-NEXT: global_store_b128 v4, v[0:3], s[2:3] -; GFX12-SDAG-W32-NEXT: s_nop 0 -; GFX12-SDAG-W32-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) -; GFX12-SDAG-W32-NEXT: s_endpgm -; -; GFX12-GISEL-W32-LABEL: global_load_tr_b128_i16: -; GFX12-GISEL-W32: ; %bb.0: ; %entry -; GFX12-GISEL-W32-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 -; GFX12-GISEL-W32-NEXT: v_mov_b32_e32 v4, 0 -; GFX12-GISEL-W32-NEXT: s_wait_kmcnt 0x0 -; GFX12-GISEL-W32-NEXT: global_load_tr_b128 v[0:3], v4, s[0:1] offset:32 -; GFX12-GISEL-W32-NEXT: s_wait_loadcnt 0x0 -; GFX12-GISEL-W32-NEXT: global_store_b128 v4, v[0:3], s[2:3] -; GFX12-GISEL-W32-NEXT: s_nop 0 -; GFX12-GISEL-W32-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) -; GFX12-GISEL-W32-NEXT: s_endpgm +define amdgpu_kernel void @global_load_tr_b128(ptr addrspace(1) %addr, ptr addrspace(1) %use) { +; GFX12-LABEL: global_load_tr_b128: +; GFX12: ; %bb.0: ; %entry +; GFX12-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 +; GFX12-NEXT: v_mov_b32_e32 v4, 0 +; GFX12-NEXT: s_wait_kmcnt 0x0 +; GFX12-NEXT: global_load_tr_b128 v[0:3], v4, s[0:1] offset:32 +; GFX12-NEXT: s_wait_loadcnt 0x0 +; GFX12-NEXT: global_store_b128 v4, v[0:3], s[2:3] +; GFX12-NEXT: s_nop 0 +; GFX12-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) +; GFX12-NEXT: s_endpgm entry: %gep = getelementptr i64, ptr addrspace(1) %addr, i32 4 - %val = call <8 x i16> @llvm.amdgcn.global.load.tr.v8i16.p1(ptr addrspace(1) %gep) + %val = call <8 x i16> @llvm.amdgcn.global.load.tr.b128.v8i16.p1(ptr addrspace(1) %gep) store <8 x i16> %val, ptr addrspace(1) %use ret void } - -define amdgpu_kernel void @global_load_tr_b128_half(ptr addrspace(1) %addr, ptr addrspace(1) %use) { -; GFX12-SDAG-W32-LABEL: global_load_tr_b128_half: -; GFX12-SDAG-W32: ; %bb.0: ; %entry -; GFX12-SDAG-W32-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 -; GFX12-SDAG-W32-NEXT: v_mov_b32_e32 v4, 0 -; GFX12-SDAG-W32-NEXT: s_wait_kmcnt 0x0 -; GFX12-SDAG-W32-NEXT: global_load_tr_b128 v[0:3], v4, s[0:1] offset:32 -; GFX12-SDAG-W32-NEXT: s_wait_loadcnt 0x0 -; GFX12-SDAG-W32-NEXT: global_store_b128 v4, v[0:3], s[2:3] -; GFX12-SDAG-W32-NEXT: s_nop 0 -; GFX12-SDAG-W32-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) -; GFX12-SDAG-W32-NEXT: s_endpgm -; -; GFX12-GISEL-W32-LABEL: global_load_tr_b128_half: -; GFX12-GISEL-W32: ; %bb.0: ; %entry -; GFX12-GISEL-W32-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 -; GFX12-GISEL-W32-NEXT: v_mov_b32_e32 v4, 0 -; GFX12-GISEL-W32-NEXT: s_wait_kmcnt 0x0 -; GFX12-GISEL-W32-NEXT: global_load_tr_b128 v[0:3], v4, s[0:1] offset:32 -; GFX12-GISEL-W32-NEXT: s_wait_loadcnt 0x0 -; GFX12-GISEL-W32-NEXT: global_store_b128 v4, v[0:3], s[2:3] -; GFX12-GISEL-W32-NEXT: s_nop 0 -; GFX12-GISEL-W32-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) -; GFX12-GISEL-W32-NEXT: s_endpgm -entry: - %gep = getelementptr i64, ptr addrspace(1) %addr, i32 4 - %val = call <8 x half> @llvm.amdgcn.global.load.tr.v8f16.p1(ptr addrspace(1) %gep) - store <8 x half> %val, ptr addrspace(1) %use - ret void -} - -define amdgpu_kernel void @global_load_tr_b128_bfloat(ptr addrspace(1) %addr, ptr addrspace(1) %use) { -; GFX12-SDAG-W32-LABEL: global_load_tr_b128_bfloat: -; GFX12-SDAG-W32: ; %bb.0: ; %entry -; GFX12-SDAG-W32-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 -; GFX12-SDAG-W32-NEXT: v_mov_b32_e32 v4, 0 -; GFX12-SDAG-W32-NEXT: s_wait_kmcnt 0x0 -; GFX12-SDAG-W32-NEXT: global_load_tr_b128 v[0:3], v4, s[0:1] offset:32 -; GFX12-SDAG-W32-NEXT: s_wait_loadcnt 0x0 -; GFX12-SDAG-W32-NEXT: global_store_b128 v4, v[0:3], s[2:3] -; GFX12-SDAG-W32-NEXT: s_nop 0 -; GFX12-SDAG-W32-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) -; GFX12-SDAG-W32-NEXT: s_endpgm -; -; GFX12-GISEL-W32-LABEL: global_load_tr_b128_bfloat: -; GFX12-GISEL-W32: ; %bb.0: ; %entry -; GFX12-GISEL-W32-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 -; GFX12-GISEL-W32-NEXT: v_mov_b32_e32 v4, 0 -; GFX12-GISEL-W32-NEXT: s_wait_kmcnt 0x0 -; GFX12-GISEL-W32-NEXT: global_load_tr_b128 v[0:3], v4, s[0:1] offset:32 -; GFX12-GISEL-W32-NEXT: s_wait_loadcnt 0x0 -; GFX12-GISEL-W32-NEXT: global_store_b128 v4, v[0:3], s[2:3] -; GFX12-GISEL-W32-NEXT: s_nop 0 -; GFX12-GISEL-W32-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) -; GFX12-GISEL-W32-NEXT: s_endpgm -entry: - %gep = getelementptr i64, ptr addrspace(1) %addr, i32 4 - %val = call <8 x bfloat> @llvm.amdgcn.global.load.tr.v8bf16.p1(ptr addrspace(1) %gep) - store <8 x bfloat> %val, ptr addrspace(1) %use - ret void -} diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.global.load.tr-w64.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.global.load.tr-w64.ll index 7ad1416789de79e6c42fff38c43eb96610b4bc29..a2dc3662fcc4859f91f6abbd2a4b0d51f6157ceb 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.global.load.tr-w64.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.global.load.tr-w64.ll @@ -1,132 +1,44 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -global-isel=0 -mtriple=amdgcn -mcpu=gfx1200 -verify-machineinstrs -mattr=-wavefrontsize32,+wavefrontsize64 < %s | FileCheck -check-prefixes=GFX12-SDAG-W64 %s -; RUN: llc -global-isel=1 -mtriple=amdgcn -mcpu=gfx1200 -verify-machineinstrs -mattr=-wavefrontsize32,+wavefrontsize64 < %s | FileCheck -check-prefixes=GFX12-GISEL-W64 %s +; RUN: llc -global-isel=0 -mtriple=amdgcn -mcpu=gfx1200 -verify-machineinstrs -mattr=-wavefrontsize32,+wavefrontsize64 < %s | FileCheck -check-prefix=GFX12 %s +; RUN: llc -global-isel=1 -mtriple=amdgcn -mcpu=gfx1200 -verify-machineinstrs -mattr=-wavefrontsize32,+wavefrontsize64 < %s | FileCheck -check-prefix=GFX12 %s -declare i32 @llvm.amdgcn.global.load.tr.i32.p1(ptr addrspace(1)) -declare <4 x i16> @llvm.amdgcn.global.load.tr.v4i16.p1(ptr addrspace(1)) -declare <4 x half> @llvm.amdgcn.global.load.tr.v4f16.p1(ptr addrspace(1)) -declare <4 x bfloat> @llvm.amdgcn.global.load.tr.v4bf16.p1(ptr addrspace(1)) +declare i32 @llvm.amdgcn.global.load.tr.b64.i32.p1(ptr addrspace(1)) +declare <4 x i16> @llvm.amdgcn.global.load.tr.b128.v4i16.p1(ptr addrspace(1)) define amdgpu_kernel void @global_load_tr_b64(ptr addrspace(1) %addr, ptr addrspace(1) %use) { -; GFX12-SDAG-W64-LABEL: global_load_tr_b64: -; GFX12-SDAG-W64: ; %bb.0: ; %entry -; GFX12-SDAG-W64-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 -; GFX12-SDAG-W64-NEXT: v_mov_b32_e32 v0, 0 -; GFX12-SDAG-W64-NEXT: s_wait_kmcnt 0x0 -; GFX12-SDAG-W64-NEXT: global_load_tr_b64 v1, v0, s[0:1] offset:32 -; GFX12-SDAG-W64-NEXT: s_wait_loadcnt 0x0 -; GFX12-SDAG-W64-NEXT: global_store_b32 v0, v1, s[2:3] -; GFX12-SDAG-W64-NEXT: s_nop 0 -; GFX12-SDAG-W64-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) -; GFX12-SDAG-W64-NEXT: s_endpgm -; -; GFX12-GISEL-W64-LABEL: global_load_tr_b64: -; GFX12-GISEL-W64: ; %bb.0: ; %entry -; GFX12-GISEL-W64-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 -; GFX12-GISEL-W64-NEXT: v_mov_b32_e32 v0, 0 -; GFX12-GISEL-W64-NEXT: s_wait_kmcnt 0x0 -; GFX12-GISEL-W64-NEXT: global_load_tr_b64 v1, v0, s[0:1] offset:32 -; GFX12-GISEL-W64-NEXT: s_wait_loadcnt 0x0 -; GFX12-GISEL-W64-NEXT: global_store_b32 v0, v1, s[2:3] -; GFX12-GISEL-W64-NEXT: s_nop 0 -; GFX12-GISEL-W64-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) -; GFX12-GISEL-W64-NEXT: s_endpgm +; GFX12-LABEL: global_load_tr_b64: +; GFX12: ; %bb.0: ; %entry +; GFX12-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 +; GFX12-NEXT: v_mov_b32_e32 v0, 0 +; GFX12-NEXT: s_wait_kmcnt 0x0 +; GFX12-NEXT: global_load_tr_b64 v1, v0, s[0:1] offset:32 +; GFX12-NEXT: s_wait_loadcnt 0x0 +; GFX12-NEXT: global_store_b32 v0, v1, s[2:3] +; GFX12-NEXT: s_nop 0 +; GFX12-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) +; GFX12-NEXT: s_endpgm entry: %gep = getelementptr i64, ptr addrspace(1) %addr, i32 4 - %val = call i32 @llvm.amdgcn.global.load.tr.i32.p1(ptr addrspace(1) %gep) + %val = call i32 @llvm.amdgcn.global.load.tr.b64.i32.p1(ptr addrspace(1) %gep) store i32 %val, ptr addrspace(1) %use ret void } -define amdgpu_kernel void @global_load_tr_b128_i16(ptr addrspace(1) %addr, ptr addrspace(1) %use) { -; GFX12-SDAG-W64-LABEL: global_load_tr_b128_i16: -; GFX12-SDAG-W64: ; %bb.0: ; %entry -; GFX12-SDAG-W64-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 -; GFX12-SDAG-W64-NEXT: v_mov_b32_e32 v2, 0 -; GFX12-SDAG-W64-NEXT: s_wait_kmcnt 0x0 -; GFX12-SDAG-W64-NEXT: global_load_tr_b128 v[0:1], v2, s[0:1] offset:32 -; GFX12-SDAG-W64-NEXT: s_wait_loadcnt 0x0 -; GFX12-SDAG-W64-NEXT: global_store_b64 v2, v[0:1], s[2:3] -; GFX12-SDAG-W64-NEXT: s_nop 0 -; GFX12-SDAG-W64-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) -; GFX12-SDAG-W64-NEXT: s_endpgm -; -; GFX12-GISEL-W64-LABEL: global_load_tr_b128_i16: -; GFX12-GISEL-W64: ; %bb.0: ; %entry -; GFX12-GISEL-W64-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 -; GFX12-GISEL-W64-NEXT: v_mov_b32_e32 v2, 0 -; GFX12-GISEL-W64-NEXT: s_wait_kmcnt 0x0 -; GFX12-GISEL-W64-NEXT: global_load_tr_b128 v[0:1], v2, s[0:1] offset:32 -; GFX12-GISEL-W64-NEXT: s_wait_loadcnt 0x0 -; GFX12-GISEL-W64-NEXT: global_store_b64 v2, v[0:1], s[2:3] -; GFX12-GISEL-W64-NEXT: s_nop 0 -; GFX12-GISEL-W64-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) -; GFX12-GISEL-W64-NEXT: s_endpgm +define amdgpu_kernel void @global_load_tr_b128(ptr addrspace(1) %addr, ptr addrspace(1) %use) { +; GFX12-LABEL: global_load_tr_b128: +; GFX12: ; %bb.0: ; %entry +; GFX12-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 +; GFX12-NEXT: v_mov_b32_e32 v2, 0 +; GFX12-NEXT: s_wait_kmcnt 0x0 +; GFX12-NEXT: global_load_tr_b128 v[0:1], v2, s[0:1] offset:32 +; GFX12-NEXT: s_wait_loadcnt 0x0 +; GFX12-NEXT: global_store_b64 v2, v[0:1], s[2:3] +; GFX12-NEXT: s_nop 0 +; GFX12-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) +; GFX12-NEXT: s_endpgm entry: %gep = getelementptr i64, ptr addrspace(1) %addr, i32 4 - %val = call <4 x i16> @llvm.amdgcn.global.load.tr.v4i16.p1(ptr addrspace(1) %gep) + %val = call <4 x i16> @llvm.amdgcn.global.load.tr.b128.v4i16.p1(ptr addrspace(1) %gep) store <4 x i16> %val, ptr addrspace(1) %use ret void } - -define amdgpu_kernel void @global_load_tr_b128_half(ptr addrspace(1) %addr, ptr addrspace(1) %use) { -; GFX12-SDAG-W64-LABEL: global_load_tr_b128_half: -; GFX12-SDAG-W64: ; %bb.0: ; %entry -; GFX12-SDAG-W64-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 -; GFX12-SDAG-W64-NEXT: v_mov_b32_e32 v2, 0 -; GFX12-SDAG-W64-NEXT: s_wait_kmcnt 0x0 -; GFX12-SDAG-W64-NEXT: global_load_tr_b128 v[0:1], v2, s[0:1] offset:32 -; GFX12-SDAG-W64-NEXT: s_wait_loadcnt 0x0 -; GFX12-SDAG-W64-NEXT: global_store_b64 v2, v[0:1], s[2:3] -; GFX12-SDAG-W64-NEXT: s_nop 0 -; GFX12-SDAG-W64-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) -; GFX12-SDAG-W64-NEXT: s_endpgm -; -; GFX12-GISEL-W64-LABEL: global_load_tr_b128_half: -; GFX12-GISEL-W64: ; %bb.0: ; %entry -; GFX12-GISEL-W64-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 -; GFX12-GISEL-W64-NEXT: v_mov_b32_e32 v2, 0 -; GFX12-GISEL-W64-NEXT: s_wait_kmcnt 0x0 -; GFX12-GISEL-W64-NEXT: global_load_tr_b128 v[0:1], v2, s[0:1] offset:32 -; GFX12-GISEL-W64-NEXT: s_wait_loadcnt 0x0 -; GFX12-GISEL-W64-NEXT: global_store_b64 v2, v[0:1], s[2:3] -; GFX12-GISEL-W64-NEXT: s_nop 0 -; GFX12-GISEL-W64-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) -; GFX12-GISEL-W64-NEXT: s_endpgm -entry: - %gep = getelementptr i64, ptr addrspace(1) %addr, i32 4 - %val = call <4 x half> @llvm.amdgcn.global.load.tr.v4f16.p1(ptr addrspace(1) %gep) - store <4 x half> %val, ptr addrspace(1) %use - ret void -} - -define amdgpu_kernel void @global_load_tr_b128_bfloat(ptr addrspace(1) %addr, ptr addrspace(1) %use) { -; GFX12-SDAG-W64-LABEL: global_load_tr_b128_bfloat: -; GFX12-SDAG-W64: ; %bb.0: ; %entry -; GFX12-SDAG-W64-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 -; GFX12-SDAG-W64-NEXT: v_mov_b32_e32 v2, 0 -; GFX12-SDAG-W64-NEXT: s_wait_kmcnt 0x0 -; GFX12-SDAG-W64-NEXT: global_load_tr_b128 v[0:1], v2, s[0:1] offset:32 -; GFX12-SDAG-W64-NEXT: s_wait_loadcnt 0x0 -; GFX12-SDAG-W64-NEXT: global_store_b64 v2, v[0:1], s[2:3] -; GFX12-SDAG-W64-NEXT: s_nop 0 -; GFX12-SDAG-W64-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) -; GFX12-SDAG-W64-NEXT: s_endpgm -; -; GFX12-GISEL-W64-LABEL: global_load_tr_b128_bfloat: -; GFX12-GISEL-W64: ; %bb.0: ; %entry -; GFX12-GISEL-W64-NEXT: s_load_b128 s[0:3], s[0:1], 0x24 -; GFX12-GISEL-W64-NEXT: v_mov_b32_e32 v2, 0 -; GFX12-GISEL-W64-NEXT: s_wait_kmcnt 0x0 -; GFX12-GISEL-W64-NEXT: global_load_tr_b128 v[0:1], v2, s[0:1] offset:32 -; GFX12-GISEL-W64-NEXT: s_wait_loadcnt 0x0 -; GFX12-GISEL-W64-NEXT: global_store_b64 v2, v[0:1], s[2:3] -; GFX12-GISEL-W64-NEXT: s_nop 0 -; GFX12-GISEL-W64-NEXT: s_sendmsg sendmsg(MSG_DEALLOC_VGPRS) -; GFX12-GISEL-W64-NEXT: s_endpgm -entry: - %gep = getelementptr i64, ptr addrspace(1) %addr, i32 4 - %val = call <4 x bfloat> @llvm.amdgcn.global.load.tr.v4bf16.p1(ptr addrspace(1) %gep) - store <4 x bfloat> %val, ptr addrspace(1) %use - ret void -} diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.iglp.opt.single.2b.mir b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.iglp.opt.single.2b.mir index 091b29c23d60e2dc6635e71baaea52efc8d6be67..e93595b9ef273557baa0ca924697fde57b5e31da 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.iglp.opt.single.2b.mir +++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.iglp.opt.single.2b.mir @@ -4,6 +4,8 @@ --- | define amdgpu_kernel void @single-wave-phase-2b(ptr addrspace(3) noalias %in0, ptr addrspace(3) noalias %in1, ptr addrspace(3) noalias %in2, ptr addrspace(3) noalias %in3, ptr addrspace(3) noalias %in4, ptr addrspace(3) noalias %in5, ptr addrspace(3) noalias %in6, ptr addrspace(3) noalias %in7, ptr addrspace(3) noalias %in8, ptr addrspace(3) noalias %in9, ptr addrspace(3) noalias %in10, ptr addrspace(3) noalias %in11, ptr addrspace(7) noalias %in12, ptr addrspace(7) noalias %in13, ptr addrspace(7) noalias %in14, ptr addrspace(7) noalias %in15, ptr addrspace(7) noalias %in16, ptr addrspace(7) noalias %in17, ptr addrspace(7) noalias %in18, ptr addrspace(7) noalias %in19, ptr addrspace(7) noalias %in20, ptr addrspace(7) noalias %in21, ptr addrspace(7) noalias %in22, ptr addrspace(7) noalias %in23, ptr addrspace(7) noalias %in24, ptr addrspace(7) noalias %in25, ptr addrspace(7) noalias %in26, ptr addrspace(7) noalias %in27, ptr addrspace(7) noalias %in28, ptr addrspace(7) noalias %in29) #0 { ret void } + attributes #0 = { nounwind "amdgpu-waves-per-eu"="1,1" "amdgpu-flat-work-group-size"="1,256" } + !0 = distinct !{!0} !1 = !{!1, !0} ... diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.image.msaa.load.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.image.msaa.load.ll index 1348315e72e7bc3c3a795ad8437765c3be026534..7b1f55e7eebac006859960d608c7e1408f494f86 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.image.msaa.load.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.image.msaa.load.ll @@ -22,18 +22,36 @@ main_body: define amdgpu_ps <4 x float> @load_2dmsaa_both(<8 x i32> inreg %rsrc, ptr addrspace(1) inreg %out, i32 %s, i32 %t, i32 %fragid) { ; GFX11-LABEL: load_2dmsaa_both: ; GFX11: ; %bb.0: ; %main_body -; GFX11-NEXT: image_msaa_load v[0:4], v[0:2], s[0:7] dmask:0x2 dim:SQ_RSRC_IMG_2D_MSAA unorm tfe lwe ; encoding: [0x98,0x02,0x60,0xf0,0x00,0x00,0x60,0x00] -; GFX11-NEXT: v_mov_b32_e32 v5, 0 ; encoding: [0x80,0x02,0x0a,0x7e] +; GFX11-NEXT: v_dual_mov_b32 v5, v0 :: v_dual_mov_b32 v8, 0 ; encoding: [0x00,0x01,0x10,0xca,0x80,0x00,0x08,0x05] +; GFX11-NEXT: v_dual_mov_b32 v7, v2 :: v_dual_mov_b32 v6, v1 ; encoding: [0x02,0x01,0x10,0xca,0x01,0x01,0x06,0x07] +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(SKIP_3) | instid1(VALU_DEP_4) ; encoding: [0x42,0x02,0x87,0xbf] +; GFX11-NEXT: v_mov_b32_e32 v9, v8 ; encoding: [0x08,0x03,0x12,0x7e] +; GFX11-NEXT: v_mov_b32_e32 v10, v8 ; encoding: [0x08,0x03,0x14,0x7e] +; GFX11-NEXT: v_mov_b32_e32 v11, v8 ; encoding: [0x08,0x03,0x16,0x7e] +; GFX11-NEXT: v_mov_b32_e32 v12, v8 ; encoding: [0x08,0x03,0x18,0x7e] +; GFX11-NEXT: v_dual_mov_b32 v0, v8 :: v_dual_mov_b32 v1, v9 ; encoding: [0x08,0x01,0x10,0xca,0x09,0x01,0x00,0x00] +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_3) | instskip(NEXT) | instid1(VALU_DEP_3) ; encoding: [0x93,0x01,0x87,0xbf] +; GFX11-NEXT: v_dual_mov_b32 v2, v10 :: v_dual_mov_b32 v3, v11 ; encoding: [0x0a,0x01,0x10,0xca,0x0b,0x01,0x02,0x02] +; GFX11-NEXT: v_mov_b32_e32 v4, v12 ; encoding: [0x0c,0x03,0x08,0x7e] +; GFX11-NEXT: image_msaa_load v[0:4], v[5:7], s[0:7] dmask:0x2 dim:SQ_RSRC_IMG_2D_MSAA unorm tfe lwe ; encoding: [0x98,0x02,0x60,0xf0,0x05,0x00,0x60,0x00] ; GFX11-NEXT: s_waitcnt vmcnt(0) ; encoding: [0xf7,0x03,0x89,0xbf] -; GFX11-NEXT: global_store_b32 v5, v4, s[8:9] ; encoding: [0x00,0x00,0x6a,0xdc,0x05,0x04,0x08,0x00] +; GFX11-NEXT: global_store_b32 v8, v4, s[8:9] ; encoding: [0x00,0x00,0x6a,0xdc,0x08,0x04,0x08,0x00] ; GFX11-NEXT: ; return to shader part epilog ; ; GFX12-LABEL: load_2dmsaa_both: ; GFX12: ; %bb.0: ; %main_body -; GFX12-NEXT: image_msaa_load v[0:4], [v0, v1, v2], s[0:7] dmask:0x2 dim:SQ_RSRC_IMG_2D_MSAA unorm tfe lwe ; encoding: [0x0e,0x20,0x86,0xe4,0x00,0x01,0x00,0x00,0x00,0x01,0x02,0x00] -; GFX12-NEXT: v_mov_b32_e32 v5, 0 ; encoding: [0x80,0x02,0x0a,0x7e] +; GFX12-NEXT: v_dual_mov_b32 v7, v0 :: v_dual_mov_b32 v8, 0 ; encoding: [0x00,0x01,0x10,0xca,0x80,0x00,0x08,0x07] +; GFX12-NEXT: v_dual_mov_b32 v5, v2 :: v_dual_mov_b32 v6, v1 ; encoding: [0x02,0x01,0x10,0xca,0x01,0x01,0x06,0x05] +; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(SKIP_1) | instid1(VALU_DEP_2) ; encoding: [0x22,0x01,0x87,0xbf] +; GFX12-NEXT: v_dual_mov_b32 v9, v8 :: v_dual_mov_b32 v10, v8 ; encoding: [0x08,0x01,0x10,0xca,0x08,0x01,0x0a,0x09] +; GFX12-NEXT: v_dual_mov_b32 v11, v8 :: v_dual_mov_b32 v12, v8 ; encoding: [0x08,0x01,0x10,0xca,0x08,0x01,0x0c,0x0b] +; GFX12-NEXT: v_dual_mov_b32 v0, v8 :: v_dual_mov_b32 v1, v9 ; encoding: [0x08,0x01,0x10,0xca,0x09,0x01,0x00,0x00] +; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_3) ; encoding: [0x92,0x01,0x87,0xbf] +; GFX12-NEXT: v_dual_mov_b32 v2, v10 :: v_dual_mov_b32 v3, v11 ; encoding: [0x0a,0x01,0x10,0xca,0x0b,0x01,0x02,0x02] +; GFX12-NEXT: v_mov_b32_e32 v4, v12 ; encoding: [0x0c,0x03,0x08,0x7e] +; GFX12-NEXT: image_msaa_load v[0:4], [v7, v6, v5], s[0:7] dmask:0x2 dim:SQ_RSRC_IMG_2D_MSAA unorm tfe lwe ; encoding: [0x0e,0x20,0x86,0xe4,0x00,0x01,0x00,0x00,0x07,0x06,0x05,0x00] ; GFX12-NEXT: s_wait_loadcnt 0x0 ; encoding: [0x00,0x00,0xc0,0xbf] -; GFX12-NEXT: global_store_b32 v5, v4, s[8:9] ; encoding: [0x08,0x80,0x06,0xee,0x00,0x00,0x00,0x02,0x05,0x00,0x00,0x00] +; GFX12-NEXT: global_store_b32 v8, v4, s[8:9] ; encoding: [0x08,0x80,0x06,0xee,0x00,0x00,0x00,0x02,0x08,0x00,0x00,0x00] ; GFX12-NEXT: ; return to shader part epilog main_body: %v = call {<4 x float>,i32} @llvm.amdgcn.image.msaa.load.2dmsaa.v4f32i32.i32(i32 2, i32 %s, i32 %t, i32 %fragid, <8 x i32> %rsrc, i32 3, i32 0) @@ -63,18 +81,37 @@ main_body: define amdgpu_ps <4 x float> @load_2darraymsaa_tfe(<8 x i32> inreg %rsrc, ptr addrspace(1) inreg %out, i32 %s, i32 %t, i32 %slice, i32 %fragid) { ; GFX11-LABEL: load_2darraymsaa_tfe: ; GFX11: ; %bb.0: ; %main_body -; GFX11-NEXT: image_msaa_load v[0:4], v[0:3], s[0:7] dmask:0x8 dim:SQ_RSRC_IMG_2D_MSAA_ARRAY unorm tfe ; encoding: [0x9c,0x08,0x60,0xf0,0x00,0x00,0x20,0x00] -; GFX11-NEXT: v_mov_b32_e32 v5, 0 ; encoding: [0x80,0x02,0x0a,0x7e] +; GFX11-NEXT: v_dual_mov_b32 v9, 0 :: v_dual_mov_b32 v8, v3 ; encoding: [0x80,0x00,0x10,0xca,0x03,0x01,0x08,0x09] +; GFX11-NEXT: v_dual_mov_b32 v7, v2 :: v_dual_mov_b32 v6, v1 ; encoding: [0x02,0x01,0x10,0xca,0x01,0x01,0x06,0x07] +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(SKIP_3) | instid1(VALU_DEP_4) ; encoding: [0x42,0x02,0x87,0xbf] +; GFX11-NEXT: v_dual_mov_b32 v5, v0 :: v_dual_mov_b32 v10, v9 ; encoding: [0x00,0x01,0x10,0xca,0x09,0x01,0x0a,0x05] +; GFX11-NEXT: v_mov_b32_e32 v11, v9 ; encoding: [0x09,0x03,0x16,0x7e] +; GFX11-NEXT: v_mov_b32_e32 v12, v9 ; encoding: [0x09,0x03,0x18,0x7e] +; GFX11-NEXT: v_mov_b32_e32 v13, v9 ; encoding: [0x09,0x03,0x1a,0x7e] +; GFX11-NEXT: v_dual_mov_b32 v0, v9 :: v_dual_mov_b32 v1, v10 ; encoding: [0x09,0x01,0x10,0xca,0x0a,0x01,0x00,0x00] +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_3) | instskip(NEXT) | instid1(VALU_DEP_3) ; encoding: [0x93,0x01,0x87,0xbf] +; GFX11-NEXT: v_dual_mov_b32 v2, v11 :: v_dual_mov_b32 v3, v12 ; encoding: [0x0b,0x01,0x10,0xca,0x0c,0x01,0x02,0x02] +; GFX11-NEXT: v_mov_b32_e32 v4, v13 ; encoding: [0x0d,0x03,0x08,0x7e] +; GFX11-NEXT: image_msaa_load v[0:4], v[5:8], s[0:7] dmask:0x8 dim:SQ_RSRC_IMG_2D_MSAA_ARRAY unorm tfe ; encoding: [0x9c,0x08,0x60,0xf0,0x05,0x00,0x20,0x00] ; GFX11-NEXT: s_waitcnt vmcnt(0) ; encoding: [0xf7,0x03,0x89,0xbf] -; GFX11-NEXT: global_store_b32 v5, v4, s[8:9] ; encoding: [0x00,0x00,0x6a,0xdc,0x05,0x04,0x08,0x00] +; GFX11-NEXT: global_store_b32 v9, v4, s[8:9] ; encoding: [0x00,0x00,0x6a,0xdc,0x09,0x04,0x08,0x00] ; GFX11-NEXT: ; return to shader part epilog ; ; GFX12-LABEL: load_2darraymsaa_tfe: ; GFX12: ; %bb.0: ; %main_body -; GFX12-NEXT: image_msaa_load v[0:4], [v0, v1, v2, v3], s[0:7] dmask:0x8 dim:SQ_RSRC_IMG_2D_MSAA_ARRAY unorm tfe ; encoding: [0x0f,0x20,0x06,0xe6,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03] -; GFX12-NEXT: v_mov_b32_e32 v5, 0 ; encoding: [0x80,0x02,0x0a,0x7e] +; GFX12-NEXT: v_mov_b32_e32 v9, 0 ; encoding: [0x80,0x02,0x12,0x7e] +; GFX12-NEXT: v_dual_mov_b32 v5, v3 :: v_dual_mov_b32 v6, v2 ; encoding: [0x03,0x01,0x10,0xca,0x02,0x01,0x06,0x05] +; GFX12-NEXT: v_dual_mov_b32 v7, v1 :: v_dual_mov_b32 v8, v0 ; encoding: [0x01,0x01,0x10,0xca,0x00,0x01,0x08,0x07] +; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_3) | instskip(SKIP_1) | instid1(VALU_DEP_2) ; encoding: [0x23,0x01,0x87,0xbf] +; GFX12-NEXT: v_dual_mov_b32 v10, v9 :: v_dual_mov_b32 v11, v9 ; encoding: [0x09,0x01,0x10,0xca,0x09,0x01,0x0a,0x0a] +; GFX12-NEXT: v_dual_mov_b32 v12, v9 :: v_dual_mov_b32 v13, v9 ; encoding: [0x09,0x01,0x10,0xca,0x09,0x01,0x0c,0x0c] +; GFX12-NEXT: v_dual_mov_b32 v0, v9 :: v_dual_mov_b32 v1, v10 ; encoding: [0x09,0x01,0x10,0xca,0x0a,0x01,0x00,0x00] +; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_3) ; encoding: [0x92,0x01,0x87,0xbf] +; GFX12-NEXT: v_dual_mov_b32 v2, v11 :: v_dual_mov_b32 v3, v12 ; encoding: [0x0b,0x01,0x10,0xca,0x0c,0x01,0x02,0x02] +; GFX12-NEXT: v_mov_b32_e32 v4, v13 ; encoding: [0x0d,0x03,0x08,0x7e] +; GFX12-NEXT: image_msaa_load v[0:4], [v8, v7, v6, v5], s[0:7] dmask:0x8 dim:SQ_RSRC_IMG_2D_MSAA_ARRAY unorm tfe ; encoding: [0x0f,0x20,0x06,0xe6,0x00,0x00,0x00,0x00,0x08,0x07,0x06,0x05] ; GFX12-NEXT: s_wait_loadcnt 0x0 ; encoding: [0x00,0x00,0xc0,0xbf] -; GFX12-NEXT: global_store_b32 v5, v4, s[8:9] ; encoding: [0x08,0x80,0x06,0xee,0x00,0x00,0x00,0x02,0x05,0x00,0x00,0x00] +; GFX12-NEXT: global_store_b32 v9, v4, s[8:9] ; encoding: [0x08,0x80,0x06,0xee,0x00,0x00,0x00,0x02,0x09,0x00,0x00,0x00] ; GFX12-NEXT: ; return to shader part epilog main_body: %v = call {<4 x float>,i32} @llvm.amdgcn.image.msaa.load.2darraymsaa.v4f32i32.i32(i32 8, i32 %s, i32 %t, i32 %slice, i32 %fragid, <8 x i32> %rsrc, i32 1, i32 0) @@ -155,18 +192,31 @@ main_body: define amdgpu_ps <4 x half> @load_2dmsaa_tfe_d16(<8 x i32> inreg %rsrc, ptr addrspace(1) inreg %out, i32 %s, i32 %t, i32 %fragid) { ; GFX11-LABEL: load_2dmsaa_tfe_d16: ; GFX11: ; %bb.0: ; %main_body -; GFX11-NEXT: image_msaa_load v[0:2], v[0:2], s[0:7] dmask:0x1 dim:SQ_RSRC_IMG_2D_MSAA unorm tfe d16 ; encoding: [0x98,0x01,0x62,0xf0,0x00,0x00,0x20,0x00] -; GFX11-NEXT: v_mov_b32_e32 v3, 0 ; encoding: [0x80,0x02,0x06,0x7e] +; GFX11-NEXT: v_dual_mov_b32 v3, v0 :: v_dual_mov_b32 v6, 0 ; encoding: [0x00,0x01,0x10,0xca,0x80,0x00,0x06,0x03] +; GFX11-NEXT: v_dual_mov_b32 v5, v2 :: v_dual_mov_b32 v4, v1 ; encoding: [0x02,0x01,0x10,0xca,0x01,0x01,0x04,0x05] +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(SKIP_1) | instid1(VALU_DEP_2) ; encoding: [0x22,0x01,0x87,0xbf] +; GFX11-NEXT: v_mov_b32_e32 v7, v6 ; encoding: [0x06,0x03,0x0e,0x7e] +; GFX11-NEXT: v_mov_b32_e32 v8, v6 ; encoding: [0x06,0x03,0x10,0x7e] +; GFX11-NEXT: v_dual_mov_b32 v0, v6 :: v_dual_mov_b32 v1, v7 ; encoding: [0x06,0x01,0x10,0xca,0x07,0x01,0x00,0x00] +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_2) ; encoding: [0x02,0x00,0x87,0xbf] +; GFX11-NEXT: v_mov_b32_e32 v2, v8 ; encoding: [0x08,0x03,0x04,0x7e] +; GFX11-NEXT: image_msaa_load v[0:2], v[3:5], s[0:7] dmask:0x1 dim:SQ_RSRC_IMG_2D_MSAA unorm tfe d16 ; encoding: [0x98,0x01,0x62,0xf0,0x03,0x00,0x20,0x00] ; GFX11-NEXT: s_waitcnt vmcnt(0) ; encoding: [0xf7,0x03,0x89,0xbf] -; GFX11-NEXT: global_store_b32 v3, v2, s[8:9] ; encoding: [0x00,0x00,0x6a,0xdc,0x03,0x02,0x08,0x00] +; GFX11-NEXT: global_store_b32 v6, v2, s[8:9] ; encoding: [0x00,0x00,0x6a,0xdc,0x06,0x02,0x08,0x00] ; GFX11-NEXT: ; return to shader part epilog ; ; GFX12-LABEL: load_2dmsaa_tfe_d16: ; GFX12: ; %bb.0: ; %main_body -; GFX12-NEXT: image_msaa_load v[0:2], [v0, v1, v2], s[0:7] dmask:0x1 dim:SQ_RSRC_IMG_2D_MSAA unorm tfe d16 ; encoding: [0x2e,0x20,0x46,0xe4,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x00] -; GFX12-NEXT: v_mov_b32_e32 v3, 0 ; encoding: [0x80,0x02,0x06,0x7e] +; GFX12-NEXT: v_dual_mov_b32 v5, v0 :: v_dual_mov_b32 v6, 0 ; encoding: [0x00,0x01,0x10,0xca,0x80,0x00,0x06,0x05] +; GFX12-NEXT: v_dual_mov_b32 v3, v2 :: v_dual_mov_b32 v4, v1 ; encoding: [0x02,0x01,0x10,0xca,0x01,0x01,0x04,0x03] +; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_1) ; encoding: [0x92,0x00,0x87,0xbf] +; GFX12-NEXT: v_dual_mov_b32 v7, v6 :: v_dual_mov_b32 v8, v6 ; encoding: [0x06,0x01,0x10,0xca,0x06,0x01,0x08,0x07] +; GFX12-NEXT: v_dual_mov_b32 v0, v6 :: v_dual_mov_b32 v1, v7 ; encoding: [0x06,0x01,0x10,0xca,0x07,0x01,0x00,0x00] +; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_2) ; encoding: [0x02,0x00,0x87,0xbf] +; GFX12-NEXT: v_mov_b32_e32 v2, v8 ; encoding: [0x08,0x03,0x04,0x7e] +; GFX12-NEXT: image_msaa_load v[0:2], [v5, v4, v3], s[0:7] dmask:0x1 dim:SQ_RSRC_IMG_2D_MSAA unorm tfe d16 ; encoding: [0x2e,0x20,0x46,0xe4,0x00,0x00,0x00,0x00,0x05,0x04,0x03,0x00] ; GFX12-NEXT: s_wait_loadcnt 0x0 ; encoding: [0x00,0x00,0xc0,0xbf] -; GFX12-NEXT: global_store_b32 v3, v2, s[8:9] ; encoding: [0x08,0x80,0x06,0xee,0x00,0x00,0x00,0x01,0x03,0x00,0x00,0x00] +; GFX12-NEXT: global_store_b32 v6, v2, s[8:9] ; encoding: [0x08,0x80,0x06,0xee,0x00,0x00,0x00,0x01,0x06,0x00,0x00,0x00] ; GFX12-NEXT: ; return to shader part epilog main_body: %v = call {<4 x half>,i32} @llvm.amdgcn.image.msaa.load.2dmsaa.v4f16i32.i32(i32 1, i32 %s, i32 %t, i32 %fragid, <8 x i32> %rsrc, i32 1, i32 0) @@ -196,18 +246,31 @@ main_body: define amdgpu_ps <4 x half> @load_2darraymsaa_tfe_d16(<8 x i32> inreg %rsrc, ptr addrspace(1) inreg %out, i32 %s, i32 %t, i32 %slice, i32 %fragid) { ; GFX11-LABEL: load_2darraymsaa_tfe_d16: ; GFX11: ; %bb.0: ; %main_body -; GFX11-NEXT: image_msaa_load v[0:2], v[0:3], s[0:7] dmask:0x1 dim:SQ_RSRC_IMG_2D_MSAA_ARRAY unorm tfe d16 ; encoding: [0x9c,0x01,0x62,0xf0,0x00,0x00,0x20,0x00] -; GFX11-NEXT: v_mov_b32_e32 v3, 0 ; encoding: [0x80,0x02,0x06,0x7e] +; GFX11-NEXT: v_dual_mov_b32 v6, v0 :: v_dual_mov_b32 v7, 0 ; encoding: [0x00,0x01,0x10,0xca,0x80,0x00,0x06,0x06] +; GFX11-NEXT: v_dual_mov_b32 v4, v2 :: v_dual_mov_b32 v5, v1 ; encoding: [0x02,0x01,0x10,0xca,0x01,0x01,0x04,0x04] +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(SKIP_1) | instid1(VALU_DEP_2) ; encoding: [0x22,0x01,0x87,0xbf] +; GFX11-NEXT: v_mov_b32_e32 v8, v7 ; encoding: [0x07,0x03,0x10,0x7e] +; GFX11-NEXT: v_mov_b32_e32 v9, v7 ; encoding: [0x07,0x03,0x12,0x7e] +; GFX11-NEXT: v_dual_mov_b32 v0, v7 :: v_dual_mov_b32 v1, v8 ; encoding: [0x07,0x01,0x10,0xca,0x08,0x01,0x00,0x00] +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_2) ; encoding: [0x02,0x00,0x87,0xbf] +; GFX11-NEXT: v_mov_b32_e32 v2, v9 ; encoding: [0x09,0x03,0x04,0x7e] +; GFX11-NEXT: image_msaa_load v[0:2], [v6, v5, v4, v3], s[0:7] dmask:0x1 dim:SQ_RSRC_IMG_2D_MSAA_ARRAY unorm tfe d16 ; encoding: [0x9d,0x01,0x62,0xf0,0x06,0x00,0x20,0x00,0x05,0x04,0x03,0x00] ; GFX11-NEXT: s_waitcnt vmcnt(0) ; encoding: [0xf7,0x03,0x89,0xbf] -; GFX11-NEXT: global_store_b32 v3, v2, s[8:9] ; encoding: [0x00,0x00,0x6a,0xdc,0x03,0x02,0x08,0x00] +; GFX11-NEXT: global_store_b32 v7, v2, s[8:9] ; encoding: [0x00,0x00,0x6a,0xdc,0x07,0x02,0x08,0x00] ; GFX11-NEXT: ; return to shader part epilog ; ; GFX12-LABEL: load_2darraymsaa_tfe_d16: ; GFX12: ; %bb.0: ; %main_body -; GFX12-NEXT: image_msaa_load v[0:2], [v0, v1, v2, v3], s[0:7] dmask:0x1 dim:SQ_RSRC_IMG_2D_MSAA_ARRAY unorm tfe d16 ; encoding: [0x2f,0x20,0x46,0xe4,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03] -; GFX12-NEXT: v_mov_b32_e32 v3, 0 ; encoding: [0x80,0x02,0x06,0x7e] +; GFX12-NEXT: v_dual_mov_b32 v6, v0 :: v_dual_mov_b32 v7, 0 ; encoding: [0x00,0x01,0x10,0xca,0x80,0x00,0x06,0x06] +; GFX12-NEXT: v_dual_mov_b32 v4, v2 :: v_dual_mov_b32 v5, v1 ; encoding: [0x02,0x01,0x10,0xca,0x01,0x01,0x04,0x04] +; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_1) ; encoding: [0x92,0x00,0x87,0xbf] +; GFX12-NEXT: v_dual_mov_b32 v8, v7 :: v_dual_mov_b32 v9, v7 ; encoding: [0x07,0x01,0x10,0xca,0x07,0x01,0x08,0x08] +; GFX12-NEXT: v_dual_mov_b32 v0, v7 :: v_dual_mov_b32 v1, v8 ; encoding: [0x07,0x01,0x10,0xca,0x08,0x01,0x00,0x00] +; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_2) ; encoding: [0x02,0x00,0x87,0xbf] +; GFX12-NEXT: v_mov_b32_e32 v2, v9 ; encoding: [0x09,0x03,0x04,0x7e] +; GFX12-NEXT: image_msaa_load v[0:2], [v6, v5, v4, v3], s[0:7] dmask:0x1 dim:SQ_RSRC_IMG_2D_MSAA_ARRAY unorm tfe d16 ; encoding: [0x2f,0x20,0x46,0xe4,0x00,0x00,0x00,0x00,0x06,0x05,0x04,0x03] ; GFX12-NEXT: s_wait_loadcnt 0x0 ; encoding: [0x00,0x00,0xc0,0xbf] -; GFX12-NEXT: global_store_b32 v3, v2, s[8:9] ; encoding: [0x08,0x80,0x06,0xee,0x00,0x00,0x00,0x01,0x03,0x00,0x00,0x00] +; GFX12-NEXT: global_store_b32 v7, v2, s[8:9] ; encoding: [0x08,0x80,0x06,0xee,0x00,0x00,0x00,0x01,0x07,0x00,0x00,0x00] ; GFX12-NEXT: ; return to shader part epilog main_body: %v = call {<4 x half>,i32} @llvm.amdgcn.image.msaa.load.2darraymsaa.v4f16i32.i32(i32 1, i32 %s, i32 %t, i32 %slice, i32 %fragid, <8 x i32> %rsrc, i32 1, i32 0) diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.interp.inreg.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.interp.inreg.ll index 429528e9091d13263ff6f64e1ba3c94fc29df94e..e3dd036ecc3083dc771c338285362d538f0ed086 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.interp.inreg.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.interp.inreg.ll @@ -147,6 +147,34 @@ main_body: ret half %res } +define amdgpu_ps half @v_interp_rtz_f16(float inreg %i, float inreg %j, i32 inreg %m0) #0 { +; GCN-LABEL: v_interp_rtz_f16: +; GCN: ; %bb.0: ; %main_body +; GCN-NEXT: s_mov_b32 s3, exec_lo +; GCN-NEXT: s_wqm_b32 exec_lo, exec_lo +; GCN-NEXT: s_mov_b32 m0, s2 +; GCN-NEXT: lds_param_load v1, attr0.x wait_vdst:15 +; GCN-NEXT: s_mov_b32 exec_lo, s3 +; GCN-NEXT: v_mov_b32_e32 v0, s0 +; GCN-NEXT: v_mov_b32_e32 v2, s1 +; GCN-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(SKIP_1) | instid1(VALU_DEP_2) +; GCN-NEXT: v_interp_p10_rtz_f16_f32 v3, v1, v0, v1 wait_exp:0 +; GCN-NEXT: v_interp_p10_rtz_f16_f32 v0, v1, v0, v1 op_sel:[1,0,1,0] wait_exp:7 +; GCN-NEXT: v_interp_p2_rtz_f16_f32 v3, v1, v2, v3 wait_exp:7 +; GCN-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_1) +; GCN-NEXT: v_interp_p2_rtz_f16_f32 v0, v1, v2, v0 op_sel:[1,0,0,0] wait_exp:7 +; GCN-NEXT: v_add_f16_e32 v0, v3, v0 +; GCN-NEXT: ; return to shader part epilog +main_body: + %p0 = call float @llvm.amdgcn.lds.param.load(i32 0, i32 0, i32 %m0) + %l_p0 = call float @llvm.amdgcn.interp.p10.rtz.f16(float %p0, float %i, float %p0, i1 0) + %l_p1 = call half @llvm.amdgcn.interp.p2.rtz.f16(float %p0, float %j, float %l_p0, i1 0) + %h_p0 = call float @llvm.amdgcn.interp.p10.rtz.f16(float %p0, float %i, float %p0, i1 1) + %h_p1 = call half @llvm.amdgcn.interp.p2.rtz.f16(float %p0, float %j, float %h_p0, i1 1) + %res = fadd half %l_p1, %h_p1 + ret half %res +} + define amdgpu_ps half @v_interp_f16_imm_params(float inreg %i, float inreg %j) #0 { ; GCN-LABEL: v_interp_f16_imm_params: ; GCN: ; %bb.0: ; %main_body @@ -172,6 +200,8 @@ declare float @llvm.amdgcn.interp.inreg.p10(float, float, float) #0 declare float @llvm.amdgcn.interp.inreg.p2(float, float, float) #0 declare float @llvm.amdgcn.interp.inreg.p10.f16(float, float, float, i1) #0 declare half @llvm.amdgcn.interp.inreg.p2.f16(float, float, float, i1) #0 +declare float @llvm.amdgcn.interp.p10.rtz.f16(float, float, float, i1) #0 +declare half @llvm.amdgcn.interp.p2.rtz.f16(float, float, float, i1) #0 declare void @llvm.amdgcn.exp.f32(i32, i32, float, float, float, float, i1, i1) #0 declare void @llvm.amdgcn.exp.f16(i32, i32, float, float, float, float, i1, i1) #0 diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.sched.group.barrier.gfx12.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.sched.group.barrier.gfx12.ll new file mode 100644 index 0000000000000000000000000000000000000000..fdcb1773d0a3f496c32a576b4d31911bf35ef243 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.sched.group.barrier.gfx12.ll @@ -0,0 +1,333 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=amdgcn -mcpu=gfx1200 -misched-cluster=0 < %s | FileCheck -check-prefix=GCN %s +; RUN: llc -mtriple=amdgcn -mcpu=gfx1200 -misched-cluster=0 -amdgpu-igrouplp-exact-solver-max-branches=250000 < %s | FileCheck -check-prefix=EXACTCUTOFF %s + +declare <8 x half> @llvm.amdgcn.swmmac.f16.16x16x32.f16.v8f16.v8f16.v16f16..i16(<8 x half>, <16 x half>, <8 x half>, i16) + +define amdgpu_kernel void @test_sched_group_barrier_pipeline_SWMMAC_cluster(ptr addrspace(3) noalias %in, ptr addrspace(3) noalias %out) #0 { +; GCN-LABEL: test_sched_group_barrier_pipeline_SWMMAC_cluster: +; GCN: ; %bb.0: ; %entry +; GCN-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GCN-NEXT: v_lshlrev_b32_e32 v28, 4, v0 +; GCN-NEXT: v_mov_b32_e32 v48, 0 +; GCN-NEXT: s_wait_kmcnt 0x0 +; GCN-NEXT: s_delay_alu instid0(VALU_DEP_2) +; GCN-NEXT: v_add_nc_u32_e32 v0, s0, v28 +; GCN-NEXT: v_dual_mov_b32 v50, s1 :: v_dual_add_nc_u32 v49, s1, v28 +; GCN-NEXT: ds_load_b128 v[8:11], v0 +; GCN-NEXT: ds_load_b128 v[12:15], v0 offset:512 +; GCN-NEXT: ds_load_b128 v[16:19], v0 offset:1536 +; GCN-NEXT: ds_load_b128 v[20:23], v0 offset:3072 +; GCN-NEXT: ds_load_b128 v[24:27], v0 offset:5120 +; GCN-NEXT: ds_load_b128 v[4:7], v0 offset:11280 +; GCN-NEXT: ds_load_b128 v[0:3], v0 offset:11264 +; GCN-NEXT: ; sched_group_barrier mask(0x00000100) size(7) SyncID(0) +; GCN-NEXT: s_wait_dscnt 0x6 +; GCN-NEXT: v_mov_b32_e32 v31, v11 +; GCN-NEXT: s_wait_dscnt 0x5 +; GCN-NEXT: v_mov_b32_e32 v35, v15 +; GCN-NEXT: s_wait_dscnt 0x4 +; GCN-NEXT: v_mov_b32_e32 v39, v19 +; GCN-NEXT: s_wait_dscnt 0x3 +; GCN-NEXT: v_mov_b32_e32 v43, v23 +; GCN-NEXT: s_wait_dscnt 0x2 +; GCN-NEXT: v_dual_mov_b32 v47, v27 :: v_dual_mov_b32 v30, v10 +; GCN-NEXT: v_dual_mov_b32 v29, v9 :: v_dual_mov_b32 v28, v8 +; GCN-NEXT: v_dual_mov_b32 v34, v14 :: v_dual_mov_b32 v33, v13 +; GCN-NEXT: v_mov_b32_e32 v32, v12 +; GCN-NEXT: v_dual_mov_b32 v38, v18 :: v_dual_mov_b32 v37, v17 +; GCN-NEXT: v_mov_b32_e32 v36, v16 +; GCN-NEXT: v_dual_mov_b32 v42, v22 :: v_dual_mov_b32 v41, v21 +; GCN-NEXT: v_mov_b32_e32 v40, v20 +; GCN-NEXT: v_dual_mov_b32 v46, v26 :: v_dual_mov_b32 v45, v25 +; GCN-NEXT: v_mov_b32_e32 v44, v24 +; GCN-NEXT: s_wait_dscnt 0x0 +; GCN-NEXT: v_swmmac_f16_16x16x32_f16 v[28:31], v[8:11], v[0:7], v48 +; GCN-NEXT: v_swmmac_f16_16x16x32_f16 v[32:35], v[12:15], v[0:7], v48 +; GCN-NEXT: v_swmmac_f16_16x16x32_f16 v[36:39], v[16:19], v[0:7], v48 +; GCN-NEXT: v_swmmac_f16_16x16x32_f16 v[40:43], v[20:23], v[0:7], v48 +; GCN-NEXT: v_swmmac_f16_16x16x32_f16 v[44:47], v[24:27], v[0:7], v48 +; GCN-NEXT: ds_store_b128 v49, v[28:31] +; GCN-NEXT: ds_store_b128 v50, v[32:35] offset:512 +; GCN-NEXT: ds_store_b128 v50, v[36:39] offset:1024 +; GCN-NEXT: ds_store_b128 v50, v[40:43] offset:1536 +; GCN-NEXT: ds_store_b128 v50, v[44:47] offset:2048 +; GCN-NEXT: ; sched_group_barrier mask(0x00000008) size(5) SyncID(0) +; GCN-NEXT: ; sched_group_barrier mask(0x00000200) size(5) SyncID(0) +; GCN-NEXT: s_endpgm +; +; EXACTCUTOFF-LABEL: test_sched_group_barrier_pipeline_SWMMAC_cluster: +; EXACTCUTOFF: ; %bb.0: ; %entry +; EXACTCUTOFF-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; EXACTCUTOFF-NEXT: v_lshlrev_b32_e32 v28, 4, v0 +; EXACTCUTOFF-NEXT: v_mov_b32_e32 v48, 0 +; EXACTCUTOFF-NEXT: s_wait_kmcnt 0x0 +; EXACTCUTOFF-NEXT: s_delay_alu instid0(VALU_DEP_2) +; EXACTCUTOFF-NEXT: v_add_nc_u32_e32 v0, s0, v28 +; EXACTCUTOFF-NEXT: v_dual_mov_b32 v50, s1 :: v_dual_add_nc_u32 v49, s1, v28 +; EXACTCUTOFF-NEXT: ds_load_b128 v[8:11], v0 +; EXACTCUTOFF-NEXT: ds_load_b128 v[12:15], v0 offset:512 +; EXACTCUTOFF-NEXT: ds_load_b128 v[16:19], v0 offset:1536 +; EXACTCUTOFF-NEXT: ds_load_b128 v[20:23], v0 offset:3072 +; EXACTCUTOFF-NEXT: ds_load_b128 v[24:27], v0 offset:5120 +; EXACTCUTOFF-NEXT: ds_load_b128 v[4:7], v0 offset:11280 +; EXACTCUTOFF-NEXT: ds_load_b128 v[0:3], v0 offset:11264 +; EXACTCUTOFF-NEXT: ; sched_group_barrier mask(0x00000100) size(7) SyncID(0) +; EXACTCUTOFF-NEXT: s_wait_dscnt 0x6 +; EXACTCUTOFF-NEXT: v_mov_b32_e32 v31, v11 +; EXACTCUTOFF-NEXT: s_wait_dscnt 0x5 +; EXACTCUTOFF-NEXT: v_mov_b32_e32 v35, v15 +; EXACTCUTOFF-NEXT: s_wait_dscnt 0x4 +; EXACTCUTOFF-NEXT: v_mov_b32_e32 v39, v19 +; EXACTCUTOFF-NEXT: s_wait_dscnt 0x3 +; EXACTCUTOFF-NEXT: v_mov_b32_e32 v43, v23 +; EXACTCUTOFF-NEXT: s_wait_dscnt 0x2 +; EXACTCUTOFF-NEXT: v_dual_mov_b32 v47, v27 :: v_dual_mov_b32 v30, v10 +; EXACTCUTOFF-NEXT: v_dual_mov_b32 v29, v9 :: v_dual_mov_b32 v28, v8 +; EXACTCUTOFF-NEXT: v_dual_mov_b32 v34, v14 :: v_dual_mov_b32 v33, v13 +; EXACTCUTOFF-NEXT: v_mov_b32_e32 v32, v12 +; EXACTCUTOFF-NEXT: v_dual_mov_b32 v38, v18 :: v_dual_mov_b32 v37, v17 +; EXACTCUTOFF-NEXT: v_mov_b32_e32 v36, v16 +; EXACTCUTOFF-NEXT: v_dual_mov_b32 v42, v22 :: v_dual_mov_b32 v41, v21 +; EXACTCUTOFF-NEXT: v_mov_b32_e32 v40, v20 +; EXACTCUTOFF-NEXT: v_dual_mov_b32 v46, v26 :: v_dual_mov_b32 v45, v25 +; EXACTCUTOFF-NEXT: v_mov_b32_e32 v44, v24 +; EXACTCUTOFF-NEXT: s_wait_dscnt 0x0 +; EXACTCUTOFF-NEXT: v_swmmac_f16_16x16x32_f16 v[28:31], v[8:11], v[0:7], v48 +; EXACTCUTOFF-NEXT: v_swmmac_f16_16x16x32_f16 v[32:35], v[12:15], v[0:7], v48 +; EXACTCUTOFF-NEXT: v_swmmac_f16_16x16x32_f16 v[36:39], v[16:19], v[0:7], v48 +; EXACTCUTOFF-NEXT: v_swmmac_f16_16x16x32_f16 v[40:43], v[20:23], v[0:7], v48 +; EXACTCUTOFF-NEXT: v_swmmac_f16_16x16x32_f16 v[44:47], v[24:27], v[0:7], v48 +; EXACTCUTOFF-NEXT: ds_store_b128 v49, v[28:31] +; EXACTCUTOFF-NEXT: ds_store_b128 v50, v[32:35] offset:512 +; EXACTCUTOFF-NEXT: ds_store_b128 v50, v[36:39] offset:1024 +; EXACTCUTOFF-NEXT: ds_store_b128 v50, v[40:43] offset:1536 +; EXACTCUTOFF-NEXT: ds_store_b128 v50, v[44:47] offset:2048 +; EXACTCUTOFF-NEXT: ; sched_group_barrier mask(0x00000008) size(5) SyncID(0) +; EXACTCUTOFF-NEXT: ; sched_group_barrier mask(0x00000200) size(5) SyncID(0) +; EXACTCUTOFF-NEXT: s_endpgm +entry: + %idx = call i32 @llvm.amdgcn.workitem.id.x() + %load.0.addr = getelementptr <8 x half>, ptr addrspace(3) %in, i32 %idx + %load.0 = load <8 x half>, ptr addrspace(3) %load.0.addr + %load.1.addr = getelementptr <8 x half>, ptr addrspace(3) %load.0.addr, i32 32 + %load.1 = load <8 x half>, ptr addrspace(3) %load.1.addr + %load.2.addr = getelementptr <8 x half>, ptr addrspace(3) %load.1.addr, i32 64 + %load.2 = load <8 x half>, ptr addrspace(3) %load.2.addr + %load.3.addr = getelementptr <8 x half>, ptr addrspace(3) %load.2.addr, i32 96 + %load.3 = load <8 x half>, ptr addrspace(3) %load.3.addr + %load.4.addr = getelementptr <8 x half>, ptr addrspace(3) %load.3.addr, i32 128 + %load.4 = load <8 x half>, ptr addrspace(3) %load.4.addr + %load.b.addr = getelementptr <16 x half>, ptr addrspace(3) %load.4.addr, i32 192 + %load.b = load <16 x half>, ptr addrspace(3) %load.b.addr + %mai.0 = call <8 x half> @llvm.amdgcn.swmmac.f16.16x16x32.f16.v8f16.v8f16.v16f16.i16(<8 x half> %load.0, <16 x half> %load.b, <8 x half> %load.0, i1 0) + %mai.1 = call <8 x half> @llvm.amdgcn.swmmac.f16.16x16x32.f16.v8f16.v8f16.v16f16.i16(<8 x half> %load.1, <16 x half> %load.b, <8 x half> %load.1, i1 0) + %mai.2 = call <8 x half> @llvm.amdgcn.swmmac.f16.16x16x32.f16.v8f16.v8f16.v16f16.i16(<8 x half> %load.2, <16 x half> %load.b, <8 x half> %load.2, i1 0) + %mai.3 = call <8 x half> @llvm.amdgcn.swmmac.f16.16x16x32.f16.v8f16.v8f16.v16f16.i16(<8 x half> %load.3, <16 x half> %load.b, <8 x half> %load.3, i1 0) + %mai.4 = call <8 x half> @llvm.amdgcn.swmmac.f16.16x16x32.f16.v8f16.v8f16.v16f16.i16(<8 x half> %load.4, <16 x half> %load.b, <8 x half> %load.4, i1 0) + %store.0.addr = getelementptr <8 x half>, ptr addrspace(3) %out, i32 %idx + store <8 x half> %mai.0, ptr addrspace(3) %store.0.addr + %store.1.addr = getelementptr <8 x half>, ptr addrspace(3) %out, i32 32 + store <8 x half> %mai.1, ptr addrspace(3) %store.1.addr + %store.2.addr = getelementptr <8 x half>, ptr addrspace(3) %out, i32 64 + store <8 x half> %mai.2, ptr addrspace(3) %store.2.addr + %store.3.addr = getelementptr <8 x half>, ptr addrspace(3) %out, i32 96 + store <8 x half> %mai.3, ptr addrspace(3) %store.3.addr + %store.4.addr = getelementptr <8 x half>, ptr addrspace(3) %out, i32 128 + store <8 x half> %mai.4, ptr addrspace(3) %store.4.addr + ; 7 DS read + call void @llvm.amdgcn.sched.group.barrier(i32 256, i32 7, i32 0) + ; 5 SWMMAC + call void @llvm.amdgcn.sched.group.barrier(i32 8, i32 5, i32 0) + ; 5 DS write + call void @llvm.amdgcn.sched.group.barrier(i32 512, i32 5, i32 0) + ret void +} + +define amdgpu_kernel void @test_sched_group_barrier_pipeline_SWMMAC_interleaved(ptr addrspace(3) noalias %in, ptr addrspace(3) noalias %out) #0 { +; GCN-LABEL: test_sched_group_barrier_pipeline_SWMMAC_interleaved: +; GCN: ; %bb.0: ; %entry +; GCN-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; GCN-NEXT: v_mov_b32_e32 v18, 0 +; GCN-NEXT: s_wait_kmcnt 0x0 +; GCN-NEXT: v_lshl_add_u32 v17, v0, 5, s0 +; GCN-NEXT: v_lshl_add_u32 v0, v0, 4, s1 +; GCN-NEXT: ds_load_b128 v[9:12], v17 offset:1024 +; GCN-NEXT: ds_load_b128 v[1:4], v17 +; GCN-NEXT: ds_load_b128 v[5:8], v17 offset:16 +; GCN-NEXT: ; sched_group_barrier mask(0x00000100) size(3) SyncID(0) +; GCN-NEXT: s_wait_dscnt 0x2 +; GCN-NEXT: v_dual_mov_b32 v16, v12 :: v_dual_mov_b32 v15, v11 +; GCN-NEXT: v_dual_mov_b32 v14, v10 :: v_dual_mov_b32 v13, v9 +; GCN-NEXT: s_wait_dscnt 0x0 +; GCN-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GCN-NEXT: v_swmmac_f16_16x16x32_f16 v[13:16], v[9:12], v[1:8], v18 +; GCN-NEXT: ; sched_group_barrier mask(0x00000008) size(1) SyncID(0) +; GCN-NEXT: ds_store_b128 v0, v[13:16] +; GCN-NEXT: ds_load_b128 v[9:12], v17 offset:2560 +; GCN-NEXT: v_mov_b32_e32 v0, s1 +; GCN-NEXT: ; sched_group_barrier mask(0x00000200) size(1) SyncID(0) +; GCN-NEXT: ; sched_group_barrier mask(0x00000100) size(1) SyncID(0) +; GCN-NEXT: s_wait_dscnt 0x0 +; GCN-NEXT: v_dual_mov_b32 v16, v12 :: v_dual_mov_b32 v15, v11 +; GCN-NEXT: v_dual_mov_b32 v14, v10 :: v_dual_mov_b32 v13, v9 +; GCN-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GCN-NEXT: v_swmmac_f16_16x16x32_f16 v[13:16], v[9:12], v[1:8], v18 +; GCN-NEXT: ; sched_group_barrier mask(0x00000008) size(1) SyncID(0) +; GCN-NEXT: ds_store_b128 v0, v[13:16] offset:512 +; GCN-NEXT: ds_load_b128 v[9:12], v17 offset:4608 +; GCN-NEXT: ; sched_group_barrier mask(0x00000200) size(1) SyncID(0) +; GCN-NEXT: ; sched_group_barrier mask(0x00000100) size(1) SyncID(0) +; GCN-NEXT: s_wait_dscnt 0x0 +; GCN-NEXT: v_dual_mov_b32 v16, v12 :: v_dual_mov_b32 v15, v11 +; GCN-NEXT: v_dual_mov_b32 v14, v10 :: v_dual_mov_b32 v13, v9 +; GCN-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GCN-NEXT: v_swmmac_f16_16x16x32_f16 v[13:16], v[9:12], v[1:8], v18 +; GCN-NEXT: ; sched_group_barrier mask(0x00000008) size(1) SyncID(0) +; GCN-NEXT: ds_store_b128 v0, v[13:16] offset:1024 +; GCN-NEXT: ds_load_b128 v[9:12], v17 offset:7168 +; GCN-NEXT: ; sched_group_barrier mask(0x00000200) size(1) SyncID(0) +; GCN-NEXT: ; sched_group_barrier mask(0x00000100) size(1) SyncID(0) +; GCN-NEXT: s_wait_dscnt 0x0 +; GCN-NEXT: v_dual_mov_b32 v16, v12 :: v_dual_mov_b32 v15, v11 +; GCN-NEXT: v_dual_mov_b32 v14, v10 :: v_dual_mov_b32 v13, v9 +; GCN-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GCN-NEXT: v_swmmac_f16_16x16x32_f16 v[13:16], v[9:12], v[1:8], v18 +; GCN-NEXT: ; sched_group_barrier mask(0x00000008) size(1) SyncID(0) +; GCN-NEXT: ds_store_b128 v0, v[13:16] offset:1536 +; GCN-NEXT: ds_load_b128 v[9:12], v17 offset:10240 +; GCN-NEXT: ; sched_group_barrier mask(0x00000200) size(1) SyncID(0) +; GCN-NEXT: ; sched_group_barrier mask(0x00000100) size(1) SyncID(0) +; GCN-NEXT: s_wait_dscnt 0x0 +; GCN-NEXT: v_dual_mov_b32 v16, v12 :: v_dual_mov_b32 v15, v11 +; GCN-NEXT: v_dual_mov_b32 v14, v10 :: v_dual_mov_b32 v13, v9 +; GCN-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GCN-NEXT: v_swmmac_f16_16x16x32_f16 v[13:16], v[9:12], v[1:8], v18 +; GCN-NEXT: ; sched_group_barrier mask(0x00000008) size(1) SyncID(0) +; GCN-NEXT: ds_store_b128 v0, v[13:16] offset:2048 +; GCN-NEXT: ; sched_group_barrier mask(0x00000200) size(1) SyncID(0) +; GCN-NEXT: s_endpgm +; +; EXACTCUTOFF-LABEL: test_sched_group_barrier_pipeline_SWMMAC_interleaved: +; EXACTCUTOFF: ; %bb.0: ; %entry +; EXACTCUTOFF-NEXT: s_load_b64 s[0:1], s[0:1], 0x24 +; EXACTCUTOFF-NEXT: v_mov_b32_e32 v18, 0 +; EXACTCUTOFF-NEXT: s_wait_kmcnt 0x0 +; EXACTCUTOFF-NEXT: v_lshl_add_u32 v17, v0, 5, s0 +; EXACTCUTOFF-NEXT: v_lshl_add_u32 v0, v0, 4, s1 +; EXACTCUTOFF-NEXT: ds_load_b128 v[9:12], v17 offset:1024 +; EXACTCUTOFF-NEXT: ds_load_b128 v[1:4], v17 +; EXACTCUTOFF-NEXT: ds_load_b128 v[5:8], v17 offset:16 +; EXACTCUTOFF-NEXT: ; sched_group_barrier mask(0x00000100) size(3) SyncID(0) +; EXACTCUTOFF-NEXT: s_wait_dscnt 0x2 +; EXACTCUTOFF-NEXT: v_dual_mov_b32 v16, v12 :: v_dual_mov_b32 v15, v11 +; EXACTCUTOFF-NEXT: v_dual_mov_b32 v14, v10 :: v_dual_mov_b32 v13, v9 +; EXACTCUTOFF-NEXT: s_wait_dscnt 0x0 +; EXACTCUTOFF-NEXT: s_delay_alu instid0(VALU_DEP_1) +; EXACTCUTOFF-NEXT: v_swmmac_f16_16x16x32_f16 v[13:16], v[9:12], v[1:8], v18 +; EXACTCUTOFF-NEXT: ; sched_group_barrier mask(0x00000008) size(1) SyncID(0) +; EXACTCUTOFF-NEXT: ds_store_b128 v0, v[13:16] +; EXACTCUTOFF-NEXT: ds_load_b128 v[9:12], v17 offset:2560 +; EXACTCUTOFF-NEXT: v_mov_b32_e32 v0, s1 +; EXACTCUTOFF-NEXT: ; sched_group_barrier mask(0x00000200) size(1) SyncID(0) +; EXACTCUTOFF-NEXT: ; sched_group_barrier mask(0x00000100) size(1) SyncID(0) +; EXACTCUTOFF-NEXT: s_wait_dscnt 0x0 +; EXACTCUTOFF-NEXT: v_dual_mov_b32 v16, v12 :: v_dual_mov_b32 v15, v11 +; EXACTCUTOFF-NEXT: v_dual_mov_b32 v14, v10 :: v_dual_mov_b32 v13, v9 +; EXACTCUTOFF-NEXT: s_delay_alu instid0(VALU_DEP_1) +; EXACTCUTOFF-NEXT: v_swmmac_f16_16x16x32_f16 v[13:16], v[9:12], v[1:8], v18 +; EXACTCUTOFF-NEXT: ; sched_group_barrier mask(0x00000008) size(1) SyncID(0) +; EXACTCUTOFF-NEXT: ds_store_b128 v0, v[13:16] offset:512 +; EXACTCUTOFF-NEXT: ds_load_b128 v[9:12], v17 offset:4608 +; EXACTCUTOFF-NEXT: ; sched_group_barrier mask(0x00000200) size(1) SyncID(0) +; EXACTCUTOFF-NEXT: ; sched_group_barrier mask(0x00000100) size(1) SyncID(0) +; EXACTCUTOFF-NEXT: s_wait_dscnt 0x0 +; EXACTCUTOFF-NEXT: v_dual_mov_b32 v16, v12 :: v_dual_mov_b32 v15, v11 +; EXACTCUTOFF-NEXT: v_dual_mov_b32 v14, v10 :: v_dual_mov_b32 v13, v9 +; EXACTCUTOFF-NEXT: s_delay_alu instid0(VALU_DEP_1) +; EXACTCUTOFF-NEXT: v_swmmac_f16_16x16x32_f16 v[13:16], v[9:12], v[1:8], v18 +; EXACTCUTOFF-NEXT: ; sched_group_barrier mask(0x00000008) size(1) SyncID(0) +; EXACTCUTOFF-NEXT: ds_store_b128 v0, v[13:16] offset:1024 +; EXACTCUTOFF-NEXT: ds_load_b128 v[9:12], v17 offset:7168 +; EXACTCUTOFF-NEXT: ; sched_group_barrier mask(0x00000200) size(1) SyncID(0) +; EXACTCUTOFF-NEXT: ; sched_group_barrier mask(0x00000100) size(1) SyncID(0) +; EXACTCUTOFF-NEXT: s_wait_dscnt 0x0 +; EXACTCUTOFF-NEXT: v_dual_mov_b32 v16, v12 :: v_dual_mov_b32 v15, v11 +; EXACTCUTOFF-NEXT: v_dual_mov_b32 v14, v10 :: v_dual_mov_b32 v13, v9 +; EXACTCUTOFF-NEXT: s_delay_alu instid0(VALU_DEP_1) +; EXACTCUTOFF-NEXT: v_swmmac_f16_16x16x32_f16 v[13:16], v[9:12], v[1:8], v18 +; EXACTCUTOFF-NEXT: ; sched_group_barrier mask(0x00000008) size(1) SyncID(0) +; EXACTCUTOFF-NEXT: ds_store_b128 v0, v[13:16] offset:1536 +; EXACTCUTOFF-NEXT: ds_load_b128 v[9:12], v17 offset:10240 +; EXACTCUTOFF-NEXT: ; sched_group_barrier mask(0x00000200) size(1) SyncID(0) +; EXACTCUTOFF-NEXT: ; sched_group_barrier mask(0x00000100) size(1) SyncID(0) +; EXACTCUTOFF-NEXT: s_wait_dscnt 0x0 +; EXACTCUTOFF-NEXT: v_dual_mov_b32 v16, v12 :: v_dual_mov_b32 v15, v11 +; EXACTCUTOFF-NEXT: v_dual_mov_b32 v14, v10 :: v_dual_mov_b32 v13, v9 +; EXACTCUTOFF-NEXT: s_delay_alu instid0(VALU_DEP_1) +; EXACTCUTOFF-NEXT: v_swmmac_f16_16x16x32_f16 v[13:16], v[9:12], v[1:8], v18 +; EXACTCUTOFF-NEXT: ; sched_group_barrier mask(0x00000008) size(1) SyncID(0) +; EXACTCUTOFF-NEXT: ds_store_b128 v0, v[13:16] offset:2048 +; EXACTCUTOFF-NEXT: ; sched_group_barrier mask(0x00000200) size(1) SyncID(0) +; EXACTCUTOFF-NEXT: s_endpgm +entry: + %idx = call i32 @llvm.amdgcn.workitem.id.x() + %load.b.addr = getelementptr <16 x half>, ptr addrspace(3) %in, i32 %idx + %load.b = load <16 x half>, ptr addrspace(3) %load.b.addr + %load.0.addr = getelementptr <8 x half>, ptr addrspace(3) %load.b.addr, i32 64 + %load.0 = load <8 x half>, ptr addrspace(3) %load.0.addr + %load.1.addr = getelementptr <8 x half>, ptr addrspace(3) %load.0.addr, i32 96 + %load.1 = load <8 x half>, ptr addrspace(3) %load.1.addr + %load.2.addr = getelementptr <8 x half>, ptr addrspace(3) %load.1.addr, i32 128 + %load.2 = load <8 x half>, ptr addrspace(3) %load.2.addr + %load.3.addr = getelementptr <8 x half>, ptr addrspace(3) %load.2.addr, i32 160 + %load.3 = load <8 x half>, ptr addrspace(3) %load.3.addr + %load.4.addr = getelementptr <8 x half>, ptr addrspace(3) %load.3.addr, i32 192 + %load.4 = load <8 x half>, ptr addrspace(3) %load.4.addr + %mai.0 = call <8 x half> @llvm.amdgcn.swmmac.f16.16x16x32.f16.v8f16.v8f16.v16f16.i16(<8 x half> %load.0, <16 x half> %load.b, <8 x half> %load.0, i1 0) + %mai.1 = call <8 x half> @llvm.amdgcn.swmmac.f16.16x16x32.f16.v8f16.v8f16.v16f16.i16(<8 x half> %load.1, <16 x half> %load.b, <8 x half> %load.1, i1 0) + %mai.2 = call <8 x half> @llvm.amdgcn.swmmac.f16.16x16x32.f16.v8f16.v8f16.v16f16.i16(<8 x half> %load.2, <16 x half> %load.b, <8 x half> %load.2, i1 0) + %mai.3 = call <8 x half> @llvm.amdgcn.swmmac.f16.16x16x32.f16.v8f16.v8f16.v16f16.i16(<8 x half> %load.3, <16 x half> %load.b, <8 x half> %load.3, i1 0) + %mai.4 = call <8 x half> @llvm.amdgcn.swmmac.f16.16x16x32.f16.v8f16.v8f16.v16f16.i16(<8 x half> %load.4, <16 x half> %load.b, <8 x half> %load.4, i1 0) + %store.0.addr = getelementptr <8 x half>, ptr addrspace(3) %out, i32 %idx + store <8 x half> %mai.0, ptr addrspace(3) %store.0.addr + %store.1.addr = getelementptr <8 x half>, ptr addrspace(3) %out, i32 32 + store <8 x half> %mai.1, ptr addrspace(3) %store.1.addr + %store.2.addr = getelementptr <8 x half>, ptr addrspace(3) %out, i32 64 + store <8 x half> %mai.2, ptr addrspace(3) %store.2.addr + %store.3.addr = getelementptr <8 x half>, ptr addrspace(3) %out, i32 96 + store <8 x half> %mai.3, ptr addrspace(3) %store.3.addr + %store.4.addr = getelementptr <8 x half>, ptr addrspace(3) %out, i32 128 + store <8 x half> %mai.4, ptr addrspace(3) %store.4.addr + ; 3 DS read + call void @llvm.amdgcn.sched.group.barrier(i32 256, i32 3, i32 0) + ; 1 SWMMAC + call void @llvm.amdgcn.sched.group.barrier(i32 8, i32 1, i32 0) + ; 1 DS write + call void @llvm.amdgcn.sched.group.barrier(i32 512, i32 1, i32 0) + ; 1 DS read + call void @llvm.amdgcn.sched.group.barrier(i32 256, i32 1, i32 0) + ; 1 SWMMAC + call void @llvm.amdgcn.sched.group.barrier(i32 8, i32 1, i32 0) + ; 1 DS write + call void @llvm.amdgcn.sched.group.barrier(i32 512, i32 1, i32 0) + ; 1 DS read + call void @llvm.amdgcn.sched.group.barrier(i32 256, i32 1, i32 0) + ; 1 SWMMAC + call void @llvm.amdgcn.sched.group.barrier(i32 8, i32 1, i32 0) + ; 1 DS write + call void @llvm.amdgcn.sched.group.barrier(i32 512, i32 1, i32 0) + ; 1 DS read + call void @llvm.amdgcn.sched.group.barrier(i32 256, i32 1, i32 0) + ; 1 SWMMAC + call void @llvm.amdgcn.sched.group.barrier(i32 8, i32 1, i32 0) + ; 1 DS write + call void @llvm.amdgcn.sched.group.barrier(i32 512, i32 1, i32 0) + ; 1 DS read + call void @llvm.amdgcn.sched.group.barrier(i32 256, i32 1, i32 0) + ; 1 SWMMAC + call void @llvm.amdgcn.sched.group.barrier(i32 8, i32 1, i32 0) + ; 1 DS write + call void @llvm.amdgcn.sched.group.barrier(i32 512, i32 1, i32 0) + ret void +} diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.buffer.load.format.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.buffer.load.format.ll index 00be32b06de0582d1b544b8eaed877564702a6b1..ba3d306cc0cfdafd7787ffbd3e62b296e6f69577 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.buffer.load.format.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.buffer.load.format.ll @@ -2,6 +2,7 @@ ;RUN: llc < %s -mtriple=amdgcn -mcpu=verde -verify-machineinstrs | FileCheck --check-prefixes=GFX6 %s ;RUN: llc < %s -mtriple=amdgcn -mcpu=tonga -verify-machineinstrs | FileCheck --check-prefixes=GFX8PLUS %s ;RUN: llc < %s -mtriple=amdgcn -mcpu=gfx1100 -verify-machineinstrs | FileCheck --check-prefixes=GFX11 %s +;RUN: llc < %s -mtriple=amdgcn -mcpu=gfx1100 -mattr=-enable-prt-strict-null -verify-machineinstrs | FileCheck --check-prefixes=NOPRT %s ;RUN: llc < %s -mtriple=amdgcn -mcpu=gfx1200 -verify-machineinstrs | FileCheck --check-prefixes=GFX12,GFX12-SDAG %s ;RUN: llc < %s -global-isel -mtriple=amdgcn -mcpu=gfx1200 -verify-machineinstrs | FileCheck --check-prefixes=GFX12,GFX12-GISEL %s @@ -34,6 +35,16 @@ define amdgpu_ps {<4 x float>, <4 x float>, <4 x float>} @buffer_load(<4 x i32> ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: v_mov_b32_e32 v8, 0 +; NOPRT-NEXT: s_clause 0x2 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v8, s[0:3], 0 idxen +; NOPRT-NEXT: buffer_load_format_xyzw v[4:7], v8, s[0:3], 0 idxen glc +; NOPRT-NEXT: buffer_load_format_xyzw v[8:11], v8, s[0:3], 0 idxen slc +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load: ; GFX12: ; %bb.0: ; %main_body ; GFX12-NEXT: v_mov_b32_e32 v8, 0 @@ -75,6 +86,13 @@ define amdgpu_ps <4 x float> @buffer_load_immoffs(<4 x i32> inreg) { ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_immoffs: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: v_mov_b32_e32 v0, 0 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v0, s[0:3], 0 idxen offset:42 +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_immoffs: ; GFX12: ; %bb.0: ; %main_body ; GFX12-NEXT: v_mov_b32_e32 v0, 0 @@ -146,6 +164,25 @@ define amdgpu_ps <4 x float> @buffer_load_immoffs_large(<4 x i32> inreg) { ; GFX11-NEXT: v_add_f32_e32 v2, v10, v2 ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_immoffs_large: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: v_mov_b32_e32 v8, 0 +; NOPRT-NEXT: s_movk_i32 s4, 0x7ffc +; NOPRT-NEXT: s_clause 0x1 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v8, s[0:3], 60 idxen offset:4092 +; NOPRT-NEXT: buffer_load_format_xyzw v[4:7], v8, s[0:3], s4 idxen offset:4092 +; NOPRT-NEXT: s_mov_b32 s4, 0x8ffc +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: v_add_f32_e32 v1, v1, v5 +; NOPRT-NEXT: buffer_load_format_xyzw v[8:11], v8, s[0:3], s4 idxen offset:4 +; NOPRT-NEXT: v_dual_add_f32 v0, v0, v4 :: v_dual_add_f32 v3, v3, v7 +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: v_dual_add_f32 v2, v2, v6 :: v_dual_add_f32 v1, v9, v1 +; NOPRT-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) +; NOPRT-NEXT: v_dual_add_f32 v0, v8, v0 :: v_dual_add_f32 v3, v11, v3 +; NOPRT-NEXT: v_add_f32_e32 v2, v10, v2 +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_immoffs_large: ; GFX12: ; %bb.0: ; %main_body ; GFX12-NEXT: v_mov_b32_e32 v8, 0 @@ -196,6 +233,13 @@ define amdgpu_ps <4 x float> @buffer_load_voffset_large_12bit(<4 x i32> inreg) { ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_voffset_large_12bit: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: v_mov_b32_e32 v0, 0 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v0, s[0:3], 0 idxen offset:4092 +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_voffset_large_12bit: ; GFX12: ; %bb.0: ; %main_body ; GFX12-NEXT: v_mov_b32_e32 v0, 0 @@ -235,6 +279,15 @@ define amdgpu_ps <4 x float> @buffer_load_voffset_large_13bit(<4 x i32> inreg) { ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_voffset_large_13bit: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: s_mov_b32 s4, 0 +; NOPRT-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; NOPRT-NEXT: v_dual_mov_b32 v1, 0x1000 :: v_dual_mov_b32 v0, s4 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen offset:4092 +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_voffset_large_13bit: ; GFX12: ; %bb.0: ; %main_body ; GFX12-NEXT: v_mov_b32_e32 v0, 0 @@ -274,6 +327,15 @@ define amdgpu_ps <4 x float> @buffer_load_voffset_large_16bit(<4 x i32> inreg) { ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_voffset_large_16bit: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: s_mov_b32 s4, 0 +; NOPRT-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; NOPRT-NEXT: v_dual_mov_b32 v1, 0xf000 :: v_dual_mov_b32 v0, s4 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen offset:4092 +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_voffset_large_16bit: ; GFX12: ; %bb.0: ; %main_body ; GFX12-NEXT: v_mov_b32_e32 v0, 0 @@ -313,6 +375,15 @@ define amdgpu_ps <4 x float> @buffer_load_voffset_large_23bit(<4 x i32> inreg) { ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_voffset_large_23bit: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: s_mov_b32 s4, 0 +; NOPRT-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; NOPRT-NEXT: v_dual_mov_b32 v1, 0x7ff000 :: v_dual_mov_b32 v0, s4 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen offset:4092 +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_voffset_large_23bit: ; GFX12: ; %bb.0: ; %main_body ; GFX12-NEXT: v_mov_b32_e32 v0, 0 @@ -352,6 +423,15 @@ define amdgpu_ps <4 x float> @buffer_load_voffset_large_24bit(<4 x i32> inreg) { ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_voffset_large_24bit: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: s_mov_b32 s4, 0 +; NOPRT-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; NOPRT-NEXT: v_dual_mov_b32 v1, 0xfff000 :: v_dual_mov_b32 v0, s4 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen offset:4092 +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-SDAG-LABEL: buffer_load_voffset_large_24bit: ; GFX12-SDAG: ; %bb.0: ; %main_body ; GFX12-SDAG-NEXT: v_dual_mov_b32 v1, 0x800000 :: v_dual_mov_b32 v0, 0 @@ -389,6 +469,12 @@ define amdgpu_ps <4 x float> @buffer_load_idx(<4 x i32> inreg, i32) { ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_idx: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v0, s[0:3], 0 idxen +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_idx: ; GFX12: ; %bb.0: ; %main_body ; GFX12-NEXT: buffer_load_format_xyzw v[0:3], v0, s[0:3], null idxen @@ -427,6 +513,15 @@ define amdgpu_ps <4 x float> @buffer_load_ofs(<4 x i32> inreg, i32) { ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_ofs: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: s_mov_b32 s4, 0 +; NOPRT-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; NOPRT-NEXT: v_dual_mov_b32 v1, v0 :: v_dual_mov_b32 v0, s4 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_ofs: ; GFX12: ; %bb.0: ; %main_body ; GFX12-NEXT: v_dual_mov_b32 v1, v0 :: v_dual_mov_b32 v0, 0 @@ -466,6 +561,15 @@ define amdgpu_ps <4 x float> @buffer_load_ofs_imm(<4 x i32> inreg, i32) { ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_ofs_imm: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: s_mov_b32 s4, 0 +; NOPRT-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; NOPRT-NEXT: v_dual_mov_b32 v1, v0 :: v_dual_mov_b32 v0, s4 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen offset:60 +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_ofs_imm: ; GFX12: ; %bb.0: ; %main_body ; GFX12-NEXT: v_dual_mov_b32 v1, v0 :: v_dual_mov_b32 v0, 0 @@ -497,6 +601,12 @@ define amdgpu_ps <4 x float> @buffer_load_both(<4 x i32> inreg, i32, i32) { ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_both: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_both: ; GFX12: ; %bb.0: ; %main_body ; GFX12-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], null idxen offen @@ -529,6 +639,13 @@ define amdgpu_ps <4 x float> @buffer_load_both_reversed(<4 x i32> inreg, i32, i3 ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_both_reversed: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: v_mov_b32_e32 v2, v0 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v[1:2], s[0:3], 0 idxen offen +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_both_reversed: ; GFX12: ; %bb.0: ; %main_body ; GFX12-NEXT: v_mov_b32_e32 v2, v0 @@ -562,6 +679,13 @@ define amdgpu_ps float @buffer_load_x(<4 x i32> inreg %rsrc) { ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_x: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: v_mov_b32_e32 v0, 0 +; NOPRT-NEXT: buffer_load_format_x v0, v0, s[0:3], 0 idxen +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_x: ; GFX12: ; %bb.0: ; %main_body ; GFX12-NEXT: v_mov_b32_e32 v0, 0 @@ -595,6 +719,13 @@ define amdgpu_ps float @buffer_load_x_i32(<4 x i32> inreg %rsrc) { ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_x_i32: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: v_mov_b32_e32 v0, 0 +; NOPRT-NEXT: buffer_load_format_x v0, v0, s[0:3], 0 idxen +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_x_i32: ; GFX12: ; %bb.0: ; %main_body ; GFX12-NEXT: v_mov_b32_e32 v0, 0 @@ -629,6 +760,13 @@ define amdgpu_ps <2 x float> @buffer_load_xy(<4 x i32> inreg %rsrc) { ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_xy: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: v_mov_b32_e32 v0, 0 +; NOPRT-NEXT: buffer_load_format_xy v[0:1], v0, s[0:3], 0 idxen +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_xy: ; GFX12: ; %bb.0: ; %main_body ; GFX12-NEXT: v_mov_b32_e32 v0, 0 @@ -644,7 +782,12 @@ define amdgpu_cs float @buffer_load_v4i32_tfe(<4 x i32> inreg %rsrc, ptr addrspa ; GFX6-LABEL: buffer_load_v4i32_tfe: ; GFX6: ; %bb.0: ; GFX6-NEXT: v_mov_b32_e32 v2, 0 -; GFX6-NEXT: buffer_load_format_xyzw v[2:6], v2, s[0:3], 0 idxen tfe +; GFX6-NEXT: v_mov_b32_e32 v7, 2 +; GFX6-NEXT: v_mov_b32_e32 v3, v2 +; GFX6-NEXT: v_mov_b32_e32 v4, v2 +; GFX6-NEXT: v_mov_b32_e32 v5, v2 +; GFX6-NEXT: v_mov_b32_e32 v6, v2 +; GFX6-NEXT: buffer_load_format_xyzw v[2:6], v7, s[0:3], 0 idxen tfe ; GFX6-NEXT: s_mov_b32 s2, 0 ; GFX6-NEXT: s_mov_b32 s3, 0xf000 ; GFX6-NEXT: s_mov_b32 s0, s2 @@ -658,7 +801,12 @@ define amdgpu_cs float @buffer_load_v4i32_tfe(<4 x i32> inreg %rsrc, ptr addrspa ; GFX8PLUS-LABEL: buffer_load_v4i32_tfe: ; GFX8PLUS: ; %bb.0: ; GFX8PLUS-NEXT: v_mov_b32_e32 v2, 0 -; GFX8PLUS-NEXT: buffer_load_format_xyzw v[2:6], v2, s[0:3], 0 idxen tfe +; GFX8PLUS-NEXT: v_mov_b32_e32 v7, 2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v3, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v4, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v5, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v6, v2 +; GFX8PLUS-NEXT: buffer_load_format_xyzw v[2:6], v7, s[0:3], 0 idxen tfe ; GFX8PLUS-NEXT: s_waitcnt vmcnt(0) ; GFX8PLUS-NEXT: flat_store_dwordx4 v[0:1], v[2:5] ; GFX8PLUS-NEXT: v_mov_b32_e32 v0, v6 @@ -667,22 +815,40 @@ define amdgpu_cs float @buffer_load_v4i32_tfe(<4 x i32> inreg %rsrc, ptr addrspa ; ; GFX11-LABEL: buffer_load_v4i32_tfe: ; GFX11: ; %bb.0: -; GFX11-NEXT: v_mov_b32_e32 v2, 0 -; GFX11-NEXT: buffer_load_format_xyzw v[2:6], v2, s[0:3], 0 idxen tfe +; GFX11-NEXT: v_dual_mov_b32 v2, 0 :: v_dual_mov_b32 v7, 2 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v3, v2 +; GFX11-NEXT: v_mov_b32_e32 v4, v2 +; GFX11-NEXT: v_mov_b32_e32 v5, v2 +; GFX11-NEXT: v_mov_b32_e32 v6, v2 +; GFX11-NEXT: buffer_load_format_xyzw v[2:6], v7, s[0:3], 0 idxen tfe ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: global_store_b128 v[0:1], v[2:5], off ; GFX11-NEXT: v_mov_b32_e32 v0, v6 ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_v4i32_tfe: +; NOPRT: ; %bb.0: +; NOPRT-NEXT: v_mov_b32_e32 v2, 2 +; NOPRT-NEXT: v_mov_b32_e32 v6, 0 +; NOPRT-NEXT: buffer_load_format_xyzw v[2:6], v2, s[0:3], 0 idxen tfe +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: global_store_b128 v[0:1], v[2:5], off +; NOPRT-NEXT: v_mov_b32_e32 v0, v6 +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_v4i32_tfe: ; GFX12: ; %bb.0: -; GFX12-NEXT: v_mov_b32_e32 v2, 0 -; GFX12-NEXT: buffer_load_format_xyzw v[2:6], v2, s[0:3], null idxen tfe +; GFX12-NEXT: v_dual_mov_b32 v2, 0 :: v_dual_mov_b32 v7, 2 +; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX12-NEXT: v_dual_mov_b32 v3, v2 :: v_dual_mov_b32 v4, v2 +; GFX12-NEXT: v_dual_mov_b32 v5, v2 :: v_dual_mov_b32 v6, v2 +; GFX12-NEXT: buffer_load_format_xyzw v[2:6], v7, s[0:3], null idxen tfe ; GFX12-NEXT: s_wait_loadcnt 0x0 ; GFX12-NEXT: global_store_b128 v[0:1], v[2:5], off ; GFX12-NEXT: v_mov_b32_e32 v0, v6 ; GFX12-NEXT: ; return to shader part epilog - %load = call { <4 x i32>, i32 } @llvm.amdgcn.struct.buffer.load.format.sl_v4i32i32s(<4 x i32> %rsrc, i32 0, i32 0, i32 0, i32 0) + %load = call { <4 x i32>, i32 } @llvm.amdgcn.struct.buffer.load.format.sl_v4i32i32s(<4 x i32> %rsrc, i32 2, i32 0, i32 0, i32 0) %data = extractvalue { <4 x i32>, i32 } %load, 0 store <4 x i32> %data, ptr addrspace(1) %out %status = extractvalue { <4 x i32>, i32 } %load, 1 @@ -694,6 +860,10 @@ define amdgpu_cs float @buffer_load_v4f32_tfe(<4 x i32> inreg %rsrc, ptr addrspa ; GFX6-LABEL: buffer_load_v4f32_tfe: ; GFX6: ; %bb.0: ; GFX6-NEXT: v_mov_b32_e32 v2, 0 +; GFX6-NEXT: v_mov_b32_e32 v3, v2 +; GFX6-NEXT: v_mov_b32_e32 v4, v2 +; GFX6-NEXT: v_mov_b32_e32 v5, v2 +; GFX6-NEXT: v_mov_b32_e32 v6, v2 ; GFX6-NEXT: buffer_load_format_xyzw v[2:6], v2, s[0:3], 0 idxen tfe ; GFX6-NEXT: s_mov_b32 s2, 0 ; GFX6-NEXT: s_mov_b32 s3, 0xf000 @@ -708,6 +878,10 @@ define amdgpu_cs float @buffer_load_v4f32_tfe(<4 x i32> inreg %rsrc, ptr addrspa ; GFX8PLUS-LABEL: buffer_load_v4f32_tfe: ; GFX8PLUS: ; %bb.0: ; GFX8PLUS-NEXT: v_mov_b32_e32 v2, 0 +; GFX8PLUS-NEXT: v_mov_b32_e32 v3, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v4, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v5, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v6, v2 ; GFX8PLUS-NEXT: buffer_load_format_xyzw v[2:6], v2, s[0:3], 0 idxen tfe ; GFX8PLUS-NEXT: s_waitcnt vmcnt(0) ; GFX8PLUS-NEXT: flat_store_dwordx4 v[0:1], v[2:5] @@ -718,15 +892,32 @@ define amdgpu_cs float @buffer_load_v4f32_tfe(<4 x i32> inreg %rsrc, ptr addrspa ; GFX11-LABEL: buffer_load_v4f32_tfe: ; GFX11: ; %bb.0: ; GFX11-NEXT: v_mov_b32_e32 v2, 0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v3, v2 +; GFX11-NEXT: v_mov_b32_e32 v4, v2 +; GFX11-NEXT: v_mov_b32_e32 v5, v2 +; GFX11-NEXT: v_mov_b32_e32 v6, v2 ; GFX11-NEXT: buffer_load_format_xyzw v[2:6], v2, s[0:3], 0 idxen tfe ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: global_store_b128 v[0:1], v[2:5], off ; GFX11-NEXT: v_mov_b32_e32 v0, v6 ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_v4f32_tfe: +; NOPRT: ; %bb.0: +; NOPRT-NEXT: v_mov_b32_e32 v6, 0 +; NOPRT-NEXT: buffer_load_format_xyzw v[2:6], v6, s[0:3], 0 idxen tfe +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: global_store_b128 v[0:1], v[2:5], off +; NOPRT-NEXT: v_mov_b32_e32 v0, v6 +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_v4f32_tfe: ; GFX12: ; %bb.0: ; GFX12-NEXT: v_mov_b32_e32 v2, 0 +; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX12-NEXT: v_dual_mov_b32 v3, v2 :: v_dual_mov_b32 v4, v2 +; GFX12-NEXT: v_dual_mov_b32 v5, v2 :: v_dual_mov_b32 v6, v2 ; GFX12-NEXT: buffer_load_format_xyzw v[2:6], v2, s[0:3], null idxen tfe ; GFX12-NEXT: s_wait_loadcnt 0x0 ; GFX12-NEXT: global_store_b128 v[0:1], v[2:5], off @@ -744,6 +935,9 @@ define amdgpu_cs float @buffer_load_v3i32_tfe(<4 x i32> inreg %rsrc, ptr addrspa ; GFX6-LABEL: buffer_load_v3i32_tfe: ; GFX6: ; %bb.0: ; GFX6-NEXT: v_mov_b32_e32 v2, 0 +; GFX6-NEXT: v_mov_b32_e32 v3, v2 +; GFX6-NEXT: v_mov_b32_e32 v4, v2 +; GFX6-NEXT: v_mov_b32_e32 v5, v2 ; GFX6-NEXT: buffer_load_format_xyz v[2:5], v2, s[0:3], 0 idxen tfe ; GFX6-NEXT: s_mov_b32 s2, 0 ; GFX6-NEXT: s_mov_b32 s3, 0xf000 @@ -759,6 +953,9 @@ define amdgpu_cs float @buffer_load_v3i32_tfe(<4 x i32> inreg %rsrc, ptr addrspa ; GFX8PLUS-LABEL: buffer_load_v3i32_tfe: ; GFX8PLUS: ; %bb.0: ; GFX8PLUS-NEXT: v_mov_b32_e32 v2, 0 +; GFX8PLUS-NEXT: v_mov_b32_e32 v3, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v4, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v5, v2 ; GFX8PLUS-NEXT: buffer_load_format_xyz v[2:5], v2, s[0:3], 0 idxen tfe ; GFX8PLUS-NEXT: s_waitcnt vmcnt(0) ; GFX8PLUS-NEXT: flat_store_dwordx3 v[0:1], v[2:4] @@ -769,15 +966,31 @@ define amdgpu_cs float @buffer_load_v3i32_tfe(<4 x i32> inreg %rsrc, ptr addrspa ; GFX11-LABEL: buffer_load_v3i32_tfe: ; GFX11: ; %bb.0: ; GFX11-NEXT: v_mov_b32_e32 v2, 0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v3, v2 +; GFX11-NEXT: v_mov_b32_e32 v4, v2 +; GFX11-NEXT: v_mov_b32_e32 v5, v2 ; GFX11-NEXT: buffer_load_format_xyz v[2:5], v2, s[0:3], 0 idxen tfe ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: global_store_b96 v[0:1], v[2:4], off ; GFX11-NEXT: v_mov_b32_e32 v0, v5 ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_v3i32_tfe: +; NOPRT: ; %bb.0: +; NOPRT-NEXT: v_mov_b32_e32 v5, 0 +; NOPRT-NEXT: buffer_load_format_xyz v[2:5], v5, s[0:3], 0 idxen tfe +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: global_store_b96 v[0:1], v[2:4], off +; NOPRT-NEXT: v_mov_b32_e32 v0, v5 +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_v3i32_tfe: ; GFX12: ; %bb.0: ; GFX12-NEXT: v_mov_b32_e32 v2, 0 +; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX12-NEXT: v_dual_mov_b32 v3, v2 :: v_dual_mov_b32 v4, v2 +; GFX12-NEXT: v_mov_b32_e32 v5, v2 ; GFX12-NEXT: buffer_load_format_xyz v[2:5], v2, s[0:3], null idxen tfe ; GFX12-NEXT: s_wait_loadcnt 0x0 ; GFX12-NEXT: global_store_b96 v[0:1], v[2:4], off @@ -795,6 +1008,9 @@ define amdgpu_cs float @buffer_load_v3f32_tfe(<4 x i32> inreg %rsrc, ptr addrspa ; GFX6-LABEL: buffer_load_v3f32_tfe: ; GFX6: ; %bb.0: ; GFX6-NEXT: v_mov_b32_e32 v2, 0 +; GFX6-NEXT: v_mov_b32_e32 v3, v2 +; GFX6-NEXT: v_mov_b32_e32 v4, v2 +; GFX6-NEXT: v_mov_b32_e32 v5, v2 ; GFX6-NEXT: buffer_load_format_xyz v[2:5], v2, s[0:3], 0 idxen tfe ; GFX6-NEXT: s_mov_b32 s2, 0 ; GFX6-NEXT: s_mov_b32 s3, 0xf000 @@ -810,6 +1026,9 @@ define amdgpu_cs float @buffer_load_v3f32_tfe(<4 x i32> inreg %rsrc, ptr addrspa ; GFX8PLUS-LABEL: buffer_load_v3f32_tfe: ; GFX8PLUS: ; %bb.0: ; GFX8PLUS-NEXT: v_mov_b32_e32 v2, 0 +; GFX8PLUS-NEXT: v_mov_b32_e32 v3, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v4, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v5, v2 ; GFX8PLUS-NEXT: buffer_load_format_xyz v[2:5], v2, s[0:3], 0 idxen tfe ; GFX8PLUS-NEXT: s_waitcnt vmcnt(0) ; GFX8PLUS-NEXT: flat_store_dwordx3 v[0:1], v[2:4] @@ -820,15 +1039,31 @@ define amdgpu_cs float @buffer_load_v3f32_tfe(<4 x i32> inreg %rsrc, ptr addrspa ; GFX11-LABEL: buffer_load_v3f32_tfe: ; GFX11: ; %bb.0: ; GFX11-NEXT: v_mov_b32_e32 v2, 0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v3, v2 +; GFX11-NEXT: v_mov_b32_e32 v4, v2 +; GFX11-NEXT: v_mov_b32_e32 v5, v2 ; GFX11-NEXT: buffer_load_format_xyz v[2:5], v2, s[0:3], 0 idxen tfe ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: global_store_b96 v[0:1], v[2:4], off ; GFX11-NEXT: v_mov_b32_e32 v0, v5 ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_v3f32_tfe: +; NOPRT: ; %bb.0: +; NOPRT-NEXT: v_mov_b32_e32 v5, 0 +; NOPRT-NEXT: buffer_load_format_xyz v[2:5], v5, s[0:3], 0 idxen tfe +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: global_store_b96 v[0:1], v[2:4], off +; NOPRT-NEXT: v_mov_b32_e32 v0, v5 +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_v3f32_tfe: ; GFX12: ; %bb.0: ; GFX12-NEXT: v_mov_b32_e32 v2, 0 +; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX12-NEXT: v_dual_mov_b32 v3, v2 :: v_dual_mov_b32 v4, v2 +; GFX12-NEXT: v_mov_b32_e32 v5, v2 ; GFX12-NEXT: buffer_load_format_xyz v[2:5], v2, s[0:3], null idxen tfe ; GFX12-NEXT: s_wait_loadcnt 0x0 ; GFX12-NEXT: global_store_b96 v[0:1], v[2:4], off @@ -846,6 +1081,9 @@ define amdgpu_cs float @buffer_load_v2i32_tfe(<4 x i32> inreg %rsrc, ptr addrspa ; GFX6-LABEL: buffer_load_v2i32_tfe: ; GFX6: ; %bb.0: ; GFX6-NEXT: v_mov_b32_e32 v2, 0 +; GFX6-NEXT: v_mov_b32_e32 v3, v2 +; GFX6-NEXT: v_mov_b32_e32 v4, v2 +; GFX6-NEXT: v_mov_b32_e32 v5, v2 ; GFX6-NEXT: buffer_load_format_xyz v[2:5], v2, s[0:3], 0 idxen tfe ; GFX6-NEXT: s_mov_b32 s2, 0 ; GFX6-NEXT: s_mov_b32 s3, 0xf000 @@ -860,6 +1098,8 @@ define amdgpu_cs float @buffer_load_v2i32_tfe(<4 x i32> inreg %rsrc, ptr addrspa ; GFX8PLUS-LABEL: buffer_load_v2i32_tfe: ; GFX8PLUS: ; %bb.0: ; GFX8PLUS-NEXT: v_mov_b32_e32 v2, 0 +; GFX8PLUS-NEXT: v_mov_b32_e32 v3, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v4, v2 ; GFX8PLUS-NEXT: buffer_load_format_xy v[2:4], v2, s[0:3], 0 idxen tfe ; GFX8PLUS-NEXT: s_waitcnt vmcnt(0) ; GFX8PLUS-NEXT: flat_store_dwordx2 v[0:1], v[2:3] @@ -870,15 +1110,29 @@ define amdgpu_cs float @buffer_load_v2i32_tfe(<4 x i32> inreg %rsrc, ptr addrspa ; GFX11-LABEL: buffer_load_v2i32_tfe: ; GFX11: ; %bb.0: ; GFX11-NEXT: v_mov_b32_e32 v2, 0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v3, v2 +; GFX11-NEXT: v_mov_b32_e32 v4, v2 ; GFX11-NEXT: buffer_load_format_xy v[2:4], v2, s[0:3], 0 idxen tfe ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: global_store_b64 v[0:1], v[2:3], off ; GFX11-NEXT: v_mov_b32_e32 v0, v4 ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_v2i32_tfe: +; NOPRT: ; %bb.0: +; NOPRT-NEXT: v_mov_b32_e32 v4, 0 +; NOPRT-NEXT: buffer_load_format_xy v[2:4], v4, s[0:3], 0 idxen tfe +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: global_store_b64 v[0:1], v[2:3], off +; NOPRT-NEXT: v_mov_b32_e32 v0, v4 +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_v2i32_tfe: ; GFX12: ; %bb.0: ; GFX12-NEXT: v_mov_b32_e32 v2, 0 +; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX12-NEXT: v_dual_mov_b32 v3, v2 :: v_dual_mov_b32 v4, v2 ; GFX12-NEXT: buffer_load_format_xy v[2:4], v2, s[0:3], null idxen tfe ; GFX12-NEXT: s_wait_loadcnt 0x0 ; GFX12-NEXT: global_store_b64 v[0:1], v[2:3], off @@ -896,6 +1150,9 @@ define amdgpu_cs float @buffer_load_v2f32_tfe(<4 x i32> inreg %rsrc, ptr addrspa ; GFX6-LABEL: buffer_load_v2f32_tfe: ; GFX6: ; %bb.0: ; GFX6-NEXT: v_mov_b32_e32 v2, 0 +; GFX6-NEXT: v_mov_b32_e32 v3, v2 +; GFX6-NEXT: v_mov_b32_e32 v4, v2 +; GFX6-NEXT: v_mov_b32_e32 v5, v2 ; GFX6-NEXT: buffer_load_format_xyz v[2:5], v2, s[0:3], 0 idxen tfe ; GFX6-NEXT: s_mov_b32 s2, 0 ; GFX6-NEXT: s_mov_b32 s3, 0xf000 @@ -910,6 +1167,8 @@ define amdgpu_cs float @buffer_load_v2f32_tfe(<4 x i32> inreg %rsrc, ptr addrspa ; GFX8PLUS-LABEL: buffer_load_v2f32_tfe: ; GFX8PLUS: ; %bb.0: ; GFX8PLUS-NEXT: v_mov_b32_e32 v2, 0 +; GFX8PLUS-NEXT: v_mov_b32_e32 v3, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v4, v2 ; GFX8PLUS-NEXT: buffer_load_format_xy v[2:4], v2, s[0:3], 0 idxen tfe ; GFX8PLUS-NEXT: s_waitcnt vmcnt(0) ; GFX8PLUS-NEXT: flat_store_dwordx2 v[0:1], v[2:3] @@ -920,15 +1179,29 @@ define amdgpu_cs float @buffer_load_v2f32_tfe(<4 x i32> inreg %rsrc, ptr addrspa ; GFX11-LABEL: buffer_load_v2f32_tfe: ; GFX11: ; %bb.0: ; GFX11-NEXT: v_mov_b32_e32 v2, 0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v3, v2 +; GFX11-NEXT: v_mov_b32_e32 v4, v2 ; GFX11-NEXT: buffer_load_format_xy v[2:4], v2, s[0:3], 0 idxen tfe ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: global_store_b64 v[0:1], v[2:3], off ; GFX11-NEXT: v_mov_b32_e32 v0, v4 ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_v2f32_tfe: +; NOPRT: ; %bb.0: +; NOPRT-NEXT: v_mov_b32_e32 v4, 0 +; NOPRT-NEXT: buffer_load_format_xy v[2:4], v4, s[0:3], 0 idxen tfe +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: global_store_b64 v[0:1], v[2:3], off +; NOPRT-NEXT: v_mov_b32_e32 v0, v4 +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_v2f32_tfe: ; GFX12: ; %bb.0: ; GFX12-NEXT: v_mov_b32_e32 v2, 0 +; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX12-NEXT: v_dual_mov_b32 v3, v2 :: v_dual_mov_b32 v4, v2 ; GFX12-NEXT: buffer_load_format_xy v[2:4], v2, s[0:3], null idxen tfe ; GFX12-NEXT: s_wait_loadcnt 0x0 ; GFX12-NEXT: global_store_b64 v[0:1], v[2:3], off @@ -946,6 +1219,7 @@ define amdgpu_cs float @buffer_load_i32_tfe(<4 x i32> inreg %rsrc, ptr addrspace ; GFX6-LABEL: buffer_load_i32_tfe: ; GFX6: ; %bb.0: ; GFX6-NEXT: v_mov_b32_e32 v2, 0 +; GFX6-NEXT: v_mov_b32_e32 v3, v2 ; GFX6-NEXT: buffer_load_format_x v[2:3], v2, s[0:3], 0 idxen tfe ; GFX6-NEXT: s_mov_b32 s2, 0 ; GFX6-NEXT: s_mov_b32 s3, 0xf000 @@ -960,6 +1234,7 @@ define amdgpu_cs float @buffer_load_i32_tfe(<4 x i32> inreg %rsrc, ptr addrspace ; GFX8PLUS-LABEL: buffer_load_i32_tfe: ; GFX8PLUS: ; %bb.0: ; GFX8PLUS-NEXT: v_mov_b32_e32 v2, 0 +; GFX8PLUS-NEXT: v_mov_b32_e32 v3, v2 ; GFX8PLUS-NEXT: buffer_load_format_x v[2:3], v2, s[0:3], 0 idxen tfe ; GFX8PLUS-NEXT: s_waitcnt vmcnt(0) ; GFX8PLUS-NEXT: flat_store_dword v[0:1], v2 @@ -970,15 +1245,28 @@ define amdgpu_cs float @buffer_load_i32_tfe(<4 x i32> inreg %rsrc, ptr addrspace ; GFX11-LABEL: buffer_load_i32_tfe: ; GFX11: ; %bb.0: ; GFX11-NEXT: v_mov_b32_e32 v2, 0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v3, v2 ; GFX11-NEXT: buffer_load_format_x v[2:3], v2, s[0:3], 0 idxen tfe ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: global_store_b32 v[0:1], v2, off ; GFX11-NEXT: v_mov_b32_e32 v0, v3 ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_i32_tfe: +; NOPRT: ; %bb.0: +; NOPRT-NEXT: v_mov_b32_e32 v3, 0 +; NOPRT-NEXT: buffer_load_format_x v[2:3], v3, s[0:3], 0 idxen tfe +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: global_store_b32 v[0:1], v2, off +; NOPRT-NEXT: v_mov_b32_e32 v0, v3 +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_i32_tfe: ; GFX12: ; %bb.0: ; GFX12-NEXT: v_mov_b32_e32 v2, 0 +; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX12-NEXT: v_mov_b32_e32 v3, v2 ; GFX12-NEXT: buffer_load_format_x v[2:3], v2, s[0:3], null idxen tfe ; GFX12-NEXT: s_wait_loadcnt 0x0 ; GFX12-NEXT: global_store_b32 v[0:1], v2, off @@ -996,6 +1284,7 @@ define amdgpu_cs float @buffer_load_f32_tfe(<4 x i32> inreg %rsrc, ptr addrspace ; GFX6-LABEL: buffer_load_f32_tfe: ; GFX6: ; %bb.0: ; GFX6-NEXT: v_mov_b32_e32 v2, 0 +; GFX6-NEXT: v_mov_b32_e32 v3, v2 ; GFX6-NEXT: buffer_load_format_x v[2:3], v2, s[0:3], 0 idxen tfe ; GFX6-NEXT: s_mov_b32 s2, 0 ; GFX6-NEXT: s_mov_b32 s3, 0xf000 @@ -1010,6 +1299,7 @@ define amdgpu_cs float @buffer_load_f32_tfe(<4 x i32> inreg %rsrc, ptr addrspace ; GFX8PLUS-LABEL: buffer_load_f32_tfe: ; GFX8PLUS: ; %bb.0: ; GFX8PLUS-NEXT: v_mov_b32_e32 v2, 0 +; GFX8PLUS-NEXT: v_mov_b32_e32 v3, v2 ; GFX8PLUS-NEXT: buffer_load_format_x v[2:3], v2, s[0:3], 0 idxen tfe ; GFX8PLUS-NEXT: s_waitcnt vmcnt(0) ; GFX8PLUS-NEXT: flat_store_dword v[0:1], v2 @@ -1020,15 +1310,28 @@ define amdgpu_cs float @buffer_load_f32_tfe(<4 x i32> inreg %rsrc, ptr addrspace ; GFX11-LABEL: buffer_load_f32_tfe: ; GFX11: ; %bb.0: ; GFX11-NEXT: v_mov_b32_e32 v2, 0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v3, v2 ; GFX11-NEXT: buffer_load_format_x v[2:3], v2, s[0:3], 0 idxen tfe ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: global_store_b32 v[0:1], v2, off ; GFX11-NEXT: v_mov_b32_e32 v0, v3 ; GFX11-NEXT: ; return to shader part epilog ; +; NOPRT-LABEL: buffer_load_f32_tfe: +; NOPRT: ; %bb.0: +; NOPRT-NEXT: v_mov_b32_e32 v3, 0 +; NOPRT-NEXT: buffer_load_format_x v[2:3], v3, s[0:3], 0 idxen tfe +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: global_store_b32 v[0:1], v2, off +; NOPRT-NEXT: v_mov_b32_e32 v0, v3 +; NOPRT-NEXT: ; return to shader part epilog +; ; GFX12-LABEL: buffer_load_f32_tfe: ; GFX12: ; %bb.0: ; GFX12-NEXT: v_mov_b32_e32 v2, 0 +; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX12-NEXT: v_mov_b32_e32 v3, v2 ; GFX12-NEXT: buffer_load_format_x v[2:3], v2, s[0:3], null idxen tfe ; GFX12-NEXT: s_wait_loadcnt 0x0 ; GFX12-NEXT: global_store_b32 v[0:1], v2, off diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.buffer.load.format.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.buffer.load.format.ll index b0bd4e428ef2dd5ae3d6605a0694e3aeb51fd1fd..c5202b84fa1efe6e2ae4445dc5db2ef31c1b80d5 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.buffer.load.format.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.struct.ptr.buffer.load.format.ll @@ -2,6 +2,7 @@ ;RUN: llc < %s -mtriple=amdgcn -mcpu=verde -verify-machineinstrs | FileCheck --check-prefixes=GFX6 %s ;RUN: llc < %s -mtriple=amdgcn -mcpu=tonga -verify-machineinstrs | FileCheck --check-prefixes=GFX8PLUS %s ;RUN: llc < %s -mtriple=amdgcn -mcpu=gfx1100 -verify-machineinstrs | FileCheck --check-prefixes=GFX11 %s +;RUN: llc < %s -mtriple=amdgcn -mattr=-enable-prt-strict-null -mcpu=gfx1100 -verify-machineinstrs | FileCheck --check-prefixes=NOPRT %s define amdgpu_ps {<4 x float>, <4 x float>, <4 x float>} @buffer_load(ptr addrspace(8) inreg) { ; GFX6-LABEL: buffer_load: @@ -31,6 +32,16 @@ define amdgpu_ps {<4 x float>, <4 x float>, <4 x float>} @buffer_load(ptr addrsp ; GFX11-NEXT: buffer_load_format_xyzw v[8:11], v8, s[0:3], 0 idxen slc ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: v_mov_b32_e32 v8, 0 +; NOPRT-NEXT: s_clause 0x2 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v8, s[0:3], 0 idxen +; NOPRT-NEXT: buffer_load_format_xyzw v[4:7], v8, s[0:3], 0 idxen glc +; NOPRT-NEXT: buffer_load_format_xyzw v[8:11], v8, s[0:3], 0 idxen slc +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog main_body: %data = call <4 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v4f32(ptr addrspace(8) %0, i32 0, i32 0, i32 0, i32 0) %data_glc = call <4 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v4f32(ptr addrspace(8) %0, i32 0, i32 0, i32 0, i32 1) @@ -62,6 +73,13 @@ define amdgpu_ps <4 x float> @buffer_load_immoffs(ptr addrspace(8) inreg) { ; GFX11-NEXT: buffer_load_format_xyzw v[0:3], v0, s[0:3], 0 idxen offset:42 ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_immoffs: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: v_mov_b32_e32 v0, 0 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v0, s[0:3], 0 idxen offset:42 +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog main_body: %data = call <4 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v4f32(ptr addrspace(8) %0, i32 0, i32 42, i32 0, i32 0) ret <4 x float> %data @@ -126,6 +144,25 @@ define amdgpu_ps <4 x float> @buffer_load_immoffs_large(ptr addrspace(8) inreg) ; GFX11-NEXT: v_dual_add_f32 v0, v8, v0 :: v_dual_add_f32 v3, v11, v3 ; GFX11-NEXT: v_add_f32_e32 v2, v10, v2 ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_immoffs_large: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: v_mov_b32_e32 v8, 0 +; NOPRT-NEXT: s_movk_i32 s4, 0x7ffc +; NOPRT-NEXT: s_clause 0x1 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v8, s[0:3], 60 idxen offset:4092 +; NOPRT-NEXT: buffer_load_format_xyzw v[4:7], v8, s[0:3], s4 idxen offset:4092 +; NOPRT-NEXT: s_mov_b32 s4, 0x8ffc +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: v_add_f32_e32 v1, v1, v5 +; NOPRT-NEXT: buffer_load_format_xyzw v[8:11], v8, s[0:3], s4 idxen offset:4 +; NOPRT-NEXT: v_dual_add_f32 v0, v0, v4 :: v_dual_add_f32 v3, v3, v7 +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: v_dual_add_f32 v2, v2, v6 :: v_dual_add_f32 v1, v9, v1 +; NOPRT-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) +; NOPRT-NEXT: v_dual_add_f32 v0, v8, v0 :: v_dual_add_f32 v3, v11, v3 +; NOPRT-NEXT: v_add_f32_e32 v2, v10, v2 +; NOPRT-NEXT: ; return to shader part epilog main_body: %d.0 = call <4 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v4f32(ptr addrspace(8) %0, i32 0, i32 4092, i32 60, i32 0) %d.1 = call <4 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v4f32(ptr addrspace(8) %0, i32 0, i32 4092, i32 32764, i32 0) @@ -156,6 +193,13 @@ define amdgpu_ps <4 x float> @buffer_load_voffset_large_12bit(ptr addrspace(8) i ; GFX11-NEXT: buffer_load_format_xyzw v[0:3], v0, s[0:3], 0 idxen offset:4092 ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_voffset_large_12bit: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: v_mov_b32_e32 v0, 0 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v0, s[0:3], 0 idxen offset:4092 +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog main_body: %data = call <4 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v4f32(ptr addrspace(8) %0, i32 0, i32 4092, i32 0, i32 0) ret <4 x float> %data @@ -188,6 +232,15 @@ define amdgpu_ps <4 x float> @buffer_load_voffset_large_13bit(ptr addrspace(8) i ; GFX11-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen offset:4092 ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_voffset_large_13bit: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: s_mov_b32 s4, 0 +; NOPRT-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; NOPRT-NEXT: v_dual_mov_b32 v1, 0x1000 :: v_dual_mov_b32 v0, s4 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen offset:4092 +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog main_body: %data = call <4 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v4f32(ptr addrspace(8) %0, i32 0, i32 8188, i32 0, i32 0) ret <4 x float> %data @@ -220,6 +273,15 @@ define amdgpu_ps <4 x float> @buffer_load_voffset_large_16bit(ptr addrspace(8) i ; GFX11-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen offset:4092 ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_voffset_large_16bit: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: s_mov_b32 s4, 0 +; NOPRT-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; NOPRT-NEXT: v_dual_mov_b32 v1, 0xf000 :: v_dual_mov_b32 v0, s4 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen offset:4092 +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog main_body: %data = call <4 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v4f32(ptr addrspace(8) %0, i32 0, i32 65532, i32 0, i32 0) ret <4 x float> %data @@ -252,6 +314,15 @@ define amdgpu_ps <4 x float> @buffer_load_voffset_large_23bit(ptr addrspace(8) i ; GFX11-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen offset:4092 ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_voffset_large_23bit: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: s_mov_b32 s4, 0 +; NOPRT-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; NOPRT-NEXT: v_dual_mov_b32 v1, 0x7ff000 :: v_dual_mov_b32 v0, s4 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen offset:4092 +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog main_body: %data = call <4 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v4f32(ptr addrspace(8) %0, i32 0, i32 8388604, i32 0, i32 0) ret <4 x float> %data @@ -284,6 +355,15 @@ define amdgpu_ps <4 x float> @buffer_load_voffset_large_24bit(ptr addrspace(8) i ; GFX11-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen offset:4092 ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_voffset_large_24bit: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: s_mov_b32 s4, 0 +; NOPRT-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; NOPRT-NEXT: v_dual_mov_b32 v1, 0xfff000 :: v_dual_mov_b32 v0, s4 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen offset:4092 +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog main_body: %data = call <4 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v4f32(ptr addrspace(8) %0, i32 0, i32 16777212, i32 0, i32 0) ret <4 x float> %data @@ -307,6 +387,12 @@ define amdgpu_ps <4 x float> @buffer_load_idx(ptr addrspace(8) inreg, i32) { ; GFX11-NEXT: buffer_load_format_xyzw v[0:3], v0, s[0:3], 0 idxen ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_idx: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v0, s[0:3], 0 idxen +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog main_body: %data = call <4 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v4f32(ptr addrspace(8) %0, i32 %1, i32 0, i32 0, i32 0) ret <4 x float> %data @@ -339,6 +425,15 @@ define amdgpu_ps <4 x float> @buffer_load_ofs(ptr addrspace(8) inreg, i32) { ; GFX11-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_ofs: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: s_mov_b32 s4, 0 +; NOPRT-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; NOPRT-NEXT: v_dual_mov_b32 v1, v0 :: v_dual_mov_b32 v0, s4 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog main_body: %data = call <4 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v4f32(ptr addrspace(8) %0, i32 0, i32 %1, i32 0, i32 0) ret <4 x float> %data @@ -371,6 +466,15 @@ define amdgpu_ps <4 x float> @buffer_load_ofs_imm(ptr addrspace(8) inreg, i32) { ; GFX11-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen offset:60 ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_ofs_imm: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: s_mov_b32 s4, 0 +; NOPRT-NEXT: s_delay_alu instid0(SALU_CYCLE_1) +; NOPRT-NEXT: v_dual_mov_b32 v1, v0 :: v_dual_mov_b32 v0, s4 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen offset:60 +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog main_body: %ofs = add i32 %1, 60 %data = call <4 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v4f32(ptr addrspace(8) %0, i32 0, i32 %ofs, i32 0, i32 0) @@ -395,6 +499,12 @@ define amdgpu_ps <4 x float> @buffer_load_both(ptr addrspace(8) inreg, i32, i32) ; GFX11-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_both: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v[0:1], s[0:3], 0 idxen offen +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog main_body: %data = call <4 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v4f32(ptr addrspace(8) %0, i32 %1, i32 %2, i32 0, i32 0) ret <4 x float> %data @@ -421,6 +531,13 @@ define amdgpu_ps <4 x float> @buffer_load_both_reversed(ptr addrspace(8) inreg, ; GFX11-NEXT: buffer_load_format_xyzw v[0:3], v[1:2], s[0:3], 0 idxen offen ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_both_reversed: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: v_mov_b32_e32 v2, v0 +; NOPRT-NEXT: buffer_load_format_xyzw v[0:3], v[1:2], s[0:3], 0 idxen offen +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog main_body: %data = call <4 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v4f32(ptr addrspace(8) %0, i32 %2, i32 %1, i32 0, i32 0) ret <4 x float> %data @@ -447,6 +564,13 @@ define amdgpu_ps float @buffer_load_x(ptr addrspace(8) inreg %rsrc) { ; GFX11-NEXT: buffer_load_format_x v0, v0, s[0:3], 0 idxen ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_x: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: v_mov_b32_e32 v0, 0 +; NOPRT-NEXT: buffer_load_format_x v0, v0, s[0:3], 0 idxen +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog main_body: %data = call float @llvm.amdgcn.struct.ptr.buffer.load.format.f32(ptr addrspace(8) %rsrc, i32 0, i32 0, i32 0, i32 0) ret float %data @@ -473,6 +597,13 @@ define amdgpu_ps float @buffer_load_x_i32(ptr addrspace(8) inreg %rsrc) { ; GFX11-NEXT: buffer_load_format_x v0, v0, s[0:3], 0 idxen ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_x_i32: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: v_mov_b32_e32 v0, 0 +; NOPRT-NEXT: buffer_load_format_x v0, v0, s[0:3], 0 idxen +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog main_body: %data = call i32 @llvm.amdgcn.struct.ptr.buffer.load.format.i32(ptr addrspace(8) %rsrc, i32 0, i32 0, i32 0, i32 0) %fdata = bitcast i32 %data to float @@ -500,6 +631,13 @@ define amdgpu_ps <2 x float> @buffer_load_xy(ptr addrspace(8) inreg %rsrc) { ; GFX11-NEXT: buffer_load_format_xy v[0:1], v0, s[0:3], 0 idxen ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_xy: +; NOPRT: ; %bb.0: ; %main_body +; NOPRT-NEXT: v_mov_b32_e32 v0, 0 +; NOPRT-NEXT: buffer_load_format_xy v[0:1], v0, s[0:3], 0 idxen +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: ; return to shader part epilog main_body: %data = call <2 x float> @llvm.amdgcn.struct.ptr.buffer.load.format.v2f32(ptr addrspace(8) %rsrc, i32 0, i32 0, i32 0, i32 0) ret <2 x float> %data @@ -509,6 +647,10 @@ define amdgpu_cs float @buffer_load_v4i32_tfe(ptr addrspace(8) inreg %rsrc, ptr ; GFX6-LABEL: buffer_load_v4i32_tfe: ; GFX6: ; %bb.0: ; GFX6-NEXT: v_mov_b32_e32 v2, 0 +; GFX6-NEXT: v_mov_b32_e32 v3, v2 +; GFX6-NEXT: v_mov_b32_e32 v4, v2 +; GFX6-NEXT: v_mov_b32_e32 v5, v2 +; GFX6-NEXT: v_mov_b32_e32 v6, v2 ; GFX6-NEXT: buffer_load_format_xyzw v[2:6], v2, s[0:3], 0 idxen tfe ; GFX6-NEXT: s_mov_b32 s2, 0 ; GFX6-NEXT: s_mov_b32 s3, 0xf000 @@ -523,6 +665,10 @@ define amdgpu_cs float @buffer_load_v4i32_tfe(ptr addrspace(8) inreg %rsrc, ptr ; GFX8PLUS-LABEL: buffer_load_v4i32_tfe: ; GFX8PLUS: ; %bb.0: ; GFX8PLUS-NEXT: v_mov_b32_e32 v2, 0 +; GFX8PLUS-NEXT: v_mov_b32_e32 v3, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v4, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v5, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v6, v2 ; GFX8PLUS-NEXT: buffer_load_format_xyzw v[2:6], v2, s[0:3], 0 idxen tfe ; GFX8PLUS-NEXT: s_waitcnt vmcnt(0) ; GFX8PLUS-NEXT: flat_store_dwordx4 v[0:1], v[2:5] @@ -533,11 +679,25 @@ define amdgpu_cs float @buffer_load_v4i32_tfe(ptr addrspace(8) inreg %rsrc, ptr ; GFX11-LABEL: buffer_load_v4i32_tfe: ; GFX11: ; %bb.0: ; GFX11-NEXT: v_mov_b32_e32 v2, 0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v3, v2 +; GFX11-NEXT: v_mov_b32_e32 v4, v2 +; GFX11-NEXT: v_mov_b32_e32 v5, v2 +; GFX11-NEXT: v_mov_b32_e32 v6, v2 ; GFX11-NEXT: buffer_load_format_xyzw v[2:6], v2, s[0:3], 0 idxen tfe ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: global_store_b128 v[0:1], v[2:5], off ; GFX11-NEXT: v_mov_b32_e32 v0, v6 ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_v4i32_tfe: +; NOPRT: ; %bb.0: +; NOPRT-NEXT: v_mov_b32_e32 v6, 0 +; NOPRT-NEXT: buffer_load_format_xyzw v[2:6], v6, s[0:3], 0 idxen tfe +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: global_store_b128 v[0:1], v[2:5], off +; NOPRT-NEXT: v_mov_b32_e32 v0, v6 +; NOPRT-NEXT: ; return to shader part epilog %load = call { <4 x i32>, i32 } @llvm.amdgcn.struct.ptr.buffer.load.format.sl_v4i32i32s(ptr addrspace(8) %rsrc, i32 0, i32 0, i32 0, i32 0) %data = extractvalue { <4 x i32>, i32 } %load, 0 store <4 x i32> %data, ptr addrspace(1) %out @@ -550,6 +710,10 @@ define amdgpu_cs float @buffer_load_v4f32_tfe(ptr addrspace(8) inreg %rsrc, ptr ; GFX6-LABEL: buffer_load_v4f32_tfe: ; GFX6: ; %bb.0: ; GFX6-NEXT: v_mov_b32_e32 v2, 0 +; GFX6-NEXT: v_mov_b32_e32 v3, v2 +; GFX6-NEXT: v_mov_b32_e32 v4, v2 +; GFX6-NEXT: v_mov_b32_e32 v5, v2 +; GFX6-NEXT: v_mov_b32_e32 v6, v2 ; GFX6-NEXT: buffer_load_format_xyzw v[2:6], v2, s[0:3], 0 idxen tfe ; GFX6-NEXT: s_mov_b32 s2, 0 ; GFX6-NEXT: s_mov_b32 s3, 0xf000 @@ -564,6 +728,10 @@ define amdgpu_cs float @buffer_load_v4f32_tfe(ptr addrspace(8) inreg %rsrc, ptr ; GFX8PLUS-LABEL: buffer_load_v4f32_tfe: ; GFX8PLUS: ; %bb.0: ; GFX8PLUS-NEXT: v_mov_b32_e32 v2, 0 +; GFX8PLUS-NEXT: v_mov_b32_e32 v3, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v4, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v5, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v6, v2 ; GFX8PLUS-NEXT: buffer_load_format_xyzw v[2:6], v2, s[0:3], 0 idxen tfe ; GFX8PLUS-NEXT: s_waitcnt vmcnt(0) ; GFX8PLUS-NEXT: flat_store_dwordx4 v[0:1], v[2:5] @@ -574,11 +742,25 @@ define amdgpu_cs float @buffer_load_v4f32_tfe(ptr addrspace(8) inreg %rsrc, ptr ; GFX11-LABEL: buffer_load_v4f32_tfe: ; GFX11: ; %bb.0: ; GFX11-NEXT: v_mov_b32_e32 v2, 0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v3, v2 +; GFX11-NEXT: v_mov_b32_e32 v4, v2 +; GFX11-NEXT: v_mov_b32_e32 v5, v2 +; GFX11-NEXT: v_mov_b32_e32 v6, v2 ; GFX11-NEXT: buffer_load_format_xyzw v[2:6], v2, s[0:3], 0 idxen tfe ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: global_store_b128 v[0:1], v[2:5], off ; GFX11-NEXT: v_mov_b32_e32 v0, v6 ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_v4f32_tfe: +; NOPRT: ; %bb.0: +; NOPRT-NEXT: v_mov_b32_e32 v6, 0 +; NOPRT-NEXT: buffer_load_format_xyzw v[2:6], v6, s[0:3], 0 idxen tfe +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: global_store_b128 v[0:1], v[2:5], off +; NOPRT-NEXT: v_mov_b32_e32 v0, v6 +; NOPRT-NEXT: ; return to shader part epilog %load = call { <4 x float>, i32 } @llvm.amdgcn.struct.ptr.buffer.load.format.sl_v4f32i32s(ptr addrspace(8) %rsrc, i32 0, i32 0, i32 0, i32 0) %data = extractvalue { <4 x float>, i32 } %load, 0 store <4 x float> %data, ptr addrspace(1) %out @@ -591,6 +773,9 @@ define amdgpu_cs float @buffer_load_v3i32_tfe(ptr addrspace(8) inreg %rsrc, ptr ; GFX6-LABEL: buffer_load_v3i32_tfe: ; GFX6: ; %bb.0: ; GFX6-NEXT: v_mov_b32_e32 v2, 0 +; GFX6-NEXT: v_mov_b32_e32 v3, v2 +; GFX6-NEXT: v_mov_b32_e32 v4, v2 +; GFX6-NEXT: v_mov_b32_e32 v5, v2 ; GFX6-NEXT: buffer_load_format_xyz v[2:5], v2, s[0:3], 0 idxen tfe ; GFX6-NEXT: s_mov_b32 s2, 0 ; GFX6-NEXT: s_mov_b32 s3, 0xf000 @@ -606,6 +791,9 @@ define amdgpu_cs float @buffer_load_v3i32_tfe(ptr addrspace(8) inreg %rsrc, ptr ; GFX8PLUS-LABEL: buffer_load_v3i32_tfe: ; GFX8PLUS: ; %bb.0: ; GFX8PLUS-NEXT: v_mov_b32_e32 v2, 0 +; GFX8PLUS-NEXT: v_mov_b32_e32 v3, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v4, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v5, v2 ; GFX8PLUS-NEXT: buffer_load_format_xyz v[2:5], v2, s[0:3], 0 idxen tfe ; GFX8PLUS-NEXT: s_waitcnt vmcnt(0) ; GFX8PLUS-NEXT: flat_store_dwordx3 v[0:1], v[2:4] @@ -616,11 +804,24 @@ define amdgpu_cs float @buffer_load_v3i32_tfe(ptr addrspace(8) inreg %rsrc, ptr ; GFX11-LABEL: buffer_load_v3i32_tfe: ; GFX11: ; %bb.0: ; GFX11-NEXT: v_mov_b32_e32 v2, 0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v3, v2 +; GFX11-NEXT: v_mov_b32_e32 v4, v2 +; GFX11-NEXT: v_mov_b32_e32 v5, v2 ; GFX11-NEXT: buffer_load_format_xyz v[2:5], v2, s[0:3], 0 idxen tfe ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: global_store_b96 v[0:1], v[2:4], off ; GFX11-NEXT: v_mov_b32_e32 v0, v5 ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_v3i32_tfe: +; NOPRT: ; %bb.0: +; NOPRT-NEXT: v_mov_b32_e32 v5, 0 +; NOPRT-NEXT: buffer_load_format_xyz v[2:5], v5, s[0:3], 0 idxen tfe +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: global_store_b96 v[0:1], v[2:4], off +; NOPRT-NEXT: v_mov_b32_e32 v0, v5 +; NOPRT-NEXT: ; return to shader part epilog %load = call { <3 x i32>, i32 } @llvm.amdgcn.struct.ptr.buffer.load.format.sl_v3i32i32s(ptr addrspace(8) %rsrc, i32 0, i32 0, i32 0, i32 0) %data = extractvalue { <3 x i32>, i32 } %load, 0 store <3 x i32> %data, ptr addrspace(1) %out @@ -633,6 +834,9 @@ define amdgpu_cs float @buffer_load_v3f32_tfe(ptr addrspace(8) inreg %rsrc, ptr ; GFX6-LABEL: buffer_load_v3f32_tfe: ; GFX6: ; %bb.0: ; GFX6-NEXT: v_mov_b32_e32 v2, 0 +; GFX6-NEXT: v_mov_b32_e32 v3, v2 +; GFX6-NEXT: v_mov_b32_e32 v4, v2 +; GFX6-NEXT: v_mov_b32_e32 v5, v2 ; GFX6-NEXT: buffer_load_format_xyz v[2:5], v2, s[0:3], 0 idxen tfe ; GFX6-NEXT: s_mov_b32 s2, 0 ; GFX6-NEXT: s_mov_b32 s3, 0xf000 @@ -648,6 +852,9 @@ define amdgpu_cs float @buffer_load_v3f32_tfe(ptr addrspace(8) inreg %rsrc, ptr ; GFX8PLUS-LABEL: buffer_load_v3f32_tfe: ; GFX8PLUS: ; %bb.0: ; GFX8PLUS-NEXT: v_mov_b32_e32 v2, 0 +; GFX8PLUS-NEXT: v_mov_b32_e32 v3, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v4, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v5, v2 ; GFX8PLUS-NEXT: buffer_load_format_xyz v[2:5], v2, s[0:3], 0 idxen tfe ; GFX8PLUS-NEXT: s_waitcnt vmcnt(0) ; GFX8PLUS-NEXT: flat_store_dwordx3 v[0:1], v[2:4] @@ -658,11 +865,24 @@ define amdgpu_cs float @buffer_load_v3f32_tfe(ptr addrspace(8) inreg %rsrc, ptr ; GFX11-LABEL: buffer_load_v3f32_tfe: ; GFX11: ; %bb.0: ; GFX11-NEXT: v_mov_b32_e32 v2, 0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v3, v2 +; GFX11-NEXT: v_mov_b32_e32 v4, v2 +; GFX11-NEXT: v_mov_b32_e32 v5, v2 ; GFX11-NEXT: buffer_load_format_xyz v[2:5], v2, s[0:3], 0 idxen tfe ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: global_store_b96 v[0:1], v[2:4], off ; GFX11-NEXT: v_mov_b32_e32 v0, v5 ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_v3f32_tfe: +; NOPRT: ; %bb.0: +; NOPRT-NEXT: v_mov_b32_e32 v5, 0 +; NOPRT-NEXT: buffer_load_format_xyz v[2:5], v5, s[0:3], 0 idxen tfe +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: global_store_b96 v[0:1], v[2:4], off +; NOPRT-NEXT: v_mov_b32_e32 v0, v5 +; NOPRT-NEXT: ; return to shader part epilog %load = call { <3 x float>, i32 } @llvm.amdgcn.struct.ptr.buffer.load.format.sl_v3f32i32s(ptr addrspace(8) %rsrc, i32 0, i32 0, i32 0, i32 0) %data = extractvalue { <3 x float>, i32 } %load, 0 store <3 x float> %data, ptr addrspace(1) %out @@ -675,6 +895,9 @@ define amdgpu_cs float @buffer_load_v2i32_tfe(ptr addrspace(8) inreg %rsrc, ptr ; GFX6-LABEL: buffer_load_v2i32_tfe: ; GFX6: ; %bb.0: ; GFX6-NEXT: v_mov_b32_e32 v2, 0 +; GFX6-NEXT: v_mov_b32_e32 v3, v2 +; GFX6-NEXT: v_mov_b32_e32 v4, v2 +; GFX6-NEXT: v_mov_b32_e32 v5, v2 ; GFX6-NEXT: buffer_load_format_xyz v[2:5], v2, s[0:3], 0 idxen tfe ; GFX6-NEXT: s_mov_b32 s2, 0 ; GFX6-NEXT: s_mov_b32 s3, 0xf000 @@ -689,6 +912,8 @@ define amdgpu_cs float @buffer_load_v2i32_tfe(ptr addrspace(8) inreg %rsrc, ptr ; GFX8PLUS-LABEL: buffer_load_v2i32_tfe: ; GFX8PLUS: ; %bb.0: ; GFX8PLUS-NEXT: v_mov_b32_e32 v2, 0 +; GFX8PLUS-NEXT: v_mov_b32_e32 v3, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v4, v2 ; GFX8PLUS-NEXT: buffer_load_format_xy v[2:4], v2, s[0:3], 0 idxen tfe ; GFX8PLUS-NEXT: s_waitcnt vmcnt(0) ; GFX8PLUS-NEXT: flat_store_dwordx2 v[0:1], v[2:3] @@ -699,11 +924,23 @@ define amdgpu_cs float @buffer_load_v2i32_tfe(ptr addrspace(8) inreg %rsrc, ptr ; GFX11-LABEL: buffer_load_v2i32_tfe: ; GFX11: ; %bb.0: ; GFX11-NEXT: v_mov_b32_e32 v2, 0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v3, v2 +; GFX11-NEXT: v_mov_b32_e32 v4, v2 ; GFX11-NEXT: buffer_load_format_xy v[2:4], v2, s[0:3], 0 idxen tfe ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: global_store_b64 v[0:1], v[2:3], off ; GFX11-NEXT: v_mov_b32_e32 v0, v4 ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_v2i32_tfe: +; NOPRT: ; %bb.0: +; NOPRT-NEXT: v_mov_b32_e32 v4, 0 +; NOPRT-NEXT: buffer_load_format_xy v[2:4], v4, s[0:3], 0 idxen tfe +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: global_store_b64 v[0:1], v[2:3], off +; NOPRT-NEXT: v_mov_b32_e32 v0, v4 +; NOPRT-NEXT: ; return to shader part epilog %load = call { <2 x i32>, i32 } @llvm.amdgcn.struct.ptr.buffer.load.format.sl_v2i32i32s(ptr addrspace(8) %rsrc, i32 0, i32 0, i32 0, i32 0) %data = extractvalue { <2 x i32>, i32 } %load, 0 store <2 x i32> %data, ptr addrspace(1) %out @@ -716,6 +953,9 @@ define amdgpu_cs float @buffer_load_v2f32_tfe(ptr addrspace(8) inreg %rsrc, ptr ; GFX6-LABEL: buffer_load_v2f32_tfe: ; GFX6: ; %bb.0: ; GFX6-NEXT: v_mov_b32_e32 v2, 0 +; GFX6-NEXT: v_mov_b32_e32 v3, v2 +; GFX6-NEXT: v_mov_b32_e32 v4, v2 +; GFX6-NEXT: v_mov_b32_e32 v5, v2 ; GFX6-NEXT: buffer_load_format_xyz v[2:5], v2, s[0:3], 0 idxen tfe ; GFX6-NEXT: s_mov_b32 s2, 0 ; GFX6-NEXT: s_mov_b32 s3, 0xf000 @@ -730,6 +970,8 @@ define amdgpu_cs float @buffer_load_v2f32_tfe(ptr addrspace(8) inreg %rsrc, ptr ; GFX8PLUS-LABEL: buffer_load_v2f32_tfe: ; GFX8PLUS: ; %bb.0: ; GFX8PLUS-NEXT: v_mov_b32_e32 v2, 0 +; GFX8PLUS-NEXT: v_mov_b32_e32 v3, v2 +; GFX8PLUS-NEXT: v_mov_b32_e32 v4, v2 ; GFX8PLUS-NEXT: buffer_load_format_xy v[2:4], v2, s[0:3], 0 idxen tfe ; GFX8PLUS-NEXT: s_waitcnt vmcnt(0) ; GFX8PLUS-NEXT: flat_store_dwordx2 v[0:1], v[2:3] @@ -740,11 +982,23 @@ define amdgpu_cs float @buffer_load_v2f32_tfe(ptr addrspace(8) inreg %rsrc, ptr ; GFX11-LABEL: buffer_load_v2f32_tfe: ; GFX11: ; %bb.0: ; GFX11-NEXT: v_mov_b32_e32 v2, 0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v3, v2 +; GFX11-NEXT: v_mov_b32_e32 v4, v2 ; GFX11-NEXT: buffer_load_format_xy v[2:4], v2, s[0:3], 0 idxen tfe ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: global_store_b64 v[0:1], v[2:3], off ; GFX11-NEXT: v_mov_b32_e32 v0, v4 ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_v2f32_tfe: +; NOPRT: ; %bb.0: +; NOPRT-NEXT: v_mov_b32_e32 v4, 0 +; NOPRT-NEXT: buffer_load_format_xy v[2:4], v4, s[0:3], 0 idxen tfe +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: global_store_b64 v[0:1], v[2:3], off +; NOPRT-NEXT: v_mov_b32_e32 v0, v4 +; NOPRT-NEXT: ; return to shader part epilog %load = call { <2 x float>, i32 } @llvm.amdgcn.struct.ptr.buffer.load.format.sl_v2f32i32s(ptr addrspace(8) %rsrc, i32 0, i32 0, i32 0, i32 0) %data = extractvalue { <2 x float>, i32 } %load, 0 store <2 x float> %data, ptr addrspace(1) %out @@ -757,6 +1011,7 @@ define amdgpu_cs float @buffer_load_i32_tfe(ptr addrspace(8) inreg %rsrc, ptr ad ; GFX6-LABEL: buffer_load_i32_tfe: ; GFX6: ; %bb.0: ; GFX6-NEXT: v_mov_b32_e32 v2, 0 +; GFX6-NEXT: v_mov_b32_e32 v3, v2 ; GFX6-NEXT: buffer_load_format_x v[2:3], v2, s[0:3], 0 idxen tfe ; GFX6-NEXT: s_mov_b32 s2, 0 ; GFX6-NEXT: s_mov_b32 s3, 0xf000 @@ -771,6 +1026,7 @@ define amdgpu_cs float @buffer_load_i32_tfe(ptr addrspace(8) inreg %rsrc, ptr ad ; GFX8PLUS-LABEL: buffer_load_i32_tfe: ; GFX8PLUS: ; %bb.0: ; GFX8PLUS-NEXT: v_mov_b32_e32 v2, 0 +; GFX8PLUS-NEXT: v_mov_b32_e32 v3, v2 ; GFX8PLUS-NEXT: buffer_load_format_x v[2:3], v2, s[0:3], 0 idxen tfe ; GFX8PLUS-NEXT: s_waitcnt vmcnt(0) ; GFX8PLUS-NEXT: flat_store_dword v[0:1], v2 @@ -781,11 +1037,22 @@ define amdgpu_cs float @buffer_load_i32_tfe(ptr addrspace(8) inreg %rsrc, ptr ad ; GFX11-LABEL: buffer_load_i32_tfe: ; GFX11: ; %bb.0: ; GFX11-NEXT: v_mov_b32_e32 v2, 0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v3, v2 ; GFX11-NEXT: buffer_load_format_x v[2:3], v2, s[0:3], 0 idxen tfe ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: global_store_b32 v[0:1], v2, off ; GFX11-NEXT: v_mov_b32_e32 v0, v3 ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_i32_tfe: +; NOPRT: ; %bb.0: +; NOPRT-NEXT: v_mov_b32_e32 v3, 0 +; NOPRT-NEXT: buffer_load_format_x v[2:3], v3, s[0:3], 0 idxen tfe +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: global_store_b32 v[0:1], v2, off +; NOPRT-NEXT: v_mov_b32_e32 v0, v3 +; NOPRT-NEXT: ; return to shader part epilog %load = call { i32, i32 } @llvm.amdgcn.struct.ptr.buffer.load.format.sl_i32i32s(ptr addrspace(8) %rsrc, i32 0, i32 0, i32 0, i32 0) %data = extractvalue { i32, i32 } %load, 0 store i32 %data, ptr addrspace(1) %out @@ -798,6 +1065,7 @@ define amdgpu_cs float @buffer_load_f32_tfe(ptr addrspace(8) inreg %rsrc, ptr ad ; GFX6-LABEL: buffer_load_f32_tfe: ; GFX6: ; %bb.0: ; GFX6-NEXT: v_mov_b32_e32 v2, 0 +; GFX6-NEXT: v_mov_b32_e32 v3, v2 ; GFX6-NEXT: buffer_load_format_x v[2:3], v2, s[0:3], 0 idxen tfe ; GFX6-NEXT: s_mov_b32 s2, 0 ; GFX6-NEXT: s_mov_b32 s3, 0xf000 @@ -812,6 +1080,7 @@ define amdgpu_cs float @buffer_load_f32_tfe(ptr addrspace(8) inreg %rsrc, ptr ad ; GFX8PLUS-LABEL: buffer_load_f32_tfe: ; GFX8PLUS: ; %bb.0: ; GFX8PLUS-NEXT: v_mov_b32_e32 v2, 0 +; GFX8PLUS-NEXT: v_mov_b32_e32 v3, v2 ; GFX8PLUS-NEXT: buffer_load_format_x v[2:3], v2, s[0:3], 0 idxen tfe ; GFX8PLUS-NEXT: s_waitcnt vmcnt(0) ; GFX8PLUS-NEXT: flat_store_dword v[0:1], v2 @@ -822,11 +1091,22 @@ define amdgpu_cs float @buffer_load_f32_tfe(ptr addrspace(8) inreg %rsrc, ptr ad ; GFX11-LABEL: buffer_load_f32_tfe: ; GFX11: ; %bb.0: ; GFX11-NEXT: v_mov_b32_e32 v2, 0 +; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GFX11-NEXT: v_mov_b32_e32 v3, v2 ; GFX11-NEXT: buffer_load_format_x v[2:3], v2, s[0:3], 0 idxen tfe ; GFX11-NEXT: s_waitcnt vmcnt(0) ; GFX11-NEXT: global_store_b32 v[0:1], v2, off ; GFX11-NEXT: v_mov_b32_e32 v0, v3 ; GFX11-NEXT: ; return to shader part epilog +; +; NOPRT-LABEL: buffer_load_f32_tfe: +; NOPRT: ; %bb.0: +; NOPRT-NEXT: v_mov_b32_e32 v3, 0 +; NOPRT-NEXT: buffer_load_format_x v[2:3], v3, s[0:3], 0 idxen tfe +; NOPRT-NEXT: s_waitcnt vmcnt(0) +; NOPRT-NEXT: global_store_b32 v[0:1], v2, off +; NOPRT-NEXT: v_mov_b32_e32 v0, v3 +; NOPRT-NEXT: ; return to shader part epilog %load = call { float, i32 } @llvm.amdgcn.struct.ptr.buffer.load.format.sl_f32i32s(ptr addrspace(8) %rsrc, i32 0, i32 0, i32 0, i32 0) %data = extractvalue { float, i32 } %load, 0 store float %data, ptr addrspace(1) %out diff --git a/llvm/test/CodeGen/AMDGPU/llvm.maxnum.f16.ll b/llvm/test/CodeGen/AMDGPU/llvm.maxnum.f16.ll index ab7ab4de186142d2a455a2f54c98e8688513b039..d056a97dc544427803aa23e7e7368f7c5c450c77 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.maxnum.f16.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.maxnum.f16.ll @@ -32,8 +32,6 @@ define amdgpu_kernel void @maxnum_f16( ; SI-NEXT: s_mov_b32 s1, s5 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; SI-NEXT: v_cvt_f32_f16_e32 v1, v1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; SI-NEXT: v_max_f32_e32 v0, v0, v1 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: buffer_store_short v0, off, s[0:3], 0 @@ -170,7 +168,6 @@ define amdgpu_kernel void @maxnum_f16_imm_a( ; SI-NEXT: s_mov_b32 s5, s1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 0x40400000, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: buffer_store_short v0, off, s[4:7], 0 @@ -279,7 +276,6 @@ define amdgpu_kernel void @maxnum_f16_imm_b( ; SI-NEXT: s_mov_b32 s5, s1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_max_f32_e32 v0, 4.0, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: buffer_store_short v0, off, s[4:7], 0 @@ -384,21 +380,17 @@ define amdgpu_kernel void @maxnum_v2f16( ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: s_lshr_b32 s1, s2, 16 -; SI-NEXT: v_cvt_f32_f16_e32 v1, s0 -; SI-NEXT: s_lshr_b32 s0, s0, 16 -; SI-NEXT: v_cvt_f32_f16_e32 v2, s0 -; SI-NEXT: v_cvt_f32_f16_e32 v3, s1 -; SI-NEXT: v_cvt_f32_f16_e32 v0, s2 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_max_f32_e32 v2, v3, v2 -; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 +; SI-NEXT: s_lshr_b32 s3, s0, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v0, s1 +; SI-NEXT: v_cvt_f32_f16_e32 v1, s3 +; SI-NEXT: v_cvt_f32_f16_e32 v2, s2 +; SI-NEXT: v_cvt_f32_f16_e32 v3, s0 ; SI-NEXT: v_max_f32_e32 v0, v0, v1 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v2 -; SI-NEXT: v_or_b32_e32 v0, v0, v1 +; SI-NEXT: v_max_f32_e32 v1, v2, v3 +; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_lshlrev_b32_e32 v0, 16, v0 +; SI-NEXT: v_or_b32_e32 v0, v1, v0 ; SI-NEXT: buffer_store_dword v0, off, s[4:7], 0 ; SI-NEXT: s_endpgm ; @@ -497,20 +489,18 @@ define amdgpu_kernel void @maxnum_v2f16_imm_a( ; SI-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x9 ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: s_load_dword s2, s[2:3], 0x0 -; SI-NEXT: s_mov_b32 s3, 0xf000 ; SI-NEXT: s_waitcnt lgkmcnt(0) -; SI-NEXT: v_cvt_f32_f16_e32 v0, s2 -; SI-NEXT: s_lshr_b32 s2, s2, 16 +; SI-NEXT: s_lshr_b32 s3, s2, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v0, s3 ; SI-NEXT: v_cvt_f32_f16_e32 v1, s2 +; SI-NEXT: s_mov_b32 s3, 0xf000 ; SI-NEXT: s_mov_b32 s2, -1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_max_f32_e32 v0, 0x40400000, v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_max_f32_e32 v1, 4.0, v1 -; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_max_f32_e32 v0, 4.0, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 -; SI-NEXT: v_or_b32_e32 v0, v0, v1 +; SI-NEXT: v_max_f32_e32 v1, 0x40400000, v1 +; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_lshlrev_b32_e32 v0, 16, v0 +; SI-NEXT: v_or_b32_e32 v0, v1, v0 ; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0 ; SI-NEXT: s_endpgm ; @@ -589,20 +579,18 @@ define amdgpu_kernel void @maxnum_v2f16_imm_b( ; SI-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x9 ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: s_load_dword s2, s[2:3], 0x0 -; SI-NEXT: s_mov_b32 s3, 0xf000 ; SI-NEXT: s_waitcnt lgkmcnt(0) -; SI-NEXT: v_cvt_f32_f16_e32 v0, s2 -; SI-NEXT: s_lshr_b32 s2, s2, 16 +; SI-NEXT: s_lshr_b32 s3, s2, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v0, s3 ; SI-NEXT: v_cvt_f32_f16_e32 v1, s2 +; SI-NEXT: s_mov_b32 s3, 0xf000 ; SI-NEXT: s_mov_b32 s2, -1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_max_f32_e32 v0, 4.0, v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_max_f32_e32 v1, 0x40400000, v1 -; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_max_f32_e32 v0, 0x40400000, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 -; SI-NEXT: v_or_b32_e32 v0, v0, v1 +; SI-NEXT: v_max_f32_e32 v1, 4.0, v1 +; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_lshlrev_b32_e32 v0, 16, v0 +; SI-NEXT: v_or_b32_e32 v0, v1, v0 ; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0 ; SI-NEXT: s_endpgm ; @@ -688,27 +676,21 @@ define amdgpu_kernel void @maxnum_v3f16( ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_cvt_f32_f16_e32 v0, s3 -; SI-NEXT: v_cvt_f32_f16_e32 v1, s2 -; SI-NEXT: s_lshr_b32 s2, s2, 16 -; SI-NEXT: s_lshr_b32 s3, s0, 16 -; SI-NEXT: v_cvt_f32_f16_e32 v2, s3 +; SI-NEXT: s_lshr_b32 s3, s2, 16 +; SI-NEXT: s_lshr_b32 s8, s0, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v1, s3 +; SI-NEXT: v_cvt_f32_f16_e32 v2, s8 ; SI-NEXT: v_cvt_f32_f16_e32 v3, s2 -; SI-NEXT: v_cvt_f32_f16_e32 v5, s0 -; SI-NEXT: v_cvt_f32_f16_e32 v4, s1 -; SI-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; SI-NEXT: v_max_f32_e32 v2, v3, v2 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v5 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_max_f32_e32 v1, v1, v3 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v4 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 -; SI-NEXT: v_max_f32_e32 v0, v0, v3 +; SI-NEXT: v_cvt_f32_f16_e32 v4, s0 +; SI-NEXT: v_cvt_f32_f16_e32 v5, s1 +; SI-NEXT: v_max_f32_e32 v1, v1, v2 ; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_max_f32_e32 v2, v3, v4 +; SI-NEXT: v_max_f32_e32 v0, v0, v5 +; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; SI-NEXT: v_lshlrev_b32_e32 v2, 16, v2 -; SI-NEXT: v_or_b32_e32 v1, v1, v2 +; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 +; SI-NEXT: v_or_b32_e32 v1, v2, v1 ; SI-NEXT: buffer_store_short v0, off, s[4:7], 0 offset:4 ; SI-NEXT: buffer_store_dword v1, off, s[4:7], 0 ; SI-NEXT: s_endpgm @@ -837,25 +819,17 @@ define amdgpu_kernel void @maxnum_v4f16( ; SI-NEXT: v_cvt_f32_f16_e32 v2, s6 ; SI-NEXT: s_lshr_b32 s6, s7, 16 ; SI-NEXT: v_cvt_f32_f16_e32 v3, s6 +; SI-NEXT: v_cvt_f32_f16_e32 v4, s4 ; SI-NEXT: s_lshr_b32 s6, s5, 16 +; SI-NEXT: s_lshr_b32 s4, s4, 16 ; SI-NEXT: v_cvt_f32_f16_e32 v5, s6 +; SI-NEXT: v_cvt_f32_f16_e32 v7, s4 ; SI-NEXT: v_cvt_f32_f16_e32 v1, s7 -; SI-NEXT: v_cvt_f32_f16_e32 v4, s4 -; SI-NEXT: s_lshr_b32 s4, s4, 16 -; SI-NEXT: v_cvt_f32_f16_e32 v7, s5 -; SI-NEXT: v_cvt_f32_f16_e32 v6, s4 -; SI-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v3 +; SI-NEXT: v_cvt_f32_f16_e32 v6, s5 ; SI-NEXT: v_max_f32_e32 v3, v3, v5 -; SI-NEXT: v_mul_f32_e32 v5, 1.0, v7 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_max_f32_e32 v1, v1, v5 -; SI-NEXT: v_mul_f32_e32 v5, 1.0, v6 -; SI-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; SI-NEXT: v_max_f32_e32 v2, v2, v5 -; SI-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 +; SI-NEXT: v_max_f32_e32 v2, v2, v7 ; SI-NEXT: v_cvt_f16_f32_e32 v3, v3 +; SI-NEXT: v_max_f32_e32 v1, v1, v6 ; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; SI-NEXT: v_max_f32_e32 v0, v0, v4 ; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 @@ -986,20 +960,16 @@ define amdgpu_kernel void @fmax_v4f16_imm_a( ; SI-NEXT: v_cvt_f32_f16_e32 v1, s5 ; SI-NEXT: s_lshr_b32 s5, s5, 16 ; SI-NEXT: v_cvt_f32_f16_e32 v0, s4 -; SI-NEXT: v_cvt_f32_f16_e32 v2, s5 ; SI-NEXT: s_lshr_b32 s4, s4, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v2, s5 ; SI-NEXT: v_cvt_f32_f16_e32 v3, s4 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; SI-NEXT: v_max_f32_e32 v2, 4.0, v2 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; SI-NEXT: v_max_f32_e32 v1, 0x40400000, v1 +; SI-NEXT: v_max_f32_e32 v0, 0x41000000, v0 +; SI-NEXT: v_max_f32_e32 v2, 4.0, v2 ; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; SI-NEXT: v_max_f32_e32 v3, 2.0, v3 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; SI-NEXT: v_cvt_f16_f32_e32 v3, v3 -; SI-NEXT: v_max_f32_e32 v0, 0x41000000, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: v_lshlrev_b32_e32 v2, 16, v2 ; SI-NEXT: v_or_b32_e32 v1, v1, v2 diff --git a/llvm/test/CodeGen/AMDGPU/llvm.minnum.f16.ll b/llvm/test/CodeGen/AMDGPU/llvm.minnum.f16.ll index b7370ce0fde1abab82427fa8f02f1de38ecfd866..f934a2de9247f0dbb987754ec2d38aafd69c8cc3 100644 --- a/llvm/test/CodeGen/AMDGPU/llvm.minnum.f16.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.minnum.f16.ll @@ -32,8 +32,6 @@ define amdgpu_kernel void @minnum_f16_ieee( ; SI-NEXT: s_mov_b32 s1, s5 ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; SI-NEXT: v_cvt_f32_f16_e32 v1, v1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 ; SI-NEXT: v_min_f32_e32 v0, v0, v1 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: buffer_store_short v0, off, s[0:3], 0 @@ -197,7 +195,6 @@ define amdgpu_kernel void @minnum_f16_imm_a( ; SI-NEXT: s_mov_b32 s5, s1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_min_f32_e32 v0, 0x40400000, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: buffer_store_short v0, off, s[4:7], 0 @@ -305,7 +302,6 @@ define amdgpu_kernel void @minnum_f16_imm_b( ; SI-NEXT: s_mov_b32 s5, s1 ; SI-NEXT: s_waitcnt vmcnt(0) ; SI-NEXT: v_cvt_f32_f16_e32 v0, v0 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_min_f32_e32 v0, 4.0, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: buffer_store_short v0, off, s[4:7], 0 @@ -409,21 +405,17 @@ define amdgpu_kernel void @minnum_v2f16_ieee( ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: s_lshr_b32 s1, s2, 16 -; SI-NEXT: v_cvt_f32_f16_e32 v1, s0 -; SI-NEXT: s_lshr_b32 s0, s0, 16 -; SI-NEXT: v_cvt_f32_f16_e32 v2, s0 -; SI-NEXT: v_cvt_f32_f16_e32 v3, s1 -; SI-NEXT: v_cvt_f32_f16_e32 v0, s2 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_min_f32_e32 v2, v3, v2 -; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 +; SI-NEXT: s_lshr_b32 s3, s0, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v0, s1 +; SI-NEXT: v_cvt_f32_f16_e32 v1, s3 +; SI-NEXT: v_cvt_f32_f16_e32 v2, s2 +; SI-NEXT: v_cvt_f32_f16_e32 v3, s0 ; SI-NEXT: v_min_f32_e32 v0, v0, v1 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v2 -; SI-NEXT: v_or_b32_e32 v0, v0, v1 +; SI-NEXT: v_min_f32_e32 v1, v2, v3 +; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_lshlrev_b32_e32 v0, 16, v0 +; SI-NEXT: v_or_b32_e32 v0, v1, v0 ; SI-NEXT: buffer_store_dword v0, off, s[4:7], 0 ; SI-NEXT: s_endpgm ; @@ -556,20 +548,18 @@ define amdgpu_kernel void @minnum_v2f16_imm_a( ; SI-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x9 ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: s_load_dword s2, s[2:3], 0x0 -; SI-NEXT: s_mov_b32 s3, 0xf000 ; SI-NEXT: s_waitcnt lgkmcnt(0) -; SI-NEXT: v_cvt_f32_f16_e32 v0, s2 -; SI-NEXT: s_lshr_b32 s2, s2, 16 +; SI-NEXT: s_lshr_b32 s3, s2, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v0, s3 ; SI-NEXT: v_cvt_f32_f16_e32 v1, s2 +; SI-NEXT: s_mov_b32 s3, 0xf000 ; SI-NEXT: s_mov_b32 s2, -1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_min_f32_e32 v0, 0x40400000, v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_min_f32_e32 v1, 4.0, v1 -; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_min_f32_e32 v0, 4.0, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 -; SI-NEXT: v_or_b32_e32 v0, v0, v1 +; SI-NEXT: v_min_f32_e32 v1, 0x40400000, v1 +; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_lshlrev_b32_e32 v0, 16, v0 +; SI-NEXT: v_or_b32_e32 v0, v1, v0 ; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0 ; SI-NEXT: s_endpgm ; @@ -647,20 +637,18 @@ define amdgpu_kernel void @minnum_v2f16_imm_b( ; SI-NEXT: s_load_dwordx4 s[0:3], s[0:1], 0x9 ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: s_load_dword s2, s[2:3], 0x0 -; SI-NEXT: s_mov_b32 s3, 0xf000 ; SI-NEXT: s_waitcnt lgkmcnt(0) -; SI-NEXT: v_cvt_f32_f16_e32 v0, s2 -; SI-NEXT: s_lshr_b32 s2, s2, 16 +; SI-NEXT: s_lshr_b32 s3, s2, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v0, s3 ; SI-NEXT: v_cvt_f32_f16_e32 v1, s2 +; SI-NEXT: s_mov_b32 s3, 0xf000 ; SI-NEXT: s_mov_b32 s2, -1 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_min_f32_e32 v0, 4.0, v0 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_min_f32_e32 v1, 0x40400000, v1 -; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_min_f32_e32 v0, 0x40400000, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 -; SI-NEXT: v_or_b32_e32 v0, v0, v1 +; SI-NEXT: v_min_f32_e32 v1, 4.0, v1 +; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_lshlrev_b32_e32 v0, 16, v0 +; SI-NEXT: v_or_b32_e32 v0, v1, v0 ; SI-NEXT: buffer_store_dword v0, off, s[0:3], 0 ; SI-NEXT: s_endpgm ; @@ -745,27 +733,21 @@ define amdgpu_kernel void @minnum_v3f16( ; SI-NEXT: s_mov_b32 s6, -1 ; SI-NEXT: s_waitcnt lgkmcnt(0) ; SI-NEXT: v_cvt_f32_f16_e32 v0, s3 -; SI-NEXT: v_cvt_f32_f16_e32 v1, s2 -; SI-NEXT: s_lshr_b32 s2, s2, 16 -; SI-NEXT: s_lshr_b32 s3, s0, 16 -; SI-NEXT: v_cvt_f32_f16_e32 v2, s3 +; SI-NEXT: s_lshr_b32 s3, s2, 16 +; SI-NEXT: s_lshr_b32 s8, s0, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v1, s3 +; SI-NEXT: v_cvt_f32_f16_e32 v2, s8 ; SI-NEXT: v_cvt_f32_f16_e32 v3, s2 -; SI-NEXT: v_cvt_f32_f16_e32 v5, s0 -; SI-NEXT: v_cvt_f32_f16_e32 v4, s1 -; SI-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v3 -; SI-NEXT: v_min_f32_e32 v2, v3, v2 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v5 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_min_f32_e32 v1, v1, v3 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v4 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 -; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 -; SI-NEXT: v_min_f32_e32 v0, v0, v3 +; SI-NEXT: v_cvt_f32_f16_e32 v4, s0 +; SI-NEXT: v_cvt_f32_f16_e32 v5, s1 +; SI-NEXT: v_min_f32_e32 v1, v1, v2 ; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 +; SI-NEXT: v_min_f32_e32 v2, v3, v4 +; SI-NEXT: v_min_f32_e32 v0, v0, v5 +; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 -; SI-NEXT: v_lshlrev_b32_e32 v2, 16, v2 -; SI-NEXT: v_or_b32_e32 v1, v1, v2 +; SI-NEXT: v_lshlrev_b32_e32 v1, 16, v1 +; SI-NEXT: v_or_b32_e32 v1, v2, v1 ; SI-NEXT: buffer_store_short v0, off, s[4:7], 0 offset:4 ; SI-NEXT: buffer_store_dword v1, off, s[4:7], 0 ; SI-NEXT: s_endpgm @@ -893,25 +875,17 @@ define amdgpu_kernel void @minnum_v4f16( ; SI-NEXT: v_cvt_f32_f16_e32 v2, s6 ; SI-NEXT: s_lshr_b32 s6, s7, 16 ; SI-NEXT: v_cvt_f32_f16_e32 v3, s6 +; SI-NEXT: v_cvt_f32_f16_e32 v4, s4 ; SI-NEXT: s_lshr_b32 s6, s5, 16 +; SI-NEXT: s_lshr_b32 s4, s4, 16 ; SI-NEXT: v_cvt_f32_f16_e32 v5, s6 +; SI-NEXT: v_cvt_f32_f16_e32 v7, s4 ; SI-NEXT: v_cvt_f32_f16_e32 v1, s7 -; SI-NEXT: v_cvt_f32_f16_e32 v4, s4 -; SI-NEXT: s_lshr_b32 s4, s4, 16 -; SI-NEXT: v_cvt_f32_f16_e32 v7, s5 -; SI-NEXT: v_cvt_f32_f16_e32 v6, s4 -; SI-NEXT: v_mul_f32_e32 v5, 1.0, v5 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v3 +; SI-NEXT: v_cvt_f32_f16_e32 v6, s5 ; SI-NEXT: v_min_f32_e32 v3, v3, v5 -; SI-NEXT: v_mul_f32_e32 v5, 1.0, v7 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_min_f32_e32 v1, v1, v5 -; SI-NEXT: v_mul_f32_e32 v5, 1.0, v6 -; SI-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; SI-NEXT: v_min_f32_e32 v2, v2, v5 -; SI-NEXT: v_mul_f32_e32 v4, 1.0, v4 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 +; SI-NEXT: v_min_f32_e32 v2, v2, v7 ; SI-NEXT: v_cvt_f16_f32_e32 v3, v3 +; SI-NEXT: v_min_f32_e32 v1, v1, v6 ; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; SI-NEXT: v_min_f32_e32 v0, v0, v4 ; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 @@ -1041,20 +1015,16 @@ define amdgpu_kernel void @fmin_v4f16_imm_a( ; SI-NEXT: v_cvt_f32_f16_e32 v1, s5 ; SI-NEXT: s_lshr_b32 s5, s5, 16 ; SI-NEXT: v_cvt_f32_f16_e32 v0, s4 -; SI-NEXT: v_cvt_f32_f16_e32 v2, s5 ; SI-NEXT: s_lshr_b32 s4, s4, 16 +; SI-NEXT: v_cvt_f32_f16_e32 v2, s5 ; SI-NEXT: v_cvt_f32_f16_e32 v3, s4 -; SI-NEXT: v_mul_f32_e32 v1, 1.0, v1 -; SI-NEXT: v_mul_f32_e32 v2, 1.0, v2 -; SI-NEXT: v_min_f32_e32 v2, 4.0, v2 -; SI-NEXT: v_mul_f32_e32 v3, 1.0, v3 ; SI-NEXT: v_min_f32_e32 v1, 0x40400000, v1 +; SI-NEXT: v_min_f32_e32 v0, 0x41000000, v0 +; SI-NEXT: v_min_f32_e32 v2, 4.0, v2 ; SI-NEXT: v_cvt_f16_f32_e32 v2, v2 ; SI-NEXT: v_min_f32_e32 v3, 2.0, v3 -; SI-NEXT: v_mul_f32_e32 v0, 1.0, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v1, v1 ; SI-NEXT: v_cvt_f16_f32_e32 v3, v3 -; SI-NEXT: v_min_f32_e32 v0, 0x41000000, v0 ; SI-NEXT: v_cvt_f16_f32_e32 v0, v0 ; SI-NEXT: v_lshlrev_b32_e32 v2, 16, v2 ; SI-NEXT: v_or_b32_e32 v1, v1, v2 diff --git a/llvm/test/CodeGen/AMDGPU/lto-lower-module-lds.ll b/llvm/test/CodeGen/AMDGPU/lto-lower-module-lds.ll new file mode 100644 index 0000000000000000000000000000000000000000..f1d946376afe06ae68cf46c990999a6cb161926c --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/lto-lower-module-lds.ll @@ -0,0 +1,47 @@ + +; Default O0 +; RUN: opt -mtriple=amdgcn-- -mcpu=gfx1030 %s -o %t.bc +; RUN: llvm-lto2 run -O0 -cg-opt-level 0 %t.bc -o %t.s -r %t.bc,test,px -debug-pass-manager -debug-pass=Structure 2>&1 | FileCheck %s + +; Unified O0 +; RUN: opt -unified-lto -thinlto-split-lto-unit -thinlto-bc -mtriple=amdgcn-- -mcpu=gfx1030 %s -o %t.bc +; RUN: llvm-lto2 run -unified-lto=full -O0 -cg-opt-level 0 %t.bc -o %t.s -r %t.bc,test,px -debug-pass-manager -debug-pass=Structure 2>&1 | FileCheck %s + +; Default O1 +; RUN: opt -mtriple=amdgcn-- -mcpu=gfx1030 %s -o %t.bc +; RUN: llvm-lto2 run -O1 -cg-opt-level 1 %t.bc -o %t.s -r %t.bc,test,px -debug-pass-manager -debug-pass=Structure 2>&1 | FileCheck %s + +; Unified O1 +; RUN: opt -unified-lto -thinlto-split-lto-unit -thinlto-bc -mtriple=amdgcn-- -mcpu=gfx1030 %s -o %t.bc +; RUN: llvm-lto2 run -unified-lto=full -O1 -cg-opt-level 1 %t.bc -o %t.s -r %t.bc,test,px -debug-pass-manager -debug-pass=Structure 2>&1 | FileCheck %s + +; Default O2 +; RUN: opt -mtriple=amdgcn-- -mcpu=gfx1030 %s -o %t.bc +; RUN: llvm-lto2 run -O2 -cg-opt-level 2 %t.bc -o %t.s -r %t.bc,test,px -debug-pass-manager -debug-pass=Structure 2>&1 | FileCheck %s + +; Unified O2 +; RUN: opt -unified-lto -thinlto-split-lto-unit -thinlto-bc -mtriple=amdgcn-- -mcpu=gfx1030 %s -o %t.bc +; RUN: llvm-lto2 run -unified-lto=full -O2 -cg-opt-level 2 %t.bc -o %t.s -r %t.bc,test,px -debug-pass-manager -debug-pass=Structure 2>&1 | FileCheck %s + +; Default O3 +; RUN: opt -mtriple=amdgcn-- -mcpu=gfx1030 %s -o %t.bc +; RUN: llvm-lto2 run -O3 -cg-opt-level 3 %t.bc -o %t.s -r %t.bc,test,px -debug-pass-manager -debug-pass=Structure 2>&1 | FileCheck %s + +; Unified O3 +; RUN: opt -unified-lto -thinlto-split-lto-unit -thinlto-bc -mtriple=amdgcn-- -mcpu=gfx1030 %s -o %t.bc +; RUN: llvm-lto2 run -unified-lto=full -O3 -cg-opt-level 3 %t.bc -o %t.s -r %t.bc,test,px -debug-pass-manager -debug-pass=Structure 2>&1 | FileCheck %s + +; First print will be from the New PM during the full LTO pipeline. +; Second print will be from the legacy PM during the CG pipeline. + +; CHECK: Running pass: AMDGPULowerModuleLDSPass on [module] +; CHECK: ModulePass Manager +; CHECK: Lower uses of LDS variables from non-kernel functions + +@lds = internal unnamed_addr addrspace(3) global i32 poison, align 4 + +define amdgpu_kernel void @test() { +entry: + store i32 1, ptr addrspace(3) @lds + ret void +} diff --git a/llvm/test/CodeGen/AMDGPU/mad-mix-lo.ll b/llvm/test/CodeGen/AMDGPU/mad-mix-lo.ll index fb3e79b2cf2934278c93e548d8f73bcfabe437b9..5b7f0e72b70da5a868e9dd9678d5427b1f99a0ba 100644 --- a/llvm/test/CodeGen/AMDGPU/mad-mix-lo.ll +++ b/llvm/test/CodeGen/AMDGPU/mad-mix-lo.ll @@ -951,56 +951,70 @@ define <3 x half> @v_mad_mix_v3f32_clamp_postcvt(<3 x half> %src0, <3 x half> %s ; SDAG-GFX1100-LABEL: v_mad_mix_v3f32_clamp_postcvt: ; SDAG-GFX1100: ; %bb.0: ; SDAG-GFX1100-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-GFX1100-NEXT: v_fma_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] ; SDAG-GFX1100-NEXT: v_fma_mixlo_f16 v1, v1, v3, v5 op_sel_hi:[1,1,1] -; SDAG-GFX1100-NEXT: v_fma_mixlo_f16 v3, v0, v2, v4 op_sel_hi:[1,1,1] clamp ; SDAG-GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) -; SDAG-GFX1100-NEXT: v_pack_b32_f16 v1, v1, 0 -; SDAG-GFX1100-NEXT: v_fma_mixhi_f16 v3, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp +; SDAG-GFX1100-NEXT: v_fma_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] +; SDAG-GFX1100-NEXT: v_pack_b32_f16 v0, v1, 0 ; SDAG-GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) -; SDAG-GFX1100-NEXT: v_pk_max_f16 v1, v1, v1 clamp -; SDAG-GFX1100-NEXT: v_mov_b32_e32 v0, v3 +; SDAG-GFX1100-NEXT: v_pk_max_f16 v1, v6, 0 +; SDAG-GFX1100-NEXT: v_pk_max_f16 v2, v0, 0 +; SDAG-GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) +; SDAG-GFX1100-NEXT: v_pk_min_f16 v0, v1, 1.0 op_sel_hi:[1,0] +; SDAG-GFX1100-NEXT: v_pk_min_f16 v1, v2, 1.0 op_sel_hi:[1,0] ; SDAG-GFX1100-NEXT: s_setpc_b64 s[30:31] ; ; SDAG-GFX900-LABEL: v_mad_mix_v3f32_clamp_postcvt: ; SDAG-GFX900: ; %bb.0: ; SDAG-GFX900-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-GFX900-NEXT: v_mad_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] ; SDAG-GFX900-NEXT: v_mad_mixlo_f16 v1, v1, v3, v5 op_sel_hi:[1,1,1] -; SDAG-GFX900-NEXT: v_mad_mixlo_f16 v3, v0, v2, v4 op_sel_hi:[1,1,1] clamp ; SDAG-GFX900-NEXT: v_pack_b32_f16 v1, v1, 0 -; SDAG-GFX900-NEXT: v_mad_mixhi_f16 v3, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp -; SDAG-GFX900-NEXT: v_pk_max_f16 v1, v1, v1 clamp -; SDAG-GFX900-NEXT: v_mov_b32_e32 v0, v3 +; SDAG-GFX900-NEXT: v_mad_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] +; SDAG-GFX900-NEXT: v_pk_max_f16 v1, v1, 0 +; SDAG-GFX900-NEXT: v_pk_max_f16 v0, v6, 0 +; SDAG-GFX900-NEXT: v_pk_min_f16 v0, v0, 1.0 op_sel_hi:[1,0] +; SDAG-GFX900-NEXT: v_pk_min_f16 v1, v1, 1.0 op_sel_hi:[1,0] ; SDAG-GFX900-NEXT: s_setpc_b64 s[30:31] ; ; SDAG-GFX906-LABEL: v_mad_mix_v3f32_clamp_postcvt: ; SDAG-GFX906: ; %bb.0: ; SDAG-GFX906-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-GFX906-NEXT: v_fma_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] ; SDAG-GFX906-NEXT: v_fma_mixlo_f16 v1, v1, v3, v5 op_sel_hi:[1,1,1] -; SDAG-GFX906-NEXT: v_fma_mixlo_f16 v3, v0, v2, v4 op_sel_hi:[1,1,1] clamp ; SDAG-GFX906-NEXT: v_pack_b32_f16 v1, v1, 0 -; SDAG-GFX906-NEXT: v_fma_mixhi_f16 v3, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp -; SDAG-GFX906-NEXT: v_pk_max_f16 v1, v1, v1 clamp -; SDAG-GFX906-NEXT: v_mov_b32_e32 v0, v3 +; SDAG-GFX906-NEXT: v_fma_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] +; SDAG-GFX906-NEXT: v_pk_max_f16 v1, v1, 0 +; SDAG-GFX906-NEXT: v_pk_max_f16 v0, v6, 0 +; SDAG-GFX906-NEXT: v_pk_min_f16 v0, v0, 1.0 op_sel_hi:[1,0] +; SDAG-GFX906-NEXT: v_pk_min_f16 v1, v1, 1.0 op_sel_hi:[1,0] ; SDAG-GFX906-NEXT: s_setpc_b64 s[30:31] ; ; SDAG-VI-LABEL: v_mad_mix_v3f32_clamp_postcvt: ; SDAG-VI: ; %bb.0: ; SDAG-VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v6, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 +; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v1, v1 ; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v0, v0 ; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v7, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 +; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v3, v3 ; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v2, v2 ; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v8, v4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 ; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v4, v4 -; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v1, v1 -; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v3, v3 ; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v5, v5 ; SDAG-VI-NEXT: v_mac_f32_e32 v8, v6, v7 ; SDAG-VI-NEXT: v_mac_f32_e32 v4, v0, v2 -; SDAG-VI-NEXT: v_cvt_f16_f32_sdwa v0, v8 clamp dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD -; SDAG-VI-NEXT: v_cvt_f16_f32_e64 v2, v4 clamp ; SDAG-VI-NEXT: v_mac_f32_e32 v5, v1, v3 -; SDAG-VI-NEXT: v_cvt_f16_f32_e64 v1, v5 clamp +; SDAG-VI-NEXT: v_cvt_f16_f32_e32 v0, v8 +; SDAG-VI-NEXT: v_cvt_f16_f32_e32 v1, v4 +; SDAG-VI-NEXT: v_cvt_f16_f32_e32 v2, v5 +; SDAG-VI-NEXT: v_max_f16_e32 v0, 0, v0 +; SDAG-VI-NEXT: v_max_f16_e32 v3, 0, v1 +; SDAG-VI-NEXT: v_max_f16_e32 v1, 0, v2 +; SDAG-VI-NEXT: v_mov_b32_e32 v2, 0x3c00 +; SDAG-VI-NEXT: v_min_f16_sdwa v0, v0, v2 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:DWORD +; SDAG-VI-NEXT: v_min_f16_e32 v2, 1.0, v3 +; SDAG-VI-NEXT: v_min_f16_e32 v1, 1.0, v1 ; SDAG-VI-NEXT: v_or_b32_e32 v0, v2, v0 ; SDAG-VI-NEXT: s_setpc_b64 s[30:31] ; @@ -1139,63 +1153,80 @@ define <3 x half> @v_mad_mix_v3f32_clamp_postcvt(<3 x half> %src0, <3 x half> %s } define <4 x half> @v_mad_mix_v4f32_clamp_postcvt(<4 x half> %src0, <4 x half> %src1, <4 x half> %src2) #0 { -; GFX1100-LABEL: v_mad_mix_v4f32_clamp_postcvt: -; GFX1100: ; %bb.0: -; GFX1100-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX1100-NEXT: v_fma_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] clamp -; GFX1100-NEXT: v_fma_mixlo_f16 v7, v1, v3, v5 op_sel_hi:[1,1,1] clamp -; GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) -; GFX1100-NEXT: v_fma_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp -; GFX1100-NEXT: v_fma_mixhi_f16 v7, v1, v3, v5 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp -; GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_1) -; GFX1100-NEXT: v_dual_mov_b32 v0, v6 :: v_dual_mov_b32 v1, v7 -; GFX1100-NEXT: s_setpc_b64 s[30:31] +; SDAG-GFX1100-LABEL: v_mad_mix_v4f32_clamp_postcvt: +; SDAG-GFX1100: ; %bb.0: +; SDAG-GFX1100-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-GFX1100-NEXT: v_fma_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] +; SDAG-GFX1100-NEXT: v_fma_mixlo_f16 v7, v1, v3, v5 op_sel_hi:[1,1,1] +; SDAG-GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) +; SDAG-GFX1100-NEXT: v_fma_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] +; SDAG-GFX1100-NEXT: v_fma_mixhi_f16 v7, v1, v3, v5 op_sel:[1,1,1] op_sel_hi:[1,1,1] +; SDAG-GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) +; SDAG-GFX1100-NEXT: v_pk_max_f16 v0, v6, 0 +; SDAG-GFX1100-NEXT: v_pk_max_f16 v1, v7, 0 +; SDAG-GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) +; SDAG-GFX1100-NEXT: v_pk_min_f16 v0, v0, 1.0 op_sel_hi:[1,0] +; SDAG-GFX1100-NEXT: v_pk_min_f16 v1, v1, 1.0 op_sel_hi:[1,0] +; SDAG-GFX1100-NEXT: s_setpc_b64 s[30:31] ; -; GFX900-LABEL: v_mad_mix_v4f32_clamp_postcvt: -; GFX900: ; %bb.0: -; GFX900-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX900-NEXT: v_mad_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] clamp -; GFX900-NEXT: v_mad_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp -; GFX900-NEXT: v_mad_mixlo_f16 v2, v1, v3, v5 op_sel_hi:[1,1,1] clamp -; GFX900-NEXT: v_mad_mixhi_f16 v2, v1, v3, v5 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp -; GFX900-NEXT: v_mov_b32_e32 v0, v6 -; GFX900-NEXT: v_mov_b32_e32 v1, v2 -; GFX900-NEXT: s_setpc_b64 s[30:31] +; SDAG-GFX900-LABEL: v_mad_mix_v4f32_clamp_postcvt: +; SDAG-GFX900: ; %bb.0: +; SDAG-GFX900-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-GFX900-NEXT: v_mad_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] +; SDAG-GFX900-NEXT: v_mad_mixlo_f16 v7, v1, v3, v5 op_sel_hi:[1,1,1] +; SDAG-GFX900-NEXT: v_mad_mixhi_f16 v7, v1, v3, v5 op_sel:[1,1,1] op_sel_hi:[1,1,1] +; SDAG-GFX900-NEXT: v_mad_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] +; SDAG-GFX900-NEXT: v_pk_max_f16 v1, v7, 0 +; SDAG-GFX900-NEXT: v_pk_max_f16 v0, v6, 0 +; SDAG-GFX900-NEXT: v_pk_min_f16 v0, v0, 1.0 op_sel_hi:[1,0] +; SDAG-GFX900-NEXT: v_pk_min_f16 v1, v1, 1.0 op_sel_hi:[1,0] +; SDAG-GFX900-NEXT: s_setpc_b64 s[30:31] ; -; GFX906-LABEL: v_mad_mix_v4f32_clamp_postcvt: -; GFX906: ; %bb.0: -; GFX906-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GFX906-NEXT: v_fma_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] clamp -; GFX906-NEXT: v_fma_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp -; GFX906-NEXT: v_fma_mixlo_f16 v2, v1, v3, v5 op_sel_hi:[1,1,1] clamp -; GFX906-NEXT: v_fma_mixhi_f16 v2, v1, v3, v5 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp -; GFX906-NEXT: v_mov_b32_e32 v0, v6 -; GFX906-NEXT: v_mov_b32_e32 v1, v2 -; GFX906-NEXT: s_setpc_b64 s[30:31] +; SDAG-GFX906-LABEL: v_mad_mix_v4f32_clamp_postcvt: +; SDAG-GFX906: ; %bb.0: +; SDAG-GFX906-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; SDAG-GFX906-NEXT: v_fma_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] +; SDAG-GFX906-NEXT: v_fma_mixlo_f16 v7, v1, v3, v5 op_sel_hi:[1,1,1] +; SDAG-GFX906-NEXT: v_fma_mixhi_f16 v7, v1, v3, v5 op_sel:[1,1,1] op_sel_hi:[1,1,1] +; SDAG-GFX906-NEXT: v_fma_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] +; SDAG-GFX906-NEXT: v_pk_max_f16 v1, v7, 0 +; SDAG-GFX906-NEXT: v_pk_max_f16 v0, v6, 0 +; SDAG-GFX906-NEXT: v_pk_min_f16 v0, v0, 1.0 op_sel_hi:[1,0] +; SDAG-GFX906-NEXT: v_pk_min_f16 v1, v1, 1.0 op_sel_hi:[1,0] +; SDAG-GFX906-NEXT: s_setpc_b64 s[30:31] ; ; SDAG-VI-LABEL: v_mad_mix_v4f32_clamp_postcvt: ; SDAG-VI: ; %bb.0: ; SDAG-VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v6, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v7, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v0, v0 +; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v6, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 +; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v7, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 ; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v1, v1 -; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v8, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v9, v3 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v2, v2 +; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v0, v0 +; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v8, v3 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 +; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v9, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 ; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v3, v3 -; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v10, v5 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v11, v4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 -; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v5, v5 +; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v2, v2 +; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v10, v4 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 +; SDAG-VI-NEXT: v_cvt_f32_f16_sdwa v11, v5 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_1 ; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v4, v4 +; SDAG-VI-NEXT: v_cvt_f32_f16_e32 v5, v5 ; SDAG-VI-NEXT: v_mac_f32_e32 v10, v7, v9 ; SDAG-VI-NEXT: v_mac_f32_e32 v11, v6, v8 -; SDAG-VI-NEXT: v_mac_f32_e32 v5, v1, v3 ; SDAG-VI-NEXT: v_mac_f32_e32 v4, v0, v2 -; SDAG-VI-NEXT: v_cvt_f16_f32_sdwa v0, v11 clamp dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD -; SDAG-VI-NEXT: v_cvt_f16_f32_sdwa v1, v10 clamp dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD -; SDAG-VI-NEXT: v_cvt_f16_f32_e64 v2, v4 clamp -; SDAG-VI-NEXT: v_cvt_f16_f32_e64 v3, v5 clamp +; SDAG-VI-NEXT: v_mac_f32_e32 v5, v1, v3 +; SDAG-VI-NEXT: v_cvt_f16_f32_e32 v0, v10 +; SDAG-VI-NEXT: v_cvt_f16_f32_e32 v1, v11 +; SDAG-VI-NEXT: v_cvt_f16_f32_e32 v2, v4 +; SDAG-VI-NEXT: v_cvt_f16_f32_e32 v3, v5 +; SDAG-VI-NEXT: v_max_f16_e32 v0, 0, v0 +; SDAG-VI-NEXT: v_max_f16_e32 v1, 0, v1 +; SDAG-VI-NEXT: v_max_f16_e32 v2, 0, v2 +; SDAG-VI-NEXT: v_max_f16_e32 v3, 0, v3 +; SDAG-VI-NEXT: v_mov_b32_e32 v4, 0x3c00 +; SDAG-VI-NEXT: v_min_f16_sdwa v1, v1, v4 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:DWORD +; SDAG-VI-NEXT: v_min_f16_sdwa v0, v0, v4 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:DWORD +; SDAG-VI-NEXT: v_min_f16_e32 v3, 1.0, v3 +; SDAG-VI-NEXT: v_min_f16_e32 v2, 1.0, v2 ; SDAG-VI-NEXT: v_or_b32_e32 v0, v2, v0 ; SDAG-VI-NEXT: v_or_b32_e32 v1, v3, v1 ; SDAG-VI-NEXT: s_setpc_b64 s[30:31] @@ -1241,6 +1272,40 @@ define <4 x half> @v_mad_mix_v4f32_clamp_postcvt(<4 x half> %src0, <4 x half> %s ; SDAG-CI-NEXT: v_cvt_f32_f16_e64 v3, v3 clamp ; SDAG-CI-NEXT: s_setpc_b64 s[30:31] ; +; GISEL-GFX1100-LABEL: v_mad_mix_v4f32_clamp_postcvt: +; GISEL-GFX1100: ; %bb.0: +; GISEL-GFX1100-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-GFX1100-NEXT: v_fma_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] clamp +; GISEL-GFX1100-NEXT: v_fma_mixlo_f16 v7, v1, v3, v5 op_sel_hi:[1,1,1] clamp +; GISEL-GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) +; GISEL-GFX1100-NEXT: v_fma_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp +; GISEL-GFX1100-NEXT: v_fma_mixhi_f16 v7, v1, v3, v5 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp +; GISEL-GFX1100-NEXT: s_delay_alu instid0(VALU_DEP_1) +; GISEL-GFX1100-NEXT: v_dual_mov_b32 v0, v6 :: v_dual_mov_b32 v1, v7 +; GISEL-GFX1100-NEXT: s_setpc_b64 s[30:31] +; +; GISEL-GFX900-LABEL: v_mad_mix_v4f32_clamp_postcvt: +; GISEL-GFX900: ; %bb.0: +; GISEL-GFX900-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-GFX900-NEXT: v_mad_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] clamp +; GISEL-GFX900-NEXT: v_mad_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp +; GISEL-GFX900-NEXT: v_mad_mixlo_f16 v2, v1, v3, v5 op_sel_hi:[1,1,1] clamp +; GISEL-GFX900-NEXT: v_mad_mixhi_f16 v2, v1, v3, v5 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp +; GISEL-GFX900-NEXT: v_mov_b32_e32 v0, v6 +; GISEL-GFX900-NEXT: v_mov_b32_e32 v1, v2 +; GISEL-GFX900-NEXT: s_setpc_b64 s[30:31] +; +; GISEL-GFX906-LABEL: v_mad_mix_v4f32_clamp_postcvt: +; GISEL-GFX906: ; %bb.0: +; GISEL-GFX906-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; GISEL-GFX906-NEXT: v_fma_mixlo_f16 v6, v0, v2, v4 op_sel_hi:[1,1,1] clamp +; GISEL-GFX906-NEXT: v_fma_mixhi_f16 v6, v0, v2, v4 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp +; GISEL-GFX906-NEXT: v_fma_mixlo_f16 v2, v1, v3, v5 op_sel_hi:[1,1,1] clamp +; GISEL-GFX906-NEXT: v_fma_mixhi_f16 v2, v1, v3, v5 op_sel:[1,1,1] op_sel_hi:[1,1,1] clamp +; GISEL-GFX906-NEXT: v_mov_b32_e32 v0, v6 +; GISEL-GFX906-NEXT: v_mov_b32_e32 v1, v2 +; GISEL-GFX906-NEXT: s_setpc_b64 s[30:31] +; ; GISEL-VI-LABEL: v_mad_mix_v4f32_clamp_postcvt: ; GISEL-VI: ; %bb.0: ; GISEL-VI-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) diff --git a/llvm/test/CodeGen/AMDGPU/merge-buffer-gfx12.mir b/llvm/test/CodeGen/AMDGPU/merge-buffer-gfx12.mir new file mode 100644 index 0000000000000000000000000000000000000000..d7f5d1a2378955f927940977f324d0211c4c400a --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/merge-buffer-gfx12.mir @@ -0,0 +1,1154 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 2 +# RUN: llc -mtriple=amdgcn -mcpu=gfx1200 -verify-machineinstrs -run-pass si-load-store-opt -o - %s | FileCheck -check-prefixes=GFX12 %s + +--- +name: buffer_load_dword_dwordx3 +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_dwordx3 + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX4_VBUFFER_OFFSET:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_VBUFFER_OFFSET [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX4_VBUFFER_OFFSET]].sub0 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vreg_96 = COPY killed [[BUFFER_LOAD_DWORDX4_VBUFFER_OFFSET]].sub1_sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_96 = BUFFER_LOAD_DWORDX3_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s96), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx3_dword +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dwordx3_dword + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX4_VBUFFER_OFFSET:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_VBUFFER_OFFSET [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vreg_96 = COPY [[BUFFER_LOAD_DWORDX4_VBUFFER_OFFSET]].sub0_sub1_sub2 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX4_VBUFFER_OFFSET]].sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vreg_96 = BUFFER_LOAD_DWORDX3_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s96), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 16, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dwordx2 +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dwordx2_dwordx2 + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX4_VBUFFER_OFFSET:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_VBUFFER_OFFSET [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY [[BUFFER_LOAD_DWORDX4_VBUFFER_OFFSET]].sub0_sub1 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX4_VBUFFER_OFFSET]].sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 12, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dwordx2 +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_dwordx2 + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX3_VBUFFER_OFFSET:%[0-9]+]]:vreg_96 = BUFFER_LOAD_DWORDX3_VBUFFER_OFFSET [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s96), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX3_VBUFFER_OFFSET]].sub0 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX3_VBUFFER_OFFSET]].sub1_sub2 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dword +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dwordx2_dword + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX3_VBUFFER_OFFSET:%[0-9]+]]:vreg_96 = BUFFER_LOAD_DWORDX3_VBUFFER_OFFSET [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s96), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY [[BUFFER_LOAD_DWORDX3_VBUFFER_OFFSET]].sub0_sub1 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX3_VBUFFER_OFFSET]].sub2 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + + +name: buffer_load_dword_dword +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_dword + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET]].sub0 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_32 +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_32 + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET]].sub0 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET]].sub1 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX4_VBUFFER_OFFSET:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_VBUFFER_OFFSET [[REG_SEQUENCE]], $sgpr_null, 16, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vreg_96 = COPY [[BUFFER_LOAD_DWORDX4_VBUFFER_OFFSET]].sub0_sub1_sub2 + ; GFX12-NEXT: [[COPY7:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX4_VBUFFER_OFFSET]].sub3 + ; GFX12-NEXT: [[COPY8:%[0-9]+]]:vreg_64 = COPY [[COPY6]].sub0_sub1 + ; GFX12-NEXT: [[COPY9:%[0-9]+]]:vgpr_32 = COPY killed [[COPY6]].sub2 + ; GFX12-NEXT: [[COPY10:%[0-9]+]]:vgpr_32 = COPY [[COPY8]].sub0 + ; GFX12-NEXT: [[COPY11:%[0-9]+]]:vgpr_32 = COPY killed [[COPY8]].sub1 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX3_VBUFFER_OFFSET:%[0-9]+]]:vreg_96 = BUFFER_LOAD_DWORDX3_VBUFFER_OFFSET [[REG_SEQUENCE]], $sgpr_null, 36, 0, 0, implicit $exec :: (dereferenceable load (s96), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY12:%[0-9]+]]:vreg_64 = COPY [[BUFFER_LOAD_DWORDX3_VBUFFER_OFFSET]].sub0_sub1 + ; GFX12-NEXT: [[COPY13:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX3_VBUFFER_OFFSET]].sub2 + ; GFX12-NEXT: [[COPY14:%[0-9]+]]:vgpr_32 = COPY [[COPY12]].sub0 + ; GFX12-NEXT: [[COPY15:%[0-9]+]]:vgpr_32 = COPY killed [[COPY12]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %9:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 16, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %10:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 20, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %11:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 24, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %12:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 28, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %13:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 36, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %14:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 40, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %15:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 44, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +# +# buffer_store_dword +# + +name: buffer_store_dword_xyz +body: | + bb.0.entry: + liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GFX12-LABEL: name: buffer_store_dword_xyz + ; GFX12: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GFX12-NEXT: {{ $}} + ; GFX12-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr3 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY7:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY7]], %subreg.sub0, [[COPY6]], %subreg.sub1, [[COPY5]], %subreg.sub2, [[COPY4]], %subreg.sub3 + ; GFX12-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:vreg_96 = REG_SEQUENCE [[COPY3]], %subreg.sub0, [[COPY2]], %subreg.sub1, [[COPY1]], %subreg.sub2 + ; GFX12-NEXT: [[REG_SEQUENCE2:%[0-9]+]]:vreg_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[REG_SEQUENCE1]], %subreg.sub1_sub2_sub3 + ; GFX12-NEXT: BUFFER_STORE_DWORDX4_VBUFFER_OFFSET_exact killed [[REG_SEQUENCE2]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable store (s128), align 1, addrspace 4) + %7:vgpr_32 = COPY $vgpr3 + %6:vgpr_32 = COPY $vgpr2 + %5:vgpr_32 = COPY $vgpr1 + %4:vgpr_32 = COPY $vgpr0 + %3:sgpr_32 = COPY $sgpr3 + %2:sgpr_32 = COPY $sgpr2 + %1:sgpr_32 = COPY $sgpr1 + %0:sgpr_32 = COPY $sgpr0 + %13:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %14:vreg_96 = REG_SEQUENCE %4:vgpr_32, %subreg.sub0, %5:vgpr_32, %subreg.sub1, %6:vgpr_32, %subreg.sub2 + BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact %7:vgpr_32, %13:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORDX3_VBUFFER_OFFSET_exact %14:vreg_96, %13:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable store (s96), align 1, addrspace 4) +... +--- + +name: buffer_store_dwordx3_dword +body: | + bb.0.entry: + liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GFX12-LABEL: name: buffer_store_dwordx3_dword + ; GFX12: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GFX12-NEXT: {{ $}} + ; GFX12-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr3 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY7:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY7]], %subreg.sub0, [[COPY6]], %subreg.sub1, [[COPY5]], %subreg.sub2, [[COPY4]], %subreg.sub3 + ; GFX12-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:vreg_96 = REG_SEQUENCE [[COPY3]], %subreg.sub0, [[COPY2]], %subreg.sub1, [[COPY1]], %subreg.sub2 + ; GFX12-NEXT: [[REG_SEQUENCE2:%[0-9]+]]:vreg_128 = REG_SEQUENCE [[REG_SEQUENCE1]], %subreg.sub0_sub1_sub2, [[COPY]], %subreg.sub3 + ; GFX12-NEXT: BUFFER_STORE_DWORDX4_VBUFFER_OFFSET_exact killed [[REG_SEQUENCE2]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable store (s128), align 1, addrspace 4) + %7:vgpr_32 = COPY $vgpr3 + %6:vgpr_32 = COPY $vgpr2 + %5:vgpr_32 = COPY $vgpr1 + %4:vgpr_32 = COPY $vgpr0 + %3:sgpr_32 = COPY $sgpr3 + %2:sgpr_32 = COPY $sgpr2 + %1:sgpr_32 = COPY $sgpr1 + %0:sgpr_32 = COPY $sgpr0 + %13:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %14:vreg_96 = REG_SEQUENCE %4:vgpr_32, %subreg.sub0, %5:vgpr_32, %subreg.sub1, %6:vgpr_32, %subreg.sub2 + BUFFER_STORE_DWORDX3_VBUFFER_OFFSET_exact %14:vreg_96, %13:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable store (s96), align 1, addrspace 4) + BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact %7:vgpr_32, %13:sgpr_128, $sgpr_null, 16, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) +... +--- + +name: buffer_store_dwordx2_dwordx2 +body: | + bb.0.entry: + liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GFX12-LABEL: name: buffer_store_dwordx2_dwordx2 + ; GFX12: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GFX12-NEXT: {{ $}} + ; GFX12-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr3 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY7:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY7]], %subreg.sub0, [[COPY6]], %subreg.sub1, [[COPY5]], %subreg.sub2, [[COPY4]], %subreg.sub3 + ; GFX12-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY3]], %subreg.sub0, [[COPY2]], %subreg.sub1 + ; GFX12-NEXT: [[REG_SEQUENCE2:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY1]], %subreg.sub0, [[COPY]], %subreg.sub1 + ; GFX12-NEXT: [[REG_SEQUENCE3:%[0-9]+]]:vreg_128 = REG_SEQUENCE [[REG_SEQUENCE1]], %subreg.sub0_sub1, [[REG_SEQUENCE2]], %subreg.sub2_sub3 + ; GFX12-NEXT: BUFFER_STORE_DWORDX4_VBUFFER_OFFSET_exact killed [[REG_SEQUENCE3]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable store (s128), align 1, addrspace 4) + %7:vgpr_32 = COPY $vgpr3 + %6:vgpr_32 = COPY $vgpr2 + %5:vgpr_32 = COPY $vgpr1 + %4:vgpr_32 = COPY $vgpr0 + %3:sgpr_32 = COPY $sgpr3 + %2:sgpr_32 = COPY $sgpr2 + %1:sgpr_32 = COPY $sgpr1 + %0:sgpr_32 = COPY $sgpr0 + %13:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %14:vreg_64 = REG_SEQUENCE %4:vgpr_32, %subreg.sub0, %5:vgpr_32, %subreg.sub1 + %15:vreg_64 = REG_SEQUENCE %6:vgpr_32, %subreg.sub0, %7:vgpr_32, %subreg.sub1 + BUFFER_STORE_DWORDX2_VBUFFER_OFFSET_exact %14:vreg_64, %13:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable store (s64), align 1, addrspace 4) + BUFFER_STORE_DWORDX2_VBUFFER_OFFSET_exact %15:vreg_64, %13:sgpr_128, $sgpr_null, 12, 0, 0, implicit $exec :: (dereferenceable store (s64), align 1, addrspace 4) +... +--- + +name: buffer_store_dword_dwordx2 +body: | + bb.0.entry: + liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GFX12-LABEL: name: buffer_store_dword_dwordx2 + ; GFX12: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GFX12-NEXT: {{ $}} + ; GFX12-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr3 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY7:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY7]], %subreg.sub0, [[COPY6]], %subreg.sub1, [[COPY5]], %subreg.sub2, [[COPY4]], %subreg.sub3 + ; GFX12-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY3]], %subreg.sub0, [[COPY2]], %subreg.sub1 + ; GFX12-NEXT: [[REG_SEQUENCE2:%[0-9]+]]:vreg_96 = REG_SEQUENCE [[COPY]], %subreg.sub0, %10:vreg_64, %subreg.sub1_sub2 + ; GFX12-NEXT: BUFFER_STORE_DWORDX3_VBUFFER_OFFSET_exact killed [[REG_SEQUENCE2]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable store (s96), align 1, addrspace 4) + %7:vgpr_32 = COPY $vgpr3 + %6:vgpr_32 = COPY $vgpr2 + %5:vgpr_32 = COPY $vgpr1 + %4:vgpr_32 = COPY $vgpr0 + %3:sgpr_32 = COPY $sgpr3 + %2:sgpr_32 = COPY $sgpr2 + %1:sgpr_32 = COPY $sgpr1 + %0:sgpr_32 = COPY $sgpr0 + %13:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %14:vreg_64 = REG_SEQUENCE %4:vgpr_32, %subreg.sub0, %5:vgpr_32, %subreg.sub1 + BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact %7:vgpr_32, %13:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORDX2_VBUFFER_OFFSET_exact %15:vreg_64, %13:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable store (s64), align 1, addrspace 4) +... +--- + +name: buffer_store_dwordx2_dword +body: | + bb.0.entry: + liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GFX12-LABEL: name: buffer_store_dwordx2_dword + ; GFX12: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3, $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GFX12-NEXT: {{ $}} + ; GFX12-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr3 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY7:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY7]], %subreg.sub0, [[COPY6]], %subreg.sub1, [[COPY5]], %subreg.sub2, [[COPY4]], %subreg.sub3 + ; GFX12-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY3]], %subreg.sub0, [[COPY2]], %subreg.sub1 + ; GFX12-NEXT: [[REG_SEQUENCE2:%[0-9]+]]:vreg_96 = REG_SEQUENCE [[REG_SEQUENCE1]], %subreg.sub0_sub1, [[COPY]], %subreg.sub2 + ; GFX12-NEXT: BUFFER_STORE_DWORDX3_VBUFFER_OFFSET_exact killed [[REG_SEQUENCE2]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable store (s96), align 1, addrspace 4) + %7:vgpr_32 = COPY $vgpr3 + %6:vgpr_32 = COPY $vgpr2 + %5:vgpr_32 = COPY $vgpr1 + %4:vgpr_32 = COPY $vgpr0 + %3:sgpr_32 = COPY $sgpr3 + %2:sgpr_32 = COPY $sgpr2 + %1:sgpr_32 = COPY $sgpr1 + %0:sgpr_32 = COPY $sgpr0 + %13:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %14:vreg_64 = REG_SEQUENCE %4:vgpr_32, %subreg.sub0, %5:vgpr_32, %subreg.sub1 + BUFFER_STORE_DWORDX2_VBUFFER_OFFSET_exact %14:vreg_64, %13:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable store (s64), align 1, addrspace 4) + BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact %7:vgpr_32, %13:sgpr_128, $sgpr_null, 12, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) +... +--- + +name: buffer_store_dword_dword +body: | + bb.0.entry: + liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GFX12-LABEL: name: buffer_store_dword_dword + ; GFX12: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GFX12-NEXT: {{ $}} + ; GFX12-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr3 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY7:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY7]], %subreg.sub0, [[COPY6]], %subreg.sub1, [[COPY5]], %subreg.sub2, [[COPY4]], %subreg.sub3 + ; GFX12-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY1]], %subreg.sub0, [[COPY]], %subreg.sub1 + ; GFX12-NEXT: BUFFER_STORE_DWORDX2_VBUFFER_OFFSET_exact killed [[REG_SEQUENCE1]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable store (s64), align 1, addrspace 4) + %7:vgpr_32 = COPY $vgpr3 + %6:vgpr_32 = COPY $vgpr2 + %5:vgpr_32 = COPY $vgpr1 + %4:vgpr_32 = COPY $vgpr0 + %3:sgpr_32 = COPY $sgpr3 + %2:sgpr_32 = COPY $sgpr2 + %1:sgpr_32 = COPY $sgpr1 + %0:sgpr_32 = COPY $sgpr0 + %13:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact %6:vgpr_32, %13:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact %7:vgpr_32, %13:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) +... +--- + +name: buffer_store_dword_32 +body: | + bb.0.entry: + liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3, $vgpr4, $vgpr5, $vgpr6, $vgpr7, $vgpr8 + ; GFX12-LABEL: name: buffer_store_dword_32 + ; GFX12: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3, $vgpr4, $vgpr5, $vgpr6, $vgpr7, $vgpr8 + ; GFX12-NEXT: {{ $}} + ; GFX12-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr8 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr7 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr6 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:vgpr_32 = COPY $vgpr5 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr4 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY $vgpr3 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; GFX12-NEXT: [[COPY7:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; GFX12-NEXT: [[COPY8:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[COPY9:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY10:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY11:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY12:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY12]], %subreg.sub0, [[COPY11]], %subreg.sub1, [[COPY10]], %subreg.sub2, [[COPY9]], %subreg.sub3 + ; GFX12-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY8]], %subreg.sub0, [[COPY7]], %subreg.sub1 + ; GFX12-NEXT: BUFFER_STORE_DWORDX2_VBUFFER_OFFSET_exact killed [[REG_SEQUENCE1]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable store (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[REG_SEQUENCE2:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY6]], %subreg.sub0, [[COPY5]], %subreg.sub1 + ; GFX12-NEXT: [[REG_SEQUENCE3:%[0-9]+]]:vreg_96 = REG_SEQUENCE killed [[REG_SEQUENCE2]], %subreg.sub0_sub1, [[COPY4]], %subreg.sub2 + ; GFX12-NEXT: [[REG_SEQUENCE4:%[0-9]+]]:vreg_128 = REG_SEQUENCE killed [[REG_SEQUENCE3]], %subreg.sub0_sub1_sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: BUFFER_STORE_DWORDX4_VBUFFER_OFFSET_exact killed [[REG_SEQUENCE4]], [[REG_SEQUENCE]], $sgpr_null, 16, 0, 0, implicit $exec :: (dereferenceable store (s128), align 1, addrspace 4) + ; GFX12-NEXT: [[REG_SEQUENCE5:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY2]], %subreg.sub0, [[COPY1]], %subreg.sub1 + ; GFX12-NEXT: [[REG_SEQUENCE6:%[0-9]+]]:vreg_96 = REG_SEQUENCE killed [[REG_SEQUENCE5]], %subreg.sub0_sub1, [[COPY]], %subreg.sub2 + ; GFX12-NEXT: BUFFER_STORE_DWORDX3_VBUFFER_OFFSET_exact killed [[REG_SEQUENCE6]], [[REG_SEQUENCE]], $sgpr_null, 36, 0, 0, implicit $exec :: (dereferenceable store (s96), align 1, addrspace 4) + %12:vgpr_32 = COPY $vgpr8 + %11:vgpr_32 = COPY $vgpr7 + %10:vgpr_32 = COPY $vgpr6 + %9:vgpr_32 = COPY $vgpr5 + %8:vgpr_32 = COPY $vgpr4 + %7:vgpr_32 = COPY $vgpr3 + %6:vgpr_32 = COPY $vgpr2 + %5:vgpr_32 = COPY $vgpr1 + %4:vgpr_32 = COPY $vgpr0 + %3:sgpr_32 = COPY $sgpr3 + %2:sgpr_32 = COPY $sgpr2 + %1:sgpr_32 = COPY $sgpr1 + %0:sgpr_32 = COPY $sgpr0 + %13:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact %4:vgpr_32, %13:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact %5:vgpr_32, %13:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact %6:vgpr_32, %13:sgpr_128, $sgpr_null, 16, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact %7:vgpr_32, %13:sgpr_128, $sgpr_null, 20, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact %8:vgpr_32, %13:sgpr_128, $sgpr_null, 24, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact %9:vgpr_32, %13:sgpr_128, $sgpr_null, 28, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact %10:vgpr_32, %13:sgpr_128, $sgpr_null, 36, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact %11:vgpr_32, %13:sgpr_128, $sgpr_null, 40, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact %12:vgpr_32, %13:sgpr_128, $sgpr_null, 44, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_not_merged_swizzled_0 +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_not_merged_swizzled_0 + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORD_VBUFFER_OFFSET:%[0-9]+]]:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET [[REG_SEQUENCE]], $sgpr_null, 4, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GFX12-NEXT: [[BUFFER_LOAD_DWORD_VBUFFER_OFFSET1:%[0-9]+]]:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET [[REG_SEQUENCE]], $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 4, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_not_merged_swizzled_1 +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_not_merged_swizzled_1 + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORD_VBUFFER_OFFSET:%[0-9]+]]:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GFX12-NEXT: [[BUFFER_LOAD_DWORD_VBUFFER_OFFSET1:%[0-9]+]]:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET [[REG_SEQUENCE]], $sgpr_null, 8, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 8, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_merge_across_swizzle +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_merge_across_swizzle + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET]].sub0 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET]].sub1 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORD_VBUFFER_OFFSET:%[0-9]+]]:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET [[REG_SEQUENCE]], $sgpr_null, 12, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %5:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %4:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %6:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %4:sgpr_128, $sgpr_null, 12, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %4:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_not_merge_across_swizzled_store +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_not_merge_across_swizzled_store + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORD_VBUFFER_OFFSET:%[0-9]+]]:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GFX12-NEXT: BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 6, 0, 1, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + ; GFX12-NEXT: [[BUFFER_LOAD_DWORD_VBUFFER_OFFSET1:%[0-9]+]]:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET [[REG_SEQUENCE]], $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %6:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact %4:vgpr_32, %5:sgpr_128, $sgpr_null, 6, 0, 1, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_merge_across_swizzled_store +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_merge_across_swizzled_store + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET]].sub0 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_VBUFFER_OFFSET]].sub1 + ; GFX12-NEXT: BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 12, 0, 1, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %6:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact %4:vgpr_32, %5:sgpr_128, $sgpr_null, 12, 0, 1, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_OFFSET %5:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dword_idxen +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_dword_idxen + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN]].sub0 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_IDXEN %4, %5:sgpr_128, $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_IDXEN %4, %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dwordx2_idxen +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_dwordx2_idxen + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX3_VBUFFER_IDXEN:%[0-9]+]]:vreg_96 = BUFFER_LOAD_DWORDX3_VBUFFER_IDXEN [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX3_VBUFFER_IDXEN]].sub0 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX3_VBUFFER_IDXEN]].sub1_sub2 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_IDXEN %4, %5:sgpr_128, $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN %4, %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dwordx2_idxen +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dwordx2_dwordx2_idxen + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX4_VBUFFER_IDXEN:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_VBUFFER_IDXEN [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY [[BUFFER_LOAD_DWORDX4_VBUFFER_IDXEN]].sub0_sub1 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX4_VBUFFER_IDXEN]].sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN %4, %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN %4, %5:sgpr_128, $sgpr_null, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dwordx3_idxen +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_dwordx3_idxen + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX4_VBUFFER_IDXEN:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_VBUFFER_IDXEN [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX4_VBUFFER_IDXEN]].sub0 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vreg_96 = COPY killed [[BUFFER_LOAD_DWORDX4_VBUFFER_IDXEN]].sub1_sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_IDXEN %4, %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_96 = BUFFER_LOAD_DWORDX3_VBUFFER_IDXEN %4, %5:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dword_bothen +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_dword_bothen + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN]].sub0 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_BOTHEN %4, %5:sgpr_128, $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_BOTHEN %4, %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dwordx2_bothen +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_dwordx2_bothen + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX3_VBUFFER_BOTHEN:%[0-9]+]]:vreg_96 = BUFFER_LOAD_DWORDX3_VBUFFER_BOTHEN [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX3_VBUFFER_BOTHEN]].sub0 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX3_VBUFFER_BOTHEN]].sub1_sub2 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_BOTHEN %4, %5:sgpr_128, $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN %4, %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dwordx2_bothen +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dwordx2_dwordx2_bothen + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX4_VBUFFER_BOTHEN:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_VBUFFER_BOTHEN [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY [[BUFFER_LOAD_DWORDX4_VBUFFER_BOTHEN]].sub0_sub1 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX4_VBUFFER_BOTHEN]].sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN %4, %5:sgpr_128, $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN %4, %5:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dwordx3_bothen +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_dwordx3_bothen + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX4_VBUFFER_BOTHEN:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_VBUFFER_BOTHEN [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX4_VBUFFER_BOTHEN]].sub0 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vreg_96 = COPY killed [[BUFFER_LOAD_DWORDX4_VBUFFER_BOTHEN]].sub1_sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_BOTHEN %4, %5:sgpr_128, $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_96 = BUFFER_LOAD_DWORDX3_VBUFFER_BOTHEN %4, %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dword_idxen_exact +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_dword_idxen_exact + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact]].sub0 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact %4, %5:sgpr_128, $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact %4, %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dwordx2_idxen_exact +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_dwordx2_idxen_exact + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX3_VBUFFER_IDXEN_exact:%[0-9]+]]:vreg_96 = BUFFER_LOAD_DWORDX3_VBUFFER_IDXEN_exact [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX3_VBUFFER_IDXEN_exact]].sub0 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX3_VBUFFER_IDXEN_exact]].sub1_sub2 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact %4, %5:sgpr_128, $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact %4, %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dwordx2_idxen_exact +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dwordx2_dwordx2_idxen_exact + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX4_VBUFFER_IDXEN_exact:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_VBUFFER_IDXEN_exact [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY [[BUFFER_LOAD_DWORDX4_VBUFFER_IDXEN_exact]].sub0_sub1 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX4_VBUFFER_IDXEN_exact]].sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact %4, %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact %4, %5:sgpr_128, $sgpr_null, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dwordx3_idxen_exact +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_dwordx3_idxen_exact + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX4_VBUFFER_IDXEN_exact:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_VBUFFER_IDXEN_exact [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX4_VBUFFER_IDXEN_exact]].sub0 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vreg_96 = COPY killed [[BUFFER_LOAD_DWORDX4_VBUFFER_IDXEN_exact]].sub1_sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact %4, %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_96 = BUFFER_LOAD_DWORDX3_VBUFFER_IDXEN_exact %4, %5:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dword_dword_idxen_exact +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_dword_dword_idxen_exact + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX3_VBUFFER_IDXEN_exact:%[0-9]+]]:vreg_96 = BUFFER_LOAD_DWORDX3_VBUFFER_IDXEN_exact [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s96), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY [[BUFFER_LOAD_DWORDX3_VBUFFER_IDXEN_exact]].sub0_sub1 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX3_VBUFFER_IDXEN_exact]].sub2 + ; GFX12-NEXT: [[COPY7:%[0-9]+]]:vgpr_32 = COPY [[COPY5]].sub0 + ; GFX12-NEXT: [[COPY8:%[0-9]+]]:vgpr_32 = COPY killed [[COPY5]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact %4, %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact %4, %5:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %9:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact %4, %5:sgpr_128, $sgpr_null, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dword_dword_idxen_exact_swizzled_0 +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_dword_dword_idxen_exact_swizzled_0 + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact:%[0-9]+]]:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact]].sub0 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact %4, %5:sgpr_128, $sgpr_null, 4, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact %4, %5:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %9:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact %4, %5:sgpr_128, $sgpr_null, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dword_bothen_exact +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_dword_bothen_exact + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact]].sub0 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact %4, %5:sgpr_128, $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact %4, %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dwordx2_bothen_exact +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_dwordx2_bothen_exact + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX3_VBUFFER_BOTHEN_exact:%[0-9]+]]:vreg_96 = BUFFER_LOAD_DWORDX3_VBUFFER_BOTHEN_exact [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX3_VBUFFER_BOTHEN_exact]].sub0 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX3_VBUFFER_BOTHEN_exact]].sub1_sub2 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact %4, %5:sgpr_128, $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact %4, %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dwordx2_bothen_exact +body: | + bb.0.entry: + + ; GFX12-LABEL: name: buffer_load_dwordx2_dwordx2_bothen_exact + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX4_VBUFFER_BOTHEN_exact:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_VBUFFER_BOTHEN_exact [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY [[BUFFER_LOAD_DWORDX4_VBUFFER_BOTHEN_exact]].sub0_sub1 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX4_VBUFFER_BOTHEN_exact]].sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact %4, %5:sgpr_128, $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact %4, %5:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dwordx3_bothen_exact +body: | + bb.0.entry: + + ; GFX12-LABEL: name: buffer_load_dword_dwordx3_bothen_exact + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX4_VBUFFER_BOTHEN_exact:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_VBUFFER_BOTHEN_exact [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX4_VBUFFER_BOTHEN_exact]].sub0 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vreg_96 = COPY killed [[BUFFER_LOAD_DWORDX4_VBUFFER_BOTHEN_exact]].sub1_sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact %4, %5:sgpr_128, $sgpr_null, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_96 = BUFFER_LOAD_DWORDX3_VBUFFER_BOTHEN_exact %4, %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dword_dword_bothen_exact +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_dword_dword_bothen_exact + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX3_VBUFFER_BOTHEN_exact:%[0-9]+]]:vreg_96 = BUFFER_LOAD_DWORDX3_VBUFFER_BOTHEN_exact [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s96), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY [[BUFFER_LOAD_DWORDX3_VBUFFER_BOTHEN_exact]].sub0_sub1 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX3_VBUFFER_BOTHEN_exact]].sub2 + ; GFX12-NEXT: [[COPY7:%[0-9]+]]:vgpr_32 = COPY [[COPY5]].sub0 + ; GFX12-NEXT: [[COPY8:%[0-9]+]]:vgpr_32 = COPY killed [[COPY5]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact %4, %5:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact %4, %5:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %9:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact %4, %5:sgpr_128, $sgpr_null, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dword_dword_bothen_exact_swizzled_0 +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dword_dword_dword_bothen_exact_swizzled_0 + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact:%[0-9]+]]:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact]].sub0 + ; GFX12-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact %4, %5:sgpr_128, $sgpr_null, 4, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact %4, %5:sgpr_128, $sgpr_null, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %9:vgpr_32 = BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact %4, %5:sgpr_128, $sgpr_null, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dwordx2_bothen_exact_diff_vaddr +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dwordx2_dwordx2_bothen_exact_diff_vaddr + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY $vgpr1 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact1:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact [[COPY5]], [[REG_SEQUENCE]], $sgpr_null, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:vreg_64 = COPY $vgpr1 + %6:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %8:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact %4, %6:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %9:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact %5, %6:sgpr_128, $sgpr_null, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dwordx2_bothen_exact_diff_srsrc +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dwordx2_dwordx2_bothen_exact_diff_srsrc + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr4 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY1]], %subreg.sub0, [[COPY2]], %subreg.sub1, [[COPY3]], %subreg.sub2, [[COPY4]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact [[COPY5]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact1:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact [[COPY5]], [[REG_SEQUENCE1]], $sgpr_null, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:sgpr_32 = COPY $sgpr4 + %5:vreg_64 = COPY $vgpr0 + %6:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:sgpr_128 = REG_SEQUENCE %1:sgpr_32, %subreg.sub0, %2:sgpr_32, %subreg.sub1, %3:sgpr_32, %subreg.sub2, %4:sgpr_32, %subreg.sub3 + %8:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact %5, %6:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %9:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_BOTHEN_exact %5, %7:sgpr_128, $sgpr_null, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dwordx2_idxen_exact_diff_vaddr +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dwordx2_dwordx2_idxen_exact_diff_vaddr + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact [[COPY4]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact1:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact [[COPY5]], [[REG_SEQUENCE]], $sgpr_null, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:vgpr_32 = COPY $vgpr1 + %6:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %8:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact %4, %6:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %9:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact %5, %6:sgpr_128, $sgpr_null, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dwordx2_idxen_exact_diff_srsrc +body: | + bb.0.entry: + ; GFX12-LABEL: name: buffer_load_dwordx2_dwordx2_idxen_exact_diff_srsrc + ; GFX12: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX12-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX12-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX12-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr4 + ; GFX12-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GFX12-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX12-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY1]], %subreg.sub0, [[COPY2]], %subreg.sub1, [[COPY3]], %subreg.sub2, [[COPY4]], %subreg.sub3 + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact [[COPY5]], [[REG_SEQUENCE]], $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GFX12-NEXT: [[BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact1:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact [[COPY5]], [[REG_SEQUENCE1]], $sgpr_null, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:sgpr_32 = COPY $sgpr4 + %5:vgpr_32 = COPY $vgpr0 + %6:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:sgpr_128 = REG_SEQUENCE %1:sgpr_32, %subreg.sub0, %2:sgpr_32, %subreg.sub1, %3:sgpr_32, %subreg.sub2, %4:sgpr_32, %subreg.sub3 + %8:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact %5, %6:sgpr_128, $sgpr_null, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %9:vreg_64 = BUFFER_LOAD_DWORDX2_VBUFFER_IDXEN_exact %5, %7:sgpr_128, $sgpr_null, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... diff --git a/llvm/test/CodeGen/AMDGPU/merge-buffer.mir b/llvm/test/CodeGen/AMDGPU/merge-buffer.mir new file mode 100644 index 0000000000000000000000000000000000000000..1c6d429d20eac26c5b9dc27d18a1e81858f3ca9b --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/merge-buffer.mir @@ -0,0 +1,1130 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 2 +# RUN: llc -mtriple=amdgcn -mcpu=gfx900 -verify-machineinstrs -run-pass si-load-store-opt -o - %s | FileCheck -check-prefixes=GCN %s +# RUN: llc -mtriple=amdgcn -mcpu=gfx1010 -verify-machineinstrs -run-pass si-load-store-opt -o - %s | FileCheck -check-prefixes=GCN %s +# RUN: llc -mtriple=amdgcn -mcpu=gfx1100 -verify-machineinstrs -run-pass si-load-store-opt -o - %s | FileCheck -check-prefixes=GCN %s + +--- +name: buffer_load_dword_dwordx3 +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_dwordx3 + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX4_OFFSET:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_OFFSET [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 4) + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX4_OFFSET]].sub0 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vreg_96 = COPY killed [[BUFFER_LOAD_DWORDX4_OFFSET]].sub1_sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_96 = BUFFER_LOAD_DWORDX3_OFFSET %5:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s96), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx3_dword +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dwordx3_dword + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX4_OFFSET:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_OFFSET [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 4) + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vreg_96 = COPY [[BUFFER_LOAD_DWORDX4_OFFSET]].sub0_sub1_sub2 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX4_OFFSET]].sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vreg_96 = BUFFER_LOAD_DWORDX3_OFFSET %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s96), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 16, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dwordx2 +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dwordx2_dwordx2 + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX4_OFFSET:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_OFFSET [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 4) + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY [[BUFFER_LOAD_DWORDX4_OFFSET]].sub0_sub1 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX4_OFFSET]].sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vreg_64 = BUFFER_LOAD_DWORDX2_OFFSET %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_OFFSET %5:sgpr_128, 0, 12, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dwordx2 +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_dwordx2 + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX3_OFFSET:%[0-9]+]]:vreg_96 = BUFFER_LOAD_DWORDX3_OFFSET [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s96), align 1, addrspace 4) + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX3_OFFSET]].sub0 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX3_OFFSET]].sub1_sub2 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_OFFSET %5:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dword +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dwordx2_dword + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX3_OFFSET:%[0-9]+]]:vreg_96 = BUFFER_LOAD_DWORDX3_OFFSET [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s96), align 1, addrspace 4) + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY [[BUFFER_LOAD_DWORDX3_OFFSET]].sub0_sub1 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX3_OFFSET]].sub2 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vreg_64 = BUFFER_LOAD_DWORDX2_OFFSET %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + + +name: buffer_load_dword_dword +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_dword + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX2_OFFSET:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_OFFSET [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_OFFSET]].sub0 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_OFFSET]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_32 +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_32 + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX2_OFFSET:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_OFFSET [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_OFFSET]].sub0 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_OFFSET]].sub1 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX4_OFFSET:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_OFFSET [[REG_SEQUENCE]], 0, 16, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 4) + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vreg_96 = COPY [[BUFFER_LOAD_DWORDX4_OFFSET]].sub0_sub1_sub2 + ; GCN-NEXT: [[COPY7:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX4_OFFSET]].sub3 + ; GCN-NEXT: [[COPY8:%[0-9]+]]:vreg_64 = COPY [[COPY6]].sub0_sub1 + ; GCN-NEXT: [[COPY9:%[0-9]+]]:vgpr_32 = COPY killed [[COPY6]].sub2 + ; GCN-NEXT: [[COPY10:%[0-9]+]]:vgpr_32 = COPY [[COPY8]].sub0 + ; GCN-NEXT: [[COPY11:%[0-9]+]]:vgpr_32 = COPY killed [[COPY8]].sub1 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX3_OFFSET:%[0-9]+]]:vreg_96 = BUFFER_LOAD_DWORDX3_OFFSET [[REG_SEQUENCE]], 0, 36, 0, 0, implicit $exec :: (dereferenceable load (s96), align 1, addrspace 4) + ; GCN-NEXT: [[COPY12:%[0-9]+]]:vreg_64 = COPY [[BUFFER_LOAD_DWORDX3_OFFSET]].sub0_sub1 + ; GCN-NEXT: [[COPY13:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX3_OFFSET]].sub2 + ; GCN-NEXT: [[COPY14:%[0-9]+]]:vgpr_32 = COPY [[COPY12]].sub0 + ; GCN-NEXT: [[COPY15:%[0-9]+]]:vgpr_32 = COPY killed [[COPY12]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %9:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 16, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %10:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 20, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %11:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 24, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %12:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 28, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %13:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 36, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %14:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 40, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %15:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 44, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +# +# buffer_store_dword +# + +name: buffer_store_dword_xyz +body: | + bb.0.entry: + liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GCN-LABEL: name: buffer_store_dword_xyz + ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GCN-NEXT: {{ $}} + ; GCN-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr3 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY7:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY7]], %subreg.sub0, [[COPY6]], %subreg.sub1, [[COPY5]], %subreg.sub2, [[COPY4]], %subreg.sub3 + ; GCN-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:vreg_96 = REG_SEQUENCE [[COPY3]], %subreg.sub0, [[COPY2]], %subreg.sub1, [[COPY1]], %subreg.sub2 + ; GCN-NEXT: [[REG_SEQUENCE2:%[0-9]+]]:vreg_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[REG_SEQUENCE1]], %subreg.sub1_sub2_sub3 + ; GCN-NEXT: BUFFER_STORE_DWORDX4_OFFSET_exact killed [[REG_SEQUENCE2]], [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable store (s128), align 1, addrspace 4) + %7:vgpr_32 = COPY $vgpr3 + %6:vgpr_32 = COPY $vgpr2 + %5:vgpr_32 = COPY $vgpr1 + %4:vgpr_32 = COPY $vgpr0 + %3:sgpr_32 = COPY $sgpr3 + %2:sgpr_32 = COPY $sgpr2 + %1:sgpr_32 = COPY $sgpr1 + %0:sgpr_32 = COPY $sgpr0 + %13:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %14:vreg_96 = REG_SEQUENCE %4:vgpr_32, %subreg.sub0, %5:vgpr_32, %subreg.sub1, %6:vgpr_32, %subreg.sub2 + BUFFER_STORE_DWORD_OFFSET_exact %7:vgpr_32, %13:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORDX3_OFFSET_exact %14:vreg_96, %13:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable store (s96), align 1, addrspace 4) +... +--- + +name: buffer_store_dwordx3_dword +body: | + bb.0.entry: + liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GCN-LABEL: name: buffer_store_dwordx3_dword + ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GCN-NEXT: {{ $}} + ; GCN-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr3 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY7:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY7]], %subreg.sub0, [[COPY6]], %subreg.sub1, [[COPY5]], %subreg.sub2, [[COPY4]], %subreg.sub3 + ; GCN-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:vreg_96 = REG_SEQUENCE [[COPY3]], %subreg.sub0, [[COPY2]], %subreg.sub1, [[COPY1]], %subreg.sub2 + ; GCN-NEXT: [[REG_SEQUENCE2:%[0-9]+]]:vreg_128 = REG_SEQUENCE [[REG_SEQUENCE1]], %subreg.sub0_sub1_sub2, [[COPY]], %subreg.sub3 + ; GCN-NEXT: BUFFER_STORE_DWORDX4_OFFSET_exact killed [[REG_SEQUENCE2]], [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable store (s128), align 1, addrspace 4) + %7:vgpr_32 = COPY $vgpr3 + %6:vgpr_32 = COPY $vgpr2 + %5:vgpr_32 = COPY $vgpr1 + %4:vgpr_32 = COPY $vgpr0 + %3:sgpr_32 = COPY $sgpr3 + %2:sgpr_32 = COPY $sgpr2 + %1:sgpr_32 = COPY $sgpr1 + %0:sgpr_32 = COPY $sgpr0 + %13:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %14:vreg_96 = REG_SEQUENCE %4:vgpr_32, %subreg.sub0, %5:vgpr_32, %subreg.sub1, %6:vgpr_32, %subreg.sub2 + BUFFER_STORE_DWORDX3_OFFSET_exact %14:vreg_96, %13:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable store (s96), align 1, addrspace 4) + BUFFER_STORE_DWORD_OFFSET_exact %7:vgpr_32, %13:sgpr_128, 0, 16, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) +... +--- + +name: buffer_store_dwordx2_dwordx2 +body: | + bb.0.entry: + liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GCN-LABEL: name: buffer_store_dwordx2_dwordx2 + ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GCN-NEXT: {{ $}} + ; GCN-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr3 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY7:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY7]], %subreg.sub0, [[COPY6]], %subreg.sub1, [[COPY5]], %subreg.sub2, [[COPY4]], %subreg.sub3 + ; GCN-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY3]], %subreg.sub0, [[COPY2]], %subreg.sub1 + ; GCN-NEXT: [[REG_SEQUENCE2:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY1]], %subreg.sub0, [[COPY]], %subreg.sub1 + ; GCN-NEXT: [[REG_SEQUENCE3:%[0-9]+]]:vreg_128 = REG_SEQUENCE [[REG_SEQUENCE1]], %subreg.sub0_sub1, [[REG_SEQUENCE2]], %subreg.sub2_sub3 + ; GCN-NEXT: BUFFER_STORE_DWORDX4_OFFSET_exact killed [[REG_SEQUENCE3]], [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable store (s128), align 1, addrspace 4) + %7:vgpr_32 = COPY $vgpr3 + %6:vgpr_32 = COPY $vgpr2 + %5:vgpr_32 = COPY $vgpr1 + %4:vgpr_32 = COPY $vgpr0 + %3:sgpr_32 = COPY $sgpr3 + %2:sgpr_32 = COPY $sgpr2 + %1:sgpr_32 = COPY $sgpr1 + %0:sgpr_32 = COPY $sgpr0 + %13:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %14:vreg_64 = REG_SEQUENCE %4:vgpr_32, %subreg.sub0, %5:vgpr_32, %subreg.sub1 + %15:vreg_64 = REG_SEQUENCE %6:vgpr_32, %subreg.sub0, %7:vgpr_32, %subreg.sub1 + BUFFER_STORE_DWORDX2_OFFSET_exact %14:vreg_64, %13:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable store (s64), align 1, addrspace 4) + BUFFER_STORE_DWORDX2_OFFSET_exact %15:vreg_64, %13:sgpr_128, 0, 12, 0, 0, implicit $exec :: (dereferenceable store (s64), align 1, addrspace 4) +... +--- + +name: buffer_store_dword_dwordx2 +body: | + bb.0.entry: + liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GCN-LABEL: name: buffer_store_dword_dwordx2 + ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GCN-NEXT: {{ $}} + ; GCN-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr3 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY7:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY7]], %subreg.sub0, [[COPY6]], %subreg.sub1, [[COPY5]], %subreg.sub2, [[COPY4]], %subreg.sub3 + ; GCN-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY3]], %subreg.sub0, [[COPY2]], %subreg.sub1 + ; GCN-NEXT: [[REG_SEQUENCE2:%[0-9]+]]:vreg_96 = REG_SEQUENCE [[COPY]], %subreg.sub0, %10:vreg_64, %subreg.sub1_sub2 + ; GCN-NEXT: BUFFER_STORE_DWORDX3_OFFSET_exact killed [[REG_SEQUENCE2]], [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable store (s96), align 1, addrspace 4) + %7:vgpr_32 = COPY $vgpr3 + %6:vgpr_32 = COPY $vgpr2 + %5:vgpr_32 = COPY $vgpr1 + %4:vgpr_32 = COPY $vgpr0 + %3:sgpr_32 = COPY $sgpr3 + %2:sgpr_32 = COPY $sgpr2 + %1:sgpr_32 = COPY $sgpr1 + %0:sgpr_32 = COPY $sgpr0 + %13:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %14:vreg_64 = REG_SEQUENCE %4:vgpr_32, %subreg.sub0, %5:vgpr_32, %subreg.sub1 + BUFFER_STORE_DWORD_OFFSET_exact %7:vgpr_32, %13:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORDX2_OFFSET_exact %15:vreg_64, %13:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable store (s64), align 1, addrspace 4) +... +--- + +name: buffer_store_dwordx2_dword +body: | + bb.0.entry: + liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GCN-LABEL: name: buffer_store_dwordx2_dword + ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3, $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GCN-NEXT: {{ $}} + ; GCN-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr3 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY7:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY7]], %subreg.sub0, [[COPY6]], %subreg.sub1, [[COPY5]], %subreg.sub2, [[COPY4]], %subreg.sub3 + ; GCN-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY3]], %subreg.sub0, [[COPY2]], %subreg.sub1 + ; GCN-NEXT: [[REG_SEQUENCE2:%[0-9]+]]:vreg_96 = REG_SEQUENCE [[REG_SEQUENCE1]], %subreg.sub0_sub1, [[COPY]], %subreg.sub2 + ; GCN-NEXT: BUFFER_STORE_DWORDX3_OFFSET_exact killed [[REG_SEQUENCE2]], [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable store (s96), align 1, addrspace 4) + %7:vgpr_32 = COPY $vgpr3 + %6:vgpr_32 = COPY $vgpr2 + %5:vgpr_32 = COPY $vgpr1 + %4:vgpr_32 = COPY $vgpr0 + %3:sgpr_32 = COPY $sgpr3 + %2:sgpr_32 = COPY $sgpr2 + %1:sgpr_32 = COPY $sgpr1 + %0:sgpr_32 = COPY $sgpr0 + %13:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %14:vreg_64 = REG_SEQUENCE %4:vgpr_32, %subreg.sub0, %5:vgpr_32, %subreg.sub1 + BUFFER_STORE_DWORDX2_OFFSET_exact %14:vreg_64, %13:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable store (s64), align 1, addrspace 4) + BUFFER_STORE_DWORD_OFFSET_exact %7:vgpr_32, %13:sgpr_128, 0, 12, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) +... +--- + +name: buffer_store_dword_dword +body: | + bb.0.entry: + liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GCN-LABEL: name: buffer_store_dword_dword + ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3 + ; GCN-NEXT: {{ $}} + ; GCN-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr3 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY7:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY7]], %subreg.sub0, [[COPY6]], %subreg.sub1, [[COPY5]], %subreg.sub2, [[COPY4]], %subreg.sub3 + ; GCN-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY1]], %subreg.sub0, [[COPY]], %subreg.sub1 + ; GCN-NEXT: BUFFER_STORE_DWORDX2_OFFSET_exact killed [[REG_SEQUENCE1]], [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable store (s64), align 1, addrspace 4) + %7:vgpr_32 = COPY $vgpr3 + %6:vgpr_32 = COPY $vgpr2 + %5:vgpr_32 = COPY $vgpr1 + %4:vgpr_32 = COPY $vgpr0 + %3:sgpr_32 = COPY $sgpr3 + %2:sgpr_32 = COPY $sgpr2 + %1:sgpr_32 = COPY $sgpr1 + %0:sgpr_32 = COPY $sgpr0 + %13:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + BUFFER_STORE_DWORD_OFFSET_exact %6:vgpr_32, %13:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_OFFSET_exact %7:vgpr_32, %13:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) +... +--- + +name: buffer_store_dword_32 +body: | + bb.0.entry: + liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3, $vgpr4, $vgpr5, $vgpr6, $vgpr7, $vgpr8 + ; GCN-LABEL: name: buffer_store_dword_32 + ; GCN: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $vgpr0, $vgpr1, $vgpr2, $vgpr3, $vgpr4, $vgpr5, $vgpr6, $vgpr7, $vgpr8 + ; GCN-NEXT: {{ $}} + ; GCN-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr8 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr7 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr6 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:vgpr_32 = COPY $vgpr5 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr4 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY $vgpr3 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY $vgpr2 + ; GCN-NEXT: [[COPY7:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; GCN-NEXT: [[COPY8:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[COPY9:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY10:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY11:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY12:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY12]], %subreg.sub0, [[COPY11]], %subreg.sub1, [[COPY10]], %subreg.sub2, [[COPY9]], %subreg.sub3 + ; GCN-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY8]], %subreg.sub0, [[COPY7]], %subreg.sub1 + ; GCN-NEXT: BUFFER_STORE_DWORDX2_OFFSET_exact killed [[REG_SEQUENCE1]], [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable store (s64), align 1, addrspace 4) + ; GCN-NEXT: [[REG_SEQUENCE2:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY6]], %subreg.sub0, [[COPY5]], %subreg.sub1 + ; GCN-NEXT: [[REG_SEQUENCE3:%[0-9]+]]:vreg_96 = REG_SEQUENCE killed [[REG_SEQUENCE2]], %subreg.sub0_sub1, [[COPY4]], %subreg.sub2 + ; GCN-NEXT: [[REG_SEQUENCE4:%[0-9]+]]:vreg_128 = REG_SEQUENCE killed [[REG_SEQUENCE3]], %subreg.sub0_sub1_sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: BUFFER_STORE_DWORDX4_OFFSET_exact killed [[REG_SEQUENCE4]], [[REG_SEQUENCE]], 0, 16, 0, 0, implicit $exec :: (dereferenceable store (s128), align 1, addrspace 4) + ; GCN-NEXT: [[REG_SEQUENCE5:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[COPY2]], %subreg.sub0, [[COPY1]], %subreg.sub1 + ; GCN-NEXT: [[REG_SEQUENCE6:%[0-9]+]]:vreg_96 = REG_SEQUENCE killed [[REG_SEQUENCE5]], %subreg.sub0_sub1, [[COPY]], %subreg.sub2 + ; GCN-NEXT: BUFFER_STORE_DWORDX3_OFFSET_exact killed [[REG_SEQUENCE6]], [[REG_SEQUENCE]], 0, 36, 0, 0, implicit $exec :: (dereferenceable store (s96), align 1, addrspace 4) + %12:vgpr_32 = COPY $vgpr8 + %11:vgpr_32 = COPY $vgpr7 + %10:vgpr_32 = COPY $vgpr6 + %9:vgpr_32 = COPY $vgpr5 + %8:vgpr_32 = COPY $vgpr4 + %7:vgpr_32 = COPY $vgpr3 + %6:vgpr_32 = COPY $vgpr2 + %5:vgpr_32 = COPY $vgpr1 + %4:vgpr_32 = COPY $vgpr0 + %3:sgpr_32 = COPY $sgpr3 + %2:sgpr_32 = COPY $sgpr2 + %1:sgpr_32 = COPY $sgpr1 + %0:sgpr_32 = COPY $sgpr0 + %13:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + BUFFER_STORE_DWORD_OFFSET_exact %4:vgpr_32, %13:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_OFFSET_exact %5:vgpr_32, %13:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_OFFSET_exact %6:vgpr_32, %13:sgpr_128, 0, 16, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_OFFSET_exact %7:vgpr_32, %13:sgpr_128, 0, 20, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_OFFSET_exact %8:vgpr_32, %13:sgpr_128, 0, 24, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_OFFSET_exact %9:vgpr_32, %13:sgpr_128, 0, 28, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_OFFSET_exact %10:vgpr_32, %13:sgpr_128, 0, 36, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_OFFSET_exact %11:vgpr_32, %13:sgpr_128, 0, 40, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_OFFSET_exact %12:vgpr_32, %13:sgpr_128, 0, 44, 0, 0, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_not_merged_swizzled_0 +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_not_merged_swizzled_0 + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORD_OFFSET:%[0-9]+]]:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET [[REG_SEQUENCE]], 0, 4, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GCN-NEXT: [[BUFFER_LOAD_DWORD_OFFSET1:%[0-9]+]]:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET [[REG_SEQUENCE]], 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 4, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_not_merged_swizzled_1 +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_not_merged_swizzled_1 + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORD_OFFSET:%[0-9]+]]:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GCN-NEXT: [[BUFFER_LOAD_DWORD_OFFSET1:%[0-9]+]]:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET [[REG_SEQUENCE]], 0, 8, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 8, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_merge_across_swizzle +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_merge_across_swizzle + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX2_OFFSET:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_OFFSET [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_OFFSET]].sub0 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_OFFSET]].sub1 + ; GCN-NEXT: [[BUFFER_LOAD_DWORD_OFFSET:%[0-9]+]]:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET [[REG_SEQUENCE]], 0, 12, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %5:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %4:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %6:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %4:sgpr_128, 0, 12, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %7:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %4:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_merge_across_swizzled_store +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_merge_across_swizzled_store + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORD_OFFSET:%[0-9]+]]:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GCN-NEXT: BUFFER_STORE_DWORD_OFFSET_exact [[COPY4]], [[REG_SEQUENCE]], 0, 6, 0, 1, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + ; GCN-NEXT: [[BUFFER_LOAD_DWORD_OFFSET1:%[0-9]+]]:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET [[REG_SEQUENCE]], 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %6:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + BUFFER_STORE_DWORD_OFFSET_exact %4:vgpr_32, %5:sgpr_128, 0, 6, 0, 1, implicit $exec :: (dereferenceable store (s32), align 1, addrspace 4) + %7:vgpr_32 = BUFFER_LOAD_DWORD_OFFSET %5:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dword_idxen +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_dword_idxen + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX2_IDXEN:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_IDXEN [[COPY4]], [[REG_SEQUENCE]], 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_IDXEN]].sub0 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_IDXEN]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_IDXEN %4, %5:sgpr_128, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_IDXEN %4, %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dwordx2_idxen +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_dwordx2_idxen + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX3_IDXEN:%[0-9]+]]:vreg_96 = BUFFER_LOAD_DWORDX3_IDXEN [[COPY4]], [[REG_SEQUENCE]], 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX3_IDXEN]].sub0 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX3_IDXEN]].sub1_sub2 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_IDXEN %4, %5:sgpr_128, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_IDXEN %4, %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dwordx2_idxen +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dwordx2_dwordx2_idxen + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX4_IDXEN:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_IDXEN [[COPY4]], [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY [[BUFFER_LOAD_DWORDX4_IDXEN]].sub0_sub1 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX4_IDXEN]].sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vreg_64 = BUFFER_LOAD_DWORDX2_IDXEN %4, %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_IDXEN %4, %5:sgpr_128, 0, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dwordx3_idxen +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_dwordx3_idxen + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX4_IDXEN:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_IDXEN [[COPY4]], [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX4_IDXEN]].sub0 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vreg_96 = COPY killed [[BUFFER_LOAD_DWORDX4_IDXEN]].sub1_sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_IDXEN %4, %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_96 = BUFFER_LOAD_DWORDX3_IDXEN %4, %5:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dword_bothen +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_dword_bothen + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX2_BOTHEN:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_BOTHEN [[COPY4]], [[REG_SEQUENCE]], 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_BOTHEN]].sub0 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_BOTHEN]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_BOTHEN %4, %5:sgpr_128, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_BOTHEN %4, %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dwordx2_bothen +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_dwordx2_bothen + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX3_BOTHEN:%[0-9]+]]:vreg_96 = BUFFER_LOAD_DWORDX3_BOTHEN [[COPY4]], [[REG_SEQUENCE]], 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX3_BOTHEN]].sub0 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX3_BOTHEN]].sub1_sub2 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_BOTHEN %4, %5:sgpr_128, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_BOTHEN %4, %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dwordx2_bothen +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dwordx2_dwordx2_bothen + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX4_BOTHEN:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_BOTHEN [[COPY4]], [[REG_SEQUENCE]], 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY [[BUFFER_LOAD_DWORDX4_BOTHEN]].sub0_sub1 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX4_BOTHEN]].sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vreg_64 = BUFFER_LOAD_DWORDX2_BOTHEN %4, %5:sgpr_128, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_BOTHEN %4, %5:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dwordx3_bothen +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_dwordx3_bothen + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX4_BOTHEN:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_BOTHEN [[COPY4]], [[REG_SEQUENCE]], 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX4_BOTHEN]].sub0 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vreg_96 = COPY killed [[BUFFER_LOAD_DWORDX4_BOTHEN]].sub1_sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_BOTHEN %4, %5:sgpr_128, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_96 = BUFFER_LOAD_DWORDX3_BOTHEN %4, %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dword_idxen_exact +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_dword_idxen_exact + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX2_IDXEN_exact:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_IDXEN_exact [[COPY4]], [[REG_SEQUENCE]], 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_IDXEN_exact]].sub0 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_IDXEN_exact]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_IDXEN_exact %4, %5:sgpr_128, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_IDXEN_exact %4, %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dwordx2_idxen_exact +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_dwordx2_idxen_exact + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX3_IDXEN_exact:%[0-9]+]]:vreg_96 = BUFFER_LOAD_DWORDX3_IDXEN_exact [[COPY4]], [[REG_SEQUENCE]], 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX3_IDXEN_exact]].sub0 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX3_IDXEN_exact]].sub1_sub2 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_IDXEN_exact %4, %5:sgpr_128, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_IDXEN_exact %4, %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dwordx2_idxen_exact +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dwordx2_dwordx2_idxen_exact + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX4_IDXEN_exact:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_IDXEN_exact [[COPY4]], [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY [[BUFFER_LOAD_DWORDX4_IDXEN_exact]].sub0_sub1 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX4_IDXEN_exact]].sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vreg_64 = BUFFER_LOAD_DWORDX2_IDXEN_exact %4, %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_IDXEN_exact %4, %5:sgpr_128, 0, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dwordx3_idxen_exact +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_dwordx3_idxen_exact + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX4_IDXEN_exact:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_IDXEN_exact [[COPY4]], [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX4_IDXEN_exact]].sub0 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vreg_96 = COPY killed [[BUFFER_LOAD_DWORDX4_IDXEN_exact]].sub1_sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_IDXEN_exact %4, %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_96 = BUFFER_LOAD_DWORDX3_IDXEN_exact %4, %5:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dword_dword_idxen_exact +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_dword_dword_idxen_exact + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX3_IDXEN_exact:%[0-9]+]]:vreg_96 = BUFFER_LOAD_DWORDX3_IDXEN_exact [[COPY4]], [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s96), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY [[BUFFER_LOAD_DWORDX3_IDXEN_exact]].sub0_sub1 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX3_IDXEN_exact]].sub2 + ; GCN-NEXT: [[COPY7:%[0-9]+]]:vgpr_32 = COPY [[COPY5]].sub0 + ; GCN-NEXT: [[COPY8:%[0-9]+]]:vgpr_32 = COPY killed [[COPY5]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_IDXEN_exact %4, %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_IDXEN_exact %4, %5:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %9:vgpr_32 = BUFFER_LOAD_DWORD_IDXEN_exact %4, %5:sgpr_128, 0, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dword_dword_idxen_exact_swizzled_0 +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_dword_dword_idxen_exact_swizzled_0 + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORD_IDXEN_exact:%[0-9]+]]:vgpr_32 = BUFFER_LOAD_DWORD_IDXEN_exact [[COPY4]], [[REG_SEQUENCE]], 0, 4, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX2_IDXEN_exact:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_IDXEN_exact [[COPY4]], [[REG_SEQUENCE]], 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_IDXEN_exact]].sub0 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_IDXEN_exact]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_IDXEN_exact %4, %5:sgpr_128, 0, 4, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_IDXEN_exact %4, %5:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %9:vgpr_32 = BUFFER_LOAD_DWORD_IDXEN_exact %4, %5:sgpr_128, 0, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dword_bothen_exact +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_dword_bothen_exact + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX2_BOTHEN_exact:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_BOTHEN_exact [[COPY4]], [[REG_SEQUENCE]], 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_BOTHEN_exact]].sub0 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_BOTHEN_exact]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_BOTHEN_exact %4, %5:sgpr_128, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_BOTHEN_exact %4, %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dwordx2_bothen_exact +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_dwordx2_bothen_exact + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX3_BOTHEN_exact:%[0-9]+]]:vreg_96 = BUFFER_LOAD_DWORDX3_BOTHEN_exact [[COPY4]], [[REG_SEQUENCE]], 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX3_BOTHEN_exact]].sub0 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX3_BOTHEN_exact]].sub1_sub2 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_BOTHEN_exact %4, %5:sgpr_128, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_BOTHEN_exact %4, %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dwordx2_bothen_exact +body: | + bb.0.entry: + + ; GCN-LABEL: name: buffer_load_dwordx2_dwordx2_bothen_exact + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX4_BOTHEN_exact:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_BOTHEN_exact [[COPY4]], [[REG_SEQUENCE]], 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY [[BUFFER_LOAD_DWORDX4_BOTHEN_exact]].sub0_sub1 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vreg_64 = COPY killed [[BUFFER_LOAD_DWORDX4_BOTHEN_exact]].sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vreg_64 = BUFFER_LOAD_DWORDX2_BOTHEN_exact %4, %5:sgpr_128, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_64 = BUFFER_LOAD_DWORDX2_BOTHEN_exact %4, %5:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dwordx3_bothen_exact +body: | + bb.0.entry: + + ; GCN-LABEL: name: buffer_load_dword_dwordx3_bothen_exact + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX4_BOTHEN_exact:%[0-9]+]]:vreg_128 = BUFFER_LOAD_DWORDX4_BOTHEN_exact [[COPY4]], [[REG_SEQUENCE]], 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX4_BOTHEN_exact]].sub0 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vreg_96 = COPY killed [[BUFFER_LOAD_DWORDX4_BOTHEN_exact]].sub1_sub2_sub3 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_BOTHEN_exact %4, %5:sgpr_128, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vreg_96 = BUFFER_LOAD_DWORDX3_BOTHEN_exact %4, %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dword_dword_bothen_exact +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_dword_dword_bothen_exact + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX3_BOTHEN_exact:%[0-9]+]]:vreg_96 = BUFFER_LOAD_DWORDX3_BOTHEN_exact [[COPY4]], [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s96), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY [[BUFFER_LOAD_DWORDX3_BOTHEN_exact]].sub0_sub1 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX3_BOTHEN_exact]].sub2 + ; GCN-NEXT: [[COPY7:%[0-9]+]]:vgpr_32 = COPY [[COPY5]].sub0 + ; GCN-NEXT: [[COPY8:%[0-9]+]]:vgpr_32 = COPY killed [[COPY5]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_BOTHEN_exact %4, %5:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_BOTHEN_exact %4, %5:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %9:vgpr_32 = BUFFER_LOAD_DWORD_BOTHEN_exact %4, %5:sgpr_128, 0, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dword_dword_dword_bothen_exact_swizzled_0 +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dword_dword_dword_bothen_exact_swizzled_0 + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORD_BOTHEN_exact:%[0-9]+]]:vgpr_32 = BUFFER_LOAD_DWORD_BOTHEN_exact [[COPY4]], [[REG_SEQUENCE]], 0, 4, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX2_BOTHEN_exact:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_BOTHEN_exact [[COPY4]], [[REG_SEQUENCE]], 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s64), align 1, addrspace 4) + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY [[BUFFER_LOAD_DWORDX2_BOTHEN_exact]].sub0 + ; GCN-NEXT: [[COPY6:%[0-9]+]]:vgpr_32 = COPY killed [[BUFFER_LOAD_DWORDX2_BOTHEN_exact]].sub1 + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:vgpr_32 = BUFFER_LOAD_DWORD_BOTHEN_exact %4, %5:sgpr_128, 0, 4, 0, 1, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %8:vgpr_32 = BUFFER_LOAD_DWORD_BOTHEN_exact %4, %5:sgpr_128, 0, 8, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %9:vgpr_32 = BUFFER_LOAD_DWORD_BOTHEN_exact %4, %5:sgpr_128, 0, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dwordx2_bothen_exact_diff_vaddr +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dwordx2_dwordx2_bothen_exact_diff_vaddr + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY $vgpr1 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX2_BOTHEN_exact:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_BOTHEN_exact [[COPY4]], [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX2_BOTHEN_exact1:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_BOTHEN_exact [[COPY5]], [[REG_SEQUENCE]], 0, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vreg_64 = COPY $vgpr0 + %5:vreg_64 = COPY $vgpr1 + %6:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %8:vreg_64 = BUFFER_LOAD_DWORDX2_BOTHEN_exact %4, %6:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %9:vreg_64 = BUFFER_LOAD_DWORDX2_BOTHEN_exact %5, %6:sgpr_128, 0, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dwordx2_bothen_exact_diff_srsrc +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dwordx2_dwordx2_bothen_exact_diff_srsrc + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr4 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vreg_64 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY1]], %subreg.sub0, [[COPY2]], %subreg.sub1, [[COPY3]], %subreg.sub2, [[COPY4]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX2_BOTHEN_exact:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_BOTHEN_exact [[COPY5]], [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX2_BOTHEN_exact1:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_BOTHEN_exact [[COPY5]], [[REG_SEQUENCE1]], 0, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:sgpr_32 = COPY $sgpr4 + %5:vreg_64 = COPY $vgpr0 + %6:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:sgpr_128 = REG_SEQUENCE %1:sgpr_32, %subreg.sub0, %2:sgpr_32, %subreg.sub1, %3:sgpr_32, %subreg.sub2, %4:sgpr_32, %subreg.sub3 + %8:vreg_64 = BUFFER_LOAD_DWORDX2_BOTHEN_exact %5, %6:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %9:vreg_64 = BUFFER_LOAD_DWORDX2_BOTHEN_exact %5, %7:sgpr_128, 0, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dwordx2_idxen_exact_diff_vaddr +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dwordx2_dwordx2_idxen_exact_diff_vaddr + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY $vgpr1 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX2_IDXEN_exact:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_IDXEN_exact [[COPY4]], [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX2_IDXEN_exact1:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_IDXEN_exact [[COPY5]], [[REG_SEQUENCE]], 0, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:vgpr_32 = COPY $vgpr0 + %5:vgpr_32 = COPY $vgpr1 + %6:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %8:vreg_64 = BUFFER_LOAD_DWORDX2_IDXEN_exact %4, %6:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %9:vreg_64 = BUFFER_LOAD_DWORDX2_IDXEN_exact %5, %6:sgpr_128, 0, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... +--- + +name: buffer_load_dwordx2_dwordx2_idxen_exact_diff_srsrc +body: | + bb.0.entry: + ; GCN-LABEL: name: buffer_load_dwordx2_dwordx2_idxen_exact_diff_srsrc + ; GCN: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GCN-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GCN-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GCN-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GCN-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr4 + ; GCN-NEXT: [[COPY5:%[0-9]+]]:vgpr_32 = COPY $vgpr0 + ; GCN-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GCN-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY1]], %subreg.sub0, [[COPY2]], %subreg.sub1, [[COPY3]], %subreg.sub2, [[COPY4]], %subreg.sub3 + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX2_IDXEN_exact:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_IDXEN_exact [[COPY5]], [[REG_SEQUENCE]], 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GCN-NEXT: [[BUFFER_LOAD_DWORDX2_IDXEN_exact1:%[0-9]+]]:vreg_64 = BUFFER_LOAD_DWORDX2_IDXEN_exact [[COPY5]], [[REG_SEQUENCE1]], 0, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %0:sgpr_32 = COPY $sgpr0 + %1:sgpr_32 = COPY $sgpr1 + %2:sgpr_32 = COPY $sgpr2 + %3:sgpr_32 = COPY $sgpr3 + %4:sgpr_32 = COPY $sgpr4 + %5:vgpr_32 = COPY $vgpr0 + %6:sgpr_128 = REG_SEQUENCE %0:sgpr_32, %subreg.sub0, %1:sgpr_32, %subreg.sub1, %2:sgpr_32, %subreg.sub2, %3:sgpr_32, %subreg.sub3 + %7:sgpr_128 = REG_SEQUENCE %1:sgpr_32, %subreg.sub0, %2:sgpr_32, %subreg.sub1, %3:sgpr_32, %subreg.sub2, %4:sgpr_32, %subreg.sub3 + %8:vreg_64 = BUFFER_LOAD_DWORDX2_IDXEN_exact %5, %6:sgpr_128, 0, 4, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + %9:vreg_64 = BUFFER_LOAD_DWORDX2_IDXEN_exact %5, %7:sgpr_128, 0, 12, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) +... diff --git a/llvm/test/CodeGen/AMDGPU/merge-tbuffer.mir b/llvm/test/CodeGen/AMDGPU/merge-tbuffer.mir index c86b5adec372d6c74066ed0641cdd7631654927f..9766b427b43258733684f438135120ccab0a378d 100644 --- a/llvm/test/CodeGen/AMDGPU/merge-tbuffer.mir +++ b/llvm/test/CodeGen/AMDGPU/merge-tbuffer.mir @@ -7,9 +7,37 @@ # GFX9 tests # +--- name: gfx9_tbuffer_load_x_xyz body: | bb.0.entry: + ; GFX9-LABEL: name: gfx9_tbuffer_load_x_xyz + ; GFX9: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX9-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX9-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX9-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX9-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX9-NEXT: [[TBUFFER_LOAD_FORMAT_XYZW_OFFSET:%[0-9]+]]:vreg_128 = TBUFFER_LOAD_FORMAT_XYZW_OFFSET [[REG_SEQUENCE]], 0, 4, 126, 0, 0, implicit $exec :: (dereferenceable load (s128), align 1, addrspace 4) + ; GFX9-NEXT: [[COPY4:%[0-9]+]]:vgpr_32 = COPY [[TBUFFER_LOAD_FORMAT_XYZW_OFFSET]].sub0 + ; GFX9-NEXT: [[COPY5:%[0-9]+]]:vreg_96 = COPY killed [[TBUFFER_LOAD_FORMAT_XYZW_OFFSET]].sub1_sub2_sub3 + ; + ; GFX10-LABEL: name: gfx9_tbuffer_load_x_xyz + ; GFX10: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX10-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX10-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX10-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX10-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX10-NEXT: [[TBUFFER_LOAD_FORMAT_X_OFFSET:%[0-9]+]]:vgpr_32 = TBUFFER_LOAD_FORMAT_X_OFFSET [[REG_SEQUENCE]], 0, 4, 116, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GFX10-NEXT: [[TBUFFER_LOAD_FORMAT_XYZ_OFFSET:%[0-9]+]]:vreg_96 = TBUFFER_LOAD_FORMAT_XYZ_OFFSET [[REG_SEQUENCE]], 0, 8, 125, 0, 0, implicit $exec :: (dereferenceable load (s96), align 1, addrspace 4) + ; + ; GFX11-LABEL: name: gfx9_tbuffer_load_x_xyz + ; GFX11: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr0 + ; GFX11-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1 + ; GFX11-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2 + ; GFX11-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr3 + ; GFX11-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 + ; GFX11-NEXT: [[TBUFFER_LOAD_FORMAT_X_OFFSET:%[0-9]+]]:vgpr_32 = TBUFFER_LOAD_FORMAT_X_OFFSET [[REG_SEQUENCE]], 0, 4, 116, 0, 0, implicit $exec :: (dereferenceable load (s32), align 1, addrspace 4) + ; GFX11-NEXT: [[TBUFFER_LOAD_FORMAT_XYZ_OFFSET:%[0-9]+]]:vreg_96 = TBUFFER_LOAD_FORMAT_XYZ_OFFSET [[REG_SEQUENCE]], 0, 8, 125, 0, 0, implicit $exec :: (dereferenceable load (s96), align 1, addrspace 4) %0:sgpr_32 = COPY $sgpr0 %1:sgpr_32 = COPY $sgpr1 %2:sgpr_32 = COPY $sgpr2 diff --git a/llvm/test/CodeGen/AMDGPU/need-fp-from-vgpr-spills.ll b/llvm/test/CodeGen/AMDGPU/need-fp-from-vgpr-spills.ll index cbdc7bb456346f224857d8f9000dc5e932192b09..69971bca2738ad6856aa3546151b1beed93f572d 100644 --- a/llvm/test/CodeGen/AMDGPU/need-fp-from-vgpr-spills.ll +++ b/llvm/test/CodeGen/AMDGPU/need-fp-from-vgpr-spills.ll @@ -27,7 +27,7 @@ define internal fastcc void @csr_vgpr_spill_fp_callee() #0 { ; CHECK-LABEL: csr_vgpr_spill_fp_callee: ; CHECK: ; %bb.0: ; %bb ; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; CHECK-NEXT: s_mov_b32 s24, s33 +; CHECK-NEXT: s_mov_b32 s18, s33 ; CHECK-NEXT: s_mov_b32 s33, s32 ; CHECK-NEXT: s_xor_saveexec_b64 s[16:17], -1 ; CHECK-NEXT: buffer_store_dword v1, off, s[0:3], s33 offset:4 ; 4-byte Folded Spill @@ -43,7 +43,6 @@ define internal fastcc void @csr_vgpr_spill_fp_callee() #0 { ; CHECK-NEXT: s_mov_b64 s[20:21], s[0:1] ; CHECK-NEXT: s_mov_b64 s[0:1], s[20:21] ; CHECK-NEXT: s_mov_b64 s[2:3], s[22:23] -; CHECK-NEXT: ; implicit-def: $sgpr18_sgpr19 ; CHECK-NEXT: s_swappc_b64 s[30:31], s[16:17] ; CHECK-NEXT: ;;#ASMSTART ; CHECK-NEXT: ; clobber csr v40 @@ -55,7 +54,7 @@ define internal fastcc void @csr_vgpr_spill_fp_callee() #0 { ; CHECK-NEXT: buffer_load_dword v1, off, s[0:3], s33 offset:4 ; 4-byte Folded Reload ; CHECK-NEXT: s_mov_b64 exec, s[4:5] ; CHECK-NEXT: s_add_i32 s32, s32, 0xfffffc00 -; CHECK-NEXT: s_mov_b32 s33, s24 +; CHECK-NEXT: s_mov_b32 s33, s18 ; CHECK-NEXT: s_waitcnt vmcnt(0) ; CHECK-NEXT: s_setpc_b64 s[30:31] bb: @@ -88,7 +87,6 @@ define amdgpu_kernel void @kernel_call() { ; CHECK-NEXT: ; implicit-def: $sgpr15 ; CHECK-NEXT: s_mov_b64 s[0:1], s[20:21] ; CHECK-NEXT: s_mov_b64 s[2:3], s[22:23] -; CHECK-NEXT: ; implicit-def: $sgpr18_sgpr19 ; CHECK-NEXT: s_swappc_b64 s[30:31], s[16:17] ; CHECK-NEXT: s_endpgm bb: @@ -148,7 +146,6 @@ define amdgpu_kernel void @kernel_tailcall() { ; CHECK-NEXT: ; implicit-def: $sgpr15 ; CHECK-NEXT: s_mov_b64 s[0:1], s[20:21] ; CHECK-NEXT: s_mov_b64 s[2:3], s[22:23] -; CHECK-NEXT: ; implicit-def: $sgpr18_sgpr19 ; CHECK-NEXT: s_swappc_b64 s[30:31], s[16:17] ; CHECK-NEXT: s_endpgm bb: @@ -173,7 +170,7 @@ define hidden i32 @caller_save_vgpr_spill_fp_tail_call() #0 { ; CHECK-LABEL: caller_save_vgpr_spill_fp_tail_call: ; CHECK: ; %bb.0: ; %entry ; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; CHECK-NEXT: s_mov_b32 s24, s33 +; CHECK-NEXT: s_mov_b32 s18, s33 ; CHECK-NEXT: s_mov_b32 s33, s32 ; CHECK-NEXT: s_xor_saveexec_b64 s[16:17], -1 ; CHECK-NEXT: buffer_store_dword v1, off, s[0:3], s33 ; 4-byte Folded Spill @@ -188,7 +185,6 @@ define hidden i32 @caller_save_vgpr_spill_fp_tail_call() #0 { ; CHECK-NEXT: s_mov_b64 s[20:21], s[0:1] ; CHECK-NEXT: s_mov_b64 s[0:1], s[20:21] ; CHECK-NEXT: s_mov_b64 s[2:3], s[22:23] -; CHECK-NEXT: ; implicit-def: $sgpr18_sgpr19 ; CHECK-NEXT: s_swappc_b64 s[30:31], s[16:17] ; CHECK-NEXT: v_readlane_b32 s31, v1, 1 ; CHECK-NEXT: v_readlane_b32 s30, v1, 0 @@ -196,7 +192,7 @@ define hidden i32 @caller_save_vgpr_spill_fp_tail_call() #0 { ; CHECK-NEXT: buffer_load_dword v1, off, s[0:3], s33 ; 4-byte Folded Reload ; CHECK-NEXT: s_mov_b64 exec, s[4:5] ; CHECK-NEXT: s_add_i32 s32, s32, 0xfffffc00 -; CHECK-NEXT: s_mov_b32 s33, s24 +; CHECK-NEXT: s_mov_b32 s33, s18 ; CHECK-NEXT: s_waitcnt vmcnt(0) ; CHECK-NEXT: s_setpc_b64 s[30:31] entry: @@ -208,7 +204,7 @@ define hidden i32 @caller_save_vgpr_spill_fp() #0 { ; CHECK-LABEL: caller_save_vgpr_spill_fp: ; CHECK: ; %bb.0: ; %entry ; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; CHECK-NEXT: s_mov_b32 s25, s33 +; CHECK-NEXT: s_mov_b32 s19, s33 ; CHECK-NEXT: s_mov_b32 s33, s32 ; CHECK-NEXT: s_xor_saveexec_b64 s[16:17], -1 ; CHECK-NEXT: buffer_store_dword v2, off, s[0:3], s33 ; 4-byte Folded Spill @@ -223,7 +219,6 @@ define hidden i32 @caller_save_vgpr_spill_fp() #0 { ; CHECK-NEXT: s_mov_b64 s[20:21], s[0:1] ; CHECK-NEXT: s_mov_b64 s[0:1], s[20:21] ; CHECK-NEXT: s_mov_b64 s[2:3], s[22:23] -; CHECK-NEXT: ; implicit-def: $sgpr18_sgpr19 ; CHECK-NEXT: s_swappc_b64 s[30:31], s[16:17] ; CHECK-NEXT: v_readlane_b32 s31, v2, 1 ; CHECK-NEXT: v_readlane_b32 s30, v2, 0 @@ -231,7 +226,7 @@ define hidden i32 @caller_save_vgpr_spill_fp() #0 { ; CHECK-NEXT: buffer_load_dword v2, off, s[0:3], s33 ; 4-byte Folded Reload ; CHECK-NEXT: s_mov_b64 exec, s[4:5] ; CHECK-NEXT: s_add_i32 s32, s32, 0xfffffc00 -; CHECK-NEXT: s_mov_b32 s33, s25 +; CHECK-NEXT: s_mov_b32 s33, s19 ; CHECK-NEXT: s_waitcnt vmcnt(0) ; CHECK-NEXT: s_setpc_b64 s[30:31] entry: @@ -263,7 +258,6 @@ define protected amdgpu_kernel void @kernel() { ; CHECK-NEXT: ; implicit-def: $sgpr15 ; CHECK-NEXT: s_mov_b64 s[0:1], s[20:21] ; CHECK-NEXT: s_mov_b64 s[2:3], s[22:23] -; CHECK-NEXT: ; implicit-def: $sgpr18_sgpr19 ; CHECK-NEXT: s_swappc_b64 s[30:31], s[16:17] ; CHECK-NEXT: s_endpgm entry: diff --git a/llvm/test/CodeGen/AMDGPU/neighboring-mfma-padding.mir b/llvm/test/CodeGen/AMDGPU/neighboring-mfma-padding.mir index 3de258bb52a55609fc98a53324cc49467dbcf8b3..bf2cf6aeb990d7043aeeecd477a0ac197bcb7a8f 100644 --- a/llvm/test/CodeGen/AMDGPU/neighboring-mfma-padding.mir +++ b/llvm/test/CodeGen/AMDGPU/neighboring-mfma-padding.mir @@ -5,6 +5,14 @@ # RUN: llc -mtriple=amdgcn -mcpu=gfx908 -amdgpu-mfma-padding-ratio=75 -verify-machineinstrs -run-pass post-RA-hazard-rec %s -o - | FileCheck -check-prefix=gfx908-PAD75 %s # RUN: llc -mtriple=amdgcn -mcpu=gfx908 -amdgpu-mfma-padding-ratio=100 -verify-machineinstrs -run-pass post-RA-hazard-rec %s -o - | FileCheck -check-prefix=gfx908-PAD100 %s +# RUN: llc -mtriple=amdgcn -mcpu=gfx90a -verify-machineinstrs -run-pass post-RA-hazard-rec %s -o - | FileCheck -check-prefix=gfx90a-DEFAULT %s +# RUN: llc -mtriple=amdgcn -mcpu=gfx90a -amdgpu-mfma-padding-ratio=50 -verify-machineinstrs -run-pass post-RA-hazard-rec %s -o - | FileCheck -check-prefix=gfx90a-PAD50 %s +# RUN: llc -mtriple=amdgcn -mcpu=gfx90a -amdgpu-mfma-padding-ratio=100 -verify-machineinstrs -run-pass post-RA-hazard-rec %s -o - | FileCheck -check-prefix=gfx90a-PAD100 %s + +# RUN: llc -mtriple=amdgcn -mcpu=gfx940 -verify-machineinstrs -run-pass post-RA-hazard-rec %s -o - | FileCheck -check-prefix=gfx940-DEFAULT %s +# RUN: llc -mtriple=amdgcn -mcpu=gfx940 -amdgpu-mfma-padding-ratio=50 -verify-machineinstrs -run-pass post-RA-hazard-rec %s -o - | FileCheck -check-prefix=gfx940-PAD50 %s +# RUN: llc -mtriple=amdgcn -mcpu=gfx940 -amdgpu-mfma-padding-ratio=100 -verify-machineinstrs -run-pass post-RA-hazard-rec %s -o - | FileCheck -check-prefix=gfx940-PAD100 %s + --- name: mfma_padding_2_pass body: | @@ -31,6 +39,35 @@ body: | ; gfx908-PAD100: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec ; gfx908-PAD100-NEXT: S_NOP 1 ; gfx908-PAD100-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-DEFAULT-LABEL: name: mfma_padding_2_pass + ; gfx90a-DEFAULT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-DEFAULT-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD50-LABEL: name: mfma_padding_2_pass + ; gfx90a-PAD50: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD50-NEXT: S_NOP 0 + ; gfx90a-PAD50-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD100-LABEL: name: mfma_padding_2_pass + ; gfx90a-PAD100: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD100-NEXT: S_NOP 1 + ; gfx90a-PAD100-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-DEFAULT-LABEL: name: mfma_padding_2_pass + ; gfx940-DEFAULT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-DEFAULT-NEXT: S_NOP 1 + ; gfx940-DEFAULT-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD50-LABEL: name: mfma_padding_2_pass + ; gfx940-PAD50: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD50-NEXT: S_NOP 1 + ; gfx940-PAD50-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD100-LABEL: name: mfma_padding_2_pass + ; gfx940-PAD100: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD100-NEXT: S_NOP 1 + ; gfx940-PAD100-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec ... @@ -64,6 +101,40 @@ body: | ; gfx908-PAD100-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec ; gfx908-PAD100-NEXT: S_NOP 0 ; gfx908-PAD100-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-DEFAULT-LABEL: name: mfma_padding_2_pass_1_intervening_valu + ; gfx90a-DEFAULT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD50-LABEL: name: mfma_padding_2_pass_1_intervening_valu + ; gfx90a-PAD50: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD100-LABEL: name: mfma_padding_2_pass_1_intervening_valu + ; gfx90a-PAD100: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: S_NOP 0 + ; gfx90a-PAD100-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-DEFAULT-LABEL: name: mfma_padding_2_pass_1_intervening_valu + ; gfx940-DEFAULT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: S_NOP 0 + ; gfx940-DEFAULT-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD50-LABEL: name: mfma_padding_2_pass_1_intervening_valu + ; gfx940-PAD50: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: S_NOP 0 + ; gfx940-PAD50-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD100-LABEL: name: mfma_padding_2_pass_1_intervening_valu + ; gfx940-PAD100: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: S_NOP 0 + ; gfx940-PAD100-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec $vgpr2 = V_MOV_B32_e32 1, implicit $exec $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec @@ -100,6 +171,41 @@ body: | ; gfx908-PAD100-NEXT: DBG_VALUE ; gfx908-PAD100-NEXT: S_NOP 1 ; gfx908-PAD100-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-DEFAULT-LABEL: name: mfma_padding_2_pass_dbg + ; gfx90a-DEFAULT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-DEFAULT-NEXT: DBG_VALUE + ; gfx90a-DEFAULT-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD50-LABEL: name: mfma_padding_2_pass_dbg + ; gfx90a-PAD50: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD50-NEXT: DBG_VALUE + ; gfx90a-PAD50-NEXT: S_NOP 0 + ; gfx90a-PAD50-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD100-LABEL: name: mfma_padding_2_pass_dbg + ; gfx90a-PAD100: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD100-NEXT: DBG_VALUE + ; gfx90a-PAD100-NEXT: S_NOP 1 + ; gfx90a-PAD100-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-DEFAULT-LABEL: name: mfma_padding_2_pass_dbg + ; gfx940-DEFAULT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-DEFAULT-NEXT: DBG_VALUE + ; gfx940-DEFAULT-NEXT: S_NOP 1 + ; gfx940-DEFAULT-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD50-LABEL: name: mfma_padding_2_pass_dbg + ; gfx940-PAD50: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD50-NEXT: DBG_VALUE + ; gfx940-PAD50-NEXT: S_NOP 1 + ; gfx940-PAD50-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD100-LABEL: name: mfma_padding_2_pass_dbg + ; gfx940-PAD100: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD100-NEXT: DBG_VALUE + ; gfx940-PAD100-NEXT: S_NOP 1 + ; gfx940-PAD100-NEXT: $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec DBG_VALUE $agpr0_agpr1_agpr2_agpr3 = V_MFMA_F32_4X4X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3, 0, 0, 0, implicit $mode, implicit $exec @@ -132,6 +238,34 @@ body: | ; gfx908-PAD100: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec ; gfx908-PAD100-NEXT: S_NOP 7 ; gfx908-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-DEFAULT-LABEL: name: mfma_padding_8_pass + ; gfx90a-DEFAULT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-DEFAULT-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD50-LABEL: name: mfma_padding_8_pass + ; gfx90a-PAD50: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD50-NEXT: S_NOP 3 + ; gfx90a-PAD50-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD100-LABEL: name: mfma_padding_8_pass + ; gfx90a-PAD100: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD100-NEXT: S_NOP 7 + ; gfx90a-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-DEFAULT-LABEL: name: mfma_padding_8_pass + ; gfx940-DEFAULT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-DEFAULT-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD50-LABEL: name: mfma_padding_8_pass + ; gfx940-PAD50: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD50-NEXT: S_NOP 3 + ; gfx940-PAD50-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD100-LABEL: name: mfma_padding_8_pass + ; gfx940-PAD100: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD100-NEXT: S_NOP 7 + ; gfx940-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec ... @@ -172,6 +306,46 @@ body: | ; gfx908-PAD100-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec ; gfx908-PAD100-NEXT: S_NOP 5 ; gfx908-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-DEFAULT-LABEL: name: mfma_padding_8_pass_2_intervening_valu + ; gfx90a-DEFAULT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD50-LABEL: name: mfma_padding_8_pass_2_intervening_valu + ; gfx90a-PAD50: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: S_NOP 1 + ; gfx90a-PAD50-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD100-LABEL: name: mfma_padding_8_pass_2_intervening_valu + ; gfx90a-PAD100: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: S_NOP 5 + ; gfx90a-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-DEFAULT-LABEL: name: mfma_padding_8_pass_2_intervening_valu + ; gfx940-DEFAULT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD50-LABEL: name: mfma_padding_8_pass_2_intervening_valu + ; gfx940-PAD50: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: S_NOP 1 + ; gfx940-PAD50-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD100-LABEL: name: mfma_padding_8_pass_2_intervening_valu + ; gfx940-PAD100: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: S_NOP 5 + ; gfx940-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_16X16X1F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec $vgpr2 = V_MOV_B32_e32 1, implicit $exec $vgpr3 = V_MOV_B32_e32 1, implicit $exec @@ -207,6 +381,36 @@ body: | ; gfx908-PAD100-NEXT: S_NOP 7 ; gfx908-PAD100-NEXT: S_NOP 7 ; gfx908-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-DEFAULT-LABEL: name: mfma_padding_16_pass + ; gfx90a-DEFAULT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-DEFAULT-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD50-LABEL: name: mfma_padding_16_pass + ; gfx90a-PAD50: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD50-NEXT: S_NOP 7 + ; gfx90a-PAD50-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD100-LABEL: name: mfma_padding_16_pass + ; gfx90a-PAD100: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD100-NEXT: S_NOP 7 + ; gfx90a-PAD100-NEXT: S_NOP 7 + ; gfx90a-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-DEFAULT-LABEL: name: mfma_padding_16_pass + ; gfx940-DEFAULT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-DEFAULT-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD50-LABEL: name: mfma_padding_16_pass + ; gfx940-PAD50: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD50-NEXT: S_NOP 7 + ; gfx940-PAD50-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD100-LABEL: name: mfma_padding_16_pass + ; gfx940-PAD100: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD100-NEXT: S_NOP 7 + ; gfx940-PAD100-NEXT: S_NOP 7 + ; gfx940-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec ... @@ -258,6 +462,60 @@ body: | ; gfx908-PAD100-NEXT: S_NOP 7 ; gfx908-PAD100-NEXT: S_NOP 3 ; gfx908-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-DEFAULT-LABEL: name: mfma_padding_16_pass_4_intervening_valu + ; gfx90a-DEFAULT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr4 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr5 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD50-LABEL: name: mfma_padding_16_pass_4_intervening_valu + ; gfx90a-PAD50: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr4 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr5 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: S_NOP 3 + ; gfx90a-PAD50-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD100-LABEL: name: mfma_padding_16_pass_4_intervening_valu + ; gfx90a-PAD100: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr4 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr5 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: S_NOP 7 + ; gfx90a-PAD100-NEXT: S_NOP 3 + ; gfx90a-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-DEFAULT-LABEL: name: mfma_padding_16_pass_4_intervening_valu + ; gfx940-DEFAULT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr4 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr5 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD50-LABEL: name: mfma_padding_16_pass_4_intervening_valu + ; gfx940-PAD50: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr4 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr5 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: S_NOP 3 + ; gfx940-PAD50-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD100-LABEL: name: mfma_padding_16_pass_4_intervening_valu + ; gfx940-PAD100: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr4 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr5 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: S_NOP 7 + ; gfx940-PAD100-NEXT: S_NOP 3 + ; gfx940-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec $vgpr2 = V_MOV_B32_e32 1, implicit $exec $vgpr3 = V_MOV_B32_e32 1, implicit $exec @@ -369,6 +627,126 @@ body: | ; gfx908-PAD100-NEXT: $vgpr16 = V_MOV_B32_e32 1, implicit $exec ; gfx908-PAD100-NEXT: $vgpr17 = V_MOV_B32_e32 1, implicit $exec ; gfx908-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-DEFAULT-LABEL: name: mfma_padding_16_pass_16_intervening_valu + ; gfx90a-DEFAULT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr4 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr5 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr6 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr7 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr8 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr9 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr10 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr11 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr12 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr13 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr14 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr15 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr16 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: $vgpr17 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD50-LABEL: name: mfma_padding_16_pass_16_intervening_valu + ; gfx90a-PAD50: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr4 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr5 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr6 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr7 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr8 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr9 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr10 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr11 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr12 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr13 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr14 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr15 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr16 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: $vgpr17 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD100-LABEL: name: mfma_padding_16_pass_16_intervening_valu + ; gfx90a-PAD100: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr4 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr5 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr6 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr7 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr8 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr9 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr10 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr11 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr12 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr13 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr14 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr15 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr16 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: $vgpr17 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-DEFAULT-LABEL: name: mfma_padding_16_pass_16_intervening_valu + ; gfx940-DEFAULT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr4 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr5 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr6 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr7 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr8 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr9 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr10 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr11 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr12 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr13 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr14 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr15 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr16 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: $vgpr17 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD50-LABEL: name: mfma_padding_16_pass_16_intervening_valu + ; gfx940-PAD50: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr4 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr5 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr6 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr7 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr8 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr9 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr10 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr11 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr12 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr13 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr14 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr15 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr16 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: $vgpr17 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD100-LABEL: name: mfma_padding_16_pass_16_intervening_valu + ; gfx940-PAD100: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr4 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr5 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr6 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr7 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr8 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr9 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr10 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr11 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr12 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr13 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr14 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr15 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr16 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: $vgpr17 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec $vgpr2 = V_MOV_B32_e32 1, implicit $exec $vgpr3 = V_MOV_B32_e32 1, implicit $exec @@ -414,6 +792,30 @@ body: | ; gfx908-PAD100-LABEL: name: mfma_padding_16_pass_occ_1 ; gfx908-PAD100: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec ; gfx908-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-DEFAULT-LABEL: name: mfma_padding_16_pass_occ_1 + ; gfx90a-DEFAULT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-DEFAULT-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD50-LABEL: name: mfma_padding_16_pass_occ_1 + ; gfx90a-PAD50: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD50-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD100-LABEL: name: mfma_padding_16_pass_occ_1 + ; gfx90a-PAD100: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-DEFAULT-LABEL: name: mfma_padding_16_pass_occ_1 + ; gfx940-DEFAULT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-DEFAULT-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD50-LABEL: name: mfma_padding_16_pass_occ_1 + ; gfx940-PAD50: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD50-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD100-LABEL: name: mfma_padding_16_pass_occ_1 + ; gfx940-PAD100: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec ... @@ -506,6 +908,108 @@ body: | ; gfx908-PAD100-NEXT: S_NOP 7 ; gfx908-PAD100-NEXT: S_NOP 5 ; gfx908-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-DEFAULT-LABEL: name: mfma_padding_16_pass_2_preds + ; gfx90a-DEFAULT: bb.0: + ; gfx90a-DEFAULT-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000) + ; gfx90a-DEFAULT-NEXT: {{ $}} + ; gfx90a-DEFAULT-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-DEFAULT-NEXT: S_CBRANCH_VCCZ %bb.2, implicit undef $vcc + ; gfx90a-DEFAULT-NEXT: {{ $}} + ; gfx90a-DEFAULT-NEXT: bb.1: + ; gfx90a-DEFAULT-NEXT: successors: %bb.2(0x80000000) + ; gfx90a-DEFAULT-NEXT: {{ $}} + ; gfx90a-DEFAULT-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: {{ $}} + ; gfx90a-DEFAULT-NEXT: bb.2: + ; gfx90a-DEFAULT-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-DEFAULT-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD50-LABEL: name: mfma_padding_16_pass_2_preds + ; gfx90a-PAD50: bb.0: + ; gfx90a-PAD50-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000) + ; gfx90a-PAD50-NEXT: {{ $}} + ; gfx90a-PAD50-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD50-NEXT: S_CBRANCH_VCCZ %bb.2, implicit undef $vcc + ; gfx90a-PAD50-NEXT: {{ $}} + ; gfx90a-PAD50-NEXT: bb.1: + ; gfx90a-PAD50-NEXT: successors: %bb.2(0x80000000) + ; gfx90a-PAD50-NEXT: {{ $}} + ; gfx90a-PAD50-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: {{ $}} + ; gfx90a-PAD50-NEXT: bb.2: + ; gfx90a-PAD50-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD50-NEXT: S_NOP 5 + ; gfx90a-PAD50-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx90a-PAD100-LABEL: name: mfma_padding_16_pass_2_preds + ; gfx90a-PAD100: bb.0: + ; gfx90a-PAD100-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000) + ; gfx90a-PAD100-NEXT: {{ $}} + ; gfx90a-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx90a-PAD100-NEXT: S_CBRANCH_VCCZ %bb.2, implicit undef $vcc + ; gfx90a-PAD100-NEXT: {{ $}} + ; gfx90a-PAD100-NEXT: bb.1: + ; gfx90a-PAD100-NEXT: successors: %bb.2(0x80000000) + ; gfx90a-PAD100-NEXT: {{ $}} + ; gfx90a-PAD100-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: {{ $}} + ; gfx90a-PAD100-NEXT: bb.2: + ; gfx90a-PAD100-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx90a-PAD100-NEXT: S_NOP 7 + ; gfx90a-PAD100-NEXT: S_NOP 5 + ; gfx90a-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-DEFAULT-LABEL: name: mfma_padding_16_pass_2_preds + ; gfx940-DEFAULT: bb.0: + ; gfx940-DEFAULT-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000) + ; gfx940-DEFAULT-NEXT: {{ $}} + ; gfx940-DEFAULT-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-DEFAULT-NEXT: S_CBRANCH_VCCZ %bb.2, implicit undef $vcc + ; gfx940-DEFAULT-NEXT: {{ $}} + ; gfx940-DEFAULT-NEXT: bb.1: + ; gfx940-DEFAULT-NEXT: successors: %bb.2(0x80000000) + ; gfx940-DEFAULT-NEXT: {{ $}} + ; gfx940-DEFAULT-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: {{ $}} + ; gfx940-DEFAULT-NEXT: bb.2: + ; gfx940-DEFAULT-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-DEFAULT-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD50-LABEL: name: mfma_padding_16_pass_2_preds + ; gfx940-PAD50: bb.0: + ; gfx940-PAD50-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000) + ; gfx940-PAD50-NEXT: {{ $}} + ; gfx940-PAD50-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD50-NEXT: S_CBRANCH_VCCZ %bb.2, implicit undef $vcc + ; gfx940-PAD50-NEXT: {{ $}} + ; gfx940-PAD50-NEXT: bb.1: + ; gfx940-PAD50-NEXT: successors: %bb.2(0x80000000) + ; gfx940-PAD50-NEXT: {{ $}} + ; gfx940-PAD50-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: {{ $}} + ; gfx940-PAD50-NEXT: bb.2: + ; gfx940-PAD50-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD50-NEXT: S_NOP 5 + ; gfx940-PAD50-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; + ; gfx940-PAD100-LABEL: name: mfma_padding_16_pass_2_preds + ; gfx940-PAD100: bb.0: + ; gfx940-PAD100-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000) + ; gfx940-PAD100-NEXT: {{ $}} + ; gfx940-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec + ; gfx940-PAD100-NEXT: S_CBRANCH_VCCZ %bb.2, implicit undef $vcc + ; gfx940-PAD100-NEXT: {{ $}} + ; gfx940-PAD100-NEXT: bb.1: + ; gfx940-PAD100-NEXT: successors: %bb.2(0x80000000) + ; gfx940-PAD100-NEXT: {{ $}} + ; gfx940-PAD100-NEXT: $vgpr2 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: {{ $}} + ; gfx940-PAD100-NEXT: bb.2: + ; gfx940-PAD100-NEXT: $vgpr3 = V_MOV_B32_e32 1, implicit $exec + ; gfx940-PAD100-NEXT: S_NOP 7 + ; gfx940-PAD100-NEXT: S_NOP 5 + ; gfx940-PAD100-NEXT: early-clobber $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec bb.0: $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15 = V_MFMA_F32_32X32X2F32_e64 $vgpr1, $vgpr0, $agpr0_agpr1_agpr2_agpr3_agpr4_agpr5_agpr6_agpr7_agpr8_agpr9_agpr10_agpr11_agpr12_agpr13_agpr14_agpr15, 0, 0, 0, implicit $mode, implicit $exec S_CBRANCH_VCCZ %bb.2, implicit undef $vcc diff --git a/llvm/test/CodeGen/AMDGPU/no-source-locations-in-prologue.ll b/llvm/test/CodeGen/AMDGPU/no-source-locations-in-prologue.ll index 34e67d0993fb7a0dd17ae3b070d29992711551b2..9999cb9173b5db0d200c1687a799885e046414f5 100644 --- a/llvm/test/CodeGen/AMDGPU/no-source-locations-in-prologue.ll +++ b/llvm/test/CodeGen/AMDGPU/no-source-locations-in-prologue.ll @@ -32,7 +32,6 @@ define hidden void @_ZL3barv() #0 !dbg !1644 { ; CHECK-NEXT: s_mov_b64 s[20:21], s[0:1] ; CHECK-NEXT: s_mov_b64 s[0:1], s[20:21] ; CHECK-NEXT: s_mov_b64 s[2:3], s[22:23] -; CHECK-NEXT: ; implicit-def: $sgpr18_sgpr19 ; CHECK-NEXT: s_waitcnt lgkmcnt(0) ; CHECK-NEXT: s_swappc_b64 s[30:31], s[16:17] ; CHECK-NEXT: .Ltmp1: diff --git a/llvm/test/CodeGen/AMDGPU/pal-metadata-3.0-callable.ll b/llvm/test/CodeGen/AMDGPU/pal-metadata-3.0-callable.ll new file mode 100644 index 0000000000000000000000000000000000000000..538ce15979de88b1c035022f0ae369a53fb6acbc --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/pal-metadata-3.0-callable.ll @@ -0,0 +1,305 @@ +; RUN: llc -mtriple=amdgcn--amdpal -mcpu=gfx1100 -verify-machineinstrs < %s | FileCheck %s + +; CHECK: .amdgpu_pal_metadata +; CHECK-NEXT: --- +; CHECK-NEXT: amdpal.pipelines: +; CHECK-NEXT: - .api: Vulkan +; CHECK-NEXT: .compute_registers: +; CHECK-NEXT: .tg_size_en: true +; CHECK-NEXT: .tgid_x_en: false +; CHECK-NEXT: .tgid_y_en: false +; CHECK-NEXT: .tgid_z_en: false +; CHECK-NEXT: .tidig_comp_cnt: 0x1 +; CHECK-NEXT: .hardware_stages: +; CHECK-NEXT: .cs: +; CHECK-NEXT: .checksum_value: 0x9444d7d0 +; CHECK-NEXT: .debug_mode: 0 +; CHECK-NEXT: .excp_en: 0 +; CHECK-NEXT: .float_mode: 0xc0 +; CHECK-NEXT: .ieee_mode: true +; CHECK-NEXT: .image_op: false +; CHECK-NEXT: .lds_size: 0x200 +; CHECK-NEXT: .mem_ordered: true +; CHECK-NEXT: .sgpr_limit: 0x6a +; CHECK-NEXT: .threadgroup_dimensions: +; CHECK-NEXT: - 0x1 +; CHECK-NEXT: - 0x400 +; CHECK-NEXT: - 0x1 +; CHECK-NEXT: .trap_present: false +; CHECK-NEXT: .user_data_reg_map: +; CHECK-NEXT: - 0x10000000 +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0 +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: - 0xffffffff +; CHECK-NEXT: .user_sgprs: 0x3 +; CHECK-NEXT: .vgpr_limit: 0x100 +; CHECK-NEXT: .wavefront_size: 0x40 +; CHECK-NEXT: .wgp_mode: true +; CHECK: .registers: {} +; CHECK-NEXT: .shader_functions: +; CHECK-NEXT: dynamic_stack: +; CHECK-NEXT: .backend_stack_size: 0x10 +; CHECK-NEXT: .lds_size: 0 +; CHECK-NEXT: .sgpr_count: 0x22 +; CHECK-NEXT: .stack_frame_size_in_bytes: 0x10 +; CHECK-NEXT: .vgpr_count: 0x2 +; CHECK-NEXT: dynamic_stack_loop: +; CHECK-NEXT: .backend_stack_size: 0x10 +; CHECK-NEXT: .lds_size: 0 +; CHECK-NEXT: .sgpr_count: 0x22 +; CHECK-NEXT: .stack_frame_size_in_bytes: 0x10 +; CHECK-NEXT: .vgpr_count: 0x3 +; CHECK-NEXT: multiple_stack: +; CHECK-NEXT: .backend_stack_size: 0x24 +; CHECK-NEXT: .lds_size: 0 +; CHECK-NEXT: .sgpr_count: 0x21 +; CHECK-NEXT: .stack_frame_size_in_bytes: 0x24 +; CHECK-NEXT: .vgpr_count: 0x3 +; CHECK-NEXT: no_stack: +; CHECK-NEXT: .backend_stack_size: 0 +; CHECK-NEXT: .lds_size: 0 +; CHECK-NEXT: .sgpr_count: 0x20 +; CHECK-NEXT: .stack_frame_size_in_bytes: 0 +; CHECK-NEXT: .vgpr_count: 0x1 +; CHECK-NEXT: no_stack_call: +; CHECK-NEXT: .backend_stack_size: 0x10 +; CHECK-NEXT: .lds_size: 0 +; CHECK-NEXT: .sgpr_count: 0x22 +; CHECK-NEXT: .stack_frame_size_in_bytes: 0x10 +; CHECK-NEXT: .vgpr_count: 0x3 +; CHECK-NEXT: no_stack_extern_call: +; CHECK-NEXT: .backend_stack_size: 0x10 +; CHECK-NEXT: .lds_size: 0 +; CHECK-NEXT: .sgpr_count: 0x29 +; CHECK-NEXT: .stack_frame_size_in_bytes: 0x10 +; CHECK-NEXT: .vgpr_count: 0x58 +; CHECK-NEXT: no_stack_extern_call_many_args: +; CHECK-NEXT: .backend_stack_size: 0x90 +; CHECK-NEXT: .lds_size: 0 +; CHECK-NEXT: .sgpr_count: 0x29 +; CHECK-NEXT: .stack_frame_size_in_bytes: 0x90 +; CHECK-NEXT: .vgpr_count: 0x58 +; CHECK-NEXT: no_stack_indirect_call: +; CHECK-NEXT: .backend_stack_size: 0x10 +; CHECK-NEXT: .lds_size: 0 +; CHECK-NEXT: .sgpr_count: 0x29 +; CHECK-NEXT: .stack_frame_size_in_bytes: 0x10 +; CHECK-NEXT: .vgpr_count: 0x58 +; CHECK-NEXT: simple_lds: +; CHECK-NEXT: .backend_stack_size: 0 +; CHECK-NEXT: .lds_size: 0x100 +; CHECK-NEXT: .sgpr_count: 0x20 +; CHECK-NEXT: .stack_frame_size_in_bytes: 0 +; CHECK-NEXT: .vgpr_count: 0x1 +; CHECK-NEXT: simple_lds_recurse: +; CHECK-NEXT: .backend_stack_size: 0x10 +; CHECK-NEXT: .lds_size: 0x100 +; CHECK-NEXT: .sgpr_count: 0x24 +; CHECK-NEXT: .stack_frame_size_in_bytes: 0x10 +; CHECK-NEXT: .vgpr_count: 0x29 +; CHECK-NEXT: simple_stack: +; CHECK-NEXT: .backend_stack_size: 0x14 +; CHECK-NEXT: .lds_size: 0 +; CHECK-NEXT: .sgpr_count: 0x21 +; CHECK-NEXT: .stack_frame_size_in_bytes: 0x14 +; CHECK-NEXT: .vgpr_count: 0x2 +; CHECK-NEXT: simple_stack_call: +; CHECK-NEXT: .backend_stack_size: 0x20 +; CHECK-NEXT: .lds_size: 0 +; CHECK-NEXT: .sgpr_count: 0x22 +; CHECK-NEXT: .stack_frame_size_in_bytes: 0x20 +; CHECK-NEXT: .vgpr_count: 0x4 +; CHECK-NEXT: simple_stack_extern_call: +; CHECK-NEXT: .backend_stack_size: 0x20 +; CHECK-NEXT: .lds_size: 0 +; CHECK-NEXT: .sgpr_count: 0x29 +; CHECK-NEXT: .stack_frame_size_in_bytes: 0x20 +; CHECK-NEXT: .vgpr_count: 0x58 +; CHECK-NEXT: simple_stack_indirect_call: +; CHECK-NEXT: .backend_stack_size: 0x20 +; CHECK-NEXT: .lds_size: 0 +; CHECK-NEXT: .sgpr_count: 0x29 +; CHECK-NEXT: .stack_frame_size_in_bytes: 0x20 +; CHECK-NEXT: .vgpr_count: 0x58 +; CHECK-NEXT: simple_stack_recurse: +; CHECK-NEXT: .backend_stack_size: 0x20 +; CHECK-NEXT: .lds_size: 0 +; CHECK-NEXT: .sgpr_count: 0x24 +; CHECK-NEXT: .stack_frame_size_in_bytes: 0x20 +; CHECK-NEXT: .vgpr_count: 0x2a +; CHECK:amdpal.version: +; CHECK-NEXT: - 0x3 +; CHECK-NEXT: - 0 +; CHECK-NEXT:... +; CHECK-NEXT: .end_amdgpu_pal_metadata + +declare amdgpu_gfx float @extern_func(float) #0 +declare amdgpu_gfx float @extern_func_many_args(<64 x float>) #0 + +@funcptr = external hidden unnamed_addr addrspace(4) constant ptr, align 4 + +define amdgpu_gfx float @no_stack(float %arg0) #0 { + %add = fadd float %arg0, 1.0 + ret float %add +} + +define amdgpu_gfx float @simple_stack(float %arg0) #0 { + %stack = alloca float, i32 4, align 4, addrspace(5) + store volatile float 2.0, ptr addrspace(5) %stack + %val = load volatile float, ptr addrspace(5) %stack + %add = fadd float %arg0, %val + ret float %add +} + +define amdgpu_gfx float @multiple_stack(float %arg0) #0 { + %stack = alloca float, i32 4, align 4, addrspace(5) + store volatile float 2.0, ptr addrspace(5) %stack + %val = load volatile float, ptr addrspace(5) %stack + %add = fadd float %arg0, %val + %stack2 = alloca float, i32 4, align 4, addrspace(5) + store volatile float 2.0, ptr addrspace(5) %stack2 + %val2 = load volatile float, ptr addrspace(5) %stack2 + %add2 = fadd float %add, %val2 + ret float %add2 +} + +define amdgpu_gfx float @dynamic_stack(float %arg0) #0 { +bb0: + %cmp = fcmp ogt float %arg0, 0.0 + br i1 %cmp, label %bb1, label %bb2 + +bb1: + %stack = alloca float, i32 4, align 4, addrspace(5) + store volatile float 2.0, ptr addrspace(5) %stack + %val = load volatile float, ptr addrspace(5) %stack + %add = fadd float %arg0, %val + br label %bb2 + +bb2: + %res = phi float [ 0.0, %bb0 ], [ %add, %bb1 ] + ret float %res +} + +define amdgpu_gfx float @dynamic_stack_loop(float %arg0) #0 { +bb0: + br label %bb1 + +bb1: + %ctr = phi i32 [ 0, %bb0 ], [ %newctr, %bb1 ] + %stack = alloca float, i32 4, align 4, addrspace(5) + store volatile float 2.0, ptr addrspace(5) %stack + %val = load volatile float, ptr addrspace(5) %stack + %add = fadd float %arg0, %val + %cmp = icmp sgt i32 %ctr, 0 + %newctr = sub i32 %ctr, 1 + br i1 %cmp, label %bb1, label %bb2 + +bb2: + ret float %add +} + +define amdgpu_gfx float @no_stack_call(float %arg0) #0 { + %res = call amdgpu_gfx float @simple_stack(float %arg0) + ret float %res +} + +define amdgpu_gfx float @simple_stack_call(float %arg0) #0 { + %stack = alloca float, i32 4, align 4, addrspace(5) + store volatile float 2.0, ptr addrspace(5) %stack + %val = load volatile float, ptr addrspace(5) %stack + %res = call amdgpu_gfx float @simple_stack(float %arg0) + %add = fadd float %res, %val + ret float %add +} + +define amdgpu_gfx float @no_stack_extern_call(float %arg0) #0 { + %res = call amdgpu_gfx float @extern_func(float %arg0) + ret float %res +} + +define amdgpu_gfx float @simple_stack_extern_call(float %arg0) #0 { + %stack = alloca float, i32 4, align 4, addrspace(5) + store volatile float 2.0, ptr addrspace(5) %stack + %val = load volatile float, ptr addrspace(5) %stack + %res = call amdgpu_gfx float @extern_func(float %arg0) + %add = fadd float %res, %val + ret float %add +} + +define amdgpu_gfx float @no_stack_extern_call_many_args(<64 x float> %arg0) #0 { + %res = call amdgpu_gfx float @extern_func_many_args(<64 x float> %arg0) + ret float %res +} + +define amdgpu_gfx float @no_stack_indirect_call(float %arg0) #0 { + %fptr = load ptr, ptr addrspace(4) @funcptr + call amdgpu_gfx void %fptr() + ret float %arg0 +} + +define amdgpu_gfx float @simple_stack_indirect_call(float %arg0) #0 { + %stack = alloca float, i32 4, align 4, addrspace(5) + store volatile float 2.0, ptr addrspace(5) %stack + %val = load volatile float, ptr addrspace(5) %stack + %fptr = load ptr, ptr addrspace(4) @funcptr + call amdgpu_gfx void %fptr() + %add = fadd float %arg0, %val + ret float %add +} + +define amdgpu_gfx float @simple_stack_recurse(float %arg0) #0 { + %stack = alloca float, i32 4, align 4, addrspace(5) + store volatile float 2.0, ptr addrspace(5) %stack + %val = load volatile float, ptr addrspace(5) %stack + %res = call amdgpu_gfx float @simple_stack_recurse(float %arg0) + %add = fadd float %res, %val + ret float %add +} + +@lds = internal addrspace(3) global [64 x float] undef + +define amdgpu_gfx float @simple_lds(float %arg0) #0 { + %val = load float, ptr addrspace(3) @lds + ret float %val +} + +define amdgpu_gfx float @simple_lds_recurse(float %arg0) #0 { + %val = load float, ptr addrspace(3) @lds + %res = call amdgpu_gfx float @simple_lds_recurse(float %val) + ret float %res +} + +attributes #0 = { nounwind } + +!amdgpu.pal.metadata.msgpack = !{!0} + +!0 = !{!"\82\B0amdpal.pipelines\91\8A\A4.api\A6Vulkan\B2.compute_registers\85\AB.tg_size_en\C3\AA.tgid_x_en\C2\AA.tgid_y_en\C2\AA.tgid_z_en\C2\AF.tidig_comp_cnt\01\B0.hardware_stages\81\A3.cs\8C\AF.checksum_value\CE\94D\D7\D0\AB.debug_mode\00\AB.float_mode\CC\C0\A9.image_op\C2\AC.mem_ordered\C3\AB.sgpr_limitj\B7.threadgroup_dimensions\93\01\CD\04\00\01\AD.trap_present\00\B2.user_data_reg_map\DC\00 \CE\10\00\00\00\CE\FF\FF\FF\FF\00\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\CE\FF\FF\FF\FF\AB.user_sgprs\03\AB.vgpr_limit\CD\01\00\AF.wavefront_size@\B7.internal_pipeline_hash\92\CF\E7\10k\A6:\A6%\F7\CF\B2\1F\1A\D4{\DA\E1T\AA.registers\80\A8.shaders\81\A8.compute\82\B0.api_shader_hash\92\CF\E9Zn7}\1E\B9\E7\00\B1.hardware_mapping\91\A3.cs\B0.spill_threshold\CE\FF\FF\FF\FF\A5.type\A2Cs\B0.user_data_limit\01\AF.xgl_cache_info\82\B3.128_bit_cache_hash\92\CF\B4X\B8\11[\A4\88P\CF\A0;\B0\AF\FF\B4\BE\C0\AD.llpc_version\A461.1\AEamdpal.version\92\03\00"} +!1 = !{i32 7} diff --git a/llvm/test/CodeGen/AMDGPU/preload-kernarg-header.ll b/llvm/test/CodeGen/AMDGPU/preload-kernarg-header.ll index a70488a00db739a3c97a9688cd4cbfe95781b94c..a030f86da1b67d3a968834d715db20db7a0b7ce5 100644 --- a/llvm/test/CodeGen/AMDGPU/preload-kernarg-header.ll +++ b/llvm/test/CodeGen/AMDGPU/preload-kernarg-header.ll @@ -1,17 +1,20 @@ -; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx940 -amdgpu-kernarg-preload-count=1 -asm-verbose=0 < %s | FileCheck -check-prefixes=GCN,HSA %s -; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx940 -amdgpu-kernarg-preload-count=1 -filetype=obj < %s | llvm-objdump --arch=amdgcn --mcpu=gfx940 --disassemble - | FileCheck -check-prefixes=GCN,HSA %s -; RUN: llc -mtriple=amdgcn -mcpu=gfx940 -amdgpu-kernarg-preload-count=1 -filetype=obj < %s | llvm-objdump --arch=amdgcn --mcpu=gfx940 --disassemble - | FileCheck -check-prefixes=GCN,NON-HSA %s +; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx940 -amdgpu-kernarg-preload-count=1 -asm-verbose=0 < %s | FileCheck -check-prefixes=GCN,HSA,ASM %s +; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx940 -amdgpu-kernarg-preload-count=1 -filetype=obj < %s | llvm-objdump --arch=amdgcn --mcpu=gfx940 --disassemble - | FileCheck -check-prefixes=GCN,HSA,OBJ %s +; RUN: llc -mtriple=amdgcn -mcpu=gfx940 -amdgpu-kernarg-preload-count=1 -filetype=obj < %s | llvm-objdump --arch=amdgcn --mcpu=gfx940 --disassemble - | FileCheck -check-prefixes=GCN,NON-HSA,OBJ %s +; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx940 -amdgpu-kernarg-preload-count=1 -asm-verbose=0 < %s | llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx940 -filetype=obj | llvm-objdump --arch=amdgcn --mcpu=gfx940 --disassemble - | FileCheck -check-prefixes=GCN,HSA,OBJ %s ; GCN: preload_kernarg_header ; HSA: s_trap 2 ; NON-HSA: s_endpgm -; GCN-COUNT-63: s_nop 0 +; ASM: .fill 63, 4, 0xbf800000 ; s_nop 0 +; OBJ-COUNT-63: s_nop 0 define amdgpu_kernel void @preload_kernarg_header(ptr %arg) { store ptr %arg, ptr %arg ret void } ; GCN: non_kernel_function +; GCN-NOT: s_trap 2 ; GCN-NOT: s_nop 0 ; GCN: flat_store define void @non_kernel_function(ptr %arg) { diff --git a/llvm/test/CodeGen/AMDGPU/preload-kernargs-inreg-hints.ll b/llvm/test/CodeGen/AMDGPU/preload-kernargs-inreg-hints.ll index e7488e059ee9df8afec8c380ed69328cfff8164e..20edbd6c0d0fa6386f512893a112de87db1f48b2 100644 --- a/llvm/test/CodeGen/AMDGPU/preload-kernargs-inreg-hints.ll +++ b/llvm/test/CodeGen/AMDGPU/preload-kernargs-inreg-hints.ll @@ -157,27 +157,27 @@ define amdgpu_kernel void @test_preload_hint_kernel_1_call_func(ptr %0) #0 { define amdgpu_kernel void @test_preload_hint_kernel_1_call_intrinsic(i16 %0) #0 { ; NO-PRELOAD-LABEL: define {{[^@]+}}@test_preload_hint_kernel_1_call_intrinsic -; NO-PRELOAD-SAME: (i16 [[TMP0:%.*]]) #[[ATTR2]] { +; NO-PRELOAD-SAME: (i16 [[TMP0:%.*]]) #[[ATTR3:[0-9]+]] { ; NO-PRELOAD-NEXT: call void @llvm.amdgcn.set.prio(i16 [[TMP0]]) ; NO-PRELOAD-NEXT: ret void ; ; PRELOAD-1-LABEL: define {{[^@]+}}@test_preload_hint_kernel_1_call_intrinsic -; PRELOAD-1-SAME: (i16 inreg [[TMP0:%.*]]) #[[ATTR2]] { +; PRELOAD-1-SAME: (i16 inreg [[TMP0:%.*]]) #[[ATTR3:[0-9]+]] { ; PRELOAD-1-NEXT: call void @llvm.amdgcn.set.prio(i16 [[TMP0]]) ; PRELOAD-1-NEXT: ret void ; ; PRELOAD-3-LABEL: define {{[^@]+}}@test_preload_hint_kernel_1_call_intrinsic -; PRELOAD-3-SAME: (i16 inreg [[TMP0:%.*]]) #[[ATTR2]] { +; PRELOAD-3-SAME: (i16 inreg [[TMP0:%.*]]) #[[ATTR3:[0-9]+]] { ; PRELOAD-3-NEXT: call void @llvm.amdgcn.set.prio(i16 [[TMP0]]) ; PRELOAD-3-NEXT: ret void ; ; PRELOAD-16-LABEL: define {{[^@]+}}@test_preload_hint_kernel_1_call_intrinsic -; PRELOAD-16-SAME: (i16 inreg [[TMP0:%.*]]) #[[ATTR2]] { +; PRELOAD-16-SAME: (i16 inreg [[TMP0:%.*]]) #[[ATTR3:[0-9]+]] { ; PRELOAD-16-NEXT: call void @llvm.amdgcn.set.prio(i16 [[TMP0]]) ; PRELOAD-16-NEXT: ret void ; ; PRELOAD-20-LABEL: define {{[^@]+}}@test_preload_hint_kernel_1_call_intrinsic -; PRELOAD-20-SAME: (i16 inreg [[TMP0:%.*]]) #[[ATTR2]] { +; PRELOAD-20-SAME: (i16 inreg [[TMP0:%.*]]) #[[ATTR3:[0-9]+]] { ; PRELOAD-20-NEXT: call void @llvm.amdgcn.set.prio(i16 [[TMP0]]) ; PRELOAD-20-NEXT: ret void ; @@ -235,23 +235,23 @@ define amdgpu_kernel void @test_preload_hint_kernel_2_preexisting(i32 inreg %0, define amdgpu_kernel void @test_preload_hint_kernel_incompatible_attributes(ptr addrspace(4) byref(i32) %0, ptr nest %1) { ; NO-PRELOAD-LABEL: define {{[^@]+}}@test_preload_hint_kernel_incompatible_attributes -; NO-PRELOAD-SAME: (ptr addrspace(4) byref(i32) [[TMP0:%.*]], ptr nest [[TMP1:%.*]]) #[[ATTR3:[0-9]+]] { +; NO-PRELOAD-SAME: (ptr addrspace(4) byref(i32) [[TMP0:%.*]], ptr nest [[TMP1:%.*]]) #[[ATTR4:[0-9]+]] { ; NO-PRELOAD-NEXT: ret void ; ; PRELOAD-1-LABEL: define {{[^@]+}}@test_preload_hint_kernel_incompatible_attributes -; PRELOAD-1-SAME: (ptr addrspace(4) byref(i32) [[TMP0:%.*]], ptr nest [[TMP1:%.*]]) #[[ATTR3:[0-9]+]] { +; PRELOAD-1-SAME: (ptr addrspace(4) byref(i32) [[TMP0:%.*]], ptr nest [[TMP1:%.*]]) #[[ATTR4:[0-9]+]] { ; PRELOAD-1-NEXT: ret void ; ; PRELOAD-3-LABEL: define {{[^@]+}}@test_preload_hint_kernel_incompatible_attributes -; PRELOAD-3-SAME: (ptr addrspace(4) byref(i32) [[TMP0:%.*]], ptr nest [[TMP1:%.*]]) #[[ATTR3:[0-9]+]] { +; PRELOAD-3-SAME: (ptr addrspace(4) byref(i32) [[TMP0:%.*]], ptr nest [[TMP1:%.*]]) #[[ATTR4:[0-9]+]] { ; PRELOAD-3-NEXT: ret void ; ; PRELOAD-16-LABEL: define {{[^@]+}}@test_preload_hint_kernel_incompatible_attributes -; PRELOAD-16-SAME: (ptr addrspace(4) byref(i32) [[TMP0:%.*]], ptr nest [[TMP1:%.*]]) #[[ATTR3:[0-9]+]] { +; PRELOAD-16-SAME: (ptr addrspace(4) byref(i32) [[TMP0:%.*]], ptr nest [[TMP1:%.*]]) #[[ATTR4:[0-9]+]] { ; PRELOAD-16-NEXT: ret void ; ; PRELOAD-20-LABEL: define {{[^@]+}}@test_preload_hint_kernel_incompatible_attributes -; PRELOAD-20-SAME: (ptr addrspace(4) byref(i32) [[TMP0:%.*]], ptr nest [[TMP1:%.*]]) #[[ATTR3:[0-9]+]] { +; PRELOAD-20-SAME: (ptr addrspace(4) byref(i32) [[TMP0:%.*]], ptr nest [[TMP1:%.*]]) #[[ATTR4:[0-9]+]] { ; PRELOAD-20-NEXT: ret void ; ret void diff --git a/llvm/test/CodeGen/AMDGPU/preload-kernargs.ll b/llvm/test/CodeGen/AMDGPU/preload-kernargs.ll index d20c3a4007ffdde4af801ad345f7fb7ffea9815f..f0e709b5a17279c8121cd93c0a72d3a05f61efa6 100644 --- a/llvm/test/CodeGen/AMDGPU/preload-kernargs.ll +++ b/llvm/test/CodeGen/AMDGPU/preload-kernargs.ll @@ -24,70 +24,8 @@ define amdgpu_kernel void @ptr1_i8(ptr addrspace(1) %out, i8 %arg0) { ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; ; GFX940-PRELOAD-1-LABEL: ptr1_i8: -; GFX940-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 +; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-1-NEXT: ; %bb.0: ; GFX940-PRELOAD-1-NEXT: s_load_dword s0, s[0:1], 0x8 ; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 @@ -98,70 +36,8 @@ define amdgpu_kernel void @ptr1_i8(ptr addrspace(1) %out, i8 %arg0) { ; GFX940-PRELOAD-1-NEXT: s_endpgm ; ; GFX940-PRELOAD-2-LABEL: ptr1_i8: -; GFX940-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: ; GFX940-PRELOAD-2-NEXT: s_and_b32 s0, s4, 0xff ; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 @@ -170,70 +46,8 @@ define amdgpu_kernel void @ptr1_i8(ptr addrspace(1) %out, i8 %arg0) { ; GFX940-PRELOAD-2-NEXT: s_endpgm ; ; GFX940-PRELOAD-4-LABEL: ptr1_i8: -; GFX940-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 +; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-4-NEXT: ; %bb.0: ; GFX940-PRELOAD-4-NEXT: s_and_b32 s0, s4, 0xff ; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 @@ -242,70 +56,8 @@ define amdgpu_kernel void @ptr1_i8(ptr addrspace(1) %out, i8 %arg0) { ; GFX940-PRELOAD-4-NEXT: s_endpgm ; ; GFX940-PRELOAD-8-LABEL: ptr1_i8: -; GFX940-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: ; GFX940-PRELOAD-8-NEXT: s_and_b32 s0, s4, 0xff ; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 @@ -325,70 +77,8 @@ define amdgpu_kernel void @ptr1_i8(ptr addrspace(1) %out, i8 %arg0) { ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; ; GFX90a-PRELOAD-1-LABEL: ptr1_i8: -; GFX90a-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 +; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-1-NEXT: ; %bb.0: ; GFX90a-PRELOAD-1-NEXT: s_load_dword s0, s[4:5], 0x8 ; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 @@ -399,70 +89,8 @@ define amdgpu_kernel void @ptr1_i8(ptr addrspace(1) %out, i8 %arg0) { ; GFX90a-PRELOAD-1-NEXT: s_endpgm ; ; GFX90a-PRELOAD-2-LABEL: ptr1_i8: -; GFX90a-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: ; GFX90a-PRELOAD-2-NEXT: s_and_b32 s0, s8, 0xff ; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 @@ -471,70 +99,8 @@ define amdgpu_kernel void @ptr1_i8(ptr addrspace(1) %out, i8 %arg0) { ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; ; GFX90a-PRELOAD-4-LABEL: ptr1_i8: -; GFX90a-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 +; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-4-NEXT: ; %bb.0: ; GFX90a-PRELOAD-4-NEXT: s_and_b32 s0, s8, 0xff ; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 @@ -543,70 +109,8 @@ define amdgpu_kernel void @ptr1_i8(ptr addrspace(1) %out, i8 %arg0) { ; GFX90a-PRELOAD-4-NEXT: s_endpgm ; ; GFX90a-PRELOAD-8-LABEL: ptr1_i8: -; GFX90a-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: ; GFX90a-PRELOAD-8-NEXT: s_and_b32 s0, s8, 0xff ; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 @@ -631,70 +135,8 @@ define amdgpu_kernel void @ptr1_i8_zext_arg(ptr addrspace(1) %out, i8 zeroext %a ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; ; GFX940-PRELOAD-1-LABEL: ptr1_i8_zext_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 +; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-1-NEXT: ; %bb.0: ; GFX940-PRELOAD-1-NEXT: s_load_dword s0, s[0:1], 0x8 ; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 @@ -705,70 +147,8 @@ define amdgpu_kernel void @ptr1_i8_zext_arg(ptr addrspace(1) %out, i8 zeroext %a ; GFX940-PRELOAD-1-NEXT: s_endpgm ; ; GFX940-PRELOAD-2-LABEL: ptr1_i8_zext_arg: -; GFX940-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: ; GFX940-PRELOAD-2-NEXT: s_mov_b32 s0, 0xffff ; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s4 @@ -778,70 +158,8 @@ define amdgpu_kernel void @ptr1_i8_zext_arg(ptr addrspace(1) %out, i8 zeroext %a ; GFX940-PRELOAD-2-NEXT: s_endpgm ; ; GFX940-PRELOAD-4-LABEL: ptr1_i8_zext_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 +; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-4-NEXT: ; %bb.0: ; GFX940-PRELOAD-4-NEXT: s_mov_b32 s0, 0xffff ; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s4 @@ -851,70 +169,8 @@ define amdgpu_kernel void @ptr1_i8_zext_arg(ptr addrspace(1) %out, i8 zeroext %a ; GFX940-PRELOAD-4-NEXT: s_endpgm ; ; GFX940-PRELOAD-8-LABEL: ptr1_i8_zext_arg: -; GFX940-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: ; GFX940-PRELOAD-8-NEXT: s_mov_b32 s0, 0xffff ; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s4 @@ -935,70 +191,8 @@ define amdgpu_kernel void @ptr1_i8_zext_arg(ptr addrspace(1) %out, i8 zeroext %a ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; ; GFX90a-PRELOAD-1-LABEL: ptr1_i8_zext_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 +; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-1-NEXT: ; %bb.0: ; GFX90a-PRELOAD-1-NEXT: s_load_dword s0, s[4:5], 0x8 ; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 @@ -1009,70 +203,8 @@ define amdgpu_kernel void @ptr1_i8_zext_arg(ptr addrspace(1) %out, i8 zeroext %a ; GFX90a-PRELOAD-1-NEXT: s_endpgm ; ; GFX90a-PRELOAD-2-LABEL: ptr1_i8_zext_arg: -; GFX90a-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: ; GFX90a-PRELOAD-2-NEXT: s_mov_b32 s0, 0xffff ; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s8 @@ -1082,70 +214,8 @@ define amdgpu_kernel void @ptr1_i8_zext_arg(ptr addrspace(1) %out, i8 zeroext %a ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; ; GFX90a-PRELOAD-4-LABEL: ptr1_i8_zext_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 +; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-4-NEXT: ; %bb.0: ; GFX90a-PRELOAD-4-NEXT: s_mov_b32 s0, 0xffff ; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s8 @@ -1155,70 +225,8 @@ define amdgpu_kernel void @ptr1_i8_zext_arg(ptr addrspace(1) %out, i8 zeroext %a ; GFX90a-PRELOAD-4-NEXT: s_endpgm ; ; GFX90a-PRELOAD-8-LABEL: ptr1_i8_zext_arg: -; GFX90a-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: ; GFX90a-PRELOAD-8-NEXT: s_mov_b32 s0, 0xffff ; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s8 @@ -1244,70 +252,8 @@ define amdgpu_kernel void @ptr1_i16_preload_arg(ptr addrspace(1) %out, i16 %arg0 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; ; GFX940-PRELOAD-1-LABEL: ptr1_i16_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 +; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-1-NEXT: ; %bb.0: ; GFX940-PRELOAD-1-NEXT: s_load_dword s0, s[0:1], 0x8 ; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 @@ -1318,70 +264,8 @@ define amdgpu_kernel void @ptr1_i16_preload_arg(ptr addrspace(1) %out, i16 %arg0 ; GFX940-PRELOAD-1-NEXT: s_endpgm ; ; GFX940-PRELOAD-2-LABEL: ptr1_i16_preload_arg: -; GFX940-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: ; GFX940-PRELOAD-2-NEXT: s_and_b32 s0, s4, 0xffff ; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 @@ -1390,70 +274,8 @@ define amdgpu_kernel void @ptr1_i16_preload_arg(ptr addrspace(1) %out, i16 %arg0 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; ; GFX940-PRELOAD-4-LABEL: ptr1_i16_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 +; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-4-NEXT: ; %bb.0: ; GFX940-PRELOAD-4-NEXT: s_and_b32 s0, s4, 0xffff ; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 @@ -1462,70 +284,8 @@ define amdgpu_kernel void @ptr1_i16_preload_arg(ptr addrspace(1) %out, i16 %arg0 ; GFX940-PRELOAD-4-NEXT: s_endpgm ; ; GFX940-PRELOAD-8-LABEL: ptr1_i16_preload_arg: -; GFX940-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: ; GFX940-PRELOAD-8-NEXT: s_and_b32 s0, s4, 0xffff ; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 @@ -1545,70 +305,8 @@ define amdgpu_kernel void @ptr1_i16_preload_arg(ptr addrspace(1) %out, i16 %arg0 ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; ; GFX90a-PRELOAD-1-LABEL: ptr1_i16_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 +; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-1-NEXT: ; %bb.0: ; GFX90a-PRELOAD-1-NEXT: s_load_dword s0, s[4:5], 0x8 ; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 @@ -1619,70 +317,8 @@ define amdgpu_kernel void @ptr1_i16_preload_arg(ptr addrspace(1) %out, i16 %arg0 ; GFX90a-PRELOAD-1-NEXT: s_endpgm ; ; GFX90a-PRELOAD-2-LABEL: ptr1_i16_preload_arg: -; GFX90a-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: ; GFX90a-PRELOAD-2-NEXT: s_and_b32 s0, s8, 0xffff ; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 @@ -1691,70 +327,8 @@ define amdgpu_kernel void @ptr1_i16_preload_arg(ptr addrspace(1) %out, i16 %arg0 ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; ; GFX90a-PRELOAD-4-LABEL: ptr1_i16_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 +; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-4-NEXT: ; %bb.0: ; GFX90a-PRELOAD-4-NEXT: s_and_b32 s0, s8, 0xffff ; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 @@ -1763,70 +337,8 @@ define amdgpu_kernel void @ptr1_i16_preload_arg(ptr addrspace(1) %out, i16 %arg0 ; GFX90a-PRELOAD-4-NEXT: s_endpgm ; ; GFX90a-PRELOAD-8-LABEL: ptr1_i16_preload_arg: -; GFX90a-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: ; GFX90a-PRELOAD-8-NEXT: s_and_b32 s0, s8, 0xffff ; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 @@ -1850,70 +362,8 @@ define amdgpu_kernel void @ptr1_i32_preload_arg(ptr addrspace(1) %out, i32 %arg0 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; ; GFX940-PRELOAD-1-LABEL: ptr1_i32_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 +; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-1-NEXT: ; %bb.0: ; GFX940-PRELOAD-1-NEXT: s_load_dword s0, s[0:1], 0x8 ; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 @@ -1923,70 +373,8 @@ define amdgpu_kernel void @ptr1_i32_preload_arg(ptr addrspace(1) %out, i32 %arg0 ; GFX940-PRELOAD-1-NEXT: s_endpgm ; ; GFX940-PRELOAD-2-LABEL: ptr1_i32_preload_arg: -; GFX940-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: ; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 ; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s4 @@ -1994,70 +382,8 @@ define amdgpu_kernel void @ptr1_i32_preload_arg(ptr addrspace(1) %out, i32 %arg0 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; ; GFX940-PRELOAD-4-LABEL: ptr1_i32_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 +; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-4-NEXT: ; %bb.0: ; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 ; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s4 @@ -2065,70 +391,8 @@ define amdgpu_kernel void @ptr1_i32_preload_arg(ptr addrspace(1) %out, i32 %arg0 ; GFX940-PRELOAD-4-NEXT: s_endpgm ; ; GFX940-PRELOAD-8-LABEL: ptr1_i32_preload_arg: -; GFX940-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: ; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 ; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s4 @@ -2146,70 +410,8 @@ define amdgpu_kernel void @ptr1_i32_preload_arg(ptr addrspace(1) %out, i32 %arg0 ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; ; GFX90a-PRELOAD-1-LABEL: ptr1_i32_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 +; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-1-NEXT: ; %bb.0: ; GFX90a-PRELOAD-1-NEXT: s_load_dword s0, s[4:5], 0x8 ; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 @@ -2219,70 +421,8 @@ define amdgpu_kernel void @ptr1_i32_preload_arg(ptr addrspace(1) %out, i32 %arg0 ; GFX90a-PRELOAD-1-NEXT: s_endpgm ; ; GFX90a-PRELOAD-2-LABEL: ptr1_i32_preload_arg: -; GFX90a-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: ; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 ; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s8 @@ -2290,70 +430,8 @@ define amdgpu_kernel void @ptr1_i32_preload_arg(ptr addrspace(1) %out, i32 %arg0 ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; ; GFX90a-PRELOAD-4-LABEL: ptr1_i32_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 +; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-4-NEXT: ; %bb.0: ; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 ; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s8 @@ -2361,70 +439,8 @@ define amdgpu_kernel void @ptr1_i32_preload_arg(ptr addrspace(1) %out, i32 %arg0 ; GFX90a-PRELOAD-4-NEXT: s_endpgm ; ; GFX90a-PRELOAD-8-LABEL: ptr1_i32_preload_arg: -; GFX90a-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: ; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 ; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s8 @@ -2449,70 +465,8 @@ define amdgpu_kernel void @i32_ptr1_i32_preload_arg(i32 %arg0, ptr addrspace(1) ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; ; GFX940-PRELOAD-1-LABEL: i32_ptr1_i32_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 +; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-1-NEXT: ; %bb.0: ; GFX940-PRELOAD-1-NEXT: s_load_dword s3, s[0:1], 0x10 ; GFX940-PRELOAD-1-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x8 @@ -2524,70 +478,8 @@ define amdgpu_kernel void @i32_ptr1_i32_preload_arg(i32 %arg0, ptr addrspace(1) ; GFX940-PRELOAD-1-NEXT: s_endpgm ; ; GFX940-PRELOAD-2-LABEL: i32_ptr1_i32_preload_arg: -; GFX940-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: ; GFX940-PRELOAD-2-NEXT: s_load_dword s0, s[0:1], 0x10 ; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 @@ -2598,70 +490,8 @@ define amdgpu_kernel void @i32_ptr1_i32_preload_arg(i32 %arg0, ptr addrspace(1) ; GFX940-PRELOAD-2-NEXT: s_endpgm ; ; GFX940-PRELOAD-4-LABEL: i32_ptr1_i32_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 +; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-4-NEXT: ; %bb.0: ; GFX940-PRELOAD-4-NEXT: s_add_i32 s0, s2, s6 ; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 @@ -2670,70 +500,8 @@ define amdgpu_kernel void @i32_ptr1_i32_preload_arg(i32 %arg0, ptr addrspace(1) ; GFX940-PRELOAD-4-NEXT: s_endpgm ; ; GFX940-PRELOAD-8-LABEL: i32_ptr1_i32_preload_arg: -; GFX940-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: ; GFX940-PRELOAD-8-NEXT: s_add_i32 s0, s2, s6 ; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 @@ -2754,70 +522,8 @@ define amdgpu_kernel void @i32_ptr1_i32_preload_arg(i32 %arg0, ptr addrspace(1) ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; ; GFX90a-PRELOAD-1-LABEL: i32_ptr1_i32_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 +; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-1-NEXT: ; %bb.0: ; GFX90a-PRELOAD-1-NEXT: s_load_dword s2, s[4:5], 0x10 ; GFX90a-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x8 @@ -2829,70 +535,8 @@ define amdgpu_kernel void @i32_ptr1_i32_preload_arg(i32 %arg0, ptr addrspace(1) ; GFX90a-PRELOAD-1-NEXT: s_endpgm ; ; GFX90a-PRELOAD-2-LABEL: i32_ptr1_i32_preload_arg: -; GFX90a-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: ; GFX90a-PRELOAD-2-NEXT: s_load_dword s0, s[4:5], 0x10 ; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 @@ -2903,70 +547,8 @@ define amdgpu_kernel void @i32_ptr1_i32_preload_arg(i32 %arg0, ptr addrspace(1) ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; ; GFX90a-PRELOAD-4-LABEL: i32_ptr1_i32_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 +; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-4-NEXT: ; %bb.0: ; GFX90a-PRELOAD-4-NEXT: s_add_i32 s0, s6, s10 ; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 @@ -2975,70 +557,8 @@ define amdgpu_kernel void @i32_ptr1_i32_preload_arg(i32 %arg0, ptr addrspace(1) ; GFX90a-PRELOAD-4-NEXT: s_endpgm ; ; GFX90a-PRELOAD-8-LABEL: i32_ptr1_i32_preload_arg: -; GFX90a-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: ; GFX90a-PRELOAD-8-NEXT: s_add_i32 s0, s6, s10 ; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 @@ -3065,70 +585,8 @@ define amdgpu_kernel void @ptr1_i16_i16_preload_arg(ptr addrspace(1) %out, i16 % ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; ; GFX940-PRELOAD-1-LABEL: ptr1_i16_i16_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 +; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-1-NEXT: ; %bb.0: ; GFX940-PRELOAD-1-NEXT: s_load_dword s0, s[0:1], 0x8 ; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 @@ -3141,70 +599,8 @@ define amdgpu_kernel void @ptr1_i16_i16_preload_arg(ptr addrspace(1) %out, i16 % ; GFX940-PRELOAD-1-NEXT: s_endpgm ; ; GFX940-PRELOAD-2-LABEL: ptr1_i16_i16_preload_arg: -; GFX940-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: ; GFX940-PRELOAD-2-NEXT: s_load_dword s0, s[0:1], 0x8 ; GFX940-PRELOAD-2-NEXT: s_and_b32 s1, s4, 0xffff @@ -3217,70 +613,8 @@ define amdgpu_kernel void @ptr1_i16_i16_preload_arg(ptr addrspace(1) %out, i16 % ; GFX940-PRELOAD-2-NEXT: s_endpgm ; ; GFX940-PRELOAD-4-LABEL: ptr1_i16_i16_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 +; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-4-NEXT: ; %bb.0: ; GFX940-PRELOAD-4-NEXT: s_lshr_b32 s0, s4, 16 ; GFX940-PRELOAD-4-NEXT: s_and_b32 s1, s4, 0xffff @@ -3291,70 +625,8 @@ define amdgpu_kernel void @ptr1_i16_i16_preload_arg(ptr addrspace(1) %out, i16 % ; GFX940-PRELOAD-4-NEXT: s_endpgm ; ; GFX940-PRELOAD-8-LABEL: ptr1_i16_i16_preload_arg: -; GFX940-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: ; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s4, 16 ; GFX940-PRELOAD-8-NEXT: s_and_b32 s1, s4, 0xffff @@ -3378,70 +650,8 @@ define amdgpu_kernel void @ptr1_i16_i16_preload_arg(ptr addrspace(1) %out, i16 % ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; ; GFX90a-PRELOAD-1-LABEL: ptr1_i16_i16_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 +; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-1-NEXT: ; %bb.0: ; GFX90a-PRELOAD-1-NEXT: s_load_dword s0, s[4:5], 0x8 ; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 @@ -3454,70 +664,8 @@ define amdgpu_kernel void @ptr1_i16_i16_preload_arg(ptr addrspace(1) %out, i16 % ; GFX90a-PRELOAD-1-NEXT: s_endpgm ; ; GFX90a-PRELOAD-2-LABEL: ptr1_i16_i16_preload_arg: -; GFX90a-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: ; GFX90a-PRELOAD-2-NEXT: s_load_dword s0, s[4:5], 0x8 ; GFX90a-PRELOAD-2-NEXT: s_and_b32 s1, s8, 0xffff @@ -3530,70 +678,8 @@ define amdgpu_kernel void @ptr1_i16_i16_preload_arg(ptr addrspace(1) %out, i16 % ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; ; GFX90a-PRELOAD-4-LABEL: ptr1_i16_i16_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 +; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-4-NEXT: ; %bb.0: ; GFX90a-PRELOAD-4-NEXT: s_lshr_b32 s0, s8, 16 ; GFX90a-PRELOAD-4-NEXT: s_and_b32 s1, s8, 0xffff @@ -3604,70 +690,8 @@ define amdgpu_kernel void @ptr1_i16_i16_preload_arg(ptr addrspace(1) %out, i16 % ; GFX90a-PRELOAD-4-NEXT: s_endpgm ; ; GFX90a-PRELOAD-8-LABEL: ptr1_i16_i16_preload_arg: -; GFX90a-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: ; GFX90a-PRELOAD-8-NEXT: s_lshr_b32 s0, s8, 16 ; GFX90a-PRELOAD-8-NEXT: s_and_b32 s1, s8, 0xffff @@ -3695,70 +719,8 @@ define amdgpu_kernel void @ptr1_v2i8_preload_arg(ptr addrspace(1) %out, <2 x i8> ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; ; GFX940-PRELOAD-1-LABEL: ptr1_v2i8_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 +; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-1-NEXT: ; %bb.0: ; GFX940-PRELOAD-1-NEXT: s_load_dword s0, s[0:1], 0x8 ; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 @@ -3768,70 +730,8 @@ define amdgpu_kernel void @ptr1_v2i8_preload_arg(ptr addrspace(1) %out, <2 x i8> ; GFX940-PRELOAD-1-NEXT: s_endpgm ; ; GFX940-PRELOAD-2-LABEL: ptr1_v2i8_preload_arg: -; GFX940-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: ; GFX940-PRELOAD-2-NEXT: s_lshr_b32 s0, s4, 8 ; GFX940-PRELOAD-2-NEXT: v_lshlrev_b16_e64 v0, 8, s0 @@ -3841,70 +741,8 @@ define amdgpu_kernel void @ptr1_v2i8_preload_arg(ptr addrspace(1) %out, <2 x i8> ; GFX940-PRELOAD-2-NEXT: s_endpgm ; ; GFX940-PRELOAD-4-LABEL: ptr1_v2i8_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 +; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-4-NEXT: ; %bb.0: ; GFX940-PRELOAD-4-NEXT: s_lshr_b32 s0, s4, 8 ; GFX940-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v0, 8, s0 @@ -3914,70 +752,8 @@ define amdgpu_kernel void @ptr1_v2i8_preload_arg(ptr addrspace(1) %out, <2 x i8> ; GFX940-PRELOAD-4-NEXT: s_endpgm ; ; GFX940-PRELOAD-8-LABEL: ptr1_v2i8_preload_arg: -; GFX940-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: ; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s4, 8 ; GFX940-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v0, 8, s0 @@ -3997,70 +773,8 @@ define amdgpu_kernel void @ptr1_v2i8_preload_arg(ptr addrspace(1) %out, <2 x i8> ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; ; GFX90a-PRELOAD-1-LABEL: ptr1_v2i8_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 +; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-1-NEXT: ; %bb.0: ; GFX90a-PRELOAD-1-NEXT: s_load_dword s0, s[4:5], 0x8 ; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 @@ -4070,70 +784,8 @@ define amdgpu_kernel void @ptr1_v2i8_preload_arg(ptr addrspace(1) %out, <2 x i8> ; GFX90a-PRELOAD-1-NEXT: s_endpgm ; ; GFX90a-PRELOAD-2-LABEL: ptr1_v2i8_preload_arg: -; GFX90a-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: ; GFX90a-PRELOAD-2-NEXT: s_lshr_b32 s0, s8, 8 ; GFX90a-PRELOAD-2-NEXT: v_lshlrev_b16_e64 v0, 8, s0 @@ -4143,70 +795,8 @@ define amdgpu_kernel void @ptr1_v2i8_preload_arg(ptr addrspace(1) %out, <2 x i8> ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; ; GFX90a-PRELOAD-4-LABEL: ptr1_v2i8_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 +; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-4-NEXT: ; %bb.0: ; GFX90a-PRELOAD-4-NEXT: s_lshr_b32 s0, s8, 8 ; GFX90a-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v0, 8, s0 @@ -4216,70 +806,8 @@ define amdgpu_kernel void @ptr1_v2i8_preload_arg(ptr addrspace(1) %out, <2 x i8> ; GFX90a-PRELOAD-4-NEXT: s_endpgm ; ; GFX90a-PRELOAD-8-LABEL: ptr1_v2i8_preload_arg: -; GFX90a-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: ; GFX90a-PRELOAD-8-NEXT: s_lshr_b32 s0, s8, 8 ; GFX90a-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v0, 8, s0 @@ -4308,70 +836,8 @@ define amdgpu_kernel void @byref_preload_arg(ptr addrspace(1) %out, ptr addrspac ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; ; GFX940-PRELOAD-1-LABEL: byref_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 +; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-1-NEXT: ; %bb.0: ; GFX940-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x100 ; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 @@ -4385,70 +851,8 @@ define amdgpu_kernel void @byref_preload_arg(ptr addrspace(1) %out, ptr addrspac ; GFX940-PRELOAD-1-NEXT: s_endpgm ; ; GFX940-PRELOAD-2-LABEL: byref_preload_arg: -; GFX940-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: ; GFX940-PRELOAD-2-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x100 ; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 @@ -4462,70 +866,8 @@ define amdgpu_kernel void @byref_preload_arg(ptr addrspace(1) %out, ptr addrspac ; GFX940-PRELOAD-2-NEXT: s_endpgm ; ; GFX940-PRELOAD-4-LABEL: byref_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 +; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-4-NEXT: ; %bb.0: ; GFX940-PRELOAD-4-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x100 ; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 @@ -4539,70 +881,8 @@ define amdgpu_kernel void @byref_preload_arg(ptr addrspace(1) %out, ptr addrspac ; GFX940-PRELOAD-4-NEXT: s_endpgm ; ; GFX940-PRELOAD-8-LABEL: byref_preload_arg: -; GFX940-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: ; GFX940-PRELOAD-8-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x100 ; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 @@ -4630,70 +910,8 @@ define amdgpu_kernel void @byref_preload_arg(ptr addrspace(1) %out, ptr addrspac ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; ; GFX90a-PRELOAD-1-LABEL: byref_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 +; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-1-NEXT: ; %bb.0: ; GFX90a-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x100 ; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 @@ -4707,70 +925,8 @@ define amdgpu_kernel void @byref_preload_arg(ptr addrspace(1) %out, ptr addrspac ; GFX90a-PRELOAD-1-NEXT: s_endpgm ; ; GFX90a-PRELOAD-2-LABEL: byref_preload_arg: -; GFX90a-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: ; GFX90a-PRELOAD-2-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x100 ; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 @@ -4784,70 +940,8 @@ define amdgpu_kernel void @byref_preload_arg(ptr addrspace(1) %out, ptr addrspac ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; ; GFX90a-PRELOAD-4-LABEL: byref_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 +; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-4-NEXT: ; %bb.0: ; GFX90a-PRELOAD-4-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x100 ; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 @@ -4861,70 +955,8 @@ define amdgpu_kernel void @byref_preload_arg(ptr addrspace(1) %out, ptr addrspac ; GFX90a-PRELOAD-4-NEXT: s_endpgm ; ; GFX90a-PRELOAD-8-LABEL: byref_preload_arg: -; GFX90a-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: ; GFX90a-PRELOAD-8-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x100 ; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 @@ -4964,70 +996,8 @@ define amdgpu_kernel void @v8i32_arg(ptr addrspace(1) nocapture %out, <8 x i32> ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; ; GFX940-PRELOAD-1-LABEL: v8i32_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 +; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-1-NEXT: ; %bb.0: ; GFX940-PRELOAD-1-NEXT: s_load_dwordx8 s[4:11], s[0:1], 0x20 ; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v4, 0 @@ -5046,70 +1016,8 @@ define amdgpu_kernel void @v8i32_arg(ptr addrspace(1) nocapture %out, <8 x i32> ; GFX940-PRELOAD-1-NEXT: s_endpgm ; ; GFX940-PRELOAD-2-LABEL: v8i32_arg: -; GFX940-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: ; GFX940-PRELOAD-2-NEXT: s_load_dwordx8 s[4:11], s[0:1], 0x20 ; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v4, 0 @@ -5128,70 +1036,8 @@ define amdgpu_kernel void @v8i32_arg(ptr addrspace(1) nocapture %out, <8 x i32> ; GFX940-PRELOAD-2-NEXT: s_endpgm ; ; GFX940-PRELOAD-4-LABEL: v8i32_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 +; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-4-NEXT: ; %bb.0: ; GFX940-PRELOAD-4-NEXT: s_load_dwordx8 s[4:11], s[0:1], 0x20 ; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v4, 0 @@ -5210,70 +1056,8 @@ define amdgpu_kernel void @v8i32_arg(ptr addrspace(1) nocapture %out, <8 x i32> ; GFX940-PRELOAD-4-NEXT: s_endpgm ; ; GFX940-PRELOAD-8-LABEL: v8i32_arg: -; GFX940-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: ; GFX940-PRELOAD-8-NEXT: s_load_dwordx8 s[4:11], s[0:1], 0x20 ; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v4, 0 @@ -5311,70 +1095,8 @@ define amdgpu_kernel void @v8i32_arg(ptr addrspace(1) nocapture %out, <8 x i32> ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; ; GFX90a-PRELOAD-1-LABEL: v8i32_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 +; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-1-NEXT: ; %bb.0: ; GFX90a-PRELOAD-1-NEXT: s_load_dwordx8 s[8:15], s[4:5], 0x20 ; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v4, 0 @@ -5393,79 +1115,17 @@ define amdgpu_kernel void @v8i32_arg(ptr addrspace(1) nocapture %out, <8 x i32> ; GFX90a-PRELOAD-1-NEXT: s_endpgm ; ; GFX90a-PRELOAD-2-LABEL: v8i32_arg: -; GFX90a-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: ; %bb.0: -; GFX90a-PRELOAD-2-NEXT: s_load_dwordx8 s[8:15], s[4:5], 0x20 -; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v4, 0 -; GFX90a-PRELOAD-2-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s12 -; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s13 -; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v2, s14 -; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v3, s15 -; GFX90a-PRELOAD-2-NEXT: global_store_dwordx4 v4, v[0:3], s[6:7] offset:16 +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-2-NEXT: ; %bb.0: +; GFX90a-PRELOAD-2-NEXT: s_load_dwordx8 s[8:15], s[4:5], 0x20 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v4, 0 +; GFX90a-PRELOAD-2-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s12 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s13 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v2, s14 +; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v3, s15 +; GFX90a-PRELOAD-2-NEXT: global_store_dwordx4 v4, v[0:3], s[6:7] offset:16 ; GFX90a-PRELOAD-2-NEXT: s_nop 0 ; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s8 ; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s9 @@ -5475,70 +1135,8 @@ define amdgpu_kernel void @v8i32_arg(ptr addrspace(1) nocapture %out, <8 x i32> ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; ; GFX90a-PRELOAD-4-LABEL: v8i32_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 +; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-4-NEXT: ; %bb.0: ; GFX90a-PRELOAD-4-NEXT: s_load_dwordx8 s[8:15], s[4:5], 0x20 ; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v4, 0 @@ -5557,70 +1155,8 @@ define amdgpu_kernel void @v8i32_arg(ptr addrspace(1) nocapture %out, <8 x i32> ; GFX90a-PRELOAD-4-NEXT: s_endpgm ; ; GFX90a-PRELOAD-8-LABEL: v8i32_arg: -; GFX90a-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: ; GFX90a-PRELOAD-8-NEXT: s_load_dwordx8 s[8:15], s[4:5], 0x20 ; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v4, 0 @@ -5654,70 +1190,8 @@ define amdgpu_kernel void @v3i16_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; ; GFX940-PRELOAD-1-LABEL: v3i16_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 +; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-1-NEXT: ; %bb.0: ; GFX940-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x8 ; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 @@ -5729,70 +1203,8 @@ define amdgpu_kernel void @v3i16_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-PRELOAD-1-NEXT: s_endpgm ; ; GFX940-PRELOAD-2-LABEL: v3i16_preload_arg: -; GFX940-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: ; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 ; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s5 @@ -5802,70 +1214,8 @@ define amdgpu_kernel void @v3i16_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; ; GFX940-PRELOAD-4-LABEL: v3i16_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 +; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-4-NEXT: ; %bb.0: ; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 ; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s5 @@ -5875,70 +1225,8 @@ define amdgpu_kernel void @v3i16_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-PRELOAD-4-NEXT: s_endpgm ; ; GFX940-PRELOAD-8-LABEL: v3i16_preload_arg: -; GFX940-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: ; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 ; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s5 @@ -5959,70 +1247,8 @@ define amdgpu_kernel void @v3i16_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; ; GFX90a-PRELOAD-1-LABEL: v3i16_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 +; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-1-NEXT: ; %bb.0: ; GFX90a-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x8 ; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 @@ -6034,70 +1260,8 @@ define amdgpu_kernel void @v3i16_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX90a-PRELOAD-1-NEXT: s_endpgm ; ; GFX90a-PRELOAD-2-LABEL: v3i16_preload_arg: -; GFX90a-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: ; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, 0 ; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s9 @@ -6107,70 +1271,8 @@ define amdgpu_kernel void @v3i16_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; ; GFX90a-PRELOAD-4-LABEL: v3i16_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 +; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-4-NEXT: ; %bb.0: ; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, 0 ; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s9 @@ -6180,70 +1282,8 @@ define amdgpu_kernel void @v3i16_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX90a-PRELOAD-4-NEXT: s_endpgm ; ; GFX90a-PRELOAD-8-LABEL: v3i16_preload_arg: -; GFX90a-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: ; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, 0 ; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s9 @@ -6269,70 +1309,8 @@ define amdgpu_kernel void @v3i32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; ; GFX940-PRELOAD-1-LABEL: v3i32_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 +; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-1-NEXT: ; %bb.0: ; GFX940-PRELOAD-1-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x10 ; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v3, 0 @@ -6344,70 +1322,8 @@ define amdgpu_kernel void @v3i32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-PRELOAD-1-NEXT: s_endpgm ; ; GFX940-PRELOAD-2-LABEL: v3i32_preload_arg: -; GFX940-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: ; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s6 ; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s7 @@ -6417,70 +1333,8 @@ define amdgpu_kernel void @v3i32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; ; GFX940-PRELOAD-4-LABEL: v3i32_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 +; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-4-NEXT: ; %bb.0: ; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, s6 ; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s7 @@ -6490,70 +1344,8 @@ define amdgpu_kernel void @v3i32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-PRELOAD-4-NEXT: s_endpgm ; ; GFX940-PRELOAD-8-LABEL: v3i32_preload_arg: -; GFX940-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: ; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s6 ; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s7 @@ -6575,70 +1367,8 @@ define amdgpu_kernel void @v3i32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; ; GFX90a-PRELOAD-1-LABEL: v3i32_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 +; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-1-NEXT: ; %bb.0: ; GFX90a-PRELOAD-1-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x10 ; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v3, 0 @@ -6650,70 +1380,8 @@ define amdgpu_kernel void @v3i32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX90a-PRELOAD-1-NEXT: s_endpgm ; ; GFX90a-PRELOAD-2-LABEL: v3i32_preload_arg: -; GFX90a-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: ; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s10 ; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v1, s11 @@ -6723,70 +1391,8 @@ define amdgpu_kernel void @v3i32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; ; GFX90a-PRELOAD-4-LABEL: v3i32_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 +; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-4-NEXT: ; %bb.0: ; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, s10 ; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v1, s11 @@ -6796,70 +1402,8 @@ define amdgpu_kernel void @v3i32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX90a-PRELOAD-4-NEXT: s_endpgm ; ; GFX90a-PRELOAD-8-LABEL: v3i32_preload_arg: -; GFX90a-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: ; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s10 ; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s11 @@ -6885,70 +1429,8 @@ define amdgpu_kernel void @v3f32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; ; GFX940-PRELOAD-1-LABEL: v3f32_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 +; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-1-NEXT: ; %bb.0: ; GFX940-PRELOAD-1-NEXT: s_load_dwordx4 s[4:7], s[0:1], 0x10 ; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v3, 0 @@ -6960,70 +1442,8 @@ define amdgpu_kernel void @v3f32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-PRELOAD-1-NEXT: s_endpgm ; ; GFX940-PRELOAD-2-LABEL: v3f32_preload_arg: -; GFX940-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: ; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v3, 0 ; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s6 @@ -7033,70 +1453,8 @@ define amdgpu_kernel void @v3f32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; ; GFX940-PRELOAD-4-LABEL: v3f32_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 +; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-4-NEXT: ; %bb.0: ; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v3, 0 ; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v0, s6 @@ -7106,70 +1464,8 @@ define amdgpu_kernel void @v3f32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX940-PRELOAD-4-NEXT: s_endpgm ; ; GFX940-PRELOAD-8-LABEL: v3f32_preload_arg: -; GFX940-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: ; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v3, 0 ; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s6 @@ -7191,70 +1487,8 @@ define amdgpu_kernel void @v3f32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; ; GFX90a-PRELOAD-1-LABEL: v3f32_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 +; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-1-NEXT: ; %bb.0: ; GFX90a-PRELOAD-1-NEXT: s_load_dwordx4 s[0:3], s[4:5], 0x10 ; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v3, 0 @@ -7266,70 +1500,8 @@ define amdgpu_kernel void @v3f32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX90a-PRELOAD-1-NEXT: s_endpgm ; ; GFX90a-PRELOAD-2-LABEL: v3f32_preload_arg: -; GFX90a-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: ; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v3, 0 ; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v0, s10 @@ -7339,70 +1511,8 @@ define amdgpu_kernel void @v3f32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; ; GFX90a-PRELOAD-4-LABEL: v3f32_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 +; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-4-NEXT: ; %bb.0: ; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v3, 0 ; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v0, s10 @@ -7412,70 +1522,8 @@ define amdgpu_kernel void @v3f32_preload_arg(ptr addrspace(1) nocapture %out, <3 ; GFX90a-PRELOAD-4-NEXT: s_endpgm ; ; GFX90a-PRELOAD-8-LABEL: v3f32_preload_arg: -; GFX90a-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: ; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v3, 0 ; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s10 @@ -7500,70 +1548,8 @@ define amdgpu_kernel void @v5i8_preload_arg(ptr addrspace(1) nocapture %out, <5 ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; ; GFX940-PRELOAD-1-LABEL: v5i8_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 +; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-1-NEXT: ; %bb.0: ; GFX940-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x8 ; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 @@ -7575,70 +1561,8 @@ define amdgpu_kernel void @v5i8_preload_arg(ptr addrspace(1) nocapture %out, <5 ; GFX940-PRELOAD-1-NEXT: s_endpgm ; ; GFX940-PRELOAD-2-LABEL: v5i8_preload_arg: -; GFX940-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: ; GFX940-PRELOAD-2-NEXT: s_lshr_b32 s0, s4, 8 ; GFX940-PRELOAD-2-NEXT: v_lshlrev_b16_e64 v0, 8, s0 @@ -7655,70 +1579,8 @@ define amdgpu_kernel void @v5i8_preload_arg(ptr addrspace(1) nocapture %out, <5 ; GFX940-PRELOAD-2-NEXT: s_endpgm ; ; GFX940-PRELOAD-4-LABEL: v5i8_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 +; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-4-NEXT: ; %bb.0: ; GFX940-PRELOAD-4-NEXT: s_lshr_b32 s0, s4, 8 ; GFX940-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v0, 8, s0 @@ -7735,70 +1597,8 @@ define amdgpu_kernel void @v5i8_preload_arg(ptr addrspace(1) nocapture %out, <5 ; GFX940-PRELOAD-4-NEXT: s_endpgm ; ; GFX940-PRELOAD-8-LABEL: v5i8_preload_arg: -; GFX940-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: ; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s4, 8 ; GFX940-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v0, 8, s0 @@ -7826,70 +1626,8 @@ define amdgpu_kernel void @v5i8_preload_arg(ptr addrspace(1) nocapture %out, <5 ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; ; GFX90a-PRELOAD-1-LABEL: v5i8_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 +; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-1-NEXT: ; %bb.0: ; GFX90a-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x8 ; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v0, 0 @@ -7901,70 +1639,8 @@ define amdgpu_kernel void @v5i8_preload_arg(ptr addrspace(1) nocapture %out, <5 ; GFX90a-PRELOAD-1-NEXT: s_endpgm ; ; GFX90a-PRELOAD-2-LABEL: v5i8_preload_arg: -; GFX90a-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: ; GFX90a-PRELOAD-2-NEXT: s_lshr_b32 s0, s8, 8 ; GFX90a-PRELOAD-2-NEXT: v_lshlrev_b16_e64 v0, 8, s0 @@ -7981,70 +1657,8 @@ define amdgpu_kernel void @v5i8_preload_arg(ptr addrspace(1) nocapture %out, <5 ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; ; GFX90a-PRELOAD-4-LABEL: v5i8_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 +; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-4-NEXT: ; %bb.0: ; GFX90a-PRELOAD-4-NEXT: s_lshr_b32 s0, s8, 8 ; GFX90a-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v0, 8, s0 @@ -8061,70 +1675,8 @@ define amdgpu_kernel void @v5i8_preload_arg(ptr addrspace(1) nocapture %out, <5 ; GFX90a-PRELOAD-4-NEXT: s_endpgm ; ; GFX90a-PRELOAD-8-LABEL: v5i8_preload_arg: -; GFX90a-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: ; GFX90a-PRELOAD-8-NEXT: s_lshr_b32 s0, s8, 8 ; GFX90a-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v0, 8, s0 @@ -8167,70 +1719,8 @@ define amdgpu_kernel void @v5f64_arg(ptr addrspace(1) nocapture %out, <5 x doubl ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; ; GFX940-PRELOAD-1-LABEL: v5f64_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 +; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-1-NEXT: ; %bb.0: ; GFX940-PRELOAD-1-NEXT: s_load_dwordx2 s[12:13], s[0:1], 0x60 ; GFX940-PRELOAD-1-NEXT: s_load_dwordx8 s[4:11], s[0:1], 0x40 @@ -8252,70 +1742,8 @@ define amdgpu_kernel void @v5f64_arg(ptr addrspace(1) nocapture %out, <5 x doubl ; GFX940-PRELOAD-1-NEXT: s_endpgm ; ; GFX940-PRELOAD-2-LABEL: v5f64_arg: -; GFX940-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: ; GFX940-PRELOAD-2-NEXT: s_load_dwordx2 s[12:13], s[0:1], 0x60 ; GFX940-PRELOAD-2-NEXT: s_load_dwordx8 s[4:11], s[0:1], 0x40 @@ -8337,70 +1765,8 @@ define amdgpu_kernel void @v5f64_arg(ptr addrspace(1) nocapture %out, <5 x doubl ; GFX940-PRELOAD-2-NEXT: s_endpgm ; ; GFX940-PRELOAD-4-LABEL: v5f64_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 +; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-4-NEXT: ; %bb.0: ; GFX940-PRELOAD-4-NEXT: s_load_dwordx2 s[12:13], s[0:1], 0x60 ; GFX940-PRELOAD-4-NEXT: s_load_dwordx8 s[4:11], s[0:1], 0x40 @@ -8422,70 +1788,8 @@ define amdgpu_kernel void @v5f64_arg(ptr addrspace(1) nocapture %out, <5 x doubl ; GFX940-PRELOAD-4-NEXT: s_endpgm ; ; GFX940-PRELOAD-8-LABEL: v5f64_arg: -; GFX940-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: ; GFX940-PRELOAD-8-NEXT: s_load_dwordx2 s[12:13], s[0:1], 0x60 ; GFX940-PRELOAD-8-NEXT: s_load_dwordx8 s[4:11], s[0:1], 0x40 @@ -8529,70 +1833,8 @@ define amdgpu_kernel void @v5f64_arg(ptr addrspace(1) nocapture %out, <5 x doubl ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; ; GFX90a-PRELOAD-1-LABEL: v5f64_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 +; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-1-NEXT: ; %bb.0: ; GFX90a-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x60 ; GFX90a-PRELOAD-1-NEXT: s_load_dwordx8 s[8:15], s[4:5], 0x40 @@ -8614,70 +1856,8 @@ define amdgpu_kernel void @v5f64_arg(ptr addrspace(1) nocapture %out, <5 x doubl ; GFX90a-PRELOAD-1-NEXT: s_endpgm ; ; GFX90a-PRELOAD-2-LABEL: v5f64_arg: -; GFX90a-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: ; GFX90a-PRELOAD-2-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x60 ; GFX90a-PRELOAD-2-NEXT: s_load_dwordx8 s[8:15], s[4:5], 0x40 @@ -8699,70 +1879,8 @@ define amdgpu_kernel void @v5f64_arg(ptr addrspace(1) nocapture %out, <5 x doubl ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; ; GFX90a-PRELOAD-4-LABEL: v5f64_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 +; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-4-NEXT: ; %bb.0: ; GFX90a-PRELOAD-4-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x60 ; GFX90a-PRELOAD-4-NEXT: s_load_dwordx8 s[8:15], s[4:5], 0x40 @@ -8784,82 +1902,20 @@ define amdgpu_kernel void @v5f64_arg(ptr addrspace(1) nocapture %out, <5 x doubl ; GFX90a-PRELOAD-4-NEXT: s_endpgm ; ; GFX90a-PRELOAD-8-LABEL: v5f64_arg: -; GFX90a-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: ; %bb.0: -; GFX90a-PRELOAD-8-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x60 -; GFX90a-PRELOAD-8-NEXT: s_load_dwordx8 s[8:15], s[4:5], 0x40 -; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v4, 0 -; GFX90a-PRELOAD-8-NEXT: s_waitcnt lgkmcnt(0) -; GFX90a-PRELOAD-8-NEXT: v_pk_mov_b32 v[2:3], s[0:1], s[0:1] op_sel:[0,1] -; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s12 -; GFX90a-PRELOAD-8-NEXT: global_store_dwordx2 v4, v[2:3], s[6:7] offset:32 -; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s13 -; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v2, s14 -; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v3, s15 -; GFX90a-PRELOAD-8-NEXT: global_store_dwordx4 v4, v[0:3], s[6:7] offset:16 +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX90a-PRELOAD-8-NEXT: ; %bb.0: +; GFX90a-PRELOAD-8-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x60 +; GFX90a-PRELOAD-8-NEXT: s_load_dwordx8 s[8:15], s[4:5], 0x40 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v4, 0 +; GFX90a-PRELOAD-8-NEXT: s_waitcnt lgkmcnt(0) +; GFX90a-PRELOAD-8-NEXT: v_pk_mov_b32 v[2:3], s[0:1], s[0:1] op_sel:[0,1] +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s12 +; GFX90a-PRELOAD-8-NEXT: global_store_dwordx2 v4, v[2:3], s[6:7] offset:32 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s13 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v2, s14 +; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v3, s15 +; GFX90a-PRELOAD-8-NEXT: global_store_dwordx4 v4, v[0:3], s[6:7] offset:16 ; GFX90a-PRELOAD-8-NEXT: s_nop 0 ; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v0, s8 ; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v1, s9 @@ -8882,70 +1938,8 @@ define amdgpu_kernel void @v8i8_preload_arg(ptr addrspace(1) %out, <8 x i8> %in) ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; ; GFX940-PRELOAD-1-LABEL: v8i8_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 +; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-1-NEXT: ; %bb.0: ; GFX940-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x8 ; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v2, 0 @@ -8955,70 +1949,8 @@ define amdgpu_kernel void @v8i8_preload_arg(ptr addrspace(1) %out, <8 x i8> %in) ; GFX940-PRELOAD-1-NEXT: s_endpgm ; ; GFX940-PRELOAD-2-LABEL: v8i8_preload_arg: -; GFX940-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: ; GFX940-PRELOAD-2-NEXT: s_lshr_b32 s0, s5, 8 ; GFX940-PRELOAD-2-NEXT: v_lshlrev_b16_e64 v0, 8, s0 @@ -9042,70 +1974,8 @@ define amdgpu_kernel void @v8i8_preload_arg(ptr addrspace(1) %out, <8 x i8> %in) ; GFX940-PRELOAD-2-NEXT: s_endpgm ; ; GFX940-PRELOAD-4-LABEL: v8i8_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 +; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-4-NEXT: ; %bb.0: ; GFX940-PRELOAD-4-NEXT: s_lshr_b32 s0, s5, 8 ; GFX940-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v0, 8, s0 @@ -9129,86 +1999,24 @@ define amdgpu_kernel void @v8i8_preload_arg(ptr addrspace(1) %out, <8 x i8> %in) ; GFX940-PRELOAD-4-NEXT: s_endpgm ; ; GFX940-PRELOAD-8-LABEL: v8i8_preload_arg: -; GFX940-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: ; %bb.0: -; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s5, 8 -; GFX940-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v0, 8, s0 -; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s5, 24 -; GFX940-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v1, 8, s0 -; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s5, 16 -; GFX940-PRELOAD-8-NEXT: v_or_b32_sdwa v0, s5, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD -; GFX940-PRELOAD-8-NEXT: v_or_b32_sdwa v1, s0, v1 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD -; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s4, 8 -; GFX940-PRELOAD-8-NEXT: v_or_b32_sdwa v1, v0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD -; GFX940-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v0, 8, s0 -; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s4, 24 -; GFX940-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v2, 8, s0 -; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s4, 16 -; GFX940-PRELOAD-8-NEXT: v_or_b32_sdwa v0, s4, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD -; GFX940-PRELOAD-8-NEXT: v_or_b32_sdwa v2, s0, v2 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 +; GFX940-PRELOAD-8-NEXT: ; %bb.0: +; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s5, 8 +; GFX940-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v0, 8, s0 +; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s5, 24 +; GFX940-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v1, 8, s0 +; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s5, 16 +; GFX940-PRELOAD-8-NEXT: v_or_b32_sdwa v0, s5, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD +; GFX940-PRELOAD-8-NEXT: v_or_b32_sdwa v1, s0, v1 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD +; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s4, 8 +; GFX940-PRELOAD-8-NEXT: v_or_b32_sdwa v1, v0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD +; GFX940-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v0, 8, s0 +; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s4, 24 +; GFX940-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v2, 8, s0 +; GFX940-PRELOAD-8-NEXT: s_lshr_b32 s0, s4, 16 +; GFX940-PRELOAD-8-NEXT: v_or_b32_sdwa v0, s4, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD +; GFX940-PRELOAD-8-NEXT: v_or_b32_sdwa v2, s0, v2 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:DWORD ; GFX940-PRELOAD-8-NEXT: s_nop 0 ; GFX940-PRELOAD-8-NEXT: v_or_b32_sdwa v0, v0, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD ; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v2, 0 @@ -9225,70 +2033,8 @@ define amdgpu_kernel void @v8i8_preload_arg(ptr addrspace(1) %out, <8 x i8> %in) ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; ; GFX90a-PRELOAD-1-LABEL: v8i8_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 +; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-1-NEXT: ; %bb.0: ; GFX90a-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x8 ; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v2, 0 @@ -9298,70 +2044,8 @@ define amdgpu_kernel void @v8i8_preload_arg(ptr addrspace(1) %out, <8 x i8> %in) ; GFX90a-PRELOAD-1-NEXT: s_endpgm ; ; GFX90a-PRELOAD-2-LABEL: v8i8_preload_arg: -; GFX90a-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: ; GFX90a-PRELOAD-2-NEXT: s_lshr_b32 s0, s9, 8 ; GFX90a-PRELOAD-2-NEXT: v_lshlrev_b16_e64 v0, 8, s0 @@ -9384,70 +2068,8 @@ define amdgpu_kernel void @v8i8_preload_arg(ptr addrspace(1) %out, <8 x i8> %in) ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; ; GFX90a-PRELOAD-4-LABEL: v8i8_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 +; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-4-NEXT: ; %bb.0: ; GFX90a-PRELOAD-4-NEXT: s_lshr_b32 s0, s9, 8 ; GFX90a-PRELOAD-4-NEXT: v_lshlrev_b16_e64 v0, 8, s0 @@ -9470,70 +2092,8 @@ define amdgpu_kernel void @v8i8_preload_arg(ptr addrspace(1) %out, <8 x i8> %in) ; GFX90a-PRELOAD-4-NEXT: s_endpgm ; ; GFX90a-PRELOAD-8-LABEL: v8i8_preload_arg: -; GFX90a-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: ; GFX90a-PRELOAD-8-NEXT: s_lshr_b32 s0, s9, 8 ; GFX90a-PRELOAD-8-NEXT: v_lshlrev_b16_e64 v0, 8, s0 @@ -9570,70 +2130,8 @@ define amdgpu_kernel void @i64_kernel_preload_arg(ptr addrspace(1) %out, i64 %a) ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; ; GFX940-PRELOAD-1-LABEL: i64_kernel_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 +; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-1-NEXT: ; %bb.0: ; GFX940-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x8 ; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v2, 0 @@ -9643,70 +2141,8 @@ define amdgpu_kernel void @i64_kernel_preload_arg(ptr addrspace(1) %out, i64 %a) ; GFX940-PRELOAD-1-NEXT: s_endpgm ; ; GFX940-PRELOAD-2-LABEL: i64_kernel_preload_arg: -; GFX940-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: ; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v2, 0 ; GFX940-PRELOAD-2-NEXT: v_mov_b64_e32 v[0:1], s[4:5] @@ -9714,70 +2150,8 @@ define amdgpu_kernel void @i64_kernel_preload_arg(ptr addrspace(1) %out, i64 %a) ; GFX940-PRELOAD-2-NEXT: s_endpgm ; ; GFX940-PRELOAD-4-LABEL: i64_kernel_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 +; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-4-NEXT: ; %bb.0: ; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v2, 0 ; GFX940-PRELOAD-4-NEXT: v_mov_b64_e32 v[0:1], s[4:5] @@ -9785,70 +2159,8 @@ define amdgpu_kernel void @i64_kernel_preload_arg(ptr addrspace(1) %out, i64 %a) ; GFX940-PRELOAD-4-NEXT: s_endpgm ; ; GFX940-PRELOAD-8-LABEL: i64_kernel_preload_arg: -; GFX940-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: ; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v2, 0 ; GFX940-PRELOAD-8-NEXT: v_mov_b64_e32 v[0:1], s[4:5] @@ -9866,70 +2178,8 @@ define amdgpu_kernel void @i64_kernel_preload_arg(ptr addrspace(1) %out, i64 %a) ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; ; GFX90a-PRELOAD-1-LABEL: i64_kernel_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 +; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-1-NEXT: ; %bb.0: ; GFX90a-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x8 ; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v2, 0 @@ -9939,70 +2189,8 @@ define amdgpu_kernel void @i64_kernel_preload_arg(ptr addrspace(1) %out, i64 %a) ; GFX90a-PRELOAD-1-NEXT: s_endpgm ; ; GFX90a-PRELOAD-2-LABEL: i64_kernel_preload_arg: -; GFX90a-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: ; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v2, 0 ; GFX90a-PRELOAD-2-NEXT: v_pk_mov_b32 v[0:1], s[8:9], s[8:9] op_sel:[0,1] @@ -10010,70 +2198,8 @@ define amdgpu_kernel void @i64_kernel_preload_arg(ptr addrspace(1) %out, i64 %a) ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; ; GFX90a-PRELOAD-4-LABEL: i64_kernel_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 +; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-4-NEXT: ; %bb.0: ; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v2, 0 ; GFX90a-PRELOAD-4-NEXT: v_pk_mov_b32 v[0:1], s[8:9], s[8:9] op_sel:[0,1] @@ -10081,70 +2207,8 @@ define amdgpu_kernel void @i64_kernel_preload_arg(ptr addrspace(1) %out, i64 %a) ; GFX90a-PRELOAD-4-NEXT: s_endpgm ; ; GFX90a-PRELOAD-8-LABEL: i64_kernel_preload_arg: -; GFX90a-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: ; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v2, 0 ; GFX90a-PRELOAD-8-NEXT: v_pk_mov_b32 v[0:1], s[8:9], s[8:9] op_sel:[0,1] @@ -10166,70 +2230,8 @@ define amdgpu_kernel void @f64_kernel_preload_arg(ptr addrspace(1) %out, double ; GFX940-NO-PRELOAD-NEXT: s_endpgm ; ; GFX940-PRELOAD-1-LABEL: f64_kernel_preload_arg: -; GFX940-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 -; GFX940-PRELOAD-1-NEXT: s_nop 0 +; GFX940-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-1-NEXT: ; %bb.0: ; GFX940-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[0:1], 0x8 ; GFX940-PRELOAD-1-NEXT: v_mov_b32_e32 v2, 0 @@ -10239,70 +2241,8 @@ define amdgpu_kernel void @f64_kernel_preload_arg(ptr addrspace(1) %out, double ; GFX940-PRELOAD-1-NEXT: s_endpgm ; ; GFX940-PRELOAD-2-LABEL: f64_kernel_preload_arg: -; GFX940-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 -; GFX940-PRELOAD-2-NEXT: s_nop 0 +; GFX940-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-2-NEXT: ; %bb.0: ; GFX940-PRELOAD-2-NEXT: v_mov_b32_e32 v2, 0 ; GFX940-PRELOAD-2-NEXT: v_mov_b64_e32 v[0:1], s[4:5] @@ -10310,70 +2250,8 @@ define amdgpu_kernel void @f64_kernel_preload_arg(ptr addrspace(1) %out, double ; GFX940-PRELOAD-2-NEXT: s_endpgm ; ; GFX940-PRELOAD-4-LABEL: f64_kernel_preload_arg: -; GFX940-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 -; GFX940-PRELOAD-4-NEXT: s_nop 0 +; GFX940-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-4-NEXT: ; %bb.0: ; GFX940-PRELOAD-4-NEXT: v_mov_b32_e32 v2, 0 ; GFX940-PRELOAD-4-NEXT: v_mov_b64_e32 v[0:1], s[4:5] @@ -10381,70 +2259,8 @@ define amdgpu_kernel void @f64_kernel_preload_arg(ptr addrspace(1) %out, double ; GFX940-PRELOAD-4-NEXT: s_endpgm ; ; GFX940-PRELOAD-8-LABEL: f64_kernel_preload_arg: -; GFX940-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 -; GFX940-PRELOAD-8-NEXT: s_nop 0 +; GFX940-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX940-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX940-PRELOAD-8-NEXT: ; %bb.0: ; GFX940-PRELOAD-8-NEXT: v_mov_b32_e32 v2, 0 ; GFX940-PRELOAD-8-NEXT: v_mov_b64_e32 v[0:1], s[4:5] @@ -10462,70 +2278,8 @@ define amdgpu_kernel void @f64_kernel_preload_arg(ptr addrspace(1) %out, double ; GFX90a-NO-PRELOAD-NEXT: s_endpgm ; ; GFX90a-PRELOAD-1-LABEL: f64_kernel_preload_arg: -; GFX90a-PRELOAD-1: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 -; GFX90a-PRELOAD-1-NEXT: s_nop 0 +; GFX90a-PRELOAD-1: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-1-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-1-NEXT: ; %bb.0: ; GFX90a-PRELOAD-1-NEXT: s_load_dwordx2 s[0:1], s[4:5], 0x8 ; GFX90a-PRELOAD-1-NEXT: v_mov_b32_e32 v2, 0 @@ -10535,70 +2289,8 @@ define amdgpu_kernel void @f64_kernel_preload_arg(ptr addrspace(1) %out, double ; GFX90a-PRELOAD-1-NEXT: s_endpgm ; ; GFX90a-PRELOAD-2-LABEL: f64_kernel_preload_arg: -; GFX90a-PRELOAD-2: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 -; GFX90a-PRELOAD-2-NEXT: s_nop 0 +; GFX90a-PRELOAD-2: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-2-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-2-NEXT: ; %bb.0: ; GFX90a-PRELOAD-2-NEXT: v_mov_b32_e32 v2, 0 ; GFX90a-PRELOAD-2-NEXT: v_pk_mov_b32 v[0:1], s[8:9], s[8:9] op_sel:[0,1] @@ -10606,70 +2298,8 @@ define amdgpu_kernel void @f64_kernel_preload_arg(ptr addrspace(1) %out, double ; GFX90a-PRELOAD-2-NEXT: s_endpgm ; ; GFX90a-PRELOAD-4-LABEL: f64_kernel_preload_arg: -; GFX90a-PRELOAD-4: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 -; GFX90a-PRELOAD-4-NEXT: s_nop 0 +; GFX90a-PRELOAD-4: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-4-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-4-NEXT: ; %bb.0: ; GFX90a-PRELOAD-4-NEXT: v_mov_b32_e32 v2, 0 ; GFX90a-PRELOAD-4-NEXT: v_pk_mov_b32 v[0:1], s[8:9], s[8:9] op_sel:[0,1] @@ -10677,70 +2307,8 @@ define amdgpu_kernel void @f64_kernel_preload_arg(ptr addrspace(1) %out, double ; GFX90a-PRELOAD-4-NEXT: s_endpgm ; ; GFX90a-PRELOAD-8-LABEL: f64_kernel_preload_arg: -; GFX90a-PRELOAD-8: s_trap 2 ; Trap with incompatible firmware that doesn't support preloading kernel arguments. -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 -; GFX90a-PRELOAD-8-NEXT: s_nop 0 +; GFX90a-PRELOAD-8: s_trap 2 ; Kernarg preload header. Trap with incompatible firmware that doesn't support preloading kernel arguments. +; GFX90a-PRELOAD-8-NEXT: .fill 63, 4, 0xbf800000 ; s_nop 0 ; GFX90a-PRELOAD-8-NEXT: ; %bb.0: ; GFX90a-PRELOAD-8-NEXT: v_mov_b32_e32 v2, 0 ; GFX90a-PRELOAD-8-NEXT: v_pk_mov_b32 v[0:1], s[8:9], s[8:9] op_sel:[0,1] diff --git a/llvm/test/CodeGen/AMDGPU/promote-alloca-scoring.ll b/llvm/test/CodeGen/AMDGPU/promote-alloca-scoring.ll new file mode 100644 index 0000000000000000000000000000000000000000..ab03177d1edc51c7133e6e72c71f73544046b11a --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/promote-alloca-scoring.ll @@ -0,0 +1,69 @@ +; RUN: opt -S -mtriple=amdgcn-unknown-amdhsa -mcpu=kaveri -debug-only=amdgpu-promote-alloca -amdgpu-promote-alloca-to-vector-limit=512 -passes=amdgpu-promote-alloca %s -o - 2>&1 | FileCheck %s +; REQUIRES: asserts + +; CHECK: Scoring: %simpleuser = alloca [4 x i64], align 4, addrspace(5) +; CHECK-NEXT: [+1]: store i32 42, ptr addrspace(5) %simpleuser, align 4 +; CHECK-NEXT: => Final Score:1 +; CHECK-NEXT: Scoring: %manyusers = alloca [4 x i64], align 4, addrspace(5) +; CHECK-NEXT: [+1]: store i32 %v0.ext, ptr addrspace(5) %manyusers.1, align 4 +; CHECK-NEXT: [+1]: %v0 = load i8, ptr addrspace(5) %manyusers.1, align 1 +; CHECK-NEXT: [+1]: store i32 %v1.ext, ptr addrspace(5) %manyusers.2, align 4 +; CHECK-NEXT: [+1]: %v1 = load i8, ptr addrspace(5) %manyusers.2, align 1 +; CHECK-NEXT: => Final Score:4 +; CHECK-NEXT: Sorted Worklist: +; CHECK-NEXT: %manyusers = alloca [4 x i64], align 4, addrspace(5) +; CHECK-NEXT: %simpleuser = alloca [4 x i64], align 4, addrspace(5) +define amdgpu_kernel void @simple_users_scores() #0 { +entry: + ; should get a score of 1 + %simpleuser = alloca [4 x i64], align 4, addrspace(5) + ; should get a score of 4 + %manyusers = alloca [4 x i64], align 4, addrspace(5) + + store i32 42, ptr addrspace(5) %simpleuser + + %manyusers.1 = getelementptr i8, ptr addrspace(5) %manyusers, i64 2 + %v0 = load i8, ptr addrspace(5) %manyusers.1 + %v0.ext = zext i8 %v0 to i32 + store i32 %v0.ext, ptr addrspace(5) %manyusers.1 + + %manyusers.2 = getelementptr i8, ptr addrspace(5) %manyusers, i64 1 + %v1 = load i8, ptr addrspace(5) %manyusers.2 + %v1.ext = zext i8 %v0 to i32 + store i32 %v1.ext, ptr addrspace(5) %manyusers.2 + + ret void +} + +; CHECK: Scoring: %stack = alloca [4 x i64], align 4, addrspace(5) +; CHECK-NEXT: [+5]: store i32 32, ptr addrspace(5) %stack, align 4 +; CHECK-NEXT: [+1]: store i32 42, ptr addrspace(5) %stack, align 4 +; CHECK-NEXT: [+9]: store i32 32, ptr addrspace(5) %stack.1, align 4 +; CHECK-NEXT: [+5]: %outer.cmp = load i1, ptr addrspace(5) %stack.1, align 1 +; CHECK-NEXT: [+1]: store i32 64, ptr addrspace(5) %stack.2, align 4 +; CHECK-NEXT: [+9]: %inner.cmp = load i1, ptr addrspace(5) %stack.2, align 1 +; CHECK-NEXT: => Final Score:30 +define amdgpu_kernel void @loop_users_alloca(i1 %x, i2) #0 { +entry: + ; should get a score of 1 + %stack = alloca [4 x i64], align 4, addrspace(5) + %stack.1 = getelementptr i8, ptr addrspace(5) %stack, i64 4 + %stack.2 = getelementptr i8, ptr addrspace(5) %stack, i64 8 + + store i32 42, ptr addrspace(5) %stack + br label %loop.outer + +loop.outer: + store i32 32, ptr addrspace(5) %stack + %outer.cmp = load i1, ptr addrspace(5) %stack.1 + br label %loop.inner + +loop.inner: + store i32 32, ptr addrspace(5) %stack.1 + %inner.cmp = load i1, ptr addrspace(5) %stack.2 + br i1 %inner.cmp, label %loop.inner, label %loop.outer + +exit: + store i32 64, ptr addrspace(5) %stack.2 + ret void +} diff --git a/llvm/test/CodeGen/AMDGPU/propagate-flat-work-group-size.ll b/llvm/test/CodeGen/AMDGPU/propagate-flat-work-group-size.ll index d92ba7774bd3a192ea5ec7665a8f99abc3a11a90..d070dc3b770f814a1aa2f9e8f04e63d25d1e1a9b 100644 --- a/llvm/test/CodeGen/AMDGPU/propagate-flat-work-group-size.ll +++ b/llvm/test/CodeGen/AMDGPU/propagate-flat-work-group-size.ll @@ -203,13 +203,13 @@ attributes #5 = { "amdgpu-flat-work-group-size"="128,512" } attributes #6 = { "amdgpu-flat-work-group-size"="512,512" } attributes #7 = { "amdgpu-flat-work-group-size"="64,256" } ;. -; CHECK: attributes #[[ATTR0]] = { "amdgpu-flat-work-group-size"="1,256" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR1]] = { "amdgpu-flat-work-group-size"="64,128" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR2]] = { "amdgpu-flat-work-group-size"="128,512" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="2,10" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR3]] = { "amdgpu-flat-work-group-size"="64,64" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR4]] = { "amdgpu-flat-work-group-size"="128,128" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR5]] = { "amdgpu-flat-work-group-size"="512,512" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="2,10" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR6]] = { "amdgpu-flat-work-group-size"="64,256" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR7]] = { "amdgpu-flat-work-group-size"="128,256" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR8]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR0]] = { "amdgpu-flat-work-group-size"="1,256" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR1]] = { "amdgpu-flat-work-group-size"="64,128" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR2]] = { "amdgpu-flat-work-group-size"="128,512" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="2,10" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR3]] = { "amdgpu-flat-work-group-size"="64,64" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR4]] = { "amdgpu-flat-work-group-size"="128,128" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR5]] = { "amdgpu-flat-work-group-size"="512,512" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="2,10" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR6]] = { "amdgpu-flat-work-group-size"="64,256" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR7]] = { "amdgpu-flat-work-group-size"="128,256" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR8]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } ;. diff --git a/llvm/test/CodeGen/AMDGPU/propagate-waves-per-eu.ll b/llvm/test/CodeGen/AMDGPU/propagate-waves-per-eu.ll index 2df219bd0401e883e63531dec4cdfed8fe0e5567..f62f1d57aec8e45e82f4c25dec22d01a591d02a0 100644 --- a/llvm/test/CodeGen/AMDGPU/propagate-waves-per-eu.ll +++ b/llvm/test/CodeGen/AMDGPU/propagate-waves-per-eu.ll @@ -399,26 +399,26 @@ attributes #17 = { "amdgpu-waves-per-eu"="5,8" } attributes #18 = { "amdgpu-waves-per-eu"="9,10" } attributes #19 = { "amdgpu-waves-per-eu"="8,9" } ;. -; CHECK: attributes #[[ATTR0]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="1,8" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR1]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="1,2" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR2]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="1,4" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR3]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="2,9" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR4]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="1,1" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR5]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="2,2" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR6]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="9,9" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR7]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="2,8" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR8]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="3,8" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR9]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR10]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR11]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="0,8" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR12]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="1,123" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR13]] = { "amdgpu-flat-work-group-size"="1,512" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="2,10" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR14]] = { "amdgpu-flat-work-group-size"="1,512" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="3,6" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR15]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="6,9" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR16]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="6,8" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR17]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="5,5" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR18]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="8,8" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR19]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="9,10" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR20]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="9,9" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR21]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="8,9" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR0]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="1,8" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR1]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="1,2" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR2]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="1,4" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR3]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="2,9" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR4]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="1,1" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR5]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="2,2" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR6]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="9,9" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR7]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="2,8" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR8]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="3,8" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR9]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR10]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR11]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="0,8" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR12]] = { "amdgpu-flat-work-group-size"="1,64" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="1,123" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR13]] = { "amdgpu-flat-work-group-size"="1,512" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="2,10" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR14]] = { "amdgpu-flat-work-group-size"="1,512" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="3,6" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR15]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="6,9" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR16]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="6,8" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR17]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="5,5" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR18]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="8,8" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR19]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="9,10" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR20]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="9,9" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR21]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="8,9" "uniform-work-group-size"="false" } ;. diff --git a/llvm/test/CodeGen/AMDGPU/ran-out-of-sgprs-allocation-failure.mir b/llvm/test/CodeGen/AMDGPU/ran-out-of-sgprs-allocation-failure.mir index 2ccc24152a9f0bbe1a679fe2cfd4e3e719b7d949..fdfc9b043cc9d2c329a94c3173deec5065471ca3 100644 --- a/llvm/test/CodeGen/AMDGPU/ran-out-of-sgprs-allocation-failure.mir +++ b/llvm/test/CodeGen/AMDGPU/ran-out-of-sgprs-allocation-failure.mir @@ -24,6 +24,7 @@ registers: - { id: 10, class: sreg_64_xexec, preferred-register: '$vcc' } frameInfo: maxAlignment: 1 + adjustsStack: true hasCalls: true machineFunctionInfo: maxKernArgAlign: 1 diff --git a/llvm/test/CodeGen/AMDGPU/recursive_global_initializer.ll b/llvm/test/CodeGen/AMDGPU/recursive_global_initializer.ll index eaef63bbfc3c9dc04db4942e77e93a7da62fac2b..c1d647c5d3b907e29b22cd22b1376f711acd3bde 100644 --- a/llvm/test/CodeGen/AMDGPU/recursive_global_initializer.ll +++ b/llvm/test/CodeGen/AMDGPU/recursive_global_initializer.ll @@ -19,5 +19,5 @@ define void @hoge() { ret void } ;. -; CHECK: attributes #[[ATTR0]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR0]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } ;. diff --git a/llvm/test/CodeGen/AMDGPU/remove-no-kernel-id-attribute.ll b/llvm/test/CodeGen/AMDGPU/remove-no-kernel-id-attribute.ll index 297a056526ca4ed97daa94b9474a884de29ec39f..384a9c4043a1d3cfbab0f07712a63411df523b09 100644 --- a/llvm/test/CodeGen/AMDGPU/remove-no-kernel-id-attribute.ll +++ b/llvm/test/CodeGen/AMDGPU/remove-no-kernel-id-attribute.ll @@ -191,11 +191,11 @@ define amdgpu_kernel void @kernel_lds_recursion() { !1 = !{i32 1, !"amdhsa_code_object_version", i32 400} ;. -; CHECK: attributes #[[ATTR0]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR1]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR2]] = { "amdgpu-lds-size"="2" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR0]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR1]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR2]] = { "amdgpu-lds-size"="2" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } ; CHECK: attributes #[[ATTR3]] = { "amdgpu-lds-size"="4" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR4]] = { "amdgpu-lds-size"="2" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR4]] = { "amdgpu-lds-size"="2" "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } ; CHECK: attributes #[[ATTR5:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(none) } ; CHECK: attributes #[[ATTR6:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } ;. diff --git a/llvm/test/CodeGen/AMDGPU/sched-crash-dbg-value.mir b/llvm/test/CodeGen/AMDGPU/sched-crash-dbg-value.mir index c0d199920bd94e0304abef8004198eb9749c9c09..09037709d51d8b94538156aa9815d950d7abd8e4 100644 --- a/llvm/test/CodeGen/AMDGPU/sched-crash-dbg-value.mir +++ b/llvm/test/CodeGen/AMDGPU/sched-crash-dbg-value.mir @@ -181,6 +181,8 @@ legalized: false regBankSelected: false selected: false tracksRegLiveness: true +frameInfo: + adjustsStack: true liveins: - { reg: '$vgpr0', virtual-reg: '%0' } - { reg: '$vgpr1', virtual-reg: '%1' } diff --git a/llvm/test/CodeGen/AMDGPU/sgpr-spill-wrong-stack-id.mir b/llvm/test/CodeGen/AMDGPU/sgpr-spill-wrong-stack-id.mir index efbdbca9da6b7fe628d4392dfafd953af9464ae6..c6ccbd99bf890274b0dc00637fa79dcb76d687c8 100644 --- a/llvm/test/CodeGen/AMDGPU/sgpr-spill-wrong-stack-id.mir +++ b/llvm/test/CodeGen/AMDGPU/sgpr-spill-wrong-stack-id.mir @@ -78,6 +78,7 @@ name: sgpr_spill_wrong_stack_id tracksRegLiveness: true frameInfo: + adjustsStack: true hasCalls: true machineFunctionInfo: scratchRSrcReg: $sgpr0_sgpr1_sgpr2_sgpr3 diff --git a/llvm/test/CodeGen/AMDGPU/sgpr-spills-split-regalloc.ll b/llvm/test/CodeGen/AMDGPU/sgpr-spills-split-regalloc.ll index 764f4942cbd03c2e6e0b4df5028e8dbfcbb1b9d8..f523b4a2495f1980d8455ef68464978ccc736fde 100644 --- a/llvm/test/CodeGen/AMDGPU/sgpr-spills-split-regalloc.ll +++ b/llvm/test/CodeGen/AMDGPU/sgpr-spills-split-regalloc.ll @@ -16,7 +16,7 @@ define void @spill_sgpr_with_no_lower_vgpr_available() #0 { ; GCN-LABEL: spill_sgpr_with_no_lower_vgpr_available: ; GCN: ; %bb.0: ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN-NEXT: s_mov_b32 s24, s33 +; GCN-NEXT: s_mov_b32 s18, s33 ; GCN-NEXT: s_mov_b32 s33, s32 ; GCN-NEXT: s_or_saveexec_b64 s[16:17], -1 ; GCN-NEXT: buffer_store_dword v255, off, s[0:3], s33 offset:448 ; 4-byte Folded Spill @@ -150,7 +150,6 @@ define void @spill_sgpr_with_no_lower_vgpr_available() #0 { ; GCN-NEXT: s_mov_b64 s[20:21], s[0:1] ; GCN-NEXT: s_mov_b64 s[0:1], s[20:21] ; GCN-NEXT: s_mov_b64 s[2:3], s[22:23] -; GCN-NEXT: ; implicit-def: $sgpr18_sgpr19 ; GCN-NEXT: s_waitcnt lgkmcnt(0) ; GCN-NEXT: s_swappc_b64 s[30:31], s[16:17] ; GCN-NEXT: v_readlane_b32 s31, v255, 1 @@ -270,7 +269,7 @@ define void @spill_sgpr_with_no_lower_vgpr_available() #0 { ; GCN-NEXT: buffer_load_dword v255, off, s[0:3], s33 offset:448 ; 4-byte Folded Reload ; GCN-NEXT: s_mov_b64 exec, s[4:5] ; GCN-NEXT: s_add_i32 s32, s32, 0xffff8c00 -; GCN-NEXT: s_mov_b32 s33, s24 +; GCN-NEXT: s_mov_b32 s33, s18 ; GCN-NEXT: s_waitcnt vmcnt(0) ; GCN-NEXT: s_setpc_b64 s[30:31] %alloca = alloca i32, align 4, addrspace(5) @@ -311,7 +310,7 @@ define void @spill_to_lowest_available_vgpr() #0 { ; GCN-LABEL: spill_to_lowest_available_vgpr: ; GCN: ; %bb.0: ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN-NEXT: s_mov_b32 s24, s33 +; GCN-NEXT: s_mov_b32 s18, s33 ; GCN-NEXT: s_mov_b32 s33, s32 ; GCN-NEXT: s_or_saveexec_b64 s[16:17], -1 ; GCN-NEXT: buffer_store_dword v254, off, s[0:3], s33 offset:444 ; 4-byte Folded Spill @@ -444,7 +443,6 @@ define void @spill_to_lowest_available_vgpr() #0 { ; GCN-NEXT: s_mov_b64 s[20:21], s[0:1] ; GCN-NEXT: s_mov_b64 s[0:1], s[20:21] ; GCN-NEXT: s_mov_b64 s[2:3], s[22:23] -; GCN-NEXT: ; implicit-def: $sgpr18_sgpr19 ; GCN-NEXT: s_waitcnt lgkmcnt(0) ; GCN-NEXT: s_swappc_b64 s[30:31], s[16:17] ; GCN-NEXT: v_readlane_b32 s31, v254, 1 @@ -563,7 +561,7 @@ define void @spill_to_lowest_available_vgpr() #0 { ; GCN-NEXT: buffer_load_dword v254, off, s[0:3], s33 offset:444 ; 4-byte Folded Reload ; GCN-NEXT: s_mov_b64 exec, s[4:5] ; GCN-NEXT: s_add_i32 s32, s32, 0xffff8c00 -; GCN-NEXT: s_mov_b32 s33, s24 +; GCN-NEXT: s_mov_b32 s33, s18 ; GCN-NEXT: s_waitcnt vmcnt(0) ; GCN-NEXT: s_setpc_b64 s[30:31] %alloca = alloca i32, align 4, addrspace(5) @@ -1530,7 +1528,7 @@ define void @spill_sgpr_no_free_vgpr_ipra() #0 { ; GCN-LABEL: spill_sgpr_no_free_vgpr_ipra: ; GCN: ; %bb.0: ; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; GCN-NEXT: s_mov_b32 s24, s33 +; GCN-NEXT: s_mov_b32 s18, s33 ; GCN-NEXT: s_mov_b32 s33, s32 ; GCN-NEXT: s_add_i32 s32, s32, 0x7400 ; GCN-NEXT: buffer_store_dword v40, off, s[0:3], s33 offset:444 ; 4-byte Folded Spill @@ -1668,7 +1666,6 @@ define void @spill_sgpr_no_free_vgpr_ipra() #0 { ; GCN-NEXT: s_mov_b64 s[20:21], s[0:1] ; GCN-NEXT: s_mov_b64 s[0:1], s[20:21] ; GCN-NEXT: s_mov_b64 s[2:3], s[22:23] -; GCN-NEXT: ; implicit-def: $sgpr18_sgpr19 ; GCN-NEXT: s_swappc_b64 s[30:31], s[16:17] ; GCN-NEXT: s_mov_b64 s[4:5], exec ; GCN-NEXT: s_mov_b64 exec, 1 @@ -1801,7 +1798,7 @@ define void @spill_sgpr_no_free_vgpr_ipra() #0 { ; GCN-NEXT: buffer_load_dword v41, off, s[0:3], s33 offset:440 ; 4-byte Folded Reload ; GCN-NEXT: buffer_load_dword v40, off, s[0:3], s33 offset:444 ; 4-byte Folded Reload ; GCN-NEXT: s_add_i32 s32, s32, 0xffff8c00 -; GCN-NEXT: s_mov_b32 s33, s24 +; GCN-NEXT: s_mov_b32 s33, s18 ; GCN-NEXT: s_waitcnt vmcnt(0) ; GCN-NEXT: s_setpc_b64 s[30:31] call void @child_function_ipra() diff --git a/llvm/test/CodeGen/AMDGPU/simple-indirect-call.ll b/llvm/test/CodeGen/AMDGPU/simple-indirect-call.ll index f229f33664e1dcf8b2636c723ab4dd2360a1effa..539cfc71a80f934b118ace3f55f3ad6faae96b43 100644 --- a/llvm/test/CodeGen/AMDGPU/simple-indirect-call.ll +++ b/llvm/test/CodeGen/AMDGPU/simple-indirect-call.ll @@ -73,7 +73,7 @@ define amdgpu_kernel void @test_simple_indirect_call() { ;. ; AKF_GCN: attributes #[[ATTR0]] = { "amdgpu-calls" "amdgpu-stack-objects" } ;. -; ATTRIBUTOR_GCN: attributes #[[ATTR0]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; ATTRIBUTOR_GCN: attributes #[[ATTR0]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } ; ATTRIBUTOR_GCN: attributes #[[ATTR1]] = { "uniform-work-group-size"="false" } ;. diff --git a/llvm/test/CodeGen/AMDGPU/snippet-copy-bundle-regression.mir b/llvm/test/CodeGen/AMDGPU/snippet-copy-bundle-regression.mir index 355829825146dfe859f8401647990aa0bfde9d8c..f8ec6bb5d943f72208816fd244183aff352547e7 100644 --- a/llvm/test/CodeGen/AMDGPU/snippet-copy-bundle-regression.mir +++ b/llvm/test/CodeGen/AMDGPU/snippet-copy-bundle-regression.mir @@ -21,6 +21,7 @@ name: kernel tracksRegLiveness: true frameInfo: + adjustsStack: true hasCalls: true machineFunctionInfo: isEntryFunction: true diff --git a/llvm/test/CodeGen/AMDGPU/stacksave_stackrestore.ll b/llvm/test/CodeGen/AMDGPU/stacksave_stackrestore.ll index b8bc01e0b879b5bb82874a001270d7181c602a6f..c6a599094fe431ade1dfcfd8abd2c9ee3adedcb6 100644 --- a/llvm/test/CodeGen/AMDGPU/stacksave_stackrestore.ll +++ b/llvm/test/CodeGen/AMDGPU/stacksave_stackrestore.ll @@ -916,13 +916,13 @@ define amdgpu_kernel void @kernel_stacksave_stackrestore_call_with_stack_objects ; WAVE32-O0-LABEL: kernel_stacksave_stackrestore_call_with_stack_objects: ; WAVE32-O0: ; %bb.0: ; WAVE32-O0-NEXT: s_mov_b32 s32, 0x1200 -; WAVE32-O0-NEXT: s_getpc_b64 s[24:25] -; WAVE32-O0-NEXT: s_mov_b32 s24, s0 -; WAVE32-O0-NEXT: s_load_dwordx4 s[24:27], s[24:25], 0x0 +; WAVE32-O0-NEXT: s_getpc_b64 s[20:21] +; WAVE32-O0-NEXT: s_mov_b32 s20, s0 +; WAVE32-O0-NEXT: s_load_dwordx4 s[20:23], s[20:21], 0x0 ; WAVE32-O0-NEXT: s_waitcnt lgkmcnt(0) -; WAVE32-O0-NEXT: s_bitset0_b32 s27, 21 -; WAVE32-O0-NEXT: s_add_u32 s24, s24, s9 -; WAVE32-O0-NEXT: s_addc_u32 s25, s25, 0 +; WAVE32-O0-NEXT: s_bitset0_b32 s23, 21 +; WAVE32-O0-NEXT: s_add_u32 s20, s20, s9 +; WAVE32-O0-NEXT: s_addc_u32 s21, s21, 0 ; WAVE32-O0-NEXT: ; implicit-def: $vgpr3 : SGPR spill to VGPR lane ; WAVE32-O0-NEXT: s_mov_b32 s14, s8 ; WAVE32-O0-NEXT: s_mov_b32 s13, s7 @@ -934,17 +934,17 @@ define amdgpu_kernel void @kernel_stacksave_stackrestore_call_with_stack_objects ; WAVE32-O0-NEXT: v_writelane_b32 v3, s0, 0 ; WAVE32-O0-NEXT: s_lshr_b32 s0, s0, 5 ; WAVE32-O0-NEXT: v_writelane_b32 v3, s0, 1 -; WAVE32-O0-NEXT: s_or_saveexec_b32 s20, -1 -; WAVE32-O0-NEXT: buffer_store_dword v3, off, s[24:27], 0 offset:128 ; 4-byte Folded Spill -; WAVE32-O0-NEXT: s_mov_b32 exec_lo, s20 +; WAVE32-O0-NEXT: s_or_saveexec_b32 s19, -1 +; WAVE32-O0-NEXT: buffer_store_dword v3, off, s[20:23], 0 offset:128 ; 4-byte Folded Spill +; WAVE32-O0-NEXT: s_mov_b32 exec_lo, s19 ; WAVE32-O0-NEXT: v_mov_b32_e32 v3, 42 -; WAVE32-O0-NEXT: buffer_store_dword v3, off, s[24:27], 0 +; WAVE32-O0-NEXT: buffer_store_dword v3, off, s[20:23], 0 ; WAVE32-O0-NEXT: s_waitcnt_vscnt null, 0x0 -; WAVE32-O0-NEXT: s_mov_b64 s[0:1], s[24:25] -; WAVE32-O0-NEXT: s_mov_b64 s[2:3], s[26:27] +; WAVE32-O0-NEXT: s_mov_b64 s[0:1], s[20:21] +; WAVE32-O0-NEXT: s_mov_b64 s[2:3], s[22:23] ; WAVE32-O0-NEXT: s_mov_b32 s6, s32 ; WAVE32-O0-NEXT: v_mov_b32_e32 v3, 17 -; WAVE32-O0-NEXT: buffer_store_dword v3, off, s[24:27], s6 offset:4 +; WAVE32-O0-NEXT: buffer_store_dword v3, off, s[20:23], s6 offset:4 ; WAVE32-O0-NEXT: s_mov_b32 s6, stack_passed_argument@abs32@hi ; WAVE32-O0-NEXT: s_mov_b32 s16, stack_passed_argument@abs32@lo ; WAVE32-O0-NEXT: ; kill: def $sgpr16 killed $sgpr16 def $sgpr16_sgpr17 @@ -1018,11 +1018,10 @@ define amdgpu_kernel void @kernel_stacksave_stackrestore_call_with_stack_objects ; WAVE32-O0-NEXT: v_mov_b32_e32 v29, s18 ; WAVE32-O0-NEXT: ; implicit-def: $sgpr18 ; WAVE32-O0-NEXT: v_mov_b32_e32 v30, s18 -; WAVE32-O0-NEXT: ; implicit-def: $sgpr18_sgpr19 ; WAVE32-O0-NEXT: s_swappc_b64 s[30:31], s[16:17] -; WAVE32-O0-NEXT: s_or_saveexec_b32 s20, -1 -; WAVE32-O0-NEXT: buffer_load_dword v0, off, s[24:27], 0 offset:128 ; 4-byte Folded Reload -; WAVE32-O0-NEXT: s_mov_b32 exec_lo, s20 +; WAVE32-O0-NEXT: s_or_saveexec_b32 s19, -1 +; WAVE32-O0-NEXT: buffer_load_dword v0, off, s[20:23], 0 offset:128 ; 4-byte Folded Reload +; WAVE32-O0-NEXT: s_mov_b32 exec_lo, s19 ; WAVE32-O0-NEXT: s_waitcnt vmcnt(0) ; WAVE32-O0-NEXT: v_readlane_b32 s1, v0, 1 ; WAVE32-O0-NEXT: v_readlane_b32 s0, v0, 0 @@ -1137,7 +1136,6 @@ define amdgpu_kernel void @kernel_stacksave_stackrestore_call_with_stack_objects ; WAVE64-O0-NEXT: v_mov_b32_e32 v29, s18 ; WAVE64-O0-NEXT: ; implicit-def: $sgpr18 ; WAVE64-O0-NEXT: v_mov_b32_e32 v30, s18 -; WAVE64-O0-NEXT: ; implicit-def: $sgpr18_sgpr19 ; WAVE64-O0-NEXT: s_swappc_b64 s[30:31], s[16:17] ; WAVE64-O0-NEXT: s_or_saveexec_b64 s[20:21], -1 ; WAVE64-O0-NEXT: buffer_load_dword v0, off, s[24:27], 0 offset:128 ; 4-byte Folded Reload @@ -1155,13 +1153,13 @@ define amdgpu_kernel void @kernel_stacksave_stackrestore_call_with_stack_objects ; WAVE32-WWM-PREALLOC-LABEL: kernel_stacksave_stackrestore_call_with_stack_objects: ; WAVE32-WWM-PREALLOC: ; %bb.0: ; WAVE32-WWM-PREALLOC-NEXT: s_mov_b32 s32, 0x1200 -; WAVE32-WWM-PREALLOC-NEXT: s_getpc_b64 s[24:25] -; WAVE32-WWM-PREALLOC-NEXT: s_mov_b32 s24, s0 -; WAVE32-WWM-PREALLOC-NEXT: s_load_dwordx4 s[24:27], s[24:25], 0x0 +; WAVE32-WWM-PREALLOC-NEXT: s_getpc_b64 s[20:21] +; WAVE32-WWM-PREALLOC-NEXT: s_mov_b32 s20, s0 +; WAVE32-WWM-PREALLOC-NEXT: s_load_dwordx4 s[20:23], s[20:21], 0x0 ; WAVE32-WWM-PREALLOC-NEXT: s_waitcnt lgkmcnt(0) -; WAVE32-WWM-PREALLOC-NEXT: s_bitset0_b32 s27, 21 -; WAVE32-WWM-PREALLOC-NEXT: s_add_u32 s24, s24, s9 -; WAVE32-WWM-PREALLOC-NEXT: s_addc_u32 s25, s25, 0 +; WAVE32-WWM-PREALLOC-NEXT: s_bitset0_b32 s23, 21 +; WAVE32-WWM-PREALLOC-NEXT: s_add_u32 s20, s20, s9 +; WAVE32-WWM-PREALLOC-NEXT: s_addc_u32 s21, s21, 0 ; WAVE32-WWM-PREALLOC-NEXT: ; implicit-def: $vgpr32 : SGPR spill to VGPR lane ; WAVE32-WWM-PREALLOC-NEXT: s_mov_b32 s14, s8 ; WAVE32-WWM-PREALLOC-NEXT: s_mov_b32 s13, s7 @@ -1174,13 +1172,13 @@ define amdgpu_kernel void @kernel_stacksave_stackrestore_call_with_stack_objects ; WAVE32-WWM-PREALLOC-NEXT: s_lshr_b32 s0, s0, 5 ; WAVE32-WWM-PREALLOC-NEXT: v_writelane_b32 v32, s0, 1 ; WAVE32-WWM-PREALLOC-NEXT: v_mov_b32_e32 v3, 42 -; WAVE32-WWM-PREALLOC-NEXT: buffer_store_dword v3, off, s[24:27], 0 +; WAVE32-WWM-PREALLOC-NEXT: buffer_store_dword v3, off, s[20:23], 0 ; WAVE32-WWM-PREALLOC-NEXT: s_waitcnt_vscnt null, 0x0 -; WAVE32-WWM-PREALLOC-NEXT: s_mov_b64 s[0:1], s[24:25] -; WAVE32-WWM-PREALLOC-NEXT: s_mov_b64 s[2:3], s[26:27] +; WAVE32-WWM-PREALLOC-NEXT: s_mov_b64 s[0:1], s[20:21] +; WAVE32-WWM-PREALLOC-NEXT: s_mov_b64 s[2:3], s[22:23] ; WAVE32-WWM-PREALLOC-NEXT: s_mov_b32 s6, s32 ; WAVE32-WWM-PREALLOC-NEXT: v_mov_b32_e32 v3, 17 -; WAVE32-WWM-PREALLOC-NEXT: buffer_store_dword v3, off, s[24:27], s6 offset:4 +; WAVE32-WWM-PREALLOC-NEXT: buffer_store_dword v3, off, s[20:23], s6 offset:4 ; WAVE32-WWM-PREALLOC-NEXT: s_mov_b32 s6, stack_passed_argument@abs32@hi ; WAVE32-WWM-PREALLOC-NEXT: s_mov_b32 s16, stack_passed_argument@abs32@lo ; WAVE32-WWM-PREALLOC-NEXT: ; kill: def $sgpr16 killed $sgpr16 def $sgpr16_sgpr17 @@ -1254,7 +1252,6 @@ define amdgpu_kernel void @kernel_stacksave_stackrestore_call_with_stack_objects ; WAVE32-WWM-PREALLOC-NEXT: v_mov_b32_e32 v29, s18 ; WAVE32-WWM-PREALLOC-NEXT: ; implicit-def: $sgpr18 ; WAVE32-WWM-PREALLOC-NEXT: v_mov_b32_e32 v30, s18 -; WAVE32-WWM-PREALLOC-NEXT: ; implicit-def: $sgpr18_sgpr19 ; WAVE32-WWM-PREALLOC-NEXT: s_swappc_b64 s[30:31], s[16:17] ; WAVE32-WWM-PREALLOC-NEXT: v_readlane_b32 s1, v32, 1 ; WAVE32-WWM-PREALLOC-NEXT: v_readlane_b32 s0, v32, 0 @@ -1347,7 +1344,7 @@ define void @func_stacksave_stackrestore_call_with_stack_objects() { ; WAVE32-O0-LABEL: func_stacksave_stackrestore_call_with_stack_objects: ; WAVE32-O0: ; %bb.0: ; WAVE32-O0-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; WAVE32-O0-NEXT: s_mov_b32 s26, s33 +; WAVE32-O0-NEXT: s_mov_b32 s25, s33 ; WAVE32-O0-NEXT: s_mov_b32 s33, s32 ; WAVE32-O0-NEXT: s_xor_saveexec_b32 s16, -1 ; WAVE32-O0-NEXT: buffer_store_dword v32, off, s[0:3], s33 offset:128 ; 4-byte Folded Spill @@ -1361,9 +1358,9 @@ define void @func_stacksave_stackrestore_call_with_stack_objects() { ; WAVE32-O0-NEXT: v_writelane_b32 v0, s16, 0 ; WAVE32-O0-NEXT: s_lshr_b32 s16, s16, 5 ; WAVE32-O0-NEXT: v_writelane_b32 v0, s16, 1 -; WAVE32-O0-NEXT: s_or_saveexec_b32 s25, -1 +; WAVE32-O0-NEXT: s_or_saveexec_b32 s24, -1 ; WAVE32-O0-NEXT: buffer_store_dword v0, off, s[0:3], s33 offset:132 ; 4-byte Folded Spill -; WAVE32-O0-NEXT: s_mov_b32 exec_lo, s25 +; WAVE32-O0-NEXT: s_mov_b32 exec_lo, s24 ; WAVE32-O0-NEXT: v_mov_b32_e32 v0, 42 ; WAVE32-O0-NEXT: buffer_store_dword v0, off, s[0:3], s33 ; WAVE32-O0-NEXT: s_waitcnt_vscnt null, 0x0 @@ -1440,11 +1437,10 @@ define void @func_stacksave_stackrestore_call_with_stack_objects() { ; WAVE32-O0-NEXT: v_mov_b32_e32 v29, s18 ; WAVE32-O0-NEXT: ; implicit-def: $sgpr18 ; WAVE32-O0-NEXT: v_mov_b32_e32 v30, s18 -; WAVE32-O0-NEXT: ; implicit-def: $sgpr18_sgpr19 ; WAVE32-O0-NEXT: s_swappc_b64 s[30:31], s[16:17] -; WAVE32-O0-NEXT: s_or_saveexec_b32 s25, -1 +; WAVE32-O0-NEXT: s_or_saveexec_b32 s24, -1 ; WAVE32-O0-NEXT: buffer_load_dword v0, off, s[0:3], s33 offset:132 ; 4-byte Folded Reload -; WAVE32-O0-NEXT: s_mov_b32 exec_lo, s25 +; WAVE32-O0-NEXT: s_mov_b32 exec_lo, s24 ; WAVE32-O0-NEXT: s_waitcnt vmcnt(0) ; WAVE32-O0-NEXT: v_readlane_b32 s5, v0, 1 ; WAVE32-O0-NEXT: v_readlane_b32 s4, v0, 0 @@ -1460,14 +1456,14 @@ define void @func_stacksave_stackrestore_call_with_stack_objects() { ; WAVE32-O0-NEXT: buffer_load_dword v0, off, s[0:3], s33 offset:136 ; 4-byte Folded Reload ; WAVE32-O0-NEXT: s_mov_b32 exec_lo, s4 ; WAVE32-O0-NEXT: s_add_i32 s32, s32, 0xffffee00 -; WAVE32-O0-NEXT: s_mov_b32 s33, s26 +; WAVE32-O0-NEXT: s_mov_b32 s33, s25 ; WAVE32-O0-NEXT: s_waitcnt vmcnt(0) ; WAVE32-O0-NEXT: s_setpc_b64 s[30:31] ; ; WAVE64-O0-LABEL: func_stacksave_stackrestore_call_with_stack_objects: ; WAVE64-O0: ; %bb.0: ; WAVE64-O0-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; WAVE64-O0-NEXT: s_mov_b32 s28, s33 +; WAVE64-O0-NEXT: s_mov_b32 s19, s33 ; WAVE64-O0-NEXT: s_mov_b32 s33, s32 ; WAVE64-O0-NEXT: s_xor_saveexec_b64 s[16:17], -1 ; WAVE64-O0-NEXT: buffer_store_dword v32, off, s[0:3], s33 offset:128 ; 4-byte Folded Spill @@ -1560,7 +1556,6 @@ define void @func_stacksave_stackrestore_call_with_stack_objects() { ; WAVE64-O0-NEXT: v_mov_b32_e32 v29, s18 ; WAVE64-O0-NEXT: ; implicit-def: $sgpr18 ; WAVE64-O0-NEXT: v_mov_b32_e32 v30, s18 -; WAVE64-O0-NEXT: ; implicit-def: $sgpr18_sgpr19 ; WAVE64-O0-NEXT: s_swappc_b64 s[30:31], s[16:17] ; WAVE64-O0-NEXT: s_or_saveexec_b64 s[26:27], -1 ; WAVE64-O0-NEXT: buffer_load_dword v0, off, s[0:3], s33 offset:132 ; 4-byte Folded Reload @@ -1580,14 +1575,14 @@ define void @func_stacksave_stackrestore_call_with_stack_objects() { ; WAVE64-O0-NEXT: buffer_load_dword v0, off, s[0:3], s33 offset:136 ; 4-byte Folded Reload ; WAVE64-O0-NEXT: s_mov_b64 exec, s[4:5] ; WAVE64-O0-NEXT: s_add_i32 s32, s32, 0xffffdc00 -; WAVE64-O0-NEXT: s_mov_b32 s33, s28 +; WAVE64-O0-NEXT: s_mov_b32 s33, s19 ; WAVE64-O0-NEXT: s_waitcnt vmcnt(0) ; WAVE64-O0-NEXT: s_setpc_b64 s[30:31] ; ; WAVE32-WWM-PREALLOC-LABEL: func_stacksave_stackrestore_call_with_stack_objects: ; WAVE32-WWM-PREALLOC: ; %bb.0: ; WAVE32-WWM-PREALLOC-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) -; WAVE32-WWM-PREALLOC-NEXT: s_mov_b32 s25, s33 +; WAVE32-WWM-PREALLOC-NEXT: s_mov_b32 s24, s33 ; WAVE32-WWM-PREALLOC-NEXT: s_mov_b32 s33, s32 ; WAVE32-WWM-PREALLOC-NEXT: s_xor_saveexec_b32 s16, -1 ; WAVE32-WWM-PREALLOC-NEXT: buffer_store_dword v33, off, s[0:3], s33 offset:128 ; 4-byte Folded Spill @@ -1677,7 +1672,6 @@ define void @func_stacksave_stackrestore_call_with_stack_objects() { ; WAVE32-WWM-PREALLOC-NEXT: v_mov_b32_e32 v29, s18 ; WAVE32-WWM-PREALLOC-NEXT: ; implicit-def: $sgpr18 ; WAVE32-WWM-PREALLOC-NEXT: v_mov_b32_e32 v30, s18 -; WAVE32-WWM-PREALLOC-NEXT: ; implicit-def: $sgpr18_sgpr19 ; WAVE32-WWM-PREALLOC-NEXT: s_swappc_b64 s[30:31], s[16:17] ; WAVE32-WWM-PREALLOC-NEXT: v_readlane_b32 s5, v32, 1 ; WAVE32-WWM-PREALLOC-NEXT: v_readlane_b32 s4, v32, 0 @@ -1693,7 +1687,7 @@ define void @func_stacksave_stackrestore_call_with_stack_objects() { ; WAVE32-WWM-PREALLOC-NEXT: buffer_load_dword v32, off, s[0:3], s33 offset:132 ; 4-byte Folded Reload ; WAVE32-WWM-PREALLOC-NEXT: s_mov_b32 exec_lo, s4 ; WAVE32-WWM-PREALLOC-NEXT: s_add_i32 s32, s32, 0xffffee00 -; WAVE32-WWM-PREALLOC-NEXT: s_mov_b32 s33, s25 +; WAVE32-WWM-PREALLOC-NEXT: s_mov_b32 s33, s24 ; WAVE32-WWM-PREALLOC-NEXT: s_waitcnt vmcnt(0) ; WAVE32-WWM-PREALLOC-NEXT: s_setpc_b64 s[30:31] %alloca = alloca [32 x i32], addrspace(5) diff --git a/llvm/test/CodeGen/AMDGPU/uniform-work-group-attribute-missing.ll b/llvm/test/CodeGen/AMDGPU/uniform-work-group-attribute-missing.ll index 8d5dc7943164f765d7a25fca5988552f8a734bdb..049db01badacf9961931080c2df6dff56d321021 100644 --- a/llvm/test/CodeGen/AMDGPU/uniform-work-group-attribute-missing.ll +++ b/llvm/test/CodeGen/AMDGPU/uniform-work-group-attribute-missing.ll @@ -31,6 +31,6 @@ define amdgpu_kernel void @kernel1() #1 { attributes #0 = { "uniform-work-group-size"="true" } ;. -; CHECK: attributes #[[ATTR0]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR1]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR0]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR1]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } ;. diff --git a/llvm/test/CodeGen/AMDGPU/uniform-work-group-multistep.ll b/llvm/test/CodeGen/AMDGPU/uniform-work-group-multistep.ll index 7a6f82d589e6838b8d861030465a798e17c8b118..c9387f196dff9633ed43b87a7e654d3a623bf4ed 100644 --- a/llvm/test/CodeGen/AMDGPU/uniform-work-group-multistep.ll +++ b/llvm/test/CodeGen/AMDGPU/uniform-work-group-multistep.ll @@ -98,7 +98,7 @@ define amdgpu_kernel void @kernel2() #0 { attributes #0 = { "uniform-work-group-size"="true" } ;. ; CHECK: attributes #[[ATTR0]] = { "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR1]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR1]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } ; CHECK: attributes #[[ATTR2]] = { "uniform-work-group-size"="true" } -; CHECK: attributes #[[ATTR3]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="true" } +; CHECK: attributes #[[ATTR3]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="true" } ;. diff --git a/llvm/test/CodeGen/AMDGPU/uniform-work-group-nested-function-calls.ll b/llvm/test/CodeGen/AMDGPU/uniform-work-group-nested-function-calls.ll index c04154c7c23f2fbbcc9ee2697df9e4684ee461d2..7183da2c5efc36d7b86a4504f92e173a75599284 100644 --- a/llvm/test/CodeGen/AMDGPU/uniform-work-group-nested-function-calls.ll +++ b/llvm/test/CodeGen/AMDGPU/uniform-work-group-nested-function-calls.ll @@ -41,6 +41,6 @@ define amdgpu_kernel void @kernel3() #2 { attributes #2 = { "uniform-work-group-size"="true" } ;. -; CHECK: attributes #[[ATTR0]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR1]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="true" } +; CHECK: attributes #[[ATTR0]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR1]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="true" } ;. diff --git a/llvm/test/CodeGen/AMDGPU/uniform-work-group-prevent-attribute-propagation.ll b/llvm/test/CodeGen/AMDGPU/uniform-work-group-prevent-attribute-propagation.ll index 2d5ff045d12e5a1112da1db6dcb00d38482bb3d2..6ed04cf63d20bedc7943af25cc190f0f3da76ad4 100644 --- a/llvm/test/CodeGen/AMDGPU/uniform-work-group-prevent-attribute-propagation.ll +++ b/llvm/test/CodeGen/AMDGPU/uniform-work-group-prevent-attribute-propagation.ll @@ -41,7 +41,7 @@ define amdgpu_kernel void @kernel2() #2 { attributes #1 = { "uniform-work-group-size"="true" } ;. -; CHECK: attributes #[[ATTR0]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR1]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="true" } -; CHECK: attributes #[[ATTR2]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR0]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR1]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="true" } +; CHECK: attributes #[[ATTR2]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } ;. diff --git a/llvm/test/CodeGen/AMDGPU/uniform-work-group-propagate-attribute.ll b/llvm/test/CodeGen/AMDGPU/uniform-work-group-propagate-attribute.ll index e8bf6fc8321b3af0cedcfa8c120ab6427db8e2a3..d5ba2fd617c6ef97b8b6a55bc21da847bf892248 100644 --- a/llvm/test/CodeGen/AMDGPU/uniform-work-group-propagate-attribute.ll +++ b/llvm/test/CodeGen/AMDGPU/uniform-work-group-propagate-attribute.ll @@ -52,8 +52,8 @@ attributes #0 = { nounwind } attributes #1 = { "uniform-work-group-size"="false" } attributes #2 = { "uniform-work-group-size"="true" } ;. -; CHECK: attributes #[[ATTR0]] = { nounwind "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR1]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR0]] = { nounwind "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR1]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } ; CHECK: attributes #[[ATTR2]] = { nounwind "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } ; CHECK: attributes #[[ATTR3]] = { "uniform-work-group-size"="true" } ;. diff --git a/llvm/test/CodeGen/AMDGPU/uniform-work-group-recursion-test.ll b/llvm/test/CodeGen/AMDGPU/uniform-work-group-recursion-test.ll index 473eea4eedceca8b5a5fe7343d6be679deb489ff..7f0dfeaf75c80859dab25cbcb2cf77b4438f153e 100644 --- a/llvm/test/CodeGen/AMDGPU/uniform-work-group-recursion-test.ll +++ b/llvm/test/CodeGen/AMDGPU/uniform-work-group-recursion-test.ll @@ -101,7 +101,7 @@ define amdgpu_kernel void @kernel(ptr addrspace(1) %m) #1 { attributes #0 = { nounwind readnone } attributes #1 = { "uniform-work-group-size"="true" } ;. -; CHECK: attributes #[[ATTR0]] = { nounwind memory(none) "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR1]] = { nounwind memory(none) "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="true" } -; CHECK: attributes #[[ATTR2]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="true" } +; CHECK: attributes #[[ATTR0]] = { nounwind memory(none) "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR1]] = { nounwind memory(none) "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="true" } +; CHECK: attributes #[[ATTR2]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="true" } ;. diff --git a/llvm/test/CodeGen/AMDGPU/uniform-work-group-test.ll b/llvm/test/CodeGen/AMDGPU/uniform-work-group-test.ll index 221f1a11676fc03126edbb5218d025b4b1deae62..8616c73ad51c130f3760ee4f546c692b12668b7e 100644 --- a/llvm/test/CodeGen/AMDGPU/uniform-work-group-test.ll +++ b/llvm/test/CodeGen/AMDGPU/uniform-work-group-test.ll @@ -61,6 +61,6 @@ define amdgpu_kernel void @kernel3() #0 { attributes #0 = { "uniform-work-group-size"="false" } ;. -; CHECK: attributes #[[ATTR0]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } -; CHECK: attributes #[[ATTR1]] = { "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR0]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "amdgpu-waves-per-eu"="4,10" "uniform-work-group-size"="false" } +; CHECK: attributes #[[ATTR1]] = { "amdgpu-no-agpr" "amdgpu-no-completion-action" "amdgpu-no-default-queue" "amdgpu-no-dispatch-id" "amdgpu-no-dispatch-ptr" "amdgpu-no-heap-ptr" "amdgpu-no-hostcall-ptr" "amdgpu-no-implicitarg-ptr" "amdgpu-no-lds-kernel-id" "amdgpu-no-multigrid-sync-arg" "amdgpu-no-queue-ptr" "amdgpu-no-workgroup-id-x" "amdgpu-no-workgroup-id-y" "amdgpu-no-workgroup-id-z" "amdgpu-no-workitem-id-x" "amdgpu-no-workitem-id-y" "amdgpu-no-workitem-id-z" "uniform-work-group-size"="false" } ;. diff --git a/llvm/test/CodeGen/AMDGPU/vgpr-agpr-limit-gfx90a.ll b/llvm/test/CodeGen/AMDGPU/vgpr-agpr-limit-gfx90a.ll index 717d3d975aaf7c483ec09b56e67d73e845242953..040799435db4a5914edb0870423e477da5538da6 100644 --- a/llvm/test/CodeGen/AMDGPU/vgpr-agpr-limit-gfx90a.ll +++ b/llvm/test/CodeGen/AMDGPU/vgpr-agpr-limit-gfx90a.ll @@ -540,6 +540,7 @@ define internal void @use512vgprs() { } define void @foo() #0 { + call void asm sideeffect "; use $0", "a"(i32 0) ret void } diff --git a/llvm/test/CodeGen/AMDGPU/vgpr-liverange-ir.ll b/llvm/test/CodeGen/AMDGPU/vgpr-liverange-ir.ll index d2364a61ed68622ac894db0b7e0b34edfbca4ae3..bfc249e9081d226c2ff00e890f67485f07701f08 100644 --- a/llvm/test/CodeGen/AMDGPU/vgpr-liverange-ir.ll +++ b/llvm/test/CodeGen/AMDGPU/vgpr-liverange-ir.ll @@ -233,10 +233,10 @@ define amdgpu_ps float @loop(i32 %z, float %v, i32 inreg %bound, ptr %extern_fun ; SI-NEXT: bb.1.Flow: ; SI-NEXT: successors: %bb.2(0x40000000), %bb.10(0x40000000) ; SI-NEXT: {{ $}} - ; SI-NEXT: [[PHI:%[0-9]+]]:vgpr_32 = PHI undef %49:vgpr_32, %bb.0, %4, %bb.9 - ; SI-NEXT: [[PHI1:%[0-9]+]]:vgpr_32 = PHI [[COPY4]], %bb.0, undef %51:vgpr_32, %bb.9 - ; SI-NEXT: [[PHI2:%[0-9]+]]:vgpr_32 = PHI [[COPY3]], %bb.0, undef %53:vgpr_32, %bb.9 - ; SI-NEXT: [[PHI3:%[0-9]+]]:vgpr_32 = PHI [[COPY2]], %bb.0, undef %55:vgpr_32, %bb.9 + ; SI-NEXT: [[PHI:%[0-9]+]]:vgpr_32 = PHI undef %47:vgpr_32, %bb.0, %4, %bb.9 + ; SI-NEXT: [[PHI1:%[0-9]+]]:vgpr_32 = PHI [[COPY4]], %bb.0, undef %49:vgpr_32, %bb.9 + ; SI-NEXT: [[PHI2:%[0-9]+]]:vgpr_32 = PHI [[COPY3]], %bb.0, undef %51:vgpr_32, %bb.9 + ; SI-NEXT: [[PHI3:%[0-9]+]]:vgpr_32 = PHI [[COPY2]], %bb.0, undef %53:vgpr_32, %bb.9 ; SI-NEXT: [[SI_ELSE:%[0-9]+]]:sreg_32 = SI_ELSE killed [[SI_IF]], %bb.10, implicit-def dead $exec, implicit-def dead $scc, implicit $exec ; SI-NEXT: S_BRANCH %bb.2 ; SI-NEXT: {{ $}} @@ -249,8 +249,8 @@ define amdgpu_ps float @loop(i32 %z, float %v, i32 inreg %bound, ptr %extern_fun ; SI-NEXT: bb.3: ; SI-NEXT: successors: %bb.4(0x80000000) ; SI-NEXT: {{ $}} - ; SI-NEXT: [[PHI4:%[0-9]+]]:vreg_64 = PHI undef %57:vreg_64, %bb.4, [[REG_SEQUENCE]], %bb.2 - ; SI-NEXT: [[PHI5:%[0-9]+]]:vgpr_32 = PHI undef %59:vgpr_32, %bb.4, [[PHI1]], %bb.2 + ; SI-NEXT: [[PHI4:%[0-9]+]]:vreg_64 = PHI undef %55:vreg_64, %bb.4, [[REG_SEQUENCE]], %bb.2 + ; SI-NEXT: [[PHI5:%[0-9]+]]:vgpr_32 = PHI undef %57:vgpr_32, %bb.4, [[PHI1]], %bb.2 ; SI-NEXT: [[V_READFIRSTLANE_B32_:%[0-9]+]]:sgpr_32 = V_READFIRSTLANE_B32 [[PHI4]].sub0, implicit $exec ; SI-NEXT: [[V_READFIRSTLANE_B32_1:%[0-9]+]]:sgpr_32 = V_READFIRSTLANE_B32 [[PHI4]].sub1, implicit $exec ; SI-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:sgpr_64 = REG_SEQUENCE killed [[V_READFIRSTLANE_B32_]], %subreg.sub0, killed [[V_READFIRSTLANE_B32_1]], %subreg.sub1 @@ -286,8 +286,8 @@ define amdgpu_ps float @loop(i32 %z, float %v, i32 inreg %bound, ptr %extern_fun ; SI-NEXT: bb.7: ; SI-NEXT: successors: %bb.8(0x80000000) ; SI-NEXT: {{ $}} - ; SI-NEXT: [[PHI6:%[0-9]+]]:vreg_64 = PHI undef %61:vreg_64, %bb.8, [[REG_SEQUENCE2]], %bb.6 - ; SI-NEXT: [[PHI7:%[0-9]+]]:vgpr_32 = PHI undef %63:vgpr_32, %bb.8, [[COPY4]], %bb.6 + ; SI-NEXT: [[PHI6:%[0-9]+]]:vreg_64 = PHI undef %59:vreg_64, %bb.8, [[REG_SEQUENCE2]], %bb.6 + ; SI-NEXT: [[PHI7:%[0-9]+]]:vgpr_32 = PHI undef %61:vgpr_32, %bb.8, [[COPY4]], %bb.6 ; SI-NEXT: [[V_READFIRSTLANE_B32_2:%[0-9]+]]:sgpr_32 = V_READFIRSTLANE_B32 [[PHI6]].sub0, implicit $exec ; SI-NEXT: [[V_READFIRSTLANE_B32_3:%[0-9]+]]:sgpr_32 = V_READFIRSTLANE_B32 [[PHI6]].sub1, implicit $exec ; SI-NEXT: [[REG_SEQUENCE3:%[0-9]+]]:sgpr_64 = REG_SEQUENCE killed [[V_READFIRSTLANE_B32_2]], %subreg.sub0, killed [[V_READFIRSTLANE_B32_3]], %subreg.sub1 @@ -356,9 +356,9 @@ define amdgpu_ps float @loop_with_use(i32 %z, float %v, i32 inreg %bound, ptr %e ; SI-NEXT: bb.1.Flow: ; SI-NEXT: successors: %bb.2(0x40000000), %bb.10(0x40000000) ; SI-NEXT: {{ $}} - ; SI-NEXT: [[PHI:%[0-9]+]]:vgpr_32 = PHI undef %50:vgpr_32, %bb.0, %4, %bb.9 - ; SI-NEXT: [[PHI1:%[0-9]+]]:vgpr_32 = PHI [[COPY3]], %bb.0, undef %52:vgpr_32, %bb.9 - ; SI-NEXT: [[PHI2:%[0-9]+]]:vgpr_32 = PHI [[COPY2]], %bb.0, undef %54:vgpr_32, %bb.9 + ; SI-NEXT: [[PHI:%[0-9]+]]:vgpr_32 = PHI undef %48:vgpr_32, %bb.0, %4, %bb.9 + ; SI-NEXT: [[PHI1:%[0-9]+]]:vgpr_32 = PHI [[COPY3]], %bb.0, undef %50:vgpr_32, %bb.9 + ; SI-NEXT: [[PHI2:%[0-9]+]]:vgpr_32 = PHI [[COPY2]], %bb.0, undef %52:vgpr_32, %bb.9 ; SI-NEXT: [[SI_ELSE:%[0-9]+]]:sreg_32 = SI_ELSE killed [[SI_IF]], %bb.10, implicit-def dead $exec, implicit-def dead $scc, implicit $exec ; SI-NEXT: S_BRANCH %bb.2 ; SI-NEXT: {{ $}} @@ -371,7 +371,7 @@ define amdgpu_ps float @loop_with_use(i32 %z, float %v, i32 inreg %bound, ptr %e ; SI-NEXT: bb.3: ; SI-NEXT: successors: %bb.4(0x80000000) ; SI-NEXT: {{ $}} - ; SI-NEXT: [[PHI3:%[0-9]+]]:vreg_64 = PHI undef %56:vreg_64, %bb.4, [[REG_SEQUENCE]], %bb.2 + ; SI-NEXT: [[PHI3:%[0-9]+]]:vreg_64 = PHI undef %54:vreg_64, %bb.4, [[REG_SEQUENCE]], %bb.2 ; SI-NEXT: [[V_READFIRSTLANE_B32_:%[0-9]+]]:sgpr_32 = V_READFIRSTLANE_B32 [[PHI3]].sub0, implicit $exec ; SI-NEXT: [[V_READFIRSTLANE_B32_1:%[0-9]+]]:sgpr_32 = V_READFIRSTLANE_B32 [[PHI3]].sub1, implicit $exec ; SI-NEXT: [[REG_SEQUENCE1:%[0-9]+]]:sgpr_64 = REG_SEQUENCE killed [[V_READFIRSTLANE_B32_]], %subreg.sub0, killed [[V_READFIRSTLANE_B32_1]], %subreg.sub1 @@ -407,7 +407,7 @@ define amdgpu_ps float @loop_with_use(i32 %z, float %v, i32 inreg %bound, ptr %e ; SI-NEXT: bb.7: ; SI-NEXT: successors: %bb.8(0x80000000) ; SI-NEXT: {{ $}} - ; SI-NEXT: [[PHI4:%[0-9]+]]:vreg_64 = PHI undef %58:vreg_64, %bb.8, [[REG_SEQUENCE2]], %bb.6 + ; SI-NEXT: [[PHI4:%[0-9]+]]:vreg_64 = PHI undef %56:vreg_64, %bb.8, [[REG_SEQUENCE2]], %bb.6 ; SI-NEXT: [[V_READFIRSTLANE_B32_2:%[0-9]+]]:sgpr_32 = V_READFIRSTLANE_B32 [[PHI4]].sub0, implicit $exec ; SI-NEXT: [[V_READFIRSTLANE_B32_3:%[0-9]+]]:sgpr_32 = V_READFIRSTLANE_B32 [[PHI4]].sub1, implicit $exec ; SI-NEXT: [[REG_SEQUENCE3:%[0-9]+]]:sgpr_64 = REG_SEQUENCE killed [[V_READFIRSTLANE_B32_2]], %subreg.sub0, killed [[V_READFIRSTLANE_B32_3]], %subreg.sub1 diff --git a/llvm/test/CodeGen/AMDGPU/vgpr_constant_to_sgpr.ll b/llvm/test/CodeGen/AMDGPU/vgpr_constant_to_sgpr.ll index 37f207fc7a5433181ffd775744e7f278e9ab37f4..4939d52651d96b499d265e55539467b465425c0c 100644 --- a/llvm/test/CodeGen/AMDGPU/vgpr_constant_to_sgpr.ll +++ b/llvm/test/CodeGen/AMDGPU/vgpr_constant_to_sgpr.ll @@ -47,7 +47,6 @@ define protected amdgpu_kernel void @kern(ptr %addr) !llvm.amdgcn.lds.kernel.id ; CHECK-NEXT: s_mov_b32 s15, 42 ; CHECK-NEXT: s_mov_b64 s[0:1], s[20:21] ; CHECK-NEXT: s_mov_b64 s[2:3], s[22:23] -; CHECK-NEXT: ; implicit-def: $sgpr18_sgpr19 ; CHECK-NEXT: s_waitcnt lgkmcnt(0) ; CHECK-NEXT: s_swappc_b64 s[30:31], s[16:17] ; CHECK-NEXT: s_endpgm diff --git a/llvm/test/CodeGen/AMDGPU/virtregrewrite-undef-identity-copy.mir b/llvm/test/CodeGen/AMDGPU/virtregrewrite-undef-identity-copy.mir index 3d9db687ffa15af6c5e086f0bfbc53fa84dec8b1..6659e9532376926d099e2cdd9e380b3bc4951453 100644 --- a/llvm/test/CodeGen/AMDGPU/virtregrewrite-undef-identity-copy.mir +++ b/llvm/test/CodeGen/AMDGPU/virtregrewrite-undef-identity-copy.mir @@ -20,6 +20,7 @@ name: undef_identity_copy tracksRegLiveness: true frameInfo: maxAlignment: 4 + adjustsStack: true hasCalls: true machineFunctionInfo: isEntryFunction: true diff --git a/llvm/test/CodeGen/AMDGPU/wave32.ll b/llvm/test/CodeGen/AMDGPU/wave32.ll index 82816b4564e8687aa6a8db11f6758a2e204ae3f3..901e88a4c6aca82198526225528937b61d55d3c9 100644 --- a/llvm/test/CodeGen/AMDGPU/wave32.ll +++ b/llvm/test/CodeGen/AMDGPU/wave32.ll @@ -2479,8 +2479,7 @@ define amdgpu_kernel void @icmp64(i32 %n, i32 %s) { ; GFX1032-NEXT: v_mul_f32_e32 v1, 0x4f7ffffe, v1 ; GFX1032-NEXT: v_cvt_u32_f32_e32 v1, v1 ; GFX1032-NEXT: v_mul_lo_u32 v2, s1, v1 -; GFX1032-NEXT: s_ff1_i32_b32 s1, 0x80000000 -; GFX1032-NEXT: s_add_i32 s1, s1, 32 +; GFX1032-NEXT: s_brev_b32 s1, 1 ; GFX1032-NEXT: v_mul_hi_u32 v2, v1, v2 ; GFX1032-NEXT: v_add_nc_u32_e32 v1, v1, v2 ; GFX1032-NEXT: v_mul_hi_u32 v1, v0, v1 @@ -2494,8 +2493,7 @@ define amdgpu_kernel void @icmp64(i32 %n, i32 %s) { ; GFX1032-NEXT: v_cndmask_b32_e32 v0, v0, v1, vcc_lo ; GFX1032-NEXT: v_cmp_eq_u32_e32 vcc_lo, 0, v0 ; GFX1032-NEXT: s_lshr_b32 s0, vcc_lo, 1 -; GFX1032-NEXT: s_ff1_i32_b32 s0, s0 -; GFX1032-NEXT: s_min_u32 s0, s0, s1 +; GFX1032-NEXT: s_ff1_i32_b64 s0, s[0:1] ; GFX1032-NEXT: s_cmp_gt_u32 s0, 9 ; GFX1032-NEXT: s_cselect_b32 s0, -1, 0 ; GFX1032-NEXT: s_and_b32 s0, vcc_lo, s0 @@ -2529,10 +2527,7 @@ define amdgpu_kernel void @icmp64(i32 %n, i32 %s) { ; GFX1064-NEXT: v_cmp_eq_u32_e32 vcc, 0, v0 ; GFX1064-NEXT: s_lshr_b64 s[0:1], vcc, 1 ; GFX1064-NEXT: s_bitset1_b32 s1, 31 -; GFX1064-NEXT: s_ff1_i32_b32 s0, s0 -; GFX1064-NEXT: s_ff1_i32_b32 s1, s1 -; GFX1064-NEXT: s_add_i32 s1, s1, 32 -; GFX1064-NEXT: s_min_u32 s0, s0, s1 +; GFX1064-NEXT: s_ff1_i32_b64 s0, s[0:1] ; GFX1064-NEXT: s_cmp_gt_u32 s0, 9 ; GFX1064-NEXT: s_cselect_b64 s[0:1], -1, 0 ; GFX1064-NEXT: s_and_b64 s[0:1], vcc, s[0:1] @@ -2576,9 +2571,8 @@ define amdgpu_kernel void @fcmp64(float %n, float %s) { ; GFX1032-NEXT: s_waitcnt lgkmcnt(0) ; GFX1032-NEXT: v_div_scale_f32 v1, s1, s0, s0, v0 ; GFX1032-NEXT: v_div_scale_f32 v4, vcc_lo, v0, s0, v0 -; GFX1032-NEXT: s_ff1_i32_b32 s1, 0x80000000 +; GFX1032-NEXT: s_brev_b32 s1, 1 ; GFX1032-NEXT: v_rcp_f32_e32 v2, v1 -; GFX1032-NEXT: s_add_i32 s1, s1, 32 ; GFX1032-NEXT: v_fma_f32 v3, -v1, v2, 1.0 ; GFX1032-NEXT: v_fmac_f32_e32 v2, v3, v2 ; GFX1032-NEXT: v_mul_f32_e32 v3, v4, v2 @@ -2592,8 +2586,7 @@ define amdgpu_kernel void @fcmp64(float %n, float %s) { ; GFX1032-NEXT: v_cmp_eq_f32_e32 vcc_lo, 0, v0 ; GFX1032-NEXT: s_lshr_b32 s0, vcc_lo, 1 ; GFX1032-NEXT: v_cmp_nlg_f32_e32 vcc_lo, 0, v0 -; GFX1032-NEXT: s_ff1_i32_b32 s0, s0 -; GFX1032-NEXT: s_min_u32 s0, s0, s1 +; GFX1032-NEXT: s_ff1_i32_b64 s0, s[0:1] ; GFX1032-NEXT: s_cmp_gt_u32 s0, 9 ; GFX1032-NEXT: s_cselect_b32 s0, -1, 0 ; GFX1032-NEXT: s_and_b32 s0, vcc_lo, s0 @@ -2609,15 +2602,15 @@ define amdgpu_kernel void @fcmp64(float %n, float %s) { ; GFX1064-NEXT: v_cvt_f32_u32_e32 v0, v0 ; GFX1064-NEXT: s_waitcnt lgkmcnt(0) ; GFX1064-NEXT: v_div_scale_f32 v1, s[0:1], s2, s2, v0 -; GFX1064-NEXT: v_div_scale_f32 v4, vcc, v0, s2, v0 ; GFX1064-NEXT: v_rcp_f32_e32 v2, v1 ; GFX1064-NEXT: v_fma_f32 v3, -v1, v2, 1.0 ; GFX1064-NEXT: v_fmac_f32_e32 v2, v3, v2 -; GFX1064-NEXT: v_mul_f32_e32 v3, v4, v2 -; GFX1064-NEXT: v_fma_f32 v5, -v1, v3, v4 -; GFX1064-NEXT: v_fmac_f32_e32 v3, v5, v2 -; GFX1064-NEXT: v_fma_f32 v1, -v1, v3, v4 -; GFX1064-NEXT: v_div_fmas_f32 v1, v1, v2, v3 +; GFX1064-NEXT: v_div_scale_f32 v3, vcc, v0, s2, v0 +; GFX1064-NEXT: v_mul_f32_e32 v4, v3, v2 +; GFX1064-NEXT: v_fma_f32 v5, -v1, v4, v3 +; GFX1064-NEXT: v_fmac_f32_e32 v4, v5, v2 +; GFX1064-NEXT: v_fma_f32 v1, -v1, v4, v3 +; GFX1064-NEXT: v_div_fmas_f32 v1, v1, v2, v4 ; GFX1064-NEXT: v_div_fixup_f32 v1, v1, s2, v0 ; GFX1064-NEXT: v_trunc_f32_e32 v1, v1 ; GFX1064-NEXT: v_fma_f32 v0, -v1, s2, v0 @@ -2625,10 +2618,7 @@ define amdgpu_kernel void @fcmp64(float %n, float %s) { ; GFX1064-NEXT: s_lshr_b64 s[0:1], vcc, 1 ; GFX1064-NEXT: v_cmp_nlg_f32_e32 vcc, 0, v0 ; GFX1064-NEXT: s_bitset1_b32 s1, 31 -; GFX1064-NEXT: s_ff1_i32_b32 s0, s0 -; GFX1064-NEXT: s_ff1_i32_b32 s1, s1 -; GFX1064-NEXT: s_add_i32 s1, s1, 32 -; GFX1064-NEXT: s_min_u32 s0, s0, s1 +; GFX1064-NEXT: s_ff1_i32_b64 s0, s[0:1] ; GFX1064-NEXT: s_cmp_gt_u32 s0, 9 ; GFX1064-NEXT: s_cselect_b64 s[0:1], -1, 0 ; GFX1064-NEXT: s_and_b64 s[0:1], vcc, s[0:1] diff --git a/llvm/test/CodeGen/AMDGPU/whole-wave-register-spill.ll b/llvm/test/CodeGen/AMDGPU/whole-wave-register-spill.ll index 3a33194f17c875afc31e9681a185e8ad3f0cc6db..7eabe982ff2bcdec482fa9ebee7f6893db74aaa4 100644 --- a/llvm/test/CodeGen/AMDGPU/whole-wave-register-spill.ll +++ b/llvm/test/CodeGen/AMDGPU/whole-wave-register-spill.ll @@ -101,7 +101,6 @@ define void @test() #0 { ; GCN-O0-NEXT: s_mov_b64 s[20:21], s[0:1] ; GCN-O0-NEXT: s_mov_b64 s[0:1], s[20:21] ; GCN-O0-NEXT: s_mov_b64 s[2:3], s[22:23] -; GCN-O0-NEXT: ; implicit-def: $sgpr18_sgpr19 ; GCN-O0-NEXT: s_waitcnt lgkmcnt(0) ; GCN-O0-NEXT: s_swappc_b64 s[30:31], s[16:17] ; GCN-O0-NEXT: s_or_saveexec_b64 s[28:29], -1 diff --git a/llvm/test/CodeGen/AMDGPU/wwm-reserved-spill.ll b/llvm/test/CodeGen/AMDGPU/wwm-reserved-spill.ll index 11f6a2960776b04aec56ebac736c2b36ba2eae5d..e79cb66dcd7760e79d231911c9ecedf6f04bbc40 100644 --- a/llvm/test/CodeGen/AMDGPU/wwm-reserved-spill.ll +++ b/llvm/test/CodeGen/AMDGPU/wwm-reserved-spill.ll @@ -406,7 +406,6 @@ define amdgpu_gfx void @strict_wwm_call(ptr addrspace(8) inreg %tmp14, i32 inreg ; GFX9-O0-NEXT: s_mov_b64 s[0:1], s[44:45] ; GFX9-O0-NEXT: s_mov_b64 s[2:3], s[46:47] ; GFX9-O0-NEXT: v_mov_b32_e32 v0, v2 -; GFX9-O0-NEXT: ; implicit-def: $sgpr44_sgpr45 ; GFX9-O0-NEXT: s_swappc_b64 s[30:31], s[42:43] ; GFX9-O0-NEXT: v_mov_b32_e32 v1, v0 ; GFX9-O0-NEXT: v_add_u32_e64 v1, v1, v2 @@ -633,7 +632,6 @@ define amdgpu_gfx void @strict_wwm_call_i64(ptr addrspace(8) inreg %tmp14, i64 i ; GFX9-O0-NEXT: s_mov_b64 s[2:3], s[38:39] ; GFX9-O0-NEXT: v_mov_b32_e32 v0, v2 ; GFX9-O0-NEXT: v_mov_b32_e32 v1, v3 -; GFX9-O0-NEXT: ; implicit-def: $sgpr36_sgpr37 ; GFX9-O0-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-O0-NEXT: s_swappc_b64 s[30:31], s[34:35] ; GFX9-O0-NEXT: s_or_saveexec_b64 s[46:47], -1 diff --git a/llvm/test/CodeGen/AMDGPU/wwm-reserved.ll b/llvm/test/CodeGen/AMDGPU/wwm-reserved.ll index e5cebc1c31832cd464d22b8d4acd0cb00a22e785..def51f2b16d3e913045e4428c124042803955d7e 100644 --- a/llvm/test/CodeGen/AMDGPU/wwm-reserved.ll +++ b/llvm/test/CodeGen/AMDGPU/wwm-reserved.ll @@ -413,7 +413,6 @@ define amdgpu_kernel void @call(ptr addrspace(8) inreg %tmp14, i32 inreg %arg) { ; GFX9-O0-NEXT: ; implicit-def: $sgpr15 ; GFX9-O0-NEXT: v_mov_b32_e32 v31, v3 ; GFX9-O0-NEXT: v_mov_b32_e32 v0, v6 -; GFX9-O0-NEXT: ; implicit-def: $sgpr18_sgpr19 ; GFX9-O0-NEXT: s_swappc_b64 s[30:31], s[16:17] ; GFX9-O0-NEXT: s_or_saveexec_b64 s[20:21], -1 ; GFX9-O0-NEXT: buffer_load_dword v1, off, s[24:27], 0 ; 4-byte Folded Reload @@ -657,7 +656,6 @@ define amdgpu_kernel void @call_i64(ptr addrspace(8) inreg %tmp14, i64 inreg %ar ; GFX9-O0-NEXT: v_mov_b32_e32 v31, v3 ; GFX9-O0-NEXT: v_mov_b32_e32 v0, v6 ; GFX9-O0-NEXT: v_mov_b32_e32 v1, v7 -; GFX9-O0-NEXT: ; implicit-def: $sgpr18_sgpr19 ; GFX9-O0-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-O0-NEXT: s_swappc_b64 s[30:31], s[16:17] ; GFX9-O0-NEXT: s_or_saveexec_b64 s[20:21], -1 @@ -1285,7 +1283,6 @@ define amdgpu_kernel void @strict_wwm_call(ptr addrspace(8) inreg %tmp14, i32 in ; GFX9-O0-NEXT: ; implicit-def: $sgpr15 ; GFX9-O0-NEXT: v_mov_b32_e32 v31, v3 ; GFX9-O0-NEXT: v_mov_b32_e32 v0, v6 -; GFX9-O0-NEXT: ; implicit-def: $sgpr18_sgpr19 ; GFX9-O0-NEXT: s_swappc_b64 s[30:31], s[16:17] ; GFX9-O0-NEXT: s_or_saveexec_b64 s[20:21], -1 ; GFX9-O0-NEXT: buffer_load_dword v1, off, s[24:27], 0 ; 4-byte Folded Reload @@ -1529,7 +1526,6 @@ define amdgpu_kernel void @strict_wwm_call_i64(ptr addrspace(8) inreg %tmp14, i6 ; GFX9-O0-NEXT: v_mov_b32_e32 v31, v3 ; GFX9-O0-NEXT: v_mov_b32_e32 v0, v6 ; GFX9-O0-NEXT: v_mov_b32_e32 v1, v7 -; GFX9-O0-NEXT: ; implicit-def: $sgpr18_sgpr19 ; GFX9-O0-NEXT: s_waitcnt lgkmcnt(0) ; GFX9-O0-NEXT: s_swappc_b64 s[30:31], s[16:17] ; GFX9-O0-NEXT: s_or_saveexec_b64 s[20:21], -1 diff --git a/llvm/test/CodeGen/ARM/arm-and-tst-peephole.ll b/llvm/test/CodeGen/ARM/arm-and-tst-peephole.ll index 365727c9dd27d5c2874c97855ee3b5a9efb1b5f0..0795525fba1b3a299b681605c2ea9901163ed4d4 100644 --- a/llvm/test/CodeGen/ARM/arm-and-tst-peephole.ll +++ b/llvm/test/CodeGen/ARM/arm-and-tst-peephole.ll @@ -8,10 +8,8 @@ %struct.Foo = type { ptr } -; ARM-LABEL: foo: -; THUMB-LABEL: foo: -; T2-LABEL: foo: define ptr @foo(ptr %this, i32 %acc) nounwind readonly align 2 { +; ARM-LABEL: foo: ; ARM: @ %bb.0: @ %entry ; ARM-NEXT: add r2, r0, #4 ; ARM-NEXT: mov r12, #1 @@ -44,6 +42,7 @@ define ptr @foo(ptr %this, i32 %acc) nounwind readonly align 2 { ; ARM-NEXT: add r0, r0, r1, lsl #2 ; ARM-NEXT: mov pc, lr ; +; THUMB-LABEL: foo: ; THUMB: @ %bb.0: @ %entry ; THUMB-NEXT: .save {r4, r5, r7, lr} ; THUMB-NEXT: push {r4, r5, r7, lr} @@ -91,6 +90,7 @@ define ptr @foo(ptr %this, i32 %acc) nounwind readonly align 2 { ; THUMB-NEXT: pop {r0} ; THUMB-NEXT: bx r0 ; +; T2-LABEL: foo: ; T2: @ %bb.0: @ %entry ; T2-NEXT: adds r2, r0, #4 ; T2-NEXT: mov.w r12, #1 @@ -125,6 +125,7 @@ define ptr @foo(ptr %this, i32 %acc) nounwind readonly align 2 { ; T2-NEXT: add.w r0, r0, r1, lsl #2 ; T2-NEXT: bx lr ; +; V8-LABEL: foo: ; V8: @ %bb.0: @ %entry ; V8-NEXT: adds r2, r0, #4 ; V8-NEXT: mov.w r12, #1 @@ -210,11 +211,8 @@ sw.epilog: ; preds = %tailrecurse.switch %struct.S = type { ptr, [1 x i8] } -; ARM-LABEL: bar: -; THUMB-LABEL: bar: -; T2-LABEL: bar: -; V8-LABEL: bar: define internal zeroext i8 @bar(ptr %x, ptr nocapture %y) nounwind readonly { +; ARM-LABEL: bar: ; ARM: @ %bb.0: @ %entry ; ARM-NEXT: ldrb r2, [r0, #4] ; ARM-NEXT: ands r2, r2, #112 @@ -230,6 +228,7 @@ define internal zeroext i8 @bar(ptr %x, ptr nocapture %y) nounwind readonly { ; ARM-NEXT: mov r0, #1 ; ARM-NEXT: mov pc, lr ; +; THUMB-LABEL: bar: ; THUMB: @ %bb.0: @ %entry ; THUMB-NEXT: ldrb r2, [r0, #4] ; THUMB-NEXT: movs r3, #112 @@ -253,6 +252,7 @@ define internal zeroext i8 @bar(ptr %x, ptr nocapture %y) nounwind readonly { ; THUMB-NEXT: ands r0, r1 ; THUMB-NEXT: bx lr ; +; T2-LABEL: bar: ; T2: @ %bb.0: @ %entry ; T2-NEXT: ldrb r2, [r0, #4] ; T2-NEXT: ands r2, r2, #112 @@ -270,6 +270,7 @@ define internal zeroext i8 @bar(ptr %x, ptr nocapture %y) nounwind readonly { ; T2-NEXT: movs r0, #1 ; T2-NEXT: bx lr ; +; V8-LABEL: bar: ; V8: @ %bb.0: @ %entry ; V8-NEXT: ldrb r2, [r0, #4] ; V8-NEXT: ands r2, r2, #112 diff --git a/llvm/test/CodeGen/ARM/no-register-coalescing-in-returnsTwice.mir b/llvm/test/CodeGen/ARM/no-register-coalescing-in-returnsTwice.mir index 5c59566247d892a6984e4599e45226fd595eb3f8..b4bbb9be8ae40589f8df367ad65e277a20dc5f6f 100644 --- a/llvm/test/CodeGen/ARM/no-register-coalescing-in-returnsTwice.mir +++ b/llvm/test/CodeGen/ARM/no-register-coalescing-in-returnsTwice.mir @@ -86,6 +86,8 @@ --- name: main exposesReturnsTwice: true +frameInfo: + adjustsStack: true stack: - { id: 0, name: P0, size: 80, alignment: 8, local-offset: -80 } - { id: 1, name: jb1, size: 160, alignment: 8, local-offset: -240 } diff --git a/llvm/test/CodeGen/ARM/select.ll b/llvm/test/CodeGen/ARM/select.ll index 4bb79651f04029e1d485f79b89468879bb66e340..24ca9aeac7f2dbe853edad431911396c5496f0b4 100644 --- a/llvm/test/CodeGen/ARM/select.ll +++ b/llvm/test/CodeGen/ARM/select.ll @@ -1,14 +1,25 @@ -; RUN: llc -mtriple=arm-apple-darwin %s -o - | FileCheck %s - -; RUN: llc -mtriple=arm-eabi -mattr=+vfp2 %s -o - \ -; RUN: | FileCheck %s --check-prefix=CHECK-VFP - -; RUN: llc -mtriple=thumbv7-apple-darwin -mattr=+neon,+thumb2 %s -o - \ -; RUN: | FileCheck %s --check-prefix=CHECK-NEON +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple=armv7-eabi -mattr=-fpregs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-ARM +; RUN: llc -mtriple=armv7-eabi -mattr=+vfp2 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-VFP +; RUN: llc -mtriple=thumbv7-apple-darwin -mattr=+neon,+thumb2 %s -o - | FileCheck %s --check-prefix=CHECK-NEON define i32 @f1(i32 %a.s) { -;CHECK-LABEL: f1: -;CHECK: moveq +; CHECK-LABEL: f1: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: mov r1, #3 +; CHECK-NEXT: cmp r0, #4 +; CHECK-NEXT: movweq r1, #2 +; CHECK-NEXT: mov r0, r1 +; CHECK-NEXT: bx lr +; +; CHECK-NEON-LABEL: f1: +; CHECK-NEON: @ %bb.0: @ %entry +; CHECK-NEON-NEXT: movs r1, #3 +; CHECK-NEON-NEXT: cmp r0, #4 +; CHECK-NEON-NEXT: it eq +; CHECK-NEON-NEXT: moveq r1, #2 +; CHECK-NEON-NEXT: mov r0, r1 +; CHECK-NEON-NEXT: bx lr entry: %tmp = icmp eq i32 %a.s, 4 %tmp1.s = select i1 %tmp, i32 2, i32 3 @@ -16,8 +27,22 @@ entry: } define i32 @f2(i32 %a.s) { -;CHECK-LABEL: f2: -;CHECK: movgt +; CHECK-LABEL: f2: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: mov r1, #3 +; CHECK-NEXT: cmp r0, #4 +; CHECK-NEXT: movwgt r1, #2 +; CHECK-NEXT: mov r0, r1 +; CHECK-NEXT: bx lr +; +; CHECK-NEON-LABEL: f2: +; CHECK-NEON: @ %bb.0: @ %entry +; CHECK-NEON-NEXT: movs r1, #3 +; CHECK-NEON-NEXT: cmp r0, #4 +; CHECK-NEON-NEXT: it gt +; CHECK-NEON-NEXT: movgt r1, #2 +; CHECK-NEON-NEXT: mov r0, r1 +; CHECK-NEON-NEXT: bx lr entry: %tmp = icmp sgt i32 %a.s, 4 %tmp1.s = select i1 %tmp, i32 2, i32 3 @@ -25,8 +50,22 @@ entry: } define i32 @f3(i32 %a.s, i32 %b.s) { -;CHECK-LABEL: f3: -;CHECK: movlt +; CHECK-LABEL: f3: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: mov r2, #3 +; CHECK-NEXT: cmp r0, r1 +; CHECK-NEXT: movwlt r2, #2 +; CHECK-NEXT: mov r0, r2 +; CHECK-NEXT: bx lr +; +; CHECK-NEON-LABEL: f3: +; CHECK-NEON: @ %bb.0: @ %entry +; CHECK-NEON-NEXT: movs r2, #3 +; CHECK-NEON-NEXT: cmp r0, r1 +; CHECK-NEON-NEXT: it lt +; CHECK-NEON-NEXT: movlt r2, #2 +; CHECK-NEON-NEXT: mov r0, r2 +; CHECK-NEON-NEXT: bx lr entry: %tmp = icmp slt i32 %a.s, %b.s %tmp1.s = select i1 %tmp, i32 2, i32 3 @@ -34,8 +73,22 @@ entry: } define i32 @f4(i32 %a.s, i32 %b.s) { -;CHECK-LABEL: f4: -;CHECK: movle +; CHECK-LABEL: f4: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: mov r2, #3 +; CHECK-NEXT: cmp r0, r1 +; CHECK-NEXT: movwle r2, #2 +; CHECK-NEXT: mov r0, r2 +; CHECK-NEXT: bx lr +; +; CHECK-NEON-LABEL: f4: +; CHECK-NEON: @ %bb.0: @ %entry +; CHECK-NEON-NEXT: movs r2, #3 +; CHECK-NEON-NEXT: cmp r0, r1 +; CHECK-NEON-NEXT: it le +; CHECK-NEON-NEXT: movle r2, #2 +; CHECK-NEON-NEXT: mov r0, r2 +; CHECK-NEON-NEXT: bx lr entry: %tmp = icmp sle i32 %a.s, %b.s %tmp1.s = select i1 %tmp, i32 2, i32 3 @@ -43,8 +96,22 @@ entry: } define i32 @f5(i32 %a.u, i32 %b.u) { -;CHECK-LABEL: f5: -;CHECK: movls +; CHECK-LABEL: f5: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: mov r2, #3 +; CHECK-NEXT: cmp r0, r1 +; CHECK-NEXT: movwls r2, #2 +; CHECK-NEXT: mov r0, r2 +; CHECK-NEXT: bx lr +; +; CHECK-NEON-LABEL: f5: +; CHECK-NEON: @ %bb.0: @ %entry +; CHECK-NEON-NEXT: movs r2, #3 +; CHECK-NEON-NEXT: cmp r0, r1 +; CHECK-NEON-NEXT: it ls +; CHECK-NEON-NEXT: movls r2, #2 +; CHECK-NEON-NEXT: mov r0, r2 +; CHECK-NEON-NEXT: bx lr entry: %tmp = icmp ule i32 %a.u, %b.u %tmp1.s = select i1 %tmp, i32 2, i32 3 @@ -52,8 +119,22 @@ entry: } define i32 @f6(i32 %a.u, i32 %b.u) { -;CHECK-LABEL: f6: -;CHECK: movhi +; CHECK-LABEL: f6: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: mov r2, #3 +; CHECK-NEXT: cmp r0, r1 +; CHECK-NEXT: movwhi r2, #2 +; CHECK-NEXT: mov r0, r2 +; CHECK-NEXT: bx lr +; +; CHECK-NEON-LABEL: f6: +; CHECK-NEON: @ %bb.0: @ %entry +; CHECK-NEON-NEXT: movs r2, #3 +; CHECK-NEON-NEXT: cmp r0, r1 +; CHECK-NEON-NEXT: it hi +; CHECK-NEON-NEXT: movhi r2, #2 +; CHECK-NEON-NEXT: mov r0, r2 +; CHECK-NEON-NEXT: bx lr entry: %tmp = icmp ugt i32 %a.u, %b.u %tmp1.s = select i1 %tmp, i32 2, i32 3 @@ -61,11 +142,61 @@ entry: } define double @f7(double %a, double %b) { -;CHECK-LABEL: f7: -;CHECK: movmi -;CHECK: movpl -;CHECK-VFP-LABEL: f7: -;CHECK-VFP: vmovmi +; CHECK-ARM-LABEL: f7: +; CHECK-ARM: @ %bb.0: +; CHECK-ARM-NEXT: .save {r4, r5, r11, lr} +; CHECK-ARM-NEXT: push {r4, r5, r11, lr} +; CHECK-ARM-NEXT: mov r4, r3 +; CHECK-ARM-NEXT: movw r3, #48758 +; CHECK-ARM-NEXT: mov r5, r2 +; CHECK-ARM-NEXT: movw r2, #14680 +; CHECK-ARM-NEXT: movt r2, #51380 +; CHECK-ARM-NEXT: movt r3, #16371 +; CHECK-ARM-NEXT: bl __aeabi_dcmplt +; CHECK-ARM-NEXT: cmp r0, #0 +; CHECK-ARM-NEXT: movwne r4, #0 +; CHECK-ARM-NEXT: movwne r5, #0 +; CHECK-ARM-NEXT: movtne r4, #49136 +; CHECK-ARM-NEXT: mov r0, r5 +; CHECK-ARM-NEXT: mov r1, r4 +; CHECK-ARM-NEXT: pop {r4, r5, r11, pc} +; +; CHECK-VFP-LABEL: f7: +; CHECK-VFP: @ %bb.0: +; CHECK-VFP-NEXT: vldr d17, .LCPI6_0 +; CHECK-VFP-NEXT: vmov d19, r0, r1 +; CHECK-VFP-NEXT: vmov.f64 d16, #-1.000000e+00 +; CHECK-VFP-NEXT: vcmp.f64 d19, d17 +; CHECK-VFP-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-VFP-NEXT: vmov d18, r2, r3 +; CHECK-VFP-NEXT: vmovmi.f64 d18, d16 +; CHECK-VFP-NEXT: vmov r0, r1, d18 +; CHECK-VFP-NEXT: bx lr +; CHECK-VFP-NEXT: .p2align 3 +; CHECK-VFP-NEXT: @ %bb.1: +; CHECK-VFP-NEXT: .LCPI6_0: +; CHECK-VFP-NEXT: .long 3367254360 @ double 1.234 +; CHECK-VFP-NEXT: .long 1072938614 +; +; CHECK-NEON-LABEL: f7: +; CHECK-NEON: @ %bb.0: +; CHECK-NEON-NEXT: vldr d17, LCPI6_0 +; CHECK-NEON-NEXT: vmov d19, r0, r1 +; CHECK-NEON-NEXT: vmov d18, r2, r3 +; CHECK-NEON-NEXT: vcmp.f64 d19, d17 +; CHECK-NEON-NEXT: vmov.f64 d16, #-1.000000e+00 +; CHECK-NEON-NEXT: vmrs APSR_nzcv, fpscr +; CHECK-NEON-NEXT: it mi +; CHECK-NEON-NEXT: vmovmi.f64 d18, d16 +; CHECK-NEON-NEXT: vmov r0, r1, d18 +; CHECK-NEON-NEXT: bx lr +; CHECK-NEON-NEXT: .p2align 3 +; CHECK-NEON-NEXT: @ %bb.1: +; CHECK-NEON-NEXT: .data_region +; CHECK-NEON-NEXT: LCPI6_0: +; CHECK-NEON-NEXT: .long 3367254360 @ double 1.234 +; CHECK-NEON-NEXT: .long 1072938614 +; CHECK-NEON-NEXT: .end_data_region %tmp = fcmp olt double %a, 1.234e+00 %tmp1 = select i1 %tmp, double -1.000e+00, double %b ret double %tmp1 @@ -77,18 +208,49 @@ define double @f7(double %a, double %b) { ; a lack of a custom lowering routine for an ISD::SELECT. This would result in ; two "it" blocks in the code: one for the "icmp" and another to move the index ; into the constant pool based on the value of the "icmp". If we have one "it" -; block generated, odds are good that we have close to the ideal code for this: +; block generated, odds are good that we have close to the ideal code for this. +define arm_apcscc float @f8(i32 %a) nounwind { +; CHECK-ARM-LABEL: f8: +; CHECK-ARM: @ %bb.0: +; CHECK-ARM-NEXT: movw r1, #29905 +; CHECK-ARM-NEXT: movw r2, #1123 +; CHECK-ARM-NEXT: movt r1, #16408 +; CHECK-ARM-NEXT: cmp r0, r2 +; CHECK-ARM-NEXT: movweq r1, #62390 +; CHECK-ARM-NEXT: movteq r1, #16285 +; CHECK-ARM-NEXT: mov r0, r1 +; CHECK-ARM-NEXT: bx lr +; +; CHECK-VFP-LABEL: f8: +; CHECK-VFP: @ %bb.0: +; CHECK-VFP-NEXT: movw r2, #1123 +; CHECK-VFP-NEXT: adr r1, .LCPI7_0 +; CHECK-VFP-NEXT: cmp r0, r2 +; CHECK-VFP-NEXT: addeq r1, r1, #4 +; CHECK-VFP-NEXT: ldr r0, [r1] +; CHECK-VFP-NEXT: bx lr +; CHECK-VFP-NEXT: .p2align 2 +; CHECK-VFP-NEXT: @ %bb.1: +; CHECK-VFP-NEXT: .LCPI7_0: +; CHECK-VFP-NEXT: .long 0x401874d1 @ float 2.38212991 +; CHECK-VFP-NEXT: .long 0x3f9df3b6 @ float 1.23399997 ; ; CHECK-NEON-LABEL: f8: -; CHECK-NEON: adr [[R2:r[0-9]+]], LCPI7_0 -; CHECK-NEON: movw [[R3:r[0-9]+]], #1123 -; CHECK-NEON-NEXT: cmp r0, [[R3]] -; CHECK-NEON-NEXT: it eq -; CHECK-NEON-NEXT: addeq{{.*}} [[R2]], #4 -; CHECK-NEON-NEXT: ldr -; CHECK-NEON: bx - -define arm_apcscc float @f8(i32 %a) nounwind { +; CHECK-NEON: @ %bb.0: +; CHECK-NEON-NEXT: adr r1, LCPI7_0 +; CHECK-NEON-NEXT: movw r2, #1123 +; CHECK-NEON-NEXT: cmp r0, r2 +; CHECK-NEON-NEXT: it eq +; CHECK-NEON-NEXT: addeq r1, #4 +; CHECK-NEON-NEXT: ldr r0, [r1] +; CHECK-NEON-NEXT: bx lr +; CHECK-NEON-NEXT: .p2align 2 +; CHECK-NEON-NEXT: @ %bb.1: +; CHECK-NEON-NEXT: .data_region +; CHECK-NEON-NEXT: LCPI7_0: +; CHECK-NEON-NEXT: .long 0x401874d1 @ float 2.38212991 +; CHECK-NEON-NEXT: .long 0x3f9df3b6 @ float 1.23399997 +; CHECK-NEON-NEXT: .end_data_region %tmp = icmp eq i32 %a, 1123 %tmp1 = select i1 %tmp, float 0x3FF3BE76C0000000, float 0x40030E9A20000000 ret float %tmp1 @@ -98,10 +260,40 @@ define arm_apcscc float @f8(i32 %a) nounwind { ; Glue values can only have a single use, but the following test exposed a ; case where a SELECT was lowered with 2 uses of a comparison, causing the ; scheduler to assert. -; CHECK-VFP-LABEL: f9: - declare ptr @objc_msgSend(ptr, ptr, ...) define void @f9() optsize { +; CHECK-LABEL: f9: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: .save {r11, lr} +; CHECK-NEXT: push {r11, lr} +; CHECK-NEXT: .pad #8 +; CHECK-NEXT: sub sp, sp, #8 +; CHECK-NEXT: movw r2, #0 +; CHECK-NEXT: movw r3, #0 +; CHECK-NEXT: mov r1, #1065353216 +; CHECK-NEXT: mov r0, #0 +; CHECK-NEXT: movt r2, #16672 +; CHECK-NEXT: movt r3, #32704 +; CHECK-NEXT: strd r0, r1, [sp] +; CHECK-NEXT: bl objc_msgSend +; CHECK-NEXT: add sp, sp, #8 +; CHECK-NEXT: pop {r11, pc} +; +; CHECK-NEON-LABEL: f9: +; CHECK-NEON: @ %bb.0: @ %entry +; CHECK-NEON-NEXT: str lr, [sp, #-4]! +; CHECK-NEON-NEXT: sub sp, #8 +; CHECK-NEON-NEXT: movs r2, #0 +; CHECK-NEON-NEXT: movs r3, #0 +; CHECK-NEON-NEXT: mov.w r0, #1065353216 +; CHECK-NEON-NEXT: movs r1, #0 +; CHECK-NEON-NEXT: movt r2, #16672 +; CHECK-NEON-NEXT: movt r3, #32704 +; CHECK-NEON-NEXT: strd r1, r0, [sp] +; CHECK-NEON-NEXT: bl _objc_msgSend +; CHECK-NEON-NEXT: add sp, #8 +; CHECK-NEON-NEXT: ldr lr, [sp], #4 +; CHECK-NEON-NEXT: bx lr entry: %cmp = icmp eq ptr undef, inttoptr (i32 4 to ptr) %conv191 = select i1 %cmp, float -3.000000e+00, float 0.000000e+00 @@ -117,36 +309,151 @@ entry: ret void } -; CHECK-LABEL: f10: define float @f10(i32 %a, i32 %b) nounwind uwtable readnone ssp { -; CHECK-NOT: floatsisf +; CHECK-ARM-LABEL: f10: +; CHECK-ARM: @ %bb.0: +; CHECK-ARM-NEXT: mov r2, #0 +; CHECK-ARM-NEXT: cmp r0, r1 +; CHECK-ARM-NEXT: moveq r2, #1065353216 +; CHECK-ARM-NEXT: mov r0, r2 +; CHECK-ARM-NEXT: bx lr +; +; CHECK-VFP-LABEL: f10: +; CHECK-VFP: @ %bb.0: +; CHECK-VFP-NEXT: vmov.f32 s2, #1.000000e+00 +; CHECK-VFP-NEXT: vldr s0, .LCPI9_0 +; CHECK-VFP-NEXT: cmp r0, r1 +; CHECK-VFP-NEXT: vmoveq.f32 s0, s2 +; CHECK-VFP-NEXT: vmov r0, s0 +; CHECK-VFP-NEXT: bx lr +; CHECK-VFP-NEXT: .p2align 2 +; CHECK-VFP-NEXT: @ %bb.1: +; CHECK-VFP-NEXT: .LCPI9_0: +; CHECK-VFP-NEXT: .long 0x00000000 @ float 0 +; +; CHECK-NEON-LABEL: f10: +; CHECK-NEON: @ %bb.0: +; CHECK-NEON-NEXT: vldr s0, LCPI9_0 +; CHECK-NEON-NEXT: vmov.f32 s2, #1.000000e+00 +; CHECK-NEON-NEXT: cmp r0, r1 +; CHECK-NEON-NEXT: it eq +; CHECK-NEON-NEXT: vmoveq.f32 s0, s2 +; CHECK-NEON-NEXT: vmov r0, s0 +; CHECK-NEON-NEXT: bx lr +; CHECK-NEON-NEXT: .p2align 2 +; CHECK-NEON-NEXT: @ %bb.1: +; CHECK-NEON-NEXT: .data_region +; CHECK-NEON-NEXT: LCPI9_0: +; CHECK-NEON-NEXT: .long 0x00000000 @ float 0 +; CHECK-NEON-NEXT: .end_data_region %1 = icmp eq i32 %a, %b %2 = zext i1 %1 to i32 %3 = sitofp i32 %2 to float ret float %3 } -; CHECK-LABEL: f11: define float @f11(i32 %a, i32 %b) nounwind uwtable readnone ssp { -; CHECK-NOT: floatsisf +; CHECK-ARM-LABEL: f11: +; CHECK-ARM: @ %bb.0: +; CHECK-ARM-NEXT: mov r2, #0 +; CHECK-ARM-NEXT: cmp r0, r1 +; CHECK-ARM-NEXT: movweq r2, #0 +; CHECK-ARM-NEXT: movteq r2, #49024 +; CHECK-ARM-NEXT: mov r0, r2 +; CHECK-ARM-NEXT: bx lr +; +; CHECK-VFP-LABEL: f11: +; CHECK-VFP: @ %bb.0: +; CHECK-VFP-NEXT: vmov.f32 s2, #-1.000000e+00 +; CHECK-VFP-NEXT: vldr s0, .LCPI10_0 +; CHECK-VFP-NEXT: cmp r0, r1 +; CHECK-VFP-NEXT: vmoveq.f32 s0, s2 +; CHECK-VFP-NEXT: vmov r0, s0 +; CHECK-VFP-NEXT: bx lr +; CHECK-VFP-NEXT: .p2align 2 +; CHECK-VFP-NEXT: @ %bb.1: +; CHECK-VFP-NEXT: .LCPI10_0: +; CHECK-VFP-NEXT: .long 0x00000000 @ float 0 +; +; CHECK-NEON-LABEL: f11: +; CHECK-NEON: @ %bb.0: +; CHECK-NEON-NEXT: vldr s0, LCPI10_0 +; CHECK-NEON-NEXT: vmov.f32 s2, #-1.000000e+00 +; CHECK-NEON-NEXT: cmp r0, r1 +; CHECK-NEON-NEXT: it eq +; CHECK-NEON-NEXT: vmoveq.f32 s0, s2 +; CHECK-NEON-NEXT: vmov r0, s0 +; CHECK-NEON-NEXT: bx lr +; CHECK-NEON-NEXT: .p2align 2 +; CHECK-NEON-NEXT: @ %bb.1: +; CHECK-NEON-NEXT: .data_region +; CHECK-NEON-NEXT: LCPI10_0: +; CHECK-NEON-NEXT: .long 0x00000000 @ float 0 +; CHECK-NEON-NEXT: .end_data_region %1 = icmp eq i32 %a, %b %2 = sitofp i1 %1 to float ret float %2 } -; CHECK-LABEL: f12: define float @f12(i32 %a, i32 %b) nounwind uwtable readnone ssp { -; CHECK-NOT: floatunsisf +; CHECK-ARM-LABEL: f12: +; CHECK-ARM: @ %bb.0: +; CHECK-ARM-NEXT: mov r2, #0 +; CHECK-ARM-NEXT: cmp r0, r1 +; CHECK-ARM-NEXT: moveq r2, #1065353216 +; CHECK-ARM-NEXT: mov r0, r2 +; CHECK-ARM-NEXT: bx lr +; +; CHECK-VFP-LABEL: f12: +; CHECK-VFP: @ %bb.0: +; CHECK-VFP-NEXT: vmov.f32 s2, #1.000000e+00 +; CHECK-VFP-NEXT: vldr s0, .LCPI11_0 +; CHECK-VFP-NEXT: cmp r0, r1 +; CHECK-VFP-NEXT: vmoveq.f32 s0, s2 +; CHECK-VFP-NEXT: vmov r0, s0 +; CHECK-VFP-NEXT: bx lr +; CHECK-VFP-NEXT: .p2align 2 +; CHECK-VFP-NEXT: @ %bb.1: +; CHECK-VFP-NEXT: .LCPI11_0: +; CHECK-VFP-NEXT: .long 0x00000000 @ float 0 +; +; CHECK-NEON-LABEL: f12: +; CHECK-NEON: @ %bb.0: +; CHECK-NEON-NEXT: vldr s0, LCPI11_0 +; CHECK-NEON-NEXT: vmov.f32 s2, #1.000000e+00 +; CHECK-NEON-NEXT: cmp r0, r1 +; CHECK-NEON-NEXT: it eq +; CHECK-NEON-NEXT: vmoveq.f32 s0, s2 +; CHECK-NEON-NEXT: vmov r0, s0 +; CHECK-NEON-NEXT: bx lr +; CHECK-NEON-NEXT: .p2align 2 +; CHECK-NEON-NEXT: @ %bb.1: +; CHECK-NEON-NEXT: .data_region +; CHECK-NEON-NEXT: LCPI11_0: +; CHECK-NEON-NEXT: .long 0x00000000 @ float 0 +; CHECK-NEON-NEXT: .end_data_region %1 = icmp eq i32 %a, %b %2 = uitofp i1 %1 to float ret float %2 } -; CHECK-LABEL: test_overflow_recombine: define i1 @test_overflow_recombine(i32 %in1, i32 %in2) { -; CHECK: smull [[LO:r[0-9]+]], [[HI:r[0-9]+]] -; CHECK: subs [[ZERO:r[0-9]+]], [[HI]], [[LO]], asr #31 -; CHECK: movne [[ZERO]], #1 +; CHECK-LABEL: test_overflow_recombine: +; CHECK: @ %bb.0: +; CHECK-NEXT: mul r2, r0, r1 +; CHECK-NEXT: smmul r0, r0, r1 +; CHECK-NEXT: subs r0, r0, r2, asr #31 +; CHECK-NEXT: movwne r0, #1 +; CHECK-NEXT: bx lr +; +; CHECK-NEON-LABEL: test_overflow_recombine: +; CHECK-NEON: @ %bb.0: +; CHECK-NEON-NEXT: mul r2, r0, r1 +; CHECK-NEON-NEXT: smmul r0, r0, r1 +; CHECK-NEON-NEXT: subs.w r0, r0, r2, asr #31 +; CHECK-NEON-NEXT: it ne +; CHECK-NEON-NEXT: movne r0, #1 +; CHECK-NEON-NEXT: bx lr %prod = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %in1, i32 %in2) %overflow = extractvalue { i32, i1 } %prod, 1 ret i1 %overflow diff --git a/llvm/test/CodeGen/AVR/bug-81911.ll b/llvm/test/CodeGen/AVR/bug-81911.ll new file mode 100644 index 0000000000000000000000000000000000000000..2a22666a1ff927673e4bee1b148231b1144d7b60 --- /dev/null +++ b/llvm/test/CodeGen/AVR/bug-81911.ll @@ -0,0 +1,163 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=avr -mcpu=atmega328 -O1 -verify-machineinstrs | FileCheck %s + +define internal i8 @main() { +; CHECK-LABEL: main: +; CHECK: ; %bb.0: ; %bb0 +; CHECK-NEXT: push r2 +; CHECK-NEXT: push r3 +; CHECK-NEXT: push r4 +; CHECK-NEXT: push r5 +; CHECK-NEXT: push r6 +; CHECK-NEXT: push r7 +; CHECK-NEXT: push r8 +; CHECK-NEXT: push r9 +; CHECK-NEXT: push r10 +; CHECK-NEXT: push r11 +; CHECK-NEXT: push r12 +; CHECK-NEXT: push r13 +; CHECK-NEXT: push r14 +; CHECK-NEXT: push r15 +; CHECK-NEXT: push r16 +; CHECK-NEXT: push r17 +; CHECK-NEXT: push r28 +; CHECK-NEXT: push r29 +; CHECK-NEXT: in r28, 61 +; CHECK-NEXT: in r29, 62 +; CHECK-NEXT: sbiw r28, 13 +; CHECK-NEXT: in r0, 63 +; CHECK-NEXT: cli +; CHECK-NEXT: out 62, r29 +; CHECK-NEXT: out 63, r0 +; CHECK-NEXT: out 61, r28 +; CHECK-NEXT: ldi r16, 0 +; CHECK-NEXT: ldi r17, 0 +; CHECK-NEXT: ldi r18, -1 +; CHECK-NEXT: ;APP +; CHECK-NEXT: ldi r24, 123 +; CHECK-NEXT: ;NO_APP +; CHECK-NEXT: std Y+1, r24 ; 1-byte Folded Spill +; CHECK-NEXT: movw r24, r28 +; CHECK-NEXT: adiw r24, 6 +; CHECK-NEXT: std Y+3, r25 ; 2-byte Folded Spill +; CHECK-NEXT: std Y+2, r24 ; 2-byte Folded Spill +; CHECK-NEXT: movw r8, r16 +; CHECK-NEXT: movw r6, r16 +; CHECK-NEXT: movw r4, r16 +; CHECK-NEXT: movw r2, r16 +; CHECK-NEXT: rjmp .LBB0_2 +; CHECK-NEXT: .LBB0_1: ; %bb1 +; CHECK-NEXT: ; in Loop: Header=BB0_2 Depth=1 +; CHECK-NEXT: andi r30, 1 +; CHECK-NEXT: ldd r31, Y+4 ; 1-byte Folded Reload +; CHECK-NEXT: dec r31 +; CHECK-NEXT: cpi r30, 0 +; CHECK-NEXT: movw r8, r18 +; CHECK-NEXT: movw r6, r20 +; CHECK-NEXT: movw r4, r22 +; CHECK-NEXT: movw r2, r24 +; CHECK-NEXT: mov r18, r31 +; CHECK-NEXT: brne .LBB0_2 +; CHECK-NEXT: rjmp .LBB0_4 +; CHECK-NEXT: .LBB0_2: ; %bb1 +; CHECK-NEXT: ; =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: std Y+4, r18 ; 1-byte Folded Spill +; CHECK-NEXT: movw r18, r8 +; CHECK-NEXT: movw r20, r6 +; CHECK-NEXT: movw r22, r4 +; CHECK-NEXT: movw r24, r2 +; CHECK-NEXT: ldi r26, 10 +; CHECK-NEXT: ldi r27, 0 +; CHECK-NEXT: movw r10, r26 +; CHECK-NEXT: movw r12, r16 +; CHECK-NEXT: movw r14, r16 +; CHECK-NEXT: call __udivdi3 +; CHECK-NEXT: std Y+13, r25 +; CHECK-NEXT: std Y+12, r24 +; CHECK-NEXT: std Y+11, r23 +; CHECK-NEXT: std Y+10, r22 +; CHECK-NEXT: std Y+9, r21 +; CHECK-NEXT: std Y+8, r20 +; CHECK-NEXT: std Y+7, r19 +; CHECK-NEXT: std Y+6, r18 +; CHECK-NEXT: ldd r30, Y+2 ; 2-byte Folded Reload +; CHECK-NEXT: ldd r31, Y+3 ; 2-byte Folded Reload +; CHECK-NEXT: ;APP +; CHECK-NEXT: ;NO_APP +; CHECK-NEXT: ldi r30, 1 +; CHECK-NEXT: cp r8, r1 +; CHECK-NEXT: cpc r9, r1 +; CHECK-NEXT: cpc r6, r16 +; CHECK-NEXT: cpc r7, r17 +; CHECK-NEXT: cpc r4, r16 +; CHECK-NEXT: cpc r5, r17 +; CHECK-NEXT: cpc r2, r16 +; CHECK-NEXT: cpc r3, r17 +; CHECK-NEXT: breq .LBB0_3 +; CHECK-NEXT: rjmp .LBB0_1 +; CHECK-NEXT: .LBB0_3: ; %bb1 +; CHECK-NEXT: ; in Loop: Header=BB0_2 Depth=1 +; CHECK-NEXT: mov r30, r1 +; CHECK-NEXT: rjmp .LBB0_1 +; CHECK-NEXT: .LBB0_4: ; %bb3 +; CHECK-NEXT: ldd r24, Y+1 ; 1-byte Folded Reload +; CHECK-NEXT: std Y+5, r24 +; CHECK-NEXT: movw r24, r28 +; CHECK-NEXT: adiw r24, 5 +; CHECK-NEXT: ;APP +; CHECK-NEXT: ;NO_APP +; CHECK-NEXT: ldd r24, Y+5 +; CHECK-NEXT: adiw r28, 13 +; CHECK-NEXT: in r0, 63 +; CHECK-NEXT: cli +; CHECK-NEXT: out 62, r29 +; CHECK-NEXT: out 63, r0 +; CHECK-NEXT: out 61, r28 +; CHECK-NEXT: pop r29 +; CHECK-NEXT: pop r28 +; CHECK-NEXT: pop r17 +; CHECK-NEXT: pop r16 +; CHECK-NEXT: pop r15 +; CHECK-NEXT: pop r14 +; CHECK-NEXT: pop r13 +; CHECK-NEXT: pop r12 +; CHECK-NEXT: pop r11 +; CHECK-NEXT: pop r10 +; CHECK-NEXT: pop r9 +; CHECK-NEXT: pop r8 +; CHECK-NEXT: pop r7 +; CHECK-NEXT: pop r6 +; CHECK-NEXT: pop r5 +; CHECK-NEXT: pop r4 +; CHECK-NEXT: pop r3 +; CHECK-NEXT: pop r2 +; CHECK-NEXT: ret +bb0: + %0 = alloca i64 + %1 = alloca i8 + %2 = tail call i8 asm sideeffect "ldi ${0}, 123", "=&r,~{sreg},~{memory}"() + + br label %bb1 + +bb1: + %3 = phi i64 [ %5, %bb1 ], [ 0, %bb0 ] + %4 = phi i8 [ %6, %bb1 ], [ 0, %bb0 ] + %5 = udiv i64 %3, 10 + %6 = add i8 %4, 1 + + store i64 %5, ptr %0 + call void asm sideeffect "", "r,~{memory}"(ptr %0) + + %7 = icmp eq i64 %3, 0 + %8 = icmp eq i8 %6, 0 + + br i1 %7, label %bb3, label %bb1 + +bb3: + store i8 %2, ptr %1 + call void asm sideeffect "", "r,~{memory}"(ptr %1) + + %9 = load i8, ptr %1 + + ret i8 %9 +} diff --git a/llvm/test/CodeGen/BPF/addr-space-globals.ll b/llvm/test/CodeGen/BPF/addr-space-globals.ll index 878ba0dfce6cd17803ff469a6ab3eaa24194914c..73e80b7a0400b352cf597d323b4754ebe6a72d7c 100644 --- a/llvm/test/CodeGen/BPF/addr-space-globals.ll +++ b/llvm/test/CodeGen/BPF/addr-space-globals.ll @@ -18,7 +18,7 @@ ; Verify that a,b,c reside in the same section -; CHECK: .section .arena.272,"aw",@progbits +; CHECK: .section .addr_space.272,"aw",@progbits ; CHECK-NOT: .section ; CHECK: .globl a ; CHECK: .ascii "\001\002" diff --git a/llvm/test/CodeGen/BPF/addr-space-globals2.ll b/llvm/test/CodeGen/BPF/addr-space-globals2.ll index d1e2318948751e38a030a009dda7680a006db931..5944cb27ee18a87263b1c5d3c295626fe4d71ede 100644 --- a/llvm/test/CodeGen/BPF/addr-space-globals2.ll +++ b/llvm/test/CodeGen/BPF/addr-space-globals2.ll @@ -14,12 +14,12 @@ ; Verify that a,b reside in separate sections -; CHECK: .section .arena.1,"aw",@progbits +; CHECK: .section .addr_space.1,"aw",@progbits ; CHECK-NOT: .section ; CHECK: .globl a ; CHECK: .ascii "\001\002" -; CHECK: .section .arena.2,"aw",@progbits +; CHECK: .section .addr_space.2,"aw",@progbits ; CHECK-NOT: .section ; CHECK: .globl b ; CHECK: .ascii "\003\004" diff --git a/llvm/test/CodeGen/BPF/cttz-ctlz.ll b/llvm/test/CodeGen/BPF/cttz-ctlz.ll new file mode 100644 index 0000000000000000000000000000000000000000..f42b2e2d10871bb2114c18588f3d6378f5a0339e --- /dev/null +++ b/llvm/test/CodeGen/BPF/cttz-ctlz.ll @@ -0,0 +1,304 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -march=bpf | FileCheck %s + +; test that we can expand CTTZ & CTLZ + +declare i32 @llvm.cttz.i32(i32, i1) + +define i32 @cttz_i32_zdef(i32 %a) { +; CHECK-LABEL: cttz_i32_zdef: +; CHECK: # %bb.0: +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 = -r2 +; CHECK-NEXT: r1 &= r2 +; CHECK-NEXT: r1 *= 125613361 +; CHECK-NEXT: r2 = 4160749568 ll +; CHECK-NEXT: r1 &= r2 +; CHECK-NEXT: r1 >>= 27 +; CHECK-NEXT: r2 = {{\.?LCPI[0-9]+_[0-9]+}} ll +; CHECK-NEXT: r2 += r1 +; CHECK-NEXT: r0 = *(u8 *)(r2 + 0) +; CHECK-NEXT: exit + %ret = call i32 @llvm.cttz.i32(i32 %a, i1 1) + ret i32 %ret +} + + +define i32 @cttz_i32(i32 %a) { +; CHECK-LABEL: cttz_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: r0 = 32 +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 <<= 32 +; CHECK-NEXT: r2 >>= 32 +; CHECK-NEXT: if r2 == 0 goto LBB1_2 +; CHECK-NEXT: # %bb.1: # %cond.false +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 = -r2 +; CHECK-NEXT: r1 &= r2 +; CHECK-NEXT: r1 *= 125613361 +; CHECK-NEXT: r2 = 4160749568 ll +; CHECK-NEXT: r1 &= r2 +; CHECK-NEXT: r1 >>= 27 +; CHECK-NEXT: r2 = {{\.?LCPI[0-9]+_[0-9]+}} ll +; CHECK-NEXT: r2 += r1 +; CHECK-NEXT: r0 = *(u8 *)(r2 + 0) +; CHECK-NEXT: LBB1_2: # %cond.end +; CHECK-NEXT: exit + %ret = call i32 @llvm.cttz.i32(i32 %a, i1 0) + ret i32 %ret +} + +declare i64 @llvm.cttz.i64(i64, i1) + +define i64 @cttz_i64_zdef(i64 %a) { +; CHECK-LABEL: cttz_i64_zdef: +; CHECK: # %bb.0: +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 = -r2 +; CHECK-NEXT: r1 &= r2 +; CHECK-NEXT: r2 = 151050438420815295 ll +; CHECK-NEXT: r1 *= r2 +; CHECK-NEXT: r1 >>= 58 +; CHECK-NEXT: r2 = {{\.?LCPI[0-9]+_[0-9]+}} ll +; CHECK-NEXT: r2 += r1 +; CHECK-NEXT: r0 = *(u8 *)(r2 + 0) +; CHECK-NEXT: exit + %ret = call i64 @llvm.cttz.i64(i64 %a, i1 1) + ret i64 %ret +} + + +define i64 @cttz_i64(i64 %a) { +; CHECK-LABEL: cttz_i64: +; CHECK: # %bb.0: +; CHECK-NEXT: r0 = 64 +; CHECK-NEXT: if r1 == 0 goto LBB3_2 +; CHECK-NEXT: # %bb.1: # %cond.false +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 = -r2 +; CHECK-NEXT: r1 &= r2 +; CHECK-NEXT: r2 = 151050438420815295 ll +; CHECK-NEXT: r1 *= r2 +; CHECK-NEXT: r1 >>= 58 +; CHECK-NEXT: r2 = {{\.?LCPI[0-9]+_[0-9]+}} ll +; CHECK-NEXT: r2 += r1 +; CHECK-NEXT: r0 = *(u8 *)(r2 + 0) +; CHECK-NEXT: LBB3_2: # %cond.end +; CHECK-NEXT: exit + %ret = call i64 @llvm.cttz.i64(i64 %a, i1 0) + ret i64 %ret +} + + +declare i32 @llvm.ctlz.i32(i32, i1) + +define i32 @ctlz_i32_zdef(i32 %a) { +; CHECK-LABEL: ctlz_i32_zdef: +; CHECK: # %bb.0: +; CHECK-NEXT: r2 = 4294967294 ll +; CHECK-NEXT: r3 = r1 +; CHECK-NEXT: r3 &= r2 +; CHECK-NEXT: r3 >>= 1 +; CHECK-NEXT: r1 |= r3 +; CHECK-NEXT: r2 = 4294967292 ll +; CHECK-NEXT: r3 = r1 +; CHECK-NEXT: r3 &= r2 +; CHECK-NEXT: r3 >>= 2 +; CHECK-NEXT: r1 |= r3 +; CHECK-NEXT: r2 = 4294967280 ll +; CHECK-NEXT: r3 = r1 +; CHECK-NEXT: r3 &= r2 +; CHECK-NEXT: r3 >>= 4 +; CHECK-NEXT: r1 |= r3 +; CHECK-NEXT: r2 = 4294967040 ll +; CHECK-NEXT: r3 = r1 +; CHECK-NEXT: r3 &= r2 +; CHECK-NEXT: r3 >>= 8 +; CHECK-NEXT: r1 |= r3 +; CHECK-NEXT: r2 = 4294901760 ll +; CHECK-NEXT: r3 = r1 +; CHECK-NEXT: r3 &= r2 +; CHECK-NEXT: r3 >>= 16 +; CHECK-NEXT: r1 |= r3 +; CHECK-NEXT: r1 ^= -1 +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 >>= 1 +; CHECK-NEXT: r2 &= 1431655765 +; CHECK-NEXT: r1 -= r2 +; CHECK-NEXT: r0 = r1 +; CHECK-NEXT: r0 &= 858993459 +; CHECK-NEXT: r1 >>= 2 +; CHECK-NEXT: r1 &= 858993459 +; CHECK-NEXT: r0 += r1 +; CHECK-NEXT: r1 = r0 +; CHECK-NEXT: r1 >>= 4 +; CHECK-NEXT: r0 += r1 +; CHECK-NEXT: r0 &= 252645135 +; CHECK-NEXT: r0 *= 16843009 +; CHECK-NEXT: r1 = 4278190080 ll +; CHECK-NEXT: r0 &= r1 +; CHECK-NEXT: r0 >>= 24 +; CHECK-NEXT: exit + %ret = call i32 @llvm.ctlz.i32(i32 %a, i1 1) + ret i32 %ret +} + + +define i32 @ctlz_i32(i32 %a) { +; CHECK-LABEL: ctlz_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: r0 = 32 +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 <<= 32 +; CHECK-NEXT: r2 >>= 32 +; CHECK-NEXT: if r2 == 0 goto LBB5_2 +; CHECK-NEXT: # %bb.1: # %cond.false +; CHECK-NEXT: r2 = 4294967294 ll +; CHECK-NEXT: r3 = r1 +; CHECK-NEXT: r3 &= r2 +; CHECK-NEXT: r3 >>= 1 +; CHECK-NEXT: r1 |= r3 +; CHECK-NEXT: r2 = 4294967292 ll +; CHECK-NEXT: r3 = r1 +; CHECK-NEXT: r3 &= r2 +; CHECK-NEXT: r3 >>= 2 +; CHECK-NEXT: r1 |= r3 +; CHECK-NEXT: r2 = 4294967280 ll +; CHECK-NEXT: r3 = r1 +; CHECK-NEXT: r3 &= r2 +; CHECK-NEXT: r3 >>= 4 +; CHECK-NEXT: r1 |= r3 +; CHECK-NEXT: r2 = 4294967040 ll +; CHECK-NEXT: r3 = r1 +; CHECK-NEXT: r3 &= r2 +; CHECK-NEXT: r3 >>= 8 +; CHECK-NEXT: r1 |= r3 +; CHECK-NEXT: r2 = 4294901760 ll +; CHECK-NEXT: r3 = r1 +; CHECK-NEXT: r3 &= r2 +; CHECK-NEXT: r3 >>= 16 +; CHECK-NEXT: r1 |= r3 +; CHECK-NEXT: r1 ^= -1 +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 >>= 1 +; CHECK-NEXT: r2 &= 1431655765 +; CHECK-NEXT: r1 -= r2 +; CHECK-NEXT: r0 = r1 +; CHECK-NEXT: r0 &= 858993459 +; CHECK-NEXT: r1 >>= 2 +; CHECK-NEXT: r1 &= 858993459 +; CHECK-NEXT: r0 += r1 +; CHECK-NEXT: r1 = r0 +; CHECK-NEXT: r1 >>= 4 +; CHECK-NEXT: r0 += r1 +; CHECK-NEXT: r0 &= 252645135 +; CHECK-NEXT: r0 *= 16843009 +; CHECK-NEXT: r1 = 4278190080 ll +; CHECK-NEXT: r0 &= r1 +; CHECK-NEXT: r0 >>= 24 +; CHECK-NEXT: LBB5_2: # %cond.end +; CHECK-NEXT: exit + %ret = call i32 @llvm.ctlz.i32(i32 %a, i1 0) + ret i32 %ret +} + +declare i64 @llvm.ctlz.i64(i64, i1) + +define i64 @ctlz_i64_zdef(i64 %a) { +; CHECK-LABEL: ctlz_i64_zdef: +; CHECK: # %bb.0: +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 >>= 1 +; CHECK-NEXT: r1 |= r2 +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 >>= 2 +; CHECK-NEXT: r1 |= r2 +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 >>= 4 +; CHECK-NEXT: r1 |= r2 +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 >>= 8 +; CHECK-NEXT: r1 |= r2 +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 >>= 16 +; CHECK-NEXT: r1 |= r2 +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 >>= 32 +; CHECK-NEXT: r1 |= r2 +; CHECK-NEXT: r1 ^= -1 +; CHECK-NEXT: r2 = 6148914691236517205 ll +; CHECK-NEXT: r3 = r1 +; CHECK-NEXT: r3 >>= 1 +; CHECK-NEXT: r3 &= r2 +; CHECK-NEXT: r1 -= r3 +; CHECK-NEXT: r2 = 3689348814741910323 ll +; CHECK-NEXT: r0 = r1 +; CHECK-NEXT: r0 &= r2 +; CHECK-NEXT: r1 >>= 2 +; CHECK-NEXT: r1 &= r2 +; CHECK-NEXT: r0 += r1 +; CHECK-NEXT: r1 = r0 +; CHECK-NEXT: r1 >>= 4 +; CHECK-NEXT: r0 += r1 +; CHECK-NEXT: r1 = 1085102592571150095 ll +; CHECK-NEXT: r0 &= r1 +; CHECK-NEXT: r1 = 72340172838076673 ll +; CHECK-NEXT: r0 *= r1 +; CHECK-NEXT: r0 >>= 56 +; CHECK-NEXT: exit + %ret = call i64 @llvm.ctlz.i64(i64 %a, i1 1) + ret i64 %ret +} + + +define i64 @ctlz_i64(i64 %a) { +; CHECK-LABEL: ctlz_i64: +; CHECK: # %bb.0: +; CHECK-NEXT: r0 = 64 +; CHECK-NEXT: if r1 == 0 goto LBB7_2 +; CHECK-NEXT: # %bb.1: # %cond.false +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 >>= 1 +; CHECK-NEXT: r1 |= r2 +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 >>= 2 +; CHECK-NEXT: r1 |= r2 +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 >>= 4 +; CHECK-NEXT: r1 |= r2 +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 >>= 8 +; CHECK-NEXT: r1 |= r2 +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 >>= 16 +; CHECK-NEXT: r1 |= r2 +; CHECK-NEXT: r2 = r1 +; CHECK-NEXT: r2 >>= 32 +; CHECK-NEXT: r1 |= r2 +; CHECK-NEXT: r1 ^= -1 +; CHECK-NEXT: r2 = 6148914691236517205 ll +; CHECK-NEXT: r3 = r1 +; CHECK-NEXT: r3 >>= 1 +; CHECK-NEXT: r3 &= r2 +; CHECK-NEXT: r1 -= r3 +; CHECK-NEXT: r2 = 3689348814741910323 ll +; CHECK-NEXT: r0 = r1 +; CHECK-NEXT: r0 &= r2 +; CHECK-NEXT: r1 >>= 2 +; CHECK-NEXT: r1 &= r2 +; CHECK-NEXT: r0 += r1 +; CHECK-NEXT: r1 = r0 +; CHECK-NEXT: r1 >>= 4 +; CHECK-NEXT: r0 += r1 +; CHECK-NEXT: r1 = 1085102592571150095 ll +; CHECK-NEXT: r0 &= r1 +; CHECK-NEXT: r1 = 72340172838076673 ll +; CHECK-NEXT: r0 *= r1 +; CHECK-NEXT: r0 >>= 56 +; CHECK-NEXT: LBB7_2: # %cond.end +; CHECK-NEXT: exit + %ret = call i64 @llvm.ctlz.i64(i64 %a, i1 0) + ret i64 %ret +} + diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll index 865fefeac335dd284309f4b22996667053091227..d027216e4213d546a124d92d0d8fe5a7d2b5e341 100644 --- a/llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll +++ b/llvm/test/CodeGen/DirectX/ShaderFlags/double-extensions.ll @@ -3,10 +3,11 @@ target triple = "dxil-pc-shadermodel6.7-library" -; CHECK: ; Shader Flags Value: 0x00000021 +; CHECK: ; Shader Flags Value: 0x00000044 ; CHECK: ; Note: shader requires additional functionality: ; CHECK-NEXT: ; Double-precision floating point ; CHECK-NEXT: ; Double-precision extensions for 11.1 +; CHECK-NEXT: ; Note: extra DXIL module flags: ; CHECK-NEXT: {{^;$}} define double @div(double %a, double %b) { %res = fdiv double %a, %b diff --git a/llvm/test/CodeGen/DirectX/ShaderFlags/doubles.ll b/llvm/test/CodeGen/DirectX/ShaderFlags/doubles.ll index f90db61661f09f1b5290addf3f6f011d8b48a54e..c1a4c219a169515a4deb8cf4b99dff83cd195f64 100644 --- a/llvm/test/CodeGen/DirectX/ShaderFlags/doubles.ll +++ b/llvm/test/CodeGen/DirectX/ShaderFlags/doubles.ll @@ -3,10 +3,12 @@ target triple = "dxil-pc-shadermodel6.7-library" -; CHECK: ; Shader Flags Value: 0x00000001 +; CHECK: ; Shader Flags Value: 0x00000004 ; CHECK: ; Note: shader requires additional functionality: ; CHECK-NEXT: ; Double-precision floating point +; CHECK-NEXT: ; Note: extra DXIL module flags: ; CHECK-NEXT: {{^;$}} + define double @add(double %a, double %b) { %sum = fadd double %a, %b ret double %sum diff --git a/llvm/test/CodeGen/DirectX/abs-vec.ll b/llvm/test/CodeGen/DirectX/abs-vec.ll new file mode 100644 index 0000000000000000000000000000000000000000..1c40555eb390cd4da3fd34df5b200df8e0cd95b0 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/abs-vec.ll @@ -0,0 +1,34 @@ +; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s + +; Make sure dxil operation function calls for abs are generated for int vectors. + +; CHECK-LABEL: abs_i16Vec2 +define noundef <2 x i16> @abs_i16Vec2(<2 x i16> noundef %a) #0 { +entry: +; CHECK: sub <2 x i16> zeroinitializer, %a +; CHECK: call <2 x i16> @llvm.smax.v2i16(<2 x i16> %a, <2 x i16> %{{.*}}) + %elt.abs = call <2 x i16> @llvm.abs.v2i16(<2 x i16> %a, i1 false) + ret <2 x i16> %elt.abs +} + +; CHECK-LABEL: abs_i32Vec3 +define noundef <3 x i32> @abs_i32Vec3(<3 x i32> noundef %a) #0 { +entry: +; CHECK: sub <3 x i32> zeroinitializer, %a +; CHECK: call <3 x i32> @llvm.smax.v3i32(<3 x i32> %a, <3 x i32> %{{.*}}) + %elt.abs = call <3 x i32> @llvm.abs.v3i32(<3 x i32> %a, i1 false) + ret <3 x i32> %elt.abs +} + +; CHECK-LABEL: abs_i64Vec4 +define noundef <4 x i64> @abs_i64Vec4(<4 x i64> noundef %a) #0 { +entry: +; CHECK: sub <4 x i64> zeroinitializer, %a +; CHECK: call <4 x i64> @llvm.smax.v4i64(<4 x i64> %a, <4 x i64> %{{.*}}) + %elt.abs = call <4 x i64> @llvm.abs.v4i64(<4 x i64> %a, i1 false) + ret <4 x i64> %elt.abs +} + +declare <2 x i16> @llvm.abs.v2i16(<2 x i16>, i1 immarg) +declare <3 x i32> @llvm.abs.v3i32(<3 x i32>, i1 immarg) +declare <4 x i64> @llvm.abs.v4i64(<4 x i64>, i1 immarg) diff --git a/llvm/test/CodeGen/DirectX/abs.ll b/llvm/test/CodeGen/DirectX/abs.ll new file mode 100644 index 0000000000000000000000000000000000000000..822580e8c089afb5b3ee5df57a334fcca8d71fd9 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/abs.ll @@ -0,0 +1,38 @@ +; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK + +; Make sure dxil operation function calls for abs are generated for int16_t/int/int64_t. + +; CHECK-LABEL: abs_i16 +define noundef i16 @abs_i16(i16 noundef %a) { +entry: +; CHECK: sub i16 0, %a +; EXPCHECK: call i16 @llvm.smax.i16(i16 %a, i16 %{{.*}}) +; DOPCHECK: call i16 @dx.op.binary.i16(i32 37, i16 %a, i16 %{{.*}}) + %elt.abs = call i16 @llvm.abs.i16(i16 %a, i1 false) + ret i16 %elt.abs +} + +; CHECK-LABEL: abs_i32 +define noundef i32 @abs_i32(i32 noundef %a) { +entry: +; CHECK: sub i32 0, %a +; EXPCHECK: call i32 @llvm.smax.i32(i32 %a, i32 %{{.*}}) +; DOPCHECK: call i32 @dx.op.binary.i32(i32 37, i32 %a, i32 %{{.*}}) + %elt.abs = call i32 @llvm.abs.i32(i32 %a, i1 false) + ret i32 %elt.abs +} + +; CHECK-LABEL: abs_i64 +define noundef i64 @abs_i64(i64 noundef %a) { +entry: +; CHECK: sub i64 0, %a +; EXPCHECK: call i64 @llvm.smax.i64(i64 %a, i64 %{{.*}}) +; DOPCHECK: call i64 @dx.op.binary.i64(i32 37, i64 %a, i64 %{{.*}}) + %elt.abs = call i64 @llvm.abs.i64(i64 %a, i1 false) + ret i64 %elt.abs +} + +declare i16 @llvm.abs.i16(i16, i1 immarg) +declare i32 @llvm.abs.i32(i32, i1 immarg) +declare i64 @llvm.abs.i64(i64, i1 immarg) diff --git a/llvm/test/CodeGen/DirectX/any.ll b/llvm/test/CodeGen/DirectX/any.ll new file mode 100644 index 0000000000000000000000000000000000000000..e8d87075d65cfe37478a8878b5ffd9620385b554 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/any.ll @@ -0,0 +1,113 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for any are generated for float and half. + +; CHECK-LABEL: any_bool +; CHECK: icmp ne i1 %{{.*}}, false +define noundef i1 @any_bool(i1 noundef %p0) { +entry: + %p0.addr = alloca i8, align 1 + %frombool = zext i1 %p0 to i8 + store i8 %frombool, ptr %p0.addr, align 1 + %0 = load i8, ptr %p0.addr, align 1 + %tobool = trunc i8 %0 to i1 + %dx.any = call i1 @llvm.dx.any.i1(i1 %tobool) + ret i1 %dx.any +} + +; CHECK-LABEL: any_int64_t +; CHECK: icmp ne i64 %{{.*}}, 0 +define noundef i1 @any_int64_t(i64 noundef %p0) { +entry: + %p0.addr = alloca i64, align 8 + store i64 %p0, ptr %p0.addr, align 8 + %0 = load i64, ptr %p0.addr, align 8 + %dx.any = call i1 @llvm.dx.any.i64(i64 %0) + ret i1 %dx.any +} + +; CHECK-LABEL: any_int +; CHECK: icmp ne i32 %{{.*}}, 0 +define noundef i1 @any_int(i32 noundef %p0) { +entry: + %p0.addr = alloca i32, align 4 + store i32 %p0, ptr %p0.addr, align 4 + %0 = load i32, ptr %p0.addr, align 4 + %dx.any = call i1 @llvm.dx.any.i32(i32 %0) + ret i1 %dx.any +} + +; CHECK-LABEL: any_int16_t +; CHECK: icmp ne i16 %{{.*}}, 0 +define noundef i1 @any_int16_t(i16 noundef %p0) { +entry: + %p0.addr = alloca i16, align 2 + store i16 %p0, ptr %p0.addr, align 2 + %0 = load i16, ptr %p0.addr, align 2 + %dx.any = call i1 @llvm.dx.any.i16(i16 %0) + ret i1 %dx.any +} + +; CHECK-LABEL: any_double +; CHECK: fcmp une double %{{.*}}, 0.000000e+00 +define noundef i1 @any_double(double noundef %p0) { +entry: + %p0.addr = alloca double, align 8 + store double %p0, ptr %p0.addr, align 8 + %0 = load double, ptr %p0.addr, align 8 + %dx.any = call i1 @llvm.dx.any.f64(double %0) + ret i1 %dx.any +} + +; CHECK-LABEL: any_float +; CHECK: fcmp une float %{{.*}}, 0.000000e+00 +define noundef i1 @any_float(float noundef %p0) { +entry: + %p0.addr = alloca float, align 4 + store float %p0, ptr %p0.addr, align 4 + %0 = load float, ptr %p0.addr, align 4 + %dx.any = call i1 @llvm.dx.any.f32(float %0) + ret i1 %dx.any +} + +; CHECK-LABEL: any_half +; CHECK: fcmp une half %{{.*}}, 0xH0000 +define noundef i1 @any_half(half noundef %p0) { +entry: + %p0.addr = alloca half, align 2 + store half %p0, ptr %p0.addr, align 2 + %0 = load half, ptr %p0.addr, align 2 + %dx.any = call i1 @llvm.dx.any.f16(half %0) + ret i1 %dx.any +} + +; CHECK-LABEL: any_bool4 +; CHECK: icmp ne <4 x i1> %extractvec, zeroinitialize +; CHECK: extractelement <4 x i1> %{{.*}}, i64 0 +; CHECK: extractelement <4 x i1> %{{.*}}, i64 1 +; CHECK: or i1 %{{.*}}, %{{.*}} +; CHECK: extractelement <4 x i1> %{{.*}}, i64 2 +; CHECK: or i1 %{{.*}}, %{{.*}} +; CHECK: extractelement <4 x i1> %{{.*}}, i64 3 +; CHECK: or i1 %{{.*}}, %{{.*}} +define noundef i1 @any_bool4(<4 x i1> noundef %p0) { +entry: + %p0.addr = alloca i8, align 1 + %insertvec = shufflevector <4 x i1> %p0, <4 x i1> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison> + %0 = bitcast <8 x i1> %insertvec to i8 + store i8 %0, ptr %p0.addr, align 1 + %load_bits = load i8, ptr %p0.addr, align 1 + %1 = bitcast i8 %load_bits to <8 x i1> + %extractvec = shufflevector <8 x i1> %1, <8 x i1> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3> + %dx.any = call i1 @llvm.dx.any.v4i1(<4 x i1> %extractvec) + ret i1 %dx.any +} + +declare i1 @llvm.dx.any.v4i1(<4 x i1>) +declare i1 @llvm.dx.any.i1(i1) +declare i1 @llvm.dx.any.i16(i16) +declare i1 @llvm.dx.any.i32(i32) +declare i1 @llvm.dx.any.i64(i64) +declare i1 @llvm.dx.any.f16(half) +declare i1 @llvm.dx.any.f32(float) +declare i1 @llvm.dx.any.f64(double) diff --git a/llvm/test/CodeGen/DirectX/ceil.ll b/llvm/test/CodeGen/DirectX/ceil.ll new file mode 100644 index 0000000000000000000000000000000000000000..15854714678014f4d5ed5e50dc264aca0a0ebd22 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/ceil.ll @@ -0,0 +1,20 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for ceil are generated for float and half. + +define noundef float @ceil_float(float noundef %a) { +entry: +; CHECK:call float @dx.op.unary.f32(i32 28, float %{{.*}}) + %elt.ceil = call float @llvm.ceil.f32(float %a) + ret float %elt.ceil +} + +define noundef half @ceil_half(half noundef %a) { +entry: +; CHECK:call half @dx.op.unary.f16(i32 28, half %{{.*}}) + %elt.ceil = call half @llvm.ceil.f16(half %a) + ret half %elt.ceil +} + +declare half @llvm.ceil.f16(half) +declare float @llvm.ceil.f32(float) diff --git a/llvm/test/CodeGen/DirectX/ceil_error.ll b/llvm/test/CodeGen/DirectX/ceil_error.ll new file mode 100644 index 0000000000000000000000000000000000000000..1b554d8715566e10e67c49c4a877648d5318d14f --- /dev/null +++ b/llvm/test/CodeGen/DirectX/ceil_error.ll @@ -0,0 +1,10 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; DXIL operation ceil does not support double overload type +; CHECK: LLVM ERROR: Invalid Overload Type + +define noundef double @ceil_double(double noundef %a) { +entry: + %elt.ceil = call double @llvm.ceil.f64(double %a) + ret double %elt.ceil +} diff --git a/llvm/test/CodeGen/DirectX/clamp-vec.ll b/llvm/test/CodeGen/DirectX/clamp-vec.ll new file mode 100644 index 0000000000000000000000000000000000000000..d4f33a18b71573e97e2bb88f6b7f30642b63bb08 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/clamp-vec.ll @@ -0,0 +1,74 @@ +; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s + +; Make sure dxil operation function calls for clamp are generated for float/int/uint vectors. + +; CHECK-LABEL: clamp_half3 +define noundef <3 x half> @clamp_half3(<3 x half> noundef %a, <3 x half> noundef %b, <3 x half> noundef %c) { +entry: + ; CHECK: call <3 x half> @llvm.maxnum.v3f16(<3 x half> %a, <3 x half> %b) + ; CHECK: call <3 x half> @llvm.minnum.v3f16(<3 x half> %{{.*}}, <3 x half> %c) + %dx.clamp = call <3 x half> @llvm.dx.clamp.v3f16(<3 x half> %a, <3 x half> %b, <3 x half> %c) + ret <3 x half> %dx.clamp +} + +; CHECK-LABEL: clamp_float4 +define noundef <4 x float> @clamp_float4(<4 x float> noundef %a, <4 x float> noundef %b, <4 x float> noundef %c) { +entry: + ; CHECK: call <4 x float> @llvm.maxnum.v4f32(<4 x float> %a, <4 x float> %b) + ; CHECK: call <4 x float> @llvm.minnum.v4f32(<4 x float> %{{.*}}, <4 x float> %c) + %dx.clamp = call <4 x float> @llvm.dx.clamp.v4f32(<4 x float> %a, <4 x float> %b, <4 x float> %c) + ret <4 x float> %dx.clamp +} + +; CHECK-LABEL: clamp_double2 +define noundef <2 x double> @clamp_double2(<2 x double> noundef %a, <2 x double> noundef %b, <2 x double> noundef %c) { +entry: + ; CHECK: call <2 x double> @llvm.maxnum.v2f64(<2 x double> %a, <2 x double> %b) + ; CHECK: call <2 x double> @llvm.minnum.v2f64(<2 x double> %{{.*}}, <2 x double> %c) + %dx.clamp = call <2 x double> @llvm.dx.clamp.v2f64(<2 x double> %a, <2 x double> %b, <2 x double> %c) + ret <2 x double> %dx.clamp +} + +; CHECK-LABEL: clamp_int4 +define noundef <4 x i32> @clamp_int4(<4 x i32> noundef %a, <4 x i32> noundef %b, <4 x i32> noundef %c) { +entry: + ; CHECK: call <4 x i32> @llvm.smax.v4i32(<4 x i32> %a, <4 x i32> %b) + ; CHECK: call <4 x i32> @llvm.smin.v4i32(<4 x i32> %{{.*}}, <4 x i32> %c) + %dx.clamp = call <4 x i32> @llvm.dx.clamp.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) + ret <4 x i32> %dx.clamp +} + +; CHECK-LABEL: clamp_uint16_t3 +define noundef <3 x i16> @clamp_uint16_t3(<3 x i16> noundef %a, <3 x i16> noundef %b, <3 x i16> noundef %c) { +entry: + ; CHECK: call <3 x i16> @llvm.umax.v3i16(<3 x i16> %a, <3 x i16> %b) + ; CHECK: call <3 x i16> @llvm.umin.v3i16(<3 x i16> %{{.*}}, <3 x i16> %c) + %dx.clamp = call <3 x i16> @llvm.dx.uclamp.v3i16(<3 x i16> %a, <3 x i16> %b, <3 x i16> %c) + ret <3 x i16> %dx.clamp +} + +; CHECK-LABEL: clamp_uint4 +define noundef <4 x i32> @clamp_uint4(<4 x i32> noundef %a, <4 x i32> noundef %b, <4 x i32> noundef %c) { +entry: + ; CHECK: call <4 x i32> @llvm.umax.v4i32(<4 x i32> %a, <4 x i32> %b) + ; CHECK: call <4 x i32> @llvm.umin.v4i32(<4 x i32> %{{.*}}, <4 x i32> %c) + %dx.clamp = call <4 x i32> @llvm.dx.uclamp.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) + ret <4 x i32> %dx.clamp +} + +; CHECK-LABEL: clamp_uint64_t4 +define noundef <2 x i64> @clamp_uint64_t4(<2 x i64> noundef %a, <2 x i64> noundef %b, <2 x i64> noundef %c) { +entry: + ; CHECK: call <2 x i64> @llvm.umax.v2i64(<2 x i64> %a, <2 x i64> %b) + ; CHECK: call <2 x i64> @llvm.umin.v2i64(<2 x i64> %{{.*}}, <2 x i64> %c) + %dx.clamp = call <2 x i64> @llvm.dx.uclamp.v2i64(<2 x i64> %a, <2 x i64> %b, <2 x i64> %c) + ret <2 x i64> %dx.clamp +} + +declare <3 x half> @llvm.dx.clamp.v3f16(<3 x half>, <3 x half>, <3 x half>) +declare <4 x float> @llvm.dx.clamp.v4f32(<4 x float>, <4 x float>, <4 x float>) +declare <2 x double> @llvm.dx.clamp.v2f64(<2 x double>, <2 x double>, <2 x double>) +declare <4 x i32> @llvm.dx.clamp.v4i32(<4 x i32>, <4 x i32>, <4 x i32>) +declare <3 x i16> @llvm.dx.uclamp.v3i32(<3 x i16>, <3 x i32>, <3 x i16>) +declare <4 x i32> @llvm.dx.uclamp.v4i32(<4 x i32>, <4 x i32>, <4 x i32>) +declare <2 x i64> @llvm.dx.uclamp.v2i64(<2 x i64>, <2 x i64>, <2 x i64>) diff --git a/llvm/test/CodeGen/DirectX/clamp.ll b/llvm/test/CodeGen/DirectX/clamp.ll new file mode 100644 index 0000000000000000000000000000000000000000..f122313b8d7dcc99158ee4fa65364454b75cd482 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/clamp.ll @@ -0,0 +1,94 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for clamp/uclamp are generated for half/float/double/i16/i32/i64. + +; CHECK-LABEL:test_clamp_i16 +define noundef i16 @test_clamp_i16(i16 noundef %a, i16 noundef %b, i16 noundef %c) { +entry: +; CHECK: call i16 @dx.op.binary.i16(i32 37, i16 %{{.*}}, i16 %{{.*}}) +; CHECK: call i16 @dx.op.binary.i16(i32 38, i16 %{{.*}}, i16 %{{.*}}) + %0 = call i16 @llvm.dx.clamp.i16(i16 %a, i16 %b, i16 %c) + ret i16 %0 +} + +; CHECK-LABEL:test_clamp_i32 +define noundef i32 @test_clamp_i32(i32 noundef %a, i32 noundef %b, i32 noundef %c) { +entry: +; CHECK: call i32 @dx.op.binary.i32(i32 37, i32 %{{.*}}, i32 %{{.*}}) +; CHECK: call i32 @dx.op.binary.i32(i32 38, i32 %{{.*}}, i32 %{{.*}}) + %0 = call i32 @llvm.dx.clamp.i32(i32 %a, i32 %b, i32 %c) + ret i32 %0 +} + +; CHECK-LABEL:test_clamp_i64 +define noundef i64 @test_clamp_i64(i64 noundef %a, i64 noundef %b, i64 noundef %c) { +entry: +; CHECK: call i64 @dx.op.binary.i64(i32 37, i64 %a, i64 %b) +; CHECK: call i64 @dx.op.binary.i64(i32 38, i64 %{{.*}}, i64 %c) + %0 = call i64 @llvm.dx.clamp.i64(i64 %a, i64 %b, i64 %c) + ret i64 %0 +} + +; CHECK-LABEL:test_clamp_half +define noundef half @test_clamp_half(half noundef %a, half noundef %b, half noundef %c) { +entry: +; CHECK: call half @dx.op.binary.f16(i32 35, half %{{.*}}, half %{{.*}}) +; CHECK: call half @dx.op.binary.f16(i32 36, half %{{.*}}, half %{{.*}}) + %0 = call half @llvm.dx.clamp.f16(half %a, half %b, half %c) + ret half %0 +} + +; CHECK-LABEL:test_clamp_float +define noundef float @test_clamp_float(float noundef %a, float noundef %b, float noundef %c) { +entry: +; CHECK: call float @dx.op.binary.f32(i32 35, float %{{.*}}, float %{{.*}}) +; CHECK: call float @dx.op.binary.f32(i32 36, float %{{.*}}, float %{{.*}}) + %0 = call float @llvm.dx.clamp.f32(float %a, float %b, float %c) + ret float %0 +} + +; CHECK-LABEL:test_clamp_double +define noundef double @test_clamp_double(double noundef %a, double noundef %b, double noundef %c) { +entry: +; CHECK: call double @dx.op.binary.f64(i32 35, double %{{.*}}, double %{{.*}}) +; CHECK: call double @dx.op.binary.f64(i32 36, double %{{.*}}, double %{{.*}}) + %0 = call double @llvm.dx.clamp.f64(double %a, double %b, double %c) + ret double %0 +} + +; CHECK-LABEL:test_uclamp_i16 +define noundef i16 @test_uclamp_i16(i16 noundef %a, i16 noundef %b, i16 noundef %c) { +entry: +; CHECK: call i16 @dx.op.binary.i16(i32 39, i16 %{{.*}}, i16 %{{.*}}) +; CHECK: call i16 @dx.op.binary.i16(i32 40, i16 %{{.*}}, i16 %{{.*}}) + %0 = call i16 @llvm.dx.uclamp.i16(i16 %a, i16 %b, i16 %c) + ret i16 %0 +} + +; CHECK-LABEL:test_uclamp_i32 +define noundef i32 @test_uclamp_i32(i32 noundef %a, i32 noundef %b, i32 noundef %c) { +entry: +; CHECK: call i32 @dx.op.binary.i32(i32 39, i32 %{{.*}}, i32 %{{.*}}) +; CHECK: call i32 @dx.op.binary.i32(i32 40, i32 %{{.*}}, i32 %{{.*}}) + %0 = call i32 @llvm.dx.uclamp.i32(i32 %a, i32 %b, i32 %c) + ret i32 %0 +} + +; CHECK-LABEL:test_uclamp_i64 +define noundef i64 @test_uclamp_i64(i64 noundef %a, i64 noundef %b, i64 noundef %c) { +entry: +; CHECK: call i64 @dx.op.binary.i64(i32 39, i64 %a, i64 %b) +; CHECK: call i64 @dx.op.binary.i64(i32 40, i64 %{{.*}}, i64 %c) + %0 = call i64 @llvm.dx.uclamp.i64(i64 %a, i64 %b, i64 %c) + ret i64 %0 +} + +declare half @llvm.dx.clamp.f16(half, half, half) +declare float @llvm.dx.clamp.f32(float, float, float) +declare double @llvm.dx.clamp.f64(double, double, double) +declare i16 @llvm.dx.clamp.i16(i16, i16, i16) +declare i32 @llvm.dx.clamp.i32(i32, i32, i32) +declare i64 @llvm.dx.clamp.i64(i64, i64, i64) +declare i16 @llvm.dx.uclamp.i16(i16, i16, i16) +declare i32 @llvm.dx.uclamp.i32(i32, i32, i32) +declare i64 @llvm.dx.uclamp.i64(i64, i64, i64) diff --git a/llvm/test/CodeGen/DirectX/cos.ll b/llvm/test/CodeGen/DirectX/cos.ll new file mode 100644 index 0000000000000000000000000000000000000000..00f2e2c3f6e5abfbf98d722ed6434a01bac702ec --- /dev/null +++ b/llvm/test/CodeGen/DirectX/cos.ll @@ -0,0 +1,20 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for cos are generated for float and half. + +define noundef float @cos_float(float noundef %a) #0 { +entry: +; CHECK:call float @dx.op.unary.f32(i32 12, float %{{.*}}) + %elt.cos = call float @llvm.cos.f32(float %a) + ret float %elt.cos +} + +define noundef half @cos_half(half noundef %a) #0 { +entry: +; CHECK:call half @dx.op.unary.f16(i32 12, half %{{.*}}) + %elt.cos = call half @llvm.cos.f16(half %a) + ret half %elt.cos +} + +declare half @llvm.cos.f16(half) +declare float @llvm.cos.f32(float) diff --git a/llvm/test/CodeGen/DirectX/cos_error.ll b/llvm/test/CodeGen/DirectX/cos_error.ll new file mode 100644 index 0000000000000000000000000000000000000000..a074f5b493dfd636d98eb206900c192d60f2fec3 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/cos_error.ll @@ -0,0 +1,10 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; DXIL operation cos does not support double overload type +; CHECK: LLVM ERROR: Invalid Overload Type + +define noundef double @cos_double(double noundef %a) { +entry: + %elt.cos = call double @llvm.cos.f64(double %a) + ret double %elt.cos +} diff --git a/llvm/test/CodeGen/DirectX/dot2_error.ll b/llvm/test/CodeGen/DirectX/dot2_error.ll new file mode 100644 index 0000000000000000000000000000000000000000..a27bfaedacd57301f62990b17ff2e083c480bd5a --- /dev/null +++ b/llvm/test/CodeGen/DirectX/dot2_error.ll @@ -0,0 +1,10 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; DXIL operation dot2 does not support double overload type +; CHECK: LLVM ERROR: Invalid Overload + +define noundef double @dot_double2(<2 x double> noundef %a, <2 x double> noundef %b) { +entry: + %dx.dot = call double @llvm.dx.dot2.v2f64(<2 x double> %a, <2 x double> %b) + ret double %dx.dot +} diff --git a/llvm/test/CodeGen/DirectX/dot3_error.ll b/llvm/test/CodeGen/DirectX/dot3_error.ll new file mode 100644 index 0000000000000000000000000000000000000000..eb69fb145038aab8f636ca395af2a1b1e369f8fb --- /dev/null +++ b/llvm/test/CodeGen/DirectX/dot3_error.ll @@ -0,0 +1,10 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; DXIL operation dot3 does not support double overload type +; CHECK: LLVM ERROR: Invalid Overload + +define noundef double @dot_double3(<3 x double> noundef %a, <3 x double> noundef %b) { +entry: + %dx.dot = call double @llvm.dx.dot3.v3f64(<3 x double> %a, <3 x double> %b) + ret double %dx.dot +} diff --git a/llvm/test/CodeGen/DirectX/dot4_error.ll b/llvm/test/CodeGen/DirectX/dot4_error.ll new file mode 100644 index 0000000000000000000000000000000000000000..5cd632684c0c01e8ffcd53fe955fb1b5c98d880d --- /dev/null +++ b/llvm/test/CodeGen/DirectX/dot4_error.ll @@ -0,0 +1,10 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; DXIL operation dot4 does not support double overload type +; CHECK: LLVM ERROR: Invalid Overload + +define noundef double @dot_double4(<4 x double> noundef %a, <4 x double> noundef %b) { +entry: + %dx.dot = call double @llvm.dx.dot4.v4f64(<4 x double> %a, <4 x double> %b) + ret double %dx.dot +} diff --git a/llvm/test/CodeGen/DirectX/exp-vec.ll b/llvm/test/CodeGen/DirectX/exp-vec.ll new file mode 100644 index 0000000000000000000000000000000000000000..c9371557190549230fd6f877d1e9b465a7cfbbe8 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/exp-vec.ll @@ -0,0 +1,17 @@ +; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s + +; Make sure dxil operation function calls for exp are generated for float and half. + +; CHECK-LABEL: exp_float4 +; CHECK: fmul <4 x float> <float 0x3FF7154760000000, float 0x3FF7154760000000, float 0x3FF7154760000000, float 0x3FF7154760000000>, %{{.*}} +; CHECK: call <4 x float> @llvm.exp2.v4f32(<4 x float> %{{.*}}) +define noundef <4 x float> @exp_float4(<4 x float> noundef %p0) { +entry: + %p0.addr = alloca <4 x float>, align 16 + store <4 x float> %p0, ptr %p0.addr, align 16 + %0 = load <4 x float>, ptr %p0.addr, align 16 + %elt.exp = call <4 x float> @llvm.exp.v4f32(<4 x float> %0) + ret <4 x float> %elt.exp +} + +declare <4 x float> @llvm.exp.v4f32(<4 x float>) diff --git a/llvm/test/CodeGen/DirectX/exp.ll b/llvm/test/CodeGen/DirectX/exp.ll new file mode 100644 index 0000000000000000000000000000000000000000..fdafc1438cf0e857b64aa2d6a199dcaf98179d65 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/exp.ll @@ -0,0 +1,31 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for exp are generated for float and half. + +; CHECK-LABEL: exp_float +; CHECK: fmul float 0x3FF7154760000000, %{{.*}} +; CHECK: call float @dx.op.unary.f32(i32 21, float %{{.*}}) +define noundef float @exp_float(float noundef %a) { +entry: + %a.addr = alloca float, align 4 + store float %a, ptr %a.addr, align 4 + %0 = load float, ptr %a.addr, align 4 + %elt.exp = call float @llvm.exp.f32(float %0) + ret float %elt.exp +} + +; CHECK-LABEL: exp_half +; CHECK: fmul half 0xH3DC5, %{{.*}} +; CHECK: call half @dx.op.unary.f16(i32 21, half %{{.*}}) +; Function Attrs: noinline nounwind optnone +define noundef half @exp_half(half noundef %a) { +entry: + %a.addr = alloca half, align 2 + store half %a, ptr %a.addr, align 2 + %0 = load half, ptr %a.addr, align 2 + %elt.exp = call half @llvm.exp.f16(half %0) + ret half %elt.exp +} + +declare half @llvm.exp.f16(half) +declare float @llvm.exp.f32(float) diff --git a/llvm/test/CodeGen/DirectX/fabs.ll b/llvm/test/CodeGen/DirectX/fabs.ll new file mode 100644 index 0000000000000000000000000000000000000000..3b3f8aa9a4a928985f557555f2e0aa1b34189c5c --- /dev/null +++ b/llvm/test/CodeGen/DirectX/fabs.ll @@ -0,0 +1,32 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for abs are generated for float, half, and double. + + +; CHECK-LABEL: fabs_half +define noundef half @fabs_half(half noundef %a) { +entry: + ; CHECK: call half @dx.op.unary.f16(i32 6, half %{{.*}}) + %elt.abs = call half @llvm.fabs.f16(half %a) + ret half %elt.abs +} + +; CHECK-LABEL: fabs_float +define noundef float @fabs_float(float noundef %a) { +entry: +; CHECK: call float @dx.op.unary.f32(i32 6, float %{{.*}}) + %elt.abs = call float @llvm.fabs.f32(float %a) + ret float %elt.abs +} + +; CHECK-LABEL: fabs_double +define noundef double @fabs_double(double noundef %a) { +entry: +; CHECK: call double @dx.op.unary.f64(i32 6, double %{{.*}}) + %elt.abs = call double @llvm.fabs.f64(double %a) + ret double %elt.abs +} + +declare half @llvm.fabs.f16(half) +declare float @llvm.fabs.f32(float) +declare double @llvm.fabs.f64(double) diff --git a/llvm/test/CodeGen/DirectX/fdot.ll b/llvm/test/CodeGen/DirectX/fdot.ll new file mode 100644 index 0000000000000000000000000000000000000000..3e13b2ad2650c8ebaf14e8ca8523ec2613039726 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/fdot.ll @@ -0,0 +1,94 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for dot are generated for int/uint vectors. + +; CHECK-LABEL: dot_half2 +define noundef half @dot_half2(<2 x half> noundef %a, <2 x half> noundef %b) { +entry: +; CHECK: extractelement <2 x half> %a, i32 0 +; CHECK: extractelement <2 x half> %a, i32 1 +; CHECK: extractelement <2 x half> %b, i32 0 +; CHECK: extractelement <2 x half> %b, i32 1 +; CHECK: call half @dx.op.dot2.f16(i32 54, half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}}) + %dx.dot = call half @llvm.dx.dot2.v2f16(<2 x half> %a, <2 x half> %b) + ret half %dx.dot +} + +; CHECK-LABEL: dot_half3 +define noundef half @dot_half3(<3 x half> noundef %a, <3 x half> noundef %b) { +entry: +; CHECK: extractelement <3 x half> %a, i32 0 +; CHECK: extractelement <3 x half> %a, i32 1 +; CHECK: extractelement <3 x half> %a, i32 2 +; CHECK: extractelement <3 x half> %b, i32 0 +; CHECK: extractelement <3 x half> %b, i32 1 +; CHECK: extractelement <3 x half> %b, i32 2 +; CHECK: call half @dx.op.dot3.f16(i32 55, half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}}) + %dx.dot = call half @llvm.dx.dot3.v3f16(<3 x half> %a, <3 x half> %b) + ret half %dx.dot +} + +; CHECK-LABEL: dot_half4 +define noundef half @dot_half4(<4 x half> noundef %a, <4 x half> noundef %b) { +entry: +; CHECK: extractelement <4 x half> %a, i32 0 +; CHECK: extractelement <4 x half> %a, i32 1 +; CHECK: extractelement <4 x half> %a, i32 2 +; CHECK: extractelement <4 x half> %a, i32 3 +; CHECK: extractelement <4 x half> %b, i32 0 +; CHECK: extractelement <4 x half> %b, i32 1 +; CHECK: extractelement <4 x half> %b, i32 2 +; CHECK: extractelement <4 x half> %b, i32 3 +; CHECK: call half @dx.op.dot4.f16(i32 56, half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}}) + %dx.dot = call half @llvm.dx.dot4.v4f16(<4 x half> %a, <4 x half> %b) + ret half %dx.dot +} + +; CHECK-LABEL: dot_float2 +define noundef float @dot_float2(<2 x float> noundef %a, <2 x float> noundef %b) { +entry: +; CHECK: extractelement <2 x float> %a, i32 0 +; CHECK: extractelement <2 x float> %a, i32 1 +; CHECK: extractelement <2 x float> %b, i32 0 +; CHECK: extractelement <2 x float> %b, i32 1 +; CHECK: call float @dx.op.dot2.f32(i32 54, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}) + %dx.dot = call float @llvm.dx.dot2.v2f32(<2 x float> %a, <2 x float> %b) + ret float %dx.dot +} + +; CHECK-LABEL: dot_float3 +define noundef float @dot_float3(<3 x float> noundef %a, <3 x float> noundef %b) { +entry: +; CHECK: extractelement <3 x float> %a, i32 0 +; CHECK: extractelement <3 x float> %a, i32 1 +; CHECK: extractelement <3 x float> %a, i32 2 +; CHECK: extractelement <3 x float> %b, i32 0 +; CHECK: extractelement <3 x float> %b, i32 1 +; CHECK: extractelement <3 x float> %b, i32 2 +; CHECK: call float @dx.op.dot3.f32(i32 55, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}) + %dx.dot = call float @llvm.dx.dot3.v3f32(<3 x float> %a, <3 x float> %b) + ret float %dx.dot +} + +; CHECK-LABEL: dot_float4 +define noundef float @dot_float4(<4 x float> noundef %a, <4 x float> noundef %b) { +entry: +; CHECK: extractelement <4 x float> %a, i32 0 +; CHECK: extractelement <4 x float> %a, i32 1 +; CHECK: extractelement <4 x float> %a, i32 2 +; CHECK: extractelement <4 x float> %a, i32 3 +; CHECK: extractelement <4 x float> %b, i32 0 +; CHECK: extractelement <4 x float> %b, i32 1 +; CHECK: extractelement <4 x float> %b, i32 2 +; CHECK: extractelement <4 x float> %b, i32 3 +; CHECK: call float @dx.op.dot4.f32(i32 56, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}}) + %dx.dot = call float @llvm.dx.dot4.v4f32(<4 x float> %a, <4 x float> %b) + ret float %dx.dot +} + +declare half @llvm.dx.dot.v2f16(<2 x half> , <2 x half> ) +declare half @llvm.dx.dot.v3f16(<3 x half> , <3 x half> ) +declare half @llvm.dx.dot.v4f16(<4 x half> , <4 x half> ) +declare float @llvm.dx.dot.v2f32(<2 x float>, <2 x float>) +declare float @llvm.dx.dot.v3f32(<3 x float>, <3 x float>) +declare float @llvm.dx.dot.v4f32(<4 x float>, <4 x float>) diff --git a/llvm/test/CodeGen/DirectX/floor.ll b/llvm/test/CodeGen/DirectX/floor.ll new file mode 100644 index 0000000000000000000000000000000000000000..b033e2eaa491e73d3890d97c905b6ebfc1581873 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/floor.ll @@ -0,0 +1,20 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for floor are generated for float and half. + +define noundef float @floor_float(float noundef %a) #0 { +entry: +; CHECK:call float @dx.op.unary.f32(i32 27, float %{{.*}}) + %elt.floor = call float @llvm.floor.f32(float %a) + ret float %elt.floor +} + +define noundef half @floor_half(half noundef %a) #0 { +entry: +; CHECK:call half @dx.op.unary.f16(i32 27, half %{{.*}}) + %elt.floor = call half @llvm.floor.f16(half %a) + ret half %elt.floor +} + +declare half @llvm.floor.f16(half) +declare float @llvm.floor.f32(float) diff --git a/llvm/test/CodeGen/DirectX/floor_error.ll b/llvm/test/CodeGen/DirectX/floor_error.ll new file mode 100644 index 0000000000000000000000000000000000000000..3b51a4b543b7f6bd293263760428ffa897e5a2cb --- /dev/null +++ b/llvm/test/CodeGen/DirectX/floor_error.ll @@ -0,0 +1,10 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; DXIL operation floor does not support double overload type +; CHECK: LLVM ERROR: Invalid Overload Type + +define noundef double @floor_double(double noundef %a) { +entry: + %elt.floor = call double @llvm.floor.f64(double %a) + ret double %elt.floor +} diff --git a/llvm/test/CodeGen/DirectX/fmax.ll b/llvm/test/CodeGen/DirectX/fmax.ll new file mode 100644 index 0000000000000000000000000000000000000000..aff722c29309c031344b2b56a6fa9791cb994850 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/fmax.ll @@ -0,0 +1,31 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for fmax are generated for half/float/double. + +; CHECK-LABEL:test_fmax_half +define noundef half @test_fmax_half(half noundef %a, half noundef %b) { +entry: +; CHECK: call half @dx.op.binary.f16(i32 35, half %{{.*}}, half %{{.*}}) + %0 = call half @llvm.maxnum.f16(half %a, half %b) + ret half %0 +} + +; CHECK-LABEL:test_fmax_float +define noundef float @test_fmax_float(float noundef %a, float noundef %b) { +entry: +; CHECK: call float @dx.op.binary.f32(i32 35, float %{{.*}}, float %{{.*}}) + %0 = call float @llvm.maxnum.f32(float %a, float %b) + ret float %0 +} + +; CHECK-LABEL:test_fmax_double +define noundef double @test_fmax_double(double noundef %a, double noundef %b) { +entry: +; CHECK: call double @dx.op.binary.f64(i32 35, double %{{.*}}, double %{{.*}}) + %0 = call double @llvm.maxnum.f64(double %a, double %b) + ret double %0 +} + +declare half @llvm.maxnum.f16(half, half) +declare float @llvm.maxnum.f32(float, float) +declare double @llvm.maxnum.f64(double, double) diff --git a/llvm/test/CodeGen/DirectX/fmin.ll b/llvm/test/CodeGen/DirectX/fmin.ll new file mode 100644 index 0000000000000000000000000000000000000000..2f7c209f0278ae7a1fc86adc9d860f79fc4c8e9d --- /dev/null +++ b/llvm/test/CodeGen/DirectX/fmin.ll @@ -0,0 +1,31 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for fmin are generated for half/float/double. + +; CHECK-LABEL:test_fmin_half +define noundef half @test_fmin_half(half noundef %a, half noundef %b) { +entry: +; CHECK: call half @dx.op.binary.f16(i32 36, half %{{.*}}, half %{{.*}}) + %0 = call half @llvm.minnum.f16(half %a, half %b) + ret half %0 +} + +; CHECK-LABEL:test_fmin_float +define noundef float @test_fmin_float(float noundef %a, float noundef %b) { +entry: +; CHECK: call float @dx.op.binary.f32(i32 36, float %{{.*}}, float %{{.*}}) + %0 = call float @llvm.minnum.f32(float %a, float %b) + ret float %0 +} + +; CHECK-LABEL:test_fmin_double +define noundef double @test_fmin_double(double noundef %a, double noundef %b) { +entry: +; CHECK: call double @dx.op.binary.f64(i32 36, double %{{.*}}, double %{{.*}}) + %0 = call double @llvm.minnum.f64(double %a, double %b) + ret double %0 +} + +declare half @llvm.minnum.f16(half, half) +declare float @llvm.minnum.f32(float, float) +declare double @llvm.minnum.f64(double, double) diff --git a/llvm/test/CodeGen/DirectX/idot.ll b/llvm/test/CodeGen/DirectX/idot.ll new file mode 100644 index 0000000000000000000000000000000000000000..9f89a8d6d340d50d05bd994400c868846b716dc2 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/idot.ll @@ -0,0 +1,100 @@ +; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK + +; Make sure dxil operation function calls for dot are generated for int/uint vectors. + +; CHECK-LABEL: dot_int16_t2 +define noundef i16 @dot_int16_t2(<2 x i16> noundef %a, <2 x i16> noundef %b) { +entry: +; CHECK: extractelement <2 x i16> %a, i64 0 +; CHECK: extractelement <2 x i16> %b, i64 0 +; CHECK: mul i16 %{{.*}}, %{{.*}} +; CHECK: extractelement <2 x i16> %a, i64 1 +; CHECK: extractelement <2 x i16> %b, i64 1 +; EXPCHECK: call i16 @llvm.dx.imad.i16(i16 %{{.*}}, i16 %{{.*}}, i16 %{{.*}}) +; DOPCHECK: call i16 @dx.op.tertiary.i16(i32 48, i16 %{{.*}}, i16 %{{.*}}, i16 %{{.*}}) + %dx.dot = call i16 @llvm.dx.sdot.v3i16(<2 x i16> %a, <2 x i16> %b) + ret i16 %dx.dot +} + +; CHECK-LABEL: sdot_int4 +define noundef i32 @sdot_int4(<4 x i32> noundef %a, <4 x i32> noundef %b) { +entry: +; CHECK: extractelement <4 x i32> %a, i64 0 +; CHECK: extractelement <4 x i32> %b, i64 0 +; CHECK: mul i32 %{{.*}}, %{{.*}} +; CHECK: extractelement <4 x i32> %a, i64 1 +; CHECK: extractelement <4 x i32> %b, i64 1 +; EXPCHECK: call i32 @llvm.dx.imad.i32(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}) +; DOPCHECK: call i32 @dx.op.tertiary.i32(i32 48, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}) +; CHECK: extractelement <4 x i32> %a, i64 2 +; CHECK: extractelement <4 x i32> %b, i64 2 +; EXPCHECK: call i32 @llvm.dx.imad.i32(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}) +; DOPCHECK: call i32 @dx.op.tertiary.i32(i32 48, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}) +; CHECK: extractelement <4 x i32> %a, i64 3 +; CHECK: extractelement <4 x i32> %b, i64 3 +; EXPCHECK: call i32 @llvm.dx.imad.i32(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}) +; DOPCHECK: call i32 @dx.op.tertiary.i32(i32 48, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}) + %dx.dot = call i32 @llvm.dx.sdot.v4i32(<4 x i32> %a, <4 x i32> %b) + ret i32 %dx.dot +} + +; CHECK-LABEL: dot_uint16_t3 +define noundef i16 @dot_uint16_t3(<3 x i16> noundef %a, <3 x i16> noundef %b) { +entry: +; CHECK: extractelement <3 x i16> %a, i64 0 +; CHECK: extractelement <3 x i16> %b, i64 0 +; CHECK: mul i16 %{{.*}}, %{{.*}} +; CHECK: extractelement <3 x i16> %a, i64 1 +; CHECK: extractelement <3 x i16> %b, i64 1 +; EXPCHECK: call i16 @llvm.dx.umad.i16(i16 %{{.*}}, i16 %{{.*}}, i16 %{{.*}}) +; DOPCHECK: call i16 @dx.op.tertiary.i16(i32 49, i16 %{{.*}}, i16 %{{.*}}, i16 %{{.*}}) +; CHECK: extractelement <3 x i16> %a, i64 2 +; CHECK: extractelement <3 x i16> %b, i64 2 +; EXPCHECK: call i16 @llvm.dx.umad.i16(i16 %{{.*}}, i16 %{{.*}}, i16 %{{.*}}) +; DOPCHECK: call i16 @dx.op.tertiary.i16(i32 49, i16 %{{.*}}, i16 %{{.*}}, i16 %{{.*}}) + %dx.dot = call i16 @llvm.dx.udot.v3i16(<3 x i16> %a, <3 x i16> %b) + ret i16 %dx.dot +} + +; CHECK-LABEL: dot_uint4 +define noundef i32 @dot_uint4(<4 x i32> noundef %a, <4 x i32> noundef %b) { +entry: +; CHECK: extractelement <4 x i32> %a, i64 0 +; CHECK: extractelement <4 x i32> %b, i64 0 +; CHECK: mul i32 %{{.*}}, %{{.*}} +; CHECK: extractelement <4 x i32> %a, i64 1 +; CHECK: extractelement <4 x i32> %b, i64 1 +; EXPCHECK: call i32 @llvm.dx.umad.i32(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}) +; DOPCHECK: call i32 @dx.op.tertiary.i32(i32 49, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}) +; CHECK: extractelement <4 x i32> %a, i64 2 +; CHECK: extractelement <4 x i32> %b, i64 2 +; EXPCHECK: call i32 @llvm.dx.umad.i32(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}) +; DOPCHECK: call i32 @dx.op.tertiary.i32(i32 49, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}) +; CHECK: extractelement <4 x i32> %a, i64 3 +; CHECK: extractelement <4 x i32> %b, i64 3 +; EXPCHECK: call i32 @llvm.dx.umad.i32(i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}) +; DOPCHECK: call i32 @dx.op.tertiary.i32(i32 49, i32 %{{.*}}, i32 %{{.*}}, i32 %{{.*}}) + %dx.dot = call i32 @llvm.dx.udot.v4i32(<4 x i32> %a, <4 x i32> %b) + ret i32 %dx.dot +} + +; CHECK-LABEL: dot_uint64_t4 +define noundef i64 @dot_uint64_t4(<2 x i64> noundef %a, <2 x i64> noundef %b) { +entry: +; CHECK: extractelement <2 x i64> %a, i64 0 +; CHECK: extractelement <2 x i64> %b, i64 0 +; CHECK: mul i64 %{{.*}}, %{{.*}} +; CHECK: extractelement <2 x i64> %a, i64 1 +; CHECK: extractelement <2 x i64> %b, i64 1 +; EXPCHECK: call i64 @llvm.dx.umad.i64(i64 %{{.*}}, i64 %{{.*}}, i64 %{{.*}}) +; DOPCHECK: call i64 @dx.op.tertiary.i64(i32 49, i64 %{{.*}}, i64 %{{.*}}, i64 %{{.*}}) + %dx.dot = call i64 @llvm.dx.udot.v2i64(<2 x i64> %a, <2 x i64> %b) + ret i64 %dx.dot +} + +declare i16 @llvm.dx.sdot.v2i16(<2 x i16>, <2 x i16>) +declare i32 @llvm.dx.sdot.v4i32(<4 x i32>, <4 x i32>) +declare i16 @llvm.dx.udot.v3i32(<3 x i16>, <3 x i16>) +declare i32 @llvm.dx.udot.v4i32(<4 x i32>, <4 x i32>) +declare i64 @llvm.dx.udot.v2i64(<2 x i64>, <2 x i64>) diff --git a/llvm/test/CodeGen/DirectX/isinf.ll b/llvm/test/CodeGen/DirectX/isinf.ll new file mode 100644 index 0000000000000000000000000000000000000000..e2975da90bfc1b540a0fbfa0c9284cfb187e7258 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/isinf.ll @@ -0,0 +1,25 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for isinf are generated for float and half. +; CHECK: call i1 @dx.op.isSpecialFloat.f32(i32 9, float %{{.*}}) +; CHECK: call i1 @dx.op.isSpecialFloat.f16(i32 9, half %{{.*}}) + +; Function Attrs: noinline nounwind optnone +define noundef i1 @isinf_float(float noundef %a) #0 { +entry: + %a.addr = alloca float, align 4 + store float %a, ptr %a.addr, align 4 + %0 = load float, ptr %a.addr, align 4 + %dx.isinf = call i1 @llvm.dx.isinf.f32(float %0) + ret i1 %dx.isinf +} + +; Function Attrs: noinline nounwind optnone +define noundef i1 @isinf_half(half noundef %p0) #0 { +entry: + %p0.addr = alloca half, align 2 + store half %p0, ptr %p0.addr, align 2 + %0 = load half, ptr %p0.addr, align 2 + %dx.isinf = call i1 @llvm.dx.isinf.f16(half %0) + ret i1 %dx.isinf +} diff --git a/llvm/test/CodeGen/DirectX/isinf_error.ll b/llvm/test/CodeGen/DirectX/isinf_error.ll new file mode 100644 index 0000000000000000000000000000000000000000..95b2d0cabcc43b2f312dd58d017c662bdf16d9fc --- /dev/null +++ b/llvm/test/CodeGen/DirectX/isinf_error.ll @@ -0,0 +1,13 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; DXIL operation isinf does not support double overload type +; CHECK: LLVM ERROR: Invalid Overload Type + +define noundef i1 @isinf_double(double noundef %a) #0 { +entry: + %a.addr = alloca double, align 8 + store double %a, ptr %a.addr, align 8 + %0 = load double, ptr %a.addr, align 8 + %dx.isinf = call i1 @llvm.dx.isinf.f64(double %0) + ret i1 %dx.isinf +} diff --git a/llvm/test/CodeGen/DirectX/lerp.ll b/llvm/test/CodeGen/DirectX/lerp.ll new file mode 100644 index 0000000000000000000000000000000000000000..ebd7e133b5163c8128fb7ebb825379b74a0e174b --- /dev/null +++ b/llvm/test/CodeGen/DirectX/lerp.ll @@ -0,0 +1,56 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for lerp are generated for float and half. + +; CHECK-LABEL: lerp_half +; CHECK: fsub half %{{.*}}, %{{.*}} +; CHECK: fmul half %{{.*}}, %{{.*}} +; CHECK: fadd half %{{.*}}, %{{.*}} +define noundef half @lerp_half(half noundef %p0) { +entry: + %p0.addr = alloca half, align 2 + store half %p0, ptr %p0.addr, align 2 + %0 = load half, ptr %p0.addr, align 2 + %1 = load half, ptr %p0.addr, align 2 + %2 = load half, ptr %p0.addr, align 2 + %dx.lerp = call half @llvm.dx.lerp.f16(half %0, half %1, half %2) + ret half %dx.lerp +} + +; CHECK-LABEL: lerp_float +; CHECK: fsub float %{{.*}}, %{{.*}} +; CHECK: fmul float %{{.*}}, %{{.*}} +; CHECK: fadd float %{{.*}}, %{{.*}} +define noundef float @lerp_float(float noundef %p0, float noundef %p1) { +entry: + %p1.addr = alloca float, align 4 + %p0.addr = alloca float, align 4 + store float %p1, ptr %p1.addr, align 4 + store float %p0, ptr %p0.addr, align 4 + %0 = load float, ptr %p0.addr, align 4 + %1 = load float, ptr %p0.addr, align 4 + %2 = load float, ptr %p0.addr, align 4 + %dx.lerp = call float @llvm.dx.lerp.f32(float %0, float %1, float %2) + ret float %dx.lerp +} + +; CHECK-LABEL: lerp_float4 +; CHECK: fsub <4 x float> %{{.*}}, %{{.*}} +; CHECK: fmul <4 x float> %{{.*}}, %{{.*}} +; CHECK: fadd <4 x float> %{{.*}}, %{{.*}} +define noundef <4 x float> @lerp_float4(<4 x float> noundef %p0, <4 x float> noundef %p1) { +entry: + %p1.addr = alloca <4 x float>, align 16 + %p0.addr = alloca <4 x float>, align 16 + store <4 x float> %p1, ptr %p1.addr, align 16 + store <4 x float> %p0, ptr %p0.addr, align 16 + %0 = load <4 x float>, ptr %p0.addr, align 16 + %1 = load <4 x float>, ptr %p0.addr, align 16 + %2 = load <4 x float>, ptr %p0.addr, align 16 + %dx.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2) + ret <4 x float> %dx.lerp +} + +declare half @llvm.dx.lerp.f16(half, half, half) +declare float @llvm.dx.lerp.f32(float, float, float) +declare <4 x float> @llvm.dx.lerp.v4f32(<4 x float>, <4 x float>, <4 x float>) diff --git a/llvm/test/CodeGen/DirectX/lib_entry.ll b/llvm/test/CodeGen/DirectX/lib_entry.ll index 9208d6d3f32246be5a3a4226732bea24a6c76ae3..5254a0880558884cff621f403a302b9bbb127b55 100644 --- a/llvm/test/CodeGen/DirectX/lib_entry.ll +++ b/llvm/test/CodeGen/DirectX/lib_entry.ll @@ -7,7 +7,7 @@ target triple = "dxil-unknown-shadermodel6.7-library" ; Make sure generate empty entry for lib profile. ;CHECK:![[empty_entry]] = !{null, !"", null, null, ![[shader_flags:[0-9]+]]} ; Make sure double is marked for shader flags. -;CHECK:![[shader_flags]] = !{i32 0, i64 1} +;CHECK:![[shader_flags]] = !{i32 0, i64 4} ;CHECK:![[entry]] = !{ptr @entry, !"entry", null, null, ![[extra:[0-9]+]]} ;CHECK:![[extra]] = !{i32 8, i32 5, i32 4, ![[numthreads:[0-9]+]]} ;CHECK:![[numthreads]] = !{i32 1, i32 2, i32 1} diff --git a/llvm/test/CodeGen/DirectX/log-vec.ll b/llvm/test/CodeGen/DirectX/log-vec.ll new file mode 100644 index 0000000000000000000000000000000000000000..4768fdd94b02559d6b57b75d32f7bd1db7930a6b --- /dev/null +++ b/llvm/test/CodeGen/DirectX/log-vec.ll @@ -0,0 +1,30 @@ +; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s + +; Make sure dxil operation function calls for log are generated for float and half. + +; CHECK-LABEL: log_float4 +; CHECK: call <4 x float> @llvm.log2.v4f32(<4 x float> %{{.*}}) +; CHECK: fmul <4 x float> <float 0x3FE62E4300000000, float 0x3FE62E4300000000, float 0x3FE62E4300000000, float 0x3FE62E4300000000>, %{{.*}} +define noundef <4 x float> @log_float4(<4 x float> noundef %p0) { +entry: + %p0.addr = alloca <4 x float>, align 16 + store <4 x float> %p0, ptr %p0.addr, align 16 + %0 = load <4 x float>, ptr %p0.addr, align 16 + %elt.log = call <4 x float> @llvm.log.v4f32(<4 x float> %0) + ret <4 x float> %elt.log +} + +; CHECK-LABEL: log10_float4 +; CHECK: call <4 x float> @llvm.log2.v4f32(<4 x float> %{{.*}}) +; CHECK: fmul <4 x float> <float 0x3FD3441340000000, float 0x3FD3441340000000, float 0x3FD3441340000000, float 0x3FD3441340000000>, %{{.*}} +define noundef <4 x float> @log10_float4(<4 x float> noundef %p0) { +entry: + %p0.addr = alloca <4 x float>, align 16 + store <4 x float> %p0, ptr %p0.addr, align 16 + %0 = load <4 x float>, ptr %p0.addr, align 16 + %elt.log10 = call <4 x float> @llvm.log10.v4f32(<4 x float> %0) + ret <4 x float> %elt.log10 +} + +declare <4 x float> @llvm.log.v4f32(<4 x float>) +declare <4 x float> @llvm.log10.v4f32(<4 x float>) diff --git a/llvm/test/CodeGen/DirectX/log.ll b/llvm/test/CodeGen/DirectX/log.ll new file mode 100644 index 0000000000000000000000000000000000000000..172c3bfed3b770cfb63b9d30326239a82da235bf --- /dev/null +++ b/llvm/test/CodeGen/DirectX/log.ll @@ -0,0 +1,25 @@ +; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK + +; Make sure dxil operation function calls for log are generated. + +define noundef float @log_float(float noundef %a) #0 { +entry: +; DOPCHECK: call float @dx.op.unary.f32(i32 23, float %{{.*}}) +; EXPCHECK: call float @llvm.log2.f32(float %a) +; CHECK: fmul float 0x3FE62E4300000000, %{{.*}} + %elt.log = call float @llvm.log.f32(float %a) + ret float %elt.log +} + +define noundef half @log_half(half noundef %a) #0 { +entry: +; DOPCHECK: call half @dx.op.unary.f16(i32 23, half %{{.*}}) +; EXPCHECK: call half @llvm.log2.f16(half %a) +; CHECK: fmul half 0xH398C, %{{.*}} + %elt.log = call half @llvm.log.f16(half %a) + ret half %elt.log +} + +declare half @llvm.log.f16(half) +declare float @llvm.log.f32(float) diff --git a/llvm/test/CodeGen/DirectX/log10.ll b/llvm/test/CodeGen/DirectX/log10.ll new file mode 100644 index 0000000000000000000000000000000000000000..d4f827a0d1af83a801e3e2ece040fede4bb0dca5 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/log10.ll @@ -0,0 +1,25 @@ +; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK + +; Make sure dxil operation function calls for log10 are generated. + +define noundef float @log10_float(float noundef %a) #0 { +entry: +; DOPCHECK: call float @dx.op.unary.f32(i32 23, float %{{.*}}) +; EXPCHECK: call float @llvm.log2.f32(float %a) +; CHECK: fmul float 0x3FD3441340000000, %{{.*}} + %elt.log10 = call float @llvm.log10.f32(float %a) + ret float %elt.log10 +} + +define noundef half @log10_half(half noundef %a) #0 { +entry: +; DOPCHECK: call half @dx.op.unary.f16(i32 23, half %{{.*}}) +; EXPCHECK: call half @llvm.log2.f16(half %a) +; CHECK: fmul half 0xH34D1, %{{.*}} + %elt.log10 = call half @llvm.log10.f16(half %a) + ret half %elt.log10 +} + +declare half @llvm.log10.f16(half) +declare float @llvm.log10.f32(float) diff --git a/llvm/test/CodeGen/DirectX/log2.ll b/llvm/test/CodeGen/DirectX/log2.ll new file mode 100644 index 0000000000000000000000000000000000000000..2164d4db9396d1142c393f9bd45c3938fd1c2bd2 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/log2.ll @@ -0,0 +1,20 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for log2 are generated for float and half. + +define noundef float @log2_float(float noundef %a) #0 { +entry: +; CHECK:call float @dx.op.unary.f32(i32 23, float %{{.*}}) + %elt.log2 = call float @llvm.log2.f32(float %a) + ret float %elt.log2 +} + +define noundef half @log2_half(half noundef %a) #0 { +entry: +; CHECK:call half @dx.op.unary.f16(i32 23, half %{{.*}}) + %elt.log2 = call half @llvm.log2.f16(half %a) + ret half %elt.log2 +} + +declare half @llvm.log2.f16(half) +declare float @llvm.log2.f32(float) diff --git a/llvm/test/CodeGen/DirectX/log2_error.ll b/llvm/test/CodeGen/DirectX/log2_error.ll new file mode 100644 index 0000000000000000000000000000000000000000..a26f6e8c3117f5b136495482aeb571dc43ce8bed --- /dev/null +++ b/llvm/test/CodeGen/DirectX/log2_error.ll @@ -0,0 +1,10 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; DXIL operation log2 does not support double overload type +; CHECK: LLVM ERROR: Invalid Overload Type + +define noundef double @log2_double(double noundef %a) { +entry: + %elt.log2 = call double @llvm.log2.f64(double %a) + ret double %elt.log2 +} diff --git a/llvm/test/CodeGen/DirectX/pow-vec.ll b/llvm/test/CodeGen/DirectX/pow-vec.ll new file mode 100644 index 0000000000000000000000000000000000000000..781fa5b8cb2409e48d2aa78d0013dce2ee56ccd0 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/pow-vec.ll @@ -0,0 +1,15 @@ +; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s + +; Make sure dxil operation function calls for pow are generated for float and half. + +; CHECK-LABEL: pow_float4 +; CHECK: call <4 x float> @llvm.log2.v4f32(<4 x float> %a) +; CHECK: fmul <4 x float> %{{.*}}, %b +; CHECK: call <4 x float> @llvm.exp2.v4f32(<4 x float> %{{.*}}) +define noundef <4 x float> @pow_float4(<4 x float> noundef %a, <4 x float> noundef %b) { +entry: + %elt.pow = call <4 x float> @llvm.pow.v4f32(<4 x float> %a, <4 x float> %b) + ret <4 x float> %elt.pow +} + +declare <4 x float> @llvm.pow.v4f32(<4 x float>,<4 x float>) diff --git a/llvm/test/CodeGen/DirectX/pow.ll b/llvm/test/CodeGen/DirectX/pow.ll new file mode 100644 index 0000000000000000000000000000000000000000..25ce0fe731d0ba79f0d73c844af28b97cec1a1cf --- /dev/null +++ b/llvm/test/CodeGen/DirectX/pow.ll @@ -0,0 +1,29 @@ +; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK + +; Make sure dxil operation function calls for pow are generated. + +define noundef float @pow_float(float noundef %a, float noundef %b) { +entry: +; DOPCHECK: call float @dx.op.unary.f32(i32 23, float %a) +; EXPCHECK: call float @llvm.log2.f32(float %a) +; CHECK: fmul float %{{.*}}, %b +; DOPCHECK: call float @dx.op.unary.f32(i32 21, float %{{.*}}) +; EXPCHECK: call float @llvm.exp2.f32(float %{{.*}}) + %elt.pow = call float @llvm.pow.f32(float %a, float %b) + ret float %elt.pow +} + +define noundef half @pow_half(half noundef %a, half noundef %b) { +entry: +; DOPCHECK: call half @dx.op.unary.f16(i32 23, half %a) +; EXPCHECK: call half @llvm.log2.f16(half %a) +; CHECK: fmul half %{{.*}}, %b +; DOPCHECK: call half @dx.op.unary.f16(i32 21, half %{{.*}}) +; EXPCHECK: call half @llvm.exp2.f16(half %{{.*}}) + %elt.pow = call half @llvm.pow.f16(half %a, half %b) + ret half %elt.pow +} + +declare half @llvm.pow.f16(half,half) +declare float @llvm.pow.f32(float,float) diff --git a/llvm/test/CodeGen/DirectX/rcp.ll b/llvm/test/CodeGen/DirectX/rcp.ll new file mode 100644 index 0000000000000000000000000000000000000000..65abe832db53fea8df8985d60dcdb6b9e89d28c5 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rcp.ll @@ -0,0 +1,52 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for rcp are generated for float, double, and half. + +; CHECK-LABEL: rcp_float4 +; CHECK: fdiv <4 x float> <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>, %{{.*}} +define noundef <4 x float> @rcp_float4(<4 x float> noundef %p0) { +entry: + %p0.addr = alloca <4 x float>, align 16 + store <4 x float> %p0, ptr %p0.addr, align 16 + %0 = load <4 x float>, ptr %p0.addr, align 16 + %dx.rcp = call <4 x float> @llvm.dx.rcp.v4f32(<4 x float> %0) + ret <4 x float> %dx.rcp +} + +; CHECK-LABEL: rcp_double4 +; CHECK: fdiv <4 x double> <double 1.000000e+00, double 1.000000e+00, double 1.000000e+00, double 1.000000e+00>, %{{.*}} +define noundef <4 x double> @rcp_double4(<4 x double> noundef %p0) { +entry: + %p0.addr = alloca <4 x double>, align 16 + store <4 x double> %p0, ptr %p0.addr, align 16 + %0 = load <4 x double>, ptr %p0.addr, align 16 + %dx.rcp = call <4 x double> @llvm.dx.rcp.v4f64(<4 x double> %0) + ret <4 x double> %dx.rcp +} + +; CHECK-LABEL: rcp_half4 +; CHECK: fdiv <4 x half> <half 0xH3C00, half 0xH3C00, half 0xH3C00, half 0xH3C00>, %{{.*}} +define noundef <4 x half> @rcp_half4(<4 x half> noundef %p0) { +entry: + %p0.addr = alloca <4 x half>, align 16 + store <4 x half> %p0, ptr %p0.addr, align 16 + %0 = load <4 x half>, ptr %p0.addr, align 16 + %dx.rcp = call <4 x half> @llvm.dx.rcp.v4f16(<4 x half> %0) + ret <4 x half> %dx.rcp +} + +; CHECK-LABEL: rcp_half +; CHECK: fdiv half 0xH3C00, %{{.*}} +define noundef half @rcp_half(half noundef %p0) { +entry: + %p0.addr = alloca half, align 2 + store half %p0, ptr %p0.addr, align 2 + %0 = load half, ptr %p0.addr, align 2 + %dx.rcp = call half @llvm.dx.rcp.f16(half %0) + ret half %dx.rcp +} + +declare half @llvm.dx.rcp.f16(half) +declare <4 x half> @llvm.dx.rcp.v4f16(<4 x half>) +declare <4 x float> @llvm.dx.rcp.v4f32(<4 x float>) +declare <4 x double> @llvm.dx.rcp.v4f64(<4 x double>) diff --git a/llvm/test/CodeGen/DirectX/reversebits.ll b/llvm/test/CodeGen/DirectX/reversebits.ll new file mode 100644 index 0000000000000000000000000000000000000000..b6a7a1bc6152e3b3272c6eca6fec1309e2f7dbe0 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/reversebits.ll @@ -0,0 +1,31 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for reversebits are generated for all integer types. + +; Function Attrs: nounwind +define noundef i16 @test_bitreverse_short(i16 noundef %a) { +entry: +; CHECK:call i16 @dx.op.unary.i16(i32 30, i16 %{{.*}}) + %elt.bitreverse = call i16 @llvm.bitreverse.i16(i16 %a) + ret i16 %elt.bitreverse +} + +; Function Attrs: nounwind +define noundef i32 @test_bitreverse_int(i32 noundef %a) { +entry: +; CHECK:call i32 @dx.op.unary.i32(i32 30, i32 %{{.*}}) + %elt.bitreverse = call i32 @llvm.bitreverse.i32(i32 %a) + ret i32 %elt.bitreverse +} + +; Function Attrs: nounwind +define noundef i64 @test_bitreverse_long(i64 noundef %a) { +entry: +; CHECK:call i64 @dx.op.unary.i64(i32 30, i64 %{{.*}}) + %elt.bitreverse = call i64 @llvm.bitreverse.i64(i64 %a) + ret i64 %elt.bitreverse +} + +declare i16 @llvm.bitreverse.i16(i16) +declare i32 @llvm.bitreverse.i32(i32) +declare i64 @llvm.bitreverse.i64(i64) diff --git a/llvm/test/CodeGen/DirectX/round.ll b/llvm/test/CodeGen/DirectX/round.ll index 5d53a794b763a68d4f8ad33ba6ab5dcf8795c324..e0a3772ebca8fa2c9be6b6cce66a91bbcd9c1cd6 100644 --- a/llvm/test/CodeGen/DirectX/round.ll +++ b/llvm/test/CodeGen/DirectX/round.ll @@ -1,31 +1,22 @@ ; RUN: opt -S -dxil-op-lower < %s | FileCheck %s ; Make sure dxil operation function calls for round are generated for float and half. -; CHECK:call float @dx.op.unary.f32(i32 26, float %{{.*}}) -; CHECK:call half @dx.op.unary.f16(i32 26, half %{{.*}}) -target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" -target triple = "dxil-pc-shadermodel6.7-library" - -; Function Attrs: noinline nounwind optnone -define noundef float @round_float(float noundef %a) #0 { +; CHECK-LABEL: round_half +define noundef half @round_half(half noundef %a) { entry: - %a.addr = alloca float, align 4 - store float %a, ptr %a.addr, align 4 - %0 = load float, ptr %a.addr, align 4 - %elt.round = call float @llvm.round.f32(float %0) - ret float %elt.round +; CHECK: call half @dx.op.unary.f16(i32 26, half %{{.*}}) + %elt.roundeven = call half @llvm.roundeven.f16(half %a) + ret half %elt.roundeven } -; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn -declare float @llvm.round.f32(float) #1 - -; Function Attrs: noinline nounwind optnone -define noundef half @round_half(half noundef %a) #0 { +; CHECK-LABEL: round_float +define noundef float @round_float(float noundef %a) { entry: - %a.addr = alloca half, align 2 - store half %a, ptr %a.addr, align 2 - %0 = load half, ptr %a.addr, align 2 - %elt.round = call half @llvm.round.f16(half %0) - ret half %elt.round +; CHECK: call float @dx.op.unary.f32(i32 26, float %{{.*}}) + %elt.roundeven = call float @llvm.roundeven.f32(float %a) + ret float %elt.roundeven } + +declare half @llvm.roundeven.f16(half) +declare float @llvm.roundeven.f32(float) diff --git a/llvm/test/CodeGen/DirectX/round_error.ll b/llvm/test/CodeGen/DirectX/round_error.ll index 3bd87b2bbf02007916b67fe0a2e89c8a4ffd3970..2d27fbb5ee20de3a5fb45c46f4f50c1e9003a1e6 100644 --- a/llvm/test/CodeGen/DirectX/round_error.ll +++ b/llvm/test/CodeGen/DirectX/round_error.ll @@ -8,6 +8,6 @@ entry: %a.addr = alloca double, align 8 store double %a, ptr %a.addr, align 8 %0 = load double, ptr %a.addr, align 8 - %elt.round = call double @llvm.round.f64(double %0) - ret double %elt.round + %elt.roundeven = call double @llvm.roundeven.f64(double %0) + ret double %elt.roundeven } diff --git a/llvm/test/CodeGen/DirectX/rsqrt.ll b/llvm/test/CodeGen/DirectX/rsqrt.ll new file mode 100644 index 0000000000000000000000000000000000000000..52af0e62220b3e55aac13c0269d3ace5579ea3ef --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rsqrt.ll @@ -0,0 +1,28 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for rsqrt are generated for float and half. + +; CHECK-LABEL: rsqrt_float +; CHECK: call float @dx.op.unary.f32(i32 25, float %{{.*}}) +define noundef float @rsqrt_float(float noundef %a) { +entry: + %a.addr = alloca float, align 4 + store float %a, ptr %a.addr, align 4 + %0 = load float, ptr %a.addr, align 4 + %dx.rsqrt = call float @llvm.dx.rsqrt.f32(float %0) + ret float %dx.rsqrt +} + +; CHECK-LABEL: rsqrt_half +; CHECK: call half @dx.op.unary.f16(i32 25, half %{{.*}}) +define noundef half @rsqrt_half(half noundef %a) { +entry: + %a.addr = alloca half, align 2 + store half %a, ptr %a.addr, align 2 + %0 = load half, ptr %a.addr, align 2 + %dx.rsqrt = call half @llvm.dx.rsqrt.f16(half %0) + ret half %dx.rsqrt +} + +declare half @llvm.dx.rsqrt.f16(half) +declare float @llvm.dx.rsqrt.f32(float) diff --git a/llvm/test/CodeGen/DirectX/rsqrt_error.ll b/llvm/test/CodeGen/DirectX/rsqrt_error.ll new file mode 100644 index 0000000000000000000000000000000000000000..9cd5002c20f7ec2282025e5fcd4794d5cbdd7f8b --- /dev/null +++ b/llvm/test/CodeGen/DirectX/rsqrt_error.ll @@ -0,0 +1,14 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; DXIL operation rsqrt does not support double overload type +; CHECK: LLVM ERROR: Invalid Overload Type + +; Function Attrs: noinline nounwind optnone +define noundef double @rsqrt_double(double noundef %a) #0 { +entry: + %a.addr = alloca double, align 8 + store double %a, ptr %a.addr, align 8 + %0 = load double, ptr %a.addr, align 8 + %dx.rsqrt = call double @llvm.dx.rsqrt.f64(double %0) + ret double %dx.rsqrt +} diff --git a/llvm/test/CodeGen/DirectX/smax.ll b/llvm/test/CodeGen/DirectX/smax.ll new file mode 100644 index 0000000000000000000000000000000000000000..8b2406782c0938a8c5b2257a37069ca4c053c2bd --- /dev/null +++ b/llvm/test/CodeGen/DirectX/smax.ll @@ -0,0 +1,31 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for smax are generated for i16/i32/i64. + +; CHECK-LABEL:test_smax_i16 +define noundef i16 @test_smax_i16(i16 noundef %a, i16 noundef %b) { +entry: +; CHECK: call i16 @dx.op.binary.i16(i32 37, i16 %{{.*}}, i16 %{{.*}}) + %0 = call i16 @llvm.smax.i16(i16 %a, i16 %b) + ret i16 %0 +} + +; CHECK-LABEL:test_smax_i32 +define noundef i32 @test_smax_i32(i32 noundef %a, i32 noundef %b) { +entry: +; CHECK: call i32 @dx.op.binary.i32(i32 37, i32 %{{.*}}, i32 %{{.*}}) + %0 = call i32 @llvm.smax.i32(i32 %a, i32 %b) + ret i32 %0 +} + +; CHECK-LABEL:test_smax_i64 +define noundef i64 @test_smax_i64(i64 noundef %a, i64 noundef %b) { +entry: +; CHECK: call i64 @dx.op.binary.i64(i32 37, i64 %{{.*}}, i64 %{{.*}}) + %0 = call i64 @llvm.smax.i64(i64 %a, i64 %b) + ret i64 %0 +} + +declare i16 @llvm.smax.i16(i16, i16) +declare i32 @llvm.smax.i32(i32, i32) +declare i64 @llvm.smax.i64(i64, i64) diff --git a/llvm/test/CodeGen/DirectX/smin.ll b/llvm/test/CodeGen/DirectX/smin.ll new file mode 100644 index 0000000000000000000000000000000000000000..b2b40a1b6243358765056b961d238b5581302f39 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/smin.ll @@ -0,0 +1,31 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for smin are generated for i16/i32/i64. + +; CHECK-LABEL:test_smin_i16 +define noundef i16 @test_smin_i16(i16 noundef %a, i16 noundef %b) { +entry: +; CHECK: call i16 @dx.op.binary.i16(i32 38, i16 %{{.*}}, i16 %{{.*}}) + %0 = call i16 @llvm.smin.i16(i16 %a, i16 %b) + ret i16 %0 +} + +; CHECK-LABEL:test_smin_i32 +define noundef i32 @test_smin_i32(i32 noundef %a, i32 noundef %b) { +entry: +; CHECK: call i32 @dx.op.binary.i32(i32 38, i32 %{{.*}}, i32 %{{.*}}) + %0 = call i32 @llvm.smin.i32(i32 %a, i32 %b) + ret i32 %0 +} + +; CHECK-LABEL:test_smin_i64 +define noundef i64 @test_smin_i64(i64 noundef %a, i64 noundef %b) { +entry: +; CHECK: call i64 @dx.op.binary.i64(i32 38, i64 %{{.*}}, i64 %{{.*}}) + %0 = call i64 @llvm.smin.i64(i64 %a, i64 %b) + ret i64 %0 +} + +declare i16 @llvm.smin.i16(i16, i16) +declare i32 @llvm.smin.i32(i32, i32) +declare i64 @llvm.smin.i64(i64, i64) diff --git a/llvm/test/CodeGen/DirectX/sqrt.ll b/llvm/test/CodeGen/DirectX/sqrt.ll new file mode 100644 index 0000000000000000000000000000000000000000..76a572efd20557e136da713e7fcf6bf94a6076bc --- /dev/null +++ b/llvm/test/CodeGen/DirectX/sqrt.ll @@ -0,0 +1,20 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for sqrt are generated for float and half. + +define noundef float @sqrt_float(float noundef %a) #0 { +entry: +; CHECK:call float @dx.op.unary.f32(i32 24, float %{{.*}}) + %elt.sqrt = call float @llvm.sqrt.f32(float %a) + ret float %elt.sqrt +} + +define noundef half @sqrt_half(half noundef %a) #0 { +entry: +; CHECK:call half @dx.op.unary.f16(i32 24, half %{{.*}}) + %elt.sqrt = call half @llvm.sqrt.f16(half %a) + ret half %elt.sqrt +} + +declare half @llvm.sqrt.f16(half) +declare float @llvm.sqrt.f32(float) diff --git a/llvm/test/CodeGen/DirectX/sqrt_error.ll b/llvm/test/CodeGen/DirectX/sqrt_error.ll new file mode 100644 index 0000000000000000000000000000000000000000..fffa2e19b80fa986456508d651ef7ad558467d9b --- /dev/null +++ b/llvm/test/CodeGen/DirectX/sqrt_error.ll @@ -0,0 +1,10 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; DXIL operation sqrt does not support double overload type +; CHECK: LLVM ERROR: Invalid Overload Type + +define noundef double @sqrt_double(double noundef %a) { +entry: + %elt.sqrt = call double @llvm.sqrt.f64(double %a) + ret double %elt.sqrt +} diff --git a/llvm/test/CodeGen/DirectX/trunc.ll b/llvm/test/CodeGen/DirectX/trunc.ll new file mode 100644 index 0000000000000000000000000000000000000000..2072f28cef50a01cabd1e31aa55daaa6dc14bf74 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/trunc.ll @@ -0,0 +1,20 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for trunc are generated for float and half. + +define noundef float @trunc_float(float noundef %a) { +entry: +; CHECK:call float @dx.op.unary.f32(i32 29, float %{{.*}}) + %elt.trunc = call float @llvm.trunc.f32(float %a) + ret float %elt.trunc +} + +define noundef half @trunc_half(half noundef %a) { +entry: +; CHECK:call half @dx.op.unary.f16(i32 29, half %{{.*}}) + %elt.trunc = call half @llvm.trunc.f16(half %a) + ret half %elt.trunc +} + +declare half @llvm.trunc.f16(half) +declare float @llvm.trunc.f32(float) diff --git a/llvm/test/CodeGen/DirectX/trunc_error.ll b/llvm/test/CodeGen/DirectX/trunc_error.ll new file mode 100644 index 0000000000000000000000000000000000000000..751b0b94c280df7d00bbff204b03a06cb41046cb --- /dev/null +++ b/llvm/test/CodeGen/DirectX/trunc_error.ll @@ -0,0 +1,10 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; DXIL operation trunc does not support double overload type +; CHECK: LLVM ERROR: Invalid Overload Type + +define noundef double @trunc_double(double noundef %a) { +entry: + %elt.trunc = call double @llvm.trunc.f64(double %a) + ret double %elt.trunc +} diff --git a/llvm/test/CodeGen/DirectX/umax.ll b/llvm/test/CodeGen/DirectX/umax.ll index c7b6a87599279a621342dc6d8b554e5c638c7d29..be0f557fc8da69bda865b0369c32750c347b9107 100644 --- a/llvm/test/CodeGen/DirectX/umax.ll +++ b/llvm/test/CodeGen/DirectX/umax.ll @@ -1,30 +1,31 @@ ; RUN: opt -S -dxil-op-lower < %s | FileCheck %s -; Make sure dxil operation function calls for umax are generated for i32/i64. +; Make sure dxil operation function calls for umax are generated for i16/i32/i64. -target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" -target triple = "dxil-pc-shadermodel6.7-library" +; CHECK-LABEL:test_umax_i16 +define noundef i16 @test_umax_i16(i16 noundef %a, i16 noundef %b) { +entry: +; CHECK: call i16 @dx.op.binary.i16(i32 39, i16 %{{.*}}, i16 %{{.*}}) + %0 = call i16 @llvm.umax.i16(i16 %a, i16 %b) + ret i16 %0 +} ; CHECK-LABEL:test_umax_i32 -; Function Attrs: noinline nounwind optnone -define noundef i32 @test_umax_i32(i32 noundef %a, i32 noundef %b) #0 { +define noundef i32 @test_umax_i32(i32 noundef %a, i32 noundef %b) { entry: -; CHECK:call i32 @dx.op.binary.i32(i32 39, i32 %{{.*}}, i32 %{{.*}}) +; CHECK: call i32 @dx.op.binary.i32(i32 39, i32 %{{.*}}, i32 %{{.*}}) %0 = call i32 @llvm.umax.i32(i32 %a, i32 %b) ret i32 %0 } ; CHECK-LABEL:test_umax_i64 -define noundef i64 @test_umax_i64(i64 noundef %a, i64 noundef %b) #0 { +define noundef i64 @test_umax_i64(i64 noundef %a, i64 noundef %b) { entry: -; CHECK:call i64 @dx.op.binary.i64(i32 39, i64 %{{.*}}, i64 %{{.*}}) +; CHECK: call i64 @dx.op.binary.i64(i32 39, i64 %{{.*}}, i64 %{{.*}}) %0 = call i64 @llvm.umax.i64(i64 %a, i64 %b) ret i64 %0 } -; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn -declare i32 @llvm.umax.i32(i32, i32) #1 -declare i64 @llvm.umax.i64(i64, i64) #1 - -attributes #0 = { noinline nounwind } -attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn } +declare i16 @llvm.umax.i16(i16, i16) +declare i32 @llvm.umax.i32(i32, i32) +declare i64 @llvm.umax.i64(i64, i64) diff --git a/llvm/test/CodeGen/DirectX/umin.ll b/llvm/test/CodeGen/DirectX/umin.ll new file mode 100644 index 0000000000000000000000000000000000000000..5051c7117448921fe69f1b54ffc8bc73949db4c4 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/umin.ll @@ -0,0 +1,31 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for umin are generated for i16/i32/i64. + +; CHECK-LABEL:test_umin_i16 +define noundef i16 @test_umin_i16(i16 noundef %a, i16 noundef %b) { +entry: +; CHECK: call i16 @dx.op.binary.i16(i32 40, i16 %{{.*}}, i16 %{{.*}}) + %0 = call i16 @llvm.umin.i16(i16 %a, i16 %b) + ret i16 %0 +} + +; CHECK-LABEL:test_umin_i32 +define noundef i32 @test_umin_i32(i32 noundef %a, i32 noundef %b) { +entry: +; CHECK: call i32 @dx.op.binary.i32(i32 40, i32 %{{.*}}, i32 %{{.*}}) + %0 = call i32 @llvm.umin.i32(i32 %a, i32 %b) + ret i32 %0 +} + +; CHECK-LABEL:test_umin_i64 +define noundef i64 @test_umin_i64(i64 noundef %a, i64 noundef %b) { +entry: +; CHECK: call i64 @dx.op.binary.i64(i32 40, i64 %{{.*}}, i64 %{{.*}}) + %0 = call i64 @llvm.umin.i64(i64 %a, i64 %b) + ret i64 %0 +} + +declare i16 @llvm.umin.i16(i16, i16) +declare i32 @llvm.umin.i32(i32, i32) +declare i64 @llvm.umin.i64(i64, i64) diff --git a/llvm/test/CodeGen/Generic/ForceStackAlign.ll b/llvm/test/CodeGen/Generic/ForceStackAlign.ll index 2c35ad350f0473ed555695afb43b91af64f14180..7993b3eff65b684b603f2626469f2c2a9d645994 100644 --- a/llvm/test/CodeGen/Generic/ForceStackAlign.ll +++ b/llvm/test/CodeGen/Generic/ForceStackAlign.ll @@ -8,7 +8,7 @@ ; Stack realignment not supported. ; XFAIL: target=sparc{{.*}} -; NVPTX cannot select dynamic_stackalloc +; NVPTX can only select dynamic_stackalloc on sm_52+ and with ptx73+ ; XFAIL: target=nvptx{{.*}} define i32 @f(ptr %p) nounwind { diff --git a/llvm/test/CodeGen/Generic/allow-check.ll b/llvm/test/CodeGen/Generic/allow-check.ll new file mode 100644 index 0000000000000000000000000000000000000000..43dab6802acaac0e5e0f360d16badf7b2401126f --- /dev/null +++ b/llvm/test/CodeGen/Generic/allow-check.ll @@ -0,0 +1,31 @@ +; Avoid `!DL->isLittleEndian() && !CLI->enableBigEndian()` missmatch on PPC64BE. +; REQUIRES: host-byteorder-little-endian + +; -global-isel=1 is unsupported. +; XFAIL: target=nvptx{{.*}} +; XFAIL: target=sparc{{.*}} +; XFAIL: target=hexagon-{{.*}} + +; RUN: llc < %s -O3 -global-isel=0 -fast-isel=0 +; RUN: llc < %s -O3 -global-isel=1 -fast-isel=0 +; RUN: llc < %s -O3 -global-isel=0 -fast-isel=1 + +; RUN: llc < %s -O0 -global-isel=0 -fast-isel=0 +; RUN: llc < %s -O0 -global-isel=1 -fast-isel=0 +; RUN: llc < %s -O0 -global-isel=0 -fast-isel=1 + +define i1 @test_runtime() local_unnamed_addr { +entry: + %allow = call i1 @llvm.allow.runtime.check(metadata !"test_check") + ret i1 %allow +} + +declare i1 @llvm.allow.runtime.check(metadata) nounwind + +define i1 @test_ubsan() local_unnamed_addr { +entry: + %allow = call i1 @llvm.allow.ubsan.check(i8 7) + ret i1 %allow +} + +declare i1 @llvm.allow.ubsan.check(i8) nounwind diff --git a/llvm/test/CodeGen/Generic/builtin-hot.ll b/llvm/test/CodeGen/Generic/builtin-hot.ll deleted file mode 100644 index 449f58d3c0067581e969de49fa57781f46ada29d..0000000000000000000000000000000000000000 --- a/llvm/test/CodeGen/Generic/builtin-hot.ll +++ /dev/null @@ -1,19 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 -; RUN: llc -o - %s | FileCheck %s - -; REQUIRES: aarch64-registered-target - -target triple = "aarch64-linux" - -define i1 @test() { -; CHECK-LABEL: test: -; CHECK: // %bb.0: // %entry -; CHECK-NEXT: mov w0, wzr -; CHECK-NEXT: ret -entry: - %hot = call i1 @llvm.experimental.hot() - ret i1 %hot -} - -declare i1 @llvm.expect.hot() nounwind - diff --git a/llvm/test/CodeGen/Generic/gc-lowering.ll b/llvm/test/CodeGen/Generic/gc-lowering.ll new file mode 100644 index 0000000000000000000000000000000000000000..fa2e92ab495f4dc66b3c2ec290d2ad57beb927ed --- /dev/null +++ b/llvm/test/CodeGen/Generic/gc-lowering.ll @@ -0,0 +1,62 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -passes='require<collector-metadata>,function(gc-lowering)' < %s | FileCheck %s + +declare ptr @llvm_gc_allocate(i32) +declare void @llvm_gc_initialize(i32) + +declare void @llvm.gcroot(ptr, ptr) +declare void @llvm.gcwrite(ptr, ptr, ptr) + +define i32 @main() gc "shadow-stack" { +; CHECK-LABEL: define i32 @main() gc "shadow-stack" { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = alloca ptr, align 8 +; CHECK-NEXT: store ptr null, ptr [[A]], align 8 +; CHECK-NEXT: [[B:%.*]] = alloca ptr, align 8 +; CHECK-NEXT: store ptr null, ptr [[B]], align 8 +; CHECK-NEXT: call void @llvm_gc_initialize(i32 1048576) +; CHECK-NEXT: call void @llvm.gcroot(ptr [[A]], ptr null) +; CHECK-NEXT: [[APTR:%.*]] = call ptr @llvm_gc_allocate(i32 10) +; CHECK-NEXT: store ptr [[APTR]], ptr [[A]], align 8 +; CHECK-NEXT: call void @llvm.gcroot(ptr [[B]], ptr null) +; CHECK-NEXT: [[B_UPGRD_1:%.*]] = call ptr @llvm_gc_allocate(i32 8) +; CHECK-NEXT: store ptr [[B_UPGRD_1]], ptr [[B]], align 8 +; CHECK-NEXT: [[B_1:%.*]] = load ptr, ptr [[B]], align 8 +; CHECK-NEXT: [[A_1:%.*]] = load ptr, ptr [[A]], align 8 +; CHECK-NEXT: store ptr [[A_1]], ptr [[B_1]], align 8 +; CHECK-NEXT: ret i32 0 +; +entry: + %A = alloca ptr + %B = alloca ptr + + call void @llvm_gc_initialize(i32 1048576) ; Start with 1MB heap + + ;; ptr A; + call void @llvm.gcroot(ptr %A, ptr null) + + ;; A = gcalloc(10); + %Aptr = call ptr @llvm_gc_allocate(i32 10) + store ptr %Aptr, ptr %A + + ;; ptr B; + call void @llvm.gcroot(ptr %B, ptr null) + + ;; B = gcalloc(4); + %B.upgrd.1 = call ptr @llvm_gc_allocate(i32 8) + store ptr %B.upgrd.1, ptr %B + + ;; *B = A; + %B.1 = load ptr, ptr %B + %A.1 = load ptr, ptr %A + call void @llvm.gcwrite(ptr %A.1, ptr %B.upgrd.1, ptr %B.1) + + ret i32 0 +} + +define void @no_gc() { +; CHECK-LABEL: define void @no_gc() { +; CHECK-NEXT: ret void +; + ret void +} diff --git a/llvm/test/CodeGen/Hexagon/addrmode-immop.mir b/llvm/test/CodeGen/Hexagon/addrmode-immop.mir index 3069cbe5969d66fc9bbcbb69e51a3b4196c44650..1412d31f35ac107f110c09ea41ac33ad6e8ed6e1 100644 --- a/llvm/test/CodeGen/Hexagon/addrmode-immop.mir +++ b/llvm/test/CodeGen/Hexagon/addrmode-immop.mir @@ -15,7 +15,7 @@ ; Function Attrs: norecurse define void @f0() #0 { b0: - %v0 = load ptr, ptr getelementptr (i8, ptr getelementptr inbounds ({ [3 x ptr], [3 x ptr] }, ptr @g0, i32 0, inrange i32 0, i32 3), i32 sub (i32 ptrtoint (ptr @f1 to i32), i32 1)), align 4 + %v0 = load ptr, ptr getelementptr (i8, ptr getelementptr inbounds ({ [3 x ptr], [3 x ptr] }, ptr @g0, i32 0, i32 0, i32 3), i32 sub (i32 ptrtoint (ptr @f1 to i32), i32 1)), align 4 %v1 = call i32 %v0(ptr nonnull undef) unreachable } @@ -33,7 +33,7 @@ tracksRegLiveness: true body: | bb.0.b0: $r2 = A2_tfrsi @g0 + 12 - $r2 = L2_loadri_io killed $r2, @f1 - 1 :: (load (s32) from `ptr getelementptr (i8, ptr getelementptr inbounds ({ [3 x ptr], [3 x ptr] }, ptr @g0, i32 0, inrange i32 0, i32 3), i32 sub (i32 ptrtoint (ptr @f1 to i32), i32 1))`) + $r2 = L2_loadri_io killed $r2, @f1 - 1 :: (load (s32) from `ptr getelementptr (i8, ptr getelementptr inbounds ({ [3 x ptr], [3 x ptr] }, ptr @g0, i32 0, i32 0, i32 3), i32 sub (i32 ptrtoint (ptr @f1 to i32), i32 1))`) ADJCALLSTACKDOWN 0, 0, implicit-def $r29, implicit-def dead $r30, implicit $r31, implicit $r30, implicit $r29 PS_callr_nr killed $r2, hexagoncsr, implicit undef $r0, implicit-def $r29, implicit-def dead $r0 ADJCALLSTACKUP 0, 0, implicit-def dead $r29, implicit-def dead $r30, implicit-def dead $r31, implicit $r29 diff --git a/llvm/test/CodeGen/Hexagon/build-attributes.ll b/llvm/test/CodeGen/Hexagon/build-attributes.ll new file mode 100644 index 0000000000000000000000000000000000000000..48ee31a4d19bd6abfb3167e861015ae038c4b56d --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/build-attributes.ll @@ -0,0 +1,16 @@ +;; Generate build attributes from llc. + +; RUN: llc -mtriple=hexagon-unknown-elf \ +; RUN: -mattr=+hvxv73,+cabac,+v71,+hvx-ieee-fp,+hvx-length128b %s -o - | FileCheck %s + +; CHECK: .attribute 4, 71 // Tag_arch +; CHECK-NEXT: .attribute 5, 73 // Tag_hvx_arch +; CHECK-NEXT: .attribute 6, 1 // Tag_hvx_ieeefp +; CHECK-NEXT: .attribute 7, 1 // Tag_hvx_qfloat +; CHECK-NEXT: .attribute 8, 1 // Tag_zreg +; CHECK-NEXT: .attribute 10, 1 // Tag_cabac + +define i32 @addi(i32 %a) { + %1 = add i32 %a, 1 + ret i32 %1 +} \ No newline at end of file diff --git a/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse.ll b/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse.ll index 0771fda02cfb79c40af3cafe0550e4c0bc57209a..7ccee168918522a26fbca40762687037de37ef9a 100644 --- a/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse.ll +++ b/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -hexagon-vlcr | opt -passes=adce -S | FileCheck %s +; RUN: opt -mtriple=hexagon-- -passes='loop(hexagon-vlcr),adce' -S %s | FileCheck %s ; CHECK: %.hexagon.vlcr = tail call <32 x i32> @llvm.hexagon.V6.vmaxub.128B ; ModuleID = 'hexagon_vector_loop_carried_reuse.c' diff --git a/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_commutative.ll b/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_commutative.ll index 25afb9f1a137daea85b7f174bd22746b806f222e..532f7fd06793ac734fb93b04a6dc0621509b12c0 100644 --- a/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_commutative.ll +++ b/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_commutative.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -march=hexagon -hexagon-vlcr | opt -passes=adce -S | FileCheck %s +; RUN: opt -mtriple hexagon-- -passes='loop(hexagon-vlcr),adce' -S %s | FileCheck %s ; CHECK: %v32.hexagon.vlcr = tail call <32 x i32> @llvm.hexagon.V6.vmaxub.128B diff --git a/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_constant.ll b/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_constant.ll index 53973423732cdb13033138fbeb913696fcb8a91c..ecfcf53d9133084e65f1050b779a639c2040de58 100644 --- a/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_constant.ll +++ b/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_constant.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -hexagon-vlcr | opt -passes=adce -S | FileCheck %s +; RUN: opt -mtriple=hexagon-- -passes='loop(hexagon-vlcr),adce' -S %s | FileCheck %s ; CHECK-NOT: %.hexagon.vlcr ; ModuleID = 'hexagon_vector_loop_carried_reuse.c' diff --git a/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_invalid.ll b/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_invalid.ll index b440dba66f673a8888665a4a04348567bd082e1b..9872faeb3da029b84a253d27393c7b4978754240 100644 --- a/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_invalid.ll +++ b/llvm/test/CodeGen/Hexagon/hexagon_vector_loop_carried_reuse_invalid.ll @@ -1,4 +1,4 @@ -; RUN: opt -hexagon-vlcr < %s -S | FileCheck %s +; RUN: opt -mtriple=hexagon-- -passes=hexagon-vlcr -S %s | FileCheck %s ; Test that reuse doesn't occur due to two shufflevectors with different masks. diff --git a/llvm/test/CodeGen/Hexagon/hvx-loopidiom-memcpy.ll b/llvm/test/CodeGen/Hexagon/hvx-loopidiom-memcpy.ll index ab7bf1b4b0e865e3f31239b8aebf069d8774a580..c53e57800edd51eaa6ee115841e02dfed9faff28 100644 --- a/llvm/test/CodeGen/Hexagon/hvx-loopidiom-memcpy.ll +++ b/llvm/test/CodeGen/Hexagon/hvx-loopidiom-memcpy.ll @@ -1,4 +1,5 @@ ; RUN: opt -march=hexagon -hexagon-loop-idiom -S < %s | FileCheck %s +; RUN: opt -mtriple=hexagon-- -p hexagon-loop-idiom -disable-memcpy-idiom -S < %s | FileCheck %s ; Make sure we don't convert load/store loops into memcpy if the access type ; is a vector. Using vector instructions is generally better in such cases. diff --git a/llvm/test/CodeGen/Hexagon/livephysregs-regmask-clobber.mir b/llvm/test/CodeGen/Hexagon/livephysregs-regmask-clobber.mir index 8f1cb42b96a6fa780819cf2eeb24e2b48c4c14f5..52213070f535672325fff4c27b41b279d77735bc 100644 --- a/llvm/test/CodeGen/Hexagon/livephysregs-regmask-clobber.mir +++ b/llvm/test/CodeGen/Hexagon/livephysregs-regmask-clobber.mir @@ -17,6 +17,8 @@ name: f0 tracksRegLiveness: true +frameInfo: + adjustsStack: true stack: - { id: 0, offset: 0, size: 128, alignment: 128 } - { id: 1, offset: 128, size: 128, alignment: 128 } diff --git a/llvm/test/CodeGen/Hexagon/loop-idiom/hexagon-memmove1.ll b/llvm/test/CodeGen/Hexagon/loop-idiom/hexagon-memmove1.ll index c7110263c65809a6b70b08cd2f82a6bf2477e90a..5ace9e6ee486f195dbf0d6b5c5431cc57b171c35 100644 --- a/llvm/test/CodeGen/Hexagon/loop-idiom/hexagon-memmove1.ll +++ b/llvm/test/CodeGen/Hexagon/loop-idiom/hexagon-memmove1.ll @@ -1,6 +1,8 @@ ; Check for recognizing the "memmove" idiom. ; RUN: opt -hexagon-loop-idiom -S -mtriple hexagon-unknown-elf < %s \ ; RUN: | FileCheck %s +; RUN: opt -p hexagon-loop-idiom -S -mtriple hexagon-unknown-elf < %s \ +; RUN: | FileCheck %s ; CHECK: call void @llvm.memmove ; Function Attrs: norecurse nounwind diff --git a/llvm/test/CodeGen/Hexagon/loop-idiom/hexagon-memmove2.ll b/llvm/test/CodeGen/Hexagon/loop-idiom/hexagon-memmove2.ll index 234e4f56b5d818ca085c24ce6cd67640ce8e18e9..ed56a332f65795ed40bcf2f3266e3408108802dc 100644 --- a/llvm/test/CodeGen/Hexagon/loop-idiom/hexagon-memmove2.ll +++ b/llvm/test/CodeGen/Hexagon/loop-idiom/hexagon-memmove2.ll @@ -1,5 +1,7 @@ ; RUN: opt -hexagon-loop-idiom -S -mtriple hexagon-unknown-elf < %s \ ; RUN: | FileCheck %s +; RUN: opt -p hexagon-loop-idiom -S -mtriple hexagon-unknown-elf < %s \ +; RUN: | FileCheck %s define void @PR14241(ptr %s, i64 %size) #0 { ; Ensure that we don't form a memcpy for strided loops. Briefly, when we taught diff --git a/llvm/test/CodeGen/Hexagon/loop-idiom/lcssa.ll b/llvm/test/CodeGen/Hexagon/loop-idiom/lcssa.ll index 140c676175ea8e0be5449266a13e9fda007a83de..e5bcc2b9aebf6e50496fc78212ef29272abb2639 100644 --- a/llvm/test/CodeGen/Hexagon/loop-idiom/lcssa.ll +++ b/llvm/test/CodeGen/Hexagon/loop-idiom/lcssa.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -hexagon-loop-idiom < %s | opt -S -passes='loop(loop-deletion),gvn' +; RUN: opt -mtriple hexagon-- -S -passes='loop(hexagon-loop-idiom,loop-deletion),gvn' ; REQUIRES: asserts ; This tests that the HexagonLoopIdiom pass does not mark LCSSA information diff --git a/llvm/test/CodeGen/Hexagon/loop-idiom/memmove-rt-check.ll b/llvm/test/CodeGen/Hexagon/loop-idiom/memmove-rt-check.ll index 7a7d1d9b1a86593afae20abbb0aaebea4ef74326..78f0c9e36b556f8fc136b08f93c09416d5e47c08 100644 --- a/llvm/test/CodeGen/Hexagon/loop-idiom/memmove-rt-check.ll +++ b/llvm/test/CodeGen/Hexagon/loop-idiom/memmove-rt-check.ll @@ -1,4 +1,5 @@ ; RUN: opt -hexagon-loop-idiom -S < %s | FileCheck %s +; RUN: opt -p hexagon-loop-idiom -S < %s | FileCheck %s ; Make sure that we generate correct runtime checks. diff --git a/llvm/test/CodeGen/Hexagon/loop-idiom/nullptr-crash.ll b/llvm/test/CodeGen/Hexagon/loop-idiom/nullptr-crash.ll index 37e1bb6eb7df12de688f5276acdcfdfe71e2d7b7..ce02b62911c0bf8e7e2eb83b09d87ca4498fb734 100644 --- a/llvm/test/CodeGen/Hexagon/loop-idiom/nullptr-crash.ll +++ b/llvm/test/CodeGen/Hexagon/loop-idiom/nullptr-crash.ll @@ -1,4 +1,5 @@ ; RUN: opt -hexagon-loop-idiom -mtriple hexagon-unknown-elf < %s +; RUN: opt -p hexagon-loop-idiom -mtriple hexagon-unknown-elf < %s ; REQUIRES: asserts target triple = "hexagon" diff --git a/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-infinite-loop.ll b/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-infinite-loop.ll index 1934ced7e7aed28bab3d146329eb4c7b8058d091..74c02d63d54d32b186dba2d75e3dcad2e97aa775 100644 --- a/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-infinite-loop.ll +++ b/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-infinite-loop.ll @@ -1,4 +1,5 @@ ; RUN: opt -march=hexagon -hexagon-loop-idiom -S < %s | FileCheck %s +; RUN: opt -march=hexagon -p hexagon-loop-idiom -S < %s | FileCheck %s ; CHECK-LABEL: define void @fred ; Check that this test does not crash. diff --git a/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-long-loop.ll b/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-long-loop.ll index b25010f2a90fedc9b898ad1288d7a5b3929c3e9a..94b0c96c3d5178184c61cb26e1ca2f955402fe30 100644 --- a/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-long-loop.ll +++ b/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-long-loop.ll @@ -1,4 +1,5 @@ ; RUN: opt -march=hexagon -hexagon-loop-idiom -S < %s | FileCheck %s +; RUN: opt -march=hexagon -p hexagon-loop-idiom -S < %s | FileCheck %s ; ; The number of nested selects caused the simplification loop to take ; more than the maximum number of iterations. This caused the compiler diff --git a/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-shiftconv-fail.ll b/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-shiftconv-fail.ll index e4b2b5a298edf032b5066fa33201aa49beeaf78c..a00b1d5876ba89778528a8a972d237df97d18653 100644 --- a/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-shiftconv-fail.ll +++ b/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy-shiftconv-fail.ll @@ -1,4 +1,5 @@ ; RUN: opt -march=hexagon -hexagon-loop-idiom -S < %s | FileCheck %s +; RUN: opt -march=hexagon -p hexagon-loop-idiom -S < %s | FileCheck %s ; REQUIRES: asserts ; ; Check for sane output, this used to crash. diff --git a/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy.ll b/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy.ll index 781618e5890151b872a8b794186fad7925dc8e13..2461e1cfde8debcf27cc87411126a24eb8e3703a 100644 --- a/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy.ll +++ b/llvm/test/CodeGen/Hexagon/loop-idiom/pmpy.ll @@ -1,5 +1,7 @@ ; RUN: opt -hexagon-loop-idiom < %s -mtriple=hexagon-unknown-unknown -S \ ; RUN: | FileCheck %s +; RUN: opt -p hexagon-loop-idiom < %s -mtriple=hexagon-unknown-unknown -S \ +; RUN: | FileCheck %s target triple = "hexagon" diff --git a/llvm/test/CodeGen/Hexagon/regalloc-bad-undef.mir b/llvm/test/CodeGen/Hexagon/regalloc-bad-undef.mir index 67f4dd72ea0b2dbc3083644969e3506045a939fa..9468b18bf8e47e68ae7359517e85e3e911e4e06f 100644 --- a/llvm/test/CodeGen/Hexagon/regalloc-bad-undef.mir +++ b/llvm/test/CodeGen/Hexagon/regalloc-bad-undef.mir @@ -135,7 +135,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 0 - adjustsStack: false + adjustsStack: true hasCalls: true maxCallFrameSize: 0 hasOpaqueSPAdjustment: false diff --git a/llvm/test/CodeGen/LoongArch/lasx/intrinsic-permi.ll b/llvm/test/CodeGen/LoongArch/lasx/intrinsic-permi.ll index 92669d2e589558a03e524379d0d291a33a4602bf..0d9f9daabc44887efdda3375c15dd7e39490315a 100644 --- a/llvm/test/CodeGen/LoongArch/lasx/intrinsic-permi.ll +++ b/llvm/test/CodeGen/LoongArch/lasx/intrinsic-permi.ll @@ -36,33 +36,3 @@ entry: %res = call <32 x i8> @llvm.loongarch.lasx.xvpermi.q(<32 x i8> %va, <32 x i8> %vb, i32 1) ret <32 x i8> %res } - -define <32 x i8> @lasx_xvpermi_q_204(<32 x i8> %va, <32 x i8> %vb) nounwind { -; CHECK-LABEL: lasx_xvpermi_q_204: -; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xvpermi.q $xr0, $xr1, 0 -; CHECK-NEXT: ret -entry: - %res = call <32 x i8> @llvm.loongarch.lasx.xvpermi.q(<32 x i8> %va, <32 x i8> %vb, i32 204) - ret <32 x i8> %res -} - -define <32 x i8> @lasx_xvpermi_q_221(<32 x i8> %va, <32 x i8> %vb) nounwind { -; CHECK-LABEL: lasx_xvpermi_q_221: -; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xvpermi.q $xr0, $xr1, 17 -; CHECK-NEXT: ret -entry: - %res = call <32 x i8> @llvm.loongarch.lasx.xvpermi.q(<32 x i8> %va, <32 x i8> %vb, i32 221) - ret <32 x i8> %res -} - -define <32 x i8> @lasx_xvpermi_q_255(<32 x i8> %va, <32 x i8> %vb) nounwind { -; CHECK-LABEL: lasx_xvpermi_q_255: -; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xvpermi.q $xr0, $xr1, 51 -; CHECK-NEXT: ret -entry: - %res = call <32 x i8> @llvm.loongarch.lasx.xvpermi.q(<32 x i8> %va, <32 x i8> %vb, i32 255) - ret <32 x i8> %res -} diff --git a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insertelement.ll b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insertelement.ll index 25106b456d2f7a6dd9e775a4c431619ff1db9dac..6629d34405492cc732406a2b43ccf0e4e1b291b8 100644 --- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insertelement.ll +++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/insertelement.ll @@ -123,9 +123,10 @@ define void @insert_32xi8_idx(ptr %src, ptr %dst, i8 %in, i32 %idx) nounwind { ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr0, $a0, 0 ; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a3, 4, 0 -; CHECK-NEXT: st.b $a2, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a3, 31, 0 +; CHECK-NEXT: addi.d $a3, $sp, 0 +; CHECK-NEXT: bstrins.d $a3, $a0, 4, 0 +; CHECK-NEXT: st.b $a2, $a3, 0 ; CHECK-NEXT: xvld $xr0, $sp, 0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $fp, -64 @@ -149,9 +150,10 @@ define void @insert_16xi16_idx(ptr %src, ptr %dst, i16 %in, i32 %idx) nounwind { ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr0, $a0, 0 ; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a3, 4, 1 -; CHECK-NEXT: st.h $a2, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a3, 31, 0 +; CHECK-NEXT: addi.d $a3, $sp, 0 +; CHECK-NEXT: bstrins.d $a3, $a0, 4, 1 +; CHECK-NEXT: st.h $a2, $a3, 0 ; CHECK-NEXT: xvld $xr0, $sp, 0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $fp, -64 @@ -175,9 +177,10 @@ define void @insert_8xi32_idx(ptr %src, ptr %dst, i32 %in, i32 %idx) nounwind { ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr0, $a0, 0 ; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a3, 4, 2 -; CHECK-NEXT: st.w $a2, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a3, 31, 0 +; CHECK-NEXT: addi.d $a3, $sp, 0 +; CHECK-NEXT: bstrins.d $a3, $a0, 4, 2 +; CHECK-NEXT: st.w $a2, $a3, 0 ; CHECK-NEXT: xvld $xr0, $sp, 0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $fp, -64 @@ -201,9 +204,10 @@ define void @insert_4xi64_idx(ptr %src, ptr %dst, i64 %in, i32 %idx) nounwind { ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr0, $a0, 0 ; CHECK-NEXT: xvst $xr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a3, 4, 3 -; CHECK-NEXT: st.d $a2, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a3, 31, 0 +; CHECK-NEXT: addi.d $a3, $sp, 0 +; CHECK-NEXT: bstrins.d $a3, $a0, 4, 3 +; CHECK-NEXT: st.d $a2, $a3, 0 ; CHECK-NEXT: xvld $xr0, $sp, 0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $fp, -64 @@ -227,9 +231,10 @@ define void @insert_8xfloat_idx(ptr %src, ptr %dst, float %in, i32 %idx) nounwin ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr1, $a0, 0 ; CHECK-NEXT: xvst $xr1, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a2, 4, 2 -; CHECK-NEXT: fst.s $fa0, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a2, 31, 0 +; CHECK-NEXT: addi.d $a2, $sp, 0 +; CHECK-NEXT: bstrins.d $a2, $a0, 4, 2 +; CHECK-NEXT: fst.s $fa0, $a2, 0 ; CHECK-NEXT: xvld $xr0, $sp, 0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $fp, -64 @@ -253,9 +258,10 @@ define void @insert_4xdouble_idx(ptr %src, ptr %dst, double %in, i32 %idx) nounw ; CHECK-NEXT: bstrins.d $sp, $zero, 4, 0 ; CHECK-NEXT: xvld $xr1, $a0, 0 ; CHECK-NEXT: xvst $xr1, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a2, 4, 3 -; CHECK-NEXT: fst.d $fa0, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a2, 31, 0 +; CHECK-NEXT: addi.d $a2, $sp, 0 +; CHECK-NEXT: bstrins.d $a2, $a0, 4, 3 +; CHECK-NEXT: fst.d $fa0, $a2, 0 ; CHECK-NEXT: xvld $xr0, $sp, 0 ; CHECK-NEXT: xvst $xr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $fp, -64 diff --git a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/insertelement.ll b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/insertelement.ll index 7f232073ae129c4163784e28ae6c8c5be37134b0..19171b7d8ed7845ffcf1dcce910c2c4e2b052243 100644 --- a/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/insertelement.ll +++ b/llvm/test/CodeGen/LoongArch/lsx/ir-instruction/insertelement.ll @@ -87,9 +87,10 @@ define void @insert_16xi8_idx(ptr %src, ptr %dst, i8 %ins, i32 %idx) nounwind { ; CHECK-NEXT: addi.d $sp, $sp, -16 ; CHECK-NEXT: vld $vr0, $a0, 0 ; CHECK-NEXT: vst $vr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a3, 3, 0 -; CHECK-NEXT: st.b $a2, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a3, 31, 0 +; CHECK-NEXT: addi.d $a3, $sp, 0 +; CHECK-NEXT: bstrins.d $a3, $a0, 3, 0 +; CHECK-NEXT: st.b $a2, $a3, 0 ; CHECK-NEXT: vld $vr0, $sp, 0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $sp, 16 @@ -106,9 +107,10 @@ define void @insert_8xi16_idx(ptr %src, ptr %dst, i16 %ins, i32 %idx) nounwind { ; CHECK-NEXT: addi.d $sp, $sp, -16 ; CHECK-NEXT: vld $vr0, $a0, 0 ; CHECK-NEXT: vst $vr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a3, 3, 1 -; CHECK-NEXT: st.h $a2, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a3, 31, 0 +; CHECK-NEXT: addi.d $a3, $sp, 0 +; CHECK-NEXT: bstrins.d $a3, $a0, 3, 1 +; CHECK-NEXT: st.h $a2, $a3, 0 ; CHECK-NEXT: vld $vr0, $sp, 0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $sp, 16 @@ -125,9 +127,10 @@ define void @insert_4xi32_idx(ptr %src, ptr %dst, i32 %ins, i32 %idx) nounwind { ; CHECK-NEXT: addi.d $sp, $sp, -16 ; CHECK-NEXT: vld $vr0, $a0, 0 ; CHECK-NEXT: vst $vr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a3, 3, 2 -; CHECK-NEXT: st.w $a2, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a3, 31, 0 +; CHECK-NEXT: addi.d $a3, $sp, 0 +; CHECK-NEXT: bstrins.d $a3, $a0, 3, 2 +; CHECK-NEXT: st.w $a2, $a3, 0 ; CHECK-NEXT: vld $vr0, $sp, 0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $sp, 16 @@ -144,9 +147,10 @@ define void @insert_2xi64_idx(ptr %src, ptr %dst, i64 %ins, i32 %idx) nounwind { ; CHECK-NEXT: addi.d $sp, $sp, -16 ; CHECK-NEXT: vld $vr0, $a0, 0 ; CHECK-NEXT: vst $vr0, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a3, 3, 3 -; CHECK-NEXT: st.d $a2, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a3, 31, 0 +; CHECK-NEXT: addi.d $a3, $sp, 0 +; CHECK-NEXT: bstrins.d $a3, $a0, 3, 3 +; CHECK-NEXT: st.d $a2, $a3, 0 ; CHECK-NEXT: vld $vr0, $sp, 0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $sp, 16 @@ -163,9 +167,10 @@ define void @insert_4xfloat_idx(ptr %src, ptr %dst, float %ins, i32 %idx) nounwi ; CHECK-NEXT: addi.d $sp, $sp, -16 ; CHECK-NEXT: vld $vr1, $a0, 0 ; CHECK-NEXT: vst $vr1, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a2, 3, 2 -; CHECK-NEXT: fst.s $fa0, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a2, 31, 0 +; CHECK-NEXT: addi.d $a2, $sp, 0 +; CHECK-NEXT: bstrins.d $a2, $a0, 3, 2 +; CHECK-NEXT: fst.s $fa0, $a2, 0 ; CHECK-NEXT: vld $vr0, $sp, 0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $sp, 16 @@ -182,9 +187,10 @@ define void @insert_2xdouble_idx(ptr %src, ptr %dst, double %ins, i32 %idx) noun ; CHECK-NEXT: addi.d $sp, $sp, -16 ; CHECK-NEXT: vld $vr1, $a0, 0 ; CHECK-NEXT: vst $vr1, $sp, 0 -; CHECK-NEXT: addi.d $a0, $sp, 0 -; CHECK-NEXT: bstrins.d $a0, $a2, 3, 3 -; CHECK-NEXT: fst.d $fa0, $a0, 0 +; CHECK-NEXT: bstrpick.d $a0, $a2, 31, 0 +; CHECK-NEXT: addi.d $a2, $sp, 0 +; CHECK-NEXT: bstrins.d $a2, $a0, 3, 3 +; CHECK-NEXT: fst.d $fa0, $a2, 0 ; CHECK-NEXT: vld $vr0, $sp, 0 ; CHECK-NEXT: vst $vr0, $a1, 0 ; CHECK-NEXT: addi.d $sp, $sp, 16 diff --git a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid4.mir b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid4.mir deleted file mode 100644 index d66dd1044869225ae2a2e336ecfcd4772005b393..0000000000000000000000000000000000000000 --- a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid4.mir +++ /dev/null @@ -1,10 +0,0 @@ -# RUN: not llc -mtriple=aarch64-- -run-pass none -o /dev/null %s 2>&1 | FileCheck %s -# When a low-level type is 0 bits ---- -name: test_scalar_size_0 -body: | - bb.0: - liveins: $x0 - ; CHECK: [[@LINE+1]]:10: invalid size for scalar type - %0:_(s0) = G_IMPLICIT_DEF -... diff --git a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid6.mir b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid6.mir index 698568701fb1a47210a74d86b9d168a879141a9a..632e5fa81db111b03bf43fba1262bb53b4e7e839 100644 --- a/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid6.mir +++ b/llvm/test/CodeGen/MIR/AArch64/parse-low-level-type-invalid6.mir @@ -5,6 +5,6 @@ name: test_vector_element_size_0 body: | bb.0: liveins: $x0 - ; CHECK: [[@LINE+1]]:15: invalid size for scalar type + ; CHECK: [[@LINE+1]]:15: invalid size for scalar element in vector %0:_(<2 x s0>) = G_IMPLICIT_DEF ... diff --git a/llvm/test/CodeGen/MIR/AMDGPU/stack-id-assert.mir b/llvm/test/CodeGen/MIR/AMDGPU/stack-id-assert.mir index e40d1879399cef5f5f5ea201e832182c88f5ac01..9831f786b847d3a82d48bb9573c53a9800debe15 100644 --- a/llvm/test/CodeGen/MIR/AMDGPU/stack-id-assert.mir +++ b/llvm/test/CodeGen/MIR/AMDGPU/stack-id-assert.mir @@ -29,6 +29,8 @@ liveins: - { reg: '$vgpr0', virtual-reg: '' } - { reg: '$vgpr1', virtual-reg: '' } - { reg: '$vgpr2', virtual-reg: '' } +frameInfo: + adjustsStack: true stack: - { id: 0, name: '', type: spill-slot, offset: 0, size: 8, alignment: 4, stack-id: sgpr-spill, callee-saved-register: '', callee-saved-restored: true, diff --git a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/trap.mir b/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/trap.mir similarity index 55% rename from llvm/test/CodeGen/Mips/GlobalISel/legalizer/trap.mir rename to llvm/test/CodeGen/Mips/GlobalISel/instruction-select/trap.mir index 64388933fda88b66b8728494a3f4c88f3641270c..dc99ce8d7a099f0d000913068acdecf7ea525447 100644 --- a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/trap.mir +++ b/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/trap.mir @@ -1,5 +1,5 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py -# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32 +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32 --- | declare void @llvm.trap() @@ -9,12 +9,15 @@ --- name: f alignment: 4 +legalized: true +regBankSelected: true +tracksRegLiveness: true body: | bb.1 (%ir-block.0): ; MIPS32-LABEL: name: f ; MIPS32: TRAP - ; MIPS32: RetRA - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + ; MIPS32-NEXT: RetRA + G_TRAP RetRA ... diff --git a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/add.mir b/llvm/test/CodeGen/Mips/GlobalISel/legalizer/add.mir index 52352edbe33921af89b73ca928027bc3c8f69cbe..e471e1047caa211937d16b1fb7338e8f81e1cc3e 100644 --- a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/add.mir +++ b/llvm/test/CodeGen/Mips/GlobalISel/legalizer/add.mir @@ -220,10 +220,12 @@ body: | ; MIPS32-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $a3 ; MIPS32-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY3]], [[COPY1]] ; MIPS32-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), [[COPY1]] + ; MIPS32-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) ; MIPS32-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[COPY2]], [[COPY]] ; MIPS32-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ADD1]], [[ICMP]] - ; MIPS32-NEXT: $v0 = COPY [[ADD2]](s32) - ; MIPS32-NEXT: $v1 = COPY [[ADD]](s32) + ; MIPS32-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY [[ADD2]](s32) + ; MIPS32-NEXT: $v0 = COPY [[COPY5]](s32) + ; MIPS32-NEXT: $v1 = COPY [[COPY4]](s32) ; MIPS32-NEXT: RetRA implicit $v0, implicit $v1 %2:_(s32) = COPY $a0 %3:_(s32) = COPY $a1 @@ -268,6 +270,7 @@ body: | ; MIPS32-NEXT: [[LOAD3:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX3]](p0) :: (load (s32) from %fixed-stack.3) ; MIPS32-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[LOAD]], [[COPY]] ; MIPS32-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), [[COPY]] + ; MIPS32-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) ; MIPS32-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[LOAD1]], [[COPY1]] ; MIPS32-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD1]](s32), [[LOAD1]] ; MIPS32-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ADD1]], [[ICMP]] @@ -275,6 +278,7 @@ body: | ; MIPS32-NEXT: [[ICMP2:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[ADD2]](s32), [[C]] ; MIPS32-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ICMP2]], [[ICMP]] ; MIPS32-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[ICMP1]], [[AND]] + ; MIPS32-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY [[ADD2]](s32) ; MIPS32-NEXT: [[ADD3:%[0-9]+]]:_(s32) = G_ADD [[LOAD2]], [[COPY2]] ; MIPS32-NEXT: [[ICMP3:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD3]](s32), [[LOAD2]] ; MIPS32-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 @@ -283,13 +287,15 @@ body: | ; MIPS32-NEXT: [[ICMP4:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[ADD4]](s32), [[C]] ; MIPS32-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[ICMP4]], [[OR]] ; MIPS32-NEXT: [[OR1:%[0-9]+]]:_(s32) = G_OR [[ICMP3]], [[AND2]] + ; MIPS32-NEXT: [[COPY6:%[0-9]+]]:_(s32) = COPY [[ADD4]](s32) ; MIPS32-NEXT: [[ADD5:%[0-9]+]]:_(s32) = G_ADD [[LOAD3]], [[COPY3]] ; MIPS32-NEXT: [[AND3:%[0-9]+]]:_(s32) = G_AND [[OR1]], [[C1]] ; MIPS32-NEXT: [[ADD6:%[0-9]+]]:_(s32) = G_ADD [[ADD5]], [[AND3]] - ; MIPS32-NEXT: $v0 = COPY [[ADD]](s32) - ; MIPS32-NEXT: $v1 = COPY [[ADD2]](s32) - ; MIPS32-NEXT: $a0 = COPY [[ADD4]](s32) - ; MIPS32-NEXT: $a1 = COPY [[ADD6]](s32) + ; MIPS32-NEXT: [[COPY7:%[0-9]+]]:_(s32) = COPY [[ADD6]](s32) + ; MIPS32-NEXT: $v0 = COPY [[COPY4]](s32) + ; MIPS32-NEXT: $v1 = COPY [[COPY5]](s32) + ; MIPS32-NEXT: $a0 = COPY [[COPY6]](s32) + ; MIPS32-NEXT: $a1 = COPY [[COPY7]](s32) ; MIPS32-NEXT: RetRA implicit $v0, implicit $v1, implicit $a0, implicit $a1 %2:_(s32) = COPY $a0 %3:_(s32) = COPY $a1 @@ -331,10 +337,11 @@ body: | ; MIPS32-NEXT: [[COPY3:%[0-9]+]]:_(p0) = COPY $a3 ; MIPS32-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[COPY1]] ; MIPS32-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), [[COPY1]] + ; MIPS32-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) ; MIPS32-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 ; MIPS32-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ICMP]], [[C]] ; MIPS32-NEXT: G_STORE [[AND]](s32), [[COPY3]](p0) :: (store (s8) into %ir.pcarry_flag) - ; MIPS32-NEXT: G_STORE [[ADD]](s32), [[COPY2]](p0) :: (store (s32) into %ir.padd) + ; MIPS32-NEXT: G_STORE [[COPY4]](s32), [[COPY2]](p0) :: (store (s32) into %ir.padd) ; MIPS32-NEXT: RetRA %0:_(s32) = COPY $a0 %1:_(s32) = COPY $a1 diff --git a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/ctpop.mir b/llvm/test/CodeGen/Mips/GlobalISel/legalizer/ctpop.mir index 136c03946f367215df0c7393e44531093c0f41aa..f518e9ec9e5897d6a2f4da275658591eaea082ad 100644 --- a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/ctpop.mir +++ b/llvm/test/CodeGen/Mips/GlobalISel/legalizer/ctpop.mir @@ -10,29 +10,30 @@ body: | ; MIPS32-LABEL: name: ctpop_i32 ; MIPS32: liveins: $a0 - ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 - ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 - ; MIPS32: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[COPY]], [[C]](s32) - ; MIPS32: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1431655765 - ; MIPS32: [[AND:%[0-9]+]]:_(s32) = G_AND [[LSHR]], [[C1]] - ; MIPS32: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[AND]] - ; MIPS32: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 - ; MIPS32: [[LSHR1:%[0-9]+]]:_(s32) = G_LSHR [[SUB]], [[C2]](s32) - ; MIPS32: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 858993459 - ; MIPS32: [[AND1:%[0-9]+]]:_(s32) = G_AND [[LSHR1]], [[C3]] - ; MIPS32: [[AND2:%[0-9]+]]:_(s32) = G_AND [[SUB]], [[C3]] - ; MIPS32: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[AND1]], [[AND2]] - ; MIPS32: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 - ; MIPS32: [[LSHR2:%[0-9]+]]:_(s32) = G_LSHR [[ADD]], [[C4]](s32) - ; MIPS32: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[LSHR2]], [[ADD]] - ; MIPS32: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 - ; MIPS32: [[AND3:%[0-9]+]]:_(s32) = G_AND [[ADD1]], [[C5]] - ; MIPS32: [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 - ; MIPS32: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND3]], [[C6]] - ; MIPS32: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 - ; MIPS32: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C7]](s32) - ; MIPS32: $v0 = COPY [[LSHR3]](s32) - ; MIPS32: RetRA implicit $v0 + ; MIPS32-NEXT: {{ $}} + ; MIPS32-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; MIPS32-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[COPY]], [[C]](s32) + ; MIPS32-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1431655765 + ; MIPS32-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[LSHR]], [[C1]] + ; MIPS32-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[AND]] + ; MIPS32-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 + ; MIPS32-NEXT: [[LSHR1:%[0-9]+]]:_(s32) = G_LSHR [[SUB]], [[C2]](s32) + ; MIPS32-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 858993459 + ; MIPS32-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[LSHR1]], [[C3]] + ; MIPS32-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[SUB]], [[C3]] + ; MIPS32-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[AND1]], [[AND2]] + ; MIPS32-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 + ; MIPS32-NEXT: [[LSHR2:%[0-9]+]]:_(s32) = G_LSHR [[ADD]], [[C4]](s32) + ; MIPS32-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[LSHR2]], [[ADD]] + ; MIPS32-NEXT: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 + ; MIPS32-NEXT: [[AND3:%[0-9]+]]:_(s32) = G_AND [[ADD1]], [[C5]] + ; MIPS32-NEXT: [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 + ; MIPS32-NEXT: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; MIPS32-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND3]], [[C6]] + ; MIPS32-NEXT: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C7]](s32) + ; MIPS32-NEXT: $v0 = COPY [[LSHR3]](s32) + ; MIPS32-NEXT: RetRA implicit $v0 %0:_(s32) = COPY $a0 %1:_(s32) = G_CTPOP %0(s32) $v0 = COPY %1(s32) @@ -49,45 +50,46 @@ body: | ; MIPS32-LABEL: name: ctpop_i64 ; MIPS32: liveins: $a0, $a1 - ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 - ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 - ; MIPS32: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 - ; MIPS32: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[COPY]], [[C]](s32) - ; MIPS32: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1431655765 - ; MIPS32: [[AND:%[0-9]+]]:_(s32) = G_AND [[LSHR]], [[C1]] - ; MIPS32: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[AND]] - ; MIPS32: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 - ; MIPS32: [[LSHR1:%[0-9]+]]:_(s32) = G_LSHR [[SUB]], [[C2]](s32) - ; MIPS32: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 858993459 - ; MIPS32: [[AND1:%[0-9]+]]:_(s32) = G_AND [[LSHR1]], [[C3]] - ; MIPS32: [[AND2:%[0-9]+]]:_(s32) = G_AND [[SUB]], [[C3]] - ; MIPS32: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[AND1]], [[AND2]] - ; MIPS32: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 - ; MIPS32: [[LSHR2:%[0-9]+]]:_(s32) = G_LSHR [[ADD]], [[C4]](s32) - ; MIPS32: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[LSHR2]], [[ADD]] - ; MIPS32: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 - ; MIPS32: [[AND3:%[0-9]+]]:_(s32) = G_AND [[ADD1]], [[C5]] - ; MIPS32: [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 - ; MIPS32: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND3]], [[C6]] - ; MIPS32: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 - ; MIPS32: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C7]](s32) - ; MIPS32: [[LSHR4:%[0-9]+]]:_(s32) = G_LSHR [[COPY1]], [[C]](s32) - ; MIPS32: [[AND4:%[0-9]+]]:_(s32) = G_AND [[LSHR4]], [[C1]] - ; MIPS32: [[SUB1:%[0-9]+]]:_(s32) = G_SUB [[COPY1]], [[AND4]] - ; MIPS32: [[LSHR5:%[0-9]+]]:_(s32) = G_LSHR [[SUB1]], [[C2]](s32) - ; MIPS32: [[AND5:%[0-9]+]]:_(s32) = G_AND [[LSHR5]], [[C3]] - ; MIPS32: [[AND6:%[0-9]+]]:_(s32) = G_AND [[SUB1]], [[C3]] - ; MIPS32: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[AND5]], [[AND6]] - ; MIPS32: [[LSHR6:%[0-9]+]]:_(s32) = G_LSHR [[ADD2]], [[C4]](s32) - ; MIPS32: [[ADD3:%[0-9]+]]:_(s32) = G_ADD [[LSHR6]], [[ADD2]] - ; MIPS32: [[AND7:%[0-9]+]]:_(s32) = G_AND [[ADD3]], [[C5]] - ; MIPS32: [[MUL1:%[0-9]+]]:_(s32) = G_MUL [[AND7]], [[C6]] - ; MIPS32: [[LSHR7:%[0-9]+]]:_(s32) = G_LSHR [[MUL1]], [[C7]](s32) - ; MIPS32: [[ADD4:%[0-9]+]]:_(s32) = G_ADD [[LSHR7]], [[LSHR3]] - ; MIPS32: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 - ; MIPS32: $v0 = COPY [[ADD4]](s32) - ; MIPS32: $v1 = COPY [[C8]](s32) - ; MIPS32: RetRA implicit $v0, implicit $v1 + ; MIPS32-NEXT: {{ $}} + ; MIPS32-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $a0 + ; MIPS32-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1 + ; MIPS32-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; MIPS32-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[COPY]], [[C]](s32) + ; MIPS32-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1431655765 + ; MIPS32-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[LSHR]], [[C1]] + ; MIPS32-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[AND]] + ; MIPS32-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 + ; MIPS32-NEXT: [[LSHR1:%[0-9]+]]:_(s32) = G_LSHR [[SUB]], [[C2]](s32) + ; MIPS32-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 858993459 + ; MIPS32-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[LSHR1]], [[C3]] + ; MIPS32-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[SUB]], [[C3]] + ; MIPS32-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[AND1]], [[AND2]] + ; MIPS32-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 + ; MIPS32-NEXT: [[LSHR2:%[0-9]+]]:_(s32) = G_LSHR [[ADD]], [[C4]](s32) + ; MIPS32-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[LSHR2]], [[ADD]] + ; MIPS32-NEXT: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 + ; MIPS32-NEXT: [[AND3:%[0-9]+]]:_(s32) = G_AND [[ADD1]], [[C5]] + ; MIPS32-NEXT: [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 + ; MIPS32-NEXT: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; MIPS32-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND3]], [[C6]] + ; MIPS32-NEXT: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C7]](s32) + ; MIPS32-NEXT: [[LSHR4:%[0-9]+]]:_(s32) = G_LSHR [[COPY1]], [[C]](s32) + ; MIPS32-NEXT: [[AND4:%[0-9]+]]:_(s32) = G_AND [[LSHR4]], [[C1]] + ; MIPS32-NEXT: [[SUB1:%[0-9]+]]:_(s32) = G_SUB [[COPY1]], [[AND4]] + ; MIPS32-NEXT: [[LSHR5:%[0-9]+]]:_(s32) = G_LSHR [[SUB1]], [[C2]](s32) + ; MIPS32-NEXT: [[AND5:%[0-9]+]]:_(s32) = G_AND [[LSHR5]], [[C3]] + ; MIPS32-NEXT: [[AND6:%[0-9]+]]:_(s32) = G_AND [[SUB1]], [[C3]] + ; MIPS32-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[AND5]], [[AND6]] + ; MIPS32-NEXT: [[LSHR6:%[0-9]+]]:_(s32) = G_LSHR [[ADD2]], [[C4]](s32) + ; MIPS32-NEXT: [[ADD3:%[0-9]+]]:_(s32) = G_ADD [[LSHR6]], [[ADD2]] + ; MIPS32-NEXT: [[AND7:%[0-9]+]]:_(s32) = G_AND [[ADD3]], [[C5]] + ; MIPS32-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL [[AND7]], [[C6]] + ; MIPS32-NEXT: [[LSHR7:%[0-9]+]]:_(s32) = G_LSHR [[MUL1]], [[C7]](s32) + ; MIPS32-NEXT: [[ADD4:%[0-9]+]]:_(s32) = G_ADD [[LSHR7]], [[LSHR3]] + ; MIPS32-NEXT: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; MIPS32-NEXT: $v0 = COPY [[ADD4]](s32) + ; MIPS32-NEXT: $v1 = COPY [[C8]](s32) + ; MIPS32-NEXT: RetRA implicit $v0, implicit $v1 %1:_(s32) = COPY $a0 %2:_(s32) = COPY $a1 %0:_(s64) = G_MERGE_VALUES %1(s32), %2(s32) diff --git a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/cttz.mir b/llvm/test/CodeGen/Mips/GlobalISel/legalizer/cttz.mir index 3e7bcdc39d5d9020294a646397798ce1145c32a9..a06bb6da45d23f9fb6d1e3cda117db78372aaefb 100644 --- a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/cttz.mir +++ b/llvm/test/CodeGen/Mips/GlobalISel/legalizer/cttz.mir @@ -139,9 +139,11 @@ body: | ; MIPS32-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP]](s32), [[ADD1]], [[SUB1]] ; MIPS32-NEXT: [[ADD3:%[0-9]+]]:_(s32) = G_ADD [[SELECT]], [[C]] ; MIPS32-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD3]](s32), [[C]] + ; MIPS32-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY [[ADD3]](s32) ; MIPS32-NEXT: [[ADD4:%[0-9]+]]:_(s32) = G_ADD [[C1]], [[C1]] ; MIPS32-NEXT: [[ADD5:%[0-9]+]]:_(s32) = G_ADD [[ADD4]], [[ICMP1]] - ; MIPS32-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[ADD3]](s32), [[ADD5]](s32) + ; MIPS32-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY [[ADD5]](s32) + ; MIPS32-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY2]](s32), [[COPY3]](s32) ; MIPS32-NEXT: [[XOR2:%[0-9]+]]:_(s32) = G_XOR [[COPY]], [[C1]] ; MIPS32-NEXT: [[XOR3:%[0-9]+]]:_(s32) = G_XOR [[COPY1]], [[C1]] ; MIPS32-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[XOR2]], [[XOR3]] diff --git a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/mul.mir b/llvm/test/CodeGen/Mips/GlobalISel/legalizer/mul.mir index 7ad286b952cb1202e7a2eb8d957f5534ef668630..674d7b68bfae6c4f310e7159a92561661bdbd8d1 100644 --- a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/mul.mir +++ b/llvm/test/CodeGen/Mips/GlobalISel/legalizer/mul.mir @@ -275,8 +275,10 @@ body: | ; MIPS32-NEXT: [[UMULH:%[0-9]+]]:_(s32) = G_UMULH [[LOAD]], [[COPY]] ; MIPS32-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[MUL1]], [[MUL2]] ; MIPS32-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), [[MUL2]] - ; MIPS32-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ADD]], [[UMULH]] + ; MIPS32-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) + ; MIPS32-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[COPY4]], [[UMULH]] ; MIPS32-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD1]](s32), [[UMULH]] + ; MIPS32-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY [[ADD1]](s32) ; MIPS32-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ICMP]], [[ICMP1]] ; MIPS32-NEXT: [[MUL3:%[0-9]+]]:_(s32) = G_MUL [[LOAD2]], [[COPY]] ; MIPS32-NEXT: [[MUL4:%[0-9]+]]:_(s32) = G_MUL [[LOAD1]], [[COPY1]] @@ -285,17 +287,22 @@ body: | ; MIPS32-NEXT: [[UMULH2:%[0-9]+]]:_(s32) = G_UMULH [[LOAD]], [[COPY1]] ; MIPS32-NEXT: [[ADD3:%[0-9]+]]:_(s32) = G_ADD [[MUL3]], [[MUL4]] ; MIPS32-NEXT: [[ICMP2:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD3]](s32), [[MUL4]] - ; MIPS32-NEXT: [[ADD4:%[0-9]+]]:_(s32) = G_ADD [[ADD3]], [[MUL5]] + ; MIPS32-NEXT: [[COPY6:%[0-9]+]]:_(s32) = COPY [[ADD3]](s32) + ; MIPS32-NEXT: [[ADD4:%[0-9]+]]:_(s32) = G_ADD [[COPY6]], [[MUL5]] ; MIPS32-NEXT: [[ICMP3:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD4]](s32), [[MUL5]] + ; MIPS32-NEXT: [[COPY7:%[0-9]+]]:_(s32) = COPY [[ADD4]](s32) ; MIPS32-NEXT: [[ADD5:%[0-9]+]]:_(s32) = G_ADD [[ICMP2]], [[ICMP3]] - ; MIPS32-NEXT: [[ADD6:%[0-9]+]]:_(s32) = G_ADD [[ADD4]], [[UMULH1]] + ; MIPS32-NEXT: [[ADD6:%[0-9]+]]:_(s32) = G_ADD [[COPY7]], [[UMULH1]] ; MIPS32-NEXT: [[ICMP4:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD6]](s32), [[UMULH1]] + ; MIPS32-NEXT: [[COPY8:%[0-9]+]]:_(s32) = COPY [[ADD6]](s32) ; MIPS32-NEXT: [[ADD7:%[0-9]+]]:_(s32) = G_ADD [[ADD5]], [[ICMP4]] - ; MIPS32-NEXT: [[ADD8:%[0-9]+]]:_(s32) = G_ADD [[ADD6]], [[UMULH2]] + ; MIPS32-NEXT: [[ADD8:%[0-9]+]]:_(s32) = G_ADD [[COPY8]], [[UMULH2]] ; MIPS32-NEXT: [[ICMP5:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD8]](s32), [[UMULH2]] + ; MIPS32-NEXT: [[COPY9:%[0-9]+]]:_(s32) = COPY [[ADD8]](s32) ; MIPS32-NEXT: [[ADD9:%[0-9]+]]:_(s32) = G_ADD [[ADD7]], [[ICMP5]] - ; MIPS32-NEXT: [[ADD10:%[0-9]+]]:_(s32) = G_ADD [[ADD8]], [[ADD2]] + ; MIPS32-NEXT: [[ADD10:%[0-9]+]]:_(s32) = G_ADD [[COPY9]], [[ADD2]] ; MIPS32-NEXT: [[ICMP6:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD10]](s32), [[ADD2]] + ; MIPS32-NEXT: [[COPY10:%[0-9]+]]:_(s32) = COPY [[ADD10]](s32) ; MIPS32-NEXT: [[ADD11:%[0-9]+]]:_(s32) = G_ADD [[ADD9]], [[ICMP6]] ; MIPS32-NEXT: [[MUL6:%[0-9]+]]:_(s32) = G_MUL [[LOAD3]], [[COPY]] ; MIPS32-NEXT: [[MUL7:%[0-9]+]]:_(s32) = G_MUL [[LOAD2]], [[COPY1]] @@ -312,8 +319,8 @@ body: | ; MIPS32-NEXT: [[ADD17:%[0-9]+]]:_(s32) = G_ADD [[ADD16]], [[UMULH5]] ; MIPS32-NEXT: [[ADD18:%[0-9]+]]:_(s32) = G_ADD [[ADD17]], [[ADD11]] ; MIPS32-NEXT: $v0 = COPY [[MUL]](s32) - ; MIPS32-NEXT: $v1 = COPY [[ADD1]](s32) - ; MIPS32-NEXT: $a0 = COPY [[ADD10]](s32) + ; MIPS32-NEXT: $v1 = COPY [[COPY5]](s32) + ; MIPS32-NEXT: $a0 = COPY [[COPY10]](s32) ; MIPS32-NEXT: $a1 = COPY [[ADD18]](s32) ; MIPS32-NEXT: RetRA implicit $v0, implicit $v1, implicit $a0, implicit $a1 %2:_(s32) = COPY $a0 @@ -359,23 +366,28 @@ body: | ; MIPS32-NEXT: [[UMULH:%[0-9]+]]:_(s32) = G_UMULH [[COPY2]], [[COPY]] ; MIPS32-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[MUL]], [[MUL1]] ; MIPS32-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), [[MUL1]] - ; MIPS32-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ADD]], [[UMULH]] + ; MIPS32-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) + ; MIPS32-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[COPY4]], [[UMULH]] ; MIPS32-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD1]](s32), [[UMULH]] + ; MIPS32-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY [[ADD1]](s32) ; MIPS32-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ICMP]], [[ICMP1]] ; MIPS32-NEXT: [[MUL2:%[0-9]+]]:_(s32) = G_MUL [[COPY3]], [[COPY1]] ; MIPS32-NEXT: [[UMULH1:%[0-9]+]]:_(s32) = G_UMULH [[COPY3]], [[COPY]] ; MIPS32-NEXT: [[UMULH2:%[0-9]+]]:_(s32) = G_UMULH [[COPY2]], [[COPY1]] ; MIPS32-NEXT: [[ADD3:%[0-9]+]]:_(s32) = G_ADD [[MUL2]], [[UMULH1]] ; MIPS32-NEXT: [[ICMP2:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD3]](s32), [[UMULH1]] - ; MIPS32-NEXT: [[ADD4:%[0-9]+]]:_(s32) = G_ADD [[ADD3]], [[UMULH2]] + ; MIPS32-NEXT: [[COPY6:%[0-9]+]]:_(s32) = COPY [[ADD3]](s32) + ; MIPS32-NEXT: [[ADD4:%[0-9]+]]:_(s32) = G_ADD [[COPY6]], [[UMULH2]] ; MIPS32-NEXT: [[ICMP3:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD4]](s32), [[UMULH2]] + ; MIPS32-NEXT: [[COPY7:%[0-9]+]]:_(s32) = COPY [[ADD4]](s32) ; MIPS32-NEXT: [[ADD5:%[0-9]+]]:_(s32) = G_ADD [[ICMP2]], [[ICMP3]] - ; MIPS32-NEXT: [[ADD6:%[0-9]+]]:_(s32) = G_ADD [[ADD4]], [[ADD2]] + ; MIPS32-NEXT: [[ADD6:%[0-9]+]]:_(s32) = G_ADD [[COPY7]], [[ADD2]] ; MIPS32-NEXT: [[ICMP4:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD6]](s32), [[ADD2]] + ; MIPS32-NEXT: [[COPY8:%[0-9]+]]:_(s32) = COPY [[ADD6]](s32) ; MIPS32-NEXT: [[ADD7:%[0-9]+]]:_(s32) = G_ADD [[ADD5]], [[ICMP4]] ; MIPS32-NEXT: [[UMULH3:%[0-9]+]]:_(s32) = G_UMULH [[COPY3]], [[COPY1]] ; MIPS32-NEXT: [[ADD8:%[0-9]+]]:_(s32) = G_ADD [[UMULH3]], [[ADD7]] - ; MIPS32-NEXT: $v0 = COPY [[ADD6]](s32) + ; MIPS32-NEXT: $v0 = COPY [[COPY8]](s32) ; MIPS32-NEXT: $v1 = COPY [[ADD8]](s32) ; MIPS32-NEXT: RetRA implicit $v0, implicit $v1 %2:_(s32) = COPY $a0 diff --git a/llvm/test/CodeGen/Mips/atomic-min-max.ll b/llvm/test/CodeGen/Mips/atomic-min-max.ll index bc3643f3947a406acf011bb977f64b7307365d54..a96581bdb39a4c7a0559c6027d7d188781a72efb 100644 --- a/llvm/test/CodeGen/Mips/atomic-min-max.ll +++ b/llvm/test/CodeGen/Mips/atomic-min-max.ll @@ -2146,6 +2146,8 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS32-NEXT: $BB6_1: # %entry ; MIPS32-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS32-NEXT: ll $2, 0($6) +; MIPS32-NEXT: and $2, $2, $8 +; MIPS32-NEXT: and $7, $7, $8 ; MIPS32-NEXT: sltu $5, $2, $7 ; MIPS32-NEXT: move $3, $2 ; MIPS32-NEXT: movn $3, $7, $5 @@ -2186,6 +2188,8 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSEL-NEXT: $BB6_1: # %entry ; MIPSEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSEL-NEXT: ll $2, 0($6) +; MIPSEL-NEXT: and $2, $2, $8 +; MIPSEL-NEXT: and $7, $7, $8 ; MIPSEL-NEXT: sltu $5, $2, $7 ; MIPSEL-NEXT: move $3, $2 ; MIPSEL-NEXT: movn $3, $7, $5 @@ -2225,6 +2229,8 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSELR6-NEXT: $BB6_1: # %entry ; MIPSELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSELR6-NEXT: ll $2, 0($6) +; MIPSELR6-NEXT: and $2, $2, $8 +; MIPSELR6-NEXT: and $7, $7, $8 ; MIPSELR6-NEXT: sltu $5, $2, $7 ; MIPSELR6-NEXT: seleqz $3, $2, $5 ; MIPSELR6-NEXT: selnez $5, $7, $5 @@ -2263,6 +2269,8 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MMEL-NEXT: $BB6_1: # %entry ; MMEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MMEL-NEXT: ll $2, 0($6) +; MMEL-NEXT: and $2, $2, $8 +; MMEL-NEXT: and $7, $7, $8 ; MMEL-NEXT: sltu $5, $2, $7 ; MMEL-NEXT: or $3, $2, $zero ; MMEL-NEXT: movn $3, $7, $5 @@ -2300,6 +2308,8 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MMELR6-NEXT: $BB6_1: # %entry ; MMELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMELR6-NEXT: ll $2, 0($6) +; MMELR6-NEXT: and $2, $2, $8 +; MMELR6-NEXT: and $7, $7, $8 ; MMELR6-NEXT: sltu $5, $2, $7 ; MMELR6-NEXT: seleqz $3, $2, $5 ; MMELR6-NEXT: selnez $5, $7, $5 @@ -2417,6 +2427,8 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64EL-NEXT: .LBB6_1: # %entry ; MIPS64EL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64EL-NEXT: ll $2, 0($6) +; MIPS64EL-NEXT: and $2, $2, $8 +; MIPS64EL-NEXT: and $7, $7, $8 ; MIPS64EL-NEXT: sltu $5, $2, $7 ; MIPS64EL-NEXT: move $3, $2 ; MIPS64EL-NEXT: movn $3, $7, $5 @@ -2456,6 +2468,8 @@ define i16 @test_umax_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64ELR6-NEXT: .LBB6_1: # %entry ; MIPS64ELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64ELR6-NEXT: ll $2, 0($6) +; MIPS64ELR6-NEXT: and $2, $2, $8 +; MIPS64ELR6-NEXT: and $7, $7, $8 ; MIPS64ELR6-NEXT: sltu $5, $2, $7 ; MIPS64ELR6-NEXT: seleqz $3, $2, $5 ; MIPS64ELR6-NEXT: selnez $5, $7, $5 @@ -2655,6 +2669,8 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS32-NEXT: $BB7_1: # %entry ; MIPS32-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS32-NEXT: ll $2, 0($6) +; MIPS32-NEXT: and $2, $2, $8 +; MIPS32-NEXT: and $7, $7, $8 ; MIPS32-NEXT: sltu $5, $2, $7 ; MIPS32-NEXT: move $3, $2 ; MIPS32-NEXT: movz $3, $7, $5 @@ -2696,6 +2712,8 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSEL-NEXT: $BB7_1: # %entry ; MIPSEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSEL-NEXT: ll $2, 0($6) +; MIPSEL-NEXT: and $2, $2, $8 +; MIPSEL-NEXT: and $7, $7, $8 ; MIPSEL-NEXT: sltu $5, $2, $7 ; MIPSEL-NEXT: move $3, $2 ; MIPSEL-NEXT: movz $3, $7, $5 @@ -2735,6 +2753,8 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPSELR6-NEXT: $BB7_1: # %entry ; MIPSELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSELR6-NEXT: ll $2, 0($6) +; MIPSELR6-NEXT: and $2, $2, $8 +; MIPSELR6-NEXT: and $7, $7, $8 ; MIPSELR6-NEXT: sltu $5, $2, $7 ; MIPSELR6-NEXT: selnez $3, $2, $5 ; MIPSELR6-NEXT: seleqz $5, $7, $5 @@ -2773,6 +2793,8 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MMEL-NEXT: $BB7_1: # %entry ; MMEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MMEL-NEXT: ll $2, 0($6) +; MMEL-NEXT: and $2, $2, $8 +; MMEL-NEXT: and $7, $7, $8 ; MMEL-NEXT: sltu $5, $2, $7 ; MMEL-NEXT: or $3, $2, $zero ; MMEL-NEXT: movz $3, $7, $5 @@ -2810,6 +2832,8 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MMELR6-NEXT: $BB7_1: # %entry ; MMELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMELR6-NEXT: ll $2, 0($6) +; MMELR6-NEXT: and $2, $2, $8 +; MMELR6-NEXT: and $7, $7, $8 ; MMELR6-NEXT: sltu $5, $2, $7 ; MMELR6-NEXT: selnez $3, $2, $5 ; MMELR6-NEXT: seleqz $5, $7, $5 @@ -2927,6 +2951,8 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64EL-NEXT: .LBB7_1: # %entry ; MIPS64EL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64EL-NEXT: ll $2, 0($6) +; MIPS64EL-NEXT: and $2, $2, $8 +; MIPS64EL-NEXT: and $7, $7, $8 ; MIPS64EL-NEXT: sltu $5, $2, $7 ; MIPS64EL-NEXT: move $3, $2 ; MIPS64EL-NEXT: movz $3, $7, $5 @@ -2966,6 +2992,8 @@ define i16 @test_umin_16(ptr nocapture %ptr, i16 signext %val) { ; MIPS64ELR6-NEXT: .LBB7_1: # %entry ; MIPS64ELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64ELR6-NEXT: ll $2, 0($6) +; MIPS64ELR6-NEXT: and $2, $2, $8 +; MIPS64ELR6-NEXT: and $7, $7, $8 ; MIPS64ELR6-NEXT: sltu $5, $2, $7 ; MIPS64ELR6-NEXT: selnez $3, $2, $5 ; MIPS64ELR6-NEXT: seleqz $5, $7, $5 @@ -4244,6 +4272,8 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS32-NEXT: $BB10_1: # %entry ; MIPS32-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS32-NEXT: ll $2, 0($6) +; MIPS32-NEXT: and $2, $2, $8 +; MIPS32-NEXT: and $7, $7, $8 ; MIPS32-NEXT: sltu $5, $2, $7 ; MIPS32-NEXT: move $3, $2 ; MIPS32-NEXT: movn $3, $7, $5 @@ -4284,6 +4314,8 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSEL-NEXT: $BB10_1: # %entry ; MIPSEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSEL-NEXT: ll $2, 0($6) +; MIPSEL-NEXT: and $2, $2, $8 +; MIPSEL-NEXT: and $7, $7, $8 ; MIPSEL-NEXT: sltu $5, $2, $7 ; MIPSEL-NEXT: move $3, $2 ; MIPSEL-NEXT: movn $3, $7, $5 @@ -4323,6 +4355,8 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSELR6-NEXT: $BB10_1: # %entry ; MIPSELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSELR6-NEXT: ll $2, 0($6) +; MIPSELR6-NEXT: and $2, $2, $8 +; MIPSELR6-NEXT: and $7, $7, $8 ; MIPSELR6-NEXT: sltu $5, $2, $7 ; MIPSELR6-NEXT: seleqz $3, $2, $5 ; MIPSELR6-NEXT: selnez $5, $7, $5 @@ -4361,6 +4395,8 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MMEL-NEXT: $BB10_1: # %entry ; MMEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MMEL-NEXT: ll $2, 0($6) +; MMEL-NEXT: and $2, $2, $8 +; MMEL-NEXT: and $7, $7, $8 ; MMEL-NEXT: sltu $5, $2, $7 ; MMEL-NEXT: or $3, $2, $zero ; MMEL-NEXT: movn $3, $7, $5 @@ -4398,6 +4434,8 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MMELR6-NEXT: $BB10_1: # %entry ; MMELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMELR6-NEXT: ll $2, 0($6) +; MMELR6-NEXT: and $2, $2, $8 +; MMELR6-NEXT: and $7, $7, $8 ; MMELR6-NEXT: sltu $5, $2, $7 ; MMELR6-NEXT: seleqz $3, $2, $5 ; MMELR6-NEXT: selnez $5, $7, $5 @@ -4515,6 +4553,8 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64EL-NEXT: .LBB10_1: # %entry ; MIPS64EL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64EL-NEXT: ll $2, 0($6) +; MIPS64EL-NEXT: and $2, $2, $8 +; MIPS64EL-NEXT: and $7, $7, $8 ; MIPS64EL-NEXT: sltu $5, $2, $7 ; MIPS64EL-NEXT: move $3, $2 ; MIPS64EL-NEXT: movn $3, $7, $5 @@ -4554,6 +4594,8 @@ define i8 @test_umax_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64ELR6-NEXT: .LBB10_1: # %entry ; MIPS64ELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64ELR6-NEXT: ll $2, 0($6) +; MIPS64ELR6-NEXT: and $2, $2, $8 +; MIPS64ELR6-NEXT: and $7, $7, $8 ; MIPS64ELR6-NEXT: sltu $5, $2, $7 ; MIPS64ELR6-NEXT: seleqz $3, $2, $5 ; MIPS64ELR6-NEXT: selnez $5, $7, $5 @@ -4753,6 +4795,8 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS32-NEXT: $BB11_1: # %entry ; MIPS32-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS32-NEXT: ll $2, 0($6) +; MIPS32-NEXT: and $2, $2, $8 +; MIPS32-NEXT: and $7, $7, $8 ; MIPS32-NEXT: sltu $5, $2, $7 ; MIPS32-NEXT: move $3, $2 ; MIPS32-NEXT: movz $3, $7, $5 @@ -4793,6 +4837,8 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSEL-NEXT: $BB11_1: # %entry ; MIPSEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSEL-NEXT: ll $2, 0($6) +; MIPSEL-NEXT: and $2, $2, $8 +; MIPSEL-NEXT: and $7, $7, $8 ; MIPSEL-NEXT: sltu $5, $2, $7 ; MIPSEL-NEXT: move $3, $2 ; MIPSEL-NEXT: movz $3, $7, $5 @@ -4832,6 +4878,8 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPSELR6-NEXT: $BB11_1: # %entry ; MIPSELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPSELR6-NEXT: ll $2, 0($6) +; MIPSELR6-NEXT: and $2, $2, $8 +; MIPSELR6-NEXT: and $7, $7, $8 ; MIPSELR6-NEXT: sltu $5, $2, $7 ; MIPSELR6-NEXT: selnez $3, $2, $5 ; MIPSELR6-NEXT: seleqz $5, $7, $5 @@ -4870,6 +4918,8 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MMEL-NEXT: $BB11_1: # %entry ; MMEL-NEXT: # =>This Inner Loop Header: Depth=1 ; MMEL-NEXT: ll $2, 0($6) +; MMEL-NEXT: and $2, $2, $8 +; MMEL-NEXT: and $7, $7, $8 ; MMEL-NEXT: sltu $5, $2, $7 ; MMEL-NEXT: or $3, $2, $zero ; MMEL-NEXT: movz $3, $7, $5 @@ -4907,6 +4957,8 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MMELR6-NEXT: $BB11_1: # %entry ; MMELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MMELR6-NEXT: ll $2, 0($6) +; MMELR6-NEXT: and $2, $2, $8 +; MMELR6-NEXT: and $7, $7, $8 ; MMELR6-NEXT: sltu $5, $2, $7 ; MMELR6-NEXT: selnez $3, $2, $5 ; MMELR6-NEXT: seleqz $5, $7, $5 @@ -5024,6 +5076,8 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64EL-NEXT: .LBB11_1: # %entry ; MIPS64EL-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64EL-NEXT: ll $2, 0($6) +; MIPS64EL-NEXT: and $2, $2, $8 +; MIPS64EL-NEXT: and $7, $7, $8 ; MIPS64EL-NEXT: sltu $5, $2, $7 ; MIPS64EL-NEXT: move $3, $2 ; MIPS64EL-NEXT: movz $3, $7, $5 @@ -5063,6 +5117,8 @@ define i8 @test_umin_8(ptr nocapture %ptr, i8 signext %val) { ; MIPS64ELR6-NEXT: .LBB11_1: # %entry ; MIPS64ELR6-NEXT: # =>This Inner Loop Header: Depth=1 ; MIPS64ELR6-NEXT: ll $2, 0($6) +; MIPS64ELR6-NEXT: and $2, $2, $8 +; MIPS64ELR6-NEXT: and $7, $7, $8 ; MIPS64ELR6-NEXT: sltu $5, $2, $7 ; MIPS64ELR6-NEXT: selnez $3, $2, $5 ; MIPS64ELR6-NEXT: seleqz $5, $7, $5 diff --git a/llvm/test/CodeGen/Mips/avoid-zero-copy.mir b/llvm/test/CodeGen/Mips/avoid-zero-copy.mir index 5c7cffd109ea62e8a906af1dc1d8d57256eda2a1..e3990bdf9bc3fb546f0d951062684bc6b720d24b 100644 --- a/llvm/test/CodeGen/Mips/avoid-zero-copy.mir +++ b/llvm/test/CodeGen/Mips/avoid-zero-copy.mir @@ -19,6 +19,8 @@ ... --- name: a +frameInfo: + adjustsStack: true body: | bb.0 (%ir-block.0): liveins: $a0_64, $t9_64, $ra_64, $fp_64, $gp_64 diff --git a/llvm/test/CodeGen/Mips/msa/emergency-spill.mir b/llvm/test/CodeGen/Mips/msa/emergency-spill.mir index e1c7b2158d61743edbc0f8c1c29ee67ab4234db0..2089464528661808f537028b6af276617de049f8 100644 --- a/llvm/test/CodeGen/Mips/msa/emergency-spill.mir +++ b/llvm/test/CodeGen/Mips/msa/emergency-spill.mir @@ -90,7 +90,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 16 - adjustsStack: false + adjustsStack: true hasCalls: true stackProtector: '' maxCallFrameSize: 4294967295 diff --git a/llvm/test/CodeGen/Mips/msa/f16-llvm-ir.ll b/llvm/test/CodeGen/Mips/msa/f16-llvm-ir.ll index 6a27c9f5dac9b23aa288bd35b3b837aacae9b4fa..45c7ab980edd64fc2a84ece49eccb2bb3a51928f 100644 --- a/llvm/test/CodeGen/Mips/msa/f16-llvm-ir.ll +++ b/llvm/test/CodeGen/Mips/msa/f16-llvm-ir.ll @@ -405,8 +405,9 @@ define void @uitofp(i32 %a) { ; MIPS64-N32-NEXT: addiu $1, $1, %lo(%neg(%gp_rel(uitofp))) ; MIPS64-N32-NEXT: lui $2, 17200 ; MIPS64-N32-NEXT: sw $2, 12($sp) -; MIPS64-N32-NEXT: sll $2, $4, 0 -; MIPS64-N32-NEXT: sw $2, 8($sp) +; MIPS64R5-N32-NEXT: sll $2, $4, 0 +; MIPS64R5-N32-NEXT: sw $2, 8($sp) +; MIPSR6-N32-NEXT: sw $4, 8($sp) ; MIPS64-N32-NEXT: lw $2, %got_page(.LCPI5_0)($1) ; MIPS64-N32-NEXT: ldc1 $f0, %got_ofst(.LCPI5_0)($2) ; MIPS64-N32-NEXT: ldc1 $f1, 8($sp) @@ -430,8 +431,9 @@ define void @uitofp(i32 %a) { ; MIPS64-N64-NEXT: daddiu $1, $1, %lo(%neg(%gp_rel(uitofp))) ; MIPS64-N64-NEXT: lui $2, 17200 ; MIPS64-N64-NEXT: sw $2, 12($sp) -; MIPS64-N64-NEXT: sll $2, $4, 0 -; MIPS64-N64-NEXT: sw $2, 8($sp) +; MIPS64R5-N64-NEXT: sll $2, $4, 0 +; MIPS64R5-N64-NEXT: sw $2, 8($sp) +; MIPSR6-N64-NEXT: sw $4, 8($sp) ; MIPS64-N64-NEXT: ld $2, %got_page(.LCPI5_0)($1) ; MIPS64-N64-NEXT: ldc1 $f0, %got_ofst(.LCPI5_0)($2) ; MIPS64-N64-NEXT: ldc1 $f1, 8($sp) diff --git a/llvm/test/CodeGen/Mips/no-unaligned-access-r6.ll b/llvm/test/CodeGen/Mips/no-unaligned-access-r6.ll new file mode 100644 index 0000000000000000000000000000000000000000..0695868f9c80386ebee668f0fbdbbccbd462946d --- /dev/null +++ b/llvm/test/CodeGen/Mips/no-unaligned-access-r6.ll @@ -0,0 +1,69 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +;; Test the strict-align feature which is similar to AArch64/arm64-strict-align.ll. + +; RUN: llc --mtriple=mipsisa32r6 < %s | FileCheck %s --check-prefix=MIPS32R6-UNALIGNED +; RUN: llc --mtriple=mipsisa32r6 --mattr=-strict-align < %s | FileCheck %s --check-prefix=MIPS32R6-UNALIGNED +; RUN: llc --mtriple=mipsisa32r6 --mattr=+strict-align < %s | FileCheck %s --check-prefix=MIPS32R6-ALIGNED + +; RUN: llc --mtriple=mipsisa64r6 < %s | FileCheck %s --check-prefix=MIPS64R6-UNALIGNED +; RUN: llc --mtriple=mipsisa64r6 --mattr=-strict-align < %s | FileCheck %s --check-prefix=MIPS64R6-UNALIGNED +; RUN: llc --mtriple=mipsisa64r6 --mattr=+strict-align < %s | FileCheck %s --check-prefix=MIPS64R6-ALIGNED + +define i32 @f0(ptr %p) nounwind { +; MIPS32R6-UNALIGNED-LABEL: f0: +; MIPS32R6-UNALIGNED: # %bb.0: +; MIPS32R6-UNALIGNED-NEXT: lw $2, 0($4) +; MIPS32R6-UNALIGNED-NEXT: jrc $ra +; +; MIPS32R6-ALIGNED-LABEL: f0: +; MIPS32R6-ALIGNED: # %bb.0: +; MIPS32R6-ALIGNED-NEXT: lhu $1, 2($4) +; MIPS32R6-ALIGNED-NEXT: lhu $2, 0($4) +; MIPS32R6-ALIGNED-NEXT: sll $2, $2, 16 +; MIPS32R6-ALIGNED-NEXT: jr $ra +; MIPS32R6-ALIGNED-NEXT: or $2, $2, $1 +; +; MIPS64R6-UNALIGNED-LABEL: f0: +; MIPS64R6-UNALIGNED: # %bb.0: +; MIPS64R6-UNALIGNED-NEXT: lw $2, 0($4) +; MIPS64R6-UNALIGNED-NEXT: jrc $ra +; +; MIPS64R6-ALIGNED-LABEL: f0: +; MIPS64R6-ALIGNED: # %bb.0: +; MIPS64R6-ALIGNED-NEXT: lhu $1, 2($4) +; MIPS64R6-ALIGNED-NEXT: lhu $2, 0($4) +; MIPS64R6-ALIGNED-NEXT: sll $2, $2, 16 +; MIPS64R6-ALIGNED-NEXT: jr $ra +; MIPS64R6-ALIGNED-NEXT: or $2, $2, $1 + %tmp = load i32, ptr %p, align 2 + ret i32 %tmp +} + +define i64 @f1(ptr %p) nounwind { +; MIPS32R6-UNALIGNED-LABEL: f1: +; MIPS32R6-UNALIGNED: # %bb.0: +; MIPS32R6-UNALIGNED-NEXT: lw $2, 0($4) +; MIPS32R6-UNALIGNED-NEXT: lw $3, 4($4) +; MIPS32R6-UNALIGNED-NEXT: jrc $ra +; +; MIPS32R6-ALIGNED-LABEL: f1: +; MIPS32R6-ALIGNED: # %bb.0: +; MIPS32R6-ALIGNED-NEXT: lw $2, 0($4) +; MIPS32R6-ALIGNED-NEXT: lw $3, 4($4) +; MIPS32R6-ALIGNED-NEXT: jrc $ra +; +; MIPS64R6-UNALIGNED-LABEL: f1: +; MIPS64R6-UNALIGNED: # %bb.0: +; MIPS64R6-UNALIGNED-NEXT: ld $2, 0($4) +; MIPS64R6-UNALIGNED-NEXT: jrc $ra +; +; MIPS64R6-ALIGNED-LABEL: f1: +; MIPS64R6-ALIGNED: # %bb.0: +; MIPS64R6-ALIGNED-NEXT: lwu $1, 4($4) +; MIPS64R6-ALIGNED-NEXT: lwu $2, 0($4) +; MIPS64R6-ALIGNED-NEXT: dsll $2, $2, 32 +; MIPS64R6-ALIGNED-NEXT: jr $ra +; MIPS64R6-ALIGNED-NEXT: or $2, $2, $1 + %tmp = load i64, ptr %p, align 4 + ret i64 %tmp +} diff --git a/llvm/test/CodeGen/NVPTX/atomics-sm70.ll b/llvm/test/CodeGen/NVPTX/atomics-sm70.ll new file mode 100644 index 0000000000000000000000000000000000000000..9cc45fbe313b7efd6516e7c824d22d04b0f70f3f --- /dev/null +++ b/llvm/test/CodeGen/NVPTX/atomics-sm70.ll @@ -0,0 +1,142 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -march=nvptx -mcpu=sm_70 -mattr=+ptx63 | FileCheck %s --check-prefixes=CHECK +; RUN: llc < %s -march=nvptx64 -mcpu=sm_70 -mattr=+ptx63 | FileCheck %s --check-prefixes=CHECK64 +; RUN: llc < %s -march=nvptx -mcpu=sm_70 -mattr=+ptx62 | FileCheck %s --check-prefixes=CHECKPTX62 +; RUN: %if ptxas && !ptxas-12.0 %{ llc < %s -march=nvptx -mcpu=sm_70 -mattr=+ptx63 | %ptxas-verify -arch=sm_70 %} +; RUN: %if ptxas %{ llc < %s -march=nvptx64 -mcpu=sm_70 -mattr=+ptx63 | %ptxas-verify -arch=sm_70 %} +; RUN: %if ptxas && !ptxas-12.0 %{ llc < %s -march=nvptx -mcpu=sm_70 -mattr=+ptx62 | %ptxas-verify -arch=sm_70 %} + +target triple = "nvptx64-nvidia-cuda" + +define void @test(ptr %dp0, ptr addrspace(1) %dp1, ptr addrspace(3) %dp3, half %val) { +; CHECK-LABEL: test( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<7>; +; CHECK-NEXT: .reg .b32 %r<4>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [test_param_0]; +; CHECK-NEXT: ld.param.b16 %rs1, [test_param_3]; +; CHECK-NEXT: atom.add.noftz.f16 %rs2, [%r1], %rs1; +; CHECK-NEXT: ld.param.u32 %r2, [test_param_1]; +; CHECK-NEXT: mov.b16 %rs3, 0x3C00; +; CHECK-NEXT: atom.add.noftz.f16 %rs4, [%r1], %rs3; +; CHECK-NEXT: ld.param.u32 %r3, [test_param_2]; +; CHECK-NEXT: atom.global.add.noftz.f16 %rs5, [%r2], %rs1; +; CHECK-NEXT: atom.shared.add.noftz.f16 %rs6, [%r3], %rs1; +; CHECK-NEXT: ret; +; +; CHECK64-LABEL: test( +; CHECK64: { +; CHECK64-NEXT: .reg .b16 %rs<7>; +; CHECK64-NEXT: .reg .b64 %rd<4>; +; CHECK64-EMPTY: +; CHECK64-NEXT: // %bb.0: +; CHECK64-NEXT: ld.param.u64 %rd1, [test_param_0]; +; CHECK64-NEXT: ld.param.b16 %rs1, [test_param_3]; +; CHECK64-NEXT: atom.add.noftz.f16 %rs2, [%rd1], %rs1; +; CHECK64-NEXT: ld.param.u64 %rd2, [test_param_1]; +; CHECK64-NEXT: mov.b16 %rs3, 0x3C00; +; CHECK64-NEXT: atom.add.noftz.f16 %rs4, [%rd1], %rs3; +; CHECK64-NEXT: ld.param.u64 %rd3, [test_param_2]; +; CHECK64-NEXT: atom.global.add.noftz.f16 %rs5, [%rd2], %rs1; +; CHECK64-NEXT: atom.shared.add.noftz.f16 %rs6, [%rd3], %rs1; +; CHECK64-NEXT: ret; +; +; CHECKPTX62-LABEL: test( +; CHECKPTX62: { +; CHECKPTX62-NEXT: .reg .pred %p<5>; +; CHECKPTX62-NEXT: .reg .b16 %rs<19>; +; CHECKPTX62-NEXT: .reg .b32 %r<58>; +; CHECKPTX62-EMPTY: +; CHECKPTX62-NEXT: // %bb.0: +; CHECKPTX62-NEXT: ld.param.b16 %rs1, [test_param_3]; +; CHECKPTX62-NEXT: ld.param.u32 %r23, [test_param_2]; +; CHECKPTX62-NEXT: ld.param.u32 %r22, [test_param_1]; +; CHECKPTX62-NEXT: ld.param.u32 %r24, [test_param_0]; +; CHECKPTX62-NEXT: and.b32 %r1, %r24, -4; +; CHECKPTX62-NEXT: and.b32 %r25, %r24, 3; +; CHECKPTX62-NEXT: shl.b32 %r2, %r25, 3; +; CHECKPTX62-NEXT: mov.b32 %r26, 65535; +; CHECKPTX62-NEXT: shl.b32 %r27, %r26, %r2; +; CHECKPTX62-NEXT: not.b32 %r3, %r27; +; CHECKPTX62-NEXT: ld.u32 %r54, [%r1]; +; CHECKPTX62-NEXT: $L__BB0_1: // %atomicrmw.start +; CHECKPTX62-NEXT: // =>This Inner Loop Header: Depth=1 +; CHECKPTX62-NEXT: shr.u32 %r28, %r54, %r2; +; CHECKPTX62-NEXT: cvt.u16.u32 %rs2, %r28; +; CHECKPTX62-NEXT: add.rn.f16 %rs4, %rs2, %rs1; +; CHECKPTX62-NEXT: cvt.u32.u16 %r29, %rs4; +; CHECKPTX62-NEXT: shl.b32 %r30, %r29, %r2; +; CHECKPTX62-NEXT: and.b32 %r31, %r54, %r3; +; CHECKPTX62-NEXT: or.b32 %r32, %r31, %r30; +; CHECKPTX62-NEXT: atom.cas.b32 %r6, [%r1], %r54, %r32; +; CHECKPTX62-NEXT: setp.ne.s32 %p1, %r6, %r54; +; CHECKPTX62-NEXT: mov.u32 %r54, %r6; +; CHECKPTX62-NEXT: @%p1 bra $L__BB0_1; +; CHECKPTX62-NEXT: // %bb.2: // %atomicrmw.end +; CHECKPTX62-NEXT: ld.u32 %r55, [%r1]; +; CHECKPTX62-NEXT: $L__BB0_3: // %atomicrmw.start9 +; CHECKPTX62-NEXT: // =>This Inner Loop Header: Depth=1 +; CHECKPTX62-NEXT: shr.u32 %r33, %r55, %r2; +; CHECKPTX62-NEXT: cvt.u16.u32 %rs6, %r33; +; CHECKPTX62-NEXT: mov.b16 %rs8, 0x3C00; +; CHECKPTX62-NEXT: add.rn.f16 %rs9, %rs6, %rs8; +; CHECKPTX62-NEXT: cvt.u32.u16 %r34, %rs9; +; CHECKPTX62-NEXT: shl.b32 %r35, %r34, %r2; +; CHECKPTX62-NEXT: and.b32 %r36, %r55, %r3; +; CHECKPTX62-NEXT: or.b32 %r37, %r36, %r35; +; CHECKPTX62-NEXT: atom.cas.b32 %r9, [%r1], %r55, %r37; +; CHECKPTX62-NEXT: setp.ne.s32 %p2, %r9, %r55; +; CHECKPTX62-NEXT: mov.u32 %r55, %r9; +; CHECKPTX62-NEXT: @%p2 bra $L__BB0_3; +; CHECKPTX62-NEXT: // %bb.4: // %atomicrmw.end8 +; CHECKPTX62-NEXT: and.b32 %r10, %r22, -4; +; CHECKPTX62-NEXT: shl.b32 %r38, %r22, 3; +; CHECKPTX62-NEXT: and.b32 %r11, %r38, 24; +; CHECKPTX62-NEXT: shl.b32 %r40, %r26, %r11; +; CHECKPTX62-NEXT: not.b32 %r12, %r40; +; CHECKPTX62-NEXT: ld.global.u32 %r56, [%r10]; +; CHECKPTX62-NEXT: $L__BB0_5: // %atomicrmw.start27 +; CHECKPTX62-NEXT: // =>This Inner Loop Header: Depth=1 +; CHECKPTX62-NEXT: shr.u32 %r41, %r56, %r11; +; CHECKPTX62-NEXT: cvt.u16.u32 %rs11, %r41; +; CHECKPTX62-NEXT: add.rn.f16 %rs13, %rs11, %rs1; +; CHECKPTX62-NEXT: cvt.u32.u16 %r42, %rs13; +; CHECKPTX62-NEXT: shl.b32 %r43, %r42, %r11; +; CHECKPTX62-NEXT: and.b32 %r44, %r56, %r12; +; CHECKPTX62-NEXT: or.b32 %r45, %r44, %r43; +; CHECKPTX62-NEXT: atom.global.cas.b32 %r15, [%r10], %r56, %r45; +; CHECKPTX62-NEXT: setp.ne.s32 %p3, %r15, %r56; +; CHECKPTX62-NEXT: mov.u32 %r56, %r15; +; CHECKPTX62-NEXT: @%p3 bra $L__BB0_5; +; CHECKPTX62-NEXT: // %bb.6: // %atomicrmw.end26 +; CHECKPTX62-NEXT: and.b32 %r16, %r23, -4; +; CHECKPTX62-NEXT: shl.b32 %r46, %r23, 3; +; CHECKPTX62-NEXT: and.b32 %r17, %r46, 24; +; CHECKPTX62-NEXT: shl.b32 %r48, %r26, %r17; +; CHECKPTX62-NEXT: not.b32 %r18, %r48; +; CHECKPTX62-NEXT: ld.shared.u32 %r57, [%r16]; +; CHECKPTX62-NEXT: $L__BB0_7: // %atomicrmw.start45 +; CHECKPTX62-NEXT: // =>This Inner Loop Header: Depth=1 +; CHECKPTX62-NEXT: shr.u32 %r49, %r57, %r17; +; CHECKPTX62-NEXT: cvt.u16.u32 %rs15, %r49; +; CHECKPTX62-NEXT: add.rn.f16 %rs17, %rs15, %rs1; +; CHECKPTX62-NEXT: cvt.u32.u16 %r50, %rs17; +; CHECKPTX62-NEXT: shl.b32 %r51, %r50, %r17; +; CHECKPTX62-NEXT: and.b32 %r52, %r57, %r18; +; CHECKPTX62-NEXT: or.b32 %r53, %r52, %r51; +; CHECKPTX62-NEXT: atom.shared.cas.b32 %r21, [%r16], %r57, %r53; +; CHECKPTX62-NEXT: setp.ne.s32 %p4, %r21, %r57; +; CHECKPTX62-NEXT: mov.u32 %r57, %r21; +; CHECKPTX62-NEXT: @%p4 bra $L__BB0_7; +; CHECKPTX62-NEXT: // %bb.8: // %atomicrmw.end44 +; CHECKPTX62-NEXT: ret; + %r1 = atomicrmw fadd ptr %dp0, half %val seq_cst + %r2 = atomicrmw fadd ptr %dp0, half 1.0 seq_cst + %r3 = atomicrmw fadd ptr addrspace(1) %dp1, half %val seq_cst + %r4 = atomicrmw fadd ptr addrspace(3) %dp3, half %val seq_cst + ret void +} + +attributes #1 = { argmemonly nounwind } diff --git a/llvm/test/CodeGen/NVPTX/atomics.ll b/llvm/test/CodeGen/NVPTX/atomics.ll index e99d0fd05e346b3f30d5ca18b7f71fb868ac35c5..6f2b5dcf47f13bba2a82b7cc9eb77d570ec52c8c 100644 --- a/llvm/test/CodeGen/NVPTX/atomics.ll +++ b/llvm/test/CodeGen/NVPTX/atomics.ll @@ -175,6 +175,13 @@ define float @atomicrmw_add_f32_generic(ptr %addr, float %val) { ret float %ret } +; CHECK-LABEL: atomicrmw_add_f16_generic +define half @atomicrmw_add_f16_generic(ptr %addr, half %val) { +; CHECK: atom.cas + %ret = atomicrmw fadd ptr %addr, half %val seq_cst + ret half %ret +} + ; CHECK-LABEL: atomicrmw_add_f32_addrspace1 define float @atomicrmw_add_f32_addrspace1(ptr addrspace(1) %addr, float %val) { ; CHECK: atom.global.add.f32 diff --git a/llvm/test/CodeGen/NVPTX/b52037.ll b/llvm/test/CodeGen/NVPTX/b52037.ll index d9322dabfa065e0d208817e294d71b2e6a5d2fa1..5d1c390909f6a5af3e5ac1b0cf1d353e8ef4d428 100644 --- a/llvm/test/CodeGen/NVPTX/b52037.ll +++ b/llvm/test/CodeGen/NVPTX/b52037.ll @@ -47,7 +47,7 @@ bb: %tmp5 = load ptr, ptr %tmp4, align 8 %tmp9 = getelementptr inbounds %struct.zot, ptr %tmp, i64 0, i32 2, i32 1 store ptr %tmp5, ptr %tmp9, align 8 - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @global_1, i64 0, inrange i32 0, i64 3), ptr %tmp, align 16 + store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @global_1, i64 0, i32 0, i64 3), ptr %tmp, align 16 %tmp.i1 = tail call i64 @foo() %tmp44.i16 = getelementptr inbounds i16, ptr %tmp5, i64 undef %tmp45.i17 = load i16, ptr %tmp44.i16, align 2 diff --git a/llvm/test/CodeGen/NVPTX/bswap.ll b/llvm/test/CodeGen/NVPTX/bswap.ll new file mode 100644 index 0000000000000000000000000000000000000000..3f929ec6a75d0a84e29088cd837b3978e4ea5031 --- /dev/null +++ b/llvm/test/CodeGen/NVPTX/bswap.ll @@ -0,0 +1,77 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -march=nvptx64 -mcpu=sm_20 | FileCheck %s +; RUN: %if ptxas %{ llc < %s -march=nvptx64 -mcpu=sm_20 | %ptxas-verify %} + +target triple = "nvptx64-nvidia-cuda" + +define i16 @bswap16(i16 %a) { +; CHECK-LABEL: bswap16( +; CHECK: { +; CHECK-NEXT: .reg .b16 %rs<5>; +; CHECK-NEXT: .reg .b32 %r<2>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u16 %rs1, [bswap16_param_0]; +; CHECK-NEXT: shr.u16 %rs2, %rs1, 8; +; CHECK-NEXT: shl.b16 %rs3, %rs1, 8; +; CHECK-NEXT: or.b16 %rs4, %rs3, %rs2; +; CHECK-NEXT: cvt.u32.u16 %r1, %rs4; +; CHECK-NEXT: st.param.b32 [func_retval0+0], %r1; +; CHECK-NEXT: ret; + %b = tail call i16 @llvm.bswap.i16(i16 %a) + ret i16 %b +} + + +define i32 @bswap32(i32 %a) { +; CHECK-LABEL: bswap32( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [bswap32_param_0]; +; CHECK-NEXT: prmt.b32 %r2, %r1, 0, 291; +; CHECK-NEXT: st.param.b32 [func_retval0+0], %r2; +; CHECK-NEXT: ret; + %b = tail call i32 @llvm.bswap.i32(i32 %a) + ret i32 %b +} + + +define <2 x i16> @bswapv2i16(<2 x i16> %a) #0 { +; CHECK-LABEL: bswapv2i16( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u32 %r1, [bswapv2i16_param_0]; +; CHECK-NEXT: prmt.b32 %r2, %r1, 0, 8961; +; CHECK-NEXT: st.param.b32 [func_retval0+0], %r2; +; CHECK-NEXT: ret; + %b = tail call <2 x i16> @llvm.bswap.v2i16(<2 x i16> %a) + ret <2 x i16> %b +} + +define i64 @bswap64(i64 %a) { +; CHECK-LABEL: bswap64( +; CHECK: { +; CHECK-NEXT: .reg .b32 %r<5>; +; CHECK-NEXT: .reg .b64 %rd<3>; +; CHECK-EMPTY: +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: ld.param.u64 %rd1, [bswap64_param_0]; +; CHECK-NEXT: { .reg .b32 tmp; mov.b64 {%r1, tmp}, %rd1; } +; CHECK-NEXT: prmt.b32 %r2, %r1, 0, 291; +; CHECK-NEXT: { .reg .b32 tmp; mov.b64 {tmp, %r3}, %rd1; } +; CHECK-NEXT: prmt.b32 %r4, %r3, 0, 291; +; CHECK-NEXT: mov.b64 %rd2, {%r4, %r2}; +; CHECK-NEXT: st.param.b64 [func_retval0+0], %rd2; +; CHECK-NEXT: ret; + %b = tail call i64 @llvm.bswap.i64(i64 %a) + ret i64 %b +} + +declare i16 @llvm.bswap.i16(i16) +declare i32 @llvm.bswap.i32(i32) +declare <2 x i16> @llvm.bswap.v2i16(<2 x i16>) +declare i64 @llvm.bswap.i64(i64) diff --git a/llvm/test/CodeGen/NVPTX/common-linkage.ll b/llvm/test/CodeGen/NVPTX/common-linkage.ll new file mode 100644 index 0000000000000000000000000000000000000000..976074e12ba6672844c19ae428cec14421fa2089 --- /dev/null +++ b/llvm/test/CodeGen/NVPTX/common-linkage.ll @@ -0,0 +1,29 @@ +; RUN: llc < %s -march=nvptx -mcpu=sm_20 -mattr=+ptx43 | FileCheck %s --check-prefixes CHECK,PTX43 +; RUN: llc < %s -march=nvptx -mcpu=sm_20 -mattr=+ptx50 | FileCheck %s --check-prefixes CHECK,PTX50 +; RUN: %if ptxas %{ llc < %s -march=nvptx64 -mcpu=sm_20 -mattr=+ptx43 | %ptxas-verify %} +; RUN: %if ptxas %{ llc < %s -march=nvptx64 -mcpu=sm_20 -mattr=+ptx50 | %ptxas-verify %} + +; PTX43: .weak .global .align 4 .u32 g +; PTX50: .common .global .align 4 .u32 g +@g = common addrspace(1) global i32 0, align 4 + +; CHECK: .weak .const .align 4 .u32 c +@c = common addrspace(4) global i32 0, align 4 + +; CHECK: .weak .shared .align 4 .u32 s +@s = common addrspace(3) global i32 0, align 4 + +define i32 @f1() { + %1 = load i32, ptr addrspace(1) @g + ret i32 %1 +} + +define i32 @f4() { + %1 = load i32, ptr addrspace(4) @c + ret i32 %1 +} + +define i32 @f3() { + %1 = load i32, ptr addrspace(3) @s + ret i32 %1 +} diff --git a/llvm/test/CodeGen/NVPTX/dynamic_stackalloc.ll b/llvm/test/CodeGen/NVPTX/dynamic_stackalloc.ll index 3ef55ca5309f88dd7967322475551b42960a75aa..09297fb819ce55f0a9d7bdfc1b5d0b3bc91cd592 100644 --- a/llvm/test/CodeGen/NVPTX/dynamic_stackalloc.ll +++ b/llvm/test/CodeGen/NVPTX/dynamic_stackalloc.ll @@ -1,10 +1,44 @@ -; RUN: not llc -march=nvptx < %s 2>&1 | FileCheck %s -; RUN: not llc -march=nvptx64 < %s 2>&1 | FileCheck %s +; RUN: not llc < %s -march=nvptx -mattr=+ptx72 -mcpu=sm_52 2>&1 | FileCheck %s --check-prefixes=CHECK-FAILS +; RUN: not llc < %s -march=nvptx -mattr=+ptx73 -mcpu=sm_50 2>&1 | FileCheck %s --check-prefixes=CHECK-FAILS -; CHECK: in function test_dynamic_stackalloc{{.*}}: dynamic alloca unsupported by NVPTX backend +; RUN: llc < %s -march=nvptx -mattr=+ptx73 -mcpu=sm_52 | FileCheck %s --check-prefixes=CHECK,CHECK-32 +; RUN: llc < %s -march=nvptx64 -mattr=+ptx73 -mcpu=sm_52 | FileCheck %s --check-prefixes=CHECK,CHECK-64 +; RUN: %if ptxas && !ptxas-12.0 %{ llc < %s -march=nvptx -mattr=+ptx73 -mcpu=sm_52 | %ptxas-verify %} +; RUN: %if ptxas %{ llc < %s -march=nvptx64 -mattr=+ptx73 -mcpu=sm_52 | %ptxas-verify %} -define void @test_dynamic_stackalloc(i64 %n) { - %alloca = alloca i32, i64 %n - store volatile i32 0, ptr %alloca - ret void +; CHECK-FAILS: in function test_dynamic_stackalloc{{.*}}: Support for dynamic alloca introduced in PTX ISA version 7.3 and requires target sm_52. + +; CHECK-LABEL: .visible .func (.param .b32 func_retval0) test_dynamic_stackalloc( +; CHECK-NOT: __local_depot + +; CHECK-32: ld.param.u32 %r[[SIZE:[0-9]]], [test_dynamic_stackalloc_param_0]; +; CHECK-32-NEXT: mad.lo.s32 %r[[SIZE2:[0-9]]], %r[[SIZE]], 1, 7; +; CHECK-32-NEXT: and.b32 %r[[SIZE3:[0-9]]], %r[[SIZE2]], -8; +; CHECK-32-NEXT: alloca.u32 %r[[ALLOCA:[0-9]]], %r[[SIZE3]], 16; +; CHECK-32-NEXT: cvta.local.u32 %r[[ALLOCA]], %r[[ALLOCA]]; +; CHECK-32-NEXT: { // callseq 0, 0 +; CHECK-32-NEXT: .reg .b32 temp_param_reg; +; CHECK-32-NEXT: .param .b32 param0; +; CHECK-32-NEXT: st.param.b32 [param0+0], %r[[ALLOCA]]; + +; CHECK-64: ld.param.u64 %rd[[SIZE:[0-9]]], [test_dynamic_stackalloc_param_0]; +; CHECK-64-NEXT: add.s64 %rd[[SIZE2:[0-9]]], %rd[[SIZE]], 7; +; CHECK-64-NEXT: and.b64 %rd[[SIZE3:[0-9]]], %rd[[SIZE2]], -8; +; CHECK-64-NEXT: alloca.u64 %rd[[ALLOCA:[0-9]]], %rd[[SIZE3]], 16; +; CHECK-64-NEXT: cvta.local.u64 %rd[[ALLOCA]], %rd[[ALLOCA]]; +; CHECK-64-NEXT: { // callseq 0, 0 +; CHECK-64-NEXT: .reg .b32 temp_param_reg; +; CHECK-64-NEXT: .param .b64 param0; +; CHECK-64-NEXT: st.param.b64 [param0+0], %rd[[ALLOCA]]; + +; CHECK-NEXT: .param .b32 retval0; +; CHECK-NEXT: call.uni (retval0), +; CHECK-NEXT: bar, + +define i32 @test_dynamic_stackalloc(i64 %n) { + %alloca = alloca i8, i64 %n, align 16 + %call = call i32 @bar(ptr %alloca) + ret i32 %call } + +declare i32 @bar(ptr) diff --git a/llvm/test/CodeGen/NVPTX/weak-global.ll b/llvm/test/CodeGen/NVPTX/weak-global.ll index dd0160d1c0a6541546aaba29843f4e938109e3f8..c5467aad08a360c2c1189cfa2e88c088258809a8 100644 --- a/llvm/test/CodeGen/NVPTX/weak-global.ll +++ b/llvm/test/CodeGen/NVPTX/weak-global.ll @@ -1,7 +1,10 @@ -; RUN: llc < %s -march=nvptx64 -mcpu=sm_20 | FileCheck %s -; RUN: %if ptxas %{ llc < %s -march=nvptx64 -mcpu=sm_20 | %ptxas-verify %} +; RUN: llc < %s -march=nvptx64 -mcpu=sm_20 -mattr=+ptx43 | FileCheck %s --check-prefix PTX43 +; RUN: llc < %s -march=nvptx64 -mcpu=sm_20 -mattr=+ptx50 | FileCheck %s --check-prefix PTX50 +; RUN: %if ptxas %{ llc < %s -march=nvptx64 -mcpu=sm_20 -mattr=+ptx43 | %ptxas-verify %} +; RUN: %if ptxas %{ llc < %s -march=nvptx64 -mcpu=sm_20 -mattr=+ptx50 | %ptxas-verify %} -; CHECK: .weak .global .align 4 .u32 g +; PTX43: .weak .global .align 4 .u32 g +; PTX50: .common .global .align 4 .u32 g @g = common addrspace(1) global i32 zeroinitializer define i32 @func0() { diff --git a/llvm/test/CodeGen/PowerPC/aix-codemodel-attr.ll b/llvm/test/CodeGen/PowerPC/aix-codemodel-attr.ll new file mode 100644 index 0000000000000000000000000000000000000000..ef1156e338a89a57ff7b996d2605626a423c0722 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-codemodel-attr.ll @@ -0,0 +1,166 @@ +; RUN: llc --verify-machineinstrs -mtriple powerpc-ibm-aix --code-model=small < \ +; RUN: %s | FileCheck --check-prefixes=CHECK,CHECK32,CHECK-SMALL,CHECK-SMALL32 %s + +; RUN: llc --verify-machineinstrs -mtriple powerpc-ibm-aix --code-model=large < \ +; RUN: %s | FileCheck --check-prefixes=CHECK,CHECK32,CHECK-LARGE,CHECK-LARGE32 %s + +; RUN: llc --verify-machineinstrs -mtriple powerpc64-ibm-aix --code-model=small < \ +; RUN: %s | FileCheck --check-prefixes=CHECK,CHECK64,CHECK-SMALL,CHECK-SMALL64 %s + +; RUN: llc --verify-machineinstrs -mtriple powerpc64-ibm-aix --code-model=large < \ +; RUN: %s | FileCheck --check-prefixes=CHECK,CHECK64,CHECK-LARGE,CHECK-LARGE64 %s + +@a = external dso_local global i32, code_model "small", align 4 +@b = external dso_local global i32, code_model "large", align 4 +@c = dso_local global i32 55, code_model "small", align 4 +@d = dso_local global i32 41, code_model "large", align 4 +@e = external dso_local global i32, align 4 +@f = dso_local global i32 2748, align 4 + +@large_aliasee = global i32 10, code_model "large", align 4 +@small_aliasee = global i32 171, code_model "small", align 4 +@normal_aliasee = global i32 2748, align 4 + +@al = alias i32, ptr @large_aliasee +@as = alias i32, ptr @small_aliasee +@an = alias i32, ptr @normal_aliasee + +define i32 @A() local_unnamed_addr { +entry: + %0 = load i32, ptr @a, align 4 + ret i32 %0 +} +; CHECK32: lwz [[SCRATCH:[0-9]+]], L..C[[TL_A:[0-9]+]](2) # @a +; CHECK64: ld [[SCRATCH:[0-9]+]], L..C[[TL_A:[0-9]+]](2) # @a +; CHECK: lwz 3, 0([[SCRATCH]]) +; CHECK: blr + +define i32 @B() local_unnamed_addr { +entry: + %0 = load i32, ptr @b, align 4 + ret i32 %0 +} +; CHECK: addis [[HI:[0-9]+]], L..C[[TL_B:[0-9]+]]@u(2) +; CHECK32: lwz [[ADDR:[0-9]+]], L..C[[TL_B]]@l([[HI]]) +; CHECK64: ld [[ADDR:[0-9]+]], L..C[[TL_B]]@l([[HI]]) +; CHECK: lwz 3, 0([[ADDR]]) +; CHECK: blr + +define i32 @C() local_unnamed_addr { +entry: + %0 = load i32, ptr @c, align 4 + ret i32 %0 +} +; CHECK32: lwz [[SCRATCH:[0-9]+]], L..C[[TL_C:[0-9]+]](2) # @c +; CHECK64: ld [[SCRATCH:[0-9]+]], L..C[[TL_C:[0-9]+]](2) # @c +; CHECK: lwz 3, 0([[SCRATCH]]) +; CHECK: blr + +define i32 @D() local_unnamed_addr { +entry: + %0 = load i32, ptr @d, align 4 + ret i32 %0 +} +; CHECK: addis [[HI:[0-9]+]], L..C[[TL_D:[0-9]+]]@u(2) +; CHECK32: lwz [[ADDR:[0-9]+]], L..C[[TL_D]]@l([[HI]]) +; CHECK64: ld [[ADDR:[0-9]+]], L..C[[TL_D]]@l([[HI]]) +; CHECK: lwz 3, 0([[ADDR]]) +; CHECK: blr + +define i32 @E() { +entry: + %0 = load i32, ptr @e, align 4 + ret i32 %0 +} +; CHECK-LARGE: addis [[HI:[0-9]+]], L..C[[TL_E:[0-9]+]]@u(2) +; CHECK-LARGE32: lwz [[SCRATCH:[0-9]+]], L..C[[TL_E]]@l([[HI]]) +; CHECK-SMALL32: lwz [[SCRATCH:[0-9]+]], L..C[[TL_E:[0-9]+]](2) +; CHECK-LARGE64: ld [[SCRATCH:[0-9]+]], L..C[[TL_E]]@l([[HI]]) +; CHECK-SMALL64: ld [[SCRATCH:[0-9]+]], L..C[[TL_E:[0-9]+]](2) +; CHECK: lwz 3, 0([[SCRATCH]]) +; CHECK: blr + +define i32 @F() { +entry: + %0 = load i32, ptr @f, align 4 + ret i32 %0 +} +; CHECK-LARGE: addis [[HI:[0-9]+]], L..C[[TL_F:[0-9]+]]@u(2) +; CHECK-LARGE32: lwz [[SCRATCH:[0-9]+]], L..C[[TL_F]]@l([[HI]]) +; CHECK-SMALL32: lwz [[SCRATCH:[0-9]+]], L..C[[TL_F:[0-9]+]](2) +; CHECK-LARGE64: ld [[SCRATCH:[0-9]+]], L..C[[TL_F]]@l([[HI]]) +; CHECK-SMALL64: ld [[SCRATCH:[0-9]+]], L..C[[TL_F:[0-9]+]](2) +; CHECK: lwz 3, 0([[SCRATCH]]) +; CHECK: blr + +define noundef nonnull ptr @addr_a() local_unnamed_addr { +entry: + ret ptr @a +} +; CHECK32: lwz 3, L..C[[TL_A]](2) # @a +; CHECK64: ld 3, L..C[[TL_A]](2) # @a +; CHECK: blr + +define noundef nonnull ptr @addr_b() local_unnamed_addr { +entry: + ret ptr @b +} +; CHECK: addis [[HI:[0-9]+]], L..C[[TL_B]]@u(2) +; CHECK32: lwz 3, L..C[[TL_B]]@l([[HI]]) +; CHECK64: ld 3, L..C[[TL_B]]@l([[HI]]) +; CHECK: blr + + +define noundef nonnull ptr @addr_c() local_unnamed_addr { +entry: + ret ptr @c +} +; CHECK32: lwz 3, L..C[[TL_C]](2) # @c +; CHECK64: ld 3, L..C[[TL_C]](2) # @c +; CHECK: blr + +define noundef nonnull ptr @addr_d() local_unnamed_addr { +entry: + ret ptr @d +} +; CHECK: addis [[HI:[0-9]+]], L..C[[TL_D]]@u(2) +; CHECK32: lwz 3, L..C[[TL_D]]@l([[HI]]) +; CHECK64: ld 3, L..C[[TL_D]]@l([[HI]]) +; CHECK: blr + +define i32 @G() { + %tmp = load i32, ptr @al + ret i32 %tmp +} +; CHECK: addis [[HI:[0-9]+]], L..C[[TL_AL:[0-9]+]]@u(2) +; CHECK32: lwz [[ADDR:[0-9]+]], L..C[[TL_AL]]@l([[HI]]) +; CHECK64: ld [[ADDR:[0-9]+]], L..C[[TL_AL]]@l([[HI]]) +; CHECK: lwz 3, 0([[ADDR]]) + +define i32 @H() { + %tmp = load i32, ptr @as + ret i32 %tmp +} +; CHECK32: lwz [[ADDR:[0-9]+]], L..C[[TL_AS:[0-9]+]](2) +; CHECK64: ld [[ADDR:[0-9]+]], L..C[[TL_AS:[0-9]+]](2) +; CHECK: lwz 3, 0([[ADDR]]) + +;; Check TOC entires have correct storage mapping class +; CHECK: L..C[[TL_A]]: +; CHECK: .tc a[TC],a[UA] +; CHECK: L..C[[TL_B]]: +; CHECK: .tc b[TE],b[UA] +; CHECK: L..C[[TL_C]]: +; CHECK: .tc c[TC],c[RW] +; CHECK: L..C[[TL_D]]: +; CHECK: .tc d[TE],d[RW] +; CHECK: L..C[[TL_E]]: +; CHECK-SMALL: .tc e[TC],e[UA] +; CHECK-LARGE: .tc e[TE],e[UA] +; CHECK: L..C[[TL_F]]: +; CHECK-SMALL: .tc f[TC],f[RW] +; CHECK-LARGE: .tc f[TE],f[RW] +; CHECK: L..C[[TL_AL]]: +; CHECK: .tc al[TE],al +; CHECK: L..C[[TL_AS]]: +; CHECK: .tc as[TC],as diff --git a/llvm/test/CodeGen/PowerPC/aix-overflow-toc-data.py b/llvm/test/CodeGen/PowerPC/aix-overflow-toc-data.py new file mode 100644 index 0000000000000000000000000000000000000000..276c6da3feae2484c7f2c78bbd9a0de57c3628c6 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-overflow-toc-data.py @@ -0,0 +1,59 @@ +# UNSUPPORTED: expensive_checks, debug + +# RUN: %python %s > %t.ll +# RUN: llc -mtriple powerpc-ibm-aix-xcoff -code-model=small -mcpu=pwr7 -mattr=-altivec -O0 < %t.ll | \ +# RUN: FileCheck --check-prefix=ASM32 %s + +# RUN: llc -mtriple powerpc64-ibm-aix-xcoff -code-model=small -mcpu=pwr7 -mattr=-altivec -O0 < %t.ll | \ +# RUN: FileCheck --check-prefix=ASM64 %s + +# RUN: llc -mtriple powerpc-ibm-aix-xcoff -code-model=small -mcpu=pwr7 -mattr=-altivec -O0 \ +# RUN: -filetype=obj -o %t.o < %t.ll +# RUN: llvm-objdump --no-print-imm-hex -D -r --symbol-description %t.o | FileCheck -D#NFA=2 --check-prefix=DIS32 %s + +# RUN: llc -mtriple powerpc64-ibm-aix-xcoff -code-model=small -mcpu=pwr7 -mattr=-altivec -O0 \ +# RUN: -filetype=obj -o %t.o < %t.ll +# RUN: llvm-objdump --no-print-imm-hex -D -r --symbol-description %t.o | FileCheck -D#NFA=2 --check-prefix=DIS64 %s + +numentries = 8195 +for x in range(0, numentries): + print("@a%d = global i32 0, align 4 #0" % (x)) + +print("define void @foo() {") +print("entry:") +for x in range(0, numentries): + print("store i32 1, i32* @a%d, align 4" % (x)) +print("ret void") +print("}") + +print('attributes #0 = { "toc-data" }') + +# 32-bit assembly check +# ASM32: la 4, a0[TD](2) +# ASM32: la 4, a1[TD](2) + +# ASM32: la 4, a8191[TD](2) +# ASM32: la 4, a8192[TD](2) +# ASM32: la 4, a8193[TD](2) + +# 64-bit assembly check +# ASM64: la 4, a0[TD](2) +# ASM64: la 4, a1[TD](2) + +# ASM64: la 4, a8191[TD](2) +# ASM64: la 4, a8192[TD](2) +# ASM64: la 4, a8193[TD](2) + +# DIS32: fffc: 38 82 7f fc addi 4, 2, 32764 +# DIS32: 0000fffe: R_TOC (idx: [[#NFA+16391]]) a8191[TD] +# DIS32: 10004: 38 82 80 00 addi 4, 2, -32768 +# DIS32: 00010006: R_TOC (idx: [[#NFA+16393]]) a8192[TD] +# DIS32: 1000c: 38 82 80 04 addi 4, 2, -32764 +# DIS32: 0001000e: R_TOC (idx: [[#NFA+16395]]) a8193[TD] + +# DIS64: fffc: 38 82 7f fc addi 4, 2, 32764 +# DIS64: 0000fffe: R_TOC (idx: [[#NFA+16391]]) a8191[TD] +# DIS64: 10004: 38 82 80 00 addi 4, 2, -32768 +# DIS64: 00010006: R_TOC (idx: [[#NFA+16393]]) a8192[TD] +# DIS64: 1000c: 38 82 80 04 addi 4, 2, -32764 +# DIS64: 0001000e: R_TOC (idx: [[#NFA+16395]]) a8193[TD] diff --git a/llvm/test/CodeGen/PowerPC/aix-small-local-dynamic-tls-largeaccess.ll b/llvm/test/CodeGen/PowerPC/aix-small-local-dynamic-tls-largeaccess.ll new file mode 100644 index 0000000000000000000000000000000000000000..eb16bae67150e3a2b4011c6b20bd20efb1c59d03 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-small-local-dynamic-tls-largeaccess.ll @@ -0,0 +1,632 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff < %s \ +; RUN: | FileCheck %s --check-prefix=SMALL-LOCAL-DYNAMIC-SMALLCM64 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff --code-model=large \ +; RUN: < %s | FileCheck %s \ +; RUN: --check-prefix=SMALL-LOCAL-DYNAMIC-LARGECM64 + +; Test disassembly of object. +; RUN: llc -verify-machineinstrs -mcpu=pwr7 \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff -xcoff-traceback-table=false \ +; RUN: --code-model=large -filetype=obj -o %t.o < %s +; RUN: llvm-objdump -D -r --symbol-description %t.o | FileCheck -D#NFA=2 --check-prefix=DIS %s + +@ElementIntTLSv1 = thread_local(localdynamic) global [8187 x i32] zeroinitializer, align 4 ; Within 32K +@ElementIntTLS2 = thread_local(localdynamic) global [4000 x i32] zeroinitializer, align 4 +@ElementIntTLS3 = thread_local(localdynamic) global [4000 x i32] zeroinitializer, align 4 +@ElementIntTLS4 = thread_local(localdynamic) global [4000 x i32] zeroinitializer, align 4 +@ElementIntTLS5 = thread_local(localdynamic) global [4000 x i32] zeroinitializer, align 4 +@ElementIntTLSv2 = thread_local(localdynamic) global [9000 x i32] zeroinitializer, align 4 ; Beyond 32K + +@ElementLongTLS6 = external thread_local(localdynamic) global [60 x i64], align 8 +@ElementLongTLS2 = thread_local(localdynamic) global [3000 x i64] zeroinitializer, align 8 ; Within 32K +@MyTLSGDVar = thread_local global [800 x i64] zeroinitializer, align 8 +@ElementLongTLS3 = thread_local(localdynamic) global [3000 x i64] zeroinitializer, align 8 +@ElementLongTLS4 = thread_local(localdynamic) global [3000 x i64] zeroinitializer, align 8 +@ElementLongTLS5 = thread_local(localdynamic) global [3000 x i64] zeroinitializer, align 8 +@ElementLongTLS = thread_local(localdynamic) local_unnamed_addr global [7800 x i64] zeroinitializer, align 8 ; Beyond 32K + +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) #1 + +; All accesses use a "faster" local-dynamic sequence directly off the module handle. +; Exercise PPCXCOFFObjectWriter::getRelocTypeAndSignSize/fixup_ppc_half16. +define signext i32 @test1() { +; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: test1: +; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r6, L..C1(r2) # target-flags(ppc-tlsld) @ElementIntTLS2 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r7, L..C2(r2) # target-flags(ppc-tlsld) @ElementIntTLS3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r8, L..C3(r2) # target-flags(ppc-tlsld) @ElementIntTLS4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r9, L..C4(r2) # target-flags(ppc-tlsld) @ElementIntTLS5 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r5, L..C5(r2) # target-flags(ppc-tlsld) @ElementIntTLSv1 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 1 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r6, r3, r6 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r7, r3, r7 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r8, r3, r8 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r9, r3, r9 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stwux r4, r3, r5 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r4, 24(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 2 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r3, 320(r6) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r3, 324(r7) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 88 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r4, 328(r8) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r3, 332(r9) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 102 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-LABEL: test1: +; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C1@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r7, L..C2@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r8, L..C3@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r9, L..C4@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r7, L..C2@l(r7) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r8, L..C3@l(r8) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r9, L..C4@l(r9) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r5, L..C1@l(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C5@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 1 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r6, L..C5@l(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r7, r3, r7 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r8, r3, r8 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r9, r3, r9 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r6, r3, r6 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stwux r4, r3, r5 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r4, 24(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 2 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r3, 320(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r3, 324(r7) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 88 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r4, 328(r8) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r3, 332(r9) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 102 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +entry: + %tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ElementIntTLSv1) + store i32 1, ptr %tls1, align 4 + %arrayidx1 = getelementptr inbounds [8187 x i32], ptr %tls1, i64 0, i64 6 + store i32 4, ptr %arrayidx1, align 4 + %tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ElementIntTLS2) + %arrayidx2 = getelementptr inbounds [4000 x i32], ptr %tls2, i64 0, i64 80 + store i32 2, ptr %arrayidx2, align 4 + %tls3 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ElementIntTLS3) + %arrayidx3 = getelementptr inbounds [4000 x i32], ptr %tls3, i64 0, i64 81 + store i32 3, ptr %arrayidx3, align 4 + %tls4 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ElementIntTLS4) + %arrayidx4 = getelementptr inbounds [4000 x i32], ptr %tls4, i64 0, i64 82 + store i32 4, ptr %arrayidx4, align 4 + %tls5 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ElementIntTLS5) + %arrayidx5 = getelementptr inbounds [4000 x i32], ptr %tls5, i64 0, i64 83 + store i32 88, ptr %arrayidx5, align 4 + %load1 = load i32, ptr %tls1, align 4 + %load2 = load i32, ptr %arrayidx1, align 4 + %load3 = load i32, ptr %arrayidx2, align 4 + %load4 = load i32, ptr %arrayidx3, align 4 + %load5 = load i32, ptr %arrayidx4, align 4 + %add = add i32 %load1, 88 + %add6 = add i32 %add, %load2 + %add8 = add i32 %add6, %load3 + %add10 = add i32 %add8, %load4 + %add12 = add i32 %add10, %load5 + ret i32 %add12 +} + +; All accesses use a "faster" local-dynamic sequence directly off the module handle. +; Exercise PPCXCOFFObjectWriter::getRelocTypeAndSignSize/fixup_ppc_half16ds. +define i64 @test2() { +; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: test2: +; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C6(r2) # target-flags(ppc-tlsld) @ElementLongTLS6 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mr r6, r3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 212 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r4, r6, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r3, 424(r4) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C7(r2) # target-flags(ppc-tlsld) @ElementLongTLS2 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 203 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r3, r6, r3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r4, 1200(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C8(r2) # target-flags(ppc-tlsgdm) @MyTLSGDVar +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C9(r2) # target-flags(ppc-tlsgd) @MyTLSGDVar +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_addr[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 44 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r4, 440(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C10(r2) # target-flags(ppc-tlsld) @ElementLongTLS3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 6 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r3, r6, r3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r4, 2000(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C11(r2) # target-flags(ppc-tlsld) @ElementLongTLS4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 100 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r4, r6, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r3, 6800(r4) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C12(r2) # target-flags(ppc-tlsld) @ElementLongTLS5 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 882 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r3, r6, r3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r4, 8400(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 1191 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-LABEL: test2: +; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r7, L..C6@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 212 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mr r6, r3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C6@l(r7) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r3, r6, r3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r4, 424(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C7@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 203 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C7@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r3, r6, r3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r4, 1200(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C8@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r4, L..C9@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C8@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C9@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_addr[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 44 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r4, 440(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C10@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 6 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C10@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r3, r6, r3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r4, 2000(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C11@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 100 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C11@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r3, r6, r3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r4, 6800(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C12@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 882 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C12@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r3, r6, r3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r4, 8400(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 1191 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +entry: + %tls1 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @ElementLongTLS6) + %arrayidx = getelementptr inbounds [60 x i64], ptr %tls1, i64 0, i64 53 + store i64 212, ptr %arrayidx, align 8 + %tls2 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @ElementLongTLS2) + %arrayidx1 = getelementptr inbounds [3000 x i64], ptr %tls2, i64 0, i64 150 + store i64 203, ptr %arrayidx1, align 8 + %tls3 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @MyTLSGDVar) + %arrayidx2 = getelementptr inbounds [800 x i64], ptr %tls3, i64 0, i64 55 + store i64 44, ptr %arrayidx2, align 8 + %tls4 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @ElementLongTLS3) + %arrayidx3 = getelementptr inbounds [3000 x i64], ptr %tls4, i64 0, i64 250 + store i64 6, ptr %arrayidx3, align 8 + %tls5 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @ElementLongTLS4) + %arrayidx4 = getelementptr inbounds [3000 x i64], ptr %tls5, i64 0, i64 850 + store i64 100, ptr %arrayidx4, align 8 + %tls6 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @ElementLongTLS5) + %arrayidx5 = getelementptr inbounds [3000 x i64], ptr %tls6, i64 0, i64 1050 + store i64 882, ptr %arrayidx5, align 8 + %load1 = load i64, ptr %arrayidx1, align 8 + %load2 = load i64, ptr %arrayidx3, align 8 + %load3 = load i64, ptr %arrayidx4, align 8 + %add = add i64 %load1, 882 + %add9 = add i64 %add, %load2 + %add11 = add i64 %add9, %load3 + ret i64 %add11 +} + +; Example of one access using the regular local-dynamic access from the TOC. +define signext i32 @test3() { +; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: test3: +; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r6, L..C1(r2) # target-flags(ppc-tlsld) @ElementIntTLS2 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r7, L..C2(r2) # target-flags(ppc-tlsld) @ElementIntTLS3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r8, L..C3(r2) # target-flags(ppc-tlsld) @ElementIntTLS4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r9, L..C4(r2) # target-flags(ppc-tlsld) @ElementIntTLS5 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r5, L..C13(r2) # target-flags(ppc-tlsld) @ElementIntTLSv2 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 1 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r6, r3, r6 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r7, r3, r7 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r8, r3, r8 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r9, r3, r9 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stwux r4, r3, r5 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r4, 4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r4, 24(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 2 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r3, 320(r6) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r3, 324(r7) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 88 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r4, 328(r8) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stw r3, 332(r9) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: li r3, 102 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-LABEL: test3: +; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C13@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r7, L..C2@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r8, L..C3@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r9, L..C4@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r7, L..C2@l(r7) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r8, L..C3@l(r8) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r9, L..C4@l(r9) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r5, L..C13@l(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C5@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 1 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r6, L..C5@l(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r7, r3, r7 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r8, r3, r8 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r9, r3, r9 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r6, r3, r6 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stwux r4, r3, r5 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r4, 4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r4, 24(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 2 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r3, 320(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r3, 324(r7) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 88 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r4, 328(r8) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stw r3, 332(r9) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: li r3, 102 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +entry: + %tls1 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ElementIntTLSv2) + store i32 1, ptr %tls1, align 4 + %arrayidx1 = getelementptr inbounds [9000 x i32], ptr %tls1, i64 0, i64 6 + store i32 4, ptr %arrayidx1, align 4 + %tls2 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ElementIntTLS2) + %arrayidx2 = getelementptr inbounds [4000 x i32], ptr %tls2, i64 0, i64 80 + store i32 2, ptr %arrayidx2, align 4 + %tls3 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ElementIntTLS3) + %arrayidx3 = getelementptr inbounds [4000 x i32], ptr %tls3, i64 0, i64 81 + store i32 3, ptr %arrayidx3, align 4 + %tls4 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ElementIntTLS4) + %arrayidx4 = getelementptr inbounds [4000 x i32], ptr %tls4, i64 0, i64 82 + store i32 4, ptr %arrayidx4, align 4 + %tls5 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @ElementIntTLS5) + %arrayidx5 = getelementptr inbounds [4000 x i32], ptr %tls5, i64 0, i64 83 + store i32 88, ptr %arrayidx5, align 4 + %load1 = load i32, ptr %tls1, align 4 + %load2 = load i32, ptr %arrayidx1, align 4 + %load3 = load i32, ptr %arrayidx2, align 4 + %load4 = load i32, ptr %arrayidx3, align 4 + %load5 = load i32, ptr %arrayidx4, align 4 + %add = add i32 %load1, 88 + %add9 = add i32 %add, %load2 + %add11 = add i32 %add9, %load3 + %add13 = add i32 %add11, %load4 + %add15 = add i32 %add13, %load5 + ret i32 %add15 +} + +; DIS: file format aix5coff64-rs6000 +; DIS: Disassembly of section .text: +; DIS: 0000000000000000 (idx: [[#NFA+9]]) .test1: +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} mflr 0 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stdu 1, -48(1) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 3, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+23]]) _$TLSML[TC] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 6, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+25]]) ElementIntTLSv1[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} std 0, 64(1) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 7, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+27]]) ElementIntTLS3[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 3, 0(3) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+23]]) _$TLSML[TC] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 8, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+29]]) ElementIntTLS4[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 9, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+31]]) ElementIntTLS5[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 7, 16(7) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+27]]) ElementIntTLS3[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 8, 24(8) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+29]]) ElementIntTLS4[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 9, 32(9) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+31]]) ElementIntTLS5[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} bla 0x0 +; DIS-NEXT: {{0*}}[[#ADDR]]: R_RBA (idx: [[#NFA+1]]) .__tls_get_mod[PR] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 5, 8(6) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+25]]) ElementIntTLSv1[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 6, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+33]]) ElementIntTLS2[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 1 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 6, 40(6) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+33]]) ElementIntTLS2[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 7, 3, 7 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 8, 3, 8 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 9, 3, 9 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 6, 3, 6 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stwux 4, 3, 5 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 4 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, 24(3) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 2 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, 320(6) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 3 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, 324(7) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 88 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, 328(8) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, 332(9) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 102 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addi 1, 1, 48 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 0, 16(1) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} mtlr 0 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} blr + +; DIS: 0000000000000090 (idx: [[#NFA+11]]) .test2: +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} mflr 0 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stdu 1, -48(1) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 3, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+23]]) _$TLSML[TC] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} std 0, 64(1) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 7, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+35]]) ElementLongTLS6[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 3, 0(3) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+23]]) _$TLSML[TC] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} bla 0x0 +; DIS-NEXT: {{0*}}[[#ADDR]]: R_RBA (idx: [[#NFA+1]]) .__tls_get_mod[PR] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 212 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} mr 6, 3 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 3, 48(7) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+35]]) ElementLongTLS6[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 3, 6, 3 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} std 4, 424(3) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 3, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+37]]) ElementLongTLS2[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 203 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 3, 56(3) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+37]]) ElementLongTLS2[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 3, 6, 3 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} std 4, 1200(3) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 3, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+39]]) .MyTLSGDVar[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 4, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+41]]) MyTLSGDVar[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 3, 64(3) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+39]]) .MyTLSGDVar[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 4, 72(4) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+41]]) MyTLSGDVar[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} bla 0x0 +; DIS-NEXT: {{0*}}[[#ADDR]]: R_RBA (idx: [[#NFA+3]]) .__tls_get_addr[PR] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 44 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} std 4, 440(3) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 3, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+43]]) ElementLongTLS3[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 6 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 3, 80(3) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+43]]) ElementLongTLS3[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 3, 6, 3 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} std 4, 2000(3) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 3, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+45]]) ElementLongTLS4[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 100 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 3, 88(3) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+45]]) ElementLongTLS4[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 3, 6, 3 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} std 4, 6800(3) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 3, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+47]]) ElementLongTLS5[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 882 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 3, 96(3) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+47]]) ElementLongTLS5[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 3, 6, 3 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} std 4, 8400(3) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 1191 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addi 1, 1, 48 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 0, 16(1) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} mtlr 0 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} blr + +; DIS: 0000000000000140 (idx: [[#NFA+13]]) .test3: +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} mflr 0 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stdu 1, -48(1) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 3, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+23]]) _$TLSML[TC] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 6, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+49]]) ElementIntTLSv2[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} std 0, 64(1) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 7, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+27]]) ElementIntTLS3[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 3, 0(3) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+23]]) _$TLSML[TC] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 8, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+29]]) ElementIntTLS4[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 9, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+31]]) ElementIntTLS5[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 7, 16(7) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+27]]) ElementIntTLS3[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 8, 24(8) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+29]]) ElementIntTLS4[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 9, 32(9) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+31]]) ElementIntTLS5[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} bla 0x0 +; DIS-NEXT: {{0*}}[[#ADDR]]: R_RBA (idx: [[#NFA+1]]) .__tls_get_mod[PR] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 5, 104(6) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+49]]) ElementIntTLSv2[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addis 6, 2, 0 +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCU (idx: [[#NFA+33]]) ElementIntTLS2[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 1 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 6, 40(6) +; DIS-NEXT: {{0*}}[[#ADDR + 2]]: R_TOCL (idx: [[#NFA+33]]) ElementIntTLS2[TE] +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 7, 3, 7 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 8, 3, 8 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 9, 3, 9 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} add 6, 3, 6 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stwux 4, 3, 5 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 4, 4 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, 24(3) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 2 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, 320(6) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 3 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, 324(7) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 88 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 4, 328(8) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} stw 3, 332(9) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} li 3, 102 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} addi 1, 1, 48 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} ld 0, 16(1) +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} mtlr 0 +; DIS-NEXT: [[#%x, ADDR:]]: {{.*}} blr + +; DIS: Disassembly of section .data: + +; DIS: 00000000000001d0 (idx: 17) test1[DS]: +; DIS-NEXT: 1d0: 00 00 00 00 +; DIS-NEXT: 00000000000001d0: R_POS (idx: [[#NFA+9]]) .test1 +; DIS-NEXT: 1d4: 00 00 00 00 +; DIS-NEXT: 1d8: 00 00 00 00 +; DIS-NEXT: 00000000000001d8: R_POS (idx: [[#NFA+21]]) TOC[TC0] +; DIS-NEXT: 1dc: 00 00 02 18 + +; DIS: 00000000000001e8 (idx: 19) test2[DS]: +; DIS-NEXT: 1e8: 00 00 00 00 +; DIS-NEXT: 00000000000001e8: R_POS (idx: [[#NFA+11]]) .test2 +; DIS-NEXT: 1ec: 00 00 00 90 +; DIS-NEXT: 1f0: 00 00 00 00 +; DIS-NEXT: 00000000000001f0: R_POS (idx: [[#NFA+21]]) TOC[TC0] +; DIS-NEXT: 1f4: 00 00 02 18 + +; DIS: 0000000000000200 (idx: 21) test3[DS]: +; DIS-NEXT: 200: 00 00 00 00 +; DIS-NEXT: 0000000000000200: R_POS (idx: [[#NFA+13]]) .test3 +; DIS-NEXT: 204: 00 00 01 40 +; DIS-NEXT: 208: 00 00 00 00 +; DIS-NEXT: 0000000000000208: R_POS (idx: [[#NFA+21]]) TOC[TC0] +; DIS-NEXT: 20c: 00 00 02 18 + +; DIS: 0000000000000218 (idx: 25) _$TLSML[TC]: +; DIS-NEXT: 218: 00 00 00 00 +; DIS-NEXT: 0000000000000218: R_TLSML (idx: [[#NFA+23]]) _$TLSML[TC] +; DIS-NEXT: 21c: 00 00 00 00 + +; DIS: 0000000000000220 (idx: 27) ElementIntTLSv1[TE]: +; DIS-NEXT: 220: 00 00 00 00 +; DIS-NEXT: 0000000000000220: R_TLS_LD (idx: [[#NFA+51]]) ElementIntTLSv1[TL] +; DIS-NEXT: 224: 00 00 00 00 + +; DIS: 0000000000000228 (idx: 29) ElementIntTLS3[TE]: +; DIS-NEXT: 228: 00 00 00 00 +; DIS-NEXT: 0000000000000228: R_TLS_LD (idx: [[#NFA+55]]) ElementIntTLS3[TL] +; DIS-NEXT: 22c: 00 00 be 6c + +; DIS: 0000000000000230 (idx: 31) ElementIntTLS4[TE]: +; DIS-NEXT: 230: 00 00 00 00 +; DIS-NEXT: 0000000000000230: R_TLS_LD (idx: [[#NFA+57]]) ElementIntTLS4[TL] +; DIS-NEXT: 234: 00 00 fc ec + +; DIS: 0000000000000238 (idx: 33) ElementIntTLS5[TE]: +; DIS-NEXT: 238: 00 00 00 00 +; DIS-NEXT: 0000000000000238: R_TLS_LD (idx: [[#NFA+59]]) ElementIntTLS5[TL] +; DIS-NEXT: 23c: 00 01 3b 6c + +; DIS: 0000000000000240 (idx: 35) ElementIntTLS2[TE]: +; DIS-NEXT: 240: 00 00 00 00 +; DIS-NEXT: 0000000000000240: R_TLS_LD (idx: [[#NFA+53]]) ElementIntTLS2[TL] +; DIS-NEXT: 244: 00 00 7f ec + +; DIS: 0000000000000248 (idx: 37) ElementLongTLS6[TE]: +; DIS-NEXT: 248: 00 00 00 00 +; DIS-NEXT: 0000000000000248: R_TLS_LD (idx: [[#NFA+5]]) ElementLongTLS6[UL] +; DIS-NEXT: 24c: 00 00 00 00 + +; DIS: 0000000000000250 (idx: 39) ElementLongTLS2[TE]: +; DIS-NEXT: 250: 00 00 00 00 +; DIS-NEXT: 0000000000000250: R_TLS_LD (idx: [[#NFA+63]]) ElementLongTLS2[TL] +; DIS-NEXT: 254: 00 02 06 90 + +; DIS: 0000000000000258 (idx: 41) .MyTLSGDVar[TE]: +; DIS-NEXT: 258: 00 00 00 00 +; DIS-NEXT: 0000000000000258: R_TLSM (idx: [[#NFA+65]]) MyTLSGDVar[TL] +; DIS-NEXT: 25c: 00 00 00 00 + +; DIS: 0000000000000260 (idx: 43) MyTLSGDVar[TE]: +; DIS-NEXT: 260: 00 00 00 00 +; DIS-NEXT: 0000000000000260: R_TLS (idx: [[#NFA+65]]) MyTLSGDVar[TL] +; DIS-NEXT: 264: 00 02 64 50 + +; DIS: 0000000000000268 (idx: 45) ElementLongTLS3[TE]: +; DIS-NEXT: 268: 00 00 00 00 +; DIS-NEXT: 0000000000000268: R_TLS_LD (idx: [[#NFA+67]]) ElementLongTLS3[TL] +; DIS-NEXT: 26c: 00 02 7d 50 + +; DIS: 0000000000000270 (idx: 47) ElementLongTLS4[TE]: +; DIS-NEXT: 270: 00 00 00 00 +; DIS-NEXT: 0000000000000270: R_TLS_LD (idx: [[#NFA+69]]) ElementLongTLS4[TL] +; DIS-NEXT: 274: 00 02 db 10 + +; DIS: 0000000000000278 (idx: 49) ElementLongTLS5[TE]: +; DIS-NEXT: 278: 00 00 00 00 +; DIS-NEXT: 0000000000000278: R_TLS_LD (idx: [[#NFA+71]]) ElementLongTLS5[TL] +; DIS-NEXT: 27c: 00 03 38 d0 + +; DIS: 0000000000000280 (idx: 51) ElementIntTLSv2[TE]: +; DIS-NEXT: 280: 00 00 00 00 +; DIS-NEXT: 0000000000000280: R_TLS_LD (idx: [[#NFA+61]]) ElementIntTLSv2[TL] +; DIS-NEXT: 284: 00 01 79 ec + +; DIS: Disassembly of section .tdata: +; DIS: 0000000000000000 (idx: [[#NFA+51]]) ElementIntTLSv1[TL]: +; DIS: 0000000000007fec (idx: [[#NFA+53]]) ElementIntTLS2[TL]: +; DIS: 000000000000be6c (idx: [[#NFA+55]]) ElementIntTLS3[TL]: +; DIS: 000000000000fcec (idx: [[#NFA+57]]) ElementIntTLS4[TL]: +; DIS: 0000000000013b6c (idx: [[#NFA+59]]) ElementIntTLS5[TL]: +; DIS: 00000000000179ec (idx: [[#NFA+61]]) ElementIntTLSv2[TL]: +; DIS: 0000000000020690 (idx: [[#NFA+63]]) ElementLongTLS2[TL]: +; DIS: 0000000000026450 (idx: [[#NFA+65]]) MyTLSGDVar[TL]: +; DIS: 0000000000027d50 (idx: [[#NFA+67]]) ElementLongTLS3[TL]: +; DIS: 000000000002db10 (idx: [[#NFA+69]]) ElementLongTLS4[TL]: +; DIS: 00000000000338d0 (idx: [[#NFA+71]]) ElementLongTLS5[TL]: +; DIS: 0000000000039690 (idx: [[#NFA+73]]) ElementLongTLS[TL]: diff --git a/llvm/test/CodeGen/PowerPC/aix-small-local-dynamic-tls-types.ll b/llvm/test/CodeGen/PowerPC/aix-small-local-dynamic-tls-types.ll new file mode 100644 index 0000000000000000000000000000000000000000..d996d86a23d868097e009016a5f6ea9509dd474c --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-small-local-dynamic-tls-types.ll @@ -0,0 +1,1066 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff < %s \ +; RUN: | FileCheck %s --check-prefix=SMALL-LOCAL-DYNAMIC-SMALLCM64 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff --code-model=large \ +; RUN: < %s | FileCheck %s \ +; RUN: --check-prefix=SMALL-LOCAL-DYNAMIC-LARGECM64 +; RUN: llc -O0 -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff < %s \ +; RUN: | FileCheck %s --check-prefix=SMALL-LOCAL-DYNAMIC-SMALLCM64-O0 +; RUN: llc -O0 -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff --code-model=large \ +; RUN: < %s | FileCheck %s \ +; RUN: --check-prefix=SMALL-LOCAL-DYNAMIC-LARGECM64-O0 + +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) #1 +@tlv_int_init = local_unnamed_addr global i32 87, align 4 + +@tlv_char = thread_local(localdynamic) global i8 1, align 1 +@tlv_short = thread_local(localdynamic) global i8 1, align 2 +@tlv_int = thread_local(localdynamic) global i32 1, align 4 +@internal_tlv_int = internal thread_local(localdynamic) global i32 1, align 4 +@tlv_long = thread_local(localdynamic) global i64 1, align 8 +@internal_tlv_long = internal thread_local(localdynamic) global i64 1, align 8 +@tlv_float = thread_local(localdynamic) global float 1.000000e+00, align 4 +@internal_tlv_double = internal thread_local(localdynamic) global double 1.000000e+00, align 8 + +%struct.anon = type { i32 } +@ThreadLocalStruct = thread_local(localdynamic) global %struct.anon zeroinitializer, align 1 +@a = thread_local(localdynamic) global [87 x i32] zeroinitializer, align 4 + +define nonnull ptr @AddrTest1() local_unnamed_addr { +; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: AddrTest1: +; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C1(r2) # target-flags(ppc-tlsld) @a +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r3, r3, 12 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-LABEL: AddrTest1: +; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C1@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C1@l(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r3, r3, 12 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: AddrTest1: +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C1(r2) # target-flags(ppc-tlsld) @a +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r3, r3, 12 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: AddrTest1: +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C0@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r3, r3, 12 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +entry: + %tlv_addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @a) + %arrayidx = getelementptr inbounds [87 x i32], ptr %tlv_addr, i64 0, i64 3 + ret ptr %arrayidx +} + +define signext i32 @testUnaligned() { +; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: testUnaligned: +; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C2(r2) # target-flags(ppc-tlsld) @ThreadLocalStruct +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwax r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-LABEL: testUnaligned: +; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C2@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C2@l(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lwax r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testUnaligned: +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C2(r2) # target-flags(ppc-tlsld) @ThreadLocalStruct +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwa r3, 0(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testUnaligned: +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C2@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C2@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwa r3, 0(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +entry: + %tlv_addr = call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @ThreadLocalStruct) + %x = getelementptr inbounds %struct.anon, ptr %tlv_addr, i32 0, i32 0 + %value = load i32, ptr %x, align 1 + ret i32 %value +} + +define void @testChar(i8 noundef signext %x) { +; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: testChar: +; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mr r6, r3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C3(r2) # target-flags(ppc-tlsld) @tlv_char +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stbx r6, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-LABEL: testChar: +; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mr r6, r3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r7, L..C3@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C3@l(r7) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stbx r6, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testChar: +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: # kill: def $r3 killed $r3 killed $x3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stw r3, 60(r1) # 4-byte Folded Spill +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mr r4, r3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwz r3, 60(r1) # 4-byte Folded Reload +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r5, L..C3(r2) # target-flags(ppc-tlsld) @tlv_char +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r4, r4, r5 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stb r3, 0(r4) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testChar: +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: # kill: def $r3 killed $r3 killed $x3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stw r3, 60(r1) # 4-byte Folded Spill +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C3@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 48(r1) # 8-byte Folded Spill +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r5, 48(r1) # 8-byte Folded Reload +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mr r4, r3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwz r3, 60(r1) # 4-byte Folded Reload +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r5, L..C3@l(r5) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r4, r4, r5 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stb r3, 0(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +entry: + %tlv_addr = tail call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @tlv_char) + store i8 %x, ptr %tlv_addr, align 1 + ret void +} + +define void @testShort(i16 noundef signext %x) { +; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: testShort: +; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mr r6, r3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C4(r2) # target-flags(ppc-tlsld) @tlv_short +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: sthx r6, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-LABEL: testShort: +; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mr r6, r3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r7, L..C4@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C4@l(r7) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: sthx r6, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testShort: +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: # kill: def $r3 killed $r3 killed $x3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stw r3, 60(r1) # 4-byte Folded Spill +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mr r4, r3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwz r3, 60(r1) # 4-byte Folded Reload +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r5, L..C4(r2) # target-flags(ppc-tlsld) @tlv_short +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r4, r4, r5 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: sth r3, 0(r4) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testShort: +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: # kill: def $r3 killed $r3 killed $x3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stw r3, 60(r1) # 4-byte Folded Spill +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C4@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 48(r1) # 8-byte Folded Spill +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r5, 48(r1) # 8-byte Folded Reload +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mr r4, r3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwz r3, 60(r1) # 4-byte Folded Reload +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r5, L..C4@l(r5) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r4, r4, r5 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: sth r3, 0(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +entry: + %tlv_addr = tail call align 2 ptr @llvm.threadlocal.address.p0(ptr align 2 @tlv_short) + store i16 %x, ptr %tlv_addr, align 2 + ret void +} + +define signext i32 @testInt1() { +; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: testInt1: +; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C5(r2) # target-flags(ppc-tlsld) @tlv_int +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwax r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-LABEL: testInt1: +; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C5@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C5@l(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lwax r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testInt1: +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C5(r2) # target-flags(ppc-tlsld) @tlv_int +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwa r3, 0(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testInt1: +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C5@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C5@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwa r3, 0(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +entry: + %tlv_addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @tlv_int) + %value = load i32, ptr %tlv_addr, align 4 + ret i32 %value +} + +define signext i32 @testInt2() { +; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: testInt2: +; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C6(r2) # target-flags(ppc-tlsld) @internal_tlv_int +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwzx r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C7(r2) # @tlv_int_init +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwz r4, 0(r4) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: add r3, r4, r3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: extsw r3, r3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-LABEL: testInt2: +; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C6@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C6@l(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lwzx r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r4, L..C7@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C7@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lwz r4, 0(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: add r3, r4, r3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: extsw r3, r3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testInt2: +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C6(r2) # target-flags(ppc-tlsld) @internal_tlv_int +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwz r4, 0(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C7(r2) # @tlv_int_init +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwz r3, 0(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: extsw r3, r3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testInt2: +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C6@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C6@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwz r4, 0(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C7@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C7@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwz r3, 0(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: extsw r3, r3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +entry: + %tlv_addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @internal_tlv_int) + %tlv_val = load i32, ptr %tlv_addr, align 4 + %global_val = load i32, ptr @tlv_int_init, align 4 + %sum = add nsw i32 %global_val, %tlv_val + ret i32 %sum +} + +define signext i64 @testLong1() { +; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: testLong1: +; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C8(r2) # target-flags(ppc-tlsld) @tlv_long +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ldx r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-LABEL: testLong1: +; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C8@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C8@l(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ldx r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testLong1: +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C8(r2) # target-flags(ppc-tlsld) @tlv_long +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, 0(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testLong1: +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C8@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C8@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, 0(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +entry: + %tlv_addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @tlv_long) + %value = load i64, ptr %tlv_addr, align 4 + ret i64 %value +} + +define void @testLong2(i64 noundef signext %x) { +; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: testLong2: +; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C9(r2) # target-flags(ppc-tlsld) @internal_tlv_long +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ldx r5, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r5, r5, 9 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdx r5, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-LABEL: testLong2: +; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C9@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C9@l(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ldx r5, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r5, r5, 9 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdx r5, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testLong2: +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C9(r2) # target-flags(ppc-tlsld) @internal_tlv_long +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r4, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, 0(r4) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r3, r3, 9 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r3, 0(r4) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testLong2: +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C9@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C9@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r4, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, 0(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r3, r3, 9 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 0(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +entry: + %tlv_addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @internal_tlv_long) + %value = load i64, ptr %tlv_addr, align 8 + %add = add nsw i64 %value, 9 + store i64 %add, ptr %tlv_addr, align 8 + ret void +} + +define i32 @testLong3() { +; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: testLong3: +; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C8(r2) # target-flags(ppc-tlsld) @tlv_long +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ldx r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-LABEL: testLong3: +; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C8@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C8@l(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ldx r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testLong3: +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C8(r2) # target-flags(ppc-tlsld) @tlv_long +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, 0(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: # kill: def $r3 killed $r3 killed $x3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: clrldi r3, r3, 32 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testLong3: +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C8@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C8@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, 0(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: # kill: def $r3 killed $r3 killed $x3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: clrldi r3, r3, 32 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +entry: + %tlv_addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @tlv_long) + %value = load i64, ptr %tlv_addr, align 8 + %conv = trunc i64 %value to i32 + ret i32 %conv +} + +define void @testFloat1(float noundef %x) { +; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: testFloat1: +; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: vspltisw v2, 1 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: vspltisw v3, 8 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: xvcvsxwdp vs0, vs34 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C10(r2) # target-flags(ppc-tlsld) @tlv_float +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lfsx f1, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: fadds f0, f1, f0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: xvcvsxwdp vs1, vs35 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: fadds f0, f0, f1 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stfsx f0, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-LABEL: testFloat1: +; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: vspltisw v2, 1 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C10@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: vspltisw v3, 8 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: xvcvsxwdp vs0, vs34 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C10@l(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lfsx f1, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: fadds f0, f1, f0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: xvcvsxwdp vs1, vs35 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: fadds f0, f0, f1 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stfsx f0, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testFloat1: +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C10(r2) # target-flags(ppc-tlsld) @tlv_float +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lfs f0, 0(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C11(r2) # %const.1 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lfs f1, 0(r4) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: fadds f0, f0, f1 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C12(r2) # %const.0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lfs f1, 0(r4) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: fadds f0, f0, f1 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stfs f0, 0(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testFloat1: +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C10@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C10@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lfs f0, 0(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r4, L..C11@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C11@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lfs f1, 0(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: fadds f0, f0, f1 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r4, L..C12@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C12@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lfs f1, 0(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: fadds f0, f0, f1 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stfs f0, 0(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +entry: + %tlv_addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @tlv_float) + %value = load float, ptr %tlv_addr, align 4 + %inc = fadd float %value, 1.000000e+00 + %add = fadd float %inc, 8.000000e+00 + store float %add, ptr %tlv_addr, align 4 + ret void +} + +define i32 @testFloat2() { +; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: testFloat2: +; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C10(r2) # target-flags(ppc-tlsld) @tlv_float +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lfsx f0, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r3, r1, 60 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: xscvdpsxws f0, f0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stfiwx f0, 0, r3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwz r3, 60(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-LABEL: testFloat2: +; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C10@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C10@l(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lfsx f0, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r3, r1, 60 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: xscvdpsxws f0, f0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stfiwx f0, 0, r3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lwz r3, 60(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testFloat2: +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C10(r2) # target-flags(ppc-tlsld) @tlv_float +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lfs f0, 0(r3) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: fctiwz f0, f0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stfd f0, 56(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwa r3, 60(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: clrldi r3, r3, 32 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testFloat2: +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C10@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 48(r1) # 8-byte Folded Spill +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 48(r1) # 8-byte Folded Reload +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C10@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lfs f0, 0(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: fctiwz f0, f0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stfd f0, 56(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwa r3, 60(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: clrldi r3, r3, 32 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +entry: + %tlv_addr = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @tlv_float) + %value = load float, ptr %tlv_addr, align 4 + %conv = fptosi float %value to i32 + ret i32 %conv +} + +define void @testDouble1(double noundef %x) { +; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: testDouble1: +; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C11(r2) # target-flags(ppc-tlsld) @internal_tlv_double +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stfdx f1, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-LABEL: testDouble1: +; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C11@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C11@l(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stfdx f1, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testDouble1: +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -48(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C13(r2) # target-flags(ppc-tlsld) @internal_tlv_double +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stxsdx f1, 0, r3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 48 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testDouble1: +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C13@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C13@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: add r3, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stxsdx f1, 0, r3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +entry: + %tlv_addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @internal_tlv_double) + store double %x, ptr %tlv_addr, align 8 + ret void +} + +define i32 @testDouble2() { +; SMALL-LOCAL-DYNAMIC-SMALLCM64-LABEL: testDouble2: +; SMALL-LOCAL-DYNAMIC-SMALLCM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r4, L..C11(r2) # target-flags(ppc-tlsld) @internal_tlv_double +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lfdx f0, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r3, r1, 60 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: xscvdpsxws f0, f0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: stfiwx f0, 0, r3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: lwz r3, 60(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-LABEL: testDouble2: +; SMALL-LOCAL-DYNAMIC-LARGECM64: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r3, L..C0@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addis r6, L..C11@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r4, L..C11@l(r6) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lfdx f0, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r3, r1, 60 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: xscvdpsxws f0, f0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: stfiwx f0, 0, r3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: lwz r3, 60(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-LABEL: testDouble2: +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stdu r1, -64(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: std r0, 80(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tlsldm) @"_$TLSML" +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r4, L..C13(r2) # target-flags(ppc-tlsld) @internal_tlv_double +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lfdx f0, r3, r4 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: xscvdpsxws f0, f0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r3, r1, 52 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: stfiwx f0, 0, r3 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: lwz r3, 52(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: clrldi r3, r3, 32 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: addi r1, r1, 64 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-SMALLCM64-O0-NEXT: blr +; +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-LABEL: testDouble2: +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0: # %bb.0: # %entry +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mflr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stdu r1, -80(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r0, 96(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C13@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: std r3, 56(r1) # 8-byte Folded Spill +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addis r3, L..C1@u(r2) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r3, L..C1@l(r3) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: bla .__tls_get_mod[PR] +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, 56(r1) # 8-byte Folded Reload +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r4, L..C13@l(r4) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lfdx f0, r3, r4 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: xscvdpsxws f0, f0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r3, r1, 68 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: stfiwx f0, 0, r3 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: lwz r3, 68(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: clrldi r3, r3, 32 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: addi r1, r1, 80 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: ld r0, 16(r1) +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: mtlr r0 +; SMALL-LOCAL-DYNAMIC-LARGECM64-O0-NEXT: blr +entry: + %tlv_addr = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @internal_tlv_double) + %value = load double, ptr %tlv_addr, align 8 + %conv = fptosi double %value to i32 + ret i32 %conv +} diff --git a/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-funcattr.ll b/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-funcattr.ll new file mode 100644 index 0000000000000000000000000000000000000000..38b35dc6c81cf8e2c74c70945e532c51f7288454 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-funcattr.ll @@ -0,0 +1,105 @@ +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff < %s \ +; RUN: | FileCheck %s --check-prefixes=COMMONCM,CHECK-SMALLCM64 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff --code-model=large \ +; RUN: < %s | FileCheck %s --check-prefixes=COMMONCM,CHECK-LARGECM64 + +@mySmallTLS = thread_local(localexec) global [7800 x i64] zeroinitializer, align 8 #0 +@mySmallTLS2 = thread_local(localexec) global [3000 x i64] zeroinitializer, align 8 #0 +@mySmallTLS3 = thread_local(localexec) global [3000 x i64] zeroinitializer, align 8 +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) + +; All accesses use a "faster" local-exec sequence directly off the thread pointer, +; except for mySmallTLS, as this variable is over the 32KB size limit. +define i64 @StoreLargeAccess1() #1 { +; COMMONCM-LABEL: StoreLargeAccess1: +; COMMONCM-NEXT: # %bb.0: # %entry +; CHECK-SMALLCM64: ld r3, L..C0(r2) # target-flags(ppc-tprel) @mySmallTLS +; CHECK-SMALLCM64-NEXT: li r4, 0 +; CHECK-SMALLCM64-NEXT: li r5, 23 +; CHECK-LARGECM64: addis r3, L..C0@u(r2) +; CHECK-LARGECM64-NEXT: li r4, 0 +; CHECK-LARGECM64-NEXT: li r5, 23 +; CHECK-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; COMMONCM: ori r4, r4, 53328 +; COMMONCM-NEXT: add r3, r13, r3 +; COMMONCM-NEXT: stdx r5, r3, r4 +; COMMONCM-NEXT: li r3, 55 +; COMMONCM-NEXT: li r4, 64 +; COMMONCM-NEXT: std r3, (mySmallTLS2[TL]@le+696)-65536(r13) +; COMMONCM-NEXT: li r3, 142 +; COMMONCM-NEXT: std r4, (mySmallTLS3[TL]@le+20000)-131072(r13) +; COMMONCM-NEXT: blr +entry: + %tls0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @mySmallTLS) + %arrayidx = getelementptr inbounds i8, ptr %tls0, i32 53328 + store i64 23, ptr %arrayidx, align 8 + %tls1 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @mySmallTLS2) + %arrayidx1 = getelementptr inbounds i8, ptr %tls1, i32 696 + store i64 55, ptr %arrayidx1, align 8 + %tls2 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @mySmallTLS3) + %arrayidx2 = getelementptr inbounds i8, ptr %tls2, i32 20000 + store i64 64, ptr %arrayidx2, align 8 + %load1 = load i64, ptr %arrayidx, align 8 + %load2 = load i64, ptr %arrayidx1, align 8 + %add1 = add i64 %load1, 64 + %add2 = add i64 %add1, %load2 + ret i64 %add2 +} + +; Since this function does not have the 'aix-small-local-exec-tls` attribute, +; only some local-exec variables should have the small-local-exec TLS access +; sequence (as opposed to all of them). +define i64 @StoreLargeAccess2() { +; COMMONCM-LABEL: StoreLargeAccess2: +; COMMONCM-NEXT: # %bb.0: # %entry +; CHECK-SMALLCM64: ld r5, L..C0(r2) # target-flags(ppc-tprel) @mySmallTLS +; CHECK-SMALLCM64-NEXT: li r3, 0 +; CHECK-SMALLCM64-NEXT: li r4, 23 +; CHECK-SMALLCM64-NEXT: ori r3, r3, 53328 +; CHECK-SMALLCM64-NEXT: add r5, r13, r5 +; CHECK-SMALLCM64-NEXT: stdx r4, r5, r3 +; CHECK-SMALLCM64-NEXT: ld r5, L..C1(r2) # target-flags(ppc-tprel) @mySmallTLS3 +; CHECK-SMALLCM64-NEXT: li r3, 55 +; CHECK-SMALLCM64-NEXT: li r4, 64 +; CHECK-SMALLCM64-NEXT: std r3, mySmallTLS2[TL]@le+696(r13) +; CHECK-SMALLCM64-NEXT: li r3, 142 +; CHECK-SMALLCM64-NEXT: add r5, r13, r5 +; CHECK-SMALLCM64-NEXT: std r4, 20000(r5) +; CHECK-LARGECM64: addis r3, L..C0@u(r2) +; CHECK-LARGECM64-NEXT: li r4, 0 +; CHECK-LARGECM64-NEXT: li r5, 23 +; CHECK-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; CHECK-LARGECM64-NEXT: ori r4, r4, 53328 +; CHECK-LARGECM64-NEXT: add r3, r13, r3 +; CHECK-LARGECM64-NEXT: stdx r5, r3, r4 +; CHECK-LARGECM64-NEXT: addis r3, L..C1@u(r2) +; CHECK-LARGECM64-NEXT: li r4, 55 +; CHECK-LARGECM64-NEXT: li r5, 64 +; CHECK-LARGECM64-NEXT: ld r3, L..C1@l(r3) +; CHECK-LARGECM64-NEXT: std r4, mySmallTLS2[TL]@le+696(r13) +; CHECK-LARGECM64-NEXT: add r3, r13, r3 +; CHECK-LARGECM64-NEXT: std r5, 20000(r3) +; CHECK-LARGECM64-NEXT: li r3, 142 +; COMMONCM-NEXT: blr +; +entry: + %tls0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @mySmallTLS) + %arrayidx = getelementptr inbounds i8, ptr %tls0, i32 53328 + store i64 23, ptr %arrayidx, align 8 + %tls1 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @mySmallTLS2) + %arrayidx1 = getelementptr inbounds i8, ptr %tls1, i32 696 + store i64 55, ptr %arrayidx1, align 8 + %tls2 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @mySmallTLS3) + %arrayidx2 = getelementptr inbounds i8, ptr %tls2, i32 20000 + store i64 64, ptr %arrayidx2, align 8 + %load1 = load i64, ptr %arrayidx, align 8 + %load2 = load i64, ptr %arrayidx1, align 8 + %add1 = add i64 %load1, 64 + %add2 = add i64 %add1, %load2 + ret i64 %add2 +} + +attributes #0 = { "aix-small-tls" } +attributes #1 = { "target-features"="+aix-small-local-exec-tls" } diff --git a/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-loadaddr.ll b/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-loadaddr.ll new file mode 100644 index 0000000000000000000000000000000000000000..c8537fba6a3cff1b3bf44bc453e51de28adf4fbd --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-loadaddr.ll @@ -0,0 +1,222 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff -mattr=-aix-small-local-exec-tls \ +; RUN: < %s | FileCheck %s --check-prefixes=COMMONCM,SMALLCM64 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff --code-model=large \ +; RUN: -mattr=-aix-small-local-exec-tls < %s | \ +; RUN: FileCheck %s --check-prefixes=COMMONCM,LARGECM64 + +; Test that the 'aix-small-tls' global variable attribute generates the +; optimized small-local-exec TLS sequence. Global variables without this +; attribute should still generate a TOC-based local-exec access sequence. + +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) + +@a = thread_local(localexec) global [87 x i8] zeroinitializer, align 1 #0 +@a_noattr = thread_local(localexec) global [87 x i8] zeroinitializer, align 1 +@b = thread_local(localexec) global [87 x i16] zeroinitializer, align 2 #0 +@b_noattr = thread_local(localexec) global [87 x i16] zeroinitializer, align 2 +@c = thread_local(localexec) global [87 x i32] zeroinitializer, align 4 #0 +@c_noattr = thread_local(localexec) global [87 x i32] zeroinitializer, align 4 +@d = thread_local(localexec) global [87 x i64] zeroinitializer, align 8 #0 +@d_noattr = thread_local(localexec) global [87 x i64] zeroinitializer, align 8 #0 + +@e = thread_local(localexec) global [87 x double] zeroinitializer, align 8 #0 +@e_noattr = thread_local(localexec) global [87 x double] zeroinitializer, align 8 +@f = thread_local(localexec) global [87 x float] zeroinitializer, align 4 #0 +@f_noattr = thread_local(localexec) global [87 x float] zeroinitializer, align 4 + +define nonnull ptr @AddrTest1() { +; COMMONCM-LABEL: AddrTest1: +; COMMONCM: # %bb.0: # %entry +; COMMONCM-NEXT: addi r3, r13, a[TL]@le+1 +; COMMONCM-NEXT: blr +entry: + %tls0 = tail call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @a) + %arrayidx = getelementptr inbounds [87 x i8], ptr %tls0, i64 0, i64 1 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest1_NoAttr() { +; SMALLCM64-LABEL: AddrTest1_NoAttr: +; SMALLCM64: # %bb.0: # %entry +; SMALLCM64-NEXT: ld r3, L..C0(r2) # target-flags(ppc-tprel) @a_noattr +; SMALLCM64-NEXT: add r3, r13, r3 +; SMALLCM64-NEXT: addi r3, r3, 1 +; SMALLCM64-NEXT: blr +; +; LARGECM64-LABEL: AddrTest1_NoAttr: +; LARGECM64: # %bb.0: # %entry +; LARGECM64-NEXT: addis r3, L..C0@u(r2) +; LARGECM64-NEXT: ld r3, L..C0@l(r3) +; LARGECM64-NEXT: add r3, r13, r3 +; LARGECM64-NEXT: addi r3, r3, 1 +; LARGECM64-NEXT: blr +entry: + %tls0 = tail call align 1 ptr @llvm.threadlocal.address.p0(ptr align 1 @a_noattr) + %arrayidx = getelementptr inbounds [87 x i8], ptr %tls0, i64 0, i64 1 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest2() { +; COMMONCM-LABEL: AddrTest2: +; COMMONCM: # %bb.0: # %entry +; COMMONCM-NEXT: addi r3, r13, b[TL]@le+4 +; COMMONCM-NEXT: blr +entry: + %tls0 = tail call align 2 ptr @llvm.threadlocal.address.p0(ptr align 2 @b) + %arrayidx = getelementptr inbounds [87 x i16], ptr %tls0, i64 0, i64 2 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest2_NoAttr() { +; SMALLCM64-LABEL: AddrTest2_NoAttr: +; SMALLCM64: # %bb.0: # %entry +; SMALLCM64-NEXT: ld r3, L..C1(r2) # target-flags(ppc-tprel) @b_noattr +; SMALLCM64-NEXT: add r3, r13, r3 +; SMALLCM64-NEXT: addi r3, r3, 4 +; SMALLCM64-NEXT: blr +; +; LARGECM64-LABEL: AddrTest2_NoAttr: +; LARGECM64: # %bb.0: # %entry +; LARGECM64-NEXT: addis r3, L..C1@u(r2) +; LARGECM64-NEXT: ld r3, L..C1@l(r3) +; LARGECM64-NEXT: add r3, r13, r3 +; LARGECM64-NEXT: addi r3, r3, 4 +; LARGECM64-NEXT: blr +entry: + %tls0 = tail call align 2 ptr @llvm.threadlocal.address.p0(ptr align 2 @b_noattr) + %arrayidx = getelementptr inbounds [87 x i16], ptr %tls0, i64 0, i64 2 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest3() { +; COMMONCM-LABEL: AddrTest3: +; COMMONCM: # %bb.0: # %entry +; COMMONCM-NEXT: addi r3, r13, c[TL]@le+12 +; COMMONCM-NEXT: blr +entry: + %tls0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @c) + %arrayidx = getelementptr inbounds [87 x i32], ptr %tls0, i64 0, i64 3 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest3_NoAttr() { +; SMALLCM64-LABEL: AddrTest3_NoAttr: +; SMALLCM64: # %bb.0: # %entry +; SMALLCM64-NEXT: ld r3, L..C2(r2) # target-flags(ppc-tprel) @c_noattr +; SMALLCM64-NEXT: add r3, r13, r3 +; SMALLCM64-NEXT: addi r3, r3, 12 +; SMALLCM64-NEXT: blr +; +; LARGECM64-LABEL: AddrTest3_NoAttr: +; LARGECM64: # %bb.0: # %entry +; LARGECM64-NEXT: addis r3, L..C2@u(r2) +; LARGECM64-NEXT: ld r3, L..C2@l(r3) +; LARGECM64-NEXT: add r3, r13, r3 +; LARGECM64-NEXT: addi r3, r3, 12 +; LARGECM64-NEXT: blr +entry: + %tls0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @c_noattr) + %arrayidx = getelementptr inbounds [87 x i32], ptr %tls0, i64 0, i64 3 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest4() { +; COMMONCM-LABEL: AddrTest4: +; COMMONCM: # %bb.0: # %entry +; COMMONCM-NEXT: addi r3, r13, c[TL]@le+56 +; COMMONCM-NEXT: blr +entry: + %tls0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @c) + %arrayidx = getelementptr inbounds [87 x i64], ptr %tls0, i64 0, i64 7 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest4_NoAttr() { +; SMALLCM64-LABEL: AddrTest4_NoAttr: +; SMALLCM64: # %bb.0: # %entry +; SMALLCM64-NEXT: ld r3, L..C2(r2) # target-flags(ppc-tprel) @c_noattr +; SMALLCM64-NEXT: add r3, r13, r3 +; SMALLCM64-NEXT: addi r3, r3, 56 +; SMALLCM64-NEXT: blr +; +; LARGECM64-LABEL: AddrTest4_NoAttr: +; LARGECM64: # %bb.0: # %entry +; LARGECM64-NEXT: addis r3, L..C2@u(r2) +; LARGECM64-NEXT: ld r3, L..C2@l(r3) +; LARGECM64-NEXT: add r3, r13, r3 +; LARGECM64-NEXT: addi r3, r3, 56 +; LARGECM64-NEXT: blr +entry: + %tls0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @c_noattr) + %arrayidx = getelementptr inbounds [87 x i64], ptr %tls0, i64 0, i64 7 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest5() { +; COMMONCM-LABEL: AddrTest5: +; COMMONCM: # %bb.0: # %entry +; COMMONCM-NEXT: addi r3, r13, e[TL]@le+48 +; COMMONCM-NEXT: blr +entry: + %tls0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @e) + %arrayidx = getelementptr inbounds [87 x double], ptr %tls0, i64 0, i64 6 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest5_NoAttr() { +; SMALLCM64-LABEL: AddrTest5_NoAttr: +; SMALLCM64: # %bb.0: # %entry +; SMALLCM64-NEXT: ld r3, L..C3(r2) # target-flags(ppc-tprel) @e_noattr +; SMALLCM64-NEXT: add r3, r13, r3 +; SMALLCM64-NEXT: addi r3, r3, 48 +; SMALLCM64-NEXT: blr +; +; LARGECM64-LABEL: AddrTest5_NoAttr: +; LARGECM64: # %bb.0: # %entry +; LARGECM64-NEXT: addis r3, L..C3@u(r2) +; LARGECM64-NEXT: ld r3, L..C3@l(r3) +; LARGECM64-NEXT: add r3, r13, r3 +; LARGECM64-NEXT: addi r3, r3, 48 +; LARGECM64-NEXT: blr +entry: + %tls0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @e_noattr) + %arrayidx = getelementptr inbounds [87 x double], ptr %tls0, i64 0, i64 6 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest6() { +; COMMONCM-LABEL: AddrTest6: +; COMMONCM: # %bb.0: # %entry +; COMMONCM-NEXT: addi r3, r13, f[TL]@le+16 +; COMMONCM-NEXT: blr +entry: + %tls0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @f) + %arrayidx = getelementptr inbounds [87 x float], ptr %tls0, i64 0, i64 4 + ret ptr %arrayidx +} + +define nonnull ptr @AddrTest6_NoAttr() { +; SMALLCM64-LABEL: AddrTest6_NoAttr: +; SMALLCM64: # %bb.0: # %entry +; SMALLCM64-NEXT: ld r3, L..C4(r2) # target-flags(ppc-tprel) @f_noattr +; SMALLCM64-NEXT: add r3, r13, r3 +; SMALLCM64-NEXT: addi r3, r3, 16 +; SMALLCM64-NEXT: blr +; +; LARGECM64-LABEL: AddrTest6_NoAttr: +; LARGECM64: # %bb.0: # %entry +; LARGECM64-NEXT: addis r3, L..C4@u(r2) +; LARGECM64-NEXT: ld r3, L..C4@l(r3) +; LARGECM64-NEXT: add r3, r13, r3 +; LARGECM64-NEXT: addi r3, r3, 16 +; LARGECM64-NEXT: blr +entry: + %tls0 = tail call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @f_noattr) + %arrayidx = getelementptr inbounds [87 x float], ptr %tls0, i64 0, i64 4 + ret ptr %arrayidx +} + +attributes #0 = { "aix-small-tls" } diff --git a/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-targetattr.ll b/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-targetattr.ll new file mode 100644 index 0000000000000000000000000000000000000000..1e4a3b9bcc47c00e3a8b882821f6ca5a0a39164d --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-small-tls-globalvarattr-targetattr.ll @@ -0,0 +1,53 @@ +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff -mattr=+aix-small-local-exec-tls < %s \ +; RUN: | FileCheck %s --check-prefixes=COMMONCM,SMALL-LOCAL-EXEC-SMALLCM64 +; RUN: llc -verify-machineinstrs -mcpu=pwr7 -ppc-asm-full-reg-names \ +; RUN: -mtriple powerpc64-ibm-aix-xcoff --code-model=large \ +; RUN: -mattr=+aix-small-local-exec-tls < %s | FileCheck %s \ +; RUN: --check-prefixes=COMMONCM,SMALL-LOCAL-EXEC-LARGECM64 + +@mySmallTLS = thread_local(localexec) global [7800 x i64] zeroinitializer, align 8 #0 +@mySmallTLS2 = thread_local(localexec) global [3000 x i64] zeroinitializer, align 8 #0 +@mySmallTLS3 = thread_local(localexec) global [3000 x i64] zeroinitializer, align 8 +declare nonnull ptr @llvm.threadlocal.address.p0(ptr nonnull) + +; Although some global variables are annotated with 'aix-small-tls', because the +; aix-small-local-exec-tls target attribute is turned on, all accesses will use +; a "faster" local-exec sequence directly off the thread pointer. +define i64 @StoreLargeAccess1() { +; COMMONCM-LABEL: StoreLargeAccess1: +; COMMONCM-NEXT: # %bb.0: # %entry +; SMALL-LOCAL-EXEC-SMALLCM64: ld r3, L..C0(r2) # target-flags(ppc-tprel) @mySmallTLS +; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: li r4, 0 +; SMALL-LOCAL-EXEC-SMALLCM64-NEXT: li r5, 23 +; SMALL-LOCAL-EXEC-LARGECM64: addis r3, L..C0@u(r2) +; SMALL-LOCAL-EXEC-LARGECM64-NEXT: li r4, 0 +; SMALL-LOCAL-EXEC-LARGECM64-NEXT: li r5, 23 +; SMALL-LOCAL-EXEC-LARGECM64-NEXT: ld r3, L..C0@l(r3) +; COMMONCM: ori r4, r4, 53328 +; COMMONCM-NEXT: add r3, r13, r3 +; COMMONCM-NEXT: stdx r5, r3, r4 +; COMMONCM-NEXT: li r3, 55 +; COMMONCM-NEXT: li r4, 64 +; COMMONCM-NEXT: std r3, (mySmallTLS2[TL]@le+696)-65536(r13) +; COMMONCM-NEXT: li r3, 142 +; COMMONCM-NEXT: std r4, (mySmallTLS3[TL]@le+20000)-131072(r13) +; COMMONCM-NEXT: blr +entry: + %tls0 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @mySmallTLS) + %arrayidx = getelementptr inbounds i8, ptr %tls0, i32 53328 + store i64 23, ptr %arrayidx, align 8 + %tls1 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @mySmallTLS2) + %arrayidx1 = getelementptr inbounds i8, ptr %tls1, i32 696 + store i64 55, ptr %arrayidx1, align 8 + %tls2 = tail call align 8 ptr @llvm.threadlocal.address.p0(ptr align 8 @mySmallTLS3) + %arrayidx2 = getelementptr inbounds i8, ptr %tls2, i32 20000 + store i64 64, ptr %arrayidx2, align 8 + %load1 = load i64, ptr %arrayidx, align 8 + %load2 = load i64, ptr %arrayidx1, align 8 + %add1 = add i64 %load1, 64 + %add2 = add i64 %add1, %load2 + ret i64 %add2 +} + +attributes #0 = { "aix-small-tls" } diff --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-funcsect-explicitsect.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-funcsect-explicitsect.ll new file mode 100644 index 0000000000000000000000000000000000000000..4e94228404d61abff3631d973bb8ffd17b9cfe8a --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-xcoff-funcsect-explicitsect.ll @@ -0,0 +1,142 @@ +; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mattr=-altivec -mtriple powerpc-ibm-aix-xcoff \ +; RUN: -xcoff-traceback-table=false -filetype=obj -function-sections -o %t.o < %s +; RUN: llvm-readobj -s %t.o | FileCheck %s + +define dso_local signext i32 @foo1() section "sect" { +entry: + ret i32 1 +} + +define dso_local signext i32 @foo2() section "sect2" { +entry: + ret i32 2 +} + +define dso_local signext i32 @foo3() section "sect2" { +entry: + ret i32 3 +} + +define dso_local signext i32 @foo4() { +entry: + ret i32 4 +} + +; CHECK: Symbol {{[{][[:space:]] *}}Index: [[#INDX:]]{{[[:space:]] *}}Name: sect +; CHECK-NEXT: Value (RelocatableAddress): 0x0 +; CHECK-NEXT: Section: .text +; CHECK-NEXT: Type: 0x0 +; CHECK-NEXT: StorageClass: C_HIDEXT (0x6B) +; CHECK-NEXT: NumberOfAuxEntries: 1 +; CHECK-NEXT: CSECT Auxiliary Entry { +; CHECK-NEXT: Index: [[#INDX+1]] +; CHECK-NEXT: SectionLen: 8 +; CHECK-NEXT: ParameterHashIndex: 0x0 +; CHECK-NEXT: TypeChkSectNum: 0x0 +; CHECK-NEXT: SymbolAlignmentLog2: 5 +; CHECK-NEXT: SymbolType: XTY_SD (0x1) +; CHECK-NEXT: StorageMappingClass: XMC_PR (0x0) +; CHECK-NEXT: StabInfoIndex: 0x0 +; CHECK-NEXT: StabSectNum: 0x0 +; CHECK-NEXT: } +; CHECK-NEXT: } +; CHECK-NEXT: Symbol { +; CHECK-NEXT: Index: [[#INDX+2]] +; CHECK-NEXT: Name: .foo1 +; CHECK-NEXT: Value (RelocatableAddress): 0x0 +; CHECK-NEXT: Section: .text +; CHECK-NEXT: Type: 0x0 +; CHECK-NEXT: StorageClass: C_EXT (0x2) +; CHECK-NEXT: NumberOfAuxEntries: 1 +; CHECK-NEXT: CSECT Auxiliary Entry { +; CHECK-NEXT: Index: [[#INDX+3]] +; CHECK-NEXT: ContainingCsectSymbolIndex: [[#INDX]] +; CHECK-NEXT: ParameterHashIndex: 0x0 +; CHECK-NEXT: TypeChkSectNum: 0x0 +; CHECK-NEXT: SymbolAlignmentLog2: 0 +; CHECK-NEXT: SymbolType: XTY_LD (0x2) +; CHECK-NEXT: StorageMappingClass: XMC_PR (0x0) +; CHECK-NEXT: StabInfoIndex: 0x0 +; CHECK-NEXT: StabSectNum: 0x0 +; CHECK-NEXT: } +; CHECK-NEXT: } +; CHECK-NEXT: Symbol { +; CHECK-NEXT: Index: [[#INDX+4]] +; CHECK-NEXT: Name: sect2 +; CHECK-NEXT: Value (RelocatableAddress): 0x20 +; CHECK-NEXT: Section: .text +; CHECK-NEXT: Type: 0x0 +; CHECK-NEXT: StorageClass: C_HIDEXT (0x6B) +; CHECK-NEXT: NumberOfAuxEntries: 1 +; CHECK-NEXT: CSECT Auxiliary Entry { +; CHECK-NEXT: Index: [[#INDX+5]] +; CHECK-NEXT: SectionLen: 24 +; CHECK-NEXT: ParameterHashIndex: 0x0 +; CHECK-NEXT: TypeChkSectNum: 0x0 +; CHECK-NEXT: SymbolAlignmentLog2: 5 +; CHECK-NEXT: SymbolType: XTY_SD (0x1) +; CHECK-NEXT: StorageMappingClass: XMC_PR (0x0) +; CHECK-NEXT: StabInfoIndex: 0x0 +; CHECK-NEXT: StabSectNum: 0x0 +; CHECK-NEXT: } +; CHECK-NEXT: } +; CHECK-NEXT: Symbol { +; CHECK-NEXT: Index: [[#INDX+6]] +; CHECK-NEXT: Name: .foo2 +; CHECK-NEXT: Value (RelocatableAddress): 0x20 +; CHECK-NEXT: Section: .text +; CHECK-NEXT: Type: 0x0 +; CHECK-NEXT: StorageClass: C_EXT (0x2) +; CHECK-NEXT: NumberOfAuxEntries: 1 +; CHECK-NEXT: CSECT Auxiliary Entry { +; CHECK-NEXT: Index: [[#INDX+7]] +; CHECK-NEXT: ContainingCsectSymbolIndex: [[#INDX+4]] +; CHECK-NEXT: ParameterHashIndex: 0x0 +; CHECK-NEXT: TypeChkSectNum: 0x0 +; CHECK-NEXT: SymbolAlignmentLog2: 0 +; CHECK-NEXT: SymbolType: XTY_LD (0x2) +; CHECK-NEXT: StorageMappingClass: XMC_PR (0x0) +; CHECK-NEXT: StabInfoIndex: 0x0 +; CHECK-NEXT: StabSectNum: 0x0 +; CHECK-NEXT: } +; CHECK-NEXT: } +; CHECK-NEXT: Symbol { +; CHECK-NEXT: Index: [[#INDX+8]] +; CHECK-NEXT: Name: .foo3 +; CHECK-NEXT: Value (RelocatableAddress): 0x30 +; CHECK-NEXT: Section: .text +; CHECK-NEXT: Type: 0x0 +; CHECK-NEXT: StorageClass: C_EXT (0x2) +; CHECK-NEXT: NumberOfAuxEntries: 1 +; CHECK-NEXT: CSECT Auxiliary Entry { +; CHECK-NEXT: Index: [[#INDX+9]] +; CHECK-NEXT: ContainingCsectSymbolIndex: [[#INDX+4]] +; CHECK-NEXT: ParameterHashIndex: 0x0 +; CHECK-NEXT: TypeChkSectNum: 0x0 +; CHECK-NEXT: SymbolAlignmentLog2: 0 +; CHECK-NEXT: SymbolType: XTY_LD (0x2) +; CHECK-NEXT: StorageMappingClass: XMC_PR (0x0) +; CHECK-NEXT: StabInfoIndex: 0x0 +; CHECK-NEXT: StabSectNum: 0x0 +; CHECK-NEXT: } +; CHECK-NEXT: } +; CHECK-NEXT: Symbol { +; CHECK-NEXT: Index: [[#INDX+10]] +; CHECK-NEXT: Name: .foo4 +; CHECK-NEXT: Value (RelocatableAddress): 0x40 +; CHECK-NEXT: Section: .text +; CHECK-NEXT: Type: 0x0 +; CHECK-NEXT: StorageClass: C_EXT (0x2) +; CHECK-NEXT: NumberOfAuxEntries: 1 +; CHECK-NEXT: CSECT Auxiliary Entry { +; CHECK-NEXT: Index: 16 +; CHECK-NEXT: SectionLen: 8 +; CHECK-NEXT: ParameterHashIndex: 0x0 +; CHECK-NEXT: TypeChkSectNum: 0x0 +; CHECK-NEXT: SymbolAlignmentLog2: 5 +; CHECK-NEXT: SymbolType: XTY_SD (0x1) +; CHECK-NEXT: StorageMappingClass: XMC_PR (0x0) +; CHECK-NEXT: StabInfoIndex: 0x0 +; CHECK-NEXT: StabSectNum: 0x0 +; CHECK-NEXT: } +; CHECK-NEXT: } diff --git a/llvm/test/CodeGen/PowerPC/ctrloop-constrained-fp.ll b/llvm/test/CodeGen/PowerPC/ctrloop-constrained-fp.ll index c1d1461664418c856a1e023ac4d9d9f9d32109a9..50ebe0471dceacbdae9df8ccf6d65e7ef6dfd737 100644 --- a/llvm/test/CodeGen/PowerPC/ctrloop-constrained-fp.ll +++ b/llvm/test/CodeGen/PowerPC/ctrloop-constrained-fp.ll @@ -2,7 +2,7 @@ ; RUN: llc -mtriple powerpc64le < %s | FileCheck %s ; Check constrained ops converted to call -define void @test(ptr %cast) { +define void @test(ptr %cast) strictfp { ; CHECK-LABEL: test: ; CHECK: # %bb.0: # %root ; CHECK-NEXT: mflr 0 @@ -51,7 +51,7 @@ for.body: } ; Check constrained ops converted to native instruction -define void @test2(ptr %cast) { +define void @test2(ptr %cast) strictfp { ; CHECK-LABEL: test2: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: li 4, 255 diff --git a/llvm/test/CodeGen/PowerPC/fp-classify.ll b/llvm/test/CodeGen/PowerPC/fp-classify.ll index 7de35b880a5d9cfc010a0da28e5d5881c9e79e07..f527b3c48040e7c58d6365b1050ab6cab3757ddc 100644 --- a/llvm/test/CodeGen/PowerPC/fp-classify.ll +++ b/llvm/test/CodeGen/PowerPC/fp-classify.ll @@ -57,30 +57,18 @@ entry: define zeroext i1 @abs_isinfq(fp128 %x) { ; P8-LABEL: abs_isinfq: ; P8: # %bb.0: # %entry -; P8-NEXT: mflr 0 -; P8-NEXT: stdu 1, -48(1) -; P8-NEXT: std 0, 64(1) -; P8-NEXT: .cfi_def_cfa_offset 48 -; P8-NEXT: .cfi_offset lr, 16 ; P8-NEXT: xxswapd 0, 34 -; P8-NEXT: addi 3, 1, 32 +; P8-NEXT: addi 3, 1, -16 +; P8-NEXT: li 5, 32767 ; P8-NEXT: stxvd2x 0, 0, 3 -; P8-NEXT: lbz 4, 47(1) -; P8-NEXT: clrlwi 4, 4, 25 -; P8-NEXT: stb 4, 47(1) -; P8-NEXT: lxvd2x 0, 0, 3 -; P8-NEXT: addis 3, 2, .LCPI2_0@toc@ha -; P8-NEXT: addi 3, 3, .LCPI2_0@toc@l -; P8-NEXT: xxswapd 34, 0 -; P8-NEXT: lxvd2x 0, 0, 3 -; P8-NEXT: xxswapd 35, 0 -; P8-NEXT: bl __eqkf2 -; P8-NEXT: nop -; P8-NEXT: cntlzw 3, 3 -; P8-NEXT: srwi 3, 3, 5 -; P8-NEXT: addi 1, 1, 48 -; P8-NEXT: ld 0, 16(1) -; P8-NEXT: mtlr 0 +; P8-NEXT: rldic 5, 5, 48, 1 +; P8-NEXT: ld 4, -8(1) +; P8-NEXT: ld 3, -16(1) +; P8-NEXT: clrldi 4, 4, 1 +; P8-NEXT: xor 4, 4, 5 +; P8-NEXT: or 3, 3, 4 +; P8-NEXT: cntlzd 3, 3 +; P8-NEXT: rldicl 3, 3, 58, 63 ; P8-NEXT: blr ; ; P9-LABEL: abs_isinfq: @@ -99,12 +87,13 @@ entry: define zeroext i1 @abs_isinfornanf(float %x) { ; P8-LABEL: abs_isinfornanf: ; P8: # %bb.0: # %entry -; P8-NEXT: addis 3, 2, .LCPI3_0@toc@ha -; P8-NEXT: xsabsdp 0, 1 -; P8-NEXT: lfs 1, .LCPI3_0@toc@l(3) -; P8-NEXT: li 3, 1 -; P8-NEXT: fcmpu 0, 0, 1 -; P8-NEXT: isellt 3, 0, 3 +; P8-NEXT: xscvdpspn 0, 1 +; P8-NEXT: lis 4, 32639 +; P8-NEXT: ori 4, 4, 65535 +; P8-NEXT: mffprwz 3, 0 +; P8-NEXT: clrlwi 3, 3, 1 +; P8-NEXT: sub 3, 4, 3 +; P8-NEXT: rldicl 3, 3, 1, 63 ; P8-NEXT: blr ; ; P9-LABEL: abs_isinfornanf: @@ -123,12 +112,15 @@ entry: define zeroext i1 @abs_isinfornan(double %x) { ; P8-LABEL: abs_isinfornan: ; P8: # %bb.0: # %entry -; P8-NEXT: addis 3, 2, .LCPI4_0@toc@ha -; P8-NEXT: xsabsdp 0, 1 -; P8-NEXT: lfs 1, .LCPI4_0@toc@l(3) -; P8-NEXT: li 3, 1 -; P8-NEXT: fcmpu 0, 0, 1 -; P8-NEXT: isellt 3, 0, 3 +; P8-NEXT: mffprd 3, 1 +; P8-NEXT: li 4, -33 +; P8-NEXT: rldicl 4, 4, 47, 1 +; P8-NEXT: sradi 5, 4, 63 +; P8-NEXT: clrldi 3, 3, 1 +; P8-NEXT: rldicl 6, 3, 1, 63 +; P8-NEXT: subc 3, 4, 3 +; P8-NEXT: adde 3, 6, 5 +; P8-NEXT: xori 3, 3, 1 ; P8-NEXT: blr ; ; P9-LABEL: abs_isinfornan: @@ -147,53 +139,18 @@ entry: define zeroext i1 @abs_isinfornanq(fp128 %x) { ; P8-LABEL: abs_isinfornanq: ; P8: # %bb.0: # %entry -; P8-NEXT: mflr 0 -; P8-NEXT: stdu 1, -112(1) -; P8-NEXT: std 0, 128(1) -; P8-NEXT: .cfi_def_cfa_offset 112 -; P8-NEXT: .cfi_offset lr, 16 -; P8-NEXT: .cfi_offset r30, -16 -; P8-NEXT: .cfi_offset v30, -48 -; P8-NEXT: .cfi_offset v31, -32 -; P8-NEXT: li 3, 64 ; P8-NEXT: xxswapd 0, 34 -; P8-NEXT: std 30, 96(1) # 8-byte Folded Spill -; P8-NEXT: stvx 30, 1, 3 # 16-byte Folded Spill -; P8-NEXT: li 3, 80 -; P8-NEXT: stvx 31, 1, 3 # 16-byte Folded Spill -; P8-NEXT: addi 3, 1, 48 +; P8-NEXT: addi 3, 1, -16 +; P8-NEXT: li 4, -3 ; P8-NEXT: stxvd2x 0, 0, 3 -; P8-NEXT: lbz 4, 63(1) -; P8-NEXT: clrlwi 4, 4, 25 -; P8-NEXT: stb 4, 63(1) -; P8-NEXT: lxvd2x 0, 0, 3 -; P8-NEXT: addis 3, 2, .LCPI5_0@toc@ha -; P8-NEXT: addi 3, 3, .LCPI5_0@toc@l -; P8-NEXT: xxswapd 63, 0 -; P8-NEXT: lxvd2x 0, 0, 3 -; P8-NEXT: vmr 2, 31 -; P8-NEXT: xxswapd 62, 0 -; P8-NEXT: vmr 3, 30 -; P8-NEXT: bl __eqkf2 -; P8-NEXT: nop -; P8-NEXT: cntlzw 3, 3 -; P8-NEXT: vmr 2, 31 -; P8-NEXT: vmr 3, 30 -; P8-NEXT: srwi 30, 3, 5 -; P8-NEXT: bl __unordkf2 -; P8-NEXT: nop -; P8-NEXT: cntlzw 3, 3 -; P8-NEXT: li 4, 80 -; P8-NEXT: lvx 31, 1, 4 # 16-byte Folded Reload -; P8-NEXT: li 4, 64 -; P8-NEXT: srwi 3, 3, 5 -; P8-NEXT: lvx 30, 1, 4 # 16-byte Folded Reload +; P8-NEXT: rldicl 4, 4, 47, 1 +; P8-NEXT: ld 3, -8(1) +; P8-NEXT: sradi 5, 4, 63 +; P8-NEXT: clrldi 3, 3, 1 +; P8-NEXT: rldicl 6, 3, 1, 63 +; P8-NEXT: subc 3, 4, 3 +; P8-NEXT: adde 3, 6, 5 ; P8-NEXT: xori 3, 3, 1 -; P8-NEXT: or 3, 3, 30 -; P8-NEXT: ld 30, 96(1) # 8-byte Folded Reload -; P8-NEXT: addi 1, 1, 112 -; P8-NEXT: ld 0, 16(1) -; P8-NEXT: mtlr 0 ; P8-NEXT: blr ; ; P9-LABEL: abs_isinfornanq: diff --git a/llvm/test/CodeGen/PowerPC/remove-copy-crunsetcrbit.mir b/llvm/test/CodeGen/PowerPC/remove-copy-crunsetcrbit.mir index 3a312d2f4a8bac1f795eeb28ce1324c80dab343c..f3ef95bbb79a4725033937a37dde1429e896a947 100644 --- a/llvm/test/CodeGen/PowerPC/remove-copy-crunsetcrbit.mir +++ b/llvm/test/CodeGen/PowerPC/remove-copy-crunsetcrbit.mir @@ -130,7 +130,7 @@ body: | %22:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @c %10:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @e %13:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @a - %14:g8rc_and_g8rc_nox0 = ADDItocL killed %13, @a, implicit $x2 + %14:g8rc_and_g8rc_nox0 = ADDItocL8 killed %13, @a, implicit $x2 bb.2.while.body: successors: %bb.4(0x30000000), %bb.3(0x50000000) diff --git a/llvm/test/CodeGen/PowerPC/rldimi.ll b/llvm/test/CodeGen/PowerPC/rldimi.ll index 322975f547c9965f30a4443b13f8b38b3de787e0..78ea9aa862f2c26599a0c17e78034800fd80ed73 100644 --- a/llvm/test/CodeGen/PowerPC/rldimi.ll +++ b/llvm/test/CodeGen/PowerPC/rldimi.ll @@ -59,8 +59,8 @@ entry: ret i64 %8 } -define i64 @rldimi_intrinsic(i64 %a) { -; CHECK-LABEL: rldimi_intrinsic: +define i64 @rldimi4(i64 %a) { +; CHECK-LABEL: rldimi4: ; CHECK: # %bb.0: ; CHECK-NEXT: rldimi 3, 3, 8, 0 ; CHECK-NEXT: rldimi 3, 3, 16, 0 @@ -72,4 +72,71 @@ define i64 @rldimi_intrinsic(i64 %a) { ret i64 %r3 } +define i64 @rldimi5(i64 %a, i64 %b) { +; CHECK-LABEL: rldimi5: +; CHECK: # %bb.0: +; CHECK-NEXT: rldimi 4, 3, 8, 40 +; CHECK-NEXT: mr 3, 4 +; CHECK-NEXT: blr + %r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 8, i64 16776960) ; 0xffff << 8 + ret i64 %r +} + +define i64 @rldimi6(i64 %a, i64 %b) { +; CHECK-LABEL: rldimi6: +; CHECK: # %bb.0: +; CHECK-NEXT: rotldi 3, 3, 1 +; CHECK-NEXT: rldimi 4, 3, 7, 41 +; CHECK-NEXT: mr 3, 4 +; CHECK-NEXT: blr + %r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 8, i64 8388480) ; 0xffff << 7 + ret i64 %r +} + +define i64 @rldimi7(i64 %a, i64 %b) { +; CHECK-LABEL: rldimi7: +; CHECK: # %bb.0: +; CHECK-NEXT: rotldi 3, 3, 63 +; CHECK-NEXT: rldimi 4, 3, 9, 39 +; CHECK-NEXT: mr 3, 4 +; CHECK-NEXT: blr + %r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 8, i64 33553920) ; 0xffff << 9 + ret i64 %r +} + +define i64 @rldimi8(i64 %a, i64 %b) { +; CHECK-LABEL: rldimi8: +; CHECK: # %bb.0: +; CHECK-NEXT: mr 3, 4 +; CHECK-NEXT: blr + %r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 0, i64 0) + ret i64 %r +} + +define i64 @rldimi9(i64 %a, i64 %b) { +; CHECK-LABEL: rldimi9: +; CHECK: # %bb.0: +; CHECK-NEXT: mr 3, 4 +; CHECK-NEXT: blr + %r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 63, i64 0) + ret i64 %r +} + +define i64 @rldimi10(i64 %a, i64 %b) { +; CHECK-LABEL: rldimi10: +; CHECK: # %bb.0: +; CHECK-NEXT: blr + %r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 0, i64 -1) + ret i64 %r +} + +define i64 @rldimi11(i64 %a, i64 %b) { +; CHECK-LABEL: rldimi11: +; CHECK: # %bb.0: +; CHECK-NEXT: rotldi 3, 3, 8 +; CHECK-NEXT: blr + %r = call i64 @llvm.ppc.rldimi(i64 %a, i64 %b, i32 8, i64 -1) + ret i64 %r +} + declare i64 @llvm.ppc.rldimi(i64, i64, i32 immarg, i64 immarg) diff --git a/llvm/test/CodeGen/PowerPC/rlwimi.ll b/llvm/test/CodeGen/PowerPC/rlwimi.ll index 8b126cd3393c1044e746d1e80498b3b40722b312..8da769508c9ae88cd5957e201fc3c08e4c8f43fb 100644 --- a/llvm/test/CodeGen/PowerPC/rlwimi.ll +++ b/llvm/test/CodeGen/PowerPC/rlwimi.ll @@ -107,11 +107,51 @@ entry: define i32 @test9(i32 %a, i32 %b) { ; CHECK-LABEL: test9: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: rlwimi 3, 4, 8, 20, 26 +; CHECK-NEXT: rlwimi 4, 3, 8, 20, 26 +; CHECK-NEXT: mr 3, 4 ; CHECK-NEXT: blr entry: %r = call i32 @llvm.ppc.rlwimi(i32 %a, i32 %b, i32 8, i32 4064) ret i32 %r } +define i32 @test10(i32 %a, i32 %b) { +; CHECK-LABEL: test10: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: blr +entry: + %r = call i32 @llvm.ppc.rlwimi(i32 %a, i32 %b, i32 0, i32 -1) + ret i32 %r +} + +define i32 @test11(i32 %a, i32 %b) { +; CHECK-LABEL: test11: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: rotlwi 3, 3, 8 +; CHECK-NEXT: blr +entry: + %r = call i32 @llvm.ppc.rlwimi(i32 %a, i32 %b, i32 8, i32 -1) + ret i32 %r +} + +define i32 @test12(i32 %a, i32 %b) { +; CHECK-LABEL: test12: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mr 3, 4 +; CHECK-NEXT: blr +entry: + %r = call i32 @llvm.ppc.rlwimi(i32 %a, i32 %b, i32 0, i32 0) + ret i32 %r +} + +define i32 @test13(i32 %a, i32 %b) { +; CHECK-LABEL: test13: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: rlwimi 3, 4, 0, 27, 19 +; CHECK-NEXT: blr +entry: + %r = call i32 @llvm.ppc.rlwimi(i32 %a, i32 %b, i32 0, i32 4064) + ret i32 %r +} + declare i32 @llvm.ppc.rlwimi(i32, i32, i32 immarg, i32 immarg) diff --git a/llvm/test/CodeGen/PowerPC/rlwinm.ll b/llvm/test/CodeGen/PowerPC/rlwinm.ll index c6d4e5bb000040eb700a6de76f33b6be456bad3b..363eb171276566cdf55ea306d09ed20e7d2a7cf0 100644 --- a/llvm/test/CodeGen/PowerPC/rlwinm.ll +++ b/llvm/test/CodeGen/PowerPC/rlwinm.ll @@ -97,4 +97,24 @@ entry: ret i32 %r } +define i32 @test10(i32 %a, i32 %s) { +; CHECK-LABEL: test10: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: li 3, 0 +; CHECK-NEXT: blr +entry: + %r = call i32 @llvm.ppc.rlwnm(i32 %a, i32 %s, i32 0) + ret i32 %r +} + +define i32 @test11(i32 %a, i32 %s) { +; CHECK-LABEL: test11: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: rotlw 3, 3, 4 +; CHECK-NEXT: blr +entry: + %r = call i32 @llvm.ppc.rlwnm(i32 %a, i32 %s, i32 -1) + ret i32 %r +} + declare i32 @llvm.ppc.rlwnm(i32, i32, i32 immarg) diff --git a/llvm/test/CodeGen/PowerPC/scalar-double-ldst.ll b/llvm/test/CodeGen/PowerPC/scalar-double-ldst.ll index 6f68679325c5799e6f6ecc328515baa896569120..798637b6840f1e85640e4d400a8f3e9296936ad9 100644 --- a/llvm/test/CodeGen/PowerPC/scalar-double-ldst.ll +++ b/llvm/test/CodeGen/PowerPC/scalar-double-ldst.ll @@ -7281,3 +7281,61 @@ entry: store double %str, ptr inttoptr (i64 1000000000000 to ptr), align 4096 ret void } + +define dso_local void @st_reversed_double_from_i8(ptr %ptr) { +; CHECK-P10-LABEL: st_reversed_double_from_i8: +; CHECK-P10: # %bb.0: # %entry +; CHECK-P10-NEXT: li r4, 8 +; CHECK-P10-NEXT: lxsibzx f0, 0, r3 +; CHECK-P10-NEXT: xxspltidp vs2, -1023410176 +; CHECK-P10-NEXT: lxsibzx f1, r3, r4 +; CHECK-P10-NEXT: xscvuxddp f0, f0 +; CHECK-P10-NEXT: xscvuxddp f1, f1 +; CHECK-P10-NEXT: xsadddp f0, f0, f2 +; CHECK-P10-NEXT: xsadddp f1, f1, f2 +; CHECK-P10-NEXT: stfd f1, 0(r3) +; CHECK-P10-NEXT: stfd f0, 8(r3) +; CHECK-P10-NEXT: blr +; +; CHECK-P9-LABEL: st_reversed_double_from_i8: +; CHECK-P9: # %bb.0: # %entry +; CHECK-P9-NEXT: li r4, 8 +; CHECK-P9-NEXT: lxsibzx f0, 0, r3 +; CHECK-P9-NEXT: lxsibzx f1, r3, r4 +; CHECK-P9-NEXT: addis r4, r2, .LCPI300_0@toc@ha +; CHECK-P9-NEXT: lfs f2, .LCPI300_0@toc@l(r4) +; CHECK-P9-NEXT: xscvuxddp f0, f0 +; CHECK-P9-NEXT: xscvuxddp f1, f1 +; CHECK-P9-NEXT: xsadddp f0, f0, f2 +; CHECK-P9-NEXT: xsadddp f1, f1, f2 +; CHECK-P9-NEXT: stfd f0, 8(r3) +; CHECK-P9-NEXT: stfd f1, 0(r3) +; CHECK-P9-NEXT: blr +; +; CHECK-P8-LABEL: st_reversed_double_from_i8: +; CHECK-P8: # %bb.0: # %entry +; CHECK-P8-NEXT: lbz r4, 0(r3) +; CHECK-P8-NEXT: lbz r5, 8(r3) +; CHECK-P8-NEXT: mtfprwz f0, r4 +; CHECK-P8-NEXT: mtfprwz f1, r5 +; CHECK-P8-NEXT: addis r4, r2, .LCPI300_0@toc@ha +; CHECK-P8-NEXT: lfs f2, .LCPI300_0@toc@l(r4) +; CHECK-P8-NEXT: xscvuxddp f0, f0 +; CHECK-P8-NEXT: xscvuxddp f1, f1 +; CHECK-P8-NEXT: xsadddp f0, f0, f2 +; CHECK-P8-NEXT: xsadddp f1, f1, f2 +; CHECK-P8-NEXT: stfd f1, 0(r3) +; CHECK-P8-NEXT: stfd f0, 8(r3) +; CHECK-P8-NEXT: blr +entry: + %idx = getelementptr inbounds i8, ptr %ptr, i64 8 + %i0 = load i8, ptr %ptr, align 1 + %i1 = load i8, ptr %idx, align 1 + %f0 = uitofp i8 %i0 to double + %f1 = uitofp i8 %i1 to double + %a0 = fadd double %f0, -1.280000e+02 + %a1 = fadd double %f1, -1.280000e+02 + store double %a1, ptr %ptr, align 8 + store double %a0, ptr %idx, align 8 + ret void +} diff --git a/llvm/test/CodeGen/PowerPC/scalar-float-ldst.ll b/llvm/test/CodeGen/PowerPC/scalar-float-ldst.ll index 824dd4c4db6cb70d2e52175d6cc3f92c143e66fc..f39605734212987d777a6ef2f2c5721989248964 100644 --- a/llvm/test/CodeGen/PowerPC/scalar-float-ldst.ll +++ b/llvm/test/CodeGen/PowerPC/scalar-float-ldst.ll @@ -7271,3 +7271,61 @@ entry: store double %conv, ptr inttoptr (i64 1000000000000 to ptr), align 4096 ret void } + +define dso_local void @st_reversed_float_from_i8(ptr %ptr) { +; CHECK-P10-LABEL: st_reversed_float_from_i8: +; CHECK-P10: # %bb.0: # %entry +; CHECK-P10-NEXT: li r4, 8 +; CHECK-P10-NEXT: lxsibzx f0, 0, r3 +; CHECK-P10-NEXT: xxspltidp vs2, -1023410176 +; CHECK-P10-NEXT: lxsibzx f1, r3, r4 +; CHECK-P10-NEXT: xscvuxdsp f0, f0 +; CHECK-P10-NEXT: xscvuxdsp f1, f1 +; CHECK-P10-NEXT: xsaddsp f0, f0, f2 +; CHECK-P10-NEXT: xsaddsp f1, f1, f2 +; CHECK-P10-NEXT: stfs f0, 8(r3) +; CHECK-P10-NEXT: stfs f1, 0(r3) +; CHECK-P10-NEXT: blr +; +; CHECK-P9-LABEL: st_reversed_float_from_i8: +; CHECK-P9: # %bb.0: # %entry +; CHECK-P9-NEXT: li r4, 8 +; CHECK-P9-NEXT: lxsibzx f0, 0, r3 +; CHECK-P9-NEXT: lxsibzx f1, r3, r4 +; CHECK-P9-NEXT: addis r4, r2, .LCPI300_0@toc@ha +; CHECK-P9-NEXT: lfs f2, .LCPI300_0@toc@l(r4) +; CHECK-P9-NEXT: xscvuxdsp f0, f0 +; CHECK-P9-NEXT: xscvuxdsp f1, f1 +; CHECK-P9-NEXT: xsaddsp f0, f0, f2 +; CHECK-P9-NEXT: xsaddsp f1, f1, f2 +; CHECK-P9-NEXT: stfs f0, 8(r3) +; CHECK-P9-NEXT: stfs f1, 0(r3) +; CHECK-P9-NEXT: blr +; +; CHECK-P8-LABEL: st_reversed_float_from_i8: +; CHECK-P8: # %bb.0: # %entry +; CHECK-P8-NEXT: lbz r4, 0(r3) +; CHECK-P8-NEXT: lbz r5, 8(r3) +; CHECK-P8-NEXT: mtfprwz f0, r4 +; CHECK-P8-NEXT: mtfprwz f1, r5 +; CHECK-P8-NEXT: addis r4, r2, .LCPI300_0@toc@ha +; CHECK-P8-NEXT: lfs f2, .LCPI300_0@toc@l(r4) +; CHECK-P8-NEXT: xscvuxdsp f0, f0 +; CHECK-P8-NEXT: xscvuxdsp f1, f1 +; CHECK-P8-NEXT: xsaddsp f0, f0, f2 +; CHECK-P8-NEXT: xsaddsp f1, f1, f2 +; CHECK-P8-NEXT: stfs f1, 0(r3) +; CHECK-P8-NEXT: stfs f0, 8(r3) +; CHECK-P8-NEXT: blr +entry: + %idx = getelementptr inbounds i8, ptr %ptr, i64 8 + %i0 = load i8, ptr %ptr, align 1 + %i1 = load i8, ptr %idx, align 1 + %f0 = uitofp i8 %i0 to float + %f1 = uitofp i8 %i1 to float + %a0 = fadd float %f0, -1.280000e+02 + %a1 = fadd float %f1, -1.280000e+02 + store float %a1, ptr %ptr, align 8 + store float %a0, ptr %idx, align 8 + ret void +} diff --git a/llvm/test/CodeGen/PowerPC/stack-restore-with-setjmp.ll b/llvm/test/CodeGen/PowerPC/stack-restore-with-setjmp.ll index c8278e58ad064cb6f7441126f6d6b5178b17ead0..8748767501bd00a258fb9c3b9c8a2775278de000 100644 --- a/llvm/test/CodeGen/PowerPC/stack-restore-with-setjmp.ll +++ b/llvm/test/CodeGen/PowerPC/stack-restore-with-setjmp.ll @@ -29,9 +29,7 @@ define dso_local signext i32 @main(i32 signext %argc, ptr nocapture readnone %ar ; CHECK-NEXT: nop ; CHECK-NEXT: # kill: def $r3 killed $r3 killed $x3 ; CHECK-NEXT: cmpwi 3, 0 -; CHECK-NEXT: crmove 20, 10 ; CHECK-NEXT: crorc 20, 10, 2 -; CHECK-NEXT: crmove 21, 2 ; CHECK-NEXT: bc 4, 20, .LBB0_4 ; CHECK-NEXT: # %bb.2: # %if.end5 ; CHECK-NEXT: addis 3, 2, .L.str@toc@ha @@ -76,11 +74,9 @@ define dso_local signext i32 @main(i32 signext %argc, ptr nocapture readnone %ar ; BE-NEXT: addi 3, 31, 128 ; BE-NEXT: bl _setjmp ; BE-NEXT: nop -; BE-NEXT: crmove 20, 10 ; BE-NEXT: # kill: def $r3 killed $r3 killed $x3 ; BE-NEXT: cmpwi 3, 0 ; BE-NEXT: crorc 20, 10, 2 -; BE-NEXT: crmove 21, 2 ; BE-NEXT: bc 4, 20, .LBB0_4 ; BE-NEXT: # %bb.2: # %if.end5 ; BE-NEXT: addis 3, 2, .L.str@toc@ha diff --git a/llvm/test/CodeGen/PowerPC/toc-data-large-array.ll b/llvm/test/CodeGen/PowerPC/toc-data-large-array.ll new file mode 100644 index 0000000000000000000000000000000000000000..90f40d9f0fec951f7e186575c86aba9576cd2401 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/toc-data-large-array.ll @@ -0,0 +1,16 @@ +; RUN: not --crash llc -mtriple powerpc-ibm-aix-xcoff < %s 2>&1 | FileCheck %s --check-prefix CHECK-ERROR +; RUN: not --crash llc -mtriple powerpc64-ibm-aix-xcoff < %s 2>&1 | FileCheck %s --check-prefix CHECK-ERROR + +@a = global [5 x i16] zeroinitializer, align 2 #0 + +; Function Attrs: noinline +define i16 @foo() #1 { +entry: + %0 = load i16, ptr @a, align 2 + ret i16 %0 +} + +attributes #0 = { "toc-data" } +attributes #1 = { noinline } + +; CHECK-ERROR: LLVM ERROR: A GlobalVariable with size larger than a TOC entry is not currently supported by the toc data transformation. diff --git a/llvm/test/CodeGen/PowerPC/toc-data-large-array2.ll b/llvm/test/CodeGen/PowerPC/toc-data-large-array2.ll new file mode 100644 index 0000000000000000000000000000000000000000..f870e996a401924d5fdbd50d6f2ff4f419606fca --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/toc-data-large-array2.ll @@ -0,0 +1,8 @@ +; RUN: not --crash llc -mtriple powerpc-ibm-aix-xcoff < %s 2>&1 | FileCheck %s --check-prefix CHECK-ERROR +; RUN: not --crash llc -mtriple powerpc64-ibm-aix-xcoff < %s 2>&1 | FileCheck %s --check-prefix CHECK-ERROR + +@a = global [5 x i16] zeroinitializer, align 2 #0 + +attributes #0 = { "toc-data" } + +; CHECK-ERROR: LLVM ERROR: A GlobalVariable with size larger than a TOC entry is not currently supported by the toc data transformation. diff --git a/llvm/test/CodeGen/PowerPC/toc-data-struct-array.ll b/llvm/test/CodeGen/PowerPC/toc-data-struct-array.ll new file mode 100644 index 0000000000000000000000000000000000000000..a5c9a8b909d1cf2c882645b456b70ed11fa94116 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/toc-data-struct-array.ll @@ -0,0 +1,110 @@ +; RUN: llc -mtriple powerpc-ibm-aix-xcoff < %s | FileCheck %s --check-prefix CHECK +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff < %s | FileCheck %s --check-prefix CHECK + +; RUN: llc -filetype=obj -mtriple powerpc-ibm-aix-xcoff < %s -o %t32.o +; RUN: llvm-readobj %t32.o --syms | FileCheck %s --check-prefix=OBJ32 +; RUN: llc -filetype=obj -mtriple powerpc64-ibm-aix-xcoff < %s -o %t64.o +; RUN: llvm-readobj %t64.o --syms | FileCheck %s --check-prefix=OBJ64 + +%struct.small_struct = type { i16 } + +@a = global %struct.small_struct zeroinitializer, align 2 #0 +@b = global [2 x i16] zeroinitializer, align 2 #0 + +; Function Attrs: noinline +define i16 @foo() #1 { +entry: + %0 = load i16, ptr @a, align 2 + %1 = load i16, ptr @b, align 2 + %add = add nsw i16 %0, %1 + ret i16 %add +} + +attributes #0 = { "toc-data" } +attributes #1 = { noinline } + +; CHECK: .toc +; CHECK-NEXT: .csect a[TD],2 +; CHECK-NEXT: .globl a[TD] # @a +; CHECK-NEXT: .align 1 +; CHECK-NEXT: .space 2 +; CHECK-NEXT: .csect b[TD],2 +; CHECK-NEXT: .globl b[TD] # @b +; CHECK-NEXT: .align 1 +; CHECK-NEXT: .space 4 + +; OBJ32: Symbol { +; OBJ32: Name: a +; OBJ32-NEXT: Value (RelocatableAddress): 0x3C +; OBJ32-NEXT: Section: .data +; OBJ32-NEXT: Type: 0x0 +; OBJ32-NEXT: StorageClass: C_EXT (0x2) +; OBJ32-NEXT: NumberOfAuxEntries: 1 +; OBJ32-NEXT: CSECT Auxiliary Entry { +; OBJ32-NEXT: Index: {{[0-9]+}} +; OBJ32-NEXT: SectionLen: 2 +; OBJ32-NEXT: ParameterHashIndex: 0x0 +; OBJ32-NEXT: TypeChkSectNum: 0x0 +; OBJ32-NEXT: SymbolAlignmentLog2: 2 +; OBJ32-NEXT: SymbolType: XTY_SD (0x1) +; OBJ32-NEXT: StorageMappingClass: XMC_TD (0x10) +; OBJ32-NEXT: StabInfoIndex: 0x0 +; OBJ32-NEXT: StabSectNum: 0x0 +; OBJ32-NEXT: } +; OBJ32-NEXT: } +; OBJ32-NEXT: Symbol { +; OBJ32: Name: b +; OBJ32-NEXT: Value (RelocatableAddress): 0x40 +; OBJ32-NEXT: Section: .data +; OBJ32-NEXT: Type: 0x0 +; OBJ32-NEXT: StorageClass: C_EXT (0x2) +; OBJ32-NEXT: NumberOfAuxEntries: 1 +; OBJ32-NEXT: CSECT Auxiliary Entry { +; OBJ32-NEXT: Index: {{[0-9]+}} +; OBJ32-NEXT: SectionLen: 4 +; OBJ32-NEXT: ParameterHashIndex: 0x0 +; OBJ32-NEXT: TypeChkSectNum: 0x0 +; OBJ32-NEXT: SymbolAlignmentLog2: 2 +; OBJ32-NEXT: SymbolType: XTY_SD (0x1) +; OBJ32-NEXT: StorageMappingClass: XMC_TD (0x10) +; OBJ32-NEXT: StabInfoIndex: 0x0 +; OBJ32-NEXT: StabSectNum: 0x0 +; OBJ32-NEXT: } +; OBJ32-NEXT: } + +; OBJ64: Symbol { +; OBJ64: Name: a +; OBJ64-NEXT: Value (RelocatableAddress): 0x48 +; OBJ64-NEXT: Section: .data +; OBJ64-NEXT: Type: 0x0 +; OBJ64-NEXT: StorageClass: C_EXT (0x2) +; OBJ64-NEXT: NumberOfAuxEntries: 1 +; OBJ64-NEXT: CSECT Auxiliary Entry { +; OBJ64-NEXT: Index: {{[0-9]+}} +; OBJ64-NEXT: SectionLen: 2 +; OBJ64-NEXT: ParameterHashIndex: 0x0 +; OBJ64-NEXT: TypeChkSectNum: 0x0 +; OBJ64-NEXT: SymbolAlignmentLog2: 2 +; OBJ64-NEXT: SymbolType: XTY_SD (0x1) +; OBJ64-NEXT: StorageMappingClass: XMC_TD (0x10) +; OBJ64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; OBJ64-NEXT: } +; OBJ64-NEXT: } +; OBJ64-NEXT: Symbol { +; OBJ64: Name: b +; OBJ64-NEXT: Value (RelocatableAddress): 0x4C +; OBJ64-NEXT: Section: .data +; OBJ64-NEXT: Type: 0x0 +; OBJ64-NEXT: StorageClass: C_EXT (0x2) +; OBJ64-NEXT: NumberOfAuxEntries: 1 +; OBJ64-NEXT: CSECT Auxiliary Entry { +; OBJ64-NEXT: Index: {{[0-9]+}} +; OBJ64-NEXT: SectionLen: 4 +; OBJ64-NEXT: ParameterHashIndex: 0x0 +; OBJ64-NEXT: TypeChkSectNum: 0x0 +; OBJ64-NEXT: SymbolAlignmentLog2: 2 +; OBJ64-NEXT: SymbolType: XTY_SD (0x1) +; OBJ64-NEXT: StorageMappingClass: XMC_TD (0x10) +; OBJ64-NEXT: Auxiliary Type: AUX_CSECT (0xFB) +; OBJ64-NEXT: } +; OBJ64-NEXT: } diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/rvv/select.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/rvv/select.mir new file mode 100644 index 0000000000000000000000000000000000000000..42bf32122870535e51b44c2f3103c99c98ade792 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/rvv/select.mir @@ -0,0 +1,345 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=riscv32 -mattr=+v -run-pass=instruction-select -simplify-mir -verify-machineinstrs %s -o - | FileCheck -check-prefix=RV32I %s +# RUN: llc -mtriple=riscv64 -mattr=+v -run-pass=instruction-select -simplify-mir -verify-machineinstrs %s -o - | FileCheck -check-prefix=RV64I %s + +--- +name: select_nxv1i8 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv1i8 + ; RV32I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF2:%[0-9]+]]:vrnov0 = IMPLICIT_DEF + ; RV32I-NEXT: $v0 = COPY [[DEF]] + ; RV32I-NEXT: [[PseudoVMERGE_VVM_MF4_:%[0-9]+]]:vrnov0 = PseudoVMERGE_VVM_MF4 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 3 /* e8 */ + ; RV32I-NEXT: $v8 = COPY [[PseudoVMERGE_VVM_MF4_]] + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: select_nxv1i8 + ; RV64I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF2:%[0-9]+]]:vrnov0 = IMPLICIT_DEF + ; RV64I-NEXT: $v0 = COPY [[DEF]] + ; RV64I-NEXT: [[PseudoVMERGE_VVM_MF4_:%[0-9]+]]:vrnov0 = PseudoVMERGE_VVM_MF4 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 3 /* e8 */ + ; RV64I-NEXT: $v8 = COPY [[PseudoVMERGE_VVM_MF4_]] + ; RV64I-NEXT: PseudoRET implicit $v8 + %0:vrb(<vscale x 2 x s1>) = G_IMPLICIT_DEF + %1:vrb(<vscale x 2 x s8>) = G_IMPLICIT_DEF + %2:vrb(<vscale x 2 x s8>) = G_SELECT %0(<vscale x 2 x s1>), %1, %1 + $v8 = COPY %2(<vscale x 2 x s8>) + PseudoRET implicit $v8 + +... +--- +name: select_nxv4i8 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv4i8 + ; RV32I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF2:%[0-9]+]]:vrnov0 = IMPLICIT_DEF + ; RV32I-NEXT: $v0 = COPY [[DEF]] + ; RV32I-NEXT: [[PseudoVMERGE_VVM_M1_:%[0-9]+]]:vrnov0 = PseudoVMERGE_VVM_M1 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 3 /* e8 */ + ; RV32I-NEXT: $v8 = COPY [[PseudoVMERGE_VVM_M1_]] + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: select_nxv4i8 + ; RV64I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF2:%[0-9]+]]:vrnov0 = IMPLICIT_DEF + ; RV64I-NEXT: $v0 = COPY [[DEF]] + ; RV64I-NEXT: [[PseudoVMERGE_VVM_M1_:%[0-9]+]]:vrnov0 = PseudoVMERGE_VVM_M1 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 3 /* e8 */ + ; RV64I-NEXT: $v8 = COPY [[PseudoVMERGE_VVM_M1_]] + ; RV64I-NEXT: PseudoRET implicit $v8 + %0:vrb(<vscale x 8 x s1>) = G_IMPLICIT_DEF + %1:vrb(<vscale x 8 x s8>) = G_IMPLICIT_DEF + %2:vrb(<vscale x 8 x s8>) = G_SELECT %0(<vscale x 8 x s1>), %1, %1 + $v8 = COPY %2(<vscale x 8 x s8>) + PseudoRET implicit $v8 + +... +--- +name: select_nxv16i8 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv16i8 + ; RV32I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrm4 = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF2:%[0-9]+]]:vrm4nov0 = IMPLICIT_DEF + ; RV32I-NEXT: $v0 = COPY [[DEF]] + ; RV32I-NEXT: [[PseudoVMERGE_VVM_M4_:%[0-9]+]]:vrm4nov0 = PseudoVMERGE_VVM_M4 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 3 /* e8 */ + ; RV32I-NEXT: $v8m4 = COPY [[PseudoVMERGE_VVM_M4_]] + ; RV32I-NEXT: PseudoRET implicit $v8m4 + ; + ; RV64I-LABEL: name: select_nxv16i8 + ; RV64I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrm4 = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF2:%[0-9]+]]:vrm4nov0 = IMPLICIT_DEF + ; RV64I-NEXT: $v0 = COPY [[DEF]] + ; RV64I-NEXT: [[PseudoVMERGE_VVM_M4_:%[0-9]+]]:vrm4nov0 = PseudoVMERGE_VVM_M4 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 3 /* e8 */ + ; RV64I-NEXT: $v8m4 = COPY [[PseudoVMERGE_VVM_M4_]] + ; RV64I-NEXT: PseudoRET implicit $v8m4 + %0:vrb(<vscale x 32 x s1>) = G_IMPLICIT_DEF + %1:vrb(<vscale x 32 x s8>) = G_IMPLICIT_DEF + %2:vrb(<vscale x 32 x s8>) = G_SELECT %0(<vscale x 32 x s1>), %1, %1 + $v8m4 = COPY %2(<vscale x 32 x s8>) + PseudoRET implicit $v8m4 + +... +--- +name: select_nxv64i8 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv64i8 + ; RV32I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF2:%[0-9]+]]:vrnov0 = IMPLICIT_DEF + ; RV32I-NEXT: $v0 = COPY [[DEF]] + ; RV32I-NEXT: [[PseudoVMERGE_VVM_MF4_:%[0-9]+]]:vrnov0 = PseudoVMERGE_VVM_MF4 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 4 /* e16 */ + ; RV32I-NEXT: $v8 = COPY [[PseudoVMERGE_VVM_MF4_]] + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: select_nxv64i8 + ; RV64I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF2:%[0-9]+]]:vrnov0 = IMPLICIT_DEF + ; RV64I-NEXT: $v0 = COPY [[DEF]] + ; RV64I-NEXT: [[PseudoVMERGE_VVM_MF4_:%[0-9]+]]:vrnov0 = PseudoVMERGE_VVM_MF4 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 4 /* e16 */ + ; RV64I-NEXT: $v8 = COPY [[PseudoVMERGE_VVM_MF4_]] + ; RV64I-NEXT: PseudoRET implicit $v8 + %0:vrb(<vscale x 1 x s1>) = G_IMPLICIT_DEF + %1:vrb(<vscale x 1 x s16>) = G_IMPLICIT_DEF + %2:vrb(<vscale x 1 x s16>) = G_SELECT %0(<vscale x 1 x s1>), %1, %1 + $v8 = COPY %2(<vscale x 1 x s16>) + PseudoRET implicit $v8 + +... +--- +name: select_nxv2i16 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv2i16 + ; RV32I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF2:%[0-9]+]]:vrnov0 = IMPLICIT_DEF + ; RV32I-NEXT: $v0 = COPY [[DEF]] + ; RV32I-NEXT: [[PseudoVMERGE_VVM_M1_:%[0-9]+]]:vrnov0 = PseudoVMERGE_VVM_M1 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 4 /* e16 */ + ; RV32I-NEXT: $v8 = COPY [[PseudoVMERGE_VVM_M1_]] + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: select_nxv2i16 + ; RV64I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF2:%[0-9]+]]:vrnov0 = IMPLICIT_DEF + ; RV64I-NEXT: $v0 = COPY [[DEF]] + ; RV64I-NEXT: [[PseudoVMERGE_VVM_M1_:%[0-9]+]]:vrnov0 = PseudoVMERGE_VVM_M1 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 4 /* e16 */ + ; RV64I-NEXT: $v8 = COPY [[PseudoVMERGE_VVM_M1_]] + ; RV64I-NEXT: PseudoRET implicit $v8 + %0:vrb(<vscale x 4 x s1>) = G_IMPLICIT_DEF + %1:vrb(<vscale x 4 x s16>) = G_IMPLICIT_DEF + %2:vrb(<vscale x 4 x s16>) = G_SELECT %0(<vscale x 4 x s1>), %1, %1 + $v8 = COPY %2(<vscale x 4 x s16>) + PseudoRET implicit $v8 + +... +--- +name: select_nxv8i16 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv8i16 + ; RV32I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrm4 = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF2:%[0-9]+]]:vrm4nov0 = IMPLICIT_DEF + ; RV32I-NEXT: $v0 = COPY [[DEF]] + ; RV32I-NEXT: [[PseudoVMERGE_VVM_M4_:%[0-9]+]]:vrm4nov0 = PseudoVMERGE_VVM_M4 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 4 /* e16 */ + ; RV32I-NEXT: $v8m4 = COPY [[PseudoVMERGE_VVM_M4_]] + ; RV32I-NEXT: PseudoRET implicit $v8m4 + ; + ; RV64I-LABEL: name: select_nxv8i16 + ; RV64I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrm4 = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF2:%[0-9]+]]:vrm4nov0 = IMPLICIT_DEF + ; RV64I-NEXT: $v0 = COPY [[DEF]] + ; RV64I-NEXT: [[PseudoVMERGE_VVM_M4_:%[0-9]+]]:vrm4nov0 = PseudoVMERGE_VVM_M4 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 4 /* e16 */ + ; RV64I-NEXT: $v8m4 = COPY [[PseudoVMERGE_VVM_M4_]] + ; RV64I-NEXT: PseudoRET implicit $v8m4 + %0:vrb(<vscale x 16 x s1>) = G_IMPLICIT_DEF + %1:vrb(<vscale x 16 x s16>) = G_IMPLICIT_DEF + %2:vrb(<vscale x 16 x s16>) = G_SELECT %0(<vscale x 16 x s1>), %1, %1 + $v8m4 = COPY %2(<vscale x 16 x s16>) + PseudoRET implicit $v8m4 + +... +--- +name: select_nxv32i16 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv32i16 + ; RV32I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF2:%[0-9]+]]:vrnov0 = IMPLICIT_DEF + ; RV32I-NEXT: $v0 = COPY [[DEF]] + ; RV32I-NEXT: [[PseudoVMERGE_VVM_MF2_:%[0-9]+]]:vrnov0 = PseudoVMERGE_VVM_MF2 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 5 /* e32 */ + ; RV32I-NEXT: $v8 = COPY [[PseudoVMERGE_VVM_MF2_]] + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: select_nxv32i16 + ; RV64I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF2:%[0-9]+]]:vrnov0 = IMPLICIT_DEF + ; RV64I-NEXT: $v0 = COPY [[DEF]] + ; RV64I-NEXT: [[PseudoVMERGE_VVM_MF2_:%[0-9]+]]:vrnov0 = PseudoVMERGE_VVM_MF2 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 5 /* e32 */ + ; RV64I-NEXT: $v8 = COPY [[PseudoVMERGE_VVM_MF2_]] + ; RV64I-NEXT: PseudoRET implicit $v8 + %0:vrb(<vscale x 1 x s1>) = G_IMPLICIT_DEF + %1:vrb(<vscale x 1 x s32>) = G_IMPLICIT_DEF + %2:vrb(<vscale x 1 x s32>) = G_SELECT %0(<vscale x 1 x s1>), %1, %1 + $v8 = COPY %2(<vscale x 1 x s32>) + PseudoRET implicit $v8 + +... +--- +name: select_nxv2i32 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv2i32 + ; RV32I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrm2 = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF2:%[0-9]+]]:vrm2nov0 = IMPLICIT_DEF + ; RV32I-NEXT: $v0 = COPY [[DEF]] + ; RV32I-NEXT: [[PseudoVMERGE_VVM_M2_:%[0-9]+]]:vrm2nov0 = PseudoVMERGE_VVM_M2 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 5 /* e32 */ + ; RV32I-NEXT: $v8m2 = COPY [[PseudoVMERGE_VVM_M2_]] + ; RV32I-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64I-LABEL: name: select_nxv2i32 + ; RV64I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrm2 = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF2:%[0-9]+]]:vrm2nov0 = IMPLICIT_DEF + ; RV64I-NEXT: $v0 = COPY [[DEF]] + ; RV64I-NEXT: [[PseudoVMERGE_VVM_M2_:%[0-9]+]]:vrm2nov0 = PseudoVMERGE_VVM_M2 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 5 /* e32 */ + ; RV64I-NEXT: $v8m2 = COPY [[PseudoVMERGE_VVM_M2_]] + ; RV64I-NEXT: PseudoRET implicit $v8m2 + %0:vrb(<vscale x 4 x s1>) = G_IMPLICIT_DEF + %1:vrb(<vscale x 4 x s32>) = G_IMPLICIT_DEF + %2:vrb(<vscale x 4 x s32>) = G_SELECT %0(<vscale x 4 x s1>), %1, %1 + $v8m2 = COPY %2(<vscale x 4 x s32>) + PseudoRET implicit $v8m2 + +... +--- +name: select_nxv8i32 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv8i32 + ; RV32I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrm8 = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF2:%[0-9]+]]:vrm8nov0 = IMPLICIT_DEF + ; RV32I-NEXT: $v0 = COPY [[DEF]] + ; RV32I-NEXT: [[PseudoVMERGE_VVM_M8_:%[0-9]+]]:vrm8nov0 = PseudoVMERGE_VVM_M8 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 5 /* e32 */ + ; RV32I-NEXT: $v8m8 = COPY [[PseudoVMERGE_VVM_M8_]] + ; RV32I-NEXT: PseudoRET implicit $v8m8 + ; + ; RV64I-LABEL: name: select_nxv8i32 + ; RV64I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrm8 = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF2:%[0-9]+]]:vrm8nov0 = IMPLICIT_DEF + ; RV64I-NEXT: $v0 = COPY [[DEF]] + ; RV64I-NEXT: [[PseudoVMERGE_VVM_M8_:%[0-9]+]]:vrm8nov0 = PseudoVMERGE_VVM_M8 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 5 /* e32 */ + ; RV64I-NEXT: $v8m8 = COPY [[PseudoVMERGE_VVM_M8_]] + ; RV64I-NEXT: PseudoRET implicit $v8m8 + %0:vrb(<vscale x 16 x s1>) = G_IMPLICIT_DEF + %1:vrb(<vscale x 16 x s32>) = G_IMPLICIT_DEF + %2:vrb(<vscale x 16 x s32>) = G_SELECT %0(<vscale x 16 x s1>), %1, %1 + $v8m8 = COPY %2(<vscale x 16 x s32>) + PseudoRET implicit $v8m8 + +... +--- +name: select_nxv1i64 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv1i64 + ; RV32I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrm2 = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF2:%[0-9]+]]:vrm2nov0 = IMPLICIT_DEF + ; RV32I-NEXT: $v0 = COPY [[DEF]] + ; RV32I-NEXT: [[PseudoVMERGE_VVM_M2_:%[0-9]+]]:vrm2nov0 = PseudoVMERGE_VVM_M2 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 6 /* e64 */ + ; RV32I-NEXT: $v8m2 = COPY [[PseudoVMERGE_VVM_M2_]] + ; RV32I-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64I-LABEL: name: select_nxv1i64 + ; RV64I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrm2 = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF2:%[0-9]+]]:vrm2nov0 = IMPLICIT_DEF + ; RV64I-NEXT: $v0 = COPY [[DEF]] + ; RV64I-NEXT: [[PseudoVMERGE_VVM_M2_:%[0-9]+]]:vrm2nov0 = PseudoVMERGE_VVM_M2 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 6 /* e64 */ + ; RV64I-NEXT: $v8m2 = COPY [[PseudoVMERGE_VVM_M2_]] + ; RV64I-NEXT: PseudoRET implicit $v8m2 + %0:vrb(<vscale x 2 x s1>) = G_IMPLICIT_DEF + %1:vrb(<vscale x 2 x s64>) = G_IMPLICIT_DEF + %2:vrb(<vscale x 2 x s64>) = G_SELECT %0(<vscale x 2 x s1>), %1, %1 + $v8m2 = COPY %2(<vscale x 2 x s64>) + PseudoRET implicit $v8m2 + +... +--- +name: select_nxv4i64 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv4i64 + ; RV32I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrm8 = IMPLICIT_DEF + ; RV32I-NEXT: [[DEF2:%[0-9]+]]:vrm8nov0 = IMPLICIT_DEF + ; RV32I-NEXT: $v0 = COPY [[DEF]] + ; RV32I-NEXT: [[PseudoVMERGE_VVM_M8_:%[0-9]+]]:vrm8nov0 = PseudoVMERGE_VVM_M8 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 6 /* e64 */ + ; RV32I-NEXT: $v8m8 = COPY [[PseudoVMERGE_VVM_M8_]] + ; RV32I-NEXT: PseudoRET implicit $v8m8 + ; + ; RV64I-LABEL: name: select_nxv4i64 + ; RV64I: [[DEF:%[0-9]+]]:vr = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrm8 = IMPLICIT_DEF + ; RV64I-NEXT: [[DEF2:%[0-9]+]]:vrm8nov0 = IMPLICIT_DEF + ; RV64I-NEXT: $v0 = COPY [[DEF]] + ; RV64I-NEXT: [[PseudoVMERGE_VVM_M8_:%[0-9]+]]:vrm8nov0 = PseudoVMERGE_VVM_M8 [[DEF2]], [[DEF1]], [[DEF1]], $v0, -1, 6 /* e64 */ + ; RV64I-NEXT: $v8m8 = COPY [[PseudoVMERGE_VVM_M8_]] + ; RV64I-NEXT: PseudoRET implicit $v8m8 + %0:vrb(<vscale x 8 x s1>) = G_IMPLICIT_DEF + %1:vrb(<vscale x 8 x s64>) = G_IMPLICIT_DEF + %2:vrb(<vscale x 8 x s64>) = G_SELECT %0(<vscale x 8 x s1>), %1, %1 + $v8m8 = COPY %2(<vscale x 8 x s64>) + PseudoRET implicit $v8m8 + +... diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/rvv/vscale32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/rvv/vscale32.mir new file mode 100644 index 0000000000000000000000000000000000000000..27dfb3fdda9db7d09e0ee5c0e1f3b6837248c70c --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/rvv/vscale32.mir @@ -0,0 +1,300 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=riscv32 -mattr=+v,+m -run-pass=instruction-select \ +# RUN: -simplify-mir -verify-machineinstrs %s -o - | FileCheck %s + +--- +name: test_1_s32 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_1_s32 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: $x10 = COPY [[SRLI]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:gprb(s32) = G_READ_VLENB + %2:gprb(s32) = G_CONSTANT i32 3 + %0:gprb(s32) = G_LSHR %1, %2(s32) + $x10 = COPY %0(s32) + PseudoRET implicit $x10 + +... +--- +name: test_2_s32 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_2_s32 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 2 + ; CHECK-NEXT: $x10 = COPY [[SRLI]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:gprb(s32) = G_READ_VLENB + %2:gprb(s32) = G_CONSTANT i32 2 + %0:gprb(s32) = G_LSHR %1, %2(s32) + $x10 = COPY %0(s32) + PseudoRET implicit $x10 + +... +--- +name: test_3_s32 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_3_s32 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 3 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[SRLI]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:gprb(s32) = G_READ_VLENB + %2:gprb(s32) = G_CONSTANT i32 3 + %3:gprb(s32) = G_LSHR %1, %2(s32) + %4:gprb(s32) = G_CONSTANT i32 3 + %0:gprb(s32) = G_MUL %3, %4 + $x10 = COPY %0(s32) + PseudoRET implicit $x10 + +... +--- +name: test_4_s32 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_4_s32 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 1 + ; CHECK-NEXT: $x10 = COPY [[SRLI]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:gprb(s32) = G_READ_VLENB + %2:gprb(s32) = G_CONSTANT i32 1 + %0:gprb(s32) = G_LSHR %1, %2(s32) + $x10 = COPY %0(s32) + PseudoRET implicit $x10 + +... +--- +name: test_8_s32 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_8_s32 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: $x10 = COPY [[PseudoReadVLENB]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:gprb(s32) = G_READ_VLENB + $x10 = COPY %0(s32) + PseudoRET implicit $x10 + +... +--- +name: test_16_s32 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_16_s32 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[PseudoReadVLENB]], 1 + ; CHECK-NEXT: $x10 = COPY [[SLLI]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:gprb(s32) = G_READ_VLENB + %2:gprb(s32) = G_CONSTANT i32 1 + %0:gprb(s32) = G_SHL %1, %2(s32) + $x10 = COPY %0(s32) + PseudoRET implicit $x10 + +... +--- +name: test_40_s32 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_40_s32 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 5 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[PseudoReadVLENB]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:gprb(s32) = G_READ_VLENB + %2:gprb(s32) = G_CONSTANT i32 5 + %0:gprb(s32) = G_MUL %1, %2 + $x10 = COPY %0(s32) + PseudoRET implicit $x10 + +... +--- +name: test_1_s64 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_1_s64 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 1 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[SRLI]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %17:gprb(s32) = G_READ_VLENB + %18:gprb(s32) = G_CONSTANT i32 3 + %2:gprb(s32) = G_LSHR %17, %18(s32) + %15:gprb(s32) = G_CONSTANT i32 1 + %9:gprb(s32) = G_MUL %2, %15 + $x10 = COPY %9(s32) + PseudoRET implicit $x10 + +... +--- +name: test_2_s64 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_2_s64 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 2 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[SRLI]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %17:gprb(s32) = G_READ_VLENB + %18:gprb(s32) = G_CONSTANT i32 3 + %2:gprb(s32) = G_LSHR %17, %18(s32) + %15:gprb(s32) = G_CONSTANT i32 2 + %9:gprb(s32) = G_MUL %2, %15 + $x10 = COPY %9(s32) + PseudoRET implicit $x10 + +... +--- +name: test_3_s64 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_3_s64 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 3 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[SRLI]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %17:gprb(s32) = G_READ_VLENB + %18:gprb(s32) = G_CONSTANT i32 3 + %2:gprb(s32) = G_LSHR %17, %18(s32) + %15:gprb(s32) = G_CONSTANT i32 3 + %9:gprb(s32) = G_MUL %2, %15 + $x10 = COPY %9(s32) + PseudoRET implicit $x10 + +... +--- +name: test_4_s64 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_4_s64 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 4 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[SRLI]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %17:gprb(s32) = G_READ_VLENB + %18:gprb(s32) = G_CONSTANT i32 3 + %2:gprb(s32) = G_LSHR %17, %18(s32) + %15:gprb(s32) = G_CONSTANT i32 4 + %9:gprb(s32) = G_MUL %2, %15 + $x10 = COPY %9(s32) + PseudoRET implicit $x10 + +... +--- +name: test_8_s64 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_8_s64 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 8 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[SRLI]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %17:gprb(s32) = G_READ_VLENB + %18:gprb(s32) = G_CONSTANT i32 3 + %2:gprb(s32) = G_LSHR %17, %18(s32) + %15:gprb(s32) = G_CONSTANT i32 8 + %9:gprb(s32) = G_MUL %2, %15 + $x10 = COPY %9(s32) + PseudoRET implicit $x10 + +... +--- +name: test_16_s64 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_16_s64 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 16 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[SRLI]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %17:gprb(s32) = G_READ_VLENB + %18:gprb(s32) = G_CONSTANT i32 3 + %2:gprb(s32) = G_LSHR %17, %18(s32) + %15:gprb(s32) = G_CONSTANT i32 16 + %9:gprb(s32) = G_MUL %2, %15 + $x10 = COPY %9(s32) + PseudoRET implicit $x10 + +... +--- +name: test_40_s64 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_40_s64 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 40 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[SRLI]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %17:gprb(s32) = G_READ_VLENB + %18:gprb(s32) = G_CONSTANT i32 3 + %2:gprb(s32) = G_LSHR %17, %18(s32) + %15:gprb(s32) = G_CONSTANT i32 40 + %9:gprb(s32) = G_MUL %2, %15 + $x10 = COPY %9(s32) + PseudoRET implicit $x10 + +... diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/rvv/vscale64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/rvv/vscale64.mir new file mode 100644 index 0000000000000000000000000000000000000000..4a96be2471f8bfac252defc8e7b64d78747d8031 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/rvv/vscale64.mir @@ -0,0 +1,139 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=riscv64 -mattr=+v,+m -run-pass=instruction-select \ +# RUN: -simplify-mir -verify-machineinstrs %s -o - | FileCheck %s + +--- +name: test_1 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_1 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: $x10 = COPY [[SRLI]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:gprb(s64) = G_READ_VLENB + %1:gprb(s64) = G_CONSTANT i64 3 + %2:gprb(s64) = G_LSHR %0, %1(s64) + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: test_2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_2 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 2 + ; CHECK-NEXT: $x10 = COPY [[SRLI]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:gprb(s64) = G_READ_VLENB + %1:gprb(s64) = G_CONSTANT i64 2 + %2:gprb(s64) = G_LSHR %0, %1(s64) + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: test_3 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_3 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 3 + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 3 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[SRLI]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:gprb(s64) = G_READ_VLENB + %1:gprb(s64) = G_CONSTANT i64 3 + %2:gprb(s64) = G_LSHR %0, %1(s64) + %3:gprb(s64) = G_CONSTANT i64 3 + %4:gprb(s64) = G_MUL %2, %3 + $x10 = COPY %4(s64) + PseudoRET implicit $x10 + +... +--- +name: test_4 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_4 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[PseudoReadVLENB]], 1 + ; CHECK-NEXT: $x10 = COPY [[SRLI]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:gprb(s64) = G_READ_VLENB + %1:gprb(s64) = G_CONSTANT i64 1 + %2:gprb(s64) = G_LSHR %0, %1(s64) + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: test_8 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_8 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: $x10 = COPY [[PseudoReadVLENB]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:gprb(s64) = G_READ_VLENB + $x10 = COPY %0(s64) + PseudoRET implicit $x10 + +... +--- +name: test_16 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_16 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[PseudoReadVLENB]], 1 + ; CHECK-NEXT: $x10 = COPY [[SLLI]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:gprb(s64) = G_READ_VLENB + %1:gprb(s64) = G_CONSTANT i64 1 + %2:gprb(s64) = G_SHL %0, %1(s64) + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... +--- +name: test_40 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_40 + ; CHECK: [[PseudoReadVLENB:%[0-9]+]]:gpr = PseudoReadVLENB + ; CHECK-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 5 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gpr = MUL [[PseudoReadVLENB]], [[ADDI]] + ; CHECK-NEXT: $x10 = COPY [[MUL]] + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:gprb(s64) = G_READ_VLENB + %1:gprb(s64) = G_CONSTANT i64 5 + %2:gprb(s64) = G_MUL %0, %1 + $x10 = COPY %2(s64) + PseudoRET implicit $x10 + +... diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/trap.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/trap.mir index 11789a030e6fac0973afcba844be67e2fa6df751..5f52030fc170127d95d267146f3ad3b0ca9286b2 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/trap.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/trap.mir @@ -14,7 +14,7 @@ body: | ; CHECK-LABEL: name: test_trap ; CHECK: UNIMP ; CHECK-NEXT: PseudoRET - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + G_TRAP PseudoRET ... @@ -28,7 +28,7 @@ body: | ; CHECK-LABEL: name: test_debugtrap ; CHECK: EBREAK ; CHECK-NEXT: PseudoRET - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.debugtrap) + G_DEBUGTRAP PseudoRET ... diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/vec-ld.ll b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/vec-ld.ll new file mode 100644 index 0000000000000000000000000000000000000000..31b3c3fe3c5be8a0b9b82e3d2d2d9997ebbacca9 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/irtranslator/vec-ld.ll @@ -0,0 +1,948 @@ +; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+v -global-isel -stop-after=irtranslator -verify-machineinstrs < %s | FileCheck -check-prefixes=RV32 %s +; RUN: llc -mtriple=riscv64 -mattr=+v -global-isel -stop-after=irtranslator -verify-machineinstrs < %s | FileCheck -check-prefixes=RV64 %s + +define <vscale x 1 x i8> @vload_nx1i8(ptr %pa) { + ; RV32-LABEL: name: vload_nx1i8 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 1 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 1 x s8>) from %ir.pa) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 1 x s8>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx1i8 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 1 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 1 x s8>) from %ir.pa) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 1 x s8>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 1 x i8>, ptr %pa + ret <vscale x 1 x i8> %va +} + +define <vscale x 2 x i8> @vload_nx2i8(ptr %pa) { + ; RV32-LABEL: name: vload_nx2i8 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s8>) from %ir.pa) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 2 x s8>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx2i8 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s8>) from %ir.pa) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 2 x s8>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 2 x i8>, ptr %pa + ret <vscale x 2 x i8> %va +} + +define <vscale x 4 x i8> @vload_nx4i8(ptr %pa) { + ; RV32-LABEL: name: vload_nx4i8 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s8>) from %ir.pa) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 4 x s8>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx4i8 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s8>) from %ir.pa) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 4 x s8>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 4 x i8>, ptr %pa + ret <vscale x 4 x i8> %va +} + +define <vscale x 8 x i8> @vload_nx8i8(ptr %pa) { + ; RV32-LABEL: name: vload_nx8i8 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 8 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 8 x s8>) from %ir.pa) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 8 x s8>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx8i8 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 8 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 8 x s8>) from %ir.pa) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 8 x s8>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 8 x i8>, ptr %pa + ret <vscale x 8 x i8> %va +} + +define <vscale x 16 x i8> @vload_nx16i8(ptr %pa) { + ; RV32-LABEL: name: vload_nx16i8 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 16 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 16 x s8>) from %ir.pa) + ; RV32-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 16 x s8>) + ; RV32-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64-LABEL: name: vload_nx16i8 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 16 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 16 x s8>) from %ir.pa) + ; RV64-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 16 x s8>) + ; RV64-NEXT: PseudoRET implicit $v8m2 + %va = load <vscale x 16 x i8>, ptr %pa + ret <vscale x 16 x i8> %va +} + +define <vscale x 32 x i8> @vload_nx32i8(ptr %pa) { + ; RV32-LABEL: name: vload_nx32i8 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 32 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 32 x s8>) from %ir.pa) + ; RV32-NEXT: $v8m4 = COPY [[LOAD]](<vscale x 32 x s8>) + ; RV32-NEXT: PseudoRET implicit $v8m4 + ; + ; RV64-LABEL: name: vload_nx32i8 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 32 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 32 x s8>) from %ir.pa) + ; RV64-NEXT: $v8m4 = COPY [[LOAD]](<vscale x 32 x s8>) + ; RV64-NEXT: PseudoRET implicit $v8m4 + %va = load <vscale x 32 x i8>, ptr %pa + ret <vscale x 32 x i8> %va +} + +define <vscale x 64 x i8> @vload_nx64i8(ptr %pa) { + ; RV32-LABEL: name: vload_nx64i8 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 64 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 64 x s8>) from %ir.pa) + ; RV32-NEXT: $v8m8 = COPY [[LOAD]](<vscale x 64 x s8>) + ; RV32-NEXT: PseudoRET implicit $v8m8 + ; + ; RV64-LABEL: name: vload_nx64i8 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 64 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 64 x s8>) from %ir.pa) + ; RV64-NEXT: $v8m8 = COPY [[LOAD]](<vscale x 64 x s8>) + ; RV64-NEXT: PseudoRET implicit $v8m8 + %va = load <vscale x 64 x i8>, ptr %pa + ret <vscale x 64 x i8> %va +} + +define <vscale x 1 x i16> @vload_nx1i16(ptr %pa) { + ; RV32-LABEL: name: vload_nx1i16 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 1 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 1 x s16>) from %ir.pa) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 1 x s16>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx1i16 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 1 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 1 x s16>) from %ir.pa) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 1 x s16>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 1 x i16>, ptr %pa + ret <vscale x 1 x i16> %va +} + +define <vscale x 2 x i16> @vload_nx2i16(ptr %pa) { + ; RV32-LABEL: name: vload_nx2i16 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s16>) from %ir.pa) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 2 x s16>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx2i16 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s16>) from %ir.pa) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 2 x s16>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 2 x i16>, ptr %pa + ret <vscale x 2 x i16> %va +} + +define <vscale x 4 x i16> @vload_nx4i16(ptr %pa) { + ; RV32-LABEL: name: vload_nx4i16 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s16>) from %ir.pa) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 4 x s16>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx4i16 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s16>) from %ir.pa) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 4 x s16>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 4 x i16>, ptr %pa + ret <vscale x 4 x i16> %va +} + +define <vscale x 8 x i16> @vload_nx8i16(ptr %pa) { + ; RV32-LABEL: name: vload_nx8i16 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 8 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 8 x s16>) from %ir.pa) + ; RV32-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 8 x s16>) + ; RV32-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64-LABEL: name: vload_nx8i16 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 8 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 8 x s16>) from %ir.pa) + ; RV64-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 8 x s16>) + ; RV64-NEXT: PseudoRET implicit $v8m2 + %va = load <vscale x 8 x i16>, ptr %pa + ret <vscale x 8 x i16> %va +} + +define <vscale x 16 x i16> @vload_nx16i16(ptr %pa) { + ; RV32-LABEL: name: vload_nx16i16 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 16 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 16 x s16>) from %ir.pa) + ; RV32-NEXT: $v8m4 = COPY [[LOAD]](<vscale x 16 x s16>) + ; RV32-NEXT: PseudoRET implicit $v8m4 + ; + ; RV64-LABEL: name: vload_nx16i16 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 16 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 16 x s16>) from %ir.pa) + ; RV64-NEXT: $v8m4 = COPY [[LOAD]](<vscale x 16 x s16>) + ; RV64-NEXT: PseudoRET implicit $v8m4 + %va = load <vscale x 16 x i16>, ptr %pa + ret <vscale x 16 x i16> %va +} + +define <vscale x 32 x i16> @vload_nx32i16(ptr %pa) { + ; RV32-LABEL: name: vload_nx32i16 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 32 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 32 x s16>) from %ir.pa) + ; RV32-NEXT: $v8m8 = COPY [[LOAD]](<vscale x 32 x s16>) + ; RV32-NEXT: PseudoRET implicit $v8m8 + ; + ; RV64-LABEL: name: vload_nx32i16 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 32 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 32 x s16>) from %ir.pa) + ; RV64-NEXT: $v8m8 = COPY [[LOAD]](<vscale x 32 x s16>) + ; RV64-NEXT: PseudoRET implicit $v8m8 + %va = load <vscale x 32 x i16>, ptr %pa + ret <vscale x 32 x i16> %va +} + +define <vscale x 1 x i32> @vload_nx1i32(ptr %pa) { + ; RV32-LABEL: name: vload_nx1i32 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 1 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 1 x s32>) from %ir.pa) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 1 x s32>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx1i32 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 1 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 1 x s32>) from %ir.pa) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 1 x s32>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 1 x i32>, ptr %pa + ret <vscale x 1 x i32> %va +} + +define <vscale x 2 x i32> @vload_nx2i32(ptr %pa) { + ; RV32-LABEL: name: vload_nx2i32 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s32>) from %ir.pa) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 2 x s32>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx2i32 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s32>) from %ir.pa) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 2 x s32>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 2 x i32>, ptr %pa + ret <vscale x 2 x i32> %va +} + +define <vscale x 4 x i32> @vload_nx4i32(ptr %pa) { + ; RV32-LABEL: name: vload_nx4i32 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s32>) from %ir.pa) + ; RV32-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 4 x s32>) + ; RV32-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64-LABEL: name: vload_nx4i32 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s32>) from %ir.pa) + ; RV64-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 4 x s32>) + ; RV64-NEXT: PseudoRET implicit $v8m2 + %va = load <vscale x 4 x i32>, ptr %pa + ret <vscale x 4 x i32> %va +} + +define <vscale x 8 x i32> @vload_nx8i32(ptr %pa) { + ; RV32-LABEL: name: vload_nx8i32 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 8 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 8 x s32>) from %ir.pa) + ; RV32-NEXT: $v8m4 = COPY [[LOAD]](<vscale x 8 x s32>) + ; RV32-NEXT: PseudoRET implicit $v8m4 + ; + ; RV64-LABEL: name: vload_nx8i32 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 8 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 8 x s32>) from %ir.pa) + ; RV64-NEXT: $v8m4 = COPY [[LOAD]](<vscale x 8 x s32>) + ; RV64-NEXT: PseudoRET implicit $v8m4 + %va = load <vscale x 8 x i32>, ptr %pa + ret <vscale x 8 x i32> %va +} + +define <vscale x 16 x i32> @vload_nx16i32(ptr %pa) { + ; RV32-LABEL: name: vload_nx16i32 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 16 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 16 x s32>) from %ir.pa) + ; RV32-NEXT: $v8m8 = COPY [[LOAD]](<vscale x 16 x s32>) + ; RV32-NEXT: PseudoRET implicit $v8m8 + ; + ; RV64-LABEL: name: vload_nx16i32 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 16 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 16 x s32>) from %ir.pa) + ; RV64-NEXT: $v8m8 = COPY [[LOAD]](<vscale x 16 x s32>) + ; RV64-NEXT: PseudoRET implicit $v8m8 + %va = load <vscale x 16 x i32>, ptr %pa + ret <vscale x 16 x i32> %va +} + +define <vscale x 1 x i64> @vload_nx1i64(ptr %pa) { + ; RV32-LABEL: name: vload_nx1i64 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 1 x s64>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 1 x s64>) from %ir.pa) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 1 x s64>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx1i64 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 1 x s64>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 1 x s64>) from %ir.pa) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 1 x s64>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 1 x i64>, ptr %pa + ret <vscale x 1 x i64> %va +} + +define <vscale x 2 x i64> @vload_nx2i64(ptr %pa) { + ; RV32-LABEL: name: vload_nx2i64 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s64>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s64>) from %ir.pa) + ; RV32-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 2 x s64>) + ; RV32-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64-LABEL: name: vload_nx2i64 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s64>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s64>) from %ir.pa) + ; RV64-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 2 x s64>) + ; RV64-NEXT: PseudoRET implicit $v8m2 + %va = load <vscale x 2 x i64>, ptr %pa + ret <vscale x 2 x i64> %va +} + +define <vscale x 4 x i64> @vload_nx4i64(ptr %pa) { + ; RV32-LABEL: name: vload_nx4i64 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s64>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s64>) from %ir.pa) + ; RV32-NEXT: $v8m4 = COPY [[LOAD]](<vscale x 4 x s64>) + ; RV32-NEXT: PseudoRET implicit $v8m4 + ; + ; RV64-LABEL: name: vload_nx4i64 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s64>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s64>) from %ir.pa) + ; RV64-NEXT: $v8m4 = COPY [[LOAD]](<vscale x 4 x s64>) + ; RV64-NEXT: PseudoRET implicit $v8m4 + %va = load <vscale x 4 x i64>, ptr %pa + ret <vscale x 4 x i64> %va +} + +define <vscale x 8 x i64> @vload_nx8i64(ptr %pa) { + ; RV32-LABEL: name: vload_nx8i64 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 8 x s64>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 8 x s64>) from %ir.pa) + ; RV32-NEXT: $v8m8 = COPY [[LOAD]](<vscale x 8 x s64>) + ; RV32-NEXT: PseudoRET implicit $v8m8 + ; + ; RV64-LABEL: name: vload_nx8i64 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 8 x s64>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 8 x s64>) from %ir.pa) + ; RV64-NEXT: $v8m8 = COPY [[LOAD]](<vscale x 8 x s64>) + ; RV64-NEXT: PseudoRET implicit $v8m8 + %va = load <vscale x 8 x i64>, ptr %pa + ret <vscale x 8 x i64> %va +} + +define <vscale x 16 x i8> @vload_nx16i8_align1(ptr %pa) { + ; RV32-LABEL: name: vload_nx16i8_align1 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 16 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 16 x s8>) from %ir.pa, align 1) + ; RV32-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 16 x s8>) + ; RV32-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64-LABEL: name: vload_nx16i8_align1 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 16 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 16 x s8>) from %ir.pa, align 1) + ; RV64-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 16 x s8>) + ; RV64-NEXT: PseudoRET implicit $v8m2 + %va = load <vscale x 16 x i8>, ptr %pa, align 1 + ret <vscale x 16 x i8> %va +} + +define <vscale x 16 x i8> @vload_nx16i8_align2(ptr %pa) { + ; RV32-LABEL: name: vload_nx16i8_align2 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 16 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 16 x s8>) from %ir.pa, align 2) + ; RV32-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 16 x s8>) + ; RV32-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64-LABEL: name: vload_nx16i8_align2 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 16 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 16 x s8>) from %ir.pa, align 2) + ; RV64-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 16 x s8>) + ; RV64-NEXT: PseudoRET implicit $v8m2 + %va = load <vscale x 16 x i8>, ptr %pa, align 2 + ret <vscale x 16 x i8> %va +} + +define <vscale x 16 x i8> @vload_nx16i8_align16(ptr %pa) { + ; RV32-LABEL: name: vload_nx16i8_align16 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 16 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 16 x s8>) from %ir.pa) + ; RV32-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 16 x s8>) + ; RV32-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64-LABEL: name: vload_nx16i8_align16 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 16 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 16 x s8>) from %ir.pa) + ; RV64-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 16 x s8>) + ; RV64-NEXT: PseudoRET implicit $v8m2 + %va = load <vscale x 16 x i8>, ptr %pa, align 16 + ret <vscale x 16 x i8> %va +} + +define <vscale x 16 x i8> @vload_nx16i8_align64(ptr %pa) { + ; RV32-LABEL: name: vload_nx16i8_align64 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 16 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 16 x s8>) from %ir.pa, align 64) + ; RV32-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 16 x s8>) + ; RV32-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64-LABEL: name: vload_nx16i8_align64 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 16 x s8>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 16 x s8>) from %ir.pa, align 64) + ; RV64-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 16 x s8>) + ; RV64-NEXT: PseudoRET implicit $v8m2 + %va = load <vscale x 16 x i8>, ptr %pa, align 64 + ret <vscale x 16 x i8> %va +} + +define <vscale x 4 x i16> @vload_nx4i16_align1(ptr %pa) { + ; RV32-LABEL: name: vload_nx4i16_align1 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s16>) from %ir.pa, align 1) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 4 x s16>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx4i16_align1 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s16>) from %ir.pa, align 1) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 4 x s16>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 4 x i16>, ptr %pa, align 1 + ret <vscale x 4 x i16> %va +} + +define <vscale x 4 x i16> @vload_nx4i16_align2(ptr %pa) { + ; RV32-LABEL: name: vload_nx4i16_align2 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s16>) from %ir.pa, align 2) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 4 x s16>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx4i16_align2 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s16>) from %ir.pa, align 2) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 4 x s16>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 4 x i16>, ptr %pa, align 2 + ret <vscale x 4 x i16> %va +} + +define <vscale x 4 x i16> @vload_nx4i16_align4(ptr %pa) { + ; RV32-LABEL: name: vload_nx4i16_align4 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s16>) from %ir.pa, align 4) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 4 x s16>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx4i16_align4 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s16>) from %ir.pa, align 4) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 4 x s16>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 4 x i16>, ptr %pa, align 4 + ret <vscale x 4 x i16> %va +} +define <vscale x 4 x i16> @vload_nx4i16_align8(ptr %pa) { + ; RV32-LABEL: name: vload_nx4i16_align8 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s16>) from %ir.pa) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 4 x s16>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx4i16_align8 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s16>) from %ir.pa) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 4 x s16>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 4 x i16>, ptr %pa, align 8 + ret <vscale x 4 x i16> %va +} + +define <vscale x 4 x i16> @vload_nx4i16_align16(ptr %pa) { + ; RV32-LABEL: name: vload_nx4i16_align16 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s16>) from %ir.pa, align 16) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 4 x s16>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx4i16_align16 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 4 x s16>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 4 x s16>) from %ir.pa, align 16) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 4 x s16>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 4 x i16>, ptr %pa, align 16 + ret <vscale x 4 x i16> %va +} + +define <vscale x 2 x i32> @vload_nx2i32_align2(ptr %pa) { + ; RV32-LABEL: name: vload_nx2i32_align2 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s32>) from %ir.pa, align 2) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 2 x s32>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx2i32_align2 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s32>) from %ir.pa, align 2) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 2 x s32>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 2 x i32>, ptr %pa, align 2 + ret <vscale x 2 x i32> %va +} + +define <vscale x 2 x i32> @vload_nx2i32_align4(ptr %pa) { + ; RV32-LABEL: name: vload_nx2i32_align4 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s32>) from %ir.pa, align 4) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 2 x s32>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx2i32_align4 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s32>) from %ir.pa, align 4) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 2 x s32>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 2 x i32>, ptr %pa, align 4 + ret <vscale x 2 x i32> %va +} + +define <vscale x 2 x i32> @vload_nx2i32_align8(ptr %pa) { + ; RV32-LABEL: name: vload_nx2i32_align8 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s32>) from %ir.pa) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 2 x s32>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx2i32_align8 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s32>) from %ir.pa) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 2 x s32>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 2 x i32>, ptr %pa, align 8 + ret <vscale x 2 x i32> %va +} + +define <vscale x 2 x i32> @vload_nx2i32_align16(ptr %pa) { + ; RV32-LABEL: name: vload_nx2i32_align16 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s32>) from %ir.pa, align 16) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 2 x s32>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx2i32_align16 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s32>) from %ir.pa, align 16) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 2 x s32>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 2 x i32>, ptr %pa, align 16 + ret <vscale x 2 x i32> %va +} + +define <vscale x 2 x i32> @vload_nx2i32_align256(ptr %pa) { + ; RV32-LABEL: name: vload_nx2i32_align256 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s32>) from %ir.pa, align 256) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 2 x s32>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx2i32_align256 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s32>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s32>) from %ir.pa, align 256) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 2 x s32>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 2 x i32>, ptr %pa, align 256 + ret <vscale x 2 x i32> %va +} +define <vscale x 2 x i64> @vload_nx2i64_align4(ptr %pa) { + ; RV32-LABEL: name: vload_nx2i64_align4 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s64>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s64>) from %ir.pa, align 4) + ; RV32-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 2 x s64>) + ; RV32-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64-LABEL: name: vload_nx2i64_align4 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s64>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s64>) from %ir.pa, align 4) + ; RV64-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 2 x s64>) + ; RV64-NEXT: PseudoRET implicit $v8m2 + %va = load <vscale x 2 x i64>, ptr %pa, align 4 + ret <vscale x 2 x i64> %va +} + +define <vscale x 2 x i64> @vload_nx2i64_align8(ptr %pa) { + ; RV32-LABEL: name: vload_nx2i64_align8 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s64>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s64>) from %ir.pa, align 8) + ; RV32-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 2 x s64>) + ; RV32-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64-LABEL: name: vload_nx2i64_align8 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s64>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s64>) from %ir.pa, align 8) + ; RV64-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 2 x s64>) + ; RV64-NEXT: PseudoRET implicit $v8m2 + %va = load <vscale x 2 x i64>, ptr %pa, align 8 + ret <vscale x 2 x i64> %va +} + +define <vscale x 2 x i64> @vload_nx2i64_align16(ptr %pa) { + ; RV32-LABEL: name: vload_nx2i64_align16 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s64>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s64>) from %ir.pa) + ; RV32-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 2 x s64>) + ; RV32-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64-LABEL: name: vload_nx2i64_align16 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s64>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s64>) from %ir.pa) + ; RV64-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 2 x s64>) + ; RV64-NEXT: PseudoRET implicit $v8m2 + %va = load <vscale x 2 x i64>, ptr %pa, align 16 + ret <vscale x 2 x i64> %va +} + +define <vscale x 2 x i64> @vload_nx2i64_align32(ptr %pa) { + ; RV32-LABEL: name: vload_nx2i64_align32 + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s64>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s64>) from %ir.pa, align 32) + ; RV32-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 2 x s64>) + ; RV32-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64-LABEL: name: vload_nx2i64_align32 + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x s64>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x s64>) from %ir.pa, align 32) + ; RV64-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 2 x s64>) + ; RV64-NEXT: PseudoRET implicit $v8m2 + %va = load <vscale x 2 x i64>, ptr %pa, align 32 + ret <vscale x 2 x i64> %va +} + +define <vscale x 1 x ptr> @vload_nx1ptr(ptr %pa) { + ; RV32-LABEL: name: vload_nx1ptr + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 1 x p0>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 1 x p0>) from %ir.pa) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 1 x p0>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx1ptr + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 1 x p0>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 1 x p0>) from %ir.pa) + ; RV64-NEXT: $v8 = COPY [[LOAD]](<vscale x 1 x p0>) + ; RV64-NEXT: PseudoRET implicit $v8 + %va = load <vscale x 1 x ptr>, ptr %pa + ret <vscale x 1 x ptr> %va +} + +define <vscale x 2 x ptr> @vload_nx2ptr(ptr %pa) { + ; RV32-LABEL: name: vload_nx2ptr + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x p0>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x p0>) from %ir.pa) + ; RV32-NEXT: $v8 = COPY [[LOAD]](<vscale x 2 x p0>) + ; RV32-NEXT: PseudoRET implicit $v8 + ; + ; RV64-LABEL: name: vload_nx2ptr + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 2 x p0>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 2 x p0>) from %ir.pa) + ; RV64-NEXT: $v8m2 = COPY [[LOAD]](<vscale x 2 x p0>) + ; RV64-NEXT: PseudoRET implicit $v8m2 + %va = load <vscale x 2x ptr>, ptr %pa + ret <vscale x 2 x ptr> %va +} + +define <vscale x 8 x ptr> @vload_nx8ptr(ptr %pa) { + ; RV32-LABEL: name: vload_nx8ptr + ; RV32: bb.1 (%ir-block.0): + ; RV32-NEXT: liveins: $x10 + ; RV32-NEXT: {{ $}} + ; RV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV32-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 8 x p0>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 8 x p0>) from %ir.pa) + ; RV32-NEXT: $v8m4 = COPY [[LOAD]](<vscale x 8 x p0>) + ; RV32-NEXT: PseudoRET implicit $v8m4 + ; + ; RV64-LABEL: name: vload_nx8ptr + ; RV64: bb.1 (%ir-block.0): + ; RV64-NEXT: liveins: $x10 + ; RV64-NEXT: {{ $}} + ; RV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 + ; RV64-NEXT: [[LOAD:%[0-9]+]]:_(<vscale x 8 x p0>) = G_LOAD [[COPY]](p0) :: (load (<vscale x 8 x p0>) from %ir.pa) + ; RV64-NEXT: $v8m8 = COPY [[LOAD]](<vscale x 8 x p0>) + ; RV64-NEXT: PseudoRET implicit $v8m8 + %va = load <vscale x 8 x ptr>, ptr %pa + ret <vscale x 8 x ptr> %va +} + diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-add-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-add-rv32.mir index d169eb316dfcb7a5e352621701297e2e19e607f0..b3c62df4ffdcab8a6464cb276583232ab84ff5f7 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-add-rv32.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-add-rv32.mir @@ -89,10 +89,12 @@ body: | ; CHECK-NEXT: %yhi:_(s32) = COPY $x13 ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD %xlo, %ylo ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), %ylo + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD %xhi, %yhi ; CHECK-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ADD1]], [[ICMP]] - ; CHECK-NEXT: $x10 = COPY [[ADD]](s32) - ; CHECK-NEXT: $x11 = COPY [[ADD2]](s32) + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY [[ADD2]](s32) + ; CHECK-NEXT: $x10 = COPY [[COPY]](s32) + ; CHECK-NEXT: $x11 = COPY [[COPY1]](s32) ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11 %xlo:_(s32) = COPY $x10 %xhi:_(s32) = COPY $x11 @@ -121,10 +123,12 @@ body: | ; CHECK-NEXT: %hi2:_(s32) = COPY $x13 ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD %lo1, %lo2 ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), %lo2 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD %hi1, %hi2 ; CHECK-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ADD1]], [[ICMP]] - ; CHECK-NEXT: $x10 = COPY [[ADD]](s32) - ; CHECK-NEXT: $x11 = COPY [[ADD2]](s32) + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY [[ADD2]](s32) + ; CHECK-NEXT: $x10 = COPY [[COPY]](s32) + ; CHECK-NEXT: $x11 = COPY [[COPY1]](s32) ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11 %lo1:_(s32) = COPY $x10 %hi1:_(s32) = COPY $x11 @@ -152,6 +156,7 @@ body: | ; CHECK-NEXT: %hi2:_(s32) = COPY $x15 ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD %lo1, %lo2 ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), %lo2 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD %mid1, %mid2 ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD1]](s32), %mid1 ; CHECK-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ADD1]], [[ICMP]] @@ -159,11 +164,13 @@ body: | ; CHECK-NEXT: [[ICMP2:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[ADD2]](s32), [[C]] ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ICMP2]], [[ICMP]] ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[ICMP1]], [[AND]] + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY [[ADD2]](s32) ; CHECK-NEXT: [[ADD3:%[0-9]+]]:_(s32) = G_ADD %hi1, %hi2 ; CHECK-NEXT: [[ADD4:%[0-9]+]]:_(s32) = G_ADD [[ADD3]], [[OR]] - ; CHECK-NEXT: $x10 = COPY [[ADD]](s32) - ; CHECK-NEXT: $x11 = COPY [[ADD2]](s32) - ; CHECK-NEXT: $x12 = COPY [[ADD4]](s32) + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY [[ADD4]](s32) + ; CHECK-NEXT: $x10 = COPY [[COPY]](s32) + ; CHECK-NEXT: $x11 = COPY [[COPY1]](s32) + ; CHECK-NEXT: $x12 = COPY [[COPY2]](s32) ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11, implicit $x12 %lo1:_(s32) = COPY $x10 %mid1:_(s32) = COPY $x11 diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-add-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-add-rv64.mir index f394e4d5064edc50bafac78bb4ae2a3ec5258749..6e76bb0e3eff55c1be557c5aee5688edaf3b10fe 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-add-rv64.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-add-rv64.mir @@ -121,10 +121,12 @@ body: | ; CHECK-NEXT: %y01:_(s64) = COPY $x13 ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD %x00, %y00 ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(ult), [[ADD]](s64), %y00 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY [[ADD]](s64) ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s64) = G_ADD %x01, %y01 ; CHECK-NEXT: [[ADD2:%[0-9]+]]:_(s64) = G_ADD [[ADD1]], [[ICMP]] - ; CHECK-NEXT: $x10 = COPY [[ADD]](s64) - ; CHECK-NEXT: $x11 = COPY [[ADD2]](s64) + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY [[ADD2]](s64) + ; CHECK-NEXT: $x10 = COPY [[COPY]](s64) + ; CHECK-NEXT: $x11 = COPY [[COPY1]](s64) ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11 %x00:_(s64) = COPY $x10 %x01:_(s64) = COPY $x11 @@ -153,10 +155,12 @@ body: | ; CHECK-NEXT: %hi2:_(s64) = COPY $x13 ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD %lo1, %lo2 ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(ult), [[ADD]](s64), %lo2 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY [[ADD]](s64) ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s64) = G_ADD %hi1, %hi2 ; CHECK-NEXT: [[ADD2:%[0-9]+]]:_(s64) = G_ADD [[ADD1]], [[ICMP]] - ; CHECK-NEXT: $x10 = COPY [[ADD]](s64) - ; CHECK-NEXT: $x11 = COPY [[ADD2]](s64) + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY [[ADD2]](s64) + ; CHECK-NEXT: $x10 = COPY [[COPY]](s64) + ; CHECK-NEXT: $x11 = COPY [[COPY1]](s64) ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11 %lo1:_(s64) = COPY $x10 %hi1:_(s64) = COPY $x11 @@ -184,6 +188,7 @@ body: | ; CHECK-NEXT: %hi2:_(s64) = COPY $x15 ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD %lo1, %lo2 ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(ult), [[ADD]](s64), %lo2 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY [[ADD]](s64) ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s64) = G_ADD %mid1, %mid2 ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s64) = G_ICMP intpred(ult), [[ADD1]](s64), %mid1 ; CHECK-NEXT: [[ADD2:%[0-9]+]]:_(s64) = G_ADD [[ADD1]], [[ICMP]] @@ -194,14 +199,16 @@ body: | ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[TRUNC]], [[TRUNC1]] ; CHECK-NEXT: [[TRUNC2:%[0-9]+]]:_(s32) = G_TRUNC [[ICMP1]](s64) ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[TRUNC2]], [[AND]] + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY [[ADD2]](s64) ; CHECK-NEXT: [[ADD3:%[0-9]+]]:_(s64) = G_ADD %hi1, %hi2 ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[OR]](s32) ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s64) = G_AND [[ANYEXT]], [[C1]] ; CHECK-NEXT: [[ADD4:%[0-9]+]]:_(s64) = G_ADD [[ADD3]], [[AND1]] - ; CHECK-NEXT: $x10 = COPY [[ADD]](s64) - ; CHECK-NEXT: $x11 = COPY [[ADD2]](s64) - ; CHECK-NEXT: $x12 = COPY [[ADD4]](s64) + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[ADD4]](s64) + ; CHECK-NEXT: $x10 = COPY [[COPY]](s64) + ; CHECK-NEXT: $x11 = COPY [[COPY1]](s64) + ; CHECK-NEXT: $x12 = COPY [[COPY2]](s64) ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11, implicit $x12 %lo1:_(s64) = COPY $x10 %mid1:_(s64) = COPY $x11 diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-addo-subo-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-addo-subo-rv32.mir index c348ec6f73ad3d52ff3ff7f3699935b6d570d96b..9227e6530221c9ae476d8540cd4013c274aabc8c 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-addo-subo-rv32.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-addo-subo-rv32.mir @@ -92,7 +92,8 @@ body: | ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[ADD]](s32), [[COPY]] ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[COPY1]](s32), [[C]] ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ICMP1]], [[ICMP]] - ; CHECK-NEXT: $x10 = COPY [[ADD]](s32) + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) + ; CHECK-NEXT: $x10 = COPY [[COPY2]](s32) ; CHECK-NEXT: $x11 = COPY [[XOR]](s32) ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11 %0:_(s32) = COPY $x10 @@ -119,21 +120,23 @@ body: | ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $x13 ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[COPY2]] ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), [[COPY2]] + ; CHECK-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[COPY1]], [[COPY3]] ; CHECK-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ADD1]], [[ICMP]] + ; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY [[ADD2]](s32) ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 - ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[ADD2]](s32), [[COPY1]] - ; CHECK-NEXT: [[ICMP2:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[ADD2]](s32), [[COPY1]] - ; CHECK-NEXT: [[ICMP3:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), [[COPY]] + ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[COPY5]](s32), [[COPY1]] + ; CHECK-NEXT: [[ICMP2:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[COPY5]](s32), [[COPY1]] + ; CHECK-NEXT: [[ICMP3:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[COPY4]](s32), [[COPY]] ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP2]](s32), [[ICMP3]], [[ICMP1]] ; CHECK-NEXT: [[ICMP4:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[COPY3]](s32), [[C1]] ; CHECK-NEXT: [[ICMP5:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[COPY3]](s32), [[C1]] ; CHECK-NEXT: [[ICMP6:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[COPY2]](s32), [[C]] ; CHECK-NEXT: [[SELECT1:%[0-9]+]]:_(s32) = G_SELECT [[ICMP5]](s32), [[ICMP6]], [[ICMP4]] ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[SELECT1]], [[SELECT]] - ; CHECK-NEXT: $x10 = COPY [[ADD]](s32) - ; CHECK-NEXT: $x11 = COPY [[ADD2]](s32) + ; CHECK-NEXT: $x10 = COPY [[COPY4]](s32) + ; CHECK-NEXT: $x11 = COPY [[COPY5]](s32) ; CHECK-NEXT: $x12 = COPY [[XOR]](s32) ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11, implicit $x12 %2:_(s32) = COPY $x10 @@ -241,7 +244,8 @@ body: | ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(slt), [[SUB]](s32), [[COPY]] ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(sgt), [[COPY1]](s32), [[C]] ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ICMP1]], [[ICMP]] - ; CHECK-NEXT: $x10 = COPY [[SUB]](s32) + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY [[SUB]](s32) + ; CHECK-NEXT: $x10 = COPY [[COPY2]](s32) ; CHECK-NEXT: $x11 = COPY [[XOR]](s32) ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11 %0:_(s32) = COPY $x10 @@ -377,7 +381,8 @@ body: | ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[COPY1]] ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), [[COPY1]] - ; CHECK-NEXT: $x10 = COPY [[ADD]](s32) + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) + ; CHECK-NEXT: $x10 = COPY [[COPY2]](s32) ; CHECK-NEXT: $x11 = COPY [[ICMP]](s32) ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11 %0:_(s32) = COPY $x10 @@ -404,14 +409,16 @@ body: | ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $x13 ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[COPY2]] ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), [[COPY2]] + ; CHECK-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[COPY1]], [[COPY3]] ; CHECK-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ADD1]], [[ICMP]] - ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD2]](s32), [[COPY3]] - ; CHECK-NEXT: [[ICMP2:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[ADD2]](s32), [[COPY3]] - ; CHECK-NEXT: [[ICMP3:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), [[COPY2]] + ; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY [[ADD2]](s32) + ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[COPY5]](s32), [[COPY3]] + ; CHECK-NEXT: [[ICMP2:%[0-9]+]]:_(s32) = G_ICMP intpred(eq), [[COPY5]](s32), [[COPY3]] + ; CHECK-NEXT: [[ICMP3:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[COPY4]](s32), [[COPY2]] ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP2]](s32), [[ICMP3]], [[ICMP1]] - ; CHECK-NEXT: $x10 = COPY [[ADD]](s32) - ; CHECK-NEXT: $x11 = COPY [[ADD2]](s32) + ; CHECK-NEXT: $x10 = COPY [[COPY4]](s32) + ; CHECK-NEXT: $x11 = COPY [[COPY5]](s32) ; CHECK-NEXT: $x12 = COPY [[SELECT]](s32) ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11, implicit $x12 %2:_(s32) = COPY $x10 diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-addo-subo-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-addo-subo-rv64.mir index 5506f5228e9dbdc25b9034eddb37f674050518b0..8acaff5dbb25a363729dc6f682f9e72d2ec2dc59 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-addo-subo-rv64.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-addo-subo-rv64.mir @@ -125,8 +125,9 @@ body: | ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[ICMP1]](s64) ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[ICMP]](s64) ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[TRUNC]], [[TRUNC1]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[ADD]](s64) ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[XOR]](s32) - ; CHECK-NEXT: $x10 = COPY [[ADD]](s64) + ; CHECK-NEXT: $x10 = COPY [[COPY2]](s64) ; CHECK-NEXT: $x11 = COPY [[ANYEXT]](s64) ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11 %0:_(s64) = COPY $x10 @@ -261,8 +262,9 @@ body: | ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[ICMP1]](s64) ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[ICMP]](s64) ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[TRUNC]], [[TRUNC1]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[SUB]](s64) ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[XOR]](s32) - ; CHECK-NEXT: $x10 = COPY [[SUB]](s64) + ; CHECK-NEXT: $x10 = COPY [[COPY2]](s64) ; CHECK-NEXT: $x11 = COPY [[ANYEXT]](s64) ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11 %0:_(s64) = COPY $x10 @@ -364,7 +366,8 @@ body: | ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 4294967295 ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[COPY1]], [[C]] ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(ult), [[ZEXT]](s64), [[AND]] - ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[ADD]](s32) + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[COPY2]](s32) ; CHECK-NEXT: $x10 = COPY [[ANYEXT]](s64) ; CHECK-NEXT: $x11 = COPY [[ICMP]](s64) ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11 @@ -393,7 +396,8 @@ body: | ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11 ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[COPY]], [[COPY1]] ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(ult), [[ADD]](s64), [[COPY1]] - ; CHECK-NEXT: $x10 = COPY [[ADD]](s64) + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[ADD]](s64) + ; CHECK-NEXT: $x10 = COPY [[COPY2]](s64) ; CHECK-NEXT: $x11 = COPY [[ICMP]](s64) ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11 %0:_(s64) = COPY $x10 diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-ctlz-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-ctlz-rv32.mir index a890a411544e74bb6a2892ec0fc5f2ec36037f05..354fc109a463819f971afb9fb4f041356f6c9986 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-ctlz-rv32.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-ctlz-rv32.mir @@ -50,8 +50,8 @@ body: | ; RV32I-NEXT: [[C13:%[0-9]+]]:_(s32) = G_CONSTANT i32 15 ; RV32I-NEXT: [[AND8:%[0-9]+]]:_(s32) = G_AND [[ADD1]], [[C13]] ; RV32I-NEXT: [[C14:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND8]], [[C14]] ; RV32I-NEXT: [[C15:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND8]], [[C14]] ; RV32I-NEXT: [[LSHR6:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C15]](s32) ; RV32I-NEXT: [[C16:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 ; RV32I-NEXT: [[SUB1:%[0-9]+]]:_(s32) = G_SUB [[C16]], [[LSHR6]] @@ -129,8 +129,8 @@ body: | ; RV32I-NEXT: [[C15:%[0-9]+]]:_(s32) = G_CONSTANT i32 3855 ; RV32I-NEXT: [[AND9:%[0-9]+]]:_(s32) = G_AND [[ADD1]], [[C15]] ; RV32I-NEXT: [[C16:%[0-9]+]]:_(s32) = G_CONSTANT i32 257 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND9]], [[C16]] ; RV32I-NEXT: [[C17:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND9]], [[C16]] ; RV32I-NEXT: [[C18:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 ; RV32I-NEXT: [[AND10:%[0-9]+]]:_(s32) = G_AND [[MUL]], [[C18]] ; RV32I-NEXT: [[LSHR7:%[0-9]+]]:_(s32) = G_LSHR [[AND10]], [[C17]](s32) @@ -201,8 +201,8 @@ body: | ; RV32I-NEXT: [[C10:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 ; RV32I-NEXT: [[AND3:%[0-9]+]]:_(s32) = G_AND [[ADD1]], [[C10]] ; RV32I-NEXT: [[C11:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND3]], [[C11]] ; RV32I-NEXT: [[C12:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND3]], [[C11]] ; RV32I-NEXT: [[LSHR8:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C12]](s32) ; RV32I-NEXT: [[C13:%[0-9]+]]:_(s32) = G_CONSTANT i32 32 ; RV32I-NEXT: [[SUB1:%[0-9]+]]:_(s32) = G_SUB [[C13]], [[LSHR8]] @@ -267,8 +267,8 @@ body: | ; RV32I-NEXT: [[C11:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 ; RV32I-NEXT: [[AND3:%[0-9]+]]:_(s32) = G_AND [[ADD1]], [[C11]] ; RV32I-NEXT: [[C12:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND3]], [[C12]] ; RV32I-NEXT: [[C13:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND3]], [[C12]] ; RV32I-NEXT: [[LSHR8:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C13]](s32) ; RV32I-NEXT: [[C14:%[0-9]+]]:_(s32) = G_CONSTANT i32 32 ; RV32I-NEXT: [[SUB1:%[0-9]+]]:_(s32) = G_SUB [[C14]], [[LSHR8]] @@ -306,8 +306,8 @@ body: | ; RV32I-NEXT: [[C26:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 ; RV32I-NEXT: [[AND7:%[0-9]+]]:_(s32) = G_AND [[ADD4]], [[C26]] ; RV32I-NEXT: [[C27:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 - ; RV32I-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL [[AND7]], [[C27]] ; RV32I-NEXT: [[C28:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; RV32I-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL [[AND7]], [[C27]] ; RV32I-NEXT: [[LSHR17:%[0-9]+]]:_(s32) = G_LSHR [[MUL1]], [[C28]](s32) ; RV32I-NEXT: [[C29:%[0-9]+]]:_(s32) = G_CONSTANT i32 32 ; RV32I-NEXT: [[SUB3:%[0-9]+]]:_(s32) = G_SUB [[C29]], [[LSHR17]] @@ -389,8 +389,8 @@ body: | ; RV32I-NEXT: [[C13:%[0-9]+]]:_(s32) = G_CONSTANT i32 15 ; RV32I-NEXT: [[AND8:%[0-9]+]]:_(s32) = G_AND [[ADD1]], [[C13]] ; RV32I-NEXT: [[C14:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND8]], [[C14]] ; RV32I-NEXT: [[C15:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND8]], [[C14]] ; RV32I-NEXT: [[LSHR6:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C15]](s32) ; RV32I-NEXT: [[C16:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 ; RV32I-NEXT: [[SUB1:%[0-9]+]]:_(s32) = G_SUB [[C16]], [[LSHR6]] @@ -468,8 +468,8 @@ body: | ; RV32I-NEXT: [[C15:%[0-9]+]]:_(s32) = G_CONSTANT i32 3855 ; RV32I-NEXT: [[AND9:%[0-9]+]]:_(s32) = G_AND [[ADD1]], [[C15]] ; RV32I-NEXT: [[C16:%[0-9]+]]:_(s32) = G_CONSTANT i32 257 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND9]], [[C16]] ; RV32I-NEXT: [[C17:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND9]], [[C16]] ; RV32I-NEXT: [[C18:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 ; RV32I-NEXT: [[AND10:%[0-9]+]]:_(s32) = G_AND [[MUL]], [[C18]] ; RV32I-NEXT: [[LSHR7:%[0-9]+]]:_(s32) = G_LSHR [[AND10]], [[C17]](s32) @@ -540,8 +540,8 @@ body: | ; RV32I-NEXT: [[C10:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 ; RV32I-NEXT: [[AND3:%[0-9]+]]:_(s32) = G_AND [[ADD1]], [[C10]] ; RV32I-NEXT: [[C11:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND3]], [[C11]] ; RV32I-NEXT: [[C12:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND3]], [[C11]] ; RV32I-NEXT: [[LSHR8:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C12]](s32) ; RV32I-NEXT: [[C13:%[0-9]+]]:_(s32) = G_CONSTANT i32 32 ; RV32I-NEXT: [[SUB1:%[0-9]+]]:_(s32) = G_SUB [[C13]], [[LSHR8]] @@ -606,8 +606,8 @@ body: | ; RV32I-NEXT: [[C11:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 ; RV32I-NEXT: [[AND3:%[0-9]+]]:_(s32) = G_AND [[ADD1]], [[C11]] ; RV32I-NEXT: [[C12:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND3]], [[C12]] ; RV32I-NEXT: [[C13:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND3]], [[C12]] ; RV32I-NEXT: [[LSHR8:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C13]](s32) ; RV32I-NEXT: [[C14:%[0-9]+]]:_(s32) = G_CONSTANT i32 32 ; RV32I-NEXT: [[SUB1:%[0-9]+]]:_(s32) = G_SUB [[C14]], [[LSHR8]] @@ -645,8 +645,8 @@ body: | ; RV32I-NEXT: [[C26:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 ; RV32I-NEXT: [[AND7:%[0-9]+]]:_(s32) = G_AND [[ADD4]], [[C26]] ; RV32I-NEXT: [[C27:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 - ; RV32I-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL [[AND7]], [[C27]] ; RV32I-NEXT: [[C28:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; RV32I-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL [[AND7]], [[C27]] ; RV32I-NEXT: [[LSHR17:%[0-9]+]]:_(s32) = G_LSHR [[MUL1]], [[C28]](s32) ; RV32I-NEXT: [[C29:%[0-9]+]]:_(s32) = G_CONSTANT i32 32 ; RV32I-NEXT: [[SUB3:%[0-9]+]]:_(s32) = G_SUB [[C29]], [[LSHR17]] diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-ctlz-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-ctlz-rv64.mir index add8a565202df4fe7a12032ffc9442fa2020310e..38a4b9c6dae38ac7600ba9c653c0850d01a1f0f5 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-ctlz-rv64.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-ctlz-rv64.mir @@ -283,8 +283,8 @@ body: | ; RV64I-NEXT: [[C11:%[0-9]+]]:_(s64) = G_CONSTANT i64 1085102592571150095 ; RV64I-NEXT: [[AND3:%[0-9]+]]:_(s64) = G_AND [[ADD1]], [[C11]] ; RV64I-NEXT: [[C12:%[0-9]+]]:_(s64) = G_CONSTANT i64 72340172838076673 - ; RV64I-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[AND3]], [[C12]] ; RV64I-NEXT: [[C13:%[0-9]+]]:_(s64) = G_CONSTANT i64 56 + ; RV64I-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[AND3]], [[C12]] ; RV64I-NEXT: [[LSHR9:%[0-9]+]]:_(s64) = G_LSHR [[MUL]], [[C13]](s64) ; RV64I-NEXT: [[C14:%[0-9]+]]:_(s64) = G_CONSTANT i64 64 ; RV64I-NEXT: [[SUB1:%[0-9]+]]:_(s64) = G_SUB [[C14]], [[LSHR9]] @@ -583,8 +583,8 @@ body: | ; RV64I-NEXT: [[C11:%[0-9]+]]:_(s64) = G_CONSTANT i64 1085102592571150095 ; RV64I-NEXT: [[AND3:%[0-9]+]]:_(s64) = G_AND [[ADD1]], [[C11]] ; RV64I-NEXT: [[C12:%[0-9]+]]:_(s64) = G_CONSTANT i64 72340172838076673 - ; RV64I-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[AND3]], [[C12]] ; RV64I-NEXT: [[C13:%[0-9]+]]:_(s64) = G_CONSTANT i64 56 + ; RV64I-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[AND3]], [[C12]] ; RV64I-NEXT: [[LSHR9:%[0-9]+]]:_(s64) = G_LSHR [[MUL]], [[C13]](s64) ; RV64I-NEXT: [[C14:%[0-9]+]]:_(s64) = G_CONSTANT i64 64 ; RV64I-NEXT: [[SUB1:%[0-9]+]]:_(s64) = G_SUB [[C14]], [[LSHR9]] diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-ctpop-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-ctpop-rv32.mir index d4eb5ebc2e29445e24d1b16fba138fdcf2f8aa64..c64669cb7341eb57ea70c0e4c74cb37552dd29df 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-ctpop-rv32.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-ctpop-rv32.mir @@ -35,8 +35,8 @@ body: | ; RV32I-NEXT: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 15 ; RV32I-NEXT: [[AND5:%[0-9]+]]:_(s32) = G_AND [[ADD1]], [[C7]] ; RV32I-NEXT: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND5]], [[C8]] ; RV32I-NEXT: [[C9:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND5]], [[C8]] ; RV32I-NEXT: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C9]](s32) ; RV32I-NEXT: $x10 = COPY [[LSHR3]](s32) ; RV32I-NEXT: PseudoRET implicit $x10 @@ -90,8 +90,8 @@ body: | ; RV32I-NEXT: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 3855 ; RV32I-NEXT: [[AND5:%[0-9]+]]:_(s32) = G_AND [[ADD1]], [[C7]] ; RV32I-NEXT: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 257 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND5]], [[C8]] ; RV32I-NEXT: [[C9:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND5]], [[C8]] ; RV32I-NEXT: [[C10:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 ; RV32I-NEXT: [[AND6:%[0-9]+]]:_(s32) = G_AND [[MUL]], [[C10]] ; RV32I-NEXT: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[AND6]], [[C9]](s32) @@ -143,8 +143,8 @@ body: | ; RV32I-NEXT: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 ; RV32I-NEXT: [[AND3:%[0-9]+]]:_(s32) = G_AND [[ADD1]], [[C5]] ; RV32I-NEXT: [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND3]], [[C6]] ; RV32I-NEXT: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND3]], [[C6]] ; RV32I-NEXT: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C7]](s32) ; RV32I-NEXT: $x10 = COPY [[LSHR3]](s32) ; RV32I-NEXT: PseudoRET implicit $x10 @@ -190,8 +190,8 @@ body: | ; RV32I-NEXT: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 ; RV32I-NEXT: [[AND3:%[0-9]+]]:_(s32) = G_AND [[ADD1]], [[C5]] ; RV32I-NEXT: [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND3]], [[C6]] ; RV32I-NEXT: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND3]], [[C6]] ; RV32I-NEXT: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C7]](s32) ; RV32I-NEXT: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 ; RV32I-NEXT: [[LSHR4:%[0-9]+]]:_(s32) = G_LSHR [[COPY1]], [[C8]](s32) @@ -210,8 +210,8 @@ body: | ; RV32I-NEXT: [[C13:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 ; RV32I-NEXT: [[AND7:%[0-9]+]]:_(s32) = G_AND [[ADD3]], [[C13]] ; RV32I-NEXT: [[C14:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 - ; RV32I-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL [[AND7]], [[C14]] ; RV32I-NEXT: [[C15:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; RV32I-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL [[AND7]], [[C14]] ; RV32I-NEXT: [[LSHR7:%[0-9]+]]:_(s32) = G_LSHR [[MUL1]], [[C15]](s32) ; RV32I-NEXT: [[ADD4:%[0-9]+]]:_(s32) = G_ADD [[LSHR7]], [[LSHR3]] ; RV32I-NEXT: [[C16:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-ctpop-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-ctpop-rv64.mir index e2434ba9301c04565d7427509bb4281a2fafe631..196b367e59271fa2fbe148bb6660f28f3ed078c2 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-ctpop-rv64.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-ctpop-rv64.mir @@ -205,8 +205,8 @@ body: | ; RV64I-NEXT: [[C5:%[0-9]+]]:_(s64) = G_CONSTANT i64 1085102592571150095 ; RV64I-NEXT: [[AND3:%[0-9]+]]:_(s64) = G_AND [[ADD1]], [[C5]] ; RV64I-NEXT: [[C6:%[0-9]+]]:_(s64) = G_CONSTANT i64 72340172838076673 - ; RV64I-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[AND3]], [[C6]] ; RV64I-NEXT: [[C7:%[0-9]+]]:_(s64) = G_CONSTANT i64 56 + ; RV64I-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[AND3]], [[C6]] ; RV64I-NEXT: [[LSHR3:%[0-9]+]]:_(s64) = G_LSHR [[MUL]], [[C7]](s64) ; RV64I-NEXT: $x10 = COPY [[LSHR3]](s64) ; RV64I-NEXT: PseudoRET implicit $x10 diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-cttz-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-cttz-rv32.mir index 19555a702b73ce82a67873a102f8c441af4106f2..372becaf08d9486b0998c24ae9d8281c63883460 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-cttz-rv32.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-cttz-rv32.mir @@ -39,8 +39,8 @@ body: | ; RV32I-NEXT: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 15 ; RV32I-NEXT: [[AND6:%[0-9]+]]:_(s32) = G_AND [[ADD2]], [[C8]] ; RV32I-NEXT: [[C9:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND6]], [[C9]] ; RV32I-NEXT: [[C10:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND6]], [[C9]] ; RV32I-NEXT: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C10]](s32) ; RV32I-NEXT: $x10 = COPY [[LSHR3]](s32) ; RV32I-NEXT: PseudoRET implicit $x10 @@ -98,8 +98,8 @@ body: | ; RV32I-NEXT: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 3855 ; RV32I-NEXT: [[AND6:%[0-9]+]]:_(s32) = G_AND [[ADD2]], [[C8]] ; RV32I-NEXT: [[C9:%[0-9]+]]:_(s32) = G_CONSTANT i32 257 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND6]], [[C9]] ; RV32I-NEXT: [[C10:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND6]], [[C9]] ; RV32I-NEXT: [[C11:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 ; RV32I-NEXT: [[AND7:%[0-9]+]]:_(s32) = G_AND [[MUL]], [[C11]] ; RV32I-NEXT: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[AND7]], [[C10]](s32) @@ -155,8 +155,8 @@ body: | ; RV32I-NEXT: [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 ; RV32I-NEXT: [[AND4:%[0-9]+]]:_(s32) = G_AND [[ADD2]], [[C6]] ; RV32I-NEXT: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND4]], [[C7]] ; RV32I-NEXT: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND4]], [[C7]] ; RV32I-NEXT: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C8]](s32) ; RV32I-NEXT: $x10 = COPY [[LSHR3]](s32) ; RV32I-NEXT: PseudoRET implicit $x10 @@ -208,8 +208,8 @@ body: | ; RV32I-NEXT: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 ; RV32I-NEXT: [[AND4:%[0-9]+]]:_(s32) = G_AND [[ADD2]], [[C7]] ; RV32I-NEXT: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND4]], [[C8]] ; RV32I-NEXT: [[C9:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND4]], [[C8]] ; RV32I-NEXT: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C9]](s32) ; RV32I-NEXT: [[C10:%[0-9]+]]:_(s32) = G_CONSTANT i32 32 ; RV32I-NEXT: [[ADD3:%[0-9]+]]:_(s32) = G_ADD [[LSHR3]], [[C10]] @@ -234,8 +234,8 @@ body: | ; RV32I-NEXT: [[C17:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 ; RV32I-NEXT: [[AND9:%[0-9]+]]:_(s32) = G_AND [[ADD6]], [[C17]] ; RV32I-NEXT: [[C18:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 - ; RV32I-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL [[AND9]], [[C18]] ; RV32I-NEXT: [[C19:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; RV32I-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL [[AND9]], [[C18]] ; RV32I-NEXT: [[LSHR7:%[0-9]+]]:_(s32) = G_LSHR [[MUL1]], [[C19]](s32) ; RV32I-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP]](s32), [[ADD3]], [[LSHR7]] ; RV32I-NEXT: [[C20:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 @@ -304,8 +304,8 @@ body: | ; RV32I-NEXT: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 15 ; RV32I-NEXT: [[AND6:%[0-9]+]]:_(s32) = G_AND [[ADD2]], [[C8]] ; RV32I-NEXT: [[C9:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND6]], [[C9]] ; RV32I-NEXT: [[C10:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND6]], [[C9]] ; RV32I-NEXT: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C10]](s32) ; RV32I-NEXT: $x10 = COPY [[LSHR3]](s32) ; RV32I-NEXT: PseudoRET implicit $x10 @@ -363,8 +363,8 @@ body: | ; RV32I-NEXT: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 3855 ; RV32I-NEXT: [[AND6:%[0-9]+]]:_(s32) = G_AND [[ADD2]], [[C8]] ; RV32I-NEXT: [[C9:%[0-9]+]]:_(s32) = G_CONSTANT i32 257 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND6]], [[C9]] ; RV32I-NEXT: [[C10:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND6]], [[C9]] ; RV32I-NEXT: [[C11:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535 ; RV32I-NEXT: [[AND7:%[0-9]+]]:_(s32) = G_AND [[MUL]], [[C11]] ; RV32I-NEXT: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[AND7]], [[C10]](s32) @@ -420,8 +420,8 @@ body: | ; RV32I-NEXT: [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 ; RV32I-NEXT: [[AND4:%[0-9]+]]:_(s32) = G_AND [[ADD2]], [[C6]] ; RV32I-NEXT: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND4]], [[C7]] ; RV32I-NEXT: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND4]], [[C7]] ; RV32I-NEXT: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C8]](s32) ; RV32I-NEXT: $x10 = COPY [[LSHR3]](s32) ; RV32I-NEXT: PseudoRET implicit $x10 @@ -473,8 +473,8 @@ body: | ; RV32I-NEXT: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 ; RV32I-NEXT: [[AND4:%[0-9]+]]:_(s32) = G_AND [[ADD2]], [[C7]] ; RV32I-NEXT: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 - ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND4]], [[C8]] ; RV32I-NEXT: [[C9:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; RV32I-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[AND4]], [[C8]] ; RV32I-NEXT: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C9]](s32) ; RV32I-NEXT: [[C10:%[0-9]+]]:_(s32) = G_CONSTANT i32 32 ; RV32I-NEXT: [[ADD3:%[0-9]+]]:_(s32) = G_ADD [[LSHR3]], [[C10]] @@ -499,8 +499,8 @@ body: | ; RV32I-NEXT: [[C17:%[0-9]+]]:_(s32) = G_CONSTANT i32 252645135 ; RV32I-NEXT: [[AND9:%[0-9]+]]:_(s32) = G_AND [[ADD6]], [[C17]] ; RV32I-NEXT: [[C18:%[0-9]+]]:_(s32) = G_CONSTANT i32 16843009 - ; RV32I-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL [[AND9]], [[C18]] ; RV32I-NEXT: [[C19:%[0-9]+]]:_(s32) = G_CONSTANT i32 24 + ; RV32I-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL [[AND9]], [[C18]] ; RV32I-NEXT: [[LSHR7:%[0-9]+]]:_(s32) = G_LSHR [[MUL1]], [[C19]](s32) ; RV32I-NEXT: [[SELECT:%[0-9]+]]:_(s32) = G_SELECT [[ICMP]](s32), [[ADD3]], [[LSHR7]] ; RV32I-NEXT: [[C20:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-cttz-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-cttz-rv64.mir index e030e3ce2a80398f6f08e2f480ba0ae6829fc729..e51a2143efd02a418fbc028db9125ff06fe9aaba 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-cttz-rv64.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-cttz-rv64.mir @@ -221,8 +221,8 @@ body: | ; RV64I-NEXT: [[C6:%[0-9]+]]:_(s64) = G_CONSTANT i64 1085102592571150095 ; RV64I-NEXT: [[AND4:%[0-9]+]]:_(s64) = G_AND [[ADD2]], [[C6]] ; RV64I-NEXT: [[C7:%[0-9]+]]:_(s64) = G_CONSTANT i64 72340172838076673 - ; RV64I-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[AND4]], [[C7]] ; RV64I-NEXT: [[C8:%[0-9]+]]:_(s64) = G_CONSTANT i64 56 + ; RV64I-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[AND4]], [[C7]] ; RV64I-NEXT: [[LSHR3:%[0-9]+]]:_(s64) = G_LSHR [[MUL]], [[C8]](s64) ; RV64I-NEXT: $x10 = COPY [[LSHR3]](s64) ; RV64I-NEXT: PseudoRET implicit $x10 @@ -457,8 +457,8 @@ body: | ; RV64I-NEXT: [[C6:%[0-9]+]]:_(s64) = G_CONSTANT i64 1085102592571150095 ; RV64I-NEXT: [[AND4:%[0-9]+]]:_(s64) = G_AND [[ADD2]], [[C6]] ; RV64I-NEXT: [[C7:%[0-9]+]]:_(s64) = G_CONSTANT i64 72340172838076673 - ; RV64I-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[AND4]], [[C7]] ; RV64I-NEXT: [[C8:%[0-9]+]]:_(s64) = G_CONSTANT i64 56 + ; RV64I-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[AND4]], [[C7]] ; RV64I-NEXT: [[LSHR3:%[0-9]+]]:_(s64) = G_LSHR [[MUL]], [[C8]](s64) ; RV64I-NEXT: $x10 = COPY [[LSHR3]](s64) ; RV64I-NEXT: PseudoRET implicit $x10 diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-mul-ext-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-mul-ext-rv32.mir index 433d6e6b821f327f87df7629b39fac781663c0ce..ec2dc568a5ec379fae33c9cd4c9fde7e088ef6d8 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-mul-ext-rv32.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-mul-ext-rv32.mir @@ -162,8 +162,10 @@ body: | ; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(s32) = G_UMULH %lo1, %lo2 ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[MUL1]], [[MUL2]] ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), [[MUL2]] - ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ADD]], [[UMULH]] + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY [[ADD]](s32) + ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[UMULH]] ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD1]](s32), [[UMULH]] + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY [[ADD1]](s32) ; CHECK-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ICMP]], [[ICMP1]] ; CHECK-NEXT: [[MUL3:%[0-9]+]]:_(s32) = G_MUL %hi1, %lo2 ; CHECK-NEXT: [[MUL4:%[0-9]+]]:_(s32) = G_MUL %mid1, %mid2 @@ -171,13 +173,18 @@ body: | ; CHECK-NEXT: [[UMULH1:%[0-9]+]]:_(s32) = G_UMULH %mid1, %lo2 ; CHECK-NEXT: [[UMULH2:%[0-9]+]]:_(s32) = G_UMULH %lo1, %mid2 ; CHECK-NEXT: [[ADD3:%[0-9]+]]:_(s32) = G_ADD [[MUL3]], [[MUL4]] - ; CHECK-NEXT: [[ADD4:%[0-9]+]]:_(s32) = G_ADD [[ADD3]], [[MUL5]] - ; CHECK-NEXT: [[ADD5:%[0-9]+]]:_(s32) = G_ADD [[ADD4]], [[UMULH1]] - ; CHECK-NEXT: [[ADD6:%[0-9]+]]:_(s32) = G_ADD [[ADD5]], [[UMULH2]] - ; CHECK-NEXT: [[ADD7:%[0-9]+]]:_(s32) = G_ADD [[ADD6]], [[ADD2]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY [[ADD3]](s32) + ; CHECK-NEXT: [[ADD4:%[0-9]+]]:_(s32) = G_ADD [[COPY2]], [[MUL5]] + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY [[ADD4]](s32) + ; CHECK-NEXT: [[ADD5:%[0-9]+]]:_(s32) = G_ADD [[COPY3]], [[UMULH1]] + ; CHECK-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY [[ADD5]](s32) + ; CHECK-NEXT: [[ADD6:%[0-9]+]]:_(s32) = G_ADD [[COPY4]], [[UMULH2]] + ; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY [[ADD6]](s32) + ; CHECK-NEXT: [[ADD7:%[0-9]+]]:_(s32) = G_ADD [[COPY5]], [[ADD2]] + ; CHECK-NEXT: [[COPY6:%[0-9]+]]:_(s32) = COPY [[ADD7]](s32) ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) - ; CHECK-NEXT: $x11 = COPY [[ADD1]](s32) - ; CHECK-NEXT: $x12 = COPY [[ADD7]](s32) + ; CHECK-NEXT: $x11 = COPY [[COPY1]](s32) + ; CHECK-NEXT: $x12 = COPY [[COPY6]](s32) ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11, implicit $x12 %lo1:_(s32) = COPY $x10 %mid1:_(s32) = COPY $x11 diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-mul-ext-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-mul-ext-rv64.mir index 09e002e8428d79b7093779f72e37a19c8e86ca19..39d9c5b7dfd1e2447cbb6470dfce79fcf824d93c 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-mul-ext-rv64.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-mul-ext-rv64.mir @@ -194,8 +194,10 @@ body: | ; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(s64) = G_UMULH %lo1, %lo2 ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[MUL1]], [[MUL2]] ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s64) = G_ICMP intpred(ult), [[ADD]](s64), [[MUL2]] - ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s64) = G_ADD [[ADD]], [[UMULH]] + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY [[ADD]](s64) + ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s64) = G_ADD [[COPY]], [[UMULH]] ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s64) = G_ICMP intpred(ult), [[ADD1]](s64), [[UMULH]] + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY [[ADD1]](s64) ; CHECK-NEXT: [[ADD2:%[0-9]+]]:_(s64) = G_ADD [[ICMP]], [[ICMP1]] ; CHECK-NEXT: [[MUL3:%[0-9]+]]:_(s64) = G_MUL %hi1, %lo2 ; CHECK-NEXT: [[MUL4:%[0-9]+]]:_(s64) = G_MUL %mid1, %mid2 @@ -203,13 +205,18 @@ body: | ; CHECK-NEXT: [[UMULH1:%[0-9]+]]:_(s64) = G_UMULH %mid1, %lo2 ; CHECK-NEXT: [[UMULH2:%[0-9]+]]:_(s64) = G_UMULH %lo1, %mid2 ; CHECK-NEXT: [[ADD3:%[0-9]+]]:_(s64) = G_ADD [[MUL3]], [[MUL4]] - ; CHECK-NEXT: [[ADD4:%[0-9]+]]:_(s64) = G_ADD [[ADD3]], [[MUL5]] - ; CHECK-NEXT: [[ADD5:%[0-9]+]]:_(s64) = G_ADD [[ADD4]], [[UMULH1]] - ; CHECK-NEXT: [[ADD6:%[0-9]+]]:_(s64) = G_ADD [[ADD5]], [[UMULH2]] - ; CHECK-NEXT: [[ADD7:%[0-9]+]]:_(s64) = G_ADD [[ADD6]], [[ADD2]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s64) = COPY [[ADD3]](s64) + ; CHECK-NEXT: [[ADD4:%[0-9]+]]:_(s64) = G_ADD [[COPY2]], [[MUL5]] + ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s64) = COPY [[ADD4]](s64) + ; CHECK-NEXT: [[ADD5:%[0-9]+]]:_(s64) = G_ADD [[COPY3]], [[UMULH1]] + ; CHECK-NEXT: [[COPY4:%[0-9]+]]:_(s64) = COPY [[ADD5]](s64) + ; CHECK-NEXT: [[ADD6:%[0-9]+]]:_(s64) = G_ADD [[COPY4]], [[UMULH2]] + ; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(s64) = COPY [[ADD6]](s64) + ; CHECK-NEXT: [[ADD7:%[0-9]+]]:_(s64) = G_ADD [[COPY5]], [[ADD2]] + ; CHECK-NEXT: [[COPY6:%[0-9]+]]:_(s64) = COPY [[ADD7]](s64) ; CHECK-NEXT: $x10 = COPY [[MUL]](s64) - ; CHECK-NEXT: $x11 = COPY [[ADD1]](s64) - ; CHECK-NEXT: $x12 = COPY [[ADD7]](s64) + ; CHECK-NEXT: $x11 = COPY [[COPY1]](s64) + ; CHECK-NEXT: $x12 = COPY [[COPY6]](s64) ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11, implicit $x12 %lo1:_(s64) = COPY $x10 %mid1:_(s64) = COPY $x11 diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-vacopy.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-vacopy.mir index f9eda1252937e87a428c128e0a00cae9d112c774..16542f58001212f80b1f2c8b8af7024e9a5c5f2b 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-vacopy.mir +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-vacopy.mir @@ -14,7 +14,7 @@ body: | ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(p0) = COPY $x11 ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[COPY1]](p0) :: (load (p0)) - ; CHECK-NEXT: G_STORE [[COPY]](p0), [[LOAD]](p0) :: (store (p0)) + ; CHECK-NEXT: G_STORE [[LOAD]](p0), [[COPY]](p0) :: (store (p0)) ; CHECK-NEXT: PseudoRET %0:_(p0) = COPY $x10 %1:_(p0) = COPY $x11 diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-bitcast.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-bitcast.mir new file mode 100644 index 0000000000000000000000000000000000000000..7b5d56864a340db126267676e0c375a914eec434 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-bitcast.mir @@ -0,0 +1,356 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=riscv32 -mattr=+v -run-pass=legalizer %s -o - | FileCheck %s +# RUN: llc -mtriple=riscv64 -mattr=+v -run-pass=legalizer %s -o - | FileCheck %s + +--- +name: bitcast_nxv1i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv1i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 1 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 8 x s1>) = G_BITCAST [[DEF]](<vscale x 1 x s8>) + ; CHECK-NEXT: $v8 = COPY [[BITCAST]](<vscale x 8 x s1>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 1 x s8>) = G_IMPLICIT_DEF + %1:_(<vscale x 8 x s1>) = G_BITCAST %0(<vscale x 1 x s8>) + $v8 = COPY %1(<vscale x 8 x s1>) + PseudoRET implicit $v8 +... +--- +name: bitcast_nxv2i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv2i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 2 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 1 x s16>) = G_BITCAST [[DEF]](<vscale x 2 x s8>) + ; CHECK-NEXT: $v8 = COPY [[BITCAST]](<vscale x 1 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 2 x s8>) = G_IMPLICIT_DEF + %1:_(<vscale x 1 x s16>) = G_BITCAST %0(<vscale x 2 x s8>) + $v8 = COPY %1(<vscale x 1 x s16>) + PseudoRET implicit $v8 +... +--- +name: bitcast_nxv4i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv4i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 4 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x s16>) = G_BITCAST [[DEF]](<vscale x 4 x s8>) + ; CHECK-NEXT: $v8 = COPY [[BITCAST]](<vscale x 2 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 4 x s8>) = G_IMPLICIT_DEF + %1:_(<vscale x 2 x s16>) = G_BITCAST %0(<vscale x 4 x s8>) + $v8 = COPY %1(<vscale x 2 x s16>) + PseudoRET implicit $v8 +... +--- +name: bitcast_nxv8i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv8i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 8 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 64 x s1>) = G_BITCAST [[DEF]](<vscale x 8 x s8>) + ; CHECK-NEXT: $v8 = COPY [[BITCAST]](<vscale x 64 x s1>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 8 x s8>) = G_IMPLICIT_DEF + %1:_(<vscale x 64 x s1>) = G_BITCAST %0(<vscale x 8 x s8>) + $v8 = COPY %1(<vscale x 64 x s1>) + PseudoRET implicit $v8 +... +--- +name: bitcast_nxv16i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv16i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 16 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 4 x s32>) = G_BITCAST [[DEF]](<vscale x 16 x s8>) + ; CHECK-NEXT: $v8m2 = COPY [[BITCAST]](<vscale x 4 x s32>) + ; CHECK-NEXT: PseudoRET implicit $v8m2 + %0:_(<vscale x 16 x s8>) = G_IMPLICIT_DEF + %1:_(<vscale x 4 x s32>) = G_BITCAST %0(<vscale x 16 x s8>) + $v8m2 = COPY %1(<vscale x 4 x s32>) + PseudoRET implicit $v8m2 +... +--- +name: bitcast_nxv32i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv32i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 32 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 16 x s16>) = G_BITCAST [[DEF]](<vscale x 32 x s8>) + ; CHECK-NEXT: $v8m4 = COPY [[BITCAST]](<vscale x 16 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8m4 + %0:_(<vscale x 32 x s8>) = G_IMPLICIT_DEF + %1:_(<vscale x 16 x s16>) = G_BITCAST %0(<vscale x 32 x s8>) + $v8m4 = COPY %1(<vscale x 16 x s16>) + PseudoRET implicit $v8m4 +... +--- +name: bitcast_nxv64i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv64i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 64 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 8 x s64>) = G_BITCAST [[DEF]](<vscale x 64 x s8>) + ; CHECK-NEXT: $v8m8 = COPY [[BITCAST]](<vscale x 8 x s64>) + ; CHECK-NEXT: PseudoRET implicit $v8m8 + %0:_(<vscale x 64 x s8>) = G_IMPLICIT_DEF + %1:_(<vscale x 8 x s64>) = G_BITCAST %0(<vscale x 64 x s8>) + $v8m8 = COPY %1(<vscale x 8 x s64>) + PseudoRET implicit $v8m8 +... +--- +name: bitcast_nxv1i16 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv1i16 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 1 x s16>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x s8>) = G_BITCAST [[DEF]](<vscale x 1 x s16>) + ; CHECK-NEXT: $v8 = COPY [[BITCAST]](<vscale x 2 x s8>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 1 x s16>) = G_IMPLICIT_DEF + %1:_(<vscale x 2 x s8>) = G_BITCAST %0(<vscale x 1 x s16>) + $v8 = COPY %1(<vscale x 2 x s8>) + PseudoRET implicit $v8 +... +--- +name: bitcast_nxv2i16 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv2i16 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 2 x s16>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 1 x s32>) = G_BITCAST [[DEF]](<vscale x 2 x s16>) + ; CHECK-NEXT: $v8 = COPY [[BITCAST]](<vscale x 1 x s32>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 2 x s16>) = G_IMPLICIT_DEF + %1:_(<vscale x 1 x s32>) = G_BITCAST %0(<vscale x 2 x s16>) + $v8 = COPY %1(<vscale x 1 x s32>) + PseudoRET implicit $v8 +... +--- +name: bitcast_nxv4i16 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv4i16 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 4 x s16>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 1 x s64>) = G_BITCAST [[DEF]](<vscale x 4 x s16>) + ; CHECK-NEXT: $v8 = COPY [[BITCAST]](<vscale x 1 x s64>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 4 x s16>) = G_IMPLICIT_DEF + %1:_(<vscale x 1 x s64>) = G_BITCAST %0(<vscale x 4 x s16>) + $v8 = COPY %1(<vscale x 1 x s64>) + PseudoRET implicit $v8 +... +--- +name: bitcast_nxv8i16 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv8i16 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 8 x s16>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x s64>) = G_BITCAST [[DEF]](<vscale x 8 x s16>) + ; CHECK-NEXT: $v8m2 = COPY [[BITCAST]](<vscale x 2 x s64>) + ; CHECK-NEXT: PseudoRET implicit $v8m2 + %0:_(<vscale x 8 x s16>) = G_IMPLICIT_DEF + %1:_(<vscale x 2 x s64>) = G_BITCAST %0(<vscale x 8 x s16>) + $v8m2 = COPY %1(<vscale x 2 x s64>) + PseudoRET implicit $v8m2 +... +--- +name: bitcast_nxv16i16 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv16i16 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 16 x s16>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 8 x s32>) = G_BITCAST [[DEF]](<vscale x 16 x s16>) + ; CHECK-NEXT: $v8m4 = COPY [[BITCAST]](<vscale x 8 x s32>) + ; CHECK-NEXT: PseudoRET implicit $v8m4 + %0:_(<vscale x 16 x s16>) = G_IMPLICIT_DEF + %1:_(<vscale x 8 x s32>) = G_BITCAST %0(<vscale x 16 x s16>) + $v8m4 = COPY %1(<vscale x 8 x s32>) + PseudoRET implicit $v8m4 +... +--- +name: bitcast_nxv32i16 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv32i16 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 32 x s16>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 8 x s64>) = G_BITCAST [[DEF]](<vscale x 32 x s16>) + ; CHECK-NEXT: $v8m8 = COPY [[BITCAST]](<vscale x 8 x s64>) + ; CHECK-NEXT: PseudoRET implicit $v8m8 + %0:_(<vscale x 32 x s16>) = G_IMPLICIT_DEF + %1:_(<vscale x 8 x s64>) = G_BITCAST %0(<vscale x 32 x s16>) + $v8m8 = COPY %1(<vscale x 8 x s64>) + PseudoRET implicit $v8m8 +... +--- +name: bitcast_nxv1i32 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv1i32 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 1 x s32>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x s16>) = G_BITCAST [[DEF]](<vscale x 1 x s32>) + ; CHECK-NEXT: $v8 = COPY [[BITCAST]](<vscale x 2 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 1 x s32>) = G_IMPLICIT_DEF + %1:_(<vscale x 2 x s16>) = G_BITCAST %0(<vscale x 1 x s32>) + $v8 = COPY %1(<vscale x 2 x s16>) + PseudoRET implicit $v8 +... +--- +name: bitcast_nxv2i32 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv2i32 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 2 x s32>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 4 x s16>) = G_BITCAST [[DEF]](<vscale x 2 x s32>) + ; CHECK-NEXT: $v8 = COPY [[BITCAST]](<vscale x 4 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 2 x s32>) = G_IMPLICIT_DEF + %1:_(<vscale x 4 x s16>) = G_BITCAST %0(<vscale x 2 x s32>) + $v8 = COPY %1(<vscale x 4 x s16>) + PseudoRET implicit $v8 +... +--- +name: bitcast_nxv4i32 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv4i32 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 4 x s32>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 8 x s16>) = G_BITCAST [[DEF]](<vscale x 4 x s32>) + ; CHECK-NEXT: $v8m2 = COPY [[BITCAST]](<vscale x 8 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8m2 + %0:_(<vscale x 4 x s32>) = G_IMPLICIT_DEF + %1:_(<vscale x 8 x s16>) = G_BITCAST %0(<vscale x 4 x s32>) + $v8m2 = COPY %1(<vscale x 8 x s16>) + PseudoRET implicit $v8m2 +... +--- +name: bitcast_nxv8i32 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv8i32 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 8 x s32>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 4 x s64>) = G_BITCAST [[DEF]](<vscale x 8 x s32>) + ; CHECK-NEXT: $v8m4 = COPY [[BITCAST]](<vscale x 4 x s64>) + ; CHECK-NEXT: PseudoRET implicit $v8m4 + %0:_(<vscale x 8 x s32>) = G_IMPLICIT_DEF + %1:_(<vscale x 4 x s64>) = G_BITCAST %0(<vscale x 8 x s32>) + $v8m4 = COPY %1(<vscale x 4 x s64>) + PseudoRET implicit $v8m4 +... +--- +name: bitcast_nxv16i32 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv16i32 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 16 x s32>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 32 x s16>) = G_BITCAST [[DEF]](<vscale x 16 x s32>) + ; CHECK-NEXT: $v8m8 = COPY [[BITCAST]](<vscale x 32 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8m8 + %0:_(<vscale x 16 x s32>) = G_IMPLICIT_DEF + %1:_(<vscale x 32 x s16>) = G_BITCAST %0(<vscale x 16 x s32>) + $v8m8 = COPY %1(<vscale x 32 x s16>) + PseudoRET implicit $v8m8 +... +--- +name: bitcast_nxv1i64 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv1i64 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 1 x s64>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 2 x s32>) = G_BITCAST [[DEF]](<vscale x 1 x s64>) + ; CHECK-NEXT: $v8 = COPY [[BITCAST]](<vscale x 2 x s32>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 1 x s64>) = G_IMPLICIT_DEF + %1:_(<vscale x 2 x s32>) = G_BITCAST %0(<vscale x 1 x s64>) + $v8 = COPY %1(<vscale x 2 x s32>) + PseudoRET implicit $v8 +... +--- +name: bitcast_nxv2i64 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv2i64 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 2 x s64>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 4 x s32>) = G_BITCAST [[DEF]](<vscale x 2 x s64>) + ; CHECK-NEXT: $v8m2 = COPY [[BITCAST]](<vscale x 4 x s32>) + ; CHECK-NEXT: PseudoRET implicit $v8m2 + %0:_(<vscale x 2 x s64>) = G_IMPLICIT_DEF + %1:_(<vscale x 4 x s32>) = G_BITCAST %0(<vscale x 2 x s64>) + $v8m2 = COPY %1(<vscale x 4 x s32>) + PseudoRET implicit $v8m2 +... +--- +name: bitcast_nxv4i64 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv4i64 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 4 x s64>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 16 x s16>) = G_BITCAST [[DEF]](<vscale x 4 x s64>) + ; CHECK-NEXT: $v8m4 = COPY [[BITCAST]](<vscale x 16 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8m4 + %0:_(<vscale x 4 x s64>) = G_IMPLICIT_DEF + %1:_(<vscale x 16 x s16>) = G_BITCAST %0(<vscale x 4 x s64>) + $v8m4 = COPY %1(<vscale x 16 x s16>) + PseudoRET implicit $v8m4 +... +--- +name: bitcast_nxv8i64 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: bitcast_nxv8i64 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 8 x s64>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[BITCAST:%[0-9]+]]:_(<vscale x 64 x s8>) = G_BITCAST [[DEF]](<vscale x 8 x s64>) + ; CHECK-NEXT: $v8m8 = COPY [[BITCAST]](<vscale x 64 x s8>) + ; CHECK-NEXT: PseudoRET implicit $v8m8 + %0:_(<vscale x 8 x s64>) = G_IMPLICIT_DEF + %1:_(<vscale x 64 x s8>) = G_BITCAST %0(<vscale x 8 x s64>) + $v8m8 = COPY %1(<vscale x 64 x s8>) + PseudoRET implicit $v8m8 +... diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-implicit-def.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-implicit-def.mir new file mode 100644 index 0000000000000000000000000000000000000000..8ee40861ce028e61e240cddadb23cb496a07d887 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-implicit-def.mir @@ -0,0 +1,410 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=riscv32 -mattr=+v -run-pass=legalizer %s -o - | FileCheck %s +# RUN: llc -mtriple=riscv64 -mattr=+v -run-pass=legalizer %s -o - | FileCheck %s + +--- +name: implicitdef_nxv1i1 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv1i1 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 1 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8 = COPY [[DEF]](<vscale x 1 x s1>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 1 x s1>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 1 x s1>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv2i1 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv2i1 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 2 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8 = COPY [[DEF]](<vscale x 2 x s1>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 2 x s1>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 2 x s1>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv4i1 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv4i1 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 4 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8 = COPY [[DEF]](<vscale x 4 x s1>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 4 x s1>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 4 x s1>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv8i1 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv8i1 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 8 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8 = COPY [[DEF]](<vscale x 8 x s1>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 8 x s1>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 8 x s1>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv16i1 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv16i1 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 16 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8 = COPY [[DEF]](<vscale x 16 x s1>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 16 x s1>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 16 x s1>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv32i1 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv32i1 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 32 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8 = COPY [[DEF]](<vscale x 32 x s1>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 32 x s1>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 32 x s1>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv64i1 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv64i1 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 64 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8 = COPY [[DEF]](<vscale x 64 x s1>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 64 x s1>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 64 x s1>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv1i8 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv1i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 1 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8 = COPY [[DEF]](<vscale x 1 x s8>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 1 x s8>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 1 x s8>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv2i8 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv2i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 2 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8 = COPY [[DEF]](<vscale x 2 x s8>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 2 x s8>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 2 x s8>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv4i8 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv4i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 4 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8 = COPY [[DEF]](<vscale x 4 x s8>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 4 x s8>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 4 x s8>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv8i8 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv8i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 8 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8 = COPY [[DEF]](<vscale x 8 x s8>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 8 x s8>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 8 x s8>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv16i8 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv16i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 16 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8m2 = COPY [[DEF]](<vscale x 16 x s8>) + ; CHECK-NEXT: PseudoRET implicit $v8m2 + %0:_(<vscale x 16 x s8>) = G_IMPLICIT_DEF + $v8m2 = COPY %0(<vscale x 16 x s8>) + PseudoRET implicit $v8m2 +... +--- +name: implicitdef_nxv32i8 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv32i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 32 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8m4 = COPY [[DEF]](<vscale x 32 x s8>) + ; CHECK-NEXT: PseudoRET implicit $v8m4 + %0:_(<vscale x 32 x s8>) = G_IMPLICIT_DEF + $v8m4 = COPY %0(<vscale x 32 x s8>) + PseudoRET implicit $v8m4 +... +--- +name: implicitdef_nxv64i8 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv64i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 64 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8m8 = COPY [[DEF]](<vscale x 64 x s8>) + ; CHECK-NEXT: PseudoRET implicit $v8m8 + %0:_(<vscale x 64 x s8>) = G_IMPLICIT_DEF + $v8m8 = COPY %0(<vscale x 64 x s8>) + PseudoRET implicit $v8m8 +... +--- +name: implicitdef_nxv1i16 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv1i16 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 1 x s16>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8 = COPY [[DEF]](<vscale x 1 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 1 x s16>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 1 x s16>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv2i16 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv2i16 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 2 x s16>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8 = COPY [[DEF]](<vscale x 2 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 2 x s16>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 2 x s16>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv4i16 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv4i16 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 4 x s16>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8 = COPY [[DEF]](<vscale x 4 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 4 x s16>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 4 x s16>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv8i16 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv8i16 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 8 x s16>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8m2 = COPY [[DEF]](<vscale x 8 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8m2 + %0:_(<vscale x 8 x s16>) = G_IMPLICIT_DEF + $v8m2 = COPY %0(<vscale x 8 x s16>) + PseudoRET implicit $v8m2 +... +--- +name: implicitdef_nxv16i16 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv16i16 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 16 x s16>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8m4 = COPY [[DEF]](<vscale x 16 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8m4 + %0:_(<vscale x 16 x s16>) = G_IMPLICIT_DEF + $v8m4 = COPY %0(<vscale x 16 x s16>) + PseudoRET implicit $v8m4 +... +--- +name: implicitdef_nxv32i16 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv32i16 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 32 x s16>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8m8 = COPY [[DEF]](<vscale x 32 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8m8 + %0:_(<vscale x 32 x s16>) = G_IMPLICIT_DEF + $v8m8 = COPY %0(<vscale x 32 x s16>) + PseudoRET implicit $v8m8 +... +--- +name: implicitdef_nxv1i32 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv1i32 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 1 x s32>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8 = COPY [[DEF]](<vscale x 1 x s32>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 1 x s32>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 1 x s32>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv2i32 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv2i32 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 2 x s32>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8 = COPY [[DEF]](<vscale x 2 x s32>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 2 x s32>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 2 x s32>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv4i32 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv4i32 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 4 x s32>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8m2 = COPY [[DEF]](<vscale x 4 x s32>) + ; CHECK-NEXT: PseudoRET implicit $v8m2 + %0:_(<vscale x 4 x s32>) = G_IMPLICIT_DEF + $v8m2 = COPY %0(<vscale x 4 x s32>) + PseudoRET implicit $v8m2 +... +--- +name: implicitdef_nxv8i32 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv8i32 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 8 x s32>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8m4 = COPY [[DEF]](<vscale x 8 x s32>) + ; CHECK-NEXT: PseudoRET implicit $v8m4 + %0:_(<vscale x 8 x s32>) = G_IMPLICIT_DEF + $v8m4 = COPY %0(<vscale x 8 x s32>) + PseudoRET implicit $v8m4 +... +--- +name: implicitdef_nxv16i32 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv16i32 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 16 x s32>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8m8 = COPY [[DEF]](<vscale x 16 x s32>) + ; CHECK-NEXT: PseudoRET implicit $v8m8 + %0:_(<vscale x 16 x s32>) = G_IMPLICIT_DEF + $v8m8 = COPY %0(<vscale x 16 x s32>) + PseudoRET implicit $v8m8 +... +--- +name: implicitdef_nxv1i64 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv1i64 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 1 x s64>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8 = COPY [[DEF]](<vscale x 1 x s64>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 1 x s64>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 1 x s64>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv2i64 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv2i64 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 2 x s64>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8m2 = COPY [[DEF]](<vscale x 2 x s64>) + ; CHECK-NEXT: PseudoRET implicit $v8m2 + %0:_(<vscale x 2 x s64>) = G_IMPLICIT_DEF + $v8m2 = COPY %0(<vscale x 2 x s64>) + PseudoRET implicit $v8m2 +... +--- +name: implicitdef_nxv4i64 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv4i64 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 4 x s64>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8m4 = COPY [[DEF]](<vscale x 4 x s64>) + ; CHECK-NEXT: PseudoRET implicit $v8m4 + %0:_(<vscale x 4 x s64>) = G_IMPLICIT_DEF + $v8m4 = COPY %0(<vscale x 4 x s64>) + PseudoRET implicit $v8m4 +... +--- +name: implicitdef_nxv8i64 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: implicitdef_nxv8i64 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 8 x s64>) = G_IMPLICIT_DEF + ; CHECK-NEXT: $v8m8 = COPY [[DEF]](<vscale x 8 x s64>) + ; CHECK-NEXT: PseudoRET implicit $v8m8 + %0:_(<vscale x 8 x s64>) = G_IMPLICIT_DEF + $v8m8 = COPY %0(<vscale x 8 x s64>) + PseudoRET implicit $v8m8 +... diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-select.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-select.mir new file mode 100644 index 0000000000000000000000000000000000000000..6e1d4aa4d7d6f57f0c7fd5a79e0242734d4f5660 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-select.mir @@ -0,0 +1,400 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=riscv32 -mattr=+v -run-pass=legalizer %s -o - | FileCheck %s +# RUN: llc -mtriple=riscv64 -mattr=+v -run-pass=legalizer %s -o - | FileCheck %s + +--- +name: select_nxv1i8 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv1i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 1 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 1 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 1 x s8>) = G_SELECT [[DEF]](<vscale x 1 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8 = COPY [[SELECT]](<vscale x 1 x s8>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 1 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 1 x s8>) = G_IMPLICIT_DEF + %0:_(<vscale x 1 x s8>) = G_SELECT %1(<vscale x 1 x s1>), %2(<vscale x 1 x s8>), %2(<vscale x 1 x s8>) + $v8 = COPY %0(<vscale x 1 x s8>) + PseudoRET implicit $v8 +... +--- +name: select_nxv2i8 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv2i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 2 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 2 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 2 x s8>) = G_SELECT [[DEF]](<vscale x 2 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8 = COPY [[SELECT]](<vscale x 2 x s8>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 2 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 2 x s8>) = G_IMPLICIT_DEF + %0:_(<vscale x 2 x s8>) = G_SELECT %1(<vscale x 2 x s1>), %2(<vscale x 2 x s8>), %2(<vscale x 2 x s8>) + $v8 = COPY %0(<vscale x 2 x s8>) + PseudoRET implicit $v8 +... +--- +name: select_nxv4i8 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv4i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 4 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 4 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 4 x s8>) = G_SELECT [[DEF]](<vscale x 4 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8 = COPY [[SELECT]](<vscale x 4 x s8>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 4 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 4 x s8>) = G_IMPLICIT_DEF + %0:_(<vscale x 4 x s8>) = G_SELECT %1(<vscale x 4 x s1>), %2(<vscale x 4 x s8>), %2(<vscale x 4 x s8>) + $v8 = COPY %0(<vscale x 4 x s8>) + PseudoRET implicit $v8 +... +--- +name: select_nxv8i8 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv8i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 8 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 8 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 8 x s8>) = G_SELECT [[DEF]](<vscale x 8 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8 = COPY [[SELECT]](<vscale x 8 x s8>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 8 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 8 x s8>) = G_IMPLICIT_DEF + %0:_(<vscale x 8 x s8>) = G_SELECT %1(<vscale x 8 x s1>), %2(<vscale x 8 x s8>), %2(<vscale x 8 x s8>) + $v8 = COPY %0(<vscale x 8 x s8>) + PseudoRET implicit $v8 +... +--- +name: select_nxv16i8 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv16i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 16 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 16 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 16 x s8>) = G_SELECT [[DEF]](<vscale x 16 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8m2 = COPY [[SELECT]](<vscale x 16 x s8>) + ; CHECK-NEXT: PseudoRET implicit $v8m2 + %1:_(<vscale x 16 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 16 x s8>) = G_IMPLICIT_DEF + %0:_(<vscale x 16 x s8>) = G_SELECT %1(<vscale x 16 x s1>), %2(<vscale x 16 x s8>), %2(<vscale x 16 x s8>) + $v8m2 = COPY %0(<vscale x 16 x s8>) + PseudoRET implicit $v8m2 +... +--- +name: select_nxv32i8 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv32i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 32 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 32 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 32 x s8>) = G_SELECT [[DEF]](<vscale x 32 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8m4 = COPY [[SELECT]](<vscale x 32 x s8>) + ; CHECK-NEXT: PseudoRET implicit $v8m4 + %1:_(<vscale x 32 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 32 x s8>) = G_IMPLICIT_DEF + %0:_(<vscale x 32 x s8>) = G_SELECT %1(<vscale x 32 x s1>), %2(<vscale x 32 x s8>), %2(<vscale x 32 x s8>) + $v8m4 = COPY %0(<vscale x 32 x s8>) + PseudoRET implicit $v8m4 +... +--- +name: select_nxv64i8 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv64i8 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 64 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 64 x s8>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 64 x s8>) = G_SELECT [[DEF]](<vscale x 64 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8m8 = COPY [[SELECT]](<vscale x 64 x s8>) + ; CHECK-NEXT: PseudoRET implicit $v8m8 + %1:_(<vscale x 64 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 64 x s8>) = G_IMPLICIT_DEF + %0:_(<vscale x 64 x s8>) = G_SELECT %1(<vscale x 64 x s1>), %2(<vscale x 64 x s8>), %2(<vscale x 64 x s8>) + $v8m8 = COPY %0(<vscale x 64 x s8>) + PseudoRET implicit $v8m8 +... +--- +name: select_nxv1i16 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv1i16 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 1 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 1 x s16>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 1 x s16>) = G_SELECT [[DEF]](<vscale x 1 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8 = COPY [[SELECT]](<vscale x 1 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 1 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 1 x s16>) = G_IMPLICIT_DEF + %0:_(<vscale x 1 x s16>) = G_SELECT %1(<vscale x 1 x s1>), %2(<vscale x 1 x s16>), %2(<vscale x 1 x s16>) + $v8 = COPY %0(<vscale x 1 x s16>) + PseudoRET implicit $v8 +... +--- +name: select_nxv2i16 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv2i16 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 2 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 2 x s16>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 2 x s16>) = G_SELECT [[DEF]](<vscale x 2 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8 = COPY [[SELECT]](<vscale x 2 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 2 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 2 x s16>) = G_IMPLICIT_DEF + %0:_(<vscale x 2 x s16>) = G_SELECT %1(<vscale x 2 x s1>), %2(<vscale x 2 x s16>), %2(<vscale x 2 x s16>) + $v8 = COPY %0(<vscale x 2 x s16>) + PseudoRET implicit $v8 +... +--- +name: select_nxv4i16 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv4i16 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 4 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 4 x s16>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 4 x s16>) = G_SELECT [[DEF]](<vscale x 4 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8 = COPY [[SELECT]](<vscale x 4 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 4 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 4 x s16>) = G_IMPLICIT_DEF + %0:_(<vscale x 4 x s16>) = G_SELECT %1(<vscale x 4 x s1>), %2(<vscale x 4 x s16>), %2(<vscale x 4 x s16>) + $v8 = COPY %0(<vscale x 4 x s16>) + PseudoRET implicit $v8 +... +--- +name: select_nxv8i16 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv8i16 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 8 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 8 x s16>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 8 x s16>) = G_SELECT [[DEF]](<vscale x 8 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8m2 = COPY [[SELECT]](<vscale x 8 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8m2 + %1:_(<vscale x 8 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 8 x s16>) = G_IMPLICIT_DEF + %0:_(<vscale x 8 x s16>) = G_SELECT %1(<vscale x 8 x s1>), %2(<vscale x 8 x s16>), %2(<vscale x 8 x s16>) + $v8m2 = COPY %0(<vscale x 8 x s16>) + PseudoRET implicit $v8m2 +... +--- +name: select_nxv16i16 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv16i16 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 16 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 16 x s16>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 16 x s16>) = G_SELECT [[DEF]](<vscale x 16 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8m4 = COPY [[SELECT]](<vscale x 16 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8m4 + %1:_(<vscale x 16 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 16 x s16>) = G_IMPLICIT_DEF + %0:_(<vscale x 16 x s16>) = G_SELECT %1(<vscale x 16 x s1>), %2(<vscale x 16 x s16>), %2(<vscale x 16 x s16>) + $v8m4 = COPY %0(<vscale x 16 x s16>) + PseudoRET implicit $v8m4 +... +--- +name: select_nxv32i16 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv32i16 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 32 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 32 x s16>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 32 x s16>) = G_SELECT [[DEF]](<vscale x 32 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8m8 = COPY [[SELECT]](<vscale x 32 x s16>) + ; CHECK-NEXT: PseudoRET implicit $v8m8 + %1:_(<vscale x 32 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 32 x s16>) = G_IMPLICIT_DEF + %0:_(<vscale x 32 x s16>) = G_SELECT %1(<vscale x 32 x s1>), %2(<vscale x 32 x s16>), %2(<vscale x 32 x s16>) + $v8m8 = COPY %0(<vscale x 32 x s16>) + PseudoRET implicit $v8m8 +... +--- +name: select_nxv1i32 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv1i32 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 1 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 1 x s32>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 1 x s32>) = G_SELECT [[DEF]](<vscale x 1 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8 = COPY [[SELECT]](<vscale x 1 x s32>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 1 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 1 x s32>) = G_IMPLICIT_DEF + %0:_(<vscale x 1 x s32>) = G_SELECT %1(<vscale x 1 x s1>), %2(<vscale x 1 x s32>), %2(<vscale x 1 x s32>) + $v8 = COPY %0(<vscale x 1 x s32>) + PseudoRET implicit $v8 +... +--- +name: select_nxv2i32 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv2i32 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 2 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 2 x s32>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 2 x s32>) = G_SELECT [[DEF]](<vscale x 2 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8 = COPY [[SELECT]](<vscale x 2 x s32>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 2 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 2 x s32>) = G_IMPLICIT_DEF + %0:_(<vscale x 2 x s32>) = G_SELECT %1(<vscale x 2 x s1>), %2(<vscale x 2 x s32>), %2(<vscale x 2 x s32>) + $v8 = COPY %0(<vscale x 2 x s32>) + PseudoRET implicit $v8 +... +--- +name: select_nxv4i32 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv4i32 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 4 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 4 x s32>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 4 x s32>) = G_SELECT [[DEF]](<vscale x 4 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8m2 = COPY [[SELECT]](<vscale x 4 x s32>) + ; CHECK-NEXT: PseudoRET implicit $v8m2 + %1:_(<vscale x 4 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 4 x s32>) = G_IMPLICIT_DEF + %0:_(<vscale x 4 x s32>) = G_SELECT %1(<vscale x 4 x s1>), %2(<vscale x 4 x s32>), %2(<vscale x 4 x s32>) + $v8m2 = COPY %0(<vscale x 4 x s32>) + PseudoRET implicit $v8m2 +... +--- +name: select_nxv8i32 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv8i32 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 8 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 8 x s32>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 8 x s32>) = G_SELECT [[DEF]](<vscale x 8 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8m4 = COPY [[SELECT]](<vscale x 8 x s32>) + ; CHECK-NEXT: PseudoRET implicit $v8m4 + %1:_(<vscale x 8 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 8 x s32>) = G_IMPLICIT_DEF + %0:_(<vscale x 8 x s32>) = G_SELECT %1(<vscale x 8 x s1>), %2(<vscale x 8 x s32>), %2(<vscale x 8 x s32>) + $v8m4 = COPY %0(<vscale x 8 x s32>) + PseudoRET implicit $v8m4 +... +--- +name: select_nxv16i32 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv16i32 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 16 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 16 x s32>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 16 x s32>) = G_SELECT [[DEF]](<vscale x 16 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8m8 = COPY [[SELECT]](<vscale x 16 x s32>) + ; CHECK-NEXT: PseudoRET implicit $v8m8 + %1:_(<vscale x 16 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 16 x s32>) = G_IMPLICIT_DEF + %0:_(<vscale x 16 x s32>) = G_SELECT %1(<vscale x 16 x s1>), %2(<vscale x 16 x s32>), %2(<vscale x 16 x s32>) + $v8m8 = COPY %0(<vscale x 16 x s32>) + PseudoRET implicit $v8m8 +... +--- +name: select_nxv1i64 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv1i64 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 1 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 1 x s64>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 1 x s64>) = G_SELECT [[DEF]](<vscale x 1 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8 = COPY [[SELECT]](<vscale x 1 x s64>) + ; CHECK-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 1 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 1 x s64>) = G_IMPLICIT_DEF + %0:_(<vscale x 1 x s64>) = G_SELECT %1(<vscale x 1 x s1>), %2(<vscale x 1 x s64>), %2(<vscale x 1 x s64>) + $v8 = COPY %0(<vscale x 1 x s64>) + PseudoRET implicit $v8 +... +--- +name: select_nxv2i64 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv2i64 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 2 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 2 x s64>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 2 x s64>) = G_SELECT [[DEF]](<vscale x 2 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8m2 = COPY [[SELECT]](<vscale x 2 x s64>) + ; CHECK-NEXT: PseudoRET implicit $v8m2 + %1:_(<vscale x 2 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 2 x s64>) = G_IMPLICIT_DEF + %0:_(<vscale x 2 x s64>) = G_SELECT %1(<vscale x 2 x s1>), %2(<vscale x 2 x s64>), %2(<vscale x 2 x s64>) + $v8m2 = COPY %0(<vscale x 2 x s64>) + PseudoRET implicit $v8m2 +... +--- +name: select_nxv4i64 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv4i64 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 4 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 4 x s64>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 4 x s64>) = G_SELECT [[DEF]](<vscale x 4 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8m4 = COPY [[SELECT]](<vscale x 4 x s64>) + ; CHECK-NEXT: PseudoRET implicit $v8m4 + %1:_(<vscale x 4 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 4 x s64>) = G_IMPLICIT_DEF + %0:_(<vscale x 4 x s64>) = G_SELECT %1(<vscale x 4 x s1>), %2(<vscale x 4 x s64>), %2(<vscale x 4 x s64>) + $v8m4 = COPY %0(<vscale x 4 x s64>) + PseudoRET implicit $v8m4 +... +--- +name: select_nxv8i64 +legalized: false +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: select_nxv8i64 + ; CHECK: [[DEF:%[0-9]+]]:_(<vscale x 8 x s1>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<vscale x 8 x s64>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[SELECT:%[0-9]+]]:_(<vscale x 8 x s64>) = G_SELECT [[DEF]](<vscale x 8 x s1>), [[DEF1]], [[DEF1]] + ; CHECK-NEXT: $v8m8 = COPY [[SELECT]](<vscale x 8 x s64>) + ; CHECK-NEXT: PseudoRET implicit $v8m8 + %1:_(<vscale x 8 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 8 x s64>) = G_IMPLICIT_DEF + %0:_(<vscale x 8 x s64>) = G_SELECT %1(<vscale x 8 x s1>), %2(<vscale x 8 x s64>), %2(<vscale x 8 x s64>) + $v8m8 = COPY %0(<vscale x 8 x s64>) + PseudoRET implicit $v8m8 +... diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-vscale-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-vscale-rv32.mir new file mode 100644 index 0000000000000000000000000000000000000000..899f7955a27302943362e9c75de052bd2b20a768 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-vscale-rv32.mir @@ -0,0 +1,228 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=riscv32 -mattr=+v,+m -run-pass=legalizer %s -o - | FileCheck %s + +--- +name: test_1_s32 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_1_s32 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: $x10 = COPY [[LSHR]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s32) = G_VSCALE i32 1 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_2_s32 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_2_s32 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: $x10 = COPY [[LSHR]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s32) = G_VSCALE i32 2 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_3_s32 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_3_s32 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s32) = G_VSCALE i32 3 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_4_s32 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_4_s32 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: $x10 = COPY [[LSHR]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s32) = G_VSCALE i32 4 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_8_s32 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_8_s32 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: $x10 = COPY [[READ_VLENB]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s32) = G_VSCALE i32 8 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_16_s32 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_16_s32 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: $x10 = COPY [[SHL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s32) = G_VSCALE i32 16 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_40_s32 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_40_s32 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 5 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[READ_VLENB]], [[C]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s32) = G_VSCALE i32 40 + $x10 = COPY %0 + PseudoRET implicit $x10 +... + +--- +name: test_1_s64 +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_1_s64 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 1 + %1:_(s32) = G_TRUNC %0 + $x10 = COPY %1 + PseudoRET implicit $x10 +... +--- +name: test_2_s64 +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_2_s64 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 2 + %1:_(s32) = G_TRUNC %0 + $x10 = COPY %1 + PseudoRET implicit $x10 +... +--- +name: test_3_s64 +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_3_s64 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 3 + %1:_(s32) = G_TRUNC %0 + $x10 = COPY %1 + PseudoRET implicit $x10 +... +--- +name: test_4_s64 +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_4_s64 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 4 + %1:_(s32) = G_TRUNC %0 + $x10 = COPY %1 + PseudoRET implicit $x10 +... +--- +name: test_8_s64 +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_8_s64 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 8 + %1:_(s32) = G_TRUNC %0 + $x10 = COPY %1 + PseudoRET implicit $x10 +... +--- +name: test_16_s64 +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_16_s64 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 16 + %1:_(s32) = G_TRUNC %0 + $x10 = COPY %1 + PseudoRET implicit $x10 +... +--- +name: test_40_s64 +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_40_s64 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 40 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 40 + %1:_(s32) = G_TRUNC %0 + $x10 = COPY %1 + PseudoRET implicit $x10 +... diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-vscale-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-vscale-rv64.mir new file mode 100644 index 0000000000000000000000000000000000000000..c0453a04a1815850b277c39d67cdf239d7d2d72f --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/rvv/legalize-vscale-rv64.mir @@ -0,0 +1,110 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=riscv64 -mattr=+v,+m -run-pass=legalizer %s -o - | FileCheck %s + +--- +name: test_1 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_1 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s64) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[READ_VLENB]], [[C]](s64) + ; CHECK-NEXT: $x10 = COPY [[LSHR]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 1 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_2 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_2 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s64) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 2 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[READ_VLENB]], [[C]](s64) + ; CHECK-NEXT: $x10 = COPY [[LSHR]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 2 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_3 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_3 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s64) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[READ_VLENB]], [[C]](s64) + ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 3 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 3 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_4 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_4 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s64) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[READ_VLENB]], [[C]](s64) + ; CHECK-NEXT: $x10 = COPY [[LSHR]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 4 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_8 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_8 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s64) = G_READ_VLENB + ; CHECK-NEXT: $x10 = COPY [[READ_VLENB]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 8 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_16 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_16 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s64) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1 + ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[READ_VLENB]], [[C]](s64) + ; CHECK-NEXT: $x10 = COPY [[SHL]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 16 + $x10 = COPY %0 + PseudoRET implicit $x10 +... +--- +name: test_40 +body: | + bb.0.entry: + + ; CHECK-LABEL: name: test_40 + ; CHECK: [[READ_VLENB:%[0-9]+]]:_(s64) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 5 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[READ_VLENB]], [[C]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %0:_(s64) = G_VSCALE i64 40 + $x10 = COPY %0 + PseudoRET implicit $x10 +... + + diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/implicit-def.mir b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/implicit-def.mir new file mode 100644 index 0000000000000000000000000000000000000000..ef1e355252e1bb7195d6cb20a1c5c1622f464b19 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/implicit-def.mir @@ -0,0 +1,425 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=riscv32 -mattr=+m,+v -run-pass=regbankselect \ +# RUN: -disable-gisel-legality-check -simplify-mir -verify-machineinstrs %s \ +# RUN: -o - | FileCheck -check-prefix=RV32I %s +# RUN: llc -mtriple=riscv64 -mattr=+m,+v -run-pass=regbankselect \ +# RUN: -disable-gisel-legality-check -simplify-mir -verify-machineinstrs %s \ +# RUN: -o - | FileCheck -check-prefix=RV64I %s +--- +name: implicitdef_nxv1i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv1i8 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 1 x s8>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8 = COPY [[DEF]](<vscale x 1 x s8>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: implicitdef_nxv1i8 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 1 x s8>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8 = COPY [[DEF]](<vscale x 1 x s8>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 1 x s8>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 1 x s8>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv2i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv2i8 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 2 x s8>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8 = COPY [[DEF]](<vscale x 2 x s8>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: implicitdef_nxv2i8 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 2 x s8>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8 = COPY [[DEF]](<vscale x 2 x s8>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 2 x s8>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 2 x s8>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv4i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv4i8 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 4 x s8>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8 = COPY [[DEF]](<vscale x 4 x s8>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: implicitdef_nxv4i8 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 4 x s8>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8 = COPY [[DEF]](<vscale x 4 x s8>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 4 x s8>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 4 x s8>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv8i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv8i8 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 8 x s8>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8 = COPY [[DEF]](<vscale x 8 x s8>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: implicitdef_nxv8i8 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 8 x s8>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8 = COPY [[DEF]](<vscale x 8 x s8>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 8 x s8>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 8 x s8>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv16i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv16i8 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 16 x s8>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8m2 = COPY [[DEF]](<vscale x 16 x s8>) + ; RV32I-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64I-LABEL: name: implicitdef_nxv16i8 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 16 x s8>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8m2 = COPY [[DEF]](<vscale x 16 x s8>) + ; RV64I-NEXT: PseudoRET implicit $v8m2 + %0:_(<vscale x 16 x s8>) = G_IMPLICIT_DEF + $v8m2 = COPY %0(<vscale x 16 x s8>) + PseudoRET implicit $v8m2 +... +--- +name: implicitdef_nxv32i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv32i8 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 32 x s8>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8m4 = COPY [[DEF]](<vscale x 32 x s8>) + ; RV32I-NEXT: PseudoRET implicit $v8m4 + ; + ; RV64I-LABEL: name: implicitdef_nxv32i8 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 32 x s8>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8m4 = COPY [[DEF]](<vscale x 32 x s8>) + ; RV64I-NEXT: PseudoRET implicit $v8m4 + %0:_(<vscale x 32 x s8>) = G_IMPLICIT_DEF + $v8m4 = COPY %0(<vscale x 32 x s8>) + PseudoRET implicit $v8m4 +... +--- +name: implicitdef_nxv64i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv64i8 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 64 x s8>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8m8 = COPY [[DEF]](<vscale x 64 x s8>) + ; RV32I-NEXT: PseudoRET implicit $v8m8 + ; + ; RV64I-LABEL: name: implicitdef_nxv64i8 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 64 x s8>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8m8 = COPY [[DEF]](<vscale x 64 x s8>) + ; RV64I-NEXT: PseudoRET implicit $v8m8 + %0:_(<vscale x 64 x s8>) = G_IMPLICIT_DEF + $v8m8 = COPY %0(<vscale x 64 x s8>) + PseudoRET implicit $v8m8 +... +--- +name: implicitdef_nxv1i16 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv1i16 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 1 x s16>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8 = COPY [[DEF]](<vscale x 1 x s16>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: implicitdef_nxv1i16 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 1 x s16>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8 = COPY [[DEF]](<vscale x 1 x s16>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 1 x s16>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 1 x s16>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv2i16 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv2i16 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 2 x s16>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8 = COPY [[DEF]](<vscale x 2 x s16>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: implicitdef_nxv2i16 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 2 x s16>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8 = COPY [[DEF]](<vscale x 2 x s16>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 2 x s16>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 2 x s16>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv4i16 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv4i16 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 4 x s16>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8 = COPY [[DEF]](<vscale x 4 x s16>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: implicitdef_nxv4i16 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 4 x s16>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8 = COPY [[DEF]](<vscale x 4 x s16>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 4 x s16>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 4 x s16>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv8i16 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv8i16 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 8 x s16>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8m2 = COPY [[DEF]](<vscale x 8 x s16>) + ; RV32I-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64I-LABEL: name: implicitdef_nxv8i16 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 8 x s16>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8m2 = COPY [[DEF]](<vscale x 8 x s16>) + ; RV64I-NEXT: PseudoRET implicit $v8m2 + %0:_(<vscale x 8 x s16>) = G_IMPLICIT_DEF + $v8m2 = COPY %0(<vscale x 8 x s16>) + PseudoRET implicit $v8m2 +... +--- +name: implicitdef_nxv16i16 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv16i16 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 16 x s16>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8m4 = COPY [[DEF]](<vscale x 16 x s16>) + ; RV32I-NEXT: PseudoRET implicit $v8m4 + ; + ; RV64I-LABEL: name: implicitdef_nxv16i16 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 16 x s16>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8m4 = COPY [[DEF]](<vscale x 16 x s16>) + ; RV64I-NEXT: PseudoRET implicit $v8m4 + %0:_(<vscale x 16 x s16>) = G_IMPLICIT_DEF + $v8m4 = COPY %0(<vscale x 16 x s16>) + PseudoRET implicit $v8m4 +... +--- +name: implicitdef_nxv32i16 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv32i16 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 32 x s16>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8m8 = COPY [[DEF]](<vscale x 32 x s16>) + ; RV32I-NEXT: PseudoRET implicit $v8m8 + ; + ; RV64I-LABEL: name: implicitdef_nxv32i16 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 32 x s16>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8m8 = COPY [[DEF]](<vscale x 32 x s16>) + ; RV64I-NEXT: PseudoRET implicit $v8m8 + %0:_(<vscale x 32 x s16>) = G_IMPLICIT_DEF + $v8m8 = COPY %0(<vscale x 32 x s16>) + PseudoRET implicit $v8m8 +... +--- +name: implicitdef_nxv1i32 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv1i32 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 1 x s32>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8 = COPY [[DEF]](<vscale x 1 x s32>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: implicitdef_nxv1i32 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 1 x s32>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8 = COPY [[DEF]](<vscale x 1 x s32>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 1 x s32>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 1 x s32>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv2i32 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv2i32 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 2 x s32>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8 = COPY [[DEF]](<vscale x 2 x s32>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: implicitdef_nxv2i32 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 2 x s32>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8 = COPY [[DEF]](<vscale x 2 x s32>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 2 x s32>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 2 x s32>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv4i32 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv4i32 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 4 x s32>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8m2 = COPY [[DEF]](<vscale x 4 x s32>) + ; RV32I-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64I-LABEL: name: implicitdef_nxv4i32 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 4 x s32>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8m2 = COPY [[DEF]](<vscale x 4 x s32>) + ; RV64I-NEXT: PseudoRET implicit $v8m2 + %0:_(<vscale x 4 x s32>) = G_IMPLICIT_DEF + $v8m2 = COPY %0(<vscale x 4 x s32>) + PseudoRET implicit $v8m2 +... +--- +name: implicitdef_nxv8i32 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv8i32 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 8 x s32>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8m4 = COPY [[DEF]](<vscale x 8 x s32>) + ; RV32I-NEXT: PseudoRET implicit $v8m4 + ; + ; RV64I-LABEL: name: implicitdef_nxv8i32 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 8 x s32>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8m4 = COPY [[DEF]](<vscale x 8 x s32>) + ; RV64I-NEXT: PseudoRET implicit $v8m4 + %0:_(<vscale x 8 x s32>) = G_IMPLICIT_DEF + $v8m4 = COPY %0(<vscale x 8 x s32>) + PseudoRET implicit $v8m4 +... +--- +name: implicitdef_nxv16i32 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv16i32 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 16 x s32>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8m8 = COPY [[DEF]](<vscale x 16 x s32>) + ; RV32I-NEXT: PseudoRET implicit $v8m8 + ; + ; RV64I-LABEL: name: implicitdef_nxv16i32 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 16 x s32>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8m8 = COPY [[DEF]](<vscale x 16 x s32>) + ; RV64I-NEXT: PseudoRET implicit $v8m8 + %0:_(<vscale x 16 x s32>) = G_IMPLICIT_DEF + $v8m8 = COPY %0(<vscale x 16 x s32>) + PseudoRET implicit $v8m8 +... +--- +name: implicitdef_nxv1i64 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv1i64 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 1 x s64>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8 = COPY [[DEF]](<vscale x 1 x s64>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: implicitdef_nxv1i64 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 1 x s64>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8 = COPY [[DEF]](<vscale x 1 x s64>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %0:_(<vscale x 1 x s64>) = G_IMPLICIT_DEF + $v8 = COPY %0(<vscale x 1 x s64>) + PseudoRET implicit $v8 +... +--- +name: implicitdef_nxv2i64 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv2i64 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 2 x s64>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8m2 = COPY [[DEF]](<vscale x 2 x s64>) + ; RV32I-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64I-LABEL: name: implicitdef_nxv2i64 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 2 x s64>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8m2 = COPY [[DEF]](<vscale x 2 x s64>) + ; RV64I-NEXT: PseudoRET implicit $v8m2 + %0:_(<vscale x 2 x s64>) = G_IMPLICIT_DEF + $v8m2 = COPY %0(<vscale x 2 x s64>) + PseudoRET implicit $v8m2 +... +--- +name: implicitdef_nxv4i64 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv4i64 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 4 x s64>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8m4 = COPY [[DEF]](<vscale x 4 x s64>) + ; RV32I-NEXT: PseudoRET implicit $v8m4 + ; + ; RV64I-LABEL: name: implicitdef_nxv4i64 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 4 x s64>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8m4 = COPY [[DEF]](<vscale x 4 x s64>) + ; RV64I-NEXT: PseudoRET implicit $v8m4 + %0:_(<vscale x 4 x s64>) = G_IMPLICIT_DEF + $v8m4 = COPY %0(<vscale x 4 x s64>) + PseudoRET implicit $v8m4 +... +--- +name: implicitdef_nxv8i64 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: implicitdef_nxv8i64 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 8 x s64>) = G_IMPLICIT_DEF + ; RV32I-NEXT: $v8m8 = COPY [[DEF]](<vscale x 8 x s64>) + ; RV32I-NEXT: PseudoRET implicit $v8m8 + ; + ; RV64I-LABEL: name: implicitdef_nxv8i64 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 8 x s64>) = G_IMPLICIT_DEF + ; RV64I-NEXT: $v8m8 = COPY [[DEF]](<vscale x 8 x s64>) + ; RV64I-NEXT: PseudoRET implicit $v8m8 + %0:_(<vscale x 8 x s64>) = G_IMPLICIT_DEF + $v8m8 = COPY %0(<vscale x 8 x s64>) + PseudoRET implicit $v8m8 +... diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/select.mir b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/select.mir new file mode 100644 index 0000000000000000000000000000000000000000..4dc077ae6bfebeab2fb84972f071c168241031be --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/select.mir @@ -0,0 +1,558 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=riscv32 -mattr=+m,+v -run-pass=regbankselect \ +# RUN: -disable-gisel-legality-check -simplify-mir -verify-machineinstrs %s \ +# RUN: -o - | FileCheck -check-prefix=RV32I %s +# RUN: llc -mtriple=riscv64 -mattr=+m,+v -run-pass=regbankselect \ +# RUN: -disable-gisel-legality-check -simplify-mir -verify-machineinstrs %s \ +# RUN: -o - | FileCheck -check-prefix=RV64I %s + +--- +name: select_nxv1i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv1i8 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 1 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 1 x s8>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 1 x s8>) = G_SELECT [[DEF]](<vscale x 1 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8 = COPY [[SELECT]](<vscale x 1 x s8>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: select_nxv1i8 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 1 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 1 x s8>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 1 x s8>) = G_SELECT [[DEF]](<vscale x 1 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8 = COPY [[SELECT]](<vscale x 1 x s8>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 1 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 1 x s8>) = G_IMPLICIT_DEF + %0:_(<vscale x 1 x s8>) = G_SELECT %1(<vscale x 1 x s1>), %2(<vscale x 1 x s8>), %2(<vscale x 1 x s8>) + $v8 = COPY %0(<vscale x 1 x s8>) + PseudoRET implicit $v8 +... +--- +name: select_nxv2i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv2i8 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 2 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 2 x s8>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 2 x s8>) = G_SELECT [[DEF]](<vscale x 2 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8 = COPY [[SELECT]](<vscale x 2 x s8>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: select_nxv2i8 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 2 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 2 x s8>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 2 x s8>) = G_SELECT [[DEF]](<vscale x 2 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8 = COPY [[SELECT]](<vscale x 2 x s8>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 2 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 2 x s8>) = G_IMPLICIT_DEF + %0:_(<vscale x 2 x s8>) = G_SELECT %1(<vscale x 2 x s1>), %2(<vscale x 2 x s8>), %2(<vscale x 2 x s8>) + $v8 = COPY %0(<vscale x 2 x s8>) + PseudoRET implicit $v8 +... +--- +name: select_nxv4i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv4i8 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 4 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 4 x s8>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 4 x s8>) = G_SELECT [[DEF]](<vscale x 4 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8 = COPY [[SELECT]](<vscale x 4 x s8>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: select_nxv4i8 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 4 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 4 x s8>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 4 x s8>) = G_SELECT [[DEF]](<vscale x 4 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8 = COPY [[SELECT]](<vscale x 4 x s8>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 4 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 4 x s8>) = G_IMPLICIT_DEF + %0:_(<vscale x 4 x s8>) = G_SELECT %1(<vscale x 4 x s1>), %2(<vscale x 4 x s8>), %2(<vscale x 4 x s8>) + $v8 = COPY %0(<vscale x 4 x s8>) + PseudoRET implicit $v8 +... +--- +name: select_nxv8i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv8i8 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 8 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 8 x s8>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 8 x s8>) = G_SELECT [[DEF]](<vscale x 8 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8 = COPY [[SELECT]](<vscale x 8 x s8>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: select_nxv8i8 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 8 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 8 x s8>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 8 x s8>) = G_SELECT [[DEF]](<vscale x 8 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8 = COPY [[SELECT]](<vscale x 8 x s8>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 8 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 8 x s8>) = G_IMPLICIT_DEF + %0:_(<vscale x 8 x s8>) = G_SELECT %1(<vscale x 8 x s1>), %2(<vscale x 8 x s8>), %2(<vscale x 8 x s8>) + $v8 = COPY %0(<vscale x 8 x s8>) + PseudoRET implicit $v8 +... +--- +name: select_nxv16i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv16i8 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 16 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 16 x s8>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 16 x s8>) = G_SELECT [[DEF]](<vscale x 16 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8m2 = COPY [[SELECT]](<vscale x 16 x s8>) + ; RV32I-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64I-LABEL: name: select_nxv16i8 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 16 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 16 x s8>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 16 x s8>) = G_SELECT [[DEF]](<vscale x 16 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8m2 = COPY [[SELECT]](<vscale x 16 x s8>) + ; RV64I-NEXT: PseudoRET implicit $v8m2 + %1:_(<vscale x 16 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 16 x s8>) = G_IMPLICIT_DEF + %0:_(<vscale x 16 x s8>) = G_SELECT %1(<vscale x 16 x s1>), %2(<vscale x 16 x s8>), %2(<vscale x 16 x s8>) + $v8m2 = COPY %0(<vscale x 16 x s8>) + PseudoRET implicit $v8m2 +... +--- +name: select_nxv32i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv32i8 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 32 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 32 x s8>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 32 x s8>) = G_SELECT [[DEF]](<vscale x 32 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8m4 = COPY [[SELECT]](<vscale x 32 x s8>) + ; RV32I-NEXT: PseudoRET implicit $v8m4 + ; + ; RV64I-LABEL: name: select_nxv32i8 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 32 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 32 x s8>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 32 x s8>) = G_SELECT [[DEF]](<vscale x 32 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8m4 = COPY [[SELECT]](<vscale x 32 x s8>) + ; RV64I-NEXT: PseudoRET implicit $v8m4 + %1:_(<vscale x 32 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 32 x s8>) = G_IMPLICIT_DEF + %0:_(<vscale x 32 x s8>) = G_SELECT %1(<vscale x 32 x s1>), %2(<vscale x 32 x s8>), %2(<vscale x 32 x s8>) + $v8m4 = COPY %0(<vscale x 32 x s8>) + PseudoRET implicit $v8m4 +... +--- +name: select_nxv64i8 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv64i8 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 64 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 64 x s8>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 64 x s8>) = G_SELECT [[DEF]](<vscale x 64 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8m8 = COPY [[SELECT]](<vscale x 64 x s8>) + ; RV32I-NEXT: PseudoRET implicit $v8m8 + ; + ; RV64I-LABEL: name: select_nxv64i8 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 64 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 64 x s8>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 64 x s8>) = G_SELECT [[DEF]](<vscale x 64 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8m8 = COPY [[SELECT]](<vscale x 64 x s8>) + ; RV64I-NEXT: PseudoRET implicit $v8m8 + %1:_(<vscale x 64 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 64 x s8>) = G_IMPLICIT_DEF + %0:_(<vscale x 64 x s8>) = G_SELECT %1(<vscale x 64 x s1>), %2(<vscale x 64 x s8>), %2(<vscale x 64 x s8>) + $v8m8 = COPY %0(<vscale x 64 x s8>) + PseudoRET implicit $v8m8 +... +--- +name: select_nxv1i16 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv1i16 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 1 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 1 x s16>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 1 x s16>) = G_SELECT [[DEF]](<vscale x 1 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8 = COPY [[SELECT]](<vscale x 1 x s16>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: select_nxv1i16 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 1 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 1 x s16>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 1 x s16>) = G_SELECT [[DEF]](<vscale x 1 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8 = COPY [[SELECT]](<vscale x 1 x s16>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 1 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 1 x s16>) = G_IMPLICIT_DEF + %0:_(<vscale x 1 x s16>) = G_SELECT %1(<vscale x 1 x s1>), %2(<vscale x 1 x s16>), %2(<vscale x 1 x s16>) + $v8 = COPY %0(<vscale x 1 x s16>) + PseudoRET implicit $v8 +... +--- +name: select_nxv2i16 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv2i16 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 2 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 2 x s16>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 2 x s16>) = G_SELECT [[DEF]](<vscale x 2 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8 = COPY [[SELECT]](<vscale x 2 x s16>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: select_nxv2i16 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 2 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 2 x s16>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 2 x s16>) = G_SELECT [[DEF]](<vscale x 2 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8 = COPY [[SELECT]](<vscale x 2 x s16>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 2 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 2 x s16>) = G_IMPLICIT_DEF + %0:_(<vscale x 2 x s16>) = G_SELECT %1(<vscale x 2 x s1>), %2(<vscale x 2 x s16>), %2(<vscale x 2 x s16>) + $v8 = COPY %0(<vscale x 2 x s16>) + PseudoRET implicit $v8 +... +--- +name: select_nxv4i16 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv4i16 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 4 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 4 x s16>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 4 x s16>) = G_SELECT [[DEF]](<vscale x 4 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8 = COPY [[SELECT]](<vscale x 4 x s16>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: select_nxv4i16 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 4 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 4 x s16>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 4 x s16>) = G_SELECT [[DEF]](<vscale x 4 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8 = COPY [[SELECT]](<vscale x 4 x s16>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 4 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 4 x s16>) = G_IMPLICIT_DEF + %0:_(<vscale x 4 x s16>) = G_SELECT %1(<vscale x 4 x s1>), %2(<vscale x 4 x s16>), %2(<vscale x 4 x s16>) + $v8 = COPY %0(<vscale x 4 x s16>) + PseudoRET implicit $v8 +... +--- +name: select_nxv8i16 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv8i16 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 8 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 8 x s16>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 8 x s16>) = G_SELECT [[DEF]](<vscale x 8 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8m2 = COPY [[SELECT]](<vscale x 8 x s16>) + ; RV32I-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64I-LABEL: name: select_nxv8i16 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 8 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 8 x s16>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 8 x s16>) = G_SELECT [[DEF]](<vscale x 8 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8m2 = COPY [[SELECT]](<vscale x 8 x s16>) + ; RV64I-NEXT: PseudoRET implicit $v8m2 + %1:_(<vscale x 8 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 8 x s16>) = G_IMPLICIT_DEF + %0:_(<vscale x 8 x s16>) = G_SELECT %1(<vscale x 8 x s1>), %2(<vscale x 8 x s16>), %2(<vscale x 8 x s16>) + $v8m2 = COPY %0(<vscale x 8 x s16>) + PseudoRET implicit $v8m2 +... +--- +name: select_nxv16i16 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv16i16 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 16 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 16 x s16>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 16 x s16>) = G_SELECT [[DEF]](<vscale x 16 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8m4 = COPY [[SELECT]](<vscale x 16 x s16>) + ; RV32I-NEXT: PseudoRET implicit $v8m4 + ; + ; RV64I-LABEL: name: select_nxv16i16 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 16 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 16 x s16>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 16 x s16>) = G_SELECT [[DEF]](<vscale x 16 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8m4 = COPY [[SELECT]](<vscale x 16 x s16>) + ; RV64I-NEXT: PseudoRET implicit $v8m4 + %1:_(<vscale x 16 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 16 x s16>) = G_IMPLICIT_DEF + %0:_(<vscale x 16 x s16>) = G_SELECT %1(<vscale x 16 x s1>), %2(<vscale x 16 x s16>), %2(<vscale x 16 x s16>) + $v8m4 = COPY %0(<vscale x 16 x s16>) + PseudoRET implicit $v8m4 +... +--- +name: select_nxv32i16 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv32i16 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 32 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 32 x s16>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 32 x s16>) = G_SELECT [[DEF]](<vscale x 32 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8m8 = COPY [[SELECT]](<vscale x 32 x s16>) + ; RV32I-NEXT: PseudoRET implicit $v8m8 + ; + ; RV64I-LABEL: name: select_nxv32i16 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 32 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 32 x s16>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 32 x s16>) = G_SELECT [[DEF]](<vscale x 32 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8m8 = COPY [[SELECT]](<vscale x 32 x s16>) + ; RV64I-NEXT: PseudoRET implicit $v8m8 + %1:_(<vscale x 32 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 32 x s16>) = G_IMPLICIT_DEF + %0:_(<vscale x 32 x s16>) = G_SELECT %1(<vscale x 32 x s1>), %2(<vscale x 32 x s16>), %2(<vscale x 32 x s16>) + $v8m8 = COPY %0(<vscale x 32 x s16>) + PseudoRET implicit $v8m8 +... +--- +name: select_nxv1i32 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv1i32 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 1 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 1 x s32>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 1 x s32>) = G_SELECT [[DEF]](<vscale x 1 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8 = COPY [[SELECT]](<vscale x 1 x s32>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: select_nxv1i32 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 1 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 1 x s32>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 1 x s32>) = G_SELECT [[DEF]](<vscale x 1 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8 = COPY [[SELECT]](<vscale x 1 x s32>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 1 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 1 x s32>) = G_IMPLICIT_DEF + %0:_(<vscale x 1 x s32>) = G_SELECT %1(<vscale x 1 x s1>), %2(<vscale x 1 x s32>), %2(<vscale x 1 x s32>) + $v8 = COPY %0(<vscale x 1 x s32>) + PseudoRET implicit $v8 +... +--- +name: select_nxv2i32 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv2i32 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 2 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 2 x s32>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 2 x s32>) = G_SELECT [[DEF]](<vscale x 2 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8 = COPY [[SELECT]](<vscale x 2 x s32>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: select_nxv2i32 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 2 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 2 x s32>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 2 x s32>) = G_SELECT [[DEF]](<vscale x 2 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8 = COPY [[SELECT]](<vscale x 2 x s32>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 2 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 2 x s32>) = G_IMPLICIT_DEF + %0:_(<vscale x 2 x s32>) = G_SELECT %1(<vscale x 2 x s1>), %2(<vscale x 2 x s32>), %2(<vscale x 2 x s32>) + $v8 = COPY %0(<vscale x 2 x s32>) + PseudoRET implicit $v8 +... +--- +name: select_nxv4i32 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv4i32 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 4 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 4 x s32>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 4 x s32>) = G_SELECT [[DEF]](<vscale x 4 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8m2 = COPY [[SELECT]](<vscale x 4 x s32>) + ; RV32I-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64I-LABEL: name: select_nxv4i32 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 4 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 4 x s32>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 4 x s32>) = G_SELECT [[DEF]](<vscale x 4 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8m2 = COPY [[SELECT]](<vscale x 4 x s32>) + ; RV64I-NEXT: PseudoRET implicit $v8m2 + %1:_(<vscale x 4 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 4 x s32>) = G_IMPLICIT_DEF + %0:_(<vscale x 4 x s32>) = G_SELECT %1(<vscale x 4 x s1>), %2(<vscale x 4 x s32>), %2(<vscale x 4 x s32>) + $v8m2 = COPY %0(<vscale x 4 x s32>) + PseudoRET implicit $v8m2 +... +--- +name: select_nxv8i32 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv8i32 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 8 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 8 x s32>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 8 x s32>) = G_SELECT [[DEF]](<vscale x 8 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8m4 = COPY [[SELECT]](<vscale x 8 x s32>) + ; RV32I-NEXT: PseudoRET implicit $v8m4 + ; + ; RV64I-LABEL: name: select_nxv8i32 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 8 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 8 x s32>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 8 x s32>) = G_SELECT [[DEF]](<vscale x 8 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8m4 = COPY [[SELECT]](<vscale x 8 x s32>) + ; RV64I-NEXT: PseudoRET implicit $v8m4 + %1:_(<vscale x 8 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 8 x s32>) = G_IMPLICIT_DEF + %0:_(<vscale x 8 x s32>) = G_SELECT %1(<vscale x 8 x s1>), %2(<vscale x 8 x s32>), %2(<vscale x 8 x s32>) + $v8m4 = COPY %0(<vscale x 8 x s32>) + PseudoRET implicit $v8m4 +... +--- +name: select_nxv16i32 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv16i32 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 16 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 16 x s32>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 16 x s32>) = G_SELECT [[DEF]](<vscale x 16 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8m8 = COPY [[SELECT]](<vscale x 16 x s32>) + ; RV32I-NEXT: PseudoRET implicit $v8m8 + ; + ; RV64I-LABEL: name: select_nxv16i32 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 16 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 16 x s32>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 16 x s32>) = G_SELECT [[DEF]](<vscale x 16 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8m8 = COPY [[SELECT]](<vscale x 16 x s32>) + ; RV64I-NEXT: PseudoRET implicit $v8m8 + %1:_(<vscale x 16 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 16 x s32>) = G_IMPLICIT_DEF + %0:_(<vscale x 16 x s32>) = G_SELECT %1(<vscale x 16 x s1>), %2(<vscale x 16 x s32>), %2(<vscale x 16 x s32>) + $v8m8 = COPY %0(<vscale x 16 x s32>) + PseudoRET implicit $v8m8 +... +--- +name: select_nxv1i64 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv1i64 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 1 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 1 x s64>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 1 x s64>) = G_SELECT [[DEF]](<vscale x 1 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8 = COPY [[SELECT]](<vscale x 1 x s64>) + ; RV32I-NEXT: PseudoRET implicit $v8 + ; + ; RV64I-LABEL: name: select_nxv1i64 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 1 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 1 x s64>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 1 x s64>) = G_SELECT [[DEF]](<vscale x 1 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8 = COPY [[SELECT]](<vscale x 1 x s64>) + ; RV64I-NEXT: PseudoRET implicit $v8 + %1:_(<vscale x 1 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 1 x s64>) = G_IMPLICIT_DEF + %0:_(<vscale x 1 x s64>) = G_SELECT %1(<vscale x 1 x s1>), %2(<vscale x 1 x s64>), %2(<vscale x 1 x s64>) + $v8 = COPY %0(<vscale x 1 x s64>) + PseudoRET implicit $v8 +... +--- +name: select_nxv2i64 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv2i64 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 2 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 2 x s64>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 2 x s64>) = G_SELECT [[DEF]](<vscale x 2 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8m2 = COPY [[SELECT]](<vscale x 2 x s64>) + ; RV32I-NEXT: PseudoRET implicit $v8m2 + ; + ; RV64I-LABEL: name: select_nxv2i64 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 2 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 2 x s64>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 2 x s64>) = G_SELECT [[DEF]](<vscale x 2 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8m2 = COPY [[SELECT]](<vscale x 2 x s64>) + ; RV64I-NEXT: PseudoRET implicit $v8m2 + %1:_(<vscale x 2 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 2 x s64>) = G_IMPLICIT_DEF + %0:_(<vscale x 2 x s64>) = G_SELECT %1(<vscale x 2 x s1>), %2(<vscale x 2 x s64>), %2(<vscale x 2 x s64>) + $v8m2 = COPY %0(<vscale x 2 x s64>) + PseudoRET implicit $v8m2 +... +--- +name: select_nxv4i64 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv4i64 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 4 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 4 x s64>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 4 x s64>) = G_SELECT [[DEF]](<vscale x 4 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8m4 = COPY [[SELECT]](<vscale x 4 x s64>) + ; RV32I-NEXT: PseudoRET implicit $v8m4 + ; + ; RV64I-LABEL: name: select_nxv4i64 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 4 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 4 x s64>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 4 x s64>) = G_SELECT [[DEF]](<vscale x 4 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8m4 = COPY [[SELECT]](<vscale x 4 x s64>) + ; RV64I-NEXT: PseudoRET implicit $v8m4 + %1:_(<vscale x 4 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 4 x s64>) = G_IMPLICIT_DEF + %0:_(<vscale x 4 x s64>) = G_SELECT %1(<vscale x 4 x s1>), %2(<vscale x 4 x s64>), %2(<vscale x 4 x s64>) + $v8m4 = COPY %0(<vscale x 4 x s64>) + PseudoRET implicit $v8m4 +... +--- +name: select_nxv8i64 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; RV32I-LABEL: name: select_nxv8i64 + ; RV32I: [[DEF:%[0-9]+]]:vrb(<vscale x 8 x s1>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 8 x s64>) = G_IMPLICIT_DEF + ; RV32I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 8 x s64>) = G_SELECT [[DEF]](<vscale x 8 x s1>), [[DEF1]], [[DEF1]] + ; RV32I-NEXT: $v8m8 = COPY [[SELECT]](<vscale x 8 x s64>) + ; RV32I-NEXT: PseudoRET implicit $v8m8 + ; + ; RV64I-LABEL: name: select_nxv8i64 + ; RV64I: [[DEF:%[0-9]+]]:vrb(<vscale x 8 x s1>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[DEF1:%[0-9]+]]:vrb(<vscale x 8 x s64>) = G_IMPLICIT_DEF + ; RV64I-NEXT: [[SELECT:%[0-9]+]]:vrb(<vscale x 8 x s64>) = G_SELECT [[DEF]](<vscale x 8 x s1>), [[DEF1]], [[DEF1]] + ; RV64I-NEXT: $v8m8 = COPY [[SELECT]](<vscale x 8 x s64>) + ; RV64I-NEXT: PseudoRET implicit $v8m8 + %1:_(<vscale x 8 x s1>) = G_IMPLICIT_DEF + %2:_(<vscale x 8 x s64>) = G_IMPLICIT_DEF + %0:_(<vscale x 8 x s64>) = G_SELECT %1(<vscale x 8 x s1>), %2(<vscale x 8 x s64>), %2(<vscale x 8 x s64>) + $v8m8 = COPY %0(<vscale x 8 x s64>) + PseudoRET implicit $v8m8 +... diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/vscale-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/vscale-rv32.mir new file mode 100644 index 0000000000000000000000000000000000000000..ae3bb0a18020d32dd1156219460f5652c714b41a --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/vscale-rv32.mir @@ -0,0 +1,48 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4 +# RUN: llc -mtriple=riscv32 -mattr=+m,+v -run-pass=regbankselect \ +# RUN: -disable-gisel-legality-check -simplify-mir -verify-machineinstrs %s \ +# RUN: -o - | FileCheck %s + +--- +name: test_s32 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_s32 + ; CHECK: [[READ_VLENB:%[0-9]+]]:gprb(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:gprb(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: $x10 = COPY [[LSHR]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:_(s32) = G_READ_VLENB + %2:_(s32) = G_CONSTANT i32 3 + %0:_(s32) = G_LSHR %1, %2(s32) + $x10 = COPY %0(s32) + PseudoRET implicit $x10 + +... +--- +name: test_s64 +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test_s64 + ; CHECK: [[READ_VLENB:%[0-9]+]]:gprb(s32) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:gprb(s32) = G_LSHR [[READ_VLENB]], [[C]](s32) + ; CHECK-NEXT: [[C1:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: [[MUL:%[0-9]+]]:gprb(s32) = G_MUL [[LSHR]], [[C1]] + ; CHECK-NEXT: $x10 = COPY [[MUL]](s32) + ; CHECK-NEXT: PseudoRET implicit $x10 + %17:_(s32) = G_READ_VLENB + %18:_(s32) = G_CONSTANT i32 3 + %2:_(s32) = G_LSHR %17, %18(s32) + %15:_(s32) = G_CONSTANT i32 1 + %9:_(s32) = G_MUL %2, %15 + $x10 = COPY %9(s32) + PseudoRET implicit $x10 + +... + diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/vscale-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/vscale-rv64.mir new file mode 100644 index 0000000000000000000000000000000000000000..a7446d976f25744fbdb832b0144b42fadedb7b37 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/regbankselect/rvv/vscale-rv64.mir @@ -0,0 +1,25 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=riscv64 -mattr=+m,+v -run-pass=regbankselect \ +# RUN: -disable-gisel-legality-check -simplify-mir -verify-machineinstrs %s \ +# RUN: -o - | FileCheck %s + +--- +name: test +legalized: true +tracksRegLiveness: true +body: | + bb.0.entry: + ; CHECK-LABEL: name: test + ; CHECK: [[READ_VLENB:%[0-9]+]]:gprb(s64) = G_READ_VLENB + ; CHECK-NEXT: [[C:%[0-9]+]]:gprb(s64) = G_CONSTANT i64 3 + ; CHECK-NEXT: [[LSHR:%[0-9]+]]:gprb(s64) = G_LSHR [[READ_VLENB]], [[C]](s64) + ; CHECK-NEXT: $x10 = COPY [[LSHR]](s64) + ; CHECK-NEXT: PseudoRET implicit $x10 + %1:_(s64) = G_READ_VLENB + %2:_(s64) = G_CONSTANT i64 3 + %0:_(s64) = G_LSHR %1, %2(s64) + $x10 = COPY %0(s64) + PseudoRET implicit $x10 + +... + diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll b/llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll index 7b110e562e053324221a9999617b48dda0f8e58d..d55adf371119b5c39f2377e961e186fb875fa3d2 100644 --- a/llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll +++ b/llvm/test/CodeGen/RISCV/GlobalISel/vararg.ll @@ -17,6 +17,12 @@ ; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -global-isel -mattr=+d -target-abi lp64d \ ; RUN: -verify-machineinstrs \ ; RUN: | FileCheck -check-prefixes=RV64,LP64D %s +; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv32 -global-isel \ +; RUN: -frame-pointer=all -target-abi ilp32 -verify-machineinstrs \ +; RUN: | FileCheck -check-prefixes=RV32-WITHFP %s +; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -global-isel \ +; RUN: -frame-pointer=all -target-abi lp64 -verify-machineinstrs \ +; RUN: | FileCheck -check-prefixes=RV64-WITHFP %s ; The same vararg calling convention is used for ilp32/ilp32f/ilp32d and for ; lp64/lp64f/lp64d. Different CHECK lines are required due to slight @@ -79,6 +85,67 @@ define i32 @va1(ptr %fmt, ...) { ; RV64-NEXT: lw a0, 0(a0) ; RV64-NEXT: addi sp, sp, 80 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va1: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: .cfi_def_cfa_offset 48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: .cfi_offset ra, -36 +; RV32-WITHFP-NEXT: .cfi_offset s0, -40 +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: .cfi_def_cfa s0, 32 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -12(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a0) +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va1: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: .cfi_def_cfa_offset 96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: .cfi_offset ra, -72 +; RV64-WITHFP-NEXT: .cfi_offset s0, -80 +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: .cfi_def_cfa s0, 64 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: addi a0, s0, 8 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: lw a0, -20(s0) +; RV64-WITHFP-NEXT: lwu a1, -24(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: slli a0, a0, 32 +; RV64-WITHFP-NEXT: or a0, a0, a1 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: srli a2, a1, 32 +; RV64-WITHFP-NEXT: sw a1, -24(s0) +; RV64-WITHFP-NEXT: sw a2, -20(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %argp.cur = load ptr, ptr %va, align 4 @@ -131,6 +198,58 @@ define i32 @va1_va_arg(ptr %fmt, ...) nounwind { ; RV64-NEXT: lw a0, 0(a0) ; RV64-NEXT: addi sp, sp, 80 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va1_va_arg: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -12(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a0) +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va1_va_arg: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: addi a0, s0, 8 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -24(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %1 = va_arg ptr %va, i32 @@ -212,6 +331,78 @@ define i32 @va1_va_arg_alloca(ptr %fmt, ...) nounwind { ; RV64-NEXT: ld s1, 8(sp) # 8-byte Folded Reload ; RV64-NEXT: addi sp, sp, 96 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va1_va_arg_alloca: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s1, 4(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -16(s0) +; RV32-WITHFP-NEXT: lw a0, -16(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -16(s0) +; RV32-WITHFP-NEXT: lw s1, 0(a0) +; RV32-WITHFP-NEXT: addi a0, s1, 15 +; RV32-WITHFP-NEXT: andi a0, a0, -16 +; RV32-WITHFP-NEXT: sub a0, sp, a0 +; RV32-WITHFP-NEXT: mv sp, a0 +; RV32-WITHFP-NEXT: call notdead +; RV32-WITHFP-NEXT: mv a0, s1 +; RV32-WITHFP-NEXT: addi sp, s0, -16 +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va1_va_arg_alloca: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s1, 8(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: addi a0, s0, 8 +; RV64-WITHFP-NEXT: sd a0, -32(s0) +; RV64-WITHFP-NEXT: ld a0, -32(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -32(s0) +; RV64-WITHFP-NEXT: lw s1, 0(a0) +; RV64-WITHFP-NEXT: slli a0, s1, 32 +; RV64-WITHFP-NEXT: srli a0, a0, 32 +; RV64-WITHFP-NEXT: addi a0, a0, 15 +; RV64-WITHFP-NEXT: andi a0, a0, -16 +; RV64-WITHFP-NEXT: sub a0, sp, a0 +; RV64-WITHFP-NEXT: mv sp, a0 +; RV64-WITHFP-NEXT: call notdead +; RV64-WITHFP-NEXT: mv a0, s1 +; RV64-WITHFP-NEXT: addi sp, s0, -32 +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s1, 8(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %1 = va_arg ptr %va, i32 @@ -273,6 +464,36 @@ define void @va1_caller() nounwind { ; LP64D-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; LP64D-NEXT: addi sp, sp, 16 ; LP64D-NEXT: ret +; +; RV32-WITHFP-LABEL: va1_caller: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -16 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: lui a3, 261888 +; RV32-WITHFP-NEXT: li a4, 2 +; RV32-WITHFP-NEXT: li a2, 0 +; RV32-WITHFP-NEXT: call va1 +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 16 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va1_caller: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -16 +; RV64-WITHFP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 0(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 16 +; RV64-WITHFP-NEXT: lui a0, %hi(.LCPI3_0) +; RV64-WITHFP-NEXT: ld a1, %lo(.LCPI3_0)(a0) +; RV64-WITHFP-NEXT: li a2, 2 +; RV64-WITHFP-NEXT: call va1 +; RV64-WITHFP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 0(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 16 +; RV64-WITHFP-NEXT: ret %1 = call i32 (ptr, ...) @va1(ptr undef, double 1.0, i32 2) ret void } @@ -395,6 +616,59 @@ define i64 @va2(ptr %fmt, ...) nounwind { ; RV64-NEXT: ld a0, 0(a1) ; RV64-NEXT: addi sp, sp, 80 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va2: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 7 +; RV32-WITHFP-NEXT: andi a1, a0, -8 +; RV32-WITHFP-NEXT: addi a0, a0, 8 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a1) +; RV32-WITHFP-NEXT: lw a1, 4(a1) +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va2: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: addi a0, s0, 8 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: addi a1, a0, 7 +; RV64-WITHFP-NEXT: andi a1, a1, -8 +; RV64-WITHFP-NEXT: addi a0, a0, 15 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, 0(a1) +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %argp.cur = load ptr, ptr %va @@ -459,6 +733,61 @@ define i64 @va2_va_arg(ptr %fmt, ...) nounwind { ; RV64-NEXT: srli a0, a0, 32 ; RV64-NEXT: addi sp, sp, 80 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va2_va_arg: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -12(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a0) +; RV32-WITHFP-NEXT: li a1, 0 +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va2_va_arg: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: addi a0, s0, 8 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -24(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: slli a0, a0, 32 +; RV64-WITHFP-NEXT: srli a0, a0, 32 +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %1 = va_arg ptr %va, i32 @@ -487,6 +816,32 @@ define void @va2_caller() nounwind { ; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; RV64-NEXT: addi sp, sp, 16 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va2_caller: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -16 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: li a1, 1 +; RV32-WITHFP-NEXT: call va2 +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 16 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va2_caller: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -16 +; RV64-WITHFP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 0(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 16 +; RV64-WITHFP-NEXT: li a1, 1 +; RV64-WITHFP-NEXT: call va2 +; RV64-WITHFP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 0(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 16 +; RV64-WITHFP-NEXT: ret %1 = call i64 (ptr, ...) @va2(ptr undef, i32 1) ret void } @@ -617,6 +972,61 @@ define i64 @va3(i32 %a, i64 %b, ...) nounwind { ; RV64-NEXT: add a0, a1, a0 ; RV64-NEXT: addi sp, sp, 64 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va3: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 20(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 16(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 24 +; RV32-WITHFP-NEXT: sw a3, 4(s0) +; RV32-WITHFP-NEXT: sw a4, 8(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: sw a5, 12(s0) +; RV32-WITHFP-NEXT: sw a6, 16(s0) +; RV32-WITHFP-NEXT: sw a7, 20(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 7 +; RV32-WITHFP-NEXT: andi a3, a0, -8 +; RV32-WITHFP-NEXT: addi a0, a0, 8 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a4, 0(a3) +; RV32-WITHFP-NEXT: lw a3, 4(a3) +; RV32-WITHFP-NEXT: add a0, a1, a4 +; RV32-WITHFP-NEXT: sltu a1, a0, a4 +; RV32-WITHFP-NEXT: add a2, a2, a3 +; RV32-WITHFP-NEXT: add a1, a2, a1 +; RV32-WITHFP-NEXT: lw ra, 20(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 16(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va3: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -80 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a2, 0(s0) +; RV64-WITHFP-NEXT: sd a3, 8(s0) +; RV64-WITHFP-NEXT: sd a4, 16(s0) +; RV64-WITHFP-NEXT: mv a0, s0 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: sd a5, 24(s0) +; RV64-WITHFP-NEXT: sd a6, 32(s0) +; RV64-WITHFP-NEXT: sd a7, 40(s0) +; RV64-WITHFP-NEXT: addi a2, a0, 7 +; RV64-WITHFP-NEXT: andi a2, a2, -8 +; RV64-WITHFP-NEXT: addi a0, a0, 15 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, 0(a2) +; RV64-WITHFP-NEXT: add a0, a1, a0 +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 80 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %argp.cur = load ptr, ptr %va @@ -682,6 +1092,61 @@ define i64 @va3_va_arg(i32 %a, i64 %b, ...) nounwind { ; RV64-NEXT: add a0, a1, a0 ; RV64-NEXT: addi sp, sp, 64 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va3_va_arg: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 20(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 16(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 24 +; RV32-WITHFP-NEXT: sw a3, 4(s0) +; RV32-WITHFP-NEXT: sw a4, 8(s0) +; RV32-WITHFP-NEXT: sw a5, 12(s0) +; RV32-WITHFP-NEXT: sw a6, 16(s0) +; RV32-WITHFP-NEXT: sw a7, 20(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a3, a0, 4 +; RV32-WITHFP-NEXT: sw a3, -12(s0) +; RV32-WITHFP-NEXT: lw a3, 0(a0) +; RV32-WITHFP-NEXT: add a0, a1, a3 +; RV32-WITHFP-NEXT: sltu a1, a0, a3 +; RV32-WITHFP-NEXT: add a1, a2, a1 +; RV32-WITHFP-NEXT: lw ra, 20(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 16(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va3_va_arg: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -80 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a2, 0(s0) +; RV64-WITHFP-NEXT: sd a3, 8(s0) +; RV64-WITHFP-NEXT: sd a4, 16(s0) +; RV64-WITHFP-NEXT: sd a5, 24(s0) +; RV64-WITHFP-NEXT: sd a6, 32(s0) +; RV64-WITHFP-NEXT: sd a7, 40(s0) +; RV64-WITHFP-NEXT: mv a0, s0 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a2, a0, 4 +; RV64-WITHFP-NEXT: sd a2, -24(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: slli a0, a0, 32 +; RV64-WITHFP-NEXT: srli a0, a0, 32 +; RV64-WITHFP-NEXT: add a0, a1, a0 +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 80 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %1 = va_arg ptr %va, i32 @@ -718,6 +1183,39 @@ define void @va3_caller() nounwind { ; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; RV64-NEXT: addi sp, sp, 16 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va3_caller: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -16 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: lui a0, 5 +; RV32-WITHFP-NEXT: addi a3, a0, -480 +; RV32-WITHFP-NEXT: li a0, 2 +; RV32-WITHFP-NEXT: li a1, 1111 +; RV32-WITHFP-NEXT: li a2, 0 +; RV32-WITHFP-NEXT: call va3 +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 16 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va3_caller: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -16 +; RV64-WITHFP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 0(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 16 +; RV64-WITHFP-NEXT: lui a0, 5 +; RV64-WITHFP-NEXT: addiw a2, a0, -480 +; RV64-WITHFP-NEXT: li a0, 2 +; RV64-WITHFP-NEXT: li a1, 1111 +; RV64-WITHFP-NEXT: call va3 +; RV64-WITHFP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 0(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 16 +; RV64-WITHFP-NEXT: ret %1 = call i64 (i32, i64, ...) @va3(i32 2, i64 1111, i32 20000) ret void } @@ -745,9 +1243,8 @@ define i32 @va4_va_copy(i32 %argno, ...) nounwind { ; RV32-NEXT: addi a1, a0, 4 ; RV32-NEXT: sw a1, 4(sp) ; RV32-NEXT: lw a1, 4(sp) -; RV32-NEXT: mv a2, sp ; RV32-NEXT: lw s0, 0(a0) -; RV32-NEXT: sw a2, 0(a1) +; RV32-NEXT: sw a1, 0(sp) ; RV32-NEXT: lw a0, 0(sp) ; RV32-NEXT: call notdead ; RV32-NEXT: lw a0, 4(sp) @@ -796,9 +1293,8 @@ define i32 @va4_va_copy(i32 %argno, ...) nounwind { ; RV64-NEXT: addi a1, a0, 4 ; RV64-NEXT: sd a1, 8(sp) ; RV64-NEXT: ld a1, 8(sp) -; RV64-NEXT: mv a2, sp ; RV64-NEXT: lw s0, 0(a0) -; RV64-NEXT: sd a2, 0(a1) +; RV64-NEXT: sd a1, 0(sp) ; RV64-NEXT: lw a0, 4(sp) ; RV64-NEXT: lwu a1, 0(sp) ; RV64-NEXT: slli a0, a0, 32 @@ -829,6 +1325,115 @@ define i32 @va4_va_copy(i32 %argno, ...) nounwind { ; RV64-NEXT: ld s0, 16(sp) # 8-byte Folded Reload ; RV64-NEXT: addi sp, sp, 96 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va4_va_copy: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -64 +; RV32-WITHFP-NEXT: sw ra, 28(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 24(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s1, 20(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 32 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a0, s0, 4 +; RV32-WITHFP-NEXT: sw a0, -16(s0) +; RV32-WITHFP-NEXT: lw a0, -16(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -16(s0) +; RV32-WITHFP-NEXT: lw a1, -16(s0) +; RV32-WITHFP-NEXT: lw s1, 0(a0) +; RV32-WITHFP-NEXT: sw a1, -20(s0) +; RV32-WITHFP-NEXT: lw a0, -20(s0) +; RV32-WITHFP-NEXT: call notdead +; RV32-WITHFP-NEXT: lw a0, -16(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -16(s0) +; RV32-WITHFP-NEXT: lw a1, -16(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a0) +; RV32-WITHFP-NEXT: addi a1, a1, 3 +; RV32-WITHFP-NEXT: andi a1, a1, -4 +; RV32-WITHFP-NEXT: addi a2, a1, 4 +; RV32-WITHFP-NEXT: sw a2, -16(s0) +; RV32-WITHFP-NEXT: lw a2, -16(s0) +; RV32-WITHFP-NEXT: lw a1, 0(a1) +; RV32-WITHFP-NEXT: addi a2, a2, 3 +; RV32-WITHFP-NEXT: andi a2, a2, -4 +; RV32-WITHFP-NEXT: addi a3, a2, 4 +; RV32-WITHFP-NEXT: sw a3, -16(s0) +; RV32-WITHFP-NEXT: lw a2, 0(a2) +; RV32-WITHFP-NEXT: add a0, a0, s1 +; RV32-WITHFP-NEXT: add a1, a1, a2 +; RV32-WITHFP-NEXT: add a0, a0, a1 +; RV32-WITHFP-NEXT: lw ra, 28(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 24(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s1, 20(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 64 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va4_va_copy: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -112 +; RV64-WITHFP-NEXT: sd ra, 40(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 32(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s1, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 48 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: addi a0, s0, 8 +; RV64-WITHFP-NEXT: sd a0, -32(s0) +; RV64-WITHFP-NEXT: ld a0, -32(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -32(s0) +; RV64-WITHFP-NEXT: ld a1, -32(s0) +; RV64-WITHFP-NEXT: lw s1, 0(a0) +; RV64-WITHFP-NEXT: sd a1, -40(s0) +; RV64-WITHFP-NEXT: lw a0, -36(s0) +; RV64-WITHFP-NEXT: lwu a1, -40(s0) +; RV64-WITHFP-NEXT: slli a0, a0, 32 +; RV64-WITHFP-NEXT: or a0, a0, a1 +; RV64-WITHFP-NEXT: call notdead +; RV64-WITHFP-NEXT: ld a0, -32(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -32(s0) +; RV64-WITHFP-NEXT: ld a1, -32(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: addi a1, a1, 3 +; RV64-WITHFP-NEXT: andi a1, a1, -4 +; RV64-WITHFP-NEXT: addi a2, a1, 4 +; RV64-WITHFP-NEXT: sd a2, -32(s0) +; RV64-WITHFP-NEXT: ld a2, -32(s0) +; RV64-WITHFP-NEXT: lw a1, 0(a1) +; RV64-WITHFP-NEXT: addi a2, a2, 3 +; RV64-WITHFP-NEXT: andi a2, a2, -4 +; RV64-WITHFP-NEXT: addi a3, a2, 4 +; RV64-WITHFP-NEXT: sd a3, -32(s0) +; RV64-WITHFP-NEXT: lw a2, 0(a2) +; RV64-WITHFP-NEXT: add a0, a0, s1 +; RV64-WITHFP-NEXT: add a1, a1, a2 +; RV64-WITHFP-NEXT: addw a0, a0, a1 +; RV64-WITHFP-NEXT: ld ra, 40(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 32(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s1, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 112 +; RV64-WITHFP-NEXT: ret %vargs = alloca ptr %wargs = alloca ptr call void @llvm.va_start(ptr %vargs) @@ -899,6 +1504,60 @@ define i32 @va6_no_fixed_args(...) nounwind { ; RV64-NEXT: lw a0, 0(a0) ; RV64-NEXT: addi sp, sp, 80 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va6_no_fixed_args: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: sw a0, 0(s0) +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: mv a0, s0 +; RV32-WITHFP-NEXT: sw a0, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -12(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a0) +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va6_no_fixed_args: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: sd a0, 0(s0) +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: mv a0, s0 +; RV64-WITHFP-NEXT: sd a0, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -24(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret %va = alloca ptr call void @llvm.va_start(ptr %va) %1 = va_arg ptr %va, i32 @@ -993,6 +1652,85 @@ define i32 @va_large_stack(ptr %fmt, ...) { ; RV64-NEXT: addiw a1, a1, 336 ; RV64-NEXT: add sp, sp, a1 ; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va_large_stack: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -2032 +; RV32-WITHFP-NEXT: .cfi_def_cfa_offset 2032 +; RV32-WITHFP-NEXT: sw ra, 1996(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 1992(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: .cfi_offset ra, -36 +; RV32-WITHFP-NEXT: .cfi_offset s0, -40 +; RV32-WITHFP-NEXT: addi s0, sp, 2000 +; RV32-WITHFP-NEXT: .cfi_def_cfa s0, 32 +; RV32-WITHFP-NEXT: lui a0, 24414 +; RV32-WITHFP-NEXT: addi a0, a0, -1728 +; RV32-WITHFP-NEXT: sub sp, sp, a0 +; RV32-WITHFP-NEXT: lui a0, 24414 +; RV32-WITHFP-NEXT: addi a0, a0, 272 +; RV32-WITHFP-NEXT: sub a0, s0, a0 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: addi a1, s0, 4 +; RV32-WITHFP-NEXT: sw a1, 0(a0) +; RV32-WITHFP-NEXT: lw a1, 0(a0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: addi a2, a1, 4 +; RV32-WITHFP-NEXT: sw a2, 0(a0) +; RV32-WITHFP-NEXT: lw a0, 0(a1) +; RV32-WITHFP-NEXT: lui a1, 24414 +; RV32-WITHFP-NEXT: addi a1, a1, -1728 +; RV32-WITHFP-NEXT: add sp, sp, a1 +; RV32-WITHFP-NEXT: lw ra, 1996(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 1992(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 2032 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va_large_stack: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -2032 +; RV64-WITHFP-NEXT: .cfi_def_cfa_offset 2032 +; RV64-WITHFP-NEXT: sd ra, 1960(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 1952(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: .cfi_offset ra, -72 +; RV64-WITHFP-NEXT: .cfi_offset s0, -80 +; RV64-WITHFP-NEXT: addi s0, sp, 1968 +; RV64-WITHFP-NEXT: .cfi_def_cfa s0, 64 +; RV64-WITHFP-NEXT: lui a0, 24414 +; RV64-WITHFP-NEXT: addiw a0, a0, -1680 +; RV64-WITHFP-NEXT: sub sp, sp, a0 +; RV64-WITHFP-NEXT: lui a0, 24414 +; RV64-WITHFP-NEXT: addiw a0, a0, 288 +; RV64-WITHFP-NEXT: sub a0, s0, a0 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: addi a1, s0, 8 +; RV64-WITHFP-NEXT: sd a1, 0(a0) +; RV64-WITHFP-NEXT: lw a1, 4(a0) +; RV64-WITHFP-NEXT: lwu a2, 0(a0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: slli a1, a1, 32 +; RV64-WITHFP-NEXT: or a1, a1, a2 +; RV64-WITHFP-NEXT: addi a2, a1, 4 +; RV64-WITHFP-NEXT: srli a3, a2, 32 +; RV64-WITHFP-NEXT: sw a2, 0(a0) +; RV64-WITHFP-NEXT: sw a3, 4(a0) +; RV64-WITHFP-NEXT: lw a0, 0(a1) +; RV64-WITHFP-NEXT: lui a1, 24414 +; RV64-WITHFP-NEXT: addiw a1, a1, -1680 +; RV64-WITHFP-NEXT: add sp, sp, a1 +; RV64-WITHFP-NEXT: ld ra, 1960(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 1952(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 2032 +; RV64-WITHFP-NEXT: ret %large = alloca [ 100000000 x i8 ] %va = alloca ptr call void @llvm.va_start(ptr %va) @@ -1004,5 +1742,193 @@ define i32 @va_large_stack(ptr %fmt, ...) { ret i32 %1 } +define i32 @va_vprintf(ptr %fmt, ptr %arg_start) { +; RV32-LABEL: va_vprintf: +; RV32: # %bb.0: +; RV32-NEXT: addi sp, sp, -16 +; RV32-NEXT: .cfi_def_cfa_offset 16 +; RV32-NEXT: sw a1, 12(sp) +; RV32-NEXT: lw a0, 12(sp) +; RV32-NEXT: sw a0, 8(sp) +; RV32-NEXT: lw a0, 8(sp) +; RV32-NEXT: addi a0, a0, 3 +; RV32-NEXT: andi a0, a0, -4 +; RV32-NEXT: addi a1, a0, 4 +; RV32-NEXT: sw a1, 8(sp) +; RV32-NEXT: lw a0, 0(a0) +; RV32-NEXT: addi sp, sp, 16 +; RV32-NEXT: ret +; +; RV64-LABEL: va_vprintf: +; RV64: # %bb.0: +; RV64-NEXT: addi sp, sp, -16 +; RV64-NEXT: .cfi_def_cfa_offset 16 +; RV64-NEXT: sd a1, 8(sp) +; RV64-NEXT: ld a0, 8(sp) +; RV64-NEXT: sd a0, 0(sp) +; RV64-NEXT: ld a0, 0(sp) +; RV64-NEXT: addi a0, a0, 3 +; RV64-NEXT: andi a0, a0, -4 +; RV64-NEXT: addi a1, a0, 4 +; RV64-NEXT: sd a1, 0(sp) +; RV64-NEXT: lw a0, 0(a0) +; RV64-NEXT: addi sp, sp, 16 +; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va_vprintf: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -16 +; RV32-WITHFP-NEXT: .cfi_def_cfa_offset 16 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: .cfi_offset ra, -4 +; RV32-WITHFP-NEXT: .cfi_offset s0, -8 +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: .cfi_def_cfa s0, 0 +; RV32-WITHFP-NEXT: sw a1, -12(s0) +; RV32-WITHFP-NEXT: lw a0, -12(s0) +; RV32-WITHFP-NEXT: sw a0, -16(s0) +; RV32-WITHFP-NEXT: lw a0, -16(s0) +; RV32-WITHFP-NEXT: addi a0, a0, 3 +; RV32-WITHFP-NEXT: andi a0, a0, -4 +; RV32-WITHFP-NEXT: addi a1, a0, 4 +; RV32-WITHFP-NEXT: sw a1, -16(s0) +; RV32-WITHFP-NEXT: lw a0, 0(a0) +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 16 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va_vprintf: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -32 +; RV64-WITHFP-NEXT: .cfi_def_cfa_offset 32 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: .cfi_offset ra, -8 +; RV64-WITHFP-NEXT: .cfi_offset s0, -16 +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: .cfi_def_cfa s0, 0 +; RV64-WITHFP-NEXT: sd a1, -24(s0) +; RV64-WITHFP-NEXT: ld a0, -24(s0) +; RV64-WITHFP-NEXT: sd a0, -32(s0) +; RV64-WITHFP-NEXT: ld a0, -32(s0) +; RV64-WITHFP-NEXT: addi a0, a0, 3 +; RV64-WITHFP-NEXT: andi a0, a0, -4 +; RV64-WITHFP-NEXT: addi a1, a0, 4 +; RV64-WITHFP-NEXT: sd a1, -32(s0) +; RV64-WITHFP-NEXT: lw a0, 0(a0) +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 32 +; RV64-WITHFP-NEXT: ret + %args = alloca ptr + %args_cp = alloca ptr + store ptr %arg_start, ptr %args + call void @llvm.va_copy(ptr %args_cp, ptr %args) + %width = va_arg ptr %args_cp, i32 + call void @llvm.va_end(ptr %args_cp) + ret i32 %width +} - +define i32 @va_printf(ptr %fmt, ...) { +; RV32-LABEL: va_printf: +; RV32: # %bb.0: +; RV32-NEXT: addi sp, sp, -48 +; RV32-NEXT: .cfi_def_cfa_offset 48 +; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-NEXT: .cfi_offset ra, -36 +; RV32-NEXT: sw a1, 20(sp) +; RV32-NEXT: sw a2, 24(sp) +; RV32-NEXT: sw a3, 28(sp) +; RV32-NEXT: sw a4, 32(sp) +; RV32-NEXT: addi a1, sp, 20 +; RV32-NEXT: sw a1, 8(sp) +; RV32-NEXT: lw a1, 8(sp) +; RV32-NEXT: sw a5, 36(sp) +; RV32-NEXT: sw a6, 40(sp) +; RV32-NEXT: sw a7, 44(sp) +; RV32-NEXT: call va_vprintf +; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-NEXT: addi sp, sp, 48 +; RV32-NEXT: ret +; +; RV64-LABEL: va_printf: +; RV64: # %bb.0: +; RV64-NEXT: addi sp, sp, -80 +; RV64-NEXT: .cfi_def_cfa_offset 80 +; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-NEXT: .cfi_offset ra, -72 +; RV64-NEXT: sd a1, 24(sp) +; RV64-NEXT: sd a2, 32(sp) +; RV64-NEXT: sd a3, 40(sp) +; RV64-NEXT: sd a4, 48(sp) +; RV64-NEXT: addi a1, sp, 24 +; RV64-NEXT: sd a1, 0(sp) +; RV64-NEXT: ld a1, 0(sp) +; RV64-NEXT: sd a5, 56(sp) +; RV64-NEXT: sd a6, 64(sp) +; RV64-NEXT: sd a7, 72(sp) +; RV64-NEXT: call va_vprintf +; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-NEXT: addi sp, sp, 80 +; RV64-NEXT: ret +; +; RV32-WITHFP-LABEL: va_printf: +; RV32-WITHFP: # %bb.0: +; RV32-WITHFP-NEXT: addi sp, sp, -48 +; RV32-WITHFP-NEXT: .cfi_def_cfa_offset 48 +; RV32-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32-WITHFP-NEXT: .cfi_offset ra, -36 +; RV32-WITHFP-NEXT: .cfi_offset s0, -40 +; RV32-WITHFP-NEXT: addi s0, sp, 16 +; RV32-WITHFP-NEXT: .cfi_def_cfa s0, 32 +; RV32-WITHFP-NEXT: sw a1, 4(s0) +; RV32-WITHFP-NEXT: sw a2, 8(s0) +; RV32-WITHFP-NEXT: sw a3, 12(s0) +; RV32-WITHFP-NEXT: sw a4, 16(s0) +; RV32-WITHFP-NEXT: addi a1, s0, 4 +; RV32-WITHFP-NEXT: sw a1, -12(s0) +; RV32-WITHFP-NEXT: lw a1, -12(s0) +; RV32-WITHFP-NEXT: sw a5, 20(s0) +; RV32-WITHFP-NEXT: sw a6, 24(s0) +; RV32-WITHFP-NEXT: sw a7, 28(s0) +; RV32-WITHFP-NEXT: call va_vprintf +; RV32-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32-WITHFP-NEXT: addi sp, sp, 48 +; RV32-WITHFP-NEXT: ret +; +; RV64-WITHFP-LABEL: va_printf: +; RV64-WITHFP: # %bb.0: +; RV64-WITHFP-NEXT: addi sp, sp, -96 +; RV64-WITHFP-NEXT: .cfi_def_cfa_offset 96 +; RV64-WITHFP-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; RV64-WITHFP-NEXT: .cfi_offset ra, -72 +; RV64-WITHFP-NEXT: .cfi_offset s0, -80 +; RV64-WITHFP-NEXT: addi s0, sp, 32 +; RV64-WITHFP-NEXT: .cfi_def_cfa s0, 64 +; RV64-WITHFP-NEXT: sd a1, 8(s0) +; RV64-WITHFP-NEXT: sd a2, 16(s0) +; RV64-WITHFP-NEXT: sd a3, 24(s0) +; RV64-WITHFP-NEXT: sd a4, 32(s0) +; RV64-WITHFP-NEXT: addi a1, s0, 8 +; RV64-WITHFP-NEXT: sd a1, -24(s0) +; RV64-WITHFP-NEXT: ld a1, -24(s0) +; RV64-WITHFP-NEXT: sd a5, 40(s0) +; RV64-WITHFP-NEXT: sd a6, 48(s0) +; RV64-WITHFP-NEXT: sd a7, 56(s0) +; RV64-WITHFP-NEXT: call va_vprintf +; RV64-WITHFP-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; RV64-WITHFP-NEXT: addi sp, sp, 96 +; RV64-WITHFP-NEXT: ret + %args = alloca ptr + call void @llvm.va_start(ptr %args) + %arg_start = load ptr, ptr %args + %ret_val = call i32 @va_vprintf(ptr %fmt, ptr %arg_start) + call void @llvm.va_end(ptr %args) + ret i32 %ret_val +} diff --git a/llvm/test/CodeGen/RISCV/allow-check.ll b/llvm/test/CodeGen/RISCV/allow-check.ll new file mode 100644 index 0000000000000000000000000000000000000000..0ddb5266db8f5501eec089eb05b777bc24fafe53 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/allow-check.ll @@ -0,0 +1,32 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=riscv32 -global-isel=0 -fast-isel=0 | FileCheck %s +; RUN: llc < %s -mtriple=riscv32 -global-isel=1 -fast-isel=0 | FileCheck %s +; RUN: llc < %s -mtriple=riscv32 -global-isel=0 -fast-isel=1 | FileCheck %s + +; RUN: llc < %s -mtriple=riscv64 -global-isel=0 -fast-isel=0 | FileCheck %s +; RUN: llc < %s -mtriple=riscv64 -global-isel=1 -fast-isel=0 | FileCheck %s +; RUN: llc < %s -mtriple=riscv64 -global-isel=0 -fast-isel=1 | FileCheck %s + +define i1 @test_runtime() local_unnamed_addr { +; CHECK-LABEL: test_runtime: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: li a0, 1 +; CHECK-NEXT: ret +entry: + %allow = call i1 @llvm.allow.runtime.check(metadata !"test_check") + ret i1 %allow +} + +declare i1 @llvm.allow.runtime.check(metadata) nounwind + +define i1 @test_ubsan() local_unnamed_addr { +; CHECK-LABEL: test_ubsan: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: li a0, 1 +; CHECK-NEXT: ret +entry: + %allow = call i1 @llvm.allow.ubsan.check(i8 7) + ret i1 %allow +} + +declare i1 @llvm.allow.ubsan.check(i8) nounwind diff --git a/llvm/test/CodeGen/RISCV/attributes-module-flag.ll b/llvm/test/CodeGen/RISCV/attributes-module-flag.ll new file mode 100644 index 0000000000000000000000000000000000000000..4580539fbb29b90e7fbaf9455cbd2d946f7d5b97 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/attributes-module-flag.ll @@ -0,0 +1,17 @@ +; RUN: llc -mtriple=riscv32 %s -o - | FileCheck %s --check-prefix=RV32 +; RUN: llc -mtriple=riscv64 %s -o - | FileCheck %s --check-prefix=RV64 + +; Test generation of ELF attribute from module metadata + +; RV32: .attribute 5, "rv32i2p1_m2p0_zba1p0" +; RV64: .attribute 5, "rv64i2p1_m2p0_zba1p0" + +define i32 @addi(i32 %a) { + %1 = add i32 %a, 1 + ret i32 %1 +} + +!llvm.module.flags = !{!0} + +!0 = !{i32 6, !"riscv-isa", !1} +!1 = !{!"rv64i2p1_m2p0", !"rv64i2p1_zba1p0"} diff --git a/llvm/test/CodeGen/RISCV/ctlz-cttz-ctpop.ll b/llvm/test/CodeGen/RISCV/ctlz-cttz-ctpop.ll index 455e6e54c9b3962e404fbc89eb934c108f05a0fb..549d531e829ea5ec0f05df2c48c540c685cedc31 100644 --- a/llvm/test/CodeGen/RISCV/ctlz-cttz-ctpop.ll +++ b/llvm/test/CodeGen/RISCV/ctlz-cttz-ctpop.ll @@ -1160,8 +1160,6 @@ define i32 @test_ctlz_i32(i32 %a) nounwind { ; RV32I: # %bb.0: ; RV32I-NEXT: beqz a0, .LBB10_2 ; RV32I-NEXT: # %bb.1: # %cond.false -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32I-NEXT: srli a1, a0, 1 ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 2 @@ -1189,12 +1187,11 @@ define i32 @test_ctlz_i32(i32 %a) nounwind { ; RV32I-NEXT: lui a1, 61681 ; RV32I-NEXT: addi a1, a1, -241 ; RV32I-NEXT: and a0, a0, a1 -; RV32I-NEXT: lui a1, 4112 -; RV32I-NEXT: addi a1, a1, 257 -; RV32I-NEXT: call __mulsi3 +; RV32I-NEXT: slli a1, a0, 8 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: slli a1, a0, 16 +; RV32I-NEXT: add a0, a0, a1 ; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32I-NEXT: addi sp, sp, 16 ; RV32I-NEXT: ret ; RV32I-NEXT: .LBB10_2: ; RV32I-NEXT: li a0, 32 @@ -1205,8 +1202,6 @@ define i32 @test_ctlz_i32(i32 %a) nounwind { ; RV64I-NEXT: sext.w a1, a0 ; RV64I-NEXT: beqz a1, .LBB10_2 ; RV64I-NEXT: # %bb.1: # %cond.false -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: srliw a1, a0, 1 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: srliw a1, a0, 2 @@ -1232,14 +1227,13 @@ define i32 @test_ctlz_i32(i32 %a) nounwind { ; RV64I-NEXT: srli a1, a0, 4 ; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: lui a1, 61681 -; RV64I-NEXT: addiw a1, a1, -241 +; RV64I-NEXT: addi a1, a1, -241 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srliw a0, a0, 24 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret ; RV64I-NEXT: .LBB10_2: ; RV64I-NEXT: li a0, 32 @@ -1354,19 +1348,16 @@ define i32 @test_ctlz_i32(i32 %a) nounwind { define i64 @test_ctlz_i64(i64 %a) nounwind { ; RV32I-LABEL: test_ctlz_i64: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -32 -; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s4, 8(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s5, 4(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s6, 0(sp) # 4-byte Folded Spill -; RV32I-NEXT: mv s0, a1 -; RV32I-NEXT: mv s2, a0 -; RV32I-NEXT: srli a0, a1, 1 -; RV32I-NEXT: or a0, a1, a0 +; RV32I-NEXT: lui a2, 349525 +; RV32I-NEXT: addi a4, a2, 1365 +; RV32I-NEXT: lui a2, 209715 +; RV32I-NEXT: addi a3, a2, 819 +; RV32I-NEXT: lui a2, 61681 +; RV32I-NEXT: addi a2, a2, -241 +; RV32I-NEXT: bnez a1, .LBB11_2 +; RV32I-NEXT: # %bb.1: +; RV32I-NEXT: srli a1, a0, 1 +; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 2 ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 4 @@ -1377,28 +1368,26 @@ define i64 @test_ctlz_i64(i64 %a) nounwind { ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: not a0, a0 ; RV32I-NEXT: srli a1, a0, 1 -; RV32I-NEXT: lui a2, 349525 -; RV32I-NEXT: addi s4, a2, 1365 -; RV32I-NEXT: and a1, a1, s4 +; RV32I-NEXT: and a1, a1, a4 ; RV32I-NEXT: sub a0, a0, a1 -; RV32I-NEXT: lui a1, 209715 -; RV32I-NEXT: addi s5, a1, 819 -; RV32I-NEXT: and a1, a0, s5 +; RV32I-NEXT: and a1, a0, a3 ; RV32I-NEXT: srli a0, a0, 2 -; RV32I-NEXT: and a0, a0, s5 +; RV32I-NEXT: and a0, a0, a3 ; RV32I-NEXT: add a0, a1, a0 ; RV32I-NEXT: srli a1, a0, 4 ; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: lui a1, 61681 -; RV32I-NEXT: addi s6, a1, -241 -; RV32I-NEXT: and a0, a0, s6 -; RV32I-NEXT: lui a1, 4112 -; RV32I-NEXT: addi s3, a1, 257 -; RV32I-NEXT: mv a1, s3 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: mv s1, a0 -; RV32I-NEXT: srli a0, s2, 1 -; RV32I-NEXT: or a0, s2, a0 +; RV32I-NEXT: and a0, a0, a2 +; RV32I-NEXT: slli a1, a0, 8 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: slli a1, a0, 16 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: srli a0, a0, 24 +; RV32I-NEXT: addi a0, a0, 32 +; RV32I-NEXT: li a1, 0 +; RV32I-NEXT: ret +; RV32I-NEXT: .LBB11_2: +; RV32I-NEXT: srli a0, a1, 1 +; RV32I-NEXT: or a0, a1, a0 ; RV32I-NEXT: srli a1, a0, 2 ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 4 @@ -1409,43 +1398,27 @@ define i64 @test_ctlz_i64(i64 %a) nounwind { ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: not a0, a0 ; RV32I-NEXT: srli a1, a0, 1 -; RV32I-NEXT: and a1, a1, s4 +; RV32I-NEXT: and a1, a1, a4 ; RV32I-NEXT: sub a0, a0, a1 -; RV32I-NEXT: and a1, a0, s5 +; RV32I-NEXT: and a1, a0, a3 ; RV32I-NEXT: srli a0, a0, 2 -; RV32I-NEXT: and a0, a0, s5 +; RV32I-NEXT: and a0, a0, a3 ; RV32I-NEXT: add a0, a1, a0 ; RV32I-NEXT: srli a1, a0, 4 ; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: and a0, a0, s6 -; RV32I-NEXT: mv a1, s3 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: bnez s0, .LBB11_2 -; RV32I-NEXT: # %bb.1: +; RV32I-NEXT: and a0, a0, a2 +; RV32I-NEXT: slli a1, a0, 8 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: slli a1, a0, 16 +; RV32I-NEXT: add a0, a0, a1 ; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: addi a0, a0, 32 -; RV32I-NEXT: j .LBB11_3 -; RV32I-NEXT: .LBB11_2: -; RV32I-NEXT: srli a0, s1, 24 -; RV32I-NEXT: .LBB11_3: ; RV32I-NEXT: li a1, 0 -; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s4, 8(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s5, 4(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s6, 0(sp) # 4-byte Folded Reload -; RV32I-NEXT: addi sp, sp, 32 ; RV32I-NEXT: ret ; ; RV64I-LABEL: test_ctlz_i64: ; RV64I: # %bb.0: ; RV64I-NEXT: beqz a0, .LBB11_2 ; RV64I-NEXT: # %bb.1: # %cond.false -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: srli a1, a0, 1 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: srli a1, a0, 2 @@ -1481,14 +1454,13 @@ define i64 @test_ctlz_i64(i64 %a) nounwind { ; RV64I-NEXT: slli a2, a1, 32 ; RV64I-NEXT: add a1, a1, a2 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: slli a2, a1, 32 -; RV64I-NEXT: add a1, a1, a2 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 32 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srli a0, a0, 56 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret ; RV64I-NEXT: .LBB11_2: ; RV64I-NEXT: li a0, 64 @@ -1831,8 +1803,6 @@ define i16 @test_ctlz_i16_zero_undef(i16 %a) nounwind { define i32 @test_ctlz_i32_zero_undef(i32 %a) nounwind { ; RV32I-LABEL: test_ctlz_i32_zero_undef: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32I-NEXT: srli a1, a0, 1 ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 2 @@ -1860,18 +1830,15 @@ define i32 @test_ctlz_i32_zero_undef(i32 %a) nounwind { ; RV32I-NEXT: lui a1, 61681 ; RV32I-NEXT: addi a1, a1, -241 ; RV32I-NEXT: and a0, a0, a1 -; RV32I-NEXT: lui a1, 4112 -; RV32I-NEXT: addi a1, a1, 257 -; RV32I-NEXT: call __mulsi3 +; RV32I-NEXT: slli a1, a0, 8 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: slli a1, a0, 16 +; RV32I-NEXT: add a0, a0, a1 ; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32I-NEXT: addi sp, sp, 16 ; RV32I-NEXT: ret ; ; RV64I-LABEL: test_ctlz_i32_zero_undef: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: srliw a1, a0, 1 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: srliw a1, a0, 2 @@ -1897,14 +1864,13 @@ define i32 @test_ctlz_i32_zero_undef(i32 %a) nounwind { ; RV64I-NEXT: srli a1, a0, 4 ; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: lui a1, 61681 -; RV64I-NEXT: addiw a1, a1, -241 +; RV64I-NEXT: addi a1, a1, -241 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srliw a0, a0, 24 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret ; ; RV32M-LABEL: test_ctlz_i32_zero_undef: @@ -2005,19 +1971,16 @@ define i32 @test_ctlz_i32_zero_undef(i32 %a) nounwind { define i64 @test_ctlz_i64_zero_undef(i64 %a) nounwind { ; RV32I-LABEL: test_ctlz_i64_zero_undef: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -32 -; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s4, 8(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s5, 4(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s6, 0(sp) # 4-byte Folded Spill -; RV32I-NEXT: mv s0, a1 -; RV32I-NEXT: mv s2, a0 -; RV32I-NEXT: srli a0, a1, 1 -; RV32I-NEXT: or a0, a1, a0 +; RV32I-NEXT: lui a2, 349525 +; RV32I-NEXT: addi a4, a2, 1365 +; RV32I-NEXT: lui a2, 209715 +; RV32I-NEXT: addi a3, a2, 819 +; RV32I-NEXT: lui a2, 61681 +; RV32I-NEXT: addi a2, a2, -241 +; RV32I-NEXT: bnez a1, .LBB15_2 +; RV32I-NEXT: # %bb.1: +; RV32I-NEXT: srli a1, a0, 1 +; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 2 ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 4 @@ -2028,28 +1991,26 @@ define i64 @test_ctlz_i64_zero_undef(i64 %a) nounwind { ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: not a0, a0 ; RV32I-NEXT: srli a1, a0, 1 -; RV32I-NEXT: lui a2, 349525 -; RV32I-NEXT: addi s4, a2, 1365 -; RV32I-NEXT: and a1, a1, s4 +; RV32I-NEXT: and a1, a1, a4 ; RV32I-NEXT: sub a0, a0, a1 -; RV32I-NEXT: lui a1, 209715 -; RV32I-NEXT: addi s5, a1, 819 -; RV32I-NEXT: and a1, a0, s5 +; RV32I-NEXT: and a1, a0, a3 ; RV32I-NEXT: srli a0, a0, 2 -; RV32I-NEXT: and a0, a0, s5 +; RV32I-NEXT: and a0, a0, a3 ; RV32I-NEXT: add a0, a1, a0 ; RV32I-NEXT: srli a1, a0, 4 ; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: lui a1, 61681 -; RV32I-NEXT: addi s6, a1, -241 -; RV32I-NEXT: and a0, a0, s6 -; RV32I-NEXT: lui a1, 4112 -; RV32I-NEXT: addi s3, a1, 257 -; RV32I-NEXT: mv a1, s3 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: mv s1, a0 -; RV32I-NEXT: srli a0, s2, 1 -; RV32I-NEXT: or a0, s2, a0 +; RV32I-NEXT: and a0, a0, a2 +; RV32I-NEXT: slli a1, a0, 8 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: slli a1, a0, 16 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: srli a0, a0, 24 +; RV32I-NEXT: addi a0, a0, 32 +; RV32I-NEXT: li a1, 0 +; RV32I-NEXT: ret +; RV32I-NEXT: .LBB15_2: +; RV32I-NEXT: srli a0, a1, 1 +; RV32I-NEXT: or a0, a1, a0 ; RV32I-NEXT: srli a1, a0, 2 ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 4 @@ -2060,41 +2021,25 @@ define i64 @test_ctlz_i64_zero_undef(i64 %a) nounwind { ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: not a0, a0 ; RV32I-NEXT: srli a1, a0, 1 -; RV32I-NEXT: and a1, a1, s4 +; RV32I-NEXT: and a1, a1, a4 ; RV32I-NEXT: sub a0, a0, a1 -; RV32I-NEXT: and a1, a0, s5 +; RV32I-NEXT: and a1, a0, a3 ; RV32I-NEXT: srli a0, a0, 2 -; RV32I-NEXT: and a0, a0, s5 +; RV32I-NEXT: and a0, a0, a3 ; RV32I-NEXT: add a0, a1, a0 ; RV32I-NEXT: srli a1, a0, 4 ; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: and a0, a0, s6 -; RV32I-NEXT: mv a1, s3 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: bnez s0, .LBB15_2 -; RV32I-NEXT: # %bb.1: +; RV32I-NEXT: and a0, a0, a2 +; RV32I-NEXT: slli a1, a0, 8 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: slli a1, a0, 16 +; RV32I-NEXT: add a0, a0, a1 ; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: addi a0, a0, 32 -; RV32I-NEXT: j .LBB15_3 -; RV32I-NEXT: .LBB15_2: -; RV32I-NEXT: srli a0, s1, 24 -; RV32I-NEXT: .LBB15_3: ; RV32I-NEXT: li a1, 0 -; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s4, 8(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s5, 4(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s6, 0(sp) # 4-byte Folded Reload -; RV32I-NEXT: addi sp, sp, 32 ; RV32I-NEXT: ret ; ; RV64I-LABEL: test_ctlz_i64_zero_undef: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: srli a1, a0, 1 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: srli a1, a0, 2 @@ -2130,14 +2075,13 @@ define i64 @test_ctlz_i64_zero_undef(i64 %a) nounwind { ; RV64I-NEXT: slli a2, a1, 32 ; RV64I-NEXT: add a1, a1, a2 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: slli a2, a1, 32 -; RV64I-NEXT: add a1, a1, a2 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 32 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srli a0, a0, 56 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret ; ; RV32M-LABEL: test_ctlz_i64_zero_undef: @@ -2464,8 +2408,6 @@ define i16 @test_ctpop_i16(i16 %a) nounwind { define i32 @test_ctpop_i32(i32 %a) nounwind { ; RV32I-LABEL: test_ctpop_i32: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32I-NEXT: srli a1, a0, 1 ; RV32I-NEXT: lui a2, 349525 ; RV32I-NEXT: addi a2, a2, 1365 @@ -2482,18 +2424,15 @@ define i32 @test_ctpop_i32(i32 %a) nounwind { ; RV32I-NEXT: lui a1, 61681 ; RV32I-NEXT: addi a1, a1, -241 ; RV32I-NEXT: and a0, a0, a1 -; RV32I-NEXT: lui a1, 4112 -; RV32I-NEXT: addi a1, a1, 257 -; RV32I-NEXT: call __mulsi3 +; RV32I-NEXT: slli a1, a0, 8 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: slli a1, a0, 16 +; RV32I-NEXT: add a0, a0, a1 ; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32I-NEXT: addi sp, sp, 16 ; RV32I-NEXT: ret ; ; RV64I-LABEL: test_ctpop_i32: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: srli a1, a0, 1 ; RV64I-NEXT: lui a2, 349525 ; RV64I-NEXT: addiw a2, a2, 1365 @@ -2508,14 +2447,13 @@ define i32 @test_ctpop_i32(i32 %a) nounwind { ; RV64I-NEXT: srli a1, a0, 4 ; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: lui a1, 61681 -; RV64I-NEXT: addiw a1, a1, -241 +; RV64I-NEXT: addi a1, a1, -241 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srliw a0, a0, 24 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret ; ; RV32M-LABEL: test_ctpop_i32: @@ -2578,8 +2516,6 @@ define i32 @test_ctpop_i32(i32 %a) nounwind { ; ; RV32XTHEADBB-LABEL: test_ctpop_i32: ; RV32XTHEADBB: # %bb.0: -; RV32XTHEADBB-NEXT: addi sp, sp, -16 -; RV32XTHEADBB-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32XTHEADBB-NEXT: srli a1, a0, 1 ; RV32XTHEADBB-NEXT: lui a2, 349525 ; RV32XTHEADBB-NEXT: addi a2, a2, 1365 @@ -2596,18 +2532,15 @@ define i32 @test_ctpop_i32(i32 %a) nounwind { ; RV32XTHEADBB-NEXT: lui a1, 61681 ; RV32XTHEADBB-NEXT: addi a1, a1, -241 ; RV32XTHEADBB-NEXT: and a0, a0, a1 -; RV32XTHEADBB-NEXT: lui a1, 4112 -; RV32XTHEADBB-NEXT: addi a1, a1, 257 -; RV32XTHEADBB-NEXT: call __mulsi3 +; RV32XTHEADBB-NEXT: slli a1, a0, 8 +; RV32XTHEADBB-NEXT: add a0, a0, a1 +; RV32XTHEADBB-NEXT: slli a1, a0, 16 +; RV32XTHEADBB-NEXT: add a0, a0, a1 ; RV32XTHEADBB-NEXT: srli a0, a0, 24 -; RV32XTHEADBB-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32XTHEADBB-NEXT: addi sp, sp, 16 ; RV32XTHEADBB-NEXT: ret ; ; RV64XTHEADBB-LABEL: test_ctpop_i32: ; RV64XTHEADBB: # %bb.0: -; RV64XTHEADBB-NEXT: addi sp, sp, -16 -; RV64XTHEADBB-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64XTHEADBB-NEXT: srli a1, a0, 1 ; RV64XTHEADBB-NEXT: lui a2, 349525 ; RV64XTHEADBB-NEXT: addiw a2, a2, 1365 @@ -2622,14 +2555,13 @@ define i32 @test_ctpop_i32(i32 %a) nounwind { ; RV64XTHEADBB-NEXT: srli a1, a0, 4 ; RV64XTHEADBB-NEXT: add a0, a0, a1 ; RV64XTHEADBB-NEXT: lui a1, 61681 -; RV64XTHEADBB-NEXT: addiw a1, a1, -241 +; RV64XTHEADBB-NEXT: addi a1, a1, -241 ; RV64XTHEADBB-NEXT: and a0, a0, a1 -; RV64XTHEADBB-NEXT: lui a1, 4112 -; RV64XTHEADBB-NEXT: addiw a1, a1, 257 -; RV64XTHEADBB-NEXT: call __muldi3 +; RV64XTHEADBB-NEXT: slli a1, a0, 8 +; RV64XTHEADBB-NEXT: add a0, a0, a1 +; RV64XTHEADBB-NEXT: slli a1, a0, 16 +; RV64XTHEADBB-NEXT: add a0, a0, a1 ; RV64XTHEADBB-NEXT: srliw a0, a0, 24 -; RV64XTHEADBB-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64XTHEADBB-NEXT: addi sp, sp, 16 ; RV64XTHEADBB-NEXT: ret %1 = call i32 @llvm.ctpop.i32(i32 %a) ret i32 %1 @@ -2638,65 +2570,48 @@ define i32 @test_ctpop_i32(i32 %a) nounwind { define i64 @test_ctpop_i64(i64 %a) nounwind { ; RV32I-LABEL: test_ctpop_i64: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -32 -; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s4, 8(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s5, 4(sp) # 4-byte Folded Spill -; RV32I-NEXT: mv s0, a0 -; RV32I-NEXT: srli a0, a1, 1 -; RV32I-NEXT: lui a2, 349525 -; RV32I-NEXT: addi s2, a2, 1365 -; RV32I-NEXT: and a0, a0, s2 -; RV32I-NEXT: sub a1, a1, a0 -; RV32I-NEXT: lui a0, 209715 -; RV32I-NEXT: addi s3, a0, 819 -; RV32I-NEXT: and a0, a1, s3 +; RV32I-NEXT: srli a2, a1, 1 +; RV32I-NEXT: lui a3, 349525 +; RV32I-NEXT: addi a3, a3, 1365 +; RV32I-NEXT: and a2, a2, a3 +; RV32I-NEXT: sub a1, a1, a2 +; RV32I-NEXT: lui a2, 209715 +; RV32I-NEXT: addi a2, a2, 819 +; RV32I-NEXT: and a4, a1, a2 ; RV32I-NEXT: srli a1, a1, 2 -; RV32I-NEXT: and a1, a1, s3 -; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: srli a1, a0, 4 -; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: lui a1, 61681 -; RV32I-NEXT: addi s4, a1, -241 -; RV32I-NEXT: and a0, a0, s4 -; RV32I-NEXT: lui a1, 4112 -; RV32I-NEXT: addi s1, a1, 257 -; RV32I-NEXT: mv a1, s1 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: srli s5, a0, 24 -; RV32I-NEXT: srli a0, s0, 1 -; RV32I-NEXT: and a0, a0, s2 -; RV32I-NEXT: sub s0, s0, a0 -; RV32I-NEXT: and a0, s0, s3 -; RV32I-NEXT: srli s0, s0, 2 -; RV32I-NEXT: and a1, s0, s3 -; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: srli a1, a0, 4 -; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: and a0, a0, s4 -; RV32I-NEXT: mv a1, s1 -; RV32I-NEXT: call __mulsi3 +; RV32I-NEXT: and a1, a1, a2 +; RV32I-NEXT: add a1, a4, a1 +; RV32I-NEXT: srli a4, a1, 4 +; RV32I-NEXT: add a1, a1, a4 +; RV32I-NEXT: lui a4, 61681 +; RV32I-NEXT: addi a4, a4, -241 +; RV32I-NEXT: and a1, a1, a4 +; RV32I-NEXT: slli a5, a1, 8 +; RV32I-NEXT: add a1, a1, a5 +; RV32I-NEXT: slli a5, a1, 16 +; RV32I-NEXT: add a1, a1, a5 +; RV32I-NEXT: srli a1, a1, 24 +; RV32I-NEXT: srli a5, a0, 1 +; RV32I-NEXT: and a3, a5, a3 +; RV32I-NEXT: sub a0, a0, a3 +; RV32I-NEXT: and a3, a0, a2 +; RV32I-NEXT: srli a0, a0, 2 +; RV32I-NEXT: and a0, a0, a2 +; RV32I-NEXT: add a0, a3, a0 +; RV32I-NEXT: srli a2, a0, 4 +; RV32I-NEXT: add a0, a0, a2 +; RV32I-NEXT: and a0, a0, a4 +; RV32I-NEXT: slli a2, a0, 8 +; RV32I-NEXT: add a0, a0, a2 +; RV32I-NEXT: slli a2, a0, 16 +; RV32I-NEXT: add a0, a0, a2 ; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: add a0, a0, s5 +; RV32I-NEXT: add a0, a0, a1 ; RV32I-NEXT: li a1, 0 -; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s4, 8(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s5, 4(sp) # 4-byte Folded Reload -; RV32I-NEXT: addi sp, sp, 32 ; RV32I-NEXT: ret ; ; RV64I-LABEL: test_ctpop_i64: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: srli a1, a0, 1 ; RV64I-NEXT: lui a2, 349525 ; RV64I-NEXT: addiw a2, a2, 1365 @@ -2719,14 +2634,13 @@ define i64 @test_ctpop_i64(i64 %a) nounwind { ; RV64I-NEXT: slli a2, a1, 32 ; RV64I-NEXT: add a1, a1, a2 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: slli a2, a1, 32 -; RV64I-NEXT: add a1, a1, a2 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 32 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srli a0, a0, 56 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret ; ; RV32M-LABEL: test_ctpop_i64: @@ -2814,65 +2728,48 @@ define i64 @test_ctpop_i64(i64 %a) nounwind { ; ; RV32XTHEADBB-LABEL: test_ctpop_i64: ; RV32XTHEADBB: # %bb.0: -; RV32XTHEADBB-NEXT: addi sp, sp, -32 -; RV32XTHEADBB-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32XTHEADBB-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32XTHEADBB-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32XTHEADBB-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32XTHEADBB-NEXT: sw s3, 12(sp) # 4-byte Folded Spill -; RV32XTHEADBB-NEXT: sw s4, 8(sp) # 4-byte Folded Spill -; RV32XTHEADBB-NEXT: sw s5, 4(sp) # 4-byte Folded Spill -; RV32XTHEADBB-NEXT: mv s0, a0 -; RV32XTHEADBB-NEXT: srli a0, a1, 1 -; RV32XTHEADBB-NEXT: lui a2, 349525 -; RV32XTHEADBB-NEXT: addi s2, a2, 1365 -; RV32XTHEADBB-NEXT: and a0, a0, s2 -; RV32XTHEADBB-NEXT: sub a1, a1, a0 -; RV32XTHEADBB-NEXT: lui a0, 209715 -; RV32XTHEADBB-NEXT: addi s3, a0, 819 -; RV32XTHEADBB-NEXT: and a0, a1, s3 +; RV32XTHEADBB-NEXT: srli a2, a1, 1 +; RV32XTHEADBB-NEXT: lui a3, 349525 +; RV32XTHEADBB-NEXT: addi a3, a3, 1365 +; RV32XTHEADBB-NEXT: and a2, a2, a3 +; RV32XTHEADBB-NEXT: sub a1, a1, a2 +; RV32XTHEADBB-NEXT: lui a2, 209715 +; RV32XTHEADBB-NEXT: addi a2, a2, 819 +; RV32XTHEADBB-NEXT: and a4, a1, a2 ; RV32XTHEADBB-NEXT: srli a1, a1, 2 -; RV32XTHEADBB-NEXT: and a1, a1, s3 -; RV32XTHEADBB-NEXT: add a0, a0, a1 -; RV32XTHEADBB-NEXT: srli a1, a0, 4 -; RV32XTHEADBB-NEXT: add a0, a0, a1 -; RV32XTHEADBB-NEXT: lui a1, 61681 -; RV32XTHEADBB-NEXT: addi s4, a1, -241 -; RV32XTHEADBB-NEXT: and a0, a0, s4 -; RV32XTHEADBB-NEXT: lui a1, 4112 -; RV32XTHEADBB-NEXT: addi s1, a1, 257 -; RV32XTHEADBB-NEXT: mv a1, s1 -; RV32XTHEADBB-NEXT: call __mulsi3 -; RV32XTHEADBB-NEXT: srli s5, a0, 24 -; RV32XTHEADBB-NEXT: srli a0, s0, 1 -; RV32XTHEADBB-NEXT: and a0, a0, s2 -; RV32XTHEADBB-NEXT: sub s0, s0, a0 -; RV32XTHEADBB-NEXT: and a0, s0, s3 -; RV32XTHEADBB-NEXT: srli s0, s0, 2 -; RV32XTHEADBB-NEXT: and a1, s0, s3 -; RV32XTHEADBB-NEXT: add a0, a0, a1 -; RV32XTHEADBB-NEXT: srli a1, a0, 4 -; RV32XTHEADBB-NEXT: add a0, a0, a1 -; RV32XTHEADBB-NEXT: and a0, a0, s4 -; RV32XTHEADBB-NEXT: mv a1, s1 -; RV32XTHEADBB-NEXT: call __mulsi3 +; RV32XTHEADBB-NEXT: and a1, a1, a2 +; RV32XTHEADBB-NEXT: add a1, a4, a1 +; RV32XTHEADBB-NEXT: srli a4, a1, 4 +; RV32XTHEADBB-NEXT: add a1, a1, a4 +; RV32XTHEADBB-NEXT: lui a4, 61681 +; RV32XTHEADBB-NEXT: addi a4, a4, -241 +; RV32XTHEADBB-NEXT: and a1, a1, a4 +; RV32XTHEADBB-NEXT: slli a5, a1, 8 +; RV32XTHEADBB-NEXT: add a1, a1, a5 +; RV32XTHEADBB-NEXT: slli a5, a1, 16 +; RV32XTHEADBB-NEXT: add a1, a1, a5 +; RV32XTHEADBB-NEXT: srli a1, a1, 24 +; RV32XTHEADBB-NEXT: srli a5, a0, 1 +; RV32XTHEADBB-NEXT: and a3, a5, a3 +; RV32XTHEADBB-NEXT: sub a0, a0, a3 +; RV32XTHEADBB-NEXT: and a3, a0, a2 +; RV32XTHEADBB-NEXT: srli a0, a0, 2 +; RV32XTHEADBB-NEXT: and a0, a0, a2 +; RV32XTHEADBB-NEXT: add a0, a3, a0 +; RV32XTHEADBB-NEXT: srli a2, a0, 4 +; RV32XTHEADBB-NEXT: add a0, a0, a2 +; RV32XTHEADBB-NEXT: and a0, a0, a4 +; RV32XTHEADBB-NEXT: slli a2, a0, 8 +; RV32XTHEADBB-NEXT: add a0, a0, a2 +; RV32XTHEADBB-NEXT: slli a2, a0, 16 +; RV32XTHEADBB-NEXT: add a0, a0, a2 ; RV32XTHEADBB-NEXT: srli a0, a0, 24 -; RV32XTHEADBB-NEXT: add a0, a0, s5 +; RV32XTHEADBB-NEXT: add a0, a0, a1 ; RV32XTHEADBB-NEXT: li a1, 0 -; RV32XTHEADBB-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32XTHEADBB-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32XTHEADBB-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32XTHEADBB-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32XTHEADBB-NEXT: lw s3, 12(sp) # 4-byte Folded Reload -; RV32XTHEADBB-NEXT: lw s4, 8(sp) # 4-byte Folded Reload -; RV32XTHEADBB-NEXT: lw s5, 4(sp) # 4-byte Folded Reload -; RV32XTHEADBB-NEXT: addi sp, sp, 32 ; RV32XTHEADBB-NEXT: ret ; ; RV64XTHEADBB-LABEL: test_ctpop_i64: ; RV64XTHEADBB: # %bb.0: -; RV64XTHEADBB-NEXT: addi sp, sp, -16 -; RV64XTHEADBB-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64XTHEADBB-NEXT: srli a1, a0, 1 ; RV64XTHEADBB-NEXT: lui a2, 349525 ; RV64XTHEADBB-NEXT: addiw a2, a2, 1365 @@ -2895,14 +2792,13 @@ define i64 @test_ctpop_i64(i64 %a) nounwind { ; RV64XTHEADBB-NEXT: slli a2, a1, 32 ; RV64XTHEADBB-NEXT: add a1, a1, a2 ; RV64XTHEADBB-NEXT: and a0, a0, a1 -; RV64XTHEADBB-NEXT: lui a1, 4112 -; RV64XTHEADBB-NEXT: addiw a1, a1, 257 -; RV64XTHEADBB-NEXT: slli a2, a1, 32 -; RV64XTHEADBB-NEXT: add a1, a1, a2 -; RV64XTHEADBB-NEXT: call __muldi3 +; RV64XTHEADBB-NEXT: slli a1, a0, 8 +; RV64XTHEADBB-NEXT: add a0, a0, a1 +; RV64XTHEADBB-NEXT: slli a1, a0, 16 +; RV64XTHEADBB-NEXT: add a0, a0, a1 +; RV64XTHEADBB-NEXT: slli a1, a0, 32 +; RV64XTHEADBB-NEXT: add a0, a0, a1 ; RV64XTHEADBB-NEXT: srli a0, a0, 56 -; RV64XTHEADBB-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64XTHEADBB-NEXT: addi sp, sp, 16 ; RV64XTHEADBB-NEXT: ret %1 = call i64 @llvm.ctpop.i64(i64 %a) ret i64 %1 diff --git a/llvm/test/CodeGen/RISCV/ctz_zero_return_test.ll b/llvm/test/CodeGen/RISCV/ctz_zero_return_test.ll index adf614435b31d7695205b56b3c5c370488250195..9ae30e646fdbf7c669f66f474c12f91b298187cc 100644 --- a/llvm/test/CodeGen/RISCV/ctz_zero_return_test.ll +++ b/llvm/test/CodeGen/RISCV/ctz_zero_return_test.ll @@ -602,19 +602,16 @@ define signext i32 @ctlz(i64 %b) nounwind { ; ; RV32I-LABEL: ctlz: ; RV32I: # %bb.0: # %entry -; RV32I-NEXT: addi sp, sp, -32 -; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s4, 8(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s5, 4(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s6, 0(sp) # 4-byte Folded Spill -; RV32I-NEXT: mv s0, a1 -; RV32I-NEXT: mv s2, a0 -; RV32I-NEXT: srli a0, a1, 1 -; RV32I-NEXT: or a0, a1, a0 +; RV32I-NEXT: lui a2, 349525 +; RV32I-NEXT: addi a4, a2, 1365 +; RV32I-NEXT: lui a2, 209715 +; RV32I-NEXT: addi a3, a2, 819 +; RV32I-NEXT: lui a2, 61681 +; RV32I-NEXT: addi a2, a2, -241 +; RV32I-NEXT: bnez a1, .LBB7_2 +; RV32I-NEXT: # %bb.1: # %entry +; RV32I-NEXT: srli a1, a0, 1 +; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 2 ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 4 @@ -625,28 +622,26 @@ define signext i32 @ctlz(i64 %b) nounwind { ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: not a0, a0 ; RV32I-NEXT: srli a1, a0, 1 -; RV32I-NEXT: lui a2, 349525 -; RV32I-NEXT: addi s4, a2, 1365 -; RV32I-NEXT: and a1, a1, s4 +; RV32I-NEXT: and a1, a1, a4 ; RV32I-NEXT: sub a0, a0, a1 -; RV32I-NEXT: lui a1, 209715 -; RV32I-NEXT: addi s5, a1, 819 -; RV32I-NEXT: and a1, a0, s5 +; RV32I-NEXT: and a1, a0, a3 ; RV32I-NEXT: srli a0, a0, 2 -; RV32I-NEXT: and a0, a0, s5 +; RV32I-NEXT: and a0, a0, a3 ; RV32I-NEXT: add a0, a1, a0 ; RV32I-NEXT: srli a1, a0, 4 ; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: lui a1, 61681 -; RV32I-NEXT: addi s6, a1, -241 -; RV32I-NEXT: and a0, a0, s6 -; RV32I-NEXT: lui a1, 4112 -; RV32I-NEXT: addi s3, a1, 257 -; RV32I-NEXT: mv a1, s3 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: mv s1, a0 -; RV32I-NEXT: srli a0, s2, 1 -; RV32I-NEXT: or a0, s2, a0 +; RV32I-NEXT: and a0, a0, a2 +; RV32I-NEXT: slli a1, a0, 8 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: slli a1, a0, 16 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: srli a0, a0, 24 +; RV32I-NEXT: addi a0, a0, 32 +; RV32I-NEXT: andi a0, a0, 63 +; RV32I-NEXT: ret +; RV32I-NEXT: .LBB7_2: +; RV32I-NEXT: srli a0, a1, 1 +; RV32I-NEXT: or a0, a1, a0 ; RV32I-NEXT: srli a1, a0, 2 ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 4 @@ -657,41 +652,25 @@ define signext i32 @ctlz(i64 %b) nounwind { ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: not a0, a0 ; RV32I-NEXT: srli a1, a0, 1 -; RV32I-NEXT: and a1, a1, s4 +; RV32I-NEXT: and a1, a1, a4 ; RV32I-NEXT: sub a0, a0, a1 -; RV32I-NEXT: and a1, a0, s5 +; RV32I-NEXT: and a1, a0, a3 ; RV32I-NEXT: srli a0, a0, 2 -; RV32I-NEXT: and a0, a0, s5 +; RV32I-NEXT: and a0, a0, a3 ; RV32I-NEXT: add a0, a1, a0 ; RV32I-NEXT: srli a1, a0, 4 ; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: and a0, a0, s6 -; RV32I-NEXT: mv a1, s3 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: bnez s0, .LBB7_2 -; RV32I-NEXT: # %bb.1: # %entry +; RV32I-NEXT: and a0, a0, a2 +; RV32I-NEXT: slli a1, a0, 8 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: slli a1, a0, 16 +; RV32I-NEXT: add a0, a0, a1 ; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: addi s1, a0, 32 -; RV32I-NEXT: j .LBB7_3 -; RV32I-NEXT: .LBB7_2: -; RV32I-NEXT: srli s1, s1, 24 -; RV32I-NEXT: .LBB7_3: # %entry -; RV32I-NEXT: andi a0, s1, 63 -; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s4, 8(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s5, 4(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s6, 0(sp) # 4-byte Folded Reload -; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: andi a0, a0, 63 ; RV32I-NEXT: ret ; ; RV64I-LABEL: ctlz: ; RV64I: # %bb.0: # %entry -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: srli a1, a0, 1 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: srli a1, a0, 2 @@ -727,15 +706,14 @@ define signext i32 @ctlz(i64 %b) nounwind { ; RV64I-NEXT: slli a2, a1, 32 ; RV64I-NEXT: add a1, a1, a2 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: slli a2, a1, 32 -; RV64I-NEXT: add a1, a1, a2 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 32 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: slli a0, a0, 2 ; RV64I-NEXT: srli a0, a0, 58 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret diff --git a/llvm/test/CodeGen/RISCV/double-arith-strict.ll b/llvm/test/CodeGen/RISCV/double-arith-strict.ll index 186175537772b533436df3ed2966c408cde354c3..23336933abff98ee9d213fd4df1cc80fe6d0efe9 100644 --- a/llvm/test/CodeGen/RISCV/double-arith-strict.ll +++ b/llvm/test/CodeGen/RISCV/double-arith-strict.ll @@ -24,21 +24,7 @@ define double @fadd_d(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fadd_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fadd_d: @@ -76,21 +62,7 @@ define double @fsub_d(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fsub_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fsub.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fsub_d: @@ -128,21 +100,7 @@ define double @fmul_d(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fmul_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fmul.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fmul_d: @@ -180,21 +138,7 @@ define double @fdiv_d(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fdiv_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fdiv.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fdiv_d: @@ -232,17 +176,7 @@ define double @fsqrt_d(double %a) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fsqrt_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fsqrt.d a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fsqrt_d: @@ -398,25 +332,7 @@ define double @fmadd_d(double %a, double %b, double %c) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fmadd_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fmadd.d a0, a0, a2, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fmadd_d: @@ -463,27 +379,9 @@ define double @fmsub_d(double %a, double %b, double %c) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fmsub_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.d.w a6, zero ; RV32IZFINXZDINX-NEXT: fadd.d a4, a4, a6 ; RV32IZFINXZDINX-NEXT: fmsub.d a0, a0, a2, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fmsub_d: @@ -572,28 +470,10 @@ define double @fnmadd_d(double %a, double %b, double %c) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fnmadd_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.d.w a6, zero ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, a6 ; RV32IZFINXZDINX-NEXT: fadd.d a4, a4, a6 ; RV32IZFINXZDINX-NEXT: fnmadd.d a0, a0, a2, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fnmadd_d: @@ -701,28 +581,10 @@ define double @fnmadd_d_2(double %a, double %b, double %c) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fnmadd_d_2: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.d.w a6, zero ; RV32IZFINXZDINX-NEXT: fadd.d a2, a2, a6 ; RV32IZFINXZDINX-NEXT: fadd.d a4, a4, a6 ; RV32IZFINXZDINX-NEXT: fnmadd.d a0, a2, a0, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fnmadd_d_2: @@ -829,27 +691,9 @@ define double @fnmsub_d(double %a, double %b, double %c) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fnmsub_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.d.w a6, zero ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, a6 ; RV32IZFINXZDINX-NEXT: fnmsub.d a0, a0, a2, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fnmsub_d: @@ -932,27 +776,9 @@ define double @fnmsub_d_2(double %a, double %b, double %c) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fnmsub_d_2: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.d.w a6, zero ; RV32IZFINXZDINX-NEXT: fadd.d a2, a2, a6 ; RV32IZFINXZDINX-NEXT: fnmsub.d a0, a2, a0, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fnmsub_d_2: diff --git a/llvm/test/CodeGen/RISCV/double-arith.ll b/llvm/test/CodeGen/RISCV/double-arith.ll index 82ddf06187d383f35e0d116e435049d52fac8051..a2093f5b5e43ad296430d1640247c8b03453ffc2 100644 --- a/llvm/test/CodeGen/RISCV/double-arith.ll +++ b/llvm/test/CodeGen/RISCV/double-arith.ll @@ -25,21 +25,7 @@ define double @fadd_d(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fadd_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fadd_d: @@ -76,21 +62,7 @@ define double @fsub_d(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fsub_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fsub.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fsub_d: @@ -127,21 +99,7 @@ define double @fmul_d(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fmul_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fmul.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fmul_d: @@ -178,21 +136,7 @@ define double @fdiv_d(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fdiv_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fdiv.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fdiv_d: @@ -231,17 +175,7 @@ define double @fsqrt_d(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fsqrt_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fsqrt.d a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fsqrt_d: @@ -280,21 +214,7 @@ define double @fsgnj_d(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fsgnj_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fsgnj.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fsgnj_d: @@ -335,15 +255,9 @@ define i32 @fneg_d(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fneg_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: fneg.d a2, a0 ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fneg_d: @@ -401,21 +315,7 @@ define double @fsgnjn_d(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fsgnjn_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fsgnjn.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fsgnjn_d: @@ -464,23 +364,9 @@ define double @fabs_d(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fabs_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, a2 ; RV32IZFINXZDINX-NEXT: fabs.d a2, a0 ; RV32IZFINXZDINX-NEXT: fadd.d a0, a2, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fabs_d: @@ -532,21 +418,7 @@ define double @fmin_d(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fmin_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fmin.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fmin_d: @@ -585,21 +457,7 @@ define double @fmax_d(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fmax_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fmax.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fmax_d: @@ -638,25 +496,7 @@ define double @fmadd_d(double %a, double %b, double %c) nounwind { ; ; RV32IZFINXZDINX-LABEL: fmadd_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fmadd.d a0, a0, a2, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fmadd_d: @@ -702,27 +542,9 @@ define double @fmsub_d(double %a, double %b, double %c) nounwind { ; ; RV32IZFINXZDINX-LABEL: fmsub_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.d.w a6, zero ; RV32IZFINXZDINX-NEXT: fadd.d a4, a4, a6 ; RV32IZFINXZDINX-NEXT: fmsub.d a0, a0, a2, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fmsub_d: @@ -811,28 +633,10 @@ define double @fnmadd_d(double %a, double %b, double %c) nounwind { ; ; RV32IZFINXZDINX-LABEL: fnmadd_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.d.w a6, zero ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, a6 ; RV32IZFINXZDINX-NEXT: fadd.d a4, a4, a6 ; RV32IZFINXZDINX-NEXT: fnmadd.d a0, a0, a2, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fnmadd_d: @@ -940,28 +744,10 @@ define double @fnmadd_d_2(double %a, double %b, double %c) nounwind { ; ; RV32IZFINXZDINX-LABEL: fnmadd_d_2: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.d.w a6, zero ; RV32IZFINXZDINX-NEXT: fadd.d a2, a2, a6 ; RV32IZFINXZDINX-NEXT: fadd.d a4, a4, a6 ; RV32IZFINXZDINX-NEXT: fnmadd.d a0, a2, a0, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fnmadd_d_2: @@ -1060,27 +846,9 @@ define double @fnmadd_d_3(double %a, double %b, double %c) nounwind { ; ; RV32IZFINXZDINX-LABEL: fnmadd_d_3: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fmadd.d a0, a0, a2, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) ; RV32IZFINXZDINX-NEXT: lui a2, 524288 ; RV32IZFINXZDINX-NEXT: xor a1, a1, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fnmadd_d_3: @@ -1127,27 +895,9 @@ define double @fnmadd_nsz(double %a, double %b, double %c) nounwind { ; ; RV32IZFINXZDINX-LABEL: fnmadd_nsz: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fmadd.d a0, a0, a2, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) ; RV32IZFINXZDINX-NEXT: lui a2, 524288 ; RV32IZFINXZDINX-NEXT: xor a1, a1, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fnmadd_nsz: @@ -1202,27 +952,9 @@ define double @fnmsub_d(double %a, double %b, double %c) nounwind { ; ; RV32IZFINXZDINX-LABEL: fnmsub_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.d.w a6, zero ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, a6 ; RV32IZFINXZDINX-NEXT: fnmsub.d a0, a0, a2, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fnmsub_d: @@ -1305,27 +1037,9 @@ define double @fnmsub_d_2(double %a, double %b, double %c) nounwind { ; ; RV32IZFINXZDINX-LABEL: fnmsub_d_2: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.d.w a6, zero ; RV32IZFINXZDINX-NEXT: fadd.d a2, a2, a6 ; RV32IZFINXZDINX-NEXT: fnmsub.d a0, a2, a0, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fnmsub_d_2: @@ -1403,25 +1117,7 @@ define double @fmadd_d_contract(double %a, double %b, double %c) nounwind { ; ; RV32IZFINXZDINX-LABEL: fmadd_d_contract: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fmadd.d a0, a0, a2, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fmadd_d_contract: @@ -1482,27 +1178,9 @@ define double @fmsub_d_contract(double %a, double %b, double %c) nounwind { ; ; RV32IZFINXZDINX-LABEL: fmsub_d_contract: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.d.w a6, zero ; RV32IZFINXZDINX-NEXT: fadd.d a4, a4, a6 ; RV32IZFINXZDINX-NEXT: fmsub.d a0, a0, a2, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fmsub_d_contract: @@ -1601,29 +1279,11 @@ define double @fnmadd_d_contract(double %a, double %b, double %c) nounwind { ; ; RV32IZFINXZDINX-LABEL: fnmadd_d_contract: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.d.w a6, zero ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, a6 ; RV32IZFINXZDINX-NEXT: fadd.d a2, a2, a6 ; RV32IZFINXZDINX-NEXT: fadd.d a4, a4, a6 ; RV32IZFINXZDINX-NEXT: fnmadd.d a0, a0, a2, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fnmadd_d_contract: @@ -1749,28 +1409,10 @@ define double @fnmsub_d_contract(double %a, double %b, double %c) nounwind { ; ; RV32IZFINXZDINX-LABEL: fnmsub_d_contract: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.d.w a6, zero ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, a6 ; RV32IZFINXZDINX-NEXT: fadd.d a2, a2, a6 ; RV32IZFINXZDINX-NEXT: fnmsub.d a0, a0, a2, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fnmsub_d_contract: diff --git a/llvm/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll b/llvm/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll index 55bf95a126ac1869d8c1cd540af461167fefa670..99835ff59493fdc8cdf05556f076be3a86336318 100644 --- a/llvm/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll +++ b/llvm/test/CodeGen/RISCV/double-bitmanip-dagcombines.ll @@ -141,21 +141,7 @@ define double @fcopysign_fneg(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcopysign_fneg: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fsgnjn.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64I-LABEL: fcopysign_fneg: diff --git a/llvm/test/CodeGen/RISCV/double-br-fcmp.ll b/llvm/test/CodeGen/RISCV/double-br-fcmp.ll index 2c5505edb1fa2aa8455bfe81cf4016e5577b8cb9..035228e73c707148cab6a9e669b35be68ca5060d 100644 --- a/llvm/test/CodeGen/RISCV/double-br-fcmp.ll +++ b/llvm/test/CodeGen/RISCV/double-br-fcmp.ll @@ -89,23 +89,13 @@ define void @br_fcmp_oeq(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: br_fcmp_oeq: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a2 ; RV32IZFINXZDINX-NEXT: bnez a0, .LBB1_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: # %if.else -; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; RV32IZFINXZDINX-NEXT: .LBB1_2: # %if.then +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call abort ; ; RV64IZFINXZDINX-LABEL: br_fcmp_oeq: @@ -155,23 +145,13 @@ define void @br_fcmp_oeq_alt(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: br_fcmp_oeq_alt: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a2 ; RV32IZFINXZDINX-NEXT: bnez a0, .LBB2_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: # %if.else -; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; RV32IZFINXZDINX-NEXT: .LBB2_2: # %if.then +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call abort ; ; RV64IZFINXZDINX-LABEL: br_fcmp_oeq_alt: @@ -218,23 +198,13 @@ define void @br_fcmp_ogt(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: br_fcmp_ogt: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 4(sp) ; RV32IZFINXZDINX-NEXT: flt.d a0, a2, a0 ; RV32IZFINXZDINX-NEXT: bnez a0, .LBB3_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: # %if.else -; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; RV32IZFINXZDINX-NEXT: .LBB3_2: # %if.then +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call abort ; ; RV64IZFINXZDINX-LABEL: br_fcmp_ogt: @@ -281,23 +251,13 @@ define void @br_fcmp_oge(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: br_fcmp_oge: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 4(sp) ; RV32IZFINXZDINX-NEXT: fle.d a0, a2, a0 ; RV32IZFINXZDINX-NEXT: bnez a0, .LBB4_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: # %if.else -; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; RV32IZFINXZDINX-NEXT: .LBB4_2: # %if.then +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call abort ; ; RV64IZFINXZDINX-LABEL: br_fcmp_oge: @@ -344,23 +304,13 @@ define void @br_fcmp_olt(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: br_fcmp_olt: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) ; RV32IZFINXZDINX-NEXT: flt.d a0, a0, a2 ; RV32IZFINXZDINX-NEXT: bnez a0, .LBB5_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: # %if.else -; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; RV32IZFINXZDINX-NEXT: .LBB5_2: # %if.then +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call abort ; ; RV64IZFINXZDINX-LABEL: br_fcmp_olt: @@ -407,23 +357,13 @@ define void @br_fcmp_ole(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: br_fcmp_ole: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) ; RV32IZFINXZDINX-NEXT: fle.d a0, a0, a2 ; RV32IZFINXZDINX-NEXT: bnez a0, .LBB6_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: # %if.else -; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; RV32IZFINXZDINX-NEXT: .LBB6_2: # %if.then +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call abort ; ; RV64IZFINXZDINX-LABEL: br_fcmp_ole: @@ -474,25 +414,15 @@ define void @br_fcmp_one(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: br_fcmp_one: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) ; RV32IZFINXZDINX-NEXT: flt.d a4, a0, a2 ; RV32IZFINXZDINX-NEXT: flt.d a0, a2, a0 ; RV32IZFINXZDINX-NEXT: or a0, a0, a4 ; RV32IZFINXZDINX-NEXT: bnez a0, .LBB7_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: # %if.else -; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; RV32IZFINXZDINX-NEXT: .LBB7_2: # %if.then +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call abort ; ; RV64IZFINXZDINX-LABEL: br_fcmp_one: @@ -545,25 +475,15 @@ define void @br_fcmp_ord(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: br_fcmp_ord: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 4(sp) ; RV32IZFINXZDINX-NEXT: feq.d a2, a2, a2 ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 ; RV32IZFINXZDINX-NEXT: bnez a0, .LBB8_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: # %if.else -; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; RV32IZFINXZDINX-NEXT: .LBB8_2: # %if.then +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call abort ; ; RV64IZFINXZDINX-LABEL: br_fcmp_ord: @@ -616,25 +536,15 @@ define void @br_fcmp_ueq(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: br_fcmp_ueq: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) ; RV32IZFINXZDINX-NEXT: flt.d a4, a0, a2 ; RV32IZFINXZDINX-NEXT: flt.d a0, a2, a0 ; RV32IZFINXZDINX-NEXT: or a0, a0, a4 ; RV32IZFINXZDINX-NEXT: beqz a0, .LBB9_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: # %if.else -; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; RV32IZFINXZDINX-NEXT: .LBB9_2: # %if.then +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call abort ; ; RV64IZFINXZDINX-LABEL: br_fcmp_ueq: @@ -683,23 +593,13 @@ define void @br_fcmp_ugt(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: br_fcmp_ugt: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) ; RV32IZFINXZDINX-NEXT: fle.d a0, a0, a2 ; RV32IZFINXZDINX-NEXT: beqz a0, .LBB10_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: # %if.else -; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; RV32IZFINXZDINX-NEXT: .LBB10_2: # %if.then +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call abort ; ; RV64IZFINXZDINX-LABEL: br_fcmp_ugt: @@ -746,23 +646,13 @@ define void @br_fcmp_uge(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: br_fcmp_uge: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) ; RV32IZFINXZDINX-NEXT: flt.d a0, a0, a2 ; RV32IZFINXZDINX-NEXT: beqz a0, .LBB11_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: # %if.else -; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; RV32IZFINXZDINX-NEXT: .LBB11_2: # %if.then +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call abort ; ; RV64IZFINXZDINX-LABEL: br_fcmp_uge: @@ -809,23 +699,13 @@ define void @br_fcmp_ult(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: br_fcmp_ult: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 4(sp) ; RV32IZFINXZDINX-NEXT: fle.d a0, a2, a0 ; RV32IZFINXZDINX-NEXT: beqz a0, .LBB12_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: # %if.else -; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; RV32IZFINXZDINX-NEXT: .LBB12_2: # %if.then +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call abort ; ; RV64IZFINXZDINX-LABEL: br_fcmp_ult: @@ -872,23 +752,13 @@ define void @br_fcmp_ule(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: br_fcmp_ule: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 4(sp) ; RV32IZFINXZDINX-NEXT: flt.d a0, a2, a0 ; RV32IZFINXZDINX-NEXT: beqz a0, .LBB13_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: # %if.else -; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; RV32IZFINXZDINX-NEXT: .LBB13_2: # %if.then +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call abort ; ; RV64IZFINXZDINX-LABEL: br_fcmp_ule: @@ -935,23 +805,13 @@ define void @br_fcmp_une(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: br_fcmp_une: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a2 ; RV32IZFINXZDINX-NEXT: beqz a0, .LBB14_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: # %if.else -; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; RV32IZFINXZDINX-NEXT: .LBB14_2: # %if.then +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call abort ; ; RV64IZFINXZDINX-LABEL: br_fcmp_une: @@ -1002,25 +862,15 @@ define void @br_fcmp_uno(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: br_fcmp_uno: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 4(sp) ; RV32IZFINXZDINX-NEXT: feq.d a2, a2, a2 ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 ; RV32IZFINXZDINX-NEXT: beqz a0, .LBB15_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: # %if.else -; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; RV32IZFINXZDINX-NEXT: .LBB15_2: # %if.then +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call abort ; ; RV64IZFINXZDINX-LABEL: br_fcmp_uno: diff --git a/llvm/test/CodeGen/RISCV/double-calling-conv.ll b/llvm/test/CodeGen/RISCV/double-calling-conv.ll index d46256b12052e0801f6719820258e1f0a02e90c2..57aaa4c9f74e46b5a3337637248d506faedae1c6 100644 --- a/llvm/test/CodeGen/RISCV/double-calling-conv.ll +++ b/llvm/test/CodeGen/RISCV/double-calling-conv.ll @@ -28,21 +28,7 @@ define double @callee_double_inreg(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: callee_double_inreg: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret %1 = fadd double %a, %b ret double %1 @@ -106,22 +92,11 @@ define double @callee_double_split_reg_stack(i32 %a, i64 %b, i64 %c, double %d, ; ; RV32IZFINXZDINX-LABEL: callee_double_split_reg_stack: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: lw a0, 16(sp) -; RV32IZFINXZDINX-NEXT: sw a7, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a6, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) +; RV32IZFINXZDINX-NEXT: mv a0, a7 +; RV32IZFINXZDINX-NEXT: lw a1, 0(sp) +; RV32IZFINXZDINX-NEXT: mv a3, a6 +; RV32IZFINXZDINX-NEXT: mv a2, a5 ; RV32IZFINXZDINX-NEXT: fadd.d a0, a2, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret %1 = fadd double %d, %e ret double %1 @@ -190,17 +165,11 @@ define double @callee_double_stack(i64 %a, i64 %b, i64 %c, i64 %d, double %e, do ; ; RV32IZFINXZDINX-LABEL: callee_double_stack: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: lw a0, 24(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 28(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 16(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 20(sp) -; RV32IZFINXZDINX-NEXT: fadd.d a0, a2, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) ; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 +; RV32IZFINXZDINX-NEXT: lw a2, 0(sp) +; RV32IZFINXZDINX-NEXT: lw a3, 4(sp) +; RV32IZFINXZDINX-NEXT: fadd.d a0, a2, a0 ; RV32IZFINXZDINX-NEXT: ret %1 = fadd double %e, %f ret double %1 diff --git a/llvm/test/CodeGen/RISCV/double-convert-strict.ll b/llvm/test/CodeGen/RISCV/double-convert-strict.ll index 967b119581af1a920c7d44fe8616e8697975346f..13bcafb5ebd136176cfd87564efe379bacf93fa7 100644 --- a/llvm/test/CodeGen/RISCV/double-convert-strict.ll +++ b/llvm/test/CodeGen/RISCV/double-convert-strict.ll @@ -28,13 +28,7 @@ define float @fcvt_s_d(double %a) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcvt_s_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.s.d a0, a0 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_s_d: @@ -72,13 +66,7 @@ define double @fcvt_d_s(float %a) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcvt_d_s: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: fcvt.d.s a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_d_s: @@ -116,13 +104,7 @@ define i32 @fcvt_w_d(double %a) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcvt_w_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rtz -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_w_d: @@ -162,13 +144,7 @@ define i32 @fcvt_wu_d(double %a) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcvt_wu_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rtz -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_wu_d: @@ -210,15 +186,9 @@ define i32 @fcvt_wu_d_multiple_use(double %x, ptr %y) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcvt_wu_d_multiple_use: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rtz ; RV32IZFINXZDINX-NEXT: seqz a1, a0 ; RV32IZFINXZDINX-NEXT: add a0, a0, a1 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_wu_d_multiple_use: @@ -263,13 +233,7 @@ define double @fcvt_d_w(i32 %a) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcvt_d_w: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: fcvt.d.w a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_d_w: @@ -309,14 +273,8 @@ define double @fcvt_d_w_load(ptr %p) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcvt_d_w_load: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: lw a0, 0(a0) ; RV32IZFINXZDINX-NEXT: fcvt.d.w a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_d_w_load: @@ -357,13 +315,7 @@ define double @fcvt_d_wu(i32 %a) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcvt_d_wu: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: fcvt.d.wu a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_d_wu: @@ -409,14 +361,8 @@ define double @fcvt_d_wu_load(ptr %p) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcvt_d_wu_load: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: lw a0, 0(a0) ; RV32IZFINXZDINX-NEXT: fcvt.d.wu a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_d_wu_load: @@ -661,13 +607,7 @@ define double @fcvt_d_w_i8(i8 signext %a) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcvt_d_w_i8: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: fcvt.d.w a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_d_w_i8: @@ -705,13 +645,7 @@ define double @fcvt_d_wu_i8(i8 zeroext %a) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcvt_d_wu_i8: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: fcvt.d.wu a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_d_wu_i8: @@ -749,13 +683,7 @@ define double @fcvt_d_w_i16(i16 signext %a) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcvt_d_w_i16: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: fcvt.d.w a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_d_w_i16: @@ -793,13 +721,7 @@ define double @fcvt_d_wu_i16(i16 zeroext %a) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcvt_d_wu_i16: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: fcvt.d.wu a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_d_wu_i16: diff --git a/llvm/test/CodeGen/RISCV/double-convert.ll b/llvm/test/CodeGen/RISCV/double-convert.ll index 3700a18bafc61270076561f5055c86e149d1f75f..da882cafd99715fdb2cd3c2fc85f34d4e9e447eb 100644 --- a/llvm/test/CodeGen/RISCV/double-convert.ll +++ b/llvm/test/CodeGen/RISCV/double-convert.ll @@ -20,13 +20,7 @@ define float @fcvt_s_d(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_s_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.s.d a0, a0 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_s_d: @@ -63,13 +57,7 @@ define double @fcvt_d_s(float %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_d_s: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: fcvt.d.s a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_d_s: @@ -106,13 +94,7 @@ define i32 @fcvt_w_d(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_w_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rtz -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_w_d: @@ -153,17 +135,11 @@ define i32 @fcvt_w_d_sat(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_w_d_sat: ; RV32IZFINXZDINX: # %bb.0: # %start -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a2, a0, rtz ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: seqz a0, a0 ; RV32IZFINXZDINX-NEXT: addi a0, a0, -1 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_w_d_sat: @@ -287,13 +263,7 @@ define i32 @fcvt_wu_d(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_wu_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rtz -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_wu_d: @@ -334,15 +304,9 @@ define i32 @fcvt_wu_d_multiple_use(double %x, ptr %y) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_wu_d_multiple_use: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rtz ; RV32IZFINXZDINX-NEXT: seqz a1, a0 ; RV32IZFINXZDINX-NEXT: add a0, a0, a1 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_wu_d_multiple_use: @@ -402,17 +366,11 @@ define i32 @fcvt_wu_d_sat(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_wu_d_sat: ; RV32IZFINXZDINX: # %bb.0: # %start -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a2, a0, rtz ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: seqz a0, a0 ; RV32IZFINXZDINX-NEXT: addi a0, a0, -1 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_wu_d_sat: @@ -512,13 +470,7 @@ define double @fcvt_d_w(i32 %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_d_w: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: fcvt.d.w a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_d_w: @@ -557,14 +509,8 @@ define double @fcvt_d_w_load(ptr %p) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_d_w_load: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: lw a0, 0(a0) ; RV32IZFINXZDINX-NEXT: fcvt.d.w a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_d_w_load: @@ -605,13 +551,7 @@ define double @fcvt_d_wu(i32 %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_d_wu: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: fcvt.d.wu a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_d_wu: @@ -656,14 +596,8 @@ define double @fcvt_d_wu_load(ptr %p) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_d_wu_load: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: lw a0, 0(a0) ; RV32IZFINXZDINX-NEXT: fcvt.d.wu a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_d_wu_load: @@ -749,47 +683,41 @@ define i64 @fcvt_l_d(double %a) nounwind { define i64 @fcvt_l_d_sat(double %a) nounwind { ; RV32IFD-LABEL: fcvt_l_d_sat: ; RV32IFD: # %bb.0: # %start -; RV32IFD-NEXT: addi sp, sp, -32 -; RV32IFD-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s3, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: sw s0, 8(sp) # 4-byte Folded Spill ; RV32IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill ; RV32IFD-NEXT: lui a0, %hi(.LCPI12_0) ; RV32IFD-NEXT: fld fa5, %lo(.LCPI12_0)(a0) -; RV32IFD-NEXT: lui a0, %hi(.LCPI12_1) -; RV32IFD-NEXT: fld fa4, %lo(.LCPI12_1)(a0) ; RV32IFD-NEXT: fmv.d fs0, fa0 -; RV32IFD-NEXT: flt.d s0, fa5, fa0 -; RV32IFD-NEXT: neg s1, s0 -; RV32IFD-NEXT: fle.d s2, fa4, fa0 -; RV32IFD-NEXT: neg s3, s2 +; RV32IFD-NEXT: fle.d s0, fa5, fa0 ; RV32IFD-NEXT: call __fixdfdi -; RV32IFD-NEXT: and a0, s3, a0 -; RV32IFD-NEXT: or a0, s1, a0 -; RV32IFD-NEXT: feq.d a2, fs0, fs0 -; RV32IFD-NEXT: neg a2, a2 -; RV32IFD-NEXT: lui a4, 524288 -; RV32IFD-NEXT: li a5, 1 ; RV32IFD-NEXT: lui a3, 524288 -; RV32IFD-NEXT: bne s2, a5, .LBB12_2 +; RV32IFD-NEXT: li a4, 1 +; RV32IFD-NEXT: lui a2, 524288 +; RV32IFD-NEXT: bne s0, a4, .LBB12_2 ; RV32IFD-NEXT: # %bb.1: # %start -; RV32IFD-NEXT: mv a3, a1 +; RV32IFD-NEXT: mv a2, a1 ; RV32IFD-NEXT: .LBB12_2: # %start -; RV32IFD-NEXT: and a0, a2, a0 -; RV32IFD-NEXT: beqz s0, .LBB12_4 +; RV32IFD-NEXT: lui a1, %hi(.LCPI12_1) +; RV32IFD-NEXT: fld fa5, %lo(.LCPI12_1)(a1) +; RV32IFD-NEXT: flt.d a4, fa5, fs0 +; RV32IFD-NEXT: beqz a4, .LBB12_4 ; RV32IFD-NEXT: # %bb.3: -; RV32IFD-NEXT: addi a3, a4, -1 +; RV32IFD-NEXT: addi a2, a3, -1 ; RV32IFD-NEXT: .LBB12_4: # %start -; RV32IFD-NEXT: and a1, a2, a3 -; RV32IFD-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s3, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: feq.d a1, fs0, fs0 +; RV32IFD-NEXT: neg a3, a1 +; RV32IFD-NEXT: and a1, a3, a2 +; RV32IFD-NEXT: neg a2, a4 +; RV32IFD-NEXT: neg a4, s0 +; RV32IFD-NEXT: and a0, a4, a0 +; RV32IFD-NEXT: or a0, a2, a0 +; RV32IFD-NEXT: and a0, a3, a0 +; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload -; RV32IFD-NEXT: addi sp, sp, 32 +; RV32IFD-NEXT: addi sp, sp, 16 ; RV32IFD-NEXT: ret ; ; RV64IFD-LABEL: fcvt_l_d_sat: @@ -803,50 +731,44 @@ define i64 @fcvt_l_d_sat(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_l_d_sat: ; RV32IZFINXZDINX: # %bb.0: # %start -; RV32IZFINXZDINX-NEXT: addi sp, sp, -32 -; RV32IZFINXZDINX-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s3, 12(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw s0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s1, 4(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: mv s1, a1 +; RV32IZFINXZDINX-NEXT: mv s0, a0 +; RV32IZFINXZDINX-NEXT: call __fixdfdi ; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI12_0) ; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI12_0+4)(a2) ; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI12_0)(a2) -; RV32IZFINXZDINX-NEXT: fle.d s2, a2, s0 -; RV32IZFINXZDINX-NEXT: neg s3, s2 -; RV32IZFINXZDINX-NEXT: call __fixdfdi -; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI12_1) -; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI12_1+4)(a2) -; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI12_1)(a2) -; RV32IZFINXZDINX-NEXT: and a0, s3, a0 -; RV32IZFINXZDINX-NEXT: flt.d a3, a2, s0 -; RV32IZFINXZDINX-NEXT: neg a2, a3 -; RV32IZFINXZDINX-NEXT: or a0, a2, a0 -; RV32IZFINXZDINX-NEXT: feq.d a2, s0, s0 -; RV32IZFINXZDINX-NEXT: neg a2, a2 +; RV32IZFINXZDINX-NEXT: fle.d a2, a2, s0 ; RV32IZFINXZDINX-NEXT: lui a5, 524288 -; RV32IZFINXZDINX-NEXT: li a6, 1 -; RV32IZFINXZDINX-NEXT: lui a4, 524288 -; RV32IZFINXZDINX-NEXT: bne s2, a6, .LBB12_2 +; RV32IZFINXZDINX-NEXT: li a4, 1 +; RV32IZFINXZDINX-NEXT: lui a3, 524288 +; RV32IZFINXZDINX-NEXT: bne a2, a4, .LBB12_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: # %start -; RV32IZFINXZDINX-NEXT: mv a4, a1 +; RV32IZFINXZDINX-NEXT: mv a3, a1 ; RV32IZFINXZDINX-NEXT: .LBB12_2: # %start -; RV32IZFINXZDINX-NEXT: and a0, a2, a0 -; RV32IZFINXZDINX-NEXT: beqz a3, .LBB12_4 +; RV32IZFINXZDINX-NEXT: lui a1, %hi(.LCPI12_1) +; RV32IZFINXZDINX-NEXT: lw a6, %lo(.LCPI12_1)(a1) +; RV32IZFINXZDINX-NEXT: lw a7, %lo(.LCPI12_1+4)(a1) +; RV32IZFINXZDINX-NEXT: flt.d a4, a6, s0 +; RV32IZFINXZDINX-NEXT: beqz a4, .LBB12_4 ; RV32IZFINXZDINX-NEXT: # %bb.3: -; RV32IZFINXZDINX-NEXT: addi a4, a5, -1 +; RV32IZFINXZDINX-NEXT: addi a3, a5, -1 ; RV32IZFINXZDINX-NEXT: .LBB12_4: # %start -; RV32IZFINXZDINX-NEXT: and a1, a2, a4 -; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s3, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 32 +; RV32IZFINXZDINX-NEXT: feq.d a1, s0, s0 +; RV32IZFINXZDINX-NEXT: neg a5, a1 +; RV32IZFINXZDINX-NEXT: and a1, a5, a3 +; RV32IZFINXZDINX-NEXT: neg a2, a2 +; RV32IZFINXZDINX-NEXT: and a0, a2, a0 +; RV32IZFINXZDINX-NEXT: neg a2, a4 +; RV32IZFINXZDINX-NEXT: or a0, a2, a0 +; RV32IZFINXZDINX-NEXT: and a0, a5, a0 +; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_l_d_sat: @@ -1057,18 +979,17 @@ define i64 @fcvt_lu_d_sat(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_lu_d_sat: ; RV32IZFINXZDINX: # %bb.0: # %start -; RV32IZFINXZDINX-NEXT: addi sp, sp, -32 -; RV32IZFINXZDINX-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw s1, 12(sp) +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s1, 4(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s2, 0(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: mv s1, a1 ; RV32IZFINXZDINX-NEXT: fcvt.d.w a2, zero -; RV32IZFINXZDINX-NEXT: fle.d a2, a2, s0 -; RV32IZFINXZDINX-NEXT: neg s2, a2 +; RV32IZFINXZDINX-NEXT: mv s0, a0 +; RV32IZFINXZDINX-NEXT: fle.d a0, a2, s0 +; RV32IZFINXZDINX-NEXT: neg s2, a0 +; RV32IZFINXZDINX-NEXT: mv a0, s0 ; RV32IZFINXZDINX-NEXT: call __fixunsdfdi ; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI14_0) ; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI14_0+4)(a2) @@ -1079,11 +1000,11 @@ define i64 @fcvt_lu_d_sat(double %a) nounwind { ; RV32IZFINXZDINX-NEXT: or a0, a2, a0 ; RV32IZFINXZDINX-NEXT: and a1, s2, a1 ; RV32IZFINXZDINX-NEXT: or a1, a2, a1 -; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 32 +; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s2, 0(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_lu_d_sat: @@ -1185,21 +1106,7 @@ define i64 @fmv_x_d(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fmv_x_d: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 4(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fmv_x_d: @@ -1334,13 +1241,13 @@ define double @fmv_d_x(i64 %a, i64 %b) nounwind { ; RV32IFD-LABEL: fmv_d_x: ; RV32IFD: # %bb.0: ; RV32IFD-NEXT: addi sp, sp, -16 -; RV32IFD-NEXT: sw a3, 4(sp) -; RV32IFD-NEXT: sw a2, 0(sp) -; RV32IFD-NEXT: sw a1, 12(sp) ; RV32IFD-NEXT: sw a0, 8(sp) -; RV32IFD-NEXT: fld fa5, 0(sp) +; RV32IFD-NEXT: sw a1, 12(sp) +; RV32IFD-NEXT: fld fa5, 8(sp) +; RV32IFD-NEXT: sw a2, 8(sp) +; RV32IFD-NEXT: sw a3, 12(sp) ; RV32IFD-NEXT: fld fa4, 8(sp) -; RV32IFD-NEXT: fadd.d fa0, fa4, fa5 +; RV32IFD-NEXT: fadd.d fa0, fa5, fa4 ; RV32IFD-NEXT: addi sp, sp, 16 ; RV32IFD-NEXT: ret ; @@ -1353,21 +1260,7 @@ define double @fmv_d_x(i64 %a, i64 %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fmv_d_x: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -32 -; RV32IZFINXZDINX-NEXT: sw a3, 20(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 16(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 28(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 24(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 16(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 20(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 24(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 28(sp) -; RV32IZFINXZDINX-NEXT: fadd.d a0, a2, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 32 +; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, a2 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fmv_d_x: @@ -1406,13 +1299,7 @@ define double @fcvt_d_w_i8(i8 signext %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_d_w_i8: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: fcvt.d.w a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_d_w_i8: @@ -1449,13 +1336,7 @@ define double @fcvt_d_wu_i8(i8 zeroext %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_d_wu_i8: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: fcvt.d.wu a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_d_wu_i8: @@ -1492,13 +1373,7 @@ define double @fcvt_d_w_i16(i16 signext %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_d_w_i16: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: fcvt.d.w a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_d_w_i16: @@ -1535,13 +1410,7 @@ define double @fcvt_d_wu_i16(i16 zeroext %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_d_wu_i16: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: fcvt.d.wu a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_d_wu_i16: @@ -1731,13 +1600,7 @@ define signext i16 @fcvt_w_s_i16(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_w_s_i16: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rtz -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_w_s_i16: @@ -1797,24 +1660,18 @@ define signext i16 @fcvt_w_s_sat_i16(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_w_s_sat_i16: ; RV32IZFINXZDINX: # %bb.0: # %start -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI26_0) ; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI26_0+4)(a2) ; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI26_0)(a2) ; RV32IZFINXZDINX-NEXT: lui a4, %hi(.LCPI26_1) ; RV32IZFINXZDINX-NEXT: lw a5, %lo(.LCPI26_1+4)(a4) ; RV32IZFINXZDINX-NEXT: lw a4, %lo(.LCPI26_1)(a4) -; RV32IZFINXZDINX-NEXT: fmax.d a2, a0, a2 -; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 -; RV32IZFINXZDINX-NEXT: neg a0, a0 -; RV32IZFINXZDINX-NEXT: fmin.d a2, a2, a4 -; RV32IZFINXZDINX-NEXT: fcvt.w.d a1, a2, rtz -; RV32IZFINXZDINX-NEXT: and a0, a0, a1 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 +; RV32IZFINXZDINX-NEXT: feq.d a6, a0, a0 +; RV32IZFINXZDINX-NEXT: neg a6, a6 +; RV32IZFINXZDINX-NEXT: fmax.d a0, a0, a2 +; RV32IZFINXZDINX-NEXT: fmin.d a0, a0, a4 +; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rtz +; RV32IZFINXZDINX-NEXT: and a0, a6, a0 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_w_s_sat_i16: @@ -1948,13 +1805,7 @@ define zeroext i16 @fcvt_wu_s_i16(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_wu_s_i16: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rtz -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_wu_s_i16: @@ -2006,11 +1857,6 @@ define zeroext i16 @fcvt_wu_s_sat_i16(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_wu_s_sat_i16: ; RV32IZFINXZDINX: # %bb.0: # %start -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI28_0) ; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI28_0+4)(a2) ; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI28_0)(a2) @@ -2018,7 +1864,6 @@ define zeroext i16 @fcvt_wu_s_sat_i16(double %a) nounwind { ; RV32IZFINXZDINX-NEXT: fmax.d a0, a0, a4 ; RV32IZFINXZDINX-NEXT: fmin.d a0, a0, a2 ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rtz -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_wu_s_sat_i16: @@ -2130,13 +1975,7 @@ define signext i8 @fcvt_w_s_i8(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_w_s_i8: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rtz -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_w_s_i8: @@ -2196,24 +2035,18 @@ define signext i8 @fcvt_w_s_sat_i8(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_w_s_sat_i8: ; RV32IZFINXZDINX: # %bb.0: # %start -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI30_0) ; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI30_0+4)(a2) ; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI30_0)(a2) ; RV32IZFINXZDINX-NEXT: lui a4, %hi(.LCPI30_1) ; RV32IZFINXZDINX-NEXT: lw a5, %lo(.LCPI30_1+4)(a4) ; RV32IZFINXZDINX-NEXT: lw a4, %lo(.LCPI30_1)(a4) -; RV32IZFINXZDINX-NEXT: fmax.d a2, a0, a2 -; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 -; RV32IZFINXZDINX-NEXT: neg a0, a0 -; RV32IZFINXZDINX-NEXT: fmin.d a2, a2, a4 -; RV32IZFINXZDINX-NEXT: fcvt.w.d a1, a2, rtz -; RV32IZFINXZDINX-NEXT: and a0, a0, a1 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 +; RV32IZFINXZDINX-NEXT: feq.d a6, a0, a0 +; RV32IZFINXZDINX-NEXT: neg a6, a6 +; RV32IZFINXZDINX-NEXT: fmax.d a0, a0, a2 +; RV32IZFINXZDINX-NEXT: fmin.d a0, a0, a4 +; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rtz +; RV32IZFINXZDINX-NEXT: and a0, a6, a0 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_w_s_sat_i8: @@ -2344,13 +2177,7 @@ define zeroext i8 @fcvt_wu_s_i8(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_wu_s_i8: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rtz -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_wu_s_i8: @@ -2404,11 +2231,6 @@ define zeroext i8 @fcvt_wu_s_sat_i8(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_wu_s_sat_i8: ; RV32IZFINXZDINX: # %bb.0: # %start -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI32_0) ; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI32_0+4)(a2) ; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI32_0)(a2) @@ -2416,7 +2238,6 @@ define zeroext i8 @fcvt_wu_s_sat_i8(double %a) nounwind { ; RV32IZFINXZDINX-NEXT: fmax.d a0, a0, a4 ; RV32IZFINXZDINX-NEXT: fmin.d a0, a0, a2 ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rtz -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_wu_s_sat_i8: @@ -2532,17 +2353,11 @@ define zeroext i32 @fcvt_wu_d_sat_zext(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_wu_d_sat_zext: ; RV32IZFINXZDINX: # %bb.0: # %start -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a2, a0, rtz ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: seqz a0, a0 ; RV32IZFINXZDINX-NEXT: addi a0, a0, -1 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_wu_d_sat_zext: @@ -2647,17 +2462,11 @@ define signext i32 @fcvt_w_d_sat_sext(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fcvt_w_d_sat_sext: ; RV32IZFINXZDINX: # %bb.0: # %start -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a2, a0, rtz ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: seqz a0, a0 ; RV32IZFINXZDINX-NEXT: addi a0, a0, -1 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcvt_w_d_sat_sext: diff --git a/llvm/test/CodeGen/RISCV/double-fcmp-strict.ll b/llvm/test/CodeGen/RISCV/double-fcmp-strict.ll index 3ae2e997019caa138c71a3054d056514f2cfad9d..e864d8fb0eddd557042d057a204915b4a46c393b 100644 --- a/llvm/test/CodeGen/RISCV/double-fcmp-strict.ll +++ b/llvm/test/CodeGen/RISCV/double-fcmp-strict.ll @@ -24,17 +24,7 @@ define i32 @fcmp_oeq(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmp_oeq: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmp_oeq: @@ -78,20 +68,11 @@ define i32 @fcmp_ogt(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmp_ogt: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: csrr a1, fflags -; RV32IZFINXZDINX-NEXT: flt.d a0, a2, a4 -; RV32IZFINXZDINX-NEXT: csrw fflags, a1 -; RV32IZFINXZDINX-NEXT: feq.d zero, a2, a4 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 +; RV32IZFINXZDINX-NEXT: csrr a5, fflags +; RV32IZFINXZDINX-NEXT: flt.d a4, a2, a0 +; RV32IZFINXZDINX-NEXT: csrw fflags, a5 +; RV32IZFINXZDINX-NEXT: feq.d zero, a2, a0 +; RV32IZFINXZDINX-NEXT: mv a0, a4 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmp_ogt: @@ -138,20 +119,11 @@ define i32 @fcmp_oge(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmp_oge: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: csrr a1, fflags -; RV32IZFINXZDINX-NEXT: fle.d a0, a2, a4 -; RV32IZFINXZDINX-NEXT: csrw fflags, a1 -; RV32IZFINXZDINX-NEXT: feq.d zero, a2, a4 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 +; RV32IZFINXZDINX-NEXT: csrr a5, fflags +; RV32IZFINXZDINX-NEXT: fle.d a4, a2, a0 +; RV32IZFINXZDINX-NEXT: csrw fflags, a5 +; RV32IZFINXZDINX-NEXT: feq.d zero, a2, a0 +; RV32IZFINXZDINX-NEXT: mv a0, a4 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmp_oge: @@ -200,20 +172,11 @@ define i32 @fcmp_olt(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmp_olt: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: csrr a1, fflags -; RV32IZFINXZDINX-NEXT: flt.d a0, a4, a2 -; RV32IZFINXZDINX-NEXT: csrw fflags, a1 -; RV32IZFINXZDINX-NEXT: feq.d zero, a4, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 +; RV32IZFINXZDINX-NEXT: csrr a5, fflags +; RV32IZFINXZDINX-NEXT: flt.d a4, a0, a2 +; RV32IZFINXZDINX-NEXT: csrw fflags, a5 +; RV32IZFINXZDINX-NEXT: feq.d zero, a0, a2 +; RV32IZFINXZDINX-NEXT: mv a0, a4 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmp_olt: @@ -260,20 +223,11 @@ define i32 @fcmp_ole(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmp_ole: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: csrr a1, fflags -; RV32IZFINXZDINX-NEXT: fle.d a0, a4, a2 -; RV32IZFINXZDINX-NEXT: csrw fflags, a1 -; RV32IZFINXZDINX-NEXT: feq.d zero, a4, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 +; RV32IZFINXZDINX-NEXT: csrr a5, fflags +; RV32IZFINXZDINX-NEXT: fle.d a4, a0, a2 +; RV32IZFINXZDINX-NEXT: csrw fflags, a5 +; RV32IZFINXZDINX-NEXT: feq.d zero, a0, a2 +; RV32IZFINXZDINX-NEXT: mv a0, a4 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmp_ole: @@ -327,25 +281,16 @@ define i32 @fcmp_one(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmp_one: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: csrr a0, fflags -; RV32IZFINXZDINX-NEXT: flt.d a1, a4, a2 -; RV32IZFINXZDINX-NEXT: csrw fflags, a0 -; RV32IZFINXZDINX-NEXT: feq.d zero, a4, a2 -; RV32IZFINXZDINX-NEXT: csrr a0, fflags -; RV32IZFINXZDINX-NEXT: flt.d a6, a2, a4 -; RV32IZFINXZDINX-NEXT: csrw fflags, a0 -; RV32IZFINXZDINX-NEXT: or a0, a6, a1 -; RV32IZFINXZDINX-NEXT: feq.d zero, a2, a4 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 +; RV32IZFINXZDINX-NEXT: csrr a4, fflags +; RV32IZFINXZDINX-NEXT: flt.d a5, a0, a2 +; RV32IZFINXZDINX-NEXT: csrw fflags, a4 +; RV32IZFINXZDINX-NEXT: feq.d zero, a0, a2 +; RV32IZFINXZDINX-NEXT: csrr a4, fflags +; RV32IZFINXZDINX-NEXT: flt.d a6, a2, a0 +; RV32IZFINXZDINX-NEXT: csrw fflags, a4 +; RV32IZFINXZDINX-NEXT: or a4, a6, a5 +; RV32IZFINXZDINX-NEXT: feq.d zero, a2, a0 +; RV32IZFINXZDINX-NEXT: mv a0, a4 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmp_one: @@ -430,19 +375,9 @@ define i32 @fcmp_ord(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmp_ord: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; RV32IZFINXZDINX-NEXT: feq.d a2, a2, a2 ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmp_ord: @@ -495,26 +430,17 @@ define i32 @fcmp_ueq(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmp_ueq: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: csrr a0, fflags -; RV32IZFINXZDINX-NEXT: flt.d a1, a4, a2 -; RV32IZFINXZDINX-NEXT: csrw fflags, a0 -; RV32IZFINXZDINX-NEXT: feq.d zero, a4, a2 -; RV32IZFINXZDINX-NEXT: csrr a0, fflags -; RV32IZFINXZDINX-NEXT: flt.d a6, a2, a4 -; RV32IZFINXZDINX-NEXT: csrw fflags, a0 -; RV32IZFINXZDINX-NEXT: or a0, a6, a1 -; RV32IZFINXZDINX-NEXT: xori a0, a0, 1 -; RV32IZFINXZDINX-NEXT: feq.d zero, a2, a4 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 +; RV32IZFINXZDINX-NEXT: csrr a4, fflags +; RV32IZFINXZDINX-NEXT: flt.d a5, a0, a2 +; RV32IZFINXZDINX-NEXT: csrw fflags, a4 +; RV32IZFINXZDINX-NEXT: feq.d zero, a0, a2 +; RV32IZFINXZDINX-NEXT: csrr a4, fflags +; RV32IZFINXZDINX-NEXT: flt.d a6, a2, a0 +; RV32IZFINXZDINX-NEXT: csrw fflags, a4 +; RV32IZFINXZDINX-NEXT: or a4, a6, a5 +; RV32IZFINXZDINX-NEXT: xori a4, a4, 1 +; RV32IZFINXZDINX-NEXT: feq.d zero, a2, a0 +; RV32IZFINXZDINX-NEXT: mv a0, a4 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmp_ueq: @@ -602,21 +528,12 @@ define i32 @fcmp_ugt(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmp_ugt: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: csrr a0, fflags -; RV32IZFINXZDINX-NEXT: fle.d a1, a4, a2 -; RV32IZFINXZDINX-NEXT: csrw fflags, a0 -; RV32IZFINXZDINX-NEXT: xori a0, a1, 1 -; RV32IZFINXZDINX-NEXT: feq.d zero, a4, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 +; RV32IZFINXZDINX-NEXT: csrr a4, fflags +; RV32IZFINXZDINX-NEXT: fle.d a5, a0, a2 +; RV32IZFINXZDINX-NEXT: csrw fflags, a4 +; RV32IZFINXZDINX-NEXT: xori a4, a5, 1 +; RV32IZFINXZDINX-NEXT: feq.d zero, a0, a2 +; RV32IZFINXZDINX-NEXT: mv a0, a4 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmp_ugt: @@ -665,21 +582,12 @@ define i32 @fcmp_uge(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmp_uge: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: csrr a0, fflags -; RV32IZFINXZDINX-NEXT: flt.d a1, a4, a2 -; RV32IZFINXZDINX-NEXT: csrw fflags, a0 -; RV32IZFINXZDINX-NEXT: xori a0, a1, 1 -; RV32IZFINXZDINX-NEXT: feq.d zero, a4, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 +; RV32IZFINXZDINX-NEXT: csrr a4, fflags +; RV32IZFINXZDINX-NEXT: flt.d a5, a0, a2 +; RV32IZFINXZDINX-NEXT: csrw fflags, a4 +; RV32IZFINXZDINX-NEXT: xori a4, a5, 1 +; RV32IZFINXZDINX-NEXT: feq.d zero, a0, a2 +; RV32IZFINXZDINX-NEXT: mv a0, a4 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmp_uge: @@ -730,21 +638,12 @@ define i32 @fcmp_ult(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmp_ult: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: csrr a0, fflags -; RV32IZFINXZDINX-NEXT: fle.d a1, a2, a4 -; RV32IZFINXZDINX-NEXT: csrw fflags, a0 -; RV32IZFINXZDINX-NEXT: xori a0, a1, 1 -; RV32IZFINXZDINX-NEXT: feq.d zero, a2, a4 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 +; RV32IZFINXZDINX-NEXT: csrr a4, fflags +; RV32IZFINXZDINX-NEXT: fle.d a5, a2, a0 +; RV32IZFINXZDINX-NEXT: csrw fflags, a4 +; RV32IZFINXZDINX-NEXT: xori a4, a5, 1 +; RV32IZFINXZDINX-NEXT: feq.d zero, a2, a0 +; RV32IZFINXZDINX-NEXT: mv a0, a4 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmp_ult: @@ -793,21 +692,12 @@ define i32 @fcmp_ule(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmp_ule: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: csrr a0, fflags -; RV32IZFINXZDINX-NEXT: flt.d a1, a2, a4 -; RV32IZFINXZDINX-NEXT: csrw fflags, a0 -; RV32IZFINXZDINX-NEXT: xori a0, a1, 1 -; RV32IZFINXZDINX-NEXT: feq.d zero, a2, a4 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 +; RV32IZFINXZDINX-NEXT: csrr a4, fflags +; RV32IZFINXZDINX-NEXT: flt.d a5, a2, a0 +; RV32IZFINXZDINX-NEXT: csrw fflags, a4 +; RV32IZFINXZDINX-NEXT: xori a4, a5, 1 +; RV32IZFINXZDINX-NEXT: feq.d zero, a2, a0 +; RV32IZFINXZDINX-NEXT: mv a0, a4 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmp_ule: @@ -853,18 +743,8 @@ define i32 @fcmp_une(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmp_une: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a2 ; RV32IZFINXZDINX-NEXT: xori a0, a0, 1 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmp_une: @@ -908,20 +788,10 @@ define i32 @fcmp_uno(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmp_uno: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; RV32IZFINXZDINX-NEXT: feq.d a2, a2, a2 ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 ; RV32IZFINXZDINX-NEXT: xori a0, a0, 1 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmp_uno: @@ -966,19 +836,9 @@ define i32 @fcmps_oeq(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmps_oeq: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; RV32IZFINXZDINX-NEXT: fle.d a4, a2, a0 ; RV32IZFINXZDINX-NEXT: fle.d a0, a0, a2 ; RV32IZFINXZDINX-NEXT: and a0, a0, a4 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmps_oeq: @@ -1021,17 +881,7 @@ define i32 @fcmps_ogt(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmps_ogt: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; RV32IZFINXZDINX-NEXT: flt.d a0, a2, a0 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmps_ogt: @@ -1071,17 +921,7 @@ define i32 @fcmps_oge(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmps_oge: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; RV32IZFINXZDINX-NEXT: fle.d a0, a2, a0 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmps_oge: @@ -1123,17 +963,7 @@ define i32 @fcmps_olt(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmps_olt: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: flt.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmps_olt: @@ -1173,17 +1003,7 @@ define i32 @fcmps_ole(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmps_ole: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fle.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmps_ole: @@ -1225,19 +1045,9 @@ define i32 @fcmps_one(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmps_one: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: flt.d a4, a0, a2 ; RV32IZFINXZDINX-NEXT: flt.d a0, a2, a0 ; RV32IZFINXZDINX-NEXT: or a0, a0, a4 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmps_one: @@ -1315,19 +1125,9 @@ define i32 @fcmps_ord(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmps_ord: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; RV32IZFINXZDINX-NEXT: fle.d a2, a2, a2 ; RV32IZFINXZDINX-NEXT: fle.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmps_ord: @@ -1372,20 +1172,10 @@ define i32 @fcmps_ueq(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmps_ueq: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: flt.d a4, a0, a2 ; RV32IZFINXZDINX-NEXT: flt.d a0, a2, a0 ; RV32IZFINXZDINX-NEXT: or a0, a0, a4 ; RV32IZFINXZDINX-NEXT: xori a0, a0, 1 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmps_ueq: @@ -1463,18 +1253,8 @@ define i32 @fcmps_ugt(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmps_ugt: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fle.d a0, a0, a2 ; RV32IZFINXZDINX-NEXT: xori a0, a0, 1 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmps_ugt: @@ -1516,18 +1296,8 @@ define i32 @fcmps_uge(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmps_uge: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: flt.d a0, a0, a2 ; RV32IZFINXZDINX-NEXT: xori a0, a0, 1 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmps_uge: @@ -1571,18 +1341,8 @@ define i32 @fcmps_ult(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmps_ult: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; RV32IZFINXZDINX-NEXT: fle.d a0, a2, a0 ; RV32IZFINXZDINX-NEXT: xori a0, a0, 1 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmps_ult: @@ -1624,18 +1384,8 @@ define i32 @fcmps_ule(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmps_ule: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; RV32IZFINXZDINX-NEXT: flt.d a0, a2, a0 ; RV32IZFINXZDINX-NEXT: xori a0, a0, 1 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmps_ule: @@ -1679,20 +1429,10 @@ define i32 @fcmps_une(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmps_une: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; RV32IZFINXZDINX-NEXT: fle.d a4, a2, a0 ; RV32IZFINXZDINX-NEXT: fle.d a0, a0, a2 ; RV32IZFINXZDINX-NEXT: and a0, a0, a4 ; RV32IZFINXZDINX-NEXT: xori a0, a0, 1 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmps_une: @@ -1738,20 +1478,10 @@ define i32 @fcmps_uno(double %a, double %b) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fcmps_uno: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; RV32IZFINXZDINX-NEXT: fle.d a2, a2, a2 ; RV32IZFINXZDINX-NEXT: fle.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 ; RV32IZFINXZDINX-NEXT: xori a0, a0, 1 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fcmps_uno: diff --git a/llvm/test/CodeGen/RISCV/double-fcmp.ll b/llvm/test/CodeGen/RISCV/double-fcmp.ll index 64a154f450f183f52e28622b4fa4f9c9b052fe2c..1e609f8081ebfbc05111bef2b6bc29d9d416c1b7 100644 --- a/llvm/test/CodeGen/RISCV/double-fcmp.ll +++ b/llvm/test/CodeGen/RISCV/double-fcmp.ll @@ -45,17 +45,7 @@ define i32 @fcmp_oeq(double %a, double %b) nounwind { ; ; CHECKRV32IZFINXZDINX-LABEL: fcmp_oeq: ; CHECKRV32IZFINXZDINX: # %bb.0: -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32IZFINXZDINX-NEXT: feq.d a0, a0, a2 -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32IZFINXZDINX-NEXT: ret ; ; CHECKRV64IZFINXZDINX-LABEL: fcmp_oeq: @@ -95,17 +85,7 @@ define i32 @fcmp_ogt(double %a, double %b) nounwind { ; ; CHECKRV32IZFINXZDINX-LABEL: fcmp_ogt: ; CHECKRV32IZFINXZDINX: # %bb.0: -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; CHECKRV32IZFINXZDINX-NEXT: flt.d a0, a2, a0 -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32IZFINXZDINX-NEXT: ret ; ; CHECKRV64IZFINXZDINX-LABEL: fcmp_ogt: @@ -145,17 +125,7 @@ define i32 @fcmp_oge(double %a, double %b) nounwind { ; ; CHECKRV32IZFINXZDINX-LABEL: fcmp_oge: ; CHECKRV32IZFINXZDINX: # %bb.0: -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; CHECKRV32IZFINXZDINX-NEXT: fle.d a0, a2, a0 -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32IZFINXZDINX-NEXT: ret ; ; CHECKRV64IZFINXZDINX-LABEL: fcmp_oge: @@ -197,17 +167,7 @@ define i32 @fcmp_olt(double %a, double %b) nounwind { ; ; CHECKRV32IZFINXZDINX-LABEL: fcmp_olt: ; CHECKRV32IZFINXZDINX: # %bb.0: -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32IZFINXZDINX-NEXT: flt.d a0, a0, a2 -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32IZFINXZDINX-NEXT: ret ; ; CHECKRV64IZFINXZDINX-LABEL: fcmp_olt: @@ -247,17 +207,7 @@ define i32 @fcmp_ole(double %a, double %b) nounwind { ; ; CHECKRV32IZFINXZDINX-LABEL: fcmp_ole: ; CHECKRV32IZFINXZDINX: # %bb.0: -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32IZFINXZDINX-NEXT: fle.d a0, a0, a2 -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32IZFINXZDINX-NEXT: ret ; ; CHECKRV64IZFINXZDINX-LABEL: fcmp_ole: @@ -299,19 +249,9 @@ define i32 @fcmp_one(double %a, double %b) nounwind { ; ; CHECKRV32IZFINXZDINX-LABEL: fcmp_one: ; CHECKRV32IZFINXZDINX: # %bb.0: -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32IZFINXZDINX-NEXT: flt.d a4, a0, a2 ; CHECKRV32IZFINXZDINX-NEXT: flt.d a0, a2, a0 ; CHECKRV32IZFINXZDINX-NEXT: or a0, a0, a4 -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32IZFINXZDINX-NEXT: ret ; ; CHECKRV64IZFINXZDINX-LABEL: fcmp_one: @@ -389,19 +329,9 @@ define i32 @fcmp_ord(double %a, double %b) nounwind { ; ; CHECKRV32IZFINXZDINX-LABEL: fcmp_ord: ; CHECKRV32IZFINXZDINX: # %bb.0: -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; CHECKRV32IZFINXZDINX-NEXT: feq.d a2, a2, a2 ; CHECKRV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; CHECKRV32IZFINXZDINX-NEXT: and a0, a0, a2 -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32IZFINXZDINX-NEXT: ret ; ; CHECKRV64IZFINXZDINX-LABEL: fcmp_ord: @@ -446,20 +376,10 @@ define i32 @fcmp_ueq(double %a, double %b) nounwind { ; ; CHECKRV32IZFINXZDINX-LABEL: fcmp_ueq: ; CHECKRV32IZFINXZDINX: # %bb.0: -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32IZFINXZDINX-NEXT: flt.d a4, a0, a2 ; CHECKRV32IZFINXZDINX-NEXT: flt.d a0, a2, a0 ; CHECKRV32IZFINXZDINX-NEXT: or a0, a0, a4 ; CHECKRV32IZFINXZDINX-NEXT: xori a0, a0, 1 -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32IZFINXZDINX-NEXT: ret ; ; CHECKRV64IZFINXZDINX-LABEL: fcmp_ueq: @@ -537,18 +457,8 @@ define i32 @fcmp_ugt(double %a, double %b) nounwind { ; ; CHECKRV32IZFINXZDINX-LABEL: fcmp_ugt: ; CHECKRV32IZFINXZDINX: # %bb.0: -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32IZFINXZDINX-NEXT: fle.d a0, a0, a2 ; CHECKRV32IZFINXZDINX-NEXT: xori a0, a0, 1 -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32IZFINXZDINX-NEXT: ret ; ; CHECKRV64IZFINXZDINX-LABEL: fcmp_ugt: @@ -590,18 +500,8 @@ define i32 @fcmp_uge(double %a, double %b) nounwind { ; ; CHECKRV32IZFINXZDINX-LABEL: fcmp_uge: ; CHECKRV32IZFINXZDINX: # %bb.0: -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32IZFINXZDINX-NEXT: flt.d a0, a0, a2 ; CHECKRV32IZFINXZDINX-NEXT: xori a0, a0, 1 -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32IZFINXZDINX-NEXT: ret ; ; CHECKRV64IZFINXZDINX-LABEL: fcmp_uge: @@ -645,18 +545,8 @@ define i32 @fcmp_ult(double %a, double %b) nounwind { ; ; CHECKRV32IZFINXZDINX-LABEL: fcmp_ult: ; CHECKRV32IZFINXZDINX: # %bb.0: -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; CHECKRV32IZFINXZDINX-NEXT: fle.d a0, a2, a0 ; CHECKRV32IZFINXZDINX-NEXT: xori a0, a0, 1 -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32IZFINXZDINX-NEXT: ret ; ; CHECKRV64IZFINXZDINX-LABEL: fcmp_ult: @@ -698,18 +588,8 @@ define i32 @fcmp_ule(double %a, double %b) nounwind { ; ; CHECKRV32IZFINXZDINX-LABEL: fcmp_ule: ; CHECKRV32IZFINXZDINX: # %bb.0: -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; CHECKRV32IZFINXZDINX-NEXT: flt.d a0, a2, a0 ; CHECKRV32IZFINXZDINX-NEXT: xori a0, a0, 1 -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32IZFINXZDINX-NEXT: ret ; ; CHECKRV64IZFINXZDINX-LABEL: fcmp_ule: @@ -751,18 +631,8 @@ define i32 @fcmp_une(double %a, double %b) nounwind { ; ; CHECKRV32IZFINXZDINX-LABEL: fcmp_une: ; CHECKRV32IZFINXZDINX: # %bb.0: -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32IZFINXZDINX-NEXT: feq.d a0, a0, a2 ; CHECKRV32IZFINXZDINX-NEXT: xori a0, a0, 1 -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32IZFINXZDINX-NEXT: ret ; ; CHECKRV64IZFINXZDINX-LABEL: fcmp_une: @@ -806,20 +676,10 @@ define i32 @fcmp_uno(double %a, double %b) nounwind { ; ; CHECKRV32IZFINXZDINX-LABEL: fcmp_uno: ; CHECKRV32IZFINXZDINX: # %bb.0: -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32IZFINXZDINX-NEXT: lw a3, 12(sp) ; CHECKRV32IZFINXZDINX-NEXT: feq.d a2, a2, a2 ; CHECKRV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; CHECKRV32IZFINXZDINX-NEXT: and a0, a0, a2 ; CHECKRV32IZFINXZDINX-NEXT: xori a0, a0, 1 -; CHECKRV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32IZFINXZDINX-NEXT: ret ; ; CHECKRV64IZFINXZDINX-LABEL: fcmp_uno: diff --git a/llvm/test/CodeGen/RISCV/double-imm.ll b/llvm/test/CodeGen/RISCV/double-imm.ll index 9254369baf19f3de328b3c3c9903ab98f0b52f20..74d4acc4f23f8c2bed01c9a082ebd6b88314d491 100644 --- a/llvm/test/CodeGen/RISCV/double-imm.ll +++ b/llvm/test/CodeGen/RISCV/double-imm.ll @@ -54,20 +54,10 @@ define double @double_imm_op(double %a) nounwind { ; ; CHECKRV32ZDINX-LABEL: double_imm_op: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32ZDINX-NEXT: lui a2, %hi(.LCPI1_0) ; CHECKRV32ZDINX-NEXT: lw a3, %lo(.LCPI1_0+4)(a2) ; CHECKRV32ZDINX-NEXT: lw a2, %lo(.LCPI1_0)(a2) ; CHECKRV32ZDINX-NEXT: fadd.d a0, a0, a2 -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: double_imm_op: @@ -153,24 +143,18 @@ define dso_local double @negzero_sel(i16 noundef %a, double noundef %d) nounwind ; ; CHECKRV32ZDINX-LABEL: negzero_sel: ; CHECKRV32ZDINX: # %bb.0: # %entry -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a1, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a2, 12(sp) -; CHECKRV32ZDINX-NEXT: slli a2, a0, 16 -; CHECKRV32ZDINX-NEXT: fcvt.d.w a0, zero -; CHECKRV32ZDINX-NEXT: beqz a2, .LBB4_2 +; CHECKRV32ZDINX-NEXT: slli a0, a0, 16 +; CHECKRV32ZDINX-NEXT: fcvt.d.w a4, zero +; CHECKRV32ZDINX-NEXT: beqz a0, .LBB4_2 ; CHECKRV32ZDINX-NEXT: # %bb.1: # %entry -; CHECKRV32ZDINX-NEXT: fneg.d a0, a0 +; CHECKRV32ZDINX-NEXT: fneg.d a2, a4 ; CHECKRV32ZDINX-NEXT: j .LBB4_3 ; CHECKRV32ZDINX-NEXT: .LBB4_2: -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) +; CHECKRV32ZDINX-NEXT: mv a3, a2 +; CHECKRV32ZDINX-NEXT: mv a2, a1 ; CHECKRV32ZDINX-NEXT: .LBB4_3: # %entry -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 +; CHECKRV32ZDINX-NEXT: mv a0, a2 +; CHECKRV32ZDINX-NEXT: mv a1, a3 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: negzero_sel: diff --git a/llvm/test/CodeGen/RISCV/double-intrinsics-strict.ll b/llvm/test/CodeGen/RISCV/double-intrinsics-strict.ll index c574f64150a249690ec1411257f6e3ee746a220a..38215860193eaf7c76019e9e47c166d7c1c08a81 100644 --- a/llvm/test/CodeGen/RISCV/double-intrinsics-strict.ll +++ b/llvm/test/CodeGen/RISCV/double-intrinsics-strict.ll @@ -28,17 +28,7 @@ define double @sqrt_f64(double %a) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: sqrt_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fsqrt.d a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: sqrt_f64: @@ -299,22 +289,12 @@ define double @sincos_f64(double %a) nounwind strictfp { ; RV32IZFINXZDINX-NEXT: mv s0, a1 ; RV32IZFINXZDINX-NEXT: mv s1, a0 ; RV32IZFINXZDINX-NEXT: call sin -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw s2, 0(sp) -; RV32IZFINXZDINX-NEXT: lw s3, 4(sp) +; RV32IZFINXZDINX-NEXT: mv s2, a0 +; RV32IZFINXZDINX-NEXT: mv s3, a1 ; RV32IZFINXZDINX-NEXT: mv a0, s1 ; RV32IZFINXZDINX-NEXT: mv a1, s0 ; RV32IZFINXZDINX-NEXT: call cos -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) ; RV32IZFINXZDINX-NEXT: fadd.d a0, s2, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) ; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload ; RV32IZFINXZDINX-NEXT: lw s0, 24(sp) # 4-byte Folded Reload ; RV32IZFINXZDINX-NEXT: lw s1, 20(sp) # 4-byte Folded Reload @@ -765,25 +745,7 @@ define double @fma_f64(double %a, double %b, double %c) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fma_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fmadd.d a0, a0, a2, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fma_f64: @@ -822,25 +784,7 @@ define double @fmuladd_f64(double %a, double %b, double %c) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: fmuladd_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fmadd.d a0, a0, a2, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fmuladd_f64: @@ -1455,13 +1399,7 @@ define iXLen @lrint_f64(double %a) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: lrint_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: lrint_f64: @@ -1505,13 +1443,7 @@ define iXLen @lround_f64(double %a) nounwind strictfp { ; ; RV32IZFINXZDINX-LABEL: lround_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rmm -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: lround_f64: diff --git a/llvm/test/CodeGen/RISCV/double-intrinsics.ll b/llvm/test/CodeGen/RISCV/double-intrinsics.ll index f290cf0f7736e3c5e665585cc2363d265bae8925..52c49cfbfb30a799bbb9bd35915d450a87de6662 100644 --- a/llvm/test/CodeGen/RISCV/double-intrinsics.ll +++ b/llvm/test/CodeGen/RISCV/double-intrinsics.ll @@ -26,17 +26,7 @@ define double @sqrt_f64(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: sqrt_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fsqrt.d a0, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: sqrt_f64: @@ -254,22 +244,12 @@ define double @sincos_f64(double %a) nounwind { ; RV32IZFINXZDINX-NEXT: mv s0, a1 ; RV32IZFINXZDINX-NEXT: mv s1, a0 ; RV32IZFINXZDINX-NEXT: call sin -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw s2, 0(sp) -; RV32IZFINXZDINX-NEXT: lw s3, 4(sp) +; RV32IZFINXZDINX-NEXT: mv s2, a0 +; RV32IZFINXZDINX-NEXT: mv s3, a1 ; RV32IZFINXZDINX-NEXT: mv a0, s1 ; RV32IZFINXZDINX-NEXT: mv a1, s0 ; RV32IZFINXZDINX-NEXT: call cos -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) ; RV32IZFINXZDINX-NEXT: fadd.d a0, s2, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) ; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload ; RV32IZFINXZDINX-NEXT: lw s0, 24(sp) # 4-byte Folded Reload ; RV32IZFINXZDINX-NEXT: lw s1, 20(sp) # 4-byte Folded Reload @@ -606,25 +586,7 @@ define double @fma_f64(double %a, double %b, double %c) nounwind { ; ; RV32IZFINXZDINX-LABEL: fma_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fmadd.d a0, a0, a2, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fma_f64: @@ -663,25 +625,7 @@ define double @fmuladd_f64(double %a, double %b, double %c) nounwind { ; ; RV32IZFINXZDINX-LABEL: fmuladd_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fmadd.d a0, a0, a2, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fmuladd_f64: @@ -769,21 +713,7 @@ define double @minnum_f64(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: minnum_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fmin.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: minnum_f64: @@ -822,21 +752,7 @@ define double @maxnum_f64(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: maxnum_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fmax.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: maxnum_f64: @@ -892,21 +808,7 @@ define double @copysign_f64(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: copysign_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fsgnj.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: copysign_f64: @@ -1381,13 +1283,7 @@ define iXLen @lrint_f64(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: lrint_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: lrint_f64: @@ -1432,13 +1328,7 @@ define iXLen @lround_f64(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: lround_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rmm -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: lround_f64: @@ -1475,13 +1365,7 @@ define i32 @lround_i32_f64(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: lround_i32_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rmm -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: lround_i32_f64: @@ -1625,16 +1509,9 @@ define i1 @isnan_d_fpclass(double %x) { ; ; RV32IZFINXZDINX-LABEL: isnan_d_fpclass: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fclass.d a0, a0 ; RV32IZFINXZDINX-NEXT: andi a0, a0, 768 ; RV32IZFINXZDINX-NEXT: snez a0, a0 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: isnan_d_fpclass: diff --git a/llvm/test/CodeGen/RISCV/double-isnan.ll b/llvm/test/CodeGen/RISCV/double-isnan.ll index 4d0b8151f3c43a3bedd6996b21152a4f42307959..6a3779dc2d36d065684dac30598c1f7d4c318a06 100644 --- a/llvm/test/CodeGen/RISCV/double-isnan.ll +++ b/llvm/test/CodeGen/RISCV/double-isnan.ll @@ -17,14 +17,8 @@ define zeroext i1 @double_is_nan(double %a) nounwind { ; ; CHECKRV32ZDINX-LABEL: double_is_nan: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32ZDINX-NEXT: feq.d a0, a0, a0 ; CHECKRV32ZDINX-NEXT: xori a0, a0, 1 -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: double_is_nan: @@ -44,13 +38,7 @@ define zeroext i1 @double_not_nan(double %a) nounwind { ; ; CHECKRV32ZDINX-LABEL: double_not_nan: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32ZDINX-NEXT: feq.d a0, a0, a0 -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: double_not_nan: diff --git a/llvm/test/CodeGen/RISCV/double-maximum-minimum.ll b/llvm/test/CodeGen/RISCV/double-maximum-minimum.ll index 0ca20783591adacb1f38a3d7df2eb965642975a5..5229117caa2c293ab53595b12f0c809a97013054 100644 --- a/llvm/test/CodeGen/RISCV/double-maximum-minimum.ll +++ b/llvm/test/CodeGen/RISCV/double-maximum-minimum.ll @@ -36,35 +36,25 @@ define double @fminimum_f64(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fminimum_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: feq.d a6, a0, a0 ; RV32IZFINXZDINX-NEXT: mv a4, a2 ; RV32IZFINXZDINX-NEXT: mv a5, a3 -; RV32IZFINXZDINX-NEXT: bnez a6, .LBB0_2 +; RV32IZFINXZDINX-NEXT: beqz a6, .LBB0_3 ; RV32IZFINXZDINX-NEXT: # %bb.1: +; RV32IZFINXZDINX-NEXT: feq.d a6, a2, a2 +; RV32IZFINXZDINX-NEXT: beqz a6, .LBB0_4 +; RV32IZFINXZDINX-NEXT: .LBB0_2: +; RV32IZFINXZDINX-NEXT: fmin.d a0, a0, a4 +; RV32IZFINXZDINX-NEXT: ret +; RV32IZFINXZDINX-NEXT: .LBB0_3: ; RV32IZFINXZDINX-NEXT: mv a4, a0 ; RV32IZFINXZDINX-NEXT: mv a5, a1 -; RV32IZFINXZDINX-NEXT: .LBB0_2: ; RV32IZFINXZDINX-NEXT: feq.d a6, a2, a2 -; RV32IZFINXZDINX-NEXT: bnez a6, .LBB0_4 -; RV32IZFINXZDINX-NEXT: # %bb.3: +; RV32IZFINXZDINX-NEXT: bnez a6, .LBB0_2 +; RV32IZFINXZDINX-NEXT: .LBB0_4: ; RV32IZFINXZDINX-NEXT: mv a0, a2 ; RV32IZFINXZDINX-NEXT: mv a1, a3 -; RV32IZFINXZDINX-NEXT: .LBB0_4: ; RV32IZFINXZDINX-NEXT: fmin.d a0, a0, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fminimum_f64: @@ -113,35 +103,25 @@ define double @fmaximum_f64(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fmaximum_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: feq.d a6, a0, a0 ; RV32IZFINXZDINX-NEXT: mv a4, a2 ; RV32IZFINXZDINX-NEXT: mv a5, a3 -; RV32IZFINXZDINX-NEXT: bnez a6, .LBB1_2 +; RV32IZFINXZDINX-NEXT: beqz a6, .LBB1_3 ; RV32IZFINXZDINX-NEXT: # %bb.1: +; RV32IZFINXZDINX-NEXT: feq.d a6, a2, a2 +; RV32IZFINXZDINX-NEXT: beqz a6, .LBB1_4 +; RV32IZFINXZDINX-NEXT: .LBB1_2: +; RV32IZFINXZDINX-NEXT: fmax.d a0, a0, a4 +; RV32IZFINXZDINX-NEXT: ret +; RV32IZFINXZDINX-NEXT: .LBB1_3: ; RV32IZFINXZDINX-NEXT: mv a4, a0 ; RV32IZFINXZDINX-NEXT: mv a5, a1 -; RV32IZFINXZDINX-NEXT: .LBB1_2: ; RV32IZFINXZDINX-NEXT: feq.d a6, a2, a2 -; RV32IZFINXZDINX-NEXT: bnez a6, .LBB1_4 -; RV32IZFINXZDINX-NEXT: # %bb.3: +; RV32IZFINXZDINX-NEXT: bnez a6, .LBB1_2 +; RV32IZFINXZDINX-NEXT: .LBB1_4: ; RV32IZFINXZDINX-NEXT: mv a0, a2 ; RV32IZFINXZDINX-NEXT: mv a1, a3 -; RV32IZFINXZDINX-NEXT: .LBB1_4: ; RV32IZFINXZDINX-NEXT: fmax.d a0, a0, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fmaximum_f64: @@ -174,21 +154,7 @@ define double @fminimum_nnan_f64(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fminimum_nnan_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fmin.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fminimum_nnan_f64: @@ -221,35 +187,25 @@ define double @fmaximum_nnan_f64(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fmaximum_nnan_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: feq.d a6, a0, a0 ; RV32IZFINXZDINX-NEXT: mv a4, a2 ; RV32IZFINXZDINX-NEXT: mv a5, a3 -; RV32IZFINXZDINX-NEXT: bnez a6, .LBB3_2 +; RV32IZFINXZDINX-NEXT: beqz a6, .LBB3_3 ; RV32IZFINXZDINX-NEXT: # %bb.1: +; RV32IZFINXZDINX-NEXT: feq.d a6, a2, a2 +; RV32IZFINXZDINX-NEXT: beqz a6, .LBB3_4 +; RV32IZFINXZDINX-NEXT: .LBB3_2: +; RV32IZFINXZDINX-NEXT: fmin.d a0, a0, a4 +; RV32IZFINXZDINX-NEXT: ret +; RV32IZFINXZDINX-NEXT: .LBB3_3: ; RV32IZFINXZDINX-NEXT: mv a4, a0 ; RV32IZFINXZDINX-NEXT: mv a5, a1 -; RV32IZFINXZDINX-NEXT: .LBB3_2: ; RV32IZFINXZDINX-NEXT: feq.d a6, a2, a2 -; RV32IZFINXZDINX-NEXT: bnez a6, .LBB3_4 -; RV32IZFINXZDINX-NEXT: # %bb.3: +; RV32IZFINXZDINX-NEXT: bnez a6, .LBB3_2 +; RV32IZFINXZDINX-NEXT: .LBB3_4: ; RV32IZFINXZDINX-NEXT: mv a0, a2 ; RV32IZFINXZDINX-NEXT: mv a1, a3 -; RV32IZFINXZDINX-NEXT: .LBB3_4: ; RV32IZFINXZDINX-NEXT: fmin.d a0, a0, a4 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fmaximum_nnan_f64: @@ -289,30 +245,14 @@ define double @fminimum_nnan_op_f64(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fminimum_nnan_op_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: feq.d a0, a2, a2 -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: bnez a0, .LBB4_2 +; RV32IZFINXZDINX-NEXT: feq.d a4, a2, a2 +; RV32IZFINXZDINX-NEXT: bnez a4, .LBB4_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: -; RV32IZFINXZDINX-NEXT: mv a0, a2 -; RV32IZFINXZDINX-NEXT: mv a1, a3 -; RV32IZFINXZDINX-NEXT: j .LBB4_3 +; RV32IZFINXZDINX-NEXT: fmin.d a0, a2, a2 +; RV32IZFINXZDINX-NEXT: ret ; RV32IZFINXZDINX-NEXT: .LBB4_2: -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, a0 -; RV32IZFINXZDINX-NEXT: .LBB4_3: ; RV32IZFINXZDINX-NEXT: fmin.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fminimum_nnan_op_f64: @@ -341,23 +281,9 @@ define double @fmaximum_nnan_op_f64(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fmaximum_nnan_op_f64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fadd.d a4, a0, a2 ; RV32IZFINXZDINX-NEXT: fsub.d a0, a0, a2 ; RV32IZFINXZDINX-NEXT: fmax.d a0, a4, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fmaximum_nnan_op_f64: diff --git a/llvm/test/CodeGen/RISCV/double-mem.ll b/llvm/test/CodeGen/RISCV/double-mem.ll index 6c6f70d6e2ed40972599183a6b27f773ff4cd8fe..38cb52b6f4b302188cd0be3b277e39011ae9b1b7 100644 --- a/llvm/test/CodeGen/RISCV/double-mem.ll +++ b/llvm/test/CodeGen/RISCV/double-mem.ll @@ -18,17 +18,11 @@ define dso_local double @fld(ptr %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fld: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 ; RV32IZFINXZDINX-NEXT: lw a2, 0(a0) ; RV32IZFINXZDINX-NEXT: lw a3, 4(a0) ; RV32IZFINXZDINX-NEXT: lw a1, 28(a0) ; RV32IZFINXZDINX-NEXT: lw a0, 24(a0) ; RV32IZFINXZDINX-NEXT: fadd.d a0, a2, a0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fld: @@ -56,21 +50,15 @@ define dso_local void @fsd(ptr %a, double %b, double %c) nounwind { ; ; RV32IZFINXZDINX-LABEL: fsd: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a3, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a4, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a4, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a5, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: fadd.d a2, a2, a4 +; RV32IZFINXZDINX-NEXT: mv a5, a4 +; RV32IZFINXZDINX-NEXT: mv a7, a2 +; RV32IZFINXZDINX-NEXT: mv a4, a3 +; RV32IZFINXZDINX-NEXT: mv a6, a1 +; RV32IZFINXZDINX-NEXT: fadd.d a2, a6, a4 ; RV32IZFINXZDINX-NEXT: sw a2, 0(a0) ; RV32IZFINXZDINX-NEXT: sw a3, 4(a0) ; RV32IZFINXZDINX-NEXT: sw a2, 64(a0) ; RV32IZFINXZDINX-NEXT: sw a3, 68(a0) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fsd: @@ -105,15 +93,6 @@ define dso_local double @fld_fsd_global(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fld_fsd_global: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, a2 ; RV32IZFINXZDINX-NEXT: lui a2, %hi(G) ; RV32IZFINXZDINX-NEXT: lw a4, %lo(G)(a2) @@ -125,11 +104,6 @@ define dso_local double @fld_fsd_global(double %a, double %b) nounwind { ; RV32IZFINXZDINX-NEXT: lw a5, 76(a3) ; RV32IZFINXZDINX-NEXT: sw a0, 72(a3) ; RV32IZFINXZDINX-NEXT: sw a1, 76(a3) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fld_fsd_global: @@ -174,22 +148,12 @@ define dso_local double @fld_fsd_constant(double %a) nounwind { ; ; RV32IZFINXZDINX-LABEL: fld_fsd_constant: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: lui a2, 912092 ; RV32IZFINXZDINX-NEXT: lw a4, -273(a2) ; RV32IZFINXZDINX-NEXT: lw a5, -269(a2) ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, a4 ; RV32IZFINXZDINX-NEXT: sw a0, -273(a2) ; RV32IZFINXZDINX-NEXT: sw a1, -269(a2) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fld_fsd_constant: @@ -246,19 +210,13 @@ define dso_local double @fld_stack(double %a) nounwind { ; RV32IZFINXZDINX-NEXT: sw ra, 28(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: sw s0, 24(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw s0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) +; RV32IZFINXZDINX-NEXT: mv s1, a1 +; RV32IZFINXZDINX-NEXT: mv s0, a0 ; RV32IZFINXZDINX-NEXT: addi a0, sp, 8 ; RV32IZFINXZDINX-NEXT: call notdead ; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) ; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, s0 -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) ; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload ; RV32IZFINXZDINX-NEXT: lw s0, 24(sp) # 4-byte Folded Reload ; RV32IZFINXZDINX-NEXT: lw s1, 20(sp) # 4-byte Folded Reload @@ -313,23 +271,15 @@ define dso_local void @fsd_stack(double %a, double %b) nounwind { ; ; RV32IZFINXZDINX-LABEL: fsd_stack: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -32 -; RV32IZFINXZDINX-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, a2 -; RV32IZFINXZDINX-NEXT: sw a0, 16(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 20(sp) -; RV32IZFINXZDINX-NEXT: addi a0, sp, 16 +; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) +; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) +; RV32IZFINXZDINX-NEXT: mv a0, sp ; RV32IZFINXZDINX-NEXT: call notdead -; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 32 +; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fsd_stack: @@ -360,14 +310,10 @@ define dso_local void @fsd_trunc(ptr %a, double %b) nounwind noinline optnone { ; ; RV32IZFINXZDINX-LABEL: fsd_trunc: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: sw a1, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a2, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a2, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a3, 12(sp) +; RV32IZFINXZDINX-NEXT: mv a3, a2 +; RV32IZFINXZDINX-NEXT: mv a2, a1 ; RV32IZFINXZDINX-NEXT: fcvt.s.d a1, a2 ; RV32IZFINXZDINX-NEXT: sw a1, 0(a0) -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: fsd_trunc: diff --git a/llvm/test/CodeGen/RISCV/double-previous-failure.ll b/llvm/test/CodeGen/RISCV/double-previous-failure.ll index 8b8f538886edbdeebf4ca9c729c9f3d86e2d58db..c169b1099b273a05ddbc9d8d289f2f827ea3a0fe 100644 --- a/llvm/test/CodeGen/RISCV/double-previous-failure.ll +++ b/llvm/test/CodeGen/RISCV/double-previous-failure.ll @@ -50,10 +50,6 @@ define i32 @main() nounwind { ; RV32IZFINXZDINX-NEXT: lui a1, 262144 ; RV32IZFINXZDINX-NEXT: li a0, 0 ; RV32IZFINXZDINX-NEXT: call test -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 4(sp) ; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI1_0) ; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI1_0+4)(a2) ; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI1_0)(a2) diff --git a/llvm/test/CodeGen/RISCV/double-round-conv-sat.ll b/llvm/test/CodeGen/RISCV/double-round-conv-sat.ll index 7cdf18e2fea9c01c9127736ef19990e1537ba608..f1c56b320b76c467d90022ba99d556bc8945fc55 100644 --- a/llvm/test/CodeGen/RISCV/double-round-conv-sat.ll +++ b/llvm/test/CodeGen/RISCV/double-round-conv-sat.ll @@ -20,18 +20,11 @@ define signext i32 @test_floor_si32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_floor_si32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a2, a0, rdn ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: seqz a0, a0 ; RV32IZFINXZDINX-NEXT: addi a0, a0, -1 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_floor_si32: @@ -50,48 +43,42 @@ define signext i32 @test_floor_si32(double %x) { define i64 @test_floor_si64(double %x) nounwind { ; RV32IFD-LABEL: test_floor_si64: ; RV32IFD: # %bb.0: -; RV32IFD-NEXT: addi sp, sp, -32 -; RV32IFD-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s3, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: sw s0, 8(sp) # 4-byte Folded Spill ; RV32IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill ; RV32IFD-NEXT: call floor ; RV32IFD-NEXT: lui a0, %hi(.LCPI1_0) ; RV32IFD-NEXT: fld fa5, %lo(.LCPI1_0)(a0) -; RV32IFD-NEXT: lui a0, %hi(.LCPI1_1) -; RV32IFD-NEXT: fld fa4, %lo(.LCPI1_1)(a0) ; RV32IFD-NEXT: fmv.d fs0, fa0 -; RV32IFD-NEXT: flt.d s0, fa5, fa0 -; RV32IFD-NEXT: neg s1, s0 -; RV32IFD-NEXT: fle.d s2, fa4, fa0 -; RV32IFD-NEXT: neg s3, s2 +; RV32IFD-NEXT: fle.d s0, fa5, fa0 ; RV32IFD-NEXT: call __fixdfdi -; RV32IFD-NEXT: and a0, s3, a0 -; RV32IFD-NEXT: or a0, s1, a0 -; RV32IFD-NEXT: feq.d a2, fs0, fs0 -; RV32IFD-NEXT: neg a2, a2 -; RV32IFD-NEXT: lui a4, 524288 -; RV32IFD-NEXT: li a5, 1 ; RV32IFD-NEXT: lui a3, 524288 -; RV32IFD-NEXT: bne s2, a5, .LBB1_2 +; RV32IFD-NEXT: li a4, 1 +; RV32IFD-NEXT: lui a2, 524288 +; RV32IFD-NEXT: bne s0, a4, .LBB1_2 ; RV32IFD-NEXT: # %bb.1: -; RV32IFD-NEXT: mv a3, a1 +; RV32IFD-NEXT: mv a2, a1 ; RV32IFD-NEXT: .LBB1_2: -; RV32IFD-NEXT: and a0, a2, a0 -; RV32IFD-NEXT: beqz s0, .LBB1_4 +; RV32IFD-NEXT: lui a1, %hi(.LCPI1_1) +; RV32IFD-NEXT: fld fa5, %lo(.LCPI1_1)(a1) +; RV32IFD-NEXT: flt.d a4, fa5, fs0 +; RV32IFD-NEXT: beqz a4, .LBB1_4 ; RV32IFD-NEXT: # %bb.3: -; RV32IFD-NEXT: addi a3, a4, -1 +; RV32IFD-NEXT: addi a2, a3, -1 ; RV32IFD-NEXT: .LBB1_4: -; RV32IFD-NEXT: and a1, a2, a3 -; RV32IFD-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s3, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: feq.d a1, fs0, fs0 +; RV32IFD-NEXT: neg a3, a1 +; RV32IFD-NEXT: and a1, a3, a2 +; RV32IFD-NEXT: neg a2, a4 +; RV32IFD-NEXT: neg a4, s0 +; RV32IFD-NEXT: and a0, a4, a0 +; RV32IFD-NEXT: or a0, a2, a0 +; RV32IFD-NEXT: and a0, a3, a0 +; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload -; RV32IFD-NEXT: addi sp, sp, 32 +; RV32IFD-NEXT: addi sp, sp, 16 ; RV32IFD-NEXT: ret ; ; RV64IFD-LABEL: test_floor_si64: @@ -105,51 +92,45 @@ define i64 @test_floor_si64(double %x) nounwind { ; ; RV32IZFINXZDINX-LABEL: test_floor_si64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -32 -; RV32IZFINXZDINX-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s3, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s1, 4(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call floor -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw s0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) +; RV32IZFINXZDINX-NEXT: mv s0, a0 +; RV32IZFINXZDINX-NEXT: mv s1, a1 +; RV32IZFINXZDINX-NEXT: call __fixdfdi ; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI1_0) ; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI1_0+4)(a2) ; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI1_0)(a2) -; RV32IZFINXZDINX-NEXT: fle.d s2, a2, s0 -; RV32IZFINXZDINX-NEXT: neg s3, s2 -; RV32IZFINXZDINX-NEXT: call __fixdfdi -; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI1_1) -; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI1_1+4)(a2) -; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI1_1)(a2) -; RV32IZFINXZDINX-NEXT: and a0, s3, a0 -; RV32IZFINXZDINX-NEXT: flt.d a3, a2, s0 -; RV32IZFINXZDINX-NEXT: neg a2, a3 -; RV32IZFINXZDINX-NEXT: or a0, a2, a0 -; RV32IZFINXZDINX-NEXT: feq.d a2, s0, s0 -; RV32IZFINXZDINX-NEXT: neg a2, a2 +; RV32IZFINXZDINX-NEXT: fle.d a2, a2, s0 ; RV32IZFINXZDINX-NEXT: lui a5, 524288 -; RV32IZFINXZDINX-NEXT: li a6, 1 -; RV32IZFINXZDINX-NEXT: lui a4, 524288 -; RV32IZFINXZDINX-NEXT: bne s2, a6, .LBB1_2 +; RV32IZFINXZDINX-NEXT: li a4, 1 +; RV32IZFINXZDINX-NEXT: lui a3, 524288 +; RV32IZFINXZDINX-NEXT: bne a2, a4, .LBB1_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: -; RV32IZFINXZDINX-NEXT: mv a4, a1 +; RV32IZFINXZDINX-NEXT: mv a3, a1 ; RV32IZFINXZDINX-NEXT: .LBB1_2: -; RV32IZFINXZDINX-NEXT: and a0, a2, a0 -; RV32IZFINXZDINX-NEXT: beqz a3, .LBB1_4 +; RV32IZFINXZDINX-NEXT: lui a1, %hi(.LCPI1_1) +; RV32IZFINXZDINX-NEXT: lw a6, %lo(.LCPI1_1)(a1) +; RV32IZFINXZDINX-NEXT: lw a7, %lo(.LCPI1_1+4)(a1) +; RV32IZFINXZDINX-NEXT: flt.d a4, a6, s0 +; RV32IZFINXZDINX-NEXT: beqz a4, .LBB1_4 ; RV32IZFINXZDINX-NEXT: # %bb.3: -; RV32IZFINXZDINX-NEXT: addi a4, a5, -1 +; RV32IZFINXZDINX-NEXT: addi a3, a5, -1 ; RV32IZFINXZDINX-NEXT: .LBB1_4: -; RV32IZFINXZDINX-NEXT: and a1, a2, a4 -; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s3, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 32 +; RV32IZFINXZDINX-NEXT: feq.d a1, s0, s0 +; RV32IZFINXZDINX-NEXT: neg a5, a1 +; RV32IZFINXZDINX-NEXT: and a1, a5, a3 +; RV32IZFINXZDINX-NEXT: neg a2, a2 +; RV32IZFINXZDINX-NEXT: and a0, a2, a0 +; RV32IZFINXZDINX-NEXT: neg a2, a4 +; RV32IZFINXZDINX-NEXT: or a0, a2, a0 +; RV32IZFINXZDINX-NEXT: and a0, a5, a0 +; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_floor_si64: @@ -177,18 +158,11 @@ define signext i32 @test_floor_ui32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_floor_ui32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a2, a0, rdn ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: seqz a0, a0 ; RV32IZFINXZDINX-NEXT: addi a0, a0, -1 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_floor_ui32: @@ -241,38 +215,30 @@ define i64 @test_floor_ui64(double %x) nounwind { ; ; RV32IZFINXZDINX-LABEL: test_floor_ui64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -32 -; RV32IZFINXZDINX-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s2, 16(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s1, 4(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call floor -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw s1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw s1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) +; RV32IZFINXZDINX-NEXT: mv s0, a0 +; RV32IZFINXZDINX-NEXT: mv s1, a1 +; RV32IZFINXZDINX-NEXT: call __fixunsdfdi ; RV32IZFINXZDINX-NEXT: fcvt.d.w a2, zero +; RV32IZFINXZDINX-NEXT: lui a4, %hi(.LCPI3_0) +; RV32IZFINXZDINX-NEXT: lw a5, %lo(.LCPI3_0+4)(a4) +; RV32IZFINXZDINX-NEXT: lw a4, %lo(.LCPI3_0)(a4) ; RV32IZFINXZDINX-NEXT: fle.d a2, a2, s0 -; RV32IZFINXZDINX-NEXT: neg s2, a2 -; RV32IZFINXZDINX-NEXT: call __fixunsdfdi -; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI3_0) -; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI3_0+4)(a2) -; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI3_0)(a2) -; RV32IZFINXZDINX-NEXT: and a0, s2, a0 -; RV32IZFINXZDINX-NEXT: flt.d a2, a2, s0 ; RV32IZFINXZDINX-NEXT: neg a2, a2 -; RV32IZFINXZDINX-NEXT: or a0, a2, a0 -; RV32IZFINXZDINX-NEXT: and a1, s2, a1 -; RV32IZFINXZDINX-NEXT: or a1, a2, a1 -; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 32 +; RV32IZFINXZDINX-NEXT: and a0, a2, a0 +; RV32IZFINXZDINX-NEXT: flt.d a3, a4, s0 +; RV32IZFINXZDINX-NEXT: neg a3, a3 +; RV32IZFINXZDINX-NEXT: or a0, a3, a0 +; RV32IZFINXZDINX-NEXT: and a1, a2, a1 +; RV32IZFINXZDINX-NEXT: or a1, a3, a1 +; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_floor_ui64: @@ -300,18 +266,11 @@ define signext i32 @test_ceil_si32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_ceil_si32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a2, a0, rup ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: seqz a0, a0 ; RV32IZFINXZDINX-NEXT: addi a0, a0, -1 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_ceil_si32: @@ -330,48 +289,42 @@ define signext i32 @test_ceil_si32(double %x) { define i64 @test_ceil_si64(double %x) nounwind { ; RV32IFD-LABEL: test_ceil_si64: ; RV32IFD: # %bb.0: -; RV32IFD-NEXT: addi sp, sp, -32 -; RV32IFD-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s3, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: sw s0, 8(sp) # 4-byte Folded Spill ; RV32IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill ; RV32IFD-NEXT: call ceil ; RV32IFD-NEXT: lui a0, %hi(.LCPI5_0) ; RV32IFD-NEXT: fld fa5, %lo(.LCPI5_0)(a0) -; RV32IFD-NEXT: lui a0, %hi(.LCPI5_1) -; RV32IFD-NEXT: fld fa4, %lo(.LCPI5_1)(a0) ; RV32IFD-NEXT: fmv.d fs0, fa0 -; RV32IFD-NEXT: flt.d s0, fa5, fa0 -; RV32IFD-NEXT: neg s1, s0 -; RV32IFD-NEXT: fle.d s2, fa4, fa0 -; RV32IFD-NEXT: neg s3, s2 +; RV32IFD-NEXT: fle.d s0, fa5, fa0 ; RV32IFD-NEXT: call __fixdfdi -; RV32IFD-NEXT: and a0, s3, a0 -; RV32IFD-NEXT: or a0, s1, a0 -; RV32IFD-NEXT: feq.d a2, fs0, fs0 -; RV32IFD-NEXT: neg a2, a2 -; RV32IFD-NEXT: lui a4, 524288 -; RV32IFD-NEXT: li a5, 1 ; RV32IFD-NEXT: lui a3, 524288 -; RV32IFD-NEXT: bne s2, a5, .LBB5_2 +; RV32IFD-NEXT: li a4, 1 +; RV32IFD-NEXT: lui a2, 524288 +; RV32IFD-NEXT: bne s0, a4, .LBB5_2 ; RV32IFD-NEXT: # %bb.1: -; RV32IFD-NEXT: mv a3, a1 +; RV32IFD-NEXT: mv a2, a1 ; RV32IFD-NEXT: .LBB5_2: -; RV32IFD-NEXT: and a0, a2, a0 -; RV32IFD-NEXT: beqz s0, .LBB5_4 +; RV32IFD-NEXT: lui a1, %hi(.LCPI5_1) +; RV32IFD-NEXT: fld fa5, %lo(.LCPI5_1)(a1) +; RV32IFD-NEXT: flt.d a4, fa5, fs0 +; RV32IFD-NEXT: beqz a4, .LBB5_4 ; RV32IFD-NEXT: # %bb.3: -; RV32IFD-NEXT: addi a3, a4, -1 +; RV32IFD-NEXT: addi a2, a3, -1 ; RV32IFD-NEXT: .LBB5_4: -; RV32IFD-NEXT: and a1, a2, a3 -; RV32IFD-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s3, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: feq.d a1, fs0, fs0 +; RV32IFD-NEXT: neg a3, a1 +; RV32IFD-NEXT: and a1, a3, a2 +; RV32IFD-NEXT: neg a2, a4 +; RV32IFD-NEXT: neg a4, s0 +; RV32IFD-NEXT: and a0, a4, a0 +; RV32IFD-NEXT: or a0, a2, a0 +; RV32IFD-NEXT: and a0, a3, a0 +; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload -; RV32IFD-NEXT: addi sp, sp, 32 +; RV32IFD-NEXT: addi sp, sp, 16 ; RV32IFD-NEXT: ret ; ; RV64IFD-LABEL: test_ceil_si64: @@ -385,51 +338,45 @@ define i64 @test_ceil_si64(double %x) nounwind { ; ; RV32IZFINXZDINX-LABEL: test_ceil_si64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -32 -; RV32IZFINXZDINX-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s3, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s1, 4(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call ceil -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw s0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) +; RV32IZFINXZDINX-NEXT: mv s0, a0 +; RV32IZFINXZDINX-NEXT: mv s1, a1 +; RV32IZFINXZDINX-NEXT: call __fixdfdi ; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI5_0) ; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI5_0+4)(a2) ; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI5_0)(a2) -; RV32IZFINXZDINX-NEXT: fle.d s2, a2, s0 -; RV32IZFINXZDINX-NEXT: neg s3, s2 -; RV32IZFINXZDINX-NEXT: call __fixdfdi -; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI5_1) -; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI5_1+4)(a2) -; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI5_1)(a2) -; RV32IZFINXZDINX-NEXT: and a0, s3, a0 -; RV32IZFINXZDINX-NEXT: flt.d a3, a2, s0 -; RV32IZFINXZDINX-NEXT: neg a2, a3 -; RV32IZFINXZDINX-NEXT: or a0, a2, a0 -; RV32IZFINXZDINX-NEXT: feq.d a2, s0, s0 -; RV32IZFINXZDINX-NEXT: neg a2, a2 +; RV32IZFINXZDINX-NEXT: fle.d a2, a2, s0 ; RV32IZFINXZDINX-NEXT: lui a5, 524288 -; RV32IZFINXZDINX-NEXT: li a6, 1 -; RV32IZFINXZDINX-NEXT: lui a4, 524288 -; RV32IZFINXZDINX-NEXT: bne s2, a6, .LBB5_2 +; RV32IZFINXZDINX-NEXT: li a4, 1 +; RV32IZFINXZDINX-NEXT: lui a3, 524288 +; RV32IZFINXZDINX-NEXT: bne a2, a4, .LBB5_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: -; RV32IZFINXZDINX-NEXT: mv a4, a1 +; RV32IZFINXZDINX-NEXT: mv a3, a1 ; RV32IZFINXZDINX-NEXT: .LBB5_2: -; RV32IZFINXZDINX-NEXT: and a0, a2, a0 -; RV32IZFINXZDINX-NEXT: beqz a3, .LBB5_4 +; RV32IZFINXZDINX-NEXT: lui a1, %hi(.LCPI5_1) +; RV32IZFINXZDINX-NEXT: lw a6, %lo(.LCPI5_1)(a1) +; RV32IZFINXZDINX-NEXT: lw a7, %lo(.LCPI5_1+4)(a1) +; RV32IZFINXZDINX-NEXT: flt.d a4, a6, s0 +; RV32IZFINXZDINX-NEXT: beqz a4, .LBB5_4 ; RV32IZFINXZDINX-NEXT: # %bb.3: -; RV32IZFINXZDINX-NEXT: addi a4, a5, -1 +; RV32IZFINXZDINX-NEXT: addi a3, a5, -1 ; RV32IZFINXZDINX-NEXT: .LBB5_4: -; RV32IZFINXZDINX-NEXT: and a1, a2, a4 -; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s3, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 32 +; RV32IZFINXZDINX-NEXT: feq.d a1, s0, s0 +; RV32IZFINXZDINX-NEXT: neg a5, a1 +; RV32IZFINXZDINX-NEXT: and a1, a5, a3 +; RV32IZFINXZDINX-NEXT: neg a2, a2 +; RV32IZFINXZDINX-NEXT: and a0, a2, a0 +; RV32IZFINXZDINX-NEXT: neg a2, a4 +; RV32IZFINXZDINX-NEXT: or a0, a2, a0 +; RV32IZFINXZDINX-NEXT: and a0, a5, a0 +; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_ceil_si64: @@ -457,18 +404,11 @@ define signext i32 @test_ceil_ui32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_ceil_ui32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a2, a0, rup ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: seqz a0, a0 ; RV32IZFINXZDINX-NEXT: addi a0, a0, -1 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_ceil_ui32: @@ -521,38 +461,30 @@ define i64 @test_ceil_ui64(double %x) nounwind { ; ; RV32IZFINXZDINX-LABEL: test_ceil_ui64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -32 -; RV32IZFINXZDINX-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s2, 16(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s1, 4(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call ceil -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw s1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw s1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) +; RV32IZFINXZDINX-NEXT: mv s0, a0 +; RV32IZFINXZDINX-NEXT: mv s1, a1 +; RV32IZFINXZDINX-NEXT: call __fixunsdfdi ; RV32IZFINXZDINX-NEXT: fcvt.d.w a2, zero +; RV32IZFINXZDINX-NEXT: lui a4, %hi(.LCPI7_0) +; RV32IZFINXZDINX-NEXT: lw a5, %lo(.LCPI7_0+4)(a4) +; RV32IZFINXZDINX-NEXT: lw a4, %lo(.LCPI7_0)(a4) ; RV32IZFINXZDINX-NEXT: fle.d a2, a2, s0 -; RV32IZFINXZDINX-NEXT: neg s2, a2 -; RV32IZFINXZDINX-NEXT: call __fixunsdfdi -; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI7_0) -; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI7_0+4)(a2) -; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI7_0)(a2) -; RV32IZFINXZDINX-NEXT: and a0, s2, a0 -; RV32IZFINXZDINX-NEXT: flt.d a2, a2, s0 ; RV32IZFINXZDINX-NEXT: neg a2, a2 -; RV32IZFINXZDINX-NEXT: or a0, a2, a0 -; RV32IZFINXZDINX-NEXT: and a1, s2, a1 -; RV32IZFINXZDINX-NEXT: or a1, a2, a1 -; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 32 +; RV32IZFINXZDINX-NEXT: and a0, a2, a0 +; RV32IZFINXZDINX-NEXT: flt.d a3, a4, s0 +; RV32IZFINXZDINX-NEXT: neg a3, a3 +; RV32IZFINXZDINX-NEXT: or a0, a3, a0 +; RV32IZFINXZDINX-NEXT: and a1, a2, a1 +; RV32IZFINXZDINX-NEXT: or a1, a3, a1 +; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_ceil_ui64: @@ -580,18 +512,11 @@ define signext i32 @test_trunc_si32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_trunc_si32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a2, a0, rtz ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: seqz a0, a0 ; RV32IZFINXZDINX-NEXT: addi a0, a0, -1 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_trunc_si32: @@ -610,48 +535,42 @@ define signext i32 @test_trunc_si32(double %x) { define i64 @test_trunc_si64(double %x) nounwind { ; RV32IFD-LABEL: test_trunc_si64: ; RV32IFD: # %bb.0: -; RV32IFD-NEXT: addi sp, sp, -32 -; RV32IFD-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s3, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: sw s0, 8(sp) # 4-byte Folded Spill ; RV32IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill ; RV32IFD-NEXT: call trunc ; RV32IFD-NEXT: lui a0, %hi(.LCPI9_0) ; RV32IFD-NEXT: fld fa5, %lo(.LCPI9_0)(a0) -; RV32IFD-NEXT: lui a0, %hi(.LCPI9_1) -; RV32IFD-NEXT: fld fa4, %lo(.LCPI9_1)(a0) ; RV32IFD-NEXT: fmv.d fs0, fa0 -; RV32IFD-NEXT: flt.d s0, fa5, fa0 -; RV32IFD-NEXT: neg s1, s0 -; RV32IFD-NEXT: fle.d s2, fa4, fa0 -; RV32IFD-NEXT: neg s3, s2 +; RV32IFD-NEXT: fle.d s0, fa5, fa0 ; RV32IFD-NEXT: call __fixdfdi -; RV32IFD-NEXT: and a0, s3, a0 -; RV32IFD-NEXT: or a0, s1, a0 -; RV32IFD-NEXT: feq.d a2, fs0, fs0 -; RV32IFD-NEXT: neg a2, a2 -; RV32IFD-NEXT: lui a4, 524288 -; RV32IFD-NEXT: li a5, 1 ; RV32IFD-NEXT: lui a3, 524288 -; RV32IFD-NEXT: bne s2, a5, .LBB9_2 +; RV32IFD-NEXT: li a4, 1 +; RV32IFD-NEXT: lui a2, 524288 +; RV32IFD-NEXT: bne s0, a4, .LBB9_2 ; RV32IFD-NEXT: # %bb.1: -; RV32IFD-NEXT: mv a3, a1 +; RV32IFD-NEXT: mv a2, a1 ; RV32IFD-NEXT: .LBB9_2: -; RV32IFD-NEXT: and a0, a2, a0 -; RV32IFD-NEXT: beqz s0, .LBB9_4 +; RV32IFD-NEXT: lui a1, %hi(.LCPI9_1) +; RV32IFD-NEXT: fld fa5, %lo(.LCPI9_1)(a1) +; RV32IFD-NEXT: flt.d a4, fa5, fs0 +; RV32IFD-NEXT: beqz a4, .LBB9_4 ; RV32IFD-NEXT: # %bb.3: -; RV32IFD-NEXT: addi a3, a4, -1 +; RV32IFD-NEXT: addi a2, a3, -1 ; RV32IFD-NEXT: .LBB9_4: -; RV32IFD-NEXT: and a1, a2, a3 -; RV32IFD-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s3, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: feq.d a1, fs0, fs0 +; RV32IFD-NEXT: neg a3, a1 +; RV32IFD-NEXT: and a1, a3, a2 +; RV32IFD-NEXT: neg a2, a4 +; RV32IFD-NEXT: neg a4, s0 +; RV32IFD-NEXT: and a0, a4, a0 +; RV32IFD-NEXT: or a0, a2, a0 +; RV32IFD-NEXT: and a0, a3, a0 +; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload -; RV32IFD-NEXT: addi sp, sp, 32 +; RV32IFD-NEXT: addi sp, sp, 16 ; RV32IFD-NEXT: ret ; ; RV64IFD-LABEL: test_trunc_si64: @@ -665,51 +584,45 @@ define i64 @test_trunc_si64(double %x) nounwind { ; ; RV32IZFINXZDINX-LABEL: test_trunc_si64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -32 -; RV32IZFINXZDINX-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s3, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s1, 4(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call trunc -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw s0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) +; RV32IZFINXZDINX-NEXT: mv s0, a0 +; RV32IZFINXZDINX-NEXT: mv s1, a1 +; RV32IZFINXZDINX-NEXT: call __fixdfdi ; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI9_0) ; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI9_0+4)(a2) ; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI9_0)(a2) -; RV32IZFINXZDINX-NEXT: fle.d s2, a2, s0 -; RV32IZFINXZDINX-NEXT: neg s3, s2 -; RV32IZFINXZDINX-NEXT: call __fixdfdi -; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI9_1) -; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI9_1+4)(a2) -; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI9_1)(a2) -; RV32IZFINXZDINX-NEXT: and a0, s3, a0 -; RV32IZFINXZDINX-NEXT: flt.d a3, a2, s0 -; RV32IZFINXZDINX-NEXT: neg a2, a3 -; RV32IZFINXZDINX-NEXT: or a0, a2, a0 -; RV32IZFINXZDINX-NEXT: feq.d a2, s0, s0 -; RV32IZFINXZDINX-NEXT: neg a2, a2 +; RV32IZFINXZDINX-NEXT: fle.d a2, a2, s0 ; RV32IZFINXZDINX-NEXT: lui a5, 524288 -; RV32IZFINXZDINX-NEXT: li a6, 1 -; RV32IZFINXZDINX-NEXT: lui a4, 524288 -; RV32IZFINXZDINX-NEXT: bne s2, a6, .LBB9_2 +; RV32IZFINXZDINX-NEXT: li a4, 1 +; RV32IZFINXZDINX-NEXT: lui a3, 524288 +; RV32IZFINXZDINX-NEXT: bne a2, a4, .LBB9_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: -; RV32IZFINXZDINX-NEXT: mv a4, a1 +; RV32IZFINXZDINX-NEXT: mv a3, a1 ; RV32IZFINXZDINX-NEXT: .LBB9_2: -; RV32IZFINXZDINX-NEXT: and a0, a2, a0 -; RV32IZFINXZDINX-NEXT: beqz a3, .LBB9_4 +; RV32IZFINXZDINX-NEXT: lui a1, %hi(.LCPI9_1) +; RV32IZFINXZDINX-NEXT: lw a6, %lo(.LCPI9_1)(a1) +; RV32IZFINXZDINX-NEXT: lw a7, %lo(.LCPI9_1+4)(a1) +; RV32IZFINXZDINX-NEXT: flt.d a4, a6, s0 +; RV32IZFINXZDINX-NEXT: beqz a4, .LBB9_4 ; RV32IZFINXZDINX-NEXT: # %bb.3: -; RV32IZFINXZDINX-NEXT: addi a4, a5, -1 +; RV32IZFINXZDINX-NEXT: addi a3, a5, -1 ; RV32IZFINXZDINX-NEXT: .LBB9_4: -; RV32IZFINXZDINX-NEXT: and a1, a2, a4 -; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s3, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 32 +; RV32IZFINXZDINX-NEXT: feq.d a1, s0, s0 +; RV32IZFINXZDINX-NEXT: neg a5, a1 +; RV32IZFINXZDINX-NEXT: and a1, a5, a3 +; RV32IZFINXZDINX-NEXT: neg a2, a2 +; RV32IZFINXZDINX-NEXT: and a0, a2, a0 +; RV32IZFINXZDINX-NEXT: neg a2, a4 +; RV32IZFINXZDINX-NEXT: or a0, a2, a0 +; RV32IZFINXZDINX-NEXT: and a0, a5, a0 +; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_trunc_si64: @@ -737,18 +650,11 @@ define signext i32 @test_trunc_ui32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_trunc_ui32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a2, a0, rtz ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: seqz a0, a0 ; RV32IZFINXZDINX-NEXT: addi a0, a0, -1 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_trunc_ui32: @@ -801,38 +707,30 @@ define i64 @test_trunc_ui64(double %x) nounwind { ; ; RV32IZFINXZDINX-LABEL: test_trunc_ui64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -32 -; RV32IZFINXZDINX-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s2, 16(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s1, 4(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call trunc -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw s1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw s1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) +; RV32IZFINXZDINX-NEXT: mv s0, a0 +; RV32IZFINXZDINX-NEXT: mv s1, a1 +; RV32IZFINXZDINX-NEXT: call __fixunsdfdi ; RV32IZFINXZDINX-NEXT: fcvt.d.w a2, zero +; RV32IZFINXZDINX-NEXT: lui a4, %hi(.LCPI11_0) +; RV32IZFINXZDINX-NEXT: lw a5, %lo(.LCPI11_0+4)(a4) +; RV32IZFINXZDINX-NEXT: lw a4, %lo(.LCPI11_0)(a4) ; RV32IZFINXZDINX-NEXT: fle.d a2, a2, s0 -; RV32IZFINXZDINX-NEXT: neg s2, a2 -; RV32IZFINXZDINX-NEXT: call __fixunsdfdi -; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI11_0) -; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI11_0+4)(a2) -; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI11_0)(a2) -; RV32IZFINXZDINX-NEXT: and a0, s2, a0 -; RV32IZFINXZDINX-NEXT: flt.d a2, a2, s0 ; RV32IZFINXZDINX-NEXT: neg a2, a2 -; RV32IZFINXZDINX-NEXT: or a0, a2, a0 -; RV32IZFINXZDINX-NEXT: and a1, s2, a1 -; RV32IZFINXZDINX-NEXT: or a1, a2, a1 -; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 32 +; RV32IZFINXZDINX-NEXT: and a0, a2, a0 +; RV32IZFINXZDINX-NEXT: flt.d a3, a4, s0 +; RV32IZFINXZDINX-NEXT: neg a3, a3 +; RV32IZFINXZDINX-NEXT: or a0, a3, a0 +; RV32IZFINXZDINX-NEXT: and a1, a2, a1 +; RV32IZFINXZDINX-NEXT: or a1, a3, a1 +; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_trunc_ui64: @@ -860,18 +758,11 @@ define signext i32 @test_round_si32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_round_si32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a2, a0, rmm ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: seqz a0, a0 ; RV32IZFINXZDINX-NEXT: addi a0, a0, -1 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_round_si32: @@ -890,48 +781,42 @@ define signext i32 @test_round_si32(double %x) { define i64 @test_round_si64(double %x) nounwind { ; RV32IFD-LABEL: test_round_si64: ; RV32IFD: # %bb.0: -; RV32IFD-NEXT: addi sp, sp, -32 -; RV32IFD-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s3, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: sw s0, 8(sp) # 4-byte Folded Spill ; RV32IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill ; RV32IFD-NEXT: call round ; RV32IFD-NEXT: lui a0, %hi(.LCPI13_0) ; RV32IFD-NEXT: fld fa5, %lo(.LCPI13_0)(a0) -; RV32IFD-NEXT: lui a0, %hi(.LCPI13_1) -; RV32IFD-NEXT: fld fa4, %lo(.LCPI13_1)(a0) ; RV32IFD-NEXT: fmv.d fs0, fa0 -; RV32IFD-NEXT: flt.d s0, fa5, fa0 -; RV32IFD-NEXT: neg s1, s0 -; RV32IFD-NEXT: fle.d s2, fa4, fa0 -; RV32IFD-NEXT: neg s3, s2 +; RV32IFD-NEXT: fle.d s0, fa5, fa0 ; RV32IFD-NEXT: call __fixdfdi -; RV32IFD-NEXT: and a0, s3, a0 -; RV32IFD-NEXT: or a0, s1, a0 -; RV32IFD-NEXT: feq.d a2, fs0, fs0 -; RV32IFD-NEXT: neg a2, a2 -; RV32IFD-NEXT: lui a4, 524288 -; RV32IFD-NEXT: li a5, 1 ; RV32IFD-NEXT: lui a3, 524288 -; RV32IFD-NEXT: bne s2, a5, .LBB13_2 +; RV32IFD-NEXT: li a4, 1 +; RV32IFD-NEXT: lui a2, 524288 +; RV32IFD-NEXT: bne s0, a4, .LBB13_2 ; RV32IFD-NEXT: # %bb.1: -; RV32IFD-NEXT: mv a3, a1 +; RV32IFD-NEXT: mv a2, a1 ; RV32IFD-NEXT: .LBB13_2: -; RV32IFD-NEXT: and a0, a2, a0 -; RV32IFD-NEXT: beqz s0, .LBB13_4 +; RV32IFD-NEXT: lui a1, %hi(.LCPI13_1) +; RV32IFD-NEXT: fld fa5, %lo(.LCPI13_1)(a1) +; RV32IFD-NEXT: flt.d a4, fa5, fs0 +; RV32IFD-NEXT: beqz a4, .LBB13_4 ; RV32IFD-NEXT: # %bb.3: -; RV32IFD-NEXT: addi a3, a4, -1 +; RV32IFD-NEXT: addi a2, a3, -1 ; RV32IFD-NEXT: .LBB13_4: -; RV32IFD-NEXT: and a1, a2, a3 -; RV32IFD-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s3, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: feq.d a1, fs0, fs0 +; RV32IFD-NEXT: neg a3, a1 +; RV32IFD-NEXT: and a1, a3, a2 +; RV32IFD-NEXT: neg a2, a4 +; RV32IFD-NEXT: neg a4, s0 +; RV32IFD-NEXT: and a0, a4, a0 +; RV32IFD-NEXT: or a0, a2, a0 +; RV32IFD-NEXT: and a0, a3, a0 +; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload -; RV32IFD-NEXT: addi sp, sp, 32 +; RV32IFD-NEXT: addi sp, sp, 16 ; RV32IFD-NEXT: ret ; ; RV64IFD-LABEL: test_round_si64: @@ -945,51 +830,45 @@ define i64 @test_round_si64(double %x) nounwind { ; ; RV32IZFINXZDINX-LABEL: test_round_si64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -32 -; RV32IZFINXZDINX-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s3, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s1, 4(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call round -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw s0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) +; RV32IZFINXZDINX-NEXT: mv s0, a0 +; RV32IZFINXZDINX-NEXT: mv s1, a1 +; RV32IZFINXZDINX-NEXT: call __fixdfdi ; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI13_0) ; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI13_0+4)(a2) ; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI13_0)(a2) -; RV32IZFINXZDINX-NEXT: fle.d s2, a2, s0 -; RV32IZFINXZDINX-NEXT: neg s3, s2 -; RV32IZFINXZDINX-NEXT: call __fixdfdi -; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI13_1) -; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI13_1+4)(a2) -; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI13_1)(a2) -; RV32IZFINXZDINX-NEXT: and a0, s3, a0 -; RV32IZFINXZDINX-NEXT: flt.d a3, a2, s0 -; RV32IZFINXZDINX-NEXT: neg a2, a3 -; RV32IZFINXZDINX-NEXT: or a0, a2, a0 -; RV32IZFINXZDINX-NEXT: feq.d a2, s0, s0 -; RV32IZFINXZDINX-NEXT: neg a2, a2 +; RV32IZFINXZDINX-NEXT: fle.d a2, a2, s0 ; RV32IZFINXZDINX-NEXT: lui a5, 524288 -; RV32IZFINXZDINX-NEXT: li a6, 1 -; RV32IZFINXZDINX-NEXT: lui a4, 524288 -; RV32IZFINXZDINX-NEXT: bne s2, a6, .LBB13_2 +; RV32IZFINXZDINX-NEXT: li a4, 1 +; RV32IZFINXZDINX-NEXT: lui a3, 524288 +; RV32IZFINXZDINX-NEXT: bne a2, a4, .LBB13_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: -; RV32IZFINXZDINX-NEXT: mv a4, a1 +; RV32IZFINXZDINX-NEXT: mv a3, a1 ; RV32IZFINXZDINX-NEXT: .LBB13_2: -; RV32IZFINXZDINX-NEXT: and a0, a2, a0 -; RV32IZFINXZDINX-NEXT: beqz a3, .LBB13_4 +; RV32IZFINXZDINX-NEXT: lui a1, %hi(.LCPI13_1) +; RV32IZFINXZDINX-NEXT: lw a6, %lo(.LCPI13_1)(a1) +; RV32IZFINXZDINX-NEXT: lw a7, %lo(.LCPI13_1+4)(a1) +; RV32IZFINXZDINX-NEXT: flt.d a4, a6, s0 +; RV32IZFINXZDINX-NEXT: beqz a4, .LBB13_4 ; RV32IZFINXZDINX-NEXT: # %bb.3: -; RV32IZFINXZDINX-NEXT: addi a4, a5, -1 +; RV32IZFINXZDINX-NEXT: addi a3, a5, -1 ; RV32IZFINXZDINX-NEXT: .LBB13_4: -; RV32IZFINXZDINX-NEXT: and a1, a2, a4 -; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s3, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 32 +; RV32IZFINXZDINX-NEXT: feq.d a1, s0, s0 +; RV32IZFINXZDINX-NEXT: neg a5, a1 +; RV32IZFINXZDINX-NEXT: and a1, a5, a3 +; RV32IZFINXZDINX-NEXT: neg a2, a2 +; RV32IZFINXZDINX-NEXT: and a0, a2, a0 +; RV32IZFINXZDINX-NEXT: neg a2, a4 +; RV32IZFINXZDINX-NEXT: or a0, a2, a0 +; RV32IZFINXZDINX-NEXT: and a0, a5, a0 +; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_round_si64: @@ -1017,18 +896,11 @@ define signext i32 @test_round_ui32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_round_ui32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a2, a0, rmm ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: seqz a0, a0 ; RV32IZFINXZDINX-NEXT: addi a0, a0, -1 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_round_ui32: @@ -1081,38 +953,30 @@ define i64 @test_round_ui64(double %x) nounwind { ; ; RV32IZFINXZDINX-LABEL: test_round_ui64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -32 -; RV32IZFINXZDINX-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s2, 16(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s1, 4(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call round -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw s1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw s1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) +; RV32IZFINXZDINX-NEXT: mv s0, a0 +; RV32IZFINXZDINX-NEXT: mv s1, a1 +; RV32IZFINXZDINX-NEXT: call __fixunsdfdi ; RV32IZFINXZDINX-NEXT: fcvt.d.w a2, zero +; RV32IZFINXZDINX-NEXT: lui a4, %hi(.LCPI15_0) +; RV32IZFINXZDINX-NEXT: lw a5, %lo(.LCPI15_0+4)(a4) +; RV32IZFINXZDINX-NEXT: lw a4, %lo(.LCPI15_0)(a4) ; RV32IZFINXZDINX-NEXT: fle.d a2, a2, s0 -; RV32IZFINXZDINX-NEXT: neg s2, a2 -; RV32IZFINXZDINX-NEXT: call __fixunsdfdi -; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI15_0) -; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI15_0+4)(a2) -; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI15_0)(a2) -; RV32IZFINXZDINX-NEXT: and a0, s2, a0 -; RV32IZFINXZDINX-NEXT: flt.d a2, a2, s0 ; RV32IZFINXZDINX-NEXT: neg a2, a2 -; RV32IZFINXZDINX-NEXT: or a0, a2, a0 -; RV32IZFINXZDINX-NEXT: and a1, s2, a1 -; RV32IZFINXZDINX-NEXT: or a1, a2, a1 -; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 32 +; RV32IZFINXZDINX-NEXT: and a0, a2, a0 +; RV32IZFINXZDINX-NEXT: flt.d a3, a4, s0 +; RV32IZFINXZDINX-NEXT: neg a3, a3 +; RV32IZFINXZDINX-NEXT: or a0, a3, a0 +; RV32IZFINXZDINX-NEXT: and a1, a2, a1 +; RV32IZFINXZDINX-NEXT: or a1, a3, a1 +; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_round_ui64: @@ -1140,18 +1004,11 @@ define signext i32 @test_roundeven_si32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_roundeven_si32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a2, a0, rne ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: seqz a0, a0 ; RV32IZFINXZDINX-NEXT: addi a0, a0, -1 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_roundeven_si32: @@ -1170,48 +1027,42 @@ define signext i32 @test_roundeven_si32(double %x) { define i64 @test_roundeven_si64(double %x) nounwind { ; RV32IFD-LABEL: test_roundeven_si64: ; RV32IFD: # %bb.0: -; RV32IFD-NEXT: addi sp, sp, -32 -; RV32IFD-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s3, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: sw s0, 8(sp) # 4-byte Folded Spill ; RV32IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill ; RV32IFD-NEXT: call roundeven ; RV32IFD-NEXT: lui a0, %hi(.LCPI17_0) ; RV32IFD-NEXT: fld fa5, %lo(.LCPI17_0)(a0) -; RV32IFD-NEXT: lui a0, %hi(.LCPI17_1) -; RV32IFD-NEXT: fld fa4, %lo(.LCPI17_1)(a0) ; RV32IFD-NEXT: fmv.d fs0, fa0 -; RV32IFD-NEXT: flt.d s0, fa5, fa0 -; RV32IFD-NEXT: neg s1, s0 -; RV32IFD-NEXT: fle.d s2, fa4, fa0 -; RV32IFD-NEXT: neg s3, s2 +; RV32IFD-NEXT: fle.d s0, fa5, fa0 ; RV32IFD-NEXT: call __fixdfdi -; RV32IFD-NEXT: and a0, s3, a0 -; RV32IFD-NEXT: or a0, s1, a0 -; RV32IFD-NEXT: feq.d a2, fs0, fs0 -; RV32IFD-NEXT: neg a2, a2 -; RV32IFD-NEXT: lui a4, 524288 -; RV32IFD-NEXT: li a5, 1 ; RV32IFD-NEXT: lui a3, 524288 -; RV32IFD-NEXT: bne s2, a5, .LBB17_2 +; RV32IFD-NEXT: li a4, 1 +; RV32IFD-NEXT: lui a2, 524288 +; RV32IFD-NEXT: bne s0, a4, .LBB17_2 ; RV32IFD-NEXT: # %bb.1: -; RV32IFD-NEXT: mv a3, a1 +; RV32IFD-NEXT: mv a2, a1 ; RV32IFD-NEXT: .LBB17_2: -; RV32IFD-NEXT: and a0, a2, a0 -; RV32IFD-NEXT: beqz s0, .LBB17_4 +; RV32IFD-NEXT: lui a1, %hi(.LCPI17_1) +; RV32IFD-NEXT: fld fa5, %lo(.LCPI17_1)(a1) +; RV32IFD-NEXT: flt.d a4, fa5, fs0 +; RV32IFD-NEXT: beqz a4, .LBB17_4 ; RV32IFD-NEXT: # %bb.3: -; RV32IFD-NEXT: addi a3, a4, -1 +; RV32IFD-NEXT: addi a2, a3, -1 ; RV32IFD-NEXT: .LBB17_4: -; RV32IFD-NEXT: and a1, a2, a3 -; RV32IFD-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s3, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: feq.d a1, fs0, fs0 +; RV32IFD-NEXT: neg a3, a1 +; RV32IFD-NEXT: and a1, a3, a2 +; RV32IFD-NEXT: neg a2, a4 +; RV32IFD-NEXT: neg a4, s0 +; RV32IFD-NEXT: and a0, a4, a0 +; RV32IFD-NEXT: or a0, a2, a0 +; RV32IFD-NEXT: and a0, a3, a0 +; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload -; RV32IFD-NEXT: addi sp, sp, 32 +; RV32IFD-NEXT: addi sp, sp, 16 ; RV32IFD-NEXT: ret ; ; RV64IFD-LABEL: test_roundeven_si64: @@ -1225,51 +1076,45 @@ define i64 @test_roundeven_si64(double %x) nounwind { ; ; RV32IZFINXZDINX-LABEL: test_roundeven_si64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -32 -; RV32IZFINXZDINX-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s3, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s1, 4(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call roundeven -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw s0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) +; RV32IZFINXZDINX-NEXT: mv s0, a0 +; RV32IZFINXZDINX-NEXT: mv s1, a1 +; RV32IZFINXZDINX-NEXT: call __fixdfdi ; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI17_0) ; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI17_0+4)(a2) ; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI17_0)(a2) -; RV32IZFINXZDINX-NEXT: fle.d s2, a2, s0 -; RV32IZFINXZDINX-NEXT: neg s3, s2 -; RV32IZFINXZDINX-NEXT: call __fixdfdi -; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI17_1) -; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI17_1+4)(a2) -; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI17_1)(a2) -; RV32IZFINXZDINX-NEXT: and a0, s3, a0 -; RV32IZFINXZDINX-NEXT: flt.d a3, a2, s0 -; RV32IZFINXZDINX-NEXT: neg a2, a3 -; RV32IZFINXZDINX-NEXT: or a0, a2, a0 -; RV32IZFINXZDINX-NEXT: feq.d a2, s0, s0 -; RV32IZFINXZDINX-NEXT: neg a2, a2 +; RV32IZFINXZDINX-NEXT: fle.d a2, a2, s0 ; RV32IZFINXZDINX-NEXT: lui a5, 524288 -; RV32IZFINXZDINX-NEXT: li a6, 1 -; RV32IZFINXZDINX-NEXT: lui a4, 524288 -; RV32IZFINXZDINX-NEXT: bne s2, a6, .LBB17_2 +; RV32IZFINXZDINX-NEXT: li a4, 1 +; RV32IZFINXZDINX-NEXT: lui a3, 524288 +; RV32IZFINXZDINX-NEXT: bne a2, a4, .LBB17_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: -; RV32IZFINXZDINX-NEXT: mv a4, a1 +; RV32IZFINXZDINX-NEXT: mv a3, a1 ; RV32IZFINXZDINX-NEXT: .LBB17_2: -; RV32IZFINXZDINX-NEXT: and a0, a2, a0 -; RV32IZFINXZDINX-NEXT: beqz a3, .LBB17_4 +; RV32IZFINXZDINX-NEXT: lui a1, %hi(.LCPI17_1) +; RV32IZFINXZDINX-NEXT: lw a6, %lo(.LCPI17_1)(a1) +; RV32IZFINXZDINX-NEXT: lw a7, %lo(.LCPI17_1+4)(a1) +; RV32IZFINXZDINX-NEXT: flt.d a4, a6, s0 +; RV32IZFINXZDINX-NEXT: beqz a4, .LBB17_4 ; RV32IZFINXZDINX-NEXT: # %bb.3: -; RV32IZFINXZDINX-NEXT: addi a4, a5, -1 +; RV32IZFINXZDINX-NEXT: addi a3, a5, -1 ; RV32IZFINXZDINX-NEXT: .LBB17_4: -; RV32IZFINXZDINX-NEXT: and a1, a2, a4 -; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s3, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 32 +; RV32IZFINXZDINX-NEXT: feq.d a1, s0, s0 +; RV32IZFINXZDINX-NEXT: neg a5, a1 +; RV32IZFINXZDINX-NEXT: and a1, a5, a3 +; RV32IZFINXZDINX-NEXT: neg a2, a2 +; RV32IZFINXZDINX-NEXT: and a0, a2, a0 +; RV32IZFINXZDINX-NEXT: neg a2, a4 +; RV32IZFINXZDINX-NEXT: or a0, a2, a0 +; RV32IZFINXZDINX-NEXT: and a0, a5, a0 +; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_roundeven_si64: @@ -1297,18 +1142,11 @@ define signext i32 @test_roundeven_ui32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_roundeven_ui32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a2, a0, rne ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: seqz a0, a0 ; RV32IZFINXZDINX-NEXT: addi a0, a0, -1 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_roundeven_ui32: @@ -1361,38 +1199,30 @@ define i64 @test_roundeven_ui64(double %x) nounwind { ; ; RV32IZFINXZDINX-LABEL: test_roundeven_ui64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -32 -; RV32IZFINXZDINX-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s2, 16(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s1, 4(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call roundeven -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw s1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw s1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) +; RV32IZFINXZDINX-NEXT: mv s0, a0 +; RV32IZFINXZDINX-NEXT: mv s1, a1 +; RV32IZFINXZDINX-NEXT: call __fixunsdfdi ; RV32IZFINXZDINX-NEXT: fcvt.d.w a2, zero +; RV32IZFINXZDINX-NEXT: lui a4, %hi(.LCPI19_0) +; RV32IZFINXZDINX-NEXT: lw a5, %lo(.LCPI19_0+4)(a4) +; RV32IZFINXZDINX-NEXT: lw a4, %lo(.LCPI19_0)(a4) ; RV32IZFINXZDINX-NEXT: fle.d a2, a2, s0 -; RV32IZFINXZDINX-NEXT: neg s2, a2 -; RV32IZFINXZDINX-NEXT: call __fixunsdfdi -; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI19_0) -; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI19_0+4)(a2) -; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI19_0)(a2) -; RV32IZFINXZDINX-NEXT: and a0, s2, a0 -; RV32IZFINXZDINX-NEXT: flt.d a2, a2, s0 ; RV32IZFINXZDINX-NEXT: neg a2, a2 -; RV32IZFINXZDINX-NEXT: or a0, a2, a0 -; RV32IZFINXZDINX-NEXT: and a1, s2, a1 -; RV32IZFINXZDINX-NEXT: or a1, a2, a1 -; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 32 +; RV32IZFINXZDINX-NEXT: and a0, a2, a0 +; RV32IZFINXZDINX-NEXT: flt.d a3, a4, s0 +; RV32IZFINXZDINX-NEXT: neg a3, a3 +; RV32IZFINXZDINX-NEXT: or a0, a3, a0 +; RV32IZFINXZDINX-NEXT: and a1, a2, a1 +; RV32IZFINXZDINX-NEXT: or a1, a3, a1 +; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_roundeven_ui64: @@ -1420,18 +1250,11 @@ define signext i32 @test_rint_si32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_rint_si32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a2, a0 ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: seqz a0, a0 ; RV32IZFINXZDINX-NEXT: addi a0, a0, -1 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_rint_si32: @@ -1450,48 +1273,42 @@ define signext i32 @test_rint_si32(double %x) { define i64 @test_rint_si64(double %x) nounwind { ; RV32IFD-LABEL: test_rint_si64: ; RV32IFD: # %bb.0: -; RV32IFD-NEXT: addi sp, sp, -32 -; RV32IFD-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32IFD-NEXT: sw s3, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: sw s0, 8(sp) # 4-byte Folded Spill ; RV32IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill ; RV32IFD-NEXT: call rint ; RV32IFD-NEXT: lui a0, %hi(.LCPI21_0) ; RV32IFD-NEXT: fld fa5, %lo(.LCPI21_0)(a0) -; RV32IFD-NEXT: lui a0, %hi(.LCPI21_1) -; RV32IFD-NEXT: fld fa4, %lo(.LCPI21_1)(a0) ; RV32IFD-NEXT: fmv.d fs0, fa0 -; RV32IFD-NEXT: flt.d s0, fa5, fa0 -; RV32IFD-NEXT: neg s1, s0 -; RV32IFD-NEXT: fle.d s2, fa4, fa0 -; RV32IFD-NEXT: neg s3, s2 +; RV32IFD-NEXT: fle.d s0, fa5, fa0 ; RV32IFD-NEXT: call __fixdfdi -; RV32IFD-NEXT: and a0, s3, a0 -; RV32IFD-NEXT: or a0, s1, a0 -; RV32IFD-NEXT: feq.d a2, fs0, fs0 -; RV32IFD-NEXT: neg a2, a2 -; RV32IFD-NEXT: lui a4, 524288 -; RV32IFD-NEXT: li a5, 1 ; RV32IFD-NEXT: lui a3, 524288 -; RV32IFD-NEXT: bne s2, a5, .LBB21_2 +; RV32IFD-NEXT: li a4, 1 +; RV32IFD-NEXT: lui a2, 524288 +; RV32IFD-NEXT: bne s0, a4, .LBB21_2 ; RV32IFD-NEXT: # %bb.1: -; RV32IFD-NEXT: mv a3, a1 +; RV32IFD-NEXT: mv a2, a1 ; RV32IFD-NEXT: .LBB21_2: -; RV32IFD-NEXT: and a0, a2, a0 -; RV32IFD-NEXT: beqz s0, .LBB21_4 +; RV32IFD-NEXT: lui a1, %hi(.LCPI21_1) +; RV32IFD-NEXT: fld fa5, %lo(.LCPI21_1)(a1) +; RV32IFD-NEXT: flt.d a4, fa5, fs0 +; RV32IFD-NEXT: beqz a4, .LBB21_4 ; RV32IFD-NEXT: # %bb.3: -; RV32IFD-NEXT: addi a3, a4, -1 +; RV32IFD-NEXT: addi a2, a3, -1 ; RV32IFD-NEXT: .LBB21_4: -; RV32IFD-NEXT: and a1, a2, a3 -; RV32IFD-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IFD-NEXT: lw s3, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: feq.d a1, fs0, fs0 +; RV32IFD-NEXT: neg a3, a1 +; RV32IFD-NEXT: and a1, a3, a2 +; RV32IFD-NEXT: neg a2, a4 +; RV32IFD-NEXT: neg a4, s0 +; RV32IFD-NEXT: and a0, a4, a0 +; RV32IFD-NEXT: or a0, a2, a0 +; RV32IFD-NEXT: and a0, a3, a0 +; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload -; RV32IFD-NEXT: addi sp, sp, 32 +; RV32IFD-NEXT: addi sp, sp, 16 ; RV32IFD-NEXT: ret ; ; RV64IFD-LABEL: test_rint_si64: @@ -1505,51 +1322,45 @@ define i64 @test_rint_si64(double %x) nounwind { ; ; RV32IZFINXZDINX-LABEL: test_rint_si64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -32 -; RV32IZFINXZDINX-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s3, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s1, 4(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call rint -; RV32IZFINXZDINX-NEXT: sw a0, 0(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 4(sp) -; RV32IZFINXZDINX-NEXT: lw s0, 0(sp) -; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) +; RV32IZFINXZDINX-NEXT: mv s0, a0 +; RV32IZFINXZDINX-NEXT: mv s1, a1 +; RV32IZFINXZDINX-NEXT: call __fixdfdi ; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI21_0) ; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI21_0+4)(a2) ; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI21_0)(a2) -; RV32IZFINXZDINX-NEXT: fle.d s2, a2, s0 -; RV32IZFINXZDINX-NEXT: neg s3, s2 -; RV32IZFINXZDINX-NEXT: call __fixdfdi -; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI21_1) -; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI21_1+4)(a2) -; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI21_1)(a2) -; RV32IZFINXZDINX-NEXT: and a0, s3, a0 -; RV32IZFINXZDINX-NEXT: flt.d a3, a2, s0 -; RV32IZFINXZDINX-NEXT: neg a2, a3 -; RV32IZFINXZDINX-NEXT: or a0, a2, a0 -; RV32IZFINXZDINX-NEXT: feq.d a2, s0, s0 -; RV32IZFINXZDINX-NEXT: neg a2, a2 +; RV32IZFINXZDINX-NEXT: fle.d a2, a2, s0 ; RV32IZFINXZDINX-NEXT: lui a5, 524288 -; RV32IZFINXZDINX-NEXT: li a6, 1 -; RV32IZFINXZDINX-NEXT: lui a4, 524288 -; RV32IZFINXZDINX-NEXT: bne s2, a6, .LBB21_2 +; RV32IZFINXZDINX-NEXT: li a4, 1 +; RV32IZFINXZDINX-NEXT: lui a3, 524288 +; RV32IZFINXZDINX-NEXT: bne a2, a4, .LBB21_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: -; RV32IZFINXZDINX-NEXT: mv a4, a1 +; RV32IZFINXZDINX-NEXT: mv a3, a1 ; RV32IZFINXZDINX-NEXT: .LBB21_2: -; RV32IZFINXZDINX-NEXT: and a0, a2, a0 -; RV32IZFINXZDINX-NEXT: beqz a3, .LBB21_4 +; RV32IZFINXZDINX-NEXT: lui a1, %hi(.LCPI21_1) +; RV32IZFINXZDINX-NEXT: lw a6, %lo(.LCPI21_1)(a1) +; RV32IZFINXZDINX-NEXT: lw a7, %lo(.LCPI21_1+4)(a1) +; RV32IZFINXZDINX-NEXT: flt.d a4, a6, s0 +; RV32IZFINXZDINX-NEXT: beqz a4, .LBB21_4 ; RV32IZFINXZDINX-NEXT: # %bb.3: -; RV32IZFINXZDINX-NEXT: addi a4, a5, -1 +; RV32IZFINXZDINX-NEXT: addi a3, a5, -1 ; RV32IZFINXZDINX-NEXT: .LBB21_4: -; RV32IZFINXZDINX-NEXT: and a1, a2, a4 -; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s3, 12(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 32 +; RV32IZFINXZDINX-NEXT: feq.d a1, s0, s0 +; RV32IZFINXZDINX-NEXT: neg a5, a1 +; RV32IZFINXZDINX-NEXT: and a1, a5, a3 +; RV32IZFINXZDINX-NEXT: neg a2, a2 +; RV32IZFINXZDINX-NEXT: and a0, a2, a0 +; RV32IZFINXZDINX-NEXT: neg a2, a4 +; RV32IZFINXZDINX-NEXT: or a0, a2, a0 +; RV32IZFINXZDINX-NEXT: and a0, a5, a0 +; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_rint_si64: @@ -1577,18 +1388,11 @@ define signext i32 @test_rint_ui32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_rint_ui32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a2, a0 ; RV32IZFINXZDINX-NEXT: feq.d a0, a0, a0 ; RV32IZFINXZDINX-NEXT: seqz a0, a0 ; RV32IZFINXZDINX-NEXT: addi a0, a0, -1 ; RV32IZFINXZDINX-NEXT: and a0, a0, a2 -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_rint_ui32: @@ -1641,38 +1445,30 @@ define i64 @test_rint_ui64(double %x) nounwind { ; ; RV32IZFINXZDINX-LABEL: test_rint_ui64: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -32 -; RV32IZFINXZDINX-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s2, 16(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s1, 4(sp) # 4-byte Folded Spill ; RV32IZFINXZDINX-NEXT: call rint -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw s1, 12(sp) -; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw s1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) +; RV32IZFINXZDINX-NEXT: mv s0, a0 +; RV32IZFINXZDINX-NEXT: mv s1, a1 +; RV32IZFINXZDINX-NEXT: call __fixunsdfdi ; RV32IZFINXZDINX-NEXT: fcvt.d.w a2, zero +; RV32IZFINXZDINX-NEXT: lui a4, %hi(.LCPI23_0) +; RV32IZFINXZDINX-NEXT: lw a5, %lo(.LCPI23_0+4)(a4) +; RV32IZFINXZDINX-NEXT: lw a4, %lo(.LCPI23_0)(a4) ; RV32IZFINXZDINX-NEXT: fle.d a2, a2, s0 -; RV32IZFINXZDINX-NEXT: neg s2, a2 -; RV32IZFINXZDINX-NEXT: call __fixunsdfdi -; RV32IZFINXZDINX-NEXT: lui a2, %hi(.LCPI23_0) -; RV32IZFINXZDINX-NEXT: lw a3, %lo(.LCPI23_0+4)(a2) -; RV32IZFINXZDINX-NEXT: lw a2, %lo(.LCPI23_0)(a2) -; RV32IZFINXZDINX-NEXT: and a0, s2, a0 -; RV32IZFINXZDINX-NEXT: flt.d a2, a2, s0 ; RV32IZFINXZDINX-NEXT: neg a2, a2 -; RV32IZFINXZDINX-NEXT: or a0, a2, a0 -; RV32IZFINXZDINX-NEXT: and a1, s2, a1 -; RV32IZFINXZDINX-NEXT: or a1, a2, a1 -; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 32 +; RV32IZFINXZDINX-NEXT: and a0, a2, a0 +; RV32IZFINXZDINX-NEXT: flt.d a3, a4, s0 +; RV32IZFINXZDINX-NEXT: neg a3, a3 +; RV32IZFINXZDINX-NEXT: or a0, a3, a0 +; RV32IZFINXZDINX-NEXT: and a1, a2, a1 +; RV32IZFINXZDINX-NEXT: or a1, a3, a1 +; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_rint_ui64: diff --git a/llvm/test/CodeGen/RISCV/double-round-conv.ll b/llvm/test/CodeGen/RISCV/double-round-conv.ll index 094a4105de71c347b8b8b960ac1cac4cd6f52be0..d84d80a4a10e9254d1df438154aabe23e704ca51 100644 --- a/llvm/test/CodeGen/RISCV/double-round-conv.ll +++ b/llvm/test/CodeGen/RISCV/double-round-conv.ll @@ -21,14 +21,7 @@ define signext i8 @test_floor_si8(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_floor_si8: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rdn -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_floor_si8: @@ -53,14 +46,7 @@ define signext i16 @test_floor_si16(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_floor_si16: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rdn -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_floor_si16: @@ -80,14 +66,7 @@ define signext i32 @test_floor_si32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_floor_si32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rdn -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_floor_si32: @@ -151,14 +130,7 @@ define zeroext i8 @test_floor_ui8(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_floor_ui8: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rdn -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_floor_ui8: @@ -183,14 +155,7 @@ define zeroext i16 @test_floor_ui16(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_floor_ui16: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rdn -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_floor_ui16: @@ -210,14 +175,7 @@ define signext i32 @test_floor_ui32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_floor_ui32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rdn -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_floor_ui32: @@ -281,14 +239,7 @@ define signext i8 @test_ceil_si8(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_ceil_si8: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rup -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_ceil_si8: @@ -313,14 +264,7 @@ define signext i16 @test_ceil_si16(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_ceil_si16: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rup -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_ceil_si16: @@ -340,14 +284,7 @@ define signext i32 @test_ceil_si32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_ceil_si32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rup -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_ceil_si32: @@ -411,14 +348,7 @@ define zeroext i8 @test_ceil_ui8(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_ceil_ui8: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rup -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_ceil_ui8: @@ -443,14 +373,7 @@ define zeroext i16 @test_ceil_ui16(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_ceil_ui16: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rup -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_ceil_ui16: @@ -470,14 +393,7 @@ define signext i32 @test_ceil_ui32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_ceil_ui32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rup -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_ceil_ui32: @@ -541,14 +457,7 @@ define signext i8 @test_trunc_si8(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_trunc_si8: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rtz -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_trunc_si8: @@ -573,14 +482,7 @@ define signext i16 @test_trunc_si16(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_trunc_si16: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rtz -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_trunc_si16: @@ -600,14 +502,7 @@ define signext i32 @test_trunc_si32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_trunc_si32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rtz -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_trunc_si32: @@ -671,14 +566,7 @@ define zeroext i8 @test_trunc_ui8(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_trunc_ui8: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rtz -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_trunc_ui8: @@ -703,14 +591,7 @@ define zeroext i16 @test_trunc_ui16(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_trunc_ui16: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rtz -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_trunc_ui16: @@ -730,14 +611,7 @@ define signext i32 @test_trunc_ui32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_trunc_ui32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rtz -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_trunc_ui32: @@ -801,14 +675,7 @@ define signext i8 @test_round_si8(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_round_si8: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rmm -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_round_si8: @@ -833,14 +700,7 @@ define signext i16 @test_round_si16(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_round_si16: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rmm -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_round_si16: @@ -860,14 +720,7 @@ define signext i32 @test_round_si32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_round_si32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rmm -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_round_si32: @@ -931,14 +784,7 @@ define zeroext i8 @test_round_ui8(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_round_ui8: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rmm -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_round_ui8: @@ -963,14 +809,7 @@ define zeroext i16 @test_round_ui16(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_round_ui16: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rmm -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_round_ui16: @@ -990,14 +829,7 @@ define signext i32 @test_round_ui32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_round_ui32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rmm -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_round_ui32: @@ -1061,14 +893,7 @@ define signext i8 @test_roundeven_si8(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_roundeven_si8: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rne -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_roundeven_si8: @@ -1093,14 +918,7 @@ define signext i16 @test_roundeven_si16(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_roundeven_si16: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rne -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_roundeven_si16: @@ -1120,14 +938,7 @@ define signext i32 @test_roundeven_si32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_roundeven_si32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.w.d a0, a0, rne -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_roundeven_si32: @@ -1191,14 +1002,7 @@ define zeroext i8 @test_roundeven_ui8(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_roundeven_ui8: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rne -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_roundeven_ui8: @@ -1223,14 +1027,7 @@ define zeroext i16 @test_roundeven_ui16(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_roundeven_ui16: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rne -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_roundeven_ui16: @@ -1250,14 +1047,7 @@ define signext i32 @test_roundeven_ui32(double %x) { ; ; RV32IZFINXZDINX-LABEL: test_roundeven_ui32: ; RV32IZFINXZDINX: # %bb.0: -; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 -; RV32IZFINXZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fcvt.wu.d a0, a0, rne -; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: test_roundeven_ui32: diff --git a/llvm/test/CodeGen/RISCV/double-select-fcmp.ll b/llvm/test/CodeGen/RISCV/double-select-fcmp.ll index 766da3680ffc0da049b85fecb559179ccbe84e53..654a4609caa23fe2f3909ff4ef6a7568e8306066 100644 --- a/llvm/test/CodeGen/RISCV/double-select-fcmp.ll +++ b/llvm/test/CodeGen/RISCV/double-select-fcmp.ll @@ -41,26 +41,12 @@ define double @select_fcmp_oeq(double %a, double %b) nounwind { ; ; CHECKRV32ZDINX-LABEL: select_fcmp_oeq: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32ZDINX-NEXT: feq.d a4, a0, a2 ; CHECKRV32ZDINX-NEXT: bnez a4, .LBB1_2 ; CHECKRV32ZDINX-NEXT: # %bb.1: ; CHECKRV32ZDINX-NEXT: mv a0, a2 ; CHECKRV32ZDINX-NEXT: mv a1, a3 ; CHECKRV32ZDINX-NEXT: .LBB1_2: -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: select_fcmp_oeq: @@ -88,26 +74,12 @@ define double @select_fcmp_ogt(double %a, double %b) nounwind { ; ; CHECKRV32ZDINX-LABEL: select_fcmp_ogt: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a3, 12(sp) ; CHECKRV32ZDINX-NEXT: flt.d a4, a2, a0 ; CHECKRV32ZDINX-NEXT: bnez a4, .LBB2_2 ; CHECKRV32ZDINX-NEXT: # %bb.1: ; CHECKRV32ZDINX-NEXT: mv a0, a2 ; CHECKRV32ZDINX-NEXT: mv a1, a3 ; CHECKRV32ZDINX-NEXT: .LBB2_2: -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: select_fcmp_ogt: @@ -135,26 +107,12 @@ define double @select_fcmp_oge(double %a, double %b) nounwind { ; ; CHECKRV32ZDINX-LABEL: select_fcmp_oge: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a3, 12(sp) ; CHECKRV32ZDINX-NEXT: fle.d a4, a2, a0 ; CHECKRV32ZDINX-NEXT: bnez a4, .LBB3_2 ; CHECKRV32ZDINX-NEXT: # %bb.1: ; CHECKRV32ZDINX-NEXT: mv a0, a2 ; CHECKRV32ZDINX-NEXT: mv a1, a3 ; CHECKRV32ZDINX-NEXT: .LBB3_2: -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: select_fcmp_oge: @@ -182,26 +140,12 @@ define double @select_fcmp_olt(double %a, double %b) nounwind { ; ; CHECKRV32ZDINX-LABEL: select_fcmp_olt: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32ZDINX-NEXT: flt.d a4, a0, a2 ; CHECKRV32ZDINX-NEXT: bnez a4, .LBB4_2 ; CHECKRV32ZDINX-NEXT: # %bb.1: ; CHECKRV32ZDINX-NEXT: mv a0, a2 ; CHECKRV32ZDINX-NEXT: mv a1, a3 ; CHECKRV32ZDINX-NEXT: .LBB4_2: -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: select_fcmp_olt: @@ -229,26 +173,12 @@ define double @select_fcmp_ole(double %a, double %b) nounwind { ; ; CHECKRV32ZDINX-LABEL: select_fcmp_ole: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32ZDINX-NEXT: fle.d a4, a0, a2 ; CHECKRV32ZDINX-NEXT: bnez a4, .LBB5_2 ; CHECKRV32ZDINX-NEXT: # %bb.1: ; CHECKRV32ZDINX-NEXT: mv a0, a2 ; CHECKRV32ZDINX-NEXT: mv a1, a3 ; CHECKRV32ZDINX-NEXT: .LBB5_2: -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: select_fcmp_ole: @@ -278,15 +208,6 @@ define double @select_fcmp_one(double %a, double %b) nounwind { ; ; CHECKRV32ZDINX-LABEL: select_fcmp_one: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32ZDINX-NEXT: flt.d a4, a0, a2 ; CHECKRV32ZDINX-NEXT: flt.d a5, a2, a0 ; CHECKRV32ZDINX-NEXT: or a4, a5, a4 @@ -295,11 +216,6 @@ define double @select_fcmp_one(double %a, double %b) nounwind { ; CHECKRV32ZDINX-NEXT: mv a0, a2 ; CHECKRV32ZDINX-NEXT: mv a1, a3 ; CHECKRV32ZDINX-NEXT: .LBB6_2: -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: select_fcmp_one: @@ -331,15 +247,6 @@ define double @select_fcmp_ord(double %a, double %b) nounwind { ; ; CHECKRV32ZDINX-LABEL: select_fcmp_ord: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a3, 12(sp) ; CHECKRV32ZDINX-NEXT: feq.d a4, a2, a2 ; CHECKRV32ZDINX-NEXT: feq.d a5, a0, a0 ; CHECKRV32ZDINX-NEXT: and a4, a5, a4 @@ -348,11 +255,6 @@ define double @select_fcmp_ord(double %a, double %b) nounwind { ; CHECKRV32ZDINX-NEXT: mv a0, a2 ; CHECKRV32ZDINX-NEXT: mv a1, a3 ; CHECKRV32ZDINX-NEXT: .LBB7_2: -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: select_fcmp_ord: @@ -384,15 +286,6 @@ define double @select_fcmp_ueq(double %a, double %b) nounwind { ; ; CHECKRV32ZDINX-LABEL: select_fcmp_ueq: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32ZDINX-NEXT: flt.d a4, a0, a2 ; CHECKRV32ZDINX-NEXT: flt.d a5, a2, a0 ; CHECKRV32ZDINX-NEXT: or a4, a5, a4 @@ -401,11 +294,6 @@ define double @select_fcmp_ueq(double %a, double %b) nounwind { ; CHECKRV32ZDINX-NEXT: mv a0, a2 ; CHECKRV32ZDINX-NEXT: mv a1, a3 ; CHECKRV32ZDINX-NEXT: .LBB8_2: -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: select_fcmp_ueq: @@ -435,26 +323,12 @@ define double @select_fcmp_ugt(double %a, double %b) nounwind { ; ; CHECKRV32ZDINX-LABEL: select_fcmp_ugt: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32ZDINX-NEXT: fle.d a4, a0, a2 ; CHECKRV32ZDINX-NEXT: beqz a4, .LBB9_2 ; CHECKRV32ZDINX-NEXT: # %bb.1: ; CHECKRV32ZDINX-NEXT: mv a0, a2 ; CHECKRV32ZDINX-NEXT: mv a1, a3 ; CHECKRV32ZDINX-NEXT: .LBB9_2: -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: select_fcmp_ugt: @@ -482,26 +356,12 @@ define double @select_fcmp_uge(double %a, double %b) nounwind { ; ; CHECKRV32ZDINX-LABEL: select_fcmp_uge: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32ZDINX-NEXT: flt.d a4, a0, a2 ; CHECKRV32ZDINX-NEXT: beqz a4, .LBB10_2 ; CHECKRV32ZDINX-NEXT: # %bb.1: ; CHECKRV32ZDINX-NEXT: mv a0, a2 ; CHECKRV32ZDINX-NEXT: mv a1, a3 ; CHECKRV32ZDINX-NEXT: .LBB10_2: -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: select_fcmp_uge: @@ -529,26 +389,12 @@ define double @select_fcmp_ult(double %a, double %b) nounwind { ; ; CHECKRV32ZDINX-LABEL: select_fcmp_ult: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a3, 12(sp) ; CHECKRV32ZDINX-NEXT: fle.d a4, a2, a0 ; CHECKRV32ZDINX-NEXT: beqz a4, .LBB11_2 ; CHECKRV32ZDINX-NEXT: # %bb.1: ; CHECKRV32ZDINX-NEXT: mv a0, a2 ; CHECKRV32ZDINX-NEXT: mv a1, a3 ; CHECKRV32ZDINX-NEXT: .LBB11_2: -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: select_fcmp_ult: @@ -576,26 +422,12 @@ define double @select_fcmp_ule(double %a, double %b) nounwind { ; ; CHECKRV32ZDINX-LABEL: select_fcmp_ule: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a3, 12(sp) ; CHECKRV32ZDINX-NEXT: flt.d a4, a2, a0 ; CHECKRV32ZDINX-NEXT: beqz a4, .LBB12_2 ; CHECKRV32ZDINX-NEXT: # %bb.1: ; CHECKRV32ZDINX-NEXT: mv a0, a2 ; CHECKRV32ZDINX-NEXT: mv a1, a3 ; CHECKRV32ZDINX-NEXT: .LBB12_2: -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: select_fcmp_ule: @@ -623,26 +455,12 @@ define double @select_fcmp_une(double %a, double %b) nounwind { ; ; CHECKRV32ZDINX-LABEL: select_fcmp_une: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32ZDINX-NEXT: feq.d a4, a0, a2 ; CHECKRV32ZDINX-NEXT: beqz a4, .LBB13_2 ; CHECKRV32ZDINX-NEXT: # %bb.1: ; CHECKRV32ZDINX-NEXT: mv a0, a2 ; CHECKRV32ZDINX-NEXT: mv a1, a3 ; CHECKRV32ZDINX-NEXT: .LBB13_2: -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: select_fcmp_une: @@ -672,15 +490,6 @@ define double @select_fcmp_uno(double %a, double %b) nounwind { ; ; CHECKRV32ZDINX-LABEL: select_fcmp_uno: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a3, 12(sp) ; CHECKRV32ZDINX-NEXT: feq.d a4, a2, a2 ; CHECKRV32ZDINX-NEXT: feq.d a5, a0, a0 ; CHECKRV32ZDINX-NEXT: and a4, a5, a4 @@ -689,11 +498,6 @@ define double @select_fcmp_uno(double %a, double %b) nounwind { ; CHECKRV32ZDINX-NEXT: mv a0, a2 ; CHECKRV32ZDINX-NEXT: mv a1, a3 ; CHECKRV32ZDINX-NEXT: .LBB14_2: -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: select_fcmp_uno: @@ -741,22 +545,12 @@ define i32 @i32_select_fcmp_oeq(double %a, double %b, i32 %c, i32 %d) nounwind { ; ; CHECKRV32ZDINX-LABEL: i32_select_fcmp_oeq: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32ZDINX-NEXT: feq.d a1, a0, a2 ; CHECKRV32ZDINX-NEXT: mv a0, a4 ; CHECKRV32ZDINX-NEXT: bnez a1, .LBB16_2 ; CHECKRV32ZDINX-NEXT: # %bb.1: ; CHECKRV32ZDINX-NEXT: mv a0, a5 ; CHECKRV32ZDINX-NEXT: .LBB16_2: -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: i32_select_fcmp_oeq: @@ -783,20 +577,9 @@ define i32 @select_fcmp_oeq_1_2(double %a, double %b) { ; ; CHECKRV32ZDINX-LABEL: select_fcmp_oeq_1_2: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: .cfi_def_cfa_offset 16 -; CHECKRV32ZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32ZDINX-NEXT: feq.d a0, a0, a2 ; CHECKRV32ZDINX-NEXT: li a1, 2 ; CHECKRV32ZDINX-NEXT: sub a0, a1, a0 -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: select_fcmp_oeq_1_2: @@ -819,18 +602,8 @@ define signext i32 @select_fcmp_uge_negone_zero(double %a, double %b) nounwind { ; ; CHECKRV32ZDINX-LABEL: select_fcmp_uge_negone_zero: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32ZDINX-NEXT: fle.d a0, a0, a2 ; CHECKRV32ZDINX-NEXT: addi a0, a0, -1 -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: select_fcmp_uge_negone_zero: @@ -852,18 +625,8 @@ define signext i32 @select_fcmp_uge_1_2(double %a, double %b) nounwind { ; ; CHECKRV32ZDINX-LABEL: select_fcmp_uge_1_2: ; CHECKRV32ZDINX: # %bb.0: -; CHECKRV32ZDINX-NEXT: addi sp, sp, -16 -; CHECKRV32ZDINX-NEXT: sw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a2, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a3, 12(sp) -; CHECKRV32ZDINX-NEXT: sw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: sw a1, 12(sp) -; CHECKRV32ZDINX-NEXT: lw a0, 8(sp) -; CHECKRV32ZDINX-NEXT: lw a1, 12(sp) ; CHECKRV32ZDINX-NEXT: fle.d a0, a0, a2 ; CHECKRV32ZDINX-NEXT: addi a0, a0, 1 -; CHECKRV32ZDINX-NEXT: addi sp, sp, 16 ; CHECKRV32ZDINX-NEXT: ret ; ; CHECKRV64ZDINX-LABEL: select_fcmp_uge_1_2: diff --git a/llvm/test/CodeGen/RISCV/double-select-icmp.ll b/llvm/test/CodeGen/RISCV/double-select-icmp.ll index d864ff51b4669b6506af842b728b6c84d47abf00..929ffc578f5b432e4fe9a4493a95712aae7f95d2 100644 --- a/llvm/test/CodeGen/RISCV/double-select-icmp.ll +++ b/llvm/test/CodeGen/RISCV/double-select-icmp.ll @@ -20,24 +20,13 @@ define double @select_icmp_eq(i32 signext %a, i32 signext %b, double %c, double ; ; RV32ZDINX-LABEL: select_icmp_eq: ; RV32ZDINX: # %bb.0: -; RV32ZDINX-NEXT: addi sp, sp, -16 -; RV32ZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) -; RV32ZDINX-NEXT: sw a2, 8(sp) -; RV32ZDINX-NEXT: sw a3, 12(sp) -; RV32ZDINX-NEXT: bne a0, a1, .LBB0_2 +; RV32ZDINX-NEXT: beq a0, a1, .LBB0_2 ; RV32ZDINX-NEXT: # %bb.1: -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) +; RV32ZDINX-NEXT: mv a2, a4 +; RV32ZDINX-NEXT: mv a3, a5 ; RV32ZDINX-NEXT: .LBB0_2: -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a0, 8(sp) -; RV32ZDINX-NEXT: lw a1, 12(sp) -; RV32ZDINX-NEXT: addi sp, sp, 16 +; RV32ZDINX-NEXT: mv a0, a2 +; RV32ZDINX-NEXT: mv a1, a3 ; RV32ZDINX-NEXT: ret ; ; RV64ZDINX-LABEL: select_icmp_eq: @@ -64,24 +53,13 @@ define double @select_icmp_ne(i32 signext %a, i32 signext %b, double %c, double ; ; RV32ZDINX-LABEL: select_icmp_ne: ; RV32ZDINX: # %bb.0: -; RV32ZDINX-NEXT: addi sp, sp, -16 -; RV32ZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) -; RV32ZDINX-NEXT: sw a2, 8(sp) -; RV32ZDINX-NEXT: sw a3, 12(sp) -; RV32ZDINX-NEXT: beq a0, a1, .LBB1_2 +; RV32ZDINX-NEXT: bne a0, a1, .LBB1_2 ; RV32ZDINX-NEXT: # %bb.1: -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) +; RV32ZDINX-NEXT: mv a2, a4 +; RV32ZDINX-NEXT: mv a3, a5 ; RV32ZDINX-NEXT: .LBB1_2: -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a0, 8(sp) -; RV32ZDINX-NEXT: lw a1, 12(sp) -; RV32ZDINX-NEXT: addi sp, sp, 16 +; RV32ZDINX-NEXT: mv a0, a2 +; RV32ZDINX-NEXT: mv a1, a3 ; RV32ZDINX-NEXT: ret ; ; RV64ZDINX-LABEL: select_icmp_ne: @@ -108,24 +86,13 @@ define double @select_icmp_ugt(i32 signext %a, i32 signext %b, double %c, double ; ; RV32ZDINX-LABEL: select_icmp_ugt: ; RV32ZDINX: # %bb.0: -; RV32ZDINX-NEXT: addi sp, sp, -16 -; RV32ZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) -; RV32ZDINX-NEXT: sw a2, 8(sp) -; RV32ZDINX-NEXT: sw a3, 12(sp) -; RV32ZDINX-NEXT: bgeu a1, a0, .LBB2_2 +; RV32ZDINX-NEXT: bltu a1, a0, .LBB2_2 ; RV32ZDINX-NEXT: # %bb.1: -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) +; RV32ZDINX-NEXT: mv a2, a4 +; RV32ZDINX-NEXT: mv a3, a5 ; RV32ZDINX-NEXT: .LBB2_2: -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a0, 8(sp) -; RV32ZDINX-NEXT: lw a1, 12(sp) -; RV32ZDINX-NEXT: addi sp, sp, 16 +; RV32ZDINX-NEXT: mv a0, a2 +; RV32ZDINX-NEXT: mv a1, a3 ; RV32ZDINX-NEXT: ret ; ; RV64ZDINX-LABEL: select_icmp_ugt: @@ -152,24 +119,13 @@ define double @select_icmp_uge(i32 signext %a, i32 signext %b, double %c, double ; ; RV32ZDINX-LABEL: select_icmp_uge: ; RV32ZDINX: # %bb.0: -; RV32ZDINX-NEXT: addi sp, sp, -16 -; RV32ZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) -; RV32ZDINX-NEXT: sw a2, 8(sp) -; RV32ZDINX-NEXT: sw a3, 12(sp) -; RV32ZDINX-NEXT: bltu a0, a1, .LBB3_2 +; RV32ZDINX-NEXT: bgeu a0, a1, .LBB3_2 ; RV32ZDINX-NEXT: # %bb.1: -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) +; RV32ZDINX-NEXT: mv a2, a4 +; RV32ZDINX-NEXT: mv a3, a5 ; RV32ZDINX-NEXT: .LBB3_2: -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a0, 8(sp) -; RV32ZDINX-NEXT: lw a1, 12(sp) -; RV32ZDINX-NEXT: addi sp, sp, 16 +; RV32ZDINX-NEXT: mv a0, a2 +; RV32ZDINX-NEXT: mv a1, a3 ; RV32ZDINX-NEXT: ret ; ; RV64ZDINX-LABEL: select_icmp_uge: @@ -196,24 +152,13 @@ define double @select_icmp_ult(i32 signext %a, i32 signext %b, double %c, double ; ; RV32ZDINX-LABEL: select_icmp_ult: ; RV32ZDINX: # %bb.0: -; RV32ZDINX-NEXT: addi sp, sp, -16 -; RV32ZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) -; RV32ZDINX-NEXT: sw a2, 8(sp) -; RV32ZDINX-NEXT: sw a3, 12(sp) -; RV32ZDINX-NEXT: bgeu a0, a1, .LBB4_2 +; RV32ZDINX-NEXT: bltu a0, a1, .LBB4_2 ; RV32ZDINX-NEXT: # %bb.1: -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) +; RV32ZDINX-NEXT: mv a2, a4 +; RV32ZDINX-NEXT: mv a3, a5 ; RV32ZDINX-NEXT: .LBB4_2: -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a0, 8(sp) -; RV32ZDINX-NEXT: lw a1, 12(sp) -; RV32ZDINX-NEXT: addi sp, sp, 16 +; RV32ZDINX-NEXT: mv a0, a2 +; RV32ZDINX-NEXT: mv a1, a3 ; RV32ZDINX-NEXT: ret ; ; RV64ZDINX-LABEL: select_icmp_ult: @@ -240,24 +185,13 @@ define double @select_icmp_ule(i32 signext %a, i32 signext %b, double %c, double ; ; RV32ZDINX-LABEL: select_icmp_ule: ; RV32ZDINX: # %bb.0: -; RV32ZDINX-NEXT: addi sp, sp, -16 -; RV32ZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) -; RV32ZDINX-NEXT: sw a2, 8(sp) -; RV32ZDINX-NEXT: sw a3, 12(sp) -; RV32ZDINX-NEXT: bltu a1, a0, .LBB5_2 +; RV32ZDINX-NEXT: bgeu a1, a0, .LBB5_2 ; RV32ZDINX-NEXT: # %bb.1: -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) +; RV32ZDINX-NEXT: mv a2, a4 +; RV32ZDINX-NEXT: mv a3, a5 ; RV32ZDINX-NEXT: .LBB5_2: -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a0, 8(sp) -; RV32ZDINX-NEXT: lw a1, 12(sp) -; RV32ZDINX-NEXT: addi sp, sp, 16 +; RV32ZDINX-NEXT: mv a0, a2 +; RV32ZDINX-NEXT: mv a1, a3 ; RV32ZDINX-NEXT: ret ; ; RV64ZDINX-LABEL: select_icmp_ule: @@ -284,24 +218,13 @@ define double @select_icmp_sgt(i32 signext %a, i32 signext %b, double %c, double ; ; RV32ZDINX-LABEL: select_icmp_sgt: ; RV32ZDINX: # %bb.0: -; RV32ZDINX-NEXT: addi sp, sp, -16 -; RV32ZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) -; RV32ZDINX-NEXT: sw a2, 8(sp) -; RV32ZDINX-NEXT: sw a3, 12(sp) -; RV32ZDINX-NEXT: bge a1, a0, .LBB6_2 +; RV32ZDINX-NEXT: blt a1, a0, .LBB6_2 ; RV32ZDINX-NEXT: # %bb.1: -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) +; RV32ZDINX-NEXT: mv a2, a4 +; RV32ZDINX-NEXT: mv a3, a5 ; RV32ZDINX-NEXT: .LBB6_2: -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a0, 8(sp) -; RV32ZDINX-NEXT: lw a1, 12(sp) -; RV32ZDINX-NEXT: addi sp, sp, 16 +; RV32ZDINX-NEXT: mv a0, a2 +; RV32ZDINX-NEXT: mv a1, a3 ; RV32ZDINX-NEXT: ret ; ; RV64ZDINX-LABEL: select_icmp_sgt: @@ -328,24 +251,13 @@ define double @select_icmp_sge(i32 signext %a, i32 signext %b, double %c, double ; ; RV32ZDINX-LABEL: select_icmp_sge: ; RV32ZDINX: # %bb.0: -; RV32ZDINX-NEXT: addi sp, sp, -16 -; RV32ZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) -; RV32ZDINX-NEXT: sw a2, 8(sp) -; RV32ZDINX-NEXT: sw a3, 12(sp) -; RV32ZDINX-NEXT: blt a0, a1, .LBB7_2 +; RV32ZDINX-NEXT: bge a0, a1, .LBB7_2 ; RV32ZDINX-NEXT: # %bb.1: -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) +; RV32ZDINX-NEXT: mv a2, a4 +; RV32ZDINX-NEXT: mv a3, a5 ; RV32ZDINX-NEXT: .LBB7_2: -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a0, 8(sp) -; RV32ZDINX-NEXT: lw a1, 12(sp) -; RV32ZDINX-NEXT: addi sp, sp, 16 +; RV32ZDINX-NEXT: mv a0, a2 +; RV32ZDINX-NEXT: mv a1, a3 ; RV32ZDINX-NEXT: ret ; ; RV64ZDINX-LABEL: select_icmp_sge: @@ -372,24 +284,13 @@ define double @select_icmp_slt(i32 signext %a, i32 signext %b, double %c, double ; ; RV32ZDINX-LABEL: select_icmp_slt: ; RV32ZDINX: # %bb.0: -; RV32ZDINX-NEXT: addi sp, sp, -16 -; RV32ZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) -; RV32ZDINX-NEXT: sw a2, 8(sp) -; RV32ZDINX-NEXT: sw a3, 12(sp) -; RV32ZDINX-NEXT: bge a0, a1, .LBB8_2 +; RV32ZDINX-NEXT: blt a0, a1, .LBB8_2 ; RV32ZDINX-NEXT: # %bb.1: -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) +; RV32ZDINX-NEXT: mv a2, a4 +; RV32ZDINX-NEXT: mv a3, a5 ; RV32ZDINX-NEXT: .LBB8_2: -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a0, 8(sp) -; RV32ZDINX-NEXT: lw a1, 12(sp) -; RV32ZDINX-NEXT: addi sp, sp, 16 +; RV32ZDINX-NEXT: mv a0, a2 +; RV32ZDINX-NEXT: mv a1, a3 ; RV32ZDINX-NEXT: ret ; ; RV64ZDINX-LABEL: select_icmp_slt: @@ -416,24 +317,13 @@ define double @select_icmp_sle(i32 signext %a, i32 signext %b, double %c, double ; ; RV32ZDINX-LABEL: select_icmp_sle: ; RV32ZDINX: # %bb.0: -; RV32ZDINX-NEXT: addi sp, sp, -16 -; RV32ZDINX-NEXT: .cfi_def_cfa_offset 16 -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) -; RV32ZDINX-NEXT: sw a2, 8(sp) -; RV32ZDINX-NEXT: sw a3, 12(sp) -; RV32ZDINX-NEXT: blt a1, a0, .LBB9_2 +; RV32ZDINX-NEXT: bge a1, a0, .LBB9_2 ; RV32ZDINX-NEXT: # %bb.1: -; RV32ZDINX-NEXT: lw a4, 8(sp) -; RV32ZDINX-NEXT: lw a5, 12(sp) +; RV32ZDINX-NEXT: mv a2, a4 +; RV32ZDINX-NEXT: mv a3, a5 ; RV32ZDINX-NEXT: .LBB9_2: -; RV32ZDINX-NEXT: sw a4, 8(sp) -; RV32ZDINX-NEXT: sw a5, 12(sp) -; RV32ZDINX-NEXT: lw a0, 8(sp) -; RV32ZDINX-NEXT: lw a1, 12(sp) -; RV32ZDINX-NEXT: addi sp, sp, 16 +; RV32ZDINX-NEXT: mv a0, a2 +; RV32ZDINX-NEXT: mv a1, a3 ; RV32ZDINX-NEXT: ret ; ; RV64ZDINX-LABEL: select_icmp_sle: @@ -458,15 +348,8 @@ define double @select_icmp_slt_one(i32 signext %a) { ; ; RV32ZDINX-LABEL: select_icmp_slt_one: ; RV32ZDINX: # %bb.0: -; RV32ZDINX-NEXT: addi sp, sp, -16 -; RV32ZDINX-NEXT: .cfi_def_cfa_offset 16 ; RV32ZDINX-NEXT: slti a0, a0, 1 ; RV32ZDINX-NEXT: fcvt.d.w a0, a0 -; RV32ZDINX-NEXT: sw a0, 8(sp) -; RV32ZDINX-NEXT: sw a1, 12(sp) -; RV32ZDINX-NEXT: lw a0, 8(sp) -; RV32ZDINX-NEXT: lw a1, 12(sp) -; RV32ZDINX-NEXT: addi sp, sp, 16 ; RV32ZDINX-NEXT: ret ; ; RV64ZDINX-LABEL: select_icmp_slt_one: @@ -488,15 +371,8 @@ define double @select_icmp_sgt_zero(i32 signext %a) { ; ; RV32ZDINX-LABEL: select_icmp_sgt_zero: ; RV32ZDINX: # %bb.0: -; RV32ZDINX-NEXT: addi sp, sp, -16 -; RV32ZDINX-NEXT: .cfi_def_cfa_offset 16 ; RV32ZDINX-NEXT: slti a0, a0, 1 ; RV32ZDINX-NEXT: fcvt.d.w a0, a0 -; RV32ZDINX-NEXT: sw a0, 8(sp) -; RV32ZDINX-NEXT: sw a1, 12(sp) -; RV32ZDINX-NEXT: lw a0, 8(sp) -; RV32ZDINX-NEXT: lw a1, 12(sp) -; RV32ZDINX-NEXT: addi sp, sp, 16 ; RV32ZDINX-NEXT: ret ; ; RV64ZDINX-LABEL: select_icmp_sgt_zero: diff --git a/llvm/test/CodeGen/RISCV/double-stack-spill-restore.ll b/llvm/test/CodeGen/RISCV/double-stack-spill-restore.ll index aa88a365431a57329fa6be204f00a1e627722233..4ae912a34d337cf79b7f8e65cdf20f844121ded8 100644 --- a/llvm/test/CodeGen/RISCV/double-stack-spill-restore.ll +++ b/llvm/test/CodeGen/RISCV/double-stack-spill-restore.ll @@ -62,40 +62,28 @@ define double @func(double %d, i32 %n) nounwind { ; ; RV32IZFINXZDINX-LABEL: func: ; RV32IZFINXZDINX: # %bb.0: # %entry -; RV32IZFINXZDINX-NEXT: addi sp, sp, -32 -; RV32IZFINXZDINX-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw s1, 12(sp) +; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 +; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: sw s1, 4(sp) # 4-byte Folded Spill +; RV32IZFINXZDINX-NEXT: mv s1, a1 +; RV32IZFINXZDINX-NEXT: mv s0, a0 ; RV32IZFINXZDINX-NEXT: beqz a2, .LBB0_2 ; RV32IZFINXZDINX-NEXT: # %bb.1: # %if.else ; RV32IZFINXZDINX-NEXT: addi a2, a2, -1 -; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw s1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) +; RV32IZFINXZDINX-NEXT: mv a0, s0 +; RV32IZFINXZDINX-NEXT: mv a1, s1 ; RV32IZFINXZDINX-NEXT: call func -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, s0 -; RV32IZFINXZDINX-NEXT: sw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw a1, 12(sp) ; RV32IZFINXZDINX-NEXT: j .LBB0_3 ; RV32IZFINXZDINX-NEXT: .LBB0_2: # %return -; RV32IZFINXZDINX-NEXT: sw s0, 8(sp) -; RV32IZFINXZDINX-NEXT: sw s1, 12(sp) +; RV32IZFINXZDINX-NEXT: mv a0, s0 +; RV32IZFINXZDINX-NEXT: mv a1, s1 ; RV32IZFINXZDINX-NEXT: .LBB0_3: # %return -; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) -; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) -; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32IZFINXZDINX-NEXT: addi sp, sp, 32 +; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload +; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 ; RV32IZFINXZDINX-NEXT: ret ; ; RV64IZFINXZDINX-LABEL: func: diff --git a/llvm/test/CodeGen/RISCV/fastcc-without-f-reg.ll b/llvm/test/CodeGen/RISCV/fastcc-without-f-reg.ll index fb0b34cf796be0ab664059df636aefda3fa91b5a..a44d31dff09ccb35788a83490c588e47de2c8ff2 100644 --- a/llvm/test/CodeGen/RISCV/fastcc-without-f-reg.ll +++ b/llvm/test/CodeGen/RISCV/fastcc-without-f-reg.ll @@ -160,17 +160,13 @@ define double @caller_double(double %x) nounwind { ; ; ZDINX32-LABEL: caller_double: ; ZDINX32: # %bb.0: # %entry -; ZDINX32-NEXT: addi sp, sp, -32 -; ZDINX32-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; ZDINX32-NEXT: sw a0, 16(sp) -; ZDINX32-NEXT: sw a1, 20(sp) -; ZDINX32-NEXT: lw a0, 16(sp) -; ZDINX32-NEXT: lw a1, 20(sp) +; ZDINX32-NEXT: addi sp, sp, -16 +; ZDINX32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; ZDINX32-NEXT: sw a0, 0(sp) ; ZDINX32-NEXT: sw a1, 4(sp) ; ZDINX32-NEXT: call d -; ZDINX32-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; ZDINX32-NEXT: addi sp, sp, 32 +; ZDINX32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; ZDINX32-NEXT: addi sp, sp, 16 ; ZDINX32-NEXT: ret ; ; ZDINX64-LABEL: caller_double: @@ -200,14 +196,8 @@ define internal fastcc double @d(double %x) nounwind { ; ; ZDINX32-LABEL: d: ; ZDINX32: # %bb.0: # %entry -; ZDINX32-NEXT: addi sp, sp, -16 -; ZDINX32-NEXT: lw a0, 16(sp) -; ZDINX32-NEXT: lw a1, 20(sp) -; ZDINX32-NEXT: sw a0, 8(sp) -; ZDINX32-NEXT: sw a1, 12(sp) -; ZDINX32-NEXT: lw a0, 8(sp) -; ZDINX32-NEXT: lw a1, 12(sp) -; ZDINX32-NEXT: addi sp, sp, 16 +; ZDINX32-NEXT: lw a0, 0(sp) +; ZDINX32-NEXT: lw a1, 4(sp) ; ZDINX32-NEXT: ret ; ; ZDINX64-LABEL: d: @@ -1360,14 +1350,8 @@ define fastcc double @callee_double_32(<32 x double> %A) nounwind { ; ; ZDINX32-LABEL: callee_double_32: ; ZDINX32: # %bb.0: -; ZDINX32-NEXT: addi sp, sp, -16 -; ZDINX32-NEXT: lw a0, 16(sp) -; ZDINX32-NEXT: lw a1, 20(sp) -; ZDINX32-NEXT: sw a0, 8(sp) -; ZDINX32-NEXT: sw a1, 12(sp) -; ZDINX32-NEXT: lw a0, 8(sp) -; ZDINX32-NEXT: lw a1, 12(sp) -; ZDINX32-NEXT: addi sp, sp, 16 +; ZDINX32-NEXT: lw a0, 0(sp) +; ZDINX32-NEXT: lw a1, 4(sp) ; ZDINX32-NEXT: ret ; ; ZDINX64-LABEL: callee_double_32: diff --git a/llvm/test/CodeGen/RISCV/float-convert.ll b/llvm/test/CodeGen/RISCV/float-convert.ll index 9fb78d4c4d52106075d767ff7d5ff2302f75e9a4..2c7315fbe59f6f92c420efa709bdf34599d0cf0e 100644 --- a/llvm/test/CodeGen/RISCV/float-convert.ll +++ b/llvm/test/CodeGen/RISCV/float-convert.ll @@ -629,23 +629,23 @@ define i64 @fcvt_l_s_sat(float %a) nounwind { ; RV32IF-NEXT: lui a2, %hi(.LCPI12_0) ; RV32IF-NEXT: flw fa5, %lo(.LCPI12_0)(a2) ; RV32IF-NEXT: and a0, s1, a0 -; RV32IF-NEXT: flt.s a4, fa5, fs0 -; RV32IF-NEXT: neg a2, a4 +; RV32IF-NEXT: flt.s a3, fa5, fs0 +; RV32IF-NEXT: neg a2, a3 ; RV32IF-NEXT: or a0, a2, a0 ; RV32IF-NEXT: feq.s a2, fs0, fs0 ; RV32IF-NEXT: neg a2, a2 ; RV32IF-NEXT: lui a5, 524288 -; RV32IF-NEXT: lui a3, 524288 +; RV32IF-NEXT: lui a4, 524288 ; RV32IF-NEXT: beqz s0, .LBB12_2 ; RV32IF-NEXT: # %bb.1: # %start -; RV32IF-NEXT: mv a3, a1 +; RV32IF-NEXT: mv a4, a1 ; RV32IF-NEXT: .LBB12_2: # %start ; RV32IF-NEXT: and a0, a2, a0 -; RV32IF-NEXT: beqz a4, .LBB12_4 +; RV32IF-NEXT: beqz a3, .LBB12_4 ; RV32IF-NEXT: # %bb.3: -; RV32IF-NEXT: addi a3, a5, -1 +; RV32IF-NEXT: addi a4, a5, -1 ; RV32IF-NEXT: .LBB12_4: # %start -; RV32IF-NEXT: and a1, a2, a3 +; RV32IF-NEXT: and a1, a2, a4 ; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IF-NEXT: lw s1, 4(sp) # 4-byte Folded Reload @@ -668,37 +668,35 @@ define i64 @fcvt_l_s_sat(float %a) nounwind { ; RV32IZFINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IZFINX-NEXT: sw s0, 8(sp) # 4-byte Folded Spill ; RV32IZFINX-NEXT: sw s1, 4(sp) # 4-byte Folded Spill -; RV32IZFINX-NEXT: sw s2, 0(sp) # 4-byte Folded Spill ; RV32IZFINX-NEXT: mv s0, a0 ; RV32IZFINX-NEXT: lui a0, 913408 ; RV32IZFINX-NEXT: fle.s s1, a0, s0 -; RV32IZFINX-NEXT: neg s2, s1 ; RV32IZFINX-NEXT: mv a0, s0 ; RV32IZFINX-NEXT: call __fixsfdi -; RV32IZFINX-NEXT: lui a2, %hi(.LCPI12_0) -; RV32IZFINX-NEXT: lw a2, %lo(.LCPI12_0)(a2) -; RV32IZFINX-NEXT: and a0, s2, a0 -; RV32IZFINX-NEXT: flt.s a4, a2, s0 -; RV32IZFINX-NEXT: neg a2, a4 -; RV32IZFINX-NEXT: or a0, a2, a0 -; RV32IZFINX-NEXT: feq.s a2, s0, s0 -; RV32IZFINX-NEXT: neg a2, a2 -; RV32IZFINX-NEXT: lui a5, 524288 -; RV32IZFINX-NEXT: lui a3, 524288 +; RV32IZFINX-NEXT: lui a4, 524288 +; RV32IZFINX-NEXT: lui a2, 524288 ; RV32IZFINX-NEXT: beqz s1, .LBB12_2 ; RV32IZFINX-NEXT: # %bb.1: # %start -; RV32IZFINX-NEXT: mv a3, a1 +; RV32IZFINX-NEXT: mv a2, a1 ; RV32IZFINX-NEXT: .LBB12_2: # %start -; RV32IZFINX-NEXT: and a0, a2, a0 -; RV32IZFINX-NEXT: beqz a4, .LBB12_4 +; RV32IZFINX-NEXT: lui a1, %hi(.LCPI12_0) +; RV32IZFINX-NEXT: lw a1, %lo(.LCPI12_0)(a1) +; RV32IZFINX-NEXT: flt.s a3, a1, s0 +; RV32IZFINX-NEXT: beqz a3, .LBB12_4 ; RV32IZFINX-NEXT: # %bb.3: -; RV32IZFINX-NEXT: addi a3, a5, -1 +; RV32IZFINX-NEXT: addi a2, a4, -1 ; RV32IZFINX-NEXT: .LBB12_4: # %start -; RV32IZFINX-NEXT: and a1, a2, a3 +; RV32IZFINX-NEXT: feq.s a1, s0, s0 +; RV32IZFINX-NEXT: neg a4, a1 +; RV32IZFINX-NEXT: and a1, a4, a2 +; RV32IZFINX-NEXT: neg a2, s1 +; RV32IZFINX-NEXT: and a0, a2, a0 +; RV32IZFINX-NEXT: neg a2, a3 +; RV32IZFINX-NEXT: or a0, a2, a0 +; RV32IZFINX-NEXT: and a0, a4, a0 ; RV32IZFINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; RV32IZFINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IZFINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload -; RV32IZFINX-NEXT: lw s2, 0(sp) # 4-byte Folded Reload ; RV32IZFINX-NEXT: addi sp, sp, 16 ; RV32IZFINX-NEXT: ret ; diff --git a/llvm/test/CodeGen/RISCV/float-round-conv-sat.ll b/llvm/test/CodeGen/RISCV/float-round-conv-sat.ll index c72e69c92a132be6451bd23f7926d099f67b0101..4f747c278da03c16d44a343e7a43e4e669dc0183 100644 --- a/llvm/test/CodeGen/RISCV/float-round-conv-sat.ll +++ b/llvm/test/CodeGen/RISCV/float-round-conv-sat.ll @@ -59,23 +59,23 @@ define i64 @test_floor_si64(float %x) nounwind { ; RV32IF-NEXT: lui a2, %hi(.LCPI1_0) ; RV32IF-NEXT: flw fa5, %lo(.LCPI1_0)(a2) ; RV32IF-NEXT: and a0, s1, a0 -; RV32IF-NEXT: flt.s a4, fa5, fs0 -; RV32IF-NEXT: neg a2, a4 +; RV32IF-NEXT: flt.s a3, fa5, fs0 +; RV32IF-NEXT: neg a2, a3 ; RV32IF-NEXT: or a0, a2, a0 ; RV32IF-NEXT: feq.s a2, fs0, fs0 ; RV32IF-NEXT: neg a2, a2 ; RV32IF-NEXT: lui a5, 524288 -; RV32IF-NEXT: lui a3, 524288 +; RV32IF-NEXT: lui a4, 524288 ; RV32IF-NEXT: beqz s0, .LBB1_4 ; RV32IF-NEXT: # %bb.3: -; RV32IF-NEXT: mv a3, a1 +; RV32IF-NEXT: mv a4, a1 ; RV32IF-NEXT: .LBB1_4: ; RV32IF-NEXT: and a0, a2, a0 -; RV32IF-NEXT: beqz a4, .LBB1_6 +; RV32IF-NEXT: beqz a3, .LBB1_6 ; RV32IF-NEXT: # %bb.5: -; RV32IF-NEXT: addi a3, a5, -1 +; RV32IF-NEXT: addi a4, a5, -1 ; RV32IF-NEXT: .LBB1_6: -; RV32IF-NEXT: and a1, a2, a3 +; RV32IF-NEXT: and a1, a2, a4 ; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IF-NEXT: lw s1, 4(sp) # 4-byte Folded Reload @@ -117,23 +117,23 @@ define i64 @test_floor_si64(float %x) nounwind { ; RV32IZFINX-NEXT: lui a2, %hi(.LCPI1_0) ; RV32IZFINX-NEXT: lw a2, %lo(.LCPI1_0)(a2) ; RV32IZFINX-NEXT: and a0, s2, a0 -; RV32IZFINX-NEXT: flt.s a4, a2, s0 -; RV32IZFINX-NEXT: neg a2, a4 +; RV32IZFINX-NEXT: flt.s a3, a2, s0 +; RV32IZFINX-NEXT: neg a2, a3 ; RV32IZFINX-NEXT: or a0, a2, a0 ; RV32IZFINX-NEXT: feq.s a2, s0, s0 ; RV32IZFINX-NEXT: neg a2, a2 ; RV32IZFINX-NEXT: lui a5, 524288 -; RV32IZFINX-NEXT: lui a3, 524288 +; RV32IZFINX-NEXT: lui a4, 524288 ; RV32IZFINX-NEXT: beqz s1, .LBB1_4 ; RV32IZFINX-NEXT: # %bb.3: -; RV32IZFINX-NEXT: mv a3, a1 +; RV32IZFINX-NEXT: mv a4, a1 ; RV32IZFINX-NEXT: .LBB1_4: ; RV32IZFINX-NEXT: and a0, a2, a0 -; RV32IZFINX-NEXT: beqz a4, .LBB1_6 +; RV32IZFINX-NEXT: beqz a3, .LBB1_6 ; RV32IZFINX-NEXT: # %bb.5: -; RV32IZFINX-NEXT: addi a3, a5, -1 +; RV32IZFINX-NEXT: addi a4, a5, -1 ; RV32IZFINX-NEXT: .LBB1_6: -; RV32IZFINX-NEXT: and a1, a2, a3 +; RV32IZFINX-NEXT: and a1, a2, a4 ; RV32IZFINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; RV32IZFINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IZFINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload @@ -321,23 +321,23 @@ define i64 @test_ceil_si64(float %x) nounwind { ; RV32IF-NEXT: lui a2, %hi(.LCPI5_0) ; RV32IF-NEXT: flw fa5, %lo(.LCPI5_0)(a2) ; RV32IF-NEXT: and a0, s1, a0 -; RV32IF-NEXT: flt.s a4, fa5, fs0 -; RV32IF-NEXT: neg a2, a4 +; RV32IF-NEXT: flt.s a3, fa5, fs0 +; RV32IF-NEXT: neg a2, a3 ; RV32IF-NEXT: or a0, a2, a0 ; RV32IF-NEXT: feq.s a2, fs0, fs0 ; RV32IF-NEXT: neg a2, a2 ; RV32IF-NEXT: lui a5, 524288 -; RV32IF-NEXT: lui a3, 524288 +; RV32IF-NEXT: lui a4, 524288 ; RV32IF-NEXT: beqz s0, .LBB5_4 ; RV32IF-NEXT: # %bb.3: -; RV32IF-NEXT: mv a3, a1 +; RV32IF-NEXT: mv a4, a1 ; RV32IF-NEXT: .LBB5_4: ; RV32IF-NEXT: and a0, a2, a0 -; RV32IF-NEXT: beqz a4, .LBB5_6 +; RV32IF-NEXT: beqz a3, .LBB5_6 ; RV32IF-NEXT: # %bb.5: -; RV32IF-NEXT: addi a3, a5, -1 +; RV32IF-NEXT: addi a4, a5, -1 ; RV32IF-NEXT: .LBB5_6: -; RV32IF-NEXT: and a1, a2, a3 +; RV32IF-NEXT: and a1, a2, a4 ; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IF-NEXT: lw s1, 4(sp) # 4-byte Folded Reload @@ -379,23 +379,23 @@ define i64 @test_ceil_si64(float %x) nounwind { ; RV32IZFINX-NEXT: lui a2, %hi(.LCPI5_0) ; RV32IZFINX-NEXT: lw a2, %lo(.LCPI5_0)(a2) ; RV32IZFINX-NEXT: and a0, s2, a0 -; RV32IZFINX-NEXT: flt.s a4, a2, s0 -; RV32IZFINX-NEXT: neg a2, a4 +; RV32IZFINX-NEXT: flt.s a3, a2, s0 +; RV32IZFINX-NEXT: neg a2, a3 ; RV32IZFINX-NEXT: or a0, a2, a0 ; RV32IZFINX-NEXT: feq.s a2, s0, s0 ; RV32IZFINX-NEXT: neg a2, a2 ; RV32IZFINX-NEXT: lui a5, 524288 -; RV32IZFINX-NEXT: lui a3, 524288 +; RV32IZFINX-NEXT: lui a4, 524288 ; RV32IZFINX-NEXT: beqz s1, .LBB5_4 ; RV32IZFINX-NEXT: # %bb.3: -; RV32IZFINX-NEXT: mv a3, a1 +; RV32IZFINX-NEXT: mv a4, a1 ; RV32IZFINX-NEXT: .LBB5_4: ; RV32IZFINX-NEXT: and a0, a2, a0 -; RV32IZFINX-NEXT: beqz a4, .LBB5_6 +; RV32IZFINX-NEXT: beqz a3, .LBB5_6 ; RV32IZFINX-NEXT: # %bb.5: -; RV32IZFINX-NEXT: addi a3, a5, -1 +; RV32IZFINX-NEXT: addi a4, a5, -1 ; RV32IZFINX-NEXT: .LBB5_6: -; RV32IZFINX-NEXT: and a1, a2, a3 +; RV32IZFINX-NEXT: and a1, a2, a4 ; RV32IZFINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; RV32IZFINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IZFINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload @@ -583,23 +583,23 @@ define i64 @test_trunc_si64(float %x) nounwind { ; RV32IF-NEXT: lui a2, %hi(.LCPI9_0) ; RV32IF-NEXT: flw fa5, %lo(.LCPI9_0)(a2) ; RV32IF-NEXT: and a0, s1, a0 -; RV32IF-NEXT: flt.s a4, fa5, fs0 -; RV32IF-NEXT: neg a2, a4 +; RV32IF-NEXT: flt.s a3, fa5, fs0 +; RV32IF-NEXT: neg a2, a3 ; RV32IF-NEXT: or a0, a2, a0 ; RV32IF-NEXT: feq.s a2, fs0, fs0 ; RV32IF-NEXT: neg a2, a2 ; RV32IF-NEXT: lui a5, 524288 -; RV32IF-NEXT: lui a3, 524288 +; RV32IF-NEXT: lui a4, 524288 ; RV32IF-NEXT: beqz s0, .LBB9_4 ; RV32IF-NEXT: # %bb.3: -; RV32IF-NEXT: mv a3, a1 +; RV32IF-NEXT: mv a4, a1 ; RV32IF-NEXT: .LBB9_4: ; RV32IF-NEXT: and a0, a2, a0 -; RV32IF-NEXT: beqz a4, .LBB9_6 +; RV32IF-NEXT: beqz a3, .LBB9_6 ; RV32IF-NEXT: # %bb.5: -; RV32IF-NEXT: addi a3, a5, -1 +; RV32IF-NEXT: addi a4, a5, -1 ; RV32IF-NEXT: .LBB9_6: -; RV32IF-NEXT: and a1, a2, a3 +; RV32IF-NEXT: and a1, a2, a4 ; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IF-NEXT: lw s1, 4(sp) # 4-byte Folded Reload @@ -641,23 +641,23 @@ define i64 @test_trunc_si64(float %x) nounwind { ; RV32IZFINX-NEXT: lui a2, %hi(.LCPI9_0) ; RV32IZFINX-NEXT: lw a2, %lo(.LCPI9_0)(a2) ; RV32IZFINX-NEXT: and a0, s2, a0 -; RV32IZFINX-NEXT: flt.s a4, a2, s0 -; RV32IZFINX-NEXT: neg a2, a4 +; RV32IZFINX-NEXT: flt.s a3, a2, s0 +; RV32IZFINX-NEXT: neg a2, a3 ; RV32IZFINX-NEXT: or a0, a2, a0 ; RV32IZFINX-NEXT: feq.s a2, s0, s0 ; RV32IZFINX-NEXT: neg a2, a2 ; RV32IZFINX-NEXT: lui a5, 524288 -; RV32IZFINX-NEXT: lui a3, 524288 +; RV32IZFINX-NEXT: lui a4, 524288 ; RV32IZFINX-NEXT: beqz s1, .LBB9_4 ; RV32IZFINX-NEXT: # %bb.3: -; RV32IZFINX-NEXT: mv a3, a1 +; RV32IZFINX-NEXT: mv a4, a1 ; RV32IZFINX-NEXT: .LBB9_4: ; RV32IZFINX-NEXT: and a0, a2, a0 -; RV32IZFINX-NEXT: beqz a4, .LBB9_6 +; RV32IZFINX-NEXT: beqz a3, .LBB9_6 ; RV32IZFINX-NEXT: # %bb.5: -; RV32IZFINX-NEXT: addi a3, a5, -1 +; RV32IZFINX-NEXT: addi a4, a5, -1 ; RV32IZFINX-NEXT: .LBB9_6: -; RV32IZFINX-NEXT: and a1, a2, a3 +; RV32IZFINX-NEXT: and a1, a2, a4 ; RV32IZFINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; RV32IZFINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IZFINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload @@ -845,23 +845,23 @@ define i64 @test_round_si64(float %x) nounwind { ; RV32IF-NEXT: lui a2, %hi(.LCPI13_0) ; RV32IF-NEXT: flw fa5, %lo(.LCPI13_0)(a2) ; RV32IF-NEXT: and a0, s1, a0 -; RV32IF-NEXT: flt.s a4, fa5, fs0 -; RV32IF-NEXT: neg a2, a4 +; RV32IF-NEXT: flt.s a3, fa5, fs0 +; RV32IF-NEXT: neg a2, a3 ; RV32IF-NEXT: or a0, a2, a0 ; RV32IF-NEXT: feq.s a2, fs0, fs0 ; RV32IF-NEXT: neg a2, a2 ; RV32IF-NEXT: lui a5, 524288 -; RV32IF-NEXT: lui a3, 524288 +; RV32IF-NEXT: lui a4, 524288 ; RV32IF-NEXT: beqz s0, .LBB13_4 ; RV32IF-NEXT: # %bb.3: -; RV32IF-NEXT: mv a3, a1 +; RV32IF-NEXT: mv a4, a1 ; RV32IF-NEXT: .LBB13_4: ; RV32IF-NEXT: and a0, a2, a0 -; RV32IF-NEXT: beqz a4, .LBB13_6 +; RV32IF-NEXT: beqz a3, .LBB13_6 ; RV32IF-NEXT: # %bb.5: -; RV32IF-NEXT: addi a3, a5, -1 +; RV32IF-NEXT: addi a4, a5, -1 ; RV32IF-NEXT: .LBB13_6: -; RV32IF-NEXT: and a1, a2, a3 +; RV32IF-NEXT: and a1, a2, a4 ; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IF-NEXT: lw s1, 4(sp) # 4-byte Folded Reload @@ -903,23 +903,23 @@ define i64 @test_round_si64(float %x) nounwind { ; RV32IZFINX-NEXT: lui a2, %hi(.LCPI13_0) ; RV32IZFINX-NEXT: lw a2, %lo(.LCPI13_0)(a2) ; RV32IZFINX-NEXT: and a0, s2, a0 -; RV32IZFINX-NEXT: flt.s a4, a2, s0 -; RV32IZFINX-NEXT: neg a2, a4 +; RV32IZFINX-NEXT: flt.s a3, a2, s0 +; RV32IZFINX-NEXT: neg a2, a3 ; RV32IZFINX-NEXT: or a0, a2, a0 ; RV32IZFINX-NEXT: feq.s a2, s0, s0 ; RV32IZFINX-NEXT: neg a2, a2 ; RV32IZFINX-NEXT: lui a5, 524288 -; RV32IZFINX-NEXT: lui a3, 524288 +; RV32IZFINX-NEXT: lui a4, 524288 ; RV32IZFINX-NEXT: beqz s1, .LBB13_4 ; RV32IZFINX-NEXT: # %bb.3: -; RV32IZFINX-NEXT: mv a3, a1 +; RV32IZFINX-NEXT: mv a4, a1 ; RV32IZFINX-NEXT: .LBB13_4: ; RV32IZFINX-NEXT: and a0, a2, a0 -; RV32IZFINX-NEXT: beqz a4, .LBB13_6 +; RV32IZFINX-NEXT: beqz a3, .LBB13_6 ; RV32IZFINX-NEXT: # %bb.5: -; RV32IZFINX-NEXT: addi a3, a5, -1 +; RV32IZFINX-NEXT: addi a4, a5, -1 ; RV32IZFINX-NEXT: .LBB13_6: -; RV32IZFINX-NEXT: and a1, a2, a3 +; RV32IZFINX-NEXT: and a1, a2, a4 ; RV32IZFINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; RV32IZFINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IZFINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload @@ -1107,23 +1107,23 @@ define i64 @test_roundeven_si64(float %x) nounwind { ; RV32IF-NEXT: lui a2, %hi(.LCPI17_0) ; RV32IF-NEXT: flw fa5, %lo(.LCPI17_0)(a2) ; RV32IF-NEXT: and a0, s1, a0 -; RV32IF-NEXT: flt.s a4, fa5, fs0 -; RV32IF-NEXT: neg a2, a4 +; RV32IF-NEXT: flt.s a3, fa5, fs0 +; RV32IF-NEXT: neg a2, a3 ; RV32IF-NEXT: or a0, a2, a0 ; RV32IF-NEXT: feq.s a2, fs0, fs0 ; RV32IF-NEXT: neg a2, a2 ; RV32IF-NEXT: lui a5, 524288 -; RV32IF-NEXT: lui a3, 524288 +; RV32IF-NEXT: lui a4, 524288 ; RV32IF-NEXT: beqz s0, .LBB17_4 ; RV32IF-NEXT: # %bb.3: -; RV32IF-NEXT: mv a3, a1 +; RV32IF-NEXT: mv a4, a1 ; RV32IF-NEXT: .LBB17_4: ; RV32IF-NEXT: and a0, a2, a0 -; RV32IF-NEXT: beqz a4, .LBB17_6 +; RV32IF-NEXT: beqz a3, .LBB17_6 ; RV32IF-NEXT: # %bb.5: -; RV32IF-NEXT: addi a3, a5, -1 +; RV32IF-NEXT: addi a4, a5, -1 ; RV32IF-NEXT: .LBB17_6: -; RV32IF-NEXT: and a1, a2, a3 +; RV32IF-NEXT: and a1, a2, a4 ; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IF-NEXT: lw s1, 4(sp) # 4-byte Folded Reload @@ -1165,23 +1165,23 @@ define i64 @test_roundeven_si64(float %x) nounwind { ; RV32IZFINX-NEXT: lui a2, %hi(.LCPI17_0) ; RV32IZFINX-NEXT: lw a2, %lo(.LCPI17_0)(a2) ; RV32IZFINX-NEXT: and a0, s2, a0 -; RV32IZFINX-NEXT: flt.s a4, a2, s0 -; RV32IZFINX-NEXT: neg a2, a4 +; RV32IZFINX-NEXT: flt.s a3, a2, s0 +; RV32IZFINX-NEXT: neg a2, a3 ; RV32IZFINX-NEXT: or a0, a2, a0 ; RV32IZFINX-NEXT: feq.s a2, s0, s0 ; RV32IZFINX-NEXT: neg a2, a2 ; RV32IZFINX-NEXT: lui a5, 524288 -; RV32IZFINX-NEXT: lui a3, 524288 +; RV32IZFINX-NEXT: lui a4, 524288 ; RV32IZFINX-NEXT: beqz s1, .LBB17_4 ; RV32IZFINX-NEXT: # %bb.3: -; RV32IZFINX-NEXT: mv a3, a1 +; RV32IZFINX-NEXT: mv a4, a1 ; RV32IZFINX-NEXT: .LBB17_4: ; RV32IZFINX-NEXT: and a0, a2, a0 -; RV32IZFINX-NEXT: beqz a4, .LBB17_6 +; RV32IZFINX-NEXT: beqz a3, .LBB17_6 ; RV32IZFINX-NEXT: # %bb.5: -; RV32IZFINX-NEXT: addi a3, a5, -1 +; RV32IZFINX-NEXT: addi a4, a5, -1 ; RV32IZFINX-NEXT: .LBB17_6: -; RV32IZFINX-NEXT: and a1, a2, a3 +; RV32IZFINX-NEXT: and a1, a2, a4 ; RV32IZFINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; RV32IZFINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IZFINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload @@ -1369,23 +1369,23 @@ define i64 @test_rint_si64(float %x) nounwind { ; RV32IF-NEXT: lui a2, %hi(.LCPI21_0) ; RV32IF-NEXT: flw fa5, %lo(.LCPI21_0)(a2) ; RV32IF-NEXT: and a0, s1, a0 -; RV32IF-NEXT: flt.s a4, fa5, fs0 -; RV32IF-NEXT: neg a2, a4 +; RV32IF-NEXT: flt.s a3, fa5, fs0 +; RV32IF-NEXT: neg a2, a3 ; RV32IF-NEXT: or a0, a2, a0 ; RV32IF-NEXT: feq.s a2, fs0, fs0 ; RV32IF-NEXT: neg a2, a2 ; RV32IF-NEXT: lui a5, 524288 -; RV32IF-NEXT: lui a3, 524288 +; RV32IF-NEXT: lui a4, 524288 ; RV32IF-NEXT: beqz s0, .LBB21_4 ; RV32IF-NEXT: # %bb.3: -; RV32IF-NEXT: mv a3, a1 +; RV32IF-NEXT: mv a4, a1 ; RV32IF-NEXT: .LBB21_4: ; RV32IF-NEXT: and a0, a2, a0 -; RV32IF-NEXT: beqz a4, .LBB21_6 +; RV32IF-NEXT: beqz a3, .LBB21_6 ; RV32IF-NEXT: # %bb.5: -; RV32IF-NEXT: addi a3, a5, -1 +; RV32IF-NEXT: addi a4, a5, -1 ; RV32IF-NEXT: .LBB21_6: -; RV32IF-NEXT: and a1, a2, a3 +; RV32IF-NEXT: and a1, a2, a4 ; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IF-NEXT: lw s1, 4(sp) # 4-byte Folded Reload @@ -1427,23 +1427,23 @@ define i64 @test_rint_si64(float %x) nounwind { ; RV32IZFINX-NEXT: lui a2, %hi(.LCPI21_0) ; RV32IZFINX-NEXT: lw a2, %lo(.LCPI21_0)(a2) ; RV32IZFINX-NEXT: and a0, s2, a0 -; RV32IZFINX-NEXT: flt.s a4, a2, s0 -; RV32IZFINX-NEXT: neg a2, a4 +; RV32IZFINX-NEXT: flt.s a3, a2, s0 +; RV32IZFINX-NEXT: neg a2, a3 ; RV32IZFINX-NEXT: or a0, a2, a0 ; RV32IZFINX-NEXT: feq.s a2, s0, s0 ; RV32IZFINX-NEXT: neg a2, a2 ; RV32IZFINX-NEXT: lui a5, 524288 -; RV32IZFINX-NEXT: lui a3, 524288 +; RV32IZFINX-NEXT: lui a4, 524288 ; RV32IZFINX-NEXT: beqz s1, .LBB21_4 ; RV32IZFINX-NEXT: # %bb.3: -; RV32IZFINX-NEXT: mv a3, a1 +; RV32IZFINX-NEXT: mv a4, a1 ; RV32IZFINX-NEXT: .LBB21_4: ; RV32IZFINX-NEXT: and a0, a2, a0 -; RV32IZFINX-NEXT: beqz a4, .LBB21_6 +; RV32IZFINX-NEXT: beqz a3, .LBB21_6 ; RV32IZFINX-NEXT: # %bb.5: -; RV32IZFINX-NEXT: addi a3, a5, -1 +; RV32IZFINX-NEXT: addi a4, a5, -1 ; RV32IZFINX-NEXT: .LBB21_6: -; RV32IZFINX-NEXT: and a1, a2, a3 +; RV32IZFINX-NEXT: and a1, a2, a4 ; RV32IZFINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; RV32IZFINX-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IZFINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload diff --git a/llvm/test/CodeGen/RISCV/half-convert-strict.ll b/llvm/test/CodeGen/RISCV/half-convert-strict.ll index f03a020762bb3c4742b5807873f2625b0f3394a0..677aa9263ea6155d2857f553343d01b7bbe208ef 100644 --- a/llvm/test/CodeGen/RISCV/half-convert-strict.ll +++ b/llvm/test/CodeGen/RISCV/half-convert-strict.ll @@ -1745,13 +1745,7 @@ define half @fcvt_h_d(double %a) nounwind strictfp { ; ; RV32IZDINXZHINX-LABEL: fcvt_h_d: ; RV32IZDINXZHINX: # %bb.0: -; RV32IZDINXZHINX-NEXT: addi sp, sp, -16 -; RV32IZDINXZHINX-NEXT: sw a0, 8(sp) -; RV32IZDINXZHINX-NEXT: sw a1, 12(sp) -; RV32IZDINXZHINX-NEXT: lw a0, 8(sp) -; RV32IZDINXZHINX-NEXT: lw a1, 12(sp) ; RV32IZDINXZHINX-NEXT: fcvt.h.d a0, a0 -; RV32IZDINXZHINX-NEXT: addi sp, sp, 16 ; RV32IZDINXZHINX-NEXT: ret ; ; RV64IZDINXZHINX-LABEL: fcvt_h_d: @@ -1807,13 +1801,7 @@ define half @fcvt_h_d(double %a) nounwind strictfp { ; ; CHECK32-IZDINXZHINXMIN-LABEL: fcvt_h_d: ; CHECK32-IZDINXZHINXMIN: # %bb.0: -; CHECK32-IZDINXZHINXMIN-NEXT: addi sp, sp, -16 -; CHECK32-IZDINXZHINXMIN-NEXT: sw a0, 8(sp) -; CHECK32-IZDINXZHINXMIN-NEXT: sw a1, 12(sp) -; CHECK32-IZDINXZHINXMIN-NEXT: lw a0, 8(sp) -; CHECK32-IZDINXZHINXMIN-NEXT: lw a1, 12(sp) ; CHECK32-IZDINXZHINXMIN-NEXT: fcvt.h.d a0, a0 -; CHECK32-IZDINXZHINXMIN-NEXT: addi sp, sp, 16 ; CHECK32-IZDINXZHINXMIN-NEXT: ret ; ; CHECK64-IZDINXZHINXMIN-LABEL: fcvt_h_d: @@ -1878,13 +1866,7 @@ define double @fcvt_d_h(half %a) nounwind strictfp { ; ; RV32IZDINXZHINX-LABEL: fcvt_d_h: ; RV32IZDINXZHINX: # %bb.0: -; RV32IZDINXZHINX-NEXT: addi sp, sp, -16 ; RV32IZDINXZHINX-NEXT: fcvt.d.h a0, a0 -; RV32IZDINXZHINX-NEXT: sw a0, 8(sp) -; RV32IZDINXZHINX-NEXT: sw a1, 12(sp) -; RV32IZDINXZHINX-NEXT: lw a0, 8(sp) -; RV32IZDINXZHINX-NEXT: lw a1, 12(sp) -; RV32IZDINXZHINX-NEXT: addi sp, sp, 16 ; RV32IZDINXZHINX-NEXT: ret ; ; RV64IZDINXZHINX-LABEL: fcvt_d_h: @@ -1944,13 +1926,7 @@ define double @fcvt_d_h(half %a) nounwind strictfp { ; ; CHECK32-IZDINXZHINXMIN-LABEL: fcvt_d_h: ; CHECK32-IZDINXZHINXMIN: # %bb.0: -; CHECK32-IZDINXZHINXMIN-NEXT: addi sp, sp, -16 ; CHECK32-IZDINXZHINXMIN-NEXT: fcvt.d.h a0, a0 -; CHECK32-IZDINXZHINXMIN-NEXT: sw a0, 8(sp) -; CHECK32-IZDINXZHINXMIN-NEXT: sw a1, 12(sp) -; CHECK32-IZDINXZHINXMIN-NEXT: lw a0, 8(sp) -; CHECK32-IZDINXZHINXMIN-NEXT: lw a1, 12(sp) -; CHECK32-IZDINXZHINXMIN-NEXT: addi sp, sp, 16 ; CHECK32-IZDINXZHINXMIN-NEXT: ret ; ; CHECK64-IZDINXZHINXMIN-LABEL: fcvt_d_h: diff --git a/llvm/test/CodeGen/RISCV/half-convert.ll b/llvm/test/CodeGen/RISCV/half-convert.ll index 28ac6e272e11df308c460f79a785327c5dbd91a6..16c096290720d37bce06d7d45acc2c0fd79dc58c 100644 --- a/llvm/test/CodeGen/RISCV/half-convert.ll +++ b/llvm/test/CodeGen/RISCV/half-convert.ll @@ -2460,47 +2460,42 @@ define i64 @fcvt_l_h_sat(half %a) nounwind { ; ; RV32ID-ILP32-LABEL: fcvt_l_h_sat: ; RV32ID-ILP32: # %bb.0: # %start -; RV32ID-ILP32-NEXT: addi sp, sp, -32 -; RV32ID-ILP32-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32ID-ILP32-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32ID-ILP32-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32ID-ILP32-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32ID-ILP32-NEXT: sw s3, 12(sp) # 4-byte Folded Spill +; RV32ID-ILP32-NEXT: addi sp, sp, -16 +; RV32ID-ILP32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32ID-ILP32-NEXT: sw s0, 8(sp) # 4-byte Folded Spill ; RV32ID-ILP32-NEXT: call __extendhfsf2 -; RV32ID-ILP32-NEXT: lui a1, %hi(.LCPI10_0) -; RV32ID-ILP32-NEXT: flw fa5, %lo(.LCPI10_0)(a1) ; RV32ID-ILP32-NEXT: fmv.w.x fa4, a0 -; RV32ID-ILP32-NEXT: fsw fa4, 8(sp) # 4-byte Folded Spill -; RV32ID-ILP32-NEXT: flt.s s0, fa5, fa4 -; RV32ID-ILP32-NEXT: neg s1, s0 ; RV32ID-ILP32-NEXT: lui a1, 913408 ; RV32ID-ILP32-NEXT: fmv.w.x fa5, a1 -; RV32ID-ILP32-NEXT: fle.s s2, fa5, fa4 -; RV32ID-ILP32-NEXT: neg s3, s2 +; RV32ID-ILP32-NEXT: fsw fa4, 4(sp) # 4-byte Folded Spill +; RV32ID-ILP32-NEXT: fle.s s0, fa5, fa4 ; RV32ID-ILP32-NEXT: call __fixsfdi -; RV32ID-ILP32-NEXT: and a0, s3, a0 -; RV32ID-ILP32-NEXT: or a0, s1, a0 -; RV32ID-ILP32-NEXT: flw fa5, 8(sp) # 4-byte Folded Reload -; RV32ID-ILP32-NEXT: feq.s a2, fa5, fa5 -; RV32ID-ILP32-NEXT: neg a2, a2 ; RV32ID-ILP32-NEXT: lui a4, 524288 -; RV32ID-ILP32-NEXT: lui a3, 524288 -; RV32ID-ILP32-NEXT: beqz s2, .LBB10_2 +; RV32ID-ILP32-NEXT: lui a2, 524288 +; RV32ID-ILP32-NEXT: beqz s0, .LBB10_2 ; RV32ID-ILP32-NEXT: # %bb.1: # %start -; RV32ID-ILP32-NEXT: mv a3, a1 +; RV32ID-ILP32-NEXT: mv a2, a1 ; RV32ID-ILP32-NEXT: .LBB10_2: # %start -; RV32ID-ILP32-NEXT: and a0, a2, a0 -; RV32ID-ILP32-NEXT: beqz s0, .LBB10_4 +; RV32ID-ILP32-NEXT: lui a1, %hi(.LCPI10_0) +; RV32ID-ILP32-NEXT: flw fa5, %lo(.LCPI10_0)(a1) +; RV32ID-ILP32-NEXT: flw fa4, 4(sp) # 4-byte Folded Reload +; RV32ID-ILP32-NEXT: flt.s a3, fa5, fa4 +; RV32ID-ILP32-NEXT: fmv.s fa5, fa4 +; RV32ID-ILP32-NEXT: beqz a3, .LBB10_4 ; RV32ID-ILP32-NEXT: # %bb.3: -; RV32ID-ILP32-NEXT: addi a3, a4, -1 +; RV32ID-ILP32-NEXT: addi a2, a4, -1 ; RV32ID-ILP32-NEXT: .LBB10_4: # %start -; RV32ID-ILP32-NEXT: and a1, a2, a3 -; RV32ID-ILP32-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32ID-ILP32-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32ID-ILP32-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32ID-ILP32-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32ID-ILP32-NEXT: lw s3, 12(sp) # 4-byte Folded Reload -; RV32ID-ILP32-NEXT: addi sp, sp, 32 +; RV32ID-ILP32-NEXT: feq.s a1, fa5, fa5 +; RV32ID-ILP32-NEXT: neg a4, a1 +; RV32ID-ILP32-NEXT: and a1, a4, a2 +; RV32ID-ILP32-NEXT: neg a2, a3 +; RV32ID-ILP32-NEXT: neg a3, s0 +; RV32ID-ILP32-NEXT: and a0, a3, a0 +; RV32ID-ILP32-NEXT: or a0, a2, a0 +; RV32ID-ILP32-NEXT: and a0, a4, a0 +; RV32ID-ILP32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32ID-ILP32-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; RV32ID-ILP32-NEXT: addi sp, sp, 16 ; RV32ID-ILP32-NEXT: ret ; ; RV64ID-LP64-LABEL: fcvt_l_h_sat: @@ -5275,21 +5270,10 @@ define half @fcvt_h_d(double %a) nounwind { ; RV64IZHINX-NEXT: addi sp, sp, 16 ; RV64IZHINX-NEXT: ret ; -; RV32IZDINXZHINX-LABEL: fcvt_h_d: -; RV32IZDINXZHINX: # %bb.0: -; RV32IZDINXZHINX-NEXT: addi sp, sp, -16 -; RV32IZDINXZHINX-NEXT: sw a0, 8(sp) -; RV32IZDINXZHINX-NEXT: sw a1, 12(sp) -; RV32IZDINXZHINX-NEXT: lw a0, 8(sp) -; RV32IZDINXZHINX-NEXT: lw a1, 12(sp) -; RV32IZDINXZHINX-NEXT: fcvt.h.d a0, a0 -; RV32IZDINXZHINX-NEXT: addi sp, sp, 16 -; RV32IZDINXZHINX-NEXT: ret -; -; RV64IZDINXZHINX-LABEL: fcvt_h_d: -; RV64IZDINXZHINX: # %bb.0: -; RV64IZDINXZHINX-NEXT: fcvt.h.d a0, a0 -; RV64IZDINXZHINX-NEXT: ret +; CHECKIZDINXZHINX-LABEL: fcvt_h_d: +; CHECKIZDINXZHINX: # %bb.0: +; CHECKIZDINXZHINX-NEXT: fcvt.h.d a0, a0 +; CHECKIZDINXZHINX-NEXT: ret ; ; RV32I-LABEL: fcvt_h_d: ; RV32I: # %bb.0: @@ -5405,13 +5389,7 @@ define half @fcvt_h_d(double %a) nounwind { ; ; CHECK32-IZDINXZHINXMIN-LABEL: fcvt_h_d: ; CHECK32-IZDINXZHINXMIN: # %bb.0: -; CHECK32-IZDINXZHINXMIN-NEXT: addi sp, sp, -16 -; CHECK32-IZDINXZHINXMIN-NEXT: sw a0, 8(sp) -; CHECK32-IZDINXZHINXMIN-NEXT: sw a1, 12(sp) -; CHECK32-IZDINXZHINXMIN-NEXT: lw a0, 8(sp) -; CHECK32-IZDINXZHINXMIN-NEXT: lw a1, 12(sp) ; CHECK32-IZDINXZHINXMIN-NEXT: fcvt.h.d a0, a0 -; CHECK32-IZDINXZHINXMIN-NEXT: addi sp, sp, 16 ; CHECK32-IZDINXZHINXMIN-NEXT: ret ; ; CHECK64-IZDINXZHINXMIN-LABEL: fcvt_h_d: @@ -5473,21 +5451,10 @@ define double @fcvt_d_h(half %a) nounwind { ; RV64IZHINX-NEXT: addi sp, sp, 16 ; RV64IZHINX-NEXT: ret ; -; RV32IZDINXZHINX-LABEL: fcvt_d_h: -; RV32IZDINXZHINX: # %bb.0: -; RV32IZDINXZHINX-NEXT: addi sp, sp, -16 -; RV32IZDINXZHINX-NEXT: fcvt.d.h a0, a0 -; RV32IZDINXZHINX-NEXT: sw a0, 8(sp) -; RV32IZDINXZHINX-NEXT: sw a1, 12(sp) -; RV32IZDINXZHINX-NEXT: lw a0, 8(sp) -; RV32IZDINXZHINX-NEXT: lw a1, 12(sp) -; RV32IZDINXZHINX-NEXT: addi sp, sp, 16 -; RV32IZDINXZHINX-NEXT: ret -; -; RV64IZDINXZHINX-LABEL: fcvt_d_h: -; RV64IZDINXZHINX: # %bb.0: -; RV64IZDINXZHINX-NEXT: fcvt.d.h a0, a0 -; RV64IZDINXZHINX-NEXT: ret +; CHECKIZDINXZHINX-LABEL: fcvt_d_h: +; CHECKIZDINXZHINX: # %bb.0: +; CHECKIZDINXZHINX-NEXT: fcvt.d.h a0, a0 +; CHECKIZDINXZHINX-NEXT: ret ; ; RV32I-LABEL: fcvt_d_h: ; RV32I: # %bb.0: @@ -5607,13 +5574,7 @@ define double @fcvt_d_h(half %a) nounwind { ; ; CHECK32-IZDINXZHINXMIN-LABEL: fcvt_d_h: ; CHECK32-IZDINXZHINXMIN: # %bb.0: -; CHECK32-IZDINXZHINXMIN-NEXT: addi sp, sp, -16 ; CHECK32-IZDINXZHINXMIN-NEXT: fcvt.d.h a0, a0 -; CHECK32-IZDINXZHINXMIN-NEXT: sw a0, 8(sp) -; CHECK32-IZDINXZHINXMIN-NEXT: sw a1, 12(sp) -; CHECK32-IZDINXZHINXMIN-NEXT: lw a0, 8(sp) -; CHECK32-IZDINXZHINXMIN-NEXT: lw a1, 12(sp) -; CHECK32-IZDINXZHINXMIN-NEXT: addi sp, sp, 16 ; CHECK32-IZDINXZHINXMIN-NEXT: ret ; ; CHECK64-IZDINXZHINXMIN-LABEL: fcvt_d_h: diff --git a/llvm/test/CodeGen/RISCV/half-round-conv-sat.ll b/llvm/test/CodeGen/RISCV/half-round-conv-sat.ll index dd1115b20225b2cb76153470373fac5e52ad5b9d..9c95210bfa7c01cb2b98880d18c2d8f2f45f075e 100644 --- a/llvm/test/CodeGen/RISCV/half-round-conv-sat.ll +++ b/llvm/test/CodeGen/RISCV/half-round-conv-sat.ll @@ -120,16 +120,16 @@ define i64 @test_floor_si64(half %x) nounwind { ; RV32IZFH-NEXT: lui a2, %hi(.LCPI1_1) ; RV32IZFH-NEXT: flw fa5, %lo(.LCPI1_1)(a2) ; RV32IZFH-NEXT: and a0, s1, a0 -; RV32IZFH-NEXT: flt.s a4, fa5, fs0 -; RV32IZFH-NEXT: neg a2, a4 +; RV32IZFH-NEXT: flt.s a3, fa5, fs0 +; RV32IZFH-NEXT: neg a2, a3 ; RV32IZFH-NEXT: or a0, a2, a0 ; RV32IZFH-NEXT: feq.s a2, fs0, fs0 ; RV32IZFH-NEXT: neg a2, a2 ; RV32IZFH-NEXT: lui a5, 524288 -; RV32IZFH-NEXT: lui a3, 524288 +; RV32IZFH-NEXT: lui a4, 524288 ; RV32IZFH-NEXT: beqz s0, .LBB1_4 ; RV32IZFH-NEXT: # %bb.3: -; RV32IZFH-NEXT: mv a3, a1 +; RV32IZFH-NEXT: mv a4, a1 ; RV32IZFH-NEXT: .LBB1_4: ; RV32IZFH-NEXT: and a0, a2, a0 ; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -137,11 +137,11 @@ define i64 @test_floor_si64(half %x) nounwind { ; RV32IZFH-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZFH-NEXT: flw fs0, 0(sp) # 4-byte Folded Reload ; RV32IZFH-NEXT: addi sp, sp, 16 -; RV32IZFH-NEXT: beqz a4, .LBB1_6 +; RV32IZFH-NEXT: beqz a3, .LBB1_6 ; RV32IZFH-NEXT: # %bb.5: -; RV32IZFH-NEXT: addi a3, a5, -1 +; RV32IZFH-NEXT: addi a4, a5, -1 ; RV32IZFH-NEXT: .LBB1_6: -; RV32IZFH-NEXT: and a1, a2, a3 +; RV32IZFH-NEXT: and a1, a2, a4 ; RV32IZFH-NEXT: ret ; ; RV64IZFH-LABEL: test_floor_si64: @@ -179,16 +179,16 @@ define i64 @test_floor_si64(half %x) nounwind { ; RV32IZHINX-NEXT: lui a2, %hi(.LCPI1_1) ; RV32IZHINX-NEXT: lw a2, %lo(.LCPI1_1)(a2) ; RV32IZHINX-NEXT: and a0, s2, a0 -; RV32IZHINX-NEXT: flt.s a4, a2, s0 -; RV32IZHINX-NEXT: neg a2, a4 +; RV32IZHINX-NEXT: flt.s a3, a2, s0 +; RV32IZHINX-NEXT: neg a2, a3 ; RV32IZHINX-NEXT: or a0, a2, a0 ; RV32IZHINX-NEXT: feq.s a2, s0, s0 ; RV32IZHINX-NEXT: neg a2, a2 ; RV32IZHINX-NEXT: lui a5, 524288 -; RV32IZHINX-NEXT: lui a3, 524288 +; RV32IZHINX-NEXT: lui a4, 524288 ; RV32IZHINX-NEXT: beqz s1, .LBB1_4 ; RV32IZHINX-NEXT: # %bb.3: -; RV32IZHINX-NEXT: mv a3, a1 +; RV32IZHINX-NEXT: mv a4, a1 ; RV32IZHINX-NEXT: .LBB1_4: ; RV32IZHINX-NEXT: and a0, a2, a0 ; RV32IZHINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -196,11 +196,11 @@ define i64 @test_floor_si64(half %x) nounwind { ; RV32IZHINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZHINX-NEXT: lw s2, 0(sp) # 4-byte Folded Reload ; RV32IZHINX-NEXT: addi sp, sp, 16 -; RV32IZHINX-NEXT: beqz a4, .LBB1_6 +; RV32IZHINX-NEXT: beqz a3, .LBB1_6 ; RV32IZHINX-NEXT: # %bb.5: -; RV32IZHINX-NEXT: addi a3, a5, -1 +; RV32IZHINX-NEXT: addi a4, a5, -1 ; RV32IZHINX-NEXT: .LBB1_6: -; RV32IZHINX-NEXT: and a1, a2, a3 +; RV32IZHINX-NEXT: and a1, a2, a4 ; RV32IZHINX-NEXT: ret ; ; RV64IZHINX-LABEL: test_floor_si64: @@ -251,16 +251,16 @@ define i64 @test_floor_si64(half %x) nounwind { ; RV32IZFHMIN-NEXT: lui a2, %hi(.LCPI1_0) ; RV32IZFHMIN-NEXT: flw fa5, %lo(.LCPI1_0)(a2) ; RV32IZFHMIN-NEXT: and a0, s1, a0 -; RV32IZFHMIN-NEXT: flt.s a4, fa5, fs0 -; RV32IZFHMIN-NEXT: neg a2, a4 +; RV32IZFHMIN-NEXT: flt.s a3, fa5, fs0 +; RV32IZFHMIN-NEXT: neg a2, a3 ; RV32IZFHMIN-NEXT: or a0, a2, a0 ; RV32IZFHMIN-NEXT: feq.s a2, fs0, fs0 ; RV32IZFHMIN-NEXT: neg a2, a2 ; RV32IZFHMIN-NEXT: lui a5, 524288 -; RV32IZFHMIN-NEXT: lui a3, 524288 +; RV32IZFHMIN-NEXT: lui a4, 524288 ; RV32IZFHMIN-NEXT: beqz s0, .LBB1_4 ; RV32IZFHMIN-NEXT: # %bb.3: -; RV32IZFHMIN-NEXT: mv a3, a1 +; RV32IZFHMIN-NEXT: mv a4, a1 ; RV32IZFHMIN-NEXT: .LBB1_4: ; RV32IZFHMIN-NEXT: and a0, a2, a0 ; RV32IZFHMIN-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -268,11 +268,11 @@ define i64 @test_floor_si64(half %x) nounwind { ; RV32IZFHMIN-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZFHMIN-NEXT: flw fs0, 0(sp) # 4-byte Folded Reload ; RV32IZFHMIN-NEXT: addi sp, sp, 16 -; RV32IZFHMIN-NEXT: beqz a4, .LBB1_6 +; RV32IZFHMIN-NEXT: beqz a3, .LBB1_6 ; RV32IZFHMIN-NEXT: # %bb.5: -; RV32IZFHMIN-NEXT: addi a3, a5, -1 +; RV32IZFHMIN-NEXT: addi a4, a5, -1 ; RV32IZFHMIN-NEXT: .LBB1_6: -; RV32IZFHMIN-NEXT: and a1, a2, a3 +; RV32IZFHMIN-NEXT: and a1, a2, a4 ; RV32IZFHMIN-NEXT: ret ; ; RV64IZFHMIN-LABEL: test_floor_si64: @@ -324,16 +324,16 @@ define i64 @test_floor_si64(half %x) nounwind { ; RV32IZHINXMIN-NEXT: lui a2, %hi(.LCPI1_0) ; RV32IZHINXMIN-NEXT: lw a2, %lo(.LCPI1_0)(a2) ; RV32IZHINXMIN-NEXT: and a0, s2, a0 -; RV32IZHINXMIN-NEXT: flt.s a4, a2, s0 -; RV32IZHINXMIN-NEXT: neg a2, a4 +; RV32IZHINXMIN-NEXT: flt.s a3, a2, s0 +; RV32IZHINXMIN-NEXT: neg a2, a3 ; RV32IZHINXMIN-NEXT: or a0, a2, a0 ; RV32IZHINXMIN-NEXT: feq.s a2, s0, s0 ; RV32IZHINXMIN-NEXT: neg a2, a2 ; RV32IZHINXMIN-NEXT: lui a5, 524288 -; RV32IZHINXMIN-NEXT: lui a3, 524288 +; RV32IZHINXMIN-NEXT: lui a4, 524288 ; RV32IZHINXMIN-NEXT: beqz s1, .LBB1_4 ; RV32IZHINXMIN-NEXT: # %bb.3: -; RV32IZHINXMIN-NEXT: mv a3, a1 +; RV32IZHINXMIN-NEXT: mv a4, a1 ; RV32IZHINXMIN-NEXT: .LBB1_4: ; RV32IZHINXMIN-NEXT: and a0, a2, a0 ; RV32IZHINXMIN-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -341,11 +341,11 @@ define i64 @test_floor_si64(half %x) nounwind { ; RV32IZHINXMIN-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZHINXMIN-NEXT: lw s2, 0(sp) # 4-byte Folded Reload ; RV32IZHINXMIN-NEXT: addi sp, sp, 16 -; RV32IZHINXMIN-NEXT: beqz a4, .LBB1_6 +; RV32IZHINXMIN-NEXT: beqz a3, .LBB1_6 ; RV32IZHINXMIN-NEXT: # %bb.5: -; RV32IZHINXMIN-NEXT: addi a3, a5, -1 +; RV32IZHINXMIN-NEXT: addi a4, a5, -1 ; RV32IZHINXMIN-NEXT: .LBB1_6: -; RV32IZHINXMIN-NEXT: and a1, a2, a3 +; RV32IZHINXMIN-NEXT: and a1, a2, a4 ; RV32IZHINXMIN-NEXT: ret ; ; RV64IZHINXMIN-LABEL: test_floor_si64: @@ -836,16 +836,16 @@ define i64 @test_ceil_si64(half %x) nounwind { ; RV32IZFH-NEXT: lui a2, %hi(.LCPI5_1) ; RV32IZFH-NEXT: flw fa5, %lo(.LCPI5_1)(a2) ; RV32IZFH-NEXT: and a0, s1, a0 -; RV32IZFH-NEXT: flt.s a4, fa5, fs0 -; RV32IZFH-NEXT: neg a2, a4 +; RV32IZFH-NEXT: flt.s a3, fa5, fs0 +; RV32IZFH-NEXT: neg a2, a3 ; RV32IZFH-NEXT: or a0, a2, a0 ; RV32IZFH-NEXT: feq.s a2, fs0, fs0 ; RV32IZFH-NEXT: neg a2, a2 ; RV32IZFH-NEXT: lui a5, 524288 -; RV32IZFH-NEXT: lui a3, 524288 +; RV32IZFH-NEXT: lui a4, 524288 ; RV32IZFH-NEXT: beqz s0, .LBB5_4 ; RV32IZFH-NEXT: # %bb.3: -; RV32IZFH-NEXT: mv a3, a1 +; RV32IZFH-NEXT: mv a4, a1 ; RV32IZFH-NEXT: .LBB5_4: ; RV32IZFH-NEXT: and a0, a2, a0 ; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -853,11 +853,11 @@ define i64 @test_ceil_si64(half %x) nounwind { ; RV32IZFH-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZFH-NEXT: flw fs0, 0(sp) # 4-byte Folded Reload ; RV32IZFH-NEXT: addi sp, sp, 16 -; RV32IZFH-NEXT: beqz a4, .LBB5_6 +; RV32IZFH-NEXT: beqz a3, .LBB5_6 ; RV32IZFH-NEXT: # %bb.5: -; RV32IZFH-NEXT: addi a3, a5, -1 +; RV32IZFH-NEXT: addi a4, a5, -1 ; RV32IZFH-NEXT: .LBB5_6: -; RV32IZFH-NEXT: and a1, a2, a3 +; RV32IZFH-NEXT: and a1, a2, a4 ; RV32IZFH-NEXT: ret ; ; RV64IZFH-LABEL: test_ceil_si64: @@ -895,16 +895,16 @@ define i64 @test_ceil_si64(half %x) nounwind { ; RV32IZHINX-NEXT: lui a2, %hi(.LCPI5_1) ; RV32IZHINX-NEXT: lw a2, %lo(.LCPI5_1)(a2) ; RV32IZHINX-NEXT: and a0, s2, a0 -; RV32IZHINX-NEXT: flt.s a4, a2, s0 -; RV32IZHINX-NEXT: neg a2, a4 +; RV32IZHINX-NEXT: flt.s a3, a2, s0 +; RV32IZHINX-NEXT: neg a2, a3 ; RV32IZHINX-NEXT: or a0, a2, a0 ; RV32IZHINX-NEXT: feq.s a2, s0, s0 ; RV32IZHINX-NEXT: neg a2, a2 ; RV32IZHINX-NEXT: lui a5, 524288 -; RV32IZHINX-NEXT: lui a3, 524288 +; RV32IZHINX-NEXT: lui a4, 524288 ; RV32IZHINX-NEXT: beqz s1, .LBB5_4 ; RV32IZHINX-NEXT: # %bb.3: -; RV32IZHINX-NEXT: mv a3, a1 +; RV32IZHINX-NEXT: mv a4, a1 ; RV32IZHINX-NEXT: .LBB5_4: ; RV32IZHINX-NEXT: and a0, a2, a0 ; RV32IZHINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -912,11 +912,11 @@ define i64 @test_ceil_si64(half %x) nounwind { ; RV32IZHINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZHINX-NEXT: lw s2, 0(sp) # 4-byte Folded Reload ; RV32IZHINX-NEXT: addi sp, sp, 16 -; RV32IZHINX-NEXT: beqz a4, .LBB5_6 +; RV32IZHINX-NEXT: beqz a3, .LBB5_6 ; RV32IZHINX-NEXT: # %bb.5: -; RV32IZHINX-NEXT: addi a3, a5, -1 +; RV32IZHINX-NEXT: addi a4, a5, -1 ; RV32IZHINX-NEXT: .LBB5_6: -; RV32IZHINX-NEXT: and a1, a2, a3 +; RV32IZHINX-NEXT: and a1, a2, a4 ; RV32IZHINX-NEXT: ret ; ; RV64IZHINX-LABEL: test_ceil_si64: @@ -967,16 +967,16 @@ define i64 @test_ceil_si64(half %x) nounwind { ; RV32IZFHMIN-NEXT: lui a2, %hi(.LCPI5_0) ; RV32IZFHMIN-NEXT: flw fa5, %lo(.LCPI5_0)(a2) ; RV32IZFHMIN-NEXT: and a0, s1, a0 -; RV32IZFHMIN-NEXT: flt.s a4, fa5, fs0 -; RV32IZFHMIN-NEXT: neg a2, a4 +; RV32IZFHMIN-NEXT: flt.s a3, fa5, fs0 +; RV32IZFHMIN-NEXT: neg a2, a3 ; RV32IZFHMIN-NEXT: or a0, a2, a0 ; RV32IZFHMIN-NEXT: feq.s a2, fs0, fs0 ; RV32IZFHMIN-NEXT: neg a2, a2 ; RV32IZFHMIN-NEXT: lui a5, 524288 -; RV32IZFHMIN-NEXT: lui a3, 524288 +; RV32IZFHMIN-NEXT: lui a4, 524288 ; RV32IZFHMIN-NEXT: beqz s0, .LBB5_4 ; RV32IZFHMIN-NEXT: # %bb.3: -; RV32IZFHMIN-NEXT: mv a3, a1 +; RV32IZFHMIN-NEXT: mv a4, a1 ; RV32IZFHMIN-NEXT: .LBB5_4: ; RV32IZFHMIN-NEXT: and a0, a2, a0 ; RV32IZFHMIN-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -984,11 +984,11 @@ define i64 @test_ceil_si64(half %x) nounwind { ; RV32IZFHMIN-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZFHMIN-NEXT: flw fs0, 0(sp) # 4-byte Folded Reload ; RV32IZFHMIN-NEXT: addi sp, sp, 16 -; RV32IZFHMIN-NEXT: beqz a4, .LBB5_6 +; RV32IZFHMIN-NEXT: beqz a3, .LBB5_6 ; RV32IZFHMIN-NEXT: # %bb.5: -; RV32IZFHMIN-NEXT: addi a3, a5, -1 +; RV32IZFHMIN-NEXT: addi a4, a5, -1 ; RV32IZFHMIN-NEXT: .LBB5_6: -; RV32IZFHMIN-NEXT: and a1, a2, a3 +; RV32IZFHMIN-NEXT: and a1, a2, a4 ; RV32IZFHMIN-NEXT: ret ; ; RV64IZFHMIN-LABEL: test_ceil_si64: @@ -1040,16 +1040,16 @@ define i64 @test_ceil_si64(half %x) nounwind { ; RV32IZHINXMIN-NEXT: lui a2, %hi(.LCPI5_0) ; RV32IZHINXMIN-NEXT: lw a2, %lo(.LCPI5_0)(a2) ; RV32IZHINXMIN-NEXT: and a0, s2, a0 -; RV32IZHINXMIN-NEXT: flt.s a4, a2, s0 -; RV32IZHINXMIN-NEXT: neg a2, a4 +; RV32IZHINXMIN-NEXT: flt.s a3, a2, s0 +; RV32IZHINXMIN-NEXT: neg a2, a3 ; RV32IZHINXMIN-NEXT: or a0, a2, a0 ; RV32IZHINXMIN-NEXT: feq.s a2, s0, s0 ; RV32IZHINXMIN-NEXT: neg a2, a2 ; RV32IZHINXMIN-NEXT: lui a5, 524288 -; RV32IZHINXMIN-NEXT: lui a3, 524288 +; RV32IZHINXMIN-NEXT: lui a4, 524288 ; RV32IZHINXMIN-NEXT: beqz s1, .LBB5_4 ; RV32IZHINXMIN-NEXT: # %bb.3: -; RV32IZHINXMIN-NEXT: mv a3, a1 +; RV32IZHINXMIN-NEXT: mv a4, a1 ; RV32IZHINXMIN-NEXT: .LBB5_4: ; RV32IZHINXMIN-NEXT: and a0, a2, a0 ; RV32IZHINXMIN-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -1057,11 +1057,11 @@ define i64 @test_ceil_si64(half %x) nounwind { ; RV32IZHINXMIN-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZHINXMIN-NEXT: lw s2, 0(sp) # 4-byte Folded Reload ; RV32IZHINXMIN-NEXT: addi sp, sp, 16 -; RV32IZHINXMIN-NEXT: beqz a4, .LBB5_6 +; RV32IZHINXMIN-NEXT: beqz a3, .LBB5_6 ; RV32IZHINXMIN-NEXT: # %bb.5: -; RV32IZHINXMIN-NEXT: addi a3, a5, -1 +; RV32IZHINXMIN-NEXT: addi a4, a5, -1 ; RV32IZHINXMIN-NEXT: .LBB5_6: -; RV32IZHINXMIN-NEXT: and a1, a2, a3 +; RV32IZHINXMIN-NEXT: and a1, a2, a4 ; RV32IZHINXMIN-NEXT: ret ; ; RV64IZHINXMIN-LABEL: test_ceil_si64: @@ -1552,16 +1552,16 @@ define i64 @test_trunc_si64(half %x) nounwind { ; RV32IZFH-NEXT: lui a2, %hi(.LCPI9_1) ; RV32IZFH-NEXT: flw fa5, %lo(.LCPI9_1)(a2) ; RV32IZFH-NEXT: and a0, s1, a0 -; RV32IZFH-NEXT: flt.s a4, fa5, fs0 -; RV32IZFH-NEXT: neg a2, a4 +; RV32IZFH-NEXT: flt.s a3, fa5, fs0 +; RV32IZFH-NEXT: neg a2, a3 ; RV32IZFH-NEXT: or a0, a2, a0 ; RV32IZFH-NEXT: feq.s a2, fs0, fs0 ; RV32IZFH-NEXT: neg a2, a2 ; RV32IZFH-NEXT: lui a5, 524288 -; RV32IZFH-NEXT: lui a3, 524288 +; RV32IZFH-NEXT: lui a4, 524288 ; RV32IZFH-NEXT: beqz s0, .LBB9_4 ; RV32IZFH-NEXT: # %bb.3: -; RV32IZFH-NEXT: mv a3, a1 +; RV32IZFH-NEXT: mv a4, a1 ; RV32IZFH-NEXT: .LBB9_4: ; RV32IZFH-NEXT: and a0, a2, a0 ; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -1569,11 +1569,11 @@ define i64 @test_trunc_si64(half %x) nounwind { ; RV32IZFH-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZFH-NEXT: flw fs0, 0(sp) # 4-byte Folded Reload ; RV32IZFH-NEXT: addi sp, sp, 16 -; RV32IZFH-NEXT: beqz a4, .LBB9_6 +; RV32IZFH-NEXT: beqz a3, .LBB9_6 ; RV32IZFH-NEXT: # %bb.5: -; RV32IZFH-NEXT: addi a3, a5, -1 +; RV32IZFH-NEXT: addi a4, a5, -1 ; RV32IZFH-NEXT: .LBB9_6: -; RV32IZFH-NEXT: and a1, a2, a3 +; RV32IZFH-NEXT: and a1, a2, a4 ; RV32IZFH-NEXT: ret ; ; RV64IZFH-LABEL: test_trunc_si64: @@ -1611,16 +1611,16 @@ define i64 @test_trunc_si64(half %x) nounwind { ; RV32IZHINX-NEXT: lui a2, %hi(.LCPI9_1) ; RV32IZHINX-NEXT: lw a2, %lo(.LCPI9_1)(a2) ; RV32IZHINX-NEXT: and a0, s2, a0 -; RV32IZHINX-NEXT: flt.s a4, a2, s0 -; RV32IZHINX-NEXT: neg a2, a4 +; RV32IZHINX-NEXT: flt.s a3, a2, s0 +; RV32IZHINX-NEXT: neg a2, a3 ; RV32IZHINX-NEXT: or a0, a2, a0 ; RV32IZHINX-NEXT: feq.s a2, s0, s0 ; RV32IZHINX-NEXT: neg a2, a2 ; RV32IZHINX-NEXT: lui a5, 524288 -; RV32IZHINX-NEXT: lui a3, 524288 +; RV32IZHINX-NEXT: lui a4, 524288 ; RV32IZHINX-NEXT: beqz s1, .LBB9_4 ; RV32IZHINX-NEXT: # %bb.3: -; RV32IZHINX-NEXT: mv a3, a1 +; RV32IZHINX-NEXT: mv a4, a1 ; RV32IZHINX-NEXT: .LBB9_4: ; RV32IZHINX-NEXT: and a0, a2, a0 ; RV32IZHINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -1628,11 +1628,11 @@ define i64 @test_trunc_si64(half %x) nounwind { ; RV32IZHINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZHINX-NEXT: lw s2, 0(sp) # 4-byte Folded Reload ; RV32IZHINX-NEXT: addi sp, sp, 16 -; RV32IZHINX-NEXT: beqz a4, .LBB9_6 +; RV32IZHINX-NEXT: beqz a3, .LBB9_6 ; RV32IZHINX-NEXT: # %bb.5: -; RV32IZHINX-NEXT: addi a3, a5, -1 +; RV32IZHINX-NEXT: addi a4, a5, -1 ; RV32IZHINX-NEXT: .LBB9_6: -; RV32IZHINX-NEXT: and a1, a2, a3 +; RV32IZHINX-NEXT: and a1, a2, a4 ; RV32IZHINX-NEXT: ret ; ; RV64IZHINX-LABEL: test_trunc_si64: @@ -1683,16 +1683,16 @@ define i64 @test_trunc_si64(half %x) nounwind { ; RV32IZFHMIN-NEXT: lui a2, %hi(.LCPI9_0) ; RV32IZFHMIN-NEXT: flw fa5, %lo(.LCPI9_0)(a2) ; RV32IZFHMIN-NEXT: and a0, s1, a0 -; RV32IZFHMIN-NEXT: flt.s a4, fa5, fs0 -; RV32IZFHMIN-NEXT: neg a2, a4 +; RV32IZFHMIN-NEXT: flt.s a3, fa5, fs0 +; RV32IZFHMIN-NEXT: neg a2, a3 ; RV32IZFHMIN-NEXT: or a0, a2, a0 ; RV32IZFHMIN-NEXT: feq.s a2, fs0, fs0 ; RV32IZFHMIN-NEXT: neg a2, a2 ; RV32IZFHMIN-NEXT: lui a5, 524288 -; RV32IZFHMIN-NEXT: lui a3, 524288 +; RV32IZFHMIN-NEXT: lui a4, 524288 ; RV32IZFHMIN-NEXT: beqz s0, .LBB9_4 ; RV32IZFHMIN-NEXT: # %bb.3: -; RV32IZFHMIN-NEXT: mv a3, a1 +; RV32IZFHMIN-NEXT: mv a4, a1 ; RV32IZFHMIN-NEXT: .LBB9_4: ; RV32IZFHMIN-NEXT: and a0, a2, a0 ; RV32IZFHMIN-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -1700,11 +1700,11 @@ define i64 @test_trunc_si64(half %x) nounwind { ; RV32IZFHMIN-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZFHMIN-NEXT: flw fs0, 0(sp) # 4-byte Folded Reload ; RV32IZFHMIN-NEXT: addi sp, sp, 16 -; RV32IZFHMIN-NEXT: beqz a4, .LBB9_6 +; RV32IZFHMIN-NEXT: beqz a3, .LBB9_6 ; RV32IZFHMIN-NEXT: # %bb.5: -; RV32IZFHMIN-NEXT: addi a3, a5, -1 +; RV32IZFHMIN-NEXT: addi a4, a5, -1 ; RV32IZFHMIN-NEXT: .LBB9_6: -; RV32IZFHMIN-NEXT: and a1, a2, a3 +; RV32IZFHMIN-NEXT: and a1, a2, a4 ; RV32IZFHMIN-NEXT: ret ; ; RV64IZFHMIN-LABEL: test_trunc_si64: @@ -1756,16 +1756,16 @@ define i64 @test_trunc_si64(half %x) nounwind { ; RV32IZHINXMIN-NEXT: lui a2, %hi(.LCPI9_0) ; RV32IZHINXMIN-NEXT: lw a2, %lo(.LCPI9_0)(a2) ; RV32IZHINXMIN-NEXT: and a0, s2, a0 -; RV32IZHINXMIN-NEXT: flt.s a4, a2, s0 -; RV32IZHINXMIN-NEXT: neg a2, a4 +; RV32IZHINXMIN-NEXT: flt.s a3, a2, s0 +; RV32IZHINXMIN-NEXT: neg a2, a3 ; RV32IZHINXMIN-NEXT: or a0, a2, a0 ; RV32IZHINXMIN-NEXT: feq.s a2, s0, s0 ; RV32IZHINXMIN-NEXT: neg a2, a2 ; RV32IZHINXMIN-NEXT: lui a5, 524288 -; RV32IZHINXMIN-NEXT: lui a3, 524288 +; RV32IZHINXMIN-NEXT: lui a4, 524288 ; RV32IZHINXMIN-NEXT: beqz s1, .LBB9_4 ; RV32IZHINXMIN-NEXT: # %bb.3: -; RV32IZHINXMIN-NEXT: mv a3, a1 +; RV32IZHINXMIN-NEXT: mv a4, a1 ; RV32IZHINXMIN-NEXT: .LBB9_4: ; RV32IZHINXMIN-NEXT: and a0, a2, a0 ; RV32IZHINXMIN-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -1773,11 +1773,11 @@ define i64 @test_trunc_si64(half %x) nounwind { ; RV32IZHINXMIN-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZHINXMIN-NEXT: lw s2, 0(sp) # 4-byte Folded Reload ; RV32IZHINXMIN-NEXT: addi sp, sp, 16 -; RV32IZHINXMIN-NEXT: beqz a4, .LBB9_6 +; RV32IZHINXMIN-NEXT: beqz a3, .LBB9_6 ; RV32IZHINXMIN-NEXT: # %bb.5: -; RV32IZHINXMIN-NEXT: addi a3, a5, -1 +; RV32IZHINXMIN-NEXT: addi a4, a5, -1 ; RV32IZHINXMIN-NEXT: .LBB9_6: -; RV32IZHINXMIN-NEXT: and a1, a2, a3 +; RV32IZHINXMIN-NEXT: and a1, a2, a4 ; RV32IZHINXMIN-NEXT: ret ; ; RV64IZHINXMIN-LABEL: test_trunc_si64: @@ -2268,16 +2268,16 @@ define i64 @test_round_si64(half %x) nounwind { ; RV32IZFH-NEXT: lui a2, %hi(.LCPI13_1) ; RV32IZFH-NEXT: flw fa5, %lo(.LCPI13_1)(a2) ; RV32IZFH-NEXT: and a0, s1, a0 -; RV32IZFH-NEXT: flt.s a4, fa5, fs0 -; RV32IZFH-NEXT: neg a2, a4 +; RV32IZFH-NEXT: flt.s a3, fa5, fs0 +; RV32IZFH-NEXT: neg a2, a3 ; RV32IZFH-NEXT: or a0, a2, a0 ; RV32IZFH-NEXT: feq.s a2, fs0, fs0 ; RV32IZFH-NEXT: neg a2, a2 ; RV32IZFH-NEXT: lui a5, 524288 -; RV32IZFH-NEXT: lui a3, 524288 +; RV32IZFH-NEXT: lui a4, 524288 ; RV32IZFH-NEXT: beqz s0, .LBB13_4 ; RV32IZFH-NEXT: # %bb.3: -; RV32IZFH-NEXT: mv a3, a1 +; RV32IZFH-NEXT: mv a4, a1 ; RV32IZFH-NEXT: .LBB13_4: ; RV32IZFH-NEXT: and a0, a2, a0 ; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -2285,11 +2285,11 @@ define i64 @test_round_si64(half %x) nounwind { ; RV32IZFH-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZFH-NEXT: flw fs0, 0(sp) # 4-byte Folded Reload ; RV32IZFH-NEXT: addi sp, sp, 16 -; RV32IZFH-NEXT: beqz a4, .LBB13_6 +; RV32IZFH-NEXT: beqz a3, .LBB13_6 ; RV32IZFH-NEXT: # %bb.5: -; RV32IZFH-NEXT: addi a3, a5, -1 +; RV32IZFH-NEXT: addi a4, a5, -1 ; RV32IZFH-NEXT: .LBB13_6: -; RV32IZFH-NEXT: and a1, a2, a3 +; RV32IZFH-NEXT: and a1, a2, a4 ; RV32IZFH-NEXT: ret ; ; RV64IZFH-LABEL: test_round_si64: @@ -2327,16 +2327,16 @@ define i64 @test_round_si64(half %x) nounwind { ; RV32IZHINX-NEXT: lui a2, %hi(.LCPI13_1) ; RV32IZHINX-NEXT: lw a2, %lo(.LCPI13_1)(a2) ; RV32IZHINX-NEXT: and a0, s2, a0 -; RV32IZHINX-NEXT: flt.s a4, a2, s0 -; RV32IZHINX-NEXT: neg a2, a4 +; RV32IZHINX-NEXT: flt.s a3, a2, s0 +; RV32IZHINX-NEXT: neg a2, a3 ; RV32IZHINX-NEXT: or a0, a2, a0 ; RV32IZHINX-NEXT: feq.s a2, s0, s0 ; RV32IZHINX-NEXT: neg a2, a2 ; RV32IZHINX-NEXT: lui a5, 524288 -; RV32IZHINX-NEXT: lui a3, 524288 +; RV32IZHINX-NEXT: lui a4, 524288 ; RV32IZHINX-NEXT: beqz s1, .LBB13_4 ; RV32IZHINX-NEXT: # %bb.3: -; RV32IZHINX-NEXT: mv a3, a1 +; RV32IZHINX-NEXT: mv a4, a1 ; RV32IZHINX-NEXT: .LBB13_4: ; RV32IZHINX-NEXT: and a0, a2, a0 ; RV32IZHINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -2344,11 +2344,11 @@ define i64 @test_round_si64(half %x) nounwind { ; RV32IZHINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZHINX-NEXT: lw s2, 0(sp) # 4-byte Folded Reload ; RV32IZHINX-NEXT: addi sp, sp, 16 -; RV32IZHINX-NEXT: beqz a4, .LBB13_6 +; RV32IZHINX-NEXT: beqz a3, .LBB13_6 ; RV32IZHINX-NEXT: # %bb.5: -; RV32IZHINX-NEXT: addi a3, a5, -1 +; RV32IZHINX-NEXT: addi a4, a5, -1 ; RV32IZHINX-NEXT: .LBB13_6: -; RV32IZHINX-NEXT: and a1, a2, a3 +; RV32IZHINX-NEXT: and a1, a2, a4 ; RV32IZHINX-NEXT: ret ; ; RV64IZHINX-LABEL: test_round_si64: @@ -2399,16 +2399,16 @@ define i64 @test_round_si64(half %x) nounwind { ; RV32IZFHMIN-NEXT: lui a2, %hi(.LCPI13_0) ; RV32IZFHMIN-NEXT: flw fa5, %lo(.LCPI13_0)(a2) ; RV32IZFHMIN-NEXT: and a0, s1, a0 -; RV32IZFHMIN-NEXT: flt.s a4, fa5, fs0 -; RV32IZFHMIN-NEXT: neg a2, a4 +; RV32IZFHMIN-NEXT: flt.s a3, fa5, fs0 +; RV32IZFHMIN-NEXT: neg a2, a3 ; RV32IZFHMIN-NEXT: or a0, a2, a0 ; RV32IZFHMIN-NEXT: feq.s a2, fs0, fs0 ; RV32IZFHMIN-NEXT: neg a2, a2 ; RV32IZFHMIN-NEXT: lui a5, 524288 -; RV32IZFHMIN-NEXT: lui a3, 524288 +; RV32IZFHMIN-NEXT: lui a4, 524288 ; RV32IZFHMIN-NEXT: beqz s0, .LBB13_4 ; RV32IZFHMIN-NEXT: # %bb.3: -; RV32IZFHMIN-NEXT: mv a3, a1 +; RV32IZFHMIN-NEXT: mv a4, a1 ; RV32IZFHMIN-NEXT: .LBB13_4: ; RV32IZFHMIN-NEXT: and a0, a2, a0 ; RV32IZFHMIN-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -2416,11 +2416,11 @@ define i64 @test_round_si64(half %x) nounwind { ; RV32IZFHMIN-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZFHMIN-NEXT: flw fs0, 0(sp) # 4-byte Folded Reload ; RV32IZFHMIN-NEXT: addi sp, sp, 16 -; RV32IZFHMIN-NEXT: beqz a4, .LBB13_6 +; RV32IZFHMIN-NEXT: beqz a3, .LBB13_6 ; RV32IZFHMIN-NEXT: # %bb.5: -; RV32IZFHMIN-NEXT: addi a3, a5, -1 +; RV32IZFHMIN-NEXT: addi a4, a5, -1 ; RV32IZFHMIN-NEXT: .LBB13_6: -; RV32IZFHMIN-NEXT: and a1, a2, a3 +; RV32IZFHMIN-NEXT: and a1, a2, a4 ; RV32IZFHMIN-NEXT: ret ; ; RV64IZFHMIN-LABEL: test_round_si64: @@ -2472,16 +2472,16 @@ define i64 @test_round_si64(half %x) nounwind { ; RV32IZHINXMIN-NEXT: lui a2, %hi(.LCPI13_0) ; RV32IZHINXMIN-NEXT: lw a2, %lo(.LCPI13_0)(a2) ; RV32IZHINXMIN-NEXT: and a0, s2, a0 -; RV32IZHINXMIN-NEXT: flt.s a4, a2, s0 -; RV32IZHINXMIN-NEXT: neg a2, a4 +; RV32IZHINXMIN-NEXT: flt.s a3, a2, s0 +; RV32IZHINXMIN-NEXT: neg a2, a3 ; RV32IZHINXMIN-NEXT: or a0, a2, a0 ; RV32IZHINXMIN-NEXT: feq.s a2, s0, s0 ; RV32IZHINXMIN-NEXT: neg a2, a2 ; RV32IZHINXMIN-NEXT: lui a5, 524288 -; RV32IZHINXMIN-NEXT: lui a3, 524288 +; RV32IZHINXMIN-NEXT: lui a4, 524288 ; RV32IZHINXMIN-NEXT: beqz s1, .LBB13_4 ; RV32IZHINXMIN-NEXT: # %bb.3: -; RV32IZHINXMIN-NEXT: mv a3, a1 +; RV32IZHINXMIN-NEXT: mv a4, a1 ; RV32IZHINXMIN-NEXT: .LBB13_4: ; RV32IZHINXMIN-NEXT: and a0, a2, a0 ; RV32IZHINXMIN-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -2489,11 +2489,11 @@ define i64 @test_round_si64(half %x) nounwind { ; RV32IZHINXMIN-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZHINXMIN-NEXT: lw s2, 0(sp) # 4-byte Folded Reload ; RV32IZHINXMIN-NEXT: addi sp, sp, 16 -; RV32IZHINXMIN-NEXT: beqz a4, .LBB13_6 +; RV32IZHINXMIN-NEXT: beqz a3, .LBB13_6 ; RV32IZHINXMIN-NEXT: # %bb.5: -; RV32IZHINXMIN-NEXT: addi a3, a5, -1 +; RV32IZHINXMIN-NEXT: addi a4, a5, -1 ; RV32IZHINXMIN-NEXT: .LBB13_6: -; RV32IZHINXMIN-NEXT: and a1, a2, a3 +; RV32IZHINXMIN-NEXT: and a1, a2, a4 ; RV32IZHINXMIN-NEXT: ret ; ; RV64IZHINXMIN-LABEL: test_round_si64: @@ -2984,16 +2984,16 @@ define i64 @test_roundeven_si64(half %x) nounwind { ; RV32IZFH-NEXT: lui a2, %hi(.LCPI17_1) ; RV32IZFH-NEXT: flw fa5, %lo(.LCPI17_1)(a2) ; RV32IZFH-NEXT: and a0, s1, a0 -; RV32IZFH-NEXT: flt.s a4, fa5, fs0 -; RV32IZFH-NEXT: neg a2, a4 +; RV32IZFH-NEXT: flt.s a3, fa5, fs0 +; RV32IZFH-NEXT: neg a2, a3 ; RV32IZFH-NEXT: or a0, a2, a0 ; RV32IZFH-NEXT: feq.s a2, fs0, fs0 ; RV32IZFH-NEXT: neg a2, a2 ; RV32IZFH-NEXT: lui a5, 524288 -; RV32IZFH-NEXT: lui a3, 524288 +; RV32IZFH-NEXT: lui a4, 524288 ; RV32IZFH-NEXT: beqz s0, .LBB17_4 ; RV32IZFH-NEXT: # %bb.3: -; RV32IZFH-NEXT: mv a3, a1 +; RV32IZFH-NEXT: mv a4, a1 ; RV32IZFH-NEXT: .LBB17_4: ; RV32IZFH-NEXT: and a0, a2, a0 ; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -3001,11 +3001,11 @@ define i64 @test_roundeven_si64(half %x) nounwind { ; RV32IZFH-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZFH-NEXT: flw fs0, 0(sp) # 4-byte Folded Reload ; RV32IZFH-NEXT: addi sp, sp, 16 -; RV32IZFH-NEXT: beqz a4, .LBB17_6 +; RV32IZFH-NEXT: beqz a3, .LBB17_6 ; RV32IZFH-NEXT: # %bb.5: -; RV32IZFH-NEXT: addi a3, a5, -1 +; RV32IZFH-NEXT: addi a4, a5, -1 ; RV32IZFH-NEXT: .LBB17_6: -; RV32IZFH-NEXT: and a1, a2, a3 +; RV32IZFH-NEXT: and a1, a2, a4 ; RV32IZFH-NEXT: ret ; ; RV64IZFH-LABEL: test_roundeven_si64: @@ -3043,16 +3043,16 @@ define i64 @test_roundeven_si64(half %x) nounwind { ; RV32IZHINX-NEXT: lui a2, %hi(.LCPI17_1) ; RV32IZHINX-NEXT: lw a2, %lo(.LCPI17_1)(a2) ; RV32IZHINX-NEXT: and a0, s2, a0 -; RV32IZHINX-NEXT: flt.s a4, a2, s0 -; RV32IZHINX-NEXT: neg a2, a4 +; RV32IZHINX-NEXT: flt.s a3, a2, s0 +; RV32IZHINX-NEXT: neg a2, a3 ; RV32IZHINX-NEXT: or a0, a2, a0 ; RV32IZHINX-NEXT: feq.s a2, s0, s0 ; RV32IZHINX-NEXT: neg a2, a2 ; RV32IZHINX-NEXT: lui a5, 524288 -; RV32IZHINX-NEXT: lui a3, 524288 +; RV32IZHINX-NEXT: lui a4, 524288 ; RV32IZHINX-NEXT: beqz s1, .LBB17_4 ; RV32IZHINX-NEXT: # %bb.3: -; RV32IZHINX-NEXT: mv a3, a1 +; RV32IZHINX-NEXT: mv a4, a1 ; RV32IZHINX-NEXT: .LBB17_4: ; RV32IZHINX-NEXT: and a0, a2, a0 ; RV32IZHINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -3060,11 +3060,11 @@ define i64 @test_roundeven_si64(half %x) nounwind { ; RV32IZHINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZHINX-NEXT: lw s2, 0(sp) # 4-byte Folded Reload ; RV32IZHINX-NEXT: addi sp, sp, 16 -; RV32IZHINX-NEXT: beqz a4, .LBB17_6 +; RV32IZHINX-NEXT: beqz a3, .LBB17_6 ; RV32IZHINX-NEXT: # %bb.5: -; RV32IZHINX-NEXT: addi a3, a5, -1 +; RV32IZHINX-NEXT: addi a4, a5, -1 ; RV32IZHINX-NEXT: .LBB17_6: -; RV32IZHINX-NEXT: and a1, a2, a3 +; RV32IZHINX-NEXT: and a1, a2, a4 ; RV32IZHINX-NEXT: ret ; ; RV64IZHINX-LABEL: test_roundeven_si64: @@ -3115,16 +3115,16 @@ define i64 @test_roundeven_si64(half %x) nounwind { ; RV32IZFHMIN-NEXT: lui a2, %hi(.LCPI17_0) ; RV32IZFHMIN-NEXT: flw fa5, %lo(.LCPI17_0)(a2) ; RV32IZFHMIN-NEXT: and a0, s1, a0 -; RV32IZFHMIN-NEXT: flt.s a4, fa5, fs0 -; RV32IZFHMIN-NEXT: neg a2, a4 +; RV32IZFHMIN-NEXT: flt.s a3, fa5, fs0 +; RV32IZFHMIN-NEXT: neg a2, a3 ; RV32IZFHMIN-NEXT: or a0, a2, a0 ; RV32IZFHMIN-NEXT: feq.s a2, fs0, fs0 ; RV32IZFHMIN-NEXT: neg a2, a2 ; RV32IZFHMIN-NEXT: lui a5, 524288 -; RV32IZFHMIN-NEXT: lui a3, 524288 +; RV32IZFHMIN-NEXT: lui a4, 524288 ; RV32IZFHMIN-NEXT: beqz s0, .LBB17_4 ; RV32IZFHMIN-NEXT: # %bb.3: -; RV32IZFHMIN-NEXT: mv a3, a1 +; RV32IZFHMIN-NEXT: mv a4, a1 ; RV32IZFHMIN-NEXT: .LBB17_4: ; RV32IZFHMIN-NEXT: and a0, a2, a0 ; RV32IZFHMIN-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -3132,11 +3132,11 @@ define i64 @test_roundeven_si64(half %x) nounwind { ; RV32IZFHMIN-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZFHMIN-NEXT: flw fs0, 0(sp) # 4-byte Folded Reload ; RV32IZFHMIN-NEXT: addi sp, sp, 16 -; RV32IZFHMIN-NEXT: beqz a4, .LBB17_6 +; RV32IZFHMIN-NEXT: beqz a3, .LBB17_6 ; RV32IZFHMIN-NEXT: # %bb.5: -; RV32IZFHMIN-NEXT: addi a3, a5, -1 +; RV32IZFHMIN-NEXT: addi a4, a5, -1 ; RV32IZFHMIN-NEXT: .LBB17_6: -; RV32IZFHMIN-NEXT: and a1, a2, a3 +; RV32IZFHMIN-NEXT: and a1, a2, a4 ; RV32IZFHMIN-NEXT: ret ; ; RV64IZFHMIN-LABEL: test_roundeven_si64: @@ -3188,16 +3188,16 @@ define i64 @test_roundeven_si64(half %x) nounwind { ; RV32IZHINXMIN-NEXT: lui a2, %hi(.LCPI17_0) ; RV32IZHINXMIN-NEXT: lw a2, %lo(.LCPI17_0)(a2) ; RV32IZHINXMIN-NEXT: and a0, s2, a0 -; RV32IZHINXMIN-NEXT: flt.s a4, a2, s0 -; RV32IZHINXMIN-NEXT: neg a2, a4 +; RV32IZHINXMIN-NEXT: flt.s a3, a2, s0 +; RV32IZHINXMIN-NEXT: neg a2, a3 ; RV32IZHINXMIN-NEXT: or a0, a2, a0 ; RV32IZHINXMIN-NEXT: feq.s a2, s0, s0 ; RV32IZHINXMIN-NEXT: neg a2, a2 ; RV32IZHINXMIN-NEXT: lui a5, 524288 -; RV32IZHINXMIN-NEXT: lui a3, 524288 +; RV32IZHINXMIN-NEXT: lui a4, 524288 ; RV32IZHINXMIN-NEXT: beqz s1, .LBB17_4 ; RV32IZHINXMIN-NEXT: # %bb.3: -; RV32IZHINXMIN-NEXT: mv a3, a1 +; RV32IZHINXMIN-NEXT: mv a4, a1 ; RV32IZHINXMIN-NEXT: .LBB17_4: ; RV32IZHINXMIN-NEXT: and a0, a2, a0 ; RV32IZHINXMIN-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -3205,11 +3205,11 @@ define i64 @test_roundeven_si64(half %x) nounwind { ; RV32IZHINXMIN-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZHINXMIN-NEXT: lw s2, 0(sp) # 4-byte Folded Reload ; RV32IZHINXMIN-NEXT: addi sp, sp, 16 -; RV32IZHINXMIN-NEXT: beqz a4, .LBB17_6 +; RV32IZHINXMIN-NEXT: beqz a3, .LBB17_6 ; RV32IZHINXMIN-NEXT: # %bb.5: -; RV32IZHINXMIN-NEXT: addi a3, a5, -1 +; RV32IZHINXMIN-NEXT: addi a4, a5, -1 ; RV32IZHINXMIN-NEXT: .LBB17_6: -; RV32IZHINXMIN-NEXT: and a1, a2, a3 +; RV32IZHINXMIN-NEXT: and a1, a2, a4 ; RV32IZHINXMIN-NEXT: ret ; ; RV64IZHINXMIN-LABEL: test_roundeven_si64: @@ -3700,16 +3700,16 @@ define i64 @test_rint_si64(half %x) nounwind { ; RV32IZFH-NEXT: lui a2, %hi(.LCPI21_1) ; RV32IZFH-NEXT: flw fa5, %lo(.LCPI21_1)(a2) ; RV32IZFH-NEXT: and a0, s1, a0 -; RV32IZFH-NEXT: flt.s a4, fa5, fs0 -; RV32IZFH-NEXT: neg a2, a4 +; RV32IZFH-NEXT: flt.s a3, fa5, fs0 +; RV32IZFH-NEXT: neg a2, a3 ; RV32IZFH-NEXT: or a0, a2, a0 ; RV32IZFH-NEXT: feq.s a2, fs0, fs0 ; RV32IZFH-NEXT: neg a2, a2 ; RV32IZFH-NEXT: lui a5, 524288 -; RV32IZFH-NEXT: lui a3, 524288 +; RV32IZFH-NEXT: lui a4, 524288 ; RV32IZFH-NEXT: beqz s0, .LBB21_4 ; RV32IZFH-NEXT: # %bb.3: -; RV32IZFH-NEXT: mv a3, a1 +; RV32IZFH-NEXT: mv a4, a1 ; RV32IZFH-NEXT: .LBB21_4: ; RV32IZFH-NEXT: and a0, a2, a0 ; RV32IZFH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -3717,11 +3717,11 @@ define i64 @test_rint_si64(half %x) nounwind { ; RV32IZFH-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZFH-NEXT: flw fs0, 0(sp) # 4-byte Folded Reload ; RV32IZFH-NEXT: addi sp, sp, 16 -; RV32IZFH-NEXT: beqz a4, .LBB21_6 +; RV32IZFH-NEXT: beqz a3, .LBB21_6 ; RV32IZFH-NEXT: # %bb.5: -; RV32IZFH-NEXT: addi a3, a5, -1 +; RV32IZFH-NEXT: addi a4, a5, -1 ; RV32IZFH-NEXT: .LBB21_6: -; RV32IZFH-NEXT: and a1, a2, a3 +; RV32IZFH-NEXT: and a1, a2, a4 ; RV32IZFH-NEXT: ret ; ; RV64IZFH-LABEL: test_rint_si64: @@ -3759,16 +3759,16 @@ define i64 @test_rint_si64(half %x) nounwind { ; RV32IZHINX-NEXT: lui a2, %hi(.LCPI21_1) ; RV32IZHINX-NEXT: lw a2, %lo(.LCPI21_1)(a2) ; RV32IZHINX-NEXT: and a0, s2, a0 -; RV32IZHINX-NEXT: flt.s a4, a2, s0 -; RV32IZHINX-NEXT: neg a2, a4 +; RV32IZHINX-NEXT: flt.s a3, a2, s0 +; RV32IZHINX-NEXT: neg a2, a3 ; RV32IZHINX-NEXT: or a0, a2, a0 ; RV32IZHINX-NEXT: feq.s a2, s0, s0 ; RV32IZHINX-NEXT: neg a2, a2 ; RV32IZHINX-NEXT: lui a5, 524288 -; RV32IZHINX-NEXT: lui a3, 524288 +; RV32IZHINX-NEXT: lui a4, 524288 ; RV32IZHINX-NEXT: beqz s1, .LBB21_4 ; RV32IZHINX-NEXT: # %bb.3: -; RV32IZHINX-NEXT: mv a3, a1 +; RV32IZHINX-NEXT: mv a4, a1 ; RV32IZHINX-NEXT: .LBB21_4: ; RV32IZHINX-NEXT: and a0, a2, a0 ; RV32IZHINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -3776,11 +3776,11 @@ define i64 @test_rint_si64(half %x) nounwind { ; RV32IZHINX-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZHINX-NEXT: lw s2, 0(sp) # 4-byte Folded Reload ; RV32IZHINX-NEXT: addi sp, sp, 16 -; RV32IZHINX-NEXT: beqz a4, .LBB21_6 +; RV32IZHINX-NEXT: beqz a3, .LBB21_6 ; RV32IZHINX-NEXT: # %bb.5: -; RV32IZHINX-NEXT: addi a3, a5, -1 +; RV32IZHINX-NEXT: addi a4, a5, -1 ; RV32IZHINX-NEXT: .LBB21_6: -; RV32IZHINX-NEXT: and a1, a2, a3 +; RV32IZHINX-NEXT: and a1, a2, a4 ; RV32IZHINX-NEXT: ret ; ; RV64IZHINX-LABEL: test_rint_si64: @@ -3831,16 +3831,16 @@ define i64 @test_rint_si64(half %x) nounwind { ; RV32IZFHMIN-NEXT: lui a2, %hi(.LCPI21_0) ; RV32IZFHMIN-NEXT: flw fa5, %lo(.LCPI21_0)(a2) ; RV32IZFHMIN-NEXT: and a0, s1, a0 -; RV32IZFHMIN-NEXT: flt.s a4, fa5, fs0 -; RV32IZFHMIN-NEXT: neg a2, a4 +; RV32IZFHMIN-NEXT: flt.s a3, fa5, fs0 +; RV32IZFHMIN-NEXT: neg a2, a3 ; RV32IZFHMIN-NEXT: or a0, a2, a0 ; RV32IZFHMIN-NEXT: feq.s a2, fs0, fs0 ; RV32IZFHMIN-NEXT: neg a2, a2 ; RV32IZFHMIN-NEXT: lui a5, 524288 -; RV32IZFHMIN-NEXT: lui a3, 524288 +; RV32IZFHMIN-NEXT: lui a4, 524288 ; RV32IZFHMIN-NEXT: beqz s0, .LBB21_4 ; RV32IZFHMIN-NEXT: # %bb.3: -; RV32IZFHMIN-NEXT: mv a3, a1 +; RV32IZFHMIN-NEXT: mv a4, a1 ; RV32IZFHMIN-NEXT: .LBB21_4: ; RV32IZFHMIN-NEXT: and a0, a2, a0 ; RV32IZFHMIN-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -3848,11 +3848,11 @@ define i64 @test_rint_si64(half %x) nounwind { ; RV32IZFHMIN-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZFHMIN-NEXT: flw fs0, 0(sp) # 4-byte Folded Reload ; RV32IZFHMIN-NEXT: addi sp, sp, 16 -; RV32IZFHMIN-NEXT: beqz a4, .LBB21_6 +; RV32IZFHMIN-NEXT: beqz a3, .LBB21_6 ; RV32IZFHMIN-NEXT: # %bb.5: -; RV32IZFHMIN-NEXT: addi a3, a5, -1 +; RV32IZFHMIN-NEXT: addi a4, a5, -1 ; RV32IZFHMIN-NEXT: .LBB21_6: -; RV32IZFHMIN-NEXT: and a1, a2, a3 +; RV32IZFHMIN-NEXT: and a1, a2, a4 ; RV32IZFHMIN-NEXT: ret ; ; RV64IZFHMIN-LABEL: test_rint_si64: @@ -3904,16 +3904,16 @@ define i64 @test_rint_si64(half %x) nounwind { ; RV32IZHINXMIN-NEXT: lui a2, %hi(.LCPI21_0) ; RV32IZHINXMIN-NEXT: lw a2, %lo(.LCPI21_0)(a2) ; RV32IZHINXMIN-NEXT: and a0, s2, a0 -; RV32IZHINXMIN-NEXT: flt.s a4, a2, s0 -; RV32IZHINXMIN-NEXT: neg a2, a4 +; RV32IZHINXMIN-NEXT: flt.s a3, a2, s0 +; RV32IZHINXMIN-NEXT: neg a2, a3 ; RV32IZHINXMIN-NEXT: or a0, a2, a0 ; RV32IZHINXMIN-NEXT: feq.s a2, s0, s0 ; RV32IZHINXMIN-NEXT: neg a2, a2 ; RV32IZHINXMIN-NEXT: lui a5, 524288 -; RV32IZHINXMIN-NEXT: lui a3, 524288 +; RV32IZHINXMIN-NEXT: lui a4, 524288 ; RV32IZHINXMIN-NEXT: beqz s1, .LBB21_4 ; RV32IZHINXMIN-NEXT: # %bb.3: -; RV32IZHINXMIN-NEXT: mv a3, a1 +; RV32IZHINXMIN-NEXT: mv a4, a1 ; RV32IZHINXMIN-NEXT: .LBB21_4: ; RV32IZHINXMIN-NEXT: and a0, a2, a0 ; RV32IZHINXMIN-NEXT: lw ra, 12(sp) # 4-byte Folded Reload @@ -3921,11 +3921,11 @@ define i64 @test_rint_si64(half %x) nounwind { ; RV32IZHINXMIN-NEXT: lw s1, 4(sp) # 4-byte Folded Reload ; RV32IZHINXMIN-NEXT: lw s2, 0(sp) # 4-byte Folded Reload ; RV32IZHINXMIN-NEXT: addi sp, sp, 16 -; RV32IZHINXMIN-NEXT: beqz a4, .LBB21_6 +; RV32IZHINXMIN-NEXT: beqz a3, .LBB21_6 ; RV32IZHINXMIN-NEXT: # %bb.5: -; RV32IZHINXMIN-NEXT: addi a3, a5, -1 +; RV32IZHINXMIN-NEXT: addi a4, a5, -1 ; RV32IZHINXMIN-NEXT: .LBB21_6: -; RV32IZHINXMIN-NEXT: and a1, a2, a3 +; RV32IZHINXMIN-NEXT: and a1, a2, a4 ; RV32IZHINXMIN-NEXT: ret ; ; RV64IZHINXMIN-LABEL: test_rint_si64: diff --git a/llvm/test/CodeGen/RISCV/inline-asm-d-constraint-f.ll b/llvm/test/CodeGen/RISCV/inline-asm-d-constraint-f.ll index 71769a800c06bffdd9923a515f717496871ca0ec..c480ba800c6904d24180667ab1bd0e77676802d2 100644 --- a/llvm/test/CodeGen/RISCV/inline-asm-d-constraint-f.ll +++ b/llvm/test/CodeGen/RISCV/inline-asm-d-constraint-f.ll @@ -75,24 +75,10 @@ define double @constraint_f_double_abi_name(double %a) nounwind { define double @constraint_gpr(double %x) { ; RV32F-LABEL: constraint_gpr: ; RV32F: # %bb.0: -; RV32F-NEXT: addi sp, sp, -32 -; RV32F-NEXT: .cfi_def_cfa_offset 32 -; RV32F-NEXT: sw a0, 8(sp) -; RV32F-NEXT: sw a1, 12(sp) -; RV32F-NEXT: fld fa5, 8(sp) -; RV32F-NEXT: fsd fa5, 24(sp) -; RV32F-NEXT: lw a0, 24(sp) -; RV32F-NEXT: lw a1, 28(sp) +; RV32F-NEXT: .cfi_def_cfa_offset 0 ; RV32F-NEXT: #APP ; RV32F-NEXT: mv a0, a0 ; RV32F-NEXT: #NO_APP -; RV32F-NEXT: sw a1, 20(sp) -; RV32F-NEXT: sw a0, 16(sp) -; RV32F-NEXT: fld fa5, 16(sp) -; RV32F-NEXT: fsd fa5, 8(sp) -; RV32F-NEXT: lw a0, 8(sp) -; RV32F-NEXT: lw a1, 12(sp) -; RV32F-NEXT: addi sp, sp, 32 ; RV32F-NEXT: ret ; ; RV64F-LABEL: constraint_gpr: diff --git a/llvm/test/CodeGen/RISCV/live-sp.mir b/llvm/test/CodeGen/RISCV/live-sp.mir index 8dd307f521f5bd44fd17fd0050eee18abfcab69f..fa6297a3913a9bc42a0db6e6d720c39cd7a1ea86 100644 --- a/llvm/test/CodeGen/RISCV/live-sp.mir +++ b/llvm/test/CodeGen/RISCV/live-sp.mir @@ -44,7 +44,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 4 - adjustsStack: false + adjustsStack: true hasCalls: true stackProtector: '' maxCallFrameSize: 4294967295 diff --git a/llvm/test/CodeGen/RISCV/machine-combiner.ll b/llvm/test/CodeGen/RISCV/machine-combiner.ll index cfdefec04600c80b9bd5d6db2234abc17729f51d..ebf232cc458ba0abf794b1ba4f8f7e00a8ccd9c2 100644 --- a/llvm/test/CodeGen/RISCV/machine-combiner.ll +++ b/llvm/test/CodeGen/RISCV/machine-combiner.ll @@ -740,9 +740,9 @@ define i8 @test_reassoc_minu_i8(i8 %a0, i8 %a1, i8 %a2, i8 %a3) { ; CHECK-LABEL: test_reassoc_minu_i8: ; CHECK: # %bb.0: ; CHECK-NEXT: andi a3, a3, 255 -; CHECK-NEXT: andi a2, a2, 255 ; CHECK-NEXT: andi a1, a1, 255 ; CHECK-NEXT: andi a0, a0, 255 +; CHECK-NEXT: andi a2, a2, 255 ; CHECK-NEXT: minu a0, a0, a1 ; CHECK-NEXT: minu a1, a2, a3 ; CHECK-NEXT: minu a0, a0, a1 @@ -757,9 +757,9 @@ define i16 @test_reassoc_minu_i16(i16 %a0, i16 %a1, i16 %a2, i16 %a3) { ; CHECK-LABEL: test_reassoc_minu_i16: ; CHECK: # %bb.0: ; CHECK-NEXT: zext.h a3, a3 -; CHECK-NEXT: zext.h a2, a2 ; CHECK-NEXT: zext.h a1, a1 ; CHECK-NEXT: zext.h a0, a0 +; CHECK-NEXT: zext.h a2, a2 ; CHECK-NEXT: minu a0, a0, a1 ; CHECK-NEXT: minu a1, a2, a3 ; CHECK-NEXT: minu a0, a0, a1 @@ -774,9 +774,9 @@ define i32 @test_reassoc_minu_i32(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { ; CHECK-LABEL: test_reassoc_minu_i32: ; CHECK: # %bb.0: ; CHECK-NEXT: sext.w a3, a3 -; CHECK-NEXT: sext.w a2, a2 ; CHECK-NEXT: sext.w a1, a1 ; CHECK-NEXT: sext.w a0, a0 +; CHECK-NEXT: sext.w a2, a2 ; CHECK-NEXT: minu a0, a0, a1 ; CHECK-NEXT: minu a1, a2, a3 ; CHECK-NEXT: minu a0, a0, a1 @@ -804,9 +804,9 @@ define i8 @test_reassoc_min_i8(i8 %a0, i8 %a1, i8 %a2, i8 %a3) { ; CHECK-LABEL: test_reassoc_min_i8: ; CHECK: # %bb.0: ; CHECK-NEXT: sext.b a3, a3 -; CHECK-NEXT: sext.b a2, a2 ; CHECK-NEXT: sext.b a1, a1 ; CHECK-NEXT: sext.b a0, a0 +; CHECK-NEXT: sext.b a2, a2 ; CHECK-NEXT: min a0, a0, a1 ; CHECK-NEXT: min a1, a2, a3 ; CHECK-NEXT: min a0, a0, a1 @@ -821,9 +821,9 @@ define i16 @test_reassoc_min_i16(i16 %a0, i16 %a1, i16 %a2, i16 %a3) { ; CHECK-LABEL: test_reassoc_min_i16: ; CHECK: # %bb.0: ; CHECK-NEXT: sext.h a3, a3 -; CHECK-NEXT: sext.h a2, a2 ; CHECK-NEXT: sext.h a1, a1 ; CHECK-NEXT: sext.h a0, a0 +; CHECK-NEXT: sext.h a2, a2 ; CHECK-NEXT: min a0, a0, a1 ; CHECK-NEXT: min a1, a2, a3 ; CHECK-NEXT: min a0, a0, a1 @@ -838,9 +838,9 @@ define i32 @test_reassoc_min_i32(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { ; CHECK-LABEL: test_reassoc_min_i32: ; CHECK: # %bb.0: ; CHECK-NEXT: sext.w a3, a3 -; CHECK-NEXT: sext.w a2, a2 ; CHECK-NEXT: sext.w a1, a1 ; CHECK-NEXT: sext.w a0, a0 +; CHECK-NEXT: sext.w a2, a2 ; CHECK-NEXT: min a0, a0, a1 ; CHECK-NEXT: min a1, a2, a3 ; CHECK-NEXT: min a0, a0, a1 @@ -868,9 +868,9 @@ define i8 @test_reassoc_maxu_i8(i8 %a0, i8 %a1, i8 %a2, i8 %a3) { ; CHECK-LABEL: test_reassoc_maxu_i8: ; CHECK: # %bb.0: ; CHECK-NEXT: andi a3, a3, 255 -; CHECK-NEXT: andi a2, a2, 255 ; CHECK-NEXT: andi a1, a1, 255 ; CHECK-NEXT: andi a0, a0, 255 +; CHECK-NEXT: andi a2, a2, 255 ; CHECK-NEXT: maxu a0, a0, a1 ; CHECK-NEXT: maxu a1, a2, a3 ; CHECK-NEXT: maxu a0, a0, a1 @@ -885,9 +885,9 @@ define i16 @test_reassoc_maxu_i16(i16 %a0, i16 %a1, i16 %a2, i16 %a3) { ; CHECK-LABEL: test_reassoc_maxu_i16: ; CHECK: # %bb.0: ; CHECK-NEXT: zext.h a3, a3 -; CHECK-NEXT: zext.h a2, a2 ; CHECK-NEXT: zext.h a1, a1 ; CHECK-NEXT: zext.h a0, a0 +; CHECK-NEXT: zext.h a2, a2 ; CHECK-NEXT: maxu a0, a0, a1 ; CHECK-NEXT: maxu a1, a2, a3 ; CHECK-NEXT: maxu a0, a0, a1 @@ -902,9 +902,9 @@ define i32 @test_reassoc_maxu_i32(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { ; CHECK-LABEL: test_reassoc_maxu_i32: ; CHECK: # %bb.0: ; CHECK-NEXT: sext.w a3, a3 -; CHECK-NEXT: sext.w a2, a2 ; CHECK-NEXT: sext.w a1, a1 ; CHECK-NEXT: sext.w a0, a0 +; CHECK-NEXT: sext.w a2, a2 ; CHECK-NEXT: maxu a0, a0, a1 ; CHECK-NEXT: maxu a1, a2, a3 ; CHECK-NEXT: maxu a0, a0, a1 @@ -932,9 +932,9 @@ define i8 @test_reassoc_max_i8(i8 %a0, i8 %a1, i8 %a2, i8 %a3) { ; CHECK-LABEL: test_reassoc_max_i8: ; CHECK: # %bb.0: ; CHECK-NEXT: sext.b a3, a3 -; CHECK-NEXT: sext.b a2, a2 ; CHECK-NEXT: sext.b a1, a1 ; CHECK-NEXT: sext.b a0, a0 +; CHECK-NEXT: sext.b a2, a2 ; CHECK-NEXT: max a0, a0, a1 ; CHECK-NEXT: max a1, a2, a3 ; CHECK-NEXT: max a0, a0, a1 @@ -949,9 +949,9 @@ define i16 @test_reassoc_max_i16(i16 %a0, i16 %a1, i16 %a2, i16 %a3) { ; CHECK-LABEL: test_reassoc_max_i16: ; CHECK: # %bb.0: ; CHECK-NEXT: sext.h a3, a3 -; CHECK-NEXT: sext.h a2, a2 ; CHECK-NEXT: sext.h a1, a1 ; CHECK-NEXT: sext.h a0, a0 +; CHECK-NEXT: sext.h a2, a2 ; CHECK-NEXT: max a0, a0, a1 ; CHECK-NEXT: max a1, a2, a3 ; CHECK-NEXT: max a0, a0, a1 @@ -966,9 +966,9 @@ define i32 @test_reassoc_max_i32(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { ; CHECK-LABEL: test_reassoc_max_i32: ; CHECK: # %bb.0: ; CHECK-NEXT: sext.w a3, a3 -; CHECK-NEXT: sext.w a2, a2 ; CHECK-NEXT: sext.w a1, a1 ; CHECK-NEXT: sext.w a0, a0 +; CHECK-NEXT: sext.w a2, a2 ; CHECK-NEXT: max a0, a0, a1 ; CHECK-NEXT: max a1, a2, a3 ; CHECK-NEXT: max a0, a0, a1 diff --git a/llvm/test/CodeGen/RISCV/make-compressible-zbc.mir b/llvm/test/CodeGen/RISCV/make-compressible-zbc.mir new file mode 100644 index 0000000000000000000000000000000000000000..89a6ca7af9be130b7b1e3cecda5be54ad58abb02 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/make-compressible-zbc.mir @@ -0,0 +1,585 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -o - %s -mtriple=riscv32 -mattr=+zcb -simplify-mir \ +# RUN: -run-pass=riscv-make-compressible | FileCheck --check-prefixes=CHECK %s +# RUN: llc -o - %s -mtriple=riscv64 -mattr=+zcb -simplify-mir \ +# RUN: -run-pass=riscv-make-compressible | FileCheck --check-prefixes=CHECK %s + +--- | + define void @store_common_value_i8(ptr %a, ptr %b, ptr %c) #0 { + entry: + store i8 0, ptr %a, align 1 + store i8 0, ptr %b, align 1 + store i8 0, ptr %c, align 1 + ret void + } + + define void @store_common_value_i16(ptr %a, ptr %b, ptr %c) #0 { + entry: + store i16 0, ptr %a, align 2 + store i16 0, ptr %b, align 2 + store i16 0, ptr %c, align 2 + ret void + } + + define void @store_common_ptr_i8(ptr %p) #0 { + entry: + store volatile i8 1, ptr %p, align 1 + store volatile i8 3, ptr %p, align 1 + store volatile i8 5, ptr %p, align 1 + ret void + } + + define void @store_common_ptr_i16(ptr %p) #0 { + entry: + store volatile i16 1, ptr %p, align 2 + store volatile i16 3, ptr %p, align 2 + store volatile i16 5, ptr %p, align 2 + ret void + } + + define void @load_common_ptr_i8(ptr %p) #0 { + entry: + %0 = load volatile i8, ptr %p, align 1 + %a = sext i8 %0 to i32 + %1 = load volatile i8, ptr %p, align 1 + %2 = load volatile i8, ptr %p, align 1 + ret void + } + + define void @load_common_ptr_s16(ptr %p) #0 { + entry: + %0 = load volatile i16, ptr %p, align 2 + %1 = load volatile i16, ptr %p, align 2 + %2 = load volatile i16, ptr %p, align 2 + ret void + } + + define void @load_common_ptr_u16(ptr %p) #0 { + entry: + %0 = load volatile i16, ptr %p, align 2 + %1 = load volatile i16, ptr %p, align 2 + %2 = load volatile i16, ptr %p, align 2 + ret void + } + + define void @store_large_offset_i8(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i8, ptr %p, i8 100 + store volatile i8 1, ptr %0, align 1 + %1 = getelementptr inbounds i8, ptr %p, i8 101 + store volatile i8 3, ptr %1, align 1 + %2 = getelementptr inbounds i8, ptr %p, i8 102 + store volatile i8 5, ptr %2, align 1 + %3 = getelementptr inbounds i8, ptr %p, i8 103 + store volatile i8 7, ptr %3, align 1 + ret void + } + + define void @store_large_offset_i16(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i16, ptr %p, i16 100 + store volatile i16 1, ptr %0, align 2 + %1 = getelementptr inbounds i16, ptr %p, i16 100 + store volatile i16 3, ptr %1, align 2 + %2 = getelementptr inbounds i16, ptr %p, i16 101 + store volatile i16 3, ptr %1, align 2 + %3 = getelementptr inbounds i16, ptr %p, i16 101 + store volatile i16 7, ptr %3, align 2 + ret void + } + + define void @load_large_offset_i8(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i8, ptr %p, i8 100 + %a = load volatile i8, ptr %0 + %1 = getelementptr inbounds i8, ptr %p, i8 101 + %b = load volatile i8, ptr %1 + %2 = getelementptr inbounds i8, ptr %p, i8 102 + %c = load volatile i8, ptr %2 + %3 = getelementptr inbounds i8, ptr %p, i8 103 + %d = load volatile i8, ptr %3 + ret void + } + + define void @load_large_offset_s16(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i16, ptr %p, i16 100 + %a = load volatile i16, ptr %0, align 2 + %1 = getelementptr inbounds i16, ptr %p, i16 100 + %b = load volatile i16, ptr %1, align 2 + %2 = getelementptr inbounds i16, ptr %p, i16 101 + %c = load volatile i16, ptr %2, align 2 + %3 = getelementptr inbounds i16, ptr %p, i16 101 + %d = load volatile i16, ptr %3, align 2 + ret void + } + + define void @load_large_offset_u16(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i16, ptr %p, i16 100 + %a = load volatile i16, ptr %0, align 2 + %1 = getelementptr inbounds i16, ptr %p, i16 100 + %b = load volatile i16, ptr %1, align 2 + %2 = getelementptr inbounds i16, ptr %p, i16 101 + %c = load volatile i16, ptr %2, align 2 + %3 = getelementptr inbounds i16, ptr %p, i16 101 + %d = load volatile i16, ptr %3, align 2 + ret void + } + define void @store_large_offset_no_opt_i8(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i8, ptr %p, i8 100 + store volatile i8 1, ptr %0, align 1 + %1 = getelementptr inbounds i8, ptr %p, i8 101 + store volatile i8 3, ptr %1, align 1 + %2 = getelementptr inbounds i8, ptr %p, i8 104 + store volatile i8 5, ptr %2, align 1 + ret void + } + + define void @store_large_offset_no_opt_i16(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i16, ptr %p, i16 100 + %a = load volatile i16, ptr %0, align 2 + %1 = getelementptr inbounds i16, ptr %p, i16 100 + %b = load volatile i16, ptr %1, align 2 + %2 = getelementptr inbounds i16, ptr %p, i16 101 + %c = load volatile i16, ptr %2, align 2 + %3 = getelementptr inbounds i16, ptr %p, i16 102 + %d = load volatile i16, ptr %3, align 2 + ret void + } + + define void @load_large_offset_no_opt_i8(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i8, ptr %p, i8 100 + %a = load volatile i8, ptr %0 + %1 = getelementptr inbounds i8, ptr %p, i8 101 + %b = load volatile i8, ptr %1 + %2 = getelementptr inbounds i8, ptr %p, i8 103 + %c = load volatile i8, ptr %2 + ret void + } + + define void @load_large_offset_no_opt_s16(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i16, ptr %p, i16 100 + %a = load volatile i16, ptr %0, align 2 + %1 = getelementptr inbounds i16, ptr %p, i16 101 + %c = load volatile i16, ptr %1, align 2 + %2 = getelementptr inbounds i16, ptr %p, i16 102 + %d = load volatile i16, ptr %2, align 2 + ret void + } + + define void @load_large_offset_no_opt_u16(ptr %p) #0 { + entry: + %0 = getelementptr inbounds i16, ptr %p, i16 100 + %a = load volatile i16, ptr %0, align 2 + %1 = getelementptr inbounds i16, ptr %p, i16 101 + %c = load volatile i16, ptr %1, align 2 + %2 = getelementptr inbounds i16, ptr %p, i16 102 + %d = load volatile i16, ptr %2, align 2 + ret void + } + attributes #0 = { minsize } + +... +--- +name: store_common_value_i8 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x10, $x11, $x12 + + ; CHECK-LABEL: name: store_common_value_i8 + ; CHECK: liveins: $x10, $x11, $x12 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x13 = ADDI $x0, 0 + ; CHECK-NEXT: SB $x13, killed renamable $x10, 0 :: (store (s8) into %ir.a) + ; CHECK-NEXT: SB $x13, killed renamable $x11, 0 :: (store (s8) into %ir.b) + ; CHECK-NEXT: SB $x13, killed renamable $x12, 0 :: (store (s8) into %ir.c) + ; CHECK-NEXT: PseudoRET + SB $x0, killed renamable $x10, 0 :: (store (s8) into %ir.a) + SB $x0, killed renamable $x11, 0 :: (store (s8) into %ir.b) + SB $x0, killed renamable $x12, 0 :: (store (s8) into %ir.c) + PseudoRET + +... +--- +name: store_common_value_i16 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x10, $x11, $x12 + + ; CHECK-LABEL: name: store_common_value_i16 + ; CHECK: liveins: $x10, $x11, $x12 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x13 = ADDI $x0, 0 + ; CHECK-NEXT: SH $x13, killed renamable $x10, 0 :: (store (s16) into %ir.a) + ; CHECK-NEXT: SH $x13, killed renamable $x11, 0 :: (store (s16) into %ir.b) + ; CHECK-NEXT: SH $x13, killed renamable $x12, 0 :: (store (s16) into %ir.c) + ; CHECK-NEXT: PseudoRET + SH $x0, killed renamable $x10, 0 :: (store (s16) into %ir.a) + SH $x0, killed renamable $x11, 0 :: (store (s16) into %ir.b) + SH $x0, killed renamable $x12, 0 :: (store (s16) into %ir.c) + PseudoRET + +... +--- +name: store_common_ptr_i8 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: store_common_ptr_i8 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x10 = ADDI $x0, 1 + ; CHECK-NEXT: $x11 = ADDI $x16, 0 + ; CHECK-NEXT: SB killed renamable $x10, $x11, 0 :: (volatile store (s8) into %ir.p) + ; CHECK-NEXT: renamable $x10 = ADDI $x0, 3 + ; CHECK-NEXT: SB killed renamable $x10, $x11, 0 :: (volatile store (s8) into %ir.p) + ; CHECK-NEXT: renamable $x10 = ADDI $x0, 5 + ; CHECK-NEXT: SB killed renamable $x10, killed $x11, 0 :: (volatile store (s8) into %ir.p) + ; CHECK-NEXT: PseudoRET + renamable $x10 = ADDI $x0, 1 + SB killed renamable $x10, renamable $x16, 0 :: (volatile store (s8) into %ir.p) + renamable $x10 = ADDI $x0, 3 + SB killed renamable $x10, renamable $x16, 0 :: (volatile store (s8) into %ir.p) + renamable $x10 = ADDI $x0, 5 + SB killed renamable $x10, killed renamable $x16, 0 :: (volatile store (s8) into %ir.p) + PseudoRET + +... +--- +name: store_common_ptr_i16 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: store_common_ptr_i16 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x10 = ADDI $x0, 1 + ; CHECK-NEXT: $x11 = ADDI $x16, 0 + ; CHECK-NEXT: SH killed renamable $x10, $x11, 0 :: (volatile store (s16) into %ir.p) + ; CHECK-NEXT: renamable $x10 = ADDI $x0, 3 + ; CHECK-NEXT: SH killed renamable $x10, $x11, 0 :: (volatile store (s16) into %ir.p) + ; CHECK-NEXT: renamable $x10 = ADDI $x0, 5 + ; CHECK-NEXT: SH killed renamable $x10, killed $x11, 0 :: (volatile store (s16) into %ir.p) + ; CHECK-NEXT: PseudoRET + renamable $x10 = ADDI $x0, 1 + SH killed renamable $x10, renamable $x16, 0 :: (volatile store (s16) into %ir.p) + renamable $x10 = ADDI $x0, 3 + SH killed renamable $x10, renamable $x16, 0 :: (volatile store (s16) into %ir.p) + renamable $x10 = ADDI $x0, 5 + SH killed renamable $x10, killed renamable $x16, 0 :: (volatile store (s16) into %ir.p) + PseudoRET + +... +--- +name: load_common_ptr_i8 +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: load_common_ptr_i8 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x11 = ADDI $x16, 0 + ; CHECK-NEXT: dead $x10 = LBU $x11, 0 :: (volatile load (s8) from %ir.p) + ; CHECK-NEXT: dead $x10 = LBU $x11, 0 :: (volatile load (s8) from %ir.p) + ; CHECK-NEXT: dead $x10 = LBU killed $x11, 0 :: (volatile load (s8) from %ir.p) + ; CHECK-NEXT: PseudoRET + dead $x10 = LBU renamable $x16, 0 :: (volatile load (s8) from %ir.p) + dead $x10 = LBU renamable $x16, 0 :: (volatile load (s8) from %ir.p) + dead $x10 = LBU killed renamable $x16, 0 :: (volatile load (s8) from %ir.p) + PseudoRET + +... +--- +name: load_common_ptr_s16 +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: load_common_ptr_s16 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x11 = ADDI $x16, 0 + ; CHECK-NEXT: dead $x10 = LH $x11, 0 :: (volatile load (s16) from %ir.p) + ; CHECK-NEXT: dead $x10 = LH $x11, 0 :: (volatile load (s16) from %ir.p) + ; CHECK-NEXT: dead $x10 = LH killed $x11, 0 :: (volatile load (s16) from %ir.p) + ; CHECK-NEXT: PseudoRET + dead $x10 = LH renamable $x16, 0 :: (volatile load (s16) from %ir.p) + dead $x10 = LH renamable $x16, 0 :: (volatile load (s16) from %ir.p) + dead $x10 = LH killed renamable $x16, 0 :: (volatile load (s16) from %ir.p) + PseudoRET + +... +--- +name: load_common_ptr_u16 +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: load_common_ptr_u16 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x11 = ADDI $x16, 0 + ; CHECK-NEXT: dead $x10 = LHU $x11, 0 :: (volatile load (s16) from %ir.p) + ; CHECK-NEXT: dead $x10 = LHU $x11, 0 :: (volatile load (s16) from %ir.p) + ; CHECK-NEXT: dead $x10 = LHU killed $x11, 0 :: (volatile load (s16) from %ir.p) + ; CHECK-NEXT: PseudoRET + dead $x10 = LHU renamable $x16, 0 :: (volatile load (s16) from %ir.p) + dead $x10 = LHU renamable $x16, 0 :: (volatile load (s16) from %ir.p) + dead $x10 = LHU killed renamable $x16, 0 :: (volatile load (s16) from %ir.p) + PseudoRET + +... +--- +name: store_large_offset_i8 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x10 + + ; CHECK-LABEL: name: store_large_offset_i8 + ; CHECK: liveins: $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 1 + ; CHECK-NEXT: $x12 = ADDI $x10, 100 + ; CHECK-NEXT: SB killed renamable $x11, $x12, 0 :: (volatile store (s8) into %ir.0) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 3 + ; CHECK-NEXT: SB killed renamable $x11, $x12, 1 :: (volatile store (s8) into %ir.1) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 5 + ; CHECK-NEXT: SB killed renamable $x11, $x12, 2 :: (volatile store (s8) into %ir.2) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 7 + ; CHECK-NEXT: SB killed renamable $x11, killed $x12, 3 :: (volatile store (s8) into %ir.3) + ; CHECK-NEXT: PseudoRET + renamable $x11 = ADDI $x0, 1 + SB killed renamable $x11, renamable $x10, 100 :: (volatile store (s8) into %ir.0) + renamable $x11 = ADDI $x0, 3 + SB killed renamable $x11, renamable $x10, 101 :: (volatile store (s8) into %ir.1) + renamable $x11 = ADDI $x0, 5 + SB killed renamable $x11, renamable $x10, 102 :: (volatile store (s8) into %ir.2) + renamable $x11 = ADDI $x0, 7 + SB killed renamable $x11, killed renamable $x10, 103 :: (volatile store (s8) into %ir.3) + PseudoRET + +... +--- +name: store_large_offset_i16 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x10 + ; CHECK-LABEL: name: store_large_offset_i16 + ; CHECK: liveins: $x10 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 1 + ; CHECK-NEXT: $x12 = ADDI $x10, 200 + ; CHECK-NEXT: SH killed renamable $x11, $x12, 0 :: (volatile store (s16) into %ir.0) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 3 + ; CHECK-NEXT: SH killed renamable $x11, $x12, 0 :: (volatile store (s16) into %ir.1) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 5 + ; CHECK-NEXT: SH killed renamable $x11, $x12, 2 :: (volatile store (s16) into %ir.2) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 7 + ; CHECK-NEXT: SH killed renamable $x11, killed $x12, 2 :: (volatile store (s16) into %ir.3) + ; CHECK-NEXT: PseudoRET + renamable $x11 = ADDI $x0, 1 + SH killed renamable $x11, renamable $x10, 200 :: (volatile store (s16) into %ir.0) + renamable $x11 = ADDI $x0, 3 + SH killed renamable $x11, renamable $x10, 200 :: (volatile store (s16) into %ir.1) + renamable $x11 = ADDI $x0, 5 + SH killed renamable $x11, renamable $x10, 202 :: (volatile store (s16) into %ir.2) + renamable $x11 = ADDI $x0, 7 + SH killed renamable $x11, killed renamable $x10, 202 :: (volatile store (s16) into %ir.3) + PseudoRET + +... +--- +name: load_large_offset_i8 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: load_large_offset_i8 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x11 = ADDI $x16, 100 + ; CHECK-NEXT: dead $x10 = LBU $x11, 0 :: (volatile load (s8) from %ir.0) + ; CHECK-NEXT: dead $x10 = LBU $x11, 1 :: (volatile load (s8) from %ir.1) + ; CHECK-NEXT: dead $x10 = LBU $x11, 2 :: (volatile load (s8) from %ir.2) + ; CHECK-NEXT: dead $x10 = LBU killed $x11, 3 :: (volatile load (s8) from %ir.3) + ; CHECK-NEXT: PseudoRET + dead $x10 = LBU renamable $x16, 100 :: (volatile load (s8) from %ir.0) + dead $x10 = LBU renamable $x16, 101 :: (volatile load (s8) from %ir.1) + dead $x10 = LBU renamable $x16, 102 :: (volatile load (s8) from %ir.2) + dead $x10 = LBU killed renamable $x16, 103 :: (volatile load (s8) from %ir.3) + PseudoRET + +... +--- +name: load_large_offset_s16 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: load_large_offset_s16 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x11 = ADDI $x16, 100 + ; CHECK-NEXT: dead $x10 = LH $x11, 0 :: (volatile load (s16) from %ir.0) + ; CHECK-NEXT: dead $x10 = LH $x11, 0 :: (volatile load (s16) from %ir.1) + ; CHECK-NEXT: dead $x10 = LH $x11, 2 :: (volatile load (s16) from %ir.2) + ; CHECK-NEXT: dead $x10 = LH killed $x11, 2 :: (volatile load (s16) from %ir.3) + ; CHECK-NEXT: PseudoRET + dead $x10 = LH renamable $x16, 100 :: (volatile load (s16) from %ir.0) + dead $x10 = LH renamable $x16, 100 :: (volatile load (s16) from %ir.1) + dead $x10 = LH renamable $x16, 102 :: (volatile load (s16) from %ir.2) + dead $x10 = LH killed renamable $x16, 102 :: (volatile load (s16) from %ir.3) + PseudoRET + +... +--- +name: load_large_offset_u16 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: load_large_offset_u16 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: $x11 = ADDI $x16, 100 + ; CHECK-NEXT: dead $x10 = LHU $x11, 0 :: (volatile load (s16) from %ir.0) + ; CHECK-NEXT: dead $x10 = LHU $x11, 0 :: (volatile load (s16) from %ir.1) + ; CHECK-NEXT: dead $x10 = LHU $x11, 2 :: (volatile load (s16) from %ir.2) + ; CHECK-NEXT: dead $x10 = LHU killed $x11, 2 :: (volatile load (s16) from %ir.3) + ; CHECK-NEXT: PseudoRET + dead $x10 = LHU renamable $x16, 100 :: (volatile load (s16) from %ir.0) + dead $x10 = LHU renamable $x16, 100 :: (volatile load (s16) from %ir.1) + dead $x10 = LHU renamable $x16, 102 :: (volatile load (s16) from %ir.2) + dead $x10 = LHU killed renamable $x16, 102 :: (volatile load (s16) from %ir.3) + PseudoRET + +... +--- +name: store_large_offset_no_opt_i8 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: store_large_offset_no_opt_i8 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 1 + ; CHECK-NEXT: SB killed renamable $x11, renamable $x16, 100 :: (volatile store (s8) into %ir.0) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 3 + ; CHECK-NEXT: SB killed renamable $x11, renamable $x16, 101 :: (volatile store (s8) into %ir.1) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 5 + ; CHECK-NEXT: SB killed renamable $x11, renamable $x16, 104 :: (volatile store (s8) into %ir.2) + ; CHECK-NEXT: PseudoRET + renamable $x11 = ADDI $x0, 1 + SB killed renamable $x11, renamable $x16, 100 :: (volatile store (s8) into %ir.0) + renamable $x11 = ADDI $x0, 3 + SB killed renamable $x11, renamable $x16, 101 :: (volatile store (s8) into %ir.1) + renamable $x11 = ADDI $x0, 5 + SB killed renamable $x11, renamable $x16, 104 :: (volatile store (s8) into %ir.2) + PseudoRET + +... +--- +name: store_large_offset_no_opt_i16 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: store_large_offset_no_opt_i16 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 1 + ; CHECK-NEXT: SH killed renamable $x11, renamable $x16, 200 :: (volatile store (s16) into %ir.0) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 3 + ; CHECK-NEXT: SH killed renamable $x11, renamable $x16, 202 :: (volatile store (s16) into %ir.1) + ; CHECK-NEXT: renamable $x11 = ADDI $x0, 5 + ; CHECK-NEXT: SH killed renamable $x11, renamable $x16, 204 :: (volatile store (s16) into %ir.2) + ; CHECK-NEXT: PseudoRET + renamable $x11 = ADDI $x0, 1 + SH killed renamable $x11, renamable $x16, 200 :: (volatile store (s16) into %ir.0) + renamable $x11 = ADDI $x0, 3 + SH killed renamable $x11, renamable $x16, 202 :: (volatile store (s16) into %ir.1) + renamable $x11 = ADDI $x0, 5 + SH killed renamable $x11, renamable $x16, 204 :: (volatile store (s16) into %ir.2) + PseudoRET + +... +--- +name: load_large_offset_no_opt_i8 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: load_large_offset_no_opt_i8 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: dead $x10 = LBU renamable $x16, 100 :: (volatile load (s8) from %ir.0) + ; CHECK-NEXT: dead $x10 = LBU renamable $x16, 101 :: (volatile load (s8) from %ir.1) + ; CHECK-NEXT: dead $x10 = LBU killed renamable $x16, 104 :: (volatile load (s8) from %ir.2) + ; CHECK-NEXT: PseudoRET + dead $x10 = LBU renamable $x16, 100 :: (volatile load (s8) from %ir.0) + dead $x10 = LBU renamable $x16, 101 :: (volatile load (s8) from %ir.1) + dead $x10 = LBU killed renamable $x16, 104 :: (volatile load (s8) from %ir.2) + PseudoRET + +... +--- +name: load_large_offset_no_opt_s16 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: load_large_offset_no_opt_s16 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: dead $x10 = LH renamable $x16, 100 :: (volatile load (s8) from %ir.0) + ; CHECK-NEXT: dead $x10 = LH renamable $x16, 102 :: (volatile load (s8) from %ir.1) + ; CHECK-NEXT: dead $x10 = LH killed renamable $x16, 104 :: (volatile load (s8) from %ir.2) + ; CHECK-NEXT: PseudoRET + dead $x10 = LH renamable $x16, 100 :: (volatile load (s8) from %ir.0) + dead $x10 = LH renamable $x16, 102 :: (volatile load (s8) from %ir.1) + dead $x10 = LH killed renamable $x16, 104 :: (volatile load (s8) from %ir.2) + PseudoRET + +... +--- +name: load_large_offset_no_opt_u16 +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $x16 + + ; CHECK-LABEL: name: load_large_offset_no_opt_u16 + ; CHECK: liveins: $x16 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: dead $x10 = LHU renamable $x16, 100 :: (volatile load (s8) from %ir.0) + ; CHECK-NEXT: dead $x10 = LHU renamable $x16, 102 :: (volatile load (s8) from %ir.1) + ; CHECK-NEXT: dead $x10 = LHU killed renamable $x16, 104 :: (volatile load (s8) from %ir.2) + ; CHECK-NEXT: PseudoRET + dead $x10 = LHU renamable $x16, 100 :: (volatile load (s8) from %ir.0) + dead $x10 = LHU renamable $x16, 102 :: (volatile load (s8) from %ir.1) + dead $x10 = LHU killed renamable $x16, 104 :: (volatile load (s8) from %ir.2) + PseudoRET + +... diff --git a/llvm/test/CodeGen/RISCV/misched-postra-direction.mir b/llvm/test/CodeGen/RISCV/misched-postra-direction.mir index 841d0e6d65da69285bab93ceba17d47229253cd5..2cca042bebee6248e3894239981e7c0ac6270221 100644 --- a/llvm/test/CodeGen/RISCV/misched-postra-direction.mir +++ b/llvm/test/CodeGen/RISCV/misched-postra-direction.mir @@ -1,5 +1,15 @@ -# RUN: llc -mtriple=riscv64 -mcpu=sifive-x280 -run-pass=postmisched -enable-post-misched -debug-only=machine-scheduler -misched-dump-schedule-trace -misched-postra-direction=topdown -o - %s 2>&1 | FileCheck --check-prefix=TOPDOWN %s -# RUN: llc -mtriple=riscv64 -mcpu=sifive-x280 -run-pass=postmisched -enable-post-misched -debug-only=machine-scheduler -misched-dump-schedule-trace -misched-postra-direction=bottomup -o - %s 2>&1 | FileCheck --check-prefix=BOTTOMUP %s +# RUN: llc -mtriple=riscv64 -mcpu=sifive-x280 -run-pass=postmisched \ +# RUN: -enable-post-misched -debug-only=machine-scheduler \ +# RUN: -misched-dump-schedule-trace -misched-postra-direction=topdown \ +# RUN: -o - %s 2>&1 | FileCheck --check-prefix=TOPDOWN %s +# RUN: llc -mtriple=riscv64 -mcpu=sifive-x280 -run-pass=postmisched \ +# RUN: -enable-post-misched -debug-only=machine-scheduler \ +# RUN: -misched-dump-schedule-trace -misched-postra-direction=bottomup \ +# RUN: -o - %s 2>&1 | FileCheck --check-prefix=BOTTOMUP %s +# RUN: llc -mtriple=riscv64 -mcpu=sifive-x280 -run-pass=postmisched \ +# RUN: -enable-post-misched -debug-only=machine-scheduler \ +# RUN: -misched-dump-schedule-trace -misched-postra-direction=bidirectional \ +# RUN: -o - %s 2>&1 | FileCheck --check-prefix=BIDIRECTIONAL %s # REQUIRES: asserts @@ -51,3 +61,9 @@ body: | # BOTTOMUP-NEXT: SU(1): renamable $x13 = ADD renamable $x11, renamable $x10 # BOTTOMUP-NEXT: SU(0): renamable $x12 = MUL renamable $x11, renamable $x10 # BOTTOMUP-NEXT: SU(2): renamable $x14 = DIVW renamable $x12, renamable $x13 + +# BIDIRECTIONAL: *** Final schedule for %bb.0 *** +# BIDIRECTIONAL-NEXT: * Schedule table (Bidirectional): not implemented +# BIDIRECTIONAL-NEXT: SU(1): renamable $x13 = ADD renamable $x11, renamable $x10 +# BIDIRECTIONAL-NEXT: SU(0): renamable $x12 = MUL renamable $x11, renamable $x10 +# BIDIRECTIONAL-NEXT: SU(2): renamable $x14 = DIVW renamable $x12, renamable $x13 diff --git a/llvm/test/CodeGen/RISCV/module-elf-flags.ll b/llvm/test/CodeGen/RISCV/module-elf-flags.ll new file mode 100644 index 0000000000000000000000000000000000000000..1b4bc9fd5466cc9f85d51a11f4a0dc0bad1cf4ec --- /dev/null +++ b/llvm/test/CodeGen/RISCV/module-elf-flags.ll @@ -0,0 +1,13 @@ +; RUN: llc -mtriple=riscv32 -filetype=obj < %s | llvm-readelf -h - | FileCheck -check-prefixes=FLAGS %s + +; FLAGS: Flags: 0x11, RVC, TSO + +define i32 @addi(i32 %a) { + %1 = add i32 %a, 1 + ret i32 %1 +} + +!llvm.module.flags = !{!0} + +!0 = !{i32 6, !"riscv-isa", !1} +!1 = !{!"rv64i2p1_c2p0_ztso0p1"} diff --git a/llvm/test/CodeGen/RISCV/pr64645.ll b/llvm/test/CodeGen/RISCV/pr64645.ll index 44dce5aabd2242699c31681af25796173c2dd060..f6d46516a3c00527a261f8dbfc2e311efa609334 100644 --- a/llvm/test/CodeGen/RISCV/pr64645.ll +++ b/llvm/test/CodeGen/RISCV/pr64645.ll @@ -5,34 +5,8 @@ define <2 x double> @v2f64(<2 x double> %x, <2 x double> %y) nounwind { ; CHECK-LABEL: v2f64: ; CHECK: # %bb.0: -; CHECK-NEXT: addi sp, sp, -16 -; CHECK-NEXT: sw a4, 8(sp) -; CHECK-NEXT: sw a5, 12(sp) -; CHECK-NEXT: lw a4, 8(sp) -; CHECK-NEXT: lw a5, 12(sp) -; CHECK-NEXT: sw a0, 8(sp) -; CHECK-NEXT: sw a1, 12(sp) -; CHECK-NEXT: lw a0, 8(sp) -; CHECK-NEXT: lw a1, 12(sp) -; CHECK-NEXT: sw a6, 8(sp) -; CHECK-NEXT: sw a7, 12(sp) -; CHECK-NEXT: lw a6, 8(sp) -; CHECK-NEXT: lw a7, 12(sp) -; CHECK-NEXT: sw a2, 8(sp) -; CHECK-NEXT: sw a3, 12(sp) -; CHECK-NEXT: lw a2, 8(sp) -; CHECK-NEXT: lw a3, 12(sp) ; CHECK-NEXT: fadd.d a2, a2, a6 ; CHECK-NEXT: fadd.d a0, a0, a4 -; CHECK-NEXT: sw a0, 8(sp) -; CHECK-NEXT: sw a1, 12(sp) -; CHECK-NEXT: lw a0, 8(sp) -; CHECK-NEXT: lw a1, 12(sp) -; CHECK-NEXT: sw a2, 8(sp) -; CHECK-NEXT: sw a3, 12(sp) -; CHECK-NEXT: lw a2, 8(sp) -; CHECK-NEXT: lw a3, 12(sp) -; CHECK-NEXT: addi sp, sp, 16 ; CHECK-NEXT: ret %1 = fadd <2 x double> %x, %y ret <2 x double> %1 diff --git a/llvm/test/CodeGen/RISCV/rv32xtheadbb.ll b/llvm/test/CodeGen/RISCV/rv32xtheadbb.ll index 3731b9719445ea9ac99bfebf4a84a21d5e686802..b45ab135fa1c7c611a5d415b1d12efd7c0a7ae27 100644 --- a/llvm/test/CodeGen/RISCV/rv32xtheadbb.ll +++ b/llvm/test/CodeGen/RISCV/rv32xtheadbb.ll @@ -11,8 +11,6 @@ define i32 @ctlz_i32(i32 %a) nounwind { ; RV32I: # %bb.0: ; RV32I-NEXT: beqz a0, .LBB0_2 ; RV32I-NEXT: # %bb.1: # %cond.false -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32I-NEXT: srli a1, a0, 1 ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 2 @@ -40,12 +38,11 @@ define i32 @ctlz_i32(i32 %a) nounwind { ; RV32I-NEXT: lui a1, 61681 ; RV32I-NEXT: addi a1, a1, -241 ; RV32I-NEXT: and a0, a0, a1 -; RV32I-NEXT: lui a1, 4112 -; RV32I-NEXT: addi a1, a1, 257 -; RV32I-NEXT: call __mulsi3 +; RV32I-NEXT: slli a1, a0, 8 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: slli a1, a0, 16 +; RV32I-NEXT: add a0, a0, a1 ; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32I-NEXT: addi sp, sp, 16 ; RV32I-NEXT: ret ; RV32I-NEXT: .LBB0_2: ; RV32I-NEXT: li a0, 32 @@ -64,19 +61,16 @@ declare i64 @llvm.ctlz.i64(i64, i1) define i64 @ctlz_i64(i64 %a) nounwind { ; RV32I-LABEL: ctlz_i64: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -32 -; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s4, 8(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s5, 4(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s6, 0(sp) # 4-byte Folded Spill -; RV32I-NEXT: mv s0, a1 -; RV32I-NEXT: mv s2, a0 -; RV32I-NEXT: srli a0, a1, 1 -; RV32I-NEXT: or a0, a1, a0 +; RV32I-NEXT: lui a2, 349525 +; RV32I-NEXT: addi a4, a2, 1365 +; RV32I-NEXT: lui a2, 209715 +; RV32I-NEXT: addi a3, a2, 819 +; RV32I-NEXT: lui a2, 61681 +; RV32I-NEXT: addi a2, a2, -241 +; RV32I-NEXT: bnez a1, .LBB1_2 +; RV32I-NEXT: # %bb.1: +; RV32I-NEXT: srli a1, a0, 1 +; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 2 ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 4 @@ -87,28 +81,26 @@ define i64 @ctlz_i64(i64 %a) nounwind { ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: not a0, a0 ; RV32I-NEXT: srli a1, a0, 1 -; RV32I-NEXT: lui a2, 349525 -; RV32I-NEXT: addi s4, a2, 1365 -; RV32I-NEXT: and a1, a1, s4 +; RV32I-NEXT: and a1, a1, a4 ; RV32I-NEXT: sub a0, a0, a1 -; RV32I-NEXT: lui a1, 209715 -; RV32I-NEXT: addi s5, a1, 819 -; RV32I-NEXT: and a1, a0, s5 +; RV32I-NEXT: and a1, a0, a3 ; RV32I-NEXT: srli a0, a0, 2 -; RV32I-NEXT: and a0, a0, s5 +; RV32I-NEXT: and a0, a0, a3 ; RV32I-NEXT: add a0, a1, a0 ; RV32I-NEXT: srli a1, a0, 4 ; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: lui a1, 61681 -; RV32I-NEXT: addi s6, a1, -241 -; RV32I-NEXT: and a0, a0, s6 -; RV32I-NEXT: lui a1, 4112 -; RV32I-NEXT: addi s3, a1, 257 -; RV32I-NEXT: mv a1, s3 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: mv s1, a0 -; RV32I-NEXT: srli a0, s2, 1 -; RV32I-NEXT: or a0, s2, a0 +; RV32I-NEXT: and a0, a0, a2 +; RV32I-NEXT: slli a1, a0, 8 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: slli a1, a0, 16 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: srli a0, a0, 24 +; RV32I-NEXT: addi a0, a0, 32 +; RV32I-NEXT: li a1, 0 +; RV32I-NEXT: ret +; RV32I-NEXT: .LBB1_2: +; RV32I-NEXT: srli a0, a1, 1 +; RV32I-NEXT: or a0, a1, a0 ; RV32I-NEXT: srli a1, a0, 2 ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 4 @@ -119,35 +111,21 @@ define i64 @ctlz_i64(i64 %a) nounwind { ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: not a0, a0 ; RV32I-NEXT: srli a1, a0, 1 -; RV32I-NEXT: and a1, a1, s4 +; RV32I-NEXT: and a1, a1, a4 ; RV32I-NEXT: sub a0, a0, a1 -; RV32I-NEXT: and a1, a0, s5 +; RV32I-NEXT: and a1, a0, a3 ; RV32I-NEXT: srli a0, a0, 2 -; RV32I-NEXT: and a0, a0, s5 +; RV32I-NEXT: and a0, a0, a3 ; RV32I-NEXT: add a0, a1, a0 ; RV32I-NEXT: srli a1, a0, 4 ; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: and a0, a0, s6 -; RV32I-NEXT: mv a1, s3 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: bnez s0, .LBB1_2 -; RV32I-NEXT: # %bb.1: +; RV32I-NEXT: and a0, a0, a2 +; RV32I-NEXT: slli a1, a0, 8 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: slli a1, a0, 16 +; RV32I-NEXT: add a0, a0, a1 ; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: addi a0, a0, 32 -; RV32I-NEXT: j .LBB1_3 -; RV32I-NEXT: .LBB1_2: -; RV32I-NEXT: srli a0, s1, 24 -; RV32I-NEXT: .LBB1_3: ; RV32I-NEXT: li a1, 0 -; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s4, 8(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s5, 4(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s6, 0(sp) # 4-byte Folded Reload -; RV32I-NEXT: addi sp, sp, 32 ; RV32I-NEXT: ret ; ; RV32XTHEADBB-LABEL: ctlz_i64: diff --git a/llvm/test/CodeGen/RISCV/rv32zbb.ll b/llvm/test/CodeGen/RISCV/rv32zbb.ll index 36c107061795c46066338d088fd247e976a6c858..7e6c3f9c87d277f51163299c66112d0fd7d40416 100644 --- a/llvm/test/CodeGen/RISCV/rv32zbb.ll +++ b/llvm/test/CodeGen/RISCV/rv32zbb.ll @@ -11,8 +11,6 @@ define i32 @ctlz_i32(i32 %a) nounwind { ; RV32I: # %bb.0: ; RV32I-NEXT: beqz a0, .LBB0_2 ; RV32I-NEXT: # %bb.1: # %cond.false -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32I-NEXT: srli a1, a0, 1 ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 2 @@ -40,12 +38,11 @@ define i32 @ctlz_i32(i32 %a) nounwind { ; RV32I-NEXT: lui a1, 61681 ; RV32I-NEXT: addi a1, a1, -241 ; RV32I-NEXT: and a0, a0, a1 -; RV32I-NEXT: lui a1, 4112 -; RV32I-NEXT: addi a1, a1, 257 -; RV32I-NEXT: call __mulsi3 +; RV32I-NEXT: slli a1, a0, 8 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: slli a1, a0, 16 +; RV32I-NEXT: add a0, a0, a1 ; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32I-NEXT: addi sp, sp, 16 ; RV32I-NEXT: ret ; RV32I-NEXT: .LBB0_2: ; RV32I-NEXT: li a0, 32 @@ -64,19 +61,16 @@ declare i64 @llvm.ctlz.i64(i64, i1) define i64 @ctlz_i64(i64 %a) nounwind { ; RV32I-LABEL: ctlz_i64: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -32 -; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s4, 8(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s5, 4(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s6, 0(sp) # 4-byte Folded Spill -; RV32I-NEXT: mv s0, a1 -; RV32I-NEXT: mv s2, a0 -; RV32I-NEXT: srli a0, a1, 1 -; RV32I-NEXT: or a0, a1, a0 +; RV32I-NEXT: lui a2, 349525 +; RV32I-NEXT: addi a4, a2, 1365 +; RV32I-NEXT: lui a2, 209715 +; RV32I-NEXT: addi a3, a2, 819 +; RV32I-NEXT: lui a2, 61681 +; RV32I-NEXT: addi a2, a2, -241 +; RV32I-NEXT: bnez a1, .LBB1_2 +; RV32I-NEXT: # %bb.1: +; RV32I-NEXT: srli a1, a0, 1 +; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 2 ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 4 @@ -87,28 +81,26 @@ define i64 @ctlz_i64(i64 %a) nounwind { ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: not a0, a0 ; RV32I-NEXT: srli a1, a0, 1 -; RV32I-NEXT: lui a2, 349525 -; RV32I-NEXT: addi s4, a2, 1365 -; RV32I-NEXT: and a1, a1, s4 +; RV32I-NEXT: and a1, a1, a4 ; RV32I-NEXT: sub a0, a0, a1 -; RV32I-NEXT: lui a1, 209715 -; RV32I-NEXT: addi s5, a1, 819 -; RV32I-NEXT: and a1, a0, s5 +; RV32I-NEXT: and a1, a0, a3 ; RV32I-NEXT: srli a0, a0, 2 -; RV32I-NEXT: and a0, a0, s5 +; RV32I-NEXT: and a0, a0, a3 ; RV32I-NEXT: add a0, a1, a0 ; RV32I-NEXT: srli a1, a0, 4 ; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: lui a1, 61681 -; RV32I-NEXT: addi s6, a1, -241 -; RV32I-NEXT: and a0, a0, s6 -; RV32I-NEXT: lui a1, 4112 -; RV32I-NEXT: addi s3, a1, 257 -; RV32I-NEXT: mv a1, s3 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: mv s1, a0 -; RV32I-NEXT: srli a0, s2, 1 -; RV32I-NEXT: or a0, s2, a0 +; RV32I-NEXT: and a0, a0, a2 +; RV32I-NEXT: slli a1, a0, 8 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: slli a1, a0, 16 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: srli a0, a0, 24 +; RV32I-NEXT: addi a0, a0, 32 +; RV32I-NEXT: li a1, 0 +; RV32I-NEXT: ret +; RV32I-NEXT: .LBB1_2: +; RV32I-NEXT: srli a0, a1, 1 +; RV32I-NEXT: or a0, a1, a0 ; RV32I-NEXT: srli a1, a0, 2 ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: srli a1, a0, 4 @@ -119,35 +111,21 @@ define i64 @ctlz_i64(i64 %a) nounwind { ; RV32I-NEXT: or a0, a0, a1 ; RV32I-NEXT: not a0, a0 ; RV32I-NEXT: srli a1, a0, 1 -; RV32I-NEXT: and a1, a1, s4 +; RV32I-NEXT: and a1, a1, a4 ; RV32I-NEXT: sub a0, a0, a1 -; RV32I-NEXT: and a1, a0, s5 +; RV32I-NEXT: and a1, a0, a3 ; RV32I-NEXT: srli a0, a0, 2 -; RV32I-NEXT: and a0, a0, s5 +; RV32I-NEXT: and a0, a0, a3 ; RV32I-NEXT: add a0, a1, a0 ; RV32I-NEXT: srli a1, a0, 4 ; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: and a0, a0, s6 -; RV32I-NEXT: mv a1, s3 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: bnez s0, .LBB1_2 -; RV32I-NEXT: # %bb.1: +; RV32I-NEXT: and a0, a0, a2 +; RV32I-NEXT: slli a1, a0, 8 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: slli a1, a0, 16 +; RV32I-NEXT: add a0, a0, a1 ; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: addi a0, a0, 32 -; RV32I-NEXT: j .LBB1_3 -; RV32I-NEXT: .LBB1_2: -; RV32I-NEXT: srli a0, s1, 24 -; RV32I-NEXT: .LBB1_3: ; RV32I-NEXT: li a1, 0 -; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s4, 8(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s5, 4(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s6, 0(sp) # 4-byte Folded Reload -; RV32I-NEXT: addi sp, sp, 32 ; RV32I-NEXT: ret ; ; RV32ZBB-LABEL: ctlz_i64: @@ -275,8 +253,6 @@ declare i32 @llvm.ctpop.i32(i32) define i32 @ctpop_i32(i32 %a) nounwind { ; RV32I-LABEL: ctpop_i32: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32I-NEXT: srli a1, a0, 1 ; RV32I-NEXT: lui a2, 349525 ; RV32I-NEXT: addi a2, a2, 1365 @@ -293,12 +269,11 @@ define i32 @ctpop_i32(i32 %a) nounwind { ; RV32I-NEXT: lui a1, 61681 ; RV32I-NEXT: addi a1, a1, -241 ; RV32I-NEXT: and a0, a0, a1 -; RV32I-NEXT: lui a1, 4112 -; RV32I-NEXT: addi a1, a1, 257 -; RV32I-NEXT: call __mulsi3 +; RV32I-NEXT: slli a1, a0, 8 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: slli a1, a0, 16 +; RV32I-NEXT: add a0, a0, a1 ; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload -; RV32I-NEXT: addi sp, sp, 16 ; RV32I-NEXT: ret ; ; RV32ZBB-LABEL: ctpop_i32: @@ -390,58 +365,42 @@ declare <2 x i32> @llvm.ctpop.v2i32(<2 x i32>) define <2 x i32> @ctpop_v2i32(<2 x i32> %a) nounwind { ; RV32I-LABEL: ctpop_v2i32: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -32 -; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s4, 8(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s5, 4(sp) # 4-byte Folded Spill -; RV32I-NEXT: mv s0, a1 -; RV32I-NEXT: srli a1, a0, 1 -; RV32I-NEXT: lui a2, 349525 -; RV32I-NEXT: addi s3, a2, 1365 -; RV32I-NEXT: and a1, a1, s3 -; RV32I-NEXT: sub a0, a0, a1 -; RV32I-NEXT: lui a1, 209715 -; RV32I-NEXT: addi s4, a1, 819 -; RV32I-NEXT: and a1, a0, s4 +; RV32I-NEXT: srli a2, a0, 1 +; RV32I-NEXT: lui a3, 349525 +; RV32I-NEXT: addi a3, a3, 1365 +; RV32I-NEXT: and a2, a2, a3 +; RV32I-NEXT: sub a0, a0, a2 +; RV32I-NEXT: lui a2, 209715 +; RV32I-NEXT: addi a2, a2, 819 +; RV32I-NEXT: and a4, a0, a2 ; RV32I-NEXT: srli a0, a0, 2 -; RV32I-NEXT: and a0, a0, s4 -; RV32I-NEXT: add a0, a1, a0 -; RV32I-NEXT: srli a1, a0, 4 -; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: lui a1, 61681 -; RV32I-NEXT: addi s5, a1, -241 -; RV32I-NEXT: and a0, a0, s5 -; RV32I-NEXT: lui a1, 4112 -; RV32I-NEXT: addi s1, a1, 257 -; RV32I-NEXT: mv a1, s1 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: srli s2, a0, 24 -; RV32I-NEXT: srli a0, s0, 1 -; RV32I-NEXT: and a0, a0, s3 -; RV32I-NEXT: sub s0, s0, a0 -; RV32I-NEXT: and a0, s0, s4 -; RV32I-NEXT: srli s0, s0, 2 -; RV32I-NEXT: and a1, s0, s4 -; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: srli a1, a0, 4 -; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: and a0, a0, s5 -; RV32I-NEXT: mv a1, s1 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: srli a1, a0, 24 -; RV32I-NEXT: mv a0, s2 -; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s4, 8(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s5, 4(sp) # 4-byte Folded Reload -; RV32I-NEXT: addi sp, sp, 32 +; RV32I-NEXT: and a0, a0, a2 +; RV32I-NEXT: add a0, a4, a0 +; RV32I-NEXT: srli a4, a0, 4 +; RV32I-NEXT: add a0, a0, a4 +; RV32I-NEXT: lui a4, 61681 +; RV32I-NEXT: addi a4, a4, -241 +; RV32I-NEXT: and a0, a0, a4 +; RV32I-NEXT: slli a5, a0, 8 +; RV32I-NEXT: add a0, a0, a5 +; RV32I-NEXT: slli a5, a0, 16 +; RV32I-NEXT: add a0, a0, a5 +; RV32I-NEXT: srli a0, a0, 24 +; RV32I-NEXT: srli a5, a1, 1 +; RV32I-NEXT: and a3, a5, a3 +; RV32I-NEXT: sub a1, a1, a3 +; RV32I-NEXT: and a3, a1, a2 +; RV32I-NEXT: srli a1, a1, 2 +; RV32I-NEXT: and a1, a1, a2 +; RV32I-NEXT: add a1, a3, a1 +; RV32I-NEXT: srli a2, a1, 4 +; RV32I-NEXT: add a1, a1, a2 +; RV32I-NEXT: and a1, a1, a4 +; RV32I-NEXT: slli a2, a1, 8 +; RV32I-NEXT: add a1, a1, a2 +; RV32I-NEXT: slli a2, a1, 16 +; RV32I-NEXT: add a1, a1, a2 +; RV32I-NEXT: srli a1, a1, 24 ; RV32I-NEXT: ret ; ; RV32ZBB-LABEL: ctpop_v2i32: @@ -558,59 +517,44 @@ declare i64 @llvm.ctpop.i64(i64) define i64 @ctpop_i64(i64 %a) nounwind { ; RV32I-LABEL: ctpop_i64: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -32 -; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s4, 8(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s5, 4(sp) # 4-byte Folded Spill -; RV32I-NEXT: mv s0, a0 -; RV32I-NEXT: srli a0, a1, 1 -; RV32I-NEXT: lui a2, 349525 -; RV32I-NEXT: addi s2, a2, 1365 -; RV32I-NEXT: and a0, a0, s2 -; RV32I-NEXT: sub a1, a1, a0 -; RV32I-NEXT: lui a0, 209715 -; RV32I-NEXT: addi s3, a0, 819 -; RV32I-NEXT: and a0, a1, s3 +; RV32I-NEXT: srli a2, a1, 1 +; RV32I-NEXT: lui a3, 349525 +; RV32I-NEXT: addi a3, a3, 1365 +; RV32I-NEXT: and a2, a2, a3 +; RV32I-NEXT: sub a1, a1, a2 +; RV32I-NEXT: lui a2, 209715 +; RV32I-NEXT: addi a2, a2, 819 +; RV32I-NEXT: and a4, a1, a2 ; RV32I-NEXT: srli a1, a1, 2 -; RV32I-NEXT: and a1, a1, s3 -; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: srli a1, a0, 4 -; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: lui a1, 61681 -; RV32I-NEXT: addi s4, a1, -241 -; RV32I-NEXT: and a0, a0, s4 -; RV32I-NEXT: lui a1, 4112 -; RV32I-NEXT: addi s1, a1, 257 -; RV32I-NEXT: mv a1, s1 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: srli s5, a0, 24 -; RV32I-NEXT: srli a0, s0, 1 -; RV32I-NEXT: and a0, a0, s2 -; RV32I-NEXT: sub s0, s0, a0 -; RV32I-NEXT: and a0, s0, s3 -; RV32I-NEXT: srli s0, s0, 2 -; RV32I-NEXT: and a1, s0, s3 -; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: srli a1, a0, 4 -; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: and a0, a0, s4 -; RV32I-NEXT: mv a1, s1 -; RV32I-NEXT: call __mulsi3 +; RV32I-NEXT: and a1, a1, a2 +; RV32I-NEXT: add a1, a4, a1 +; RV32I-NEXT: srli a4, a1, 4 +; RV32I-NEXT: add a1, a1, a4 +; RV32I-NEXT: lui a4, 61681 +; RV32I-NEXT: addi a4, a4, -241 +; RV32I-NEXT: and a1, a1, a4 +; RV32I-NEXT: slli a5, a1, 8 +; RV32I-NEXT: add a1, a1, a5 +; RV32I-NEXT: slli a5, a1, 16 +; RV32I-NEXT: add a1, a1, a5 +; RV32I-NEXT: srli a1, a1, 24 +; RV32I-NEXT: srli a5, a0, 1 +; RV32I-NEXT: and a3, a5, a3 +; RV32I-NEXT: sub a0, a0, a3 +; RV32I-NEXT: and a3, a0, a2 +; RV32I-NEXT: srli a0, a0, 2 +; RV32I-NEXT: and a0, a0, a2 +; RV32I-NEXT: add a0, a3, a0 +; RV32I-NEXT: srli a2, a0, 4 +; RV32I-NEXT: add a0, a0, a2 +; RV32I-NEXT: and a0, a0, a4 +; RV32I-NEXT: slli a2, a0, 8 +; RV32I-NEXT: add a0, a0, a2 +; RV32I-NEXT: slli a2, a0, 16 +; RV32I-NEXT: add a0, a0, a2 ; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: add a0, a0, s5 +; RV32I-NEXT: add a0, a0, a1 ; RV32I-NEXT: li a1, 0 -; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s4, 8(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s5, 4(sp) # 4-byte Folded Reload -; RV32I-NEXT: addi sp, sp, 32 ; RV32I-NEXT: ret ; ; RV32ZBB-LABEL: ctpop_i64: @@ -738,99 +682,82 @@ declare <2 x i64> @llvm.ctpop.v2i64(<2 x i64>) define <2 x i64> @ctpop_v2i64(<2 x i64> %a) nounwind { ; RV32I-LABEL: ctpop_v2i64: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -48 -; RV32I-NEXT: sw ra, 44(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s0, 40(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s1, 36(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s2, 32(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s3, 28(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s4, 24(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s5, 20(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s6, 16(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s7, 12(sp) # 4-byte Folded Spill -; RV32I-NEXT: sw s8, 8(sp) # 4-byte Folded Spill -; RV32I-NEXT: mv s0, a0 -; RV32I-NEXT: lw a0, 4(a1) -; RV32I-NEXT: lw s2, 8(a1) -; RV32I-NEXT: lw s5, 12(a1) -; RV32I-NEXT: lw s6, 0(a1) -; RV32I-NEXT: srli a1, a0, 1 -; RV32I-NEXT: lui a2, 349525 -; RV32I-NEXT: addi s3, a2, 1365 -; RV32I-NEXT: and a1, a1, s3 -; RV32I-NEXT: sub a0, a0, a1 -; RV32I-NEXT: lui a1, 209715 -; RV32I-NEXT: addi s4, a1, 819 -; RV32I-NEXT: and a1, a0, s4 -; RV32I-NEXT: srli a0, a0, 2 -; RV32I-NEXT: and a0, a0, s4 -; RV32I-NEXT: add a0, a1, a0 -; RV32I-NEXT: srli a1, a0, 4 -; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: lui a1, 61681 -; RV32I-NEXT: addi s7, a1, -241 -; RV32I-NEXT: and a0, a0, s7 -; RV32I-NEXT: lui a1, 4112 -; RV32I-NEXT: addi s1, a1, 257 -; RV32I-NEXT: mv a1, s1 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: srli s8, a0, 24 -; RV32I-NEXT: srli a0, s6, 1 -; RV32I-NEXT: and a0, a0, s3 -; RV32I-NEXT: sub a0, s6, a0 -; RV32I-NEXT: and a1, a0, s4 -; RV32I-NEXT: srli a0, a0, 2 -; RV32I-NEXT: and a0, a0, s4 -; RV32I-NEXT: add a0, a1, a0 -; RV32I-NEXT: srli a1, a0, 4 -; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: and a0, a0, s7 -; RV32I-NEXT: mv a1, s1 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: add s8, a0, s8 -; RV32I-NEXT: srli a0, s5, 1 -; RV32I-NEXT: and a0, a0, s3 -; RV32I-NEXT: sub a0, s5, a0 -; RV32I-NEXT: and a1, a0, s4 -; RV32I-NEXT: srli a0, a0, 2 -; RV32I-NEXT: and a0, a0, s4 -; RV32I-NEXT: add a0, a1, a0 -; RV32I-NEXT: srli a1, a0, 4 -; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: and a0, a0, s7 -; RV32I-NEXT: mv a1, s1 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: srli s5, a0, 24 -; RV32I-NEXT: srli a0, s2, 1 -; RV32I-NEXT: and a0, a0, s3 -; RV32I-NEXT: sub a0, s2, a0 -; RV32I-NEXT: and a1, a0, s4 -; RV32I-NEXT: srli a0, a0, 2 -; RV32I-NEXT: and a0, a0, s4 -; RV32I-NEXT: add a0, a1, a0 -; RV32I-NEXT: srli a1, a0, 4 -; RV32I-NEXT: add a0, a0, a1 -; RV32I-NEXT: and a0, a0, s7 -; RV32I-NEXT: mv a1, s1 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: srli a0, a0, 24 -; RV32I-NEXT: add a0, a0, s5 -; RV32I-NEXT: sw zero, 12(s0) -; RV32I-NEXT: sw zero, 4(s0) -; RV32I-NEXT: sw a0, 8(s0) -; RV32I-NEXT: sw s8, 0(s0) -; RV32I-NEXT: lw ra, 44(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s0, 40(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s1, 36(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s2, 32(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s3, 28(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s4, 24(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s5, 20(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s6, 16(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s7, 12(sp) # 4-byte Folded Reload -; RV32I-NEXT: lw s8, 8(sp) # 4-byte Folded Reload -; RV32I-NEXT: addi sp, sp, 48 +; RV32I-NEXT: lw a3, 4(a1) +; RV32I-NEXT: lw a2, 8(a1) +; RV32I-NEXT: lw a4, 12(a1) +; RV32I-NEXT: lw a1, 0(a1) +; RV32I-NEXT: srli a5, a3, 1 +; RV32I-NEXT: lui a6, 349525 +; RV32I-NEXT: addi a6, a6, 1365 +; RV32I-NEXT: and a5, a5, a6 +; RV32I-NEXT: sub a3, a3, a5 +; RV32I-NEXT: lui a5, 209715 +; RV32I-NEXT: addi a5, a5, 819 +; RV32I-NEXT: and a7, a3, a5 +; RV32I-NEXT: srli a3, a3, 2 +; RV32I-NEXT: and a3, a3, a5 +; RV32I-NEXT: add a3, a7, a3 +; RV32I-NEXT: srli a7, a3, 4 +; RV32I-NEXT: add a3, a3, a7 +; RV32I-NEXT: lui a7, 61681 +; RV32I-NEXT: addi a7, a7, -241 +; RV32I-NEXT: and a3, a3, a7 +; RV32I-NEXT: slli t0, a3, 8 +; RV32I-NEXT: add a3, a3, t0 +; RV32I-NEXT: slli t0, a3, 16 +; RV32I-NEXT: add a3, a3, t0 +; RV32I-NEXT: srli a3, a3, 24 +; RV32I-NEXT: srli t0, a1, 1 +; RV32I-NEXT: and t0, t0, a6 +; RV32I-NEXT: sub a1, a1, t0 +; RV32I-NEXT: and t0, a1, a5 +; RV32I-NEXT: srli a1, a1, 2 +; RV32I-NEXT: and a1, a1, a5 +; RV32I-NEXT: add a1, t0, a1 +; RV32I-NEXT: srli t0, a1, 4 +; RV32I-NEXT: add a1, a1, t0 +; RV32I-NEXT: and a1, a1, a7 +; RV32I-NEXT: slli t0, a1, 8 +; RV32I-NEXT: add a1, a1, t0 +; RV32I-NEXT: slli t0, a1, 16 +; RV32I-NEXT: add a1, a1, t0 +; RV32I-NEXT: srli a1, a1, 24 +; RV32I-NEXT: add a1, a1, a3 +; RV32I-NEXT: srli a3, a4, 1 +; RV32I-NEXT: and a3, a3, a6 +; RV32I-NEXT: sub a4, a4, a3 +; RV32I-NEXT: and a3, a4, a5 +; RV32I-NEXT: srli a4, a4, 2 +; RV32I-NEXT: and a4, a4, a5 +; RV32I-NEXT: add a3, a3, a4 +; RV32I-NEXT: srli a4, a3, 4 +; RV32I-NEXT: add a3, a3, a4 +; RV32I-NEXT: and a3, a3, a7 +; RV32I-NEXT: slli a4, a3, 8 +; RV32I-NEXT: add a3, a3, a4 +; RV32I-NEXT: slli a4, a3, 16 +; RV32I-NEXT: add a3, a3, a4 +; RV32I-NEXT: srli a3, a3, 24 +; RV32I-NEXT: srli a4, a2, 1 +; RV32I-NEXT: and a4, a4, a6 +; RV32I-NEXT: sub a2, a2, a4 +; RV32I-NEXT: and a4, a2, a5 +; RV32I-NEXT: srli a2, a2, 2 +; RV32I-NEXT: and a2, a2, a5 +; RV32I-NEXT: add a2, a4, a2 +; RV32I-NEXT: srli a4, a2, 4 +; RV32I-NEXT: add a2, a2, a4 +; RV32I-NEXT: and a2, a2, a7 +; RV32I-NEXT: slli a4, a2, 8 +; RV32I-NEXT: add a2, a2, a4 +; RV32I-NEXT: slli a4, a2, 16 +; RV32I-NEXT: add a2, a2, a4 +; RV32I-NEXT: srli a2, a2, 24 +; RV32I-NEXT: add a2, a2, a3 +; RV32I-NEXT: sw zero, 12(a0) +; RV32I-NEXT: sw zero, 4(a0) +; RV32I-NEXT: sw a2, 8(a0) +; RV32I-NEXT: sw a1, 0(a0) ; RV32I-NEXT: ret ; ; RV32ZBB-LABEL: ctpop_v2i64: diff --git a/llvm/test/CodeGen/RISCV/rv64-legal-i32/rv64xtheadbb.ll b/llvm/test/CodeGen/RISCV/rv64-legal-i32/rv64xtheadbb.ll index 73bfc6480b4d755fe50ab634f9049cb2690d7f3b..acd63f24bb8f763ed004be93c385d0506a381c3a 100644 --- a/llvm/test/CodeGen/RISCV/rv64-legal-i32/rv64xtheadbb.ll +++ b/llvm/test/CodeGen/RISCV/rv64-legal-i32/rv64xtheadbb.ll @@ -317,8 +317,6 @@ define i64 @ctlz_i64(i64 %a) nounwind { ; RV64I: # %bb.0: ; RV64I-NEXT: beqz a0, .LBB5_2 ; RV64I-NEXT: # %bb.1: # %cond.false -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: srli a1, a0, 1 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: srli a1, a0, 2 @@ -354,14 +352,13 @@ define i64 @ctlz_i64(i64 %a) nounwind { ; RV64I-NEXT: slli a2, a1, 32 ; RV64I-NEXT: add a1, a1, a2 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: slli a2, a1, 32 -; RV64I-NEXT: add a1, a1, a2 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 32 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srli a0, a0, 56 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret ; RV64I-NEXT: .LBB5_2: ; RV64I-NEXT: li a0, 64 diff --git a/llvm/test/CodeGen/RISCV/rv64-legal-i32/rv64zbb.ll b/llvm/test/CodeGen/RISCV/rv64-legal-i32/rv64zbb.ll index 7feef4dad4116a020282de4f884729b915ef6f0e..b0e447b71178b45a8736f5241c42b3f6d0f46a2f 100644 --- a/llvm/test/CodeGen/RISCV/rv64-legal-i32/rv64zbb.ll +++ b/llvm/test/CodeGen/RISCV/rv64-legal-i32/rv64zbb.ll @@ -307,8 +307,6 @@ define i64 @ctlz_i64(i64 %a) nounwind { ; RV64I: # %bb.0: ; RV64I-NEXT: beqz a0, .LBB5_2 ; RV64I-NEXT: # %bb.1: # %cond.false -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: srli a1, a0, 1 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: srli a1, a0, 2 @@ -344,14 +342,13 @@ define i64 @ctlz_i64(i64 %a) nounwind { ; RV64I-NEXT: slli a2, a1, 32 ; RV64I-NEXT: add a1, a1, a2 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: slli a2, a1, 32 -; RV64I-NEXT: add a1, a1, a2 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 32 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srli a0, a0, 56 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret ; RV64I-NEXT: .LBB5_2: ; RV64I-NEXT: li a0, 64 @@ -623,8 +620,6 @@ declare i64 @llvm.ctpop.i64(i64) define i64 @ctpop_i64(i64 %a) nounwind { ; RV64I-LABEL: ctpop_i64: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: srli a1, a0, 1 ; RV64I-NEXT: lui a2, 349525 ; RV64I-NEXT: addiw a2, a2, 1365 @@ -647,14 +642,13 @@ define i64 @ctpop_i64(i64 %a) nounwind { ; RV64I-NEXT: slli a2, a1, 32 ; RV64I-NEXT: add a1, a1, a2 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: slli a2, a1, 32 -; RV64I-NEXT: add a1, a1, a2 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 32 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srli a0, a0, 56 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret ; ; RV64ZBB-LABEL: ctpop_i64: diff --git a/llvm/test/CodeGen/RISCV/rv64-typepromotion.ll b/llvm/test/CodeGen/RISCV/rv64-typepromotion.ll new file mode 100644 index 0000000000000000000000000000000000000000..23eae33739c970b50b29af55a1e152db69e6319e --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rv64-typepromotion.ll @@ -0,0 +1,27 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -mtriple=riscv64 -passes=typepromotion -S %s | FileCheck %s + +; Test that this does not crash +define i16 @test(i8 %a, i32 %b) { +; CHECK-LABEL: define i16 @test( +; CHECK-SAME: i8 [[A:%.*]], i32 [[B:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = zext i8 [[A]] to i32 +; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[B]] to i16 +; CHECK-NEXT: [[TMP2:%.*]] = zext i16 [[TMP1]] to i64 +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[TMP2]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP0]], 255 +; CHECK-NEXT: [[TMP5:%.*]] = zext i32 [[TMP4]] to i64 +; CHECK-NEXT: [[TMP6:%.*]] = xor i64 [[TMP5]], [[TMP2]] +; CHECK-NEXT: [[TMP7:%.*]] = trunc i64 [[TMP6]] to i16 +; CHECK-NEXT: ret i16 [[TMP7]] +; +entry: + %0 = zext i8 %a to i32 + %1 = trunc i32 %b to i16 + %2 = icmp eq i16 %1, 0 + %3 = trunc i32 %0 to i8 + %4 = zext i8 %3 to i16 + %5 = xor i16 %4, %1 + ret i16 %5 +} diff --git a/llvm/test/CodeGen/RISCV/rv64xtheadbb.ll b/llvm/test/CodeGen/RISCV/rv64xtheadbb.ll index 1f62ea9f5681911c613a5657f0eabbf32ca8cc06..6cdab888ffcde7f88ba4ead025b56b0e898978a1 100644 --- a/llvm/test/CodeGen/RISCV/rv64xtheadbb.ll +++ b/llvm/test/CodeGen/RISCV/rv64xtheadbb.ll @@ -11,8 +11,6 @@ define signext i32 @ctlz_i32(i32 signext %a) nounwind { ; RV64I: # %bb.0: ; RV64I-NEXT: beqz a0, .LBB0_2 ; RV64I-NEXT: # %bb.1: # %cond.false -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: srliw a1, a0, 1 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: srliw a1, a0, 2 @@ -38,14 +36,13 @@ define signext i32 @ctlz_i32(i32 signext %a) nounwind { ; RV64I-NEXT: srli a1, a0, 4 ; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: lui a1, 61681 -; RV64I-NEXT: addiw a1, a1, -241 +; RV64I-NEXT: addi a1, a1, -241 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srliw a0, a0, 24 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret ; RV64I-NEXT: .LBB0_2: ; RV64I-NEXT: li a0, 32 @@ -66,8 +63,6 @@ define signext i32 @log2_i32(i32 signext %a) nounwind { ; RV64I: # %bb.0: ; RV64I-NEXT: beqz a0, .LBB1_2 ; RV64I-NEXT: # %bb.1: # %cond.false -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: srliw a1, a0, 1 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: srliw a1, a0, 2 @@ -93,14 +88,13 @@ define signext i32 @log2_i32(i32 signext %a) nounwind { ; RV64I-NEXT: srli a1, a0, 4 ; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: lui a1, 61681 -; RV64I-NEXT: addiw a1, a1, -241 +; RV64I-NEXT: addi a1, a1, -241 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srliw a0, a0, 24 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: j .LBB1_3 ; RV64I-NEXT: .LBB1_2: ; RV64I-NEXT: li a0, 32 @@ -125,50 +119,45 @@ define signext i32 @log2_i32(i32 signext %a) nounwind { define signext i32 @log2_ceil_i32(i32 signext %a) nounwind { ; RV64I-LABEL: log2_ceil_i32: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s0, 0(sp) # 8-byte Folded Spill -; RV64I-NEXT: addiw a0, a0, -1 -; RV64I-NEXT: li s0, 32 -; RV64I-NEXT: li a1, 32 -; RV64I-NEXT: beqz a0, .LBB2_2 +; RV64I-NEXT: addiw a1, a0, -1 +; RV64I-NEXT: li a0, 32 +; RV64I-NEXT: li a2, 32 +; RV64I-NEXT: beqz a1, .LBB2_2 ; RV64I-NEXT: # %bb.1: # %cond.false -; RV64I-NEXT: srliw a1, a0, 1 -; RV64I-NEXT: or a0, a0, a1 -; RV64I-NEXT: srliw a1, a0, 2 -; RV64I-NEXT: or a0, a0, a1 -; RV64I-NEXT: srliw a1, a0, 4 -; RV64I-NEXT: or a0, a0, a1 -; RV64I-NEXT: srliw a1, a0, 8 -; RV64I-NEXT: or a0, a0, a1 -; RV64I-NEXT: srliw a1, a0, 16 -; RV64I-NEXT: or a0, a0, a1 -; RV64I-NEXT: not a0, a0 -; RV64I-NEXT: srli a1, a0, 1 -; RV64I-NEXT: lui a2, 349525 -; RV64I-NEXT: addiw a2, a2, 1365 +; RV64I-NEXT: srliw a2, a1, 1 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: srliw a2, a1, 2 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: srliw a2, a1, 4 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: srliw a2, a1, 8 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: srliw a2, a1, 16 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: not a1, a1 +; RV64I-NEXT: srli a2, a1, 1 +; RV64I-NEXT: lui a3, 349525 +; RV64I-NEXT: addiw a3, a3, 1365 +; RV64I-NEXT: and a2, a2, a3 +; RV64I-NEXT: sub a1, a1, a2 +; RV64I-NEXT: lui a2, 209715 +; RV64I-NEXT: addiw a2, a2, 819 +; RV64I-NEXT: and a3, a1, a2 +; RV64I-NEXT: srli a1, a1, 2 ; RV64I-NEXT: and a1, a1, a2 -; RV64I-NEXT: sub a0, a0, a1 -; RV64I-NEXT: lui a1, 209715 -; RV64I-NEXT: addiw a1, a1, 819 -; RV64I-NEXT: and a2, a0, a1 -; RV64I-NEXT: srli a0, a0, 2 -; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: add a0, a2, a0 -; RV64I-NEXT: srli a1, a0, 4 -; RV64I-NEXT: add a0, a0, a1 -; RV64I-NEXT: lui a1, 61681 -; RV64I-NEXT: addiw a1, a1, -241 -; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: srliw a1, a0, 24 +; RV64I-NEXT: add a1, a3, a1 +; RV64I-NEXT: srli a2, a1, 4 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: lui a2, 61681 +; RV64I-NEXT: addi a2, a2, -241 +; RV64I-NEXT: and a1, a1, a2 +; RV64I-NEXT: slli a2, a1, 8 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: slli a2, a1, 16 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: srliw a2, a1, 24 ; RV64I-NEXT: .LBB2_2: # %cond.end -; RV64I-NEXT: sub a0, s0, a1 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s0, 0(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: sub a0, a0, a2 ; RV64I-NEXT: ret ; ; RV64XTHEADBB-LABEL: log2_ceil_i32: @@ -189,48 +178,42 @@ define signext i32 @log2_ceil_i32(i32 signext %a) nounwind { define signext i32 @findLastSet_i32(i32 signext %a) nounwind { ; RV64I-LABEL: findLastSet_i32: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s0, 0(sp) # 8-byte Folded Spill -; RV64I-NEXT: mv s0, a0 -; RV64I-NEXT: srliw a0, a0, 1 -; RV64I-NEXT: or a0, s0, a0 -; RV64I-NEXT: srliw a1, a0, 2 -; RV64I-NEXT: or a0, a0, a1 -; RV64I-NEXT: srliw a1, a0, 4 -; RV64I-NEXT: or a0, a0, a1 -; RV64I-NEXT: srliw a1, a0, 8 -; RV64I-NEXT: or a0, a0, a1 -; RV64I-NEXT: srliw a1, a0, 16 -; RV64I-NEXT: or a0, a0, a1 -; RV64I-NEXT: not a0, a0 -; RV64I-NEXT: srli a1, a0, 1 -; RV64I-NEXT: lui a2, 349525 -; RV64I-NEXT: addiw a2, a2, 1365 +; RV64I-NEXT: srliw a1, a0, 1 +; RV64I-NEXT: or a1, a0, a1 +; RV64I-NEXT: srliw a2, a1, 2 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: srliw a2, a1, 4 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: srliw a2, a1, 8 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: srliw a2, a1, 16 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: not a1, a1 +; RV64I-NEXT: srli a2, a1, 1 +; RV64I-NEXT: lui a3, 349525 +; RV64I-NEXT: addiw a3, a3, 1365 +; RV64I-NEXT: and a2, a2, a3 +; RV64I-NEXT: sub a1, a1, a2 +; RV64I-NEXT: lui a2, 209715 +; RV64I-NEXT: addiw a2, a2, 819 +; RV64I-NEXT: and a3, a1, a2 +; RV64I-NEXT: srli a1, a1, 2 ; RV64I-NEXT: and a1, a1, a2 -; RV64I-NEXT: sub a0, a0, a1 -; RV64I-NEXT: lui a1, 209715 -; RV64I-NEXT: addiw a1, a1, 819 -; RV64I-NEXT: and a2, a0, a1 -; RV64I-NEXT: srli a0, a0, 2 -; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: add a0, a2, a0 -; RV64I-NEXT: srli a1, a0, 4 -; RV64I-NEXT: add a0, a0, a1 -; RV64I-NEXT: lui a1, 61681 -; RV64I-NEXT: addiw a1, a1, -241 -; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: srliw a0, a0, 24 -; RV64I-NEXT: xori a0, a0, 31 -; RV64I-NEXT: snez a1, s0 -; RV64I-NEXT: addi a1, a1, -1 -; RV64I-NEXT: or a0, a1, a0 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s0, 0(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: add a1, a3, a1 +; RV64I-NEXT: srli a2, a1, 4 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: lui a2, 61681 +; RV64I-NEXT: addi a2, a2, -241 +; RV64I-NEXT: and a1, a1, a2 +; RV64I-NEXT: slli a2, a1, 8 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: slli a2, a1, 16 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: srliw a1, a1, 24 +; RV64I-NEXT: xori a1, a1, 31 +; RV64I-NEXT: snez a0, a0 +; RV64I-NEXT: addi a0, a0, -1 +; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: ret ; ; RV64XTHEADBB-LABEL: findLastSet_i32: @@ -256,10 +239,6 @@ define i32 @ctlz_lshr_i32(i32 signext %a) { ; RV64I-NEXT: srliw a0, a0, 1 ; RV64I-NEXT: beqz a0, .LBB4_2 ; RV64I-NEXT: # %bb.1: # %cond.false -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: .cfi_def_cfa_offset 16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill -; RV64I-NEXT: .cfi_offset ra, -8 ; RV64I-NEXT: srliw a1, a0, 1 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: srliw a1, a0, 2 @@ -285,14 +264,13 @@ define i32 @ctlz_lshr_i32(i32 signext %a) { ; RV64I-NEXT: srli a1, a0, 4 ; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: lui a1, 61681 -; RV64I-NEXT: addiw a1, a1, -241 +; RV64I-NEXT: addi a1, a1, -241 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srliw a0, a0, 24 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret ; RV64I-NEXT: .LBB4_2: ; RV64I-NEXT: li a0, 32 @@ -317,8 +295,6 @@ define i64 @ctlz_i64(i64 %a) nounwind { ; RV64I: # %bb.0: ; RV64I-NEXT: beqz a0, .LBB5_2 ; RV64I-NEXT: # %bb.1: # %cond.false -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: srli a1, a0, 1 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: srli a1, a0, 2 @@ -354,14 +330,13 @@ define i64 @ctlz_i64(i64 %a) nounwind { ; RV64I-NEXT: slli a2, a1, 32 ; RV64I-NEXT: add a1, a1, a2 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: slli a2, a1, 32 -; RV64I-NEXT: add a1, a1, a2 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 32 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srli a0, a0, 56 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret ; RV64I-NEXT: .LBB5_2: ; RV64I-NEXT: li a0, 64 diff --git a/llvm/test/CodeGen/RISCV/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64zba.ll index f810f51f6bc07a347147285242f9ffd56002321a..c81c6aeaab890c1f74a697ae18d8dfe7249855a0 100644 --- a/llvm/test/CodeGen/RISCV/rv64zba.ll +++ b/llvm/test/CodeGen/RISCV/rv64zba.ll @@ -209,6 +209,24 @@ define i64 @sh1adduw_2(i64 %0, i64 %1) { ret i64 %5 } +define i64 @sh1adduw_3(i64 %0, i64 %1) { +; RV64I-LABEL: sh1adduw_3: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: srli a0, a0, 31 +; RV64I-NEXT: or a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: sh1adduw_3: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: sh1add.uw a0, a0, a1 +; RV64ZBA-NEXT: ret + %3 = shl i64 %0, 1 + %4 = and i64 %3, 8589934590 + %5 = or disjoint i64 %4, %1 + ret i64 %5 +} + define signext i32 @sh2adduw(i32 signext %0, ptr %1) { ; RV64I-LABEL: sh2adduw: ; RV64I: # %bb.0: @@ -247,6 +265,24 @@ define i64 @sh2adduw_2(i64 %0, i64 %1) { ret i64 %5 } +define i64 @sh2adduw_3(i64 %0, i64 %1) { +; RV64I-LABEL: sh2adduw_3: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: srli a0, a0, 30 +; RV64I-NEXT: or a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: sh2adduw_3: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: sh2add.uw a0, a0, a1 +; RV64ZBA-NEXT: ret + %3 = shl i64 %0, 2 + %4 = and i64 %3, 17179869180 + %5 = or disjoint i64 %4, %1 + ret i64 %5 +} + define i64 @sh3adduw(i32 signext %0, ptr %1) { ; RV64I-LABEL: sh3adduw: ; RV64I: # %bb.0: @@ -285,6 +321,24 @@ define i64 @sh3adduw_2(i64 %0, i64 %1) { ret i64 %5 } +define i64 @sh3adduw_3(i64 %0, i64 %1) { +; RV64I-LABEL: sh3adduw_3: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: srli a0, a0, 29 +; RV64I-NEXT: or a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: sh3adduw_3: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: sh3add.uw a0, a0, a1 +; RV64ZBA-NEXT: ret + %3 = shl i64 %0, 3 + %4 = and i64 %3, 34359738360 + %5 = or disjoint i64 %4, %1 + ret i64 %5 +} + ; Type legalization inserts a sext_inreg after the first add. That add will be ; selected as sh2add which does not sign extend. SimplifyDemandedBits is unable ; to remove the sext_inreg because it has multiple uses. The ashr will use the @@ -335,6 +389,24 @@ define i64 @addmul6(i64 %a, i64 %b) { ret i64 %d } +define i64 @disjointormul6(i64 %a, i64 %b) { +; RV64I-LABEL: disjointormul6: +; RV64I: # %bb.0: +; RV64I-NEXT: li a2, 6 +; RV64I-NEXT: mul a0, a0, a2 +; RV64I-NEXT: or a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: disjointormul6: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: sh1add a0, a0, a0 +; RV64ZBA-NEXT: sh1add a0, a0, a1 +; RV64ZBA-NEXT: ret + %c = mul i64 %a, 6 + %d = or disjoint i64 %c, %b + ret i64 %d +} + define i64 @addmul10(i64 %a, i64 %b) { ; RV64I-LABEL: addmul10: ; RV64I: # %bb.0: @@ -1099,6 +1171,23 @@ define i64 @add4104(i64 %a) { ret i64 %c } +define i64 @add4104_2(i64 %a) { +; RV64I-LABEL: add4104_2: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a1, 1 +; RV64I-NEXT: addiw a1, a1, 8 +; RV64I-NEXT: or a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: add4104_2: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: li a1, 1026 +; RV64ZBA-NEXT: sh2add a0, a1, a0 +; RV64ZBA-NEXT: ret + %c = or disjoint i64 %a, 4104 + ret i64 %c +} + define i64 @add8208(i64 %a) { ; RV64I-LABEL: add8208: ; RV64I: # %bb.0: @@ -1282,6 +1371,96 @@ define zeroext i32 @sext_ashr_zext_i8(i8 %a) nounwind { ret i32 %1 } +define i64 @sh6_sh3_add1(i64 noundef %x, i64 noundef %y, i64 noundef %z) { +; RV64I-LABEL: sh6_sh3_add1: +; RV64I: # %bb.0: # %entry +; RV64I-NEXT: slli a2, a2, 3 +; RV64I-NEXT: slli a1, a1, 6 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: add a0, a1, a0 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: sh6_sh3_add1: +; RV64ZBA: # %bb.0: # %entry +; RV64ZBA-NEXT: sh3add a1, a1, a2 +; RV64ZBA-NEXT: sh3add a0, a1, a0 +; RV64ZBA-NEXT: ret +entry: + %shl = shl i64 %z, 3 + %shl1 = shl i64 %y, 6 + %add = add nsw i64 %shl1, %shl + %add2 = add nsw i64 %add, %x + ret i64 %add2 +} + +define i64 @sh6_sh3_add2(i64 noundef %x, i64 noundef %y, i64 noundef %z) { +; RV64I-LABEL: sh6_sh3_add2: +; RV64I: # %bb.0: # %entry +; RV64I-NEXT: slli a2, a2, 3 +; RV64I-NEXT: slli a1, a1, 6 +; RV64I-NEXT: add a0, a1, a0 +; RV64I-NEXT: add a0, a0, a2 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: sh6_sh3_add2: +; RV64ZBA: # %bb.0: # %entry +; RV64ZBA-NEXT: slli a1, a1, 6 +; RV64ZBA-NEXT: add a0, a1, a0 +; RV64ZBA-NEXT: sh3add a0, a2, a0 +; RV64ZBA-NEXT: ret +entry: + %shl = shl i64 %z, 3 + %shl1 = shl i64 %y, 6 + %add = add nsw i64 %shl1, %x + %add2 = add nsw i64 %add, %shl + ret i64 %add2 +} + +define i64 @sh6_sh3_add3(i64 noundef %x, i64 noundef %y, i64 noundef %z) { +; RV64I-LABEL: sh6_sh3_add3: +; RV64I: # %bb.0: # %entry +; RV64I-NEXT: slli a2, a2, 3 +; RV64I-NEXT: slli a1, a1, 6 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: sh6_sh3_add3: +; RV64ZBA: # %bb.0: # %entry +; RV64ZBA-NEXT: sh3add a1, a1, a2 +; RV64ZBA-NEXT: sh3add a0, a1, a0 +; RV64ZBA-NEXT: ret +entry: + %shl = shl i64 %z, 3 + %shl1 = shl i64 %y, 6 + %add = add nsw i64 %shl1, %shl + %add2 = add nsw i64 %x, %add + ret i64 %add2 +} + +define i64 @sh6_sh3_add4(i64 noundef %x, i64 noundef %y, i64 noundef %z) { +; RV64I-LABEL: sh6_sh3_add4: +; RV64I: # %bb.0: # %entry +; RV64I-NEXT: slli a2, a2, 3 +; RV64I-NEXT: slli a1, a1, 6 +; RV64I-NEXT: add a0, a0, a2 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: sh6_sh3_add4: +; RV64ZBA: # %bb.0: # %entry +; RV64ZBA-NEXT: slli a1, a1, 6 +; RV64ZBA-NEXT: sh3add a0, a2, a0 +; RV64ZBA-NEXT: add a0, a0, a1 +; RV64ZBA-NEXT: ret +entry: + %shl = shl i64 %z, 3 + %shl1 = shl i64 %y, 6 + %add = add nsw i64 %x, %shl + %add2 = add nsw i64 %add, %shl1 + ret i64 %add2 +} + ; Make sure we use sext.h+slli+srli for Zba+Zbb. ; FIXME: The RV64I and Zba only cases can be done with only 3 shifts. define zeroext i32 @sext_ashr_zext_i16(i16 %a) nounwind { diff --git a/llvm/test/CodeGen/RISCV/rv64zbb.ll b/llvm/test/CodeGen/RISCV/rv64zbb.ll index 2269d8d04c9cb006a1fc554a7f6b4a788ce4d1a3..4d5ef5db86057bce1591b7811e6ce4a66fe53756 100644 --- a/llvm/test/CodeGen/RISCV/rv64zbb.ll +++ b/llvm/test/CodeGen/RISCV/rv64zbb.ll @@ -11,8 +11,6 @@ define signext i32 @ctlz_i32(i32 signext %a) nounwind { ; RV64I: # %bb.0: ; RV64I-NEXT: beqz a0, .LBB0_2 ; RV64I-NEXT: # %bb.1: # %cond.false -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: srliw a1, a0, 1 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: srliw a1, a0, 2 @@ -38,14 +36,13 @@ define signext i32 @ctlz_i32(i32 signext %a) nounwind { ; RV64I-NEXT: srli a1, a0, 4 ; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: lui a1, 61681 -; RV64I-NEXT: addiw a1, a1, -241 +; RV64I-NEXT: addi a1, a1, -241 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srliw a0, a0, 24 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret ; RV64I-NEXT: .LBB0_2: ; RV64I-NEXT: li a0, 32 @@ -64,8 +61,6 @@ define signext i32 @log2_i32(i32 signext %a) nounwind { ; RV64I: # %bb.0: ; RV64I-NEXT: beqz a0, .LBB1_2 ; RV64I-NEXT: # %bb.1: # %cond.false -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: srliw a1, a0, 1 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: srliw a1, a0, 2 @@ -91,14 +86,13 @@ define signext i32 @log2_i32(i32 signext %a) nounwind { ; RV64I-NEXT: srli a1, a0, 4 ; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: lui a1, 61681 -; RV64I-NEXT: addiw a1, a1, -241 +; RV64I-NEXT: addi a1, a1, -241 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srliw a0, a0, 24 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: j .LBB1_3 ; RV64I-NEXT: .LBB1_2: ; RV64I-NEXT: li a0, 32 @@ -121,50 +115,45 @@ define signext i32 @log2_i32(i32 signext %a) nounwind { define signext i32 @log2_ceil_i32(i32 signext %a) nounwind { ; RV64I-LABEL: log2_ceil_i32: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s0, 0(sp) # 8-byte Folded Spill -; RV64I-NEXT: addiw a0, a0, -1 -; RV64I-NEXT: li s0, 32 -; RV64I-NEXT: li a1, 32 -; RV64I-NEXT: beqz a0, .LBB2_2 +; RV64I-NEXT: addiw a1, a0, -1 +; RV64I-NEXT: li a0, 32 +; RV64I-NEXT: li a2, 32 +; RV64I-NEXT: beqz a1, .LBB2_2 ; RV64I-NEXT: # %bb.1: # %cond.false -; RV64I-NEXT: srliw a1, a0, 1 -; RV64I-NEXT: or a0, a0, a1 -; RV64I-NEXT: srliw a1, a0, 2 -; RV64I-NEXT: or a0, a0, a1 -; RV64I-NEXT: srliw a1, a0, 4 -; RV64I-NEXT: or a0, a0, a1 -; RV64I-NEXT: srliw a1, a0, 8 -; RV64I-NEXT: or a0, a0, a1 -; RV64I-NEXT: srliw a1, a0, 16 -; RV64I-NEXT: or a0, a0, a1 -; RV64I-NEXT: not a0, a0 -; RV64I-NEXT: srli a1, a0, 1 -; RV64I-NEXT: lui a2, 349525 -; RV64I-NEXT: addiw a2, a2, 1365 +; RV64I-NEXT: srliw a2, a1, 1 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: srliw a2, a1, 2 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: srliw a2, a1, 4 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: srliw a2, a1, 8 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: srliw a2, a1, 16 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: not a1, a1 +; RV64I-NEXT: srli a2, a1, 1 +; RV64I-NEXT: lui a3, 349525 +; RV64I-NEXT: addiw a3, a3, 1365 +; RV64I-NEXT: and a2, a2, a3 +; RV64I-NEXT: sub a1, a1, a2 +; RV64I-NEXT: lui a2, 209715 +; RV64I-NEXT: addiw a2, a2, 819 +; RV64I-NEXT: and a3, a1, a2 +; RV64I-NEXT: srli a1, a1, 2 ; RV64I-NEXT: and a1, a1, a2 -; RV64I-NEXT: sub a0, a0, a1 -; RV64I-NEXT: lui a1, 209715 -; RV64I-NEXT: addiw a1, a1, 819 -; RV64I-NEXT: and a2, a0, a1 -; RV64I-NEXT: srli a0, a0, 2 -; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: add a0, a2, a0 -; RV64I-NEXT: srli a1, a0, 4 -; RV64I-NEXT: add a0, a0, a1 -; RV64I-NEXT: lui a1, 61681 -; RV64I-NEXT: addiw a1, a1, -241 -; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: srliw a1, a0, 24 +; RV64I-NEXT: add a1, a3, a1 +; RV64I-NEXT: srli a2, a1, 4 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: lui a2, 61681 +; RV64I-NEXT: addi a2, a2, -241 +; RV64I-NEXT: and a1, a1, a2 +; RV64I-NEXT: slli a2, a1, 8 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: slli a2, a1, 16 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: srliw a2, a1, 24 ; RV64I-NEXT: .LBB2_2: # %cond.end -; RV64I-NEXT: sub a0, s0, a1 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s0, 0(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: sub a0, a0, a2 ; RV64I-NEXT: ret ; ; RV64ZBB-LABEL: log2_ceil_i32: @@ -183,48 +172,42 @@ define signext i32 @log2_ceil_i32(i32 signext %a) nounwind { define signext i32 @findLastSet_i32(i32 signext %a) nounwind { ; RV64I-LABEL: findLastSet_i32: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s0, 0(sp) # 8-byte Folded Spill -; RV64I-NEXT: mv s0, a0 -; RV64I-NEXT: srliw a0, a0, 1 -; RV64I-NEXT: or a0, s0, a0 -; RV64I-NEXT: srliw a1, a0, 2 -; RV64I-NEXT: or a0, a0, a1 -; RV64I-NEXT: srliw a1, a0, 4 -; RV64I-NEXT: or a0, a0, a1 -; RV64I-NEXT: srliw a1, a0, 8 -; RV64I-NEXT: or a0, a0, a1 -; RV64I-NEXT: srliw a1, a0, 16 -; RV64I-NEXT: or a0, a0, a1 -; RV64I-NEXT: not a0, a0 -; RV64I-NEXT: srli a1, a0, 1 -; RV64I-NEXT: lui a2, 349525 -; RV64I-NEXT: addiw a2, a2, 1365 +; RV64I-NEXT: srliw a1, a0, 1 +; RV64I-NEXT: or a1, a0, a1 +; RV64I-NEXT: srliw a2, a1, 2 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: srliw a2, a1, 4 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: srliw a2, a1, 8 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: srliw a2, a1, 16 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: not a1, a1 +; RV64I-NEXT: srli a2, a1, 1 +; RV64I-NEXT: lui a3, 349525 +; RV64I-NEXT: addiw a3, a3, 1365 +; RV64I-NEXT: and a2, a2, a3 +; RV64I-NEXT: sub a1, a1, a2 +; RV64I-NEXT: lui a2, 209715 +; RV64I-NEXT: addiw a2, a2, 819 +; RV64I-NEXT: and a3, a1, a2 +; RV64I-NEXT: srli a1, a1, 2 ; RV64I-NEXT: and a1, a1, a2 -; RV64I-NEXT: sub a0, a0, a1 -; RV64I-NEXT: lui a1, 209715 -; RV64I-NEXT: addiw a1, a1, 819 -; RV64I-NEXT: and a2, a0, a1 -; RV64I-NEXT: srli a0, a0, 2 -; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: add a0, a2, a0 -; RV64I-NEXT: srli a1, a0, 4 -; RV64I-NEXT: add a0, a0, a1 -; RV64I-NEXT: lui a1, 61681 -; RV64I-NEXT: addiw a1, a1, -241 -; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: srliw a0, a0, 24 -; RV64I-NEXT: xori a0, a0, 31 -; RV64I-NEXT: snez a1, s0 -; RV64I-NEXT: addi a1, a1, -1 -; RV64I-NEXT: or a0, a1, a0 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s0, 0(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: add a1, a3, a1 +; RV64I-NEXT: srli a2, a1, 4 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: lui a2, 61681 +; RV64I-NEXT: addi a2, a2, -241 +; RV64I-NEXT: and a1, a1, a2 +; RV64I-NEXT: slli a2, a1, 8 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: slli a2, a1, 16 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: srliw a1, a1, 24 +; RV64I-NEXT: xori a1, a1, 31 +; RV64I-NEXT: snez a0, a0 +; RV64I-NEXT: addi a0, a0, -1 +; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: ret ; ; RV64ZBB-LABEL: findLastSet_i32: @@ -248,10 +231,6 @@ define i32 @ctlz_lshr_i32(i32 signext %a) { ; RV64I-NEXT: srliw a0, a0, 1 ; RV64I-NEXT: beqz a0, .LBB4_2 ; RV64I-NEXT: # %bb.1: # %cond.false -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: .cfi_def_cfa_offset 16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill -; RV64I-NEXT: .cfi_offset ra, -8 ; RV64I-NEXT: srliw a1, a0, 1 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: srliw a1, a0, 2 @@ -277,14 +256,13 @@ define i32 @ctlz_lshr_i32(i32 signext %a) { ; RV64I-NEXT: srli a1, a0, 4 ; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: lui a1, 61681 -; RV64I-NEXT: addiw a1, a1, -241 +; RV64I-NEXT: addi a1, a1, -241 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srliw a0, a0, 24 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret ; RV64I-NEXT: .LBB4_2: ; RV64I-NEXT: li a0, 32 @@ -307,8 +285,6 @@ define i64 @ctlz_i64(i64 %a) nounwind { ; RV64I: # %bb.0: ; RV64I-NEXT: beqz a0, .LBB5_2 ; RV64I-NEXT: # %bb.1: # %cond.false -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: srli a1, a0, 1 ; RV64I-NEXT: or a0, a0, a1 ; RV64I-NEXT: srli a1, a0, 2 @@ -344,14 +320,13 @@ define i64 @ctlz_i64(i64 %a) nounwind { ; RV64I-NEXT: slli a2, a1, 32 ; RV64I-NEXT: add a1, a1, a2 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: slli a2, a1, 32 -; RV64I-NEXT: add a1, a1, a2 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 32 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srli a0, a0, 56 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret ; RV64I-NEXT: .LBB5_2: ; RV64I-NEXT: li a0, 64 @@ -544,8 +519,6 @@ declare i32 @llvm.ctpop.i32(i32) define signext i32 @ctpop_i32(i32 signext %a) nounwind { ; RV64I-LABEL: ctpop_i32: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: srli a1, a0, 1 ; RV64I-NEXT: lui a2, 349525 ; RV64I-NEXT: addiw a2, a2, 1365 @@ -560,14 +533,13 @@ define signext i32 @ctpop_i32(i32 signext %a) nounwind { ; RV64I-NEXT: srli a1, a0, 4 ; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: lui a1, 61681 -; RV64I-NEXT: addiw a1, a1, -241 +; RV64I-NEXT: addi a1, a1, -241 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srliw a0, a0, 24 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret ; ; RV64ZBB-LABEL: ctpop_i32: @@ -657,8 +629,6 @@ define i1 @ctpop_i32_ne_one(i32 signext %a) nounwind { define signext i32 @ctpop_i32_load(ptr %p) nounwind { ; RV64I-LABEL: ctpop_i32_load: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: lw a0, 0(a0) ; RV64I-NEXT: srli a1, a0, 1 ; RV64I-NEXT: lui a2, 349525 @@ -674,14 +644,13 @@ define signext i32 @ctpop_i32_load(ptr %p) nounwind { ; RV64I-NEXT: srli a1, a0, 4 ; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: lui a1, 61681 -; RV64I-NEXT: addiw a1, a1, -241 +; RV64I-NEXT: addi a1, a1, -241 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srliw a0, a0, 24 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret ; ; RV64ZBB-LABEL: ctpop_i32_load: @@ -699,58 +668,42 @@ declare <2 x i32> @llvm.ctpop.v2i32(<2 x i32>) define <2 x i32> @ctpop_v2i32(<2 x i32> %a) nounwind { ; RV64I-LABEL: ctpop_v2i32: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -64 -; RV64I-NEXT: sd ra, 56(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s0, 48(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s1, 40(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s2, 32(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s3, 24(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s4, 16(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s5, 8(sp) # 8-byte Folded Spill -; RV64I-NEXT: mv s0, a1 -; RV64I-NEXT: srli a1, a0, 1 -; RV64I-NEXT: lui a2, 349525 -; RV64I-NEXT: addiw s3, a2, 1365 -; RV64I-NEXT: and a1, a1, s3 -; RV64I-NEXT: sub a0, a0, a1 -; RV64I-NEXT: lui a1, 209715 -; RV64I-NEXT: addiw s4, a1, 819 -; RV64I-NEXT: and a1, a0, s4 +; RV64I-NEXT: srli a2, a0, 1 +; RV64I-NEXT: lui a3, 349525 +; RV64I-NEXT: addiw a3, a3, 1365 +; RV64I-NEXT: and a2, a2, a3 +; RV64I-NEXT: sub a0, a0, a2 +; RV64I-NEXT: lui a2, 209715 +; RV64I-NEXT: addiw a2, a2, 819 +; RV64I-NEXT: and a4, a0, a2 ; RV64I-NEXT: srli a0, a0, 2 -; RV64I-NEXT: and a0, a0, s4 -; RV64I-NEXT: add a0, a1, a0 -; RV64I-NEXT: srli a1, a0, 4 -; RV64I-NEXT: add a0, a0, a1 -; RV64I-NEXT: lui a1, 61681 -; RV64I-NEXT: addiw s5, a1, -241 -; RV64I-NEXT: and a0, a0, s5 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw s1, a1, 257 -; RV64I-NEXT: mv a1, s1 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: srliw s2, a0, 24 -; RV64I-NEXT: srli a0, s0, 1 -; RV64I-NEXT: and a0, a0, s3 -; RV64I-NEXT: sub s0, s0, a0 -; RV64I-NEXT: and a0, s0, s4 -; RV64I-NEXT: srli s0, s0, 2 -; RV64I-NEXT: and a1, s0, s4 -; RV64I-NEXT: add a0, a0, a1 -; RV64I-NEXT: srli a1, a0, 4 -; RV64I-NEXT: add a0, a0, a1 -; RV64I-NEXT: and a0, a0, s5 -; RV64I-NEXT: mv a1, s1 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: srliw a1, a0, 24 -; RV64I-NEXT: mv a0, s2 -; RV64I-NEXT: ld ra, 56(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s0, 48(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s1, 40(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s2, 32(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s3, 24(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s4, 16(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s5, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 64 +; RV64I-NEXT: and a0, a0, a2 +; RV64I-NEXT: add a0, a4, a0 +; RV64I-NEXT: srli a4, a0, 4 +; RV64I-NEXT: add a0, a0, a4 +; RV64I-NEXT: lui a4, 61681 +; RV64I-NEXT: addi a4, a4, -241 +; RV64I-NEXT: and a0, a0, a4 +; RV64I-NEXT: slli a5, a0, 8 +; RV64I-NEXT: add a0, a0, a5 +; RV64I-NEXT: slli a5, a0, 16 +; RV64I-NEXT: add a0, a0, a5 +; RV64I-NEXT: srliw a0, a0, 24 +; RV64I-NEXT: srli a5, a1, 1 +; RV64I-NEXT: and a3, a5, a3 +; RV64I-NEXT: sub a1, a1, a3 +; RV64I-NEXT: and a3, a1, a2 +; RV64I-NEXT: srli a1, a1, 2 +; RV64I-NEXT: and a1, a1, a2 +; RV64I-NEXT: add a1, a3, a1 +; RV64I-NEXT: srli a2, a1, 4 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: and a1, a1, a4 +; RV64I-NEXT: slli a2, a1, 8 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: slli a2, a1, 16 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: srliw a1, a1, 24 ; RV64I-NEXT: ret ; ; RV64ZBB-LABEL: ctpop_v2i32: @@ -875,8 +828,6 @@ declare i64 @llvm.ctpop.i64(i64) define i64 @ctpop_i64(i64 %a) nounwind { ; RV64I-LABEL: ctpop_i64: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64I-NEXT: srli a1, a0, 1 ; RV64I-NEXT: lui a2, 349525 ; RV64I-NEXT: addiw a2, a2, 1365 @@ -899,14 +850,13 @@ define i64 @ctpop_i64(i64 %a) nounwind { ; RV64I-NEXT: slli a2, a1, 32 ; RV64I-NEXT: add a1, a1, a2 ; RV64I-NEXT: and a0, a0, a1 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw a1, a1, 257 -; RV64I-NEXT: slli a2, a1, 32 -; RV64I-NEXT: add a1, a1, a2 -; RV64I-NEXT: call __muldi3 +; RV64I-NEXT: slli a1, a0, 8 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 16 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: slli a1, a0, 32 +; RV64I-NEXT: add a0, a0, a1 ; RV64I-NEXT: srli a0, a0, 56 -; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret ; ; RV64ZBB-LABEL: ctpop_i64: @@ -998,66 +948,52 @@ declare <2 x i64> @llvm.ctpop.v2i64(<2 x i64>) define <2 x i64> @ctpop_v2i64(<2 x i64> %a) nounwind { ; RV64I-LABEL: ctpop_v2i64: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -64 -; RV64I-NEXT: sd ra, 56(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s0, 48(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s1, 40(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s2, 32(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s3, 24(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s4, 16(sp) # 8-byte Folded Spill -; RV64I-NEXT: sd s5, 8(sp) # 8-byte Folded Spill -; RV64I-NEXT: mv s0, a1 -; RV64I-NEXT: srli a1, a0, 1 -; RV64I-NEXT: lui a2, 349525 -; RV64I-NEXT: addiw a2, a2, 1365 -; RV64I-NEXT: slli a3, a2, 32 -; RV64I-NEXT: add s3, a2, a3 -; RV64I-NEXT: and a1, a1, s3 -; RV64I-NEXT: sub a0, a0, a1 -; RV64I-NEXT: lui a1, 209715 -; RV64I-NEXT: addiw a1, a1, 819 -; RV64I-NEXT: slli a2, a1, 32 -; RV64I-NEXT: add s4, a1, a2 -; RV64I-NEXT: and a1, a0, s4 +; RV64I-NEXT: srli a2, a0, 1 +; RV64I-NEXT: lui a3, 349525 +; RV64I-NEXT: addiw a3, a3, 1365 +; RV64I-NEXT: slli a4, a3, 32 +; RV64I-NEXT: add a3, a3, a4 +; RV64I-NEXT: and a2, a2, a3 +; RV64I-NEXT: sub a0, a0, a2 +; RV64I-NEXT: lui a2, 209715 +; RV64I-NEXT: addiw a2, a2, 819 +; RV64I-NEXT: slli a4, a2, 32 +; RV64I-NEXT: add a2, a2, a4 +; RV64I-NEXT: and a4, a0, a2 ; RV64I-NEXT: srli a0, a0, 2 -; RV64I-NEXT: and a0, a0, s4 -; RV64I-NEXT: add a0, a1, a0 -; RV64I-NEXT: srli a1, a0, 4 -; RV64I-NEXT: add a0, a0, a1 -; RV64I-NEXT: lui a1, 61681 -; RV64I-NEXT: addiw a1, a1, -241 +; RV64I-NEXT: and a0, a0, a2 +; RV64I-NEXT: add a0, a4, a0 +; RV64I-NEXT: srli a4, a0, 4 +; RV64I-NEXT: add a0, a0, a4 +; RV64I-NEXT: lui a4, 61681 +; RV64I-NEXT: addiw a4, a4, -241 +; RV64I-NEXT: slli a5, a4, 32 +; RV64I-NEXT: add a4, a4, a5 +; RV64I-NEXT: and a0, a0, a4 +; RV64I-NEXT: slli a5, a0, 8 +; RV64I-NEXT: add a0, a0, a5 +; RV64I-NEXT: slli a5, a0, 16 +; RV64I-NEXT: add a0, a0, a5 +; RV64I-NEXT: slli a5, a0, 32 +; RV64I-NEXT: add a0, a0, a5 +; RV64I-NEXT: srli a0, a0, 56 +; RV64I-NEXT: srli a5, a1, 1 +; RV64I-NEXT: and a3, a5, a3 +; RV64I-NEXT: sub a1, a1, a3 +; RV64I-NEXT: and a3, a1, a2 +; RV64I-NEXT: srli a1, a1, 2 +; RV64I-NEXT: and a1, a1, a2 +; RV64I-NEXT: add a1, a3, a1 +; RV64I-NEXT: srli a2, a1, 4 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: and a1, a1, a4 +; RV64I-NEXT: slli a2, a1, 8 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: slli a2, a1, 16 +; RV64I-NEXT: add a1, a1, a2 ; RV64I-NEXT: slli a2, a1, 32 -; RV64I-NEXT: add s5, a1, a2 -; RV64I-NEXT: and a0, a0, s5 -; RV64I-NEXT: lui a1, 4112 -; RV64I-NEXT: addiw s1, a1, 257 -; RV64I-NEXT: slli a1, s1, 32 -; RV64I-NEXT: add s1, s1, a1 -; RV64I-NEXT: mv a1, s1 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: srli s2, a0, 56 -; RV64I-NEXT: srli a0, s0, 1 -; RV64I-NEXT: and a0, a0, s3 -; RV64I-NEXT: sub s0, s0, a0 -; RV64I-NEXT: and a0, s0, s4 -; RV64I-NEXT: srli s0, s0, 2 -; RV64I-NEXT: and a1, s0, s4 -; RV64I-NEXT: add a0, a0, a1 -; RV64I-NEXT: srli a1, a0, 4 -; RV64I-NEXT: add a0, a0, a1 -; RV64I-NEXT: and a0, a0, s5 -; RV64I-NEXT: mv a1, s1 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: srli a1, a0, 56 -; RV64I-NEXT: mv a0, s2 -; RV64I-NEXT: ld ra, 56(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s0, 48(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s1, 40(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s2, 32(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s3, 24(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s4, 16(sp) # 8-byte Folded Reload -; RV64I-NEXT: ld s5, 8(sp) # 8-byte Folded Reload -; RV64I-NEXT: addi sp, sp, 64 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: srli a1, a1, 56 ; RV64I-NEXT: ret ; ; RV64ZBB-LABEL: ctpop_v2i64: diff --git a/llvm/test/CodeGen/RISCV/rvv/abd.ll b/llvm/test/CodeGen/RISCV/rvv/abd.ll new file mode 100644 index 0000000000000000000000000000000000000000..ddbfbd0b59fa4b62e9862a10f448cfb84da8825f --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/abd.ll @@ -0,0 +1,343 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+v,+d -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK,RV32 +; RUN: llc -mtriple=riscv64 -mattr=+v,+d -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK,RV64 + +; +; SABD +; + +define <vscale x 16 x i8> @sabd_b(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b) { +; CHECK-LABEL: sabd_b: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e8, m2, ta, ma +; CHECK-NEXT: vmin.vv v12, v8, v10 +; CHECK-NEXT: vmax.vv v8, v8, v10 +; CHECK-NEXT: vsub.vv v8, v8, v12 +; CHECK-NEXT: ret + %a.sext = sext <vscale x 16 x i8> %a to <vscale x 16 x i16> + %b.sext = sext <vscale x 16 x i8> %b to <vscale x 16 x i16> + %sub = sub <vscale x 16 x i16> %a.sext, %b.sext + %abs = call <vscale x 16 x i16> @llvm.abs.nxv16i16(<vscale x 16 x i16> %sub, i1 true) + %trunc = trunc <vscale x 16 x i16> %abs to <vscale x 16 x i8> + ret <vscale x 16 x i8> %trunc +} + +define <vscale x 16 x i8> @sabd_b_promoted_ops(<vscale x 16 x i1> %a, <vscale x 16 x i1> %b) { +; CHECK-LABEL: sabd_b_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e8, m2, ta, ma +; CHECK-NEXT: vmv.v.i v10, 0 +; CHECK-NEXT: vmerge.vim v12, v10, -1, v0 +; CHECK-NEXT: vmv1r.v v0, v8 +; CHECK-NEXT: vmerge.vim v8, v10, -1, v0 +; CHECK-NEXT: vmin.vv v10, v12, v8 +; CHECK-NEXT: vmax.vv v8, v12, v8 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a.sext = sext <vscale x 16 x i1> %a to <vscale x 16 x i8> + %b.sext = sext <vscale x 16 x i1> %b to <vscale x 16 x i8> + %sub = sub <vscale x 16 x i8> %a.sext, %b.sext + %abs = call <vscale x 16 x i8> @llvm.abs.nxv16i8(<vscale x 16 x i8> %sub, i1 true) + ret <vscale x 16 x i8> %abs +} + +define <vscale x 8 x i16> @sabd_h(<vscale x 8 x i16> %a, <vscale x 8 x i16> %b) { +; CHECK-LABEL: sabd_h: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, m2, ta, ma +; CHECK-NEXT: vmin.vv v12, v8, v10 +; CHECK-NEXT: vmax.vv v8, v8, v10 +; CHECK-NEXT: vsub.vv v8, v8, v12 +; CHECK-NEXT: ret + %a.sext = sext <vscale x 8 x i16> %a to <vscale x 8 x i32> + %b.sext = sext <vscale x 8 x i16> %b to <vscale x 8 x i32> + %sub = sub <vscale x 8 x i32> %a.sext, %b.sext + %abs = call <vscale x 8 x i32> @llvm.abs.nxv8i32(<vscale x 8 x i32> %sub, i1 true) + %trunc = trunc <vscale x 8 x i32> %abs to <vscale x 8 x i16> + ret <vscale x 8 x i16> %trunc +} + +define <vscale x 8 x i16> @sabd_h_promoted_ops(<vscale x 8 x i8> %a, <vscale x 8 x i8> %b) { +; CHECK-LABEL: sabd_h_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v10, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v10 +; CHECK-NEXT: ret + %a.sext = sext <vscale x 8 x i8> %a to <vscale x 8 x i16> + %b.sext = sext <vscale x 8 x i8> %b to <vscale x 8 x i16> + %sub = sub <vscale x 8 x i16> %a.sext, %b.sext + %abs = call <vscale x 8 x i16> @llvm.abs.nxv8i16(<vscale x 8 x i16> %sub, i1 true) + ret <vscale x 8 x i16> %abs +} + +define <vscale x 4 x i32> @sabd_s(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) { +; CHECK-LABEL: sabd_s: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vmin.vv v12, v8, v10 +; CHECK-NEXT: vmax.vv v8, v8, v10 +; CHECK-NEXT: vsub.vv v8, v8, v12 +; CHECK-NEXT: ret + %a.sext = sext <vscale x 4 x i32> %a to <vscale x 4 x i64> + %b.sext = sext <vscale x 4 x i32> %b to <vscale x 4 x i64> + %sub = sub <vscale x 4 x i64> %a.sext, %b.sext + %abs = call <vscale x 4 x i64> @llvm.abs.nxv4i64(<vscale x 4 x i64> %sub, i1 true) + %trunc = trunc <vscale x 4 x i64> %abs to <vscale x 4 x i32> + ret <vscale x 4 x i32> %trunc +} + +define <vscale x 4 x i32> @sabd_s_promoted_ops(<vscale x 4 x i16> %a, <vscale x 4 x i16> %b) { +; CHECK-LABEL: sabd_s_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, m1, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v10, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v10 +; CHECK-NEXT: ret + %a.sext = sext <vscale x 4 x i16> %a to <vscale x 4 x i32> + %b.sext = sext <vscale x 4 x i16> %b to <vscale x 4 x i32> + %sub = sub <vscale x 4 x i32> %a.sext, %b.sext + %abs = call <vscale x 4 x i32> @llvm.abs.nxv4i32(<vscale x 4 x i32> %sub, i1 true) + ret <vscale x 4 x i32> %abs +} + +; FIXME: Crashes legalization if enabled +;; define <vscale x 2 x i64> @sabd_d(<vscale x 2 x i64> %a, <vscale x 2 x i64> %b) { +;; %a.sext = sext <vscale x 2 x i64> %a to <vscale x 2 x i128> +;; %b.sext = sext <vscale x 2 x i64> %b to <vscale x 2 x i128> +;; %sub = sub <vscale x 2 x i128> %a.sext, %b.sext +;; %abs = call <vscale x 2 x i128> @llvm.abs.nxv2i128(<vscale x 2 x i128> %sub, i1 true) +;; %trunc = trunc <vscale x 2 x i128> %abs to <vscale x 2 x i64> +;; ret <vscale x 2 x i64> %trunc +;; } + +define <vscale x 2 x i64> @sabd_d_promoted_ops(<vscale x 2 x i32> %a, <vscale x 2 x i32> %b) { +; CHECK-LABEL: sabd_d_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v10, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v10 +; CHECK-NEXT: ret + %a.sext = sext <vscale x 2 x i32> %a to <vscale x 2 x i64> + %b.sext = sext <vscale x 2 x i32> %b to <vscale x 2 x i64> + %sub = sub <vscale x 2 x i64> %a.sext, %b.sext + %abs = call <vscale x 2 x i64> @llvm.abs.nxv2i64(<vscale x 2 x i64> %sub, i1 true) + ret <vscale x 2 x i64> %abs +} + +; +; UABD +; + +define <vscale x 16 x i8> @uabd_b(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b) { +; CHECK-LABEL: uabd_b: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e8, m2, ta, ma +; CHECK-NEXT: vminu.vv v12, v8, v10 +; CHECK-NEXT: vmaxu.vv v8, v8, v10 +; CHECK-NEXT: vsub.vv v8, v8, v12 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 16 x i8> %a to <vscale x 16 x i16> + %b.zext = zext <vscale x 16 x i8> %b to <vscale x 16 x i16> + %sub = sub <vscale x 16 x i16> %a.zext, %b.zext + %abs = call <vscale x 16 x i16> @llvm.abs.nxv16i16(<vscale x 16 x i16> %sub, i1 true) + %trunc = trunc <vscale x 16 x i16> %abs to <vscale x 16 x i8> + ret <vscale x 16 x i8> %trunc +} + +define <vscale x 16 x i8> @uabd_b_promoted_ops(<vscale x 16 x i1> %a, <vscale x 16 x i1> %b) { +; CHECK-LABEL: uabd_b_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e8, m2, ta, ma +; CHECK-NEXT: vmv.v.i v10, 0 +; CHECK-NEXT: vmerge.vim v12, v10, 1, v0 +; CHECK-NEXT: vmv1r.v v0, v8 +; CHECK-NEXT: vmerge.vim v8, v10, 1, v0 +; CHECK-NEXT: vminu.vv v10, v12, v8 +; CHECK-NEXT: vmaxu.vv v8, v12, v8 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 16 x i1> %a to <vscale x 16 x i8> + %b.zext = zext <vscale x 16 x i1> %b to <vscale x 16 x i8> + %sub = sub <vscale x 16 x i8> %a.zext, %b.zext + %abs = call <vscale x 16 x i8> @llvm.abs.nxv16i8(<vscale x 16 x i8> %sub, i1 true) + ret <vscale x 16 x i8> %abs +} + +define <vscale x 8 x i16> @uabd_h(<vscale x 8 x i16> %a, <vscale x 8 x i16> %b) { +; CHECK-LABEL: uabd_h: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, m2, ta, ma +; CHECK-NEXT: vminu.vv v12, v8, v10 +; CHECK-NEXT: vmaxu.vv v8, v8, v10 +; CHECK-NEXT: vsub.vv v8, v8, v12 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 8 x i16> %a to <vscale x 8 x i32> + %b.zext = zext <vscale x 8 x i16> %b to <vscale x 8 x i32> + %sub = sub <vscale x 8 x i32> %a.zext, %b.zext + %abs = call <vscale x 8 x i32> @llvm.abs.nxv8i32(<vscale x 8 x i32> %sub, i1 true) + %trunc = trunc <vscale x 8 x i32> %abs to <vscale x 8 x i16> + ret <vscale x 8 x i16> %trunc +} + +define <vscale x 8 x i16> @uabd_h_promoted_ops(<vscale x 8 x i8> %a, <vscale x 8 x i8> %b) { +; CHECK-LABEL: uabd_h_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v10, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v10 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 8 x i8> %a to <vscale x 8 x i16> + %b.zext = zext <vscale x 8 x i8> %b to <vscale x 8 x i16> + %sub = sub <vscale x 8 x i16> %a.zext, %b.zext + %abs = call <vscale x 8 x i16> @llvm.abs.nxv8i16(<vscale x 8 x i16> %sub, i1 true) + ret <vscale x 8 x i16> %abs +} + +define <vscale x 4 x i32> @uabd_s(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b) { +; CHECK-LABEL: uabd_s: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vminu.vv v12, v8, v10 +; CHECK-NEXT: vmaxu.vv v8, v8, v10 +; CHECK-NEXT: vsub.vv v8, v8, v12 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 4 x i32> %a to <vscale x 4 x i64> + %b.zext = zext <vscale x 4 x i32> %b to <vscale x 4 x i64> + %sub = sub <vscale x 4 x i64> %a.zext, %b.zext + %abs = call <vscale x 4 x i64> @llvm.abs.nxv4i64(<vscale x 4 x i64> %sub, i1 true) + %trunc = trunc <vscale x 4 x i64> %abs to <vscale x 4 x i32> + ret <vscale x 4 x i32> %trunc +} + +define <vscale x 4 x i32> @uabd_s_promoted_ops(<vscale x 4 x i16> %a, <vscale x 4 x i16> %b) { +; CHECK-LABEL: uabd_s_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, m1, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v10, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v10 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 4 x i16> %a to <vscale x 4 x i32> + %b.zext = zext <vscale x 4 x i16> %b to <vscale x 4 x i32> + %sub = sub <vscale x 4 x i32> %a.zext, %b.zext + %abs = call <vscale x 4 x i32> @llvm.abs.nxv4i32(<vscale x 4 x i32> %sub, i1 true) + ret <vscale x 4 x i32> %abs +} + +; FIXME: Crashes legalization if enabled +;; define <vscale x 2 x i64> @uabd_d(<vscale x 2 x i64> %a, <vscale x 2 x i64> %b) { +;; %a.zext = zext <vscale x 2 x i64> %a to <vscale x 2 x i128> +;; %b.zext = zext <vscale x 2 x i64> %b to <vscale x 2 x i128> +;; %sub = sub <vscale x 2 x i128> %a.zext, %b.zext +;; %abs = call <vscale x 2 x i128> @llvm.abs.nxv2i128(<vscale x 2 x i128> %sub, i1 true) +;; %trunc = trunc <vscale x 2 x i128> %abs to <vscale x 2 x i64> +;; ret <vscale x 2 x i64> %trunc +;; } + +define <vscale x 2 x i64> @uabd_d_promoted_ops(<vscale x 2 x i32> %a, <vscale x 2 x i32> %b) { +; CHECK-LABEL: uabd_d_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v10, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v10 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 2 x i32> %a to <vscale x 2 x i64> + %b.zext = zext <vscale x 2 x i32> %b to <vscale x 2 x i64> + %sub = sub <vscale x 2 x i64> %a.zext, %b.zext + %abs = call <vscale x 2 x i64> @llvm.abs.nxv2i64(<vscale x 2 x i64> %sub, i1 true) + ret <vscale x 2 x i64> %abs +} + +; Test the situation where isLegal(ISD::ABD, typeof(%a)) returns true but %a and +; %b have differing types. +define <vscale x 4 x i32> @uabd_non_matching_extension(<vscale x 4 x i32> %a, <vscale x 4 x i8> %b) { +; CHECK-LABEL: uabd_non_matching_extension: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf4 v12, v10 +; CHECK-NEXT: vminu.vv v10, v8, v12 +; CHECK-NEXT: vmaxu.vv v8, v8, v12 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 4 x i32> %a to <vscale x 4 x i64> + %b.zext = zext <vscale x 4 x i8> %b to <vscale x 4 x i64> + %sub = sub <vscale x 4 x i64> %a.zext, %b.zext + %abs = call <vscale x 4 x i64> @llvm.abs.nxv4i64(<vscale x 4 x i64> %sub, i1 true) + %trunc = trunc <vscale x 4 x i64> %abs to <vscale x 4 x i32> + ret <vscale x 4 x i32> %trunc +} + +; Test the situation where isLegal(ISD::ABD, typeof(%a.zext)) returns true but +; %a and %b have differing types. +define <vscale x 4 x i32> @uabd_non_matching_promoted_ops(<vscale x 4 x i8> %a, <vscale x 4 x i16> %b) { +; CHECK-LABEL: uabd_non_matching_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, m1, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vminu.vv v8, v10, v9 +; CHECK-NEXT: vmaxu.vv v9, v10, v9 +; CHECK-NEXT: vsub.vv v10, v9, v8 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v10 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 4 x i8> %a to <vscale x 4 x i32> + %b.zext = zext <vscale x 4 x i16> %b to <vscale x 4 x i32> + %sub = sub <vscale x 4 x i32> %a.zext, %b.zext + %abs = call <vscale x 4 x i32> @llvm.abs.nxv4i32(<vscale x 4 x i32> %sub, i1 true) + ret <vscale x 4 x i32> %abs +} + +; Test the situation where isLegal(ISD::ABD, typeof(%a)) returns true but %a and +; %b are promoted differently. +define <vscale x 4 x i32> @uabd_non_matching_promotion(<vscale x 4 x i8> %a, <vscale x 4 x i8> %b) { +; CHECK-LABEL: uabd_non_matching_promotion: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf4 v10, v8 +; CHECK-NEXT: vsetvli zero, zero, e16, m1, ta, ma +; CHECK-NEXT: vsext.vf2 v8, v9 +; CHECK-NEXT: vwsub.wv v10, v10, v8 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vrsub.vi v8, v10, 0 +; CHECK-NEXT: vmax.vv v8, v10, v8 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 4 x i8> %a to <vscale x 4 x i32> + %b.zext = sext <vscale x 4 x i8> %b to <vscale x 4 x i32> + %sub = sub <vscale x 4 x i32> %a.zext, %b.zext + %abs = call <vscale x 4 x i32> @llvm.abs.nxv4i32(<vscale x 4 x i32> %sub, i1 true) + ret <vscale x 4 x i32> %abs +} + +declare <vscale x 16 x i8> @llvm.abs.nxv16i8(<vscale x 16 x i8>, i1) + +declare <vscale x 8 x i16> @llvm.abs.nxv8i16(<vscale x 8 x i16>, i1) +declare <vscale x 16 x i16> @llvm.abs.nxv16i16(<vscale x 16 x i16>, i1) + +declare <vscale x 4 x i32> @llvm.abs.nxv4i32(<vscale x 4 x i32>, i1) +declare <vscale x 8 x i32> @llvm.abs.nxv8i32(<vscale x 8 x i32>, i1) + +declare <vscale x 2 x i64> @llvm.abs.nxv2i64(<vscale x 2 x i64>, i1) +declare <vscale x 4 x i64> @llvm.abs.nxv4i64(<vscale x 4 x i64>, i1) + +declare <vscale x 2 x i128> @llvm.abs.nxv2i128(<vscale x 2 x i128>, i1) +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; RV32: {{.*}} +; RV64: {{.*}} diff --git a/llvm/test/CodeGen/RISCV/rvv/addi-rvv-stack-object.mir b/llvm/test/CodeGen/RISCV/rvv/addi-rvv-stack-object.mir index 525572882103945c730089bbb95defa0bc02c68d..080a89e41f0d54eab67d9ee75c4efcefa2767923 100644 --- a/llvm/test/CodeGen/RISCV/rvv/addi-rvv-stack-object.mir +++ b/llvm/test/CodeGen/RISCV/rvv/addi-rvv-stack-object.mir @@ -22,7 +22,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 16 - adjustsStack: false + adjustsStack: true hasCalls: true stackProtector: '' functionContext: '' diff --git a/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-array.ll b/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-array.ll index 1d025a2f776f82575624586b4ad2fd3f2367da6f..1fe91c721f4dd2b2a9751934d32c3a679b7ed9ba 100644 --- a/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-array.ll +++ b/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-array.ll @@ -18,15 +18,15 @@ define void @test(ptr %addr) { ; CHECK-NEXT: add a2, a0, a1 ; CHECK-NEXT: vl1re64.v v8, (a2) ; CHECK-NEXT: slli a2, a1, 1 -; CHECK-NEXT: add a3, a0, a2 -; CHECK-NEXT: vl1re64.v v9, (a3) +; CHECK-NEXT: vl1re64.v v9, (a0) +; CHECK-NEXT: add a0, a0, a2 ; CHECK-NEXT: vl1re64.v v10, (a0) ; CHECK-NEXT: addi a0, sp, 16 +; CHECK-NEXT: vs1r.v v9, (a0) ; CHECK-NEXT: add a2, a0, a2 -; CHECK-NEXT: vs1r.v v9, (a2) -; CHECK-NEXT: add a1, a0, a1 -; CHECK-NEXT: vs1r.v v8, (a1) -; CHECK-NEXT: vs1r.v v10, (a0) +; CHECK-NEXT: vs1r.v v10, (a2) +; CHECK-NEXT: add a0, a0, a1 +; CHECK-NEXT: vs1r.v v8, (a0) ; CHECK-NEXT: csrrs a0, vlenb, zero ; CHECK-NEXT: slli a0, a0, 2 ; CHECK-NEXT: add sp, sp, a0 diff --git a/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-struct.ll b/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-struct.ll index 64031f8a93598f690015bc74dc73aabca82df94f..a9a680d54d589779e530a94eb0e933573cde62de 100644 --- a/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-struct.ll +++ b/llvm/test/CodeGen/RISCV/rvv/alloca-load-store-scalable-struct.ll @@ -16,13 +16,13 @@ define <vscale x 1 x double> @test(ptr %addr, i64 %vl) { ; CHECK-NEXT: sub sp, sp, a2 ; CHECK-NEXT: .cfi_escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x10, 0x22, 0x11, 0x02, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # sp + 16 + 2 * vlenb ; CHECK-NEXT: csrrs a2, vlenb, zero -; CHECK-NEXT: add a3, a0, a2 -; CHECK-NEXT: vl1re64.v v8, (a3) +; CHECK-NEXT: vl1re64.v v8, (a0) +; CHECK-NEXT: add a0, a0, a2 ; CHECK-NEXT: vl1re64.v v9, (a0) ; CHECK-NEXT: addi a0, sp, 16 +; CHECK-NEXT: vs1r.v v8, (a0) ; CHECK-NEXT: add a2, a0, a2 -; CHECK-NEXT: vs1r.v v8, (a2) -; CHECK-NEXT: vs1r.v v9, (a0) +; CHECK-NEXT: vs1r.v v9, (a2) ; CHECK-NEXT: vl1re64.v v8, (a2) ; CHECK-NEXT: vl1re64.v v9, (a0) ; CHECK-NEXT: vsetvli zero, a1, e64, m1, ta, ma diff --git a/llvm/test/CodeGen/RISCV/rvv/binop-zext.ll b/llvm/test/CodeGen/RISCV/rvv/binop-zext.ll new file mode 100644 index 0000000000000000000000000000000000000000..2d5258fbabfac3a58039cf2f5278f2cafc8b9403 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/binop-zext.ll @@ -0,0 +1,154 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple=riscv32 -mattr=+v -verify-machineinstrs < %s | FileCheck %s +; RUN: llc -mtriple=riscv64 -mattr=+v -verify-machineinstrs < %s | FileCheck %s + +; Check that we perform binary arithmetic in a narrower type where possible, via +; combineBinOpOfZExt or otherwise. + +define <vscale x 8 x i32> @add(<vscale x 8 x i8> %a, <vscale x 8 x i8> %b) { +; CHECK-LABEL: add: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma +; CHECK-NEXT: vwaddu.vv v12, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v12 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 8 x i8> %a to <vscale x 8 x i32> + %b.zext = zext <vscale x 8 x i8> %b to <vscale x 8 x i32> + %add = add <vscale x 8 x i32> %a.zext, %b.zext + ret <vscale x 8 x i32> %add +} + +define <vscale x 8 x i32> @sub(<vscale x 8 x i8> %a, <vscale x 8 x i8> %b) { +; CHECK-LABEL: sub: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma +; CHECK-NEXT: vwsubu.vv v12, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf2 v8, v12 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 8 x i8> %a to <vscale x 8 x i32> + %b.zext = zext <vscale x 8 x i8> %b to <vscale x 8 x i32> + %sub = sub <vscale x 8 x i32> %a.zext, %b.zext + ret <vscale x 8 x i32> %sub +} + +define <vscale x 8 x i32> @mul(<vscale x 8 x i8> %a, <vscale x 8 x i8> %b) { +; CHECK-LABEL: mul: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma +; CHECK-NEXT: vwmulu.vv v12, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v12 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 8 x i8> %a to <vscale x 8 x i32> + %b.zext = zext <vscale x 8 x i8> %b to <vscale x 8 x i32> + %mul = mul <vscale x 8 x i32> %a.zext, %b.zext + ret <vscale x 8 x i32> %mul +} + +define <vscale x 8 x i32> @sdiv(<vscale x 8 x i8> %a, <vscale x 8 x i8> %b) { +; CHECK-LABEL: sdiv: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v9 +; CHECK-NEXT: vzext.vf2 v12, v8 +; CHECK-NEXT: vdivu.vv v12, v12, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v12 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 8 x i8> %a to <vscale x 8 x i32> + %b.zext = zext <vscale x 8 x i8> %b to <vscale x 8 x i32> + %sdiv = sdiv <vscale x 8 x i32> %a.zext, %b.zext + ret <vscale x 8 x i32> %sdiv +} + +define <vscale x 8 x i32> @udiv(<vscale x 8 x i8> %a, <vscale x 8 x i8> %b) { +; CHECK-LABEL: udiv: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v9 +; CHECK-NEXT: vzext.vf2 v12, v8 +; CHECK-NEXT: vdivu.vv v12, v12, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v12 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 8 x i8> %a to <vscale x 8 x i32> + %b.zext = zext <vscale x 8 x i8> %b to <vscale x 8 x i32> + %udiv = udiv <vscale x 8 x i32> %a.zext, %b.zext + ret <vscale x 8 x i32> %udiv +} + +define <vscale x 8 x i32> @srem(<vscale x 8 x i8> %a, <vscale x 8 x i8> %b) { +; CHECK-LABEL: srem: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v9 +; CHECK-NEXT: vzext.vf2 v12, v8 +; CHECK-NEXT: vremu.vv v12, v12, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v12 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 8 x i8> %a to <vscale x 8 x i32> + %b.zext = zext <vscale x 8 x i8> %b to <vscale x 8 x i32> + %srem = srem <vscale x 8 x i32> %a.zext, %b.zext + ret <vscale x 8 x i32> %srem +} + +define <vscale x 8 x i32> @urem(<vscale x 8 x i8> %a, <vscale x 8 x i8> %b) { +; CHECK-LABEL: urem: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v9 +; CHECK-NEXT: vzext.vf2 v12, v8 +; CHECK-NEXT: vremu.vv v12, v12, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v12 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 8 x i8> %a to <vscale x 8 x i32> + %b.zext = zext <vscale x 8 x i8> %b to <vscale x 8 x i32> + %urem = urem <vscale x 8 x i32> %a.zext, %b.zext + ret <vscale x 8 x i32> %urem +} + +define <vscale x 8 x i32> @and(<vscale x 8 x i8> %a, <vscale x 8 x i8> %b) { +; CHECK-LABEL: and: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma +; CHECK-NEXT: vand.vv v12, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf4 v8, v12 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 8 x i8> %a to <vscale x 8 x i32> + %b.zext = zext <vscale x 8 x i8> %b to <vscale x 8 x i32> + %shl = and <vscale x 8 x i32> %a.zext, %b.zext + ret <vscale x 8 x i32> %shl +} + +define <vscale x 8 x i32> @or(<vscale x 8 x i8> %a, <vscale x 8 x i8> %b) { +; CHECK-LABEL: or: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma +; CHECK-NEXT: vor.vv v12, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf4 v8, v12 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 8 x i8> %a to <vscale x 8 x i32> + %b.zext = zext <vscale x 8 x i8> %b to <vscale x 8 x i32> + %or = or <vscale x 8 x i32> %a.zext, %b.zext + ret <vscale x 8 x i32> %or +} + +define <vscale x 8 x i32> @xor(<vscale x 8 x i8> %a, <vscale x 8 x i8> %b) { +; CHECK-LABEL: xor: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma +; CHECK-NEXT: vxor.vv v12, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf4 v8, v12 +; CHECK-NEXT: ret + %a.zext = zext <vscale x 8 x i8> %a to <vscale x 8 x i32> + %b.zext = zext <vscale x 8 x i8> %b to <vscale x 8 x i32> + %xor = xor <vscale x 8 x i32> %a.zext, %b.zext + ret <vscale x 8 x i32> %xor +} diff --git a/llvm/test/CodeGen/RISCV/rvv/callee-saved-regs.ll b/llvm/test/CodeGen/RISCV/rvv/callee-saved-regs.ll new file mode 100644 index 0000000000000000000000000000000000000000..84936d88e1874fd6abb0cd16757f88d802ef3a85 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/callee-saved-regs.ll @@ -0,0 +1,95 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+m -mattr=+v -O2 < %s \ +; RUN: | FileCheck --check-prefix=SPILL-O2 %s + +define <vscale x 1 x i32> @test_vector_std(<vscale x 1 x i32> %va) nounwind { +; SPILL-O2-LABEL: test_vector_std: +; SPILL-O2: # %bb.0: # %entry +; SPILL-O2-NEXT: addi sp, sp, -16 +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: slli a0, a0, 1 +; SPILL-O2-NEXT: sub sp, sp, a0 +; SPILL-O2-NEXT: addi a0, sp, 16 +; SPILL-O2-NEXT: vs1r.v v8, (a0) # Unknown-size Folded Spill +; SPILL-O2-NEXT: #APP +; SPILL-O2-NEXT: #NO_APP +; SPILL-O2-NEXT: vl1r.v v8, (a0) # Unknown-size Folded Reload +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: slli a0, a0, 1 +; SPILL-O2-NEXT: add sp, sp, a0 +; SPILL-O2-NEXT: addi sp, sp, 16 +; SPILL-O2-NEXT: ret +entry: + call void asm sideeffect "", + "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29},~{v30},~{v31}"() + + ret <vscale x 1 x i32> %va +} + +define riscv_vector_cc <vscale x 1 x i32> @test_vector_callee(<vscale x 1 x i32> %va) nounwind { +; SPILL-O2-LABEL: test_vector_callee: +; SPILL-O2: # %bb.0: # %entry +; SPILL-O2-NEXT: addi sp, sp, -16 +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: slli a0, a0, 4 +; SPILL-O2-NEXT: sub sp, sp, a0 +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: slli a1, a0, 4 +; SPILL-O2-NEXT: sub a0, a1, a0 +; SPILL-O2-NEXT: add a0, sp, a0 +; SPILL-O2-NEXT: addi a0, a0, 16 +; SPILL-O2-NEXT: vs1r.v v1, (a0) # Unknown-size Folded Spill +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: li a1, 13 +; SPILL-O2-NEXT: mul a0, a0, a1 +; SPILL-O2-NEXT: add a0, sp, a0 +; SPILL-O2-NEXT: addi a0, a0, 16 +; SPILL-O2-NEXT: vs2r.v v2, (a0) # Unknown-size Folded Spill +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: slli a1, a0, 3 +; SPILL-O2-NEXT: add a0, a1, a0 +; SPILL-O2-NEXT: add a0, sp, a0 +; SPILL-O2-NEXT: addi a0, a0, 16 +; SPILL-O2-NEXT: vs4r.v v4, (a0) # Unknown-size Folded Spill +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: add a0, sp, a0 +; SPILL-O2-NEXT: addi a0, a0, 16 +; SPILL-O2-NEXT: vs8r.v v24, (a0) # Unknown-size Folded Spill +; SPILL-O2-NEXT: addi a0, sp, 16 +; SPILL-O2-NEXT: vs1r.v v8, (a0) # Unknown-size Folded Spill +; SPILL-O2-NEXT: #APP +; SPILL-O2-NEXT: #NO_APP +; SPILL-O2-NEXT: vl1r.v v8, (a0) # Unknown-size Folded Reload +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: slli a1, a0, 4 +; SPILL-O2-NEXT: sub a0, a1, a0 +; SPILL-O2-NEXT: add a0, sp, a0 +; SPILL-O2-NEXT: addi a0, a0, 16 +; SPILL-O2-NEXT: vl1r.v v1, (a0) # Unknown-size Folded Reload +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: li a1, 13 +; SPILL-O2-NEXT: mul a0, a0, a1 +; SPILL-O2-NEXT: add a0, sp, a0 +; SPILL-O2-NEXT: addi a0, a0, 16 +; SPILL-O2-NEXT: vl2r.v v2, (a0) # Unknown-size Folded Reload +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: slli a1, a0, 3 +; SPILL-O2-NEXT: add a0, a1, a0 +; SPILL-O2-NEXT: add a0, sp, a0 +; SPILL-O2-NEXT: addi a0, a0, 16 +; SPILL-O2-NEXT: vl4r.v v4, (a0) # Unknown-size Folded Reload +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: add a0, sp, a0 +; SPILL-O2-NEXT: addi a0, a0, 16 +; SPILL-O2-NEXT: vl8r.v v24, (a0) # Unknown-size Folded Reload +; SPILL-O2-NEXT: csrr a0, vlenb +; SPILL-O2-NEXT: slli a0, a0, 4 +; SPILL-O2-NEXT: add sp, sp, a0 +; SPILL-O2-NEXT: addi sp, sp, 16 +; SPILL-O2-NEXT: ret +entry: + call void asm sideeffect "", + "~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{v20},~{v21},~{v22},~{v23},~{v24},~{v25},~{v26},~{v27},~{v28},~{v29},~{v30},~{v31}"() + + ret <vscale x 1 x i32> %va +} diff --git a/llvm/test/CodeGen/RISCV/rvv/calling-conv.ll b/llvm/test/CodeGen/RISCV/rvv/calling-conv.ll index 78385a80b47ebd399fc3bc1a89a7f46c408fc6ce..90edb994ce82220594f55d0b4008ca64308c79de 100644 --- a/llvm/test/CodeGen/RISCV/rvv/calling-conv.ll +++ b/llvm/test/CodeGen/RISCV/rvv/calling-conv.ll @@ -86,3 +86,166 @@ define <vscale x 32 x i32> @caller_scalable_vector_split_indirect(<vscale x 32 x %a = call <vscale x 32 x i32> @callee_scalable_vector_split_indirect(<vscale x 32 x i32> zeroinitializer, <vscale x 32 x i32> %x) ret <vscale x 32 x i32> %a } + +define {<vscale x 4 x i32>, <vscale x 4 x i32>} @caller_tuple_return() { +; RV32-LABEL: caller_tuple_return: +; RV32: # %bb.0: +; RV32-NEXT: addi sp, sp, -16 +; RV32-NEXT: .cfi_def_cfa_offset 16 +; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-NEXT: .cfi_offset ra, -4 +; RV32-NEXT: call callee_tuple_return +; RV32-NEXT: vmv2r.v v12, v8 +; RV32-NEXT: vmv2r.v v8, v10 +; RV32-NEXT: vmv2r.v v10, v12 +; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-NEXT: addi sp, sp, 16 +; RV32-NEXT: ret +; +; RV64-LABEL: caller_tuple_return: +; RV64: # %bb.0: +; RV64-NEXT: addi sp, sp, -16 +; RV64-NEXT: .cfi_def_cfa_offset 16 +; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-NEXT: .cfi_offset ra, -8 +; RV64-NEXT: call callee_tuple_return +; RV64-NEXT: vmv2r.v v12, v8 +; RV64-NEXT: vmv2r.v v8, v10 +; RV64-NEXT: vmv2r.v v10, v12 +; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-NEXT: addi sp, sp, 16 +; RV64-NEXT: ret + %a = call {<vscale x 4 x i32>, <vscale x 4 x i32>} @callee_tuple_return() + %b = extractvalue {<vscale x 4 x i32>, <vscale x 4 x i32>} %a, 0 + %c = extractvalue {<vscale x 4 x i32>, <vscale x 4 x i32>} %a, 1 + %d = insertvalue {<vscale x 4 x i32>, <vscale x 4 x i32>} poison, <vscale x 4 x i32> %c, 0 + %e = insertvalue {<vscale x 4 x i32>, <vscale x 4 x i32>} %d, <vscale x 4 x i32> %b, 1 + ret {<vscale x 4 x i32>, <vscale x 4 x i32>} %e +} + +declare {<vscale x 4 x i32>, <vscale x 4 x i32>} @callee_tuple_return() + +define void @caller_tuple_argument({<vscale x 4 x i32>, <vscale x 4 x i32>} %x) { +; RV32-LABEL: caller_tuple_argument: +; RV32: # %bb.0: +; RV32-NEXT: addi sp, sp, -16 +; RV32-NEXT: .cfi_def_cfa_offset 16 +; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32-NEXT: .cfi_offset ra, -4 +; RV32-NEXT: vmv2r.v v12, v8 +; RV32-NEXT: vmv2r.v v8, v10 +; RV32-NEXT: vmv2r.v v10, v12 +; RV32-NEXT: call callee_tuple_argument +; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32-NEXT: addi sp, sp, 16 +; RV32-NEXT: ret +; +; RV64-LABEL: caller_tuple_argument: +; RV64: # %bb.0: +; RV64-NEXT: addi sp, sp, -16 +; RV64-NEXT: .cfi_def_cfa_offset 16 +; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64-NEXT: .cfi_offset ra, -8 +; RV64-NEXT: vmv2r.v v12, v8 +; RV64-NEXT: vmv2r.v v8, v10 +; RV64-NEXT: vmv2r.v v10, v12 +; RV64-NEXT: call callee_tuple_argument +; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64-NEXT: addi sp, sp, 16 +; RV64-NEXT: ret + %a = extractvalue {<vscale x 4 x i32>, <vscale x 4 x i32>} %x, 0 + %b = extractvalue {<vscale x 4 x i32>, <vscale x 4 x i32>} %x, 1 + %c = insertvalue {<vscale x 4 x i32>, <vscale x 4 x i32>} poison, <vscale x 4 x i32> %b, 0 + %d = insertvalue {<vscale x 4 x i32>, <vscale x 4 x i32>} %c, <vscale x 4 x i32> %a, 1 + call void @callee_tuple_argument({<vscale x 4 x i32>, <vscale x 4 x i32>} %d) + ret void +} + +declare void @callee_tuple_argument({<vscale x 4 x i32>, <vscale x 4 x i32>}) + +; %0 -> v8 +; %1 -> v9 +define <vscale x 1 x i64> @case1(<vscale x 1 x i64> %0, <vscale x 1 x i64> %1) { +; CHECK-LABEL: case1: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma +; CHECK-NEXT: vadd.vv v8, v8, v9 +; CHECK-NEXT: ret + %a = add <vscale x 1 x i64> %0, %1 + ret <vscale x 1 x i64> %a +} + +; %0 -> v8 +; %1 -> v10-v11 +; %2 -> v9 +define <vscale x 1 x i64> @case2_1(<vscale x 1 x i64> %0, <vscale x 2 x i64> %1, <vscale x 1 x i64> %2) { +; CHECK-LABEL: case2_1: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma +; CHECK-NEXT: vadd.vv v8, v8, v9 +; CHECK-NEXT: ret + %a = add <vscale x 1 x i64> %0, %2 + ret <vscale x 1 x i64> %a +} +define <vscale x 2 x i64> @case2_2(<vscale x 1 x i64> %0, <vscale x 2 x i64> %1, <vscale x 1 x i64> %2) { +; CHECK-LABEL: case2_2: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma +; CHECK-NEXT: vadd.vv v8, v10, v10 +; CHECK-NEXT: ret + %a = add <vscale x 2 x i64> %1, %1 + ret <vscale x 2 x i64> %a +} + +; %0 -> v8 +; %1 -> {v10-v11, v12-v13} +; %2 -> v9 +define <vscale x 1 x i64> @case3_1(<vscale x 1 x i64> %0, {<vscale x 2 x i64>, <vscale x 2 x i64>} %1, <vscale x 1 x i64> %2) { +; CHECK-LABEL: case3_1: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma +; CHECK-NEXT: vadd.vv v8, v8, v9 +; CHECK-NEXT: ret + %add = add <vscale x 1 x i64> %0, %2 + ret <vscale x 1 x i64> %add +} +define <vscale x 2 x i64> @case3_2(<vscale x 1 x i64> %0, {<vscale x 2 x i64>, <vscale x 2 x i64>} %1, <vscale x 1 x i64> %2) { +; CHECK-LABEL: case3_2: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma +; CHECK-NEXT: vadd.vv v8, v10, v12 +; CHECK-NEXT: ret + %a = extractvalue { <vscale x 2 x i64>, <vscale x 2 x i64> } %1, 0 + %b = extractvalue { <vscale x 2 x i64>, <vscale x 2 x i64> } %1, 1 + %add = add <vscale x 2 x i64> %a, %b + ret <vscale x 2 x i64> %add +} + +; %0 -> v8 +; %1 -> {by-ref, by-ref} +; %2 -> v9 +define <vscale x 8 x i64> @case4_1(<vscale x 1 x i64> %0, {<vscale x 8 x i64>, <vscale x 8 x i64>} %1, <vscale x 1 x i64> %2) { +; CHECK-LABEL: case4_1: +; CHECK: # %bb.0: +; CHECK-NEXT: csrr a1, vlenb +; CHECK-NEXT: slli a1, a1, 3 +; CHECK-NEXT: add a1, a0, a1 +; CHECK-NEXT: vl8re64.v v8, (a1) +; CHECK-NEXT: vl8re64.v v16, (a0) +; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma +; CHECK-NEXT: vadd.vv v8, v16, v8 +; CHECK-NEXT: ret + %a = extractvalue { <vscale x 8 x i64>, <vscale x 8 x i64> } %1, 0 + %b = extractvalue { <vscale x 8 x i64>, <vscale x 8 x i64> } %1, 1 + %add = add <vscale x 8 x i64> %a, %b + ret <vscale x 8 x i64> %add +} +define <vscale x 1 x i64> @case4_2(<vscale x 1 x i64> %0, {<vscale x 8 x i64>, <vscale x 8 x i64>} %1, <vscale x 1 x i64> %2) { +; CHECK-LABEL: case4_2: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma +; CHECK-NEXT: vadd.vv v8, v8, v9 +; CHECK-NEXT: ret + %add = add <vscale x 1 x i64> %0, %2 + ret <vscale x 1 x i64> %add +} diff --git a/llvm/test/CodeGen/RISCV/rvv/compressstore.ll b/llvm/test/CodeGen/RISCV/rvv/compressstore.ll new file mode 100644 index 0000000000000000000000000000000000000000..673008d9c0b3d82475ba2d519250c07b85dcea91 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/compressstore.ll @@ -0,0 +1,871 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -verify-machineinstrs -mtriple=riscv64 -mattr=+v,+d,+m,+zbb %s -o - | FileCheck %s --check-prefix=RV64 +; RUN: llc -verify-machineinstrs -mtriple=riscv32 -mattr=+v,+d,+m,+zbb %s -o - | FileCheck %s --check-prefix=RV32 + +; Compress + store for i8 type + +define void @test_compresstore_v1i8(ptr %p, <1 x i1> %mask, <1 x i8> %data) { +; RV64-LABEL: test_compresstore_v1i8: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 1, e8, mf8, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e8, mf8, ta, ma +; RV64-NEXT: vse8.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v1i8: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 1, e8, mf8, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e8, mf8, ta, ma +; RV32-NEXT: vse8.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v1i8(<1 x i8> %data, ptr align 1 %p, <1 x i1> %mask) + ret void +} + +define void @test_compresstore_v2i8(ptr %p, <2 x i1> %mask, <2 x i8> %data) { +; RV64-LABEL: test_compresstore_v2i8: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 2, e8, mf8, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e8, mf8, ta, ma +; RV64-NEXT: vse8.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v2i8: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 2, e8, mf8, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e8, mf8, ta, ma +; RV32-NEXT: vse8.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v2i8(<2 x i8> %data, ptr align 1 %p, <2 x i1> %mask) + ret void +} + +define void @test_compresstore_v4i8(ptr %p, <4 x i1> %mask, <4 x i8> %data) { +; RV64-LABEL: test_compresstore_v4i8: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e8, mf4, ta, ma +; RV64-NEXT: vse8.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v4i8: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e8, mf4, ta, ma +; RV32-NEXT: vse8.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v4i8(<4 x i8> %data, ptr align 1 %p, <4 x i1> %mask) + ret void +} + +define void @test_compresstore_v8i8(ptr %p, <8 x i1> %mask, <8 x i8> %data) { +; RV64-LABEL: test_compresstore_v8i8: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 8, e8, mf2, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e8, mf2, ta, ma +; RV64-NEXT: vse8.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v8i8: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 8, e8, mf2, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e8, mf2, ta, ma +; RV32-NEXT: vse8.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v8i8(<8 x i8> %data, ptr align 1 %p, <8 x i1> %mask) + ret void +} + +define void @test_compresstore_v16i8(ptr %p, <16 x i1> %mask, <16 x i8> %data) { +; RV64-LABEL: test_compresstore_v16i8: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 16, e8, m1, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e8, m1, ta, ma +; RV64-NEXT: vse8.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v16i8: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 16, e8, m1, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e8, m1, ta, ma +; RV32-NEXT: vse8.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v16i8(<16 x i8> %data, ptr align 1 %p, <16 x i1> %mask) + ret void +} + +define void @test_compresstore_v32i8(ptr %p, <32 x i1> %mask, <32 x i8> %data) { +; RV64-LABEL: test_compresstore_v32i8: +; RV64: # %bb.0: # %entry +; RV64-NEXT: li a1, 32 +; RV64-NEXT: vsetvli zero, a1, e8, m2, ta, ma +; RV64-NEXT: vcompress.vm v10, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e8, m2, ta, ma +; RV64-NEXT: vse8.v v10, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v32i8: +; RV32: # %bb.0: # %entry +; RV32-NEXT: li a1, 32 +; RV32-NEXT: vsetvli zero, a1, e8, m2, ta, ma +; RV32-NEXT: vcompress.vm v10, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e8, m2, ta, ma +; RV32-NEXT: vse8.v v10, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v32i8(<32 x i8> %data, ptr align 1 %p, <32 x i1> %mask) + ret void +} + +define void @test_compresstore_v64i8(ptr %p, <64 x i1> %mask, <64 x i8> %data) { +; RV64-LABEL: test_compresstore_v64i8: +; RV64: # %bb.0: # %entry +; RV64-NEXT: li a1, 64 +; RV64-NEXT: vsetvli zero, a1, e8, m4, ta, ma +; RV64-NEXT: vcompress.vm v12, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e8, m4, ta, ma +; RV64-NEXT: vse8.v v12, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v64i8: +; RV32: # %bb.0: # %entry +; RV32-NEXT: li a1, 64 +; RV32-NEXT: vsetvli zero, a1, e8, m4, ta, ma +; RV32-NEXT: vcompress.vm v12, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e8, m4, ta, ma +; RV32-NEXT: vse8.v v12, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v64i8(<64 x i8> %data, ptr align 1 %p, <64 x i1> %mask) + ret void +} + +define void @test_compresstore_v128i8(ptr %p, <128 x i1> %mask, <128 x i8> %data) { +; RV64-LABEL: test_compresstore_v128i8: +; RV64: # %bb.0: # %entry +; RV64-NEXT: li a1, 128 +; RV64-NEXT: vsetvli zero, a1, e8, m8, ta, ma +; RV64-NEXT: vcompress.vm v16, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e8, m8, ta, ma +; RV64-NEXT: vse8.v v16, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v128i8: +; RV32: # %bb.0: # %entry +; RV32-NEXT: li a1, 128 +; RV32-NEXT: vsetvli zero, a1, e8, m8, ta, ma +; RV32-NEXT: vcompress.vm v16, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e8, m8, ta, ma +; RV32-NEXT: vse8.v v16, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v128i8(<128 x i8> %data, ptr align 1 %p, <128 x i1> %mask) + ret void +} + +define void @test_compresstore_v256i8(ptr %p, <256 x i1> %mask, <256 x i8> %data) { +; RV64-LABEL: test_compresstore_v256i8: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vmv1r.v v7, v8 +; RV64-NEXT: li a2, 128 +; RV64-NEXT: vsetvli zero, a2, e8, m8, ta, ma +; RV64-NEXT: vle8.v v24, (a1) +; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma +; RV64-NEXT: vslidedown.vi v9, v0, 1 +; RV64-NEXT: vmv.x.s a1, v9 +; RV64-NEXT: vmv.x.s a3, v0 +; RV64-NEXT: vsetvli zero, a2, e8, m8, ta, ma +; RV64-NEXT: vcompress.vm v8, v16, v0 +; RV64-NEXT: vcpop.m a4, v0 +; RV64-NEXT: vsetvli zero, a4, e8, m8, ta, ma +; RV64-NEXT: vse8.v v8, (a0) +; RV64-NEXT: vsetvli zero, a2, e8, m8, ta, ma +; RV64-NEXT: vcompress.vm v8, v24, v7 +; RV64-NEXT: vcpop.m a2, v7 +; RV64-NEXT: cpop a3, a3 +; RV64-NEXT: cpop a1, a1 +; RV64-NEXT: add a0, a0, a3 +; RV64-NEXT: add a0, a0, a1 +; RV64-NEXT: vsetvli zero, a2, e8, m8, ta, ma +; RV64-NEXT: vse8.v v8, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v256i8: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vmv1r.v v7, v8 +; RV32-NEXT: li a2, 128 +; RV32-NEXT: vsetvli zero, a2, e8, m8, ta, ma +; RV32-NEXT: vle8.v v24, (a1) +; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma +; RV32-NEXT: vslidedown.vi v9, v0, 1 +; RV32-NEXT: li a1, 32 +; RV32-NEXT: vsrl.vx v10, v9, a1 +; RV32-NEXT: vmv.x.s a3, v10 +; RV32-NEXT: vsrl.vx v10, v0, a1 +; RV32-NEXT: vmv.x.s a1, v10 +; RV32-NEXT: vmv.x.s a4, v9 +; RV32-NEXT: vmv.x.s a5, v0 +; RV32-NEXT: vsetvli zero, a2, e8, m8, ta, ma +; RV32-NEXT: vcompress.vm v8, v16, v0 +; RV32-NEXT: vcpop.m a6, v0 +; RV32-NEXT: vsetvli zero, a6, e8, m8, ta, ma +; RV32-NEXT: vse8.v v8, (a0) +; RV32-NEXT: cpop a1, a1 +; RV32-NEXT: cpop a5, a5 +; RV32-NEXT: add a1, a5, a1 +; RV32-NEXT: cpop a3, a3 +; RV32-NEXT: cpop a4, a4 +; RV32-NEXT: add a3, a4, a3 +; RV32-NEXT: add a1, a1, a3 +; RV32-NEXT: add a0, a0, a1 +; RV32-NEXT: vsetvli zero, a2, e8, m8, ta, ma +; RV32-NEXT: vcompress.vm v8, v24, v7 +; RV32-NEXT: vcpop.m a1, v7 +; RV32-NEXT: vsetvli zero, a1, e8, m8, ta, ma +; RV32-NEXT: vse8.v v8, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v256i8(<256 x i8> %data, ptr align 1 %p, <256 x i1> %mask) + ret void +} + +; Compress + store for i16 type + +define void @test_compresstore_v1i16(ptr %p, <1 x i1> %mask, <1 x i16> %data) { +; RV64-LABEL: test_compresstore_v1i16: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 1, e16, mf4, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; RV64-NEXT: vse16.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v1i16: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 1, e16, mf4, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; RV32-NEXT: vse16.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v1i16(<1 x i16> %data, ptr align 2 %p, <1 x i1> %mask) + ret void +} + +define void @test_compresstore_v2i16(ptr %p, <2 x i1> %mask, <2 x i16> %data) { +; RV64-LABEL: test_compresstore_v2i16: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 2, e16, mf4, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; RV64-NEXT: vse16.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v2i16: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 2, e16, mf4, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; RV32-NEXT: vse16.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v2i16(<2 x i16> %data, ptr align 2 %p, <2 x i1> %mask) + ret void +} + +define void @test_compresstore_v4i16(ptr %p, <4 x i1> %mask, <4 x i16> %data) { +; RV64-LABEL: test_compresstore_v4i16: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, mf2, ta, ma +; RV64-NEXT: vse16.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v4i16: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, mf2, ta, ma +; RV32-NEXT: vse16.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v4i16(<4 x i16> %data, ptr align 2 %p, <4 x i1> %mask) + ret void +} + +define void @test_compresstore_v8i16(ptr %p, <8 x i1> %mask, <8 x i16> %data) { +; RV64-LABEL: test_compresstore_v8i16: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, m1, ta, ma +; RV64-NEXT: vse16.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v8i16: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, m1, ta, ma +; RV32-NEXT: vse16.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v8i16(<8 x i16> %data, ptr align 2 %p, <8 x i1> %mask) + ret void +} + +define void @test_compresstore_v16i16(ptr %p, <16 x i1> %mask, <16 x i16> %data) { +; RV64-LABEL: test_compresstore_v16i16: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 16, e16, m2, ta, ma +; RV64-NEXT: vcompress.vm v10, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, m2, ta, ma +; RV64-NEXT: vse16.v v10, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v16i16: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 16, e16, m2, ta, ma +; RV32-NEXT: vcompress.vm v10, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, m2, ta, ma +; RV32-NEXT: vse16.v v10, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v16i16(<16 x i16> %data, ptr align 2 %p, <16 x i1> %mask) + ret void +} + +define void @test_compresstore_v32i16(ptr %p, <32 x i1> %mask, <32 x i16> %data) { +; RV64-LABEL: test_compresstore_v32i16: +; RV64: # %bb.0: # %entry +; RV64-NEXT: li a1, 32 +; RV64-NEXT: vsetvli zero, a1, e16, m4, ta, ma +; RV64-NEXT: vcompress.vm v12, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, m4, ta, ma +; RV64-NEXT: vse16.v v12, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v32i16: +; RV32: # %bb.0: # %entry +; RV32-NEXT: li a1, 32 +; RV32-NEXT: vsetvli zero, a1, e16, m4, ta, ma +; RV32-NEXT: vcompress.vm v12, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, m4, ta, ma +; RV32-NEXT: vse16.v v12, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v32i16(<32 x i16> %data, ptr align 2 %p, <32 x i1> %mask) + ret void +} + +define void @test_compresstore_v64i16(ptr %p, <64 x i1> %mask, <64 x i16> %data) { +; RV64-LABEL: test_compresstore_v64i16: +; RV64: # %bb.0: # %entry +; RV64-NEXT: li a1, 64 +; RV64-NEXT: vsetvli zero, a1, e16, m8, ta, ma +; RV64-NEXT: vcompress.vm v16, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, m8, ta, ma +; RV64-NEXT: vse16.v v16, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v64i16: +; RV32: # %bb.0: # %entry +; RV32-NEXT: li a1, 64 +; RV32-NEXT: vsetvli zero, a1, e16, m8, ta, ma +; RV32-NEXT: vcompress.vm v16, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, m8, ta, ma +; RV32-NEXT: vse16.v v16, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v64i16(<64 x i16> %data, ptr align 2 %p, <64 x i1> %mask) + ret void +} + +define void @test_compresstore_v128i16(ptr %p, <128 x i1> %mask, <128 x i16> %data) { +; RV64-LABEL: test_compresstore_v128i16: +; RV64: # %bb.0: # %entry +; RV64-NEXT: li a1, 64 +; RV64-NEXT: vsetvli zero, a1, e16, m8, ta, ma +; RV64-NEXT: vcompress.vm v24, v8, v0 +; RV64-NEXT: vcpop.m a2, v0 +; RV64-NEXT: vsetvli zero, a2, e16, m8, ta, ma +; RV64-NEXT: vse16.v v24, (a0) +; RV64-NEXT: vsetivli zero, 8, e8, m1, ta, ma +; RV64-NEXT: vslidedown.vi v8, v0, 8 +; RV64-NEXT: vsetvli zero, a1, e16, m8, ta, ma +; RV64-NEXT: vcompress.vm v24, v16, v8 +; RV64-NEXT: vcpop.m a2, v8 +; RV64-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; RV64-NEXT: vmv.x.s a1, v0 +; RV64-NEXT: cpop a1, a1 +; RV64-NEXT: slli a1, a1, 1 +; RV64-NEXT: add a0, a0, a1 +; RV64-NEXT: vsetvli zero, a2, e16, m8, ta, ma +; RV64-NEXT: vse16.v v24, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v128i16: +; RV32: # %bb.0: # %entry +; RV32-NEXT: li a1, 64 +; RV32-NEXT: vsetvli zero, a1, e16, m8, ta, ma +; RV32-NEXT: vcompress.vm v24, v8, v0 +; RV32-NEXT: vcpop.m a2, v0 +; RV32-NEXT: vsetvli zero, a2, e16, m8, ta, ma +; RV32-NEXT: vse16.v v24, (a0) +; RV32-NEXT: vsetivli zero, 8, e8, m1, ta, ma +; RV32-NEXT: vslidedown.vi v24, v0, 8 +; RV32-NEXT: vsetvli zero, a1, e16, m8, ta, ma +; RV32-NEXT: vcompress.vm v8, v16, v24 +; RV32-NEXT: vcpop.m a1, v24 +; RV32-NEXT: li a2, 32 +; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma +; RV32-NEXT: vsrl.vx v16, v0, a2 +; RV32-NEXT: vmv.x.s a2, v16 +; RV32-NEXT: cpop a2, a2 +; RV32-NEXT: vmv.x.s a3, v0 +; RV32-NEXT: cpop a3, a3 +; RV32-NEXT: add a2, a3, a2 +; RV32-NEXT: slli a2, a2, 1 +; RV32-NEXT: add a0, a0, a2 +; RV32-NEXT: vsetvli zero, a1, e16, m8, ta, ma +; RV32-NEXT: vse16.v v8, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v128i16(<128 x i16> %data, ptr align 2 %p, <128 x i1> %mask) + ret void +} + +; Compress + store for i32 type + +define void @test_compresstore_v1i32(ptr %p, <1 x i1> %mask, <1 x i32> %data) { +; RV64-LABEL: test_compresstore_v1i32: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 1, e32, mf2, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; RV64-NEXT: vse32.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v1i32: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 1, e32, mf2, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; RV32-NEXT: vse32.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v1i32(<1 x i32> %data, ptr align 4 %p, <1 x i1> %mask) + ret void +} + +define void @test_compresstore_v2i32(ptr %p, <2 x i1> %mask, <2 x i32> %data) { +; RV64-LABEL: test_compresstore_v2i32: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 2, e32, mf2, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; RV64-NEXT: vse32.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v2i32: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; RV32-NEXT: vse32.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v2i32(<2 x i32> %data, ptr align 4 %p, <2 x i1> %mask) + ret void +} + +define void @test_compresstore_v4i32(ptr %p, <4 x i1> %mask, <4 x i32> %data) { +; RV64-LABEL: test_compresstore_v4i32: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, m1, ta, ma +; RV64-NEXT: vse32.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v4i32: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, m1, ta, ma +; RV32-NEXT: vse32.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v4i32(<4 x i32> %data, ptr align 4 %p, <4 x i1> %mask) + ret void +} + +define void @test_compresstore_v8i32(ptr %p, <8 x i1> %mask, <8 x i32> %data) { +; RV64-LABEL: test_compresstore_v8i32: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; RV64-NEXT: vcompress.vm v10, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, m2, ta, ma +; RV64-NEXT: vse32.v v10, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v8i32: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; RV32-NEXT: vcompress.vm v10, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, m2, ta, ma +; RV32-NEXT: vse32.v v10, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v8i32(<8 x i32> %data, ptr align 4 %p, <8 x i1> %mask) + ret void +} + +define void @test_compresstore_v16i32(ptr %p, <16 x i1> %mask, <16 x i32> %data) { +; RV64-LABEL: test_compresstore_v16i32: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 16, e32, m4, ta, ma +; RV64-NEXT: vcompress.vm v12, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, m4, ta, ma +; RV64-NEXT: vse32.v v12, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v16i32: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 16, e32, m4, ta, ma +; RV32-NEXT: vcompress.vm v12, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, m4, ta, ma +; RV32-NEXT: vse32.v v12, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v16i32(<16 x i32> %data, ptr align 4 %p, <16 x i1> %mask) + ret void +} + +define void @test_compresstore_v32i32(ptr %p, <32 x i1> %mask, <32 x i32> %data) { +; RV64-LABEL: test_compresstore_v32i32: +; RV64: # %bb.0: # %entry +; RV64-NEXT: li a1, 32 +; RV64-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV64-NEXT: vcompress.vm v16, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV64-NEXT: vse32.v v16, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v32i32: +; RV32: # %bb.0: # %entry +; RV32-NEXT: li a1, 32 +; RV32-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV32-NEXT: vcompress.vm v16, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV32-NEXT: vse32.v v16, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v32i32(<32 x i32> %data, ptr align 4 %p, <32 x i1> %mask) + ret void +} + +define void @test_compresstore_v64i32(ptr %p, <64 x i1> %mask, <64 x i32> %data) { +; RV64-LABEL: test_compresstore_v64i32: +; RV64: # %bb.0: # %entry +; RV64-NEXT: li a1, 32 +; RV64-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV64-NEXT: vcompress.vm v24, v8, v0 +; RV64-NEXT: vcpop.m a2, v0 +; RV64-NEXT: vsetvli zero, a2, e32, m8, ta, ma +; RV64-NEXT: vse32.v v24, (a0) +; RV64-NEXT: vsetivli zero, 4, e8, mf2, ta, ma +; RV64-NEXT: vslidedown.vi v8, v0, 4 +; RV64-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV64-NEXT: vcompress.vm v24, v16, v8 +; RV64-NEXT: vcpop.m a1, v8 +; RV64-NEXT: vmv.x.s a2, v0 +; RV64-NEXT: cpopw a2, a2 +; RV64-NEXT: slli a2, a2, 2 +; RV64-NEXT: add a0, a0, a2 +; RV64-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV64-NEXT: vse32.v v24, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v64i32: +; RV32: # %bb.0: # %entry +; RV32-NEXT: li a1, 32 +; RV32-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV32-NEXT: vcompress.vm v24, v8, v0 +; RV32-NEXT: vcpop.m a2, v0 +; RV32-NEXT: vsetvli zero, a2, e32, m8, ta, ma +; RV32-NEXT: vse32.v v24, (a0) +; RV32-NEXT: vsetivli zero, 4, e8, mf2, ta, ma +; RV32-NEXT: vslidedown.vi v8, v0, 4 +; RV32-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV32-NEXT: vcompress.vm v24, v16, v8 +; RV32-NEXT: vcpop.m a1, v8 +; RV32-NEXT: vmv.x.s a2, v0 +; RV32-NEXT: cpop a2, a2 +; RV32-NEXT: slli a2, a2, 2 +; RV32-NEXT: add a0, a0, a2 +; RV32-NEXT: vsetvli zero, a1, e32, m8, ta, ma +; RV32-NEXT: vse32.v v24, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v64i32(<64 x i32> %data, ptr align 4 %p, <64 x i1> %mask) + ret void +} + +; Compress + store for i64 type + +define void @test_compresstore_v1i64(ptr %p, <1 x i1> %mask, <1 x i64> %data) { +; RV64-LABEL: test_compresstore_v1i64: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; RV64-NEXT: vse64.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v1i64: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; RV32-NEXT: vse64.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v1i64(<1 x i64> %data, ptr align 8 %p, <1 x i1> %mask) + ret void +} + +define void @test_compresstore_v2i64(ptr %p, <2 x i1> %mask, <2 x i64> %data) { +; RV64-LABEL: test_compresstore_v2i64: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 2, e64, m1, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; RV64-NEXT: vse64.v v9, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v2i64: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; RV32-NEXT: vse64.v v9, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v2i64(<2 x i64> %data, ptr align 8 %p, <2 x i1> %mask) + ret void +} + +define void @test_compresstore_v4i64(ptr %p, <4 x i1> %mask, <4 x i64> %data) { +; RV64-LABEL: test_compresstore_v4i64: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; RV64-NEXT: vcompress.vm v10, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m2, ta, ma +; RV64-NEXT: vse64.v v10, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v4i64: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; RV32-NEXT: vcompress.vm v10, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m2, ta, ma +; RV32-NEXT: vse64.v v10, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v4i64(<4 x i64> %data, ptr align 8 %p, <4 x i1> %mask) + ret void +} + +define void @test_compresstore_v8i64(ptr %p, <8 x i1> %mask, <8 x i64> %data) { +; RV64-LABEL: test_compresstore_v8i64: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 8, e64, m4, ta, ma +; RV64-NEXT: vcompress.vm v12, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m4, ta, ma +; RV64-NEXT: vse64.v v12, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v8i64: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 8, e64, m4, ta, ma +; RV32-NEXT: vcompress.vm v12, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m4, ta, ma +; RV32-NEXT: vse64.v v12, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v8i64(<8 x i64> %data, ptr align 8 %p, <8 x i1> %mask) + ret void +} + +define void @test_compresstore_v16i64(ptr %p, <16 x i1> %mask, <16 x i64> %data) { +; RV64-LABEL: test_compresstore_v16i64: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 16, e64, m8, ta, ma +; RV64-NEXT: vcompress.vm v16, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m8, ta, ma +; RV64-NEXT: vse64.v v16, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v16i64: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 16, e64, m8, ta, ma +; RV32-NEXT: vcompress.vm v16, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m8, ta, ma +; RV32-NEXT: vse64.v v16, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v16i64(<16 x i64> %data, ptr align 8 %p, <16 x i1> %mask) + ret void +} + +define void @test_compresstore_v32i64(ptr %p, <32 x i1> %mask, <32 x i64> %data) { +; RV64-LABEL: test_compresstore_v32i64: +; RV64: # %bb.0: # %entry +; RV64-NEXT: vsetivli zero, 16, e64, m8, ta, ma +; RV64-NEXT: vcompress.vm v24, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m8, ta, ma +; RV64-NEXT: vse64.v v24, (a0) +; RV64-NEXT: vsetivli zero, 2, e8, mf4, ta, ma +; RV64-NEXT: vslidedown.vi v24, v0, 2 +; RV64-NEXT: vsetivli zero, 16, e64, m8, ta, ma +; RV64-NEXT: vcompress.vm v8, v16, v24 +; RV64-NEXT: vsetvli zero, zero, e16, m2, ta, ma +; RV64-NEXT: vmv.x.s a1, v0 +; RV64-NEXT: zext.h a1, a1 +; RV64-NEXT: cpopw a1, a1 +; RV64-NEXT: slli a1, a1, 3 +; RV64-NEXT: add a0, a0, a1 +; RV64-NEXT: vcpop.m a1, v24 +; RV64-NEXT: vsetvli zero, a1, e64, m8, ta, ma +; RV64-NEXT: vse64.v v8, (a0) +; RV64-NEXT: ret +; +; RV32-LABEL: test_compresstore_v32i64: +; RV32: # %bb.0: # %entry +; RV32-NEXT: vsetivli zero, 16, e64, m8, ta, ma +; RV32-NEXT: vcompress.vm v24, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m8, ta, ma +; RV32-NEXT: vse64.v v24, (a0) +; RV32-NEXT: vsetivli zero, 2, e8, mf4, ta, ma +; RV32-NEXT: vslidedown.vi v24, v0, 2 +; RV32-NEXT: vsetivli zero, 16, e64, m8, ta, ma +; RV32-NEXT: vcompress.vm v8, v16, v24 +; RV32-NEXT: vsetvli zero, zero, e16, m2, ta, ma +; RV32-NEXT: vmv.x.s a1, v0 +; RV32-NEXT: zext.h a1, a1 +; RV32-NEXT: cpop a1, a1 +; RV32-NEXT: slli a1, a1, 3 +; RV32-NEXT: add a0, a0, a1 +; RV32-NEXT: vcpop.m a1, v24 +; RV32-NEXT: vsetvli zero, a1, e64, m8, ta, ma +; RV32-NEXT: vse64.v v8, (a0) +; RV32-NEXT: ret +entry: + tail call void @llvm.masked.compressstore.v32i64(<32 x i64> %data, ptr align 8 %p, <32 x i1> %mask) + ret void +} + +declare void @llvm.masked.compressstore.v1i8(<1 x i8>, ptr, <1 x i1>) +declare void @llvm.masked.compressstore.v2i8(<2 x i8>, ptr, <2 x i1>) +declare void @llvm.masked.compressstore.v4i8(<4 x i8>, ptr, <4 x i1>) +declare void @llvm.masked.compressstore.v8i8(<8 x i8>, ptr, <8 x i1>) +declare void @llvm.masked.compressstore.v16i8(<16 x i8>, ptr, <16 x i1>) +declare void @llvm.masked.compressstore.v32i8(<32 x i8>, ptr, <32 x i1>) +declare void @llvm.masked.compressstore.v64i8(<64 x i8>, ptr, <64 x i1>) +declare void @llvm.masked.compressstore.v128i8(<128 x i8>, ptr, <128 x i1>) +declare void @llvm.masked.compressstore.v256i8(<256 x i8>, ptr, <256 x i1>) + +declare void @llvm.masked.compressstore.v1i16(<1 x i16>, ptr, <1 x i1>) +declare void @llvm.masked.compressstore.v2i16(<2 x i16>, ptr, <2 x i1>) +declare void @llvm.masked.compressstore.v4i16(<4 x i16>, ptr, <4 x i1>) +declare void @llvm.masked.compressstore.v8i16(<8 x i16>, ptr, <8 x i1>) +declare void @llvm.masked.compressstore.v16i16(<16 x i16>, ptr, <16 x i1>) +declare void @llvm.masked.compressstore.v32i16(<32 x i16>, ptr, <32 x i1>) +declare void @llvm.masked.compressstore.v64i16(<64 x i16>, ptr, <64 x i1>) +declare void @llvm.masked.compressstore.v128i16(<128 x i16>, ptr, <128 x i1>) + +declare void @llvm.masked.compressstore.v1i32(<1 x i32>, ptr, <1 x i1>) +declare void @llvm.masked.compressstore.v2i32(<2 x i32>, ptr, <2 x i1>) +declare void @llvm.masked.compressstore.v4i32(<4 x i32>, ptr, <4 x i1>) +declare void @llvm.masked.compressstore.v8i32(<8 x i32>, ptr, <8 x i1>) +declare void @llvm.masked.compressstore.v16i32(<16 x i32>, ptr, <16 x i1>) +declare void @llvm.masked.compressstore.v32i32(<32 x i32>, ptr, <32 x i1>) +declare void @llvm.masked.compressstore.v64i32(<64 x i32>, ptr, <64 x i1>) + +declare void @llvm.masked.compressstore.v1i64(<1 x i64>, ptr, <1 x i1>) +declare void @llvm.masked.compressstore.v2i64(<2 x i64>, ptr, <2 x i1>) +declare void @llvm.masked.compressstore.v4i64(<4 x i64>, ptr, <4 x i1>) +declare void @llvm.masked.compressstore.v8i64(<8 x i64>, ptr, <8 x i1>) +declare void @llvm.masked.compressstore.v16i64(<16 x i64>, ptr, <16 x i1>) +declare void @llvm.masked.compressstore.v32i64(<32 x i64>, ptr, <32 x i1>) diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-abd.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-abd.ll new file mode 100644 index 0000000000000000000000000000000000000000..bd1209a17b5345615a24f71238e20059e7f6e193 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-abd.ll @@ -0,0 +1,727 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+v,+d -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK,RV32 +; RUN: llc -mtriple=riscv64 -mattr=+v,+d -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK,RV64 +; +; SABD +; + +define <8 x i8> @sabd_8b_as_16b(<8 x i8> %a, <8 x i8> %b) { +; +; CHECK-LABEL: sabd_8b_as_16b: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a.sext = sext <8 x i8> %a to <8 x i16> + %b.sext = sext <8 x i8> %b to <8 x i16> + %sub = sub <8 x i16> %a.sext, %b.sext + %abs = call <8 x i16> @llvm.abs.v8i16(<8 x i16> %sub, i1 true) + %trunc = trunc <8 x i16> %abs to <8 x i8> + ret <8 x i8> %trunc +} + +define <8 x i8> @sabd_8b_as_32b(<8 x i8> %a, <8 x i8> %b) { +; +; CHECK-LABEL: sabd_8b_as_32b: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a.sext = sext <8 x i8> %a to <8 x i32> + %b.sext = sext <8 x i8> %b to <8 x i32> + %sub = sub <8 x i32> %a.sext, %b.sext + %abs = call <8 x i32> @llvm.abs.v8i32(<8 x i32> %sub, i1 true) + %trunc = trunc <8 x i32> %abs to <8 x i8> + ret <8 x i8> %trunc +} + +define <16 x i8> @sabd_16b(<16 x i8> %a, <16 x i8> %b) { +; +; CHECK-LABEL: sabd_16b: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a.sext = sext <16 x i8> %a to <16 x i16> + %b.sext = sext <16 x i8> %b to <16 x i16> + %sub = sub <16 x i16> %a.sext, %b.sext + %abs = call <16 x i16> @llvm.abs.v16i16(<16 x i16> %sub, i1 true) + %trunc = trunc <16 x i16> %abs to <16 x i8> + ret <16 x i8> %trunc +} + +define <4 x i16> @sabd_4h(<4 x i16> %a, <4 x i16> %b) { +; +; CHECK-LABEL: sabd_4h: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a.sext = sext <4 x i16> %a to <4 x i32> + %b.sext = sext <4 x i16> %b to <4 x i32> + %sub = sub <4 x i32> %a.sext, %b.sext + %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %sub, i1 true) + %trunc = trunc <4 x i32> %abs to <4 x i16> + ret <4 x i16> %trunc +} + +define <4 x i16> @sabd_4h_promoted_ops(<4 x i8> %a, <4 x i8> %b) { +; +; CHECK-LABEL: sabd_4h_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v9, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e16, mf2, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v9 +; CHECK-NEXT: ret + %a.sext = sext <4 x i8> %a to <4 x i16> + %b.sext = sext <4 x i8> %b to <4 x i16> + %sub = sub <4 x i16> %a.sext, %b.sext + %abs = call <4 x i16> @llvm.abs.v4i16(<4 x i16> %sub, i1 true) + ret <4 x i16> %abs +} + +define <8 x i16> @sabd_8h(<8 x i16> %a, <8 x i16> %b) { +; +; CHECK-LABEL: sabd_8h: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a.sext = sext <8 x i16> %a to <8 x i32> + %b.sext = sext <8 x i16> %b to <8 x i32> + %sub = sub <8 x i32> %a.sext, %b.sext + %abs = call <8 x i32> @llvm.abs.v8i32(<8 x i32> %sub, i1 true) + %trunc = trunc <8 x i32> %abs to <8 x i16> + ret <8 x i16> %trunc +} + +define <8 x i16> @sabd_8h_promoted_ops(<8 x i8> %a, <8 x i8> %b) { +; +; CHECK-LABEL: sabd_8h_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v9, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e16, m1, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v9 +; CHECK-NEXT: ret + %a.sext = sext <8 x i8> %a to <8 x i16> + %b.sext = sext <8 x i8> %b to <8 x i16> + %sub = sub <8 x i16> %a.sext, %b.sext + %abs = call <8 x i16> @llvm.abs.v8i16(<8 x i16> %sub, i1 true) + ret <8 x i16> %abs +} + +define <2 x i32> @sabd_2s(<2 x i32> %a, <2 x i32> %b) { +; +; CHECK-LABEL: sabd_2s: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a.sext = sext <2 x i32> %a to <2 x i64> + %b.sext = sext <2 x i32> %b to <2 x i64> + %sub = sub <2 x i64> %a.sext, %b.sext + %abs = call <2 x i64> @llvm.abs.v2i64(<2 x i64> %sub, i1 true) + %trunc = trunc <2 x i64> %abs to <2 x i32> + ret <2 x i32> %trunc +} + +define <2 x i32> @sabd_2s_promoted_ops(<2 x i16> %a, <2 x i16> %b) { +; +; CHECK-LABEL: sabd_2s_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 2, e16, mf4, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v9, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v9 +; CHECK-NEXT: ret + %a.sext = sext <2 x i16> %a to <2 x i32> + %b.sext = sext <2 x i16> %b to <2 x i32> + %sub = sub <2 x i32> %a.sext, %b.sext + %abs = call <2 x i32> @llvm.abs.v2i32(<2 x i32> %sub, i1 true) + ret <2 x i32> %abs +} + +define <4 x i32> @sabd_4s(<4 x i32> %a, <4 x i32> %b) { +; +; CHECK-LABEL: sabd_4s: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a.sext = sext <4 x i32> %a to <4 x i64> + %b.sext = sext <4 x i32> %b to <4 x i64> + %sub = sub <4 x i64> %a.sext, %b.sext + %abs = call <4 x i64> @llvm.abs.v4i64(<4 x i64> %sub, i1 true) + %trunc = trunc <4 x i64> %abs to <4 x i32> + ret <4 x i32> %trunc +} + +define <4 x i32> @sabd_4s_promoted_ops(<4 x i16> %a, <4 x i16> %b) { +; +; CHECK-LABEL: sabd_4s_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v9, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v9 +; CHECK-NEXT: ret + %a.sext = sext <4 x i16> %a to <4 x i32> + %b.sext = sext <4 x i16> %b to <4 x i32> + %sub = sub <4 x i32> %a.sext, %b.sext + %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %sub, i1 true) + ret <4 x i32> %abs +} + +define <2 x i64> @sabd_2d(<2 x i64> %a, <2 x i64> %b) { +; CHECK-LABEL: sabd_2d: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a.sext = sext <2 x i64> %a to <2 x i128> + %b.sext = sext <2 x i64> %b to <2 x i128> + %sub = sub <2 x i128> %a.sext, %b.sext + %abs = call <2 x i128> @llvm.abs.v2i128(<2 x i128> %sub, i1 true) + %trunc = trunc <2 x i128> %abs to <2 x i64> + ret <2 x i64> %trunc +} + +define <2 x i64> @sabd_2d_promoted_ops(<2 x i32> %a, <2 x i32> %b) { +; +; CHECK-LABEL: sabd_2d_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v9, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v9 +; CHECK-NEXT: ret + %a.sext = sext <2 x i32> %a to <2 x i64> + %b.sext = sext <2 x i32> %b to <2 x i64> + %sub = sub <2 x i64> %a.sext, %b.sext + %abs = call <2 x i64> @llvm.abs.v2i64(<2 x i64> %sub, i1 true) + ret <2 x i64> %abs +} + +; +; UABD +; + +define <8 x i8> @uabd_8b(<8 x i8> %a, <8 x i8> %b) { +; +; CHECK-LABEL: uabd_8b: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a.zext = zext <8 x i8> %a to <8 x i16> + %b.zext = zext <8 x i8> %b to <8 x i16> + %sub = sub <8 x i16> %a.zext, %b.zext + %abs = call <8 x i16> @llvm.abs.v8i16(<8 x i16> %sub, i1 true) + %trunc = trunc <8 x i16> %abs to <8 x i8> + ret <8 x i8> %trunc +} + +define <16 x i8> @uabd_16b(<16 x i8> %a, <16 x i8> %b) { +; +; CHECK-LABEL: uabd_16b: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a.zext = zext <16 x i8> %a to <16 x i16> + %b.zext = zext <16 x i8> %b to <16 x i16> + %sub = sub <16 x i16> %a.zext, %b.zext + %abs = call <16 x i16> @llvm.abs.v16i16(<16 x i16> %sub, i1 true) + %trunc = trunc <16 x i16> %abs to <16 x i8> + ret <16 x i8> %trunc +} + +define <4 x i16> @uabd_4h(<4 x i16> %a, <4 x i16> %b) { +; +; CHECK-LABEL: uabd_4h: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a.zext = zext <4 x i16> %a to <4 x i32> + %b.zext = zext <4 x i16> %b to <4 x i32> + %sub = sub <4 x i32> %a.zext, %b.zext + %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %sub, i1 true) + %trunc = trunc <4 x i32> %abs to <4 x i16> + ret <4 x i16> %trunc +} + +define <4 x i16> @uabd_4h_promoted_ops(<4 x i8> %a, <4 x i8> %b) { +; +; CHECK-LABEL: uabd_4h_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v9, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e16, mf2, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v9 +; CHECK-NEXT: ret + %a.zext = zext <4 x i8> %a to <4 x i16> + %b.zext = zext <4 x i8> %b to <4 x i16> + %sub = sub <4 x i16> %a.zext, %b.zext + %abs = call <4 x i16> @llvm.abs.v4i16(<4 x i16> %sub, i1 true) + ret <4 x i16> %abs +} + +define <8 x i16> @uabd_8h(<8 x i16> %a, <8 x i16> %b) { +; +; CHECK-LABEL: uabd_8h: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a.zext = zext <8 x i16> %a to <8 x i32> + %b.zext = zext <8 x i16> %b to <8 x i32> + %sub = sub <8 x i32> %a.zext, %b.zext + %abs = call <8 x i32> @llvm.abs.v8i32(<8 x i32> %sub, i1 true) + %trunc = trunc <8 x i32> %abs to <8 x i16> + ret <8 x i16> %trunc +} + +define <8 x i16> @uabd_8h_promoted_ops(<8 x i8> %a, <8 x i8> %b) { +; +; CHECK-LABEL: uabd_8h_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v9, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e16, m1, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v9 +; CHECK-NEXT: ret + %a.zext = zext <8 x i8> %a to <8 x i16> + %b.zext = zext <8 x i8> %b to <8 x i16> + %sub = sub <8 x i16> %a.zext, %b.zext + %abs = call <8 x i16> @llvm.abs.v8i16(<8 x i16> %sub, i1 true) + ret <8 x i16> %abs +} + +define <2 x i32> @uabd_2s(<2 x i32> %a, <2 x i32> %b) { +; +; CHECK-LABEL: uabd_2s: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a.zext = zext <2 x i32> %a to <2 x i64> + %b.zext = zext <2 x i32> %b to <2 x i64> + %sub = sub <2 x i64> %a.zext, %b.zext + %abs = call <2 x i64> @llvm.abs.v2i64(<2 x i64> %sub, i1 true) + %trunc = trunc <2 x i64> %abs to <2 x i32> + ret <2 x i32> %trunc +} + +define <2 x i32> @uabd_2s_promoted_ops(<2 x i16> %a, <2 x i16> %b) { +; +; CHECK-LABEL: uabd_2s_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 2, e16, mf4, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v9, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v9 +; CHECK-NEXT: ret + %a.zext = zext <2 x i16> %a to <2 x i32> + %b.zext = zext <2 x i16> %b to <2 x i32> + %sub = sub <2 x i32> %a.zext, %b.zext + %abs = call <2 x i32> @llvm.abs.v2i32(<2 x i32> %sub, i1 true) + ret <2 x i32> %abs +} + +define <4 x i32> @uabd_4s(<4 x i32> %a, <4 x i32> %b) { +; +; CHECK-LABEL: uabd_4s: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a.zext = zext <4 x i32> %a to <4 x i64> + %b.zext = zext <4 x i32> %b to <4 x i64> + %sub = sub <4 x i64> %a.zext, %b.zext + %abs = call <4 x i64> @llvm.abs.v4i64(<4 x i64> %sub, i1 true) + %trunc = trunc <4 x i64> %abs to <4 x i32> + ret <4 x i32> %trunc +} + +define <4 x i32> @uabd_4s_promoted_ops(<4 x i16> %a, <4 x i16> %b) { +; +; CHECK-LABEL: uabd_4s_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v9, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v9 +; CHECK-NEXT: ret + %a.zext = zext <4 x i16> %a to <4 x i32> + %b.zext = zext <4 x i16> %b to <4 x i32> + %sub = sub <4 x i32> %a.zext, %b.zext + %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %sub, i1 true) + ret <4 x i32> %abs +} + +define <2 x i64> @uabd_2d(<2 x i64> %a, <2 x i64> %b) { +; CHECK-LABEL: uabd_2d: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a.zext = zext <2 x i64> %a to <2 x i128> + %b.zext = zext <2 x i64> %b to <2 x i128> + %sub = sub <2 x i128> %a.zext, %b.zext + %abs = call <2 x i128> @llvm.abs.v2i128(<2 x i128> %sub, i1 true) + %trunc = trunc <2 x i128> %abs to <2 x i64> + ret <2 x i64> %trunc +} + +define <2 x i64> @uabd_2d_promoted_ops(<2 x i32> %a, <2 x i32> %b) { +; +; CHECK-LABEL: uabd_2d_promoted_ops: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v9, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v9 +; CHECK-NEXT: ret + %a.zext = zext <2 x i32> %a to <2 x i64> + %b.zext = zext <2 x i32> %b to <2 x i64> + %sub = sub <2 x i64> %a.zext, %b.zext + %abs = call <2 x i64> @llvm.abs.v2i64(<2 x i64> %sub, i1 true) + ret <2 x i64> %abs +} + +define <16 x i8> @uabd_v16i8_nuw(<16 x i8> %a, <16 x i8> %b) { +; +; CHECK-LABEL: uabd_v16i8_nuw: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma +; CHECK-NEXT: vsub.vv v8, v8, v9 +; CHECK-NEXT: vrsub.vi v9, v8, 0 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: ret + %sub = sub nuw <16 x i8> %a, %b + %abs = call <16 x i8> @llvm.abs.v16i8(<16 x i8> %sub, i1 true) + ret <16 x i8> %abs +} + +define <8 x i16> @uabd_v8i16_nuw(<8 x i16> %a, <8 x i16> %b) { +; +; CHECK-LABEL: uabd_v8i16_nuw: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vsub.vv v8, v8, v9 +; CHECK-NEXT: vrsub.vi v9, v8, 0 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: ret + %sub = sub nuw <8 x i16> %a, %b + %abs = call <8 x i16> @llvm.abs.v8i16(<8 x i16> %sub, i1 true) + ret <8 x i16> %abs +} + +define <4 x i32> @uabd_v4i32_nuw(<4 x i32> %a, <4 x i32> %b) { +; +; CHECK-LABEL: uabd_v4i32_nuw: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-NEXT: vsub.vv v8, v8, v9 +; CHECK-NEXT: vrsub.vi v9, v8, 0 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: ret + %sub = sub nuw <4 x i32> %a, %b + %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %sub, i1 true) + ret <4 x i32> %abs +} + +define <2 x i64> @uabd_v2i64_nuw(<2 x i64> %a, <2 x i64> %b) { +; +; CHECK-LABEL: uabd_v2i64_nuw: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma +; CHECK-NEXT: vsub.vv v8, v8, v9 +; CHECK-NEXT: vrsub.vi v9, v8, 0 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: ret + %sub = sub nuw <2 x i64> %a, %b + %abs = call <2 x i64> @llvm.abs.v2i64(<2 x i64> %sub, i1 true) + ret <2 x i64> %abs +} + +define <16 x i8> @sabd_v16i8_nsw(<16 x i8> %a, <16 x i8> %b) { +; +; CHECK-LABEL: sabd_v16i8_nsw: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %sub = sub nsw <16 x i8> %a, %b + %abs = call <16 x i8> @llvm.abs.v16i8(<16 x i8> %sub, i1 true) + ret <16 x i8> %abs +} + +define <8 x i16> @sabd_v8i16_nsw(<8 x i16> %a, <8 x i16> %b) { +; +; CHECK-LABEL: sabd_v8i16_nsw: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %sub = sub nsw <8 x i16> %a, %b + %abs = call <8 x i16> @llvm.abs.v8i16(<8 x i16> %sub, i1 true) + ret <8 x i16> %abs +} + +define <4 x i32> @sabd_v4i32_nsw(<4 x i32> %a, <4 x i32> %b) { +; +; CHECK-LABEL: sabd_v4i32_nsw: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %sub = sub nsw <4 x i32> %a, %b + %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %sub, i1 true) + ret <4 x i32> %abs +} + +define <2 x i64> @sabd_v2i64_nsw(<2 x i64> %a, <2 x i64> %b) { +; +; CHECK-LABEL: sabd_v2i64_nsw: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %sub = sub nsw <2 x i64> %a, %b + %abs = call <2 x i64> @llvm.abs.v2i64(<2 x i64> %sub, i1 true) + ret <2 x i64> %abs +} + +define <16 x i8> @smaxmin_v16i8(<16 x i8> %0, <16 x i8> %1) { +; +; CHECK-LABEL: smaxmin_v16i8: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a = tail call <16 x i8> @llvm.smax.v16i8(<16 x i8> %0, <16 x i8> %1) + %b = tail call <16 x i8> @llvm.smin.v16i8(<16 x i8> %0, <16 x i8> %1) + %sub = sub <16 x i8> %a, %b + ret <16 x i8> %sub +} + +define <8 x i16> @smaxmin_v8i16(<8 x i16> %0, <8 x i16> %1) { +; +; CHECK-LABEL: smaxmin_v8i16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a = tail call <8 x i16> @llvm.smax.v8i16(<8 x i16> %0, <8 x i16> %1) + %b = tail call <8 x i16> @llvm.smin.v8i16(<8 x i16> %0, <8 x i16> %1) + %sub = sub <8 x i16> %a, %b + ret <8 x i16> %sub +} + +define <4 x i32> @smaxmin_v4i32(<4 x i32> %0, <4 x i32> %1) { +; +; CHECK-LABEL: smaxmin_v4i32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a = tail call <4 x i32> @llvm.smax.v4i32(<4 x i32> %0, <4 x i32> %1) + %b = tail call <4 x i32> @llvm.smin.v4i32(<4 x i32> %0, <4 x i32> %1) + %sub = sub <4 x i32> %a, %b + ret <4 x i32> %sub +} + +define <2 x i64> @smaxmin_v2i64(<2 x i64> %0, <2 x i64> %1) { +; +; CHECK-LABEL: smaxmin_v2i64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma +; CHECK-NEXT: vmin.vv v10, v8, v9 +; CHECK-NEXT: vmax.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a = tail call <2 x i64> @llvm.smax.v2i64(<2 x i64> %0, <2 x i64> %1) + %b = tail call <2 x i64> @llvm.smin.v2i64(<2 x i64> %0, <2 x i64> %1) + %sub = sub <2 x i64> %a, %b + ret <2 x i64> %sub +} + +define <16 x i8> @umaxmin_v16i8(<16 x i8> %0, <16 x i8> %1) { +; +; CHECK-LABEL: umaxmin_v16i8: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a = tail call <16 x i8> @llvm.umax.v16i8(<16 x i8> %0, <16 x i8> %1) + %b = tail call <16 x i8> @llvm.umin.v16i8(<16 x i8> %0, <16 x i8> %1) + %sub = sub <16 x i8> %a, %b + ret <16 x i8> %sub +} + +define <8 x i16> @umaxmin_v8i16(<8 x i16> %0, <8 x i16> %1) { +; +; CHECK-LABEL: umaxmin_v8i16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a = tail call <8 x i16> @llvm.umax.v8i16(<8 x i16> %0, <8 x i16> %1) + %b = tail call <8 x i16> @llvm.umin.v8i16(<8 x i16> %0, <8 x i16> %1) + %sub = sub <8 x i16> %a, %b + ret <8 x i16> %sub +} + +define <4 x i32> @umaxmin_v4i32(<4 x i32> %0, <4 x i32> %1) { +; +; CHECK-LABEL: umaxmin_v4i32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a = tail call <4 x i32> @llvm.umax.v4i32(<4 x i32> %0, <4 x i32> %1) + %b = tail call <4 x i32> @llvm.umin.v4i32(<4 x i32> %0, <4 x i32> %1) + %sub = sub <4 x i32> %a, %b + ret <4 x i32> %sub +} + +define <2 x i64> @umaxmin_v2i64(<2 x i64> %0, <2 x i64> %1) { +; +; CHECK-LABEL: umaxmin_v2i64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a = tail call <2 x i64> @llvm.umax.v2i64(<2 x i64> %0, <2 x i64> %1) + %b = tail call <2 x i64> @llvm.umin.v2i64(<2 x i64> %0, <2 x i64> %1) + %sub = sub <2 x i64> %a, %b + ret <2 x i64> %sub +} + +define <16 x i8> @umaxmin_v16i8_com1(<16 x i8> %0, <16 x i8> %1) { +; +; CHECK-LABEL: umaxmin_v16i8_com1: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: ret + %a = tail call <16 x i8> @llvm.umax.v16i8(<16 x i8> %0, <16 x i8> %1) + %b = tail call <16 x i8> @llvm.umin.v16i8(<16 x i8> %1, <16 x i8> %0) + %sub = sub <16 x i8> %a, %b + ret <16 x i8> %sub +} + +declare <8 x i8> @llvm.abs.v8i8(<8 x i8>, i1) +declare <16 x i8> @llvm.abs.v16i8(<16 x i8>, i1) + +declare <4 x i16> @llvm.abs.v4i16(<4 x i16>, i1) +declare <8 x i16> @llvm.abs.v8i16(<8 x i16>, i1) +declare <16 x i16> @llvm.abs.v16i16(<16 x i16>, i1) + +declare <2 x i32> @llvm.abs.v2i32(<2 x i32>, i1) +declare <4 x i32> @llvm.abs.v4i32(<4 x i32>, i1) +declare <8 x i32> @llvm.abs.v8i32(<8 x i32>, i1) + +declare <2 x i64> @llvm.abs.v2i64(<2 x i64>, i1) +declare <4 x i64> @llvm.abs.v4i64(<4 x i64>, i1) + +declare <2 x i128> @llvm.abs.v2i128(<2 x i128>, i1) + +declare <16 x i8> @llvm.smax.v16i8(<16 x i8>, <16 x i8>) +declare <8 x i16> @llvm.smax.v8i16(<8 x i16>, <8 x i16>) +declare <4 x i32> @llvm.smax.v4i32(<4 x i32>, <4 x i32>) +declare <2 x i64> @llvm.smax.v2i64(<2 x i64>, <2 x i64>) +declare <16 x i8> @llvm.smin.v16i8(<16 x i8>, <16 x i8>) +declare <8 x i16> @llvm.smin.v8i16(<8 x i16>, <8 x i16>) +declare <4 x i32> @llvm.smin.v4i32(<4 x i32>, <4 x i32>) +declare <2 x i64> @llvm.smin.v2i64(<2 x i64>, <2 x i64>) +declare <16 x i8> @llvm.umax.v16i8(<16 x i8>, <16 x i8>) +declare <8 x i16> @llvm.umax.v8i16(<8 x i16>, <8 x i16>) +declare <4 x i32> @llvm.umax.v4i32(<4 x i32>, <4 x i32>) +declare <2 x i64> @llvm.umax.v2i64(<2 x i64>, <2 x i64>) +declare <16 x i8> @llvm.umin.v16i8(<16 x i8>, <16 x i8>) +declare <8 x i16> @llvm.umin.v8i16(<8 x i16>, <8 x i16>) +declare <4 x i32> @llvm.umin.v4i32(<4 x i32>, <4 x i32>) +declare <2 x i64> @llvm.umin.v2i64(<2 x i64>, <2 x i64>) + +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; RV32: {{.*}} +; RV64: {{.*}} diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-bitcast.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-bitcast.ll index b7afee754f68b31449beef92fa27eff696224fed..5252eb71c383dbabd2fcbcdb6e38066332342fb7 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-bitcast.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-bitcast.ll @@ -416,8 +416,8 @@ define double @bitcast_v1i64_f64(<1 x i64> %a) { ; RV32ELEN32: # %bb.0: ; RV32ELEN32-NEXT: addi sp, sp, -16 ; RV32ELEN32-NEXT: .cfi_def_cfa_offset 16 -; RV32ELEN32-NEXT: sw a1, 12(sp) ; RV32ELEN32-NEXT: sw a0, 8(sp) +; RV32ELEN32-NEXT: sw a1, 12(sp) ; RV32ELEN32-NEXT: fld fa0, 8(sp) ; RV32ELEN32-NEXT: addi sp, sp, 16 ; RV32ELEN32-NEXT: ret diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-compressstore-fp.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-compressstore-fp.ll index 52c52921e7e1d280659cc81ed152cbeb8e6aa163..36fbdd8e0664fd9734acd2bbebb80c77080b2790 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-compressstore-fp.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-compressstore-fp.ll @@ -6,24 +6,20 @@ declare void @llvm.masked.compressstore.v1f16(<1 x half>, ptr, <1 x i1>) define void @compressstore_v1f16(ptr %base, <1 x half> %v, <1 x i1> %mask) { ; RV32-LABEL: compressstore_v1f16: ; RV32: # %bb.0: -; RV32-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; RV32-NEXT: vfirst.m a1, v0 -; RV32-NEXT: bnez a1, .LBB0_2 -; RV32-NEXT: # %bb.1: # %cond.store ; RV32-NEXT: vsetivli zero, 1, e16, mf4, ta, ma -; RV32-NEXT: vse16.v v8, (a0) -; RV32-NEXT: .LBB0_2: # %else +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; RV32-NEXT: vse16.v v9, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v1f16: ; RV64: # %bb.0: -; RV64-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; RV64-NEXT: vfirst.m a1, v0 -; RV64-NEXT: bnez a1, .LBB0_2 -; RV64-NEXT: # %bb.1: # %cond.store ; RV64-NEXT: vsetivli zero, 1, e16, mf4, ta, ma -; RV64-NEXT: vse16.v v8, (a0) -; RV64-NEXT: .LBB0_2: # %else +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; RV64-NEXT: vse16.v v9, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v1f16(<1 x half> %v, ptr align 2 %base, <1 x i1> %mask) ret void @@ -33,48 +29,20 @@ declare void @llvm.masked.compressstore.v2f16(<2 x half>, ptr, <2 x i1>) define void @compressstore_v2f16(ptr %base, <2 x half> %v, <2 x i1> %mask) { ; RV32-LABEL: compressstore_v2f16: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB1_3 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a1, a1, 2 -; RV32-NEXT: bnez a1, .LBB1_4 -; RV32-NEXT: .LBB1_2: # %else2 -; RV32-NEXT: ret -; RV32-NEXT: .LBB1_3: # %cond.store -; RV32-NEXT: vsetivli zero, 1, e16, mf4, ta, ma -; RV32-NEXT: vse16.v v8, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a1, a1, 2 -; RV32-NEXT: beqz a1, .LBB1_2 -; RV32-NEXT: .LBB1_4: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e16, mf4, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 1 -; RV32-NEXT: vse16.v v8, (a0) +; RV32-NEXT: vsetivli zero, 2, e16, mf4, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; RV32-NEXT: vse16.v v9, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v2f16: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB1_3 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a1, a1, 2 -; RV64-NEXT: bnez a1, .LBB1_4 -; RV64-NEXT: .LBB1_2: # %else2 -; RV64-NEXT: ret -; RV64-NEXT: .LBB1_3: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e16, mf4, ta, ma -; RV64-NEXT: vse16.v v8, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a1, a1, 2 -; RV64-NEXT: beqz a1, .LBB1_2 -; RV64-NEXT: .LBB1_4: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e16, mf4, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 1 -; RV64-NEXT: vse16.v v8, (a0) +; RV64-NEXT: vsetivli zero, 2, e16, mf4, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; RV64-NEXT: vse16.v v9, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v2f16(<2 x half> %v, ptr align 2 %base, <2 x i1> %mask) ret void @@ -84,88 +52,20 @@ declare void @llvm.masked.compressstore.v4f16(<4 x half>, ptr, <4 x i1>) define void @compressstore_v4f16(ptr %base, <4 x half> %v, <4 x i1> %mask) { ; RV32-LABEL: compressstore_v4f16: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB2_5 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: bnez a2, .LBB2_6 -; RV32-NEXT: .LBB2_2: # %else2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: bnez a2, .LBB2_7 -; RV32-NEXT: .LBB2_3: # %else5 -; RV32-NEXT: andi a1, a1, 8 -; RV32-NEXT: bnez a1, .LBB2_8 -; RV32-NEXT: .LBB2_4: # %else8 -; RV32-NEXT: ret -; RV32-NEXT: .LBB2_5: # %cond.store -; RV32-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; RV32-NEXT: vse16.v v8, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: beqz a2, .LBB2_2 -; RV32-NEXT: .LBB2_6: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 1 -; RV32-NEXT: vse16.v v9, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: beqz a2, .LBB2_3 -; RV32-NEXT: .LBB2_7: # %cond.store4 -; RV32-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 2 +; RV32-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, mf2, ta, ma ; RV32-NEXT: vse16.v v9, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a1, a1, 8 -; RV32-NEXT: beqz a1, .LBB2_4 -; RV32-NEXT: .LBB2_8: # %cond.store7 -; RV32-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 3 -; RV32-NEXT: vse16.v v8, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v4f16: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB2_5 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: bnez a2, .LBB2_6 -; RV64-NEXT: .LBB2_2: # %else2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: bnez a2, .LBB2_7 -; RV64-NEXT: .LBB2_3: # %else5 -; RV64-NEXT: andi a1, a1, 8 -; RV64-NEXT: bnez a1, .LBB2_8 -; RV64-NEXT: .LBB2_4: # %else8 -; RV64-NEXT: ret -; RV64-NEXT: .LBB2_5: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; RV64-NEXT: vse16.v v8, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: beqz a2, .LBB2_2 -; RV64-NEXT: .LBB2_6: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 1 -; RV64-NEXT: vse16.v v9, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: beqz a2, .LBB2_3 -; RV64-NEXT: .LBB2_7: # %cond.store4 -; RV64-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 2 +; RV64-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, mf2, ta, ma ; RV64-NEXT: vse16.v v9, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a1, a1, 8 -; RV64-NEXT: beqz a1, .LBB2_4 -; RV64-NEXT: .LBB2_8: # %cond.store7 -; RV64-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 3 -; RV64-NEXT: vse16.v v8, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v4f16(<4 x half> %v, ptr align 2 %base, <4 x i1> %mask) ret void @@ -175,168 +75,20 @@ declare void @llvm.masked.compressstore.v8f16(<8 x half>, ptr, <8 x i1>) define void @compressstore_v8f16(ptr %base, <8 x half> %v, <8 x i1> %mask) { ; RV32-LABEL: compressstore_v8f16: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB3_9 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: bnez a2, .LBB3_10 -; RV32-NEXT: .LBB3_2: # %else2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: bnez a2, .LBB3_11 -; RV32-NEXT: .LBB3_3: # %else5 -; RV32-NEXT: andi a2, a1, 8 -; RV32-NEXT: bnez a2, .LBB3_12 -; RV32-NEXT: .LBB3_4: # %else8 -; RV32-NEXT: andi a2, a1, 16 -; RV32-NEXT: bnez a2, .LBB3_13 -; RV32-NEXT: .LBB3_5: # %else11 -; RV32-NEXT: andi a2, a1, 32 -; RV32-NEXT: bnez a2, .LBB3_14 -; RV32-NEXT: .LBB3_6: # %else14 -; RV32-NEXT: andi a2, a1, 64 -; RV32-NEXT: bnez a2, .LBB3_15 -; RV32-NEXT: .LBB3_7: # %else17 -; RV32-NEXT: andi a1, a1, -128 -; RV32-NEXT: bnez a1, .LBB3_16 -; RV32-NEXT: .LBB3_8: # %else20 -; RV32-NEXT: ret -; RV32-NEXT: .LBB3_9: # %cond.store -; RV32-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV32-NEXT: vse16.v v8, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: beqz a2, .LBB3_2 -; RV32-NEXT: .LBB3_10: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 1 -; RV32-NEXT: vse16.v v9, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: beqz a2, .LBB3_3 -; RV32-NEXT: .LBB3_11: # %cond.store4 -; RV32-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 2 -; RV32-NEXT: vse16.v v9, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a2, a1, 8 -; RV32-NEXT: beqz a2, .LBB3_4 -; RV32-NEXT: .LBB3_12: # %cond.store7 -; RV32-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 3 -; RV32-NEXT: vse16.v v9, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a2, a1, 16 -; RV32-NEXT: beqz a2, .LBB3_5 -; RV32-NEXT: .LBB3_13: # %cond.store10 -; RV32-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 4 +; RV32-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e16, m1, ta, ma ; RV32-NEXT: vse16.v v9, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a2, a1, 32 -; RV32-NEXT: beqz a2, .LBB3_6 -; RV32-NEXT: .LBB3_14: # %cond.store13 -; RV32-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 5 -; RV32-NEXT: vse16.v v9, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a2, a1, 64 -; RV32-NEXT: beqz a2, .LBB3_7 -; RV32-NEXT: .LBB3_15: # %cond.store16 -; RV32-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 6 -; RV32-NEXT: vse16.v v9, (a0) -; RV32-NEXT: addi a0, a0, 2 -; RV32-NEXT: andi a1, a1, -128 -; RV32-NEXT: beqz a1, .LBB3_8 -; RV32-NEXT: .LBB3_16: # %cond.store19 -; RV32-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 7 -; RV32-NEXT: vse16.v v8, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v8f16: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB3_9 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: bnez a2, .LBB3_10 -; RV64-NEXT: .LBB3_2: # %else2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: bnez a2, .LBB3_11 -; RV64-NEXT: .LBB3_3: # %else5 -; RV64-NEXT: andi a2, a1, 8 -; RV64-NEXT: bnez a2, .LBB3_12 -; RV64-NEXT: .LBB3_4: # %else8 -; RV64-NEXT: andi a2, a1, 16 -; RV64-NEXT: bnez a2, .LBB3_13 -; RV64-NEXT: .LBB3_5: # %else11 -; RV64-NEXT: andi a2, a1, 32 -; RV64-NEXT: bnez a2, .LBB3_14 -; RV64-NEXT: .LBB3_6: # %else14 -; RV64-NEXT: andi a2, a1, 64 -; RV64-NEXT: bnez a2, .LBB3_15 -; RV64-NEXT: .LBB3_7: # %else17 -; RV64-NEXT: andi a1, a1, -128 -; RV64-NEXT: bnez a1, .LBB3_16 -; RV64-NEXT: .LBB3_8: # %else20 -; RV64-NEXT: ret -; RV64-NEXT: .LBB3_9: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV64-NEXT: vse16.v v8, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: beqz a2, .LBB3_2 -; RV64-NEXT: .LBB3_10: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 1 -; RV64-NEXT: vse16.v v9, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: beqz a2, .LBB3_3 -; RV64-NEXT: .LBB3_11: # %cond.store4 -; RV64-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 2 -; RV64-NEXT: vse16.v v9, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a2, a1, 8 -; RV64-NEXT: beqz a2, .LBB3_4 -; RV64-NEXT: .LBB3_12: # %cond.store7 -; RV64-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 3 +; RV64-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e16, m1, ta, ma ; RV64-NEXT: vse16.v v9, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a2, a1, 16 -; RV64-NEXT: beqz a2, .LBB3_5 -; RV64-NEXT: .LBB3_13: # %cond.store10 -; RV64-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 4 -; RV64-NEXT: vse16.v v9, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a2, a1, 32 -; RV64-NEXT: beqz a2, .LBB3_6 -; RV64-NEXT: .LBB3_14: # %cond.store13 -; RV64-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 5 -; RV64-NEXT: vse16.v v9, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a2, a1, 64 -; RV64-NEXT: beqz a2, .LBB3_7 -; RV64-NEXT: .LBB3_15: # %cond.store16 -; RV64-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 6 -; RV64-NEXT: vse16.v v9, (a0) -; RV64-NEXT: addi a0, a0, 2 -; RV64-NEXT: andi a1, a1, -128 -; RV64-NEXT: beqz a1, .LBB3_8 -; RV64-NEXT: .LBB3_16: # %cond.store19 -; RV64-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 7 -; RV64-NEXT: vse16.v v8, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v8f16(<8 x half> %v, ptr align 2 %base, <8 x i1> %mask) ret void @@ -346,24 +98,20 @@ declare void @llvm.masked.compressstore.v1f32(<1 x float>, ptr, <1 x i1>) define void @compressstore_v1f32(ptr %base, <1 x float> %v, <1 x i1> %mask) { ; RV32-LABEL: compressstore_v1f32: ; RV32: # %bb.0: -; RV32-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; RV32-NEXT: vfirst.m a1, v0 -; RV32-NEXT: bnez a1, .LBB4_2 -; RV32-NEXT: # %bb.1: # %cond.store ; RV32-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; RV32-NEXT: vse32.v v8, (a0) -; RV32-NEXT: .LBB4_2: # %else +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; RV32-NEXT: vse32.v v9, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v1f32: ; RV64: # %bb.0: -; RV64-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; RV64-NEXT: vfirst.m a1, v0 -; RV64-NEXT: bnez a1, .LBB4_2 -; RV64-NEXT: # %bb.1: # %cond.store ; RV64-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; RV64-NEXT: vse32.v v8, (a0) -; RV64-NEXT: .LBB4_2: # %else +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; RV64-NEXT: vse32.v v9, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v1f32(<1 x float> %v, ptr align 4 %base, <1 x i1> %mask) ret void @@ -373,48 +121,20 @@ declare void @llvm.masked.compressstore.v2f32(<2 x float>, ptr, <2 x i1>) define void @compressstore_v2f32(ptr %base, <2 x float> %v, <2 x i1> %mask) { ; RV32-LABEL: compressstore_v2f32: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB5_3 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a1, a1, 2 -; RV32-NEXT: bnez a1, .LBB5_4 -; RV32-NEXT: .LBB5_2: # %else2 -; RV32-NEXT: ret -; RV32-NEXT: .LBB5_3: # %cond.store -; RV32-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; RV32-NEXT: vse32.v v8, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a1, a1, 2 -; RV32-NEXT: beqz a1, .LBB5_2 -; RV32-NEXT: .LBB5_4: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 1 -; RV32-NEXT: vse32.v v8, (a0) +; RV32-NEXT: vsetivli zero, 2, e32, mf2, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; RV32-NEXT: vse32.v v9, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v2f32: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB5_3 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a1, a1, 2 -; RV64-NEXT: bnez a1, .LBB5_4 -; RV64-NEXT: .LBB5_2: # %else2 -; RV64-NEXT: ret -; RV64-NEXT: .LBB5_3: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; RV64-NEXT: vse32.v v8, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a1, a1, 2 -; RV64-NEXT: beqz a1, .LBB5_2 -; RV64-NEXT: .LBB5_4: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 1 -; RV64-NEXT: vse32.v v8, (a0) +; RV64-NEXT: vsetivli zero, 2, e32, mf2, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; RV64-NEXT: vse32.v v9, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v2f32(<2 x float> %v, ptr align 4 %base, <2 x i1> %mask) ret void @@ -424,88 +144,20 @@ declare void @llvm.masked.compressstore.v4f32(<4 x float>, ptr, <4 x i1>) define void @compressstore_v4f32(ptr %base, <4 x float> %v, <4 x i1> %mask) { ; RV32-LABEL: compressstore_v4f32: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB6_5 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: bnez a2, .LBB6_6 -; RV32-NEXT: .LBB6_2: # %else2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: bnez a2, .LBB6_7 -; RV32-NEXT: .LBB6_3: # %else5 -; RV32-NEXT: andi a1, a1, 8 -; RV32-NEXT: bnez a1, .LBB6_8 -; RV32-NEXT: .LBB6_4: # %else8 -; RV32-NEXT: ret -; RV32-NEXT: .LBB6_5: # %cond.store -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vse32.v v8, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: beqz a2, .LBB6_2 -; RV32-NEXT: .LBB6_6: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 1 -; RV32-NEXT: vse32.v v9, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: beqz a2, .LBB6_3 -; RV32-NEXT: .LBB6_7: # %cond.store4 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vslidedown.vi v9, v8, 2 +; RV32-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, m1, ta, ma ; RV32-NEXT: vse32.v v9, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a1, a1, 8 -; RV32-NEXT: beqz a1, .LBB6_4 -; RV32-NEXT: .LBB6_8: # %cond.store7 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 3 -; RV32-NEXT: vse32.v v8, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v4f32: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB6_5 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: bnez a2, .LBB6_6 -; RV64-NEXT: .LBB6_2: # %else2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: bnez a2, .LBB6_7 -; RV64-NEXT: .LBB6_3: # %else5 -; RV64-NEXT: andi a1, a1, 8 -; RV64-NEXT: bnez a1, .LBB6_8 -; RV64-NEXT: .LBB6_4: # %else8 -; RV64-NEXT: ret -; RV64-NEXT: .LBB6_5: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vse32.v v8, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: beqz a2, .LBB6_2 -; RV64-NEXT: .LBB6_6: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 1 -; RV64-NEXT: vse32.v v9, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: beqz a2, .LBB6_3 -; RV64-NEXT: .LBB6_7: # %cond.store4 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vslidedown.vi v9, v8, 2 +; RV64-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, m1, ta, ma ; RV64-NEXT: vse32.v v9, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a1, a1, 8 -; RV64-NEXT: beqz a1, .LBB6_4 -; RV64-NEXT: .LBB6_8: # %cond.store7 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 3 -; RV64-NEXT: vse32.v v8, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v4f32(<4 x float> %v, ptr align 4 %base, <4 x i1> %mask) ret void @@ -515,176 +167,20 @@ declare void @llvm.masked.compressstore.v8f32(<8 x float>, ptr, <8 x i1>) define void @compressstore_v8f32(ptr %base, <8 x float> %v, <8 x i1> %mask) { ; RV32-LABEL: compressstore_v8f32: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB7_9 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: bnez a2, .LBB7_10 -; RV32-NEXT: .LBB7_2: # %else2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: bnez a2, .LBB7_11 -; RV32-NEXT: .LBB7_3: # %else5 -; RV32-NEXT: andi a2, a1, 8 -; RV32-NEXT: bnez a2, .LBB7_12 -; RV32-NEXT: .LBB7_4: # %else8 -; RV32-NEXT: andi a2, a1, 16 -; RV32-NEXT: bnez a2, .LBB7_13 -; RV32-NEXT: .LBB7_5: # %else11 -; RV32-NEXT: andi a2, a1, 32 -; RV32-NEXT: bnez a2, .LBB7_14 -; RV32-NEXT: .LBB7_6: # %else14 -; RV32-NEXT: andi a2, a1, 64 -; RV32-NEXT: bnez a2, .LBB7_15 -; RV32-NEXT: .LBB7_7: # %else17 -; RV32-NEXT: andi a1, a1, -128 -; RV32-NEXT: bnez a1, .LBB7_16 -; RV32-NEXT: .LBB7_8: # %else20 -; RV32-NEXT: ret -; RV32-NEXT: .LBB7_9: # %cond.store -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vse32.v v8, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: beqz a2, .LBB7_2 -; RV32-NEXT: .LBB7_10: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 1 -; RV32-NEXT: vse32.v v10, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: beqz a2, .LBB7_3 -; RV32-NEXT: .LBB7_11: # %cond.store4 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 2 -; RV32-NEXT: vse32.v v10, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a2, a1, 8 -; RV32-NEXT: beqz a2, .LBB7_4 -; RV32-NEXT: .LBB7_12: # %cond.store7 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 3 -; RV32-NEXT: vse32.v v10, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a2, a1, 16 -; RV32-NEXT: beqz a2, .LBB7_5 -; RV32-NEXT: .LBB7_13: # %cond.store10 -; RV32-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 4 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vse32.v v10, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a2, a1, 32 -; RV32-NEXT: beqz a2, .LBB7_6 -; RV32-NEXT: .LBB7_14: # %cond.store13 -; RV32-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 5 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vse32.v v10, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a2, a1, 64 -; RV32-NEXT: beqz a2, .LBB7_7 -; RV32-NEXT: .LBB7_15: # %cond.store16 -; RV32-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 6 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma +; RV32-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; RV32-NEXT: vcompress.vm v10, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e32, m2, ta, ma ; RV32-NEXT: vse32.v v10, (a0) -; RV32-NEXT: addi a0, a0, 4 -; RV32-NEXT: andi a1, a1, -128 -; RV32-NEXT: beqz a1, .LBB7_8 -; RV32-NEXT: .LBB7_16: # %cond.store19 -; RV32-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 7 -; RV32-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV32-NEXT: vse32.v v8, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v8f32: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB7_9 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: bnez a2, .LBB7_10 -; RV64-NEXT: .LBB7_2: # %else2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: bnez a2, .LBB7_11 -; RV64-NEXT: .LBB7_3: # %else5 -; RV64-NEXT: andi a2, a1, 8 -; RV64-NEXT: bnez a2, .LBB7_12 -; RV64-NEXT: .LBB7_4: # %else8 -; RV64-NEXT: andi a2, a1, 16 -; RV64-NEXT: bnez a2, .LBB7_13 -; RV64-NEXT: .LBB7_5: # %else11 -; RV64-NEXT: andi a2, a1, 32 -; RV64-NEXT: bnez a2, .LBB7_14 -; RV64-NEXT: .LBB7_6: # %else14 -; RV64-NEXT: andi a2, a1, 64 -; RV64-NEXT: bnez a2, .LBB7_15 -; RV64-NEXT: .LBB7_7: # %else17 -; RV64-NEXT: andi a1, a1, -128 -; RV64-NEXT: bnez a1, .LBB7_16 -; RV64-NEXT: .LBB7_8: # %else20 -; RV64-NEXT: ret -; RV64-NEXT: .LBB7_9: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vse32.v v8, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: beqz a2, .LBB7_2 -; RV64-NEXT: .LBB7_10: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 1 -; RV64-NEXT: vse32.v v10, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: beqz a2, .LBB7_3 -; RV64-NEXT: .LBB7_11: # %cond.store4 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 2 -; RV64-NEXT: vse32.v v10, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a2, a1, 8 -; RV64-NEXT: beqz a2, .LBB7_4 -; RV64-NEXT: .LBB7_12: # %cond.store7 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 3 -; RV64-NEXT: vse32.v v10, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a2, a1, 16 -; RV64-NEXT: beqz a2, .LBB7_5 -; RV64-NEXT: .LBB7_13: # %cond.store10 -; RV64-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 4 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vse32.v v10, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a2, a1, 32 -; RV64-NEXT: beqz a2, .LBB7_6 -; RV64-NEXT: .LBB7_14: # %cond.store13 -; RV64-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 5 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vse32.v v10, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a2, a1, 64 -; RV64-NEXT: beqz a2, .LBB7_7 -; RV64-NEXT: .LBB7_15: # %cond.store16 -; RV64-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 6 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma +; RV64-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; RV64-NEXT: vcompress.vm v10, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e32, m2, ta, ma ; RV64-NEXT: vse32.v v10, (a0) -; RV64-NEXT: addi a0, a0, 4 -; RV64-NEXT: andi a1, a1, -128 -; RV64-NEXT: beqz a1, .LBB7_8 -; RV64-NEXT: .LBB7_16: # %cond.store19 -; RV64-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 7 -; RV64-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; RV64-NEXT: vse32.v v8, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v8f32(<8 x float> %v, ptr align 4 %base, <8 x i1> %mask) ret void @@ -694,24 +190,20 @@ declare void @llvm.masked.compressstore.v1f64(<1 x double>, ptr, <1 x i1>) define void @compressstore_v1f64(ptr %base, <1 x double> %v, <1 x i1> %mask) { ; RV32-LABEL: compressstore_v1f64: ; RV32: # %bb.0: -; RV32-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; RV32-NEXT: vfirst.m a1, v0 -; RV32-NEXT: bnez a1, .LBB8_2 -; RV32-NEXT: # %bb.1: # %cond.store ; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vse64.v v8, (a0) -; RV32-NEXT: .LBB8_2: # %else +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; RV32-NEXT: vse64.v v9, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v1f64: ; RV64: # %bb.0: -; RV64-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; RV64-NEXT: vfirst.m a1, v0 -; RV64-NEXT: bnez a1, .LBB8_2 -; RV64-NEXT: # %bb.1: # %cond.store ; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: .LBB8_2: # %else +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; RV64-NEXT: vse64.v v9, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v1f64(<1 x double> %v, ptr align 8 %base, <1 x i1> %mask) ret void @@ -721,48 +213,20 @@ declare void @llvm.masked.compressstore.v2f64(<2 x double>, ptr, <2 x i1>) define void @compressstore_v2f64(ptr %base, <2 x double> %v, <2 x i1> %mask) { ; RV32-LABEL: compressstore_v2f64: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB9_3 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a1, a1, 2 -; RV32-NEXT: bnez a1, .LBB9_4 -; RV32-NEXT: .LBB9_2: # %else2 -; RV32-NEXT: ret -; RV32-NEXT: .LBB9_3: # %cond.store -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vse64.v v8, (a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a1, a1, 2 -; RV32-NEXT: beqz a1, .LBB9_2 -; RV32-NEXT: .LBB9_4: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 1 -; RV32-NEXT: vse64.v v8, (a0) +; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma +; RV32-NEXT: vcompress.vm v9, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; RV32-NEXT: vse64.v v9, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v2f64: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB9_3 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a1, a1, 2 -; RV64-NEXT: bnez a1, .LBB9_4 -; RV64-NEXT: .LBB9_2: # %else2 -; RV64-NEXT: ret -; RV64-NEXT: .LBB9_3: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a1, a1, 2 -; RV64-NEXT: beqz a1, .LBB9_2 -; RV64-NEXT: .LBB9_4: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 1 -; RV64-NEXT: vse64.v v8, (a0) +; RV64-NEXT: vsetivli zero, 2, e64, m1, ta, ma +; RV64-NEXT: vcompress.vm v9, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; RV64-NEXT: vse64.v v9, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v2f64(<2 x double> %v, ptr align 8 %base, <2 x i1> %mask) ret void @@ -772,92 +236,20 @@ declare void @llvm.masked.compressstore.v4f64(<4 x double>, ptr, <4 x i1>) define void @compressstore_v4f64(ptr %base, <4 x double> %v, <4 x i1> %mask) { ; RV32-LABEL: compressstore_v4f64: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB10_5 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: bnez a2, .LBB10_6 -; RV32-NEXT: .LBB10_2: # %else2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: bnez a2, .LBB10_7 -; RV32-NEXT: .LBB10_3: # %else5 -; RV32-NEXT: andi a1, a1, 8 -; RV32-NEXT: bnez a1, .LBB10_8 -; RV32-NEXT: .LBB10_4: # %else8 -; RV32-NEXT: ret -; RV32-NEXT: .LBB10_5: # %cond.store -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vse64.v v8, (a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: beqz a2, .LBB10_2 -; RV32-NEXT: .LBB10_6: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 1 +; RV32-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; RV32-NEXT: vcompress.vm v10, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m2, ta, ma ; RV32-NEXT: vse64.v v10, (a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: beqz a2, .LBB10_3 -; RV32-NEXT: .LBB10_7: # %cond.store4 -; RV32-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 2 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vse64.v v10, (a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a1, a1, 8 -; RV32-NEXT: beqz a1, .LBB10_4 -; RV32-NEXT: .LBB10_8: # %cond.store7 -; RV32-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 3 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vse64.v v8, (a0) ; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v4f64: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB10_5 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: bnez a2, .LBB10_6 -; RV64-NEXT: .LBB10_2: # %else2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: bnez a2, .LBB10_7 -; RV64-NEXT: .LBB10_3: # %else5 -; RV64-NEXT: andi a1, a1, 8 -; RV64-NEXT: bnez a1, .LBB10_8 -; RV64-NEXT: .LBB10_4: # %else8 -; RV64-NEXT: ret -; RV64-NEXT: .LBB10_5: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: beqz a2, .LBB10_2 -; RV64-NEXT: .LBB10_6: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 1 -; RV64-NEXT: vse64.v v10, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: beqz a2, .LBB10_3 -; RV64-NEXT: .LBB10_7: # %cond.store4 -; RV64-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 2 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma +; RV64-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; RV64-NEXT: vcompress.vm v10, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m2, ta, ma ; RV64-NEXT: vse64.v v10, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a1, a1, 8 -; RV64-NEXT: beqz a1, .LBB10_4 -; RV64-NEXT: .LBB10_8: # %cond.store7 -; RV64-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 3 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) ; RV64-NEXT: ret call void @llvm.masked.compressstore.v4f64(<4 x double> %v, ptr align 8 %base, <4 x i1> %mask) ret void @@ -867,213 +259,21 @@ declare void @llvm.masked.compressstore.v8f64(<8 x double>, ptr, <8 x i1>) define void @compressstore_v8f64(ptr %base, <8 x double> %v, <8 x i1> %mask) { ; RV32-LABEL: compressstore_v8f64: ; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB11_11 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: bnez a2, .LBB11_12 -; RV32-NEXT: .LBB11_2: # %else2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: bnez a2, .LBB11_13 -; RV32-NEXT: .LBB11_3: # %else5 -; RV32-NEXT: andi a2, a1, 8 -; RV32-NEXT: beqz a2, .LBB11_5 -; RV32-NEXT: .LBB11_4: # %cond.store7 -; RV32-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV32-NEXT: vslidedown.vi v12, v8, 3 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vse64.v v12, (a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: .LBB11_5: # %else8 -; RV32-NEXT: addi sp, sp, -320 -; RV32-NEXT: .cfi_def_cfa_offset 320 -; RV32-NEXT: sw ra, 316(sp) # 4-byte Folded Spill -; RV32-NEXT: sw s0, 312(sp) # 4-byte Folded Spill -; RV32-NEXT: .cfi_offset ra, -4 -; RV32-NEXT: .cfi_offset s0, -8 -; RV32-NEXT: addi s0, sp, 320 -; RV32-NEXT: .cfi_def_cfa s0, 0 -; RV32-NEXT: andi sp, sp, -64 -; RV32-NEXT: andi a2, a1, 16 -; RV32-NEXT: bnez a2, .LBB11_14 -; RV32-NEXT: # %bb.6: # %else11 -; RV32-NEXT: andi a2, a1, 32 -; RV32-NEXT: bnez a2, .LBB11_15 -; RV32-NEXT: .LBB11_7: # %else14 -; RV32-NEXT: andi a2, a1, 64 -; RV32-NEXT: bnez a2, .LBB11_16 -; RV32-NEXT: .LBB11_8: # %else17 -; RV32-NEXT: andi a1, a1, -128 -; RV32-NEXT: beqz a1, .LBB11_10 -; RV32-NEXT: .LBB11_9: # %cond.store19 -; RV32-NEXT: mv a1, sp ; RV32-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV32-NEXT: vse64.v v8, (a1) -; RV32-NEXT: fld fa5, 56(sp) -; RV32-NEXT: fsd fa5, 0(a0) -; RV32-NEXT: .LBB11_10: # %else20 -; RV32-NEXT: addi sp, s0, -320 -; RV32-NEXT: lw ra, 316(sp) # 4-byte Folded Reload -; RV32-NEXT: lw s0, 312(sp) # 4-byte Folded Reload -; RV32-NEXT: addi sp, sp, 320 -; RV32-NEXT: ret -; RV32-NEXT: .LBB11_11: # %cond.store -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vse64.v v8, (a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: beqz a2, .LBB11_2 -; RV32-NEXT: .LBB11_12: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vslidedown.vi v12, v8, 1 +; RV32-NEXT: vcompress.vm v12, v8, v0 +; RV32-NEXT: vcpop.m a1, v0 +; RV32-NEXT: vsetvli zero, a1, e64, m4, ta, ma ; RV32-NEXT: vse64.v v12, (a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: beqz a2, .LBB11_3 -; RV32-NEXT: .LBB11_13: # %cond.store4 -; RV32-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV32-NEXT: vslidedown.vi v12, v8, 2 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vse64.v v12, (a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 8 -; RV32-NEXT: bnez a2, .LBB11_4 -; RV32-NEXT: j .LBB11_5 -; RV32-NEXT: .LBB11_14: # %cond.store10 -; RV32-NEXT: addi a2, sp, 192 -; RV32-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV32-NEXT: vse64.v v8, (a2) -; RV32-NEXT: fld fa5, 224(sp) -; RV32-NEXT: fsd fa5, 0(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 32 -; RV32-NEXT: beqz a2, .LBB11_7 -; RV32-NEXT: .LBB11_15: # %cond.store13 -; RV32-NEXT: addi a2, sp, 128 -; RV32-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV32-NEXT: vse64.v v8, (a2) -; RV32-NEXT: fld fa5, 168(sp) -; RV32-NEXT: fsd fa5, 0(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 64 -; RV32-NEXT: beqz a2, .LBB11_8 -; RV32-NEXT: .LBB11_16: # %cond.store16 -; RV32-NEXT: addi a2, sp, 64 -; RV32-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV32-NEXT: vse64.v v8, (a2) -; RV32-NEXT: fld fa5, 112(sp) -; RV32-NEXT: fsd fa5, 0(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a1, a1, -128 -; RV32-NEXT: bnez a1, .LBB11_9 -; RV32-NEXT: j .LBB11_10 +; RV32-NEXT: ret ; ; RV64-LABEL: compressstore_v8f64: ; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB11_11 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: bnez a2, .LBB11_12 -; RV64-NEXT: .LBB11_2: # %else2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: bnez a2, .LBB11_13 -; RV64-NEXT: .LBB11_3: # %else5 -; RV64-NEXT: andi a2, a1, 8 -; RV64-NEXT: beqz a2, .LBB11_5 -; RV64-NEXT: .LBB11_4: # %cond.store7 -; RV64-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV64-NEXT: vslidedown.vi v12, v8, 3 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v12, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: .LBB11_5: # %else8 -; RV64-NEXT: addi sp, sp, -320 -; RV64-NEXT: .cfi_def_cfa_offset 320 -; RV64-NEXT: sd ra, 312(sp) # 8-byte Folded Spill -; RV64-NEXT: sd s0, 304(sp) # 8-byte Folded Spill -; RV64-NEXT: .cfi_offset ra, -8 -; RV64-NEXT: .cfi_offset s0, -16 -; RV64-NEXT: addi s0, sp, 320 -; RV64-NEXT: .cfi_def_cfa s0, 0 -; RV64-NEXT: andi sp, sp, -64 -; RV64-NEXT: andi a2, a1, 16 -; RV64-NEXT: bnez a2, .LBB11_14 -; RV64-NEXT: # %bb.6: # %else11 -; RV64-NEXT: andi a2, a1, 32 -; RV64-NEXT: bnez a2, .LBB11_15 -; RV64-NEXT: .LBB11_7: # %else14 -; RV64-NEXT: andi a2, a1, 64 -; RV64-NEXT: bnez a2, .LBB11_16 -; RV64-NEXT: .LBB11_8: # %else17 -; RV64-NEXT: andi a1, a1, -128 -; RV64-NEXT: beqz a1, .LBB11_10 -; RV64-NEXT: .LBB11_9: # %cond.store19 -; RV64-NEXT: mv a1, sp ; RV64-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV64-NEXT: vse64.v v8, (a1) -; RV64-NEXT: fld fa5, 56(sp) -; RV64-NEXT: fsd fa5, 0(a0) -; RV64-NEXT: .LBB11_10: # %else20 -; RV64-NEXT: addi sp, s0, -320 -; RV64-NEXT: ld ra, 312(sp) # 8-byte Folded Reload -; RV64-NEXT: ld s0, 304(sp) # 8-byte Folded Reload -; RV64-NEXT: addi sp, sp, 320 -; RV64-NEXT: ret -; RV64-NEXT: .LBB11_11: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: beqz a2, .LBB11_2 -; RV64-NEXT: .LBB11_12: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vslidedown.vi v12, v8, 1 +; RV64-NEXT: vcompress.vm v12, v8, v0 +; RV64-NEXT: vcpop.m a1, v0 +; RV64-NEXT: vsetvli zero, a1, e64, m4, ta, ma ; RV64-NEXT: vse64.v v12, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: beqz a2, .LBB11_3 -; RV64-NEXT: .LBB11_13: # %cond.store4 -; RV64-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV64-NEXT: vslidedown.vi v12, v8, 2 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v12, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 8 -; RV64-NEXT: bnez a2, .LBB11_4 -; RV64-NEXT: j .LBB11_5 -; RV64-NEXT: .LBB11_14: # %cond.store10 -; RV64-NEXT: addi a2, sp, 192 -; RV64-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV64-NEXT: vse64.v v8, (a2) -; RV64-NEXT: fld fa5, 224(sp) -; RV64-NEXT: fsd fa5, 0(a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 32 -; RV64-NEXT: beqz a2, .LBB11_7 -; RV64-NEXT: .LBB11_15: # %cond.store13 -; RV64-NEXT: addi a2, sp, 128 -; RV64-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV64-NEXT: vse64.v v8, (a2) -; RV64-NEXT: fld fa5, 168(sp) -; RV64-NEXT: fsd fa5, 0(a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 64 -; RV64-NEXT: beqz a2, .LBB11_8 -; RV64-NEXT: .LBB11_16: # %cond.store16 -; RV64-NEXT: addi a2, sp, 64 -; RV64-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV64-NEXT: vse64.v v8, (a2) -; RV64-NEXT: fld fa5, 112(sp) -; RV64-NEXT: fsd fa5, 0(a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a1, a1, -128 -; RV64-NEXT: bnez a1, .LBB11_9 -; RV64-NEXT: j .LBB11_10 +; RV64-NEXT: ret call void @llvm.masked.compressstore.v8f64(<8 x double> %v, ptr align 8 %base, <8 x i1> %mask) ret void } diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-compressstore-int.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-compressstore-int.ll index eb0096dbfba6dead919b0c79e693b99bc6a65dd0..a388ba92f302bfb4a8b105ce6376b2398ed9d0fb 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-compressstore-int.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-compressstore-int.ll @@ -6,13 +6,11 @@ declare void @llvm.masked.compressstore.v1i8(<1 x i8>, ptr, <1 x i1>) define void @compressstore_v1i8(ptr %base, <1 x i8> %v, <1 x i1> %mask) { ; CHECK-LABEL: compressstore_v1i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; CHECK-NEXT: vfirst.m a1, v0 -; CHECK-NEXT: bnez a1, .LBB0_2 -; CHECK-NEXT: # %bb.1: # %cond.store ; CHECK-NEXT: vsetivli zero, 1, e8, mf8, ta, ma -; CHECK-NEXT: vse8.v v8, (a0) -; CHECK-NEXT: .LBB0_2: # %else +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e8, mf8, ta, ma +; CHECK-NEXT: vse8.v v9, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v1i8(<1 x i8> %v, ptr %base, <1 x i1> %mask) ret void @@ -22,25 +20,11 @@ declare void @llvm.masked.compressstore.v2i8(<2 x i8>, ptr, <2 x i1>) define void @compressstore_v2i8(ptr %base, <2 x i8> %v, <2 x i1> %mask) { ; CHECK-LABEL: compressstore_v2i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; CHECK-NEXT: vmv.x.s a1, v0 -; CHECK-NEXT: andi a2, a1, 1 -; CHECK-NEXT: bnez a2, .LBB1_3 -; CHECK-NEXT: # %bb.1: # %else -; CHECK-NEXT: andi a1, a1, 2 -; CHECK-NEXT: bnez a1, .LBB1_4 -; CHECK-NEXT: .LBB1_2: # %else2 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB1_3: # %cond.store -; CHECK-NEXT: vsetivli zero, 1, e8, mf8, ta, ma -; CHECK-NEXT: vse8.v v8, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a1, a1, 2 -; CHECK-NEXT: beqz a1, .LBB1_2 -; CHECK-NEXT: .LBB1_4: # %cond.store1 -; CHECK-NEXT: vsetivli zero, 1, e8, mf8, ta, ma -; CHECK-NEXT: vslidedown.vi v8, v8, 1 -; CHECK-NEXT: vse8.v v8, (a0) +; CHECK-NEXT: vsetivli zero, 2, e8, mf8, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e8, mf8, ta, ma +; CHECK-NEXT: vse8.v v9, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v2i8(<2 x i8> %v, ptr %base, <2 x i1> %mask) ret void @@ -50,45 +34,11 @@ declare void @llvm.masked.compressstore.v4i8(<4 x i8>, ptr, <4 x i1>) define void @compressstore_v4i8(ptr %base, <4 x i8> %v, <4 x i1> %mask) { ; CHECK-LABEL: compressstore_v4i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; CHECK-NEXT: vmv.x.s a1, v0 -; CHECK-NEXT: andi a2, a1, 1 -; CHECK-NEXT: bnez a2, .LBB2_5 -; CHECK-NEXT: # %bb.1: # %else -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: bnez a2, .LBB2_6 -; CHECK-NEXT: .LBB2_2: # %else2 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: bnez a2, .LBB2_7 -; CHECK-NEXT: .LBB2_3: # %else5 -; CHECK-NEXT: andi a1, a1, 8 -; CHECK-NEXT: bnez a1, .LBB2_8 -; CHECK-NEXT: .LBB2_4: # %else8 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB2_5: # %cond.store -; CHECK-NEXT: vsetivli zero, 1, e8, mf4, ta, ma -; CHECK-NEXT: vse8.v v8, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: beqz a2, .LBB2_2 -; CHECK-NEXT: .LBB2_6: # %cond.store1 -; CHECK-NEXT: vsetivli zero, 1, e8, mf4, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 1 +; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e8, mf4, ta, ma ; CHECK-NEXT: vse8.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: beqz a2, .LBB2_3 -; CHECK-NEXT: .LBB2_7: # %cond.store4 -; CHECK-NEXT: vsetivli zero, 1, e8, mf4, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 2 -; CHECK-NEXT: vse8.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a1, a1, 8 -; CHECK-NEXT: beqz a1, .LBB2_4 -; CHECK-NEXT: .LBB2_8: # %cond.store7 -; CHECK-NEXT: vsetivli zero, 1, e8, mf4, ta, ma -; CHECK-NEXT: vslidedown.vi v8, v8, 3 -; CHECK-NEXT: vse8.v v8, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v4i8(<4 x i8> %v, ptr %base, <4 x i1> %mask) ret void @@ -98,85 +48,11 @@ declare void @llvm.masked.compressstore.v8i8(<8 x i8>, ptr, <8 x i1>) define void @compressstore_v8i8(ptr %base, <8 x i8> %v, <8 x i1> %mask) { ; CHECK-LABEL: compressstore_v8i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; CHECK-NEXT: vmv.x.s a1, v0 -; CHECK-NEXT: andi a2, a1, 1 -; CHECK-NEXT: bnez a2, .LBB3_9 -; CHECK-NEXT: # %bb.1: # %else -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: bnez a2, .LBB3_10 -; CHECK-NEXT: .LBB3_2: # %else2 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: bnez a2, .LBB3_11 -; CHECK-NEXT: .LBB3_3: # %else5 -; CHECK-NEXT: andi a2, a1, 8 -; CHECK-NEXT: bnez a2, .LBB3_12 -; CHECK-NEXT: .LBB3_4: # %else8 -; CHECK-NEXT: andi a2, a1, 16 -; CHECK-NEXT: bnez a2, .LBB3_13 -; CHECK-NEXT: .LBB3_5: # %else11 -; CHECK-NEXT: andi a2, a1, 32 -; CHECK-NEXT: bnez a2, .LBB3_14 -; CHECK-NEXT: .LBB3_6: # %else14 -; CHECK-NEXT: andi a2, a1, 64 -; CHECK-NEXT: bnez a2, .LBB3_15 -; CHECK-NEXT: .LBB3_7: # %else17 -; CHECK-NEXT: andi a1, a1, -128 -; CHECK-NEXT: bnez a1, .LBB3_16 -; CHECK-NEXT: .LBB3_8: # %else20 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB3_9: # %cond.store -; CHECK-NEXT: vsetivli zero, 1, e8, mf2, ta, ma -; CHECK-NEXT: vse8.v v8, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: beqz a2, .LBB3_2 -; CHECK-NEXT: .LBB3_10: # %cond.store1 -; CHECK-NEXT: vsetivli zero, 1, e8, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 1 -; CHECK-NEXT: vse8.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: beqz a2, .LBB3_3 -; CHECK-NEXT: .LBB3_11: # %cond.store4 -; CHECK-NEXT: vsetivli zero, 1, e8, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 2 -; CHECK-NEXT: vse8.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a2, a1, 8 -; CHECK-NEXT: beqz a2, .LBB3_4 -; CHECK-NEXT: .LBB3_12: # %cond.store7 -; CHECK-NEXT: vsetivli zero, 1, e8, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 3 -; CHECK-NEXT: vse8.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a2, a1, 16 -; CHECK-NEXT: beqz a2, .LBB3_5 -; CHECK-NEXT: .LBB3_13: # %cond.store10 -; CHECK-NEXT: vsetivli zero, 1, e8, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 4 -; CHECK-NEXT: vse8.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a2, a1, 32 -; CHECK-NEXT: beqz a2, .LBB3_6 -; CHECK-NEXT: .LBB3_14: # %cond.store13 -; CHECK-NEXT: vsetivli zero, 1, e8, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 5 +; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e8, mf2, ta, ma ; CHECK-NEXT: vse8.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a2, a1, 64 -; CHECK-NEXT: beqz a2, .LBB3_7 -; CHECK-NEXT: .LBB3_15: # %cond.store16 -; CHECK-NEXT: vsetivli zero, 1, e8, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 6 -; CHECK-NEXT: vse8.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 1 -; CHECK-NEXT: andi a1, a1, -128 -; CHECK-NEXT: beqz a1, .LBB3_8 -; CHECK-NEXT: .LBB3_16: # %cond.store19 -; CHECK-NEXT: vsetivli zero, 1, e8, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v8, v8, 7 -; CHECK-NEXT: vse8.v v8, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v8i8(<8 x i8> %v, ptr %base, <8 x i1> %mask) ret void @@ -186,13 +62,11 @@ declare void @llvm.masked.compressstore.v1i16(<1 x i16>, ptr, <1 x i1>) define void @compressstore_v1i16(ptr %base, <1 x i16> %v, <1 x i1> %mask) { ; CHECK-LABEL: compressstore_v1i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; CHECK-NEXT: vfirst.m a1, v0 -; CHECK-NEXT: bnez a1, .LBB4_2 -; CHECK-NEXT: # %bb.1: # %cond.store ; CHECK-NEXT: vsetivli zero, 1, e16, mf4, ta, ma -; CHECK-NEXT: vse16.v v8, (a0) -; CHECK-NEXT: .LBB4_2: # %else +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; CHECK-NEXT: vse16.v v9, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v1i16(<1 x i16> %v, ptr align 2 %base, <1 x i1> %mask) ret void @@ -202,25 +76,11 @@ declare void @llvm.masked.compressstore.v2i16(<2 x i16>, ptr, <2 x i1>) define void @compressstore_v2i16(ptr %base, <2 x i16> %v, <2 x i1> %mask) { ; CHECK-LABEL: compressstore_v2i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; CHECK-NEXT: vmv.x.s a1, v0 -; CHECK-NEXT: andi a2, a1, 1 -; CHECK-NEXT: bnez a2, .LBB5_3 -; CHECK-NEXT: # %bb.1: # %else -; CHECK-NEXT: andi a1, a1, 2 -; CHECK-NEXT: bnez a1, .LBB5_4 -; CHECK-NEXT: .LBB5_2: # %else2 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB5_3: # %cond.store -; CHECK-NEXT: vsetivli zero, 1, e16, mf4, ta, ma -; CHECK-NEXT: vse16.v v8, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a1, a1, 2 -; CHECK-NEXT: beqz a1, .LBB5_2 -; CHECK-NEXT: .LBB5_4: # %cond.store1 -; CHECK-NEXT: vsetivli zero, 1, e16, mf4, ta, ma -; CHECK-NEXT: vslidedown.vi v8, v8, 1 -; CHECK-NEXT: vse16.v v8, (a0) +; CHECK-NEXT: vsetivli zero, 2, e16, mf4, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e16, mf4, ta, ma +; CHECK-NEXT: vse16.v v9, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v2i16(<2 x i16> %v, ptr align 2 %base, <2 x i1> %mask) ret void @@ -230,45 +90,11 @@ declare void @llvm.masked.compressstore.v4i16(<4 x i16>, ptr, <4 x i1>) define void @compressstore_v4i16(ptr %base, <4 x i16> %v, <4 x i1> %mask) { ; CHECK-LABEL: compressstore_v4i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; CHECK-NEXT: vmv.x.s a1, v0 -; CHECK-NEXT: andi a2, a1, 1 -; CHECK-NEXT: bnez a2, .LBB6_5 -; CHECK-NEXT: # %bb.1: # %else -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: bnez a2, .LBB6_6 -; CHECK-NEXT: .LBB6_2: # %else2 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: bnez a2, .LBB6_7 -; CHECK-NEXT: .LBB6_3: # %else5 -; CHECK-NEXT: andi a1, a1, 8 -; CHECK-NEXT: bnez a1, .LBB6_8 -; CHECK-NEXT: .LBB6_4: # %else8 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB6_5: # %cond.store -; CHECK-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; CHECK-NEXT: vse16.v v8, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: beqz a2, .LBB6_2 -; CHECK-NEXT: .LBB6_6: # %cond.store1 -; CHECK-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 1 -; CHECK-NEXT: vse16.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: beqz a2, .LBB6_3 -; CHECK-NEXT: .LBB6_7: # %cond.store4 -; CHECK-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 2 +; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e16, mf2, ta, ma ; CHECK-NEXT: vse16.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a1, a1, 8 -; CHECK-NEXT: beqz a1, .LBB6_4 -; CHECK-NEXT: .LBB6_8: # %cond.store7 -; CHECK-NEXT: vsetivli zero, 1, e16, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v8, v8, 3 -; CHECK-NEXT: vse16.v v8, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v4i16(<4 x i16> %v, ptr align 2 %base, <4 x i1> %mask) ret void @@ -278,85 +104,11 @@ declare void @llvm.masked.compressstore.v8i16(<8 x i16>, ptr, <8 x i1>) define void @compressstore_v8i16(ptr %base, <8 x i16> %v, <8 x i1> %mask) { ; CHECK-LABEL: compressstore_v8i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; CHECK-NEXT: vmv.x.s a1, v0 -; CHECK-NEXT: andi a2, a1, 1 -; CHECK-NEXT: bnez a2, .LBB7_9 -; CHECK-NEXT: # %bb.1: # %else -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: bnez a2, .LBB7_10 -; CHECK-NEXT: .LBB7_2: # %else2 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: bnez a2, .LBB7_11 -; CHECK-NEXT: .LBB7_3: # %else5 -; CHECK-NEXT: andi a2, a1, 8 -; CHECK-NEXT: bnez a2, .LBB7_12 -; CHECK-NEXT: .LBB7_4: # %else8 -; CHECK-NEXT: andi a2, a1, 16 -; CHECK-NEXT: bnez a2, .LBB7_13 -; CHECK-NEXT: .LBB7_5: # %else11 -; CHECK-NEXT: andi a2, a1, 32 -; CHECK-NEXT: bnez a2, .LBB7_14 -; CHECK-NEXT: .LBB7_6: # %else14 -; CHECK-NEXT: andi a2, a1, 64 -; CHECK-NEXT: bnez a2, .LBB7_15 -; CHECK-NEXT: .LBB7_7: # %else17 -; CHECK-NEXT: andi a1, a1, -128 -; CHECK-NEXT: bnez a1, .LBB7_16 -; CHECK-NEXT: .LBB7_8: # %else20 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB7_9: # %cond.store -; CHECK-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; CHECK-NEXT: vse16.v v8, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: beqz a2, .LBB7_2 -; CHECK-NEXT: .LBB7_10: # %cond.store1 -; CHECK-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 1 -; CHECK-NEXT: vse16.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: beqz a2, .LBB7_3 -; CHECK-NEXT: .LBB7_11: # %cond.store4 -; CHECK-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 2 -; CHECK-NEXT: vse16.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a2, a1, 8 -; CHECK-NEXT: beqz a2, .LBB7_4 -; CHECK-NEXT: .LBB7_12: # %cond.store7 -; CHECK-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 3 -; CHECK-NEXT: vse16.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a2, a1, 16 -; CHECK-NEXT: beqz a2, .LBB7_5 -; CHECK-NEXT: .LBB7_13: # %cond.store10 -; CHECK-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 4 +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e16, m1, ta, ma ; CHECK-NEXT: vse16.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a2, a1, 32 -; CHECK-NEXT: beqz a2, .LBB7_6 -; CHECK-NEXT: .LBB7_14: # %cond.store13 -; CHECK-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 5 -; CHECK-NEXT: vse16.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a2, a1, 64 -; CHECK-NEXT: beqz a2, .LBB7_7 -; CHECK-NEXT: .LBB7_15: # %cond.store16 -; CHECK-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 6 -; CHECK-NEXT: vse16.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 2 -; CHECK-NEXT: andi a1, a1, -128 -; CHECK-NEXT: beqz a1, .LBB7_8 -; CHECK-NEXT: .LBB7_16: # %cond.store19 -; CHECK-NEXT: vsetivli zero, 1, e16, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v8, v8, 7 -; CHECK-NEXT: vse16.v v8, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v8i16(<8 x i16> %v, ptr align 2 %base, <8 x i1> %mask) ret void @@ -366,13 +118,11 @@ declare void @llvm.masked.compressstore.v1i32(<1 x i32>, ptr, <1 x i1>) define void @compressstore_v1i32(ptr %base, <1 x i32> %v, <1 x i1> %mask) { ; CHECK-LABEL: compressstore_v1i32: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; CHECK-NEXT: vfirst.m a1, v0 -; CHECK-NEXT: bnez a1, .LBB8_2 -; CHECK-NEXT: # %bb.1: # %cond.store ; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vse32.v v8, (a0) -; CHECK-NEXT: .LBB8_2: # %else +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; CHECK-NEXT: vse32.v v9, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v1i32(<1 x i32> %v, ptr align 4 %base, <1 x i1> %mask) ret void @@ -382,25 +132,11 @@ declare void @llvm.masked.compressstore.v2i32(<2 x i32>, ptr, <2 x i1>) define void @compressstore_v2i32(ptr %base, <2 x i32> %v, <2 x i1> %mask) { ; CHECK-LABEL: compressstore_v2i32: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; CHECK-NEXT: vmv.x.s a1, v0 -; CHECK-NEXT: andi a2, a1, 1 -; CHECK-NEXT: bnez a2, .LBB9_3 -; CHECK-NEXT: # %bb.1: # %else -; CHECK-NEXT: andi a1, a1, 2 -; CHECK-NEXT: bnez a1, .LBB9_4 -; CHECK-NEXT: .LBB9_2: # %else2 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB9_3: # %cond.store -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vse32.v v8, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a1, a1, 2 -; CHECK-NEXT: beqz a1, .LBB9_2 -; CHECK-NEXT: .LBB9_4: # %cond.store1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vslidedown.vi v8, v8, 1 -; CHECK-NEXT: vse32.v v8, (a0) +; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e32, mf2, ta, ma +; CHECK-NEXT: vse32.v v9, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v2i32(<2 x i32> %v, ptr align 4 %base, <2 x i1> %mask) ret void @@ -410,45 +146,11 @@ declare void @llvm.masked.compressstore.v4i32(<4 x i32>, ptr, <4 x i1>) define void @compressstore_v4i32(ptr %base, <4 x i32> %v, <4 x i1> %mask) { ; CHECK-LABEL: compressstore_v4i32: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; CHECK-NEXT: vmv.x.s a1, v0 -; CHECK-NEXT: andi a2, a1, 1 -; CHECK-NEXT: bnez a2, .LBB10_5 -; CHECK-NEXT: # %bb.1: # %else -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: bnez a2, .LBB10_6 -; CHECK-NEXT: .LBB10_2: # %else2 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: bnez a2, .LBB10_7 -; CHECK-NEXT: .LBB10_3: # %else5 -; CHECK-NEXT: andi a1, a1, 8 -; CHECK-NEXT: bnez a1, .LBB10_8 -; CHECK-NEXT: .LBB10_4: # %else8 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB10_5: # %cond.store -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vse32.v v8, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: beqz a2, .LBB10_2 -; CHECK-NEXT: .LBB10_6: # %cond.store1 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 1 -; CHECK-NEXT: vse32.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: beqz a2, .LBB10_3 -; CHECK-NEXT: .LBB10_7: # %cond.store4 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v9, v8, 2 +; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e32, m1, ta, ma ; CHECK-NEXT: vse32.v v9, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a1, a1, 8 -; CHECK-NEXT: beqz a1, .LBB10_4 -; CHECK-NEXT: .LBB10_8: # %cond.store7 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v8, v8, 3 -; CHECK-NEXT: vse32.v v8, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v4i32(<4 x i32> %v, ptr align 4 %base, <4 x i1> %mask) ret void @@ -458,89 +160,11 @@ declare void @llvm.masked.compressstore.v8i32(<8 x i32>, ptr, <8 x i1>) define void @compressstore_v8i32(ptr %base, <8 x i32> %v, <8 x i1> %mask) { ; CHECK-LABEL: compressstore_v8i32: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; CHECK-NEXT: vmv.x.s a1, v0 -; CHECK-NEXT: andi a2, a1, 1 -; CHECK-NEXT: bnez a2, .LBB11_9 -; CHECK-NEXT: # %bb.1: # %else -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: bnez a2, .LBB11_10 -; CHECK-NEXT: .LBB11_2: # %else2 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: bnez a2, .LBB11_11 -; CHECK-NEXT: .LBB11_3: # %else5 -; CHECK-NEXT: andi a2, a1, 8 -; CHECK-NEXT: bnez a2, .LBB11_12 -; CHECK-NEXT: .LBB11_4: # %else8 -; CHECK-NEXT: andi a2, a1, 16 -; CHECK-NEXT: bnez a2, .LBB11_13 -; CHECK-NEXT: .LBB11_5: # %else11 -; CHECK-NEXT: andi a2, a1, 32 -; CHECK-NEXT: bnez a2, .LBB11_14 -; CHECK-NEXT: .LBB11_6: # %else14 -; CHECK-NEXT: andi a2, a1, 64 -; CHECK-NEXT: bnez a2, .LBB11_15 -; CHECK-NEXT: .LBB11_7: # %else17 -; CHECK-NEXT: andi a1, a1, -128 -; CHECK-NEXT: bnez a1, .LBB11_16 -; CHECK-NEXT: .LBB11_8: # %else20 -; CHECK-NEXT: ret -; CHECK-NEXT: .LBB11_9: # %cond.store -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vse32.v v8, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a2, a1, 2 -; CHECK-NEXT: beqz a2, .LBB11_2 -; CHECK-NEXT: .LBB11_10: # %cond.store1 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v8, 1 -; CHECK-NEXT: vse32.v v10, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a2, a1, 4 -; CHECK-NEXT: beqz a2, .LBB11_3 -; CHECK-NEXT: .LBB11_11: # %cond.store4 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v8, 2 -; CHECK-NEXT: vse32.v v10, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a2, a1, 8 -; CHECK-NEXT: beqz a2, .LBB11_4 -; CHECK-NEXT: .LBB11_12: # %cond.store7 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v8, 3 +; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; CHECK-NEXT: vcompress.vm v10, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e32, m2, ta, ma ; CHECK-NEXT: vse32.v v10, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a2, a1, 16 -; CHECK-NEXT: beqz a2, .LBB11_5 -; CHECK-NEXT: .LBB11_13: # %cond.store10 -; CHECK-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v8, 4 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vse32.v v10, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a2, a1, 32 -; CHECK-NEXT: beqz a2, .LBB11_6 -; CHECK-NEXT: .LBB11_14: # %cond.store13 -; CHECK-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v8, 5 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vse32.v v10, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a2, a1, 64 -; CHECK-NEXT: beqz a2, .LBB11_7 -; CHECK-NEXT: .LBB11_15: # %cond.store16 -; CHECK-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v8, 6 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vse32.v v10, (a0) -; CHECK-NEXT: addi a0, a0, 4 -; CHECK-NEXT: andi a1, a1, -128 -; CHECK-NEXT: beqz a1, .LBB11_8 -; CHECK-NEXT: .LBB11_16: # %cond.store19 -; CHECK-NEXT: vsetivli zero, 1, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v8, v8, 7 -; CHECK-NEXT: vsetivli zero, 1, e32, m1, ta, ma -; CHECK-NEXT: vse32.v v8, (a0) ; CHECK-NEXT: ret call void @llvm.masked.compressstore.v8i32(<8 x i32> %v, ptr align 4 %base, <8 x i1> %mask) ret void @@ -548,439 +172,59 @@ define void @compressstore_v8i32(ptr %base, <8 x i32> %v, <8 x i1> %mask) { declare void @llvm.masked.compressstore.v1i64(<1 x i64>, ptr, <1 x i1>) define void @compressstore_v1i64(ptr %base, <1 x i64> %v, <1 x i1> %mask) { -; RV32-LABEL: compressstore_v1i64: -; RV32: # %bb.0: -; RV32-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; RV32-NEXT: vfirst.m a1, v0 -; RV32-NEXT: bnez a1, .LBB12_2 -; RV32-NEXT: # %bb.1: # %cond.store -; RV32-NEXT: li a1, 32 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vsrl.vx v9, v8, a1 -; RV32-NEXT: vmv.x.s a1, v9 -; RV32-NEXT: vmv.x.s a2, v8 -; RV32-NEXT: sw a2, 0(a0) -; RV32-NEXT: sw a1, 4(a0) -; RV32-NEXT: .LBB12_2: # %else -; RV32-NEXT: ret -; -; RV64-LABEL: compressstore_v1i64: -; RV64: # %bb.0: -; RV64-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; RV64-NEXT: vfirst.m a1, v0 -; RV64-NEXT: bnez a1, .LBB12_2 -; RV64-NEXT: # %bb.1: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: .LBB12_2: # %else -; RV64-NEXT: ret +; CHECK-LABEL: compressstore_v1i64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; CHECK-NEXT: vse64.v v9, (a0) +; CHECK-NEXT: ret call void @llvm.masked.compressstore.v1i64(<1 x i64> %v, ptr align 8 %base, <1 x i1> %mask) ret void } declare void @llvm.masked.compressstore.v2i64(<2 x i64>, ptr, <2 x i1>) define void @compressstore_v2i64(ptr %base, <2 x i64> %v, <2 x i1> %mask) { -; RV32-LABEL: compressstore_v2i64: -; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB13_3 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a1, a1, 2 -; RV32-NEXT: bnez a1, .LBB13_4 -; RV32-NEXT: .LBB13_2: # %else2 -; RV32-NEXT: ret -; RV32-NEXT: .LBB13_3: # %cond.store -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vsrl.vx v9, v8, a2 -; RV32-NEXT: vmv.x.s a2, v9 -; RV32-NEXT: vmv.x.s a3, v8 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a1, a1, 2 -; RV32-NEXT: beqz a1, .LBB13_2 -; RV32-NEXT: .LBB13_4: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 1 -; RV32-NEXT: li a1, 32 -; RV32-NEXT: vsrl.vx v9, v8, a1 -; RV32-NEXT: vmv.x.s a1, v9 -; RV32-NEXT: vmv.x.s a2, v8 -; RV32-NEXT: sw a2, 0(a0) -; RV32-NEXT: sw a1, 4(a0) -; RV32-NEXT: ret -; -; RV64-LABEL: compressstore_v2i64: -; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB13_3 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a1, a1, 2 -; RV64-NEXT: bnez a1, .LBB13_4 -; RV64-NEXT: .LBB13_2: # %else2 -; RV64-NEXT: ret -; RV64-NEXT: .LBB13_3: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a1, a1, 2 -; RV64-NEXT: beqz a1, .LBB13_2 -; RV64-NEXT: .LBB13_4: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 1 -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: ret +; CHECK-LABEL: compressstore_v2i64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma +; CHECK-NEXT: vcompress.vm v9, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e64, m1, ta, ma +; CHECK-NEXT: vse64.v v9, (a0) +; CHECK-NEXT: ret call void @llvm.masked.compressstore.v2i64(<2 x i64> %v, ptr align 8 %base, <2 x i1> %mask) ret void } declare void @llvm.masked.compressstore.v4i64(<4 x i64>, ptr, <4 x i1>) define void @compressstore_v4i64(ptr %base, <4 x i64> %v, <4 x i1> %mask) { -; RV32-LABEL: compressstore_v4i64: -; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB14_5 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: bnez a2, .LBB14_6 -; RV32-NEXT: .LBB14_2: # %else2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: bnez a2, .LBB14_7 -; RV32-NEXT: .LBB14_3: # %else5 -; RV32-NEXT: andi a1, a1, 8 -; RV32-NEXT: bnez a1, .LBB14_8 -; RV32-NEXT: .LBB14_4: # %else8 -; RV32-NEXT: ret -; RV32-NEXT: .LBB14_5: # %cond.store -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV32-NEXT: vsrl.vx v10, v8, a2 -; RV32-NEXT: vmv.x.s a2, v10 -; RV32-NEXT: vmv.x.s a3, v8 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: beqz a2, .LBB14_2 -; RV32-NEXT: .LBB14_6: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 1 -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsrl.vx v12, v10, a2 -; RV32-NEXT: vmv.x.s a2, v12 -; RV32-NEXT: vmv.x.s a3, v10 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: beqz a2, .LBB14_3 -; RV32-NEXT: .LBB14_7: # %cond.store4 -; RV32-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV32-NEXT: vslidedown.vi v10, v8, 2 -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsrl.vx v12, v10, a2 -; RV32-NEXT: vmv.x.s a2, v12 -; RV32-NEXT: vmv.x.s a3, v10 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a1, a1, 8 -; RV32-NEXT: beqz a1, .LBB14_4 -; RV32-NEXT: .LBB14_8: # %cond.store7 -; RV32-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 3 -; RV32-NEXT: li a1, 32 -; RV32-NEXT: vsrl.vx v10, v8, a1 -; RV32-NEXT: vmv.x.s a1, v10 -; RV32-NEXT: vmv.x.s a2, v8 -; RV32-NEXT: sw a2, 0(a0) -; RV32-NEXT: sw a1, 4(a0) -; RV32-NEXT: ret -; -; RV64-LABEL: compressstore_v4i64: -; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB14_5 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: bnez a2, .LBB14_6 -; RV64-NEXT: .LBB14_2: # %else2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: bnez a2, .LBB14_7 -; RV64-NEXT: .LBB14_3: # %else5 -; RV64-NEXT: andi a1, a1, 8 -; RV64-NEXT: bnez a1, .LBB14_8 -; RV64-NEXT: .LBB14_4: # %else8 -; RV64-NEXT: ret -; RV64-NEXT: .LBB14_5: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: beqz a2, .LBB14_2 -; RV64-NEXT: .LBB14_6: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 1 -; RV64-NEXT: vse64.v v10, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: beqz a2, .LBB14_3 -; RV64-NEXT: .LBB14_7: # %cond.store4 -; RV64-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV64-NEXT: vslidedown.vi v10, v8, 2 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v10, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a1, a1, 8 -; RV64-NEXT: beqz a1, .LBB14_4 -; RV64-NEXT: .LBB14_8: # %cond.store7 -; RV64-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV64-NEXT: vslidedown.vi v8, v8, 3 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: ret +; CHECK-LABEL: compressstore_v4i64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-NEXT: vcompress.vm v10, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e64, m2, ta, ma +; CHECK-NEXT: vse64.v v10, (a0) +; CHECK-NEXT: ret call void @llvm.masked.compressstore.v4i64(<4 x i64> %v, ptr align 8 %base, <4 x i1> %mask) ret void } declare void @llvm.masked.compressstore.v8i64(<8 x i64>, ptr, <8 x i1>) define void @compressstore_v8i64(ptr %base, <8 x i64> %v, <8 x i1> %mask) { -; RV32-LABEL: compressstore_v8i64: -; RV32: # %bb.0: -; RV32-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV32-NEXT: vmv.x.s a1, v0 -; RV32-NEXT: andi a2, a1, 1 -; RV32-NEXT: bnez a2, .LBB15_9 -; RV32-NEXT: # %bb.1: # %else -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: bnez a2, .LBB15_10 -; RV32-NEXT: .LBB15_2: # %else2 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: bnez a2, .LBB15_11 -; RV32-NEXT: .LBB15_3: # %else5 -; RV32-NEXT: andi a2, a1, 8 -; RV32-NEXT: bnez a2, .LBB15_12 -; RV32-NEXT: .LBB15_4: # %else8 -; RV32-NEXT: andi a2, a1, 16 -; RV32-NEXT: bnez a2, .LBB15_13 -; RV32-NEXT: .LBB15_5: # %else11 -; RV32-NEXT: andi a2, a1, 32 -; RV32-NEXT: bnez a2, .LBB15_14 -; RV32-NEXT: .LBB15_6: # %else14 -; RV32-NEXT: andi a2, a1, 64 -; RV32-NEXT: bnez a2, .LBB15_15 -; RV32-NEXT: .LBB15_7: # %else17 -; RV32-NEXT: andi a1, a1, -128 -; RV32-NEXT: bnez a1, .LBB15_16 -; RV32-NEXT: .LBB15_8: # %else20 -; RV32-NEXT: ret -; RV32-NEXT: .LBB15_9: # %cond.store -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsetivli zero, 1, e64, m4, ta, ma -; RV32-NEXT: vsrl.vx v12, v8, a2 -; RV32-NEXT: vmv.x.s a2, v12 -; RV32-NEXT: vmv.x.s a3, v8 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 2 -; RV32-NEXT: beqz a2, .LBB15_2 -; RV32-NEXT: .LBB15_10: # %cond.store1 -; RV32-NEXT: vsetivli zero, 1, e64, m4, ta, ma -; RV32-NEXT: vslidedown.vi v12, v8, 1 -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsrl.vx v16, v12, a2 -; RV32-NEXT: vmv.x.s a2, v16 -; RV32-NEXT: vmv.x.s a3, v12 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 4 -; RV32-NEXT: beqz a2, .LBB15_3 -; RV32-NEXT: .LBB15_11: # %cond.store4 -; RV32-NEXT: vsetivli zero, 1, e64, m4, ta, ma -; RV32-NEXT: vslidedown.vi v12, v8, 2 -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsrl.vx v16, v12, a2 -; RV32-NEXT: vmv.x.s a2, v16 -; RV32-NEXT: vmv.x.s a3, v12 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 8 -; RV32-NEXT: beqz a2, .LBB15_4 -; RV32-NEXT: .LBB15_12: # %cond.store7 -; RV32-NEXT: vsetivli zero, 1, e64, m4, ta, ma -; RV32-NEXT: vslidedown.vi v12, v8, 3 -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsrl.vx v16, v12, a2 -; RV32-NEXT: vmv.x.s a2, v16 -; RV32-NEXT: vmv.x.s a3, v12 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 16 -; RV32-NEXT: beqz a2, .LBB15_5 -; RV32-NEXT: .LBB15_13: # %cond.store10 -; RV32-NEXT: vsetivli zero, 1, e64, m4, ta, ma -; RV32-NEXT: vslidedown.vi v12, v8, 4 -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsrl.vx v16, v12, a2 -; RV32-NEXT: vmv.x.s a2, v16 -; RV32-NEXT: vmv.x.s a3, v12 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 32 -; RV32-NEXT: beqz a2, .LBB15_6 -; RV32-NEXT: .LBB15_14: # %cond.store13 -; RV32-NEXT: vsetivli zero, 1, e64, m4, ta, ma -; RV32-NEXT: vslidedown.vi v12, v8, 5 -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsrl.vx v16, v12, a2 -; RV32-NEXT: vmv.x.s a2, v16 -; RV32-NEXT: vmv.x.s a3, v12 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a2, a1, 64 -; RV32-NEXT: beqz a2, .LBB15_7 -; RV32-NEXT: .LBB15_15: # %cond.store16 -; RV32-NEXT: vsetivli zero, 1, e64, m4, ta, ma -; RV32-NEXT: vslidedown.vi v12, v8, 6 -; RV32-NEXT: li a2, 32 -; RV32-NEXT: vsrl.vx v16, v12, a2 -; RV32-NEXT: vmv.x.s a2, v16 -; RV32-NEXT: vmv.x.s a3, v12 -; RV32-NEXT: sw a3, 0(a0) -; RV32-NEXT: sw a2, 4(a0) -; RV32-NEXT: addi a0, a0, 8 -; RV32-NEXT: andi a1, a1, -128 -; RV32-NEXT: beqz a1, .LBB15_8 -; RV32-NEXT: .LBB15_16: # %cond.store19 -; RV32-NEXT: vsetivli zero, 1, e64, m4, ta, ma -; RV32-NEXT: vslidedown.vi v8, v8, 7 -; RV32-NEXT: li a1, 32 -; RV32-NEXT: vsrl.vx v12, v8, a1 -; RV32-NEXT: vmv.x.s a1, v12 -; RV32-NEXT: vmv.x.s a2, v8 -; RV32-NEXT: sw a2, 0(a0) -; RV32-NEXT: sw a1, 4(a0) -; RV32-NEXT: ret -; -; RV64-LABEL: compressstore_v8i64: -; RV64: # %bb.0: -; RV64-NEXT: vsetivli zero, 1, e8, m1, ta, ma -; RV64-NEXT: vmv.x.s a1, v0 -; RV64-NEXT: andi a2, a1, 1 -; RV64-NEXT: bnez a2, .LBB15_11 -; RV64-NEXT: # %bb.1: # %else -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: bnez a2, .LBB15_12 -; RV64-NEXT: .LBB15_2: # %else2 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: bnez a2, .LBB15_13 -; RV64-NEXT: .LBB15_3: # %else5 -; RV64-NEXT: andi a2, a1, 8 -; RV64-NEXT: beqz a2, .LBB15_5 -; RV64-NEXT: .LBB15_4: # %cond.store7 -; RV64-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV64-NEXT: vslidedown.vi v12, v8, 3 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v12, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: .LBB15_5: # %else8 -; RV64-NEXT: addi sp, sp, -320 -; RV64-NEXT: .cfi_def_cfa_offset 320 -; RV64-NEXT: sd ra, 312(sp) # 8-byte Folded Spill -; RV64-NEXT: sd s0, 304(sp) # 8-byte Folded Spill -; RV64-NEXT: .cfi_offset ra, -8 -; RV64-NEXT: .cfi_offset s0, -16 -; RV64-NEXT: addi s0, sp, 320 -; RV64-NEXT: .cfi_def_cfa s0, 0 -; RV64-NEXT: andi sp, sp, -64 -; RV64-NEXT: andi a2, a1, 16 -; RV64-NEXT: bnez a2, .LBB15_14 -; RV64-NEXT: # %bb.6: # %else11 -; RV64-NEXT: andi a2, a1, 32 -; RV64-NEXT: bnez a2, .LBB15_15 -; RV64-NEXT: .LBB15_7: # %else14 -; RV64-NEXT: andi a2, a1, 64 -; RV64-NEXT: bnez a2, .LBB15_16 -; RV64-NEXT: .LBB15_8: # %else17 -; RV64-NEXT: andi a1, a1, -128 -; RV64-NEXT: beqz a1, .LBB15_10 -; RV64-NEXT: .LBB15_9: # %cond.store19 -; RV64-NEXT: mv a1, sp -; RV64-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV64-NEXT: vse64.v v8, (a1) -; RV64-NEXT: ld a1, 56(sp) -; RV64-NEXT: sd a1, 0(a0) -; RV64-NEXT: .LBB15_10: # %else20 -; RV64-NEXT: addi sp, s0, -320 -; RV64-NEXT: ld ra, 312(sp) # 8-byte Folded Reload -; RV64-NEXT: ld s0, 304(sp) # 8-byte Folded Reload -; RV64-NEXT: addi sp, sp, 320 -; RV64-NEXT: ret -; RV64-NEXT: .LBB15_11: # %cond.store -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v8, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 2 -; RV64-NEXT: beqz a2, .LBB15_2 -; RV64-NEXT: .LBB15_12: # %cond.store1 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vslidedown.vi v12, v8, 1 -; RV64-NEXT: vse64.v v12, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 4 -; RV64-NEXT: beqz a2, .LBB15_3 -; RV64-NEXT: .LBB15_13: # %cond.store4 -; RV64-NEXT: vsetivli zero, 1, e64, m2, ta, ma -; RV64-NEXT: vslidedown.vi v12, v8, 2 -; RV64-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; RV64-NEXT: vse64.v v12, (a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 8 -; RV64-NEXT: bnez a2, .LBB15_4 -; RV64-NEXT: j .LBB15_5 -; RV64-NEXT: .LBB15_14: # %cond.store10 -; RV64-NEXT: addi a2, sp, 192 -; RV64-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV64-NEXT: vse64.v v8, (a2) -; RV64-NEXT: ld a2, 224(sp) -; RV64-NEXT: sd a2, 0(a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 32 -; RV64-NEXT: beqz a2, .LBB15_7 -; RV64-NEXT: .LBB15_15: # %cond.store13 -; RV64-NEXT: addi a2, sp, 128 -; RV64-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV64-NEXT: vse64.v v8, (a2) -; RV64-NEXT: ld a2, 168(sp) -; RV64-NEXT: sd a2, 0(a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a2, a1, 64 -; RV64-NEXT: beqz a2, .LBB15_8 -; RV64-NEXT: .LBB15_16: # %cond.store16 -; RV64-NEXT: addi a2, sp, 64 -; RV64-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; RV64-NEXT: vse64.v v8, (a2) -; RV64-NEXT: ld a2, 112(sp) -; RV64-NEXT: sd a2, 0(a0) -; RV64-NEXT: addi a0, a0, 8 -; RV64-NEXT: andi a1, a1, -128 -; RV64-NEXT: bnez a1, .LBB15_9 -; RV64-NEXT: j .LBB15_10 +; CHECK-LABEL: compressstore_v8i64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma +; CHECK-NEXT: vcompress.vm v12, v8, v0 +; CHECK-NEXT: vcpop.m a1, v0 +; CHECK-NEXT: vsetvli zero, a1, e64, m4, ta, ma +; CHECK-NEXT: vse64.v v12, (a0) +; CHECK-NEXT: ret call void @llvm.masked.compressstore.v8i64(<8 x i64> %v, ptr align 8 %base, <8 x i1> %mask) ret void } +;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +; RV32: {{.*}} +; RV64: {{.*}} diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-reduction-fp.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-reduction-fp.ll index 68740eec56e4c4c933e2fa0466caf865a474065a..7dcfb247d37cbe559ca2f827e2f81f810759b633 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-reduction-fp.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-reduction-fp.ll @@ -1599,15 +1599,16 @@ define float @vreduce_fminimum_v2f32(ptr %x) { ; CHECK-LABEL: vreduce_fminimum_v2f32: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vle32.v v9, (a0) -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vmfne.vv v9, v8, v8 +; CHECK-NEXT: vcpop.m a0, v9 +; CHECK-NEXT: beqz a0, .LBB99_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, 523264 +; CHECK-NEXT: fmv.w.x fa0, a0 +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB99_2: +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <2 x float>, ptr %x @@ -1619,15 +1620,8 @@ define float @vreduce_fminimum_v2f32_nonans(ptr %x) { ; CHECK-LABEL: vreduce_fminimum_v2f32_nonans: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vle32.v v9, (a0) -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <2 x float>, ptr %x @@ -1641,24 +1635,16 @@ define float @vreduce_fminimum_v4f32(ptr %x) { ; CHECK-LABEL: vreduce_fminimum_v4f32: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vle32.v v9, (a0) -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vmfne.vv v9, v8, v8 +; CHECK-NEXT: vcpop.m a0, v9 +; CHECK-NEXT: beqz a0, .LBB101_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, 523264 +; CHECK-NEXT: fmv.w.x fa0, a0 +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB101_2: +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <4 x float>, ptr %x @@ -1670,24 +1656,8 @@ define float @vreduce_fminimum_v4f32_nonans(ptr %x) { ; CHECK-LABEL: vreduce_fminimum_v4f32_nonans: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vle32.v v9, (a0) -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <4 x float>, ptr %x @@ -1701,33 +1671,16 @@ define float @vreduce_fminimum_v8f32(ptr %x) { ; CHECK-LABEL: vreduce_fminimum_v8f32: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vle32.v v10, (a0) -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vmfne.vv v10, v8, v8 +; CHECK-NEXT: vcpop.m a0, v10 +; CHECK-NEXT: beqz a0, .LBB103_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, 523264 +; CHECK-NEXT: fmv.w.x fa0, a0 +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB103_2: +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <8 x float>, ptr %x @@ -1739,33 +1692,8 @@ define float @vreduce_fminimum_v8f32_nonans(ptr %x) { ; CHECK-LABEL: vreduce_fminimum_v8f32_nonans: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vle32.v v10, (a0) -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <8 x float>, ptr %x @@ -1779,42 +1707,16 @@ define float @vreduce_fminimum_v16f32(ptr %x) { ; CHECK-LABEL: vreduce_fminimum_v16f32: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma -; CHECK-NEXT: vle32.v v12, (a0) -; CHECK-NEXT: vsetivli zero, 8, e32, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 8 -; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmin.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vmfne.vv v12, v8, v8 +; CHECK-NEXT: vcpop.m a0, v12 +; CHECK-NEXT: beqz a0, .LBB105_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, 523264 +; CHECK-NEXT: fmv.w.x fa0, a0 +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB105_2: +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <16 x float>, ptr %x @@ -1826,42 +1728,8 @@ define float @vreduce_fminimum_v16f32_nonans(ptr %x) { ; CHECK-LABEL: vreduce_fminimum_v16f32_nonans: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma -; CHECK-NEXT: vle32.v v12, (a0) -; CHECK-NEXT: vsetivli zero, 8, e32, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 8 -; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmin.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <16 x float>, ptr %x @@ -1876,51 +1744,16 @@ define float @vreduce_fminimum_v32f32(ptr %x) { ; CHECK: # %bb.0: ; CHECK-NEXT: li a1, 32 ; CHECK-NEXT: vsetvli zero, a1, e32, m8, ta, ma -; CHECK-NEXT: vle32.v v16, (a0) -; CHECK-NEXT: vsetivli zero, 16, e32, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 16 -; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmin.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 8, e32, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 8 -; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmin.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vmfne.vv v16, v8, v8 +; CHECK-NEXT: vcpop.m a0, v16 +; CHECK-NEXT: beqz a0, .LBB107_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, 523264 +; CHECK-NEXT: fmv.w.x fa0, a0 +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB107_2: +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <32 x float>, ptr %x @@ -1933,51 +1766,8 @@ define float @vreduce_fminimum_v32f32_nonans(ptr %x) { ; CHECK: # %bb.0: ; CHECK-NEXT: li a1, 32 ; CHECK-NEXT: vsetvli zero, a1, e32, m8, ta, ma -; CHECK-NEXT: vle32.v v16, (a0) -; CHECK-NEXT: vsetivli zero, 16, e32, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 16 -; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmin.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 8, e32, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 8 -; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmin.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <32 x float>, ptr %x @@ -2009,52 +1799,18 @@ define float @vreduce_fminimum_v64f32(ptr %x) { ; CHECK-NEXT: vmv1r.v v0, v7 ; CHECK-NEXT: vmerge.vvm v8, v24, v16, v0 ; CHECK-NEXT: vl8r.v v16, (a0) # Unknown-size Folded Reload -; CHECK-NEXT: vfmin.vv v16, v8, v16 -; CHECK-NEXT: vsetivli zero, 16, e32, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 16 -; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmin.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 8, e32, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 8 -; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmin.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vfmin.vv v8, v8, v16 +; CHECK-NEXT: vmfne.vv v16, v8, v8 +; CHECK-NEXT: vcpop.m a0, v16 +; CHECK-NEXT: beqz a0, .LBB109_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, 523264 +; CHECK-NEXT: fmv.w.x fa0, a0 +; CHECK-NEXT: j .LBB109_3 +; CHECK-NEXT: .LBB109_2: +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 +; CHECK-NEXT: .LBB109_3: ; CHECK-NEXT: csrr a0, vlenb ; CHECK-NEXT: slli a0, a0, 3 ; CHECK-NEXT: add sp, sp, a0 @@ -2073,51 +1829,8 @@ define float @vreduce_fminimum_v64f32_nonans(ptr %x) { ; CHECK-NEXT: vle32.v v8, (a0) ; CHECK-NEXT: addi a0, a0, 128 ; CHECK-NEXT: vle32.v v16, (a0) -; CHECK-NEXT: vfmin.vv v16, v8, v16 -; CHECK-NEXT: vsetivli zero, 16, e32, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 16 -; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmin.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 8, e32, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 8 -; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmin.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vfmin.vv v8, v8, v16 +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <64 x float>, ptr %x @@ -2208,52 +1921,18 @@ define float @vreduce_fminimum_v128f32(ptr %x) { ; CHECK-NEXT: add a0, sp, a0 ; CHECK-NEXT: addi a0, a0, 16 ; CHECK-NEXT: vl8r.v v16, (a0) # Unknown-size Folded Reload -; CHECK-NEXT: vfmin.vv v16, v8, v16 -; CHECK-NEXT: vsetivli zero, 16, e32, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 16 -; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmin.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 8, e32, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 8 -; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmin.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vfmin.vv v8, v8, v16 +; CHECK-NEXT: vmfne.vv v16, v8, v8 +; CHECK-NEXT: vcpop.m a0, v16 +; CHECK-NEXT: beqz a0, .LBB111_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, 523264 +; CHECK-NEXT: fmv.w.x fa0, a0 +; CHECK-NEXT: j .LBB111_3 +; CHECK-NEXT: .LBB111_2: +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 +; CHECK-NEXT: .LBB111_3: ; CHECK-NEXT: csrr a0, vlenb ; CHECK-NEXT: slli a0, a0, 3 ; CHECK-NEXT: mv a1, a0 @@ -2281,51 +1960,8 @@ define float @vreduce_fminimum_v128f32_nonans(ptr %x) { ; CHECK-NEXT: vle32.v v0, (a1) ; CHECK-NEXT: vfmin.vv v16, v24, v16 ; CHECK-NEXT: vfmin.vv v8, v8, v0 -; CHECK-NEXT: vfmin.vv v16, v8, v16 -; CHECK-NEXT: vsetivli zero, 16, e32, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 16 -; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmin.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 8, e32, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 8 -; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmin.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vfmin.vv v8, v8, v16 +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <128 x float>, ptr %x @@ -2339,15 +1975,16 @@ define double @vreduce_fminimum_v2f64(ptr %x) { ; CHECK-LABEL: vreduce_fminimum_v2f64: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vle64.v v9, (a0) -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v9, v8, v8 +; CHECK-NEXT: vcpop.m a0, v9 +; CHECK-NEXT: beqz a0, .LBB113_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, %hi(.LCPI113_0) +; CHECK-NEXT: fld fa0, %lo(.LCPI113_0)(a0) +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB113_2: +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <2 x double>, ptr %x @@ -2359,15 +1996,8 @@ define double @vreduce_fminimum_v2f64_nonans(ptr %x) { ; CHECK-LABEL: vreduce_fminimum_v2f64_nonans: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vle64.v v9, (a0) -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <2 x double>, ptr %x @@ -2381,24 +2011,16 @@ define double @vreduce_fminimum_v4f64(ptr %x) { ; CHECK-LABEL: vreduce_fminimum_v4f64: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vle64.v v10, (a0) -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v10, v8, v8 +; CHECK-NEXT: vcpop.m a0, v10 +; CHECK-NEXT: beqz a0, .LBB115_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, %hi(.LCPI115_0) +; CHECK-NEXT: fld fa0, %lo(.LCPI115_0)(a0) +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB115_2: +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <4 x double>, ptr %x @@ -2410,24 +2032,8 @@ define double @vreduce_fminimum_v4f64_nonans(ptr %x) { ; CHECK-LABEL: vreduce_fminimum_v4f64_nonans: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vle64.v v10, (a0) -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <4 x double>, ptr %x @@ -2441,33 +2047,16 @@ define double @vreduce_fminimum_v8f64(ptr %x) { ; CHECK-LABEL: vreduce_fminimum_v8f64: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; CHECK-NEXT: vle64.v v12, (a0) -; CHECK-NEXT: vsetivli zero, 4, e64, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 4 -; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmin.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v12, v8, v8 +; CHECK-NEXT: vcpop.m a0, v12 +; CHECK-NEXT: beqz a0, .LBB117_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, %hi(.LCPI117_0) +; CHECK-NEXT: fld fa0, %lo(.LCPI117_0)(a0) +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB117_2: +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <8 x double>, ptr %x @@ -2479,33 +2068,8 @@ define double @vreduce_fminimum_v8f64_nonans(ptr %x) { ; CHECK-LABEL: vreduce_fminimum_v8f64_nonans: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; CHECK-NEXT: vle64.v v12, (a0) -; CHECK-NEXT: vsetivli zero, 4, e64, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 4 -; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmin.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <8 x double>, ptr %x @@ -2519,42 +2083,16 @@ define double @vreduce_fminimum_v16f64(ptr %x) { ; CHECK-LABEL: vreduce_fminimum_v16f64: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 16, e64, m8, ta, ma -; CHECK-NEXT: vle64.v v16, (a0) -; CHECK-NEXT: vsetivli zero, 8, e64, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 8 -; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmin.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 4, e64, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 4 -; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmin.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v16, v8, v8 +; CHECK-NEXT: vcpop.m a0, v16 +; CHECK-NEXT: beqz a0, .LBB119_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, %hi(.LCPI119_0) +; CHECK-NEXT: fld fa0, %lo(.LCPI119_0)(a0) +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB119_2: +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <16 x double>, ptr %x @@ -2566,42 +2104,8 @@ define double @vreduce_fminimum_v16f64_nonans(ptr %x) { ; CHECK-LABEL: vreduce_fminimum_v16f64_nonans: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 16, e64, m8, ta, ma -; CHECK-NEXT: vle64.v v16, (a0) -; CHECK-NEXT: vsetivli zero, 8, e64, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 8 -; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmin.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 4, e64, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 4 -; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmin.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <16 x double>, ptr %x @@ -2632,43 +2136,18 @@ define double @vreduce_fminimum_v32f64(ptr %x) { ; CHECK-NEXT: vmv1r.v v0, v7 ; CHECK-NEXT: vmerge.vvm v8, v24, v16, v0 ; CHECK-NEXT: vl8r.v v16, (a0) # Unknown-size Folded Reload -; CHECK-NEXT: vfmin.vv v16, v8, v16 -; CHECK-NEXT: vsetivli zero, 8, e64, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 8 -; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmin.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 4, e64, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 4 -; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmin.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vfmin.vv v8, v8, v16 +; CHECK-NEXT: vmfne.vv v16, v8, v8 +; CHECK-NEXT: vcpop.m a0, v16 +; CHECK-NEXT: beqz a0, .LBB121_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, %hi(.LCPI121_0) +; CHECK-NEXT: fld fa0, %lo(.LCPI121_0)(a0) +; CHECK-NEXT: j .LBB121_3 +; CHECK-NEXT: .LBB121_2: +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 +; CHECK-NEXT: .LBB121_3: ; CHECK-NEXT: csrr a0, vlenb ; CHECK-NEXT: slli a0, a0, 3 ; CHECK-NEXT: add sp, sp, a0 @@ -2686,42 +2165,8 @@ define double @vreduce_fminimum_v32f64_nonans(ptr %x) { ; CHECK-NEXT: vle64.v v8, (a0) ; CHECK-NEXT: addi a0, a0, 128 ; CHECK-NEXT: vle64.v v16, (a0) -; CHECK-NEXT: vfmin.vv v16, v8, v16 -; CHECK-NEXT: vsetivli zero, 8, e64, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 8 -; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmin.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 4, e64, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 4 -; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmin.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vfmin.vv v8, v8, v16 +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <32 x double>, ptr %x @@ -2811,43 +2256,18 @@ define double @vreduce_fminimum_v64f64(ptr %x) { ; CHECK-NEXT: add a0, sp, a0 ; CHECK-NEXT: addi a0, a0, 16 ; CHECK-NEXT: vl8r.v v16, (a0) # Unknown-size Folded Reload -; CHECK-NEXT: vfmin.vv v16, v8, v16 -; CHECK-NEXT: vsetivli zero, 8, e64, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 8 -; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmin.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 4, e64, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 4 -; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmin.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vfmin.vv v8, v8, v16 +; CHECK-NEXT: vmfne.vv v16, v8, v8 +; CHECK-NEXT: vcpop.m a0, v16 +; CHECK-NEXT: beqz a0, .LBB123_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, %hi(.LCPI123_0) +; CHECK-NEXT: fld fa0, %lo(.LCPI123_0)(a0) +; CHECK-NEXT: j .LBB123_3 +; CHECK-NEXT: .LBB123_2: +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 +; CHECK-NEXT: .LBB123_3: ; CHECK-NEXT: csrr a0, vlenb ; CHECK-NEXT: slli a0, a0, 3 ; CHECK-NEXT: mv a1, a0 @@ -2874,42 +2294,8 @@ define double @vreduce_fminimum_v64f64_nonans(ptr %x) { ; CHECK-NEXT: vle64.v v0, (a1) ; CHECK-NEXT: vfmin.vv v16, v24, v16 ; CHECK-NEXT: vfmin.vv v8, v8, v0 -; CHECK-NEXT: vfmin.vv v16, v8, v16 -; CHECK-NEXT: vsetivli zero, 8, e64, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 8 -; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmin.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 4, e64, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 4 -; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmin.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmin.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmin.vv v8, v11, v8 +; CHECK-NEXT: vfmin.vv v8, v8, v16 +; CHECK-NEXT: vfredmin.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <64 x double>, ptr %x @@ -2923,15 +2309,16 @@ define float @vreduce_fmaximum_v2f32(ptr %x) { ; CHECK-LABEL: vreduce_fmaximum_v2f32: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vle32.v v9, (a0) -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vmfne.vv v9, v8, v8 +; CHECK-NEXT: vcpop.m a0, v9 +; CHECK-NEXT: beqz a0, .LBB125_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, 523264 +; CHECK-NEXT: fmv.w.x fa0, a0 +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB125_2: +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <2 x float>, ptr %x @@ -2943,15 +2330,8 @@ define float @vreduce_fmaximum_v2f32_nonans(ptr %x) { ; CHECK-LABEL: vreduce_fmaximum_v2f32_nonans: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vle32.v v9, (a0) -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <2 x float>, ptr %x @@ -2965,24 +2345,16 @@ define float @vreduce_fmaximum_v4f32(ptr %x) { ; CHECK-LABEL: vreduce_fmaximum_v4f32: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vle32.v v9, (a0) -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vmfne.vv v9, v8, v8 +; CHECK-NEXT: vcpop.m a0, v9 +; CHECK-NEXT: beqz a0, .LBB127_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, 523264 +; CHECK-NEXT: fmv.w.x fa0, a0 +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB127_2: +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <4 x float>, ptr %x @@ -2994,24 +2366,8 @@ define float @vreduce_fmaximum_v4f32_nonans(ptr %x) { ; CHECK-LABEL: vreduce_fmaximum_v4f32_nonans: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vle32.v v9, (a0) -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <4 x float>, ptr %x @@ -3025,33 +2381,16 @@ define float @vreduce_fmaximum_v8f32(ptr %x) { ; CHECK-LABEL: vreduce_fmaximum_v8f32: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vle32.v v10, (a0) -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vmfne.vv v10, v8, v8 +; CHECK-NEXT: vcpop.m a0, v10 +; CHECK-NEXT: beqz a0, .LBB129_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, 523264 +; CHECK-NEXT: fmv.w.x fa0, a0 +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB129_2: +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <8 x float>, ptr %x @@ -3063,33 +2402,8 @@ define float @vreduce_fmaximum_v8f32_nonans(ptr %x) { ; CHECK-LABEL: vreduce_fmaximum_v8f32_nonans: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vle32.v v10, (a0) -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <8 x float>, ptr %x @@ -3103,42 +2417,16 @@ define float @vreduce_fmaximum_v16f32(ptr %x) { ; CHECK-LABEL: vreduce_fmaximum_v16f32: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma -; CHECK-NEXT: vle32.v v12, (a0) -; CHECK-NEXT: vsetivli zero, 8, e32, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 8 -; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmax.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vmfne.vv v12, v8, v8 +; CHECK-NEXT: vcpop.m a0, v12 +; CHECK-NEXT: beqz a0, .LBB131_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, 523264 +; CHECK-NEXT: fmv.w.x fa0, a0 +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB131_2: +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <16 x float>, ptr %x @@ -3150,42 +2438,8 @@ define float @vreduce_fmaximum_v16f32_nonans(ptr %x) { ; CHECK-LABEL: vreduce_fmaximum_v16f32_nonans: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma -; CHECK-NEXT: vle32.v v12, (a0) -; CHECK-NEXT: vsetivli zero, 8, e32, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 8 -; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmax.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <16 x float>, ptr %x @@ -3200,51 +2454,16 @@ define float @vreduce_fmaximum_v32f32(ptr %x) { ; CHECK: # %bb.0: ; CHECK-NEXT: li a1, 32 ; CHECK-NEXT: vsetvli zero, a1, e32, m8, ta, ma -; CHECK-NEXT: vle32.v v16, (a0) -; CHECK-NEXT: vsetivli zero, 16, e32, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 16 -; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmax.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 8, e32, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 8 -; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmax.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vmfne.vv v16, v8, v8 +; CHECK-NEXT: vcpop.m a0, v16 +; CHECK-NEXT: beqz a0, .LBB133_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, 523264 +; CHECK-NEXT: fmv.w.x fa0, a0 +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB133_2: +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <32 x float>, ptr %x @@ -3257,51 +2476,8 @@ define float @vreduce_fmaximum_v32f32_nonans(ptr %x) { ; CHECK: # %bb.0: ; CHECK-NEXT: li a1, 32 ; CHECK-NEXT: vsetvli zero, a1, e32, m8, ta, ma -; CHECK-NEXT: vle32.v v16, (a0) -; CHECK-NEXT: vsetivli zero, 16, e32, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 16 -; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmax.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 8, e32, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 8 -; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmax.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vle32.v v8, (a0) +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <32 x float>, ptr %x @@ -3333,52 +2509,18 @@ define float @vreduce_fmaximum_v64f32(ptr %x) { ; CHECK-NEXT: vmv1r.v v0, v7 ; CHECK-NEXT: vmerge.vvm v8, v24, v16, v0 ; CHECK-NEXT: vl8r.v v16, (a0) # Unknown-size Folded Reload -; CHECK-NEXT: vfmax.vv v16, v8, v16 -; CHECK-NEXT: vsetivli zero, 16, e32, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 16 -; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmax.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 8, e32, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 8 -; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmax.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vfmax.vv v8, v8, v16 +; CHECK-NEXT: vmfne.vv v16, v8, v8 +; CHECK-NEXT: vcpop.m a0, v16 +; CHECK-NEXT: beqz a0, .LBB135_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, 523264 +; CHECK-NEXT: fmv.w.x fa0, a0 +; CHECK-NEXT: j .LBB135_3 +; CHECK-NEXT: .LBB135_2: +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 +; CHECK-NEXT: .LBB135_3: ; CHECK-NEXT: csrr a0, vlenb ; CHECK-NEXT: slli a0, a0, 3 ; CHECK-NEXT: add sp, sp, a0 @@ -3397,51 +2539,8 @@ define float @vreduce_fmaximum_v64f32_nonans(ptr %x) { ; CHECK-NEXT: vle32.v v8, (a0) ; CHECK-NEXT: addi a0, a0, 128 ; CHECK-NEXT: vle32.v v16, (a0) -; CHECK-NEXT: vfmax.vv v16, v8, v16 -; CHECK-NEXT: vsetivli zero, 16, e32, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 16 -; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmax.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 8, e32, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 8 -; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmax.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vfmax.vv v8, v8, v16 +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <64 x float>, ptr %x @@ -3532,52 +2631,18 @@ define float @vreduce_fmaximum_v128f32(ptr %x) { ; CHECK-NEXT: add a0, sp, a0 ; CHECK-NEXT: addi a0, a0, 16 ; CHECK-NEXT: vl8r.v v16, (a0) # Unknown-size Folded Reload -; CHECK-NEXT: vfmax.vv v16, v8, v16 -; CHECK-NEXT: vsetivli zero, 16, e32, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 16 -; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmax.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 8, e32, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 8 -; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmax.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vfmax.vv v8, v8, v16 +; CHECK-NEXT: vmfne.vv v16, v8, v8 +; CHECK-NEXT: vcpop.m a0, v16 +; CHECK-NEXT: beqz a0, .LBB137_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, 523264 +; CHECK-NEXT: fmv.w.x fa0, a0 +; CHECK-NEXT: j .LBB137_3 +; CHECK-NEXT: .LBB137_2: +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 +; CHECK-NEXT: .LBB137_3: ; CHECK-NEXT: csrr a0, vlenb ; CHECK-NEXT: slli a0, a0, 3 ; CHECK-NEXT: mv a1, a0 @@ -3605,51 +2670,8 @@ define float @vreduce_fmaximum_v128f32_nonans(ptr %x) { ; CHECK-NEXT: vle32.v v0, (a1) ; CHECK-NEXT: vfmax.vv v16, v24, v16 ; CHECK-NEXT: vfmax.vv v8, v8, v0 -; CHECK-NEXT: vfmax.vv v16, v8, v16 -; CHECK-NEXT: vsetivli zero, 16, e32, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 16 -; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmax.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 8, e32, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 8 -; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmax.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 4, e32, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 4 -; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vsetivli zero, 2, e32, m1, ta, ma -; CHECK-NEXT: vslidedown.vi v10, v9, 2 -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v9, v11, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e32, mf2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vfmax.vv v8, v8, v16 +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <128 x float>, ptr %x @@ -3663,15 +2685,16 @@ define double @vreduce_fmaximum_v2f64(ptr %x) { ; CHECK-LABEL: vreduce_fmaximum_v2f64: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vle64.v v9, (a0) -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v9, v8, v8 +; CHECK-NEXT: vcpop.m a0, v9 +; CHECK-NEXT: beqz a0, .LBB139_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, %hi(.LCPI139_0) +; CHECK-NEXT: fld fa0, %lo(.LCPI139_0)(a0) +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB139_2: +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <2 x double>, ptr %x @@ -3683,15 +2706,8 @@ define double @vreduce_fmaximum_v2f64_nonans(ptr %x) { ; CHECK-LABEL: vreduce_fmaximum_v2f64_nonans: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vle64.v v9, (a0) -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <2 x double>, ptr %x @@ -3705,24 +2721,16 @@ define double @vreduce_fmaximum_v4f64(ptr %x) { ; CHECK-LABEL: vreduce_fmaximum_v4f64: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vle64.v v10, (a0) -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v10, v8, v8 +; CHECK-NEXT: vcpop.m a0, v10 +; CHECK-NEXT: beqz a0, .LBB141_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, %hi(.LCPI141_0) +; CHECK-NEXT: fld fa0, %lo(.LCPI141_0)(a0) +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB141_2: +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <4 x double>, ptr %x @@ -3734,24 +2742,8 @@ define double @vreduce_fmaximum_v4f64_nonans(ptr %x) { ; CHECK-LABEL: vreduce_fmaximum_v4f64_nonans: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vle64.v v10, (a0) -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <4 x double>, ptr %x @@ -3765,33 +2757,16 @@ define double @vreduce_fmaximum_v8f64(ptr %x) { ; CHECK-LABEL: vreduce_fmaximum_v8f64: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; CHECK-NEXT: vle64.v v12, (a0) -; CHECK-NEXT: vsetivli zero, 4, e64, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 4 -; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmax.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v12, v8, v8 +; CHECK-NEXT: vcpop.m a0, v12 +; CHECK-NEXT: beqz a0, .LBB143_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, %hi(.LCPI143_0) +; CHECK-NEXT: fld fa0, %lo(.LCPI143_0)(a0) +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB143_2: +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <8 x double>, ptr %x @@ -3803,33 +2778,8 @@ define double @vreduce_fmaximum_v8f64_nonans(ptr %x) { ; CHECK-LABEL: vreduce_fmaximum_v8f64_nonans: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; CHECK-NEXT: vle64.v v12, (a0) -; CHECK-NEXT: vsetivli zero, 4, e64, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 4 -; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmax.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <8 x double>, ptr %x @@ -3843,42 +2793,16 @@ define double @vreduce_fmaximum_v16f64(ptr %x) { ; CHECK-LABEL: vreduce_fmaximum_v16f64: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 16, e64, m8, ta, ma -; CHECK-NEXT: vle64.v v16, (a0) -; CHECK-NEXT: vsetivli zero, 8, e64, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 8 -; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmax.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 4, e64, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 4 -; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmax.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v16, v8, v8 +; CHECK-NEXT: vcpop.m a0, v16 +; CHECK-NEXT: beqz a0, .LBB145_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, %hi(.LCPI145_0) +; CHECK-NEXT: fld fa0, %lo(.LCPI145_0)(a0) +; CHECK-NEXT: ret +; CHECK-NEXT: .LBB145_2: +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <16 x double>, ptr %x @@ -3890,42 +2814,8 @@ define double @vreduce_fmaximum_v16f64_nonans(ptr %x) { ; CHECK-LABEL: vreduce_fmaximum_v16f64_nonans: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetivli zero, 16, e64, m8, ta, ma -; CHECK-NEXT: vle64.v v16, (a0) -; CHECK-NEXT: vsetivli zero, 8, e64, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 8 -; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmax.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 4, e64, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 4 -; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmax.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <16 x double>, ptr %x @@ -3956,43 +2846,18 @@ define double @vreduce_fmaximum_v32f64(ptr %x) { ; CHECK-NEXT: vmv1r.v v0, v7 ; CHECK-NEXT: vmerge.vvm v8, v24, v16, v0 ; CHECK-NEXT: vl8r.v v16, (a0) # Unknown-size Folded Reload -; CHECK-NEXT: vfmax.vv v16, v8, v16 -; CHECK-NEXT: vsetivli zero, 8, e64, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 8 -; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmax.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 4, e64, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 4 -; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmax.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vfmax.vv v8, v8, v16 +; CHECK-NEXT: vmfne.vv v16, v8, v8 +; CHECK-NEXT: vcpop.m a0, v16 +; CHECK-NEXT: beqz a0, .LBB147_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, %hi(.LCPI147_0) +; CHECK-NEXT: fld fa0, %lo(.LCPI147_0)(a0) +; CHECK-NEXT: j .LBB147_3 +; CHECK-NEXT: .LBB147_2: +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 +; CHECK-NEXT: .LBB147_3: ; CHECK-NEXT: csrr a0, vlenb ; CHECK-NEXT: slli a0, a0, 3 ; CHECK-NEXT: add sp, sp, a0 @@ -4010,42 +2875,8 @@ define double @vreduce_fmaximum_v32f64_nonans(ptr %x) { ; CHECK-NEXT: vle64.v v8, (a0) ; CHECK-NEXT: addi a0, a0, 128 ; CHECK-NEXT: vle64.v v16, (a0) -; CHECK-NEXT: vfmax.vv v16, v8, v16 -; CHECK-NEXT: vsetivli zero, 8, e64, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 8 -; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmax.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 4, e64, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 4 -; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmax.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vfmax.vv v8, v8, v16 +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <32 x double>, ptr %x @@ -4135,43 +2966,18 @@ define double @vreduce_fmaximum_v64f64(ptr %x) { ; CHECK-NEXT: add a0, sp, a0 ; CHECK-NEXT: addi a0, a0, 16 ; CHECK-NEXT: vl8r.v v16, (a0) # Unknown-size Folded Reload -; CHECK-NEXT: vfmax.vv v16, v8, v16 -; CHECK-NEXT: vsetivli zero, 8, e64, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 8 -; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmax.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 4, e64, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 4 -; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmax.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vfmax.vv v8, v8, v16 +; CHECK-NEXT: vmfne.vv v16, v8, v8 +; CHECK-NEXT: vcpop.m a0, v16 +; CHECK-NEXT: beqz a0, .LBB149_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: lui a0, %hi(.LCPI149_0) +; CHECK-NEXT: fld fa0, %lo(.LCPI149_0)(a0) +; CHECK-NEXT: j .LBB149_3 +; CHECK-NEXT: .LBB149_2: +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 +; CHECK-NEXT: .LBB149_3: ; CHECK-NEXT: csrr a0, vlenb ; CHECK-NEXT: slli a0, a0, 3 ; CHECK-NEXT: mv a1, a0 @@ -4198,42 +3004,8 @@ define double @vreduce_fmaximum_v64f64_nonans(ptr %x) { ; CHECK-NEXT: vle64.v v0, (a1) ; CHECK-NEXT: vfmax.vv v16, v24, v16 ; CHECK-NEXT: vfmax.vv v8, v8, v0 -; CHECK-NEXT: vfmax.vv v16, v8, v16 -; CHECK-NEXT: vsetivli zero, 8, e64, m8, ta, ma -; CHECK-NEXT: vslidedown.vi v24, v16, 8 -; CHECK-NEXT: vsetivli zero, 8, e64, m4, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v24, v24 -; CHECK-NEXT: vmfeq.vv v8, v16, v16 -; CHECK-NEXT: vmerge.vvm v12, v24, v16, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v16, v24, v0 -; CHECK-NEXT: vfmax.vv v12, v12, v8 -; CHECK-NEXT: vsetivli zero, 4, e64, m4, ta, ma -; CHECK-NEXT: vslidedown.vi v16, v12, 4 -; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v16, v16 -; CHECK-NEXT: vmfeq.vv v8, v12, v12 -; CHECK-NEXT: vmerge.vvm v10, v16, v12, v0 -; CHECK-NEXT: vmv1r.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v12, v16, v0 -; CHECK-NEXT: vfmax.vv v10, v10, v8 -; CHECK-NEXT: vsetivli zero, 2, e64, m2, ta, ma -; CHECK-NEXT: vslidedown.vi v12, v10, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v12, v12 -; CHECK-NEXT: vmfeq.vv v8, v10, v10 -; CHECK-NEXT: vmerge.vvm v9, v12, v10, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v10, v12, v0 -; CHECK-NEXT: vfmax.vv v9, v9, v8 -; CHECK-NEXT: vslidedown.vi v10, v9, 1 -; CHECK-NEXT: vsetivli zero, 1, e64, m1, ta, ma -; CHECK-NEXT: vmfeq.vv v0, v10, v10 -; CHECK-NEXT: vmfeq.vv v8, v9, v9 -; CHECK-NEXT: vmerge.vvm v11, v10, v9, v0 -; CHECK-NEXT: vmv.v.v v0, v8 -; CHECK-NEXT: vmerge.vvm v8, v9, v10, v0 -; CHECK-NEXT: vfmax.vv v8, v11, v8 +; CHECK-NEXT: vfmax.vv v8, v8, v16 +; CHECK-NEXT: vfredmax.vs v8, v8, v8 ; CHECK-NEXT: vfmv.f.s fa0, v8 ; CHECK-NEXT: ret %v = load <64 x double>, ptr %x diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-sad.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-sad.ll new file mode 100644 index 0000000000000000000000000000000000000000..a4ab67f41595d4ea85ce4c9afc85b19da7df141e --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-sad.ll @@ -0,0 +1,189 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc < %s -mtriple=riscv32 -mattr=+v | FileCheck %s +; RUN: llc < %s -mtriple=riscv64 -mattr=+v | FileCheck %s + +define signext i16 @sad_4x8_as_i16(<4 x i8> %a, <4 x i8> %b) { +; CHECK-LABEL: sad_4x8_as_i16: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e16, mf2, ta, ma +; CHECK-NEXT: vmv.s.x v9, zero +; CHECK-NEXT: vsetvli zero, zero, e8, mf4, ta, ma +; CHECK-NEXT: vwredsumu.vs v8, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e16, mf2, ta, ma +; CHECK-NEXT: vmv.x.s a0, v8 +; CHECK-NEXT: ret +entry: + %1 = zext <4 x i8> %a to <4 x i16> + %3 = zext <4 x i8> %b to <4 x i16> + %4 = sub nsw <4 x i16> %1, %3 + %5 = tail call <4 x i16> @llvm.abs.v4i16(<4 x i16> %4, i1 true) + %6 = tail call i16 @llvm.vector.reduce.add.v4i16(<4 x i16> %5) + ret i16 %6 +} + +define signext i32 @sad_4x8_as_i32(<4 x i8> %a, <4 x i8> %b) { +; CHECK-LABEL: sad_4x8_as_i32: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vzext.vf4 v9, v8 +; CHECK-NEXT: vmv.s.x v8, zero +; CHECK-NEXT: vredsum.vs v8, v9, v8 +; CHECK-NEXT: vmv.x.s a0, v8 +; CHECK-NEXT: ret +entry: + %1 = zext <4 x i8> %a to <4 x i32> + %3 = zext <4 x i8> %b to <4 x i32> + %4 = sub nsw <4 x i32> %1, %3 + %5 = tail call <4 x i32> @llvm.abs.v4i32(<4 x i32> %4, i1 true) + %6 = tail call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %5) + ret i32 %6 +} + +define signext i16 @sad_16x8_as_i16(<16 x i8> %a, <16 x i8> %b) { +; CHECK-LABEL: sad_16x8_as_i16: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, ma +; CHECK-NEXT: vmv.s.x v9, zero +; CHECK-NEXT: vsetvli zero, zero, e8, m1, ta, ma +; CHECK-NEXT: vwredsumu.vs v8, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, ma +; CHECK-NEXT: vmv.x.s a0, v8 +; CHECK-NEXT: ret +entry: + %1 = zext <16 x i8> %a to <16 x i16> + %3 = zext <16 x i8> %b to <16 x i16> + %4 = sub nsw <16 x i16> %1, %3 + %5 = tail call <16 x i16> @llvm.abs.v16i16(<16 x i16> %4, i1 true) + %6 = tail call i16 @llvm.vector.reduce.add.v16i16(<16 x i16> %5) + ret i16 %6 +} + +define signext i32 @sad_16x8_as_i32(<16 x i8> %a, <16 x i8> %b) { +; CHECK-LABEL: sad_16x8_as_i32: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma +; CHECK-NEXT: vminu.vv v10, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf4 v12, v8 +; CHECK-NEXT: vmv.s.x v8, zero +; CHECK-NEXT: vredsum.vs v8, v12, v8 +; CHECK-NEXT: vmv.x.s a0, v8 +; CHECK-NEXT: ret +entry: + %1 = zext <16 x i8> %a to <16 x i32> + %3 = zext <16 x i8> %b to <16 x i32> + %4 = sub nsw <16 x i32> %1, %3 + %5 = tail call <16 x i32> @llvm.abs.v16i32(<16 x i32> %4, i1 true) + %6 = tail call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> %5) + ret i32 %6 +} + +define signext i32 @sad_2block_16xi8_as_i32(ptr %a, ptr %b, i32 signext %stridea, i32 signext %strideb) { +; CHECK-LABEL: sad_2block_16xi8_as_i32: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma +; CHECK-NEXT: vle8.v v8, (a0) +; CHECK-NEXT: vle8.v v9, (a1) +; CHECK-NEXT: add a0, a0, a2 +; CHECK-NEXT: add a1, a1, a3 +; CHECK-NEXT: vle8.v v10, (a0) +; CHECK-NEXT: vle8.v v11, (a1) +; CHECK-NEXT: vminu.vv v12, v8, v9 +; CHECK-NEXT: vmaxu.vv v8, v8, v9 +; CHECK-NEXT: vsub.vv v8, v8, v12 +; CHECK-NEXT: vminu.vv v9, v10, v11 +; CHECK-NEXT: add a0, a0, a2 +; CHECK-NEXT: add a1, a1, a3 +; CHECK-NEXT: vle8.v v12, (a0) +; CHECK-NEXT: vle8.v v13, (a1) +; CHECK-NEXT: vmaxu.vv v10, v10, v11 +; CHECK-NEXT: vsub.vv v9, v10, v9 +; CHECK-NEXT: vwaddu.vv v10, v9, v8 +; CHECK-NEXT: vminu.vv v8, v12, v13 +; CHECK-NEXT: vmaxu.vv v9, v12, v13 +; CHECK-NEXT: vsub.vv v8, v9, v8 +; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, ma +; CHECK-NEXT: add a0, a0, a2 +; CHECK-NEXT: add a1, a1, a3 +; CHECK-NEXT: vle8.v v9, (a0) +; CHECK-NEXT: vle8.v v12, (a1) +; CHECK-NEXT: vzext.vf2 v14, v8 +; CHECK-NEXT: vwaddu.vv v16, v14, v10 +; CHECK-NEXT: vsetvli zero, zero, e8, m1, ta, ma +; CHECK-NEXT: vminu.vv v8, v9, v12 +; CHECK-NEXT: vmaxu.vv v9, v9, v12 +; CHECK-NEXT: vsub.vv v8, v9, v8 +; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vwaddu.wv v16, v16, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vmv.s.x v8, zero +; CHECK-NEXT: vredsum.vs v8, v16, v8 +; CHECK-NEXT: vmv.x.s a0, v8 +; CHECK-NEXT: ret +entry: + %idx.ext8 = sext i32 %strideb to i64 + %idx.ext = sext i32 %stridea to i64 + %0 = load <16 x i8>, ptr %a, align 1 + %1 = zext <16 x i8> %0 to <16 x i32> + %2 = load <16 x i8>, ptr %b, align 1 + %3 = zext <16 x i8> %2 to <16 x i32> + %4 = sub nsw <16 x i32> %1, %3 + %5 = tail call <16 x i32> @llvm.abs.v16i32(<16 x i32> %4, i1 true) + %6 = tail call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> %5) + %add.ptr = getelementptr inbounds i8, ptr %a, i64 %idx.ext + %add.ptr9 = getelementptr inbounds i8, ptr %b, i64 %idx.ext8 + %7 = load <16 x i8>, ptr %add.ptr, align 1 + %8 = zext <16 x i8> %7 to <16 x i32> + %9 = load <16 x i8>, ptr %add.ptr9, align 1 + %10 = zext <16 x i8> %9 to <16 x i32> + %11 = sub nsw <16 x i32> %8, %10 + %12 = tail call <16 x i32> @llvm.abs.v16i32(<16 x i32> %11, i1 true) + %13 = tail call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> %12) + %op.rdx.1 = add i32 %13, %6 + %add.ptr.1 = getelementptr inbounds i8, ptr %add.ptr, i64 %idx.ext + %add.ptr9.1 = getelementptr inbounds i8, ptr %add.ptr9, i64 %idx.ext8 + %14 = load <16 x i8>, ptr %add.ptr.1, align 1 + %15 = zext <16 x i8> %14 to <16 x i32> + %16 = load <16 x i8>, ptr %add.ptr9.1, align 1 + %17 = zext <16 x i8> %16 to <16 x i32> + %18 = sub nsw <16 x i32> %15, %17 + %19 = tail call <16 x i32> @llvm.abs.v16i32(<16 x i32> %18, i1 true) + %20 = tail call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> %19) + %op.rdx.2 = add i32 %20, %op.rdx.1 + %add.ptr.2 = getelementptr inbounds i8, ptr %add.ptr.1, i64 %idx.ext + %add.ptr9.2 = getelementptr inbounds i8, ptr %add.ptr9.1, i64 %idx.ext8 + %21 = load <16 x i8>, ptr %add.ptr.2, align 1 + %22 = zext <16 x i8> %21 to <16 x i32> + %23 = load <16 x i8>, ptr %add.ptr9.2, align 1 + %24 = zext <16 x i8> %23 to <16 x i32> + %25 = sub nsw <16 x i32> %22, %24 + %26 = tail call <16 x i32> @llvm.abs.v16i32(<16 x i32> %25, i1 true) + %27 = tail call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> %26) + %op.rdx.3 = add i32 %27, %op.rdx.2 + ret i32 %op.rdx.3 +} + +declare <4 x i32> @llvm.abs.v4i32(<4 x i32>, i1) +declare i32 @llvm.vector.reduce.add.v4i32(<4 x i32>) +declare <4 x i16> @llvm.abs.v4i16(<4 x i16>, i1) +declare i16 @llvm.vector.reduce.add.v4i16(<4 x i16>) + +declare <16 x i32> @llvm.abs.v16i32(<16 x i32>, i1) +declare i32 @llvm.vector.reduce.add.v16i32(<16 x i32>) +declare <16 x i16> @llvm.abs.v16i16(<16 x i16>, i1) +declare i16 @llvm.vector.reduce.add.v16i16(<16 x i16>) diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-concat.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-concat.ll index 8474f95edd813f7c7fba91da6cda6a4382e214e5..98e6b8f2dd760adddb2a49195863bb1bfa31dfd3 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-concat.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-concat.ll @@ -5,59 +5,6 @@ ; RUN: llc < %s -mtriple=riscv32 -mattr=+v -riscv-v-vector-bits-max=128 -verify-machineinstrs | FileCheck -check-prefixes=CHECK,VLS %s ; RUN: llc < %s -mtriple=riscv64 -mattr=+v -riscv-v-vector-bits-max=128 -verify-machineinstrs | FileCheck -check-prefixes=CHECK,VLS %s -define <8 x i16> @concat_2xv4i16(<4 x i16> %a, <4 x i16> %b) { -; CHECK-LABEL: concat_2xv4i16: -; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma -; CHECK-NEXT: vslideup.vi v8, v9, 4 -; CHECK-NEXT: ret - %ab = shufflevector <4 x i16> %a, <4 x i16> %b, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> - ret <8 x i16> %ab -} - -define <8 x i16> @concat_4xv2i16(<2 x i16> %a, <2 x i16> %b, <2 x i16> %c, <2 x i16> %d) { -; CHECK-LABEL: concat_4xv2i16: -; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma -; CHECK-NEXT: vslideup.vi v10, v11, 2 -; CHECK-NEXT: vslideup.vi v8, v9, 2 -; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma -; CHECK-NEXT: vslideup.vi v8, v10, 4 -; CHECK-NEXT: ret - %ab = shufflevector <2 x i16> %a, <2 x i16> %b, <4 x i32> <i32 0, i32 1, i32 2, i32 3> - %cd = shufflevector <2 x i16> %c, <2 x i16> %d, <4 x i32> <i32 0, i32 1, i32 2, i32 3> - %abcd = shufflevector <4 x i16> %ab, <4 x i16> %cd, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> - ret <8 x i16> %abcd -} - -define <8 x i16> @concat_8xv1i16(<1 x i16> %a, <1 x i16> %b, <1 x i16> %c, <1 x i16> %d, <1 x i16> %e, <1 x i16> %f, <1 x i16> %g, <1 x i16> %h) { -; CHECK-LABEL: concat_8xv1i16: -; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 2, e16, mf2, tu, ma -; CHECK-NEXT: vslideup.vi v12, v13, 1 -; CHECK-NEXT: vsetivli zero, 3, e16, mf2, tu, ma -; CHECK-NEXT: vslideup.vi v12, v14, 2 -; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma -; CHECK-NEXT: vslideup.vi v12, v15, 3 -; CHECK-NEXT: vsetivli zero, 2, e16, mf2, tu, ma -; CHECK-NEXT: vslideup.vi v8, v9, 1 -; CHECK-NEXT: vsetivli zero, 3, e16, mf2, tu, ma -; CHECK-NEXT: vslideup.vi v8, v10, 2 -; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma -; CHECK-NEXT: vslideup.vi v8, v11, 3 -; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma -; CHECK-NEXT: vslideup.vi v8, v12, 4 -; CHECK-NEXT: ret - %ab = shufflevector <1 x i16> %a, <1 x i16> %b, <2 x i32> <i32 0, i32 1> - %cd = shufflevector <1 x i16> %c, <1 x i16> %d, <2 x i32> <i32 0, i32 1> - %abcd = shufflevector <2 x i16> %ab, <2 x i16> %cd, <4 x i32> <i32 0, i32 1, i32 2, i32 3> - %ef = shufflevector <1 x i16> %e, <1 x i16> %f, <2 x i32> <i32 0, i32 1> - %gh = shufflevector <1 x i16> %g, <1 x i16> %h, <2 x i32> <i32 0, i32 1> - %efgh = shufflevector <2 x i16> %ef, <2 x i16> %gh, <4 x i32> <i32 0, i32 1, i32 2, i32 3> - %abcdefgh = shufflevector <4 x i16> %abcd, <4 x i16> %efgh, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> - ret <8 x i16> %abcdefgh -} - define <8 x i32> @concat_2xv4i32(<4 x i32> %a, <4 x i32> %b) { ; CHECK-LABEL: concat_2xv4i32: ; CHECK: # %bb.0: diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-load-combine.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-load-combine.ll index 37902aa18732151729c5e11209ac36386daf0800..657d52354aa39ffb6dc2c1179d101dd4ebda80e6 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-load-combine.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-strided-load-combine.ll @@ -24,15 +24,18 @@ define void @widen_2xv4i16(ptr %x, ptr %z) { define void @widen_3xv4i16(ptr %x, ptr %z) { ; CHECK-LABEL: widen_3xv4i16: ; CHECK: # %bb.0: -; CHECK-NEXT: addi a2, a0, 16 ; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma -; CHECK-NEXT: vle16.v v8, (a2) -; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vle16.v v8, (a0) +; CHECK-NEXT: addi a2, a0, 8 +; CHECK-NEXT: vle16.v v9, (a2) +; CHECK-NEXT: addi a0, a0, 16 ; CHECK-NEXT: vle16.v v10, (a0) +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vslideup.vi v8, v9, 4 ; CHECK-NEXT: vsetivli zero, 16, e16, m2, ta, ma -; CHECK-NEXT: vslideup.vi v10, v8, 8 +; CHECK-NEXT: vslideup.vi v8, v10, 8 ; CHECK-NEXT: vsetivli zero, 12, e16, m2, ta, ma -; CHECK-NEXT: vse16.v v10, (a1) +; CHECK-NEXT: vse16.v v8, (a1) ; CHECK-NEXT: ret %a = load <4 x i16>, ptr %x %b.gep = getelementptr i8, ptr %x, i64 8 @@ -181,14 +184,20 @@ define void @strided_constant_0(ptr %x, ptr %z) { define void @strided_constant_mismatch_4xv4i16(ptr %x, ptr %z) { ; CHECK-LABEL: strided_constant_mismatch_4xv4i16: ; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; CHECK-NEXT: vle16.v v8, (a0) ; CHECK-NEXT: addi a2, a0, 6 -; CHECK-NEXT: li a3, 2 -; CHECK-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; CHECK-NEXT: vlse64.v v8, (a0), a3 -; CHECK-NEXT: vlse64.v v10, (a2), a3 -; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; CHECK-NEXT: vslideup.vi v8, v10, 2 -; CHECK-NEXT: vse64.v v8, (a1) +; CHECK-NEXT: vle16.v v10, (a2) +; CHECK-NEXT: addi a2, a0, 2 +; CHECK-NEXT: addi a0, a0, 8 +; CHECK-NEXT: vle16.v v9, (a0) +; CHECK-NEXT: vle16.v v11, (a2) +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vslideup.vi v10, v9, 4 +; CHECK-NEXT: vslideup.vi v8, v11, 4 +; CHECK-NEXT: vsetivli zero, 16, e16, m2, ta, ma +; CHECK-NEXT: vslideup.vi v8, v10, 8 +; CHECK-NEXT: vse16.v v8, (a1) ; CHECK-NEXT: ret %a = load <4 x i16>, ptr %x %b.gep = getelementptr i8, ptr %x, i64 2 @@ -244,38 +253,56 @@ define void @strided_runtime_4xv4i16(ptr %x, ptr %z, i64 %s) { define void @strided_runtime_mismatch_4xv4i16(ptr %x, ptr %z, i64 %s, i64 %t) { ; RV32-LABEL: strided_runtime_mismatch_4xv4i16: ; RV32: # %bb.0: -; RV32-NEXT: add a3, a0, a2 -; RV32-NEXT: add a3, a3, a4 -; RV32-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; RV32-NEXT: vlse64.v v8, (a0), a2 -; RV32-NEXT: vlse64.v v10, (a3), a2 -; RV32-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; RV32-NEXT: vslideup.vi v8, v10, 2 -; RV32-NEXT: vse64.v v8, (a1) +; RV32-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; RV32-NEXT: vle16.v v8, (a0) +; RV32-NEXT: add a0, a0, a2 +; RV32-NEXT: add a4, a0, a4 +; RV32-NEXT: vle16.v v10, (a4) +; RV32-NEXT: add a2, a4, a2 +; RV32-NEXT: vle16.v v9, (a2) +; RV32-NEXT: vle16.v v11, (a0) +; RV32-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; RV32-NEXT: vslideup.vi v10, v9, 4 +; RV32-NEXT: vslideup.vi v8, v11, 4 +; RV32-NEXT: vsetivli zero, 16, e16, m2, ta, ma +; RV32-NEXT: vslideup.vi v8, v10, 8 +; RV32-NEXT: vse16.v v8, (a1) ; RV32-NEXT: ret ; ; RV64-LABEL: strided_runtime_mismatch_4xv4i16: ; RV64: # %bb.0: -; RV64-NEXT: add a4, a0, a2 -; RV64-NEXT: add a3, a4, a3 -; RV64-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; RV64-NEXT: vlse64.v v8, (a0), a2 -; RV64-NEXT: vlse64.v v10, (a3), a2 -; RV64-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; RV64-NEXT: vslideup.vi v8, v10, 2 -; RV64-NEXT: vse64.v v8, (a1) +; RV64-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; RV64-NEXT: vle16.v v8, (a0) +; RV64-NEXT: add a0, a0, a2 +; RV64-NEXT: add a3, a0, a3 +; RV64-NEXT: vle16.v v10, (a3) +; RV64-NEXT: add a2, a3, a2 +; RV64-NEXT: vle16.v v9, (a2) +; RV64-NEXT: vle16.v v11, (a0) +; RV64-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; RV64-NEXT: vslideup.vi v10, v9, 4 +; RV64-NEXT: vslideup.vi v8, v11, 4 +; RV64-NEXT: vsetivli zero, 16, e16, m2, ta, ma +; RV64-NEXT: vslideup.vi v8, v10, 8 +; RV64-NEXT: vse16.v v8, (a1) ; RV64-NEXT: ret ; ; ZVE64F-LABEL: strided_runtime_mismatch_4xv4i16: ; ZVE64F: # %bb.0: -; ZVE64F-NEXT: add a4, a0, a2 -; ZVE64F-NEXT: add a3, a4, a3 -; ZVE64F-NEXT: vsetivli zero, 2, e64, m1, ta, ma -; ZVE64F-NEXT: vlse64.v v8, (a0), a2 -; ZVE64F-NEXT: vlse64.v v10, (a3), a2 -; ZVE64F-NEXT: vsetivli zero, 4, e64, m2, ta, ma -; ZVE64F-NEXT: vslideup.vi v8, v10, 2 -; ZVE64F-NEXT: vse64.v v8, (a1) +; ZVE64F-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; ZVE64F-NEXT: vle16.v v8, (a0) +; ZVE64F-NEXT: add a0, a0, a2 +; ZVE64F-NEXT: add a3, a0, a3 +; ZVE64F-NEXT: vle16.v v10, (a3) +; ZVE64F-NEXT: add a2, a3, a2 +; ZVE64F-NEXT: vle16.v v9, (a2) +; ZVE64F-NEXT: vle16.v v11, (a0) +; ZVE64F-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; ZVE64F-NEXT: vslideup.vi v10, v9, 4 +; ZVE64F-NEXT: vslideup.vi v8, v11, 4 +; ZVE64F-NEXT: vsetivli zero, 16, e16, m2, ta, ma +; ZVE64F-NEXT: vslideup.vi v8, v10, 8 +; ZVE64F-NEXT: vse16.v v8, (a1) ; ZVE64F-NEXT: ret %a = load <4 x i16>, ptr %x %b.gep = getelementptr i8, ptr %x, i64 %s @@ -534,3 +561,28 @@ define void @reverse_strided_runtime_4xv2f32(ptr %x, ptr %z, i64 %s) { store <8 x float> %e.2, ptr %z ret void } + +; The middle end sometimes produces this pattern of shuffles, where the +; intermediate shuffles are the full result vector size padded with poison +; elements. +define <16 x i8> @widen_4xv4i8_immediate_expand(ptr %p, i64 %s) { +; CHECK-LABEL: widen_4xv4i8_immediate_expand: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-NEXT: vlse32.v v8, (a0), a1 +; CHECK-NEXT: ret + %a = load <4 x i8>, ptr %p + %b.ptr = getelementptr i8, ptr %p, i64 %s + %b = load <4 x i8>, ptr %b.ptr + %c.ptr = getelementptr i8, ptr %b.ptr, i64 %s + %c = load <4 x i8>, ptr %c.ptr + %d.ptr = getelementptr i8, ptr %c.ptr, i64 %s + %d = load <4 x i8>, ptr %d.ptr + + %ab = shufflevector <4 x i8> %a, <4 x i8> %b, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison> + %cx = shufflevector <4 x i8> %c, <4 x i8> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison> + %dx = shufflevector <4 x i8> %d, <4 x i8> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison> + %abcx = shufflevector <16 x i8> %ab, <16 x i8> %cx, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 16, i32 17, i32 18, i32 19, i32 poison, i32 poison, i32 poison, i32 poison> + %abcd = shufflevector <16 x i8> %abcx, <16 x i8> %dx, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 16, i32 17, i32 18, i32 19> + ret <16 x i8> %abcd +} diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwaddu.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwaddu.ll index 57a72c639b334cae7b60df8b9f37616b989455cf..bc0bf5dd76ad45dab23097fbb37a6cbacd27fe35 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwaddu.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwaddu.ll @@ -385,12 +385,12 @@ define <32 x i64> @vwaddu_v32i64(ptr %x, ptr %y) nounwind { define <2 x i32> @vwaddu_v2i32_v2i8(ptr %x, ptr %y) { ; CHECK-LABEL: vwaddu_v2i32_v2i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 2, e16, mf4, ta, ma +; CHECK-NEXT: vsetivli zero, 2, e8, mf8, ta, ma ; CHECK-NEXT: vle8.v v8, (a0) ; CHECK-NEXT: vle8.v v9, (a1) -; CHECK-NEXT: vzext.vf2 v10, v8 -; CHECK-NEXT: vzext.vf2 v11, v9 -; CHECK-NEXT: vwaddu.vv v8, v10, v11 +; CHECK-NEXT: vwaddu.vv v10, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v10 ; CHECK-NEXT: ret %a = load <2 x i8>, ptr %x %b = load <2 x i8>, ptr %y @@ -912,12 +912,12 @@ define <4 x i64> @crash(<4 x i16> %x, <4 x i16> %y) { define <2 x i32> @vwaddu_v2i32_of_v2i8(ptr %x, ptr %y) { ; CHECK-LABEL: vwaddu_v2i32_of_v2i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 2, e16, mf4, ta, ma +; CHECK-NEXT: vsetivli zero, 2, e8, mf8, ta, ma ; CHECK-NEXT: vle8.v v8, (a0) ; CHECK-NEXT: vle8.v v9, (a1) -; CHECK-NEXT: vzext.vf2 v10, v8 -; CHECK-NEXT: vzext.vf2 v11, v9 -; CHECK-NEXT: vwaddu.vv v8, v10, v11 +; CHECK-NEXT: vwaddu.vv v10, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v10 ; CHECK-NEXT: ret %a = load <2 x i8>, ptr %x %b = load <2 x i8>, ptr %y @@ -930,12 +930,12 @@ define <2 x i32> @vwaddu_v2i32_of_v2i8(ptr %x, ptr %y) { define <2 x i64> @vwaddu_v2i64_of_v2i8(ptr %x, ptr %y) { ; CHECK-LABEL: vwaddu_v2i64_of_v2i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma +; CHECK-NEXT: vsetivli zero, 2, e8, mf8, ta, ma ; CHECK-NEXT: vle8.v v8, (a0) ; CHECK-NEXT: vle8.v v9, (a1) -; CHECK-NEXT: vzext.vf4 v10, v8 -; CHECK-NEXT: vzext.vf4 v11, v9 -; CHECK-NEXT: vwaddu.vv v8, v10, v11 +; CHECK-NEXT: vwaddu.vv v10, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma +; CHECK-NEXT: vzext.vf4 v8, v10 ; CHECK-NEXT: ret %a = load <2 x i8>, ptr %x %b = load <2 x i8>, ptr %y @@ -948,12 +948,12 @@ define <2 x i64> @vwaddu_v2i64_of_v2i8(ptr %x, ptr %y) { define <2 x i64> @vwaddu_v2i64_of_v2i16(ptr %x, ptr %y) { ; CHECK-LABEL: vwaddu_v2i64_of_v2i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 2, e32, mf2, ta, ma +; CHECK-NEXT: vsetivli zero, 2, e16, mf4, ta, ma ; CHECK-NEXT: vle16.v v8, (a0) ; CHECK-NEXT: vle16.v v9, (a1) -; CHECK-NEXT: vzext.vf2 v10, v8 -; CHECK-NEXT: vzext.vf2 v11, v9 -; CHECK-NEXT: vwaddu.vv v8, v10, v11 +; CHECK-NEXT: vwaddu.vv v10, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v10 ; CHECK-NEXT: ret %a = load <2 x i16>, ptr %x %b = load <2 x i16>, ptr %y diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwmulu.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwmulu.ll index bff7ef86c289600b625fba0bdff56113e48164cb..b97c9654ad3cb47988d9b286d5f12b94e7416f2e 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwmulu.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwmulu.ll @@ -391,12 +391,12 @@ define <32 x i64> @vwmulu_v32i64(ptr %x, ptr %y) { define <2 x i32> @vwmulu_v2i32_v2i8(ptr %x, ptr %y) { ; CHECK-LABEL: vwmulu_v2i32_v2i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetivli zero, 2, e16, mf4, ta, ma +; CHECK-NEXT: vsetivli zero, 2, e8, mf8, ta, ma ; CHECK-NEXT: vle8.v v8, (a0) ; CHECK-NEXT: vle8.v v9, (a1) -; CHECK-NEXT: vzext.vf2 v10, v8 -; CHECK-NEXT: vzext.vf2 v11, v9 -; CHECK-NEXT: vwmulu.vv v8, v10, v11 +; CHECK-NEXT: vwmulu.vv v10, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v10 ; CHECK-NEXT: ret %a = load <2 x i8>, ptr %x %b = load <2 x i8>, ptr %y diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwsll.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwsll.ll new file mode 100644 index 0000000000000000000000000000000000000000..f5305a1c36de16755ede8e1e14587fd5120673b1 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vwsll.ll @@ -0,0 +1,920 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc -mtriple=riscv32 -mattr=+v -verify-machineinstrs < %s | FileCheck %s +; RUN: llc -mtriple=riscv64 -mattr=+v -verify-machineinstrs < %s | FileCheck %s +; RUN: llc -mtriple=riscv32 -mattr=+v,+zvbb -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK-ZVBB +; RUN: llc -mtriple=riscv64 -mattr=+v,+zvbb -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK-ZVBB + +; ============================================================================== +; i32 -> i64 +; ============================================================================== + +define <4 x i64> @vwsll_vv_v4i64_sext(<4 x i32> %a, <4 x i32> %b) { +; CHECK-LABEL: vwsll_vv_v4i64_sext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf2 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vv_v4i64_sext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vsext.vf2 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %x = zext <4 x i32> %a to <4 x i64> + %y = sext <4 x i32> %b to <4 x i64> + %z = shl <4 x i64> %x, %y + ret <4 x i64> %z +} + +define <4 x i64> @vwsll_vv_v4i64_zext(<4 x i32> %a, <4 x i32> %b) { +; CHECK-LABEL: vwsll_vv_v4i64_zext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vzext.vf2 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vv_v4i64_zext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vzext.vf2 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %x = zext <4 x i32> %a to <4 x i64> + %y = zext <4 x i32> %b to <4 x i64> + %z = shl <4 x i64> %x, %y + ret <4 x i64> %z +} + +define <4 x i64> @vwsll_vx_i64_v4i64(<4 x i32> %a, i64 %b) { +; CHECK-LABEL: vwsll_vx_i64_v4i64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vsll.vx v8, v10, a0 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i64_v4i64: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vsll.vx v8, v10, a0 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <4 x i64> poison, i64 %b, i32 0 + %splat = shufflevector <4 x i64> %head, <4 x i64> poison, <4 x i32> zeroinitializer + %x = zext <4 x i32> %a to <4 x i64> + %z = shl <4 x i64> %x, %splat + ret <4 x i64> %z +} + +define <4 x i64> @vwsll_vx_i32_v4i64_sext(<4 x i32> %a, i32 %b) { +; CHECK-LABEL: vwsll_vx_i32_v4i64_sext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf2 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i32_v4i64_sext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v9, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vsext.vf2 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <4 x i32> poison, i32 %b, i32 0 + %splat = shufflevector <4 x i32> %head, <4 x i32> poison, <4 x i32> zeroinitializer + %x = zext <4 x i32> %a to <4 x i64> + %y = sext <4 x i32> %splat to <4 x i64> + %z = shl <4 x i64> %x, %y + ret <4 x i64> %z +} + +define <4 x i64> @vwsll_vx_i32_v4i64_zext(<4 x i32> %a, i32 %b) { +; CHECK-LABEL: vwsll_vx_i32_v4i64_zext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vzext.vf2 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i32_v4i64_zext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v9, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vzext.vf2 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <4 x i32> poison, i32 %b, i32 0 + %splat = shufflevector <4 x i32> %head, <4 x i32> poison, <4 x i32> zeroinitializer + %x = zext <4 x i32> %a to <4 x i64> + %y = zext <4 x i32> %splat to <4 x i64> + %z = shl <4 x i64> %x, %y + ret <4 x i64> %z +} + +define <4 x i64> @vwsll_vx_i16_v4i64_sext(<4 x i32> %a, i16 %b) { +; CHECK-LABEL: vwsll_vx_i16_v4i64_sext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf4 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i16_v4i64_sext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v9, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vsext.vf4 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <4 x i16> poison, i16 %b, i32 0 + %splat = shufflevector <4 x i16> %head, <4 x i16> poison, <4 x i32> zeroinitializer + %x = zext <4 x i32> %a to <4 x i64> + %y = sext <4 x i16> %splat to <4 x i64> + %z = shl <4 x i64> %x, %y + ret <4 x i64> %z +} + +define <4 x i64> @vwsll_vx_i16_v4i64_zext(<4 x i32> %a, i16 %b) { +; CHECK-LABEL: vwsll_vx_i16_v4i64_zext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vzext.vf4 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i16_v4i64_zext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v9, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vzext.vf4 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <4 x i16> poison, i16 %b, i32 0 + %splat = shufflevector <4 x i16> %head, <4 x i16> poison, <4 x i32> zeroinitializer + %x = zext <4 x i32> %a to <4 x i64> + %y = zext <4 x i16> %splat to <4 x i64> + %z = shl <4 x i64> %x, %y + ret <4 x i64> %z +} + +define <4 x i64> @vwsll_vx_i8_v4i64_sext(<4 x i32> %a, i8 %b) { +; CHECK-LABEL: vwsll_vx_i8_v4i64_sext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf8 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i8_v4i64_sext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v9, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vsext.vf8 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <4 x i8> poison, i8 %b, i32 0 + %splat = shufflevector <4 x i8> %head, <4 x i8> poison, <4 x i32> zeroinitializer + %x = zext <4 x i32> %a to <4 x i64> + %y = sext <4 x i8> %splat to <4 x i64> + %z = shl <4 x i64> %x, %y + ret <4 x i64> %z +} + +define <4 x i64> @vwsll_vx_i8_v4i64_zext(<4 x i32> %a, i8 %b) { +; CHECK-LABEL: vwsll_vx_i8_v4i64_zext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vzext.vf8 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i8_v4i64_zext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v9, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vzext.vf8 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <4 x i8> poison, i8 %b, i32 0 + %splat = shufflevector <4 x i8> %head, <4 x i8> poison, <4 x i32> zeroinitializer + %x = zext <4 x i32> %a to <4 x i64> + %y = zext <4 x i8> %splat to <4 x i64> + %z = shl <4 x i64> %x, %y + ret <4 x i64> %z +} + +define <4 x i64> @vwsll_vi_v4i64(<4 x i32> %a) { +; CHECK-LABEL: vwsll_vi_v4i64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vsll.vi v8, v10, 2 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vi_v4i64: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vsll.vi v8, v10, 2 +; CHECK-ZVBB-NEXT: ret + %x = zext <4 x i32> %a to <4 x i64> + %z = shl <4 x i64> %x, splat (i64 2) + ret <4 x i64> %z +} + +; ============================================================================== +; i16 -> i32 +; ============================================================================== + +define <8 x i32> @vwsll_vv_v8i32_sext(<8 x i16> %a, <8 x i16> %b) { +; CHECK-LABEL: vwsll_vv_v8i32_sext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf2 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vv_v8i32_sext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vsext.vf2 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %x = zext <8 x i16> %a to <8 x i32> + %y = sext <8 x i16> %b to <8 x i32> + %z = shl <8 x i32> %x, %y + ret <8 x i32> %z +} + +define <8 x i32> @vwsll_vv_v8i32_zext(<8 x i16> %a, <8 x i16> %b) { +; CHECK-LABEL: vwsll_vv_v8i32_zext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vzext.vf2 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vv_v8i32_zext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vzext.vf2 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %x = zext <8 x i16> %a to <8 x i32> + %y = zext <8 x i16> %b to <8 x i32> + %z = shl <8 x i32> %x, %y + ret <8 x i32> %z +} + +define <8 x i32> @vwsll_vx_i64_v8i32(<8 x i16> %a, i64 %b) { +; CHECK-LABEL: vwsll_vx_i64_v8i32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vsll.vx v8, v10, a0 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i64_v8i32: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vsll.vx v8, v10, a0 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <8 x i64> poison, i64 %b, i32 0 + %splat = shufflevector <8 x i64> %head, <8 x i64> poison, <8 x i32> zeroinitializer + %x = zext <8 x i16> %a to <8 x i32> + %y = trunc <8 x i64> %splat to <8 x i32> + %z = shl <8 x i32> %x, %y + ret <8 x i32> %z +} + +define <8 x i32> @vwsll_vx_i32_v8i32(<8 x i16> %a, i32 %b) { +; CHECK-LABEL: vwsll_vx_i32_v8i32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vsll.vx v8, v10, a0 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i32_v8i32: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vsll.vx v8, v10, a0 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <8 x i32> poison, i32 %b, i32 0 + %splat = shufflevector <8 x i32> %head, <8 x i32> poison, <8 x i32> zeroinitializer + %x = zext <8 x i16> %a to <8 x i32> + %z = shl <8 x i32> %x, %splat + ret <8 x i32> %z +} + +define <8 x i32> @vwsll_vx_i16_v8i32_sext(<8 x i16> %a, i16 %b) { +; CHECK-LABEL: vwsll_vx_i16_v8i32_sext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf2 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i16_v8i32_sext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v9, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vsext.vf2 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <8 x i16> poison, i16 %b, i32 0 + %splat = shufflevector <8 x i16> %head, <8 x i16> poison, <8 x i32> zeroinitializer + %x = zext <8 x i16> %a to <8 x i32> + %y = sext <8 x i16> %splat to <8 x i32> + %z = shl <8 x i32> %x, %y + ret <8 x i32> %z +} + +define <8 x i32> @vwsll_vx_i16_v8i32_zext(<8 x i16> %a, i16 %b) { +; CHECK-LABEL: vwsll_vx_i16_v8i32_zext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vzext.vf2 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i16_v8i32_zext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 8, e16, m1, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v9, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vzext.vf2 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <8 x i16> poison, i16 %b, i32 0 + %splat = shufflevector <8 x i16> %head, <8 x i16> poison, <8 x i32> zeroinitializer + %x = zext <8 x i16> %a to <8 x i32> + %y = zext <8 x i16> %splat to <8 x i32> + %z = shl <8 x i32> %x, %y + ret <8 x i32> %z +} + +define <8 x i32> @vwsll_vx_i8_v8i32_sext(<8 x i16> %a, i8 %b) { +; CHECK-LABEL: vwsll_vx_i8_v8i32_sext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma +; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf4 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i8_v8i32_sext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 8, e8, mf2, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v9, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vsext.vf4 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <8 x i8> poison, i8 %b, i32 0 + %splat = shufflevector <8 x i8> %head, <8 x i8> poison, <8 x i32> zeroinitializer + %x = zext <8 x i16> %a to <8 x i32> + %y = sext <8 x i8> %splat to <8 x i32> + %z = shl <8 x i32> %x, %y + ret <8 x i32> %z +} + +define <8 x i32> @vwsll_vx_i8_v8i32_zext(<8 x i16> %a, i8 %b) { +; CHECK-LABEL: vwsll_vx_i8_v8i32_zext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma +; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vzext.vf4 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i8_v8i32_zext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 8, e8, mf2, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v9, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vzext.vf4 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <8 x i8> poison, i8 %b, i32 0 + %splat = shufflevector <8 x i8> %head, <8 x i8> poison, <8 x i32> zeroinitializer + %x = zext <8 x i16> %a to <8 x i32> + %y = zext <8 x i8> %splat to <8 x i32> + %z = shl <8 x i32> %x, %y + ret <8 x i32> %z +} + +define <8 x i32> @vwsll_vi_v8i32(<8 x i16> %a) { +; CHECK-LABEL: vwsll_vi_v8i32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vsll.vi v8, v10, 2 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vi_v8i32: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 8, e32, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vsll.vi v8, v10, 2 +; CHECK-ZVBB-NEXT: ret + %x = zext <8 x i16> %a to <8 x i32> + %z = shl <8 x i32> %x, splat (i32 2) + ret <8 x i32> %z +} + +; ============================================================================== +; i8 -> i16 +; ============================================================================== + +define <16 x i16> @vwsll_vv_v16i16_sext(<16 x i8> %a, <16 x i8> %b) { +; CHECK-LABEL: vwsll_vv_v16i16_sext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 16, e16, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf2 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vv_v16i16_sext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 16, e16, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vsext.vf2 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %x = zext <16 x i8> %a to <16 x i16> + %y = sext <16 x i8> %b to <16 x i16> + %z = shl <16 x i16> %x, %y + ret <16 x i16> %z +} + +define <16 x i16> @vwsll_vv_v16i16_zext(<16 x i8> %a, <16 x i8> %b) { +; CHECK-LABEL: vwsll_vv_v16i16_zext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 16, e16, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vzext.vf2 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vv_v16i16_zext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 16, e16, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vzext.vf2 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %x = zext <16 x i8> %a to <16 x i16> + %y = zext <16 x i8> %b to <16 x i16> + %z = shl <16 x i16> %x, %y + ret <16 x i16> %z +} + +define <16 x i16> @vwsll_vx_i64_v16i16(<16 x i8> %a, i64 %b) { + %head = insertelement <8 x i64> poison, i64 %b, i32 0 + %splat = shufflevector <8 x i64> %head, <8 x i64> poison, <16 x i32> zeroinitializer + %x = zext <16 x i8> %a to <16 x i16> + %y = trunc <16 x i64> %splat to <16 x i16> + %z = shl <16 x i16> %x, %y + ret <16 x i16> %z +} + +define <16 x i16> @vwsll_vx_i32_v16i16(<16 x i8> %a, i32 %b) { +; CHECK-LABEL: vwsll_vx_i32_v16i16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 16, e32, m4, ta, ma +; CHECK-NEXT: vmv.v.x v12, a0 +; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vnsrl.wi v8, v12, 0 +; CHECK-NEXT: vsll.vv v8, v10, v8 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i32_v16i16: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 16, e32, m4, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v12, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e16, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vnsrl.wi v8, v12, 0 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v8 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <16 x i32> poison, i32 %b, i32 0 + %splat = shufflevector <16 x i32> %head, <16 x i32> poison, <16 x i32> zeroinitializer + %x = zext <16 x i8> %a to <16 x i16> + %y = trunc <16 x i32> %splat to <16 x i16> + %z = shl <16 x i16> %x, %y + ret <16 x i16> %z +} + +define <16 x i16> @vwsll_vx_i16_v16i16(<16 x i8> %a, i16 %b) { +; CHECK-LABEL: vwsll_vx_i16_v16i16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 16, e16, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vsll.vx v8, v10, a0 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i16_v16i16: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 16, e16, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vsll.vx v8, v10, a0 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <16 x i16> poison, i16 %b, i32 0 + %splat = shufflevector <16 x i16> %head, <16 x i16> poison, <16 x i32> zeroinitializer + %x = zext <16 x i8> %a to <16 x i16> + %z = shl <16 x i16> %x, %splat + ret <16 x i16> %z +} + +define <16 x i16> @vwsll_vx_i8_v16i16_sext(<16 x i8> %a, i8 %b) { +; CHECK-LABEL: vwsll_vx_i8_v16i16_sext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma +; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf2 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i8_v16i16_sext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 16, e8, m1, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v9, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e16, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vsext.vf2 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <16 x i8> poison, i8 %b, i32 0 + %splat = shufflevector <16 x i8> %head, <16 x i8> poison, <16 x i32> zeroinitializer + %x = zext <16 x i8> %a to <16 x i16> + %y = sext <16 x i8> %splat to <16 x i16> + %z = shl <16 x i16> %x, %y + ret <16 x i16> %z +} + +define <16 x i16> @vwsll_vx_i8_v16i16_zext(<16 x i8> %a, i8 %b) { +; CHECK-LABEL: vwsll_vx_i8_v16i16_zext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma +; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vzext.vf2 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i8_v16i16_zext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 16, e8, m1, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v9, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e16, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vzext.vf2 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <16 x i8> poison, i8 %b, i32 0 + %splat = shufflevector <16 x i8> %head, <16 x i8> poison, <16 x i32> zeroinitializer + %x = zext <16 x i8> %a to <16 x i16> + %y = zext <16 x i8> %splat to <16 x i16> + %z = shl <16 x i16> %x, %y + ret <16 x i16> %z +} + +define <16 x i16> @vwsll_vi_v16i16(<16 x i8> %a) { +; CHECK-LABEL: vwsll_vi_v16i16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 16, e16, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vsll.vi v8, v10, 2 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vi_v16i16: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 16, e16, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf2 v10, v8 +; CHECK-ZVBB-NEXT: vsll.vi v8, v10, 2 +; CHECK-ZVBB-NEXT: ret + %x = zext <16 x i8> %a to <16 x i16> + %z = shl <16 x i16> %x, splat (i16 2) + ret <16 x i16> %z +} + +; ============================================================================== +; i8 -> i64 +; ============================================================================== + +define <4 x i64> @vwsll_vv_v4i64_v4i8_sext(<4 x i8> %a, <4 x i8> %b) { +; CHECK-LABEL: vwsll_vv_v4i64_v4i8_sext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf8 v10, v8 +; CHECK-NEXT: vsext.vf8 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vv_v4i64_v4i8_sext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf8 v10, v8 +; CHECK-ZVBB-NEXT: vsext.vf8 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %x = zext <4 x i8> %a to <4 x i64> + %y = sext <4 x i8> %b to <4 x i64> + %z = shl <4 x i64> %x, %y + ret <4 x i64> %z +} + +define <4 x i64> @vwsll_vv_v4i64_v4i8_zext(<4 x i8> %a, <4 x i8> %b) { +; CHECK-LABEL: vwsll_vv_v4i64_v4i8_zext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf8 v10, v8 +; CHECK-NEXT: vzext.vf8 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vv_v4i64_v4i8_zext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf8 v10, v8 +; CHECK-ZVBB-NEXT: vzext.vf8 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %x = zext <4 x i8> %a to <4 x i64> + %y = zext <4 x i8> %b to <4 x i64> + %z = shl <4 x i64> %x, %y + ret <4 x i64> %z +} + +define <4 x i64> @vwsll_vx_i64_v4i64_v4i8(<4 x i8> %a, i64 %b) { +; CHECK-LABEL: vwsll_vx_i64_v4i64_v4i8: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf8 v10, v8 +; CHECK-NEXT: vsll.vx v8, v10, a0 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i64_v4i64_v4i8: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf8 v10, v8 +; CHECK-ZVBB-NEXT: vsll.vx v8, v10, a0 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <4 x i64> poison, i64 %b, i32 0 + %splat = shufflevector <4 x i64> %head, <4 x i64> poison, <4 x i32> zeroinitializer + %x = zext <4 x i8> %a to <4 x i64> + %z = shl <4 x i64> %x, %splat + ret <4 x i64> %z +} + +define <4 x i64> @vwsll_vx_i32_v4i64_v4i8_sext(<4 x i8> %a, i32 %b) { +; CHECK-LABEL: vwsll_vx_i32_v4i64_v4i8_sext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf8 v10, v8 +; CHECK-NEXT: vsext.vf2 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i32_v4i64_v4i8_sext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v9, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf8 v10, v8 +; CHECK-ZVBB-NEXT: vsext.vf2 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <4 x i32> poison, i32 %b, i32 0 + %splat = shufflevector <4 x i32> %head, <4 x i32> poison, <4 x i32> zeroinitializer + %x = zext <4 x i8> %a to <4 x i64> + %y = sext <4 x i32> %splat to <4 x i64> + %z = shl <4 x i64> %x, %y + ret <4 x i64> %z +} + +define <4 x i64> @vwsll_vx_i32_v4i64_v4i8_zext(<4 x i8> %a, i32 %b) { +; CHECK-LABEL: vwsll_vx_i32_v4i64_v4i8_zext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf8 v10, v8 +; CHECK-NEXT: vzext.vf2 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i32_v4i64_v4i8_zext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e32, m1, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v9, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf8 v10, v8 +; CHECK-ZVBB-NEXT: vzext.vf2 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <4 x i32> poison, i32 %b, i32 0 + %splat = shufflevector <4 x i32> %head, <4 x i32> poison, <4 x i32> zeroinitializer + %x = zext <4 x i8> %a to <4 x i64> + %y = zext <4 x i32> %splat to <4 x i64> + %z = shl <4 x i64> %x, %y + ret <4 x i64> %z +} + +define <4 x i64> @vwsll_vx_i16_v4i64_v4i8_sext(<4 x i8> %a, i16 %b) { +; CHECK-LABEL: vwsll_vx_i16_v4i64_v4i8_sext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf8 v10, v8 +; CHECK-NEXT: vsext.vf4 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i16_v4i64_v4i8_sext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v9, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf8 v10, v8 +; CHECK-ZVBB-NEXT: vsext.vf4 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <4 x i16> poison, i16 %b, i32 0 + %splat = shufflevector <4 x i16> %head, <4 x i16> poison, <4 x i32> zeroinitializer + %x = zext <4 x i8> %a to <4 x i64> + %y = sext <4 x i16> %splat to <4 x i64> + %z = shl <4 x i64> %x, %y + ret <4 x i64> %z +} + +define <4 x i64> @vwsll_vx_i16_v4i64_v4i8_zext(<4 x i8> %a, i16 %b) { +; CHECK-LABEL: vwsll_vx_i16_v4i64_v4i8_zext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf8 v10, v8 +; CHECK-NEXT: vzext.vf4 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i16_v4i64_v4i8_zext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e16, mf2, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v9, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf8 v10, v8 +; CHECK-ZVBB-NEXT: vzext.vf4 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <4 x i16> poison, i16 %b, i32 0 + %splat = shufflevector <4 x i16> %head, <4 x i16> poison, <4 x i32> zeroinitializer + %x = zext <4 x i8> %a to <4 x i64> + %y = zext <4 x i16> %splat to <4 x i64> + %z = shl <4 x i64> %x, %y + ret <4 x i64> %z +} + +define <4 x i64> @vwsll_vx_i8_v4i64_v4i8_sext(<4 x i8> %a, i8 %b) { +; CHECK-LABEL: vwsll_vx_i8_v4i64_v4i8_sext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf8 v10, v8 +; CHECK-NEXT: vsext.vf8 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i8_v4i64_v4i8_sext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v9, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf8 v10, v8 +; CHECK-ZVBB-NEXT: vsext.vf8 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <4 x i8> poison, i8 %b, i32 0 + %splat = shufflevector <4 x i8> %head, <4 x i8> poison, <4 x i32> zeroinitializer + %x = zext <4 x i8> %a to <4 x i64> + %y = sext <4 x i8> %splat to <4 x i64> + %z = shl <4 x i64> %x, %y + ret <4 x i64> %z +} + +define <4 x i64> @vwsll_vx_i8_v4i64_v4i8_zext(<4 x i8> %a, i8 %b) { +; CHECK-LABEL: vwsll_vx_i8_v4i64_v4i8_zext: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf8 v10, v8 +; CHECK-NEXT: vzext.vf8 v12, v9 +; CHECK-NEXT: vsll.vv v8, v10, v12 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vx_i8_v4i64_v4i8_zext: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; CHECK-ZVBB-NEXT: vmv.v.x v9, a0 +; CHECK-ZVBB-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf8 v10, v8 +; CHECK-ZVBB-NEXT: vzext.vf8 v12, v9 +; CHECK-ZVBB-NEXT: vsll.vv v8, v10, v12 +; CHECK-ZVBB-NEXT: ret + %head = insertelement <4 x i8> poison, i8 %b, i32 0 + %splat = shufflevector <4 x i8> %head, <4 x i8> poison, <4 x i32> zeroinitializer + %x = zext <4 x i8> %a to <4 x i64> + %y = zext <4 x i8> %splat to <4 x i64> + %z = shl <4 x i64> %x, %y + ret <4 x i64> %z +} + +define <4 x i64> @vwsll_vi_v4i64_v4i8(<4 x i8> %a) { +; CHECK-LABEL: vwsll_vi_v4i64_v4i8: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf8 v10, v8 +; CHECK-NEXT: vsll.vi v8, v10, 2 +; CHECK-NEXT: ret +; +; CHECK-ZVBB-LABEL: vwsll_vi_v4i64_v4i8: +; CHECK-ZVBB: # %bb.0: +; CHECK-ZVBB-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-ZVBB-NEXT: vzext.vf8 v10, v8 +; CHECK-ZVBB-NEXT: vsll.vi v8, v10, 2 +; CHECK-ZVBB-NEXT: ret + %x = zext <4 x i8> %a to <4 x i64> + %z = shl <4 x i64> %x, splat (i64 2) + ret <4 x i64> %z +} diff --git a/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops-mir.ll b/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops-mir.ll index 0544204cce792aeb7012fcf503f7041f9ddfc553..52bd15742ef4bbf6f0626aa2f5d52b3e932e0514 100644 --- a/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops-mir.ll +++ b/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops-mir.ll @@ -16,8 +16,8 @@ define void @vpmerge_vpload_store(<vscale x 2 x i32> %passthru, ptr %p, <vscale ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x10 ; CHECK-NEXT: [[COPY3:%[0-9]+]]:vrnov0 = COPY $v8 ; CHECK-NEXT: $v0 = COPY [[COPY1]] - ; CHECK-NEXT: [[PseudoVLE32_V_M1_MASK:%[0-9]+]]:vrnov0 = PseudoVLE32_V_M1_MASK [[COPY3]], [[COPY2]], $v0, [[COPY]], 5 /* e32 */, 0 /* tu, mu */ - ; CHECK-NEXT: VS1R_V killed [[PseudoVLE32_V_M1_MASK]], [[COPY2]] :: (store unknown-size into %ir.p, align 8) + ; CHECK-NEXT: [[PseudoVLE32_V_M1_MASK:%[0-9]+]]:vrnov0 = PseudoVLE32_V_M1_MASK [[COPY3]], [[COPY2]], $v0, [[COPY]], 5 /* e32 */, 0 /* tu, mu */ :: (load unknown-size from %ir.p, align 8) + ; CHECK-NEXT: VS1R_V killed [[PseudoVLE32_V_M1_MASK]], [[COPY2]] :: (store (<vscale x 1 x s64>) into %ir.p) ; CHECK-NEXT: PseudoRET %splat = insertelement <vscale x 2 x i1> poison, i1 -1, i32 0 %mask = shufflevector <vscale x 2 x i1> %splat, <vscale x 2 x i1> poison, <vscale x 2 x i32> zeroinitializer @@ -37,8 +37,8 @@ define void @vpselect_vpload_store(<vscale x 2 x i32> %passthru, ptr %p, <vscale ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x10 ; CHECK-NEXT: [[COPY3:%[0-9]+]]:vrnov0 = COPY $v8 ; CHECK-NEXT: $v0 = COPY [[COPY1]] - ; CHECK-NEXT: [[PseudoVLE32_V_M1_MASK:%[0-9]+]]:vrnov0 = PseudoVLE32_V_M1_MASK [[COPY3]], [[COPY2]], $v0, [[COPY]], 5 /* e32 */, 1 /* ta, mu */ - ; CHECK-NEXT: VS1R_V killed [[PseudoVLE32_V_M1_MASK]], [[COPY2]] :: (store unknown-size into %ir.p, align 8) + ; CHECK-NEXT: [[PseudoVLE32_V_M1_MASK:%[0-9]+]]:vrnov0 = PseudoVLE32_V_M1_MASK [[COPY3]], [[COPY2]], $v0, [[COPY]], 5 /* e32 */, 1 /* ta, mu */ :: (load unknown-size from %ir.p, align 8) + ; CHECK-NEXT: VS1R_V killed [[PseudoVLE32_V_M1_MASK]], [[COPY2]] :: (store (<vscale x 1 x s64>) into %ir.p) ; CHECK-NEXT: PseudoRET %splat = insertelement <vscale x 2 x i1> poison, i1 -1, i32 0 %mask = shufflevector <vscale x 2 x i1> %splat, <vscale x 2 x i1> poison, <vscale x 2 x i32> zeroinitializer diff --git a/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll b/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll index a4aef577bc9ae7ffe8cd60348e8aeceda1ac5a2e..7cc4a9da3d429401977ed03dd681e242d2754f04 100644 --- a/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll +++ b/llvm/test/CodeGen/RISCV/rvv/rvv-peephole-vmerge-vops.ll @@ -1187,3 +1187,30 @@ define <vscale x 2 x i32> @vmerge_larger_vl_false_becomes_tail(<vscale x 2 x i32 %b = call <vscale x 2 x i32> @llvm.riscv.vmerge.nxv2i32.nxv2i32(<vscale x 2 x i32> poison, <vscale x 2 x i32> %false, <vscale x 2 x i32> %a, <vscale x 2 x i1> %m, i64 3) ret <vscale x 2 x i32> %b } + +; Test widening pseudos with their TIED variant (passthru same as first op). +define <vscale x 2 x i64> @vpmerge_vwsub.w_tied(<vscale x 2 x i64> %passthru, <vscale x 2 x i64> %x, <vscale x 2 x i32> %y, <vscale x 2 x i1> %mask, i32 zeroext %vl) { +; CHECK-LABEL: vpmerge_vwsub.w_tied: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli zero, a0, e32, m1, tu, mu +; CHECK-NEXT: vwsub.wv v8, v8, v12, v0.t +; CHECK-NEXT: ret + %vl.zext = zext i32 %vl to i64 + %a = call <vscale x 2 x i64> @llvm.riscv.vwsub.w.nxv2i64.nxv2i32(<vscale x 2 x i64> %passthru, <vscale x 2 x i64> %passthru, <vscale x 2 x i32> %y, i64 %vl.zext) + %b = call <vscale x 2 x i64> @llvm.vp.merge.nxv2i64(<vscale x 2 x i1> %mask, <vscale x 2 x i64> %a, <vscale x 2 x i64> %passthru, i32 %vl) + ret <vscale x 2 x i64> %b +} + +define <vscale x 2 x double> @vpmerge_vfwsub.w_tied(<vscale x 2 x double> %passthru, <vscale x 2 x double> %x, <vscale x 2 x float> %y, <vscale x 2 x i1> %mask, i32 zeroext %vl) { +; CHECK-LABEL: vpmerge_vfwsub.w_tied: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli zero, a0, e32, m1, tu, mu +; CHECK-NEXT: fsrmi a0, 1 +; CHECK-NEXT: vfwsub.wv v8, v8, v12, v0.t +; CHECK-NEXT: fsrm a0 +; CHECK-NEXT: ret + %vl.zext = zext i32 %vl to i64 + %a = call <vscale x 2 x double> @llvm.riscv.vfwsub.w.nxv2f64.nxv2f32(<vscale x 2 x double> %passthru, <vscale x 2 x double> %passthru, <vscale x 2 x float> %y, i64 1, i64 %vl.zext) + %b = call <vscale x 2 x double> @llvm.vp.merge.nxv2f64(<vscale x 2 x i1> %mask, <vscale x 2 x double> %a, <vscale x 2 x double> %passthru, i32 %vl) + ret <vscale x 2 x double> %b +} diff --git a/llvm/test/CodeGen/RISCV/rvv/rvv-stack-align.mir b/llvm/test/CodeGen/RISCV/rvv/rvv-stack-align.mir index 6ea6fb183a7fdf0cca5447f825873aee0febc412..749bd4c13879b6bd23b3119c9eed63d087167ab1 100644 --- a/llvm/test/CodeGen/RISCV/rvv/rvv-stack-align.mir +++ b/llvm/test/CodeGen/RISCV/rvv/rvv-stack-align.mir @@ -159,7 +159,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 8 - adjustsStack: false + adjustsStack: true hasCalls: true stackProtector: '' maxCallFrameSize: 4294967295 @@ -204,7 +204,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 16 - adjustsStack: false + adjustsStack: true hasCalls: true stackProtector: '' maxCallFrameSize: 4294967295 @@ -249,7 +249,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 32 - adjustsStack: false + adjustsStack: true hasCalls: true stackProtector: '' maxCallFrameSize: 4294967295 diff --git a/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-load.ll b/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-load.ll index a320aecc6fce49110f29d70e277c5214dbd25fe0..6a712080fda74ab96f14d78a2fb8eb9f20d0bee0 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-load.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-load.ll @@ -18,10 +18,10 @@ define {<vscale x 16 x i1>, <vscale x 16 x i1>} @vector_deinterleave_load_nxv16i ; CHECK-NEXT: vmerge.vim v14, v10, 1, v0 ; CHECK-NEXT: vmv1r.v v0, v8 ; CHECK-NEXT: vmerge.vim v12, v10, 1, v0 -; CHECK-NEXT: vnsrl.wi v8, v12, 0 -; CHECK-NEXT: vmsne.vi v0, v8, 0 -; CHECK-NEXT: vnsrl.wi v10, v12, 8 +; CHECK-NEXT: vnsrl.wi v10, v12, 0 ; CHECK-NEXT: vmsne.vi v8, v10, 0 +; CHECK-NEXT: vnsrl.wi v10, v12, 8 +; CHECK-NEXT: vmsne.vi v9, v10, 0 ; CHECK-NEXT: ret %vec = load <vscale x 32 x i1>, ptr %p %retval = call {<vscale x 16 x i1>, <vscale x 16 x i1>} @llvm.experimental.vector.deinterleave2.nxv32i1(<vscale x 32 x i1> %vec) diff --git a/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave.ll b/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave.ll index ef4baf34d23f03bcaf66b49fc6eafa85e565983f..d98597fabcd953785b2188fc9ff7b1ac354af354 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave.ll @@ -8,18 +8,18 @@ define {<vscale x 16 x i1>, <vscale x 16 x i1>} @vector_deinterleave_nxv16i1_nxv ; CHECK-LABEL: vector_deinterleave_nxv16i1_nxv32i1: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a0, zero, e8, m2, ta, ma -; CHECK-NEXT: vmv.v.i v10, 0 -; CHECK-NEXT: vmerge.vim v8, v10, 1, v0 +; CHECK-NEXT: vmv.v.i v8, 0 +; CHECK-NEXT: vmerge.vim v12, v8, 1, v0 ; CHECK-NEXT: csrr a0, vlenb ; CHECK-NEXT: srli a0, a0, 2 ; CHECK-NEXT: vsetvli a1, zero, e8, mf2, ta, ma ; CHECK-NEXT: vslidedown.vx v0, v0, a0 ; CHECK-NEXT: vsetvli a0, zero, e8, m2, ta, ma -; CHECK-NEXT: vmerge.vim v10, v10, 1, v0 -; CHECK-NEXT: vnsrl.wi v12, v8, 0 -; CHECK-NEXT: vmsne.vi v0, v12, 0 -; CHECK-NEXT: vnsrl.wi v12, v8, 8 -; CHECK-NEXT: vmsne.vi v8, v12, 0 +; CHECK-NEXT: vmerge.vim v14, v8, 1, v0 +; CHECK-NEXT: vnsrl.wi v10, v12, 0 +; CHECK-NEXT: vmsne.vi v8, v10, 0 +; CHECK-NEXT: vnsrl.wi v10, v12, 8 +; CHECK-NEXT: vmsne.vi v9, v10, 0 ; CHECK-NEXT: ret %retval = call {<vscale x 16 x i1>, <vscale x 16 x i1>} @llvm.experimental.vector.deinterleave2.nxv32i1(<vscale x 32 x i1> %vec) ret {<vscale x 16 x i1>, <vscale x 16 x i1>} %retval @@ -102,12 +102,13 @@ define {<vscale x 64 x i1>, <vscale x 64 x i1>} @vector_deinterleave_nxv64i1_nxv ; CHECK-NEXT: vsetvli a0, zero, e8, m4, ta, ma ; CHECK-NEXT: vnsrl.wi v28, v8, 0 ; CHECK-NEXT: vsetvli a0, zero, e8, m8, ta, ma -; CHECK-NEXT: vmsne.vi v0, v24, 0 +; CHECK-NEXT: vmsne.vi v7, v24, 0 ; CHECK-NEXT: vsetvli a0, zero, e8, m4, ta, ma ; CHECK-NEXT: vnsrl.wi v24, v16, 8 ; CHECK-NEXT: vnsrl.wi v28, v8, 8 ; CHECK-NEXT: vsetvli a0, zero, e8, m8, ta, ma -; CHECK-NEXT: vmsne.vi v8, v24, 0 +; CHECK-NEXT: vmsne.vi v9, v24, 0 +; CHECK-NEXT: vmv1r.v v8, v7 ; CHECK-NEXT: ret %retval = call {<vscale x 64 x i1>, <vscale x 64 x i1>} @llvm.experimental.vector.deinterleave2.nxv128i1(<vscale x 128 x i1> %vec) ret {<vscale x 64 x i1>, <vscale x 64 x i1>} %retval diff --git a/llvm/test/CodeGen/RISCV/rvv/vector-interleave-store.ll b/llvm/test/CodeGen/RISCV/rvv/vector-interleave-store.ll index 4aae8b8bd1dc02adeef372bac9d02171d0976a3a..9a5e86d61c265ea18634174a401c73675ab72c76 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vector-interleave-store.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vector-interleave-store.ll @@ -101,40 +101,36 @@ define void @vector_interleave_store_nxv16i64_nxv8i64(<vscale x 8 x i64> %a, <vs ; CHECK-NEXT: slli a1, a1, 4 ; CHECK-NEXT: sub sp, sp, a1 ; CHECK-NEXT: .cfi_escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x10, 0x22, 0x11, 0x10, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # sp + 16 + 16 * vlenb -; CHECK-NEXT: csrr a1, vlenb -; CHECK-NEXT: slli a1, a1, 3 -; CHECK-NEXT: add a1, sp, a1 -; CHECK-NEXT: addi a1, a1, 16 +; CHECK-NEXT: addi a1, sp, 16 ; CHECK-NEXT: vs8r.v v8, (a1) # Unknown-size Folded Spill ; CHECK-NEXT: csrr a1, vlenb ; CHECK-NEXT: srli a2, a1, 1 ; CHECK-NEXT: vsetvli a3, zero, e16, m2, ta, mu ; CHECK-NEXT: vid.v v24 ; CHECK-NEXT: vand.vi v26, v24, 1 -; CHECK-NEXT: vmsne.vi v0, v26, 0 -; CHECK-NEXT: vsrl.vi v6, v24, 1 -; CHECK-NEXT: csrr a3, vlenb -; CHECK-NEXT: slli a3, a3, 3 -; CHECK-NEXT: add a3, sp, a3 -; CHECK-NEXT: addi a3, a3, 16 -; CHECK-NEXT: vl8r.v v8, (a3) # Unknown-size Folded Reload -; CHECK-NEXT: vadd.vx v6, v6, a2, v0.t +; CHECK-NEXT: vmsne.vi v28, v26, 0 +; CHECK-NEXT: vsrl.vi v24, v24, 1 +; CHECK-NEXT: vmv1r.v v0, v28 +; CHECK-NEXT: vadd.vx v24, v24, a2, v0.t ; CHECK-NEXT: vmv4r.v v12, v16 ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vrgatherei16.vv v24, v8, v6 -; CHECK-NEXT: addi a2, sp, 16 -; CHECK-NEXT: vs8r.v v24, (a2) # Unknown-size Folded Spill +; CHECK-NEXT: vrgatherei16.vv v0, v8, v24 ; CHECK-NEXT: csrr a2, vlenb ; CHECK-NEXT: slli a2, a2, 3 ; CHECK-NEXT: add a2, sp, a2 ; CHECK-NEXT: addi a2, a2, 16 +; CHECK-NEXT: vs8r.v v0, (a2) # Unknown-size Folded Spill +; CHECK-NEXT: addi a2, sp, 16 ; CHECK-NEXT: vl8r.v v8, (a2) # Unknown-size Folded Reload ; CHECK-NEXT: vmv4r.v v16, v12 -; CHECK-NEXT: vrgatherei16.vv v8, v16, v6 +; CHECK-NEXT: vrgatherei16.vv v8, v16, v24 ; CHECK-NEXT: slli a1, a1, 3 ; CHECK-NEXT: add a1, a0, a1 ; CHECK-NEXT: vs8r.v v8, (a1) -; CHECK-NEXT: addi a1, sp, 16 +; CHECK-NEXT: csrr a1, vlenb +; CHECK-NEXT: slli a1, a1, 3 +; CHECK-NEXT: add a1, sp, a1 +; CHECK-NEXT: addi a1, a1, 16 ; CHECK-NEXT: vl8r.v v8, (a1) # Unknown-size Folded Reload ; CHECK-NEXT: vs8r.v v8, (a0) ; CHECK-NEXT: csrr a0, vlenb diff --git a/llvm/test/CodeGen/RISCV/rvv/vector-interleave.ll b/llvm/test/CodeGen/RISCV/rvv/vector-interleave.ll index 1acc0fec8fe5869b4abe27e5d086f3fe661ee2e7..0992c9fe495f43c1df6483ed8bb6e6f241aa0fb8 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vector-interleave.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vector-interleave.ll @@ -656,6 +656,24 @@ define <vscale x 16 x double> @vector_interleave_nxv16f64_nxv8f64(<vscale x 8 x ret <vscale x 16 x double> %res } +define <vscale x 8 x i32> @vector_interleave_nxv8i32_nxv4i32_poison(<vscale x 4 x i32> %a) { +; CHECK-LABEL: vector_interleave_nxv8i32_nxv4i32_poison: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma +; CHECK-NEXT: vzext.vf2 v12, v8 +; CHECK-NEXT: vmv.v.v v8, v12 +; CHECK-NEXT: ret +; +; ZVBB-LABEL: vector_interleave_nxv8i32_nxv4i32_poison: +; ZVBB: # %bb.0: +; ZVBB-NEXT: vsetvli a0, zero, e64, m4, ta, ma +; ZVBB-NEXT: vzext.vf2 v12, v8 +; ZVBB-NEXT: vmv.v.v v8, v12 +; ZVBB-NEXT: ret + %res = call <vscale x 8 x i32> @llvm.experimental.vector.interleave2.nxv8i32(<vscale x 4 x i32> %a, <vscale x 4 x i32> poison) + ret <vscale x 8 x i32> %res +} + declare <vscale x 64 x half> @llvm.experimental.vector.interleave2.nxv64f16(<vscale x 32 x half>, <vscale x 32 x half>) declare <vscale x 32 x float> @llvm.experimental.vector.interleave2.nxv32f32(<vscale x 16 x float>, <vscale x 16 x float>) declare <vscale x 16 x double> @llvm.experimental.vector.interleave2.nxv16f64(<vscale x 8 x double>, <vscale x 8 x double>) diff --git a/llvm/test/CodeGen/RISCV/rvv/vscale-vw-web-simplification.ll b/llvm/test/CodeGen/RISCV/rvv/vscale-vw-web-simplification.ll index 972fa66917a5689f978fbf04a218ebce953c21e7..e56dca0732bb4ce719bf5fdffd04372a4f418150 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vscale-vw-web-simplification.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vscale-vw-web-simplification.ll @@ -283,18 +283,19 @@ define <vscale x 2 x i32> @vwop_vscale_sext_i8i32_multiple_users(ptr %x, ptr %y, ; ; FOLDING-LABEL: vwop_vscale_sext_i8i32_multiple_users: ; FOLDING: # %bb.0: -; FOLDING-NEXT: vsetvli a3, zero, e32, m1, ta, ma +; FOLDING-NEXT: vsetvli a3, zero, e16, mf2, ta, ma ; FOLDING-NEXT: vle8.v v8, (a0) ; FOLDING-NEXT: vle8.v v9, (a1) ; FOLDING-NEXT: vle8.v v10, (a2) -; FOLDING-NEXT: vsext.vf4 v11, v8 -; FOLDING-NEXT: vsext.vf4 v8, v9 -; FOLDING-NEXT: vsext.vf4 v9, v10 -; FOLDING-NEXT: vmul.vv v8, v11, v8 -; FOLDING-NEXT: vadd.vv v10, v11, v9 -; FOLDING-NEXT: vsub.vv v9, v11, v9 -; FOLDING-NEXT: vor.vv v8, v8, v10 -; FOLDING-NEXT: vor.vv v8, v8, v9 +; FOLDING-NEXT: vsext.vf2 v11, v8 +; FOLDING-NEXT: vsext.vf2 v8, v9 +; FOLDING-NEXT: vsext.vf2 v9, v10 +; FOLDING-NEXT: vwmul.vv v10, v11, v8 +; FOLDING-NEXT: vwadd.vv v8, v11, v9 +; FOLDING-NEXT: vwsub.vv v12, v11, v9 +; FOLDING-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; FOLDING-NEXT: vor.vv v8, v10, v8 +; FOLDING-NEXT: vor.vv v8, v8, v12 ; FOLDING-NEXT: ret %a = load <vscale x 2 x i8>, ptr %x %b = load <vscale x 2 x i8>, ptr %y @@ -563,18 +564,19 @@ define <vscale x 2 x i32> @vwop_vscale_zext_i8i32_multiple_users(ptr %x, ptr %y, ; ; FOLDING-LABEL: vwop_vscale_zext_i8i32_multiple_users: ; FOLDING: # %bb.0: -; FOLDING-NEXT: vsetvli a3, zero, e32, m1, ta, ma +; FOLDING-NEXT: vsetvli a3, zero, e16, mf2, ta, ma ; FOLDING-NEXT: vle8.v v8, (a0) ; FOLDING-NEXT: vle8.v v9, (a1) ; FOLDING-NEXT: vle8.v v10, (a2) -; FOLDING-NEXT: vzext.vf4 v11, v8 -; FOLDING-NEXT: vzext.vf4 v8, v9 -; FOLDING-NEXT: vzext.vf4 v9, v10 -; FOLDING-NEXT: vmul.vv v8, v11, v8 -; FOLDING-NEXT: vadd.vv v10, v11, v9 -; FOLDING-NEXT: vsub.vv v9, v11, v9 -; FOLDING-NEXT: vor.vv v8, v8, v10 -; FOLDING-NEXT: vor.vv v8, v8, v9 +; FOLDING-NEXT: vzext.vf2 v11, v8 +; FOLDING-NEXT: vzext.vf2 v8, v9 +; FOLDING-NEXT: vzext.vf2 v9, v10 +; FOLDING-NEXT: vwmulu.vv v10, v11, v8 +; FOLDING-NEXT: vwaddu.vv v8, v11, v9 +; FOLDING-NEXT: vwsubu.vv v12, v11, v9 +; FOLDING-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; FOLDING-NEXT: vor.vv v8, v10, v8 +; FOLDING-NEXT: vor.vv v8, v8, v12 ; FOLDING-NEXT: ret %a = load <vscale x 2 x i8>, ptr %x %b = load <vscale x 2 x i8>, ptr %y diff --git a/llvm/test/CodeGen/RISCV/rvv/vwadd-sdnode.ll b/llvm/test/CodeGen/RISCV/rvv/vwadd-sdnode.ll index a559fbf2bc8a7ab018ae9ed16dd6ea028db385bb..66e6883dd1d3e3872ff6e15cd44fd8728d3a4a57 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vwadd-sdnode.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vwadd-sdnode.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=riscv32 -mattr=+v -verify-machineinstrs < %s | FileCheck %s -; RUN: llc -mtriple=riscv64 -mattr=+v -verify-machineinstrs < %s | FileCheck %s +; RUN: llc -mtriple=riscv32 -mattr=+v -verify-machineinstrs < %s | FileCheck -check-prefixes=CHECK,RV32 %s +; RUN: llc -mtriple=riscv64 -mattr=+v -verify-machineinstrs < %s | FileCheck -check-prefixes=CHECK,RV64 %s define <vscale x 1 x i64> @vwadd_vv_nxv1i64_nxv1i32(<vscale x 1 x i32> %va, <vscale x 1 x i32> %vb) { ; CHECK-LABEL: vwadd_vv_nxv1i64_nxv1i32: @@ -421,10 +421,10 @@ define <vscale x 8 x i64> @vwaddu_wx_nxv8i64_nxv8i32(<vscale x 8 x i64> %va, i32 define <vscale x 1 x i64> @vwadd_vv_nxv1i64_nxv1i16(<vscale x 1 x i16> %va, <vscale x 1 x i16> %vb) { ; CHECK-LABEL: vwadd_vv_nxv1i64_nxv1i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v8 -; CHECK-NEXT: vsext.vf4 v8, v9 -; CHECK-NEXT: vadd.vv v8, v10, v8 +; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf2 v11, v9 +; CHECK-NEXT: vwadd.vv v8, v10, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 1 x i16> %va to <vscale x 1 x i64> %vd = sext <vscale x 1 x i16> %vb to <vscale x 1 x i64> @@ -435,10 +435,10 @@ define <vscale x 1 x i64> @vwadd_vv_nxv1i64_nxv1i16(<vscale x 1 x i16> %va, <vsc define <vscale x 1 x i64> @vwaddu_vv_nxv1i64_nxv1i16(<vscale x 1 x i16> %va, <vscale x 1 x i16> %vb) { ; CHECK-LABEL: vwaddu_vv_nxv1i64_nxv1i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vzext.vf4 v10, v8 -; CHECK-NEXT: vzext.vf4 v8, v9 -; CHECK-NEXT: vadd.vv v8, v10, v8 +; CHECK-NEXT: vsetvli a0, zero, e16, mf4, ta, ma +; CHECK-NEXT: vwaddu.vv v10, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v10 ; CHECK-NEXT: ret %vc = zext <vscale x 1 x i16> %va to <vscale x 1 x i64> %vd = zext <vscale x 1 x i16> %vb to <vscale x 1 x i64> @@ -451,10 +451,10 @@ define <vscale x 1 x i64> @vwadd_vx_nxv1i64_nxv1i16(<vscale x 1 x i16> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf4, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v8 -; CHECK-NEXT: vsext.vf4 v8, v9 -; CHECK-NEXT: vadd.vv v8, v10, v8 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf2 v11, v9 +; CHECK-NEXT: vwadd.vv v8, v10, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 1 x i16> %head, <vscale x 1 x i16> poison, <vscale x 1 x i32> zeroinitializer @@ -468,11 +468,9 @@ define <vscale x 1 x i64> @vwaddu_vx_nxv1i64_nxv1i16(<vscale x 1 x i16> %va, i16 ; CHECK-LABEL: vwaddu_vx_nxv1i64_nxv1i16: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf4, ta, ma -; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vwaddu.vx v9, v8, a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vzext.vf4 v10, v8 -; CHECK-NEXT: vzext.vf4 v8, v9 -; CHECK-NEXT: vadd.vv v8, v10, v8 +; CHECK-NEXT: vzext.vf2 v8, v9 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 1 x i16> %head, <vscale x 1 x i16> poison, <vscale x 1 x i32> zeroinitializer @@ -485,9 +483,9 @@ define <vscale x 1 x i64> @vwaddu_vx_nxv1i64_nxv1i16(<vscale x 1 x i16> %va, i16 define <vscale x 1 x i64> @vwadd_wv_nxv1i64_nxv1i16(<vscale x 1 x i64> %va, <vscale x 1 x i16> %vb) { ; CHECK-LABEL: vwadd_wv_nxv1i64_nxv1i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v9 -; CHECK-NEXT: vadd.vv v8, v8, v10 +; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v9 +; CHECK-NEXT: vwadd.wv v8, v8, v10 ; CHECK-NEXT: ret %vc = sext <vscale x 1 x i16> %vb to <vscale x 1 x i64> %vd = add <vscale x 1 x i64> %va, %vc @@ -497,9 +495,9 @@ define <vscale x 1 x i64> @vwadd_wv_nxv1i64_nxv1i16(<vscale x 1 x i64> %va, <vsc define <vscale x 1 x i64> @vwaddu_wv_nxv1i64_nxv1i16(<vscale x 1 x i64> %va, <vscale x 1 x i16> %vb) { ; CHECK-LABEL: vwaddu_wv_nxv1i64_nxv1i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vzext.vf4 v10, v9 -; CHECK-NEXT: vadd.vv v8, v8, v10 +; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v9 +; CHECK-NEXT: vwaddu.wv v8, v8, v10 ; CHECK-NEXT: ret %vc = zext <vscale x 1 x i16> %vb to <vscale x 1 x i64> %vd = add <vscale x 1 x i64> %va, %vc @@ -511,9 +509,9 @@ define <vscale x 1 x i64> @vwadd_wx_nxv1i64_nxv1i16(<vscale x 1 x i64> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf4, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v9 -; CHECK-NEXT: vadd.vv v8, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v9 +; CHECK-NEXT: vwadd.wv v8, v8, v10 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 1 x i16> %head, <vscale x 1 x i16> poison, <vscale x 1 x i32> zeroinitializer @@ -527,9 +525,9 @@ define <vscale x 1 x i64> @vwaddu_wx_nxv1i64_nxv1i16(<vscale x 1 x i64> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf4, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vzext.vf4 v10, v9 -; CHECK-NEXT: vadd.vv v8, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v9 +; CHECK-NEXT: vwaddu.wv v8, v8, v10 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 1 x i16> %head, <vscale x 1 x i16> poison, <vscale x 1 x i32> zeroinitializer @@ -541,10 +539,10 @@ define <vscale x 1 x i64> @vwaddu_wx_nxv1i64_nxv1i16(<vscale x 1 x i64> %va, i16 define <vscale x 2 x i64> @vwadd_vv_nxv2i64_nxv2i16(<vscale x 2 x i16> %va, <vscale x 2 x i16> %vb) { ; CHECK-LABEL: vwadd_vv_nxv2i64_nxv2i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v8 -; CHECK-NEXT: vsext.vf4 v12, v9 -; CHECK-NEXT: vadd.vv v8, v10, v12 +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf2 v11, v9 +; CHECK-NEXT: vwadd.vv v8, v10, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 2 x i16> %va to <vscale x 2 x i64> %vd = sext <vscale x 2 x i16> %vb to <vscale x 2 x i64> @@ -555,10 +553,10 @@ define <vscale x 2 x i64> @vwadd_vv_nxv2i64_nxv2i16(<vscale x 2 x i16> %va, <vsc define <vscale x 2 x i64> @vwaddu_vv_nxv2i64_nxv2i16(<vscale x 2 x i16> %va, <vscale x 2 x i16> %vb) { ; CHECK-LABEL: vwaddu_vv_nxv2i64_nxv2i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vzext.vf4 v10, v8 -; CHECK-NEXT: vzext.vf4 v12, v9 -; CHECK-NEXT: vadd.vv v8, v10, v12 +; CHECK-NEXT: vsetvli a0, zero, e16, mf2, ta, ma +; CHECK-NEXT: vwaddu.vv v10, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v10 ; CHECK-NEXT: ret %vc = zext <vscale x 2 x i16> %va to <vscale x 2 x i64> %vd = zext <vscale x 2 x i16> %vb to <vscale x 2 x i64> @@ -571,10 +569,10 @@ define <vscale x 2 x i64> @vwadd_vx_nxv2i64_nxv2i16(<vscale x 2 x i16> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf2, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v8 -; CHECK-NEXT: vsext.vf4 v12, v9 -; CHECK-NEXT: vadd.vv v8, v10, v12 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf2 v11, v9 +; CHECK-NEXT: vwadd.vv v8, v10, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 2 x i16> %head, <vscale x 2 x i16> poison, <vscale x 2 x i32> zeroinitializer @@ -588,11 +586,9 @@ define <vscale x 2 x i64> @vwaddu_vx_nxv2i64_nxv2i16(<vscale x 2 x i16> %va, i16 ; CHECK-LABEL: vwaddu_vx_nxv2i64_nxv2i16: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf2, ta, ma -; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vwaddu.vx v10, v8, a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vzext.vf4 v10, v8 -; CHECK-NEXT: vzext.vf4 v12, v9 -; CHECK-NEXT: vadd.vv v8, v10, v12 +; CHECK-NEXT: vzext.vf2 v8, v10 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 2 x i16> %head, <vscale x 2 x i16> poison, <vscale x 2 x i32> zeroinitializer @@ -605,9 +601,9 @@ define <vscale x 2 x i64> @vwaddu_vx_nxv2i64_nxv2i16(<vscale x 2 x i16> %va, i16 define <vscale x 2 x i64> @vwadd_wv_nxv2i64_nxv2i16(<vscale x 2 x i64> %va, <vscale x 2 x i16> %vb) { ; CHECK-LABEL: vwadd_wv_nxv2i64_nxv2i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf4 v12, v10 -; CHECK-NEXT: vadd.vv v8, v8, v12 +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf2 v11, v10 +; CHECK-NEXT: vwadd.wv v8, v8, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 2 x i16> %vb to <vscale x 2 x i64> %vd = add <vscale x 2 x i64> %va, %vc @@ -617,9 +613,9 @@ define <vscale x 2 x i64> @vwadd_wv_nxv2i64_nxv2i16(<vscale x 2 x i64> %va, <vsc define <vscale x 2 x i64> @vwaddu_wv_nxv2i64_nxv2i16(<vscale x 2 x i64> %va, <vscale x 2 x i16> %vb) { ; CHECK-LABEL: vwaddu_wv_nxv2i64_nxv2i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vzext.vf4 v12, v10 -; CHECK-NEXT: vadd.vv v8, v8, v12 +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vzext.vf2 v11, v10 +; CHECK-NEXT: vwaddu.wv v8, v8, v11 ; CHECK-NEXT: ret %vc = zext <vscale x 2 x i16> %vb to <vscale x 2 x i64> %vd = add <vscale x 2 x i64> %va, %vc @@ -631,9 +627,9 @@ define <vscale x 2 x i64> @vwadd_wx_nxv2i64_nxv2i16(<vscale x 2 x i64> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf2, ta, ma ; CHECK-NEXT: vmv.v.x v10, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf4 v12, v10 -; CHECK-NEXT: vadd.vv v8, v8, v12 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf2 v11, v10 +; CHECK-NEXT: vwadd.wv v8, v8, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 2 x i16> %head, <vscale x 2 x i16> poison, <vscale x 2 x i32> zeroinitializer @@ -647,9 +643,9 @@ define <vscale x 2 x i64> @vwaddu_wx_nxv2i64_nxv2i16(<vscale x 2 x i64> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf2, ta, ma ; CHECK-NEXT: vmv.v.x v10, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vzext.vf4 v12, v10 -; CHECK-NEXT: vadd.vv v8, v8, v12 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vzext.vf2 v11, v10 +; CHECK-NEXT: vwaddu.wv v8, v8, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 2 x i16> %head, <vscale x 2 x i16> poison, <vscale x 2 x i32> zeroinitializer @@ -661,10 +657,10 @@ define <vscale x 2 x i64> @vwaddu_wx_nxv2i64_nxv2i16(<vscale x 2 x i64> %va, i16 define <vscale x 4 x i64> @vwadd_vv_nxv4i64_nxv4i16(<vscale x 4 x i16> %va, <vscale x 4 x i16> %vb) { ; CHECK-LABEL: vwadd_vv_nxv4i64_nxv4i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf4 v12, v8 -; CHECK-NEXT: vsext.vf4 v16, v9 -; CHECK-NEXT: vadd.vv v8, v12, v16 +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf2 v12, v8 +; CHECK-NEXT: vsext.vf2 v14, v9 +; CHECK-NEXT: vwadd.vv v8, v12, v14 ; CHECK-NEXT: ret %vc = sext <vscale x 4 x i16> %va to <vscale x 4 x i64> %vd = sext <vscale x 4 x i16> %vb to <vscale x 4 x i64> @@ -675,10 +671,10 @@ define <vscale x 4 x i64> @vwadd_vv_nxv4i64_nxv4i16(<vscale x 4 x i16> %va, <vsc define <vscale x 4 x i64> @vwaddu_vv_nxv4i64_nxv4i16(<vscale x 4 x i16> %va, <vscale x 4 x i16> %vb) { ; CHECK-LABEL: vwaddu_vv_nxv4i64_nxv4i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vzext.vf4 v12, v8 -; CHECK-NEXT: vzext.vf4 v16, v9 -; CHECK-NEXT: vadd.vv v8, v12, v16 +; CHECK-NEXT: vsetvli a0, zero, e16, m1, ta, ma +; CHECK-NEXT: vwaddu.vv v12, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v12 ; CHECK-NEXT: ret %vc = zext <vscale x 4 x i16> %va to <vscale x 4 x i64> %vd = zext <vscale x 4 x i16> %vb to <vscale x 4 x i64> @@ -691,10 +687,10 @@ define <vscale x 4 x i64> @vwadd_vx_nxv4i64_nxv4i16(<vscale x 4 x i16> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m1, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf4 v12, v8 -; CHECK-NEXT: vsext.vf4 v16, v9 -; CHECK-NEXT: vadd.vv v8, v12, v16 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf2 v12, v8 +; CHECK-NEXT: vsext.vf2 v14, v9 +; CHECK-NEXT: vwadd.vv v8, v12, v14 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 4 x i16> %head, <vscale x 4 x i16> poison, <vscale x 4 x i32> zeroinitializer @@ -708,11 +704,9 @@ define <vscale x 4 x i64> @vwaddu_vx_nxv4i64_nxv4i16(<vscale x 4 x i16> %va, i16 ; CHECK-LABEL: vwaddu_vx_nxv4i64_nxv4i16: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m1, ta, ma -; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vwaddu.vx v12, v8, a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vzext.vf4 v12, v8 -; CHECK-NEXT: vzext.vf4 v16, v9 -; CHECK-NEXT: vadd.vv v8, v12, v16 +; CHECK-NEXT: vzext.vf2 v8, v12 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 4 x i16> %head, <vscale x 4 x i16> poison, <vscale x 4 x i32> zeroinitializer @@ -725,9 +719,9 @@ define <vscale x 4 x i64> @vwaddu_vx_nxv4i64_nxv4i16(<vscale x 4 x i16> %va, i16 define <vscale x 4 x i64> @vwadd_wv_nxv4i64_nxv4i16(<vscale x 4 x i64> %va, <vscale x 4 x i16> %vb) { ; CHECK-LABEL: vwadd_wv_nxv4i64_nxv4i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf4 v16, v12 -; CHECK-NEXT: vadd.vv v8, v8, v16 +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf2 v14, v12 +; CHECK-NEXT: vwadd.wv v8, v8, v14 ; CHECK-NEXT: ret %vc = sext <vscale x 4 x i16> %vb to <vscale x 4 x i64> %vd = add <vscale x 4 x i64> %va, %vc @@ -737,9 +731,9 @@ define <vscale x 4 x i64> @vwadd_wv_nxv4i64_nxv4i16(<vscale x 4 x i64> %va, <vsc define <vscale x 4 x i64> @vwaddu_wv_nxv4i64_nxv4i16(<vscale x 4 x i64> %va, <vscale x 4 x i16> %vb) { ; CHECK-LABEL: vwaddu_wv_nxv4i64_nxv4i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vzext.vf4 v16, v12 -; CHECK-NEXT: vadd.vv v8, v8, v16 +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v14, v12 +; CHECK-NEXT: vwaddu.wv v8, v8, v14 ; CHECK-NEXT: ret %vc = zext <vscale x 4 x i16> %vb to <vscale x 4 x i64> %vd = add <vscale x 4 x i64> %va, %vc @@ -751,9 +745,9 @@ define <vscale x 4 x i64> @vwadd_wx_nxv4i64_nxv4i16(<vscale x 4 x i64> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m1, ta, ma ; CHECK-NEXT: vmv.v.x v12, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf4 v16, v12 -; CHECK-NEXT: vadd.vv v8, v8, v16 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf2 v14, v12 +; CHECK-NEXT: vwadd.wv v8, v8, v14 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 4 x i16> %head, <vscale x 4 x i16> poison, <vscale x 4 x i32> zeroinitializer @@ -767,9 +761,9 @@ define <vscale x 4 x i64> @vwaddu_wx_nxv4i64_nxv4i16(<vscale x 4 x i64> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m1, ta, ma ; CHECK-NEXT: vmv.v.x v12, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vzext.vf4 v16, v12 -; CHECK-NEXT: vadd.vv v8, v8, v16 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v14, v12 +; CHECK-NEXT: vwaddu.wv v8, v8, v14 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 4 x i16> %head, <vscale x 4 x i16> poison, <vscale x 4 x i32> zeroinitializer @@ -781,10 +775,10 @@ define <vscale x 4 x i64> @vwaddu_wx_nxv4i64_nxv4i16(<vscale x 4 x i64> %va, i16 define <vscale x 8 x i64> @vwadd_vv_nxv8i64_nxv8i16(<vscale x 8 x i16> %va, <vscale x 8 x i16> %vb) { ; CHECK-LABEL: vwadd_vv_nxv8i64_nxv8i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf4 v16, v8 -; CHECK-NEXT: vsext.vf4 v24, v10 -; CHECK-NEXT: vadd.vv v8, v16, v24 +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf2 v16, v8 +; CHECK-NEXT: vsext.vf2 v20, v10 +; CHECK-NEXT: vwadd.vv v8, v16, v20 ; CHECK-NEXT: ret %vc = sext <vscale x 8 x i16> %va to <vscale x 8 x i64> %vd = sext <vscale x 8 x i16> %vb to <vscale x 8 x i64> @@ -795,10 +789,10 @@ define <vscale x 8 x i64> @vwadd_vv_nxv8i64_nxv8i16(<vscale x 8 x i16> %va, <vsc define <vscale x 8 x i64> @vwaddu_vv_nxv8i64_nxv8i16(<vscale x 8 x i16> %va, <vscale x 8 x i16> %vb) { ; CHECK-LABEL: vwaddu_vv_nxv8i64_nxv8i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vzext.vf4 v16, v8 -; CHECK-NEXT: vzext.vf4 v24, v10 -; CHECK-NEXT: vadd.vv v8, v16, v24 +; CHECK-NEXT: vsetvli a0, zero, e16, m2, ta, ma +; CHECK-NEXT: vwaddu.vv v16, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v16 ; CHECK-NEXT: ret %vc = zext <vscale x 8 x i16> %va to <vscale x 8 x i64> %vd = zext <vscale x 8 x i16> %vb to <vscale x 8 x i64> @@ -811,10 +805,10 @@ define <vscale x 8 x i64> @vwadd_vx_nxv8i64_nxv8i16(<vscale x 8 x i16> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m2, ta, ma ; CHECK-NEXT: vmv.v.x v10, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf4 v16, v8 -; CHECK-NEXT: vsext.vf4 v24, v10 -; CHECK-NEXT: vadd.vv v8, v16, v24 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf2 v16, v8 +; CHECK-NEXT: vsext.vf2 v20, v10 +; CHECK-NEXT: vwadd.vv v8, v16, v20 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 8 x i16> %head, <vscale x 8 x i16> poison, <vscale x 8 x i32> zeroinitializer @@ -828,11 +822,9 @@ define <vscale x 8 x i64> @vwaddu_vx_nxv8i64_nxv8i16(<vscale x 8 x i16> %va, i16 ; CHECK-LABEL: vwaddu_vx_nxv8i64_nxv8i16: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m2, ta, ma -; CHECK-NEXT: vmv.v.x v10, a0 +; CHECK-NEXT: vwaddu.vx v16, v8, a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vzext.vf4 v16, v8 -; CHECK-NEXT: vzext.vf4 v24, v10 -; CHECK-NEXT: vadd.vv v8, v16, v24 +; CHECK-NEXT: vzext.vf2 v8, v16 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 8 x i16> %head, <vscale x 8 x i16> poison, <vscale x 8 x i32> zeroinitializer @@ -845,9 +837,9 @@ define <vscale x 8 x i64> @vwaddu_vx_nxv8i64_nxv8i16(<vscale x 8 x i16> %va, i16 define <vscale x 8 x i64> @vwadd_wv_nxv8i64_nxv8i16(<vscale x 8 x i64> %va, <vscale x 8 x i16> %vb) { ; CHECK-LABEL: vwadd_wv_nxv8i64_nxv8i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf4 v24, v16 -; CHECK-NEXT: vadd.vv v8, v8, v24 +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf2 v20, v16 +; CHECK-NEXT: vwadd.wv v8, v8, v20 ; CHECK-NEXT: ret %vc = sext <vscale x 8 x i16> %vb to <vscale x 8 x i64> %vd = add <vscale x 8 x i64> %va, %vc @@ -857,9 +849,9 @@ define <vscale x 8 x i64> @vwadd_wv_nxv8i64_nxv8i16(<vscale x 8 x i64> %va, <vsc define <vscale x 8 x i64> @vwaddu_wv_nxv8i64_nxv8i16(<vscale x 8 x i64> %va, <vscale x 8 x i16> %vb) { ; CHECK-LABEL: vwaddu_wv_nxv8i64_nxv8i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vzext.vf4 v24, v16 -; CHECK-NEXT: vadd.vv v8, v8, v24 +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf2 v20, v16 +; CHECK-NEXT: vwaddu.wv v8, v8, v20 ; CHECK-NEXT: ret %vc = zext <vscale x 8 x i16> %vb to <vscale x 8 x i64> %vd = add <vscale x 8 x i64> %va, %vc @@ -871,9 +863,9 @@ define <vscale x 8 x i64> @vwadd_wx_nxv8i64_nxv8i16(<vscale x 8 x i64> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m2, ta, ma ; CHECK-NEXT: vmv.v.x v16, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf4 v24, v16 -; CHECK-NEXT: vadd.vv v8, v8, v24 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf2 v20, v16 +; CHECK-NEXT: vwadd.wv v8, v8, v20 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 8 x i16> %head, <vscale x 8 x i16> poison, <vscale x 8 x i32> zeroinitializer @@ -887,9 +879,9 @@ define <vscale x 8 x i64> @vwaddu_wx_nxv8i64_nxv8i16(<vscale x 8 x i64> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m2, ta, ma ; CHECK-NEXT: vmv.v.x v16, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vzext.vf4 v24, v16 -; CHECK-NEXT: vadd.vv v8, v8, v24 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf2 v20, v16 +; CHECK-NEXT: vwaddu.wv v8, v8, v20 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 8 x i16> %head, <vscale x 8 x i16> poison, <vscale x 8 x i32> zeroinitializer @@ -901,10 +893,10 @@ define <vscale x 8 x i64> @vwaddu_wx_nxv8i64_nxv8i16(<vscale x 8 x i64> %va, i16 define <vscale x 1 x i64> @vwadd_vv_nxv1i64_nxv1i8(<vscale x 1 x i8> %va, <vscale x 1 x i8> %vb) { ; CHECK-LABEL: vwadd_vv_nxv1i64_nxv1i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v8 -; CHECK-NEXT: vsext.vf8 v8, v9 -; CHECK-NEXT: vadd.vv v8, v10, v8 +; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v8 +; CHECK-NEXT: vsext.vf4 v11, v9 +; CHECK-NEXT: vwadd.vv v8, v10, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 1 x i8> %va to <vscale x 1 x i64> %vd = sext <vscale x 1 x i8> %vb to <vscale x 1 x i64> @@ -915,10 +907,10 @@ define <vscale x 1 x i64> @vwadd_vv_nxv1i64_nxv1i8(<vscale x 1 x i8> %va, <vscal define <vscale x 1 x i64> @vwaddu_vv_nxv1i64_nxv1i8(<vscale x 1 x i8> %va, <vscale x 1 x i8> %vb) { ; CHECK-LABEL: vwaddu_vv_nxv1i64_nxv1i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vzext.vf8 v10, v8 -; CHECK-NEXT: vzext.vf8 v8, v9 -; CHECK-NEXT: vadd.vv v8, v10, v8 +; CHECK-NEXT: vsetvli a0, zero, e8, mf8, ta, ma +; CHECK-NEXT: vwaddu.vv v10, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma +; CHECK-NEXT: vzext.vf4 v8, v10 ; CHECK-NEXT: ret %vc = zext <vscale x 1 x i8> %va to <vscale x 1 x i64> %vd = zext <vscale x 1 x i8> %vb to <vscale x 1 x i64> @@ -931,10 +923,10 @@ define <vscale x 1 x i64> @vwadd_vx_nxv1i64_nxv1i8(<vscale x 1 x i8> %va, i8 %b) ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v8 -; CHECK-NEXT: vsext.vf8 v8, v9 -; CHECK-NEXT: vadd.vv v8, v10, v8 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v8 +; CHECK-NEXT: vsext.vf4 v11, v9 +; CHECK-NEXT: vwadd.vv v8, v10, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 1 x i8> %head, <vscale x 1 x i8> poison, <vscale x 1 x i32> zeroinitializer @@ -948,11 +940,9 @@ define <vscale x 1 x i64> @vwaddu_vx_nxv1i64_nxv1i8(<vscale x 1 x i8> %va, i8 %b ; CHECK-LABEL: vwaddu_vx_nxv1i64_nxv1i8: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vwaddu.vx v9, v8, a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vzext.vf8 v10, v8 -; CHECK-NEXT: vzext.vf8 v8, v9 -; CHECK-NEXT: vadd.vv v8, v10, v8 +; CHECK-NEXT: vzext.vf4 v8, v9 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 1 x i8> %head, <vscale x 1 x i8> poison, <vscale x 1 x i32> zeroinitializer @@ -965,9 +955,9 @@ define <vscale x 1 x i64> @vwaddu_vx_nxv1i64_nxv1i8(<vscale x 1 x i8> %va, i8 %b define <vscale x 1 x i64> @vwadd_wv_nxv1i64_nxv1i8(<vscale x 1 x i64> %va, <vscale x 1 x i8> %vb) { ; CHECK-LABEL: vwadd_wv_nxv1i64_nxv1i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v9 -; CHECK-NEXT: vadd.vv v8, v8, v10 +; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v9 +; CHECK-NEXT: vwadd.wv v8, v8, v10 ; CHECK-NEXT: ret %vc = sext <vscale x 1 x i8> %vb to <vscale x 1 x i64> %vd = add <vscale x 1 x i64> %va, %vc @@ -977,9 +967,9 @@ define <vscale x 1 x i64> @vwadd_wv_nxv1i64_nxv1i8(<vscale x 1 x i64> %va, <vsca define <vscale x 1 x i64> @vwaddu_wv_nxv1i64_nxv1i8(<vscale x 1 x i64> %va, <vscale x 1 x i8> %vb) { ; CHECK-LABEL: vwaddu_wv_nxv1i64_nxv1i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vzext.vf8 v10, v9 -; CHECK-NEXT: vadd.vv v8, v8, v10 +; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma +; CHECK-NEXT: vzext.vf4 v10, v9 +; CHECK-NEXT: vwaddu.wv v8, v8, v10 ; CHECK-NEXT: ret %vc = zext <vscale x 1 x i8> %vb to <vscale x 1 x i64> %vd = add <vscale x 1 x i64> %va, %vc @@ -991,9 +981,9 @@ define <vscale x 1 x i64> @vwadd_wx_nxv1i64_nxv1i8(<vscale x 1 x i64> %va, i8 %b ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v9 -; CHECK-NEXT: vadd.vv v8, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v9 +; CHECK-NEXT: vwadd.wv v8, v8, v10 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 1 x i8> %head, <vscale x 1 x i8> poison, <vscale x 1 x i32> zeroinitializer @@ -1007,9 +997,9 @@ define <vscale x 1 x i64> @vwaddu_wx_nxv1i64_nxv1i8(<vscale x 1 x i64> %va, i8 % ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vzext.vf8 v10, v9 -; CHECK-NEXT: vadd.vv v8, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vzext.vf4 v10, v9 +; CHECK-NEXT: vwaddu.wv v8, v8, v10 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 1 x i8> %head, <vscale x 1 x i8> poison, <vscale x 1 x i32> zeroinitializer @@ -1021,10 +1011,10 @@ define <vscale x 1 x i64> @vwaddu_wx_nxv1i64_nxv1i8(<vscale x 1 x i64> %va, i8 % define <vscale x 2 x i64> @vwadd_vv_nxv2i64_nxv2i8(<vscale x 2 x i8> %va, <vscale x 2 x i8> %vb) { ; CHECK-LABEL: vwadd_vv_nxv2i64_nxv2i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v8 -; CHECK-NEXT: vsext.vf8 v12, v9 -; CHECK-NEXT: vadd.vv v8, v10, v12 +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v8 +; CHECK-NEXT: vsext.vf4 v11, v9 +; CHECK-NEXT: vwadd.vv v8, v10, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 2 x i8> %va to <vscale x 2 x i64> %vd = sext <vscale x 2 x i8> %vb to <vscale x 2 x i64> @@ -1035,10 +1025,10 @@ define <vscale x 2 x i64> @vwadd_vv_nxv2i64_nxv2i8(<vscale x 2 x i8> %va, <vscal define <vscale x 2 x i64> @vwaddu_vv_nxv2i64_nxv2i8(<vscale x 2 x i8> %va, <vscale x 2 x i8> %vb) { ; CHECK-LABEL: vwaddu_vv_nxv2i64_nxv2i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vzext.vf8 v10, v8 -; CHECK-NEXT: vzext.vf8 v12, v9 -; CHECK-NEXT: vadd.vv v8, v10, v12 +; CHECK-NEXT: vsetvli a0, zero, e8, mf4, ta, ma +; CHECK-NEXT: vwaddu.vv v10, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf4 v8, v10 ; CHECK-NEXT: ret %vc = zext <vscale x 2 x i8> %va to <vscale x 2 x i64> %vd = zext <vscale x 2 x i8> %vb to <vscale x 2 x i64> @@ -1051,10 +1041,10 @@ define <vscale x 2 x i64> @vwadd_vx_nxv2i64_nxv2i8(<vscale x 2 x i8> %va, i8 %b) ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf4, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v8 -; CHECK-NEXT: vsext.vf8 v12, v9 -; CHECK-NEXT: vadd.vv v8, v10, v12 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v8 +; CHECK-NEXT: vsext.vf4 v11, v9 +; CHECK-NEXT: vwadd.vv v8, v10, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 2 x i8> %head, <vscale x 2 x i8> poison, <vscale x 2 x i32> zeroinitializer @@ -1068,11 +1058,9 @@ define <vscale x 2 x i64> @vwaddu_vx_nxv2i64_nxv2i8(<vscale x 2 x i8> %va, i8 %b ; CHECK-LABEL: vwaddu_vx_nxv2i64_nxv2i8: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf4, ta, ma -; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vwaddu.vx v10, v8, a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vzext.vf8 v10, v8 -; CHECK-NEXT: vzext.vf8 v12, v9 -; CHECK-NEXT: vadd.vv v8, v10, v12 +; CHECK-NEXT: vzext.vf4 v8, v10 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 2 x i8> %head, <vscale x 2 x i8> poison, <vscale x 2 x i32> zeroinitializer @@ -1085,9 +1073,9 @@ define <vscale x 2 x i64> @vwaddu_vx_nxv2i64_nxv2i8(<vscale x 2 x i8> %va, i8 %b define <vscale x 2 x i64> @vwadd_wv_nxv2i64_nxv2i8(<vscale x 2 x i64> %va, <vscale x 2 x i8> %vb) { ; CHECK-LABEL: vwadd_wv_nxv2i64_nxv2i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf8 v12, v10 -; CHECK-NEXT: vadd.vv v8, v8, v12 +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf4 v11, v10 +; CHECK-NEXT: vwadd.wv v8, v8, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 2 x i8> %vb to <vscale x 2 x i64> %vd = add <vscale x 2 x i64> %va, %vc @@ -1097,9 +1085,9 @@ define <vscale x 2 x i64> @vwadd_wv_nxv2i64_nxv2i8(<vscale x 2 x i64> %va, <vsca define <vscale x 2 x i64> @vwaddu_wv_nxv2i64_nxv2i8(<vscale x 2 x i64> %va, <vscale x 2 x i8> %vb) { ; CHECK-LABEL: vwaddu_wv_nxv2i64_nxv2i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vzext.vf8 v12, v10 -; CHECK-NEXT: vadd.vv v8, v8, v12 +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vzext.vf4 v11, v10 +; CHECK-NEXT: vwaddu.wv v8, v8, v11 ; CHECK-NEXT: ret %vc = zext <vscale x 2 x i8> %vb to <vscale x 2 x i64> %vd = add <vscale x 2 x i64> %va, %vc @@ -1111,9 +1099,9 @@ define <vscale x 2 x i64> @vwadd_wx_nxv2i64_nxv2i8(<vscale x 2 x i64> %va, i8 %b ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf4, ta, ma ; CHECK-NEXT: vmv.v.x v10, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf8 v12, v10 -; CHECK-NEXT: vadd.vv v8, v8, v12 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf4 v11, v10 +; CHECK-NEXT: vwadd.wv v8, v8, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 2 x i8> %head, <vscale x 2 x i8> poison, <vscale x 2 x i32> zeroinitializer @@ -1127,9 +1115,9 @@ define <vscale x 2 x i64> @vwaddu_wx_nxv2i64_nxv2i8(<vscale x 2 x i64> %va, i8 % ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf4, ta, ma ; CHECK-NEXT: vmv.v.x v10, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vzext.vf8 v12, v10 -; CHECK-NEXT: vadd.vv v8, v8, v12 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vzext.vf4 v11, v10 +; CHECK-NEXT: vwaddu.wv v8, v8, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 2 x i8> %head, <vscale x 2 x i8> poison, <vscale x 2 x i32> zeroinitializer @@ -1141,10 +1129,10 @@ define <vscale x 2 x i64> @vwaddu_wx_nxv2i64_nxv2i8(<vscale x 2 x i64> %va, i8 % define <vscale x 4 x i64> @vwadd_vv_nxv4i64_nxv4i8(<vscale x 4 x i8> %va, <vscale x 4 x i8> %vb) { ; CHECK-LABEL: vwadd_vv_nxv4i64_nxv4i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf8 v12, v8 -; CHECK-NEXT: vsext.vf8 v16, v9 -; CHECK-NEXT: vadd.vv v8, v12, v16 +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf4 v12, v8 +; CHECK-NEXT: vsext.vf4 v14, v9 +; CHECK-NEXT: vwadd.vv v8, v12, v14 ; CHECK-NEXT: ret %vc = sext <vscale x 4 x i8> %va to <vscale x 4 x i64> %vd = sext <vscale x 4 x i8> %vb to <vscale x 4 x i64> @@ -1155,10 +1143,10 @@ define <vscale x 4 x i64> @vwadd_vv_nxv4i64_nxv4i8(<vscale x 4 x i8> %va, <vscal define <vscale x 4 x i64> @vwaddu_vv_nxv4i64_nxv4i8(<vscale x 4 x i8> %va, <vscale x 4 x i8> %vb) { ; CHECK-LABEL: vwaddu_vv_nxv4i64_nxv4i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vzext.vf8 v12, v8 -; CHECK-NEXT: vzext.vf8 v16, v9 -; CHECK-NEXT: vadd.vv v8, v12, v16 +; CHECK-NEXT: vsetvli a0, zero, e8, mf2, ta, ma +; CHECK-NEXT: vwaddu.vv v12, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma +; CHECK-NEXT: vzext.vf4 v8, v12 ; CHECK-NEXT: ret %vc = zext <vscale x 4 x i8> %va to <vscale x 4 x i64> %vd = zext <vscale x 4 x i8> %vb to <vscale x 4 x i64> @@ -1171,10 +1159,10 @@ define <vscale x 4 x i64> @vwadd_vx_nxv4i64_nxv4i8(<vscale x 4 x i8> %va, i8 %b) ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf2, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf8 v12, v8 -; CHECK-NEXT: vsext.vf8 v16, v9 -; CHECK-NEXT: vadd.vv v8, v12, v16 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf4 v12, v8 +; CHECK-NEXT: vsext.vf4 v14, v9 +; CHECK-NEXT: vwadd.vv v8, v12, v14 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 4 x i8> %head, <vscale x 4 x i8> poison, <vscale x 4 x i32> zeroinitializer @@ -1188,11 +1176,9 @@ define <vscale x 4 x i64> @vwaddu_vx_nxv4i64_nxv4i8(<vscale x 4 x i8> %va, i8 %b ; CHECK-LABEL: vwaddu_vx_nxv4i64_nxv4i8: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf2, ta, ma -; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vwaddu.vx v12, v8, a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vzext.vf8 v12, v8 -; CHECK-NEXT: vzext.vf8 v16, v9 -; CHECK-NEXT: vadd.vv v8, v12, v16 +; CHECK-NEXT: vzext.vf4 v8, v12 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 4 x i8> %head, <vscale x 4 x i8> poison, <vscale x 4 x i32> zeroinitializer @@ -1205,9 +1191,9 @@ define <vscale x 4 x i64> @vwaddu_vx_nxv4i64_nxv4i8(<vscale x 4 x i8> %va, i8 %b define <vscale x 4 x i64> @vwadd_wv_nxv4i64_nxv4i8(<vscale x 4 x i64> %va, <vscale x 4 x i8> %vb) { ; CHECK-LABEL: vwadd_wv_nxv4i64_nxv4i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf8 v16, v12 -; CHECK-NEXT: vadd.vv v8, v8, v16 +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf4 v14, v12 +; CHECK-NEXT: vwadd.wv v8, v8, v14 ; CHECK-NEXT: ret %vc = sext <vscale x 4 x i8> %vb to <vscale x 4 x i64> %vd = add <vscale x 4 x i64> %va, %vc @@ -1217,9 +1203,9 @@ define <vscale x 4 x i64> @vwadd_wv_nxv4i64_nxv4i8(<vscale x 4 x i64> %va, <vsca define <vscale x 4 x i64> @vwaddu_wv_nxv4i64_nxv4i8(<vscale x 4 x i64> %va, <vscale x 4 x i8> %vb) { ; CHECK-LABEL: vwaddu_wv_nxv4i64_nxv4i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vzext.vf8 v16, v12 -; CHECK-NEXT: vadd.vv v8, v8, v16 +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf4 v14, v12 +; CHECK-NEXT: vwaddu.wv v8, v8, v14 ; CHECK-NEXT: ret %vc = zext <vscale x 4 x i8> %vb to <vscale x 4 x i64> %vd = add <vscale x 4 x i64> %va, %vc @@ -1231,9 +1217,9 @@ define <vscale x 4 x i64> @vwadd_wx_nxv4i64_nxv4i8(<vscale x 4 x i64> %va, i8 %b ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf2, ta, ma ; CHECK-NEXT: vmv.v.x v12, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf8 v16, v12 -; CHECK-NEXT: vadd.vv v8, v8, v16 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf4 v14, v12 +; CHECK-NEXT: vwadd.wv v8, v8, v14 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 4 x i8> %head, <vscale x 4 x i8> poison, <vscale x 4 x i32> zeroinitializer @@ -1247,9 +1233,9 @@ define <vscale x 4 x i64> @vwaddu_wx_nxv4i64_nxv4i8(<vscale x 4 x i64> %va, i8 % ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf2, ta, ma ; CHECK-NEXT: vmv.v.x v12, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vzext.vf8 v16, v12 -; CHECK-NEXT: vadd.vv v8, v8, v16 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf4 v14, v12 +; CHECK-NEXT: vwaddu.wv v8, v8, v14 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 4 x i8> %head, <vscale x 4 x i8> poison, <vscale x 4 x i32> zeroinitializer @@ -1261,10 +1247,10 @@ define <vscale x 4 x i64> @vwaddu_wx_nxv4i64_nxv4i8(<vscale x 4 x i64> %va, i8 % define <vscale x 8 x i64> @vwadd_vv_nxv8i64_nxv8i8(<vscale x 8 x i8> %va, <vscale x 8 x i8> %vb) { ; CHECK-LABEL: vwadd_vv_nxv8i64_nxv8i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf8 v16, v8 -; CHECK-NEXT: vsext.vf8 v24, v9 -; CHECK-NEXT: vadd.vv v8, v16, v24 +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf4 v16, v8 +; CHECK-NEXT: vsext.vf4 v20, v9 +; CHECK-NEXT: vwadd.vv v8, v16, v20 ; CHECK-NEXT: ret %vc = sext <vscale x 8 x i8> %va to <vscale x 8 x i64> %vd = sext <vscale x 8 x i8> %vb to <vscale x 8 x i64> @@ -1275,10 +1261,10 @@ define <vscale x 8 x i64> @vwadd_vv_nxv8i64_nxv8i8(<vscale x 8 x i8> %va, <vscal define <vscale x 8 x i64> @vwaddu_vv_nxv8i64_nxv8i8(<vscale x 8 x i8> %va, <vscale x 8 x i8> %vb) { ; CHECK-LABEL: vwaddu_vv_nxv8i64_nxv8i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vzext.vf8 v16, v8 -; CHECK-NEXT: vzext.vf8 v24, v9 -; CHECK-NEXT: vadd.vv v8, v16, v24 +; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma +; CHECK-NEXT: vwaddu.vv v16, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma +; CHECK-NEXT: vzext.vf4 v8, v16 ; CHECK-NEXT: ret %vc = zext <vscale x 8 x i8> %va to <vscale x 8 x i64> %vd = zext <vscale x 8 x i8> %vb to <vscale x 8 x i64> @@ -1291,10 +1277,10 @@ define <vscale x 8 x i64> @vwadd_vx_nxv8i64_nxv8i8(<vscale x 8 x i8> %va, i8 %b) ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, m1, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf8 v16, v8 -; CHECK-NEXT: vsext.vf8 v24, v9 -; CHECK-NEXT: vadd.vv v8, v16, v24 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf4 v16, v8 +; CHECK-NEXT: vsext.vf4 v20, v9 +; CHECK-NEXT: vwadd.vv v8, v16, v20 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 8 x i8> %head, <vscale x 8 x i8> poison, <vscale x 8 x i32> zeroinitializer @@ -1308,11 +1294,9 @@ define <vscale x 8 x i64> @vwaddu_vx_nxv8i64_nxv8i8(<vscale x 8 x i8> %va, i8 %b ; CHECK-LABEL: vwaddu_vx_nxv8i64_nxv8i8: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, m1, ta, ma -; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vwaddu.vx v16, v8, a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vzext.vf8 v16, v8 -; CHECK-NEXT: vzext.vf8 v24, v9 -; CHECK-NEXT: vadd.vv v8, v16, v24 +; CHECK-NEXT: vzext.vf4 v8, v16 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 8 x i8> %head, <vscale x 8 x i8> poison, <vscale x 8 x i32> zeroinitializer @@ -1325,9 +1309,9 @@ define <vscale x 8 x i64> @vwaddu_vx_nxv8i64_nxv8i8(<vscale x 8 x i8> %va, i8 %b define <vscale x 8 x i64> @vwadd_wv_nxv8i64_nxv8i8(<vscale x 8 x i64> %va, <vscale x 8 x i8> %vb) { ; CHECK-LABEL: vwadd_wv_nxv8i64_nxv8i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf8 v24, v16 -; CHECK-NEXT: vadd.vv v8, v8, v24 +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf4 v20, v16 +; CHECK-NEXT: vwadd.wv v8, v8, v20 ; CHECK-NEXT: ret %vc = sext <vscale x 8 x i8> %vb to <vscale x 8 x i64> %vd = add <vscale x 8 x i64> %va, %vc @@ -1337,9 +1321,9 @@ define <vscale x 8 x i64> @vwadd_wv_nxv8i64_nxv8i8(<vscale x 8 x i64> %va, <vsca define <vscale x 8 x i64> @vwaddu_wv_nxv8i64_nxv8i8(<vscale x 8 x i64> %va, <vscale x 8 x i8> %vb) { ; CHECK-LABEL: vwaddu_wv_nxv8i64_nxv8i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vzext.vf8 v24, v16 -; CHECK-NEXT: vadd.vv v8, v8, v24 +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf4 v20, v16 +; CHECK-NEXT: vwaddu.wv v8, v8, v20 ; CHECK-NEXT: ret %vc = zext <vscale x 8 x i8> %vb to <vscale x 8 x i64> %vd = add <vscale x 8 x i64> %va, %vc @@ -1351,9 +1335,9 @@ define <vscale x 8 x i64> @vwadd_wx_nxv8i64_nxv8i8(<vscale x 8 x i64> %va, i8 %b ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, m1, ta, ma ; CHECK-NEXT: vmv.v.x v16, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf8 v24, v16 -; CHECK-NEXT: vadd.vv v8, v8, v24 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf4 v20, v16 +; CHECK-NEXT: vwadd.wv v8, v8, v20 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 8 x i8> %head, <vscale x 8 x i8> poison, <vscale x 8 x i32> zeroinitializer @@ -1367,9 +1351,9 @@ define <vscale x 8 x i64> @vwaddu_wx_nxv8i64_nxv8i8(<vscale x 8 x i64> %va, i8 % ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, m1, ta, ma ; CHECK-NEXT: vmv.v.x v16, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vzext.vf8 v24, v16 -; CHECK-NEXT: vadd.vv v8, v8, v24 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf4 v20, v16 +; CHECK-NEXT: vwaddu.wv v8, v8, v20 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 8 x i8> %head, <vscale x 8 x i8> poison, <vscale x 8 x i32> zeroinitializer @@ -1377,3 +1361,108 @@ define <vscale x 8 x i64> @vwaddu_wx_nxv8i64_nxv8i8(<vscale x 8 x i64> %va, i8 % %vc = add <vscale x 8 x i64> %va, %vb ret <vscale x 8 x i64> %vc } + +; Make sure that we don't introduce any V{S,Z}EXT_VL nodes with i1 types from +; combineBinOp_VLToVWBinOp_VL, since they can't be selected. +define <vscale x 1 x i64> @i1_zext(<vscale x 1 x i1> %va, <vscale x 1 x i64> %vb, ptr %p) { +; RV32-LABEL: i1_zext: +; RV32: # %bb.0: +; RV32-NEXT: vsetvli a1, zero, e64, m1, ta, ma +; RV32-NEXT: vmv.v.i v9, 0 +; RV32-NEXT: vmerge.vim v9, v9, 1, v0 +; RV32-NEXT: vadd.vv v8, v9, v8 +; RV32-NEXT: li a1, 42 +; RV32-NEXT: sh a1, 0(a0) +; RV32-NEXT: ret +; +; RV64-LABEL: i1_zext: +; RV64: # %bb.0: +; RV64-NEXT: vsetvli a1, zero, e64, m1, ta, mu +; RV64-NEXT: vadd.vi v8, v8, 1, v0.t +; RV64-NEXT: li a1, 42 +; RV64-NEXT: sh a1, 0(a0) +; RV64-NEXT: ret + %vc = zext <vscale x 1 x i1> %va to <vscale x 1 x i64> + %vd = add <vscale x 1 x i64> %vc, %vb + +; Introduce an illegal type so that the DAG changes after legalizing +; types. Otherwise the legalize vector ops phase will be run immediately after +; the legalize types phase, and the zext will already be in non-i1 form by the +; time combineBinOp_VLToVWBinOp_VL is called. + store i9 42, ptr %p + ret <vscale x 1 x i64> %vd +} + +; %x.i32 and %y.i32 are disjoint, so DAGCombiner will combine it into an or. +; FIXME: We should be able to recover the or into vwaddu.vv if the disjoint +; flag is set. +define <vscale x 2 x i32> @vwaddu_vv_disjoint_or_add(<vscale x 2 x i8> %x.i8, <vscale x 2 x i8> %y.i8) { +; CHECK-LABEL: vwaddu_vv_disjoint_or_add: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, mf2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v8 +; CHECK-NEXT: vsll.vi v10, v10, 8 +; CHECK-NEXT: vzext.vf2 v11, v9 +; CHECK-NEXT: vwaddu.vv v8, v10, v11 +; CHECK-NEXT: ret + %x.i16 = zext <vscale x 2 x i8> %x.i8 to <vscale x 2 x i16> + %x.shl = shl <vscale x 2 x i16> %x.i16, shufflevector(<vscale x 2 x i16> insertelement(<vscale x 2 x i16> poison, i16 8, i32 0), <vscale x 2 x i16> poison, <vscale x 2 x i32> zeroinitializer) + %x.i32 = zext <vscale x 2 x i16> %x.shl to <vscale x 2 x i32> + %y.i32 = zext <vscale x 2 x i8> %y.i8 to <vscale x 2 x i32> + %add = add <vscale x 2 x i32> %x.i32, %y.i32 + ret <vscale x 2 x i32> %add +} + +; TODO: We could select vwaddu.vv, but when both arms of the or are the same +; DAGCombiner::hoistLogicOpWithSameOpcodeHands moves the zext above the or. +define <vscale x 2 x i32> @vwaddu_vv_disjoint_or(<vscale x 2 x i16> %x.i16, <vscale x 2 x i16> %y.i16) { +; CHECK-LABEL: vwaddu_vv_disjoint_or: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, mf2, ta, ma +; CHECK-NEXT: vor.vv v9, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v9 +; CHECK-NEXT: ret + %x.i32 = zext <vscale x 2 x i16> %x.i16 to <vscale x 2 x i32> + %y.i32 = zext <vscale x 2 x i16> %y.i16 to <vscale x 2 x i32> + %or = or disjoint <vscale x 2 x i32> %x.i32, %y.i32 + ret <vscale x 2 x i32> %or +} + +; TODO: We could select vwadd.vv, but when both arms of the or are the same +; DAGCombiner::hoistLogicOpWithSameOpcodeHands moves the zext above the or. +define <vscale x 2 x i32> @vwadd_vv_disjoint_or(<vscale x 2 x i16> %x.i16, <vscale x 2 x i16> %y.i16) { +; CHECK-LABEL: vwadd_vv_disjoint_or: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, mf2, ta, ma +; CHECK-NEXT: vor.vv v9, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf2 v8, v9 +; CHECK-NEXT: ret + %x.i32 = sext <vscale x 2 x i16> %x.i16 to <vscale x 2 x i32> + %y.i32 = sext <vscale x 2 x i16> %y.i16 to <vscale x 2 x i32> + %or = or disjoint <vscale x 2 x i32> %x.i32, %y.i32 + ret <vscale x 2 x i32> %or +} + +define <vscale x 2 x i32> @vwaddu_wv_disjoint_or(<vscale x 2 x i32> %x.i32, <vscale x 2 x i16> %y.i16) { +; CHECK-LABEL: vwaddu_wv_disjoint_or: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, mf2, ta, ma +; CHECK-NEXT: vwaddu.wv v8, v8, v9 +; CHECK-NEXT: ret + %y.i32 = zext <vscale x 2 x i16> %y.i16 to <vscale x 2 x i32> + %or = or disjoint <vscale x 2 x i32> %x.i32, %y.i32 + ret <vscale x 2 x i32> %or +} + +define <vscale x 2 x i32> @vwadd_wv_disjoint_or(<vscale x 2 x i32> %x.i32, <vscale x 2 x i16> %y.i16) { +; CHECK-LABEL: vwadd_wv_disjoint_or: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16, mf2, ta, ma +; CHECK-NEXT: vwadd.wv v8, v8, v9 +; CHECK-NEXT: ret + %y.i32 = sext <vscale x 2 x i16> %y.i16 to <vscale x 2 x i32> + %or = or disjoint <vscale x 2 x i32> %x.i32, %y.i32 + ret <vscale x 2 x i32> %or +} diff --git a/llvm/test/CodeGen/RISCV/rvv/vwmul-sdnode.ll b/llvm/test/CodeGen/RISCV/rvv/vwmul-sdnode.ll index 3634162eefd642f8047497beaab14729c15784cc..28fc53f37ba1d39440fd0fcedacab405ab85b70f 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vwmul-sdnode.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vwmul-sdnode.ll @@ -341,10 +341,10 @@ define <vscale x 8 x i64> @vwmulsu_vx_nxv8i64_nxv8i32(<vscale x 8 x i32> %va, i3 define <vscale x 1 x i64> @vwmul_vv_nxv1i64_nxv1i16(<vscale x 1 x i16> %va, <vscale x 1 x i16> %vb) { ; CHECK-LABEL: vwmul_vv_nxv1i64_nxv1i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v8 -; CHECK-NEXT: vsext.vf4 v8, v9 -; CHECK-NEXT: vmul.vv v8, v10, v8 +; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf2 v11, v9 +; CHECK-NEXT: vwmul.vv v8, v10, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 1 x i16> %va to <vscale x 1 x i64> %vd = sext <vscale x 1 x i16> %vb to <vscale x 1 x i64> @@ -355,10 +355,10 @@ define <vscale x 1 x i64> @vwmul_vv_nxv1i64_nxv1i16(<vscale x 1 x i16> %va, <vsc define <vscale x 1 x i64> @vwmulu_vv_nxv1i64_nxv1i16(<vscale x 1 x i16> %va, <vscale x 1 x i16> %vb) { ; CHECK-LABEL: vwmulu_vv_nxv1i64_nxv1i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vzext.vf4 v10, v8 -; CHECK-NEXT: vzext.vf4 v8, v9 -; CHECK-NEXT: vmul.vv v8, v10, v8 +; CHECK-NEXT: vsetvli a0, zero, e16, mf4, ta, ma +; CHECK-NEXT: vwmulu.vv v10, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v10 ; CHECK-NEXT: ret %vc = zext <vscale x 1 x i16> %va to <vscale x 1 x i64> %vd = zext <vscale x 1 x i16> %vb to <vscale x 1 x i64> @@ -369,10 +369,10 @@ define <vscale x 1 x i64> @vwmulu_vv_nxv1i64_nxv1i16(<vscale x 1 x i16> %va, <vs define <vscale x 1 x i64> @vwmulsu_vv_nxv1i64_nxv1i16(<vscale x 1 x i16> %va, <vscale x 1 x i16> %vb) { ; CHECK-LABEL: vwmulsu_vv_nxv1i64_nxv1i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v8 -; CHECK-NEXT: vzext.vf4 v8, v9 -; CHECK-NEXT: vmul.vv v8, v10, v8 +; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v8 +; CHECK-NEXT: vzext.vf2 v11, v9 +; CHECK-NEXT: vwmulsu.vv v8, v10, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 1 x i16> %va to <vscale x 1 x i64> %vd = zext <vscale x 1 x i16> %vb to <vscale x 1 x i64> @@ -385,10 +385,10 @@ define <vscale x 1 x i64> @vwmul_vx_nxv1i64_nxv1i16(<vscale x 1 x i16> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf4, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v8 -; CHECK-NEXT: vsext.vf4 v8, v9 -; CHECK-NEXT: vmul.vv v8, v10, v8 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf2 v11, v9 +; CHECK-NEXT: vwmul.vv v8, v10, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i16> undef, i16 %b, i16 0 %splat = shufflevector <vscale x 1 x i16> %head, <vscale x 1 x i16> undef, <vscale x 1 x i32> zeroinitializer @@ -402,11 +402,9 @@ define <vscale x 1 x i64> @vwmulu_vx_nxv1i64_nxv1i16(<vscale x 1 x i16> %va, i16 ; CHECK-LABEL: vwmulu_vx_nxv1i64_nxv1i16: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf4, ta, ma -; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vwmulu.vx v9, v8, a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vzext.vf4 v10, v8 -; CHECK-NEXT: vzext.vf4 v8, v9 -; CHECK-NEXT: vmul.vv v8, v10, v8 +; CHECK-NEXT: vzext.vf2 v8, v9 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i16> undef, i16 %b, i16 0 %splat = shufflevector <vscale x 1 x i16> %head, <vscale x 1 x i16> undef, <vscale x 1 x i32> zeroinitializer @@ -421,10 +419,10 @@ define <vscale x 1 x i64> @vwmulsu_vx_nxv1i64_nxv1i16(<vscale x 1 x i16> %va, i1 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf4, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v8 -; CHECK-NEXT: vzext.vf4 v8, v9 -; CHECK-NEXT: vmul.vv v8, v10, v8 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v8 +; CHECK-NEXT: vzext.vf2 v11, v9 +; CHECK-NEXT: vwmulsu.vv v8, v10, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i16> undef, i16 %b, i16 0 %splat = shufflevector <vscale x 1 x i16> %head, <vscale x 1 x i16> undef, <vscale x 1 x i32> zeroinitializer @@ -437,10 +435,10 @@ define <vscale x 1 x i64> @vwmulsu_vx_nxv1i64_nxv1i16(<vscale x 1 x i16> %va, i1 define <vscale x 2 x i64> @vwmul_vv_nxv2i64_nxv2i16(<vscale x 2 x i16> %va, <vscale x 2 x i16> %vb) { ; CHECK-LABEL: vwmul_vv_nxv2i64_nxv2i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v8 -; CHECK-NEXT: vsext.vf4 v12, v9 -; CHECK-NEXT: vmul.vv v8, v10, v12 +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf2 v11, v9 +; CHECK-NEXT: vwmul.vv v8, v10, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 2 x i16> %va to <vscale x 2 x i64> %vd = sext <vscale x 2 x i16> %vb to <vscale x 2 x i64> @@ -451,10 +449,10 @@ define <vscale x 2 x i64> @vwmul_vv_nxv2i64_nxv2i16(<vscale x 2 x i16> %va, <vsc define <vscale x 2 x i64> @vwmulu_vv_nxv2i64_nxv2i16(<vscale x 2 x i16> %va, <vscale x 2 x i16> %vb) { ; CHECK-LABEL: vwmulu_vv_nxv2i64_nxv2i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vzext.vf4 v10, v8 -; CHECK-NEXT: vzext.vf4 v12, v9 -; CHECK-NEXT: vmul.vv v8, v10, v12 +; CHECK-NEXT: vsetvli a0, zero, e16, mf2, ta, ma +; CHECK-NEXT: vwmulu.vv v10, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v10 ; CHECK-NEXT: ret %vc = zext <vscale x 2 x i16> %va to <vscale x 2 x i64> %vd = zext <vscale x 2 x i16> %vb to <vscale x 2 x i64> @@ -465,10 +463,10 @@ define <vscale x 2 x i64> @vwmulu_vv_nxv2i64_nxv2i16(<vscale x 2 x i16> %va, <vs define <vscale x 2 x i64> @vwmulsu_vv_nxv2i64_nxv2i16(<vscale x 2 x i16> %va, <vscale x 2 x i16> %vb) { ; CHECK-LABEL: vwmulsu_vv_nxv2i64_nxv2i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v8 -; CHECK-NEXT: vzext.vf4 v12, v9 -; CHECK-NEXT: vmul.vv v8, v10, v12 +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v8 +; CHECK-NEXT: vzext.vf2 v11, v9 +; CHECK-NEXT: vwmulsu.vv v8, v10, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 2 x i16> %va to <vscale x 2 x i64> %vd = zext <vscale x 2 x i16> %vb to <vscale x 2 x i64> @@ -481,10 +479,10 @@ define <vscale x 2 x i64> @vwmul_vx_nxv2i64_nxv2i16(<vscale x 2 x i16> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf2, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v8 -; CHECK-NEXT: vsext.vf4 v12, v9 -; CHECK-NEXT: vmul.vv v8, v10, v12 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf2 v11, v9 +; CHECK-NEXT: vwmul.vv v8, v10, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i16> undef, i16 %b, i16 0 %splat = shufflevector <vscale x 2 x i16> %head, <vscale x 2 x i16> undef, <vscale x 2 x i32> zeroinitializer @@ -498,11 +496,9 @@ define <vscale x 2 x i64> @vwmulu_vx_nxv2i64_nxv2i16(<vscale x 2 x i16> %va, i16 ; CHECK-LABEL: vwmulu_vx_nxv2i64_nxv2i16: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf2, ta, ma -; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vwmulu.vx v10, v8, a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vzext.vf4 v10, v8 -; CHECK-NEXT: vzext.vf4 v12, v9 -; CHECK-NEXT: vmul.vv v8, v10, v12 +; CHECK-NEXT: vzext.vf2 v8, v10 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i16> undef, i16 %b, i16 0 %splat = shufflevector <vscale x 2 x i16> %head, <vscale x 2 x i16> undef, <vscale x 2 x i32> zeroinitializer @@ -517,10 +513,10 @@ define <vscale x 2 x i64> @vwmulsu_vx_nxv2i64_nxv2i16(<vscale x 2 x i16> %va, i1 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf2, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v8 -; CHECK-NEXT: vzext.vf4 v12, v9 -; CHECK-NEXT: vmul.vv v8, v10, v12 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v8 +; CHECK-NEXT: vzext.vf2 v11, v9 +; CHECK-NEXT: vwmulsu.vv v8, v10, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i16> undef, i16 %b, i16 0 %splat = shufflevector <vscale x 2 x i16> %head, <vscale x 2 x i16> undef, <vscale x 2 x i32> zeroinitializer @@ -533,10 +529,10 @@ define <vscale x 2 x i64> @vwmulsu_vx_nxv2i64_nxv2i16(<vscale x 2 x i16> %va, i1 define <vscale x 4 x i64> @vwmul_vv_nxv4i64_nxv4i16(<vscale x 4 x i16> %va, <vscale x 4 x i16> %vb) { ; CHECK-LABEL: vwmul_vv_nxv4i64_nxv4i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf4 v12, v8 -; CHECK-NEXT: vsext.vf4 v16, v9 -; CHECK-NEXT: vmul.vv v8, v12, v16 +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf2 v12, v8 +; CHECK-NEXT: vsext.vf2 v14, v9 +; CHECK-NEXT: vwmul.vv v8, v12, v14 ; CHECK-NEXT: ret %vc = sext <vscale x 4 x i16> %va to <vscale x 4 x i64> %vd = sext <vscale x 4 x i16> %vb to <vscale x 4 x i64> @@ -547,10 +543,10 @@ define <vscale x 4 x i64> @vwmul_vv_nxv4i64_nxv4i16(<vscale x 4 x i16> %va, <vsc define <vscale x 4 x i64> @vwmulu_vv_nxv4i64_nxv4i16(<vscale x 4 x i16> %va, <vscale x 4 x i16> %vb) { ; CHECK-LABEL: vwmulu_vv_nxv4i64_nxv4i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vzext.vf4 v12, v8 -; CHECK-NEXT: vzext.vf4 v16, v9 -; CHECK-NEXT: vmul.vv v8, v12, v16 +; CHECK-NEXT: vsetvli a0, zero, e16, m1, ta, ma +; CHECK-NEXT: vwmulu.vv v12, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v12 ; CHECK-NEXT: ret %vc = zext <vscale x 4 x i16> %va to <vscale x 4 x i64> %vd = zext <vscale x 4 x i16> %vb to <vscale x 4 x i64> @@ -561,10 +557,10 @@ define <vscale x 4 x i64> @vwmulu_vv_nxv4i64_nxv4i16(<vscale x 4 x i16> %va, <vs define <vscale x 4 x i64> @vwmulsu_vv_nxv4i64_nxv4i16(<vscale x 4 x i16> %va, <vscale x 4 x i16> %vb) { ; CHECK-LABEL: vwmulsu_vv_nxv4i64_nxv4i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf4 v12, v8 -; CHECK-NEXT: vzext.vf4 v16, v9 -; CHECK-NEXT: vmul.vv v8, v12, v16 +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf2 v12, v8 +; CHECK-NEXT: vzext.vf2 v14, v9 +; CHECK-NEXT: vwmulsu.vv v8, v12, v14 ; CHECK-NEXT: ret %vc = sext <vscale x 4 x i16> %va to <vscale x 4 x i64> %vd = zext <vscale x 4 x i16> %vb to <vscale x 4 x i64> @@ -577,10 +573,10 @@ define <vscale x 4 x i64> @vwmul_vx_nxv4i64_nxv4i16(<vscale x 4 x i16> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m1, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf4 v12, v8 -; CHECK-NEXT: vsext.vf4 v16, v9 -; CHECK-NEXT: vmul.vv v8, v12, v16 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf2 v12, v8 +; CHECK-NEXT: vsext.vf2 v14, v9 +; CHECK-NEXT: vwmul.vv v8, v12, v14 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i16> undef, i16 %b, i16 0 %splat = shufflevector <vscale x 4 x i16> %head, <vscale x 4 x i16> undef, <vscale x 4 x i32> zeroinitializer @@ -594,11 +590,9 @@ define <vscale x 4 x i64> @vwmulu_vx_nxv4i64_nxv4i16(<vscale x 4 x i16> %va, i16 ; CHECK-LABEL: vwmulu_vx_nxv4i64_nxv4i16: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m1, ta, ma -; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vwmulu.vx v12, v8, a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vzext.vf4 v12, v8 -; CHECK-NEXT: vzext.vf4 v16, v9 -; CHECK-NEXT: vmul.vv v8, v12, v16 +; CHECK-NEXT: vzext.vf2 v8, v12 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i16> undef, i16 %b, i16 0 %splat = shufflevector <vscale x 4 x i16> %head, <vscale x 4 x i16> undef, <vscale x 4 x i32> zeroinitializer @@ -613,10 +607,10 @@ define <vscale x 4 x i64> @vwmulsu_vx_nxv4i64_nxv4i16(<vscale x 4 x i16> %va, i1 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m1, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf4 v12, v8 -; CHECK-NEXT: vzext.vf4 v16, v9 -; CHECK-NEXT: vmul.vv v8, v12, v16 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf2 v12, v8 +; CHECK-NEXT: vzext.vf2 v14, v9 +; CHECK-NEXT: vwmulsu.vv v8, v12, v14 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i16> undef, i16 %b, i16 0 %splat = shufflevector <vscale x 4 x i16> %head, <vscale x 4 x i16> undef, <vscale x 4 x i32> zeroinitializer @@ -629,10 +623,10 @@ define <vscale x 4 x i64> @vwmulsu_vx_nxv4i64_nxv4i16(<vscale x 4 x i16> %va, i1 define <vscale x 8 x i64> @vwmul_vv_nxv8i64_nxv8i16(<vscale x 8 x i16> %va, <vscale x 8 x i16> %vb) { ; CHECK-LABEL: vwmul_vv_nxv8i64_nxv8i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf4 v16, v8 -; CHECK-NEXT: vsext.vf4 v24, v10 -; CHECK-NEXT: vmul.vv v8, v16, v24 +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf2 v16, v8 +; CHECK-NEXT: vsext.vf2 v20, v10 +; CHECK-NEXT: vwmul.vv v8, v16, v20 ; CHECK-NEXT: ret %vc = sext <vscale x 8 x i16> %va to <vscale x 8 x i64> %vd = sext <vscale x 8 x i16> %vb to <vscale x 8 x i64> @@ -643,10 +637,10 @@ define <vscale x 8 x i64> @vwmul_vv_nxv8i64_nxv8i16(<vscale x 8 x i16> %va, <vsc define <vscale x 8 x i64> @vwmulu_vv_nxv8i64_nxv8i16(<vscale x 8 x i16> %va, <vscale x 8 x i16> %vb) { ; CHECK-LABEL: vwmulu_vv_nxv8i64_nxv8i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vzext.vf4 v16, v8 -; CHECK-NEXT: vzext.vf4 v24, v10 -; CHECK-NEXT: vmul.vv v8, v16, v24 +; CHECK-NEXT: vsetvli a0, zero, e16, m2, ta, ma +; CHECK-NEXT: vwmulu.vv v16, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma +; CHECK-NEXT: vzext.vf2 v8, v16 ; CHECK-NEXT: ret %vc = zext <vscale x 8 x i16> %va to <vscale x 8 x i64> %vd = zext <vscale x 8 x i16> %vb to <vscale x 8 x i64> @@ -657,10 +651,10 @@ define <vscale x 8 x i64> @vwmulu_vv_nxv8i64_nxv8i16(<vscale x 8 x i16> %va, <vs define <vscale x 8 x i64> @vwmulsu_vv_nxv8i64_nxv8i16(<vscale x 8 x i16> %va, <vscale x 8 x i16> %vb) { ; CHECK-LABEL: vwmulsu_vv_nxv8i64_nxv8i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf4 v16, v8 -; CHECK-NEXT: vzext.vf4 v24, v10 -; CHECK-NEXT: vmul.vv v8, v16, v24 +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf2 v16, v8 +; CHECK-NEXT: vzext.vf2 v20, v10 +; CHECK-NEXT: vwmulsu.vv v8, v16, v20 ; CHECK-NEXT: ret %vc = sext <vscale x 8 x i16> %va to <vscale x 8 x i64> %vd = zext <vscale x 8 x i16> %vb to <vscale x 8 x i64> @@ -673,10 +667,10 @@ define <vscale x 8 x i64> @vwmul_vx_nxv8i64_nxv8i16(<vscale x 8 x i16> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m2, ta, ma ; CHECK-NEXT: vmv.v.x v10, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf4 v16, v8 -; CHECK-NEXT: vsext.vf4 v24, v10 -; CHECK-NEXT: vmul.vv v8, v16, v24 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf2 v16, v8 +; CHECK-NEXT: vsext.vf2 v20, v10 +; CHECK-NEXT: vwmul.vv v8, v16, v20 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i16> undef, i16 %b, i16 0 %splat = shufflevector <vscale x 8 x i16> %head, <vscale x 8 x i16> undef, <vscale x 8 x i32> zeroinitializer @@ -690,11 +684,9 @@ define <vscale x 8 x i64> @vwmulu_vx_nxv8i64_nxv8i16(<vscale x 8 x i16> %va, i16 ; CHECK-LABEL: vwmulu_vx_nxv8i64_nxv8i16: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m2, ta, ma -; CHECK-NEXT: vmv.v.x v10, a0 +; CHECK-NEXT: vwmulu.vx v16, v8, a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vzext.vf4 v16, v8 -; CHECK-NEXT: vzext.vf4 v24, v10 -; CHECK-NEXT: vmul.vv v8, v16, v24 +; CHECK-NEXT: vzext.vf2 v8, v16 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i16> undef, i16 %b, i16 0 %splat = shufflevector <vscale x 8 x i16> %head, <vscale x 8 x i16> undef, <vscale x 8 x i32> zeroinitializer @@ -709,10 +701,10 @@ define <vscale x 8 x i64> @vwmulsu_vx_nxv8i64_nxv8i16(<vscale x 8 x i16> %va, i1 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m2, ta, ma ; CHECK-NEXT: vmv.v.x v10, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf4 v16, v8 -; CHECK-NEXT: vzext.vf4 v24, v10 -; CHECK-NEXT: vmul.vv v8, v16, v24 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf2 v16, v8 +; CHECK-NEXT: vzext.vf2 v20, v10 +; CHECK-NEXT: vwmulsu.vv v8, v16, v20 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i16> undef, i16 %b, i16 0 %splat = shufflevector <vscale x 8 x i16> %head, <vscale x 8 x i16> undef, <vscale x 8 x i32> zeroinitializer @@ -725,10 +717,10 @@ define <vscale x 8 x i64> @vwmulsu_vx_nxv8i64_nxv8i16(<vscale x 8 x i16> %va, i1 define <vscale x 1 x i64> @vwmul_vv_nxv1i64_nxv1i8(<vscale x 1 x i8> %va, <vscale x 1 x i8> %vb) { ; CHECK-LABEL: vwmul_vv_nxv1i64_nxv1i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v8 -; CHECK-NEXT: vsext.vf8 v8, v9 -; CHECK-NEXT: vmul.vv v8, v10, v8 +; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v8 +; CHECK-NEXT: vsext.vf4 v11, v9 +; CHECK-NEXT: vwmul.vv v8, v10, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 1 x i8> %va to <vscale x 1 x i64> %vd = sext <vscale x 1 x i8> %vb to <vscale x 1 x i64> @@ -739,10 +731,10 @@ define <vscale x 1 x i64> @vwmul_vv_nxv1i64_nxv1i8(<vscale x 1 x i8> %va, <vscal define <vscale x 1 x i64> @vwmulu_vv_nxv1i64_nxv1i8(<vscale x 1 x i8> %va, <vscale x 1 x i8> %vb) { ; CHECK-LABEL: vwmulu_vv_nxv1i64_nxv1i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vzext.vf8 v10, v8 -; CHECK-NEXT: vzext.vf8 v8, v9 -; CHECK-NEXT: vmul.vv v8, v10, v8 +; CHECK-NEXT: vsetvli a0, zero, e8, mf8, ta, ma +; CHECK-NEXT: vwmulu.vv v10, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma +; CHECK-NEXT: vzext.vf4 v8, v10 ; CHECK-NEXT: ret %vc = zext <vscale x 1 x i8> %va to <vscale x 1 x i64> %vd = zext <vscale x 1 x i8> %vb to <vscale x 1 x i64> @@ -753,10 +745,10 @@ define <vscale x 1 x i64> @vwmulu_vv_nxv1i64_nxv1i8(<vscale x 1 x i8> %va, <vsca define <vscale x 1 x i64> @vwmulsu_vv_nxv1i64_nxv1i8(<vscale x 1 x i8> %va, <vscale x 1 x i8> %vb) { ; CHECK-LABEL: vwmulsu_vv_nxv1i64_nxv1i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v8 -; CHECK-NEXT: vzext.vf8 v8, v9 -; CHECK-NEXT: vmul.vv v8, v10, v8 +; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v8 +; CHECK-NEXT: vzext.vf4 v11, v9 +; CHECK-NEXT: vwmulsu.vv v8, v10, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 1 x i8> %va to <vscale x 1 x i64> %vd = zext <vscale x 1 x i8> %vb to <vscale x 1 x i64> @@ -769,10 +761,10 @@ define <vscale x 1 x i64> @vwmul_vx_nxv1i64_nxv1i8(<vscale x 1 x i8> %va, i8 %b) ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v8 -; CHECK-NEXT: vsext.vf8 v8, v9 -; CHECK-NEXT: vmul.vv v8, v10, v8 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v8 +; CHECK-NEXT: vsext.vf4 v11, v9 +; CHECK-NEXT: vwmul.vv v8, v10, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i8> undef, i8 %b, i8 0 %splat = shufflevector <vscale x 1 x i8> %head, <vscale x 1 x i8> undef, <vscale x 1 x i32> zeroinitializer @@ -786,11 +778,9 @@ define <vscale x 1 x i64> @vwmulu_vx_nxv1i64_nxv1i8(<vscale x 1 x i8> %va, i8 %b ; CHECK-LABEL: vwmulu_vx_nxv1i64_nxv1i8: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma -; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vwmulu.vx v9, v8, a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vzext.vf8 v10, v8 -; CHECK-NEXT: vzext.vf8 v8, v9 -; CHECK-NEXT: vmul.vv v8, v10, v8 +; CHECK-NEXT: vzext.vf4 v8, v9 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i8> undef, i8 %b, i8 0 %splat = shufflevector <vscale x 1 x i8> %head, <vscale x 1 x i8> undef, <vscale x 1 x i32> zeroinitializer @@ -805,10 +795,10 @@ define <vscale x 1 x i64> @vwmulsu_vx_nxv1i64_nxv1i8(<vscale x 1 x i8> %va, i8 % ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v8 -; CHECK-NEXT: vzext.vf8 v8, v9 -; CHECK-NEXT: vmul.vv v8, v10, v8 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v8 +; CHECK-NEXT: vzext.vf4 v11, v9 +; CHECK-NEXT: vwmulsu.vv v8, v10, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i8> undef, i8 %b, i8 0 %splat = shufflevector <vscale x 1 x i8> %head, <vscale x 1 x i8> undef, <vscale x 1 x i32> zeroinitializer @@ -821,10 +811,10 @@ define <vscale x 1 x i64> @vwmulsu_vx_nxv1i64_nxv1i8(<vscale x 1 x i8> %va, i8 % define <vscale x 2 x i64> @vwmul_vv_nxv2i64_nxv2i8(<vscale x 2 x i8> %va, <vscale x 2 x i8> %vb) { ; CHECK-LABEL: vwmul_vv_nxv2i64_nxv2i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v8 -; CHECK-NEXT: vsext.vf8 v12, v9 -; CHECK-NEXT: vmul.vv v8, v10, v12 +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v8 +; CHECK-NEXT: vsext.vf4 v11, v9 +; CHECK-NEXT: vwmul.vv v8, v10, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 2 x i8> %va to <vscale x 2 x i64> %vd = sext <vscale x 2 x i8> %vb to <vscale x 2 x i64> @@ -835,10 +825,10 @@ define <vscale x 2 x i64> @vwmul_vv_nxv2i64_nxv2i8(<vscale x 2 x i8> %va, <vscal define <vscale x 2 x i64> @vwmulu_vv_nxv2i64_nxv2i8(<vscale x 2 x i8> %va, <vscale x 2 x i8> %vb) { ; CHECK-LABEL: vwmulu_vv_nxv2i64_nxv2i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vzext.vf8 v10, v8 -; CHECK-NEXT: vzext.vf8 v12, v9 -; CHECK-NEXT: vmul.vv v8, v10, v12 +; CHECK-NEXT: vsetvli a0, zero, e8, mf4, ta, ma +; CHECK-NEXT: vwmulu.vv v10, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma +; CHECK-NEXT: vzext.vf4 v8, v10 ; CHECK-NEXT: ret %vc = zext <vscale x 2 x i8> %va to <vscale x 2 x i64> %vd = zext <vscale x 2 x i8> %vb to <vscale x 2 x i64> @@ -849,10 +839,10 @@ define <vscale x 2 x i64> @vwmulu_vv_nxv2i64_nxv2i8(<vscale x 2 x i8> %va, <vsca define <vscale x 2 x i64> @vwmulsu_vv_nxv2i64_nxv2i8(<vscale x 2 x i8> %va, <vscale x 2 x i8> %vb) { ; CHECK-LABEL: vwmulsu_vv_nxv2i64_nxv2i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v8 -; CHECK-NEXT: vzext.vf8 v12, v9 -; CHECK-NEXT: vmul.vv v8, v10, v12 +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v8 +; CHECK-NEXT: vzext.vf4 v11, v9 +; CHECK-NEXT: vwmulsu.vv v8, v10, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 2 x i8> %va to <vscale x 2 x i64> %vd = zext <vscale x 2 x i8> %vb to <vscale x 2 x i64> @@ -865,10 +855,10 @@ define <vscale x 2 x i64> @vwmul_vx_nxv2i64_nxv2i8(<vscale x 2 x i8> %va, i8 %b) ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf4, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v8 -; CHECK-NEXT: vsext.vf8 v12, v9 -; CHECK-NEXT: vmul.vv v8, v10, v12 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v8 +; CHECK-NEXT: vsext.vf4 v11, v9 +; CHECK-NEXT: vwmul.vv v8, v10, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i8> undef, i8 %b, i8 0 %splat = shufflevector <vscale x 2 x i8> %head, <vscale x 2 x i8> undef, <vscale x 2 x i32> zeroinitializer @@ -882,11 +872,9 @@ define <vscale x 2 x i64> @vwmulu_vx_nxv2i64_nxv2i8(<vscale x 2 x i8> %va, i8 %b ; CHECK-LABEL: vwmulu_vx_nxv2i64_nxv2i8: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf4, ta, ma -; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vwmulu.vx v10, v8, a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vzext.vf8 v10, v8 -; CHECK-NEXT: vzext.vf8 v12, v9 -; CHECK-NEXT: vmul.vv v8, v10, v12 +; CHECK-NEXT: vzext.vf4 v8, v10 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i8> undef, i8 %b, i8 0 %splat = shufflevector <vscale x 2 x i8> %head, <vscale x 2 x i8> undef, <vscale x 2 x i32> zeroinitializer @@ -901,10 +889,10 @@ define <vscale x 2 x i64> @vwmulsu_vx_nxv2i64_nxv2i8(<vscale x 2 x i8> %va, i8 % ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf4, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v8 -; CHECK-NEXT: vzext.vf8 v12, v9 -; CHECK-NEXT: vmul.vv v8, v10, v12 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v8 +; CHECK-NEXT: vzext.vf4 v11, v9 +; CHECK-NEXT: vwmulsu.vv v8, v10, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i8> undef, i8 %b, i8 0 %splat = shufflevector <vscale x 2 x i8> %head, <vscale x 2 x i8> undef, <vscale x 2 x i32> zeroinitializer @@ -917,10 +905,10 @@ define <vscale x 2 x i64> @vwmulsu_vx_nxv2i64_nxv2i8(<vscale x 2 x i8> %va, i8 % define <vscale x 4 x i64> @vwmul_vv_nxv4i64_nxv4i8(<vscale x 4 x i8> %va, <vscale x 4 x i8> %vb) { ; CHECK-LABEL: vwmul_vv_nxv4i64_nxv4i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf8 v12, v8 -; CHECK-NEXT: vsext.vf8 v16, v9 -; CHECK-NEXT: vmul.vv v8, v12, v16 +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf4 v12, v8 +; CHECK-NEXT: vsext.vf4 v14, v9 +; CHECK-NEXT: vwmul.vv v8, v12, v14 ; CHECK-NEXT: ret %vc = sext <vscale x 4 x i8> %va to <vscale x 4 x i64> %vd = sext <vscale x 4 x i8> %vb to <vscale x 4 x i64> @@ -931,10 +919,10 @@ define <vscale x 4 x i64> @vwmul_vv_nxv4i64_nxv4i8(<vscale x 4 x i8> %va, <vscal define <vscale x 4 x i64> @vwmulu_vv_nxv4i64_nxv4i8(<vscale x 4 x i8> %va, <vscale x 4 x i8> %vb) { ; CHECK-LABEL: vwmulu_vv_nxv4i64_nxv4i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vzext.vf8 v12, v8 -; CHECK-NEXT: vzext.vf8 v16, v9 -; CHECK-NEXT: vmul.vv v8, v12, v16 +; CHECK-NEXT: vsetvli a0, zero, e8, mf2, ta, ma +; CHECK-NEXT: vwmulu.vv v12, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma +; CHECK-NEXT: vzext.vf4 v8, v12 ; CHECK-NEXT: ret %vc = zext <vscale x 4 x i8> %va to <vscale x 4 x i64> %vd = zext <vscale x 4 x i8> %vb to <vscale x 4 x i64> @@ -945,10 +933,10 @@ define <vscale x 4 x i64> @vwmulu_vv_nxv4i64_nxv4i8(<vscale x 4 x i8> %va, <vsca define <vscale x 4 x i64> @vwmulsu_vv_nxv4i64_nxv4i8(<vscale x 4 x i8> %va, <vscale x 4 x i8> %vb) { ; CHECK-LABEL: vwmulsu_vv_nxv4i64_nxv4i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf8 v12, v8 -; CHECK-NEXT: vzext.vf8 v16, v9 -; CHECK-NEXT: vmul.vv v8, v12, v16 +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf4 v12, v8 +; CHECK-NEXT: vzext.vf4 v14, v9 +; CHECK-NEXT: vwmulsu.vv v8, v12, v14 ; CHECK-NEXT: ret %vc = sext <vscale x 4 x i8> %va to <vscale x 4 x i64> %vd = zext <vscale x 4 x i8> %vb to <vscale x 4 x i64> @@ -961,10 +949,10 @@ define <vscale x 4 x i64> @vwmul_vx_nxv4i64_nxv4i8(<vscale x 4 x i8> %va, i8 %b) ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf2, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf8 v12, v8 -; CHECK-NEXT: vsext.vf8 v16, v9 -; CHECK-NEXT: vmul.vv v8, v12, v16 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf4 v12, v8 +; CHECK-NEXT: vsext.vf4 v14, v9 +; CHECK-NEXT: vwmul.vv v8, v12, v14 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i8> undef, i8 %b, i8 0 %splat = shufflevector <vscale x 4 x i8> %head, <vscale x 4 x i8> undef, <vscale x 4 x i32> zeroinitializer @@ -978,11 +966,9 @@ define <vscale x 4 x i64> @vwmulu_vx_nxv4i64_nxv4i8(<vscale x 4 x i8> %va, i8 %b ; CHECK-LABEL: vwmulu_vx_nxv4i64_nxv4i8: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf2, ta, ma -; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vwmulu.vx v12, v8, a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vzext.vf8 v12, v8 -; CHECK-NEXT: vzext.vf8 v16, v9 -; CHECK-NEXT: vmul.vv v8, v12, v16 +; CHECK-NEXT: vzext.vf4 v8, v12 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i8> undef, i8 %b, i8 0 %splat = shufflevector <vscale x 4 x i8> %head, <vscale x 4 x i8> undef, <vscale x 4 x i32> zeroinitializer @@ -997,10 +983,10 @@ define <vscale x 4 x i64> @vwmulsu_vx_nxv4i64_nxv4i8(<vscale x 4 x i8> %va, i8 % ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf2, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf8 v12, v8 -; CHECK-NEXT: vzext.vf8 v16, v9 -; CHECK-NEXT: vmul.vv v8, v12, v16 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf4 v12, v8 +; CHECK-NEXT: vzext.vf4 v14, v9 +; CHECK-NEXT: vwmulsu.vv v8, v12, v14 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i8> undef, i8 %b, i8 0 %splat = shufflevector <vscale x 4 x i8> %head, <vscale x 4 x i8> undef, <vscale x 4 x i32> zeroinitializer @@ -1013,10 +999,10 @@ define <vscale x 4 x i64> @vwmulsu_vx_nxv4i64_nxv4i8(<vscale x 4 x i8> %va, i8 % define <vscale x 8 x i64> @vwmul_vv_nxv8i64_nxv8i8(<vscale x 8 x i8> %va, <vscale x 8 x i8> %vb) { ; CHECK-LABEL: vwmul_vv_nxv8i64_nxv8i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf8 v16, v8 -; CHECK-NEXT: vsext.vf8 v24, v9 -; CHECK-NEXT: vmul.vv v8, v16, v24 +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf4 v16, v8 +; CHECK-NEXT: vsext.vf4 v20, v9 +; CHECK-NEXT: vwmul.vv v8, v16, v20 ; CHECK-NEXT: ret %vc = sext <vscale x 8 x i8> %va to <vscale x 8 x i64> %vd = sext <vscale x 8 x i8> %vb to <vscale x 8 x i64> @@ -1027,10 +1013,10 @@ define <vscale x 8 x i64> @vwmul_vv_nxv8i64_nxv8i8(<vscale x 8 x i8> %va, <vscal define <vscale x 8 x i64> @vwmulu_vv_nxv8i64_nxv8i8(<vscale x 8 x i8> %va, <vscale x 8 x i8> %vb) { ; CHECK-LABEL: vwmulu_vv_nxv8i64_nxv8i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vzext.vf8 v16, v8 -; CHECK-NEXT: vzext.vf8 v24, v9 -; CHECK-NEXT: vmul.vv v8, v16, v24 +; CHECK-NEXT: vsetvli a0, zero, e8, m1, ta, ma +; CHECK-NEXT: vwmulu.vv v16, v8, v9 +; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma +; CHECK-NEXT: vzext.vf4 v8, v16 ; CHECK-NEXT: ret %vc = zext <vscale x 8 x i8> %va to <vscale x 8 x i64> %vd = zext <vscale x 8 x i8> %vb to <vscale x 8 x i64> @@ -1041,10 +1027,10 @@ define <vscale x 8 x i64> @vwmulu_vv_nxv8i64_nxv8i8(<vscale x 8 x i8> %va, <vsca define <vscale x 8 x i64> @vwmulsu_vv_nxv8i64_nxv8i8(<vscale x 8 x i8> %va, <vscale x 8 x i8> %vb) { ; CHECK-LABEL: vwmulsu_vv_nxv8i64_nxv8i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf8 v16, v8 -; CHECK-NEXT: vzext.vf8 v24, v9 -; CHECK-NEXT: vmul.vv v8, v16, v24 +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf4 v16, v8 +; CHECK-NEXT: vzext.vf4 v20, v9 +; CHECK-NEXT: vwmulsu.vv v8, v16, v20 ; CHECK-NEXT: ret %vc = sext <vscale x 8 x i8> %va to <vscale x 8 x i64> %vd = zext <vscale x 8 x i8> %vb to <vscale x 8 x i64> @@ -1057,10 +1043,10 @@ define <vscale x 8 x i64> @vwmul_vx_nxv8i64_nxv8i8(<vscale x 8 x i8> %va, i8 %b) ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, m1, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf8 v16, v8 -; CHECK-NEXT: vsext.vf8 v24, v9 -; CHECK-NEXT: vmul.vv v8, v16, v24 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf4 v16, v8 +; CHECK-NEXT: vsext.vf4 v20, v9 +; CHECK-NEXT: vwmul.vv v8, v16, v20 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i8> undef, i8 %b, i8 0 %splat = shufflevector <vscale x 8 x i8> %head, <vscale x 8 x i8> undef, <vscale x 8 x i32> zeroinitializer @@ -1074,11 +1060,9 @@ define <vscale x 8 x i64> @vwmulu_vx_nxv8i64_nxv8i8(<vscale x 8 x i8> %va, i8 %b ; CHECK-LABEL: vwmulu_vx_nxv8i64_nxv8i8: ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, m1, ta, ma -; CHECK-NEXT: vmv.v.x v9, a0 +; CHECK-NEXT: vwmulu.vx v16, v8, a0 ; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vzext.vf8 v16, v8 -; CHECK-NEXT: vzext.vf8 v24, v9 -; CHECK-NEXT: vmul.vv v8, v16, v24 +; CHECK-NEXT: vzext.vf4 v8, v16 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i8> undef, i8 %b, i8 0 %splat = shufflevector <vscale x 8 x i8> %head, <vscale x 8 x i8> undef, <vscale x 8 x i32> zeroinitializer @@ -1093,10 +1077,10 @@ define <vscale x 8 x i64> @vwmulsu_vx_nxv8i64_nxv8i8(<vscale x 8 x i8> %va, i8 % ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, m1, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf8 v16, v8 -; CHECK-NEXT: vzext.vf8 v24, v9 -; CHECK-NEXT: vmul.vv v8, v16, v24 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf4 v16, v8 +; CHECK-NEXT: vzext.vf4 v20, v9 +; CHECK-NEXT: vwmulsu.vv v8, v16, v20 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i8> undef, i8 %b, i8 0 %splat = shufflevector <vscale x 8 x i8> %head, <vscale x 8 x i8> undef, <vscale x 8 x i32> zeroinitializer diff --git a/llvm/test/CodeGen/RISCV/rvv/vwsub-sdnode.ll b/llvm/test/CodeGen/RISCV/rvv/vwsub-sdnode.ll index 123469ade0ed4d787ad367c8cb53cca18338e3aa..852814d648bfcf4cb0a4ae0e8d2ad9427d62bc69 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vwsub-sdnode.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vwsub-sdnode.ll @@ -421,10 +421,10 @@ define <vscale x 8 x i64> @vwsubu_wx_nxv8i64_nxv8i32(<vscale x 8 x i64> %va, i32 define <vscale x 1 x i64> @vwsub_vv_nxv1i64_nxv1i16(<vscale x 1 x i16> %va, <vscale x 1 x i16> %vb) { ; CHECK-LABEL: vwsub_vv_nxv1i64_nxv1i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v8 -; CHECK-NEXT: vsext.vf4 v8, v9 -; CHECK-NEXT: vsub.vv v8, v10, v8 +; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf2 v11, v9 +; CHECK-NEXT: vwsub.vv v8, v10, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 1 x i16> %va to <vscale x 1 x i64> %vd = sext <vscale x 1 x i16> %vb to <vscale x 1 x i64> @@ -451,10 +451,10 @@ define <vscale x 1 x i64> @vwsub_vx_nxv1i64_nxv1i16(<vscale x 1 x i16> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf4, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v8 -; CHECK-NEXT: vsext.vf4 v8, v9 -; CHECK-NEXT: vsub.vv v8, v10, v8 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf2 v11, v9 +; CHECK-NEXT: vwsub.vv v8, v10, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 1 x i16> %head, <vscale x 1 x i16> poison, <vscale x 1 x i32> zeroinitializer @@ -483,9 +483,9 @@ define <vscale x 1 x i64> @vwsubu_vx_nxv1i64_nxv1i16(<vscale x 1 x i16> %va, i16 define <vscale x 1 x i64> @vwsub_wv_nxv1i64_nxv1i16(<vscale x 1 x i64> %va, <vscale x 1 x i16> %vb) { ; CHECK-LABEL: vwsub_wv_nxv1i64_nxv1i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v9 -; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v9 +; CHECK-NEXT: vwsub.wv v8, v8, v10 ; CHECK-NEXT: ret %vc = sext <vscale x 1 x i16> %vb to <vscale x 1 x i64> %vd = sub <vscale x 1 x i64> %va, %vc @@ -495,9 +495,9 @@ define <vscale x 1 x i64> @vwsub_wv_nxv1i64_nxv1i16(<vscale x 1 x i64> %va, <vsc define <vscale x 1 x i64> @vwsubu_wv_nxv1i64_nxv1i16(<vscale x 1 x i64> %va, <vscale x 1 x i16> %vb) { ; CHECK-LABEL: vwsubu_wv_nxv1i64_nxv1i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vzext.vf4 v10, v9 -; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v9 +; CHECK-NEXT: vwsubu.wv v8, v8, v10 ; CHECK-NEXT: ret %vc = zext <vscale x 1 x i16> %vb to <vscale x 1 x i64> %vd = sub <vscale x 1 x i64> %va, %vc @@ -509,9 +509,9 @@ define <vscale x 1 x i64> @vwsub_wx_nxv1i64_nxv1i16(<vscale x 1 x i64> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf4, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v9 -; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v9 +; CHECK-NEXT: vwsub.wv v8, v8, v10 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 1 x i16> %head, <vscale x 1 x i16> poison, <vscale x 1 x i32> zeroinitializer @@ -525,9 +525,9 @@ define <vscale x 1 x i64> @vwsubu_wx_nxv1i64_nxv1i16(<vscale x 1 x i64> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf4, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vzext.vf4 v10, v9 -; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vzext.vf2 v10, v9 +; CHECK-NEXT: vwsubu.wv v8, v8, v10 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 1 x i16> %head, <vscale x 1 x i16> poison, <vscale x 1 x i32> zeroinitializer @@ -539,10 +539,10 @@ define <vscale x 1 x i64> @vwsubu_wx_nxv1i64_nxv1i16(<vscale x 1 x i64> %va, i16 define <vscale x 2 x i64> @vwsub_vv_nxv2i64_nxv2i16(<vscale x 2 x i16> %va, <vscale x 2 x i16> %vb) { ; CHECK-LABEL: vwsub_vv_nxv2i64_nxv2i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v8 -; CHECK-NEXT: vsext.vf4 v12, v9 -; CHECK-NEXT: vsub.vv v8, v10, v12 +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf2 v11, v9 +; CHECK-NEXT: vwsub.vv v8, v10, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 2 x i16> %va to <vscale x 2 x i64> %vd = sext <vscale x 2 x i16> %vb to <vscale x 2 x i64> @@ -569,10 +569,10 @@ define <vscale x 2 x i64> @vwsub_vx_nxv2i64_nxv2i16(<vscale x 2 x i16> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf2, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf4 v10, v8 -; CHECK-NEXT: vsext.vf4 v12, v9 -; CHECK-NEXT: vsub.vv v8, v10, v12 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf2 v10, v8 +; CHECK-NEXT: vsext.vf2 v11, v9 +; CHECK-NEXT: vwsub.vv v8, v10, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 2 x i16> %head, <vscale x 2 x i16> poison, <vscale x 2 x i32> zeroinitializer @@ -601,9 +601,9 @@ define <vscale x 2 x i64> @vwsubu_vx_nxv2i64_nxv2i16(<vscale x 2 x i16> %va, i16 define <vscale x 2 x i64> @vwsub_wv_nxv2i64_nxv2i16(<vscale x 2 x i64> %va, <vscale x 2 x i16> %vb) { ; CHECK-LABEL: vwsub_wv_nxv2i64_nxv2i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf4 v12, v10 -; CHECK-NEXT: vsub.vv v8, v8, v12 +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf2 v11, v10 +; CHECK-NEXT: vwsub.wv v8, v8, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 2 x i16> %vb to <vscale x 2 x i64> %vd = sub <vscale x 2 x i64> %va, %vc @@ -613,9 +613,9 @@ define <vscale x 2 x i64> @vwsub_wv_nxv2i64_nxv2i16(<vscale x 2 x i64> %va, <vsc define <vscale x 2 x i64> @vwsubu_wv_nxv2i64_nxv2i16(<vscale x 2 x i64> %va, <vscale x 2 x i16> %vb) { ; CHECK-LABEL: vwsubu_wv_nxv2i64_nxv2i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vzext.vf4 v12, v10 -; CHECK-NEXT: vsub.vv v8, v8, v12 +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vzext.vf2 v11, v10 +; CHECK-NEXT: vwsubu.wv v8, v8, v11 ; CHECK-NEXT: ret %vc = zext <vscale x 2 x i16> %vb to <vscale x 2 x i64> %vd = sub <vscale x 2 x i64> %va, %vc @@ -627,9 +627,9 @@ define <vscale x 2 x i64> @vwsub_wx_nxv2i64_nxv2i16(<vscale x 2 x i64> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf2, ta, ma ; CHECK-NEXT: vmv.v.x v10, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf4 v12, v10 -; CHECK-NEXT: vsub.vv v8, v8, v12 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf2 v11, v10 +; CHECK-NEXT: vwsub.wv v8, v8, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 2 x i16> %head, <vscale x 2 x i16> poison, <vscale x 2 x i32> zeroinitializer @@ -643,9 +643,9 @@ define <vscale x 2 x i64> @vwsubu_wx_nxv2i64_nxv2i16(<vscale x 2 x i64> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, mf2, ta, ma ; CHECK-NEXT: vmv.v.x v10, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vzext.vf4 v12, v10 -; CHECK-NEXT: vsub.vv v8, v8, v12 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vzext.vf2 v11, v10 +; CHECK-NEXT: vwsubu.wv v8, v8, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 2 x i16> %head, <vscale x 2 x i16> poison, <vscale x 2 x i32> zeroinitializer @@ -657,10 +657,10 @@ define <vscale x 2 x i64> @vwsubu_wx_nxv2i64_nxv2i16(<vscale x 2 x i64> %va, i16 define <vscale x 4 x i64> @vwsub_vv_nxv4i64_nxv4i16(<vscale x 4 x i16> %va, <vscale x 4 x i16> %vb) { ; CHECK-LABEL: vwsub_vv_nxv4i64_nxv4i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf4 v12, v8 -; CHECK-NEXT: vsext.vf4 v16, v9 -; CHECK-NEXT: vsub.vv v8, v12, v16 +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf2 v12, v8 +; CHECK-NEXT: vsext.vf2 v14, v9 +; CHECK-NEXT: vwsub.vv v8, v12, v14 ; CHECK-NEXT: ret %vc = sext <vscale x 4 x i16> %va to <vscale x 4 x i64> %vd = sext <vscale x 4 x i16> %vb to <vscale x 4 x i64> @@ -687,10 +687,10 @@ define <vscale x 4 x i64> @vwsub_vx_nxv4i64_nxv4i16(<vscale x 4 x i16> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m1, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf4 v12, v8 -; CHECK-NEXT: vsext.vf4 v16, v9 -; CHECK-NEXT: vsub.vv v8, v12, v16 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf2 v12, v8 +; CHECK-NEXT: vsext.vf2 v14, v9 +; CHECK-NEXT: vwsub.vv v8, v12, v14 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 4 x i16> %head, <vscale x 4 x i16> poison, <vscale x 4 x i32> zeroinitializer @@ -719,9 +719,9 @@ define <vscale x 4 x i64> @vwsubu_vx_nxv4i64_nxv4i16(<vscale x 4 x i16> %va, i16 define <vscale x 4 x i64> @vwsub_wv_nxv4i64_nxv4i16(<vscale x 4 x i64> %va, <vscale x 4 x i16> %vb) { ; CHECK-LABEL: vwsub_wv_nxv4i64_nxv4i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf4 v16, v12 -; CHECK-NEXT: vsub.vv v8, v8, v16 +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf2 v14, v12 +; CHECK-NEXT: vwsub.wv v8, v8, v14 ; CHECK-NEXT: ret %vc = sext <vscale x 4 x i16> %vb to <vscale x 4 x i64> %vd = sub <vscale x 4 x i64> %va, %vc @@ -731,9 +731,9 @@ define <vscale x 4 x i64> @vwsub_wv_nxv4i64_nxv4i16(<vscale x 4 x i64> %va, <vsc define <vscale x 4 x i64> @vwsubu_wv_nxv4i64_nxv4i16(<vscale x 4 x i64> %va, <vscale x 4 x i16> %vb) { ; CHECK-LABEL: vwsubu_wv_nxv4i64_nxv4i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vzext.vf4 v16, v12 -; CHECK-NEXT: vsub.vv v8, v8, v16 +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v14, v12 +; CHECK-NEXT: vwsubu.wv v8, v8, v14 ; CHECK-NEXT: ret %vc = zext <vscale x 4 x i16> %vb to <vscale x 4 x i64> %vd = sub <vscale x 4 x i64> %va, %vc @@ -745,9 +745,9 @@ define <vscale x 4 x i64> @vwsub_wx_nxv4i64_nxv4i16(<vscale x 4 x i64> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m1, ta, ma ; CHECK-NEXT: vmv.v.x v12, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf4 v16, v12 -; CHECK-NEXT: vsub.vv v8, v8, v16 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf2 v14, v12 +; CHECK-NEXT: vwsub.wv v8, v8, v14 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 4 x i16> %head, <vscale x 4 x i16> poison, <vscale x 4 x i32> zeroinitializer @@ -761,9 +761,9 @@ define <vscale x 4 x i64> @vwsubu_wx_nxv4i64_nxv4i16(<vscale x 4 x i64> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m1, ta, ma ; CHECK-NEXT: vmv.v.x v12, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vzext.vf4 v16, v12 -; CHECK-NEXT: vsub.vv v8, v8, v16 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf2 v14, v12 +; CHECK-NEXT: vwsubu.wv v8, v8, v14 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 4 x i16> %head, <vscale x 4 x i16> poison, <vscale x 4 x i32> zeroinitializer @@ -775,10 +775,10 @@ define <vscale x 4 x i64> @vwsubu_wx_nxv4i64_nxv4i16(<vscale x 4 x i64> %va, i16 define <vscale x 8 x i64> @vwsub_vv_nxv8i64_nxv8i16(<vscale x 8 x i16> %va, <vscale x 8 x i16> %vb) { ; CHECK-LABEL: vwsub_vv_nxv8i64_nxv8i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf4 v16, v8 -; CHECK-NEXT: vsext.vf4 v24, v10 -; CHECK-NEXT: vsub.vv v8, v16, v24 +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf2 v16, v8 +; CHECK-NEXT: vsext.vf2 v20, v10 +; CHECK-NEXT: vwsub.vv v8, v16, v20 ; CHECK-NEXT: ret %vc = sext <vscale x 8 x i16> %va to <vscale x 8 x i64> %vd = sext <vscale x 8 x i16> %vb to <vscale x 8 x i64> @@ -805,10 +805,10 @@ define <vscale x 8 x i64> @vwsub_vx_nxv8i64_nxv8i16(<vscale x 8 x i16> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m2, ta, ma ; CHECK-NEXT: vmv.v.x v10, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf4 v16, v8 -; CHECK-NEXT: vsext.vf4 v24, v10 -; CHECK-NEXT: vsub.vv v8, v16, v24 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf2 v16, v8 +; CHECK-NEXT: vsext.vf2 v20, v10 +; CHECK-NEXT: vwsub.vv v8, v16, v20 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 8 x i16> %head, <vscale x 8 x i16> poison, <vscale x 8 x i32> zeroinitializer @@ -837,9 +837,9 @@ define <vscale x 8 x i64> @vwsubu_vx_nxv8i64_nxv8i16(<vscale x 8 x i16> %va, i16 define <vscale x 8 x i64> @vwsub_wv_nxv8i64_nxv8i16(<vscale x 8 x i64> %va, <vscale x 8 x i16> %vb) { ; CHECK-LABEL: vwsub_wv_nxv8i64_nxv8i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf4 v24, v16 -; CHECK-NEXT: vsub.vv v8, v8, v24 +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf2 v20, v16 +; CHECK-NEXT: vwsub.wv v8, v8, v20 ; CHECK-NEXT: ret %vc = sext <vscale x 8 x i16> %vb to <vscale x 8 x i64> %vd = sub <vscale x 8 x i64> %va, %vc @@ -849,9 +849,9 @@ define <vscale x 8 x i64> @vwsub_wv_nxv8i64_nxv8i16(<vscale x 8 x i64> %va, <vsc define <vscale x 8 x i64> @vwsubu_wv_nxv8i64_nxv8i16(<vscale x 8 x i64> %va, <vscale x 8 x i16> %vb) { ; CHECK-LABEL: vwsubu_wv_nxv8i64_nxv8i16: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vzext.vf4 v24, v16 -; CHECK-NEXT: vsub.vv v8, v8, v24 +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf2 v20, v16 +; CHECK-NEXT: vwsubu.wv v8, v8, v20 ; CHECK-NEXT: ret %vc = zext <vscale x 8 x i16> %vb to <vscale x 8 x i64> %vd = sub <vscale x 8 x i64> %va, %vc @@ -863,9 +863,9 @@ define <vscale x 8 x i64> @vwsub_wx_nxv8i64_nxv8i16(<vscale x 8 x i64> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m2, ta, ma ; CHECK-NEXT: vmv.v.x v16, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf4 v24, v16 -; CHECK-NEXT: vsub.vv v8, v8, v24 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf2 v20, v16 +; CHECK-NEXT: vwsub.wv v8, v8, v20 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 8 x i16> %head, <vscale x 8 x i16> poison, <vscale x 8 x i32> zeroinitializer @@ -879,9 +879,9 @@ define <vscale x 8 x i64> @vwsubu_wx_nxv8i64_nxv8i16(<vscale x 8 x i64> %va, i16 ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e16, m2, ta, ma ; CHECK-NEXT: vmv.v.x v16, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vzext.vf4 v24, v16 -; CHECK-NEXT: vsub.vv v8, v8, v24 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf2 v20, v16 +; CHECK-NEXT: vwsubu.wv v8, v8, v20 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i16> poison, i16 %b, i16 0 %splat = shufflevector <vscale x 8 x i16> %head, <vscale x 8 x i16> poison, <vscale x 8 x i32> zeroinitializer @@ -893,10 +893,10 @@ define <vscale x 8 x i64> @vwsubu_wx_nxv8i64_nxv8i16(<vscale x 8 x i64> %va, i16 define <vscale x 1 x i64> @vwsub_vv_nxv1i64_nxv1i8(<vscale x 1 x i8> %va, <vscale x 1 x i8> %vb) { ; CHECK-LABEL: vwsub_vv_nxv1i64_nxv1i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v8 -; CHECK-NEXT: vsext.vf8 v8, v9 -; CHECK-NEXT: vsub.vv v8, v10, v8 +; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v8 +; CHECK-NEXT: vsext.vf4 v11, v9 +; CHECK-NEXT: vwsub.vv v8, v10, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 1 x i8> %va to <vscale x 1 x i64> %vd = sext <vscale x 1 x i8> %vb to <vscale x 1 x i64> @@ -923,10 +923,10 @@ define <vscale x 1 x i64> @vwsub_vx_nxv1i64_nxv1i8(<vscale x 1 x i8> %va, i8 %b) ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v8 -; CHECK-NEXT: vsext.vf8 v8, v9 -; CHECK-NEXT: vsub.vv v8, v10, v8 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v8 +; CHECK-NEXT: vsext.vf4 v11, v9 +; CHECK-NEXT: vwsub.vv v8, v10, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 1 x i8> %head, <vscale x 1 x i8> poison, <vscale x 1 x i32> zeroinitializer @@ -955,9 +955,9 @@ define <vscale x 1 x i64> @vwsubu_vx_nxv1i64_nxv1i8(<vscale x 1 x i8> %va, i8 %b define <vscale x 1 x i64> @vwsub_wv_nxv1i64_nxv1i8(<vscale x 1 x i64> %va, <vscale x 1 x i8> %vb) { ; CHECK-LABEL: vwsub_wv_nxv1i64_nxv1i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v9 -; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v9 +; CHECK-NEXT: vwsub.wv v8, v8, v10 ; CHECK-NEXT: ret %vc = sext <vscale x 1 x i8> %vb to <vscale x 1 x i64> %vd = sub <vscale x 1 x i64> %va, %vc @@ -967,9 +967,9 @@ define <vscale x 1 x i64> @vwsub_wv_nxv1i64_nxv1i8(<vscale x 1 x i64> %va, <vsca define <vscale x 1 x i64> @vwsubu_wv_nxv1i64_nxv1i8(<vscale x 1 x i64> %va, <vscale x 1 x i8> %vb) { ; CHECK-LABEL: vwsubu_wv_nxv1i64_nxv1i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m1, ta, ma -; CHECK-NEXT: vzext.vf8 v10, v9 -; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: vsetvli a0, zero, e32, mf2, ta, ma +; CHECK-NEXT: vzext.vf4 v10, v9 +; CHECK-NEXT: vwsubu.wv v8, v8, v10 ; CHECK-NEXT: ret %vc = zext <vscale x 1 x i8> %vb to <vscale x 1 x i64> %vd = sub <vscale x 1 x i64> %va, %vc @@ -981,9 +981,9 @@ define <vscale x 1 x i64> @vwsub_wx_nxv1i64_nxv1i8(<vscale x 1 x i64> %va, i8 %b ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v9 -; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v9 +; CHECK-NEXT: vwsub.wv v8, v8, v10 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 1 x i8> %head, <vscale x 1 x i8> poison, <vscale x 1 x i32> zeroinitializer @@ -997,9 +997,9 @@ define <vscale x 1 x i64> @vwsubu_wx_nxv1i64_nxv1i8(<vscale x 1 x i64> %va, i8 % ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf8, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m1, ta, ma -; CHECK-NEXT: vzext.vf8 v10, v9 -; CHECK-NEXT: vsub.vv v8, v8, v10 +; CHECK-NEXT: vsetvli zero, zero, e32, mf2, ta, ma +; CHECK-NEXT: vzext.vf4 v10, v9 +; CHECK-NEXT: vwsubu.wv v8, v8, v10 ; CHECK-NEXT: ret %head = insertelement <vscale x 1 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 1 x i8> %head, <vscale x 1 x i8> poison, <vscale x 1 x i32> zeroinitializer @@ -1011,10 +1011,10 @@ define <vscale x 1 x i64> @vwsubu_wx_nxv1i64_nxv1i8(<vscale x 1 x i64> %va, i8 % define <vscale x 2 x i64> @vwsub_vv_nxv2i64_nxv2i8(<vscale x 2 x i8> %va, <vscale x 2 x i8> %vb) { ; CHECK-LABEL: vwsub_vv_nxv2i64_nxv2i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v8 -; CHECK-NEXT: vsext.vf8 v12, v9 -; CHECK-NEXT: vsub.vv v8, v10, v12 +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v8 +; CHECK-NEXT: vsext.vf4 v11, v9 +; CHECK-NEXT: vwsub.vv v8, v10, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 2 x i8> %va to <vscale x 2 x i64> %vd = sext <vscale x 2 x i8> %vb to <vscale x 2 x i64> @@ -1041,10 +1041,10 @@ define <vscale x 2 x i64> @vwsub_vx_nxv2i64_nxv2i8(<vscale x 2 x i8> %va, i8 %b) ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf4, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf8 v10, v8 -; CHECK-NEXT: vsext.vf8 v12, v9 -; CHECK-NEXT: vsub.vv v8, v10, v12 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf4 v10, v8 +; CHECK-NEXT: vsext.vf4 v11, v9 +; CHECK-NEXT: vwsub.vv v8, v10, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 2 x i8> %head, <vscale x 2 x i8> poison, <vscale x 2 x i32> zeroinitializer @@ -1073,9 +1073,9 @@ define <vscale x 2 x i64> @vwsubu_vx_nxv2i64_nxv2i8(<vscale x 2 x i8> %va, i8 %b define <vscale x 2 x i64> @vwsub_wv_nxv2i64_nxv2i8(<vscale x 2 x i64> %va, <vscale x 2 x i8> %vb) { ; CHECK-LABEL: vwsub_wv_nxv2i64_nxv2i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf8 v12, v10 -; CHECK-NEXT: vsub.vv v8, v8, v12 +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf4 v11, v10 +; CHECK-NEXT: vwsub.wv v8, v8, v11 ; CHECK-NEXT: ret %vc = sext <vscale x 2 x i8> %vb to <vscale x 2 x i64> %vd = sub <vscale x 2 x i64> %va, %vc @@ -1085,9 +1085,9 @@ define <vscale x 2 x i64> @vwsub_wv_nxv2i64_nxv2i8(<vscale x 2 x i64> %va, <vsca define <vscale x 2 x i64> @vwsubu_wv_nxv2i64_nxv2i8(<vscale x 2 x i64> %va, <vscale x 2 x i8> %vb) { ; CHECK-LABEL: vwsubu_wv_nxv2i64_nxv2i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m2, ta, ma -; CHECK-NEXT: vzext.vf8 v12, v10 -; CHECK-NEXT: vsub.vv v8, v8, v12 +; CHECK-NEXT: vsetvli a0, zero, e32, m1, ta, ma +; CHECK-NEXT: vzext.vf4 v11, v10 +; CHECK-NEXT: vwsubu.wv v8, v8, v11 ; CHECK-NEXT: ret %vc = zext <vscale x 2 x i8> %vb to <vscale x 2 x i64> %vd = sub <vscale x 2 x i64> %va, %vc @@ -1099,9 +1099,9 @@ define <vscale x 2 x i64> @vwsub_wx_nxv2i64_nxv2i8(<vscale x 2 x i64> %va, i8 %b ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf4, ta, ma ; CHECK-NEXT: vmv.v.x v10, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vsext.vf8 v12, v10 -; CHECK-NEXT: vsub.vv v8, v8, v12 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vsext.vf4 v11, v10 +; CHECK-NEXT: vwsub.wv v8, v8, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 2 x i8> %head, <vscale x 2 x i8> poison, <vscale x 2 x i32> zeroinitializer @@ -1115,9 +1115,9 @@ define <vscale x 2 x i64> @vwsubu_wx_nxv2i64_nxv2i8(<vscale x 2 x i64> %va, i8 % ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf4, ta, ma ; CHECK-NEXT: vmv.v.x v10, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m2, ta, ma -; CHECK-NEXT: vzext.vf8 v12, v10 -; CHECK-NEXT: vsub.vv v8, v8, v12 +; CHECK-NEXT: vsetvli zero, zero, e32, m1, ta, ma +; CHECK-NEXT: vzext.vf4 v11, v10 +; CHECK-NEXT: vwsubu.wv v8, v8, v11 ; CHECK-NEXT: ret %head = insertelement <vscale x 2 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 2 x i8> %head, <vscale x 2 x i8> poison, <vscale x 2 x i32> zeroinitializer @@ -1129,10 +1129,10 @@ define <vscale x 2 x i64> @vwsubu_wx_nxv2i64_nxv2i8(<vscale x 2 x i64> %va, i8 % define <vscale x 4 x i64> @vwsub_vv_nxv4i64_nxv4i8(<vscale x 4 x i8> %va, <vscale x 4 x i8> %vb) { ; CHECK-LABEL: vwsub_vv_nxv4i64_nxv4i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf8 v12, v8 -; CHECK-NEXT: vsext.vf8 v16, v9 -; CHECK-NEXT: vsub.vv v8, v12, v16 +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf4 v12, v8 +; CHECK-NEXT: vsext.vf4 v14, v9 +; CHECK-NEXT: vwsub.vv v8, v12, v14 ; CHECK-NEXT: ret %vc = sext <vscale x 4 x i8> %va to <vscale x 4 x i64> %vd = sext <vscale x 4 x i8> %vb to <vscale x 4 x i64> @@ -1159,10 +1159,10 @@ define <vscale x 4 x i64> @vwsub_vx_nxv4i64_nxv4i8(<vscale x 4 x i8> %va, i8 %b) ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf2, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf8 v12, v8 -; CHECK-NEXT: vsext.vf8 v16, v9 -; CHECK-NEXT: vsub.vv v8, v12, v16 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf4 v12, v8 +; CHECK-NEXT: vsext.vf4 v14, v9 +; CHECK-NEXT: vwsub.vv v8, v12, v14 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 4 x i8> %head, <vscale x 4 x i8> poison, <vscale x 4 x i32> zeroinitializer @@ -1191,9 +1191,9 @@ define <vscale x 4 x i64> @vwsubu_vx_nxv4i64_nxv4i8(<vscale x 4 x i8> %va, i8 %b define <vscale x 4 x i64> @vwsub_wv_nxv4i64_nxv4i8(<vscale x 4 x i64> %va, <vscale x 4 x i8> %vb) { ; CHECK-LABEL: vwsub_wv_nxv4i64_nxv4i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf8 v16, v12 -; CHECK-NEXT: vsub.vv v8, v8, v16 +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf4 v14, v12 +; CHECK-NEXT: vwsub.wv v8, v8, v14 ; CHECK-NEXT: ret %vc = sext <vscale x 4 x i8> %vb to <vscale x 4 x i64> %vd = sub <vscale x 4 x i64> %va, %vc @@ -1203,9 +1203,9 @@ define <vscale x 4 x i64> @vwsub_wv_nxv4i64_nxv4i8(<vscale x 4 x i64> %va, <vsca define <vscale x 4 x i64> @vwsubu_wv_nxv4i64_nxv4i8(<vscale x 4 x i64> %va, <vscale x 4 x i8> %vb) { ; CHECK-LABEL: vwsubu_wv_nxv4i64_nxv4i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma -; CHECK-NEXT: vzext.vf8 v16, v12 -; CHECK-NEXT: vsub.vv v8, v8, v16 +; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf4 v14, v12 +; CHECK-NEXT: vwsubu.wv v8, v8, v14 ; CHECK-NEXT: ret %vc = zext <vscale x 4 x i8> %vb to <vscale x 4 x i64> %vd = sub <vscale x 4 x i64> %va, %vc @@ -1217,9 +1217,9 @@ define <vscale x 4 x i64> @vwsub_wx_nxv4i64_nxv4i8(<vscale x 4 x i64> %va, i8 %b ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf2, ta, ma ; CHECK-NEXT: vmv.v.x v12, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vsext.vf8 v16, v12 -; CHECK-NEXT: vsub.vv v8, v8, v16 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vsext.vf4 v14, v12 +; CHECK-NEXT: vwsub.wv v8, v8, v14 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 4 x i8> %head, <vscale x 4 x i8> poison, <vscale x 4 x i32> zeroinitializer @@ -1233,9 +1233,9 @@ define <vscale x 4 x i64> @vwsubu_wx_nxv4i64_nxv4i8(<vscale x 4 x i64> %va, i8 % ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, mf2, ta, ma ; CHECK-NEXT: vmv.v.x v12, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m4, ta, ma -; CHECK-NEXT: vzext.vf8 v16, v12 -; CHECK-NEXT: vsub.vv v8, v8, v16 +; CHECK-NEXT: vsetvli zero, zero, e32, m2, ta, ma +; CHECK-NEXT: vzext.vf4 v14, v12 +; CHECK-NEXT: vwsubu.wv v8, v8, v14 ; CHECK-NEXT: ret %head = insertelement <vscale x 4 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 4 x i8> %head, <vscale x 4 x i8> poison, <vscale x 4 x i32> zeroinitializer @@ -1247,10 +1247,10 @@ define <vscale x 4 x i64> @vwsubu_wx_nxv4i64_nxv4i8(<vscale x 4 x i64> %va, i8 % define <vscale x 8 x i64> @vwsub_vv_nxv8i64_nxv8i8(<vscale x 8 x i8> %va, <vscale x 8 x i8> %vb) { ; CHECK-LABEL: vwsub_vv_nxv8i64_nxv8i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf8 v16, v8 -; CHECK-NEXT: vsext.vf8 v24, v9 -; CHECK-NEXT: vsub.vv v8, v16, v24 +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf4 v16, v8 +; CHECK-NEXT: vsext.vf4 v20, v9 +; CHECK-NEXT: vwsub.vv v8, v16, v20 ; CHECK-NEXT: ret %vc = sext <vscale x 8 x i8> %va to <vscale x 8 x i64> %vd = sext <vscale x 8 x i8> %vb to <vscale x 8 x i64> @@ -1277,10 +1277,10 @@ define <vscale x 8 x i64> @vwsub_vx_nxv8i64_nxv8i8(<vscale x 8 x i8> %va, i8 %b) ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, m1, ta, ma ; CHECK-NEXT: vmv.v.x v9, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf8 v16, v8 -; CHECK-NEXT: vsext.vf8 v24, v9 -; CHECK-NEXT: vsub.vv v8, v16, v24 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf4 v16, v8 +; CHECK-NEXT: vsext.vf4 v20, v9 +; CHECK-NEXT: vwsub.vv v8, v16, v20 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 8 x i8> %head, <vscale x 8 x i8> poison, <vscale x 8 x i32> zeroinitializer @@ -1309,9 +1309,9 @@ define <vscale x 8 x i64> @vwsubu_vx_nxv8i64_nxv8i8(<vscale x 8 x i8> %va, i8 %b define <vscale x 8 x i64> @vwsub_wv_nxv8i64_nxv8i8(<vscale x 8 x i64> %va, <vscale x 8 x i8> %vb) { ; CHECK-LABEL: vwsub_wv_nxv8i64_nxv8i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf8 v24, v16 -; CHECK-NEXT: vsub.vv v8, v8, v24 +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf4 v20, v16 +; CHECK-NEXT: vwsub.wv v8, v8, v20 ; CHECK-NEXT: ret %vc = sext <vscale x 8 x i8> %vb to <vscale x 8 x i64> %vd = sub <vscale x 8 x i64> %va, %vc @@ -1321,9 +1321,9 @@ define <vscale x 8 x i64> @vwsub_wv_nxv8i64_nxv8i8(<vscale x 8 x i64> %va, <vsca define <vscale x 8 x i64> @vwsubu_wv_nxv8i64_nxv8i8(<vscale x 8 x i64> %va, <vscale x 8 x i8> %vb) { ; CHECK-LABEL: vwsubu_wv_nxv8i64_nxv8i8: ; CHECK: # %bb.0: -; CHECK-NEXT: vsetvli a0, zero, e64, m8, ta, ma -; CHECK-NEXT: vzext.vf8 v24, v16 -; CHECK-NEXT: vsub.vv v8, v8, v24 +; CHECK-NEXT: vsetvli a0, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf4 v20, v16 +; CHECK-NEXT: vwsubu.wv v8, v8, v20 ; CHECK-NEXT: ret %vc = zext <vscale x 8 x i8> %vb to <vscale x 8 x i64> %vd = sub <vscale x 8 x i64> %va, %vc @@ -1335,9 +1335,9 @@ define <vscale x 8 x i64> @vwsub_wx_nxv8i64_nxv8i8(<vscale x 8 x i64> %va, i8 %b ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, m1, ta, ma ; CHECK-NEXT: vmv.v.x v16, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vsext.vf8 v24, v16 -; CHECK-NEXT: vsub.vv v8, v8, v24 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vsext.vf4 v20, v16 +; CHECK-NEXT: vwsub.wv v8, v8, v20 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 8 x i8> %head, <vscale x 8 x i8> poison, <vscale x 8 x i32> zeroinitializer @@ -1351,9 +1351,9 @@ define <vscale x 8 x i64> @vwsubu_wx_nxv8i64_nxv8i8(<vscale x 8 x i64> %va, i8 % ; CHECK: # %bb.0: ; CHECK-NEXT: vsetvli a1, zero, e8, m1, ta, ma ; CHECK-NEXT: vmv.v.x v16, a0 -; CHECK-NEXT: vsetvli zero, zero, e64, m8, ta, ma -; CHECK-NEXT: vzext.vf8 v24, v16 -; CHECK-NEXT: vsub.vv v8, v8, v24 +; CHECK-NEXT: vsetvli zero, zero, e32, m4, ta, ma +; CHECK-NEXT: vzext.vf4 v20, v16 +; CHECK-NEXT: vwsubu.wv v8, v8, v20 ; CHECK-NEXT: ret %head = insertelement <vscale x 8 x i8> poison, i8 %b, i8 0 %splat = shufflevector <vscale x 8 x i8> %head, <vscale x 8 x i8> poison, <vscale x 8 x i32> zeroinitializer diff --git a/llvm/test/CodeGen/RISCV/rvv/wrong-stack-offset-for-rvv-object.mir b/llvm/test/CodeGen/RISCV/rvv/wrong-stack-offset-for-rvv-object.mir index 06ed46f291a832a9e723da0de963ea5b38c01075..8248c26636793e0c9e329e68759a22cad05700d4 100644 --- a/llvm/test/CodeGen/RISCV/rvv/wrong-stack-offset-for-rvv-object.mir +++ b/llvm/test/CodeGen/RISCV/rvv/wrong-stack-offset-for-rvv-object.mir @@ -83,7 +83,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 8 - adjustsStack: false + adjustsStack: true hasCalls: true stackProtector: '' maxCallFrameSize: 4294967295 diff --git a/llvm/test/CodeGen/RISCV/spill-fill-fold.ll b/llvm/test/CodeGen/RISCV/spill-fill-fold.ll index a9a0cc5cf94d85a65bd1a3f273de39a2deec37e1..8cf5f55ad5c51dcb3444727b3c81c098011b5a2a 100644 --- a/llvm/test/CodeGen/RISCV/spill-fill-fold.ll +++ b/llvm/test/CodeGen/RISCV/spill-fill-fold.ll @@ -290,8 +290,8 @@ define double @spill_i64_to_double(i64 %a) nounwind { ; RV32ID-NEXT: fsd fs9, 40(sp) # 8-byte Folded Spill ; RV32ID-NEXT: fsd fs10, 32(sp) # 8-byte Folded Spill ; RV32ID-NEXT: fsd fs11, 24(sp) # 8-byte Folded Spill -; RV32ID-NEXT: sw a1, 20(sp) ; RV32ID-NEXT: sw a0, 16(sp) +; RV32ID-NEXT: sw a1, 20(sp) ; RV32ID-NEXT: fld fa5, 16(sp) ; RV32ID-NEXT: fsd fa5, 8(sp) # 8-byte Folded Spill ; RV32ID-NEXT: #APP @@ -804,13 +804,15 @@ define double @fill_i64_to_double(i64 %a) nounwind { ; RV32ID-NEXT: fsd fs9, 40(sp) # 8-byte Folded Spill ; RV32ID-NEXT: fsd fs10, 32(sp) # 8-byte Folded Spill ; RV32ID-NEXT: fsd fs11, 24(sp) # 8-byte Folded Spill -; RV32ID-NEXT: sw a1, 20(sp) -; RV32ID-NEXT: sw a0, 16(sp) -; RV32ID-NEXT: fld fa5, 16(sp) -; RV32ID-NEXT: fsd fa5, 8(sp) # 8-byte Folded Spill +; RV32ID-NEXT: sw a1, 12(sp) # 4-byte Folded Spill +; RV32ID-NEXT: sw a0, 8(sp) # 4-byte Folded Spill ; RV32ID-NEXT: #APP ; RV32ID-NEXT: #NO_APP -; RV32ID-NEXT: fld fa0, 8(sp) # 8-byte Folded Reload +; RV32ID-NEXT: lw a0, 8(sp) # 4-byte Folded Reload +; RV32ID-NEXT: sw a0, 16(sp) +; RV32ID-NEXT: lw a0, 12(sp) # 4-byte Folded Reload +; RV32ID-NEXT: sw a0, 20(sp) +; RV32ID-NEXT: fld fa0, 16(sp) ; RV32ID-NEXT: lw ra, 172(sp) # 4-byte Folded Reload ; RV32ID-NEXT: lw s0, 168(sp) # 4-byte Folded Reload ; RV32ID-NEXT: lw s1, 164(sp) # 4-byte Folded Reload diff --git a/llvm/test/CodeGen/RISCV/stack-inst-compress.mir b/llvm/test/CodeGen/RISCV/stack-inst-compress.mir index 6721ff11d99b7bb530ddc64cc1f5c41fd2fef02f..5cc4615bb64a139aaf765b7496553dfb74dea1f3 100644 --- a/llvm/test/CodeGen/RISCV/stack-inst-compress.mir +++ b/llvm/test/CodeGen/RISCV/stack-inst-compress.mir @@ -32,6 +32,7 @@ alignment: 2 tracksRegLiveness: true frameInfo: maxAlignment: 4 + adjustsStack: true hasCalls: true localFrameSize: 2048 stack: @@ -117,6 +118,7 @@ alignment: 2 tracksRegLiveness: true frameInfo: maxAlignment: 4 + adjustsStack: true hasCalls: true localFrameSize: 4096 stack: @@ -210,6 +212,7 @@ alignment: 2 tracksRegLiveness: true frameInfo: maxAlignment: 4 + adjustsStack: true hasCalls: true localFrameSize: 8192 stack: diff --git a/llvm/test/CodeGen/RISCV/strip-w-suffix.ll b/llvm/test/CodeGen/RISCV/strip-w-suffix.ll new file mode 100644 index 0000000000000000000000000000000000000000..4124b3d0d360d2769309a020f6ac36250c345548 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/strip-w-suffix.ll @@ -0,0 +1,74 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv64 -mattr=+m -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefixes=STRIP %s +; RUN: llc -mtriple=riscv64 -mattr=+m,+no-strip-w-suffix -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefixes=NO-STRIP %s + +define i32 @addiw(i32 %a) { +; STRIP-LABEL: addiw: +; STRIP: # %bb.0: +; STRIP-NEXT: lui a1, 1 +; STRIP-NEXT: addi a1, a1, -1 +; STRIP-NEXT: addw a0, a0, a1 +; STRIP-NEXT: ret +; +; NO-STRIP-LABEL: addiw: +; NO-STRIP: # %bb.0: +; NO-STRIP-NEXT: lui a1, 1 +; NO-STRIP-NEXT: addiw a1, a1, -1 +; NO-STRIP-NEXT: addw a0, a0, a1 +; NO-STRIP-NEXT: ret + %ret = add i32 %a, 4095 + ret i32 %ret +} + +define i32 @addw(i32 %a, i32 %b) { +; STRIP-LABEL: addw: +; STRIP: # %bb.0: +; STRIP-NEXT: add a0, a0, a1 +; STRIP-NEXT: addiw a0, a0, 1024 +; STRIP-NEXT: ret +; +; NO-STRIP-LABEL: addw: +; NO-STRIP: # %bb.0: +; NO-STRIP-NEXT: addw a0, a0, a1 +; NO-STRIP-NEXT: addiw a0, a0, 1024 +; NO-STRIP-NEXT: ret + %add = add i32 %a, %b + %ret = add i32 %add, 1024 + ret i32 %ret +} + +define i32 @mulw(i32 %a, i32 %b) { +; STRIP-LABEL: mulw: +; STRIP: # %bb.0: +; STRIP-NEXT: mul a0, a0, a1 +; STRIP-NEXT: addiw a0, a0, 1024 +; STRIP-NEXT: ret +; +; NO-STRIP-LABEL: mulw: +; NO-STRIP: # %bb.0: +; NO-STRIP-NEXT: mulw a0, a0, a1 +; NO-STRIP-NEXT: addiw a0, a0, 1024 +; NO-STRIP-NEXT: ret + %mul = mul i32 %a, %b + %ret = add i32 %mul, 1024 + ret i32 %ret +} + +define i32 @slliw(i32 %a) { +; STRIP-LABEL: slliw: +; STRIP: # %bb.0: +; STRIP-NEXT: slli a0, a0, 1 +; STRIP-NEXT: addiw a0, a0, 1024 +; STRIP-NEXT: ret +; +; NO-STRIP-LABEL: slliw: +; NO-STRIP: # %bb.0: +; NO-STRIP-NEXT: slliw a0, a0, 1 +; NO-STRIP-NEXT: addiw a0, a0, 1024 +; NO-STRIP-NEXT: ret + %shl = shl i32 %a, 1 + %ret = add i32 %shl, 1024 + ret i32 %ret +} diff --git a/llvm/test/CodeGen/RISCV/tlsdesc-symbol.ll b/llvm/test/CodeGen/RISCV/tlsdesc-symbol.ll new file mode 100644 index 0000000000000000000000000000000000000000..23ba2ffb1ad766ce6702cbbdbcdb4f065ad1af05 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/tlsdesc-symbol.ll @@ -0,0 +1,24 @@ +;; The test in this file do not appear in tls-models.ll because +;; they are not auto-generated. +; RUN: llc -mtriple=riscv64 -relocation-model=pic -enable-tlsdesc < %s \ +; RUN: | llvm-mc -triple=riscv64 -filetype=obj -o - \ +; RUN: | llvm-readelf --symbols - \ +; RUN: | FileCheck %s + +; RUN: llc -mtriple=riscv32 -relocation-model=pic -enable-tlsdesc < %s \ +; RUN: | llvm-mc -triple=riscv32 -filetype=obj -o - \ +; RUN: | llvm-readelf --symbols - \ +; RUN: | FileCheck %s + +; Check that TLS symbols are lowered correctly based on the specified +; model. Make sure they're external to avoid them all being optimised to Local +; Exec for the executable. + +@unspecified = external thread_local global i32 + +define ptr @f1() nounwind { +entry: + ret ptr @unspecified + ; CHECK: Symbol table '.symtab' contains 7 entries: + ; CHECK: TLS {{.*}} unspecified +} diff --git a/llvm/test/CodeGen/RISCV/umulo-128-legalisation-lowering.ll b/llvm/test/CodeGen/RISCV/umulo-128-legalisation-lowering.ll index 8c0d97afe6c21d4a5d417908c22c6bdaef9f93a6..f1ae320017563670d0c3bed169e331032d8e80c0 100644 --- a/llvm/test/CodeGen/RISCV/umulo-128-legalisation-lowering.ll +++ b/llvm/test/CodeGen/RISCV/umulo-128-legalisation-lowering.ll @@ -89,8 +89,8 @@ define { i128, i8 } @muloti_test(i128 %l, i128 %r) #0 { ; RISCV32-NEXT: snez a3, a3 ; RISCV32-NEXT: and a3, a3, a7 ; RISCV32-NEXT: or a2, a3, a2 -; RISCV32-NEXT: or a3, t2, t3 -; RISCV32-NEXT: or a2, a2, a3 +; RISCV32-NEXT: or a2, a2, t2 +; RISCV32-NEXT: or a2, a2, t3 ; RISCV32-NEXT: mul a3, a5, a4 ; RISCV32-NEXT: andi a2, a2, 1 ; RISCV32-NEXT: sw a3, 0(a0) diff --git a/llvm/test/CodeGen/RISCV/zcmp-additional-stack.ll b/llvm/test/CodeGen/RISCV/zcmp-additional-stack.ll index e5c2e0180ee0a6f719e6ab77643066fc39739c21..73ace203398501b7c06aeddbc5d968dc5254774a 100644 --- a/llvm/test/CodeGen/RISCV/zcmp-additional-stack.ll +++ b/llvm/test/CodeGen/RISCV/zcmp-additional-stack.ll @@ -3,7 +3,8 @@ define ptr @func(ptr %s, i32 %_c, ptr %incdec.ptr, i1 %0, i8 %conv14) #0 { ; RV32-LABEL: func: ; RV32: # %bb.0: # %entry -; RV32-NEXT: cm.push {ra, s0-s1}, -24 +; RV32-NEXT: cm.push {ra, s0-s1}, -16 +; RV32-NEXT: addi sp, sp, -8 ; RV32-NEXT: .cfi_def_cfa_offset 24 ; RV32-NEXT: .cfi_offset ra, -12 ; RV32-NEXT: .cfi_offset s0, -8 @@ -31,7 +32,8 @@ define ptr @func(ptr %s, i32 %_c, ptr %incdec.ptr, i1 %0, i8 %conv14) #0 { ; RV32-NEXT: lw a0, 4(sp) # 4-byte Folded Reload ; RV32-NEXT: sb a0, 0(s0) ; RV32-NEXT: mv a0, s1 -; RV32-NEXT: cm.popret {ra, s0-s1}, 24 +; RV32-NEXT: addi sp, sp, 8 +; RV32-NEXT: cm.popret {ra, s0-s1}, 16 entry: br label %while.body diff --git a/llvm/test/CodeGen/RISCV/zdinx-asm-constraint.ll b/llvm/test/CodeGen/RISCV/zdinx-asm-constraint.ll index 63c46ca4eafce8237a98d8063c1e89e6370ede02..95695aa697764af1dd431724e9adfe549d9cbf28 100644 --- a/llvm/test/CodeGen/RISCV/zdinx-asm-constraint.ll +++ b/llvm/test/CodeGen/RISCV/zdinx-asm-constraint.ll @@ -4,21 +4,15 @@ define dso_local void @zdinx_asm(ptr nocapture noundef writeonly %a, double noundef %b, double noundef %c) nounwind { ; CHECK-LABEL: zdinx_asm: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addi sp, sp, -16 -; CHECK-NEXT: sw a1, 8(sp) -; CHECK-NEXT: sw a2, 12(sp) -; CHECK-NEXT: lw a6, 8(sp) -; CHECK-NEXT: lw a7, 12(sp) -; CHECK-NEXT: sw a3, 8(sp) -; CHECK-NEXT: sw a4, 12(sp) -; CHECK-NEXT: lw a2, 8(sp) -; CHECK-NEXT: lw a3, 12(sp) +; CHECK-NEXT: mv a5, a4 +; CHECK-NEXT: mv a7, a2 +; CHECK-NEXT: mv a4, a3 +; CHECK-NEXT: mv a6, a1 ; CHECK-NEXT: #APP -; CHECK-NEXT: fsgnjx.d a2, a6, a2 +; CHECK-NEXT: fsgnjx.d a2, a6, a4 ; CHECK-NEXT: #NO_APP ; CHECK-NEXT: sw a2, 8(a0) ; CHECK-NEXT: sw a3, 12(a0) -; CHECK-NEXT: addi sp, sp, 16 ; CHECK-NEXT: ret entry: %arrayidx = getelementptr inbounds double, ptr %a, i32 1 diff --git a/llvm/test/CodeGen/RISCV/zdinx-boundary-check.ll b/llvm/test/CodeGen/RISCV/zdinx-boundary-check.ll index 3eeb704f80ebac09325f1f3c0ec7df486b5bbd2a..f56d47716bd78157afffbe803220e4074695ac83 100644 --- a/llvm/test/CodeGen/RISCV/zdinx-boundary-check.ll +++ b/llvm/test/CodeGen/RISCV/zdinx-boundary-check.ll @@ -7,15 +7,11 @@ define void @foo(ptr nocapture %p, double %d) nounwind { ; RV32ZDINX-LABEL: foo: ; RV32ZDINX: # %bb.0: # %entry -; RV32ZDINX-NEXT: addi sp, sp, -16 -; RV32ZDINX-NEXT: sw a1, 8(sp) -; RV32ZDINX-NEXT: sw a2, 12(sp) -; RV32ZDINX-NEXT: lw a2, 8(sp) -; RV32ZDINX-NEXT: lw a3, 12(sp) +; RV32ZDINX-NEXT: mv a3, a2 ; RV32ZDINX-NEXT: addi a0, a0, 2047 +; RV32ZDINX-NEXT: mv a2, a1 ; RV32ZDINX-NEXT: sw a2, -3(a0) ; RV32ZDINX-NEXT: sw a3, 1(a0) -; RV32ZDINX-NEXT: addi sp, sp, 16 ; RV32ZDINX-NEXT: ret ; ; RV64ZDINX-LABEL: foo: @@ -31,16 +27,12 @@ entry: define void @foo2(ptr nocapture %p, double %d) nounwind { ; RV32ZDINX-LABEL: foo2: ; RV32ZDINX: # %bb.0: # %entry -; RV32ZDINX-NEXT: addi sp, sp, -16 -; RV32ZDINX-NEXT: sw a1, 8(sp) -; RV32ZDINX-NEXT: sw a2, 12(sp) -; RV32ZDINX-NEXT: lw a2, 8(sp) -; RV32ZDINX-NEXT: lw a3, 12(sp) +; RV32ZDINX-NEXT: mv a3, a2 +; RV32ZDINX-NEXT: mv a2, a1 ; RV32ZDINX-NEXT: fadd.d a2, a2, a2 ; RV32ZDINX-NEXT: addi a0, a0, 2047 ; RV32ZDINX-NEXT: sw a2, -3(a0) ; RV32ZDINX-NEXT: sw a3, 1(a0) -; RV32ZDINX-NEXT: addi sp, sp, 16 ; RV32ZDINX-NEXT: ret ; ; RV64ZDINX-LABEL: foo2: @@ -117,15 +109,11 @@ entry: define void @foo5(ptr nocapture %p, double %d) nounwind { ; RV32ZDINX-LABEL: foo5: ; RV32ZDINX: # %bb.0: # %entry -; RV32ZDINX-NEXT: addi sp, sp, -16 -; RV32ZDINX-NEXT: sw a1, 8(sp) -; RV32ZDINX-NEXT: sw a2, 12(sp) -; RV32ZDINX-NEXT: lw a2, 8(sp) -; RV32ZDINX-NEXT: lw a3, 12(sp) +; RV32ZDINX-NEXT: mv a3, a2 ; RV32ZDINX-NEXT: addi a0, a0, -2048 +; RV32ZDINX-NEXT: mv a2, a1 ; RV32ZDINX-NEXT: sw a2, -1(a0) ; RV32ZDINX-NEXT: sw a3, 3(a0) -; RV32ZDINX-NEXT: addi sp, sp, 16 ; RV32ZDINX-NEXT: ret ; ; RV64ZDINX-LABEL: foo5: @@ -142,19 +130,15 @@ entry: define void @foo6(ptr %p, double %d) nounwind { ; RV32ZDINX-LABEL: foo6: ; RV32ZDINX: # %bb.0: # %entry -; RV32ZDINX-NEXT: addi sp, sp, -16 -; RV32ZDINX-NEXT: sw a1, 8(sp) -; RV32ZDINX-NEXT: sw a2, 12(sp) -; RV32ZDINX-NEXT: lw a2, 8(sp) -; RV32ZDINX-NEXT: lw a3, 12(sp) -; RV32ZDINX-NEXT: lui a1, %hi(.LCPI5_0) -; RV32ZDINX-NEXT: lw a4, %lo(.LCPI5_0)(a1) -; RV32ZDINX-NEXT: lw a5, %lo(.LCPI5_0+4)(a1) +; RV32ZDINX-NEXT: lui a3, %hi(.LCPI5_0) +; RV32ZDINX-NEXT: lw a4, %lo(.LCPI5_0)(a3) +; RV32ZDINX-NEXT: lw a5, %lo(.LCPI5_0+4)(a3) +; RV32ZDINX-NEXT: mv a3, a2 +; RV32ZDINX-NEXT: mv a2, a1 ; RV32ZDINX-NEXT: fadd.d a2, a2, a4 ; RV32ZDINX-NEXT: addi a0, a0, 2047 ; RV32ZDINX-NEXT: sw a2, -3(a0) ; RV32ZDINX-NEXT: sw a3, 1(a0) -; RV32ZDINX-NEXT: addi sp, sp, 16 ; RV32ZDINX-NEXT: ret ; ; RV64ZDINX-LABEL: foo6: diff --git a/llvm/test/CodeGen/RISCV/zdinx-large-spill.mir b/llvm/test/CodeGen/RISCV/zdinx-large-spill.mir new file mode 100644 index 0000000000000000000000000000000000000000..8596a65c378c6c23969f06fc3de4331526ef5f61 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/zdinx-large-spill.mir @@ -0,0 +1,74 @@ +# NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +# RUN: llc %s -mtriple=riscv32 -mattr=+zdinx -start-before=prologepilog -o - | FileCheck %s + +# We want to make sure eliminateFrameIndex doesn't fold sp+2044 as an offset in +# a GPR pair spill/reload instruction. When we split the pair spill, we would be +# unable to add 4 to the immediate without overflowing simm12. + +--- | + define void @foo() { + ; CHECK-LABEL: foo: + ; CHECK: # %bb.0: + ; CHECK-NEXT: addi sp, sp, -2048 + ; CHECK-NEXT: addi sp, sp, -16 + ; CHECK-NEXT: .cfi_def_cfa_offset 2064 + ; CHECK-NEXT: lui t0, 1 + ; CHECK-NEXT: add t0, sp, t0 + ; CHECK-NEXT: sw a0, -2040(t0) # 4-byte Folded Spill + ; CHECK-NEXT: sw a1, -2036(t0) # 4-byte Folded Spill + ; CHECK-NEXT: lui a0, 1 + ; CHECK-NEXT: add a0, sp, a0 + ; CHECK-NEXT: sw a2, -2048(a0) # 4-byte Folded Spill + ; CHECK-NEXT: sw a3, -2044(a0) # 4-byte Folded Spill + ; CHECK-NEXT: sw a4, 2040(sp) # 4-byte Folded Spill + ; CHECK-NEXT: sw a5, 2044(sp) # 4-byte Folded Spill + ; CHECK-NEXT: sw a6, 2032(sp) # 4-byte Folded Spill + ; CHECK-NEXT: sw a7, 2036(sp) # 4-byte Folded Spill + ; CHECK-NEXT: lui a0, 1 + ; CHECK-NEXT: add a0, sp, a0 + ; CHECK-NEXT: lw a1, -2036(a0) # 4-byte Folded Reload + ; CHECK-NEXT: lw a0, -2040(a0) # 4-byte Folded Reload + ; CHECK-NEXT: lui a0, 1 + ; CHECK-NEXT: add a0, sp, a0 + ; CHECK-NEXT: lw a2, -2048(a0) # 4-byte Folded Reload + ; CHECK-NEXT: lw a3, -2044(a0) # 4-byte Folded Reload + ; CHECK-NEXT: lw a4, 2040(sp) # 4-byte Folded Reload + ; CHECK-NEXT: lw a5, 2044(sp) # 4-byte Folded Reload + ; CHECK-NEXT: lw a6, 2032(sp) # 4-byte Folded Reload + ; CHECK-NEXT: lw a7, 2036(sp) # 4-byte Folded Reload + ; CHECK-NEXT: addi sp, sp, 2032 + ; CHECK-NEXT: addi sp, sp, 32 + ; CHECK-NEXT: ret + ret void + } +... +--- +name: foo +tracksRegLiveness: true +tracksDebugUserValues: true +frameInfo: + maxAlignment: 4 +stack: + - { id: 0, type: spill-slot, size: 8, alignment: 4 } + - { id: 1, type: spill-slot, size: 8, alignment: 4 } + - { id: 2, type: spill-slot, size: 8, alignment: 4 } + - { id: 3, type: spill-slot, size: 8, alignment: 4 } + - { id: 4, type: spill-slot, size: 2024, alignment: 4 } +machineFunctionInfo: + varArgsFrameIndex: 0 + varArgsSaveSize: 0 +body: | + bb.0: + liveins: $x10_x11, $x12_x13, $x14_x15, $x16_x17 + + PseudoRV32ZdinxSD killed renamable $x10_x11, %stack.0, 0 :: (store (s64) into %stack.0, align 4) + PseudoRV32ZdinxSD killed renamable $x12_x13, %stack.1, 0 :: (store (s64) into %stack.1, align 4) + PseudoRV32ZdinxSD killed renamable $x14_x15, %stack.2, 0 :: (store (s64) into %stack.2, align 4) + PseudoRV32ZdinxSD killed renamable $x16_x17, %stack.3, 0 :: (store (s64) into %stack.3, align 4) + renamable $x10_x11 = PseudoRV32ZdinxLD %stack.0, 0 :: (load (s64) from %stack.0, align 4) + renamable $x12_x13 = PseudoRV32ZdinxLD %stack.1, 0 :: (load (s64) from %stack.1, align 4) + renamable $x14_x15 = PseudoRV32ZdinxLD %stack.2, 0 :: (load (s64) from %stack.2, align 4) + renamable $x16_x17 = PseudoRV32ZdinxLD %stack.3, 0 :: (load (s64) from %stack.3, align 4) + PseudoRET + +... diff --git a/llvm/test/CodeGen/SPIRV/ComparePointers.ll b/llvm/test/CodeGen/SPIRV/ComparePointers.ll index fd2084dbc260a34712889d506214586e60987905..6777fc38024b32fc866da9b7f83263a228adbd74 100644 --- a/llvm/test/CodeGen/SPIRV/ComparePointers.ll +++ b/llvm/test/CodeGen/SPIRV/ComparePointers.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown --mattr=+spirv1.3 %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; kernel void test(int global *in, int global *in2) { ;; if (!in) diff --git a/llvm/test/CodeGen/SPIRV/ExecutionMode.ll b/llvm/test/CodeGen/SPIRV/ExecutionMode.ll index 3e321e1c2bd280ff02b44d47d52bc42863dbe9f8..180b7246952db5fc8664c5e0cec8dffbf1b9e720 100644 --- a/llvm/test/CodeGen/SPIRV/ExecutionMode.ll +++ b/llvm/test/CodeGen/SPIRV/ExecutionMode.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: %[[#VOID:]] = OpTypeVoid diff --git a/llvm/test/CodeGen/SPIRV/LinkOnceODR.ll b/llvm/test/CodeGen/SPIRV/LinkOnceODR.ll index 3dfdeac7adaa5e02e3c0074150d4a015bb986235..ec660b77368e11df444960fc9f3daa8fec5af39e 100644 --- a/llvm/test/CodeGen/SPIRV/LinkOnceODR.ll +++ b/llvm/test/CodeGen/SPIRV/LinkOnceODR.ll @@ -1,5 +1,5 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_linkonce_odr %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV-EXT -; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_linkonce_odr %s -o - -filetype=obj | spirv-val %} +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_linkonce_odr %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV-EXT +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_linkonce_odr %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV-EXT: Capability Linkage ; CHECK-SPIRV-EXT: Extension "SPV_KHR_linkonce_odr" diff --git a/llvm/test/CodeGen/SPIRV/LinkOnceODRFun.ll b/llvm/test/CodeGen/SPIRV/LinkOnceODRFun.ll index 7505c3fc277e9e9c96bc96b35bb8d1febb789828..42170dce5d136e12a08187d109e76f79edfc5c4d 100644 --- a/llvm/test/CodeGen/SPIRV/LinkOnceODRFun.ll +++ b/llvm/test/CodeGen/SPIRV/LinkOnceODRFun.ll @@ -1,5 +1,5 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_linkonce_odr %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV-EXT -; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_linkonce_odr %s -o - -filetype=obj | spirv-val %} +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_linkonce_odr %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV-EXT +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_linkonce_odr %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV-EXT: Capability Linkage ; CHECK-SPIRV-EXT: Extension "SPV_KHR_linkonce_odr" diff --git a/llvm/test/CodeGen/SPIRV/assume.ll b/llvm/test/CodeGen/SPIRV/assume.ll index 6099955e4afb4ef11c9d155c7a5f0a11873d126f..fbf12ef184a8919b11390233bfc45ece1863b77a 100644 --- a/llvm/test/CodeGen/SPIRV/assume.ll +++ b/llvm/test/CodeGen/SPIRV/assume.ll @@ -1,5 +1,5 @@ -; RUN: llc -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_expect_assume < %s | FileCheck --check-prefixes=EXT,CHECK %s -; RUN: llc -mtriple=spirv64-unknown-unknown --spirv-extensions=SPV_KHR_expect_assume < %s | FileCheck --check-prefixes=EXT,CHECK %s +; RUN: llc -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_expect_assume < %s | FileCheck --check-prefixes=EXT,CHECK %s +; RUN: llc -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_expect_assume < %s | FileCheck --check-prefixes=EXT,CHECK %s ; RUN: llc -mtriple=spirv32-unknown-unknown < %s | FileCheck --check-prefixes=NOEXT,CHECK %s ; RUN: llc -mtriple=spirv64-unknown-unknown < %s | FileCheck --check-prefixes=NOEXT,CHECK %s diff --git a/llvm/test/CodeGen/SPIRV/capability-kernel.ll b/llvm/test/CodeGen/SPIRV/capability-kernel.ll index 03ea58c985adb82bb15291b7e9b039f77772d089..fea19511d4fdcce96d2ace801bcbc295dbe18493 100644 --- a/llvm/test/CodeGen/SPIRV/capability-kernel.ll +++ b/llvm/test/CodeGen/SPIRV/capability-kernel.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: OpCapability Addresses diff --git a/llvm/test/CodeGen/SPIRV/empty-logical.ll b/llvm/test/CodeGen/SPIRV/empty-logical.ll index a99df5f7eaaa71ffac0e9d6ec445ca114650bc92..1c6604006e2c25972ca162e4b74147ceaba0db4b 100644 --- a/llvm/test/CodeGen/SPIRV/empty-logical.ll +++ b/llvm/test/CodeGen/SPIRV/empty-logical.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; Ensure the required Capabilities are listed. ; CHECK-DAG: OpCapability Shader diff --git a/llvm/test/CodeGen/SPIRV/empty-module.ll b/llvm/test/CodeGen/SPIRV/empty-module.ll index f220176a409905d19a3c3c7297addad8f11e89b5..b56e58ccaf8f1b15d08fea7e9929baf14c0e643e 100644 --- a/llvm/test/CodeGen/SPIRV/empty-module.ll +++ b/llvm/test/CodeGen/SPIRV/empty-module.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: OpCapability Addresses ; CHECK-DAG: OpCapability Linkage diff --git a/llvm/test/CodeGen/SPIRV/empty-opencl32.ll b/llvm/test/CodeGen/SPIRV/empty-opencl32.ll index a373781e290bdde4f426c456e4fc9af3d996670b..8e826ec35f378156257dae58450eefc0173bdba7 100644 --- a/llvm/test/CodeGen/SPIRV/empty-opencl32.ll +++ b/llvm/test/CodeGen/SPIRV/empty-opencl32.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; FIXME: ensure Magic Number, version number, generator's magic number, "bound" and "schema" are at least present diff --git a/llvm/test/CodeGen/SPIRV/empty-opencl64.ll b/llvm/test/CodeGen/SPIRV/empty-opencl64.ll index d10196525368db8970c7c42ff6e6d1384caf421f..4eaa2e4af0fc769fece54ea5a2563b22c2502eff 100644 --- a/llvm/test/CodeGen/SPIRV/empty-opencl64.ll +++ b/llvm/test/CodeGen/SPIRV/empty-opencl64.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; FIXME: ensure Magic Number, version number, generator's magic number, "bound" and "schema" are at least present diff --git a/llvm/test/CodeGen/SPIRV/empty.ll b/llvm/test/CodeGen/SPIRV/empty.ll index fdcf316b02566b16545ae7fd5e4cf0d384b327b9..390ab329aea33bc0250dc6694273cc3505912df5 100644 --- a/llvm/test/CodeGen/SPIRV/empty.ll +++ b/llvm/test/CodeGen/SPIRV/empty.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK: OpCapability Addresses ; CHECK: "foo" diff --git a/llvm/test/CodeGen/SPIRV/exec_mode_float_control_khr.ll b/llvm/test/CodeGen/SPIRV/exec_mode_float_control_khr.ll index 473794a1ac978dd4868bb74afe8c1f243d3eac3c..721e825a1c98e23ed9a7d354db323f8d9659172e 100644 --- a/llvm/test/CodeGen/SPIRV/exec_mode_float_control_khr.ll +++ b/llvm/test/CodeGen/SPIRV/exec_mode_float_control_khr.ll @@ -1,5 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=SPV -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s --mattr=+spirv1.3 --spirv-extensions=SPV_KHR_float_controls -o - | FileCheck %s --check-prefixes=SPVEXT +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s --mattr=+spirv1.3 --spirv-ext=+SPV_KHR_float_controls -o - | FileCheck %s --check-prefixes=SPVEXT define dso_local dllexport spir_kernel void @k_float_controls_0(i32 %ibuf, i32 %obuf) local_unnamed_addr { entry: diff --git a/llvm/test/CodeGen/SPIRV/expect.ll b/llvm/test/CodeGen/SPIRV/expect.ll index 51555cd155523dab26baac8c0d80866856ba43ea..82c1ec7dc916cf76b98e7ac1a33e493ef5666efa 100644 --- a/llvm/test/CodeGen/SPIRV/expect.ll +++ b/llvm/test/CodeGen/SPIRV/expect.ll @@ -1,5 +1,5 @@ -; RUN: llc -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_expect_assume < %s | FileCheck --check-prefixes=CHECK,EXT %s -; RUN: llc -mtriple=spirv64-unknown-unknown --spirv-extensions=SPV_KHR_expect_assume < %s | FileCheck --check-prefixes=CHECK,EXT %s +; RUN: llc -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_expect_assume < %s | FileCheck --check-prefixes=CHECK,EXT %s +; RUN: llc -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_expect_assume < %s | FileCheck --check-prefixes=CHECK,EXT %s ; RUN: llc -mtriple=spirv32-unknown-unknown < %s | FileCheck --check-prefixes=CHECK,NOEXT %s ; RUN: llc -mtriple=spirv64-unknown-unknown < %s | FileCheck --check-prefixes=CHECK,NOEXT %s diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_add/atomicrmw_faddfsub_double.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_add/atomicrmw_faddfsub_double.ll index 1bfa556affceca2dde8d3cb18b0ca86997dc6c4c..e7b66798d3b34005bff9854008970a917076dd96 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_add/atomicrmw_faddfsub_double.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_add/atomicrmw_faddfsub_double.ll @@ -1,6 +1,6 @@ ; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_EXT_shader_atomic_float_add %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_EXT_shader_atomic_float_add %s -o - | FileCheck %s ; CHECK-ERROR: LLVM ERROR: The atomic float instruction requires the following SPIR-V extension: SPV_EXT_shader_atomic_float_add diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_add/atomicrmw_faddfsub_float.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_add/atomicrmw_faddfsub_float.ll index 627b59fee1a63259f2f344a5994746ac2fc8f269..4fb99d9dfc76f820d2266e5b90dc70fece29f54a 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_add/atomicrmw_faddfsub_float.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_add/atomicrmw_faddfsub_float.ll @@ -1,6 +1,6 @@ ; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_EXT_shader_atomic_float_add %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_EXT_shader_atomic_float_add %s -o - | FileCheck %s ; CHECK-ERROR: LLVM ERROR: The atomic float instruction requires the following SPIR-V extension: SPV_EXT_shader_atomic_float_add diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_add/atomicrmw_faddfsub_half.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_add/atomicrmw_faddfsub_half.ll index fffda4bd112823fd57e014c4ba3c1c583ae6a807..2f536dc53843c11d648efacd1c3b61327c57d76d 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_add/atomicrmw_faddfsub_half.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_add/atomicrmw_faddfsub_half.ll @@ -1,7 +1,7 @@ ; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR1 -; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_EXT_shader_atomic_float_add %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR2 +; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_EXT_shader_atomic_float_add %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR2 -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_EXT_shader_atomic_float_add --spirv-extensions=SPV_EXT_shader_atomic_float16_add %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_EXT_shader_atomic_float_add,+SPV_EXT_shader_atomic_float16_add %s -o - | FileCheck %s ; CHECK-ERROR1: LLVM ERROR: The atomic float instruction requires the following SPIR-V extension: SPV_EXT_shader_atomic_float_add ; CHECK-ERROR2: LLVM ERROR: The atomic float instruction requires the following SPIR-V extension: SPV_EXT_shader_atomic_float16_add diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_min_max/atomicrmw_fminfmax_double.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_min_max/atomicrmw_fminfmax_double.ll index 3c6fa276cb76a3a5c695b241da66fb2f11a811bc..7654c3618fd48fac9bbc770275c66dd435bc482f 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_min_max/atomicrmw_fminfmax_double.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_min_max/atomicrmw_fminfmax_double.ll @@ -1,6 +1,6 @@ ; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_EXT_shader_atomic_float_min_max %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_EXT_shader_atomic_float_min_max %s -o - | FileCheck %s ; CHECK-ERROR: LLVM ERROR: The atomic float instruction requires the following SPIR-V extension: SPV_EXT_shader_atomic_float_min_max diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_min_max/atomicrmw_fminfmax_float.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_min_max/atomicrmw_fminfmax_float.ll index cc52e4c720551f5d5c419c665672709a9d8fcd7b..8a3599002822319bdc2fb5c2ceadd70873e1d0d7 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_min_max/atomicrmw_fminfmax_float.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_min_max/atomicrmw_fminfmax_float.ll @@ -1,6 +1,6 @@ ; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_EXT_shader_atomic_float_min_max %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_EXT_shader_atomic_float_min_max %s -o - | FileCheck %s ; CHECK-ERROR: LLVM ERROR: The atomic float instruction requires the following SPIR-V extension: SPV_EXT_shader_atomic_float_min_max diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_min_max/atomicrmw_fminfmax_half.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_min_max/atomicrmw_fminfmax_half.ll index b406aee528b2169b2c7fd40d010bf2210ce192e4..45baaa8e9749a5105e4a9c56fe96ac4400c75443 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_min_max/atomicrmw_fminfmax_half.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_EXT_shader_atomic_float_min_max/atomicrmw_fminfmax_half.ll @@ -1,6 +1,6 @@ ; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_EXT_shader_atomic_float_min_max %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_EXT_shader_atomic_float_min_max %s -o - | FileCheck %s ; CHECK-ERROR: LLVM ERROR: The atomic float instruction requires the following SPIR-V extension: SPV_EXT_shader_atomic_float_min_max diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_arbitrary_precision_integers.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_arbitrary_precision_integers.ll index b68fb363ad85f8b40c1f51f9990a4c043dd0681a..f49367c50e0ef0a9a1481942f7a0f8b512989c7b 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_arbitrary_precision_integers.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_arbitrary_precision_integers.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_arbitrary_precision_integers %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_arbitrary_precision_integers %s -o - | FileCheck %s define i6 @getConstantI6() { ret i6 2 diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv-negative1.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv-negative1.ll index 2f3c859db346df58abc47a18bd40f23e8ba99eb5..4326d8df8820d4653bf353ebdcd98dd497f8cecb 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv-negative1.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv-negative1.ll @@ -1,4 +1,4 @@ -; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_bfloat16_conversion %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR +; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_bfloat16_conversion %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR ; CHECK-ERROR: result and argument must have the same number of components target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv-negative2.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv-negative2.ll index 8ab84d63d485c16d99d74a307e1684e00a05e7b9..57f52b97c4cc9cf0670cf8a9fae0c84818c937a5 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv-negative2.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv-negative2.ll @@ -1,4 +1,4 @@ -; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_bfloat16_conversion %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR +; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_bfloat16_conversion %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR ; CHECK-ERROR: result and argument must have the same number of components target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv-negative3.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv-negative3.ll index 20a8042ad9c29751bc6a2b9ae53bcd8f2ebc5255..2cb229eb7ef7814359586ae84078b273862dc689 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv-negative3.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv-negative3.ll @@ -1,4 +1,4 @@ -; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_bfloat16_conversion %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR +; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_bfloat16_conversion %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR ; CHECK-ERROR: result and argument must have the same number of components target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv-negative4.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv-negative4.ll index efbd50b77dc6d18965fc82ea02b38847bd7f7737..eb5a2c72910210f4260cd0b93a1d0adcda212704 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv-negative4.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv-negative4.ll @@ -1,4 +1,4 @@ -; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_bfloat16_conversion %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR +; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_bfloat16_conversion %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR ; CHECK-ERROR: result and argument must have the same number of components target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64" diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv.ll index 2bd59b22322ffd58cdfe376480296781221ad9b3..91fa340e461121f09c04400d5332b63a270beed5 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_bfloat16_conversion/bfloat16-conv.ll @@ -1,5 +1,5 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_bfloat16_conversion %s -o - | FileCheck %s -; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-extensions=SPV_INTEL_bfloat16_conversion %s -o - -filetype=obj | spirv-val %} +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_bfloat16_conversion %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_bfloat16_conversion %s -o - -filetype=obj | spirv-val %} ; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR ; CHECK-ERROR: the builtin requires the following SPIR-V extension: SPV_INTEL_bfloat16_conversion diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_const.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_const.ll index 0bd1b5d776a94cc501f20af0aaaeecd8b106c816..5f073e95cb68f2c10128d88bb3d1f41a226bc369 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_const.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_const.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_function_pointers %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s ; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: OpCapability Int8 diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_two_calls.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_two_calls.ll index 89de098dead9c868aae8a470dce46eba422c5b62..b7fecefe9a5812d351c6bbd9cb44b9fa7f1a6774 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_two_calls.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_function_pointers/fp_two_calls.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_function_pointers %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s ; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: OpCapability Int8 diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll index afbcaec9c5c5288a8f40ec36e4c13c3178bf55ed..a611be8eb6ee79c53678532e876c0e271630bdfc 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_optnone.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_optnone %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-EXTENSION +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_optnone %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-EXTENSION ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NO-EXTENSION ; CHECK-EXTENSION: OpCapability OptNoneINTEL diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_subgroups/cl_intel_sub_groups.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_subgroups/cl_intel_sub_groups.ll index 0e0b2a4dd6ec2c0cf7a2f6cdbb6374bd42ed94ca..df17ec435ad37733b729b415b47a03a163e39a07 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_subgroups/cl_intel_sub_groups.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_subgroups/cl_intel_sub_groups.ll @@ -37,7 +37,7 @@ ; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_subgroups %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_subgroups %s -o - | FileCheck %s ; CHECK-ERROR: LLVM ERROR: intel_sub_group_shuffle: the builtin requires the following SPIR-V extension: SPV_INTEL_subgroups diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_usm_storage_classes/intel-usm-addrspaces.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_usm_storage_classes/intel-usm-addrspaces.ll index 30c16350bf2b1fc66b3a0b27959cd050c71b7c8a..b5df462bd8fa9b4795802f228d1f9c4af319ff8f 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_usm_storage_classes/intel-usm-addrspaces.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_usm_storage_classes/intel-usm-addrspaces.ll @@ -1,7 +1,7 @@ ; Modified from: https://github.com/KhronosGroup/SPIRV-LLVM-Translator/test/extensions/INTEL/SPV_INTEL_usm_storage_classes/intel_usm_addrspaces.ll -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_usm_storage_classes %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-EXT -; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-extensions=SPV_INTEL_usm_storage_classes %s -o - -filetype=obj | spirv-val %} +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_usm_storage_classes %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-EXT +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_INTEL_usm_storage_classes %s -o - -filetype=obj | spirv-val %} ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-WITHOUT ; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_variable_length_array/vararr.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_variable_length_array/vararr.ll index 897aab70852d2e3e0701bff2c718749a900a9bbf..8a54d22a539db1041b9238b73182ee5084ae0ca9 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_variable_length_array/vararr.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_variable_length_array/vararr.ll @@ -1,8 +1,8 @@ ; Modified from: https://github.com/KhronosGroup/SPIRV-LLVM-Translator/test/extensions/INTEL/SPV_INTEL_variable_length_array/basic.ll ; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_variable_length_array %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV -; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_variable_length_array %s -o - -filetype=obj | spirv-val %} +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_variable_length_array %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_variable_length_array %s -o - -filetype=obj | spirv-val %} ; CHECK-ERROR: LLVM ERROR: array allocation: this instruction requires the following SPIR-V extension: SPV_INTEL_variable_length_array diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_variable_length_array/vararr_spec_const.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_variable_length_array/vararr_spec_const.ll index fbac43e51f39963ff6b909b2100f72fda25c2fb6..7b9f75d74db9977db05c894a02d3797ca1c6e6d5 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_variable_length_array/vararr_spec_const.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_INTEL_variable_length_array/vararr_spec_const.ll @@ -1,7 +1,7 @@ ; Modified from: https://github.com/KhronosGroup/SPIRV-LLVM-Translator/test/extensions/INTEL/SPV_INTEL_variable_length_array/vla_spec_const.ll -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_variable_length_array %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV -; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_variable_length_array %s -o - -filetype=obj | spirv-val %} +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_variable_length_array %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_variable_length_array %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: Capability VariableLengthArrayINTEL ; CHECK-SPIRV: Extension "SPV_INTEL_variable_length_array" diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_bit_instructions.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_bit_instructions.ll index 95395d5efb55d8b2ff6411b115f6725443dc335d..100f02faba857534fb7340a1f2b0178b7c4448a2 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_bit_instructions.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_bit_instructions.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s --spirv-extensions=SPV_KHR_bit_instructions -o - | FileCheck %s --check-prefix=CHECK-EXTENSION +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s --spirv-ext=+SPV_KHR_bit_instructions -o - | FileCheck %s --check-prefix=CHECK-EXTENSION ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-NO-EXTENSION ; CHECK-EXTENSION: OpCapability BitInstructions diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_no_integer_wrap_decoration.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_no_integer_wrap_decoration.ll index e74dd99617f91ae3ad86ba2efcbda0ce00c9f00c..0d9ab4ab65ceaa2cdd9b2c70000a7afb1d1647e1 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_no_integer_wrap_decoration.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_no_integer_wrap_decoration.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_no_integer_wrap_decoration %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_no_integer_wrap_decoration %s -o - | FileCheck %s ; CHECK-DAG: OpExtension "SPV_KHR_no_integer_wrap_decoration" diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_subgroup_rotate/subgroup-rotate.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_subgroup_rotate/subgroup-rotate.ll index b1d6a09c7fe35ba40a000c9906db6962427d93fc..63aade4f7f8daf6a7523b22e55c2b348b7afa440 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_subgroup_rotate/subgroup-rotate.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_subgroup_rotate/subgroup-rotate.ll @@ -1,6 +1,6 @@ ; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_subgroup_rotate %s -o - | FileCheck %s -; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-extensions=SPV_KHR_subgroup_rotate %s -o - -filetype=obj | spirv-val %} +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_subgroup_rotate %s -o - | FileCheck %s +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_subgroup_rotate %s -o - -filetype=obj | spirv-val %} ; CHECK-ERROR: LLVM ERROR: OpGroupNonUniformRotateKHR instruction requires the following SPIR-V extension: SPV_KHR_subgroup_rotate diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_uniform_group_instructions/uniform-group-instructions.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_uniform_group_instructions/uniform-group-instructions.ll index 39bf63ddae4fe7490674d23b569eb9e3a6803659..0de654be8ed7d5d04f4dbc74237ef5af0173709e 100644 --- a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_uniform_group_instructions/uniform-group-instructions.ll +++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_uniform_group_instructions/uniform-group-instructions.ll @@ -1,6 +1,6 @@ ; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown %s -o %t.spvt 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_uniform_group_instructions %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_uniform_group_instructions %s -o - | FileCheck %s ; CHECK-ERROR: LLVM ERROR: __spirv_GroupBitwiseAndKHR: the builtin requires the following SPIR-V extension: SPV_KHR_uniform_group_instructions diff --git a/llvm/test/CodeGen/SPIRV/extensions/both-allowed-disallowed-extension-error.ll b/llvm/test/CodeGen/SPIRV/extensions/both-allowed-disallowed-extension-error.ll new file mode 100644 index 0000000000000000000000000000000000000000..fc07cca4dd240e81a9711b57eb0ec8663d9dece3 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/both-allowed-disallowed-extension-error.ll @@ -0,0 +1,7 @@ +; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_arbitrary_precision_integers,-SPV_INTEL_arbitrary_precision_integers %s -o %t.spvt 2>&1 | FileCheck %s +; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=-SPV_INTEL_arbitrary_precision_integers,+SPV_INTEL_arbitrary_precision_integers %s -o %t.spvt 2>&1 | FileCheck %s +; CHECK: Extension cannot be allowed and disallowed at the same time: SPV_INTEL_arbitrary_precision_integers + +define i8 @foo() { + ret i8 2 +} diff --git a/llvm/test/CodeGen/SPIRV/extensions/enable-all-extensions-but-one.ll b/llvm/test/CodeGen/SPIRV/extensions/enable-all-extensions-but-one.ll new file mode 100644 index 0000000000000000000000000000000000000000..973a5e6f60569f1a7508952ef031f5f874754025 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/enable-all-extensions-but-one.ll @@ -0,0 +1,9 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=all,-SPV_INTEL_arbitrary_precision_integers %s -o - | FileCheck %s + +define i6 @foo() { + %call = tail call i32 @llvm.bitreverse.i32(i32 42) + ret i6 2 +} + +; CHECK-NOT: OpExtension "SPV_INTEL_arbitrary_precision_integers" +; CHECK-DAG: OpExtension "SPV_KHR_bit_instructions" diff --git a/llvm/test/CodeGen/SPIRV/extensions/enable-all-extensions.ll b/llvm/test/CodeGen/SPIRV/extensions/enable-all-extensions.ll new file mode 100644 index 0000000000000000000000000000000000000000..a5b979469b931d4fdae55475b3217635401f1729 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/enable-all-extensions.ll @@ -0,0 +1,7 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=all %s -o - | FileCheck %s + +define i6 @getConstantI6() { + ret i6 2 +} + +; CHECK: OpExtension "SPV_INTEL_arbitrary_precision_integers" diff --git a/llvm/test/CodeGen/SPIRV/extensions/invalid-extension-list-format.ll b/llvm/test/CodeGen/SPIRV/extensions/invalid-extension-list-format.ll new file mode 100644 index 0000000000000000000000000000000000000000..207ed4bf2572d3863b0d7ea64db7a186d003240b --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/invalid-extension-list-format.ll @@ -0,0 +1,6 @@ +; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=UNKNOWN_EXTENSION %s -o %t.spvt 2>&1 | FileCheck %s +; CHECK: Invalid extension list format: UNKNOWN_EXTENSION + +define i8 @foo() { + ret i8 2 +} diff --git a/llvm/test/CodeGen/SPIRV/extensions/unknown-extension-name.ll b/llvm/test/CodeGen/SPIRV/extensions/unknown-extension-name.ll new file mode 100644 index 0000000000000000000000000000000000000000..f4f54247c2adea005fbee01e1ff9a8b0d1c7aa7a --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/extensions/unknown-extension-name.ll @@ -0,0 +1,6 @@ +; RUN: not llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+UNKNOWN_EXTENSION %s -o %t.spvt 2>&1 | FileCheck %s +; CHECK: Unknown SPIR-V extension: +UNKNOWN_EXTENSION + +define i8 @foo() { + ret i8 2 +} diff --git a/llvm/test/CodeGen/SPIRV/fence.ll b/llvm/test/CodeGen/SPIRV/fence.ll new file mode 100644 index 0000000000000000000000000000000000000000..5da58667f24f29a3a9a3c40eebdb66163189187c --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/fence.ll @@ -0,0 +1,54 @@ +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-DAG: OpName %[[#GetScope:]] "_Z8getScopev" +; CHECK-DAG: %[[#Long:]] = OpTypeInt 32 0 +; CHECK-DAG: %[[#ScopeDevice:]] = OpConstant %[[#Long]] 1 +; CHECK-DAG: %[[#WrkGrpConst2:]] = OpConstant %[[#Long]] 2 +; CHECK-DAG: %[[#Const3:]] = OpConstant %[[#Long]] 3 +; CHECK-DAG: %[[#InvocationConst4:]] = OpConstant %[[#Long]] 4 +; CHECK-DAG: %[[#Const8:]] = OpConstant %[[#Long]] 8 +; CHECK-DAG: %[[#Const16:]] = OpConstant %[[#Long]] 16 +; CHECK-DAG: %[[#Const912:]] = OpConstant %[[#Long]] 912 +; CHECK: OpMemoryBarrier %[[#ScopeDevice]] %[[#WrkGrpConst2]] +; CHECK: OpMemoryBarrier %[[#ScopeDevice]] %[[#InvocationConst4]] +; CHECK: OpMemoryBarrier %[[#ScopeDevice]] %[[#Const8]] +; CHECK: OpMemoryBarrier %[[#InvocationConst4]] %[[#Const16]] +; CHECK: OpMemoryBarrier %[[#WrkGrpConst2]] %[[#InvocationConst4]] +; CHECK: OpFunctionEnd +; CHECK: %[[#ScopeId:]] = OpFunctionCall %[[#Long]] %[[#GetScope]] +; CHECK: OpControlBarrier %[[#Const3]] %[[#ScopeId:]] %[[#Const912]] + +define spir_kernel void @fence_test_kernel1(ptr addrspace(1) noalias %s.ascast) { + fence acquire + ret void +} + +define spir_kernel void @fence_test_kernel2(ptr addrspace(1) noalias %s.ascast) { + fence release + ret void +} + +define spir_kernel void @fence_test_kernel3(ptr addrspace(1) noalias %s.ascast) { + fence acq_rel + ret void +} + +define spir_kernel void @fence_test_kernel4(ptr addrspace(1) noalias %s.ascast) { + fence syncscope("singlethread") seq_cst + ret void +} + +define spir_kernel void @fence_test_kernel5(ptr addrspace(1) noalias %s.ascast) { + fence syncscope("workgroup") release + ret void +} + +define spir_func void @barrier_test1() { + %scope = call noundef i32 @_Z8getScopev() + call void @_Z22__spirv_ControlBarrieriii(i32 noundef 3, i32 noundef %scope, i32 noundef 912) + ret void +} + +declare spir_func void @_Z22__spirv_ControlBarrieriii(i32 noundef, i32 noundef, i32 noundef) +declare spir_func i32 @_Z8getScopev() diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveGetLaneIndex.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveGetLaneIndex.ll new file mode 100644 index 0000000000000000000000000000000000000000..ec35690ac1547cc64a4931bc638af803135bf02c --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveGetLaneIndex.ll @@ -0,0 +1,68 @@ +; RUN: llc -O0 -mtriple=spirv-vulkan-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-vulkan-unknown %s -o - -filetype=obj | spirv-val %} + +; This file generated from the following command: +; clang -cc1 -triple spirv-vulkan-compute -x hlsl -emit-llvm -finclude-default-header -o - - <<EOF +; [numthreads(1, 1, 1)] +; void main() { +; int idx = WaveGetLaneIndex(); +; } +; EOF + +; CHECK-DAG: OpCapability Shader +; CHECK-DAG: OpCapability GroupNonUniform +; CHECK-DAG: OpDecorate %[[#var:]] BuiltIn SubgroupLocalInvocationId +; CHECK-DAG: %[[#int:]] = OpTypeInt 32 0 +; CHECK-DAG: %[[#ptri:]] = OpTypePointer Input %[[#int]] +; CHECK-DAG: %[[#ptrf:]] = OpTypePointer Function %[[#int]] +; CHECK-DAG: %[[#var]] = OpVariable %[[#ptri]] Input + +; CHECK-NOT: OpDecorate %[[#var]] LinkageAttributes + + +; ModuleID = '-' +source_filename = "-" +target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" +target triple = "spirv-unknown-vulkan-compute" + +; Function Attrs: convergent noinline norecurse nounwind optnone +define internal spir_func void @main() #0 { +entry: + %0 = call token @llvm.experimental.convergence.entry() + %idx = alloca i32, align 4 +; CHECK: %[[#idx:]] = OpVariable %[[#ptrf]] Function + + %1 = call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %0) ] +; CHECK: %[[#tmp:]] = OpLoad %[[#int]] %[[#var]] + + store i32 %1, ptr %idx, align 4 +; CHECK: OpStore %[[#idx]] %[[#tmp]] + + ret void +} + +; Function Attrs: norecurse +define void @main.1() #1 { +entry: + call void @main() + ret void +} + +; Function Attrs: convergent +declare i32 @__hlsl_wave_get_lane_index() #2 + +; Function Attrs: convergent nocallback nofree nosync nounwind willreturn memory(none) +declare token @llvm.experimental.convergence.entry() #3 + +attributes #0 = { convergent noinline norecurse nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +attributes #1 = { norecurse "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +attributes #2 = { convergent } +attributes #3 = { convergent nocallback nofree nosync nounwind willreturn memory(none) } + +!llvm.module.flags = !{!0, !1} +!llvm.ident = !{!2} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 4, !"dx.disable_optimizations", i32 1} +!2 = !{!"clang version 19.0.0git (/usr/local/google/home/nathangauer/projects/llvm-project/clang bc6fd04b73a195981ee77823cf1382d04ab96c44)"} + diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/abs.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/abs.ll index 7031129de21ac6b14d9dad3380f091d1631bfb17..38c033bdd4dd78de75be0851abb300bb695ef01d 100644 --- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/abs.ll +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/abs.ll @@ -1,4 +1,5 @@ -; RUN: llc -O0 -mtriple=spirv-unknown-linux %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK: OpExtInstImport "GLSL.std.450" diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/ceil.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/ceil.ll new file mode 100644 index 0000000000000000000000000000000000000000..1b358ae54502baeade6636a201a3a66930b7fdc4 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/ceil.ll @@ -0,0 +1,20 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} +; CHECK: OpExtInstImport "GLSL.std.450" + +define noundef float @ceil_float(float noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Ceil %[[#]] + %elt.ceil = call float @llvm.ceil.f32(float %a) + ret float %elt.ceil +} + +define noundef half @ceil_half(half noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Ceil %[[#]] + %elt.ceil = call half @llvm.ceil.f16(half %a) + ret half %elt.ceil +} + +declare half @llvm.ceil.f16(half) +declare float @llvm.ceil.f32(float) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/cos.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/cos.ll new file mode 100644 index 0000000000000000000000000000000000000000..28675cf9f154129bcc0485075f2a6021cfcfe660 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/cos.ll @@ -0,0 +1,21 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpExtInstImport "GLSL.std.450" + +define noundef float @cos_float(float noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Cos %[[#]] + %elt.cos = call float @llvm.cos.f32(float %a) + ret float %elt.cos +} + +define noundef half @cos_half(half noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Cos %[[#]] + %elt.cos = call half @llvm.cos.f16(half %a) + ret half %elt.cos +} + +declare half @llvm.cos.f16(half) +declare float @llvm.cos.f32(float) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/exp.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/exp.ll new file mode 100644 index 0000000000000000000000000000000000000000..ee230df41a6c7bf1010b5e40d825523a8b7d0018 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/exp.ll @@ -0,0 +1,21 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpExtInstImport "GLSL.std.450" + +define noundef float @exp_float(float noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Exp %[[#]] + %elt.exp = call float @llvm.exp.f32(float %a) + ret float %elt.exp +} + +define noundef half @exp_half(half noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Exp %[[#]] + %elt.exp = call half @llvm.exp.f16(half %a) + ret half %elt.exp +} + +declare half @llvm.exp.f16(half) +declare float @llvm.exp.f32(float) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/exp2.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/exp2.ll new file mode 100644 index 0000000000000000000000000000000000000000..eeaca1b6560af03b45209e164f424794856f47a6 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/exp2.ll @@ -0,0 +1,21 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpExtInstImport "GLSL.std.450" + +define noundef float @exp2_float(float noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Exp2 %[[#]] + %elt.exp2 = call float @llvm.exp2.f32(float %a) + ret float %elt.exp2 +} + +define noundef half @exp2_half(half noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Exp2 %[[#]] + %elt.exp2 = call half @llvm.exp2.f16(half %a) + ret half %elt.exp2 +} + +declare half @llvm.exp2.f16(half) +declare float @llvm.exp2.f32(float) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/floor.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/floor.ll new file mode 100644 index 0000000000000000000000000000000000000000..5b972104d5038910ba8fdf481adb19053500837d --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/floor.ll @@ -0,0 +1,21 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpExtInstImport "GLSL.std.450" + +define noundef float @floor_float(float noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Floor %[[#]] + %elt.floor = call float @llvm.floor.f32(float %a) + ret float %elt.floor +} + +define noundef half @floor_half(half noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Floor %[[#]] + %elt.floor = call half @llvm.floor.f16(half %a) + ret half %elt.floor +} + +declare half @llvm.floor.f16(half) +declare float @llvm.floor.f32(float) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/fmad.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/fmad.ll new file mode 100644 index 0000000000000000000000000000000000000000..a3fec10a9e4bc9f56e14041575b6768ec08e1e69 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/fmad.ll @@ -0,0 +1,29 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpExtInstImport "GLSL.std.450" + +define noundef half @fmad_half(half noundef %a, half noundef %b, half noundef %c) #0 { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Fma %[[#]] %[[#]] %[[#]] + %dx.fmad = call half @llvm.fmuladd.f16(half %a, half %b, half %c) + ret half %dx.fmad +} + +define noundef float @fmad_float(float noundef %a, float noundef %b, float noundef %c) #0 { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Fma %[[#]] %[[#]] %[[#]] + %dx.fmad = call float @llvm.fmuladd.f32(float %a, float %b, float %c) + ret float %dx.fmad +} + +define noundef double @fmad_double(double noundef %a, double noundef %b, double noundef %c) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Fma %[[#]] %[[#]] %[[#]] + %dx.fmad = call double @llvm.fmuladd.f64(double %a, double %b, double %c) + ret double %dx.fmad +} + +declare half @llvm.fmuladd.f16(half, half, half) +declare float @llvm.fmuladd.f32(float, float, float) +declare double @llvm.fmuladd.f64(double, double, double) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/fmax.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/fmax.ll new file mode 100644 index 0000000000000000000000000000000000000000..48e916581f9ff2958f285eaeadfe01d7cfd95935 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/fmax.ll @@ -0,0 +1,29 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} +; TODO: This need to be NMax: See https://github.com/llvm/llvm-project/issues/87072 +; CHECK: OpExtInstImport "GLSL.std.450" + +define noundef half @test_fmax_half(half noundef %a, half noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] FMax %[[#]] %[[#]] + %0 = call half @llvm.maxnum.f16(half %a, half %b) + ret half %0 +} + +define noundef float @test_fmax_float(float noundef %a, float noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] FMax %[[#]] %[[#]] + %0 = call float @llvm.maxnum.f32(float %a, float %b) + ret float %0 +} + +define noundef double @test_fmax_double(double noundef %a, double noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] FMax %[[#]] %[[#]] + %0 = call double @llvm.maxnum.f64(double %a, double %b) + ret double %0 +} + +declare half @llvm.maxnum.f16(half, half) +declare float @llvm.maxnum.f32(float, float) +declare double @llvm.maxnum.f64(double, double) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/fmin.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/fmin.ll new file mode 100644 index 0000000000000000000000000000000000000000..5bfd69c972a3fa0b0f57b9c50dc552e1420370c1 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/fmin.ll @@ -0,0 +1,31 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} +; TODO: This need to be NMin: See https://github.com/llvm/llvm-project/issues/87072 + +; CHECK: OpExtInstImport "GLSL.std.450" +; CHECK: OpMemoryModel Logical GLSL450 + +define noundef half @test_fmax_half(half noundef %a, half noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] FMin %[[#]] %[[#]] + %0 = call half @llvm.minnum.f16(half %a, half %b) + ret half %0 +} + +define noundef float @test_fmax_float(float noundef %a, float noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] FMin %[[#]] %[[#]] + %0 = call float @llvm.minnum.f32(float %a, float %b) + ret float %0 +} + +define noundef double @test_fmax_double(double noundef %a, double noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] FMin %[[#]] %[[#]] + %0 = call double @llvm.minnum.f64(double %a, double %b) + ret double %0 +} + +declare half @llvm.minnum.f16(half, half) +declare float @llvm.minnum.f32(float, float) +declare double @llvm.minnum.f64(double, double) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/log.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/log.ll new file mode 100644 index 0000000000000000000000000000000000000000..5a09f32b83b2d472cac0d216bf441a081178f6b6 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/log.ll @@ -0,0 +1,21 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpExtInstImport "GLSL.std.450" + +define noundef float @log_float(float noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Log %[[#]] + %elt.log = call float @llvm.log.f32(float %a) + ret float %elt.log +} + +define noundef half @log_half(half noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Log %[[#]] + %elt.log = call half @llvm.log.f16(half %a) + ret half %elt.log +} + +declare half @llvm.log.f16(half) +declare float @llvm.log.f32(float) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/log10.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/log10.ll index e7b00eb962f444e911e78547c631d7f0fbd304e3..52ca6812d5d63aa33fc0be366b9aab3c119ffd9b 100644 --- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/log10.ll +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/log10.ll @@ -1,4 +1,5 @@ -; RUN: llc -O0 -mtriple=spirv-unknown-linux %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK: %[[#extinst:]] = OpExtInstImport "GLSL.std.450" diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/log2.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/log2.ll new file mode 100644 index 0000000000000000000000000000000000000000..21f02a40fc089e6361cd72a2cbbf2caf96a81671 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/log2.ll @@ -0,0 +1,21 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpExtInstImport "GLSL.std.450" + +define noundef float @log2_float(float noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Log2 %[[#]] + %elt.log2 = call float @llvm.log2.f32(float %a) + ret float %elt.log2 +} + +define noundef half @log2_half(half noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Log2 %[[#]] + %elt.log2 = call half @llvm.log2.f16(half %a) + ret half %elt.log2 +} + +declare half @llvm.log2.f16(half) +declare float @llvm.log2.f32(float) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pow.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pow.ll new file mode 100644 index 0000000000000000000000000000000000000000..7fae9637946fa2b6205c7d626a7ab344a89c03b0 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/pow.ll @@ -0,0 +1,21 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpExtInstImport "GLSL.std.450" + +define noundef float @pow_float(float noundef %a,float noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Pow %[[#]] + %elt.pow = call float @llvm.pow.f32(float %a,float %b) + ret float %elt.pow +} + +define noundef half @pow_half(half noundef %a, half noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Pow %[[#]] + %elt.pow = call half @llvm.pow.f16(half %a, half %b) + ret half %elt.pow +} + +declare half @llvm.pow.f16(half,half) +declare float @llvm.pow.f32(float,float) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reversebits.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reversebits.ll new file mode 100644 index 0000000000000000000000000000000000000000..e58c9ab6dfb1c1e4eadd6573336ef88a272d1935 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reversebits.ll @@ -0,0 +1,21 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpMemoryModel Logical GLSL450 + +define noundef i32 @reversebits_i32(i32 noundef %a) { +entry: +; CHECK: %[[#]] = OpBitReverse %[[#]] %[[#]] + %elt.bitreverse = call i32 @llvm.bitreverse.i32(i32 %a) + ret i32 %elt.bitreverse +} + +define noundef i16 @reversebits_i16(i16 noundef %a) { +entry: +; CHECK: %[[#]] = OpBitReverse %[[#]] %[[#]] + %elt.bitreverse = call i16 @llvm.bitreverse.i16(i16 %a) + ret i16 %elt.bitreverse +} + +declare i16 @llvm.bitreverse.i16(i16) +declare i32 @llvm.bitreverse.i32(i32) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/round.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/round.ll new file mode 100644 index 0000000000000000000000000000000000000000..baf20833840b6509cef721807b5ded5e409ecece --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/round.ll @@ -0,0 +1,21 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpExtInstImport "GLSL.std.450" + +define noundef float @round_float(float noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] RoundEven %[[#]] + %elt.roundeven = call float @llvm.roundeven.f32(float %a) + ret float %elt.roundeven +} + +define noundef half @round_half(half noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] RoundEven %[[#]] + %elt.roundeven = call half @llvm.roundeven.f16(half %a) + ret half %elt.roundeven +} + +declare half @llvm.roundeven.f16(half) +declare float @llvm.roundeven.f32(float) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/sin.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/sin.ll new file mode 100644 index 0000000000000000000000000000000000000000..061af5b37345adc766c75e74c6a08a8be5e95461 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/sin.ll @@ -0,0 +1,21 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpExtInstImport "GLSL.std.450" + +define noundef float @sin_float(float noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Sin %[[#]] + %elt.sin = call float @llvm.sin.f32(float %a) + ret float %elt.sin +} + +define noundef half @sin_half(half noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Sin %[[#]] + %elt.sin = call half @llvm.sin.f16(half %a) + ret half %elt.sin +} + +declare half @llvm.sin.f16(half) +declare float @llvm.sin.f32(float) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/smax.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/smax.ll new file mode 100644 index 0000000000000000000000000000000000000000..6bbf10323faba272814703249cac1792ff5a9651 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/smax.ll @@ -0,0 +1,29 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpExtInstImport "GLSL.std.450" + +define noundef i16 @test_smax_i16(i16 noundef %a, i16 noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] SMax %[[#]] %[[#]] + %0 = call i16 @llvm.smax.i16(i16 %a, i16 %b) + ret i16 %0 +} + +define noundef i32 @test_smax_i32(i32 noundef %a, i32 noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] SMax %[[#]] %[[#]] + %0 = call i32 @llvm.smax.i32(i32 %a, i32 %b) + ret i32 %0 +} + +define noundef i64 @test_smax_i64(i64 noundef %a, i64 noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] SMax %[[#]] %[[#]] + %0 = call i64 @llvm.smax.i64(i64 %a, i64 %b) + ret i64 %0 +} + +declare i16 @llvm.smax.i16(i16, i16) +declare i32 @llvm.smax.i32(i32, i32) +declare i64 @llvm.smax.i64(i64, i64) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/smin.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/smin.ll new file mode 100644 index 0000000000000000000000000000000000000000..04ab9600c85b7cace000618e9d389aa3de4c8812 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/smin.ll @@ -0,0 +1,32 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpExtInstImport "GLSL.std.450" + + +define noundef i16 @test_smin_i16(i16 noundef %a, i16 noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] SMin %[[#]] %[[#]] + %0 = call i16 @llvm.smin.i16(i16 %a, i16 %b) + ret i16 %0 +} + + +define noundef i32 @test_smin_i32(i32 noundef %a, i32 noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] SMin %[[#]] %[[#]] + %0 = call i32 @llvm.smin.i32(i32 %a, i32 %b) + ret i32 %0 +} + + +define noundef i64 @test_smin_i64(i64 noundef %a, i64 noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] SMin %[[#]] %[[#]] + %0 = call i64 @llvm.smin.i64(i64 %a, i64 %b) + ret i64 %0 +} + +declare i16 @llvm.smin.i16(i16, i16) +declare i32 @llvm.smin.i32(i32, i32) +declare i64 @llvm.smin.i64(i64, i64) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/sqrt.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/sqrt.ll new file mode 100644 index 0000000000000000000000000000000000000000..6882b77a427339620757ad3c94ca6c7284c33efe --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/sqrt.ll @@ -0,0 +1,21 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpExtInstImport "GLSL.std.450" + +define noundef float @sqrt_float(float noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Sqrt %[[#]] + %elt.sqrt = call float @llvm.sqrt.f32(float %a) + ret float %elt.sqrt +} + +define noundef half @sqrt_half(half noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Sqrt %[[#]] + %elt.sqrt = call half @llvm.sqrt.f16(half %a) + ret half %elt.sqrt +} + +declare half @llvm.sqrt.f16(half) +declare float @llvm.sqrt.f32(float) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/trunc.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/trunc.ll new file mode 100644 index 0000000000000000000000000000000000000000..d75b7fa5a381d836001480f551f2c40dd6fdb4cb --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/trunc.ll @@ -0,0 +1,21 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpExtInstImport "GLSL.std.450" + +define noundef float @trunc_float(float noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Trunc %[[#]] + %elt.trunc = call float @llvm.trunc.f32(float %a) + ret float %elt.trunc +} + +define noundef half @trunc_half(half noundef %a) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] Trunc %[[#]] + %elt.trunc = call half @llvm.trunc.f16(half %a) + ret half %elt.trunc +} + +declare half @llvm.trunc.f16(half) +declare float @llvm.trunc.f32(float) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/umax.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/umax.ll new file mode 100644 index 0000000000000000000000000000000000000000..32677df3d518316ac0430bf37313b6509ef4dbfe --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/umax.ll @@ -0,0 +1,29 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpExtInstImport "GLSL.std.450" + +define noundef i16 @test_umax_i16(i16 noundef %a, i16 noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] UMax %[[#]] %[[#]] + %0 = call i16 @llvm.umax.i16(i16 %a, i16 %b) + ret i16 %0 +} + +define noundef i32 @test_umax_i32(i32 noundef %a, i32 noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] UMax %[[#]] %[[#]] + %0 = call i32 @llvm.umax.i32(i32 %a, i32 %b) + ret i32 %0 +} + +define noundef i64 @test_umax_i64(i64 noundef %a, i64 noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] UMax %[[#]] %[[#]] + %0 = call i64 @llvm.umax.i64(i64 %a, i64 %b) + ret i64 %0 +} + +declare i16 @llvm.umax.i16(i16, i16) +declare i32 @llvm.umax.i32(i32, i32) +declare i64 @llvm.umax.i64(i64, i64) diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/umin.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/umin.ll new file mode 100644 index 0000000000000000000000000000000000000000..a91fb8096c2f0c926ba9dc93386aad71fe5c8d2d --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/umin.ll @@ -0,0 +1,32 @@ +; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK: OpExtInstImport "GLSL.std.450" + + +define noundef i16 @test_umin_i16(i16 noundef %a, i16 noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] UMin %[[#]] %[[#]] + %0 = call i16 @llvm.umin.i16(i16 %a, i16 %b) + ret i16 %0 +} + + +define noundef i32 @test_umin_i32(i32 noundef %a, i32 noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] UMin %[[#]] %[[#]] + %0 = call i32 @llvm.umin.i32(i32 %a, i32 %b) + ret i32 %0 +} + + +define noundef i64 @test_umin_i64(i64 noundef %a, i64 noundef %b) { +entry: +; CHECK: %[[#]] = OpExtInst %[[#]] %[[#]] UMin %[[#]] %[[#]] + %0 = call i64 @llvm.umin.i64(i64 %a, i64 %b) + ret i64 %0 +} + +declare i16 @llvm.umin.i16(i16, i16) +declare i32 @llvm.umin.i32(i32, i32) +declare i64 @llvm.umin.i64(i64, i64) diff --git a/llvm/test/CodeGen/SPIRV/instructions/atomic.ll b/llvm/test/CodeGen/SPIRV/instructions/atomic.ll index 9715504fcc5d38471f3555fc283f9fbb087e14d5..ce59bb2064027acb9e000597bc670d01e5dc2212 100644 --- a/llvm/test/CodeGen/SPIRV/instructions/atomic.ll +++ b/llvm/test/CodeGen/SPIRV/instructions/atomic.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: OpName [[ADD:%.*]] "test_add" ; CHECK-DAG: OpName [[SUB:%.*]] "test_sub" @@ -20,7 +21,8 @@ ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicIAdd [[I32Ty]] [[A]] [[SCOPE]] [[RELAXED]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicIAdd [[I32Ty]] [[BC_A]] [[SCOPE]] [[RELAXED]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_add(i32* %ptr, i32 %val) { @@ -32,7 +34,8 @@ define i32 @test_add(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicISub [[I32Ty]] [[A]] [[SCOPE]] [[RELAXED]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicISub [[I32Ty]] [[BC_A]] [[SCOPE]] [[RELAXED]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_sub(i32* %ptr, i32 %val) { @@ -44,7 +47,8 @@ define i32 @test_sub(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicSMin [[I32Ty]] [[A]] [[SCOPE]] [[RELAXED]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicSMin [[I32Ty]] [[BC_A]] [[SCOPE]] [[RELAXED]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_min(i32* %ptr, i32 %val) { @@ -56,7 +60,8 @@ define i32 @test_min(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicSMax [[I32Ty]] [[A]] [[SCOPE]] [[RELAXED]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicSMax [[I32Ty]] [[BC_A]] [[SCOPE]] [[RELAXED]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_max(i32* %ptr, i32 %val) { @@ -68,7 +73,8 @@ define i32 @test_max(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicUMin [[I32Ty]] [[A]] [[SCOPE]] [[RELAXED]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicUMin [[I32Ty]] [[BC_A]] [[SCOPE]] [[RELAXED]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_umin(i32* %ptr, i32 %val) { @@ -80,7 +86,8 @@ define i32 @test_umin(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicUMax [[I32Ty]] [[A]] [[SCOPE]] [[RELAXED]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicUMax [[I32Ty]] [[BC_A]] [[SCOPE]] [[RELAXED]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_umax(i32* %ptr, i32 %val) { @@ -92,7 +99,8 @@ define i32 @test_umax(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicAnd [[I32Ty]] [[A]] [[SCOPE]] [[RELAXED]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicAnd [[I32Ty]] [[BC_A]] [[SCOPE]] [[RELAXED]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_and(i32* %ptr, i32 %val) { @@ -104,7 +112,8 @@ define i32 @test_and(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicOr [[I32Ty]] [[A]] [[SCOPE]] [[RELAXED]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicOr [[I32Ty]] [[BC_A]] [[SCOPE]] [[RELAXED]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_or(i32* %ptr, i32 %val) { @@ -116,7 +125,8 @@ define i32 @test_or(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicXor [[I32Ty]] [[A]] [[SCOPE]] [[RELAXED]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicXor [[I32Ty]] [[BC_A]] [[SCOPE]] [[RELAXED]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_xor(i32* %ptr, i32 %val) { diff --git a/llvm/test/CodeGen/SPIRV/instructions/atomic_acqrel.ll b/llvm/test/CodeGen/SPIRV/instructions/atomic_acqrel.ll index 63c0ae75f5ecdde4d1c3a265628ff72f0b3db1d0..950dfe417637feb8584e04cbba9c7362c9e74745 100644 --- a/llvm/test/CodeGen/SPIRV/instructions/atomic_acqrel.ll +++ b/llvm/test/CodeGen/SPIRV/instructions/atomic_acqrel.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: OpName [[ADD:%.*]] "test_add" ; CHECK-DAG: OpName [[SUB:%.*]] "test_sub" @@ -20,7 +21,8 @@ ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicIAdd [[I32Ty]] [[A]] [[SCOPE]] [[ACQREL]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicIAdd [[I32Ty]] [[BC_A]] [[SCOPE]] [[ACQREL]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_add(i32* %ptr, i32 %val) { @@ -32,7 +34,8 @@ define i32 @test_add(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicISub [[I32Ty]] [[A]] [[SCOPE]] [[ACQREL]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicISub [[I32Ty]] [[BC_A]] [[SCOPE]] [[ACQREL]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_sub(i32* %ptr, i32 %val) { @@ -44,7 +47,8 @@ define i32 @test_sub(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicSMin [[I32Ty]] [[A]] [[SCOPE]] [[ACQREL]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicSMin [[I32Ty]] [[BC_A]] [[SCOPE]] [[ACQREL]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_min(i32* %ptr, i32 %val) { @@ -56,7 +60,8 @@ define i32 @test_min(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicSMax [[I32Ty]] [[A]] [[SCOPE]] [[ACQREL]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicSMax [[I32Ty]] [[BC_A]] [[SCOPE]] [[ACQREL]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_max(i32* %ptr, i32 %val) { @@ -68,7 +73,8 @@ define i32 @test_max(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicUMin [[I32Ty]] [[A]] [[SCOPE]] [[ACQREL]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicUMin [[I32Ty]] [[BC_A]] [[SCOPE]] [[ACQREL]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_umin(i32* %ptr, i32 %val) { @@ -80,7 +86,8 @@ define i32 @test_umin(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicUMax [[I32Ty]] [[A]] [[SCOPE]] [[ACQREL]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicUMax [[I32Ty]] [[BC_A]] [[SCOPE]] [[ACQREL]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_umax(i32* %ptr, i32 %val) { @@ -92,7 +99,8 @@ define i32 @test_umax(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicAnd [[I32Ty]] [[A]] [[SCOPE]] [[ACQREL]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicAnd [[I32Ty]] [[BC_A]] [[SCOPE]] [[ACQREL]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_and(i32* %ptr, i32 %val) { @@ -104,7 +112,8 @@ define i32 @test_and(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicOr [[I32Ty]] [[A]] [[SCOPE]] [[ACQREL]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicOr [[I32Ty]] [[BC_A]] [[SCOPE]] [[ACQREL]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_or(i32* %ptr, i32 %val) { @@ -116,7 +125,8 @@ define i32 @test_or(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicXor [[I32Ty]] [[A]] [[SCOPE]] [[ACQREL]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicXor [[I32Ty]] [[BC_A]] [[SCOPE]] [[ACQREL]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_xor(i32* %ptr, i32 %val) { diff --git a/llvm/test/CodeGen/SPIRV/instructions/atomic_seq.ll b/llvm/test/CodeGen/SPIRV/instructions/atomic_seq.ll index f6a8fe1e6db18e5ae4c00e6fceff933b2651889d..f142e012dcb7449b8c46cb6fc1cf2360cabea82b 100644 --- a/llvm/test/CodeGen/SPIRV/instructions/atomic_seq.ll +++ b/llvm/test/CodeGen/SPIRV/instructions/atomic_seq.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: OpName [[ADD:%.*]] "test_add" ; CHECK-DAG: OpName [[SUB:%.*]] "test_sub" @@ -20,7 +21,8 @@ ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicIAdd [[I32Ty]] [[A]] [[SCOPE]] [[SEQ]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicIAdd [[I32Ty]] [[BC_A]] [[SCOPE]] [[SEQ]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_add(i32* %ptr, i32 %val) { @@ -32,7 +34,8 @@ define i32 @test_add(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicISub [[I32Ty]] [[A]] [[SCOPE]] [[SEQ]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicISub [[I32Ty]] [[BC_A]] [[SCOPE]] [[SEQ]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_sub(i32* %ptr, i32 %val) { @@ -44,7 +47,8 @@ define i32 @test_sub(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicSMin [[I32Ty]] [[A]] [[SCOPE]] [[SEQ]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicSMin [[I32Ty]] [[BC_A]] [[SCOPE]] [[SEQ]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_min(i32* %ptr, i32 %val) { @@ -56,7 +60,8 @@ define i32 @test_min(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicSMax [[I32Ty]] [[A]] [[SCOPE]] [[SEQ]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicSMax [[I32Ty]] [[BC_A]] [[SCOPE]] [[SEQ]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_max(i32* %ptr, i32 %val) { @@ -68,7 +73,8 @@ define i32 @test_max(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicUMin [[I32Ty]] [[A]] [[SCOPE]] [[SEQ]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicUMin [[I32Ty]] [[BC_A]] [[SCOPE]] [[SEQ]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_umin(i32* %ptr, i32 %val) { @@ -80,7 +86,8 @@ define i32 @test_umin(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicUMax [[I32Ty]] [[A]] [[SCOPE]] [[SEQ]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicUMax [[I32Ty]] [[BC_A]] [[SCOPE]] [[SEQ]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_umax(i32* %ptr, i32 %val) { @@ -92,7 +99,8 @@ define i32 @test_umax(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicAnd [[I32Ty]] [[A]] [[SCOPE]] [[SEQ]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicAnd [[I32Ty]] [[BC_A]] [[SCOPE]] [[SEQ]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_and(i32* %ptr, i32 %val) { @@ -104,7 +112,8 @@ define i32 @test_and(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicOr [[I32Ty]] [[A]] [[SCOPE]] [[SEQ]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicOr [[I32Ty]] [[BC_A]] [[SCOPE]] [[SEQ]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_or(i32* %ptr, i32 %val) { @@ -116,7 +125,8 @@ define i32 @test_or(i32* %ptr, i32 %val) { ; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter ; CHECK-NEXT: [[B:%.*]] = OpFunctionParameter ; CHECK-NEXT: OpLabel -; CHECK-NEXT: [[R:%.*]] = OpAtomicXor [[I32Ty]] [[A]] [[SCOPE]] [[SEQ]] [[B]] +; CHECK-NEXT: [[BC_A:%.*]] = OpBitcast %[[#]] [[A]] +; CHECK-NEXT: [[R:%.*]] = OpAtomicXor [[I32Ty]] [[BC_A]] [[SCOPE]] [[SEQ]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd define i32 @test_xor(i32* %ptr, i32 %val) { diff --git a/llvm/test/CodeGen/SPIRV/instructions/bitwise-i1.ll b/llvm/test/CodeGen/SPIRV/instructions/bitwise-i1.ll new file mode 100644 index 0000000000000000000000000000000000000000..8d3657b36454bfe615a6a9f9d1b4dd118b99a10a --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/instructions/bitwise-i1.ll @@ -0,0 +1,69 @@ +; This test ensures that LLVM IR bitwise instructions result in logical SPIR-V instructions +; when applied to i1 type + +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-DAG: %[[#Char:]] = OpTypeInt 8 0 +; CHECK-DAG: %[[#Vec2Char:]] = OpTypeVector %[[#Char]] 2 +; CHECK-DAG: %[[#Bool:]] = OpTypeBool +; CHECK-DAG: %[[#Vec2Bool:]] = OpTypeVector %[[#Bool]] 2 + +; CHECK: OpBitwiseAnd %[[#Char]] +; CHECK: OpBitwiseOr %[[#Char]] +; CHECK: OpBitwiseXor %[[#Char]] +; CHECK: OpBitwiseAnd %[[#Vec2Char]] +; CHECK: OpBitwiseOr %[[#Vec2Char]] +; CHECK: OpBitwiseXor %[[#Vec2Char]] + +; CHECK: OpLogicalAnd %[[#Bool]] + +; CHECK: OpLogicalAnd %[[#Bool]] +; CHECK: OpLogicalOr %[[#Bool]] +; CHECK: OpLogicalNotEqual %[[#Bool]] +; CHECK: OpLogicalAnd %[[#Vec2Bool]] +; CHECK: OpLogicalOr %[[#Vec2Bool]] +; CHECK: OpLogicalNotEqual %[[#Vec2Bool]] + +define void @test1(i8 noundef %arg1, i8 noundef %arg2) { + %cond1 = and i8 %arg1, %arg2 + %cond2 = or i8 %arg1, %arg2 + %cond3 = xor i8 %arg1, %arg2 + ret void +} + +define void @test1v(<2 x i8> noundef %arg1, <2 x i8> noundef %arg2) { + %cond1 = and <2 x i8> %arg1, %arg2 + %cond2 = or <2 x i8> %arg1, %arg2 + %cond3 = xor <2 x i8> %arg1, %arg2 + ret void +} + +define void @test2(float noundef %real, float noundef %imag) { +entry: + %realabs = tail call spir_func noundef float @_Z16__spirv_ocl_fabsf(float noundef %real) + %cond1 = fcmp oeq float %realabs, 1.000000e+00 + %cond2 = fcmp oeq float %imag, 0.000000e+00 + %cond3 = and i1 %cond1, %cond2 + br i1 %cond3, label %midlbl, label %cleanup +midlbl: + br label %cleanup +cleanup: + ret void +} + +define void @test3(i1 noundef %arg1, i1 noundef %arg2) { + %cond1 = and i1 %arg1, %arg2 + %cond2 = or i1 %arg1, %arg2 + %cond3 = xor i1 %arg1, %arg2 + ret void +} + +define void @test3v(<2 x i1> noundef %arg1, <2 x i1> noundef %arg2) { + %cond1 = and <2 x i1> %arg1, %arg2 + %cond2 = or <2 x i1> %arg1, %arg2 + %cond3 = xor <2 x i1> %arg1, %arg2 + ret void +} + +declare dso_local spir_func noundef float @_Z16__spirv_ocl_fabsf(float noundef) diff --git a/llvm/test/CodeGen/SPIRV/instructions/ptrcmp.ll b/llvm/test/CodeGen/SPIRV/instructions/ptrcmp.ll index 641e2bf0649ce6c5b58ea737ecd8d5878c82c91a..31cd8bd459297ab604004ff63ac7aa3d8f3a83e6 100644 --- a/llvm/test/CodeGen/SPIRV/instructions/ptrcmp.ll +++ b/llvm/test/CodeGen/SPIRV/instructions/ptrcmp.ll @@ -1,7 +1,13 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s --translator-compatibility-mode -o - | FileCheck %s --check-prefix=CHECK-COMPAT +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s --translator-compatibility-mode -o - -filetype=obj | spirv-val %} ; CHECK-DAG: OpName [[EQ:%.*]] "test_eq" ; CHECK-DAG: OpName [[NE:%.*]] "test_ne" +; CHECK-COMPAT-DAG: OpName [[EQ:%.*]] "test_eq" +; CHECK-COMPAT-DAG: OpName [[NE:%.*]] "test_ne" ; CHECK-DAG: OpName [[ULT:%.*]] "test_ult" ; CHECK-DAG: OpName [[SLT:%.*]] "test_slt" ; CHECK-DAG: OpName [[ULE:%.*]] "test_ule" @@ -19,6 +25,9 @@ ; CHECK-NEXT: [[R:%.*]] = OpPtrEqual {{%.+}} [[A]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd +; CHECK-COMPAT: [[EQ]] = OpFunction +; CHECK-COMPAT-NOT: OpPtrEqual +; CHECK-COMPAT: OpFunctionEnd define i1 @test_eq(i16* %a, i16* %b) { %r = icmp eq i16* %a, %b ret i1 %r @@ -31,6 +40,9 @@ define i1 @test_eq(i16* %a, i16* %b) { ; CHECK-NEXT: [[R:%.*]] = OpPtrNotEqual {{%.+}} [[A]] [[B]] ; CHECK-NEXT: OpReturnValue [[R]] ; CHECK-NEXT: OpFunctionEnd +; CHECK-COMPAT: [[NE]] = OpFunction +; CHECK-COMPAT-NOT: OpPtrNotEqual +; CHECK-COMPAT: OpFunctionEnd define i1 @test_ne(i16* %a, i16* %b) { %r = icmp ne i16* %a, %b ret i1 %r diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/lifetime.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/lifetime.ll new file mode 100644 index 0000000000000000000000000000000000000000..710a1581f760ca190c8386754eb8e2364458d1be --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/lifetime.ll @@ -0,0 +1,25 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s + +; CHECK: OpFunction +; CHECK: %[[FooArg:.*]] = OpVariable +; CHECK: OpLifetimeStart %[[FooArg]], 0 +; CHECK: OpCopyMemorySized +; CHECK: OpBitcast +; CHECK: OpInBoundsPtrAccessChain +; CHECK: OpLifetimeStop %[[FooArg]], 0 + +%tprange = type { %tparray } +%tparray = type { [2 x i64] } + +define spir_func void @foo(ptr noundef byval(%tprange) align 8 %_arg_UserRange) { + %RoundedRangeKernel = alloca %tprange, align 8 + call void @llvm.lifetime.start.p0(i64 72, ptr nonnull %RoundedRangeKernel) #7 + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %RoundedRangeKernel, ptr align 8 %_arg_UserRange, i64 16, i1 false) + %KernelFunc = getelementptr inbounds i8, ptr %RoundedRangeKernel, i64 16 + call void @llvm.lifetime.end.p0(i64 72, ptr nonnull %RoundedRangeKernel) #7 + ret void +} + +declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) +declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) +declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/add.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/add.ll index 93190f972d9b9bfd0832d79db6403bed2edf4240..e0c84ee3a3f1c1e6e072742154807dbf0d3c33ee 100644 --- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/add.ll +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/add.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_function_pointers %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} target triple = "spir64-unknown-unknown" diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/and.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/and.ll index aa879b22e057f39f81a74944c1b3708094ad39f9..12a4a86fa4a8bef9cb47c809da57c8eb7d814eac 100644 --- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/and.ll +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/and.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_function_pointers %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} target triple = "spir64-unknown-unknown" diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fadd.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fadd.ll index a0d18d5a750f59c51c26f4dfaaa902de84fe4764..459bc6bdcdaff88cd3286c4704fe6aa201075901 100644 --- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fadd.ll +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fadd.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_function_pointers %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} target triple = "spir64-unknown-unknown" diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fmax.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fmax.ll index 247ebcca2dd83fb4d96d332b96e0f51487e3e705..4f9cd29cd05d2a9e6dbd01a78535713df7bdcb13 100644 --- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fmax.ll +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fmax.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_function_pointers %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} target triple = "spir64-unknown-unknown" diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fmaximum.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fmaximum.ll index 13f44108733cfbf6fdd34ca34fbfbac6d5e4ce80..837bea0fbe624734492794f269c6274d6e9903c2 100644 --- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fmaximum.ll +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fmaximum.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_function_pointers %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} target triple = "spir64-unknown-unknown" diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fmin.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fmin.ll index 13ef11862166a8943f55378d4735e364c6951d0a..475da2e1ec31eaa66d15f919ea591f229f05591b 100644 --- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fmin.ll +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fmin.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_function_pointers %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} target triple = "spir64-unknown-unknown" diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fminimum.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fminimum.ll index 93ef79affdda3d641ec788f48e99b8198fefb310..b525c849c3b59a07e72f97b9075848e39950d564 100644 --- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fminimum.ll +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fminimum.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_function_pointers %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} target triple = "spir64-unknown-unknown" diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fmul.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fmul.ll index afe30d5b51e0f5628b3201667cd3d7dbe4a211e9..0985be992ca74e3d39ee84c22866204b912a6f1f 100644 --- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fmul.ll +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/fmul.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_function_pointers %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} target triple = "spir64-unknown-unknown" diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/mul.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/mul.ll index 9b397aee30cbf44f2c540df97908adbb68a957e9..1a700577e46b414709f7d974dd094e56a8917910 100644 --- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/mul.ll +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/mul.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_function_pointers %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} target triple = "spir64-unknown-unknown" diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/or.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/or.ll index a62bb0c376f33d0424436ab0ddb2c754f3198887..90c6cf5562a924ba20a6d789443a1049915d3e6c 100644 --- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/or.ll +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/or.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_function_pointers %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} target triple = "spir64-unknown-unknown" diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/smax.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/smax.ll index 3fc2bcc86054aa03d5a471c96ad73ccf8de95f31..4551fa31681d2bd09023dce7ad01eea845c1f3d9 100644 --- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/smax.ll +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/smax.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_function_pointers %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} target triple = "spir64-unknown-unknown" diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/smin.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/smin.ll index 9459946a408fba1da8533ea6b7abeddb90c56872..a0d257bb13180442abfcf33cb7e52c002ad6caf4 100644 --- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/smin.ll +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/smin.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_function_pointers %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} target triple = "spir64-unknown-unknown" diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/umax.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/umax.ll index cce7189c173c5d412974aa946d6f61e78c72a0ac..ba5dba76aeeccafad09d5edd37a69609d04cb199 100644 --- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/umax.ll +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/umax.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_function_pointers %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} target triple = "spir64-unknown-unknown" diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/umin.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/umin.ll index bcc49c50d480fc30b37f00ef3508bab7eb5bf1e3..e16bde88ef5094215d4ca9a7840076c8f343a4d1 100644 --- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/umin.ll +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/umin.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_function_pointers %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} target triple = "spir64-unknown-unknown" diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/xor.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/xor.ll index 26bc96b41a9898d134ff3bdc585c3b682a873b97..cf887bb358aca6c5f8b00dfbdd4d078db43beffb 100644 --- a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/xor.ll +++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/llvm-vector-reduce/xor.ll @@ -1,4 +1,4 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_INTEL_function_pointers %s -o - | FileCheck %s +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_INTEL_function_pointers %s -o - | FileCheck %s ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} target triple = "spir64-unknown-unknown" diff --git a/llvm/test/CodeGen/SPIRV/pointers/bitcast-fix-accesschain.ll b/llvm/test/CodeGen/SPIRV/pointers/bitcast-fix-accesschain.ll new file mode 100644 index 0000000000000000000000000000000000000000..7fae6ca2c48cf1838420011427dc6b9c86331a74 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/bitcast-fix-accesschain.ll @@ -0,0 +1,37 @@ +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-DAG: %[[#TYCHAR:]] = OpTypeInt 8 0 +; CHECK-DAG: %[[#TYCHARPTR:]] = OpTypePointer Function %[[#TYCHAR]] +; CHECK-DAG: %[[#TYINT32:]] = OpTypeInt 32 0 +; CHECK-DAG: %[[#TYSTRUCTINT32:]] = OpTypeStruct %[[#TYINT32]] +; CHECK-DAG: %[[#TYARRAY:]] = OpTypeArray %[[#TYSTRUCTINT32]] %[[#]] +; CHECK-DAG: %[[#TYSTRUCT:]] = OpTypeStruct %[[#TYARRAY]] +; CHECK-DAG: %[[#TYSTRUCTPTR:]] = OpTypePointer Function %[[#TYSTRUCT]] +; CHECK-DAG: %[[#TYINT64:]] = OpTypeInt 64 0 +; CHECK-DAG: %[[#TYINT64PTR:]] = OpTypePointer Function %[[#TYINT64]] +; CHECK: OpFunction +; CHECK: %[[#PTRTOSTRUCT:]] = OpFunctionParameter %[[#TYSTRUCTPTR]] +; CHECK: %[[#PTRTOCHAR:]] = OpBitcast %[[#TYCHARPTR]] %[[#PTRTOSTRUCT]] +; CHECK-NEXT: OpInBoundsPtrAccessChain %[[#TYCHARPTR]] %[[#PTRTOCHAR]] +; CHECK: OpFunction +; CHECK: %[[#PTRTOSTRUCT2:]] = OpFunctionParameter %[[#TYSTRUCTPTR]] +; CHECK: %[[#ELEM:]] = OpInBoundsPtrAccessChain %[[#TYSTRUCTPTR]] %[[#PTRTOSTRUCT2]] +; CHECK-NEXT: %[[#TOLOAD:]] = OpBitcast %[[#TYINT64PTR]] %[[#ELEM]] +; CHECK-NEXT: OpLoad %[[#TYINT64]] %[[#TOLOAD]] + +%struct.S = type { i32 } +%struct.__wrapper_class = type { [7 x %struct.S] } + +define spir_kernel void @foo1(ptr noundef byval(%struct.__wrapper_class) align 4 %_arg_Arr) { +entry: + %elem = getelementptr inbounds i8, ptr %_arg_Arr, i64 0 + ret void +} + +define spir_kernel void @foo2(ptr noundef byval(%struct.__wrapper_class) align 4 %_arg_Arr) { +entry: + %elem = getelementptr inbounds %struct.__wrapper_class, ptr %_arg_Arr, i64 0 + %data = load i64, ptr %elem + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/pointers/bitcast-fix-load.ll b/llvm/test/CodeGen/SPIRV/pointers/bitcast-fix-load.ll index a30d0792e39988db2ad6c99c9dedeedc398bcc10..18752fdf843d20723868d43986cf60fe73234991 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/bitcast-fix-load.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/bitcast-fix-load.ll @@ -9,7 +9,7 @@ ; CHECK-DAG: %[[#TYLONGPTR:]] = OpTypePointer Function %[[#TYLONG]] ; CHECK: %[[#PTRTOSTRUCT:]] = OpFunctionParameter %[[#TYSTRUCTPTR]] ; CHECK: %[[#PTRTOLONG:]] = OpBitcast %[[#TYLONGPTR]] %[[#PTRTOSTRUCT]] -; CHECK: OpLoad %[[#TYLONG]] %[[#PTRTOLONG]] +; CHECK-NEXT: OpLoad %[[#TYLONG]] %[[#PTRTOLONG]] %struct.S = type { i32 } %struct.__wrapper_class = type { [7 x %struct.S] } diff --git a/llvm/test/CodeGen/SPIRV/pointers/bitcast-fix-store.ll b/llvm/test/CodeGen/SPIRV/pointers/bitcast-fix-store.ll index 4701f02ea33af385c0f728945abae7693cea483c..202bcfbf2599a9893a01d33aff40df5d7ea00d71 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/bitcast-fix-store.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/bitcast-fix-store.ll @@ -13,7 +13,7 @@ ; CHECK: %[[#OBJ:]] = OpFunctionParameter %[[#TYSTRUCT]] ; CHECK: %[[#ARGPTR2:]] = OpFunctionParameter %[[#TYLONGPTR]] ; CHECK: %[[#PTRTOSTRUCT:]] = OpBitcast %[[#TYSTRUCTPTR]] %[[#ARGPTR2]] -; CHECK: OpStore %[[#PTRTOSTRUCT]] %[[#OBJ]] +; CHECK-NEXT: OpStore %[[#PTRTOSTRUCT]] %[[#OBJ]] %struct.S = type { i32 } %struct.__wrapper_class = type { [7 x %struct.S] } diff --git a/llvm/test/CodeGen/SPIRV/pointers/getelementptr-addressspace.ll b/llvm/test/CodeGen/SPIRV/pointers/getelementptr-addressspace.ll index 062863a0e3adc98a4b6ef2e0708145a2670d4a50..7e9c6214c2818a0e6b32e6924d5d9352273beb89 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/getelementptr-addressspace.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/getelementptr-addressspace.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK: %[[#INT8:]] = OpTypeInt 8 0 ; CHECK: %[[#PTR1:]] = OpTypePointer CrossWorkgroup %[[#INT8]] diff --git a/llvm/test/CodeGen/SPIRV/pointers/getelementptr-base-type.ll b/llvm/test/CodeGen/SPIRV/pointers/getelementptr-base-type.ll index aaf97f8cc836c6be46f9754bd547685f3663d07a..fc999ba1a3cdac8cadf4f9c03cce66b2c751534c 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/getelementptr-base-type.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/getelementptr-base-type.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK: %[[#FLOAT32:]] = OpTypeFloat 32 ; CHECK: %[[#PTR:]] = OpTypePointer CrossWorkgroup %[[#FLOAT32]] diff --git a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-addressspace.ll b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-addressspace.ll index 6d1202328197d9567caabbad98e955b1ad6c49ab..a3a730ac67e782c976ad21b10d676cca74a5356c 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-addressspace.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-addressspace.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: %[[#INT:]] = OpTypeInt 32 0 ; CHECK-DAG: %[[#PTR1:]] = OpTypePointer Function %[[#INT]] diff --git a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-no-bitcast-to-generic.ll b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-no-bitcast-to-generic.ll index 9e136ce887468d538edab4c7101f29f3ec7759f9..b74a3449980d979ef5e48f014546d068972f0459 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-no-bitcast-to-generic.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type-deduction-no-bitcast-to-generic.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: %[[#IMAGE:]] = OpTypeImage %2 2D 0 0 0 0 Unknown ReadOnly diff --git a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type.ll b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type.ll index 1fcc6d9da9c7876676ee3495146b5b9e6d070318..b8f205a68e56167034f6431eb7db105372d59f95 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/kernel-argument-pointer-type.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: %[[#FLOAT32:]] = OpTypeFloat 32 ; CHECK-DAG: %[[#PTR1:]] = OpTypePointer Function %[[#FLOAT32]] diff --git a/llvm/test/CodeGen/SPIRV/pointers/load-addressspace.ll b/llvm/test/CodeGen/SPIRV/pointers/load-addressspace.ll index 1b4e7a3e733fc610ac32e0b70378de69aca66e40..1667abc51be9fc16241e3856eaa51baad164b8e2 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/load-addressspace.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/load-addressspace.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK: %[[#INT8:]] = OpTypeInt 8 0 ; CHECK: %[[#PTR1:]] = OpTypePointer CrossWorkgroup %[[#INT8]] diff --git a/llvm/test/CodeGen/SPIRV/pointers/nested-struct-opaque-pointers.ll b/llvm/test/CodeGen/SPIRV/pointers/nested-struct-opaque-pointers.ll new file mode 100644 index 0000000000000000000000000000000000000000..77b895c7762fbaf1a6651df9a6a51067d22c9f44 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/nested-struct-opaque-pointers.ll @@ -0,0 +1,20 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-NOT: OpTypeInt 8 0 + +@GI = addrspace(1) constant i64 42 + +@GS = addrspace(1) global {ptr addrspace(1), ptr addrspace(1)} { ptr addrspace(1) @GI, ptr addrspace(1) @GI } +@GS2 = addrspace(1) global {ptr addrspace(1), ptr addrspace(1)} { ptr addrspace(1) @GS, ptr addrspace(1) @GS } +@GS3 = addrspace(1) global {ptr addrspace(1), ptr addrspace(1)} { ptr addrspace(1) @GS2, ptr addrspace(1) @GS2 } + +@GPS = addrspace(1) global ptr addrspace(1) @GS3 + +@GPI1 = addrspace(1) global ptr addrspace(1) @GI +@GPI2 = addrspace(1) global ptr addrspace(1) @GPI1 +@GPI3 = addrspace(1) global ptr addrspace(1) @GPI2 + +define spir_kernel void @foo() { + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/pointers/store-operand-ptr-to-struct.ll b/llvm/test/CodeGen/SPIRV/pointers/store-operand-ptr-to-struct.ll index 00b03c08e7bbcd36b1f85ecc48e6359bba27e0dc..3a0d65e1e95f192ee830f603751d91fc9dd12847 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/store-operand-ptr-to-struct.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/store-operand-ptr-to-struct.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; TODO: OpFunctionParameter should be a pointer of struct base type. ; XFAIL: * diff --git a/llvm/test/CodeGen/SPIRV/pointers/struct-opaque-pointers.ll b/llvm/test/CodeGen/SPIRV/pointers/struct-opaque-pointers.ll index 86f5f5bf24f5be2d98ee1fcece36b00eedf739a7..6d4913f802c289847775cca5c6bc7ad5b219d7f4 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/struct-opaque-pointers.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/struct-opaque-pointers.ll @@ -1,14 +1,14 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s -; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} -; CHECK: %[[TyInt8:.*]] = OpTypeInt 8 0 -; CHECK: %[[TyInt8Ptr:.*]] = OpTypePointer {{[a-zA-Z]+}} %[[TyInt8]] -; CHECK: %[[TyStruct:.*]] = OpTypeStruct %[[TyInt8Ptr]] %[[TyInt8Ptr]] +; CHECK: %[[TyInt64:.*]] = OpTypeInt 64 0 +; CHECK: %[[TyInt64Ptr:.*]] = OpTypePointer {{[a-zA-Z]+}} %[[TyInt64]] +; CHECK: %[[TyStruct:.*]] = OpTypeStruct %[[TyInt64Ptr]] %[[TyInt64Ptr]] ; CHECK: %[[ConstStruct:.*]] = OpConstantComposite %[[TyStruct]] %[[ConstField:.*]] %[[ConstField]] ; CHECK: %[[TyStructPtr:.*]] = OpTypePointer {{[a-zA-Z]+}} %[[TyStruct]] ; CHECK: OpVariable %[[TyStructPtr]] {{[a-zA-Z]+}} %[[ConstStruct]] -@a = addrspace(1) constant i32 123 +@a = addrspace(1) constant i64 42 @struct = addrspace(1) global {ptr addrspace(1), ptr addrspace(1)} { ptr addrspace(1) @a, ptr addrspace(1) @a } define spir_kernel void @foo() { diff --git a/llvm/test/CodeGen/SPIRV/pointers/two-bitcast-or-param-users.ll b/llvm/test/CodeGen/SPIRV/pointers/two-bitcast-or-param-users.ll index 52180d53740883b8ccdd0e85d21a8f01483926f0..23c3faaf88151f32e331913220ea7292f87fc70d 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/two-bitcast-or-param-users.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/two-bitcast-or-param-users.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: %[[#INT:]] = OpTypeInt 32 ; CHECK-DAG: %[[#GLOBAL_PTR_INT:]] = OpTypePointer CrossWorkgroup %[[#INT]] diff --git a/llvm/test/CodeGen/SPIRV/pointers/two-subsequent-bitcasts.ll b/llvm/test/CodeGen/SPIRV/pointers/two-subsequent-bitcasts.ll index 473c2a8b7311152f5dec570c874ca3516a981f31..83234e3986c84f49803fb6d1aa4dae9e01d6f44a 100644 --- a/llvm/test/CodeGen/SPIRV/pointers/two-subsequent-bitcasts.ll +++ b/llvm/test/CodeGen/SPIRV/pointers/two-subsequent-bitcasts.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-DAG: %[[#float:]] = OpTypeFloat 32 ; CHECK-DAG: %[[#pointer:]] = OpTypePointer CrossWorkgroup %[[#float]] diff --git a/llvm/test/CodeGen/SPIRV/pointers/type-deduce-args-rev.ll b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-args-rev.ll new file mode 100644 index 0000000000000000000000000000000000000000..ae7fb99907b131cc02c47926106bfa5089399b69 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-args-rev.ll @@ -0,0 +1,28 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-SPIRV-DAG: OpName %[[FooArg:.*]] "known_type_ptr" +; CHECK-SPIRV-DAG: OpName %[[Foo:.*]] "foo" +; CHECK-SPIRV-DAG: OpName %[[ArgToDeduce:.*]] "unknown_type_ptr" +; CHECK-SPIRV-DAG: OpName %[[Bar:.*]] "bar" +; CHECK-SPIRV-DAG: %[[Long:.*]] = OpTypeInt 32 0 +; CHECK-SPIRV-DAG: %[[Void:.*]] = OpTypeVoid +; CHECK-SPIRV-DAG: %[[LongPtr:.*]] = OpTypePointer CrossWorkgroup %[[Long]] +; CHECK-SPIRV-DAG: %[[Fun:.*]] = OpTypeFunction %[[Void]] %[[LongPtr]] +; CHECK-SPIRV: %[[Bar]] = OpFunction %[[Void]] None %[[Fun]] +; CHECK-SPIRV: %[[ArgToDeduce]] = OpFunctionParameter %[[LongPtr]] +; CHECK-SPIRV: OpFunctionCall %[[Void]] %[[Foo]] %[[ArgToDeduce]] +; CHECK-SPIRV: %[[Foo]] = OpFunction %[[Void]] None %[[Fun]] +; CHECK-SPIRV: %[[FooArg]] = OpFunctionParameter %[[LongPtr]] + +define spir_kernel void @bar(ptr addrspace(1) %unknown_type_ptr) { +entry: + %elem = getelementptr inbounds i32, ptr addrspace(1) %unknown_type_ptr, i64 0 + call void @foo(ptr addrspace(1) %unknown_type_ptr) + ret void +} + +define void @foo(ptr addrspace(1) %known_type_ptr) { +entry: + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/pointers/type-deduce-args.ll b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-args.ll new file mode 100644 index 0000000000000000000000000000000000000000..ee411f2646602731b3b1a78962ca3d1802e71b5c --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-args.ll @@ -0,0 +1,97 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-SPIRV-DAG: OpName %[[FooArg:.*]] "unknown_type_ptr" +; CHECK-SPIRV-DAG: OpName %[[Foo:.*]] "foo" +; CHECK-SPIRV-DAG: OpName %[[BarArg:.*]] "known_type_ptr" +; CHECK-SPIRV-DAG: OpName %[[Bar:.*]] "bar" +; CHECK-SPIRV-DAG: OpName %[[UntypedArg:.*]] "arg" +; CHECK-SPIRV-DAG: OpName %[[FunUntypedArg:.*]] "foo_untyped_arg" +; CHECK-SPIRV-DAG: OpName %[[UnusedArg1:.*]] "unused_arg1" +; CHECK-SPIRV-DAG: OpName %[[Foo2Arg:.*]] "unknown_type_ptr" +; CHECK-SPIRV-DAG: OpName %[[Foo2:.*]] "foo2" +; CHECK-SPIRV-DAG: OpName %[[Bar2Arg:.*]] "known_type_ptr" +; CHECK-SPIRV-DAG: OpName %[[Bar2:.*]] "bar2" +; CHECK-SPIRV-DAG: OpName %[[Foo5Arg1:.*]] "unknown_type_ptr1" +; CHECK-SPIRV-DAG: OpName %[[Foo5Arg2:.*]] "unknown_type_ptr2" +; CHECK-SPIRV-DAG: OpName %[[Foo5:.*]] "foo5" +; CHECK-SPIRV-DAG: OpName %[[Bar5Arg:.*]] "known_type_ptr" +; CHECK-SPIRV-DAG: OpName %[[Bar5:.*]] "bar5" +; CHECK-SPIRV-DAG: %[[Char:.*]] = OpTypeInt 8 0 +; CHECK-SPIRV-DAG: %[[Long:.*]] = OpTypeInt 32 0 +; CHECK-SPIRV-DAG: %[[Half:.*]] = OpTypeFloat 16 +; CHECK-SPIRV-DAG: %[[Void:.*]] = OpTypeVoid +; CHECK-SPIRV-DAG: %[[HalfConst:.*]] = OpConstant %[[Half]] 15360 +; CHECK-SPIRV-DAG: %[[CharPtr:.*]] = OpTypePointer CrossWorkgroup %[[Char]] +; CHECK-SPIRV-DAG: %[[LongPtr:.*]] = OpTypePointer CrossWorkgroup %[[Long]] +; CHECK-SPIRV-DAG: %[[Fun:.*]] = OpTypeFunction %[[Void]] %[[LongPtr]] +; CHECK-SPIRV-DAG: %[[Fun2:.*]] = OpTypeFunction %[[Void]] %[[Half]] %[[LongPtr]] +; CHECK-SPIRV-DAG: %[[Fun5:.*]] = OpTypeFunction %[[Void]] %[[Half]] %[[LongPtr]] %[[Half]] %[[LongPtr]] %[[Half]] +; CHECK-SPIRV-DAG: %[[FunUntyped:.*]] = OpTypeFunction %[[Void]] %[[CharPtr]] + +; CHECK-SPIRV: %[[Foo]] = OpFunction %[[Void]] None %[[Fun]] +; CHECK-SPIRV: %[[FooArg]] = OpFunctionParameter %[[LongPtr]] +; CHECK-SPIRV: %[[Bar]] = OpFunction %[[Void]] None %[[Fun]] +; CHECK-SPIRV: %[[BarArg]] = OpFunctionParameter %[[LongPtr]] +; CHECK-SPIRV: OpFunctionCall %[[Void]] %[[Foo]] %[[BarArg]] + +; CHECK-SPIRV: %[[FunUntypedArg]] = OpFunction %[[Void]] None %[[FunUntyped]] +; CHECK-SPIRV: %[[UntypedArg]] = OpFunctionParameter %[[CharPtr]] + +; CHECK-SPIRV: %[[Foo2]] = OpFunction %[[Void]] None %[[Fun2]] +; CHECK-SPIRV: %[[UnusedArg1]] = OpFunctionParameter %[[Half]] +; CHECK-SPIRV: %[[Foo2Arg]] = OpFunctionParameter %[[LongPtr]] +; CHECK-SPIRV: %[[Bar2]] = OpFunction %[[Void]] None %[[Fun]] +; CHECK-SPIRV: %[[Bar2Arg]] = OpFunctionParameter %[[LongPtr]] +; CHECK-SPIRV: OpFunctionCall %[[Void]] %[[Foo2]] %[[HalfConst]] %[[Bar2Arg]] + +; CHECK-SPIRV: %[[Foo5]] = OpFunction %[[Void]] None %[[Fun5]] +; CHECK-SPIRV: OpFunctionParameter %[[Half]] +; CHECK-SPIRV: %[[Foo5Arg1]] = OpFunctionParameter %[[LongPtr]] +; CHECK-SPIRV: OpFunctionParameter %[[Half]] +; CHECK-SPIRV: %[[Foo5Arg2]] = OpFunctionParameter %[[LongPtr]] +; CHECK-SPIRV: OpFunctionParameter %[[Half]] +; CHECK-SPIRV: %[[Bar5]] = OpFunction %[[Void]] None %[[Fun]] +; CHECK-SPIRV: %[[Bar5Arg]] = OpFunctionParameter %[[LongPtr]] +; CHECK-SPIRV: OpFunctionCall %[[Void]] %[[Foo5]] %[[HalfConst]] %[[Bar5Arg]] %[[HalfConst]] %[[Bar5Arg]] %[[HalfConst]] + +define void @foo(ptr addrspace(1) %unknown_type_ptr) { +entry: + ret void +} + +define spir_kernel void @bar(ptr addrspace(1) %known_type_ptr) { +entry: + %elem = getelementptr inbounds i32, ptr addrspace(1) %known_type_ptr, i64 0 + call void @foo(ptr addrspace(1) %known_type_ptr) + ret void +} + +define void @foo_untyped_arg(ptr addrspace(1) %arg) { +entry: + ret void +} + +define void @foo2(half %unused_arg1, ptr addrspace(1) %unknown_type_ptr) { +entry: + ret void +} + +define spir_kernel void @bar2(ptr addrspace(1) %known_type_ptr) { +entry: + %elem = getelementptr inbounds i32, ptr addrspace(1) %known_type_ptr, i64 0 + call void @foo2(half 1.0, ptr addrspace(1) %known_type_ptr) + ret void +} + +define void @foo5(half %unused_arg1, ptr addrspace(1) %unknown_type_ptr1, half %unused_arg2, ptr addrspace(1) %unknown_type_ptr2, half %unused_arg3) { +entry: + ret void +} + +define spir_kernel void @bar5(ptr addrspace(1) %known_type_ptr) { +entry: + %elem = getelementptr inbounds i32, ptr addrspace(1) %known_type_ptr, i64 0 + call void @foo5(half 1.0, ptr addrspace(1) %known_type_ptr, half 1.0, ptr addrspace(1) %known_type_ptr, half 1.0) + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call-chain.ll b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call-chain.ll new file mode 100644 index 0000000000000000000000000000000000000000..1071d3443056cb3c86e215eb9ff8783b49afa404 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call-chain.ll @@ -0,0 +1,57 @@ +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-SPIRV-DAG: OpName %[[ArgCum:.*]] "_arg_cum" +; CHECK-SPIRV-DAG: OpName %[[FunTest:.*]] "test" +; CHECK-SPIRV-DAG: OpName %[[Addr:.*]] "addr" +; CHECK-SPIRV-DAG: OpName %[[StubObj:.*]] "stub_object" +; CHECK-SPIRV-DAG: OpName %[[MemOrder:.*]] "mem_order" +; CHECK-SPIRV-DAG: OpName %[[FooStub:.*]] "foo_stub" +; CHECK-SPIRV-DAG: OpName %[[FooObj:.*]] "foo_object" +; CHECK-SPIRV-DAG: OpName %[[FooMemOrder:.*]] "mem_order" +; CHECK-SPIRV-DAG: OpName %[[FooFunc:.*]] "foo" +; CHECK-SPIRV-DAG: %[[TyLong:.*]] = OpTypeInt 32 0 +; CHECK-SPIRV-DAG: %[[TyVoid:.*]] = OpTypeVoid +; CHECK-SPIRV-DAG: %[[TyPtrLong:.*]] = OpTypePointer CrossWorkgroup %[[TyLong]] +; CHECK-SPIRV-DAG: %[[TyFunPtrLong:.*]] = OpTypeFunction %[[TyVoid]] %[[TyPtrLong]] +; CHECK-SPIRV-DAG: %[[TyGenPtrLong:.*]] = OpTypePointer Generic %[[TyLong]] +; CHECK-SPIRV-DAG: %[[TyFunGenPtrLongLong:.*]] = OpTypeFunction %[[TyVoid]] %[[TyGenPtrLong]] %[[TyLong]] +; CHECK-SPIRV-DAG: %[[Const3:.*]] = OpConstant %[[TyLong]] 3 +; CHECK-SPIRV: %[[FunTest]] = OpFunction %[[TyVoid]] None %[[TyFunPtrLong]] +; CHECK-SPIRV: %[[ArgCum]] = OpFunctionParameter %[[TyPtrLong]] +; CHECK-SPIRV: OpFunctionCall %[[TyVoid]] %[[FooFunc]] %[[Addr]] %[[Const3]] +; CHECK-SPIRV: %[[FooStub]] = OpFunction %[[TyVoid]] None %[[TyFunGenPtrLongLong]] +; CHECK-SPIRV: %[[StubObj]] = OpFunctionParameter %[[TyGenPtrLong]] +; CHECK-SPIRV: %[[MemOrder]] = OpFunctionParameter %[[TyLong]] +; CHECK-SPIRV: %[[FooFunc]] = OpFunction %[[TyVoid]] None %[[TyFunGenPtrLongLong]] +; CHECK-SPIRV: %[[FooObj]] = OpFunctionParameter %[[TyGenPtrLong]] +; CHECK-SPIRV: %[[FooMemOrder]] = OpFunctionParameter %[[TyLong]] +; CHECK-SPIRV: OpFunctionCall %[[TyVoid]] %[[FooStub]] %[[FooObj]] %[[FooMemOrder]] + +define spir_kernel void @test(ptr addrspace(1) noundef align 4 %_arg_cum) { +entry: + %lptr = getelementptr inbounds i32, ptr addrspace(1) %_arg_cum, i64 1 + %addr = addrspacecast ptr addrspace(1) %lptr to ptr addrspace(4) + %object = bitcast ptr addrspace(4) %addr to ptr addrspace(4) + call spir_func void @foo(ptr addrspace(4) %object, i32 3) + %halfptr = getelementptr inbounds half, ptr addrspace(1) %_arg_cum, i64 1 + %halfaddr = addrspacecast ptr addrspace(1) %halfptr to ptr addrspace(4) + call spir_func void @foo(ptr addrspace(4) %halfaddr, i32 3) + %dblptr = getelementptr inbounds double, ptr addrspace(1) %_arg_cum, i64 1 + %dbladdr = addrspacecast ptr addrspace(1) %dblptr to ptr addrspace(4) + call spir_func void @foo(ptr addrspace(4) %dbladdr, i32 3) + ret void +} + +define void @foo_stub(ptr addrspace(4) noundef %stub_object, i32 noundef %mem_order) { +entry: + %object.addr = alloca ptr addrspace(4) + %object.addr.ascast = addrspacecast ptr %object.addr to ptr addrspace(4) + store ptr addrspace(4) %stub_object, ptr addrspace(4) %object.addr.ascast + ret void +} + +define void @foo(ptr addrspace(4) noundef %foo_object, i32 noundef %mem_order) { + tail call void @foo_stub(ptr addrspace(4) noundef %foo_object, i32 noundef %mem_order) + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call-complex.ll b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call-complex.ll new file mode 100644 index 0000000000000000000000000000000000000000..ea7a22c31d0e8545949cc5b783a1f4df05b5c857 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call-complex.ll @@ -0,0 +1,29 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-SPIRV-DAG: %[[Long:.*]] = OpTypeInt 32 0 +; CHECK-SPIRV-DAG: %[[Void:.*]] = OpTypeVoid +; CHECK-SPIRV-DAG: %[[Struct:.*]] = OpTypeStruct %[[Long]] +; CHECK-SPIRV-DAG: %[[StructPtr:.*]] = OpTypePointer Generic %[[Struct]] +; CHECK-SPIRV-DAG: %[[Function:.*]] = OpTypeFunction %[[Void]] %[[StructPtr]] +; CHECK-SPIRV-DAG: %[[Const:.*]] = OpConstantNull %[[Struct]] +; CHECK-SPIRV-DAG: %[[CrossStructPtr:.*]] = OpTypePointer CrossWorkgroup %[[Struct]] +; CHECK-SPIRV-DAG: %[[Var:.*]] = OpVariable %[[CrossStructPtr]] CrossWorkgroup %[[Const]] +; CHECK-SPIRV: %[[Foo:.*]] = OpFunction %[[Void]] None %[[Function]] +; CHECK-SPIRV-NEXT: OpFunctionParameter %[[StructPtr]] +; CHECK-SPIRV: %[[Casted:.*]] = OpPtrCastToGeneric %[[StructPtr]] %[[Var]] +; CHECK-SPIRV-NEXT: OpFunctionCall %[[Void]] %[[Foo]] %[[Casted]] + +%struct.global_ctor_dtor = type { i32 } +@g1 = addrspace(1) global %struct.global_ctor_dtor zeroinitializer + +define linkonce_odr spir_func void @foo(ptr addrspace(4) %this) { +entry: + ret void +} + +define internal spir_func void @bar() { +entry: + call spir_func void @foo(ptr addrspace(4) addrspacecast (ptr addrspace(1) @g1 to ptr addrspace(4))) + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call-rev.ll b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call-rev.ll new file mode 100644 index 0000000000000000000000000000000000000000..76769ab874308253ca990af76d81de7c1ce9a800 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call-rev.ll @@ -0,0 +1,28 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-SPIRV-DAG: OpName %[[FooArg:.*]] "known_type_ptr" +; CHECK-SPIRV-DAG: OpName %[[Foo:.*]] "foo" +; CHECK-SPIRV-DAG: OpName %[[ArgToDeduce:.*]] "unknown_type_ptr" +; CHECK-SPIRV-DAG: OpName %[[Bar:.*]] "bar" +; CHECK-SPIRV-DAG: %[[Long:.*]] = OpTypeInt 32 0 +; CHECK-SPIRV-DAG: %[[Void:.*]] = OpTypeVoid +; CHECK-SPIRV-DAG: %[[LongPtr:.*]] = OpTypePointer CrossWorkgroup %[[Long]] +; CHECK-SPIRV-DAG: %[[Fun:.*]] = OpTypeFunction %[[Void]] %[[LongPtr]] +; CHECK-SPIRV: %[[Bar]] = OpFunction %[[Void]] None %[[Fun]] +; CHECK-SPIRV: %[[ArgToDeduce]] = OpFunctionParameter %[[LongPtr]] +; CHECK-SPIRV: OpFunctionCall %[[Void]] %[[Foo]] %[[ArgToDeduce]] +; CHECK-SPIRV: %[[Foo]] = OpFunction %[[Void]] None %[[Fun]] +; CHECK-SPIRV: %[[FooArg]] = OpFunctionParameter %[[LongPtr]] + +define spir_kernel void @bar(ptr addrspace(1) %unknown_type_ptr) { +entry: + call spir_func void @foo(ptr addrspace(1) %unknown_type_ptr) + ret void +} + +define void @foo(ptr addrspace(1) %known_type_ptr) { +entry: + %elem = getelementptr inbounds i32, ptr addrspace(1) %known_type_ptr, i64 0 + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call.ll b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call.ll new file mode 100644 index 0000000000000000000000000000000000000000..8cbf360a2e38d4eb73770faf9b6ee6e5a4dee21b --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/type-deduce-by-call.ll @@ -0,0 +1,28 @@ +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-SPIRV-DAG: OpName %[[FooArg:.*]] "known_type_ptr" +; CHECK-SPIRV-DAG: OpName %[[Foo:.*]] "foo" +; CHECK-SPIRV-DAG: OpName %[[ArgToDeduce:.*]] "unknown_type_ptr" +; CHECK-SPIRV-DAG: OpName %[[Bar:.*]] "bar" +; CHECK-SPIRV-DAG: %[[Long:.*]] = OpTypeInt 32 0 +; CHECK-SPIRV-DAG: %[[Void:.*]] = OpTypeVoid +; CHECK-SPIRV-DAG: %[[LongPtr:.*]] = OpTypePointer CrossWorkgroup %[[Long]] +; CHECK-SPIRV-DAG: %[[Fun:.*]] = OpTypeFunction %[[Void]] %[[LongPtr]] +; CHECK-SPIRV: %[[Foo]] = OpFunction %[[Void]] None %[[Fun]] +; CHECK-SPIRV: %[[FooArg]] = OpFunctionParameter %[[LongPtr]] +; CHECK-SPIRV: %[[Bar]] = OpFunction %[[Void]] None %[[Fun]] +; CHECK-SPIRV: %[[ArgToDeduce]] = OpFunctionParameter %[[LongPtr]] +; CHECK-SPIRV: OpFunctionCall %[[Void]] %[[Foo]] %[[ArgToDeduce]] + +define void @foo(ptr addrspace(1) %known_type_ptr) { +entry: + %elem = getelementptr inbounds i32, ptr addrspace(1) %known_type_ptr, i64 0 + ret void +} + +define spir_kernel void @bar(ptr addrspace(1) %unknown_type_ptr) { +entry: + call spir_func void @foo(ptr addrspace(1) %unknown_type_ptr) + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/pointers/typeof-ptr-int.ll b/llvm/test/CodeGen/SPIRV/pointers/typeof-ptr-int.ll new file mode 100644 index 0000000000000000000000000000000000000000..f144418cf54259763a0b610366a1f975d85cbf4e --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/pointers/typeof-ptr-int.ll @@ -0,0 +1,29 @@ +; This test is to check that two functions have different SPIR-V type +; definitions, even though their LLVM function types are identical. + +; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} + +; CHECK-DAG: OpName %[[Fun32:.*]] "tp_arg_i32" +; CHECK-DAG: OpName %[[Fun64:.*]] "tp_arg_i64" +; CHECK-DAG: %[[TyI32:.*]] = OpTypeInt 32 0 +; CHECK-DAG: %[[TyVoid:.*]] = OpTypeVoid +; CHECK-DAG: %[[TyPtr32:.*]] = OpTypePointer Function %[[TyI32]] +; CHECK-DAG: %[[TyFun32:.*]] = OpTypeFunction %[[TyVoid]] %[[TyPtr32]] +; CHECK-DAG: %[[TyI64:.*]] = OpTypeInt 64 0 +; CHECK-DAG: %[[TyPtr64:.*]] = OpTypePointer Function %[[TyI64]] +; CHECK-DAG: %[[TyFun64:.*]] = OpTypeFunction %[[TyVoid]] %[[TyPtr64]] +; CHECK-DAG: %[[Fun32]] = OpFunction %[[TyVoid]] None %[[TyFun32]] +; CHECK-DAG: %[[Fun64]] = OpFunction %[[TyVoid]] None %[[TyFun64]] + +define spir_kernel void @tp_arg_i32(ptr %ptr) { +entry: + store i32 1, ptr %ptr + ret void +} + +define spir_kernel void @tp_arg_i64(ptr %ptr) { +entry: + store i64 1, ptr %ptr + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/relationals.ll b/llvm/test/CodeGen/SPIRV/relationals.ll index 1644dc7c03d91173d326f96b9203253740a0b477..f4fcf4d9f77b8c6c135e72c5a37d04a848f2cdaf 100644 --- a/llvm/test/CodeGen/SPIRV/relationals.ll +++ b/llvm/test/CodeGen/SPIRV/relationals.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} declare dso_local spir_func <4 x i8> @_Z13__spirv_IsNanIDv4_aDv4_fET_T0_(<4 x float>) declare dso_local spir_func <4 x i8> @_Z13__spirv_IsInfIDv4_aDv4_fET_T0_(<4 x float>) diff --git a/llvm/test/CodeGen/SPIRV/scfg-add-pre-headers.ll b/llvm/test/CodeGen/SPIRV/scfg-add-pre-headers.ll index 329399bab3e5b90565615b37f517fd211ba56a0d..2ea5c767730e19d097bd7a2cffcd656af57c8c19 100644 --- a/llvm/test/CodeGen/SPIRV/scfg-add-pre-headers.ll +++ b/llvm/test/CodeGen/SPIRV/scfg-add-pre-headers.ll @@ -1,5 +1,6 @@ ; RUN: llc -mtriple=spirv-unknown-unknown -O0 %s -o - | FileCheck %s +; CHECK-DAG: OpDecorate %[[#SubgroupLocalInvocationId:]] BuiltIn SubgroupLocalInvocationId ; CHECK-DAG: %[[#bool:]] = OpTypeBool ; CHECK-DAG: %[[#uint:]] = OpTypeInt 32 0 ; CHECK-DAG: %[[#uint_0:]] = OpConstant %[[#uint]] 0 @@ -37,10 +38,10 @@ l1_continue: ; CHECK-NEXT: OpBranch %[[#l1_header]] l1_end: - %call = call spir_func i32 @_Z3absi(i32 0) [ "convergencectrl"(token %tl1) ] + %call = call i32 @__hlsl_wave_get_lane_index() [ "convergencectrl"(token %tl1) ] br label %end ; CHECK-DAG: %[[#l1_end]] = OpLabel -; CHECK-DAG: %[[#]] = OpFunctionCall +; CHECK-DAG: %[[#]] = OpLoad %[[#]] %[[#SubgroupLocalInvocationId]] ; CHECK-NEXT: OpBranch %[[#end:]] l2: @@ -76,6 +77,4 @@ declare token @llvm.experimental.convergence.entry() declare token @llvm.experimental.convergence.control() declare token @llvm.experimental.convergence.loop() -; This intrinsic is not convergent. This is only because the backend doesn't -; support convergent operations yet. -declare spir_func i32 @_Z3absi(i32) convergent +declare i32 @__hlsl_wave_get_lane_index() convergent diff --git a/llvm/test/CodeGen/SPIRV/simple.ll b/llvm/test/CodeGen/SPIRV/simple.ll index de9efa83838582a8376fb83c8c22835c8e1f737a..63c15968c725356df01fdc84d0015a7a288aae2c 100644 --- a/llvm/test/CodeGen/SPIRV/simple.ll +++ b/llvm/test/CodeGen/SPIRV/simple.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; Support of doubles is required. ; CHECK: OpCapability Float64 diff --git a/llvm/test/CodeGen/SPIRV/transcoding/AtomicCompareExchangeExplicit_cl20.ll b/llvm/test/CodeGen/SPIRV/transcoding/AtomicCompareExchangeExplicit_cl20.ll index fdb26bab60fe140b10c237e9f3a0203120f87a0f..e0c47798cc6d099025c103ca31f5df36a04cefdb 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/AtomicCompareExchangeExplicit_cl20.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/AtomicCompareExchangeExplicit_cl20.ll @@ -1,4 +1,5 @@ -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --mattr=+spirv1.3 %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown --mattr=+spirv1.3 %s -o - -filetype=obj | spirv-val %} ;; __kernel void testAtomicCompareExchangeExplicit_cl20( ;; volatile global atomic_int* object, diff --git a/llvm/test/CodeGen/SPIRV/transcoding/BitReversePref.ll b/llvm/test/CodeGen/SPIRV/transcoding/BitReversePref.ll index 55161e670ca1333f69ab735ae1c9e2bce454a304..11b0578a0c9c07d460badf8e158d22745eb5b4c4 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/BitReversePref.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/BitReversePref.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-linux %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK: OpDecorate %[[#FUNC_NAME:]] LinkageAttributes "_Z10BitReversei" ; CHECK-NOT: OpBitReverse diff --git a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll index 95f3673d1c968deee7a249bcb59f262c689f28da..b63c1c60d007364b7fe1ac30ff07167532792524 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV-DAG: %[[#]] = OpBuildNDRange %[[#]] %[[#GWS:]] %[[#LWS:]] %[[#GWO:]] ; CHECK-SPIRV-DAG: %[[#GWS]] = OpConstant %[[#]] 123 diff --git a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_2.ll b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_2.ll index a2ae808259a32a6fbd29ec59b7e3d2445ddf9c3c..65c992c9b28ed3dcdeeb7b65663874ad144e7131 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_2.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/BuildNDRange_2.ll @@ -19,6 +19,7 @@ ;; bash$ $PATH_TO_GEN/bin/clang -cc1 -x cl -cl-std=CL2.0 -triple spir64-unknown-unknown -emit-llvm -include opencl-20.h BuildNDRange_2.cl -o BuildNDRange_2.ll ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; TODO(#60133): Requires updates following opaque pointer migration. ; XFAIL: * diff --git a/llvm/test/CodeGen/SPIRV/transcoding/ConvertPtr.ll b/llvm/test/CodeGen/SPIRV/transcoding/ConvertPtr.ll index 34036951e31e0baa0b649cf0d3e81d1f4fc0fe95..93aecc5331aa4fc06ccb49407c34e2660e84d885 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/ConvertPtr.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/ConvertPtr.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; kernel void testConvertPtrToU(global int *a, global unsigned long *res) { ;; res[0] = (unsigned long)&a[0]; diff --git a/llvm/test/CodeGen/SPIRV/transcoding/DecorationAlignment.ll b/llvm/test/CodeGen/SPIRV/transcoding/DecorationAlignment.ll index 2e9b4a494c04d85720e5dff9c92bf28c7c4add2d..d4fc5c3280b714f0e25b9e648e7a876bcfaa9263 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/DecorationAlignment.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/DecorationAlignment.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpDecorate %[[#ALIGNMENT:]] Alignment 16 ; CHECK-SPIRV: %[[#ALIGNMENT]] = OpFunctionParameter %[[#]] diff --git a/llvm/test/CodeGen/SPIRV/transcoding/DecorationMaxByteOffset.ll b/llvm/test/CodeGen/SPIRV/transcoding/DecorationMaxByteOffset.ll index 64f25b7f42035599fee0bef6edf6e454d6a59c08..966d83516bb3aef4bff72894c1a70bf1657800e7 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/DecorationMaxByteOffset.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/DecorationMaxByteOffset.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpName %[[#PTR_ID:]] "ptr" ; CHECK-SPIRV: OpName %[[#PTR2_ID:]] "ptr2" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/DivRem.ll b/llvm/test/CodeGen/SPIRV/transcoding/DivRem.ll index 2f423c2518e83aefa5040de9c7603689cc7ee603..67c3380941887d39bc6883494e7d4d9800f03c94 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/DivRem.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/DivRem.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV-DAG: %[[#int:]] = OpTypeInt 32 0 ; CHECK-SPIRV-DAG: %[[#int2:]] = OpTypeVector %[[#int]] 2 diff --git a/llvm/test/CodeGen/SPIRV/transcoding/ExecutionMode_SPIR_to_SPIRV.ll b/llvm/test/CodeGen/SPIRV/transcoding/ExecutionMode_SPIR_to_SPIRV.ll index 6d6dd2481b17dbc67aad18deda3244a7fbf3e2c8..6e8726cf03d4428a957d5ea0382d13cb07d40586 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/ExecutionMode_SPIR_to_SPIRV.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/ExecutionMode_SPIR_to_SPIRV.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV-DAG: OpEntryPoint Kernel %[[#WORKER:]] "worker" ; CHECK-SPIRV-DAG: OpExecutionMode %[[#WORKER]] LocalSizeHint 128 10 1 diff --git a/llvm/test/CodeGen/SPIRV/transcoding/GlobalFunAnnotate.ll b/llvm/test/CodeGen/SPIRV/transcoding/GlobalFunAnnotate.ll index 2796dcbdca948afaa69ae232942bb7096e94ddf2..33bece5b9c00f7eb9f2efed7ee185d7077e91ea7 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/GlobalFunAnnotate.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/GlobalFunAnnotate.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-linux %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpDecorate %[[#]] UserSemantic "annotation_on_function" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/NoSignedUnsignedWrap.ll b/llvm/test/CodeGen/SPIRV/transcoding/NoSignedUnsignedWrap.ll index 02d1250399f9fcc10bf8232fae488230015ab554..e405ef0ed58a5ef3ab1addbfa2cc951af80d3be4 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/NoSignedUnsignedWrap.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/NoSignedUnsignedWrap.ll @@ -7,7 +7,7 @@ ;; ;; Positive tests: ;; -; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-extensions=SPV_KHR_no_integer_wrap_decoration %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-NEGATIVE +; RUN: llc -O0 -mtriple=spirv32-unknown-unknown --spirv-ext=+SPV_KHR_no_integer_wrap_decoration %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV-NEGATIVE ;; ;; Negative tests: ;; diff --git a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_cmpxchg.ll b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_cmpxchg.ll index 331960cdb341e7bdfa363d5acf39783bb2b722cf..417b89eb36f0f534218b7bc0be07ed14e2cc45cc 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_cmpxchg.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_cmpxchg.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; This test checks that the backend is capable to correctly translate ;; atomic_cmpxchg OpenCL C 1.2 built-in function [1] into corresponding SPIR-V diff --git a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_legacy.ll b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_legacy.ll index 95eb6ade11a25cb2f01b02785ea4a08be937bdf4..3180b57731d01cd53b3fe91944c97c92726fe1f2 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_legacy.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_legacy.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; This test checks that the backend is capable to correctly translate ;; legacy atomic OpenCL C 1.2 built-in functions [1] into corresponding SPIR-V diff --git a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_work_item_fence.ll b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_work_item_fence.ll index 0f3a62a3e401073ba904863c8ae81e600e5db2f4..c94c13044185466c7adc6e7444bc9670ec317db4 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_work_item_fence.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/atomic_work_item_fence.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; This test checks that the backend is capable to correctly translate ;; atomic_work_item_fence OpenCL C 2.0 built-in function [1] into corresponding diff --git a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/barrier.ll b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/barrier.ll index a126d94e06334fdede97cd26113bee7ff2d49ba4..cf4a24754e7bfa34878efd3c3d1badbc2e5703c2 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/barrier.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/barrier.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; This test checks that the backend is capable to correctly translate ;; barrier OpenCL C 1.2 built-in function [1] into corresponding SPIR-V diff --git a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/sub_group_mask.ll b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/sub_group_mask.ll index 42b127cf3b69b6978c70945319d69b599bebf636..5d9840d3bd5b9c2b7b8aad874d4628c361e4ab29 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/sub_group_mask.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/sub_group_mask.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpCapability GroupNonUniformBallot ; CHECK-SPIRV: OpDecorate %[[#]] BuiltIn SubgroupGtMask diff --git a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/work_group_barrier.ll b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/work_group_barrier.ll index 0874e6f71e040767d6e9c736460999221c5bb0ea..0702fd0c9cb9b126c45441e1c9550645c8a33ace 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/work_group_barrier.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/OpenCL/work_group_barrier.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; This test checks that the backend is capable to correctly translate ;; sub_group_barrier built-in function [1] from cl_khr_subgroups extension into diff --git a/llvm/test/CodeGen/SPIRV/transcoding/atomic_flag.ll b/llvm/test/CodeGen/SPIRV/transcoding/atomic_flag.ll index 3c563d373f1bd42280cc93af24917d2ddcc3714e..20204acb1ef584e234bd361ac8f6ee925b4f9f6c 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/atomic_flag.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/atomic_flag.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; Types: ; CHECK-DAG: %[[#INT:]] = OpTypeInt 32 diff --git a/llvm/test/CodeGen/SPIRV/transcoding/atomic_load_store.ll b/llvm/test/CodeGen/SPIRV/transcoding/atomic_load_store.ll index d013abcade8bb4e458cca84d8315b22d760c4d46..3e5a3ac356936cb7d774bc71c100412f4129b3da 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/atomic_load_store.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/atomic_load_store.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; Check 'LLVM ==> SPIR-V' conversion of atomic_load and atomic_store. diff --git a/llvm/test/CodeGen/SPIRV/transcoding/bitcast.ll b/llvm/test/CodeGen/SPIRV/transcoding/bitcast.ll index 8dbf4d2c58b4bd9a2bc855d58e1fabda14d2e15f..2c0fc393b135a2a5f60f4f3efac0ad1185398fdd 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/bitcast.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/bitcast.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; Check the bitcast is translated back to bitcast diff --git a/llvm/test/CodeGen/SPIRV/transcoding/block_w_struct_return.ll b/llvm/test/CodeGen/SPIRV/transcoding/block_w_struct_return.ll index 5ecd7f73a52e3720f998d0963326917fdd4d5528..2249cbe4e98a54eab94a5a26753d164bb0c8174b 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/block_w_struct_return.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/block_w_struct_return.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV1_4 +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; TODO(#60133): Requires updates following opaque pointer migration. ; XFAIL: * diff --git a/llvm/test/CodeGen/SPIRV/transcoding/builtin_calls.ll b/llvm/test/CodeGen/SPIRV/transcoding/builtin_calls.ll index 9b1ce76631809dbcb507f2d433d8179cd87e6eb1..0a02a8bf56ace53f498103c036c98eb1fb461cd0 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/builtin_calls.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/builtin_calls.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV-DAG: OpDecorate %[[#Id:]] BuiltIn GlobalInvocationId ; CHECK-SPIRV-DAG: OpDecorate %[[#Id:]] BuiltIn GlobalLinearId diff --git a/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars.ll b/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars.ll index 82866712c0778840fe430f16de491d5e4d6db034..50748931635656d31f7afb6c35c7832d3b7f6cfe 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpDecorate %[[#Id:]] BuiltIn GlobalLinearId ; CHECK-SPIRV: %[[#Id:]] = OpVariable %[[#]] diff --git a/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars_arithmetics.ll b/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars_arithmetics.ll index 22aa40c0c7a796e682b583302e271216032f40fe..d0c4dff43121ccfba0b54a13adc94802fb09df2e 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars_arithmetics.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars_arithmetics.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-linux %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; The IR was generated from the following source: ;; #include <CL/sycl.hpp> diff --git a/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars_opt.ll b/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars_opt.ll index 5b3474f97bfedf14516dbafeed30b61954350151..3885f070231442a214c32e681f545fd3ac09bc9d 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars_opt.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/builtin_vars_opt.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-linux %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; The IR was generated from the following source: ;; #include <CL/sycl.hpp> diff --git a/llvm/test/CodeGen/SPIRV/transcoding/check_ro_qualifier.ll b/llvm/test/CodeGen/SPIRV/transcoding/check_ro_qualifier.ll index 6de610b2240da741615ced267b83025e6a79e8b2..824ca1b2d692496d01c8db25ebe4b1a5506ab266 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/check_ro_qualifier.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/check_ro_qualifier.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: %[[#IMAGE_TYPE:]] = OpTypeImage ; CHECK-SPIRV: %[[#IMAGE_ARG:]] = OpFunctionParameter %[[#IMAGE_TYPE]] diff --git a/llvm/test/CodeGen/SPIRV/transcoding/cl-types.ll b/llvm/test/CodeGen/SPIRV/transcoding/cl-types.ll index 52b7dac8866f695fd483f90b4fef50ad8f890df1..d7e87c05340d14f72e630f1a190807c4ebce1beb 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/cl-types.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/cl-types.ll @@ -19,6 +19,7 @@ ;; } ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV-DAG: OpCapability Sampled1D ; CHECK-SPIRV-DAG: OpCapability SampledBuffer diff --git a/llvm/test/CodeGen/SPIRV/transcoding/clk_event_t.ll b/llvm/test/CodeGen/SPIRV/transcoding/clk_event_t.ll index 9054454879cc26f8e03579ae3b9a77f4593394ec..0cd75bb215ada2e41cdf7d1532ee8daa646aa35f 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/clk_event_t.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/clk_event_t.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpTypeDeviceEvent ; CHECK-SPIRV: OpFunction diff --git a/llvm/test/CodeGen/SPIRV/transcoding/enqueue_kernel.ll b/llvm/test/CodeGen/SPIRV/transcoding/enqueue_kernel.ll index cf124ec0a2782e5ac6c15352e645e3ccf01c5ef1..d23b0687face59b53346101c897900fe028f2e60 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/enqueue_kernel.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/enqueue_kernel.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; TODO(#60133): Requires updates following opaque pointer migration. ; XFAIL: * diff --git a/llvm/test/CodeGen/SPIRV/transcoding/explicit-conversions.ll b/llvm/test/CodeGen/SPIRV/transcoding/explicit-conversions.ll index c186a8135fee7cf112aaa425724a43d5fda93d5b..49b84c1e9530a50744ca68ac3fcf72f5ac40ae4c 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/explicit-conversions.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/explicit-conversions.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpSatConvertSToU diff --git a/llvm/test/CodeGen/SPIRV/transcoding/extract_insert_value.ll b/llvm/test/CodeGen/SPIRV/transcoding/extract_insert_value.ll index fd29bc8a1ebf89de76bea6b48aede7a8e888c28e..0ed1dc76628ca013758b02d7ad7be08a5637ab3f 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/extract_insert_value.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/extract_insert_value.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; TODO(#60133): Requires updates following opaque pointer migration. ; XFAIL: * diff --git a/llvm/test/CodeGen/SPIRV/transcoding/fadd.ll b/llvm/test/CodeGen/SPIRV/transcoding/fadd.ll index 78d9a23266558542496b196055152413d9a5f42c..af76c0e96f9f49c49f73c54309f2b5118b3da15a 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/fadd.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/fadd.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpName %[[#r1:]] "r1" ; CHECK-SPIRV: OpName %[[#r2:]] "r2" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/fclamp.ll b/llvm/test/CodeGen/SPIRV/transcoding/fclamp.ll index cfdcc728fbe43ad638ed4f7166c0e19282943ff6..550ec1a6f25507a7ec57a2ae6f0ccce4533ebd99 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/fclamp.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/fclamp.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: %[[#]] = OpExtInst %[[#]] %[[#]] fclamp ; CHECK-SPIRV-NOT: %[[#]] = OpExtInst %[[#]] %[[#]] clamp diff --git a/llvm/test/CodeGen/SPIRV/transcoding/fcmp.ll b/llvm/test/CodeGen/SPIRV/transcoding/fcmp.ll index 572ccc3ed625d27875f15e07dd7b73b778a9f1c4..46eaba9d5ceb1e0240a4c357d061c74aeaf3601b 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/fcmp.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/fcmp.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpName %[[#r1:]] "r1" ; CHECK-SPIRV: OpName %[[#r2:]] "r2" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/fdiv.ll b/llvm/test/CodeGen/SPIRV/transcoding/fdiv.ll index d0ed5640e7066dc47c507b76c675d69fb379a447..79b786814c716e858c6f37de028dc3726ed3c84b 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/fdiv.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/fdiv.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpName %[[#r1:]] "r1" ; CHECK-SPIRV: OpName %[[#r2:]] "r2" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/fmod.ll b/llvm/test/CodeGen/SPIRV/transcoding/fmod.ll index f506787bcb9ce6cb960c69e9499b223198c6a9d2..683b5c24f5b712ea3a77d126dfea258e4ac658fa 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/fmod.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/fmod.ll @@ -2,6 +2,7 @@ ;; { out = fmod( in1, in2 ); } ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: %[[#]] = OpExtInst %[[#]] %[[#]] fmod %[[#]] %[[#]] diff --git a/llvm/test/CodeGen/SPIRV/transcoding/fmul.ll b/llvm/test/CodeGen/SPIRV/transcoding/fmul.ll index 886077a67b4e60fc02e0d839169f22f3a425061e..fdab29c9041cb8868d8afe69360c2b67ae2093bb 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/fmul.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/fmul.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpName %[[#r1:]] "r1" ; CHECK-SPIRV: OpName %[[#r2:]] "r2" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/fneg.ll b/llvm/test/CodeGen/SPIRV/transcoding/fneg.ll index e17601a2c25a7c6ee1443851de5a93018bec8fe5..60bbfe6b7f3931ac9123779288ae348726bdb631 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/fneg.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/fneg.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpName %[[#r1:]] "r1" ; CHECK-SPIRV: OpName %[[#r2:]] "r2" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/fp_contract_reassoc_fast_mode.ll b/llvm/test/CodeGen/SPIRV/transcoding/fp_contract_reassoc_fast_mode.ll index c035c35a339ee9ae1feb8246345e73020a1642ac..974043c11991f7ba90f101ad6b6dbeb762219780 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/fp_contract_reassoc_fast_mode.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/fp_contract_reassoc_fast_mode.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV-NOT: OpCapability FPFastMathModeINTEL ; CHECK-SPIRV: OpName %[[#mu:]] "mul" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/frem.ll b/llvm/test/CodeGen/SPIRV/transcoding/frem.ll index ecb8f6f950cabf36c7c45bd6b0136fbede3e0911..d36ba7f70e453d99ff862c28c4336d27bd7cc48f 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/frem.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/frem.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpName %[[#r1:]] "r1" ; CHECK-SPIRV: OpName %[[#r2:]] "r2" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/fsub.ll b/llvm/test/CodeGen/SPIRV/transcoding/fsub.ll index 99d0d0eb84f95f6983afac30f5c0f4f1bdaf9c8a..3677c00405626fdf2610e6a96d6d753a4b1170cf 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/fsub.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/fsub.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV: OpName %[[#r1:]] "r1" ; CHECK-SPIRV: OpName %[[#r2:]] "r2" diff --git a/llvm/test/CodeGen/SPIRV/transcoding/get_image_num_mip_levels.ll b/llvm/test/CodeGen/SPIRV/transcoding/get_image_num_mip_levels.ll index dc307c70612eba095aa8bbaf055402ca30502bda..fd241963d1e98d697327a369d5a2a9b086df3b51 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/get_image_num_mip_levels.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/get_image_num_mip_levels.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; Types: ; CHECK-DAG: %[[#INT:]] = OpTypeInt 32 diff --git a/llvm/test/CodeGen/SPIRV/transcoding/global_block.ll b/llvm/test/CodeGen/SPIRV/transcoding/global_block.ll index 2f44e1943b6a6da50197b35410bad94ee90be40e..ff1bec4497ba2ae4738fcb7406291f9779a795a0 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/global_block.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/global_block.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefixes=CHECK-SPIRV,CHECK-SPIRV1_4 +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; TODO(#60133): Requires updates following opaque pointer migration. ; XFAIL: * diff --git a/llvm/test/CodeGen/SPIRV/transcoding/group_ops.ll b/llvm/test/CodeGen/SPIRV/transcoding/group_ops.ll index 6aa9faa6c893e998c80d2cab000d7452850df6ca..2412f406a9c62ed69b3ecf77e4a60e5b6728a82d 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/group_ops.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/group_ops.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV-DAG: %[[#int:]] = OpTypeInt 32 0 ; CHECK-SPIRV-DAG: %[[#float:]] = OpTypeFloat 32 diff --git a/llvm/test/CodeGen/SPIRV/transcoding/isequal.ll b/llvm/test/CodeGen/SPIRV/transcoding/isequal.ll index 3c818afcdb16701fe78bb79e13a0102543e1e728..c5f3f9e1e2e74c2dc95457869659ff961a3205ca 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/isequal.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/isequal.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %} ; CHECK-SPIRV-NOT: OpSConvert diff --git a/llvm/test/CodeGen/SPIRV/transcoding/relationals_double.ll b/llvm/test/CodeGen/SPIRV/transcoding/relationals_double.ll index f771854672ce16275e05f7e35b94962af0f6f065..de7673ad7f17eb85b6b0db01a93a04b1ed7914b7 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/relationals_double.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/relationals_double.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; This test checks following SYCL relational builtins with double and double2 ;; types: diff --git a/llvm/test/CodeGen/SPIRV/transcoding/relationals_float.ll b/llvm/test/CodeGen/SPIRV/transcoding/relationals_float.ll index 1f55cebb0911b2f29d4e72dc035153654edb6092..69a4a30fd65ef33cf68791eceb192a5d5281ee35 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/relationals_float.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/relationals_float.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; This test checks following SYCL relational builtins with float and float2 ;; types: diff --git a/llvm/test/CodeGen/SPIRV/transcoding/relationals_half.ll b/llvm/test/CodeGen/SPIRV/transcoding/relationals_half.ll index 864fb4f29efdc2e95315d3f7dbcf6fbacc4adec2..d6a7fda41afd08f5fcb9f3047f3e7d3668c1643a 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/relationals_half.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/relationals_half.ll @@ -1,4 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV +; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %} ;; This test checks following SYCL relational builtins with half and half2 types: ;; isfinite, isinf, isnan, isnormal, signbit, isequal, isnotequal, isgreater diff --git a/llvm/test/CodeGen/SPIRV/transcoding/spirv-private-array-initialization.ll b/llvm/test/CodeGen/SPIRV/transcoding/spirv-private-array-initialization.ll index 3551030843d062fa1bfb768430ccd8bab5ce9f13..e0172ec3c1bdb781c47c5c2142a5e2f8da9f2c2e 100644 --- a/llvm/test/CodeGen/SPIRV/transcoding/spirv-private-array-initialization.ll +++ b/llvm/test/CodeGen/SPIRV/transcoding/spirv-private-array-initialization.ll @@ -1,6 +1,5 @@ ; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV ; -; CHECK-SPIRV-DAG: %[[#i8:]] = OpTypeInt 8 0 ; CHECK-SPIRV-DAG: %[[#i32:]] = OpTypeInt 32 0 ; CHECK-SPIRV-DAG: %[[#one:]] = OpConstant %[[#i32]] 1 ; CHECK-SPIRV-DAG: %[[#two:]] = OpConstant %[[#i32]] 2 @@ -13,7 +12,6 @@ ; CHECK-SPIRV: %[[#test_arr2:]] = OpVariable %[[#const_i32x3_ptr]] UniformConstant %[[#test_arr_init]] ; CHECK-SPIRV: %[[#test_arr:]] = OpVariable %[[#const_i32x3_ptr]] UniformConstant %[[#test_arr_init]] -; CHECK-SPIRV-DAG: %[[#const_i8_ptr:]] = OpTypePointer UniformConstant %[[#i8]] ; CHECK-SPIRV-DAG: %[[#i32x3_ptr:]] = OpTypePointer Function %[[#i32x3]] ; CHECK-SPIRV: %[[#arr:]] = OpVariable %[[#i32x3_ptr]] Function diff --git a/llvm/test/CodeGen/SystemZ/RAbasic-invalid-LR-update.mir b/llvm/test/CodeGen/SystemZ/RAbasic-invalid-LR-update.mir index 3b308ce3d0d24cab1a10f236c20674344b9bfb93..adeec15b175523a615f4e3edbf8a47cd963b7f3f 100644 --- a/llvm/test/CodeGen/SystemZ/RAbasic-invalid-LR-update.mir +++ b/llvm/test/CodeGen/SystemZ/RAbasic-invalid-LR-update.mir @@ -25,6 +25,8 @@ name: autogen_SD21418 alignment: 4 tracksRegLiveness: true +frameInfo: + adjustsStack: true registers: - { id: 0, class: vr128bit } - { id: 1, class: vr128bit } diff --git a/llvm/test/CodeGen/SystemZ/atomic-load-06.ll b/llvm/test/CodeGen/SystemZ/atomic-load-06.ll index c9c5504520345cd5b09cb516bebc91d07028e81a..60ff780df87b0e4fb594c52f29c6613bd7a46c02 100644 --- a/llvm/test/CodeGen/SystemZ/atomic-load-06.ll +++ b/llvm/test/CodeGen/SystemZ/atomic-load-06.ll @@ -4,9 +4,7 @@ define float @f1(ptr %src) { ; CHECK-LABEL: f1: -; CHECK: lgf [[R:%r[0-9]+]], 0(%r2) -; CHECK: sllg [[R]], [[R]], 32 -; CHECK: ldgr %f0, [[R]] +; CHECK: le %f0, 0(%r2) ; CHECK: br %r14 %val = load atomic float, ptr %src seq_cst, align 4 ret float %val diff --git a/llvm/test/CodeGen/SystemZ/atomic-memops-fp128.ll b/llvm/test/CodeGen/SystemZ/atomic-memops-fp128.ll new file mode 100644 index 0000000000000000000000000000000000000000..8038329c0e09a08bbe744df9f853fa0ec0b1b6ad --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/atomic-memops-fp128.ll @@ -0,0 +1,31 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 | FileCheck %s +; +; Test fpext of atomic loads to fp128 without VectorEnhancements1 (using FP register pairs). + +define fp128 @f1(ptr %src) { +; CHECK-LABEL: f1: +; CHECK: # %bb.0: +; CHECK-NEXT: lxeb %f0, 0(%r3) +; CHECK-NEXT: std %f0, 0(%r2) +; CHECK-NEXT: std %f2, 8(%r2) +; CHECK-NEXT: br %r14 + %V = load atomic float, ptr %src seq_cst, align 4 + %Res = fpext float %V to fp128 + ret fp128 %Res +} + +define fp128 @f2(ptr %src) { +; CHECK-LABEL: f2: +; CHECK: # %bb.0: +; CHECK-NEXT: lxdb %f0, 0(%r3) +; CHECK-NEXT: std %f0, 0(%r2) +; CHECK-NEXT: std %f2, 8(%r2) +; CHECK-NEXT: br %r14 + %V = load atomic double, ptr %src seq_cst, align 8 + %Res = fpext double %V to fp128 + ret fp128 %Res +} + + + diff --git a/llvm/test/CodeGen/SystemZ/atomic-memops.ll b/llvm/test/CodeGen/SystemZ/atomic-memops.ll new file mode 100644 index 0000000000000000000000000000000000000000..0bc647aa0e0f7c1dc180bf2a4fcf7e1987cf6ff4 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/atomic-memops.ll @@ -0,0 +1,739 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z16 | FileCheck %s + +; Sign-extending atomic loads. +define void @f1(ptr %src, ptr %dst) { +; CHECK-LABEL: f1: +; CHECK: # %bb.0: +; CHECK-NEXT: lb %r0, 0(%r2) +; CHECK-NEXT: sth %r0, 0(%r3) +; CHECK-NEXT: br %r14 + %b = load atomic i8, ptr %src seq_cst, align 1 + %s = sext i8 %b to i16 + store volatile i16 %s, ptr %dst + ret void +} + +define void @f2(ptr %src, ptr %dst) { +; CHECK-LABEL: f2: +; CHECK: # %bb.0: +; CHECK-NEXT: lb %r0, 0(%r2) +; CHECK-NEXT: st %r0, 0(%r3) +; CHECK-NEXT: br %r14 + %b = load atomic i8, ptr %src seq_cst, align 1 + %s = sext i8 %b to i32 + store volatile i32 %s, ptr %dst + ret void +} + +define void @f3(ptr %src, ptr %dst) { +; CHECK-LABEL: f3: +; CHECK: # %bb.0: +; CHECK-NEXT: lgb %r0, 0(%r2) +; CHECK-NEXT: stg %r0, 0(%r3) +; CHECK-NEXT: br %r14 + %b = load atomic i8, ptr %src seq_cst, align 1 + %s = sext i8 %b to i64 + store volatile i64 %s, ptr %dst + ret void +} + +define void @f4(ptr %src, ptr %dst) { +; CHECK-LABEL: f4: +; CHECK: # %bb.0: +; CHECK-NEXT: lh %r0, 0(%r2) +; CHECK-NEXT: st %r0, 0(%r3) +; CHECK-NEXT: br %r14 + %b = load atomic i16, ptr %src seq_cst, align 2 + %s = sext i16 %b to i32 + store volatile i32 %s, ptr %dst + ret void +} + +define void @f5(ptr %src, ptr %dst) { +; CHECK-LABEL: f5: +; CHECK: # %bb.0: +; CHECK-NEXT: lgh %r0, 0(%r2) +; CHECK-NEXT: stg %r0, 0(%r3) +; CHECK-NEXT: br %r14 + %b = load atomic i16, ptr %src seq_cst, align 2 + %s = sext i16 %b to i64 + store volatile i64 %s, ptr %dst + ret void +} + +define void @f6(ptr %src, ptr %dst) { +; CHECK-LABEL: f6: +; CHECK: # %bb.0: +; CHECK-NEXT: lgf %r0, 0(%r2) +; CHECK-NEXT: stg %r0, 0(%r3) +; CHECK-NEXT: br %r14 + %b = load atomic i32, ptr %src seq_cst, align 4 + %s = sext i32 %b to i64 + store volatile i64 %s, ptr %dst + ret void +} + +; Zero-extending atomic loads. +define void @f7(ptr %src, ptr %dst) { +; CHECK-LABEL: f7: +; CHECK: # %bb.0: +; CHECK-NEXT: llc %r0, 0(%r2) +; CHECK-NEXT: sth %r0, 0(%r3) +; CHECK-NEXT: br %r14 + %b = load atomic i8, ptr %src seq_cst, align 1 + %z = zext i8 %b to i16 + store volatile i16 %z, ptr %dst + ret void +} + +define void @f8(ptr %src, ptr %dst) { +; CHECK-LABEL: f8: +; CHECK: # %bb.0: +; CHECK-NEXT: llc %r0, 0(%r2) +; CHECK-NEXT: st %r0, 0(%r3) +; CHECK-NEXT: br %r14 + %b = load atomic i8, ptr %src seq_cst, align 1 + %z = zext i8 %b to i32 + store volatile i32 %z, ptr %dst + ret void +} + +define void @f9(ptr %src, ptr %dst) { +; CHECK-LABEL: f9: +; CHECK: # %bb.0: +; CHECK-NEXT: llgc %r0, 0(%r2) +; CHECK-NEXT: stg %r0, 0(%r3) +; CHECK-NEXT: br %r14 + %b = load atomic i8, ptr %src seq_cst, align 1 + %z = zext i8 %b to i64 + store volatile i64 %z, ptr %dst + ret void +} + +define void @f10(ptr %src, ptr %dst) { +; CHECK-LABEL: f10: +; CHECK: # %bb.0: +; CHECK-NEXT: llh %r0, 0(%r2) +; CHECK-NEXT: st %r0, 0(%r3) +; CHECK-NEXT: br %r14 + %b = load atomic i16, ptr %src seq_cst, align 2 + %z = zext i16 %b to i32 + store volatile i32 %z, ptr %dst + ret void +} + +define void @f11(ptr %src, ptr %dst) { +; CHECK-LABEL: f11: +; CHECK: # %bb.0: +; CHECK-NEXT: llgh %r0, 0(%r2) +; CHECK-NEXT: stg %r0, 0(%r3) +; CHECK-NEXT: br %r14 + %b = load atomic i16, ptr %src seq_cst, align 2 + %z = zext i16 %b to i64 + store volatile i64 %z, ptr %dst + ret void +} + +define void @f12(ptr %src, ptr %dst) { +; CHECK-LABEL: f12: +; CHECK: # %bb.0: +; CHECK-NEXT: llgf %r0, 0(%r2) +; CHECK-NEXT: stg %r0, 0(%r3) +; CHECK-NEXT: br %r14 + %b = load atomic i32, ptr %src seq_cst, align 4 + %z = zext i32 %b to i64 + store volatile i64 %z, ptr %dst + ret void +} + +; reg/mem +define i64 @f13(i64 %a, ptr %src) { +; CHECK-LABEL: f13: +; CHECK: # %bb.0: +; CHECK-NEXT: ag %r2, 0(%r3) +; CHECK-NEXT: br %r14 + %b = load atomic i64, ptr %src seq_cst, align 8 + %add = add i64 %a, %b + ret i64 %add +} + +; reg/mem op with extension from memory. +define i64 @f14(i64 %a, ptr %src) { +; CHECK-LABEL: f14: +; CHECK: # %bb.0: +; CHECK-NEXT: slgf %r2, 0(%r3) +; CHECK-NEXT: br %r14 + %b = load atomic i32, ptr %src seq_cst, align 4 + %bext = zext i32 %b to i64 + %sub = sub i64 %a, %bext + ret i64 %sub +} + +define float @f15(float %f1, ptr %ptr, float %acc) { +; CHECK-LABEL: f15: +; CHECK: # %bb.0: +; CHECK-NEXT: maeb %f2, %f0, 0(%r2) +; CHECK-NEXT: ldr %f0, %f2 +; CHECK-NEXT: br %r14 + %f2 = load atomic float, ptr %ptr seq_cst, align 4 + %res = call float @llvm.fma.f32 (float %f1, float %f2, float %acc) + ret float %res +} +declare float @llvm.fma.f32(float %f1, float %f2, float %f3) + +define double @f15_b(ptr %src) { +; CHECK-LABEL: f15_b: +; CHECK: # %bb.0: +; CHECK-NEXT: ldeb %f0, 0(%r2) +; CHECK-NEXT: br %r14 + %V = load atomic float, ptr %src seq_cst, align 4 + %Res = fpext float %V to double + ret double %Res +} + +define fp128 @f15_c(ptr %src) { +; CHECK-LABEL: f15_c: +; CHECK: # %bb.0: +; CHECK-NEXT: lde %f0, 0(%r3) +; CHECK-NEXT: ldebr %f0, %f0 +; CHECK-NEXT: wflld %v0, %f0 +; CHECK-NEXT: vst %v0, 0(%r2), 3 +; CHECK-NEXT: br %r14 + %V = load atomic float, ptr %src seq_cst, align 4 + %Res = fpext float %V to fp128 + ret fp128 %Res +} + +define fp128 @f15_d(ptr %src) { +; CHECK-LABEL: f15_d: +; CHECK: # %bb.0: +; CHECK-NEXT: ld %f0, 0(%r3) +; CHECK-NEXT: wflld %v0, %f0 +; CHECK-NEXT: vst %v0, 0(%r2), 3 +; CHECK-NEXT: br %r14 + %V = load atomic double, ptr %src seq_cst, align 8 + %Res = fpext double %V to fp128 + ret fp128 %Res +} + +; Do it twice for good measure given the involved DAG combines. +define void @f16(ptr %src, ptr %dst) { +; CHECK-LABEL: f16: +; CHECK: # %bb.0: +; CHECK-NEXT: llgc %r0, 0(%r2) +; CHECK-NEXT: lgbr %r1, %r0 +; CHECK-NEXT: stg %r1, 0(%r3) +; CHECK-NEXT: stg %r0, 0(%r3) +; CHECK-NEXT: llgc %r0, 0(%r2) +; CHECK-NEXT: lgbr %r1, %r0 +; CHECK-NEXT: stg %r1, 0(%r3) +; CHECK-NEXT: stg %r0, 0(%r3) +; CHECK-NEXT: br %r14 + %b = load atomic i8, ptr %src seq_cst, align 1 + %s = sext i8 %b to i64 + %z = zext i8 %b to i64 + store volatile i64 %s, ptr %dst + store volatile i64 %z, ptr %dst + + %b2 = load atomic i8, ptr %src seq_cst, align 1 + %s2 = sext i8 %b2 to i64 + %z2 = zext i8 %b2 to i64 + store volatile i64 %s2, ptr %dst + store volatile i64 %z2, ptr %dst + + ret void +} + +define void @f16_b(ptr %src, ptr %dst) { +; CHECK-LABEL: f16_b: +; CHECK: # %bb.0: +; CHECK-NEXT: lgb %r0, 0(%r2) +; CHECK-NEXT: sth %r0, 0(%r3) +; CHECK-NEXT: stg %r0, 0(%r3) +; CHECK-NEXT: br %r14 + %b = load atomic i8, ptr %src seq_cst, align 1 + %s = sext i8 %b to i16 + store volatile i16 %s, ptr %dst + + %s2 = sext i8 %b to i64 + store volatile i64 %s2, ptr %dst + + ret void +} + +define void @f16_c(ptr %src, ptr %dst) { +; CHECK-LABEL: f16_c: +; CHECK: # %bb.0: +; CHECK-NEXT: llgc %r0, 0(%r2) +; CHECK-NEXT: sth %r0, 0(%r3) +; CHECK-NEXT: stg %r0, 0(%r3) +; CHECK-NEXT: br %r14 + %b = load atomic i8, ptr %src seq_cst, align 1 + %z = zext i8 %b to i16 + store volatile i16 %z, ptr %dst + + %z2 = zext i8 %b to i64 + store volatile i64 %z2, ptr %dst + + ret void +} + +; Check that two i8 loads use a reg/reg op. +define i8 @f16_d(ptr %src, ptr %src2) { +; CHECK-LABEL: f16_d: +; CHECK: # %bb.0: +; CHECK-NEXT: lb %r2, 0(%r2) +; CHECK-NEXT: lb %r0, 0(%r3) +; CHECK-NEXT: ar %r2, %r0 +; CHECK-NEXT: br %r14 + %b = load atomic i8, ptr %src seq_cst, align 1 + %b2 = load atomic i8, ptr %src2 seq_cst, align 1 + %add = add i8 %b, %b2 + ret i8 %add +} + +; Binary operations on a byte in memory, with an atomic load. +define void @f17(ptr %ptr) { +; CHECK-LABEL: f17: +; CHECK: # %bb.0: +; CHECK-NEXT: ni 0(%r2), 1 +; CHECK-NEXT: br %r14 + %val = load atomic i8, ptr %ptr seq_cst, align 1 + %xor = and i8 %val, -255 + store i8 %xor, ptr %ptr + ret void +} + +define void @f18(ptr %src) { +; CHECK-LABEL: f18: +; CHECK: # %bb.0: +; CHECK-NEXT: oiy 4096(%r2), 1 +; CHECK-NEXT: br %r14 + %ptr = getelementptr i8, ptr %src, i64 4096 + %val = load atomic i8, ptr %ptr seq_cst, align 1 + %xor = or i8 %val, -255 + store i8 %xor, ptr %ptr + ret void +} + +define void @f19(ptr %src) { +; CHECK-LABEL: f19: +; CHECK: # %bb.0: +; CHECK-NEXT: xi 4095(%r2), 1 +; CHECK-NEXT: br %r14 + %ptr = getelementptr i8, ptr %src, i64 4095 + %val = load atomic i8, ptr %ptr seq_cst, align 1 + %xor = xor i8 %val, -255 + store i8 %xor, ptr %ptr + ret void +} + +; TM +define double @f20(ptr %src, double %a, double %b) { +; CHECK-LABEL: f20: +; CHECK: # %bb.0: +; CHECK-NEXT: tm 0(%r2), 1 +; CHECK-NEXT: je .LBB25_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: ldr %f2, %f0 +; CHECK-NEXT: .LBB25_2: +; CHECK-NEXT: ldr %f0, %f2 +; CHECK-NEXT: br %r14 + %byte = load atomic i8, ptr %src seq_cst, align 1 + %and = and i8 %byte, 1 + %cmp = icmp eq i8 %and, 0 + %res = select i1 %cmp, double %b, double %a + ret double %res +} + +; vector load and replicate +define void @f21(ptr %src, ptr %dst) { +; CHECK-LABEL: f21: +; CHECK: # %bb.0: +; CHECK-NEXT: vlrepb %v0, 0(%r2) +; CHECK-NEXT: vst %v0, 0(%r3), 3 +; CHECK-NEXT: br %r14 + %b = load atomic i8, ptr %src seq_cst, align 1 + %v = insertelement <16 x i8> undef, i8 %b, i32 1 + store volatile <16 x i8> %v, ptr %dst + ret void +} + +define void @f22(ptr %src, ptr %dst) { +; CHECK-LABEL: f22: +; CHECK: # %bb.0: +; CHECK-NEXT: vlreph %v0, 0(%r2) +; CHECK-NEXT: vst %v0, 0(%r3), 3 +; CHECK-NEXT: br %r14 + %b = load atomic i16, ptr %src seq_cst, align 2 + %v = insertelement <8 x i16> undef, i16 %b, i32 1 + store volatile <8 x i16> %v, ptr %dst + ret void +} + +define void @f23(ptr %src, ptr %dst) { +; CHECK-LABEL: f23: +; CHECK: # %bb.0: +; CHECK-NEXT: vlrepf %v0, 0(%r2) +; CHECK-NEXT: vst %v0, 0(%r3), 3 +; CHECK-NEXT: br %r14 + %b = load atomic i32, ptr %src seq_cst, align 4 + %v = insertelement <4 x i32> undef, i32 %b, i32 2 + store volatile <4 x i32> %v, ptr %dst + ret void +} + +define void @f24(ptr %src, ptr %dst) { +; CHECK-LABEL: f24: +; CHECK: # %bb.0: +; CHECK-NEXT: vlrepg %v0, 0(%r2) +; CHECK-NEXT: vst %v0, 0(%r3), 3 +; CHECK-NEXT: br %r14 + %b = load atomic i64, ptr %src seq_cst, align 8 + %v = insertelement <2 x i64> undef, i64 %b, i32 0 + store volatile <2 x i64> %v, ptr %dst + ret void +} + +define void @f25(ptr %src, ptr %dst) { +; CHECK-LABEL: f25: +; CHECK: # %bb.0: +; CHECK-NEXT: vlrepf %v0, 0(%r2) +; CHECK-NEXT: vst %v0, 0(%r3), 3 +; CHECK-NEXT: br %r14 + %b = load atomic float, ptr %src seq_cst, align 4 + %v = insertelement <4 x float> undef, float %b, i32 1 + store volatile <4 x float> %v, ptr %dst + ret void +} + +; Do *not* use vlrep for an extending load. +define <4 x i32> @f25_c(ptr %ptr) { +; CHECK-LABEL: f25_c: +; CHECK: # %bb.0: +; CHECK-NEXT: lb %r0, 0(%r2) +; CHECK-NEXT: vlvgp %v0, %r0, %r0 +; CHECK-NEXT: vrepf %v24, %v0, 1 +; CHECK-NEXT: br %r14 + %L = load atomic i8, ptr %ptr seq_cst, align 4 + %S = sext i8 %L to i32 + %val = insertelement <4 x i32> undef, i32 %S, i32 0 + %ret = shufflevector <4 x i32> %val, <4 x i32> undef, + <4 x i32> zeroinitializer + ret <4 x i32> %ret +} + +; Do *not* use vlrep if there is another scalar use. +define <4 x i32> @f25_d(ptr %ptr, ptr %dst) { +; CHECK-LABEL: f25_d: +; CHECK: # %bb.0: +; CHECK-NEXT: l %r0, 0(%r2) +; CHECK-NEXT: vlvgp %v0, %r0, %r0 +; CHECK-NEXT: vrepf %v24, %v0, 1 +; CHECK-NEXT: st %r0, 0(%r3) +; CHECK-NEXT: br %r14 + %L = load atomic i32, ptr %ptr seq_cst, align 4 + store i32 %L, ptr %dst, align 4 + %val = insertelement <4 x i32> undef, i32 %L, i32 0 + %ret = shufflevector <4 x i32> %val, <4 x i32> undef, + <4 x i32> zeroinitializer + ret <4 x i32> %ret +} + +define void @f26(ptr %src, ptr %dst) { +; CHECK-LABEL: f26: +; CHECK: # %bb.0: +; CHECK-NEXT: vlrepg %v0, 0(%r2) +; CHECK-NEXT: vst %v0, 0(%r3), 3 +; CHECK-NEXT: br %r14 + %b = load atomic double, ptr %src seq_cst, align 8 + %v = insertelement <2 x double> undef, double %b, i32 0 + store volatile <2 x double> %v, ptr %dst + ret void +} + +; Vector Load logical element and zero. +define <16 x i8> @f27(ptr %ptr) { +; CHECK-LABEL: f27: +; CHECK: # %bb.0: +; CHECK-NEXT: vllezb %v24, 0(%r2) +; CHECK-NEXT: br %r14 + %val = load atomic i8, ptr %ptr seq_cst, align 1 + %ret = insertelement <16 x i8> zeroinitializer, i8 %val, i32 7 + ret <16 x i8> %ret +} + +define <8 x i16> @f28(ptr %ptr) { +; CHECK-LABEL: f28: +; CHECK: # %bb.0: +; CHECK-NEXT: vllezh %v24, 0(%r2) +; CHECK-NEXT: br %r14 + %val = load atomic i16, ptr %ptr seq_cst, align 2 + %ret = insertelement <8 x i16> zeroinitializer, i16 %val, i32 3 + ret <8 x i16> %ret +} + +define <4 x i32> @f29(ptr %ptr) { +; CHECK-LABEL: f29: +; CHECK: # %bb.0: +; CHECK-NEXT: vllezf %v24, 0(%r2) +; CHECK-NEXT: br %r14 + %val = load atomic i32, ptr %ptr seq_cst, align 4 + %ret = insertelement <4 x i32> zeroinitializer, i32 %val, i32 1 + ret <4 x i32> %ret +} + +define <2 x i64> @f30(ptr %ptr) { +; CHECK-LABEL: f30: +; CHECK: # %bb.0: +; CHECK-NEXT: vllezg %v24, 0(%r2) +; CHECK-NEXT: br %r14 + %val = load atomic i64, ptr %ptr seq_cst, align 8 + %ret = insertelement <2 x i64> zeroinitializer, i64 %val, i32 0 + ret <2 x i64> %ret +} + +define <4 x i32> @f31(ptr %ptr) { +; CHECK-LABEL: f31: +; CHECK: # %bb.0: +; CHECK-NEXT: vllezlf %v24, 0(%r2) +; CHECK-NEXT: br %r14 + %val = load atomic i32, ptr %ptr seq_cst, align 4 + %ret = insertelement <4 x i32> zeroinitializer, i32 %val, i32 0 + ret <4 x i32> %ret +} + +define <4 x float> @f32(ptr %ptr) { +; CHECK-LABEL: f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vllezlf %v24, 0(%r2) +; CHECK-NEXT: br %r14 + %val = load atomic float, ptr %ptr seq_cst, align 4 + %ret = insertelement <4 x float> zeroinitializer, float %val, i32 0 + ret <4 x float> %ret +} + +; Vector Load element. +define <16 x i8> @f33(<16 x i8> %val, ptr %ptr) { +; CHECK-LABEL: f33: +; CHECK: # %bb.0: +; CHECK-NEXT: vleb %v24, 0(%r2), 0 +; CHECK-NEXT: br %r14 + %element = load atomic i8, ptr %ptr seq_cst, align 1 + %ret = insertelement <16 x i8> %val, i8 %element, i32 0 + ret <16 x i8> %ret +} + +define <8 x i16> @f34(<8 x i16> %val, ptr %ptr) { +; CHECK-LABEL: f34: +; CHECK: # %bb.0: +; CHECK-NEXT: vleh %v24, 0(%r2), 0 +; CHECK-NEXT: br %r14 + %element = load atomic i16, ptr %ptr seq_cst, align 2 + %ret = insertelement <8 x i16> %val, i16 %element, i32 0 + ret <8 x i16> %ret +} + +define <4 x i32> @f35(<4 x i32> %val, ptr %ptr) { +; CHECK-LABEL: f35: +; CHECK: # %bb.0: +; CHECK-NEXT: vlef %v24, 0(%r2), 0 +; CHECK-NEXT: br %r14 + %element = load atomic i32, ptr %ptr seq_cst, align 4 + %ret = insertelement <4 x i32> %val, i32 %element, i32 0 + ret <4 x i32> %ret +} + +define <2 x i64> @f36(<2 x i64> %val, ptr %ptr) { +; CHECK-LABEL: f36: +; CHECK: # %bb.0: +; CHECK-NEXT: vleg %v24, 0(%r2), 0 +; CHECK-NEXT: br %r14 + %element = load atomic i64, ptr %ptr seq_cst, align 8 + %ret = insertelement <2 x i64> %val, i64 %element, i32 0 + ret <2 x i64> %ret +} + +; Test operation on memory involving atomic load and store. +define void @f39(ptr %ptr) { +; CHECK-LABEL: f39: +; CHECK: # %bb.0: +; CHECK-NEXT: oi 0(%r2), 1 +; CHECK-NEXT: bcr 14, %r0 +; CHECK-NEXT: br %r14 + %val = load atomic i8, ptr %ptr seq_cst, align 1 + %or = or i8 %val, -255 + store atomic i8 %or, ptr %ptr seq_cst, align 1 + ret void +} + +; Some atomic stores of immediates. +define void @f40(ptr %ptr) { +; CHECK-LABEL: f40: +; CHECK: # %bb.0: +; CHECK-NEXT: mvi 0(%r2), 128 +; CHECK-NEXT: bcr 14, %r0 +; CHECK-NEXT: br %r14 + store atomic i8 128, ptr %ptr seq_cst, align 1 + ret void +} + +define void @f41(ptr %ptr) { +; CHECK-LABEL: f41: +; CHECK: # %bb.0: +; CHECK-NEXT: mvhi 0(%r2), -1 +; CHECK-NEXT: bcr 14, %r0 +; CHECK-NEXT: br %r14 + store atomic i32 4294967295, ptr %ptr seq_cst, align 4 + ret void +} + +define void @f42(ptr %ptr) { +; CHECK-LABEL: f42: +; CHECK: # %bb.0: +; CHECK-NEXT: mvhi 0(%r2), -1 +; CHECK-NEXT: bcr 14, %r0 +; CHECK-NEXT: br %r14 + store atomic i32 4294967295, ptr %ptr seq_cst, align 4 + ret void +} + +define void @f43(ptr %ptr) { +; CHECK-LABEL: f43: +; CHECK: # %bb.0: +; CHECK-NEXT: llihl %r0, 255 +; CHECK-NEXT: oilf %r0, 4294967295 +; CHECK-NEXT: stg %r0, 0(%r2) +; CHECK-NEXT: bcr 14, %r0 +; CHECK-NEXT: br %r14 + store atomic i64 1099511627775, ptr %ptr seq_cst, align 8 + ret void +} + +define void @f44(ptr %ptr) { +; CHECK-LABEL: f44: +; CHECK: # %bb.0: +; CHECK-NEXT: larl %r1, .LCPI49_0 +; CHECK-NEXT: ld %f0, 0(%r1) +; CHECK-NEXT: std %f0, 0(%r2) +; CHECK-NEXT: bcr 14, %r0 +; CHECK-NEXT: br %r14 + store atomic double 0x3ff0000020000000, ptr %ptr seq_cst, align 8 + ret void +} + +; Vector Store Element. +define void @f45(<16 x i8> %val, ptr %ptr) { +; CHECK-LABEL: f45: +; CHECK: # %bb.0: +; CHECK-NEXT: vsteb %v24, 0(%r2), 0 +; CHECK-NEXT: bcr 14, %r0 +; CHECK-NEXT: br %r14 + %element = extractelement <16 x i8> %val, i32 0 + store atomic i8 %element, ptr %ptr seq_cst, align 1 + ret void +} + +define void @f46(<8 x i16> %val, ptr %base) { +; CHECK-LABEL: f46: +; CHECK: # %bb.0: +; CHECK-NEXT: vsteh %v24, 4094(%r2), 5 +; CHECK-NEXT: bcr 14, %r0 +; CHECK-NEXT: br %r14 + %ptr = getelementptr i16, ptr %base, i32 2047 + %element = extractelement <8 x i16> %val, i32 5 + store atomic i16 %element, ptr %ptr seq_cst, align 2 + ret void +} + +define void @f47(<4 x i32> %val, ptr %ptr) { +; CHECK-LABEL: f47: +; CHECK: # %bb.0: +; CHECK-NEXT: vstef %v24, 0(%r2), 3 +; CHECK-NEXT: bcr 14, %r0 +; CHECK-NEXT: br %r14 + %element = extractelement <4 x i32> %val, i32 3 + store atomic i32 %element, ptr %ptr seq_cst, align 4 + ret void +} + +define void @f48(<2 x i64> %val, ptr %ptr) { +; CHECK-LABEL: f48: +; CHECK: # %bb.0: +; CHECK-NEXT: vsteg %v24, 0(%r2), 1 +; CHECK-NEXT: bcr 14, %r0 +; CHECK-NEXT: br %r14 + %element = extractelement <2 x i64> %val, i32 1 + store atomic i64 %element, ptr %ptr seq_cst, align 8 + ret void +} + +define void @f49(<4 x float> %val, ptr %ptr) { +; CHECK-LABEL: f49: +; CHECK: # %bb.0: +; CHECK-NEXT: vstef %v24, 0(%r2), 0 +; CHECK-NEXT: bcr 14, %r0 +; CHECK-NEXT: br %r14 + %element = extractelement <4 x float> %val, i32 0 + store atomic float %element, ptr %ptr seq_cst, align 4 + ret void +} + +define void @f50(<2 x double> %val, ptr %ptr) { +; CHECK-LABEL: f50: +; CHECK: # %bb.0: +; CHECK-NEXT: vsteg %v24, 0(%r2), 1 +; CHECK-NEXT: bcr 14, %r0 +; CHECK-NEXT: br %r14 + %element = extractelement <2 x double> %val, i32 1 + store atomic double %element, ptr %ptr seq_cst, align 8 + ret void +} + +define void @f51(ptr %src, ptr %dst) { +; CHECK-LABEL: f51: +; CHECK: # %bb.0: +; CHECK-NEXT: lpq %r0, 0(%r2) +; CHECK-NEXT: vlvgp %v0, %r0, %r1 +; CHECK-NEXT: vgmf %v1, 2, 8 +; CHECK-NEXT: aebr %f0, %f1 +; CHECK-NEXT: ste %f0, 0(%r3) +; CHECK-NEXT: bcr 14, %r0 +; CHECK-NEXT: br %r14 + %atomic-load = load atomic i128, ptr %src seq_cst, align 16 + %b0 = bitcast i128 %atomic-load to <4 x float> + %vecext = extractelement <4 x float> %b0, i64 0 + %add = fadd float %vecext, 1.000000e+00 + store atomic float %add, ptr %dst seq_cst, align 4 + ret void +} + +define void @f52(ptr %src, ptr %dst) { +; CHECK-LABEL: f52: +; CHECK: # %bb.0: +; CHECK-NEXT: lpq %r0, 0(%r2) +; CHECK-NEXT: vlvgp %v0, %r0, %r1 +; CHECK-NEXT: vgmg %v1, 2, 11 +; CHECK-NEXT: adbr %f0, %f1 +; CHECK-NEXT: std %f0, 0(%r3) +; CHECK-NEXT: bcr 14, %r0 +; CHECK-NEXT: br %r14 + %atomic-load = load atomic i128, ptr %src seq_cst, align 16 + %b0 = bitcast i128 %atomic-load to <2 x double> + %vecext = extractelement <2 x double> %b0, i64 0 + %add = fadd double %vecext, 1.000000e+00 + store atomic double %add, ptr %dst seq_cst, align 8 + ret void +} + +define void @fun58(ptr %ptr, i64 %arg) { +; CHECK-LABEL: fun58: +; CHECK: # %bb.0: +; CHECK-NEXT: st %r3, 0(%r2) +; CHECK-NEXT: bcr 14, %r0 +; CHECK-NEXT: br %r14 + %res = trunc i64 %arg to i32 + store atomic i32 %res, ptr %ptr seq_cst, align 4 + ret void +} diff --git a/llvm/test/CodeGen/SystemZ/atomic-store-06.ll b/llvm/test/CodeGen/SystemZ/atomic-store-06.ll index b748bfc767a4db3387bd32b6f5019398bada998f..91e324b0af1a972f89ef1ba79db3ef21ce8362b1 100644 --- a/llvm/test/CodeGen/SystemZ/atomic-store-06.ll +++ b/llvm/test/CodeGen/SystemZ/atomic-store-06.ll @@ -6,10 +6,7 @@ define void @f1(ptr %src, float %val) { ; CHECK-LABEL: f1: ; CHECK: # %bb.0: -; CHECK-NEXT: # kill: def $f0s killed $f0s def $f0d -; CHECK-NEXT: lgdr %r0, %f0 -; CHECK-NEXT: srlg %r0, %r0, 32 -; CHECK-NEXT: st %r0, 0(%r2) +; CHECK-NEXT: ste %f0, 0(%r2) ; CHECK-NEXT: bcr 15, %r0 ; CHECK-NEXT: br %r14 store atomic float %val, ptr %src seq_cst, align 4 diff --git a/llvm/test/CodeGen/SystemZ/call-zos-01.ll b/llvm/test/CodeGen/SystemZ/call-zos-01.ll index 77776861186ba4b27670999a7114294a037cd4c3..fc7a85caa37eb0e3083874d81bf5c0edb02cc171 100644 --- a/llvm/test/CodeGen/SystemZ/call-zos-01.ll +++ b/llvm/test/CodeGen/SystemZ/call-zos-01.ll @@ -104,7 +104,7 @@ entry: } ; CHECK-LABEL: call_double: -; CHECK: larl [[GENREG:[0-9]+]], @{{CPI[0-9]+_[0-9]+}} +; CHECK: larl [[GENREG:[0-9]+]], L#{{CPI[0-9]+_[0-9]+}} ; CHECK-NEXT: ld 0, 0([[GENREG]]) define double @call_double() { entry: @@ -113,7 +113,7 @@ entry: } ; CHECK-LABEL: call_longdouble: -; CHECK: larl [[GENREG:[0-9]+]], @{{CPI[0-9]+_[0-9]+}} +; CHECK: larl [[GENREG:[0-9]+]], L#{{CPI[0-9]+_[0-9]+}} ; CHECK-NEXT: ld 0, 0([[GENREG]]) ; CHECK-NEXT: ld 2, 8([[GENREG]]) define fp128 @call_longdouble() { @@ -123,7 +123,7 @@ entry: } ; CHECK-LABEL: call_floats0 -; CHECK: larl [[GENREG:[0-9]+]], @{{CPI[0-9]+_[0-9]+}} +; CHECK: larl [[GENREG:[0-9]+]], L#{{CPI[0-9]+_[0-9]+}} ; CHECK-NEXT: ld 1, 0([[GENREG]]) ; CHECK-NEXT: ld 3, 8([[GENREG]]) ; CHECK: lxr 5, 0 @@ -146,7 +146,7 @@ entry: } ; CHECK-LABEL: pass_float: -; CHECK: larl 1, @{{CPI[0-9]+_[0-9]+}} +; CHECK: larl 1, L#{{CPI[0-9]+_[0-9]+}} ; CHECK: aeb 0, 0(1) define float @pass_float(float %arg) { entry: @@ -155,7 +155,7 @@ entry: } ; CHECK-LABEL: pass_double: -; CHECK: larl 1, @{{CPI[0-9]+_[0-9]+}} +; CHECK: larl 1, L#{{CPI[0-9]+_[0-9]+}} ; CHECK: adb 0, 0(1) define double @pass_double(double %arg) { entry: @@ -164,7 +164,7 @@ entry: } ; CHECK-LABEL: pass_longdouble -; CHECK: larl 1, @{{CPI[0-9]+_[0-9]+}} +; CHECK: larl 1, L#{{CPI[0-9]+_[0-9]+}} ; CHECK: lxdb 1, 0(1) ; CHECK: axbr 0, 1 define fp128 @pass_longdouble(fp128 %arg) { @@ -174,7 +174,7 @@ entry: } ; CHECK-LABEL: pass_floats0 -; CHECK: larl 1, @{{CPI[0-9]+_[0-9]+}} +; CHECK: larl 1, L#{{CPI[0-9]+_[0-9]+}} ; CHECK: axbr 0, 4 ; CHECK: axbr 1, 0 ; CHECK: cxbr 1, 5 diff --git a/llvm/test/CodeGen/SystemZ/call-zos-i128.ll b/llvm/test/CodeGen/SystemZ/call-zos-i128.ll index ccdac161d08a9446325793110292e2f475bcd418..775483374a32f381b4d97e77bcf901ba48a1babd 100644 --- a/llvm/test/CodeGen/SystemZ/call-zos-i128.ll +++ b/llvm/test/CodeGen/SystemZ/call-zos-i128.ll @@ -3,10 +3,10 @@ ; RUN: llc < %s -mtriple=s390x-ibm-zos -mcpu=z13 | FileCheck %s ; CHECK-LABEL: call_i128: -; CHECK-DAG: larl 1, @CPI0_0 +; CHECK-DAG: larl 1, L#CPI0_0 ; CHECK-DAG: vl 0, 0(1), 3 ; CHECK-DAG: vst 0, 2256(4), 3 -; CHECK-DAG: larl 1, @CPI0_1 +; CHECK-DAG: larl 1, L#CPI0_1 ; CHECK-DAG: vl 0, 0(1), 3 ; CHECK-DAG: vst 0, 2272(4), 3 ; CHECK-DAG: la 1, 2288(4) diff --git a/llvm/test/CodeGen/SystemZ/call-zos-vararg.ll b/llvm/test/CodeGen/SystemZ/call-zos-vararg.ll index bde59a6be782277b9292f14f8b923763371bebcf..81aedc1a1d7f2d924b2ab8b29ab782ca7ae0d180 100644 --- a/llvm/test/CodeGen/SystemZ/call-zos-vararg.ll +++ b/llvm/test/CodeGen/SystemZ/call-zos-vararg.ll @@ -88,13 +88,15 @@ entry: ret i64 %retval } +;; TODO: The extra COPY after LGDR is unnecessary (machine-scheduler introduces the overlap). ; CHECK-LABEL: call_vararg_both0: ; CHECK: stmg 6, 7, 1872(4) ; CHECK-NEXT: aghi 4, -192 ; CHECK-NEXT: lg 6, 40(5) ; CHECK-NEXT: lg 5, 32(5) +; CHECK-NEXT: lgdr 0, 0 ; CHECK-NEXT: lgr 2, 1 -; CHECK-NEXT: lgdr 1, 0 +; CHECK-NEXT: lgr 1, 0 ; CHECK-NEXT: basr 7, 6 ; CHECK-NEXT: bcr 0, 0 ; CHECK-NEXT: lg 7, 2072(4) @@ -108,7 +110,7 @@ define i64 @call_vararg_both0(i64 %arg0, double %arg1) { ; CHECK-LABEL: call_vararg_long_double0: ; CHECK: stmg 6, 7, 1872(4) ; CHECK-NEXT: aghi 4, -192 -; CHECK-NEXT: larl 1, @CPI5_0 +; CHECK-NEXT: larl 1, L#CPI5_0 ; CHECK-NEXT: ld 0, 0(1) ; CHECK-NEXT: ld 2, 8(1) ; CHECK-NEXT: lg 6, 8(5) @@ -202,7 +204,7 @@ define void @call_vec_vararg_test0(<2 x double> %v) { } ; ARCH12-LABEL: call_vec_vararg_test1 -; ARCH12: larl 1, @CPI10_0 +; ARCH12: larl 1, L#CPI10_0 ; ARCH12: vl 0, 0(1), 3 ; ARCH12: vlgvg 3, 24, 0 ; ARCH12: vrepg 2, 0, 1 @@ -294,7 +296,7 @@ entry: ; CHECK-NEXT: aghi 4, -192 ; CHECK-NEXT: lg 6, 72(5) ; CHECK-NEXT: lg 5, 64(5) -; CHECK-NEXT: larl 1, @CPI17_0 +; CHECK-NEXT: larl 1, L#CPI17_0 ; CHECK-NEXT: le 0, 0(1) ; CHECK-NEXT: llihf 0, 1073692672 ; CHECK-NEXT: llihh 2, 16384 diff --git a/llvm/test/CodeGen/SystemZ/clear-liverange-spillreg.mir b/llvm/test/CodeGen/SystemZ/clear-liverange-spillreg.mir index 7ff7d9b8b7094a29e17898cd9d8c7fe504e80a9a..197c3d8551fc38cd3a8fbef1ba414efcc7f09d2f 100644 --- a/llvm/test/CodeGen/SystemZ/clear-liverange-spillreg.mir +++ b/llvm/test/CodeGen/SystemZ/clear-liverange-spillreg.mir @@ -157,6 +157,7 @@ registers: - { id: 129, class: grx32bit } - { id: 130, class: fp64bit } frameInfo: + adjustsStack: true hasCalls: true body: | bb.0: diff --git a/llvm/test/CodeGen/SystemZ/cond-move-04.mir b/llvm/test/CodeGen/SystemZ/cond-move-04.mir index 97aa00f582921d3f8f26c1e6e1437227c86267c6..ab4a14cfaee87bae1f003f67abddba5d5c73ef8c 100644 --- a/llvm/test/CodeGen/SystemZ/cond-move-04.mir +++ b/llvm/test/CodeGen/SystemZ/cond-move-04.mir @@ -53,6 +53,7 @@ registers: - { id: 10, class: gr64bit } - { id: 11, class: gr32bit } frameInfo: + adjustsStack: true hasCalls: true body: | bb.0 (%ir-block.1): @@ -64,12 +65,10 @@ body: | CHIMux %3, 0, implicit-def $cc %0 = LOCRMux undef %0, %5, 14, 6, implicit $cc %0 = LOCRMux %0, %2, 14, 6, implicit killed $cc - ADJCALLSTACKDOWN 0, 0 %7 = LGFR %0 $r3d = LGHI 0 $r4d = COPY %7 CallBRASL @foo, undef $r2d, killed $r3d, killed $r4d, csr_systemz_elf, implicit-def dead $r14d, implicit-def dead $cc, implicit-def dead $r2d - ADJCALLSTACKUP 0, 0 J %bb.1 ... diff --git a/llvm/test/CodeGen/SystemZ/cond-move-08.mir b/llvm/test/CodeGen/SystemZ/cond-move-08.mir index 93aa5626b8e894724611c35fd7d04b7696460bc8..2ea67dcce067bc3d23b24966fe8f89a281d79116 100644 --- a/llvm/test/CodeGen/SystemZ/cond-move-08.mir +++ b/llvm/test/CodeGen/SystemZ/cond-move-08.mir @@ -116,6 +116,7 @@ registers: - { id: 27, class: grx32bit } - { id: 28, class: addr64bit } frameInfo: + adjustsStack: true hasCalls: true body: | bb.0.bb5: @@ -154,9 +155,7 @@ body: | J %bb.4 bb.4.bb33: - ADJCALLSTACKDOWN 0, 0 CallBRASL @fun, csr_systemz_elf, implicit-def dead $r14d, implicit-def dead $cc - ADJCALLSTACKUP 0, 0 STRL %4, @globvar :: (store (s32) into @globvar) CLFIMux undef %23:grx32bit, 1, implicit-def $cc %25:grx32bit = LHIMux 0 diff --git a/llvm/test/CodeGen/SystemZ/cond-move-regalloc-hints-02.mir b/llvm/test/CodeGen/SystemZ/cond-move-regalloc-hints-02.mir index 37e29800fb1d627d00627618192352d32d7648d9..8a7929c9eb2c3196491c6e4164e1c9e95fdc2b3d 100644 --- a/llvm/test/CodeGen/SystemZ/cond-move-regalloc-hints-02.mir +++ b/llvm/test/CodeGen/SystemZ/cond-move-regalloc-hints-02.mir @@ -30,6 +30,7 @@ registers: - { id: 11, class: gr32bit } frameInfo: maxAlignment: 1 + adjustsStack: true hasCalls: true machineFunctionInfo: {} body: | @@ -44,11 +45,9 @@ body: | %11:gr32bit = SELRMux %8, %9:grx32bit, 14, 6, implicit killed $cc CHIMux %6, 2, implicit-def $cc %0:gr32bit = SELRMux %11, %5, 14, 8, implicit killed $cc - ADJCALLSTACKDOWN 0, 0 %10:gr64bit = LGFR %0 $r2d = COPY %10 CallBRASL @foo, killed $r2d, csr_systemz_elf, implicit-def dead $r14d, implicit-def dead $cc, implicit $fpc - ADJCALLSTACKUP 0, 0 J %bb.1 ... diff --git a/llvm/test/CodeGen/SystemZ/cond-move-regalloc-hints.mir b/llvm/test/CodeGen/SystemZ/cond-move-regalloc-hints.mir index e7e1eaf8f8fdcd768374e63686a2bd71bd5b74af..009fd6ce82679b7d7aafad6c2c18b05d851e7dd4 100644 --- a/llvm/test/CodeGen/SystemZ/cond-move-regalloc-hints.mir +++ b/llvm/test/CodeGen/SystemZ/cond-move-regalloc-hints.mir @@ -192,6 +192,7 @@ liveins: - { reg: '$r2d', virtual-reg: '%31' } - { reg: '$r3d', virtual-reg: '%32' } frameInfo: + adjustsStack: true hasCalls: true body: | bb.0.bb: @@ -199,18 +200,12 @@ body: | %32:gr64bit = COPY $r3d %0:gr64bit = COPY $r2d - ADJCALLSTACKDOWN 0, 0 CallBRASL @sre_malloc, csr_systemz_elf, implicit-def dead $r14d, implicit-def dead $cc, implicit-def $r2d %1:addr64bit = COPY $r2d - ADJCALLSTACKUP 0, 0 - ADJCALLSTACKDOWN 0, 0 CallBRASL @sre_malloc, csr_systemz_elf, implicit-def dead $r14d, implicit-def dead $cc, implicit-def $r2d %2:addr64bit = COPY $r2d - ADJCALLSTACKUP 0, 0 %3:gr32bit = AHIMuxK %0.subreg_l32, -1, implicit-def dead $cc - ADJCALLSTACKDOWN 0, 0 CallBRASL @malloc, csr_systemz_elf, implicit-def dead $r14d, implicit-def dead $cc - ADJCALLSTACKUP 0, 0 %55:gr32bit = AHIMuxK %0.subreg_l32, 3, implicit-def dead $cc %56:addr64bit = LGHI 0 %57:gr64bit = COPY %0 diff --git a/llvm/test/CodeGen/SystemZ/frame-28.mir b/llvm/test/CodeGen/SystemZ/frame-28.mir index dd5933a9c7b4b4c73860a5888b18a12c21ff554f..254b8a2cf2461bcac1ac393b937a877b56dd96e6 100644 --- a/llvm/test/CodeGen/SystemZ/frame-28.mir +++ b/llvm/test/CodeGen/SystemZ/frame-28.mir @@ -162,6 +162,8 @@ body: | --- name: fun4 tracksRegLiveness: true +frameInfo: + adjustsStack: true stack: - { id: 0, size: 5000 } - { id: 1, size: 2500 } @@ -177,9 +179,7 @@ body: | VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.1, 0, $noreg - ADJCALLSTACKDOWN 0, 0 CallBRASL @foo, csr_systemz_elf, implicit-def dead $r14d, implicit-def dead $cc, implicit $fpc, implicit-def $r2l - ADJCALLSTACKUP 0, 0 $f17d = IMPLICIT_DEF VST64 renamable $f17d, %stack.1, 0, $noreg Return diff --git a/llvm/test/CodeGen/SystemZ/frame-adjstack.ll b/llvm/test/CodeGen/SystemZ/frame-adjstack.ll new file mode 100644 index 0000000000000000000000000000000000000000..7edacaa3d7d714e74311ac20fd47bd4e1009d3a5 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/frame-adjstack.ll @@ -0,0 +1,16 @@ +; RUN: llc < %s -mtriple=s390x-linux-gnu -verify-machineinstrs | FileCheck %s +; +; Test that inserting a new MBB near a call during finalize isel custom +; insertion does not cause all frame instructions to be missed. That would +; result in a missing to set the AdjustsStack flag. + +; CHECK-LABEL: fun +define void @fun(i1 %cc) { + %sel = select i1 %cc, i32 5, i32 0 + tail call void @input_report_abs(i32 %sel) + %sel2 = select i1 %cc, i32 6, i32 1 + tail call void @input_report_abs(i32 %sel2) + ret void +} + +declare void @input_report_abs(i32) diff --git a/llvm/test/CodeGen/SystemZ/int-cmp-56.mir b/llvm/test/CodeGen/SystemZ/int-cmp-56.mir index e52fd44ae47db98448654432e9bdd7e42c9b4b10..3e00b6065eb908b114d90ccca8f32e2d027e5a55 100644 --- a/llvm/test/CodeGen/SystemZ/int-cmp-56.mir +++ b/llvm/test/CodeGen/SystemZ/int-cmp-56.mir @@ -48,6 +48,7 @@ liveins: - { reg: '$r2d', virtual-reg: '%0' } frameInfo: maxAlignment: 1 + adjustsStack: true hasCalls: true machineFunctionInfo: {} body: | @@ -125,6 +126,7 @@ liveins: - { reg: '$r2d', virtual-reg: '%0' } frameInfo: maxAlignment: 1 + adjustsStack: true hasCalls: true machineFunctionInfo: {} body: | @@ -202,6 +204,7 @@ liveins: - { reg: '$r2d', virtual-reg: '%0' } frameInfo: maxAlignment: 1 + adjustsStack: true hasCalls: true machineFunctionInfo: {} body: | @@ -279,6 +282,7 @@ liveins: - { reg: '$r2d', virtual-reg: '%0' } frameInfo: maxAlignment: 1 + adjustsStack: true hasCalls: true machineFunctionInfo: {} body: | diff --git a/llvm/test/CodeGen/SystemZ/int-usub-12.ll b/llvm/test/CodeGen/SystemZ/int-usub-12.ll index c39a6da37048d3af4e5285a0283959df41ab4d76..147fbfd920a9dcc743b6b9776524a175d1cd39ec 100644 --- a/llvm/test/CodeGen/SystemZ/int-usub-12.ll +++ b/llvm/test/CodeGen/SystemZ/int-usub-12.ll @@ -11,6 +11,7 @@ define zeroext i1 @f1(i128 %a, i128 %b, ptr %res) { ; CHECK-NEXT: vscbiq %v2, %v1, %v0 ; CHECK-NEXT: vlgvg %r2, %v2, 1 ; CHECK-NEXT: vsq %v0, %v1, %v0 +; CHECK-NEXT: xilf %r2, 1 ; CHECK-NEXT: vst %v0, 0(%r4), 3 ; CHECK-NEXT: br %r14 %t = call {i128, i1} @llvm.usub.with.overflow.i128(i128 %a, i128 %b) @@ -27,6 +28,7 @@ define zeroext i1 @f2(i128 %a, i128 %b) { ; CHECK-NEXT: vl %v1, 0(%r2), 3 ; CHECK-NEXT: vscbiq %v0, %v1, %v0 ; CHECK-NEXT: vlgvg %r2, %v0, 1 +; CHECK-NEXT: xilf %r2, 1 ; CHECK-NEXT: br %r14 %t = call {i128, i1} @llvm.usub.with.overflow.i128(i128 %a, i128 %b) %obit = extractvalue {i128, i1} %t, 1 @@ -46,5 +48,25 @@ define i128 @f3(i128 %a, i128 %b) { ret i128 %val } +define i128 @f4(i128 %a, i128 %b) { +; CHECK-LABEL: f4: +; CHECK: # %bb.0: +; CHECK-NEXT: vl %v0, 0(%r4), 3 +; CHECK-NEXT: vl %v1, 0(%r3), 3 +; CHECK-NEXT: vscbiq %v2, %v1, %v0 +; CHECK-NEXT: vlgvf %r0, %v2, 3 +; CHECK-NEXT: vgbm %v2, 0 +; CHECK-NEXT: xilf %r0, 1 +; CHECK-NEXT: jl .LBB3_2 +; CHECK-NEXT: # %bb.1: +; CHECK-NEXT: vsq %v2, %v1, %v0 +; CHECK-NEXT: .LBB3_2: +; CHECK-NEXT: vst %v2, 0(%r2), 3 +; CHECK-NEXT: br %r14 + %val = call i128 @llvm.usub.sat.i128(i128 %a, i128 %b) + ret i128 %val +} + declare {i128, i1} @llvm.usub.with.overflow.i128(i128, i128) nounwind readnone +declare i128 @llvm.usub.sat.i128(i128, i128) nounwind readnone diff --git a/llvm/test/CodeGen/SystemZ/int-usub-13.ll b/llvm/test/CodeGen/SystemZ/int-usub-13.ll index 637e1a81de996fadbd9bf364825b1cf64267a381..794af3b73fbe2ad8fa846e59c8d6f861f9ef7c8a 100644 --- a/llvm/test/CodeGen/SystemZ/int-usub-13.ll +++ b/llvm/test/CodeGen/SystemZ/int-usub-13.ll @@ -15,6 +15,7 @@ define zeroext i1 @f1(i256 %a, i256 %b, ptr %res) { ; CHECK-NEXT: vlgvg %r2, %v5, 1 ; CHECK-NEXT: vsbiq %v0, %v1, %v0, %v4 ; CHECK-NEXT: vsq %v1, %v3, %v2 +; CHECK-NEXT: xilf %r2, 1 ; CHECK-NEXT: vst %v1, 16(%r4), 3 ; CHECK-NEXT: vst %v0, 0(%r4), 3 ; CHECK-NEXT: br %r14 @@ -35,6 +36,7 @@ define zeroext i1 @f2(i256 %a, i256 %b) { ; CHECK-NEXT: vscbiq %v2, %v3, %v2 ; CHECK-NEXT: vsbcbiq %v0, %v1, %v0, %v2 ; CHECK-NEXT: vlgvg %r2, %v0, 1 +; CHECK-NEXT: xilf %r2, 1 ; CHECK-NEXT: br %r14 %t = call {i256, i1} @llvm.usub.with.overflow.i256(i256 %a, i256 %b) %obit = extractvalue {i256, i1} %t, 1 diff --git a/llvm/test/CodeGen/SystemZ/readcyclecounter.ll b/llvm/test/CodeGen/SystemZ/readcyclecounter.ll new file mode 100644 index 0000000000000000000000000000000000000000..34b6d34143f89effa9eb639ad3ec5c25c9bf071b --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/readcyclecounter.ll @@ -0,0 +1,27 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=s390x-ibm-linux | FileCheck %s + +; Verify that we correctly lower ISD::READCYCLECOUNTER. + +define i64 @test_builtin_readcyclecounter1() { +; CHECK-LABEL: test_builtin_readcyclecounter1: +; CHECK: # %bb.0: +; CHECK-NEXT: aghi %r15, -168 +; CHECK-NEXT: .cfi_def_cfa_offset 328 +; CHECK-NEXT: stckf 160(%r15) +; CHECK-NEXT: lg %r2, 160(%r15) +; CHECK-NEXT: aghi %r15, 168 +; CHECK-NEXT: br %r14 + %1 = tail call i64 @llvm.readcyclecounter() + ret i64 %1 +} + +define void @test_builtin_readcyclecounter2(ptr %ptr) { +; CHECK-LABEL: test_builtin_readcyclecounter2: +; CHECK: # %bb.0: +; CHECK-NEXT: stckf 0(%r2) +; CHECK-NEXT: br %r14 + %1 = tail call i64 @llvm.readcyclecounter() + store i64 %1, ptr %ptr + ret void +} diff --git a/llvm/test/CodeGen/SystemZ/regcoal-subranges-update.mir b/llvm/test/CodeGen/SystemZ/regcoal-subranges-update.mir index f709b70ff1b7981cc0b4ccba91d86896f1ab371a..bf5855010bf90b7a754aed24ea7e46669c3cc049 100644 --- a/llvm/test/CodeGen/SystemZ/regcoal-subranges-update.mir +++ b/llvm/test/CodeGen/SystemZ/regcoal-subranges-update.mir @@ -49,6 +49,8 @@ body: | --- name: segfault tracksRegLiveness: true +frameInfo: + adjustsStack: true liveins: [] body: | ; CHECK-LABEL: name: segfault diff --git a/llvm/test/CodeGen/SystemZ/swifterror.ll b/llvm/test/CodeGen/SystemZ/swifterror.ll index 3ea29f1d830ec64a9bda9820d5351e30ab41f465..1b18287cac1468f89755cade1a7c9b82f23ff248 100644 --- a/llvm/test/CodeGen/SystemZ/swifterror.ll +++ b/llvm/test/CodeGen/SystemZ/swifterror.ll @@ -30,8 +30,8 @@ entry: define float @caller(ptr %error_ref) { ; CHECK-LABEL: caller: ; Make a copy of error_ref because r2 is getting clobbered -; CHECK: lgr %r[[REG1:[0-9]+]], %r2 -; CHECK: lghi %r9, 0 +; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r2 +; CHECK-DAG: lghi %r9, 0 ; CHECK: brasl %r14, foo ; CHECK: %r2, %r9 ; CHECK: jlh @@ -197,7 +197,7 @@ define void @foo_sret(ptr sret(%struct.S) %agg.result, i32 %val1, ptr swifterror ; CHECK-LABEL: foo_sret: ; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r2 ; CHECK-DAG: lr %r[[REG2:[0-9]+]], %r3 -; CHECK: lghi %r2, 16 +; CHECK-DAG: lghi %r2, 16 ; CHECK: brasl %r14, malloc ; CHECK: mvi 8(%r2), 1 ; CHECK: st %r[[REG2]], 4(%r[[REG1]]) @@ -280,7 +280,7 @@ define float @caller_with_multiple_swifterror_values(ptr %error_ref, ptr %error_ ; CHECK-DAG: lgr %r[[REG1:[0-9]+]], %r2 ; CHECK-DAG: lgr %r[[REG2:[0-9]+]], %r3 ; The first swifterror value: -; CHECK: lghi %r9, 0 +; CHECK-DAG: lghi %r9, 0 ; CHECK: brasl %r14, foo ; CHECK: ltgr %r2, %r9 ; CHECK: jlh diff --git a/llvm/test/CodeGen/SystemZ/vector-constrained-fp-intrinsics.ll b/llvm/test/CodeGen/SystemZ/vector-constrained-fp-intrinsics.ll index 69e1c2f4aa0af35a1dc4e32200ccb095c8772bf2..9d77744f18ca1a13de6821bb39f335066610bba5 100644 --- a/llvm/test/CodeGen/SystemZ/vector-constrained-fp-intrinsics.ll +++ b/llvm/test/CodeGen/SystemZ/vector-constrained-fp-intrinsics.ll @@ -1649,8 +1649,8 @@ define <2 x double> @constrained_vector_powi_v2f64() #0 { ; S390X-NEXT: brasl %r14, __powidf2@PLT ; S390X-NEXT: larl %r1, .LCPI36_1 ; S390X-NEXT: ld %f1, 0(%r1) -; S390X-NEXT: ldr %f8, %f0 ; S390X-NEXT: lghi %r2, 3 +; S390X-NEXT: ldr %f8, %f0 ; S390X-NEXT: ldr %f0, %f1 ; S390X-NEXT: brasl %r14, __powidf2@PLT ; S390X-NEXT: ldr %f2, %f8 @@ -1707,14 +1707,14 @@ define <3 x float> @constrained_vector_powi_v3f32() #0 { ; S390X-NEXT: brasl %r14, __powisf2@PLT ; S390X-NEXT: larl %r1, .LCPI37_1 ; S390X-NEXT: le %f1, 0(%r1) -; S390X-NEXT: ler %f8, %f0 ; S390X-NEXT: lghi %r2, 3 +; S390X-NEXT: ler %f8, %f0 ; S390X-NEXT: ler %f0, %f1 ; S390X-NEXT: brasl %r14, __powisf2@PLT ; S390X-NEXT: larl %r1, .LCPI37_2 ; S390X-NEXT: le %f1, 0(%r1) -; S390X-NEXT: ler %f9, %f0 ; S390X-NEXT: lghi %r2, 3 +; S390X-NEXT: ler %f9, %f0 ; S390X-NEXT: ler %f0, %f1 ; S390X-NEXT: brasl %r14, __powisf2@PLT ; S390X-NEXT: ler %f2, %f9 @@ -1784,14 +1784,14 @@ define void @constrained_vector_powi_v3f64(ptr %a) #0 { ; S390X-NEXT: brasl %r14, __powidf2@PLT ; S390X-NEXT: larl %r1, .LCPI38_1 ; S390X-NEXT: ld %f1, 0(%r1) -; S390X-NEXT: ldr %f8, %f0 ; S390X-NEXT: lghi %r2, 3 +; S390X-NEXT: ldr %f8, %f0 ; S390X-NEXT: ldr %f0, %f1 ; S390X-NEXT: brasl %r14, __powidf2@PLT ; S390X-NEXT: larl %r1, .LCPI38_2 ; S390X-NEXT: ld %f1, 0(%r1) -; S390X-NEXT: ldr %f9, %f0 ; S390X-NEXT: lghi %r2, 3 +; S390X-NEXT: ldr %f9, %f0 ; S390X-NEXT: ldr %f0, %f1 ; S390X-NEXT: brasl %r14, __powidf2@PLT ; S390X-NEXT: std %f0, 16(%r13) @@ -1865,20 +1865,20 @@ define <4 x double> @constrained_vector_powi_v4f64() #0 { ; S390X-NEXT: brasl %r14, __powidf2@PLT ; S390X-NEXT: larl %r1, .LCPI39_1 ; S390X-NEXT: ld %f1, 0(%r1) -; S390X-NEXT: ldr %f8, %f0 ; S390X-NEXT: lghi %r2, 3 +; S390X-NEXT: ldr %f8, %f0 ; S390X-NEXT: ldr %f0, %f1 ; S390X-NEXT: brasl %r14, __powidf2@PLT ; S390X-NEXT: larl %r1, .LCPI39_2 ; S390X-NEXT: ld %f1, 0(%r1) -; S390X-NEXT: ldr %f9, %f0 ; S390X-NEXT: lghi %r2, 3 +; S390X-NEXT: ldr %f9, %f0 ; S390X-NEXT: ldr %f0, %f1 ; S390X-NEXT: brasl %r14, __powidf2@PLT ; S390X-NEXT: larl %r1, .LCPI39_3 ; S390X-NEXT: ld %f1, 0(%r1) -; S390X-NEXT: ldr %f10, %f0 ; S390X-NEXT: lghi %r2, 3 +; S390X-NEXT: ldr %f10, %f0 ; S390X-NEXT: ldr %f0, %f1 ; S390X-NEXT: brasl %r14, __powidf2@PLT ; S390X-NEXT: ldr %f2, %f10 diff --git a/llvm/test/CodeGen/SystemZ/zos-ada-relocations.ll b/llvm/test/CodeGen/SystemZ/zos-ada-relocations.ll index e25246917ec0998b5462ce5006be8c464ceecc25..db67ac578186802a3590304c3997852284d82c3f 100644 --- a/llvm/test/CodeGen/SystemZ/zos-ada-relocations.ll +++ b/llvm/test/CodeGen/SystemZ/zos-ada-relocations.ll @@ -56,9 +56,9 @@ entry: declare signext i32 @callout(i32 signext) ; CHECK: .section ".ada" -; CHECK: .set @@DoFunc@indirect0, DoFunc -; CHECK: .indirect_symbol @@DoFunc@indirect0 -; CHECK: .quad V(@@DoFunc@indirect0) * Offset 0 pointer to function descriptor DoFunc +; CHECK: .set L#DoFunc@indirect0, DoFunc +; CHECK: .indirect_symbol L#DoFunc@indirect0 +; CHECK: .quad V(L#DoFunc@indirect0) * Offset 0 pointer to function descriptor DoFunc ; CHECK: .quad R(Caller) * Offset 8 function descriptor of Caller ; CHECK: .quad V(Caller) ; CHECK: .quad A(i2) * Offset 24 pointer to data symbol i2 diff --git a/llvm/test/CodeGen/SystemZ/zos-landingpad.ll b/llvm/test/CodeGen/SystemZ/zos-landingpad.ll index 7f3214d574242b097757567fef003bfe2f12f34e..9db10114e9795f5ee880d8c96d6adc6d933d3cf8 100644 --- a/llvm/test/CodeGen/SystemZ/zos-landingpad.ll +++ b/llvm/test/CodeGen/SystemZ/zos-landingpad.ll @@ -19,7 +19,7 @@ done: lpad: %0 = landingpad { ptr, i32 } cleanup ; The Exception Pointer is %r1; the Exception Selector, %r2. -; CHECK: @BB{{[^%]*}} %lpad +; CHECK: L#BB{{[^%]*}} %lpad ; CHECK-DAG: stg 1, {{.*}} ; CHECK-DAG: st 2, {{.*}} %1 = extractvalue { ptr, i32 } %0, 0 diff --git a/llvm/test/CodeGen/SystemZ/zos-ppa2.ll b/llvm/test/CodeGen/SystemZ/zos-ppa2.ll index 60580aeb6d83cc76ddeb036245f90e6ae5a7a0f0..189b5a3757ee072c1b509f9da363f9c0d38ef386 100644 --- a/llvm/test/CodeGen/SystemZ/zos-ppa2.ll +++ b/llvm/test/CodeGen/SystemZ/zos-ppa2.ll @@ -2,24 +2,24 @@ ; REQUIRES: systemz-registered-target ; CHECK: .section ".ppa2" -; CHECK: @@PPA2: +; CHECK: L#PPA2: ; CHECK: .byte 3 ; CHECK: .byte 231 ; CHECK: .byte 34 ; CHECK: .byte 4 -; CHECK: .long CELQSTRT-@@PPA2 +; CHECK: .long CELQSTRT-L#PPA2 ; CHECK: .long 0 -; CHECK: .long @@DVS-@@PPA2 +; CHECK: .long L#DVS-L#PPA2 ; CHECK: .long 0 ; CHECK: .byte 129 ; CHECK: .byte 0 ; CHECK: .short 0 -; CHECK: @@DVS: +; CHECK: L#DVS: ; CHECK: .ascii "\361\371\367\360\360\361\360\361\360\360\360\360\360\360" ; CHECK: .short 0 -; CHECK: .quad @@PPA2-CELQSTRT * A(PPA2-CELQSTRT) -; CHECK: @@PPA1_void_test_0: -; CHECK: .long @@PPA2-@@PPA1_void_test_0 * Offset to PPA2 +; CHECK: .quad L#PPA2-CELQSTRT * A(PPA2-CELQSTRT) +; CHECK: L#PPA1_void_test_0: +; CHECK: .long L#PPA2-L#PPA1_void_test_0 * Offset to PPA2 ; CHECK: .section "B_IDRL" ; CHECK: .byte 0 ; CHECK: .byte 3 diff --git a/llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll b/llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll index 8c0411629da7d27c5877e0b2383f019886fc52cc..d3e5823fcb1fe76af429ba003bbe2fe4aa2cdc69 100644 --- a/llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll +++ b/llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll @@ -15,7 +15,7 @@ ; CHECK64: aghi 4, 192 ; CHECK64: b 2(7) -; CHECK64: @@PPA1_func0_0: +; CHECK64: L#PPA1_func0_0: ; CHECK64: .short 0 * Length/4 of Parms define void @func0() { call i64 (i64) @fun(i64 10) @@ -31,7 +31,7 @@ define void @func0() { ; CHECK64: aghi 4, 160 ; CHECK64: b 2(7) -; CHECK64: @@PPA1_func1_0: +; CHECK64: L#PPA1_func1_0: ; CHECK64: .short 2 * Length/4 of Parms define void @func1(ptr %ptr) { %l01 = load volatile i64, ptr %ptr @@ -336,16 +336,16 @@ define void @large_stack0() { ; CHECK64: lgr 0, 3 ; CHECK64: llgt 3, 1208 ; CHECK64: cg 4, 64(3) -; CHECK64: jhe @BB7_2 +; CHECK64: jhe L#BB7_2 ; CHECK64: %bb.1: ; CHECK64: lg 3, 72(3) ; CHECK64: basr 3, 3 ; CHECK64: bcr 0, 7 -; CHECK64: @BB7_2: +; CHECK64: L#BB7_2: ; CHECK64: stmg 6, 7, 2064(4) ; CHECK64: lgr 3, 0 -; CHECK64: @@PPA1_large_stack1_0: +; CHECK64: L#PPA1_large_stack1_0: ; CHECK64: .short 6 * Length/4 of Parms define void @large_stack1(i64 %n1, i64 %n2, i64 %n3) { %arr = alloca [131072 x i64], align 8 @@ -361,12 +361,12 @@ define void @large_stack1(i64 %n1, i64 %n2, i64 %n3) { ; CHECK64: agfi 4, -1048768 ; CHECK64: llgt 3, 1208 ; CHECK64: cg 4, 64(3) -; CHECK64: jhe @BB8_2 +; CHECK64: jhe L#BB8_2 ; CHECK64: %bb.1: ; CHECK64: lg 3, 72(3) ; CHECK64: basr 3, 3 ; CHECK64: bcr 0, 7 -; CHECK64: @BB8_2: +; CHECK64: L#BB8_2: ; CHECK64: lgr 3, 0 ; CHECK64: lg 3, 2192(3) ; CHECK64: stmg 4, 12, 2048(4) diff --git a/llvm/test/CodeGen/Thumb2/aligned-nonfallthrough.ll b/llvm/test/CodeGen/Thumb2/aligned-nonfallthrough.ll index 767b7028a967cf04ed20c52173f7016df48ab526..a0f8374e074d932949da29547fc35f36fd515607 100644 --- a/llvm/test/CodeGen/Thumb2/aligned-nonfallthrough.ll +++ b/llvm/test/CodeGen/Thumb2/aligned-nonfallthrough.ll @@ -42,9 +42,8 @@ define i64 @loopif(ptr nocapture readonly %x, i32 %y, i32 %n) { ; CHECK-NEXT: cmp r2, #1 ; CHECK-NEXT: blt .LBB1_4 ; CHECK-NEXT: @ %bb.1: @ %for.body.lr.ph -; CHECK-NEXT: mov lr, r2 -; CHECK-NEXT: mov r12, r0 ; CHECK-NEXT: dls lr, r2 +; CHECK-NEXT: mov r12, r0 ; CHECK-NEXT: movs r0, #0 ; CHECK-NEXT: movs r3, #0 ; CHECK-NEXT: .p2align 2 diff --git a/llvm/test/CodeGen/Thumb2/mve-gather-increment.ll b/llvm/test/CodeGen/Thumb2/mve-gather-increment.ll index 4ab569777b2adbd91612d5df66dc2332a52f7972..93cab25c2cb72e6a5b27aa08e0e2e452d003099b 100644 --- a/llvm/test/CodeGen/Thumb2/mve-gather-increment.ll +++ b/llvm/test/CodeGen/Thumb2/mve-gather-increment.ll @@ -542,9 +542,7 @@ define arm_aapcs_vfpcc void @gather_inc_v8i16_simple(ptr noalias nocapture reado ; CHECK-NEXT: .pad #28 ; CHECK-NEXT: sub sp, #28 ; CHECK-NEXT: cmp r2, #1 -; CHECK-NEXT: str r1, [sp, #4] @ 4-byte Spill -; CHECK-NEXT: mov r1, r2 -; CHECK-NEXT: str r2, [sp, #8] @ 4-byte Spill +; CHECK-NEXT: strd r1, r2, [sp, #4] @ 8-byte Folded Spill ; CHECK-NEXT: blt .LBB11_5 ; CHECK-NEXT: @ %bb.1: @ %vector.ph.preheader ; CHECK-NEXT: ldr r1, [sp, #8] @ 4-byte Reload @@ -661,9 +659,7 @@ define arm_aapcs_vfpcc void @gather_inc_v8i16_complex(ptr noalias nocapture read ; CHECK-NEXT: .pad #136 ; CHECK-NEXT: sub sp, #136 ; CHECK-NEXT: cmp r2, #1 -; CHECK-NEXT: str r1, [sp, #64] @ 4-byte Spill -; CHECK-NEXT: mov r1, r2 -; CHECK-NEXT: str r2, [sp, #68] @ 4-byte Spill +; CHECK-NEXT: strd r1, r2, [sp, #64] @ 8-byte Folded Spill ; CHECK-NEXT: blt.w .LBB12_5 ; CHECK-NEXT: @ %bb.1: @ %vector.ph.preheader ; CHECK-NEXT: ldr r1, [sp, #68] @ 4-byte Reload @@ -952,11 +948,9 @@ define arm_aapcs_vfpcc void @gather_inc_v16i8_complex(ptr noalias nocapture read ; CHECK-NEXT: vstrw.32 q1, [sp, #152] @ 16-byte Spill ; CHECK-NEXT: vldrw.u32 q1, [sp, #296] @ 16-byte Reload ; CHECK-NEXT: vstrw.32 q0, [sp, #168] @ 16-byte Spill -; CHECK-NEXT: vmov q0, q2 -; CHECK-NEXT: vmov q3, q5 -; CHECK-NEXT: vadd.i32 q1, q1, r0 ; CHECK-NEXT: vldrw.u32 q0, [sp, #248] @ 16-byte Reload ; CHECK-NEXT: vldrw.u32 q3, [sp, #216] @ 16-byte Reload +; CHECK-NEXT: vadd.i32 q1, q1, r0 ; CHECK-NEXT: vstrw.32 q5, [sp, #120] @ 16-byte Spill ; CHECK-NEXT: vadd.i32 q0, q0, r0 ; CHECK-NEXT: subs.w r11, r11, #16 @@ -1243,9 +1237,7 @@ define arm_aapcs_vfpcc void @gather_inc_v16i8_simple(ptr noalias nocapture reado ; CHECK-NEXT: .pad #64 ; CHECK-NEXT: sub sp, #64 ; CHECK-NEXT: cmp r2, #1 -; CHECK-NEXT: str r1, [sp, #56] @ 4-byte Spill -; CHECK-NEXT: mov r1, r2 -; CHECK-NEXT: str r2, [sp, #60] @ 4-byte Spill +; CHECK-NEXT: strd r1, r2, [sp, #56] @ 8-byte Folded Spill ; CHECK-NEXT: blt.w .LBB14_5 ; CHECK-NEXT: @ %bb.1: @ %vector.ph.preheader ; CHECK-NEXT: adr r5, .LCPI14_3 diff --git a/llvm/test/CodeGen/Thumb2/mve-gather-scatter-optimisation.ll b/llvm/test/CodeGen/Thumb2/mve-gather-scatter-optimisation.ll index 18c8a8a22ef22a145a76b13887567eac21dfbd25..7b8b884576d13e6cd85925ee21636b8951f6fdf3 100644 --- a/llvm/test/CodeGen/Thumb2/mve-gather-scatter-optimisation.ll +++ b/llvm/test/CodeGen/Thumb2/mve-gather-scatter-optimisation.ll @@ -609,7 +609,6 @@ define dso_local void @arm_mat_mult_q15(ptr noalias nocapture readonly %A, ptr n ; CHECK-NEXT: strd r0, r2, [sp, #24] @ 8-byte Folded Spill ; CHECK-NEXT: cmp r3, #0 ; CHECK-NEXT: str r3, [sp, #8] @ 4-byte Spill -; CHECK-NEXT: mov r0, r3 ; CHECK-NEXT: itt ne ; CHECK-NEXT: ldrne r0, [sp, #136] ; CHECK-NEXT: cmpne r0, #0 diff --git a/llvm/test/CodeGen/Thumb2/mve-laneinterleaving-reduct.ll b/llvm/test/CodeGen/Thumb2/mve-laneinterleaving-reduct.ll index 9987ff940b5aac1b3054d17d3edb00082331d9ce..77980be9052072ccc60e1d7441fe9d4317b3552a 100644 --- a/llvm/test/CodeGen/Thumb2/mve-laneinterleaving-reduct.ll +++ b/llvm/test/CodeGen/Thumb2/mve-laneinterleaving-reduct.ll @@ -108,9 +108,7 @@ define void @correlate(ptr nocapture noundef readonly %ID, ptr nocapture noundef ; CHECK-NEXT: .pad #12 ; CHECK-NEXT: sub sp, #12 ; CHECK-NEXT: cmp r3, #1 -; CHECK-NEXT: strd r0, r1, [sp] @ 8-byte Folded Spill -; CHECK-NEXT: mov r1, r3 -; CHECK-NEXT: str r3, [sp, #8] @ 4-byte Spill +; CHECK-NEXT: stm.w sp, {r0, r1, r3} @ 12-byte Folded Spill ; CHECK-NEXT: blt .LBB4_12 ; CHECK-NEXT: @ %bb.1: @ %for.body.lr.ph ; CHECK-NEXT: ldr r1, [sp, #48] diff --git a/llvm/test/CodeGen/Thumb2/mve-postinc-lsr.ll b/llvm/test/CodeGen/Thumb2/mve-postinc-lsr.ll index 82a186bcc73d6cf964d94e924a150b393caa7133..c03339b52f2643bd271f4741c2578d465e221daa 100644 --- a/llvm/test/CodeGen/Thumb2/mve-postinc-lsr.ll +++ b/llvm/test/CodeGen/Thumb2/mve-postinc-lsr.ll @@ -1062,9 +1062,8 @@ define arm_aapcs_vfpcc void @_Z37_arm_radix4_butterfly_inverse_f32_mvePK21arm_cf ; CHECK-NEXT: .pad #40 ; CHECK-NEXT: sub sp, #40 ; CHECK-NEXT: cmp r2, #8 -; CHECK-NEXT: str r1, [sp, #16] @ 4-byte Spill ; CHECK-NEXT: vstr s0, [sp] @ 4-byte Spill -; CHECK-NEXT: mov r1, r2 +; CHECK-NEXT: str r1, [sp, #16] @ 4-byte Spill ; CHECK-NEXT: str r2, [sp, #4] @ 4-byte Spill ; CHECK-NEXT: blo .LBB7_9 ; CHECK-NEXT: @ %bb.1: diff --git a/llvm/test/CodeGen/Thumb2/mve-vldst4.ll b/llvm/test/CodeGen/Thumb2/mve-vldst4.ll index 219541cffb940fa339842f02b23877f9fef3a8cd..2e51e9e059f65e8594608cd731bb55cd2649b075 100644 --- a/llvm/test/CodeGen/Thumb2/mve-vldst4.ll +++ b/llvm/test/CodeGen/Thumb2/mve-vldst4.ll @@ -95,14 +95,13 @@ define void @vldst4(ptr nocapture readonly %pIn, ptr nocapture %pOut, i32 %numRo ; CHECK-NEXT: vmovx.f16 s8, s27 ; CHECK-NEXT: vins.f16 s12, s24 ; CHECK-NEXT: vins.f16 s13, s25 +; CHECK-NEXT: vins.f16 s2, s10 ; CHECK-NEXT: vins.f16 s3, s11 ; CHECK-NEXT: vins.f16 s1, s9 -; CHECK-NEXT: vins.f16 s2, s10 ; CHECK-NEXT: vins.f16 s22, s8 ; CHECK-NEXT: vmov q2, q3 -; CHECK-NEXT: vmov.f32 s17, s0 -; CHECK-NEXT: vmov.f32 s10, s4 ; CHECK-NEXT: vmov q6, q0 +; CHECK-NEXT: vmov.f32 s10, s4 ; CHECK-NEXT: vmov.f32 s11, s7 ; CHECK-NEXT: vmov.f32 s9, s0 ; CHECK-NEXT: vmov.f32 s17, s2 diff --git a/llvm/test/CodeGen/Thumb2/mve-vpt-optimisations.mir b/llvm/test/CodeGen/Thumb2/mve-vpt-optimisations.mir index f28311e6563f4186165c59f5cf50044a86097ad7..f9b175ed80fbf3595df68cdda3bd7f8883bed65e 100644 --- a/llvm/test/CodeGen/Thumb2/mve-vpt-optimisations.mir +++ b/llvm/test/CodeGen/Thumb2/mve-vpt-optimisations.mir @@ -1,5 +1,5 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py -# RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+armv8.1-m.main,+hwdiv,+mve.fp,+ras,+thumb-mode -run-pass arm-mve-vpt-opts %s -o - | FileCheck %s +# RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+armv8.1-m.main,+hwdiv,+mve.fp,+ras,+thumb-mode -run-pass arm-mve-vpt-opts -verify-machineinstrs %s -o - | FileCheck %s --- name: vcmp_with_opposite_cond @@ -1021,3 +1021,26 @@ body: | %16:mqpr = MVE_VORR %15, %15, 1, %10, $noreg, undef %16 %17:mqpr = MVE_VORR %16, %16, 1, %11, $noreg, undef %17 ... +--- +name: reuse_kill_flags +alignment: 4 +body: | + bb.0: + ; CHECK-LABEL: name: reuse_kill_flags + ; CHECK: [[t2MOVi:%[0-9]+]]:tgpreven = t2MOVi 0, 14 /* CC::al */, $noreg, $noreg + ; CHECK-NEXT: [[COPY:%[0-9]+]]:vccr = COPY [[t2MOVi]] + ; CHECK-NEXT: [[DEF:%[0-9]+]]:mqpr = IMPLICIT_DEF + ; CHECK-NEXT: [[MVE_VORR:%[0-9]+]]:mqpr = MVE_VORR [[DEF]], [[DEF]], 1, [[COPY]], $noreg, undef [[MVE_VORR]] + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:mqpr = IMPLICIT_DEF + ; CHECK-NEXT: [[MVE_VORR1:%[0-9]+]]:mqpr = MVE_VORR [[DEF1]], [[DEF1]], 1, killed [[COPY]], $noreg, undef [[MVE_VORR1]] + ; CHECK-NEXT: tBX_RET 14 /* CC::al */, $noreg, implicit [[DEF1]] + %0:tgpreven = t2MOVi 0, 14, $noreg, $noreg + %1:vccr = COPY %0:tgpreven + %2:mqpr = IMPLICIT_DEF + %3:mqpr = MVE_VORR %2:mqpr, %2:mqpr, 1, killed %1, $noreg, undef %3 + %4:vccr = COPY %0:tgpreven + %5:mqpr = IMPLICIT_DEF + %6:mqpr = MVE_VORR %5:mqpr, %5:mqpr, 1, killed %4, $noreg, undef %6 + tBX_RET 14 /* CC::al */, $noreg, implicit %5:mqpr + +... diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj-options.ll b/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj-options.ll index aa4d87756c87d0a66f4b3637a1fca6f6b7670e68..4a63c812d6ae9ac0d40fb66fa17d8ddddfd2af5e 100644 --- a/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj-options.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj-options.ll @@ -59,12 +59,12 @@ entry: %call = call i32 @setjmp(ptr %buf) #0 call void @longjmp(ptr %buf, i32 1) #1 unreachable -; SJLJ: call saveSetjmp +; SJLJ: call __wasm_setjmp ; SJLJ: i32.const emscripten_longjmp ; SJLJ-NOT: i32.const emscripten_longjmp_jmpbuf ; SJLJ: call invoke_vii ; SJLJ-NOT: call "__invoke_void_ptr_i32" -; SJLJ: call testSetjmp +; SJLJ: call __wasm_setjmp_test ; NONE: call setjmp ; NONE: call longjmp diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll b/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll index 7cf05cc922cd370f084207c3d87b52d7e572e2a7..32942cd92e684f880188fdce1d34e4d854071302 100644 --- a/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll @@ -49,7 +49,7 @@ try.cont: ; preds = %lpad, %entry ; longjmp checking part ; CHECK: if.then1: -; CHECK: call i32 @testSetjmp +; CHECK: call i32 @__wasm_setjmp_test } ; @foo can either throw an exception or longjmp. Because this function doesn't @@ -117,7 +117,6 @@ if.end: ; preds = %entry ; CHECK: rethrow.exn: ; CHECK-NEXT: %exn = call ptr @__cxa_find_matching_catch_2() -; CHECK-NEXT: call void @free(ptr %setjmpTable{{.*}}) ; CHECK-NEXT: call void @__resumeException(ptr %exn) ; CHECK-NEXT: unreachable @@ -147,7 +146,6 @@ throw: ; preds = %if.end, %entry unreachable ; CHECK: throw: -; CHECK-NEXT: call void @free(ptr %setjmpTable{{.*}}) ; CHECK-NEXT: call void @__cxa_throw(ptr null, ptr null, ptr null) ; CHECK-NEXT: unreachable } @@ -208,7 +206,6 @@ return: ; preds = %entry, %if.end ; CHECK: rethrow.exn: ; CHECK-NEXT: %exn = call ptr @__cxa_find_matching_catch_2() -; CHECK-NEXT: tail call void @free(ptr %setjmpTable{{.*}}) ; CHECK-NEXT: call void @__resumeException(ptr %exn) ; CHECK-NEXT: unreachable } diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-alias.ll b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-alias.ll index 1a85a63e44ad4b312353917d7a1c7a3472b9c203..79ae16191d6b3cdd017c5ccfca7e8ad38edd83ac 100644 --- a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-alias.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-alias.ll @@ -12,7 +12,7 @@ target triple = "wasm32-unknown-emscripten" ; CHECK-LABEL: @malloc_test define void @malloc_test() { entry: - ; CHECK: call ptr @malloc + ; CHECK: alloca i32 %retval = alloca i32, align 4 %jmp = alloca [1 x %struct.__jmp_buf_tag], align 16 store i32 0, ptr %retval, align 4 diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-debuginfo.ll b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-debuginfo.ll index 4f694151c7613264db5c1ffacd010351679399b7..fec9836a1607c5be1d52ab96a5f47716851f01df 100644 --- a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-debuginfo.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-debuginfo.ll @@ -16,25 +16,22 @@ entry: call void @foo(), !dbg !7 ret void, !dbg !8 ; CHECK: entry: - ; CHECK-NEXT: call ptr @malloc(i32 40), !dbg ![[DL0:.*]] + ; CHECK-NEXT: %functionInvocationId = alloca i32, align 4, !dbg ![[DL0:.*]] ; CHECK: entry.split: ; CHECK: alloca {{.*}}, !dbg ![[DL0]] - ; CHECK: call ptr @saveSetjmp{{.*}}, !dbg ![[DL1:.*]] - ; CHECK-NEXT: call i32 @getTempRet0{{.*}}, !dbg ![[DL1]] + ; CHECK: call void @__wasm_setjmp{{.*}}, !dbg ![[DL1:.*]] ; CHECK-NEXT: br {{.*}}, !dbg ![[DL2:.*]] ; CHECK: entry.split.split: ; CHECK: call {{.*}} void @__invoke_void{{.*}}, !dbg ![[DL2]] ; CHECK: entry.split.split.split: - ; CHECK-NEXT: call void @free{{.*}}, !dbg ![[DL3:.*]] ; CHECK: if.then1: - ; CHECK: call i32 @testSetjmp{{.*}}, !dbg ![[DL2]] + ; CHECK: call i32 @__wasm_setjmp_test{{.*}}, !dbg ![[DL2]] ; CHECK: if.end: - ; CHECK: call i32 @getTempRet0{{.*}}, !dbg ![[DL2]] ; CHECK: call.em.longjmp: ; CHECK: call void @emscripten_longjmp{{.*}}, !dbg ![[DL2]] @@ -43,26 +40,6 @@ entry: ; CHECK: call void @setTempRet0{{.*}}, !dbg ![[DL2]] } -; No instruction has debug info but the current function (setjmp_debug_info2) -; and the called function (malloc / free) have DISubprograms, so the newly -; generated calls should have debug info attached. We don't have an instruction -; to take debug info from, so we create dummy debug info. -define void @setjmp_debug_info1() !dbg !9 { -; CHECK-LABEL: @setjmp_debug_info1 -entry: - %buf = alloca [1 x %struct.__jmp_buf_tag], align 16 - %arraydecay = getelementptr inbounds [1 x %struct.__jmp_buf_tag], ptr %buf, i32 0, i32 0 - %call = call i32 @setjmp(ptr %arraydecay) #0 - call void @foo() - ret void - ; CHECK: call ptr @malloc(i32 40), !dbg ![[DL_DUMMY:.*]] - ; CHECK: call void @free{{.*}}, !dbg ![[DL_DUMMY]] -} - -; Note that these functions have DISubprograms. -declare !dbg !10 ptr @malloc(i32) -declare !dbg !11 void @free(ptr) - declare void @foo() ; Function Attrs: returns_twice declare i32 @setjmp(ptr) #0 @@ -79,9 +56,3 @@ declare i32 @setjmp(ptr) #0 !6 = !DILocation(line:4, scope: !3) !7 = !DILocation(line:5, scope: !3) !8 = !DILocation(line:6, scope: !3) -!9 = distinct !DISubprogram(name: "setjmp_debug_info1", unit:!2, file: !1, line: 50) -!10 = !DISubprogram(name: "malloc", file: !1, line: 10, isDefinition: false) -!11 = !DISubprogram(name: "free", file: !1, line: 20, isDefinition: false) - -; Dummy debug info generated -; CHECK: ![[DL_DUMMY]] = !DILocation(line: 50, column: 1, scope: !9) diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll index 7115b01ed1618e92197f95e1c416887181c1f3a4..27ec95a2c462ab19d6c2096dcceff21e7af98d74 100644 --- a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll @@ -22,15 +22,12 @@ entry: call void @longjmp(ptr %buf, i32 1) #1 unreachable ; CHECK: entry: -; CHECK-NEXT: %[[MALLOCCALL:.*]] = tail call ptr @malloc([[PTR]] 40) -; CHECK-NEXT: store i32 0, ptr %[[MALLOCCALL]] -; CHECK-NEXT: %[[SETJMP_TABLE_SIZE:.*]] = add i32 4, 0 +; CHECK-NEXT: %functionInvocationId = alloca i32, align 4 ; CHECK-NEXT: br label %entry.split ; CHECK: entry.split ; CHECK-NEXT: %[[BUF:.*]] = alloca [1 x %struct.__jmp_buf_tag] -; CHECK-NEXT: %[[SETJMP_TABLE1:.*]] = call ptr @saveSetjmp(ptr %[[BUF]], i32 1, ptr %[[MALLOCCALL]], i32 %[[SETJMP_TABLE_SIZE]]) -; CHECK-NEXT: %[[SETJMP_TABLE_SIZE1:.*]] = call i32 @getTempRet0() +; CHECK-NEXT: call void @__wasm_setjmp(ptr %[[BUF]], i32 1, ptr %functionInvocationId) ; CHECK-NEXT: br label %entry.split.split ; CHECK: entry.split.split: @@ -51,8 +48,7 @@ entry: ; CHECK: if.then1: ; CHECK-NEXT: %[[__THREW__VAL_P:.*]] = inttoptr [[PTR]] %[[__THREW__VAL]] to ptr -; CHECK-NEXT: %[[__THREW__VAL_P_LOADED:.*]] = load [[PTR]], ptr %[[__THREW__VAL_P]] -; CHECK-NEXT: %[[LABEL:.*]] = call i32 @testSetjmp([[PTR]] %[[__THREW__VAL_P_LOADED]], ptr %[[SETJMP_TABLE1]], i32 %[[SETJMP_TABLE_SIZE1]]) +; CHECK-NEXT: %[[LABEL:.*]] = call i32 @__wasm_setjmp_test(ptr %[[__THREW__VAL_P]], ptr %functionInvocationId) ; CHECK-NEXT: %[[CMP:.*]] = icmp eq i32 %[[LABEL]], 0 ; CHECK-NEXT: br i1 %[[CMP]], label %call.em.longjmp, label %if.end2 @@ -69,7 +65,6 @@ entry: ; CHECK: call.em.longjmp: ; CHECK-NEXT: %threw.phi = phi [[PTR]] [ %[[__THREW__VAL]], %if.then1 ] ; CHECK-NEXT: %threwvalue.phi = phi i32 [ %[[THREWVALUE_VAL]], %if.then1 ] -; CHECK-NEXT: tail call void @free(ptr %[[SETJMP_TABLE1]]) ; CHECK-NEXT: call void @emscripten_longjmp([[PTR]] %threw.phi, i32 %threwvalue.phi) ; CHECK-NEXT: unreachable @@ -87,13 +82,12 @@ entry: call void @foo() ret void ; CHECK: entry: -; CHECK: %[[SETJMP_TABLE:.*]] = call ptr @saveSetjmp( +; CHECK: call void @__wasm_setjmp( ; CHECK: entry.split.split: ; CHECK: @__invoke_void(ptr @foo) ; CHECK: entry.split.split.split: -; CHECK-NEXT: tail call void @free(ptr %[[SETJMP_TABLE]]) ; CHECK-NEXT: ret void } @@ -110,9 +104,8 @@ entry: call void @foo() ret void ; CHECK: call.em.longjmp: -; CHECK-NEXT: %threw.phi = phi [[PTR]] [ %__THREW__.val, %if.then1 ], [ %__THREW__.val4, %if.then15 ] -; CHECK-NEXT: %threwvalue.phi = phi i32 [ %__threwValue.val, %if.then1 ], [ %__threwValue.val8, %if.then15 ] -; CHECK-NEXT: tail call void @free(ptr %[[SETJMP_TABLE1]]) +; CHECK-NEXT: %threw.phi = phi [[PTR]] [ %__THREW__.val, %if.then1 ], [ %__THREW__.val2, %if.then13 ] +; CHECK-NEXT: %threwvalue.phi = phi i32 [ %__threwValue.val, %if.then1 ], [ %__threwValue.val6, %if.then13 ] ; CHECK-NEXT: call void @emscripten_longjmp([[PTR]] %threw.phi, i32 %threwvalue.phi) ; CHECK-NEXT: unreachable } @@ -145,7 +138,6 @@ entry: %cmp = icmp sgt i32 %n, 5 br i1 %cmp, label %if.then, label %if.end ; CHECK: entry: -; CHECK: %[[SETJMP_TABLE_SIZE0:.*]] = add i32 4, 0 if.then: ; preds = %entry %0 = load i32, ptr @global_var, align 4 @@ -154,13 +146,10 @@ if.then: ; preds = %entry br label %if.end ; CHECK: if.then: ; CHECK: %[[VAR0:.*]] = load i32, ptr @global_var, align 4 -; CHECK: %[[SETJMP_TABLE1:.*]] = call ptr @saveSetjmp( -; CHECK-NEXT: %[[SETJMP_TABLE_SIZE1:.*]] = call i32 @getTempRet0() +; CHECK: call void @__wasm_setjmp( ; CHECK: if.then.split: -; CHECK: %[[VAR1:.*]] = phi i32 [ %[[VAR2:.*]], %if.end3 ], [ %[[VAR0]], %if.then ] -; CHECK: %[[SETJMP_TABLE_SIZE2:.*]] = phi i32 [ %[[SETJMP_TABLE_SIZE1]], %if.then ], [ %[[SETJMP_TABLE_SIZE3:.*]], %if.end3 ] -; CHECK: %[[SETJMP_TABLE2:.*]] = phi ptr [ %[[SETJMP_TABLE1]], %if.then ], [ %[[SETJMP_TABLE3:.*]], %if.end3 ] +; CHECK: %[[VAR1:.*]] = phi i32 [ %[[VAR2:.*]], %if.end1 ], [ %[[VAR0]], %if.then ] ; CHECK: store i32 %[[VAR1]], ptr @global_var, align 4 if.end: ; preds = %if.then, %entry @@ -168,8 +157,6 @@ if.end: ; preds = %if.then, %entry unreachable ; CHECK: if.end: ; CHECK: %[[VAR2]] = phi i32 [ %[[VAR1]], %if.then.split ], [ undef, %entry.split ] -; CHECK: %[[SETJMP_TABLE_SIZE3]] = phi i32 [ %[[SETJMP_TABLE_SIZE2]], %if.then.split ], [ %[[SETJMP_TABLE_SIZE0]], %entry.split ] -; CHECK: %[[SETJMP_TABLE3]] = phi ptr [ %[[SETJMP_TABLE2]], %if.then.split ], [ %setjmpTable, %entry.split ] } ; Test a case when a function only calls other functions that are neither setjmp nor longjmp @@ -296,8 +283,8 @@ declare void @free(ptr) ; JS glue functions and invoke wrappers declaration ; CHECK-DAG: declare i32 @getTempRet0() ; CHECK-DAG: declare void @setTempRet0(i32) -; CHECK-DAG: declare ptr @saveSetjmp(ptr, i32, ptr, i32) -; CHECK-DAG: declare i32 @testSetjmp([[PTR]], ptr, i32) +; CHECK-DAG: declare void @__wasm_setjmp(ptr, i32, ptr) +; CHECK-DAG: declare i32 @__wasm_setjmp_test(ptr, ptr) ; CHECK-DAG: declare void @emscripten_longjmp([[PTR]], i32) ; CHECK-DAG: declare void @__invoke_void(ptr) @@ -308,8 +295,8 @@ attributes #3 = { allocsize(0) } ; CHECK-DAG: attributes #{{[0-9]+}} = { nounwind "wasm-import-module"="env" "wasm-import-name"="getTempRet0" } ; CHECK-DAG: attributes #{{[0-9]+}} = { nounwind "wasm-import-module"="env" "wasm-import-name"="setTempRet0" } ; CHECK-DAG: attributes #{{[0-9]+}} = { "wasm-import-module"="env" "wasm-import-name"="__invoke_void" } -; CHECK-DAG: attributes #{{[0-9]+}} = { "wasm-import-module"="env" "wasm-import-name"="saveSetjmp" } -; CHECK-DAG: attributes #{{[0-9]+}} = { "wasm-import-module"="env" "wasm-import-name"="testSetjmp" } +; CHECK-DAG: attributes #{{[0-9]+}} = { "wasm-import-module"="env" "wasm-import-name"="__wasm_setjmp" } +; CHECK-DAG: attributes #{{[0-9]+}} = { "wasm-import-module"="env" "wasm-import-name"="__wasm_setjmp_test" } ; CHECK-DAG: attributes #{{[0-9]+}} = { noreturn "wasm-import-module"="env" "wasm-import-name"="emscripten_longjmp" } ; CHECK-DAG: attributes #{{[0-9]+}} = { "wasm-import-module"="env" "wasm-import-name"="__invoke_ptr_i32_ptr" } ; CHECK-DAG: attributes #[[ALLOCSIZE_ATTR]] = { allocsize(1) } diff --git a/llvm/test/CodeGen/WebAssembly/lower-wasm-ehsjlj.ll b/llvm/test/CodeGen/WebAssembly/lower-wasm-ehsjlj.ll index 25471eb50081b39171e9ed2f75810622ba384d39..bd8db83a0e57ed7cb71ef8acb2d4a390b548cfea 100644 --- a/llvm/test/CodeGen/WebAssembly/lower-wasm-ehsjlj.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-wasm-ehsjlj.ll @@ -108,8 +108,8 @@ catch: ; preds = %catch.start call void @__cxa_end_catch() [ "funclet"(token %2) ] catchret from %2 to label %catchret.dest ; CHECK: catch: ; preds = %catch.start -; CHECK-NEXT: %exn = load ptr, ptr %exn.slot15, align 4 -; CHECK-NEXT: %5 = call ptr @__cxa_begin_catch(ptr %exn) #7 [ "funclet"(token %2) ] +; CHECK-NEXT: %exn = load ptr, ptr %exn.slot6, align 4 +; CHECK-NEXT: %5 = call ptr @__cxa_begin_catch(ptr %exn) #6 [ "funclet"(token %2) ] ; CHECK-NEXT: invoke void @__cxa_end_catch() [ "funclet"(token %2) ] ; CHECK-NEXT: to label %.noexc unwind label %catch.dispatch.longjmp @@ -265,7 +265,7 @@ ehcleanup: ; preds = %entry ; (cleanuppad), whose parent is 'none', so we should unwind directly to ; %catch.dispatch.longjmp. %call2 = call noundef ptr @_ZN4TempD2Ev(ptr noundef %t) #2 [ "funclet"(token %0) ] -; CHECK: %call13 = invoke {{.*}} ptr @_ZN4TempD2Ev(ptr +; CHECK: %call11 = invoke {{.*}} ptr @_ZN4TempD2Ev(ptr ; CHECK-NEXT: to label {{.*}} unwind label %catch.dispatch.longjmp cleanupret from %0 unwind to caller } diff --git a/llvm/test/CodeGen/WebAssembly/lower-wasm-sjlj.ll b/llvm/test/CodeGen/WebAssembly/lower-wasm-sjlj.ll index b8d2230fac9f5bb33bd4cbac1d56d10da95dcfa0..82c04e24b72f13bd3dea76f38d108f1915793eb7 100644 --- a/llvm/test/CodeGen/WebAssembly/lower-wasm-sjlj.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-wasm-sjlj.ll @@ -25,16 +25,12 @@ entry: unreachable ; CHECK: entry: -; CHECK-NEXT: %setjmpTable = tail call ptr @malloc([[PTR]] 40) -; CHECK-NEXT: store i32 0, ptr %setjmpTable, align 4 -; CHECK-NEXT: %setjmpTableSize = add i32 4, 0 +; CHECK-NEXT: %functionInvocationId = alloca i32, align 4 ; CHECK-NEXT: br label %setjmp.dispatch ; CHECK: setjmp.dispatch: ; CHECK-NEXT: %[[VAL2:.*]] = phi i32 [ %val, %if.end ], [ undef, %entry ] ; CHECK-NEXT: %[[BUF:.*]] = phi ptr [ %[[BUF2:.*]], %if.end ], [ undef, %entry ] -; CHECK-NEXT: %[[SETJMPTABLESIZE2:.*]] = phi i32 [ %[[SETJMPTABLESIZE3:.*]], %if.end ], [ %setjmpTableSize, %entry ] -; CHECK-NEXT: %[[SETJMPTABLE2:.*]] = phi ptr [ %[[SETJMPTABLE3:.*]], %if.end ], [ %setjmpTable, %entry ] ; CHECK-NEXT: %label.phi = phi i32 [ %label, %if.end ], [ -1, %entry ] ; CHECK-NEXT: switch i32 %label.phi, label %entry.split [ ; CHECK-NEXT: i32 1, label %entry.split.split @@ -42,14 +38,11 @@ entry: ; CHECK: entry.split: ; CHECK-NEXT: %buf = alloca [1 x %struct.__jmp_buf_tag], align 16 -; CHECK-NEXT: %[[SETJMPTABLE4:.*]] = call ptr @saveSetjmp(ptr %buf, i32 1, ptr %[[SETJMPTABLE2]], i32 %[[SETJMPTABLESIZE2]]) -; CHECK-NEXT: %[[SETJMPTABLESIZE4:.*]] = call i32 @getTempRet0() +; CHECK-NEXT: call void @__wasm_setjmp(ptr %buf, i32 1, ptr %functionInvocationId) ; CHECK-NEXT: br label %entry.split.split ; CHECK: entry.split.split: ; CHECK-NEXT: %[[BUF2]] = phi ptr [ %[[BUF]], %setjmp.dispatch ], [ %buf, %entry.split ] -; CHECK-NEXT: %[[SETJMPTABLESIZE3]] = phi i32 [ %[[SETJMPTABLESIZE4]], %entry.split ], [ %[[SETJMPTABLESIZE2]], %setjmp.dispatch ] -; CHECK-NEXT: %[[SETJMPTABLE3]] = phi ptr [ %[[SETJMPTABLE4]], %entry.split ], [ %[[SETJMPTABLE2]], %setjmp.dispatch ] ; CHECK-NEXT: %setjmp.ret = phi i32 [ 0, %entry.split ], [ %[[VAL2]], %setjmp.dispatch ] ; CHECK-NEXT: invoke void @__wasm_longjmp(ptr %[[BUF2]], i32 1) ; CHECK-NEXT: to label %.noexc unwind label %catch.dispatch.longjmp @@ -67,13 +60,11 @@ entry: ; CHECK-NEXT: %val_gep = getelementptr { ptr, i32 }, ptr %thrown, i32 0, i32 1 ; CHECK-NEXT: %env = load ptr, ptr %env_gep, align {{.*}} ; CHECK-NEXT: %val = load i32, ptr %val_gep, align 4 -; CHECK-NEXT: %setjmp.id = load [[PTR]], ptr %env, align {{.*}} -; CHECK-NEXT: %label = call i32 @testSetjmp([[PTR]] %setjmp.id, ptr %[[SETJMPTABLE3]], i32 %[[SETJMPTABLESIZE3]]) [ "funclet"(token %1) ] +; CHECK-NEXT: %label = call i32 @__wasm_setjmp_test(ptr %env, ptr %functionInvocationId) [ "funclet"(token %1) ] ; CHECK-NEXT: %2 = icmp eq i32 %label, 0 ; CHECK-NEXT: br i1 %2, label %if.then, label %if.end ; CHECK: if.then: -; CHECK-NEXT: tail call void @free(ptr %[[SETJMPTABLE3]]) [ "funclet"(token %1) ] ; CHECK-NEXT: call void @__wasm_longjmp(ptr %env, i32 %val) [ "funclet"(token %1) ] ; CHECK-NEXT: unreachable @@ -142,10 +133,9 @@ declare ptr @__cxa_begin_catch(ptr) declare void @__cxa_end_catch() declare void @free(ptr) -; JS glue function declarations -; CHECK-DAG: declare i32 @getTempRet0() -; CHECK-DAG: declare ptr @saveSetjmp(ptr, i32, ptr, i32) -; CHECK-DAG: declare i32 @testSetjmp([[PTR]], ptr, i32) +; Runtime glue function declarations +; CHECK-DAG: declare void @__wasm_setjmp(ptr, i32, ptr) +; CHECK-DAG: declare i32 @__wasm_setjmp_test(ptr, ptr) ; CHECK-DAG: declare void @__wasm_longjmp(ptr, i32) attributes #0 = { returns_twice } diff --git a/llvm/test/CodeGen/WebAssembly/pr63817.ll b/llvm/test/CodeGen/WebAssembly/pr63817.ll new file mode 100644 index 0000000000000000000000000000000000000000..252768d43f188896e8baa9078ff917370cdd2c77 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/pr63817.ll @@ -0,0 +1,15 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=wasm32 -mattr=+simd128 | FileCheck %s + +;; Regression test for a bug in which BUILD_VECTOR nodes with large unsigned +;; lane constants were not properly selected. +define <4 x i8> @test(<4 x i8> %0) { +; CHECK-LABEL: test: +; CHECK: .functype test (v128) -> (v128) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: v128.const 255, 17, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +; CHECK-NEXT: # fallthrough-return + %V1 = or <4 x i8> <i8 255, i8 255, i8 255, i8 255>, %0 + %V2 = insertelement <4 x i8> %V1, i8 17, i32 1 + ret <4 x i8> %V2 +} diff --git a/llvm/test/CodeGen/WinCFGuard/cfguard-mingw.ll b/llvm/test/CodeGen/WinCFGuard/cfguard-mingw.ll index 085cde8c61693a4f5dab3dabf30151ac5a284ec1..7a5baa09f95e94c87a1a17332a697c20ff4764f4 100644 --- a/llvm/test/CodeGen/WinCFGuard/cfguard-mingw.ll +++ b/llvm/test/CodeGen/WinCFGuard/cfguard-mingw.ll @@ -97,7 +97,7 @@ $_ZTI7Derived = comdat any ; Function Attrs: nounwind uwtable define weak_odr dso_local dllexport void @_ZN4BaseC2Ev(ptr noundef nonnull align 8 dereferenceable(12) %0) unnamed_addr #0 comdat align 2 { - store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV4Base, i64 0, inrange i32 0, i64 2), ptr %0, align 8, !tbaa !5 + store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV4Base, i64 0, i32 0, i64 2), ptr %0, align 8, !tbaa !5 %2 = getelementptr inbounds %class.Base, ptr %0, i64 0, i32 1 store i32 0, ptr %2, align 8, !tbaa !8 ret void @@ -105,7 +105,7 @@ define weak_odr dso_local dllexport void @_ZN4BaseC2Ev(ptr noundef nonnull align ; Function Attrs: nounwind uwtable define weak_odr dso_local dllexport void @_ZN4BaseC1Ev(ptr noundef nonnull align 8 dereferenceable(12) %0) unnamed_addr #0 comdat align 2 { - store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV4Base, i64 0, inrange i32 0, i64 2), ptr %0, align 8, !tbaa !5 + store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV4Base, i64 0, i32 0, i64 2), ptr %0, align 8, !tbaa !5 %2 = getelementptr inbounds %class.Base, ptr %0, i64 0, i32 1 store i32 0, ptr %2, align 8, !tbaa !8 ret void @@ -140,10 +140,10 @@ declare dso_local void @_ZdlPv(ptr noundef) local_unnamed_addr #2 ; Function Attrs: nounwind uwtable define weak_odr dso_local dllexport void @_ZN7DerivedC2Ev(ptr noundef nonnull align 8 dereferenceable(16) %0) unnamed_addr #0 comdat align 2 { - store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV4Base, i64 0, inrange i32 0, i64 2), ptr %0, align 8, !tbaa !5 + store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV4Base, i64 0, i32 0, i64 2), ptr %0, align 8, !tbaa !5 %2 = getelementptr inbounds %class.Base, ptr %0, i64 0, i32 1 store i32 0, ptr %2, align 8, !tbaa !8 - store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV7Derived, i64 0, inrange i32 0, i64 2), ptr %0, align 8, !tbaa !5 + store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV7Derived, i64 0, i32 0, i64 2), ptr %0, align 8, !tbaa !5 %3 = getelementptr inbounds %class.Derived, ptr %0, i64 0, i32 1 store i32 0, ptr %3, align 4, !tbaa !12 ret void @@ -151,10 +151,10 @@ define weak_odr dso_local dllexport void @_ZN7DerivedC2Ev(ptr noundef nonnull al ; Function Attrs: nounwind uwtable define weak_odr dso_local dllexport void @_ZN7DerivedC1Ev(ptr noundef nonnull align 8 dereferenceable(16) %0) unnamed_addr #0 comdat align 2 { - store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV4Base, i64 0, inrange i32 0, i64 2), ptr %0, align 8, !tbaa !5 + store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV4Base, i64 0, i32 0, i64 2), ptr %0, align 8, !tbaa !5 %2 = getelementptr inbounds %class.Base, ptr %0, i64 0, i32 1 store i32 0, ptr %2, align 8, !tbaa !8 - store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV7Derived, i64 0, inrange i32 0, i64 2), ptr %0, align 8, !tbaa !5 + store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV7Derived, i64 0, i32 0, i64 2), ptr %0, align 8, !tbaa !5 %3 = getelementptr inbounds %class.Derived, ptr %0, i64 0, i32 1 store i32 0, ptr %3, align 4, !tbaa !12 ret void diff --git a/llvm/test/CodeGen/X86/2009-06-05-VariableIndexInsert.ll b/llvm/test/CodeGen/X86/2009-06-05-VariableIndexInsert.ll index 535450a52ff60e74b8c2f67ae7ade17b2eb32e33..695a2d0cd806e054ed5aa8fa9664b410bfd36aca 100644 --- a/llvm/test/CodeGen/X86/2009-06-05-VariableIndexInsert.ll +++ b/llvm/test/CodeGen/X86/2009-06-05-VariableIndexInsert.ll @@ -9,11 +9,11 @@ define <2 x i64> @_mm_insert_epi16(<2 x i64> %a, i32 %b, i32 %imm) nounwind read ; X86-NEXT: movl %esp, %ebp ; X86-NEXT: andl $-16, %esp ; X86-NEXT: subl $32, %esp -; X86-NEXT: movzwl 8(%ebp), %eax -; X86-NEXT: movl 12(%ebp), %ecx -; X86-NEXT: andl $7, %ecx +; X86-NEXT: movl 12(%ebp), %eax +; X86-NEXT: movzwl 8(%ebp), %ecx +; X86-NEXT: andl $7, %eax ; X86-NEXT: movaps %xmm0, (%esp) -; X86-NEXT: movw %ax, (%esp,%ecx,2) +; X86-NEXT: movw %cx, (%esp,%eax,2) ; X86-NEXT: movaps (%esp), %xmm0 ; X86-NEXT: movl %ebp, %esp ; X86-NEXT: popl %ebp diff --git a/llvm/test/CodeGen/X86/GlobalISel/legalize-icmp-vec.mir b/llvm/test/CodeGen/X86/GlobalISel/legalize-icmp-vec.mir new file mode 100644 index 0000000000000000000000000000000000000000..e0fb0fc9d11d3c0df70983ed88ef1659b7e632c9 --- /dev/null +++ b/llvm/test/CodeGen/X86/GlobalISel/legalize-icmp-vec.mir @@ -0,0 +1,25 @@ +# RUN: llc -mtriple=x86_64-linux-gnu -run-pass=legalizer -global-isel-abort=2 -pass-remarks-missed='gisel*' %s -o - 2>%t | FileCheck %s +# RUN: FileCheck -check-prefix=ILLEGAL %s < %t + +# ILLEGAL: remark: <unknown>:0:0: unable to legalize instruction: %2:_(<4 x s1>) = G_ICMP intpred(sle), %0:_(<4 x s64>), %1:_ (in function: test_icmp_v4i64) + +# PR86203 +--- +name: test_icmp_v4i64 +tracksRegLiveness: true +body: | + bb.1: + ; CHECK-LABEL: name: test_icmp_v4i64 + ; CHECK: [[DEF:%[0-9]+]]:_(<4 x s64>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(<4 x s64>) = G_IMPLICIT_DEF + ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(<4 x s1>) = G_ICMP intpred(sle), [[DEF]](<4 x s64>), [[DEF1]] + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(<4 x s32>) = G_ANYEXT [[ICMP]](<4 x s1>) + ; CHECK-NEXT: $xmm0 = COPY [[ANYEXT]](<4 x s32>) + ; CHECK-NEXT: RET 0, implicit $xmm0 + %0:_(<4 x s64>) = G_IMPLICIT_DEF + %1:_(<4 x s64>) = G_IMPLICIT_DEF + %3:_(<4 x s1>) = G_ICMP intpred(sle), %0(<4 x s64>), %1 + %4:_(<4 x s32>) = G_ANYEXT %3(<4 x s1>) + $xmm0 = COPY %4(<4 x s32>) + RET 0, implicit $xmm0 +... diff --git a/llvm/test/CodeGen/X86/GlobalISel/x86-select-trap.mir b/llvm/test/CodeGen/X86/GlobalISel/x86-select-trap.mir index ea548c296dcaf63fe435ad523cc1a9296893ffeb..20b8b671ac5a5312a7086acebb3e641e154cea12 100644 --- a/llvm/test/CodeGen/X86/GlobalISel/x86-select-trap.mir +++ b/llvm/test/CodeGen/X86/GlobalISel/x86-select-trap.mir @@ -23,6 +23,6 @@ body: | bb.1 (%ir-block.0): ; CHECK-LABEL: name: trap ; CHECK: TRAP - G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.trap) + G_TRAP ... diff --git a/llvm/test/CodeGen/X86/addcarry.ll b/llvm/test/CodeGen/X86/addcarry.ll index 3fc4ed99fad0fa89851a03ae506003522d1d2b86..f8d32fc2d29252cb2aadacdd914258a7ad9e5384 100644 --- a/llvm/test/CodeGen/X86/addcarry.ll +++ b/llvm/test/CodeGen/X86/addcarry.ll @@ -1490,3 +1490,26 @@ define { i64, i64 } @addcarry_commutative_2(i64 %x0, i64 %x1, i64 %y0, i64 %y1) %r1 = insertvalue { i64, i64 } %r0, i64 %b1s, 1 ret { i64, i64 } %r1 } + +define i1 @pr84831(i64 %arg) { +; CHECK-LABEL: pr84831: +; CHECK: # %bb.0: +; CHECK-NEXT: testq %rdi, %rdi +; CHECK-NEXT: setne %al +; CHECK-NEXT: xorl %ecx, %ecx +; CHECK-NEXT: addb $-1, %al +; CHECK-NEXT: adcq $1, %rcx +; CHECK-NEXT: setb %al +; CHECK-NEXT: retq + %a = icmp ult i64 0, %arg + %add1 = add i64 0, 1 + %carryout1 = icmp ult i64 %add1, 0 + %b = zext i1 %a to i64 + %add2 = add i64 %add1, %b + %carryout2 = icmp ult i64 %add2, %add1 + %zc1 = zext i1 %carryout1 to i63 + %zc2 = zext i1 %carryout2 to i63 + %or = or i63 %zc1, %zc2 + %trunc = trunc i63 %or to i1 + ret i1 %trunc +} diff --git a/llvm/test/CodeGen/X86/allow-check.ll b/llvm/test/CodeGen/X86/allow-check.ll new file mode 100644 index 0000000000000000000000000000000000000000..602e5a94ee3ee293646eaa2341a71e18800ce32f --- /dev/null +++ b/llvm/test/CodeGen/X86/allow-check.ll @@ -0,0 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=x86_64 -global-isel=0 -fast-isel=0 | FileCheck %s +; RUN: llc < %s -mtriple=x86_64 -global-isel=1 -fast-isel=0 | FileCheck %s +; RUN: llc < %s -mtriple=x86_64 -global-isel=0 -fast-isel=1 | FileCheck %s + +define i1 @test_runtime() local_unnamed_addr { +; CHECK-LABEL: test_runtime: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: movb $1, %al +; CHECK-NEXT: retq +entry: + %allow = call i1 @llvm.allow.runtime.check(metadata !"test_check") + ret i1 %allow +} + +declare i1 @llvm.allow.runtime.check(metadata) nounwind + +define i1 @test_ubsan() local_unnamed_addr { +; CHECK-LABEL: test_ubsan: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: movb $1, %al +; CHECK-NEXT: retq +entry: + %allow = call i1 @llvm.allow.ubsan.check(i8 7) + ret i1 %allow +} + +declare i1 @llvm.allow.ubsan.check(i8) nounwind diff --git a/llvm/test/CodeGen/X86/apx/add.ll b/llvm/test/CodeGen/X86/apx/add.ll index cdb29a70770e4b45831c0ee368aad0cbcd301bc9..d3301ecdb72d0f21dfa3ecc73483ee0e683ed730 100644 --- a/llvm/test/CodeGen/X86/apx/add.ll +++ b/llvm/test/CodeGen/X86/apx/add.ll @@ -298,9 +298,9 @@ define i8 @addflag8rr(i8 noundef %a, i8 noundef %b) { ; CHECK-LABEL: addflag8rr: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: addb %sil, %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x00,0xf7] -; CHECK-NEXT: movzbl %al, %ecx # encoding: [0x0f,0xb6,0xc8] -; CHECK-NEXT: movl $255, %eax # encoding: [0xb8,0xff,0x00,0x00,0x00] -; CHECK-NEXT: cmovael %ecx, %eax # encoding: [0x0f,0x43,0xc1] +; CHECK-NEXT: movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0] +; CHECK-NEXT: movl $255, %ecx # encoding: [0xb9,0xff,0x00,0x00,0x00] +; CHECK-NEXT: cmovbl %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x42,0xc1] ; CHECK-NEXT: # kill: def $al killed $al killed $eax ; CHECK-NEXT: retq # encoding: [0xc3] entry: @@ -311,10 +311,10 @@ entry: define i16 @addflag16rr(i16 noundef %a, i16 noundef %b) { ; CHECK-LABEL: addflag16rr: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addw %si, %di, %cx # encoding: [0x62,0xf4,0x75,0x18,0x01,0xf7] -; CHECK-NEXT: movl $65535, %eax # encoding: [0xb8,0xff,0xff,0x00,0x00] +; CHECK-NEXT: addw %si, %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x01,0xf7] +; CHECK-NEXT: movl $65535, %ecx # encoding: [0xb9,0xff,0xff,0x00,0x00] ; CHECK-NEXT: # imm = 0xFFFF -; CHECK-NEXT: cmovael %ecx, %eax # encoding: [0x0f,0x43,0xc1] +; CHECK-NEXT: cmovbl %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x42,0xc1] ; CHECK-NEXT: # kill: def $ax killed $ax killed $eax ; CHECK-NEXT: retq # encoding: [0xc3] entry: @@ -325,9 +325,9 @@ entry: define i32 @addflag32rr(i32 noundef %a, i32 noundef %b) { ; CHECK-LABEL: addflag32rr: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addl %esi, %edi, %ecx # encoding: [0x62,0xf4,0x74,0x18,0x01,0xf7] -; CHECK-NEXT: movl $-1, %eax # encoding: [0xb8,0xff,0xff,0xff,0xff] -; CHECK-NEXT: cmovael %ecx, %eax # encoding: [0x0f,0x43,0xc1] +; CHECK-NEXT: addl %esi, %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x01,0xf7] +; CHECK-NEXT: movl $-1, %ecx # encoding: [0xb9,0xff,0xff,0xff,0xff] +; CHECK-NEXT: cmovbl %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x42,0xc1] ; CHECK-NEXT: retq # encoding: [0xc3] entry: %add = call i32 @llvm.uadd.sat.i32(i32 %a, i32 %b) @@ -337,9 +337,9 @@ entry: define i64 @addflag64rr(i64 noundef %a, i64 noundef %b) { ; CHECK-LABEL: addflag64rr: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addq %rsi, %rdi, %rcx # encoding: [0x62,0xf4,0xf4,0x18,0x01,0xf7] -; CHECK-NEXT: movq $-1, %rax # encoding: [0x48,0xc7,0xc0,0xff,0xff,0xff,0xff] -; CHECK-NEXT: cmovaeq %rcx, %rax # encoding: [0x48,0x0f,0x43,0xc1] +; CHECK-NEXT: addq %rsi, %rdi, %rax # encoding: [0x62,0xf4,0xfc,0x18,0x01,0xf7] +; CHECK-NEXT: movq $-1, %rcx # encoding: [0x48,0xc7,0xc1,0xff,0xff,0xff,0xff] +; CHECK-NEXT: cmovbq %rcx, %rax # EVEX TO LEGACY Compression encoding: [0x48,0x0f,0x42,0xc1] ; CHECK-NEXT: retq # encoding: [0xc3] entry: %add = call i64 @llvm.uadd.sat.i64(i64 %a, i64 %b) @@ -350,9 +350,9 @@ define i8 @addflag8rm(i8 noundef %a, ptr %b) { ; CHECK-LABEL: addflag8rm: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: addb (%rsi), %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x02,0x3e] -; CHECK-NEXT: movzbl %al, %ecx # encoding: [0x0f,0xb6,0xc8] -; CHECK-NEXT: movl $255, %eax # encoding: [0xb8,0xff,0x00,0x00,0x00] -; CHECK-NEXT: cmovael %ecx, %eax # encoding: [0x0f,0x43,0xc1] +; CHECK-NEXT: movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0] +; CHECK-NEXT: movl $255, %ecx # encoding: [0xb9,0xff,0x00,0x00,0x00] +; CHECK-NEXT: cmovbl %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x42,0xc1] ; CHECK-NEXT: # kill: def $al killed $al killed $eax ; CHECK-NEXT: retq # encoding: [0xc3] entry: @@ -364,10 +364,10 @@ entry: define i16 @addflag16rm(i16 noundef %a, ptr %b) { ; CHECK-LABEL: addflag16rm: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addw (%rsi), %di, %cx # encoding: [0x62,0xf4,0x75,0x18,0x03,0x3e] -; CHECK-NEXT: movl $65535, %eax # encoding: [0xb8,0xff,0xff,0x00,0x00] +; CHECK-NEXT: addw (%rsi), %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x03,0x3e] +; CHECK-NEXT: movl $65535, %ecx # encoding: [0xb9,0xff,0xff,0x00,0x00] ; CHECK-NEXT: # imm = 0xFFFF -; CHECK-NEXT: cmovael %ecx, %eax # encoding: [0x0f,0x43,0xc1] +; CHECK-NEXT: cmovbl %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x42,0xc1] ; CHECK-NEXT: # kill: def $ax killed $ax killed $eax ; CHECK-NEXT: retq # encoding: [0xc3] entry: @@ -379,9 +379,9 @@ entry: define i32 @addflag32rm(i32 noundef %a, ptr %b) { ; CHECK-LABEL: addflag32rm: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addl (%rsi), %edi, %ecx # encoding: [0x62,0xf4,0x74,0x18,0x03,0x3e] -; CHECK-NEXT: movl $-1, %eax # encoding: [0xb8,0xff,0xff,0xff,0xff] -; CHECK-NEXT: cmovael %ecx, %eax # encoding: [0x0f,0x43,0xc1] +; CHECK-NEXT: addl (%rsi), %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x03,0x3e] +; CHECK-NEXT: movl $-1, %ecx # encoding: [0xb9,0xff,0xff,0xff,0xff] +; CHECK-NEXT: cmovbl %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x42,0xc1] ; CHECK-NEXT: retq # encoding: [0xc3] entry: %t = load i32, ptr %b @@ -392,9 +392,9 @@ entry: define i64 @addflag64rm(i64 noundef %a, ptr %b) { ; CHECK-LABEL: addflag64rm: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addq (%rsi), %rdi, %rcx # encoding: [0x62,0xf4,0xf4,0x18,0x03,0x3e] -; CHECK-NEXT: movq $-1, %rax # encoding: [0x48,0xc7,0xc0,0xff,0xff,0xff,0xff] -; CHECK-NEXT: cmovaeq %rcx, %rax # encoding: [0x48,0x0f,0x43,0xc1] +; CHECK-NEXT: addq (%rsi), %rdi, %rax # encoding: [0x62,0xf4,0xfc,0x18,0x03,0x3e] +; CHECK-NEXT: movq $-1, %rcx # encoding: [0x48,0xc7,0xc1,0xff,0xff,0xff,0xff] +; CHECK-NEXT: cmovbq %rcx, %rax # EVEX TO LEGACY Compression encoding: [0x48,0x0f,0x42,0xc1] ; CHECK-NEXT: retq # encoding: [0xc3] entry: %t = load i64, ptr %b @@ -405,10 +405,10 @@ entry: define i16 @addflag16ri8(i16 noundef %a) { ; CHECK-LABEL: addflag16ri8: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addw $123, %di, %cx # encoding: [0x62,0xf4,0x75,0x18,0x83,0xc7,0x7b] -; CHECK-NEXT: movl $65535, %eax # encoding: [0xb8,0xff,0xff,0x00,0x00] +; CHECK-NEXT: addw $123, %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x83,0xc7,0x7b] +; CHECK-NEXT: movl $65535, %ecx # encoding: [0xb9,0xff,0xff,0x00,0x00] ; CHECK-NEXT: # imm = 0xFFFF -; CHECK-NEXT: cmovael %ecx, %eax # encoding: [0x0f,0x43,0xc1] +; CHECK-NEXT: cmovbl %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x42,0xc1] ; CHECK-NEXT: # kill: def $ax killed $ax killed $eax ; CHECK-NEXT: retq # encoding: [0xc3] entry: @@ -419,9 +419,9 @@ entry: define i32 @addflag32ri8(i32 noundef %a) { ; CHECK-LABEL: addflag32ri8: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addl $123, %edi, %ecx # encoding: [0x62,0xf4,0x74,0x18,0x83,0xc7,0x7b] -; CHECK-NEXT: movl $-1, %eax # encoding: [0xb8,0xff,0xff,0xff,0xff] -; CHECK-NEXT: cmovael %ecx, %eax # encoding: [0x0f,0x43,0xc1] +; CHECK-NEXT: addl $123, %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x83,0xc7,0x7b] +; CHECK-NEXT: movl $-1, %ecx # encoding: [0xb9,0xff,0xff,0xff,0xff] +; CHECK-NEXT: cmovbl %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x42,0xc1] ; CHECK-NEXT: retq # encoding: [0xc3] entry: %add = call i32 @llvm.uadd.sat.i32(i32 %a, i32 123) @@ -431,9 +431,9 @@ entry: define i64 @addflag64ri8(i64 noundef %a) { ; CHECK-LABEL: addflag64ri8: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addq $123, %rdi, %rcx # encoding: [0x62,0xf4,0xf4,0x18,0x83,0xc7,0x7b] -; CHECK-NEXT: movq $-1, %rax # encoding: [0x48,0xc7,0xc0,0xff,0xff,0xff,0xff] -; CHECK-NEXT: cmovaeq %rcx, %rax # encoding: [0x48,0x0f,0x43,0xc1] +; CHECK-NEXT: addq $123, %rdi, %rax # encoding: [0x62,0xf4,0xfc,0x18,0x83,0xc7,0x7b] +; CHECK-NEXT: movq $-1, %rcx # encoding: [0x48,0xc7,0xc1,0xff,0xff,0xff,0xff] +; CHECK-NEXT: cmovbq %rcx, %rax # EVEX TO LEGACY Compression encoding: [0x48,0x0f,0x42,0xc1] ; CHECK-NEXT: retq # encoding: [0xc3] entry: %add = call i64 @llvm.uadd.sat.i64(i64 %a, i64 123) @@ -444,9 +444,9 @@ define i8 @addflag8ri(i8 noundef %a) { ; CHECK-LABEL: addflag8ri: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: addb $123, %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x80,0xc7,0x7b] -; CHECK-NEXT: movzbl %al, %ecx # encoding: [0x0f,0xb6,0xc8] -; CHECK-NEXT: movl $255, %eax # encoding: [0xb8,0xff,0x00,0x00,0x00] -; CHECK-NEXT: cmovael %ecx, %eax # encoding: [0x0f,0x43,0xc1] +; CHECK-NEXT: movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0] +; CHECK-NEXT: movl $255, %ecx # encoding: [0xb9,0xff,0x00,0x00,0x00] +; CHECK-NEXT: cmovbl %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x42,0xc1] ; CHECK-NEXT: # kill: def $al killed $al killed $eax ; CHECK-NEXT: retq # encoding: [0xc3] entry: @@ -457,11 +457,11 @@ entry: define i16 @addflag16ri(i16 noundef %a) { ; CHECK-LABEL: addflag16ri: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addw $1234, %di, %cx # encoding: [0x62,0xf4,0x75,0x18,0x81,0xc7,0xd2,0x04] +; CHECK-NEXT: addw $1234, %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x81,0xc7,0xd2,0x04] ; CHECK-NEXT: # imm = 0x4D2 -; CHECK-NEXT: movl $65535, %eax # encoding: [0xb8,0xff,0xff,0x00,0x00] +; CHECK-NEXT: movl $65535, %ecx # encoding: [0xb9,0xff,0xff,0x00,0x00] ; CHECK-NEXT: # imm = 0xFFFF -; CHECK-NEXT: cmovael %ecx, %eax # encoding: [0x0f,0x43,0xc1] +; CHECK-NEXT: cmovbl %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x42,0xc1] ; CHECK-NEXT: # kill: def $ax killed $ax killed $eax ; CHECK-NEXT: retq # encoding: [0xc3] entry: @@ -472,10 +472,10 @@ entry: define i32 @addflag32ri(i32 noundef %a) { ; CHECK-LABEL: addflag32ri: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addl $123456, %edi, %ecx # encoding: [0x62,0xf4,0x74,0x18,0x81,0xc7,0x40,0xe2,0x01,0x00] +; CHECK-NEXT: addl $123456, %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x81,0xc7,0x40,0xe2,0x01,0x00] ; CHECK-NEXT: # imm = 0x1E240 -; CHECK-NEXT: movl $-1, %eax # encoding: [0xb8,0xff,0xff,0xff,0xff] -; CHECK-NEXT: cmovael %ecx, %eax # encoding: [0x0f,0x43,0xc1] +; CHECK-NEXT: movl $-1, %ecx # encoding: [0xb9,0xff,0xff,0xff,0xff] +; CHECK-NEXT: cmovbl %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x42,0xc1] ; CHECK-NEXT: retq # encoding: [0xc3] entry: %add = call i32 @llvm.uadd.sat.i32(i32 %a, i32 123456) @@ -485,10 +485,10 @@ entry: define i64 @addflag64ri(i64 noundef %a) { ; CHECK-LABEL: addflag64ri: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addq $123456, %rdi, %rcx # encoding: [0x62,0xf4,0xf4,0x18,0x81,0xc7,0x40,0xe2,0x01,0x00] +; CHECK-NEXT: addq $123456, %rdi, %rax # encoding: [0x62,0xf4,0xfc,0x18,0x81,0xc7,0x40,0xe2,0x01,0x00] ; CHECK-NEXT: # imm = 0x1E240 -; CHECK-NEXT: movq $-1, %rax # encoding: [0x48,0xc7,0xc0,0xff,0xff,0xff,0xff] -; CHECK-NEXT: cmovaeq %rcx, %rax # encoding: [0x48,0x0f,0x43,0xc1] +; CHECK-NEXT: movq $-1, %rcx # encoding: [0x48,0xc7,0xc1,0xff,0xff,0xff,0xff] +; CHECK-NEXT: cmovbq %rcx, %rax # EVEX TO LEGACY Compression encoding: [0x48,0x0f,0x42,0xc1] ; CHECK-NEXT: retq # encoding: [0xc3] entry: %add = call i64 @llvm.uadd.sat.i64(i64 %a, i64 123456) diff --git a/llvm/test/CodeGen/X86/apx/cfcmov.ll b/llvm/test/CodeGen/X86/apx/cfcmov.ll new file mode 100644 index 0000000000000000000000000000000000000000..f643120c9b50ff837d6e6cde6835677b4cacf525 --- /dev/null +++ b/llvm/test/CodeGen/X86/apx/cfcmov.ll @@ -0,0 +1,95 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+cf -verify-machineinstrs | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+cf -x86-cmov-converter=false -verify-machineinstrs | FileCheck %s + +define i8 @cfcmov8rr(i8 %0) { +; CHECK-LABEL: cfcmov8rr: +; CHECK: # %bb.0: +; CHECK-NEXT: cmpb $1, %dil +; CHECK-NEXT: cfcmovel %edi, %eax +; CHECK-NEXT: # kill: def $al killed $al killed $eax +; CHECK-NEXT: retq + %2 = icmp eq i8 %0, 1 + %3 = select i1 %2, i8 %0, i8 0 + ret i8 %3 +} + +define i16 @cfcmov16rr(i16 %0) { +; CHECK-LABEL: cfcmov16rr: +; CHECK: # %bb.0: +; CHECK-NEXT: cmpw $1, %di +; CHECK-NEXT: cfcmovnel %edi, %eax +; CHECK-NEXT: # kill: def $ax killed $ax killed $eax +; CHECK-NEXT: retq + %2 = icmp ne i16 %0, 1 + %3 = select i1 %2, i16 %0, i16 0 + ret i16 %3 +} + +define i32 @cfcmov32rr(i32 %0) { +; CHECK-LABEL: cfcmov32rr: +; CHECK: # %bb.0: +; CHECK-NEXT: cmpl $2, %edi +; CHECK-NEXT: cfcmovael %edi, %eax +; CHECK-NEXT: retq + %2 = icmp ugt i32 %0, 1 + %3 = select i1 %2, i32 %0, i32 0 + ret i32 %3 +} + +define i64 @cfcmov64rr(i64 %0) { +; CHECK-LABEL: cfcmov64rr: +; CHECK: # %bb.0: +; CHECK-NEXT: testq %rdi, %rdi +; CHECK-NEXT: cfcmoveq %rdi, %rax +; CHECK-NEXT: retq + %2 = icmp ult i64 %0, 1 + %3 = select i1 %2, i64 %0, i64 0 + ret i64 %3 +} + +define i8 @cfcmov8rr_inv(i8 %0) { +; CHECK-LABEL: cfcmov8rr_inv: +; CHECK: # %bb.0: +; CHECK-NEXT: cmpb $1, %dil +; CHECK-NEXT: cfcmovnel %edi, %eax +; CHECK-NEXT: # kill: def $al killed $al killed $eax +; CHECK-NEXT: retq + %2 = icmp eq i8 %0, 1 + %3 = select i1 %2, i8 0, i8 %0 + ret i8 %3 +} + +define i16 @cfcmov16rr_inv(i16 %0) { +; CHECK-LABEL: cfcmov16rr_inv: +; CHECK: # %bb.0: +; CHECK-NEXT: cmpw $1, %di +; CHECK-NEXT: cfcmovel %edi, %eax +; CHECK-NEXT: # kill: def $ax killed $ax killed $eax +; CHECK-NEXT: retq + %2 = icmp ne i16 %0, 1 + %3 = select i1 %2, i16 0, i16 %0 + ret i16 %3 +} + +define i32 @cfcmov32rr_inv(i32 %0) { +; CHECK-LABEL: cfcmov32rr_inv: +; CHECK: # %bb.0: +; CHECK-NEXT: cmpl $2, %edi +; CHECK-NEXT: cfcmovbl %edi, %eax +; CHECK-NEXT: retq + %2 = icmp ugt i32 %0, 1 + %3 = select i1 %2, i32 0, i32 %0 + ret i32 %3 +} + +define i64 @cfcmov64rr_inv(i64 %0) { +; CHECK-LABEL: cfcmov64rr_inv: +; CHECK: # %bb.0: +; CHECK-NEXT: cmpq $2, %rdi +; CHECK-NEXT: cfcmovaeq %rdi, %rax +; CHECK-NEXT: retq + %2 = icmp ule i64 %0, 1 + %3 = select i1 %2, i64 0, i64 %0 + ret i64 %3 +} diff --git a/llvm/test/CodeGen/X86/apx/domain-reassignment.mir b/llvm/test/CodeGen/X86/apx/domain-reassignment.mir new file mode 100644 index 0000000000000000000000000000000000000000..7352aa2b307f9ab8a605438d13a5ef3d58f8a35f --- /dev/null +++ b/llvm/test/CodeGen/X86/apx/domain-reassignment.mir @@ -0,0 +1,929 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -run-pass x86-domain-reassignment -mtriple=x86_64-unknown-unknown -mattr=+avx512f,+avx512bw,+avx512dq,+ndd -o - %s | FileCheck %s +--- | + ; ModuleID = '../test/CodeGen/X86/gpr-to-mask.ll' + source_filename = "../test/CodeGen/X86/gpr-to-mask.ll" + target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + target triple = "x86_64-unknown-unknown" + + define void @test_fcmp_storefloat(i1 %cond, ptr %fptr, float %f1, float %f2, float %f3, float %f4, float %f5, float %f6) #0 { + entry: + br i1 %cond, label %if, label %else + + if: ; preds = %entry + %cmp1 = fcmp oeq float %f3, %f4 + br label %exit + + else: ; preds = %entry + %cmp2 = fcmp oeq float %f5, %f6 + br label %exit + + exit: ; preds = %else, %if + %val = phi i1 [ %cmp1, %if ], [ %cmp2, %else ] + %selected = select i1 %val, float %f1, float %f2 + store float %selected, ptr %fptr + ret void + } + + define void @test_8bitops() #0 { + ret void + } + define void @test_16bitops() #0 { + ret void + } + define void @test_32bitops() #0 { + ret void + } + define void @test_64bitops() #0 { + ret void + } + define void @test_16bitext() #0 { + ret void + } + define void @test_32bitext() #0 { + ret void + } + define void @test_64bitext() #0 { + ret void + } + ; Note that this function need to be compiled with -global-isel + ; to obtain testable MIR + define void @test_unused(i64 %0) #0 { + %unused = lshr i64 %0, 7 + ret void + } +... +--- +name: test_fcmp_storefloat +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: gr8, preferred-register: '' } + - { id: 1, class: gr8, preferred-register: '' } + - { id: 2, class: gr8, preferred-register: '' } + - { id: 3, class: gr32, preferred-register: '' } + - { id: 4, class: gr64, preferred-register: '' } + - { id: 5, class: vr128x, preferred-register: '' } + - { id: 6, class: fr32x, preferred-register: '' } + - { id: 7, class: fr32x, preferred-register: '' } + - { id: 8, class: fr32x, preferred-register: '' } + - { id: 9, class: fr32x, preferred-register: '' } + - { id: 10, class: fr32x, preferred-register: '' } + - { id: 11, class: gr8, preferred-register: '' } + - { id: 12, class: vk1, preferred-register: '' } + - { id: 13, class: gr32, preferred-register: '' } + - { id: 14, class: vk1, preferred-register: '' } + - { id: 15, class: gr32, preferred-register: '' } + - { id: 16, class: gr32, preferred-register: '' } + - { id: 17, class: gr32, preferred-register: '' } + - { id: 18, class: vk1wm, preferred-register: '' } + - { id: 19, class: vr128x, preferred-register: '' } + - { id: 20, class: vr128, preferred-register: '' } + - { id: 21, class: vr128, preferred-register: '' } + - { id: 22, class: fr32x, preferred-register: '' } +liveins: + - { reg: '$edi', virtual-reg: '%3' } + - { reg: '$rsi', virtual-reg: '%4' } + - { reg: '$xmm0', virtual-reg: '%5' } + - { reg: '$xmm1', virtual-reg: '%6' } + - { reg: '$xmm2', virtual-reg: '%7' } + - { reg: '$xmm3', virtual-reg: '%8' } + - { reg: '$xmm4', virtual-reg: '%9' } + - { reg: '$xmm5', virtual-reg: '%10' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 4294967295 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + savePoint: '' + restorePoint: '' +fixedStack: +stack: +constants: +body: | + ; CHECK-LABEL: name: test_fcmp_storefloat + ; CHECK: bb.0.entry: + ; CHECK: successors: %bb.1(0x40000000), %bb.2(0x40000000) + ; CHECK: liveins: $edi, $rsi, $xmm0, $xmm1, $xmm2, $xmm3, $xmm4, $xmm5 + ; CHECK: [[COPY:%[0-9]+]]:fr32x = COPY $xmm5 + ; CHECK: [[COPY1:%[0-9]+]]:fr32x = COPY $xmm4 + ; CHECK: [[COPY2:%[0-9]+]]:fr32x = COPY $xmm3 + ; CHECK: [[COPY3:%[0-9]+]]:fr32x = COPY $xmm2 + ; CHECK: [[COPY4:%[0-9]+]]:fr32x = COPY $xmm1 + ; CHECK: [[COPY5:%[0-9]+]]:vr128x = COPY $xmm0 + ; CHECK: [[COPY6:%[0-9]+]]:gr64 = COPY $rsi + ; CHECK: [[COPY7:%[0-9]+]]:gr32 = COPY $edi + ; CHECK: [[COPY8:%[0-9]+]]:gr8 = COPY [[COPY7]].sub_8bit + ; CHECK: TEST8ri killed [[COPY8]], 1, implicit-def $eflags + ; CHECK: JCC_1 %bb.2, 4, implicit $eflags + ; CHECK: JMP_1 %bb.1 + ; CHECK: bb.1.if: + ; CHECK: successors: %bb.3(0x80000000) + ; CHECK: [[VCMPSSZrri:%[0-9]+]]:vk1 = VCMPSSZrri [[COPY3]], [[COPY2]], 0 + ; CHECK: [[COPY9:%[0-9]+]]:vk32 = COPY [[VCMPSSZrri]] + ; CHECK: [[COPY10:%[0-9]+]]:vk8 = COPY [[COPY9]] + ; CHECK: JMP_1 %bb.3 + ; CHECK: bb.2.else: + ; CHECK: successors: %bb.3(0x80000000) + ; CHECK: [[VCMPSSZrri1:%[0-9]+]]:vk1 = VCMPSSZrri [[COPY1]], [[COPY]], 0 + ; CHECK: [[COPY11:%[0-9]+]]:vk32 = COPY [[VCMPSSZrri1]] + ; CHECK: [[COPY12:%[0-9]+]]:vk8 = COPY [[COPY11]] + ; CHECK: bb.3.exit: + ; CHECK: [[PHI:%[0-9]+]]:vk8 = PHI [[COPY12]], %bb.2, [[COPY10]], %bb.1 + ; CHECK: [[DEF:%[0-9]+]]:vk32 = IMPLICIT_DEF + ; CHECK: [[COPY13:%[0-9]+]]:vk32 = COPY [[PHI]] + ; CHECK: [[COPY14:%[0-9]+]]:vk1wm = COPY [[COPY13]] + ; CHECK: [[COPY15:%[0-9]+]]:vr128x = COPY [[COPY4]] + ; CHECK: [[DEF1:%[0-9]+]]:vr128 = IMPLICIT_DEF + ; CHECK: [[VMOVSSZrrk:%[0-9]+]]:vr128 = VMOVSSZrrk [[COPY15]], killed [[COPY14]], killed [[DEF1]], [[COPY5]] + ; CHECK: [[COPY16:%[0-9]+]]:fr32x = COPY [[VMOVSSZrrk]] + ; CHECK: VMOVSSZmr [[COPY6]], 1, $noreg, 0, $noreg, killed [[COPY16]] :: (store (s32) into %ir.fptr) + ; CHECK: RET 0 + bb.0.entry: + successors: %bb.1(0x40000000), %bb.2(0x40000000) + liveins: $edi, $rsi, $xmm0, $xmm1, $xmm2, $xmm3, $xmm4, $xmm5 + + %10 = COPY $xmm5 + %9 = COPY $xmm4 + %8 = COPY $xmm3 + %7 = COPY $xmm2 + %6 = COPY $xmm1 + %5 = COPY $xmm0 + %4 = COPY $rsi + %3 = COPY $edi + %11 = COPY %3.sub_8bit + TEST8ri killed %11, 1, implicit-def $eflags + JCC_1 %bb.2, 4, implicit $eflags + JMP_1 %bb.1 + + bb.1.if: + successors: %bb.3(0x80000000) + + %14 = VCMPSSZrri %7, %8, 0, implicit $mxcsr + + ; check that cross domain copies are replaced with same domain copies. + + %15 = COPY %14 + %0 = COPY %15.sub_8bit + JMP_1 %bb.3 + + bb.2.else: + successors: %bb.3(0x80000000) + %12 = VCMPSSZrri %9, %10, 0, implicit $mxcsr + + ; check that cross domain copies are replaced with same domain copies. + + %13 = COPY %12 + %1 = COPY %13.sub_8bit + + bb.3.exit: + + ; check PHI, IMPLICIT_DEF, and INSERT_SUBREG replacers. + + %2 = PHI %1, %bb.2, %0, %bb.1 + %17 = IMPLICIT_DEF + %16 = INSERT_SUBREG %17, %2, %subreg.sub_8bit_hi + %18 = COPY %16 + %19 = COPY %6 + %21 = IMPLICIT_DEF + %20 = VMOVSSZrrk %19, killed %18, killed %21, %5 + %22 = COPY %20 + VMOVSSZmr %4, 1, $noreg, 0, $noreg, killed %22 :: (store (s32) into %ir.fptr) + RET 0 + +... +--- +name: test_8bitops +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: gr64, preferred-register: '' } + - { id: 1, class: vr512, preferred-register: '' } + - { id: 2, class: vr512, preferred-register: '' } + - { id: 3, class: vr512, preferred-register: '' } + - { id: 4, class: vr512, preferred-register: '' } + - { id: 5, class: vk8, preferred-register: '' } + - { id: 6, class: gr32, preferred-register: '' } + - { id: 7, class: gr8, preferred-register: '' } + - { id: 8, class: gr32, preferred-register: '' } + - { id: 9, class: gr32, preferred-register: '' } + - { id: 10, class: vk8wm, preferred-register: '' } + - { id: 11, class: vr512, preferred-register: '' } + - { id: 12, class: gr8, preferred-register: '' } + - { id: 13, class: gr8, preferred-register: '' } + - { id: 14, class: gr8, preferred-register: '' } + - { id: 15, class: gr8, preferred-register: '' } + - { id: 16, class: gr8, preferred-register: '' } + - { id: 17, class: gr8, preferred-register: '' } + - { id: 18, class: gr8, preferred-register: '' } +liveins: + - { reg: '$rdi', virtual-reg: '%0' } + - { reg: '$zmm0', virtual-reg: '%1' } + - { reg: '$zmm1', virtual-reg: '%2' } + - { reg: '$zmm2', virtual-reg: '%3' } + - { reg: '$zmm3', virtual-reg: '%4' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 4294967295 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + savePoint: '' + restorePoint: '' +fixedStack: +stack: +constants: +body: | + ; CHECK-LABEL: name: test_8bitops + ; CHECK: bb.0: + ; CHECK: successors: %bb.1(0x80000000) + ; CHECK: liveins: $rdi, $zmm0, $zmm1, $zmm2, $zmm3 + ; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rdi + ; CHECK: [[COPY1:%[0-9]+]]:vr512 = COPY $zmm0 + ; CHECK: [[COPY2:%[0-9]+]]:vr512 = COPY $zmm1 + ; CHECK: [[COPY3:%[0-9]+]]:vr512 = COPY $zmm2 + ; CHECK: [[COPY4:%[0-9]+]]:vr512 = COPY $zmm3 + ; CHECK: [[VCMPPDZrri:%[0-9]+]]:vk8 = VCMPPDZrri [[COPY3]], [[COPY4]], 0 + ; CHECK: [[COPY5:%[0-9]+]]:vk32 = COPY [[VCMPPDZrri]] + ; CHECK: [[COPY6:%[0-9]+]]:vk8 = COPY [[COPY5]] + ; CHECK: [[KSHIFTRBri:%[0-9]+]]:vk8 = KSHIFTRBri [[COPY6]], 2 + ; CHECK: [[KSHIFTLBri:%[0-9]+]]:vk8 = KSHIFTLBri [[KSHIFTRBri]], 1 + ; CHECK: [[KNOTBrr:%[0-9]+]]:vk8 = KNOTBrr [[KSHIFTLBri]] + ; CHECK: [[KORBrr:%[0-9]+]]:vk8 = KORBrr [[KNOTBrr]], [[KSHIFTRBri]] + ; CHECK: [[KANDBrr:%[0-9]+]]:vk8 = KANDBrr [[KORBrr]], [[KSHIFTLBri]] + ; CHECK: [[KXORBrr:%[0-9]+]]:vk8 = KXORBrr [[KANDBrr]], [[KSHIFTRBri]] + ; CHECK: [[KADDBrr:%[0-9]+]]:vk8 = KADDBrr [[KXORBrr]], [[KNOTBrr]] + ; CHECK: [[DEF:%[0-9]+]]:vk32 = IMPLICIT_DEF + ; CHECK: [[COPY7:%[0-9]+]]:vk32 = COPY [[KADDBrr]] + ; CHECK: [[COPY8:%[0-9]+]]:vk8wm = COPY [[COPY7]] + ; CHECK: [[VMOVAPDZrrk:%[0-9]+]]:vr512 = VMOVAPDZrrk [[COPY2]], killed [[COPY8]], [[COPY1]] + ; CHECK: VMOVAPDZmr [[COPY]], 1, $noreg, 0, $noreg, killed [[VMOVAPDZrrk]] + ; CHECK: bb.1: + ; CHECK: successors: %bb.2(0x80000000) + ; CHECK: bb.2: + ; CHECK: RET 0 + bb.0: + liveins: $rdi, $zmm0, $zmm1, $zmm2, $zmm3 + + %0 = COPY $rdi + %1 = COPY $zmm0 + %2 = COPY $zmm1 + %3 = COPY $zmm2 + %4 = COPY $zmm3 + + %5 = VCMPPDZrri %3, %4, 0, implicit $mxcsr + %6 = COPY %5 + %7 = COPY %6.sub_8bit + + %12 = SHR8ri_ND %7, 2, implicit-def dead $eflags + %13 = SHL8ri_ND %12, 1, implicit-def dead $eflags + %14 = NOT8r_ND %13 + %15 = OR8rr_ND %14, %12, implicit-def dead $eflags + %16 = AND8rr_ND %15, %13, implicit-def dead $eflags + %17 = XOR8rr_ND %16, %12, implicit-def dead $eflags + %18 = ADD8rr_ND %17, %14, implicit-def dead $eflags + + %8 = IMPLICIT_DEF + %9 = INSERT_SUBREG %8, %18, %subreg.sub_8bit_hi + %10 = COPY %9 + %11 = VMOVAPDZrrk %2, killed %10, %1 + VMOVAPDZmr %0, 1, $noreg, 0, $noreg, killed %11 + + ; FIXME We can't replace TEST with KTEST due to flag differences + ; TEST8rr %18, %18, implicit-def $eflags + ; JCC_1 %bb.1, 4, implicit $eflags + ; JMP_1 %bb.2 + + bb.1: + + bb.2: + RET 0 + +... +--- +name: test_16bitops +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: gr64, preferred-register: '' } + - { id: 1, class: vr512, preferred-register: '' } + - { id: 2, class: vr512, preferred-register: '' } + - { id: 3, class: vr512, preferred-register: '' } + - { id: 4, class: vr512, preferred-register: '' } + - { id: 5, class: vk16, preferred-register: '' } + - { id: 6, class: gr32, preferred-register: '' } + - { id: 7, class: gr16, preferred-register: '' } + - { id: 8, class: gr32, preferred-register: '' } + - { id: 9, class: gr32, preferred-register: '' } + - { id: 10, class: vk16wm, preferred-register: '' } + - { id: 11, class: vr512, preferred-register: '' } + - { id: 12, class: gr16, preferred-register: '' } + - { id: 13, class: gr16, preferred-register: '' } + - { id: 14, class: gr16, preferred-register: '' } + - { id: 15, class: gr16, preferred-register: '' } + - { id: 16, class: gr16, preferred-register: '' } + - { id: 17, class: gr16, preferred-register: '' } +liveins: + - { reg: '$rdi', virtual-reg: '%0' } + - { reg: '$zmm0', virtual-reg: '%1' } + - { reg: '$zmm1', virtual-reg: '%2' } + - { reg: '$zmm2', virtual-reg: '%3' } + - { reg: '$zmm3', virtual-reg: '%4' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 4294967295 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + savePoint: '' + restorePoint: '' +fixedStack: +stack: +constants: +body: | + ; CHECK-LABEL: name: test_16bitops + ; CHECK: bb.0: + ; CHECK: successors: %bb.1(0x80000000) + ; CHECK: liveins: $rdi, $zmm0, $zmm1, $zmm2, $zmm3 + ; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rdi + ; CHECK: [[COPY1:%[0-9]+]]:vr512 = COPY $zmm0 + ; CHECK: [[COPY2:%[0-9]+]]:vr512 = COPY $zmm1 + ; CHECK: [[COPY3:%[0-9]+]]:vr512 = COPY $zmm2 + ; CHECK: [[COPY4:%[0-9]+]]:vr512 = COPY $zmm3 + ; CHECK: [[VCMPPSZrri:%[0-9]+]]:vk16 = VCMPPSZrri [[COPY3]], [[COPY4]], 0 + ; CHECK: [[COPY5:%[0-9]+]]:vk32 = COPY [[VCMPPSZrri]] + ; CHECK: [[COPY6:%[0-9]+]]:vk16 = COPY [[COPY5]] + ; CHECK: [[KSHIFTRWri:%[0-9]+]]:vk16 = KSHIFTRWri [[COPY6]], 2 + ; CHECK: [[KSHIFTLWri:%[0-9]+]]:vk16 = KSHIFTLWri [[KSHIFTRWri]], 1 + ; CHECK: [[KNOTWrr:%[0-9]+]]:vk16 = KNOTWrr [[KSHIFTLWri]] + ; CHECK: [[KORWrr:%[0-9]+]]:vk16 = KORWrr [[KNOTWrr]], [[KSHIFTRWri]] + ; CHECK: [[KANDWrr:%[0-9]+]]:vk16 = KANDWrr [[KORWrr]], [[KSHIFTLWri]] + ; CHECK: [[KXORWrr:%[0-9]+]]:vk16 = KXORWrr [[KANDWrr]], [[KSHIFTRWri]] + ; CHECK: [[DEF:%[0-9]+]]:vk32 = IMPLICIT_DEF + ; CHECK: [[COPY7:%[0-9]+]]:vk32 = COPY [[KXORWrr]] + ; CHECK: [[COPY8:%[0-9]+]]:vk16wm = COPY [[COPY7]] + ; CHECK: [[VMOVAPSZrrk:%[0-9]+]]:vr512 = VMOVAPSZrrk [[COPY2]], killed [[COPY8]], [[COPY1]] + ; CHECK: VMOVAPSZmr [[COPY]], 1, $noreg, 0, $noreg, killed [[VMOVAPSZrrk]] + ; CHECK: bb.1: + ; CHECK: successors: %bb.2(0x80000000) + ; CHECK: bb.2: + ; CHECK: RET 0 + bb.0: + liveins: $rdi, $zmm0, $zmm1, $zmm2, $zmm3 + + %0 = COPY $rdi + %1 = COPY $zmm0 + %2 = COPY $zmm1 + %3 = COPY $zmm2 + %4 = COPY $zmm3 + + %5 = VCMPPSZrri %3, %4, 0, implicit $mxcsr + %6 = COPY %5 + %7 = COPY %6.sub_16bit + + %12 = SHR16ri_ND %7, 2, implicit-def dead $eflags + %13 = SHL16ri_ND %12, 1, implicit-def dead $eflags + %14 = NOT16r_ND %13 + %15 = OR16rr_ND %14, %12, implicit-def dead $eflags + %16 = AND16rr_ND %15, %13, implicit-def dead $eflags + %17 = XOR16rr_ND %16, %12, implicit-def dead $eflags + + %8 = IMPLICIT_DEF + %9 = INSERT_SUBREG %8, %17, %subreg.sub_16bit + %10 = COPY %9 + %11 = VMOVAPSZrrk %2, killed %10, %1 + VMOVAPSZmr %0, 1, $noreg, 0, $noreg, killed %11 + + ; FIXME We can't replace TEST with KTEST due to flag differences + ; FIXME TEST16rr %17, %17, implicit-def $eflags + ; FIXME JCC_1 %bb.1, 4, implicit $eflags + ; FIXME JMP_1 %bb.2 + + bb.1: + + bb.2: + RET 0 + +... +--- +name: test_32bitops +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: gr64, preferred-register: '' } + - { id: 1, class: vr512, preferred-register: '' } + - { id: 2, class: vr512, preferred-register: '' } + - { id: 3, class: vk32wm, preferred-register: '' } + - { id: 4, class: vr512, preferred-register: '' } + - { id: 5, class: gr32, preferred-register: '' } + - { id: 6, class: gr32, preferred-register: '' } + - { id: 7, class: gr32, preferred-register: '' } + - { id: 8, class: gr32, preferred-register: '' } + - { id: 9, class: gr32, preferred-register: '' } + - { id: 10, class: gr32, preferred-register: '' } + - { id: 11, class: gr32, preferred-register: '' } + - { id: 12, class: gr32, preferred-register: '' } + - { id: 13, class: gr32, preferred-register: '' } +liveins: + - { reg: '$rdi', virtual-reg: '%0' } + - { reg: '$zmm0', virtual-reg: '%1' } + - { reg: '$zmm1', virtual-reg: '%2' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 4294967295 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + savePoint: '' + restorePoint: '' +fixedStack: +stack: +constants: +body: | + ; CHECK-LABEL: name: test_32bitops + ; CHECK: bb.0: + ; CHECK: successors: %bb.1(0x80000000) + ; CHECK: liveins: $rdi, $zmm0, $zmm1 + ; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rdi + ; CHECK: [[COPY1:%[0-9]+]]:vr512 = COPY $zmm0 + ; CHECK: [[COPY2:%[0-9]+]]:vr512 = COPY $zmm1 + ; CHECK: [[KMOVDkm:%[0-9]+]]:vk32 = KMOVDkm [[COPY]], 1, $noreg, 0, $noreg + ; CHECK: [[KSHIFTRDri:%[0-9]+]]:vk32 = KSHIFTRDri [[KMOVDkm]], 2 + ; CHECK: [[KSHIFTLDri:%[0-9]+]]:vk32 = KSHIFTLDri [[KSHIFTRDri]], 1 + ; CHECK: [[KNOTDrr:%[0-9]+]]:vk32 = KNOTDrr [[KSHIFTLDri]] + ; CHECK: [[KORDrr:%[0-9]+]]:vk32 = KORDrr [[KNOTDrr]], [[KSHIFTRDri]] + ; CHECK: [[KANDDrr:%[0-9]+]]:vk32 = KANDDrr [[KORDrr]], [[KSHIFTLDri]] + ; CHECK: [[KXORDrr:%[0-9]+]]:vk32 = KXORDrr [[KANDDrr]], [[KSHIFTRDri]] + ; CHECK: [[KANDNDrr:%[0-9]+]]:vk32 = KANDNDrr [[KXORDrr]], [[KORDrr]] + ; CHECK: [[KADDDrr:%[0-9]+]]:vk32 = KADDDrr [[KANDNDrr]], [[KXORDrr]] + ; CHECK: [[COPY3:%[0-9]+]]:vk32wm = COPY [[KADDDrr]] + ; CHECK: [[VMOVDQU16Zrrk:%[0-9]+]]:vr512 = VMOVDQU16Zrrk [[COPY2]], killed [[COPY3]], [[COPY1]] + ; CHECK: VMOVDQA32Zmr [[COPY]], 1, $noreg, 0, $noreg, killed [[VMOVDQU16Zrrk]] + ; CHECK: bb.1: + ; CHECK: successors: %bb.2(0x80000000) + ; CHECK: bb.2: + ; CHECK: RET 0 + bb.0: + liveins: $rdi, $zmm0, $zmm1 + + %0 = COPY $rdi + %1 = COPY $zmm0 + %2 = COPY $zmm1 + + %5 = MOV32rm %0, 1, $noreg, 0, $noreg + %6 = SHR32ri_ND %5, 2, implicit-def dead $eflags + %7 = SHL32ri_ND %6, 1, implicit-def dead $eflags + %8 = NOT32r_ND %7 + %9 = OR32rr_ND %8, %6, implicit-def dead $eflags + %10 = AND32rr_ND %9, %7, implicit-def dead $eflags + %11 = XOR32rr_ND %10, %6, implicit-def dead $eflags + %12 = ANDN32rr %11, %9, implicit-def dead $eflags + %13 = ADD32rr_ND %12, %11, implicit-def dead $eflags + + %3 = COPY %13 + %4 = VMOVDQU16Zrrk %2, killed %3, %1 + VMOVDQA32Zmr %0, 1, $noreg, 0, $noreg, killed %4 + + ; FIXME We can't replace TEST with KTEST due to flag differences + ; FIXME TEST32rr %13, %13, implicit-def $eflags + ; FIXME JCC_1 %bb.1, 4, implicit $eflags + ; FIXME JMP_1 %bb.2 + + bb.1: + + bb.2: + RET 0 + +... +--- +name: test_64bitops +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: gr64, preferred-register: '' } + - { id: 1, class: vr512, preferred-register: '' } + - { id: 2, class: vr512, preferred-register: '' } + - { id: 3, class: vk64wm, preferred-register: '' } + - { id: 4, class: vr512, preferred-register: '' } + - { id: 5, class: gr64, preferred-register: '' } + - { id: 6, class: gr64, preferred-register: '' } + - { id: 7, class: gr64, preferred-register: '' } + - { id: 8, class: gr64, preferred-register: '' } + - { id: 9, class: gr64, preferred-register: '' } + - { id: 10, class: gr64, preferred-register: '' } + - { id: 11, class: gr64, preferred-register: '' } + - { id: 12, class: gr64, preferred-register: '' } + - { id: 13, class: gr64, preferred-register: '' } +liveins: + - { reg: '$rdi', virtual-reg: '%0' } + - { reg: '$zmm0', virtual-reg: '%1' } + - { reg: '$zmm1', virtual-reg: '%2' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 4294967295 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + savePoint: '' + restorePoint: '' +fixedStack: +stack: +constants: +body: | + ; CHECK-LABEL: name: test_64bitops + ; CHECK: bb.0: + ; CHECK: successors: %bb.1(0x80000000) + ; CHECK: liveins: $rdi, $zmm0, $zmm1 + ; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rdi + ; CHECK: [[COPY1:%[0-9]+]]:vr512 = COPY $zmm0 + ; CHECK: [[COPY2:%[0-9]+]]:vr512 = COPY $zmm1 + ; CHECK: [[KMOVQkm:%[0-9]+]]:vk64 = KMOVQkm [[COPY]], 1, $noreg, 0, $noreg + ; CHECK: [[KSHIFTRQri:%[0-9]+]]:vk64 = KSHIFTRQri [[KMOVQkm]], 2 + ; CHECK: [[KSHIFTLQri:%[0-9]+]]:vk64 = KSHIFTLQri [[KSHIFTRQri]], 1 + ; CHECK: [[KNOTQrr:%[0-9]+]]:vk64 = KNOTQrr [[KSHIFTLQri]] + ; CHECK: [[KORQrr:%[0-9]+]]:vk64 = KORQrr [[KNOTQrr]], [[KSHIFTRQri]] + ; CHECK: [[KANDQrr:%[0-9]+]]:vk64 = KANDQrr [[KORQrr]], [[KSHIFTLQri]] + ; CHECK: [[KXORQrr:%[0-9]+]]:vk64 = KXORQrr [[KANDQrr]], [[KSHIFTRQri]] + ; CHECK: [[KANDNQrr:%[0-9]+]]:vk64 = KANDNQrr [[KXORQrr]], [[KORQrr]] + ; CHECK: [[KADDQrr:%[0-9]+]]:vk64 = KADDQrr [[KANDNQrr]], [[KXORQrr]] + ; CHECK: [[COPY3:%[0-9]+]]:vk64wm = COPY [[KADDQrr]] + ; CHECK: [[VMOVDQU8Zrrk:%[0-9]+]]:vr512 = VMOVDQU8Zrrk [[COPY2]], killed [[COPY3]], [[COPY1]] + ; CHECK: VMOVDQA32Zmr [[COPY]], 1, $noreg, 0, $noreg, killed [[VMOVDQU8Zrrk]] + ; CHECK: bb.1: + ; CHECK: successors: %bb.2(0x80000000) + ; CHECK: bb.2: + ; CHECK: RET 0 + bb.0: + liveins: $rdi, $zmm0, $zmm1 + + %0 = COPY $rdi + %1 = COPY $zmm0 + %2 = COPY $zmm1 + + %5 = MOV64rm %0, 1, $noreg, 0, $noreg + %6 = SHR64ri_ND %5, 2, implicit-def dead $eflags + %7 = SHL64ri_ND %6, 1, implicit-def dead $eflags + %8 = NOT64r_ND %7 + %9 = OR64rr_ND %8, %6, implicit-def dead $eflags + %10 = AND64rr_ND %9, %7, implicit-def dead $eflags + %11 = XOR64rr_ND %10, %6, implicit-def dead $eflags + %12 = ANDN64rr %11, %9, implicit-def dead $eflags + %13 = ADD64rr_ND %12, %11, implicit-def dead $eflags + + %3 = COPY %13 + %4 = VMOVDQU8Zrrk %2, killed %3, %1 + VMOVDQA32Zmr %0, 1, $noreg, 0, $noreg, killed %4 + + ; FIXME We can't replace TEST with KTEST due to flag differences + ; FIXME TEST64rr %13, %13, implicit-def $eflags + ; FIXME JCC_1 %bb.1, 4, implicit $eflags + ; FIXME JMP_1 %bb.2 + + bb.1: + + bb.2: + RET 0 + +... +--- +name: test_16bitext +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: gr64, preferred-register: '' } + - { id: 1, class: vr512, preferred-register: '' } + - { id: 2, class: vr512, preferred-register: '' } + - { id: 3, class: vk16wm, preferred-register: '' } + - { id: 4, class: vr512, preferred-register: '' } + - { id: 5, class: gr16, preferred-register: '' } + - { id: 6, class: gr16, preferred-register: '' } +liveins: + - { reg: '$rdi', virtual-reg: '%0' } + - { reg: '$zmm0', virtual-reg: '%1' } + - { reg: '$zmm1', virtual-reg: '%2' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 4294967295 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + savePoint: '' + restorePoint: '' +fixedStack: +stack: +constants: +body: | + bb.0: + liveins: $rdi, $zmm0, $zmm1 + + ; CHECK-LABEL: name: test_16bitext + ; CHECK: liveins: $rdi, $zmm0, $zmm1 + ; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rdi + ; CHECK: [[COPY1:%[0-9]+]]:vr512 = COPY $zmm0 + ; CHECK: [[COPY2:%[0-9]+]]:vr512 = COPY $zmm1 + ; CHECK: [[KMOVBkm:%[0-9]+]]:vk8 = KMOVBkm [[COPY]], 1, $noreg, 0, $noreg + ; CHECK: [[COPY3:%[0-9]+]]:vk16 = COPY [[KMOVBkm]] + ; CHECK: [[KNOTWrr:%[0-9]+]]:vk16 = KNOTWrr [[COPY3]] + ; CHECK: [[COPY4:%[0-9]+]]:vk16wm = COPY [[KNOTWrr]] + ; CHECK: [[VMOVAPSZrrk:%[0-9]+]]:vr512 = VMOVAPSZrrk [[COPY2]], killed [[COPY4]], [[COPY1]] + ; CHECK: VMOVAPSZmr [[COPY]], 1, $noreg, 0, $noreg, killed [[VMOVAPSZrrk]] + ; CHECK: RET 0 + %0 = COPY $rdi + %1 = COPY $zmm0 + %2 = COPY $zmm1 + + %5 = MOVZX16rm8 %0, 1, $noreg, 0, $noreg + %6 = NOT16r_ND %5 + + %3 = COPY %6 + %4 = VMOVAPSZrrk %2, killed %3, %1 + VMOVAPSZmr %0, 1, $noreg, 0, $noreg, killed %4 + RET 0 + +... +--- +name: test_32bitext +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: gr64, preferred-register: '' } + - { id: 1, class: vr512, preferred-register: '' } + - { id: 2, class: vr512, preferred-register: '' } + - { id: 3, class: vk64wm, preferred-register: '' } + - { id: 4, class: vr512, preferred-register: '' } + - { id: 5, class: gr32, preferred-register: '' } + - { id: 6, class: gr32, preferred-register: '' } + - { id: 7, class: gr32, preferred-register: '' } +liveins: + - { reg: '$rdi', virtual-reg: '%0' } + - { reg: '$zmm0', virtual-reg: '%1' } + - { reg: '$zmm1', virtual-reg: '%2' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 4294967295 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + savePoint: '' + restorePoint: '' +fixedStack: +stack: +constants: +body: | + bb.0: + liveins: $rdi, $zmm0, $zmm1 + + ; CHECK-LABEL: name: test_32bitext + ; CHECK: liveins: $rdi, $zmm0, $zmm1 + ; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rdi + ; CHECK: [[COPY1:%[0-9]+]]:vr512 = COPY $zmm0 + ; CHECK: [[COPY2:%[0-9]+]]:vr512 = COPY $zmm1 + ; CHECK: [[KMOVBkm:%[0-9]+]]:vk8 = KMOVBkm [[COPY]], 1, $noreg, 0, $noreg + ; CHECK: [[COPY3:%[0-9]+]]:vk32 = COPY [[KMOVBkm]] + ; CHECK: [[KMOVWkm:%[0-9]+]]:vk16 = KMOVWkm [[COPY]], 1, $noreg, 0, $noreg + ; CHECK: [[COPY4:%[0-9]+]]:vk32 = COPY [[KMOVWkm]] + ; CHECK: [[KADDDrr:%[0-9]+]]:vk32 = KADDDrr [[COPY3]], [[COPY4]] + ; CHECK: [[COPY5:%[0-9]+]]:vk64wm = COPY [[KADDDrr]] + ; CHECK: [[VMOVDQU16Zrrk:%[0-9]+]]:vr512 = VMOVDQU16Zrrk [[COPY2]], killed [[COPY5]], [[COPY1]] + ; CHECK: VMOVDQA32Zmr [[COPY]], 1, $noreg, 0, $noreg, killed [[VMOVDQU16Zrrk]] + ; CHECK: RET 0 + %0 = COPY $rdi + %1 = COPY $zmm0 + %2 = COPY $zmm1 + + %5 = MOVZX32rm8 %0, 1, $noreg, 0, $noreg + %6 = MOVZX32rm16 %0, 1, $noreg, 0, $noreg + %7 = ADD32rr_ND %5, %6, implicit-def dead $eflags + + %3 = COPY %7 + %4 = VMOVDQU16Zrrk %2, killed %3, %1 + VMOVDQA32Zmr %0, 1, $noreg, 0, $noreg, killed %4 + RET 0 + +... +--- +name: test_64bitext +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: gr64, preferred-register: '' } + - { id: 1, class: vr512, preferred-register: '' } + - { id: 2, class: vr512, preferred-register: '' } + - { id: 3, class: vk64wm, preferred-register: '' } + - { id: 4, class: vr512, preferred-register: '' } + - { id: 5, class: gr64, preferred-register: '' } + - { id: 6, class: gr64, preferred-register: '' } + - { id: 7, class: gr64, preferred-register: '' } +liveins: + - { reg: '$rdi', virtual-reg: '%0' } + - { reg: '$zmm0', virtual-reg: '%1' } + - { reg: '$zmm1', virtual-reg: '%2' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 4294967295 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + savePoint: '' + restorePoint: '' +fixedStack: +stack: +constants: +body: | + bb.0: + liveins: $rdi, $zmm0, $zmm1 + + ; CHECK-LABEL: name: test_64bitext + ; CHECK: liveins: $rdi, $zmm0, $zmm1 + ; CHECK: [[COPY:%[0-9]+]]:gr64 = COPY $rdi + ; CHECK: [[COPY1:%[0-9]+]]:vr512 = COPY $zmm0 + ; CHECK: [[COPY2:%[0-9]+]]:vr512 = COPY $zmm1 + ; CHECK: [[KMOVBkm:%[0-9]+]]:vk8 = KMOVBkm [[COPY]], 1, $noreg, 0, $noreg + ; CHECK: [[COPY3:%[0-9]+]]:vk64 = COPY [[KMOVBkm]] + ; CHECK: [[KMOVWkm:%[0-9]+]]:vk16 = KMOVWkm [[COPY]], 1, $noreg, 0, $noreg + ; CHECK: [[COPY4:%[0-9]+]]:vk64 = COPY [[KMOVWkm]] + ; CHECK: [[KADDQrr:%[0-9]+]]:vk64 = KADDQrr [[COPY3]], [[COPY4]] + ; CHECK: [[COPY5:%[0-9]+]]:vk64wm = COPY [[KADDQrr]] + ; CHECK: [[VMOVDQU8Zrrk:%[0-9]+]]:vr512 = VMOVDQU8Zrrk [[COPY2]], killed [[COPY5]], [[COPY1]] + ; CHECK: VMOVDQA32Zmr [[COPY]], 1, $noreg, 0, $noreg, killed [[VMOVDQU8Zrrk]] + ; CHECK: RET 0 + %0 = COPY $rdi + %1 = COPY $zmm0 + %2 = COPY $zmm1 + + %5 = MOVZX64rm8 %0, 1, $noreg, 0, $noreg + %6 = MOVZX64rm16 %0, 1, $noreg, 0, $noreg + %7 = ADD64rr_ND %5, %6, implicit-def dead $eflags + + %3 = COPY %7 + %4 = VMOVDQU8Zrrk %2, killed %3, %1 + VMOVDQA32Zmr %0, 1, $noreg, 0, $noreg, killed %4 + RET 0 + +... +--- +name: test_unused +alignment: 16 +exposesReturnsTwice: false +legalized: true +regBankSelected: true +selected: true +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +callsEHReturn: false +callsUnwindInit: false +hasEHCatchret: false +hasEHScopes: false +hasEHFunclets: false +isOutlined: false +debugInstrRef: false +failsVerification: false +tracksDebugUserValues: false +registers: +# Note that this test is supposed to have registers without classes + - { id: 0, class: _, preferred-register: '' } + - { id: 1, class: _, preferred-register: '' } + - { id: 2, class: _, preferred-register: '' } +liveins: + - { reg: '$rdi', virtual-reg: '' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 1 + adjustsStack: false + hasCalls: false + stackProtector: '' + functionContext: '' + maxCallFrameSize: 4294967295 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: [] +entry_values: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: {} +body: | + bb.1 (%ir-block.1): + liveins: $rdi + + RET 0 + +... diff --git a/llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir b/llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir index d6a9cda1dc81621722c4e58c8e97911da43e8d7b..e81a4480ba44cbd16d8a8eeabc37ad36f283beac 100644 --- a/llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir +++ b/llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir @@ -29,6 +29,18 @@ call void @foo() ret void } + + define void @test_cmov(i64 %a, i64 %b) { + entry: + call void @foo() + ret void + } + + define void @test_cfcmov(i64 %a, i64 %b) { + entry: + call void @foo() + ret void + } ... --- name: test_adc @@ -166,3 +178,93 @@ body: | RET 0 ... +--- +name: test_cmov +# CHECK-LABEL: name: test_cmov +liveins: + - { reg: '$rdi', virtual-reg: '%0' } + - { reg: '$rsi', virtual-reg: '%1' } +body: | + bb.0: + liveins: $rdi, $rsi + + %0:gr64 = COPY $rdi + %1:gr64 = COPY $rsi + CMP64rr %0, %1, implicit-def $eflags + %2:gr64 = COPY $eflags + ; CHECK-NOT: COPY{{( killed)?}} $eflags + ; CHECK: %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags + ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags + ; CHECK-NEXT: %[[E_REG:[^:]*]]:gr8 = SETCCr 4, implicit $eflags + ; CHECK-NOT: COPY{{( killed)?}} $eflags + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + + $eflags = COPY %2 + %3:gr64 = CMOV64rr_ND %0, %1, 7, implicit $eflags + %4:gr64 = CMOV64rr_ND %0, %1, 2, implicit $eflags + %5:gr64 = CMOV64rr_ND %0, %1, 4, implicit $eflags + %6:gr64 = CMOV64rr_ND %0, %1, 5, implicit killed $eflags + ; CHECK-NOT: $eflags = + ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags + ; CHECK-NEXT: %3:gr64 = CMOV64rr_ND %0, %1, 5, implicit killed $eflags + ; CHECK-NEXT: TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags + ; CHECK-NEXT: %4:gr64 = CMOV64rr_ND %0, %1, 5, implicit killed $eflags + ; CHECK-NEXT: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags + ; CHECK-NEXT: %5:gr64 = CMOV64rr_ND %0, %1, 5, implicit killed $eflags + ; CHECK-NEXT: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags + ; CHECK-NEXT: %6:gr64 = CMOV64rr_ND %0, %1, 4, implicit killed $eflags + MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %3 + MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %4 + MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5 + MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %6 + + RET 0 +... +--- +name: test_cfcmov +# CHECK-LABEL: name: test_cfcmov +liveins: + - { reg: '$rdi', virtual-reg: '%0' } + - { reg: '$rsi', virtual-reg: '%1' } +body: | + bb.0: + liveins: $rdi, $rsi + + %0:gr64 = COPY $rdi + %1:gr64 = COPY $rsi + CMP64rr %0, %1, implicit-def $eflags + %2:gr64 = COPY $eflags + ; CHECK-NOT: COPY{{( killed)?}} $eflags + ; CHECK: %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags + ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags + ; CHECK-NEXT: %[[E_REG:[^:]*]]:gr8 = SETCCr 4, implicit $eflags + ; CHECK-NOT: COPY{{( killed)?}} $eflags + + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + + $eflags = COPY %2 + %3:gr64 = CFCMOV64rr %1, 7, implicit $eflags + %4:gr64 = CFCMOV64rr %1, 2, implicit $eflags + %5:gr64 = CFCMOV64rr_ND %0, %1, 4, implicit $eflags + %6:gr64 = CFCMOV64rr_ND %0, %1, 5, implicit killed $eflags + ; CHECK-NOT: $eflags = + ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags + ; CHECK-NEXT: %3:gr64 = CFCMOV64rr %1, 5, implicit killed $eflags + ; CHECK-NEXT: TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags + ; CHECK-NEXT: %4:gr64 = CFCMOV64rr %1, 5, implicit killed $eflags + ; CHECK-NEXT: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags + ; CHECK-NEXT: %5:gr64 = CFCMOV64rr_ND %0, %1, 5, implicit killed $eflags + ; CHECK-NEXT: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags + ; CHECK-NEXT: %6:gr64 = CFCMOV64rr_ND %0, %1, 4, implicit killed $eflags + MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %3 + MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %4 + MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5 + MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %6 + + RET 0 +... diff --git a/llvm/test/CodeGen/X86/apx/foldimmediate.mir b/llvm/test/CodeGen/X86/apx/foldimmediate.mir new file mode 100644 index 0000000000000000000000000000000000000000..310fc64841f7a58bba5de8f4647f752c0e401712 --- /dev/null +++ b/llvm/test/CodeGen/X86/apx/foldimmediate.mir @@ -0,0 +1,70 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3 +# RUN: llc -mtriple=x86_64-- -run-pass=peephole-opt %s -o - | FileCheck %s +--- | + define void @foldImmediate() { ret void } +... +--- +# Check that immediates can be folded into ALU instructions. +name: foldImmediate +registers: + - { id: 0, class: gr32 } + - { id: 1, class: gr32 } + - { id: 2, class: gr32 } + - { id: 3, class: gr32 } + - { id: 4, class: gr32 } + - { id: 5, class: gr32 } + - { id: 6, class: gr32 } + - { id: 7, class: gr64 } + - { id: 8, class: gr64 } + - { id: 9, class: gr64 } + - { id: 10, class: gr64 } + - { id: 11, class: gr64 } + - { id: 12, class: gr64 } + - { id: 13, class: gr64 } + - { id: 14, class: gr64 } + - { id: 15, class: gr64 } + - { id: 16, class: gr32 } + - { id: 17, class: gr64 } + - { id: 18, class: gr32 } + +body: | + bb.0: + liveins: $rdi, $rsi + + ; CHECK-LABEL: name: foldImmediate + ; CHECK: liveins: $rdi, $rsi + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[MOV32ri:%[0-9]+]]:gr32 = MOV32ri 81 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY $edi + ; CHECK-NEXT: CTEST32ri [[COPY]], 81, 2, 10, implicit-def $eflags, implicit $eflags + ; CHECK-NEXT: NOOP implicit $eflags + ; CHECK-NEXT: CCMP32ri [[COPY]], 81, 2, 10, implicit-def $eflags, implicit $eflags + ; CHECK-NEXT: NOOP implicit $eflags + ; CHECK-NEXT: [[SUBREG_TO_REG:%[0-9]+]]:gr64 = SUBREG_TO_REG 0, killed [[MOV32ri]], %subreg.sub_32bit + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gr64 = COPY $rsi + ; CHECK-NEXT: CTEST64ri32 [[COPY1]], 81, 2, 10, implicit-def $eflags, implicit $eflags + ; CHECK-NEXT: NOOP implicit $eflags + ; CHECK-NEXT: CCMP64ri32 [[COPY1]], 81, 2, 10, implicit-def $eflags, implicit $eflags + ; CHECK-NEXT: NOOP implicit $eflags + ; CHECK-NEXT: CCMP64rr [[SUBREG_TO_REG]], [[COPY1]], 2, 10, implicit-def $eflags, implicit $eflags + ; CHECK-NEXT: NOOP implicit $eflags + %0 = MOV32ri 81 + %1 = COPY $edi + + CTEST32rr %0, %1, 2, 10, implicit-def $eflags, implicit $eflags + NOOP implicit $eflags + + CCMP32rr %1, %0, 2, 10, implicit-def $eflags, implicit $eflags + NOOP implicit $eflags + + %7 = SUBREG_TO_REG 0, killed %0:gr32, %subreg.sub_32bit + %8 = COPY $rsi + + CTEST64rr %8, %7, 2, 10, implicit-def $eflags, implicit $eflags + NOOP implicit $eflags + + CCMP64rr %8, %7, 2, 10, implicit-def $eflags, implicit $eflags + NOOP implicit $eflags + CCMP64rr %7, %8, 2, 10, implicit-def $eflags, implicit $eflags + NOOP implicit $eflags +... diff --git a/llvm/test/CodeGen/X86/apx/inc.ll b/llvm/test/CodeGen/X86/apx/inc.ll index 613f7866c9ac5cc3dc3899127853071784546a79..a9c6d740cf2cee7b2456040cae22f31f38091327 100644 --- a/llvm/test/CodeGen/X86/apx/inc.ll +++ b/llvm/test/CodeGen/X86/apx/inc.ll @@ -92,9 +92,9 @@ define i8 @uinc8r(i8 noundef %a) { ; CHECK-LABEL: uinc8r: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: incb %dil, %al -; CHECK-NEXT: movzbl %al, %ecx -; CHECK-NEXT: movl $255, %eax -; CHECK-NEXT: cmovnel %ecx, %eax +; CHECK-NEXT: movzbl %al, %eax +; CHECK-NEXT: movl $255, %ecx +; CHECK-NEXT: cmovel %ecx, %eax ; CHECK-NEXT: # kill: def $al killed $al killed $eax ; CHECK-NEXT: retq entry: @@ -105,9 +105,9 @@ entry: define i16 @uinc16r(i16 noundef %a) { ; CHECK-LABEL: uinc16r: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: incw %di, %cx -; CHECK-NEXT: movl $65535, %eax # imm = 0xFFFF -; CHECK-NEXT: cmovnel %ecx, %eax +; CHECK-NEXT: incw %di, %ax +; CHECK-NEXT: movl $65535, %ecx # imm = 0xFFFF +; CHECK-NEXT: cmovel %ecx, %eax ; CHECK-NEXT: # kill: def $ax killed $ax killed $eax ; CHECK-NEXT: retq entry: @@ -118,9 +118,9 @@ entry: define i32 @uinc32r(i32 noundef %a) { ; CHECK-LABEL: uinc32r: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: incl %edi, %ecx -; CHECK-NEXT: movl $-1, %eax -; CHECK-NEXT: cmovnel %ecx, %eax +; CHECK-NEXT: incl %edi, %eax +; CHECK-NEXT: movl $-1, %ecx +; CHECK-NEXT: cmovel %ecx, %eax ; CHECK-NEXT: retq entry: %inc = call i32 @llvm.uadd.sat.i32(i32 %a, i32 1) @@ -130,9 +130,9 @@ entry: define i64 @uinc64r(i64 noundef %a) { ; CHECK-LABEL: uinc64r: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: incq %rdi, %rcx -; CHECK-NEXT: movq $-1, %rax -; CHECK-NEXT: cmovneq %rcx, %rax +; CHECK-NEXT: incq %rdi, %rax +; CHECK-NEXT: movq $-1, %rcx +; CHECK-NEXT: cmoveq %rcx, %rax ; CHECK-NEXT: retq entry: %inc = call i64 @llvm.uadd.sat.i64(i64 %a, i64 1) diff --git a/llvm/test/CodeGen/X86/apx/shift-eflags.ll b/llvm/test/CodeGen/X86/apx/shift-eflags.ll index f34dc6c05dad986cc67e76306cf31757382bcda3..932cdc189bf9f85212d9ef8de3ce762be4fcb3d0 100644 --- a/llvm/test/CodeGen/X86/apx/shift-eflags.ll +++ b/llvm/test/CodeGen/X86/apx/shift-eflags.ll @@ -7,9 +7,8 @@ define i32 @ashr_const(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { ; CHECK-LABEL: ashr_const: ; CHECK: # %bb.0: -; CHECK-NEXT: movl %edx, %eax -; CHECK-NEXT: sarl $14, %edi, %edx -; CHECK-NEXT: cmovnel %ecx, %eax +; CHECK-NEXT: sarl $14, %edi, %eax +; CHECK-NEXT: cmovel %edx, %ecx, %eax ; CHECK-NEXT: retq %s = ashr i32 %a0, 14 %c = icmp eq i32 %s, 0 @@ -21,9 +20,8 @@ define i32 @ashr_const(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { define i32 @lshr_const(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { ; CHECK-LABEL: lshr_const: ; CHECK: # %bb.0: -; CHECK-NEXT: movl %edx, %eax ; CHECK-NEXT: testl $-16384, %edi # imm = 0xC000 -; CHECK-NEXT: cmovnel %ecx, %eax +; CHECK-NEXT: cmovel %edx, %ecx, %eax ; CHECK-NEXT: retq %s = lshr i32 %a0, 14 %c = icmp eq i32 %s, 0 @@ -35,9 +33,8 @@ define i32 @lshr_const(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { define i32 @shl_const(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { ; CHECK-LABEL: shl_const: ; CHECK: # %bb.0: -; CHECK-NEXT: movl %edx, %eax ; CHECK-NEXT: testl $262143, %edi # imm = 0x3FFFF -; CHECK-NEXT: cmovnel %ecx, %eax +; CHECK-NEXT: cmovel %edx, %ecx, %eax ; CHECK-NEXT: retq %s = shl i32 %a0, 14 %c = icmp eq i32 %s, 0 @@ -88,9 +85,8 @@ define i32 @shl_const_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { define i32 @ashr_const1(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { ; CHECK-LABEL: ashr_const1: ; CHECK: # %bb.0: -; CHECK-NEXT: movl %edx, %eax -; CHECK-NEXT: sarl %edi, %edx -; CHECK-NEXT: cmovnel %ecx, %eax +; CHECK-NEXT: sarl %edi, %eax +; CHECK-NEXT: cmovel %edx, %ecx, %eax ; CHECK-NEXT: retq %s = ashr i32 %a0, 1 %c = icmp eq i32 %s, 0 @@ -102,9 +98,8 @@ define i32 @ashr_const1(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { define i32 @lshr_const1(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { ; CHECK-LABEL: lshr_const1: ; CHECK: # %bb.0: -; CHECK-NEXT: movl %edx, %eax ; CHECK-NEXT: testl $-2, %edi -; CHECK-NEXT: cmovnel %ecx, %eax +; CHECK-NEXT: cmovel %edx, %ecx, %eax ; CHECK-NEXT: retq %s = lshr i32 %a0, 1 %c = icmp eq i32 %s, 0 @@ -116,9 +111,8 @@ define i32 @lshr_const1(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { define i32 @shl_const1(i32 %a0, i32 %a1, i32 %a2, i32 %a3) { ; CHECK-LABEL: shl_const1: ; CHECK: # %bb.0: -; CHECK-NEXT: movl %edx, %eax ; CHECK-NEXT: testl $2147483647, %edi # imm = 0x7FFFFFFF -; CHECK-NEXT: cmovnel %ecx, %eax +; CHECK-NEXT: cmovel %edx, %ecx, %eax ; CHECK-NEXT: retq %s = shl i32 %a0, 1 %c = icmp eq i32 %s, 0 diff --git a/llvm/test/CodeGen/X86/apx/sub.ll b/llvm/test/CodeGen/X86/apx/sub.ll index 4b0bd14872141ba3fea183a712830011442343fb..be0914c90b9faf5daa641f7f1bc26d8be0b5629d 100644 --- a/llvm/test/CodeGen/X86/apx/sub.ll +++ b/llvm/test/CodeGen/X86/apx/sub.ll @@ -299,10 +299,10 @@ declare i64 @llvm.usub.sat.i64(i64, i64) define i8 @subflag8rr(i8 noundef %a, i8 noundef %b) { ; CHECK-LABEL: subflag8rr: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xorl %ecx, %ecx # encoding: [0x31,0xc9] -; CHECK-NEXT: subb %sil, %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x28,0xf7] -; CHECK-NEXT: movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0] -; CHECK-NEXT: cmovbl %ecx, %eax # encoding: [0x0f,0x42,0xc1] +; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] +; CHECK-NEXT: subb %sil, %dil, %cl # encoding: [0x62,0xf4,0x74,0x18,0x28,0xf7] +; CHECK-NEXT: movzbl %cl, %ecx # encoding: [0x0f,0xb6,0xc9] +; CHECK-NEXT: cmovael %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x43,0xc1] ; CHECK-NEXT: # kill: def $al killed $al killed $eax ; CHECK-NEXT: retq # encoding: [0xc3] entry: @@ -313,9 +313,9 @@ entry: define i16 @subflag16rr(i16 noundef %a, i16 noundef %b) { ; CHECK-LABEL: subflag16rr: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xorl %ecx, %ecx # encoding: [0x31,0xc9] -; CHECK-NEXT: subw %si, %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x29,0xf7] -; CHECK-NEXT: cmovbl %ecx, %eax # encoding: [0x0f,0x42,0xc1] +; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] +; CHECK-NEXT: subw %si, %di, %cx # encoding: [0x62,0xf4,0x75,0x18,0x29,0xf7] +; CHECK-NEXT: cmovael %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x43,0xc1] ; CHECK-NEXT: # kill: def $ax killed $ax killed $eax ; CHECK-NEXT: retq # encoding: [0xc3] entry: @@ -326,9 +326,9 @@ entry: define i32 @subflag32rr(i32 noundef %a, i32 noundef %b) { ; CHECK-LABEL: subflag32rr: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xorl %ecx, %ecx # encoding: [0x31,0xc9] -; CHECK-NEXT: subl %esi, %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x29,0xf7] -; CHECK-NEXT: cmovbl %ecx, %eax # encoding: [0x0f,0x42,0xc1] +; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] +; CHECK-NEXT: subl %esi, %edi, %ecx # encoding: [0x62,0xf4,0x74,0x18,0x29,0xf7] +; CHECK-NEXT: cmovael %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x43,0xc1] ; CHECK-NEXT: retq # encoding: [0xc3] entry: %sub = call i32 @llvm.usub.sat.i32(i32 %a, i32 %b) @@ -340,7 +340,7 @@ define i64 @subflag64rr(i64 noundef %a, i64 noundef %b) { ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] ; CHECK-NEXT: subq %rsi, %rdi, %rcx # encoding: [0x62,0xf4,0xf4,0x18,0x29,0xf7] -; CHECK-NEXT: cmovaeq %rcx, %rax # encoding: [0x48,0x0f,0x43,0xc1] +; CHECK-NEXT: cmovaeq %rcx, %rax # EVEX TO LEGACY Compression encoding: [0x48,0x0f,0x43,0xc1] ; CHECK-NEXT: retq # encoding: [0xc3] entry: %sub = call i64 @llvm.usub.sat.i64(i64 %a, i64 %b) @@ -350,10 +350,10 @@ entry: define i8 @subflag8rm(i8 noundef %a, ptr %b) { ; CHECK-LABEL: subflag8rm: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xorl %ecx, %ecx # encoding: [0x31,0xc9] -; CHECK-NEXT: subb (%rsi), %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x2a,0x3e] -; CHECK-NEXT: movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0] -; CHECK-NEXT: cmovbl %ecx, %eax # encoding: [0x0f,0x42,0xc1] +; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] +; CHECK-NEXT: subb (%rsi), %dil, %cl # encoding: [0x62,0xf4,0x74,0x18,0x2a,0x3e] +; CHECK-NEXT: movzbl %cl, %ecx # encoding: [0x0f,0xb6,0xc9] +; CHECK-NEXT: cmovael %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x43,0xc1] ; CHECK-NEXT: # kill: def $al killed $al killed $eax ; CHECK-NEXT: retq # encoding: [0xc3] entry: @@ -365,9 +365,9 @@ entry: define i16 @subflag16rm(i16 noundef %a, ptr %b) { ; CHECK-LABEL: subflag16rm: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xorl %ecx, %ecx # encoding: [0x31,0xc9] -; CHECK-NEXT: subw (%rsi), %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x2b,0x3e] -; CHECK-NEXT: cmovbl %ecx, %eax # encoding: [0x0f,0x42,0xc1] +; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] +; CHECK-NEXT: subw (%rsi), %di, %cx # encoding: [0x62,0xf4,0x75,0x18,0x2b,0x3e] +; CHECK-NEXT: cmovael %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x43,0xc1] ; CHECK-NEXT: # kill: def $ax killed $ax killed $eax ; CHECK-NEXT: retq # encoding: [0xc3] entry: @@ -379,9 +379,9 @@ entry: define i32 @subflag32rm(i32 noundef %a, ptr %b) { ; CHECK-LABEL: subflag32rm: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xorl %ecx, %ecx # encoding: [0x31,0xc9] -; CHECK-NEXT: subl (%rsi), %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x2b,0x3e] -; CHECK-NEXT: cmovbl %ecx, %eax # encoding: [0x0f,0x42,0xc1] +; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] +; CHECK-NEXT: subl (%rsi), %edi, %ecx # encoding: [0x62,0xf4,0x74,0x18,0x2b,0x3e] +; CHECK-NEXT: cmovael %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x43,0xc1] ; CHECK-NEXT: retq # encoding: [0xc3] entry: %t = load i32, ptr %b @@ -394,7 +394,7 @@ define i64 @subflag64rm(i64 noundef %a, ptr %b) { ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] ; CHECK-NEXT: subq (%rsi), %rdi, %rcx # encoding: [0x62,0xf4,0xf4,0x18,0x2b,0x3e] -; CHECK-NEXT: cmovaeq %rcx, %rax # encoding: [0x48,0x0f,0x43,0xc1] +; CHECK-NEXT: cmovaeq %rcx, %rax # EVEX TO LEGACY Compression encoding: [0x48,0x0f,0x43,0xc1] ; CHECK-NEXT: retq # encoding: [0xc3] entry: %t = load i64, ptr %b @@ -405,9 +405,9 @@ entry: define i16 @subflag16ri8(i16 noundef %a) { ; CHECK-LABEL: subflag16ri8: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xorl %ecx, %ecx # encoding: [0x31,0xc9] -; CHECK-NEXT: subw $123, %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x83,0xef,0x7b] -; CHECK-NEXT: cmovbl %ecx, %eax # encoding: [0x0f,0x42,0xc1] +; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] +; CHECK-NEXT: subw $123, %di, %cx # encoding: [0x62,0xf4,0x75,0x18,0x83,0xef,0x7b] +; CHECK-NEXT: cmovael %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x43,0xc1] ; CHECK-NEXT: # kill: def $ax killed $ax killed $eax ; CHECK-NEXT: retq # encoding: [0xc3] entry: @@ -418,9 +418,9 @@ entry: define i32 @subflag32ri8(i32 noundef %a) { ; CHECK-LABEL: subflag32ri8: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xorl %ecx, %ecx # encoding: [0x31,0xc9] -; CHECK-NEXT: subl $123, %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x83,0xef,0x7b] -; CHECK-NEXT: cmovbl %ecx, %eax # encoding: [0x0f,0x42,0xc1] +; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] +; CHECK-NEXT: subl $123, %edi, %ecx # encoding: [0x62,0xf4,0x74,0x18,0x83,0xef,0x7b] +; CHECK-NEXT: cmovael %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x43,0xc1] ; CHECK-NEXT: retq # encoding: [0xc3] entry: %sub = call i32 @llvm.usub.sat.i32(i32 %a, i32 123) @@ -432,7 +432,7 @@ define i64 @subflag64ri8(i64 noundef %a) { ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] ; CHECK-NEXT: subq $123, %rdi, %rcx # encoding: [0x62,0xf4,0xf4,0x18,0x83,0xef,0x7b] -; CHECK-NEXT: cmovaeq %rcx, %rax # encoding: [0x48,0x0f,0x43,0xc1] +; CHECK-NEXT: cmovaeq %rcx, %rax # EVEX TO LEGACY Compression encoding: [0x48,0x0f,0x43,0xc1] ; CHECK-NEXT: retq # encoding: [0xc3] entry: %sub = call i64 @llvm.usub.sat.i64(i64 %a, i64 123) @@ -442,10 +442,10 @@ entry: define i8 @subflag8ri(i8 noundef %a) { ; CHECK-LABEL: subflag8ri: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xorl %ecx, %ecx # encoding: [0x31,0xc9] -; CHECK-NEXT: subb $123, %dil, %al # encoding: [0x62,0xf4,0x7c,0x18,0x80,0xef,0x7b] -; CHECK-NEXT: movzbl %al, %eax # encoding: [0x0f,0xb6,0xc0] -; CHECK-NEXT: cmovbl %ecx, %eax # encoding: [0x0f,0x42,0xc1] +; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] +; CHECK-NEXT: subb $123, %dil, %cl # encoding: [0x62,0xf4,0x74,0x18,0x80,0xef,0x7b] +; CHECK-NEXT: movzbl %cl, %ecx # encoding: [0x0f,0xb6,0xc9] +; CHECK-NEXT: cmovael %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x43,0xc1] ; CHECK-NEXT: # kill: def $al killed $al killed $eax ; CHECK-NEXT: retq # encoding: [0xc3] entry: @@ -456,10 +456,10 @@ entry: define i16 @subflag16ri(i16 noundef %a) { ; CHECK-LABEL: subflag16ri: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xorl %ecx, %ecx # encoding: [0x31,0xc9] -; CHECK-NEXT: subw $1234, %di, %ax # encoding: [0x62,0xf4,0x7d,0x18,0x81,0xef,0xd2,0x04] +; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] +; CHECK-NEXT: subw $1234, %di, %cx # encoding: [0x62,0xf4,0x75,0x18,0x81,0xef,0xd2,0x04] ; CHECK-NEXT: # imm = 0x4D2 -; CHECK-NEXT: cmovbl %ecx, %eax # encoding: [0x0f,0x42,0xc1] +; CHECK-NEXT: cmovael %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x43,0xc1] ; CHECK-NEXT: # kill: def $ax killed $ax killed $eax ; CHECK-NEXT: retq # encoding: [0xc3] entry: @@ -470,10 +470,10 @@ entry: define i32 @subflag32ri(i32 noundef %a) { ; CHECK-LABEL: subflag32ri: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xorl %ecx, %ecx # encoding: [0x31,0xc9] -; CHECK-NEXT: subl $123456, %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x81,0xef,0x40,0xe2,0x01,0x00] +; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] +; CHECK-NEXT: subl $123456, %edi, %ecx # encoding: [0x62,0xf4,0x74,0x18,0x81,0xef,0x40,0xe2,0x01,0x00] ; CHECK-NEXT: # imm = 0x1E240 -; CHECK-NEXT: cmovbl %ecx, %eax # encoding: [0x0f,0x42,0xc1] +; CHECK-NEXT: cmovael %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x43,0xc1] ; CHECK-NEXT: retq # encoding: [0xc3] entry: %sub = call i32 @llvm.usub.sat.i32(i32 %a, i32 123456) @@ -486,7 +486,7 @@ define i64 @subflag64ri(i64 noundef %a) { ; CHECK-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] ; CHECK-NEXT: subq $123456, %rdi, %rcx # encoding: [0x62,0xf4,0xf4,0x18,0x81,0xef,0x40,0xe2,0x01,0x00] ; CHECK-NEXT: # imm = 0x1E240 -; CHECK-NEXT: cmovaeq %rcx, %rax # encoding: [0x48,0x0f,0x43,0xc1] +; CHECK-NEXT: cmovaeq %rcx, %rax # EVEX TO LEGACY Compression encoding: [0x48,0x0f,0x43,0xc1] ; CHECK-NEXT: retq # encoding: [0xc3] entry: %sub = call i64 @llvm.usub.sat.i64(i64 %a, i64 123456) diff --git a/llvm/test/CodeGen/X86/asm-dialect-module.ll b/llvm/test/CodeGen/X86/asm-dialect-module.ll new file mode 100644 index 0000000000000000000000000000000000000000..2c00a44424c2c358a06dd8a7a63d746ce715f580 --- /dev/null +++ b/llvm/test/CodeGen/X86/asm-dialect-module.ll @@ -0,0 +1,10 @@ +;; Test that we respect the assembler dialect when parsing module-level inline asm. +; RUN: not llc < %s -mtriple=x86_64 2>&1 | FileCheck %s --check-prefix=ERR +; RUN: llc < %s -mtriple=x86_64 -x86-asm-syntax=intel | FileCheck %s + +; ERR: <inline asm>:1:1: error: unknown use of instruction mnemonic without a size suffix + +; CHECK: .intel_syntax noprefix +; CHECK: mov eax, eax + +module asm "mov eax, eax" diff --git a/llvm/test/CodeGen/X86/avgceils.ll b/llvm/test/CodeGen/X86/avgceils.ll new file mode 100644 index 0000000000000000000000000000000000000000..4529ea275df9c7e255de67098fc728313cb12005 --- /dev/null +++ b/llvm/test/CodeGen/X86/avgceils.ll @@ -0,0 +1,3821 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-- -mattr=+sse2 | FileCheck %s --check-prefixes=SSE,SSE2 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+sse4.1 | FileCheck %s --check-prefixes=SSE,SSE4 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx | FileCheck %s --check-prefixes=AVX,AVX1 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx2 | FileCheck %s --check-prefixes=AVX,AVX2 +; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64-v4 | FileCheck %s --check-prefixes=AVX,AVX512 + +; +; 128-bit vectors +; + +define <16 x i8> @test_fixed_v16i8(<16 x i8> %a0, <16 x i8> %a1) { +; SSE-LABEL: test_fixed_v16i8: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm0, %xmm2 +; SSE-NEXT: por %xmm1, %xmm2 +; SSE-NEXT: pxor %xmm1, %xmm0 +; SSE-NEXT: psrlw $1, %xmm0 +; SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; SSE-NEXT: movdqa {{.*#+}} xmm1 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; SSE-NEXT: pxor %xmm1, %xmm0 +; SSE-NEXT: psubb %xmm0, %xmm2 +; SSE-NEXT: paddb %xmm1, %xmm2 +; SSE-NEXT: movdqa %xmm2, %xmm0 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v16i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vpor %xmm1, %xmm0, %xmm2 +; AVX1-NEXT: vpxor %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX1-NEXT: vbroadcastss {{.*#+}} xmm1 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; AVX1-NEXT: vpxor %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsubb %xmm0, %xmm2, %xmm0 +; AVX1-NEXT: vpaddb %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v16i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vpor %xmm1, %xmm0, %xmm2 +; AVX2-NEXT: vpxor %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX2-NEXT: vpbroadcastb {{.*#+}} xmm1 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; AVX2-NEXT: vpxor %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vpsubb %xmm0, %xmm2, %xmm0 +; AVX2-NEXT: vpaddb %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v16i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpor %xmm1, %xmm0, %xmm2 +; AVX512-NEXT: vpxor %xmm1, %xmm0, %xmm0 +; AVX512-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX512-NEXT: vpbroadcastb {{.*#+}} xmm1 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; AVX512-NEXT: vpternlogd $108, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm1, %xmm0 +; AVX512-NEXT: vpsubb %xmm0, %xmm2, %xmm0 +; AVX512-NEXT: vpaddb %xmm1, %xmm0, %xmm0 +; AVX512-NEXT: retq + %or = or <16 x i8> %a0, %a1 + %xor = xor <16 x i8> %a0, %a1 + %shift = ashr <16 x i8> %xor, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> + %res = sub <16 x i8> %or, %shift + ret <16 x i8> %res +} + +define <16 x i8> @test_ext_v16i8(<16 x i8> %a0, <16 x i8> %a1) { +; SSE2-LABEL: test_ext_v16i8: +; SSE2: # %bb.0: +; SSE2-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; SSE2-NEXT: psraw $8, %xmm2 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3],xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] +; SSE2-NEXT: psraw $8, %xmm3 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm1[8],xmm4[9],xmm1[9],xmm4[10],xmm1[10],xmm4[11],xmm1[11],xmm4[12],xmm1[12],xmm4[13],xmm1[13],xmm4[14],xmm1[14],xmm4[15],xmm1[15] +; SSE2-NEXT: psraw $8, %xmm4 +; SSE2-NEXT: paddw %xmm2, %xmm4 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] +; SSE2-NEXT: psraw $8, %xmm0 +; SSE2-NEXT: paddw %xmm3, %xmm0 +; SSE2-NEXT: pcmpeqd %xmm1, %xmm1 +; SSE2-NEXT: psubw %xmm1, %xmm4 +; SSE2-NEXT: psubw %xmm1, %xmm0 +; SSE2-NEXT: psrlw $1, %xmm0 +; SSE2-NEXT: psrlw $1, %xmm4 +; SSE2-NEXT: movdqa {{.*#+}} xmm1 = [255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0] +; SSE2-NEXT: pand %xmm1, %xmm4 +; SSE2-NEXT: pand %xmm1, %xmm0 +; SSE2-NEXT: packuswb %xmm4, %xmm0 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v16i8: +; SSE4: # %bb.0: +; SSE4-NEXT: pmovsxbw %xmm0, %xmm2 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm0, %xmm3 +; SSE4-NEXT: pmovsxbw %xmm1, %xmm0 +; SSE4-NEXT: paddw %xmm2, %xmm0 +; SSE4-NEXT: pshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm1, %xmm1 +; SSE4-NEXT: paddw %xmm3, %xmm1 +; SSE4-NEXT: pcmpeqd %xmm2, %xmm2 +; SSE4-NEXT: psubw %xmm2, %xmm0 +; SSE4-NEXT: psubw %xmm2, %xmm1 +; SSE4-NEXT: psrlw $1, %xmm1 +; SSE4-NEXT: psrlw $1, %xmm0 +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm2 = [255,255,255,255,255,255,255,255] +; SSE4-NEXT: pand %xmm2, %xmm0 +; SSE4-NEXT: pand %xmm2, %xmm1 +; SSE4-NEXT: packuswb %xmm1, %xmm0 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v16i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vpmovsxbw %xmm0, %xmm2 +; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm0, %xmm0 +; AVX1-NEXT: vpmovsxbw %xmm1, %xmm3 +; AVX1-NEXT: vpaddw %xmm3, %xmm2, %xmm2 +; AVX1-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm1, %xmm1 +; AVX1-NEXT: vpaddw %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1 +; AVX1-NEXT: vpsubw %xmm1, %xmm2, %xmm2 +; AVX1-NEXT: vpsubw %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm2, %xmm1 +; AVX1-NEXT: vbroadcastss {{.*#+}} xmm2 = [255,255,255,255,255,255,255,255] +; AVX1-NEXT: vpand %xmm2, %xmm1, %xmm1 +; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpackuswb %xmm0, %xmm1, %xmm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v16i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovsxbw %xmm0, %ymm0 +; AVX2-NEXT: vpmovsxbw %xmm1, %ymm1 +; AVX2-NEXT: vpaddw %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpcmpeqd %ymm1, %ymm1, %ymm1 +; AVX2-NEXT: vpsubw %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1 +; AVX2-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v16i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovsxbw %xmm0, %ymm0 +; AVX512-NEXT: vpmovsxbw %xmm1, %ymm1 +; AVX512-NEXT: vpaddw %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpcmpeqd %ymm1, %ymm1, %ymm1 +; AVX512-NEXT: vpsubw %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX512-NEXT: vpmovwb %ymm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + %x0 = sext <16 x i8> %a0 to <16 x i16> + %x1 = sext <16 x i8> %a1 to <16 x i16> + %sum = add <16 x i16> %x0, %x1 + %inc = add <16 x i16> %sum, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %shift = ashr <16 x i16> %inc, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = trunc <16 x i16> %shift to <16 x i8> + ret <16 x i8> %res +} + +define <8 x i16> @test_fixed_v8i16(<8 x i16> %a0, <8 x i16> %a1) { +; SSE-LABEL: test_fixed_v8i16: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm0, %xmm2 +; SSE-NEXT: por %xmm1, %xmm2 +; SSE-NEXT: pxor %xmm0, %xmm1 +; SSE-NEXT: psraw $1, %xmm1 +; SSE-NEXT: psubw %xmm1, %xmm2 +; SSE-NEXT: movdqa %xmm2, %xmm0 +; SSE-NEXT: retq +; +; AVX-LABEL: test_fixed_v8i16: +; AVX: # %bb.0: +; AVX-NEXT: vpor %xmm1, %xmm0, %xmm2 +; AVX-NEXT: vpxor %xmm0, %xmm1, %xmm0 +; AVX-NEXT: vpsraw $1, %xmm0, %xmm0 +; AVX-NEXT: vpsubw %xmm0, %xmm2, %xmm0 +; AVX-NEXT: retq + %or = or <8 x i16> %a0, %a1 + %xor = xor <8 x i16> %a1, %a0 + %shift = ashr <8 x i16> %xor, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = sub <8 x i16> %or, %shift + ret <8 x i16> %res +} + +define <8 x i16> @test_ext_v8i16(<8 x i16> %a0, <8 x i16> %a1) { +; SSE2-LABEL: test_ext_v8i16: +; SSE2: # %bb.0: +; SSE2-NEXT: punpcklwd {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3] +; SSE2-NEXT: psrad $16, %xmm2 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm3 = xmm3[4],xmm0[4],xmm3[5],xmm0[5],xmm3[6],xmm0[6],xmm3[7],xmm0[7] +; SSE2-NEXT: psrad $16, %xmm3 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3] +; SSE2-NEXT: psrad $16, %xmm0 +; SSE2-NEXT: paddd %xmm2, %xmm0 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm1 = xmm1[4,4,5,5,6,6,7,7] +; SSE2-NEXT: psrad $16, %xmm1 +; SSE2-NEXT: paddd %xmm3, %xmm1 +; SSE2-NEXT: pcmpeqd %xmm2, %xmm2 +; SSE2-NEXT: psubd %xmm2, %xmm0 +; SSE2-NEXT: psubd %xmm2, %xmm1 +; SSE2-NEXT: pslld $15, %xmm1 +; SSE2-NEXT: psrad $16, %xmm1 +; SSE2-NEXT: pslld $15, %xmm0 +; SSE2-NEXT: psrad $16, %xmm0 +; SSE2-NEXT: packssdw %xmm1, %xmm0 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v8i16: +; SSE4: # %bb.0: +; SSE4-NEXT: pmovsxwd %xmm0, %xmm2 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm0, %xmm3 +; SSE4-NEXT: pmovsxwd %xmm1, %xmm0 +; SSE4-NEXT: paddd %xmm2, %xmm0 +; SSE4-NEXT: pshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm1, %xmm1 +; SSE4-NEXT: paddd %xmm3, %xmm1 +; SSE4-NEXT: pcmpeqd %xmm2, %xmm2 +; SSE4-NEXT: psubd %xmm2, %xmm0 +; SSE4-NEXT: psubd %xmm2, %xmm1 +; SSE4-NEXT: psrld $1, %xmm1 +; SSE4-NEXT: psrld $1, %xmm0 +; SSE4-NEXT: pxor %xmm2, %xmm2 +; SSE4-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0],xmm2[1],xmm0[2],xmm2[3],xmm0[4],xmm2[5],xmm0[6],xmm2[7] +; SSE4-NEXT: pblendw {{.*#+}} xmm1 = xmm1[0],xmm2[1],xmm1[2],xmm2[3],xmm1[4],xmm2[5],xmm1[6],xmm2[7] +; SSE4-NEXT: packusdw %xmm1, %xmm0 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v8i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vpmovsxwd %xmm0, %xmm2 +; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm0, %xmm0 +; AVX1-NEXT: vpmovsxwd %xmm1, %xmm3 +; AVX1-NEXT: vpaddd %xmm3, %xmm2, %xmm2 +; AVX1-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm1, %xmm1 +; AVX1-NEXT: vpaddd %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1 +; AVX1-NEXT: vpsubd %xmm1, %xmm2, %xmm2 +; AVX1-NEXT: vpsubd %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrld $1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrld $1, %xmm2, %xmm1 +; AVX1-NEXT: vpxor %xmm2, %xmm2, %xmm2 +; AVX1-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0],xmm2[1],xmm1[2],xmm2[3],xmm1[4],xmm2[5],xmm1[6],xmm2[7] +; AVX1-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0],xmm2[1],xmm0[2],xmm2[3],xmm0[4],xmm2[5],xmm0[6],xmm2[7] +; AVX1-NEXT: vpackusdw %xmm0, %xmm1, %xmm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v8i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovsxwd %xmm0, %ymm0 +; AVX2-NEXT: vpmovsxwd %xmm1, %ymm1 +; AVX2-NEXT: vpaddd %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpcmpeqd %ymm1, %ymm1, %ymm1 +; AVX2-NEXT: vpsubd %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrld $1, %ymm0, %ymm0 +; AVX2-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[0,1,4,5,8,9,12,13,u,u,u,u,u,u,u,u,16,17,20,21,24,25,28,29,u,u,u,u,u,u,u,u] +; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,2,2,3] +; AVX2-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0 +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v8i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovsxwd %xmm0, %ymm0 +; AVX512-NEXT: vpmovsxwd %xmm1, %ymm1 +; AVX512-NEXT: vpaddd %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpcmpeqd %ymm1, %ymm1, %ymm1 +; AVX512-NEXT: vpsubd %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpsrld $1, %ymm0, %ymm0 +; AVX512-NEXT: vpmovdw %ymm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + %x0 = sext <8 x i16> %a0 to <8 x i32> + %x1 = sext <8 x i16> %a1 to <8 x i32> + %sum = add <8 x i32> %x0, %x1 + %inc = add <8 x i32> %sum, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %shift = ashr <8 x i32> %inc, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = trunc <8 x i32> %shift to <8 x i16> + ret <8 x i16> %res +} + +define <4 x i32> @test_fixed_v4i32(<4 x i32> %a0, <4 x i32> %a1) { +; SSE-LABEL: test_fixed_v4i32: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm0, %xmm2 +; SSE-NEXT: por %xmm1, %xmm2 +; SSE-NEXT: pxor %xmm0, %xmm1 +; SSE-NEXT: psrad $1, %xmm1 +; SSE-NEXT: psubd %xmm1, %xmm2 +; SSE-NEXT: movdqa %xmm2, %xmm0 +; SSE-NEXT: retq +; +; AVX-LABEL: test_fixed_v4i32: +; AVX: # %bb.0: +; AVX-NEXT: vpor %xmm1, %xmm0, %xmm2 +; AVX-NEXT: vpxor %xmm0, %xmm1, %xmm0 +; AVX-NEXT: vpsrad $1, %xmm0, %xmm0 +; AVX-NEXT: vpsubd %xmm0, %xmm2, %xmm0 +; AVX-NEXT: retq + %or = or <4 x i32> %a0, %a1 + %xor = xor <4 x i32> %a1, %a0 + %shift = ashr <4 x i32> %xor, <i32 1, i32 1, i32 1, i32 1> + %res = sub <4 x i32> %or, %shift + ret <4 x i32> %res +} + +define <4 x i32> @test_ext_v4i32(<4 x i32> %a0, <4 x i32> %a1) { +; SSE2-LABEL: test_ext_v4i32: +; SSE2: # %bb.0: +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm0[2,3,2,3] +; SSE2-NEXT: pxor %xmm3, %xmm3 +; SSE2-NEXT: pxor %xmm4, %xmm4 +; SSE2-NEXT: pcmpgtd %xmm2, %xmm4 +; SSE2-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm4[0],xmm2[1],xmm4[1] +; SSE2-NEXT: pxor %xmm4, %xmm4 +; SSE2-NEXT: pcmpgtd %xmm0, %xmm4 +; SSE2-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm4[0],xmm0[1],xmm4[1] +; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm1[2,3,2,3] +; SSE2-NEXT: pxor %xmm5, %xmm5 +; SSE2-NEXT: pcmpgtd %xmm4, %xmm5 +; SSE2-NEXT: punpckldq {{.*#+}} xmm4 = xmm4[0],xmm5[0],xmm4[1],xmm5[1] +; SSE2-NEXT: paddq %xmm2, %xmm4 +; SSE2-NEXT: pcmpgtd %xmm1, %xmm3 +; SSE2-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1] +; SSE2-NEXT: paddq %xmm1, %xmm0 +; SSE2-NEXT: pcmpeqd %xmm1, %xmm1 +; SSE2-NEXT: psubq %xmm1, %xmm4 +; SSE2-NEXT: psubq %xmm1, %xmm0 +; SSE2-NEXT: psrlq $1, %xmm0 +; SSE2-NEXT: psrlq $1, %xmm4 +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm4[0,2] +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v4i32: +; SSE4: # %bb.0: +; SSE4-NEXT: pshufd {{.*#+}} xmm2 = xmm0[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm2, %xmm2 +; SSE4-NEXT: pmovsxdq %xmm0, %xmm3 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm0, %xmm4 +; SSE4-NEXT: paddq %xmm2, %xmm4 +; SSE4-NEXT: pmovsxdq %xmm1, %xmm0 +; SSE4-NEXT: paddq %xmm3, %xmm0 +; SSE4-NEXT: pcmpeqd %xmm1, %xmm1 +; SSE4-NEXT: psubq %xmm1, %xmm4 +; SSE4-NEXT: psubq %xmm1, %xmm0 +; SSE4-NEXT: psrlq $1, %xmm0 +; SSE4-NEXT: psrlq $1, %xmm4 +; SSE4-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm4[0,2] +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v4i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vpshufd {{.*#+}} xmm2 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm2, %xmm2 +; AVX1-NEXT: vpmovsxdq %xmm0, %xmm0 +; AVX1-NEXT: vpshufd {{.*#+}} xmm3 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm3, %xmm3 +; AVX1-NEXT: vpaddq %xmm3, %xmm2, %xmm2 +; AVX1-NEXT: vpmovsxdq %xmm1, %xmm1 +; AVX1-NEXT: vpaddq %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1 +; AVX1-NEXT: vpsubq %xmm1, %xmm2, %xmm2 +; AVX1-NEXT: vpsubq %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlq $1, %xmm2, %xmm1 +; AVX1-NEXT: vshufps {{.*#+}} xmm0 = xmm0[0,2],xmm1[0,2] +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v4i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovsxdq %xmm0, %ymm0 +; AVX2-NEXT: vpmovsxdq %xmm1, %ymm1 +; AVX2-NEXT: vpaddq %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpcmpeqd %ymm1, %ymm1, %ymm1 +; AVX2-NEXT: vpsubq %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1 +; AVX2-NEXT: vshufps {{.*#+}} xmm0 = xmm0[0,2],xmm1[0,2] +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v4i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovsxdq %xmm0, %ymm0 +; AVX512-NEXT: vpmovsxdq %xmm1, %ymm1 +; AVX512-NEXT: vpaddq %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpcmpeqd %ymm1, %ymm1, %ymm1 +; AVX512-NEXT: vpsubq %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX512-NEXT: vpmovqd %ymm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + %x0 = sext <4 x i32> %a0 to <4 x i64> + %x1 = sext <4 x i32> %a1 to <4 x i64> + %sum = add <4 x i64> %x0, %x1 + %inc = add <4 x i64> %sum, <i64 1, i64 1, i64 1, i64 1> + %shift = ashr <4 x i64> %inc, <i64 1, i64 1, i64 1, i64 1> + %res = trunc <4 x i64> %shift to <4 x i32> + ret <4 x i32> %res +} + +define <2 x i64> @test_fixed_v2i64(<2 x i64> %a0, <2 x i64> %a1) { +; SSE2-LABEL: test_fixed_v2i64: +; SSE2: # %bb.0: +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: por %xmm1, %xmm2 +; SSE2-NEXT: pxor %xmm0, %xmm1 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[1,3,2,3] +; SSE2-NEXT: psrad $1, %xmm0 +; SSE2-NEXT: psrlq $1, %xmm1 +; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[0,2,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] +; SSE2-NEXT: psubq %xmm1, %xmm2 +; SSE2-NEXT: movdqa %xmm2, %xmm0 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_fixed_v2i64: +; SSE4: # %bb.0: +; SSE4-NEXT: movdqa %xmm0, %xmm2 +; SSE4-NEXT: por %xmm1, %xmm2 +; SSE4-NEXT: pxor %xmm0, %xmm1 +; SSE4-NEXT: movdqa %xmm1, %xmm0 +; SSE4-NEXT: psrad $1, %xmm0 +; SSE4-NEXT: psrlq $1, %xmm1 +; SSE4-NEXT: pblendw {{.*#+}} xmm1 = xmm1[0,1],xmm0[2,3],xmm1[4,5],xmm0[6,7] +; SSE4-NEXT: psubq %xmm1, %xmm2 +; SSE4-NEXT: movdqa %xmm2, %xmm0 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_fixed_v2i64: +; AVX1: # %bb.0: +; AVX1-NEXT: vpor %xmm1, %xmm0, %xmm2 +; AVX1-NEXT: vpxor %xmm0, %xmm1, %xmm0 +; AVX1-NEXT: vpsrad $1, %xmm0, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3],xmm0[4,5],xmm1[6,7] +; AVX1-NEXT: vpsubq %xmm0, %xmm2, %xmm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v2i64: +; AVX2: # %bb.0: +; AVX2-NEXT: vpor %xmm1, %xmm0, %xmm2 +; AVX2-NEXT: vpxor %xmm0, %xmm1, %xmm0 +; AVX2-NEXT: vpsrad $1, %xmm0, %xmm1 +; AVX2-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX2-NEXT: vpblendd {{.*#+}} xmm0 = xmm0[0],xmm1[1],xmm0[2],xmm1[3] +; AVX2-NEXT: vpsubq %xmm0, %xmm2, %xmm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v2i64: +; AVX512: # %bb.0: +; AVX512-NEXT: vpor %xmm1, %xmm0, %xmm2 +; AVX512-NEXT: vpxor %xmm0, %xmm1, %xmm0 +; AVX512-NEXT: vpsraq $1, %xmm0, %xmm0 +; AVX512-NEXT: vpsubq %xmm0, %xmm2, %xmm0 +; AVX512-NEXT: retq + %or = or <2 x i64> %a0, %a1 + %xor = xor <2 x i64> %a1, %a0 + %shift = ashr <2 x i64> %xor, <i64 1, i64 1> + %res = sub <2 x i64> %or, %shift + ret <2 x i64> %res +} + +define <2 x i64> @test_ext_v2i64(<2 x i64> %a0, <2 x i64> %a1) { +; SSE2-LABEL: test_ext_v2i64: +; SSE2: # %bb.0: +; SSE2-NEXT: movq %xmm0, %rax +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: sarq $63, %rcx +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %rdx +; SSE2-NEXT: movq %rdx, %rsi +; SSE2-NEXT: sarq $63, %rsi +; SSE2-NEXT: movq %xmm1, %rdi +; SSE2-NEXT: movq %rdi, %r8 +; SSE2-NEXT: sarq $63, %r8 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %r9 +; SSE2-NEXT: movq %r9, %r10 +; SSE2-NEXT: sarq $63, %r10 +; SSE2-NEXT: addq %r9, %rdx +; SSE2-NEXT: adcq %rsi, %r10 +; SSE2-NEXT: addq %rdi, %rax +; SSE2-NEXT: adcq %rcx, %r8 +; SSE2-NEXT: addq $1, %rax +; SSE2-NEXT: adcq $0, %r8 +; SSE2-NEXT: addq $1, %rdx +; SSE2-NEXT: adcq $0, %r10 +; SSE2-NEXT: shldq $63, %rdx, %r10 +; SSE2-NEXT: shldq $63, %rax, %r8 +; SSE2-NEXT: movq %r8, %xmm0 +; SSE2-NEXT: movq %r10, %xmm1 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v2i64: +; SSE4: # %bb.0: +; SSE4-NEXT: pextrq $1, %xmm0, %rax +; SSE4-NEXT: movq %rax, %rcx +; SSE4-NEXT: sarq $63, %rcx +; SSE4-NEXT: movq %xmm0, %rdx +; SSE4-NEXT: movq %rdx, %rsi +; SSE4-NEXT: sarq $63, %rsi +; SSE4-NEXT: pextrq $1, %xmm1, %rdi +; SSE4-NEXT: movq %rdi, %r8 +; SSE4-NEXT: sarq $63, %r8 +; SSE4-NEXT: movq %xmm1, %r9 +; SSE4-NEXT: movq %r9, %r10 +; SSE4-NEXT: sarq $63, %r10 +; SSE4-NEXT: addq %r9, %rdx +; SSE4-NEXT: adcq %rsi, %r10 +; SSE4-NEXT: addq %rdi, %rax +; SSE4-NEXT: adcq %rcx, %r8 +; SSE4-NEXT: addq $1, %rax +; SSE4-NEXT: adcq $0, %r8 +; SSE4-NEXT: addq $1, %rdx +; SSE4-NEXT: adcq $0, %r10 +; SSE4-NEXT: shldq $63, %rdx, %r10 +; SSE4-NEXT: shldq $63, %rax, %r8 +; SSE4-NEXT: movq %r8, %xmm1 +; SSE4-NEXT: movq %r10, %xmm0 +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE4-NEXT: retq +; +; AVX-LABEL: test_ext_v2i64: +; AVX: # %bb.0: +; AVX-NEXT: vpextrq $1, %xmm0, %rax +; AVX-NEXT: movq %rax, %rcx +; AVX-NEXT: sarq $63, %rcx +; AVX-NEXT: vmovq %xmm0, %rdx +; AVX-NEXT: movq %rdx, %rsi +; AVX-NEXT: sarq $63, %rsi +; AVX-NEXT: vpextrq $1, %xmm1, %rdi +; AVX-NEXT: movq %rdi, %r8 +; AVX-NEXT: sarq $63, %r8 +; AVX-NEXT: vmovq %xmm1, %r9 +; AVX-NEXT: movq %r9, %r10 +; AVX-NEXT: sarq $63, %r10 +; AVX-NEXT: addq %r9, %rdx +; AVX-NEXT: adcq %rsi, %r10 +; AVX-NEXT: addq %rdi, %rax +; AVX-NEXT: adcq %rcx, %r8 +; AVX-NEXT: addq $1, %rax +; AVX-NEXT: adcq $0, %r8 +; AVX-NEXT: addq $1, %rdx +; AVX-NEXT: adcq $0, %r10 +; AVX-NEXT: shldq $63, %rdx, %r10 +; AVX-NEXT: shldq $63, %rax, %r8 +; AVX-NEXT: vmovq %r8, %xmm0 +; AVX-NEXT: vmovq %r10, %xmm1 +; AVX-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX-NEXT: retq + %x0 = sext <2 x i64> %a0 to <2 x i128> + %x1 = sext <2 x i64> %a1 to <2 x i128> + %sum = add <2 x i128> %x0, %x1 + %inc = add <2 x i128> %sum, <i128 1, i128 1> + %shift = ashr <2 x i128> %inc, <i128 1, i128 1> + %res = trunc <2 x i128> %shift to <2 x i64> + ret <2 x i64> %res +} + +; +; 256-bit vectors +; + +define <32 x i8> @test_fixed_v32i8(<32 x i8> %a0, <32 x i8> %a1) { +; SSE-LABEL: test_fixed_v32i8: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm1, %xmm4 +; SSE-NEXT: por %xmm3, %xmm4 +; SSE-NEXT: movdqa %xmm0, %xmm5 +; SSE-NEXT: por %xmm2, %xmm5 +; SSE-NEXT: pxor %xmm2, %xmm0 +; SSE-NEXT: pxor %xmm3, %xmm1 +; SSE-NEXT: psrlw $1, %xmm1 +; SSE-NEXT: movdqa {{.*#+}} xmm2 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; SSE-NEXT: pand %xmm2, %xmm1 +; SSE-NEXT: movdqa {{.*#+}} xmm3 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; SSE-NEXT: pxor %xmm3, %xmm1 +; SSE-NEXT: psubb %xmm1, %xmm4 +; SSE-NEXT: psrlw $1, %xmm0 +; SSE-NEXT: pand %xmm2, %xmm0 +; SSE-NEXT: pxor %xmm3, %xmm0 +; SSE-NEXT: psubb %xmm0, %xmm5 +; SSE-NEXT: paddb %xmm3, %xmm5 +; SSE-NEXT: paddb %xmm3, %xmm4 +; SSE-NEXT: movdqa %xmm5, %xmm0 +; SSE-NEXT: movdqa %xmm4, %xmm1 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v32i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vorps %ymm1, %ymm0, %ymm2 +; AVX1-NEXT: vxorps %ymm1, %ymm0, %ymm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm1 +; AVX1-NEXT: vbroadcastss {{.*#+}} xmm3 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; AVX1-NEXT: vpand %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vbroadcastss {{.*#+}} xmm4 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; AVX1-NEXT: vpxor %xmm4, %xmm1, %xmm1 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 +; AVX1-NEXT: vpxor %xmm4, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3 +; AVX1-NEXT: vpsubb %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpaddb %xmm4, %xmm0, %xmm0 +; AVX1-NEXT: vpsubb %xmm1, %xmm2, %xmm1 +; AVX1-NEXT: vpaddb %xmm4, %xmm1, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v32i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vpor %ymm1, %ymm0, %ymm2 +; AVX2-NEXT: vpxor %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 +; AVX2-NEXT: vpbroadcastb {{.*#+}} ymm1 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; AVX2-NEXT: vpxor %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsubb %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: vpaddb %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v32i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpor %ymm1, %ymm0, %ymm2 +; AVX512-NEXT: vpxor %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX512-NEXT: vpbroadcastb {{.*#+}} ymm1 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; AVX512-NEXT: vpternlogd $108, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm1, %ymm0 +; AVX512-NEXT: vpsubb %ymm0, %ymm2, %ymm0 +; AVX512-NEXT: vpaddb %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: retq + %or = or <32 x i8> %a0, %a1 + %xor = xor <32 x i8> %a0, %a1 + %shift = ashr <32 x i8> %xor, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> + %res = sub <32 x i8> %or, %shift + ret <32 x i8> %res +} + +define <32 x i8> @test_ext_v32i8(<32 x i8> %a0, <32 x i8> %a1) { +; SSE2-LABEL: test_ext_v32i8: +; SSE2: # %bb.0: +; SSE2-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm0[8],xmm5[9],xmm0[9],xmm5[10],xmm0[10],xmm5[11],xmm0[11],xmm5[12],xmm0[12],xmm5[13],xmm0[13],xmm5[14],xmm0[14],xmm5[15],xmm0[15] +; SSE2-NEXT: psraw $8, %xmm5 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm6 = xmm6[0],xmm0[0],xmm6[1],xmm0[1],xmm6[2],xmm0[2],xmm6[3],xmm0[3],xmm6[4],xmm0[4],xmm6[5],xmm0[5],xmm6[6],xmm0[6],xmm6[7],xmm0[7] +; SSE2-NEXT: psraw $8, %xmm6 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm7 = xmm7[8],xmm1[8],xmm7[9],xmm1[9],xmm7[10],xmm1[10],xmm7[11],xmm1[11],xmm7[12],xmm1[12],xmm7[13],xmm1[13],xmm7[14],xmm1[14],xmm7[15],xmm1[15] +; SSE2-NEXT: psraw $8, %xmm7 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm8 = xmm8[0],xmm1[0],xmm8[1],xmm1[1],xmm8[2],xmm1[2],xmm8[3],xmm1[3],xmm8[4],xmm1[4],xmm8[5],xmm1[5],xmm8[6],xmm1[6],xmm8[7],xmm1[7] +; SSE2-NEXT: psraw $8, %xmm8 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm2[8],xmm4[9],xmm2[9],xmm4[10],xmm2[10],xmm4[11],xmm2[11],xmm4[12],xmm2[12],xmm4[13],xmm2[13],xmm4[14],xmm2[14],xmm4[15],xmm2[15] +; SSE2-NEXT: psraw $8, %xmm4 +; SSE2-NEXT: paddw %xmm5, %xmm4 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3],xmm0[4],xmm2[4],xmm0[5],xmm2[5],xmm0[6],xmm2[6],xmm0[7],xmm2[7] +; SSE2-NEXT: psraw $8, %xmm0 +; SSE2-NEXT: paddw %xmm6, %xmm0 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm3[8],xmm2[9],xmm3[9],xmm2[10],xmm3[10],xmm2[11],xmm3[11],xmm2[12],xmm3[12],xmm2[13],xmm3[13],xmm2[14],xmm3[14],xmm2[15],xmm3[15] +; SSE2-NEXT: psraw $8, %xmm2 +; SSE2-NEXT: paddw %xmm7, %xmm2 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1],xmm1[2],xmm3[2],xmm1[3],xmm3[3],xmm1[4],xmm3[4],xmm1[5],xmm3[5],xmm1[6],xmm3[6],xmm1[7],xmm3[7] +; SSE2-NEXT: psraw $8, %xmm1 +; SSE2-NEXT: paddw %xmm8, %xmm1 +; SSE2-NEXT: pcmpeqd %xmm3, %xmm3 +; SSE2-NEXT: psubw %xmm3, %xmm4 +; SSE2-NEXT: psubw %xmm3, %xmm0 +; SSE2-NEXT: psubw %xmm3, %xmm2 +; SSE2-NEXT: psubw %xmm3, %xmm1 +; SSE2-NEXT: psrlw $1, %xmm1 +; SSE2-NEXT: psrlw $1, %xmm2 +; SSE2-NEXT: psrlw $1, %xmm0 +; SSE2-NEXT: psrlw $1, %xmm4 +; SSE2-NEXT: movdqa {{.*#+}} xmm3 = [255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0] +; SSE2-NEXT: pand %xmm3, %xmm4 +; SSE2-NEXT: pand %xmm3, %xmm0 +; SSE2-NEXT: packuswb %xmm4, %xmm0 +; SSE2-NEXT: pand %xmm3, %xmm2 +; SSE2-NEXT: pand %xmm3, %xmm1 +; SSE2-NEXT: packuswb %xmm2, %xmm1 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v32i8: +; SSE4: # %bb.0: +; SSE4-NEXT: pmovsxbw %xmm0, %xmm4 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm0, %xmm5 +; SSE4-NEXT: pmovsxbw %xmm1, %xmm6 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm0, %xmm7 +; SSE4-NEXT: pmovsxbw %xmm2, %xmm0 +; SSE4-NEXT: paddw %xmm4, %xmm0 +; SSE4-NEXT: pshufd {{.*#+}} xmm1 = xmm2[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm1, %xmm2 +; SSE4-NEXT: paddw %xmm5, %xmm2 +; SSE4-NEXT: pmovsxbw %xmm3, %xmm1 +; SSE4-NEXT: paddw %xmm6, %xmm1 +; SSE4-NEXT: pshufd {{.*#+}} xmm3 = xmm3[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm3, %xmm3 +; SSE4-NEXT: paddw %xmm7, %xmm3 +; SSE4-NEXT: pcmpeqd %xmm4, %xmm4 +; SSE4-NEXT: psubw %xmm4, %xmm0 +; SSE4-NEXT: psubw %xmm4, %xmm2 +; SSE4-NEXT: psubw %xmm4, %xmm1 +; SSE4-NEXT: psubw %xmm4, %xmm3 +; SSE4-NEXT: psrlw $1, %xmm3 +; SSE4-NEXT: psrlw $1, %xmm1 +; SSE4-NEXT: psrlw $1, %xmm2 +; SSE4-NEXT: psrlw $1, %xmm0 +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm4 = [255,255,255,255,255,255,255,255] +; SSE4-NEXT: pand %xmm4, %xmm0 +; SSE4-NEXT: pand %xmm4, %xmm2 +; SSE4-NEXT: packuswb %xmm2, %xmm0 +; SSE4-NEXT: pand %xmm4, %xmm1 +; SSE4-NEXT: pand %xmm4, %xmm3 +; SSE4-NEXT: packuswb %xmm3, %xmm1 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v32i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm2 +; AVX1-NEXT: vpmovsxbw %xmm2, %xmm3 +; AVX1-NEXT: vpshufd {{.*#+}} xmm2 = xmm2[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm2, %xmm2 +; AVX1-NEXT: vpmovsxbw %xmm0, %xmm4 +; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm5 +; AVX1-NEXT: vpmovsxbw %xmm5, %xmm6 +; AVX1-NEXT: vpaddw %xmm6, %xmm3, %xmm3 +; AVX1-NEXT: vpshufd {{.*#+}} xmm5 = xmm5[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm5, %xmm5 +; AVX1-NEXT: vpaddw %xmm5, %xmm2, %xmm2 +; AVX1-NEXT: vpmovsxbw %xmm1, %xmm5 +; AVX1-NEXT: vpaddw %xmm5, %xmm4, %xmm4 +; AVX1-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm1, %xmm1 +; AVX1-NEXT: vpaddw %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1 +; AVX1-NEXT: vpsubw %xmm1, %xmm3, %xmm3 +; AVX1-NEXT: vpsubw %xmm1, %xmm2, %xmm2 +; AVX1-NEXT: vpsubw %xmm1, %xmm4, %xmm4 +; AVX1-NEXT: vpsubw %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm4, %xmm1 +; AVX1-NEXT: vpsrlw $1, %xmm2, %xmm2 +; AVX1-NEXT: vpsrlw $1, %xmm3, %xmm3 +; AVX1-NEXT: vbroadcastss {{.*#+}} xmm4 = [255,255,255,255,255,255,255,255] +; AVX1-NEXT: vpand %xmm4, %xmm3, %xmm3 +; AVX1-NEXT: vpand %xmm4, %xmm2, %xmm2 +; AVX1-NEXT: vpackuswb %xmm2, %xmm3, %xmm2 +; AVX1-NEXT: vpand %xmm4, %xmm1, %xmm1 +; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 +; AVX1-NEXT: vpackuswb %xmm0, %xmm1, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v32i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm2 +; AVX2-NEXT: vpmovsxbw %xmm2, %ymm2 +; AVX2-NEXT: vpmovsxbw %xmm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm3 +; AVX2-NEXT: vpmovsxbw %xmm3, %ymm3 +; AVX2-NEXT: vpaddw %ymm3, %ymm2, %ymm2 +; AVX2-NEXT: vpmovsxbw %xmm1, %ymm1 +; AVX2-NEXT: vpaddw %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpcmpeqd %ymm1, %ymm1, %ymm1 +; AVX2-NEXT: vpsubw %ymm1, %ymm2, %ymm2 +; AVX2-NEXT: vpsubw %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlw $1, %ymm2, %ymm1 +; AVX2-NEXT: vpbroadcastw {{.*#+}} ymm2 = [255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0] +; AVX2-NEXT: vpand %ymm2, %ymm1, %ymm1 +; AVX2-NEXT: vpand %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpackuswb %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,2,1,3] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v32i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovsxbw %ymm0, %zmm0 +; AVX512-NEXT: vpmovsxbw %ymm1, %zmm1 +; AVX512-NEXT: vpaddw %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpternlogd $255, %zmm1, %zmm1, %zmm1 +; AVX512-NEXT: vpsubw %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlw $1, %zmm0, %zmm0 +; AVX512-NEXT: vpmovwb %zmm0, %ymm0 +; AVX512-NEXT: retq + %x0 = sext <32 x i8> %a0 to <32 x i16> + %x1 = sext <32 x i8> %a1 to <32 x i16> + %sum = add <32 x i16> %x0, %x1 + %inc = add <32 x i16> %sum, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %shift = ashr <32 x i16> %inc, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = trunc <32 x i16> %shift to <32 x i8> + ret <32 x i8> %res +} + +define <16 x i16> @test_fixed_v16i16(<16 x i16> %a0, <16 x i16> %a1) { +; SSE-LABEL: test_fixed_v16i16: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm1, %xmm4 +; SSE-NEXT: por %xmm3, %xmm4 +; SSE-NEXT: movdqa %xmm0, %xmm5 +; SSE-NEXT: por %xmm2, %xmm5 +; SSE-NEXT: pxor %xmm0, %xmm2 +; SSE-NEXT: pxor %xmm1, %xmm3 +; SSE-NEXT: psraw $1, %xmm3 +; SSE-NEXT: psubw %xmm3, %xmm4 +; SSE-NEXT: psraw $1, %xmm2 +; SSE-NEXT: psubw %xmm2, %xmm5 +; SSE-NEXT: movdqa %xmm5, %xmm0 +; SSE-NEXT: movdqa %xmm4, %xmm1 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v16i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vorps %ymm1, %ymm0, %ymm2 +; AVX1-NEXT: vxorps %ymm0, %ymm1, %ymm0 +; AVX1-NEXT: vpsraw $1, %xmm0, %xmm1 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsraw $1, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3 +; AVX1-NEXT: vpsubw %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpsubw %xmm1, %xmm2, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v16i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vpor %ymm1, %ymm0, %ymm2 +; AVX2-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX2-NEXT: vpsraw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpsubw %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v16i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vpor %ymm1, %ymm0, %ymm2 +; AVX512-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX512-NEXT: vpsraw $1, %ymm0, %ymm0 +; AVX512-NEXT: vpsubw %ymm0, %ymm2, %ymm0 +; AVX512-NEXT: retq + %or = or <16 x i16> %a0, %a1 + %xor = xor <16 x i16> %a1, %a0 + %shift = ashr <16 x i16> %xor, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = sub <16 x i16> %or, %shift + ret <16 x i16> %res +} + +define <16 x i16> @test_ext_v16i16(<16 x i16> %a0, <16 x i16> %a1) { +; SSE2-LABEL: test_ext_v16i16: +; SSE2: # %bb.0: +; SSE2-NEXT: punpcklwd {{.*#+}} xmm4 = xmm4[0],xmm1[0],xmm4[1],xmm1[1],xmm4[2],xmm1[2],xmm4[3],xmm1[3] +; SSE2-NEXT: psrad $16, %xmm4 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm5 = xmm5[4],xmm1[4],xmm5[5],xmm1[5],xmm5[6],xmm1[6],xmm5[7],xmm1[7] +; SSE2-NEXT: psrad $16, %xmm5 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm6 = xmm6[0],xmm0[0],xmm6[1],xmm0[1],xmm6[2],xmm0[2],xmm6[3],xmm0[3] +; SSE2-NEXT: psrad $16, %xmm6 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm7 = xmm7[4],xmm0[4],xmm7[5],xmm0[5],xmm7[6],xmm0[6],xmm7[7],xmm0[7] +; SSE2-NEXT: psrad $16, %xmm7 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1],xmm1[2],xmm3[2],xmm1[3],xmm3[3] +; SSE2-NEXT: psrad $16, %xmm1 +; SSE2-NEXT: paddd %xmm4, %xmm1 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm3 = xmm3[4,4,5,5,6,6,7,7] +; SSE2-NEXT: psrad $16, %xmm3 +; SSE2-NEXT: paddd %xmm5, %xmm3 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3] +; SSE2-NEXT: psrad $16, %xmm0 +; SSE2-NEXT: paddd %xmm6, %xmm0 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm2 = xmm2[4,4,5,5,6,6,7,7] +; SSE2-NEXT: psrad $16, %xmm2 +; SSE2-NEXT: paddd %xmm7, %xmm2 +; SSE2-NEXT: pcmpeqd %xmm4, %xmm4 +; SSE2-NEXT: psubd %xmm4, %xmm1 +; SSE2-NEXT: psubd %xmm4, %xmm3 +; SSE2-NEXT: psubd %xmm4, %xmm0 +; SSE2-NEXT: psubd %xmm4, %xmm2 +; SSE2-NEXT: pslld $15, %xmm2 +; SSE2-NEXT: psrad $16, %xmm2 +; SSE2-NEXT: pslld $15, %xmm0 +; SSE2-NEXT: psrad $16, %xmm0 +; SSE2-NEXT: packssdw %xmm2, %xmm0 +; SSE2-NEXT: pslld $15, %xmm3 +; SSE2-NEXT: psrad $16, %xmm3 +; SSE2-NEXT: pslld $15, %xmm1 +; SSE2-NEXT: psrad $16, %xmm1 +; SSE2-NEXT: packssdw %xmm3, %xmm1 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v16i16: +; SSE4: # %bb.0: +; SSE4-NEXT: pmovsxwd %xmm0, %xmm4 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm0, %xmm5 +; SSE4-NEXT: pmovsxwd %xmm1, %xmm6 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm0, %xmm7 +; SSE4-NEXT: pmovsxwd %xmm2, %xmm0 +; SSE4-NEXT: paddd %xmm4, %xmm0 +; SSE4-NEXT: pshufd {{.*#+}} xmm1 = xmm2[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm1, %xmm2 +; SSE4-NEXT: paddd %xmm5, %xmm2 +; SSE4-NEXT: pmovsxwd %xmm3, %xmm1 +; SSE4-NEXT: paddd %xmm6, %xmm1 +; SSE4-NEXT: pshufd {{.*#+}} xmm3 = xmm3[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm3, %xmm3 +; SSE4-NEXT: paddd %xmm7, %xmm3 +; SSE4-NEXT: pcmpeqd %xmm4, %xmm4 +; SSE4-NEXT: psubd %xmm4, %xmm0 +; SSE4-NEXT: psubd %xmm4, %xmm2 +; SSE4-NEXT: psubd %xmm4, %xmm1 +; SSE4-NEXT: psubd %xmm4, %xmm3 +; SSE4-NEXT: psrld $1, %xmm3 +; SSE4-NEXT: psrld $1, %xmm1 +; SSE4-NEXT: psrld $1, %xmm2 +; SSE4-NEXT: psrld $1, %xmm0 +; SSE4-NEXT: pxor %xmm4, %xmm4 +; SSE4-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0],xmm4[1],xmm0[2],xmm4[3],xmm0[4],xmm4[5],xmm0[6],xmm4[7] +; SSE4-NEXT: pblendw {{.*#+}} xmm2 = xmm2[0],xmm4[1],xmm2[2],xmm4[3],xmm2[4],xmm4[5],xmm2[6],xmm4[7] +; SSE4-NEXT: packusdw %xmm2, %xmm0 +; SSE4-NEXT: pblendw {{.*#+}} xmm1 = xmm1[0],xmm4[1],xmm1[2],xmm4[3],xmm1[4],xmm4[5],xmm1[6],xmm4[7] +; SSE4-NEXT: pblendw {{.*#+}} xmm3 = xmm3[0],xmm4[1],xmm3[2],xmm4[3],xmm3[4],xmm4[5],xmm3[6],xmm4[7] +; SSE4-NEXT: packusdw %xmm3, %xmm1 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v16i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm2 +; AVX1-NEXT: vpmovsxwd %xmm2, %xmm3 +; AVX1-NEXT: vpshufd {{.*#+}} xmm2 = xmm2[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm2, %xmm2 +; AVX1-NEXT: vpmovsxwd %xmm0, %xmm4 +; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm5 +; AVX1-NEXT: vpmovsxwd %xmm5, %xmm6 +; AVX1-NEXT: vpaddd %xmm6, %xmm3, %xmm3 +; AVX1-NEXT: vpshufd {{.*#+}} xmm5 = xmm5[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm5, %xmm5 +; AVX1-NEXT: vpaddd %xmm5, %xmm2, %xmm2 +; AVX1-NEXT: vpmovsxwd %xmm1, %xmm5 +; AVX1-NEXT: vpaddd %xmm5, %xmm4, %xmm4 +; AVX1-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm1, %xmm1 +; AVX1-NEXT: vpaddd %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1 +; AVX1-NEXT: vpsubd %xmm1, %xmm3, %xmm3 +; AVX1-NEXT: vpsubd %xmm1, %xmm2, %xmm2 +; AVX1-NEXT: vpsubd %xmm1, %xmm4, %xmm4 +; AVX1-NEXT: vpsubd %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrld $1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrld $1, %xmm4, %xmm1 +; AVX1-NEXT: vpsrld $1, %xmm2, %xmm2 +; AVX1-NEXT: vpsrld $1, %xmm3, %xmm3 +; AVX1-NEXT: vpxor %xmm4, %xmm4, %xmm4 +; AVX1-NEXT: vpblendw {{.*#+}} xmm3 = xmm3[0],xmm4[1],xmm3[2],xmm4[3],xmm3[4],xmm4[5],xmm3[6],xmm4[7] +; AVX1-NEXT: vpblendw {{.*#+}} xmm2 = xmm2[0],xmm4[1],xmm2[2],xmm4[3],xmm2[4],xmm4[5],xmm2[6],xmm4[7] +; AVX1-NEXT: vpackusdw %xmm2, %xmm3, %xmm2 +; AVX1-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0],xmm4[1],xmm1[2],xmm4[3],xmm1[4],xmm4[5],xmm1[6],xmm4[7] +; AVX1-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0],xmm4[1],xmm0[2],xmm4[3],xmm0[4],xmm4[5],xmm0[6],xmm4[7] +; AVX1-NEXT: vpackusdw %xmm0, %xmm1, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v16i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm2 +; AVX2-NEXT: vpmovsxwd %xmm2, %ymm2 +; AVX2-NEXT: vpmovsxwd %xmm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm3 +; AVX2-NEXT: vpmovsxwd %xmm3, %ymm3 +; AVX2-NEXT: vpaddd %ymm3, %ymm2, %ymm2 +; AVX2-NEXT: vpmovsxwd %xmm1, %ymm1 +; AVX2-NEXT: vpaddd %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpcmpeqd %ymm1, %ymm1, %ymm1 +; AVX2-NEXT: vpsubd %ymm1, %ymm2, %ymm2 +; AVX2-NEXT: vpsubd %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrld $1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrld $1, %ymm2, %ymm1 +; AVX2-NEXT: vpxor %xmm2, %xmm2, %xmm2 +; AVX2-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0],ymm2[1],ymm1[2],ymm2[3],ymm1[4],ymm2[5],ymm1[6],ymm2[7],ymm1[8],ymm2[9],ymm1[10],ymm2[11],ymm1[12],ymm2[13],ymm1[14],ymm2[15] +; AVX2-NEXT: vpblendw {{.*#+}} ymm0 = ymm0[0],ymm2[1],ymm0[2],ymm2[3],ymm0[4],ymm2[5],ymm0[6],ymm2[7],ymm0[8],ymm2[9],ymm0[10],ymm2[11],ymm0[12],ymm2[13],ymm0[14],ymm2[15] +; AVX2-NEXT: vpackusdw %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,2,1,3] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v16i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovsxwd %ymm0, %zmm0 +; AVX512-NEXT: vpmovsxwd %ymm1, %zmm1 +; AVX512-NEXT: vpaddd %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpternlogd $255, %zmm1, %zmm1, %zmm1 +; AVX512-NEXT: vpsubd %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrld $1, %zmm0, %zmm0 +; AVX512-NEXT: vpmovdw %zmm0, %ymm0 +; AVX512-NEXT: retq + %x0 = sext <16 x i16> %a0 to <16 x i32> + %x1 = sext <16 x i16> %a1 to <16 x i32> + %sum = add <16 x i32> %x0, %x1 + %inc = add <16 x i32> %sum, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %shift = ashr <16 x i32> %inc, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = trunc <16 x i32> %shift to <16 x i16> + ret <16 x i16> %res +} + +define <8 x i32> @test_fixed_v8i32(<8 x i32> %a0, <8 x i32> %a1) { +; SSE-LABEL: test_fixed_v8i32: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm1, %xmm4 +; SSE-NEXT: por %xmm3, %xmm4 +; SSE-NEXT: movdqa %xmm0, %xmm5 +; SSE-NEXT: por %xmm2, %xmm5 +; SSE-NEXT: pxor %xmm0, %xmm2 +; SSE-NEXT: pxor %xmm1, %xmm3 +; SSE-NEXT: psrad $1, %xmm3 +; SSE-NEXT: psubd %xmm3, %xmm4 +; SSE-NEXT: psrad $1, %xmm2 +; SSE-NEXT: psubd %xmm2, %xmm5 +; SSE-NEXT: movdqa %xmm5, %xmm0 +; SSE-NEXT: movdqa %xmm4, %xmm1 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v8i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vorps %ymm1, %ymm0, %ymm2 +; AVX1-NEXT: vxorps %ymm0, %ymm1, %ymm0 +; AVX1-NEXT: vpsrad $1, %xmm0, %xmm1 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrad $1, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3 +; AVX1-NEXT: vpsubd %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpsubd %xmm1, %xmm2, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v8i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vpor %ymm1, %ymm0, %ymm2 +; AVX2-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX2-NEXT: vpsrad $1, %ymm0, %ymm0 +; AVX2-NEXT: vpsubd %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v8i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vpor %ymm1, %ymm0, %ymm2 +; AVX512-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX512-NEXT: vpsrad $1, %ymm0, %ymm0 +; AVX512-NEXT: vpsubd %ymm0, %ymm2, %ymm0 +; AVX512-NEXT: retq + %or = or <8 x i32> %a0, %a1 + %xor = xor <8 x i32> %a1, %a0 + %shift = ashr <8 x i32> %xor, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = sub <8 x i32> %or, %shift + ret <8 x i32> %res +} + +define <8 x i32> @test_ext_v8i32(<8 x i32> %a0, <8 x i32> %a1) { +; SSE2-LABEL: test_ext_v8i32: +; SSE2: # %bb.0: +; SSE2-NEXT: pshufd {{.*#+}} xmm6 = xmm0[2,3,2,3] +; SSE2-NEXT: pxor %xmm5, %xmm5 +; SSE2-NEXT: pxor %xmm4, %xmm4 +; SSE2-NEXT: pcmpgtd %xmm6, %xmm4 +; SSE2-NEXT: punpckldq {{.*#+}} xmm6 = xmm6[0],xmm4[0],xmm6[1],xmm4[1] +; SSE2-NEXT: pxor %xmm4, %xmm4 +; SSE2-NEXT: pcmpgtd %xmm0, %xmm4 +; SSE2-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm4[0],xmm0[1],xmm4[1] +; SSE2-NEXT: pshufd {{.*#+}} xmm7 = xmm1[2,3,2,3] +; SSE2-NEXT: pxor %xmm4, %xmm4 +; SSE2-NEXT: pcmpgtd %xmm7, %xmm4 +; SSE2-NEXT: punpckldq {{.*#+}} xmm7 = xmm7[0],xmm4[0],xmm7[1],xmm4[1] +; SSE2-NEXT: pxor %xmm4, %xmm4 +; SSE2-NEXT: pcmpgtd %xmm1, %xmm4 +; SSE2-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1] +; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm2[2,3,2,3] +; SSE2-NEXT: pxor %xmm8, %xmm8 +; SSE2-NEXT: pcmpgtd %xmm4, %xmm8 +; SSE2-NEXT: punpckldq {{.*#+}} xmm4 = xmm4[0],xmm8[0],xmm4[1],xmm8[1] +; SSE2-NEXT: paddq %xmm6, %xmm4 +; SSE2-NEXT: pxor %xmm6, %xmm6 +; SSE2-NEXT: pcmpgtd %xmm2, %xmm6 +; SSE2-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm6[0],xmm2[1],xmm6[1] +; SSE2-NEXT: paddq %xmm2, %xmm0 +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm3[2,3,2,3] +; SSE2-NEXT: pxor %xmm6, %xmm6 +; SSE2-NEXT: pcmpgtd %xmm2, %xmm6 +; SSE2-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm6[0],xmm2[1],xmm6[1] +; SSE2-NEXT: paddq %xmm7, %xmm2 +; SSE2-NEXT: pcmpgtd %xmm3, %xmm5 +; SSE2-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm5[0],xmm3[1],xmm5[1] +; SSE2-NEXT: paddq %xmm3, %xmm1 +; SSE2-NEXT: pcmpeqd %xmm3, %xmm3 +; SSE2-NEXT: psubq %xmm3, %xmm4 +; SSE2-NEXT: psubq %xmm3, %xmm0 +; SSE2-NEXT: psubq %xmm3, %xmm2 +; SSE2-NEXT: psubq %xmm3, %xmm1 +; SSE2-NEXT: psrlq $1, %xmm1 +; SSE2-NEXT: psrlq $1, %xmm2 +; SSE2-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] +; SSE2-NEXT: psrlq $1, %xmm0 +; SSE2-NEXT: psrlq $1, %xmm4 +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm4[0,2] +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v8i32: +; SSE4: # %bb.0: +; SSE4-NEXT: pshufd {{.*#+}} xmm4 = xmm0[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm4, %xmm5 +; SSE4-NEXT: pmovsxdq %xmm0, %xmm6 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm0, %xmm7 +; SSE4-NEXT: pmovsxdq %xmm1, %xmm8 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm2[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm0, %xmm4 +; SSE4-NEXT: paddq %xmm5, %xmm4 +; SSE4-NEXT: pmovsxdq %xmm2, %xmm0 +; SSE4-NEXT: paddq %xmm6, %xmm0 +; SSE4-NEXT: pshufd {{.*#+}} xmm1 = xmm3[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm1, %xmm2 +; SSE4-NEXT: paddq %xmm7, %xmm2 +; SSE4-NEXT: pmovsxdq %xmm3, %xmm1 +; SSE4-NEXT: paddq %xmm8, %xmm1 +; SSE4-NEXT: pcmpeqd %xmm3, %xmm3 +; SSE4-NEXT: psubq %xmm3, %xmm4 +; SSE4-NEXT: psubq %xmm3, %xmm0 +; SSE4-NEXT: psubq %xmm3, %xmm2 +; SSE4-NEXT: psubq %xmm3, %xmm1 +; SSE4-NEXT: psrlq $1, %xmm1 +; SSE4-NEXT: psrlq $1, %xmm2 +; SSE4-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] +; SSE4-NEXT: psrlq $1, %xmm0 +; SSE4-NEXT: psrlq $1, %xmm4 +; SSE4-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm4[0,2] +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v8i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vpmovsxdq %xmm0, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm3 +; AVX1-NEXT: vpmovsxdq %xmm3, %xmm4 +; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm0, %xmm0 +; AVX1-NEXT: vpshufd {{.*#+}} xmm3 = xmm3[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm3, %xmm3 +; AVX1-NEXT: vpmovsxdq %xmm1, %xmm5 +; AVX1-NEXT: vpaddq %xmm5, %xmm2, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm5 +; AVX1-NEXT: vpmovsxdq %xmm5, %xmm6 +; AVX1-NEXT: vpaddq %xmm6, %xmm4, %xmm4 +; AVX1-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm1, %xmm1 +; AVX1-NEXT: vpaddq %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpshufd {{.*#+}} xmm1 = xmm5[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm1, %xmm1 +; AVX1-NEXT: vpaddq %xmm1, %xmm3, %xmm1 +; AVX1-NEXT: vpcmpeqd %xmm3, %xmm3, %xmm3 +; AVX1-NEXT: vpsubq %xmm3, %xmm2, %xmm2 +; AVX1-NEXT: vpsubq %xmm3, %xmm4, %xmm4 +; AVX1-NEXT: vpsubq %xmm3, %xmm0, %xmm0 +; AVX1-NEXT: vpsubq %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlq $1, %xmm4, %xmm3 +; AVX1-NEXT: vpsrlq $1, %xmm2, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX1-NEXT: vshufps {{.*#+}} ymm0 = ymm2[0,2],ymm0[0,2],ymm2[4,6],ymm0[4,6] +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v8i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovsxdq %xmm0, %ymm2 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX2-NEXT: vpmovsxdq %xmm0, %ymm0 +; AVX2-NEXT: vpmovsxdq %xmm1, %ymm3 +; AVX2-NEXT: vpaddq %ymm3, %ymm2, %ymm2 +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm1 +; AVX2-NEXT: vpmovsxdq %xmm1, %ymm1 +; AVX2-NEXT: vpaddq %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpcmpeqd %ymm1, %ymm1, %ymm1 +; AVX2-NEXT: vpsubq %ymm1, %ymm2, %ymm2 +; AVX2-NEXT: vpsubq %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vperm2i128 {{.*#+}} ymm1 = ymm2[2,3],ymm0[2,3] +; AVX2-NEXT: vpsrlq $1, %ymm1, %ymm1 +; AVX2-NEXT: vinserti128 $1, %xmm0, %ymm2, %ymm0 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vshufps {{.*#+}} ymm0 = ymm0[0,2],ymm1[0,2],ymm0[4,6],ymm1[4,6] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v8i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovsxdq %ymm0, %zmm0 +; AVX512-NEXT: vpmovsxdq %ymm1, %zmm1 +; AVX512-NEXT: vpaddq %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpternlogd $255, %zmm1, %zmm1, %zmm1 +; AVX512-NEXT: vpsubq %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlq $1, %zmm0, %zmm0 +; AVX512-NEXT: vpmovqd %zmm0, %ymm0 +; AVX512-NEXT: retq + %x0 = sext <8 x i32> %a0 to <8 x i64> + %x1 = sext <8 x i32> %a1 to <8 x i64> + %sum = add <8 x i64> %x0, %x1 + %inc = add <8 x i64> %sum, <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1> + %shift = ashr <8 x i64> %inc, <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1> + %res = trunc <8 x i64> %shift to <8 x i32> + ret <8 x i32> %res +} + +define <4 x i64> @test_fixed_v4i64(<4 x i64> %a0, <4 x i64> %a1) { +; SSE2-LABEL: test_fixed_v4i64: +; SSE2: # %bb.0: +; SSE2-NEXT: movdqa %xmm1, %xmm4 +; SSE2-NEXT: por %xmm3, %xmm4 +; SSE2-NEXT: movdqa %xmm0, %xmm5 +; SSE2-NEXT: por %xmm2, %xmm5 +; SSE2-NEXT: pxor %xmm0, %xmm2 +; SSE2-NEXT: pxor %xmm1, %xmm3 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm3[1,3,2,3] +; SSE2-NEXT: psrad $1, %xmm0 +; SSE2-NEXT: psrlq $1, %xmm3 +; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm3[0,2,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] +; SSE2-NEXT: psubq %xmm1, %xmm4 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm2[1,3,2,3] +; SSE2-NEXT: psrad $1, %xmm0 +; SSE2-NEXT: psrlq $1, %xmm2 +; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm2[0,2,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] +; SSE2-NEXT: psubq %xmm1, %xmm5 +; SSE2-NEXT: movdqa %xmm5, %xmm0 +; SSE2-NEXT: movdqa %xmm4, %xmm1 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_fixed_v4i64: +; SSE4: # %bb.0: +; SSE4-NEXT: movdqa %xmm1, %xmm4 +; SSE4-NEXT: por %xmm3, %xmm4 +; SSE4-NEXT: movdqa %xmm0, %xmm5 +; SSE4-NEXT: por %xmm2, %xmm5 +; SSE4-NEXT: pxor %xmm0, %xmm2 +; SSE4-NEXT: pxor %xmm1, %xmm3 +; SSE4-NEXT: movdqa %xmm3, %xmm0 +; SSE4-NEXT: psrad $1, %xmm0 +; SSE4-NEXT: psrlq $1, %xmm3 +; SSE4-NEXT: pblendw {{.*#+}} xmm3 = xmm3[0,1],xmm0[2,3],xmm3[4,5],xmm0[6,7] +; SSE4-NEXT: psubq %xmm3, %xmm4 +; SSE4-NEXT: movdqa %xmm2, %xmm0 +; SSE4-NEXT: psrad $1, %xmm0 +; SSE4-NEXT: psrlq $1, %xmm2 +; SSE4-NEXT: pblendw {{.*#+}} xmm2 = xmm2[0,1],xmm0[2,3],xmm2[4,5],xmm0[6,7] +; SSE4-NEXT: psubq %xmm2, %xmm5 +; SSE4-NEXT: movdqa %xmm5, %xmm0 +; SSE4-NEXT: movdqa %xmm4, %xmm1 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_fixed_v4i64: +; AVX1: # %bb.0: +; AVX1-NEXT: vorps %ymm1, %ymm0, %ymm2 +; AVX1-NEXT: vxorps %ymm0, %ymm1, %ymm0 +; AVX1-NEXT: vpsrad $1, %xmm0, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm3 +; AVX1-NEXT: vpblendw {{.*#+}} xmm1 = xmm3[0,1],xmm1[2,3],xmm3[4,5],xmm1[6,7] +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrad $1, %xmm0, %xmm3 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0,1],xmm3[2,3],xmm0[4,5],xmm3[6,7] +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3 +; AVX1-NEXT: vpsubq %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpsubq %xmm1, %xmm2, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v4i64: +; AVX2: # %bb.0: +; AVX2-NEXT: vpor %ymm1, %ymm0, %ymm2 +; AVX2-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX2-NEXT: vpsrad $1, %ymm0, %ymm1 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vpblendd {{.*#+}} ymm0 = ymm0[0],ymm1[1],ymm0[2],ymm1[3],ymm0[4],ymm1[5],ymm0[6],ymm1[7] +; AVX2-NEXT: vpsubq %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v4i64: +; AVX512: # %bb.0: +; AVX512-NEXT: vpor %ymm1, %ymm0, %ymm2 +; AVX512-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX512-NEXT: vpsraq $1, %ymm0, %ymm0 +; AVX512-NEXT: vpsubq %ymm0, %ymm2, %ymm0 +; AVX512-NEXT: retq + %or = or <4 x i64> %a0, %a1 + %xor = xor <4 x i64> %a1, %a0 + %shift = ashr <4 x i64> %xor, <i64 1, i64 1, i64 1, i64 1> + %res = sub <4 x i64> %or, %shift + ret <4 x i64> %res +} + +define <4 x i64> @test_ext_v4i64(<4 x i64> %a0, <4 x i64> %a1) { +; SSE2-LABEL: test_ext_v4i64: +; SSE2: # %bb.0: +; SSE2-NEXT: pushq %rbp +; SSE2-NEXT: .cfi_def_cfa_offset 16 +; SSE2-NEXT: pushq %r15 +; SSE2-NEXT: .cfi_def_cfa_offset 24 +; SSE2-NEXT: pushq %r14 +; SSE2-NEXT: .cfi_def_cfa_offset 32 +; SSE2-NEXT: pushq %r13 +; SSE2-NEXT: .cfi_def_cfa_offset 40 +; SSE2-NEXT: pushq %r12 +; SSE2-NEXT: .cfi_def_cfa_offset 48 +; SSE2-NEXT: pushq %rbx +; SSE2-NEXT: .cfi_def_cfa_offset 56 +; SSE2-NEXT: .cfi_offset %rbx, -56 +; SSE2-NEXT: .cfi_offset %r12, -48 +; SSE2-NEXT: .cfi_offset %r13, -40 +; SSE2-NEXT: .cfi_offset %r14, -32 +; SSE2-NEXT: .cfi_offset %r15, -24 +; SSE2-NEXT: .cfi_offset %rbp, -16 +; SSE2-NEXT: movq %xmm0, %r11 +; SSE2-NEXT: movq %r11, %r12 +; SSE2-NEXT: sarq $63, %r12 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %rcx +; SSE2-NEXT: movq %rcx, %rbx +; SSE2-NEXT: sarq $63, %rbx +; SSE2-NEXT: movq %xmm1, %rdx +; SSE2-NEXT: movq %rdx, %r14 +; SSE2-NEXT: sarq $63, %r14 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %r9 +; SSE2-NEXT: movq %r9, %r15 +; SSE2-NEXT: sarq $63, %r15 +; SSE2-NEXT: movq %xmm2, %rsi +; SSE2-NEXT: movq %rsi, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: sarq $63, %rsi +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm2[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %r13 +; SSE2-NEXT: movq %r13, %r8 +; SSE2-NEXT: sarq $63, %r8 +; SSE2-NEXT: movq %xmm3, %rbp +; SSE2-NEXT: movq %rbp, %rdi +; SSE2-NEXT: sarq $63, %rdi +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm3[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %rax +; SSE2-NEXT: movq %rax, %r10 +; SSE2-NEXT: sarq $63, %r10 +; SSE2-NEXT: addq %rax, %r9 +; SSE2-NEXT: adcq %r15, %r10 +; SSE2-NEXT: addq %rbp, %rdx +; SSE2-NEXT: adcq %r14, %rdi +; SSE2-NEXT: addq %r13, %rcx +; SSE2-NEXT: adcq %rbx, %r8 +; SSE2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Folded Reload +; SSE2-NEXT: adcq %r12, %rsi +; SSE2-NEXT: addq $1, %r11 +; SSE2-NEXT: adcq $0, %rsi +; SSE2-NEXT: addq $1, %rcx +; SSE2-NEXT: adcq $0, %r8 +; SSE2-NEXT: addq $1, %rdx +; SSE2-NEXT: adcq $0, %rdi +; SSE2-NEXT: addq $1, %r9 +; SSE2-NEXT: adcq $0, %r10 +; SSE2-NEXT: shldq $63, %r9, %r10 +; SSE2-NEXT: shldq $63, %rdx, %rdi +; SSE2-NEXT: shldq $63, %rcx, %r8 +; SSE2-NEXT: shldq $63, %r11, %rsi +; SSE2-NEXT: movq %rsi, %xmm0 +; SSE2-NEXT: movq %r8, %xmm2 +; SSE2-NEXT: movq %rdi, %xmm1 +; SSE2-NEXT: movq %r10, %xmm3 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm2[0] +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm3[0] +; SSE2-NEXT: popq %rbx +; SSE2-NEXT: .cfi_def_cfa_offset 48 +; SSE2-NEXT: popq %r12 +; SSE2-NEXT: .cfi_def_cfa_offset 40 +; SSE2-NEXT: popq %r13 +; SSE2-NEXT: .cfi_def_cfa_offset 32 +; SSE2-NEXT: popq %r14 +; SSE2-NEXT: .cfi_def_cfa_offset 24 +; SSE2-NEXT: popq %r15 +; SSE2-NEXT: .cfi_def_cfa_offset 16 +; SSE2-NEXT: popq %rbp +; SSE2-NEXT: .cfi_def_cfa_offset 8 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v4i64: +; SSE4: # %bb.0: +; SSE4-NEXT: pushq %rbp +; SSE4-NEXT: .cfi_def_cfa_offset 16 +; SSE4-NEXT: pushq %r15 +; SSE4-NEXT: .cfi_def_cfa_offset 24 +; SSE4-NEXT: pushq %r14 +; SSE4-NEXT: .cfi_def_cfa_offset 32 +; SSE4-NEXT: pushq %r13 +; SSE4-NEXT: .cfi_def_cfa_offset 40 +; SSE4-NEXT: pushq %r12 +; SSE4-NEXT: .cfi_def_cfa_offset 48 +; SSE4-NEXT: pushq %rbx +; SSE4-NEXT: .cfi_def_cfa_offset 56 +; SSE4-NEXT: .cfi_offset %rbx, -56 +; SSE4-NEXT: .cfi_offset %r12, -48 +; SSE4-NEXT: .cfi_offset %r13, -40 +; SSE4-NEXT: .cfi_offset %r14, -32 +; SSE4-NEXT: .cfi_offset %r15, -24 +; SSE4-NEXT: .cfi_offset %rbp, -16 +; SSE4-NEXT: pextrq $1, %xmm0, %r11 +; SSE4-NEXT: movq %r11, %r12 +; SSE4-NEXT: sarq $63, %r12 +; SSE4-NEXT: movq %xmm0, %rcx +; SSE4-NEXT: movq %rcx, %rbx +; SSE4-NEXT: sarq $63, %rbx +; SSE4-NEXT: pextrq $1, %xmm1, %rdx +; SSE4-NEXT: movq %rdx, %r14 +; SSE4-NEXT: sarq $63, %r14 +; SSE4-NEXT: movq %xmm1, %r9 +; SSE4-NEXT: movq %r9, %r15 +; SSE4-NEXT: sarq $63, %r15 +; SSE4-NEXT: pextrq $1, %xmm2, %rsi +; SSE4-NEXT: movq %rsi, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: sarq $63, %rsi +; SSE4-NEXT: movq %xmm2, %r13 +; SSE4-NEXT: movq %r13, %r8 +; SSE4-NEXT: sarq $63, %r8 +; SSE4-NEXT: pextrq $1, %xmm3, %rbp +; SSE4-NEXT: movq %rbp, %rdi +; SSE4-NEXT: sarq $63, %rdi +; SSE4-NEXT: movq %xmm3, %rax +; SSE4-NEXT: movq %rax, %r10 +; SSE4-NEXT: sarq $63, %r10 +; SSE4-NEXT: addq %rax, %r9 +; SSE4-NEXT: adcq %r15, %r10 +; SSE4-NEXT: addq %rbp, %rdx +; SSE4-NEXT: adcq %r14, %rdi +; SSE4-NEXT: addq %r13, %rcx +; SSE4-NEXT: adcq %rbx, %r8 +; SSE4-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Folded Reload +; SSE4-NEXT: adcq %r12, %rsi +; SSE4-NEXT: addq $1, %r11 +; SSE4-NEXT: adcq $0, %rsi +; SSE4-NEXT: addq $1, %rcx +; SSE4-NEXT: adcq $0, %r8 +; SSE4-NEXT: addq $1, %rdx +; SSE4-NEXT: adcq $0, %rdi +; SSE4-NEXT: addq $1, %r9 +; SSE4-NEXT: adcq $0, %r10 +; SSE4-NEXT: shldq $63, %r9, %r10 +; SSE4-NEXT: shldq $63, %rdx, %rdi +; SSE4-NEXT: shldq $63, %rcx, %r8 +; SSE4-NEXT: shldq $63, %r11, %rsi +; SSE4-NEXT: movq %rsi, %xmm2 +; SSE4-NEXT: movq %r8, %xmm0 +; SSE4-NEXT: movq %rdi, %xmm3 +; SSE4-NEXT: movq %r10, %xmm1 +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm2[0] +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm3[0] +; SSE4-NEXT: popq %rbx +; SSE4-NEXT: .cfi_def_cfa_offset 48 +; SSE4-NEXT: popq %r12 +; SSE4-NEXT: .cfi_def_cfa_offset 40 +; SSE4-NEXT: popq %r13 +; SSE4-NEXT: .cfi_def_cfa_offset 32 +; SSE4-NEXT: popq %r14 +; SSE4-NEXT: .cfi_def_cfa_offset 24 +; SSE4-NEXT: popq %r15 +; SSE4-NEXT: .cfi_def_cfa_offset 16 +; SSE4-NEXT: popq %rbp +; SSE4-NEXT: .cfi_def_cfa_offset 8 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v4i64: +; AVX1: # %bb.0: +; AVX1-NEXT: pushq %rbp +; AVX1-NEXT: .cfi_def_cfa_offset 16 +; AVX1-NEXT: pushq %r15 +; AVX1-NEXT: .cfi_def_cfa_offset 24 +; AVX1-NEXT: pushq %r14 +; AVX1-NEXT: .cfi_def_cfa_offset 32 +; AVX1-NEXT: pushq %r13 +; AVX1-NEXT: .cfi_def_cfa_offset 40 +; AVX1-NEXT: pushq %r12 +; AVX1-NEXT: .cfi_def_cfa_offset 48 +; AVX1-NEXT: pushq %rbx +; AVX1-NEXT: .cfi_def_cfa_offset 56 +; AVX1-NEXT: .cfi_offset %rbx, -56 +; AVX1-NEXT: .cfi_offset %r12, -48 +; AVX1-NEXT: .cfi_offset %r13, -40 +; AVX1-NEXT: .cfi_offset %r14, -32 +; AVX1-NEXT: .cfi_offset %r15, -24 +; AVX1-NEXT: .cfi_offset %rbp, -16 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm2 +; AVX1-NEXT: vpextrq $1, %xmm2, %r11 +; AVX1-NEXT: movq %r11, %r12 +; AVX1-NEXT: sarq $63, %r12 +; AVX1-NEXT: vmovq %xmm2, %rcx +; AVX1-NEXT: movq %rcx, %rbx +; AVX1-NEXT: sarq $63, %rbx +; AVX1-NEXT: vpextrq $1, %xmm0, %rdx +; AVX1-NEXT: movq %rdx, %r14 +; AVX1-NEXT: sarq $63, %r14 +; AVX1-NEXT: vmovq %xmm0, %r8 +; AVX1-NEXT: movq %r8, %r15 +; AVX1-NEXT: sarq $63, %r15 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm0 +; AVX1-NEXT: vpextrq $1, %xmm0, %rsi +; AVX1-NEXT: movq %rsi, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: sarq $63, %rsi +; AVX1-NEXT: vmovq %xmm0, %r13 +; AVX1-NEXT: movq %r13, %rdi +; AVX1-NEXT: sarq $63, %rdi +; AVX1-NEXT: vpextrq $1, %xmm1, %rbp +; AVX1-NEXT: movq %rbp, %r9 +; AVX1-NEXT: sarq $63, %r9 +; AVX1-NEXT: vmovq %xmm1, %rax +; AVX1-NEXT: movq %rax, %r10 +; AVX1-NEXT: sarq $63, %r10 +; AVX1-NEXT: addq %rax, %r8 +; AVX1-NEXT: adcq %r15, %r10 +; AVX1-NEXT: addq %rbp, %rdx +; AVX1-NEXT: adcq %r14, %r9 +; AVX1-NEXT: addq %r13, %rcx +; AVX1-NEXT: adcq %rbx, %rdi +; AVX1-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Folded Reload +; AVX1-NEXT: adcq %r12, %rsi +; AVX1-NEXT: addq $1, %r11 +; AVX1-NEXT: adcq $0, %rsi +; AVX1-NEXT: addq $1, %rcx +; AVX1-NEXT: adcq $0, %rdi +; AVX1-NEXT: addq $1, %rdx +; AVX1-NEXT: adcq $0, %r9 +; AVX1-NEXT: addq $1, %r8 +; AVX1-NEXT: adcq $0, %r10 +; AVX1-NEXT: shldq $63, %r8, %r10 +; AVX1-NEXT: shldq $63, %rdx, %r9 +; AVX1-NEXT: shldq $63, %rcx, %rdi +; AVX1-NEXT: shldq $63, %r11, %rsi +; AVX1-NEXT: vmovq %rsi, %xmm0 +; AVX1-NEXT: vmovq %rdi, %xmm1 +; AVX1-NEXT: vmovq %r9, %xmm2 +; AVX1-NEXT: vmovq %r10, %xmm3 +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm3[0],xmm2[0] +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: popq %rbx +; AVX1-NEXT: .cfi_def_cfa_offset 48 +; AVX1-NEXT: popq %r12 +; AVX1-NEXT: .cfi_def_cfa_offset 40 +; AVX1-NEXT: popq %r13 +; AVX1-NEXT: .cfi_def_cfa_offset 32 +; AVX1-NEXT: popq %r14 +; AVX1-NEXT: .cfi_def_cfa_offset 24 +; AVX1-NEXT: popq %r15 +; AVX1-NEXT: .cfi_def_cfa_offset 16 +; AVX1-NEXT: popq %rbp +; AVX1-NEXT: .cfi_def_cfa_offset 8 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v4i64: +; AVX2: # %bb.0: +; AVX2-NEXT: pushq %rbp +; AVX2-NEXT: .cfi_def_cfa_offset 16 +; AVX2-NEXT: pushq %r15 +; AVX2-NEXT: .cfi_def_cfa_offset 24 +; AVX2-NEXT: pushq %r14 +; AVX2-NEXT: .cfi_def_cfa_offset 32 +; AVX2-NEXT: pushq %r13 +; AVX2-NEXT: .cfi_def_cfa_offset 40 +; AVX2-NEXT: pushq %r12 +; AVX2-NEXT: .cfi_def_cfa_offset 48 +; AVX2-NEXT: pushq %rbx +; AVX2-NEXT: .cfi_def_cfa_offset 56 +; AVX2-NEXT: .cfi_offset %rbx, -56 +; AVX2-NEXT: .cfi_offset %r12, -48 +; AVX2-NEXT: .cfi_offset %r13, -40 +; AVX2-NEXT: .cfi_offset %r14, -32 +; AVX2-NEXT: .cfi_offset %r15, -24 +; AVX2-NEXT: .cfi_offset %rbp, -16 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm2 +; AVX2-NEXT: vpextrq $1, %xmm2, %r11 +; AVX2-NEXT: movq %r11, %r12 +; AVX2-NEXT: sarq $63, %r12 +; AVX2-NEXT: vmovq %xmm2, %rcx +; AVX2-NEXT: movq %rcx, %rbx +; AVX2-NEXT: sarq $63, %rbx +; AVX2-NEXT: vpextrq $1, %xmm0, %rdx +; AVX2-NEXT: movq %rdx, %r14 +; AVX2-NEXT: sarq $63, %r14 +; AVX2-NEXT: vmovq %xmm0, %r8 +; AVX2-NEXT: movq %r8, %r15 +; AVX2-NEXT: sarq $63, %r15 +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm0 +; AVX2-NEXT: vpextrq $1, %xmm0, %rsi +; AVX2-NEXT: movq %rsi, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: sarq $63, %rsi +; AVX2-NEXT: vmovq %xmm0, %r13 +; AVX2-NEXT: movq %r13, %rdi +; AVX2-NEXT: sarq $63, %rdi +; AVX2-NEXT: vpextrq $1, %xmm1, %rbp +; AVX2-NEXT: movq %rbp, %r9 +; AVX2-NEXT: sarq $63, %r9 +; AVX2-NEXT: vmovq %xmm1, %rax +; AVX2-NEXT: movq %rax, %r10 +; AVX2-NEXT: sarq $63, %r10 +; AVX2-NEXT: addq %rax, %r8 +; AVX2-NEXT: adcq %r15, %r10 +; AVX2-NEXT: addq %rbp, %rdx +; AVX2-NEXT: adcq %r14, %r9 +; AVX2-NEXT: addq %r13, %rcx +; AVX2-NEXT: adcq %rbx, %rdi +; AVX2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Folded Reload +; AVX2-NEXT: adcq %r12, %rsi +; AVX2-NEXT: addq $1, %r11 +; AVX2-NEXT: adcq $0, %rsi +; AVX2-NEXT: addq $1, %rcx +; AVX2-NEXT: adcq $0, %rdi +; AVX2-NEXT: addq $1, %rdx +; AVX2-NEXT: adcq $0, %r9 +; AVX2-NEXT: addq $1, %r8 +; AVX2-NEXT: adcq $0, %r10 +; AVX2-NEXT: shldq $63, %r8, %r10 +; AVX2-NEXT: shldq $63, %rdx, %r9 +; AVX2-NEXT: shldq $63, %rcx, %rdi +; AVX2-NEXT: shldq $63, %r11, %rsi +; AVX2-NEXT: vmovq %rsi, %xmm0 +; AVX2-NEXT: vmovq %rdi, %xmm1 +; AVX2-NEXT: vmovq %r9, %xmm2 +; AVX2-NEXT: vmovq %r10, %xmm3 +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm3[0],xmm2[0] +; AVX2-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0 +; AVX2-NEXT: popq %rbx +; AVX2-NEXT: .cfi_def_cfa_offset 48 +; AVX2-NEXT: popq %r12 +; AVX2-NEXT: .cfi_def_cfa_offset 40 +; AVX2-NEXT: popq %r13 +; AVX2-NEXT: .cfi_def_cfa_offset 32 +; AVX2-NEXT: popq %r14 +; AVX2-NEXT: .cfi_def_cfa_offset 24 +; AVX2-NEXT: popq %r15 +; AVX2-NEXT: .cfi_def_cfa_offset 16 +; AVX2-NEXT: popq %rbp +; AVX2-NEXT: .cfi_def_cfa_offset 8 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v4i64: +; AVX512: # %bb.0: +; AVX512-NEXT: pushq %rbp +; AVX512-NEXT: .cfi_def_cfa_offset 16 +; AVX512-NEXT: pushq %r15 +; AVX512-NEXT: .cfi_def_cfa_offset 24 +; AVX512-NEXT: pushq %r14 +; AVX512-NEXT: .cfi_def_cfa_offset 32 +; AVX512-NEXT: pushq %r13 +; AVX512-NEXT: .cfi_def_cfa_offset 40 +; AVX512-NEXT: pushq %r12 +; AVX512-NEXT: .cfi_def_cfa_offset 48 +; AVX512-NEXT: pushq %rbx +; AVX512-NEXT: .cfi_def_cfa_offset 56 +; AVX512-NEXT: .cfi_offset %rbx, -56 +; AVX512-NEXT: .cfi_offset %r12, -48 +; AVX512-NEXT: .cfi_offset %r13, -40 +; AVX512-NEXT: .cfi_offset %r14, -32 +; AVX512-NEXT: .cfi_offset %r15, -24 +; AVX512-NEXT: .cfi_offset %rbp, -16 +; AVX512-NEXT: vextracti128 $1, %ymm0, %xmm2 +; AVX512-NEXT: vpextrq $1, %xmm2, %r11 +; AVX512-NEXT: movq %r11, %r12 +; AVX512-NEXT: sarq $63, %r12 +; AVX512-NEXT: vmovq %xmm2, %rcx +; AVX512-NEXT: movq %rcx, %rbx +; AVX512-NEXT: vpextrq $1, %xmm0, %rdx +; AVX512-NEXT: sarq $63, %rbx +; AVX512-NEXT: movq %rdx, %r14 +; AVX512-NEXT: sarq $63, %r14 +; AVX512-NEXT: vmovq %xmm0, %rdi +; AVX512-NEXT: movq %rdi, %r15 +; AVX512-NEXT: vextracti128 $1, %ymm1, %xmm0 +; AVX512-NEXT: vpextrq $1, %xmm0, %rsi +; AVX512-NEXT: movq %rsi, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: sarq $63, %r15 +; AVX512-NEXT: sarq $63, %rsi +; AVX512-NEXT: vmovq %xmm0, %r13 +; AVX512-NEXT: movq %r13, %r8 +; AVX512-NEXT: sarq $63, %r8 +; AVX512-NEXT: vpextrq $1, %xmm1, %rbp +; AVX512-NEXT: movq %rbp, %r9 +; AVX512-NEXT: sarq $63, %r9 +; AVX512-NEXT: vmovq %xmm1, %rax +; AVX512-NEXT: movq %rax, %r10 +; AVX512-NEXT: sarq $63, %r10 +; AVX512-NEXT: addq %rax, %rdi +; AVX512-NEXT: adcq %r15, %r10 +; AVX512-NEXT: addq %rbp, %rdx +; AVX512-NEXT: adcq %r14, %r9 +; AVX512-NEXT: addq %r13, %rcx +; AVX512-NEXT: adcq %rbx, %r8 +; AVX512-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Folded Reload +; AVX512-NEXT: adcq %r12, %rsi +; AVX512-NEXT: addq $1, %r11 +; AVX512-NEXT: adcq $0, %rsi +; AVX512-NEXT: addq $1, %rcx +; AVX512-NEXT: adcq $0, %r8 +; AVX512-NEXT: addq $1, %rdx +; AVX512-NEXT: adcq $0, %r9 +; AVX512-NEXT: addq $1, %rdi +; AVX512-NEXT: adcq $0, %r10 +; AVX512-NEXT: shldq $63, %rdi, %r10 +; AVX512-NEXT: shldq $63, %rdx, %r9 +; AVX512-NEXT: shldq $63, %rcx, %r8 +; AVX512-NEXT: shldq $63, %r11, %rsi +; AVX512-NEXT: vmovq %rsi, %xmm0 +; AVX512-NEXT: vmovq %r8, %xmm1 +; AVX512-NEXT: vmovq %r9, %xmm2 +; AVX512-NEXT: vmovq %r10, %xmm3 +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm3[0],xmm2[0] +; AVX512-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0 +; AVX512-NEXT: popq %rbx +; AVX512-NEXT: .cfi_def_cfa_offset 48 +; AVX512-NEXT: popq %r12 +; AVX512-NEXT: .cfi_def_cfa_offset 40 +; AVX512-NEXT: popq %r13 +; AVX512-NEXT: .cfi_def_cfa_offset 32 +; AVX512-NEXT: popq %r14 +; AVX512-NEXT: .cfi_def_cfa_offset 24 +; AVX512-NEXT: popq %r15 +; AVX512-NEXT: .cfi_def_cfa_offset 16 +; AVX512-NEXT: popq %rbp +; AVX512-NEXT: .cfi_def_cfa_offset 8 +; AVX512-NEXT: retq + %x0 = sext <4 x i64> %a0 to <4 x i128> + %x1 = sext <4 x i64> %a1 to <4 x i128> + %sum = add <4 x i128> %x0, %x1 + %inc = add <4 x i128> %sum, <i128 1, i128 1, i128 1, i128 1> + %shift = ashr <4 x i128> %inc, <i128 1, i128 1, i128 1, i128 1> + %res = trunc <4 x i128> %shift to <4 x i64> + ret <4 x i64> %res +} + +; +; 512-bit vectors +; + +define <64 x i8> @test_fixed_v64i8(<64 x i8> %a0, <64 x i8> %a1) { +; SSE-LABEL: test_fixed_v64i8: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm3, %xmm11 +; SSE-NEXT: movdqa %xmm2, %xmm8 +; SSE-NEXT: movdqa %xmm1, %xmm9 +; SSE-NEXT: movdqa %xmm0, %xmm10 +; SSE-NEXT: por %xmm7, %xmm3 +; SSE-NEXT: por %xmm6, %xmm2 +; SSE-NEXT: por %xmm5, %xmm1 +; SSE-NEXT: por %xmm4, %xmm0 +; SSE-NEXT: pxor %xmm4, %xmm10 +; SSE-NEXT: pxor %xmm5, %xmm9 +; SSE-NEXT: pxor %xmm6, %xmm8 +; SSE-NEXT: pxor %xmm7, %xmm11 +; SSE-NEXT: psrlw $1, %xmm11 +; SSE-NEXT: movdqa {{.*#+}} xmm5 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; SSE-NEXT: pand %xmm5, %xmm11 +; SSE-NEXT: movdqa {{.*#+}} xmm4 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; SSE-NEXT: pxor %xmm4, %xmm11 +; SSE-NEXT: psubb %xmm11, %xmm3 +; SSE-NEXT: psrlw $1, %xmm8 +; SSE-NEXT: pand %xmm5, %xmm8 +; SSE-NEXT: pxor %xmm4, %xmm8 +; SSE-NEXT: psubb %xmm8, %xmm2 +; SSE-NEXT: psrlw $1, %xmm9 +; SSE-NEXT: pand %xmm5, %xmm9 +; SSE-NEXT: pxor %xmm4, %xmm9 +; SSE-NEXT: psubb %xmm9, %xmm1 +; SSE-NEXT: psrlw $1, %xmm10 +; SSE-NEXT: pand %xmm5, %xmm10 +; SSE-NEXT: pxor %xmm4, %xmm10 +; SSE-NEXT: psubb %xmm10, %xmm0 +; SSE-NEXT: paddb %xmm4, %xmm0 +; SSE-NEXT: paddb %xmm4, %xmm1 +; SSE-NEXT: paddb %xmm4, %xmm2 +; SSE-NEXT: paddb %xmm4, %xmm3 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v64i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vorps %ymm3, %ymm1, %ymm4 +; AVX1-NEXT: vorps %ymm2, %ymm0, %ymm5 +; AVX1-NEXT: vxorps %ymm2, %ymm0, %ymm0 +; AVX1-NEXT: vxorps %ymm3, %ymm1, %ymm1 +; AVX1-NEXT: vpsrlw $1, %xmm1, %xmm2 +; AVX1-NEXT: vbroadcastss {{.*#+}} xmm3 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; AVX1-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX1-NEXT: vbroadcastss {{.*#+}} xmm6 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; AVX1-NEXT: vpxor %xmm6, %xmm2, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpsrlw $1, %xmm1, %xmm1 +; AVX1-NEXT: vpand %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vpxor %xmm6, %xmm1, %xmm1 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm7 +; AVX1-NEXT: vpand %xmm3, %xmm7, %xmm7 +; AVX1-NEXT: vpxor %xmm6, %xmm7, %xmm7 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 +; AVX1-NEXT: vpxor %xmm6, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm5, %xmm3 +; AVX1-NEXT: vpsubb %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpaddb %xmm6, %xmm0, %xmm0 +; AVX1-NEXT: vpsubb %xmm7, %xmm5, %xmm3 +; AVX1-NEXT: vpaddb %xmm6, %xmm3, %xmm3 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm3, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm4, %xmm3 +; AVX1-NEXT: vpsubb %xmm1, %xmm3, %xmm1 +; AVX1-NEXT: vpaddb %xmm6, %xmm1, %xmm1 +; AVX1-NEXT: vpsubb %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vpaddb %xmm6, %xmm2, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v64i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vpor %ymm3, %ymm1, %ymm4 +; AVX2-NEXT: vpor %ymm2, %ymm0, %ymm5 +; AVX2-NEXT: vpxor %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpxor %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: vpsrlw $1, %ymm1, %ymm1 +; AVX2-NEXT: vpbroadcastb {{.*#+}} ymm2 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; AVX2-NEXT: vpand %ymm2, %ymm1, %ymm1 +; AVX2-NEXT: vpbroadcastb {{.*#+}} ymm3 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; AVX2-NEXT: vpxor %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: vpsubb %ymm1, %ymm4, %ymm1 +; AVX2-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpand %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpxor %ymm3, %ymm0, %ymm0 +; AVX2-NEXT: vpsubb %ymm0, %ymm5, %ymm0 +; AVX2-NEXT: vpaddb %ymm3, %ymm0, %ymm0 +; AVX2-NEXT: vpaddb %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v64i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vporq %zmm1, %zmm0, %zmm2 +; AVX512-NEXT: vpxorq %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlw $1, %zmm0, %zmm0 +; AVX512-NEXT: vpbroadcastb {{.*#+}} zmm1 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; AVX512-NEXT: vpternlogd $108, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm1, %zmm0 +; AVX512-NEXT: vpsubb %zmm0, %zmm2, %zmm0 +; AVX512-NEXT: vpaddb %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: retq + %or = or <64 x i8> %a0, %a1 + %xor = xor <64 x i8> %a0, %a1 + %shift = ashr <64 x i8> %xor, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> + %res = sub <64 x i8> %or, %shift + ret <64 x i8> %res +} + +define <64 x i8> @test_ext_v64i8(<64 x i8> %a0, <64 x i8> %a1) { +; SSE2-LABEL: test_ext_v64i8: +; SSE2: # %bb.0: +; SSE2-NEXT: movdqa %xmm3, %xmm8 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm14 = xmm14[8],xmm0[8],xmm14[9],xmm0[9],xmm14[10],xmm0[10],xmm14[11],xmm0[11],xmm14[12],xmm0[12],xmm14[13],xmm0[13],xmm14[14],xmm0[14],xmm14[15],xmm0[15] +; SSE2-NEXT: psraw $8, %xmm14 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm15 = xmm15[0],xmm0[0],xmm15[1],xmm0[1],xmm15[2],xmm0[2],xmm15[3],xmm0[3],xmm15[4],xmm0[4],xmm15[5],xmm0[5],xmm15[6],xmm0[6],xmm15[7],xmm0[7] +; SSE2-NEXT: psraw $8, %xmm15 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm1[8],xmm3[9],xmm1[9],xmm3[10],xmm1[10],xmm3[11],xmm1[11],xmm3[12],xmm1[12],xmm3[13],xmm1[13],xmm3[14],xmm1[14],xmm3[15],xmm1[15] +; SSE2-NEXT: psraw $8, %xmm3 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm13 = xmm13[0],xmm1[0],xmm13[1],xmm1[1],xmm13[2],xmm1[2],xmm13[3],xmm1[3],xmm13[4],xmm1[4],xmm13[5],xmm1[5],xmm13[6],xmm1[6],xmm13[7],xmm1[7] +; SSE2-NEXT: psraw $8, %xmm13 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm12 = xmm12[8],xmm2[8],xmm12[9],xmm2[9],xmm12[10],xmm2[10],xmm12[11],xmm2[11],xmm12[12],xmm2[12],xmm12[13],xmm2[13],xmm12[14],xmm2[14],xmm12[15],xmm2[15] +; SSE2-NEXT: psraw $8, %xmm12 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm11 = xmm11[0],xmm2[0],xmm11[1],xmm2[1],xmm11[2],xmm2[2],xmm11[3],xmm2[3],xmm11[4],xmm2[4],xmm11[5],xmm2[5],xmm11[6],xmm2[6],xmm11[7],xmm2[7] +; SSE2-NEXT: psraw $8, %xmm11 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm10 = xmm10[8],xmm8[8],xmm10[9],xmm8[9],xmm10[10],xmm8[10],xmm10[11],xmm8[11],xmm10[12],xmm8[12],xmm10[13],xmm8[13],xmm10[14],xmm8[14],xmm10[15],xmm8[15] +; SSE2-NEXT: psraw $8, %xmm10 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm9 = xmm9[0],xmm8[0],xmm9[1],xmm8[1],xmm9[2],xmm8[2],xmm9[3],xmm8[3],xmm9[4],xmm8[4],xmm9[5],xmm8[5],xmm9[6],xmm8[6],xmm9[7],xmm8[7] +; SSE2-NEXT: psraw $8, %xmm9 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm8 = xmm8[8],xmm4[8],xmm8[9],xmm4[9],xmm8[10],xmm4[10],xmm8[11],xmm4[11],xmm8[12],xmm4[12],xmm8[13],xmm4[13],xmm8[14],xmm4[14],xmm8[15],xmm4[15] +; SSE2-NEXT: psraw $8, %xmm8 +; SSE2-NEXT: paddw %xmm14, %xmm8 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm4[0],xmm0[1],xmm4[1],xmm0[2],xmm4[2],xmm0[3],xmm4[3],xmm0[4],xmm4[4],xmm0[5],xmm4[5],xmm0[6],xmm4[6],xmm0[7],xmm4[7] +; SSE2-NEXT: psraw $8, %xmm0 +; SSE2-NEXT: paddw %xmm15, %xmm0 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm5[8],xmm4[9],xmm5[9],xmm4[10],xmm5[10],xmm4[11],xmm5[11],xmm4[12],xmm5[12],xmm4[13],xmm5[13],xmm4[14],xmm5[14],xmm4[15],xmm5[15] +; SSE2-NEXT: psraw $8, %xmm4 +; SSE2-NEXT: paddw %xmm3, %xmm4 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm5[0],xmm1[1],xmm5[1],xmm1[2],xmm5[2],xmm1[3],xmm5[3],xmm1[4],xmm5[4],xmm1[5],xmm5[5],xmm1[6],xmm5[6],xmm1[7],xmm5[7] +; SSE2-NEXT: psraw $8, %xmm1 +; SSE2-NEXT: paddw %xmm13, %xmm1 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm6[8],xmm5[9],xmm6[9],xmm5[10],xmm6[10],xmm5[11],xmm6[11],xmm5[12],xmm6[12],xmm5[13],xmm6[13],xmm5[14],xmm6[14],xmm5[15],xmm6[15] +; SSE2-NEXT: psraw $8, %xmm5 +; SSE2-NEXT: paddw %xmm12, %xmm5 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm6[0],xmm2[1],xmm6[1],xmm2[2],xmm6[2],xmm2[3],xmm6[3],xmm2[4],xmm6[4],xmm2[5],xmm6[5],xmm2[6],xmm6[6],xmm2[7],xmm6[7] +; SSE2-NEXT: psraw $8, %xmm2 +; SSE2-NEXT: paddw %xmm11, %xmm2 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm6 = xmm6[8],xmm7[8],xmm6[9],xmm7[9],xmm6[10],xmm7[10],xmm6[11],xmm7[11],xmm6[12],xmm7[12],xmm6[13],xmm7[13],xmm6[14],xmm7[14],xmm6[15],xmm7[15] +; SSE2-NEXT: psraw $8, %xmm6 +; SSE2-NEXT: paddw %xmm10, %xmm6 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm7[0],xmm3[1],xmm7[1],xmm3[2],xmm7[2],xmm3[3],xmm7[3],xmm3[4],xmm7[4],xmm3[5],xmm7[5],xmm3[6],xmm7[6],xmm3[7],xmm7[7] +; SSE2-NEXT: psraw $8, %xmm3 +; SSE2-NEXT: paddw %xmm9, %xmm3 +; SSE2-NEXT: pcmpeqd %xmm7, %xmm7 +; SSE2-NEXT: psubw %xmm7, %xmm8 +; SSE2-NEXT: psubw %xmm7, %xmm0 +; SSE2-NEXT: psubw %xmm7, %xmm4 +; SSE2-NEXT: psubw %xmm7, %xmm1 +; SSE2-NEXT: psubw %xmm7, %xmm5 +; SSE2-NEXT: psubw %xmm7, %xmm2 +; SSE2-NEXT: psubw %xmm7, %xmm6 +; SSE2-NEXT: psubw %xmm7, %xmm3 +; SSE2-NEXT: psrlw $1, %xmm3 +; SSE2-NEXT: psrlw $1, %xmm6 +; SSE2-NEXT: psrlw $1, %xmm2 +; SSE2-NEXT: psrlw $1, %xmm5 +; SSE2-NEXT: psrlw $1, %xmm1 +; SSE2-NEXT: psrlw $1, %xmm4 +; SSE2-NEXT: psrlw $1, %xmm0 +; SSE2-NEXT: psrlw $1, %xmm8 +; SSE2-NEXT: movdqa {{.*#+}} xmm7 = [255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0] +; SSE2-NEXT: pand %xmm7, %xmm8 +; SSE2-NEXT: pand %xmm7, %xmm0 +; SSE2-NEXT: packuswb %xmm8, %xmm0 +; SSE2-NEXT: pand %xmm7, %xmm4 +; SSE2-NEXT: pand %xmm7, %xmm1 +; SSE2-NEXT: packuswb %xmm4, %xmm1 +; SSE2-NEXT: pand %xmm7, %xmm5 +; SSE2-NEXT: pand %xmm7, %xmm2 +; SSE2-NEXT: packuswb %xmm5, %xmm2 +; SSE2-NEXT: pand %xmm7, %xmm6 +; SSE2-NEXT: pand %xmm7, %xmm3 +; SSE2-NEXT: packuswb %xmm6, %xmm3 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v64i8: +; SSE4: # %bb.0: +; SSE4-NEXT: pmovsxbw %xmm0, %xmm8 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm0, %xmm9 +; SSE4-NEXT: pmovsxbw %xmm1, %xmm10 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm0, %xmm11 +; SSE4-NEXT: pmovsxbw %xmm2, %xmm12 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm2[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm0, %xmm13 +; SSE4-NEXT: pmovsxbw %xmm3, %xmm14 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm3[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm0, %xmm15 +; SSE4-NEXT: pmovsxbw %xmm4, %xmm0 +; SSE4-NEXT: paddw %xmm8, %xmm0 +; SSE4-NEXT: pshufd {{.*#+}} xmm1 = xmm4[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm1, %xmm4 +; SSE4-NEXT: paddw %xmm9, %xmm4 +; SSE4-NEXT: pmovsxbw %xmm5, %xmm1 +; SSE4-NEXT: paddw %xmm10, %xmm1 +; SSE4-NEXT: pshufd {{.*#+}} xmm2 = xmm5[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm2, %xmm5 +; SSE4-NEXT: paddw %xmm11, %xmm5 +; SSE4-NEXT: pmovsxbw %xmm6, %xmm2 +; SSE4-NEXT: paddw %xmm12, %xmm2 +; SSE4-NEXT: pshufd {{.*#+}} xmm3 = xmm6[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm3, %xmm6 +; SSE4-NEXT: paddw %xmm13, %xmm6 +; SSE4-NEXT: pmovsxbw %xmm7, %xmm3 +; SSE4-NEXT: paddw %xmm14, %xmm3 +; SSE4-NEXT: pshufd {{.*#+}} xmm7 = xmm7[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm7, %xmm7 +; SSE4-NEXT: paddw %xmm15, %xmm7 +; SSE4-NEXT: pcmpeqd %xmm8, %xmm8 +; SSE4-NEXT: psubw %xmm8, %xmm0 +; SSE4-NEXT: psubw %xmm8, %xmm4 +; SSE4-NEXT: psubw %xmm8, %xmm1 +; SSE4-NEXT: psubw %xmm8, %xmm5 +; SSE4-NEXT: psubw %xmm8, %xmm2 +; SSE4-NEXT: psubw %xmm8, %xmm6 +; SSE4-NEXT: psubw %xmm8, %xmm3 +; SSE4-NEXT: psubw %xmm8, %xmm7 +; SSE4-NEXT: psrlw $1, %xmm7 +; SSE4-NEXT: psrlw $1, %xmm3 +; SSE4-NEXT: psrlw $1, %xmm6 +; SSE4-NEXT: psrlw $1, %xmm2 +; SSE4-NEXT: psrlw $1, %xmm5 +; SSE4-NEXT: psrlw $1, %xmm1 +; SSE4-NEXT: psrlw $1, %xmm4 +; SSE4-NEXT: psrlw $1, %xmm0 +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm8 = [255,255,255,255,255,255,255,255] +; SSE4-NEXT: pand %xmm8, %xmm0 +; SSE4-NEXT: pand %xmm8, %xmm4 +; SSE4-NEXT: packuswb %xmm4, %xmm0 +; SSE4-NEXT: pand %xmm8, %xmm1 +; SSE4-NEXT: pand %xmm8, %xmm5 +; SSE4-NEXT: packuswb %xmm5, %xmm1 +; SSE4-NEXT: pand %xmm8, %xmm2 +; SSE4-NEXT: pand %xmm8, %xmm6 +; SSE4-NEXT: packuswb %xmm6, %xmm2 +; SSE4-NEXT: pand %xmm8, %xmm3 +; SSE4-NEXT: pand %xmm8, %xmm7 +; SSE4-NEXT: packuswb %xmm7, %xmm3 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v64i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm4 +; AVX1-NEXT: vpmovsxbw %xmm4, %xmm5 +; AVX1-NEXT: vpshufd {{.*#+}} xmm4 = xmm4[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm4, %xmm4 +; AVX1-NEXT: vpmovsxbw %xmm0, %xmm6 +; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm7 +; AVX1-NEXT: vpmovsxbw %xmm7, %xmm8 +; AVX1-NEXT: vpshufd {{.*#+}} xmm7 = xmm7[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm7, %xmm7 +; AVX1-NEXT: vpmovsxbw %xmm1, %xmm9 +; AVX1-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm1, %xmm1 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm10 +; AVX1-NEXT: vpmovsxbw %xmm10, %xmm11 +; AVX1-NEXT: vpaddw %xmm5, %xmm11, %xmm5 +; AVX1-NEXT: vpshufd {{.*#+}} xmm10 = xmm10[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm10, %xmm10 +; AVX1-NEXT: vpaddw %xmm4, %xmm10, %xmm4 +; AVX1-NEXT: vpmovsxbw %xmm2, %xmm10 +; AVX1-NEXT: vpaddw %xmm6, %xmm10, %xmm6 +; AVX1-NEXT: vpshufd {{.*#+}} xmm2 = xmm2[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm2, %xmm2 +; AVX1-NEXT: vpaddw %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm2 +; AVX1-NEXT: vpmovsxbw %xmm2, %xmm10 +; AVX1-NEXT: vpaddw %xmm10, %xmm8, %xmm8 +; AVX1-NEXT: vpshufd {{.*#+}} xmm2 = xmm2[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm2, %xmm2 +; AVX1-NEXT: vpaddw %xmm2, %xmm7, %xmm2 +; AVX1-NEXT: vpmovsxbw %xmm3, %xmm7 +; AVX1-NEXT: vpaddw %xmm7, %xmm9, %xmm7 +; AVX1-NEXT: vpshufd {{.*#+}} xmm3 = xmm3[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm3, %xmm3 +; AVX1-NEXT: vpaddw %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vpcmpeqd %xmm3, %xmm3, %xmm3 +; AVX1-NEXT: vpsubw %xmm3, %xmm5, %xmm5 +; AVX1-NEXT: vpsubw %xmm3, %xmm4, %xmm4 +; AVX1-NEXT: vpsubw %xmm3, %xmm6, %xmm6 +; AVX1-NEXT: vpsubw %xmm3, %xmm0, %xmm0 +; AVX1-NEXT: vpsubw %xmm3, %xmm8, %xmm8 +; AVX1-NEXT: vpsubw %xmm3, %xmm2, %xmm2 +; AVX1-NEXT: vpsubw %xmm3, %xmm7, %xmm7 +; AVX1-NEXT: vpsubw %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vpsrlw $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsrlw $1, %xmm7, %xmm3 +; AVX1-NEXT: vpsrlw $1, %xmm2, %xmm2 +; AVX1-NEXT: vpsrlw $1, %xmm8, %xmm7 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm6, %xmm6 +; AVX1-NEXT: vpsrlw $1, %xmm4, %xmm4 +; AVX1-NEXT: vpsrlw $1, %xmm5, %xmm5 +; AVX1-NEXT: vbroadcastss {{.*#+}} xmm8 = [255,255,255,255,255,255,255,255] +; AVX1-NEXT: vpand %xmm5, %xmm8, %xmm5 +; AVX1-NEXT: vpand %xmm4, %xmm8, %xmm4 +; AVX1-NEXT: vpackuswb %xmm4, %xmm5, %xmm4 +; AVX1-NEXT: vpand %xmm6, %xmm8, %xmm5 +; AVX1-NEXT: vpand %xmm0, %xmm8, %xmm0 +; AVX1-NEXT: vpackuswb %xmm0, %xmm5, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm4, %ymm0, %ymm0 +; AVX1-NEXT: vpand %xmm7, %xmm8, %xmm4 +; AVX1-NEXT: vpand %xmm2, %xmm8, %xmm2 +; AVX1-NEXT: vpackuswb %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vpand %xmm3, %xmm8, %xmm3 +; AVX1-NEXT: vpand %xmm1, %xmm8, %xmm1 +; AVX1-NEXT: vpackuswb %xmm1, %xmm3, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm1, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v64i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm4 +; AVX2-NEXT: vpmovsxbw %xmm4, %ymm4 +; AVX2-NEXT: vpmovsxbw %xmm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm5 +; AVX2-NEXT: vpmovsxbw %xmm5, %ymm5 +; AVX2-NEXT: vpmovsxbw %xmm1, %ymm1 +; AVX2-NEXT: vextracti128 $1, %ymm2, %xmm6 +; AVX2-NEXT: vpmovsxbw %xmm6, %ymm6 +; AVX2-NEXT: vpaddw %ymm6, %ymm4, %ymm4 +; AVX2-NEXT: vpmovsxbw %xmm2, %ymm2 +; AVX2-NEXT: vpaddw %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm3, %xmm2 +; AVX2-NEXT: vpmovsxbw %xmm2, %ymm2 +; AVX2-NEXT: vpaddw %ymm2, %ymm5, %ymm2 +; AVX2-NEXT: vpmovsxbw %xmm3, %ymm3 +; AVX2-NEXT: vpaddw %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: vpcmpeqd %ymm3, %ymm3, %ymm3 +; AVX2-NEXT: vpsubw %ymm3, %ymm4, %ymm4 +; AVX2-NEXT: vpsubw %ymm3, %ymm0, %ymm0 +; AVX2-NEXT: vpsubw %ymm3, %ymm2, %ymm2 +; AVX2-NEXT: vpsubw %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: vpsrlw $1, %ymm1, %ymm1 +; AVX2-NEXT: vpsrlw $1, %ymm2, %ymm2 +; AVX2-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlw $1, %ymm4, %ymm3 +; AVX2-NEXT: vpbroadcastw {{.*#+}} ymm4 = [255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0] +; AVX2-NEXT: vpand %ymm4, %ymm3, %ymm3 +; AVX2-NEXT: vpand %ymm4, %ymm0, %ymm0 +; AVX2-NEXT: vpackuswb %ymm3, %ymm0, %ymm0 +; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,2,1,3] +; AVX2-NEXT: vpand %ymm4, %ymm2, %ymm2 +; AVX2-NEXT: vpand %ymm4, %ymm1, %ymm1 +; AVX2-NEXT: vpackuswb %ymm2, %ymm1, %ymm1 +; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,2,1,3] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v64i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovsxbw %ymm0, %zmm2 +; AVX512-NEXT: vextracti64x4 $1, %zmm0, %ymm0 +; AVX512-NEXT: vpmovsxbw %ymm0, %zmm0 +; AVX512-NEXT: vpmovsxbw %ymm1, %zmm3 +; AVX512-NEXT: vpaddw %zmm3, %zmm2, %zmm2 +; AVX512-NEXT: vextracti64x4 $1, %zmm1, %ymm1 +; AVX512-NEXT: vpmovsxbw %ymm1, %zmm1 +; AVX512-NEXT: vpaddw %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpternlogd $255, %zmm1, %zmm1, %zmm1 +; AVX512-NEXT: vpsubw %zmm1, %zmm2, %zmm2 +; AVX512-NEXT: vpsubw %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlw $1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlw $1, %zmm2, %zmm1 +; AVX512-NEXT: vpmovwb %zmm1, %ymm1 +; AVX512-NEXT: vpmovwb %zmm0, %ymm0 +; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-NEXT: retq + %x0 = sext <64 x i8> %a0 to <64 x i16> + %x1 = sext <64 x i8> %a1 to <64 x i16> + %sum = add <64 x i16> %x0, %x1 + %inc = add <64 x i16> %sum, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %shift = ashr <64 x i16> %inc, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = trunc <64 x i16> %shift to <64 x i8> + ret <64 x i8> %res +} + +define <32 x i16> @test_fixed_v32i16(<32 x i16> %a0, <32 x i16> %a1) { +; SSE-LABEL: test_fixed_v32i16: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm3, %xmm8 +; SSE-NEXT: por %xmm7, %xmm3 +; SSE-NEXT: movdqa %xmm2, %xmm9 +; SSE-NEXT: por %xmm6, %xmm9 +; SSE-NEXT: movdqa %xmm1, %xmm10 +; SSE-NEXT: por %xmm5, %xmm10 +; SSE-NEXT: movdqa %xmm0, %xmm11 +; SSE-NEXT: por %xmm4, %xmm11 +; SSE-NEXT: pxor %xmm0, %xmm4 +; SSE-NEXT: pxor %xmm1, %xmm5 +; SSE-NEXT: pxor %xmm2, %xmm6 +; SSE-NEXT: pxor %xmm8, %xmm7 +; SSE-NEXT: psraw $1, %xmm7 +; SSE-NEXT: psubw %xmm7, %xmm3 +; SSE-NEXT: psraw $1, %xmm6 +; SSE-NEXT: psubw %xmm6, %xmm9 +; SSE-NEXT: psraw $1, %xmm5 +; SSE-NEXT: psubw %xmm5, %xmm10 +; SSE-NEXT: psraw $1, %xmm4 +; SSE-NEXT: psubw %xmm4, %xmm11 +; SSE-NEXT: movdqa %xmm11, %xmm0 +; SSE-NEXT: movdqa %xmm10, %xmm1 +; SSE-NEXT: movdqa %xmm9, %xmm2 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v32i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vorps %ymm3, %ymm1, %ymm4 +; AVX1-NEXT: vorps %ymm2, %ymm0, %ymm5 +; AVX1-NEXT: vxorps %ymm0, %ymm2, %ymm0 +; AVX1-NEXT: vxorps %ymm1, %ymm3, %ymm1 +; AVX1-NEXT: vpsraw $1, %xmm1, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpsraw $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsraw $1, %xmm0, %xmm3 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsraw $1, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm5, %xmm6 +; AVX1-NEXT: vpsubw %xmm0, %xmm6, %xmm0 +; AVX1-NEXT: vpsubw %xmm3, %xmm5, %xmm3 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm3, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm4, %xmm3 +; AVX1-NEXT: vpsubw %xmm1, %xmm3, %xmm1 +; AVX1-NEXT: vpsubw %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v32i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vpor %ymm3, %ymm1, %ymm4 +; AVX2-NEXT: vpor %ymm2, %ymm0, %ymm5 +; AVX2-NEXT: vpxor %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: vpxor %ymm1, %ymm3, %ymm1 +; AVX2-NEXT: vpsraw $1, %ymm1, %ymm1 +; AVX2-NEXT: vpsubw %ymm1, %ymm4, %ymm1 +; AVX2-NEXT: vpsraw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpsubw %ymm0, %ymm5, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v32i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vporq %zmm1, %zmm0, %zmm2 +; AVX512-NEXT: vpxorq %zmm0, %zmm1, %zmm0 +; AVX512-NEXT: vpsraw $1, %zmm0, %zmm0 +; AVX512-NEXT: vpsubw %zmm0, %zmm2, %zmm0 +; AVX512-NEXT: retq + %or = or <32 x i16> %a0, %a1 + %xor = xor <32 x i16> %a1, %a0 + %shift = ashr <32 x i16> %xor, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = sub <32 x i16> %or, %shift + ret <32 x i16> %res +} + +define <32 x i16> @test_ext_v32i16(<32 x i16> %a0, <32 x i16> %a1) { +; SSE2-LABEL: test_ext_v32i16: +; SSE2: # %bb.0: +; SSE2-NEXT: punpcklwd {{.*#+}} xmm13 = xmm13[0],xmm3[0],xmm13[1],xmm3[1],xmm13[2],xmm3[2],xmm13[3],xmm3[3] +; SSE2-NEXT: psrad $16, %xmm13 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm14 = xmm14[4],xmm3[4],xmm14[5],xmm3[5],xmm14[6],xmm3[6],xmm14[7],xmm3[7] +; SSE2-NEXT: psrad $16, %xmm14 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm15 = xmm15[0],xmm2[0],xmm15[1],xmm2[1],xmm15[2],xmm2[2],xmm15[3],xmm2[3] +; SSE2-NEXT: psrad $16, %xmm15 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm12 = xmm12[4],xmm2[4],xmm12[5],xmm2[5],xmm12[6],xmm2[6],xmm12[7],xmm2[7] +; SSE2-NEXT: psrad $16, %xmm12 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm11 = xmm11[0],xmm1[0],xmm11[1],xmm1[1],xmm11[2],xmm1[2],xmm11[3],xmm1[3] +; SSE2-NEXT: psrad $16, %xmm11 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm10 = xmm10[4],xmm1[4],xmm10[5],xmm1[5],xmm10[6],xmm1[6],xmm10[7],xmm1[7] +; SSE2-NEXT: psrad $16, %xmm10 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm9 = xmm9[0],xmm0[0],xmm9[1],xmm0[1],xmm9[2],xmm0[2],xmm9[3],xmm0[3] +; SSE2-NEXT: psrad $16, %xmm9 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm8 = xmm8[4],xmm0[4],xmm8[5],xmm0[5],xmm8[6],xmm0[6],xmm8[7],xmm0[7] +; SSE2-NEXT: psrad $16, %xmm8 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm3 = xmm3[0],xmm7[0],xmm3[1],xmm7[1],xmm3[2],xmm7[2],xmm3[3],xmm7[3] +; SSE2-NEXT: psrad $16, %xmm3 +; SSE2-NEXT: paddd %xmm13, %xmm3 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm7 = xmm7[4,4,5,5,6,6,7,7] +; SSE2-NEXT: psrad $16, %xmm7 +; SSE2-NEXT: paddd %xmm14, %xmm7 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm2 = xmm2[0],xmm6[0],xmm2[1],xmm6[1],xmm2[2],xmm6[2],xmm2[3],xmm6[3] +; SSE2-NEXT: psrad $16, %xmm2 +; SSE2-NEXT: paddd %xmm15, %xmm2 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm6 = xmm6[4,4,5,5,6,6,7,7] +; SSE2-NEXT: psrad $16, %xmm6 +; SSE2-NEXT: paddd %xmm12, %xmm6 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm1 = xmm1[0],xmm5[0],xmm1[1],xmm5[1],xmm1[2],xmm5[2],xmm1[3],xmm5[3] +; SSE2-NEXT: psrad $16, %xmm1 +; SSE2-NEXT: paddd %xmm11, %xmm1 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm5 = xmm5[4,4,5,5,6,6,7,7] +; SSE2-NEXT: psrad $16, %xmm5 +; SSE2-NEXT: paddd %xmm10, %xmm5 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm4[0],xmm0[1],xmm4[1],xmm0[2],xmm4[2],xmm0[3],xmm4[3] +; SSE2-NEXT: psrad $16, %xmm0 +; SSE2-NEXT: paddd %xmm9, %xmm0 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm4 = xmm4[4,4,5,5,6,6,7,7] +; SSE2-NEXT: psrad $16, %xmm4 +; SSE2-NEXT: paddd %xmm8, %xmm4 +; SSE2-NEXT: pcmpeqd %xmm8, %xmm8 +; SSE2-NEXT: psubd %xmm8, %xmm3 +; SSE2-NEXT: psubd %xmm8, %xmm7 +; SSE2-NEXT: psubd %xmm8, %xmm2 +; SSE2-NEXT: psubd %xmm8, %xmm6 +; SSE2-NEXT: psubd %xmm8, %xmm1 +; SSE2-NEXT: psubd %xmm8, %xmm5 +; SSE2-NEXT: psubd %xmm8, %xmm0 +; SSE2-NEXT: psubd %xmm8, %xmm4 +; SSE2-NEXT: pslld $15, %xmm4 +; SSE2-NEXT: psrad $16, %xmm4 +; SSE2-NEXT: pslld $15, %xmm0 +; SSE2-NEXT: psrad $16, %xmm0 +; SSE2-NEXT: packssdw %xmm4, %xmm0 +; SSE2-NEXT: pslld $15, %xmm5 +; SSE2-NEXT: psrad $16, %xmm5 +; SSE2-NEXT: pslld $15, %xmm1 +; SSE2-NEXT: psrad $16, %xmm1 +; SSE2-NEXT: packssdw %xmm5, %xmm1 +; SSE2-NEXT: pslld $15, %xmm6 +; SSE2-NEXT: psrad $16, %xmm6 +; SSE2-NEXT: pslld $15, %xmm2 +; SSE2-NEXT: psrad $16, %xmm2 +; SSE2-NEXT: packssdw %xmm6, %xmm2 +; SSE2-NEXT: pslld $15, %xmm7 +; SSE2-NEXT: psrad $16, %xmm7 +; SSE2-NEXT: pslld $15, %xmm3 +; SSE2-NEXT: psrad $16, %xmm3 +; SSE2-NEXT: packssdw %xmm7, %xmm3 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v32i16: +; SSE4: # %bb.0: +; SSE4-NEXT: pmovsxwd %xmm0, %xmm8 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm0, %xmm9 +; SSE4-NEXT: pmovsxwd %xmm1, %xmm10 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm0, %xmm11 +; SSE4-NEXT: pmovsxwd %xmm2, %xmm12 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm2[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm0, %xmm13 +; SSE4-NEXT: pmovsxwd %xmm3, %xmm14 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm3[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm0, %xmm15 +; SSE4-NEXT: pmovsxwd %xmm4, %xmm0 +; SSE4-NEXT: paddd %xmm8, %xmm0 +; SSE4-NEXT: pshufd {{.*#+}} xmm1 = xmm4[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm1, %xmm4 +; SSE4-NEXT: paddd %xmm9, %xmm4 +; SSE4-NEXT: pmovsxwd %xmm5, %xmm1 +; SSE4-NEXT: paddd %xmm10, %xmm1 +; SSE4-NEXT: pshufd {{.*#+}} xmm2 = xmm5[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm2, %xmm5 +; SSE4-NEXT: paddd %xmm11, %xmm5 +; SSE4-NEXT: pmovsxwd %xmm6, %xmm2 +; SSE4-NEXT: paddd %xmm12, %xmm2 +; SSE4-NEXT: pshufd {{.*#+}} xmm3 = xmm6[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm3, %xmm6 +; SSE4-NEXT: paddd %xmm13, %xmm6 +; SSE4-NEXT: pmovsxwd %xmm7, %xmm3 +; SSE4-NEXT: paddd %xmm14, %xmm3 +; SSE4-NEXT: pshufd {{.*#+}} xmm7 = xmm7[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm7, %xmm7 +; SSE4-NEXT: paddd %xmm15, %xmm7 +; SSE4-NEXT: pcmpeqd %xmm8, %xmm8 +; SSE4-NEXT: psubd %xmm8, %xmm0 +; SSE4-NEXT: psubd %xmm8, %xmm4 +; SSE4-NEXT: psubd %xmm8, %xmm1 +; SSE4-NEXT: psubd %xmm8, %xmm5 +; SSE4-NEXT: psubd %xmm8, %xmm2 +; SSE4-NEXT: psubd %xmm8, %xmm6 +; SSE4-NEXT: psubd %xmm8, %xmm3 +; SSE4-NEXT: psubd %xmm8, %xmm7 +; SSE4-NEXT: psrld $1, %xmm7 +; SSE4-NEXT: psrld $1, %xmm3 +; SSE4-NEXT: psrld $1, %xmm6 +; SSE4-NEXT: psrld $1, %xmm2 +; SSE4-NEXT: psrld $1, %xmm5 +; SSE4-NEXT: psrld $1, %xmm1 +; SSE4-NEXT: psrld $1, %xmm4 +; SSE4-NEXT: psrld $1, %xmm0 +; SSE4-NEXT: pxor %xmm8, %xmm8 +; SSE4-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0],xmm8[1],xmm0[2],xmm8[3],xmm0[4],xmm8[5],xmm0[6],xmm8[7] +; SSE4-NEXT: pblendw {{.*#+}} xmm4 = xmm4[0],xmm8[1],xmm4[2],xmm8[3],xmm4[4],xmm8[5],xmm4[6],xmm8[7] +; SSE4-NEXT: packusdw %xmm4, %xmm0 +; SSE4-NEXT: pblendw {{.*#+}} xmm1 = xmm1[0],xmm8[1],xmm1[2],xmm8[3],xmm1[4],xmm8[5],xmm1[6],xmm8[7] +; SSE4-NEXT: pblendw {{.*#+}} xmm5 = xmm5[0],xmm8[1],xmm5[2],xmm8[3],xmm5[4],xmm8[5],xmm5[6],xmm8[7] +; SSE4-NEXT: packusdw %xmm5, %xmm1 +; SSE4-NEXT: pblendw {{.*#+}} xmm2 = xmm2[0],xmm8[1],xmm2[2],xmm8[3],xmm2[4],xmm8[5],xmm2[6],xmm8[7] +; SSE4-NEXT: pblendw {{.*#+}} xmm6 = xmm6[0],xmm8[1],xmm6[2],xmm8[3],xmm6[4],xmm8[5],xmm6[6],xmm8[7] +; SSE4-NEXT: packusdw %xmm6, %xmm2 +; SSE4-NEXT: pblendw {{.*#+}} xmm3 = xmm3[0],xmm8[1],xmm3[2],xmm8[3],xmm3[4],xmm8[5],xmm3[6],xmm8[7] +; SSE4-NEXT: pblendw {{.*#+}} xmm7 = xmm7[0],xmm8[1],xmm7[2],xmm8[3],xmm7[4],xmm8[5],xmm7[6],xmm8[7] +; SSE4-NEXT: packusdw %xmm7, %xmm3 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v32i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm4 +; AVX1-NEXT: vpmovsxwd %xmm4, %xmm5 +; AVX1-NEXT: vpshufd {{.*#+}} xmm4 = xmm4[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm4, %xmm4 +; AVX1-NEXT: vpmovsxwd %xmm0, %xmm6 +; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm7 +; AVX1-NEXT: vpmovsxwd %xmm7, %xmm8 +; AVX1-NEXT: vpshufd {{.*#+}} xmm7 = xmm7[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm7, %xmm7 +; AVX1-NEXT: vpmovsxwd %xmm1, %xmm9 +; AVX1-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm1, %xmm1 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm10 +; AVX1-NEXT: vpmovsxwd %xmm10, %xmm11 +; AVX1-NEXT: vpaddd %xmm5, %xmm11, %xmm5 +; AVX1-NEXT: vpshufd {{.*#+}} xmm10 = xmm10[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm10, %xmm10 +; AVX1-NEXT: vpaddd %xmm4, %xmm10, %xmm4 +; AVX1-NEXT: vpmovsxwd %xmm2, %xmm10 +; AVX1-NEXT: vpaddd %xmm6, %xmm10, %xmm6 +; AVX1-NEXT: vpshufd {{.*#+}} xmm2 = xmm2[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm2, %xmm2 +; AVX1-NEXT: vpaddd %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm2 +; AVX1-NEXT: vpmovsxwd %xmm2, %xmm10 +; AVX1-NEXT: vpaddd %xmm10, %xmm8, %xmm8 +; AVX1-NEXT: vpshufd {{.*#+}} xmm2 = xmm2[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm2, %xmm2 +; AVX1-NEXT: vpaddd %xmm2, %xmm7, %xmm2 +; AVX1-NEXT: vpmovsxwd %xmm3, %xmm7 +; AVX1-NEXT: vpaddd %xmm7, %xmm9, %xmm7 +; AVX1-NEXT: vpshufd {{.*#+}} xmm3 = xmm3[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm3, %xmm3 +; AVX1-NEXT: vpaddd %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vpcmpeqd %xmm3, %xmm3, %xmm3 +; AVX1-NEXT: vpsubd %xmm3, %xmm5, %xmm5 +; AVX1-NEXT: vpsubd %xmm3, %xmm4, %xmm4 +; AVX1-NEXT: vpsubd %xmm3, %xmm6, %xmm6 +; AVX1-NEXT: vpsubd %xmm3, %xmm0, %xmm0 +; AVX1-NEXT: vpsubd %xmm3, %xmm8, %xmm8 +; AVX1-NEXT: vpsubd %xmm3, %xmm2, %xmm2 +; AVX1-NEXT: vpsubd %xmm3, %xmm7, %xmm7 +; AVX1-NEXT: vpsubd %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vpsrld $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsrld $1, %xmm7, %xmm3 +; AVX1-NEXT: vpsrld $1, %xmm2, %xmm2 +; AVX1-NEXT: vpsrld $1, %xmm8, %xmm7 +; AVX1-NEXT: vpsrld $1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrld $1, %xmm6, %xmm6 +; AVX1-NEXT: vpsrld $1, %xmm4, %xmm4 +; AVX1-NEXT: vpsrld $1, %xmm5, %xmm5 +; AVX1-NEXT: vpxor %xmm8, %xmm8, %xmm8 +; AVX1-NEXT: vpblendw {{.*#+}} xmm5 = xmm5[0],xmm8[1],xmm5[2],xmm8[3],xmm5[4],xmm8[5],xmm5[6],xmm8[7] +; AVX1-NEXT: vpblendw {{.*#+}} xmm4 = xmm4[0],xmm8[1],xmm4[2],xmm8[3],xmm4[4],xmm8[5],xmm4[6],xmm8[7] +; AVX1-NEXT: vpackusdw %xmm4, %xmm5, %xmm4 +; AVX1-NEXT: vpblendw {{.*#+}} xmm5 = xmm6[0],xmm8[1],xmm6[2],xmm8[3],xmm6[4],xmm8[5],xmm6[6],xmm8[7] +; AVX1-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0],xmm8[1],xmm0[2],xmm8[3],xmm0[4],xmm8[5],xmm0[6],xmm8[7] +; AVX1-NEXT: vpackusdw %xmm0, %xmm5, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm4, %ymm0, %ymm0 +; AVX1-NEXT: vpblendw {{.*#+}} xmm4 = xmm7[0],xmm8[1],xmm7[2],xmm8[3],xmm7[4],xmm8[5],xmm7[6],xmm8[7] +; AVX1-NEXT: vpblendw {{.*#+}} xmm2 = xmm2[0],xmm8[1],xmm2[2],xmm8[3],xmm2[4],xmm8[5],xmm2[6],xmm8[7] +; AVX1-NEXT: vpackusdw %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vpblendw {{.*#+}} xmm3 = xmm3[0],xmm8[1],xmm3[2],xmm8[3],xmm3[4],xmm8[5],xmm3[6],xmm8[7] +; AVX1-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0],xmm8[1],xmm1[2],xmm8[3],xmm1[4],xmm8[5],xmm1[6],xmm8[7] +; AVX1-NEXT: vpackusdw %xmm1, %xmm3, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm1, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v32i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm4 +; AVX2-NEXT: vpmovsxwd %xmm4, %ymm4 +; AVX2-NEXT: vpmovsxwd %xmm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm5 +; AVX2-NEXT: vpmovsxwd %xmm5, %ymm5 +; AVX2-NEXT: vpmovsxwd %xmm1, %ymm1 +; AVX2-NEXT: vextracti128 $1, %ymm2, %xmm6 +; AVX2-NEXT: vpmovsxwd %xmm6, %ymm6 +; AVX2-NEXT: vpaddd %ymm6, %ymm4, %ymm4 +; AVX2-NEXT: vpmovsxwd %xmm2, %ymm2 +; AVX2-NEXT: vpaddd %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm3, %xmm2 +; AVX2-NEXT: vpmovsxwd %xmm2, %ymm2 +; AVX2-NEXT: vpaddd %ymm2, %ymm5, %ymm2 +; AVX2-NEXT: vpmovsxwd %xmm3, %ymm3 +; AVX2-NEXT: vpaddd %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: vpcmpeqd %ymm3, %ymm3, %ymm3 +; AVX2-NEXT: vpsubd %ymm3, %ymm4, %ymm4 +; AVX2-NEXT: vpsubd %ymm3, %ymm0, %ymm0 +; AVX2-NEXT: vpsubd %ymm3, %ymm2, %ymm2 +; AVX2-NEXT: vpsubd %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: vpsrld $1, %ymm1, %ymm1 +; AVX2-NEXT: vpsrld $1, %ymm2, %ymm2 +; AVX2-NEXT: vpsrld $1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrld $1, %ymm4, %ymm3 +; AVX2-NEXT: vpxor %xmm4, %xmm4, %xmm4 +; AVX2-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm4[1],ymm3[2],ymm4[3],ymm3[4],ymm4[5],ymm3[6],ymm4[7],ymm3[8],ymm4[9],ymm3[10],ymm4[11],ymm3[12],ymm4[13],ymm3[14],ymm4[15] +; AVX2-NEXT: vpblendw {{.*#+}} ymm0 = ymm0[0],ymm4[1],ymm0[2],ymm4[3],ymm0[4],ymm4[5],ymm0[6],ymm4[7],ymm0[8],ymm4[9],ymm0[10],ymm4[11],ymm0[12],ymm4[13],ymm0[14],ymm4[15] +; AVX2-NEXT: vpackusdw %ymm3, %ymm0, %ymm0 +; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,2,1,3] +; AVX2-NEXT: vpblendw {{.*#+}} ymm2 = ymm2[0],ymm4[1],ymm2[2],ymm4[3],ymm2[4],ymm4[5],ymm2[6],ymm4[7],ymm2[8],ymm4[9],ymm2[10],ymm4[11],ymm2[12],ymm4[13],ymm2[14],ymm4[15] +; AVX2-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0],ymm4[1],ymm1[2],ymm4[3],ymm1[4],ymm4[5],ymm1[6],ymm4[7],ymm1[8],ymm4[9],ymm1[10],ymm4[11],ymm1[12],ymm4[13],ymm1[14],ymm4[15] +; AVX2-NEXT: vpackusdw %ymm2, %ymm1, %ymm1 +; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,2,1,3] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v32i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovsxwd %ymm0, %zmm2 +; AVX512-NEXT: vextracti64x4 $1, %zmm0, %ymm0 +; AVX512-NEXT: vpmovsxwd %ymm0, %zmm0 +; AVX512-NEXT: vpmovsxwd %ymm1, %zmm3 +; AVX512-NEXT: vpaddd %zmm3, %zmm2, %zmm2 +; AVX512-NEXT: vextracti64x4 $1, %zmm1, %ymm1 +; AVX512-NEXT: vpmovsxwd %ymm1, %zmm1 +; AVX512-NEXT: vpaddd %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpternlogd $255, %zmm1, %zmm1, %zmm1 +; AVX512-NEXT: vpsubd %zmm1, %zmm2, %zmm2 +; AVX512-NEXT: vpsubd %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrld $1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrld $1, %zmm2, %zmm1 +; AVX512-NEXT: vpmovdw %zmm1, %ymm1 +; AVX512-NEXT: vpmovdw %zmm0, %ymm0 +; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-NEXT: retq + %x0 = sext <32 x i16> %a0 to <32 x i32> + %x1 = sext <32 x i16> %a1 to <32 x i32> + %sum = add <32 x i32> %x0, %x1 + %inc = add <32 x i32> %sum, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %shift = ashr <32 x i32> %inc, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = trunc <32 x i32> %shift to <32 x i16> + ret <32 x i16> %res +} + +define <16 x i32> @test_fixed_v16i32(<16 x i32> %a0, <16 x i32> %a1) { +; SSE-LABEL: test_fixed_v16i32: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm3, %xmm8 +; SSE-NEXT: por %xmm7, %xmm3 +; SSE-NEXT: movdqa %xmm2, %xmm9 +; SSE-NEXT: por %xmm6, %xmm9 +; SSE-NEXT: movdqa %xmm1, %xmm10 +; SSE-NEXT: por %xmm5, %xmm10 +; SSE-NEXT: movdqa %xmm0, %xmm11 +; SSE-NEXT: por %xmm4, %xmm11 +; SSE-NEXT: pxor %xmm0, %xmm4 +; SSE-NEXT: pxor %xmm1, %xmm5 +; SSE-NEXT: pxor %xmm2, %xmm6 +; SSE-NEXT: pxor %xmm8, %xmm7 +; SSE-NEXT: psrad $1, %xmm7 +; SSE-NEXT: psubd %xmm7, %xmm3 +; SSE-NEXT: psrad $1, %xmm6 +; SSE-NEXT: psubd %xmm6, %xmm9 +; SSE-NEXT: psrad $1, %xmm5 +; SSE-NEXT: psubd %xmm5, %xmm10 +; SSE-NEXT: psrad $1, %xmm4 +; SSE-NEXT: psubd %xmm4, %xmm11 +; SSE-NEXT: movdqa %xmm11, %xmm0 +; SSE-NEXT: movdqa %xmm10, %xmm1 +; SSE-NEXT: movdqa %xmm9, %xmm2 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v16i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vorps %ymm3, %ymm1, %ymm4 +; AVX1-NEXT: vorps %ymm2, %ymm0, %ymm5 +; AVX1-NEXT: vxorps %ymm0, %ymm2, %ymm0 +; AVX1-NEXT: vxorps %ymm1, %ymm3, %ymm1 +; AVX1-NEXT: vpsrad $1, %xmm1, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpsrad $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsrad $1, %xmm0, %xmm3 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrad $1, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm5, %xmm6 +; AVX1-NEXT: vpsubd %xmm0, %xmm6, %xmm0 +; AVX1-NEXT: vpsubd %xmm3, %xmm5, %xmm3 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm3, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm4, %xmm3 +; AVX1-NEXT: vpsubd %xmm1, %xmm3, %xmm1 +; AVX1-NEXT: vpsubd %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v16i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vpor %ymm3, %ymm1, %ymm4 +; AVX2-NEXT: vpor %ymm2, %ymm0, %ymm5 +; AVX2-NEXT: vpxor %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: vpxor %ymm1, %ymm3, %ymm1 +; AVX2-NEXT: vpsrad $1, %ymm1, %ymm1 +; AVX2-NEXT: vpsubd %ymm1, %ymm4, %ymm1 +; AVX2-NEXT: vpsrad $1, %ymm0, %ymm0 +; AVX2-NEXT: vpsubd %ymm0, %ymm5, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v16i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vpord %zmm1, %zmm0, %zmm2 +; AVX512-NEXT: vpxord %zmm0, %zmm1, %zmm0 +; AVX512-NEXT: vpsrad $1, %zmm0, %zmm0 +; AVX512-NEXT: vpsubd %zmm0, %zmm2, %zmm0 +; AVX512-NEXT: retq + %or = or <16 x i32> %a0, %a1 + %xor = xor <16 x i32> %a1, %a0 + %shift = ashr <16 x i32> %xor, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = sub <16 x i32> %or, %shift + ret <16 x i32> %res +} + +define <16 x i32> @test_ext_v16i32(<16 x i32> %a0, <16 x i32> %a1) { +; SSE2-LABEL: test_ext_v16i32: +; SSE2: # %bb.0: +; SSE2-NEXT: pshufd {{.*#+}} xmm13 = xmm0[2,3,2,3] +; SSE2-NEXT: pxor %xmm9, %xmm9 +; SSE2-NEXT: pxor %xmm8, %xmm8 +; SSE2-NEXT: pcmpgtd %xmm13, %xmm8 +; SSE2-NEXT: punpckldq {{.*#+}} xmm13 = xmm13[0],xmm8[0],xmm13[1],xmm8[1] +; SSE2-NEXT: pxor %xmm8, %xmm8 +; SSE2-NEXT: pcmpgtd %xmm0, %xmm8 +; SSE2-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm8[0],xmm0[1],xmm8[1] +; SSE2-NEXT: pshufd {{.*#+}} xmm12 = xmm1[2,3,2,3] +; SSE2-NEXT: pxor %xmm8, %xmm8 +; SSE2-NEXT: pcmpgtd %xmm12, %xmm8 +; SSE2-NEXT: punpckldq {{.*#+}} xmm12 = xmm12[0],xmm8[0],xmm12[1],xmm8[1] +; SSE2-NEXT: pxor %xmm8, %xmm8 +; SSE2-NEXT: pcmpgtd %xmm1, %xmm8 +; SSE2-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm8[0],xmm1[1],xmm8[1] +; SSE2-NEXT: pshufd {{.*#+}} xmm11 = xmm2[2,3,2,3] +; SSE2-NEXT: pxor %xmm8, %xmm8 +; SSE2-NEXT: pcmpgtd %xmm11, %xmm8 +; SSE2-NEXT: punpckldq {{.*#+}} xmm11 = xmm11[0],xmm8[0],xmm11[1],xmm8[1] +; SSE2-NEXT: pxor %xmm8, %xmm8 +; SSE2-NEXT: pcmpgtd %xmm2, %xmm8 +; SSE2-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm8[0],xmm2[1],xmm8[1] +; SSE2-NEXT: pshufd {{.*#+}} xmm10 = xmm3[2,3,2,3] +; SSE2-NEXT: pxor %xmm8, %xmm8 +; SSE2-NEXT: pcmpgtd %xmm10, %xmm8 +; SSE2-NEXT: punpckldq {{.*#+}} xmm10 = xmm10[0],xmm8[0],xmm10[1],xmm8[1] +; SSE2-NEXT: pxor %xmm8, %xmm8 +; SSE2-NEXT: pcmpgtd %xmm3, %xmm8 +; SSE2-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm8[0],xmm3[1],xmm8[1] +; SSE2-NEXT: pshufd {{.*#+}} xmm8 = xmm4[2,3,2,3] +; SSE2-NEXT: pxor %xmm14, %xmm14 +; SSE2-NEXT: pcmpgtd %xmm8, %xmm14 +; SSE2-NEXT: punpckldq {{.*#+}} xmm8 = xmm8[0],xmm14[0],xmm8[1],xmm14[1] +; SSE2-NEXT: paddq %xmm13, %xmm8 +; SSE2-NEXT: pxor %xmm13, %xmm13 +; SSE2-NEXT: pcmpgtd %xmm4, %xmm13 +; SSE2-NEXT: punpckldq {{.*#+}} xmm4 = xmm4[0],xmm13[0],xmm4[1],xmm13[1] +; SSE2-NEXT: paddq %xmm4, %xmm0 +; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm5[2,3,2,3] +; SSE2-NEXT: pxor %xmm13, %xmm13 +; SSE2-NEXT: pcmpgtd %xmm4, %xmm13 +; SSE2-NEXT: punpckldq {{.*#+}} xmm4 = xmm4[0],xmm13[0],xmm4[1],xmm13[1] +; SSE2-NEXT: paddq %xmm12, %xmm4 +; SSE2-NEXT: pxor %xmm12, %xmm12 +; SSE2-NEXT: pcmpgtd %xmm5, %xmm12 +; SSE2-NEXT: punpckldq {{.*#+}} xmm5 = xmm5[0],xmm12[0],xmm5[1],xmm12[1] +; SSE2-NEXT: paddq %xmm5, %xmm1 +; SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm6[2,3,2,3] +; SSE2-NEXT: pxor %xmm12, %xmm12 +; SSE2-NEXT: pcmpgtd %xmm5, %xmm12 +; SSE2-NEXT: punpckldq {{.*#+}} xmm5 = xmm5[0],xmm12[0],xmm5[1],xmm12[1] +; SSE2-NEXT: paddq %xmm11, %xmm5 +; SSE2-NEXT: pxor %xmm11, %xmm11 +; SSE2-NEXT: pcmpgtd %xmm6, %xmm11 +; SSE2-NEXT: punpckldq {{.*#+}} xmm6 = xmm6[0],xmm11[0],xmm6[1],xmm11[1] +; SSE2-NEXT: paddq %xmm6, %xmm2 +; SSE2-NEXT: pshufd {{.*#+}} xmm6 = xmm7[2,3,2,3] +; SSE2-NEXT: pxor %xmm11, %xmm11 +; SSE2-NEXT: pcmpgtd %xmm6, %xmm11 +; SSE2-NEXT: punpckldq {{.*#+}} xmm6 = xmm6[0],xmm11[0],xmm6[1],xmm11[1] +; SSE2-NEXT: paddq %xmm10, %xmm6 +; SSE2-NEXT: pcmpgtd %xmm7, %xmm9 +; SSE2-NEXT: punpckldq {{.*#+}} xmm7 = xmm7[0],xmm9[0],xmm7[1],xmm9[1] +; SSE2-NEXT: paddq %xmm7, %xmm3 +; SSE2-NEXT: pcmpeqd %xmm7, %xmm7 +; SSE2-NEXT: psubq %xmm7, %xmm8 +; SSE2-NEXT: psubq %xmm7, %xmm0 +; SSE2-NEXT: psubq %xmm7, %xmm4 +; SSE2-NEXT: psubq %xmm7, %xmm1 +; SSE2-NEXT: psubq %xmm7, %xmm5 +; SSE2-NEXT: psubq %xmm7, %xmm2 +; SSE2-NEXT: psubq %xmm7, %xmm6 +; SSE2-NEXT: psubq %xmm7, %xmm3 +; SSE2-NEXT: psrlq $1, %xmm3 +; SSE2-NEXT: psrlq $1, %xmm6 +; SSE2-NEXT: shufps {{.*#+}} xmm3 = xmm3[0,2],xmm6[0,2] +; SSE2-NEXT: psrlq $1, %xmm2 +; SSE2-NEXT: psrlq $1, %xmm5 +; SSE2-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,2],xmm5[0,2] +; SSE2-NEXT: psrlq $1, %xmm1 +; SSE2-NEXT: psrlq $1, %xmm4 +; SSE2-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm4[0,2] +; SSE2-NEXT: psrlq $1, %xmm0 +; SSE2-NEXT: psrlq $1, %xmm8 +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm8[0,2] +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v16i32: +; SSE4: # %bb.0: +; SSE4-NEXT: pshufd {{.*#+}} xmm8 = xmm0[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm8, %xmm9 +; SSE4-NEXT: pmovsxdq %xmm0, %xmm10 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm0, %xmm11 +; SSE4-NEXT: pmovsxdq %xmm1, %xmm12 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm2[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm0, %xmm13 +; SSE4-NEXT: pmovsxdq %xmm2, %xmm14 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm3[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm0, %xmm15 +; SSE4-NEXT: pmovsxdq %xmm3, %xmm0 +; SSE4-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm4[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm0, %xmm8 +; SSE4-NEXT: paddq %xmm9, %xmm8 +; SSE4-NEXT: pmovsxdq %xmm4, %xmm0 +; SSE4-NEXT: paddq %xmm10, %xmm0 +; SSE4-NEXT: pshufd {{.*#+}} xmm1 = xmm5[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm1, %xmm4 +; SSE4-NEXT: paddq %xmm11, %xmm4 +; SSE4-NEXT: pmovsxdq %xmm5, %xmm1 +; SSE4-NEXT: paddq %xmm12, %xmm1 +; SSE4-NEXT: pshufd {{.*#+}} xmm2 = xmm6[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm2, %xmm5 +; SSE4-NEXT: paddq %xmm13, %xmm5 +; SSE4-NEXT: pmovsxdq %xmm6, %xmm2 +; SSE4-NEXT: paddq %xmm14, %xmm2 +; SSE4-NEXT: pshufd {{.*#+}} xmm3 = xmm7[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm3, %xmm6 +; SSE4-NEXT: paddq %xmm15, %xmm6 +; SSE4-NEXT: pmovsxdq %xmm7, %xmm3 +; SSE4-NEXT: paddq {{[-0-9]+}}(%r{{[sb]}}p), %xmm3 # 16-byte Folded Reload +; SSE4-NEXT: pcmpeqd %xmm7, %xmm7 +; SSE4-NEXT: psubq %xmm7, %xmm8 +; SSE4-NEXT: psubq %xmm7, %xmm0 +; SSE4-NEXT: psubq %xmm7, %xmm4 +; SSE4-NEXT: psubq %xmm7, %xmm1 +; SSE4-NEXT: psubq %xmm7, %xmm5 +; SSE4-NEXT: psubq %xmm7, %xmm2 +; SSE4-NEXT: psubq %xmm7, %xmm6 +; SSE4-NEXT: psubq %xmm7, %xmm3 +; SSE4-NEXT: psrlq $1, %xmm3 +; SSE4-NEXT: psrlq $1, %xmm6 +; SSE4-NEXT: shufps {{.*#+}} xmm3 = xmm3[0,2],xmm6[0,2] +; SSE4-NEXT: psrlq $1, %xmm2 +; SSE4-NEXT: psrlq $1, %xmm5 +; SSE4-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,2],xmm5[0,2] +; SSE4-NEXT: psrlq $1, %xmm1 +; SSE4-NEXT: psrlq $1, %xmm4 +; SSE4-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm4[0,2] +; SSE4-NEXT: psrlq $1, %xmm0 +; SSE4-NEXT: psrlq $1, %xmm8 +; SSE4-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm8[0,2] +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v16i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vpmovsxdq %xmm0, %xmm4 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm5 +; AVX1-NEXT: vpmovsxdq %xmm5, %xmm6 +; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm0, %xmm0 +; AVX1-NEXT: vpshufd {{.*#+}} xmm5 = xmm5[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm5, %xmm5 +; AVX1-NEXT: vpmovsxdq %xmm1, %xmm7 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm8 +; AVX1-NEXT: vpmovsxdq %xmm8, %xmm9 +; AVX1-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm1, %xmm1 +; AVX1-NEXT: vpshufd {{.*#+}} xmm8 = xmm8[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm8, %xmm8 +; AVX1-NEXT: vpmovsxdq %xmm2, %xmm10 +; AVX1-NEXT: vpaddq %xmm4, %xmm10, %xmm4 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm10 +; AVX1-NEXT: vpmovsxdq %xmm10, %xmm11 +; AVX1-NEXT: vpaddq %xmm6, %xmm11, %xmm6 +; AVX1-NEXT: vpshufd {{.*#+}} xmm2 = xmm2[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm2, %xmm2 +; AVX1-NEXT: vpaddq %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpshufd {{.*#+}} xmm2 = xmm10[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm2, %xmm2 +; AVX1-NEXT: vpaddq %xmm2, %xmm5, %xmm2 +; AVX1-NEXT: vpmovsxdq %xmm3, %xmm5 +; AVX1-NEXT: vpaddq %xmm5, %xmm7, %xmm5 +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm7 +; AVX1-NEXT: vpmovsxdq %xmm7, %xmm10 +; AVX1-NEXT: vpaddq %xmm10, %xmm9, %xmm9 +; AVX1-NEXT: vpshufd {{.*#+}} xmm3 = xmm3[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm3, %xmm3 +; AVX1-NEXT: vpaddq %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vpshufd {{.*#+}} xmm3 = xmm7[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm3, %xmm3 +; AVX1-NEXT: vpaddq %xmm3, %xmm8, %xmm3 +; AVX1-NEXT: vpcmpeqd %xmm7, %xmm7, %xmm7 +; AVX1-NEXT: vpsubq %xmm7, %xmm4, %xmm4 +; AVX1-NEXT: vpsubq %xmm7, %xmm6, %xmm6 +; AVX1-NEXT: vpsubq %xmm7, %xmm0, %xmm0 +; AVX1-NEXT: vpsubq %xmm7, %xmm2, %xmm2 +; AVX1-NEXT: vpsubq %xmm7, %xmm5, %xmm5 +; AVX1-NEXT: vpsubq %xmm7, %xmm9, %xmm8 +; AVX1-NEXT: vpsubq %xmm7, %xmm1, %xmm1 +; AVX1-NEXT: vpsubq %xmm7, %xmm3, %xmm3 +; AVX1-NEXT: vpsrlq $1, %xmm3, %xmm3 +; AVX1-NEXT: vpsrlq $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm8, %xmm7 +; AVX1-NEXT: vpsrlq $1, %xmm5, %xmm5 +; AVX1-NEXT: vpsrlq $1, %xmm2, %xmm2 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlq $1, %xmm6, %xmm6 +; AVX1-NEXT: vpsrlq $1, %xmm4, %xmm4 +; AVX1-NEXT: vinsertf128 $1, %xmm6, %ymm4, %ymm4 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 +; AVX1-NEXT: vshufps {{.*#+}} ymm0 = ymm4[0,2],ymm0[0,2],ymm4[4,6],ymm0[4,6] +; AVX1-NEXT: vinsertf128 $1, %xmm7, %ymm5, %ymm2 +; AVX1-NEXT: vinsertf128 $1, %xmm3, %ymm1, %ymm1 +; AVX1-NEXT: vshufps {{.*#+}} ymm1 = ymm2[0,2],ymm1[0,2],ymm2[4,6],ymm1[4,6] +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v16i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovsxdq %xmm1, %ymm4 +; AVX2-NEXT: vpmovsxdq %xmm0, %ymm5 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX2-NEXT: vpmovsxdq %xmm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm1 +; AVX2-NEXT: vpmovsxdq %xmm1, %ymm1 +; AVX2-NEXT: vpmovsxdq %xmm3, %ymm6 +; AVX2-NEXT: vpaddq %ymm6, %ymm4, %ymm4 +; AVX2-NEXT: vpmovsxdq %xmm2, %ymm6 +; AVX2-NEXT: vpaddq %ymm6, %ymm5, %ymm5 +; AVX2-NEXT: vextracti128 $1, %ymm2, %xmm2 +; AVX2-NEXT: vpmovsxdq %xmm2, %ymm2 +; AVX2-NEXT: vpaddq %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm3, %xmm2 +; AVX2-NEXT: vpmovsxdq %xmm2, %ymm2 +; AVX2-NEXT: vpaddq %ymm2, %ymm1, %ymm1 +; AVX2-NEXT: vpcmpeqd %ymm2, %ymm2, %ymm2 +; AVX2-NEXT: vpsubq %ymm2, %ymm4, %ymm3 +; AVX2-NEXT: vpsubq %ymm2, %ymm5, %ymm4 +; AVX2-NEXT: vpsubq %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpsubq %ymm2, %ymm1, %ymm1 +; AVX2-NEXT: vperm2i128 {{.*#+}} ymm2 = ymm4[2,3],ymm0[2,3] +; AVX2-NEXT: vpsrlq $1, %ymm2, %ymm2 +; AVX2-NEXT: vinserti128 $1, %xmm0, %ymm4, %ymm0 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vshufps {{.*#+}} ymm0 = ymm0[0,2],ymm2[0,2],ymm0[4,6],ymm2[4,6] +; AVX2-NEXT: vperm2i128 {{.*#+}} ymm2 = ymm3[2,3],ymm1[2,3] +; AVX2-NEXT: vpsrlq $1, %ymm2, %ymm2 +; AVX2-NEXT: vinserti128 $1, %xmm1, %ymm3, %ymm1 +; AVX2-NEXT: vpsrlq $1, %ymm1, %ymm1 +; AVX2-NEXT: vshufps {{.*#+}} ymm1 = ymm1[0,2],ymm2[0,2],ymm1[4,6],ymm2[4,6] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v16i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovsxdq %ymm0, %zmm2 +; AVX512-NEXT: vextracti64x4 $1, %zmm0, %ymm0 +; AVX512-NEXT: vpmovsxdq %ymm0, %zmm0 +; AVX512-NEXT: vpmovsxdq %ymm1, %zmm3 +; AVX512-NEXT: vpaddq %zmm3, %zmm2, %zmm2 +; AVX512-NEXT: vextracti64x4 $1, %zmm1, %ymm1 +; AVX512-NEXT: vpmovsxdq %ymm1, %zmm1 +; AVX512-NEXT: vpaddq %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpternlogd $255, %zmm1, %zmm1, %zmm1 +; AVX512-NEXT: vpsubq %zmm1, %zmm2, %zmm2 +; AVX512-NEXT: vpsubq %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlq $1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlq $1, %zmm2, %zmm1 +; AVX512-NEXT: vpmovqd %zmm1, %ymm1 +; AVX512-NEXT: vpmovqd %zmm0, %ymm0 +; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-NEXT: retq + %x0 = sext <16 x i32> %a0 to <16 x i64> + %x1 = sext <16 x i32> %a1 to <16 x i64> + %sum = add <16 x i64> %x0, %x1 + %inc = add <16 x i64> %sum, <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1> + %shift = ashr <16 x i64> %inc, <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1> + %res = trunc <16 x i64> %shift to <16 x i32> + ret <16 x i32> %res +} + +define <8 x i64> @test_fixed_v8i64(<8 x i64> %a0, <8 x i64> %a1) { +; SSE2-LABEL: test_fixed_v8i64: +; SSE2: # %bb.0: +; SSE2-NEXT: movdqa %xmm3, %xmm8 +; SSE2-NEXT: movdqa %xmm2, %xmm9 +; SSE2-NEXT: movdqa %xmm1, %xmm10 +; SSE2-NEXT: movdqa %xmm0, %xmm11 +; SSE2-NEXT: por %xmm7, %xmm3 +; SSE2-NEXT: por %xmm6, %xmm2 +; SSE2-NEXT: por %xmm5, %xmm1 +; SSE2-NEXT: por %xmm4, %xmm0 +; SSE2-NEXT: pxor %xmm11, %xmm4 +; SSE2-NEXT: pxor %xmm10, %xmm5 +; SSE2-NEXT: pxor %xmm9, %xmm6 +; SSE2-NEXT: pxor %xmm8, %xmm7 +; SSE2-NEXT: pshufd {{.*#+}} xmm8 = xmm7[1,3,2,3] +; SSE2-NEXT: psrad $1, %xmm8 +; SSE2-NEXT: psrlq $1, %xmm7 +; SSE2-NEXT: pshufd {{.*#+}} xmm7 = xmm7[0,2,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm7 = xmm7[0],xmm8[0],xmm7[1],xmm8[1] +; SSE2-NEXT: psubq %xmm7, %xmm3 +; SSE2-NEXT: pshufd {{.*#+}} xmm7 = xmm6[1,3,2,3] +; SSE2-NEXT: psrad $1, %xmm7 +; SSE2-NEXT: psrlq $1, %xmm6 +; SSE2-NEXT: pshufd {{.*#+}} xmm6 = xmm6[0,2,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm6 = xmm6[0],xmm7[0],xmm6[1],xmm7[1] +; SSE2-NEXT: psubq %xmm6, %xmm2 +; SSE2-NEXT: pshufd {{.*#+}} xmm6 = xmm5[1,3,2,3] +; SSE2-NEXT: psrad $1, %xmm6 +; SSE2-NEXT: psrlq $1, %xmm5 +; SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm5[0,2,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm5 = xmm5[0],xmm6[0],xmm5[1],xmm6[1] +; SSE2-NEXT: psubq %xmm5, %xmm1 +; SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm4[1,3,2,3] +; SSE2-NEXT: psrad $1, %xmm5 +; SSE2-NEXT: psrlq $1, %xmm4 +; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm4[0,2,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm4 = xmm4[0],xmm5[0],xmm4[1],xmm5[1] +; SSE2-NEXT: psubq %xmm4, %xmm0 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_fixed_v8i64: +; SSE4: # %bb.0: +; SSE4-NEXT: movdqa %xmm3, %xmm8 +; SSE4-NEXT: movdqa %xmm2, %xmm9 +; SSE4-NEXT: movdqa %xmm1, %xmm10 +; SSE4-NEXT: movdqa %xmm0, %xmm11 +; SSE4-NEXT: por %xmm7, %xmm3 +; SSE4-NEXT: por %xmm6, %xmm2 +; SSE4-NEXT: por %xmm5, %xmm1 +; SSE4-NEXT: por %xmm4, %xmm0 +; SSE4-NEXT: pxor %xmm11, %xmm4 +; SSE4-NEXT: pxor %xmm10, %xmm5 +; SSE4-NEXT: pxor %xmm9, %xmm6 +; SSE4-NEXT: pxor %xmm8, %xmm7 +; SSE4-NEXT: movdqa %xmm7, %xmm8 +; SSE4-NEXT: psrad $1, %xmm8 +; SSE4-NEXT: psrlq $1, %xmm7 +; SSE4-NEXT: pblendw {{.*#+}} xmm7 = xmm7[0,1],xmm8[2,3],xmm7[4,5],xmm8[6,7] +; SSE4-NEXT: psubq %xmm7, %xmm3 +; SSE4-NEXT: movdqa %xmm6, %xmm7 +; SSE4-NEXT: psrad $1, %xmm7 +; SSE4-NEXT: psrlq $1, %xmm6 +; SSE4-NEXT: pblendw {{.*#+}} xmm6 = xmm6[0,1],xmm7[2,3],xmm6[4,5],xmm7[6,7] +; SSE4-NEXT: psubq %xmm6, %xmm2 +; SSE4-NEXT: movdqa %xmm5, %xmm6 +; SSE4-NEXT: psrad $1, %xmm6 +; SSE4-NEXT: psrlq $1, %xmm5 +; SSE4-NEXT: pblendw {{.*#+}} xmm5 = xmm5[0,1],xmm6[2,3],xmm5[4,5],xmm6[6,7] +; SSE4-NEXT: psubq %xmm5, %xmm1 +; SSE4-NEXT: movdqa %xmm4, %xmm5 +; SSE4-NEXT: psrad $1, %xmm5 +; SSE4-NEXT: psrlq $1, %xmm4 +; SSE4-NEXT: pblendw {{.*#+}} xmm4 = xmm4[0,1],xmm5[2,3],xmm4[4,5],xmm5[6,7] +; SSE4-NEXT: psubq %xmm4, %xmm0 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_fixed_v8i64: +; AVX1: # %bb.0: +; AVX1-NEXT: vorps %ymm3, %ymm1, %ymm4 +; AVX1-NEXT: vorps %ymm2, %ymm0, %ymm5 +; AVX1-NEXT: vxorps %ymm0, %ymm2, %ymm0 +; AVX1-NEXT: vxorps %ymm1, %ymm3, %ymm1 +; AVX1-NEXT: vpsrad $1, %xmm1, %xmm2 +; AVX1-NEXT: vpsrlq $1, %xmm1, %xmm3 +; AVX1-NEXT: vpblendw {{.*#+}} xmm2 = xmm3[0,1],xmm2[2,3],xmm3[4,5],xmm2[6,7] +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpsrad $1, %xmm1, %xmm3 +; AVX1-NEXT: vpsrlq $1, %xmm1, %xmm1 +; AVX1-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0,1],xmm3[2,3],xmm1[4,5],xmm3[6,7] +; AVX1-NEXT: vpsrad $1, %xmm0, %xmm3 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm6 +; AVX1-NEXT: vpblendw {{.*#+}} xmm3 = xmm6[0,1],xmm3[2,3],xmm6[4,5],xmm3[6,7] +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrad $1, %xmm0, %xmm6 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0,1],xmm6[2,3],xmm0[4,5],xmm6[6,7] +; AVX1-NEXT: vextractf128 $1, %ymm5, %xmm6 +; AVX1-NEXT: vpsubq %xmm0, %xmm6, %xmm0 +; AVX1-NEXT: vpsubq %xmm3, %xmm5, %xmm3 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm3, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm4, %xmm3 +; AVX1-NEXT: vpsubq %xmm1, %xmm3, %xmm1 +; AVX1-NEXT: vpsubq %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v8i64: +; AVX2: # %bb.0: +; AVX2-NEXT: vpor %ymm3, %ymm1, %ymm4 +; AVX2-NEXT: vpor %ymm2, %ymm0, %ymm5 +; AVX2-NEXT: vpxor %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: vpxor %ymm1, %ymm3, %ymm1 +; AVX2-NEXT: vpsrad $1, %ymm1, %ymm2 +; AVX2-NEXT: vpsrlq $1, %ymm1, %ymm1 +; AVX2-NEXT: vpblendd {{.*#+}} ymm1 = ymm1[0],ymm2[1],ymm1[2],ymm2[3],ymm1[4],ymm2[5],ymm1[6],ymm2[7] +; AVX2-NEXT: vpsubq %ymm1, %ymm4, %ymm1 +; AVX2-NEXT: vpsrad $1, %ymm0, %ymm2 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vpblendd {{.*#+}} ymm0 = ymm0[0],ymm2[1],ymm0[2],ymm2[3],ymm0[4],ymm2[5],ymm0[6],ymm2[7] +; AVX2-NEXT: vpsubq %ymm0, %ymm5, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v8i64: +; AVX512: # %bb.0: +; AVX512-NEXT: vporq %zmm1, %zmm0, %zmm2 +; AVX512-NEXT: vpxorq %zmm0, %zmm1, %zmm0 +; AVX512-NEXT: vpsraq $1, %zmm0, %zmm0 +; AVX512-NEXT: vpsubq %zmm0, %zmm2, %zmm0 +; AVX512-NEXT: retq + %or = or <8 x i64> %a0, %a1 + %xor = xor <8 x i64> %a1, %a0 + %shift = ashr <8 x i64> %xor, <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1> + %res = sub <8 x i64> %or, %shift + ret <8 x i64> %res +} + +define <8 x i64> @test_ext_v8i64(<8 x i64> %a0, <8 x i64> %a1) { +; SSE2-LABEL: test_ext_v8i64: +; SSE2: # %bb.0: +; SSE2-NEXT: pushq %rbp +; SSE2-NEXT: .cfi_def_cfa_offset 16 +; SSE2-NEXT: pushq %r15 +; SSE2-NEXT: .cfi_def_cfa_offset 24 +; SSE2-NEXT: pushq %r14 +; SSE2-NEXT: .cfi_def_cfa_offset 32 +; SSE2-NEXT: pushq %r13 +; SSE2-NEXT: .cfi_def_cfa_offset 40 +; SSE2-NEXT: pushq %r12 +; SSE2-NEXT: .cfi_def_cfa_offset 48 +; SSE2-NEXT: pushq %rbx +; SSE2-NEXT: .cfi_def_cfa_offset 56 +; SSE2-NEXT: pushq %rax +; SSE2-NEXT: .cfi_def_cfa_offset 64 +; SSE2-NEXT: .cfi_offset %rbx, -56 +; SSE2-NEXT: .cfi_offset %r12, -48 +; SSE2-NEXT: .cfi_offset %r13, -40 +; SSE2-NEXT: .cfi_offset %r14, -32 +; SSE2-NEXT: .cfi_offset %r15, -24 +; SSE2-NEXT: .cfi_offset %rbp, -16 +; SSE2-NEXT: movq %xmm0, %rax +; SSE2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: sarq $63, %rax +; SSE2-NEXT: movq %rax, (%rsp) # 8-byte Spill +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %rax +; SSE2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: sarq $63, %rcx +; SSE2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: movq %xmm1, %rax +; SSE2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: sarq $63, %rcx +; SSE2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %rax +; SSE2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: sarq $63, %rcx +; SSE2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: movq %xmm2, %rax +; SSE2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: sarq $63, %rcx +; SSE2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm2[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %rax +; SSE2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: sarq $63, %rcx +; SSE2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: movq %xmm3, %rbx +; SSE2-NEXT: movq %rbx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: sarq $63, %rbx +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm3[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %rdi +; SSE2-NEXT: movq %rdi, %rbp +; SSE2-NEXT: sarq $63, %rbp +; SSE2-NEXT: movq %xmm4, %r8 +; SSE2-NEXT: movq %r8, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: sarq $63, %r8 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm4[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %r11 +; SSE2-NEXT: movq %r11, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: sarq $63, %r11 +; SSE2-NEXT: movq %xmm5, %r10 +; SSE2-NEXT: movq %r10, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: sarq $63, %r10 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm5[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %r15 +; SSE2-NEXT: movq %r15, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: sarq $63, %r15 +; SSE2-NEXT: movq %xmm6, %r9 +; SSE2-NEXT: movq %r9, %r14 +; SSE2-NEXT: sarq $63, %r14 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm6[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %rsi +; SSE2-NEXT: movq %rsi, %r13 +; SSE2-NEXT: sarq $63, %r13 +; SSE2-NEXT: movq %xmm7, %rdx +; SSE2-NEXT: movq %rdx, %r12 +; SSE2-NEXT: sarq $63, %r12 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm7[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %rax +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: sarq $63, %rcx +; SSE2-NEXT: addq %rax, %rdi +; SSE2-NEXT: adcq %rbp, %rcx +; SSE2-NEXT: addq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill +; SSE2-NEXT: adcq %rbx, %r12 +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbp # 8-byte Reload +; SSE2-NEXT: addq %rsi, %rbp +; SSE2-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r13 # 8-byte Folded Reload +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload +; SSE2-NEXT: addq %r9, %rbx +; SSE2-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r14 # 8-byte Folded Reload +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r9 # 8-byte Reload +; SSE2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r9 # 8-byte Folded Reload +; SSE2-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r15 # 8-byte Folded Reload +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Reload +; SSE2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Folded Reload +; SSE2-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Folded Reload +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rdx # 8-byte Reload +; SSE2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rdx # 8-byte Folded Reload +; SSE2-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Folded Reload +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; SSE2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Folded Reload +; SSE2-NEXT: adcq (%rsp), %r8 # 8-byte Folded Reload +; SSE2-NEXT: addq $1, %rax +; SSE2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: adcq $0, %r8 +; SSE2-NEXT: addq $1, %rdx +; SSE2-NEXT: adcq $0, %r11 +; SSE2-NEXT: addq $1, %rsi +; SSE2-NEXT: adcq $0, %r10 +; SSE2-NEXT: addq $1, %r9 +; SSE2-NEXT: adcq $0, %r15 +; SSE2-NEXT: addq $1, %rbx +; SSE2-NEXT: adcq $0, %r14 +; SSE2-NEXT: addq $1, %rbp +; SSE2-NEXT: adcq $0, %r13 +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; SSE2-NEXT: addq $1, %rax +; SSE2-NEXT: adcq $0, %r12 +; SSE2-NEXT: addq $1, %rdi +; SSE2-NEXT: adcq $0, %rcx +; SSE2-NEXT: shldq $63, %rdi, %rcx +; SSE2-NEXT: shldq $63, %rax, %r12 +; SSE2-NEXT: shldq $63, %rbp, %r13 +; SSE2-NEXT: shldq $63, %rbx, %r14 +; SSE2-NEXT: shldq $63, %r9, %r15 +; SSE2-NEXT: shldq $63, %rsi, %r10 +; SSE2-NEXT: shldq $63, %rdx, %r11 +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; SSE2-NEXT: shldq $63, %rax, %r8 +; SSE2-NEXT: movq %r8, %xmm0 +; SSE2-NEXT: movq %r11, %xmm4 +; SSE2-NEXT: movq %r10, %xmm1 +; SSE2-NEXT: movq %r15, %xmm5 +; SSE2-NEXT: movq %r14, %xmm2 +; SSE2-NEXT: movq %r13, %xmm6 +; SSE2-NEXT: movq %r12, %xmm3 +; SSE2-NEXT: movq %rcx, %xmm7 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm4[0] +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm5[0] +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm6[0] +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm3 = xmm3[0],xmm7[0] +; SSE2-NEXT: addq $8, %rsp +; SSE2-NEXT: .cfi_def_cfa_offset 56 +; SSE2-NEXT: popq %rbx +; SSE2-NEXT: .cfi_def_cfa_offset 48 +; SSE2-NEXT: popq %r12 +; SSE2-NEXT: .cfi_def_cfa_offset 40 +; SSE2-NEXT: popq %r13 +; SSE2-NEXT: .cfi_def_cfa_offset 32 +; SSE2-NEXT: popq %r14 +; SSE2-NEXT: .cfi_def_cfa_offset 24 +; SSE2-NEXT: popq %r15 +; SSE2-NEXT: .cfi_def_cfa_offset 16 +; SSE2-NEXT: popq %rbp +; SSE2-NEXT: .cfi_def_cfa_offset 8 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v8i64: +; SSE4: # %bb.0: +; SSE4-NEXT: pushq %rbp +; SSE4-NEXT: .cfi_def_cfa_offset 16 +; SSE4-NEXT: pushq %r15 +; SSE4-NEXT: .cfi_def_cfa_offset 24 +; SSE4-NEXT: pushq %r14 +; SSE4-NEXT: .cfi_def_cfa_offset 32 +; SSE4-NEXT: pushq %r13 +; SSE4-NEXT: .cfi_def_cfa_offset 40 +; SSE4-NEXT: pushq %r12 +; SSE4-NEXT: .cfi_def_cfa_offset 48 +; SSE4-NEXT: pushq %rbx +; SSE4-NEXT: .cfi_def_cfa_offset 56 +; SSE4-NEXT: subq $16, %rsp +; SSE4-NEXT: .cfi_def_cfa_offset 72 +; SSE4-NEXT: .cfi_offset %rbx, -56 +; SSE4-NEXT: .cfi_offset %r12, -48 +; SSE4-NEXT: .cfi_offset %r13, -40 +; SSE4-NEXT: .cfi_offset %r14, -32 +; SSE4-NEXT: .cfi_offset %r15, -24 +; SSE4-NEXT: .cfi_offset %rbp, -16 +; SSE4-NEXT: pextrq $1, %xmm0, %rax +; SSE4-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: sarq $63, %rax +; SSE4-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: movq %xmm0, %rax +; SSE4-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: movq %rax, %rcx +; SSE4-NEXT: sarq $63, %rcx +; SSE4-NEXT: movq %rcx, (%rsp) # 8-byte Spill +; SSE4-NEXT: pextrq $1, %xmm1, %rax +; SSE4-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: movq %rax, %rcx +; SSE4-NEXT: sarq $63, %rcx +; SSE4-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: movq %xmm1, %rax +; SSE4-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: movq %rax, %rcx +; SSE4-NEXT: sarq $63, %rcx +; SSE4-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: pextrq $1, %xmm2, %rax +; SSE4-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: movq %rax, %rcx +; SSE4-NEXT: sarq $63, %rcx +; SSE4-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: movq %xmm2, %rax +; SSE4-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: movq %rax, %rcx +; SSE4-NEXT: sarq $63, %rcx +; SSE4-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: pextrq $1, %xmm3, %r13 +; SSE4-NEXT: movq %r13, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: sarq $63, %r13 +; SSE4-NEXT: movq %xmm3, %rax +; SSE4-NEXT: movq %rax, %rsi +; SSE4-NEXT: movq %rax, %rcx +; SSE4-NEXT: sarq $63, %rsi +; SSE4-NEXT: pextrq $1, %xmm4, %rax +; SSE4-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: sarq $63, %rax +; SSE4-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: movq %xmm4, %r11 +; SSE4-NEXT: movq %r11, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: sarq $63, %r11 +; SSE4-NEXT: pextrq $1, %xmm5, %r10 +; SSE4-NEXT: movq %r10, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: sarq $63, %r10 +; SSE4-NEXT: movq %xmm5, %rax +; SSE4-NEXT: movq %rax, %r14 +; SSE4-NEXT: sarq $63, %r14 +; SSE4-NEXT: pextrq $1, %xmm6, %rdi +; SSE4-NEXT: movq %rdi, %rbx +; SSE4-NEXT: sarq $63, %rbx +; SSE4-NEXT: movq %xmm6, %rdx +; SSE4-NEXT: movq %rdx, %r12 +; SSE4-NEXT: sarq $63, %r12 +; SSE4-NEXT: pextrq $1, %xmm7, %r15 +; SSE4-NEXT: movq %r15, %r9 +; SSE4-NEXT: sarq $63, %r9 +; SSE4-NEXT: movq %xmm7, %rbp +; SSE4-NEXT: movq %rbp, %r8 +; SSE4-NEXT: sarq $63, %r8 +; SSE4-NEXT: addq %rbp, %rcx +; SSE4-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: adcq %rsi, %r8 +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; SSE4-NEXT: addq %r15, %rcx +; SSE4-NEXT: adcq %r13, %r9 +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbp # 8-byte Reload +; SSE4-NEXT: addq %rdx, %rbp +; SSE4-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r12 # 8-byte Folded Reload +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r13 # 8-byte Reload +; SSE4-NEXT: addq %rdi, %r13 +; SSE4-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Folded Reload +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r15 # 8-byte Reload +; SSE4-NEXT: addq %rax, %r15 +; SSE4-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r14 # 8-byte Folded Reload +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rdi # 8-byte Reload +; SSE4-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rdi # 8-byte Folded Reload +; SSE4-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Folded Reload +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Reload +; SSE4-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Folded Reload +; SSE4-NEXT: adcq (%rsp), %r11 # 8-byte Folded Reload +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rdx # 8-byte Reload +; SSE4-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rdx # 8-byte Folded Reload +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; SSE4-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Folded Reload +; SSE4-NEXT: addq $1, %rdx +; SSE4-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: adcq $0, %rax +; SSE4-NEXT: movq %rax, %rdx +; SSE4-NEXT: addq $1, %rsi +; SSE4-NEXT: adcq $0, %r11 +; SSE4-NEXT: addq $1, %rdi +; SSE4-NEXT: adcq $0, %r10 +; SSE4-NEXT: addq $1, %r15 +; SSE4-NEXT: adcq $0, %r14 +; SSE4-NEXT: addq $1, %r13 +; SSE4-NEXT: adcq $0, %rbx +; SSE4-NEXT: addq $1, %rbp +; SSE4-NEXT: adcq $0, %r12 +; SSE4-NEXT: addq $1, %rcx +; SSE4-NEXT: adcq $0, %r9 +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; SSE4-NEXT: addq $1, %rax +; SSE4-NEXT: adcq $0, %r8 +; SSE4-NEXT: shldq $63, %rax, %r8 +; SSE4-NEXT: shldq $63, %rcx, %r9 +; SSE4-NEXT: shldq $63, %rbp, %r12 +; SSE4-NEXT: shldq $63, %r13, %rbx +; SSE4-NEXT: shldq $63, %r15, %r14 +; SSE4-NEXT: shldq $63, %rdi, %r10 +; SSE4-NEXT: shldq $63, %rsi, %r11 +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; SSE4-NEXT: shldq $63, %rcx, %rdx +; SSE4-NEXT: movq %rdx, %xmm4 +; SSE4-NEXT: movq %r11, %xmm0 +; SSE4-NEXT: movq %r10, %xmm5 +; SSE4-NEXT: movq %r14, %xmm1 +; SSE4-NEXT: movq %rbx, %xmm6 +; SSE4-NEXT: movq %r12, %xmm2 +; SSE4-NEXT: movq %r9, %xmm7 +; SSE4-NEXT: movq %r8, %xmm3 +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm4[0] +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm5[0] +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm6[0] +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm3 = xmm3[0],xmm7[0] +; SSE4-NEXT: addq $16, %rsp +; SSE4-NEXT: .cfi_def_cfa_offset 56 +; SSE4-NEXT: popq %rbx +; SSE4-NEXT: .cfi_def_cfa_offset 48 +; SSE4-NEXT: popq %r12 +; SSE4-NEXT: .cfi_def_cfa_offset 40 +; SSE4-NEXT: popq %r13 +; SSE4-NEXT: .cfi_def_cfa_offset 32 +; SSE4-NEXT: popq %r14 +; SSE4-NEXT: .cfi_def_cfa_offset 24 +; SSE4-NEXT: popq %r15 +; SSE4-NEXT: .cfi_def_cfa_offset 16 +; SSE4-NEXT: popq %rbp +; SSE4-NEXT: .cfi_def_cfa_offset 8 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v8i64: +; AVX1: # %bb.0: +; AVX1-NEXT: pushq %rbp +; AVX1-NEXT: .cfi_def_cfa_offset 16 +; AVX1-NEXT: pushq %r15 +; AVX1-NEXT: .cfi_def_cfa_offset 24 +; AVX1-NEXT: pushq %r14 +; AVX1-NEXT: .cfi_def_cfa_offset 32 +; AVX1-NEXT: pushq %r13 +; AVX1-NEXT: .cfi_def_cfa_offset 40 +; AVX1-NEXT: pushq %r12 +; AVX1-NEXT: .cfi_def_cfa_offset 48 +; AVX1-NEXT: pushq %rbx +; AVX1-NEXT: .cfi_def_cfa_offset 56 +; AVX1-NEXT: pushq %rax +; AVX1-NEXT: .cfi_def_cfa_offset 64 +; AVX1-NEXT: .cfi_offset %rbx, -56 +; AVX1-NEXT: .cfi_offset %r12, -48 +; AVX1-NEXT: .cfi_offset %r13, -40 +; AVX1-NEXT: .cfi_offset %r14, -32 +; AVX1-NEXT: .cfi_offset %r15, -24 +; AVX1-NEXT: .cfi_offset %rbp, -16 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm4 +; AVX1-NEXT: vpextrq $1, %xmm4, %rax +; AVX1-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: sarq $63, %rax +; AVX1-NEXT: movq %rax, (%rsp) # 8-byte Spill +; AVX1-NEXT: vmovq %xmm4, %rax +; AVX1-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: movq %rax, %rcx +; AVX1-NEXT: sarq $63, %rcx +; AVX1-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: vpextrq $1, %xmm0, %rax +; AVX1-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: movq %rax, %rcx +; AVX1-NEXT: sarq $63, %rcx +; AVX1-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: vmovq %xmm0, %rax +; AVX1-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: movq %rax, %rcx +; AVX1-NEXT: sarq $63, %rcx +; AVX1-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm0 +; AVX1-NEXT: vpextrq $1, %xmm0, %rax +; AVX1-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: movq %rax, %rcx +; AVX1-NEXT: sarq $63, %rcx +; AVX1-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: vmovq %xmm0, %rax +; AVX1-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: movq %rax, %rcx +; AVX1-NEXT: sarq $63, %rcx +; AVX1-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: vpextrq $1, %xmm1, %rbx +; AVX1-NEXT: movq %rbx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: sarq $63, %rbx +; AVX1-NEXT: vmovq %xmm1, %r8 +; AVX1-NEXT: movq %r8, %rbp +; AVX1-NEXT: sarq $63, %rbp +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm0 +; AVX1-NEXT: vpextrq $1, %xmm0, %r9 +; AVX1-NEXT: movq %r9, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: sarq $63, %r9 +; AVX1-NEXT: vmovq %xmm0, %r10 +; AVX1-NEXT: movq %r10, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: sarq $63, %r10 +; AVX1-NEXT: vpextrq $1, %xmm2, %r11 +; AVX1-NEXT: movq %r11, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: sarq $63, %r11 +; AVX1-NEXT: vmovq %xmm2, %r15 +; AVX1-NEXT: movq %r15, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: sarq $63, %r15 +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm0 +; AVX1-NEXT: vpextrq $1, %xmm0, %rdi +; AVX1-NEXT: movq %rdi, %r14 +; AVX1-NEXT: sarq $63, %r14 +; AVX1-NEXT: vmovq %xmm0, %rsi +; AVX1-NEXT: movq %rsi, %r12 +; AVX1-NEXT: sarq $63, %r12 +; AVX1-NEXT: vpextrq $1, %xmm3, %r13 +; AVX1-NEXT: movq %r13, %rdx +; AVX1-NEXT: sarq $63, %rdx +; AVX1-NEXT: vmovq %xmm3, %rax +; AVX1-NEXT: movq %rax, %rcx +; AVX1-NEXT: sarq $63, %rcx +; AVX1-NEXT: addq %rax, %r8 +; AVX1-NEXT: adcq %rbp, %rcx +; AVX1-NEXT: addq %r13, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill +; AVX1-NEXT: adcq %rbx, %rdx +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbp # 8-byte Reload +; AVX1-NEXT: addq %rsi, %rbp +; AVX1-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r12 # 8-byte Folded Reload +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r13 # 8-byte Reload +; AVX1-NEXT: addq %rdi, %r13 +; AVX1-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r14 # 8-byte Folded Reload +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload +; AVX1-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Folded Reload +; AVX1-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r15 # 8-byte Folded Reload +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rdi # 8-byte Reload +; AVX1-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rdi # 8-byte Folded Reload +; AVX1-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Folded Reload +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Reload +; AVX1-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Folded Reload +; AVX1-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Folded Reload +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; AVX1-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Folded Reload +; AVX1-NEXT: adcq (%rsp), %r9 # 8-byte Folded Reload +; AVX1-NEXT: addq $1, %rax +; AVX1-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: adcq $0, %r9 +; AVX1-NEXT: addq $1, %rsi +; AVX1-NEXT: adcq $0, %r10 +; AVX1-NEXT: addq $1, %rdi +; AVX1-NEXT: adcq $0, %r11 +; AVX1-NEXT: addq $1, %rbx +; AVX1-NEXT: adcq $0, %r15 +; AVX1-NEXT: addq $1, %r13 +; AVX1-NEXT: adcq $0, %r14 +; AVX1-NEXT: addq $1, %rbp +; AVX1-NEXT: adcq $0, %r12 +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; AVX1-NEXT: addq $1, %rax +; AVX1-NEXT: adcq $0, %rdx +; AVX1-NEXT: addq $1, %r8 +; AVX1-NEXT: adcq $0, %rcx +; AVX1-NEXT: shldq $63, %r8, %rcx +; AVX1-NEXT: shldq $63, %rax, %rdx +; AVX1-NEXT: shldq $63, %rbp, %r12 +; AVX1-NEXT: shldq $63, %r13, %r14 +; AVX1-NEXT: shldq $63, %rbx, %r15 +; AVX1-NEXT: shldq $63, %rdi, %r11 +; AVX1-NEXT: shldq $63, %rsi, %r10 +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; AVX1-NEXT: shldq $63, %rax, %r9 +; AVX1-NEXT: vmovq %r9, %xmm0 +; AVX1-NEXT: vmovq %r10, %xmm1 +; AVX1-NEXT: vmovq %r11, %xmm2 +; AVX1-NEXT: vmovq %r15, %xmm3 +; AVX1-NEXT: vmovq %r14, %xmm4 +; AVX1-NEXT: vmovq %r12, %xmm5 +; AVX1-NEXT: vmovq %rdx, %xmm6 +; AVX1-NEXT: vmovq %rcx, %xmm7 +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm3[0],xmm2[0] +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm5[0],xmm4[0] +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm7[0],xmm6[0] +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: addq $8, %rsp +; AVX1-NEXT: .cfi_def_cfa_offset 56 +; AVX1-NEXT: popq %rbx +; AVX1-NEXT: .cfi_def_cfa_offset 48 +; AVX1-NEXT: popq %r12 +; AVX1-NEXT: .cfi_def_cfa_offset 40 +; AVX1-NEXT: popq %r13 +; AVX1-NEXT: .cfi_def_cfa_offset 32 +; AVX1-NEXT: popq %r14 +; AVX1-NEXT: .cfi_def_cfa_offset 24 +; AVX1-NEXT: popq %r15 +; AVX1-NEXT: .cfi_def_cfa_offset 16 +; AVX1-NEXT: popq %rbp +; AVX1-NEXT: .cfi_def_cfa_offset 8 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v8i64: +; AVX2: # %bb.0: +; AVX2-NEXT: pushq %rbp +; AVX2-NEXT: .cfi_def_cfa_offset 16 +; AVX2-NEXT: pushq %r15 +; AVX2-NEXT: .cfi_def_cfa_offset 24 +; AVX2-NEXT: pushq %r14 +; AVX2-NEXT: .cfi_def_cfa_offset 32 +; AVX2-NEXT: pushq %r13 +; AVX2-NEXT: .cfi_def_cfa_offset 40 +; AVX2-NEXT: pushq %r12 +; AVX2-NEXT: .cfi_def_cfa_offset 48 +; AVX2-NEXT: pushq %rbx +; AVX2-NEXT: .cfi_def_cfa_offset 56 +; AVX2-NEXT: pushq %rax +; AVX2-NEXT: .cfi_def_cfa_offset 64 +; AVX2-NEXT: .cfi_offset %rbx, -56 +; AVX2-NEXT: .cfi_offset %r12, -48 +; AVX2-NEXT: .cfi_offset %r13, -40 +; AVX2-NEXT: .cfi_offset %r14, -32 +; AVX2-NEXT: .cfi_offset %r15, -24 +; AVX2-NEXT: .cfi_offset %rbp, -16 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm4 +; AVX2-NEXT: vpextrq $1, %xmm4, %rax +; AVX2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: sarq $63, %rax +; AVX2-NEXT: movq %rax, (%rsp) # 8-byte Spill +; AVX2-NEXT: vmovq %xmm4, %rax +; AVX2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: movq %rax, %rcx +; AVX2-NEXT: sarq $63, %rcx +; AVX2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: vpextrq $1, %xmm0, %rax +; AVX2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: movq %rax, %rcx +; AVX2-NEXT: sarq $63, %rcx +; AVX2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: vmovq %xmm0, %rax +; AVX2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: movq %rax, %rcx +; AVX2-NEXT: sarq $63, %rcx +; AVX2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm0 +; AVX2-NEXT: vpextrq $1, %xmm0, %rax +; AVX2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: movq %rax, %rcx +; AVX2-NEXT: sarq $63, %rcx +; AVX2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: vmovq %xmm0, %rax +; AVX2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: movq %rax, %rcx +; AVX2-NEXT: sarq $63, %rcx +; AVX2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: vpextrq $1, %xmm1, %rbx +; AVX2-NEXT: movq %rbx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: sarq $63, %rbx +; AVX2-NEXT: vmovq %xmm1, %r8 +; AVX2-NEXT: movq %r8, %rbp +; AVX2-NEXT: sarq $63, %rbp +; AVX2-NEXT: vextracti128 $1, %ymm2, %xmm0 +; AVX2-NEXT: vpextrq $1, %xmm0, %r9 +; AVX2-NEXT: movq %r9, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: sarq $63, %r9 +; AVX2-NEXT: vmovq %xmm0, %r10 +; AVX2-NEXT: movq %r10, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: sarq $63, %r10 +; AVX2-NEXT: vpextrq $1, %xmm2, %r11 +; AVX2-NEXT: movq %r11, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: sarq $63, %r11 +; AVX2-NEXT: vmovq %xmm2, %r15 +; AVX2-NEXT: movq %r15, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: sarq $63, %r15 +; AVX2-NEXT: vextracti128 $1, %ymm3, %xmm0 +; AVX2-NEXT: vpextrq $1, %xmm0, %rdi +; AVX2-NEXT: movq %rdi, %r14 +; AVX2-NEXT: sarq $63, %r14 +; AVX2-NEXT: vmovq %xmm0, %rsi +; AVX2-NEXT: movq %rsi, %r12 +; AVX2-NEXT: sarq $63, %r12 +; AVX2-NEXT: vpextrq $1, %xmm3, %r13 +; AVX2-NEXT: movq %r13, %rdx +; AVX2-NEXT: sarq $63, %rdx +; AVX2-NEXT: vmovq %xmm3, %rax +; AVX2-NEXT: movq %rax, %rcx +; AVX2-NEXT: sarq $63, %rcx +; AVX2-NEXT: addq %rax, %r8 +; AVX2-NEXT: adcq %rbp, %rcx +; AVX2-NEXT: addq %r13, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill +; AVX2-NEXT: adcq %rbx, %rdx +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbp # 8-byte Reload +; AVX2-NEXT: addq %rsi, %rbp +; AVX2-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r12 # 8-byte Folded Reload +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r13 # 8-byte Reload +; AVX2-NEXT: addq %rdi, %r13 +; AVX2-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r14 # 8-byte Folded Reload +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload +; AVX2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Folded Reload +; AVX2-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r15 # 8-byte Folded Reload +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rdi # 8-byte Reload +; AVX2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rdi # 8-byte Folded Reload +; AVX2-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Folded Reload +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Reload +; AVX2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Folded Reload +; AVX2-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Folded Reload +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; AVX2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Folded Reload +; AVX2-NEXT: adcq (%rsp), %r9 # 8-byte Folded Reload +; AVX2-NEXT: addq $1, %rax +; AVX2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: adcq $0, %r9 +; AVX2-NEXT: addq $1, %rsi +; AVX2-NEXT: adcq $0, %r10 +; AVX2-NEXT: addq $1, %rdi +; AVX2-NEXT: adcq $0, %r11 +; AVX2-NEXT: addq $1, %rbx +; AVX2-NEXT: adcq $0, %r15 +; AVX2-NEXT: addq $1, %r13 +; AVX2-NEXT: adcq $0, %r14 +; AVX2-NEXT: addq $1, %rbp +; AVX2-NEXT: adcq $0, %r12 +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; AVX2-NEXT: addq $1, %rax +; AVX2-NEXT: adcq $0, %rdx +; AVX2-NEXT: addq $1, %r8 +; AVX2-NEXT: adcq $0, %rcx +; AVX2-NEXT: shldq $63, %r8, %rcx +; AVX2-NEXT: shldq $63, %rax, %rdx +; AVX2-NEXT: shldq $63, %rbp, %r12 +; AVX2-NEXT: shldq $63, %r13, %r14 +; AVX2-NEXT: shldq $63, %rbx, %r15 +; AVX2-NEXT: shldq $63, %rdi, %r11 +; AVX2-NEXT: shldq $63, %rsi, %r10 +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; AVX2-NEXT: shldq $63, %rax, %r9 +; AVX2-NEXT: vmovq %r9, %xmm0 +; AVX2-NEXT: vmovq %r10, %xmm1 +; AVX2-NEXT: vmovq %r11, %xmm2 +; AVX2-NEXT: vmovq %r15, %xmm3 +; AVX2-NEXT: vmovq %r14, %xmm4 +; AVX2-NEXT: vmovq %r12, %xmm5 +; AVX2-NEXT: vmovq %rdx, %xmm6 +; AVX2-NEXT: vmovq %rcx, %xmm7 +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm3[0],xmm2[0] +; AVX2-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0 +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm5[0],xmm4[0] +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm7[0],xmm6[0] +; AVX2-NEXT: vinserti128 $1, %xmm1, %ymm2, %ymm1 +; AVX2-NEXT: addq $8, %rsp +; AVX2-NEXT: .cfi_def_cfa_offset 56 +; AVX2-NEXT: popq %rbx +; AVX2-NEXT: .cfi_def_cfa_offset 48 +; AVX2-NEXT: popq %r12 +; AVX2-NEXT: .cfi_def_cfa_offset 40 +; AVX2-NEXT: popq %r13 +; AVX2-NEXT: .cfi_def_cfa_offset 32 +; AVX2-NEXT: popq %r14 +; AVX2-NEXT: .cfi_def_cfa_offset 24 +; AVX2-NEXT: popq %r15 +; AVX2-NEXT: .cfi_def_cfa_offset 16 +; AVX2-NEXT: popq %rbp +; AVX2-NEXT: .cfi_def_cfa_offset 8 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v8i64: +; AVX512: # %bb.0: +; AVX512-NEXT: pushq %rbp +; AVX512-NEXT: .cfi_def_cfa_offset 16 +; AVX512-NEXT: pushq %r15 +; AVX512-NEXT: .cfi_def_cfa_offset 24 +; AVX512-NEXT: pushq %r14 +; AVX512-NEXT: .cfi_def_cfa_offset 32 +; AVX512-NEXT: pushq %r13 +; AVX512-NEXT: .cfi_def_cfa_offset 40 +; AVX512-NEXT: pushq %r12 +; AVX512-NEXT: .cfi_def_cfa_offset 48 +; AVX512-NEXT: pushq %rbx +; AVX512-NEXT: .cfi_def_cfa_offset 56 +; AVX512-NEXT: pushq %rax +; AVX512-NEXT: .cfi_def_cfa_offset 64 +; AVX512-NEXT: .cfi_offset %rbx, -56 +; AVX512-NEXT: .cfi_offset %r12, -48 +; AVX512-NEXT: .cfi_offset %r13, -40 +; AVX512-NEXT: .cfi_offset %r14, -32 +; AVX512-NEXT: .cfi_offset %r15, -24 +; AVX512-NEXT: .cfi_offset %rbp, -16 +; AVX512-NEXT: vextracti64x4 $1, %zmm0, %ymm2 +; AVX512-NEXT: vextracti128 $1, %ymm2, %xmm3 +; AVX512-NEXT: vpextrq $1, %xmm3, %rax +; AVX512-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: sarq $63, %rax +; AVX512-NEXT: movq %rax, (%rsp) # 8-byte Spill +; AVX512-NEXT: vmovq %xmm3, %rax +; AVX512-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: movq %rax, %rcx +; AVX512-NEXT: sarq $63, %rcx +; AVX512-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: vpextrq $1, %xmm2, %rax +; AVX512-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: movq %rax, %rcx +; AVX512-NEXT: sarq $63, %rcx +; AVX512-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: vmovq %xmm2, %rax +; AVX512-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: movq %rax, %rcx +; AVX512-NEXT: sarq $63, %rcx +; AVX512-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: vextracti128 $1, %ymm0, %xmm2 +; AVX512-NEXT: vpextrq $1, %xmm2, %rax +; AVX512-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: movq %rax, %rcx +; AVX512-NEXT: sarq $63, %rcx +; AVX512-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: vmovq %xmm2, %rax +; AVX512-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: movq %rax, %rcx +; AVX512-NEXT: sarq $63, %rcx +; AVX512-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: vpextrq $1, %xmm0, %rbx +; AVX512-NEXT: movq %rbx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: sarq $63, %rbx +; AVX512-NEXT: vmovq %xmm0, %r8 +; AVX512-NEXT: movq %r8, %r13 +; AVX512-NEXT: sarq $63, %r13 +; AVX512-NEXT: vextracti64x4 $1, %zmm1, %ymm0 +; AVX512-NEXT: vextracti128 $1, %ymm0, %xmm2 +; AVX512-NEXT: vpextrq $1, %xmm2, %r9 +; AVX512-NEXT: movq %r9, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: sarq $63, %r9 +; AVX512-NEXT: vmovq %xmm2, %r10 +; AVX512-NEXT: movq %r10, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: sarq $63, %r10 +; AVX512-NEXT: vpextrq $1, %xmm0, %r11 +; AVX512-NEXT: movq %r11, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: sarq $63, %r11 +; AVX512-NEXT: vmovq %xmm0, %r14 +; AVX512-NEXT: movq %r14, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: sarq $63, %r14 +; AVX512-NEXT: vextracti128 $1, %ymm1, %xmm0 +; AVX512-NEXT: vpextrq $1, %xmm0, %rdi +; AVX512-NEXT: movq %rdi, %r15 +; AVX512-NEXT: sarq $63, %r15 +; AVX512-NEXT: vmovq %xmm0, %rsi +; AVX512-NEXT: movq %rsi, %r12 +; AVX512-NEXT: sarq $63, %r12 +; AVX512-NEXT: vpextrq $1, %xmm1, %rbp +; AVX512-NEXT: movq %rbp, %rdx +; AVX512-NEXT: sarq $63, %rdx +; AVX512-NEXT: vmovq %xmm1, %rax +; AVX512-NEXT: movq %rax, %rcx +; AVX512-NEXT: sarq $63, %rcx +; AVX512-NEXT: addq %rax, %r8 +; AVX512-NEXT: adcq %r13, %rcx +; AVX512-NEXT: addq %rbp, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill +; AVX512-NEXT: adcq %rbx, %rdx +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbp # 8-byte Reload +; AVX512-NEXT: addq %rsi, %rbp +; AVX512-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r12 # 8-byte Folded Reload +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r13 # 8-byte Reload +; AVX512-NEXT: addq %rdi, %r13 +; AVX512-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r15 # 8-byte Folded Reload +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload +; AVX512-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Folded Reload +; AVX512-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r14 # 8-byte Folded Reload +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rdi # 8-byte Reload +; AVX512-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rdi # 8-byte Folded Reload +; AVX512-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Folded Reload +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Reload +; AVX512-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Folded Reload +; AVX512-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Folded Reload +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; AVX512-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Folded Reload +; AVX512-NEXT: adcq (%rsp), %r9 # 8-byte Folded Reload +; AVX512-NEXT: addq $1, %rax +; AVX512-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: adcq $0, %r9 +; AVX512-NEXT: addq $1, %rsi +; AVX512-NEXT: adcq $0, %r10 +; AVX512-NEXT: addq $1, %rdi +; AVX512-NEXT: adcq $0, %r11 +; AVX512-NEXT: addq $1, %rbx +; AVX512-NEXT: adcq $0, %r14 +; AVX512-NEXT: addq $1, %r13 +; AVX512-NEXT: adcq $0, %r15 +; AVX512-NEXT: addq $1, %rbp +; AVX512-NEXT: adcq $0, %r12 +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; AVX512-NEXT: addq $1, %rax +; AVX512-NEXT: adcq $0, %rdx +; AVX512-NEXT: addq $1, %r8 +; AVX512-NEXT: adcq $0, %rcx +; AVX512-NEXT: shldq $63, %r8, %rcx +; AVX512-NEXT: shldq $63, %rax, %rdx +; AVX512-NEXT: shldq $63, %rbp, %r12 +; AVX512-NEXT: shldq $63, %r13, %r15 +; AVX512-NEXT: shldq $63, %rbx, %r14 +; AVX512-NEXT: shldq $63, %rdi, %r11 +; AVX512-NEXT: shldq $63, %rsi, %r10 +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; AVX512-NEXT: shldq $63, %rax, %r9 +; AVX512-NEXT: vmovq %r9, %xmm0 +; AVX512-NEXT: vmovq %r10, %xmm1 +; AVX512-NEXT: vmovq %r11, %xmm2 +; AVX512-NEXT: vmovq %r14, %xmm3 +; AVX512-NEXT: vmovq %r15, %xmm4 +; AVX512-NEXT: vmovq %r12, %xmm5 +; AVX512-NEXT: vmovq %rdx, %xmm6 +; AVX512-NEXT: vmovq %rcx, %xmm7 +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm3[0],xmm2[0] +; AVX512-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0 +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm5[0],xmm4[0] +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm7[0],xmm6[0] +; AVX512-NEXT: vinserti128 $1, %xmm1, %ymm2, %ymm1 +; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-NEXT: addq $8, %rsp +; AVX512-NEXT: .cfi_def_cfa_offset 56 +; AVX512-NEXT: popq %rbx +; AVX512-NEXT: .cfi_def_cfa_offset 48 +; AVX512-NEXT: popq %r12 +; AVX512-NEXT: .cfi_def_cfa_offset 40 +; AVX512-NEXT: popq %r13 +; AVX512-NEXT: .cfi_def_cfa_offset 32 +; AVX512-NEXT: popq %r14 +; AVX512-NEXT: .cfi_def_cfa_offset 24 +; AVX512-NEXT: popq %r15 +; AVX512-NEXT: .cfi_def_cfa_offset 16 +; AVX512-NEXT: popq %rbp +; AVX512-NEXT: .cfi_def_cfa_offset 8 +; AVX512-NEXT: retq + %x0 = sext <8 x i64> %a0 to <8 x i128> + %x1 = sext <8 x i64> %a1 to <8 x i128> + %sum = add <8 x i128> %x0, %x1 + %inc = add <8 x i128> %sum, <i128 1, i128 1, i128 1, i128 1, i128 1, i128 1, i128 1, i128 1> + %shift = ashr <8 x i128> %inc, <i128 1, i128 1, i128 1, i128 1, i128 1, i128 1, i128 1, i128 1> + %res = trunc <8 x i128> %shift to <8 x i64> + ret <8 x i64> %res +} + diff --git a/llvm/test/CodeGen/X86/avgceilu.ll b/llvm/test/CodeGen/X86/avgceilu.ll new file mode 100644 index 0000000000000000000000000000000000000000..dee1a5a720f90fc1bedb927a54b7dac2d7f8fbe0 --- /dev/null +++ b/llvm/test/CodeGen/X86/avgceilu.ll @@ -0,0 +1,2187 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-- -mattr=+sse2 | FileCheck %s --check-prefixes=SSE,SSE2 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+sse4.1 | FileCheck %s --check-prefixes=SSE,SSE4 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx | FileCheck %s --check-prefixes=AVX,AVX1 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx2 | FileCheck %s --check-prefixes=AVX,AVX2 +; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64-v4 | FileCheck %s --check-prefixes=AVX,AVX512 + +; +; 128-bit vectors +; + +define <16 x i8> @test_fixed_v16i8(<16 x i8> %a0, <16 x i8> %a1) { +; SSE-LABEL: test_fixed_v16i8: +; SSE: # %bb.0: +; SSE-NEXT: pavgb %xmm1, %xmm0 +; SSE-NEXT: retq +; +; AVX-LABEL: test_fixed_v16i8: +; AVX: # %bb.0: +; AVX-NEXT: vpavgb %xmm1, %xmm0, %xmm0 +; AVX-NEXT: retq + %or = or <16 x i8> %a0, %a1 + %xor = xor <16 x i8> %a0, %a1 + %shift = lshr <16 x i8> %xor, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> + %res = sub <16 x i8> %or, %shift + ret <16 x i8> %res +} + +define <16 x i8> @test_ext_v16i8(<16 x i8> %a0, <16 x i8> %a1) { +; SSE-LABEL: test_ext_v16i8: +; SSE: # %bb.0: +; SSE-NEXT: pavgb %xmm1, %xmm0 +; SSE-NEXT: retq +; +; AVX-LABEL: test_ext_v16i8: +; AVX: # %bb.0: +; AVX-NEXT: vpavgb %xmm1, %xmm0, %xmm0 +; AVX-NEXT: retq + %x0 = zext <16 x i8> %a0 to <16 x i16> + %x1 = zext <16 x i8> %a1 to <16 x i16> + %sum = add <16 x i16> %x0, %x1 + %inc = add <16 x i16> %sum, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %shift = lshr <16 x i16> %inc, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = trunc <16 x i16> %shift to <16 x i8> + ret <16 x i8> %res +} + +define <8 x i16> @test_fixed_v8i16(<8 x i16> %a0, <8 x i16> %a1) { +; SSE-LABEL: test_fixed_v8i16: +; SSE: # %bb.0: +; SSE-NEXT: pavgw %xmm1, %xmm0 +; SSE-NEXT: retq +; +; AVX-LABEL: test_fixed_v8i16: +; AVX: # %bb.0: +; AVX-NEXT: vpavgw %xmm1, %xmm0, %xmm0 +; AVX-NEXT: retq + %or = or <8 x i16> %a0, %a1 + %xor = xor <8 x i16> %a1, %a0 + %shift = lshr <8 x i16> %xor, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = sub <8 x i16> %or, %shift + ret <8 x i16> %res +} + +define <8 x i16> @test_ext_v8i16(<8 x i16> %a0, <8 x i16> %a1) { +; SSE-LABEL: test_ext_v8i16: +; SSE: # %bb.0: +; SSE-NEXT: pavgw %xmm1, %xmm0 +; SSE-NEXT: retq +; +; AVX-LABEL: test_ext_v8i16: +; AVX: # %bb.0: +; AVX-NEXT: vpavgw %xmm1, %xmm0, %xmm0 +; AVX-NEXT: retq + %x0 = zext <8 x i16> %a0 to <8 x i32> + %x1 = zext <8 x i16> %a1 to <8 x i32> + %sum = add <8 x i32> %x0, %x1 + %inc = add <8 x i32> %sum, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %shift = lshr <8 x i32> %inc, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = trunc <8 x i32> %shift to <8 x i16> + ret <8 x i16> %res +} + +define <4 x i32> @test_fixed_v4i32(<4 x i32> %a0, <4 x i32> %a1) { +; SSE-LABEL: test_fixed_v4i32: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm0, %xmm2 +; SSE-NEXT: por %xmm1, %xmm2 +; SSE-NEXT: pxor %xmm0, %xmm1 +; SSE-NEXT: psrld $1, %xmm1 +; SSE-NEXT: psubd %xmm1, %xmm2 +; SSE-NEXT: movdqa %xmm2, %xmm0 +; SSE-NEXT: retq +; +; AVX-LABEL: test_fixed_v4i32: +; AVX: # %bb.0: +; AVX-NEXT: vpor %xmm1, %xmm0, %xmm2 +; AVX-NEXT: vpxor %xmm0, %xmm1, %xmm0 +; AVX-NEXT: vpsrld $1, %xmm0, %xmm0 +; AVX-NEXT: vpsubd %xmm0, %xmm2, %xmm0 +; AVX-NEXT: retq + %or = or <4 x i32> %a0, %a1 + %xor = xor <4 x i32> %a1, %a0 + %shift = lshr <4 x i32> %xor, <i32 1, i32 1, i32 1, i32 1> + %res = sub <4 x i32> %or, %shift + ret <4 x i32> %res +} + +define <4 x i32> @test_ext_v4i32(<4 x i32> %a0, <4 x i32> %a1) { +; SSE2-LABEL: test_ext_v4i32: +; SSE2: # %bb.0: +; SSE2-NEXT: pxor %xmm3, %xmm3 +; SSE2-NEXT: movdqa %xmm0, %xmm4 +; SSE2-NEXT: punpckldq {{.*#+}} xmm4 = xmm4[0],xmm3[0],xmm4[1],xmm3[1] +; SSE2-NEXT: punpckhdq {{.*#+}} xmm0 = xmm0[2],xmm3[2],xmm0[3],xmm3[3] +; SSE2-NEXT: movdqa %xmm1, %xmm2 +; SSE2-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm3[0],xmm2[1],xmm3[1] +; SSE2-NEXT: paddq %xmm4, %xmm2 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm1 = xmm1[2],xmm3[2],xmm1[3],xmm3[3] +; SSE2-NEXT: paddq %xmm0, %xmm1 +; SSE2-NEXT: pcmpeqd %xmm0, %xmm0 +; SSE2-NEXT: psubq %xmm0, %xmm2 +; SSE2-NEXT: psubq %xmm0, %xmm1 +; SSE2-NEXT: psrlq $1, %xmm1 +; SSE2-NEXT: psrlq $1, %xmm2 +; SSE2-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,2],xmm1[0,2] +; SSE2-NEXT: movaps %xmm2, %xmm0 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v4i32: +; SSE4: # %bb.0: +; SSE4-NEXT: pxor %xmm3, %xmm3 +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm4 = xmm0[0],zero,xmm0[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm0 = xmm0[2],xmm3[2],xmm0[3],xmm3[3] +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm2 = xmm1[0],zero,xmm1[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm1 = xmm1[2],xmm3[2],xmm1[3],xmm3[3] +; SSE4-NEXT: paddq %xmm0, %xmm1 +; SSE4-NEXT: paddq %xmm4, %xmm2 +; SSE4-NEXT: pcmpeqd %xmm0, %xmm0 +; SSE4-NEXT: psubq %xmm0, %xmm1 +; SSE4-NEXT: psubq %xmm0, %xmm2 +; SSE4-NEXT: psrlq $1, %xmm1 +; SSE4-NEXT: psrlq $1, %xmm2 +; SSE4-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,2],xmm1[0,2] +; SSE4-NEXT: movaps %xmm2, %xmm0 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v4i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vpxor %xmm2, %xmm2, %xmm2 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm3 = xmm0[2],xmm2[2],xmm0[3],xmm2[3] +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm2 = xmm1[2],xmm2[2],xmm1[3],xmm2[3] +; AVX1-NEXT: vpaddq %xmm2, %xmm3, %xmm2 +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero +; AVX1-NEXT: vpaddq %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1 +; AVX1-NEXT: vpsubq %xmm1, %xmm2, %xmm2 +; AVX1-NEXT: vpsubq %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlq $1, %xmm2, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vshufps {{.*#+}} xmm0 = xmm0[0,2],xmm1[0,2] +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v4i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero +; AVX2-NEXT: vpaddq %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpcmpeqd %ymm1, %ymm1, %ymm1 +; AVX2-NEXT: vpsubq %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1 +; AVX2-NEXT: vshufps {{.*#+}} xmm0 = xmm0[0,2],xmm1[0,2] +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v4i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovzxdq {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; AVX512-NEXT: vpmovzxdq {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero +; AVX512-NEXT: vpaddq %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpcmpeqd %ymm1, %ymm1, %ymm1 +; AVX512-NEXT: vpsubq %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX512-NEXT: vpmovqd %ymm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + %x0 = zext <4 x i32> %a0 to <4 x i64> + %x1 = zext <4 x i32> %a1 to <4 x i64> + %sum = add <4 x i64> %x0, %x1 + %inc = add <4 x i64> %sum, <i64 1, i64 1, i64 1, i64 1> + %shift = lshr <4 x i64> %inc, <i64 1, i64 1, i64 1, i64 1> + %res = trunc <4 x i64> %shift to <4 x i32> + ret <4 x i32> %res +} + +define <2 x i64> @test_fixed_v2i64(<2 x i64> %a0, <2 x i64> %a1) { +; SSE-LABEL: test_fixed_v2i64: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm0, %xmm2 +; SSE-NEXT: por %xmm1, %xmm2 +; SSE-NEXT: pxor %xmm0, %xmm1 +; SSE-NEXT: psrlq $1, %xmm1 +; SSE-NEXT: psubq %xmm1, %xmm2 +; SSE-NEXT: movdqa %xmm2, %xmm0 +; SSE-NEXT: retq +; +; AVX-LABEL: test_fixed_v2i64: +; AVX: # %bb.0: +; AVX-NEXT: vpor %xmm1, %xmm0, %xmm2 +; AVX-NEXT: vpxor %xmm0, %xmm1, %xmm0 +; AVX-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX-NEXT: vpsubq %xmm0, %xmm2, %xmm0 +; AVX-NEXT: retq + %or = or <2 x i64> %a0, %a1 + %xor = xor <2 x i64> %a1, %a0 + %shift = lshr <2 x i64> %xor, <i64 1, i64 1> + %res = sub <2 x i64> %or, %shift + ret <2 x i64> %res +} + +define <2 x i64> @test_ext_v2i64(<2 x i64> %a0, <2 x i64> %a1) { +; SSE2-LABEL: test_ext_v2i64: +; SSE2: # %bb.0: +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm0[2,3,2,3] +; SSE2-NEXT: movq %xmm2, %rax +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] +; SSE2-NEXT: movq %xmm2, %rcx +; SSE2-NEXT: movb $1, %dl +; SSE2-NEXT: movb $1, %sil +; SSE2-NEXT: addb $-1, %sil +; SSE2-NEXT: leaq 1(%rax,%rcx), %rsi +; SSE2-NEXT: adcq %rcx, %rax +; SSE2-NEXT: setb %al +; SSE2-NEXT: addb $-1, %dl +; SSE2-NEXT: movq %xmm0, %rcx +; SSE2-NEXT: movq %xmm1, %rdx +; SSE2-NEXT: leaq 1(%rcx,%rdx), %rdi +; SSE2-NEXT: adcq %rdx, %rcx +; SSE2-NEXT: setb %cl +; SSE2-NEXT: movzbl %cl, %ecx +; SSE2-NEXT: movzbl %al, %eax +; SSE2-NEXT: shrdq $1, %rcx, %rdi +; SSE2-NEXT: shrdq $1, %rax, %rsi +; SSE2-NEXT: movq %rdi, %xmm0 +; SSE2-NEXT: movq %rsi, %xmm1 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v2i64: +; SSE4: # %bb.0: +; SSE4-NEXT: movq %xmm0, %rax +; SSE4-NEXT: movq %xmm1, %rcx +; SSE4-NEXT: movb $1, %dl +; SSE4-NEXT: movb $1, %sil +; SSE4-NEXT: addb $-1, %sil +; SSE4-NEXT: leaq 1(%rax,%rcx), %rsi +; SSE4-NEXT: adcq %rcx, %rax +; SSE4-NEXT: setb %al +; SSE4-NEXT: addb $-1, %dl +; SSE4-NEXT: pextrq $1, %xmm0, %rcx +; SSE4-NEXT: pextrq $1, %xmm1, %rdx +; SSE4-NEXT: leaq 1(%rcx,%rdx), %rdi +; SSE4-NEXT: adcq %rdx, %rcx +; SSE4-NEXT: setb %cl +; SSE4-NEXT: movzbl %cl, %ecx +; SSE4-NEXT: movzbl %al, %eax +; SSE4-NEXT: shrdq $1, %rcx, %rdi +; SSE4-NEXT: shrdq $1, %rax, %rsi +; SSE4-NEXT: movq %rdi, %xmm1 +; SSE4-NEXT: movq %rsi, %xmm0 +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE4-NEXT: retq +; +; AVX-LABEL: test_ext_v2i64: +; AVX: # %bb.0: +; AVX-NEXT: vmovq %xmm0, %rax +; AVX-NEXT: vmovq %xmm1, %rcx +; AVX-NEXT: movb $1, %dl +; AVX-NEXT: movb $1, %sil +; AVX-NEXT: addb $-1, %sil +; AVX-NEXT: leaq 1(%rax,%rcx), %rsi +; AVX-NEXT: adcq %rcx, %rax +; AVX-NEXT: setb %al +; AVX-NEXT: addb $-1, %dl +; AVX-NEXT: vpextrq $1, %xmm0, %rcx +; AVX-NEXT: vpextrq $1, %xmm1, %rdx +; AVX-NEXT: leaq 1(%rcx,%rdx), %rdi +; AVX-NEXT: adcq %rdx, %rcx +; AVX-NEXT: setb %cl +; AVX-NEXT: movzbl %cl, %ecx +; AVX-NEXT: movzbl %al, %eax +; AVX-NEXT: shrdq $1, %rcx, %rdi +; AVX-NEXT: shrdq $1, %rax, %rsi +; AVX-NEXT: vmovq %rdi, %xmm0 +; AVX-NEXT: vmovq %rsi, %xmm1 +; AVX-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX-NEXT: retq + %x0 = zext <2 x i64> %a0 to <2 x i128> + %x1 = zext <2 x i64> %a1 to <2 x i128> + %sum = add <2 x i128> %x0, %x1 + %inc = add <2 x i128> %sum, <i128 1, i128 1> + %shift = lshr <2 x i128> %inc, <i128 1, i128 1> + %res = trunc <2 x i128> %shift to <2 x i64> + ret <2 x i64> %res +} + +; +; 256-bit vectors +; + +define <32 x i8> @test_fixed_v32i8(<32 x i8> %a0, <32 x i8> %a1) { +; SSE-LABEL: test_fixed_v32i8: +; SSE: # %bb.0: +; SSE-NEXT: pavgb %xmm2, %xmm0 +; SSE-NEXT: pavgb %xmm3, %xmm1 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v32i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm3 +; AVX1-NEXT: vpavgb %xmm2, %xmm3, %xmm2 +; AVX1-NEXT: vpavgb %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v32i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vpavgb %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v32i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpavgb %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: retq + %or = or <32 x i8> %a0, %a1 + %xor = xor <32 x i8> %a0, %a1 + %shift = lshr <32 x i8> %xor, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> + %res = sub <32 x i8> %or, %shift + ret <32 x i8> %res +} + +define <32 x i8> @test_ext_v32i8(<32 x i8> %a0, <32 x i8> %a1) { +; SSE-LABEL: test_ext_v32i8: +; SSE: # %bb.0: +; SSE-NEXT: pavgb %xmm2, %xmm0 +; SSE-NEXT: pavgb %xmm3, %xmm1 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_ext_v32i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm3 +; AVX1-NEXT: vpavgb %xmm2, %xmm3, %xmm2 +; AVX1-NEXT: vpavgb %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v32i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vpavgb %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v32i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpavgb %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: retq + %x0 = zext <32 x i8> %a0 to <32 x i16> + %x1 = zext <32 x i8> %a1 to <32 x i16> + %sum = add <32 x i16> %x0, %x1 + %inc = add <32 x i16> %sum, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %shift = lshr <32 x i16> %inc, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = trunc <32 x i16> %shift to <32 x i8> + ret <32 x i8> %res +} + +define <16 x i16> @test_fixed_v16i16(<16 x i16> %a0, <16 x i16> %a1) { +; SSE-LABEL: test_fixed_v16i16: +; SSE: # %bb.0: +; SSE-NEXT: pavgw %xmm2, %xmm0 +; SSE-NEXT: pavgw %xmm3, %xmm1 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v16i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm3 +; AVX1-NEXT: vpavgw %xmm2, %xmm3, %xmm2 +; AVX1-NEXT: vpavgw %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v16i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vpavgw %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v16i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vpavgw %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: retq + %or = or <16 x i16> %a0, %a1 + %xor = xor <16 x i16> %a1, %a0 + %shift = lshr <16 x i16> %xor, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = sub <16 x i16> %or, %shift + ret <16 x i16> %res +} + +define <16 x i16> @test_ext_v16i16(<16 x i16> %a0, <16 x i16> %a1) { +; SSE-LABEL: test_ext_v16i16: +; SSE: # %bb.0: +; SSE-NEXT: pavgw %xmm2, %xmm0 +; SSE-NEXT: pavgw %xmm3, %xmm1 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_ext_v16i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm3 +; AVX1-NEXT: vpavgw %xmm2, %xmm3, %xmm2 +; AVX1-NEXT: vpavgw %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v16i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vpavgw %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v16i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vpavgw %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: retq + %x0 = zext <16 x i16> %a0 to <16 x i32> + %x1 = zext <16 x i16> %a1 to <16 x i32> + %sum = add <16 x i32> %x0, %x1 + %inc = add <16 x i32> %sum, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %shift = lshr <16 x i32> %inc, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = trunc <16 x i32> %shift to <16 x i16> + ret <16 x i16> %res +} + +define <8 x i32> @test_fixed_v8i32(<8 x i32> %a0, <8 x i32> %a1) { +; SSE-LABEL: test_fixed_v8i32: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm1, %xmm4 +; SSE-NEXT: por %xmm3, %xmm4 +; SSE-NEXT: movdqa %xmm0, %xmm5 +; SSE-NEXT: por %xmm2, %xmm5 +; SSE-NEXT: pxor %xmm0, %xmm2 +; SSE-NEXT: pxor %xmm1, %xmm3 +; SSE-NEXT: psrld $1, %xmm3 +; SSE-NEXT: psubd %xmm3, %xmm4 +; SSE-NEXT: psrld $1, %xmm2 +; SSE-NEXT: psubd %xmm2, %xmm5 +; SSE-NEXT: movdqa %xmm5, %xmm0 +; SSE-NEXT: movdqa %xmm4, %xmm1 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v8i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vorps %ymm1, %ymm0, %ymm2 +; AVX1-NEXT: vxorps %ymm0, %ymm1, %ymm0 +; AVX1-NEXT: vpsrld $1, %xmm0, %xmm1 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrld $1, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3 +; AVX1-NEXT: vpsubd %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpsubd %xmm1, %xmm2, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v8i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vpor %ymm1, %ymm0, %ymm2 +; AVX2-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX2-NEXT: vpsrld $1, %ymm0, %ymm0 +; AVX2-NEXT: vpsubd %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v8i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vpor %ymm1, %ymm0, %ymm2 +; AVX512-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX512-NEXT: vpsrld $1, %ymm0, %ymm0 +; AVX512-NEXT: vpsubd %ymm0, %ymm2, %ymm0 +; AVX512-NEXT: retq + %or = or <8 x i32> %a0, %a1 + %xor = xor <8 x i32> %a1, %a0 + %shift = lshr <8 x i32> %xor, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = sub <8 x i32> %or, %shift + ret <8 x i32> %res +} + +define <8 x i32> @test_ext_v8i32(<8 x i32> %a0, <8 x i32> %a1) { +; SSE2-LABEL: test_ext_v8i32: +; SSE2: # %bb.0: +; SSE2-NEXT: movdqa %xmm0, %xmm4 +; SSE2-NEXT: pxor %xmm5, %xmm5 +; SSE2-NEXT: movdqa %xmm0, %xmm6 +; SSE2-NEXT: punpckldq {{.*#+}} xmm6 = xmm6[0],xmm5[0],xmm6[1],xmm5[1] +; SSE2-NEXT: punpckhdq {{.*#+}} xmm4 = xmm4[2],xmm5[2],xmm4[3],xmm5[3] +; SSE2-NEXT: movdqa %xmm1, %xmm7 +; SSE2-NEXT: punpckldq {{.*#+}} xmm7 = xmm7[0],xmm5[0],xmm7[1],xmm5[1] +; SSE2-NEXT: punpckhdq {{.*#+}} xmm1 = xmm1[2],xmm5[2],xmm1[3],xmm5[3] +; SSE2-NEXT: movdqa %xmm2, %xmm0 +; SSE2-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm5[0],xmm0[1],xmm5[1] +; SSE2-NEXT: paddq %xmm6, %xmm0 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm2 = xmm2[2],xmm5[2],xmm2[3],xmm5[3] +; SSE2-NEXT: paddq %xmm4, %xmm2 +; SSE2-NEXT: movdqa %xmm3, %xmm4 +; SSE2-NEXT: punpckldq {{.*#+}} xmm4 = xmm4[0],xmm5[0],xmm4[1],xmm5[1] +; SSE2-NEXT: paddq %xmm7, %xmm4 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm3 = xmm3[2],xmm5[2],xmm3[3],xmm5[3] +; SSE2-NEXT: paddq %xmm1, %xmm3 +; SSE2-NEXT: pcmpeqd %xmm1, %xmm1 +; SSE2-NEXT: psubq %xmm1, %xmm0 +; SSE2-NEXT: psubq %xmm1, %xmm2 +; SSE2-NEXT: psubq %xmm1, %xmm4 +; SSE2-NEXT: psubq %xmm1, %xmm3 +; SSE2-NEXT: psrlq $1, %xmm3 +; SSE2-NEXT: psrlq $1, %xmm4 +; SSE2-NEXT: shufps {{.*#+}} xmm4 = xmm4[0,2],xmm3[0,2] +; SSE2-NEXT: psrlq $1, %xmm2 +; SSE2-NEXT: psrlq $1, %xmm0 +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm2[0,2] +; SSE2-NEXT: movaps %xmm4, %xmm1 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v8i32: +; SSE4: # %bb.0: +; SSE4-NEXT: movdqa %xmm0, %xmm4 +; SSE4-NEXT: pxor %xmm5, %xmm5 +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm6 = xmm0[0],zero,xmm0[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm4 = xmm4[2],xmm5[2],xmm4[3],xmm5[3] +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm7 = xmm1[0],zero,xmm1[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm1 = xmm1[2],xmm5[2],xmm1[3],xmm5[3] +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm0 = xmm2[0],zero,xmm2[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm2 = xmm2[2],xmm5[2],xmm2[3],xmm5[3] +; SSE4-NEXT: paddq %xmm4, %xmm2 +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm4 = xmm3[0],zero,xmm3[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm3 = xmm3[2],xmm5[2],xmm3[3],xmm5[3] +; SSE4-NEXT: paddq %xmm1, %xmm3 +; SSE4-NEXT: paddq %xmm6, %xmm0 +; SSE4-NEXT: paddq %xmm7, %xmm4 +; SSE4-NEXT: pcmpeqd %xmm1, %xmm1 +; SSE4-NEXT: psubq %xmm1, %xmm2 +; SSE4-NEXT: psubq %xmm1, %xmm3 +; SSE4-NEXT: psubq %xmm1, %xmm0 +; SSE4-NEXT: psubq %xmm1, %xmm4 +; SSE4-NEXT: psrlq $1, %xmm3 +; SSE4-NEXT: psrlq $1, %xmm2 +; SSE4-NEXT: psrlq $1, %xmm4 +; SSE4-NEXT: shufps {{.*#+}} xmm4 = xmm4[0,2],xmm3[0,2] +; SSE4-NEXT: psrlq $1, %xmm0 +; SSE4-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm2[0,2] +; SSE4-NEXT: movaps %xmm4, %xmm1 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v8i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vpxor %xmm2, %xmm2, %xmm2 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm3 = xmm0[2],xmm2[2],xmm0[3],xmm2[3] +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm4 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm5 = xmm4[2],xmm2[2],xmm4[3],xmm2[3] +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm4 = xmm4[0],zero,xmm4[1],zero +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm6 = xmm1[2],xmm2[2],xmm1[3],xmm2[3] +; AVX1-NEXT: vpaddq %xmm6, %xmm3, %xmm3 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm6 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm2 = xmm6[2],xmm2[2],xmm6[3],xmm2[3] +; AVX1-NEXT: vpaddq %xmm2, %xmm5, %xmm2 +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero +; AVX1-NEXT: vpaddq %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm1 = xmm6[0],zero,xmm6[1],zero +; AVX1-NEXT: vpaddq %xmm1, %xmm4, %xmm1 +; AVX1-NEXT: vpcmpeqd %xmm4, %xmm4, %xmm4 +; AVX1-NEXT: vpsubq %xmm4, %xmm3, %xmm3 +; AVX1-NEXT: vpsubq %xmm4, %xmm2, %xmm2 +; AVX1-NEXT: vpsubq %xmm4, %xmm0, %xmm0 +; AVX1-NEXT: vpsubq %xmm4, %xmm1, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm2, %xmm2 +; AVX1-NEXT: vpsrlq $1, %xmm3, %xmm3 +; AVX1-NEXT: vpsrlq $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm3, %ymm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX1-NEXT: vshufps {{.*#+}} ymm0 = ymm0[0,2],ymm2[0,2],ymm0[4,6],ymm2[4,6] +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v8i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm2 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm3 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero +; AVX2-NEXT: vpaddq %ymm3, %ymm2, %ymm2 +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm1 +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero +; AVX2-NEXT: vpaddq %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpcmpeqd %ymm1, %ymm1, %ymm1 +; AVX2-NEXT: vpsubq %ymm1, %ymm2, %ymm2 +; AVX2-NEXT: vpsubq %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vperm2i128 {{.*#+}} ymm1 = ymm2[2,3],ymm0[2,3] +; AVX2-NEXT: vpsrlq $1, %ymm1, %ymm1 +; AVX2-NEXT: vinserti128 $1, %xmm0, %ymm2, %ymm0 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vshufps {{.*#+}} ymm0 = ymm0[0,2],ymm1[0,2],ymm0[4,6],ymm1[4,6] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v8i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovzxdq {{.*#+}} zmm0 = ymm0[0],zero,ymm0[1],zero,ymm0[2],zero,ymm0[3],zero,ymm0[4],zero,ymm0[5],zero,ymm0[6],zero,ymm0[7],zero +; AVX512-NEXT: vpmovzxdq {{.*#+}} zmm1 = ymm1[0],zero,ymm1[1],zero,ymm1[2],zero,ymm1[3],zero,ymm1[4],zero,ymm1[5],zero,ymm1[6],zero,ymm1[7],zero +; AVX512-NEXT: vpaddq %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpternlogd $255, %zmm1, %zmm1, %zmm1 +; AVX512-NEXT: vpsubq %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlq $1, %zmm0, %zmm0 +; AVX512-NEXT: vpmovqd %zmm0, %ymm0 +; AVX512-NEXT: retq + %x0 = zext <8 x i32> %a0 to <8 x i64> + %x1 = zext <8 x i32> %a1 to <8 x i64> + %sum = add <8 x i64> %x0, %x1 + %inc = add <8 x i64> %sum, <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1> + %shift = lshr <8 x i64> %inc, <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1> + %res = trunc <8 x i64> %shift to <8 x i32> + ret <8 x i32> %res +} + +define <4 x i64> @test_fixed_v4i64(<4 x i64> %a0, <4 x i64> %a1) { +; SSE-LABEL: test_fixed_v4i64: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm1, %xmm4 +; SSE-NEXT: por %xmm3, %xmm4 +; SSE-NEXT: movdqa %xmm0, %xmm5 +; SSE-NEXT: por %xmm2, %xmm5 +; SSE-NEXT: pxor %xmm0, %xmm2 +; SSE-NEXT: pxor %xmm1, %xmm3 +; SSE-NEXT: psrlq $1, %xmm3 +; SSE-NEXT: psubq %xmm3, %xmm4 +; SSE-NEXT: psrlq $1, %xmm2 +; SSE-NEXT: psubq %xmm2, %xmm5 +; SSE-NEXT: movdqa %xmm5, %xmm0 +; SSE-NEXT: movdqa %xmm4, %xmm1 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v4i64: +; AVX1: # %bb.0: +; AVX1-NEXT: vorps %ymm1, %ymm0, %ymm2 +; AVX1-NEXT: vxorps %ymm0, %ymm1, %ymm0 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm1 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3 +; AVX1-NEXT: vpsubq %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpsubq %xmm1, %xmm2, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v4i64: +; AVX2: # %bb.0: +; AVX2-NEXT: vpor %ymm1, %ymm0, %ymm2 +; AVX2-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vpsubq %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v4i64: +; AVX512: # %bb.0: +; AVX512-NEXT: vpor %ymm1, %ymm0, %ymm2 +; AVX512-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX512-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX512-NEXT: vpsubq %ymm0, %ymm2, %ymm0 +; AVX512-NEXT: retq + %or = or <4 x i64> %a0, %a1 + %xor = xor <4 x i64> %a1, %a0 + %shift = lshr <4 x i64> %xor, <i64 1, i64 1, i64 1, i64 1> + %res = sub <4 x i64> %or, %shift + ret <4 x i64> %res +} + +define <4 x i64> @test_ext_v4i64(<4 x i64> %a0, <4 x i64> %a1) { +; SSE2-LABEL: test_ext_v4i64: +; SSE2: # %bb.0: +; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm1[2,3,2,3] +; SSE2-NEXT: movq %xmm4, %rcx +; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm3[2,3,2,3] +; SSE2-NEXT: movq %xmm4, %rdx +; SSE2-NEXT: movb $1, %al +; SSE2-NEXT: movb $1, %sil +; SSE2-NEXT: addb $-1, %sil +; SSE2-NEXT: leaq 1(%rcx,%rdx), %rsi +; SSE2-NEXT: adcq %rdx, %rcx +; SSE2-NEXT: setb %dl +; SSE2-NEXT: movb $1, %cl +; SSE2-NEXT: addb $-1, %cl +; SSE2-NEXT: movq %xmm1, %rdi +; SSE2-NEXT: movq %xmm3, %r8 +; SSE2-NEXT: leaq 1(%rdi,%r8), %rcx +; SSE2-NEXT: adcq %r8, %rdi +; SSE2-NEXT: setb %dil +; SSE2-NEXT: movb $1, %r8b +; SSE2-NEXT: addb $-1, %r8b +; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] +; SSE2-NEXT: movq %xmm1, %r8 +; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm2[2,3,2,3] +; SSE2-NEXT: movq %xmm1, %r9 +; SSE2-NEXT: leaq 1(%r8,%r9), %r10 +; SSE2-NEXT: adcq %r9, %r8 +; SSE2-NEXT: setb %r8b +; SSE2-NEXT: addb $-1, %al +; SSE2-NEXT: movq %xmm0, %rax +; SSE2-NEXT: movq %xmm2, %r9 +; SSE2-NEXT: leaq 1(%rax,%r9), %r11 +; SSE2-NEXT: adcq %r9, %rax +; SSE2-NEXT: setb %al +; SSE2-NEXT: movzbl %al, %eax +; SSE2-NEXT: movzbl %r8b, %r8d +; SSE2-NEXT: movzbl %dil, %edi +; SSE2-NEXT: movzbl %dl, %edx +; SSE2-NEXT: shrdq $1, %rax, %r11 +; SSE2-NEXT: shrdq $1, %r8, %r10 +; SSE2-NEXT: shrdq $1, %rdi, %rcx +; SSE2-NEXT: shrdq $1, %rdx, %rsi +; SSE2-NEXT: movq %r11, %xmm0 +; SSE2-NEXT: movq %r10, %xmm1 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE2-NEXT: movq %rcx, %xmm1 +; SSE2-NEXT: movq %rsi, %xmm2 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm2[0] +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v4i64: +; SSE4: # %bb.0: +; SSE4-NEXT: movq %xmm1, %rcx +; SSE4-NEXT: movq %xmm3, %rdx +; SSE4-NEXT: movb $1, %al +; SSE4-NEXT: movb $1, %sil +; SSE4-NEXT: addb $-1, %sil +; SSE4-NEXT: leaq 1(%rcx,%rdx), %rsi +; SSE4-NEXT: adcq %rdx, %rcx +; SSE4-NEXT: setb %dl +; SSE4-NEXT: movb $1, %cl +; SSE4-NEXT: addb $-1, %cl +; SSE4-NEXT: pextrq $1, %xmm1, %rdi +; SSE4-NEXT: pextrq $1, %xmm3, %r8 +; SSE4-NEXT: leaq 1(%rdi,%r8), %rcx +; SSE4-NEXT: adcq %r8, %rdi +; SSE4-NEXT: setb %dil +; SSE4-NEXT: movb $1, %r8b +; SSE4-NEXT: addb $-1, %r8b +; SSE4-NEXT: movq %xmm0, %r8 +; SSE4-NEXT: movq %xmm2, %r9 +; SSE4-NEXT: leaq 1(%r8,%r9), %r10 +; SSE4-NEXT: adcq %r9, %r8 +; SSE4-NEXT: setb %r8b +; SSE4-NEXT: addb $-1, %al +; SSE4-NEXT: pextrq $1, %xmm0, %rax +; SSE4-NEXT: pextrq $1, %xmm2, %r9 +; SSE4-NEXT: leaq 1(%rax,%r9), %r11 +; SSE4-NEXT: adcq %r9, %rax +; SSE4-NEXT: setb %al +; SSE4-NEXT: movzbl %al, %eax +; SSE4-NEXT: movzbl %r8b, %r8d +; SSE4-NEXT: movzbl %dil, %edi +; SSE4-NEXT: movzbl %dl, %edx +; SSE4-NEXT: shrdq $1, %rax, %r11 +; SSE4-NEXT: shrdq $1, %r8, %r10 +; SSE4-NEXT: shrdq $1, %rdi, %rcx +; SSE4-NEXT: shrdq $1, %rdx, %rsi +; SSE4-NEXT: movq %r11, %xmm1 +; SSE4-NEXT: movq %r10, %xmm0 +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE4-NEXT: movq %rcx, %xmm2 +; SSE4-NEXT: movq %rsi, %xmm1 +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm2[0] +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v4i64: +; AVX1: # %bb.0: +; AVX1-NEXT: vmovq %xmm0, %rcx +; AVX1-NEXT: vmovq %xmm1, %rdx +; AVX1-NEXT: movb $1, %al +; AVX1-NEXT: movb $1, %sil +; AVX1-NEXT: addb $-1, %sil +; AVX1-NEXT: leaq 1(%rcx,%rdx), %rsi +; AVX1-NEXT: adcq %rdx, %rcx +; AVX1-NEXT: setb %dl +; AVX1-NEXT: movb $1, %cl +; AVX1-NEXT: addb $-1, %cl +; AVX1-NEXT: vpextrq $1, %xmm0, %rdi +; AVX1-NEXT: vpextrq $1, %xmm1, %r8 +; AVX1-NEXT: leaq 1(%rdi,%r8), %rcx +; AVX1-NEXT: adcq %r8, %rdi +; AVX1-NEXT: setb %dil +; AVX1-NEXT: movb $1, %r8b +; AVX1-NEXT: addb $-1, %r8b +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vmovq %xmm0, %r8 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vmovq %xmm1, %r9 +; AVX1-NEXT: leaq 1(%r8,%r9), %r10 +; AVX1-NEXT: adcq %r9, %r8 +; AVX1-NEXT: setb %r8b +; AVX1-NEXT: addb $-1, %al +; AVX1-NEXT: vpextrq $1, %xmm0, %rax +; AVX1-NEXT: vpextrq $1, %xmm1, %r9 +; AVX1-NEXT: leaq 1(%rax,%r9), %r11 +; AVX1-NEXT: adcq %r9, %rax +; AVX1-NEXT: setb %al +; AVX1-NEXT: movzbl %al, %eax +; AVX1-NEXT: movzbl %r8b, %r8d +; AVX1-NEXT: movzbl %dil, %edi +; AVX1-NEXT: movzbl %dl, %edx +; AVX1-NEXT: shrdq $1, %rax, %r11 +; AVX1-NEXT: shrdq $1, %r8, %r10 +; AVX1-NEXT: shrdq $1, %rdi, %rcx +; AVX1-NEXT: shrdq $1, %rdx, %rsi +; AVX1-NEXT: vmovq %r11, %xmm0 +; AVX1-NEXT: vmovq %r10, %xmm1 +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX1-NEXT: vmovq %rcx, %xmm1 +; AVX1-NEXT: vmovq %rsi, %xmm2 +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v4i64: +; AVX2: # %bb.0: +; AVX2-NEXT: vmovq %xmm0, %rcx +; AVX2-NEXT: vmovq %xmm1, %rdx +; AVX2-NEXT: movb $1, %al +; AVX2-NEXT: movb $1, %sil +; AVX2-NEXT: addb $-1, %sil +; AVX2-NEXT: leaq 1(%rcx,%rdx), %rsi +; AVX2-NEXT: adcq %rdx, %rcx +; AVX2-NEXT: setb %dl +; AVX2-NEXT: movb $1, %cl +; AVX2-NEXT: addb $-1, %cl +; AVX2-NEXT: vpextrq $1, %xmm0, %rdi +; AVX2-NEXT: vpextrq $1, %xmm1, %r8 +; AVX2-NEXT: leaq 1(%rdi,%r8), %rcx +; AVX2-NEXT: adcq %r8, %rdi +; AVX2-NEXT: setb %dil +; AVX2-NEXT: movb $1, %r8b +; AVX2-NEXT: addb $-1, %r8b +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX2-NEXT: vmovq %xmm0, %r8 +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm1 +; AVX2-NEXT: vmovq %xmm1, %r9 +; AVX2-NEXT: leaq 1(%r8,%r9), %r10 +; AVX2-NEXT: adcq %r9, %r8 +; AVX2-NEXT: setb %r8b +; AVX2-NEXT: addb $-1, %al +; AVX2-NEXT: vpextrq $1, %xmm0, %rax +; AVX2-NEXT: vpextrq $1, %xmm1, %r9 +; AVX2-NEXT: leaq 1(%rax,%r9), %r11 +; AVX2-NEXT: adcq %r9, %rax +; AVX2-NEXT: setb %al +; AVX2-NEXT: movzbl %al, %eax +; AVX2-NEXT: movzbl %r8b, %r8d +; AVX2-NEXT: movzbl %dil, %edi +; AVX2-NEXT: movzbl %dl, %edx +; AVX2-NEXT: shrdq $1, %rax, %r11 +; AVX2-NEXT: shrdq $1, %r8, %r10 +; AVX2-NEXT: shrdq $1, %rdi, %rcx +; AVX2-NEXT: shrdq $1, %rdx, %rsi +; AVX2-NEXT: vmovq %r11, %xmm0 +; AVX2-NEXT: vmovq %r10, %xmm1 +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX2-NEXT: vmovq %rcx, %xmm1 +; AVX2-NEXT: vmovq %rsi, %xmm2 +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX2-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v4i64: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovq %xmm0, %rcx +; AVX512-NEXT: vmovq %xmm1, %rdx +; AVX512-NEXT: movb $1, %al +; AVX512-NEXT: movb $1, %sil +; AVX512-NEXT: addb $-1, %sil +; AVX512-NEXT: leaq 1(%rcx,%rdx), %rsi +; AVX512-NEXT: adcq %rdx, %rcx +; AVX512-NEXT: setb %dl +; AVX512-NEXT: movb $1, %cl +; AVX512-NEXT: vpextrq $1, %xmm0, %rdi +; AVX512-NEXT: vpextrq $1, %xmm1, %r8 +; AVX512-NEXT: addb $-1, %cl +; AVX512-NEXT: leaq 1(%rdi,%r8), %rcx +; AVX512-NEXT: adcq %r8, %rdi +; AVX512-NEXT: setb %dil +; AVX512-NEXT: movb $1, %r8b +; AVX512-NEXT: addb $-1, %r8b +; AVX512-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX512-NEXT: vmovq %xmm0, %r8 +; AVX512-NEXT: vextracti128 $1, %ymm1, %xmm1 +; AVX512-NEXT: vmovq %xmm1, %r9 +; AVX512-NEXT: leaq 1(%r8,%r9), %r10 +; AVX512-NEXT: adcq %r9, %r8 +; AVX512-NEXT: setb %r8b +; AVX512-NEXT: addb $-1, %al +; AVX512-NEXT: vpextrq $1, %xmm0, %rax +; AVX512-NEXT: vpextrq $1, %xmm1, %r9 +; AVX512-NEXT: leaq 1(%rax,%r9), %r11 +; AVX512-NEXT: adcq %r9, %rax +; AVX512-NEXT: setb %al +; AVX512-NEXT: movzbl %al, %eax +; AVX512-NEXT: movzbl %r8b, %r8d +; AVX512-NEXT: movzbl %dil, %edi +; AVX512-NEXT: movzbl %dl, %edx +; AVX512-NEXT: shrdq $1, %rax, %r11 +; AVX512-NEXT: shrdq $1, %r8, %r10 +; AVX512-NEXT: shrdq $1, %rdi, %rcx +; AVX512-NEXT: shrdq $1, %rdx, %rsi +; AVX512-NEXT: vmovq %r11, %xmm0 +; AVX512-NEXT: vmovq %r10, %xmm1 +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512-NEXT: vmovq %rcx, %xmm1 +; AVX512-NEXT: vmovq %rsi, %xmm2 +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX512-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0 +; AVX512-NEXT: retq + %x0 = zext <4 x i64> %a0 to <4 x i128> + %x1 = zext <4 x i64> %a1 to <4 x i128> + %sum = add <4 x i128> %x0, %x1 + %inc = add <4 x i128> %sum, <i128 1, i128 1, i128 1, i128 1> + %shift = lshr <4 x i128> %inc, <i128 1, i128 1, i128 1, i128 1> + %res = trunc <4 x i128> %shift to <4 x i64> + ret <4 x i64> %res +} + +; +; 512-bit vectors +; + +define <64 x i8> @test_fixed_v64i8(<64 x i8> %a0, <64 x i8> %a1) { +; SSE-LABEL: test_fixed_v64i8: +; SSE: # %bb.0: +; SSE-NEXT: pavgb %xmm4, %xmm0 +; SSE-NEXT: pavgb %xmm5, %xmm1 +; SSE-NEXT: pavgb %xmm6, %xmm2 +; SSE-NEXT: pavgb %xmm7, %xmm3 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v64i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm4 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm5 +; AVX1-NEXT: vpavgb %xmm4, %xmm5, %xmm4 +; AVX1-NEXT: vpavgb %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm4, %ymm0, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm4 +; AVX1-NEXT: vpavgb %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vpavgb %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm1, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v64i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vpavgb %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpavgb %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v64i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpavgb %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: retq + %or = or <64 x i8> %a0, %a1 + %xor = xor <64 x i8> %a0, %a1 + %shift = lshr <64 x i8> %xor, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> + %res = sub <64 x i8> %or, %shift + ret <64 x i8> %res +} + +define <64 x i8> @test_ext_v64i8(<64 x i8> %a0, <64 x i8> %a1) { +; SSE-LABEL: test_ext_v64i8: +; SSE: # %bb.0: +; SSE-NEXT: pavgb %xmm4, %xmm0 +; SSE-NEXT: pavgb %xmm5, %xmm1 +; SSE-NEXT: pavgb %xmm6, %xmm2 +; SSE-NEXT: pavgb %xmm7, %xmm3 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_ext_v64i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm4 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm5 +; AVX1-NEXT: vpavgb %xmm4, %xmm5, %xmm4 +; AVX1-NEXT: vpavgb %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm4, %ymm0, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm4 +; AVX1-NEXT: vpavgb %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vpavgb %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm1, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v64i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vpavgb %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpavgb %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v64i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpavgb %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: retq + %x0 = zext <64 x i8> %a0 to <64 x i16> + %x1 = zext <64 x i8> %a1 to <64 x i16> + %sum = add <64 x i16> %x0, %x1 + %inc = add <64 x i16> %sum, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %shift = lshr <64 x i16> %inc, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = trunc <64 x i16> %shift to <64 x i8> + ret <64 x i8> %res +} + +define <32 x i16> @test_fixed_v32i16(<32 x i16> %a0, <32 x i16> %a1) { +; SSE-LABEL: test_fixed_v32i16: +; SSE: # %bb.0: +; SSE-NEXT: pavgw %xmm4, %xmm0 +; SSE-NEXT: pavgw %xmm5, %xmm1 +; SSE-NEXT: pavgw %xmm6, %xmm2 +; SSE-NEXT: pavgw %xmm7, %xmm3 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v32i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm4 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm5 +; AVX1-NEXT: vpavgw %xmm4, %xmm5, %xmm4 +; AVX1-NEXT: vpavgw %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm4, %ymm0, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm4 +; AVX1-NEXT: vpavgw %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vpavgw %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm1, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v32i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vpavgw %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpavgw %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v32i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vpavgw %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: retq + %or = or <32 x i16> %a0, %a1 + %xor = xor <32 x i16> %a1, %a0 + %shift = lshr <32 x i16> %xor, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = sub <32 x i16> %or, %shift + ret <32 x i16> %res +} + +define <32 x i16> @test_ext_v32i16(<32 x i16> %a0, <32 x i16> %a1) { +; SSE-LABEL: test_ext_v32i16: +; SSE: # %bb.0: +; SSE-NEXT: pavgw %xmm4, %xmm0 +; SSE-NEXT: pavgw %xmm5, %xmm1 +; SSE-NEXT: pavgw %xmm6, %xmm2 +; SSE-NEXT: pavgw %xmm7, %xmm3 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_ext_v32i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm4 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm5 +; AVX1-NEXT: vpavgw %xmm4, %xmm5, %xmm4 +; AVX1-NEXT: vpavgw %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm4, %ymm0, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm4 +; AVX1-NEXT: vpavgw %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vpavgw %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm1, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v32i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vpavgw %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpavgw %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v32i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vpavgw %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: retq + %x0 = zext <32 x i16> %a0 to <32 x i32> + %x1 = zext <32 x i16> %a1 to <32 x i32> + %sum = add <32 x i32> %x0, %x1 + %inc = add <32 x i32> %sum, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %shift = lshr <32 x i32> %inc, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = trunc <32 x i32> %shift to <32 x i16> + ret <32 x i16> %res +} + +define <16 x i32> @test_fixed_v16i32(<16 x i32> %a0, <16 x i32> %a1) { +; SSE-LABEL: test_fixed_v16i32: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm3, %xmm8 +; SSE-NEXT: por %xmm7, %xmm3 +; SSE-NEXT: movdqa %xmm2, %xmm9 +; SSE-NEXT: por %xmm6, %xmm9 +; SSE-NEXT: movdqa %xmm1, %xmm10 +; SSE-NEXT: por %xmm5, %xmm10 +; SSE-NEXT: movdqa %xmm0, %xmm11 +; SSE-NEXT: por %xmm4, %xmm11 +; SSE-NEXT: pxor %xmm0, %xmm4 +; SSE-NEXT: pxor %xmm1, %xmm5 +; SSE-NEXT: pxor %xmm2, %xmm6 +; SSE-NEXT: pxor %xmm8, %xmm7 +; SSE-NEXT: psrld $1, %xmm7 +; SSE-NEXT: psubd %xmm7, %xmm3 +; SSE-NEXT: psrld $1, %xmm6 +; SSE-NEXT: psubd %xmm6, %xmm9 +; SSE-NEXT: psrld $1, %xmm5 +; SSE-NEXT: psubd %xmm5, %xmm10 +; SSE-NEXT: psrld $1, %xmm4 +; SSE-NEXT: psubd %xmm4, %xmm11 +; SSE-NEXT: movdqa %xmm11, %xmm0 +; SSE-NEXT: movdqa %xmm10, %xmm1 +; SSE-NEXT: movdqa %xmm9, %xmm2 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v16i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vorps %ymm3, %ymm1, %ymm4 +; AVX1-NEXT: vorps %ymm2, %ymm0, %ymm5 +; AVX1-NEXT: vxorps %ymm0, %ymm2, %ymm0 +; AVX1-NEXT: vxorps %ymm1, %ymm3, %ymm1 +; AVX1-NEXT: vpsrld $1, %xmm1, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpsrld $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsrld $1, %xmm0, %xmm3 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrld $1, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm5, %xmm6 +; AVX1-NEXT: vpsubd %xmm0, %xmm6, %xmm0 +; AVX1-NEXT: vpsubd %xmm3, %xmm5, %xmm3 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm3, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm4, %xmm3 +; AVX1-NEXT: vpsubd %xmm1, %xmm3, %xmm1 +; AVX1-NEXT: vpsubd %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v16i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vpor %ymm3, %ymm1, %ymm4 +; AVX2-NEXT: vpor %ymm2, %ymm0, %ymm5 +; AVX2-NEXT: vpxor %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: vpxor %ymm1, %ymm3, %ymm1 +; AVX2-NEXT: vpsrld $1, %ymm1, %ymm1 +; AVX2-NEXT: vpsubd %ymm1, %ymm4, %ymm1 +; AVX2-NEXT: vpsrld $1, %ymm0, %ymm0 +; AVX2-NEXT: vpsubd %ymm0, %ymm5, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v16i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vpord %zmm1, %zmm0, %zmm2 +; AVX512-NEXT: vpxord %zmm0, %zmm1, %zmm0 +; AVX512-NEXT: vpsrld $1, %zmm0, %zmm0 +; AVX512-NEXT: vpsubd %zmm0, %zmm2, %zmm0 +; AVX512-NEXT: retq + %or = or <16 x i32> %a0, %a1 + %xor = xor <16 x i32> %a1, %a0 + %shift = lshr <16 x i32> %xor, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = sub <16 x i32> %or, %shift + ret <16 x i32> %res +} + +define <16 x i32> @test_ext_v16i32(<16 x i32> %a0, <16 x i32> %a1) { +; SSE2-LABEL: test_ext_v16i32: +; SSE2: # %bb.0: +; SSE2-NEXT: movdqa %xmm2, %xmm8 +; SSE2-NEXT: movdqa %xmm1, %xmm2 +; SSE2-NEXT: movdqa %xmm0, %xmm1 +; SSE2-NEXT: pxor %xmm9, %xmm9 +; SSE2-NEXT: movdqa %xmm0, %xmm10 +; SSE2-NEXT: punpckldq {{.*#+}} xmm10 = xmm10[0],xmm9[0],xmm10[1],xmm9[1] +; SSE2-NEXT: punpckhdq {{.*#+}} xmm1 = xmm1[2],xmm9[2],xmm1[3],xmm9[3] +; SSE2-NEXT: movdqa %xmm2, %xmm11 +; SSE2-NEXT: punpckldq {{.*#+}} xmm11 = xmm11[0],xmm9[0],xmm11[1],xmm9[1] +; SSE2-NEXT: punpckhdq {{.*#+}} xmm2 = xmm2[2],xmm9[2],xmm2[3],xmm9[3] +; SSE2-NEXT: movdqa %xmm8, %xmm12 +; SSE2-NEXT: punpckldq {{.*#+}} xmm12 = xmm12[0],xmm9[0],xmm12[1],xmm9[1] +; SSE2-NEXT: punpckhdq {{.*#+}} xmm8 = xmm8[2],xmm9[2],xmm8[3],xmm9[3] +; SSE2-NEXT: movdqa %xmm3, %xmm13 +; SSE2-NEXT: punpckldq {{.*#+}} xmm13 = xmm13[0],xmm9[0],xmm13[1],xmm9[1] +; SSE2-NEXT: punpckhdq {{.*#+}} xmm3 = xmm3[2],xmm9[2],xmm3[3],xmm9[3] +; SSE2-NEXT: movdqa %xmm4, %xmm0 +; SSE2-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm9[0],xmm0[1],xmm9[1] +; SSE2-NEXT: paddq %xmm10, %xmm0 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm4 = xmm4[2],xmm9[2],xmm4[3],xmm9[3] +; SSE2-NEXT: paddq %xmm1, %xmm4 +; SSE2-NEXT: movdqa %xmm5, %xmm1 +; SSE2-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm9[0],xmm1[1],xmm9[1] +; SSE2-NEXT: paddq %xmm11, %xmm1 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm5 = xmm5[2],xmm9[2],xmm5[3],xmm9[3] +; SSE2-NEXT: paddq %xmm2, %xmm5 +; SSE2-NEXT: movdqa %xmm6, %xmm2 +; SSE2-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm9[0],xmm2[1],xmm9[1] +; SSE2-NEXT: paddq %xmm12, %xmm2 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm6 = xmm6[2],xmm9[2],xmm6[3],xmm9[3] +; SSE2-NEXT: paddq %xmm8, %xmm6 +; SSE2-NEXT: movdqa %xmm7, %xmm8 +; SSE2-NEXT: punpckldq {{.*#+}} xmm8 = xmm8[0],xmm9[0],xmm8[1],xmm9[1] +; SSE2-NEXT: paddq %xmm13, %xmm8 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm7 = xmm7[2],xmm9[2],xmm7[3],xmm9[3] +; SSE2-NEXT: paddq %xmm3, %xmm7 +; SSE2-NEXT: pcmpeqd %xmm3, %xmm3 +; SSE2-NEXT: psubq %xmm3, %xmm0 +; SSE2-NEXT: psubq %xmm3, %xmm4 +; SSE2-NEXT: psubq %xmm3, %xmm1 +; SSE2-NEXT: psubq %xmm3, %xmm5 +; SSE2-NEXT: psubq %xmm3, %xmm2 +; SSE2-NEXT: psubq %xmm3, %xmm6 +; SSE2-NEXT: psubq %xmm3, %xmm8 +; SSE2-NEXT: psubq %xmm3, %xmm7 +; SSE2-NEXT: psrlq $1, %xmm7 +; SSE2-NEXT: psrlq $1, %xmm8 +; SSE2-NEXT: shufps {{.*#+}} xmm8 = xmm8[0,2],xmm7[0,2] +; SSE2-NEXT: psrlq $1, %xmm6 +; SSE2-NEXT: psrlq $1, %xmm2 +; SSE2-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,2],xmm6[0,2] +; SSE2-NEXT: psrlq $1, %xmm5 +; SSE2-NEXT: psrlq $1, %xmm1 +; SSE2-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm5[0,2] +; SSE2-NEXT: psrlq $1, %xmm4 +; SSE2-NEXT: psrlq $1, %xmm0 +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm4[0,2] +; SSE2-NEXT: movaps %xmm8, %xmm3 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v16i32: +; SSE4: # %bb.0: +; SSE4-NEXT: movdqa %xmm3, %xmm8 +; SSE4-NEXT: movdqa %xmm2, %xmm3 +; SSE4-NEXT: movdqa %xmm1, %xmm2 +; SSE4-NEXT: movdqa %xmm0, %xmm1 +; SSE4-NEXT: pxor %xmm10, %xmm10 +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm9 = xmm0[0],zero,xmm0[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm1 = xmm1[2],xmm10[2],xmm1[3],xmm10[3] +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm11 = xmm2[0],zero,xmm2[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm2 = xmm2[2],xmm10[2],xmm2[3],xmm10[3] +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm12 = xmm3[0],zero,xmm3[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm3 = xmm3[2],xmm10[2],xmm3[3],xmm10[3] +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm13 = xmm8[0],zero,xmm8[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm8 = xmm8[2],xmm10[2],xmm8[3],xmm10[3] +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm0 = xmm4[0],zero,xmm4[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm4 = xmm4[2],xmm10[2],xmm4[3],xmm10[3] +; SSE4-NEXT: paddq %xmm1, %xmm4 +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm1 = xmm5[0],zero,xmm5[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm5 = xmm5[2],xmm10[2],xmm5[3],xmm10[3] +; SSE4-NEXT: paddq %xmm2, %xmm5 +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm2 = xmm6[0],zero,xmm6[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm6 = xmm6[2],xmm10[2],xmm6[3],xmm10[3] +; SSE4-NEXT: paddq %xmm3, %xmm6 +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm3 = xmm7[0],zero,xmm7[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm7 = xmm7[2],xmm10[2],xmm7[3],xmm10[3] +; SSE4-NEXT: paddq %xmm8, %xmm7 +; SSE4-NEXT: paddq %xmm9, %xmm0 +; SSE4-NEXT: paddq %xmm11, %xmm1 +; SSE4-NEXT: paddq %xmm12, %xmm2 +; SSE4-NEXT: paddq %xmm13, %xmm3 +; SSE4-NEXT: pcmpeqd %xmm8, %xmm8 +; SSE4-NEXT: psubq %xmm8, %xmm4 +; SSE4-NEXT: psubq %xmm8, %xmm5 +; SSE4-NEXT: psubq %xmm8, %xmm6 +; SSE4-NEXT: psubq %xmm8, %xmm7 +; SSE4-NEXT: psubq %xmm8, %xmm0 +; SSE4-NEXT: psubq %xmm8, %xmm1 +; SSE4-NEXT: psubq %xmm8, %xmm2 +; SSE4-NEXT: psubq %xmm8, %xmm3 +; SSE4-NEXT: psrlq $1, %xmm7 +; SSE4-NEXT: psrlq $1, %xmm6 +; SSE4-NEXT: psrlq $1, %xmm5 +; SSE4-NEXT: psrlq $1, %xmm4 +; SSE4-NEXT: psrlq $1, %xmm3 +; SSE4-NEXT: shufps {{.*#+}} xmm3 = xmm3[0,2],xmm7[0,2] +; SSE4-NEXT: psrlq $1, %xmm2 +; SSE4-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,2],xmm6[0,2] +; SSE4-NEXT: psrlq $1, %xmm1 +; SSE4-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm5[0,2] +; SSE4-NEXT: psrlq $1, %xmm0 +; SSE4-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm4[0,2] +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v16i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vpxor %xmm4, %xmm4, %xmm4 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm5 = xmm0[2],xmm4[2],xmm0[3],xmm4[3] +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm6 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm7 = xmm6[2],xmm4[2],xmm6[3],xmm4[3] +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm8 = xmm1[2],xmm4[2],xmm1[3],xmm4[3] +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm9 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm10 = xmm9[2],xmm4[2],xmm9[3],xmm4[3] +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm6 = xmm6[0],zero,xmm6[1],zero +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm9 = xmm9[0],zero,xmm9[1],zero +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm11 = xmm2[2],xmm4[2],xmm2[3],xmm4[3] +; AVX1-NEXT: vpaddq %xmm5, %xmm11, %xmm5 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm11 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm12 = xmm11[2],xmm4[2],xmm11[3],xmm4[3] +; AVX1-NEXT: vpaddq %xmm7, %xmm12, %xmm7 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm12 = xmm3[2],xmm4[2],xmm3[3],xmm4[3] +; AVX1-NEXT: vpaddq %xmm12, %xmm8, %xmm8 +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm12 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm4 = xmm12[2],xmm4[2],xmm12[3],xmm4[3] +; AVX1-NEXT: vpaddq %xmm4, %xmm10, %xmm4 +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm2 = xmm2[0],zero,xmm2[1],zero +; AVX1-NEXT: vpaddq %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm2 = xmm11[0],zero,xmm11[1],zero +; AVX1-NEXT: vpaddq %xmm2, %xmm6, %xmm2 +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm3 = xmm3[0],zero,xmm3[1],zero +; AVX1-NEXT: vpaddq %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm3 = xmm12[0],zero,xmm12[1],zero +; AVX1-NEXT: vpaddq %xmm3, %xmm9, %xmm3 +; AVX1-NEXT: vpcmpeqd %xmm6, %xmm6, %xmm6 +; AVX1-NEXT: vpsubq %xmm6, %xmm5, %xmm5 +; AVX1-NEXT: vpsubq %xmm6, %xmm7, %xmm7 +; AVX1-NEXT: vpsubq %xmm6, %xmm8, %xmm8 +; AVX1-NEXT: vpsubq %xmm6, %xmm4, %xmm4 +; AVX1-NEXT: vpsubq %xmm6, %xmm0, %xmm0 +; AVX1-NEXT: vpsubq %xmm6, %xmm2, %xmm2 +; AVX1-NEXT: vpsubq %xmm6, %xmm1, %xmm1 +; AVX1-NEXT: vpsubq %xmm6, %xmm3, %xmm3 +; AVX1-NEXT: vpsrlq $1, %xmm4, %xmm4 +; AVX1-NEXT: vpsrlq $1, %xmm8, %xmm6 +; AVX1-NEXT: vpsrlq $1, %xmm7, %xmm7 +; AVX1-NEXT: vpsrlq $1, %xmm5, %xmm5 +; AVX1-NEXT: vpsrlq $1, %xmm3, %xmm3 +; AVX1-NEXT: vpsrlq $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm2, %xmm2 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm7, %ymm5, %ymm5 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 +; AVX1-NEXT: vshufps {{.*#+}} ymm0 = ymm0[0,2],ymm5[0,2],ymm0[4,6],ymm5[4,6] +; AVX1-NEXT: vinsertf128 $1, %xmm4, %ymm6, %ymm2 +; AVX1-NEXT: vinsertf128 $1, %xmm3, %ymm1, %ymm1 +; AVX1-NEXT: vshufps {{.*#+}} ymm1 = ymm1[0,2],ymm2[0,2],ymm1[4,6],ymm2[4,6] +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v16i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm4 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm5 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm1 +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm6 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero +; AVX2-NEXT: vpaddq %ymm6, %ymm4, %ymm4 +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm6 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero +; AVX2-NEXT: vpaddq %ymm6, %ymm5, %ymm5 +; AVX2-NEXT: vextracti128 $1, %ymm2, %xmm2 +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero +; AVX2-NEXT: vpaddq %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm3, %xmm2 +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero +; AVX2-NEXT: vpaddq %ymm2, %ymm1, %ymm1 +; AVX2-NEXT: vpcmpeqd %ymm2, %ymm2, %ymm2 +; AVX2-NEXT: vpsubq %ymm2, %ymm4, %ymm3 +; AVX2-NEXT: vpsubq %ymm2, %ymm5, %ymm4 +; AVX2-NEXT: vpsubq %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpsubq %ymm2, %ymm1, %ymm1 +; AVX2-NEXT: vperm2i128 {{.*#+}} ymm2 = ymm4[2,3],ymm0[2,3] +; AVX2-NEXT: vpsrlq $1, %ymm2, %ymm2 +; AVX2-NEXT: vinserti128 $1, %xmm0, %ymm4, %ymm0 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vshufps {{.*#+}} ymm0 = ymm0[0,2],ymm2[0,2],ymm0[4,6],ymm2[4,6] +; AVX2-NEXT: vperm2i128 {{.*#+}} ymm2 = ymm3[2,3],ymm1[2,3] +; AVX2-NEXT: vpsrlq $1, %ymm2, %ymm2 +; AVX2-NEXT: vinserti128 $1, %xmm1, %ymm3, %ymm1 +; AVX2-NEXT: vpsrlq $1, %ymm1, %ymm1 +; AVX2-NEXT: vshufps {{.*#+}} ymm1 = ymm1[0,2],ymm2[0,2],ymm1[4,6],ymm2[4,6] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v16i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovzxdq {{.*#+}} zmm2 = ymm0[0],zero,ymm0[1],zero,ymm0[2],zero,ymm0[3],zero,ymm0[4],zero,ymm0[5],zero,ymm0[6],zero,ymm0[7],zero +; AVX512-NEXT: vextracti64x4 $1, %zmm0, %ymm0 +; AVX512-NEXT: vpmovzxdq {{.*#+}} zmm0 = ymm0[0],zero,ymm0[1],zero,ymm0[2],zero,ymm0[3],zero,ymm0[4],zero,ymm0[5],zero,ymm0[6],zero,ymm0[7],zero +; AVX512-NEXT: vpmovzxdq {{.*#+}} zmm3 = ymm1[0],zero,ymm1[1],zero,ymm1[2],zero,ymm1[3],zero,ymm1[4],zero,ymm1[5],zero,ymm1[6],zero,ymm1[7],zero +; AVX512-NEXT: vpaddq %zmm3, %zmm2, %zmm2 +; AVX512-NEXT: vextracti64x4 $1, %zmm1, %ymm1 +; AVX512-NEXT: vpmovzxdq {{.*#+}} zmm1 = ymm1[0],zero,ymm1[1],zero,ymm1[2],zero,ymm1[3],zero,ymm1[4],zero,ymm1[5],zero,ymm1[6],zero,ymm1[7],zero +; AVX512-NEXT: vpaddq %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpternlogd $255, %zmm1, %zmm1, %zmm1 +; AVX512-NEXT: vpsubq %zmm1, %zmm2, %zmm2 +; AVX512-NEXT: vpsubq %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlq $1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlq $1, %zmm2, %zmm1 +; AVX512-NEXT: vpmovqd %zmm1, %ymm1 +; AVX512-NEXT: vpmovqd %zmm0, %ymm0 +; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-NEXT: retq + %x0 = zext <16 x i32> %a0 to <16 x i64> + %x1 = zext <16 x i32> %a1 to <16 x i64> + %sum = add <16 x i64> %x0, %x1 + %inc = add <16 x i64> %sum, <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1> + %shift = lshr <16 x i64> %inc, <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1> + %res = trunc <16 x i64> %shift to <16 x i32> + ret <16 x i32> %res +} + +define <8 x i64> @test_fixed_v8i64(<8 x i64> %a0, <8 x i64> %a1) { +; SSE-LABEL: test_fixed_v8i64: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm3, %xmm8 +; SSE-NEXT: por %xmm7, %xmm3 +; SSE-NEXT: movdqa %xmm2, %xmm9 +; SSE-NEXT: por %xmm6, %xmm9 +; SSE-NEXT: movdqa %xmm1, %xmm10 +; SSE-NEXT: por %xmm5, %xmm10 +; SSE-NEXT: movdqa %xmm0, %xmm11 +; SSE-NEXT: por %xmm4, %xmm11 +; SSE-NEXT: pxor %xmm0, %xmm4 +; SSE-NEXT: pxor %xmm1, %xmm5 +; SSE-NEXT: pxor %xmm2, %xmm6 +; SSE-NEXT: pxor %xmm8, %xmm7 +; SSE-NEXT: psrlq $1, %xmm7 +; SSE-NEXT: psubq %xmm7, %xmm3 +; SSE-NEXT: psrlq $1, %xmm6 +; SSE-NEXT: psubq %xmm6, %xmm9 +; SSE-NEXT: psrlq $1, %xmm5 +; SSE-NEXT: psubq %xmm5, %xmm10 +; SSE-NEXT: psrlq $1, %xmm4 +; SSE-NEXT: psubq %xmm4, %xmm11 +; SSE-NEXT: movdqa %xmm11, %xmm0 +; SSE-NEXT: movdqa %xmm10, %xmm1 +; SSE-NEXT: movdqa %xmm9, %xmm2 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v8i64: +; AVX1: # %bb.0: +; AVX1-NEXT: vorps %ymm3, %ymm1, %ymm4 +; AVX1-NEXT: vorps %ymm2, %ymm0, %ymm5 +; AVX1-NEXT: vxorps %ymm0, %ymm2, %ymm0 +; AVX1-NEXT: vxorps %ymm1, %ymm3, %ymm1 +; AVX1-NEXT: vpsrlq $1, %xmm1, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm3 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm5, %xmm6 +; AVX1-NEXT: vpsubq %xmm0, %xmm6, %xmm0 +; AVX1-NEXT: vpsubq %xmm3, %xmm5, %xmm3 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm3, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm4, %xmm3 +; AVX1-NEXT: vpsubq %xmm1, %xmm3, %xmm1 +; AVX1-NEXT: vpsubq %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v8i64: +; AVX2: # %bb.0: +; AVX2-NEXT: vpor %ymm3, %ymm1, %ymm4 +; AVX2-NEXT: vpor %ymm2, %ymm0, %ymm5 +; AVX2-NEXT: vpxor %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: vpxor %ymm1, %ymm3, %ymm1 +; AVX2-NEXT: vpsrlq $1, %ymm1, %ymm1 +; AVX2-NEXT: vpsubq %ymm1, %ymm4, %ymm1 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vpsubq %ymm0, %ymm5, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v8i64: +; AVX512: # %bb.0: +; AVX512-NEXT: vporq %zmm1, %zmm0, %zmm2 +; AVX512-NEXT: vpxorq %zmm0, %zmm1, %zmm0 +; AVX512-NEXT: vpsrlq $1, %zmm0, %zmm0 +; AVX512-NEXT: vpsubq %zmm0, %zmm2, %zmm0 +; AVX512-NEXT: retq + %or = or <8 x i64> %a0, %a1 + %xor = xor <8 x i64> %a1, %a0 + %shift = lshr <8 x i64> %xor, <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1> + %res = sub <8 x i64> %or, %shift + ret <8 x i64> %res +} + +define <8 x i64> @test_ext_v8i64(<8 x i64> %a0, <8 x i64> %a1) { +; SSE2-LABEL: test_ext_v8i64: +; SSE2: # %bb.0: +; SSE2-NEXT: pushq %rbp +; SSE2-NEXT: .cfi_def_cfa_offset 16 +; SSE2-NEXT: pushq %r15 +; SSE2-NEXT: .cfi_def_cfa_offset 24 +; SSE2-NEXT: pushq %r14 +; SSE2-NEXT: .cfi_def_cfa_offset 32 +; SSE2-NEXT: pushq %r13 +; SSE2-NEXT: .cfi_def_cfa_offset 40 +; SSE2-NEXT: pushq %r12 +; SSE2-NEXT: .cfi_def_cfa_offset 48 +; SSE2-NEXT: pushq %rbx +; SSE2-NEXT: .cfi_def_cfa_offset 56 +; SSE2-NEXT: .cfi_offset %rbx, -56 +; SSE2-NEXT: .cfi_offset %r12, -48 +; SSE2-NEXT: .cfi_offset %r13, -40 +; SSE2-NEXT: .cfi_offset %r14, -32 +; SSE2-NEXT: .cfi_offset %r15, -24 +; SSE2-NEXT: .cfi_offset %rbp, -16 +; SSE2-NEXT: pshufd {{.*#+}} xmm8 = xmm3[2,3,2,3] +; SSE2-NEXT: movq %xmm8, %rcx +; SSE2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: pshufd {{.*#+}} xmm8 = xmm7[2,3,2,3] +; SSE2-NEXT: movq %xmm8, %rdx +; SSE2-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: movb $1, %al +; SSE2-NEXT: addb $-1, %al +; SSE2-NEXT: movq %rcx, %rax +; SSE2-NEXT: adcq %rdx, %rax +; SSE2-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; SSE2-NEXT: movb $1, %al +; SSE2-NEXT: addb $-1, %al +; SSE2-NEXT: movq %xmm3, %r12 +; SSE2-NEXT: movq %xmm7, %rcx +; SSE2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: movq %r12, %rax +; SSE2-NEXT: adcq %rcx, %rax +; SSE2-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; SSE2-NEXT: movb $1, %al +; SSE2-NEXT: addb $-1, %al +; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm2[2,3,2,3] +; SSE2-NEXT: movq %xmm3, %r11 +; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm6[2,3,2,3] +; SSE2-NEXT: movq %xmm3, %rbx +; SSE2-NEXT: movq %r11, %rax +; SSE2-NEXT: adcq %rbx, %rax +; SSE2-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; SSE2-NEXT: movb $1, %al +; SSE2-NEXT: addb $-1, %al +; SSE2-NEXT: movq %xmm2, %r14 +; SSE2-NEXT: movq %xmm6, %r15 +; SSE2-NEXT: movq %r14, %rax +; SSE2-NEXT: adcq %r15, %rax +; SSE2-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; SSE2-NEXT: movb $1, %al +; SSE2-NEXT: addb $-1, %al +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] +; SSE2-NEXT: movq %xmm2, %r13 +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm5[2,3,2,3] +; SSE2-NEXT: movq %xmm2, %r10 +; SSE2-NEXT: movq %r13, %rax +; SSE2-NEXT: adcq %r10, %rax +; SSE2-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; SSE2-NEXT: movb $1, %al +; SSE2-NEXT: addb $-1, %al +; SSE2-NEXT: movq %xmm1, %r9 +; SSE2-NEXT: movq %xmm5, %r8 +; SSE2-NEXT: movq %r9, %rax +; SSE2-NEXT: adcq %r8, %rax +; SSE2-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; SSE2-NEXT: movb $1, %al +; SSE2-NEXT: addb $-1, %al +; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm4[2,3,2,3] +; SSE2-NEXT: movq %xmm1, %rdi +; SSE2-NEXT: movq %xmm2, %rsi +; SSE2-NEXT: movq %rdi, %rdx +; SSE2-NEXT: adcq %rsi, %rdx +; SSE2-NEXT: movb $1, %dl +; SSE2-NEXT: setb %bpl +; SSE2-NEXT: addb $-1, %dl +; SSE2-NEXT: movq %xmm0, %rcx +; SSE2-NEXT: movq %xmm4, %rax +; SSE2-NEXT: movq %rcx, %rdx +; SSE2-NEXT: adcq %rax, %rdx +; SSE2-NEXT: leaq 1(%rcx,%rax), %rdx +; SSE2-NEXT: leaq 1(%rdi,%rsi), %rax +; SSE2-NEXT: leaq 1(%r9,%r8), %rcx +; SSE2-NEXT: leaq 1(%r13,%r10), %rdi +; SSE2-NEXT: leaq 1(%r14,%r15), %rsi +; SSE2-NEXT: leaq 1(%r11,%rbx), %r11 +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r8 # 8-byte Reload +; SSE2-NEXT: leaq 1(%r12,%r8), %r9 +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r8 # 8-byte Reload +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Reload +; SSE2-NEXT: leaq 1(%r8,%r10), %r10 +; SSE2-NEXT: setb %r8b +; SSE2-NEXT: movzbl %r8b, %r8d +; SSE2-NEXT: shrdq $1, %r8, %rdx +; SSE2-NEXT: movzbl %bpl, %r8d +; SSE2-NEXT: shrdq $1, %r8, %rax +; SSE2-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r8d # 1-byte Folded Reload +; SSE2-NEXT: shrdq $1, %r8, %rcx +; SSE2-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r8d # 1-byte Folded Reload +; SSE2-NEXT: shrdq $1, %r8, %rdi +; SSE2-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r8d # 1-byte Folded Reload +; SSE2-NEXT: shrdq $1, %r8, %rsi +; SSE2-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r8d # 1-byte Folded Reload +; SSE2-NEXT: shrdq $1, %r8, %r11 +; SSE2-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r8d # 1-byte Folded Reload +; SSE2-NEXT: shrdq $1, %r8, %r9 +; SSE2-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r8d # 1-byte Folded Reload +; SSE2-NEXT: shrdq $1, %r8, %r10 +; SSE2-NEXT: movq %rdx, %xmm0 +; SSE2-NEXT: movq %rax, %xmm4 +; SSE2-NEXT: movq %rcx, %xmm1 +; SSE2-NEXT: movq %rdi, %xmm5 +; SSE2-NEXT: movq %rsi, %xmm2 +; SSE2-NEXT: movq %r11, %xmm6 +; SSE2-NEXT: movq %r9, %xmm3 +; SSE2-NEXT: movq %r10, %xmm7 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm4[0] +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm5[0] +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm6[0] +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm3 = xmm3[0],xmm7[0] +; SSE2-NEXT: popq %rbx +; SSE2-NEXT: .cfi_def_cfa_offset 48 +; SSE2-NEXT: popq %r12 +; SSE2-NEXT: .cfi_def_cfa_offset 40 +; SSE2-NEXT: popq %r13 +; SSE2-NEXT: .cfi_def_cfa_offset 32 +; SSE2-NEXT: popq %r14 +; SSE2-NEXT: .cfi_def_cfa_offset 24 +; SSE2-NEXT: popq %r15 +; SSE2-NEXT: .cfi_def_cfa_offset 16 +; SSE2-NEXT: popq %rbp +; SSE2-NEXT: .cfi_def_cfa_offset 8 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v8i64: +; SSE4: # %bb.0: +; SSE4-NEXT: pushq %rbp +; SSE4-NEXT: .cfi_def_cfa_offset 16 +; SSE4-NEXT: pushq %r15 +; SSE4-NEXT: .cfi_def_cfa_offset 24 +; SSE4-NEXT: pushq %r14 +; SSE4-NEXT: .cfi_def_cfa_offset 32 +; SSE4-NEXT: pushq %r13 +; SSE4-NEXT: .cfi_def_cfa_offset 40 +; SSE4-NEXT: pushq %r12 +; SSE4-NEXT: .cfi_def_cfa_offset 48 +; SSE4-NEXT: pushq %rbx +; SSE4-NEXT: .cfi_def_cfa_offset 56 +; SSE4-NEXT: .cfi_offset %rbx, -56 +; SSE4-NEXT: .cfi_offset %r12, -48 +; SSE4-NEXT: .cfi_offset %r13, -40 +; SSE4-NEXT: .cfi_offset %r14, -32 +; SSE4-NEXT: .cfi_offset %r15, -24 +; SSE4-NEXT: .cfi_offset %rbp, -16 +; SSE4-NEXT: movq %xmm3, %rcx +; SSE4-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: movq %xmm7, %rdx +; SSE4-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: movb $1, %al +; SSE4-NEXT: addb $-1, %al +; SSE4-NEXT: movq %rcx, %rax +; SSE4-NEXT: adcq %rdx, %rax +; SSE4-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; SSE4-NEXT: movb $1, %al +; SSE4-NEXT: addb $-1, %al +; SSE4-NEXT: pextrq $1, %xmm3, %r12 +; SSE4-NEXT: pextrq $1, %xmm7, %rbp +; SSE4-NEXT: movq %r12, %rax +; SSE4-NEXT: adcq %rbp, %rax +; SSE4-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; SSE4-NEXT: movb $1, %al +; SSE4-NEXT: addb $-1, %al +; SSE4-NEXT: movq %xmm2, %r11 +; SSE4-NEXT: movq %xmm6, %rbx +; SSE4-NEXT: movq %r11, %rax +; SSE4-NEXT: adcq %rbx, %rax +; SSE4-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; SSE4-NEXT: movb $1, %al +; SSE4-NEXT: addb $-1, %al +; SSE4-NEXT: pextrq $1, %xmm2, %r14 +; SSE4-NEXT: pextrq $1, %xmm6, %r15 +; SSE4-NEXT: movq %r14, %rax +; SSE4-NEXT: adcq %r15, %rax +; SSE4-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; SSE4-NEXT: movb $1, %al +; SSE4-NEXT: addb $-1, %al +; SSE4-NEXT: movq %xmm1, %r13 +; SSE4-NEXT: movq %xmm5, %r10 +; SSE4-NEXT: movq %r13, %rax +; SSE4-NEXT: adcq %r10, %rax +; SSE4-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; SSE4-NEXT: movb $1, %al +; SSE4-NEXT: addb $-1, %al +; SSE4-NEXT: pextrq $1, %xmm1, %r9 +; SSE4-NEXT: pextrq $1, %xmm5, %r8 +; SSE4-NEXT: movq %r9, %rax +; SSE4-NEXT: adcq %r8, %rax +; SSE4-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; SSE4-NEXT: movb $1, %al +; SSE4-NEXT: addb $-1, %al +; SSE4-NEXT: movq %xmm0, %rdi +; SSE4-NEXT: movq %xmm4, %rsi +; SSE4-NEXT: movq %rdi, %rdx +; SSE4-NEXT: adcq %rsi, %rdx +; SSE4-NEXT: movb $1, %dl +; SSE4-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; SSE4-NEXT: addb $-1, %dl +; SSE4-NEXT: pextrq $1, %xmm0, %rcx +; SSE4-NEXT: pextrq $1, %xmm4, %rax +; SSE4-NEXT: movq %rcx, %rdx +; SSE4-NEXT: adcq %rax, %rdx +; SSE4-NEXT: leaq 1(%rcx,%rax), %rdx +; SSE4-NEXT: leaq 1(%rdi,%rsi), %rax +; SSE4-NEXT: leaq 1(%r9,%r8), %rcx +; SSE4-NEXT: leaq 1(%r13,%r10), %rdi +; SSE4-NEXT: leaq 1(%r14,%r15), %rsi +; SSE4-NEXT: leaq 1(%r11,%rbx), %r11 +; SSE4-NEXT: leaq 1(%r12,%rbp), %r8 +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r9 # 8-byte Reload +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Reload +; SSE4-NEXT: leaq 1(%r9,%r10), %r9 +; SSE4-NEXT: setb %r10b +; SSE4-NEXT: movzbl %r10b, %r10d +; SSE4-NEXT: shrdq $1, %r10, %rdx +; SSE4-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; SSE4-NEXT: shrdq $1, %r10, %rax +; SSE4-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; SSE4-NEXT: shrdq $1, %r10, %rcx +; SSE4-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; SSE4-NEXT: shrdq $1, %r10, %rdi +; SSE4-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; SSE4-NEXT: shrdq $1, %r10, %rsi +; SSE4-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; SSE4-NEXT: shrdq $1, %r10, %r11 +; SSE4-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; SSE4-NEXT: shrdq $1, %r10, %r8 +; SSE4-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; SSE4-NEXT: shrdq $1, %r10, %r9 +; SSE4-NEXT: movq %rdx, %xmm4 +; SSE4-NEXT: movq %rax, %xmm0 +; SSE4-NEXT: movq %rcx, %xmm5 +; SSE4-NEXT: movq %rdi, %xmm1 +; SSE4-NEXT: movq %rsi, %xmm6 +; SSE4-NEXT: movq %r11, %xmm2 +; SSE4-NEXT: movq %r8, %xmm7 +; SSE4-NEXT: movq %r9, %xmm3 +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm4[0] +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm5[0] +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm6[0] +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm3 = xmm3[0],xmm7[0] +; SSE4-NEXT: popq %rbx +; SSE4-NEXT: .cfi_def_cfa_offset 48 +; SSE4-NEXT: popq %r12 +; SSE4-NEXT: .cfi_def_cfa_offset 40 +; SSE4-NEXT: popq %r13 +; SSE4-NEXT: .cfi_def_cfa_offset 32 +; SSE4-NEXT: popq %r14 +; SSE4-NEXT: .cfi_def_cfa_offset 24 +; SSE4-NEXT: popq %r15 +; SSE4-NEXT: .cfi_def_cfa_offset 16 +; SSE4-NEXT: popq %rbp +; SSE4-NEXT: .cfi_def_cfa_offset 8 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v8i64: +; AVX1: # %bb.0: +; AVX1-NEXT: pushq %rbp +; AVX1-NEXT: .cfi_def_cfa_offset 16 +; AVX1-NEXT: pushq %r15 +; AVX1-NEXT: .cfi_def_cfa_offset 24 +; AVX1-NEXT: pushq %r14 +; AVX1-NEXT: .cfi_def_cfa_offset 32 +; AVX1-NEXT: pushq %r13 +; AVX1-NEXT: .cfi_def_cfa_offset 40 +; AVX1-NEXT: pushq %r12 +; AVX1-NEXT: .cfi_def_cfa_offset 48 +; AVX1-NEXT: pushq %rbx +; AVX1-NEXT: .cfi_def_cfa_offset 56 +; AVX1-NEXT: .cfi_offset %rbx, -56 +; AVX1-NEXT: .cfi_offset %r12, -48 +; AVX1-NEXT: .cfi_offset %r13, -40 +; AVX1-NEXT: .cfi_offset %r14, -32 +; AVX1-NEXT: .cfi_offset %r15, -24 +; AVX1-NEXT: .cfi_offset %rbp, -16 +; AVX1-NEXT: vmovq %xmm1, %rcx +; AVX1-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: vmovq %xmm3, %rdx +; AVX1-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: movb $1, %al +; AVX1-NEXT: addb $-1, %al +; AVX1-NEXT: movq %rcx, %rax +; AVX1-NEXT: adcq %rdx, %rax +; AVX1-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; AVX1-NEXT: movb $1, %al +; AVX1-NEXT: addb $-1, %al +; AVX1-NEXT: vpextrq $1, %xmm1, %r12 +; AVX1-NEXT: vpextrq $1, %xmm3, %rcx +; AVX1-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: movq %r12, %rax +; AVX1-NEXT: adcq %rcx, %rax +; AVX1-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; AVX1-NEXT: movb $1, %al +; AVX1-NEXT: addb $-1, %al +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vmovq %xmm1, %r11 +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm3 +; AVX1-NEXT: vmovq %xmm3, %rbx +; AVX1-NEXT: movq %r11, %rax +; AVX1-NEXT: adcq %rbx, %rax +; AVX1-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; AVX1-NEXT: movb $1, %al +; AVX1-NEXT: addb $-1, %al +; AVX1-NEXT: vpextrq $1, %xmm1, %r14 +; AVX1-NEXT: vpextrq $1, %xmm3, %r15 +; AVX1-NEXT: movq %r14, %rax +; AVX1-NEXT: adcq %r15, %rax +; AVX1-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; AVX1-NEXT: movb $1, %al +; AVX1-NEXT: addb $-1, %al +; AVX1-NEXT: vmovq %xmm0, %r13 +; AVX1-NEXT: vmovq %xmm2, %r10 +; AVX1-NEXT: movq %r13, %rax +; AVX1-NEXT: adcq %r10, %rax +; AVX1-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; AVX1-NEXT: movb $1, %al +; AVX1-NEXT: addb $-1, %al +; AVX1-NEXT: vpextrq $1, %xmm0, %r9 +; AVX1-NEXT: vpextrq $1, %xmm2, %r8 +; AVX1-NEXT: movq %r9, %rax +; AVX1-NEXT: adcq %r8, %rax +; AVX1-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; AVX1-NEXT: movb $1, %al +; AVX1-NEXT: addb $-1, %al +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm1 +; AVX1-NEXT: vmovq %xmm0, %rdi +; AVX1-NEXT: vmovq %xmm1, %rsi +; AVX1-NEXT: movq %rdi, %rcx +; AVX1-NEXT: adcq %rsi, %rcx +; AVX1-NEXT: movb $1, %cl +; AVX1-NEXT: setb %bpl +; AVX1-NEXT: addb $-1, %cl +; AVX1-NEXT: vpextrq $1, %xmm0, %rdx +; AVX1-NEXT: vpextrq $1, %xmm1, %rax +; AVX1-NEXT: movq %rdx, %rcx +; AVX1-NEXT: adcq %rax, %rcx +; AVX1-NEXT: leaq 1(%rdx,%rax), %rcx +; AVX1-NEXT: leaq 1(%rdi,%rsi), %rax +; AVX1-NEXT: leaq 1(%r9,%r8), %rdx +; AVX1-NEXT: leaq 1(%r13,%r10), %rdi +; AVX1-NEXT: leaq 1(%r14,%r15), %rsi +; AVX1-NEXT: leaq 1(%r11,%rbx), %r11 +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r8 # 8-byte Reload +; AVX1-NEXT: leaq 1(%r12,%r8), %r9 +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r8 # 8-byte Reload +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Reload +; AVX1-NEXT: leaq 1(%r8,%r10), %r8 +; AVX1-NEXT: setb %r10b +; AVX1-NEXT: movzbl %r10b, %r10d +; AVX1-NEXT: shrdq $1, %r10, %rcx +; AVX1-NEXT: movzbl %bpl, %r10d +; AVX1-NEXT: shrdq $1, %r10, %rax +; AVX1-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; AVX1-NEXT: shrdq $1, %r10, %rdx +; AVX1-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; AVX1-NEXT: shrdq $1, %r10, %rdi +; AVX1-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; AVX1-NEXT: shrdq $1, %r10, %rsi +; AVX1-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; AVX1-NEXT: shrdq $1, %r10, %r11 +; AVX1-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; AVX1-NEXT: shrdq $1, %r10, %r9 +; AVX1-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; AVX1-NEXT: shrdq $1, %r10, %r8 +; AVX1-NEXT: vmovq %rcx, %xmm0 +; AVX1-NEXT: vmovq %rax, %xmm1 +; AVX1-NEXT: vmovq %rdx, %xmm2 +; AVX1-NEXT: vmovq %rdi, %xmm3 +; AVX1-NEXT: vmovq %rsi, %xmm4 +; AVX1-NEXT: vmovq %r11, %xmm5 +; AVX1-NEXT: vmovq %r9, %xmm6 +; AVX1-NEXT: vmovq %r8, %xmm7 +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm3[0],xmm2[0] +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm5[0],xmm4[0] +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm7[0],xmm6[0] +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: popq %rbx +; AVX1-NEXT: .cfi_def_cfa_offset 48 +; AVX1-NEXT: popq %r12 +; AVX1-NEXT: .cfi_def_cfa_offset 40 +; AVX1-NEXT: popq %r13 +; AVX1-NEXT: .cfi_def_cfa_offset 32 +; AVX1-NEXT: popq %r14 +; AVX1-NEXT: .cfi_def_cfa_offset 24 +; AVX1-NEXT: popq %r15 +; AVX1-NEXT: .cfi_def_cfa_offset 16 +; AVX1-NEXT: popq %rbp +; AVX1-NEXT: .cfi_def_cfa_offset 8 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v8i64: +; AVX2: # %bb.0: +; AVX2-NEXT: pushq %rbp +; AVX2-NEXT: .cfi_def_cfa_offset 16 +; AVX2-NEXT: pushq %r15 +; AVX2-NEXT: .cfi_def_cfa_offset 24 +; AVX2-NEXT: pushq %r14 +; AVX2-NEXT: .cfi_def_cfa_offset 32 +; AVX2-NEXT: pushq %r13 +; AVX2-NEXT: .cfi_def_cfa_offset 40 +; AVX2-NEXT: pushq %r12 +; AVX2-NEXT: .cfi_def_cfa_offset 48 +; AVX2-NEXT: pushq %rbx +; AVX2-NEXT: .cfi_def_cfa_offset 56 +; AVX2-NEXT: .cfi_offset %rbx, -56 +; AVX2-NEXT: .cfi_offset %r12, -48 +; AVX2-NEXT: .cfi_offset %r13, -40 +; AVX2-NEXT: .cfi_offset %r14, -32 +; AVX2-NEXT: .cfi_offset %r15, -24 +; AVX2-NEXT: .cfi_offset %rbp, -16 +; AVX2-NEXT: vmovq %xmm1, %rcx +; AVX2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: vmovq %xmm3, %rdx +; AVX2-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: movb $1, %al +; AVX2-NEXT: addb $-1, %al +; AVX2-NEXT: movq %rcx, %rax +; AVX2-NEXT: adcq %rdx, %rax +; AVX2-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; AVX2-NEXT: movb $1, %al +; AVX2-NEXT: addb $-1, %al +; AVX2-NEXT: vpextrq $1, %xmm1, %r12 +; AVX2-NEXT: vpextrq $1, %xmm3, %rcx +; AVX2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: movq %r12, %rax +; AVX2-NEXT: adcq %rcx, %rax +; AVX2-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; AVX2-NEXT: movb $1, %al +; AVX2-NEXT: addb $-1, %al +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm1 +; AVX2-NEXT: vmovq %xmm1, %r11 +; AVX2-NEXT: vextracti128 $1, %ymm3, %xmm3 +; AVX2-NEXT: vmovq %xmm3, %rbx +; AVX2-NEXT: movq %r11, %rax +; AVX2-NEXT: adcq %rbx, %rax +; AVX2-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; AVX2-NEXT: movb $1, %al +; AVX2-NEXT: addb $-1, %al +; AVX2-NEXT: vpextrq $1, %xmm1, %r14 +; AVX2-NEXT: vpextrq $1, %xmm3, %r15 +; AVX2-NEXT: movq %r14, %rax +; AVX2-NEXT: adcq %r15, %rax +; AVX2-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; AVX2-NEXT: movb $1, %al +; AVX2-NEXT: addb $-1, %al +; AVX2-NEXT: vmovq %xmm0, %r13 +; AVX2-NEXT: vmovq %xmm2, %r10 +; AVX2-NEXT: movq %r13, %rax +; AVX2-NEXT: adcq %r10, %rax +; AVX2-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; AVX2-NEXT: movb $1, %al +; AVX2-NEXT: addb $-1, %al +; AVX2-NEXT: vpextrq $1, %xmm0, %r9 +; AVX2-NEXT: vpextrq $1, %xmm2, %r8 +; AVX2-NEXT: movq %r9, %rax +; AVX2-NEXT: adcq %r8, %rax +; AVX2-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; AVX2-NEXT: movb $1, %al +; AVX2-NEXT: addb $-1, %al +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX2-NEXT: vextracti128 $1, %ymm2, %xmm1 +; AVX2-NEXT: vmovq %xmm0, %rdi +; AVX2-NEXT: vmovq %xmm1, %rsi +; AVX2-NEXT: movq %rdi, %rcx +; AVX2-NEXT: adcq %rsi, %rcx +; AVX2-NEXT: movb $1, %cl +; AVX2-NEXT: setb %bpl +; AVX2-NEXT: addb $-1, %cl +; AVX2-NEXT: vpextrq $1, %xmm0, %rdx +; AVX2-NEXT: vpextrq $1, %xmm1, %rax +; AVX2-NEXT: movq %rdx, %rcx +; AVX2-NEXT: adcq %rax, %rcx +; AVX2-NEXT: leaq 1(%rdx,%rax), %rcx +; AVX2-NEXT: leaq 1(%rdi,%rsi), %rax +; AVX2-NEXT: leaq 1(%r9,%r8), %rdx +; AVX2-NEXT: leaq 1(%r13,%r10), %rdi +; AVX2-NEXT: leaq 1(%r14,%r15), %rsi +; AVX2-NEXT: leaq 1(%r11,%rbx), %r11 +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r8 # 8-byte Reload +; AVX2-NEXT: leaq 1(%r12,%r8), %r9 +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r8 # 8-byte Reload +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Reload +; AVX2-NEXT: leaq 1(%r8,%r10), %r8 +; AVX2-NEXT: setb %r10b +; AVX2-NEXT: movzbl %r10b, %r10d +; AVX2-NEXT: shrdq $1, %r10, %rcx +; AVX2-NEXT: movzbl %bpl, %r10d +; AVX2-NEXT: shrdq $1, %r10, %rax +; AVX2-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; AVX2-NEXT: shrdq $1, %r10, %rdx +; AVX2-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; AVX2-NEXT: shrdq $1, %r10, %rdi +; AVX2-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; AVX2-NEXT: shrdq $1, %r10, %rsi +; AVX2-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; AVX2-NEXT: shrdq $1, %r10, %r11 +; AVX2-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; AVX2-NEXT: shrdq $1, %r10, %r9 +; AVX2-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; AVX2-NEXT: shrdq $1, %r10, %r8 +; AVX2-NEXT: vmovq %rcx, %xmm0 +; AVX2-NEXT: vmovq %rax, %xmm1 +; AVX2-NEXT: vmovq %rdx, %xmm2 +; AVX2-NEXT: vmovq %rdi, %xmm3 +; AVX2-NEXT: vmovq %rsi, %xmm4 +; AVX2-NEXT: vmovq %r11, %xmm5 +; AVX2-NEXT: vmovq %r9, %xmm6 +; AVX2-NEXT: vmovq %r8, %xmm7 +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm3[0],xmm2[0] +; AVX2-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0 +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm5[0],xmm4[0] +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm7[0],xmm6[0] +; AVX2-NEXT: vinserti128 $1, %xmm1, %ymm2, %ymm1 +; AVX2-NEXT: popq %rbx +; AVX2-NEXT: .cfi_def_cfa_offset 48 +; AVX2-NEXT: popq %r12 +; AVX2-NEXT: .cfi_def_cfa_offset 40 +; AVX2-NEXT: popq %r13 +; AVX2-NEXT: .cfi_def_cfa_offset 32 +; AVX2-NEXT: popq %r14 +; AVX2-NEXT: .cfi_def_cfa_offset 24 +; AVX2-NEXT: popq %r15 +; AVX2-NEXT: .cfi_def_cfa_offset 16 +; AVX2-NEXT: popq %rbp +; AVX2-NEXT: .cfi_def_cfa_offset 8 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v8i64: +; AVX512: # %bb.0: +; AVX512-NEXT: pushq %rbp +; AVX512-NEXT: .cfi_def_cfa_offset 16 +; AVX512-NEXT: pushq %r15 +; AVX512-NEXT: .cfi_def_cfa_offset 24 +; AVX512-NEXT: pushq %r14 +; AVX512-NEXT: .cfi_def_cfa_offset 32 +; AVX512-NEXT: pushq %r13 +; AVX512-NEXT: .cfi_def_cfa_offset 40 +; AVX512-NEXT: pushq %r12 +; AVX512-NEXT: .cfi_def_cfa_offset 48 +; AVX512-NEXT: pushq %rbx +; AVX512-NEXT: .cfi_def_cfa_offset 56 +; AVX512-NEXT: .cfi_offset %rbx, -56 +; AVX512-NEXT: .cfi_offset %r12, -48 +; AVX512-NEXT: .cfi_offset %r13, -40 +; AVX512-NEXT: .cfi_offset %r14, -32 +; AVX512-NEXT: .cfi_offset %r15, -24 +; AVX512-NEXT: .cfi_offset %rbp, -16 +; AVX512-NEXT: vmovq %xmm0, %rcx +; AVX512-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: vmovq %xmm1, %rdx +; AVX512-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: movb $1, %al +; AVX512-NEXT: addb $-1, %al +; AVX512-NEXT: movq %rcx, %rax +; AVX512-NEXT: adcq %rdx, %rax +; AVX512-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; AVX512-NEXT: movb $1, %al +; AVX512-NEXT: vpextrq $1, %xmm0, %r12 +; AVX512-NEXT: vpextrq $1, %xmm1, %rcx +; AVX512-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: addb $-1, %al +; AVX512-NEXT: movq %r12, %rax +; AVX512-NEXT: adcq %rcx, %rax +; AVX512-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; AVX512-NEXT: movb $1, %al +; AVX512-NEXT: addb $-1, %al +; AVX512-NEXT: vextracti128 $1, %ymm0, %xmm2 +; AVX512-NEXT: vmovq %xmm2, %r11 +; AVX512-NEXT: vextracti128 $1, %ymm1, %xmm3 +; AVX512-NEXT: vmovq %xmm3, %rbx +; AVX512-NEXT: movq %r11, %rax +; AVX512-NEXT: adcq %rbx, %rax +; AVX512-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; AVX512-NEXT: movb $1, %al +; AVX512-NEXT: addb $-1, %al +; AVX512-NEXT: vpextrq $1, %xmm2, %r14 +; AVX512-NEXT: vpextrq $1, %xmm3, %r15 +; AVX512-NEXT: movq %r14, %rax +; AVX512-NEXT: adcq %r15, %rax +; AVX512-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; AVX512-NEXT: movb $1, %al +; AVX512-NEXT: addb $-1, %al +; AVX512-NEXT: vextracti64x4 $1, %zmm0, %ymm0 +; AVX512-NEXT: vmovq %xmm0, %r13 +; AVX512-NEXT: vextracti64x4 $1, %zmm1, %ymm1 +; AVX512-NEXT: vmovq %xmm1, %r10 +; AVX512-NEXT: movq %r13, %rax +; AVX512-NEXT: adcq %r10, %rax +; AVX512-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; AVX512-NEXT: movb $1, %al +; AVX512-NEXT: vpextrq $1, %xmm0, %r9 +; AVX512-NEXT: addb $-1, %al +; AVX512-NEXT: vpextrq $1, %xmm1, %r8 +; AVX512-NEXT: movq %r9, %rax +; AVX512-NEXT: adcq %r8, %rax +; AVX512-NEXT: setb {{[-0-9]+}}(%r{{[sb]}}p) # 1-byte Folded Spill +; AVX512-NEXT: movb $1, %al +; AVX512-NEXT: addb $-1, %al +; AVX512-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX512-NEXT: vextracti128 $1, %ymm1, %xmm1 +; AVX512-NEXT: vmovq %xmm0, %rdi +; AVX512-NEXT: vmovq %xmm1, %rsi +; AVX512-NEXT: movq %rdi, %rcx +; AVX512-NEXT: adcq %rsi, %rcx +; AVX512-NEXT: movb $1, %cl +; AVX512-NEXT: setb %bpl +; AVX512-NEXT: vpextrq $1, %xmm0, %rdx +; AVX512-NEXT: vpextrq $1, %xmm1, %rax +; AVX512-NEXT: addb $-1, %cl +; AVX512-NEXT: movq %rdx, %rcx +; AVX512-NEXT: adcq %rax, %rcx +; AVX512-NEXT: leaq 1(%rdx,%rax), %rcx +; AVX512-NEXT: leaq 1(%rdi,%rsi), %rax +; AVX512-NEXT: leaq 1(%r9,%r8), %rdx +; AVX512-NEXT: leaq 1(%r13,%r10), %rdi +; AVX512-NEXT: leaq 1(%r14,%r15), %rsi +; AVX512-NEXT: leaq 1(%r11,%rbx), %r11 +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r8 # 8-byte Reload +; AVX512-NEXT: leaq 1(%r12,%r8), %r9 +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r8 # 8-byte Reload +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Reload +; AVX512-NEXT: leaq 1(%r8,%r10), %r8 +; AVX512-NEXT: setb %r10b +; AVX512-NEXT: movzbl %r10b, %r10d +; AVX512-NEXT: shrdq $1, %r10, %rcx +; AVX512-NEXT: movzbl %bpl, %r10d +; AVX512-NEXT: shrdq $1, %r10, %rax +; AVX512-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; AVX512-NEXT: shrdq $1, %r10, %rdx +; AVX512-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; AVX512-NEXT: shrdq $1, %r10, %rdi +; AVX512-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; AVX512-NEXT: shrdq $1, %r10, %rsi +; AVX512-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; AVX512-NEXT: shrdq $1, %r10, %r11 +; AVX512-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; AVX512-NEXT: shrdq $1, %r10, %r9 +; AVX512-NEXT: movzbl {{[-0-9]+}}(%r{{[sb]}}p), %r10d # 1-byte Folded Reload +; AVX512-NEXT: shrdq $1, %r10, %r8 +; AVX512-NEXT: vmovq %rcx, %xmm0 +; AVX512-NEXT: vmovq %rax, %xmm1 +; AVX512-NEXT: vmovq %rdx, %xmm2 +; AVX512-NEXT: vmovq %rdi, %xmm3 +; AVX512-NEXT: vmovq %rsi, %xmm4 +; AVX512-NEXT: vmovq %r11, %xmm5 +; AVX512-NEXT: vmovq %r9, %xmm6 +; AVX512-NEXT: vmovq %r8, %xmm7 +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm3[0],xmm2[0] +; AVX512-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0 +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm5[0],xmm4[0] +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm7[0],xmm6[0] +; AVX512-NEXT: vinserti128 $1, %xmm1, %ymm2, %ymm1 +; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-NEXT: popq %rbx +; AVX512-NEXT: .cfi_def_cfa_offset 48 +; AVX512-NEXT: popq %r12 +; AVX512-NEXT: .cfi_def_cfa_offset 40 +; AVX512-NEXT: popq %r13 +; AVX512-NEXT: .cfi_def_cfa_offset 32 +; AVX512-NEXT: popq %r14 +; AVX512-NEXT: .cfi_def_cfa_offset 24 +; AVX512-NEXT: popq %r15 +; AVX512-NEXT: .cfi_def_cfa_offset 16 +; AVX512-NEXT: popq %rbp +; AVX512-NEXT: .cfi_def_cfa_offset 8 +; AVX512-NEXT: retq + %x0 = zext <8 x i64> %a0 to <8 x i128> + %x1 = zext <8 x i64> %a1 to <8 x i128> + %sum = add <8 x i128> %x0, %x1 + %inc = add <8 x i128> %sum, <i128 1, i128 1, i128 1, i128 1, i128 1, i128 1, i128 1, i128 1> + %shift = lshr <8 x i128> %inc, <i128 1, i128 1, i128 1, i128 1, i128 1, i128 1, i128 1, i128 1> + %res = trunc <8 x i128> %shift to <8 x i64> + ret <8 x i64> %res +} + diff --git a/llvm/test/CodeGen/X86/avgfloors.ll b/llvm/test/CodeGen/X86/avgfloors.ll new file mode 100644 index 0000000000000000000000000000000000000000..a3864ab4bb44e42baed68c4107e586bbb79ade6d --- /dev/null +++ b/llvm/test/CodeGen/X86/avgfloors.ll @@ -0,0 +1,3437 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-- -mattr=+sse2 | FileCheck %s --check-prefixes=SSE,SSE2 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+sse4.1 | FileCheck %s --check-prefixes=SSE,SSE4 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx | FileCheck %s --check-prefixes=AVX,AVX1 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx2 | FileCheck %s --check-prefixes=AVX,AVX2 +; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64-v4 | FileCheck %s --check-prefixes=AVX,AVX512 + +; +; 128-bit vectors +; + +define <16 x i8> @test_fixed_v16i8(<16 x i8> %a0, <16 x i8> %a1) { +; SSE-LABEL: test_fixed_v16i8: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm0, %xmm2 +; SSE-NEXT: pand %xmm1, %xmm2 +; SSE-NEXT: pxor %xmm1, %xmm0 +; SSE-NEXT: psrlw $1, %xmm0 +; SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; SSE-NEXT: movdqa {{.*#+}} xmm1 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; SSE-NEXT: pxor %xmm1, %xmm0 +; SSE-NEXT: paddb %xmm2, %xmm0 +; SSE-NEXT: psubb %xmm1, %xmm0 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v16i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX1-NEXT: vpxor %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX1-NEXT: vbroadcastss {{.*#+}} xmm1 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; AVX1-NEXT: vpxor %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpaddb %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpsubb %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v16i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX2-NEXT: vpxor %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX2-NEXT: vpbroadcastb {{.*#+}} xmm1 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; AVX2-NEXT: vpxor %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vpaddb %xmm2, %xmm0, %xmm0 +; AVX2-NEXT: vpsubb %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v16i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512-NEXT: vpxor %xmm1, %xmm0, %xmm0 +; AVX512-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX512-NEXT: vpbroadcastb {{.*#+}} xmm1 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; AVX512-NEXT: vpternlogd $108, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm1, %xmm0 +; AVX512-NEXT: vpaddb %xmm2, %xmm0, %xmm0 +; AVX512-NEXT: vpsubb %xmm1, %xmm0, %xmm0 +; AVX512-NEXT: retq + %and = and <16 x i8> %a0, %a1 + %xor = xor <16 x i8> %a0, %a1 + %shift = ashr <16 x i8> %xor, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> + %res = add <16 x i8> %and, %shift + ret <16 x i8> %res +} + +define <16 x i8> @test_ext_v16i8(<16 x i8> %a0, <16 x i8> %a1) { +; SSE2-LABEL: test_ext_v16i8: +; SSE2: # %bb.0: +; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1],xmm2[2],xmm0[2],xmm2[3],xmm0[3],xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; SSE2-NEXT: psraw $8, %xmm2 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm0[8],xmm3[9],xmm0[9],xmm3[10],xmm0[10],xmm3[11],xmm0[11],xmm3[12],xmm0[12],xmm3[13],xmm0[13],xmm3[14],xmm0[14],xmm3[15],xmm0[15] +; SSE2-NEXT: psraw $8, %xmm3 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] +; SSE2-NEXT: psraw $8, %xmm0 +; SSE2-NEXT: paddw %xmm2, %xmm0 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; SSE2-NEXT: psraw $8, %xmm1 +; SSE2-NEXT: paddw %xmm3, %xmm1 +; SSE2-NEXT: psrlw $1, %xmm0 +; SSE2-NEXT: psrlw $1, %xmm1 +; SSE2-NEXT: movdqa {{.*#+}} xmm2 = [255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0] +; SSE2-NEXT: pand %xmm2, %xmm1 +; SSE2-NEXT: pand %xmm2, %xmm0 +; SSE2-NEXT: packuswb %xmm1, %xmm0 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v16i8: +; SSE4: # %bb.0: +; SSE4-NEXT: pshufd {{.*#+}} xmm2 = xmm0[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm2, %xmm2 +; SSE4-NEXT: pmovsxbw %xmm0, %xmm3 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm0, %xmm4 +; SSE4-NEXT: paddw %xmm2, %xmm4 +; SSE4-NEXT: pmovsxbw %xmm1, %xmm0 +; SSE4-NEXT: paddw %xmm3, %xmm0 +; SSE4-NEXT: psrlw $1, %xmm4 +; SSE4-NEXT: psrlw $1, %xmm0 +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm1 = [255,255,255,255,255,255,255,255] +; SSE4-NEXT: pand %xmm1, %xmm0 +; SSE4-NEXT: pand %xmm1, %xmm4 +; SSE4-NEXT: packuswb %xmm4, %xmm0 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v16i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vpshufd {{.*#+}} xmm2 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm2, %xmm2 +; AVX1-NEXT: vpmovsxbw %xmm0, %xmm0 +; AVX1-NEXT: vpshufd {{.*#+}} xmm3 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm3, %xmm3 +; AVX1-NEXT: vpaddw %xmm3, %xmm2, %xmm2 +; AVX1-NEXT: vpmovsxbw %xmm1, %xmm1 +; AVX1-NEXT: vpaddw %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm2, %xmm1 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vbroadcastss {{.*#+}} xmm2 = [255,255,255,255,255,255,255,255] +; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpand %xmm2, %xmm1, %xmm1 +; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v16i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovsxbw %xmm0, %ymm0 +; AVX2-NEXT: vpmovsxbw %xmm1, %ymm1 +; AVX2-NEXT: vpaddw %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1 +; AVX2-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v16i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovsxbw %xmm0, %ymm0 +; AVX512-NEXT: vpmovsxbw %xmm1, %ymm1 +; AVX512-NEXT: vpaddw %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX512-NEXT: vpmovwb %ymm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + %x0 = sext <16 x i8> %a0 to <16 x i16> + %x1 = sext <16 x i8> %a1 to <16 x i16> + %sum = add <16 x i16> %x0, %x1 + %shift = ashr <16 x i16> %sum, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = trunc <16 x i16> %shift to <16 x i8> + ret <16 x i8> %res +} + +define <8 x i16> @test_fixed_v8i16(<8 x i16> %a0, <8 x i16> %a1) { +; SSE-LABEL: test_fixed_v8i16: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm0, %xmm2 +; SSE-NEXT: pand %xmm1, %xmm2 +; SSE-NEXT: pxor %xmm1, %xmm0 +; SSE-NEXT: psraw $1, %xmm0 +; SSE-NEXT: paddw %xmm2, %xmm0 +; SSE-NEXT: retq +; +; AVX-LABEL: test_fixed_v8i16: +; AVX: # %bb.0: +; AVX-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX-NEXT: vpxor %xmm0, %xmm1, %xmm0 +; AVX-NEXT: vpsraw $1, %xmm0, %xmm0 +; AVX-NEXT: vpaddw %xmm0, %xmm2, %xmm0 +; AVX-NEXT: retq + %and = and <8 x i16> %a0, %a1 + %xor = xor <8 x i16> %a1, %a0 + %shift = ashr <8 x i16> %xor, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = add <8 x i16> %and, %shift + ret <8 x i16> %res +} + +define <8 x i16> @test_ext_v8i16(<8 x i16> %a0, <8 x i16> %a1) { +; SSE2-LABEL: test_ext_v8i16: +; SSE2: # %bb.0: +; SSE2-NEXT: punpckhwd {{.*#+}} xmm2 = xmm2[4],xmm0[4],xmm2[5],xmm0[5],xmm2[6],xmm0[6],xmm2[7],xmm0[7] +; SSE2-NEXT: psrad $16, %xmm2 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1],xmm3[2],xmm0[2],xmm3[3],xmm0[3] +; SSE2-NEXT: psrad $16, %xmm3 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm4 = xmm4[4],xmm1[4],xmm4[5],xmm1[5],xmm4[6],xmm1[6],xmm4[7],xmm1[7] +; SSE2-NEXT: psrad $16, %xmm4 +; SSE2-NEXT: paddd %xmm2, %xmm4 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3] +; SSE2-NEXT: psrad $16, %xmm0 +; SSE2-NEXT: paddd %xmm3, %xmm0 +; SSE2-NEXT: pslld $15, %xmm4 +; SSE2-NEXT: psrad $16, %xmm4 +; SSE2-NEXT: pslld $15, %xmm0 +; SSE2-NEXT: psrad $16, %xmm0 +; SSE2-NEXT: packssdw %xmm4, %xmm0 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v8i16: +; SSE4: # %bb.0: +; SSE4-NEXT: pshufd {{.*#+}} xmm2 = xmm0[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm2, %xmm2 +; SSE4-NEXT: pmovsxwd %xmm0, %xmm3 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm0, %xmm4 +; SSE4-NEXT: paddd %xmm2, %xmm4 +; SSE4-NEXT: pmovsxwd %xmm1, %xmm0 +; SSE4-NEXT: paddd %xmm3, %xmm0 +; SSE4-NEXT: psrld $1, %xmm4 +; SSE4-NEXT: psrld $1, %xmm0 +; SSE4-NEXT: pxor %xmm1, %xmm1 +; SSE4-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0],xmm1[1],xmm0[2],xmm1[3],xmm0[4],xmm1[5],xmm0[6],xmm1[7] +; SSE4-NEXT: pblendw {{.*#+}} xmm4 = xmm4[0],xmm1[1],xmm4[2],xmm1[3],xmm4[4],xmm1[5],xmm4[6],xmm1[7] +; SSE4-NEXT: packusdw %xmm4, %xmm0 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v8i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vpshufd {{.*#+}} xmm2 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm2, %xmm2 +; AVX1-NEXT: vpmovsxwd %xmm0, %xmm0 +; AVX1-NEXT: vpshufd {{.*#+}} xmm3 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm3, %xmm3 +; AVX1-NEXT: vpaddd %xmm3, %xmm2, %xmm2 +; AVX1-NEXT: vpmovsxwd %xmm1, %xmm1 +; AVX1-NEXT: vpaddd %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrld $1, %xmm2, %xmm1 +; AVX1-NEXT: vpsrld $1, %xmm0, %xmm0 +; AVX1-NEXT: vpxor %xmm2, %xmm2, %xmm2 +; AVX1-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0],xmm2[1],xmm0[2],xmm2[3],xmm0[4],xmm2[5],xmm0[6],xmm2[7] +; AVX1-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0],xmm2[1],xmm1[2],xmm2[3],xmm1[4],xmm2[5],xmm1[6],xmm2[7] +; AVX1-NEXT: vpackusdw %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v8i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovsxwd %xmm0, %ymm0 +; AVX2-NEXT: vpmovsxwd %xmm1, %ymm1 +; AVX2-NEXT: vpaddd %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrld $1, %ymm0, %ymm0 +; AVX2-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[0,1,4,5,8,9,12,13,u,u,u,u,u,u,u,u,16,17,20,21,24,25,28,29,u,u,u,u,u,u,u,u] +; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,2,2,3] +; AVX2-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0 +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v8i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovsxwd %xmm0, %ymm0 +; AVX512-NEXT: vpmovsxwd %xmm1, %ymm1 +; AVX512-NEXT: vpaddd %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpsrld $1, %ymm0, %ymm0 +; AVX512-NEXT: vpmovdw %ymm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + %x0 = sext <8 x i16> %a0 to <8 x i32> + %x1 = sext <8 x i16> %a1 to <8 x i32> + %sum = add <8 x i32> %x0, %x1 + %shift = ashr <8 x i32> %sum, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = trunc <8 x i32> %shift to <8 x i16> + ret <8 x i16> %res +} + +define <4 x i32> @test_fixed_v4i32(<4 x i32> %a0, <4 x i32> %a1) { +; SSE-LABEL: test_fixed_v4i32: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm0, %xmm2 +; SSE-NEXT: pand %xmm1, %xmm2 +; SSE-NEXT: pxor %xmm1, %xmm0 +; SSE-NEXT: psrad $1, %xmm0 +; SSE-NEXT: paddd %xmm2, %xmm0 +; SSE-NEXT: retq +; +; AVX-LABEL: test_fixed_v4i32: +; AVX: # %bb.0: +; AVX-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX-NEXT: vpxor %xmm0, %xmm1, %xmm0 +; AVX-NEXT: vpsrad $1, %xmm0, %xmm0 +; AVX-NEXT: vpaddd %xmm0, %xmm2, %xmm0 +; AVX-NEXT: retq + %and = and <4 x i32> %a0, %a1 + %xor = xor <4 x i32> %a1, %a0 + %shift = ashr <4 x i32> %xor, <i32 1, i32 1, i32 1, i32 1> + %res = add <4 x i32> %and, %shift + ret <4 x i32> %res +} + +define <4 x i32> @test_ext_v4i32(<4 x i32> %a0, <4 x i32> %a1) { +; SSE2-LABEL: test_ext_v4i32: +; SSE2: # %bb.0: +; SSE2-NEXT: pxor %xmm2, %xmm2 +; SSE2-NEXT: pxor %xmm3, %xmm3 +; SSE2-NEXT: pcmpgtd %xmm0, %xmm3 +; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm0[2,3,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1] +; SSE2-NEXT: pxor %xmm3, %xmm3 +; SSE2-NEXT: pcmpgtd %xmm4, %xmm3 +; SSE2-NEXT: punpckldq {{.*#+}} xmm4 = xmm4[0],xmm3[0],xmm4[1],xmm3[1] +; SSE2-NEXT: pxor %xmm3, %xmm3 +; SSE2-NEXT: pcmpgtd %xmm1, %xmm3 +; SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm1[2,3,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1] +; SSE2-NEXT: paddq %xmm1, %xmm0 +; SSE2-NEXT: pcmpgtd %xmm5, %xmm2 +; SSE2-NEXT: punpckldq {{.*#+}} xmm5 = xmm5[0],xmm2[0],xmm5[1],xmm2[1] +; SSE2-NEXT: paddq %xmm4, %xmm5 +; SSE2-NEXT: psrlq $1, %xmm0 +; SSE2-NEXT: psrlq $1, %xmm5 +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm5[0,2] +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v4i32: +; SSE4: # %bb.0: +; SSE4-NEXT: pmovsxdq %xmm0, %xmm2 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm0, %xmm3 +; SSE4-NEXT: pmovsxdq %xmm1, %xmm0 +; SSE4-NEXT: paddq %xmm2, %xmm0 +; SSE4-NEXT: pshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm1, %xmm1 +; SSE4-NEXT: paddq %xmm3, %xmm1 +; SSE4-NEXT: psrlq $1, %xmm0 +; SSE4-NEXT: psrlq $1, %xmm1 +; SSE4-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm1[0,2] +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v4i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vpmovsxdq %xmm0, %xmm2 +; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm0, %xmm0 +; AVX1-NEXT: vpmovsxdq %xmm1, %xmm3 +; AVX1-NEXT: vpaddq %xmm3, %xmm2, %xmm2 +; AVX1-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm1, %xmm1 +; AVX1-NEXT: vpaddq %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlq $1, %xmm2, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vshufps {{.*#+}} xmm0 = xmm1[0,2],xmm0[0,2] +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v4i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovsxdq %xmm0, %ymm0 +; AVX2-NEXT: vpmovsxdq %xmm1, %ymm1 +; AVX2-NEXT: vpaddq %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1 +; AVX2-NEXT: vshufps {{.*#+}} xmm0 = xmm0[0,2],xmm1[0,2] +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v4i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovsxdq %xmm0, %ymm0 +; AVX512-NEXT: vpmovsxdq %xmm1, %ymm1 +; AVX512-NEXT: vpaddq %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX512-NEXT: vpmovqd %ymm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + %x0 = sext <4 x i32> %a0 to <4 x i64> + %x1 = sext <4 x i32> %a1 to <4 x i64> + %sum = add <4 x i64> %x0, %x1 + %shift = ashr <4 x i64> %sum, <i64 1, i64 1, i64 1, i64 1> + %res = trunc <4 x i64> %shift to <4 x i32> + ret <4 x i32> %res +} + +define <2 x i64> @test_fixed_v2i64(<2 x i64> %a0, <2 x i64> %a1) { +; SSE2-LABEL: test_fixed_v2i64: +; SSE2: # %bb.0: +; SSE2-NEXT: movdqa %xmm0, %xmm2 +; SSE2-NEXT: pand %xmm1, %xmm2 +; SSE2-NEXT: pxor %xmm0, %xmm1 +; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm1[1,3,2,3] +; SSE2-NEXT: psrad $1, %xmm3 +; SSE2-NEXT: psrlq $1, %xmm1 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[0,2,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1] +; SSE2-NEXT: paddq %xmm2, %xmm0 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_fixed_v2i64: +; SSE4: # %bb.0: +; SSE4-NEXT: movdqa %xmm0, %xmm2 +; SSE4-NEXT: pand %xmm1, %xmm2 +; SSE4-NEXT: pxor %xmm1, %xmm0 +; SSE4-NEXT: movdqa %xmm0, %xmm1 +; SSE4-NEXT: psrad $1, %xmm1 +; SSE4-NEXT: psrlq $1, %xmm0 +; SSE4-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3],xmm0[4,5],xmm1[6,7] +; SSE4-NEXT: paddq %xmm2, %xmm0 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_fixed_v2i64: +; AVX1: # %bb.0: +; AVX1-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX1-NEXT: vpxor %xmm0, %xmm1, %xmm0 +; AVX1-NEXT: vpsrad $1, %xmm0, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3],xmm0[4,5],xmm1[6,7] +; AVX1-NEXT: vpaddq %xmm0, %xmm2, %xmm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v2i64: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX2-NEXT: vpxor %xmm0, %xmm1, %xmm0 +; AVX2-NEXT: vpsrad $1, %xmm0, %xmm1 +; AVX2-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX2-NEXT: vpblendd {{.*#+}} xmm0 = xmm0[0],xmm1[1],xmm0[2],xmm1[3] +; AVX2-NEXT: vpaddq %xmm0, %xmm2, %xmm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v2i64: +; AVX512: # %bb.0: +; AVX512-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512-NEXT: vpxor %xmm0, %xmm1, %xmm0 +; AVX512-NEXT: vpsraq $1, %xmm0, %xmm0 +; AVX512-NEXT: vpaddq %xmm0, %xmm2, %xmm0 +; AVX512-NEXT: retq + %and = and <2 x i64> %a0, %a1 + %xor = xor <2 x i64> %a1, %a0 + %shift = ashr <2 x i64> %xor, <i64 1, i64 1> + %res = add <2 x i64> %and, %shift + ret <2 x i64> %res +} + +define <2 x i64> @test_ext_v2i64(<2 x i64> %a0, <2 x i64> %a1) { +; SSE2-LABEL: test_ext_v2i64: +; SSE2: # %bb.0: +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm0[2,3,2,3] +; SSE2-NEXT: movq %xmm2, %rax +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: sarq $63, %rcx +; SSE2-NEXT: movq %xmm0, %rdx +; SSE2-NEXT: movq %rdx, %rsi +; SSE2-NEXT: sarq $63, %rsi +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %rdi +; SSE2-NEXT: movq %rdi, %r8 +; SSE2-NEXT: sarq $63, %r8 +; SSE2-NEXT: movq %xmm1, %r9 +; SSE2-NEXT: movq %r9, %r10 +; SSE2-NEXT: sarq $63, %r10 +; SSE2-NEXT: addq %r9, %rdx +; SSE2-NEXT: adcq %rsi, %r10 +; SSE2-NEXT: addq %rdi, %rax +; SSE2-NEXT: adcq %rcx, %r8 +; SSE2-NEXT: shldq $63, %rax, %r8 +; SSE2-NEXT: shldq $63, %rdx, %r10 +; SSE2-NEXT: movq %r10, %xmm0 +; SSE2-NEXT: movq %r8, %xmm1 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v2i64: +; SSE4: # %bb.0: +; SSE4-NEXT: movq %xmm0, %rax +; SSE4-NEXT: movq %rax, %rcx +; SSE4-NEXT: sarq $63, %rcx +; SSE4-NEXT: pextrq $1, %xmm0, %rdx +; SSE4-NEXT: movq %rdx, %rsi +; SSE4-NEXT: sarq $63, %rsi +; SSE4-NEXT: movq %xmm1, %rdi +; SSE4-NEXT: movq %rdi, %r8 +; SSE4-NEXT: sarq $63, %r8 +; SSE4-NEXT: pextrq $1, %xmm1, %r9 +; SSE4-NEXT: movq %r9, %r10 +; SSE4-NEXT: sarq $63, %r10 +; SSE4-NEXT: addq %r9, %rdx +; SSE4-NEXT: adcq %rsi, %r10 +; SSE4-NEXT: addq %rdi, %rax +; SSE4-NEXT: adcq %rcx, %r8 +; SSE4-NEXT: shldq $63, %rax, %r8 +; SSE4-NEXT: shldq $63, %rdx, %r10 +; SSE4-NEXT: movq %r10, %xmm1 +; SSE4-NEXT: movq %r8, %xmm0 +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE4-NEXT: retq +; +; AVX-LABEL: test_ext_v2i64: +; AVX: # %bb.0: +; AVX-NEXT: vmovq %xmm0, %rax +; AVX-NEXT: movq %rax, %rcx +; AVX-NEXT: sarq $63, %rcx +; AVX-NEXT: vpextrq $1, %xmm0, %rdx +; AVX-NEXT: movq %rdx, %rsi +; AVX-NEXT: sarq $63, %rsi +; AVX-NEXT: vmovq %xmm1, %rdi +; AVX-NEXT: movq %rdi, %r8 +; AVX-NEXT: sarq $63, %r8 +; AVX-NEXT: vpextrq $1, %xmm1, %r9 +; AVX-NEXT: movq %r9, %r10 +; AVX-NEXT: sarq $63, %r10 +; AVX-NEXT: addq %r9, %rdx +; AVX-NEXT: adcq %rsi, %r10 +; AVX-NEXT: addq %rdi, %rax +; AVX-NEXT: adcq %rcx, %r8 +; AVX-NEXT: shldq $63, %rax, %r8 +; AVX-NEXT: shldq $63, %rdx, %r10 +; AVX-NEXT: vmovq %r10, %xmm0 +; AVX-NEXT: vmovq %r8, %xmm1 +; AVX-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX-NEXT: retq + %x0 = sext <2 x i64> %a0 to <2 x i128> + %x1 = sext <2 x i64> %a1 to <2 x i128> + %sum = add <2 x i128> %x0, %x1 + %shift = ashr <2 x i128> %sum, <i128 1, i128 1> + %res = trunc <2 x i128> %shift to <2 x i64> + ret <2 x i64> %res +} + +; +; 256-bit vectors +; + +define <32 x i8> @test_fixed_v32i8(<32 x i8> %a0, <32 x i8> %a1) { +; SSE-LABEL: test_fixed_v32i8: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm1, %xmm4 +; SSE-NEXT: pand %xmm3, %xmm4 +; SSE-NEXT: movdqa %xmm0, %xmm5 +; SSE-NEXT: pand %xmm2, %xmm5 +; SSE-NEXT: pxor %xmm2, %xmm0 +; SSE-NEXT: pxor %xmm3, %xmm1 +; SSE-NEXT: psrlw $1, %xmm1 +; SSE-NEXT: movdqa {{.*#+}} xmm2 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; SSE-NEXT: pand %xmm2, %xmm1 +; SSE-NEXT: movdqa {{.*#+}} xmm3 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; SSE-NEXT: pxor %xmm3, %xmm1 +; SSE-NEXT: paddb %xmm4, %xmm1 +; SSE-NEXT: psrlw $1, %xmm0 +; SSE-NEXT: pand %xmm2, %xmm0 +; SSE-NEXT: pxor %xmm3, %xmm0 +; SSE-NEXT: paddb %xmm5, %xmm0 +; SSE-NEXT: psubb %xmm3, %xmm0 +; SSE-NEXT: psubb %xmm3, %xmm1 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v32i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vandps %ymm1, %ymm0, %ymm2 +; AVX1-NEXT: vxorps %ymm1, %ymm0, %ymm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm1 +; AVX1-NEXT: vbroadcastss {{.*#+}} xmm3 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; AVX1-NEXT: vpand %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vbroadcastss {{.*#+}} xmm4 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; AVX1-NEXT: vpxor %xmm4, %xmm1, %xmm1 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 +; AVX1-NEXT: vpxor %xmm4, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3 +; AVX1-NEXT: vpaddb %xmm3, %xmm0, %xmm0 +; AVX1-NEXT: vpsubb %xmm4, %xmm0, %xmm0 +; AVX1-NEXT: vpaddb %xmm2, %xmm1, %xmm1 +; AVX1-NEXT: vpsubb %xmm4, %xmm1, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v32i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %ymm1, %ymm0, %ymm2 +; AVX2-NEXT: vpxor %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 +; AVX2-NEXT: vpbroadcastb {{.*#+}} ymm1 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; AVX2-NEXT: vpxor %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpaddb %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpsubb %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v32i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpand %ymm1, %ymm0, %ymm2 +; AVX512-NEXT: vpxor %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX512-NEXT: vpbroadcastb {{.*#+}} ymm1 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; AVX512-NEXT: vpternlogd $108, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm1, %ymm0 +; AVX512-NEXT: vpaddb %ymm2, %ymm0, %ymm0 +; AVX512-NEXT: vpsubb %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: retq + %and = and <32 x i8> %a0, %a1 + %xor = xor <32 x i8> %a0, %a1 + %shift = ashr <32 x i8> %xor, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> + %res = add <32 x i8> %and, %shift + ret <32 x i8> %res +} + +define <32 x i8> @test_ext_v32i8(<32 x i8> %a0, <32 x i8> %a1) { +; SSE2-LABEL: test_ext_v32i8: +; SSE2: # %bb.0: +; SSE2-NEXT: punpcklbw {{.*#+}} xmm4 = xmm4[0],xmm1[0],xmm4[1],xmm1[1],xmm4[2],xmm1[2],xmm4[3],xmm1[3],xmm4[4],xmm1[4],xmm4[5],xmm1[5],xmm4[6],xmm1[6],xmm4[7],xmm1[7] +; SSE2-NEXT: psraw $8, %xmm4 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm1[8],xmm5[9],xmm1[9],xmm5[10],xmm1[10],xmm5[11],xmm1[11],xmm5[12],xmm1[12],xmm5[13],xmm1[13],xmm5[14],xmm1[14],xmm5[15],xmm1[15] +; SSE2-NEXT: psraw $8, %xmm5 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm6 = xmm6[0],xmm0[0],xmm6[1],xmm0[1],xmm6[2],xmm0[2],xmm6[3],xmm0[3],xmm6[4],xmm0[4],xmm6[5],xmm0[5],xmm6[6],xmm0[6],xmm6[7],xmm0[7] +; SSE2-NEXT: psraw $8, %xmm6 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm7 = xmm7[8],xmm0[8],xmm7[9],xmm0[9],xmm7[10],xmm0[10],xmm7[11],xmm0[11],xmm7[12],xmm0[12],xmm7[13],xmm0[13],xmm7[14],xmm0[14],xmm7[15],xmm0[15] +; SSE2-NEXT: psraw $8, %xmm7 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1],xmm1[2],xmm3[2],xmm1[3],xmm3[3],xmm1[4],xmm3[4],xmm1[5],xmm3[5],xmm1[6],xmm3[6],xmm1[7],xmm3[7] +; SSE2-NEXT: psraw $8, %xmm1 +; SSE2-NEXT: paddw %xmm4, %xmm1 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; SSE2-NEXT: psraw $8, %xmm3 +; SSE2-NEXT: paddw %xmm5, %xmm3 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3],xmm0[4],xmm2[4],xmm0[5],xmm2[5],xmm0[6],xmm2[6],xmm0[7],xmm2[7] +; SSE2-NEXT: psraw $8, %xmm0 +; SSE2-NEXT: paddw %xmm6, %xmm0 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; SSE2-NEXT: psraw $8, %xmm2 +; SSE2-NEXT: paddw %xmm7, %xmm2 +; SSE2-NEXT: psrlw $1, %xmm1 +; SSE2-NEXT: psrlw $1, %xmm3 +; SSE2-NEXT: psrlw $1, %xmm0 +; SSE2-NEXT: psrlw $1, %xmm2 +; SSE2-NEXT: movdqa {{.*#+}} xmm4 = [255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0] +; SSE2-NEXT: pand %xmm4, %xmm2 +; SSE2-NEXT: pand %xmm4, %xmm0 +; SSE2-NEXT: packuswb %xmm2, %xmm0 +; SSE2-NEXT: pand %xmm4, %xmm3 +; SSE2-NEXT: pand %xmm4, %xmm1 +; SSE2-NEXT: packuswb %xmm3, %xmm1 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v32i8: +; SSE4: # %bb.0: +; SSE4-NEXT: pshufd {{.*#+}} xmm4 = xmm1[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm4, %xmm5 +; SSE4-NEXT: pmovsxbw %xmm1, %xmm6 +; SSE4-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm1, %xmm7 +; SSE4-NEXT: pmovsxbw %xmm0, %xmm8 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm3[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm0, %xmm4 +; SSE4-NEXT: paddw %xmm5, %xmm4 +; SSE4-NEXT: pmovsxbw %xmm3, %xmm1 +; SSE4-NEXT: paddw %xmm6, %xmm1 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm2[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm0, %xmm3 +; SSE4-NEXT: paddw %xmm7, %xmm3 +; SSE4-NEXT: pmovsxbw %xmm2, %xmm0 +; SSE4-NEXT: paddw %xmm8, %xmm0 +; SSE4-NEXT: psrlw $1, %xmm4 +; SSE4-NEXT: psrlw $1, %xmm1 +; SSE4-NEXT: psrlw $1, %xmm3 +; SSE4-NEXT: psrlw $1, %xmm0 +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm2 = [255,255,255,255,255,255,255,255] +; SSE4-NEXT: pand %xmm2, %xmm0 +; SSE4-NEXT: pand %xmm2, %xmm3 +; SSE4-NEXT: packuswb %xmm3, %xmm0 +; SSE4-NEXT: pand %xmm2, %xmm1 +; SSE4-NEXT: pand %xmm2, %xmm4 +; SSE4-NEXT: packuswb %xmm4, %xmm1 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v32i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vpshufd {{.*#+}} xmm2 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm2, %xmm2 +; AVX1-NEXT: vpmovsxbw %xmm0, %xmm3 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpshufd {{.*#+}} xmm4 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm4, %xmm4 +; AVX1-NEXT: vpmovsxbw %xmm0, %xmm0 +; AVX1-NEXT: vpshufd {{.*#+}} xmm5 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm5, %xmm5 +; AVX1-NEXT: vpaddw %xmm5, %xmm2, %xmm2 +; AVX1-NEXT: vpmovsxbw %xmm1, %xmm5 +; AVX1-NEXT: vpaddw %xmm5, %xmm3, %xmm3 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpshufd {{.*#+}} xmm5 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm5, %xmm5 +; AVX1-NEXT: vpaddw %xmm5, %xmm4, %xmm4 +; AVX1-NEXT: vpmovsxbw %xmm1, %xmm1 +; AVX1-NEXT: vpaddw %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm2, %xmm1 +; AVX1-NEXT: vpsrlw $1, %xmm3, %xmm2 +; AVX1-NEXT: vpsrlw $1, %xmm4, %xmm3 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vbroadcastss {{.*#+}} xmm4 = [255,255,255,255,255,255,255,255] +; AVX1-NEXT: vpand %xmm4, %xmm0, %xmm0 +; AVX1-NEXT: vpand %xmm4, %xmm3, %xmm3 +; AVX1-NEXT: vpackuswb %xmm3, %xmm0, %xmm0 +; AVX1-NEXT: vpand %xmm4, %xmm2, %xmm2 +; AVX1-NEXT: vpand %xmm4, %xmm1, %xmm1 +; AVX1-NEXT: vpackuswb %xmm1, %xmm2, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v32i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovsxbw %xmm0, %ymm2 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX2-NEXT: vpmovsxbw %xmm0, %ymm0 +; AVX2-NEXT: vpmovsxbw %xmm1, %ymm3 +; AVX2-NEXT: vpaddw %ymm3, %ymm2, %ymm2 +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm1 +; AVX2-NEXT: vpmovsxbw %xmm1, %ymm1 +; AVX2-NEXT: vpaddw %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlw $1, %ymm2, %ymm1 +; AVX2-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpbroadcastw {{.*#+}} ymm2 = [255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0] +; AVX2-NEXT: vpand %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpand %ymm2, %ymm1, %ymm1 +; AVX2-NEXT: vpackuswb %ymm0, %ymm1, %ymm0 +; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,2,1,3] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v32i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovsxbw %ymm0, %zmm0 +; AVX512-NEXT: vpmovsxbw %ymm1, %zmm1 +; AVX512-NEXT: vpaddw %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlw $1, %zmm0, %zmm0 +; AVX512-NEXT: vpmovwb %zmm0, %ymm0 +; AVX512-NEXT: retq + %x0 = sext <32 x i8> %a0 to <32 x i16> + %x1 = sext <32 x i8> %a1 to <32 x i16> + %sum = add <32 x i16> %x0, %x1 + %shift = ashr <32 x i16> %sum, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = trunc <32 x i16> %shift to <32 x i8> + ret <32 x i8> %res +} + +define <16 x i16> @test_fixed_v16i16(<16 x i16> %a0, <16 x i16> %a1) { +; SSE-LABEL: test_fixed_v16i16: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm1, %xmm4 +; SSE-NEXT: pand %xmm3, %xmm4 +; SSE-NEXT: movdqa %xmm0, %xmm5 +; SSE-NEXT: pand %xmm2, %xmm5 +; SSE-NEXT: pxor %xmm2, %xmm0 +; SSE-NEXT: pxor %xmm3, %xmm1 +; SSE-NEXT: psraw $1, %xmm1 +; SSE-NEXT: paddw %xmm4, %xmm1 +; SSE-NEXT: psraw $1, %xmm0 +; SSE-NEXT: paddw %xmm5, %xmm0 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v16i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vandps %ymm1, %ymm0, %ymm2 +; AVX1-NEXT: vxorps %ymm0, %ymm1, %ymm0 +; AVX1-NEXT: vpsraw $1, %xmm0, %xmm1 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsraw $1, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3 +; AVX1-NEXT: vpaddw %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpaddw %xmm1, %xmm2, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v16i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %ymm1, %ymm0, %ymm2 +; AVX2-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX2-NEXT: vpsraw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpaddw %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v16i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vpand %ymm1, %ymm0, %ymm2 +; AVX512-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX512-NEXT: vpsraw $1, %ymm0, %ymm0 +; AVX512-NEXT: vpaddw %ymm0, %ymm2, %ymm0 +; AVX512-NEXT: retq + %and = and <16 x i16> %a0, %a1 + %xor = xor <16 x i16> %a1, %a0 + %shift = ashr <16 x i16> %xor, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = add <16 x i16> %and, %shift + ret <16 x i16> %res +} + +define <16 x i16> @test_ext_v16i16(<16 x i16> %a0, <16 x i16> %a1) { +; SSE2-LABEL: test_ext_v16i16: +; SSE2: # %bb.0: +; SSE2-NEXT: punpckhwd {{.*#+}} xmm4 = xmm4[4],xmm0[4],xmm4[5],xmm0[5],xmm4[6],xmm0[6],xmm4[7],xmm0[7] +; SSE2-NEXT: psrad $16, %xmm4 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm5 = xmm5[0],xmm0[0],xmm5[1],xmm0[1],xmm5[2],xmm0[2],xmm5[3],xmm0[3] +; SSE2-NEXT: psrad $16, %xmm5 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm6 = xmm6[4],xmm1[4],xmm6[5],xmm1[5],xmm6[6],xmm1[6],xmm6[7],xmm1[7] +; SSE2-NEXT: psrad $16, %xmm6 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm7 = xmm7[0],xmm1[0],xmm7[1],xmm1[1],xmm7[2],xmm1[2],xmm7[3],xmm1[3] +; SSE2-NEXT: psrad $16, %xmm7 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm8 = xmm8[4],xmm2[4],xmm8[5],xmm2[5],xmm8[6],xmm2[6],xmm8[7],xmm2[7] +; SSE2-NEXT: psrad $16, %xmm8 +; SSE2-NEXT: paddd %xmm4, %xmm8 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3] +; SSE2-NEXT: psrad $16, %xmm0 +; SSE2-NEXT: paddd %xmm5, %xmm0 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm2 = xmm2[4],xmm3[4],xmm2[5],xmm3[5],xmm2[6],xmm3[6],xmm2[7],xmm3[7] +; SSE2-NEXT: psrad $16, %xmm2 +; SSE2-NEXT: paddd %xmm6, %xmm2 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1],xmm1[2],xmm3[2],xmm1[3],xmm3[3] +; SSE2-NEXT: psrad $16, %xmm1 +; SSE2-NEXT: paddd %xmm7, %xmm1 +; SSE2-NEXT: pslld $15, %xmm8 +; SSE2-NEXT: psrad $16, %xmm8 +; SSE2-NEXT: pslld $15, %xmm0 +; SSE2-NEXT: psrad $16, %xmm0 +; SSE2-NEXT: packssdw %xmm8, %xmm0 +; SSE2-NEXT: pslld $15, %xmm2 +; SSE2-NEXT: psrad $16, %xmm2 +; SSE2-NEXT: pslld $15, %xmm1 +; SSE2-NEXT: psrad $16, %xmm1 +; SSE2-NEXT: packssdw %xmm2, %xmm1 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v16i16: +; SSE4: # %bb.0: +; SSE4-NEXT: pshufd {{.*#+}} xmm4 = xmm1[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm4, %xmm5 +; SSE4-NEXT: pmovsxwd %xmm1, %xmm6 +; SSE4-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm1, %xmm7 +; SSE4-NEXT: pmovsxwd %xmm0, %xmm8 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm3[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm0, %xmm4 +; SSE4-NEXT: paddd %xmm5, %xmm4 +; SSE4-NEXT: pmovsxwd %xmm3, %xmm1 +; SSE4-NEXT: paddd %xmm6, %xmm1 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm2[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm0, %xmm3 +; SSE4-NEXT: paddd %xmm7, %xmm3 +; SSE4-NEXT: pmovsxwd %xmm2, %xmm0 +; SSE4-NEXT: paddd %xmm8, %xmm0 +; SSE4-NEXT: psrld $1, %xmm4 +; SSE4-NEXT: psrld $1, %xmm1 +; SSE4-NEXT: psrld $1, %xmm3 +; SSE4-NEXT: psrld $1, %xmm0 +; SSE4-NEXT: pxor %xmm2, %xmm2 +; SSE4-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0],xmm2[1],xmm0[2],xmm2[3],xmm0[4],xmm2[5],xmm0[6],xmm2[7] +; SSE4-NEXT: pblendw {{.*#+}} xmm3 = xmm3[0],xmm2[1],xmm3[2],xmm2[3],xmm3[4],xmm2[5],xmm3[6],xmm2[7] +; SSE4-NEXT: packusdw %xmm3, %xmm0 +; SSE4-NEXT: pblendw {{.*#+}} xmm1 = xmm1[0],xmm2[1],xmm1[2],xmm2[3],xmm1[4],xmm2[5],xmm1[6],xmm2[7] +; SSE4-NEXT: pblendw {{.*#+}} xmm4 = xmm4[0],xmm2[1],xmm4[2],xmm2[3],xmm4[4],xmm2[5],xmm4[6],xmm2[7] +; SSE4-NEXT: packusdw %xmm4, %xmm1 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v16i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vpshufd {{.*#+}} xmm2 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm2, %xmm2 +; AVX1-NEXT: vpmovsxwd %xmm0, %xmm3 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpshufd {{.*#+}} xmm4 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm4, %xmm4 +; AVX1-NEXT: vpmovsxwd %xmm0, %xmm0 +; AVX1-NEXT: vpshufd {{.*#+}} xmm5 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm5, %xmm5 +; AVX1-NEXT: vpaddd %xmm5, %xmm2, %xmm2 +; AVX1-NEXT: vpmovsxwd %xmm1, %xmm5 +; AVX1-NEXT: vpaddd %xmm5, %xmm3, %xmm3 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpshufd {{.*#+}} xmm5 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm5, %xmm5 +; AVX1-NEXT: vpaddd %xmm5, %xmm4, %xmm4 +; AVX1-NEXT: vpmovsxwd %xmm1, %xmm1 +; AVX1-NEXT: vpaddd %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrld $1, %xmm2, %xmm1 +; AVX1-NEXT: vpsrld $1, %xmm3, %xmm2 +; AVX1-NEXT: vpsrld $1, %xmm4, %xmm3 +; AVX1-NEXT: vpsrld $1, %xmm0, %xmm0 +; AVX1-NEXT: vpxor %xmm4, %xmm4, %xmm4 +; AVX1-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0],xmm4[1],xmm0[2],xmm4[3],xmm0[4],xmm4[5],xmm0[6],xmm4[7] +; AVX1-NEXT: vpblendw {{.*#+}} xmm3 = xmm3[0],xmm4[1],xmm3[2],xmm4[3],xmm3[4],xmm4[5],xmm3[6],xmm4[7] +; AVX1-NEXT: vpackusdw %xmm3, %xmm0, %xmm0 +; AVX1-NEXT: vpblendw {{.*#+}} xmm2 = xmm2[0],xmm4[1],xmm2[2],xmm4[3],xmm2[4],xmm4[5],xmm2[6],xmm4[7] +; AVX1-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0],xmm4[1],xmm1[2],xmm4[3],xmm1[4],xmm4[5],xmm1[6],xmm4[7] +; AVX1-NEXT: vpackusdw %xmm1, %xmm2, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v16i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovsxwd %xmm0, %ymm2 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX2-NEXT: vpmovsxwd %xmm0, %ymm0 +; AVX2-NEXT: vpmovsxwd %xmm1, %ymm3 +; AVX2-NEXT: vpaddd %ymm3, %ymm2, %ymm2 +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm1 +; AVX2-NEXT: vpmovsxwd %xmm1, %ymm1 +; AVX2-NEXT: vpaddd %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrld $1, %ymm2, %ymm1 +; AVX2-NEXT: vpsrld $1, %ymm0, %ymm0 +; AVX2-NEXT: vpxor %xmm2, %xmm2, %xmm2 +; AVX2-NEXT: vpblendw {{.*#+}} ymm0 = ymm0[0],ymm2[1],ymm0[2],ymm2[3],ymm0[4],ymm2[5],ymm0[6],ymm2[7],ymm0[8],ymm2[9],ymm0[10],ymm2[11],ymm0[12],ymm2[13],ymm0[14],ymm2[15] +; AVX2-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0],ymm2[1],ymm1[2],ymm2[3],ymm1[4],ymm2[5],ymm1[6],ymm2[7],ymm1[8],ymm2[9],ymm1[10],ymm2[11],ymm1[12],ymm2[13],ymm1[14],ymm2[15] +; AVX2-NEXT: vpackusdw %ymm0, %ymm1, %ymm0 +; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,2,1,3] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v16i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovsxwd %ymm0, %zmm0 +; AVX512-NEXT: vpmovsxwd %ymm1, %zmm1 +; AVX512-NEXT: vpaddd %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrld $1, %zmm0, %zmm0 +; AVX512-NEXT: vpmovdw %zmm0, %ymm0 +; AVX512-NEXT: retq + %x0 = sext <16 x i16> %a0 to <16 x i32> + %x1 = sext <16 x i16> %a1 to <16 x i32> + %sum = add <16 x i32> %x0, %x1 + %shift = ashr <16 x i32> %sum, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = trunc <16 x i32> %shift to <16 x i16> + ret <16 x i16> %res +} + +define <8 x i32> @test_fixed_v8i32(<8 x i32> %a0, <8 x i32> %a1) { +; SSE-LABEL: test_fixed_v8i32: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm1, %xmm4 +; SSE-NEXT: pand %xmm3, %xmm4 +; SSE-NEXT: movdqa %xmm0, %xmm5 +; SSE-NEXT: pand %xmm2, %xmm5 +; SSE-NEXT: pxor %xmm2, %xmm0 +; SSE-NEXT: pxor %xmm3, %xmm1 +; SSE-NEXT: psrad $1, %xmm1 +; SSE-NEXT: paddd %xmm4, %xmm1 +; SSE-NEXT: psrad $1, %xmm0 +; SSE-NEXT: paddd %xmm5, %xmm0 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v8i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vandps %ymm1, %ymm0, %ymm2 +; AVX1-NEXT: vxorps %ymm0, %ymm1, %ymm0 +; AVX1-NEXT: vpsrad $1, %xmm0, %xmm1 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrad $1, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3 +; AVX1-NEXT: vpaddd %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpaddd %xmm1, %xmm2, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v8i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %ymm1, %ymm0, %ymm2 +; AVX2-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX2-NEXT: vpsrad $1, %ymm0, %ymm0 +; AVX2-NEXT: vpaddd %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v8i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vpand %ymm1, %ymm0, %ymm2 +; AVX512-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX512-NEXT: vpsrad $1, %ymm0, %ymm0 +; AVX512-NEXT: vpaddd %ymm0, %ymm2, %ymm0 +; AVX512-NEXT: retq + %and = and <8 x i32> %a0, %a1 + %xor = xor <8 x i32> %a1, %a0 + %shift = ashr <8 x i32> %xor, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = add <8 x i32> %and, %shift + ret <8 x i32> %res +} + +define <8 x i32> @test_ext_v8i32(<8 x i32> %a0, <8 x i32> %a1) { +; SSE2-LABEL: test_ext_v8i32: +; SSE2: # %bb.0: +; SSE2-NEXT: pxor %xmm4, %xmm4 +; SSE2-NEXT: pxor %xmm5, %xmm5 +; SSE2-NEXT: pcmpgtd %xmm1, %xmm5 +; SSE2-NEXT: pshufd {{.*#+}} xmm6 = xmm1[2,3,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm5[0],xmm1[1],xmm5[1] +; SSE2-NEXT: pxor %xmm5, %xmm5 +; SSE2-NEXT: pcmpgtd %xmm6, %xmm5 +; SSE2-NEXT: punpckldq {{.*#+}} xmm6 = xmm6[0],xmm5[0],xmm6[1],xmm5[1] +; SSE2-NEXT: pxor %xmm5, %xmm5 +; SSE2-NEXT: pcmpgtd %xmm0, %xmm5 +; SSE2-NEXT: pshufd {{.*#+}} xmm7 = xmm0[2,3,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm5[0],xmm0[1],xmm5[1] +; SSE2-NEXT: pxor %xmm5, %xmm5 +; SSE2-NEXT: pcmpgtd %xmm7, %xmm5 +; SSE2-NEXT: punpckldq {{.*#+}} xmm7 = xmm7[0],xmm5[0],xmm7[1],xmm5[1] +; SSE2-NEXT: pxor %xmm5, %xmm5 +; SSE2-NEXT: pcmpgtd %xmm3, %xmm5 +; SSE2-NEXT: pshufd {{.*#+}} xmm8 = xmm3[2,3,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm5[0],xmm3[1],xmm5[1] +; SSE2-NEXT: paddq %xmm3, %xmm1 +; SSE2-NEXT: pxor %xmm3, %xmm3 +; SSE2-NEXT: pcmpgtd %xmm8, %xmm3 +; SSE2-NEXT: punpckldq {{.*#+}} xmm8 = xmm8[0],xmm3[0],xmm8[1],xmm3[1] +; SSE2-NEXT: paddq %xmm6, %xmm8 +; SSE2-NEXT: pxor %xmm3, %xmm3 +; SSE2-NEXT: pcmpgtd %xmm2, %xmm3 +; SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm2[2,3,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm3[0],xmm2[1],xmm3[1] +; SSE2-NEXT: paddq %xmm2, %xmm0 +; SSE2-NEXT: pcmpgtd %xmm5, %xmm4 +; SSE2-NEXT: punpckldq {{.*#+}} xmm5 = xmm5[0],xmm4[0],xmm5[1],xmm4[1] +; SSE2-NEXT: paddq %xmm7, %xmm5 +; SSE2-NEXT: psrlq $1, %xmm1 +; SSE2-NEXT: psrlq $1, %xmm8 +; SSE2-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm8[0,2] +; SSE2-NEXT: psrlq $1, %xmm0 +; SSE2-NEXT: psrlq $1, %xmm5 +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm5[0,2] +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v8i32: +; SSE4: # %bb.0: +; SSE4-NEXT: pmovsxdq %xmm1, %xmm4 +; SSE4-NEXT: pshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm1, %xmm5 +; SSE4-NEXT: pmovsxdq %xmm0, %xmm6 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm0, %xmm7 +; SSE4-NEXT: pmovsxdq %xmm3, %xmm1 +; SSE4-NEXT: paddq %xmm4, %xmm1 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm3[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm0, %xmm3 +; SSE4-NEXT: paddq %xmm5, %xmm3 +; SSE4-NEXT: pmovsxdq %xmm2, %xmm0 +; SSE4-NEXT: paddq %xmm6, %xmm0 +; SSE4-NEXT: pshufd {{.*#+}} xmm2 = xmm2[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm2, %xmm2 +; SSE4-NEXT: paddq %xmm7, %xmm2 +; SSE4-NEXT: psrlq $1, %xmm1 +; SSE4-NEXT: psrlq $1, %xmm3 +; SSE4-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm3[0,2] +; SSE4-NEXT: psrlq $1, %xmm0 +; SSE4-NEXT: psrlq $1, %xmm2 +; SSE4-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm2[0,2] +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v8i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm2 +; AVX1-NEXT: vpshufd {{.*#+}} xmm3 = xmm2[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm3, %xmm3 +; AVX1-NEXT: vpshufd {{.*#+}} xmm4 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm4, %xmm4 +; AVX1-NEXT: vpmovsxdq %xmm2, %xmm2 +; AVX1-NEXT: vpmovsxdq %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm5 +; AVX1-NEXT: vpshufd {{.*#+}} xmm6 = xmm5[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm6, %xmm6 +; AVX1-NEXT: vpaddq %xmm6, %xmm3, %xmm3 +; AVX1-NEXT: vpshufd {{.*#+}} xmm6 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm6, %xmm6 +; AVX1-NEXT: vpaddq %xmm6, %xmm4, %xmm4 +; AVX1-NEXT: vpmovsxdq %xmm5, %xmm5 +; AVX1-NEXT: vpaddq %xmm5, %xmm2, %xmm2 +; AVX1-NEXT: vpmovsxdq %xmm1, %xmm1 +; AVX1-NEXT: vpaddq %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlq $1, %xmm3, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm4, %xmm3 +; AVX1-NEXT: vpsrlq $1, %xmm2, %xmm2 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm3, %ymm1 +; AVX1-NEXT: vshufps {{.*#+}} ymm0 = ymm0[0,2],ymm1[0,2],ymm0[4,6],ymm1[4,6] +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v8i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm2 +; AVX2-NEXT: vpmovsxdq %xmm2, %ymm2 +; AVX2-NEXT: vpmovsxdq %xmm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm3 +; AVX2-NEXT: vpmovsxdq %xmm3, %ymm3 +; AVX2-NEXT: vpaddq %ymm3, %ymm2, %ymm2 +; AVX2-NEXT: vpmovsxdq %xmm1, %ymm1 +; AVX2-NEXT: vpaddq %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vperm2i128 {{.*#+}} ymm1 = ymm0[2,3],ymm2[2,3] +; AVX2-NEXT: vpsrlq $1, %ymm1, %ymm1 +; AVX2-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vshufps {{.*#+}} ymm0 = ymm0[0,2],ymm1[0,2],ymm0[4,6],ymm1[4,6] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v8i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovsxdq %ymm0, %zmm0 +; AVX512-NEXT: vpmovsxdq %ymm1, %zmm1 +; AVX512-NEXT: vpaddq %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlq $1, %zmm0, %zmm0 +; AVX512-NEXT: vpmovqd %zmm0, %ymm0 +; AVX512-NEXT: retq + %x0 = sext <8 x i32> %a0 to <8 x i64> + %x1 = sext <8 x i32> %a1 to <8 x i64> + %sum = add <8 x i64> %x0, %x1 + %shift = ashr <8 x i64> %sum, <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1> + %res = trunc <8 x i64> %shift to <8 x i32> + ret <8 x i32> %res +} + +define <4 x i64> @test_fixed_v4i64(<4 x i64> %a0, <4 x i64> %a1) { +; SSE2-LABEL: test_fixed_v4i64: +; SSE2: # %bb.0: +; SSE2-NEXT: movdqa %xmm1, %xmm4 +; SSE2-NEXT: pand %xmm3, %xmm4 +; SSE2-NEXT: movdqa %xmm0, %xmm5 +; SSE2-NEXT: pand %xmm2, %xmm5 +; SSE2-NEXT: pxor %xmm0, %xmm2 +; SSE2-NEXT: pxor %xmm1, %xmm3 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm3[1,3,2,3] +; SSE2-NEXT: psrad $1, %xmm0 +; SSE2-NEXT: psrlq $1, %xmm3 +; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm3[0,2,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] +; SSE2-NEXT: paddq %xmm4, %xmm1 +; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm2[1,3,2,3] +; SSE2-NEXT: psrad $1, %xmm3 +; SSE2-NEXT: psrlq $1, %xmm2 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm2[0,2,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1] +; SSE2-NEXT: paddq %xmm5, %xmm0 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_fixed_v4i64: +; SSE4: # %bb.0: +; SSE4-NEXT: movdqa %xmm1, %xmm4 +; SSE4-NEXT: pand %xmm3, %xmm4 +; SSE4-NEXT: movdqa %xmm0, %xmm5 +; SSE4-NEXT: pand %xmm2, %xmm5 +; SSE4-NEXT: pxor %xmm2, %xmm0 +; SSE4-NEXT: pxor %xmm3, %xmm1 +; SSE4-NEXT: movdqa %xmm1, %xmm2 +; SSE4-NEXT: psrad $1, %xmm2 +; SSE4-NEXT: psrlq $1, %xmm1 +; SSE4-NEXT: pblendw {{.*#+}} xmm1 = xmm1[0,1],xmm2[2,3],xmm1[4,5],xmm2[6,7] +; SSE4-NEXT: paddq %xmm4, %xmm1 +; SSE4-NEXT: movdqa %xmm0, %xmm2 +; SSE4-NEXT: psrad $1, %xmm2 +; SSE4-NEXT: psrlq $1, %xmm0 +; SSE4-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm2[2,3],xmm0[4,5],xmm2[6,7] +; SSE4-NEXT: paddq %xmm5, %xmm0 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_fixed_v4i64: +; AVX1: # %bb.0: +; AVX1-NEXT: vandps %ymm1, %ymm0, %ymm2 +; AVX1-NEXT: vxorps %ymm0, %ymm1, %ymm0 +; AVX1-NEXT: vpsrad $1, %xmm0, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm3 +; AVX1-NEXT: vpblendw {{.*#+}} xmm1 = xmm3[0,1],xmm1[2,3],xmm3[4,5],xmm1[6,7] +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrad $1, %xmm0, %xmm3 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0,1],xmm3[2,3],xmm0[4,5],xmm3[6,7] +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3 +; AVX1-NEXT: vpaddq %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpaddq %xmm1, %xmm2, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v4i64: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %ymm1, %ymm0, %ymm2 +; AVX2-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX2-NEXT: vpsrad $1, %ymm0, %ymm1 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vpblendd {{.*#+}} ymm0 = ymm0[0],ymm1[1],ymm0[2],ymm1[3],ymm0[4],ymm1[5],ymm0[6],ymm1[7] +; AVX2-NEXT: vpaddq %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v4i64: +; AVX512: # %bb.0: +; AVX512-NEXT: vpand %ymm1, %ymm0, %ymm2 +; AVX512-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX512-NEXT: vpsraq $1, %ymm0, %ymm0 +; AVX512-NEXT: vpaddq %ymm0, %ymm2, %ymm0 +; AVX512-NEXT: retq + %and = and <4 x i64> %a0, %a1 + %xor = xor <4 x i64> %a1, %a0 + %shift = ashr <4 x i64> %xor, <i64 1, i64 1, i64 1, i64 1> + %res = add <4 x i64> %and, %shift + ret <4 x i64> %res +} + +define <4 x i64> @test_ext_v4i64(<4 x i64> %a0, <4 x i64> %a1) { +; SSE2-LABEL: test_ext_v4i64: +; SSE2: # %bb.0: +; SSE2-NEXT: pushq %rbp +; SSE2-NEXT: .cfi_def_cfa_offset 16 +; SSE2-NEXT: pushq %r15 +; SSE2-NEXT: .cfi_def_cfa_offset 24 +; SSE2-NEXT: pushq %r14 +; SSE2-NEXT: .cfi_def_cfa_offset 32 +; SSE2-NEXT: pushq %r13 +; SSE2-NEXT: .cfi_def_cfa_offset 40 +; SSE2-NEXT: pushq %r12 +; SSE2-NEXT: .cfi_def_cfa_offset 48 +; SSE2-NEXT: pushq %rbx +; SSE2-NEXT: .cfi_def_cfa_offset 56 +; SSE2-NEXT: .cfi_offset %rbx, -56 +; SSE2-NEXT: .cfi_offset %r12, -48 +; SSE2-NEXT: .cfi_offset %r13, -40 +; SSE2-NEXT: .cfi_offset %r14, -32 +; SSE2-NEXT: .cfi_offset %r15, -24 +; SSE2-NEXT: .cfi_offset %rbp, -16 +; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm1[2,3,2,3] +; SSE2-NEXT: movq %xmm4, %rdx +; SSE2-NEXT: movq %rdx, %r14 +; SSE2-NEXT: sarq $63, %r14 +; SSE2-NEXT: movq %xmm1, %rcx +; SSE2-NEXT: movq %rcx, %r10 +; SSE2-NEXT: sarq $63, %r10 +; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] +; SSE2-NEXT: movq %xmm1, %rsi +; SSE2-NEXT: movq %rsi, %r11 +; SSE2-NEXT: sarq $63, %r11 +; SSE2-NEXT: movq %xmm0, %r8 +; SSE2-NEXT: movq %r8, %rbx +; SSE2-NEXT: sarq $63, %rbx +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm3[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %rdi +; SSE2-NEXT: movq %rdi, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: sarq $63, %rdi +; SSE2-NEXT: movq %xmm3, %r15 +; SSE2-NEXT: movq %r15, %r9 +; SSE2-NEXT: sarq $63, %r9 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm2[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %r12 +; SSE2-NEXT: movq %r12, %r13 +; SSE2-NEXT: sarq $63, %r13 +; SSE2-NEXT: movq %xmm2, %rax +; SSE2-NEXT: movq %rax, %rbp +; SSE2-NEXT: sarq $63, %rbp +; SSE2-NEXT: addq %rax, %r8 +; SSE2-NEXT: adcq %rbx, %rbp +; SSE2-NEXT: addq %r12, %rsi +; SSE2-NEXT: adcq %r11, %r13 +; SSE2-NEXT: addq %r15, %rcx +; SSE2-NEXT: adcq %r10, %r9 +; SSE2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rdx # 8-byte Folded Reload +; SSE2-NEXT: adcq %r14, %rdi +; SSE2-NEXT: shldq $63, %rdx, %rdi +; SSE2-NEXT: shldq $63, %rcx, %r9 +; SSE2-NEXT: shldq $63, %rsi, %r13 +; SSE2-NEXT: shldq $63, %r8, %rbp +; SSE2-NEXT: movq %rbp, %xmm0 +; SSE2-NEXT: movq %r13, %xmm2 +; SSE2-NEXT: movq %r9, %xmm1 +; SSE2-NEXT: movq %rdi, %xmm3 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm2[0] +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm3[0] +; SSE2-NEXT: popq %rbx +; SSE2-NEXT: .cfi_def_cfa_offset 48 +; SSE2-NEXT: popq %r12 +; SSE2-NEXT: .cfi_def_cfa_offset 40 +; SSE2-NEXT: popq %r13 +; SSE2-NEXT: .cfi_def_cfa_offset 32 +; SSE2-NEXT: popq %r14 +; SSE2-NEXT: .cfi_def_cfa_offset 24 +; SSE2-NEXT: popq %r15 +; SSE2-NEXT: .cfi_def_cfa_offset 16 +; SSE2-NEXT: popq %rbp +; SSE2-NEXT: .cfi_def_cfa_offset 8 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v4i64: +; SSE4: # %bb.0: +; SSE4-NEXT: pushq %rbp +; SSE4-NEXT: .cfi_def_cfa_offset 16 +; SSE4-NEXT: pushq %r15 +; SSE4-NEXT: .cfi_def_cfa_offset 24 +; SSE4-NEXT: pushq %r14 +; SSE4-NEXT: .cfi_def_cfa_offset 32 +; SSE4-NEXT: pushq %r13 +; SSE4-NEXT: .cfi_def_cfa_offset 40 +; SSE4-NEXT: pushq %r12 +; SSE4-NEXT: .cfi_def_cfa_offset 48 +; SSE4-NEXT: pushq %rbx +; SSE4-NEXT: .cfi_def_cfa_offset 56 +; SSE4-NEXT: .cfi_offset %rbx, -56 +; SSE4-NEXT: .cfi_offset %r12, -48 +; SSE4-NEXT: .cfi_offset %r13, -40 +; SSE4-NEXT: .cfi_offset %r14, -32 +; SSE4-NEXT: .cfi_offset %r15, -24 +; SSE4-NEXT: .cfi_offset %rbp, -16 +; SSE4-NEXT: movq %xmm1, %rdi +; SSE4-NEXT: movq %rdi, %r14 +; SSE4-NEXT: sarq $63, %r14 +; SSE4-NEXT: pextrq $1, %xmm1, %rcx +; SSE4-NEXT: movq %rcx, %r10 +; SSE4-NEXT: sarq $63, %r10 +; SSE4-NEXT: movq %xmm0, %rsi +; SSE4-NEXT: movq %rsi, %r11 +; SSE4-NEXT: sarq $63, %r11 +; SSE4-NEXT: pextrq $1, %xmm0, %r8 +; SSE4-NEXT: movq %r8, %rbx +; SSE4-NEXT: sarq $63, %rbx +; SSE4-NEXT: movq %xmm3, %rdx +; SSE4-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: sarq $63, %rdx +; SSE4-NEXT: pextrq $1, %xmm3, %r15 +; SSE4-NEXT: movq %r15, %r9 +; SSE4-NEXT: sarq $63, %r9 +; SSE4-NEXT: movq %xmm2, %r12 +; SSE4-NEXT: movq %r12, %r13 +; SSE4-NEXT: sarq $63, %r13 +; SSE4-NEXT: pextrq $1, %xmm2, %rax +; SSE4-NEXT: movq %rax, %rbp +; SSE4-NEXT: sarq $63, %rbp +; SSE4-NEXT: addq %rax, %r8 +; SSE4-NEXT: adcq %rbx, %rbp +; SSE4-NEXT: addq %r12, %rsi +; SSE4-NEXT: adcq %r11, %r13 +; SSE4-NEXT: addq %r15, %rcx +; SSE4-NEXT: adcq %r10, %r9 +; SSE4-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rdi # 8-byte Folded Reload +; SSE4-NEXT: adcq %r14, %rdx +; SSE4-NEXT: shldq $63, %rdi, %rdx +; SSE4-NEXT: shldq $63, %rcx, %r9 +; SSE4-NEXT: shldq $63, %rsi, %r13 +; SSE4-NEXT: shldq $63, %r8, %rbp +; SSE4-NEXT: movq %rbp, %xmm2 +; SSE4-NEXT: movq %r13, %xmm0 +; SSE4-NEXT: movq %r9, %xmm3 +; SSE4-NEXT: movq %rdx, %xmm1 +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm2[0] +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm3[0] +; SSE4-NEXT: popq %rbx +; SSE4-NEXT: .cfi_def_cfa_offset 48 +; SSE4-NEXT: popq %r12 +; SSE4-NEXT: .cfi_def_cfa_offset 40 +; SSE4-NEXT: popq %r13 +; SSE4-NEXT: .cfi_def_cfa_offset 32 +; SSE4-NEXT: popq %r14 +; SSE4-NEXT: .cfi_def_cfa_offset 24 +; SSE4-NEXT: popq %r15 +; SSE4-NEXT: .cfi_def_cfa_offset 16 +; SSE4-NEXT: popq %rbp +; SSE4-NEXT: .cfi_def_cfa_offset 8 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v4i64: +; AVX1: # %bb.0: +; AVX1-NEXT: pushq %rbp +; AVX1-NEXT: .cfi_def_cfa_offset 16 +; AVX1-NEXT: pushq %r15 +; AVX1-NEXT: .cfi_def_cfa_offset 24 +; AVX1-NEXT: pushq %r14 +; AVX1-NEXT: .cfi_def_cfa_offset 32 +; AVX1-NEXT: pushq %r13 +; AVX1-NEXT: .cfi_def_cfa_offset 40 +; AVX1-NEXT: pushq %r12 +; AVX1-NEXT: .cfi_def_cfa_offset 48 +; AVX1-NEXT: pushq %rbx +; AVX1-NEXT: .cfi_def_cfa_offset 56 +; AVX1-NEXT: .cfi_offset %rbx, -56 +; AVX1-NEXT: .cfi_offset %r12, -48 +; AVX1-NEXT: .cfi_offset %r13, -40 +; AVX1-NEXT: .cfi_offset %r14, -32 +; AVX1-NEXT: .cfi_offset %r15, -24 +; AVX1-NEXT: .cfi_offset %rbp, -16 +; AVX1-NEXT: vmovq %xmm0, %rdx +; AVX1-NEXT: movq %rdx, %r14 +; AVX1-NEXT: sarq $63, %r14 +; AVX1-NEXT: vpextrq $1, %xmm0, %rcx +; AVX1-NEXT: movq %rcx, %r10 +; AVX1-NEXT: sarq $63, %r10 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vmovq %xmm0, %rsi +; AVX1-NEXT: movq %rsi, %r11 +; AVX1-NEXT: sarq $63, %r11 +; AVX1-NEXT: vpextrq $1, %xmm0, %rdi +; AVX1-NEXT: movq %rdi, %rbx +; AVX1-NEXT: sarq $63, %rbx +; AVX1-NEXT: vmovq %xmm1, %r8 +; AVX1-NEXT: movq %r8, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: sarq $63, %r8 +; AVX1-NEXT: vpextrq $1, %xmm1, %r15 +; AVX1-NEXT: movq %r15, %r9 +; AVX1-NEXT: sarq $63, %r9 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm0 +; AVX1-NEXT: vmovq %xmm0, %r12 +; AVX1-NEXT: movq %r12, %r13 +; AVX1-NEXT: sarq $63, %r13 +; AVX1-NEXT: vpextrq $1, %xmm0, %rax +; AVX1-NEXT: movq %rax, %rbp +; AVX1-NEXT: sarq $63, %rbp +; AVX1-NEXT: addq %rax, %rdi +; AVX1-NEXT: adcq %rbx, %rbp +; AVX1-NEXT: addq %r12, %rsi +; AVX1-NEXT: adcq %r11, %r13 +; AVX1-NEXT: addq %r15, %rcx +; AVX1-NEXT: adcq %r10, %r9 +; AVX1-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rdx # 8-byte Folded Reload +; AVX1-NEXT: adcq %r14, %r8 +; AVX1-NEXT: shldq $63, %rdx, %r8 +; AVX1-NEXT: shldq $63, %rcx, %r9 +; AVX1-NEXT: shldq $63, %rsi, %r13 +; AVX1-NEXT: shldq $63, %rdi, %rbp +; AVX1-NEXT: vmovq %rbp, %xmm0 +; AVX1-NEXT: vmovq %r13, %xmm1 +; AVX1-NEXT: vmovq %r9, %xmm2 +; AVX1-NEXT: vmovq %r8, %xmm3 +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm3[0],xmm2[0] +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: popq %rbx +; AVX1-NEXT: .cfi_def_cfa_offset 48 +; AVX1-NEXT: popq %r12 +; AVX1-NEXT: .cfi_def_cfa_offset 40 +; AVX1-NEXT: popq %r13 +; AVX1-NEXT: .cfi_def_cfa_offset 32 +; AVX1-NEXT: popq %r14 +; AVX1-NEXT: .cfi_def_cfa_offset 24 +; AVX1-NEXT: popq %r15 +; AVX1-NEXT: .cfi_def_cfa_offset 16 +; AVX1-NEXT: popq %rbp +; AVX1-NEXT: .cfi_def_cfa_offset 8 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v4i64: +; AVX2: # %bb.0: +; AVX2-NEXT: pushq %rbp +; AVX2-NEXT: .cfi_def_cfa_offset 16 +; AVX2-NEXT: pushq %r15 +; AVX2-NEXT: .cfi_def_cfa_offset 24 +; AVX2-NEXT: pushq %r14 +; AVX2-NEXT: .cfi_def_cfa_offset 32 +; AVX2-NEXT: pushq %r13 +; AVX2-NEXT: .cfi_def_cfa_offset 40 +; AVX2-NEXT: pushq %r12 +; AVX2-NEXT: .cfi_def_cfa_offset 48 +; AVX2-NEXT: pushq %rbx +; AVX2-NEXT: .cfi_def_cfa_offset 56 +; AVX2-NEXT: .cfi_offset %rbx, -56 +; AVX2-NEXT: .cfi_offset %r12, -48 +; AVX2-NEXT: .cfi_offset %r13, -40 +; AVX2-NEXT: .cfi_offset %r14, -32 +; AVX2-NEXT: .cfi_offset %r15, -24 +; AVX2-NEXT: .cfi_offset %rbp, -16 +; AVX2-NEXT: vmovq %xmm0, %rdx +; AVX2-NEXT: movq %rdx, %r14 +; AVX2-NEXT: sarq $63, %r14 +; AVX2-NEXT: vpextrq $1, %xmm0, %rcx +; AVX2-NEXT: movq %rcx, %r10 +; AVX2-NEXT: sarq $63, %r10 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX2-NEXT: vmovq %xmm0, %rsi +; AVX2-NEXT: movq %rsi, %r11 +; AVX2-NEXT: sarq $63, %r11 +; AVX2-NEXT: vpextrq $1, %xmm0, %rdi +; AVX2-NEXT: movq %rdi, %rbx +; AVX2-NEXT: sarq $63, %rbx +; AVX2-NEXT: vmovq %xmm1, %r8 +; AVX2-NEXT: movq %r8, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: sarq $63, %r8 +; AVX2-NEXT: vpextrq $1, %xmm1, %r15 +; AVX2-NEXT: movq %r15, %r9 +; AVX2-NEXT: sarq $63, %r9 +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm0 +; AVX2-NEXT: vmovq %xmm0, %r12 +; AVX2-NEXT: movq %r12, %r13 +; AVX2-NEXT: sarq $63, %r13 +; AVX2-NEXT: vpextrq $1, %xmm0, %rax +; AVX2-NEXT: movq %rax, %rbp +; AVX2-NEXT: sarq $63, %rbp +; AVX2-NEXT: addq %rax, %rdi +; AVX2-NEXT: adcq %rbx, %rbp +; AVX2-NEXT: addq %r12, %rsi +; AVX2-NEXT: adcq %r11, %r13 +; AVX2-NEXT: addq %r15, %rcx +; AVX2-NEXT: adcq %r10, %r9 +; AVX2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rdx # 8-byte Folded Reload +; AVX2-NEXT: adcq %r14, %r8 +; AVX2-NEXT: shldq $63, %rdx, %r8 +; AVX2-NEXT: shldq $63, %rcx, %r9 +; AVX2-NEXT: shldq $63, %rsi, %r13 +; AVX2-NEXT: shldq $63, %rdi, %rbp +; AVX2-NEXT: vmovq %rbp, %xmm0 +; AVX2-NEXT: vmovq %r13, %xmm1 +; AVX2-NEXT: vmovq %r9, %xmm2 +; AVX2-NEXT: vmovq %r8, %xmm3 +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm3[0],xmm2[0] +; AVX2-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0 +; AVX2-NEXT: popq %rbx +; AVX2-NEXT: .cfi_def_cfa_offset 48 +; AVX2-NEXT: popq %r12 +; AVX2-NEXT: .cfi_def_cfa_offset 40 +; AVX2-NEXT: popq %r13 +; AVX2-NEXT: .cfi_def_cfa_offset 32 +; AVX2-NEXT: popq %r14 +; AVX2-NEXT: .cfi_def_cfa_offset 24 +; AVX2-NEXT: popq %r15 +; AVX2-NEXT: .cfi_def_cfa_offset 16 +; AVX2-NEXT: popq %rbp +; AVX2-NEXT: .cfi_def_cfa_offset 8 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v4i64: +; AVX512: # %bb.0: +; AVX512-NEXT: pushq %rbp +; AVX512-NEXT: .cfi_def_cfa_offset 16 +; AVX512-NEXT: pushq %r15 +; AVX512-NEXT: .cfi_def_cfa_offset 24 +; AVX512-NEXT: pushq %r14 +; AVX512-NEXT: .cfi_def_cfa_offset 32 +; AVX512-NEXT: pushq %r13 +; AVX512-NEXT: .cfi_def_cfa_offset 40 +; AVX512-NEXT: pushq %r12 +; AVX512-NEXT: .cfi_def_cfa_offset 48 +; AVX512-NEXT: pushq %rbx +; AVX512-NEXT: .cfi_def_cfa_offset 56 +; AVX512-NEXT: .cfi_offset %rbx, -56 +; AVX512-NEXT: .cfi_offset %r12, -48 +; AVX512-NEXT: .cfi_offset %r13, -40 +; AVX512-NEXT: .cfi_offset %r14, -32 +; AVX512-NEXT: .cfi_offset %r15, -24 +; AVX512-NEXT: .cfi_offset %rbp, -16 +; AVX512-NEXT: vmovq %xmm0, %rdx +; AVX512-NEXT: movq %rdx, %r14 +; AVX512-NEXT: sarq $63, %r14 +; AVX512-NEXT: vpextrq $1, %xmm0, %rcx +; AVX512-NEXT: movq %rcx, %r10 +; AVX512-NEXT: sarq $63, %r10 +; AVX512-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX512-NEXT: vmovq %xmm0, %rsi +; AVX512-NEXT: movq %rsi, %r11 +; AVX512-NEXT: sarq $63, %r11 +; AVX512-NEXT: vpextrq $1, %xmm0, %rdi +; AVX512-NEXT: movq %rdi, %rbx +; AVX512-NEXT: sarq $63, %rbx +; AVX512-NEXT: vmovq %xmm1, %r8 +; AVX512-NEXT: movq %r8, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: sarq $63, %r8 +; AVX512-NEXT: vpextrq $1, %xmm1, %r15 +; AVX512-NEXT: movq %r15, %r9 +; AVX512-NEXT: sarq $63, %r9 +; AVX512-NEXT: vextracti128 $1, %ymm1, %xmm0 +; AVX512-NEXT: vmovq %xmm0, %r12 +; AVX512-NEXT: movq %r12, %r13 +; AVX512-NEXT: sarq $63, %r13 +; AVX512-NEXT: vpextrq $1, %xmm0, %rax +; AVX512-NEXT: movq %rax, %rbp +; AVX512-NEXT: sarq $63, %rbp +; AVX512-NEXT: addq %rax, %rdi +; AVX512-NEXT: adcq %rbx, %rbp +; AVX512-NEXT: addq %r12, %rsi +; AVX512-NEXT: adcq %r11, %r13 +; AVX512-NEXT: addq %r15, %rcx +; AVX512-NEXT: adcq %r10, %r9 +; AVX512-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rdx # 8-byte Folded Reload +; AVX512-NEXT: adcq %r14, %r8 +; AVX512-NEXT: shldq $63, %rdx, %r8 +; AVX512-NEXT: shldq $63, %rcx, %r9 +; AVX512-NEXT: shldq $63, %rsi, %r13 +; AVX512-NEXT: shldq $63, %rdi, %rbp +; AVX512-NEXT: vmovq %rbp, %xmm0 +; AVX512-NEXT: vmovq %r13, %xmm1 +; AVX512-NEXT: vmovq %r9, %xmm2 +; AVX512-NEXT: vmovq %r8, %xmm3 +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm3[0],xmm2[0] +; AVX512-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0 +; AVX512-NEXT: popq %rbx +; AVX512-NEXT: .cfi_def_cfa_offset 48 +; AVX512-NEXT: popq %r12 +; AVX512-NEXT: .cfi_def_cfa_offset 40 +; AVX512-NEXT: popq %r13 +; AVX512-NEXT: .cfi_def_cfa_offset 32 +; AVX512-NEXT: popq %r14 +; AVX512-NEXT: .cfi_def_cfa_offset 24 +; AVX512-NEXT: popq %r15 +; AVX512-NEXT: .cfi_def_cfa_offset 16 +; AVX512-NEXT: popq %rbp +; AVX512-NEXT: .cfi_def_cfa_offset 8 +; AVX512-NEXT: retq + %x0 = sext <4 x i64> %a0 to <4 x i128> + %x1 = sext <4 x i64> %a1 to <4 x i128> + %sum = add <4 x i128> %x0, %x1 + %shift = ashr <4 x i128> %sum, <i128 1, i128 1, i128 1, i128 1> + %res = trunc <4 x i128> %shift to <4 x i64> + ret <4 x i64> %res +} + +; +; 512-bit vectors +; + +define <64 x i8> @test_fixed_v64i8(<64 x i8> %a0, <64 x i8> %a1) { +; SSE-LABEL: test_fixed_v64i8: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm3, %xmm10 +; SSE-NEXT: pand %xmm7, %xmm10 +; SSE-NEXT: movdqa %xmm2, %xmm11 +; SSE-NEXT: pand %xmm6, %xmm11 +; SSE-NEXT: movdqa %xmm1, %xmm9 +; SSE-NEXT: pand %xmm5, %xmm9 +; SSE-NEXT: movdqa %xmm0, %xmm8 +; SSE-NEXT: pand %xmm4, %xmm8 +; SSE-NEXT: pxor %xmm4, %xmm0 +; SSE-NEXT: pxor %xmm5, %xmm1 +; SSE-NEXT: pxor %xmm6, %xmm2 +; SSE-NEXT: pxor %xmm7, %xmm3 +; SSE-NEXT: psrlw $1, %xmm3 +; SSE-NEXT: movdqa {{.*#+}} xmm5 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; SSE-NEXT: pand %xmm5, %xmm3 +; SSE-NEXT: movdqa {{.*#+}} xmm4 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; SSE-NEXT: pxor %xmm4, %xmm3 +; SSE-NEXT: paddb %xmm10, %xmm3 +; SSE-NEXT: psrlw $1, %xmm2 +; SSE-NEXT: pand %xmm5, %xmm2 +; SSE-NEXT: pxor %xmm4, %xmm2 +; SSE-NEXT: paddb %xmm11, %xmm2 +; SSE-NEXT: psrlw $1, %xmm1 +; SSE-NEXT: pand %xmm5, %xmm1 +; SSE-NEXT: pxor %xmm4, %xmm1 +; SSE-NEXT: paddb %xmm9, %xmm1 +; SSE-NEXT: psrlw $1, %xmm0 +; SSE-NEXT: pand %xmm5, %xmm0 +; SSE-NEXT: pxor %xmm4, %xmm0 +; SSE-NEXT: paddb %xmm8, %xmm0 +; SSE-NEXT: psubb %xmm4, %xmm0 +; SSE-NEXT: psubb %xmm4, %xmm1 +; SSE-NEXT: psubb %xmm4, %xmm2 +; SSE-NEXT: psubb %xmm4, %xmm3 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v64i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vandps %ymm3, %ymm1, %ymm4 +; AVX1-NEXT: vandps %ymm2, %ymm0, %ymm5 +; AVX1-NEXT: vxorps %ymm2, %ymm0, %ymm0 +; AVX1-NEXT: vxorps %ymm3, %ymm1, %ymm1 +; AVX1-NEXT: vpsrlw $1, %xmm1, %xmm2 +; AVX1-NEXT: vbroadcastss {{.*#+}} xmm3 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; AVX1-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX1-NEXT: vbroadcastss {{.*#+}} xmm6 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; AVX1-NEXT: vpxor %xmm6, %xmm2, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpsrlw $1, %xmm1, %xmm1 +; AVX1-NEXT: vpand %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vpxor %xmm6, %xmm1, %xmm1 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm7 +; AVX1-NEXT: vpand %xmm3, %xmm7, %xmm7 +; AVX1-NEXT: vpxor %xmm6, %xmm7, %xmm7 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 +; AVX1-NEXT: vpxor %xmm6, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm5, %xmm3 +; AVX1-NEXT: vpaddb %xmm3, %xmm0, %xmm0 +; AVX1-NEXT: vpsubb %xmm6, %xmm0, %xmm0 +; AVX1-NEXT: vpaddb %xmm5, %xmm7, %xmm3 +; AVX1-NEXT: vpsubb %xmm6, %xmm3, %xmm3 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm3, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm4, %xmm3 +; AVX1-NEXT: vpaddb %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vpsubb %xmm6, %xmm1, %xmm1 +; AVX1-NEXT: vpaddb %xmm4, %xmm2, %xmm2 +; AVX1-NEXT: vpsubb %xmm6, %xmm2, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v64i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %ymm3, %ymm1, %ymm4 +; AVX2-NEXT: vpand %ymm2, %ymm0, %ymm5 +; AVX2-NEXT: vpxor %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpxor %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: vpsrlw $1, %ymm1, %ymm1 +; AVX2-NEXT: vpbroadcastb {{.*#+}} ymm2 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; AVX2-NEXT: vpand %ymm2, %ymm1, %ymm1 +; AVX2-NEXT: vpbroadcastb {{.*#+}} ymm3 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; AVX2-NEXT: vpxor %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: vpaddb %ymm4, %ymm1, %ymm1 +; AVX2-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpand %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpxor %ymm3, %ymm0, %ymm0 +; AVX2-NEXT: vpaddb %ymm5, %ymm0, %ymm0 +; AVX2-NEXT: vpsubb %ymm3, %ymm0, %ymm0 +; AVX2-NEXT: vpsubb %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v64i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpandq %zmm1, %zmm0, %zmm2 +; AVX512-NEXT: vpxorq %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlw $1, %zmm0, %zmm0 +; AVX512-NEXT: vpbroadcastb {{.*#+}} zmm1 = [64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64] +; AVX512-NEXT: vpternlogd $108, {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm1, %zmm0 +; AVX512-NEXT: vpaddb %zmm2, %zmm0, %zmm0 +; AVX512-NEXT: vpsubb %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: retq + %and = and <64 x i8> %a0, %a1 + %xor = xor <64 x i8> %a0, %a1 + %shift = ashr <64 x i8> %xor, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> + %res = add <64 x i8> %and, %shift + ret <64 x i8> %res +} + +define <64 x i8> @test_ext_v64i8(<64 x i8> %a0, <64 x i8> %a1) { +; SSE2-LABEL: test_ext_v64i8: +; SSE2: # %bb.0: +; SSE2-NEXT: punpcklbw {{.*#+}} xmm13 = xmm13[0],xmm3[0],xmm13[1],xmm3[1],xmm13[2],xmm3[2],xmm13[3],xmm3[3],xmm13[4],xmm3[4],xmm13[5],xmm3[5],xmm13[6],xmm3[6],xmm13[7],xmm3[7] +; SSE2-NEXT: psraw $8, %xmm13 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm14 = xmm14[8],xmm3[8],xmm14[9],xmm3[9],xmm14[10],xmm3[10],xmm14[11],xmm3[11],xmm14[12],xmm3[12],xmm14[13],xmm3[13],xmm14[14],xmm3[14],xmm14[15],xmm3[15] +; SSE2-NEXT: psraw $8, %xmm14 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm15 = xmm15[0],xmm2[0],xmm15[1],xmm2[1],xmm15[2],xmm2[2],xmm15[3],xmm2[3],xmm15[4],xmm2[4],xmm15[5],xmm2[5],xmm15[6],xmm2[6],xmm15[7],xmm2[7] +; SSE2-NEXT: psraw $8, %xmm15 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm12 = xmm12[8],xmm2[8],xmm12[9],xmm2[9],xmm12[10],xmm2[10],xmm12[11],xmm2[11],xmm12[12],xmm2[12],xmm12[13],xmm2[13],xmm12[14],xmm2[14],xmm12[15],xmm2[15] +; SSE2-NEXT: psraw $8, %xmm12 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm11 = xmm11[0],xmm1[0],xmm11[1],xmm1[1],xmm11[2],xmm1[2],xmm11[3],xmm1[3],xmm11[4],xmm1[4],xmm11[5],xmm1[5],xmm11[6],xmm1[6],xmm11[7],xmm1[7] +; SSE2-NEXT: psraw $8, %xmm11 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm10 = xmm10[8],xmm1[8],xmm10[9],xmm1[9],xmm10[10],xmm1[10],xmm10[11],xmm1[11],xmm10[12],xmm1[12],xmm10[13],xmm1[13],xmm10[14],xmm1[14],xmm10[15],xmm1[15] +; SSE2-NEXT: psraw $8, %xmm10 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm9 = xmm9[0],xmm0[0],xmm9[1],xmm0[1],xmm9[2],xmm0[2],xmm9[3],xmm0[3],xmm9[4],xmm0[4],xmm9[5],xmm0[5],xmm9[6],xmm0[6],xmm9[7],xmm0[7] +; SSE2-NEXT: psraw $8, %xmm9 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm8 = xmm8[8],xmm0[8],xmm8[9],xmm0[9],xmm8[10],xmm0[10],xmm8[11],xmm0[11],xmm8[12],xmm0[12],xmm8[13],xmm0[13],xmm8[14],xmm0[14],xmm8[15],xmm0[15] +; SSE2-NEXT: psraw $8, %xmm8 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm7[0],xmm3[1],xmm7[1],xmm3[2],xmm7[2],xmm3[3],xmm7[3],xmm3[4],xmm7[4],xmm3[5],xmm7[5],xmm3[6],xmm7[6],xmm3[7],xmm7[7] +; SSE2-NEXT: psraw $8, %xmm3 +; SSE2-NEXT: paddw %xmm13, %xmm3 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm7 = xmm7[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; SSE2-NEXT: psraw $8, %xmm7 +; SSE2-NEXT: paddw %xmm14, %xmm7 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm6[0],xmm2[1],xmm6[1],xmm2[2],xmm6[2],xmm2[3],xmm6[3],xmm2[4],xmm6[4],xmm2[5],xmm6[5],xmm2[6],xmm6[6],xmm2[7],xmm6[7] +; SSE2-NEXT: psraw $8, %xmm2 +; SSE2-NEXT: paddw %xmm15, %xmm2 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm6 = xmm6[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; SSE2-NEXT: psraw $8, %xmm6 +; SSE2-NEXT: paddw %xmm12, %xmm6 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm5[0],xmm1[1],xmm5[1],xmm1[2],xmm5[2],xmm1[3],xmm5[3],xmm1[4],xmm5[4],xmm1[5],xmm5[5],xmm1[6],xmm5[6],xmm1[7],xmm5[7] +; SSE2-NEXT: psraw $8, %xmm1 +; SSE2-NEXT: paddw %xmm11, %xmm1 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; SSE2-NEXT: psraw $8, %xmm5 +; SSE2-NEXT: paddw %xmm10, %xmm5 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm4[0],xmm0[1],xmm4[1],xmm0[2],xmm4[2],xmm0[3],xmm4[3],xmm0[4],xmm4[4],xmm0[5],xmm4[5],xmm0[6],xmm4[6],xmm0[7],xmm4[7] +; SSE2-NEXT: psraw $8, %xmm0 +; SSE2-NEXT: paddw %xmm9, %xmm0 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15] +; SSE2-NEXT: psraw $8, %xmm4 +; SSE2-NEXT: paddw %xmm8, %xmm4 +; SSE2-NEXT: psrlw $1, %xmm3 +; SSE2-NEXT: psrlw $1, %xmm7 +; SSE2-NEXT: psrlw $1, %xmm2 +; SSE2-NEXT: psrlw $1, %xmm6 +; SSE2-NEXT: psrlw $1, %xmm1 +; SSE2-NEXT: psrlw $1, %xmm5 +; SSE2-NEXT: psrlw $1, %xmm0 +; SSE2-NEXT: psrlw $1, %xmm4 +; SSE2-NEXT: movdqa {{.*#+}} xmm8 = [255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0] +; SSE2-NEXT: pand %xmm8, %xmm4 +; SSE2-NEXT: pand %xmm8, %xmm0 +; SSE2-NEXT: packuswb %xmm4, %xmm0 +; SSE2-NEXT: pand %xmm8, %xmm5 +; SSE2-NEXT: pand %xmm8, %xmm1 +; SSE2-NEXT: packuswb %xmm5, %xmm1 +; SSE2-NEXT: pand %xmm8, %xmm6 +; SSE2-NEXT: pand %xmm8, %xmm2 +; SSE2-NEXT: packuswb %xmm6, %xmm2 +; SSE2-NEXT: pand %xmm8, %xmm7 +; SSE2-NEXT: pand %xmm8, %xmm3 +; SSE2-NEXT: packuswb %xmm7, %xmm3 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v64i8: +; SSE4: # %bb.0: +; SSE4-NEXT: pshufd {{.*#+}} xmm8 = xmm3[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm8, %xmm9 +; SSE4-NEXT: pmovsxbw %xmm3, %xmm10 +; SSE4-NEXT: pshufd {{.*#+}} xmm3 = xmm2[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm3, %xmm11 +; SSE4-NEXT: pmovsxbw %xmm2, %xmm12 +; SSE4-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm2, %xmm13 +; SSE4-NEXT: pmovsxbw %xmm1, %xmm14 +; SSE4-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm1, %xmm15 +; SSE4-NEXT: pmovsxbw %xmm0, %xmm0 +; SSE4-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm7[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm0, %xmm8 +; SSE4-NEXT: paddw %xmm9, %xmm8 +; SSE4-NEXT: pmovsxbw %xmm7, %xmm3 +; SSE4-NEXT: paddw %xmm10, %xmm3 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm6[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm0, %xmm7 +; SSE4-NEXT: paddw %xmm11, %xmm7 +; SSE4-NEXT: pmovsxbw %xmm6, %xmm2 +; SSE4-NEXT: paddw %xmm12, %xmm2 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm5[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm0, %xmm6 +; SSE4-NEXT: paddw %xmm13, %xmm6 +; SSE4-NEXT: pmovsxbw %xmm5, %xmm1 +; SSE4-NEXT: paddw %xmm14, %xmm1 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm4[2,3,2,3] +; SSE4-NEXT: pmovsxbw %xmm0, %xmm5 +; SSE4-NEXT: paddw %xmm15, %xmm5 +; SSE4-NEXT: pmovsxbw %xmm4, %xmm0 +; SSE4-NEXT: paddw {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Folded Reload +; SSE4-NEXT: psrlw $1, %xmm8 +; SSE4-NEXT: psrlw $1, %xmm3 +; SSE4-NEXT: psrlw $1, %xmm7 +; SSE4-NEXT: psrlw $1, %xmm2 +; SSE4-NEXT: psrlw $1, %xmm6 +; SSE4-NEXT: psrlw $1, %xmm1 +; SSE4-NEXT: psrlw $1, %xmm5 +; SSE4-NEXT: psrlw $1, %xmm0 +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm4 = [255,255,255,255,255,255,255,255] +; SSE4-NEXT: pand %xmm4, %xmm0 +; SSE4-NEXT: pand %xmm4, %xmm5 +; SSE4-NEXT: packuswb %xmm5, %xmm0 +; SSE4-NEXT: pand %xmm4, %xmm1 +; SSE4-NEXT: pand %xmm4, %xmm6 +; SSE4-NEXT: packuswb %xmm6, %xmm1 +; SSE4-NEXT: pand %xmm4, %xmm2 +; SSE4-NEXT: pand %xmm4, %xmm7 +; SSE4-NEXT: packuswb %xmm7, %xmm2 +; SSE4-NEXT: pand %xmm4, %xmm3 +; SSE4-NEXT: pand %xmm4, %xmm8 +; SSE4-NEXT: packuswb %xmm8, %xmm3 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v64i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vpshufd {{.*#+}} xmm4 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm4, %xmm4 +; AVX1-NEXT: vpmovsxbw %xmm1, %xmm5 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpshufd {{.*#+}} xmm6 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm6, %xmm6 +; AVX1-NEXT: vpmovsxbw %xmm1, %xmm1 +; AVX1-NEXT: vpshufd {{.*#+}} xmm7 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm7, %xmm7 +; AVX1-NEXT: vpmovsxbw %xmm0, %xmm8 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpshufd {{.*#+}} xmm9 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm9, %xmm9 +; AVX1-NEXT: vpmovsxbw %xmm0, %xmm0 +; AVX1-NEXT: vpshufd {{.*#+}} xmm10 = xmm3[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm10, %xmm10 +; AVX1-NEXT: vpaddw %xmm4, %xmm10, %xmm4 +; AVX1-NEXT: vpmovsxbw %xmm3, %xmm10 +; AVX1-NEXT: vpaddw %xmm5, %xmm10, %xmm5 +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm3 +; AVX1-NEXT: vpshufd {{.*#+}} xmm10 = xmm3[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm10, %xmm10 +; AVX1-NEXT: vpaddw %xmm6, %xmm10, %xmm6 +; AVX1-NEXT: vpmovsxbw %xmm3, %xmm3 +; AVX1-NEXT: vpaddw %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vpshufd {{.*#+}} xmm3 = xmm2[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm3, %xmm3 +; AVX1-NEXT: vpaddw %xmm3, %xmm7, %xmm3 +; AVX1-NEXT: vpmovsxbw %xmm2, %xmm7 +; AVX1-NEXT: vpaddw %xmm7, %xmm8, %xmm7 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm2 +; AVX1-NEXT: vpshufd {{.*#+}} xmm8 = xmm2[2,3,2,3] +; AVX1-NEXT: vpmovsxbw %xmm8, %xmm8 +; AVX1-NEXT: vpaddw %xmm8, %xmm9, %xmm8 +; AVX1-NEXT: vpmovsxbw %xmm2, %xmm2 +; AVX1-NEXT: vpaddw %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm4, %xmm2 +; AVX1-NEXT: vpsrlw $1, %xmm5, %xmm4 +; AVX1-NEXT: vpsrlw $1, %xmm6, %xmm5 +; AVX1-NEXT: vpsrlw $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsrlw $1, %xmm3, %xmm3 +; AVX1-NEXT: vpsrlw $1, %xmm7, %xmm6 +; AVX1-NEXT: vpsrlw $1, %xmm8, %xmm7 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vbroadcastss {{.*#+}} xmm8 = [255,255,255,255,255,255,255,255] +; AVX1-NEXT: vpand %xmm0, %xmm8, %xmm0 +; AVX1-NEXT: vpand %xmm7, %xmm8, %xmm7 +; AVX1-NEXT: vpackuswb %xmm7, %xmm0, %xmm0 +; AVX1-NEXT: vpand %xmm6, %xmm8, %xmm6 +; AVX1-NEXT: vpand %xmm3, %xmm8, %xmm3 +; AVX1-NEXT: vpackuswb %xmm3, %xmm6, %xmm3 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm3, %ymm0 +; AVX1-NEXT: vpand %xmm1, %xmm8, %xmm1 +; AVX1-NEXT: vpand %xmm5, %xmm8, %xmm3 +; AVX1-NEXT: vpackuswb %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vpand %xmm4, %xmm8, %xmm3 +; AVX1-NEXT: vpand %xmm2, %xmm8, %xmm2 +; AVX1-NEXT: vpackuswb %xmm2, %xmm3, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v64i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovsxbw %xmm1, %ymm4 +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm1 +; AVX2-NEXT: vpmovsxbw %xmm1, %ymm1 +; AVX2-NEXT: vpmovsxbw %xmm0, %ymm5 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX2-NEXT: vpmovsxbw %xmm0, %ymm0 +; AVX2-NEXT: vpmovsxbw %xmm3, %ymm6 +; AVX2-NEXT: vpaddw %ymm6, %ymm4, %ymm4 +; AVX2-NEXT: vextracti128 $1, %ymm3, %xmm3 +; AVX2-NEXT: vpmovsxbw %xmm3, %ymm3 +; AVX2-NEXT: vpaddw %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: vpmovsxbw %xmm2, %ymm3 +; AVX2-NEXT: vpaddw %ymm3, %ymm5, %ymm3 +; AVX2-NEXT: vextracti128 $1, %ymm2, %xmm2 +; AVX2-NEXT: vpmovsxbw %xmm2, %ymm2 +; AVX2-NEXT: vpaddw %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlw $1, %ymm4, %ymm2 +; AVX2-NEXT: vpsrlw $1, %ymm1, %ymm1 +; AVX2-NEXT: vpsrlw $1, %ymm3, %ymm3 +; AVX2-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpbroadcastw {{.*#+}} ymm4 = [255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0] +; AVX2-NEXT: vpand %ymm4, %ymm0, %ymm0 +; AVX2-NEXT: vpand %ymm4, %ymm3, %ymm3 +; AVX2-NEXT: vpackuswb %ymm0, %ymm3, %ymm0 +; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,2,1,3] +; AVX2-NEXT: vpand %ymm4, %ymm1, %ymm1 +; AVX2-NEXT: vpand %ymm4, %ymm2, %ymm2 +; AVX2-NEXT: vpackuswb %ymm1, %ymm2, %ymm1 +; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,2,1,3] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v64i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vextracti64x4 $1, %zmm0, %ymm2 +; AVX512-NEXT: vpmovsxbw %ymm2, %zmm2 +; AVX512-NEXT: vpmovsxbw %ymm0, %zmm0 +; AVX512-NEXT: vextracti64x4 $1, %zmm1, %ymm3 +; AVX512-NEXT: vpmovsxbw %ymm3, %zmm3 +; AVX512-NEXT: vpaddw %zmm3, %zmm2, %zmm2 +; AVX512-NEXT: vpmovsxbw %ymm1, %zmm1 +; AVX512-NEXT: vpaddw %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlw $1, %zmm2, %zmm1 +; AVX512-NEXT: vpsrlw $1, %zmm0, %zmm0 +; AVX512-NEXT: vpmovwb %zmm0, %ymm0 +; AVX512-NEXT: vpmovwb %zmm1, %ymm1 +; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm0, %zmm0 +; AVX512-NEXT: retq + %x0 = sext <64 x i8> %a0 to <64 x i16> + %x1 = sext <64 x i8> %a1 to <64 x i16> + %sum = add <64 x i16> %x0, %x1 + %shift = ashr <64 x i16> %sum, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = trunc <64 x i16> %shift to <64 x i8> + ret <64 x i8> %res +} + +define <32 x i16> @test_fixed_v32i16(<32 x i16> %a0, <32 x i16> %a1) { +; SSE-LABEL: test_fixed_v32i16: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm3, %xmm8 +; SSE-NEXT: pand %xmm7, %xmm8 +; SSE-NEXT: movdqa %xmm2, %xmm9 +; SSE-NEXT: pand %xmm6, %xmm9 +; SSE-NEXT: movdqa %xmm1, %xmm10 +; SSE-NEXT: pand %xmm5, %xmm10 +; SSE-NEXT: movdqa %xmm0, %xmm11 +; SSE-NEXT: pand %xmm4, %xmm11 +; SSE-NEXT: pxor %xmm4, %xmm0 +; SSE-NEXT: pxor %xmm5, %xmm1 +; SSE-NEXT: pxor %xmm6, %xmm2 +; SSE-NEXT: pxor %xmm7, %xmm3 +; SSE-NEXT: psraw $1, %xmm3 +; SSE-NEXT: paddw %xmm8, %xmm3 +; SSE-NEXT: psraw $1, %xmm2 +; SSE-NEXT: paddw %xmm9, %xmm2 +; SSE-NEXT: psraw $1, %xmm1 +; SSE-NEXT: paddw %xmm10, %xmm1 +; SSE-NEXT: psraw $1, %xmm0 +; SSE-NEXT: paddw %xmm11, %xmm0 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v32i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vandps %ymm3, %ymm1, %ymm4 +; AVX1-NEXT: vandps %ymm2, %ymm0, %ymm5 +; AVX1-NEXT: vxorps %ymm0, %ymm2, %ymm0 +; AVX1-NEXT: vxorps %ymm1, %ymm3, %ymm1 +; AVX1-NEXT: vpsraw $1, %xmm1, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpsraw $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsraw $1, %xmm0, %xmm3 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsraw $1, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm5, %xmm6 +; AVX1-NEXT: vpaddw %xmm0, %xmm6, %xmm0 +; AVX1-NEXT: vpaddw %xmm3, %xmm5, %xmm3 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm3, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm4, %xmm3 +; AVX1-NEXT: vpaddw %xmm1, %xmm3, %xmm1 +; AVX1-NEXT: vpaddw %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v32i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %ymm3, %ymm1, %ymm4 +; AVX2-NEXT: vpand %ymm2, %ymm0, %ymm5 +; AVX2-NEXT: vpxor %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: vpxor %ymm1, %ymm3, %ymm1 +; AVX2-NEXT: vpsraw $1, %ymm1, %ymm1 +; AVX2-NEXT: vpaddw %ymm1, %ymm4, %ymm1 +; AVX2-NEXT: vpsraw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpaddw %ymm0, %ymm5, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v32i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vpandq %zmm1, %zmm0, %zmm2 +; AVX512-NEXT: vpxorq %zmm0, %zmm1, %zmm0 +; AVX512-NEXT: vpsraw $1, %zmm0, %zmm0 +; AVX512-NEXT: vpaddw %zmm0, %zmm2, %zmm0 +; AVX512-NEXT: retq + %and = and <32 x i16> %a0, %a1 + %xor = xor <32 x i16> %a1, %a0 + %shift = ashr <32 x i16> %xor, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = add <32 x i16> %and, %shift + ret <32 x i16> %res +} + +define <32 x i16> @test_ext_v32i16(<32 x i16> %a0, <32 x i16> %a1) { +; SSE2-LABEL: test_ext_v32i16: +; SSE2: # %bb.0: +; SSE2-NEXT: movdqa %xmm3, %xmm9 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm8 = xmm8[4],xmm0[4],xmm8[5],xmm0[5],xmm8[6],xmm0[6],xmm8[7],xmm0[7] +; SSE2-NEXT: psrad $16, %xmm8 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm15 = xmm15[0],xmm0[0],xmm15[1],xmm0[1],xmm15[2],xmm0[2],xmm15[3],xmm0[3] +; SSE2-NEXT: psrad $16, %xmm15 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm3 = xmm3[4],xmm1[4],xmm3[5],xmm1[5],xmm3[6],xmm1[6],xmm3[7],xmm1[7] +; SSE2-NEXT: psrad $16, %xmm3 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm14 = xmm14[0],xmm1[0],xmm14[1],xmm1[1],xmm14[2],xmm1[2],xmm14[3],xmm1[3] +; SSE2-NEXT: psrad $16, %xmm14 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm13 = xmm13[4],xmm2[4],xmm13[5],xmm2[5],xmm13[6],xmm2[6],xmm13[7],xmm2[7] +; SSE2-NEXT: psrad $16, %xmm13 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm12 = xmm12[0],xmm2[0],xmm12[1],xmm2[1],xmm12[2],xmm2[2],xmm12[3],xmm2[3] +; SSE2-NEXT: psrad $16, %xmm12 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm11 = xmm11[4],xmm9[4],xmm11[5],xmm9[5],xmm11[6],xmm9[6],xmm11[7],xmm9[7] +; SSE2-NEXT: psrad $16, %xmm11 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm10 = xmm10[0],xmm9[0],xmm10[1],xmm9[1],xmm10[2],xmm9[2],xmm10[3],xmm9[3] +; SSE2-NEXT: psrad $16, %xmm10 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm9 = xmm9[4],xmm4[4],xmm9[5],xmm4[5],xmm9[6],xmm4[6],xmm9[7],xmm4[7] +; SSE2-NEXT: psrad $16, %xmm9 +; SSE2-NEXT: paddd %xmm8, %xmm9 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm4[0],xmm0[1],xmm4[1],xmm0[2],xmm4[2],xmm0[3],xmm4[3] +; SSE2-NEXT: psrad $16, %xmm0 +; SSE2-NEXT: paddd %xmm15, %xmm0 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm8 = xmm8[4],xmm5[4],xmm8[5],xmm5[5],xmm8[6],xmm5[6],xmm8[7],xmm5[7] +; SSE2-NEXT: psrad $16, %xmm8 +; SSE2-NEXT: paddd %xmm3, %xmm8 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm1 = xmm1[0],xmm5[0],xmm1[1],xmm5[1],xmm1[2],xmm5[2],xmm1[3],xmm5[3] +; SSE2-NEXT: psrad $16, %xmm1 +; SSE2-NEXT: paddd %xmm14, %xmm1 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm5 = xmm5[4],xmm6[4],xmm5[5],xmm6[5],xmm5[6],xmm6[6],xmm5[7],xmm6[7] +; SSE2-NEXT: psrad $16, %xmm5 +; SSE2-NEXT: paddd %xmm13, %xmm5 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm2 = xmm2[0],xmm6[0],xmm2[1],xmm6[1],xmm2[2],xmm6[2],xmm2[3],xmm6[3] +; SSE2-NEXT: psrad $16, %xmm2 +; SSE2-NEXT: paddd %xmm12, %xmm2 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm4 = xmm4[4],xmm7[4],xmm4[5],xmm7[5],xmm4[6],xmm7[6],xmm4[7],xmm7[7] +; SSE2-NEXT: psrad $16, %xmm4 +; SSE2-NEXT: paddd %xmm11, %xmm4 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm3 = xmm3[0],xmm7[0],xmm3[1],xmm7[1],xmm3[2],xmm7[2],xmm3[3],xmm7[3] +; SSE2-NEXT: psrad $16, %xmm3 +; SSE2-NEXT: paddd %xmm10, %xmm3 +; SSE2-NEXT: pslld $15, %xmm9 +; SSE2-NEXT: psrad $16, %xmm9 +; SSE2-NEXT: pslld $15, %xmm0 +; SSE2-NEXT: psrad $16, %xmm0 +; SSE2-NEXT: packssdw %xmm9, %xmm0 +; SSE2-NEXT: pslld $15, %xmm8 +; SSE2-NEXT: psrad $16, %xmm8 +; SSE2-NEXT: pslld $15, %xmm1 +; SSE2-NEXT: psrad $16, %xmm1 +; SSE2-NEXT: packssdw %xmm8, %xmm1 +; SSE2-NEXT: pslld $15, %xmm5 +; SSE2-NEXT: psrad $16, %xmm5 +; SSE2-NEXT: pslld $15, %xmm2 +; SSE2-NEXT: psrad $16, %xmm2 +; SSE2-NEXT: packssdw %xmm5, %xmm2 +; SSE2-NEXT: pslld $15, %xmm4 +; SSE2-NEXT: psrad $16, %xmm4 +; SSE2-NEXT: pslld $15, %xmm3 +; SSE2-NEXT: psrad $16, %xmm3 +; SSE2-NEXT: packssdw %xmm4, %xmm3 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v32i16: +; SSE4: # %bb.0: +; SSE4-NEXT: pshufd {{.*#+}} xmm8 = xmm3[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm8, %xmm9 +; SSE4-NEXT: pmovsxwd %xmm3, %xmm10 +; SSE4-NEXT: pshufd {{.*#+}} xmm3 = xmm2[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm3, %xmm11 +; SSE4-NEXT: pmovsxwd %xmm2, %xmm12 +; SSE4-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm2, %xmm13 +; SSE4-NEXT: pmovsxwd %xmm1, %xmm14 +; SSE4-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm1, %xmm15 +; SSE4-NEXT: pmovsxwd %xmm0, %xmm0 +; SSE4-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm7[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm0, %xmm8 +; SSE4-NEXT: paddd %xmm9, %xmm8 +; SSE4-NEXT: pmovsxwd %xmm7, %xmm3 +; SSE4-NEXT: paddd %xmm10, %xmm3 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm6[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm0, %xmm7 +; SSE4-NEXT: paddd %xmm11, %xmm7 +; SSE4-NEXT: pmovsxwd %xmm6, %xmm2 +; SSE4-NEXT: paddd %xmm12, %xmm2 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm5[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm0, %xmm6 +; SSE4-NEXT: paddd %xmm13, %xmm6 +; SSE4-NEXT: pmovsxwd %xmm5, %xmm1 +; SSE4-NEXT: paddd %xmm14, %xmm1 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm4[2,3,2,3] +; SSE4-NEXT: pmovsxwd %xmm0, %xmm5 +; SSE4-NEXT: paddd %xmm15, %xmm5 +; SSE4-NEXT: pmovsxwd %xmm4, %xmm0 +; SSE4-NEXT: paddd {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Folded Reload +; SSE4-NEXT: psrld $1, %xmm8 +; SSE4-NEXT: psrld $1, %xmm3 +; SSE4-NEXT: psrld $1, %xmm7 +; SSE4-NEXT: psrld $1, %xmm2 +; SSE4-NEXT: psrld $1, %xmm6 +; SSE4-NEXT: psrld $1, %xmm1 +; SSE4-NEXT: psrld $1, %xmm5 +; SSE4-NEXT: psrld $1, %xmm0 +; SSE4-NEXT: pxor %xmm4, %xmm4 +; SSE4-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0],xmm4[1],xmm0[2],xmm4[3],xmm0[4],xmm4[5],xmm0[6],xmm4[7] +; SSE4-NEXT: pblendw {{.*#+}} xmm5 = xmm5[0],xmm4[1],xmm5[2],xmm4[3],xmm5[4],xmm4[5],xmm5[6],xmm4[7] +; SSE4-NEXT: packusdw %xmm5, %xmm0 +; SSE4-NEXT: pblendw {{.*#+}} xmm1 = xmm1[0],xmm4[1],xmm1[2],xmm4[3],xmm1[4],xmm4[5],xmm1[6],xmm4[7] +; SSE4-NEXT: pblendw {{.*#+}} xmm6 = xmm6[0],xmm4[1],xmm6[2],xmm4[3],xmm6[4],xmm4[5],xmm6[6],xmm4[7] +; SSE4-NEXT: packusdw %xmm6, %xmm1 +; SSE4-NEXT: pblendw {{.*#+}} xmm2 = xmm2[0],xmm4[1],xmm2[2],xmm4[3],xmm2[4],xmm4[5],xmm2[6],xmm4[7] +; SSE4-NEXT: pblendw {{.*#+}} xmm7 = xmm7[0],xmm4[1],xmm7[2],xmm4[3],xmm7[4],xmm4[5],xmm7[6],xmm4[7] +; SSE4-NEXT: packusdw %xmm7, %xmm2 +; SSE4-NEXT: pblendw {{.*#+}} xmm3 = xmm3[0],xmm4[1],xmm3[2],xmm4[3],xmm3[4],xmm4[5],xmm3[6],xmm4[7] +; SSE4-NEXT: pblendw {{.*#+}} xmm8 = xmm8[0],xmm4[1],xmm8[2],xmm4[3],xmm8[4],xmm4[5],xmm8[6],xmm4[7] +; SSE4-NEXT: packusdw %xmm8, %xmm3 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v32i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vpshufd {{.*#+}} xmm4 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm4, %xmm4 +; AVX1-NEXT: vpmovsxwd %xmm1, %xmm5 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpshufd {{.*#+}} xmm6 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm6, %xmm6 +; AVX1-NEXT: vpmovsxwd %xmm1, %xmm1 +; AVX1-NEXT: vpshufd {{.*#+}} xmm7 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm7, %xmm7 +; AVX1-NEXT: vpmovsxwd %xmm0, %xmm8 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpshufd {{.*#+}} xmm9 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm9, %xmm9 +; AVX1-NEXT: vpmovsxwd %xmm0, %xmm0 +; AVX1-NEXT: vpshufd {{.*#+}} xmm10 = xmm3[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm10, %xmm10 +; AVX1-NEXT: vpaddd %xmm4, %xmm10, %xmm4 +; AVX1-NEXT: vpmovsxwd %xmm3, %xmm10 +; AVX1-NEXT: vpaddd %xmm5, %xmm10, %xmm5 +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm3 +; AVX1-NEXT: vpshufd {{.*#+}} xmm10 = xmm3[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm10, %xmm10 +; AVX1-NEXT: vpaddd %xmm6, %xmm10, %xmm6 +; AVX1-NEXT: vpmovsxwd %xmm3, %xmm3 +; AVX1-NEXT: vpaddd %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vpshufd {{.*#+}} xmm3 = xmm2[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm3, %xmm3 +; AVX1-NEXT: vpaddd %xmm3, %xmm7, %xmm3 +; AVX1-NEXT: vpmovsxwd %xmm2, %xmm7 +; AVX1-NEXT: vpaddd %xmm7, %xmm8, %xmm7 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm2 +; AVX1-NEXT: vpshufd {{.*#+}} xmm8 = xmm2[2,3,2,3] +; AVX1-NEXT: vpmovsxwd %xmm8, %xmm8 +; AVX1-NEXT: vpaddd %xmm8, %xmm9, %xmm8 +; AVX1-NEXT: vpmovsxwd %xmm2, %xmm2 +; AVX1-NEXT: vpaddd %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpsrld $1, %xmm4, %xmm2 +; AVX1-NEXT: vpsrld $1, %xmm5, %xmm4 +; AVX1-NEXT: vpsrld $1, %xmm6, %xmm5 +; AVX1-NEXT: vpsrld $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsrld $1, %xmm3, %xmm3 +; AVX1-NEXT: vpsrld $1, %xmm7, %xmm6 +; AVX1-NEXT: vpsrld $1, %xmm8, %xmm7 +; AVX1-NEXT: vpsrld $1, %xmm0, %xmm0 +; AVX1-NEXT: vpxor %xmm8, %xmm8, %xmm8 +; AVX1-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0],xmm8[1],xmm0[2],xmm8[3],xmm0[4],xmm8[5],xmm0[6],xmm8[7] +; AVX1-NEXT: vpblendw {{.*#+}} xmm7 = xmm7[0],xmm8[1],xmm7[2],xmm8[3],xmm7[4],xmm8[5],xmm7[6],xmm8[7] +; AVX1-NEXT: vpackusdw %xmm7, %xmm0, %xmm0 +; AVX1-NEXT: vpblendw {{.*#+}} xmm6 = xmm6[0],xmm8[1],xmm6[2],xmm8[3],xmm6[4],xmm8[5],xmm6[6],xmm8[7] +; AVX1-NEXT: vpblendw {{.*#+}} xmm3 = xmm3[0],xmm8[1],xmm3[2],xmm8[3],xmm3[4],xmm8[5],xmm3[6],xmm8[7] +; AVX1-NEXT: vpackusdw %xmm3, %xmm6, %xmm3 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm3, %ymm0 +; AVX1-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0],xmm8[1],xmm1[2],xmm8[3],xmm1[4],xmm8[5],xmm1[6],xmm8[7] +; AVX1-NEXT: vpblendw {{.*#+}} xmm3 = xmm5[0],xmm8[1],xmm5[2],xmm8[3],xmm5[4],xmm8[5],xmm5[6],xmm8[7] +; AVX1-NEXT: vpackusdw %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vpblendw {{.*#+}} xmm3 = xmm4[0],xmm8[1],xmm4[2],xmm8[3],xmm4[4],xmm8[5],xmm4[6],xmm8[7] +; AVX1-NEXT: vpblendw {{.*#+}} xmm2 = xmm2[0],xmm8[1],xmm2[2],xmm8[3],xmm2[4],xmm8[5],xmm2[6],xmm8[7] +; AVX1-NEXT: vpackusdw %xmm2, %xmm3, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v32i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovsxwd %xmm1, %ymm4 +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm1 +; AVX2-NEXT: vpmovsxwd %xmm1, %ymm1 +; AVX2-NEXT: vpmovsxwd %xmm0, %ymm5 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX2-NEXT: vpmovsxwd %xmm0, %ymm0 +; AVX2-NEXT: vpmovsxwd %xmm3, %ymm6 +; AVX2-NEXT: vpaddd %ymm6, %ymm4, %ymm4 +; AVX2-NEXT: vextracti128 $1, %ymm3, %xmm3 +; AVX2-NEXT: vpmovsxwd %xmm3, %ymm3 +; AVX2-NEXT: vpaddd %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: vpmovsxwd %xmm2, %ymm3 +; AVX2-NEXT: vpaddd %ymm3, %ymm5, %ymm3 +; AVX2-NEXT: vextracti128 $1, %ymm2, %xmm2 +; AVX2-NEXT: vpmovsxwd %xmm2, %ymm2 +; AVX2-NEXT: vpaddd %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpsrld $1, %ymm4, %ymm2 +; AVX2-NEXT: vpsrld $1, %ymm1, %ymm1 +; AVX2-NEXT: vpsrld $1, %ymm3, %ymm3 +; AVX2-NEXT: vpsrld $1, %ymm0, %ymm0 +; AVX2-NEXT: vpxor %xmm4, %xmm4, %xmm4 +; AVX2-NEXT: vpblendw {{.*#+}} ymm0 = ymm0[0],ymm4[1],ymm0[2],ymm4[3],ymm0[4],ymm4[5],ymm0[6],ymm4[7],ymm0[8],ymm4[9],ymm0[10],ymm4[11],ymm0[12],ymm4[13],ymm0[14],ymm4[15] +; AVX2-NEXT: vpblendw {{.*#+}} ymm3 = ymm3[0],ymm4[1],ymm3[2],ymm4[3],ymm3[4],ymm4[5],ymm3[6],ymm4[7],ymm3[8],ymm4[9],ymm3[10],ymm4[11],ymm3[12],ymm4[13],ymm3[14],ymm4[15] +; AVX2-NEXT: vpackusdw %ymm0, %ymm3, %ymm0 +; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,2,1,3] +; AVX2-NEXT: vpblendw {{.*#+}} ymm1 = ymm1[0],ymm4[1],ymm1[2],ymm4[3],ymm1[4],ymm4[5],ymm1[6],ymm4[7],ymm1[8],ymm4[9],ymm1[10],ymm4[11],ymm1[12],ymm4[13],ymm1[14],ymm4[15] +; AVX2-NEXT: vpblendw {{.*#+}} ymm2 = ymm2[0],ymm4[1],ymm2[2],ymm4[3],ymm2[4],ymm4[5],ymm2[6],ymm4[7],ymm2[8],ymm4[9],ymm2[10],ymm4[11],ymm2[12],ymm4[13],ymm2[14],ymm4[15] +; AVX2-NEXT: vpackusdw %ymm1, %ymm2, %ymm1 +; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,2,1,3] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v32i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vextracti64x4 $1, %zmm0, %ymm2 +; AVX512-NEXT: vpmovsxwd %ymm2, %zmm2 +; AVX512-NEXT: vpmovsxwd %ymm0, %zmm0 +; AVX512-NEXT: vextracti64x4 $1, %zmm1, %ymm3 +; AVX512-NEXT: vpmovsxwd %ymm3, %zmm3 +; AVX512-NEXT: vpaddd %zmm3, %zmm2, %zmm2 +; AVX512-NEXT: vpmovsxwd %ymm1, %zmm1 +; AVX512-NEXT: vpaddd %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrld $1, %zmm2, %zmm1 +; AVX512-NEXT: vpsrld $1, %zmm0, %zmm0 +; AVX512-NEXT: vpmovdw %zmm0, %ymm0 +; AVX512-NEXT: vpmovdw %zmm1, %ymm1 +; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm0, %zmm0 +; AVX512-NEXT: retq + %x0 = sext <32 x i16> %a0 to <32 x i32> + %x1 = sext <32 x i16> %a1 to <32 x i32> + %sum = add <32 x i32> %x0, %x1 + %shift = ashr <32 x i32> %sum, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = trunc <32 x i32> %shift to <32 x i16> + ret <32 x i16> %res +} + +define <16 x i32> @test_fixed_v16i32(<16 x i32> %a0, <16 x i32> %a1) { +; SSE-LABEL: test_fixed_v16i32: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm3, %xmm8 +; SSE-NEXT: pand %xmm7, %xmm8 +; SSE-NEXT: movdqa %xmm2, %xmm9 +; SSE-NEXT: pand %xmm6, %xmm9 +; SSE-NEXT: movdqa %xmm1, %xmm10 +; SSE-NEXT: pand %xmm5, %xmm10 +; SSE-NEXT: movdqa %xmm0, %xmm11 +; SSE-NEXT: pand %xmm4, %xmm11 +; SSE-NEXT: pxor %xmm4, %xmm0 +; SSE-NEXT: pxor %xmm5, %xmm1 +; SSE-NEXT: pxor %xmm6, %xmm2 +; SSE-NEXT: pxor %xmm7, %xmm3 +; SSE-NEXT: psrad $1, %xmm3 +; SSE-NEXT: paddd %xmm8, %xmm3 +; SSE-NEXT: psrad $1, %xmm2 +; SSE-NEXT: paddd %xmm9, %xmm2 +; SSE-NEXT: psrad $1, %xmm1 +; SSE-NEXT: paddd %xmm10, %xmm1 +; SSE-NEXT: psrad $1, %xmm0 +; SSE-NEXT: paddd %xmm11, %xmm0 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v16i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vandps %ymm3, %ymm1, %ymm4 +; AVX1-NEXT: vandps %ymm2, %ymm0, %ymm5 +; AVX1-NEXT: vxorps %ymm0, %ymm2, %ymm0 +; AVX1-NEXT: vxorps %ymm1, %ymm3, %ymm1 +; AVX1-NEXT: vpsrad $1, %xmm1, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpsrad $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsrad $1, %xmm0, %xmm3 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrad $1, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm5, %xmm6 +; AVX1-NEXT: vpaddd %xmm0, %xmm6, %xmm0 +; AVX1-NEXT: vpaddd %xmm3, %xmm5, %xmm3 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm3, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm4, %xmm3 +; AVX1-NEXT: vpaddd %xmm1, %xmm3, %xmm1 +; AVX1-NEXT: vpaddd %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v16i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %ymm3, %ymm1, %ymm4 +; AVX2-NEXT: vpand %ymm2, %ymm0, %ymm5 +; AVX2-NEXT: vpxor %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: vpxor %ymm1, %ymm3, %ymm1 +; AVX2-NEXT: vpsrad $1, %ymm1, %ymm1 +; AVX2-NEXT: vpaddd %ymm1, %ymm4, %ymm1 +; AVX2-NEXT: vpsrad $1, %ymm0, %ymm0 +; AVX2-NEXT: vpaddd %ymm0, %ymm5, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v16i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vpandd %zmm1, %zmm0, %zmm2 +; AVX512-NEXT: vpxord %zmm0, %zmm1, %zmm0 +; AVX512-NEXT: vpsrad $1, %zmm0, %zmm0 +; AVX512-NEXT: vpaddd %zmm0, %zmm2, %zmm0 +; AVX512-NEXT: retq + %and = and <16 x i32> %a0, %a1 + %xor = xor <16 x i32> %a1, %a0 + %shift = ashr <16 x i32> %xor, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = add <16 x i32> %and, %shift + ret <16 x i32> %res +} + +define <16 x i32> @test_ext_v16i32(<16 x i32> %a0, <16 x i32> %a1) { +; SSE2-LABEL: test_ext_v16i32: +; SSE2: # %bb.0: +; SSE2-NEXT: pxor %xmm8, %xmm8 +; SSE2-NEXT: pxor %xmm9, %xmm9 +; SSE2-NEXT: pcmpgtd %xmm3, %xmm9 +; SSE2-NEXT: pshufd {{.*#+}} xmm13 = xmm3[2,3,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm9[0],xmm3[1],xmm9[1] +; SSE2-NEXT: pxor %xmm9, %xmm9 +; SSE2-NEXT: pcmpgtd %xmm13, %xmm9 +; SSE2-NEXT: punpckldq {{.*#+}} xmm13 = xmm13[0],xmm9[0],xmm13[1],xmm9[1] +; SSE2-NEXT: pxor %xmm9, %xmm9 +; SSE2-NEXT: pcmpgtd %xmm2, %xmm9 +; SSE2-NEXT: pshufd {{.*#+}} xmm12 = xmm2[2,3,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm9[0],xmm2[1],xmm9[1] +; SSE2-NEXT: pxor %xmm9, %xmm9 +; SSE2-NEXT: pcmpgtd %xmm12, %xmm9 +; SSE2-NEXT: punpckldq {{.*#+}} xmm12 = xmm12[0],xmm9[0],xmm12[1],xmm9[1] +; SSE2-NEXT: pxor %xmm9, %xmm9 +; SSE2-NEXT: pcmpgtd %xmm1, %xmm9 +; SSE2-NEXT: pshufd {{.*#+}} xmm11 = xmm1[2,3,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm9[0],xmm1[1],xmm9[1] +; SSE2-NEXT: pxor %xmm9, %xmm9 +; SSE2-NEXT: pcmpgtd %xmm11, %xmm9 +; SSE2-NEXT: punpckldq {{.*#+}} xmm11 = xmm11[0],xmm9[0],xmm11[1],xmm9[1] +; SSE2-NEXT: pxor %xmm10, %xmm10 +; SSE2-NEXT: pcmpgtd %xmm0, %xmm10 +; SSE2-NEXT: pshufd {{.*#+}} xmm9 = xmm0[2,3,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm10[0],xmm0[1],xmm10[1] +; SSE2-NEXT: pxor %xmm10, %xmm10 +; SSE2-NEXT: pcmpgtd %xmm9, %xmm10 +; SSE2-NEXT: punpckldq {{.*#+}} xmm9 = xmm9[0],xmm10[0],xmm9[1],xmm10[1] +; SSE2-NEXT: pxor %xmm14, %xmm14 +; SSE2-NEXT: pcmpgtd %xmm7, %xmm14 +; SSE2-NEXT: pshufd {{.*#+}} xmm10 = xmm7[2,3,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm7 = xmm7[0],xmm14[0],xmm7[1],xmm14[1] +; SSE2-NEXT: paddq %xmm7, %xmm3 +; SSE2-NEXT: pxor %xmm7, %xmm7 +; SSE2-NEXT: pcmpgtd %xmm10, %xmm7 +; SSE2-NEXT: punpckldq {{.*#+}} xmm10 = xmm10[0],xmm7[0],xmm10[1],xmm7[1] +; SSE2-NEXT: paddq %xmm13, %xmm10 +; SSE2-NEXT: pxor %xmm13, %xmm13 +; SSE2-NEXT: pcmpgtd %xmm6, %xmm13 +; SSE2-NEXT: pshufd {{.*#+}} xmm7 = xmm6[2,3,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm6 = xmm6[0],xmm13[0],xmm6[1],xmm13[1] +; SSE2-NEXT: paddq %xmm6, %xmm2 +; SSE2-NEXT: pxor %xmm6, %xmm6 +; SSE2-NEXT: pcmpgtd %xmm7, %xmm6 +; SSE2-NEXT: punpckldq {{.*#+}} xmm7 = xmm7[0],xmm6[0],xmm7[1],xmm6[1] +; SSE2-NEXT: paddq %xmm12, %xmm7 +; SSE2-NEXT: pxor %xmm12, %xmm12 +; SSE2-NEXT: pcmpgtd %xmm5, %xmm12 +; SSE2-NEXT: pshufd {{.*#+}} xmm6 = xmm5[2,3,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm5 = xmm5[0],xmm12[0],xmm5[1],xmm12[1] +; SSE2-NEXT: paddq %xmm5, %xmm1 +; SSE2-NEXT: pxor %xmm5, %xmm5 +; SSE2-NEXT: pcmpgtd %xmm6, %xmm5 +; SSE2-NEXT: punpckldq {{.*#+}} xmm6 = xmm6[0],xmm5[0],xmm6[1],xmm5[1] +; SSE2-NEXT: paddq %xmm11, %xmm6 +; SSE2-NEXT: pxor %xmm11, %xmm11 +; SSE2-NEXT: pcmpgtd %xmm4, %xmm11 +; SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm4[2,3,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm4 = xmm4[0],xmm11[0],xmm4[1],xmm11[1] +; SSE2-NEXT: paddq %xmm4, %xmm0 +; SSE2-NEXT: pcmpgtd %xmm5, %xmm8 +; SSE2-NEXT: punpckldq {{.*#+}} xmm5 = xmm5[0],xmm8[0],xmm5[1],xmm8[1] +; SSE2-NEXT: paddq %xmm9, %xmm5 +; SSE2-NEXT: psrlq $1, %xmm3 +; SSE2-NEXT: psrlq $1, %xmm10 +; SSE2-NEXT: shufps {{.*#+}} xmm3 = xmm3[0,2],xmm10[0,2] +; SSE2-NEXT: psrlq $1, %xmm2 +; SSE2-NEXT: psrlq $1, %xmm7 +; SSE2-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,2],xmm7[0,2] +; SSE2-NEXT: psrlq $1, %xmm1 +; SSE2-NEXT: psrlq $1, %xmm6 +; SSE2-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm6[0,2] +; SSE2-NEXT: psrlq $1, %xmm0 +; SSE2-NEXT: psrlq $1, %xmm5 +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm5[0,2] +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v16i32: +; SSE4: # %bb.0: +; SSE4-NEXT: pmovsxdq %xmm3, %xmm8 +; SSE4-NEXT: pshufd {{.*#+}} xmm3 = xmm3[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm3, %xmm9 +; SSE4-NEXT: pmovsxdq %xmm2, %xmm10 +; SSE4-NEXT: pshufd {{.*#+}} xmm2 = xmm2[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm2, %xmm11 +; SSE4-NEXT: pmovsxdq %xmm1, %xmm12 +; SSE4-NEXT: pshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm1, %xmm13 +; SSE4-NEXT: pmovsxdq %xmm0, %xmm14 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm0, %xmm15 +; SSE4-NEXT: pmovsxdq %xmm7, %xmm3 +; SSE4-NEXT: paddq %xmm8, %xmm3 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm7[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm0, %xmm7 +; SSE4-NEXT: paddq %xmm9, %xmm7 +; SSE4-NEXT: pmovsxdq %xmm6, %xmm2 +; SSE4-NEXT: paddq %xmm10, %xmm2 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm6[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm0, %xmm6 +; SSE4-NEXT: paddq %xmm11, %xmm6 +; SSE4-NEXT: pmovsxdq %xmm5, %xmm1 +; SSE4-NEXT: paddq %xmm12, %xmm1 +; SSE4-NEXT: pshufd {{.*#+}} xmm0 = xmm5[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm0, %xmm5 +; SSE4-NEXT: paddq %xmm13, %xmm5 +; SSE4-NEXT: pmovsxdq %xmm4, %xmm0 +; SSE4-NEXT: paddq %xmm14, %xmm0 +; SSE4-NEXT: pshufd {{.*#+}} xmm4 = xmm4[2,3,2,3] +; SSE4-NEXT: pmovsxdq %xmm4, %xmm4 +; SSE4-NEXT: paddq %xmm15, %xmm4 +; SSE4-NEXT: psrlq $1, %xmm3 +; SSE4-NEXT: psrlq $1, %xmm7 +; SSE4-NEXT: shufps {{.*#+}} xmm3 = xmm3[0,2],xmm7[0,2] +; SSE4-NEXT: psrlq $1, %xmm2 +; SSE4-NEXT: psrlq $1, %xmm6 +; SSE4-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,2],xmm6[0,2] +; SSE4-NEXT: psrlq $1, %xmm1 +; SSE4-NEXT: psrlq $1, %xmm5 +; SSE4-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm5[0,2] +; SSE4-NEXT: psrlq $1, %xmm0 +; SSE4-NEXT: psrlq $1, %xmm4 +; SSE4-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm4[0,2] +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v16i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm4 +; AVX1-NEXT: vpshufd {{.*#+}} xmm5 = xmm4[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm5, %xmm5 +; AVX1-NEXT: vpshufd {{.*#+}} xmm6 = xmm1[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm6, %xmm6 +; AVX1-NEXT: vpmovsxdq %xmm4, %xmm4 +; AVX1-NEXT: vpmovsxdq %xmm1, %xmm1 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm7 +; AVX1-NEXT: vpshufd {{.*#+}} xmm8 = xmm7[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm8, %xmm8 +; AVX1-NEXT: vpshufd {{.*#+}} xmm9 = xmm0[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm9, %xmm9 +; AVX1-NEXT: vpmovsxdq %xmm7, %xmm7 +; AVX1-NEXT: vpmovsxdq %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm10 +; AVX1-NEXT: vpshufd {{.*#+}} xmm11 = xmm10[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm11, %xmm11 +; AVX1-NEXT: vpaddq %xmm5, %xmm11, %xmm5 +; AVX1-NEXT: vpshufd {{.*#+}} xmm11 = xmm3[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm11, %xmm11 +; AVX1-NEXT: vpaddq %xmm6, %xmm11, %xmm6 +; AVX1-NEXT: vpmovsxdq %xmm10, %xmm10 +; AVX1-NEXT: vpaddq %xmm4, %xmm10, %xmm4 +; AVX1-NEXT: vpmovsxdq %xmm3, %xmm3 +; AVX1-NEXT: vpaddq %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3 +; AVX1-NEXT: vpshufd {{.*#+}} xmm10 = xmm3[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm10, %xmm10 +; AVX1-NEXT: vpaddq %xmm10, %xmm8, %xmm8 +; AVX1-NEXT: vpshufd {{.*#+}} xmm10 = xmm2[2,3,2,3] +; AVX1-NEXT: vpmovsxdq %xmm10, %xmm10 +; AVX1-NEXT: vpaddq %xmm10, %xmm9, %xmm9 +; AVX1-NEXT: vpmovsxdq %xmm3, %xmm3 +; AVX1-NEXT: vpaddq %xmm3, %xmm7, %xmm3 +; AVX1-NEXT: vpmovsxdq %xmm2, %xmm2 +; AVX1-NEXT: vpaddq %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlq $1, %xmm5, %xmm2 +; AVX1-NEXT: vpsrlq $1, %xmm6, %xmm5 +; AVX1-NEXT: vpsrlq $1, %xmm4, %xmm4 +; AVX1-NEXT: vpsrlq $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm8, %xmm6 +; AVX1-NEXT: vpsrlq $1, %xmm9, %xmm7 +; AVX1-NEXT: vpsrlq $1, %xmm3, %xmm3 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm3, %ymm0, %ymm0 +; AVX1-NEXT: vinsertf128 $1, %xmm6, %ymm7, %ymm3 +; AVX1-NEXT: vshufps {{.*#+}} ymm0 = ymm0[0,2],ymm3[0,2],ymm0[4,6],ymm3[4,6] +; AVX1-NEXT: vinsertf128 $1, %xmm4, %ymm1, %ymm1 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm5, %ymm2 +; AVX1-NEXT: vshufps {{.*#+}} ymm1 = ymm1[0,2],ymm2[0,2],ymm1[4,6],ymm2[4,6] +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v16i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm4 +; AVX2-NEXT: vpmovsxdq %xmm4, %ymm4 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm5 +; AVX2-NEXT: vpmovsxdq %xmm5, %ymm5 +; AVX2-NEXT: vpmovsxdq %xmm0, %ymm0 +; AVX2-NEXT: vpmovsxdq %xmm1, %ymm1 +; AVX2-NEXT: vextracti128 $1, %ymm3, %xmm6 +; AVX2-NEXT: vpmovsxdq %xmm6, %ymm6 +; AVX2-NEXT: vpaddq %ymm6, %ymm4, %ymm4 +; AVX2-NEXT: vextracti128 $1, %ymm2, %xmm6 +; AVX2-NEXT: vpmovsxdq %xmm6, %ymm6 +; AVX2-NEXT: vpaddq %ymm6, %ymm5, %ymm5 +; AVX2-NEXT: vpmovsxdq %xmm2, %ymm2 +; AVX2-NEXT: vpaddq %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpmovsxdq %xmm3, %ymm2 +; AVX2-NEXT: vpaddq %ymm2, %ymm1, %ymm1 +; AVX2-NEXT: vperm2i128 {{.*#+}} ymm2 = ymm0[2,3],ymm5[2,3] +; AVX2-NEXT: vpsrlq $1, %ymm2, %ymm2 +; AVX2-NEXT: vinserti128 $1, %xmm5, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vshufps {{.*#+}} ymm0 = ymm0[0,2],ymm2[0,2],ymm0[4,6],ymm2[4,6] +; AVX2-NEXT: vperm2i128 {{.*#+}} ymm2 = ymm1[2,3],ymm4[2,3] +; AVX2-NEXT: vpsrlq $1, %ymm2, %ymm2 +; AVX2-NEXT: vinserti128 $1, %xmm4, %ymm1, %ymm1 +; AVX2-NEXT: vpsrlq $1, %ymm1, %ymm1 +; AVX2-NEXT: vshufps {{.*#+}} ymm1 = ymm1[0,2],ymm2[0,2],ymm1[4,6],ymm2[4,6] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v16i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vextracti64x4 $1, %zmm0, %ymm2 +; AVX512-NEXT: vpmovsxdq %ymm2, %zmm2 +; AVX512-NEXT: vpmovsxdq %ymm0, %zmm0 +; AVX512-NEXT: vextracti64x4 $1, %zmm1, %ymm3 +; AVX512-NEXT: vpmovsxdq %ymm3, %zmm3 +; AVX512-NEXT: vpaddq %zmm3, %zmm2, %zmm2 +; AVX512-NEXT: vpmovsxdq %ymm1, %zmm1 +; AVX512-NEXT: vpaddq %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlq $1, %zmm2, %zmm1 +; AVX512-NEXT: vpsrlq $1, %zmm0, %zmm0 +; AVX512-NEXT: vpmovqd %zmm0, %ymm0 +; AVX512-NEXT: vpmovqd %zmm1, %ymm1 +; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm0, %zmm0 +; AVX512-NEXT: retq + %x0 = sext <16 x i32> %a0 to <16 x i64> + %x1 = sext <16 x i32> %a1 to <16 x i64> + %sum = add <16 x i64> %x0, %x1 + %shift = ashr <16 x i64> %sum, <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1> + %res = trunc <16 x i64> %shift to <16 x i32> + ret <16 x i32> %res +} + +define <8 x i64> @test_fixed_v8i64(<8 x i64> %a0, <8 x i64> %a1) { +; SSE2-LABEL: test_fixed_v8i64: +; SSE2: # %bb.0: +; SSE2-NEXT: movdqa %xmm3, %xmm11 +; SSE2-NEXT: pand %xmm7, %xmm11 +; SSE2-NEXT: movdqa %xmm2, %xmm10 +; SSE2-NEXT: pand %xmm6, %xmm10 +; SSE2-NEXT: movdqa %xmm1, %xmm9 +; SSE2-NEXT: pand %xmm5, %xmm9 +; SSE2-NEXT: movdqa %xmm0, %xmm8 +; SSE2-NEXT: pand %xmm4, %xmm8 +; SSE2-NEXT: pxor %xmm0, %xmm4 +; SSE2-NEXT: pxor %xmm1, %xmm5 +; SSE2-NEXT: pxor %xmm2, %xmm6 +; SSE2-NEXT: pxor %xmm3, %xmm7 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm7[1,3,2,3] +; SSE2-NEXT: psrad $1, %xmm0 +; SSE2-NEXT: psrlq $1, %xmm7 +; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm7[0,2,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1] +; SSE2-NEXT: paddq %xmm11, %xmm3 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm6[1,3,2,3] +; SSE2-NEXT: psrad $1, %xmm0 +; SSE2-NEXT: psrlq $1, %xmm6 +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm6[0,2,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1] +; SSE2-NEXT: paddq %xmm10, %xmm2 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm5[1,3,2,3] +; SSE2-NEXT: psrad $1, %xmm0 +; SSE2-NEXT: psrlq $1, %xmm5 +; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm5[0,2,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] +; SSE2-NEXT: paddq %xmm9, %xmm1 +; SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm4[1,3,2,3] +; SSE2-NEXT: psrad $1, %xmm5 +; SSE2-NEXT: psrlq $1, %xmm4 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm4[0,2,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm5[0],xmm0[1],xmm5[1] +; SSE2-NEXT: paddq %xmm8, %xmm0 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_fixed_v8i64: +; SSE4: # %bb.0: +; SSE4-NEXT: movdqa %xmm3, %xmm10 +; SSE4-NEXT: pand %xmm7, %xmm10 +; SSE4-NEXT: movdqa %xmm2, %xmm11 +; SSE4-NEXT: pand %xmm6, %xmm11 +; SSE4-NEXT: movdqa %xmm1, %xmm9 +; SSE4-NEXT: pand %xmm5, %xmm9 +; SSE4-NEXT: movdqa %xmm0, %xmm8 +; SSE4-NEXT: pand %xmm4, %xmm8 +; SSE4-NEXT: pxor %xmm4, %xmm0 +; SSE4-NEXT: pxor %xmm5, %xmm1 +; SSE4-NEXT: pxor %xmm6, %xmm2 +; SSE4-NEXT: pxor %xmm7, %xmm3 +; SSE4-NEXT: movdqa %xmm3, %xmm4 +; SSE4-NEXT: psrad $1, %xmm4 +; SSE4-NEXT: psrlq $1, %xmm3 +; SSE4-NEXT: pblendw {{.*#+}} xmm3 = xmm3[0,1],xmm4[2,3],xmm3[4,5],xmm4[6,7] +; SSE4-NEXT: paddq %xmm10, %xmm3 +; SSE4-NEXT: movdqa %xmm2, %xmm4 +; SSE4-NEXT: psrad $1, %xmm4 +; SSE4-NEXT: psrlq $1, %xmm2 +; SSE4-NEXT: pblendw {{.*#+}} xmm2 = xmm2[0,1],xmm4[2,3],xmm2[4,5],xmm4[6,7] +; SSE4-NEXT: paddq %xmm11, %xmm2 +; SSE4-NEXT: movdqa %xmm1, %xmm4 +; SSE4-NEXT: psrad $1, %xmm4 +; SSE4-NEXT: psrlq $1, %xmm1 +; SSE4-NEXT: pblendw {{.*#+}} xmm1 = xmm1[0,1],xmm4[2,3],xmm1[4,5],xmm4[6,7] +; SSE4-NEXT: paddq %xmm9, %xmm1 +; SSE4-NEXT: movdqa %xmm0, %xmm4 +; SSE4-NEXT: psrad $1, %xmm4 +; SSE4-NEXT: psrlq $1, %xmm0 +; SSE4-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm4[2,3],xmm0[4,5],xmm4[6,7] +; SSE4-NEXT: paddq %xmm8, %xmm0 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_fixed_v8i64: +; AVX1: # %bb.0: +; AVX1-NEXT: vandps %ymm3, %ymm1, %ymm4 +; AVX1-NEXT: vandps %ymm2, %ymm0, %ymm5 +; AVX1-NEXT: vxorps %ymm0, %ymm2, %ymm0 +; AVX1-NEXT: vxorps %ymm1, %ymm3, %ymm1 +; AVX1-NEXT: vpsrad $1, %xmm1, %xmm2 +; AVX1-NEXT: vpsrlq $1, %xmm1, %xmm3 +; AVX1-NEXT: vpblendw {{.*#+}} xmm2 = xmm3[0,1],xmm2[2,3],xmm3[4,5],xmm2[6,7] +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpsrad $1, %xmm1, %xmm3 +; AVX1-NEXT: vpsrlq $1, %xmm1, %xmm1 +; AVX1-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0,1],xmm3[2,3],xmm1[4,5],xmm3[6,7] +; AVX1-NEXT: vpsrad $1, %xmm0, %xmm3 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm6 +; AVX1-NEXT: vpblendw {{.*#+}} xmm3 = xmm6[0,1],xmm3[2,3],xmm6[4,5],xmm3[6,7] +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrad $1, %xmm0, %xmm6 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vpblendw {{.*#+}} xmm0 = xmm0[0,1],xmm6[2,3],xmm0[4,5],xmm6[6,7] +; AVX1-NEXT: vextractf128 $1, %ymm5, %xmm6 +; AVX1-NEXT: vpaddq %xmm0, %xmm6, %xmm0 +; AVX1-NEXT: vpaddq %xmm3, %xmm5, %xmm3 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm3, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm4, %xmm3 +; AVX1-NEXT: vpaddq %xmm1, %xmm3, %xmm1 +; AVX1-NEXT: vpaddq %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v8i64: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %ymm3, %ymm1, %ymm4 +; AVX2-NEXT: vpand %ymm2, %ymm0, %ymm5 +; AVX2-NEXT: vpxor %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: vpxor %ymm1, %ymm3, %ymm1 +; AVX2-NEXT: vpsrad $1, %ymm1, %ymm2 +; AVX2-NEXT: vpsrlq $1, %ymm1, %ymm1 +; AVX2-NEXT: vpblendd {{.*#+}} ymm1 = ymm1[0],ymm2[1],ymm1[2],ymm2[3],ymm1[4],ymm2[5],ymm1[6],ymm2[7] +; AVX2-NEXT: vpaddq %ymm1, %ymm4, %ymm1 +; AVX2-NEXT: vpsrad $1, %ymm0, %ymm2 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vpblendd {{.*#+}} ymm0 = ymm0[0],ymm2[1],ymm0[2],ymm2[3],ymm0[4],ymm2[5],ymm0[6],ymm2[7] +; AVX2-NEXT: vpaddq %ymm0, %ymm5, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v8i64: +; AVX512: # %bb.0: +; AVX512-NEXT: vpandq %zmm1, %zmm0, %zmm2 +; AVX512-NEXT: vpxorq %zmm0, %zmm1, %zmm0 +; AVX512-NEXT: vpsraq $1, %zmm0, %zmm0 +; AVX512-NEXT: vpaddq %zmm0, %zmm2, %zmm0 +; AVX512-NEXT: retq + %and = and <8 x i64> %a0, %a1 + %xor = xor <8 x i64> %a1, %a0 + %shift = ashr <8 x i64> %xor, <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1> + %res = add <8 x i64> %and, %shift + ret <8 x i64> %res +} + +define <8 x i64> @test_ext_v8i64(<8 x i64> %a0, <8 x i64> %a1) { +; SSE2-LABEL: test_ext_v8i64: +; SSE2: # %bb.0: +; SSE2-NEXT: pushq %rbp +; SSE2-NEXT: .cfi_def_cfa_offset 16 +; SSE2-NEXT: pushq %r15 +; SSE2-NEXT: .cfi_def_cfa_offset 24 +; SSE2-NEXT: pushq %r14 +; SSE2-NEXT: .cfi_def_cfa_offset 32 +; SSE2-NEXT: pushq %r13 +; SSE2-NEXT: .cfi_def_cfa_offset 40 +; SSE2-NEXT: pushq %r12 +; SSE2-NEXT: .cfi_def_cfa_offset 48 +; SSE2-NEXT: pushq %rbx +; SSE2-NEXT: .cfi_def_cfa_offset 56 +; SSE2-NEXT: pushq %rax +; SSE2-NEXT: .cfi_def_cfa_offset 64 +; SSE2-NEXT: .cfi_offset %rbx, -56 +; SSE2-NEXT: .cfi_offset %r12, -48 +; SSE2-NEXT: .cfi_offset %r13, -40 +; SSE2-NEXT: .cfi_offset %r14, -32 +; SSE2-NEXT: .cfi_offset %r15, -24 +; SSE2-NEXT: .cfi_offset %rbp, -16 +; SSE2-NEXT: pshufd {{.*#+}} xmm8 = xmm3[2,3,2,3] +; SSE2-NEXT: movq %xmm8, %rax +; SSE2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: sarq $63, %rcx +; SSE2-NEXT: movq %rcx, (%rsp) # 8-byte Spill +; SSE2-NEXT: movq %xmm3, %rax +; SSE2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: sarq $63, %rcx +; SSE2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm2[2,3,2,3] +; SSE2-NEXT: movq %xmm3, %rax +; SSE2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: sarq $63, %rcx +; SSE2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: movq %xmm2, %rax +; SSE2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: sarq $63, %rcx +; SSE2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] +; SSE2-NEXT: movq %xmm2, %rax +; SSE2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: sarq $63, %rcx +; SSE2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: movq %xmm1, %rbp +; SSE2-NEXT: movq %rbp, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: sarq $63, %rbp +; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] +; SSE2-NEXT: movq %xmm1, %rbx +; SSE2-NEXT: movq %rbx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: sarq $63, %rbx +; SSE2-NEXT: movq %xmm0, %r15 +; SSE2-NEXT: movq %r15, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: sarq $63, %r15 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm7[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %r10 +; SSE2-NEXT: movq %r10, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: sarq $63, %r10 +; SSE2-NEXT: movq %xmm7, %r9 +; SSE2-NEXT: movq %r9, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: sarq $63, %r9 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm6[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %r12 +; SSE2-NEXT: movq %r12, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: sarq $63, %r12 +; SSE2-NEXT: movq %xmm6, %r13 +; SSE2-NEXT: movq %r13, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: sarq $63, %r13 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm5[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %r14 +; SSE2-NEXT: movq %r14, %rsi +; SSE2-NEXT: sarq $63, %rsi +; SSE2-NEXT: movq %xmm5, %r11 +; SSE2-NEXT: movq %r11, %rdx +; SSE2-NEXT: sarq $63, %rdx +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm4[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %r8 +; SSE2-NEXT: movq %r8, %rdi +; SSE2-NEXT: sarq $63, %rdi +; SSE2-NEXT: movq %xmm4, %rcx +; SSE2-NEXT: movq %rcx, %rax +; SSE2-NEXT: sarq $63, %rax +; SSE2-NEXT: addq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill +; SSE2-NEXT: adcq %r15, %rax +; SSE2-NEXT: addq %r8, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill +; SSE2-NEXT: adcq %rbx, %rdi +; SSE2-NEXT: addq %r11, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill +; SSE2-NEXT: adcq %rbp, %rdx +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r15 # 8-byte Reload +; SSE2-NEXT: addq %r14, %r15 +; SSE2-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Folded Reload +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload +; SSE2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Folded Reload +; SSE2-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r13 # 8-byte Folded Reload +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Reload +; SSE2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Folded Reload +; SSE2-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r12 # 8-byte Folded Reload +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r8 # 8-byte Reload +; SSE2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r8 # 8-byte Folded Reload +; SSE2-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r9 # 8-byte Folded Reload +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; SSE2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Folded Reload +; SSE2-NEXT: adcq (%rsp), %r10 # 8-byte Folded Reload +; SSE2-NEXT: shldq $63, %rcx, %r10 +; SSE2-NEXT: shldq $63, %r8, %r9 +; SSE2-NEXT: shldq $63, %r11, %r12 +; SSE2-NEXT: shldq $63, %rbx, %r13 +; SSE2-NEXT: shldq $63, %r15, %rsi +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; SSE2-NEXT: shldq $63, %rcx, %rdx +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; SSE2-NEXT: shldq $63, %rcx, %rdi +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; SSE2-NEXT: shldq $63, %rcx, %rax +; SSE2-NEXT: movq %rax, %xmm0 +; SSE2-NEXT: movq %rdi, %xmm4 +; SSE2-NEXT: movq %rdx, %xmm1 +; SSE2-NEXT: movq %rsi, %xmm5 +; SSE2-NEXT: movq %r13, %xmm2 +; SSE2-NEXT: movq %r12, %xmm6 +; SSE2-NEXT: movq %r9, %xmm3 +; SSE2-NEXT: movq %r10, %xmm7 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm4[0] +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm5[0] +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm6[0] +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm3 = xmm3[0],xmm7[0] +; SSE2-NEXT: addq $8, %rsp +; SSE2-NEXT: .cfi_def_cfa_offset 56 +; SSE2-NEXT: popq %rbx +; SSE2-NEXT: .cfi_def_cfa_offset 48 +; SSE2-NEXT: popq %r12 +; SSE2-NEXT: .cfi_def_cfa_offset 40 +; SSE2-NEXT: popq %r13 +; SSE2-NEXT: .cfi_def_cfa_offset 32 +; SSE2-NEXT: popq %r14 +; SSE2-NEXT: .cfi_def_cfa_offset 24 +; SSE2-NEXT: popq %r15 +; SSE2-NEXT: .cfi_def_cfa_offset 16 +; SSE2-NEXT: popq %rbp +; SSE2-NEXT: .cfi_def_cfa_offset 8 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v8i64: +; SSE4: # %bb.0: +; SSE4-NEXT: pushq %rbp +; SSE4-NEXT: .cfi_def_cfa_offset 16 +; SSE4-NEXT: pushq %r15 +; SSE4-NEXT: .cfi_def_cfa_offset 24 +; SSE4-NEXT: pushq %r14 +; SSE4-NEXT: .cfi_def_cfa_offset 32 +; SSE4-NEXT: pushq %r13 +; SSE4-NEXT: .cfi_def_cfa_offset 40 +; SSE4-NEXT: pushq %r12 +; SSE4-NEXT: .cfi_def_cfa_offset 48 +; SSE4-NEXT: pushq %rbx +; SSE4-NEXT: .cfi_def_cfa_offset 56 +; SSE4-NEXT: pushq %rax +; SSE4-NEXT: .cfi_def_cfa_offset 64 +; SSE4-NEXT: .cfi_offset %rbx, -56 +; SSE4-NEXT: .cfi_offset %r12, -48 +; SSE4-NEXT: .cfi_offset %r13, -40 +; SSE4-NEXT: .cfi_offset %r14, -32 +; SSE4-NEXT: .cfi_offset %r15, -24 +; SSE4-NEXT: .cfi_offset %rbp, -16 +; SSE4-NEXT: movq %xmm3, %rax +; SSE4-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: movq %rax, %rcx +; SSE4-NEXT: sarq $63, %rcx +; SSE4-NEXT: movq %rcx, (%rsp) # 8-byte Spill +; SSE4-NEXT: pextrq $1, %xmm3, %rax +; SSE4-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: movq %rax, %rcx +; SSE4-NEXT: sarq $63, %rcx +; SSE4-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: movq %xmm2, %rax +; SSE4-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: movq %rax, %rcx +; SSE4-NEXT: sarq $63, %rcx +; SSE4-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: pextrq $1, %xmm2, %rax +; SSE4-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: movq %rax, %rcx +; SSE4-NEXT: sarq $63, %rcx +; SSE4-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: movq %xmm1, %rax +; SSE4-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: movq %rax, %rcx +; SSE4-NEXT: sarq $63, %rcx +; SSE4-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: pextrq $1, %xmm1, %rbp +; SSE4-NEXT: movq %rbp, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: sarq $63, %rbp +; SSE4-NEXT: movq %xmm0, %rbx +; SSE4-NEXT: movq %rbx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: sarq $63, %rbx +; SSE4-NEXT: pextrq $1, %xmm0, %r14 +; SSE4-NEXT: movq %r14, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: sarq $63, %r14 +; SSE4-NEXT: movq %xmm7, %r10 +; SSE4-NEXT: movq %r10, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: sarq $63, %r10 +; SSE4-NEXT: pextrq $1, %xmm7, %r9 +; SSE4-NEXT: movq %r9, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: sarq $63, %r9 +; SSE4-NEXT: movq %xmm6, %r15 +; SSE4-NEXT: movq %r15, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: sarq $63, %r15 +; SSE4-NEXT: pextrq $1, %xmm6, %r13 +; SSE4-NEXT: movq %r13, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: sarq $63, %r13 +; SSE4-NEXT: movq %xmm5, %r12 +; SSE4-NEXT: movq %r12, %rsi +; SSE4-NEXT: sarq $63, %rsi +; SSE4-NEXT: pextrq $1, %xmm5, %r11 +; SSE4-NEXT: movq %r11, %rdx +; SSE4-NEXT: sarq $63, %rdx +; SSE4-NEXT: movq %xmm4, %r8 +; SSE4-NEXT: movq %r8, %rdi +; SSE4-NEXT: sarq $63, %rdi +; SSE4-NEXT: pextrq $1, %xmm4, %rcx +; SSE4-NEXT: movq %rcx, %rax +; SSE4-NEXT: sarq $63, %rax +; SSE4-NEXT: addq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill +; SSE4-NEXT: adcq %r14, %rax +; SSE4-NEXT: addq %r8, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill +; SSE4-NEXT: adcq %rbx, %rdi +; SSE4-NEXT: addq %r11, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill +; SSE4-NEXT: adcq %rbp, %rdx +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r14 # 8-byte Reload +; SSE4-NEXT: addq %r12, %r14 +; SSE4-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Folded Reload +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload +; SSE4-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Folded Reload +; SSE4-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r13 # 8-byte Folded Reload +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Reload +; SSE4-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Folded Reload +; SSE4-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r15 # 8-byte Folded Reload +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r8 # 8-byte Reload +; SSE4-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r8 # 8-byte Folded Reload +; SSE4-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r9 # 8-byte Folded Reload +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; SSE4-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Folded Reload +; SSE4-NEXT: adcq (%rsp), %r10 # 8-byte Folded Reload +; SSE4-NEXT: shldq $63, %rcx, %r10 +; SSE4-NEXT: shldq $63, %r8, %r9 +; SSE4-NEXT: shldq $63, %r11, %r15 +; SSE4-NEXT: shldq $63, %rbx, %r13 +; SSE4-NEXT: shldq $63, %r14, %rsi +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; SSE4-NEXT: shldq $63, %rcx, %rdx +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; SSE4-NEXT: shldq $63, %rcx, %rdi +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; SSE4-NEXT: shldq $63, %rcx, %rax +; SSE4-NEXT: movq %rax, %xmm4 +; SSE4-NEXT: movq %rdi, %xmm0 +; SSE4-NEXT: movq %rdx, %xmm5 +; SSE4-NEXT: movq %rsi, %xmm1 +; SSE4-NEXT: movq %r13, %xmm6 +; SSE4-NEXT: movq %r15, %xmm2 +; SSE4-NEXT: movq %r9, %xmm7 +; SSE4-NEXT: movq %r10, %xmm3 +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm4[0] +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm5[0] +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm6[0] +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm3 = xmm3[0],xmm7[0] +; SSE4-NEXT: addq $8, %rsp +; SSE4-NEXT: .cfi_def_cfa_offset 56 +; SSE4-NEXT: popq %rbx +; SSE4-NEXT: .cfi_def_cfa_offset 48 +; SSE4-NEXT: popq %r12 +; SSE4-NEXT: .cfi_def_cfa_offset 40 +; SSE4-NEXT: popq %r13 +; SSE4-NEXT: .cfi_def_cfa_offset 32 +; SSE4-NEXT: popq %r14 +; SSE4-NEXT: .cfi_def_cfa_offset 24 +; SSE4-NEXT: popq %r15 +; SSE4-NEXT: .cfi_def_cfa_offset 16 +; SSE4-NEXT: popq %rbp +; SSE4-NEXT: .cfi_def_cfa_offset 8 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v8i64: +; AVX1: # %bb.0: +; AVX1-NEXT: pushq %rbp +; AVX1-NEXT: .cfi_def_cfa_offset 16 +; AVX1-NEXT: pushq %r15 +; AVX1-NEXT: .cfi_def_cfa_offset 24 +; AVX1-NEXT: pushq %r14 +; AVX1-NEXT: .cfi_def_cfa_offset 32 +; AVX1-NEXT: pushq %r13 +; AVX1-NEXT: .cfi_def_cfa_offset 40 +; AVX1-NEXT: pushq %r12 +; AVX1-NEXT: .cfi_def_cfa_offset 48 +; AVX1-NEXT: pushq %rbx +; AVX1-NEXT: .cfi_def_cfa_offset 56 +; AVX1-NEXT: pushq %rax +; AVX1-NEXT: .cfi_def_cfa_offset 64 +; AVX1-NEXT: .cfi_offset %rbx, -56 +; AVX1-NEXT: .cfi_offset %r12, -48 +; AVX1-NEXT: .cfi_offset %r13, -40 +; AVX1-NEXT: .cfi_offset %r14, -32 +; AVX1-NEXT: .cfi_offset %r15, -24 +; AVX1-NEXT: .cfi_offset %rbp, -16 +; AVX1-NEXT: vmovq %xmm1, %rax +; AVX1-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: movq %rax, %rcx +; AVX1-NEXT: sarq $63, %rcx +; AVX1-NEXT: movq %rcx, (%rsp) # 8-byte Spill +; AVX1-NEXT: vpextrq $1, %xmm1, %rax +; AVX1-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: movq %rax, %rcx +; AVX1-NEXT: sarq $63, %rcx +; AVX1-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vmovq %xmm1, %rax +; AVX1-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: movq %rax, %rcx +; AVX1-NEXT: sarq $63, %rcx +; AVX1-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: vpextrq $1, %xmm1, %rax +; AVX1-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: movq %rax, %rcx +; AVX1-NEXT: sarq $63, %rcx +; AVX1-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: vmovq %xmm0, %rax +; AVX1-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: movq %rax, %rcx +; AVX1-NEXT: sarq $63, %rcx +; AVX1-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: vpextrq $1, %xmm0, %rbp +; AVX1-NEXT: movq %rbp, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: sarq $63, %rbp +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vmovq %xmm0, %rbx +; AVX1-NEXT: movq %rbx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: sarq $63, %rbx +; AVX1-NEXT: vpextrq $1, %xmm0, %r15 +; AVX1-NEXT: movq %r15, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: sarq $63, %r15 +; AVX1-NEXT: vmovq %xmm3, %r9 +; AVX1-NEXT: movq %r9, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: sarq $63, %r9 +; AVX1-NEXT: vpextrq $1, %xmm3, %r10 +; AVX1-NEXT: movq %r10, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: sarq $63, %r10 +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm0 +; AVX1-NEXT: vmovq %xmm0, %r12 +; AVX1-NEXT: movq %r12, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: sarq $63, %r12 +; AVX1-NEXT: vpextrq $1, %xmm0, %r13 +; AVX1-NEXT: movq %r13, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: sarq $63, %r13 +; AVX1-NEXT: vmovq %xmm2, %r14 +; AVX1-NEXT: movq %r14, %rsi +; AVX1-NEXT: sarq $63, %rsi +; AVX1-NEXT: vpextrq $1, %xmm2, %r11 +; AVX1-NEXT: movq %r11, %rdx +; AVX1-NEXT: sarq $63, %rdx +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm0 +; AVX1-NEXT: vmovq %xmm0, %r8 +; AVX1-NEXT: movq %r8, %rdi +; AVX1-NEXT: sarq $63, %rdi +; AVX1-NEXT: vpextrq $1, %xmm0, %rcx +; AVX1-NEXT: movq %rcx, %rax +; AVX1-NEXT: sarq $63, %rax +; AVX1-NEXT: addq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill +; AVX1-NEXT: adcq %r15, %rax +; AVX1-NEXT: addq %r8, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill +; AVX1-NEXT: adcq %rbx, %rdi +; AVX1-NEXT: addq %r11, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill +; AVX1-NEXT: adcq %rbp, %rdx +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r15 # 8-byte Reload +; AVX1-NEXT: addq %r14, %r15 +; AVX1-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Folded Reload +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload +; AVX1-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Folded Reload +; AVX1-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r13 # 8-byte Folded Reload +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Reload +; AVX1-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Folded Reload +; AVX1-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r12 # 8-byte Folded Reload +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r8 # 8-byte Reload +; AVX1-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r8 # 8-byte Folded Reload +; AVX1-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Folded Reload +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; AVX1-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Folded Reload +; AVX1-NEXT: adcq (%rsp), %r9 # 8-byte Folded Reload +; AVX1-NEXT: shldq $63, %rcx, %r9 +; AVX1-NEXT: shldq $63, %r8, %r10 +; AVX1-NEXT: shldq $63, %r11, %r12 +; AVX1-NEXT: shldq $63, %rbx, %r13 +; AVX1-NEXT: shldq $63, %r15, %rsi +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; AVX1-NEXT: shldq $63, %rcx, %rdx +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; AVX1-NEXT: shldq $63, %rcx, %rdi +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; AVX1-NEXT: shldq $63, %rcx, %rax +; AVX1-NEXT: vmovq %rax, %xmm0 +; AVX1-NEXT: vmovq %rdi, %xmm1 +; AVX1-NEXT: vmovq %rdx, %xmm2 +; AVX1-NEXT: vmovq %rsi, %xmm3 +; AVX1-NEXT: vmovq %r13, %xmm4 +; AVX1-NEXT: vmovq %r12, %xmm5 +; AVX1-NEXT: vmovq %r10, %xmm6 +; AVX1-NEXT: vmovq %r9, %xmm7 +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm3[0],xmm2[0] +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm5[0],xmm4[0] +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm7[0],xmm6[0] +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: addq $8, %rsp +; AVX1-NEXT: .cfi_def_cfa_offset 56 +; AVX1-NEXT: popq %rbx +; AVX1-NEXT: .cfi_def_cfa_offset 48 +; AVX1-NEXT: popq %r12 +; AVX1-NEXT: .cfi_def_cfa_offset 40 +; AVX1-NEXT: popq %r13 +; AVX1-NEXT: .cfi_def_cfa_offset 32 +; AVX1-NEXT: popq %r14 +; AVX1-NEXT: .cfi_def_cfa_offset 24 +; AVX1-NEXT: popq %r15 +; AVX1-NEXT: .cfi_def_cfa_offset 16 +; AVX1-NEXT: popq %rbp +; AVX1-NEXT: .cfi_def_cfa_offset 8 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v8i64: +; AVX2: # %bb.0: +; AVX2-NEXT: pushq %rbp +; AVX2-NEXT: .cfi_def_cfa_offset 16 +; AVX2-NEXT: pushq %r15 +; AVX2-NEXT: .cfi_def_cfa_offset 24 +; AVX2-NEXT: pushq %r14 +; AVX2-NEXT: .cfi_def_cfa_offset 32 +; AVX2-NEXT: pushq %r13 +; AVX2-NEXT: .cfi_def_cfa_offset 40 +; AVX2-NEXT: pushq %r12 +; AVX2-NEXT: .cfi_def_cfa_offset 48 +; AVX2-NEXT: pushq %rbx +; AVX2-NEXT: .cfi_def_cfa_offset 56 +; AVX2-NEXT: pushq %rax +; AVX2-NEXT: .cfi_def_cfa_offset 64 +; AVX2-NEXT: .cfi_offset %rbx, -56 +; AVX2-NEXT: .cfi_offset %r12, -48 +; AVX2-NEXT: .cfi_offset %r13, -40 +; AVX2-NEXT: .cfi_offset %r14, -32 +; AVX2-NEXT: .cfi_offset %r15, -24 +; AVX2-NEXT: .cfi_offset %rbp, -16 +; AVX2-NEXT: vmovq %xmm1, %rax +; AVX2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: movq %rax, %rcx +; AVX2-NEXT: sarq $63, %rcx +; AVX2-NEXT: movq %rcx, (%rsp) # 8-byte Spill +; AVX2-NEXT: vpextrq $1, %xmm1, %rax +; AVX2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: movq %rax, %rcx +; AVX2-NEXT: sarq $63, %rcx +; AVX2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm1 +; AVX2-NEXT: vmovq %xmm1, %rax +; AVX2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: movq %rax, %rcx +; AVX2-NEXT: sarq $63, %rcx +; AVX2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: vpextrq $1, %xmm1, %rax +; AVX2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: movq %rax, %rcx +; AVX2-NEXT: sarq $63, %rcx +; AVX2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: vmovq %xmm0, %rax +; AVX2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: movq %rax, %rcx +; AVX2-NEXT: sarq $63, %rcx +; AVX2-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: vpextrq $1, %xmm0, %rbp +; AVX2-NEXT: movq %rbp, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: sarq $63, %rbp +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX2-NEXT: vmovq %xmm0, %rbx +; AVX2-NEXT: movq %rbx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: sarq $63, %rbx +; AVX2-NEXT: vpextrq $1, %xmm0, %r15 +; AVX2-NEXT: movq %r15, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: sarq $63, %r15 +; AVX2-NEXT: vmovq %xmm3, %r9 +; AVX2-NEXT: movq %r9, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: sarq $63, %r9 +; AVX2-NEXT: vpextrq $1, %xmm3, %r10 +; AVX2-NEXT: movq %r10, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: sarq $63, %r10 +; AVX2-NEXT: vextracti128 $1, %ymm3, %xmm0 +; AVX2-NEXT: vmovq %xmm0, %r12 +; AVX2-NEXT: movq %r12, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: sarq $63, %r12 +; AVX2-NEXT: vpextrq $1, %xmm0, %r13 +; AVX2-NEXT: movq %r13, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: sarq $63, %r13 +; AVX2-NEXT: vmovq %xmm2, %r14 +; AVX2-NEXT: movq %r14, %rsi +; AVX2-NEXT: sarq $63, %rsi +; AVX2-NEXT: vpextrq $1, %xmm2, %r11 +; AVX2-NEXT: movq %r11, %rdx +; AVX2-NEXT: sarq $63, %rdx +; AVX2-NEXT: vextracti128 $1, %ymm2, %xmm0 +; AVX2-NEXT: vmovq %xmm0, %r8 +; AVX2-NEXT: movq %r8, %rdi +; AVX2-NEXT: sarq $63, %rdi +; AVX2-NEXT: vpextrq $1, %xmm0, %rcx +; AVX2-NEXT: movq %rcx, %rax +; AVX2-NEXT: sarq $63, %rax +; AVX2-NEXT: addq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill +; AVX2-NEXT: adcq %r15, %rax +; AVX2-NEXT: addq %r8, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill +; AVX2-NEXT: adcq %rbx, %rdi +; AVX2-NEXT: addq %r11, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill +; AVX2-NEXT: adcq %rbp, %rdx +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r15 # 8-byte Reload +; AVX2-NEXT: addq %r14, %r15 +; AVX2-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Folded Reload +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload +; AVX2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Folded Reload +; AVX2-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r13 # 8-byte Folded Reload +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Reload +; AVX2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Folded Reload +; AVX2-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r12 # 8-byte Folded Reload +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r8 # 8-byte Reload +; AVX2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r8 # 8-byte Folded Reload +; AVX2-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Folded Reload +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; AVX2-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Folded Reload +; AVX2-NEXT: adcq (%rsp), %r9 # 8-byte Folded Reload +; AVX2-NEXT: shldq $63, %rcx, %r9 +; AVX2-NEXT: shldq $63, %r8, %r10 +; AVX2-NEXT: shldq $63, %r11, %r12 +; AVX2-NEXT: shldq $63, %rbx, %r13 +; AVX2-NEXT: shldq $63, %r15, %rsi +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; AVX2-NEXT: shldq $63, %rcx, %rdx +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; AVX2-NEXT: shldq $63, %rcx, %rdi +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; AVX2-NEXT: shldq $63, %rcx, %rax +; AVX2-NEXT: vmovq %rax, %xmm0 +; AVX2-NEXT: vmovq %rdi, %xmm1 +; AVX2-NEXT: vmovq %rdx, %xmm2 +; AVX2-NEXT: vmovq %rsi, %xmm3 +; AVX2-NEXT: vmovq %r13, %xmm4 +; AVX2-NEXT: vmovq %r12, %xmm5 +; AVX2-NEXT: vmovq %r10, %xmm6 +; AVX2-NEXT: vmovq %r9, %xmm7 +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm3[0],xmm2[0] +; AVX2-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0 +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm5[0],xmm4[0] +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm7[0],xmm6[0] +; AVX2-NEXT: vinserti128 $1, %xmm1, %ymm2, %ymm1 +; AVX2-NEXT: addq $8, %rsp +; AVX2-NEXT: .cfi_def_cfa_offset 56 +; AVX2-NEXT: popq %rbx +; AVX2-NEXT: .cfi_def_cfa_offset 48 +; AVX2-NEXT: popq %r12 +; AVX2-NEXT: .cfi_def_cfa_offset 40 +; AVX2-NEXT: popq %r13 +; AVX2-NEXT: .cfi_def_cfa_offset 32 +; AVX2-NEXT: popq %r14 +; AVX2-NEXT: .cfi_def_cfa_offset 24 +; AVX2-NEXT: popq %r15 +; AVX2-NEXT: .cfi_def_cfa_offset 16 +; AVX2-NEXT: popq %rbp +; AVX2-NEXT: .cfi_def_cfa_offset 8 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v8i64: +; AVX512: # %bb.0: +; AVX512-NEXT: pushq %rbp +; AVX512-NEXT: .cfi_def_cfa_offset 16 +; AVX512-NEXT: pushq %r15 +; AVX512-NEXT: .cfi_def_cfa_offset 24 +; AVX512-NEXT: pushq %r14 +; AVX512-NEXT: .cfi_def_cfa_offset 32 +; AVX512-NEXT: pushq %r13 +; AVX512-NEXT: .cfi_def_cfa_offset 40 +; AVX512-NEXT: pushq %r12 +; AVX512-NEXT: .cfi_def_cfa_offset 48 +; AVX512-NEXT: pushq %rbx +; AVX512-NEXT: .cfi_def_cfa_offset 56 +; AVX512-NEXT: pushq %rax +; AVX512-NEXT: .cfi_def_cfa_offset 64 +; AVX512-NEXT: .cfi_offset %rbx, -56 +; AVX512-NEXT: .cfi_offset %r12, -48 +; AVX512-NEXT: .cfi_offset %r13, -40 +; AVX512-NEXT: .cfi_offset %r14, -32 +; AVX512-NEXT: .cfi_offset %r15, -24 +; AVX512-NEXT: .cfi_offset %rbp, -16 +; AVX512-NEXT: vmovq %xmm0, %rax +; AVX512-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: movq %rax, %rcx +; AVX512-NEXT: sarq $63, %rcx +; AVX512-NEXT: movq %rcx, (%rsp) # 8-byte Spill +; AVX512-NEXT: vpextrq $1, %xmm0, %rax +; AVX512-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: movq %rax, %rcx +; AVX512-NEXT: sarq $63, %rcx +; AVX512-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: vextracti128 $1, %ymm0, %xmm2 +; AVX512-NEXT: vmovq %xmm2, %rax +; AVX512-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: movq %rax, %rcx +; AVX512-NEXT: sarq $63, %rcx +; AVX512-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: vpextrq $1, %xmm2, %rax +; AVX512-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: movq %rax, %rcx +; AVX512-NEXT: sarq $63, %rcx +; AVX512-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: vextracti64x4 $1, %zmm0, %ymm0 +; AVX512-NEXT: vmovq %xmm0, %rax +; AVX512-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: movq %rax, %rcx +; AVX512-NEXT: sarq $63, %rcx +; AVX512-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: vpextrq $1, %xmm0, %r13 +; AVX512-NEXT: movq %r13, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: sarq $63, %r13 +; AVX512-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX512-NEXT: vmovq %xmm0, %r14 +; AVX512-NEXT: movq %r14, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: sarq $63, %r14 +; AVX512-NEXT: vpextrq $1, %xmm0, %r15 +; AVX512-NEXT: movq %r15, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: sarq $63, %r15 +; AVX512-NEXT: vmovq %xmm1, %r9 +; AVX512-NEXT: movq %r9, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: sarq $63, %r9 +; AVX512-NEXT: vpextrq $1, %xmm1, %r11 +; AVX512-NEXT: movq %r11, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: sarq $63, %r11 +; AVX512-NEXT: vextracti128 $1, %ymm1, %xmm0 +; AVX512-NEXT: vmovq %xmm0, %r12 +; AVX512-NEXT: movq %r12, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: sarq $63, %r12 +; AVX512-NEXT: vpextrq $1, %xmm0, %rbp +; AVX512-NEXT: movq %rbp, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: sarq $63, %rbp +; AVX512-NEXT: vextracti64x4 $1, %zmm1, %ymm0 +; AVX512-NEXT: vmovq %xmm0, %rbx +; AVX512-NEXT: movq %rbx, %rsi +; AVX512-NEXT: sarq $63, %rsi +; AVX512-NEXT: vpextrq $1, %xmm0, %r10 +; AVX512-NEXT: movq %r10, %rdx +; AVX512-NEXT: sarq $63, %rdx +; AVX512-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX512-NEXT: vmovq %xmm0, %r8 +; AVX512-NEXT: movq %r8, %rdi +; AVX512-NEXT: sarq $63, %rdi +; AVX512-NEXT: vpextrq $1, %xmm0, %rcx +; AVX512-NEXT: movq %rcx, %rax +; AVX512-NEXT: sarq $63, %rax +; AVX512-NEXT: addq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill +; AVX512-NEXT: adcq %r15, %rax +; AVX512-NEXT: addq %r8, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Folded Spill +; AVX512-NEXT: adcq %r14, %rdi +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r15 # 8-byte Reload +; AVX512-NEXT: addq %r10, %r15 +; AVX512-NEXT: adcq %r13, %rdx +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r14 # 8-byte Reload +; AVX512-NEXT: addq %rbx, %r14 +; AVX512-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %rsi # 8-byte Folded Reload +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Reload +; AVX512-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rbx # 8-byte Folded Reload +; AVX512-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %rbp # 8-byte Folded Reload +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Reload +; AVX512-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r10 # 8-byte Folded Reload +; AVX512-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r12 # 8-byte Folded Reload +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %r8 # 8-byte Reload +; AVX512-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r8 # 8-byte Folded Reload +; AVX512-NEXT: adcq {{[-0-9]+}}(%r{{[sb]}}p), %r11 # 8-byte Folded Reload +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; AVX512-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Folded Reload +; AVX512-NEXT: adcq (%rsp), %r9 # 8-byte Folded Reload +; AVX512-NEXT: shldq $63, %rcx, %r9 +; AVX512-NEXT: shldq $63, %r8, %r11 +; AVX512-NEXT: shldq $63, %r10, %r12 +; AVX512-NEXT: shldq $63, %rbx, %rbp +; AVX512-NEXT: shldq $63, %r14, %rsi +; AVX512-NEXT: shldq $63, %r15, %rdx +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; AVX512-NEXT: shldq $63, %rcx, %rdi +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload +; AVX512-NEXT: shldq $63, %rcx, %rax +; AVX512-NEXT: vmovq %rax, %xmm0 +; AVX512-NEXT: vmovq %rdi, %xmm1 +; AVX512-NEXT: vmovq %rdx, %xmm2 +; AVX512-NEXT: vmovq %rsi, %xmm3 +; AVX512-NEXT: vmovq %rbp, %xmm4 +; AVX512-NEXT: vmovq %r12, %xmm5 +; AVX512-NEXT: vmovq %r11, %xmm6 +; AVX512-NEXT: vmovq %r9, %xmm7 +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm3[0],xmm2[0] +; AVX512-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0 +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm5[0],xmm4[0] +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm7[0],xmm6[0] +; AVX512-NEXT: vinserti128 $1, %xmm1, %ymm2, %ymm1 +; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-NEXT: addq $8, %rsp +; AVX512-NEXT: .cfi_def_cfa_offset 56 +; AVX512-NEXT: popq %rbx +; AVX512-NEXT: .cfi_def_cfa_offset 48 +; AVX512-NEXT: popq %r12 +; AVX512-NEXT: .cfi_def_cfa_offset 40 +; AVX512-NEXT: popq %r13 +; AVX512-NEXT: .cfi_def_cfa_offset 32 +; AVX512-NEXT: popq %r14 +; AVX512-NEXT: .cfi_def_cfa_offset 24 +; AVX512-NEXT: popq %r15 +; AVX512-NEXT: .cfi_def_cfa_offset 16 +; AVX512-NEXT: popq %rbp +; AVX512-NEXT: .cfi_def_cfa_offset 8 +; AVX512-NEXT: retq + %x0 = sext <8 x i64> %a0 to <8 x i128> + %x1 = sext <8 x i64> %a1 to <8 x i128> + %sum = add <8 x i128> %x0, %x1 + %shift = ashr <8 x i128> %sum, <i128 1, i128 1, i128 1, i128 1, i128 1, i128 1, i128 1, i128 1> + %res = trunc <8 x i128> %shift to <8 x i64> + ret <8 x i64> %res +} + diff --git a/llvm/test/CodeGen/X86/avgflooru.ll b/llvm/test/CodeGen/X86/avgflooru.ll new file mode 100644 index 0000000000000000000000000000000000000000..e07c1f55991e84fb2994b7382efbaa40b439ea15 --- /dev/null +++ b/llvm/test/CodeGen/X86/avgflooru.ll @@ -0,0 +1,2629 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-- -mattr=+sse2 | FileCheck %s --check-prefixes=SSE,SSE2 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+sse4.1 | FileCheck %s --check-prefixes=SSE,SSE4 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx | FileCheck %s --check-prefixes=AVX,AVX1 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx2 | FileCheck %s --check-prefixes=AVX,AVX2 +; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64-v4 | FileCheck %s --check-prefixes=AVX,AVX512 + +; +; 128-bit vectors +; + +define <16 x i8> @test_fixed_v16i8(<16 x i8> %a0, <16 x i8> %a1) { +; SSE-LABEL: test_fixed_v16i8: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm0, %xmm2 +; SSE-NEXT: pand %xmm1, %xmm2 +; SSE-NEXT: pxor %xmm1, %xmm0 +; SSE-NEXT: psrlw $1, %xmm0 +; SSE-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; SSE-NEXT: paddb %xmm2, %xmm0 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v16i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX1-NEXT: vpxor %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX1-NEXT: vpaddb %xmm0, %xmm2, %xmm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v16i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX2-NEXT: vpxor %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX2-NEXT: vpaddb %xmm0, %xmm2, %xmm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v16i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX512-NEXT: vpxor %xmm1, %xmm0, %xmm0 +; AVX512-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX512-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to4}, %xmm0, %xmm0 +; AVX512-NEXT: vpaddb %xmm0, %xmm2, %xmm0 +; AVX512-NEXT: retq + %and = and <16 x i8> %a0, %a1 + %xor = xor <16 x i8> %a0, %a1 + %shift = lshr <16 x i8> %xor, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> + %res = add <16 x i8> %and, %shift + ret <16 x i8> %res +} + +define <16 x i8> @test_ext_v16i8(<16 x i8> %a0, <16 x i8> %a1) { +; SSE2-LABEL: test_ext_v16i8: +; SSE2: # %bb.0: +; SSE2-NEXT: pxor %xmm2, %xmm2 +; SSE2-NEXT: movdqa %xmm0, %xmm3 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm2[8],xmm3[9],xmm2[9],xmm3[10],xmm2[10],xmm3[11],xmm2[11],xmm3[12],xmm2[12],xmm3[13],xmm2[13],xmm3[14],xmm2[14],xmm3[15],xmm2[15] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3],xmm0[4],xmm2[4],xmm0[5],xmm2[5],xmm0[6],xmm2[6],xmm0[7],xmm2[7] +; SSE2-NEXT: movdqa %xmm1, %xmm4 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm2[8],xmm4[9],xmm2[9],xmm4[10],xmm2[10],xmm4[11],xmm2[11],xmm4[12],xmm2[12],xmm4[13],xmm2[13],xmm4[14],xmm2[14],xmm4[15],xmm2[15] +; SSE2-NEXT: paddw %xmm3, %xmm4 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3],xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7] +; SSE2-NEXT: paddw %xmm1, %xmm0 +; SSE2-NEXT: psrlw $1, %xmm4 +; SSE2-NEXT: psrlw $1, %xmm0 +; SSE2-NEXT: packuswb %xmm4, %xmm0 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v16i8: +; SSE4: # %bb.0: +; SSE4-NEXT: pxor %xmm3, %xmm3 +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm4 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; SSE4-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm3[8],xmm0[9],xmm3[9],xmm0[10],xmm3[10],xmm0[11],xmm3[11],xmm0[12],xmm3[12],xmm0[13],xmm3[13],xmm0[14],xmm3[14],xmm0[15],xmm3[15] +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero +; SSE4-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm3[8],xmm1[9],xmm3[9],xmm1[10],xmm3[10],xmm1[11],xmm3[11],xmm1[12],xmm3[12],xmm1[13],xmm3[13],xmm1[14],xmm3[14],xmm1[15],xmm3[15] +; SSE4-NEXT: paddw %xmm0, %xmm1 +; SSE4-NEXT: paddw %xmm4, %xmm2 +; SSE4-NEXT: psrlw $1, %xmm1 +; SSE4-NEXT: psrlw $1, %xmm2 +; SSE4-NEXT: packuswb %xmm1, %xmm2 +; SSE4-NEXT: movdqa %xmm2, %xmm0 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v16i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vpxor %xmm2, %xmm2, %xmm2 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8],xmm2[8],xmm0[9],xmm2[9],xmm0[10],xmm2[10],xmm0[11],xmm2[11],xmm0[12],xmm2[12],xmm0[13],xmm2[13],xmm0[14],xmm2[14],xmm0[15],xmm2[15] +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm1[8],xmm2[8],xmm1[9],xmm2[9],xmm1[10],xmm2[10],xmm1[11],xmm2[11],xmm1[12],xmm2[12],xmm1[13],xmm2[13],xmm1[14],xmm2[14],xmm1[15],xmm2[15] +; AVX1-NEXT: vpaddw %xmm2, %xmm3, %xmm2 +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero +; AVX1-NEXT: vpaddw %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm2, %xmm1 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v16i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero +; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero,xmm1[8],zero,xmm1[9],zero,xmm1[10],zero,xmm1[11],zero,xmm1[12],zero,xmm1[13],zero,xmm1[14],zero,xmm1[15],zero +; AVX2-NEXT: vpaddw %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1 +; AVX2-NEXT: vpackuswb %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v16i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero +; AVX512-NEXT: vpmovzxbw {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero,xmm1[8],zero,xmm1[9],zero,xmm1[10],zero,xmm1[11],zero,xmm1[12],zero,xmm1[13],zero,xmm1[14],zero,xmm1[15],zero +; AVX512-NEXT: vpaddw %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX512-NEXT: vpmovwb %ymm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + %x0 = zext <16 x i8> %a0 to <16 x i16> + %x1 = zext <16 x i8> %a1 to <16 x i16> + %sum = add <16 x i16> %x0, %x1 + %shift = lshr <16 x i16> %sum, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = trunc <16 x i16> %shift to <16 x i8> + ret <16 x i8> %res +} + +define <8 x i16> @test_fixed_v8i16(<8 x i16> %a0, <8 x i16> %a1) { +; SSE-LABEL: test_fixed_v8i16: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm0, %xmm2 +; SSE-NEXT: pand %xmm1, %xmm2 +; SSE-NEXT: pxor %xmm1, %xmm0 +; SSE-NEXT: psrlw $1, %xmm0 +; SSE-NEXT: paddw %xmm2, %xmm0 +; SSE-NEXT: retq +; +; AVX-LABEL: test_fixed_v8i16: +; AVX: # %bb.0: +; AVX-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX-NEXT: vpxor %xmm0, %xmm1, %xmm0 +; AVX-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX-NEXT: vpaddw %xmm0, %xmm2, %xmm0 +; AVX-NEXT: retq + %and = and <8 x i16> %a0, %a1 + %xor = xor <8 x i16> %a1, %a0 + %shift = lshr <8 x i16> %xor, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = add <8 x i16> %and, %shift + ret <8 x i16> %res +} + +define <8 x i16> @test_ext_v8i16(<8 x i16> %a0, <8 x i16> %a1) { +; SSE2-LABEL: test_ext_v8i16: +; SSE2: # %bb.0: +; SSE2-NEXT: pxor %xmm2, %xmm2 +; SSE2-NEXT: movdqa %xmm0, %xmm3 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm3 = xmm3[4],xmm2[4],xmm3[5],xmm2[5],xmm3[6],xmm2[6],xmm3[7],xmm2[7] +; SSE2-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3] +; SSE2-NEXT: movdqa %xmm1, %xmm4 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm4 = xmm4[4],xmm2[4],xmm4[5],xmm2[5],xmm4[6],xmm2[6],xmm4[7],xmm2[7] +; SSE2-NEXT: paddd %xmm3, %xmm4 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3] +; SSE2-NEXT: paddd %xmm1, %xmm0 +; SSE2-NEXT: pslld $15, %xmm4 +; SSE2-NEXT: psrad $16, %xmm4 +; SSE2-NEXT: pslld $15, %xmm0 +; SSE2-NEXT: psrad $16, %xmm0 +; SSE2-NEXT: packssdw %xmm4, %xmm0 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v8i16: +; SSE4: # %bb.0: +; SSE4-NEXT: pxor %xmm3, %xmm3 +; SSE4-NEXT: pmovzxwd {{.*#+}} xmm4 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; SSE4-NEXT: punpckhwd {{.*#+}} xmm0 = xmm0[4],xmm3[4],xmm0[5],xmm3[5],xmm0[6],xmm3[6],xmm0[7],xmm3[7] +; SSE4-NEXT: pmovzxwd {{.*#+}} xmm2 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero +; SSE4-NEXT: punpckhwd {{.*#+}} xmm1 = xmm1[4],xmm3[4],xmm1[5],xmm3[5],xmm1[6],xmm3[6],xmm1[7],xmm3[7] +; SSE4-NEXT: paddd %xmm0, %xmm1 +; SSE4-NEXT: paddd %xmm4, %xmm2 +; SSE4-NEXT: psrld $1, %xmm1 +; SSE4-NEXT: psrld $1, %xmm2 +; SSE4-NEXT: packusdw %xmm1, %xmm2 +; SSE4-NEXT: movdqa %xmm2, %xmm0 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v8i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vpxor %xmm2, %xmm2, %xmm2 +; AVX1-NEXT: vpunpckhwd {{.*#+}} xmm3 = xmm0[4],xmm2[4],xmm0[5],xmm2[5],xmm0[6],xmm2[6],xmm0[7],xmm2[7] +; AVX1-NEXT: vpmovzxwd {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; AVX1-NEXT: vpunpckhwd {{.*#+}} xmm2 = xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7] +; AVX1-NEXT: vpaddd %xmm2, %xmm3, %xmm2 +; AVX1-NEXT: vpmovzxwd {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero +; AVX1-NEXT: vpaddd %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrld $1, %xmm2, %xmm1 +; AVX1-NEXT: vpsrld $1, %xmm0, %xmm0 +; AVX1-NEXT: vpackusdw %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v8i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero +; AVX2-NEXT: vpaddd %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrld $1, %ymm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1 +; AVX2-NEXT: vpackusdw %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v8i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX512-NEXT: vpmovzxwd {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero +; AVX512-NEXT: vpaddd %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpsrld $1, %ymm0, %ymm0 +; AVX512-NEXT: vpmovdw %ymm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + %x0 = zext <8 x i16> %a0 to <8 x i32> + %x1 = zext <8 x i16> %a1 to <8 x i32> + %sum = add <8 x i32> %x0, %x1 + %shift = lshr <8 x i32> %sum, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = trunc <8 x i32> %shift to <8 x i16> + ret <8 x i16> %res +} + +define <4 x i32> @test_fixed_v4i32(<4 x i32> %a0, <4 x i32> %a1) { +; SSE-LABEL: test_fixed_v4i32: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm0, %xmm2 +; SSE-NEXT: pand %xmm1, %xmm2 +; SSE-NEXT: pxor %xmm1, %xmm0 +; SSE-NEXT: psrld $1, %xmm0 +; SSE-NEXT: paddd %xmm2, %xmm0 +; SSE-NEXT: retq +; +; AVX-LABEL: test_fixed_v4i32: +; AVX: # %bb.0: +; AVX-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX-NEXT: vpxor %xmm0, %xmm1, %xmm0 +; AVX-NEXT: vpsrld $1, %xmm0, %xmm0 +; AVX-NEXT: vpaddd %xmm0, %xmm2, %xmm0 +; AVX-NEXT: retq + %and = and <4 x i32> %a0, %a1 + %xor = xor <4 x i32> %a1, %a0 + %shift = lshr <4 x i32> %xor, <i32 1, i32 1, i32 1, i32 1> + %res = add <4 x i32> %and, %shift + ret <4 x i32> %res +} + +define <4 x i32> @test_ext_v4i32(<4 x i32> %a0, <4 x i32> %a1) { +; SSE2-LABEL: test_ext_v4i32: +; SSE2: # %bb.0: +; SSE2-NEXT: pxor %xmm2, %xmm2 +; SSE2-NEXT: movdqa %xmm0, %xmm3 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm3 = xmm3[2],xmm2[2],xmm3[3],xmm2[3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1] +; SSE2-NEXT: movdqa %xmm1, %xmm4 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm4 = xmm4[2],xmm2[2],xmm4[3],xmm2[3] +; SSE2-NEXT: paddq %xmm3, %xmm4 +; SSE2-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1] +; SSE2-NEXT: paddq %xmm1, %xmm0 +; SSE2-NEXT: psrlq $1, %xmm4 +; SSE2-NEXT: psrlq $1, %xmm0 +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm4[0,2] +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v4i32: +; SSE4: # %bb.0: +; SSE4-NEXT: pxor %xmm3, %xmm3 +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm4 = xmm0[0],zero,xmm0[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm0 = xmm0[2],xmm3[2],xmm0[3],xmm3[3] +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm2 = xmm1[0],zero,xmm1[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm1 = xmm1[2],xmm3[2],xmm1[3],xmm3[3] +; SSE4-NEXT: paddq %xmm0, %xmm1 +; SSE4-NEXT: paddq %xmm4, %xmm2 +; SSE4-NEXT: psrlq $1, %xmm1 +; SSE4-NEXT: psrlq $1, %xmm2 +; SSE4-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,2],xmm1[0,2] +; SSE4-NEXT: movaps %xmm2, %xmm0 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v4i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vpxor %xmm2, %xmm2, %xmm2 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm3 = xmm0[2],xmm2[2],xmm0[3],xmm2[3] +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm2 = xmm1[2],xmm2[2],xmm1[3],xmm2[3] +; AVX1-NEXT: vpaddq %xmm2, %xmm3, %xmm2 +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero +; AVX1-NEXT: vpaddq %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlq $1, %xmm2, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vshufps {{.*#+}} xmm0 = xmm0[0,2],xmm1[0,2] +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v4i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero +; AVX2-NEXT: vpaddq %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1 +; AVX2-NEXT: vshufps {{.*#+}} xmm0 = xmm0[0,2],xmm1[0,2] +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v4i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovzxdq {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; AVX512-NEXT: vpmovzxdq {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero +; AVX512-NEXT: vpaddq %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX512-NEXT: vpmovqd %ymm0, %xmm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + %x0 = zext <4 x i32> %a0 to <4 x i64> + %x1 = zext <4 x i32> %a1 to <4 x i64> + %sum = add <4 x i64> %x0, %x1 + %shift = lshr <4 x i64> %sum, <i64 1, i64 1, i64 1, i64 1> + %res = trunc <4 x i64> %shift to <4 x i32> + ret <4 x i32> %res +} + +define <2 x i64> @test_fixed_v2i64(<2 x i64> %a0, <2 x i64> %a1) { +; SSE-LABEL: test_fixed_v2i64: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm0, %xmm2 +; SSE-NEXT: pand %xmm1, %xmm2 +; SSE-NEXT: pxor %xmm1, %xmm0 +; SSE-NEXT: psrlq $1, %xmm0 +; SSE-NEXT: paddq %xmm2, %xmm0 +; SSE-NEXT: retq +; +; AVX-LABEL: test_fixed_v2i64: +; AVX: # %bb.0: +; AVX-NEXT: vpand %xmm1, %xmm0, %xmm2 +; AVX-NEXT: vpxor %xmm0, %xmm1, %xmm0 +; AVX-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX-NEXT: vpaddq %xmm0, %xmm2, %xmm0 +; AVX-NEXT: retq + %and = and <2 x i64> %a0, %a1 + %xor = xor <2 x i64> %a1, %a0 + %shift = lshr <2 x i64> %xor, <i64 1, i64 1> + %res = add <2 x i64> %and, %shift + ret <2 x i64> %res +} + +define <2 x i64> @test_ext_v2i64(<2 x i64> %a0, <2 x i64> %a1) { +; SSE2-LABEL: test_ext_v2i64: +; SSE2: # %bb.0: +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm0[2,3,2,3] +; SSE2-NEXT: movq %xmm2, %rax +; SSE2-NEXT: movq %xmm0, %rcx +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %rdx +; SSE2-NEXT: movq %xmm1, %rsi +; SSE2-NEXT: xorl %edi, %edi +; SSE2-NEXT: addq %rcx, %rsi +; SSE2-NEXT: setb %dil +; SSE2-NEXT: xorl %ecx, %ecx +; SSE2-NEXT: addq %rax, %rdx +; SSE2-NEXT: setb %cl +; SSE2-NEXT: shldq $63, %rdx, %rcx +; SSE2-NEXT: shldq $63, %rsi, %rdi +; SSE2-NEXT: movq %rdi, %xmm0 +; SSE2-NEXT: movq %rcx, %xmm1 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v2i64: +; SSE4: # %bb.0: +; SSE4-NEXT: movq %xmm0, %rax +; SSE4-NEXT: pextrq $1, %xmm0, %rcx +; SSE4-NEXT: movq %xmm1, %rdx +; SSE4-NEXT: pextrq $1, %xmm1, %rsi +; SSE4-NEXT: xorl %edi, %edi +; SSE4-NEXT: addq %rcx, %rsi +; SSE4-NEXT: setb %dil +; SSE4-NEXT: xorl %ecx, %ecx +; SSE4-NEXT: addq %rax, %rdx +; SSE4-NEXT: setb %cl +; SSE4-NEXT: shldq $63, %rdx, %rcx +; SSE4-NEXT: shldq $63, %rsi, %rdi +; SSE4-NEXT: movq %rdi, %xmm1 +; SSE4-NEXT: movq %rcx, %xmm0 +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v2i64: +; AVX1: # %bb.0: +; AVX1-NEXT: vmovq %xmm0, %rax +; AVX1-NEXT: vpextrq $1, %xmm0, %rcx +; AVX1-NEXT: vmovq %xmm1, %rdx +; AVX1-NEXT: vpextrq $1, %xmm1, %rsi +; AVX1-NEXT: xorl %edi, %edi +; AVX1-NEXT: addq %rcx, %rsi +; AVX1-NEXT: setb %dil +; AVX1-NEXT: xorl %ecx, %ecx +; AVX1-NEXT: addq %rax, %rdx +; AVX1-NEXT: setb %cl +; AVX1-NEXT: shldq $63, %rdx, %rcx +; AVX1-NEXT: shldq $63, %rsi, %rdi +; AVX1-NEXT: vmovq %rdi, %xmm0 +; AVX1-NEXT: vmovq %rcx, %xmm1 +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v2i64: +; AVX2: # %bb.0: +; AVX2-NEXT: vmovq %xmm0, %rax +; AVX2-NEXT: vpextrq $1, %xmm0, %rcx +; AVX2-NEXT: vmovq %xmm1, %rdx +; AVX2-NEXT: vpextrq $1, %xmm1, %rsi +; AVX2-NEXT: xorl %edi, %edi +; AVX2-NEXT: addq %rcx, %rsi +; AVX2-NEXT: setb %dil +; AVX2-NEXT: xorl %ecx, %ecx +; AVX2-NEXT: addq %rax, %rdx +; AVX2-NEXT: setb %cl +; AVX2-NEXT: shldq $63, %rdx, %rcx +; AVX2-NEXT: shldq $63, %rsi, %rdi +; AVX2-NEXT: vmovq %rdi, %xmm0 +; AVX2-NEXT: vmovq %rcx, %xmm1 +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v2i64: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovq %xmm0, %rax +; AVX512-NEXT: vpextrq $1, %xmm0, %rcx +; AVX512-NEXT: vpextrq $1, %xmm1, %rdx +; AVX512-NEXT: vmovq %xmm1, %rsi +; AVX512-NEXT: xorl %edi, %edi +; AVX512-NEXT: addq %rcx, %rdx +; AVX512-NEXT: setb %dil +; AVX512-NEXT: xorl %ecx, %ecx +; AVX512-NEXT: addq %rax, %rsi +; AVX512-NEXT: setb %cl +; AVX512-NEXT: shldq $63, %rsi, %rcx +; AVX512-NEXT: shldq $63, %rdx, %rdi +; AVX512-NEXT: vmovq %rdi, %xmm0 +; AVX512-NEXT: vmovq %rcx, %xmm1 +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512-NEXT: retq + %x0 = zext <2 x i64> %a0 to <2 x i128> + %x1 = zext <2 x i64> %a1 to <2 x i128> + %sum = add <2 x i128> %x0, %x1 + %shift = lshr <2 x i128> %sum, <i128 1, i128 1> + %res = trunc <2 x i128> %shift to <2 x i64> + ret <2 x i64> %res +} + +; +; 256-bit vectors +; + +define <32 x i8> @test_fixed_v32i8(<32 x i8> %a0, <32 x i8> %a1) { +; SSE-LABEL: test_fixed_v32i8: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm1, %xmm4 +; SSE-NEXT: pand %xmm3, %xmm4 +; SSE-NEXT: movdqa %xmm0, %xmm5 +; SSE-NEXT: pand %xmm2, %xmm5 +; SSE-NEXT: pxor %xmm2, %xmm0 +; SSE-NEXT: pxor %xmm3, %xmm1 +; SSE-NEXT: psrlw $1, %xmm1 +; SSE-NEXT: movdqa {{.*#+}} xmm2 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; SSE-NEXT: pand %xmm2, %xmm1 +; SSE-NEXT: paddb %xmm4, %xmm1 +; SSE-NEXT: psrlw $1, %xmm0 +; SSE-NEXT: pand %xmm2, %xmm0 +; SSE-NEXT: paddb %xmm5, %xmm0 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v32i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vandps %ymm1, %ymm0, %ymm2 +; AVX1-NEXT: vxorps %ymm1, %ymm0, %ymm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm1 +; AVX1-NEXT: vbroadcastss {{.*#+}} xmm3 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; AVX1-NEXT: vpand %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3 +; AVX1-NEXT: vpaddb %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpaddb %xmm1, %xmm2, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v32i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %ymm1, %ymm0, %ymm2 +; AVX2-NEXT: vpxor %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 +; AVX2-NEXT: vpaddb %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v32i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpand %ymm1, %ymm0, %ymm2 +; AVX512-NEXT: vpxor %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX512-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm0, %ymm0 +; AVX512-NEXT: vpaddb %ymm0, %ymm2, %ymm0 +; AVX512-NEXT: retq + %and = and <32 x i8> %a0, %a1 + %xor = xor <32 x i8> %a0, %a1 + %shift = lshr <32 x i8> %xor, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> + %res = add <32 x i8> %and, %shift + ret <32 x i8> %res +} + +define <32 x i8> @test_ext_v32i8(<32 x i8> %a0, <32 x i8> %a1) { +; SSE2-LABEL: test_ext_v32i8: +; SSE2: # %bb.0: +; SSE2-NEXT: pxor %xmm4, %xmm4 +; SSE2-NEXT: movdqa %xmm1, %xmm5 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm4[8],xmm5[9],xmm4[9],xmm5[10],xmm4[10],xmm5[11],xmm4[11],xmm5[12],xmm4[12],xmm5[13],xmm4[13],xmm5[14],xmm4[14],xmm5[15],xmm4[15] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1],xmm1[2],xmm4[2],xmm1[3],xmm4[3],xmm1[4],xmm4[4],xmm1[5],xmm4[5],xmm1[6],xmm4[6],xmm1[7],xmm4[7] +; SSE2-NEXT: movdqa %xmm0, %xmm6 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm6 = xmm6[8],xmm4[8],xmm6[9],xmm4[9],xmm6[10],xmm4[10],xmm6[11],xmm4[11],xmm6[12],xmm4[12],xmm6[13],xmm4[13],xmm6[14],xmm4[14],xmm6[15],xmm4[15] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm4[0],xmm0[1],xmm4[1],xmm0[2],xmm4[2],xmm0[3],xmm4[3],xmm0[4],xmm4[4],xmm0[5],xmm4[5],xmm0[6],xmm4[6],xmm0[7],xmm4[7] +; SSE2-NEXT: movdqa %xmm3, %xmm7 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm7 = xmm7[8],xmm4[8],xmm7[9],xmm4[9],xmm7[10],xmm4[10],xmm7[11],xmm4[11],xmm7[12],xmm4[12],xmm7[13],xmm4[13],xmm7[14],xmm4[14],xmm7[15],xmm4[15] +; SSE2-NEXT: paddw %xmm5, %xmm7 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm4[0],xmm3[1],xmm4[1],xmm3[2],xmm4[2],xmm3[3],xmm4[3],xmm3[4],xmm4[4],xmm3[5],xmm4[5],xmm3[6],xmm4[6],xmm3[7],xmm4[7] +; SSE2-NEXT: paddw %xmm3, %xmm1 +; SSE2-NEXT: movdqa %xmm2, %xmm3 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm4[8],xmm3[9],xmm4[9],xmm3[10],xmm4[10],xmm3[11],xmm4[11],xmm3[12],xmm4[12],xmm3[13],xmm4[13],xmm3[14],xmm4[14],xmm3[15],xmm4[15] +; SSE2-NEXT: paddw %xmm6, %xmm3 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm4[0],xmm2[1],xmm4[1],xmm2[2],xmm4[2],xmm2[3],xmm4[3],xmm2[4],xmm4[4],xmm2[5],xmm4[5],xmm2[6],xmm4[6],xmm2[7],xmm4[7] +; SSE2-NEXT: paddw %xmm2, %xmm0 +; SSE2-NEXT: psrlw $1, %xmm7 +; SSE2-NEXT: psrlw $1, %xmm1 +; SSE2-NEXT: packuswb %xmm7, %xmm1 +; SSE2-NEXT: psrlw $1, %xmm3 +; SSE2-NEXT: psrlw $1, %xmm0 +; SSE2-NEXT: packuswb %xmm3, %xmm0 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v32i8: +; SSE4: # %bb.0: +; SSE4-NEXT: pxor %xmm5, %xmm5 +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm6 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero +; SSE4-NEXT: punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm5[8],xmm1[9],xmm5[9],xmm1[10],xmm5[10],xmm1[11],xmm5[11],xmm1[12],xmm5[12],xmm1[13],xmm5[13],xmm1[14],xmm5[14],xmm1[15],xmm5[15] +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm7 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; SSE4-NEXT: punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm5[8],xmm0[9],xmm5[9],xmm0[10],xmm5[10],xmm0[11],xmm5[11],xmm0[12],xmm5[12],xmm0[13],xmm5[13],xmm0[14],xmm5[14],xmm0[15],xmm5[15] +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm4 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero +; SSE4-NEXT: punpckhbw {{.*#+}} xmm3 = xmm3[8],xmm5[8],xmm3[9],xmm5[9],xmm3[10],xmm5[10],xmm3[11],xmm5[11],xmm3[12],xmm5[12],xmm3[13],xmm5[13],xmm3[14],xmm5[14],xmm3[15],xmm5[15] +; SSE4-NEXT: paddw %xmm1, %xmm3 +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm1 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; SSE4-NEXT: punpckhbw {{.*#+}} xmm2 = xmm2[8],xmm5[8],xmm2[9],xmm5[9],xmm2[10],xmm5[10],xmm2[11],xmm5[11],xmm2[12],xmm5[12],xmm2[13],xmm5[13],xmm2[14],xmm5[14],xmm2[15],xmm5[15] +; SSE4-NEXT: paddw %xmm0, %xmm2 +; SSE4-NEXT: paddw %xmm6, %xmm4 +; SSE4-NEXT: paddw %xmm7, %xmm1 +; SSE4-NEXT: psrlw $1, %xmm3 +; SSE4-NEXT: psrlw $1, %xmm2 +; SSE4-NEXT: psrlw $1, %xmm4 +; SSE4-NEXT: packuswb %xmm3, %xmm4 +; SSE4-NEXT: psrlw $1, %xmm1 +; SSE4-NEXT: packuswb %xmm2, %xmm1 +; SSE4-NEXT: movdqa %xmm1, %xmm0 +; SSE4-NEXT: movdqa %xmm4, %xmm1 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v32i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vpxor %xmm2, %xmm2, %xmm2 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm0[8],xmm2[8],xmm0[9],xmm2[9],xmm0[10],xmm2[10],xmm0[11],xmm2[11],xmm0[12],xmm2[12],xmm0[13],xmm2[13],xmm0[14],xmm2[14],xmm0[15],xmm2[15] +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm4 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm4[8],xmm2[8],xmm4[9],xmm2[9],xmm4[10],xmm2[10],xmm4[11],xmm2[11],xmm4[12],xmm2[12],xmm4[13],xmm2[13],xmm4[14],xmm2[14],xmm4[15],xmm2[15] +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm4 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm1[8],xmm2[8],xmm1[9],xmm2[9],xmm1[10],xmm2[10],xmm1[11],xmm2[11],xmm1[12],xmm2[12],xmm1[13],xmm2[13],xmm1[14],xmm2[14],xmm1[15],xmm2[15] +; AVX1-NEXT: vpaddw %xmm6, %xmm3, %xmm3 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm6 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm6[8],xmm2[8],xmm6[9],xmm2[9],xmm6[10],xmm2[10],xmm6[11],xmm2[11],xmm6[12],xmm2[12],xmm6[13],xmm2[13],xmm6[14],xmm2[14],xmm6[15],xmm2[15] +; AVX1-NEXT: vpaddw %xmm2, %xmm5, %xmm2 +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero +; AVX1-NEXT: vpaddw %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero +; AVX1-NEXT: vpaddw %xmm1, %xmm4, %xmm1 +; AVX1-NEXT: vpsrlw $1, %xmm3, %xmm3 +; AVX1-NEXT: vpsrlw $1, %xmm2, %xmm2 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vpackuswb %xmm3, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm1, %xmm1 +; AVX1-NEXT: vpackuswb %xmm2, %xmm1, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v32i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm2 +; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero,xmm2[8],zero,xmm2[9],zero,xmm2[10],zero,xmm2[11],zero,xmm2[12],zero,xmm2[13],zero,xmm2[14],zero,xmm2[15],zero +; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm3 +; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm3 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero,xmm3[8],zero,xmm3[9],zero,xmm3[10],zero,xmm3[11],zero,xmm3[12],zero,xmm3[13],zero,xmm3[14],zero,xmm3[15],zero +; AVX2-NEXT: vpaddw %ymm3, %ymm2, %ymm2 +; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero,xmm1[8],zero,xmm1[9],zero,xmm1[10],zero,xmm1[11],zero,xmm1[12],zero,xmm1[13],zero,xmm1[14],zero,xmm1[15],zero +; AVX2-NEXT: vpaddw %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlw $1, %ymm2, %ymm1 +; AVX2-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpackuswb %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,2,1,3] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v32i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovzxbw {{.*#+}} zmm0 = ymm0[0],zero,ymm0[1],zero,ymm0[2],zero,ymm0[3],zero,ymm0[4],zero,ymm0[5],zero,ymm0[6],zero,ymm0[7],zero,ymm0[8],zero,ymm0[9],zero,ymm0[10],zero,ymm0[11],zero,ymm0[12],zero,ymm0[13],zero,ymm0[14],zero,ymm0[15],zero,ymm0[16],zero,ymm0[17],zero,ymm0[18],zero,ymm0[19],zero,ymm0[20],zero,ymm0[21],zero,ymm0[22],zero,ymm0[23],zero,ymm0[24],zero,ymm0[25],zero,ymm0[26],zero,ymm0[27],zero,ymm0[28],zero,ymm0[29],zero,ymm0[30],zero,ymm0[31],zero +; AVX512-NEXT: vpmovzxbw {{.*#+}} zmm1 = ymm1[0],zero,ymm1[1],zero,ymm1[2],zero,ymm1[3],zero,ymm1[4],zero,ymm1[5],zero,ymm1[6],zero,ymm1[7],zero,ymm1[8],zero,ymm1[9],zero,ymm1[10],zero,ymm1[11],zero,ymm1[12],zero,ymm1[13],zero,ymm1[14],zero,ymm1[15],zero,ymm1[16],zero,ymm1[17],zero,ymm1[18],zero,ymm1[19],zero,ymm1[20],zero,ymm1[21],zero,ymm1[22],zero,ymm1[23],zero,ymm1[24],zero,ymm1[25],zero,ymm1[26],zero,ymm1[27],zero,ymm1[28],zero,ymm1[29],zero,ymm1[30],zero,ymm1[31],zero +; AVX512-NEXT: vpaddw %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlw $1, %zmm0, %zmm0 +; AVX512-NEXT: vpmovwb %zmm0, %ymm0 +; AVX512-NEXT: retq + %x0 = zext <32 x i8> %a0 to <32 x i16> + %x1 = zext <32 x i8> %a1 to <32 x i16> + %sum = add <32 x i16> %x0, %x1 + %shift = lshr <32 x i16> %sum, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = trunc <32 x i16> %shift to <32 x i8> + ret <32 x i8> %res +} + +define <16 x i16> @test_fixed_v16i16(<16 x i16> %a0, <16 x i16> %a1) { +; SSE-LABEL: test_fixed_v16i16: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm1, %xmm4 +; SSE-NEXT: pand %xmm3, %xmm4 +; SSE-NEXT: movdqa %xmm0, %xmm5 +; SSE-NEXT: pand %xmm2, %xmm5 +; SSE-NEXT: pxor %xmm2, %xmm0 +; SSE-NEXT: pxor %xmm3, %xmm1 +; SSE-NEXT: psrlw $1, %xmm1 +; SSE-NEXT: paddw %xmm4, %xmm1 +; SSE-NEXT: psrlw $1, %xmm0 +; SSE-NEXT: paddw %xmm5, %xmm0 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v16i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vandps %ymm1, %ymm0, %ymm2 +; AVX1-NEXT: vxorps %ymm0, %ymm1, %ymm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm1 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3 +; AVX1-NEXT: vpaddw %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpaddw %xmm1, %xmm2, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v16i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %ymm1, %ymm0, %ymm2 +; AVX2-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX2-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpaddw %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v16i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vpand %ymm1, %ymm0, %ymm2 +; AVX512-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX512-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX512-NEXT: vpaddw %ymm0, %ymm2, %ymm0 +; AVX512-NEXT: retq + %and = and <16 x i16> %a0, %a1 + %xor = xor <16 x i16> %a1, %a0 + %shift = lshr <16 x i16> %xor, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = add <16 x i16> %and, %shift + ret <16 x i16> %res +} + +define <16 x i16> @test_ext_v16i16(<16 x i16> %a0, <16 x i16> %a1) { +; SSE2-LABEL: test_ext_v16i16: +; SSE2: # %bb.0: +; SSE2-NEXT: pxor %xmm4, %xmm4 +; SSE2-NEXT: movdqa %xmm0, %xmm5 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm5 = xmm5[4],xmm4[4],xmm5[5],xmm4[5],xmm5[6],xmm4[6],xmm5[7],xmm4[7] +; SSE2-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm4[0],xmm0[1],xmm4[1],xmm0[2],xmm4[2],xmm0[3],xmm4[3] +; SSE2-NEXT: movdqa %xmm1, %xmm6 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm6 = xmm6[4],xmm4[4],xmm6[5],xmm4[5],xmm6[6],xmm4[6],xmm6[7],xmm4[7] +; SSE2-NEXT: punpcklwd {{.*#+}} xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1],xmm1[2],xmm4[2],xmm1[3],xmm4[3] +; SSE2-NEXT: movdqa %xmm2, %xmm7 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm7 = xmm7[4],xmm4[4],xmm7[5],xmm4[5],xmm7[6],xmm4[6],xmm7[7],xmm4[7] +; SSE2-NEXT: paddd %xmm5, %xmm7 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm2 = xmm2[0],xmm4[0],xmm2[1],xmm4[1],xmm2[2],xmm4[2],xmm2[3],xmm4[3] +; SSE2-NEXT: paddd %xmm2, %xmm0 +; SSE2-NEXT: movdqa %xmm3, %xmm2 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm2 = xmm2[4],xmm4[4],xmm2[5],xmm4[5],xmm2[6],xmm4[6],xmm2[7],xmm4[7] +; SSE2-NEXT: paddd %xmm6, %xmm2 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm3 = xmm3[0],xmm4[0],xmm3[1],xmm4[1],xmm3[2],xmm4[2],xmm3[3],xmm4[3] +; SSE2-NEXT: paddd %xmm3, %xmm1 +; SSE2-NEXT: pslld $15, %xmm7 +; SSE2-NEXT: psrad $16, %xmm7 +; SSE2-NEXT: pslld $15, %xmm0 +; SSE2-NEXT: psrad $16, %xmm0 +; SSE2-NEXT: packssdw %xmm7, %xmm0 +; SSE2-NEXT: pslld $15, %xmm2 +; SSE2-NEXT: psrad $16, %xmm2 +; SSE2-NEXT: pslld $15, %xmm1 +; SSE2-NEXT: psrad $16, %xmm1 +; SSE2-NEXT: packssdw %xmm2, %xmm1 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v16i16: +; SSE4: # %bb.0: +; SSE4-NEXT: pxor %xmm5, %xmm5 +; SSE4-NEXT: pmovzxwd {{.*#+}} xmm6 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero +; SSE4-NEXT: punpckhwd {{.*#+}} xmm1 = xmm1[4],xmm5[4],xmm1[5],xmm5[5],xmm1[6],xmm5[6],xmm1[7],xmm5[7] +; SSE4-NEXT: pmovzxwd {{.*#+}} xmm7 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; SSE4-NEXT: punpckhwd {{.*#+}} xmm0 = xmm0[4],xmm5[4],xmm0[5],xmm5[5],xmm0[6],xmm5[6],xmm0[7],xmm5[7] +; SSE4-NEXT: pmovzxwd {{.*#+}} xmm4 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero +; SSE4-NEXT: punpckhwd {{.*#+}} xmm3 = xmm3[4],xmm5[4],xmm3[5],xmm5[5],xmm3[6],xmm5[6],xmm3[7],xmm5[7] +; SSE4-NEXT: paddd %xmm1, %xmm3 +; SSE4-NEXT: pmovzxwd {{.*#+}} xmm1 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero +; SSE4-NEXT: punpckhwd {{.*#+}} xmm2 = xmm2[4],xmm5[4],xmm2[5],xmm5[5],xmm2[6],xmm5[6],xmm2[7],xmm5[7] +; SSE4-NEXT: paddd %xmm0, %xmm2 +; SSE4-NEXT: paddd %xmm6, %xmm4 +; SSE4-NEXT: paddd %xmm7, %xmm1 +; SSE4-NEXT: psrld $1, %xmm3 +; SSE4-NEXT: psrld $1, %xmm2 +; SSE4-NEXT: psrld $1, %xmm4 +; SSE4-NEXT: packusdw %xmm3, %xmm4 +; SSE4-NEXT: psrld $1, %xmm1 +; SSE4-NEXT: packusdw %xmm2, %xmm1 +; SSE4-NEXT: movdqa %xmm1, %xmm0 +; SSE4-NEXT: movdqa %xmm4, %xmm1 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v16i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vpxor %xmm2, %xmm2, %xmm2 +; AVX1-NEXT: vpunpckhwd {{.*#+}} xmm3 = xmm0[4],xmm2[4],xmm0[5],xmm2[5],xmm0[6],xmm2[6],xmm0[7],xmm2[7] +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm4 +; AVX1-NEXT: vpunpckhwd {{.*#+}} xmm5 = xmm4[4],xmm2[4],xmm4[5],xmm2[5],xmm4[6],xmm2[6],xmm4[7],xmm2[7] +; AVX1-NEXT: vpmovzxwd {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; AVX1-NEXT: vpmovzxwd {{.*#+}} xmm4 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero +; AVX1-NEXT: vpunpckhwd {{.*#+}} xmm6 = xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7] +; AVX1-NEXT: vpaddd %xmm6, %xmm3, %xmm3 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm6 +; AVX1-NEXT: vpunpckhwd {{.*#+}} xmm2 = xmm6[4],xmm2[4],xmm6[5],xmm2[5],xmm6[6],xmm2[6],xmm6[7],xmm2[7] +; AVX1-NEXT: vpaddd %xmm2, %xmm5, %xmm2 +; AVX1-NEXT: vpmovzxwd {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero +; AVX1-NEXT: vpaddd %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpmovzxwd {{.*#+}} xmm1 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero +; AVX1-NEXT: vpaddd %xmm1, %xmm4, %xmm1 +; AVX1-NEXT: vpsrld $1, %xmm3, %xmm3 +; AVX1-NEXT: vpsrld $1, %xmm2, %xmm2 +; AVX1-NEXT: vpsrld $1, %xmm0, %xmm0 +; AVX1-NEXT: vpackusdw %xmm3, %xmm0, %xmm0 +; AVX1-NEXT: vpsrld $1, %xmm1, %xmm1 +; AVX1-NEXT: vpackusdw %xmm2, %xmm1, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v16i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm2 +; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm3 +; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm3 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero +; AVX2-NEXT: vpaddd %ymm3, %ymm2, %ymm2 +; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero +; AVX2-NEXT: vpaddd %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpsrld $1, %ymm2, %ymm1 +; AVX2-NEXT: vpsrld $1, %ymm0, %ymm0 +; AVX2-NEXT: vpackusdw %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,2,1,3] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v16i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovzxwd {{.*#+}} zmm0 = ymm0[0],zero,ymm0[1],zero,ymm0[2],zero,ymm0[3],zero,ymm0[4],zero,ymm0[5],zero,ymm0[6],zero,ymm0[7],zero,ymm0[8],zero,ymm0[9],zero,ymm0[10],zero,ymm0[11],zero,ymm0[12],zero,ymm0[13],zero,ymm0[14],zero,ymm0[15],zero +; AVX512-NEXT: vpmovzxwd {{.*#+}} zmm1 = ymm1[0],zero,ymm1[1],zero,ymm1[2],zero,ymm1[3],zero,ymm1[4],zero,ymm1[5],zero,ymm1[6],zero,ymm1[7],zero,ymm1[8],zero,ymm1[9],zero,ymm1[10],zero,ymm1[11],zero,ymm1[12],zero,ymm1[13],zero,ymm1[14],zero,ymm1[15],zero +; AVX512-NEXT: vpaddd %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrld $1, %zmm0, %zmm0 +; AVX512-NEXT: vpmovdw %zmm0, %ymm0 +; AVX512-NEXT: retq + %x0 = zext <16 x i16> %a0 to <16 x i32> + %x1 = zext <16 x i16> %a1 to <16 x i32> + %sum = add <16 x i32> %x0, %x1 + %shift = lshr <16 x i32> %sum, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = trunc <16 x i32> %shift to <16 x i16> + ret <16 x i16> %res +} + +define <8 x i32> @test_fixed_v8i32(<8 x i32> %a0, <8 x i32> %a1) { +; SSE-LABEL: test_fixed_v8i32: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm1, %xmm4 +; SSE-NEXT: pand %xmm3, %xmm4 +; SSE-NEXT: movdqa %xmm0, %xmm5 +; SSE-NEXT: pand %xmm2, %xmm5 +; SSE-NEXT: pxor %xmm2, %xmm0 +; SSE-NEXT: pxor %xmm3, %xmm1 +; SSE-NEXT: psrld $1, %xmm1 +; SSE-NEXT: paddd %xmm4, %xmm1 +; SSE-NEXT: psrld $1, %xmm0 +; SSE-NEXT: paddd %xmm5, %xmm0 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v8i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vandps %ymm1, %ymm0, %ymm2 +; AVX1-NEXT: vxorps %ymm0, %ymm1, %ymm0 +; AVX1-NEXT: vpsrld $1, %xmm0, %xmm1 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrld $1, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3 +; AVX1-NEXT: vpaddd %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpaddd %xmm1, %xmm2, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v8i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %ymm1, %ymm0, %ymm2 +; AVX2-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX2-NEXT: vpsrld $1, %ymm0, %ymm0 +; AVX2-NEXT: vpaddd %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v8i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vpand %ymm1, %ymm0, %ymm2 +; AVX512-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX512-NEXT: vpsrld $1, %ymm0, %ymm0 +; AVX512-NEXT: vpaddd %ymm0, %ymm2, %ymm0 +; AVX512-NEXT: retq + %and = and <8 x i32> %a0, %a1 + %xor = xor <8 x i32> %a1, %a0 + %shift = lshr <8 x i32> %xor, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = add <8 x i32> %and, %shift + ret <8 x i32> %res +} + +define <8 x i32> @test_ext_v8i32(<8 x i32> %a0, <8 x i32> %a1) { +; SSE2-LABEL: test_ext_v8i32: +; SSE2: # %bb.0: +; SSE2-NEXT: pxor %xmm4, %xmm4 +; SSE2-NEXT: movdqa %xmm1, %xmm5 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm5 = xmm5[2],xmm4[2],xmm5[3],xmm4[3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1] +; SSE2-NEXT: movdqa %xmm0, %xmm6 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm6 = xmm6[2],xmm4[2],xmm6[3],xmm4[3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm4[0],xmm0[1],xmm4[1] +; SSE2-NEXT: movdqa %xmm3, %xmm7 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm7 = xmm7[2],xmm4[2],xmm7[3],xmm4[3] +; SSE2-NEXT: paddq %xmm5, %xmm7 +; SSE2-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm4[0],xmm3[1],xmm4[1] +; SSE2-NEXT: paddq %xmm3, %xmm1 +; SSE2-NEXT: movdqa %xmm2, %xmm3 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm3 = xmm3[2],xmm4[2],xmm3[3],xmm4[3] +; SSE2-NEXT: paddq %xmm6, %xmm3 +; SSE2-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm4[0],xmm2[1],xmm4[1] +; SSE2-NEXT: paddq %xmm2, %xmm0 +; SSE2-NEXT: psrlq $1, %xmm7 +; SSE2-NEXT: psrlq $1, %xmm1 +; SSE2-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm7[0,2] +; SSE2-NEXT: psrlq $1, %xmm3 +; SSE2-NEXT: psrlq $1, %xmm0 +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm3[0,2] +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v8i32: +; SSE4: # %bb.0: +; SSE4-NEXT: pxor %xmm5, %xmm5 +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm6 = xmm1[0],zero,xmm1[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm1 = xmm1[2],xmm5[2],xmm1[3],xmm5[3] +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm7 = xmm0[0],zero,xmm0[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm0 = xmm0[2],xmm5[2],xmm0[3],xmm5[3] +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm4 = xmm3[0],zero,xmm3[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm3 = xmm3[2],xmm5[2],xmm3[3],xmm5[3] +; SSE4-NEXT: paddq %xmm1, %xmm3 +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm1 = xmm2[0],zero,xmm2[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm2 = xmm2[2],xmm5[2],xmm2[3],xmm5[3] +; SSE4-NEXT: paddq %xmm0, %xmm2 +; SSE4-NEXT: paddq %xmm6, %xmm4 +; SSE4-NEXT: paddq %xmm7, %xmm1 +; SSE4-NEXT: psrlq $1, %xmm3 +; SSE4-NEXT: psrlq $1, %xmm2 +; SSE4-NEXT: psrlq $1, %xmm4 +; SSE4-NEXT: shufps {{.*#+}} xmm4 = xmm4[0,2],xmm3[0,2] +; SSE4-NEXT: psrlq $1, %xmm1 +; SSE4-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm2[0,2] +; SSE4-NEXT: movaps %xmm1, %xmm0 +; SSE4-NEXT: movaps %xmm4, %xmm1 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v8i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm2 +; AVX1-NEXT: vpxor %xmm3, %xmm3, %xmm3 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm4 = xmm2[2],xmm3[2],xmm2[3],xmm3[3] +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm5 = xmm0[2],xmm3[2],xmm0[3],xmm3[3] +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm2 = xmm2[0],zero,xmm2[1],zero +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm6 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm7 = xmm6[2],xmm3[2],xmm6[3],xmm3[3] +; AVX1-NEXT: vpaddq %xmm7, %xmm4, %xmm4 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm3 = xmm1[2],xmm3[2],xmm1[3],xmm3[3] +; AVX1-NEXT: vpaddq %xmm3, %xmm5, %xmm3 +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm5 = xmm6[0],zero,xmm6[1],zero +; AVX1-NEXT: vpaddq %xmm5, %xmm2, %xmm2 +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero +; AVX1-NEXT: vpaddq %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlq $1, %xmm4, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm3, %xmm3 +; AVX1-NEXT: vpsrlq $1, %xmm2, %xmm2 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm3, %ymm1 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 +; AVX1-NEXT: vshufps {{.*#+}} ymm0 = ymm0[0,2],ymm1[0,2],ymm0[4,6],ymm1[4,6] +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v8i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm2 +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm3 +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm3 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero +; AVX2-NEXT: vpaddq %ymm3, %ymm2, %ymm2 +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero +; AVX2-NEXT: vpaddq %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vperm2i128 {{.*#+}} ymm1 = ymm0[2,3],ymm2[2,3] +; AVX2-NEXT: vpsrlq $1, %ymm1, %ymm1 +; AVX2-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vshufps {{.*#+}} ymm0 = ymm0[0,2],ymm1[0,2],ymm0[4,6],ymm1[4,6] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v8i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vpmovzxdq {{.*#+}} zmm0 = ymm0[0],zero,ymm0[1],zero,ymm0[2],zero,ymm0[3],zero,ymm0[4],zero,ymm0[5],zero,ymm0[6],zero,ymm0[7],zero +; AVX512-NEXT: vpmovzxdq {{.*#+}} zmm1 = ymm1[0],zero,ymm1[1],zero,ymm1[2],zero,ymm1[3],zero,ymm1[4],zero,ymm1[5],zero,ymm1[6],zero,ymm1[7],zero +; AVX512-NEXT: vpaddq %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlq $1, %zmm0, %zmm0 +; AVX512-NEXT: vpmovqd %zmm0, %ymm0 +; AVX512-NEXT: retq + %x0 = zext <8 x i32> %a0 to <8 x i64> + %x1 = zext <8 x i32> %a1 to <8 x i64> + %sum = add <8 x i64> %x0, %x1 + %shift = lshr <8 x i64> %sum, <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1> + %res = trunc <8 x i64> %shift to <8 x i32> + ret <8 x i32> %res +} + +define <4 x i64> @test_fixed_v4i64(<4 x i64> %a0, <4 x i64> %a1) { +; SSE-LABEL: test_fixed_v4i64: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm1, %xmm4 +; SSE-NEXT: pand %xmm3, %xmm4 +; SSE-NEXT: movdqa %xmm0, %xmm5 +; SSE-NEXT: pand %xmm2, %xmm5 +; SSE-NEXT: pxor %xmm2, %xmm0 +; SSE-NEXT: pxor %xmm3, %xmm1 +; SSE-NEXT: psrlq $1, %xmm1 +; SSE-NEXT: paddq %xmm4, %xmm1 +; SSE-NEXT: psrlq $1, %xmm0 +; SSE-NEXT: paddq %xmm5, %xmm0 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v4i64: +; AVX1: # %bb.0: +; AVX1-NEXT: vandps %ymm1, %ymm0, %ymm2 +; AVX1-NEXT: vxorps %ymm0, %ymm1, %ymm0 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm1 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm3 +; AVX1-NEXT: vpaddq %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpaddq %xmm1, %xmm2, %xmm1 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v4i64: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %ymm1, %ymm0, %ymm2 +; AVX2-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vpaddq %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v4i64: +; AVX512: # %bb.0: +; AVX512-NEXT: vpand %ymm1, %ymm0, %ymm2 +; AVX512-NEXT: vpxor %ymm0, %ymm1, %ymm0 +; AVX512-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX512-NEXT: vpaddq %ymm0, %ymm2, %ymm0 +; AVX512-NEXT: retq + %and = and <4 x i64> %a0, %a1 + %xor = xor <4 x i64> %a1, %a0 + %shift = lshr <4 x i64> %xor, <i64 1, i64 1, i64 1, i64 1> + %res = add <4 x i64> %and, %shift + ret <4 x i64> %res +} + +define <4 x i64> @test_ext_v4i64(<4 x i64> %a0, <4 x i64> %a1) { +; SSE2-LABEL: test_ext_v4i64: +; SSE2: # %bb.0: +; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm1[2,3,2,3] +; SSE2-NEXT: movq %xmm4, %rdi +; SSE2-NEXT: movq %xmm1, %r9 +; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] +; SSE2-NEXT: movq %xmm1, %r10 +; SSE2-NEXT: movq %xmm0, %r11 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm3[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %r8 +; SSE2-NEXT: movq %xmm3, %rsi +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm2[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %rdx +; SSE2-NEXT: movq %xmm2, %rax +; SSE2-NEXT: xorl %ecx, %ecx +; SSE2-NEXT: addq %r11, %rax +; SSE2-NEXT: setb %cl +; SSE2-NEXT: xorl %r11d, %r11d +; SSE2-NEXT: addq %r10, %rdx +; SSE2-NEXT: setb %r11b +; SSE2-NEXT: xorl %r10d, %r10d +; SSE2-NEXT: addq %r9, %rsi +; SSE2-NEXT: setb %r10b +; SSE2-NEXT: xorl %r9d, %r9d +; SSE2-NEXT: addq %rdi, %r8 +; SSE2-NEXT: setb %r9b +; SSE2-NEXT: shldq $63, %r8, %r9 +; SSE2-NEXT: shldq $63, %rsi, %r10 +; SSE2-NEXT: shldq $63, %rdx, %r11 +; SSE2-NEXT: shldq $63, %rax, %rcx +; SSE2-NEXT: movq %rcx, %xmm0 +; SSE2-NEXT: movq %r11, %xmm1 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE2-NEXT: movq %r10, %xmm1 +; SSE2-NEXT: movq %r9, %xmm2 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm2[0] +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v4i64: +; SSE4: # %bb.0: +; SSE4-NEXT: movq %xmm1, %r8 +; SSE4-NEXT: pextrq $1, %xmm1, %r9 +; SSE4-NEXT: movq %xmm0, %r10 +; SSE4-NEXT: pextrq $1, %xmm0, %r11 +; SSE4-NEXT: movq %xmm3, %rdi +; SSE4-NEXT: pextrq $1, %xmm3, %rsi +; SSE4-NEXT: movq %xmm2, %rdx +; SSE4-NEXT: pextrq $1, %xmm2, %rax +; SSE4-NEXT: xorl %ecx, %ecx +; SSE4-NEXT: addq %r11, %rax +; SSE4-NEXT: setb %cl +; SSE4-NEXT: xorl %r11d, %r11d +; SSE4-NEXT: addq %r10, %rdx +; SSE4-NEXT: setb %r11b +; SSE4-NEXT: xorl %r10d, %r10d +; SSE4-NEXT: addq %r9, %rsi +; SSE4-NEXT: setb %r10b +; SSE4-NEXT: xorl %r9d, %r9d +; SSE4-NEXT: addq %r8, %rdi +; SSE4-NEXT: setb %r9b +; SSE4-NEXT: shldq $63, %rdi, %r9 +; SSE4-NEXT: shldq $63, %rsi, %r10 +; SSE4-NEXT: shldq $63, %rdx, %r11 +; SSE4-NEXT: shldq $63, %rax, %rcx +; SSE4-NEXT: movq %rcx, %xmm1 +; SSE4-NEXT: movq %r11, %xmm0 +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE4-NEXT: movq %r10, %xmm2 +; SSE4-NEXT: movq %r9, %xmm1 +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm2[0] +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v4i64: +; AVX1: # %bb.0: +; AVX1-NEXT: vmovq %xmm0, %rdi +; AVX1-NEXT: vpextrq $1, %xmm0, %r9 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vmovq %xmm0, %r10 +; AVX1-NEXT: vpextrq $1, %xmm0, %r11 +; AVX1-NEXT: vmovq %xmm1, %r8 +; AVX1-NEXT: vpextrq $1, %xmm1, %rsi +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm0 +; AVX1-NEXT: vmovq %xmm0, %rdx +; AVX1-NEXT: vpextrq $1, %xmm0, %rax +; AVX1-NEXT: xorl %ecx, %ecx +; AVX1-NEXT: addq %r11, %rax +; AVX1-NEXT: setb %cl +; AVX1-NEXT: xorl %r11d, %r11d +; AVX1-NEXT: addq %r10, %rdx +; AVX1-NEXT: setb %r11b +; AVX1-NEXT: xorl %r10d, %r10d +; AVX1-NEXT: addq %r9, %rsi +; AVX1-NEXT: setb %r10b +; AVX1-NEXT: xorl %r9d, %r9d +; AVX1-NEXT: addq %rdi, %r8 +; AVX1-NEXT: setb %r9b +; AVX1-NEXT: shldq $63, %r8, %r9 +; AVX1-NEXT: shldq $63, %rsi, %r10 +; AVX1-NEXT: shldq $63, %rdx, %r11 +; AVX1-NEXT: shldq $63, %rax, %rcx +; AVX1-NEXT: vmovq %rcx, %xmm0 +; AVX1-NEXT: vmovq %r11, %xmm1 +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX1-NEXT: vmovq %r10, %xmm1 +; AVX1-NEXT: vmovq %r9, %xmm2 +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v4i64: +; AVX2: # %bb.0: +; AVX2-NEXT: vmovq %xmm0, %rdi +; AVX2-NEXT: vpextrq $1, %xmm0, %r9 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX2-NEXT: vmovq %xmm0, %r10 +; AVX2-NEXT: vpextrq $1, %xmm0, %r11 +; AVX2-NEXT: vmovq %xmm1, %r8 +; AVX2-NEXT: vpextrq $1, %xmm1, %rsi +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm0 +; AVX2-NEXT: vmovq %xmm0, %rdx +; AVX2-NEXT: vpextrq $1, %xmm0, %rax +; AVX2-NEXT: xorl %ecx, %ecx +; AVX2-NEXT: addq %r11, %rax +; AVX2-NEXT: setb %cl +; AVX2-NEXT: xorl %r11d, %r11d +; AVX2-NEXT: addq %r10, %rdx +; AVX2-NEXT: setb %r11b +; AVX2-NEXT: xorl %r10d, %r10d +; AVX2-NEXT: addq %r9, %rsi +; AVX2-NEXT: setb %r10b +; AVX2-NEXT: xorl %r9d, %r9d +; AVX2-NEXT: addq %rdi, %r8 +; AVX2-NEXT: setb %r9b +; AVX2-NEXT: shldq $63, %r8, %r9 +; AVX2-NEXT: shldq $63, %rsi, %r10 +; AVX2-NEXT: shldq $63, %rdx, %r11 +; AVX2-NEXT: shldq $63, %rax, %rcx +; AVX2-NEXT: vmovq %rcx, %xmm0 +; AVX2-NEXT: vmovq %r11, %xmm1 +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX2-NEXT: vmovq %r10, %xmm1 +; AVX2-NEXT: vmovq %r9, %xmm2 +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX2-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v4i64: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovq %xmm0, %rsi +; AVX512-NEXT: vpextrq $1, %xmm0, %r9 +; AVX512-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX512-NEXT: vmovq %xmm0, %r10 +; AVX512-NEXT: vpextrq $1, %xmm0, %r11 +; AVX512-NEXT: vmovq %xmm1, %rdi +; AVX512-NEXT: vpextrq $1, %xmm1, %rcx +; AVX512-NEXT: vextracti128 $1, %ymm1, %xmm0 +; AVX512-NEXT: vpextrq $1, %xmm0, %rax +; AVX512-NEXT: vmovq %xmm0, %r8 +; AVX512-NEXT: xorl %edx, %edx +; AVX512-NEXT: addq %r11, %rax +; AVX512-NEXT: setb %dl +; AVX512-NEXT: xorl %r11d, %r11d +; AVX512-NEXT: addq %r10, %r8 +; AVX512-NEXT: setb %r11b +; AVX512-NEXT: xorl %r10d, %r10d +; AVX512-NEXT: addq %r9, %rcx +; AVX512-NEXT: setb %r10b +; AVX512-NEXT: xorl %r9d, %r9d +; AVX512-NEXT: addq %rsi, %rdi +; AVX512-NEXT: setb %r9b +; AVX512-NEXT: shldq $63, %rdi, %r9 +; AVX512-NEXT: shldq $63, %rcx, %r10 +; AVX512-NEXT: shldq $63, %r8, %r11 +; AVX512-NEXT: shldq $63, %rax, %rdx +; AVX512-NEXT: vmovq %rdx, %xmm0 +; AVX512-NEXT: vmovq %r11, %xmm1 +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512-NEXT: vmovq %r10, %xmm1 +; AVX512-NEXT: vmovq %r9, %xmm2 +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm2[0],xmm1[0] +; AVX512-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0 +; AVX512-NEXT: retq + %x0 = zext <4 x i64> %a0 to <4 x i128> + %x1 = zext <4 x i64> %a1 to <4 x i128> + %sum = add <4 x i128> %x0, %x1 + %shift = lshr <4 x i128> %sum, <i128 1, i128 1, i128 1, i128 1> + %res = trunc <4 x i128> %shift to <4 x i64> + ret <4 x i64> %res +} + +; +; 512-bit vectors +; + +define <64 x i8> @test_fixed_v64i8(<64 x i8> %a0, <64 x i8> %a1) { +; SSE-LABEL: test_fixed_v64i8: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm3, %xmm9 +; SSE-NEXT: pand %xmm7, %xmm9 +; SSE-NEXT: movdqa %xmm2, %xmm10 +; SSE-NEXT: pand %xmm6, %xmm10 +; SSE-NEXT: movdqa %xmm1, %xmm11 +; SSE-NEXT: pand %xmm5, %xmm11 +; SSE-NEXT: movdqa %xmm0, %xmm8 +; SSE-NEXT: pand %xmm4, %xmm8 +; SSE-NEXT: pxor %xmm4, %xmm0 +; SSE-NEXT: pxor %xmm5, %xmm1 +; SSE-NEXT: pxor %xmm6, %xmm2 +; SSE-NEXT: pxor %xmm7, %xmm3 +; SSE-NEXT: psrlw $1, %xmm3 +; SSE-NEXT: movdqa {{.*#+}} xmm4 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; SSE-NEXT: pand %xmm4, %xmm3 +; SSE-NEXT: paddb %xmm9, %xmm3 +; SSE-NEXT: psrlw $1, %xmm2 +; SSE-NEXT: pand %xmm4, %xmm2 +; SSE-NEXT: paddb %xmm10, %xmm2 +; SSE-NEXT: psrlw $1, %xmm1 +; SSE-NEXT: pand %xmm4, %xmm1 +; SSE-NEXT: paddb %xmm11, %xmm1 +; SSE-NEXT: psrlw $1, %xmm0 +; SSE-NEXT: pand %xmm4, %xmm0 +; SSE-NEXT: paddb %xmm8, %xmm0 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v64i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vandps %ymm3, %ymm1, %ymm4 +; AVX1-NEXT: vandps %ymm2, %ymm0, %ymm5 +; AVX1-NEXT: vxorps %ymm2, %ymm0, %ymm0 +; AVX1-NEXT: vxorps %ymm3, %ymm1, %ymm1 +; AVX1-NEXT: vpsrlw $1, %xmm1, %xmm2 +; AVX1-NEXT: vbroadcastss {{.*#+}} xmm3 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; AVX1-NEXT: vpand %xmm3, %xmm2, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpsrlw $1, %xmm1, %xmm1 +; AVX1-NEXT: vpand %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm6 +; AVX1-NEXT: vpand %xmm3, %xmm6, %xmm6 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vpand %xmm3, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm5, %xmm3 +; AVX1-NEXT: vpaddb %xmm0, %xmm3, %xmm0 +; AVX1-NEXT: vpaddb %xmm6, %xmm5, %xmm3 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm3, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm4, %xmm3 +; AVX1-NEXT: vpaddb %xmm1, %xmm3, %xmm1 +; AVX1-NEXT: vpaddb %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v64i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %ymm3, %ymm1, %ymm4 +; AVX2-NEXT: vpand %ymm2, %ymm0, %ymm5 +; AVX2-NEXT: vpxor %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpxor %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: vpsrlw $1, %ymm1, %ymm1 +; AVX2-NEXT: vpbroadcastb {{.*#+}} ymm2 = [127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127] +; AVX2-NEXT: vpand %ymm2, %ymm1, %ymm1 +; AVX2-NEXT: vpaddb %ymm1, %ymm4, %ymm1 +; AVX2-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpand %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpaddb %ymm0, %ymm5, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v64i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vpandq %zmm1, %zmm0, %zmm2 +; AVX512-NEXT: vpxorq %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlw $1, %zmm0, %zmm0 +; AVX512-NEXT: vpandd {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm0, %zmm0 +; AVX512-NEXT: vpaddb %zmm0, %zmm2, %zmm0 +; AVX512-NEXT: retq + %and = and <64 x i8> %a0, %a1 + %xor = xor <64 x i8> %a0, %a1 + %shift = lshr <64 x i8> %xor, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> + %res = add <64 x i8> %and, %shift + ret <64 x i8> %res +} + +define <64 x i8> @test_ext_v64i8(<64 x i8> %a0, <64 x i8> %a1) { +; SSE2-LABEL: test_ext_v64i8: +; SSE2: # %bb.0: +; SSE2-NEXT: pxor %xmm8, %xmm8 +; SSE2-NEXT: movdqa %xmm3, %xmm10 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm10 = xmm10[8],xmm8[8],xmm10[9],xmm8[9],xmm10[10],xmm8[10],xmm10[11],xmm8[11],xmm10[12],xmm8[12],xmm10[13],xmm8[13],xmm10[14],xmm8[14],xmm10[15],xmm8[15] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm8[0],xmm3[1],xmm8[1],xmm3[2],xmm8[2],xmm3[3],xmm8[3],xmm3[4],xmm8[4],xmm3[5],xmm8[5],xmm3[6],xmm8[6],xmm3[7],xmm8[7] +; SSE2-NEXT: movdqa %xmm2, %xmm11 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm11 = xmm11[8],xmm8[8],xmm11[9],xmm8[9],xmm11[10],xmm8[10],xmm11[11],xmm8[11],xmm11[12],xmm8[12],xmm11[13],xmm8[13],xmm11[14],xmm8[14],xmm11[15],xmm8[15] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm2 = xmm2[0],xmm8[0],xmm2[1],xmm8[1],xmm2[2],xmm8[2],xmm2[3],xmm8[3],xmm2[4],xmm8[4],xmm2[5],xmm8[5],xmm2[6],xmm8[6],xmm2[7],xmm8[7] +; SSE2-NEXT: movdqa %xmm1, %xmm12 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm12 = xmm12[8],xmm8[8],xmm12[9],xmm8[9],xmm12[10],xmm8[10],xmm12[11],xmm8[11],xmm12[12],xmm8[12],xmm12[13],xmm8[13],xmm12[14],xmm8[14],xmm12[15],xmm8[15] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm8[0],xmm1[1],xmm8[1],xmm1[2],xmm8[2],xmm1[3],xmm8[3],xmm1[4],xmm8[4],xmm1[5],xmm8[5],xmm1[6],xmm8[6],xmm1[7],xmm8[7] +; SSE2-NEXT: movdqa %xmm0, %xmm13 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm13 = xmm13[8],xmm8[8],xmm13[9],xmm8[9],xmm13[10],xmm8[10],xmm13[11],xmm8[11],xmm13[12],xmm8[12],xmm13[13],xmm8[13],xmm13[14],xmm8[14],xmm13[15],xmm8[15] +; SSE2-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm8[0],xmm0[1],xmm8[1],xmm0[2],xmm8[2],xmm0[3],xmm8[3],xmm0[4],xmm8[4],xmm0[5],xmm8[5],xmm0[6],xmm8[6],xmm0[7],xmm8[7] +; SSE2-NEXT: movdqa %xmm7, %xmm9 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm9 = xmm9[8],xmm8[8],xmm9[9],xmm8[9],xmm9[10],xmm8[10],xmm9[11],xmm8[11],xmm9[12],xmm8[12],xmm9[13],xmm8[13],xmm9[14],xmm8[14],xmm9[15],xmm8[15] +; SSE2-NEXT: paddw %xmm10, %xmm9 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm7 = xmm7[0],xmm8[0],xmm7[1],xmm8[1],xmm7[2],xmm8[2],xmm7[3],xmm8[3],xmm7[4],xmm8[4],xmm7[5],xmm8[5],xmm7[6],xmm8[6],xmm7[7],xmm8[7] +; SSE2-NEXT: paddw %xmm7, %xmm3 +; SSE2-NEXT: movdqa %xmm6, %xmm7 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm7 = xmm7[8],xmm8[8],xmm7[9],xmm8[9],xmm7[10],xmm8[10],xmm7[11],xmm8[11],xmm7[12],xmm8[12],xmm7[13],xmm8[13],xmm7[14],xmm8[14],xmm7[15],xmm8[15] +; SSE2-NEXT: paddw %xmm11, %xmm7 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm6 = xmm6[0],xmm8[0],xmm6[1],xmm8[1],xmm6[2],xmm8[2],xmm6[3],xmm8[3],xmm6[4],xmm8[4],xmm6[5],xmm8[5],xmm6[6],xmm8[6],xmm6[7],xmm8[7] +; SSE2-NEXT: paddw %xmm6, %xmm2 +; SSE2-NEXT: movdqa %xmm5, %xmm6 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm6 = xmm6[8],xmm8[8],xmm6[9],xmm8[9],xmm6[10],xmm8[10],xmm6[11],xmm8[11],xmm6[12],xmm8[12],xmm6[13],xmm8[13],xmm6[14],xmm8[14],xmm6[15],xmm8[15] +; SSE2-NEXT: paddw %xmm12, %xmm6 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm5 = xmm5[0],xmm8[0],xmm5[1],xmm8[1],xmm5[2],xmm8[2],xmm5[3],xmm8[3],xmm5[4],xmm8[4],xmm5[5],xmm8[5],xmm5[6],xmm8[6],xmm5[7],xmm8[7] +; SSE2-NEXT: paddw %xmm5, %xmm1 +; SSE2-NEXT: movdqa %xmm4, %xmm5 +; SSE2-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm8[8],xmm5[9],xmm8[9],xmm5[10],xmm8[10],xmm5[11],xmm8[11],xmm5[12],xmm8[12],xmm5[13],xmm8[13],xmm5[14],xmm8[14],xmm5[15],xmm8[15] +; SSE2-NEXT: paddw %xmm13, %xmm5 +; SSE2-NEXT: punpcklbw {{.*#+}} xmm4 = xmm4[0],xmm8[0],xmm4[1],xmm8[1],xmm4[2],xmm8[2],xmm4[3],xmm8[3],xmm4[4],xmm8[4],xmm4[5],xmm8[5],xmm4[6],xmm8[6],xmm4[7],xmm8[7] +; SSE2-NEXT: paddw %xmm4, %xmm0 +; SSE2-NEXT: psrlw $1, %xmm9 +; SSE2-NEXT: psrlw $1, %xmm3 +; SSE2-NEXT: packuswb %xmm9, %xmm3 +; SSE2-NEXT: psrlw $1, %xmm7 +; SSE2-NEXT: psrlw $1, %xmm2 +; SSE2-NEXT: packuswb %xmm7, %xmm2 +; SSE2-NEXT: psrlw $1, %xmm6 +; SSE2-NEXT: psrlw $1, %xmm1 +; SSE2-NEXT: packuswb %xmm6, %xmm1 +; SSE2-NEXT: psrlw $1, %xmm5 +; SSE2-NEXT: psrlw $1, %xmm0 +; SSE2-NEXT: packuswb %xmm5, %xmm0 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v64i8: +; SSE4: # %bb.0: +; SSE4-NEXT: movdqa %xmm3, %xmm9 +; SSE4-NEXT: movdqa %xmm2, %xmm10 +; SSE4-NEXT: movdqa %xmm1, %xmm11 +; SSE4-NEXT: movdqa %xmm0, %xmm8 +; SSE4-NEXT: pxor %xmm13, %xmm13 +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm0 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero +; SSE4-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; SSE4-NEXT: punpckhbw {{.*#+}} xmm9 = xmm9[8],xmm13[8],xmm9[9],xmm13[9],xmm9[10],xmm13[10],xmm9[11],xmm13[11],xmm9[12],xmm13[12],xmm9[13],xmm13[13],xmm9[14],xmm13[14],xmm9[15],xmm13[15] +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm14 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; SSE4-NEXT: punpckhbw {{.*#+}} xmm10 = xmm10[8],xmm13[8],xmm10[9],xmm13[9],xmm10[10],xmm13[10],xmm10[11],xmm13[11],xmm10[12],xmm13[12],xmm10[13],xmm13[13],xmm10[14],xmm13[14],xmm10[15],xmm13[15] +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm15 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero +; SSE4-NEXT: punpckhbw {{.*#+}} xmm11 = xmm11[8],xmm13[8],xmm11[9],xmm13[9],xmm11[10],xmm13[10],xmm11[11],xmm13[11],xmm11[12],xmm13[12],xmm11[13],xmm13[13],xmm11[14],xmm13[14],xmm11[15],xmm13[15] +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm12 = xmm8[0],zero,xmm8[1],zero,xmm8[2],zero,xmm8[3],zero,xmm8[4],zero,xmm8[5],zero,xmm8[6],zero,xmm8[7],zero +; SSE4-NEXT: punpckhbw {{.*#+}} xmm8 = xmm8[8],xmm13[8],xmm8[9],xmm13[9],xmm8[10],xmm13[10],xmm8[11],xmm13[11],xmm8[12],xmm13[12],xmm8[13],xmm13[13],xmm8[14],xmm13[14],xmm8[15],xmm13[15] +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm3 = xmm7[0],zero,xmm7[1],zero,xmm7[2],zero,xmm7[3],zero,xmm7[4],zero,xmm7[5],zero,xmm7[6],zero,xmm7[7],zero +; SSE4-NEXT: punpckhbw {{.*#+}} xmm7 = xmm7[8],xmm13[8],xmm7[9],xmm13[9],xmm7[10],xmm13[10],xmm7[11],xmm13[11],xmm7[12],xmm13[12],xmm7[13],xmm13[13],xmm7[14],xmm13[14],xmm7[15],xmm13[15] +; SSE4-NEXT: paddw %xmm9, %xmm7 +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm2 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero +; SSE4-NEXT: punpckhbw {{.*#+}} xmm6 = xmm6[8],xmm13[8],xmm6[9],xmm13[9],xmm6[10],xmm13[10],xmm6[11],xmm13[11],xmm6[12],xmm13[12],xmm6[13],xmm13[13],xmm6[14],xmm13[14],xmm6[15],xmm13[15] +; SSE4-NEXT: paddw %xmm10, %xmm6 +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm1 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero +; SSE4-NEXT: punpckhbw {{.*#+}} xmm5 = xmm5[8],xmm13[8],xmm5[9],xmm13[9],xmm5[10],xmm13[10],xmm5[11],xmm13[11],xmm5[12],xmm13[12],xmm5[13],xmm13[13],xmm5[14],xmm13[14],xmm5[15],xmm13[15] +; SSE4-NEXT: paddw %xmm11, %xmm5 +; SSE4-NEXT: pmovzxbw {{.*#+}} xmm0 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero +; SSE4-NEXT: punpckhbw {{.*#+}} xmm4 = xmm4[8],xmm13[8],xmm4[9],xmm13[9],xmm4[10],xmm13[10],xmm4[11],xmm13[11],xmm4[12],xmm13[12],xmm4[13],xmm13[13],xmm4[14],xmm13[14],xmm4[15],xmm13[15] +; SSE4-NEXT: paddw %xmm8, %xmm4 +; SSE4-NEXT: paddw {{[-0-9]+}}(%r{{[sb]}}p), %xmm3 # 16-byte Folded Reload +; SSE4-NEXT: paddw %xmm14, %xmm2 +; SSE4-NEXT: paddw %xmm15, %xmm1 +; SSE4-NEXT: paddw %xmm12, %xmm0 +; SSE4-NEXT: psrlw $1, %xmm7 +; SSE4-NEXT: psrlw $1, %xmm6 +; SSE4-NEXT: psrlw $1, %xmm5 +; SSE4-NEXT: psrlw $1, %xmm4 +; SSE4-NEXT: psrlw $1, %xmm3 +; SSE4-NEXT: packuswb %xmm7, %xmm3 +; SSE4-NEXT: psrlw $1, %xmm2 +; SSE4-NEXT: packuswb %xmm6, %xmm2 +; SSE4-NEXT: psrlw $1, %xmm1 +; SSE4-NEXT: packuswb %xmm5, %xmm1 +; SSE4-NEXT: psrlw $1, %xmm0 +; SSE4-NEXT: packuswb %xmm4, %xmm0 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v64i8: +; AVX1: # %bb.0: +; AVX1-NEXT: vpxor %xmm4, %xmm4, %xmm4 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm1[8],xmm4[8],xmm1[9],xmm4[9],xmm1[10],xmm4[10],xmm1[11],xmm4[11],xmm1[12],xmm4[12],xmm1[13],xmm4[13],xmm1[14],xmm4[14],xmm1[15],xmm4[15] +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm6 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm6[8],xmm4[8],xmm6[9],xmm4[9],xmm6[10],xmm4[10],xmm6[11],xmm4[11],xmm6[12],xmm4[12],xmm6[13],xmm4[13],xmm6[14],xmm4[14],xmm6[15],xmm4[15] +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm8 = xmm0[8],xmm4[8],xmm0[9],xmm4[9],xmm0[10],xmm4[10],xmm0[11],xmm4[11],xmm0[12],xmm4[12],xmm0[13],xmm4[13],xmm0[14],xmm4[14],xmm0[15],xmm4[15] +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm9 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm10 = xmm9[8],xmm4[8],xmm9[9],xmm4[9],xmm9[10],xmm4[10],xmm9[11],xmm4[11],xmm9[12],xmm4[12],xmm9[13],xmm4[13],xmm9[14],xmm4[14],xmm9[15],xmm4[15] +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm6 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm9 = xmm9[0],zero,xmm9[1],zero,xmm9[2],zero,xmm9[3],zero,xmm9[4],zero,xmm9[5],zero,xmm9[6],zero,xmm9[7],zero +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm11 = xmm3[8],xmm4[8],xmm3[9],xmm4[9],xmm3[10],xmm4[10],xmm3[11],xmm4[11],xmm3[12],xmm4[12],xmm3[13],xmm4[13],xmm3[14],xmm4[14],xmm3[15],xmm4[15] +; AVX1-NEXT: vpaddw %xmm5, %xmm11, %xmm5 +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm11 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm12 = xmm11[8],xmm4[8],xmm11[9],xmm4[9],xmm11[10],xmm4[10],xmm11[11],xmm4[11],xmm11[12],xmm4[12],xmm11[13],xmm4[13],xmm11[14],xmm4[14],xmm11[15],xmm4[15] +; AVX1-NEXT: vpaddw %xmm7, %xmm12, %xmm7 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm12 = xmm2[8],xmm4[8],xmm2[9],xmm4[9],xmm2[10],xmm4[10],xmm2[11],xmm4[11],xmm2[12],xmm4[12],xmm2[13],xmm4[13],xmm2[14],xmm4[14],xmm2[15],xmm4[15] +; AVX1-NEXT: vpaddw %xmm12, %xmm8, %xmm8 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm12 +; AVX1-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm12[8],xmm4[8],xmm12[9],xmm4[9],xmm12[10],xmm4[10],xmm12[11],xmm4[11],xmm12[12],xmm4[12],xmm12[13],xmm4[13],xmm12[14],xmm4[14],xmm12[15],xmm4[15] +; AVX1-NEXT: vpaddw %xmm4, %xmm10, %xmm4 +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero +; AVX1-NEXT: vpaddw %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm3 = xmm11[0],zero,xmm11[1],zero,xmm11[2],zero,xmm11[3],zero,xmm11[4],zero,xmm11[5],zero,xmm11[6],zero,xmm11[7],zero +; AVX1-NEXT: vpaddw %xmm3, %xmm6, %xmm3 +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; AVX1-NEXT: vpaddw %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpmovzxbw {{.*#+}} xmm2 = xmm12[0],zero,xmm12[1],zero,xmm12[2],zero,xmm12[3],zero,xmm12[4],zero,xmm12[5],zero,xmm12[6],zero,xmm12[7],zero +; AVX1-NEXT: vpaddw %xmm2, %xmm9, %xmm2 +; AVX1-NEXT: vpsrlw $1, %xmm5, %xmm5 +; AVX1-NEXT: vpsrlw $1, %xmm7, %xmm6 +; AVX1-NEXT: vpsrlw $1, %xmm8, %xmm7 +; AVX1-NEXT: vpsrlw $1, %xmm4, %xmm4 +; AVX1-NEXT: vpsrlw $1, %xmm1, %xmm1 +; AVX1-NEXT: vpackuswb %xmm5, %xmm1, %xmm1 +; AVX1-NEXT: vpsrlw $1, %xmm3, %xmm3 +; AVX1-NEXT: vpackuswb %xmm6, %xmm3, %xmm3 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vpackuswb %xmm7, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm2, %xmm2 +; AVX1-NEXT: vpackuswb %xmm4, %xmm2, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 +; AVX1-NEXT: vinsertf128 $1, %xmm3, %ymm1, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v64i8: +; AVX2: # %bb.0: +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm4 +; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm4 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero,xmm4[8],zero,xmm4[9],zero,xmm4[10],zero,xmm4[11],zero,xmm4[12],zero,xmm4[13],zero,xmm4[14],zero,xmm4[15],zero +; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero,xmm1[8],zero,xmm1[9],zero,xmm1[10],zero,xmm1[11],zero,xmm1[12],zero,xmm1[13],zero,xmm1[14],zero,xmm1[15],zero +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm5 +; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm5 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero,xmm5[8],zero,xmm5[9],zero,xmm5[10],zero,xmm5[11],zero,xmm5[12],zero,xmm5[13],zero,xmm5[14],zero,xmm5[15],zero +; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero,xmm0[8],zero,xmm0[9],zero,xmm0[10],zero,xmm0[11],zero,xmm0[12],zero,xmm0[13],zero,xmm0[14],zero,xmm0[15],zero +; AVX2-NEXT: vextracti128 $1, %ymm3, %xmm6 +; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm6 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero,xmm6[8],zero,xmm6[9],zero,xmm6[10],zero,xmm6[11],zero,xmm6[12],zero,xmm6[13],zero,xmm6[14],zero,xmm6[15],zero +; AVX2-NEXT: vpaddw %ymm6, %ymm4, %ymm4 +; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm3 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero,xmm3[8],zero,xmm3[9],zero,xmm3[10],zero,xmm3[11],zero,xmm3[12],zero,xmm3[13],zero,xmm3[14],zero,xmm3[15],zero +; AVX2-NEXT: vpaddw %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: vextracti128 $1, %ymm2, %xmm3 +; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm3 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero,xmm3[8],zero,xmm3[9],zero,xmm3[10],zero,xmm3[11],zero,xmm3[12],zero,xmm3[13],zero,xmm3[14],zero,xmm3[15],zero +; AVX2-NEXT: vpaddw %ymm3, %ymm5, %ymm3 +; AVX2-NEXT: vpmovzxbw {{.*#+}} ymm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero,xmm2[8],zero,xmm2[9],zero,xmm2[10],zero,xmm2[11],zero,xmm2[12],zero,xmm2[13],zero,xmm2[14],zero,xmm2[15],zero +; AVX2-NEXT: vpaddw %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlw $1, %ymm4, %ymm2 +; AVX2-NEXT: vpsrlw $1, %ymm1, %ymm1 +; AVX2-NEXT: vpackuswb %ymm2, %ymm1, %ymm1 +; AVX2-NEXT: vpsrlw $1, %ymm3, %ymm2 +; AVX2-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpackuswb %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,2,1,3] +; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,2,1,3] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v64i8: +; AVX512: # %bb.0: +; AVX512-NEXT: vextracti64x4 $1, %zmm0, %ymm2 +; AVX512-NEXT: vpmovzxbw {{.*#+}} zmm2 = ymm2[0],zero,ymm2[1],zero,ymm2[2],zero,ymm2[3],zero,ymm2[4],zero,ymm2[5],zero,ymm2[6],zero,ymm2[7],zero,ymm2[8],zero,ymm2[9],zero,ymm2[10],zero,ymm2[11],zero,ymm2[12],zero,ymm2[13],zero,ymm2[14],zero,ymm2[15],zero,ymm2[16],zero,ymm2[17],zero,ymm2[18],zero,ymm2[19],zero,ymm2[20],zero,ymm2[21],zero,ymm2[22],zero,ymm2[23],zero,ymm2[24],zero,ymm2[25],zero,ymm2[26],zero,ymm2[27],zero,ymm2[28],zero,ymm2[29],zero,ymm2[30],zero,ymm2[31],zero +; AVX512-NEXT: vpmovzxbw {{.*#+}} zmm0 = ymm0[0],zero,ymm0[1],zero,ymm0[2],zero,ymm0[3],zero,ymm0[4],zero,ymm0[5],zero,ymm0[6],zero,ymm0[7],zero,ymm0[8],zero,ymm0[9],zero,ymm0[10],zero,ymm0[11],zero,ymm0[12],zero,ymm0[13],zero,ymm0[14],zero,ymm0[15],zero,ymm0[16],zero,ymm0[17],zero,ymm0[18],zero,ymm0[19],zero,ymm0[20],zero,ymm0[21],zero,ymm0[22],zero,ymm0[23],zero,ymm0[24],zero,ymm0[25],zero,ymm0[26],zero,ymm0[27],zero,ymm0[28],zero,ymm0[29],zero,ymm0[30],zero,ymm0[31],zero +; AVX512-NEXT: vextracti64x4 $1, %zmm1, %ymm3 +; AVX512-NEXT: vpmovzxbw {{.*#+}} zmm3 = ymm3[0],zero,ymm3[1],zero,ymm3[2],zero,ymm3[3],zero,ymm3[4],zero,ymm3[5],zero,ymm3[6],zero,ymm3[7],zero,ymm3[8],zero,ymm3[9],zero,ymm3[10],zero,ymm3[11],zero,ymm3[12],zero,ymm3[13],zero,ymm3[14],zero,ymm3[15],zero,ymm3[16],zero,ymm3[17],zero,ymm3[18],zero,ymm3[19],zero,ymm3[20],zero,ymm3[21],zero,ymm3[22],zero,ymm3[23],zero,ymm3[24],zero,ymm3[25],zero,ymm3[26],zero,ymm3[27],zero,ymm3[28],zero,ymm3[29],zero,ymm3[30],zero,ymm3[31],zero +; AVX512-NEXT: vpaddw %zmm3, %zmm2, %zmm2 +; AVX512-NEXT: vpmovzxbw {{.*#+}} zmm1 = ymm1[0],zero,ymm1[1],zero,ymm1[2],zero,ymm1[3],zero,ymm1[4],zero,ymm1[5],zero,ymm1[6],zero,ymm1[7],zero,ymm1[8],zero,ymm1[9],zero,ymm1[10],zero,ymm1[11],zero,ymm1[12],zero,ymm1[13],zero,ymm1[14],zero,ymm1[15],zero,ymm1[16],zero,ymm1[17],zero,ymm1[18],zero,ymm1[19],zero,ymm1[20],zero,ymm1[21],zero,ymm1[22],zero,ymm1[23],zero,ymm1[24],zero,ymm1[25],zero,ymm1[26],zero,ymm1[27],zero,ymm1[28],zero,ymm1[29],zero,ymm1[30],zero,ymm1[31],zero +; AVX512-NEXT: vpaddw %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlw $1, %zmm2, %zmm1 +; AVX512-NEXT: vpsrlw $1, %zmm0, %zmm0 +; AVX512-NEXT: vpmovwb %zmm0, %ymm0 +; AVX512-NEXT: vpmovwb %zmm1, %ymm1 +; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm0, %zmm0 +; AVX512-NEXT: retq + %x0 = zext <64 x i8> %a0 to <64 x i16> + %x1 = zext <64 x i8> %a1 to <64 x i16> + %sum = add <64 x i16> %x0, %x1 + %shift = lshr <64 x i16> %sum, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = trunc <64 x i16> %shift to <64 x i8> + ret <64 x i8> %res +} + +define <32 x i16> @test_fixed_v32i16(<32 x i16> %a0, <32 x i16> %a1) { +; SSE-LABEL: test_fixed_v32i16: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm3, %xmm8 +; SSE-NEXT: pand %xmm7, %xmm8 +; SSE-NEXT: movdqa %xmm2, %xmm9 +; SSE-NEXT: pand %xmm6, %xmm9 +; SSE-NEXT: movdqa %xmm1, %xmm10 +; SSE-NEXT: pand %xmm5, %xmm10 +; SSE-NEXT: movdqa %xmm0, %xmm11 +; SSE-NEXT: pand %xmm4, %xmm11 +; SSE-NEXT: pxor %xmm4, %xmm0 +; SSE-NEXT: pxor %xmm5, %xmm1 +; SSE-NEXT: pxor %xmm6, %xmm2 +; SSE-NEXT: pxor %xmm7, %xmm3 +; SSE-NEXT: psrlw $1, %xmm3 +; SSE-NEXT: paddw %xmm8, %xmm3 +; SSE-NEXT: psrlw $1, %xmm2 +; SSE-NEXT: paddw %xmm9, %xmm2 +; SSE-NEXT: psrlw $1, %xmm1 +; SSE-NEXT: paddw %xmm10, %xmm1 +; SSE-NEXT: psrlw $1, %xmm0 +; SSE-NEXT: paddw %xmm11, %xmm0 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v32i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vandps %ymm3, %ymm1, %ymm4 +; AVX1-NEXT: vandps %ymm2, %ymm0, %ymm5 +; AVX1-NEXT: vxorps %ymm0, %ymm2, %ymm0 +; AVX1-NEXT: vxorps %ymm1, %ymm3, %ymm1 +; AVX1-NEXT: vpsrlw $1, %xmm1, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpsrlw $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm3 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm5, %xmm6 +; AVX1-NEXT: vpaddw %xmm0, %xmm6, %xmm0 +; AVX1-NEXT: vpaddw %xmm3, %xmm5, %xmm3 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm3, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm4, %xmm3 +; AVX1-NEXT: vpaddw %xmm1, %xmm3, %xmm1 +; AVX1-NEXT: vpaddw %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v32i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %ymm3, %ymm1, %ymm4 +; AVX2-NEXT: vpand %ymm2, %ymm0, %ymm5 +; AVX2-NEXT: vpxor %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: vpxor %ymm1, %ymm3, %ymm1 +; AVX2-NEXT: vpsrlw $1, %ymm1, %ymm1 +; AVX2-NEXT: vpaddw %ymm1, %ymm4, %ymm1 +; AVX2-NEXT: vpsrlw $1, %ymm0, %ymm0 +; AVX2-NEXT: vpaddw %ymm0, %ymm5, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v32i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vpandq %zmm1, %zmm0, %zmm2 +; AVX512-NEXT: vpxorq %zmm0, %zmm1, %zmm0 +; AVX512-NEXT: vpsrlw $1, %zmm0, %zmm0 +; AVX512-NEXT: vpaddw %zmm0, %zmm2, %zmm0 +; AVX512-NEXT: retq + %and = and <32 x i16> %a0, %a1 + %xor = xor <32 x i16> %a1, %a0 + %shift = lshr <32 x i16> %xor, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> + %res = add <32 x i16> %and, %shift + ret <32 x i16> %res +} + +define <32 x i16> @test_ext_v32i16(<32 x i16> %a0, <32 x i16> %a1) { +; SSE2-LABEL: test_ext_v32i16: +; SSE2: # %bb.0: +; SSE2-NEXT: pxor %xmm8, %xmm8 +; SSE2-NEXT: movdqa %xmm0, %xmm9 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm9 = xmm9[4],xmm8[4],xmm9[5],xmm8[5],xmm9[6],xmm8[6],xmm9[7],xmm8[7] +; SSE2-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm8[0],xmm0[1],xmm8[1],xmm0[2],xmm8[2],xmm0[3],xmm8[3] +; SSE2-NEXT: movdqa %xmm1, %xmm11 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm11 = xmm11[4],xmm8[4],xmm11[5],xmm8[5],xmm11[6],xmm8[6],xmm11[7],xmm8[7] +; SSE2-NEXT: punpcklwd {{.*#+}} xmm1 = xmm1[0],xmm8[0],xmm1[1],xmm8[1],xmm1[2],xmm8[2],xmm1[3],xmm8[3] +; SSE2-NEXT: movdqa %xmm2, %xmm12 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm12 = xmm12[4],xmm8[4],xmm12[5],xmm8[5],xmm12[6],xmm8[6],xmm12[7],xmm8[7] +; SSE2-NEXT: punpcklwd {{.*#+}} xmm2 = xmm2[0],xmm8[0],xmm2[1],xmm8[1],xmm2[2],xmm8[2],xmm2[3],xmm8[3] +; SSE2-NEXT: movdqa %xmm3, %xmm13 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm13 = xmm13[4],xmm8[4],xmm13[5],xmm8[5],xmm13[6],xmm8[6],xmm13[7],xmm8[7] +; SSE2-NEXT: punpcklwd {{.*#+}} xmm3 = xmm3[0],xmm8[0],xmm3[1],xmm8[1],xmm3[2],xmm8[2],xmm3[3],xmm8[3] +; SSE2-NEXT: movdqa %xmm4, %xmm10 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm10 = xmm10[4],xmm8[4],xmm10[5],xmm8[5],xmm10[6],xmm8[6],xmm10[7],xmm8[7] +; SSE2-NEXT: paddd %xmm9, %xmm10 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm4 = xmm4[0],xmm8[0],xmm4[1],xmm8[1],xmm4[2],xmm8[2],xmm4[3],xmm8[3] +; SSE2-NEXT: paddd %xmm4, %xmm0 +; SSE2-NEXT: movdqa %xmm5, %xmm9 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm9 = xmm9[4],xmm8[4],xmm9[5],xmm8[5],xmm9[6],xmm8[6],xmm9[7],xmm8[7] +; SSE2-NEXT: paddd %xmm11, %xmm9 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm5 = xmm5[0],xmm8[0],xmm5[1],xmm8[1],xmm5[2],xmm8[2],xmm5[3],xmm8[3] +; SSE2-NEXT: paddd %xmm5, %xmm1 +; SSE2-NEXT: movdqa %xmm6, %xmm5 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm5 = xmm5[4],xmm8[4],xmm5[5],xmm8[5],xmm5[6],xmm8[6],xmm5[7],xmm8[7] +; SSE2-NEXT: paddd %xmm12, %xmm5 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm6 = xmm6[0],xmm8[0],xmm6[1],xmm8[1],xmm6[2],xmm8[2],xmm6[3],xmm8[3] +; SSE2-NEXT: paddd %xmm6, %xmm2 +; SSE2-NEXT: movdqa %xmm7, %xmm4 +; SSE2-NEXT: punpckhwd {{.*#+}} xmm4 = xmm4[4],xmm8[4],xmm4[5],xmm8[5],xmm4[6],xmm8[6],xmm4[7],xmm8[7] +; SSE2-NEXT: paddd %xmm13, %xmm4 +; SSE2-NEXT: punpcklwd {{.*#+}} xmm7 = xmm7[0],xmm8[0],xmm7[1],xmm8[1],xmm7[2],xmm8[2],xmm7[3],xmm8[3] +; SSE2-NEXT: paddd %xmm7, %xmm3 +; SSE2-NEXT: pslld $15, %xmm10 +; SSE2-NEXT: psrad $16, %xmm10 +; SSE2-NEXT: pslld $15, %xmm0 +; SSE2-NEXT: psrad $16, %xmm0 +; SSE2-NEXT: packssdw %xmm10, %xmm0 +; SSE2-NEXT: pslld $15, %xmm9 +; SSE2-NEXT: psrad $16, %xmm9 +; SSE2-NEXT: pslld $15, %xmm1 +; SSE2-NEXT: psrad $16, %xmm1 +; SSE2-NEXT: packssdw %xmm9, %xmm1 +; SSE2-NEXT: pslld $15, %xmm5 +; SSE2-NEXT: psrad $16, %xmm5 +; SSE2-NEXT: pslld $15, %xmm2 +; SSE2-NEXT: psrad $16, %xmm2 +; SSE2-NEXT: packssdw %xmm5, %xmm2 +; SSE2-NEXT: pslld $15, %xmm4 +; SSE2-NEXT: psrad $16, %xmm4 +; SSE2-NEXT: pslld $15, %xmm3 +; SSE2-NEXT: psrad $16, %xmm3 +; SSE2-NEXT: packssdw %xmm4, %xmm3 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v32i16: +; SSE4: # %bb.0: +; SSE4-NEXT: movdqa %xmm3, %xmm9 +; SSE4-NEXT: movdqa %xmm2, %xmm10 +; SSE4-NEXT: movdqa %xmm1, %xmm11 +; SSE4-NEXT: movdqa %xmm0, %xmm8 +; SSE4-NEXT: pxor %xmm13, %xmm13 +; SSE4-NEXT: pmovzxwd {{.*#+}} xmm0 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero +; SSE4-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; SSE4-NEXT: punpckhwd {{.*#+}} xmm9 = xmm9[4],xmm13[4],xmm9[5],xmm13[5],xmm9[6],xmm13[6],xmm9[7],xmm13[7] +; SSE4-NEXT: pmovzxwd {{.*#+}} xmm14 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero +; SSE4-NEXT: punpckhwd {{.*#+}} xmm10 = xmm10[4],xmm13[4],xmm10[5],xmm13[5],xmm10[6],xmm13[6],xmm10[7],xmm13[7] +; SSE4-NEXT: pmovzxwd {{.*#+}} xmm15 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero +; SSE4-NEXT: punpckhwd {{.*#+}} xmm11 = xmm11[4],xmm13[4],xmm11[5],xmm13[5],xmm11[6],xmm13[6],xmm11[7],xmm13[7] +; SSE4-NEXT: pmovzxwd {{.*#+}} xmm12 = xmm8[0],zero,xmm8[1],zero,xmm8[2],zero,xmm8[3],zero +; SSE4-NEXT: punpckhwd {{.*#+}} xmm8 = xmm8[4],xmm13[4],xmm8[5],xmm13[5],xmm8[6],xmm13[6],xmm8[7],xmm13[7] +; SSE4-NEXT: pmovzxwd {{.*#+}} xmm3 = xmm7[0],zero,xmm7[1],zero,xmm7[2],zero,xmm7[3],zero +; SSE4-NEXT: punpckhwd {{.*#+}} xmm7 = xmm7[4],xmm13[4],xmm7[5],xmm13[5],xmm7[6],xmm13[6],xmm7[7],xmm13[7] +; SSE4-NEXT: paddd %xmm9, %xmm7 +; SSE4-NEXT: pmovzxwd {{.*#+}} xmm2 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero +; SSE4-NEXT: punpckhwd {{.*#+}} xmm6 = xmm6[4],xmm13[4],xmm6[5],xmm13[5],xmm6[6],xmm13[6],xmm6[7],xmm13[7] +; SSE4-NEXT: paddd %xmm10, %xmm6 +; SSE4-NEXT: pmovzxwd {{.*#+}} xmm1 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero +; SSE4-NEXT: punpckhwd {{.*#+}} xmm5 = xmm5[4],xmm13[4],xmm5[5],xmm13[5],xmm5[6],xmm13[6],xmm5[7],xmm13[7] +; SSE4-NEXT: paddd %xmm11, %xmm5 +; SSE4-NEXT: pmovzxwd {{.*#+}} xmm0 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero +; SSE4-NEXT: punpckhwd {{.*#+}} xmm4 = xmm4[4],xmm13[4],xmm4[5],xmm13[5],xmm4[6],xmm13[6],xmm4[7],xmm13[7] +; SSE4-NEXT: paddd %xmm8, %xmm4 +; SSE4-NEXT: paddd {{[-0-9]+}}(%r{{[sb]}}p), %xmm3 # 16-byte Folded Reload +; SSE4-NEXT: paddd %xmm14, %xmm2 +; SSE4-NEXT: paddd %xmm15, %xmm1 +; SSE4-NEXT: paddd %xmm12, %xmm0 +; SSE4-NEXT: psrld $1, %xmm7 +; SSE4-NEXT: psrld $1, %xmm6 +; SSE4-NEXT: psrld $1, %xmm5 +; SSE4-NEXT: psrld $1, %xmm4 +; SSE4-NEXT: psrld $1, %xmm3 +; SSE4-NEXT: packusdw %xmm7, %xmm3 +; SSE4-NEXT: psrld $1, %xmm2 +; SSE4-NEXT: packusdw %xmm6, %xmm2 +; SSE4-NEXT: psrld $1, %xmm1 +; SSE4-NEXT: packusdw %xmm5, %xmm1 +; SSE4-NEXT: psrld $1, %xmm0 +; SSE4-NEXT: packusdw %xmm4, %xmm0 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v32i16: +; AVX1: # %bb.0: +; AVX1-NEXT: vpxor %xmm4, %xmm4, %xmm4 +; AVX1-NEXT: vpunpckhwd {{.*#+}} xmm5 = xmm1[4],xmm4[4],xmm1[5],xmm4[5],xmm1[6],xmm4[6],xmm1[7],xmm4[7] +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm6 +; AVX1-NEXT: vpunpckhwd {{.*#+}} xmm7 = xmm6[4],xmm4[4],xmm6[5],xmm4[5],xmm6[6],xmm4[6],xmm6[7],xmm4[7] +; AVX1-NEXT: vpunpckhwd {{.*#+}} xmm8 = xmm0[4],xmm4[4],xmm0[5],xmm4[5],xmm0[6],xmm4[6],xmm0[7],xmm4[7] +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm9 +; AVX1-NEXT: vpunpckhwd {{.*#+}} xmm10 = xmm9[4],xmm4[4],xmm9[5],xmm4[5],xmm9[6],xmm4[6],xmm9[7],xmm4[7] +; AVX1-NEXT: vpmovzxwd {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero +; AVX1-NEXT: vpmovzxwd {{.*#+}} xmm6 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero +; AVX1-NEXT: vpmovzxwd {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; AVX1-NEXT: vpmovzxwd {{.*#+}} xmm9 = xmm9[0],zero,xmm9[1],zero,xmm9[2],zero,xmm9[3],zero +; AVX1-NEXT: vpunpckhwd {{.*#+}} xmm11 = xmm3[4],xmm4[4],xmm3[5],xmm4[5],xmm3[6],xmm4[6],xmm3[7],xmm4[7] +; AVX1-NEXT: vpaddd %xmm5, %xmm11, %xmm5 +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm11 +; AVX1-NEXT: vpunpckhwd {{.*#+}} xmm12 = xmm11[4],xmm4[4],xmm11[5],xmm4[5],xmm11[6],xmm4[6],xmm11[7],xmm4[7] +; AVX1-NEXT: vpaddd %xmm7, %xmm12, %xmm7 +; AVX1-NEXT: vpunpckhwd {{.*#+}} xmm12 = xmm2[4],xmm4[4],xmm2[5],xmm4[5],xmm2[6],xmm4[6],xmm2[7],xmm4[7] +; AVX1-NEXT: vpaddd %xmm12, %xmm8, %xmm8 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm12 +; AVX1-NEXT: vpunpckhwd {{.*#+}} xmm4 = xmm12[4],xmm4[4],xmm12[5],xmm4[5],xmm12[6],xmm4[6],xmm12[7],xmm4[7] +; AVX1-NEXT: vpaddd %xmm4, %xmm10, %xmm4 +; AVX1-NEXT: vpmovzxwd {{.*#+}} xmm3 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero +; AVX1-NEXT: vpaddd %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vpmovzxwd {{.*#+}} xmm3 = xmm11[0],zero,xmm11[1],zero,xmm11[2],zero,xmm11[3],zero +; AVX1-NEXT: vpaddd %xmm3, %xmm6, %xmm3 +; AVX1-NEXT: vpmovzxwd {{.*#+}} xmm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero +; AVX1-NEXT: vpaddd %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpmovzxwd {{.*#+}} xmm2 = xmm12[0],zero,xmm12[1],zero,xmm12[2],zero,xmm12[3],zero +; AVX1-NEXT: vpaddd %xmm2, %xmm9, %xmm2 +; AVX1-NEXT: vpsrld $1, %xmm5, %xmm5 +; AVX1-NEXT: vpsrld $1, %xmm7, %xmm6 +; AVX1-NEXT: vpsrld $1, %xmm8, %xmm7 +; AVX1-NEXT: vpsrld $1, %xmm4, %xmm4 +; AVX1-NEXT: vpsrld $1, %xmm1, %xmm1 +; AVX1-NEXT: vpackusdw %xmm5, %xmm1, %xmm1 +; AVX1-NEXT: vpsrld $1, %xmm3, %xmm3 +; AVX1-NEXT: vpackusdw %xmm6, %xmm3, %xmm3 +; AVX1-NEXT: vpsrld $1, %xmm0, %xmm0 +; AVX1-NEXT: vpackusdw %xmm7, %xmm0, %xmm0 +; AVX1-NEXT: vpsrld $1, %xmm2, %xmm2 +; AVX1-NEXT: vpackusdw %xmm4, %xmm2, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 +; AVX1-NEXT: vinsertf128 $1, %xmm3, %ymm1, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v32i16: +; AVX2: # %bb.0: +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm4 +; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm4 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero,xmm4[4],zero,xmm4[5],zero,xmm4[6],zero,xmm4[7],zero +; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm5 +; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm5 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero,xmm5[4],zero,xmm5[5],zero,xmm5[6],zero,xmm5[7],zero +; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero,xmm0[4],zero,xmm0[5],zero,xmm0[6],zero,xmm0[7],zero +; AVX2-NEXT: vextracti128 $1, %ymm3, %xmm6 +; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm6 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero,xmm6[4],zero,xmm6[5],zero,xmm6[6],zero,xmm6[7],zero +; AVX2-NEXT: vpaddd %ymm6, %ymm4, %ymm4 +; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm3 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero +; AVX2-NEXT: vpaddd %ymm3, %ymm1, %ymm1 +; AVX2-NEXT: vextracti128 $1, %ymm2, %xmm3 +; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm3 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero,xmm3[4],zero,xmm3[5],zero,xmm3[6],zero,xmm3[7],zero +; AVX2-NEXT: vpaddd %ymm3, %ymm5, %ymm3 +; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero,xmm2[4],zero,xmm2[5],zero,xmm2[6],zero,xmm2[7],zero +; AVX2-NEXT: vpaddd %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpsrld $1, %ymm4, %ymm2 +; AVX2-NEXT: vpsrld $1, %ymm1, %ymm1 +; AVX2-NEXT: vpackusdw %ymm2, %ymm1, %ymm1 +; AVX2-NEXT: vpsrld $1, %ymm3, %ymm2 +; AVX2-NEXT: vpsrld $1, %ymm0, %ymm0 +; AVX2-NEXT: vpackusdw %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,2,1,3] +; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,2,1,3] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v32i16: +; AVX512: # %bb.0: +; AVX512-NEXT: vextracti64x4 $1, %zmm0, %ymm2 +; AVX512-NEXT: vpmovzxwd {{.*#+}} zmm2 = ymm2[0],zero,ymm2[1],zero,ymm2[2],zero,ymm2[3],zero,ymm2[4],zero,ymm2[5],zero,ymm2[6],zero,ymm2[7],zero,ymm2[8],zero,ymm2[9],zero,ymm2[10],zero,ymm2[11],zero,ymm2[12],zero,ymm2[13],zero,ymm2[14],zero,ymm2[15],zero +; AVX512-NEXT: vpmovzxwd {{.*#+}} zmm0 = ymm0[0],zero,ymm0[1],zero,ymm0[2],zero,ymm0[3],zero,ymm0[4],zero,ymm0[5],zero,ymm0[6],zero,ymm0[7],zero,ymm0[8],zero,ymm0[9],zero,ymm0[10],zero,ymm0[11],zero,ymm0[12],zero,ymm0[13],zero,ymm0[14],zero,ymm0[15],zero +; AVX512-NEXT: vextracti64x4 $1, %zmm1, %ymm3 +; AVX512-NEXT: vpmovzxwd {{.*#+}} zmm3 = ymm3[0],zero,ymm3[1],zero,ymm3[2],zero,ymm3[3],zero,ymm3[4],zero,ymm3[5],zero,ymm3[6],zero,ymm3[7],zero,ymm3[8],zero,ymm3[9],zero,ymm3[10],zero,ymm3[11],zero,ymm3[12],zero,ymm3[13],zero,ymm3[14],zero,ymm3[15],zero +; AVX512-NEXT: vpaddd %zmm3, %zmm2, %zmm2 +; AVX512-NEXT: vpmovzxwd {{.*#+}} zmm1 = ymm1[0],zero,ymm1[1],zero,ymm1[2],zero,ymm1[3],zero,ymm1[4],zero,ymm1[5],zero,ymm1[6],zero,ymm1[7],zero,ymm1[8],zero,ymm1[9],zero,ymm1[10],zero,ymm1[11],zero,ymm1[12],zero,ymm1[13],zero,ymm1[14],zero,ymm1[15],zero +; AVX512-NEXT: vpaddd %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrld $1, %zmm2, %zmm1 +; AVX512-NEXT: vpsrld $1, %zmm0, %zmm0 +; AVX512-NEXT: vpmovdw %zmm0, %ymm0 +; AVX512-NEXT: vpmovdw %zmm1, %ymm1 +; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm0, %zmm0 +; AVX512-NEXT: retq + %x0 = zext <32 x i16> %a0 to <32 x i32> + %x1 = zext <32 x i16> %a1 to <32 x i32> + %sum = add <32 x i32> %x0, %x1 + %shift = lshr <32 x i32> %sum, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = trunc <32 x i32> %shift to <32 x i16> + ret <32 x i16> %res +} + +define <16 x i32> @test_fixed_v16i32(<16 x i32> %a0, <16 x i32> %a1) { +; SSE-LABEL: test_fixed_v16i32: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm3, %xmm8 +; SSE-NEXT: pand %xmm7, %xmm8 +; SSE-NEXT: movdqa %xmm2, %xmm9 +; SSE-NEXT: pand %xmm6, %xmm9 +; SSE-NEXT: movdqa %xmm1, %xmm10 +; SSE-NEXT: pand %xmm5, %xmm10 +; SSE-NEXT: movdqa %xmm0, %xmm11 +; SSE-NEXT: pand %xmm4, %xmm11 +; SSE-NEXT: pxor %xmm4, %xmm0 +; SSE-NEXT: pxor %xmm5, %xmm1 +; SSE-NEXT: pxor %xmm6, %xmm2 +; SSE-NEXT: pxor %xmm7, %xmm3 +; SSE-NEXT: psrld $1, %xmm3 +; SSE-NEXT: paddd %xmm8, %xmm3 +; SSE-NEXT: psrld $1, %xmm2 +; SSE-NEXT: paddd %xmm9, %xmm2 +; SSE-NEXT: psrld $1, %xmm1 +; SSE-NEXT: paddd %xmm10, %xmm1 +; SSE-NEXT: psrld $1, %xmm0 +; SSE-NEXT: paddd %xmm11, %xmm0 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v16i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vandps %ymm3, %ymm1, %ymm4 +; AVX1-NEXT: vandps %ymm2, %ymm0, %ymm5 +; AVX1-NEXT: vxorps %ymm0, %ymm2, %ymm0 +; AVX1-NEXT: vxorps %ymm1, %ymm3, %ymm1 +; AVX1-NEXT: vpsrld $1, %xmm1, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpsrld $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsrld $1, %xmm0, %xmm3 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrld $1, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm5, %xmm6 +; AVX1-NEXT: vpaddd %xmm0, %xmm6, %xmm0 +; AVX1-NEXT: vpaddd %xmm3, %xmm5, %xmm3 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm3, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm4, %xmm3 +; AVX1-NEXT: vpaddd %xmm1, %xmm3, %xmm1 +; AVX1-NEXT: vpaddd %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v16i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %ymm3, %ymm1, %ymm4 +; AVX2-NEXT: vpand %ymm2, %ymm0, %ymm5 +; AVX2-NEXT: vpxor %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: vpxor %ymm1, %ymm3, %ymm1 +; AVX2-NEXT: vpsrld $1, %ymm1, %ymm1 +; AVX2-NEXT: vpaddd %ymm1, %ymm4, %ymm1 +; AVX2-NEXT: vpsrld $1, %ymm0, %ymm0 +; AVX2-NEXT: vpaddd %ymm0, %ymm5, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v16i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vpandd %zmm1, %zmm0, %zmm2 +; AVX512-NEXT: vpxord %zmm0, %zmm1, %zmm0 +; AVX512-NEXT: vpsrld $1, %zmm0, %zmm0 +; AVX512-NEXT: vpaddd %zmm0, %zmm2, %zmm0 +; AVX512-NEXT: retq + %and = and <16 x i32> %a0, %a1 + %xor = xor <16 x i32> %a1, %a0 + %shift = lshr <16 x i32> %xor, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1> + %res = add <16 x i32> %and, %shift + ret <16 x i32> %res +} + +define <16 x i32> @test_ext_v16i32(<16 x i32> %a0, <16 x i32> %a1) { +; SSE2-LABEL: test_ext_v16i32: +; SSE2: # %bb.0: +; SSE2-NEXT: pxor %xmm8, %xmm8 +; SSE2-NEXT: movdqa %xmm3, %xmm10 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm10 = xmm10[2],xmm8[2],xmm10[3],xmm8[3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm8[0],xmm3[1],xmm8[1] +; SSE2-NEXT: movdqa %xmm2, %xmm11 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm11 = xmm11[2],xmm8[2],xmm11[3],xmm8[3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm8[0],xmm2[1],xmm8[1] +; SSE2-NEXT: movdqa %xmm1, %xmm12 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm12 = xmm12[2],xmm8[2],xmm12[3],xmm8[3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm8[0],xmm1[1],xmm8[1] +; SSE2-NEXT: movdqa %xmm0, %xmm13 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm13 = xmm13[2],xmm8[2],xmm13[3],xmm8[3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm8[0],xmm0[1],xmm8[1] +; SSE2-NEXT: movdqa %xmm7, %xmm9 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm9 = xmm9[2],xmm8[2],xmm9[3],xmm8[3] +; SSE2-NEXT: paddq %xmm10, %xmm9 +; SSE2-NEXT: punpckldq {{.*#+}} xmm7 = xmm7[0],xmm8[0],xmm7[1],xmm8[1] +; SSE2-NEXT: paddq %xmm7, %xmm3 +; SSE2-NEXT: movdqa %xmm6, %xmm7 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm7 = xmm7[2],xmm8[2],xmm7[3],xmm8[3] +; SSE2-NEXT: paddq %xmm11, %xmm7 +; SSE2-NEXT: punpckldq {{.*#+}} xmm6 = xmm6[0],xmm8[0],xmm6[1],xmm8[1] +; SSE2-NEXT: paddq %xmm6, %xmm2 +; SSE2-NEXT: movdqa %xmm5, %xmm6 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm6 = xmm6[2],xmm8[2],xmm6[3],xmm8[3] +; SSE2-NEXT: paddq %xmm12, %xmm6 +; SSE2-NEXT: punpckldq {{.*#+}} xmm5 = xmm5[0],xmm8[0],xmm5[1],xmm8[1] +; SSE2-NEXT: paddq %xmm5, %xmm1 +; SSE2-NEXT: movdqa %xmm4, %xmm5 +; SSE2-NEXT: punpckhdq {{.*#+}} xmm5 = xmm5[2],xmm8[2],xmm5[3],xmm8[3] +; SSE2-NEXT: paddq %xmm13, %xmm5 +; SSE2-NEXT: punpckldq {{.*#+}} xmm4 = xmm4[0],xmm8[0],xmm4[1],xmm8[1] +; SSE2-NEXT: paddq %xmm4, %xmm0 +; SSE2-NEXT: psrlq $1, %xmm9 +; SSE2-NEXT: psrlq $1, %xmm3 +; SSE2-NEXT: shufps {{.*#+}} xmm3 = xmm3[0,2],xmm9[0,2] +; SSE2-NEXT: psrlq $1, %xmm7 +; SSE2-NEXT: psrlq $1, %xmm2 +; SSE2-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,2],xmm7[0,2] +; SSE2-NEXT: psrlq $1, %xmm6 +; SSE2-NEXT: psrlq $1, %xmm1 +; SSE2-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm6[0,2] +; SSE2-NEXT: psrlq $1, %xmm5 +; SSE2-NEXT: psrlq $1, %xmm0 +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm5[0,2] +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v16i32: +; SSE4: # %bb.0: +; SSE4-NEXT: movdqa %xmm3, %xmm9 +; SSE4-NEXT: movdqa %xmm2, %xmm10 +; SSE4-NEXT: movdqa %xmm1, %xmm11 +; SSE4-NEXT: movdqa %xmm0, %xmm8 +; SSE4-NEXT: pxor %xmm13, %xmm13 +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm0 = xmm3[0],zero,xmm3[1],zero +; SSE4-NEXT: movdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; SSE4-NEXT: punpckhdq {{.*#+}} xmm9 = xmm9[2],xmm13[2],xmm9[3],xmm13[3] +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm14 = xmm2[0],zero,xmm2[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm10 = xmm10[2],xmm13[2],xmm10[3],xmm13[3] +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm15 = xmm1[0],zero,xmm1[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm11 = xmm11[2],xmm13[2],xmm11[3],xmm13[3] +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm12 = xmm8[0],zero,xmm8[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm8 = xmm8[2],xmm13[2],xmm8[3],xmm13[3] +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm3 = xmm7[0],zero,xmm7[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm7 = xmm7[2],xmm13[2],xmm7[3],xmm13[3] +; SSE4-NEXT: paddq %xmm9, %xmm7 +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm2 = xmm6[0],zero,xmm6[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm6 = xmm6[2],xmm13[2],xmm6[3],xmm13[3] +; SSE4-NEXT: paddq %xmm10, %xmm6 +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm1 = xmm5[0],zero,xmm5[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm5 = xmm5[2],xmm13[2],xmm5[3],xmm13[3] +; SSE4-NEXT: paddq %xmm11, %xmm5 +; SSE4-NEXT: pmovzxdq {{.*#+}} xmm0 = xmm4[0],zero,xmm4[1],zero +; SSE4-NEXT: punpckhdq {{.*#+}} xmm4 = xmm4[2],xmm13[2],xmm4[3],xmm13[3] +; SSE4-NEXT: paddq %xmm8, %xmm4 +; SSE4-NEXT: paddq {{[-0-9]+}}(%r{{[sb]}}p), %xmm3 # 16-byte Folded Reload +; SSE4-NEXT: paddq %xmm14, %xmm2 +; SSE4-NEXT: paddq %xmm15, %xmm1 +; SSE4-NEXT: paddq %xmm12, %xmm0 +; SSE4-NEXT: psrlq $1, %xmm7 +; SSE4-NEXT: psrlq $1, %xmm6 +; SSE4-NEXT: psrlq $1, %xmm5 +; SSE4-NEXT: psrlq $1, %xmm4 +; SSE4-NEXT: psrlq $1, %xmm3 +; SSE4-NEXT: shufps {{.*#+}} xmm3 = xmm3[0,2],xmm7[0,2] +; SSE4-NEXT: psrlq $1, %xmm2 +; SSE4-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,2],xmm6[0,2] +; SSE4-NEXT: psrlq $1, %xmm1 +; SSE4-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,2],xmm5[0,2] +; SSE4-NEXT: psrlq $1, %xmm0 +; SSE4-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,2],xmm4[0,2] +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v16i32: +; AVX1: # %bb.0: +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm4 +; AVX1-NEXT: vpxor %xmm5, %xmm5, %xmm5 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm6 = xmm4[2],xmm5[2],xmm4[3],xmm5[3] +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm7 = xmm1[2],xmm5[2],xmm1[3],xmm5[3] +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm8 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm9 = xmm8[2],xmm5[2],xmm8[3],xmm5[3] +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm10 = xmm0[2],xmm5[2],xmm0[3],xmm5[3] +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm4 = xmm4[0],zero,xmm4[1],zero +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm1 = xmm1[0],zero,xmm1[1],zero +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm8 = xmm8[0],zero,xmm8[1],zero +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm11 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm12 = xmm11[2],xmm5[2],xmm11[3],xmm5[3] +; AVX1-NEXT: vpaddq %xmm6, %xmm12, %xmm6 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm12 = xmm3[2],xmm5[2],xmm3[3],xmm5[3] +; AVX1-NEXT: vpaddq %xmm7, %xmm12, %xmm7 +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm12 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm13 = xmm12[2],xmm5[2],xmm12[3],xmm5[3] +; AVX1-NEXT: vpaddq %xmm13, %xmm9, %xmm9 +; AVX1-NEXT: vpunpckhdq {{.*#+}} xmm5 = xmm2[2],xmm5[2],xmm2[3],xmm5[3] +; AVX1-NEXT: vpaddq %xmm5, %xmm10, %xmm5 +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm10 = xmm11[0],zero,xmm11[1],zero +; AVX1-NEXT: vpaddq %xmm4, %xmm10, %xmm4 +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm3 = xmm3[0],zero,xmm3[1],zero +; AVX1-NEXT: vpaddq %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm3 = xmm12[0],zero,xmm12[1],zero +; AVX1-NEXT: vpaddq %xmm3, %xmm8, %xmm3 +; AVX1-NEXT: vpmovzxdq {{.*#+}} xmm2 = xmm2[0],zero,xmm2[1],zero +; AVX1-NEXT: vpaddq %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlq $1, %xmm6, %xmm2 +; AVX1-NEXT: vpsrlq $1, %xmm7, %xmm6 +; AVX1-NEXT: vpsrlq $1, %xmm9, %xmm7 +; AVX1-NEXT: vpsrlq $1, %xmm5, %xmm5 +; AVX1-NEXT: vpsrlq $1, %xmm4, %xmm4 +; AVX1-NEXT: vpsrlq $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm3, %xmm3 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm7, %ymm5, %ymm5 +; AVX1-NEXT: vinsertf128 $1, %xmm3, %ymm0, %ymm0 +; AVX1-NEXT: vshufps {{.*#+}} ymm0 = ymm0[0,2],ymm5[0,2],ymm0[4,6],ymm5[4,6] +; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm6, %ymm2 +; AVX1-NEXT: vinsertf128 $1, %xmm4, %ymm1, %ymm1 +; AVX1-NEXT: vshufps {{.*#+}} ymm1 = ymm1[0,2],ymm2[0,2],ymm1[4,6],ymm2[4,6] +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v16i32: +; AVX2: # %bb.0: +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm4 +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm4 = xmm4[0],zero,xmm4[1],zero,xmm4[2],zero,xmm4[3],zero +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm5 +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm5 = xmm5[0],zero,xmm5[1],zero,xmm5[2],zero,xmm5[3],zero +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero +; AVX2-NEXT: vextracti128 $1, %ymm3, %xmm6 +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm6 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero +; AVX2-NEXT: vpaddq %ymm6, %ymm4, %ymm4 +; AVX2-NEXT: vextracti128 $1, %ymm2, %xmm6 +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm6 = xmm6[0],zero,xmm6[1],zero,xmm6[2],zero,xmm6[3],zero +; AVX2-NEXT: vpaddq %ymm6, %ymm5, %ymm5 +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm2 = xmm2[0],zero,xmm2[1],zero,xmm2[2],zero,xmm2[3],zero +; AVX2-NEXT: vpaddq %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpmovzxdq {{.*#+}} ymm2 = xmm3[0],zero,xmm3[1],zero,xmm3[2],zero,xmm3[3],zero +; AVX2-NEXT: vpaddq %ymm2, %ymm1, %ymm1 +; AVX2-NEXT: vperm2i128 {{.*#+}} ymm2 = ymm0[2,3],ymm5[2,3] +; AVX2-NEXT: vpsrlq $1, %ymm2, %ymm2 +; AVX2-NEXT: vinserti128 $1, %xmm5, %ymm0, %ymm0 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vshufps {{.*#+}} ymm0 = ymm0[0,2],ymm2[0,2],ymm0[4,6],ymm2[4,6] +; AVX2-NEXT: vperm2i128 {{.*#+}} ymm2 = ymm1[2,3],ymm4[2,3] +; AVX2-NEXT: vpsrlq $1, %ymm2, %ymm2 +; AVX2-NEXT: vinserti128 $1, %xmm4, %ymm1, %ymm1 +; AVX2-NEXT: vpsrlq $1, %ymm1, %ymm1 +; AVX2-NEXT: vshufps {{.*#+}} ymm1 = ymm1[0,2],ymm2[0,2],ymm1[4,6],ymm2[4,6] +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v16i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vextracti64x4 $1, %zmm0, %ymm2 +; AVX512-NEXT: vpmovzxdq {{.*#+}} zmm2 = ymm2[0],zero,ymm2[1],zero,ymm2[2],zero,ymm2[3],zero,ymm2[4],zero,ymm2[5],zero,ymm2[6],zero,ymm2[7],zero +; AVX512-NEXT: vpmovzxdq {{.*#+}} zmm0 = ymm0[0],zero,ymm0[1],zero,ymm0[2],zero,ymm0[3],zero,ymm0[4],zero,ymm0[5],zero,ymm0[6],zero,ymm0[7],zero +; AVX512-NEXT: vextracti64x4 $1, %zmm1, %ymm3 +; AVX512-NEXT: vpmovzxdq {{.*#+}} zmm3 = ymm3[0],zero,ymm3[1],zero,ymm3[2],zero,ymm3[3],zero,ymm3[4],zero,ymm3[5],zero,ymm3[6],zero,ymm3[7],zero +; AVX512-NEXT: vpaddq %zmm3, %zmm2, %zmm2 +; AVX512-NEXT: vpmovzxdq {{.*#+}} zmm1 = ymm1[0],zero,ymm1[1],zero,ymm1[2],zero,ymm1[3],zero,ymm1[4],zero,ymm1[5],zero,ymm1[6],zero,ymm1[7],zero +; AVX512-NEXT: vpaddq %zmm1, %zmm0, %zmm0 +; AVX512-NEXT: vpsrlq $1, %zmm2, %zmm1 +; AVX512-NEXT: vpsrlq $1, %zmm0, %zmm0 +; AVX512-NEXT: vpmovqd %zmm0, %ymm0 +; AVX512-NEXT: vpmovqd %zmm1, %ymm1 +; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm0, %zmm0 +; AVX512-NEXT: retq + %x0 = zext <16 x i32> %a0 to <16 x i64> + %x1 = zext <16 x i32> %a1 to <16 x i64> + %sum = add <16 x i64> %x0, %x1 + %shift = lshr <16 x i64> %sum, <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1> + %res = trunc <16 x i64> %shift to <16 x i32> + ret <16 x i32> %res +} + +define <8 x i64> @test_fixed_v8i64(<8 x i64> %a0, <8 x i64> %a1) { +; SSE-LABEL: test_fixed_v8i64: +; SSE: # %bb.0: +; SSE-NEXT: movdqa %xmm3, %xmm8 +; SSE-NEXT: pand %xmm7, %xmm8 +; SSE-NEXT: movdqa %xmm2, %xmm9 +; SSE-NEXT: pand %xmm6, %xmm9 +; SSE-NEXT: movdqa %xmm1, %xmm10 +; SSE-NEXT: pand %xmm5, %xmm10 +; SSE-NEXT: movdqa %xmm0, %xmm11 +; SSE-NEXT: pand %xmm4, %xmm11 +; SSE-NEXT: pxor %xmm4, %xmm0 +; SSE-NEXT: pxor %xmm5, %xmm1 +; SSE-NEXT: pxor %xmm6, %xmm2 +; SSE-NEXT: pxor %xmm7, %xmm3 +; SSE-NEXT: psrlq $1, %xmm3 +; SSE-NEXT: paddq %xmm8, %xmm3 +; SSE-NEXT: psrlq $1, %xmm2 +; SSE-NEXT: paddq %xmm9, %xmm2 +; SSE-NEXT: psrlq $1, %xmm1 +; SSE-NEXT: paddq %xmm10, %xmm1 +; SSE-NEXT: psrlq $1, %xmm0 +; SSE-NEXT: paddq %xmm11, %xmm0 +; SSE-NEXT: retq +; +; AVX1-LABEL: test_fixed_v8i64: +; AVX1: # %bb.0: +; AVX1-NEXT: vandps %ymm3, %ymm1, %ymm4 +; AVX1-NEXT: vandps %ymm2, %ymm0, %ymm5 +; AVX1-NEXT: vxorps %ymm0, %ymm2, %ymm0 +; AVX1-NEXT: vxorps %ymm1, %ymm3, %ymm1 +; AVX1-NEXT: vpsrlq $1, %xmm1, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm1, %xmm1 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm3 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrlq $1, %xmm0, %xmm0 +; AVX1-NEXT: vextractf128 $1, %ymm5, %xmm6 +; AVX1-NEXT: vpaddq %xmm0, %xmm6, %xmm0 +; AVX1-NEXT: vpaddq %xmm3, %xmm5, %xmm3 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm3, %ymm0 +; AVX1-NEXT: vextractf128 $1, %ymm4, %xmm3 +; AVX1-NEXT: vpaddq %xmm1, %xmm3, %xmm1 +; AVX1-NEXT: vpaddq %xmm2, %xmm4, %xmm2 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_fixed_v8i64: +; AVX2: # %bb.0: +; AVX2-NEXT: vpand %ymm3, %ymm1, %ymm4 +; AVX2-NEXT: vpand %ymm2, %ymm0, %ymm5 +; AVX2-NEXT: vpxor %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: vpxor %ymm1, %ymm3, %ymm1 +; AVX2-NEXT: vpsrlq $1, %ymm1, %ymm1 +; AVX2-NEXT: vpaddq %ymm1, %ymm4, %ymm1 +; AVX2-NEXT: vpsrlq $1, %ymm0, %ymm0 +; AVX2-NEXT: vpaddq %ymm0, %ymm5, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_fixed_v8i64: +; AVX512: # %bb.0: +; AVX512-NEXT: vpandq %zmm1, %zmm0, %zmm2 +; AVX512-NEXT: vpxorq %zmm0, %zmm1, %zmm0 +; AVX512-NEXT: vpsrlq $1, %zmm0, %zmm0 +; AVX512-NEXT: vpaddq %zmm0, %zmm2, %zmm0 +; AVX512-NEXT: retq + %and = and <8 x i64> %a0, %a1 + %xor = xor <8 x i64> %a1, %a0 + %shift = lshr <8 x i64> %xor, <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1> + %res = add <8 x i64> %and, %shift + ret <8 x i64> %res +} + +define <8 x i64> @test_ext_v8i64(<8 x i64> %a0, <8 x i64> %a1) { +; SSE2-LABEL: test_ext_v8i64: +; SSE2: # %bb.0: +; SSE2-NEXT: pushq %rbp +; SSE2-NEXT: .cfi_def_cfa_offset 16 +; SSE2-NEXT: pushq %r15 +; SSE2-NEXT: .cfi_def_cfa_offset 24 +; SSE2-NEXT: pushq %r14 +; SSE2-NEXT: .cfi_def_cfa_offset 32 +; SSE2-NEXT: pushq %r13 +; SSE2-NEXT: .cfi_def_cfa_offset 40 +; SSE2-NEXT: pushq %r12 +; SSE2-NEXT: .cfi_def_cfa_offset 48 +; SSE2-NEXT: pushq %rbx +; SSE2-NEXT: .cfi_def_cfa_offset 56 +; SSE2-NEXT: .cfi_offset %rbx, -56 +; SSE2-NEXT: .cfi_offset %r12, -48 +; SSE2-NEXT: .cfi_offset %r13, -40 +; SSE2-NEXT: .cfi_offset %r14, -32 +; SSE2-NEXT: .cfi_offset %r15, -24 +; SSE2-NEXT: .cfi_offset %rbp, -16 +; SSE2-NEXT: pshufd {{.*#+}} xmm8 = xmm3[2,3,2,3] +; SSE2-NEXT: movq %xmm3, %rbx +; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm2[2,3,2,3] +; SSE2-NEXT: movq %xmm3, %r12 +; SSE2-NEXT: movq %xmm2, %rbp +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] +; SSE2-NEXT: movq %xmm2, %r13 +; SSE2-NEXT: movq %xmm1, %r15 +; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] +; SSE2-NEXT: movq %xmm1, %r14 +; SSE2-NEXT: movq %xmm0, %r11 +; SSE2-NEXT: movq %xmm7, %r10 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm6[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %r9 +; SSE2-NEXT: movq %xmm6, %r8 +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm5[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %rdi +; SSE2-NEXT: movq %xmm5, %rsi +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm4[2,3,2,3] +; SSE2-NEXT: movq %xmm0, %rdx +; SSE2-NEXT: movq %xmm4, %rax +; SSE2-NEXT: xorl %ecx, %ecx +; SSE2-NEXT: addq %r11, %rax +; SSE2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: setb %cl +; SSE2-NEXT: xorl %r11d, %r11d +; SSE2-NEXT: addq %r14, %rdx +; SSE2-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE2-NEXT: setb %r11b +; SSE2-NEXT: xorl %r14d, %r14d +; SSE2-NEXT: addq %r15, %rsi +; SSE2-NEXT: setb %r14b +; SSE2-NEXT: xorl %r15d, %r15d +; SSE2-NEXT: addq %r13, %rdi +; SSE2-NEXT: setb %r15b +; SSE2-NEXT: xorl %r13d, %r13d +; SSE2-NEXT: addq %rbp, %r8 +; SSE2-NEXT: setb %r13b +; SSE2-NEXT: xorl %ebp, %ebp +; SSE2-NEXT: addq %r12, %r9 +; SSE2-NEXT: setb %bpl +; SSE2-NEXT: xorl %r12d, %r12d +; SSE2-NEXT: addq %rbx, %r10 +; SSE2-NEXT: movq %xmm8, %rdx +; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm7[2,3,2,3] +; SSE2-NEXT: setb %r12b +; SSE2-NEXT: movq %xmm0, %rax +; SSE2-NEXT: xorl %ebx, %ebx +; SSE2-NEXT: addq %rdx, %rax +; SSE2-NEXT: setb %bl +; SSE2-NEXT: shldq $63, %rax, %rbx +; SSE2-NEXT: shldq $63, %r10, %r12 +; SSE2-NEXT: shldq $63, %r9, %rbp +; SSE2-NEXT: shldq $63, %r8, %r13 +; SSE2-NEXT: shldq $63, %rdi, %r15 +; SSE2-NEXT: shldq $63, %rsi, %r14 +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; SSE2-NEXT: shldq $63, %rax, %r11 +; SSE2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; SSE2-NEXT: shldq $63, %rax, %rcx +; SSE2-NEXT: movq %rcx, %xmm0 +; SSE2-NEXT: movq %r11, %xmm4 +; SSE2-NEXT: movq %r14, %xmm1 +; SSE2-NEXT: movq %r15, %xmm5 +; SSE2-NEXT: movq %r13, %xmm2 +; SSE2-NEXT: movq %rbp, %xmm6 +; SSE2-NEXT: movq %r12, %xmm3 +; SSE2-NEXT: movq %rbx, %xmm7 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm4[0] +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm5[0] +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm6[0] +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm3 = xmm3[0],xmm7[0] +; SSE2-NEXT: popq %rbx +; SSE2-NEXT: .cfi_def_cfa_offset 48 +; SSE2-NEXT: popq %r12 +; SSE2-NEXT: .cfi_def_cfa_offset 40 +; SSE2-NEXT: popq %r13 +; SSE2-NEXT: .cfi_def_cfa_offset 32 +; SSE2-NEXT: popq %r14 +; SSE2-NEXT: .cfi_def_cfa_offset 24 +; SSE2-NEXT: popq %r15 +; SSE2-NEXT: .cfi_def_cfa_offset 16 +; SSE2-NEXT: popq %rbp +; SSE2-NEXT: .cfi_def_cfa_offset 8 +; SSE2-NEXT: retq +; +; SSE4-LABEL: test_ext_v8i64: +; SSE4: # %bb.0: +; SSE4-NEXT: pushq %rbp +; SSE4-NEXT: .cfi_def_cfa_offset 16 +; SSE4-NEXT: pushq %r15 +; SSE4-NEXT: .cfi_def_cfa_offset 24 +; SSE4-NEXT: pushq %r14 +; SSE4-NEXT: .cfi_def_cfa_offset 32 +; SSE4-NEXT: pushq %r13 +; SSE4-NEXT: .cfi_def_cfa_offset 40 +; SSE4-NEXT: pushq %r12 +; SSE4-NEXT: .cfi_def_cfa_offset 48 +; SSE4-NEXT: pushq %rbx +; SSE4-NEXT: .cfi_def_cfa_offset 56 +; SSE4-NEXT: .cfi_offset %rbx, -56 +; SSE4-NEXT: .cfi_offset %r12, -48 +; SSE4-NEXT: .cfi_offset %r13, -40 +; SSE4-NEXT: .cfi_offset %r14, -32 +; SSE4-NEXT: .cfi_offset %r15, -24 +; SSE4-NEXT: .cfi_offset %rbp, -16 +; SSE4-NEXT: pextrq $1, %xmm3, %r14 +; SSE4-NEXT: movq %xmm2, %r13 +; SSE4-NEXT: pextrq $1, %xmm2, %rbp +; SSE4-NEXT: movq %xmm1, %r12 +; SSE4-NEXT: pextrq $1, %xmm1, %r15 +; SSE4-NEXT: movq %xmm0, %rbx +; SSE4-NEXT: pextrq $1, %xmm0, %r11 +; SSE4-NEXT: pextrq $1, %xmm7, %r10 +; SSE4-NEXT: movq %xmm6, %r9 +; SSE4-NEXT: pextrq $1, %xmm6, %r8 +; SSE4-NEXT: movq %xmm5, %rdi +; SSE4-NEXT: pextrq $1, %xmm5, %rsi +; SSE4-NEXT: movq %xmm4, %rdx +; SSE4-NEXT: pextrq $1, %xmm4, %rax +; SSE4-NEXT: xorl %ecx, %ecx +; SSE4-NEXT: addq %r11, %rax +; SSE4-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: setb %cl +; SSE4-NEXT: xorl %r11d, %r11d +; SSE4-NEXT: addq %rbx, %rdx +; SSE4-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; SSE4-NEXT: setb %r11b +; SSE4-NEXT: xorl %ebx, %ebx +; SSE4-NEXT: addq %r15, %rsi +; SSE4-NEXT: setb %bl +; SSE4-NEXT: xorl %r15d, %r15d +; SSE4-NEXT: addq %r12, %rdi +; SSE4-NEXT: setb %r15b +; SSE4-NEXT: xorl %r12d, %r12d +; SSE4-NEXT: addq %rbp, %r8 +; SSE4-NEXT: setb %r12b +; SSE4-NEXT: xorl %ebp, %ebp +; SSE4-NEXT: addq %r13, %r9 +; SSE4-NEXT: setb %bpl +; SSE4-NEXT: xorl %r13d, %r13d +; SSE4-NEXT: addq %r14, %r10 +; SSE4-NEXT: movq %xmm3, %rdx +; SSE4-NEXT: setb %r13b +; SSE4-NEXT: movq %xmm7, %rax +; SSE4-NEXT: xorl %r14d, %r14d +; SSE4-NEXT: addq %rdx, %rax +; SSE4-NEXT: setb %r14b +; SSE4-NEXT: shldq $63, %rax, %r14 +; SSE4-NEXT: shldq $63, %r10, %r13 +; SSE4-NEXT: shldq $63, %r9, %rbp +; SSE4-NEXT: shldq $63, %r8, %r12 +; SSE4-NEXT: shldq $63, %rdi, %r15 +; SSE4-NEXT: shldq $63, %rsi, %rbx +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; SSE4-NEXT: shldq $63, %rax, %r11 +; SSE4-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; SSE4-NEXT: shldq $63, %rax, %rcx +; SSE4-NEXT: movq %rcx, %xmm4 +; SSE4-NEXT: movq %r11, %xmm0 +; SSE4-NEXT: movq %rbx, %xmm5 +; SSE4-NEXT: movq %r15, %xmm1 +; SSE4-NEXT: movq %r12, %xmm6 +; SSE4-NEXT: movq %rbp, %xmm2 +; SSE4-NEXT: movq %r13, %xmm7 +; SSE4-NEXT: movq %r14, %xmm3 +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm4[0] +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm5[0] +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm2 = xmm2[0],xmm6[0] +; SSE4-NEXT: punpcklqdq {{.*#+}} xmm3 = xmm3[0],xmm7[0] +; SSE4-NEXT: popq %rbx +; SSE4-NEXT: .cfi_def_cfa_offset 48 +; SSE4-NEXT: popq %r12 +; SSE4-NEXT: .cfi_def_cfa_offset 40 +; SSE4-NEXT: popq %r13 +; SSE4-NEXT: .cfi_def_cfa_offset 32 +; SSE4-NEXT: popq %r14 +; SSE4-NEXT: .cfi_def_cfa_offset 24 +; SSE4-NEXT: popq %r15 +; SSE4-NEXT: .cfi_def_cfa_offset 16 +; SSE4-NEXT: popq %rbp +; SSE4-NEXT: .cfi_def_cfa_offset 8 +; SSE4-NEXT: retq +; +; AVX1-LABEL: test_ext_v8i64: +; AVX1: # %bb.0: +; AVX1-NEXT: pushq %rbp +; AVX1-NEXT: .cfi_def_cfa_offset 16 +; AVX1-NEXT: pushq %r15 +; AVX1-NEXT: .cfi_def_cfa_offset 24 +; AVX1-NEXT: pushq %r14 +; AVX1-NEXT: .cfi_def_cfa_offset 32 +; AVX1-NEXT: pushq %r13 +; AVX1-NEXT: .cfi_def_cfa_offset 40 +; AVX1-NEXT: pushq %r12 +; AVX1-NEXT: .cfi_def_cfa_offset 48 +; AVX1-NEXT: pushq %rbx +; AVX1-NEXT: .cfi_def_cfa_offset 56 +; AVX1-NEXT: .cfi_offset %rbx, -56 +; AVX1-NEXT: .cfi_offset %r12, -48 +; AVX1-NEXT: .cfi_offset %r13, -40 +; AVX1-NEXT: .cfi_offset %r14, -32 +; AVX1-NEXT: .cfi_offset %r15, -24 +; AVX1-NEXT: .cfi_offset %rbp, -16 +; AVX1-NEXT: vpextrq $1, %xmm1, %rbx +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm4 +; AVX1-NEXT: vmovq %xmm4, %r15 +; AVX1-NEXT: vpextrq $1, %xmm4, %rbp +; AVX1-NEXT: vmovq %xmm0, %r13 +; AVX1-NEXT: vpextrq $1, %xmm0, %r12 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vmovq %xmm0, %r14 +; AVX1-NEXT: vpextrq $1, %xmm0, %r11 +; AVX1-NEXT: vpextrq $1, %xmm3, %r10 +; AVX1-NEXT: vextractf128 $1, %ymm3, %xmm0 +; AVX1-NEXT: vmovq %xmm0, %r9 +; AVX1-NEXT: vpextrq $1, %xmm0, %r8 +; AVX1-NEXT: vmovq %xmm2, %rdi +; AVX1-NEXT: vpextrq $1, %xmm2, %rsi +; AVX1-NEXT: vextractf128 $1, %ymm2, %xmm0 +; AVX1-NEXT: vmovq %xmm0, %rdx +; AVX1-NEXT: vpextrq $1, %xmm0, %rax +; AVX1-NEXT: xorl %ecx, %ecx +; AVX1-NEXT: addq %r11, %rax +; AVX1-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: setb %cl +; AVX1-NEXT: xorl %r11d, %r11d +; AVX1-NEXT: addq %r14, %rdx +; AVX1-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX1-NEXT: setb %r11b +; AVX1-NEXT: xorl %r14d, %r14d +; AVX1-NEXT: addq %r12, %rsi +; AVX1-NEXT: setb %r14b +; AVX1-NEXT: xorl %r12d, %r12d +; AVX1-NEXT: addq %r13, %rdi +; AVX1-NEXT: setb %r12b +; AVX1-NEXT: xorl %r13d, %r13d +; AVX1-NEXT: addq %rbp, %r8 +; AVX1-NEXT: setb %r13b +; AVX1-NEXT: xorl %ebp, %ebp +; AVX1-NEXT: addq %r15, %r9 +; AVX1-NEXT: setb %bpl +; AVX1-NEXT: xorl %r15d, %r15d +; AVX1-NEXT: addq %rbx, %r10 +; AVX1-NEXT: vmovq %xmm1, %rdx +; AVX1-NEXT: setb %r15b +; AVX1-NEXT: vmovq %xmm3, %rax +; AVX1-NEXT: xorl %ebx, %ebx +; AVX1-NEXT: addq %rdx, %rax +; AVX1-NEXT: setb %bl +; AVX1-NEXT: shldq $63, %rax, %rbx +; AVX1-NEXT: shldq $63, %r10, %r15 +; AVX1-NEXT: shldq $63, %r9, %rbp +; AVX1-NEXT: shldq $63, %r8, %r13 +; AVX1-NEXT: shldq $63, %rdi, %r12 +; AVX1-NEXT: shldq $63, %rsi, %r14 +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; AVX1-NEXT: shldq $63, %rax, %r11 +; AVX1-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; AVX1-NEXT: shldq $63, %rax, %rcx +; AVX1-NEXT: vmovq %rcx, %xmm0 +; AVX1-NEXT: vmovq %r11, %xmm1 +; AVX1-NEXT: vmovq %r14, %xmm2 +; AVX1-NEXT: vmovq %r12, %xmm3 +; AVX1-NEXT: vmovq %r13, %xmm4 +; AVX1-NEXT: vmovq %rbp, %xmm5 +; AVX1-NEXT: vmovq %r15, %xmm6 +; AVX1-NEXT: vmovq %rbx, %xmm7 +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm3[0],xmm2[0] +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0 +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm5[0],xmm4[0] +; AVX1-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm7[0],xmm6[0] +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm2, %ymm1 +; AVX1-NEXT: popq %rbx +; AVX1-NEXT: .cfi_def_cfa_offset 48 +; AVX1-NEXT: popq %r12 +; AVX1-NEXT: .cfi_def_cfa_offset 40 +; AVX1-NEXT: popq %r13 +; AVX1-NEXT: .cfi_def_cfa_offset 32 +; AVX1-NEXT: popq %r14 +; AVX1-NEXT: .cfi_def_cfa_offset 24 +; AVX1-NEXT: popq %r15 +; AVX1-NEXT: .cfi_def_cfa_offset 16 +; AVX1-NEXT: popq %rbp +; AVX1-NEXT: .cfi_def_cfa_offset 8 +; AVX1-NEXT: retq +; +; AVX2-LABEL: test_ext_v8i64: +; AVX2: # %bb.0: +; AVX2-NEXT: pushq %rbp +; AVX2-NEXT: .cfi_def_cfa_offset 16 +; AVX2-NEXT: pushq %r15 +; AVX2-NEXT: .cfi_def_cfa_offset 24 +; AVX2-NEXT: pushq %r14 +; AVX2-NEXT: .cfi_def_cfa_offset 32 +; AVX2-NEXT: pushq %r13 +; AVX2-NEXT: .cfi_def_cfa_offset 40 +; AVX2-NEXT: pushq %r12 +; AVX2-NEXT: .cfi_def_cfa_offset 48 +; AVX2-NEXT: pushq %rbx +; AVX2-NEXT: .cfi_def_cfa_offset 56 +; AVX2-NEXT: .cfi_offset %rbx, -56 +; AVX2-NEXT: .cfi_offset %r12, -48 +; AVX2-NEXT: .cfi_offset %r13, -40 +; AVX2-NEXT: .cfi_offset %r14, -32 +; AVX2-NEXT: .cfi_offset %r15, -24 +; AVX2-NEXT: .cfi_offset %rbp, -16 +; AVX2-NEXT: vpextrq $1, %xmm1, %rbx +; AVX2-NEXT: vextracti128 $1, %ymm1, %xmm4 +; AVX2-NEXT: vmovq %xmm4, %r15 +; AVX2-NEXT: vpextrq $1, %xmm4, %rbp +; AVX2-NEXT: vmovq %xmm0, %r13 +; AVX2-NEXT: vpextrq $1, %xmm0, %r12 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm0 +; AVX2-NEXT: vmovq %xmm0, %r14 +; AVX2-NEXT: vpextrq $1, %xmm0, %r11 +; AVX2-NEXT: vpextrq $1, %xmm3, %r10 +; AVX2-NEXT: vextracti128 $1, %ymm3, %xmm0 +; AVX2-NEXT: vmovq %xmm0, %r9 +; AVX2-NEXT: vpextrq $1, %xmm0, %r8 +; AVX2-NEXT: vmovq %xmm2, %rdi +; AVX2-NEXT: vpextrq $1, %xmm2, %rsi +; AVX2-NEXT: vextracti128 $1, %ymm2, %xmm0 +; AVX2-NEXT: vmovq %xmm0, %rdx +; AVX2-NEXT: vpextrq $1, %xmm0, %rax +; AVX2-NEXT: xorl %ecx, %ecx +; AVX2-NEXT: addq %r11, %rax +; AVX2-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: setb %cl +; AVX2-NEXT: xorl %r11d, %r11d +; AVX2-NEXT: addq %r14, %rdx +; AVX2-NEXT: movq %rdx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX2-NEXT: setb %r11b +; AVX2-NEXT: xorl %r14d, %r14d +; AVX2-NEXT: addq %r12, %rsi +; AVX2-NEXT: setb %r14b +; AVX2-NEXT: xorl %r12d, %r12d +; AVX2-NEXT: addq %r13, %rdi +; AVX2-NEXT: setb %r12b +; AVX2-NEXT: xorl %r13d, %r13d +; AVX2-NEXT: addq %rbp, %r8 +; AVX2-NEXT: setb %r13b +; AVX2-NEXT: xorl %ebp, %ebp +; AVX2-NEXT: addq %r15, %r9 +; AVX2-NEXT: setb %bpl +; AVX2-NEXT: xorl %r15d, %r15d +; AVX2-NEXT: addq %rbx, %r10 +; AVX2-NEXT: vmovq %xmm1, %rdx +; AVX2-NEXT: setb %r15b +; AVX2-NEXT: vmovq %xmm3, %rax +; AVX2-NEXT: xorl %ebx, %ebx +; AVX2-NEXT: addq %rdx, %rax +; AVX2-NEXT: setb %bl +; AVX2-NEXT: shldq $63, %rax, %rbx +; AVX2-NEXT: shldq $63, %r10, %r15 +; AVX2-NEXT: shldq $63, %r9, %rbp +; AVX2-NEXT: shldq $63, %r8, %r13 +; AVX2-NEXT: shldq $63, %rdi, %r12 +; AVX2-NEXT: shldq $63, %rsi, %r14 +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; AVX2-NEXT: shldq $63, %rax, %r11 +; AVX2-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; AVX2-NEXT: shldq $63, %rax, %rcx +; AVX2-NEXT: vmovq %rcx, %xmm0 +; AVX2-NEXT: vmovq %r11, %xmm1 +; AVX2-NEXT: vmovq %r14, %xmm2 +; AVX2-NEXT: vmovq %r12, %xmm3 +; AVX2-NEXT: vmovq %r13, %xmm4 +; AVX2-NEXT: vmovq %rbp, %xmm5 +; AVX2-NEXT: vmovq %r15, %xmm6 +; AVX2-NEXT: vmovq %rbx, %xmm7 +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm3[0],xmm2[0] +; AVX2-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0 +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm5[0],xmm4[0] +; AVX2-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm7[0],xmm6[0] +; AVX2-NEXT: vinserti128 $1, %xmm1, %ymm2, %ymm1 +; AVX2-NEXT: popq %rbx +; AVX2-NEXT: .cfi_def_cfa_offset 48 +; AVX2-NEXT: popq %r12 +; AVX2-NEXT: .cfi_def_cfa_offset 40 +; AVX2-NEXT: popq %r13 +; AVX2-NEXT: .cfi_def_cfa_offset 32 +; AVX2-NEXT: popq %r14 +; AVX2-NEXT: .cfi_def_cfa_offset 24 +; AVX2-NEXT: popq %r15 +; AVX2-NEXT: .cfi_def_cfa_offset 16 +; AVX2-NEXT: popq %rbp +; AVX2-NEXT: .cfi_def_cfa_offset 8 +; AVX2-NEXT: retq +; +; AVX512-LABEL: test_ext_v8i64: +; AVX512: # %bb.0: +; AVX512-NEXT: pushq %rbp +; AVX512-NEXT: .cfi_def_cfa_offset 16 +; AVX512-NEXT: pushq %r15 +; AVX512-NEXT: .cfi_def_cfa_offset 24 +; AVX512-NEXT: pushq %r14 +; AVX512-NEXT: .cfi_def_cfa_offset 32 +; AVX512-NEXT: pushq %r13 +; AVX512-NEXT: .cfi_def_cfa_offset 40 +; AVX512-NEXT: pushq %r12 +; AVX512-NEXT: .cfi_def_cfa_offset 48 +; AVX512-NEXT: pushq %rbx +; AVX512-NEXT: .cfi_def_cfa_offset 56 +; AVX512-NEXT: .cfi_offset %rbx, -56 +; AVX512-NEXT: .cfi_offset %r12, -48 +; AVX512-NEXT: .cfi_offset %r13, -40 +; AVX512-NEXT: .cfi_offset %r14, -32 +; AVX512-NEXT: .cfi_offset %r15, -24 +; AVX512-NEXT: .cfi_offset %rbp, -16 +; AVX512-NEXT: vpextrq $1, %xmm0, %r10 +; AVX512-NEXT: vextracti128 $1, %ymm0, %xmm2 +; AVX512-NEXT: vpextrq $1, %xmm2, %r13 +; AVX512-NEXT: vmovq %xmm2, %r15 +; AVX512-NEXT: vextracti64x4 $1, %zmm0, %ymm2 +; AVX512-NEXT: vmovq %xmm2, %rbp +; AVX512-NEXT: vpextrq $1, %xmm2, %r12 +; AVX512-NEXT: vextracti128 $1, %ymm2, %xmm2 +; AVX512-NEXT: vmovq %xmm2, %r14 +; AVX512-NEXT: vpextrq $1, %xmm2, %rbx +; AVX512-NEXT: vpextrq $1, %xmm1, %r9 +; AVX512-NEXT: vextracti128 $1, %ymm1, %xmm2 +; AVX512-NEXT: vmovq %xmm2, %r8 +; AVX512-NEXT: vpextrq $1, %xmm2, %rdx +; AVX512-NEXT: vextracti64x4 $1, %zmm1, %ymm2 +; AVX512-NEXT: vpextrq $1, %xmm2, %rcx +; AVX512-NEXT: vmovq %xmm2, %r11 +; AVX512-NEXT: vextracti128 $1, %ymm2, %xmm2 +; AVX512-NEXT: vmovq %xmm2, %rdi +; AVX512-NEXT: vpextrq $1, %xmm2, %rax +; AVX512-NEXT: xorl %esi, %esi +; AVX512-NEXT: addq %rbx, %rax +; AVX512-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: setb %sil +; AVX512-NEXT: xorl %ebx, %ebx +; AVX512-NEXT: addq %r14, %rdi +; AVX512-NEXT: setb %bl +; AVX512-NEXT: xorl %r14d, %r14d +; AVX512-NEXT: addq %r12, %rcx +; AVX512-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill +; AVX512-NEXT: setb %r14b +; AVX512-NEXT: xorl %r12d, %r12d +; AVX512-NEXT: addq %rbp, %r11 +; AVX512-NEXT: setb %r12b +; AVX512-NEXT: xorl %ebp, %ebp +; AVX512-NEXT: addq %r13, %rdx +; AVX512-NEXT: setb %bpl +; AVX512-NEXT: xorl %r13d, %r13d +; AVX512-NEXT: addq %r15, %r8 +; AVX512-NEXT: setb %r13b +; AVX512-NEXT: xorl %r15d, %r15d +; AVX512-NEXT: addq %r10, %r9 +; AVX512-NEXT: vmovq %xmm0, %rcx +; AVX512-NEXT: setb %r15b +; AVX512-NEXT: vmovq %xmm1, %rax +; AVX512-NEXT: xorl %r10d, %r10d +; AVX512-NEXT: addq %rcx, %rax +; AVX512-NEXT: setb %r10b +; AVX512-NEXT: shldq $63, %rax, %r10 +; AVX512-NEXT: shldq $63, %r9, %r15 +; AVX512-NEXT: shldq $63, %r8, %r13 +; AVX512-NEXT: shldq $63, %rdx, %rbp +; AVX512-NEXT: shldq $63, %r11, %r12 +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; AVX512-NEXT: shldq $63, %rax, %r14 +; AVX512-NEXT: shldq $63, %rdi, %rbx +; AVX512-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload +; AVX512-NEXT: shldq $63, %rax, %rsi +; AVX512-NEXT: vmovq %rsi, %xmm0 +; AVX512-NEXT: vmovq %rbx, %xmm1 +; AVX512-NEXT: vmovq %r14, %xmm2 +; AVX512-NEXT: vmovq %r12, %xmm3 +; AVX512-NEXT: vmovq %rbp, %xmm4 +; AVX512-NEXT: vmovq %r13, %xmm5 +; AVX512-NEXT: vmovq %r15, %xmm6 +; AVX512-NEXT: vmovq %r10, %xmm7 +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm0 = xmm1[0],xmm0[0] +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm3[0],xmm2[0] +; AVX512-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0 +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm1 = xmm5[0],xmm4[0] +; AVX512-NEXT: vpunpcklqdq {{.*#+}} xmm2 = xmm7[0],xmm6[0] +; AVX512-NEXT: vinserti128 $1, %xmm1, %ymm2, %ymm1 +; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-NEXT: popq %rbx +; AVX512-NEXT: .cfi_def_cfa_offset 48 +; AVX512-NEXT: popq %r12 +; AVX512-NEXT: .cfi_def_cfa_offset 40 +; AVX512-NEXT: popq %r13 +; AVX512-NEXT: .cfi_def_cfa_offset 32 +; AVX512-NEXT: popq %r14 +; AVX512-NEXT: .cfi_def_cfa_offset 24 +; AVX512-NEXT: popq %r15 +; AVX512-NEXT: .cfi_def_cfa_offset 16 +; AVX512-NEXT: popq %rbp +; AVX512-NEXT: .cfi_def_cfa_offset 8 +; AVX512-NEXT: retq + %x0 = zext <8 x i64> %a0 to <8 x i128> + %x1 = zext <8 x i64> %a1 to <8 x i128> + %sum = add <8 x i128> %x0, %x1 + %shift = lshr <8 x i128> %sum, <i128 1, i128 1, i128 1, i128 1, i128 1, i128 1, i128 1, i128 1> + %res = trunc <8 x i128> %shift to <8 x i64> + ret <8 x i64> %res +} + diff --git a/llvm/test/CodeGen/X86/bitcast-and-setcc-256.ll b/llvm/test/CodeGen/X86/bitcast-and-setcc-256.ll index 34ef23db345755b92e54f370afdce5c7dbbce8c8..234c7a0a500d30394b7cf74585c9c169765f80e2 100644 --- a/llvm/test/CodeGen/X86/bitcast-and-setcc-256.ll +++ b/llvm/test/CodeGen/X86/bitcast-and-setcc-256.ll @@ -553,8 +553,8 @@ define i8 @v8i32_or_select(<8 x i32> %a0, <8 x i32> %a1, <8 x i32> %a2, <8 x i32 ; AVX1-NEXT: vpcmpeqd %xmm5, %xmm4, %xmm4 ; AVX1-NEXT: vpcmpeqd %xmm1, %xmm0, %xmm0 ; AVX1-NEXT: vinsertf128 $1, %xmm4, %ymm0, %ymm0 -; AVX1-NEXT: vorps %ymm2, %ymm3, %ymm1 -; AVX1-NEXT: vorps %ymm0, %ymm1, %ymm0 +; AVX1-NEXT: vorps %ymm0, %ymm3, %ymm0 +; AVX1-NEXT: vorps %ymm2, %ymm0, %ymm0 ; AVX1-NEXT: vmovmskps %ymm0, %eax ; AVX1-NEXT: # kill: def $al killed $al killed $eax ; AVX1-NEXT: vzeroupper @@ -571,8 +571,8 @@ define i8 @v8i32_or_select(<8 x i32> %a0, <8 x i32> %a1, <8 x i32> %a2, <8 x i32 ; AVX2-NEXT: vpcmpeqd %ymm2, %ymm0, %ymm2 ; AVX2-NEXT: .LBB7_3: ; AVX2-NEXT: vpcmpeqd %ymm1, %ymm0, %ymm0 -; AVX2-NEXT: vpor %ymm2, %ymm3, %ymm1 -; AVX2-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX2-NEXT: vpor %ymm0, %ymm3, %ymm0 +; AVX2-NEXT: vpor %ymm2, %ymm0, %ymm0 ; AVX2-NEXT: vmovmskps %ymm0, %eax ; AVX2-NEXT: # kill: def $al killed $al killed $eax ; AVX2-NEXT: vzeroupper diff --git a/llvm/test/CodeGen/X86/callbr-asm-kill.mir b/llvm/test/CodeGen/X86/callbr-asm-kill.mir index 86c58c4715ed77f5129c763ad7bfaad14f62c522..0dded37c97afa6ae26dff19b38a7e900b4fb04bd 100644 --- a/llvm/test/CodeGen/X86/callbr-asm-kill.mir +++ b/llvm/test/CodeGen/X86/callbr-asm-kill.mir @@ -45,6 +45,7 @@ liveins: - { reg: '$rsi', virtual-reg: '%3' } frameInfo: maxAlignment: 1 + adjustsStack: true hasCalls: true machineFunctionInfo: {} body: | diff --git a/llvm/test/CodeGen/X86/cmov.ll b/llvm/test/CodeGen/X86/cmov.ll index 374e75967d52fc36c0f5bfafec080636a557ed35..a8c068fc5b86501feba5dc17d73bebe0d50a9b2b 100644 --- a/llvm/test/CodeGen/X86/cmov.ll +++ b/llvm/test/CodeGen/X86/cmov.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -verify-machineinstrs -mtriple=x86_64-unknown-unknown -disable-cgp-select2branch -x86-cmov-converter=false | FileCheck %s +; RUN: llc < %s -verify-machineinstrs -mtriple=x86_64-unknown-unknown -disable-cgp-select2branch -x86-cmov-converter=false -mattr=+ndd --show-mc-encoding | FileCheck %s --check-prefix=NDD target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" define i32 @test1(i32 %x, i32 %n, i32 %w, ptr %vp) nounwind readnone { @@ -9,6 +10,13 @@ define i32 @test1(i32 %x, i32 %n, i32 %w, ptr %vp) nounwind readnone { ; CHECK-NEXT: movl $12, %eax ; CHECK-NEXT: cmovael (%rcx), %eax ; CHECK-NEXT: retq +; +; NDD-LABEL: test1: +; NDD: # %bb.0: # %entry +; NDD-NEXT: btl %esi, %edi # encoding: [0x0f,0xa3,0xf7] +; NDD-NEXT: movl $12, %eax # encoding: [0xb8,0x0c,0x00,0x00,0x00] +; NDD-NEXT: cmovael (%rcx), %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x43,0x01] +; NDD-NEXT: retq # encoding: [0xc3] entry: %0 = lshr i32 %x, %n %1 = and i32 %0, 1 @@ -25,6 +33,13 @@ define i32 @test2(i32 %x, i32 %n, i32 %w, ptr %vp) nounwind readnone { ; CHECK-NEXT: movl $12, %eax ; CHECK-NEXT: cmovbl (%rcx), %eax ; CHECK-NEXT: retq +; +; NDD-LABEL: test2: +; NDD: # %bb.0: # %entry +; NDD-NEXT: btl %esi, %edi # encoding: [0x0f,0xa3,0xf7] +; NDD-NEXT: movl $12, %eax # encoding: [0xb8,0x0c,0x00,0x00,0x00] +; NDD-NEXT: cmovbl (%rcx), %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x42,0x01] +; NDD-NEXT: retq # encoding: [0xc3] entry: %0 = lshr i32 %x, %n %1 = and i32 %0, 1 @@ -50,6 +65,16 @@ define void @test3(i64 %a, i64 %b, i1 %p) nounwind { ; CHECK-NEXT: callq bar@PLT ; CHECK-NEXT: popq %rax ; CHECK-NEXT: retq +; +; NDD-LABEL: test3: +; NDD: # %bb.0: +; NDD-NEXT: pushq %rax # encoding: [0x50] +; NDD-NEXT: testb $1, %dl # encoding: [0xf6,0xc2,0x01] +; NDD-NEXT: cmovel %esi, %edi # EVEX TO LEGACY Compression encoding: [0x0f,0x44,0xfe] +; NDD-NEXT: callq bar@PLT # encoding: [0xe8,A,A,A,A] +; NDD-NEXT: # fixup A - offset: 1, value: bar@PLT-4, kind: FK_PCRel_4 +; NDD-NEXT: popq %rax # encoding: [0x58] +; NDD-NEXT: retq # encoding: [0xc3] %c = trunc i64 %a to i32 %d = trunc i64 %b to i32 %e = select i1 %p, i32 %c, i32 %d @@ -114,6 +139,54 @@ define i1 @test4() nounwind { ; CHECK-NEXT: movl %ebx, %eax ; CHECK-NEXT: popq %rbx ; CHECK-NEXT: retq +; +; NDD-LABEL: test4: +; NDD: # %bb.0: # %entry +; NDD-NEXT: movsbl g_3(%rip), %eax # encoding: [0x0f,0xbe,0x05,A,A,A,A] +; NDD-NEXT: # fixup A - offset: 3, value: g_3-4, kind: reloc_riprel_4byte +; NDD-NEXT: movzbl %al, %ecx # encoding: [0x0f,0xb6,0xc8] +; NDD-NEXT: shrl $7, %ecx # EVEX TO LEGACY Compression encoding: [0xc1,0xe9,0x07] +; NDD-NEXT: xorb $1, %cl # EVEX TO LEGACY Compression encoding: [0x80,0xf1,0x01] +; NDD-NEXT: sarl %cl, %eax, %ecx # encoding: [0x62,0xf4,0x74,0x18,0xd3,0xf8] +; NDD-NEXT: movzbl g_96(%rip), %eax # encoding: [0x0f,0xb6,0x05,A,A,A,A] +; NDD-NEXT: # fixup A - offset: 3, value: g_96-4, kind: reloc_riprel_4byte +; NDD-NEXT: testb %al, %al # encoding: [0x84,0xc0] +; NDD-NEXT: je .LBB3_2 # encoding: [0x74,A] +; NDD-NEXT: # fixup A - offset: 1, value: .LBB3_2-1, kind: FK_PCRel_1 +; NDD-NEXT: # %bb.1: # %bb.i.i.i +; NDD-NEXT: movzbl g_100(%rip), %edx # encoding: [0x0f,0xb6,0x15,A,A,A,A] +; NDD-NEXT: # fixup A - offset: 3, value: g_100-4, kind: reloc_riprel_4byte +; NDD-NEXT: .LBB3_2: # %func_4.exit.i +; NDD-NEXT: pushq %rbx # encoding: [0x53] +; NDD-NEXT: xorl %edx, %edx # encoding: [0x31,0xd2] +; NDD-NEXT: testb %cl, %cl # encoding: [0x84,0xc9] +; NDD-NEXT: setne %bl # encoding: [0x0f,0x95,0xc3] +; NDD-NEXT: movzbl %al, %ecx # encoding: [0x0f,0xb6,0xc8] +; NDD-NEXT: cmovnel %edx, %ecx # EVEX TO LEGACY Compression encoding: [0x0f,0x45,0xca] +; NDD-NEXT: testb %al, %al # encoding: [0x84,0xc0] +; NDD-NEXT: je .LBB3_5 # encoding: [0x74,A] +; NDD-NEXT: # fixup A - offset: 1, value: .LBB3_5-1, kind: FK_PCRel_1 +; NDD-NEXT: # %bb.3: # %func_4.exit.i +; NDD-NEXT: testb %bl, %bl # encoding: [0x84,0xdb] +; NDD-NEXT: jne .LBB3_5 # encoding: [0x75,A] +; NDD-NEXT: # fixup A - offset: 1, value: .LBB3_5-1, kind: FK_PCRel_1 +; NDD-NEXT: # %bb.4: # %bb.i.i +; NDD-NEXT: movzbl g_100(%rip), %ecx # encoding: [0x0f,0xb6,0x0d,A,A,A,A] +; NDD-NEXT: # fixup A - offset: 3, value: g_100-4, kind: reloc_riprel_4byte +; NDD-NEXT: xorl %ebx, %ebx # encoding: [0x31,0xdb] +; NDD-NEXT: movl %eax, %ecx # encoding: [0x89,0xc1] +; NDD-NEXT: .LBB3_5: # %func_1.exit +; NDD-NEXT: movb %cl, g_96(%rip) # encoding: [0x88,0x0d,A,A,A,A] +; NDD-NEXT: # fixup A - offset: 2, value: g_96-4, kind: reloc_riprel_4byte +; NDD-NEXT: movzbl %cl, %esi # encoding: [0x0f,0xb6,0xf1] +; NDD-NEXT: movl $_2E_str, %edi # encoding: [0xbf,A,A,A,A] +; NDD-NEXT: # fixup A - offset: 1, value: _2E_str, kind: FK_Data_4 +; NDD-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] +; NDD-NEXT: callq printf@PLT # encoding: [0xe8,A,A,A,A] +; NDD-NEXT: # fixup A - offset: 1, value: printf@PLT-4, kind: FK_PCRel_4 +; NDD-NEXT: movl %ebx, %eax # encoding: [0x89,0xd8] +; NDD-NEXT: popq %rbx # encoding: [0x5b] +; NDD-NEXT: retq # encoding: [0xc3] entry: %0 = load i8, ptr @g_3, align 1 %1 = sext i8 %0 to i32 @@ -163,6 +236,14 @@ define i32 @test5(ptr nocapture %P) nounwind readonly { ; CHECK-NEXT: setge %al ; CHECK-NEXT: orl $-2, %eax ; CHECK-NEXT: retq +; +; NDD-LABEL: test5: +; NDD: # %bb.0: # %entry +; NDD-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] +; NDD-NEXT: cmpl $42, (%rdi) # encoding: [0x83,0x3f,0x2a] +; NDD-NEXT: setge %al # encoding: [0x0f,0x9d,0xc0] +; NDD-NEXT: orl $-2, %eax # EVEX TO LEGACY Compression encoding: [0x83,0xc8,0xfe] +; NDD-NEXT: retq # encoding: [0xc3] entry: %0 = load i32, ptr %P, align 4 %1 = icmp sgt i32 %0, 41 @@ -178,6 +259,14 @@ define i32 @test6(ptr nocapture %P) nounwind readonly { ; CHECK-NEXT: setl %al ; CHECK-NEXT: leal 4(%rax,%rax,8), %eax ; CHECK-NEXT: retq +; +; NDD-LABEL: test6: +; NDD: # %bb.0: # %entry +; NDD-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] +; NDD-NEXT: cmpl $42, (%rdi) # encoding: [0x83,0x3f,0x2a] +; NDD-NEXT: setl %al # encoding: [0x0f,0x9c,0xc0] +; NDD-NEXT: leal 4(%rax,%rax,8), %eax # encoding: [0x8d,0x44,0xc0,0x04] +; NDD-NEXT: retq # encoding: [0xc3] entry: %0 = load i32, ptr %P, align 4 %1 = icmp sgt i32 %0, 41 @@ -194,6 +283,13 @@ define i8 @test7(i1 inreg %c, i8 inreg %a, i8 inreg %b) nounwind { ; CHECK-NEXT: cmovel %edx, %eax ; CHECK-NEXT: # kill: def $al killed $al killed $eax ; CHECK-NEXT: retq +; +; NDD-LABEL: test7: +; NDD: # %bb.0: +; NDD-NEXT: testb $1, %dil # encoding: [0x40,0xf6,0xc7,0x01] +; NDD-NEXT: cmovnel %esi, %edx, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x45,0xd6] +; NDD-NEXT: # kill: def $al killed $al killed $eax +; NDD-NEXT: retq # encoding: [0xc3] %d = select i1 %c, i8 %a, i8 %b ret i8 %d } @@ -205,6 +301,13 @@ define i64 @test8(i64 %0, i64 %1, i64 %2) { ; CHECK-NEXT: cmpq $-2147483648, %rdi # imm = 0x80000000 ; CHECK-NEXT: cmovlq %rdx, %rax ; CHECK-NEXT: retq +; +; NDD-LABEL: test8: +; NDD: # %bb.0: +; NDD-NEXT: cmpq $-2147483648, %rdi # encoding: [0x48,0x81,0xff,0x00,0x00,0x00,0x80] +; NDD-NEXT: # imm = 0x80000000 +; NDD-NEXT: cmovgeq %rsi, %rdx, %rax # encoding: [0x62,0xf4,0xfc,0x18,0x4d,0xd6] +; NDD-NEXT: retq # encoding: [0xc3] %4 = icmp sgt i64 %0, -2147483649 %5 = select i1 %4, i64 %1, i64 %2 ret i64 %5 @@ -218,6 +321,14 @@ define i32 @smin(i32 %x) { ; CHECK-NEXT: movl $-1, %eax ; CHECK-NEXT: cmovnsl %edi, %eax ; CHECK-NEXT: retq +; +; NDD-LABEL: smin: +; NDD: # %bb.0: +; NDD-NEXT: notl %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0xf7,0xd7] +; NDD-NEXT: testl %edi, %edi # encoding: [0x85,0xff] +; NDD-NEXT: movl $-1, %ecx # encoding: [0xb9,0xff,0xff,0xff,0xff] +; NDD-NEXT: cmovsl %ecx, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x48,0xc1] +; NDD-NEXT: retq # encoding: [0xc3] %not_x = xor i32 %x, -1 %1 = icmp slt i32 %not_x, -1 %sel = select i1 %1, i32 %not_x, i32 -1 @@ -231,6 +342,13 @@ define i32 @pr47049_1(i32 %0) { ; CHECK-NEXT: movl $1, %eax ; CHECK-NEXT: cmovlel %edi, %eax ; CHECK-NEXT: retq +; +; NDD-LABEL: pr47049_1: +; NDD: # %bb.0: +; NDD-NEXT: testl %edi, %edi # encoding: [0x85,0xff] +; NDD-NEXT: movl $1, %eax # encoding: [0xb8,0x01,0x00,0x00,0x00] +; NDD-NEXT: cmovlel %edi, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x4e,0xc7] +; NDD-NEXT: retq # encoding: [0xc3] %2 = icmp slt i32 %0, 1 %3 = select i1 %2, i32 %0, i32 1 ret i32 %3 @@ -243,6 +361,13 @@ define i32 @pr47049_2(i32 %0) { ; CHECK-NEXT: movl $-1, %eax ; CHECK-NEXT: cmovnsl %edi, %eax ; CHECK-NEXT: retq +; +; NDD-LABEL: pr47049_2: +; NDD: # %bb.0: +; NDD-NEXT: testl %edi, %edi # encoding: [0x85,0xff] +; NDD-NEXT: movl $-1, %eax # encoding: [0xb8,0xff,0xff,0xff,0xff] +; NDD-NEXT: cmovnsl %edi, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x49,0xc7] +; NDD-NEXT: retq # encoding: [0xc3] %2 = icmp sgt i32 %0, -1 %3 = select i1 %2, i32 %0, i32 -1 ret i32 %3 @@ -255,6 +380,13 @@ define i32 @pr47049_3(i32 %0) { ; CHECK-NEXT: movl $1, %eax ; CHECK-NEXT: cmovgl %edi, %eax ; CHECK-NEXT: retq +; +; NDD-LABEL: pr47049_3: +; NDD: # %bb.0: +; NDD-NEXT: testl %edi, %edi # encoding: [0x85,0xff] +; NDD-NEXT: movl $1, %eax # encoding: [0xb8,0x01,0x00,0x00,0x00] +; NDD-NEXT: cmovgl %edi, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x4f,0xc7] +; NDD-NEXT: retq # encoding: [0xc3] %2 = icmp sgt i32 %0, 1 %3 = select i1 %2, i32 %0, i32 1 ret i32 %3 @@ -267,6 +399,13 @@ define i32 @pr47049_4(i32 %0) { ; CHECK-NEXT: movl $1, %eax ; CHECK-NEXT: cmovnel %edi, %eax ; CHECK-NEXT: retq +; +; NDD-LABEL: pr47049_4: +; NDD: # %bb.0: +; NDD-NEXT: testl %edi, %edi # encoding: [0x85,0xff] +; NDD-NEXT: movl $1, %eax # encoding: [0xb8,0x01,0x00,0x00,0x00] +; NDD-NEXT: cmovnel %edi, %eax # EVEX TO LEGACY Compression encoding: [0x0f,0x45,0xc7] +; NDD-NEXT: retq # encoding: [0xc3] %2 = icmp ugt i32 %0, 1 %3 = select i1 %2, i32 %0, i32 1 ret i32 %3 diff --git a/llvm/test/CodeGen/X86/cmp.ll b/llvm/test/CodeGen/X86/cmp.ll index cd1953bec774d9a1d6fb7d1a4d945ab7025ad554..30e52f063075991466be5b0fd09c5a0fb69b7c54 100644 --- a/llvm/test/CodeGen/X86/cmp.ll +++ b/llvm/test/CodeGen/X86/cmp.ll @@ -416,9 +416,8 @@ define i32 @test13(i32 %mask, i32 %base, i32 %intra) { ; ; NDD-LABEL: test13: ; NDD: # %bb.0: -; NDD-NEXT: movl %esi, %eax # encoding: [0x89,0xf0] ; NDD-NEXT: testb $8, %dil # encoding: [0x40,0xf6,0xc7,0x08] -; NDD-NEXT: cmovnel %edx, %eax # encoding: [0x0f,0x45,0xc2] +; NDD-NEXT: cmovnel %edx, %esi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x45,0xf2] ; NDD-NEXT: retq # encoding: [0xc3] %and = and i32 %mask, 8 %tobool = icmp ne i32 %and, 0 @@ -436,9 +435,8 @@ define i32 @test14(i32 %mask, i32 %base, i32 %intra) { ; ; NDD-LABEL: test14: ; NDD: # %bb.0: -; NDD-NEXT: movl %esi, %eax # encoding: [0x89,0xf0] -; NDD-NEXT: shrl $7, %edi, %ecx # encoding: [0x62,0xf4,0x74,0x18,0xc1,0xef,0x07] -; NDD-NEXT: cmovnsl %edx, %eax # encoding: [0x0f,0x49,0xc2] +; NDD-NEXT: shrl $7, %edi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0xc1,0xef,0x07] +; NDD-NEXT: cmovnsl %edx, %esi, %eax # encoding: [0x62,0xf4,0x7c,0x18,0x49,0xf2] ; NDD-NEXT: retq # encoding: [0xc3] %s = lshr i32 %mask, 7 %tobool = icmp sgt i32 %s, -1 @@ -1100,9 +1098,8 @@ define { i64, i64 } @pr39968(i64, i64, i32) { ; NDD: # %bb.0: ; NDD-NEXT: xorl %eax, %eax # encoding: [0x31,0xc0] ; NDD-NEXT: testb $64, %dl # encoding: [0xf6,0xc2,0x40] -; NDD-NEXT: cmovneq %rdi, %rsi # encoding: [0x48,0x0f,0x45,0xf7] -; NDD-NEXT: cmovneq %rdi, %rax # encoding: [0x48,0x0f,0x45,0xc7] -; NDD-NEXT: movq %rsi, %rdx # encoding: [0x48,0x89,0xf2] +; NDD-NEXT: cmovneq %rdi, %rsi, %rdx # encoding: [0x62,0xf4,0xec,0x18,0x45,0xf7] +; NDD-NEXT: cmovneq %rdi, %rax # EVEX TO LEGACY Compression encoding: [0x48,0x0f,0x45,0xc7] ; NDD-NEXT: retq # encoding: [0xc3] %4 = and i32 %2, 64 %5 = icmp ne i32 %4, 0 diff --git a/llvm/test/CodeGen/X86/combine-pavg.ll b/llvm/test/CodeGen/X86/combine-pavg.ll index 0743592f3ca11bf42a81bc980170d3949b2b0158..7a8ddf5178d3d823b0cd1e4aa7a67d79277be3f1 100644 --- a/llvm/test/CodeGen/X86/combine-pavg.ll +++ b/llvm/test/CodeGen/X86/combine-pavg.ll @@ -18,6 +18,22 @@ define <16 x i8> @combine_pavgb_self(<16 x i8> %a0) { ret <16 x i8> %1 } +define <16 x i8> @combine_pavgb_zero(<16 x i8> %a0) { +; SSE-LABEL: combine_pavgb_zero: +; SSE: # %bb.0: +; SSE-NEXT: pxor %xmm1, %xmm1 +; SSE-NEXT: pavgb %xmm1, %xmm0 +; SSE-NEXT: retq +; +; AVX-LABEL: combine_pavgb_zero: +; AVX: # %bb.0: +; AVX-NEXT: vpxor %xmm1, %xmm1, %xmm1 +; AVX-NEXT: vpavgb %xmm1, %xmm0, %xmm0 +; AVX-NEXT: retq + %1 = call <16 x i8> @llvm.x86.sse2.pavg.b(<16 x i8> zeroinitializer, <16 x i8> %a0) + ret <16 x i8> %1 +} + define <16 x i8> @combine_pavgw_knownbits(<8 x i16> %a0, <8 x i16> %a1, <8 x i16> %a2, <8 x i16> %a3) { ; SSE-LABEL: combine_pavgw_knownbits: ; SSE: # %bb.0: @@ -64,3 +80,33 @@ define <16 x i8> @combine_pavgw_knownbits(<8 x i16> %a0, <8 x i16> %a1, <8 x i16 %trunc = trunc <16 x i16> %shuffle to <16 x i8> ret <16 x i8> %trunc } + +define <8 x i16> @combine_pavgw_demandedelts(<8 x i16> %a0, <8 x i16> %a1) { +; SSE-LABEL: combine_pavgw_demandedelts: +; SSE: # %bb.0: +; SSE-NEXT: pshuflw {{.*#+}} xmm1 = xmm1[0,0,0,0,4,5,6,7] +; SSE-NEXT: pshufb {{.*#+}} xmm0 = xmm0[0,1,0,1,0,1,0,1,8,9,8,9,12,13,12,13] +; SSE-NEXT: pavgw %xmm1, %xmm0 +; SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm0[0,0,0,0] +; SSE-NEXT: retq +; +; AVX1-LABEL: combine_pavgw_demandedelts: +; AVX1: # %bb.0: +; AVX1-NEXT: vpshuflw {{.*#+}} xmm1 = xmm1[0,0,0,0,4,5,6,7] +; AVX1-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[0,1,0,1,0,1,0,1,8,9,8,9,12,13,12,13] +; AVX1-NEXT: vpavgw %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[0,0,0,0] +; AVX1-NEXT: retq +; +; AVX2-LABEL: combine_pavgw_demandedelts: +; AVX2: # %bb.0: +; AVX2-NEXT: vpbroadcastw %xmm1, %xmm1 +; AVX2-NEXT: vpbroadcastw %xmm0, %xmm0 +; AVX2-NEXT: vpavgw %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: retq + %s0 = shufflevector <8 x i16> %a0, <8 x i16> poison, <8 x i32> <i32 0, i32 0, i32 2, i32 2, i32 4, i32 4, i32 6, i32 6> + %avg = tail call <8 x i16> @llvm.x86.sse2.pavg.w(<8 x i16> %s0, <8 x i16> %a1) + %shuffle = shufflevector <8 x i16> %avg, <8 x i16> poison, <8 x i32> zeroinitializer + ret <8 x i16> %shuffle +} + diff --git a/llvm/test/CodeGen/X86/combine-sra.ll b/llvm/test/CodeGen/X86/combine-sra.ll index 0675ced68d7a7a41ef505d765bc008aef997942c..7eee418742ddb5696a767a0cc45a3509958c0bfa 100644 --- a/llvm/test/CodeGen/X86/combine-sra.ll +++ b/llvm/test/CodeGen/X86/combine-sra.ll @@ -521,3 +521,276 @@ define <4 x i32> @combine_vec_ashr_positive_splat(<4 x i32> %x, <4 x i32> %y) { %2 = ashr <4 x i32> %1, <i32 10, i32 10, i32 10, i32 10> ret <4 x i32> %2 } + +define <8 x i16> @combine_vec8i16_ashr_clamped(<8 x i16> %x, <8 x i16> %y) { +; SSE2-LABEL: combine_vec8i16_ashr_clamped: +; SSE2: # %bb.0: +; SSE2-NEXT: movdqa %xmm1, %xmm2 +; SSE2-NEXT: psubusw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2 +; SSE2-NEXT: psubw %xmm2, %xmm1 +; SSE2-NEXT: psllw $12, %xmm1 +; SSE2-NEXT: movdqa %xmm1, %xmm2 +; SSE2-NEXT: psraw $15, %xmm2 +; SSE2-NEXT: movdqa %xmm2, %xmm3 +; SSE2-NEXT: pandn %xmm0, %xmm3 +; SSE2-NEXT: psraw $8, %xmm0 +; SSE2-NEXT: pand %xmm2, %xmm0 +; SSE2-NEXT: por %xmm3, %xmm0 +; SSE2-NEXT: paddw %xmm1, %xmm1 +; SSE2-NEXT: movdqa %xmm1, %xmm2 +; SSE2-NEXT: psraw $15, %xmm2 +; SSE2-NEXT: movdqa %xmm2, %xmm3 +; SSE2-NEXT: pandn %xmm0, %xmm3 +; SSE2-NEXT: psraw $4, %xmm0 +; SSE2-NEXT: pand %xmm2, %xmm0 +; SSE2-NEXT: por %xmm3, %xmm0 +; SSE2-NEXT: paddw %xmm1, %xmm1 +; SSE2-NEXT: movdqa %xmm1, %xmm2 +; SSE2-NEXT: psraw $15, %xmm2 +; SSE2-NEXT: movdqa %xmm2, %xmm3 +; SSE2-NEXT: pandn %xmm0, %xmm3 +; SSE2-NEXT: psraw $2, %xmm0 +; SSE2-NEXT: pand %xmm2, %xmm0 +; SSE2-NEXT: por %xmm3, %xmm0 +; SSE2-NEXT: paddw %xmm1, %xmm1 +; SSE2-NEXT: psraw $15, %xmm1 +; SSE2-NEXT: movdqa %xmm1, %xmm2 +; SSE2-NEXT: pandn %xmm0, %xmm2 +; SSE2-NEXT: psraw $1, %xmm0 +; SSE2-NEXT: pand %xmm1, %xmm0 +; SSE2-NEXT: por %xmm2, %xmm0 +; SSE2-NEXT: retq +; +; SSE41-LABEL: combine_vec8i16_ashr_clamped: +; SSE41: # %bb.0: +; SSE41-NEXT: movdqa %xmm0, %xmm2 +; SSE41-NEXT: pminuw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 +; SSE41-NEXT: movdqa %xmm1, %xmm0 +; SSE41-NEXT: psllw $12, %xmm0 +; SSE41-NEXT: psllw $4, %xmm1 +; SSE41-NEXT: por %xmm1, %xmm0 +; SSE41-NEXT: movdqa %xmm0, %xmm1 +; SSE41-NEXT: paddw %xmm0, %xmm1 +; SSE41-NEXT: movdqa %xmm2, %xmm3 +; SSE41-NEXT: psraw $8, %xmm3 +; SSE41-NEXT: pblendvb %xmm0, %xmm3, %xmm2 +; SSE41-NEXT: movdqa %xmm2, %xmm3 +; SSE41-NEXT: psraw $4, %xmm3 +; SSE41-NEXT: movdqa %xmm1, %xmm0 +; SSE41-NEXT: pblendvb %xmm0, %xmm3, %xmm2 +; SSE41-NEXT: movdqa %xmm2, %xmm3 +; SSE41-NEXT: psraw $2, %xmm3 +; SSE41-NEXT: paddw %xmm1, %xmm1 +; SSE41-NEXT: movdqa %xmm1, %xmm0 +; SSE41-NEXT: pblendvb %xmm0, %xmm3, %xmm2 +; SSE41-NEXT: movdqa %xmm2, %xmm3 +; SSE41-NEXT: psraw $1, %xmm3 +; SSE41-NEXT: paddw %xmm1, %xmm1 +; SSE41-NEXT: movdqa %xmm1, %xmm0 +; SSE41-NEXT: pblendvb %xmm0, %xmm3, %xmm2 +; SSE41-NEXT: movdqa %xmm2, %xmm0 +; SSE41-NEXT: retq +; +; AVX2-LABEL: combine_vec8i16_ashr_clamped: +; AVX2: # %bb.0: +; AVX2-NEXT: vpminuw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1 +; AVX2-NEXT: vpmovsxwd %xmm0, %ymm0 +; AVX2-NEXT: vpmovzxwd {{.*#+}} ymm1 = xmm1[0],zero,xmm1[1],zero,xmm1[2],zero,xmm1[3],zero,xmm1[4],zero,xmm1[5],zero,xmm1[6],zero,xmm1[7],zero +; AVX2-NEXT: vpsravd %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vextracti128 $1, %ymm0, %xmm1 +; AVX2-NEXT: vpackssdw %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512-LABEL: combine_vec8i16_ashr_clamped: +; AVX512: # %bb.0: +; AVX512-NEXT: vpsravw %xmm1, %xmm0, %xmm0 +; AVX512-NEXT: retq + %1 = tail call <8 x i16> @llvm.umin.v8i16(<8 x i16> %y, <8 x i16> <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15>) + %2 = ashr <8 x i16> %x, %1 + ret <8 x i16> %2 +} + +define <4 x i32> @combine_vec4i32_ashr_clamped(<4 x i32> %x, <4 x i32> %y) { +; SSE2-LABEL: combine_vec4i32_ashr_clamped: +; SSE2: # %bb.0: +; SSE2-NEXT: movdqa {{.*#+}} xmm2 = [2147483648,2147483648,2147483648,2147483648] +; SSE2-NEXT: pxor %xmm1, %xmm2 +; SSE2-NEXT: pcmpgtd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2 +; SSE2-NEXT: movdqa %xmm2, %xmm3 +; SSE2-NEXT: pandn %xmm1, %xmm3 +; SSE2-NEXT: psrld $27, %xmm2 +; SSE2-NEXT: por %xmm3, %xmm2 +; SSE2-NEXT: pshuflw {{.*#+}} xmm1 = xmm2[2,3,3,3,4,5,6,7] +; SSE2-NEXT: movdqa %xmm0, %xmm3 +; SSE2-NEXT: psrad %xmm1, %xmm3 +; SSE2-NEXT: pshuflw {{.*#+}} xmm4 = xmm2[0,1,1,1,4,5,6,7] +; SSE2-NEXT: movdqa %xmm0, %xmm1 +; SSE2-NEXT: psrad %xmm4, %xmm1 +; SSE2-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm3[0] +; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm2[2,3,2,3] +; SSE2-NEXT: pshuflw {{.*#+}} xmm3 = xmm2[2,3,3,3,4,5,6,7] +; SSE2-NEXT: movdqa %xmm0, %xmm4 +; SSE2-NEXT: psrad %xmm3, %xmm4 +; SSE2-NEXT: pshuflw {{.*#+}} xmm2 = xmm2[0,1,1,1,4,5,6,7] +; SSE2-NEXT: psrad %xmm2, %xmm0 +; SSE2-NEXT: punpckhqdq {{.*#+}} xmm0 = xmm0[1],xmm4[1] +; SSE2-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,3],xmm0[0,3] +; SSE2-NEXT: movaps %xmm1, %xmm0 +; SSE2-NEXT: retq +; +; SSE41-LABEL: combine_vec4i32_ashr_clamped: +; SSE41: # %bb.0: +; SSE41-NEXT: pminud {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 +; SSE41-NEXT: pshuflw {{.*#+}} xmm2 = xmm1[2,3,3,3,4,5,6,7] +; SSE41-NEXT: movdqa %xmm0, %xmm3 +; SSE41-NEXT: psrad %xmm2, %xmm3 +; SSE41-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] +; SSE41-NEXT: pshuflw {{.*#+}} xmm4 = xmm2[2,3,3,3,4,5,6,7] +; SSE41-NEXT: movdqa %xmm0, %xmm5 +; SSE41-NEXT: psrad %xmm4, %xmm5 +; SSE41-NEXT: pblendw {{.*#+}} xmm5 = xmm3[0,1,2,3],xmm5[4,5,6,7] +; SSE41-NEXT: pshuflw {{.*#+}} xmm1 = xmm1[0,1,1,1,4,5,6,7] +; SSE41-NEXT: movdqa %xmm0, %xmm3 +; SSE41-NEXT: psrad %xmm1, %xmm3 +; SSE41-NEXT: pshuflw {{.*#+}} xmm1 = xmm2[0,1,1,1,4,5,6,7] +; SSE41-NEXT: psrad %xmm1, %xmm0 +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm3[0,1,2,3],xmm0[4,5,6,7] +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm5[2,3],xmm0[4,5],xmm5[6,7] +; SSE41-NEXT: retq +; +; AVX-LABEL: combine_vec4i32_ashr_clamped: +; AVX: # %bb.0: +; AVX-NEXT: vpsravd %xmm1, %xmm0, %xmm0 +; AVX-NEXT: retq + %1 = tail call <4 x i32> @llvm.umin.v4i32(<4 x i32> %y, <4 x i32> <i32 31, i32 31, i32 31, i32 31>) + %2 = ashr <4 x i32> %x, %1 + ret <4 x i32> %2 +} + +define <4 x i64> @combine_vec4i64_ashr_clamped(<4 x i64> %x, <4 x i64> %y) { +; SSE2-LABEL: combine_vec4i64_ashr_clamped: +; SSE2: # %bb.0: +; SSE2-NEXT: movdqa {{.*#+}} xmm5 = [9223372039002259456,9223372039002259456] +; SSE2-NEXT: movdqa %xmm3, %xmm4 +; SSE2-NEXT: pxor %xmm5, %xmm4 +; SSE2-NEXT: pshufd {{.*#+}} xmm6 = xmm4[0,0,2,2] +; SSE2-NEXT: movdqa {{.*#+}} xmm7 = [2147483711,2147483711,2147483711,2147483711] +; SSE2-NEXT: movdqa %xmm7, %xmm8 +; SSE2-NEXT: pcmpgtd %xmm6, %xmm8 +; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm4[1,1,3,3] +; SSE2-NEXT: pcmpeqd %xmm5, %xmm4 +; SSE2-NEXT: pand %xmm8, %xmm4 +; SSE2-NEXT: movdqa {{.*#+}} xmm6 = [63,63] +; SSE2-NEXT: pand %xmm4, %xmm3 +; SSE2-NEXT: pandn %xmm6, %xmm4 +; SSE2-NEXT: por %xmm3, %xmm4 +; SSE2-NEXT: movdqa %xmm2, %xmm3 +; SSE2-NEXT: pxor %xmm5, %xmm3 +; SSE2-NEXT: pshufd {{.*#+}} xmm8 = xmm3[0,0,2,2] +; SSE2-NEXT: pcmpgtd %xmm8, %xmm7 +; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm3[1,1,3,3] +; SSE2-NEXT: pcmpeqd %xmm5, %xmm3 +; SSE2-NEXT: pand %xmm7, %xmm3 +; SSE2-NEXT: pand %xmm3, %xmm2 +; SSE2-NEXT: pandn %xmm6, %xmm3 +; SSE2-NEXT: por %xmm2, %xmm3 +; SSE2-NEXT: movdqa {{.*#+}} xmm2 = [9223372036854775808,9223372036854775808] +; SSE2-NEXT: movdqa %xmm2, %xmm5 +; SSE2-NEXT: psrlq %xmm3, %xmm5 +; SSE2-NEXT: pshufd {{.*#+}} xmm6 = xmm3[2,3,2,3] +; SSE2-NEXT: movdqa %xmm2, %xmm7 +; SSE2-NEXT: psrlq %xmm6, %xmm7 +; SSE2-NEXT: movsd {{.*#+}} xmm7 = xmm5[0],xmm7[1] +; SSE2-NEXT: movdqa %xmm0, %xmm5 +; SSE2-NEXT: psrlq %xmm3, %xmm5 +; SSE2-NEXT: psrlq %xmm6, %xmm0 +; SSE2-NEXT: movsd {{.*#+}} xmm0 = xmm5[0],xmm0[1] +; SSE2-NEXT: xorpd %xmm7, %xmm0 +; SSE2-NEXT: psubq %xmm7, %xmm0 +; SSE2-NEXT: movdqa %xmm2, %xmm3 +; SSE2-NEXT: psrlq %xmm4, %xmm3 +; SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm4[2,3,2,3] +; SSE2-NEXT: psrlq %xmm5, %xmm2 +; SSE2-NEXT: movsd {{.*#+}} xmm2 = xmm3[0],xmm2[1] +; SSE2-NEXT: movdqa %xmm1, %xmm3 +; SSE2-NEXT: psrlq %xmm4, %xmm3 +; SSE2-NEXT: psrlq %xmm5, %xmm1 +; SSE2-NEXT: movsd {{.*#+}} xmm1 = xmm3[0],xmm1[1] +; SSE2-NEXT: xorpd %xmm2, %xmm1 +; SSE2-NEXT: psubq %xmm2, %xmm1 +; SSE2-NEXT: retq +; +; SSE41-LABEL: combine_vec4i64_ashr_clamped: +; SSE41: # %bb.0: +; SSE41-NEXT: movdqa %xmm0, %xmm4 +; SSE41-NEXT: movdqa {{.*#+}} xmm7 = [9223372039002259456,9223372039002259456] +; SSE41-NEXT: movdqa %xmm3, %xmm0 +; SSE41-NEXT: pxor %xmm7, %xmm0 +; SSE41-NEXT: movdqa {{.*#+}} xmm8 = [9223372039002259519,9223372039002259519] +; SSE41-NEXT: movdqa %xmm8, %xmm6 +; SSE41-NEXT: pcmpeqd %xmm0, %xmm6 +; SSE41-NEXT: pshufd {{.*#+}} xmm9 = xmm0[0,0,2,2] +; SSE41-NEXT: movdqa {{.*#+}} xmm5 = [2147483711,2147483711,2147483711,2147483711] +; SSE41-NEXT: movdqa %xmm5, %xmm0 +; SSE41-NEXT: pcmpgtd %xmm9, %xmm0 +; SSE41-NEXT: pand %xmm6, %xmm0 +; SSE41-NEXT: movapd {{.*#+}} xmm9 = [63,63] +; SSE41-NEXT: movapd %xmm9, %xmm6 +; SSE41-NEXT: blendvpd %xmm0, %xmm3, %xmm6 +; SSE41-NEXT: pxor %xmm2, %xmm7 +; SSE41-NEXT: pcmpeqd %xmm7, %xmm8 +; SSE41-NEXT: pshufd {{.*#+}} xmm0 = xmm7[0,0,2,2] +; SSE41-NEXT: pcmpgtd %xmm0, %xmm5 +; SSE41-NEXT: pand %xmm8, %xmm5 +; SSE41-NEXT: movdqa %xmm5, %xmm0 +; SSE41-NEXT: blendvpd %xmm0, %xmm2, %xmm9 +; SSE41-NEXT: movdqa {{.*#+}} xmm0 = [9223372036854775808,9223372036854775808] +; SSE41-NEXT: movdqa %xmm0, %xmm2 +; SSE41-NEXT: psrlq %xmm9, %xmm2 +; SSE41-NEXT: pshufd {{.*#+}} xmm3 = xmm9[2,3,2,3] +; SSE41-NEXT: movdqa %xmm0, %xmm5 +; SSE41-NEXT: psrlq %xmm3, %xmm5 +; SSE41-NEXT: pblendw {{.*#+}} xmm5 = xmm2[0,1,2,3],xmm5[4,5,6,7] +; SSE41-NEXT: movdqa %xmm4, %xmm2 +; SSE41-NEXT: psrlq %xmm9, %xmm2 +; SSE41-NEXT: psrlq %xmm3, %xmm4 +; SSE41-NEXT: pblendw {{.*#+}} xmm4 = xmm2[0,1,2,3],xmm4[4,5,6,7] +; SSE41-NEXT: pxor %xmm5, %xmm4 +; SSE41-NEXT: psubq %xmm5, %xmm4 +; SSE41-NEXT: movdqa %xmm0, %xmm2 +; SSE41-NEXT: psrlq %xmm6, %xmm2 +; SSE41-NEXT: pshufd {{.*#+}} xmm3 = xmm6[2,3,2,3] +; SSE41-NEXT: psrlq %xmm3, %xmm0 +; SSE41-NEXT: pblendw {{.*#+}} xmm0 = xmm2[0,1,2,3],xmm0[4,5,6,7] +; SSE41-NEXT: movdqa %xmm1, %xmm2 +; SSE41-NEXT: psrlq %xmm6, %xmm2 +; SSE41-NEXT: psrlq %xmm3, %xmm1 +; SSE41-NEXT: pblendw {{.*#+}} xmm1 = xmm2[0,1,2,3],xmm1[4,5,6,7] +; SSE41-NEXT: pxor %xmm0, %xmm1 +; SSE41-NEXT: psubq %xmm0, %xmm1 +; SSE41-NEXT: movdqa %xmm4, %xmm0 +; SSE41-NEXT: retq +; +; AVX2-LABEL: combine_vec4i64_ashr_clamped: +; AVX2: # %bb.0: +; AVX2-NEXT: vpbroadcastq {{.*#+}} ymm2 = [9223372036854775808,9223372036854775808,9223372036854775808,9223372036854775808] +; AVX2-NEXT: vpxor %ymm2, %ymm1, %ymm3 +; AVX2-NEXT: vpbroadcastq {{.*#+}} ymm4 = [9223372036854775870,9223372036854775870,9223372036854775870,9223372036854775870] +; AVX2-NEXT: vpcmpgtq %ymm4, %ymm3, %ymm3 +; AVX2-NEXT: vbroadcastsd {{.*#+}} ymm4 = [63,63,63,63] +; AVX2-NEXT: vblendvpd %ymm3, %ymm4, %ymm1, %ymm1 +; AVX2-NEXT: vpsrlvq %ymm1, %ymm2, %ymm2 +; AVX2-NEXT: vpsrlvq %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpxor %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: vpsubq %ymm2, %ymm0, %ymm0 +; AVX2-NEXT: retq +; +; AVX512-LABEL: combine_vec4i64_ashr_clamped: +; AVX512: # %bb.0: +; AVX512-NEXT: vpsravq %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: retq + %1 = tail call <4 x i64> @llvm.umin.v4i64(<4 x i64> %y, <4 x i64> <i64 63, i64 63, i64 63, i64 63>) + %2 = ashr <4 x i64> %x, %1 + ret <4 x i64> %2 +} diff --git a/llvm/test/CodeGen/X86/dagcombine-shifts.ll b/llvm/test/CodeGen/X86/dagcombine-shifts.ll index 42b325dd4c229e0791488888a2fe5bd60bbc4427..734abfe55a4ec452ced48e948c8061cab12782d0 100644 --- a/llvm/test/CodeGen/X86/dagcombine-shifts.ll +++ b/llvm/test/CodeGen/X86/dagcombine-shifts.ll @@ -322,5 +322,132 @@ define void @g(i32 %a) nounwind { ret void } +define i32 @shift_zext_shl(i8 zeroext %x) { +; X86-LABEL: shift_zext_shl: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax +; X86-NEXT: andl $64, %eax +; X86-NEXT: shll $9, %eax +; X86-NEXT: retl +; +; X64-LABEL: shift_zext_shl: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: andl $64, %eax +; X64-NEXT: shll $9, %eax +; X64-NEXT: retq + %a = and i8 %x, 64 + %b = zext i8 %a to i16 + %c = shl i16 %b, 9 + %d = zext i16 %c to i32 + ret i32 %d +} + +define i32 @shift_zext_shl2(i8 zeroext %x) { +; X86-LABEL: shift_zext_shl2: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax +; X86-NEXT: andl $64, %eax +; X86-NEXT: shll $9, %eax +; X86-NEXT: retl +; +; X64-LABEL: shift_zext_shl2: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: andl $64, %eax +; X64-NEXT: shll $9, %eax +; X64-NEXT: retq + %a = and i8 %x, 64 + %b = zext i8 %a to i32 + %c = shl i32 %b, 9 + ret i32 %c +} + +define <4 x i32> @shift_zext_shl_vec(<4 x i8> %x) nounwind { +; X86-LABEL: shift_zext_shl_vec: +; X86: # %bb.0: +; X86-NEXT: pushl %edi +; X86-NEXT: pushl %esi +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %edi +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: andl $64, %ecx +; X86-NEXT: shll $9, %ecx +; X86-NEXT: andl $63, %edx +; X86-NEXT: shll $8, %edx +; X86-NEXT: andl $31, %esi +; X86-NEXT: shll $7, %esi +; X86-NEXT: andl $23, %edi +; X86-NEXT: shll $6, %edi +; X86-NEXT: movl %edi, 12(%eax) +; X86-NEXT: movl %esi, 8(%eax) +; X86-NEXT: movl %edx, 4(%eax) +; X86-NEXT: movl %ecx, (%eax) +; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: retl $4 +; +; X64-LABEL: shift_zext_shl_vec: +; X64: # %bb.0: +; X64-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; X64-NEXT: pxor %xmm1, %xmm1 +; X64-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] +; X64-NEXT: pmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; X64-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3] +; X64-NEXT: retq + %a = and <4 x i8> %x, <i8 64, i8 63, i8 31, i8 23> + %b = zext <4 x i8> %a to <4 x i16> + %c = shl <4 x i16> %b, <i16 9, i16 8, i16 7, i16 6> + %d = zext <4 x i16> %c to <4 x i32> + ret <4 x i32> %d +} + +define <4 x i32> @shift_zext_shl2_vec(<4 x i8> %x) nounwind { +; X86-LABEL: shift_zext_shl2_vec: +; X86: # %bb.0: +; X86-NEXT: pushl %edi +; X86-NEXT: pushl %esi +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %edx +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %esi +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %edi +; X86-NEXT: andl $23, %edi +; X86-NEXT: andl $31, %esi +; X86-NEXT: andl $63, %edx +; X86-NEXT: andl $64, %ecx +; X86-NEXT: shll $9, %ecx +; X86-NEXT: shll $8, %edx +; X86-NEXT: shll $7, %esi +; X86-NEXT: shll $6, %edi +; X86-NEXT: movl %edi, 12(%eax) +; X86-NEXT: movl %esi, 8(%eax) +; X86-NEXT: movl %edx, 4(%eax) +; X86-NEXT: movl %ecx, (%eax) +; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: retl $4 +; +; X64-LABEL: shift_zext_shl2_vec: +; X64: # %bb.0: +; X64-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; X64-NEXT: pxor %xmm1, %xmm1 +; X64-NEXT: punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] +; X64-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3] +; X64-NEXT: pshufd {{.*#+}} xmm1 = xmm0[1,1,3,3] +; X64-NEXT: pmuludq {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; X64-NEXT: pshufd {{.*#+}} xmm0 = xmm0[0,2,2,3] +; X64-NEXT: pmuludq {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1 +; X64-NEXT: pshufd {{.*#+}} xmm1 = xmm1[0,2,2,3] +; X64-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1] +; X64-NEXT: retq + %a = and <4 x i8> %x, <i8 64, i8 63, i8 31, i8 23> + %b = zext <4 x i8> %a to <4 x i32> + %c = shl <4 x i32> %b, <i32 9, i32 8, i32 7, i32 6> + ret <4 x i32> %c +} + declare dso_local void @f(i64) diff --git a/llvm/test/CodeGen/X86/extractelement-load.ll b/llvm/test/CodeGen/X86/extractelement-load.ll index 9d573ef2a8fad98c77542882a695a45f61301457..022b25a241533385015935c5df036c517a8191bb 100644 --- a/llvm/test/CodeGen/X86/extractelement-load.ll +++ b/llvm/test/CodeGen/X86/extractelement-load.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -mtriple=i686-unknown -mattr=+sse2 | FileCheck %s --check-prefix=X32-SSE2 +; RUN: llc < %s -mtriple=i686-unknown -mattr=+sse2 | FileCheck %s --check-prefix=X86-SSE2 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ssse3 | FileCheck %s --check-prefixes=X64,X64-SSSE3 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx | FileCheck %s --check-prefixes=X64,X64-AVX,X64-AVX1 ; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=X64,X64-AVX,X64-AVX2 @@ -7,23 +7,16 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" define i32 @t(ptr %val) nounwind { -; X32-SSE2-LABEL: t: -; X32-SSE2: # %bb.0: -; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax -; X32-SSE2-NEXT: pshufd {{.*#+}} xmm0 = mem[2,3,2,3] -; X32-SSE2-NEXT: movd %xmm0, %eax -; X32-SSE2-NEXT: retl +; X86-SSE2-LABEL: t: +; X86-SSE2: # %bb.0: +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE2-NEXT: movl 8(%eax), %eax +; X86-SSE2-NEXT: retl ; -; X64-SSSE3-LABEL: t: -; X64-SSSE3: # %bb.0: -; X64-SSSE3-NEXT: pshufd {{.*#+}} xmm0 = mem[2,3,2,3] -; X64-SSSE3-NEXT: movd %xmm0, %eax -; X64-SSSE3-NEXT: retq -; -; X64-AVX-LABEL: t: -; X64-AVX: # %bb.0: -; X64-AVX-NEXT: movl 8(%rdi), %eax -; X64-AVX-NEXT: retq +; X64-LABEL: t: +; X64: # %bb.0: +; X64-NEXT: movl 8(%rdi), %eax +; X64-NEXT: retq %tmp2 = load <2 x i64>, ptr %val, align 16 ; <<2 x i64>> [#uses=1] %tmp3 = bitcast <2 x i64> %tmp2 to <4 x i32> ; <<4 x i32>> [#uses=1] %tmp4 = extractelement <4 x i32> %tmp3, i32 2 ; <i32> [#uses=1] @@ -33,9 +26,9 @@ define i32 @t(ptr %val) nounwind { ; Case where extractelement of load ends up as undef. ; (Making sure this doesn't crash.) define i32 @t2(ptr %xp) { -; X32-SSE2-LABEL: t2: -; X32-SSE2: # %bb.0: -; X32-SSE2-NEXT: retl +; X86-SSE2-LABEL: t2: +; X86-SSE2: # %bb.0: +; X86-SSE2-NEXT: retl ; ; X64-LABEL: t2: ; X64: # %bb.0: @@ -51,12 +44,12 @@ define i32 @t2(ptr %xp) { ; narrow load. define void @t3(ptr %a0) { -; X32-SSE2-LABEL: t3: -; X32-SSE2: # %bb.0: # %bb -; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax -; X32-SSE2-NEXT: movups (%eax), %xmm0 -; X32-SSE2-NEXT: movhps %xmm0, (%eax) -; X32-SSE2-NEXT: retl +; X86-SSE2-LABEL: t3: +; X86-SSE2: # %bb.0: # %bb +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE2-NEXT: movups (%eax), %xmm0 +; X86-SSE2-NEXT: movhps %xmm0, (%eax) +; X86-SSE2-NEXT: retl ; ; X64-SSSE3-LABEL: t3: ; X64-SSSE3: # %bb.0: # %bb @@ -81,14 +74,12 @@ bb: ; This is testing for an assertion - the extraction was assuming that the undef ; second shuffle operand was a post-bitcast type instead of a pre-bitcast type. define i64 @t4(ptr %a) { -; X32-SSE2-LABEL: t4: -; X32-SSE2: # %bb.0: -; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax -; X32-SSE2-NEXT: movdqa (%eax), %xmm0 -; X32-SSE2-NEXT: movd %xmm0, %eax -; X32-SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1] -; X32-SSE2-NEXT: movd %xmm0, %edx -; X32-SSE2-NEXT: retl +; X86-SSE2-LABEL: t4: +; X86-SSE2: # %bb.0: +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE2-NEXT: movl (%ecx), %eax +; X86-SSE2-NEXT: movl 4(%ecx), %edx +; X86-SSE2-NEXT: retl ; ; X64-LABEL: t4: ; X64: # %bb.0: @@ -103,13 +94,13 @@ define i64 @t4(ptr %a) { ; Don't extract from a volatile. define void @t5(ptr%a0, ptr%a1) { -; X32-SSE2-LABEL: t5: -; X32-SSE2: # %bb.0: -; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax -; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X32-SSE2-NEXT: movaps (%ecx), %xmm0 -; X32-SSE2-NEXT: movhps %xmm0, (%eax) -; X32-SSE2-NEXT: retl +; X86-SSE2-LABEL: t5: +; X86-SSE2: # %bb.0: +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE2-NEXT: movaps (%ecx), %xmm0 +; X86-SSE2-NEXT: movhps %xmm0, (%eax) +; X86-SSE2-NEXT: retl ; ; X64-SSSE3-LABEL: t5: ; X64-SSSE3: # %bb.0: @@ -130,24 +121,24 @@ define void @t5(ptr%a0, ptr%a1) { ; Check for multiuse. define float @t6(ptr%a0) { -; X32-SSE2-LABEL: t6: -; X32-SSE2: # %bb.0: -; X32-SSE2-NEXT: pushl %eax -; X32-SSE2-NEXT: .cfi_def_cfa_offset 8 -; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax -; X32-SSE2-NEXT: movaps (%eax), %xmm0 -; X32-SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1] -; X32-SSE2-NEXT: xorps %xmm1, %xmm1 -; X32-SSE2-NEXT: cmpeqss %xmm0, %xmm1 -; X32-SSE2-NEXT: movss {{.*#+}} xmm2 = [1.0E+0,0.0E+0,0.0E+0,0.0E+0] -; X32-SSE2-NEXT: andps %xmm1, %xmm2 -; X32-SSE2-NEXT: andnps %xmm0, %xmm1 -; X32-SSE2-NEXT: orps %xmm2, %xmm1 -; X32-SSE2-NEXT: movss %xmm1, (%esp) -; X32-SSE2-NEXT: flds (%esp) -; X32-SSE2-NEXT: popl %eax -; X32-SSE2-NEXT: .cfi_def_cfa_offset 4 -; X32-SSE2-NEXT: retl +; X86-SSE2-LABEL: t6: +; X86-SSE2: # %bb.0: +; X86-SSE2-NEXT: pushl %eax +; X86-SSE2-NEXT: .cfi_def_cfa_offset 8 +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE2-NEXT: movaps (%eax), %xmm0 +; X86-SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1] +; X86-SSE2-NEXT: xorps %xmm1, %xmm1 +; X86-SSE2-NEXT: cmpeqss %xmm0, %xmm1 +; X86-SSE2-NEXT: movss {{.*#+}} xmm2 = [1.0E+0,0.0E+0,0.0E+0,0.0E+0] +; X86-SSE2-NEXT: andps %xmm1, %xmm2 +; X86-SSE2-NEXT: andnps %xmm0, %xmm1 +; X86-SSE2-NEXT: orps %xmm2, %xmm1 +; X86-SSE2-NEXT: movss %xmm1, (%esp) +; X86-SSE2-NEXT: flds (%esp) +; X86-SSE2-NEXT: popl %eax +; X86-SSE2-NEXT: .cfi_def_cfa_offset 4 +; X86-SSE2-NEXT: retl ; ; X64-SSSE3-LABEL: t6: ; X64-SSSE3: # %bb.0: @@ -184,20 +175,20 @@ define float @t6(ptr%a0) { } define void @PR43971(ptr%a0, ptr%a1) { -; X32-SSE2-LABEL: PR43971: -; X32-SSE2: # %bb.0: # %entry -; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax -; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X32-SSE2-NEXT: movaps 16(%ecx), %xmm0 -; X32-SSE2-NEXT: movhlps {{.*#+}} xmm0 = xmm0[1,1] -; X32-SSE2-NEXT: xorps %xmm1, %xmm1 -; X32-SSE2-NEXT: cmpltss %xmm0, %xmm1 -; X32-SSE2-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero -; X32-SSE2-NEXT: andps %xmm1, %xmm2 -; X32-SSE2-NEXT: andnps %xmm0, %xmm1 -; X32-SSE2-NEXT: orps %xmm2, %xmm1 -; X32-SSE2-NEXT: movss %xmm1, (%eax) -; X32-SSE2-NEXT: retl +; X86-SSE2-LABEL: PR43971: +; X86-SSE2: # %bb.0: # %entry +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE2-NEXT: movaps 16(%ecx), %xmm0 +; X86-SSE2-NEXT: movhlps {{.*#+}} xmm0 = xmm0[1,1] +; X86-SSE2-NEXT: xorps %xmm1, %xmm1 +; X86-SSE2-NEXT: cmpltss %xmm0, %xmm1 +; X86-SSE2-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero +; X86-SSE2-NEXT: andps %xmm1, %xmm2 +; X86-SSE2-NEXT: andnps %xmm0, %xmm1 +; X86-SSE2-NEXT: orps %xmm2, %xmm1 +; X86-SSE2-NEXT: movss %xmm1, (%eax) +; X86-SSE2-NEXT: retl ; ; X64-SSSE3-LABEL: PR43971: ; X64-SSSE3: # %bb.0: # %entry @@ -231,22 +222,22 @@ entry: } define float @PR43971_1(ptr%a0) nounwind { -; X32-SSE2-LABEL: PR43971_1: -; X32-SSE2: # %bb.0: # %entry -; X32-SSE2-NEXT: pushl %eax -; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax -; X32-SSE2-NEXT: movaps (%eax), %xmm0 -; X32-SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1] -; X32-SSE2-NEXT: xorps %xmm1, %xmm1 -; X32-SSE2-NEXT: cmpeqss %xmm0, %xmm1 -; X32-SSE2-NEXT: movss {{.*#+}} xmm2 = [1.0E+0,0.0E+0,0.0E+0,0.0E+0] -; X32-SSE2-NEXT: andps %xmm1, %xmm2 -; X32-SSE2-NEXT: andnps %xmm0, %xmm1 -; X32-SSE2-NEXT: orps %xmm2, %xmm1 -; X32-SSE2-NEXT: movss %xmm1, (%esp) -; X32-SSE2-NEXT: flds (%esp) -; X32-SSE2-NEXT: popl %eax -; X32-SSE2-NEXT: retl +; X86-SSE2-LABEL: PR43971_1: +; X86-SSE2: # %bb.0: # %entry +; X86-SSE2-NEXT: pushl %eax +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE2-NEXT: movaps (%eax), %xmm0 +; X86-SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1] +; X86-SSE2-NEXT: xorps %xmm1, %xmm1 +; X86-SSE2-NEXT: cmpeqss %xmm0, %xmm1 +; X86-SSE2-NEXT: movss {{.*#+}} xmm2 = [1.0E+0,0.0E+0,0.0E+0,0.0E+0] +; X86-SSE2-NEXT: andps %xmm1, %xmm2 +; X86-SSE2-NEXT: andnps %xmm0, %xmm1 +; X86-SSE2-NEXT: orps %xmm2, %xmm1 +; X86-SSE2-NEXT: movss %xmm1, (%esp) +; X86-SSE2-NEXT: flds (%esp) +; X86-SSE2-NEXT: popl %eax +; X86-SSE2-NEXT: retl ; ; X64-SSSE3-LABEL: PR43971_1: ; X64-SSSE3: # %bb.0: # %entry @@ -283,17 +274,48 @@ entry: ret float %cond } +define i32 @PR85419(ptr %p0) { +; X86-SSE2-LABEL: PR85419: +; X86-SSE2: # %bb.0: +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE2-NEXT: movl (%ecx), %edx +; X86-SSE2-NEXT: xorl %eax, %eax +; X86-SSE2-NEXT: orl 4(%ecx), %edx +; X86-SSE2-NEXT: je .LBB8_2 +; X86-SSE2-NEXT: # %bb.1: +; X86-SSE2-NEXT: movl 8(%ecx), %eax +; X86-SSE2-NEXT: .LBB8_2: +; X86-SSE2-NEXT: retl +; +; X64-LABEL: PR85419: +; X64: # %bb.0: +; X64-NEXT: xorl %eax, %eax +; X64-NEXT: cmpq $0, (%rdi) +; X64-NEXT: je .LBB8_2 +; X64-NEXT: # %bb.1: +; X64-NEXT: movl 8(%rdi), %eax +; X64-NEXT: .LBB8_2: +; X64-NEXT: retq + %load = load <2 x i64>, ptr %p0, align 16 + %vecext.i = extractelement <2 x i64> %load, i64 0 + %cmp = icmp eq i64 %vecext.i, 0 + %.cast = bitcast <2 x i64> %load to <4 x i32> + %vecext.i2 = extractelement <4 x i32> %.cast, i64 2 + %retval.0 = select i1 %cmp, i32 0, i32 %vecext.i2 + ret i32 %retval.0 +} + ; Test for bad extractions from a VBROADCAST_LOAD of the <2 x i16> non-uniform constant bitcast as <4 x i32>. define void @subextract_broadcast_load_constant(ptr nocapture %0, ptr nocapture %1, ptr nocapture %2) nounwind { -; X32-SSE2-LABEL: subextract_broadcast_load_constant: -; X32-SSE2: # %bb.0: -; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax -; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edx -; X32-SSE2-NEXT: movl $-1583308898, (%edx) # imm = 0xA1A09F9E -; X32-SSE2-NEXT: movw $-24674, (%ecx) # imm = 0x9F9E -; X32-SSE2-NEXT: movw $-24160, (%eax) # imm = 0xA1A0 -; X32-SSE2-NEXT: retl +; X86-SSE2-LABEL: subextract_broadcast_load_constant: +; X86-SSE2: # %bb.0: +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edx +; X86-SSE2-NEXT: movl $-1583308898, (%edx) # imm = 0xA1A09F9E +; X86-SSE2-NEXT: movw $-24674, (%ecx) # imm = 0x9F9E +; X86-SSE2-NEXT: movw $-24160, (%eax) # imm = 0xA1A0 +; X86-SSE2-NEXT: retl ; ; X64-LABEL: subextract_broadcast_load_constant: ; X64: # %bb.0: @@ -319,15 +341,15 @@ define void @subextract_broadcast_load_constant(ptr nocapture %0, ptr nocapture ; A scalar load is favored over a XMM->GPR register transfer in this example. define i32 @multi_use_load_scalarization(ptr %p) nounwind { -; X32-SSE2-LABEL: multi_use_load_scalarization: -; X32-SSE2: # %bb.0: -; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X32-SSE2-NEXT: movl (%ecx), %eax -; X32-SSE2-NEXT: movdqu (%ecx), %xmm0 -; X32-SSE2-NEXT: pcmpeqd %xmm1, %xmm1 -; X32-SSE2-NEXT: psubd %xmm1, %xmm0 -; X32-SSE2-NEXT: movdqa %xmm0, (%ecx) -; X32-SSE2-NEXT: retl +; X86-SSE2-LABEL: multi_use_load_scalarization: +; X86-SSE2: # %bb.0: +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE2-NEXT: movl (%ecx), %eax +; X86-SSE2-NEXT: movdqu (%ecx), %xmm0 +; X86-SSE2-NEXT: pcmpeqd %xmm1, %xmm1 +; X86-SSE2-NEXT: psubd %xmm1, %xmm0 +; X86-SSE2-NEXT: movdqa %xmm0, (%ecx) +; X86-SSE2-NEXT: retl ; ; X64-SSSE3-LABEL: multi_use_load_scalarization: ; X64-SSSE3: # %bb.0: @@ -354,15 +376,15 @@ define i32 @multi_use_load_scalarization(ptr %p) nounwind { } define i32 @multi_use_volatile_load_scalarization(ptr %p) nounwind { -; X32-SSE2-LABEL: multi_use_volatile_load_scalarization: -; X32-SSE2: # %bb.0: -; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X32-SSE2-NEXT: movdqu (%ecx), %xmm0 -; X32-SSE2-NEXT: pcmpeqd %xmm1, %xmm1 -; X32-SSE2-NEXT: movd %xmm0, %eax -; X32-SSE2-NEXT: psubd %xmm1, %xmm0 -; X32-SSE2-NEXT: movdqa %xmm0, (%ecx) -; X32-SSE2-NEXT: retl +; X86-SSE2-LABEL: multi_use_volatile_load_scalarization: +; X86-SSE2: # %bb.0: +; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-SSE2-NEXT: movdqu (%ecx), %xmm0 +; X86-SSE2-NEXT: pcmpeqd %xmm1, %xmm1 +; X86-SSE2-NEXT: movd %xmm0, %eax +; X86-SSE2-NEXT: psubd %xmm1, %xmm0 +; X86-SSE2-NEXT: movdqa %xmm0, (%ecx) +; X86-SSE2-NEXT: retl ; ; X64-SSSE3-LABEL: multi_use_volatile_load_scalarization: ; X64-SSSE3: # %bb.0: @@ -398,41 +420,41 @@ define i32 @multi_use_volatile_load_scalarization(ptr %p) nounwind { @zero = internal unnamed_addr global <8 x i32> zeroinitializer, align 32 define i32 @main() nounwind { -; X32-SSE2-LABEL: main: -; X32-SSE2: # %bb.0: -; X32-SSE2-NEXT: pushl %ebp -; X32-SSE2-NEXT: movl %esp, %ebp -; X32-SSE2-NEXT: pushl %esi -; X32-SSE2-NEXT: andl $-32, %esp -; X32-SSE2-NEXT: subl $64, %esp -; X32-SSE2-NEXT: movdqa zero, %xmm0 -; X32-SSE2-NEXT: movaps n1+16, %xmm1 -; X32-SSE2-NEXT: movaps n1, %xmm2 -; X32-SSE2-NEXT: movaps %xmm2, zero -; X32-SSE2-NEXT: movaps %xmm1, zero+16 -; X32-SSE2-NEXT: movaps {{.*#+}} xmm1 = [2,2,2,2] -; X32-SSE2-NEXT: movaps %xmm1, {{[0-9]+}}(%esp) -; X32-SSE2-NEXT: movaps %xmm1, (%esp) -; X32-SSE2-NEXT: movdqa (%esp), %xmm1 -; X32-SSE2-NEXT: movaps {{[0-9]+}}(%esp), %xmm2 -; X32-SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm0[2,3,2,3] -; X32-SSE2-NEXT: movd %xmm2, %eax -; X32-SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] -; X32-SSE2-NEXT: movd %xmm2, %ecx -; X32-SSE2-NEXT: xorl %edx, %edx -; X32-SSE2-NEXT: divl %ecx -; X32-SSE2-NEXT: movl %eax, %ecx -; X32-SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,1,1] -; X32-SSE2-NEXT: movd %xmm0, %eax -; X32-SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm1[1,1,1,1] -; X32-SSE2-NEXT: movd %xmm0, %esi -; X32-SSE2-NEXT: xorl %edx, %edx -; X32-SSE2-NEXT: divl %esi -; X32-SSE2-NEXT: addl %ecx, %eax -; X32-SSE2-NEXT: leal -4(%ebp), %esp -; X32-SSE2-NEXT: popl %esi -; X32-SSE2-NEXT: popl %ebp -; X32-SSE2-NEXT: retl +; X86-SSE2-LABEL: main: +; X86-SSE2: # %bb.0: +; X86-SSE2-NEXT: pushl %ebp +; X86-SSE2-NEXT: movl %esp, %ebp +; X86-SSE2-NEXT: pushl %edi +; X86-SSE2-NEXT: pushl %esi +; X86-SSE2-NEXT: andl $-32, %esp +; X86-SSE2-NEXT: subl $64, %esp +; X86-SSE2-NEXT: movaps n1+16, %xmm0 +; X86-SSE2-NEXT: movaps n1, %xmm1 +; X86-SSE2-NEXT: movl zero+4, %ecx +; X86-SSE2-NEXT: movl zero+8, %eax +; X86-SSE2-NEXT: movaps %xmm1, zero +; X86-SSE2-NEXT: movaps %xmm0, zero+16 +; X86-SSE2-NEXT: movaps {{.*#+}} xmm0 = [2,2,2,2] +; X86-SSE2-NEXT: movaps %xmm0, {{[0-9]+}}(%esp) +; X86-SSE2-NEXT: movaps %xmm0, (%esp) +; X86-SSE2-NEXT: movdqa (%esp), %xmm0 +; X86-SSE2-NEXT: movaps {{[0-9]+}}(%esp), %xmm1 +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] +; X86-SSE2-NEXT: movd %xmm1, %esi +; X86-SSE2-NEXT: xorl %edx, %edx +; X86-SSE2-NEXT: divl %esi +; X86-SSE2-NEXT: movl %eax, %esi +; X86-SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,1,1] +; X86-SSE2-NEXT: movd %xmm0, %edi +; X86-SSE2-NEXT: movl %ecx, %eax +; X86-SSE2-NEXT: xorl %edx, %edx +; X86-SSE2-NEXT: divl %edi +; X86-SSE2-NEXT: addl %esi, %eax +; X86-SSE2-NEXT: leal -8(%ebp), %esp +; X86-SSE2-NEXT: popl %esi +; X86-SSE2-NEXT: popl %edi +; X86-SSE2-NEXT: popl %ebp +; X86-SSE2-NEXT: retl ; ; X64-SSSE3-LABEL: main: ; X64-SSSE3: # %bb.0: @@ -440,31 +462,29 @@ define i32 @main() nounwind { ; X64-SSSE3-NEXT: movq %rsp, %rbp ; X64-SSSE3-NEXT: andq $-32, %rsp ; X64-SSSE3-NEXT: subq $64, %rsp -; X64-SSSE3-NEXT: movdqa zero(%rip), %xmm0 ; X64-SSSE3-NEXT: movq n1@GOTPCREL(%rip), %rax -; X64-SSSE3-NEXT: movaps (%rax), %xmm1 -; X64-SSSE3-NEXT: movaps 16(%rax), %xmm2 -; X64-SSSE3-NEXT: movaps %xmm1, zero(%rip) -; X64-SSSE3-NEXT: movaps %xmm2, zero+16(%rip) -; X64-SSSE3-NEXT: movaps {{.*#+}} xmm1 = [2,2,2,2] -; X64-SSSE3-NEXT: movaps %xmm1, {{[0-9]+}}(%rsp) -; X64-SSSE3-NEXT: movaps %xmm1, (%rsp) -; X64-SSSE3-NEXT: movdqa (%rsp), %xmm1 -; X64-SSSE3-NEXT: movaps {{[0-9]+}}(%rsp), %xmm2 -; X64-SSSE3-NEXT: pshufd {{.*#+}} xmm2 = xmm0[2,3,2,3] -; X64-SSSE3-NEXT: movd %xmm2, %eax -; X64-SSSE3-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] -; X64-SSSE3-NEXT: movd %xmm2, %ecx +; X64-SSSE3-NEXT: movaps (%rax), %xmm0 +; X64-SSSE3-NEXT: movaps 16(%rax), %xmm1 +; X64-SSSE3-NEXT: movl zero+4(%rip), %ecx +; X64-SSSE3-NEXT: movl zero+8(%rip), %eax +; X64-SSSE3-NEXT: movaps %xmm0, zero(%rip) +; X64-SSSE3-NEXT: movaps %xmm1, zero+16(%rip) +; X64-SSSE3-NEXT: movaps {{.*#+}} xmm0 = [2,2,2,2] +; X64-SSSE3-NEXT: movaps %xmm0, {{[0-9]+}}(%rsp) +; X64-SSSE3-NEXT: movaps %xmm0, (%rsp) +; X64-SSSE3-NEXT: movdqa (%rsp), %xmm0 +; X64-SSSE3-NEXT: movaps {{[0-9]+}}(%rsp), %xmm1 +; X64-SSSE3-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] +; X64-SSSE3-NEXT: movd %xmm1, %esi ; X64-SSSE3-NEXT: xorl %edx, %edx -; X64-SSSE3-NEXT: divl %ecx -; X64-SSSE3-NEXT: movl %eax, %ecx +; X64-SSSE3-NEXT: divl %esi +; X64-SSSE3-NEXT: movl %eax, %esi ; X64-SSSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,1,1] -; X64-SSSE3-NEXT: movd %xmm0, %eax -; X64-SSSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm1[1,1,1,1] -; X64-SSSE3-NEXT: movd %xmm0, %esi +; X64-SSSE3-NEXT: movd %xmm0, %edi +; X64-SSSE3-NEXT: movl %ecx, %eax ; X64-SSSE3-NEXT: xorl %edx, %edx -; X64-SSSE3-NEXT: divl %esi -; X64-SSSE3-NEXT: addl %ecx, %eax +; X64-SSSE3-NEXT: divl %edi +; X64-SSSE3-NEXT: addl %esi, %eax ; X64-SSSE3-NEXT: movq %rbp, %rsp ; X64-SSSE3-NEXT: popq %rbp ; X64-SSSE3-NEXT: retq diff --git a/llvm/test/CodeGen/X86/fast-regalloc-live-out-debug-values.mir b/llvm/test/CodeGen/X86/fast-regalloc-live-out-debug-values.mir index 56cbe3f7b563883fe84e3be8c47195cfe8c8b02e..37a90a2f16d67116c2b0e5f034032998c10dae44 100644 --- a/llvm/test/CodeGen/X86/fast-regalloc-live-out-debug-values.mir +++ b/llvm/test/CodeGen/X86/fast-regalloc-live-out-debug-values.mir @@ -119,6 +119,7 @@ name: foo tracksRegLiveness: true frameInfo: + adjustsStack: true hasCalls: true stack: - { id: 0, name: a.addr, size: 4, alignment: 4, debug-info-variable: '!11', diff --git a/llvm/test/CodeGen/X86/heap-alloc-markers.mir b/llvm/test/CodeGen/X86/heap-alloc-markers.mir index 0bf83657cb06c028ddd81bd741f81fea07e8e0a1..6e0dc50bac0e19327d1da6ab006fb89f1e24d9c4 100644 --- a/llvm/test/CodeGen/X86/heap-alloc-markers.mir +++ b/llvm/test/CodeGen/X86/heap-alloc-markers.mir @@ -34,6 +34,7 @@ name: test # CHECK-LABEL: {{^}}test: tracksRegLiveness: true frameInfo: + adjustsStack: true hasCalls: true body: | bb.0.entry: diff --git a/llvm/test/CodeGen/X86/huge-stack-offset.ll b/llvm/test/CodeGen/X86/huge-stack-offset.ll index 68dcfa748b0cb67e9e0a9974523689ed8eaa48cb..e825328ccd89a25ca7904fc8ee56c7fbf9945883 100644 --- a/llvm/test/CodeGen/X86/huge-stack-offset.ll +++ b/llvm/test/CodeGen/X86/huge-stack-offset.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -mtriple=x86_64-linux-unknown | FileCheck %s --check-prefix=CHECK-64 -; RUN: llc < %s -mtriple=i386-linux-unknown | FileCheck %s --check-prefix=CHECK-32 +; RUN: llc < %s -mtriple=x86_64-linux-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-64 +; RUN: llc < %s -mtriple=i386-linux-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-32 ; Test that a large stack offset uses a single add/sub instruction to ; adjust the stack pointer. diff --git a/llvm/test/CodeGen/X86/huge-stack-offset2.ll b/llvm/test/CodeGen/X86/huge-stack-offset2.ll index 3bf0260cc12ab953b3967a7f7694f6826fa40ee7..053643eb3686c5832d39485d54495eebc543cc99 100644 --- a/llvm/test/CodeGen/X86/huge-stack-offset2.ll +++ b/llvm/test/CodeGen/X86/huge-stack-offset2.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -mtriple=x86_64-linux | FileCheck %s --check-prefix=CHECK +; RUN: llc < %s -mtriple=x86_64-linux -verify-machineinstrs | FileCheck %s --check-prefix=CHECK ; Test how we handle pathologically large stack frames when RAX is live through ; the prologue and epilogue. diff --git a/llvm/test/CodeGen/X86/insertelement-var-index.ll b/llvm/test/CodeGen/X86/insertelement-var-index.ll index 8ed8495d7a461462a5d4a951d289aa3bdf2837ff..5420e6b5ce86f3f9d9108f4c2597147fd12807e0 100644 --- a/llvm/test/CodeGen/X86/insertelement-var-index.ll +++ b/llvm/test/CodeGen/X86/insertelement-var-index.ll @@ -1009,18 +1009,19 @@ define <2 x i64> @arg_i64_v2i64(<2 x i64> %v, i64 %x, i32 %y) nounwind { ; X86AVX2-NEXT: pushl %esi ; X86AVX2-NEXT: andl $-16, %esp ; X86AVX2-NEXT: subl $48, %esp -; X86AVX2-NEXT: movl 8(%ebp), %eax -; X86AVX2-NEXT: movl 12(%ebp), %ecx -; X86AVX2-NEXT: movl 16(%ebp), %edx +; X86AVX2-NEXT: movl 8(%ebp), %edx +; X86AVX2-NEXT: movl 12(%ebp), %eax +; X86AVX2-NEXT: movl 16(%ebp), %ecx ; X86AVX2-NEXT: vmovaps %xmm0, (%esp) -; X86AVX2-NEXT: leal (%edx,%edx), %esi +; X86AVX2-NEXT: addl %ecx, %ecx +; X86AVX2-NEXT: movl %ecx, %esi ; X86AVX2-NEXT: andl $3, %esi -; X86AVX2-NEXT: movl %eax, (%esp,%esi,4) +; X86AVX2-NEXT: movl %edx, (%esp,%esi,4) ; X86AVX2-NEXT: vmovaps (%esp), %xmm0 ; X86AVX2-NEXT: vmovaps %xmm0, {{[0-9]+}}(%esp) -; X86AVX2-NEXT: leal 1(%edx,%edx), %eax -; X86AVX2-NEXT: andl $3, %eax -; X86AVX2-NEXT: movl %ecx, 16(%esp,%eax,4) +; X86AVX2-NEXT: incl %ecx +; X86AVX2-NEXT: andl $3, %ecx +; X86AVX2-NEXT: movl %eax, 16(%esp,%ecx,4) ; X86AVX2-NEXT: vmovaps {{[0-9]+}}(%esp), %xmm0 ; X86AVX2-NEXT: leal -4(%ebp), %esp ; X86AVX2-NEXT: popl %esi @@ -1362,12 +1363,13 @@ define <2 x i64> @load_i64_v2i64(<2 x i64> %v, ptr %p, i32 %y) nounwind { ; X86AVX2-NEXT: movl (%ecx), %edx ; X86AVX2-NEXT: movl 4(%ecx), %ecx ; X86AVX2-NEXT: vmovaps %xmm0, (%esp) -; X86AVX2-NEXT: leal (%eax,%eax), %esi +; X86AVX2-NEXT: addl %eax, %eax +; X86AVX2-NEXT: movl %eax, %esi ; X86AVX2-NEXT: andl $3, %esi ; X86AVX2-NEXT: movl %edx, (%esp,%esi,4) ; X86AVX2-NEXT: vmovaps (%esp), %xmm0 ; X86AVX2-NEXT: vmovaps %xmm0, {{[0-9]+}}(%esp) -; X86AVX2-NEXT: leal 1(%eax,%eax), %eax +; X86AVX2-NEXT: incl %eax ; X86AVX2-NEXT: andl $3, %eax ; X86AVX2-NEXT: movl %ecx, 16(%esp,%eax,4) ; X86AVX2-NEXT: vmovaps {{[0-9]+}}(%esp), %xmm0 @@ -1742,18 +1744,19 @@ define <4 x i64> @arg_i64_v4i64(<4 x i64> %v, i64 %x, i32 %y) nounwind { ; X86AVX2-NEXT: pushl %esi ; X86AVX2-NEXT: andl $-32, %esp ; X86AVX2-NEXT: subl $96, %esp -; X86AVX2-NEXT: movl 8(%ebp), %eax -; X86AVX2-NEXT: movl 12(%ebp), %ecx -; X86AVX2-NEXT: movl 16(%ebp), %edx +; X86AVX2-NEXT: movl 8(%ebp), %edx +; X86AVX2-NEXT: movl 12(%ebp), %eax +; X86AVX2-NEXT: movl 16(%ebp), %ecx ; X86AVX2-NEXT: vmovaps %ymm0, (%esp) -; X86AVX2-NEXT: leal (%edx,%edx), %esi +; X86AVX2-NEXT: addl %ecx, %ecx +; X86AVX2-NEXT: movl %ecx, %esi ; X86AVX2-NEXT: andl $7, %esi -; X86AVX2-NEXT: movl %eax, (%esp,%esi,4) +; X86AVX2-NEXT: movl %edx, (%esp,%esi,4) ; X86AVX2-NEXT: vmovaps (%esp), %ymm0 ; X86AVX2-NEXT: vmovaps %ymm0, {{[0-9]+}}(%esp) -; X86AVX2-NEXT: leal 1(%edx,%edx), %eax -; X86AVX2-NEXT: andl $7, %eax -; X86AVX2-NEXT: movl %ecx, 32(%esp,%eax,4) +; X86AVX2-NEXT: incl %ecx +; X86AVX2-NEXT: andl $7, %ecx +; X86AVX2-NEXT: movl %eax, 32(%esp,%ecx,4) ; X86AVX2-NEXT: vmovaps {{[0-9]+}}(%esp), %ymm0 ; X86AVX2-NEXT: leal -4(%ebp), %esp ; X86AVX2-NEXT: popl %esi @@ -2128,12 +2131,13 @@ define <4 x i64> @load_i64_v4i64(<4 x i64> %v, ptr %p, i32 %y) nounwind { ; X86AVX2-NEXT: movl (%ecx), %edx ; X86AVX2-NEXT: movl 4(%ecx), %ecx ; X86AVX2-NEXT: vmovaps %ymm0, (%esp) -; X86AVX2-NEXT: leal (%eax,%eax), %esi +; X86AVX2-NEXT: addl %eax, %eax +; X86AVX2-NEXT: movl %eax, %esi ; X86AVX2-NEXT: andl $7, %esi ; X86AVX2-NEXT: movl %edx, (%esp,%esi,4) ; X86AVX2-NEXT: vmovaps (%esp), %ymm0 ; X86AVX2-NEXT: vmovaps %ymm0, {{[0-9]+}}(%esp) -; X86AVX2-NEXT: leal 1(%eax,%eax), %eax +; X86AVX2-NEXT: incl %eax ; X86AVX2-NEXT: andl $7, %eax ; X86AVX2-NEXT: movl %ecx, 32(%esp,%eax,4) ; X86AVX2-NEXT: vmovaps {{[0-9]+}}(%esp), %ymm0 diff --git a/llvm/test/CodeGen/X86/instr-symbols.mir b/llvm/test/CodeGen/X86/instr-symbols.mir index a900288d70869a4884ce2b8460290e818236b243..7af6ca81810123f019cea9542d36b4628aa0228c 100644 --- a/llvm/test/CodeGen/X86/instr-symbols.mir +++ b/llvm/test/CodeGen/X86/instr-symbols.mir @@ -23,6 +23,7 @@ name: test # CHECK-LABEL: {{^}}test: tracksRegLiveness: true frameInfo: + adjustsStack: true hasCalls: true body: | bb.0.entry: diff --git a/llvm/test/CodeGen/X86/int-to-fp-demanded.ll b/llvm/test/CodeGen/X86/int-to-fp-demanded.ll new file mode 100644 index 0000000000000000000000000000000000000000..cdde03fb0534b98f33e7d5ba4c09670a4d11f7f8 --- /dev/null +++ b/llvm/test/CodeGen/X86/int-to-fp-demanded.ll @@ -0,0 +1,382 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s --check-prefix=X86 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=X64 + +declare void @use.i1(i1) +declare void @use.i32(i32) +define i32 @sitofp_signbit_only(i32 %i_in) nounwind { +; X86-LABEL: sitofp_signbit_only: +; X86: # %bb.0: +; X86-NEXT: subl $8, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, (%esp) +; X86-NEXT: fildl (%esp) +; X86-NEXT: fstps {{[0-9]+}}(%esp) +; X86-NEXT: movl $-2147483648, %eax # imm = 0x80000000 +; X86-NEXT: andl {{[0-9]+}}(%esp), %eax +; X86-NEXT: addl $8, %esp +; X86-NEXT: retl +; +; X64-LABEL: sitofp_signbit_only: +; X64: # %bb.0: +; X64-NEXT: cvtsi2ss %edi, %xmm0 +; X64-NEXT: movmskps %xmm0, %eax +; X64-NEXT: shll $31, %eax +; X64-NEXT: retq + %f = sitofp i32 %i_in to float + %i = bitcast float %f to i32 + %r = and i32 %i, 2147483648 + ret i32 %r +} + +define i32 @sitofp_signbit_only_okay_width(i16 %i_in) nounwind { +; X86-LABEL: sitofp_signbit_only_okay_width: +; X86: # %bb.0: +; X86-NEXT: subl $8, %esp +; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movw %ax, {{[0-9]+}}(%esp) +; X86-NEXT: filds {{[0-9]+}}(%esp) +; X86-NEXT: fstps {{[0-9]+}}(%esp) +; X86-NEXT: movl $-2147483648, %eax # imm = 0x80000000 +; X86-NEXT: andl {{[0-9]+}}(%esp), %eax +; X86-NEXT: addl $8, %esp +; X86-NEXT: retl +; +; X64-LABEL: sitofp_signbit_only_okay_width: +; X64: # %bb.0: +; X64-NEXT: movswl %di, %eax +; X64-NEXT: cvtsi2ss %eax, %xmm0 +; X64-NEXT: movmskps %xmm0, %eax +; X64-NEXT: shll $31, %eax +; X64-NEXT: retq + %f = sitofp i16 %i_in to float + %i = bitcast float %f to i32 + %r = and i32 %i, 2147483648 + ret i32 %r +} + +define i32 @sitofp_signbit_only_fail_bad_width1(i64 %i_in) nounwind { +; X86-LABEL: sitofp_signbit_only_fail_bad_width1: +; X86: # %bb.0: +; X86-NEXT: pushl %eax +; X86-NEXT: fildll {{[0-9]+}}(%esp) +; X86-NEXT: fstps (%esp) +; X86-NEXT: movl $-2147483648, %eax # imm = 0x80000000 +; X86-NEXT: andl (%esp), %eax +; X86-NEXT: popl %ecx +; X86-NEXT: retl +; +; X64-LABEL: sitofp_signbit_only_fail_bad_width1: +; X64: # %bb.0: +; X64-NEXT: cvtsi2ss %rdi, %xmm0 +; X64-NEXT: movmskps %xmm0, %eax +; X64-NEXT: shll $31, %eax +; X64-NEXT: retq + %f = sitofp i64 %i_in to float + %i = bitcast float %f to i32 + %r = and i32 %i, 2147483648 + ret i32 %r +} + +define <2 x i16> @sitofp_signbit_only_fail_bad_width2(i32 %i_in) nounwind { +; X86-LABEL: sitofp_signbit_only_fail_bad_width2: +; X86: # %bb.0: +; X86-NEXT: subl $8, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, (%esp) +; X86-NEXT: fildl (%esp) +; X86-NEXT: fstps {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, %edx +; X86-NEXT: shrl $16, %edx +; X86-NEXT: andl $32768, %eax # imm = 0x8000 +; X86-NEXT: andl $32768, %edx # imm = 0x8000 +; X86-NEXT: # kill: def $ax killed $ax killed $eax +; X86-NEXT: # kill: def $dx killed $dx killed $edx +; X86-NEXT: addl $8, %esp +; X86-NEXT: retl +; +; X64-LABEL: sitofp_signbit_only_fail_bad_width2: +; X64: # %bb.0: +; X64-NEXT: cvtsi2ss %edi, %xmm0 +; X64-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; X64-NEXT: retq + %f = sitofp i32 %i_in to float + %i2xi16 = bitcast float %f to <2 x i16> + %r = and <2 x i16> %i2xi16, <i16 32768, i16 32768> + ret <2 x i16> %r +} + +define i32 @sitofp_many_bits_fail(i32 %i_in) nounwind { +; X86-LABEL: sitofp_many_bits_fail: +; X86: # %bb.0: +; X86-NEXT: subl $8, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, (%esp) +; X86-NEXT: fildl (%esp) +; X86-NEXT: fstps {{[0-9]+}}(%esp) +; X86-NEXT: movl $-2147483647, %eax # imm = 0x80000001 +; X86-NEXT: andl {{[0-9]+}}(%esp), %eax +; X86-NEXT: addl $8, %esp +; X86-NEXT: retl +; +; X64-LABEL: sitofp_many_bits_fail: +; X64: # %bb.0: +; X64-NEXT: cvtsi2ss %edi, %xmm0 +; X64-NEXT: movd %xmm0, %eax +; X64-NEXT: andl $-2147483647, %eax # imm = 0x80000001 +; X64-NEXT: retq + %f = sitofp i32 %i_in to float + %i = bitcast float %f to i32 + %r = and i32 %i, 2147483649 + ret i32 %r +} + +define i32 @sitofp_multiuse_fail(i32 %i_in) nounwind { +; X86-LABEL: sitofp_multiuse_fail: +; X86: # %bb.0: +; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: fildl {{[0-9]+}}(%esp) +; X86-NEXT: fsts {{[0-9]+}}(%esp) +; X86-NEXT: fstps (%esp) +; X86-NEXT: calll use.i32@PLT +; X86-NEXT: movl $-2147483648, %eax # imm = 0x80000000 +; X86-NEXT: andl {{[0-9]+}}(%esp), %eax +; X86-NEXT: addl $12, %esp +; X86-NEXT: retl +; +; X64-LABEL: sitofp_multiuse_fail: +; X64: # %bb.0: +; X64-NEXT: pushq %rbx +; X64-NEXT: cvtsi2ss %edi, %xmm0 +; X64-NEXT: movd %xmm0, %ebx +; X64-NEXT: movl %ebx, %edi +; X64-NEXT: callq use.i32@PLT +; X64-NEXT: andl $-2147483648, %ebx # imm = 0x80000000 +; X64-NEXT: movl %ebx, %eax +; X64-NEXT: popq %rbx +; X64-NEXT: retq + %f = sitofp i32 %i_in to float + %i = bitcast float %f to i32 + call void @use.i32(i32 %i) + %r = and i32 %i, 2147483648 + ret i32 %r +} + +define i32 @sitofp_multiuse_okay(i32 %i_in) nounwind { +; X86-LABEL: sitofp_multiuse_okay: +; X86: # %bb.0: +; X86-NEXT: subl $12, %esp +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: fildl {{[0-9]+}}(%esp) +; X86-NEXT: fsts {{[0-9]+}}(%esp) +; X86-NEXT: fstps (%esp) +; X86-NEXT: calll use.i1@PLT +; X86-NEXT: movl $-2147483648, %eax # imm = 0x80000000 +; X86-NEXT: andl {{[0-9]+}}(%esp), %eax +; X86-NEXT: addl $12, %esp +; X86-NEXT: retl +; +; X64-LABEL: sitofp_multiuse_okay: +; X64: # %bb.0: +; X64-NEXT: pushq %rbx +; X64-NEXT: cvtsi2ss %edi, %xmm0 +; X64-NEXT: movd %xmm0, %ebx +; X64-NEXT: movl %ebx, %edi +; X64-NEXT: callq use.i1@PLT +; X64-NEXT: andl $-2147483648, %ebx # imm = 0x80000000 +; X64-NEXT: movl %ebx, %eax +; X64-NEXT: popq %rbx +; X64-NEXT: retq + %f = sitofp i32 %i_in to float + %i = bitcast float %f to i32 + %cmp = icmp slt i32 %i, 0 + call void @use.i1(i32 %i) + %r = and i32 %i, 2147483648 + ret i32 %r +} + +define i32 @uitofp_signbit_only(i32 %i_in) nounwind { +; X86-LABEL: uitofp_signbit_only: +; X86: # %bb.0: +; X86-NEXT: xorl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: uitofp_signbit_only: +; X64: # %bb.0: +; X64-NEXT: xorl %eax, %eax +; X64-NEXT: retq + %f = uitofp i32 %i_in to float + %i = bitcast float %f to i32 + %r = and i32 %i, 2147483648 + ret i32 %r +} + +define i32 @uitofp_signbit_only_okay_width(i16 %i_in) nounwind { +; X86-LABEL: uitofp_signbit_only_okay_width: +; X86: # %bb.0: +; X86-NEXT: xorl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: uitofp_signbit_only_okay_width: +; X64: # %bb.0: +; X64-NEXT: xorl %eax, %eax +; X64-NEXT: retq + %f = uitofp i16 %i_in to float + %i = bitcast float %f to i32 + %r = and i32 %i, 2147483648 + ret i32 %r +} + +define i32 @uitofp_signbit_only_okay_width1(i64 %i_in) nounwind { +; X86-LABEL: uitofp_signbit_only_okay_width1: +; X86: # %bb.0: +; X86-NEXT: xorl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: uitofp_signbit_only_okay_width1: +; X64: # %bb.0: +; X64-NEXT: xorl %eax, %eax +; X64-NEXT: retq + %f = uitofp i64 %i_in to float + %i = bitcast float %f to i32 + %r = and i32 %i, 2147483648 + ret i32 %r +} + +define <2 x i16> @uitofp_signbit_only_fail_bad_width2(i32 %i_in) nounwind { +; X86-LABEL: uitofp_signbit_only_fail_bad_width2: +; X86: # %bb.0: +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: andl $-8, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) +; X86-NEXT: fildll {{[0-9]+}}(%esp) +; X86-NEXT: fstps {{[0-9]+}}(%esp) +; X86-NEXT: movl $32768, %eax # imm = 0x8000 +; X86-NEXT: andl {{[0-9]+}}(%esp), %eax +; X86-NEXT: # kill: def $ax killed $ax killed $eax +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: movl %ebp, %esp +; X86-NEXT: popl %ebp +; X86-NEXT: retl +; +; X64-LABEL: uitofp_signbit_only_fail_bad_width2: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: cvtsi2ss %rax, %xmm0 +; X64-NEXT: andps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 +; X64-NEXT: retq + %f = uitofp i32 %i_in to float + %i2xi16 = bitcast float %f to <2 x i16> + %r = and <2 x i16> %i2xi16, <i16 32768, i16 32768> + ret <2 x i16> %r +} + +define i32 @uitofp_many_bits_fail(i32 %i_in) nounwind { +; X86-LABEL: uitofp_many_bits_fail: +; X86: # %bb.0: +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: andl $-8, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) +; X86-NEXT: fildll {{[0-9]+}}(%esp) +; X86-NEXT: fstps {{[0-9]+}}(%esp) +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: andl $1, %eax +; X86-NEXT: movl %ebp, %esp +; X86-NEXT: popl %ebp +; X86-NEXT: retl +; +; X64-LABEL: uitofp_many_bits_fail: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: cvtsi2ss %rax, %xmm0 +; X64-NEXT: movd %xmm0, %eax +; X64-NEXT: andl $1, %eax +; X64-NEXT: retq + %f = uitofp i32 %i_in to float + %i = bitcast float %f to i32 + %r = and i32 %i, 2147483649 + ret i32 %r +} + +define i32 @uitofp_multiuse_fail(i32 %i_in) nounwind { +; X86-LABEL: uitofp_multiuse_fail: +; X86: # %bb.0: +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: andl $-8, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) +; X86-NEXT: fildll {{[0-9]+}}(%esp) +; X86-NEXT: fstps (%esp) +; X86-NEXT: calll use.i32@PLT +; X86-NEXT: xorl %eax, %eax +; X86-NEXT: movl %ebp, %esp +; X86-NEXT: popl %ebp +; X86-NEXT: retl +; +; X64-LABEL: uitofp_multiuse_fail: +; X64: # %bb.0: +; X64-NEXT: pushq %rax +; X64-NEXT: movl %edi, %eax +; X64-NEXT: cvtsi2ss %rax, %xmm0 +; X64-NEXT: movd %xmm0, %edi +; X64-NEXT: callq use.i32@PLT +; X64-NEXT: xorl %eax, %eax +; X64-NEXT: popq %rcx +; X64-NEXT: retq + %f = uitofp i32 %i_in to float + %i = bitcast float %f to i32 + call void @use.i32(i32 %i) + %r = and i32 %i, 2147483648 + ret i32 %r +} + +define i32 @uitofp_multiuse_okay(i32 %i_in) nounwind { +; X86-LABEL: uitofp_multiuse_okay: +; X86: # %bb.0: +; X86-NEXT: pushl %ebp +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: andl $-8, %esp +; X86-NEXT: subl $16, %esp +; X86-NEXT: movl 8(%ebp), %eax +; X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; X86-NEXT: movl $0, {{[0-9]+}}(%esp) +; X86-NEXT: fildll {{[0-9]+}}(%esp) +; X86-NEXT: fstps (%esp) +; X86-NEXT: calll use.i1@PLT +; X86-NEXT: xorl %eax, %eax +; X86-NEXT: movl %ebp, %esp +; X86-NEXT: popl %ebp +; X86-NEXT: retl +; +; X64-LABEL: uitofp_multiuse_okay: +; X64: # %bb.0: +; X64-NEXT: pushq %rax +; X64-NEXT: movl %edi, %eax +; X64-NEXT: cvtsi2ss %rax, %xmm0 +; X64-NEXT: movd %xmm0, %edi +; X64-NEXT: callq use.i1@PLT +; X64-NEXT: xorl %eax, %eax +; X64-NEXT: popq %rcx +; X64-NEXT: retq + %f = uitofp i32 %i_in to float + %i = bitcast float %f to i32 + %cmp = icmp slt i32 %i, 0 + call void @use.i1(i32 %i) + %r = and i32 %i, 2147483648 + ret i32 %r +} diff --git a/llvm/test/CodeGen/X86/isel-select-cmov.ll b/llvm/test/CodeGen/X86/isel-select-cmov.ll index 0e5293c9000f04d4aa59da57a523629cffe6fc37..39a20bf6637bb84cf8a8848b021abf68c61b4bfd 100644 --- a/llvm/test/CodeGen/X86/isel-select-cmov.ll +++ b/llvm/test/CodeGen/X86/isel-select-cmov.ll @@ -13,6 +13,8 @@ ; RUN: llc < %s -global-isel -global-isel-abort=1 -mtriple=i686-apple-darwin10 -verify-machineinstrs | FileCheck %s --check-prefix=GISEL-X86 ; RUN: llc < %s -global-isel -global-isel-abort=1 -mtriple=i686-apple-darwin10 -verify-machineinstrs -mattr=+cmov | FileCheck %s --check-prefix=GISEL-X86-CMOV +; RUN: llc < %s -fast-isel -fast-isel-abort=1 -mtriple=x86_64-apple-darwin10 -verify-machineinstrs -mattr=+ndd | FileCheck %s --check-prefix=NDD + ; Test conditional move for the supported types (i16, i32, and i32) and ; conditon input (argument or cmp). ; When cmov is not available (i8 type or X86), the branch is expected. @@ -114,6 +116,16 @@ define zeroext i8 @select_cmov_i8(i1 zeroext %cond, i8 zeroext %a, i8 zeroext %b ; GISEL-X86-CMOV-NEXT: cmovnew %dx, %ax ; GISEL-X86-CMOV-NEXT: ## kill: def $al killed $al killed $eax ; GISEL-X86-CMOV-NEXT: retl +; +; NDD-LABEL: select_cmov_i8: +; NDD: ## %bb.0: +; NDD-NEXT: testb $1, %dil +; NDD-NEXT: jne LBB0_2 +; NDD-NEXT: ## %bb.1: +; NDD-NEXT: movl %edx, %esi +; NDD-NEXT: LBB0_2: +; NDD-NEXT: movzbl %sil, %eax +; NDD-NEXT: retq %1 = select i1 %cond, i8 %a, i8 %b ret i8 %1 } @@ -207,6 +219,13 @@ define zeroext i16 @select_cmov_i16(i1 zeroext %cond, i16 zeroext %a, i16 zeroex ; GISEL-X86-CMOV-NEXT: cmovnew %dx, %ax ; GISEL-X86-CMOV-NEXT: ## kill: def $ax killed $ax killed $eax ; GISEL-X86-CMOV-NEXT: retl +; +; NDD-LABEL: select_cmov_i16: +; NDD: ## %bb.0: +; NDD-NEXT: testb $1, %dil +; NDD-NEXT: cmovnew %si, %dx, %ax +; NDD-NEXT: movzwl %ax, %eax +; NDD-NEXT: retq %1 = select i1 %cond, i16 %a, i16 %b ret i16 %1 } @@ -305,6 +324,13 @@ define zeroext i16 @select_cmp_cmov_i16(i16 zeroext %a, i16 zeroext %b) { ; GISEL-X86-CMOV-NEXT: cmovew %cx, %ax ; GISEL-X86-CMOV-NEXT: ## kill: def $ax killed $ax killed $eax ; GISEL-X86-CMOV-NEXT: retl +; +; NDD-LABEL: select_cmp_cmov_i16: +; NDD: ## %bb.0: +; NDD-NEXT: cmpw %si, %di +; NDD-NEXT: cmovbw %di, %si, %ax +; NDD-NEXT: movzwl %ax, %eax +; NDD-NEXT: retq %1 = icmp ult i16 %a, %b %2 = select i1 %1, i16 %a, i16 %b ret i16 %2 @@ -391,6 +417,12 @@ define i32 @select_cmov_i32(i1 zeroext %cond, i32 %a, i32 %b) { ; GISEL-X86-CMOV-NEXT: testl %ecx, %ecx ; GISEL-X86-CMOV-NEXT: cmovnel {{[0-9]+}}(%esp), %eax ; GISEL-X86-CMOV-NEXT: retl +; +; NDD-LABEL: select_cmov_i32: +; NDD: ## %bb.0: +; NDD-NEXT: testb $1, %dil +; NDD-NEXT: cmovnel %esi, %edx, %eax +; NDD-NEXT: retq %1 = select i1 %cond, i32 %a, i32 %b ret i32 %1 } @@ -482,6 +514,12 @@ define i32 @select_cmp_cmov_i32(i32 %a, i32 %b) { ; GISEL-X86-CMOV-NEXT: andl $1, %edx ; GISEL-X86-CMOV-NEXT: cmovel %ecx, %eax ; GISEL-X86-CMOV-NEXT: retl +; +; NDD-LABEL: select_cmp_cmov_i32: +; NDD: ## %bb.0: +; NDD-NEXT: cmpl %esi, %edi +; NDD-NEXT: cmovbl %edi, %esi, %eax +; NDD-NEXT: retq %1 = icmp ult i32 %a, %b %2 = select i1 %1, i32 %a, i32 %b ret i32 %2 @@ -584,6 +622,12 @@ define i64 @select_cmov_i64(i1 zeroext %cond, i64 %a, i64 %b) { ; GISEL-X86-CMOV-NEXT: cmovnel {{[0-9]+}}(%esp), %eax ; GISEL-X86-CMOV-NEXT: cmovnel {{[0-9]+}}(%esp), %edx ; GISEL-X86-CMOV-NEXT: retl +; +; NDD-LABEL: select_cmov_i64: +; NDD: ## %bb.0: +; NDD-NEXT: testb $1, %dil +; NDD-NEXT: cmovneq %rsi, %rdx, %rax +; NDD-NEXT: retq %1 = select i1 %cond, i64 %a, i64 %b ret i64 %1 } @@ -754,6 +798,12 @@ define i64 @select_cmp_cmov_i64(i64 %a, i64 %b) nounwind { ; GISEL-X86-CMOV-NEXT: popl %ebx ; GISEL-X86-CMOV-NEXT: popl %ebp ; GISEL-X86-CMOV-NEXT: retl +; +; NDD-LABEL: select_cmp_cmov_i64: +; NDD: ## %bb.0: +; NDD-NEXT: cmpq %rsi, %rdi +; NDD-NEXT: cmovbq %rdi, %rsi, %rax +; NDD-NEXT: retq %1 = icmp ult i64 %a, %b %2 = select i1 %1, i64 %a, i64 %b ret i64 %2 diff --git a/llvm/test/CodeGen/X86/isel-traps.ll b/llvm/test/CodeGen/X86/isel-traps.ll new file mode 100644 index 0000000000000000000000000000000000000000..c207387166a6bc63375a5bdef5e7bf31d9e84f2f --- /dev/null +++ b/llvm/test/CodeGen/X86/isel-traps.ll @@ -0,0 +1,73 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-linux-gnu | FileCheck %s --check-prefixes=ALL,X64 +; RUN: llc < %s -fast-isel -fast-isel-abort=1 -mtriple=x86_64-linux-gnu | FileCheck %s --check-prefixes=ALL,X64 +; RUN: llc < %s -global-isel -global-isel-abort=1 -mtriple=x86_64-linux-gnu | FileCheck %s --check-prefixes=ALL,GISEL-X64 +; RUN: llc < %s -mtriple=i686-linux-gnu | FileCheck %s --check-prefixes=ALL,X86 +; RUN: llc < %s -fast-isel -fast-isel-abort=1 -mtriple=i686-linux-gnu | FileCheck %s --check-prefixes=ALL,X86 +; RUN: llc < %s -global-isel -global-isel-abort=1 -mtriple=i686-linux-gnu | FileCheck %s --check-prefixes=ALL,GISEL-X86 + +declare void @llvm.trap() + +define void @test_trap() { +; ALL-LABEL: test_trap: +; ALL: # %bb.0: +; ALL-NEXT: ud2 +; ALL-NEXT: ret{{[l|q]}} + tail call void @llvm.trap() + ret void +} + +define void @test_debugtrap() { +; ALL-LABEL: test_debugtrap: +; ALL: # %bb.0: +; ALL-NEXT: int3 +; ALL-NEXT: ret{{[l|q]}} + tail call void @llvm.debugtrap() + ret void +} + +define void @test_ubsantrap() { +; ALL-LABEL: test_ubsantrap: +; ALL: # %bb.0: +; ALL-NEXT: ud1l 12(%eax), %eax +; ALL-NEXT: ret{{[l|q]}} + call void @llvm.ubsantrap(i8 12) + ret void +} + +define void @test_ubsantrap_custom() nounwind { +; X64-LABEL: test_ubsantrap_custom: +; X64: # %bb.0: +; X64-NEXT: pushq %rax +; X64-NEXT: movl $42, %edi +; X64-NEXT: callq guide@PLT +; X64-NEXT: popq %rax +; X64-NEXT: retq +; +; GISEL-X64-LABEL: test_ubsantrap_custom: +; GISEL-X64: # %bb.0: +; GISEL-X64-NEXT: pushq %rax +; GISEL-X64-NEXT: movl $42, %edi +; GISEL-X64-NEXT: callq guide +; GISEL-X64-NEXT: popq %rax +; GISEL-X64-NEXT: retq +; +; X86-LABEL: test_ubsantrap_custom: +; X86: # %bb.0: +; X86-NEXT: subl $12, %esp +; X86-NEXT: movl $42, (%esp) +; X86-NEXT: calll guide +; X86-NEXT: addl $12, %esp +; X86-NEXT: retl +; +; GISEL-X86-LABEL: test_ubsantrap_custom: +; GISEL-X86: # %bb.0: +; GISEL-X86-NEXT: subl $12, %esp +; GISEL-X86-NEXT: movl $42, %eax +; GISEL-X86-NEXT: movl %eax, (%esp) +; GISEL-X86-NEXT: calll guide +; GISEL-X86-NEXT: addl $12, %esp +; GISEL-X86-NEXT: retl + call void @llvm.ubsantrap(i8 42) "trap-func-name"="guide" + ret void +} diff --git a/llvm/test/CodeGen/X86/known-never-zero.ll b/llvm/test/CodeGen/X86/known-never-zero.ll index cc9862769f2b66de341cf030e1ec6fe95f426912..39d02f9112f4fcbff8b3156b406e73664c8be6fe 100644 --- a/llvm/test/CodeGen/X86/known-never-zero.ll +++ b/llvm/test/CodeGen/X86/known-never-zero.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=CHECK +; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+sse2 | FileCheck %s --check-prefixes=X86 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefixes=X64 ;; Use cttz to test if we properly prove never-zero. There is a very ;; simple transform from cttz -> cttz_zero_undef if its operand is @@ -9,50 +10,82 @@ declare i32 @llvm.uadd.sat.i32(i32, i32) declare i32 @llvm.umax.i32(i32, i32) declare i32 @llvm.umin.i32(i32, i32) declare i32 @llvm.smin.i32(i32, i32) +declare <4 x i32> @llvm.smin.v4i32(<4 x i32>, <4 x i32>) declare i32 @llvm.smax.i32(i32, i32) +declare <4 x i32> @llvm.smax.v4i32(<4 x i32>, <4 x i32>) declare i32 @llvm.bswap.i32(i32) declare i32 @llvm.bitreverse.i32(i32) declare i32 @llvm.ctpop.i32(i32) +declare <4 x i32> @llvm.ctpop.v4i32(<4 x i32>) declare i32 @llvm.abs.i32(i32, i1) declare i32 @llvm.fshl.i32(i32, i32, i32) declare i32 @llvm.fshr.i32(i32, i32, i32) define i32 @or_known_nonzero(i32 %x) { -; CHECK-LABEL: or_known_nonzero: -; CHECK: # %bb.0: -; CHECK-NEXT: orl $1, %edi -; CHECK-NEXT: rep bsfl %edi, %eax -; CHECK-NEXT: retq +; X86-LABEL: or_known_nonzero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: orl $1, %eax +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: or_known_nonzero: +; X64: # %bb.0: +; X64-NEXT: orl $1, %edi +; X64-NEXT: rep bsfl %edi, %eax +; X64-NEXT: retq %z = or i32 %x, 1 %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @or_maybe_zero(i32 %x, i32 %y) { -; CHECK-LABEL: or_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: orl %esi, %edi -; CHECK-NEXT: je .LBB1_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %edi, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB1_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: or_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: orl {{[0-9]+}}(%esp), %eax +; X86-NEXT: je .LBB1_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB1_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: or_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: orl %esi, %edi +; X64-NEXT: je .LBB1_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %edi, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB1_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %z = or i32 %x, %y %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @select_known_nonzero(i1 %c, i32 %x) { -; CHECK-LABEL: select_known_nonzero: -; CHECK: # %bb.0: -; CHECK-NEXT: orl $1, %esi -; CHECK-NEXT: testb $1, %dil -; CHECK-NEXT: movl $122, %eax -; CHECK-NEXT: cmovnel %esi, %eax -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq +; X86-LABEL: select_known_nonzero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: orl $1, %eax +; X86-NEXT: testb $1, {{[0-9]+}}(%esp) +; X86-NEXT: movl $122, %ecx +; X86-NEXT: cmovnel %eax, %ecx +; X86-NEXT: rep bsfl %ecx, %eax +; X86-NEXT: retl +; +; X64-LABEL: select_known_nonzero: +; X64: # %bb.0: +; X64-NEXT: orl $1, %esi +; X64-NEXT: testb $1, %dil +; X64-NEXT: movl $122, %eax +; X64-NEXT: cmovnel %esi, %eax +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq %y = or i32 %x, 1 %z = select i1 %c, i32 %y, i32 122 %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -60,20 +93,36 @@ define i32 @select_known_nonzero(i1 %c, i32 %x) { } define i32 @select_maybe_zero(i1 %c, i32 %x) { -; CHECK-LABEL: select_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: orl $1, %esi -; CHECK-NEXT: xorl %eax, %eax -; CHECK-NEXT: testb $1, %dil -; CHECK-NEXT: cmovnel %esi, %eax -; CHECK-NEXT: testl %eax, %eax -; CHECK-NEXT: je .LBB3_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB3_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: select_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: orl $1, %ecx +; X86-NEXT: xorl %eax, %eax +; X86-NEXT: testb $1, {{[0-9]+}}(%esp) +; X86-NEXT: cmovnel %ecx, %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB3_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB3_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: select_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: orl $1, %esi +; X64-NEXT: xorl %eax, %eax +; X64-NEXT: testb $1, %dil +; X64-NEXT: cmovnel %esi, %eax +; X64-NEXT: testl %eax, %eax +; X64-NEXT: je .LBB3_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB3_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %y = or i32 %x, 1 %z = select i1 %c, i32 %y, i32 0 %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -81,28 +130,45 @@ define i32 @select_maybe_zero(i1 %c, i32 %x) { } define i32 @shl_known_nonzero_1s_bit_set(i32 %x) { -; CHECK-LABEL: shl_known_nonzero_1s_bit_set: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: movl $123, %eax -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shll %cl, %eax -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq +; X86-LABEL: shl_known_nonzero_1s_bit_set: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $123, %eax +; X86-NEXT: shll %cl, %eax +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: shl_known_nonzero_1s_bit_set: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: movl $123, %eax +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: shll %cl, %eax +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq %z = shl i32 123, %x %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @shl_known_nonzero_nsw(i32 %x, i32 %yy) { -; CHECK-LABEL: shl_known_nonzero_nsw: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: orl $256, %esi # imm = 0x100 -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shll %cl, %esi -; CHECK-NEXT: rep bsfl %esi, %eax -; CHECK-NEXT: retq +; X86-LABEL: shl_known_nonzero_nsw: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $256, %eax # imm = 0x100 +; X86-NEXT: orl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shll %cl, %eax +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: shl_known_nonzero_nsw: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: orl $256, %esi # imm = 0x100 +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: shll %cl, %esi +; X64-NEXT: rep bsfl %esi, %eax +; X64-NEXT: retq %y = or i32 %yy, 256 %z = shl nsw i32 %y, %x %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -110,14 +176,23 @@ define i32 @shl_known_nonzero_nsw(i32 %x, i32 %yy) { } define i32 @shl_known_nonzero_nuw(i32 %x, i32 %yy) { -; CHECK-LABEL: shl_known_nonzero_nuw: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: orl $256, %esi # imm = 0x100 -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shll %cl, %esi -; CHECK-NEXT: rep bsfl %esi, %eax -; CHECK-NEXT: retq +; X86-LABEL: shl_known_nonzero_nuw: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $256, %eax # imm = 0x100 +; X86-NEXT: orl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shll %cl, %eax +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: shl_known_nonzero_nuw: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: orl $256, %esi # imm = 0x100 +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: shll %cl, %esi +; X64-NEXT: rep bsfl %esi, %eax +; X64-NEXT: retq %y = or i32 %yy, 256 %z = shl nuw i32 %y, %x %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -125,67 +200,116 @@ define i32 @shl_known_nonzero_nuw(i32 %x, i32 %yy) { } define i32 @shl_maybe_zero(i32 %x, i32 %y) { -; CHECK-LABEL: shl_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shll %cl, %esi -; CHECK-NEXT: testl %esi, %esi -; CHECK-NEXT: je .LBB7_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %esi, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB7_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: shl_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shll %cl, %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB7_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB7_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: shl_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: shll %cl, %esi +; X64-NEXT: testl %esi, %esi +; X64-NEXT: je .LBB7_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %esi, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB7_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %z = shl nuw nsw i32 %y, %x %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @uaddsat_known_nonzero(i32 %x) { -; CHECK-LABEL: uaddsat_known_nonzero: -; CHECK: # %bb.0: -; CHECK-NEXT: incl %edi -; CHECK-NEXT: movl $-1, %eax -; CHECK-NEXT: cmovnel %edi, %eax -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq +; X86-LABEL: uaddsat_known_nonzero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: incl %eax +; X86-NEXT: movl $-1, %ecx +; X86-NEXT: cmovnel %eax, %ecx +; X86-NEXT: rep bsfl %ecx, %eax +; X86-NEXT: retl +; +; X64-LABEL: uaddsat_known_nonzero: +; X64: # %bb.0: +; X64-NEXT: incl %edi +; X64-NEXT: movl $-1, %eax +; X64-NEXT: cmovnel %edi, %eax +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq %z = call i32 @llvm.uadd.sat.i32(i32 %x, i32 1) %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @uaddsat_maybe_zero(i32 %x, i32 %y) { -; CHECK-LABEL: uaddsat_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: addl %esi, %edi -; CHECK-NEXT: movl $-1, %eax -; CHECK-NEXT: cmovael %edi, %eax -; CHECK-NEXT: testl %eax, %eax -; CHECK-NEXT: je .LBB9_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB9_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: uaddsat_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: addl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $-1, %eax +; X86-NEXT: cmovael %ecx, %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB9_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB9_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: uaddsat_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: addl %esi, %edi +; X64-NEXT: movl $-1, %eax +; X64-NEXT: cmovael %edi, %eax +; X64-NEXT: testl %eax, %eax +; X64-NEXT: je .LBB9_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB9_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %z = call i32 @llvm.uadd.sat.i32(i32 %x, i32 %y) %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @umax_known_nonzero(i32 %x, i32 %y) { -; CHECK-LABEL: umax_known_nonzero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %esi, %ecx -; CHECK-NEXT: movl $4, %eax -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shll %cl, %eax -; CHECK-NEXT: cmpl %eax, %edi -; CHECK-NEXT: cmoval %edi, %eax -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq +; X86-LABEL: umax_known_nonzero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $4, %edx +; X86-NEXT: shll %cl, %edx +; X86-NEXT: cmpl %edx, %eax +; X86-NEXT: cmoval %eax, %edx +; X86-NEXT: rep bsfl %edx, %eax +; X86-NEXT: retl +; +; X64-LABEL: umax_known_nonzero: +; X64: # %bb.0: +; X64-NEXT: movl %esi, %ecx +; X64-NEXT: movl $4, %eax +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: shll %cl, %eax +; X64-NEXT: cmpl %eax, %edi +; X64-NEXT: cmoval %edi, %eax +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq %yy = shl nuw i32 4, %y %z = call i32 @llvm.umax.i32(i32 %x, i32 %yy) %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -193,35 +317,62 @@ define i32 @umax_known_nonzero(i32 %x, i32 %y) { } define i32 @umax_maybe_zero(i32 %x, i32 %y) { -; CHECK-LABEL: umax_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: cmpl %esi, %edi -; CHECK-NEXT: cmoval %edi, %esi -; CHECK-NEXT: testl %esi, %esi -; CHECK-NEXT: je .LBB11_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %esi, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB11_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: umax_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: cmpl %eax, %ecx +; X86-NEXT: cmoval %ecx, %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB11_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB11_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: umax_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: cmpl %esi, %edi +; X64-NEXT: cmoval %edi, %esi +; X64-NEXT: testl %esi, %esi +; X64-NEXT: je .LBB11_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %esi, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB11_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %z = call i32 @llvm.umax.i32(i32 %x, i32 %y) %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @umin_known_nonzero(i32 %xx, i32 %yy) { -; CHECK-LABEL: umin_known_nonzero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: movl $4, %eax -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shll %cl, %eax -; CHECK-NEXT: addl $4, %esi -; CHECK-NEXT: cmpl %esi, %eax -; CHECK-NEXT: cmovbl %eax, %esi -; CHECK-NEXT: rep bsfl %esi, %eax -; CHECK-NEXT: retq +; X86-LABEL: umin_known_nonzero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $4, %edx +; X86-NEXT: shll %cl, %edx +; X86-NEXT: addl $4, %eax +; X86-NEXT: cmpl %eax, %edx +; X86-NEXT: cmovbl %edx, %eax +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: umin_known_nonzero: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: movl $4, %eax +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: shll %cl, %eax +; X64-NEXT: addl $4, %esi +; X64-NEXT: cmpl %esi, %eax +; X64-NEXT: cmovbl %eax, %esi +; X64-NEXT: rep bsfl %esi, %eax +; X64-NEXT: retq %x = shl nuw i32 4, %xx %y = add nuw nsw i32 %yy, 4 %z = call i32 @llvm.umin.i32(i32 %x, i32 %y) @@ -230,36 +381,63 @@ define i32 @umin_known_nonzero(i32 %xx, i32 %yy) { } define i32 @umin_maybe_zero(i32 %x, i32 %y) { -; CHECK-LABEL: umin_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: cmpl $54, %edi -; CHECK-NEXT: movl $54, %eax -; CHECK-NEXT: cmovbl %edi, %eax -; CHECK-NEXT: testl %eax, %eax -; CHECK-NEXT: je .LBB13_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB13_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: umin_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: cmpl $54, %ecx +; X86-NEXT: movl $54, %eax +; X86-NEXT: cmovbl %ecx, %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB13_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB13_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: umin_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: cmpl $54, %edi +; X64-NEXT: movl $54, %eax +; X64-NEXT: cmovbl %edi, %eax +; X64-NEXT: testl %eax, %eax +; X64-NEXT: je .LBB13_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB13_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %z = call i32 @llvm.umin.i32(i32 %x, i32 54) %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @smin_known_nonzero(i32 %xx, i32 %yy) { -; CHECK-LABEL: smin_known_nonzero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: movl $4, %eax -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shll %cl, %eax -; CHECK-NEXT: addl $4, %esi -; CHECK-NEXT: cmpl %esi, %eax -; CHECK-NEXT: cmovll %eax, %esi -; CHECK-NEXT: rep bsfl %esi, %eax -; CHECK-NEXT: retq +; X86-LABEL: smin_known_nonzero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $4, %edx +; X86-NEXT: shll %cl, %edx +; X86-NEXT: addl $4, %eax +; X86-NEXT: cmpl %eax, %edx +; X86-NEXT: cmovll %edx, %eax +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: smin_known_nonzero: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: movl $4, %eax +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: shll %cl, %eax +; X64-NEXT: addl $4, %esi +; X64-NEXT: cmpl %esi, %eax +; X64-NEXT: cmovll %eax, %esi +; X64-NEXT: rep bsfl %esi, %eax +; X64-NEXT: retq %x = shl nuw i32 4, %xx %y = add nuw nsw i32 %yy, 4 %z = call i32 @llvm.smin.i32(i32 %x, i32 %y) @@ -267,37 +445,120 @@ define i32 @smin_known_nonzero(i32 %xx, i32 %yy) { ret i32 %r } +define i32 @smin_known_zero(i32 %x, i32 %y) { +; X86-LABEL: smin_known_zero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: cmpl $-54, %eax +; X86-NEXT: movl $-54, %ecx +; X86-NEXT: cmovll %eax, %ecx +; X86-NEXT: rep bsfl %ecx, %eax +; X86-NEXT: retl +; +; X64-LABEL: smin_known_zero: +; X64: # %bb.0: +; X64-NEXT: cmpl $-54, %edi +; X64-NEXT: movl $-54, %eax +; X64-NEXT: cmovll %edi, %eax +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq + %z = call i32 @llvm.smin.i32(i32 %x, i32 -54) + %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) + ret i32 %r +} + +define <4 x i32> @smin_known_zero_vec(<4 x i32> %x, <4 x i32> %y) { +; X86-LABEL: smin_known_zero_vec: +; X86: # %bb.0: +; X86-NEXT: movdqa {{.*#+}} xmm1 = [4294967242,4294967273,4294967284,4294967295] +; X86-NEXT: movdqa %xmm1, %xmm2 +; X86-NEXT: pcmpgtd %xmm0, %xmm2 +; X86-NEXT: pand %xmm2, %xmm0 +; X86-NEXT: pandn %xmm1, %xmm2 +; X86-NEXT: por %xmm2, %xmm0 +; X86-NEXT: pcmpeqd %xmm1, %xmm1 +; X86-NEXT: paddd %xmm0, %xmm1 +; X86-NEXT: pand %xmm1, %xmm0 +; X86-NEXT: pxor %xmm1, %xmm1 +; X86-NEXT: pcmpeqd %xmm1, %xmm0 +; X86-NEXT: psrld $31, %xmm0 +; X86-NEXT: retl +; +; X64-LABEL: smin_known_zero_vec: +; X64: # %bb.0: +; X64-NEXT: vpminsd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; X64-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1 +; X64-NEXT: vpaddd %xmm1, %xmm0, %xmm1 +; X64-NEXT: vpand %xmm1, %xmm0, %xmm0 +; X64-NEXT: vpxor %xmm1, %xmm1, %xmm1 +; X64-NEXT: vpcmpeqd %xmm1, %xmm0, %xmm0 +; X64-NEXT: vpsrld $31, %xmm0, %xmm0 +; X64-NEXT: retq + %z = call <4 x i32> @llvm.smin.v4i32(<4 x i32> %x, <4 x i32> <i32 -54, i32 -23, i32 -12, i32 -1>) + %r = call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %z) + %3 = icmp eq <4 x i32> %r, <i32 1, i32 1, i32 1, i32 1> + %ret = zext <4 x i1> %3 to <4 x i32> + ret <4 x i32> %ret +} + define i32 @smin_maybe_zero(i32 %x, i32 %y) { -; CHECK-LABEL: smin_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: cmpl $54, %edi -; CHECK-NEXT: movl $54, %eax -; CHECK-NEXT: cmovll %edi, %eax -; CHECK-NEXT: testl %eax, %eax -; CHECK-NEXT: je .LBB15_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB15_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: smin_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: cmpl $54, %ecx +; X86-NEXT: movl $54, %eax +; X86-NEXT: cmovll %ecx, %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB17_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB17_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: smin_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: cmpl $54, %edi +; X64-NEXT: movl $54, %eax +; X64-NEXT: cmovll %edi, %eax +; X64-NEXT: testl %eax, %eax +; X64-NEXT: je .LBB17_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB17_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %z = call i32 @llvm.smin.i32(i32 %x, i32 54) %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @smax_known_nonzero(i32 %xx, i32 %yy) { -; CHECK-LABEL: smax_known_nonzero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: movl $4, %eax -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shll %cl, %eax -; CHECK-NEXT: addl $4, %esi -; CHECK-NEXT: cmpl %esi, %eax -; CHECK-NEXT: cmovgl %eax, %esi -; CHECK-NEXT: rep bsfl %esi, %eax -; CHECK-NEXT: retq +; X86-LABEL: smax_known_nonzero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $4, %edx +; X86-NEXT: shll %cl, %edx +; X86-NEXT: addl $4, %eax +; X86-NEXT: cmpl %eax, %edx +; X86-NEXT: cmovgl %edx, %eax +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: smax_known_nonzero: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: movl $4, %eax +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: shll %cl, %eax +; X64-NEXT: addl $4, %esi +; X64-NEXT: cmpl %esi, %eax +; X64-NEXT: cmovgl %eax, %esi +; X64-NEXT: rep bsfl %esi, %eax +; X64-NEXT: retq %x = shl nuw i32 4, %xx %y = add nuw nsw i32 %yy, 4 %z = call i32 @llvm.smax.i32(i32 %x, i32 %y) @@ -306,35 +567,125 @@ define i32 @smax_known_nonzero(i32 %xx, i32 %yy) { } define i32 @smax_maybe_zero(i32 %x, i32 %y) { -; CHECK-LABEL: smax_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: cmpl $55, %edi -; CHECK-NEXT: movl $54, %eax -; CHECK-NEXT: cmovgel %edi, %eax -; CHECK-NEXT: bsfl %eax, %ecx -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: cmovnel %ecx, %eax -; CHECK-NEXT: retq +; X86-LABEL: smax_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: cmpl $55, %eax +; X86-NEXT: movl $54, %ecx +; X86-NEXT: cmovgel %eax, %ecx +; X86-NEXT: rep bsfl %ecx, %eax +; X86-NEXT: retl +; +; X64-LABEL: smax_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: cmpl $55, %edi +; X64-NEXT: movl $54, %eax +; X64-NEXT: cmovgel %edi, %eax +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq %z = call i32 @llvm.smax.i32(i32 %x, i32 54) %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } +define <4 x i32> @smax_known_zero_vec(<4 x i32> %x, <4 x i32> %y) { +; X86-LABEL: smax_known_zero_vec: +; X86: # %bb.0: +; X86-NEXT: movdqa {{.*#+}} xmm1 = [54,23,12,1] +; X86-NEXT: movdqa %xmm0, %xmm2 +; X86-NEXT: pcmpgtd %xmm1, %xmm2 +; X86-NEXT: pand %xmm2, %xmm0 +; X86-NEXT: pandn %xmm1, %xmm2 +; X86-NEXT: por %xmm2, %xmm0 +; X86-NEXT: pcmpeqd %xmm1, %xmm1 +; X86-NEXT: paddd %xmm0, %xmm1 +; X86-NEXT: pxor {{\.?LCPI[0-9]+_[0-9]+}}, %xmm1 +; X86-NEXT: pxor %xmm1, %xmm0 +; X86-NEXT: pcmpgtd %xmm1, %xmm0 +; X86-NEXT: psrld $31, %xmm0 +; X86-NEXT: retl +; +; X64-LABEL: smax_known_zero_vec: +; X64: # %bb.0: +; X64-NEXT: vpmaxsd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; X64-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1 +; X64-NEXT: vpaddd %xmm1, %xmm0, %xmm1 +; X64-NEXT: vpxor %xmm1, %xmm0, %xmm0 +; X64-NEXT: vpminud %xmm1, %xmm0, %xmm1 +; X64-NEXT: vpcmpeqd %xmm1, %xmm0, %xmm0 +; X64-NEXT: vpandn {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; X64-NEXT: retq + %z = call <4 x i32> @llvm.smax.v4i32(<4 x i32> %x, <4 x i32> <i32 54, i32 23, i32 12, i32 1>) + %r = call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %z) + %3 = icmp eq <4 x i32> %r, <i32 1, i32 1, i32 1, i32 1> + %ret = zext <4 x i1> %3 to <4 x i32> + ret <4 x i32> %ret +} + +define i32 @smax_known_zero(i32 %x, i32 %y) { +; X86-LABEL: smax_known_zero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: testl %ecx, %ecx +; X86-NEXT: movl $-1, %eax +; X86-NEXT: cmovnsl %ecx, %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB21_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB21_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: smax_known_zero: +; X64: # %bb.0: +; X64-NEXT: testl %edi, %edi +; X64-NEXT: movl $-1, %eax +; X64-NEXT: cmovnsl %edi, %eax +; X64-NEXT: testl %eax, %eax +; X64-NEXT: je .LBB21_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB21_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq + %z = call i32 @llvm.smax.i32(i32 %x, i32 -1) + %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) + ret i32 %r +} + define i32 @rotr_known_nonzero(i32 %xx, i32 %y) { -; CHECK-LABEL: rotr_known_nonzero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %esi, %ecx -; CHECK-NEXT: orl $256, %edi # imm = 0x100 -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: rorl %cl, %edi -; CHECK-NEXT: testl %edi, %edi -; CHECK-NEXT: je .LBB18_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %edi, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB18_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: rotr_known_nonzero: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $256, %eax # imm = 0x100 +; X86-NEXT: orl {{[0-9]+}}(%esp), %eax +; X86-NEXT: rorl %cl, %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB22_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB22_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: rotr_known_nonzero: +; X64: # %bb.0: +; X64-NEXT: movl %esi, %ecx +; X64-NEXT: orl $256, %edi # imm = 0x100 +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: rorl %cl, %edi +; X64-NEXT: testl %edi, %edi +; X64-NEXT: je .LBB22_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %edi, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB22_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %x = or i32 %xx, 256 %shr = lshr i32 %x, %y %sub = sub i32 32, %y @@ -345,19 +696,33 @@ define i32 @rotr_known_nonzero(i32 %xx, i32 %y) { } define i32 @rotr_maybe_zero(i32 %x, i32 %y) { -; CHECK-LABEL: rotr_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %esi, %ecx -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: rorl %cl, %edi -; CHECK-NEXT: testl %edi, %edi -; CHECK-NEXT: je .LBB19_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %edi, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB19_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: rotr_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: rorl %cl, %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB23_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB23_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: rotr_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: movl %esi, %ecx +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: rorl %cl, %edi +; X64-NEXT: testl %edi, %edi +; X64-NEXT: je .LBB23_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %edi, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB23_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %shr = lshr i32 %x, %y %sub = sub i32 32, %y %shl = shl i32 %x, %sub @@ -367,14 +732,23 @@ define i32 @rotr_maybe_zero(i32 %x, i32 %y) { } define i32 @rotr_with_fshr_known_nonzero(i32 %xx, i32 %y) { -; CHECK-LABEL: rotr_with_fshr_known_nonzero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %esi, %ecx -; CHECK-NEXT: orl $256, %edi # imm = 0x100 -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: rorl %cl, %edi -; CHECK-NEXT: rep bsfl %edi, %eax -; CHECK-NEXT: retq +; X86-LABEL: rotr_with_fshr_known_nonzero: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $256, %eax # imm = 0x100 +; X86-NEXT: orl {{[0-9]+}}(%esp), %eax +; X86-NEXT: rorl %cl, %eax +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: rotr_with_fshr_known_nonzero: +; X64: # %bb.0: +; X64-NEXT: movl %esi, %ecx +; X64-NEXT: orl $256, %edi # imm = 0x100 +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: rorl %cl, %edi +; X64-NEXT: rep bsfl %edi, %eax +; X64-NEXT: retq %x = or i32 %xx, 256 %z = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %y) %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -382,39 +756,68 @@ define i32 @rotr_with_fshr_known_nonzero(i32 %xx, i32 %y) { } define i32 @rotr_with_fshr_maybe_zero(i32 %x, i32 %y) { -; CHECK-LABEL: rotr_with_fshr_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %esi, %ecx -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: rorl %cl, %edi -; CHECK-NEXT: testl %edi, %edi -; CHECK-NEXT: je .LBB21_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %edi, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB21_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: rotr_with_fshr_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: rorl %cl, %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB25_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB25_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: rotr_with_fshr_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: movl %esi, %ecx +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: rorl %cl, %edi +; X64-NEXT: testl %edi, %edi +; X64-NEXT: je .LBB25_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %edi, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB25_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %z = call i32 @llvm.fshr.i32(i32 %x, i32 %x, i32 %y) %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @rotl_known_nonzero(i32 %xx, i32 %y) { -; CHECK-LABEL: rotl_known_nonzero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %esi, %ecx -; CHECK-NEXT: orl $256, %edi # imm = 0x100 -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: roll %cl, %edi -; CHECK-NEXT: testl %edi, %edi -; CHECK-NEXT: je .LBB22_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %edi, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB22_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: rotl_known_nonzero: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $256, %eax # imm = 0x100 +; X86-NEXT: orl {{[0-9]+}}(%esp), %eax +; X86-NEXT: roll %cl, %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB26_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB26_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: rotl_known_nonzero: +; X64: # %bb.0: +; X64-NEXT: movl %esi, %ecx +; X64-NEXT: orl $256, %edi # imm = 0x100 +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: roll %cl, %edi +; X64-NEXT: testl %edi, %edi +; X64-NEXT: je .LBB26_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %edi, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB26_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %x = or i32 %xx, 256 %shl = shl i32 %x, %y %sub = sub i32 32, %y @@ -425,19 +828,33 @@ define i32 @rotl_known_nonzero(i32 %xx, i32 %y) { } define i32 @rotl_maybe_zero(i32 %x, i32 %y) { -; CHECK-LABEL: rotl_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %esi, %ecx -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: roll %cl, %edi -; CHECK-NEXT: testl %edi, %edi -; CHECK-NEXT: je .LBB23_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %edi, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB23_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: rotl_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: roll %cl, %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB27_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB27_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: rotl_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: movl %esi, %ecx +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: roll %cl, %edi +; X64-NEXT: testl %edi, %edi +; X64-NEXT: je .LBB27_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %edi, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB27_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %shl = shl i32 %x, %y %sub = sub i32 32, %y %shr = lshr i32 %x, %sub @@ -447,14 +864,23 @@ define i32 @rotl_maybe_zero(i32 %x, i32 %y) { } define i32 @rotl_with_fshl_known_nonzero(i32 %xx, i32 %y) { -; CHECK-LABEL: rotl_with_fshl_known_nonzero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %esi, %ecx -; CHECK-NEXT: orl $256, %edi # imm = 0x100 -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: roll %cl, %edi -; CHECK-NEXT: rep bsfl %edi, %eax -; CHECK-NEXT: retq +; X86-LABEL: rotl_with_fshl_known_nonzero: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $256, %eax # imm = 0x100 +; X86-NEXT: orl {{[0-9]+}}(%esp), %eax +; X86-NEXT: roll %cl, %eax +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: rotl_with_fshl_known_nonzero: +; X64: # %bb.0: +; X64-NEXT: movl %esi, %ecx +; X64-NEXT: orl $256, %edi # imm = 0x100 +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: roll %cl, %edi +; X64-NEXT: rep bsfl %edi, %eax +; X64-NEXT: retq %x = or i32 %xx, 256 %z = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %y) %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -462,47 +888,78 @@ define i32 @rotl_with_fshl_known_nonzero(i32 %xx, i32 %y) { } define i32 @rotl_with_fshl_maybe_zero(i32 %x, i32 %y) { -; CHECK-LABEL: rotl_with_fshl_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %esi, %ecx -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: roll %cl, %edi -; CHECK-NEXT: testl %edi, %edi -; CHECK-NEXT: je .LBB25_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %edi, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB25_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: rotl_with_fshl_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: roll %cl, %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB29_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB29_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: rotl_with_fshl_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: movl %esi, %ecx +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: roll %cl, %edi +; X64-NEXT: testl %edi, %edi +; X64-NEXT: je .LBB29_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %edi, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB29_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %z = call i32 @llvm.fshl.i32(i32 %x, i32 %x, i32 %y) %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @sra_known_nonzero_sign_bit_set(i32 %x) { -; CHECK-LABEL: sra_known_nonzero_sign_bit_set: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: movl $-2147360405, %eax # imm = 0x8001E16B -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: sarl %cl, %eax -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq +; X86-LABEL: sra_known_nonzero_sign_bit_set: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $-2147360405, %eax # imm = 0x8001E16B +; X86-NEXT: sarl %cl, %eax +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: sra_known_nonzero_sign_bit_set: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: movl $-2147360405, %eax # imm = 0x8001E16B +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: sarl %cl, %eax +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq %z = ashr i32 2147606891, %x %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @sra_known_nonzero_exact(i32 %x, i32 %yy) { -; CHECK-LABEL: sra_known_nonzero_exact: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: orl $256, %esi # imm = 0x100 -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: sarl %cl, %esi -; CHECK-NEXT: rep bsfl %esi, %eax -; CHECK-NEXT: retq +; X86-LABEL: sra_known_nonzero_exact: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $256, %eax # imm = 0x100 +; X86-NEXT: orl {{[0-9]+}}(%esp), %eax +; X86-NEXT: sarl %cl, %eax +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: sra_known_nonzero_exact: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: orl $256, %esi # imm = 0x100 +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: sarl %cl, %esi +; X64-NEXT: rep bsfl %esi, %eax +; X64-NEXT: retq %y = or i32 %yy, 256 %z = ashr exact i32 %y, %x %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -510,47 +967,78 @@ define i32 @sra_known_nonzero_exact(i32 %x, i32 %yy) { } define i32 @sra_maybe_zero(i32 %x, i32 %y) { -; CHECK-LABEL: sra_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: sarl %cl, %esi -; CHECK-NEXT: testl %esi, %esi -; CHECK-NEXT: je .LBB28_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %esi, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB28_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: sra_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: sarl %cl, %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB32_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB32_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: sra_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: sarl %cl, %esi +; X64-NEXT: testl %esi, %esi +; X64-NEXT: je .LBB32_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %esi, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB32_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %z = ashr exact i32 %y, %x %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @srl_known_nonzero_sign_bit_set(i32 %x) { -; CHECK-LABEL: srl_known_nonzero_sign_bit_set: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: movl $-2147360405, %eax # imm = 0x8001E16B -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shrl %cl, %eax -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq +; X86-LABEL: srl_known_nonzero_sign_bit_set: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $-2147360405, %eax # imm = 0x8001E16B +; X86-NEXT: shrl %cl, %eax +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: srl_known_nonzero_sign_bit_set: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: movl $-2147360405, %eax # imm = 0x8001E16B +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: shrl %cl, %eax +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq %z = lshr i32 2147606891, %x %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @srl_known_nonzero_exact(i32 %x, i32 %yy) { -; CHECK-LABEL: srl_known_nonzero_exact: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: orl $256, %esi # imm = 0x100 -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shrl %cl, %esi -; CHECK-NEXT: rep bsfl %esi, %eax -; CHECK-NEXT: retq +; X86-LABEL: srl_known_nonzero_exact: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $256, %eax # imm = 0x100 +; X86-NEXT: orl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shrl %cl, %eax +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: srl_known_nonzero_exact: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: orl $256, %esi # imm = 0x100 +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: shrl %cl, %esi +; X64-NEXT: rep bsfl %esi, %eax +; X64-NEXT: retq %y = or i32 %yy, 256 %z = lshr exact i32 %y, %x %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -558,33 +1046,56 @@ define i32 @srl_known_nonzero_exact(i32 %x, i32 %yy) { } define i32 @srl_maybe_zero(i32 %x, i32 %y) { -; CHECK-LABEL: srl_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shrl %cl, %esi -; CHECK-NEXT: testl %esi, %esi -; CHECK-NEXT: je .LBB31_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %esi, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB31_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: srl_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: shrl %cl, %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB35_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB35_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: srl_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: shrl %cl, %esi +; X64-NEXT: testl %esi, %esi +; X64-NEXT: je .LBB35_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %esi, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB35_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %z = lshr exact i32 %y, %x %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @udiv_known_nonzero(i32 %xx, i32 %y) { -; CHECK-LABEL: udiv_known_nonzero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %eax -; CHECK-NEXT: orl $64, %eax -; CHECK-NEXT: xorl %edx, %edx -; CHECK-NEXT: divl %esi -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq +; X86-LABEL: udiv_known_nonzero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: orl $64, %eax +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: divl {{[0-9]+}}(%esp) +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: udiv_known_nonzero: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: orl $64, %eax +; X64-NEXT: xorl %edx, %edx +; X64-NEXT: divl %esi +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq %x = or i32 %xx, 64 %z = udiv exact i32 %x, %y %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -592,33 +1103,56 @@ define i32 @udiv_known_nonzero(i32 %xx, i32 %y) { } define i32 @udiv_maybe_zero(i32 %x, i32 %y) { -; CHECK-LABEL: udiv_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %eax -; CHECK-NEXT: xorl %edx, %edx -; CHECK-NEXT: divl %esi -; CHECK-NEXT: testl %eax, %eax -; CHECK-NEXT: je .LBB33_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB33_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: udiv_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: xorl %edx, %edx +; X86-NEXT: divl {{[0-9]+}}(%esp) +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB37_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB37_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: udiv_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: xorl %edx, %edx +; X64-NEXT: divl %esi +; X64-NEXT: testl %eax, %eax +; X64-NEXT: je .LBB37_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB37_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %z = udiv exact i32 %x, %y %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @sdiv_known_nonzero(i32 %xx, i32 %y) { -; CHECK-LABEL: sdiv_known_nonzero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %eax -; CHECK-NEXT: orl $64, %eax -; CHECK-NEXT: cltd -; CHECK-NEXT: idivl %esi -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq +; X86-LABEL: sdiv_known_nonzero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: orl $64, %eax +; X86-NEXT: cltd +; X86-NEXT: idivl {{[0-9]+}}(%esp) +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: sdiv_known_nonzero: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: orl $64, %eax +; X64-NEXT: cltd +; X64-NEXT: idivl %esi +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq %x = or i32 %xx, 64 %z = sdiv exact i32 %x, %y %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -626,31 +1160,53 @@ define i32 @sdiv_known_nonzero(i32 %xx, i32 %y) { } define i32 @sdiv_maybe_zero(i32 %x, i32 %y) { -; CHECK-LABEL: sdiv_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %eax -; CHECK-NEXT: cltd -; CHECK-NEXT: idivl %esi -; CHECK-NEXT: testl %eax, %eax -; CHECK-NEXT: je .LBB35_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB35_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: sdiv_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: cltd +; X86-NEXT: idivl {{[0-9]+}}(%esp) +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB39_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB39_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: sdiv_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: cltd +; X64-NEXT: idivl %esi +; X64-NEXT: testl %eax, %eax +; X64-NEXT: je .LBB39_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB39_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %z = sdiv exact i32 %x, %y %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @add_known_nonzero(i32 %xx, i32 %y) { -; CHECK-LABEL: add_known_nonzero: -; CHECK: # %bb.0: -; CHECK-NEXT: orl $1, %edi -; CHECK-NEXT: addl %esi, %edi -; CHECK-NEXT: rep bsfl %edi, %eax -; CHECK-NEXT: retq +; X86-LABEL: add_known_nonzero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: orl $1, %eax +; X86-NEXT: addl {{[0-9]+}}(%esp), %eax +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: add_known_nonzero: +; X64: # %bb.0: +; X64-NEXT: orl $1, %edi +; X64-NEXT: addl %esi, %edi +; X64-NEXT: rep bsfl %edi, %eax +; X64-NEXT: retq %x = or i32 %xx, 1 %z = add nuw i32 %x, %y %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -658,17 +1214,30 @@ define i32 @add_known_nonzero(i32 %xx, i32 %y) { } define i32 @add_maybe_zero(i32 %xx, i32 %y) { -; CHECK-LABEL: add_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: orl $1, %edi -; CHECK-NEXT: addl %esi, %edi -; CHECK-NEXT: je .LBB37_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %edi, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB37_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: add_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: orl $1, %eax +; X86-NEXT: addl {{[0-9]+}}(%esp), %eax +; X86-NEXT: je .LBB41_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB41_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: add_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: orl $1, %edi +; X64-NEXT: addl %esi, %edi +; X64-NEXT: je .LBB41_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %edi, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB41_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %x = or i32 %xx, 1 %z = add nsw i32 %x, %y %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -676,15 +1245,24 @@ define i32 @add_maybe_zero(i32 %xx, i32 %y) { } define i32 @sub_known_nonzero_neg_case(i32 %xx) { -; CHECK-LABEL: sub_known_nonzero_neg_case: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: movl $256, %eax # imm = 0x100 -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shll %cl, %eax -; CHECK-NEXT: negl %eax -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq +; X86-LABEL: sub_known_nonzero_neg_case: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $256, %eax # imm = 0x100 +; X86-NEXT: shll %cl, %eax +; X86-NEXT: negl %eax +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: sub_known_nonzero_neg_case: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: movl $256, %eax # imm = 0x100 +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: shll %cl, %eax +; X64-NEXT: negl %eax +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq %x = shl nuw nsw i32 256, %xx %z = sub i32 0, %x %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -692,14 +1270,24 @@ define i32 @sub_known_nonzero_neg_case(i32 %xx) { } define i32 @sub_known_nonzero_ne_case(i32 %xx, i32 %yy) { -; CHECK-LABEL: sub_known_nonzero_ne_case: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %eax -; CHECK-NEXT: orl $64, %eax -; CHECK-NEXT: andl $-65, %edi -; CHECK-NEXT: subl %eax, %edi -; CHECK-NEXT: rep bsfl %edi, %eax -; CHECK-NEXT: retq +; X86-LABEL: sub_known_nonzero_ne_case: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, %ecx +; X86-NEXT: orl $64, %ecx +; X86-NEXT: andl $-65, %eax +; X86-NEXT: subl %ecx, %eax +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: sub_known_nonzero_ne_case: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: orl $64, %eax +; X64-NEXT: andl $-65, %edi +; X64-NEXT: subl %eax, %edi +; X64-NEXT: rep bsfl %edi, %eax +; X64-NEXT: retq %x = or i32 %xx, 64 %y = and i32 %xx, -65 %z = sub i32 %y, %x @@ -708,18 +1296,32 @@ define i32 @sub_known_nonzero_ne_case(i32 %xx, i32 %yy) { } define i32 @sub_maybe_zero(i32 %x) { -; CHECK-LABEL: sub_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %eax -; CHECK-NEXT: orl $64, %eax -; CHECK-NEXT: subl %edi, %eax -; CHECK-NEXT: je .LBB40_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB40_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: sub_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl %ecx, %eax +; X86-NEXT: orl $64, %eax +; X86-NEXT: subl %ecx, %eax +; X86-NEXT: je .LBB44_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB44_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: sub_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: orl $64, %eax +; X64-NEXT: subl %edi, %eax +; X64-NEXT: je .LBB44_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB44_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %y = or i32 %x, 64 %z = sub i32 %y, %x %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -727,34 +1329,60 @@ define i32 @sub_maybe_zero(i32 %x) { } define i32 @sub_maybe_zero2(i32 %x) { -; CHECK-LABEL: sub_maybe_zero2: -; CHECK: # %bb.0: -; CHECK-NEXT: negl %edi -; CHECK-NEXT: je .LBB41_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %edi, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB41_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: sub_maybe_zero2: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: negl %eax +; X86-NEXT: je .LBB45_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB45_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: sub_maybe_zero2: +; X64: # %bb.0: +; X64-NEXT: negl %edi +; X64-NEXT: je .LBB45_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %edi, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB45_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %z = sub i32 0, %x %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @mul_known_nonzero_nsw(i32 %x, i32 %yy) { -; CHECK-LABEL: mul_known_nonzero_nsw: -; CHECK: # %bb.0: -; CHECK-NEXT: orl $256, %esi # imm = 0x100 -; CHECK-NEXT: imull %edi, %esi -; CHECK-NEXT: testl %esi, %esi -; CHECK-NEXT: je .LBB42_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %esi, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB42_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: mul_known_nonzero_nsw: +; X86: # %bb.0: +; X86-NEXT: movl $256, %eax # imm = 0x100 +; X86-NEXT: orl {{[0-9]+}}(%esp), %eax +; X86-NEXT: imull {{[0-9]+}}(%esp), %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB46_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB46_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: mul_known_nonzero_nsw: +; X64: # %bb.0: +; X64-NEXT: orl $256, %esi # imm = 0x100 +; X64-NEXT: imull %edi, %esi +; X64-NEXT: testl %esi, %esi +; X64-NEXT: je .LBB46_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %esi, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB46_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %y = or i32 %yy, 256 %z = mul nsw i32 %y, %x %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -762,18 +1390,32 @@ define i32 @mul_known_nonzero_nsw(i32 %x, i32 %yy) { } define i32 @mul_known_nonzero_nuw(i32 %x, i32 %yy) { -; CHECK-LABEL: mul_known_nonzero_nuw: -; CHECK: # %bb.0: -; CHECK-NEXT: orl $256, %esi # imm = 0x100 -; CHECK-NEXT: imull %edi, %esi -; CHECK-NEXT: testl %esi, %esi -; CHECK-NEXT: je .LBB43_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %esi, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB43_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: mul_known_nonzero_nuw: +; X86: # %bb.0: +; X86-NEXT: movl $256, %eax # imm = 0x100 +; X86-NEXT: orl {{[0-9]+}}(%esp), %eax +; X86-NEXT: imull {{[0-9]+}}(%esp), %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB47_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB47_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: mul_known_nonzero_nuw: +; X64: # %bb.0: +; X64-NEXT: orl $256, %esi # imm = 0x100 +; X64-NEXT: imull %edi, %esi +; X64-NEXT: testl %esi, %esi +; X64-NEXT: je .LBB47_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %esi, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB47_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %y = or i32 %yy, 256 %z = mul nuw i32 %y, %x %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -781,36 +1423,63 @@ define i32 @mul_known_nonzero_nuw(i32 %x, i32 %yy) { } define i32 @mul_maybe_zero(i32 %x, i32 %y) { -; CHECK-LABEL: mul_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: imull %esi, %edi -; CHECK-NEXT: testl %edi, %edi -; CHECK-NEXT: je .LBB44_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %edi, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB44_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: mul_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: imull {{[0-9]+}}(%esp), %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB48_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB48_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: mul_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: imull %esi, %edi +; X64-NEXT: testl %edi, %edi +; X64-NEXT: je .LBB48_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %edi, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB48_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %z = mul nuw nsw i32 %y, %x %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @bitcast_known_nonzero(<2 x i16> %xx) { -; CHECK-LABEL: bitcast_known_nonzero: -; CHECK: # %bb.0: -; CHECK-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3] -; CHECK-NEXT: pslld $23, %xmm0 -; CHECK-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 -; CHECK-NEXT: cvttps2dq %xmm0, %xmm0 -; CHECK-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[0,2,2,3,4,5,6,7] -; CHECK-NEXT: pmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 -; CHECK-NEXT: movd %xmm0, %eax -; CHECK-NEXT: bsfl %eax, %ecx -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: cmovnel %ecx, %eax -; CHECK-NEXT: retq +; X86-LABEL: bitcast_known_nonzero: +; X86: # %bb.0: +; X86-NEXT: punpcklwd {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3] +; X86-NEXT: pslld $23, %xmm0 +; X86-NEXT: paddd {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0 +; X86-NEXT: cvttps2dq %xmm0, %xmm0 +; X86-NEXT: pshuflw {{.*#+}} xmm0 = xmm0[0,2,2,3,4,5,6,7] +; X86-NEXT: pmullw {{\.?LCPI[0-9]+_[0-9]+}}, %xmm0 +; X86-NEXT: movd %xmm0, %eax +; X86-NEXT: bsfl %eax, %ecx +; X86-NEXT: movl $32, %eax +; X86-NEXT: cmovnel %ecx, %eax +; X86-NEXT: retl +; +; X64-LABEL: bitcast_known_nonzero: +; X64: # %bb.0: +; X64-NEXT: vpmovzxwd {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; X64-NEXT: vpslld $23, %xmm0, %xmm0 +; X64-NEXT: vpaddd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; X64-NEXT: vcvttps2dq %xmm0, %xmm0 +; X64-NEXT: vpackusdw %xmm0, %xmm0, %xmm0 +; X64-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; X64-NEXT: vmovd %xmm0, %eax +; X64-NEXT: bsfl %eax, %ecx +; X64-NEXT: movl $32, %eax +; X64-NEXT: cmovnel %ecx, %eax +; X64-NEXT: retq %x = shl nuw nsw <2 x i16> <i16 256, i16 256>, %xx %z = bitcast <2 x i16> %x to i32 %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -818,49 +1487,83 @@ define i32 @bitcast_known_nonzero(<2 x i16> %xx) { } define i32 @bitcast_maybe_zero(<2 x i16> %x) { -; CHECK-LABEL: bitcast_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: movd %xmm0, %eax -; CHECK-NEXT: testl %eax, %eax -; CHECK-NEXT: je .LBB46_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB46_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: bitcast_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movd %xmm0, %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB50_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB50_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: bitcast_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: vmovd %xmm0, %eax +; X64-NEXT: testl %eax, %eax +; X64-NEXT: je .LBB50_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB50_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %z = bitcast <2 x i16> %x to i32 %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @bitcast_from_float(float %x) { -; CHECK-LABEL: bitcast_from_float: -; CHECK: # %bb.0: -; CHECK-NEXT: movd %xmm0, %eax -; CHECK-NEXT: testl %eax, %eax -; CHECK-NEXT: je .LBB47_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB47_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: bitcast_from_float: +; X86: # %bb.0: +; X86-NEXT: movd {{.*#+}} xmm0 = mem[0],zero,zero,zero +; X86-NEXT: movd %xmm0, %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB51_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB51_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: bitcast_from_float: +; X64: # %bb.0: +; X64-NEXT: vmovd %xmm0, %eax +; X64-NEXT: testl %eax, %eax +; X64-NEXT: je .LBB51_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB51_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %z = bitcast float %x to i32 %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @zext_known_nonzero(i16 %xx) { -; CHECK-LABEL: zext_known_nonzero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: movl $256, %eax # imm = 0x100 -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shll %cl, %eax -; CHECK-NEXT: movzwl %ax, %eax -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq +; X86-LABEL: zext_known_nonzero: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $256, %eax # imm = 0x100 +; X86-NEXT: shll %cl, %eax +; X86-NEXT: movzwl %ax, %eax +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: zext_known_nonzero: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: movl $256, %eax # imm = 0x100 +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: shll %cl, %eax +; X64-NEXT: movzwl %ax, %eax +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq %x = shl nuw nsw i16 256, %xx %z = zext i16 %x to i32 %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -868,32 +1571,54 @@ define i32 @zext_known_nonzero(i16 %xx) { } define i32 @zext_maybe_zero(i16 %x) { -; CHECK-LABEL: zext_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: testw %di, %di -; CHECK-NEXT: je .LBB49_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: movzwl %di, %eax -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB49_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: zext_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax +; X86-NEXT: testw %ax, %ax +; X86-NEXT: je .LBB53_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: movzwl %ax, %eax +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB53_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: zext_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: testw %di, %di +; X64-NEXT: je .LBB53_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: movzwl %di, %eax +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB53_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %z = zext i16 %x to i32 %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r } define i32 @sext_known_nonzero(i16 %xx) { -; CHECK-LABEL: sext_known_nonzero: -; CHECK: # %bb.0: -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: movl $256, %eax # imm = 0x100 -; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx -; CHECK-NEXT: shll %cl, %eax -; CHECK-NEXT: cwtl -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq +; X86-LABEL: sext_known_nonzero: +; X86: # %bb.0: +; X86-NEXT: movzbl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl $256, %eax # imm = 0x100 +; X86-NEXT: shll %cl, %eax +; X86-NEXT: cwtl +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; +; X64-LABEL: sext_known_nonzero: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: movl $256, %eax # imm = 0x100 +; X64-NEXT: # kill: def $cl killed $cl killed $ecx +; X64-NEXT: shll %cl, %eax +; X64-NEXT: cwtl +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq %x = shl nuw nsw i16 256, %xx %z = sext i16 %x to i32 %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) @@ -901,17 +1626,29 @@ define i32 @sext_known_nonzero(i16 %xx) { } define i32 @sext_maybe_zero(i16 %x) { -; CHECK-LABEL: sext_maybe_zero: -; CHECK: # %bb.0: -; CHECK-NEXT: testw %di, %di -; CHECK-NEXT: je .LBB51_1 -; CHECK-NEXT: # %bb.2: # %cond.false -; CHECK-NEXT: movswl %di, %eax -; CHECK-NEXT: rep bsfl %eax, %eax -; CHECK-NEXT: retq -; CHECK-NEXT: .LBB51_1: -; CHECK-NEXT: movl $32, %eax -; CHECK-NEXT: retq +; X86-LABEL: sext_maybe_zero: +; X86: # %bb.0: +; X86-NEXT: movswl {{[0-9]+}}(%esp), %eax +; X86-NEXT: testl %eax, %eax +; X86-NEXT: je .LBB55_1 +; X86-NEXT: # %bb.2: # %cond.false +; X86-NEXT: rep bsfl %eax, %eax +; X86-NEXT: retl +; X86-NEXT: .LBB55_1: +; X86-NEXT: movl $32, %eax +; X86-NEXT: retl +; +; X64-LABEL: sext_maybe_zero: +; X64: # %bb.0: +; X64-NEXT: testw %di, %di +; X64-NEXT: je .LBB55_1 +; X64-NEXT: # %bb.2: # %cond.false +; X64-NEXT: movswl %di, %eax +; X64-NEXT: rep bsfl %eax, %eax +; X64-NEXT: retq +; X64-NEXT: .LBB55_1: +; X64-NEXT: movl $32, %eax +; X64-NEXT: retq %z = sext i16 %x to i32 %r = call i32 @llvm.cttz.i32(i32 %z, i1 false) ret i32 %r diff --git a/llvm/test/CodeGen/X86/late-remat-update.mir b/llvm/test/CodeGen/X86/late-remat-update.mir index 84a78f84728cac39a9dcb9d4e1cbfefe9a886314..dd4e99c6df1418f26dc9cf323c3d97877e9dc5e5 100644 --- a/llvm/test/CodeGen/X86/late-remat-update.mir +++ b/llvm/test/CodeGen/X86/late-remat-update.mir @@ -66,6 +66,7 @@ registers: liveins: - { reg: '$edi', virtual-reg: '%0' } frameInfo: + adjustsStack: true hasCalls: true body: | bb.0.entry: diff --git a/llvm/test/CodeGen/X86/limit-split-cost.mir b/llvm/test/CodeGen/X86/limit-split-cost.mir index 6f5329e5b332a049325972c42b5a722a6a6db23a..7ec0404e0f737cf66eb4f27d8d859853d64ef07f 100644 --- a/llvm/test/CodeGen/X86/limit-split-cost.mir +++ b/llvm/test/CodeGen/X86/limit-split-cost.mir @@ -86,6 +86,7 @@ registers: liveins: - { reg: '$edi', virtual-reg: '%0' } frameInfo: + adjustsStack: true hasCalls: true body: | bb.0.entry: diff --git a/llvm/test/CodeGen/X86/masked_store.ll b/llvm/test/CodeGen/X86/masked_store.ll index 898b34e969b1d255e6723e5938adb692937306d7..6aa0a81c90204d477d803cdad5b9a3297c8d2479 100644 --- a/llvm/test/CodeGen/X86/masked_store.ll +++ b/llvm/test/CodeGen/X86/masked_store.ll @@ -12,7 +12,7 @@ ; vXf64 ; -define void @store_v1f64_v1i64(<1 x i64> %trigger, ptr %addr, <1 x double> %val) { +define void @store_v1f64_v1i64(<1 x i64> %trigger, ptr %addr, <1 x double> %val) nounwind { ; SSE-LABEL: store_v1f64_v1i64: ; SSE: ## %bb.0: ; SSE-NEXT: testq %rdi, %rdi @@ -46,7 +46,7 @@ define void @store_v1f64_v1i64(<1 x i64> %trigger, ptr %addr, <1 x double> %val) ret void } -define void @store_v2f64_v2i64(<2 x i64> %trigger, ptr %addr, <2 x double> %val) { +define void @store_v2f64_v2i64(<2 x i64> %trigger, ptr %addr, <2 x double> %val) nounwind { ; SSE-LABEL: store_v2f64_v2i64: ; SSE: ## %bb.0: ; SSE-NEXT: movmskpd %xmm0, %eax @@ -106,7 +106,7 @@ define void @store_v2f64_v2i64(<2 x i64> %trigger, ptr %addr, <2 x double> %val) ret void } -define void @store_v4f64_v4i64(<4 x i64> %trigger, ptr %addr, <4 x double> %val) { +define void @store_v4f64_v4i64(<4 x i64> %trigger, ptr %addr, <4 x double> %val) nounwind { ; SSE2-LABEL: store_v4f64_v4i64: ; SSE2: ## %bb.0: ; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,3],xmm1[1,3] @@ -222,7 +222,7 @@ define void @store_v4f64_v4i64(<4 x i64> %trigger, ptr %addr, <4 x double> %val) ; vXf32 ; -define void @store_v2f32_v2i32(<2 x i32> %trigger, ptr %addr, <2 x float> %val) { +define void @store_v2f32_v2i32(<2 x i32> %trigger, ptr %addr, <2 x float> %val) nounwind { ; SSE2-LABEL: store_v2f32_v2i32: ; SSE2: ## %bb.0: ; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[0,0,1,1] @@ -314,7 +314,7 @@ define void @store_v2f32_v2i32(<2 x i32> %trigger, ptr %addr, <2 x float> %val) ret void } -define void @store_v4f32_v4i32(<4 x float> %x, ptr %ptr, <4 x float> %y, <4 x i32> %mask) { +define void @store_v4f32_v4i32(<4 x float> %x, ptr %ptr, <4 x float> %y, <4 x i32> %mask) nounwind { ; SSE2-LABEL: store_v4f32_v4i32: ; SSE2: ## %bb.0: ; SSE2-NEXT: movmskps %xmm2, %eax @@ -425,7 +425,7 @@ define void @store_v4f32_v4i32(<4 x float> %x, ptr %ptr, <4 x float> %y, <4 x i3 ret void } -define void @store_v8f32_v8i32(<8 x float> %x, ptr %ptr, <8 x float> %y, <8 x i32> %mask) { +define void @store_v8f32_v8i32(<8 x float> %x, ptr %ptr, <8 x float> %y, <8 x i32> %mask) nounwind { ; SSE2-LABEL: store_v8f32_v8i32: ; SSE2: ## %bb.0: ; SSE2-NEXT: packssdw %xmm5, %xmm4 @@ -605,7 +605,7 @@ define void @store_v8f32_v8i32(<8 x float> %x, ptr %ptr, <8 x float> %y, <8 x i3 ret void } -define void @store_v16f32_v16i32(<16 x float> %x, ptr %ptr, <16 x float> %y, <16 x i32> %mask) { +define void @store_v16f32_v16i32(<16 x float> %x, ptr %ptr, <16 x float> %y, <16 x i32> %mask) nounwind { ; SSE2-LABEL: store_v16f32_v16i32: ; SSE2: ## %bb.0: ; SSE2-NEXT: movdqa {{[0-9]+}}(%rsp), %xmm4 @@ -914,7 +914,7 @@ define void @store_v16f32_v16i32(<16 x float> %x, ptr %ptr, <16 x float> %y, <16 ; vXi64 ; -define void @store_v2i64_v2i64(<2 x i64> %trigger, ptr %addr, <2 x i64> %val) { +define void @store_v2i64_v2i64(<2 x i64> %trigger, ptr %addr, <2 x i64> %val) nounwind { ; SSE2-LABEL: store_v2i64_v2i64: ; SSE2: ## %bb.0: ; SSE2-NEXT: movmskpd %xmm0, %eax @@ -998,7 +998,7 @@ define void @store_v2i64_v2i64(<2 x i64> %trigger, ptr %addr, <2 x i64> %val) { ret void } -define void @store_v4i64_v4i64(<4 x i64> %trigger, ptr %addr, <4 x i64> %val) { +define void @store_v4i64_v4i64(<4 x i64> %trigger, ptr %addr, <4 x i64> %val) nounwind { ; SSE2-LABEL: store_v4i64_v4i64: ; SSE2: ## %bb.0: ; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,3],xmm1[1,3] @@ -1122,7 +1122,7 @@ define void @store_v4i64_v4i64(<4 x i64> %trigger, ptr %addr, <4 x i64> %val) { ; vXi32 ; -define void @store_v1i32_v1i32(<1 x i32> %trigger, ptr %addr, <1 x i32> %val) { +define void @store_v1i32_v1i32(<1 x i32> %trigger, ptr %addr, <1 x i32> %val) nounwind { ; SSE-LABEL: store_v1i32_v1i32: ; SSE: ## %bb.0: ; SSE-NEXT: testl %edi, %edi @@ -1156,7 +1156,7 @@ define void @store_v1i32_v1i32(<1 x i32> %trigger, ptr %addr, <1 x i32> %val) { ret void } -define void @store_v2i32_v2i32(<2 x i32> %trigger, ptr %addr, <2 x i32> %val) { +define void @store_v2i32_v2i32(<2 x i32> %trigger, ptr %addr, <2 x i32> %val) nounwind { ; SSE2-LABEL: store_v2i32_v2i32: ; SSE2: ## %bb.0: ; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[0,0,1,1] @@ -1256,7 +1256,7 @@ define void @store_v2i32_v2i32(<2 x i32> %trigger, ptr %addr, <2 x i32> %val) { ret void } -define void @store_v4i32_v4i32(<4 x i32> %trigger, ptr %addr, <4 x i32> %val) { +define void @store_v4i32_v4i32(<4 x i32> %trigger, ptr %addr, <4 x i32> %val) nounwind { ; SSE2-LABEL: store_v4i32_v4i32: ; SSE2: ## %bb.0: ; SSE2-NEXT: pxor %xmm2, %xmm2 @@ -1370,7 +1370,7 @@ define void @store_v4i32_v4i32(<4 x i32> %trigger, ptr %addr, <4 x i32> %val) { ret void } -define void @store_v8i32_v8i32(<8 x i32> %trigger, ptr %addr, <8 x i32> %val) { +define void @store_v8i32_v8i32(<8 x i32> %trigger, ptr %addr, <8 x i32> %val) nounwind { ; SSE2-LABEL: store_v8i32_v8i32: ; SSE2: ## %bb.0: ; SSE2-NEXT: pxor %xmm4, %xmm4 @@ -1560,7 +1560,7 @@ define void @store_v8i32_v8i32(<8 x i32> %trigger, ptr %addr, <8 x i32> %val) { ; vXi16 ; -define void @store_v8i16_v8i16(<8 x i16> %trigger, ptr %addr, <8 x i16> %val) { +define void @store_v8i16_v8i16(<8 x i16> %trigger, ptr %addr, <8 x i16> %val) nounwind { ; SSE2-LABEL: store_v8i16_v8i16: ; SSE2: ## %bb.0: ; SSE2-NEXT: pxor %xmm2, %xmm2 @@ -1907,7 +1907,7 @@ define void @store_v8i16_v8i16(<8 x i16> %trigger, ptr %addr, <8 x i16> %val) { ret void } -define void @store_v16i16_v16i16(<16 x i16> %trigger, ptr %addr, <16 x i16> %val) { +define void @store_v16i16_v16i16(<16 x i16> %trigger, ptr %addr, <16 x i16> %val) nounwind { ; SSE2-LABEL: store_v16i16_v16i16: ; SSE2: ## %bb.0: ; SSE2-NEXT: pxor %xmm4, %xmm4 @@ -2676,7 +2676,7 @@ define void @store_v16i16_v16i16(<16 x i16> %trigger, ptr %addr, <16 x i16> %val ; vXi8 ; -define void @store_v16i8_v16i8(<16 x i8> %trigger, ptr %addr, <16 x i8> %val) { +define void @store_v16i8_v16i8(<16 x i8> %trigger, ptr %addr, <16 x i8> %val) nounwind { ; SSE2-LABEL: store_v16i8_v16i8: ; SSE2: ## %bb.0: ; SSE2-NEXT: pxor %xmm2, %xmm2 @@ -3273,7 +3273,7 @@ define void @store_v16i8_v16i8(<16 x i8> %trigger, ptr %addr, <16 x i8> %val) { ret void } -define void @store_v32i8_v32i8(<32 x i8> %trigger, ptr %addr, <32 x i8> %val) { +define void @store_v32i8_v32i8(<32 x i8> %trigger, ptr %addr, <32 x i8> %val) nounwind { ; SSE2-LABEL: store_v32i8_v32i8: ; SSE2: ## %bb.0: ; SSE2-NEXT: pxor %xmm4, %xmm4 @@ -4670,7 +4670,7 @@ define void @store_v32i8_v32i8(<32 x i8> %trigger, ptr %addr, <32 x i8> %val) { ;;; Stores with Constant Masks -define void @mstore_constmask_v4i32_v4i32(<4 x i32> %trigger, ptr %addr, <4 x i32> %val) { +define void @mstore_constmask_v4i32_v4i32(<4 x i32> %trigger, ptr %addr, <4 x i32> %val) nounwind { ; SSE-LABEL: mstore_constmask_v4i32_v4i32: ; SSE: ## %bb.0: ; SSE-NEXT: movups %xmm1, (%rdi) @@ -4693,7 +4693,7 @@ define void @mstore_constmask_v4i32_v4i32(<4 x i32> %trigger, ptr %addr, <4 x i3 ; Make sure we are able to detect all ones constant mask after type legalization ; to avoid masked stores. -define void @mstore_constmask_allones_split(<16 x i64> %trigger, ptr %addr, <16 x i64> %val) { +define void @mstore_constmask_allones_split(<16 x i64> %trigger, ptr %addr, <16 x i64> %val) nounwind { ; SSE2-LABEL: mstore_constmask_allones_split: ; SSE2: ## %bb.0: ; SSE2-NEXT: movdqa {{[0-9]+}}(%rsp), %xmm0 @@ -4810,7 +4810,7 @@ define void @mstore_constmask_allones_split(<16 x i64> %trigger, ptr %addr, <16 ; When only one element of the mask is set, reduce to a scalar store. -define void @one_mask_bit_set1(ptr %addr, <4 x i32> %val) { +define void @one_mask_bit_set1(ptr %addr, <4 x i32> %val) nounwind { ; SSE-LABEL: one_mask_bit_set1: ; SSE: ## %bb.0: ; SSE-NEXT: movss %xmm0, (%rdi) @@ -4832,7 +4832,7 @@ define void @one_mask_bit_set1(ptr %addr, <4 x i32> %val) { ; Choose a different element to show that the correct address offset is produced. -define void @one_mask_bit_set2(ptr %addr, <4 x float> %val) { +define void @one_mask_bit_set2(ptr %addr, <4 x float> %val) nounwind { ; SSE2-LABEL: one_mask_bit_set2: ; SSE2: ## %bb.0: ; SSE2-NEXT: movhlps {{.*#+}} xmm0 = xmm0[1,1] @@ -4860,7 +4860,7 @@ define void @one_mask_bit_set2(ptr %addr, <4 x float> %val) { ; Choose a different scalar type and a high element of a 256-bit vector because AVX doesn't support those evenly. -define void @one_mask_bit_set3(ptr %addr, <4 x i64> %val) { +define void @one_mask_bit_set3(ptr %addr, <4 x i64> %val) nounwind { ; SSE-LABEL: one_mask_bit_set3: ; SSE: ## %bb.0: ; SSE-NEXT: movlps %xmm1, 16(%rdi) @@ -4886,7 +4886,7 @@ define void @one_mask_bit_set3(ptr %addr, <4 x i64> %val) { ; Choose a different scalar type and a high element of a 256-bit vector because AVX doesn't support those evenly. -define void @one_mask_bit_set4(ptr %addr, <4 x double> %val) { +define void @one_mask_bit_set4(ptr %addr, <4 x double> %val) nounwind { ; SSE-LABEL: one_mask_bit_set4: ; SSE: ## %bb.0: ; SSE-NEXT: movhps %xmm1, 24(%rdi) @@ -4912,7 +4912,7 @@ define void @one_mask_bit_set4(ptr %addr, <4 x double> %val) { ; Try a 512-bit vector to make sure AVX doesn't die and AVX512 works as expected. -define void @one_mask_bit_set5(ptr %addr, <8 x double> %val) { +define void @one_mask_bit_set5(ptr %addr, <8 x double> %val) nounwind { ; SSE-LABEL: one_mask_bit_set5: ; SSE: ## %bb.0: ; SSE-NEXT: movlps %xmm3, 48(%rdi) @@ -4944,7 +4944,7 @@ define void @one_mask_bit_set5(ptr %addr, <8 x double> %val) { } ; Try one elt in each half of a vector that needs to split -define void @one_mask_bit_set6(ptr %addr, <16 x i64> %val) { +define void @one_mask_bit_set6(ptr %addr, <16 x i64> %val) nounwind { ; SSE2-LABEL: one_mask_bit_set6: ; SSE2: ## %bb.0: ; SSE2-NEXT: movlps %xmm3, 48(%rdi) @@ -4999,7 +4999,7 @@ define void @one_mask_bit_set6(ptr %addr, <16 x i64> %val) { ret void } -define void @top_bits_unset_stack() { +define void @top_bits_unset_stack() nounwind { ; SSE-LABEL: top_bits_unset_stack: ; SSE: ## %bb.0: ## %entry ; SSE-NEXT: xorps %xmm0, %xmm0 @@ -5047,7 +5047,6 @@ define void @top_bits_unset_stack() { ; X86-AVX512-LABEL: top_bits_unset_stack: ; X86-AVX512: ## %bb.0: ## %entry ; X86-AVX512-NEXT: subl $76, %esp -; X86-AVX512-NEXT: .cfi_def_cfa_offset 80 ; X86-AVX512-NEXT: vxorpd %xmm0, %xmm0, %xmm0 ; X86-AVX512-NEXT: movb $63, %al ; X86-AVX512-NEXT: kmovd %eax, %k1 @@ -5064,7 +5063,7 @@ entry: ; SimplifyDemandedBits eliminates an ashr here. -define void @masked_store_bool_mask_demand_trunc_sext(<4 x double> %x, ptr %p, <4 x i32> %masksrc) { +define void @masked_store_bool_mask_demand_trunc_sext(<4 x double> %x, ptr %p, <4 x i32> %masksrc) nounwind { ; SSE-LABEL: masked_store_bool_mask_demand_trunc_sext: ; SSE: ## %bb.0: ; SSE-NEXT: pslld $31, %xmm2 @@ -5160,7 +5159,7 @@ define void @masked_store_bool_mask_demand_trunc_sext(<4 x double> %x, ptr %p, < ; PR26697 -define void @one_mask_bit_set1_variable(ptr %addr, <4 x float> %val, <4 x i32> %mask) { +define void @one_mask_bit_set1_variable(ptr %addr, <4 x float> %val, <4 x i32> %mask) nounwind { ; SSE2-LABEL: one_mask_bit_set1_variable: ; SSE2: ## %bb.0: ; SSE2-NEXT: movmskps %xmm1, %eax @@ -5267,7 +5266,7 @@ define void @one_mask_bit_set1_variable(ptr %addr, <4 x float> %val, <4 x i32> % ; This needs to be widened to v4i32. ; This used to assert in type legalization. PR38436 ; FIXME: The codegen for AVX512 should use KSHIFT to zero the upper bits of the mask. -define void @widen_masked_store(<3 x i32> %v, ptr %p, <3 x i1> %mask) { +define void @widen_masked_store(<3 x i32> %v, ptr %p, <3 x i1> %mask) nounwind { ; SSE2-LABEL: widen_masked_store: ; SSE2: ## %bb.0: ; SSE2-NEXT: andb $1, %sil @@ -5448,7 +5447,7 @@ define void @widen_masked_store(<3 x i32> %v, ptr %p, <3 x i1> %mask) { ret void } -define void @zero_mask(ptr %addr, <2 x double> %val) { +define void @zero_mask(ptr %addr, <2 x double> %val) nounwind { ; SSE-LABEL: zero_mask: ; SSE: ## %bb.0: ; SSE-NEXT: retq @@ -5464,7 +5463,7 @@ define void @zero_mask(ptr %addr, <2 x double> %val) { ret void } -define void @PR11210(<4 x float> %x, ptr %ptr, <4 x float> %y, <2 x i64> %mask) { +define void @PR11210(<4 x float> %x, ptr %ptr, <4 x float> %y, <2 x i64> %mask) nounwind { ; SSE2-LABEL: PR11210: ; SSE2: ## %bb.0: ; SSE2-NEXT: movmskps %xmm2, %eax @@ -5638,492 +5637,248 @@ define void @PR11210(<4 x float> %x, ptr %ptr, <4 x float> %y, <2 x i64> %mask) ret void } -define void @store_v24i32_v24i32_stride6_vf4_only_even_numbered_elts(ptr %trigger.ptr, ptr %val.ptr, ptr %dst) { -; SSE2-LABEL: store_v24i32_v24i32_stride6_vf4_only_even_numbered_elts: -; SSE2: ## %bb.0: -; SSE2-NEXT: movdqa (%rdi), %xmm6 -; SSE2-NEXT: movdqa 32(%rdi), %xmm7 -; SSE2-NEXT: movdqa 64(%rdi), %xmm8 -; SSE2-NEXT: movl 80(%rsi), %eax -; SSE2-NEXT: movl 64(%rsi), %r8d -; SSE2-NEXT: movl 48(%rsi), %r9d -; SSE2-NEXT: movl 32(%rsi), %r10d -; SSE2-NEXT: movl 16(%rsi), %r11d -; SSE2-NEXT: movdqa 80(%rsi), %xmm0 -; SSE2-NEXT: movdqa 64(%rsi), %xmm1 -; SSE2-NEXT: movdqa 48(%rsi), %xmm2 -; SSE2-NEXT: movdqa 32(%rsi), %xmm3 -; SSE2-NEXT: movdqa 16(%rsi), %xmm4 -; SSE2-NEXT: movdqa (%rsi), %xmm5 -; SSE2-NEXT: packssdw 48(%rdi), %xmm7 -; SSE2-NEXT: packssdw 16(%rdi), %xmm6 -; SSE2-NEXT: packsswb %xmm7, %xmm6 -; SSE2-NEXT: packssdw 80(%rdi), %xmm8 -; SSE2-NEXT: packsswb %xmm8, %xmm8 -; SSE2-NEXT: pmovmskb %xmm6, %edi -; SSE2-NEXT: andl $21845, %edi ## imm = 0x5555 -; SSE2-NEXT: pmovmskb %xmm8, %ecx -; SSE2-NEXT: andl $85, %ecx -; SSE2-NEXT: shll $16, %ecx -; SSE2-NEXT: orl %edi, %ecx -; SSE2-NEXT: testb $1, %cl -; SSE2-NEXT: jne LBB31_1 -; SSE2-NEXT: ## %bb.2: ## %else -; SSE2-NEXT: testb $2, %cl -; SSE2-NEXT: jne LBB31_3 -; SSE2-NEXT: LBB31_4: ## %else2 -; SSE2-NEXT: testb $4, %cl -; SSE2-NEXT: jne LBB31_5 -; SSE2-NEXT: LBB31_6: ## %else4 -; SSE2-NEXT: testb $8, %cl -; SSE2-NEXT: jne LBB31_7 -; SSE2-NEXT: LBB31_8: ## %else6 -; SSE2-NEXT: testb $16, %cl -; SSE2-NEXT: jne LBB31_9 -; SSE2-NEXT: LBB31_10: ## %else8 -; SSE2-NEXT: testb $32, %cl -; SSE2-NEXT: jne LBB31_11 -; SSE2-NEXT: LBB31_12: ## %else10 -; SSE2-NEXT: testb $64, %cl -; SSE2-NEXT: jne LBB31_13 -; SSE2-NEXT: LBB31_14: ## %else12 -; SSE2-NEXT: testb %cl, %cl -; SSE2-NEXT: js LBB31_15 -; SSE2-NEXT: LBB31_16: ## %else14 -; SSE2-NEXT: testl $256, %ecx ## imm = 0x100 -; SSE2-NEXT: jne LBB31_17 -; SSE2-NEXT: LBB31_18: ## %else16 -; SSE2-NEXT: testl $512, %ecx ## imm = 0x200 -; SSE2-NEXT: jne LBB31_19 -; SSE2-NEXT: LBB31_20: ## %else18 -; SSE2-NEXT: testl $1024, %ecx ## imm = 0x400 -; SSE2-NEXT: jne LBB31_21 -; SSE2-NEXT: LBB31_22: ## %else20 -; SSE2-NEXT: testl $2048, %ecx ## imm = 0x800 -; SSE2-NEXT: jne LBB31_23 -; SSE2-NEXT: LBB31_24: ## %else22 -; SSE2-NEXT: testl $4096, %ecx ## imm = 0x1000 -; SSE2-NEXT: jne LBB31_25 -; SSE2-NEXT: LBB31_26: ## %else24 -; SSE2-NEXT: testl $8192, %ecx ## imm = 0x2000 -; SSE2-NEXT: jne LBB31_27 -; SSE2-NEXT: LBB31_28: ## %else26 -; SSE2-NEXT: testl $16384, %ecx ## imm = 0x4000 -; SSE2-NEXT: jne LBB31_29 -; SSE2-NEXT: LBB31_30: ## %else28 -; SSE2-NEXT: testw %cx, %cx -; SSE2-NEXT: js LBB31_31 -; SSE2-NEXT: LBB31_32: ## %else30 -; SSE2-NEXT: testl $65536, %ecx ## imm = 0x10000 -; SSE2-NEXT: jne LBB31_33 -; SSE2-NEXT: LBB31_34: ## %else32 -; SSE2-NEXT: testl $131072, %ecx ## imm = 0x20000 -; SSE2-NEXT: jne LBB31_35 -; SSE2-NEXT: LBB31_36: ## %else34 -; SSE2-NEXT: testl $262144, %ecx ## imm = 0x40000 -; SSE2-NEXT: jne LBB31_37 -; SSE2-NEXT: LBB31_38: ## %else36 -; SSE2-NEXT: testl $524288, %ecx ## imm = 0x80000 -; SSE2-NEXT: jne LBB31_39 -; SSE2-NEXT: LBB31_40: ## %else38 -; SSE2-NEXT: testl $1048576, %ecx ## imm = 0x100000 -; SSE2-NEXT: jne LBB31_41 -; SSE2-NEXT: LBB31_42: ## %else40 -; SSE2-NEXT: testl $2097152, %ecx ## imm = 0x200000 -; SSE2-NEXT: jne LBB31_43 -; SSE2-NEXT: LBB31_44: ## %else42 -; SSE2-NEXT: testl $4194304, %ecx ## imm = 0x400000 -; SSE2-NEXT: je LBB31_46 -; SSE2-NEXT: LBB31_45: ## %cond.store43 -; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] -; SSE2-NEXT: movd %xmm1, %eax -; SSE2-NEXT: movl %eax, 88(%rdx) -; SSE2-NEXT: LBB31_46: ## %else44 -; SSE2-NEXT: movb $1, %al -; SSE2-NEXT: testb %al, %al -; SSE2-NEXT: jne LBB31_48 -; SSE2-NEXT: ## %bb.47: ## %cond.store45 -; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[3,3,3,3] -; SSE2-NEXT: movd %xmm0, %eax -; SSE2-NEXT: movl %eax, 92(%rdx) -; SSE2-NEXT: LBB31_48: ## %else46 -; SSE2-NEXT: retq -; SSE2-NEXT: LBB31_1: ## %cond.store -; SSE2-NEXT: movl (%rsi), %esi -; SSE2-NEXT: movl %esi, (%rdx) -; SSE2-NEXT: testb $2, %cl -; SSE2-NEXT: je LBB31_4 -; SSE2-NEXT: LBB31_3: ## %cond.store1 -; SSE2-NEXT: pshufd {{.*#+}} xmm6 = xmm5[1,1,1,1] -; SSE2-NEXT: movd %xmm6, %esi -; SSE2-NEXT: movl %esi, 4(%rdx) -; SSE2-NEXT: testb $4, %cl -; SSE2-NEXT: je LBB31_6 -; SSE2-NEXT: LBB31_5: ## %cond.store3 -; SSE2-NEXT: pshufd {{.*#+}} xmm6 = xmm5[2,3,2,3] -; SSE2-NEXT: movd %xmm6, %esi -; SSE2-NEXT: movl %esi, 8(%rdx) -; SSE2-NEXT: testb $8, %cl -; SSE2-NEXT: je LBB31_8 -; SSE2-NEXT: LBB31_7: ## %cond.store5 -; SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm5[3,3,3,3] -; SSE2-NEXT: movd %xmm5, %esi -; SSE2-NEXT: movl %esi, 12(%rdx) -; SSE2-NEXT: testb $16, %cl -; SSE2-NEXT: je LBB31_10 -; SSE2-NEXT: LBB31_9: ## %cond.store7 -; SSE2-NEXT: movl %r11d, 16(%rdx) -; SSE2-NEXT: testb $32, %cl -; SSE2-NEXT: je LBB31_12 -; SSE2-NEXT: LBB31_11: ## %cond.store9 -; SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm4[1,1,1,1] -; SSE2-NEXT: movd %xmm5, %esi -; SSE2-NEXT: movl %esi, 20(%rdx) -; SSE2-NEXT: testb $64, %cl -; SSE2-NEXT: je LBB31_14 -; SSE2-NEXT: LBB31_13: ## %cond.store11 -; SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm4[2,3,2,3] -; SSE2-NEXT: movd %xmm5, %esi -; SSE2-NEXT: movl %esi, 24(%rdx) -; SSE2-NEXT: testb %cl, %cl -; SSE2-NEXT: jns LBB31_16 -; SSE2-NEXT: LBB31_15: ## %cond.store13 -; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm4[3,3,3,3] -; SSE2-NEXT: movd %xmm4, %esi -; SSE2-NEXT: movl %esi, 28(%rdx) -; SSE2-NEXT: testl $256, %ecx ## imm = 0x100 -; SSE2-NEXT: je LBB31_18 -; SSE2-NEXT: LBB31_17: ## %cond.store15 -; SSE2-NEXT: movl %r10d, 32(%rdx) -; SSE2-NEXT: testl $512, %ecx ## imm = 0x200 -; SSE2-NEXT: je LBB31_20 -; SSE2-NEXT: LBB31_19: ## %cond.store17 -; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm3[1,1,1,1] -; SSE2-NEXT: movd %xmm4, %esi -; SSE2-NEXT: movl %esi, 36(%rdx) -; SSE2-NEXT: testl $1024, %ecx ## imm = 0x400 -; SSE2-NEXT: je LBB31_22 -; SSE2-NEXT: LBB31_21: ## %cond.store19 -; SSE2-NEXT: pshufd {{.*#+}} xmm4 = xmm3[2,3,2,3] -; SSE2-NEXT: movd %xmm4, %esi -; SSE2-NEXT: movl %esi, 40(%rdx) -; SSE2-NEXT: testl $2048, %ecx ## imm = 0x800 -; SSE2-NEXT: je LBB31_24 -; SSE2-NEXT: LBB31_23: ## %cond.store21 -; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm3[3,3,3,3] -; SSE2-NEXT: movd %xmm3, %esi -; SSE2-NEXT: movl %esi, 44(%rdx) -; SSE2-NEXT: testl $4096, %ecx ## imm = 0x1000 -; SSE2-NEXT: je LBB31_26 -; SSE2-NEXT: LBB31_25: ## %cond.store23 -; SSE2-NEXT: movl %r9d, 48(%rdx) -; SSE2-NEXT: testl $8192, %ecx ## imm = 0x2000 -; SSE2-NEXT: je LBB31_28 -; SSE2-NEXT: LBB31_27: ## %cond.store25 -; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm2[1,1,1,1] -; SSE2-NEXT: movd %xmm3, %esi -; SSE2-NEXT: movl %esi, 52(%rdx) -; SSE2-NEXT: testl $16384, %ecx ## imm = 0x4000 -; SSE2-NEXT: je LBB31_30 -; SSE2-NEXT: LBB31_29: ## %cond.store27 -; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm2[2,3,2,3] -; SSE2-NEXT: movd %xmm3, %esi -; SSE2-NEXT: movl %esi, 56(%rdx) -; SSE2-NEXT: testw %cx, %cx -; SSE2-NEXT: jns LBB31_32 -; SSE2-NEXT: LBB31_31: ## %cond.store29 -; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm2[3,3,3,3] -; SSE2-NEXT: movd %xmm2, %esi -; SSE2-NEXT: movl %esi, 60(%rdx) -; SSE2-NEXT: testl $65536, %ecx ## imm = 0x10000 -; SSE2-NEXT: je LBB31_34 -; SSE2-NEXT: LBB31_33: ## %cond.store31 -; SSE2-NEXT: movl %r8d, 64(%rdx) -; SSE2-NEXT: testl $131072, %ecx ## imm = 0x20000 -; SSE2-NEXT: je LBB31_36 -; SSE2-NEXT: LBB31_35: ## %cond.store33 -; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm1[1,1,1,1] -; SSE2-NEXT: movd %xmm2, %esi -; SSE2-NEXT: movl %esi, 68(%rdx) -; SSE2-NEXT: testl $262144, %ecx ## imm = 0x40000 -; SSE2-NEXT: je LBB31_38 -; SSE2-NEXT: LBB31_37: ## %cond.store35 -; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm1[2,3,2,3] -; SSE2-NEXT: movd %xmm2, %esi -; SSE2-NEXT: movl %esi, 72(%rdx) -; SSE2-NEXT: testl $524288, %ecx ## imm = 0x80000 -; SSE2-NEXT: je LBB31_40 -; SSE2-NEXT: LBB31_39: ## %cond.store37 -; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[3,3,3,3] -; SSE2-NEXT: movd %xmm1, %esi -; SSE2-NEXT: movl %esi, 76(%rdx) -; SSE2-NEXT: testl $1048576, %ecx ## imm = 0x100000 -; SSE2-NEXT: je LBB31_42 -; SSE2-NEXT: LBB31_41: ## %cond.store39 -; SSE2-NEXT: movl %eax, 80(%rdx) -; SSE2-NEXT: testl $2097152, %ecx ## imm = 0x200000 -; SSE2-NEXT: je LBB31_44 -; SSE2-NEXT: LBB31_43: ## %cond.store41 -; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[1,1,1,1] -; SSE2-NEXT: movd %xmm1, %eax -; SSE2-NEXT: movl %eax, 84(%rdx) -; SSE2-NEXT: testl $4194304, %ecx ## imm = 0x400000 -; SSE2-NEXT: jne LBB31_45 -; SSE2-NEXT: jmp LBB31_46 -; -; SSE4-LABEL: store_v24i32_v24i32_stride6_vf4_only_even_numbered_elts: -; SSE4: ## %bb.0: -; SSE4-NEXT: pushq %rbp -; SSE4-NEXT: .cfi_def_cfa_offset 16 -; SSE4-NEXT: pushq %r15 -; SSE4-NEXT: .cfi_def_cfa_offset 24 -; SSE4-NEXT: pushq %r14 -; SSE4-NEXT: .cfi_def_cfa_offset 32 -; SSE4-NEXT: pushq %r13 -; SSE4-NEXT: .cfi_def_cfa_offset 40 -; SSE4-NEXT: pushq %r12 -; SSE4-NEXT: .cfi_def_cfa_offset 48 -; SSE4-NEXT: pushq %rbx -; SSE4-NEXT: .cfi_def_cfa_offset 56 -; SSE4-NEXT: .cfi_offset %rbx, -56 -; SSE4-NEXT: .cfi_offset %r12, -48 -; SSE4-NEXT: .cfi_offset %r13, -40 -; SSE4-NEXT: .cfi_offset %r14, -32 -; SSE4-NEXT: .cfi_offset %r15, -24 -; SSE4-NEXT: .cfi_offset %rbp, -16 -; SSE4-NEXT: movdqa (%rdi), %xmm1 -; SSE4-NEXT: movdqa 32(%rdi), %xmm2 -; SSE4-NEXT: movdqa 64(%rdi), %xmm0 -; SSE4-NEXT: movl 92(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 88(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 84(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 80(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 76(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 72(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 68(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 64(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 60(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 56(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: movl 52(%rsi), %eax -; SSE4-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill -; SSE4-NEXT: packssdw 48(%rdi), %xmm2 -; SSE4-NEXT: packssdw 16(%rdi), %xmm1 -; SSE4-NEXT: packsswb %xmm2, %xmm1 -; SSE4-NEXT: packssdw 80(%rdi), %xmm0 -; SSE4-NEXT: packsswb %xmm0, %xmm0 -; SSE4-NEXT: pmovmskb %xmm1, %eax -; SSE4-NEXT: andl $21845, %eax ## imm = 0x5555 -; SSE4-NEXT: pmovmskb %xmm0, %edi -; SSE4-NEXT: andl $85, %edi -; SSE4-NEXT: shll $16, %edi -; SSE4-NEXT: orl %eax, %edi -; SSE4-NEXT: movl 48(%rsi), %r13d -; SSE4-NEXT: testb $1, %dil -; SSE4-NEXT: movl 44(%rsi), %eax -; SSE4-NEXT: movl 40(%rsi), %ecx -; SSE4-NEXT: movl 36(%rsi), %r8d -; SSE4-NEXT: movl 32(%rsi), %r9d -; SSE4-NEXT: movl 28(%rsi), %r10d -; SSE4-NEXT: movl 24(%rsi), %r11d -; SSE4-NEXT: movl 20(%rsi), %ebx -; SSE4-NEXT: movl 16(%rsi), %ebp -; SSE4-NEXT: movl 12(%rsi), %r14d -; SSE4-NEXT: movl 8(%rsi), %r15d -; SSE4-NEXT: movl 4(%rsi), %r12d -; SSE4-NEXT: jne LBB31_1 -; SSE4-NEXT: ## %bb.2: ## %else -; SSE4-NEXT: testb $2, %dil -; SSE4-NEXT: jne LBB31_3 -; SSE4-NEXT: LBB31_4: ## %else2 -; SSE4-NEXT: testb $4, %dil -; SSE4-NEXT: jne LBB31_5 -; SSE4-NEXT: LBB31_6: ## %else4 -; SSE4-NEXT: testb $8, %dil -; SSE4-NEXT: jne LBB31_7 -; SSE4-NEXT: LBB31_8: ## %else6 -; SSE4-NEXT: testb $16, %dil -; SSE4-NEXT: jne LBB31_9 -; SSE4-NEXT: LBB31_10: ## %else8 -; SSE4-NEXT: testb $32, %dil -; SSE4-NEXT: jne LBB31_11 -; SSE4-NEXT: LBB31_12: ## %else10 -; SSE4-NEXT: testb $64, %dil -; SSE4-NEXT: jne LBB31_13 -; SSE4-NEXT: LBB31_14: ## %else12 -; SSE4-NEXT: testb %dil, %dil -; SSE4-NEXT: js LBB31_15 -; SSE4-NEXT: LBB31_16: ## %else14 -; SSE4-NEXT: testl $256, %edi ## imm = 0x100 -; SSE4-NEXT: jne LBB31_17 -; SSE4-NEXT: LBB31_18: ## %else16 -; SSE4-NEXT: testl $512, %edi ## imm = 0x200 -; SSE4-NEXT: jne LBB31_19 -; SSE4-NEXT: LBB31_20: ## %else18 -; SSE4-NEXT: testl $1024, %edi ## imm = 0x400 -; SSE4-NEXT: jne LBB31_21 -; SSE4-NEXT: LBB31_22: ## %else20 -; SSE4-NEXT: testl $2048, %edi ## imm = 0x800 -; SSE4-NEXT: jne LBB31_23 -; SSE4-NEXT: LBB31_24: ## %else22 -; SSE4-NEXT: testl $4096, %edi ## imm = 0x1000 -; SSE4-NEXT: jne LBB31_25 -; SSE4-NEXT: LBB31_26: ## %else24 -; SSE4-NEXT: testl $8192, %edi ## imm = 0x2000 -; SSE4-NEXT: jne LBB31_27 -; SSE4-NEXT: LBB31_28: ## %else26 -; SSE4-NEXT: testl $16384, %edi ## imm = 0x4000 -; SSE4-NEXT: jne LBB31_29 -; SSE4-NEXT: LBB31_30: ## %else28 -; SSE4-NEXT: testw %di, %di -; SSE4-NEXT: js LBB31_31 -; SSE4-NEXT: LBB31_32: ## %else30 -; SSE4-NEXT: testl $65536, %edi ## imm = 0x10000 -; SSE4-NEXT: jne LBB31_33 -; SSE4-NEXT: LBB31_34: ## %else32 -; SSE4-NEXT: testl $131072, %edi ## imm = 0x20000 -; SSE4-NEXT: jne LBB31_35 -; SSE4-NEXT: LBB31_36: ## %else34 -; SSE4-NEXT: testl $262144, %edi ## imm = 0x40000 -; SSE4-NEXT: jne LBB31_37 -; SSE4-NEXT: LBB31_38: ## %else36 -; SSE4-NEXT: testl $524288, %edi ## imm = 0x80000 -; SSE4-NEXT: jne LBB31_39 -; SSE4-NEXT: LBB31_40: ## %else38 -; SSE4-NEXT: testl $1048576, %edi ## imm = 0x100000 -; SSE4-NEXT: jne LBB31_41 -; SSE4-NEXT: LBB31_42: ## %else40 -; SSE4-NEXT: testl $2097152, %edi ## imm = 0x200000 -; SSE4-NEXT: jne LBB31_43 -; SSE4-NEXT: LBB31_44: ## %else42 -; SSE4-NEXT: testl $4194304, %edi ## imm = 0x400000 -; SSE4-NEXT: je LBB31_46 -; SSE4-NEXT: LBB31_45: ## %cond.store43 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 88(%rdx) -; SSE4-NEXT: LBB31_46: ## %else44 -; SSE4-NEXT: movb $1, %al -; SSE4-NEXT: testb %al, %al -; SSE4-NEXT: jne LBB31_48 -; SSE4-NEXT: ## %bb.47: ## %cond.store45 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 92(%rdx) -; SSE4-NEXT: LBB31_48: ## %else46 -; SSE4-NEXT: popq %rbx -; SSE4-NEXT: popq %r12 -; SSE4-NEXT: popq %r13 -; SSE4-NEXT: popq %r14 -; SSE4-NEXT: popq %r15 -; SSE4-NEXT: popq %rbp -; SSE4-NEXT: retq -; SSE4-NEXT: LBB31_1: ## %cond.store -; SSE4-NEXT: movl (%rsi), %esi -; SSE4-NEXT: movl %esi, (%rdx) -; SSE4-NEXT: testb $2, %dil -; SSE4-NEXT: je LBB31_4 -; SSE4-NEXT: LBB31_3: ## %cond.store1 -; SSE4-NEXT: movl %r12d, 4(%rdx) -; SSE4-NEXT: testb $4, %dil -; SSE4-NEXT: je LBB31_6 -; SSE4-NEXT: LBB31_5: ## %cond.store3 -; SSE4-NEXT: movl %r15d, 8(%rdx) -; SSE4-NEXT: testb $8, %dil -; SSE4-NEXT: je LBB31_8 -; SSE4-NEXT: LBB31_7: ## %cond.store5 -; SSE4-NEXT: movl %r14d, 12(%rdx) -; SSE4-NEXT: testb $16, %dil -; SSE4-NEXT: je LBB31_10 -; SSE4-NEXT: LBB31_9: ## %cond.store7 -; SSE4-NEXT: movl %ebp, 16(%rdx) -; SSE4-NEXT: testb $32, %dil -; SSE4-NEXT: je LBB31_12 -; SSE4-NEXT: LBB31_11: ## %cond.store9 -; SSE4-NEXT: movl %ebx, 20(%rdx) -; SSE4-NEXT: testb $64, %dil -; SSE4-NEXT: je LBB31_14 -; SSE4-NEXT: LBB31_13: ## %cond.store11 -; SSE4-NEXT: movl %r11d, 24(%rdx) -; SSE4-NEXT: testb %dil, %dil -; SSE4-NEXT: jns LBB31_16 -; SSE4-NEXT: LBB31_15: ## %cond.store13 -; SSE4-NEXT: movl %r10d, 28(%rdx) -; SSE4-NEXT: testl $256, %edi ## imm = 0x100 -; SSE4-NEXT: je LBB31_18 -; SSE4-NEXT: LBB31_17: ## %cond.store15 -; SSE4-NEXT: movl %r9d, 32(%rdx) -; SSE4-NEXT: testl $512, %edi ## imm = 0x200 -; SSE4-NEXT: je LBB31_20 -; SSE4-NEXT: LBB31_19: ## %cond.store17 -; SSE4-NEXT: movl %r8d, 36(%rdx) -; SSE4-NEXT: testl $1024, %edi ## imm = 0x400 -; SSE4-NEXT: je LBB31_22 -; SSE4-NEXT: LBB31_21: ## %cond.store19 -; SSE4-NEXT: movl %ecx, 40(%rdx) -; SSE4-NEXT: testl $2048, %edi ## imm = 0x800 -; SSE4-NEXT: je LBB31_24 -; SSE4-NEXT: LBB31_23: ## %cond.store21 -; SSE4-NEXT: movl %eax, 44(%rdx) -; SSE4-NEXT: testl $4096, %edi ## imm = 0x1000 -; SSE4-NEXT: je LBB31_26 -; SSE4-NEXT: LBB31_25: ## %cond.store23 -; SSE4-NEXT: movl %r13d, 48(%rdx) -; SSE4-NEXT: testl $8192, %edi ## imm = 0x2000 -; SSE4-NEXT: je LBB31_28 -; SSE4-NEXT: LBB31_27: ## %cond.store25 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 52(%rdx) -; SSE4-NEXT: testl $16384, %edi ## imm = 0x4000 -; SSE4-NEXT: je LBB31_30 -; SSE4-NEXT: LBB31_29: ## %cond.store27 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 56(%rdx) -; SSE4-NEXT: testw %di, %di -; SSE4-NEXT: jns LBB31_32 -; SSE4-NEXT: LBB31_31: ## %cond.store29 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 60(%rdx) -; SSE4-NEXT: testl $65536, %edi ## imm = 0x10000 -; SSE4-NEXT: je LBB31_34 -; SSE4-NEXT: LBB31_33: ## %cond.store31 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 64(%rdx) -; SSE4-NEXT: testl $131072, %edi ## imm = 0x20000 -; SSE4-NEXT: je LBB31_36 -; SSE4-NEXT: LBB31_35: ## %cond.store33 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 68(%rdx) -; SSE4-NEXT: testl $262144, %edi ## imm = 0x40000 -; SSE4-NEXT: je LBB31_38 -; SSE4-NEXT: LBB31_37: ## %cond.store35 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 72(%rdx) -; SSE4-NEXT: testl $524288, %edi ## imm = 0x80000 -; SSE4-NEXT: je LBB31_40 -; SSE4-NEXT: LBB31_39: ## %cond.store37 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 76(%rdx) -; SSE4-NEXT: testl $1048576, %edi ## imm = 0x100000 -; SSE4-NEXT: je LBB31_42 -; SSE4-NEXT: LBB31_41: ## %cond.store39 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 80(%rdx) -; SSE4-NEXT: testl $2097152, %edi ## imm = 0x200000 -; SSE4-NEXT: je LBB31_44 -; SSE4-NEXT: LBB31_43: ## %cond.store41 -; SSE4-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload -; SSE4-NEXT: movl %eax, 84(%rdx) -; SSE4-NEXT: testl $4194304, %edi ## imm = 0x400000 -; SSE4-NEXT: jne LBB31_45 -; SSE4-NEXT: jmp LBB31_46 +define void @store_v24i32_v24i32_stride6_vf4_only_even_numbered_elts(ptr %trigger.ptr, ptr %val.ptr, ptr %dst) nounwind { +; SSE-LABEL: store_v24i32_v24i32_stride6_vf4_only_even_numbered_elts: +; SSE: ## %bb.0: +; SSE-NEXT: pushq %rbp +; SSE-NEXT: pushq %r15 +; SSE-NEXT: pushq %r14 +; SSE-NEXT: pushq %r13 +; SSE-NEXT: pushq %r12 +; SSE-NEXT: pushq %rbx +; SSE-NEXT: movdqa (%rdi), %xmm1 +; SSE-NEXT: movdqa 32(%rdi), %xmm2 +; SSE-NEXT: movdqa 64(%rdi), %xmm0 +; SSE-NEXT: movl 92(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 88(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 84(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 80(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 76(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 72(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 68(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 64(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 60(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 56(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: movl 52(%rsi), %eax +; SSE-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; SSE-NEXT: packssdw 48(%rdi), %xmm2 +; SSE-NEXT: packssdw 16(%rdi), %xmm1 +; SSE-NEXT: packsswb %xmm2, %xmm1 +; SSE-NEXT: packssdw 80(%rdi), %xmm0 +; SSE-NEXT: packsswb %xmm0, %xmm0 +; SSE-NEXT: pmovmskb %xmm1, %eax +; SSE-NEXT: andl $21845, %eax ## imm = 0x5555 +; SSE-NEXT: pmovmskb %xmm0, %edi +; SSE-NEXT: andl $85, %edi +; SSE-NEXT: shll $16, %edi +; SSE-NEXT: orl %eax, %edi +; SSE-NEXT: movl 48(%rsi), %r13d +; SSE-NEXT: testb $1, %dil +; SSE-NEXT: movl 44(%rsi), %eax +; SSE-NEXT: movl 40(%rsi), %ecx +; SSE-NEXT: movl 36(%rsi), %r8d +; SSE-NEXT: movl 32(%rsi), %r9d +; SSE-NEXT: movl 28(%rsi), %r10d +; SSE-NEXT: movl 24(%rsi), %r11d +; SSE-NEXT: movl 20(%rsi), %ebx +; SSE-NEXT: movl 16(%rsi), %ebp +; SSE-NEXT: movl 12(%rsi), %r14d +; SSE-NEXT: movl 8(%rsi), %r15d +; SSE-NEXT: movl 4(%rsi), %r12d +; SSE-NEXT: jne LBB31_1 +; SSE-NEXT: ## %bb.2: ## %else +; SSE-NEXT: testb $2, %dil +; SSE-NEXT: jne LBB31_3 +; SSE-NEXT: LBB31_4: ## %else2 +; SSE-NEXT: testb $4, %dil +; SSE-NEXT: jne LBB31_5 +; SSE-NEXT: LBB31_6: ## %else4 +; SSE-NEXT: testb $8, %dil +; SSE-NEXT: jne LBB31_7 +; SSE-NEXT: LBB31_8: ## %else6 +; SSE-NEXT: testb $16, %dil +; SSE-NEXT: jne LBB31_9 +; SSE-NEXT: LBB31_10: ## %else8 +; SSE-NEXT: testb $32, %dil +; SSE-NEXT: jne LBB31_11 +; SSE-NEXT: LBB31_12: ## %else10 +; SSE-NEXT: testb $64, %dil +; SSE-NEXT: jne LBB31_13 +; SSE-NEXT: LBB31_14: ## %else12 +; SSE-NEXT: testb %dil, %dil +; SSE-NEXT: js LBB31_15 +; SSE-NEXT: LBB31_16: ## %else14 +; SSE-NEXT: testl $256, %edi ## imm = 0x100 +; SSE-NEXT: jne LBB31_17 +; SSE-NEXT: LBB31_18: ## %else16 +; SSE-NEXT: testl $512, %edi ## imm = 0x200 +; SSE-NEXT: jne LBB31_19 +; SSE-NEXT: LBB31_20: ## %else18 +; SSE-NEXT: testl $1024, %edi ## imm = 0x400 +; SSE-NEXT: jne LBB31_21 +; SSE-NEXT: LBB31_22: ## %else20 +; SSE-NEXT: testl $2048, %edi ## imm = 0x800 +; SSE-NEXT: jne LBB31_23 +; SSE-NEXT: LBB31_24: ## %else22 +; SSE-NEXT: testl $4096, %edi ## imm = 0x1000 +; SSE-NEXT: jne LBB31_25 +; SSE-NEXT: LBB31_26: ## %else24 +; SSE-NEXT: testl $8192, %edi ## imm = 0x2000 +; SSE-NEXT: jne LBB31_27 +; SSE-NEXT: LBB31_28: ## %else26 +; SSE-NEXT: testl $16384, %edi ## imm = 0x4000 +; SSE-NEXT: jne LBB31_29 +; SSE-NEXT: LBB31_30: ## %else28 +; SSE-NEXT: testw %di, %di +; SSE-NEXT: js LBB31_31 +; SSE-NEXT: LBB31_32: ## %else30 +; SSE-NEXT: testl $65536, %edi ## imm = 0x10000 +; SSE-NEXT: jne LBB31_33 +; SSE-NEXT: LBB31_34: ## %else32 +; SSE-NEXT: testl $131072, %edi ## imm = 0x20000 +; SSE-NEXT: jne LBB31_35 +; SSE-NEXT: LBB31_36: ## %else34 +; SSE-NEXT: testl $262144, %edi ## imm = 0x40000 +; SSE-NEXT: jne LBB31_37 +; SSE-NEXT: LBB31_38: ## %else36 +; SSE-NEXT: testl $524288, %edi ## imm = 0x80000 +; SSE-NEXT: jne LBB31_39 +; SSE-NEXT: LBB31_40: ## %else38 +; SSE-NEXT: testl $1048576, %edi ## imm = 0x100000 +; SSE-NEXT: jne LBB31_41 +; SSE-NEXT: LBB31_42: ## %else40 +; SSE-NEXT: testl $2097152, %edi ## imm = 0x200000 +; SSE-NEXT: jne LBB31_43 +; SSE-NEXT: LBB31_44: ## %else42 +; SSE-NEXT: testl $4194304, %edi ## imm = 0x400000 +; SSE-NEXT: je LBB31_46 +; SSE-NEXT: LBB31_45: ## %cond.store43 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 88(%rdx) +; SSE-NEXT: LBB31_46: ## %else44 +; SSE-NEXT: movb $1, %al +; SSE-NEXT: testb %al, %al +; SSE-NEXT: jne LBB31_48 +; SSE-NEXT: ## %bb.47: ## %cond.store45 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 92(%rdx) +; SSE-NEXT: LBB31_48: ## %else46 +; SSE-NEXT: popq %rbx +; SSE-NEXT: popq %r12 +; SSE-NEXT: popq %r13 +; SSE-NEXT: popq %r14 +; SSE-NEXT: popq %r15 +; SSE-NEXT: popq %rbp +; SSE-NEXT: retq +; SSE-NEXT: LBB31_1: ## %cond.store +; SSE-NEXT: movl (%rsi), %esi +; SSE-NEXT: movl %esi, (%rdx) +; SSE-NEXT: testb $2, %dil +; SSE-NEXT: je LBB31_4 +; SSE-NEXT: LBB31_3: ## %cond.store1 +; SSE-NEXT: movl %r12d, 4(%rdx) +; SSE-NEXT: testb $4, %dil +; SSE-NEXT: je LBB31_6 +; SSE-NEXT: LBB31_5: ## %cond.store3 +; SSE-NEXT: movl %r15d, 8(%rdx) +; SSE-NEXT: testb $8, %dil +; SSE-NEXT: je LBB31_8 +; SSE-NEXT: LBB31_7: ## %cond.store5 +; SSE-NEXT: movl %r14d, 12(%rdx) +; SSE-NEXT: testb $16, %dil +; SSE-NEXT: je LBB31_10 +; SSE-NEXT: LBB31_9: ## %cond.store7 +; SSE-NEXT: movl %ebp, 16(%rdx) +; SSE-NEXT: testb $32, %dil +; SSE-NEXT: je LBB31_12 +; SSE-NEXT: LBB31_11: ## %cond.store9 +; SSE-NEXT: movl %ebx, 20(%rdx) +; SSE-NEXT: testb $64, %dil +; SSE-NEXT: je LBB31_14 +; SSE-NEXT: LBB31_13: ## %cond.store11 +; SSE-NEXT: movl %r11d, 24(%rdx) +; SSE-NEXT: testb %dil, %dil +; SSE-NEXT: jns LBB31_16 +; SSE-NEXT: LBB31_15: ## %cond.store13 +; SSE-NEXT: movl %r10d, 28(%rdx) +; SSE-NEXT: testl $256, %edi ## imm = 0x100 +; SSE-NEXT: je LBB31_18 +; SSE-NEXT: LBB31_17: ## %cond.store15 +; SSE-NEXT: movl %r9d, 32(%rdx) +; SSE-NEXT: testl $512, %edi ## imm = 0x200 +; SSE-NEXT: je LBB31_20 +; SSE-NEXT: LBB31_19: ## %cond.store17 +; SSE-NEXT: movl %r8d, 36(%rdx) +; SSE-NEXT: testl $1024, %edi ## imm = 0x400 +; SSE-NEXT: je LBB31_22 +; SSE-NEXT: LBB31_21: ## %cond.store19 +; SSE-NEXT: movl %ecx, 40(%rdx) +; SSE-NEXT: testl $2048, %edi ## imm = 0x800 +; SSE-NEXT: je LBB31_24 +; SSE-NEXT: LBB31_23: ## %cond.store21 +; SSE-NEXT: movl %eax, 44(%rdx) +; SSE-NEXT: testl $4096, %edi ## imm = 0x1000 +; SSE-NEXT: je LBB31_26 +; SSE-NEXT: LBB31_25: ## %cond.store23 +; SSE-NEXT: movl %r13d, 48(%rdx) +; SSE-NEXT: testl $8192, %edi ## imm = 0x2000 +; SSE-NEXT: je LBB31_28 +; SSE-NEXT: LBB31_27: ## %cond.store25 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 52(%rdx) +; SSE-NEXT: testl $16384, %edi ## imm = 0x4000 +; SSE-NEXT: je LBB31_30 +; SSE-NEXT: LBB31_29: ## %cond.store27 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 56(%rdx) +; SSE-NEXT: testw %di, %di +; SSE-NEXT: jns LBB31_32 +; SSE-NEXT: LBB31_31: ## %cond.store29 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 60(%rdx) +; SSE-NEXT: testl $65536, %edi ## imm = 0x10000 +; SSE-NEXT: je LBB31_34 +; SSE-NEXT: LBB31_33: ## %cond.store31 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 64(%rdx) +; SSE-NEXT: testl $131072, %edi ## imm = 0x20000 +; SSE-NEXT: je LBB31_36 +; SSE-NEXT: LBB31_35: ## %cond.store33 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 68(%rdx) +; SSE-NEXT: testl $262144, %edi ## imm = 0x40000 +; SSE-NEXT: je LBB31_38 +; SSE-NEXT: LBB31_37: ## %cond.store35 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 72(%rdx) +; SSE-NEXT: testl $524288, %edi ## imm = 0x80000 +; SSE-NEXT: je LBB31_40 +; SSE-NEXT: LBB31_39: ## %cond.store37 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 76(%rdx) +; SSE-NEXT: testl $1048576, %edi ## imm = 0x100000 +; SSE-NEXT: je LBB31_42 +; SSE-NEXT: LBB31_41: ## %cond.store39 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 80(%rdx) +; SSE-NEXT: testl $2097152, %edi ## imm = 0x200000 +; SSE-NEXT: je LBB31_44 +; SSE-NEXT: LBB31_43: ## %cond.store41 +; SSE-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload +; SSE-NEXT: movl %eax, 84(%rdx) +; SSE-NEXT: testl $4194304, %edi ## imm = 0x400000 +; SSE-NEXT: jne LBB31_45 +; SSE-NEXT: jmp LBB31_46 ; ; AVX1-LABEL: store_v24i32_v24i32_stride6_vf4_only_even_numbered_elts: ; AVX1: ## %bb.0: @@ -6266,7 +6021,7 @@ define void @store_v24i32_v24i32_stride6_vf4_only_even_numbered_elts(ptr %trigge } ; From https://reviews.llvm.org/rGf8d9097168b7#1165311 -define void @undefshuffle(<8 x i1> %i0, ptr %src, ptr %dst) #0 { +define void @undefshuffle(<8 x i1> %i0, ptr %src, ptr %dst) nounwind { ; SSE2-LABEL: undefshuffle: ; SSE2: ## %bb.0: ## %else ; SSE2-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) diff --git a/llvm/test/CodeGen/X86/oddshuffles.ll b/llvm/test/CodeGen/X86/oddshuffles.ll index 5da18ee6ad7c4832d95cbe274168ef1e1e2e59a6..01056a8b2c24a986bd100a74953781f4223f41b5 100644 --- a/llvm/test/CodeGen/X86/oddshuffles.ll +++ b/llvm/test/CodeGen/X86/oddshuffles.ll @@ -2369,6 +2369,31 @@ define void @PR41097() { ret void } +; FIXME - should use INSERTPS +define <2 x float> @PR86068(<2 x float> %0, <2 x float> %1) { +; SSE2-LABEL: PR86068: +; SSE2: # %bb.0: # %entry +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1],xmm1[1,1] +; SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[2,0],xmm1[1,1] +; SSE2-NEXT: retq +; +; SSE42-LABEL: PR86068: +; SSE42: # %bb.0: # %entry +; SSE42-NEXT: movshdup {{.*#+}} xmm1 = xmm1[1,1,3,3] +; SSE42-NEXT: blendps {{.*#+}} xmm0 = xmm1[0],xmm0[1],xmm1[2,3] +; SSE42-NEXT: retq +; +; AVX-LABEL: PR86068: +; AVX: # %bb.0: # %entry +; AVX-NEXT: vmovshdup {{.*#+}} xmm1 = xmm1[1,1,3,3] +; AVX-NEXT: vblendps {{.*#+}} xmm0 = xmm1[0],xmm0[1],xmm1[2,3] +; AVX-NEXT: retq +entry: + %3 = shufflevector <2 x float> %1, <2 x float> poison, <2 x i32> <i32 1, i32 poison> + %4 = shufflevector <2 x float> %3, <2 x float> %0, <2 x i32> <i32 0, i32 3> + ret <2 x float> %4 +} + define void @D107009(ptr %input, ptr %output) { ; SSE-LABEL: D107009: ; SSE: # %bb.0: diff --git a/llvm/test/CodeGen/X86/optimize-max-0.ll b/llvm/test/CodeGen/X86/optimize-max-0.ll index 1bd427c4a4b0c2abd9afc78c0cd9e1136694fc9c..81dafdffe3116398c06ace9c532ce978f6cfab20 100644 --- a/llvm/test/CodeGen/X86/optimize-max-0.ll +++ b/llvm/test/CodeGen/X86/optimize-max-0.ll @@ -489,7 +489,6 @@ define void @bar(ptr %r, i32 %s, i32 %w, i32 %x, ptr %j, i32 %d) nounwind { ; CHECK-NEXT: jb LBB1_4 ; CHECK-NEXT: ## %bb.5: ## %bb9 ; CHECK-NEXT: ## in Loop: Header=BB1_4 Depth=1 -; CHECK-NEXT: movl %edi, %ebx ; CHECK-NEXT: incl %ecx ; CHECK-NEXT: addl {{[0-9]+}}(%esp), %eax ; CHECK-NEXT: addl %edi, %edx diff --git a/llvm/test/CodeGen/X86/pr45378.ll b/llvm/test/CodeGen/X86/pr45378.ll index 426f4eed662a09b8b2205ce98bcc5dcfdd2c08e3..6a5770a4b4ad30fed05f25bd254de7972e2f25e9 100644 --- a/llvm/test/CodeGen/X86/pr45378.ll +++ b/llvm/test/CodeGen/X86/pr45378.ll @@ -1,10 +1,10 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse2 | FileCheck %s --check-prefix=SSE2 -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse4.1 | FileCheck %s --check-prefix=SSE41 -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx | FileCheck %s --check-prefix=AVX -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx2 | FileCheck %s --check-prefix=AVX -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx512f | FileCheck %s --check-prefix=AVX -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx512bw | FileCheck %s --check-prefix=AVX +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse2 | FileCheck %s --check-prefixes=CHECK,SSE2 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse4.1 | FileCheck %s --check-prefixes=CHECK,SSE41 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx | FileCheck %s --check-prefixes=CHECK,AVX +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx2 | FileCheck %s --check-prefixes=CHECK,AVX +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx512f | FileCheck %s --check-prefixes=CHECK,AVX +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx512bw | FileCheck %s --check-prefixes=CHECK,AVX declare i64 @llvm.vector.reduce.or.v2i64(<2 x i64>) @@ -71,28 +71,12 @@ define i1 @parseHeaders2_scalar_or(ptr %ptr) nounwind { } define i1 @parseHeaders2_scalar_and(ptr %ptr) nounwind { -; SSE2-LABEL: parseHeaders2_scalar_and: -; SSE2: # %bb.0: -; SSE2-NEXT: movdqu (%rdi), %xmm0 -; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] -; SSE2-NEXT: movq %xmm0, %rax -; SSE2-NEXT: testq %rax, (%rdi) -; SSE2-NEXT: sete %al -; SSE2-NEXT: retq -; -; SSE41-LABEL: parseHeaders2_scalar_and: -; SSE41: # %bb.0: -; SSE41-NEXT: movq (%rdi), %rax -; SSE41-NEXT: testq %rax, 8(%rdi) -; SSE41-NEXT: sete %al -; SSE41-NEXT: retq -; -; AVX-LABEL: parseHeaders2_scalar_and: -; AVX: # %bb.0: -; AVX-NEXT: movq (%rdi), %rax -; AVX-NEXT: testq %rax, 8(%rdi) -; AVX-NEXT: sete %al -; AVX-NEXT: retq +; CHECK-LABEL: parseHeaders2_scalar_and: +; CHECK: # %bb.0: +; CHECK-NEXT: movq (%rdi), %rax +; CHECK-NEXT: testq %rax, 8(%rdi) +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq %vload = load <2 x i64>, ptr %ptr, align 8 %v1 = extractelement <2 x i64> %vload, i32 0 %v2 = extractelement <2 x i64> %vload, i32 1 diff --git a/llvm/test/CodeGen/X86/pr85681.ll b/llvm/test/CodeGen/X86/pr85681.ll new file mode 100644 index 0000000000000000000000000000000000000000..3b27a0257ab43d28227deb5e1bd0a9eaf4a97e33 --- /dev/null +++ b/llvm/test/CodeGen/X86/pr85681.ll @@ -0,0 +1,41 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=x86_64-- -mcpu=emeraldrapids | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64 | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64-v2 | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64-v3 | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-- -mcpu=x86-64-v4 | FileCheck %s + +; PR85681 - shift i1/vXi1 X, Y -> X as only Y==0 is defined + +define i32 @shl(i32 %a0) { +; CHECK-LABEL: shl: +; CHECK: # %bb.0: +; CHECK-NEXT: movl $-1, %eax +; CHECK-NEXT: retq + %v0 = bitcast i32 %a0 to <32 x i1> + %s = shl <32 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>, %v0 + %r = bitcast <32 x i1> %s to i32 + ret i32 %r +} + +define i32 @lshr(i32 %a0) { +; CHECK-LABEL: lshr: +; CHECK: # %bb.0: +; CHECK-NEXT: movl $-1, %eax +; CHECK-NEXT: retq + %v0 = bitcast i32 %a0 to <32 x i1> + %s = lshr <32 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>, %v0 + %r = bitcast <32 x i1> %s to i32 + ret i32 %r +} + +define i32 @ashr(i32 %a0) { +; CHECK-LABEL: ashr: +; CHECK: # %bb.0: +; CHECK-NEXT: movl $-1, %eax +; CHECK-NEXT: retq + %v0 = bitcast i32 %a0 to <32 x i1> + %s = ashr <32 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>, %v0 + %r = bitcast <32 x i1> %s to i32 + ret i32 %r +} diff --git a/llvm/test/CodeGen/X86/pr86305.ll b/llvm/test/CodeGen/X86/pr86305.ll new file mode 100644 index 0000000000000000000000000000000000000000..79b42bb2532ca9da5880d4bd1fabfa72a0d01476 --- /dev/null +++ b/llvm/test/CodeGen/X86/pr86305.ll @@ -0,0 +1,74 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=x86_64-linux-gnu -mattr=avx512bf16 | FileCheck %s + +define void @add(ptr %pa, ptr %pb, ptr %pc) nounwind { +; CHECK-LABEL: add: +; CHECK: # %bb.0: +; CHECK-NEXT: pushq %rbx +; CHECK-NEXT: movq %rdx, %rbx +; CHECK-NEXT: movzwl (%rsi), %eax +; CHECK-NEXT: shll $16, %eax +; CHECK-NEXT: vmovd %eax, %xmm0 +; CHECK-NEXT: movzwl (%rdi), %eax +; CHECK-NEXT: shll $16, %eax +; CHECK-NEXT: vmovd %eax, %xmm1 +; CHECK-NEXT: vaddss %xmm0, %xmm1, %xmm0 +; CHECK-NEXT: callq __truncsfbf2@PLT +; CHECK-NEXT: vpextrw $0, %xmm0, (%rbx) +; CHECK-NEXT: popq %rbx +; CHECK-NEXT: retq + %a = load bfloat, ptr %pa + %b = load bfloat, ptr %pb + %add = fadd bfloat %a, %b + store bfloat %add, ptr %pc + ret void +} + +define <4 x bfloat> @fptrunc_v4f32(<4 x float> %a) nounwind { +; CHECK-LABEL: fptrunc_v4f32: +; CHECK: # %bb.0: +; CHECK-NEXT: pushq %rbp +; CHECK-NEXT: pushq %r15 +; CHECK-NEXT: pushq %r14 +; CHECK-NEXT: pushq %rbx +; CHECK-NEXT: subq $72, %rsp +; CHECK-NEXT: vmovaps %xmm0, (%rsp) # 16-byte Spill +; CHECK-NEXT: callq __truncsfbf2@PLT +; CHECK-NEXT: vmovaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; CHECK-NEXT: vpermilpd $1, (%rsp), %xmm0 # 16-byte Folded Reload +; CHECK-NEXT: # xmm0 = mem[1,0] +; CHECK-NEXT: callq __truncsfbf2@PLT +; CHECK-NEXT: vmovapd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; CHECK-NEXT: vpshufd $255, (%rsp), %xmm0 # 16-byte Folded Reload +; CHECK-NEXT: # xmm0 = mem[3,3,3,3] +; CHECK-NEXT: callq __truncsfbf2@PLT +; CHECK-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; CHECK-NEXT: callq __truncsfbf2@PLT +; CHECK-NEXT: vpextrw $0, %xmm0, %ebx +; CHECK-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload +; CHECK-NEXT: vpextrw $0, %xmm0, %ebp +; CHECK-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload +; CHECK-NEXT: vpextrw $0, %xmm0, %r14d +; CHECK-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload +; CHECK-NEXT: vpextrw $0, %xmm0, %r15d +; CHECK-NEXT: vmovshdup (%rsp), %xmm0 # 16-byte Folded Reload +; CHECK-NEXT: # xmm0 = mem[1,1,3,3] +; CHECK-NEXT: callq __truncsfbf2@PLT +; CHECK-NEXT: vpextrw $0, %xmm0, %eax +; CHECK-NEXT: vmovd %r15d, %xmm0 +; CHECK-NEXT: vpinsrw $1, %eax, %xmm0, %xmm0 +; CHECK-NEXT: vpinsrw $2, %r14d, %xmm0, %xmm0 +; CHECK-NEXT: vpinsrw $3, %ebp, %xmm0, %xmm0 +; CHECK-NEXT: vpinsrw $4, %ebx, %xmm0, %xmm0 +; CHECK-NEXT: vpinsrw $5, %ebx, %xmm0, %xmm0 +; CHECK-NEXT: vpinsrw $6, %ebx, %xmm0, %xmm0 +; CHECK-NEXT: vpinsrw $7, %ebx, %xmm0, %xmm0 +; CHECK-NEXT: addq $72, %rsp +; CHECK-NEXT: popq %rbx +; CHECK-NEXT: popq %r14 +; CHECK-NEXT: popq %r15 +; CHECK-NEXT: popq %rbp +; CHECK-NEXT: retq + %b = fptrunc <4 x float> %a to <4 x bfloat> + ret <4 x bfloat> %b +} diff --git a/llvm/test/CodeGen/X86/pr86880.mir b/llvm/test/CodeGen/X86/pr86880.mir new file mode 100644 index 0000000000000000000000000000000000000000..92ebf9a265bb9562aa2dcdf12222b06c81f2659f --- /dev/null +++ b/llvm/test/CodeGen/X86/pr86880.mir @@ -0,0 +1,21 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4 +# RUN: llc -mtriple=x86_64-- -run-pass=machine-cp -o - %s | FileCheck %s + +--- +name: foo +tracksRegLiveness: true +body: | + bb.0: + liveins: $eax + + ; CHECK-LABEL: name: foo + ; CHECK: liveins: $eax + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: INLINEASM &"", 0 /* attdialect */, 10 /* regdef */, implicit-def dead $eax, 2686986 /* regdef:GR32_NOREX2 */, def renamable $r15d, 10 /* regdef */, implicit-def dead $ecx, 10 /* regdef */, implicit-def dead $edx, 2147483657 /* reguse tiedto:$0 */, $eax(tied-def 3) + ; CHECK-NEXT: renamable $ecx = COPY killed renamable $r15d + ; CHECK-NEXT: NOOP implicit $ecx + INLINEASM &"", 0 /* attdialect */, 10 /* regdef */, implicit-def dead $eax, 2686986 /* regdef:GR32_NOREX2 */, def renamable $r15d, 10 /* regdef */, implicit-def dead $ecx, 10 /* regdef */, implicit-def dead $edx, 2147483657 /* reguse tiedto:$0 */, $eax(tied-def 3) + renamable $ecx = COPY killed renamable $r15d + NOOP implicit $ecx + +... diff --git a/llvm/test/CodeGen/X86/regalloc-copy-hints.mir b/llvm/test/CodeGen/X86/regalloc-copy-hints.mir index 13b5a541fa2282c79bbce6373f9de3ad702625ea..d09bcd6a6b402dcd3e42d72e05ac51dab20d01f7 100644 --- a/llvm/test/CodeGen/X86/regalloc-copy-hints.mir +++ b/llvm/test/CodeGen/X86/regalloc-copy-hints.mir @@ -103,6 +103,7 @@ registers: - { id: 82, class: gr32 } frameInfo: maxAlignment: 4 + adjustsStack: true hasCalls: true fixedStack: - { id: 0, size: 4, alignment: 4, stack-id: default, isImmutable: true } diff --git a/llvm/test/CodeGen/X86/sar_fold.ll b/llvm/test/CodeGen/X86/sar_fold.ll index 21655e19440afeecd94b11351a1e5ae55b586e41..0f1396954b03a16e8fdb9993571bac171c3d3e2b 100644 --- a/llvm/test/CodeGen/X86/sar_fold.ll +++ b/llvm/test/CodeGen/X86/sar_fold.ll @@ -44,3 +44,44 @@ define i32 @shl24sar25(i32 %a) #0 { %2 = ashr exact i32 %1, 25 ret i32 %2 } + +define void @shl144sar48(ptr %p) #0 { +; CHECK-LABEL: shl144sar48: +; CHECK: # %bb.0: +; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax +; CHECK-NEXT: movswl (%eax), %ecx +; CHECK-NEXT: movl %ecx, %edx +; CHECK-NEXT: sarl $31, %edx +; CHECK-NEXT: shldl $2, %ecx, %edx +; CHECK-NEXT: shll $2, %ecx +; CHECK-NEXT: movl %ecx, 12(%eax) +; CHECK-NEXT: movl %edx, 16(%eax) +; CHECK-NEXT: movl $0, 8(%eax) +; CHECK-NEXT: movl $0, 4(%eax) +; CHECK-NEXT: movl $0, (%eax) +; CHECK-NEXT: retl + %a = load i160, ptr %p + %1 = shl i160 %a, 144 + %2 = ashr exact i160 %1, 46 + store i160 %2, ptr %p + ret void +} + +define void @shl144sar2(ptr %p) #0 { +; CHECK-LABEL: shl144sar2: +; CHECK: # %bb.0: +; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax +; CHECK-NEXT: movswl (%eax), %ecx +; CHECK-NEXT: shll $14, %ecx +; CHECK-NEXT: movl %ecx, 16(%eax) +; CHECK-NEXT: movl $0, 8(%eax) +; CHECK-NEXT: movl $0, 12(%eax) +; CHECK-NEXT: movl $0, 4(%eax) +; CHECK-NEXT: movl $0, (%eax) +; CHECK-NEXT: retl + %a = load i160, ptr %p + %1 = shl i160 %a, 144 + %2 = ashr exact i160 %1, 2 + store i160 %2, ptr %p + ret void +} diff --git a/llvm/test/CodeGen/X86/setcc-non-simple-type.ll b/llvm/test/CodeGen/X86/setcc-non-simple-type.ll index 2187c653f76c3b9c628f1bfe197115aa55ff4f3d..97c3c2040b2914cfe75e3827d6a0dc33882a4968 100644 --- a/llvm/test/CodeGen/X86/setcc-non-simple-type.ll +++ b/llvm/test/CodeGen/X86/setcc-non-simple-type.ll @@ -60,36 +60,30 @@ define void @failing(ptr %0, ptr %1) nounwind { ; CHECK-NEXT: .LBB0_2: # %vector.body ; CHECK-NEXT: # Parent Loop BB0_1 Depth=1 ; CHECK-NEXT: # => This Inner Loop Header: Depth=2 -; CHECK-NEXT: movdqu 1024(%rdx,%rdi), %xmm5 -; CHECK-NEXT: movdqu 1040(%rdx,%rdi), %xmm6 -; CHECK-NEXT: pshufd {{.*#+}} xmm5 = xmm5[2,3,2,3] -; CHECK-NEXT: movq %xmm5, %r8 -; CHECK-NEXT: pshufd {{.*#+}} xmm5 = xmm6[2,3,2,3] -; CHECK-NEXT: movq %xmm5, %r9 -; CHECK-NEXT: cmpq 1040(%rdx,%rdi), %rsi -; CHECK-NEXT: movq %rcx, %r10 -; CHECK-NEXT: sbbq %r9, %r10 -; CHECK-NEXT: setge %r9b -; CHECK-NEXT: movzbl %r9b, %r9d -; CHECK-NEXT: andl $1, %r9d -; CHECK-NEXT: negq %r9 -; CHECK-NEXT: movq %r9, %xmm5 ; CHECK-NEXT: cmpq 1024(%rdx,%rdi), %rsi -; CHECK-NEXT: movq %rcx, %r9 -; CHECK-NEXT: sbbq %r8, %r9 +; CHECK-NEXT: movq %rcx, %r8 +; CHECK-NEXT: sbbq 1032(%rdx,%rdi), %r8 +; CHECK-NEXT: setge %r8b +; CHECK-NEXT: movzbl %r8b, %r8d +; CHECK-NEXT: andl $1, %r8d +; CHECK-NEXT: negq %r8 +; CHECK-NEXT: movq %r8, %xmm5 +; CHECK-NEXT: cmpq 1040(%rdx,%rdi), %rsi +; CHECK-NEXT: movq %rcx, %r8 +; CHECK-NEXT: sbbq 1048(%rdx,%rdi), %r8 ; CHECK-NEXT: setge %r8b ; CHECK-NEXT: movzbl %r8b, %r8d ; CHECK-NEXT: andl $1, %r8d ; CHECK-NEXT: negq %r8 ; CHECK-NEXT: movq %r8, %xmm6 -; CHECK-NEXT: punpcklqdq {{.*#+}} xmm6 = xmm6[0],xmm5[0] -; CHECK-NEXT: movdqa %xmm1, %xmm5 -; CHECK-NEXT: psllq %xmm4, %xmm5 +; CHECK-NEXT: punpcklqdq {{.*#+}} xmm5 = xmm5[0],xmm6[0] +; CHECK-NEXT: movdqa %xmm1, %xmm6 +; CHECK-NEXT: psllq %xmm4, %xmm6 ; CHECK-NEXT: pshufd {{.*#+}} xmm7 = xmm4[2,3,2,3] ; CHECK-NEXT: movdqa %xmm1, %xmm8 ; CHECK-NEXT: psllq %xmm7, %xmm8 -; CHECK-NEXT: movsd {{.*#+}} xmm8 = xmm5[0],xmm8[1] -; CHECK-NEXT: andpd %xmm6, %xmm8 +; CHECK-NEXT: movsd {{.*#+}} xmm8 = xmm6[0],xmm8[1] +; CHECK-NEXT: andpd %xmm5, %xmm8 ; CHECK-NEXT: orpd %xmm8, %xmm3 ; CHECK-NEXT: paddq %xmm2, %xmm4 ; CHECK-NEXT: addq $32, %rdi diff --git a/llvm/test/CodeGen/X86/shrink_vmul.ll b/llvm/test/CodeGen/X86/shrink_vmul.ll index 2610f4322c8e2b1e3adadf77973b27d9305c3a7f..62051d17099403aa0b13a21624b53cf4c06c63ce 100644 --- a/llvm/test/CodeGen/X86/shrink_vmul.ll +++ b/llvm/test/CodeGen/X86/shrink_vmul.ll @@ -1983,91 +1983,75 @@ define void @PR34947(ptr %p0, ptr %p1) nounwind { ; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %eax ; X86-SSE-NEXT: movzwl 16(%eax), %edx ; X86-SSE-NEXT: movl %edx, (%esp) # 4-byte Spill -; X86-SSE-NEXT: movdqa (%eax), %xmm3 -; X86-SSE-NEXT: movdqa (%ecx), %xmm0 -; X86-SSE-NEXT: movdqa 16(%ecx), %xmm1 -; X86-SSE-NEXT: pxor %xmm5, %xmm5 -; X86-SSE-NEXT: movdqa %xmm3, %xmm2 -; X86-SSE-NEXT: pextrw $7, %xmm3, %eax -; X86-SSE-NEXT: pextrw $4, %xmm3, %edi -; X86-SSE-NEXT: pextrw $0, %xmm3, %ebp -; X86-SSE-NEXT: pextrw $1, %xmm3, %esi -; X86-SSE-NEXT: pextrw $3, %xmm3, %ebx -; X86-SSE-NEXT: movdqa %xmm3, %xmm4 -; X86-SSE-NEXT: punpcklwd {{.*#+}} xmm4 = xmm4[0],xmm5[0],xmm4[1],xmm5[1],xmm4[2],xmm5[2],xmm4[3],xmm5[3] -; X86-SSE-NEXT: punpckhwd {{.*#+}} xmm2 = xmm2[4],xmm5[4],xmm2[5],xmm5[5],xmm2[6],xmm5[6],xmm2[7],xmm5[7] -; X86-SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm1[3,3,3,3] -; X86-SSE-NEXT: movd %xmm3, %ecx +; X86-SSE-NEXT: movdqa (%eax), %xmm2 +; X86-SSE-NEXT: pxor %xmm1, %xmm1 +; X86-SSE-NEXT: movdqa %xmm2, %xmm0 +; X86-SSE-NEXT: pextrw $7, %xmm2, %eax +; X86-SSE-NEXT: pextrw $4, %xmm2, %esi +; X86-SSE-NEXT: pextrw $1, %xmm2, %edi +; X86-SSE-NEXT: pextrw $0, %xmm2, %ebx +; X86-SSE-NEXT: pextrw $3, %xmm2, %ebp +; X86-SSE-NEXT: punpcklwd {{.*#+}} xmm2 = xmm2[0],xmm1[0],xmm2[1],xmm1[1],xmm2[2],xmm1[2],xmm2[3],xmm1[3] +; X86-SSE-NEXT: punpckhwd {{.*#+}} xmm0 = xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] +; X86-SSE-NEXT: xorl %edx, %edx +; X86-SSE-NEXT: divl 28(%ecx) +; X86-SSE-NEXT: movd %edx, %xmm1 +; X86-SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm0[2,3,2,3] +; X86-SSE-NEXT: movd %xmm3, %eax ; X86-SSE-NEXT: xorl %edx, %edx -; X86-SSE-NEXT: divl %ecx +; X86-SSE-NEXT: divl 24(%ecx) ; X86-SSE-NEXT: movd %edx, %xmm3 -; X86-SSE-NEXT: pshufd {{.*#+}} xmm5 = xmm2[2,3,2,3] -; X86-SSE-NEXT: movd %xmm5, %eax -; X86-SSE-NEXT: pshufd {{.*#+}} xmm5 = xmm1[2,3,2,3] -; X86-SSE-NEXT: movd %xmm5, %ecx +; X86-SSE-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm1[0],xmm3[1],xmm1[1] +; X86-SSE-NEXT: movl %esi, %eax ; X86-SSE-NEXT: xorl %edx, %edx -; X86-SSE-NEXT: divl %ecx -; X86-SSE-NEXT: movd %edx, %xmm5 -; X86-SSE-NEXT: punpckldq {{.*#+}} xmm5 = xmm5[0],xmm3[0],xmm5[1],xmm3[1] +; X86-SSE-NEXT: divl 16(%ecx) +; X86-SSE-NEXT: movd %edx, %xmm1 +; X86-SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,1,1] +; X86-SSE-NEXT: movd %xmm0, %eax +; X86-SSE-NEXT: xorl %edx, %edx +; X86-SSE-NEXT: divl 20(%ecx) +; X86-SSE-NEXT: movd %edx, %xmm0 +; X86-SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] +; X86-SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm3[0] ; X86-SSE-NEXT: movl %edi, %eax ; X86-SSE-NEXT: xorl %edx, %edx -; X86-SSE-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-SSE-NEXT: divl 16(%edi) +; X86-SSE-NEXT: divl 4(%ecx) ; X86-SSE-NEXT: movd %edx, %xmm3 -; X86-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm2[1,1,1,1] -; X86-SSE-NEXT: movd %xmm2, %eax -; X86-SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm1[1,1,1,1] -; X86-SSE-NEXT: movd %xmm1, %ecx +; X86-SSE-NEXT: movl %ebx, %eax ; X86-SSE-NEXT: xorl %edx, %edx -; X86-SSE-NEXT: divl %ecx -; X86-SSE-NEXT: movd %edx, %xmm1 -; X86-SSE-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm1[0],xmm3[1],xmm1[1] -; X86-SSE-NEXT: punpcklqdq {{.*#+}} xmm3 = xmm3[0],xmm5[0] +; X86-SSE-NEXT: divl (%ecx) +; X86-SSE-NEXT: movd %edx, %xmm0 +; X86-SSE-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1] ; X86-SSE-NEXT: movl %ebp, %eax ; X86-SSE-NEXT: xorl %edx, %edx -; X86-SSE-NEXT: divl (%edi) -; X86-SSE-NEXT: movd %edx, %xmm1 -; X86-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm0[1,1,1,1] -; X86-SSE-NEXT: movd %xmm2, %ecx -; X86-SSE-NEXT: movl %esi, %eax -; X86-SSE-NEXT: xorl %edx, %edx -; X86-SSE-NEXT: divl %ecx -; X86-SSE-NEXT: movd %edx, %xmm2 -; X86-SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1] -; X86-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm0[3,3,3,3] -; X86-SSE-NEXT: movd %xmm2, %ecx -; X86-SSE-NEXT: movl %ebx, %eax +; X86-SSE-NEXT: divl 12(%ecx) +; X86-SSE-NEXT: movd %edx, %xmm3 +; X86-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm2[2,3,2,3] +; X86-SSE-NEXT: movd %xmm2, %eax ; X86-SSE-NEXT: xorl %edx, %edx -; X86-SSE-NEXT: divl %ecx +; X86-SSE-NEXT: divl 8(%ecx) ; X86-SSE-NEXT: movd %edx, %xmm2 -; X86-SSE-NEXT: pshufd {{.*#+}} xmm4 = xmm4[2,3,2,3] -; X86-SSE-NEXT: movd %xmm4, %eax -; X86-SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] -; X86-SSE-NEXT: movd %xmm0, %ecx -; X86-SSE-NEXT: xorl %edx, %edx -; X86-SSE-NEXT: divl %ecx -; X86-SSE-NEXT: movd %edx, %xmm0 -; X86-SSE-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1] -; X86-SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm0[0] +; X86-SSE-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm3[0],xmm2[1],xmm3[1] +; X86-SSE-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm2[0] ; X86-SSE-NEXT: movl (%esp), %eax # 4-byte Reload ; X86-SSE-NEXT: xorl %edx, %edx -; X86-SSE-NEXT: divl 32(%edi) +; X86-SSE-NEXT: divl 32(%ecx) ; X86-SSE-NEXT: movdqa {{.*#+}} xmm2 = [8199,8199,8199,8199] -; X86-SSE-NEXT: pshufd {{.*#+}} xmm4 = xmm1[1,1,3,3] -; X86-SSE-NEXT: pmuludq %xmm2, %xmm1 -; X86-SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm1[0,2,2,3] -; X86-SSE-NEXT: pmuludq %xmm2, %xmm4 -; X86-SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm4[0,2,2,3] -; X86-SSE-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1] -; X86-SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm3[1,1,3,3] +; X86-SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm0[1,1,3,3] +; X86-SSE-NEXT: pmuludq %xmm2, %xmm0 +; X86-SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm0[0,2,2,3] ; X86-SSE-NEXT: pmuludq %xmm2, %xmm3 ; X86-SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm3[0,2,2,3] +; X86-SSE-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1] +; X86-SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm1[1,1,3,3] ; X86-SSE-NEXT: pmuludq %xmm2, %xmm1 ; X86-SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm1[0,2,2,3] -; X86-SSE-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm1[0],xmm3[1],xmm1[1] +; X86-SSE-NEXT: pmuludq %xmm2, %xmm3 +; X86-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm3[0,2,2,3] +; X86-SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1] ; X86-SSE-NEXT: imull $8199, %edx, %eax # imm = 0x2007 ; X86-SSE-NEXT: movl %eax, (%eax) -; X86-SSE-NEXT: movdqa %xmm3, (%eax) +; X86-SSE-NEXT: movdqa %xmm1, (%eax) ; X86-SSE-NEXT: movdqa %xmm0, (%eax) ; X86-SSE-NEXT: addl $4, %esp ; X86-SSE-NEXT: popl %esi @@ -2204,91 +2188,76 @@ define void @PR34947(ptr %p0, ptr %p1) nounwind { ; X64-SSE-LABEL: PR34947: ; X64-SSE: # %bb.0: ; X64-SSE-NEXT: movzwl 16(%rdi), %ecx -; X64-SSE-NEXT: movdqa (%rdi), %xmm3 -; X64-SSE-NEXT: movdqa (%rsi), %xmm0 -; X64-SSE-NEXT: movdqa 16(%rsi), %xmm1 -; X64-SSE-NEXT: pxor %xmm5, %xmm5 -; X64-SSE-NEXT: movdqa %xmm3, %xmm2 -; X64-SSE-NEXT: pextrw $7, %xmm3, %eax -; X64-SSE-NEXT: pextrw $4, %xmm3, %r8d -; X64-SSE-NEXT: pextrw $0, %xmm3, %r10d -; X64-SSE-NEXT: pextrw $1, %xmm3, %edi -; X64-SSE-NEXT: pextrw $3, %xmm3, %r9d -; X64-SSE-NEXT: movdqa %xmm3, %xmm4 -; X64-SSE-NEXT: punpcklwd {{.*#+}} xmm4 = xmm4[0],xmm5[0],xmm4[1],xmm5[1],xmm4[2],xmm5[2],xmm4[3],xmm5[3] -; X64-SSE-NEXT: punpckhwd {{.*#+}} xmm2 = xmm2[4],xmm5[4],xmm2[5],xmm5[5],xmm2[6],xmm5[6],xmm2[7],xmm5[7] -; X64-SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm1[3,3,3,3] -; X64-SSE-NEXT: movd %xmm3, %r11d -; X64-SSE-NEXT: xorl %edx, %edx -; X64-SSE-NEXT: divl %r11d -; X64-SSE-NEXT: movd %edx, %xmm3 -; X64-SSE-NEXT: pshufd {{.*#+}} xmm5 = xmm2[2,3,2,3] -; X64-SSE-NEXT: movd %xmm5, %eax -; X64-SSE-NEXT: pshufd {{.*#+}} xmm5 = xmm1[2,3,2,3] -; X64-SSE-NEXT: movd %xmm5, %r11d +; X64-SSE-NEXT: movdqa (%rdi), %xmm2 +; X64-SSE-NEXT: pxor %xmm1, %xmm1 +; X64-SSE-NEXT: movdqa %xmm2, %xmm0 +; X64-SSE-NEXT: pextrw $7, %xmm2, %eax +; X64-SSE-NEXT: pextrw $4, %xmm2, %edi +; X64-SSE-NEXT: pextrw $1, %xmm2, %r8d +; X64-SSE-NEXT: pextrw $0, %xmm2, %r9d +; X64-SSE-NEXT: pextrw $3, %xmm2, %r10d +; X64-SSE-NEXT: punpcklwd {{.*#+}} xmm2 = xmm2[0],xmm1[0],xmm2[1],xmm1[1],xmm2[2],xmm1[2],xmm2[3],xmm1[3] +; X64-SSE-NEXT: punpckhwd {{.*#+}} xmm0 = xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] ; X64-SSE-NEXT: xorl %edx, %edx -; X64-SSE-NEXT: divl %r11d -; X64-SSE-NEXT: movd %edx, %xmm5 -; X64-SSE-NEXT: punpckldq {{.*#+}} xmm5 = xmm5[0],xmm3[0],xmm5[1],xmm3[1] -; X64-SSE-NEXT: movl %r8d, %eax +; X64-SSE-NEXT: divl 28(%rsi) +; X64-SSE-NEXT: movd %edx, %xmm1 +; X64-SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm0[2,3,2,3] +; X64-SSE-NEXT: movd %xmm3, %eax ; X64-SSE-NEXT: xorl %edx, %edx -; X64-SSE-NEXT: divl 16(%rsi) +; X64-SSE-NEXT: divl 24(%rsi) ; X64-SSE-NEXT: movd %edx, %xmm3 -; X64-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm2[1,1,1,1] -; X64-SSE-NEXT: movd %xmm2, %eax -; X64-SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm1[1,1,1,1] -; X64-SSE-NEXT: movd %xmm1, %r8d -; X64-SSE-NEXT: xorl %edx, %edx -; X64-SSE-NEXT: divl %r8d -; X64-SSE-NEXT: movd %edx, %xmm1 ; X64-SSE-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm1[0],xmm3[1],xmm1[1] -; X64-SSE-NEXT: punpcklqdq {{.*#+}} xmm3 = xmm3[0],xmm5[0] -; X64-SSE-NEXT: movl %r10d, %eax +; X64-SSE-NEXT: movl %edi, %eax ; X64-SSE-NEXT: xorl %edx, %edx -; X64-SSE-NEXT: divl (%rsi) +; X64-SSE-NEXT: divl 16(%rsi) ; X64-SSE-NEXT: movd %edx, %xmm1 -; X64-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm0[1,1,1,1] -; X64-SSE-NEXT: movd %xmm2, %r8d -; X64-SSE-NEXT: movl %edi, %eax +; X64-SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,1,1] +; X64-SSE-NEXT: movd %xmm0, %eax ; X64-SSE-NEXT: xorl %edx, %edx -; X64-SSE-NEXT: divl %r8d -; X64-SSE-NEXT: movd %edx, %xmm2 -; X64-SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1] -; X64-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm0[3,3,3,3] -; X64-SSE-NEXT: movd %xmm2, %edi +; X64-SSE-NEXT: divl 20(%rsi) +; X64-SSE-NEXT: movd %edx, %xmm0 +; X64-SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] +; X64-SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm3[0] +; X64-SSE-NEXT: movl %r8d, %eax +; X64-SSE-NEXT: xorl %edx, %edx +; X64-SSE-NEXT: divl 4(%rsi) +; X64-SSE-NEXT: movd %edx, %xmm0 ; X64-SSE-NEXT: movl %r9d, %eax ; X64-SSE-NEXT: xorl %edx, %edx -; X64-SSE-NEXT: divl %edi -; X64-SSE-NEXT: movd %edx, %xmm2 -; X64-SSE-NEXT: pshufd {{.*#+}} xmm4 = xmm4[2,3,2,3] -; X64-SSE-NEXT: movd %xmm4, %eax -; X64-SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] -; X64-SSE-NEXT: movd %xmm0, %edi +; X64-SSE-NEXT: divl (%rsi) +; X64-SSE-NEXT: movd %edx, %xmm3 +; X64-SSE-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1] +; X64-SSE-NEXT: movl %r10d, %eax ; X64-SSE-NEXT: xorl %edx, %edx -; X64-SSE-NEXT: divl %edi +; X64-SSE-NEXT: divl 12(%rsi) ; X64-SSE-NEXT: movd %edx, %xmm0 -; X64-SSE-NEXT: punpckldq {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1] -; X64-SSE-NEXT: punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm0[0] +; X64-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm2[2,3,2,3] +; X64-SSE-NEXT: movd %xmm2, %eax +; X64-SSE-NEXT: xorl %edx, %edx +; X64-SSE-NEXT: divl 8(%rsi) +; X64-SSE-NEXT: movd %edx, %xmm2 +; X64-SSE-NEXT: punpckldq {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1] +; X64-SSE-NEXT: punpcklqdq {{.*#+}} xmm3 = xmm3[0],xmm2[0] ; X64-SSE-NEXT: movl %ecx, %eax ; X64-SSE-NEXT: xorl %edx, %edx ; X64-SSE-NEXT: divl 32(%rsi) ; X64-SSE-NEXT: movdqa {{.*#+}} xmm0 = [8199,8199,8199,8199] -; X64-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm1[1,1,3,3] -; X64-SSE-NEXT: pmuludq %xmm0, %xmm1 -; X64-SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm1[0,2,2,3] -; X64-SSE-NEXT: pmuludq %xmm0, %xmm2 -; X64-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm2[0,2,2,3] -; X64-SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1] ; X64-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm3[1,1,3,3] ; X64-SSE-NEXT: pmuludq %xmm0, %xmm3 ; X64-SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm3[0,2,2,3] ; X64-SSE-NEXT: pmuludq %xmm0, %xmm2 +; X64-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm2[0,2,2,3] +; X64-SSE-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm2[0],xmm3[1],xmm2[1] +; X64-SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm1[1,1,3,3] +; X64-SSE-NEXT: pmuludq %xmm0, %xmm1 +; X64-SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm1[0,2,2,3] +; X64-SSE-NEXT: pmuludq %xmm0, %xmm2 ; X64-SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm2[0,2,2,3] -; X64-SSE-NEXT: punpckldq {{.*#+}} xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1] +; X64-SSE-NEXT: punpckldq {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] ; X64-SSE-NEXT: imull $8199, %edx, %eax # imm = 0x2007 ; X64-SSE-NEXT: movl %eax, (%rax) -; X64-SSE-NEXT: movdqa %xmm3, (%rax) ; X64-SSE-NEXT: movdqa %xmm1, (%rax) +; X64-SSE-NEXT: movdqa %xmm3, (%rax) ; X64-SSE-NEXT: retq ; ; X64-AVX1-LABEL: PR34947: diff --git a/llvm/test/CodeGen/X86/shuffle-vs-trunc-256.ll b/llvm/test/CodeGen/X86/shuffle-vs-trunc-256.ll index 2d7e6f6e58beeeb7cc3e47767a1b522ee33d2b52..a80f38089c40144671c0b21b17d50911fd91e2f7 100644 --- a/llvm/test/CodeGen/X86/shuffle-vs-trunc-256.ll +++ b/llvm/test/CodeGen/X86/shuffle-vs-trunc-256.ll @@ -1333,8 +1333,10 @@ define <16 x i8> @negative(<32 x i8> %v, <32 x i8> %w) nounwind { ; AVX512VL-LABEL: negative: ; AVX512VL: # %bb.0: ; AVX512VL-NEXT: vpshufb {{.*#+}} ymm0 = zero,ymm0[2,4,6,8,10,12,14,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,16,18,20,22,24,26,28,30] -; AVX512VL-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,3,2,3] -; AVX512VL-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm0 +; AVX512VL-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255] +; AVX512VL-NEXT: # ymm2 = mem[0,1,0,1] +; AVX512VL-NEXT: vpternlogq $206, %ymm1, %ymm0, %ymm2 +; AVX512VL-NEXT: vpermq {{.*#+}} ymm0 = ymm2[0,3,2,3] ; AVX512VL-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0 ; AVX512VL-NEXT: vzeroupper ; AVX512VL-NEXT: retq diff --git a/llvm/test/CodeGen/X86/stack-protector.ll b/llvm/test/CodeGen/X86/stack-protector.ll index a277f9f862ab26757bb72f22142f758e5c21e033..f4f3ae4f55f2eed313b69d71399940a3df3f3ee8 100644 --- a/llvm/test/CodeGen/X86/stack-protector.ll +++ b/llvm/test/CodeGen/X86/stack-protector.ll @@ -1,6 +1,7 @@ ; RUN: llc -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck --check-prefix=LINUX-I386 %s ; RUN: llc -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck --check-prefix=LINUX-X64 %s ; RUN: llc -code-model=kernel -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck --check-prefix=LINUX-KERNEL-X64 %s +; RUN: llc -code-model=kernel -mtriple=x86_64-unknown-freebsd < %s -o - | FileCheck --check-prefix=FREEBSD-KERNEL-X64 %s ; RUN: llc -mtriple=x86_64-apple-darwin < %s -o - | FileCheck --check-prefix=DARWIN-X64 %s ; RUN: llc -mtriple=amd64-pc-openbsd < %s -o - | FileCheck --check-prefix=OPENBSD-AMD64 %s ; RUN: llc -mtriple=i386-pc-windows-msvc < %s -o - | FileCheck -check-prefix=MSVC-I386 %s @@ -75,6 +76,10 @@ entry: ; LINUX-X64: mov{{l|q}} %fs: ; LINUX-X64: callq __stack_chk_fail +; FREEBSD-KERNEL-X64-LABEL: test1b: +; FREEBSD-KERNEL-X64-NOT: mov{{l|q}} __stack_chk_guard@GOTPCREL +; FREEBSD-KERNEL-X64: callq __stack_chk_fail + ; LINUX-KERNEL-X64-LABEL: test1b: ; LINUX-KERNEL-X64: mov{{l|q}} %gs: ; LINUX-KERNEL-X64: callq __stack_chk_fail @@ -118,6 +123,10 @@ entry: ; LINUX-X64: mov{{l|q}} %fs: ; LINUX-X64: callq __stack_chk_fail +; FREEBSD-KERNEL-X64-LABEL: test1c: +; FREEBSD-KERNEL-X64: mov{{l|q}} __stack_chk_guard(%rip) +; FREEBSD-KERNEL-X64: callq __stack_chk_fail + ; LINUX-KERNEL-X64-LABEL: test1c: ; LINUX-KERNEL-X64: mov{{l|q}} %gs: ; LINUX-KERNEL-X64: callq __stack_chk_fail diff --git a/llvm/test/CodeGen/X86/statepoint-fastregalloc.mir b/llvm/test/CodeGen/X86/statepoint-fastregalloc.mir index 02c9310673006ff8409c7dc5c5dc7d0c4194f7f3..8bac14018a7dd35973296b0201a5051f88f3aa7e 100644 --- a/llvm/test/CodeGen/X86/statepoint-fastregalloc.mir +++ b/llvm/test/CodeGen/X86/statepoint-fastregalloc.mir @@ -6,6 +6,8 @@ --- name: test_relocate tracksRegLiveness: true +frameInfo: + adjustsStack: true body: | bb.0.entry: liveins: $rdi @@ -25,6 +27,8 @@ body: | --- name: test_relocate_multi_regmasks tracksRegLiveness: true +frameInfo: + adjustsStack: true body: | bb.0.entry: liveins: $rdi diff --git a/llvm/test/CodeGen/X86/statepoint-fixup-undef.mir b/llvm/test/CodeGen/X86/statepoint-fixup-undef.mir index 30a68e6c2efd2a9cfa3419dc7113e18416bdc863..4a18351bde493d3a17af5323b29eeb7222d4c4a0 100644 --- a/llvm/test/CodeGen/X86/statepoint-fixup-undef.mir +++ b/llvm/test/CodeGen/X86/statepoint-fixup-undef.mir @@ -61,7 +61,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 8 - adjustsStack: false + adjustsStack: true hasCalls: true stackProtector: '' maxCallFrameSize: 4294967295 diff --git a/llvm/test/CodeGen/X86/statepoint-invoke-ra-enter-at-end.mir b/llvm/test/CodeGen/X86/statepoint-invoke-ra-enter-at-end.mir index 11968f17c70a3eb617affd6ae8d0ee2bba7b6cfd..5f05270729fdec29d822454714e0e4cecf8df2a1 100644 --- a/llvm/test/CodeGen/X86/statepoint-invoke-ra-enter-at-end.mir +++ b/llvm/test/CodeGen/X86/statepoint-invoke-ra-enter-at-end.mir @@ -231,7 +231,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 1 - adjustsStack: false + adjustsStack: true hasCalls: true stackProtector: '' maxCallFrameSize: 4294967295 diff --git a/llvm/test/CodeGen/X86/statepoint-invoke-ra-hoist-copies.mir b/llvm/test/CodeGen/X86/statepoint-invoke-ra-hoist-copies.mir index aae2f3870138c06fcd9383157a3265fadf4cabbe..cf9128260f1962583336f5b52867b6441b518a67 100644 --- a/llvm/test/CodeGen/X86/statepoint-invoke-ra-hoist-copies.mir +++ b/llvm/test/CodeGen/X86/statepoint-invoke-ra-hoist-copies.mir @@ -398,7 +398,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 1 - adjustsStack: false + adjustsStack: true hasCalls: true stackProtector: '' maxCallFrameSize: 4294967295 diff --git a/llvm/test/CodeGen/X86/statepoint-invoke-ra-inline-spiller.mir b/llvm/test/CodeGen/X86/statepoint-invoke-ra-inline-spiller.mir index 87f5f0f96c505d4d301de9b1f4ee0277bc33faf4..fcebc69d9b2e356a209336da5c1fa58c772341a4 100644 --- a/llvm/test/CodeGen/X86/statepoint-invoke-ra-inline-spiller.mir +++ b/llvm/test/CodeGen/X86/statepoint-invoke-ra-inline-spiller.mir @@ -175,7 +175,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 4 - adjustsStack: false + adjustsStack: true hasCalls: true stackProtector: '' maxCallFrameSize: 4294967295 diff --git a/llvm/test/CodeGen/X86/statepoint-invoke-ra-remove-back-copies.mir b/llvm/test/CodeGen/X86/statepoint-invoke-ra-remove-back-copies.mir index 49253968fcca5875af097bbdfe424db480cd4008..8bb39a03f7e3683c9bd3012832fbc13be3ccd4c7 100644 --- a/llvm/test/CodeGen/X86/statepoint-invoke-ra-remove-back-copies.mir +++ b/llvm/test/CodeGen/X86/statepoint-invoke-ra-remove-back-copies.mir @@ -226,7 +226,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 4 - adjustsStack: false + adjustsStack: true hasCalls: true stackProtector: '' maxCallFrameSize: 4294967295 diff --git a/llvm/test/CodeGen/X86/statepoint-invoke-ra.mir b/llvm/test/CodeGen/X86/statepoint-invoke-ra.mir index 858ff3f1888b98dc1706424347614101f7ed6d10..da651039ce21e073a8ef5216c251a5872c50da3a 100644 --- a/llvm/test/CodeGen/X86/statepoint-invoke-ra.mir +++ b/llvm/test/CodeGen/X86/statepoint-invoke-ra.mir @@ -172,7 +172,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 4 - adjustsStack: false + adjustsStack: true hasCalls: true stackProtector: '' maxCallFrameSize: 4294967295 diff --git a/llvm/test/CodeGen/X86/statepoint-vreg-folding.mir b/llvm/test/CodeGen/X86/statepoint-vreg-folding.mir index e24d5e8af1f55392cac5f5998bae8a33b7fb9084..d40a9a06d1620e7b84a45dfb0657a66fe6be0fcc 100644 --- a/llvm/test/CodeGen/X86/statepoint-vreg-folding.mir +++ b/llvm/test/CodeGen/X86/statepoint-vreg-folding.mir @@ -114,7 +114,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 8 - adjustsStack: false + adjustsStack: true hasCalls: true stackProtector: '' maxCallFrameSize: 4294967295 diff --git a/llvm/test/CodeGen/X86/statepoint-vreg.mir b/llvm/test/CodeGen/X86/statepoint-vreg.mir index bfeadfc93da8f634bb7cf1b98d078c122c0ba640..a0c596f249931cfd909ef92556cdb5c9cf9aa80c 100644 --- a/llvm/test/CodeGen/X86/statepoint-vreg.mir +++ b/llvm/test/CodeGen/X86/statepoint-vreg.mir @@ -134,6 +134,8 @@ registers: liveins: - { reg: '$rdi', virtual-reg: '%0' } - { reg: '$rsi', virtual-reg: '%1' } +frameInfo: + adjustsStack: true fixedStack: [] stack: [] callSites: [] diff --git a/llvm/test/CodeGen/X86/tls-align.ll b/llvm/test/CodeGen/X86/tls-align.ll index 3c8ee6b3f8ab2bf121c9a99d6016c637feb89b9a..e996c00dbf1d4ac63d3fcf2a0f12b18dd9cbcdcc 100644 --- a/llvm/test/CodeGen/X86/tls-align.ll +++ b/llvm/test/CodeGen/X86/tls-align.ll @@ -12,7 +12,7 @@ define internal fastcc void @foo() unnamed_addr { entry: - store <8 x ptr> <ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV7Derived, i64 0, inrange i32 0, i64 2), ptr null, ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV7Derived, i64 0, inrange i32 0, i64 2), ptr null, ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV7Derived, i64 0, inrange i32 0, i64 2), ptr null, ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV7Derived, i64 0, inrange i32 0, i64 2), ptr null>, ptr @array, align 32 + store <8 x ptr> <ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV7Derived, i64 0, i32 0, i64 2), ptr null, ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV7Derived, i64 0, i32 0, i64 2), ptr null, ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV7Derived, i64 0, i32 0, i64 2), ptr null, ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV7Derived, i64 0, i32 0, i64 2), ptr null>, ptr @array, align 32 ret void } diff --git a/llvm/test/CodeGen/X86/tls-desc.ll b/llvm/test/CodeGen/X86/tls-desc.ll new file mode 100644 index 0000000000000000000000000000000000000000..c73986e69e79187f4b97cbd58d55e4ad97d526c6 --- /dev/null +++ b/llvm/test/CodeGen/X86/tls-desc.ll @@ -0,0 +1,199 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc < %s -mtriple=i686 --relocation-model=pic -enable-tlsdesc | FileCheck %s --check-prefix=X86 +; RUN: llc < %s -mtriple=x86_64-pc-linux-gnux32 --relocation-model=pic -enable-tlsdesc | FileCheck %s --check-prefix=X32 +; RUN: llc < %s -mtriple=x86_64 --relocation-model=pic -enable-tlsdesc | FileCheck %s --check-prefix=X64 + +@x = thread_local global i32 0, align 4 +@y = internal thread_local global i32 1, align 4 +@z = external hidden thread_local global i32, align 4 + +define ptr @f1() nounwind { +; X86-LABEL: f1: +; X86: # %bb.0: +; X86-NEXT: pushl %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %edi +; X86-NEXT: pushl %esi +; X86-NEXT: pushl %eax +; X86-NEXT: calll .L0$pb +; X86-NEXT: .L0$pb: +; X86-NEXT: popl %ebx +; X86-NEXT: .Ltmp0: +; X86-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp0-.L0$pb), %ebx +; X86-NEXT: #APP +; X86-NEXT: #NO_APP +; X86-NEXT: movl %eax, (%esp) # 4-byte Spill +; X86-NEXT: leal x@tlsdesc(%ebx), %eax +; X86-NEXT: calll *x@tlscall(%eax) +; X86-NEXT: addl %gs:0, %eax +; X86-NEXT: movl (%esp), %ebx # 4-byte Reload +; X86-NEXT: #APP +; X86-NEXT: #NO_APP +; X86-NEXT: addl $4, %esp +; X86-NEXT: popl %esi +; X86-NEXT: popl %edi +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp +; X86-NEXT: retl +; +; X32-LABEL: f1: +; X32: # %bb.0: +; X32-NEXT: pushq %rax +; X32-NEXT: #APP +; X32-NEXT: #NO_APP +; X32-NEXT: leal x@tlsdesc(%rip), %eax +; X32-NEXT: callq *x@tlscall(%eax) +; X32-NEXT: # kill: def $eax killed $eax def $rax +; X32-NEXT: addl %fs:0, %eax +; X32-NEXT: #APP +; X32-NEXT: #NO_APP +; X32-NEXT: popq %rcx +; X32-NEXT: retq +; +; X64-LABEL: f1: +; X64: # %bb.0: +; X64-NEXT: pushq %rax +; X64-NEXT: #APP +; X64-NEXT: #NO_APP +; X64-NEXT: leaq x@tlsdesc(%rip), %rax +; X64-NEXT: callq *x@tlscall(%rax) +; X64-NEXT: addq %fs:0, %rax +; X64-NEXT: #APP +; X64-NEXT: #NO_APP +; X64-NEXT: popq %rcx +; X64-NEXT: retq + %a = call { i32, i32, i32, i32, i32, i32 } asm sideeffect "", "=r,=r,=r,=r,=r,=r,~{dirflag},~{fpsr},~{flags}"() + %b = call ptr @llvm.threadlocal.address.p0(ptr @x) + %a.0 = extractvalue { i32, i32, i32, i32, i32, i32 } %a, 0 + %a.1 = extractvalue { i32, i32, i32, i32, i32, i32 } %a, 1 + %a.2 = extractvalue { i32, i32, i32, i32, i32, i32 } %a, 2 + %a.3 = extractvalue { i32, i32, i32, i32, i32, i32 } %a, 3 + %a.4 = extractvalue { i32, i32, i32, i32, i32, i32 } %a, 4 + %a.5 = extractvalue { i32, i32, i32, i32, i32, i32 } %a, 5 + call void asm sideeffect "", "r,r,r,r,r,r,~{dirflag},~{fpsr},~{flags}"(i32 %a.0, i32 %a.1, i32 %a.2, i32 %a.3, i32 %a.4, i32 %a.5) + ret ptr %b +} + +define i32 @f2() nounwind { +; X86-LABEL: f2: +; X86: # %bb.0: +; X86-NEXT: pushl %ebx +; X86-NEXT: calll .L1$pb +; X86-NEXT: .L1$pb: +; X86-NEXT: popl %ebx +; X86-NEXT: .Ltmp1: +; X86-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp1-.L1$pb), %ebx +; X86-NEXT: movl %gs:0, %ecx +; X86-NEXT: leal x@tlsdesc(%ebx), %eax +; X86-NEXT: calll *x@tlscall(%eax) +; X86-NEXT: movl (%eax,%ecx), %eax +; X86-NEXT: popl %ebx +; X86-NEXT: retl +; +; X32-LABEL: f2: +; X32: # %bb.0: +; X32-NEXT: pushq %rax +; X32-NEXT: movl %fs:0, %ecx +; X32-NEXT: leal x@tlsdesc(%rip), %eax +; X32-NEXT: callq *x@tlscall(%eax) +; X32-NEXT: movl (%eax,%ecx), %eax +; X32-NEXT: popq %rcx +; X32-NEXT: retq +; +; X64-LABEL: f2: +; X64: # %bb.0: +; X64-NEXT: pushq %rax +; X64-NEXT: movq %fs:0, %rcx +; X64-NEXT: leaq x@tlsdesc(%rip), %rax +; X64-NEXT: callq *x@tlscall(%rax) +; X64-NEXT: movl (%rax,%rcx), %eax +; X64-NEXT: popq %rcx +; X64-NEXT: retq + %1 = tail call ptr @llvm.threadlocal.address.p0(ptr @x) + %2 = load i32, ptr %1 + ret i32 %2 +} + +define ptr @f3() nounwind { +; X86-LABEL: f3: +; X86: # %bb.0: +; X86-NEXT: pushl %ebx +; X86-NEXT: calll .L2$pb +; X86-NEXT: .L2$pb: +; X86-NEXT: popl %ebx +; X86-NEXT: .Ltmp2: +; X86-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp2-.L2$pb), %ebx +; X86-NEXT: leal x@tlsdesc(%ebx), %eax +; X86-NEXT: calll *x@tlscall(%eax) +; X86-NEXT: addl %gs:0, %eax +; X86-NEXT: popl %ebx +; X86-NEXT: retl +; +; X32-LABEL: f3: +; X32: # %bb.0: +; X32-NEXT: pushq %rax +; X32-NEXT: leal x@tlsdesc(%rip), %eax +; X32-NEXT: callq *x@tlscall(%eax) +; X32-NEXT: # kill: def $eax killed $eax def $rax +; X32-NEXT: addl %fs:0, %eax +; X32-NEXT: popq %rcx +; X32-NEXT: retq +; +; X64-LABEL: f3: +; X64: # %bb.0: +; X64-NEXT: pushq %rax +; X64-NEXT: leaq x@tlsdesc(%rip), %rax +; X64-NEXT: callq *x@tlscall(%rax) +; X64-NEXT: addq %fs:0, %rax +; X64-NEXT: popq %rcx +; X64-NEXT: retq + %1 = tail call ptr @llvm.threadlocal.address.p0(ptr @x) + ret ptr %1 +} + +define i32 @f4() nounwind { +; X86-LABEL: f4: +; X86: # %bb.0: +; X86-NEXT: pushl %ebx +; X86-NEXT: calll .L3$pb +; X86-NEXT: .L3$pb: +; X86-NEXT: popl %ebx +; X86-NEXT: .Ltmp3: +; X86-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp3-.L3$pb), %ebx +; X86-NEXT: movl %gs:0, %edx +; X86-NEXT: leal _TLS_MODULE_BASE_@tlsdesc(%ebx), %eax +; X86-NEXT: calll *_TLS_MODULE_BASE_@tlscall(%eax) +; X86-NEXT: movl y@DTPOFF(%eax,%edx), %ecx +; X86-NEXT: addl z@DTPOFF(%eax,%edx), %ecx +; X86-NEXT: movl %ecx, %eax +; X86-NEXT: popl %ebx +; X86-NEXT: retl +; +; X32-LABEL: f4: +; X32: # %bb.0: +; X32-NEXT: pushq %rax +; X32-NEXT: movl %fs:0, %edx +; X32-NEXT: leal _TLS_MODULE_BASE_@tlsdesc(%rip), %eax +; X32-NEXT: callq *_TLS_MODULE_BASE_@tlscall(%eax) +; X32-NEXT: movl y@DTPOFF(%eax,%edx), %ecx +; X32-NEXT: addl z@DTPOFF(%eax,%edx), %ecx +; X32-NEXT: movl %ecx, %eax +; X32-NEXT: popq %rcx +; X32-NEXT: retq +; +; X64-LABEL: f4: +; X64: # %bb.0: +; X64-NEXT: pushq %rax +; X64-NEXT: movq %fs:0, %rdx +; X64-NEXT: leaq _TLS_MODULE_BASE_@tlsdesc(%rip), %rax +; X64-NEXT: callq *_TLS_MODULE_BASE_@tlscall(%rax) +; X64-NEXT: movl y@DTPOFF(%rax,%rdx), %ecx +; X64-NEXT: addl z@DTPOFF(%rax,%rdx), %ecx +; X64-NEXT: movl %ecx, %eax +; X64-NEXT: popq %rcx +; X64-NEXT: retq + %1 = load i32, ptr @y, align 4 + %2 = load i32, ptr @z, align 4 + %3 = add nsw i32 %1, %2 + ret i32 %3 +} diff --git a/llvm/test/CodeGen/X86/tls-loads-control3.ll b/llvm/test/CodeGen/X86/tls-loads-control3.ll index 82daac5a9bae344742e290d75c49d1feb129f244..4e521b1c696a4d3a8a216b9d236d48cc01bbaf71 100644 --- a/llvm/test/CodeGen/X86/tls-loads-control3.ll +++ b/llvm/test/CodeGen/X86/tls-loads-control3.ll @@ -183,7 +183,6 @@ define i32 @_Z2f2i(i32 %c) local_unnamed_addr #0 { ; HOIST0-NEXT: # %bb.1: # %while.body.preheader ; HOIST0-NEXT: leaq _ZZ2f2iE2st.0@TLSLD(%rip), %rdi ; HOIST0-NEXT: callq __tls_get_addr@PLT -; HOIST0-NEXT: movq %rax, %rcx ; HOIST0-NEXT: leaq _ZZ2f2iE2st.0@DTPOFF(%rax), %r15 ; HOIST0-NEXT: leaq _ZZ2f2iE2st.1@DTPOFF(%rax), %r12 ; HOIST0-NEXT: .p2align 4, 0x90 @@ -245,9 +244,7 @@ define i32 @_Z2f2i(i32 %c) local_unnamed_addr #0 { ; HOIST2-NEXT: movq %rax, %r14 ; HOIST2-NEXT: addb %bpl, _ZZ2f2iE2st.0@DTPOFF(%rax) ; HOIST2-NEXT: callq _Z5gfuncv@PLT -; HOIST2-NEXT: movl %eax, %ecx -; HOIST2-NEXT: movq %r14, %rax -; HOIST2-NEXT: addl %ecx, _ZZ2f2iE2st.1@DTPOFF(%r14) +; HOIST2-NEXT: addl %eax, _ZZ2f2iE2st.1@DTPOFF(%r14) ; HOIST2-NEXT: decl %ebx ; HOIST2-NEXT: jne .LBB1_2 ; HOIST2-NEXT: .LBB1_3: # %while.end diff --git a/llvm/test/CodeGen/X86/var-permute-128.ll b/llvm/test/CodeGen/X86/var-permute-128.ll index 99a3821bb9ba91e8020a953b5cb2d0686b779093..f2240a94684427961abe951dac0cf92e620fe025 100644 --- a/llvm/test/CodeGen/X86/var-permute-128.ll +++ b/llvm/test/CodeGen/X86/var-permute-128.ll @@ -1101,17 +1101,13 @@ define <16 x i8> @var_shuffle_v16i8_from_v32i8_v16i8(<32 x i8> %v, <16 x i8> %in define void @indices_convert() { ; SSE3-LABEL: indices_convert: ; SSE3: # %bb.0: # %bb -; SSE3-NEXT: movdqa (%rax), %xmm0 -; SSE3-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] -; SSE3-NEXT: movd %xmm1, %eax -; SSE3-NEXT: movdqa %xmm0, -{{[0-9]+}}(%rsp) -; SSE3-NEXT: movdqa %xmm0, -{{[0-9]+}}(%rsp) +; SSE3-NEXT: movaps (%rax), %xmm0 +; SSE3-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) +; SSE3-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) +; SSE3-NEXT: movl (%rax), %eax +; SSE3-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) +; SSE3-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) ; SSE3-NEXT: andl $3, %eax -; SSE3-NEXT: pshufd {{.*#+}} xmm1 = xmm0[3,3,3,3] -; SSE3-NEXT: movd %xmm1, %ecx -; SSE3-NEXT: movdqa %xmm0, -{{[0-9]+}}(%rsp) -; SSE3-NEXT: movdqa %xmm0, -{{[0-9]+}}(%rsp) -; SSE3-NEXT: andl $3, %ecx ; SSE3-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero ; SSE3-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero ; SSE3-NEXT: movlhps {{.*#+}} xmm1 = xmm1[0],xmm0[0] @@ -1120,17 +1116,13 @@ define void @indices_convert() { ; ; SSSE3-LABEL: indices_convert: ; SSSE3: # %bb.0: # %bb -; SSSE3-NEXT: movdqa (%rax), %xmm0 -; SSSE3-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3] -; SSSE3-NEXT: movd %xmm1, %eax -; SSSE3-NEXT: movdqa %xmm0, -{{[0-9]+}}(%rsp) -; SSSE3-NEXT: movdqa %xmm0, -{{[0-9]+}}(%rsp) +; SSSE3-NEXT: movaps (%rax), %xmm0 +; SSSE3-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) +; SSSE3-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) +; SSSE3-NEXT: movl (%rax), %eax +; SSSE3-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) +; SSSE3-NEXT: movaps %xmm0, -{{[0-9]+}}(%rsp) ; SSSE3-NEXT: andl $3, %eax -; SSSE3-NEXT: pshufd {{.*#+}} xmm1 = xmm0[3,3,3,3] -; SSSE3-NEXT: movd %xmm1, %ecx -; SSSE3-NEXT: movdqa %xmm0, -{{[0-9]+}}(%rsp) -; SSSE3-NEXT: movdqa %xmm0, -{{[0-9]+}}(%rsp) -; SSSE3-NEXT: andl $3, %ecx ; SSSE3-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero ; SSSE3-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero ; SSSE3-NEXT: movlhps {{.*#+}} xmm1 = xmm1[0],xmm0[0] diff --git a/llvm/test/CodeGen/X86/vec_int_to_fp.ll b/llvm/test/CodeGen/X86/vec_int_to_fp.ll index 7bbcdee9a6802e885371b6c26dc15d0696dbcd91..e26de4be7066fa521a780dafc794a17606d64ce3 100644 --- a/llvm/test/CodeGen/X86/vec_int_to_fp.ll +++ b/llvm/test/CodeGen/X86/vec_int_to_fp.ll @@ -2911,23 +2911,12 @@ define <8 x float> @uitofp_16i8_to_8f32(<16 x i8> %a) { ; define <2 x double> @sitofp_load_2i64_to_2f64(ptr%a) { -; SSE2-LABEL: sitofp_load_2i64_to_2f64: -; SSE2: # %bb.0: -; SSE2-NEXT: movdqa (%rdi), %xmm1 -; SSE2-NEXT: cvtsi2sdq (%rdi), %xmm0 -; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] -; SSE2-NEXT: movq %xmm1, %rax -; SSE2-NEXT: xorps %xmm1, %xmm1 -; SSE2-NEXT: cvtsi2sd %rax, %xmm1 -; SSE2-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] -; SSE2-NEXT: retq -; -; SSE41-LABEL: sitofp_load_2i64_to_2f64: -; SSE41: # %bb.0: -; SSE41-NEXT: cvtsi2sdq 8(%rdi), %xmm1 -; SSE41-NEXT: cvtsi2sdq (%rdi), %xmm0 -; SSE41-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] -; SSE41-NEXT: retq +; SSE-LABEL: sitofp_load_2i64_to_2f64: +; SSE: # %bb.0: +; SSE-NEXT: cvtsi2sdq 8(%rdi), %xmm1 +; SSE-NEXT: cvtsi2sdq (%rdi), %xmm0 +; SSE-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE-NEXT: retq ; ; VEX-LABEL: sitofp_load_2i64_to_2f64: ; VEX: # %bb.0: @@ -3093,35 +3082,16 @@ define <2 x double> @sitofp_load_2i8_to_2f64(ptr%a) { } define <4 x double> @sitofp_load_4i64_to_4f64(ptr%a) { -; SSE2-LABEL: sitofp_load_4i64_to_4f64: -; SSE2: # %bb.0: -; SSE2-NEXT: movdqa (%rdi), %xmm1 -; SSE2-NEXT: movdqa 16(%rdi), %xmm2 -; SSE2-NEXT: cvtsi2sdq (%rdi), %xmm0 -; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] -; SSE2-NEXT: movq %xmm1, %rax -; SSE2-NEXT: xorps %xmm1, %xmm1 -; SSE2-NEXT: cvtsi2sd %rax, %xmm1 -; SSE2-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] -; SSE2-NEXT: xorps %xmm1, %xmm1 -; SSE2-NEXT: cvtsi2sdq 16(%rdi), %xmm1 -; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm2[2,3,2,3] -; SSE2-NEXT: movq %xmm2, %rax -; SSE2-NEXT: xorps %xmm2, %xmm2 -; SSE2-NEXT: cvtsi2sd %rax, %xmm2 -; SSE2-NEXT: unpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] -; SSE2-NEXT: retq -; -; SSE41-LABEL: sitofp_load_4i64_to_4f64: -; SSE41: # %bb.0: -; SSE41-NEXT: cvtsi2sdq 8(%rdi), %xmm1 -; SSE41-NEXT: cvtsi2sdq (%rdi), %xmm0 -; SSE41-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] -; SSE41-NEXT: cvtsi2sdq 24(%rdi), %xmm2 -; SSE41-NEXT: xorps %xmm1, %xmm1 -; SSE41-NEXT: cvtsi2sdq 16(%rdi), %xmm1 -; SSE41-NEXT: unpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] -; SSE41-NEXT: retq +; SSE-LABEL: sitofp_load_4i64_to_4f64: +; SSE: # %bb.0: +; SSE-NEXT: cvtsi2sdq 8(%rdi), %xmm1 +; SSE-NEXT: cvtsi2sdq (%rdi), %xmm0 +; SSE-NEXT: unpcklpd {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE-NEXT: cvtsi2sdq 24(%rdi), %xmm2 +; SSE-NEXT: xorps %xmm1, %xmm1 +; SSE-NEXT: cvtsi2sdq 16(%rdi), %xmm1 +; SSE-NEXT: unpcklpd {{.*#+}} xmm1 = xmm1[0],xmm2[0] +; SSE-NEXT: retq ; ; VEX-LABEL: sitofp_load_4i64_to_4f64: ; VEX: # %bb.0: @@ -3865,22 +3835,14 @@ define <4 x double> @uitofp_load_4i8_to_4f64(ptr%a) { define <4 x float> @sitofp_load_4i64_to_4f32(ptr%a) { ; SSE2-LABEL: sitofp_load_4i64_to_4f32: ; SSE2: # %bb.0: -; SSE2-NEXT: movdqa (%rdi), %xmm1 -; SSE2-NEXT: movdqa 16(%rdi), %xmm0 -; SSE2-NEXT: cvtsi2ssq 16(%rdi), %xmm2 -; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] -; SSE2-NEXT: movq %xmm0, %rax -; SSE2-NEXT: xorps %xmm0, %xmm0 -; SSE2-NEXT: cvtsi2ss %rax, %xmm0 -; SSE2-NEXT: unpcklps {{.*#+}} xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1] +; SSE2-NEXT: cvtsi2ssq 24(%rdi), %xmm0 +; SSE2-NEXT: cvtsi2ssq 16(%rdi), %xmm1 +; SSE2-NEXT: unpcklps {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] +; SSE2-NEXT: cvtsi2ssq 8(%rdi), %xmm2 ; SSE2-NEXT: xorps %xmm0, %xmm0 ; SSE2-NEXT: cvtsi2ssq (%rdi), %xmm0 -; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] -; SSE2-NEXT: movq %xmm1, %rax -; SSE2-NEXT: xorps %xmm1, %xmm1 -; SSE2-NEXT: cvtsi2ss %rax, %xmm1 -; SSE2-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1] -; SSE2-NEXT: movlhps {{.*#+}} xmm0 = xmm0[0],xmm2[0] +; SSE2-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1] +; SSE2-NEXT: movlhps {{.*#+}} xmm0 = xmm0[0],xmm1[0] ; SSE2-NEXT: retq ; ; SSE41-LABEL: sitofp_load_4i64_to_4f32: @@ -4015,39 +3977,24 @@ define <4 x float> @sitofp_load_4i8_to_4f32(ptr%a) { define <8 x float> @sitofp_load_8i64_to_8f32(ptr%a) { ; SSE2-LABEL: sitofp_load_8i64_to_8f32: ; SSE2: # %bb.0: -; SSE2-NEXT: movdqa (%rdi), %xmm1 -; SSE2-NEXT: movdqa 16(%rdi), %xmm0 -; SSE2-NEXT: movdqa 32(%rdi), %xmm2 -; SSE2-NEXT: movdqa 48(%rdi), %xmm3 -; SSE2-NEXT: cvtsi2ssq 16(%rdi), %xmm4 -; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] -; SSE2-NEXT: movq %xmm0, %rax -; SSE2-NEXT: xorps %xmm0, %xmm0 -; SSE2-NEXT: cvtsi2ss %rax, %xmm0 -; SSE2-NEXT: unpcklps {{.*#+}} xmm4 = xmm4[0],xmm0[0],xmm4[1],xmm0[1] +; SSE2-NEXT: cvtsi2ssq 24(%rdi), %xmm0 +; SSE2-NEXT: cvtsi2ssq 16(%rdi), %xmm1 +; SSE2-NEXT: unpcklps {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] +; SSE2-NEXT: cvtsi2ssq 8(%rdi), %xmm2 ; SSE2-NEXT: xorps %xmm0, %xmm0 ; SSE2-NEXT: cvtsi2ssq (%rdi), %xmm0 -; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm1[2,3,2,3] -; SSE2-NEXT: movq %xmm1, %rax -; SSE2-NEXT: xorps %xmm1, %xmm1 -; SSE2-NEXT: cvtsi2ss %rax, %xmm1 -; SSE2-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1] -; SSE2-NEXT: movlhps {{.*#+}} xmm0 = xmm0[0],xmm4[0] -; SSE2-NEXT: xorps %xmm4, %xmm4 -; SSE2-NEXT: cvtsi2ssq 48(%rdi), %xmm4 -; SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm3[2,3,2,3] -; SSE2-NEXT: movq %xmm1, %rax +; SSE2-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1] +; SSE2-NEXT: movlhps {{.*#+}} xmm0 = xmm0[0],xmm1[0] ; SSE2-NEXT: xorps %xmm1, %xmm1 -; SSE2-NEXT: cvtsi2ss %rax, %xmm1 -; SSE2-NEXT: unpcklps {{.*#+}} xmm4 = xmm4[0],xmm1[0],xmm4[1],xmm1[1] +; SSE2-NEXT: cvtsi2ssq 56(%rdi), %xmm1 +; SSE2-NEXT: xorps %xmm2, %xmm2 +; SSE2-NEXT: cvtsi2ssq 48(%rdi), %xmm2 +; SSE2-NEXT: unpcklps {{.*#+}} xmm2 = xmm2[0],xmm1[0],xmm2[1],xmm1[1] +; SSE2-NEXT: cvtsi2ssq 40(%rdi), %xmm3 ; SSE2-NEXT: xorps %xmm1, %xmm1 ; SSE2-NEXT: cvtsi2ssq 32(%rdi), %xmm1 -; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm2[2,3,2,3] -; SSE2-NEXT: movq %xmm2, %rax -; SSE2-NEXT: xorps %xmm2, %xmm2 -; SSE2-NEXT: cvtsi2ss %rax, %xmm2 -; SSE2-NEXT: unpcklps {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1] -; SSE2-NEXT: movlhps {{.*#+}} xmm1 = xmm1[0],xmm4[0] +; SSE2-NEXT: unpcklps {{.*#+}} xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1] +; SSE2-NEXT: movlhps {{.*#+}} xmm1 = xmm1[0],xmm2[0] ; SSE2-NEXT: retq ; ; SSE41-LABEL: sitofp_load_8i64_to_8f32: @@ -4256,70 +4203,64 @@ define <8 x float> @sitofp_load_8i8_to_8f32(ptr%a) { define <4 x float> @uitofp_load_4i64_to_4f32(ptr%a) { ; SSE2-LABEL: uitofp_load_4i64_to_4f32: ; SSE2: # %bb.0: -; SSE2-NEXT: movdqa 16(%rdi), %xmm0 -; SSE2-NEXT: movq 16(%rdi), %rax +; SSE2-NEXT: movq 24(%rdi), %rax ; SSE2-NEXT: testq %rax, %rax ; SSE2-NEXT: js .LBB83_1 ; SSE2-NEXT: # %bb.2: -; SSE2-NEXT: cvtsi2ss %rax, %xmm1 +; SSE2-NEXT: cvtsi2ss %rax, %xmm0 ; SSE2-NEXT: jmp .LBB83_3 ; SSE2-NEXT: .LBB83_1: ; SSE2-NEXT: movq %rax, %rcx ; SSE2-NEXT: shrq %rcx ; SSE2-NEXT: andl $1, %eax ; SSE2-NEXT: orq %rcx, %rax -; SSE2-NEXT: cvtsi2ss %rax, %xmm1 -; SSE2-NEXT: addss %xmm1, %xmm1 +; SSE2-NEXT: cvtsi2ss %rax, %xmm0 +; SSE2-NEXT: addss %xmm0, %xmm0 ; SSE2-NEXT: .LBB83_3: -; SSE2-NEXT: movq (%rdi), %rax -; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] -; SSE2-NEXT: movq %xmm0, %rcx -; SSE2-NEXT: testq %rcx, %rcx +; SSE2-NEXT: movq 16(%rdi), %rax +; SSE2-NEXT: testq %rax, %rax ; SSE2-NEXT: js .LBB83_4 ; SSE2-NEXT: # %bb.5: -; SSE2-NEXT: cvtsi2ss %rcx, %xmm2 +; SSE2-NEXT: cvtsi2ss %rax, %xmm1 ; SSE2-NEXT: jmp .LBB83_6 ; SSE2-NEXT: .LBB83_4: +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: shrq %rcx +; SSE2-NEXT: andl $1, %eax +; SSE2-NEXT: orq %rcx, %rax +; SSE2-NEXT: cvtsi2ss %rax, %xmm1 +; SSE2-NEXT: addss %xmm1, %xmm1 +; SSE2-NEXT: .LBB83_6: +; SSE2-NEXT: movq (%rdi), %rax +; SSE2-NEXT: movq 8(%rdi), %rcx +; SSE2-NEXT: testq %rcx, %rcx +; SSE2-NEXT: js .LBB83_7 +; SSE2-NEXT: # %bb.8: +; SSE2-NEXT: cvtsi2ss %rcx, %xmm2 +; SSE2-NEXT: jmp .LBB83_9 +; SSE2-NEXT: .LBB83_7: ; SSE2-NEXT: movq %rcx, %rdx ; SSE2-NEXT: shrq %rdx ; SSE2-NEXT: andl $1, %ecx ; SSE2-NEXT: orq %rdx, %rcx ; SSE2-NEXT: cvtsi2ss %rcx, %xmm2 ; SSE2-NEXT: addss %xmm2, %xmm2 -; SSE2-NEXT: .LBB83_6: -; SSE2-NEXT: movdqa (%rdi), %xmm3 -; SSE2-NEXT: testq %rax, %rax -; SSE2-NEXT: js .LBB83_7 -; SSE2-NEXT: # %bb.8: -; SSE2-NEXT: xorps %xmm0, %xmm0 -; SSE2-NEXT: cvtsi2ss %rax, %xmm0 -; SSE2-NEXT: jmp .LBB83_9 -; SSE2-NEXT: .LBB83_7: -; SSE2-NEXT: movq %rax, %rcx -; SSE2-NEXT: shrq %rcx -; SSE2-NEXT: andl $1, %eax -; SSE2-NEXT: orq %rcx, %rax -; SSE2-NEXT: xorps %xmm0, %xmm0 -; SSE2-NEXT: cvtsi2ss %rax, %xmm0 -; SSE2-NEXT: addss %xmm0, %xmm0 ; SSE2-NEXT: .LBB83_9: -; SSE2-NEXT: unpcklps {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1] -; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm3[2,3,2,3] -; SSE2-NEXT: movq %xmm2, %rax +; SSE2-NEXT: unpcklps {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1] ; SSE2-NEXT: testq %rax, %rax ; SSE2-NEXT: js .LBB83_10 ; SSE2-NEXT: # %bb.11: -; SSE2-NEXT: xorps %xmm2, %xmm2 -; SSE2-NEXT: cvtsi2ss %rax, %xmm2 +; SSE2-NEXT: xorps %xmm0, %xmm0 +; SSE2-NEXT: cvtsi2ss %rax, %xmm0 ; SSE2-NEXT: jmp .LBB83_12 ; SSE2-NEXT: .LBB83_10: ; SSE2-NEXT: movq %rax, %rcx ; SSE2-NEXT: shrq %rcx ; SSE2-NEXT: andl $1, %eax ; SSE2-NEXT: orq %rcx, %rax -; SSE2-NEXT: xorps %xmm2, %xmm2 -; SSE2-NEXT: cvtsi2ss %rax, %xmm2 -; SSE2-NEXT: addss %xmm2, %xmm2 +; SSE2-NEXT: xorps %xmm0, %xmm0 +; SSE2-NEXT: cvtsi2ss %rax, %xmm0 +; SSE2-NEXT: addss %xmm0, %xmm0 ; SSE2-NEXT: .LBB83_12: ; SSE2-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1] ; SSE2-NEXT: movlhps {{.*#+}} xmm0 = xmm0[0],xmm1[0] @@ -4591,8 +4532,7 @@ define <4 x float> @uitofp_load_4i8_to_4f32(ptr%a) { define <8 x float> @uitofp_load_8i64_to_8f32(ptr%a) { ; SSE2-LABEL: uitofp_load_8i64_to_8f32: ; SSE2: # %bb.0: -; SSE2-NEXT: movdqa 16(%rdi), %xmm0 -; SSE2-NEXT: movq 16(%rdi), %rax +; SSE2-NEXT: movq 24(%rdi), %rax ; SSE2-NEXT: testq %rax, %rax ; SSE2-NEXT: js .LBB87_1 ; SSE2-NEXT: # %bb.2: @@ -4606,127 +4546,114 @@ define <8 x float> @uitofp_load_8i64_to_8f32(ptr%a) { ; SSE2-NEXT: cvtsi2ss %rax, %xmm2 ; SSE2-NEXT: addss %xmm2, %xmm2 ; SSE2-NEXT: .LBB87_3: -; SSE2-NEXT: movq (%rdi), %rax -; SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[2,3,2,3] -; SSE2-NEXT: movq %xmm0, %rcx -; SSE2-NEXT: testq %rcx, %rcx +; SSE2-NEXT: movq 16(%rdi), %rax +; SSE2-NEXT: testq %rax, %rax ; SSE2-NEXT: js .LBB87_4 ; SSE2-NEXT: # %bb.5: -; SSE2-NEXT: cvtsi2ss %rcx, %xmm1 +; SSE2-NEXT: cvtsi2ss %rax, %xmm1 ; SSE2-NEXT: jmp .LBB87_6 ; SSE2-NEXT: .LBB87_4: -; SSE2-NEXT: movq %rcx, %rdx -; SSE2-NEXT: shrq %rdx -; SSE2-NEXT: andl $1, %ecx -; SSE2-NEXT: orq %rdx, %rcx -; SSE2-NEXT: cvtsi2ss %rcx, %xmm1 +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: shrq %rcx +; SSE2-NEXT: andl $1, %eax +; SSE2-NEXT: orq %rcx, %rax +; SSE2-NEXT: cvtsi2ss %rax, %xmm1 ; SSE2-NEXT: addss %xmm1, %xmm1 ; SSE2-NEXT: .LBB87_6: -; SSE2-NEXT: movdqa (%rdi), %xmm3 -; SSE2-NEXT: testq %rax, %rax +; SSE2-NEXT: movq (%rdi), %rax +; SSE2-NEXT: movq 8(%rdi), %rcx +; SSE2-NEXT: testq %rcx, %rcx ; SSE2-NEXT: js .LBB87_7 ; SSE2-NEXT: # %bb.8: -; SSE2-NEXT: xorps %xmm0, %xmm0 -; SSE2-NEXT: cvtsi2ss %rax, %xmm0 -; SSE2-NEXT: jmp .LBB87_9 -; SSE2-NEXT: .LBB87_7: +; SSE2-NEXT: cvtsi2ss %rcx, %xmm3 +; SSE2-NEXT: testq %rax, %rax +; SSE2-NEXT: jns .LBB87_11 +; SSE2-NEXT: .LBB87_10: ; SSE2-NEXT: movq %rax, %rcx ; SSE2-NEXT: shrq %rcx ; SSE2-NEXT: andl $1, %eax ; SSE2-NEXT: orq %rcx, %rax -; SSE2-NEXT: xorps %xmm0, %xmm0 ; SSE2-NEXT: cvtsi2ss %rax, %xmm0 ; SSE2-NEXT: addss %xmm0, %xmm0 -; SSE2-NEXT: .LBB87_9: -; SSE2-NEXT: movq 48(%rdi), %rax -; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm3[2,3,2,3] -; SSE2-NEXT: movq %xmm3, %rcx -; SSE2-NEXT: testq %rcx, %rcx -; SSE2-NEXT: js .LBB87_10 -; SSE2-NEXT: # %bb.11: -; SSE2-NEXT: cvtsi2ss %rcx, %xmm4 ; SSE2-NEXT: jmp .LBB87_12 -; SSE2-NEXT: .LBB87_10: +; SSE2-NEXT: .LBB87_7: ; SSE2-NEXT: movq %rcx, %rdx ; SSE2-NEXT: shrq %rdx ; SSE2-NEXT: andl $1, %ecx ; SSE2-NEXT: orq %rdx, %rcx -; SSE2-NEXT: cvtsi2ss %rcx, %xmm4 -; SSE2-NEXT: addss %xmm4, %xmm4 +; SSE2-NEXT: cvtsi2ss %rcx, %xmm3 +; SSE2-NEXT: addss %xmm3, %xmm3 +; SSE2-NEXT: testq %rax, %rax +; SSE2-NEXT: js .LBB87_10 +; SSE2-NEXT: .LBB87_11: +; SSE2-NEXT: cvtsi2ss %rax, %xmm0 ; SSE2-NEXT: .LBB87_12: -; SSE2-NEXT: movdqa 48(%rdi), %xmm5 +; SSE2-NEXT: movq 56(%rdi), %rax ; SSE2-NEXT: testq %rax, %rax ; SSE2-NEXT: js .LBB87_13 ; SSE2-NEXT: # %bb.14: -; SSE2-NEXT: xorps %xmm3, %xmm3 -; SSE2-NEXT: cvtsi2ss %rax, %xmm3 +; SSE2-NEXT: cvtsi2ss %rax, %xmm5 ; SSE2-NEXT: jmp .LBB87_15 ; SSE2-NEXT: .LBB87_13: ; SSE2-NEXT: movq %rax, %rcx ; SSE2-NEXT: shrq %rcx ; SSE2-NEXT: andl $1, %eax ; SSE2-NEXT: orq %rcx, %rax -; SSE2-NEXT: xorps %xmm3, %xmm3 -; SSE2-NEXT: cvtsi2ss %rax, %xmm3 -; SSE2-NEXT: addss %xmm3, %xmm3 +; SSE2-NEXT: cvtsi2ss %rax, %xmm5 +; SSE2-NEXT: addss %xmm5, %xmm5 ; SSE2-NEXT: .LBB87_15: -; SSE2-NEXT: movq 32(%rdi), %rax -; SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm5[2,3,2,3] -; SSE2-NEXT: movq %xmm5, %rcx -; SSE2-NEXT: testq %rcx, %rcx +; SSE2-NEXT: movq 48(%rdi), %rax +; SSE2-NEXT: testq %rax, %rax ; SSE2-NEXT: js .LBB87_16 ; SSE2-NEXT: # %bb.17: -; SSE2-NEXT: xorps %xmm5, %xmm5 -; SSE2-NEXT: cvtsi2ss %rcx, %xmm5 +; SSE2-NEXT: cvtsi2ss %rax, %xmm4 ; SSE2-NEXT: jmp .LBB87_18 ; SSE2-NEXT: .LBB87_16: -; SSE2-NEXT: movq %rcx, %rdx -; SSE2-NEXT: shrq %rdx -; SSE2-NEXT: andl $1, %ecx -; SSE2-NEXT: orq %rdx, %rcx -; SSE2-NEXT: xorps %xmm5, %xmm5 -; SSE2-NEXT: cvtsi2ss %rcx, %xmm5 -; SSE2-NEXT: addss %xmm5, %xmm5 +; SSE2-NEXT: movq %rax, %rcx +; SSE2-NEXT: shrq %rcx +; SSE2-NEXT: andl $1, %eax +; SSE2-NEXT: orq %rcx, %rax +; SSE2-NEXT: cvtsi2ss %rax, %xmm4 +; SSE2-NEXT: addss %xmm4, %xmm4 ; SSE2-NEXT: .LBB87_18: -; SSE2-NEXT: unpcklps {{.*#+}} xmm2 = xmm2[0],xmm1[0],xmm2[1],xmm1[1] -; SSE2-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm4[0],xmm0[1],xmm4[1] -; SSE2-NEXT: movdqa 32(%rdi), %xmm4 +; SSE2-NEXT: unpcklps {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1] +; SSE2-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1] +; SSE2-NEXT: movq 40(%rdi), %rax ; SSE2-NEXT: testq %rax, %rax ; SSE2-NEXT: js .LBB87_19 ; SSE2-NEXT: # %bb.20: -; SSE2-NEXT: xorps %xmm1, %xmm1 -; SSE2-NEXT: cvtsi2ss %rax, %xmm1 +; SSE2-NEXT: xorps %xmm2, %xmm2 +; SSE2-NEXT: cvtsi2ss %rax, %xmm2 ; SSE2-NEXT: jmp .LBB87_21 ; SSE2-NEXT: .LBB87_19: ; SSE2-NEXT: movq %rax, %rcx ; SSE2-NEXT: shrq %rcx ; SSE2-NEXT: andl $1, %eax ; SSE2-NEXT: orq %rcx, %rax -; SSE2-NEXT: xorps %xmm1, %xmm1 -; SSE2-NEXT: cvtsi2ss %rax, %xmm1 -; SSE2-NEXT: addss %xmm1, %xmm1 +; SSE2-NEXT: xorps %xmm2, %xmm2 +; SSE2-NEXT: cvtsi2ss %rax, %xmm2 +; SSE2-NEXT: addss %xmm2, %xmm2 ; SSE2-NEXT: .LBB87_21: -; SSE2-NEXT: movlhps {{.*#+}} xmm0 = xmm0[0],xmm2[0] -; SSE2-NEXT: unpcklps {{.*#+}} xmm3 = xmm3[0],xmm5[0],xmm3[1],xmm5[1] -; SSE2-NEXT: pshufd {{.*#+}} xmm2 = xmm4[2,3,2,3] -; SSE2-NEXT: movq %xmm2, %rax +; SSE2-NEXT: movlhps {{.*#+}} xmm0 = xmm0[0],xmm1[0] +; SSE2-NEXT: unpcklps {{.*#+}} xmm4 = xmm4[0],xmm5[0],xmm4[1],xmm5[1] +; SSE2-NEXT: movq 32(%rdi), %rax ; SSE2-NEXT: testq %rax, %rax ; SSE2-NEXT: js .LBB87_22 ; SSE2-NEXT: # %bb.23: -; SSE2-NEXT: xorps %xmm2, %xmm2 -; SSE2-NEXT: cvtsi2ss %rax, %xmm2 +; SSE2-NEXT: xorps %xmm1, %xmm1 +; SSE2-NEXT: cvtsi2ss %rax, %xmm1 ; SSE2-NEXT: jmp .LBB87_24 ; SSE2-NEXT: .LBB87_22: ; SSE2-NEXT: movq %rax, %rcx ; SSE2-NEXT: shrq %rcx ; SSE2-NEXT: andl $1, %eax ; SSE2-NEXT: orq %rcx, %rax -; SSE2-NEXT: xorps %xmm2, %xmm2 -; SSE2-NEXT: cvtsi2ss %rax, %xmm2 -; SSE2-NEXT: addss %xmm2, %xmm2 +; SSE2-NEXT: xorps %xmm1, %xmm1 +; SSE2-NEXT: cvtsi2ss %rax, %xmm1 +; SSE2-NEXT: addss %xmm1, %xmm1 ; SSE2-NEXT: .LBB87_24: ; SSE2-NEXT: unpcklps {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1] -; SSE2-NEXT: movlhps {{.*#+}} xmm1 = xmm1[0],xmm3[0] +; SSE2-NEXT: movlhps {{.*#+}} xmm1 = xmm1[0],xmm4[0] ; SSE2-NEXT: retq ; ; SSE41-LABEL: uitofp_load_8i64_to_8f32: diff --git a/llvm/test/CodeGen/X86/vector-half-conversions.ll b/llvm/test/CodeGen/X86/vector-half-conversions.ll index ba21af231985a1adcf0fa7443cb16913ec073450..563cf016501340ceb4f5804009ede3f881563ee2 100644 --- a/llvm/test/CodeGen/X86/vector-half-conversions.ll +++ b/llvm/test/CodeGen/X86/vector-half-conversions.ll @@ -4989,3 +4989,257 @@ define <4 x i32> @fptosi_2f16_to_4i32(<2 x half> %a) nounwind { %ext = shufflevector <2 x i32> %cvt, <2 x i32> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3> ret <4 x i32> %ext } + +define <4 x i32> @fptosi_4f16_to_4i32(<4 x half> %a) nounwind { +; AVX-LABEL: fptosi_4f16_to_4i32: +; AVX: # %bb.0: +; AVX-NEXT: subq $72, %rsp +; AVX-NEXT: vmovdqa %xmm0, %xmm1 +; AVX-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX-NEXT: vpsrld $16, %xmm0, %xmm0 +; AVX-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX-NEXT: vmovshdup {{.*#+}} xmm0 = xmm1[1,1,3,3] +; AVX-NEXT: vmovaps %xmm0, (%rsp) # 16-byte Spill +; AVX-NEXT: vpsrlq $48, %xmm1, %xmm0 +; AVX-NEXT: callq __extendhfsf2@PLT +; AVX-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX-NEXT: vmovaps (%rsp), %xmm0 # 16-byte Reload +; AVX-NEXT: callq __extendhfsf2@PLT +; AVX-NEXT: vinsertps $16, {{[-0-9]+}}(%r{{[sb]}}p), %xmm0, %xmm0 # 16-byte Folded Reload +; AVX-NEXT: # xmm0 = xmm0[0],mem[0],xmm0[2,3] +; AVX-NEXT: vcvttps2dq %xmm0, %xmm0 +; AVX-NEXT: vmovaps %xmm0, (%rsp) # 16-byte Spill +; AVX-NEXT: vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload +; AVX-NEXT: callq __extendhfsf2@PLT +; AVX-NEXT: vmovaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX-NEXT: vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload +; AVX-NEXT: callq __extendhfsf2@PLT +; AVX-NEXT: vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload +; AVX-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[2,3] +; AVX-NEXT: vcvttps2dq %xmm0, %xmm0 +; AVX-NEXT: vunpcklpd (%rsp), %xmm0, %xmm0 # 16-byte Folded Reload +; AVX-NEXT: # xmm0 = xmm0[0],mem[0] +; AVX-NEXT: addq $72, %rsp +; AVX-NEXT: retq +; +; F16C-LABEL: fptosi_4f16_to_4i32: +; F16C: # %bb.0: +; F16C-NEXT: vcvtph2ps %xmm0, %ymm0 +; F16C-NEXT: vcvttps2dq %ymm0, %ymm0 +; F16C-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0 +; F16C-NEXT: vzeroupper +; F16C-NEXT: retq +; +; AVX512-LABEL: fptosi_4f16_to_4i32: +; AVX512: # %bb.0: +; AVX512-NEXT: vcvtph2ps %xmm0, %ymm0 +; AVX512-NEXT: vcvttps2dq %ymm0, %ymm0 +; AVX512-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0 +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq + %cvt = fptosi <4 x half> %a to <4 x i32> + ret <4 x i32> %cvt +} + +define <4 x i32> @fptoui_2f16_to_4i32(<2 x half> %a) nounwind { +; AVX1-LABEL: fptoui_2f16_to_4i32: +; AVX1: # %bb.0: +; AVX1-NEXT: subq $40, %rsp +; AVX1-NEXT: vpsrld $16, %xmm0, %xmm1 +; AVX1-NEXT: vmovdqa %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX1-NEXT: callq __extendhfsf2@PLT +; AVX1-NEXT: vmovdqa %xmm0, (%rsp) # 16-byte Spill +; AVX1-NEXT: vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload +; AVX1-NEXT: callq __extendhfsf2@PLT +; AVX1-NEXT: vmovaps (%rsp), %xmm1 # 16-byte Reload +; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[2,3] +; AVX1-NEXT: vcvttps2dq %xmm0, %xmm1 +; AVX1-NEXT: vpsrad $31, %xmm1, %xmm2 +; AVX1-NEXT: vsubps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX1-NEXT: vcvttps2dq %xmm0, %xmm0 +; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpor %xmm0, %xmm1, %xmm0 +; AVX1-NEXT: vmovq {{.*#+}} xmm0 = xmm0[0],zero +; AVX1-NEXT: addq $40, %rsp +; AVX1-NEXT: retq +; +; AVX2-LABEL: fptoui_2f16_to_4i32: +; AVX2: # %bb.0: +; AVX2-NEXT: subq $40, %rsp +; AVX2-NEXT: vpsrld $16, %xmm0, %xmm1 +; AVX2-NEXT: vmovdqa %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX2-NEXT: callq __extendhfsf2@PLT +; AVX2-NEXT: vmovdqa %xmm0, (%rsp) # 16-byte Spill +; AVX2-NEXT: vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload +; AVX2-NEXT: callq __extendhfsf2@PLT +; AVX2-NEXT: vmovaps (%rsp), %xmm1 # 16-byte Reload +; AVX2-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[2,3] +; AVX2-NEXT: vcvttps2dq %xmm0, %xmm1 +; AVX2-NEXT: vpsrad $31, %xmm1, %xmm2 +; AVX2-NEXT: vbroadcastss {{.*#+}} xmm3 = [2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9] +; AVX2-NEXT: vsubps %xmm3, %xmm0, %xmm0 +; AVX2-NEXT: vcvttps2dq %xmm0, %xmm0 +; AVX2-NEXT: vpand %xmm2, %xmm0, %xmm0 +; AVX2-NEXT: vpor %xmm0, %xmm1, %xmm0 +; AVX2-NEXT: vmovq {{.*#+}} xmm0 = xmm0[0],zero +; AVX2-NEXT: addq $40, %rsp +; AVX2-NEXT: retq +; +; F16C-LABEL: fptoui_2f16_to_4i32: +; F16C: # %bb.0: +; F16C-NEXT: vpsrld $16, %xmm0, %xmm1 +; F16C-NEXT: vcvtph2ps %xmm1, %xmm1 +; F16C-NEXT: vpmovzxwd {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; F16C-NEXT: vcvtph2ps %xmm0, %xmm0 +; F16C-NEXT: vunpcklps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1] +; F16C-NEXT: vcvttps2dq %xmm0, %xmm1 +; F16C-NEXT: vpsrad $31, %xmm1, %xmm2 +; F16C-NEXT: vsubps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; F16C-NEXT: vcvttps2dq %xmm0, %xmm0 +; F16C-NEXT: vpand %xmm2, %xmm0, %xmm0 +; F16C-NEXT: vpor %xmm0, %xmm1, %xmm0 +; F16C-NEXT: vmovq {{.*#+}} xmm0 = xmm0[0],zero +; F16C-NEXT: retq +; +; AVX512F-LABEL: fptoui_2f16_to_4i32: +; AVX512F: # %bb.0: +; AVX512F-NEXT: vpsrld $16, %xmm0, %xmm1 +; AVX512F-NEXT: vcvtph2ps %xmm1, %xmm1 +; AVX512F-NEXT: vpmovzxwd {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; AVX512F-NEXT: vcvtph2ps %xmm0, %xmm0 +; AVX512F-NEXT: vunpcklps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1] +; AVX512F-NEXT: vcvttps2udq %zmm0, %zmm0 +; AVX512F-NEXT: vmovq {{.*#+}} xmm0 = xmm0[0],zero +; AVX512F-NEXT: vzeroupper +; AVX512F-NEXT: retq +; +; AVX512-FASTLANE-LABEL: fptoui_2f16_to_4i32: +; AVX512-FASTLANE: # %bb.0: +; AVX512-FASTLANE-NEXT: vpsrld $16, %xmm0, %xmm1 +; AVX512-FASTLANE-NEXT: vcvtph2ps %xmm1, %xmm1 +; AVX512-FASTLANE-NEXT: vpmovzxwd {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,xmm0[2],zero,xmm0[3],zero +; AVX512-FASTLANE-NEXT: vcvtph2ps %xmm0, %xmm0 +; AVX512-FASTLANE-NEXT: vunpcklps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1] +; AVX512-FASTLANE-NEXT: vcvttps2udq %xmm0, %xmm0 +; AVX512-FASTLANE-NEXT: vmovq {{.*#+}} xmm0 = xmm0[0],zero +; AVX512-FASTLANE-NEXT: retq + %cvt = fptoui <2 x half> %a to <2 x i32> + %ext = shufflevector <2 x i32> %cvt, <2 x i32> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3> + ret <4 x i32> %ext +} + +define <4 x i32> @fptoui_4f16_to_4i32(<4 x half> %a) nounwind { +; AVX1-LABEL: fptoui_4f16_to_4i32: +; AVX1: # %bb.0: +; AVX1-NEXT: subq $72, %rsp +; AVX1-NEXT: vmovdqa %xmm0, %xmm1 +; AVX1-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX1-NEXT: vpsrld $16, %xmm0, %xmm0 +; AVX1-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX1-NEXT: vmovshdup {{.*#+}} xmm0 = xmm1[1,1,3,3] +; AVX1-NEXT: vmovaps %xmm0, (%rsp) # 16-byte Spill +; AVX1-NEXT: vpsrlq $48, %xmm1, %xmm0 +; AVX1-NEXT: callq __extendhfsf2@PLT +; AVX1-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX1-NEXT: vmovaps (%rsp), %xmm0 # 16-byte Reload +; AVX1-NEXT: callq __extendhfsf2@PLT +; AVX1-NEXT: vinsertps $16, {{[-0-9]+}}(%r{{[sb]}}p), %xmm0, %xmm0 # 16-byte Folded Reload +; AVX1-NEXT: # xmm0 = xmm0[0],mem[0],xmm0[2,3] +; AVX1-NEXT: vcvttps2dq %xmm0, %xmm1 +; AVX1-NEXT: vpsrad $31, %xmm1, %xmm2 +; AVX1-NEXT: vsubps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX1-NEXT: vcvttps2dq %xmm0, %xmm0 +; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpor %xmm0, %xmm1, %xmm0 +; AVX1-NEXT: vmovdqa %xmm0, (%rsp) # 16-byte Spill +; AVX1-NEXT: vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload +; AVX1-NEXT: callq __extendhfsf2@PLT +; AVX1-NEXT: vmovaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX1-NEXT: vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload +; AVX1-NEXT: callq __extendhfsf2@PLT +; AVX1-NEXT: vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload +; AVX1-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[2,3] +; AVX1-NEXT: vcvttps2dq %xmm0, %xmm1 +; AVX1-NEXT: vpsrad $31, %xmm1, %xmm2 +; AVX1-NEXT: vsubps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 +; AVX1-NEXT: vcvttps2dq %xmm0, %xmm0 +; AVX1-NEXT: vpand %xmm2, %xmm0, %xmm0 +; AVX1-NEXT: vpor %xmm0, %xmm1, %xmm0 +; AVX1-NEXT: vpunpcklqdq (%rsp), %xmm0, %xmm0 # 16-byte Folded Reload +; AVX1-NEXT: # xmm0 = xmm0[0],mem[0] +; AVX1-NEXT: addq $72, %rsp +; AVX1-NEXT: retq +; +; AVX2-LABEL: fptoui_4f16_to_4i32: +; AVX2: # %bb.0: +; AVX2-NEXT: subq $72, %rsp +; AVX2-NEXT: vmovdqa %xmm0, %xmm1 +; AVX2-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX2-NEXT: vpsrld $16, %xmm0, %xmm0 +; AVX2-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX2-NEXT: vmovshdup {{.*#+}} xmm0 = xmm1[1,1,3,3] +; AVX2-NEXT: vmovaps %xmm0, (%rsp) # 16-byte Spill +; AVX2-NEXT: vpsrlq $48, %xmm1, %xmm0 +; AVX2-NEXT: callq __extendhfsf2@PLT +; AVX2-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX2-NEXT: vmovaps (%rsp), %xmm0 # 16-byte Reload +; AVX2-NEXT: callq __extendhfsf2@PLT +; AVX2-NEXT: vinsertps $16, {{[-0-9]+}}(%r{{[sb]}}p), %xmm0, %xmm0 # 16-byte Folded Reload +; AVX2-NEXT: # xmm0 = xmm0[0],mem[0],xmm0[2,3] +; AVX2-NEXT: vcvttps2dq %xmm0, %xmm1 +; AVX2-NEXT: vpsrad $31, %xmm1, %xmm2 +; AVX2-NEXT: vbroadcastss {{.*#+}} xmm3 = [2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9] +; AVX2-NEXT: vsubps %xmm3, %xmm0, %xmm0 +; AVX2-NEXT: vcvttps2dq %xmm0, %xmm0 +; AVX2-NEXT: vpand %xmm2, %xmm0, %xmm0 +; AVX2-NEXT: vpor %xmm0, %xmm1, %xmm0 +; AVX2-NEXT: vmovdqa %xmm0, (%rsp) # 16-byte Spill +; AVX2-NEXT: vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload +; AVX2-NEXT: callq __extendhfsf2@PLT +; AVX2-NEXT: vmovaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX2-NEXT: vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload +; AVX2-NEXT: callq __extendhfsf2@PLT +; AVX2-NEXT: vmovaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload +; AVX2-NEXT: vinsertps {{.*#+}} xmm0 = xmm1[0],xmm0[0],xmm1[2,3] +; AVX2-NEXT: vcvttps2dq %xmm0, %xmm1 +; AVX2-NEXT: vpsrad $31, %xmm1, %xmm2 +; AVX2-NEXT: vbroadcastss {{.*#+}} xmm3 = [2.14748365E+9,2.14748365E+9,2.14748365E+9,2.14748365E+9] +; AVX2-NEXT: vsubps %xmm3, %xmm0, %xmm0 +; AVX2-NEXT: vcvttps2dq %xmm0, %xmm0 +; AVX2-NEXT: vpand %xmm2, %xmm0, %xmm0 +; AVX2-NEXT: vpor %xmm0, %xmm1, %xmm0 +; AVX2-NEXT: vpunpcklqdq (%rsp), %xmm0, %xmm0 # 16-byte Folded Reload +; AVX2-NEXT: # xmm0 = xmm0[0],mem[0] +; AVX2-NEXT: addq $72, %rsp +; AVX2-NEXT: retq +; +; F16C-LABEL: fptoui_4f16_to_4i32: +; F16C: # %bb.0: +; F16C-NEXT: vcvtph2ps %xmm0, %ymm0 +; F16C-NEXT: vcvttps2dq %ymm0, %ymm1 +; F16C-NEXT: vsubps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 +; F16C-NEXT: vcvttps2dq %ymm0, %ymm0 +; F16C-NEXT: vorps %ymm0, %ymm1, %ymm0 +; F16C-NEXT: vblendvps %ymm1, %ymm0, %ymm1, %ymm0 +; F16C-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0 +; F16C-NEXT: vzeroupper +; F16C-NEXT: retq +; +; AVX512F-LABEL: fptoui_4f16_to_4i32: +; AVX512F: # %bb.0: +; AVX512F-NEXT: vcvtph2ps %xmm0, %ymm0 +; AVX512F-NEXT: vcvttps2udq %zmm0, %zmm0 +; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0 +; AVX512F-NEXT: vzeroupper +; AVX512F-NEXT: retq +; +; AVX512-FASTLANE-LABEL: fptoui_4f16_to_4i32: +; AVX512-FASTLANE: # %bb.0: +; AVX512-FASTLANE-NEXT: vcvtph2ps %xmm0, %ymm0 +; AVX512-FASTLANE-NEXT: vcvttps2udq %ymm0, %ymm0 +; AVX512-FASTLANE-NEXT: # kill: def $xmm0 killed $xmm0 killed $ymm0 +; AVX512-FASTLANE-NEXT: vzeroupper +; AVX512-FASTLANE-NEXT: retq + %cvt = fptoui <4 x half> %a to <4 x i32> + ret <4 x i32> %cvt +} diff --git a/llvm/test/CodeGen/X86/vector-interleaved-store-i8-stride-5.ll b/llvm/test/CodeGen/X86/vector-interleaved-store-i8-stride-5.ll index 2b539aecc2ad8ecbb4dfdbd893f1851ed4a62f5c..f56c43eb49df2f8650b581dd69dc835c78467fa8 100644 --- a/llvm/test/CodeGen/X86/vector-interleaved-store-i8-stride-5.ll +++ b/llvm/test/CodeGen/X86/vector-interleaved-store-i8-stride-5.ll @@ -2208,15 +2208,13 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-NEXT: vmovdqa {{.*#+}} ymm9 = [255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255] ; AVX2-NEXT: vpblendvb %ymm9, %ymm7, %ymm8, %ymm7 ; AVX2-NEXT: vpshufb {{.*#+}} ymm8 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[21],zero,ymm3[19,20],zero,ymm3[22],zero,ymm3[24],zero,ymm3[22,23],zero,ymm3[25],zero,ymm3[23] -; AVX2-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] ; AVX2-NEXT: vpshufb {{.*#+}} ymm9 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19],zero,ymm4[21],zero,zero,ymm4[20],zero,ymm4[22],zero,ymm4[24],zero,zero,ymm4[23],zero,ymm4[25],zero -; AVX2-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] ; AVX2-NEXT: vpor %ymm8, %ymm9, %ymm8 +; AVX2-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] ; AVX2-NEXT: vpshufb {{.*#+}} ymm9 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[19],zero,ymm2[21],zero,zero,ymm2[20],zero,ymm2[22],zero,ymm2[24],zero,zero,ymm2[23],zero -; AVX2-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] ; AVX2-NEXT: vpshufb {{.*#+}} ymm10 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[19],zero,ymm1[21],zero,zero,ymm1[20],zero,ymm1[22],zero,ymm1[24],zero,zero,ymm1[23],zero,ymm1[25] -; AVX2-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,2,3,3] ; AVX2-NEXT: vpor %ymm9, %ymm10, %ymm9 +; AVX2-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] ; AVX2-NEXT: vmovdqa {{.*#+}} ymm10 = [255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0] ; AVX2-NEXT: vpblendvb %ymm10, %ymm8, %ymm9, %ymm8 ; AVX2-NEXT: vpshufd {{.*#+}} ymm9 = ymm0[0,2,1,1,4,6,5,5] @@ -2284,15 +2282,13 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm8 = [255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255] ; AVX2-FP-NEXT: vpblendvb %ymm8, %ymm6, %ymm7, %ymm6 ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm7 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[21],zero,ymm3[19,20],zero,ymm3[22],zero,ymm3[24],zero,ymm3[22,23],zero,ymm3[25],zero,ymm3[23] -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm8 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19],zero,ymm4[21],zero,zero,ymm4[20],zero,ymm4[22],zero,ymm4[24],zero,zero,ymm4[23],zero,ymm4[25],zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] ; AVX2-FP-NEXT: vpor %ymm7, %ymm8, %ymm7 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm8 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[19],zero,ymm2[21],zero,zero,ymm2[20],zero,ymm2[22],zero,ymm2[24],zero,zero,ymm2[23],zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm9 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[19],zero,ymm1[21],zero,zero,ymm1[20],zero,ymm1[22],zero,ymm1[24],zero,zero,ymm1[23],zero,ymm1[25] -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] ; AVX2-FP-NEXT: vpor %ymm8, %ymm9, %ymm8 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm9 = [255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0] ; AVX2-FP-NEXT: vpblendvb %ymm9, %ymm7, %ymm8, %ymm7 ; AVX2-FP-NEXT: vpshufd {{.*#+}} ymm8 = ymm0[0,2,1,1,4,6,5,5] @@ -2300,15 +2296,13 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm9 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255] ; AVX2-FP-NEXT: vpblendvb %ymm9, %ymm7, %ymm8, %ymm7 ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm8 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[27],zero,ymm1[29,26],zero,ymm1[28],zero,ymm1[30],zero,ymm1[28,29],zero,ymm1[31],zero,ymm1[29] -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm9 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm2[27],zero,zero,ymm2[26],zero,ymm2[28],zero,ymm2[30],zero,zero,ymm2[29],zero,ymm2[31],zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] ; AVX2-FP-NEXT: vpor %ymm8, %ymm9, %ymm8 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm9 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[29,26],zero,ymm3[28],zero,ymm3[26,27,28,29],zero,ymm3[31],zero,ymm3[29,30],zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm10 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,ymm4[26],zero,ymm4[28],zero,zero,zero,zero,ymm4[29],zero,ymm4[31],zero,zero,ymm4[30] -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,2,3,3] ; AVX2-FP-NEXT: vpor %ymm9, %ymm10, %ymm9 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm10 = [255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u] ; AVX2-FP-NEXT: vpblendvb %ymm10, %ymm8, %ymm9, %ymm8 ; AVX2-FP-NEXT: vpshufd {{.*#+}} ymm9 = ymm0[2,2,3,3,6,6,7,7] @@ -2375,15 +2369,13 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm8 = [255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255] ; AVX2-FCP-NEXT: vpblendvb %ymm8, %ymm6, %ymm7, %ymm6 ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[21],zero,ymm3[19,20],zero,ymm3[22],zero,ymm3[24],zero,ymm3[22,23],zero,ymm3[25],zero,ymm3[23] -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19],zero,ymm4[21],zero,zero,ymm4[20],zero,ymm4[22],zero,ymm4[24],zero,zero,ymm4[23],zero,ymm4[25],zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] ; AVX2-FCP-NEXT: vpor %ymm7, %ymm8, %ymm7 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[19],zero,ymm2[21],zero,zero,ymm2[20],zero,ymm2[22],zero,ymm2[24],zero,zero,ymm2[23],zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[19],zero,ymm1[21],zero,zero,ymm1[20],zero,ymm1[22],zero,ymm1[24],zero,zero,ymm1[23],zero,ymm1[25] -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] ; AVX2-FCP-NEXT: vpor %ymm8, %ymm9, %ymm8 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm9 = [255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0] ; AVX2-FCP-NEXT: vpblendvb %ymm9, %ymm7, %ymm8, %ymm7 ; AVX2-FCP-NEXT: vpmovsxbd {{.*#+}} ymm8 = [4,6,5,5,5,5,4,6] @@ -2391,15 +2383,13 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm9 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255] ; AVX2-FCP-NEXT: vpblendvb %ymm9, %ymm7, %ymm8, %ymm7 ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[27],zero,ymm1[29,26],zero,ymm1[28],zero,ymm1[30],zero,ymm1[28,29],zero,ymm1[31],zero,ymm1[29] -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm2[27],zero,zero,ymm2[26],zero,ymm2[28],zero,ymm2[30],zero,zero,ymm2[29],zero,ymm2[31],zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] ; AVX2-FCP-NEXT: vpor %ymm8, %ymm9, %ymm8 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[29,26],zero,ymm3[28],zero,ymm3[26,27,28,29],zero,ymm3[31],zero,ymm3[29,30],zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,ymm4[26],zero,ymm4[28],zero,zero,zero,zero,ymm4[29],zero,ymm4[31],zero,zero,ymm4[30] -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,2,3,3] ; AVX2-FCP-NEXT: vpor %ymm9, %ymm10, %ymm9 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm10 = [255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u] ; AVX2-FCP-NEXT: vpblendvb %ymm10, %ymm8, %ymm9, %ymm8 ; AVX2-FCP-NEXT: vpmovsxbd {{.*#+}} ymm9 = [6,6,6,6,7,7,7,7] @@ -2430,10 +2420,10 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; ; AVX512-LABEL: store_i8_stride5_vf32: ; AVX512: # %bb.0: -; AVX512-NEXT: vmovdqa (%rdi), %ymm1 -; AVX512-NEXT: vmovdqa (%rsi), %ymm2 -; AVX512-NEXT: vmovdqa (%rdx), %ymm3 -; AVX512-NEXT: vmovdqa (%rcx), %ymm4 +; AVX512-NEXT: vmovdqa (%rdi), %ymm3 +; AVX512-NEXT: vmovdqa (%rsi), %ymm4 +; AVX512-NEXT: vmovdqa (%rdx), %ymm1 +; AVX512-NEXT: vmovdqa (%rcx), %ymm2 ; AVX512-NEXT: vmovdqa (%r8), %ymm0 ; AVX512-NEXT: vmovdqa (%rdi), %xmm5 ; AVX512-NEXT: vpshufb {{.*#+}} xmm6 = xmm5[8],zero,xmm5[u,7],zero,xmm5[9],zero,xmm5[u],zero,xmm5[u,10],zero,xmm5[12],zero,xmm5[u,11] @@ -2463,45 +2453,40 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512-NEXT: vpmovsxbd {{.*#+}} zmm8 = [0,0,0,0,0,0,1,1,1,1,0,2,2,2,2,0] ; AVX512-NEXT: vpermd %zmm6, %zmm8, %zmm6 ; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm6 -; AVX512-NEXT: vpshufb {{.*#+}} ymm5 = ymm4[u,u,u],zero,ymm4[13,u,u,u],zero,ymm4[14,u,u,u],zero,ymm4[15,u,u,u],zero,ymm4[16,u,u,u],zero,ymm4[17,u,u,u],zero,ymm4[18,u,u] -; AVX512-NEXT: vpshufb {{.*#+}} ymm8 = ymm3[u,u,u,13],zero,ymm3[u,u,u,14],zero,ymm3[u,u,u,15],zero,ymm3[u,u,u,16],zero,ymm3[u,u,u,17],zero,ymm3[u,u,u,18],zero,ymm3[u,u] +; AVX512-NEXT: vpshufb {{.*#+}} ymm5 = ymm2[u,u,u],zero,ymm2[13,u,u,u],zero,ymm2[14,u,u,u],zero,ymm2[15,u,u,u],zero,ymm2[16,u,u,u],zero,ymm2[17,u,u,u],zero,ymm2[18,u,u] +; AVX512-NEXT: vpshufb {{.*#+}} ymm8 = ymm1[u,u,u,13],zero,ymm1[u,u,u,14],zero,ymm1[u,u,u,15],zero,ymm1[u,u,u,16],zero,ymm1[u,u,u,17],zero,ymm1[u,u,u,18],zero,ymm1[u,u] ; AVX512-NEXT: vpor %ymm5, %ymm8, %ymm5 -; AVX512-NEXT: vpshufb {{.*#+}} ymm8 = ymm2[u],zero,ymm2[13,u,u,u],zero,ymm2[14,u,u,u],zero,ymm2[15,u,u,u],zero,ymm2[16,u,u,u],zero,ymm2[17,u,u,u],zero,ymm2[18,u,u,u],zero -; AVX512-NEXT: vpshufb {{.*#+}} ymm9 = ymm1[u,13],zero,ymm1[u,u,u,14],zero,ymm1[u,u,u,15],zero,ymm1[u,u,u,16],zero,ymm1[u,u,u,17],zero,ymm1[u,u,u,18],zero,ymm1[u,u,u,19] +; AVX512-NEXT: vpshufb {{.*#+}} ymm8 = ymm4[u],zero,ymm4[13,u,u,u],zero,ymm4[14,u,u,u],zero,ymm4[15,u,u,u],zero,ymm4[16,u,u,u],zero,ymm4[17,u,u,u],zero,ymm4[18,u,u,u],zero +; AVX512-NEXT: vpshufb {{.*#+}} ymm9 = ymm3[u,13],zero,ymm3[u,u,u,14],zero,ymm3[u,u,u,15],zero,ymm3[u,u,u,16],zero,ymm3[u,u,u,17],zero,ymm3[u,u,u,18],zero,ymm3[u,u,u,19] ; AVX512-NEXT: vpor %ymm8, %ymm9, %ymm8 ; AVX512-NEXT: vpternlogq $226, %ymm5, %ymm11, %ymm8 -; AVX512-NEXT: vpshufb {{.*#+}} ymm5 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19,u,21,u,u,20,u,22,u,24,u,u,23,u,25,u] +; AVX512-NEXT: vpshufb {{.*#+}} ymm5 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[21],zero,zero,ymm3[20],zero,ymm3[22],zero,ymm3[24],zero,zero,ymm3[23],zero,ymm3[25],zero,zero +; AVX512-NEXT: vpshufb {{.*#+}} ymm9 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19],zero,ymm4[21,u],zero,ymm4[20],zero,ymm4[22],zero,ymm4[24,u],zero,ymm4[23],zero,ymm4[25,u] +; AVX512-NEXT: vpor %ymm5, %ymm9, %ymm5 ; AVX512-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,2,3,3] -; AVX512-NEXT: vpshufb {{.*#+}} ymm9 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[21],zero,zero,ymm1[20],zero,ymm1[22],zero,ymm1[24],zero,zero,ymm1[23],zero,ymm1[25],zero,zero +; AVX512-NEXT: vpshufb {{.*#+}} ymm9 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[19],zero,ymm2[21],zero,zero,ymm2[20],zero,ymm2[22],zero,ymm2[24],zero,zero,ymm2[23],zero +; AVX512-NEXT: vpshufb {{.*#+}} ymm10 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19],zero,ymm1[21],zero,ymm1[21,20],zero,ymm1[22],zero,ymm1[24],zero,ymm1[22,23],zero,ymm1[25] +; AVX512-NEXT: vpor %ymm9, %ymm10, %ymm9 ; AVX512-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] -; AVX512-NEXT: vmovdqa {{.*#+}} ymm10 = [18374966859431608575,18374966859431608575,18446463693966278400,18446463693966278400] -; AVX512-NEXT: vpternlogq $248, %ymm10, %ymm5, %ymm9 -; AVX512-NEXT: vpshufb {{.*#+}} ymm5 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm4[19],zero,ymm4[21],zero,zero,ymm4[20],zero,ymm4[22],zero,ymm4[24],zero,zero,ymm4[23],zero -; AVX512-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,2,3,3] -; AVX512-NEXT: vpshufb {{.*#+}} ymm11 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19],zero,ymm3[21],zero,ymm3[21,20],zero,ymm3[22],zero,ymm3[24],zero,ymm3[22,23],zero,ymm3[25] -; AVX512-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,2,3,3] -; AVX512-NEXT: vpor %ymm5, %ymm11, %ymm5 -; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm9, %ymm5 -; AVX512-NEXT: vinserti64x4 $1, %ymm5, %zmm0, %zmm5 +; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm5, %ymm9 +; AVX512-NEXT: vinserti64x4 $1, %ymm9, %zmm0, %zmm5 ; AVX512-NEXT: vshufi64x2 {{.*#+}} zmm5 = zmm8[0,1,2,3],zmm5[4,5,6,7] ; AVX512-NEXT: vpshufb {{.*#+}} ymm8 = ymm0[12],zero,zero,zero,zero,ymm0[13],zero,zero,zero,zero,ymm0[14],zero,zero,zero,zero,ymm0[15],zero,zero,zero,zero,ymm0[16],zero,zero,zero,zero,ymm0[17],zero,zero,zero,zero,ymm0[18],zero ; AVX512-NEXT: vpshufd {{.*#+}} ymm9 = ymm0[0,2,1,1,4,6,5,5] ; AVX512-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,3,3,2] -; AVX512-NEXT: vmovdqa {{.*#+}} ymm11 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255] -; AVX512-NEXT: vpandn %ymm9, %ymm11, %ymm9 +; AVX512-NEXT: vmovdqa {{.*#+}} ymm10 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255] +; AVX512-NEXT: vpandn %ymm9, %ymm10, %ymm9 ; AVX512-NEXT: vinserti64x4 $1, %ymm9, %zmm8, %zmm8 ; AVX512-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm8 -; AVX512-NEXT: vpshufb {{.*#+}} ymm4 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25,u,27,u,u,26,u,28,u,30,u,u,29,u,31,u] -; AVX512-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,2,3,3] -; AVX512-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[27],zero,zero,ymm3[26],zero,ymm3[28],zero,ymm3[30],zero,zero,ymm3[29],zero,ymm3[31],zero,zero +; AVX512-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm3[26],zero,ymm3[28],zero,zero,ymm3[27],zero,ymm3[29],zero,ymm3[31],zero,zero,ymm3[30],zero +; AVX512-NEXT: vpshufb {{.*#+}} ymm4 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u],zero,ymm4[26],zero,ymm4[28,u],zero,ymm4[u],zero,ymm4[29],zero,ymm4[31,u],zero,ymm4[30] +; AVX512-NEXT: vpor %ymm3, %ymm4, %ymm3 ; AVX512-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,3,3] -; AVX512-NEXT: vpternlogq $248, %ymm10, %ymm4, %ymm3 -; AVX512-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u,u,26,u,28,u,u,u,u,29,u,31,u,u,30] -; AVX512-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] -; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm1[26],zero,ymm1[28],zero,zero,ymm1[27],zero,ymm1[29],zero,ymm1[31],zero,zero,ymm1[30],zero +; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[27],zero,zero,ymm1[26],zero,ymm1[28],zero,ymm1[30],zero,zero,ymm1[29],zero,ymm1[31],zero,zero +; AVX512-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm2[27,u],zero,ymm2[26],zero,ymm2[28],zero,ymm2[30,u],zero,ymm2[29],zero,ymm2[31,u] +; AVX512-NEXT: vpor %ymm1, %ymm2, %ymm1 ; AVX512-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,2,3,3] -; AVX512-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm1 -; AVX512-NEXT: vpternlogq $184, %ymm3, %ymm7, %ymm1 +; AVX512-NEXT: vpternlogq $226, %ymm3, %ymm7, %ymm1 ; AVX512-NEXT: vpshufd {{.*#+}} ymm0 = ymm0[2,2,3,3,6,6,7,7] ; AVX512-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] ; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm0 @@ -2513,10 +2498,10 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; ; AVX512-FCP-LABEL: store_i8_stride5_vf32: ; AVX512-FCP: # %bb.0: -; AVX512-FCP-NEXT: vmovdqa (%rdi), %ymm0 -; AVX512-FCP-NEXT: vmovdqa (%rsi), %ymm1 -; AVX512-FCP-NEXT: vmovdqa (%rdx), %ymm2 -; AVX512-FCP-NEXT: vmovdqa (%rcx), %ymm3 +; AVX512-FCP-NEXT: vmovdqa (%rdi), %ymm2 +; AVX512-FCP-NEXT: vmovdqa (%rsi), %ymm3 +; AVX512-FCP-NEXT: vmovdqa (%rdx), %ymm0 +; AVX512-FCP-NEXT: vmovdqa (%rcx), %ymm1 ; AVX512-FCP-NEXT: vmovdqa (%rdi), %xmm4 ; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm5 = xmm4[8],zero,xmm4[u,7],zero,xmm4[9],zero,xmm4[u],zero,xmm4[u,10],zero,xmm4[12],zero,xmm4[u,11] ; AVX512-FCP-NEXT: vmovdqa (%rsi), %xmm6 @@ -2545,26 +2530,23 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} zmm7 = [0,0,0,0,0,0,1,1,9,9,0,10,10,10,10,0] ; AVX512-FCP-NEXT: vpermd %zmm4, %zmm7, %zmm7 ; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm7 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm3[u,u,u],zero,ymm3[13,u,u,u],zero,ymm3[14,u,u,u],zero,ymm3[15,u,u,u],zero,ymm3[16,u,u,u],zero,ymm3[17,u,u,u],zero,ymm3[18,u,u] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm2[u,u,u,13],zero,ymm2[u,u,u,14],zero,ymm2[u,u,u,15],zero,ymm2[u,u,u,16],zero,ymm2[u,u,u,17],zero,ymm2[u,u,u,18],zero,ymm2[u,u] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm1[u,u,u],zero,ymm1[13,u,u,u],zero,ymm1[14,u,u,u],zero,ymm1[15,u,u,u],zero,ymm1[16,u,u,u],zero,ymm1[17,u,u,u],zero,ymm1[18,u,u] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm0[u,u,u,13],zero,ymm0[u,u,u,14],zero,ymm0[u,u,u,15],zero,ymm0[u,u,u,16],zero,ymm0[u,u,u,17],zero,ymm0[u,u,u,18],zero,ymm0[u,u] ; AVX512-FCP-NEXT: vpor %ymm5, %ymm8, %ymm5 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm1[u],zero,ymm1[13,u,u,u],zero,ymm1[14,u,u,u],zero,ymm1[15,u,u,u],zero,ymm1[16,u,u,u],zero,ymm1[17,u,u,u],zero,ymm1[18,u,u,u],zero -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm0[u,13],zero,ymm0[u,u,u,14],zero,ymm0[u,u,u,15],zero,ymm0[u,u,u,16],zero,ymm0[u,u,u,17],zero,ymm0[u,u,u,18],zero,ymm0[u,u,u,19] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm3[u],zero,ymm3[13,u,u,u],zero,ymm3[14,u,u,u],zero,ymm3[15,u,u,u],zero,ymm3[16,u,u,u],zero,ymm3[17,u,u,u],zero,ymm3[18,u,u,u],zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm2[u,13],zero,ymm2[u,u,u,14],zero,ymm2[u,u,u,15],zero,ymm2[u,u,u,16],zero,ymm2[u,u,u,17],zero,ymm2[u,u,u,18],zero,ymm2[u,u,u,19] ; AVX512-FCP-NEXT: vpor %ymm8, %ymm9, %ymm8 ; AVX512-FCP-NEXT: vpternlogq $226, %ymm5, %ymm10, %ymm8 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19,u,21,u,u,20,u,22,u,24,u,u,23,u,25,u] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[21],zero,zero,ymm2[20],zero,ymm2[22],zero,ymm2[24],zero,zero,ymm2[23],zero,ymm2[25],zero,zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19],zero,ymm3[21,u],zero,ymm3[20],zero,ymm3[22],zero,ymm3[24,u],zero,ymm3[23],zero,ymm3[25,u] +; AVX512-FCP-NEXT: vpor %ymm5, %ymm9, %ymm5 ; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,2,3,3] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[21],zero,zero,ymm0[20],zero,ymm0[22],zero,ymm0[24],zero,zero,ymm0[23],zero,ymm0[25],zero,zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm1[19],zero,ymm1[21],zero,zero,ymm1[20],zero,ymm1[22],zero,ymm1[24],zero,zero,ymm1[23],zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19],zero,ymm0[21],zero,ymm0[21,20],zero,ymm0[22],zero,ymm0[24],zero,ymm0[22,23],zero,ymm0[25] +; AVX512-FCP-NEXT: vpor %ymm9, %ymm10, %ymm9 ; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm10 = [18374966859431608575,18374966859431608575,18446463693966278400,18446463693966278400] -; AVX512-FCP-NEXT: vpternlogq $248, %ymm10, %ymm5, %ymm9 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm3[19],zero,ymm3[21],zero,zero,ymm3[20],zero,ymm3[22],zero,ymm3[24],zero,zero,ymm3[23],zero -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,2,3,3] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19],zero,ymm2[21],zero,ymm2[21,20],zero,ymm2[22],zero,ymm2[24],zero,ymm2[22,23],zero,ymm2[25] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,2,3,3] -; AVX512-FCP-NEXT: vpor %ymm5, %ymm11, %ymm5 -; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm9, %ymm5 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm5, %zmm0, %zmm5 +; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm5, %ymm9 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm9, %zmm0, %zmm5 ; AVX512-FCP-NEXT: vshufi64x2 {{.*#+}} zmm5 = zmm8[0,1,2,3],zmm5[4,5,6,7] ; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} ymm8 = [4,0,5,5,5,5,0,6] ; AVX512-FCP-NEXT: vpermd %ymm4, %ymm8, %ymm8 @@ -2573,17 +2555,15 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm4[12],zero,zero,zero,zero,ymm4[13],zero,zero,zero,zero,ymm4[14],zero,zero,zero,zero,ymm4[15],zero,zero,zero,zero,ymm4[16],zero,zero,zero,zero,ymm4[17],zero,zero,zero,zero,ymm4[18],zero ; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm8, %zmm9, %zmm8 ; AVX512-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm8 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25,u,27,u,u,26,u,28,u,30,u,u,29,u,31,u] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,3,3] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[27],zero,zero,ymm2[26],zero,ymm2[28],zero,ymm2[30],zero,zero,ymm2[29],zero,ymm2[31],zero,zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[26],zero,ymm2[28],zero,zero,ymm2[27],zero,ymm2[29],zero,ymm2[31],zero,zero,ymm2[30],zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u],zero,ymm3[26],zero,ymm3[28,u],zero,ymm3[u],zero,ymm3[29],zero,ymm3[31,u],zero,ymm3[30] +; AVX512-FCP-NEXT: vpor %ymm2, %ymm3, %ymm2 ; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] -; AVX512-FCP-NEXT: vpternlogq $248, %ymm10, %ymm3, %ymm2 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u,u,26,u,28,u,u,u,u,29,u,31,u,u,30] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,2,3,3] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm0[26],zero,ymm0[28],zero,zero,ymm0[27],zero,ymm0[29],zero,ymm0[31],zero,zero,ymm0[30],zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[27],zero,zero,ymm0[26],zero,ymm0[28],zero,ymm0[30],zero,zero,ymm0[29],zero,ymm0[31],zero,zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm1[27,u],zero,ymm1[26],zero,ymm1[28],zero,ymm1[30,u],zero,ymm1[29],zero,ymm1[31,u] +; AVX512-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] -; AVX512-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm0 -; AVX512-FCP-NEXT: vpternlogq $184, %ymm2, %ymm6, %ymm0 +; AVX512-FCP-NEXT: vpternlogq $226, %ymm2, %ymm6, %ymm0 ; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} ymm1 = [6,6,6,0,7,7,7,7] ; AVX512-FCP-NEXT: vpermd %ymm4, %ymm1, %ymm1 ; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1 @@ -2595,10 +2575,10 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; ; AVX512DQ-LABEL: store_i8_stride5_vf32: ; AVX512DQ: # %bb.0: -; AVX512DQ-NEXT: vmovdqa (%rdi), %ymm1 -; AVX512DQ-NEXT: vmovdqa (%rsi), %ymm2 -; AVX512DQ-NEXT: vmovdqa (%rdx), %ymm3 -; AVX512DQ-NEXT: vmovdqa (%rcx), %ymm4 +; AVX512DQ-NEXT: vmovdqa (%rdi), %ymm3 +; AVX512DQ-NEXT: vmovdqa (%rsi), %ymm4 +; AVX512DQ-NEXT: vmovdqa (%rdx), %ymm1 +; AVX512DQ-NEXT: vmovdqa (%rcx), %ymm2 ; AVX512DQ-NEXT: vmovdqa (%r8), %ymm0 ; AVX512DQ-NEXT: vmovdqa (%rdi), %xmm5 ; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm6 = xmm5[8],zero,xmm5[u,7],zero,xmm5[9],zero,xmm5[u],zero,xmm5[u,10],zero,xmm5[12],zero,xmm5[u,11] @@ -2628,45 +2608,40 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-NEXT: vpmovsxbd {{.*#+}} zmm8 = [0,0,0,0,0,0,1,1,1,1,0,2,2,2,2,0] ; AVX512DQ-NEXT: vpermd %zmm6, %zmm8, %zmm6 ; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm6 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm5 = ymm4[u,u,u],zero,ymm4[13,u,u,u],zero,ymm4[14,u,u,u],zero,ymm4[15,u,u,u],zero,ymm4[16,u,u,u],zero,ymm4[17,u,u,u],zero,ymm4[18,u,u] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm8 = ymm3[u,u,u,13],zero,ymm3[u,u,u,14],zero,ymm3[u,u,u,15],zero,ymm3[u,u,u,16],zero,ymm3[u,u,u,17],zero,ymm3[u,u,u,18],zero,ymm3[u,u] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm5 = ymm2[u,u,u],zero,ymm2[13,u,u,u],zero,ymm2[14,u,u,u],zero,ymm2[15,u,u,u],zero,ymm2[16,u,u,u],zero,ymm2[17,u,u,u],zero,ymm2[18,u,u] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm8 = ymm1[u,u,u,13],zero,ymm1[u,u,u,14],zero,ymm1[u,u,u,15],zero,ymm1[u,u,u,16],zero,ymm1[u,u,u,17],zero,ymm1[u,u,u,18],zero,ymm1[u,u] ; AVX512DQ-NEXT: vpor %ymm5, %ymm8, %ymm5 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm8 = ymm2[u],zero,ymm2[13,u,u,u],zero,ymm2[14,u,u,u],zero,ymm2[15,u,u,u],zero,ymm2[16,u,u,u],zero,ymm2[17,u,u,u],zero,ymm2[18,u,u,u],zero -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm9 = ymm1[u,13],zero,ymm1[u,u,u,14],zero,ymm1[u,u,u,15],zero,ymm1[u,u,u,16],zero,ymm1[u,u,u,17],zero,ymm1[u,u,u,18],zero,ymm1[u,u,u,19] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm8 = ymm4[u],zero,ymm4[13,u,u,u],zero,ymm4[14,u,u,u],zero,ymm4[15,u,u,u],zero,ymm4[16,u,u,u],zero,ymm4[17,u,u,u],zero,ymm4[18,u,u,u],zero +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm9 = ymm3[u,13],zero,ymm3[u,u,u,14],zero,ymm3[u,u,u,15],zero,ymm3[u,u,u,16],zero,ymm3[u,u,u,17],zero,ymm3[u,u,u,18],zero,ymm3[u,u,u,19] ; AVX512DQ-NEXT: vpor %ymm8, %ymm9, %ymm8 ; AVX512DQ-NEXT: vpternlogq $226, %ymm5, %ymm11, %ymm8 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm5 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19,u,21,u,u,20,u,22,u,24,u,u,23,u,25,u] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm5 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[21],zero,zero,ymm3[20],zero,ymm3[22],zero,ymm3[24],zero,zero,ymm3[23],zero,ymm3[25],zero,zero +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm9 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19],zero,ymm4[21,u],zero,ymm4[20],zero,ymm4[22],zero,ymm4[24,u],zero,ymm4[23],zero,ymm4[25,u] +; AVX512DQ-NEXT: vpor %ymm5, %ymm9, %ymm5 ; AVX512DQ-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,2,3,3] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm9 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[21],zero,zero,ymm1[20],zero,ymm1[22],zero,ymm1[24],zero,zero,ymm1[23],zero,ymm1[25],zero,zero +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm9 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[19],zero,ymm2[21],zero,zero,ymm2[20],zero,ymm2[22],zero,ymm2[24],zero,zero,ymm2[23],zero +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm10 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19],zero,ymm1[21],zero,ymm1[21,20],zero,ymm1[22],zero,ymm1[24],zero,ymm1[22,23],zero,ymm1[25] +; AVX512DQ-NEXT: vpor %ymm9, %ymm10, %ymm9 ; AVX512DQ-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm10 = [18374966859431608575,18374966859431608575,18446463693966278400,18446463693966278400] -; AVX512DQ-NEXT: vpternlogq $248, %ymm10, %ymm5, %ymm9 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm5 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm4[19],zero,ymm4[21],zero,zero,ymm4[20],zero,ymm4[22],zero,ymm4[24],zero,zero,ymm4[23],zero -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,2,3,3] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm11 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19],zero,ymm3[21],zero,ymm3[21,20],zero,ymm3[22],zero,ymm3[24],zero,ymm3[22,23],zero,ymm3[25] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,2,3,3] -; AVX512DQ-NEXT: vpor %ymm5, %ymm11, %ymm5 -; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm9, %ymm5 -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm5, %zmm0, %zmm5 +; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm5, %ymm9 +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm9, %zmm0, %zmm5 ; AVX512DQ-NEXT: vshufi64x2 {{.*#+}} zmm5 = zmm8[0,1,2,3],zmm5[4,5,6,7] ; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm8 = ymm0[12],zero,zero,zero,zero,ymm0[13],zero,zero,zero,zero,ymm0[14],zero,zero,zero,zero,ymm0[15],zero,zero,zero,zero,ymm0[16],zero,zero,zero,zero,ymm0[17],zero,zero,zero,zero,ymm0[18],zero ; AVX512DQ-NEXT: vpshufd {{.*#+}} ymm9 = ymm0[0,2,1,1,4,6,5,5] ; AVX512DQ-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,3,3,2] -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm11 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255] -; AVX512DQ-NEXT: vpandn %ymm9, %ymm11, %ymm9 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm10 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255] +; AVX512DQ-NEXT: vpandn %ymm9, %ymm10, %ymm9 ; AVX512DQ-NEXT: vinserti64x4 $1, %ymm9, %zmm8, %zmm8 ; AVX512DQ-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm8 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm4 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25,u,27,u,u,26,u,28,u,30,u,u,29,u,31,u] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,2,3,3] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[27],zero,zero,ymm3[26],zero,ymm3[28],zero,ymm3[30],zero,zero,ymm3[29],zero,ymm3[31],zero,zero +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm3[26],zero,ymm3[28],zero,zero,ymm3[27],zero,ymm3[29],zero,ymm3[31],zero,zero,ymm3[30],zero +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm4 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u],zero,ymm4[26],zero,ymm4[28,u],zero,ymm4[u],zero,ymm4[29],zero,ymm4[31,u],zero,ymm4[30] +; AVX512DQ-NEXT: vpor %ymm3, %ymm4, %ymm3 ; AVX512DQ-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,3,3] -; AVX512DQ-NEXT: vpternlogq $248, %ymm10, %ymm4, %ymm3 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u,u,26,u,28,u,u,u,u,29,u,31,u,u,30] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm1[26],zero,ymm1[28],zero,zero,ymm1[27],zero,ymm1[29],zero,ymm1[31],zero,zero,ymm1[30],zero +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[27],zero,zero,ymm1[26],zero,ymm1[28],zero,ymm1[30],zero,zero,ymm1[29],zero,ymm1[31],zero,zero +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm2[27,u],zero,ymm2[26],zero,ymm2[28],zero,ymm2[30,u],zero,ymm2[29],zero,ymm2[31,u] +; AVX512DQ-NEXT: vpor %ymm1, %ymm2, %ymm1 ; AVX512DQ-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,2,3,3] -; AVX512DQ-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm1 -; AVX512DQ-NEXT: vpternlogq $184, %ymm3, %ymm7, %ymm1 +; AVX512DQ-NEXT: vpternlogq $226, %ymm3, %ymm7, %ymm1 ; AVX512DQ-NEXT: vpshufd {{.*#+}} ymm0 = ymm0[2,2,3,3,6,6,7,7] ; AVX512DQ-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] ; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm0 @@ -2678,10 +2653,10 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; ; AVX512DQ-FCP-LABEL: store_i8_stride5_vf32: ; AVX512DQ-FCP: # %bb.0: -; AVX512DQ-FCP-NEXT: vmovdqa (%rdi), %ymm0 -; AVX512DQ-FCP-NEXT: vmovdqa (%rsi), %ymm1 -; AVX512DQ-FCP-NEXT: vmovdqa (%rdx), %ymm2 -; AVX512DQ-FCP-NEXT: vmovdqa (%rcx), %ymm3 +; AVX512DQ-FCP-NEXT: vmovdqa (%rdi), %ymm2 +; AVX512DQ-FCP-NEXT: vmovdqa (%rsi), %ymm3 +; AVX512DQ-FCP-NEXT: vmovdqa (%rdx), %ymm0 +; AVX512DQ-FCP-NEXT: vmovdqa (%rcx), %ymm1 ; AVX512DQ-FCP-NEXT: vmovdqa (%rdi), %xmm4 ; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm5 = xmm4[8],zero,xmm4[u,7],zero,xmm4[9],zero,xmm4[u],zero,xmm4[u,10],zero,xmm4[12],zero,xmm4[u,11] ; AVX512DQ-FCP-NEXT: vmovdqa (%rsi), %xmm6 @@ -2710,26 +2685,23 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} zmm7 = [0,0,0,0,0,0,1,1,9,9,0,10,10,10,10,0] ; AVX512DQ-FCP-NEXT: vpermd %zmm4, %zmm7, %zmm7 ; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm7 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm3[u,u,u],zero,ymm3[13,u,u,u],zero,ymm3[14,u,u,u],zero,ymm3[15,u,u,u],zero,ymm3[16,u,u,u],zero,ymm3[17,u,u,u],zero,ymm3[18,u,u] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm2[u,u,u,13],zero,ymm2[u,u,u,14],zero,ymm2[u,u,u,15],zero,ymm2[u,u,u,16],zero,ymm2[u,u,u,17],zero,ymm2[u,u,u,18],zero,ymm2[u,u] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm1[u,u,u],zero,ymm1[13,u,u,u],zero,ymm1[14,u,u,u],zero,ymm1[15,u,u,u],zero,ymm1[16,u,u,u],zero,ymm1[17,u,u,u],zero,ymm1[18,u,u] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm0[u,u,u,13],zero,ymm0[u,u,u,14],zero,ymm0[u,u,u,15],zero,ymm0[u,u,u,16],zero,ymm0[u,u,u,17],zero,ymm0[u,u,u,18],zero,ymm0[u,u] ; AVX512DQ-FCP-NEXT: vpor %ymm5, %ymm8, %ymm5 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm1[u],zero,ymm1[13,u,u,u],zero,ymm1[14,u,u,u],zero,ymm1[15,u,u,u],zero,ymm1[16,u,u,u],zero,ymm1[17,u,u,u],zero,ymm1[18,u,u,u],zero -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm0[u,13],zero,ymm0[u,u,u,14],zero,ymm0[u,u,u,15],zero,ymm0[u,u,u,16],zero,ymm0[u,u,u,17],zero,ymm0[u,u,u,18],zero,ymm0[u,u,u,19] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm3[u],zero,ymm3[13,u,u,u],zero,ymm3[14,u,u,u],zero,ymm3[15,u,u,u],zero,ymm3[16,u,u,u],zero,ymm3[17,u,u,u],zero,ymm3[18,u,u,u],zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm2[u,13],zero,ymm2[u,u,u,14],zero,ymm2[u,u,u,15],zero,ymm2[u,u,u,16],zero,ymm2[u,u,u,17],zero,ymm2[u,u,u,18],zero,ymm2[u,u,u,19] ; AVX512DQ-FCP-NEXT: vpor %ymm8, %ymm9, %ymm8 ; AVX512DQ-FCP-NEXT: vpternlogq $226, %ymm5, %ymm10, %ymm8 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19,u,21,u,u,20,u,22,u,24,u,u,23,u,25,u] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[21],zero,zero,ymm2[20],zero,ymm2[22],zero,ymm2[24],zero,zero,ymm2[23],zero,ymm2[25],zero,zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19],zero,ymm3[21,u],zero,ymm3[20],zero,ymm3[22],zero,ymm3[24,u],zero,ymm3[23],zero,ymm3[25,u] +; AVX512DQ-FCP-NEXT: vpor %ymm5, %ymm9, %ymm5 ; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,2,3,3] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[21],zero,zero,ymm0[20],zero,ymm0[22],zero,ymm0[24],zero,zero,ymm0[23],zero,ymm0[25],zero,zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm1[19],zero,ymm1[21],zero,zero,ymm1[20],zero,ymm1[22],zero,ymm1[24],zero,zero,ymm1[23],zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19],zero,ymm0[21],zero,ymm0[21,20],zero,ymm0[22],zero,ymm0[24],zero,ymm0[22,23],zero,ymm0[25] +; AVX512DQ-FCP-NEXT: vpor %ymm9, %ymm10, %ymm9 ; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm10 = [18374966859431608575,18374966859431608575,18446463693966278400,18446463693966278400] -; AVX512DQ-FCP-NEXT: vpternlogq $248, %ymm10, %ymm5, %ymm9 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm3[19],zero,ymm3[21],zero,zero,ymm3[20],zero,ymm3[22],zero,ymm3[24],zero,zero,ymm3[23],zero -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,2,3,3] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19],zero,ymm2[21],zero,ymm2[21,20],zero,ymm2[22],zero,ymm2[24],zero,ymm2[22,23],zero,ymm2[25] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,2,3,3] -; AVX512DQ-FCP-NEXT: vpor %ymm5, %ymm11, %ymm5 -; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm9, %ymm5 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm5, %zmm0, %zmm5 +; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm5, %ymm9 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm9, %zmm0, %zmm5 ; AVX512DQ-FCP-NEXT: vshufi64x2 {{.*#+}} zmm5 = zmm8[0,1,2,3],zmm5[4,5,6,7] ; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} ymm8 = [4,0,5,5,5,5,0,6] ; AVX512DQ-FCP-NEXT: vpermd %ymm4, %ymm8, %ymm8 @@ -2738,17 +2710,15 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm4[12],zero,zero,zero,zero,ymm4[13],zero,zero,zero,zero,ymm4[14],zero,zero,zero,zero,ymm4[15],zero,zero,zero,zero,ymm4[16],zero,zero,zero,zero,ymm4[17],zero,zero,zero,zero,ymm4[18],zero ; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm8, %zmm9, %zmm8 ; AVX512DQ-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm8 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25,u,27,u,u,26,u,28,u,30,u,u,29,u,31,u] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,3,3] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[27],zero,zero,ymm2[26],zero,ymm2[28],zero,ymm2[30],zero,zero,ymm2[29],zero,ymm2[31],zero,zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[26],zero,ymm2[28],zero,zero,ymm2[27],zero,ymm2[29],zero,ymm2[31],zero,zero,ymm2[30],zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u],zero,ymm3[26],zero,ymm3[28,u],zero,ymm3[u],zero,ymm3[29],zero,ymm3[31,u],zero,ymm3[30] +; AVX512DQ-FCP-NEXT: vpor %ymm2, %ymm3, %ymm2 ; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] -; AVX512DQ-FCP-NEXT: vpternlogq $248, %ymm10, %ymm3, %ymm2 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u,u,26,u,28,u,u,u,u,29,u,31,u,u,30] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,2,3,3] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm0[26],zero,ymm0[28],zero,zero,ymm0[27],zero,ymm0[29],zero,ymm0[31],zero,zero,ymm0[30],zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[27],zero,zero,ymm0[26],zero,ymm0[28],zero,ymm0[30],zero,zero,ymm0[29],zero,ymm0[31],zero,zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm1[27,u],zero,ymm1[26],zero,ymm1[28],zero,ymm1[30,u],zero,ymm1[29],zero,ymm1[31,u] +; AVX512DQ-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] -; AVX512DQ-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm0 -; AVX512DQ-FCP-NEXT: vpternlogq $184, %ymm2, %ymm6, %ymm0 +; AVX512DQ-FCP-NEXT: vpternlogq $226, %ymm2, %ymm6, %ymm0 ; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} ymm1 = [6,6,6,0,7,7,7,7] ; AVX512DQ-FCP-NEXT: vpermd %ymm4, %ymm1, %ymm1 ; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1 @@ -2792,26 +2762,24 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-NEXT: movabsq $595056260442243600, %rax # imm = 0x842108421084210 ; AVX512BW-NEXT: kmovq %rax, %k1 ; AVX512BW-NEXT: vmovdqu8 %zmm6, %zmm3 {%k1} -; AVX512BW-NEXT: vpshufb {{.*#+}} ymm6 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19],zero,ymm1[21],zero,ymm1[21,20],zero,ymm1[22],zero,ymm1[24],zero,ymm1[22,23],zero,ymm1[25] -; AVX512BW-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,2,3,3] -; AVX512BW-NEXT: vpshufb {{.*#+}} ymm7 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[19],zero,ymm2[21],zero,zero,ymm2[20],zero,ymm2[22],zero,ymm2[24],zero,zero,ymm2[23],zero -; AVX512BW-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] +; AVX512BW-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,ymm1[12,13],zero,zero,zero,zero,ymm1[14],zero,zero,zero,ymm1[14,15],zero,zero,zero,zero,ymm1[16],zero,zero,zero,ymm1[16,17],zero,zero,zero,zero,ymm1[18],zero,zero,zero +; AVX512BW-NEXT: vpshufb {{.*#+}} ymm7 = zero,zero,zero,zero,ymm2[13],zero,zero,zero,zero,ymm2[14],zero,zero,zero,zero,ymm2[15],zero,zero,zero,zero,ymm2[16],zero,zero,zero,zero,ymm2[17],zero,zero,zero,zero,ymm2[18],zero,zero ; AVX512BW-NEXT: vpor %ymm6, %ymm7, %ymm6 -; AVX512BW-NEXT: vpshufb {{.*#+}} ymm7 = zero,zero,ymm1[12,13],zero,zero,zero,zero,ymm1[14],zero,zero,zero,ymm1[14,15],zero,zero,zero,zero,ymm1[16],zero,zero,zero,ymm1[16,17],zero,zero,zero,zero,ymm1[18],zero,zero,zero -; AVX512BW-NEXT: vpshufb {{.*#+}} ymm8 = zero,zero,zero,zero,ymm2[13],zero,zero,zero,zero,ymm2[14],zero,zero,zero,zero,ymm2[15],zero,zero,zero,zero,ymm2[16],zero,zero,zero,zero,ymm2[17],zero,zero,zero,zero,ymm2[18],zero,zero +; AVX512BW-NEXT: vpshufb {{.*#+}} ymm7 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19],zero,ymm1[21],zero,ymm1[21,20],zero,ymm1[22],zero,ymm1[24],zero,ymm1[22,23],zero,ymm1[25] +; AVX512BW-NEXT: vpshufb {{.*#+}} ymm8 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[19],zero,ymm2[21],zero,zero,ymm2[20],zero,ymm2[22],zero,ymm2[24],zero,zero,ymm2[23],zero ; AVX512BW-NEXT: vpor %ymm7, %ymm8, %ymm7 -; AVX512BW-NEXT: vinserti64x4 $1, %ymm6, %zmm7, %zmm6 -; AVX512BW-NEXT: vpshufb {{.*#+}} ymm7 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19],zero,ymm5[21],zero,zero,ymm5[20],zero,ymm5[22],zero,ymm5[24],zero,zero,ymm5[23],zero,ymm5[25],zero ; AVX512BW-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] -; AVX512BW-NEXT: vpshufb {{.*#+}} ymm8 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm4[21],zero,zero,ymm4[20],zero,ymm4[22],zero,ymm4[24],zero,zero,ymm4[23],zero,ymm4[25],zero,zero -; AVX512BW-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] -; AVX512BW-NEXT: vpor %ymm7, %ymm8, %ymm7 -; AVX512BW-NEXT: vpmovsxbd {{.*#+}} ymm8 = [3,3,3,0,4,4,4,4] -; AVX512BW-NEXT: vpermd %ymm4, %ymm8, %ymm8 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm7, %zmm6, %zmm6 +; AVX512BW-NEXT: vpmovsxbd {{.*#+}} ymm7 = [3,3,3,0,4,4,4,4] +; AVX512BW-NEXT: vpermd %ymm4, %ymm7, %ymm7 ; AVX512BW-NEXT: movl $138547332, %eax # imm = 0x8421084 ; AVX512BW-NEXT: kmovd %eax, %k1 -; AVX512BW-NEXT: vpshufb {{.*#+}} ymm8 {%k1} = ymm5[u,u,13,u,u,u,u,14,u,u,u,u,15,u,u,u,u,16,u,u,u,u,17,u,u,u,u,18,u,u,u,u] -; AVX512BW-NEXT: vinserti64x4 $1, %ymm7, %zmm8, %zmm7 +; AVX512BW-NEXT: vpshufb {{.*#+}} ymm7 {%k1} = ymm5[u,u,13,u,u,u,u,14,u,u,u,u,15,u,u,u,u,16,u,u,u,u,17,u,u,u,u,18,u,u,u,u] +; AVX512BW-NEXT: vpshufb {{.*#+}} ymm8 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19],zero,ymm5[21],zero,zero,ymm5[20],zero,ymm5[22],zero,ymm5[24],zero,zero,ymm5[23],zero,ymm5[25],zero +; AVX512BW-NEXT: vpshufb {{.*#+}} ymm9 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm4[21],zero,zero,ymm4[20],zero,ymm4[22],zero,ymm4[24],zero,zero,ymm4[23],zero,ymm4[25],zero,zero +; AVX512BW-NEXT: vpor %ymm8, %ymm9, %ymm8 +; AVX512BW-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] +; AVX512BW-NEXT: vinserti64x4 $1, %ymm8, %zmm7, %zmm7 ; AVX512BW-NEXT: movabsq $-8330787646191410408, %rax # imm = 0x8C6318C6318C6318 ; AVX512BW-NEXT: kmovq %rax, %k1 ; AVX512BW-NEXT: vmovdqu8 %zmm6, %zmm7 {%k1} @@ -2854,11 +2822,11 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-FCP-LABEL: store_i8_stride5_vf32: ; AVX512BW-FCP: # %bb.0: ; AVX512BW-FCP-NEXT: vmovdqa (%rdi), %ymm1 -; AVX512BW-FCP-NEXT: vmovdqa (%rsi), %ymm4 +; AVX512BW-FCP-NEXT: vmovdqa (%rsi), %ymm3 ; AVX512BW-FCP-NEXT: vmovdqa (%rdx), %ymm0 ; AVX512BW-FCP-NEXT: vmovdqa (%rcx), %ymm2 -; AVX512BW-FCP-NEXT: vmovdqa (%rdi), %xmm3 -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} xmm5 = xmm3[8],zero,xmm3[u,7],zero,xmm3[9],zero,xmm3[u],zero,xmm3[u,10],zero,xmm3[12],zero,xmm3[u,11] +; AVX512BW-FCP-NEXT: vmovdqa (%rdi), %xmm4 +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} xmm5 = xmm4[8],zero,xmm4[u,7],zero,xmm4[9],zero,xmm4[u],zero,xmm4[u,10],zero,xmm4[12],zero,xmm4[u,11] ; AVX512BW-FCP-NEXT: vmovdqa (%rsi), %xmm6 ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} xmm7 = zero,xmm6[8,u],zero,xmm6[7],zero,xmm6[9,u,11,u],zero,xmm6[10],zero,xmm6[12,u],zero ; AVX512BW-FCP-NEXT: vpor %xmm5, %xmm7, %xmm5 @@ -2871,39 +2839,37 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} xmm8 = zero,xmm8[6],zero,xmm8[8,u],zero,xmm8[7],zero,xmm8[9],zero,xmm8[11,u],zero,xmm8[10],zero,xmm8[12] ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} xmm7 = xmm7[6],zero,xmm7[8],zero,xmm7[u,7],zero,xmm7[9],zero,xmm7[11],zero,xmm7[u,10],zero,xmm7[12],zero ; AVX512BW-FCP-NEXT: vpor %xmm7, %xmm8, %xmm7 -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm3 = xmm3[0],xmm6[0],xmm3[1],xmm6[1],xmm3[2],xmm6[2],xmm3[3],xmm6[3],xmm3[4],xmm6[4],xmm3[5],xmm6[5],xmm3[6],xmm6[6],xmm3[7],xmm6[7] -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} xmm3 = xmm3[0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] -; AVX512BW-FCP-NEXT: vinserti32x4 $2, %xmm7, %zmm3, %zmm3 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm3 = zmm3[0,0,1,1,4,4,5,5] +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm4 = xmm4[0],xmm6[0],xmm4[1],xmm6[1],xmm4[2],xmm6[2],xmm4[3],xmm6[3],xmm4[4],xmm6[4],xmm4[5],xmm6[5],xmm4[6],xmm6[6],xmm4[7],xmm6[7] +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} xmm4 = xmm4[0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] +; AVX512BW-FCP-NEXT: vinserti32x4 $2, %xmm7, %zmm4, %zmm4 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm4 = zmm4[0,0,1,1,4,4,5,5] ; AVX512BW-FCP-NEXT: movabsq $3570337559743967628, %rax # imm = 0x318C631818C6318C ; AVX512BW-FCP-NEXT: kmovq %rax, %k1 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm5, %zmm3 {%k1} +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm5, %zmm4 {%k1} ; AVX512BW-FCP-NEXT: vbroadcasti64x4 {{.*#+}} zmm5 = mem[0,1,2,3,0,1,2,3] ; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm6 = [0,0,0,0,0,0,1,1,9,9,10,10,10,10,10,10] ; AVX512BW-FCP-NEXT: vpermd %zmm5, %zmm6, %zmm6 ; AVX512BW-FCP-NEXT: movabsq $595056260442243600, %rax # imm = 0x842108421084210 ; AVX512BW-FCP-NEXT: kmovq %rax, %k1 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm6, %zmm3 {%k1} -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm6 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19],zero,ymm0[21],zero,ymm0[21,20],zero,ymm0[22],zero,ymm0[24],zero,ymm0[22,23],zero,ymm0[25] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,2,3,3] -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[19],zero,ymm2[21],zero,zero,ymm2[20],zero,ymm2[22],zero,ymm2[24],zero,zero,ymm2[23],zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm6, %zmm4 {%k1} +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,ymm0[12,13],zero,zero,zero,zero,ymm0[14],zero,zero,zero,ymm0[14,15],zero,zero,zero,zero,ymm0[16],zero,zero,zero,ymm0[16,17],zero,zero,zero,zero,ymm0[18],zero,zero,zero +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm7 = zero,zero,zero,zero,ymm2[13],zero,zero,zero,zero,ymm2[14],zero,zero,zero,zero,ymm2[15],zero,zero,zero,zero,ymm2[16],zero,zero,zero,zero,ymm2[17],zero,zero,zero,zero,ymm2[18],zero,zero ; AVX512BW-FCP-NEXT: vpor %ymm6, %ymm7, %ymm6 -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm7 = zero,zero,ymm0[12,13],zero,zero,zero,zero,ymm0[14],zero,zero,zero,ymm0[14,15],zero,zero,zero,zero,ymm0[16],zero,zero,zero,ymm0[16,17],zero,zero,zero,zero,ymm0[18],zero,zero,zero -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm8 = zero,zero,zero,zero,ymm2[13],zero,zero,zero,zero,ymm2[14],zero,zero,zero,zero,ymm2[15],zero,zero,zero,zero,ymm2[16],zero,zero,zero,zero,ymm2[17],zero,zero,zero,zero,ymm2[18],zero,zero +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19],zero,ymm0[21],zero,ymm0[21,20],zero,ymm0[22],zero,ymm0[24],zero,ymm0[22,23],zero,ymm0[25] +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[19],zero,ymm2[21],zero,zero,ymm2[20],zero,ymm2[22],zero,ymm2[24],zero,zero,ymm2[23],zero ; AVX512BW-FCP-NEXT: vpor %ymm7, %ymm8, %ymm7 -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm6, %zmm7, %zmm6 -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19],zero,ymm4[21],zero,zero,ymm4[20],zero,ymm4[22],zero,ymm4[24],zero,zero,ymm4[23],zero,ymm4[25],zero ; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[21],zero,zero,ymm1[20],zero,ymm1[22],zero,ymm1[24],zero,zero,ymm1[23],zero,ymm1[25],zero,zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] -; AVX512BW-FCP-NEXT: vpor %ymm7, %ymm8, %ymm7 -; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} ymm8 = [3,3,3,0,4,4,4,4] -; AVX512BW-FCP-NEXT: vpermd %ymm1, %ymm8, %ymm8 +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm6, %zmm6 +; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} ymm7 = [3,3,3,0,4,4,4,4] +; AVX512BW-FCP-NEXT: vpermd %ymm1, %ymm7, %ymm7 ; AVX512BW-FCP-NEXT: movl $138547332, %eax # imm = 0x8421084 ; AVX512BW-FCP-NEXT: kmovd %eax, %k1 -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm8 {%k1} = ymm4[u,u,13,u,u,u,u,14,u,u,u,u,15,u,u,u,u,16,u,u,u,u,17,u,u,u,u,18,u,u,u,u] -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm8, %zmm7 +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm7 {%k1} = ymm3[u,u,13,u,u,u,u,14,u,u,u,u,15,u,u,u,u,16,u,u,u,u,17,u,u,u,u,18,u,u,u,u] +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19],zero,ymm3[21],zero,zero,ymm3[20],zero,ymm3[22],zero,ymm3[24],zero,zero,ymm3[23],zero,ymm3[25],zero +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[21],zero,zero,ymm1[20],zero,ymm1[22],zero,ymm1[24],zero,zero,ymm1[23],zero,ymm1[25],zero,zero +; AVX512BW-FCP-NEXT: vpor %ymm8, %ymm9, %ymm8 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm8, %zmm7, %zmm7 ; AVX512BW-FCP-NEXT: movabsq $-8330787646191410408, %rax # imm = 0x8C6318C6318C6318 ; AVX512BW-FCP-NEXT: kmovq %rax, %k1 ; AVX512BW-FCP-NEXT: vmovdqu8 %zmm6, %zmm7 {%k1} @@ -2912,16 +2878,14 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-FCP-NEXT: movabsq $1190112520884487201, %rax # imm = 0x1084210842108421 ; AVX512BW-FCP-NEXT: kmovq %rax, %k1 ; AVX512BW-FCP-NEXT: vmovdqu8 %zmm6, %zmm7 {%k1} -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,ymm4[26],zero,ymm4[28],zero,zero,zero,zero,ymm4[29],zero,ymm4[31],zero,zero,ymm4[30] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,2,3,3] +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,ymm3[26],zero,ymm3[28],zero,zero,zero,zero,ymm3[29],zero,ymm3[31],zero,zero,ymm3[30] ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm1[26],zero,ymm1[28],zero,zero,ymm1[27],zero,ymm1[29],zero,ymm1[31],zero,zero,ymm1[30],zero +; AVX512BW-FCP-NEXT: vpor %ymm3, %ymm1, %ymm1 ; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,2,3,3] -; AVX512BW-FCP-NEXT: vpor %ymm4, %ymm1, %ymm1 ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm2[27],zero,zero,ymm2[26],zero,ymm2[28],zero,ymm2[30],zero,zero,ymm2[29],zero,ymm2[31],zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[27],zero,zero,ymm0[26],zero,ymm0[28],zero,ymm0[30],zero,zero,ymm0[29],zero,ymm0[31],zero,zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] ; AVX512BW-FCP-NEXT: vpor %ymm2, %ymm0, %ymm0 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] ; AVX512BW-FCP-NEXT: movl $415641996, %eax # imm = 0x18C6318C ; AVX512BW-FCP-NEXT: kmovd %eax, %k1 ; AVX512BW-FCP-NEXT: vmovdqu8 %ymm1, %ymm0 {%k1} @@ -2932,7 +2896,7 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-FCP-NEXT: vmovdqu8 %ymm1, %ymm0 {%k1} ; AVX512BW-FCP-NEXT: vmovdqa %ymm0, 128(%r9) ; AVX512BW-FCP-NEXT: vmovdqa64 %zmm7, 64(%r9) -; AVX512BW-FCP-NEXT: vmovdqa64 %zmm3, (%r9) +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm4, (%r9) ; AVX512BW-FCP-NEXT: vzeroupper ; AVX512BW-FCP-NEXT: retq ; @@ -2970,26 +2934,24 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-NEXT: movabsq $595056260442243600, %rax # imm = 0x842108421084210 ; AVX512DQ-BW-NEXT: kmovq %rax, %k1 ; AVX512DQ-BW-NEXT: vmovdqu8 %zmm6, %zmm3 {%k1} -; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm6 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19],zero,ymm1[21],zero,ymm1[21,20],zero,ymm1[22],zero,ymm1[24],zero,ymm1[22,23],zero,ymm1[25] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,2,3,3] -; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm7 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[19],zero,ymm2[21],zero,zero,ymm2[20],zero,ymm2[22],zero,ymm2[24],zero,zero,ymm2[23],zero -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] +; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,ymm1[12,13],zero,zero,zero,zero,ymm1[14],zero,zero,zero,ymm1[14,15],zero,zero,zero,zero,ymm1[16],zero,zero,zero,ymm1[16,17],zero,zero,zero,zero,ymm1[18],zero,zero,zero +; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm7 = zero,zero,zero,zero,ymm2[13],zero,zero,zero,zero,ymm2[14],zero,zero,zero,zero,ymm2[15],zero,zero,zero,zero,ymm2[16],zero,zero,zero,zero,ymm2[17],zero,zero,zero,zero,ymm2[18],zero,zero ; AVX512DQ-BW-NEXT: vpor %ymm6, %ymm7, %ymm6 -; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm7 = zero,zero,ymm1[12,13],zero,zero,zero,zero,ymm1[14],zero,zero,zero,ymm1[14,15],zero,zero,zero,zero,ymm1[16],zero,zero,zero,ymm1[16,17],zero,zero,zero,zero,ymm1[18],zero,zero,zero -; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm8 = zero,zero,zero,zero,ymm2[13],zero,zero,zero,zero,ymm2[14],zero,zero,zero,zero,ymm2[15],zero,zero,zero,zero,ymm2[16],zero,zero,zero,zero,ymm2[17],zero,zero,zero,zero,ymm2[18],zero,zero +; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm7 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19],zero,ymm1[21],zero,ymm1[21,20],zero,ymm1[22],zero,ymm1[24],zero,ymm1[22,23],zero,ymm1[25] +; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm8 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[19],zero,ymm2[21],zero,zero,ymm2[20],zero,ymm2[22],zero,ymm2[24],zero,zero,ymm2[23],zero ; AVX512DQ-BW-NEXT: vpor %ymm7, %ymm8, %ymm7 -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm6, %zmm7, %zmm6 -; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm7 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19],zero,ymm5[21],zero,zero,ymm5[20],zero,ymm5[22],zero,ymm5[24],zero,zero,ymm5[23],zero,ymm5[25],zero ; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] -; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm8 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm4[21],zero,zero,ymm4[20],zero,ymm4[22],zero,ymm4[24],zero,zero,ymm4[23],zero,ymm4[25],zero,zero -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] -; AVX512DQ-BW-NEXT: vpor %ymm7, %ymm8, %ymm7 -; AVX512DQ-BW-NEXT: vpmovsxbd {{.*#+}} ymm8 = [3,3,3,0,4,4,4,4] -; AVX512DQ-BW-NEXT: vpermd %ymm4, %ymm8, %ymm8 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm7, %zmm6, %zmm6 +; AVX512DQ-BW-NEXT: vpmovsxbd {{.*#+}} ymm7 = [3,3,3,0,4,4,4,4] +; AVX512DQ-BW-NEXT: vpermd %ymm4, %ymm7, %ymm7 ; AVX512DQ-BW-NEXT: movl $138547332, %eax # imm = 0x8421084 ; AVX512DQ-BW-NEXT: kmovd %eax, %k1 -; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm8 {%k1} = ymm5[u,u,13,u,u,u,u,14,u,u,u,u,15,u,u,u,u,16,u,u,u,u,17,u,u,u,u,18,u,u,u,u] -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm7, %zmm8, %zmm7 +; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm7 {%k1} = ymm5[u,u,13,u,u,u,u,14,u,u,u,u,15,u,u,u,u,16,u,u,u,u,17,u,u,u,u,18,u,u,u,u] +; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm8 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19],zero,ymm5[21],zero,zero,ymm5[20],zero,ymm5[22],zero,ymm5[24],zero,zero,ymm5[23],zero,ymm5[25],zero +; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm9 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm4[21],zero,zero,ymm4[20],zero,ymm4[22],zero,ymm4[24],zero,zero,ymm4[23],zero,ymm4[25],zero,zero +; AVX512DQ-BW-NEXT: vpor %ymm8, %ymm9, %ymm8 +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm8, %zmm7, %zmm7 ; AVX512DQ-BW-NEXT: movabsq $-8330787646191410408, %rax # imm = 0x8C6318C6318C6318 ; AVX512DQ-BW-NEXT: kmovq %rax, %k1 ; AVX512DQ-BW-NEXT: vmovdqu8 %zmm6, %zmm7 {%k1} @@ -3032,11 +2994,11 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-FCP-LABEL: store_i8_stride5_vf32: ; AVX512DQ-BW-FCP: # %bb.0: ; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdi), %ymm1 -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rsi), %ymm4 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rsi), %ymm3 ; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdx), %ymm0 ; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rcx), %ymm2 -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdi), %xmm3 -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} xmm5 = xmm3[8],zero,xmm3[u,7],zero,xmm3[9],zero,xmm3[u],zero,xmm3[u,10],zero,xmm3[12],zero,xmm3[u,11] +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdi), %xmm4 +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} xmm5 = xmm4[8],zero,xmm4[u,7],zero,xmm4[9],zero,xmm4[u],zero,xmm4[u,10],zero,xmm4[12],zero,xmm4[u,11] ; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rsi), %xmm6 ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} xmm7 = zero,xmm6[8,u],zero,xmm6[7],zero,xmm6[9,u,11,u],zero,xmm6[10],zero,xmm6[12,u],zero ; AVX512DQ-BW-FCP-NEXT: vpor %xmm5, %xmm7, %xmm5 @@ -3049,39 +3011,37 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} xmm8 = zero,xmm8[6],zero,xmm8[8,u],zero,xmm8[7],zero,xmm8[9],zero,xmm8[11,u],zero,xmm8[10],zero,xmm8[12] ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} xmm7 = xmm7[6],zero,xmm7[8],zero,xmm7[u,7],zero,xmm7[9],zero,xmm7[11],zero,xmm7[u,10],zero,xmm7[12],zero ; AVX512DQ-BW-FCP-NEXT: vpor %xmm7, %xmm8, %xmm7 -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm3 = xmm3[0],xmm6[0],xmm3[1],xmm6[1],xmm3[2],xmm6[2],xmm3[3],xmm6[3],xmm3[4],xmm6[4],xmm3[5],xmm6[5],xmm3[6],xmm6[6],xmm3[7],xmm6[7] -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} xmm3 = xmm3[0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] -; AVX512DQ-BW-FCP-NEXT: vinserti32x4 $2, %xmm7, %zmm3, %zmm3 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm3 = zmm3[0,0,1,1,4,4,5,5] +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm4 = xmm4[0],xmm6[0],xmm4[1],xmm6[1],xmm4[2],xmm6[2],xmm4[3],xmm6[3],xmm4[4],xmm6[4],xmm4[5],xmm6[5],xmm4[6],xmm6[6],xmm4[7],xmm6[7] +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} xmm4 = xmm4[0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] +; AVX512DQ-BW-FCP-NEXT: vinserti32x4 $2, %xmm7, %zmm4, %zmm4 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm4 = zmm4[0,0,1,1,4,4,5,5] ; AVX512DQ-BW-FCP-NEXT: movabsq $3570337559743967628, %rax # imm = 0x318C631818C6318C ; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k1 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm5, %zmm3 {%k1} +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm5, %zmm4 {%k1} ; AVX512DQ-BW-FCP-NEXT: vbroadcasti64x4 {{.*#+}} zmm5 = mem[0,1,2,3,0,1,2,3] ; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm6 = [0,0,0,0,0,0,1,1,9,9,10,10,10,10,10,10] ; AVX512DQ-BW-FCP-NEXT: vpermd %zmm5, %zmm6, %zmm6 ; AVX512DQ-BW-FCP-NEXT: movabsq $595056260442243600, %rax # imm = 0x842108421084210 ; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k1 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm6, %zmm3 {%k1} -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm6 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19],zero,ymm0[21],zero,ymm0[21,20],zero,ymm0[22],zero,ymm0[24],zero,ymm0[22,23],zero,ymm0[25] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,2,3,3] -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[19],zero,ymm2[21],zero,zero,ymm2[20],zero,ymm2[22],zero,ymm2[24],zero,zero,ymm2[23],zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm6, %zmm4 {%k1} +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,ymm0[12,13],zero,zero,zero,zero,ymm0[14],zero,zero,zero,ymm0[14,15],zero,zero,zero,zero,ymm0[16],zero,zero,zero,ymm0[16,17],zero,zero,zero,zero,ymm0[18],zero,zero,zero +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm7 = zero,zero,zero,zero,ymm2[13],zero,zero,zero,zero,ymm2[14],zero,zero,zero,zero,ymm2[15],zero,zero,zero,zero,ymm2[16],zero,zero,zero,zero,ymm2[17],zero,zero,zero,zero,ymm2[18],zero,zero ; AVX512DQ-BW-FCP-NEXT: vpor %ymm6, %ymm7, %ymm6 -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm7 = zero,zero,ymm0[12,13],zero,zero,zero,zero,ymm0[14],zero,zero,zero,ymm0[14,15],zero,zero,zero,zero,ymm0[16],zero,zero,zero,ymm0[16,17],zero,zero,zero,zero,ymm0[18],zero,zero,zero -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm8 = zero,zero,zero,zero,ymm2[13],zero,zero,zero,zero,ymm2[14],zero,zero,zero,zero,ymm2[15],zero,zero,zero,zero,ymm2[16],zero,zero,zero,zero,ymm2[17],zero,zero,zero,zero,ymm2[18],zero,zero +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19],zero,ymm0[21],zero,ymm0[21,20],zero,ymm0[22],zero,ymm0[24],zero,ymm0[22,23],zero,ymm0[25] +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[19],zero,ymm2[21],zero,zero,ymm2[20],zero,ymm2[22],zero,ymm2[24],zero,zero,ymm2[23],zero ; AVX512DQ-BW-FCP-NEXT: vpor %ymm7, %ymm8, %ymm7 -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm6, %zmm7, %zmm6 -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19],zero,ymm4[21],zero,zero,ymm4[20],zero,ymm4[22],zero,ymm4[24],zero,zero,ymm4[23],zero,ymm4[25],zero ; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[21],zero,zero,ymm1[20],zero,ymm1[22],zero,ymm1[24],zero,zero,ymm1[23],zero,ymm1[25],zero,zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] -; AVX512DQ-BW-FCP-NEXT: vpor %ymm7, %ymm8, %ymm7 -; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} ymm8 = [3,3,3,0,4,4,4,4] -; AVX512DQ-BW-FCP-NEXT: vpermd %ymm1, %ymm8, %ymm8 +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm6, %zmm6 +; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} ymm7 = [3,3,3,0,4,4,4,4] +; AVX512DQ-BW-FCP-NEXT: vpermd %ymm1, %ymm7, %ymm7 ; AVX512DQ-BW-FCP-NEXT: movl $138547332, %eax # imm = 0x8421084 ; AVX512DQ-BW-FCP-NEXT: kmovd %eax, %k1 -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm8 {%k1} = ymm4[u,u,13,u,u,u,u,14,u,u,u,u,15,u,u,u,u,16,u,u,u,u,17,u,u,u,u,18,u,u,u,u] -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm8, %zmm7 +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm7 {%k1} = ymm3[u,u,13,u,u,u,u,14,u,u,u,u,15,u,u,u,u,16,u,u,u,u,17,u,u,u,u,18,u,u,u,u] +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19],zero,ymm3[21],zero,zero,ymm3[20],zero,ymm3[22],zero,ymm3[24],zero,zero,ymm3[23],zero,ymm3[25],zero +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[21],zero,zero,ymm1[20],zero,ymm1[22],zero,ymm1[24],zero,zero,ymm1[23],zero,ymm1[25],zero,zero +; AVX512DQ-BW-FCP-NEXT: vpor %ymm8, %ymm9, %ymm8 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm8, %zmm7, %zmm7 ; AVX512DQ-BW-FCP-NEXT: movabsq $-8330787646191410408, %rax # imm = 0x8C6318C6318C6318 ; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k1 ; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm6, %zmm7 {%k1} @@ -3090,16 +3050,14 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-FCP-NEXT: movabsq $1190112520884487201, %rax # imm = 0x1084210842108421 ; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k1 ; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm6, %zmm7 {%k1} -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,ymm4[26],zero,ymm4[28],zero,zero,zero,zero,ymm4[29],zero,ymm4[31],zero,zero,ymm4[30] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,2,3,3] +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,ymm3[26],zero,ymm3[28],zero,zero,zero,zero,ymm3[29],zero,ymm3[31],zero,zero,ymm3[30] ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm1[26],zero,ymm1[28],zero,zero,ymm1[27],zero,ymm1[29],zero,ymm1[31],zero,zero,ymm1[30],zero +; AVX512DQ-BW-FCP-NEXT: vpor %ymm3, %ymm1, %ymm1 ; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,2,3,3] -; AVX512DQ-BW-FCP-NEXT: vpor %ymm4, %ymm1, %ymm1 ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm2[27],zero,zero,ymm2[26],zero,ymm2[28],zero,ymm2[30],zero,zero,ymm2[29],zero,ymm2[31],zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[27],zero,zero,ymm0[26],zero,ymm0[28],zero,ymm0[30],zero,zero,ymm0[29],zero,ymm0[31],zero,zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] ; AVX512DQ-BW-FCP-NEXT: vpor %ymm2, %ymm0, %ymm0 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] ; AVX512DQ-BW-FCP-NEXT: movl $415641996, %eax # imm = 0x18C6318C ; AVX512DQ-BW-FCP-NEXT: kmovd %eax, %k1 ; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %ymm1, %ymm0 {%k1} @@ -3110,7 +3068,7 @@ define void @store_i8_stride5_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %ymm1, %ymm0 {%k1} ; AVX512DQ-BW-FCP-NEXT: vmovdqa %ymm0, 128(%r9) ; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm7, 64(%r9) -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm3, (%r9) +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm4, (%r9) ; AVX512DQ-BW-FCP-NEXT: vzeroupper ; AVX512DQ-BW-FCP-NEXT: retq %in.vec0 = load <32 x i8>, ptr %in.vecptr0, align 64 @@ -4148,209 +4106,200 @@ define void @store_i8_stride5_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; ; AVX2-LABEL: store_i8_stride5_vf64: ; AVX2: # %bb.0: -; AVX2-NEXT: subq $312, %rsp # imm = 0x138 -; AVX2-NEXT: vmovdqa 32(%rdi), %ymm10 +; AVX2-NEXT: subq $248, %rsp +; AVX2-NEXT: vmovdqa 32(%rdi), %ymm4 ; AVX2-NEXT: vmovdqa (%rcx), %xmm1 ; AVX2-NEXT: vmovdqa %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX2-NEXT: vmovdqa 32(%rcx), %xmm11 -; AVX2-NEXT: vmovdqa %xmm11, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX2-NEXT: vmovdqa 32(%rcx), %xmm7 +; AVX2-NEXT: vmovdqa %xmm7, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill ; AVX2-NEXT: vmovdqa {{.*#+}} xmm0 = [128,6,128,8,u,128,7,128,9,128,11,u,128,10,128,12] ; AVX2-NEXT: vpshufb %xmm0, %xmm1, %xmm1 ; AVX2-NEXT: vmovdqa (%rdx), %xmm3 ; AVX2-NEXT: vmovdqa %xmm3, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX2-NEXT: vmovdqa 32(%rdx), %xmm12 -; AVX2-NEXT: vmovdqa %xmm12, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX2-NEXT: vmovdqa 32(%rdx), %xmm10 +; AVX2-NEXT: vmovdqa %xmm10, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill ; AVX2-NEXT: vmovdqa {{.*#+}} xmm2 = [6,128,8,128,u,7,128,9,128,11,128,u,10,128,12,128] ; AVX2-NEXT: vpshufb %xmm2, %xmm3, %xmm3 ; AVX2-NEXT: vpor %xmm1, %xmm3, %xmm1 ; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,0,1,1] -; AVX2-NEXT: vmovdqa (%rdi), %xmm4 -; AVX2-NEXT: vmovdqa %xmm4, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX2-NEXT: vmovdqa (%rdi), %xmm5 +; AVX2-NEXT: vmovdqa %xmm5, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill ; AVX2-NEXT: vmovdqa {{.*#+}} xmm3 = [8,128,u,7,128,9,128,u,128,u,10,128,12,128,u,11] -; AVX2-NEXT: vpshufb %xmm3, %xmm4, %xmm4 -; AVX2-NEXT: vmovdqa (%rsi), %xmm14 -; AVX2-NEXT: vmovdqa {{.*#+}} xmm5 = [128,8,u,128,7,128,9,u,11,u,128,10,128,12,u,128] -; AVX2-NEXT: vpshufb %xmm5, %xmm14, %xmm8 -; AVX2-NEXT: vpor %xmm4, %xmm8, %xmm4 -; AVX2-NEXT: vpermq {{.*#+}} ymm4 = ymm4[0,0,1,1] -; AVX2-NEXT: vmovdqa {{.*#+}} ymm8 = [255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255] -; AVX2-NEXT: vpblendvb %ymm8, %ymm1, %ymm4, %ymm1 -; AVX2-NEXT: vmovdqa (%r8), %xmm4 -; AVX2-NEXT: vmovdqa %xmm4, (%rsp) # 16-byte Spill -; AVX2-NEXT: vpshufd {{.*#+}} xmm4 = xmm4[1,1,2,2] -; AVX2-NEXT: vpermq {{.*#+}} ymm4 = ymm4[0,1,1,1] -; AVX2-NEXT: vmovdqa {{.*#+}} ymm9 = [255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255] -; AVX2-NEXT: vpblendvb %ymm9, %ymm1, %ymm4, %ymm1 +; AVX2-NEXT: vpshufb %xmm3, %xmm5, %xmm5 +; AVX2-NEXT: vmovdqa (%rsi), %xmm6 +; AVX2-NEXT: vmovdqa {{.*#+}} xmm8 = [128,8,u,128,7,128,9,u,11,u,128,10,128,12,u,128] +; AVX2-NEXT: vpshufb %xmm8, %xmm6, %xmm9 +; AVX2-NEXT: vpor %xmm5, %xmm9, %xmm5 +; AVX2-NEXT: vpermq {{.*#+}} ymm5 = ymm5[0,0,1,1] +; AVX2-NEXT: vmovdqa {{.*#+}} ymm9 = [255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255] +; AVX2-NEXT: vpblendvb %ymm9, %ymm1, %ymm5, %ymm1 +; AVX2-NEXT: vmovdqa (%r8), %xmm5 +; AVX2-NEXT: vmovdqa %xmm5, (%rsp) # 16-byte Spill +; AVX2-NEXT: vpshufd {{.*#+}} xmm5 = xmm5[1,1,2,2] +; AVX2-NEXT: vpermq {{.*#+}} ymm5 = ymm5[0,1,1,1] +; AVX2-NEXT: vmovdqa {{.*#+}} ymm12 = [255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255] +; AVX2-NEXT: vpblendvb %ymm12, %ymm1, %ymm5, %ymm1 ; AVX2-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-NEXT: vmovdqa 32(%rdi), %xmm4 -; AVX2-NEXT: vmovdqa %xmm4, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX2-NEXT: vpshufb %xmm0, %xmm11, %xmm0 -; AVX2-NEXT: vpshufb %xmm2, %xmm12, %xmm1 +; AVX2-NEXT: vmovdqa 32(%rdi), %xmm5 +; AVX2-NEXT: vmovdqa %xmm5, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX2-NEXT: vpshufb %xmm0, %xmm7, %xmm0 +; AVX2-NEXT: vpshufb %xmm2, %xmm10, %xmm1 ; AVX2-NEXT: vpor %xmm0, %xmm1, %xmm0 ; AVX2-NEXT: vmovdqa 32(%rsi), %xmm2 ; AVX2-NEXT: vmovdqa %xmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX2-NEXT: vpshufb %xmm3, %xmm4, %xmm1 -; AVX2-NEXT: vpshufb %xmm5, %xmm2, %xmm2 +; AVX2-NEXT: vpshufb %xmm3, %xmm5, %xmm1 +; AVX2-NEXT: vpshufb %xmm8, %xmm2, %xmm2 ; AVX2-NEXT: vpor %xmm1, %xmm2, %xmm1 -; AVX2-NEXT: vmovdqa 32(%rsi), %ymm2 +; AVX2-NEXT: vmovdqa 32(%rsi), %ymm11 ; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,0,1,1] ; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,0,1,1] -; AVX2-NEXT: vpblendvb %ymm8, %ymm0, %ymm1, %ymm0 +; AVX2-NEXT: vpblendvb %ymm9, %ymm0, %ymm1, %ymm0 ; AVX2-NEXT: vmovdqa 32(%r8), %xmm1 ; AVX2-NEXT: vmovdqa %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill ; AVX2-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[1,1,2,2] ; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,1,1,1] -; AVX2-NEXT: vpblendvb %ymm9, %ymm0, %ymm1, %ymm0 +; AVX2-NEXT: vpblendvb %ymm12, %ymm0, %ymm1, %ymm0 ; AVX2-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-NEXT: vmovdqa {{.*#+}} ymm15 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,21,128,19,20,128,22,128,24,128,22,23,128,25,128,23] -; AVX2-NEXT: vpshufb %ymm15, %ymm10, %ymm1 -; AVX2-NEXT: vmovdqa %ymm10, %ymm11 -; AVX2-NEXT: vmovdqu %ymm10, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,2,3,3] -; AVX2-NEXT: vbroadcasti128 {{.*#+}} ymm5 = [19,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128] -; AVX2-NEXT: # ymm5 = mem[0,1,0,1] -; AVX2-NEXT: vpshufb %ymm5, %ymm2, %ymm3 -; AVX2-NEXT: vmovdqu %ymm2, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,3,3] +; AVX2-NEXT: vpshufb %ymm15, %ymm4, %ymm1 +; AVX2-NEXT: vmovdqa %ymm4, %ymm13 +; AVX2-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX2-NEXT: vbroadcasti128 {{.*#+}} ymm4 = [19,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128] +; AVX2-NEXT: # ymm4 = mem[0,1,0,1] +; AVX2-NEXT: vpshufb %ymm4, %ymm11, %ymm3 ; AVX2-NEXT: vpor %ymm1, %ymm3, %ymm1 -; AVX2-NEXT: vmovdqa 32(%rcx), %ymm7 +; AVX2-NEXT: vmovdqa 32(%rdx), %ymm12 +; AVX2-NEXT: vmovdqa 32(%rcx), %ymm14 ; AVX2-NEXT: vbroadcasti128 {{.*#+}} ymm3 = [128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128] ; AVX2-NEXT: # ymm3 = mem[0,1,0,1] -; AVX2-NEXT: vpshufb %ymm3, %ymm7, %ymm4 -; AVX2-NEXT: vpermq {{.*#+}} ymm9 = ymm4[2,2,3,3] -; AVX2-NEXT: vmovdqa 32(%rdx), %ymm13 -; AVX2-NEXT: vmovdqa {{.*#+}} ymm4 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,25] -; AVX2-NEXT: vpshufb %ymm4, %ymm13, %ymm12 -; AVX2-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,2,3,3] -; AVX2-NEXT: vpor %ymm9, %ymm12, %ymm9 -; AVX2-NEXT: vmovdqa {{.*#+}} ymm12 = [255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0] -; AVX2-NEXT: vpblendvb %ymm12, %ymm1, %ymm9, %ymm9 -; AVX2-NEXT: vmovdqa (%rdi), %ymm6 -; AVX2-NEXT: vpshufb %ymm15, %ymm6, %ymm1 -; AVX2-NEXT: vmovdqu %ymm6, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX2-NEXT: vpshufb %ymm3, %ymm14, %ymm8 +; AVX2-NEXT: vmovdqa {{.*#+}} ymm5 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,25] +; AVX2-NEXT: vpshufb %ymm5, %ymm12, %ymm10 +; AVX2-NEXT: vpor %ymm8, %ymm10, %ymm8 ; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,2,3,3] +; AVX2-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] +; AVX2-NEXT: vmovdqa {{.*#+}} ymm10 = [255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0] +; AVX2-NEXT: vpblendvb %ymm10, %ymm1, %ymm8, %ymm2 +; AVX2-NEXT: vmovdqa (%rdi), %ymm9 +; AVX2-NEXT: vpshufb %ymm15, %ymm9, %ymm1 ; AVX2-NEXT: vmovdqa (%rsi), %ymm15 -; AVX2-NEXT: vpshufb %ymm5, %ymm15, %ymm5 -; AVX2-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,2,3,3] -; AVX2-NEXT: vpor %ymm1, %ymm5, %ymm5 -; AVX2-NEXT: vmovdqa (%rcx), %ymm10 -; AVX2-NEXT: vpshufb %ymm3, %ymm10, %ymm3 -; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm3[2,2,3,3] -; AVX2-NEXT: vmovdqa (%rdx), %ymm8 -; AVX2-NEXT: vpshufb %ymm4, %ymm8, %ymm4 +; AVX2-NEXT: vpshufb %ymm4, %ymm15, %ymm4 +; AVX2-NEXT: vpor %ymm1, %ymm4, %ymm4 +; AVX2-NEXT: vmovdqa (%rcx), %ymm7 +; AVX2-NEXT: vpshufb %ymm3, %ymm7, %ymm0 +; AVX2-NEXT: vmovdqa (%rdx), %ymm3 +; AVX2-NEXT: vpshufb %ymm5, %ymm3, %ymm5 +; AVX2-NEXT: vpor %ymm0, %ymm5, %ymm0 ; AVX2-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,2,3,3] -; AVX2-NEXT: vpor %ymm0, %ymm4, %ymm0 -; AVX2-NEXT: vpblendvb %ymm12, %ymm5, %ymm0, %ymm0 -; AVX2-NEXT: vmovdqa 32(%r8), %ymm12 -; AVX2-NEXT: vpshufd {{.*#+}} ymm4 = ymm12[0,2,1,1,4,6,5,5] +; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] +; AVX2-NEXT: vpblendvb %ymm10, %ymm4, %ymm0, %ymm0 +; AVX2-NEXT: vmovdqa 32(%r8), %ymm10 +; AVX2-NEXT: vpshufd {{.*#+}} ymm4 = ymm10[0,2,1,1,4,6,5,5] ; AVX2-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,3,2] ; AVX2-NEXT: vmovdqa {{.*#+}} ymm5 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255] -; AVX2-NEXT: vpblendvb %ymm5, %ymm9, %ymm4, %ymm1 +; AVX2-NEXT: vpblendvb %ymm5, %ymm2, %ymm4, %ymm1 ; AVX2-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-NEXT: vmovdqa (%r8), %ymm9 -; AVX2-NEXT: vpshufd {{.*#+}} ymm4 = ymm9[0,2,1,1,4,6,5,5] +; AVX2-NEXT: vmovdqa (%r8), %ymm8 +; AVX2-NEXT: vpshufd {{.*#+}} ymm4 = ymm8[0,2,1,1,4,6,5,5] ; AVX2-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,3,2] ; AVX2-NEXT: vpblendvb %ymm5, %ymm0, %ymm4, %ymm0 ; AVX2-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-NEXT: vpmovsxbd {{.*#+}} ymm3 = [3,3,3,0,4,4,4,4] -; AVX2-NEXT: vpermd %ymm11, %ymm3, %ymm4 +; AVX2-NEXT: vpmovsxbd {{.*#+}} ymm2 = [3,3,3,0,4,4,4,4] +; AVX2-NEXT: vpermd %ymm13, %ymm2, %ymm4 ; AVX2-NEXT: vpbroadcastq {{.*#+}} ymm5 = [0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14] -; AVX2-NEXT: vpshufb %ymm5, %ymm2, %ymm0 +; AVX2-NEXT: vpshufb %ymm5, %ymm11, %ymm0 ; AVX2-NEXT: vmovdqa {{.*#+}} ymm1 = [u,255,0,u,u,u,255,0,u,u,u,255,0,u,u,u,255,0,u,u,u,255,0,u,u,u,255,0,u,u,u,255] ; AVX2-NEXT: vpblendvb %ymm1, %ymm4, %ymm0, %ymm0 -; AVX2-NEXT: vpermd %ymm6, %ymm3, %ymm2 +; AVX2-NEXT: vpermd %ymm9, %ymm2, %ymm2 ; AVX2-NEXT: vpshufb %ymm5, %ymm15, %ymm4 ; AVX2-NEXT: vpblendvb %ymm1, %ymm2, %ymm4, %ymm1 ; AVX2-NEXT: vmovdqa {{.*#+}} ymm2 = [128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128] -; AVX2-NEXT: vmovdqa %ymm7, %ymm3 -; AVX2-NEXT: vpshufb %ymm2, %ymm7, %ymm4 +; AVX2-NEXT: vpshufb %ymm2, %ymm14, %ymm4 ; AVX2-NEXT: vmovdqa {{.*#+}} ymm5 = [128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128,128] -; AVX2-NEXT: vpshufb %ymm5, %ymm13, %ymm11 -; AVX2-NEXT: vpor %ymm4, %ymm11, %ymm4 -; AVX2-NEXT: vmovdqa {{.*#+}} ymm11 = [u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255] -; AVX2-NEXT: vpblendvb %ymm11, %ymm0, %ymm4, %ymm0 -; AVX2-NEXT: vpshufb %ymm2, %ymm10, %ymm2 -; AVX2-NEXT: vpshufb %ymm5, %ymm8, %ymm4 +; AVX2-NEXT: vpshufb %ymm5, %ymm12, %ymm13 +; AVX2-NEXT: vpor %ymm4, %ymm13, %ymm4 +; AVX2-NEXT: vmovdqa {{.*#+}} ymm13 = [u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255] +; AVX2-NEXT: vpblendvb %ymm13, %ymm0, %ymm4, %ymm0 +; AVX2-NEXT: vpshufb %ymm2, %ymm7, %ymm2 +; AVX2-NEXT: vpshufb %ymm5, %ymm3, %ymm4 ; AVX2-NEXT: vpor %ymm2, %ymm4, %ymm2 -; AVX2-NEXT: vpblendvb %ymm11, %ymm1, %ymm2, %ymm1 +; AVX2-NEXT: vpblendvb %ymm13, %ymm1, %ymm2, %ymm1 ; AVX2-NEXT: vpmovsxbd {{.*#+}} ymm2 = [3,3,3,3,0,4,4,4] -; AVX2-NEXT: vpermd %ymm12, %ymm2, %ymm4 +; AVX2-NEXT: vpermd %ymm10, %ymm2, %ymm4 ; AVX2-NEXT: vmovdqa {{.*#+}} ymm5 = [0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255] ; AVX2-NEXT: vpblendvb %ymm5, %ymm0, %ymm4, %ymm0 ; AVX2-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-NEXT: vpermd %ymm9, %ymm2, %ymm0 +; AVX2-NEXT: vpermd %ymm8, %ymm2, %ymm0 ; AVX2-NEXT: vpblendvb %ymm5, %ymm1, %ymm0, %ymm0 ; AVX2-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload -; AVX2-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0],xmm14[0],xmm0[1],xmm14[1],xmm0[2],xmm14[2],xmm0[3],xmm14[3],xmm0[4],xmm14[4],xmm0[5],xmm14[5],xmm0[6],xmm14[6],xmm0[7],xmm14[7] +; AVX2-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0],xmm6[0],xmm0[1],xmm6[1],xmm0[2],xmm6[2],xmm0[3],xmm6[3],xmm0[4],xmm6[4],xmm0[5],xmm6[5],xmm0[6],xmm6[6],xmm0[7],xmm6[7] ; AVX2-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload ; AVX2-NEXT: vpunpcklbw {{[-0-9]+}}(%r{{[sb]}}p), %xmm1, %xmm1 # 16-byte Folded Reload ; AVX2-NEXT: # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1],xmm1[2],mem[2],xmm1[3],mem[3],xmm1[4],mem[4],xmm1[5],mem[5],xmm1[6],mem[6],xmm1[7],mem[7] -; AVX2-NEXT: vmovdqa {{.*#+}} xmm14 = [0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] -; AVX2-NEXT: vpshufb %xmm14, %xmm0, %xmm0 -; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,0,1,1] -; AVX2-NEXT: vmovdqa {{.*#+}} xmm7 = [2,u,1,0,5,4,u,3,u,7,6,11,10,u,9,8] -; AVX2-NEXT: vpshufb %xmm7, %xmm1, %xmm1 -; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,0,1,1] -; AVX2-NEXT: vmovdqa {{.*#+}} ymm11 = [255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255] -; AVX2-NEXT: vpblendvb %ymm11, %ymm0, %ymm1, %ymm6 -; AVX2-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload -; AVX2-NEXT: vpunpcklbw {{[-0-9]+}}(%r{{[sb]}}p), %xmm0, %xmm0 # 16-byte Folded Reload -; AVX2-NEXT: # xmm0 = xmm0[0],mem[0],xmm0[1],mem[1],xmm0[2],mem[2],xmm0[3],mem[3],xmm0[4],mem[4],xmm0[5],mem[5],xmm0[6],mem[6],xmm0[7],mem[7] -; AVX2-NEXT: vpshufb %xmm14, %xmm0, %xmm0 +; AVX2-NEXT: vmovdqa {{.*#+}} xmm13 = [0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] +; AVX2-NEXT: vpshufb %xmm13, %xmm0, %xmm0 +; AVX2-NEXT: vpermq {{.*#+}} ymm2 = ymm0[0,0,1,1] +; AVX2-NEXT: vmovdqa {{.*#+}} xmm6 = [2,u,1,0,5,4,u,3,u,7,6,11,10,u,9,8] +; AVX2-NEXT: vpshufb %xmm6, %xmm1, %xmm0 +; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm0[0,0,1,1] +; AVX2-NEXT: vmovdqa {{.*#+}} ymm0 = [255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255] +; AVX2-NEXT: vpblendvb %ymm0, %ymm2, %ymm1, %ymm4 ; AVX2-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload ; AVX2-NEXT: vpunpcklbw {{[-0-9]+}}(%r{{[sb]}}p), %xmm1, %xmm1 # 16-byte Folded Reload ; AVX2-NEXT: # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1],xmm1[2],mem[2],xmm1[3],mem[3],xmm1[4],mem[4],xmm1[5],mem[5],xmm1[6],mem[6],xmm1[7],mem[7] -; AVX2-NEXT: vpshufb %xmm7, %xmm1, %xmm1 -; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,0,1,1] +; AVX2-NEXT: vpshufb %xmm13, %xmm1, %xmm1 +; AVX2-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm2 # 16-byte Reload +; AVX2-NEXT: vpunpcklbw {{[-0-9]+}}(%r{{[sb]}}p), %xmm2, %xmm2 # 16-byte Folded Reload +; AVX2-NEXT: # xmm2 = xmm2[0],mem[0],xmm2[1],mem[1],xmm2[2],mem[2],xmm2[3],mem[3],xmm2[4],mem[4],xmm2[5],mem[5],xmm2[6],mem[6],xmm2[7],mem[7] +; AVX2-NEXT: vpshufb %xmm6, %xmm2, %xmm2 ; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,0,1,1] -; AVX2-NEXT: vpblendvb %ymm11, %ymm0, %ymm1, %ymm0 +; AVX2-NEXT: vpermq {{.*#+}} ymm2 = ymm2[0,0,1,1] +; AVX2-NEXT: vpblendvb %ymm0, %ymm1, %ymm2, %ymm0 ; AVX2-NEXT: vpshufd $80, (%rsp), %xmm1 # 16-byte Folded Reload ; AVX2-NEXT: # xmm1 = mem[0,0,1,1] ; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,0,0,1] ; AVX2-NEXT: vmovdqa {{.*#+}} ymm2 = [255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255] -; AVX2-NEXT: vpblendvb %ymm2, %ymm6, %ymm1, %ymm6 +; AVX2-NEXT: vpblendvb %ymm2, %ymm4, %ymm1, %ymm4 ; AVX2-NEXT: vpshufd $80, {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Folded Reload ; AVX2-NEXT: # xmm1 = mem[0,0,1,1] ; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,0,0,1] -; AVX2-NEXT: vpblendvb %ymm2, %ymm0, %ymm1, %ymm7 +; AVX2-NEXT: vpblendvb %ymm2, %ymm0, %ymm1, %ymm6 ; AVX2-NEXT: vpbroadcastq {{.*#+}} ymm0 = [9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12] -; AVX2-NEXT: vpshufb %ymm0, %ymm3, %ymm1 -; AVX2-NEXT: vpshufhw {{.*#+}} ymm2 = ymm13[0,1,2,3,5,6,7,6,8,9,10,11,13,14,15,14] +; AVX2-NEXT: vpshufb %ymm0, %ymm14, %ymm1 +; AVX2-NEXT: vpshufhw {{.*#+}} ymm2 = ymm12[0,1,2,3,5,6,7,6,8,9,10,11,13,14,15,14] ; AVX2-NEXT: vpshufd {{.*#+}} ymm2 = ymm2[2,2,3,3,6,6,7,7] -; AVX2-NEXT: vbroadcasti128 {{.*#+}} ymm4 = [255,0,255,0,0,255,0,255,0,255,0,0,255,0,255,0,255,0,255,0,0,255,0,255,0,255,0,0,255,0,255,0] -; AVX2-NEXT: # ymm4 = mem[0,1,0,1] -; AVX2-NEXT: vpblendvb %ymm4, %ymm1, %ymm2, %ymm1 -; AVX2-NEXT: vpshufb %ymm0, %ymm10, %ymm0 -; AVX2-NEXT: vpshufhw {{.*#+}} ymm2 = ymm8[0,1,2,3,5,6,7,6,8,9,10,11,13,14,15,14] +; AVX2-NEXT: vbroadcasti128 {{.*#+}} ymm5 = [255,0,255,0,0,255,0,255,0,255,0,0,255,0,255,0,255,0,255,0,0,255,0,255,0,255,0,0,255,0,255,0] +; AVX2-NEXT: # ymm5 = mem[0,1,0,1] +; AVX2-NEXT: vpblendvb %ymm5, %ymm1, %ymm2, %ymm1 +; AVX2-NEXT: vpshufb %ymm0, %ymm7, %ymm0 +; AVX2-NEXT: vpshufhw {{.*#+}} ymm2 = ymm3[0,1,2,3,5,6,7,6,8,9,10,11,13,14,15,14] ; AVX2-NEXT: vpshufd {{.*#+}} ymm2 = ymm2[2,2,3,3,6,6,7,7] -; AVX2-NEXT: vpblendvb %ymm4, %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: vpblendvb %ymm5, %ymm0, %ymm2, %ymm0 ; AVX2-NEXT: vpbroadcastq {{.*#+}} ymm2 = [11,0,13,10,15,12,0,14,11,0,13,10,15,12,0,14,11,0,13,10,15,12,0,14,11,0,13,10,15,12,0,14] -; AVX2-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm3 # 32-byte Reload -; AVX2-NEXT: vpshufb %ymm2, %ymm3, %ymm3 -; AVX2-NEXT: vpshufhw $230, {{[-0-9]+}}(%r{{[sb]}}p), %ymm4 # 32-byte Folded Reload -; AVX2-NEXT: # ymm4 = mem[0,1,2,3,6,5,6,7,8,9,10,11,14,13,14,15] -; AVX2-NEXT: vpshufd {{.*#+}} ymm4 = ymm4[2,2,3,3,6,6,7,7] -; AVX2-NEXT: vbroadcasti128 {{.*#+}} ymm5 = [255,0,0,255,0,255,0,0,0,0,255,0,255,0,0,255,255,0,0,255,0,255,0,0,0,0,255,0,255,0,0,255] -; AVX2-NEXT: # ymm5 = mem[0,1,0,1] -; AVX2-NEXT: vpblendvb %ymm5, %ymm3, %ymm4, %ymm3 +; AVX2-NEXT: vpshufb %ymm2, %ymm11, %ymm3 +; AVX2-NEXT: vpshufhw $230, {{[-0-9]+}}(%r{{[sb]}}p), %ymm5 # 32-byte Folded Reload +; AVX2-NEXT: # ymm5 = mem[0,1,2,3,6,5,6,7,8,9,10,11,14,13,14,15] +; AVX2-NEXT: vpshufd {{.*#+}} ymm5 = ymm5[2,2,3,3,6,6,7,7] +; AVX2-NEXT: vbroadcasti128 {{.*#+}} ymm7 = [255,0,0,255,0,255,0,0,0,0,255,0,255,0,0,255,255,0,0,255,0,255,0,0,0,0,255,0,255,0,0,255] +; AVX2-NEXT: # ymm7 = mem[0,1,0,1] +; AVX2-NEXT: vpblendvb %ymm7, %ymm3, %ymm5, %ymm3 ; AVX2-NEXT: vpshufb %ymm2, %ymm15, %ymm2 -; AVX2-NEXT: vpshufhw $230, {{[-0-9]+}}(%r{{[sb]}}p), %ymm4 # 32-byte Folded Reload -; AVX2-NEXT: # ymm4 = mem[0,1,2,3,6,5,6,7,8,9,10,11,14,13,14,15] -; AVX2-NEXT: vpshufd {{.*#+}} ymm4 = ymm4[2,2,3,3,6,6,7,7] -; AVX2-NEXT: vpblendvb %ymm5, %ymm2, %ymm4, %ymm2 +; AVX2-NEXT: vpshufhw {{.*#+}} ymm5 = ymm9[0,1,2,3,6,5,6,7,8,9,10,11,14,13,14,15] +; AVX2-NEXT: vpshufd {{.*#+}} ymm5 = ymm5[2,2,3,3,6,6,7,7] +; AVX2-NEXT: vpblendvb %ymm7, %ymm2, %ymm5, %ymm2 ; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,2,3,3] ; AVX2-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,3,3] -; AVX2-NEXT: vmovdqa {{.*#+}} ymm4 = [255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u] -; AVX2-NEXT: vpblendvb %ymm4, %ymm1, %ymm3, %ymm1 +; AVX2-NEXT: vmovdqa {{.*#+}} ymm5 = [255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u] +; AVX2-NEXT: vpblendvb %ymm5, %ymm1, %ymm3, %ymm1 ; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] ; AVX2-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] -; AVX2-NEXT: vpblendvb %ymm4, %ymm0, %ymm2, %ymm0 -; AVX2-NEXT: vpshufd {{.*#+}} ymm2 = ymm12[2,2,3,3,6,6,7,7] +; AVX2-NEXT: vpblendvb %ymm5, %ymm0, %ymm2, %ymm0 +; AVX2-NEXT: vpshufd {{.*#+}} ymm2 = ymm10[2,2,3,3,6,6,7,7] ; AVX2-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] ; AVX2-NEXT: vmovdqa {{.*#+}} ymm3 = [255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0] ; AVX2-NEXT: vpblendvb %ymm3, %ymm1, %ymm2, %ymm1 -; AVX2-NEXT: vpshufd {{.*#+}} ymm2 = ymm9[2,2,3,3,6,6,7,7] +; AVX2-NEXT: vpshufd {{.*#+}} ymm2 = ymm8[2,2,3,3,6,6,7,7] ; AVX2-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] ; AVX2-NEXT: vpblendvb %ymm3, %ymm0, %ymm2, %ymm0 ; AVX2-NEXT: vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload @@ -4362,21 +4311,21 @@ define void @store_i8_stride5_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-NEXT: vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload ; AVX2-NEXT: vmovaps %ymm2, 256(%r9) ; AVX2-NEXT: vmovdqa %ymm0, 128(%r9) -; AVX2-NEXT: vmovdqa %ymm7, 160(%r9) +; AVX2-NEXT: vmovdqa %ymm6, 160(%r9) ; AVX2-NEXT: vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload ; AVX2-NEXT: vmovaps %ymm0, 192(%r9) ; AVX2-NEXT: vmovdqa %ymm1, 288(%r9) -; AVX2-NEXT: vmovdqa %ymm6, (%r9) +; AVX2-NEXT: vmovdqa %ymm4, (%r9) ; AVX2-NEXT: vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload ; AVX2-NEXT: vmovaps %ymm0, 32(%r9) -; AVX2-NEXT: addq $312, %rsp # imm = 0x138 +; AVX2-NEXT: addq $248, %rsp ; AVX2-NEXT: vzeroupper ; AVX2-NEXT: retq ; ; AVX2-FP-LABEL: store_i8_stride5_vf64: ; AVX2-FP: # %bb.0: ; AVX2-FP-NEXT: subq $200, %rsp -; AVX2-FP-NEXT: vmovdqa 32(%rdx), %ymm11 +; AVX2-FP-NEXT: vmovdqa 32(%rdx), %ymm12 ; AVX2-FP-NEXT: vmovdqa (%rcx), %xmm1 ; AVX2-FP-NEXT: vmovdqa %xmm1, (%rsp) # 16-byte Spill ; AVX2-FP-NEXT: vmovdqa 32(%rcx), %xmm8 @@ -4420,7 +4369,7 @@ define void @store_i8_stride5_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FP-NEXT: vpshufb %xmm3, %xmm4, %xmm1 ; AVX2-FP-NEXT: vpshufb %xmm5, %xmm2, %xmm2 ; AVX2-FP-NEXT: vpor %xmm1, %xmm2, %xmm1 -; AVX2-FP-NEXT: vmovdqa 32(%rcx), %ymm3 +; AVX2-FP-NEXT: vmovdqa 32(%rcx), %ymm2 ; AVX2-FP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,0,1,1] ; AVX2-FP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,0,1,1] ; AVX2-FP-NEXT: vpblendvb %ymm6, %ymm0, %ymm1, %ymm0 @@ -4431,106 +4380,98 @@ define void @store_i8_stride5_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FP-NEXT: vpblendvb %ymm7, %ymm0, %ymm1, %ymm0 ; AVX2-FP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm0 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,27,128,29,26,128,28,128,30,128,28,29,128,31,128,29] -; AVX2-FP-NEXT: vpshufb %ymm0, %ymm11, %ymm1 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,2,3,3] +; AVX2-FP-NEXT: vpshufb %ymm0, %ymm12, %ymm1 ; AVX2-FP-NEXT: vbroadcasti128 {{.*#+}} ymm8 = [25,128,27,128,128,26,128,28,128,30,128,128,29,128,31,128,25,128,27,128,128,26,128,28,128,30,128,128,29,128,31,128] ; AVX2-FP-NEXT: # ymm8 = mem[0,1,0,1] -; AVX2-FP-NEXT: vpshufb %ymm8, %ymm3, %ymm2 -; AVX2-FP-NEXT: vmovdqa %ymm3, %ymm12 -; AVX2-FP-NEXT: vmovdqu %ymm3, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] -; AVX2-FP-NEXT: vpor %ymm1, %ymm2, %ymm1 +; AVX2-FP-NEXT: vpshufb %ymm8, %ymm2, %ymm3 +; AVX2-FP-NEXT: vmovdqa %ymm2, %ymm14 +; AVX2-FP-NEXT: vmovdqu %ymm2, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX2-FP-NEXT: vpor %ymm1, %ymm3, %ymm1 ; AVX2-FP-NEXT: vmovdqa 32(%rdi), %ymm4 +; AVX2-FP-NEXT: vmovdqa 32(%rsi), %ymm11 ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm5 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,29,26,128,28,128,26,27,28,29,128,31,128,29,30,128] -; AVX2-FP-NEXT: vpshufb %ymm5, %ymm4, %ymm2 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm6 = ymm2[2,2,3,3] -; AVX2-FP-NEXT: vmovdqa 32(%rsi), %ymm2 +; AVX2-FP-NEXT: vpshufb %ymm5, %ymm4, %ymm6 ; AVX2-FP-NEXT: vbroadcasti128 {{.*#+}} ymm9 = [27,128,128,26,128,28,128,128,128,128,29,128,31,128,128,30,27,128,128,26,128,28,128,128,128,128,29,128,31,128,128,30] ; AVX2-FP-NEXT: # ymm9 = mem[0,1,0,1] -; AVX2-FP-NEXT: vpshufb %ymm9, %ymm2, %ymm7 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] +; AVX2-FP-NEXT: vpshufb %ymm9, %ymm11, %ymm7 ; AVX2-FP-NEXT: vpor %ymm6, %ymm7, %ymm6 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,2,3,3] +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,2,3,3] ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm10 = [255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u] ; AVX2-FP-NEXT: vpblendvb %ymm10, %ymm1, %ymm6, %ymm3 ; AVX2-FP-NEXT: vmovdqa (%rdx), %ymm13 ; AVX2-FP-NEXT: vpshufb %ymm0, %ymm13, %ymm0 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] ; AVX2-FP-NEXT: vmovdqa (%rcx), %ymm7 ; AVX2-FP-NEXT: vpshufb %ymm8, %ymm7, %ymm1 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,2,3,3] ; AVX2-FP-NEXT: vpor %ymm0, %ymm1, %ymm8 -; AVX2-FP-NEXT: vmovdqa (%rdi), %ymm1 -; AVX2-FP-NEXT: vpshufb %ymm5, %ymm1, %ymm0 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm5 = ymm0[2,2,3,3] -; AVX2-FP-NEXT: vmovdqa (%rsi), %ymm0 -; AVX2-FP-NEXT: vpshufb %ymm9, %ymm0, %ymm9 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] +; AVX2-FP-NEXT: vmovdqa (%rdi), %ymm2 +; AVX2-FP-NEXT: vpshufb %ymm5, %ymm2, %ymm5 +; AVX2-FP-NEXT: vmovdqa (%rsi), %ymm1 +; AVX2-FP-NEXT: vpshufb %ymm9, %ymm1, %ymm9 ; AVX2-FP-NEXT: vpor %ymm5, %ymm9, %ymm5 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,2,3,3] ; AVX2-FP-NEXT: vpblendvb %ymm10, %ymm8, %ymm5, %ymm8 ; AVX2-FP-NEXT: vmovdqa 32(%r8), %ymm5 ; AVX2-FP-NEXT: vpshufd {{.*#+}} ymm9 = ymm5[2,2,3,3,6,6,7,7] ; AVX2-FP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm10 = [255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0] -; AVX2-FP-NEXT: vpblendvb %ymm10, %ymm3, %ymm9, %ymm3 -; AVX2-FP-NEXT: vmovdqu %ymm3, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX2-FP-NEXT: vpblendvb %ymm10, %ymm3, %ymm9, %ymm0 +; AVX2-FP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-FP-NEXT: vmovdqa (%r8), %ymm3 ; AVX2-FP-NEXT: vpshufd {{.*#+}} ymm9 = ymm3[2,2,3,3,6,6,7,7] ; AVX2-FP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] -; AVX2-FP-NEXT: vpblendvb %ymm10, %ymm8, %ymm9, %ymm6 -; AVX2-FP-NEXT: vmovdqu %ymm6, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX2-FP-NEXT: vpblendvb %ymm10, %ymm8, %ymm9, %ymm0 +; AVX2-FP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm8 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,21,128,19,20,128,22,128,24,128,22,23,128,25,128,23] ; AVX2-FP-NEXT: vpshufb %ymm8, %ymm4, %ymm9 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] ; AVX2-FP-NEXT: vbroadcasti128 {{.*#+}} ymm10 = [19,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128] ; AVX2-FP-NEXT: # ymm10 = mem[0,1,0,1] -; AVX2-FP-NEXT: vpshufb %ymm10, %ymm2, %ymm15 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,2,3,3] +; AVX2-FP-NEXT: vpshufb %ymm10, %ymm11, %ymm15 ; AVX2-FP-NEXT: vpor %ymm9, %ymm15, %ymm9 ; AVX2-FP-NEXT: vbroadcasti128 {{.*#+}} ymm15 = [128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128] ; AVX2-FP-NEXT: # ymm15 = mem[0,1,0,1] -; AVX2-FP-NEXT: vpshufb %ymm15, %ymm12, %ymm14 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm14 = ymm14[2,2,3,3] +; AVX2-FP-NEXT: vpshufb %ymm15, %ymm14, %ymm0 ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm6 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,25] -; AVX2-FP-NEXT: vpshufb %ymm6, %ymm11, %ymm12 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,2,3,3] -; AVX2-FP-NEXT: vpor %ymm14, %ymm12, %ymm12 +; AVX2-FP-NEXT: vpshufb %ymm6, %ymm12, %ymm14 +; AVX2-FP-NEXT: vpor %ymm0, %ymm14, %ymm0 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm14 = [255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0] -; AVX2-FP-NEXT: vpblendvb %ymm14, %ymm9, %ymm12, %ymm9 -; AVX2-FP-NEXT: vpshufb %ymm8, %ymm1, %ymm8 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] -; AVX2-FP-NEXT: vpshufb %ymm10, %ymm0, %ymm10 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,2,3,3] -; AVX2-FP-NEXT: vpor %ymm8, %ymm10, %ymm8 -; AVX2-FP-NEXT: vpshufb %ymm15, %ymm7, %ymm10 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,2,3,3] +; AVX2-FP-NEXT: vpblendvb %ymm14, %ymm9, %ymm0, %ymm0 +; AVX2-FP-NEXT: vpshufb %ymm8, %ymm2, %ymm8 +; AVX2-FP-NEXT: vpshufb %ymm10, %ymm1, %ymm9 +; AVX2-FP-NEXT: vpor %ymm8, %ymm9, %ymm8 +; AVX2-FP-NEXT: vpshufb %ymm15, %ymm7, %ymm9 ; AVX2-FP-NEXT: vpshufb %ymm6, %ymm13, %ymm6 +; AVX2-FP-NEXT: vpor %ymm6, %ymm9, %ymm6 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] ; AVX2-FP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,2,3,3] -; AVX2-FP-NEXT: vpor %ymm6, %ymm10, %ymm6 ; AVX2-FP-NEXT: vpblendvb %ymm14, %ymm8, %ymm6, %ymm6 ; AVX2-FP-NEXT: vpshufd {{.*#+}} ymm8 = ymm5[0,2,1,1,4,6,5,5] ; AVX2-FP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,3,2] -; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm12 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255] -; AVX2-FP-NEXT: vpblendvb %ymm12, %ymm9, %ymm8, %ymm10 -; AVX2-FP-NEXT: vpshufd {{.*#+}} ymm8 = ymm3[0,2,1,1,4,6,5,5] -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,3,2] -; AVX2-FP-NEXT: vpblendvb %ymm12, %ymm6, %ymm8, %ymm9 -; AVX2-FP-NEXT: vpmovsxbd {{.*#+}} ymm6 = [3,3,3,0,4,4,4,4] -; AVX2-FP-NEXT: vpermd %ymm4, %ymm6, %ymm4 -; AVX2-FP-NEXT: vpbroadcastq {{.*#+}} ymm8 = [0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14] -; AVX2-FP-NEXT: vpshufb %ymm8, %ymm2, %ymm2 -; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm12 = [u,255,0,u,u,u,255,0,u,u,u,255,0,u,u,u,255,0,u,u,u,255,0,u,u,u,255,0,u,u,u,255] -; AVX2-FP-NEXT: vpblendvb %ymm12, %ymm4, %ymm2, %ymm2 -; AVX2-FP-NEXT: vpermd %ymm1, %ymm6, %ymm1 -; AVX2-FP-NEXT: vpshufb %ymm8, %ymm0, %ymm0 -; AVX2-FP-NEXT: vpblendvb %ymm12, %ymm1, %ymm0, %ymm0 +; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm9 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255] +; AVX2-FP-NEXT: vpblendvb %ymm9, %ymm0, %ymm8, %ymm10 +; AVX2-FP-NEXT: vpshufd {{.*#+}} ymm0 = ymm3[0,2,1,1,4,6,5,5] +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,3,2] +; AVX2-FP-NEXT: vpblendvb %ymm9, %ymm6, %ymm0, %ymm9 +; AVX2-FP-NEXT: vpmovsxbd {{.*#+}} ymm0 = [3,3,3,0,4,4,4,4] +; AVX2-FP-NEXT: vpermd %ymm4, %ymm0, %ymm4 +; AVX2-FP-NEXT: vpbroadcastq {{.*#+}} ymm6 = [0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14] +; AVX2-FP-NEXT: vpshufb %ymm6, %ymm11, %ymm8 +; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm11 = [u,255,0,u,u,u,255,0,u,u,u,255,0,u,u,u,255,0,u,u,u,255,0,u,u,u,255,0,u,u,u,255] +; AVX2-FP-NEXT: vpblendvb %ymm11, %ymm4, %ymm8, %ymm4 +; AVX2-FP-NEXT: vpermd %ymm2, %ymm0, %ymm0 +; AVX2-FP-NEXT: vpshufb %ymm6, %ymm1, %ymm1 +; AVX2-FP-NEXT: vpblendvb %ymm11, %ymm0, %ymm1, %ymm0 ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm1 = [128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128] -; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm4 # 32-byte Reload -; AVX2-FP-NEXT: vpshufb %ymm1, %ymm4, %ymm4 +; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload +; AVX2-FP-NEXT: vpshufb %ymm1, %ymm2, %ymm2 ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm6 = [128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128,128] -; AVX2-FP-NEXT: vpshufb %ymm6, %ymm11, %ymm8 -; AVX2-FP-NEXT: vpor %ymm4, %ymm8, %ymm4 +; AVX2-FP-NEXT: vpshufb %ymm6, %ymm12, %ymm8 +; AVX2-FP-NEXT: vpor %ymm2, %ymm8, %ymm2 ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm8 = [u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255] -; AVX2-FP-NEXT: vpblendvb %ymm8, %ymm2, %ymm4, %ymm2 +; AVX2-FP-NEXT: vpblendvb %ymm8, %ymm4, %ymm2, %ymm2 ; AVX2-FP-NEXT: vpshufb %ymm1, %ymm7, %ymm1 ; AVX2-FP-NEXT: vpshufb %ymm6, %ymm13, %ymm4 ; AVX2-FP-NEXT: vpor %ymm1, %ymm4, %ymm1 @@ -4596,8 +4537,8 @@ define void @store_i8_stride5_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FCP-LABEL: store_i8_stride5_vf64: ; AVX2-FCP: # %bb.0: ; AVX2-FCP-NEXT: subq $168, %rsp -; AVX2-FCP-NEXT: vmovdqa 32(%rdx), %ymm13 -; AVX2-FCP-NEXT: vmovdqa 32(%rcx), %ymm10 +; AVX2-FCP-NEXT: vmovdqa 32(%rdx), %ymm14 +; AVX2-FCP-NEXT: vmovdqa 32(%rcx), %ymm9 ; AVX2-FCP-NEXT: vmovdqa (%r8), %ymm11 ; AVX2-FCP-NEXT: vmovdqa (%rcx), %xmm1 ; AVX2-FCP-NEXT: vmovdqa %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill @@ -4643,96 +4584,88 @@ define void @store_i8_stride5_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm4 = [255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255] ; AVX2-FCP-NEXT: vpblendvb %ymm4, %ymm1, %ymm2, %ymm1 ; AVX2-FCP-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FCP-NEXT: vmovdqa 32(%r8), %ymm12 -; AVX2-FCP-NEXT: vpermd %ymm12, %ymm3, %ymm1 +; AVX2-FCP-NEXT: vmovdqa 32(%r8), %ymm13 +; AVX2-FCP-NEXT: vpermd %ymm13, %ymm3, %ymm1 ; AVX2-FCP-NEXT: vpblendvb %ymm4, %ymm0, %ymm1, %ymm0 ; AVX2-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm0 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,27,128,29,26,128,28,128,30,128,28,29,128,31,128,29] -; AVX2-FCP-NEXT: vpshufb %ymm0, %ymm13, %ymm1 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,2,3,3] -; AVX2-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm8 = [25,128,27,128,128,26,128,28,128,30,128,128,29,128,31,128,25,128,27,128,128,26,128,28,128,30,128,128,29,128,31,128] -; AVX2-FCP-NEXT: # ymm8 = mem[0,1,0,1] -; AVX2-FCP-NEXT: vpshufb %ymm8, %ymm10, %ymm2 -; AVX2-FCP-NEXT: vmovdqa %ymm10, %ymm14 -; AVX2-FCP-NEXT: vmovdqu %ymm10, (%rsp) # 32-byte Spill -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] +; AVX2-FCP-NEXT: vpshufb %ymm0, %ymm14, %ymm1 +; AVX2-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm10 = [25,128,27,128,128,26,128,28,128,30,128,128,29,128,31,128,25,128,27,128,128,26,128,28,128,30,128,128,29,128,31,128] +; AVX2-FCP-NEXT: # ymm10 = mem[0,1,0,1] +; AVX2-FCP-NEXT: vpshufb %ymm10, %ymm9, %ymm2 +; AVX2-FCP-NEXT: vmovdqa %ymm9, %ymm15 +; AVX2-FCP-NEXT: vmovdqu %ymm9, (%rsp) # 32-byte Spill ; AVX2-FCP-NEXT: vpor %ymm1, %ymm2, %ymm1 -; AVX2-FCP-NEXT: vmovdqa 32(%rdi), %ymm3 +; AVX2-FCP-NEXT: vmovdqa 32(%rdi), %ymm2 +; AVX2-FCP-NEXT: vmovdqa 32(%rsi), %ymm3 ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm9 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,29,26,128,28,128,26,27,28,29,128,31,128,29,30,128] -; AVX2-FCP-NEXT: vpshufb %ymm9, %ymm3, %ymm2 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm2[2,2,3,3] -; AVX2-FCP-NEXT: vmovdqa 32(%rsi), %ymm2 -; AVX2-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm15 = [27,128,128,26,128,28,128,128,128,128,29,128,31,128,128,30,27,128,128,26,128,28,128,128,128,128,29,128,31,128,128,30] -; AVX2-FCP-NEXT: # ymm15 = mem[0,1,0,1] -; AVX2-FCP-NEXT: vpshufb %ymm15, %ymm2, %ymm5 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,2,3,3] +; AVX2-FCP-NEXT: vpshufb %ymm9, %ymm2, %ymm4 +; AVX2-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm8 = [27,128,128,26,128,28,128,128,128,128,29,128,31,128,128,30,27,128,128,26,128,28,128,128,128,128,29,128,31,128,128,30] +; AVX2-FCP-NEXT: # ymm8 = mem[0,1,0,1] +; AVX2-FCP-NEXT: vpshufb %ymm8, %ymm3, %ymm5 ; AVX2-FCP-NEXT: vpor %ymm4, %ymm5, %ymm4 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,2,3,3] +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,2,3,3] ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm7 = [255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u,0,0,255,255,u] ; AVX2-FCP-NEXT: vpblendvb %ymm7, %ymm1, %ymm4, %ymm4 -; AVX2-FCP-NEXT: vmovdqa (%rdx), %ymm10 -; AVX2-FCP-NEXT: vpshufb %ymm0, %ymm10, %ymm0 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] +; AVX2-FCP-NEXT: vmovdqa (%rdx), %ymm12 +; AVX2-FCP-NEXT: vpshufb %ymm0, %ymm12, %ymm0 ; AVX2-FCP-NEXT: vmovdqa (%rcx), %ymm5 -; AVX2-FCP-NEXT: vpshufb %ymm8, %ymm5, %ymm1 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,2,3,3] -; AVX2-FCP-NEXT: vpor %ymm0, %ymm1, %ymm8 +; AVX2-FCP-NEXT: vpshufb %ymm10, %ymm5, %ymm1 +; AVX2-FCP-NEXT: vpor %ymm0, %ymm1, %ymm10 ; AVX2-FCP-NEXT: vmovdqa (%rdi), %ymm1 -; AVX2-FCP-NEXT: vpshufb %ymm9, %ymm1, %ymm0 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm0[2,2,3,3] +; AVX2-FCP-NEXT: vpshufb %ymm9, %ymm1, %ymm9 ; AVX2-FCP-NEXT: vmovdqa (%rsi), %ymm0 -; AVX2-FCP-NEXT: vpshufb %ymm15, %ymm0, %ymm15 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,2,3,3] -; AVX2-FCP-NEXT: vpor %ymm9, %ymm15, %ymm9 -; AVX2-FCP-NEXT: vpblendvb %ymm7, %ymm8, %ymm9, %ymm7 +; AVX2-FCP-NEXT: vpshufb %ymm8, %ymm0, %ymm8 +; AVX2-FCP-NEXT: vpor %ymm9, %ymm8, %ymm8 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm10[2,2,3,3] +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] +; AVX2-FCP-NEXT: vpblendvb %ymm7, %ymm9, %ymm8, %ymm7 ; AVX2-FCP-NEXT: vpmovsxbd {{.*#+}} ymm8 = [6,6,6,6,7,7,7,7] -; AVX2-FCP-NEXT: vpermd %ymm12, %ymm8, %ymm9 -; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm15 = [255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0] -; AVX2-FCP-NEXT: vpblendvb %ymm15, %ymm4, %ymm9, %ymm4 +; AVX2-FCP-NEXT: vpermd %ymm13, %ymm8, %ymm9 +; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm10 = [255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0] +; AVX2-FCP-NEXT: vpblendvb %ymm10, %ymm4, %ymm9, %ymm4 ; AVX2-FCP-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-FCP-NEXT: vpermd %ymm11, %ymm8, %ymm4 -; AVX2-FCP-NEXT: vpblendvb %ymm15, %ymm7, %ymm4, %ymm4 +; AVX2-FCP-NEXT: vpblendvb %ymm10, %ymm7, %ymm4, %ymm4 ; AVX2-FCP-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm6 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,21,128,19,20,128,22,128,24,128,22,23,128,25,128,23] -; AVX2-FCP-NEXT: vpshufb %ymm6, %ymm3, %ymm7 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] +; AVX2-FCP-NEXT: vpshufb %ymm6, %ymm2, %ymm7 ; AVX2-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm8 = [19,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128] ; AVX2-FCP-NEXT: # ymm8 = mem[0,1,0,1] -; AVX2-FCP-NEXT: vpshufb %ymm8, %ymm2, %ymm9 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,3,3] +; AVX2-FCP-NEXT: vpshufb %ymm8, %ymm3, %ymm9 ; AVX2-FCP-NEXT: vpor %ymm7, %ymm9, %ymm7 ; AVX2-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm9 = [128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128] ; AVX2-FCP-NEXT: # ymm9 = mem[0,1,0,1] -; AVX2-FCP-NEXT: vpshufb %ymm9, %ymm14, %ymm15 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,2,3,3] +; AVX2-FCP-NEXT: vpshufb %ymm9, %ymm15, %ymm10 ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm4 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,25] -; AVX2-FCP-NEXT: vpshufb %ymm4, %ymm13, %ymm14 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm14 = ymm14[2,2,3,3] -; AVX2-FCP-NEXT: vpor %ymm15, %ymm14, %ymm14 +; AVX2-FCP-NEXT: vpshufb %ymm4, %ymm14, %ymm15 +; AVX2-FCP-NEXT: vpor %ymm10, %ymm15, %ymm10 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,2,3,3] ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm15 = [255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0] -; AVX2-FCP-NEXT: vpblendvb %ymm15, %ymm7, %ymm14, %ymm7 +; AVX2-FCP-NEXT: vpblendvb %ymm15, %ymm7, %ymm10, %ymm7 ; AVX2-FCP-NEXT: vpshufb %ymm6, %ymm1, %ymm6 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,2,3,3] ; AVX2-FCP-NEXT: vpshufb %ymm8, %ymm0, %ymm8 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] ; AVX2-FCP-NEXT: vpor %ymm6, %ymm8, %ymm6 ; AVX2-FCP-NEXT: vpshufb %ymm9, %ymm5, %ymm8 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] -; AVX2-FCP-NEXT: vpshufb %ymm4, %ymm10, %ymm4 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,2,3,3] +; AVX2-FCP-NEXT: vpshufb %ymm4, %ymm12, %ymm4 ; AVX2-FCP-NEXT: vpor %ymm4, %ymm8, %ymm4 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,2,3,3] +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,2,3,3] ; AVX2-FCP-NEXT: vpblendvb %ymm15, %ymm6, %ymm4, %ymm4 ; AVX2-FCP-NEXT: vpmovsxbd {{.*#+}} ymm6 = [4,6,5,5,5,5,4,6] -; AVX2-FCP-NEXT: vpermd %ymm12, %ymm6, %ymm8 -; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm14 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255] -; AVX2-FCP-NEXT: vpblendvb %ymm14, %ymm7, %ymm8, %ymm9 +; AVX2-FCP-NEXT: vpermd %ymm13, %ymm6, %ymm8 +; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm10 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255] +; AVX2-FCP-NEXT: vpblendvb %ymm10, %ymm7, %ymm8, %ymm9 ; AVX2-FCP-NEXT: vpermd %ymm11, %ymm6, %ymm6 -; AVX2-FCP-NEXT: vpblendvb %ymm14, %ymm4, %ymm6, %ymm7 +; AVX2-FCP-NEXT: vpblendvb %ymm10, %ymm4, %ymm6, %ymm7 ; AVX2-FCP-NEXT: vpmovsxbd {{.*#+}} ymm4 = [3,3,3,0,4,4,4,4] -; AVX2-FCP-NEXT: vpermd %ymm3, %ymm4, %ymm3 +; AVX2-FCP-NEXT: vpermd %ymm2, %ymm4, %ymm2 ; AVX2-FCP-NEXT: vpbroadcastq {{.*#+}} ymm6 = [0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14] -; AVX2-FCP-NEXT: vpshufb %ymm6, %ymm2, %ymm2 +; AVX2-FCP-NEXT: vpshufb %ymm6, %ymm3, %ymm3 ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm8 = [u,255,0,u,u,u,255,0,u,u,u,255,0,u,u,u,255,0,u,u,u,255,0,u,u,u,255,0,u,u,u,255] -; AVX2-FCP-NEXT: vpblendvb %ymm8, %ymm3, %ymm2, %ymm2 +; AVX2-FCP-NEXT: vpblendvb %ymm8, %ymm2, %ymm3, %ymm2 ; AVX2-FCP-NEXT: vpermd %ymm1, %ymm4, %ymm1 ; AVX2-FCP-NEXT: vpshufb %ymm6, %ymm0, %ymm0 ; AVX2-FCP-NEXT: vpblendvb %ymm8, %ymm1, %ymm0, %ymm0 @@ -4740,16 +4673,16 @@ define void @store_i8_stride5_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FCP-NEXT: vmovdqu (%rsp), %ymm3 # 32-byte Reload ; AVX2-FCP-NEXT: vpshufb %ymm1, %ymm3, %ymm3 ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm4 = [128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128,128] -; AVX2-FCP-NEXT: vpshufb %ymm4, %ymm13, %ymm6 +; AVX2-FCP-NEXT: vpshufb %ymm4, %ymm14, %ymm6 ; AVX2-FCP-NEXT: vpor %ymm3, %ymm6, %ymm3 ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm6 = [u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255,255,0,0,u,255] ; AVX2-FCP-NEXT: vpblendvb %ymm6, %ymm2, %ymm3, %ymm2 ; AVX2-FCP-NEXT: vpshufb %ymm1, %ymm5, %ymm1 -; AVX2-FCP-NEXT: vpshufb %ymm4, %ymm10, %ymm3 +; AVX2-FCP-NEXT: vpshufb %ymm4, %ymm12, %ymm3 ; AVX2-FCP-NEXT: vpor %ymm1, %ymm3, %ymm1 ; AVX2-FCP-NEXT: vpblendvb %ymm6, %ymm0, %ymm1, %ymm1 ; AVX2-FCP-NEXT: vpmovsxbd {{.*#+}} ymm3 = [3,3,3,3,0,4,4,4] -; AVX2-FCP-NEXT: vpermd %ymm12, %ymm3, %ymm0 +; AVX2-FCP-NEXT: vpermd %ymm13, %ymm3, %ymm0 ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm4 = [0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255] ; AVX2-FCP-NEXT: vpblendvb %ymm4, %ymm2, %ymm0, %ymm0 ; AVX2-FCP-NEXT: vpermd %ymm11, %ymm3, %ymm2 @@ -4783,7 +4716,7 @@ define void @store_i8_stride5_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FCP-NEXT: vpermd %ymm11, %ymm4, %ymm5 ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm6 = [255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255] ; AVX2-FCP-NEXT: vpblendvb %ymm6, %ymm2, %ymm5, %ymm2 -; AVX2-FCP-NEXT: vpermd %ymm12, %ymm4, %ymm4 +; AVX2-FCP-NEXT: vpermd %ymm13, %ymm4, %ymm4 ; AVX2-FCP-NEXT: vpblendvb %ymm6, %ymm3, %ymm4, %ymm3 ; AVX2-FCP-NEXT: vmovdqa %ymm1, 64(%r9) ; AVX2-FCP-NEXT: vmovdqa %ymm0, 224(%r9) @@ -4805,766 +4738,740 @@ define void @store_i8_stride5_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; ; AVX512-LABEL: store_i8_stride5_vf64: ; AVX512: # %bb.0: -; AVX512-NEXT: vmovdqa 32(%rsi), %ymm3 -; AVX512-NEXT: vmovdqa {{.*#+}} ymm15 = [128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128,128,128] -; AVX512-NEXT: vpshufb %ymm15, %ymm3, %ymm0 -; AVX512-NEXT: vmovdqa 32(%rdi), %ymm2 -; AVX512-NEXT: vmovdqa {{.*#+}} ymm9 = [12,13,128,15,12,13,14,128,12,13,14,15,128,u,u,u,16,128,18,19,16,17,128,19,16,17,18,128,16,17,18,19] -; AVX512-NEXT: vpshufb %ymm9, %ymm2, %ymm1 +; AVX512-NEXT: vmovdqa 32(%rsi), %ymm11 +; AVX512-NEXT: vmovdqa {{.*#+}} ymm1 = [128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128,128,128] +; AVX512-NEXT: vpshufb %ymm1, %ymm11, %ymm0 +; AVX512-NEXT: vmovdqa64 %ymm1, %ymm18 +; AVX512-NEXT: vmovdqa 32(%rdi), %ymm5 +; AVX512-NEXT: vmovdqa {{.*#+}} ymm2 = [12,13,128,15,12,13,14,128,12,13,14,15,128,u,u,u,16,128,18,19,16,17,128,19,16,17,18,128,16,17,18,19] +; AVX512-NEXT: vpshufb %ymm2, %ymm5, %ymm1 +; AVX512-NEXT: vmovdqa64 %ymm2, %ymm19 +; AVX512-NEXT: vporq %ymm0, %ymm1, %ymm20 +; AVX512-NEXT: vmovdqa 32(%rdi), %xmm12 +; AVX512-NEXT: vmovdqa {{.*#+}} xmm1 = [8,128,u,7,128,9,128,u,128,u,10,128,12,128,u,11] +; AVX512-NEXT: vpshufb %xmm1, %xmm12, %xmm0 +; AVX512-NEXT: vmovdqa64 %xmm1, %xmm28 +; AVX512-NEXT: vmovdqa 32(%rsi), %xmm10 +; AVX512-NEXT: vmovdqa {{.*#+}} xmm2 = [128,8,u,128,7,128,9,u,11,u,128,10,128,12,u,128] +; AVX512-NEXT: vpshufb %xmm2, %xmm10, %xmm1 +; AVX512-NEXT: vmovdqa64 %xmm2, %xmm29 +; AVX512-NEXT: vporq %xmm0, %xmm1, %xmm21 +; AVX512-NEXT: vmovdqa 32(%rcx), %ymm15 +; AVX512-NEXT: vmovdqa {{.*#+}} ymm8 = [128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128] +; AVX512-NEXT: vpshufb %ymm8, %ymm15, %ymm0 +; AVX512-NEXT: vmovdqa 32(%rdx), %ymm13 +; AVX512-NEXT: vmovdqa {{.*#+}} ymm3 = [u,u,12,13,128,u,u,u,14,128,u,u,14,15,128,u,u,u,16,128,u,u,16,17,128,u,u,u,18,128,u,u] +; AVX512-NEXT: vpshufb %ymm3, %ymm13, %ymm1 +; AVX512-NEXT: vporq %ymm0, %ymm1, %ymm22 +; AVX512-NEXT: vmovdqa 32(%rcx), %xmm6 +; AVX512-NEXT: vmovdqa {{.*#+}} xmm1 = [128,6,128,8,u,128,7,128,9,128,11,u,128,10,128,12] +; AVX512-NEXT: vpshufb %xmm1, %xmm6, %xmm0 +; AVX512-NEXT: vmovdqa64 %xmm1, %xmm30 +; AVX512-NEXT: vmovdqa 32(%rdx), %xmm7 +; AVX512-NEXT: vmovdqa {{.*#+}} xmm2 = [6,128,8,128,u,7,128,9,128,11,128,u,10,128,12,128] +; AVX512-NEXT: vpshufb %xmm2, %xmm7, %xmm1 +; AVX512-NEXT: vmovdqa64 %xmm2, %xmm31 +; AVX512-NEXT: vporq %xmm0, %xmm1, %xmm23 +; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm9 = [128,128,26,128,28,128,128,27,128,29,128,31,128,128,30,128,128,128,26,128,28,128,128,27,128,29,128,31,128,128,30,128] +; AVX512-NEXT: # ymm9 = mem[0,1,0,1] +; AVX512-NEXT: vpshufb %ymm9, %ymm5, %ymm0 +; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm4 = [128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,128,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,128] +; AVX512-NEXT: # ymm4 = mem[0,1,0,1] +; AVX512-NEXT: vpshufb %ymm4, %ymm5, %ymm1 +; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm24 +; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm5 = [27,0,128,26,128,28,0,128,0,128,29,128,31,0,128,30,27,0,128,26,128,28,0,128,0,128,29,128,31,0,128,30] +; AVX512-NEXT: # ymm5 = mem[0,1,0,1] +; AVX512-NEXT: vpshufb %ymm5, %ymm11, %ymm1 +; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [19,128,21,0,128,20,128,22,128,24,0,128,23,128,25,0,19,128,21,0,128,20,128,22,128,24,0,128,23,128,25,0] +; AVX512-NEXT: # ymm2 = mem[0,1,0,1] +; AVX512-NEXT: vpshufb %ymm2, %ymm11, %ymm11 +; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm11, %zmm26 +; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm11 = [128,27,128,128,26,128,28,128,30,128,128,29,128,31,128,128,128,27,128,128,26,128,28,128,30,128,128,29,128,31,128,128] +; AVX512-NEXT: # ymm11 = mem[0,1,0,1] +; AVX512-NEXT: vpshufb %ymm11, %ymm13, %ymm1 +; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm0 = [128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128] +; AVX512-NEXT: # ymm0 = mem[0,1,0,1] +; AVX512-NEXT: vpshufb %ymm0, %ymm15, %ymm14 +; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm14, %zmm25 +; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [25,128,27,0,128,26,128,28,128,30,0,128,29,128,31,0,25,128,27,0,128,26,128,28,128,30,0,128,29,128,31,0] +; AVX512-NEXT: # ymm1 = mem[0,1,0,1] +; AVX512-NEXT: vpshufb %ymm1, %ymm15, %ymm14 +; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm15 = [18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25,18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25] +; AVX512-NEXT: # ymm15 = mem[0,1,0,1] +; AVX512-NEXT: vpshufb %ymm15, %ymm13, %ymm13 +; AVX512-NEXT: vinserti64x4 $1, %ymm14, %zmm13, %zmm27 +; AVX512-NEXT: vmovdqa (%rcx), %ymm13 +; AVX512-NEXT: vpshufb %ymm8, %ymm13, %ymm8 +; AVX512-NEXT: vmovdqa (%rdx), %ymm14 +; AVX512-NEXT: vpshufb %ymm3, %ymm14, %ymm3 +; AVX512-NEXT: vporq %ymm8, %ymm3, %ymm16 +; AVX512-NEXT: vpshufb %ymm0, %ymm13, %ymm0 +; AVX512-NEXT: vpshufb %ymm15, %ymm14, %ymm3 +; AVX512-NEXT: vporq %ymm0, %ymm3, %ymm17 +; AVX512-NEXT: vmovdqa (%rsi), %ymm3 +; AVX512-NEXT: vmovdqa64 %ymm18, %ymm0 +; AVX512-NEXT: vpshufb %ymm0, %ymm3, %ymm0 +; AVX512-NEXT: vmovdqa (%rdi), %ymm8 +; AVX512-NEXT: vmovdqa64 %ymm19, %ymm15 +; AVX512-NEXT: vpshufb %ymm15, %ymm8, %ymm15 +; AVX512-NEXT: vporq %ymm0, %ymm15, %ymm18 +; AVX512-NEXT: vpshufb %ymm4, %ymm8, %ymm0 +; AVX512-NEXT: vpshufb %ymm2, %ymm3, %ymm2 +; AVX512-NEXT: vporq %ymm0, %ymm2, %ymm19 +; AVX512-NEXT: vpshufb %ymm11, %ymm14, %ymm0 +; AVX512-NEXT: vpshufb %ymm1, %ymm13, %ymm1 ; AVX512-NEXT: vpor %ymm0, %ymm1, %ymm0 -; AVX512-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-NEXT: vmovdqa 32(%rdi), %xmm1 -; AVX512-NEXT: vmovdqa {{.*#+}} xmm5 = [8,128,u,7,128,9,128,u,128,u,10,128,12,128,u,11] -; AVX512-NEXT: vpshufb %xmm5, %xmm1, %xmm0 -; AVX512-NEXT: vmovdqa64 %xmm1, %xmm16 -; AVX512-NEXT: vmovdqa 32(%rsi), %xmm4 -; AVX512-NEXT: vmovdqa {{.*#+}} xmm14 = [128,8,u,128,7,128,9,u,11,u,128,10,128,12,u,128] -; AVX512-NEXT: vpshufb %xmm14, %xmm4, %xmm1 -; AVX512-NEXT: vmovdqa64 %xmm4, %xmm31 -; AVX512-NEXT: vpor %xmm0, %xmm1, %xmm0 -; AVX512-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-NEXT: vmovdqa 32(%rcx), %ymm8 -; AVX512-NEXT: vmovdqa {{.*#+}} ymm0 = [128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128] -; AVX512-NEXT: vpshufb %ymm0, %ymm8, %ymm4 -; AVX512-NEXT: vmovdqa 32(%rdx), %ymm11 -; AVX512-NEXT: vmovdqa {{.*#+}} ymm1 = [u,u,12,13,128,u,u,u,14,128,u,u,14,15,128,u,u,u,16,128,u,u,16,17,128,u,u,u,18,128,u,u] -; AVX512-NEXT: vpshufb %ymm1, %ymm11, %ymm10 -; AVX512-NEXT: vpor %ymm4, %ymm10, %ymm4 -; AVX512-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-NEXT: vmovdqa 32(%rcx), %xmm13 -; AVX512-NEXT: vmovdqa {{.*#+}} xmm6 = [128,6,128,8,u,128,7,128,9,128,11,u,128,10,128,12] -; AVX512-NEXT: vpshufb %xmm6, %xmm13, %xmm4 -; AVX512-NEXT: vmovdqa64 %xmm6, %xmm25 -; AVX512-NEXT: vmovdqa 32(%rdx), %xmm10 -; AVX512-NEXT: vmovdqa {{.*#+}} xmm6 = [6,128,8,128,u,7,128,9,128,11,128,u,10,128,12,128] -; AVX512-NEXT: vpshufb %xmm6, %xmm10, %xmm12 -; AVX512-NEXT: vmovdqa64 %xmm6, %xmm26 -; AVX512-NEXT: vporq %xmm4, %xmm12, %xmm20 -; AVX512-NEXT: vpshufb {{.*#+}} ymm4 = ymm3[11,u,u,10,u,12,u,u,u,u,13,u,15,u,u,14,27,u,u,26,u,28,u,u,u,u,29,u,31,u,u,30] -; AVX512-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[3,u,5,u,u,4,u,6,u,8,u,u,7,u,9,u,19,u,21,u,u,20,u,22,u,24,u,u,23,u,25,u] -; AVX512-NEXT: vinserti64x4 $1, %ymm4, %zmm3, %zmm22 -; AVX512-NEXT: vpshufb {{.*#+}} ymm3 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[26],zero,ymm2[28],zero,zero,ymm2[27],zero,ymm2[29],zero,ymm2[31],zero,zero,ymm2[30],zero -; AVX512-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[21],zero,zero,ymm2[20],zero,ymm2[22],zero,ymm2[24],zero,zero,ymm2[23],zero,ymm2[25],zero,zero -; AVX512-NEXT: vinserti64x4 $1, %ymm3, %zmm2, %zmm23 -; AVX512-NEXT: vpshufb {{.*#+}} ymm2 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm11[27],zero,zero,ymm11[26],zero,ymm11[28],zero,ymm11[30],zero,zero,ymm11[29],zero,ymm11[31],zero,zero -; AVX512-NEXT: vpshufb {{.*#+}} ymm3 = ymm8[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm8[19],zero,ymm8[21],zero,zero,ymm8[20],zero,ymm8[22],zero,ymm8[24],zero,zero,ymm8[23],zero -; AVX512-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm24 -; AVX512-NEXT: vmovdqa (%rcx), %ymm12 -; AVX512-NEXT: vpshufb %ymm0, %ymm12, %ymm0 -; AVX512-NEXT: vmovdqa (%rdx), %ymm6 -; AVX512-NEXT: vpshufb %ymm1, %ymm6, %ymm1 -; AVX512-NEXT: vporq %ymm0, %ymm1, %ymm19 -; AVX512-NEXT: vmovdqa (%rsi), %ymm7 -; AVX512-NEXT: vpshufb %ymm15, %ymm7, %ymm2 -; AVX512-NEXT: vmovdqa (%rdi), %ymm4 -; AVX512-NEXT: vpshufb %ymm9, %ymm4, %ymm3 -; AVX512-NEXT: vporq %ymm2, %ymm3, %ymm21 -; AVX512-NEXT: vmovdqa (%rdi), %xmm0 -; AVX512-NEXT: vpshufb %xmm5, %xmm0, %xmm3 -; AVX512-NEXT: vmovdqa64 %xmm0, %xmm17 -; AVX512-NEXT: vmovdqa (%rsi), %xmm5 -; AVX512-NEXT: vpshufb %xmm14, %xmm5, %xmm9 -; AVX512-NEXT: vporq %xmm3, %xmm9, %xmm27 -; AVX512-NEXT: vmovdqa (%rcx), %xmm1 -; AVX512-NEXT: vmovdqa64 %xmm25, %xmm0 -; AVX512-NEXT: vpshufb %xmm0, %xmm1, %xmm0 -; AVX512-NEXT: vmovdqa64 %xmm1, %xmm18 -; AVX512-NEXT: vmovdqa (%rdx), %xmm9 -; AVX512-NEXT: vmovdqa64 %xmm26, %xmm1 -; AVX512-NEXT: vpshufb %xmm1, %xmm9, %xmm15 -; AVX512-NEXT: vporq %xmm0, %xmm15, %xmm29 -; AVX512-NEXT: vpshufd {{.*#+}} xmm0 = mem[1,1,2,2] -; AVX512-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,1,1,1] +; AVX512-NEXT: vpshufb %ymm9, %ymm8, %ymm1 +; AVX512-NEXT: vpshufb %ymm5, %ymm3, %ymm2 +; AVX512-NEXT: vmovdqa (%rdi), %xmm5 +; AVX512-NEXT: vpor %ymm1, %ymm2, %ymm1 +; AVX512-NEXT: vmovdqa (%rsi), %xmm9 +; AVX512-NEXT: vmovdqa (%rcx), %xmm8 +; AVX512-NEXT: vmovdqa64 %xmm28, %xmm2 +; AVX512-NEXT: vpshufb %xmm2, %xmm5, %xmm2 +; AVX512-NEXT: vmovdqa64 %xmm29, %xmm3 +; AVX512-NEXT: vpshufb %xmm3, %xmm9, %xmm3 +; AVX512-NEXT: vpor %xmm2, %xmm3, %xmm4 +; AVX512-NEXT: vmovdqa (%rdx), %xmm3 +; AVX512-NEXT: vmovdqa 32(%r8), %ymm11 +; AVX512-NEXT: vmovdqa64 %xmm30, %xmm2 +; AVX512-NEXT: vpshufb %xmm2, %xmm8, %xmm2 +; AVX512-NEXT: vmovdqa64 %xmm31, %xmm13 +; AVX512-NEXT: vpshufb %xmm13, %xmm3, %xmm13 +; AVX512-NEXT: vpor %xmm2, %xmm13, %xmm13 +; AVX512-NEXT: vmovdqa {{.*#+}} ymm14 = [12,128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128] +; AVX512-NEXT: vpshufb %ymm14, %ymm11, %ymm2 +; AVX512-NEXT: vpshufd {{.*#+}} xmm15 = mem[1,1,2,2] +; AVX512-NEXT: vpermq {{.*#+}} ymm15 = ymm15[0,1,1,1] ; AVX512-NEXT: vmovdqa64 {{.*#+}} zmm28 = [255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255] -; AVX512-NEXT: vpandnq %ymm0, %ymm28, %ymm0 -; AVX512-NEXT: vmovdqa 32(%r8), %ymm15 -; AVX512-NEXT: vmovdqa {{.*#+}} ymm1 = [12,128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128] -; AVX512-NEXT: vpshufb %ymm1, %ymm15, %ymm14 -; AVX512-NEXT: vinserti64x4 $1, %ymm14, %zmm0, %zmm26 -; AVX512-NEXT: vmovdqa (%r8), %ymm0 -; AVX512-NEXT: vpshufb %ymm1, %ymm0, %ymm1 -; AVX512-NEXT: vpshufd {{.*#+}} ymm0 = ymm0[0,2,1,1,4,6,5,5] -; AVX512-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,3,2] -; AVX512-NEXT: vmovdqa64 {{.*#+}} zmm30 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0] -; AVX512-NEXT: vpandnq %ymm0, %ymm30, %ymm0 -; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm25 -; AVX512-NEXT: vpbroadcastq {{.*#+}} ymm0 = [9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12] -; AVX512-NEXT: vpshufb %ymm0, %ymm8, %ymm8 -; AVX512-NEXT: vpshufb {{.*#+}} ymm14 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm12[19],zero,ymm12[21],zero,zero,ymm12[20],zero,ymm12[22],zero,ymm12[24],zero,zero,ymm12[23],zero -; AVX512-NEXT: vpshufb %ymm0, %ymm12, %ymm12 -; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm0 = [18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25,18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25] -; AVX512-NEXT: # ymm0 = mem[0,1,0,1] -; AVX512-NEXT: vpshufb %ymm0, %ymm11, %ymm11 -; AVX512-NEXT: vpshufb %ymm0, %ymm6, %ymm2 -; AVX512-NEXT: vpshufb {{.*#+}} ymm6 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[27],zero,zero,ymm6[26],zero,ymm6[28],zero,ymm6[30],zero,zero,ymm6[29],zero,ymm6[31],zero,zero -; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm10 = xmm13[0],xmm10[0],xmm13[1],xmm10[1],xmm13[2],xmm10[2],xmm13[3],xmm10[3],xmm13[4],xmm10[4],xmm13[5],xmm10[5],xmm13[6],xmm10[6],xmm13[7],xmm10[7] -; AVX512-NEXT: vpshufb {{.*#+}} ymm13 = ymm7[3,u,5,u,u,4,u,6,u,8,u,u,7,u,9,u,19,u,21,u,u,20,u,22,u,24,u,u,23,u,25,u] -; AVX512-NEXT: vpshufb {{.*#+}} ymm7 = ymm7[11,u,u,10,u,12,u,u,u,u,13,u,15,u,u,14,27,u,u,26,u,28,u,u,u,u,29,u,31,u,u,30] -; AVX512-NEXT: vpshufb {{.*#+}} ymm0 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm4[21],zero,zero,ymm4[20],zero,ymm4[22],zero,ymm4[24],zero,zero,ymm4[23],zero,ymm4[25],zero,zero -; AVX512-NEXT: vpshufb {{.*#+}} ymm3 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm4[26],zero,ymm4[28],zero,zero,ymm4[27],zero,ymm4[29],zero,ymm4[31],zero,zero,ymm4[30],zero -; AVX512-NEXT: vmovdqa64 %xmm16, %xmm1 -; AVX512-NEXT: vmovdqa64 %xmm31, %xmm4 -; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm4 = xmm1[0],xmm4[0],xmm1[1],xmm4[1],xmm1[2],xmm4[2],xmm1[3],xmm4[3],xmm1[4],xmm4[4],xmm1[5],xmm4[5],xmm1[6],xmm4[6],xmm1[7],xmm4[7] -; AVX512-NEXT: vpmovsxbd {{.*#+}} zmm1 = [4,0,5,5,5,5,0,6,6,6,6,0,7,7,7,7] -; AVX512-NEXT: vpermd %zmm15, %zmm1, %zmm31 -; AVX512-NEXT: vmovdqa64 (%r8), %zmm16 -; AVX512-NEXT: vpmovsxbd {{.*#+}} zmm1 = [6,6,6,0,7,7,7,7,0,16,16,16,16,0,17,17] -; AVX512-NEXT: vpermi2d %zmm15, %zmm16, %zmm1 -; AVX512-NEXT: vmovdqa64 %xmm17, %xmm15 -; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm5 = xmm15[0],xmm5[0],xmm15[1],xmm5[1],xmm15[2],xmm5[2],xmm15[3],xmm5[3],xmm15[4],xmm5[4],xmm15[5],xmm5[5],xmm15[6],xmm5[6],xmm15[7],xmm5[7] -; AVX512-NEXT: vmovdqa {{.*#+}} xmm15 = [0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] -; AVX512-NEXT: vpshufb %xmm15, %xmm4, %xmm4 -; AVX512-NEXT: vpshufb %xmm15, %xmm5, %xmm5 -; AVX512-NEXT: vinserti32x4 $2, %xmm27, %zmm5, %zmm5 -; AVX512-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,2,3,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm14 = ymm14[2,2,3,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,2,3,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,2,3,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,2,3,3] -; AVX512-NEXT: vmovdqa64 %xmm18, %xmm15 -; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm9 = xmm15[0],xmm9[0],xmm15[1],xmm9[1],xmm15[2],xmm9[2],xmm15[3],xmm9[3],xmm15[4],xmm9[4],xmm15[5],xmm9[5],xmm15[6],xmm9[6],xmm15[7],xmm9[7] -; AVX512-NEXT: vmovdqa {{.*#+}} xmm15 = [2,u,1,0,5,4,u,3,u,7,6,11,10,u,9,8] -; AVX512-NEXT: vpshufb %xmm15, %xmm10, %xmm10 +; AVX512-NEXT: vpandnq %ymm15, %ymm28, %ymm15 +; AVX512-NEXT: vinserti64x4 $1, %ymm2, %zmm15, %zmm2 +; AVX512-NEXT: vmovdqa (%r8), %ymm15 +; AVX512-NEXT: vpshufb %ymm14, %ymm15, %ymm14 +; AVX512-NEXT: vpshufd {{.*#+}} ymm15 = ymm15[0,2,1,1,4,6,5,5] +; AVX512-NEXT: vmovdqa64 {{.*#+}} zmm29 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0] +; AVX512-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,3,3,2] +; AVX512-NEXT: vpandnq %ymm15, %ymm29, %ymm15 +; AVX512-NEXT: vinserti64x4 $1, %ymm15, %zmm14, %zmm14 +; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm6 = xmm6[0],xmm7[0],xmm6[1],xmm7[1],xmm6[2],xmm7[2],xmm6[3],xmm7[3],xmm6[4],xmm7[4],xmm6[5],xmm7[5],xmm6[6],xmm7[6],xmm6[7],xmm7[7] +; AVX512-NEXT: vmovdqa {{.*#+}} xmm7 = [2,u,1,0,5,4,u,3,u,7,6,11,10,u,9,8] +; AVX512-NEXT: vpshufb %xmm7, %xmm6, %xmm6 +; AVX512-NEXT: vpermq {{.*#+}} ymm6 = ymm6[0,0,1,1] +; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm10 = xmm12[0],xmm10[0],xmm12[1],xmm10[1],xmm12[2],xmm10[2],xmm12[3],xmm10[3],xmm12[4],xmm10[4],xmm12[5],xmm10[5],xmm12[6],xmm10[6],xmm12[7],xmm10[7] +; AVX512-NEXT: vmovdqa {{.*#+}} xmm12 = [0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] +; AVX512-NEXT: vpshufb %xmm12, %xmm10, %xmm10 ; AVX512-NEXT: vpermq {{.*#+}} ymm10 = ymm10[0,0,1,1] -; AVX512-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,3,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm4 = ymm4[0,0,1,1] -; AVX512-NEXT: vpshufb %xmm15, %xmm9, %xmm9 -; AVX512-NEXT: vinserti32x4 $2, %xmm29, %zmm9, %zmm9 -; AVX512-NEXT: vpermq $80, {{[-0-9]+}}(%r{{[sb]}}p), %ymm15 # 32-byte Folded Reload -; AVX512-NEXT: # ymm15 = mem[0,0,1,1] -; AVX512-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm15, %zmm15 # 32-byte Folded Reload -; AVX512-NEXT: vpermq {{.*#+}} ymm17 = ymm20[0,0,1,1] -; AVX512-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm17, %zmm17 # 32-byte Folded Reload -; AVX512-NEXT: vmovdqa64 {{.*#+}} zmm18 = [255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0] -; AVX512-NEXT: vpternlogq $226, %zmm15, %zmm18, %zmm17 -; AVX512-NEXT: vpternlogq $248, %zmm28, %zmm17, %zmm26 -; AVX512-NEXT: vpermq {{.*#+}} zmm15 = zmm22[2,2,3,3,6,6,7,7] -; AVX512-NEXT: vpermq {{.*#+}} zmm17 = zmm23[2,2,3,3,6,6,7,7] -; AVX512-NEXT: vmovdqa64 {{.*#+}} zmm20 = [18374966859431608575,18374966859431608575,18446463693966278400,18446463693966278400,72056498804555775,72056498804555775,18374967950370078975,18374967950370078975] -; AVX512-NEXT: vpternlogq $248, %zmm20, %zmm15, %zmm17 -; AVX512-NEXT: vpandq %ymm20, %ymm8, %ymm8 -; AVX512-NEXT: vinserti64x4 $1, %ymm8, %zmm11, %zmm8 -; AVX512-NEXT: vpermq {{.*#+}} zmm11 = zmm24[2,2,3,3,6,6,7,7] -; AVX512-NEXT: vporq %zmm11, %zmm8, %zmm8 -; AVX512-NEXT: vmovdqa64 {{.*#+}} zmm11 = [0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255] -; AVX512-NEXT: vpternlogq $226, %zmm17, %zmm11, %zmm8 -; AVX512-NEXT: vpternlogd $184, %zmm8, %zmm30, %zmm31 -; AVX512-NEXT: vpor %ymm2, %ymm14, %ymm2 -; AVX512-NEXT: vinserti64x4 $1, %ymm2, %zmm19, %zmm2 -; AVX512-NEXT: vpternlogq $248, %ymm20, %ymm13, %ymm0 -; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm21, %zmm0 -; AVX512-NEXT: vpternlogq $226, %zmm2, %zmm18, %zmm0 -; AVX512-NEXT: vpternlogq $248, %ymm20, %ymm12, %ymm6 -; AVX512-NEXT: vinserti64x4 $1, %ymm10, %zmm6, %zmm2 -; AVX512-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm7, %ymm3 -; AVX512-NEXT: vinserti64x4 $1, %ymm4, %zmm3, %zmm3 -; AVX512-NEXT: vpternlogq $226, %zmm2, %zmm11, %zmm3 -; AVX512-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm25 -; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm3, %zmm1 -; AVX512-NEXT: vpermq {{.*#+}} zmm0 = zmm5[0,0,1,1,4,4,5,5] -; AVX512-NEXT: vpermq {{.*#+}} zmm2 = zmm9[0,0,1,1,4,4,5,5] -; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm2 +; AVX512-NEXT: vmovdqa64 (%r8), %zmm15 +; AVX512-NEXT: vpmovsxbd {{.*#+}} zmm30 = [4,0,5,5,5,5,0,6,6,6,6,0,7,7,7,7] +; AVX512-NEXT: vpermd %zmm11, %zmm30, %zmm30 +; AVX512-NEXT: vpmovsxbd {{.*#+}} zmm31 = [6,6,6,0,7,7,7,7,0,16,16,16,16,0,17,17] +; AVX512-NEXT: vpermi2d %zmm11, %zmm15, %zmm31 +; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm5 = xmm5[0],xmm9[0],xmm5[1],xmm9[1],xmm5[2],xmm9[2],xmm5[3],xmm9[3],xmm5[4],xmm9[4],xmm5[5],xmm9[5],xmm5[6],xmm9[6],xmm5[7],xmm9[7] +; AVX512-NEXT: vpshufb %xmm12, %xmm5, %xmm5 +; AVX512-NEXT: vinserti32x4 $2, %xmm4, %zmm5, %zmm4 +; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm3 = xmm8[0],xmm3[0],xmm8[1],xmm3[1],xmm8[2],xmm3[2],xmm8[3],xmm3[3],xmm8[4],xmm3[4],xmm8[5],xmm3[5],xmm8[6],xmm3[6],xmm8[7],xmm3[7] +; AVX512-NEXT: vpshufb %xmm7, %xmm3, %xmm3 +; AVX512-NEXT: vinserti32x4 $2, %xmm13, %zmm3, %zmm3 +; AVX512-NEXT: vpermq {{.*#+}} ymm5 = ymm21[0,0,1,1] +; AVX512-NEXT: vinserti64x4 $1, %ymm20, %zmm5, %zmm5 +; AVX512-NEXT: vpermq {{.*#+}} ymm7 = ymm23[0,0,1,1] +; AVX512-NEXT: vinserti64x4 $1, %ymm22, %zmm7, %zmm7 +; AVX512-NEXT: vmovdqa64 {{.*#+}} zmm8 = [255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0] +; AVX512-NEXT: vpternlogq $226, %zmm5, %zmm8, %zmm7 +; AVX512-NEXT: vpternlogq $248, %zmm28, %zmm7, %zmm2 +; AVX512-NEXT: vpermq {{.*#+}} zmm5 = zmm24[2,2,3,3,6,6,7,7] +; AVX512-NEXT: vpermq {{.*#+}} zmm7 = zmm26[2,2,3,3,6,6,7,7] +; AVX512-NEXT: vporq %zmm5, %zmm7, %zmm5 +; AVX512-NEXT: vpermq {{.*#+}} zmm7 = zmm25[2,2,3,3,6,6,7,7] +; AVX512-NEXT: vpermq {{.*#+}} zmm9 = zmm27[2,2,3,3,6,6,7,7] +; AVX512-NEXT: vporq %zmm7, %zmm9, %zmm7 +; AVX512-NEXT: vmovdqa64 {{.*#+}} zmm9 = [0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255] +; AVX512-NEXT: vpternlogq $226, %zmm5, %zmm9, %zmm7 +; AVX512-NEXT: vpternlogd $184, %zmm7, %zmm29, %zmm30 +; AVX512-NEXT: vpermq {{.*#+}} ymm5 = ymm17[2,2,3,3] +; AVX512-NEXT: vinserti64x4 $1, %ymm5, %zmm16, %zmm5 +; AVX512-NEXT: vpermq {{.*#+}} ymm7 = ymm19[2,2,3,3] +; AVX512-NEXT: vinserti64x4 $1, %ymm7, %zmm18, %zmm7 +; AVX512-NEXT: vpternlogq $226, %zmm5, %zmm8, %zmm7 +; AVX512-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] +; AVX512-NEXT: vinserti64x4 $1, %ymm6, %zmm0, %zmm0 +; AVX512-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,2,3,3] +; AVX512-NEXT: vinserti64x4 $1, %ymm10, %zmm1, %zmm1 +; AVX512-NEXT: vpternlogq $226, %zmm0, %zmm9, %zmm1 +; AVX512-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm7, %zmm14 +; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm31 +; AVX512-NEXT: vpermq {{.*#+}} zmm0 = zmm4[0,0,1,1,4,4,5,5] +; AVX512-NEXT: vpermq {{.*#+}} zmm1 = zmm3[0,0,1,1,4,4,5,5] +; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm1 ; AVX512-NEXT: vpmovsxbd {{.*#+}} zmm0 = [0,0,0,0,0,0,1,1,1,1,0,2,2,2,2,0] -; AVX512-NEXT: vpermd %zmm16, %zmm0, %zmm0 -; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm0 -; AVX512-NEXT: vmovdqa64 %zmm25, 64(%r9) +; AVX512-NEXT: vpermd %zmm15, %zmm0, %zmm0 +; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm0 +; AVX512-NEXT: vmovdqa64 %zmm14, 64(%r9) ; AVX512-NEXT: vmovdqa64 %zmm0, (%r9) -; AVX512-NEXT: vmovdqa64 %zmm1, 128(%r9) -; AVX512-NEXT: vmovdqa64 %zmm31, 256(%r9) -; AVX512-NEXT: vmovdqa64 %zmm26, 192(%r9) +; AVX512-NEXT: vmovdqa64 %zmm31, 128(%r9) +; AVX512-NEXT: vmovdqa64 %zmm30, 256(%r9) +; AVX512-NEXT: vmovdqa64 %zmm2, 192(%r9) ; AVX512-NEXT: vzeroupper ; AVX512-NEXT: retq ; ; AVX512-FCP-LABEL: store_i8_stride5_vf64: ; AVX512-FCP: # %bb.0: -; AVX512-FCP-NEXT: subq $24, %rsp -; AVX512-FCP-NEXT: vmovdqa 32(%rsi), %ymm3 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm8 = [128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128,128,128] -; AVX512-FCP-NEXT: vpshufb %ymm8, %ymm3, %ymm0 +; AVX512-FCP-NEXT: vmovdqa 32(%rsi), %ymm0 +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm14 = [128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128,128,128] +; AVX512-FCP-NEXT: vpshufb %ymm14, %ymm0, %ymm2 ; AVX512-FCP-NEXT: vmovdqa 32(%rdi), %ymm1 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm11 = [12,13,128,15,12,13,14,128,12,13,14,15,128,u,u,u,16,128,18,19,16,17,128,19,16,17,18,128,16,17,18,19] -; AVX512-FCP-NEXT: vpshufb %ymm11, %ymm1, %ymm2 -; AVX512-FCP-NEXT: vpor %ymm0, %ymm2, %ymm0 -; AVX512-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-FCP-NEXT: vmovdqa 32(%rdi), %xmm0 -; AVX512-FCP-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm5 = [8,128,u,7,128,9,128,u,128,u,10,128,12,128,u,11] -; AVX512-FCP-NEXT: vpshufb %xmm5, %xmm0, %xmm0 -; AVX512-FCP-NEXT: vmovdqa 32(%rsi), %xmm4 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm13 = [128,8,u,128,7,128,9,u,11,u,128,10,128,12,u,128] -; AVX512-FCP-NEXT: vpshufb %xmm13, %xmm4, %xmm2 -; AVX512-FCP-NEXT: vmovdqa64 %xmm4, %xmm19 -; AVX512-FCP-NEXT: vpor %xmm0, %xmm2, %xmm0 -; AVX512-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-FCP-NEXT: vmovdqa 32(%rcx), %ymm7 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm0 = [128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128] -; AVX512-FCP-NEXT: vpshufb %ymm0, %ymm7, %ymm2 -; AVX512-FCP-NEXT: vmovdqa 32(%rdx), %ymm9 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm15 = [u,u,12,13,128,u,u,u,14,128,u,u,14,15,128,u,u,u,16,128,u,u,16,17,128,u,u,u,18,128,u,u] -; AVX512-FCP-NEXT: vpshufb %ymm15, %ymm9, %ymm4 -; AVX512-FCP-NEXT: vpor %ymm2, %ymm4, %ymm2 -; AVX512-FCP-NEXT: vmovdqu %ymm2, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-FCP-NEXT: vmovdqa 32(%rcx), %xmm12 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm4 = [128,6,128,8,u,128,7,128,9,128,11,u,128,10,128,12] -; AVX512-FCP-NEXT: vpshufb %xmm4, %xmm12, %xmm2 -; AVX512-FCP-NEXT: vmovdqa64 %xmm4, %xmm25 -; AVX512-FCP-NEXT: vmovdqa 32(%rdx), %xmm10 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm6 = [6,128,8,128,u,7,128,9,128,11,128,u,10,128,12,128] -; AVX512-FCP-NEXT: vpshufb %xmm6, %xmm10, %xmm4 -; AVX512-FCP-NEXT: vmovdqa64 %xmm6, %xmm26 -; AVX512-FCP-NEXT: vpor %xmm2, %xmm4, %xmm2 -; AVX512-FCP-NEXT: vmovdqu %ymm2, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm3[11,u,u,10,u,12,u,u,u,u,13,u,15,u,u,14,27,u,u,26,u,28,u,u,u,u,29,u,31,u,u,30] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[3,u,5,u,u,4,u,6,u,8,u,u,7,u,9,u,19,u,21,u,u,20,u,22,u,24,u,u,23,u,25,u] -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm21 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm1[26],zero,ymm1[28],zero,zero,ymm1[27],zero,ymm1[29],zero,ymm1[31],zero,zero,ymm1[30],zero -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[21],zero,zero,ymm1[20],zero,ymm1[22],zero,ymm1[24],zero,zero,ymm1[23],zero,ymm1[25],zero,zero -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm1, %zmm22 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm9[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm9[27],zero,zero,ymm9[26],zero,ymm9[28],zero,ymm9[30],zero,zero,ymm9[29],zero,ymm9[31],zero,zero -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm7[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm7[19],zero,ymm7[21],zero,zero,ymm7[20],zero,ymm7[22],zero,ymm7[24],zero,zero,ymm7[23],zero -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm23 -; AVX512-FCP-NEXT: vmovdqa (%rcx), %ymm4 -; AVX512-FCP-NEXT: vpshufb %ymm0, %ymm4, %ymm0 -; AVX512-FCP-NEXT: vmovdqa (%rdx), %ymm14 -; AVX512-FCP-NEXT: vpshufb %ymm15, %ymm14, %ymm1 -; AVX512-FCP-NEXT: vporq %ymm0, %ymm1, %ymm24 -; AVX512-FCP-NEXT: vmovdqa (%rsi), %ymm15 -; AVX512-FCP-NEXT: vpshufb %ymm8, %ymm15, %ymm0 -; AVX512-FCP-NEXT: vmovdqa (%rdi), %ymm6 -; AVX512-FCP-NEXT: vpshufb %ymm11, %ymm6, %ymm1 -; AVX512-FCP-NEXT: vporq %ymm0, %ymm1, %ymm20 -; AVX512-FCP-NEXT: vmovdqa (%rdi), %xmm0 -; AVX512-FCP-NEXT: vpshufb %xmm5, %xmm0, %xmm1 -; AVX512-FCP-NEXT: vmovdqa64 %xmm0, %xmm16 -; AVX512-FCP-NEXT: vmovdqa (%rsi), %xmm3 -; AVX512-FCP-NEXT: vpshufb %xmm13, %xmm3, %xmm2 -; AVX512-FCP-NEXT: vporq %xmm1, %xmm2, %xmm28 -; AVX512-FCP-NEXT: vmovdqa (%rcx), %xmm1 -; AVX512-FCP-NEXT: vmovdqa64 %xmm25, %xmm0 -; AVX512-FCP-NEXT: vpshufb %xmm0, %xmm1, %xmm8 -; AVX512-FCP-NEXT: vmovdqa64 %xmm1, %xmm18 -; AVX512-FCP-NEXT: vmovdqa (%rdx), %xmm1 -; AVX512-FCP-NEXT: vmovdqa64 %xmm26, %xmm0 -; AVX512-FCP-NEXT: vpshufb %xmm0, %xmm1, %xmm11 -; AVX512-FCP-NEXT: vmovdqa64 %xmm1, %xmm17 -; AVX512-FCP-NEXT: vporq %xmm8, %xmm11, %xmm29 -; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} ymm11 = [1,1,2,2,2,2,2,2] +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm9 = [12,13,128,15,12,13,14,128,12,13,14,15,128,u,u,u,16,128,18,19,16,17,128,19,16,17,18,128,16,17,18,19] +; AVX512-FCP-NEXT: vpshufb %ymm9, %ymm1, %ymm3 +; AVX512-FCP-NEXT: vporq %ymm2, %ymm3, %ymm17 +; AVX512-FCP-NEXT: vmovdqa 32(%rdi), %xmm3 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm2 = xmm3[8],zero,xmm3[u,7],zero,xmm3[9],zero,xmm3[u],zero,xmm3[u,10],zero,xmm3[12],zero,xmm3[u,11] +; AVX512-FCP-NEXT: vmovdqa64 %xmm3, %xmm31 +; AVX512-FCP-NEXT: vmovdqa 32(%rsi), %xmm15 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm4 = zero,xmm15[8,u],zero,xmm15[7],zero,xmm15[9,u,11,u],zero,xmm15[10],zero,xmm15[12,u],zero +; AVX512-FCP-NEXT: vporq %xmm2, %xmm4, %xmm18 +; AVX512-FCP-NEXT: vmovdqa 32(%rcx), %ymm2 +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm10 = [128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128] +; AVX512-FCP-NEXT: vpshufb %ymm10, %ymm2, %ymm4 +; AVX512-FCP-NEXT: vmovdqa 32(%rdx), %ymm11 +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm12 = [u,u,12,13,128,u,u,u,14,128,u,u,14,15,128,u,u,u,16,128,u,u,16,17,128,u,u,u,18,128,u,u] +; AVX512-FCP-NEXT: vpshufb %ymm12, %ymm11, %ymm6 +; AVX512-FCP-NEXT: vporq %ymm4, %ymm6, %ymm19 +; AVX512-FCP-NEXT: vmovdqa 32(%rcx), %xmm6 +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm3 = [128,6,128,8,u,128,7,128,9,128,11,u,128,10,128,12] +; AVX512-FCP-NEXT: vpshufb %xmm3, %xmm6, %xmm4 +; AVX512-FCP-NEXT: vmovdqa64 %xmm3, %xmm30 +; AVX512-FCP-NEXT: vmovdqa 32(%rdx), %xmm7 +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm3 = [6,128,8,128,u,7,128,9,128,11,128,u,10,128,12,128] +; AVX512-FCP-NEXT: vpshufb %xmm3, %xmm7, %xmm8 +; AVX512-FCP-NEXT: vmovdqa64 %xmm3, %xmm29 +; AVX512-FCP-NEXT: vporq %xmm4, %xmm8, %xmm20 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm1[26],zero,ymm1[28],zero,zero,ymm1[27],zero,ymm1[29],zero,ymm1[31],zero,zero,ymm1[30],zero +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm13 = [128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,128,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,128] +; AVX512-FCP-NEXT: # ymm13 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm13, %ymm1, %ymm1 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm1, %zmm21 +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [27,0,128,26,128,28,0,128,0,128,29,128,31,0,128,30,27,0,128,26,128,28,0,128,0,128,29,128,31,0,128,30] +; AVX512-FCP-NEXT: # ymm1 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm1, %ymm0, %ymm4 +; AVX512-FCP-NEXT: vmovdqa64 %ymm1, %ymm28 +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm5 = [19,128,21,0,128,20,128,22,128,24,0,128,23,128,25,0,19,128,21,0,128,20,128,22,128,24,0,128,23,128,25,0] +; AVX512-FCP-NEXT: # ymm5 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm5, %ymm0, %ymm0 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm0, %zmm22 +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm4 = [128,27,128,128,26,128,28,128,30,128,128,29,128,31,128,128,128,27,128,128,26,128,28,128,30,128,128,29,128,31,128,128] +; AVX512-FCP-NEXT: # ymm4 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm4, %ymm11, %ymm0 +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm3 = [128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128] +; AVX512-FCP-NEXT: # ymm3 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm3, %ymm2, %ymm8 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm8, %zmm24 +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm8 = [25,128,27,0,128,26,128,28,128,30,0,128,29,128,31,0,25,128,27,0,128,26,128,28,128,30,0,128,29,128,31,0] +; AVX512-FCP-NEXT: # ymm8 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm8, %ymm2, %ymm0 +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25,18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25] +; AVX512-FCP-NEXT: # ymm1 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm1, %ymm11, %ymm2 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm2, %zmm26 +; AVX512-FCP-NEXT: vmovdqa (%rcx), %ymm2 +; AVX512-FCP-NEXT: vpshufb %ymm10, %ymm2, %ymm0 +; AVX512-FCP-NEXT: vmovdqa (%rdx), %ymm11 +; AVX512-FCP-NEXT: vpshufb %ymm12, %ymm11, %ymm10 +; AVX512-FCP-NEXT: vporq %ymm0, %ymm10, %ymm23 +; AVX512-FCP-NEXT: vpshufb %ymm3, %ymm2, %ymm0 +; AVX512-FCP-NEXT: vpshufb %ymm1, %ymm11, %ymm1 +; AVX512-FCP-NEXT: vporq %ymm0, %ymm1, %ymm25 +; AVX512-FCP-NEXT: vmovdqa (%rsi), %ymm10 +; AVX512-FCP-NEXT: vpshufb %ymm14, %ymm10, %ymm0 +; AVX512-FCP-NEXT: vmovdqa (%rdi), %ymm12 +; AVX512-FCP-NEXT: vpshufb %ymm9, %ymm12, %ymm1 +; AVX512-FCP-NEXT: vporq %ymm0, %ymm1, %ymm27 +; AVX512-FCP-NEXT: vpshufb %ymm13, %ymm12, %ymm0 +; AVX512-FCP-NEXT: vpshufb %ymm5, %ymm10, %ymm1 +; AVX512-FCP-NEXT: vporq %ymm0, %ymm1, %ymm16 +; AVX512-FCP-NEXT: vmovdqa (%rdi), %xmm9 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm0 = xmm9[8],zero,xmm9[u,7],zero,xmm9[9],zero,xmm9[u],zero,xmm9[u,10],zero,xmm9[12],zero,xmm9[u,11] +; AVX512-FCP-NEXT: vmovdqa (%rsi), %xmm14 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm1 = zero,xmm14[8,u],zero,xmm14[7],zero,xmm14[9,u,11,u],zero,xmm14[10],zero,xmm14[12,u],zero +; AVX512-FCP-NEXT: vpor %xmm0, %xmm1, %xmm3 +; AVX512-FCP-NEXT: vmovdqa (%rcx), %xmm13 +; AVX512-FCP-NEXT: vmovdqa64 %xmm30, %xmm0 +; AVX512-FCP-NEXT: vpshufb %xmm0, %xmm13, %xmm1 +; AVX512-FCP-NEXT: vmovdqa (%rdx), %xmm0 +; AVX512-FCP-NEXT: vmovdqa64 %xmm29, %xmm5 +; AVX512-FCP-NEXT: vpshufb %xmm5, %xmm0, %xmm5 +; AVX512-FCP-NEXT: vpor %xmm1, %xmm5, %xmm5 +; AVX512-FCP-NEXT: vpshufb %ymm4, %ymm11, %ymm1 +; AVX512-FCP-NEXT: vpshufb %ymm8, %ymm2, %ymm2 +; AVX512-FCP-NEXT: vpor %ymm1, %ymm2, %ymm11 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm12[26],zero,ymm12[28],zero,zero,ymm12[27],zero,ymm12[29],zero,ymm12[31],zero,zero,ymm12[30],zero +; AVX512-FCP-NEXT: vmovdqa64 %ymm28, %ymm2 +; AVX512-FCP-NEXT: vpshufb %ymm2, %ymm10, %ymm2 ; AVX512-FCP-NEXT: vmovdqa 32(%r8), %ymm8 -; AVX512-FCP-NEXT: vpermd %ymm8, %ymm11, %ymm11 -; AVX512-FCP-NEXT: vmovdqa64 {{.*#+}} zmm25 = [255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255] -; AVX512-FCP-NEXT: vpandnq %ymm11, %ymm25, %ymm11 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm0 = [12,128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128] -; AVX512-FCP-NEXT: vpshufb %ymm0, %ymm8, %ymm13 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm13, %zmm11, %zmm26 -; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} zmm31 = [4,6,5,5,5,5,4,6,30,30,30,30,31,31,31,31] -; AVX512-FCP-NEXT: vmovdqa64 {{.*#+}} zmm30 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0] -; AVX512-FCP-NEXT: vmovdqa (%r8), %ymm11 -; AVX512-FCP-NEXT: vpermd %ymm11, %ymm31, %ymm27 -; AVX512-FCP-NEXT: vpandnq %ymm27, %ymm30, %ymm27 -; AVX512-FCP-NEXT: vpshufb %ymm0, %ymm11, %ymm0 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm27, %zmm0, %zmm27 -; AVX512-FCP-NEXT: vpbroadcastq {{.*#+}} ymm0 = [9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12] -; AVX512-FCP-NEXT: vpshufb %ymm0, %ymm7, %ymm7 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm13 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm4[19],zero,ymm4[21],zero,zero,ymm4[20],zero,ymm4[22],zero,ymm4[24],zero,zero,ymm4[23],zero -; AVX512-FCP-NEXT: vpshufb %ymm0, %ymm4, %ymm5 -; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm0 = [18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25,18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25] -; AVX512-FCP-NEXT: # ymm0 = mem[0,1,0,1] -; AVX512-FCP-NEXT: vpshufb %ymm0, %ymm9, %ymm9 -; AVX512-FCP-NEXT: vpshufb %ymm0, %ymm14, %ymm4 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm14 = ymm14[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm14[27],zero,zero,ymm14[26],zero,ymm14[28],zero,ymm14[30],zero,zero,ymm14[29],zero,ymm14[31],zero,zero -; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm10 = xmm12[0],xmm10[0],xmm12[1],xmm10[1],xmm12[2],xmm10[2],xmm12[3],xmm10[3],xmm12[4],xmm10[4],xmm12[5],xmm10[5],xmm12[6],xmm10[6],xmm12[7],xmm10[7] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm15[3,u,5,u,u,4,u,6,u,8,u,u,7,u,9,u,19,u,21,u,u,20,u,22,u,24,u,u,23,u,25,u] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm15 = ymm15[11,u,u,10,u,12,u,u,u,u,13,u,15,u,u,14,27,u,u,26,u,28,u,u,u,u,29,u,31,u,u,30] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[21],zero,zero,ymm6[20],zero,ymm6[22],zero,ymm6[24],zero,zero,ymm6[23],zero,ymm6[25],zero,zero -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm6 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm6[26],zero,ymm6[28],zero,zero,ymm6[27],zero,ymm6[29],zero,ymm6[31],zero,zero,ymm6[30],zero -; AVX512-FCP-NEXT: vmovdqa64 %xmm19, %xmm1 -; AVX512-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload -; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] -; AVX512-FCP-NEXT: vmovdqa64 %xmm16, %xmm1 -; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm3 = xmm1[0],xmm3[0],xmm1[1],xmm3[1],xmm1[2],xmm3[2],xmm1[3],xmm3[3],xmm1[4],xmm3[4],xmm1[5],xmm3[5],xmm1[6],xmm3[6],xmm1[7],xmm3[7] -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm1 = [0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] -; AVX512-FCP-NEXT: vpshufb %xmm1, %xmm0, %xmm0 -; AVX512-FCP-NEXT: vpshufb %xmm1, %xmm3, %xmm1 -; AVX512-FCP-NEXT: vinserti32x4 $2, %xmm28, %zmm1, %zmm28 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm7[2,2,3,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm9[2,2,3,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm13[2,2,3,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,2,3,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,2,3,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm5[2,2,3,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm14 = ymm14[2,2,3,3] -; AVX512-FCP-NEXT: vmovdqa64 %xmm18, %xmm3 -; AVX512-FCP-NEXT: vmovdqa64 %xmm17, %xmm5 -; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm5 = xmm3[0],xmm5[0],xmm3[1],xmm5[1],xmm3[2],xmm5[2],xmm3[3],xmm5[3],xmm3[4],xmm5[4],xmm3[5],xmm5[5],xmm3[6],xmm5[6],xmm3[7],xmm5[7] -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm3 = [2,u,1,0,5,4,u,3,u,7,6,11,10,u,9,8] -; AVX512-FCP-NEXT: vpshufb %xmm3, %xmm10, %xmm10 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[0,0,1,1] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,2,3,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,2,3,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,0,1,1] -; AVX512-FCP-NEXT: vpshufb %xmm3, %xmm5, %xmm3 -; AVX512-FCP-NEXT: vinserti32x4 $2, %xmm29, %zmm3, %zmm3 +; AVX512-FCP-NEXT: vpor %ymm1, %ymm2, %ymm1 +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm4 = [12,128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128] +; AVX512-FCP-NEXT: vpshufb %ymm4, %ymm8, %ymm2 +; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} ymm10 = [1,1,2,2,2,2,2,2] +; AVX512-FCP-NEXT: vpermd %ymm8, %ymm10, %ymm10 +; AVX512-FCP-NEXT: vmovdqa64 {{.*#+}} zmm12 = [255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255] +; AVX512-FCP-NEXT: vpandn %ymm10, %ymm12, %ymm10 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm10, %zmm2 +; AVX512-FCP-NEXT: vmovdqa (%r8), %ymm10 +; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} zmm28 = [4,6,5,5,5,5,4,6,30,30,30,30,31,31,31,31] +; AVX512-FCP-NEXT: vmovdqa64 {{.*#+}} zmm29 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0] +; AVX512-FCP-NEXT: vpermd %ymm10, %ymm28, %ymm30 +; AVX512-FCP-NEXT: vpandnq %ymm30, %ymm29, %ymm30 +; AVX512-FCP-NEXT: vpshufb %ymm4, %ymm10, %ymm4 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm30, %zmm4, %zmm4 +; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm9 = xmm9[0],xmm14[0],xmm9[1],xmm14[1],xmm9[2],xmm14[2],xmm9[3],xmm14[3],xmm9[4],xmm14[4],xmm9[5],xmm14[5],xmm9[6],xmm14[6],xmm9[7],xmm14[7] +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm14 = [0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] +; AVX512-FCP-NEXT: vpshufb %xmm14, %xmm9, %xmm9 +; AVX512-FCP-NEXT: vinserti32x4 $2, %xmm3, %zmm9, %zmm3 +; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm13[0],xmm0[0],xmm13[1],xmm0[1],xmm13[2],xmm0[2],xmm13[3],xmm0[3],xmm13[4],xmm0[4],xmm13[5],xmm0[5],xmm13[6],xmm0[6],xmm13[7],xmm0[7] +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm9 = [2,u,1,0,5,4,u,3,u,7,6,11,10,u,9,8] +; AVX512-FCP-NEXT: vpshufb %xmm9, %xmm0, %xmm0 +; AVX512-FCP-NEXT: vinserti32x4 $2, %xmm5, %zmm0, %zmm0 ; AVX512-FCP-NEXT: vmovdqa64 (%r8), %zmm5 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm5, %zmm11 -; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm21 = zmm21[2,2,3,3,6,6,7,7] -; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm22 = zmm22[2,2,3,3,6,6,7,7] -; AVX512-FCP-NEXT: vmovdqa64 {{.*#+}} zmm29 = [18374966859431608575,18374966859431608575,18446463693966278400,18446463693966278400,72056498804555775,72056498804555775,18374967950370078975,18374967950370078975] -; AVX512-FCP-NEXT: vpternlogq $248, %zmm29, %zmm21, %zmm22 -; AVX512-FCP-NEXT: vpandq %ymm29, %ymm1, %ymm1 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm7, %zmm1 -; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm7 = zmm23[2,2,3,3,6,6,7,7] -; AVX512-FCP-NEXT: vporq %zmm7, %zmm1, %zmm1 -; AVX512-FCP-NEXT: vmovdqa64 {{.*#+}} zmm7 = [0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255] -; AVX512-FCP-NEXT: vpternlogq $226, %zmm22, %zmm7, %zmm1 -; AVX512-FCP-NEXT: vpermt2d %zmm5, %zmm31, %zmm8 -; AVX512-FCP-NEXT: vpternlogd $184, %zmm1, %zmm30, %zmm8 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm5, %zmm10 +; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm6 = xmm6[0],xmm7[0],xmm6[1],xmm7[1],xmm6[2],xmm7[2],xmm6[3],xmm7[3],xmm6[4],xmm7[4],xmm6[5],xmm7[5],xmm6[6],xmm7[6],xmm6[7],xmm7[7] +; AVX512-FCP-NEXT: vpshufb %xmm9, %xmm6, %xmm6 +; AVX512-FCP-NEXT: vpmovsxbq {{.*#+}} zmm7 = [2,2,3,3,8,8,9,9] +; AVX512-FCP-NEXT: vpermt2q %zmm6, %zmm7, %zmm11 +; AVX512-FCP-NEXT: vmovdqa64 %xmm31, %xmm6 +; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm6 = xmm6[0],xmm15[0],xmm6[1],xmm15[1],xmm6[2],xmm15[2],xmm6[3],xmm15[3],xmm6[4],xmm15[4],xmm6[5],xmm15[5],xmm6[6],xmm15[6],xmm6[7],xmm15[7] +; AVX512-FCP-NEXT: vpshufb %xmm14, %xmm6, %xmm6 +; AVX512-FCP-NEXT: vpermt2q %zmm6, %zmm7, %zmm1 +; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm6 = zmm21[2,2,3,3,6,6,7,7] +; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm7 = zmm22[2,2,3,3,6,6,7,7] +; AVX512-FCP-NEXT: vporq %zmm6, %zmm7, %zmm6 +; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm7 = zmm24[2,2,3,3,6,6,7,7] +; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm9 = zmm26[2,2,3,3,6,6,7,7] +; AVX512-FCP-NEXT: vporq %zmm7, %zmm9, %zmm7 +; AVX512-FCP-NEXT: vmovdqa64 {{.*#+}} zmm9 = [0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255] +; AVX512-FCP-NEXT: vpternlogq $226, %zmm6, %zmm9, %zmm7 +; AVX512-FCP-NEXT: vpermt2d %zmm5, %zmm28, %zmm8 +; AVX512-FCP-NEXT: vpternlogd $184, %zmm7, %zmm29, %zmm8 ; AVX512-FCP-NEXT: vmovdqa64 %zmm8, 256(%r9) -; AVX512-FCP-NEXT: vpermq $80, {{[-0-9]+}}(%r{{[sb]}}p), %ymm1 # 32-byte Folded Reload -; AVX512-FCP-NEXT: # ymm1 = mem[0,0,1,1] -; AVX512-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm1, %zmm1 # 32-byte Folded Reload -; AVX512-FCP-NEXT: vpermq $80, {{[-0-9]+}}(%r{{[sb]}}p), %ymm8 # 32-byte Folded Reload -; AVX512-FCP-NEXT: # ymm8 = mem[0,0,1,1] -; AVX512-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm8, %zmm8 # 32-byte Folded Reload -; AVX512-FCP-NEXT: vmovdqa64 {{.*#+}} zmm16 = [255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0] -; AVX512-FCP-NEXT: vpternlogq $226, %zmm1, %zmm16, %zmm8 -; AVX512-FCP-NEXT: vpternlogq $248, %zmm25, %zmm8, %zmm26 -; AVX512-FCP-NEXT: vpor %ymm4, %ymm9, %ymm1 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm24, %zmm1 -; AVX512-FCP-NEXT: vpternlogq $248, %ymm29, %ymm12, %ymm2 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm20, %zmm2 -; AVX512-FCP-NEXT: vpternlogq $226, %zmm1, %zmm16, %zmm2 -; AVX512-FCP-NEXT: vpternlogq $248, %ymm29, %ymm13, %ymm14 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm14, %zmm1 -; AVX512-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm15, %ymm6 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm6, %zmm0 -; AVX512-FCP-NEXT: vpternlogq $226, %zmm1, %zmm7, %zmm0 -; AVX512-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm27 -; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [6,6,6,0,7,7,7,7,0,8,8,8,8,0,9,9] -; AVX512-FCP-NEXT: vpermd %zmm5, %zmm1, %zmm1 -; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm1 -; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm0 = zmm28[0,0,1,1,4,4,5,5] -; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm2 = zmm3[0,0,1,1,4,4,5,5] -; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm2 -; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} zmm0 = [0,0,0,0,0,0,1,1,9,9,0,10,10,10,10,0] -; AVX512-FCP-NEXT: vpermd %zmm11, %zmm0, %zmm0 -; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm0 -; AVX512-FCP-NEXT: vmovdqa64 %zmm27, 64(%r9) -; AVX512-FCP-NEXT: vmovdqa64 %zmm0, (%r9) -; AVX512-FCP-NEXT: vmovdqa64 %zmm1, 128(%r9) -; AVX512-FCP-NEXT: vmovdqa64 %zmm26, 192(%r9) -; AVX512-FCP-NEXT: addq $24, %rsp +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm18[0,0,1,1] +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm17, %zmm6, %zmm6 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm20[0,0,1,1] +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm19, %zmm7, %zmm7 +; AVX512-FCP-NEXT: vmovdqa64 {{.*#+}} zmm8 = [255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0] +; AVX512-FCP-NEXT: vpternlogq $226, %zmm6, %zmm8, %zmm7 +; AVX512-FCP-NEXT: vpternlogq $248, %zmm12, %zmm7, %zmm2 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm25[2,2,3,3] +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm6, %zmm23, %zmm6 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm16[2,2,3,3] +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm27, %zmm7 +; AVX512-FCP-NEXT: vpternlogq $226, %zmm6, %zmm8, %zmm7 +; AVX512-FCP-NEXT: vpternlogq $226, %zmm11, %zmm9, %zmm1 +; AVX512-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm7, %zmm4 +; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm3 = zmm3[0,0,1,1,4,4,5,5] +; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm0 = zmm0[0,0,1,1,4,4,5,5] +; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm3, %zmm0 +; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} zmm3 = [0,0,0,0,0,0,1,1,9,9,0,10,10,10,10,0] +; AVX512-FCP-NEXT: vpermd %zmm10, %zmm3, %zmm3 +; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm3 +; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} zmm0 = [6,6,6,0,7,7,7,7,0,8,8,8,8,0,9,9] +; AVX512-FCP-NEXT: vpermd %zmm5, %zmm0, %zmm0 +; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm0 +; AVX512-FCP-NEXT: vmovdqa64 %zmm0, 128(%r9) +; AVX512-FCP-NEXT: vmovdqa64 %zmm4, 64(%r9) +; AVX512-FCP-NEXT: vmovdqa64 %zmm3, (%r9) +; AVX512-FCP-NEXT: vmovdqa64 %zmm2, 192(%r9) ; AVX512-FCP-NEXT: vzeroupper ; AVX512-FCP-NEXT: retq ; ; AVX512DQ-LABEL: store_i8_stride5_vf64: ; AVX512DQ: # %bb.0: -; AVX512DQ-NEXT: vmovdqa 32(%rsi), %ymm3 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm15 = [128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128,128,128] -; AVX512DQ-NEXT: vpshufb %ymm15, %ymm3, %ymm0 -; AVX512DQ-NEXT: vmovdqa 32(%rdi), %ymm2 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm9 = [12,13,128,15,12,13,14,128,12,13,14,15,128,u,u,u,16,128,18,19,16,17,128,19,16,17,18,128,16,17,18,19] -; AVX512DQ-NEXT: vpshufb %ymm9, %ymm2, %ymm1 +; AVX512DQ-NEXT: vmovdqa 32(%rsi), %ymm11 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm1 = [128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128,128,128] +; AVX512DQ-NEXT: vpshufb %ymm1, %ymm11, %ymm0 +; AVX512DQ-NEXT: vmovdqa64 %ymm1, %ymm18 +; AVX512DQ-NEXT: vmovdqa 32(%rdi), %ymm5 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm2 = [12,13,128,15,12,13,14,128,12,13,14,15,128,u,u,u,16,128,18,19,16,17,128,19,16,17,18,128,16,17,18,19] +; AVX512DQ-NEXT: vpshufb %ymm2, %ymm5, %ymm1 +; AVX512DQ-NEXT: vmovdqa64 %ymm2, %ymm19 +; AVX512DQ-NEXT: vporq %ymm0, %ymm1, %ymm20 +; AVX512DQ-NEXT: vmovdqa 32(%rdi), %xmm12 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm1 = [8,128,u,7,128,9,128,u,128,u,10,128,12,128,u,11] +; AVX512DQ-NEXT: vpshufb %xmm1, %xmm12, %xmm0 +; AVX512DQ-NEXT: vmovdqa64 %xmm1, %xmm28 +; AVX512DQ-NEXT: vmovdqa 32(%rsi), %xmm10 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm2 = [128,8,u,128,7,128,9,u,11,u,128,10,128,12,u,128] +; AVX512DQ-NEXT: vpshufb %xmm2, %xmm10, %xmm1 +; AVX512DQ-NEXT: vmovdqa64 %xmm2, %xmm29 +; AVX512DQ-NEXT: vporq %xmm0, %xmm1, %xmm21 +; AVX512DQ-NEXT: vmovdqa 32(%rcx), %ymm15 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm8 = [128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128] +; AVX512DQ-NEXT: vpshufb %ymm8, %ymm15, %ymm0 +; AVX512DQ-NEXT: vmovdqa 32(%rdx), %ymm13 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm3 = [u,u,12,13,128,u,u,u,14,128,u,u,14,15,128,u,u,u,16,128,u,u,16,17,128,u,u,u,18,128,u,u] +; AVX512DQ-NEXT: vpshufb %ymm3, %ymm13, %ymm1 +; AVX512DQ-NEXT: vporq %ymm0, %ymm1, %ymm22 +; AVX512DQ-NEXT: vmovdqa 32(%rcx), %xmm6 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm1 = [128,6,128,8,u,128,7,128,9,128,11,u,128,10,128,12] +; AVX512DQ-NEXT: vpshufb %xmm1, %xmm6, %xmm0 +; AVX512DQ-NEXT: vmovdqa64 %xmm1, %xmm30 +; AVX512DQ-NEXT: vmovdqa 32(%rdx), %xmm7 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm2 = [6,128,8,128,u,7,128,9,128,11,128,u,10,128,12,128] +; AVX512DQ-NEXT: vpshufb %xmm2, %xmm7, %xmm1 +; AVX512DQ-NEXT: vmovdqa64 %xmm2, %xmm31 +; AVX512DQ-NEXT: vporq %xmm0, %xmm1, %xmm23 +; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm9 = [128,128,26,128,28,128,128,27,128,29,128,31,128,128,30,128,128,128,26,128,28,128,128,27,128,29,128,31,128,128,30,128] +; AVX512DQ-NEXT: # ymm9 = mem[0,1,0,1] +; AVX512DQ-NEXT: vpshufb %ymm9, %ymm5, %ymm0 +; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm4 = [128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,128,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,128] +; AVX512DQ-NEXT: # ymm4 = mem[0,1,0,1] +; AVX512DQ-NEXT: vpshufb %ymm4, %ymm5, %ymm1 +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm24 +; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm5 = [27,0,128,26,128,28,0,128,0,128,29,128,31,0,128,30,27,0,128,26,128,28,0,128,0,128,29,128,31,0,128,30] +; AVX512DQ-NEXT: # ymm5 = mem[0,1,0,1] +; AVX512DQ-NEXT: vpshufb %ymm5, %ymm11, %ymm1 +; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [19,128,21,0,128,20,128,22,128,24,0,128,23,128,25,0,19,128,21,0,128,20,128,22,128,24,0,128,23,128,25,0] +; AVX512DQ-NEXT: # ymm2 = mem[0,1,0,1] +; AVX512DQ-NEXT: vpshufb %ymm2, %ymm11, %ymm11 +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm1, %zmm11, %zmm26 +; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm11 = [128,27,128,128,26,128,28,128,30,128,128,29,128,31,128,128,128,27,128,128,26,128,28,128,30,128,128,29,128,31,128,128] +; AVX512DQ-NEXT: # ymm11 = mem[0,1,0,1] +; AVX512DQ-NEXT: vpshufb %ymm11, %ymm13, %ymm1 +; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm0 = [128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128] +; AVX512DQ-NEXT: # ymm0 = mem[0,1,0,1] +; AVX512DQ-NEXT: vpshufb %ymm0, %ymm15, %ymm14 +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm1, %zmm14, %zmm25 +; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [25,128,27,0,128,26,128,28,128,30,0,128,29,128,31,0,25,128,27,0,128,26,128,28,128,30,0,128,29,128,31,0] +; AVX512DQ-NEXT: # ymm1 = mem[0,1,0,1] +; AVX512DQ-NEXT: vpshufb %ymm1, %ymm15, %ymm14 +; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm15 = [18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25,18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25] +; AVX512DQ-NEXT: # ymm15 = mem[0,1,0,1] +; AVX512DQ-NEXT: vpshufb %ymm15, %ymm13, %ymm13 +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm14, %zmm13, %zmm27 +; AVX512DQ-NEXT: vmovdqa (%rcx), %ymm13 +; AVX512DQ-NEXT: vpshufb %ymm8, %ymm13, %ymm8 +; AVX512DQ-NEXT: vmovdqa (%rdx), %ymm14 +; AVX512DQ-NEXT: vpshufb %ymm3, %ymm14, %ymm3 +; AVX512DQ-NEXT: vporq %ymm8, %ymm3, %ymm16 +; AVX512DQ-NEXT: vpshufb %ymm0, %ymm13, %ymm0 +; AVX512DQ-NEXT: vpshufb %ymm15, %ymm14, %ymm3 +; AVX512DQ-NEXT: vporq %ymm0, %ymm3, %ymm17 +; AVX512DQ-NEXT: vmovdqa (%rsi), %ymm3 +; AVX512DQ-NEXT: vmovdqa64 %ymm18, %ymm0 +; AVX512DQ-NEXT: vpshufb %ymm0, %ymm3, %ymm0 +; AVX512DQ-NEXT: vmovdqa (%rdi), %ymm8 +; AVX512DQ-NEXT: vmovdqa64 %ymm19, %ymm15 +; AVX512DQ-NEXT: vpshufb %ymm15, %ymm8, %ymm15 +; AVX512DQ-NEXT: vporq %ymm0, %ymm15, %ymm18 +; AVX512DQ-NEXT: vpshufb %ymm4, %ymm8, %ymm0 +; AVX512DQ-NEXT: vpshufb %ymm2, %ymm3, %ymm2 +; AVX512DQ-NEXT: vporq %ymm0, %ymm2, %ymm19 +; AVX512DQ-NEXT: vpshufb %ymm11, %ymm14, %ymm0 +; AVX512DQ-NEXT: vpshufb %ymm1, %ymm13, %ymm1 ; AVX512DQ-NEXT: vpor %ymm0, %ymm1, %ymm0 -; AVX512DQ-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-NEXT: vmovdqa 32(%rdi), %xmm1 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm5 = [8,128,u,7,128,9,128,u,128,u,10,128,12,128,u,11] -; AVX512DQ-NEXT: vpshufb %xmm5, %xmm1, %xmm0 -; AVX512DQ-NEXT: vmovdqa64 %xmm1, %xmm16 -; AVX512DQ-NEXT: vmovdqa 32(%rsi), %xmm4 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm14 = [128,8,u,128,7,128,9,u,11,u,128,10,128,12,u,128] -; AVX512DQ-NEXT: vpshufb %xmm14, %xmm4, %xmm1 -; AVX512DQ-NEXT: vmovdqa64 %xmm4, %xmm31 -; AVX512DQ-NEXT: vpor %xmm0, %xmm1, %xmm0 -; AVX512DQ-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-NEXT: vmovdqa 32(%rcx), %ymm8 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm0 = [128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128] -; AVX512DQ-NEXT: vpshufb %ymm0, %ymm8, %ymm4 -; AVX512DQ-NEXT: vmovdqa 32(%rdx), %ymm11 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm1 = [u,u,12,13,128,u,u,u,14,128,u,u,14,15,128,u,u,u,16,128,u,u,16,17,128,u,u,u,18,128,u,u] -; AVX512DQ-NEXT: vpshufb %ymm1, %ymm11, %ymm10 -; AVX512DQ-NEXT: vpor %ymm4, %ymm10, %ymm4 -; AVX512DQ-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-NEXT: vmovdqa 32(%rcx), %xmm13 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm6 = [128,6,128,8,u,128,7,128,9,128,11,u,128,10,128,12] -; AVX512DQ-NEXT: vpshufb %xmm6, %xmm13, %xmm4 -; AVX512DQ-NEXT: vmovdqa64 %xmm6, %xmm25 -; AVX512DQ-NEXT: vmovdqa 32(%rdx), %xmm10 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm6 = [6,128,8,128,u,7,128,9,128,11,128,u,10,128,12,128] -; AVX512DQ-NEXT: vpshufb %xmm6, %xmm10, %xmm12 -; AVX512DQ-NEXT: vmovdqa64 %xmm6, %xmm26 -; AVX512DQ-NEXT: vporq %xmm4, %xmm12, %xmm20 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm4 = ymm3[11,u,u,10,u,12,u,u,u,u,13,u,15,u,u,14,27,u,u,26,u,28,u,u,u,u,29,u,31,u,u,30] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[3,u,5,u,u,4,u,6,u,8,u,u,7,u,9,u,19,u,21,u,u,20,u,22,u,24,u,u,23,u,25,u] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm4, %zmm3, %zmm22 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm3 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[26],zero,ymm2[28],zero,zero,ymm2[27],zero,ymm2[29],zero,ymm2[31],zero,zero,ymm2[30],zero -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[21],zero,zero,ymm2[20],zero,ymm2[22],zero,ymm2[24],zero,zero,ymm2[23],zero,ymm2[25],zero,zero -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm3, %zmm2, %zmm23 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm2 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm11[27],zero,zero,ymm11[26],zero,ymm11[28],zero,ymm11[30],zero,zero,ymm11[29],zero,ymm11[31],zero,zero -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm3 = ymm8[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm8[19],zero,ymm8[21],zero,zero,ymm8[20],zero,ymm8[22],zero,ymm8[24],zero,zero,ymm8[23],zero -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm24 -; AVX512DQ-NEXT: vmovdqa (%rcx), %ymm12 -; AVX512DQ-NEXT: vpshufb %ymm0, %ymm12, %ymm0 -; AVX512DQ-NEXT: vmovdqa (%rdx), %ymm6 -; AVX512DQ-NEXT: vpshufb %ymm1, %ymm6, %ymm1 -; AVX512DQ-NEXT: vporq %ymm0, %ymm1, %ymm19 -; AVX512DQ-NEXT: vmovdqa (%rsi), %ymm7 -; AVX512DQ-NEXT: vpshufb %ymm15, %ymm7, %ymm2 -; AVX512DQ-NEXT: vmovdqa (%rdi), %ymm4 -; AVX512DQ-NEXT: vpshufb %ymm9, %ymm4, %ymm3 -; AVX512DQ-NEXT: vporq %ymm2, %ymm3, %ymm21 -; AVX512DQ-NEXT: vmovdqa (%rdi), %xmm0 -; AVX512DQ-NEXT: vpshufb %xmm5, %xmm0, %xmm3 -; AVX512DQ-NEXT: vmovdqa64 %xmm0, %xmm17 -; AVX512DQ-NEXT: vmovdqa (%rsi), %xmm5 -; AVX512DQ-NEXT: vpshufb %xmm14, %xmm5, %xmm9 -; AVX512DQ-NEXT: vporq %xmm3, %xmm9, %xmm27 -; AVX512DQ-NEXT: vmovdqa (%rcx), %xmm1 -; AVX512DQ-NEXT: vmovdqa64 %xmm25, %xmm0 -; AVX512DQ-NEXT: vpshufb %xmm0, %xmm1, %xmm0 -; AVX512DQ-NEXT: vmovdqa64 %xmm1, %xmm18 -; AVX512DQ-NEXT: vmovdqa (%rdx), %xmm9 -; AVX512DQ-NEXT: vmovdqa64 %xmm26, %xmm1 -; AVX512DQ-NEXT: vpshufb %xmm1, %xmm9, %xmm15 -; AVX512DQ-NEXT: vporq %xmm0, %xmm15, %xmm29 -; AVX512DQ-NEXT: vpshufd {{.*#+}} xmm0 = mem[1,1,2,2] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,1,1,1] +; AVX512DQ-NEXT: vpshufb %ymm9, %ymm8, %ymm1 +; AVX512DQ-NEXT: vpshufb %ymm5, %ymm3, %ymm2 +; AVX512DQ-NEXT: vmovdqa (%rdi), %xmm5 +; AVX512DQ-NEXT: vpor %ymm1, %ymm2, %ymm1 +; AVX512DQ-NEXT: vmovdqa (%rsi), %xmm9 +; AVX512DQ-NEXT: vmovdqa (%rcx), %xmm8 +; AVX512DQ-NEXT: vmovdqa64 %xmm28, %xmm2 +; AVX512DQ-NEXT: vpshufb %xmm2, %xmm5, %xmm2 +; AVX512DQ-NEXT: vmovdqa64 %xmm29, %xmm3 +; AVX512DQ-NEXT: vpshufb %xmm3, %xmm9, %xmm3 +; AVX512DQ-NEXT: vpor %xmm2, %xmm3, %xmm4 +; AVX512DQ-NEXT: vmovdqa (%rdx), %xmm3 +; AVX512DQ-NEXT: vmovdqa 32(%r8), %ymm11 +; AVX512DQ-NEXT: vmovdqa64 %xmm30, %xmm2 +; AVX512DQ-NEXT: vpshufb %xmm2, %xmm8, %xmm2 +; AVX512DQ-NEXT: vmovdqa64 %xmm31, %xmm13 +; AVX512DQ-NEXT: vpshufb %xmm13, %xmm3, %xmm13 +; AVX512DQ-NEXT: vpor %xmm2, %xmm13, %xmm13 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm14 = [12,128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128] +; AVX512DQ-NEXT: vpshufb %ymm14, %ymm11, %ymm2 +; AVX512DQ-NEXT: vpshufd {{.*#+}} xmm15 = mem[1,1,2,2] +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm15 = ymm15[0,1,1,1] ; AVX512DQ-NEXT: vmovdqa64 {{.*#+}} zmm28 = [255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255] -; AVX512DQ-NEXT: vpandnq %ymm0, %ymm28, %ymm0 -; AVX512DQ-NEXT: vmovdqa 32(%r8), %ymm15 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm1 = [12,128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128] -; AVX512DQ-NEXT: vpshufb %ymm1, %ymm15, %ymm14 -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm14, %zmm0, %zmm26 -; AVX512DQ-NEXT: vmovdqa (%r8), %ymm0 -; AVX512DQ-NEXT: vpshufb %ymm1, %ymm0, %ymm1 -; AVX512DQ-NEXT: vpshufd {{.*#+}} ymm0 = ymm0[0,2,1,1,4,6,5,5] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,3,2] -; AVX512DQ-NEXT: vmovdqa64 {{.*#+}} zmm30 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0] -; AVX512DQ-NEXT: vpandnq %ymm0, %ymm30, %ymm0 -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm25 -; AVX512DQ-NEXT: vpbroadcastq {{.*#+}} ymm0 = [9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12] -; AVX512DQ-NEXT: vpshufb %ymm0, %ymm8, %ymm8 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm14 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm12[19],zero,ymm12[21],zero,zero,ymm12[20],zero,ymm12[22],zero,ymm12[24],zero,zero,ymm12[23],zero -; AVX512DQ-NEXT: vpshufb %ymm0, %ymm12, %ymm12 -; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm0 = [18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25,18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25] -; AVX512DQ-NEXT: # ymm0 = mem[0,1,0,1] -; AVX512DQ-NEXT: vpshufb %ymm0, %ymm11, %ymm11 -; AVX512DQ-NEXT: vpshufb %ymm0, %ymm6, %ymm2 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm6 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[27],zero,zero,ymm6[26],zero,ymm6[28],zero,ymm6[30],zero,zero,ymm6[29],zero,ymm6[31],zero,zero -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm10 = xmm13[0],xmm10[0],xmm13[1],xmm10[1],xmm13[2],xmm10[2],xmm13[3],xmm10[3],xmm13[4],xmm10[4],xmm13[5],xmm10[5],xmm13[6],xmm10[6],xmm13[7],xmm10[7] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm13 = ymm7[3,u,5,u,u,4,u,6,u,8,u,u,7,u,9,u,19,u,21,u,u,20,u,22,u,24,u,u,23,u,25,u] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm7 = ymm7[11,u,u,10,u,12,u,u,u,u,13,u,15,u,u,14,27,u,u,26,u,28,u,u,u,u,29,u,31,u,u,30] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm0 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm4[21],zero,zero,ymm4[20],zero,ymm4[22],zero,ymm4[24],zero,zero,ymm4[23],zero,ymm4[25],zero,zero -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm3 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm4[26],zero,ymm4[28],zero,zero,ymm4[27],zero,ymm4[29],zero,ymm4[31],zero,zero,ymm4[30],zero -; AVX512DQ-NEXT: vmovdqa64 %xmm16, %xmm1 -; AVX512DQ-NEXT: vmovdqa64 %xmm31, %xmm4 -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm4 = xmm1[0],xmm4[0],xmm1[1],xmm4[1],xmm1[2],xmm4[2],xmm1[3],xmm4[3],xmm1[4],xmm4[4],xmm1[5],xmm4[5],xmm1[6],xmm4[6],xmm1[7],xmm4[7] -; AVX512DQ-NEXT: vpmovsxbd {{.*#+}} zmm1 = [4,0,5,5,5,5,0,6,6,6,6,0,7,7,7,7] -; AVX512DQ-NEXT: vpermd %zmm15, %zmm1, %zmm31 -; AVX512DQ-NEXT: vmovdqa64 (%r8), %zmm16 -; AVX512DQ-NEXT: vpmovsxbd {{.*#+}} zmm1 = [6,6,6,0,7,7,7,7,0,16,16,16,16,0,17,17] -; AVX512DQ-NEXT: vpermi2d %zmm15, %zmm16, %zmm1 -; AVX512DQ-NEXT: vmovdqa64 %xmm17, %xmm15 -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm5 = xmm15[0],xmm5[0],xmm15[1],xmm5[1],xmm15[2],xmm5[2],xmm15[3],xmm5[3],xmm15[4],xmm5[4],xmm15[5],xmm5[5],xmm15[6],xmm5[6],xmm15[7],xmm5[7] -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm15 = [0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] -; AVX512DQ-NEXT: vpshufb %xmm15, %xmm4, %xmm4 -; AVX512DQ-NEXT: vpshufb %xmm15, %xmm5, %xmm5 -; AVX512DQ-NEXT: vinserti32x4 $2, %xmm27, %zmm5, %zmm5 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,2,3,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm14 = ymm14[2,2,3,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,2,3,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,2,3,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,2,3,3] -; AVX512DQ-NEXT: vmovdqa64 %xmm18, %xmm15 -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm9 = xmm15[0],xmm9[0],xmm15[1],xmm9[1],xmm15[2],xmm9[2],xmm15[3],xmm9[3],xmm15[4],xmm9[4],xmm15[5],xmm9[5],xmm15[6],xmm9[6],xmm15[7],xmm9[7] -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm15 = [2,u,1,0,5,4,u,3,u,7,6,11,10,u,9,8] -; AVX512DQ-NEXT: vpshufb %xmm15, %xmm10, %xmm10 +; AVX512DQ-NEXT: vpandnq %ymm15, %ymm28, %ymm15 +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm2, %zmm15, %zmm2 +; AVX512DQ-NEXT: vmovdqa (%r8), %ymm15 +; AVX512DQ-NEXT: vpshufb %ymm14, %ymm15, %ymm14 +; AVX512DQ-NEXT: vpshufd {{.*#+}} ymm15 = ymm15[0,2,1,1,4,6,5,5] +; AVX512DQ-NEXT: vmovdqa64 {{.*#+}} zmm29 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0] +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,3,3,2] +; AVX512DQ-NEXT: vpandnq %ymm15, %ymm29, %ymm15 +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm15, %zmm14, %zmm14 +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm6 = xmm6[0],xmm7[0],xmm6[1],xmm7[1],xmm6[2],xmm7[2],xmm6[3],xmm7[3],xmm6[4],xmm7[4],xmm6[5],xmm7[5],xmm6[6],xmm7[6],xmm6[7],xmm7[7] +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm7 = [2,u,1,0,5,4,u,3,u,7,6,11,10,u,9,8] +; AVX512DQ-NEXT: vpshufb %xmm7, %xmm6, %xmm6 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm6 = ymm6[0,0,1,1] +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm10 = xmm12[0],xmm10[0],xmm12[1],xmm10[1],xmm12[2],xmm10[2],xmm12[3],xmm10[3],xmm12[4],xmm10[4],xmm12[5],xmm10[5],xmm12[6],xmm10[6],xmm12[7],xmm10[7] +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm12 = [0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] +; AVX512DQ-NEXT: vpshufb %xmm12, %xmm10, %xmm10 ; AVX512DQ-NEXT: vpermq {{.*#+}} ymm10 = ymm10[0,0,1,1] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,3,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm4 = ymm4[0,0,1,1] -; AVX512DQ-NEXT: vpshufb %xmm15, %xmm9, %xmm9 -; AVX512DQ-NEXT: vinserti32x4 $2, %xmm29, %zmm9, %zmm9 -; AVX512DQ-NEXT: vpermq $80, {{[-0-9]+}}(%r{{[sb]}}p), %ymm15 # 32-byte Folded Reload -; AVX512DQ-NEXT: # ymm15 = mem[0,0,1,1] -; AVX512DQ-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm15, %zmm15 # 32-byte Folded Reload -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm17 = ymm20[0,0,1,1] -; AVX512DQ-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm17, %zmm17 # 32-byte Folded Reload -; AVX512DQ-NEXT: vmovdqa64 {{.*#+}} zmm18 = [255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0] -; AVX512DQ-NEXT: vpternlogq $226, %zmm15, %zmm18, %zmm17 -; AVX512DQ-NEXT: vpternlogq $248, %zmm28, %zmm17, %zmm26 -; AVX512DQ-NEXT: vpermq {{.*#+}} zmm15 = zmm22[2,2,3,3,6,6,7,7] -; AVX512DQ-NEXT: vpermq {{.*#+}} zmm17 = zmm23[2,2,3,3,6,6,7,7] -; AVX512DQ-NEXT: vmovdqa64 {{.*#+}} zmm20 = [18374966859431608575,18374966859431608575,18446463693966278400,18446463693966278400,72056498804555775,72056498804555775,18374967950370078975,18374967950370078975] -; AVX512DQ-NEXT: vpternlogq $248, %zmm20, %zmm15, %zmm17 -; AVX512DQ-NEXT: vpandq %ymm20, %ymm8, %ymm8 -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm8, %zmm11, %zmm8 -; AVX512DQ-NEXT: vpermq {{.*#+}} zmm11 = zmm24[2,2,3,3,6,6,7,7] -; AVX512DQ-NEXT: vporq %zmm11, %zmm8, %zmm8 -; AVX512DQ-NEXT: vmovdqa64 {{.*#+}} zmm11 = [0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255] -; AVX512DQ-NEXT: vpternlogq $226, %zmm17, %zmm11, %zmm8 -; AVX512DQ-NEXT: vpternlogd $184, %zmm8, %zmm30, %zmm31 -; AVX512DQ-NEXT: vpor %ymm2, %ymm14, %ymm2 -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm2, %zmm19, %zmm2 -; AVX512DQ-NEXT: vpternlogq $248, %ymm20, %ymm13, %ymm0 -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm0, %zmm21, %zmm0 -; AVX512DQ-NEXT: vpternlogq $226, %zmm2, %zmm18, %zmm0 -; AVX512DQ-NEXT: vpternlogq $248, %ymm20, %ymm12, %ymm6 -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm10, %zmm6, %zmm2 -; AVX512DQ-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm7, %ymm3 -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm4, %zmm3, %zmm3 -; AVX512DQ-NEXT: vpternlogq $226, %zmm2, %zmm11, %zmm3 -; AVX512DQ-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm25 -; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm3, %zmm1 -; AVX512DQ-NEXT: vpermq {{.*#+}} zmm0 = zmm5[0,0,1,1,4,4,5,5] -; AVX512DQ-NEXT: vpermq {{.*#+}} zmm2 = zmm9[0,0,1,1,4,4,5,5] -; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm2 +; AVX512DQ-NEXT: vmovdqa64 (%r8), %zmm15 +; AVX512DQ-NEXT: vpmovsxbd {{.*#+}} zmm30 = [4,0,5,5,5,5,0,6,6,6,6,0,7,7,7,7] +; AVX512DQ-NEXT: vpermd %zmm11, %zmm30, %zmm30 +; AVX512DQ-NEXT: vpmovsxbd {{.*#+}} zmm31 = [6,6,6,0,7,7,7,7,0,16,16,16,16,0,17,17] +; AVX512DQ-NEXT: vpermi2d %zmm11, %zmm15, %zmm31 +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm5 = xmm5[0],xmm9[0],xmm5[1],xmm9[1],xmm5[2],xmm9[2],xmm5[3],xmm9[3],xmm5[4],xmm9[4],xmm5[5],xmm9[5],xmm5[6],xmm9[6],xmm5[7],xmm9[7] +; AVX512DQ-NEXT: vpshufb %xmm12, %xmm5, %xmm5 +; AVX512DQ-NEXT: vinserti32x4 $2, %xmm4, %zmm5, %zmm4 +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm3 = xmm8[0],xmm3[0],xmm8[1],xmm3[1],xmm8[2],xmm3[2],xmm8[3],xmm3[3],xmm8[4],xmm3[4],xmm8[5],xmm3[5],xmm8[6],xmm3[6],xmm8[7],xmm3[7] +; AVX512DQ-NEXT: vpshufb %xmm7, %xmm3, %xmm3 +; AVX512DQ-NEXT: vinserti32x4 $2, %xmm13, %zmm3, %zmm3 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm5 = ymm21[0,0,1,1] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm20, %zmm5, %zmm5 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm7 = ymm23[0,0,1,1] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm22, %zmm7, %zmm7 +; AVX512DQ-NEXT: vmovdqa64 {{.*#+}} zmm8 = [255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0] +; AVX512DQ-NEXT: vpternlogq $226, %zmm5, %zmm8, %zmm7 +; AVX512DQ-NEXT: vpternlogq $248, %zmm28, %zmm7, %zmm2 +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm5 = zmm24[2,2,3,3,6,6,7,7] +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm7 = zmm26[2,2,3,3,6,6,7,7] +; AVX512DQ-NEXT: vporq %zmm5, %zmm7, %zmm5 +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm7 = zmm25[2,2,3,3,6,6,7,7] +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm9 = zmm27[2,2,3,3,6,6,7,7] +; AVX512DQ-NEXT: vporq %zmm7, %zmm9, %zmm7 +; AVX512DQ-NEXT: vmovdqa64 {{.*#+}} zmm9 = [0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255] +; AVX512DQ-NEXT: vpternlogq $226, %zmm5, %zmm9, %zmm7 +; AVX512DQ-NEXT: vpternlogd $184, %zmm7, %zmm29, %zmm30 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm5 = ymm17[2,2,3,3] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm5, %zmm16, %zmm5 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm7 = ymm19[2,2,3,3] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm7, %zmm18, %zmm7 +; AVX512DQ-NEXT: vpternlogq $226, %zmm5, %zmm8, %zmm7 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm6, %zmm0, %zmm0 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,2,3,3] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm10, %zmm1, %zmm1 +; AVX512DQ-NEXT: vpternlogq $226, %zmm0, %zmm9, %zmm1 +; AVX512DQ-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm7, %zmm14 +; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm31 +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm0 = zmm4[0,0,1,1,4,4,5,5] +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm1 = zmm3[0,0,1,1,4,4,5,5] +; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm1 ; AVX512DQ-NEXT: vpmovsxbd {{.*#+}} zmm0 = [0,0,0,0,0,0,1,1,1,1,0,2,2,2,2,0] -; AVX512DQ-NEXT: vpermd %zmm16, %zmm0, %zmm0 -; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm0 -; AVX512DQ-NEXT: vmovdqa64 %zmm25, 64(%r9) +; AVX512DQ-NEXT: vpermd %zmm15, %zmm0, %zmm0 +; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm0 +; AVX512DQ-NEXT: vmovdqa64 %zmm14, 64(%r9) ; AVX512DQ-NEXT: vmovdqa64 %zmm0, (%r9) -; AVX512DQ-NEXT: vmovdqa64 %zmm1, 128(%r9) -; AVX512DQ-NEXT: vmovdqa64 %zmm31, 256(%r9) -; AVX512DQ-NEXT: vmovdqa64 %zmm26, 192(%r9) +; AVX512DQ-NEXT: vmovdqa64 %zmm31, 128(%r9) +; AVX512DQ-NEXT: vmovdqa64 %zmm30, 256(%r9) +; AVX512DQ-NEXT: vmovdqa64 %zmm2, 192(%r9) ; AVX512DQ-NEXT: vzeroupper ; AVX512DQ-NEXT: retq ; ; AVX512DQ-FCP-LABEL: store_i8_stride5_vf64: ; AVX512DQ-FCP: # %bb.0: -; AVX512DQ-FCP-NEXT: subq $24, %rsp -; AVX512DQ-FCP-NEXT: vmovdqa 32(%rsi), %ymm3 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm8 = [128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128,128,128] -; AVX512DQ-FCP-NEXT: vpshufb %ymm8, %ymm3, %ymm0 +; AVX512DQ-FCP-NEXT: vmovdqa 32(%rsi), %ymm0 +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm14 = [128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128,128,128] +; AVX512DQ-FCP-NEXT: vpshufb %ymm14, %ymm0, %ymm2 ; AVX512DQ-FCP-NEXT: vmovdqa 32(%rdi), %ymm1 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm11 = [12,13,128,15,12,13,14,128,12,13,14,15,128,u,u,u,16,128,18,19,16,17,128,19,16,17,18,128,16,17,18,19] -; AVX512DQ-FCP-NEXT: vpshufb %ymm11, %ymm1, %ymm2 -; AVX512DQ-FCP-NEXT: vpor %ymm0, %ymm2, %ymm0 -; AVX512DQ-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa 32(%rdi), %xmm0 -; AVX512DQ-FCP-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm5 = [8,128,u,7,128,9,128,u,128,u,10,128,12,128,u,11] -; AVX512DQ-FCP-NEXT: vpshufb %xmm5, %xmm0, %xmm0 -; AVX512DQ-FCP-NEXT: vmovdqa 32(%rsi), %xmm4 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm13 = [128,8,u,128,7,128,9,u,11,u,128,10,128,12,u,128] -; AVX512DQ-FCP-NEXT: vpshufb %xmm13, %xmm4, %xmm2 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm4, %xmm19 -; AVX512DQ-FCP-NEXT: vpor %xmm0, %xmm2, %xmm0 -; AVX512DQ-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa 32(%rcx), %ymm7 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm0 = [128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128] -; AVX512DQ-FCP-NEXT: vpshufb %ymm0, %ymm7, %ymm2 -; AVX512DQ-FCP-NEXT: vmovdqa 32(%rdx), %ymm9 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm15 = [u,u,12,13,128,u,u,u,14,128,u,u,14,15,128,u,u,u,16,128,u,u,16,17,128,u,u,u,18,128,u,u] -; AVX512DQ-FCP-NEXT: vpshufb %ymm15, %ymm9, %ymm4 -; AVX512DQ-FCP-NEXT: vpor %ymm2, %ymm4, %ymm2 -; AVX512DQ-FCP-NEXT: vmovdqu %ymm2, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa 32(%rcx), %xmm12 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm4 = [128,6,128,8,u,128,7,128,9,128,11,u,128,10,128,12] -; AVX512DQ-FCP-NEXT: vpshufb %xmm4, %xmm12, %xmm2 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm4, %xmm25 -; AVX512DQ-FCP-NEXT: vmovdqa 32(%rdx), %xmm10 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm6 = [6,128,8,128,u,7,128,9,128,11,128,u,10,128,12,128] -; AVX512DQ-FCP-NEXT: vpshufb %xmm6, %xmm10, %xmm4 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm6, %xmm26 -; AVX512DQ-FCP-NEXT: vpor %xmm2, %xmm4, %xmm2 -; AVX512DQ-FCP-NEXT: vmovdqu %ymm2, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm3[11,u,u,10,u,12,u,u,u,u,13,u,15,u,u,14,27,u,u,26,u,28,u,u,u,u,29,u,31,u,u,30] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[3,u,5,u,u,4,u,6,u,8,u,u,7,u,9,u,19,u,21,u,u,20,u,22,u,24,u,u,23,u,25,u] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm21 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm1[26],zero,ymm1[28],zero,zero,ymm1[27],zero,ymm1[29],zero,ymm1[31],zero,zero,ymm1[30],zero -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[21],zero,zero,ymm1[20],zero,ymm1[22],zero,ymm1[24],zero,zero,ymm1[23],zero,ymm1[25],zero,zero -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm1, %zmm22 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm9[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm9[27],zero,zero,ymm9[26],zero,ymm9[28],zero,ymm9[30],zero,zero,ymm9[29],zero,ymm9[31],zero,zero -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm7[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm7[19],zero,ymm7[21],zero,zero,ymm7[20],zero,ymm7[22],zero,ymm7[24],zero,zero,ymm7[23],zero -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm23 -; AVX512DQ-FCP-NEXT: vmovdqa (%rcx), %ymm4 -; AVX512DQ-FCP-NEXT: vpshufb %ymm0, %ymm4, %ymm0 -; AVX512DQ-FCP-NEXT: vmovdqa (%rdx), %ymm14 -; AVX512DQ-FCP-NEXT: vpshufb %ymm15, %ymm14, %ymm1 -; AVX512DQ-FCP-NEXT: vporq %ymm0, %ymm1, %ymm24 -; AVX512DQ-FCP-NEXT: vmovdqa (%rsi), %ymm15 -; AVX512DQ-FCP-NEXT: vpshufb %ymm8, %ymm15, %ymm0 -; AVX512DQ-FCP-NEXT: vmovdqa (%rdi), %ymm6 -; AVX512DQ-FCP-NEXT: vpshufb %ymm11, %ymm6, %ymm1 -; AVX512DQ-FCP-NEXT: vporq %ymm0, %ymm1, %ymm20 -; AVX512DQ-FCP-NEXT: vmovdqa (%rdi), %xmm0 -; AVX512DQ-FCP-NEXT: vpshufb %xmm5, %xmm0, %xmm1 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm0, %xmm16 -; AVX512DQ-FCP-NEXT: vmovdqa (%rsi), %xmm3 -; AVX512DQ-FCP-NEXT: vpshufb %xmm13, %xmm3, %xmm2 -; AVX512DQ-FCP-NEXT: vporq %xmm1, %xmm2, %xmm28 -; AVX512DQ-FCP-NEXT: vmovdqa (%rcx), %xmm1 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm25, %xmm0 -; AVX512DQ-FCP-NEXT: vpshufb %xmm0, %xmm1, %xmm8 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm1, %xmm18 -; AVX512DQ-FCP-NEXT: vmovdqa (%rdx), %xmm1 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm26, %xmm0 -; AVX512DQ-FCP-NEXT: vpshufb %xmm0, %xmm1, %xmm11 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm1, %xmm17 -; AVX512DQ-FCP-NEXT: vporq %xmm8, %xmm11, %xmm29 -; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} ymm11 = [1,1,2,2,2,2,2,2] +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm9 = [12,13,128,15,12,13,14,128,12,13,14,15,128,u,u,u,16,128,18,19,16,17,128,19,16,17,18,128,16,17,18,19] +; AVX512DQ-FCP-NEXT: vpshufb %ymm9, %ymm1, %ymm3 +; AVX512DQ-FCP-NEXT: vporq %ymm2, %ymm3, %ymm17 +; AVX512DQ-FCP-NEXT: vmovdqa 32(%rdi), %xmm3 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm2 = xmm3[8],zero,xmm3[u,7],zero,xmm3[9],zero,xmm3[u],zero,xmm3[u,10],zero,xmm3[12],zero,xmm3[u,11] +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm3, %xmm31 +; AVX512DQ-FCP-NEXT: vmovdqa 32(%rsi), %xmm15 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm4 = zero,xmm15[8,u],zero,xmm15[7],zero,xmm15[9,u,11,u],zero,xmm15[10],zero,xmm15[12,u],zero +; AVX512DQ-FCP-NEXT: vporq %xmm2, %xmm4, %xmm18 +; AVX512DQ-FCP-NEXT: vmovdqa 32(%rcx), %ymm2 +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm10 = [128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128] +; AVX512DQ-FCP-NEXT: vpshufb %ymm10, %ymm2, %ymm4 +; AVX512DQ-FCP-NEXT: vmovdqa 32(%rdx), %ymm11 +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm12 = [u,u,12,13,128,u,u,u,14,128,u,u,14,15,128,u,u,u,16,128,u,u,16,17,128,u,u,u,18,128,u,u] +; AVX512DQ-FCP-NEXT: vpshufb %ymm12, %ymm11, %ymm6 +; AVX512DQ-FCP-NEXT: vporq %ymm4, %ymm6, %ymm19 +; AVX512DQ-FCP-NEXT: vmovdqa 32(%rcx), %xmm6 +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm3 = [128,6,128,8,u,128,7,128,9,128,11,u,128,10,128,12] +; AVX512DQ-FCP-NEXT: vpshufb %xmm3, %xmm6, %xmm4 +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm3, %xmm30 +; AVX512DQ-FCP-NEXT: vmovdqa 32(%rdx), %xmm7 +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm3 = [6,128,8,128,u,7,128,9,128,11,128,u,10,128,12,128] +; AVX512DQ-FCP-NEXT: vpshufb %xmm3, %xmm7, %xmm8 +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm3, %xmm29 +; AVX512DQ-FCP-NEXT: vporq %xmm4, %xmm8, %xmm20 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm1[26],zero,ymm1[28],zero,zero,ymm1[27],zero,ymm1[29],zero,ymm1[31],zero,zero,ymm1[30],zero +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm13 = [128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,128,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,128] +; AVX512DQ-FCP-NEXT: # ymm13 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm13, %ymm1, %ymm1 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm1, %zmm21 +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [27,0,128,26,128,28,0,128,0,128,29,128,31,0,128,30,27,0,128,26,128,28,0,128,0,128,29,128,31,0,128,30] +; AVX512DQ-FCP-NEXT: # ymm1 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm1, %ymm0, %ymm4 +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm1, %ymm28 +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm5 = [19,128,21,0,128,20,128,22,128,24,0,128,23,128,25,0,19,128,21,0,128,20,128,22,128,24,0,128,23,128,25,0] +; AVX512DQ-FCP-NEXT: # ymm5 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm5, %ymm0, %ymm0 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm0, %zmm22 +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm4 = [128,27,128,128,26,128,28,128,30,128,128,29,128,31,128,128,128,27,128,128,26,128,28,128,30,128,128,29,128,31,128,128] +; AVX512DQ-FCP-NEXT: # ymm4 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm4, %ymm11, %ymm0 +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm3 = [128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128] +; AVX512DQ-FCP-NEXT: # ymm3 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm3, %ymm2, %ymm8 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm8, %zmm24 +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm8 = [25,128,27,0,128,26,128,28,128,30,0,128,29,128,31,0,25,128,27,0,128,26,128,28,128,30,0,128,29,128,31,0] +; AVX512DQ-FCP-NEXT: # ymm8 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm8, %ymm2, %ymm0 +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25,18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25] +; AVX512DQ-FCP-NEXT: # ymm1 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm1, %ymm11, %ymm2 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm2, %zmm26 +; AVX512DQ-FCP-NEXT: vmovdqa (%rcx), %ymm2 +; AVX512DQ-FCP-NEXT: vpshufb %ymm10, %ymm2, %ymm0 +; AVX512DQ-FCP-NEXT: vmovdqa (%rdx), %ymm11 +; AVX512DQ-FCP-NEXT: vpshufb %ymm12, %ymm11, %ymm10 +; AVX512DQ-FCP-NEXT: vporq %ymm0, %ymm10, %ymm23 +; AVX512DQ-FCP-NEXT: vpshufb %ymm3, %ymm2, %ymm0 +; AVX512DQ-FCP-NEXT: vpshufb %ymm1, %ymm11, %ymm1 +; AVX512DQ-FCP-NEXT: vporq %ymm0, %ymm1, %ymm25 +; AVX512DQ-FCP-NEXT: vmovdqa (%rsi), %ymm10 +; AVX512DQ-FCP-NEXT: vpshufb %ymm14, %ymm10, %ymm0 +; AVX512DQ-FCP-NEXT: vmovdqa (%rdi), %ymm12 +; AVX512DQ-FCP-NEXT: vpshufb %ymm9, %ymm12, %ymm1 +; AVX512DQ-FCP-NEXT: vporq %ymm0, %ymm1, %ymm27 +; AVX512DQ-FCP-NEXT: vpshufb %ymm13, %ymm12, %ymm0 +; AVX512DQ-FCP-NEXT: vpshufb %ymm5, %ymm10, %ymm1 +; AVX512DQ-FCP-NEXT: vporq %ymm0, %ymm1, %ymm16 +; AVX512DQ-FCP-NEXT: vmovdqa (%rdi), %xmm9 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm0 = xmm9[8],zero,xmm9[u,7],zero,xmm9[9],zero,xmm9[u],zero,xmm9[u,10],zero,xmm9[12],zero,xmm9[u,11] +; AVX512DQ-FCP-NEXT: vmovdqa (%rsi), %xmm14 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm1 = zero,xmm14[8,u],zero,xmm14[7],zero,xmm14[9,u,11,u],zero,xmm14[10],zero,xmm14[12,u],zero +; AVX512DQ-FCP-NEXT: vpor %xmm0, %xmm1, %xmm3 +; AVX512DQ-FCP-NEXT: vmovdqa (%rcx), %xmm13 +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm30, %xmm0 +; AVX512DQ-FCP-NEXT: vpshufb %xmm0, %xmm13, %xmm1 +; AVX512DQ-FCP-NEXT: vmovdqa (%rdx), %xmm0 +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm29, %xmm5 +; AVX512DQ-FCP-NEXT: vpshufb %xmm5, %xmm0, %xmm5 +; AVX512DQ-FCP-NEXT: vpor %xmm1, %xmm5, %xmm5 +; AVX512DQ-FCP-NEXT: vpshufb %ymm4, %ymm11, %ymm1 +; AVX512DQ-FCP-NEXT: vpshufb %ymm8, %ymm2, %ymm2 +; AVX512DQ-FCP-NEXT: vpor %ymm1, %ymm2, %ymm11 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm12[26],zero,ymm12[28],zero,zero,ymm12[27],zero,ymm12[29],zero,ymm12[31],zero,zero,ymm12[30],zero +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm28, %ymm2 +; AVX512DQ-FCP-NEXT: vpshufb %ymm2, %ymm10, %ymm2 ; AVX512DQ-FCP-NEXT: vmovdqa 32(%r8), %ymm8 -; AVX512DQ-FCP-NEXT: vpermd %ymm8, %ymm11, %ymm11 -; AVX512DQ-FCP-NEXT: vmovdqa64 {{.*#+}} zmm25 = [255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255] -; AVX512DQ-FCP-NEXT: vpandnq %ymm11, %ymm25, %ymm11 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm0 = [12,128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128] -; AVX512DQ-FCP-NEXT: vpshufb %ymm0, %ymm8, %ymm13 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm13, %zmm11, %zmm26 -; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} zmm31 = [4,6,5,5,5,5,4,6,30,30,30,30,31,31,31,31] -; AVX512DQ-FCP-NEXT: vmovdqa64 {{.*#+}} zmm30 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0] -; AVX512DQ-FCP-NEXT: vmovdqa (%r8), %ymm11 -; AVX512DQ-FCP-NEXT: vpermd %ymm11, %ymm31, %ymm27 -; AVX512DQ-FCP-NEXT: vpandnq %ymm27, %ymm30, %ymm27 -; AVX512DQ-FCP-NEXT: vpshufb %ymm0, %ymm11, %ymm0 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm27, %zmm0, %zmm27 -; AVX512DQ-FCP-NEXT: vpbroadcastq {{.*#+}} ymm0 = [9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12] -; AVX512DQ-FCP-NEXT: vpshufb %ymm0, %ymm7, %ymm7 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm13 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm4[19],zero,ymm4[21],zero,zero,ymm4[20],zero,ymm4[22],zero,ymm4[24],zero,zero,ymm4[23],zero -; AVX512DQ-FCP-NEXT: vpshufb %ymm0, %ymm4, %ymm5 -; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm0 = [18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25,18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25] -; AVX512DQ-FCP-NEXT: # ymm0 = mem[0,1,0,1] -; AVX512DQ-FCP-NEXT: vpshufb %ymm0, %ymm9, %ymm9 -; AVX512DQ-FCP-NEXT: vpshufb %ymm0, %ymm14, %ymm4 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm14 = ymm14[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm14[27],zero,zero,ymm14[26],zero,ymm14[28],zero,ymm14[30],zero,zero,ymm14[29],zero,ymm14[31],zero,zero -; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm10 = xmm12[0],xmm10[0],xmm12[1],xmm10[1],xmm12[2],xmm10[2],xmm12[3],xmm10[3],xmm12[4],xmm10[4],xmm12[5],xmm10[5],xmm12[6],xmm10[6],xmm12[7],xmm10[7] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm15[3,u,5,u,u,4,u,6,u,8,u,u,7,u,9,u,19,u,21,u,u,20,u,22,u,24,u,u,23,u,25,u] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm15 = ymm15[11,u,u,10,u,12,u,u,u,u,13,u,15,u,u,14,27,u,u,26,u,28,u,u,u,u,29,u,31,u,u,30] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[21],zero,zero,ymm6[20],zero,ymm6[22],zero,ymm6[24],zero,zero,ymm6[23],zero,ymm6[25],zero,zero -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm6 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm6[26],zero,ymm6[28],zero,zero,ymm6[27],zero,ymm6[29],zero,ymm6[31],zero,zero,ymm6[30],zero -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm19, %xmm1 -; AVX512DQ-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload -; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm16, %xmm1 -; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm3 = xmm1[0],xmm3[0],xmm1[1],xmm3[1],xmm1[2],xmm3[2],xmm1[3],xmm3[3],xmm1[4],xmm3[4],xmm1[5],xmm3[5],xmm1[6],xmm3[6],xmm1[7],xmm3[7] -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm1 = [0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] -; AVX512DQ-FCP-NEXT: vpshufb %xmm1, %xmm0, %xmm0 -; AVX512DQ-FCP-NEXT: vpshufb %xmm1, %xmm3, %xmm1 -; AVX512DQ-FCP-NEXT: vinserti32x4 $2, %xmm28, %zmm1, %zmm28 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm7[2,2,3,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm9[2,2,3,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm13[2,2,3,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,2,3,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,2,3,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm5[2,2,3,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm14 = ymm14[2,2,3,3] -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm18, %xmm3 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm17, %xmm5 -; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm5 = xmm3[0],xmm5[0],xmm3[1],xmm5[1],xmm3[2],xmm5[2],xmm3[3],xmm5[3],xmm3[4],xmm5[4],xmm3[5],xmm5[5],xmm3[6],xmm5[6],xmm3[7],xmm5[7] -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm3 = [2,u,1,0,5,4,u,3,u,7,6,11,10,u,9,8] -; AVX512DQ-FCP-NEXT: vpshufb %xmm3, %xmm10, %xmm10 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[0,0,1,1] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,2,3,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,2,3,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,0,1,1] -; AVX512DQ-FCP-NEXT: vpshufb %xmm3, %xmm5, %xmm3 -; AVX512DQ-FCP-NEXT: vinserti32x4 $2, %xmm29, %zmm3, %zmm3 +; AVX512DQ-FCP-NEXT: vpor %ymm1, %ymm2, %ymm1 +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm4 = [12,128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128] +; AVX512DQ-FCP-NEXT: vpshufb %ymm4, %ymm8, %ymm2 +; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} ymm10 = [1,1,2,2,2,2,2,2] +; AVX512DQ-FCP-NEXT: vpermd %ymm8, %ymm10, %ymm10 +; AVX512DQ-FCP-NEXT: vmovdqa64 {{.*#+}} zmm12 = [255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255] +; AVX512DQ-FCP-NEXT: vpandn %ymm10, %ymm12, %ymm10 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm10, %zmm2 +; AVX512DQ-FCP-NEXT: vmovdqa (%r8), %ymm10 +; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} zmm28 = [4,6,5,5,5,5,4,6,30,30,30,30,31,31,31,31] +; AVX512DQ-FCP-NEXT: vmovdqa64 {{.*#+}} zmm29 = [255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0,255,255,255,255,0] +; AVX512DQ-FCP-NEXT: vpermd %ymm10, %ymm28, %ymm30 +; AVX512DQ-FCP-NEXT: vpandnq %ymm30, %ymm29, %ymm30 +; AVX512DQ-FCP-NEXT: vpshufb %ymm4, %ymm10, %ymm4 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm30, %zmm4, %zmm4 +; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm9 = xmm9[0],xmm14[0],xmm9[1],xmm14[1],xmm9[2],xmm14[2],xmm9[3],xmm14[3],xmm9[4],xmm14[4],xmm9[5],xmm14[5],xmm9[6],xmm14[6],xmm9[7],xmm14[7] +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm14 = [0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] +; AVX512DQ-FCP-NEXT: vpshufb %xmm14, %xmm9, %xmm9 +; AVX512DQ-FCP-NEXT: vinserti32x4 $2, %xmm3, %zmm9, %zmm3 +; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm13[0],xmm0[0],xmm13[1],xmm0[1],xmm13[2],xmm0[2],xmm13[3],xmm0[3],xmm13[4],xmm0[4],xmm13[5],xmm0[5],xmm13[6],xmm0[6],xmm13[7],xmm0[7] +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm9 = [2,u,1,0,5,4,u,3,u,7,6,11,10,u,9,8] +; AVX512DQ-FCP-NEXT: vpshufb %xmm9, %xmm0, %xmm0 +; AVX512DQ-FCP-NEXT: vinserti32x4 $2, %xmm5, %zmm0, %zmm0 ; AVX512DQ-FCP-NEXT: vmovdqa64 (%r8), %zmm5 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm5, %zmm11 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm21 = zmm21[2,2,3,3,6,6,7,7] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm22 = zmm22[2,2,3,3,6,6,7,7] -; AVX512DQ-FCP-NEXT: vmovdqa64 {{.*#+}} zmm29 = [18374966859431608575,18374966859431608575,18446463693966278400,18446463693966278400,72056498804555775,72056498804555775,18374967950370078975,18374967950370078975] -; AVX512DQ-FCP-NEXT: vpternlogq $248, %zmm29, %zmm21, %zmm22 -; AVX512DQ-FCP-NEXT: vpandq %ymm29, %ymm1, %ymm1 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm7, %zmm1 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm7 = zmm23[2,2,3,3,6,6,7,7] -; AVX512DQ-FCP-NEXT: vporq %zmm7, %zmm1, %zmm1 -; AVX512DQ-FCP-NEXT: vmovdqa64 {{.*#+}} zmm7 = [0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255] -; AVX512DQ-FCP-NEXT: vpternlogq $226, %zmm22, %zmm7, %zmm1 -; AVX512DQ-FCP-NEXT: vpermt2d %zmm5, %zmm31, %zmm8 -; AVX512DQ-FCP-NEXT: vpternlogd $184, %zmm1, %zmm30, %zmm8 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm5, %zmm10 +; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm6 = xmm6[0],xmm7[0],xmm6[1],xmm7[1],xmm6[2],xmm7[2],xmm6[3],xmm7[3],xmm6[4],xmm7[4],xmm6[5],xmm7[5],xmm6[6],xmm7[6],xmm6[7],xmm7[7] +; AVX512DQ-FCP-NEXT: vpshufb %xmm9, %xmm6, %xmm6 +; AVX512DQ-FCP-NEXT: vpmovsxbq {{.*#+}} zmm7 = [2,2,3,3,8,8,9,9] +; AVX512DQ-FCP-NEXT: vpermt2q %zmm6, %zmm7, %zmm11 +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm31, %xmm6 +; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm6 = xmm6[0],xmm15[0],xmm6[1],xmm15[1],xmm6[2],xmm15[2],xmm6[3],xmm15[3],xmm6[4],xmm15[4],xmm6[5],xmm15[5],xmm6[6],xmm15[6],xmm6[7],xmm15[7] +; AVX512DQ-FCP-NEXT: vpshufb %xmm14, %xmm6, %xmm6 +; AVX512DQ-FCP-NEXT: vpermt2q %zmm6, %zmm7, %zmm1 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm6 = zmm21[2,2,3,3,6,6,7,7] +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm7 = zmm22[2,2,3,3,6,6,7,7] +; AVX512DQ-FCP-NEXT: vporq %zmm6, %zmm7, %zmm6 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm7 = zmm24[2,2,3,3,6,6,7,7] +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm9 = zmm26[2,2,3,3,6,6,7,7] +; AVX512DQ-FCP-NEXT: vporq %zmm7, %zmm9, %zmm7 +; AVX512DQ-FCP-NEXT: vmovdqa64 {{.*#+}} zmm9 = [0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255] +; AVX512DQ-FCP-NEXT: vpternlogq $226, %zmm6, %zmm9, %zmm7 +; AVX512DQ-FCP-NEXT: vpermt2d %zmm5, %zmm28, %zmm8 +; AVX512DQ-FCP-NEXT: vpternlogd $184, %zmm7, %zmm29, %zmm8 ; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm8, 256(%r9) -; AVX512DQ-FCP-NEXT: vpermq $80, {{[-0-9]+}}(%r{{[sb]}}p), %ymm1 # 32-byte Folded Reload -; AVX512DQ-FCP-NEXT: # ymm1 = mem[0,0,1,1] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm1, %zmm1 # 32-byte Folded Reload -; AVX512DQ-FCP-NEXT: vpermq $80, {{[-0-9]+}}(%r{{[sb]}}p), %ymm8 # 32-byte Folded Reload -; AVX512DQ-FCP-NEXT: # ymm8 = mem[0,0,1,1] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm8, %zmm8 # 32-byte Folded Reload -; AVX512DQ-FCP-NEXT: vmovdqa64 {{.*#+}} zmm16 = [255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0] -; AVX512DQ-FCP-NEXT: vpternlogq $226, %zmm1, %zmm16, %zmm8 -; AVX512DQ-FCP-NEXT: vpternlogq $248, %zmm25, %zmm8, %zmm26 -; AVX512DQ-FCP-NEXT: vpor %ymm4, %ymm9, %ymm1 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm24, %zmm1 -; AVX512DQ-FCP-NEXT: vpternlogq $248, %ymm29, %ymm12, %ymm2 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm20, %zmm2 -; AVX512DQ-FCP-NEXT: vpternlogq $226, %zmm1, %zmm16, %zmm2 -; AVX512DQ-FCP-NEXT: vpternlogq $248, %ymm29, %ymm13, %ymm14 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm14, %zmm1 -; AVX512DQ-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm15, %ymm6 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm6, %zmm0 -; AVX512DQ-FCP-NEXT: vpternlogq $226, %zmm1, %zmm7, %zmm0 -; AVX512DQ-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm27 -; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [6,6,6,0,7,7,7,7,0,8,8,8,8,0,9,9] -; AVX512DQ-FCP-NEXT: vpermd %zmm5, %zmm1, %zmm1 -; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm1 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm0 = zmm28[0,0,1,1,4,4,5,5] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm2 = zmm3[0,0,1,1,4,4,5,5] -; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm2 -; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} zmm0 = [0,0,0,0,0,0,1,1,9,9,0,10,10,10,10,0] -; AVX512DQ-FCP-NEXT: vpermd %zmm11, %zmm0, %zmm0 -; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm0 -; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm27, 64(%r9) -; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm0, (%r9) -; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm1, 128(%r9) -; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm26, 192(%r9) -; AVX512DQ-FCP-NEXT: addq $24, %rsp +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm18[0,0,1,1] +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm17, %zmm6, %zmm6 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm20[0,0,1,1] +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm19, %zmm7, %zmm7 +; AVX512DQ-FCP-NEXT: vmovdqa64 {{.*#+}} zmm8 = [255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0,0,255,255,255,0] +; AVX512DQ-FCP-NEXT: vpternlogq $226, %zmm6, %zmm8, %zmm7 +; AVX512DQ-FCP-NEXT: vpternlogq $248, %zmm12, %zmm7, %zmm2 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm25[2,2,3,3] +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm6, %zmm23, %zmm6 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm16[2,2,3,3] +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm27, %zmm7 +; AVX512DQ-FCP-NEXT: vpternlogq $226, %zmm6, %zmm8, %zmm7 +; AVX512DQ-FCP-NEXT: vpternlogq $226, %zmm11, %zmm9, %zmm1 +; AVX512DQ-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm7, %zmm4 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm3 = zmm3[0,0,1,1,4,4,5,5] +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm0 = zmm0[0,0,1,1,4,4,5,5] +; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm3, %zmm0 +; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} zmm3 = [0,0,0,0,0,0,1,1,9,9,0,10,10,10,10,0] +; AVX512DQ-FCP-NEXT: vpermd %zmm10, %zmm3, %zmm3 +; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm3 +; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} zmm0 = [6,6,6,0,7,7,7,7,0,8,8,8,8,0,9,9] +; AVX512DQ-FCP-NEXT: vpermd %zmm5, %zmm0, %zmm0 +; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm0 +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm0, 128(%r9) +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm4, 64(%r9) +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm3, (%r9) +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm2, 192(%r9) ; AVX512DQ-FCP-NEXT: vzeroupper ; AVX512DQ-FCP-NEXT: retq ; ; AVX512BW-LABEL: store_i8_stride5_vf64: ; AVX512BW: # %bb.0: -; AVX512BW-NEXT: vmovdqa64 (%r8), %zmm3 +; AVX512BW-NEXT: vmovdqa64 (%r8), %zmm2 ; AVX512BW-NEXT: vmovdqa (%rcx), %ymm0 ; AVX512BW-NEXT: vpbroadcastq {{.*#+}} ymm8 = [9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12] -; AVX512BW-NEXT: vpshufb %ymm8, %ymm0, %ymm2 +; AVX512BW-NEXT: vpshufb %ymm8, %ymm0, %ymm3 ; AVX512BW-NEXT: vmovdqa (%rdx), %ymm1 ; AVX512BW-NEXT: vpshufhw {{.*#+}} ymm4 = ymm1[0,1,2,3,5,6,7,6,8,9,10,11,13,14,15,14] ; AVX512BW-NEXT: vpshufd {{.*#+}} ymm4 = ymm4[2,2,3,3,6,6,7,7] ; AVX512BW-NEXT: movl $693250386, %eax # imm = 0x29522952 ; AVX512BW-NEXT: kmovd %eax, %k1 -; AVX512BW-NEXT: vmovdqu8 %ymm4, %ymm2 {%k1} -; AVX512BW-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] +; AVX512BW-NEXT: vmovdqu8 %ymm4, %ymm3 {%k1} +; AVX512BW-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,3,3] ; AVX512BW-NEXT: vmovdqa 32(%rdx), %xmm6 ; AVX512BW-NEXT: vmovdqa 32(%rcx), %xmm12 ; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm4 = xmm12[0],xmm6[0],xmm12[1],xmm6[1],xmm12[2],xmm6[2],xmm12[3],xmm6[3],xmm12[4],xmm6[4],xmm12[5],xmm6[5],xmm12[6],xmm6[6],xmm12[7],xmm6[7] ; AVX512BW-NEXT: vmovdqa {{.*#+}} xmm7 = [2,u,1,0,5,4,u,3,u,7,6,11,10,u,9,8] ; AVX512BW-NEXT: vpshufb %xmm7, %xmm4, %xmm4 ; AVX512BW-NEXT: vpermq {{.*#+}} ymm4 = ymm4[0,0,1,1] -; AVX512BW-NEXT: vinserti64x4 $1, %ymm4, %zmm2, %zmm10 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm4, %zmm3, %zmm10 ; AVX512BW-NEXT: vmovdqa (%rsi), %ymm4 ; AVX512BW-NEXT: vpbroadcastq {{.*#+}} ymm15 = [11,0,13,10,15,12,0,14,11,0,13,10,15,12,0,14,11,0,13,10,15,12,0,14,11,0,13,10,15,12,0,14] -; AVX512BW-NEXT: vpshufb %ymm15, %ymm4, %ymm2 +; AVX512BW-NEXT: vpshufb %ymm15, %ymm4, %ymm3 ; AVX512BW-NEXT: vmovdqa (%rdi), %ymm5 ; AVX512BW-NEXT: vpshufhw {{.*#+}} ymm9 = ymm5[0,1,2,3,6,5,6,7,8,9,10,11,14,13,14,15] ; AVX512BW-NEXT: vpshufd {{.*#+}} ymm9 = ymm9[2,2,3,3,6,6,7,7] ; AVX512BW-NEXT: movl $1251232404, %eax # imm = 0x4A944A94 ; AVX512BW-NEXT: kmovd %eax, %k5 -; AVX512BW-NEXT: vmovdqu8 %ymm9, %ymm2 {%k5} -; AVX512BW-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] +; AVX512BW-NEXT: vmovdqu8 %ymm9, %ymm3 {%k5} +; AVX512BW-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,3,3] ; AVX512BW-NEXT: vmovdqa 32(%rsi), %xmm13 ; AVX512BW-NEXT: vmovdqa 32(%rdi), %xmm14 ; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm11 = xmm14[0],xmm13[0],xmm14[1],xmm13[1],xmm14[2],xmm13[2],xmm14[3],xmm13[3],xmm14[4],xmm13[4],xmm14[5],xmm13[5],xmm14[6],xmm13[6],xmm14[7],xmm13[7] ; AVX512BW-NEXT: vmovdqa {{.*#+}} xmm9 = [0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] ; AVX512BW-NEXT: vpshufb %xmm9, %xmm11, %xmm11 ; AVX512BW-NEXT: vpermq {{.*#+}} ymm11 = ymm11[0,0,1,1] -; AVX512BW-NEXT: vinserti64x4 $1, %ymm11, %zmm2, %zmm2 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm11, %zmm3, %zmm3 ; AVX512BW-NEXT: movabsq $1785168781326730801, %rax # imm = 0x18C6318C6318C631 ; AVX512BW-NEXT: kmovq %rax, %k4 -; AVX512BW-NEXT: vmovdqu8 %zmm10, %zmm2 {%k4} +; AVX512BW-NEXT: vmovdqu8 %zmm10, %zmm3 {%k4} ; AVX512BW-NEXT: vmovdqa64 32(%r8), %ymm16 ; AVX512BW-NEXT: vpmovsxbd {{.*#+}} zmm10 = [6,6,6,6,7,7,7,7,16,16,16,16,16,16,17,17] -; AVX512BW-NEXT: vpermi2d %zmm16, %zmm3, %zmm10 +; AVX512BW-NEXT: vpermi2d %zmm16, %zmm2, %zmm10 ; AVX512BW-NEXT: movabsq $2380225041768974402, %rax # imm = 0x2108421084210842 ; AVX512BW-NEXT: kmovq %rax, %k2 -; AVX512BW-NEXT: vmovdqu8 %zmm10, %zmm2 {%k2} +; AVX512BW-NEXT: vmovdqu8 %zmm10, %zmm3 {%k2} ; AVX512BW-NEXT: vmovdqa64 32(%rdx), %ymm23 ; AVX512BW-NEXT: vmovdqa {{.*#+}} ymm10 = [128,128,12,13,128,128,128,128,14,128,128,128,14,15,128,128,128,128,16,128,128,128,16,17,128,128,128,128,18,128,128,128] ; AVX512BW-NEXT: vpshufb %ymm10, %ymm23, %ymm17 @@ -5584,21 +5491,21 @@ define void @store_i8_stride5_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-NEXT: vmovdqa64 {{.*#+}} xmm21 = [128,8,u,128,7,128,9,u,11,u,128,10,128,12,u,128] ; AVX512BW-NEXT: vpshufb %xmm21, %xmm13, %xmm13 ; AVX512BW-NEXT: vpor %xmm12, %xmm13, %xmm12 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm13 = ymm12[0,0,1,1] +; AVX512BW-NEXT: vpermq {{.*#+}} ymm14 = ymm12[0,0,1,1] ; AVX512BW-NEXT: vmovdqa64 32(%rdi), %ymm25 ; AVX512BW-NEXT: vpmovsxbd {{.*#+}} ymm12 = [3,3,3,0,4,4,4,4] ; AVX512BW-NEXT: vpermd %ymm25, %ymm12, %ymm17 ; AVX512BW-NEXT: vmovdqa64 32(%rsi), %ymm26 -; AVX512BW-NEXT: vpbroadcastq {{.*#+}} ymm14 = [0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14] +; AVX512BW-NEXT: vpbroadcastq {{.*#+}} ymm13 = [0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14] ; AVX512BW-NEXT: movl $138547332, %eax # imm = 0x8421084 ; AVX512BW-NEXT: kmovd %eax, %k3 -; AVX512BW-NEXT: vpshufb %ymm14, %ymm26, %ymm17 {%k3} -; AVX512BW-NEXT: vinserti64x4 $1, %ymm17, %zmm13, %zmm13 +; AVX512BW-NEXT: vpshufb %ymm13, %ymm26, %ymm17 {%k3} +; AVX512BW-NEXT: vinserti64x4 $1, %ymm17, %zmm14, %zmm14 ; AVX512BW-NEXT: movabsq $-8330787646191410408, %rax # imm = 0x8C6318C6318C6318 ; AVX512BW-NEXT: kmovq %rax, %k2 -; AVX512BW-NEXT: vmovdqu8 %zmm13, %zmm6 {%k2} -; AVX512BW-NEXT: vpmovsxbd {{.*#+}} ymm13 = [3,3,3,3,0,4,4,4] -; AVX512BW-NEXT: vpermd %ymm16, %ymm13, %ymm17 +; AVX512BW-NEXT: vmovdqu8 %zmm14, %zmm6 {%k2} +; AVX512BW-NEXT: vpmovsxbd {{.*#+}} ymm14 = [3,3,3,3,0,4,4,4] +; AVX512BW-NEXT: vpermd %ymm16, %ymm14, %ymm17 ; AVX512BW-NEXT: vpshufd {{.*#+}} xmm18 = mem[1,1,2,2] ; AVX512BW-NEXT: vpermq {{.*#+}} ymm18 = ymm18[0,1,1,1] ; AVX512BW-NEXT: vinserti64x4 $1, %ymm17, %zmm18, %zmm17 @@ -5607,32 +5514,28 @@ define void @store_i8_stride5_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-NEXT: vmovdqu8 %zmm17, %zmm6 {%k6} ; AVX512BW-NEXT: vbroadcasti32x4 {{.*#+}} ymm17 = [19,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128] ; AVX512BW-NEXT: # ymm17 = mem[0,1,2,3,0,1,2,3] -; AVX512BW-NEXT: vpshufb %ymm17, %ymm26, %ymm18 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm27 = ymm18[2,2,3,3] +; AVX512BW-NEXT: vpshufb %ymm17, %ymm26, %ymm27 ; AVX512BW-NEXT: vmovdqa64 {{.*#+}} ymm18 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,128] ; AVX512BW-NEXT: vpshufb %ymm18, %ymm25, %ymm28 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm28 = ymm28[2,2,3,3] ; AVX512BW-NEXT: vporq %ymm27, %ymm28, %ymm27 ; AVX512BW-NEXT: vpshufb %ymm15, %ymm26, %ymm15 ; AVX512BW-NEXT: vpshufhw {{.*#+}} ymm25 = ymm25[0,1,2,3,6,5,6,7,8,9,10,11,14,13,14,15] ; AVX512BW-NEXT: vpshufd {{.*#+}} ymm25 = ymm25[2,2,3,3,6,6,7,7] ; AVX512BW-NEXT: vmovdqu8 %ymm25, %ymm15 {%k5} -; AVX512BW-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,2,3,3] ; AVX512BW-NEXT: vinserti64x4 $1, %ymm15, %zmm27, %zmm15 ; AVX512BW-NEXT: vmovdqa64 {{.*#+}} ymm25 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25] ; AVX512BW-NEXT: vpshufb %ymm25, %ymm23, %ymm26 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm26 = ymm26[2,2,3,3] ; AVX512BW-NEXT: vbroadcasti32x4 {{.*#+}} ymm27 = [128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128] ; AVX512BW-NEXT: # ymm27 = mem[0,1,2,3,0,1,2,3] ; AVX512BW-NEXT: vpshufb %ymm27, %ymm24, %ymm28 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm28 = ymm28[2,2,3,3] ; AVX512BW-NEXT: vporq %ymm26, %ymm28, %ymm26 ; AVX512BW-NEXT: vpshufb %ymm8, %ymm24, %ymm8 ; AVX512BW-NEXT: vpshufhw {{.*#+}} ymm23 = ymm23[0,1,2,3,5,6,7,6,8,9,10,11,13,14,15,14] ; AVX512BW-NEXT: vpshufd {{.*#+}} ymm23 = ymm23[2,2,3,3,6,6,7,7] ; AVX512BW-NEXT: vmovdqu8 %ymm23, %ymm8 {%k1} -; AVX512BW-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] ; AVX512BW-NEXT: vinserti64x4 $1, %ymm8, %zmm26, %zmm8 +; AVX512BW-NEXT: vpermq {{.*#+}} zmm15 = zmm15[2,2,3,3,6,6,7,7] +; AVX512BW-NEXT: vpermq {{.*#+}} zmm8 = zmm8[2,2,3,3,6,6,7,7] ; AVX512BW-NEXT: vmovdqu8 %zmm15, %zmm8 {%k4} ; AVX512BW-NEXT: vpmovsxbd {{.*#+}} zmm15 = [4,6,5,5,5,5,4,6,6,6,6,6,7,7,7,7] ; AVX512BW-NEXT: vpermd %zmm16, %zmm15, %zmm15 @@ -5661,33 +5564,31 @@ define void @store_i8_stride5_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-NEXT: kmovq %rax, %k1 ; AVX512BW-NEXT: vmovdqu8 %zmm7, %zmm9 {%k1} ; AVX512BW-NEXT: vpmovsxbd {{.*#+}} zmm7 = [0,0,0,0,0,0,1,1,1,1,2,2,2,2,2,2] -; AVX512BW-NEXT: vpermd %zmm3, %zmm7, %zmm3 +; AVX512BW-NEXT: vpermd %zmm2, %zmm7, %zmm2 ; AVX512BW-NEXT: movabsq $595056260442243600, %rax # imm = 0x842108421084210 ; AVX512BW-NEXT: kmovq %rax, %k1 -; AVX512BW-NEXT: vmovdqu8 %zmm3, %zmm9 {%k1} -; AVX512BW-NEXT: vpshufb %ymm25, %ymm1, %ymm3 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,3,3] -; AVX512BW-NEXT: vpshufb %ymm27, %ymm0, %ymm7 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] -; AVX512BW-NEXT: vpor %ymm3, %ymm7, %ymm3 -; AVX512BW-NEXT: vpshufb %ymm10, %ymm1, %ymm1 -; AVX512BW-NEXT: vpshufb %ymm11, %ymm0, %ymm0 +; AVX512BW-NEXT: vmovdqu8 %zmm2, %zmm9 {%k1} +; AVX512BW-NEXT: vpshufb %ymm10, %ymm1, %ymm2 +; AVX512BW-NEXT: vpshufb %ymm11, %ymm0, %ymm7 +; AVX512BW-NEXT: vpor %ymm2, %ymm7, %ymm2 +; AVX512BW-NEXT: vpshufb %ymm25, %ymm1, %ymm1 +; AVX512BW-NEXT: vpshufb %ymm27, %ymm0, %ymm0 ; AVX512BW-NEXT: vpor %ymm1, %ymm0, %ymm0 -; AVX512BW-NEXT: vinserti64x4 $1, %ymm3, %zmm0, %zmm0 +; AVX512BW-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] +; AVX512BW-NEXT: vinserti64x4 $1, %ymm0, %zmm2, %zmm0 ; AVX512BW-NEXT: vpermd %ymm5, %ymm12, %ymm1 -; AVX512BW-NEXT: vpshufb %ymm14, %ymm4, %ymm1 {%k3} -; AVX512BW-NEXT: vpshufb %ymm17, %ymm4, %ymm3 +; AVX512BW-NEXT: vpshufb %ymm13, %ymm4, %ymm1 {%k3} +; AVX512BW-NEXT: vpshufb %ymm17, %ymm4, %ymm2 ; AVX512BW-NEXT: vpshufb %ymm18, %ymm5, %ymm4 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,3,3] -; AVX512BW-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,2,3,3] -; AVX512BW-NEXT: vpor %ymm3, %ymm4, %ymm3 -; AVX512BW-NEXT: vinserti64x4 $1, %ymm3, %zmm1, %zmm1 +; AVX512BW-NEXT: vpor %ymm2, %ymm4, %ymm2 +; AVX512BW-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] +; AVX512BW-NEXT: vinserti64x4 $1, %ymm2, %zmm1, %zmm1 ; AVX512BW-NEXT: vmovdqu8 %zmm0, %zmm1 {%k2} ; AVX512BW-NEXT: vmovdqa (%r8), %ymm0 -; AVX512BW-NEXT: vpermd %ymm0, %ymm13, %ymm3 +; AVX512BW-NEXT: vpermd %ymm0, %ymm14, %ymm2 ; AVX512BW-NEXT: vpshufd {{.*#+}} ymm0 = ymm0[0,2,1,1,4,6,5,5] ; AVX512BW-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,3,2] -; AVX512BW-NEXT: vinserti64x4 $1, %ymm0, %zmm3, %zmm0 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm0, %zmm2, %zmm0 ; AVX512BW-NEXT: movabsq $1190112520884487201, %rax # imm = 0x1084210842108421 ; AVX512BW-NEXT: kmovq %rax, %k1 ; AVX512BW-NEXT: vmovdqu8 %zmm0, %zmm1 {%k1} @@ -5695,215 +5596,206 @@ define void @store_i8_stride5_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-NEXT: vmovdqa64 %zmm9, (%r9) ; AVX512BW-NEXT: vmovdqa64 %zmm8, 256(%r9) ; AVX512BW-NEXT: vmovdqa64 %zmm6, 192(%r9) -; AVX512BW-NEXT: vmovdqa64 %zmm2, 128(%r9) +; AVX512BW-NEXT: vmovdqa64 %zmm3, 128(%r9) ; AVX512BW-NEXT: vzeroupper ; AVX512BW-NEXT: retq ; ; AVX512BW-FCP-LABEL: store_i8_stride5_vf64: ; AVX512BW-FCP: # %bb.0: -; AVX512BW-FCP-NEXT: vmovdqa64 (%r8), %zmm5 +; AVX512BW-FCP-NEXT: vmovdqa64 (%r8), %zmm0 ; AVX512BW-FCP-NEXT: vmovdqa64 32(%rdx), %ymm21 -; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} ymm1 = [128,128,12,13,128,128,128,128,14,128,128,128,14,15,128,128,128,128,16,128,128,128,16,17,128,128,128,128,18,128,128,128] -; AVX512BW-FCP-NEXT: vpshufb %ymm1, %ymm21, %ymm0 -; AVX512BW-FCP-NEXT: vmovdqa 32(%rcx), %ymm13 -; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} ymm2 = [128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128] -; AVX512BW-FCP-NEXT: vpshufb %ymm2, %ymm13, %ymm3 -; AVX512BW-FCP-NEXT: vpor %ymm0, %ymm3, %ymm0 -; AVX512BW-FCP-NEXT: vmovdqa (%rcx), %xmm6 -; AVX512BW-FCP-NEXT: vmovdqa64 32(%rcx), %xmm18 -; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm8 = [128,6,128,8,u,128,7,128,9,128,11,u,128,10,128,12] -; AVX512BW-FCP-NEXT: vpshufb %xmm8, %xmm18, %xmm3 -; AVX512BW-FCP-NEXT: vmovdqa (%rdx), %xmm7 -; AVX512BW-FCP-NEXT: vmovdqa64 32(%rdx), %xmm20 -; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm10 = [6,128,8,128,u,7,128,9,128,11,128,u,10,128,12,128] -; AVX512BW-FCP-NEXT: vpshufb %xmm10, %xmm20, %xmm4 -; AVX512BW-FCP-NEXT: vpor %xmm3, %xmm4, %xmm3 +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} ymm6 = [128,128,12,13,128,128,128,128,14,128,128,128,14,15,128,128,128,128,16,128,128,128,16,17,128,128,128,128,18,128,128,128] +; AVX512BW-FCP-NEXT: vpshufb %ymm6, %ymm21, %ymm1 +; AVX512BW-FCP-NEXT: vmovdqa 32(%rcx), %ymm8 +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} ymm7 = [128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128] +; AVX512BW-FCP-NEXT: vpshufb %ymm7, %ymm8, %ymm2 +; AVX512BW-FCP-NEXT: vpor %ymm1, %ymm2, %ymm1 +; AVX512BW-FCP-NEXT: vmovdqa (%rcx), %xmm11 +; AVX512BW-FCP-NEXT: vmovdqa 32(%rcx), %xmm2 +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm14 = [128,6,128,8,u,128,7,128,9,128,11,u,128,10,128,12] +; AVX512BW-FCP-NEXT: vpshufb %xmm14, %xmm2, %xmm3 +; AVX512BW-FCP-NEXT: vmovdqa (%rdx), %xmm12 +; AVX512BW-FCP-NEXT: vmovdqa 32(%rdx), %xmm4 +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm15 = [6,128,8,128,u,7,128,9,128,11,128,u,10,128,12,128] +; AVX512BW-FCP-NEXT: vpshufb %xmm15, %xmm4, %xmm5 +; AVX512BW-FCP-NEXT: vpor %xmm3, %xmm5, %xmm3 ; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm3[0,0,1,1] -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm3, %zmm0 -; AVX512BW-FCP-NEXT: vmovdqa (%rdi), %xmm9 -; AVX512BW-FCP-NEXT: vmovdqa64 32(%rdi), %xmm17 -; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm12 = [8,128,u,7,128,9,128,u,128,u,10,128,12,128,u,11] -; AVX512BW-FCP-NEXT: vpshufb %xmm12, %xmm17, %xmm3 -; AVX512BW-FCP-NEXT: vmovdqa (%rsi), %xmm11 -; AVX512BW-FCP-NEXT: vmovdqa64 32(%rsi), %xmm19 -; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm14 = [128,8,u,128,7,128,9,u,11,u,128,10,128,12,u,128] -; AVX512BW-FCP-NEXT: vpshufb %xmm14, %xmm19, %xmm4 -; AVX512BW-FCP-NEXT: vpor %xmm3, %xmm4, %xmm3 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm15 = ymm3[0,0,1,1] -; AVX512BW-FCP-NEXT: vmovdqa64 32(%rdi), %ymm16 -; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} ymm3 = [3,3,3,0,4,4,4,4] -; AVX512BW-FCP-NEXT: vpermd %ymm16, %ymm3, %ymm22 +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm3, %zmm1 +; AVX512BW-FCP-NEXT: vmovdqa (%rdi), %xmm13 +; AVX512BW-FCP-NEXT: vmovdqa 32(%rdi), %xmm3 +; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} xmm17 = [8,128,u,7,128,9,128,u,128,u,10,128,12,128,u,11] +; AVX512BW-FCP-NEXT: vpshufb %xmm17, %xmm3, %xmm9 +; AVX512BW-FCP-NEXT: vmovdqa64 (%rsi), %xmm16 +; AVX512BW-FCP-NEXT: vmovdqa 32(%rsi), %xmm5 +; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} xmm20 = [128,8,u,128,7,128,9,u,11,u,128,10,128,12,u,128] +; AVX512BW-FCP-NEXT: vpshufb %xmm20, %xmm5, %xmm10 +; AVX512BW-FCP-NEXT: vpor %xmm9, %xmm10, %xmm9 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm18 = ymm9[0,0,1,1] +; AVX512BW-FCP-NEXT: vmovdqa64 32(%rdi), %ymm19 +; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} ymm9 = [3,3,3,0,4,4,4,4] +; AVX512BW-FCP-NEXT: vpermd %ymm19, %ymm9, %ymm22 ; AVX512BW-FCP-NEXT: vmovdqa64 32(%rsi), %ymm23 -; AVX512BW-FCP-NEXT: vpbroadcastq {{.*#+}} ymm4 = [0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14] +; AVX512BW-FCP-NEXT: vpbroadcastq {{.*#+}} ymm10 = [0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14] ; AVX512BW-FCP-NEXT: movl $138547332, %eax # imm = 0x8421084 ; AVX512BW-FCP-NEXT: kmovd %eax, %k1 -; AVX512BW-FCP-NEXT: vpshufb %ymm4, %ymm23, %ymm22 {%k1} -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm22, %zmm15, %zmm15 +; AVX512BW-FCP-NEXT: vpshufb %ymm10, %ymm23, %ymm22 {%k1} +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm22, %zmm18, %zmm18 ; AVX512BW-FCP-NEXT: movabsq $-8330787646191410408, %rax # imm = 0x8C6318C6318C6318 ; AVX512BW-FCP-NEXT: kmovq %rax, %k2 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm15, %zmm0 {%k2} -; AVX512BW-FCP-NEXT: vmovdqa64 32(%r8), %ymm24 -; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm15 = [1,1,2,2,2,2,2,2,27,27,27,27,0,28,28,28] -; AVX512BW-FCP-NEXT: vpermi2d %zmm5, %zmm24, %zmm15 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm18, %zmm1 {%k2} +; AVX512BW-FCP-NEXT: vmovdqa64 32(%r8), %ymm22 +; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm18 = [1,1,2,2,2,2,2,2,27,27,27,27,0,28,28,28] +; AVX512BW-FCP-NEXT: vpermi2d %zmm0, %zmm22, %zmm18 ; AVX512BW-FCP-NEXT: movabsq $4760450083537948804, %rax # imm = 0x4210842108421084 ; AVX512BW-FCP-NEXT: kmovq %rax, %k3 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm15, %zmm0 {%k3} -; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm22 = zmm23[0,1,2,3],mem[4,5,6,7] -; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm15 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,128,128,26,128,28,128,128,128,128,29,128,31,128,128,30] -; AVX512BW-FCP-NEXT: vpshufb %zmm15, %zmm22, %zmm22 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm22 = zmm22[2,2,3,3,6,6,7,7] -; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm23 = zmm16[0,1,2,3],mem[4,5,6,7] -; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm16 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,26,128,28,128,128,27,128,29,128,31,128,128,30,128] -; AVX512BW-FCP-NEXT: vpshufb %zmm16, %zmm23, %zmm23 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm18, %zmm1 {%k3} +; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm23 = zmm23[0,1,2,3],mem[4,5,6,7] +; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm18 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,128,128,26,128,28,128,128,128,128,29,128,31,128,128,30] +; AVX512BW-FCP-NEXT: vpshufb %zmm18, %zmm23, %zmm23 +; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm24 = zmm19[0,1,2,3],mem[4,5,6,7] +; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm19 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,26,128,28,128,128,27,128,29,128,31,128,128,30,128] +; AVX512BW-FCP-NEXT: vpshufb %zmm19, %zmm24, %zmm24 +; AVX512BW-FCP-NEXT: vporq %zmm23, %zmm24, %zmm23 ; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm23 = zmm23[2,2,3,3,6,6,7,7] -; AVX512BW-FCP-NEXT: vporq %zmm22, %zmm23, %zmm23 -; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm22 = zmm21[0,1,2,3],mem[4,5,6,7] -; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm21 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25,128,27,128,128,26,128,28,128,30,128,128,29,128,31,128] -; AVX512BW-FCP-NEXT: vpshufb %zmm21, %zmm22, %zmm22 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm25 = zmm22[2,2,3,3,6,6,7,7] -; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm13 = zmm13[0,1,2,3],mem[4,5,6,7] -; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm22 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,27,128,128,26,128,28,128,30,128,128,29,128,31,128,128] -; AVX512BW-FCP-NEXT: vpshufb %zmm22, %zmm13, %zmm13 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm13 = zmm13[2,2,3,3,6,6,7,7] -; AVX512BW-FCP-NEXT: vporq %zmm25, %zmm13, %zmm13 +; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm21 = zmm21[0,1,2,3],mem[4,5,6,7] +; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm24 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25,128,27,128,128,26,128,28,128,30,128,128,29,128,31,128] +; AVX512BW-FCP-NEXT: vpshufb %zmm24, %zmm21, %zmm21 +; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm8 = zmm8[0,1,2,3],mem[4,5,6,7] +; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm25 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,27,128,128,26,128,28,128,30,128,128,29,128,31,128,128] +; AVX512BW-FCP-NEXT: vpshufb %zmm25, %zmm8, %zmm8 +; AVX512BW-FCP-NEXT: vporq %zmm21, %zmm8, %zmm8 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm8 = zmm8[2,2,3,3,6,6,7,7] ; AVX512BW-FCP-NEXT: movabsq $1785168781326730801, %rax # imm = 0x18C6318C6318C631 ; AVX512BW-FCP-NEXT: kmovq %rax, %k3 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm23, %zmm13 {%k3} -; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm23 = [4,6,5,5,5,5,4,6,30,30,30,30,31,31,31,31] -; AVX512BW-FCP-NEXT: vpermi2d %zmm5, %zmm24, %zmm23 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm23, %zmm8 {%k3} +; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm21 = [4,6,5,5,5,5,4,6,30,30,30,30,31,31,31,31] +; AVX512BW-FCP-NEXT: vpermi2d %zmm0, %zmm22, %zmm21 ; AVX512BW-FCP-NEXT: movabsq $-8925843906633654008, %rax # imm = 0x8421084210842108 ; AVX512BW-FCP-NEXT: kmovq %rax, %k4 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm23, %zmm13 {%k4} -; AVX512BW-FCP-NEXT: vmovdqa64 (%rcx), %ymm23 -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm24 = ymm23[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm23[27],zero,zero,ymm23[26],zero,ymm23[28],zero,ymm23[30],zero,zero,ymm23[29],zero,ymm23[31],zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm25 = ymm24[2,2,3,3] -; AVX512BW-FCP-NEXT: vmovdqa64 (%rdx), %ymm24 -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm26 = ymm24[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm24[27],zero,zero,ymm24[26],zero,ymm24[28],zero,ymm24[30],zero,zero,ymm24[29],zero,ymm24[31],zero,zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm26 = ymm26[2,2,3,3] -; AVX512BW-FCP-NEXT: vporq %ymm25, %ymm26, %ymm25 -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm18 = xmm18[0],xmm20[0],xmm18[1],xmm20[1],xmm18[2],xmm20[2],xmm18[3],xmm20[3],xmm18[4],xmm20[4],xmm18[5],xmm20[5],xmm18[6],xmm20[6],xmm18[7],xmm20[7] -; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} xmm26 = [2,u,1,0,5,4,u,3,u,7,6,11,10,u,9,8] -; AVX512BW-FCP-NEXT: vpshufb %xmm26, %xmm18, %xmm18 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm18 = ymm18[0,0,1,1] -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm18, %zmm25, %zmm25 -; AVX512BW-FCP-NEXT: vmovdqa64 (%rsi), %ymm18 -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm20 = ymm18[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,ymm18[26],zero,ymm18[28],zero,zero,zero,zero,ymm18[29],zero,ymm18[31],zero,zero,ymm18[30] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm27 = ymm20[2,2,3,3] -; AVX512BW-FCP-NEXT: vmovdqa64 (%rdi), %ymm20 -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm28 = ymm20[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm20[26],zero,ymm20[28],zero,zero,ymm20[27],zero,ymm20[29],zero,ymm20[31],zero,zero,ymm20[30],zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm28 = ymm28[2,2,3,3] -; AVX512BW-FCP-NEXT: vporq %ymm27, %ymm28, %ymm27 -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm17 = xmm17[0],xmm19[0],xmm17[1],xmm19[1],xmm17[2],xmm19[2],xmm17[3],xmm19[3],xmm17[4],xmm19[4],xmm17[5],xmm19[5],xmm17[6],xmm19[6],xmm17[7],xmm19[7] -; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} xmm19 = [0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] -; AVX512BW-FCP-NEXT: vpshufb %xmm19, %xmm17, %xmm17 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm17 = ymm17[0,0,1,1] -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm17, %zmm27, %zmm17 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm25, %zmm17 {%k3} -; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm25 = [6,6,6,6,7,7,7,7,8,8,8,8,8,8,9,9] -; AVX512BW-FCP-NEXT: vpermd %zmm5, %zmm25, %zmm5 -; AVX512BW-FCP-NEXT: movabsq $2380225041768974402, %rax # imm = 0x2108421084210842 -; AVX512BW-FCP-NEXT: kmovq %rax, %k3 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm5, %zmm17 {%k3} -; AVX512BW-FCP-NEXT: vpshufb %xmm8, %xmm6, %xmm5 -; AVX512BW-FCP-NEXT: vpshufb %xmm10, %xmm7, %xmm8 -; AVX512BW-FCP-NEXT: vpor %xmm5, %xmm8, %xmm5 -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm6 = xmm6[0],xmm7[0],xmm6[1],xmm7[1],xmm6[2],xmm7[2],xmm6[3],xmm7[3],xmm6[4],xmm7[4],xmm6[5],xmm7[5],xmm6[6],xmm7[6],xmm6[7],xmm7[7] -; AVX512BW-FCP-NEXT: vpshufb %xmm26, %xmm6, %xmm6 -; AVX512BW-FCP-NEXT: vinserti32x4 $2, %xmm5, %zmm6, %zmm5 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm5 = zmm5[0,0,1,1,4,4,5,5] -; AVX512BW-FCP-NEXT: vpshufb %xmm12, %xmm9, %xmm6 -; AVX512BW-FCP-NEXT: vpshufb %xmm14, %xmm11, %xmm7 -; AVX512BW-FCP-NEXT: vpor %xmm6, %xmm7, %xmm6 -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm7 = xmm9[0],xmm11[0],xmm9[1],xmm11[1],xmm9[2],xmm11[2],xmm9[3],xmm11[3],xmm9[4],xmm11[4],xmm9[5],xmm11[5],xmm9[6],xmm11[6],xmm9[7],xmm11[7] -; AVX512BW-FCP-NEXT: vpshufb %xmm19, %xmm7, %xmm7 -; AVX512BW-FCP-NEXT: vinserti32x4 $2, %xmm6, %zmm7, %zmm6 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm6 = zmm6[0,0,1,1,4,4,5,5] +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm21, %zmm8 {%k4} +; AVX512BW-FCP-NEXT: vpshufb %xmm14, %xmm11, %xmm14 +; AVX512BW-FCP-NEXT: vpshufb %xmm15, %xmm12, %xmm15 +; AVX512BW-FCP-NEXT: vpor %xmm14, %xmm15, %xmm14 +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm11 = xmm11[0],xmm12[0],xmm11[1],xmm12[1],xmm11[2],xmm12[2],xmm11[3],xmm12[3],xmm11[4],xmm12[4],xmm11[5],xmm12[5],xmm11[6],xmm12[6],xmm11[7],xmm12[7] +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm12 = [2,u,1,0,5,4,u,3,u,7,6,11,10,u,9,8] +; AVX512BW-FCP-NEXT: vpshufb %xmm12, %xmm11, %xmm11 +; AVX512BW-FCP-NEXT: vinserti32x4 $2, %xmm14, %zmm11, %zmm11 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm14 = zmm11[0,0,1,1,4,4,5,5] +; AVX512BW-FCP-NEXT: vpshufb %xmm17, %xmm13, %xmm11 +; AVX512BW-FCP-NEXT: vpshufb %xmm20, %xmm16, %xmm15 +; AVX512BW-FCP-NEXT: vpor %xmm11, %xmm15, %xmm11 +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm13 = xmm13[0],xmm16[0],xmm13[1],xmm16[1],xmm13[2],xmm16[2],xmm13[3],xmm16[3],xmm13[4],xmm16[4],xmm13[5],xmm16[5],xmm13[6],xmm16[6],xmm13[7],xmm16[7] +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm15 = [0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] +; AVX512BW-FCP-NEXT: vpshufb %xmm15, %xmm13, %xmm13 +; AVX512BW-FCP-NEXT: vinserti32x4 $2, %xmm11, %zmm13, %zmm11 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm11 = zmm11[0,0,1,1,4,4,5,5] ; AVX512BW-FCP-NEXT: movabsq $-4165393823095705204, %rax # imm = 0xC6318C6318C6318C -; AVX512BW-FCP-NEXT: kmovq %rax, %k3 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm5, %zmm6 {%k3} -; AVX512BW-FCP-NEXT: vbroadcasti64x4 {{.*#+}} zmm5 = mem[0,1,2,3,0,1,2,3] -; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm7 = [0,0,0,0,0,0,1,1,9,9,10,10,10,10,10,10] -; AVX512BW-FCP-NEXT: vpermd %zmm5, %zmm7, %zmm7 +; AVX512BW-FCP-NEXT: kmovq %rax, %k4 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm14, %zmm11 {%k4} +; AVX512BW-FCP-NEXT: vbroadcasti64x4 {{.*#+}} zmm13 = mem[0,1,2,3,0,1,2,3] +; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm14 = [0,0,0,0,0,0,1,1,9,9,10,10,10,10,10,10] +; AVX512BW-FCP-NEXT: vpermd %zmm13, %zmm14, %zmm14 ; AVX512BW-FCP-NEXT: movabsq $595056260442243600, %rax # imm = 0x842108421084210 -; AVX512BW-FCP-NEXT: kmovq %rax, %k3 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm7, %zmm6 {%k3} -; AVX512BW-FCP-NEXT: vpshufb %ymm21, %ymm24, %ymm7 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] -; AVX512BW-FCP-NEXT: vpshufb %ymm22, %ymm23, %ymm8 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] -; AVX512BW-FCP-NEXT: vpor %ymm7, %ymm8, %ymm7 -; AVX512BW-FCP-NEXT: vpshufb %ymm1, %ymm24, %ymm1 -; AVX512BW-FCP-NEXT: vpshufb %ymm2, %ymm23, %ymm2 -; AVX512BW-FCP-NEXT: vpor %ymm1, %ymm2, %ymm1 -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm1, %zmm1 -; AVX512BW-FCP-NEXT: vpshufb %ymm15, %ymm18, %ymm2 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] -; AVX512BW-FCP-NEXT: vpshufb %ymm16, %ymm20, %ymm7 +; AVX512BW-FCP-NEXT: kmovq %rax, %k4 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm14, %zmm11 {%k4} +; AVX512BW-FCP-NEXT: vmovdqa (%rdx), %ymm14 +; AVX512BW-FCP-NEXT: vpshufb %ymm6, %ymm14, %ymm6 +; AVX512BW-FCP-NEXT: vmovdqa64 (%rcx), %ymm16 +; AVX512BW-FCP-NEXT: vpshufb %ymm7, %ymm16, %ymm7 +; AVX512BW-FCP-NEXT: vpor %ymm6, %ymm7, %ymm6 +; AVX512BW-FCP-NEXT: vpshufb %ymm24, %ymm14, %ymm7 +; AVX512BW-FCP-NEXT: vpshufb %ymm25, %ymm16, %ymm17 +; AVX512BW-FCP-NEXT: vporq %ymm7, %ymm17, %ymm7 ; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] -; AVX512BW-FCP-NEXT: vpor %ymm2, %ymm7, %ymm2 -; AVX512BW-FCP-NEXT: vpermd %ymm20, %ymm3, %ymm3 -; AVX512BW-FCP-NEXT: vpshufb %ymm4, %ymm18, %ymm3 {%k1} -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm2 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm2 {%k2} -; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [3,3,3,3,0,4,4,4,12,14,13,13,13,13,12,14] -; AVX512BW-FCP-NEXT: vpermd %zmm5, %zmm1, %zmm1 +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm6, %zmm6 +; AVX512BW-FCP-NEXT: vmovdqa (%rsi), %ymm7 +; AVX512BW-FCP-NEXT: vpshufb %ymm18, %ymm7, %ymm17 +; AVX512BW-FCP-NEXT: vmovdqa64 (%rdi), %ymm18 +; AVX512BW-FCP-NEXT: vpshufb %ymm19, %ymm18, %ymm19 +; AVX512BW-FCP-NEXT: vporq %ymm17, %ymm19, %ymm17 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm17 = ymm17[2,2,3,3] +; AVX512BW-FCP-NEXT: vpermd %ymm18, %ymm9, %ymm9 +; AVX512BW-FCP-NEXT: vpshufb %ymm10, %ymm7, %ymm9 {%k1} +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm17, %zmm9, %zmm9 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm6, %zmm9 {%k2} +; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm6 = [3,3,3,3,0,4,4,4,12,14,13,13,13,13,12,14] +; AVX512BW-FCP-NEXT: vpermd %zmm13, %zmm6, %zmm6 ; AVX512BW-FCP-NEXT: movabsq $1190112520884487201, %rax # imm = 0x1084210842108421 ; AVX512BW-FCP-NEXT: kmovq %rax, %k1 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm2 {%k1} -; AVX512BW-FCP-NEXT: vmovdqa64 %zmm2, 64(%r9) -; AVX512BW-FCP-NEXT: vmovdqa64 %zmm6, (%r9) -; AVX512BW-FCP-NEXT: vmovdqa64 %zmm17, 128(%r9) -; AVX512BW-FCP-NEXT: vmovdqa64 %zmm13, 256(%r9) -; AVX512BW-FCP-NEXT: vmovdqa64 %zmm0, 192(%r9) +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm6, %zmm9 {%k1} +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm4[0],xmm2[1],xmm4[1],xmm2[2],xmm4[2],xmm2[3],xmm4[3],xmm2[4],xmm4[4],xmm2[5],xmm4[5],xmm2[6],xmm4[6],xmm2[7],xmm4[7] +; AVX512BW-FCP-NEXT: vpshufb %xmm12, %xmm2, %xmm2 +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm16[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm16[27],zero,zero,ymm16[26],zero,ymm16[28],zero,ymm16[30],zero,zero,ymm16[29],zero,ymm16[31],zero +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm6 = ymm14[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm14[27],zero,zero,ymm14[26],zero,ymm14[28],zero,ymm14[30],zero,zero,ymm14[29],zero,ymm14[31],zero,zero +; AVX512BW-FCP-NEXT: vpor %ymm4, %ymm6, %ymm4 +; AVX512BW-FCP-NEXT: vpmovsxbq {{.*#+}} zmm6 = [2,2,3,3,8,8,9,9] +; AVX512BW-FCP-NEXT: vpermt2q %zmm2, %zmm6, %zmm4 +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm3[0],xmm5[0],xmm3[1],xmm5[1],xmm3[2],xmm5[2],xmm3[3],xmm5[3],xmm3[4],xmm5[4],xmm3[5],xmm5[5],xmm3[6],xmm5[6],xmm3[7],xmm5[7] +; AVX512BW-FCP-NEXT: vpshufb %xmm15, %xmm2, %xmm2 +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm7[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,ymm7[26],zero,ymm7[28],zero,zero,zero,zero,ymm7[29],zero,ymm7[31],zero,zero,ymm7[30] +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm18[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm18[26],zero,ymm18[28],zero,zero,ymm18[27],zero,ymm18[29],zero,ymm18[31],zero,zero,ymm18[30],zero +; AVX512BW-FCP-NEXT: vpor %ymm3, %ymm5, %ymm3 +; AVX512BW-FCP-NEXT: vpermt2q %zmm2, %zmm6, %zmm3 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm4, %zmm3 {%k3} +; AVX512BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm2 = [6,6,6,6,7,7,7,7,8,8,8,8,8,8,9,9] +; AVX512BW-FCP-NEXT: vpermd %zmm0, %zmm2, %zmm0 +; AVX512BW-FCP-NEXT: movabsq $2380225041768974402, %rax # imm = 0x2108421084210842 +; AVX512BW-FCP-NEXT: kmovq %rax, %k1 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm0, %zmm3 {%k1} +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm3, 128(%r9) +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm9, 64(%r9) +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm11, (%r9) +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm8, 256(%r9) +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm1, 192(%r9) ; AVX512BW-FCP-NEXT: vzeroupper ; AVX512BW-FCP-NEXT: retq ; ; AVX512DQ-BW-LABEL: store_i8_stride5_vf64: ; AVX512DQ-BW: # %bb.0: -; AVX512DQ-BW-NEXT: vmovdqa64 (%r8), %zmm3 +; AVX512DQ-BW-NEXT: vmovdqa64 (%r8), %zmm2 ; AVX512DQ-BW-NEXT: vmovdqa (%rcx), %ymm0 ; AVX512DQ-BW-NEXT: vpbroadcastq {{.*#+}} ymm8 = [9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12,9,14,11,0,13,10,15,12] -; AVX512DQ-BW-NEXT: vpshufb %ymm8, %ymm0, %ymm2 +; AVX512DQ-BW-NEXT: vpshufb %ymm8, %ymm0, %ymm3 ; AVX512DQ-BW-NEXT: vmovdqa (%rdx), %ymm1 ; AVX512DQ-BW-NEXT: vpshufhw {{.*#+}} ymm4 = ymm1[0,1,2,3,5,6,7,6,8,9,10,11,13,14,15,14] ; AVX512DQ-BW-NEXT: vpshufd {{.*#+}} ymm4 = ymm4[2,2,3,3,6,6,7,7] ; AVX512DQ-BW-NEXT: movl $693250386, %eax # imm = 0x29522952 ; AVX512DQ-BW-NEXT: kmovd %eax, %k1 -; AVX512DQ-BW-NEXT: vmovdqu8 %ymm4, %ymm2 {%k1} -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] +; AVX512DQ-BW-NEXT: vmovdqu8 %ymm4, %ymm3 {%k1} +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,3,3] ; AVX512DQ-BW-NEXT: vmovdqa 32(%rdx), %xmm6 ; AVX512DQ-BW-NEXT: vmovdqa 32(%rcx), %xmm12 ; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm4 = xmm12[0],xmm6[0],xmm12[1],xmm6[1],xmm12[2],xmm6[2],xmm12[3],xmm6[3],xmm12[4],xmm6[4],xmm12[5],xmm6[5],xmm12[6],xmm6[6],xmm12[7],xmm6[7] ; AVX512DQ-BW-NEXT: vmovdqa {{.*#+}} xmm7 = [2,u,1,0,5,4,u,3,u,7,6,11,10,u,9,8] ; AVX512DQ-BW-NEXT: vpshufb %xmm7, %xmm4, %xmm4 ; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm4 = ymm4[0,0,1,1] -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm4, %zmm2, %zmm10 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm4, %zmm3, %zmm10 ; AVX512DQ-BW-NEXT: vmovdqa (%rsi), %ymm4 ; AVX512DQ-BW-NEXT: vpbroadcastq {{.*#+}} ymm15 = [11,0,13,10,15,12,0,14,11,0,13,10,15,12,0,14,11,0,13,10,15,12,0,14,11,0,13,10,15,12,0,14] -; AVX512DQ-BW-NEXT: vpshufb %ymm15, %ymm4, %ymm2 +; AVX512DQ-BW-NEXT: vpshufb %ymm15, %ymm4, %ymm3 ; AVX512DQ-BW-NEXT: vmovdqa (%rdi), %ymm5 ; AVX512DQ-BW-NEXT: vpshufhw {{.*#+}} ymm9 = ymm5[0,1,2,3,6,5,6,7,8,9,10,11,14,13,14,15] ; AVX512DQ-BW-NEXT: vpshufd {{.*#+}} ymm9 = ymm9[2,2,3,3,6,6,7,7] ; AVX512DQ-BW-NEXT: movl $1251232404, %eax # imm = 0x4A944A94 ; AVX512DQ-BW-NEXT: kmovd %eax, %k5 -; AVX512DQ-BW-NEXT: vmovdqu8 %ymm9, %ymm2 {%k5} -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] +; AVX512DQ-BW-NEXT: vmovdqu8 %ymm9, %ymm3 {%k5} +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,3,3] ; AVX512DQ-BW-NEXT: vmovdqa 32(%rsi), %xmm13 ; AVX512DQ-BW-NEXT: vmovdqa 32(%rdi), %xmm14 ; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm11 = xmm14[0],xmm13[0],xmm14[1],xmm13[1],xmm14[2],xmm13[2],xmm14[3],xmm13[3],xmm14[4],xmm13[4],xmm14[5],xmm13[5],xmm14[6],xmm13[6],xmm14[7],xmm13[7] ; AVX512DQ-BW-NEXT: vmovdqa {{.*#+}} xmm9 = [0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] ; AVX512DQ-BW-NEXT: vpshufb %xmm9, %xmm11, %xmm11 ; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm11 = ymm11[0,0,1,1] -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm11, %zmm2, %zmm2 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm11, %zmm3, %zmm3 ; AVX512DQ-BW-NEXT: movabsq $1785168781326730801, %rax # imm = 0x18C6318C6318C631 ; AVX512DQ-BW-NEXT: kmovq %rax, %k4 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm10, %zmm2 {%k4} +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm10, %zmm3 {%k4} ; AVX512DQ-BW-NEXT: vmovdqa64 32(%r8), %ymm16 ; AVX512DQ-BW-NEXT: vpmovsxbd {{.*#+}} zmm10 = [6,6,6,6,7,7,7,7,16,16,16,16,16,16,17,17] -; AVX512DQ-BW-NEXT: vpermi2d %zmm16, %zmm3, %zmm10 +; AVX512DQ-BW-NEXT: vpermi2d %zmm16, %zmm2, %zmm10 ; AVX512DQ-BW-NEXT: movabsq $2380225041768974402, %rax # imm = 0x2108421084210842 ; AVX512DQ-BW-NEXT: kmovq %rax, %k2 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm10, %zmm2 {%k2} +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm10, %zmm3 {%k2} ; AVX512DQ-BW-NEXT: vmovdqa64 32(%rdx), %ymm23 ; AVX512DQ-BW-NEXT: vmovdqa {{.*#+}} ymm10 = [128,128,12,13,128,128,128,128,14,128,128,128,14,15,128,128,128,128,16,128,128,128,16,17,128,128,128,128,18,128,128,128] ; AVX512DQ-BW-NEXT: vpshufb %ymm10, %ymm23, %ymm17 @@ -5923,21 +5815,21 @@ define void @store_i8_stride5_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} xmm21 = [128,8,u,128,7,128,9,u,11,u,128,10,128,12,u,128] ; AVX512DQ-BW-NEXT: vpshufb %xmm21, %xmm13, %xmm13 ; AVX512DQ-BW-NEXT: vpor %xmm12, %xmm13, %xmm12 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm13 = ymm12[0,0,1,1] +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm14 = ymm12[0,0,1,1] ; AVX512DQ-BW-NEXT: vmovdqa64 32(%rdi), %ymm25 ; AVX512DQ-BW-NEXT: vpmovsxbd {{.*#+}} ymm12 = [3,3,3,0,4,4,4,4] ; AVX512DQ-BW-NEXT: vpermd %ymm25, %ymm12, %ymm17 ; AVX512DQ-BW-NEXT: vmovdqa64 32(%rsi), %ymm26 -; AVX512DQ-BW-NEXT: vpbroadcastq {{.*#+}} ymm14 = [0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14] +; AVX512DQ-BW-NEXT: vpbroadcastq {{.*#+}} ymm13 = [0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14] ; AVX512DQ-BW-NEXT: movl $138547332, %eax # imm = 0x8421084 ; AVX512DQ-BW-NEXT: kmovd %eax, %k3 -; AVX512DQ-BW-NEXT: vpshufb %ymm14, %ymm26, %ymm17 {%k3} -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm17, %zmm13, %zmm13 +; AVX512DQ-BW-NEXT: vpshufb %ymm13, %ymm26, %ymm17 {%k3} +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm17, %zmm14, %zmm14 ; AVX512DQ-BW-NEXT: movabsq $-8330787646191410408, %rax # imm = 0x8C6318C6318C6318 ; AVX512DQ-BW-NEXT: kmovq %rax, %k2 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm13, %zmm6 {%k2} -; AVX512DQ-BW-NEXT: vpmovsxbd {{.*#+}} ymm13 = [3,3,3,3,0,4,4,4] -; AVX512DQ-BW-NEXT: vpermd %ymm16, %ymm13, %ymm17 +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm14, %zmm6 {%k2} +; AVX512DQ-BW-NEXT: vpmovsxbd {{.*#+}} ymm14 = [3,3,3,3,0,4,4,4] +; AVX512DQ-BW-NEXT: vpermd %ymm16, %ymm14, %ymm17 ; AVX512DQ-BW-NEXT: vpshufd {{.*#+}} xmm18 = mem[1,1,2,2] ; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm18 = ymm18[0,1,1,1] ; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm17, %zmm18, %zmm17 @@ -5946,32 +5838,28 @@ define void @store_i8_stride5_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-NEXT: vmovdqu8 %zmm17, %zmm6 {%k6} ; AVX512DQ-BW-NEXT: vbroadcasti32x4 {{.*#+}} ymm17 = [19,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128] ; AVX512DQ-BW-NEXT: # ymm17 = mem[0,1,2,3,0,1,2,3] -; AVX512DQ-BW-NEXT: vpshufb %ymm17, %ymm26, %ymm18 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm27 = ymm18[2,2,3,3] +; AVX512DQ-BW-NEXT: vpshufb %ymm17, %ymm26, %ymm27 ; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} ymm18 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,128] ; AVX512DQ-BW-NEXT: vpshufb %ymm18, %ymm25, %ymm28 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm28 = ymm28[2,2,3,3] ; AVX512DQ-BW-NEXT: vporq %ymm27, %ymm28, %ymm27 ; AVX512DQ-BW-NEXT: vpshufb %ymm15, %ymm26, %ymm15 ; AVX512DQ-BW-NEXT: vpshufhw {{.*#+}} ymm25 = ymm25[0,1,2,3,6,5,6,7,8,9,10,11,14,13,14,15] ; AVX512DQ-BW-NEXT: vpshufd {{.*#+}} ymm25 = ymm25[2,2,3,3,6,6,7,7] ; AVX512DQ-BW-NEXT: vmovdqu8 %ymm25, %ymm15 {%k5} -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,2,3,3] ; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm15, %zmm27, %zmm15 ; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} ymm25 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25] ; AVX512DQ-BW-NEXT: vpshufb %ymm25, %ymm23, %ymm26 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm26 = ymm26[2,2,3,3] ; AVX512DQ-BW-NEXT: vbroadcasti32x4 {{.*#+}} ymm27 = [128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128] ; AVX512DQ-BW-NEXT: # ymm27 = mem[0,1,2,3,0,1,2,3] ; AVX512DQ-BW-NEXT: vpshufb %ymm27, %ymm24, %ymm28 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm28 = ymm28[2,2,3,3] ; AVX512DQ-BW-NEXT: vporq %ymm26, %ymm28, %ymm26 ; AVX512DQ-BW-NEXT: vpshufb %ymm8, %ymm24, %ymm8 ; AVX512DQ-BW-NEXT: vpshufhw {{.*#+}} ymm23 = ymm23[0,1,2,3,5,6,7,6,8,9,10,11,13,14,15,14] ; AVX512DQ-BW-NEXT: vpshufd {{.*#+}} ymm23 = ymm23[2,2,3,3,6,6,7,7] ; AVX512DQ-BW-NEXT: vmovdqu8 %ymm23, %ymm8 {%k1} -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] ; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm8, %zmm26, %zmm8 +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm15 = zmm15[2,2,3,3,6,6,7,7] +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm8 = zmm8[2,2,3,3,6,6,7,7] ; AVX512DQ-BW-NEXT: vmovdqu8 %zmm15, %zmm8 {%k4} ; AVX512DQ-BW-NEXT: vpmovsxbd {{.*#+}} zmm15 = [4,6,5,5,5,5,4,6,6,6,6,6,7,7,7,7] ; AVX512DQ-BW-NEXT: vpermd %zmm16, %zmm15, %zmm15 @@ -6000,33 +5888,31 @@ define void @store_i8_stride5_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-NEXT: kmovq %rax, %k1 ; AVX512DQ-BW-NEXT: vmovdqu8 %zmm7, %zmm9 {%k1} ; AVX512DQ-BW-NEXT: vpmovsxbd {{.*#+}} zmm7 = [0,0,0,0,0,0,1,1,1,1,2,2,2,2,2,2] -; AVX512DQ-BW-NEXT: vpermd %zmm3, %zmm7, %zmm3 +; AVX512DQ-BW-NEXT: vpermd %zmm2, %zmm7, %zmm2 ; AVX512DQ-BW-NEXT: movabsq $595056260442243600, %rax # imm = 0x842108421084210 ; AVX512DQ-BW-NEXT: kmovq %rax, %k1 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm3, %zmm9 {%k1} -; AVX512DQ-BW-NEXT: vpshufb %ymm25, %ymm1, %ymm3 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,3,3] -; AVX512DQ-BW-NEXT: vpshufb %ymm27, %ymm0, %ymm7 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] -; AVX512DQ-BW-NEXT: vpor %ymm3, %ymm7, %ymm3 -; AVX512DQ-BW-NEXT: vpshufb %ymm10, %ymm1, %ymm1 -; AVX512DQ-BW-NEXT: vpshufb %ymm11, %ymm0, %ymm0 +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm2, %zmm9 {%k1} +; AVX512DQ-BW-NEXT: vpshufb %ymm10, %ymm1, %ymm2 +; AVX512DQ-BW-NEXT: vpshufb %ymm11, %ymm0, %ymm7 +; AVX512DQ-BW-NEXT: vpor %ymm2, %ymm7, %ymm2 +; AVX512DQ-BW-NEXT: vpshufb %ymm25, %ymm1, %ymm1 +; AVX512DQ-BW-NEXT: vpshufb %ymm27, %ymm0, %ymm0 ; AVX512DQ-BW-NEXT: vpor %ymm1, %ymm0, %ymm0 -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm3, %zmm0, %zmm0 +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,2,3,3] +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm0, %zmm2, %zmm0 ; AVX512DQ-BW-NEXT: vpermd %ymm5, %ymm12, %ymm1 -; AVX512DQ-BW-NEXT: vpshufb %ymm14, %ymm4, %ymm1 {%k3} -; AVX512DQ-BW-NEXT: vpshufb %ymm17, %ymm4, %ymm3 +; AVX512DQ-BW-NEXT: vpshufb %ymm13, %ymm4, %ymm1 {%k3} +; AVX512DQ-BW-NEXT: vpshufb %ymm17, %ymm4, %ymm2 ; AVX512DQ-BW-NEXT: vpshufb %ymm18, %ymm5, %ymm4 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,3,3] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,2,3,3] -; AVX512DQ-BW-NEXT: vpor %ymm3, %ymm4, %ymm3 -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm3, %zmm1, %zmm1 +; AVX512DQ-BW-NEXT: vpor %ymm2, %ymm4, %ymm2 +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm2, %zmm1, %zmm1 ; AVX512DQ-BW-NEXT: vmovdqu8 %zmm0, %zmm1 {%k2} ; AVX512DQ-BW-NEXT: vmovdqa (%r8), %ymm0 -; AVX512DQ-BW-NEXT: vpermd %ymm0, %ymm13, %ymm3 +; AVX512DQ-BW-NEXT: vpermd %ymm0, %ymm14, %ymm2 ; AVX512DQ-BW-NEXT: vpshufd {{.*#+}} ymm0 = ymm0[0,2,1,1,4,6,5,5] ; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,3,2] -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm0, %zmm3, %zmm0 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm0, %zmm2, %zmm0 ; AVX512DQ-BW-NEXT: movabsq $1190112520884487201, %rax # imm = 0x1084210842108421 ; AVX512DQ-BW-NEXT: kmovq %rax, %k1 ; AVX512DQ-BW-NEXT: vmovdqu8 %zmm0, %zmm1 {%k1} @@ -6034,166 +5920,157 @@ define void @store_i8_stride5_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-NEXT: vmovdqa64 %zmm9, (%r9) ; AVX512DQ-BW-NEXT: vmovdqa64 %zmm8, 256(%r9) ; AVX512DQ-BW-NEXT: vmovdqa64 %zmm6, 192(%r9) -; AVX512DQ-BW-NEXT: vmovdqa64 %zmm2, 128(%r9) +; AVX512DQ-BW-NEXT: vmovdqa64 %zmm3, 128(%r9) ; AVX512DQ-BW-NEXT: vzeroupper ; AVX512DQ-BW-NEXT: retq ; ; AVX512DQ-BW-FCP-LABEL: store_i8_stride5_vf64: ; AVX512DQ-BW-FCP: # %bb.0: -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%r8), %zmm5 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%r8), %zmm0 ; AVX512DQ-BW-FCP-NEXT: vmovdqa64 32(%rdx), %ymm21 -; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} ymm1 = [128,128,12,13,128,128,128,128,14,128,128,128,14,15,128,128,128,128,16,128,128,128,16,17,128,128,128,128,18,128,128,128] -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm1, %ymm21, %ymm0 -; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rcx), %ymm13 -; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} ymm2 = [128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128] -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm2, %ymm13, %ymm3 -; AVX512DQ-BW-FCP-NEXT: vpor %ymm0, %ymm3, %ymm0 -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rcx), %xmm6 -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 32(%rcx), %xmm18 -; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm8 = [128,6,128,8,u,128,7,128,9,128,11,u,128,10,128,12] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm8, %xmm18, %xmm3 -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdx), %xmm7 -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 32(%rdx), %xmm20 -; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm10 = [6,128,8,128,u,7,128,9,128,11,128,u,10,128,12,128] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm10, %xmm20, %xmm4 -; AVX512DQ-BW-FCP-NEXT: vpor %xmm3, %xmm4, %xmm3 +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} ymm6 = [128,128,12,13,128,128,128,128,14,128,128,128,14,15,128,128,128,128,16,128,128,128,16,17,128,128,128,128,18,128,128,128] +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm6, %ymm21, %ymm1 +; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rcx), %ymm8 +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} ymm7 = [128,128,128,128,13,128,128,128,128,14,128,128,128,128,15,128,128,128,128,16,128,128,128,128,17,128,128,128,128,18,128,128] +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm7, %ymm8, %ymm2 +; AVX512DQ-BW-FCP-NEXT: vpor %ymm1, %ymm2, %ymm1 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rcx), %xmm11 +; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rcx), %xmm2 +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm14 = [128,6,128,8,u,128,7,128,9,128,11,u,128,10,128,12] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm14, %xmm2, %xmm3 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdx), %xmm12 +; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rdx), %xmm4 +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm15 = [6,128,8,128,u,7,128,9,128,11,128,u,10,128,12,128] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm15, %xmm4, %xmm5 +; AVX512DQ-BW-FCP-NEXT: vpor %xmm3, %xmm5, %xmm3 ; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm3[0,0,1,1] -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm3, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdi), %xmm9 -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 32(%rdi), %xmm17 -; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm12 = [8,128,u,7,128,9,128,u,128,u,10,128,12,128,u,11] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm12, %xmm17, %xmm3 -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rsi), %xmm11 -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 32(%rsi), %xmm19 -; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm14 = [128,8,u,128,7,128,9,u,11,u,128,10,128,12,u,128] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm14, %xmm19, %xmm4 -; AVX512DQ-BW-FCP-NEXT: vpor %xmm3, %xmm4, %xmm3 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm15 = ymm3[0,0,1,1] -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 32(%rdi), %ymm16 -; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} ymm3 = [3,3,3,0,4,4,4,4] -; AVX512DQ-BW-FCP-NEXT: vpermd %ymm16, %ymm3, %ymm22 +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm3, %zmm1 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdi), %xmm13 +; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rdi), %xmm3 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} xmm17 = [8,128,u,7,128,9,128,u,128,u,10,128,12,128,u,11] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm17, %xmm3, %xmm9 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rsi), %xmm16 +; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rsi), %xmm5 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} xmm20 = [128,8,u,128,7,128,9,u,11,u,128,10,128,12,u,128] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm20, %xmm5, %xmm10 +; AVX512DQ-BW-FCP-NEXT: vpor %xmm9, %xmm10, %xmm9 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm18 = ymm9[0,0,1,1] +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 32(%rdi), %ymm19 +; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} ymm9 = [3,3,3,0,4,4,4,4] +; AVX512DQ-BW-FCP-NEXT: vpermd %ymm19, %ymm9, %ymm22 ; AVX512DQ-BW-FCP-NEXT: vmovdqa64 32(%rsi), %ymm23 -; AVX512DQ-BW-FCP-NEXT: vpbroadcastq {{.*#+}} ymm4 = [0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14] +; AVX512DQ-BW-FCP-NEXT: vpbroadcastq {{.*#+}} ymm10 = [0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14,0,0,13,2,15,0,1,14] ; AVX512DQ-BW-FCP-NEXT: movl $138547332, %eax # imm = 0x8421084 ; AVX512DQ-BW-FCP-NEXT: kmovd %eax, %k1 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm4, %ymm23, %ymm22 {%k1} -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm22, %zmm15, %zmm15 +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm10, %ymm23, %ymm22 {%k1} +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm22, %zmm18, %zmm18 ; AVX512DQ-BW-FCP-NEXT: movabsq $-8330787646191410408, %rax # imm = 0x8C6318C6318C6318 ; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k2 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm15, %zmm0 {%k2} -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 32(%r8), %ymm24 -; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm15 = [1,1,2,2,2,2,2,2,27,27,27,27,0,28,28,28] -; AVX512DQ-BW-FCP-NEXT: vpermi2d %zmm5, %zmm24, %zmm15 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm18, %zmm1 {%k2} +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 32(%r8), %ymm22 +; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm18 = [1,1,2,2,2,2,2,2,27,27,27,27,0,28,28,28] +; AVX512DQ-BW-FCP-NEXT: vpermi2d %zmm0, %zmm22, %zmm18 ; AVX512DQ-BW-FCP-NEXT: movabsq $4760450083537948804, %rax # imm = 0x4210842108421084 ; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k3 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm15, %zmm0 {%k3} -; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm22 = zmm23[0,1,2,3],mem[4,5,6,7] -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm15 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,128,128,26,128,28,128,128,128,128,29,128,31,128,128,30] -; AVX512DQ-BW-FCP-NEXT: vpshufb %zmm15, %zmm22, %zmm22 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm22 = zmm22[2,2,3,3,6,6,7,7] -; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm23 = zmm16[0,1,2,3],mem[4,5,6,7] -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm16 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,26,128,28,128,128,27,128,29,128,31,128,128,30,128] -; AVX512DQ-BW-FCP-NEXT: vpshufb %zmm16, %zmm23, %zmm23 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm18, %zmm1 {%k3} +; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm23 = zmm23[0,1,2,3],mem[4,5,6,7] +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm18 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,19,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,128,128,26,128,28,128,128,128,128,29,128,31,128,128,30] +; AVX512DQ-BW-FCP-NEXT: vpshufb %zmm18, %zmm23, %zmm23 +; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm24 = zmm19[0,1,2,3],mem[4,5,6,7] +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm19 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,21,128,128,20,128,22,128,24,128,128,23,128,25,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,26,128,28,128,128,27,128,29,128,31,128,128,30,128] +; AVX512DQ-BW-FCP-NEXT: vpshufb %zmm19, %zmm24, %zmm24 +; AVX512DQ-BW-FCP-NEXT: vporq %zmm23, %zmm24, %zmm23 ; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm23 = zmm23[2,2,3,3,6,6,7,7] -; AVX512DQ-BW-FCP-NEXT: vporq %zmm22, %zmm23, %zmm23 -; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm22 = zmm21[0,1,2,3],mem[4,5,6,7] -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm21 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25,128,27,128,128,26,128,28,128,30,128,128,29,128,31,128] -; AVX512DQ-BW-FCP-NEXT: vpshufb %zmm21, %zmm22, %zmm22 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm25 = zmm22[2,2,3,3,6,6,7,7] -; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm13 = zmm13[0,1,2,3],mem[4,5,6,7] -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm22 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,27,128,128,26,128,28,128,30,128,128,29,128,31,128,128] -; AVX512DQ-BW-FCP-NEXT: vpshufb %zmm22, %zmm13, %zmm13 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm13 = zmm13[2,2,3,3,6,6,7,7] -; AVX512DQ-BW-FCP-NEXT: vporq %zmm25, %zmm13, %zmm13 +; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm21 = zmm21[0,1,2,3],mem[4,5,6,7] +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm24 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,19,128,21,128,21,20,128,22,128,24,128,22,23,128,25,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25,128,27,128,128,26,128,28,128,30,128,128,29,128,31,128] +; AVX512DQ-BW-FCP-NEXT: vpshufb %zmm24, %zmm21, %zmm21 +; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm8 = zmm8[0,1,2,3],mem[4,5,6,7] +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm25 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,19,128,21,128,128,20,128,22,128,24,128,128,23,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,27,128,128,26,128,28,128,30,128,128,29,128,31,128,128] +; AVX512DQ-BW-FCP-NEXT: vpshufb %zmm25, %zmm8, %zmm8 +; AVX512DQ-BW-FCP-NEXT: vporq %zmm21, %zmm8, %zmm8 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm8 = zmm8[2,2,3,3,6,6,7,7] ; AVX512DQ-BW-FCP-NEXT: movabsq $1785168781326730801, %rax # imm = 0x18C6318C6318C631 ; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k3 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm23, %zmm13 {%k3} -; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm23 = [4,6,5,5,5,5,4,6,30,30,30,30,31,31,31,31] -; AVX512DQ-BW-FCP-NEXT: vpermi2d %zmm5, %zmm24, %zmm23 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm23, %zmm8 {%k3} +; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm21 = [4,6,5,5,5,5,4,6,30,30,30,30,31,31,31,31] +; AVX512DQ-BW-FCP-NEXT: vpermi2d %zmm0, %zmm22, %zmm21 ; AVX512DQ-BW-FCP-NEXT: movabsq $-8925843906633654008, %rax # imm = 0x8421084210842108 ; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k4 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm23, %zmm13 {%k4} -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rcx), %ymm23 -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm24 = ymm23[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm23[27],zero,zero,ymm23[26],zero,ymm23[28],zero,ymm23[30],zero,zero,ymm23[29],zero,ymm23[31],zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm25 = ymm24[2,2,3,3] -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rdx), %ymm24 -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm26 = ymm24[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm24[27],zero,zero,ymm24[26],zero,ymm24[28],zero,ymm24[30],zero,zero,ymm24[29],zero,ymm24[31],zero,zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm26 = ymm26[2,2,3,3] -; AVX512DQ-BW-FCP-NEXT: vporq %ymm25, %ymm26, %ymm25 -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm18 = xmm18[0],xmm20[0],xmm18[1],xmm20[1],xmm18[2],xmm20[2],xmm18[3],xmm20[3],xmm18[4],xmm20[4],xmm18[5],xmm20[5],xmm18[6],xmm20[6],xmm18[7],xmm20[7] -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} xmm26 = [2,u,1,0,5,4,u,3,u,7,6,11,10,u,9,8] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm26, %xmm18, %xmm18 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm18 = ymm18[0,0,1,1] -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm18, %zmm25, %zmm25 -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rsi), %ymm18 -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm20 = ymm18[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,ymm18[26],zero,ymm18[28],zero,zero,zero,zero,ymm18[29],zero,ymm18[31],zero,zero,ymm18[30] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm27 = ymm20[2,2,3,3] -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rdi), %ymm20 -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm28 = ymm20[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm20[26],zero,ymm20[28],zero,zero,ymm20[27],zero,ymm20[29],zero,ymm20[31],zero,zero,ymm20[30],zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm28 = ymm28[2,2,3,3] -; AVX512DQ-BW-FCP-NEXT: vporq %ymm27, %ymm28, %ymm27 -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm17 = xmm17[0],xmm19[0],xmm17[1],xmm19[1],xmm17[2],xmm19[2],xmm17[3],xmm19[3],xmm17[4],xmm19[4],xmm17[5],xmm19[5],xmm17[6],xmm19[6],xmm17[7],xmm19[7] -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} xmm19 = [0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm19, %xmm17, %xmm17 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm17 = ymm17[0,0,1,1] -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm17, %zmm27, %zmm17 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm25, %zmm17 {%k3} -; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm25 = [6,6,6,6,7,7,7,7,8,8,8,8,8,8,9,9] -; AVX512DQ-BW-FCP-NEXT: vpermd %zmm5, %zmm25, %zmm5 -; AVX512DQ-BW-FCP-NEXT: movabsq $2380225041768974402, %rax # imm = 0x2108421084210842 -; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k3 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm5, %zmm17 {%k3} -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm8, %xmm6, %xmm5 -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm10, %xmm7, %xmm8 -; AVX512DQ-BW-FCP-NEXT: vpor %xmm5, %xmm8, %xmm5 -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm6 = xmm6[0],xmm7[0],xmm6[1],xmm7[1],xmm6[2],xmm7[2],xmm6[3],xmm7[3],xmm6[4],xmm7[4],xmm6[5],xmm7[5],xmm6[6],xmm7[6],xmm6[7],xmm7[7] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm26, %xmm6, %xmm6 -; AVX512DQ-BW-FCP-NEXT: vinserti32x4 $2, %xmm5, %zmm6, %zmm5 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm5 = zmm5[0,0,1,1,4,4,5,5] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm12, %xmm9, %xmm6 -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm14, %xmm11, %xmm7 -; AVX512DQ-BW-FCP-NEXT: vpor %xmm6, %xmm7, %xmm6 -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm7 = xmm9[0],xmm11[0],xmm9[1],xmm11[1],xmm9[2],xmm11[2],xmm9[3],xmm11[3],xmm9[4],xmm11[4],xmm9[5],xmm11[5],xmm9[6],xmm11[6],xmm9[7],xmm11[7] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm19, %xmm7, %xmm7 -; AVX512DQ-BW-FCP-NEXT: vinserti32x4 $2, %xmm6, %zmm7, %zmm6 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm6 = zmm6[0,0,1,1,4,4,5,5] +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm21, %zmm8 {%k4} +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm14, %xmm11, %xmm14 +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm15, %xmm12, %xmm15 +; AVX512DQ-BW-FCP-NEXT: vpor %xmm14, %xmm15, %xmm14 +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm11 = xmm11[0],xmm12[0],xmm11[1],xmm12[1],xmm11[2],xmm12[2],xmm11[3],xmm12[3],xmm11[4],xmm12[4],xmm11[5],xmm12[5],xmm11[6],xmm12[6],xmm11[7],xmm12[7] +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm12 = [2,u,1,0,5,4,u,3,u,7,6,11,10,u,9,8] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm12, %xmm11, %xmm11 +; AVX512DQ-BW-FCP-NEXT: vinserti32x4 $2, %xmm14, %zmm11, %zmm11 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm14 = zmm11[0,0,1,1,4,4,5,5] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm17, %xmm13, %xmm11 +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm20, %xmm16, %xmm15 +; AVX512DQ-BW-FCP-NEXT: vpor %xmm11, %xmm15, %xmm11 +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm13 = xmm13[0],xmm16[0],xmm13[1],xmm16[1],xmm13[2],xmm16[2],xmm13[3],xmm16[3],xmm13[4],xmm16[4],xmm13[5],xmm16[5],xmm13[6],xmm16[6],xmm13[7],xmm16[7] +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm15 = [0,1,4,5,u,2,3,6,7,10,11,u,8,9,12,13] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm15, %xmm13, %xmm13 +; AVX512DQ-BW-FCP-NEXT: vinserti32x4 $2, %xmm11, %zmm13, %zmm11 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm11 = zmm11[0,0,1,1,4,4,5,5] ; AVX512DQ-BW-FCP-NEXT: movabsq $-4165393823095705204, %rax # imm = 0xC6318C6318C6318C -; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k3 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm5, %zmm6 {%k3} -; AVX512DQ-BW-FCP-NEXT: vbroadcasti64x4 {{.*#+}} zmm5 = mem[0,1,2,3,0,1,2,3] -; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm7 = [0,0,0,0,0,0,1,1,9,9,10,10,10,10,10,10] -; AVX512DQ-BW-FCP-NEXT: vpermd %zmm5, %zmm7, %zmm7 +; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k4 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm14, %zmm11 {%k4} +; AVX512DQ-BW-FCP-NEXT: vbroadcasti64x4 {{.*#+}} zmm13 = mem[0,1,2,3,0,1,2,3] +; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm14 = [0,0,0,0,0,0,1,1,9,9,10,10,10,10,10,10] +; AVX512DQ-BW-FCP-NEXT: vpermd %zmm13, %zmm14, %zmm14 ; AVX512DQ-BW-FCP-NEXT: movabsq $595056260442243600, %rax # imm = 0x842108421084210 -; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k3 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm7, %zmm6 {%k3} -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm21, %ymm24, %ymm7 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm22, %ymm23, %ymm8 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,2,3,3] -; AVX512DQ-BW-FCP-NEXT: vpor %ymm7, %ymm8, %ymm7 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm1, %ymm24, %ymm1 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm2, %ymm23, %ymm2 -; AVX512DQ-BW-FCP-NEXT: vpor %ymm1, %ymm2, %ymm1 -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm1, %zmm1 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm15, %ymm18, %ymm2 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,3,3] -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm16, %ymm20, %ymm7 +; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k4 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm14, %zmm11 {%k4} +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdx), %ymm14 +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm6, %ymm14, %ymm6 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rcx), %ymm16 +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm7, %ymm16, %ymm7 +; AVX512DQ-BW-FCP-NEXT: vpor %ymm6, %ymm7, %ymm6 +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm24, %ymm14, %ymm7 +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm25, %ymm16, %ymm17 +; AVX512DQ-BW-FCP-NEXT: vporq %ymm7, %ymm17, %ymm7 ; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,2,3,3] -; AVX512DQ-BW-FCP-NEXT: vpor %ymm2, %ymm7, %ymm2 -; AVX512DQ-BW-FCP-NEXT: vpermd %ymm20, %ymm3, %ymm3 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm4, %ymm18, %ymm3 {%k1} -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm2 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm2 {%k2} -; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm1 = [3,3,3,3,0,4,4,4,12,14,13,13,13,13,12,14] -; AVX512DQ-BW-FCP-NEXT: vpermd %zmm5, %zmm1, %zmm1 +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm6, %zmm6 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rsi), %ymm7 +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm18, %ymm7, %ymm17 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rdi), %ymm18 +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm19, %ymm18, %ymm19 +; AVX512DQ-BW-FCP-NEXT: vporq %ymm17, %ymm19, %ymm17 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm17 = ymm17[2,2,3,3] +; AVX512DQ-BW-FCP-NEXT: vpermd %ymm18, %ymm9, %ymm9 +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm10, %ymm7, %ymm9 {%k1} +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm17, %zmm9, %zmm9 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm6, %zmm9 {%k2} +; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm6 = [3,3,3,3,0,4,4,4,12,14,13,13,13,13,12,14] +; AVX512DQ-BW-FCP-NEXT: vpermd %zmm13, %zmm6, %zmm6 ; AVX512DQ-BW-FCP-NEXT: movabsq $1190112520884487201, %rax # imm = 0x1084210842108421 ; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k1 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm2 {%k1} -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm2, 64(%r9) -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm6, (%r9) -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm17, 128(%r9) -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm13, 256(%r9) -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm0, 192(%r9) +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm6, %zmm9 {%k1} +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm2[0],xmm4[0],xmm2[1],xmm4[1],xmm2[2],xmm4[2],xmm2[3],xmm4[3],xmm2[4],xmm4[4],xmm2[5],xmm4[5],xmm2[6],xmm4[6],xmm2[7],xmm4[7] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm12, %xmm2, %xmm2 +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm16[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm16[27],zero,zero,ymm16[26],zero,ymm16[28],zero,ymm16[30],zero,zero,ymm16[29],zero,ymm16[31],zero +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm6 = ymm14[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm14[27],zero,zero,ymm14[26],zero,ymm14[28],zero,ymm14[30],zero,zero,ymm14[29],zero,ymm14[31],zero,zero +; AVX512DQ-BW-FCP-NEXT: vpor %ymm4, %ymm6, %ymm4 +; AVX512DQ-BW-FCP-NEXT: vpmovsxbq {{.*#+}} zmm6 = [2,2,3,3,8,8,9,9] +; AVX512DQ-BW-FCP-NEXT: vpermt2q %zmm2, %zmm6, %zmm4 +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm3[0],xmm5[0],xmm3[1],xmm5[1],xmm3[2],xmm5[2],xmm3[3],xmm5[3],xmm3[4],xmm5[4],xmm3[5],xmm5[5],xmm3[6],xmm5[6],xmm3[7],xmm5[7] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm15, %xmm2, %xmm2 +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm7[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,ymm7[26],zero,ymm7[28],zero,zero,zero,zero,ymm7[29],zero,ymm7[31],zero,zero,ymm7[30] +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm18[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm18[26],zero,ymm18[28],zero,zero,ymm18[27],zero,ymm18[29],zero,ymm18[31],zero,zero,ymm18[30],zero +; AVX512DQ-BW-FCP-NEXT: vpor %ymm3, %ymm5, %ymm3 +; AVX512DQ-BW-FCP-NEXT: vpermt2q %zmm2, %zmm6, %zmm3 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm4, %zmm3 {%k3} +; AVX512DQ-BW-FCP-NEXT: vpmovsxbd {{.*#+}} zmm2 = [6,6,6,6,7,7,7,7,8,8,8,8,8,8,9,9] +; AVX512DQ-BW-FCP-NEXT: vpermd %zmm0, %zmm2, %zmm0 +; AVX512DQ-BW-FCP-NEXT: movabsq $2380225041768974402, %rax # imm = 0x2108421084210842 +; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k1 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm0, %zmm3 {%k1} +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm3, 128(%r9) +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm9, 64(%r9) +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm11, (%r9) +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm8, 256(%r9) +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm1, 192(%r9) ; AVX512DQ-BW-FCP-NEXT: vzeroupper ; AVX512DQ-BW-FCP-NEXT: retq %in.vec0 = load <64 x i8>, ptr %in.vecptr0, align 64 diff --git a/llvm/test/CodeGen/X86/vector-interleaved-store-i8-stride-6.ll b/llvm/test/CodeGen/X86/vector-interleaved-store-i8-stride-6.ll index 88144e7880e35768972ac8738b3c1c18272890ee..de34e48c01d7d5a6858a148a89cda0bb60f4c482 100644 --- a/llvm/test/CodeGen/X86/vector-interleaved-store-i8-stride-6.ll +++ b/llvm/test/CodeGen/X86/vector-interleaved-store-i8-stride-6.ll @@ -3004,428 +3004,412 @@ define void @store_i8_stride6_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-LABEL: store_i8_stride6_vf32: ; AVX512BW: # %bb.0: ; AVX512BW-NEXT: movq {{[0-9]+}}(%rsp), %rax -; AVX512BW-NEXT: vmovdqa (%rdi), %ymm3 -; AVX512BW-NEXT: vmovdqa (%rsi), %ymm5 -; AVX512BW-NEXT: vmovdqa (%rdx), %ymm2 -; AVX512BW-NEXT: vmovdqa (%rcx), %ymm4 -; AVX512BW-NEXT: vmovdqa (%r8), %ymm0 -; AVX512BW-NEXT: vmovdqa (%r9), %ymm1 -; AVX512BW-NEXT: vmovdqa (%rsi), %xmm9 -; AVX512BW-NEXT: vpbroadcastq {{.*#+}} xmm6 = [8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0] -; AVX512BW-NEXT: vpshufb %xmm6, %xmm9, %xmm7 -; AVX512BW-NEXT: vmovdqa (%rdi), %xmm10 -; AVX512BW-NEXT: vpshufb %xmm6, %xmm10, %xmm6 -; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm6[8],xmm7[8],xmm6[9],xmm7[9],xmm6[10],xmm7[10],xmm6[11],xmm7[11],xmm6[12],xmm7[12],xmm6[13],xmm7[13],xmm6[14],xmm7[14],xmm6[15],xmm7[15] -; AVX512BW-NEXT: vpermq {{.*#+}} ymm7 = ymm6[0,0,0,1] -; AVX512BW-NEXT: vpbroadcastq {{.*#+}} ymm6 = [5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10] -; AVX512BW-NEXT: vmovdqa (%rcx), %xmm11 -; AVX512BW-NEXT: vpshufb %xmm6, %xmm11, %xmm8 -; AVX512BW-NEXT: vmovdqa (%rdx), %xmm12 -; AVX512BW-NEXT: vpshufb %xmm6, %xmm12, %xmm13 -; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm8 = xmm13[0],xmm8[0],xmm13[1],xmm8[1],xmm13[2],xmm8[2],xmm13[3],xmm8[3],xmm13[4],xmm8[4],xmm13[5],xmm8[5],xmm13[6],xmm8[6],xmm13[7],xmm8[7] -; AVX512BW-NEXT: vpermq {{.*#+}} ymm8 = ymm8[0,0,0,1] -; AVX512BW-NEXT: movw $18724, %cx # imm = 0x4924 +; AVX512BW-NEXT: vmovdqa (%rdi), %ymm9 +; AVX512BW-NEXT: vmovdqa (%rsi), %ymm10 +; AVX512BW-NEXT: vmovdqa (%rdx), %ymm11 +; AVX512BW-NEXT: vmovdqa (%rcx), %ymm12 +; AVX512BW-NEXT: vmovdqa (%r8), %ymm7 +; AVX512BW-NEXT: vmovdqa (%r9), %ymm8 +; AVX512BW-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm9[0],ymm10[0],ymm9[1],ymm10[1],ymm9[2],ymm10[2],ymm9[3],ymm10[3],ymm9[4],ymm10[4],ymm9[5],ymm10[5],ymm9[6],ymm10[6],ymm9[7],ymm10[7],ymm9[16],ymm10[16],ymm9[17],ymm10[17],ymm9[18],ymm10[18],ymm9[19],ymm10[19],ymm9[20],ymm10[20],ymm9[21],ymm10[21],ymm9[22],ymm10[22],ymm9[23],ymm10[23] +; AVX512BW-NEXT: vmovdqa (%rsi), %xmm1 +; AVX512BW-NEXT: vmovdqa (%rdi), %xmm2 +; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm2[8],xmm1[8],xmm2[9],xmm1[9],xmm2[10],xmm1[10],xmm2[11],xmm1[11],xmm2[12],xmm1[12],xmm2[13],xmm1[13],xmm2[14],xmm1[14],xmm2[15],xmm1[15] +; AVX512BW-NEXT: vinserti64x4 $1, %ymm0, %zmm3, %zmm0 +; AVX512BW-NEXT: vpmovsxbw {{.*#+}} zmm3 = [4,3,6,5,4,3,6,5,4,3,6,5,7,7,7,7,24,27,26,25,24,27,26,25,24,27,26,25,28,29,30,29] +; AVX512BW-NEXT: vpermw %zmm0, %zmm3, %zmm0 +; AVX512BW-NEXT: vmovdqa (%rcx), %xmm3 +; AVX512BW-NEXT: vmovdqa (%rdx), %xmm4 +; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm4[8],xmm3[8],xmm4[9],xmm3[9],xmm4[10],xmm3[10],xmm4[11],xmm3[11],xmm4[12],xmm3[12],xmm4[13],xmm3[13],xmm4[14],xmm3[14],xmm4[15],xmm3[15] +; AVX512BW-NEXT: vpmovsxbw {{.*#+}} ymm6 = [5,4,3,6,5,4,3,6,5,4,3,6,7,7,7,7] +; AVX512BW-NEXT: vpermw %ymm5, %ymm6, %ymm5 +; AVX512BW-NEXT: vpunpcklbw {{.*#+}} ymm6 = ymm11[0],ymm12[0],ymm11[1],ymm12[1],ymm11[2],ymm12[2],ymm11[3],ymm12[3],ymm11[4],ymm12[4],ymm11[5],ymm12[5],ymm11[6],ymm12[6],ymm11[7],ymm12[7],ymm11[16],ymm12[16],ymm11[17],ymm12[17],ymm11[18],ymm12[18],ymm11[19],ymm12[19],ymm11[20],ymm12[20],ymm11[21],ymm12[21],ymm11[22],ymm12[22],ymm11[23],ymm12[23] +; AVX512BW-NEXT: vprold $16, %ymm6, %ymm6 +; AVX512BW-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,2,2,3] +; AVX512BW-NEXT: vinserti64x4 $1, %ymm6, %zmm5, %zmm5 +; AVX512BW-NEXT: movl $613566756, %ecx # imm = 0x24924924 ; AVX512BW-NEXT: kmovd %ecx, %k1 -; AVX512BW-NEXT: vmovdqu16 %ymm7, %ymm8 {%k1} -; AVX512BW-NEXT: vinserti64x4 $1, %ymm8, %zmm0, %zmm7 -; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm8 = xmm10[0],xmm9[0],xmm10[1],xmm9[1],xmm10[2],xmm9[2],xmm10[3],xmm9[3],xmm10[4],xmm9[4],xmm10[5],xmm9[5],xmm10[6],xmm9[6],xmm10[7],xmm9[7] -; AVX512BW-NEXT: vpmovsxbw {{.*#+}} ymm13 = [0,3,2,1,0,3,2,1,0,3,2,1,4,5,6,5] -; AVX512BW-NEXT: vpermw %ymm8, %ymm13, %ymm8 -; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm13 = xmm12[0],xmm11[0],xmm12[1],xmm11[1],xmm12[2],xmm11[2],xmm12[3],xmm11[3],xmm12[4],xmm11[4],xmm12[5],xmm11[5],xmm12[6],xmm11[6],xmm12[7],xmm11[7] -; AVX512BW-NEXT: vprold $16, %xmm13, %xmm13 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm13 = ymm13[0,0,0,1] -; AVX512BW-NEXT: movw $9362, %cx # imm = 0x2492 +; AVX512BW-NEXT: vmovdqu16 %zmm5, %zmm0 {%k1} +; AVX512BW-NEXT: vpunpcklbw {{.*#+}} ymm13 = ymm7[0],ymm8[0],ymm7[1],ymm8[1],ymm7[2],ymm8[2],ymm7[3],ymm8[3],ymm7[4],ymm8[4],ymm7[5],ymm8[5],ymm7[6],ymm8[6],ymm7[7],ymm8[7],ymm7[16],ymm8[16],ymm7[17],ymm8[17],ymm7[18],ymm8[18],ymm7[19],ymm8[19],ymm7[20],ymm8[20],ymm7[21],ymm8[21],ymm7[22],ymm8[22],ymm7[23],ymm8[23] +; AVX512BW-NEXT: vmovdqa (%r9), %xmm5 +; AVX512BW-NEXT: vmovdqa (%r8), %xmm6 +; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm14 = xmm6[8],xmm5[8],xmm6[9],xmm5[9],xmm6[10],xmm5[10],xmm6[11],xmm5[11],xmm6[12],xmm5[12],xmm6[13],xmm5[13],xmm6[14],xmm5[14],xmm6[15],xmm5[15] +; AVX512BW-NEXT: vinserti64x4 $1, %ymm13, %zmm14, %zmm13 +; AVX512BW-NEXT: vpmovsxbw {{.*#+}} zmm14 = [2,5,4,3,2,5,4,3,2,5,4,3,6,5,6,7,26,25,24,27,26,25,24,27,26,25,24,27,28,28,28,28] +; AVX512BW-NEXT: movl $1227133513, %ecx # imm = 0x49249249 ; AVX512BW-NEXT: kmovd %ecx, %k2 -; AVX512BW-NEXT: vmovdqu16 %ymm13, %ymm8 {%k2} -; AVX512BW-NEXT: vshufi64x2 {{.*#+}} zmm7 = zmm8[0,1,2,3],zmm7[4,5,6,7] -; AVX512BW-NEXT: vpbroadcastq {{.*#+}} ymm8 = [6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0] -; AVX512BW-NEXT: vmovdqa (%r9), %xmm13 -; AVX512BW-NEXT: vpshufb %xmm8, %xmm13, %xmm14 -; AVX512BW-NEXT: vmovdqa (%r8), %xmm15 -; AVX512BW-NEXT: vpshufb %xmm8, %xmm15, %xmm16 -; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm14 = xmm16[0],xmm14[0],xmm16[1],xmm14[1],xmm16[2],xmm14[2],xmm16[3],xmm14[3],xmm16[4],xmm14[4],xmm16[5],xmm14[5],xmm16[6],xmm14[6],xmm16[7],xmm14[7] -; AVX512BW-NEXT: vpermq {{.*#+}} ymm14 = ymm14[0,0,0,1] -; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm16 = xmm15[0],xmm13[0],xmm15[1],xmm13[1],xmm15[2],xmm13[2],xmm15[3],xmm13[3],xmm15[4],xmm13[4],xmm15[5],xmm13[5],xmm15[6],xmm13[6],xmm15[7],xmm13[7] -; AVX512BW-NEXT: vpmovsxbw {{.*#+}} ymm17 = [2,1,0,3,2,1,0,3,2,1,0,3,4,4,4,4] -; AVX512BW-NEXT: vpermw %ymm16, %ymm17, %ymm16 -; AVX512BW-NEXT: vinserti64x4 $1, %ymm14, %zmm16, %zmm14 -; AVX512BW-NEXT: movl $613566756, %ecx # imm = 0x24924924 -; AVX512BW-NEXT: kmovd %ecx, %k3 -; AVX512BW-NEXT: vmovdqu16 %zmm14, %zmm7 {%k3} -; AVX512BW-NEXT: vpunpcklbw {{.*#+}} ymm14 = ymm3[0],ymm5[0],ymm3[1],ymm5[1],ymm3[2],ymm5[2],ymm3[3],ymm5[3],ymm3[4],ymm5[4],ymm3[5],ymm5[5],ymm3[6],ymm5[6],ymm3[7],ymm5[7],ymm3[16],ymm5[16],ymm3[17],ymm5[17],ymm3[18],ymm5[18],ymm3[19],ymm5[19],ymm3[20],ymm5[20],ymm3[21],ymm5[21],ymm3[22],ymm5[22],ymm3[23],ymm5[23] -; AVX512BW-NEXT: vpmovsxbw {{.*#+}} ymm16 = [8,11,10,9,8,11,10,9,8,11,10,9,12,13,14,13] -; AVX512BW-NEXT: vpermw %ymm14, %ymm16, %ymm14 -; AVX512BW-NEXT: vpunpcklbw {{.*#+}} ymm16 = ymm2[0],ymm4[0],ymm2[1],ymm4[1],ymm2[2],ymm4[2],ymm2[3],ymm4[3],ymm2[4],ymm4[4],ymm2[5],ymm4[5],ymm2[6],ymm4[6],ymm2[7],ymm4[7],ymm2[16],ymm4[16],ymm2[17],ymm4[17],ymm2[18],ymm4[18],ymm2[19],ymm4[19],ymm2[20],ymm4[20],ymm2[21],ymm4[21],ymm2[22],ymm4[22],ymm2[23],ymm4[23] -; AVX512BW-NEXT: vprold $16, %ymm16, %ymm16 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm16 = ymm16[2,2,2,3] -; AVX512BW-NEXT: vmovdqu16 %ymm16, %ymm14 {%k2} -; AVX512BW-NEXT: vinserti64x4 $1, %ymm14, %zmm0, %zmm14 -; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm11 = xmm12[8],xmm11[8],xmm12[9],xmm11[9],xmm12[10],xmm11[10],xmm12[11],xmm11[11],xmm12[12],xmm11[12],xmm12[13],xmm11[13],xmm12[14],xmm11[14],xmm12[15],xmm11[15] -; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm9 = xmm10[8],xmm9[8],xmm10[9],xmm9[9],xmm10[10],xmm9[10],xmm10[11],xmm9[11],xmm10[12],xmm9[12],xmm10[13],xmm9[13],xmm10[14],xmm9[14],xmm10[15],xmm9[15] -; AVX512BW-NEXT: vpmovsxbw {{.*#+}} ymm10 = [4,3,6,5,4,3,6,5,4,3,6,5,7,7,7,7] +; AVX512BW-NEXT: vpermw %zmm13, %zmm14, %zmm0 {%k2} +; AVX512BW-NEXT: vpbroadcastq {{.*#+}} ymm13 = [8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0] +; AVX512BW-NEXT: vpshufb %ymm13, %ymm10, %ymm14 +; AVX512BW-NEXT: vpshufb %ymm13, %ymm9, %ymm13 +; AVX512BW-NEXT: vpunpcklbw {{.*#+}} ymm13 = ymm13[0],ymm14[0],ymm13[1],ymm14[1],ymm13[2],ymm14[2],ymm13[3],ymm14[3],ymm13[4],ymm14[4],ymm13[5],ymm14[5],ymm13[6],ymm14[6],ymm13[7],ymm14[7],ymm13[16],ymm14[16],ymm13[17],ymm14[17],ymm13[18],ymm14[18],ymm13[19],ymm14[19],ymm13[20],ymm14[20],ymm13[21],ymm14[21],ymm13[22],ymm14[22],ymm13[23],ymm14[23] +; AVX512BW-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,2,2,3] +; AVX512BW-NEXT: vpunpckhbw {{.*#+}} ymm14 = ymm11[8],ymm12[8],ymm11[9],ymm12[9],ymm11[10],ymm12[10],ymm11[11],ymm12[11],ymm11[12],ymm12[12],ymm11[13],ymm12[13],ymm11[14],ymm12[14],ymm11[15],ymm12[15],ymm11[24],ymm12[24],ymm11[25],ymm12[25],ymm11[26],ymm12[26],ymm11[27],ymm12[27],ymm11[28],ymm12[28],ymm11[29],ymm12[29],ymm11[30],ymm12[30],ymm11[31],ymm12[31] +; AVX512BW-NEXT: vpmovsxbw {{.*#+}} ymm15 = [13,12,11,14,13,12,11,14,13,12,11,14,15,15,15,15] +; AVX512BW-NEXT: vpermw %ymm14, %ymm15, %ymm14 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm14, %zmm13, %zmm13 +; AVX512BW-NEXT: vpbroadcastq {{.*#+}} ymm14 = [5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10] +; AVX512BW-NEXT: vpshufb %ymm14, %ymm12, %ymm12 +; AVX512BW-NEXT: vpshufb %ymm14, %ymm11, %ymm11 +; AVX512BW-NEXT: vpunpcklbw {{.*#+}} ymm11 = ymm11[0],ymm12[0],ymm11[1],ymm12[1],ymm11[2],ymm12[2],ymm11[3],ymm12[3],ymm11[4],ymm12[4],ymm11[5],ymm12[5],ymm11[6],ymm12[6],ymm11[7],ymm12[7],ymm11[16],ymm12[16],ymm11[17],ymm12[17],ymm11[18],ymm12[18],ymm11[19],ymm12[19],ymm11[20],ymm12[20],ymm11[21],ymm12[21],ymm11[22],ymm12[22],ymm11[23],ymm12[23] +; AVX512BW-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,2,2,3] +; AVX512BW-NEXT: vpunpckhbw {{.*#+}} ymm9 = ymm9[8],ymm10[8],ymm9[9],ymm10[9],ymm9[10],ymm10[10],ymm9[11],ymm10[11],ymm9[12],ymm10[12],ymm9[13],ymm10[13],ymm9[14],ymm10[14],ymm9[15],ymm10[15],ymm9[24],ymm10[24],ymm9[25],ymm10[25],ymm9[26],ymm10[26],ymm9[27],ymm10[27],ymm9[28],ymm10[28],ymm9[29],ymm10[29],ymm9[30],ymm10[30],ymm9[31],ymm10[31] +; AVX512BW-NEXT: vpmovsxbw {{.*#+}} ymm10 = [12,11,14,13,12,11,14,13,12,11,14,13,15,15,15,15] ; AVX512BW-NEXT: vpermw %ymm9, %ymm10, %ymm9 -; AVX512BW-NEXT: vpmovsxbw {{.*#+}} ymm10 = [5,4,3,6,5,4,3,6,5,4,3,6,7,7,7,7] -; AVX512BW-NEXT: vpermw %ymm11, %ymm10, %ymm9 {%k1} -; AVX512BW-NEXT: vshufi64x2 {{.*#+}} zmm9 = zmm9[0,1,2,3],zmm14[4,5,6,7] -; AVX512BW-NEXT: vpunpcklbw {{.*#+}} ymm10 = ymm0[0],ymm1[0],ymm0[1],ymm1[1],ymm0[2],ymm1[2],ymm0[3],ymm1[3],ymm0[4],ymm1[4],ymm0[5],ymm1[5],ymm0[6],ymm1[6],ymm0[7],ymm1[7],ymm0[16],ymm1[16],ymm0[17],ymm1[17],ymm0[18],ymm1[18],ymm0[19],ymm1[19],ymm0[20],ymm1[20],ymm0[21],ymm1[21],ymm0[22],ymm1[22],ymm0[23],ymm1[23] -; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm11 = xmm15[8],xmm13[8],xmm15[9],xmm13[9],xmm15[10],xmm13[10],xmm15[11],xmm13[11],xmm15[12],xmm13[12],xmm15[13],xmm13[13],xmm15[14],xmm13[14],xmm15[15],xmm13[15] -; AVX512BW-NEXT: vinserti64x4 $1, %ymm10, %zmm11, %zmm10 -; AVX512BW-NEXT: vpmovsxbw {{.*#+}} zmm11 = [2,5,4,3,2,5,4,3,2,5,4,3,6,5,6,7,26,25,24,27,26,25,24,27,26,25,24,27,28,28,28,28] -; AVX512BW-NEXT: movl $1227133513, %ecx # imm = 0x49249249 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm9, %zmm11, %zmm9 +; AVX512BW-NEXT: movl $1227114788, %ecx # imm = 0x49244924 ; AVX512BW-NEXT: kmovd %ecx, %k2 -; AVX512BW-NEXT: vpermw %zmm10, %zmm11, %zmm9 {%k2} -; AVX512BW-NEXT: vpunpckhbw {{.*#+}} ymm10 = ymm2[8],ymm4[8],ymm2[9],ymm4[9],ymm2[10],ymm4[10],ymm2[11],ymm4[11],ymm2[12],ymm4[12],ymm2[13],ymm4[13],ymm2[14],ymm4[14],ymm2[15],ymm4[15],ymm2[24],ymm4[24],ymm2[25],ymm4[25],ymm2[26],ymm4[26],ymm2[27],ymm4[27],ymm2[28],ymm4[28],ymm2[29],ymm4[29],ymm2[30],ymm4[30],ymm2[31],ymm4[31] -; AVX512BW-NEXT: vpunpckhbw {{.*#+}} ymm11 = ymm3[8],ymm5[8],ymm3[9],ymm5[9],ymm3[10],ymm5[10],ymm3[11],ymm5[11],ymm3[12],ymm5[12],ymm3[13],ymm5[13],ymm3[14],ymm5[14],ymm3[15],ymm5[15],ymm3[24],ymm5[24],ymm3[25],ymm5[25],ymm3[26],ymm5[26],ymm3[27],ymm5[27],ymm3[28],ymm5[28],ymm3[29],ymm5[29],ymm3[30],ymm5[30],ymm3[31],ymm5[31] -; AVX512BW-NEXT: vpmovsxbw {{.*#+}} ymm12 = [12,11,14,13,12,11,14,13,12,11,14,13,15,15,15,15] -; AVX512BW-NEXT: vpermw %ymm11, %ymm12, %ymm11 -; AVX512BW-NEXT: vpmovsxbw {{.*#+}} ymm12 = [13,12,11,14,13,12,11,14,13,12,11,14,15,15,15,15] -; AVX512BW-NEXT: vpermw %ymm10, %ymm12, %ymm11 {%k1} -; AVX512BW-NEXT: vinserti64x4 $1, %ymm11, %zmm0, %zmm10 -; AVX512BW-NEXT: vpbroadcastq {{.*#+}} ymm11 = [8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0] -; AVX512BW-NEXT: vpshufb %ymm11, %ymm5, %ymm5 -; AVX512BW-NEXT: vpshufb %ymm11, %ymm3, %ymm3 -; AVX512BW-NEXT: vpunpcklbw {{.*#+}} ymm3 = ymm3[0],ymm5[0],ymm3[1],ymm5[1],ymm3[2],ymm5[2],ymm3[3],ymm5[3],ymm3[4],ymm5[4],ymm3[5],ymm5[5],ymm3[6],ymm5[6],ymm3[7],ymm5[7],ymm3[16],ymm5[16],ymm3[17],ymm5[17],ymm3[18],ymm5[18],ymm3[19],ymm5[19],ymm3[20],ymm5[20],ymm3[21],ymm5[21],ymm3[22],ymm5[22],ymm3[23],ymm5[23] -; AVX512BW-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,2,3] -; AVX512BW-NEXT: vpshufb %ymm6, %ymm4, %ymm4 -; AVX512BW-NEXT: vpshufb %ymm6, %ymm2, %ymm2 -; AVX512BW-NEXT: vpunpcklbw {{.*#+}} ymm2 = ymm2[0],ymm4[0],ymm2[1],ymm4[1],ymm2[2],ymm4[2],ymm2[3],ymm4[3],ymm2[4],ymm4[4],ymm2[5],ymm4[5],ymm2[6],ymm4[6],ymm2[7],ymm4[7],ymm2[16],ymm4[16],ymm2[17],ymm4[17],ymm2[18],ymm4[18],ymm2[19],ymm4[19],ymm2[20],ymm4[20],ymm2[21],ymm4[21],ymm2[22],ymm4[22],ymm2[23],ymm4[23] -; AVX512BW-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,2,3] -; AVX512BW-NEXT: vmovdqu16 %ymm3, %ymm2 {%k1} -; AVX512BW-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm2[0,1,2,3],zmm10[4,5,6,7] -; AVX512BW-NEXT: vpshufb %ymm8, %ymm1, %ymm3 -; AVX512BW-NEXT: vpshufb %ymm8, %ymm0, %ymm4 -; AVX512BW-NEXT: vpunpcklbw {{.*#+}} ymm3 = ymm4[0],ymm3[0],ymm4[1],ymm3[1],ymm4[2],ymm3[2],ymm4[3],ymm3[3],ymm4[4],ymm3[4],ymm4[5],ymm3[5],ymm4[6],ymm3[6],ymm4[7],ymm3[7],ymm4[16],ymm3[16],ymm4[17],ymm3[17],ymm4[18],ymm3[18],ymm4[19],ymm3[19],ymm4[20],ymm3[20],ymm4[21],ymm3[21],ymm4[22],ymm3[22],ymm4[23],ymm3[23] -; AVX512BW-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,2,3] -; AVX512BW-NEXT: vpunpckhbw {{.*#+}} ymm0 = ymm0[8],ymm1[8],ymm0[9],ymm1[9],ymm0[10],ymm1[10],ymm0[11],ymm1[11],ymm0[12],ymm1[12],ymm0[13],ymm1[13],ymm0[14],ymm1[14],ymm0[15],ymm1[15],ymm0[24],ymm1[24],ymm0[25],ymm1[25],ymm0[26],ymm1[26],ymm0[27],ymm1[27],ymm0[28],ymm1[28],ymm0[29],ymm1[29],ymm0[30],ymm1[30],ymm0[31],ymm1[31] -; AVX512BW-NEXT: vpmovsxbw {{.*#+}} ymm1 = [10,13,12,11,10,13,12,11,10,13,12,11,14,13,14,15] -; AVX512BW-NEXT: vpermw %ymm0, %ymm1, %ymm0 -; AVX512BW-NEXT: vinserti64x4 $1, %ymm0, %zmm3, %zmm0 +; AVX512BW-NEXT: vmovdqu16 %zmm13, %zmm9 {%k2} +; AVX512BW-NEXT: vpbroadcastq {{.*#+}} ymm10 = [6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0] +; AVX512BW-NEXT: vpshufb %ymm10, %ymm8, %ymm11 +; AVX512BW-NEXT: vpshufb %ymm10, %ymm7, %ymm12 +; AVX512BW-NEXT: vpunpcklbw {{.*#+}} ymm11 = ymm12[0],ymm11[0],ymm12[1],ymm11[1],ymm12[2],ymm11[2],ymm12[3],ymm11[3],ymm12[4],ymm11[4],ymm12[5],ymm11[5],ymm12[6],ymm11[6],ymm12[7],ymm11[7],ymm12[16],ymm11[16],ymm12[17],ymm11[17],ymm12[18],ymm11[18],ymm12[19],ymm11[19],ymm12[20],ymm11[20],ymm12[21],ymm11[21],ymm12[22],ymm11[22],ymm12[23],ymm11[23] +; AVX512BW-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,2,2,3] +; AVX512BW-NEXT: vpunpckhbw {{.*#+}} ymm7 = ymm7[8],ymm8[8],ymm7[9],ymm8[9],ymm7[10],ymm8[10],ymm7[11],ymm8[11],ymm7[12],ymm8[12],ymm7[13],ymm8[13],ymm7[14],ymm8[14],ymm7[15],ymm8[15],ymm7[24],ymm8[24],ymm7[25],ymm8[25],ymm7[26],ymm8[26],ymm7[27],ymm8[27],ymm7[28],ymm8[28],ymm7[29],ymm8[29],ymm7[30],ymm8[30],ymm7[31],ymm8[31] +; AVX512BW-NEXT: vpmovsxbw {{.*#+}} ymm8 = [10,13,12,11,10,13,12,11,10,13,12,11,14,13,14,15] +; AVX512BW-NEXT: vpermw %ymm7, %ymm8, %ymm7 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm7, %zmm11, %zmm7 ; AVX512BW-NEXT: movl $-1840700270, %ecx # imm = 0x92492492 -; AVX512BW-NEXT: kmovd %ecx, %k1 -; AVX512BW-NEXT: vmovdqu16 %zmm0, %zmm2 {%k1} -; AVX512BW-NEXT: vmovdqa64 %zmm2, 128(%rax) -; AVX512BW-NEXT: vmovdqa64 %zmm9, 64(%rax) +; AVX512BW-NEXT: kmovd %ecx, %k2 +; AVX512BW-NEXT: vmovdqu16 %zmm7, %zmm9 {%k2} +; AVX512BW-NEXT: vpshufb %xmm14, %xmm3, %xmm7 +; AVX512BW-NEXT: vpshufb %xmm14, %xmm4, %xmm8 +; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm7 = xmm8[0],xmm7[0],xmm8[1],xmm7[1],xmm8[2],xmm7[2],xmm8[3],xmm7[3],xmm8[4],xmm7[4],xmm8[5],xmm7[5],xmm8[6],xmm7[6],xmm8[7],xmm7[7] +; AVX512BW-NEXT: vpermq {{.*#+}} ymm7 = ymm7[0,0,0,1] +; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm8 = xmm2[0],xmm1[0],xmm2[1],xmm1[1],xmm2[2],xmm1[2],xmm2[3],xmm1[3],xmm2[4],xmm1[4],xmm2[5],xmm1[5],xmm2[6],xmm1[6],xmm2[7],xmm1[7] +; AVX512BW-NEXT: vpmovsxbw {{.*#+}} ymm11 = [0,3,2,1,0,3,2,1,0,3,2,1,4,5,6,5] +; AVX512BW-NEXT: vpermw %ymm8, %ymm11, %ymm8 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm7, %zmm8, %zmm7 +; AVX512BW-NEXT: vpbroadcastq {{.*#+}} xmm8 = [8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0] +; AVX512BW-NEXT: vpshufb %xmm8, %xmm1, %xmm1 +; AVX512BW-NEXT: vpshufb %xmm8, %xmm2, %xmm2 +; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm2[8],xmm1[8],xmm2[9],xmm1[9],xmm2[10],xmm1[10],xmm2[11],xmm1[11],xmm2[12],xmm1[12],xmm2[13],xmm1[13],xmm2[14],xmm1[14],xmm2[15],xmm1[15] +; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm4[0],xmm3[0],xmm4[1],xmm3[1],xmm4[2],xmm3[2],xmm4[3],xmm3[3],xmm4[4],xmm3[4],xmm4[5],xmm3[5],xmm4[6],xmm3[6],xmm4[7],xmm3[7] +; AVX512BW-NEXT: vprold $16, %xmm2, %xmm2 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm1 +; AVX512BW-NEXT: vpermq {{.*#+}} zmm1 = zmm1[0,0,0,1,4,4,4,5] +; AVX512BW-NEXT: movl $1227105426, %ecx # imm = 0x49242492 +; AVX512BW-NEXT: kmovd %ecx, %k2 +; AVX512BW-NEXT: vmovdqu16 %zmm1, %zmm7 {%k2} +; AVX512BW-NEXT: vpshufb %xmm10, %xmm5, %xmm1 +; AVX512BW-NEXT: vpshufb %xmm10, %xmm6, %xmm2 +; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[1],xmm1[1],xmm2[2],xmm1[2],xmm2[3],xmm1[3],xmm2[4],xmm1[4],xmm2[5],xmm1[5],xmm2[6],xmm1[6],xmm2[7],xmm1[7] +; AVX512BW-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,0,0,1] +; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm6[0],xmm5[0],xmm6[1],xmm5[1],xmm6[2],xmm5[2],xmm6[3],xmm5[3],xmm6[4],xmm5[4],xmm6[5],xmm5[5],xmm6[6],xmm5[6],xmm6[7],xmm5[7] +; AVX512BW-NEXT: vpmovsxbw {{.*#+}} ymm3 = [2,1,0,3,2,1,0,3,2,1,0,3,4,4,4,4] +; AVX512BW-NEXT: vpermw %ymm2, %ymm3, %ymm2 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm1 +; AVX512BW-NEXT: vmovdqu16 %zmm1, %zmm7 {%k1} ; AVX512BW-NEXT: vmovdqa64 %zmm7, (%rax) +; AVX512BW-NEXT: vmovdqa64 %zmm9, 128(%rax) +; AVX512BW-NEXT: vmovdqa64 %zmm0, 64(%rax) ; AVX512BW-NEXT: vzeroupper ; AVX512BW-NEXT: retq ; ; AVX512BW-FCP-LABEL: store_i8_stride6_vf32: ; AVX512BW-FCP: # %bb.0: ; AVX512BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax -; AVX512BW-FCP-NEXT: vmovdqa (%rdi), %ymm3 -; AVX512BW-FCP-NEXT: vmovdqa (%rsi), %ymm5 -; AVX512BW-FCP-NEXT: vmovdqa (%rdx), %ymm2 -; AVX512BW-FCP-NEXT: vmovdqa (%rcx), %ymm4 +; AVX512BW-FCP-NEXT: vmovdqa (%rdi), %ymm2 +; AVX512BW-FCP-NEXT: vmovdqa (%rsi), %ymm3 +; AVX512BW-FCP-NEXT: vmovdqa (%rdx), %ymm5 +; AVX512BW-FCP-NEXT: vmovdqa (%rcx), %ymm6 ; AVX512BW-FCP-NEXT: vmovdqa (%r8), %ymm0 ; AVX512BW-FCP-NEXT: vmovdqa (%r9), %ymm1 -; AVX512BW-FCP-NEXT: vmovdqa (%rcx), %xmm9 -; AVX512BW-FCP-NEXT: vmovdqa (%rdx), %xmm10 -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm6 = xmm10[0],xmm9[0],xmm10[1],xmm9[1],xmm10[2],xmm9[2],xmm10[3],xmm9[3],xmm10[4],xmm9[4],xmm10[5],xmm9[5],xmm10[6],xmm9[6],xmm10[7],xmm9[7] -; AVX512BW-FCP-NEXT: vmovdqa (%rsi), %xmm11 +; AVX512BW-FCP-NEXT: vpbroadcastq {{.*#+}} ymm4 = [8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0] +; AVX512BW-FCP-NEXT: vpshufb %ymm4, %ymm3, %ymm7 +; AVX512BW-FCP-NEXT: vpshufb %ymm4, %ymm2, %ymm4 +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm4 = ymm4[0],ymm7[0],ymm4[1],ymm7[1],ymm4[2],ymm7[2],ymm4[3],ymm7[3],ymm4[4],ymm7[4],ymm4[5],ymm7[5],ymm4[6],ymm7[6],ymm4[7],ymm7[7],ymm4[16],ymm7[16],ymm4[17],ymm7[17],ymm4[18],ymm7[18],ymm4[19],ymm7[19],ymm4[20],ymm7[20],ymm4[21],ymm7[21],ymm4[22],ymm7[22],ymm4[23],ymm7[23] +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,2,2,3] +; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} ymm7 = ymm5[8],ymm6[8],ymm5[9],ymm6[9],ymm5[10],ymm6[10],ymm5[11],ymm6[11],ymm5[12],ymm6[12],ymm5[13],ymm6[13],ymm5[14],ymm6[14],ymm5[15],ymm6[15],ymm5[24],ymm6[24],ymm5[25],ymm6[25],ymm5[26],ymm6[26],ymm5[27],ymm6[27],ymm5[28],ymm6[28],ymm5[29],ymm6[29],ymm5[30],ymm6[30],ymm5[31],ymm6[31] +; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm8 = [13,12,11,14,13,12,11,14,13,12,11,14,15,15,15,15] +; AVX512BW-FCP-NEXT: vpermw %ymm7, %ymm8, %ymm7 +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm4, %zmm7 +; AVX512BW-FCP-NEXT: vpbroadcastq {{.*#+}} ymm8 = [5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10] +; AVX512BW-FCP-NEXT: vpshufb %ymm8, %ymm6, %ymm4 +; AVX512BW-FCP-NEXT: vpshufb %ymm8, %ymm5, %ymm9 +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm4 = ymm9[0],ymm4[0],ymm9[1],ymm4[1],ymm9[2],ymm4[2],ymm9[3],ymm4[3],ymm9[4],ymm4[4],ymm9[5],ymm4[5],ymm9[6],ymm4[6],ymm9[7],ymm4[7],ymm9[16],ymm4[16],ymm9[17],ymm4[17],ymm9[18],ymm4[18],ymm9[19],ymm4[19],ymm9[20],ymm4[20],ymm9[21],ymm4[21],ymm9[22],ymm4[22],ymm9[23],ymm4[23] +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,2,2,3] +; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} ymm9 = ymm2[8],ymm3[8],ymm2[9],ymm3[9],ymm2[10],ymm3[10],ymm2[11],ymm3[11],ymm2[12],ymm3[12],ymm2[13],ymm3[13],ymm2[14],ymm3[14],ymm2[15],ymm3[15],ymm2[24],ymm3[24],ymm2[25],ymm3[25],ymm2[26],ymm3[26],ymm2[27],ymm3[27],ymm2[28],ymm3[28],ymm2[29],ymm3[29],ymm2[30],ymm3[30],ymm2[31],ymm3[31] +; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm10 = [12,11,14,13,12,11,14,13,12,11,14,13,15,15,15,15] +; AVX512BW-FCP-NEXT: vpermw %ymm9, %ymm10, %ymm9 +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm9, %zmm4, %zmm4 +; AVX512BW-FCP-NEXT: movl $1227114788, %r10d # imm = 0x49244924 +; AVX512BW-FCP-NEXT: kmovd %r10d, %k1 +; AVX512BW-FCP-NEXT: vmovdqu16 %zmm7, %zmm4 {%k1} +; AVX512BW-FCP-NEXT: vpbroadcastq {{.*#+}} ymm7 = [6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0] +; AVX512BW-FCP-NEXT: vpshufb %ymm7, %ymm1, %ymm9 +; AVX512BW-FCP-NEXT: vpshufb %ymm7, %ymm0, %ymm10 +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm9 = ymm10[0],ymm9[0],ymm10[1],ymm9[1],ymm10[2],ymm9[2],ymm10[3],ymm9[3],ymm10[4],ymm9[4],ymm10[5],ymm9[5],ymm10[6],ymm9[6],ymm10[7],ymm9[7],ymm10[16],ymm9[16],ymm10[17],ymm9[17],ymm10[18],ymm9[18],ymm10[19],ymm9[19],ymm10[20],ymm9[20],ymm10[21],ymm9[21],ymm10[22],ymm9[22],ymm10[23],ymm9[23] +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,2,3] +; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} ymm10 = ymm0[8],ymm1[8],ymm0[9],ymm1[9],ymm0[10],ymm1[10],ymm0[11],ymm1[11],ymm0[12],ymm1[12],ymm0[13],ymm1[13],ymm0[14],ymm1[14],ymm0[15],ymm1[15],ymm0[24],ymm1[24],ymm0[25],ymm1[25],ymm0[26],ymm1[26],ymm0[27],ymm1[27],ymm0[28],ymm1[28],ymm0[29],ymm1[29],ymm0[30],ymm1[30],ymm0[31],ymm1[31] +; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm11 = [10,13,12,11,10,13,12,11,10,13,12,11,14,13,14,15] +; AVX512BW-FCP-NEXT: vpermw %ymm10, %ymm11, %ymm10 +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm9, %zmm9 +; AVX512BW-FCP-NEXT: movl $-1840700270, %r10d # imm = 0x92492492 +; AVX512BW-FCP-NEXT: kmovd %r10d, %k1 +; AVX512BW-FCP-NEXT: vmovdqu16 %zmm9, %zmm4 {%k1} +; AVX512BW-FCP-NEXT: vmovdqa (%rsi), %xmm9 +; AVX512BW-FCP-NEXT: vpbroadcastq {{.*#+}} xmm10 = [8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0] +; AVX512BW-FCP-NEXT: vpshufb %xmm10, %xmm9, %xmm11 ; AVX512BW-FCP-NEXT: vmovdqa (%rdi), %xmm12 -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm7 = xmm12[0],xmm11[0],xmm12[1],xmm11[1],xmm12[2],xmm11[2],xmm12[3],xmm11[3],xmm12[4],xmm11[4],xmm12[5],xmm11[5],xmm12[6],xmm11[6],xmm12[7],xmm11[7] -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm8 = [0,3,2,1,0,3,2,1,0,3,2,1,4,5,6,5] -; AVX512BW-FCP-NEXT: vpermw %ymm7, %ymm8, %ymm8 -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm7 = [1,0,3,2,1,0,3,2,1,0,3,2,5,4,7,6] -; AVX512BW-FCP-NEXT: movw $9362, %cx # imm = 0x2492 -; AVX512BW-FCP-NEXT: kmovd %ecx, %k2 -; AVX512BW-FCP-NEXT: vpermw %ymm6, %ymm7, %ymm8 {%k2} -; AVX512BW-FCP-NEXT: vpbroadcastq {{.*#+}} xmm6 = [8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0] -; AVX512BW-FCP-NEXT: vpshufb %xmm6, %xmm11, %xmm7 -; AVX512BW-FCP-NEXT: vpshufb %xmm6, %xmm12, %xmm6 -; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm6[8],xmm7[8],xmm6[9],xmm7[9],xmm6[10],xmm7[10],xmm6[11],xmm7[11],xmm6[12],xmm7[12],xmm6[13],xmm7[13],xmm6[14],xmm7[14],xmm6[15],xmm7[15] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[0,0,0,1] -; AVX512BW-FCP-NEXT: vpbroadcastq {{.*#+}} ymm7 = [5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10] -; AVX512BW-FCP-NEXT: vpshufb %xmm7, %xmm9, %xmm13 -; AVX512BW-FCP-NEXT: vpshufb %xmm7, %xmm10, %xmm14 -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm13 = xmm14[0],xmm13[0],xmm14[1],xmm13[1],xmm14[2],xmm13[2],xmm14[3],xmm13[3],xmm14[4],xmm13[4],xmm14[5],xmm13[5],xmm14[6],xmm13[6],xmm14[7],xmm13[7] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[0,0,0,1] -; AVX512BW-FCP-NEXT: movw $18724, %cx # imm = 0x4924 +; AVX512BW-FCP-NEXT: vpshufb %xmm10, %xmm12, %xmm10 +; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm10 = xmm10[8],xmm11[8],xmm10[9],xmm11[9],xmm10[10],xmm11[10],xmm10[11],xmm11[11],xmm10[12],xmm11[12],xmm10[13],xmm11[13],xmm10[14],xmm11[14],xmm10[15],xmm11[15] +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[0,0,0,1] +; AVX512BW-FCP-NEXT: vmovdqa (%rcx), %xmm11 +; AVX512BW-FCP-NEXT: vmovdqa (%rdx), %xmm13 +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm14 = xmm13[0],xmm11[0],xmm13[1],xmm11[1],xmm13[2],xmm11[2],xmm13[3],xmm11[3],xmm13[4],xmm11[4],xmm13[5],xmm11[5],xmm13[6],xmm11[6],xmm13[7],xmm11[7] +; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm15 = [1,0,3,2,1,0,3,2,1,0,3,2,5,4,7,6] +; AVX512BW-FCP-NEXT: vpermw %ymm14, %ymm15, %ymm14 +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm14, %zmm10 +; AVX512BW-FCP-NEXT: vpshufb %xmm8, %xmm11, %xmm14 +; AVX512BW-FCP-NEXT: vpshufb %xmm8, %xmm13, %xmm8 +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm8 = xmm8[0],xmm14[0],xmm8[1],xmm14[1],xmm8[2],xmm14[2],xmm8[3],xmm14[3],xmm8[4],xmm14[4],xmm8[5],xmm14[5],xmm8[6],xmm14[6],xmm8[7],xmm14[7] +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[0,0,0,1] +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm14 = xmm12[0],xmm9[0],xmm12[1],xmm9[1],xmm12[2],xmm9[2],xmm12[3],xmm9[3],xmm12[4],xmm9[4],xmm12[5],xmm9[5],xmm12[6],xmm9[6],xmm12[7],xmm9[7] +; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm15 = [0,3,2,1,0,3,2,1,0,3,2,1,4,5,6,5] +; AVX512BW-FCP-NEXT: vpermw %ymm14, %ymm15, %ymm14 +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm8, %zmm14, %zmm8 +; AVX512BW-FCP-NEXT: movl $1227105426, %ecx # imm = 0x49242492 ; AVX512BW-FCP-NEXT: kmovd %ecx, %k1 -; AVX512BW-FCP-NEXT: vmovdqu16 %ymm6, %ymm13 {%k1} -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm13, %zmm0, %zmm6 -; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm6 = zmm8[0,1,2,3],zmm6[4,5,6,7] -; AVX512BW-FCP-NEXT: vpbroadcastq {{.*#+}} ymm8 = [6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0] -; AVX512BW-FCP-NEXT: vmovdqa (%r9), %xmm13 -; AVX512BW-FCP-NEXT: vpshufb %xmm8, %xmm13, %xmm14 +; AVX512BW-FCP-NEXT: vmovdqu16 %zmm10, %zmm8 {%k1} +; AVX512BW-FCP-NEXT: vmovdqa (%r9), %xmm10 +; AVX512BW-FCP-NEXT: vpshufb %xmm7, %xmm10, %xmm14 ; AVX512BW-FCP-NEXT: vmovdqa (%r8), %xmm15 -; AVX512BW-FCP-NEXT: vpshufb %xmm8, %xmm15, %xmm16 -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm14 = xmm16[0],xmm14[0],xmm16[1],xmm14[1],xmm16[2],xmm14[2],xmm16[3],xmm14[3],xmm16[4],xmm14[4],xmm16[5],xmm14[5],xmm16[6],xmm14[6],xmm16[7],xmm14[7] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm14 = ymm14[0,0,0,1] -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm16 = xmm15[0],xmm13[0],xmm15[1],xmm13[1],xmm15[2],xmm13[2],xmm15[3],xmm13[3],xmm15[4],xmm13[4],xmm15[5],xmm13[5],xmm15[6],xmm13[6],xmm15[7],xmm13[7] -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm17 = [2,1,0,3,2,1,0,3,2,1,0,3,4,4,4,4] -; AVX512BW-FCP-NEXT: vpermw %ymm16, %ymm17, %ymm16 -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm14, %zmm16, %zmm14 +; AVX512BW-FCP-NEXT: vpshufb %xmm7, %xmm15, %xmm7 +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm7 = xmm7[0],xmm14[0],xmm7[1],xmm14[1],xmm7[2],xmm14[2],xmm7[3],xmm14[3],xmm7[4],xmm14[4],xmm7[5],xmm14[5],xmm7[6],xmm14[6],xmm7[7],xmm14[7] +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[0,0,0,1] +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm14 = xmm15[0],xmm10[0],xmm15[1],xmm10[1],xmm15[2],xmm10[2],xmm15[3],xmm10[3],xmm15[4],xmm10[4],xmm15[5],xmm10[5],xmm15[6],xmm10[6],xmm15[7],xmm10[7] +; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm16 = [2,1,0,3,2,1,0,3,2,1,0,3,4,4,4,4] +; AVX512BW-FCP-NEXT: vpermw %ymm14, %ymm16, %ymm14 +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm14, %zmm7 ; AVX512BW-FCP-NEXT: movl $613566756, %ecx # imm = 0x24924924 -; AVX512BW-FCP-NEXT: kmovd %ecx, %k3 -; AVX512BW-FCP-NEXT: vmovdqu16 %zmm14, %zmm6 {%k3} -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm14 = ymm2[0],ymm4[0],ymm2[1],ymm4[1],ymm2[2],ymm4[2],ymm2[3],ymm4[3],ymm2[4],ymm4[4],ymm2[5],ymm4[5],ymm2[6],ymm4[6],ymm2[7],ymm4[7],ymm2[16],ymm4[16],ymm2[17],ymm4[17],ymm2[18],ymm4[18],ymm2[19],ymm4[19],ymm2[20],ymm4[20],ymm2[21],ymm4[21],ymm2[22],ymm4[22],ymm2[23],ymm4[23] -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm16 = ymm3[0],ymm5[0],ymm3[1],ymm5[1],ymm3[2],ymm5[2],ymm3[3],ymm5[3],ymm3[4],ymm5[4],ymm3[5],ymm5[5],ymm3[6],ymm5[6],ymm3[7],ymm5[7],ymm3[16],ymm5[16],ymm3[17],ymm5[17],ymm3[18],ymm5[18],ymm3[19],ymm5[19],ymm3[20],ymm5[20],ymm3[21],ymm5[21],ymm3[22],ymm5[22],ymm3[23],ymm5[23] -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm17 = [8,11,10,9,8,11,10,9,8,11,10,9,12,13,14,13] -; AVX512BW-FCP-NEXT: vpermw %ymm16, %ymm17, %ymm16 -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm17 = [9,8,11,10,9,8,11,10,9,8,11,10,13,12,15,14] -; AVX512BW-FCP-NEXT: vpermw %ymm14, %ymm17, %ymm16 {%k2} -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm16, %zmm0, %zmm14 -; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm9 = xmm10[8],xmm9[8],xmm10[9],xmm9[9],xmm10[10],xmm9[10],xmm10[11],xmm9[11],xmm10[12],xmm9[12],xmm10[13],xmm9[13],xmm10[14],xmm9[14],xmm10[15],xmm9[15] -; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm10 = xmm12[8],xmm11[8],xmm12[9],xmm11[9],xmm12[10],xmm11[10],xmm12[11],xmm11[11],xmm12[12],xmm11[12],xmm12[13],xmm11[13],xmm12[14],xmm11[14],xmm12[15],xmm11[15] -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm11 = [4,3,6,5,4,3,6,5,4,3,6,5,7,7,7,7] -; AVX512BW-FCP-NEXT: vpermw %ymm10, %ymm11, %ymm10 -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm11 = [5,4,3,6,5,4,3,6,5,4,3,6,7,7,7,7] -; AVX512BW-FCP-NEXT: vpermw %ymm9, %ymm11, %ymm10 {%k1} -; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm9 = zmm10[0,1,2,3],zmm14[4,5,6,7] -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm10 = ymm0[0],ymm1[0],ymm0[1],ymm1[1],ymm0[2],ymm1[2],ymm0[3],ymm1[3],ymm0[4],ymm1[4],ymm0[5],ymm1[5],ymm0[6],ymm1[6],ymm0[7],ymm1[7],ymm0[16],ymm1[16],ymm0[17],ymm1[17],ymm0[18],ymm1[18],ymm0[19],ymm1[19],ymm0[20],ymm1[20],ymm0[21],ymm1[21],ymm0[22],ymm1[22],ymm0[23],ymm1[23] -; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm11 = xmm15[8],xmm13[8],xmm15[9],xmm13[9],xmm15[10],xmm13[10],xmm15[11],xmm13[11],xmm15[12],xmm13[12],xmm15[13],xmm13[13],xmm15[14],xmm13[14],xmm15[15],xmm13[15] -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm11, %zmm10 -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm11 = [2,5,4,3,2,5,4,3,2,5,4,3,6,5,6,7,26,25,24,27,26,25,24,27,26,25,24,27,28,28,28,28] +; AVX512BW-FCP-NEXT: kmovd %ecx, %k1 +; AVX512BW-FCP-NEXT: vmovdqu16 %zmm7, %zmm8 {%k1} +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm5[0],ymm6[0],ymm5[1],ymm6[1],ymm5[2],ymm6[2],ymm5[3],ymm6[3],ymm5[4],ymm6[4],ymm5[5],ymm6[5],ymm5[6],ymm6[6],ymm5[7],ymm6[7],ymm5[16],ymm6[16],ymm5[17],ymm6[17],ymm5[18],ymm6[18],ymm5[19],ymm6[19],ymm5[20],ymm6[20],ymm5[21],ymm6[21],ymm5[22],ymm6[22],ymm5[23],ymm6[23] +; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm13[8],xmm11[8],xmm13[9],xmm11[9],xmm13[10],xmm11[10],xmm13[11],xmm11[11],xmm13[12],xmm11[12],xmm13[13],xmm11[13],xmm13[14],xmm11[14],xmm13[15],xmm11[15] +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm5, %zmm6, %zmm5 +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm2 = ymm2[0],ymm3[0],ymm2[1],ymm3[1],ymm2[2],ymm3[2],ymm2[3],ymm3[3],ymm2[4],ymm3[4],ymm2[5],ymm3[5],ymm2[6],ymm3[6],ymm2[7],ymm3[7],ymm2[16],ymm3[16],ymm2[17],ymm3[17],ymm2[18],ymm3[18],ymm2[19],ymm3[19],ymm2[20],ymm3[20],ymm2[21],ymm3[21],ymm2[22],ymm3[22],ymm2[23],ymm3[23] +; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm12[8],xmm9[8],xmm12[9],xmm9[9],xmm12[10],xmm9[10],xmm12[11],xmm9[11],xmm12[12],xmm9[12],xmm12[13],xmm9[13],xmm12[14],xmm9[14],xmm12[15],xmm9[15] +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm2 +; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm3 = [4,3,6,5,4,3,6,5,4,3,6,5,7,7,7,7,24,27,26,25,24,27,26,25,24,27,26,25,28,29,30,29] +; AVX512BW-FCP-NEXT: vpermw %zmm2, %zmm3, %zmm2 +; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm3 = [5,4,3,6,5,4,3,6,5,4,3,6,7,7,7,7,25,24,27,26,25,24,27,26,25,24,27,26,29,28,31,30] +; AVX512BW-FCP-NEXT: vpermw %zmm5, %zmm3, %zmm2 {%k1} +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm0[0],ymm1[0],ymm0[1],ymm1[1],ymm0[2],ymm1[2],ymm0[3],ymm1[3],ymm0[4],ymm1[4],ymm0[5],ymm1[5],ymm0[6],ymm1[6],ymm0[7],ymm1[7],ymm0[16],ymm1[16],ymm0[17],ymm1[17],ymm0[18],ymm1[18],ymm0[19],ymm1[19],ymm0[20],ymm1[20],ymm0[21],ymm1[21],ymm0[22],ymm1[22],ymm0[23],ymm1[23] +; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm15[8],xmm10[8],xmm15[9],xmm10[9],xmm15[10],xmm10[10],xmm15[11],xmm10[11],xmm15[12],xmm10[12],xmm15[13],xmm10[13],xmm15[14],xmm10[14],xmm15[15],xmm10[15] +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm1 = [2,5,4,3,2,5,4,3,2,5,4,3,6,5,6,7,26,25,24,27,26,25,24,27,26,25,24,27,28,28,28,28] ; AVX512BW-FCP-NEXT: movl $1227133513, %ecx # imm = 0x49249249 -; AVX512BW-FCP-NEXT: kmovd %ecx, %k2 -; AVX512BW-FCP-NEXT: vpermw %zmm10, %zmm11, %zmm9 {%k2} -; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} ymm10 = ymm2[8],ymm4[8],ymm2[9],ymm4[9],ymm2[10],ymm4[10],ymm2[11],ymm4[11],ymm2[12],ymm4[12],ymm2[13],ymm4[13],ymm2[14],ymm4[14],ymm2[15],ymm4[15],ymm2[24],ymm4[24],ymm2[25],ymm4[25],ymm2[26],ymm4[26],ymm2[27],ymm4[27],ymm2[28],ymm4[28],ymm2[29],ymm4[29],ymm2[30],ymm4[30],ymm2[31],ymm4[31] -; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} ymm11 = ymm3[8],ymm5[8],ymm3[9],ymm5[9],ymm3[10],ymm5[10],ymm3[11],ymm5[11],ymm3[12],ymm5[12],ymm3[13],ymm5[13],ymm3[14],ymm5[14],ymm3[15],ymm5[15],ymm3[24],ymm5[24],ymm3[25],ymm5[25],ymm3[26],ymm5[26],ymm3[27],ymm5[27],ymm3[28],ymm5[28],ymm3[29],ymm5[29],ymm3[30],ymm5[30],ymm3[31],ymm5[31] -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm12 = [12,11,14,13,12,11,14,13,12,11,14,13,15,15,15,15] -; AVX512BW-FCP-NEXT: vpermw %ymm11, %ymm12, %ymm11 -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm12 = [13,12,11,14,13,12,11,14,13,12,11,14,15,15,15,15] -; AVX512BW-FCP-NEXT: vpermw %ymm10, %ymm12, %ymm11 {%k1} -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm0, %zmm10 -; AVX512BW-FCP-NEXT: vpbroadcastq {{.*#+}} ymm11 = [8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0] -; AVX512BW-FCP-NEXT: vpshufb %ymm11, %ymm5, %ymm5 -; AVX512BW-FCP-NEXT: vpshufb %ymm11, %ymm3, %ymm3 -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm3 = ymm3[0],ymm5[0],ymm3[1],ymm5[1],ymm3[2],ymm5[2],ymm3[3],ymm5[3],ymm3[4],ymm5[4],ymm3[5],ymm5[5],ymm3[6],ymm5[6],ymm3[7],ymm5[7],ymm3[16],ymm5[16],ymm3[17],ymm5[17],ymm3[18],ymm5[18],ymm3[19],ymm5[19],ymm3[20],ymm5[20],ymm3[21],ymm5[21],ymm3[22],ymm5[22],ymm3[23],ymm5[23] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,2,3] -; AVX512BW-FCP-NEXT: vpshufb %ymm7, %ymm4, %ymm4 -; AVX512BW-FCP-NEXT: vpshufb %ymm7, %ymm2, %ymm2 -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm2 = ymm2[0],ymm4[0],ymm2[1],ymm4[1],ymm2[2],ymm4[2],ymm2[3],ymm4[3],ymm2[4],ymm4[4],ymm2[5],ymm4[5],ymm2[6],ymm4[6],ymm2[7],ymm4[7],ymm2[16],ymm4[16],ymm2[17],ymm4[17],ymm2[18],ymm4[18],ymm2[19],ymm4[19],ymm2[20],ymm4[20],ymm2[21],ymm4[21],ymm2[22],ymm4[22],ymm2[23],ymm4[23] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,2,3] -; AVX512BW-FCP-NEXT: vmovdqu16 %ymm3, %ymm2 {%k1} -; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm2[0,1,2,3],zmm10[4,5,6,7] -; AVX512BW-FCP-NEXT: vpshufb %ymm8, %ymm1, %ymm3 -; AVX512BW-FCP-NEXT: vpshufb %ymm8, %ymm0, %ymm4 -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm3 = ymm4[0],ymm3[0],ymm4[1],ymm3[1],ymm4[2],ymm3[2],ymm4[3],ymm3[3],ymm4[4],ymm3[4],ymm4[5],ymm3[5],ymm4[6],ymm3[6],ymm4[7],ymm3[7],ymm4[16],ymm3[16],ymm4[17],ymm3[17],ymm4[18],ymm3[18],ymm4[19],ymm3[19],ymm4[20],ymm3[20],ymm4[21],ymm3[21],ymm4[22],ymm3[22],ymm4[23],ymm3[23] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,2,3] -; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} ymm0 = ymm0[8],ymm1[8],ymm0[9],ymm1[9],ymm0[10],ymm1[10],ymm0[11],ymm1[11],ymm0[12],ymm1[12],ymm0[13],ymm1[13],ymm0[14],ymm1[14],ymm0[15],ymm1[15],ymm0[24],ymm1[24],ymm0[25],ymm1[25],ymm0[26],ymm1[26],ymm0[27],ymm1[27],ymm0[28],ymm1[28],ymm0[29],ymm1[29],ymm0[30],ymm1[30],ymm0[31],ymm1[31] -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm1 = [10,13,12,11,10,13,12,11,10,13,12,11,14,13,14,15] -; AVX512BW-FCP-NEXT: vpermw %ymm0, %ymm1, %ymm0 -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm3, %zmm0 -; AVX512BW-FCP-NEXT: movl $-1840700270, %ecx # imm = 0x92492492 ; AVX512BW-FCP-NEXT: kmovd %ecx, %k1 -; AVX512BW-FCP-NEXT: vmovdqu16 %zmm0, %zmm2 {%k1} -; AVX512BW-FCP-NEXT: vmovdqa64 %zmm2, 128(%rax) -; AVX512BW-FCP-NEXT: vmovdqa64 %zmm9, 64(%rax) -; AVX512BW-FCP-NEXT: vmovdqa64 %zmm6, (%rax) +; AVX512BW-FCP-NEXT: vpermw %zmm0, %zmm1, %zmm2 {%k1} +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm2, 64(%rax) +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm8, (%rax) +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm4, 128(%rax) ; AVX512BW-FCP-NEXT: vzeroupper ; AVX512BW-FCP-NEXT: retq ; ; AVX512DQ-BW-LABEL: store_i8_stride6_vf32: ; AVX512DQ-BW: # %bb.0: ; AVX512DQ-BW-NEXT: movq {{[0-9]+}}(%rsp), %rax -; AVX512DQ-BW-NEXT: vmovdqa (%rdi), %ymm3 -; AVX512DQ-BW-NEXT: vmovdqa (%rsi), %ymm5 -; AVX512DQ-BW-NEXT: vmovdqa (%rdx), %ymm2 -; AVX512DQ-BW-NEXT: vmovdqa (%rcx), %ymm4 -; AVX512DQ-BW-NEXT: vmovdqa (%r8), %ymm0 -; AVX512DQ-BW-NEXT: vmovdqa (%r9), %ymm1 -; AVX512DQ-BW-NEXT: vmovdqa (%rsi), %xmm9 -; AVX512DQ-BW-NEXT: vpbroadcastq {{.*#+}} xmm6 = [8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0] -; AVX512DQ-BW-NEXT: vpshufb %xmm6, %xmm9, %xmm7 -; AVX512DQ-BW-NEXT: vmovdqa (%rdi), %xmm10 -; AVX512DQ-BW-NEXT: vpshufb %xmm6, %xmm10, %xmm6 -; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm6[8],xmm7[8],xmm6[9],xmm7[9],xmm6[10],xmm7[10],xmm6[11],xmm7[11],xmm6[12],xmm7[12],xmm6[13],xmm7[13],xmm6[14],xmm7[14],xmm6[15],xmm7[15] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm7 = ymm6[0,0,0,1] -; AVX512DQ-BW-NEXT: vpbroadcastq {{.*#+}} ymm6 = [5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10] -; AVX512DQ-BW-NEXT: vmovdqa (%rcx), %xmm11 -; AVX512DQ-BW-NEXT: vpshufb %xmm6, %xmm11, %xmm8 -; AVX512DQ-BW-NEXT: vmovdqa (%rdx), %xmm12 -; AVX512DQ-BW-NEXT: vpshufb %xmm6, %xmm12, %xmm13 -; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm8 = xmm13[0],xmm8[0],xmm13[1],xmm8[1],xmm13[2],xmm8[2],xmm13[3],xmm8[3],xmm13[4],xmm8[4],xmm13[5],xmm8[5],xmm13[6],xmm8[6],xmm13[7],xmm8[7] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm8 = ymm8[0,0,0,1] -; AVX512DQ-BW-NEXT: movw $18724, %cx # imm = 0x4924 +; AVX512DQ-BW-NEXT: vmovdqa (%rdi), %ymm9 +; AVX512DQ-BW-NEXT: vmovdqa (%rsi), %ymm10 +; AVX512DQ-BW-NEXT: vmovdqa (%rdx), %ymm11 +; AVX512DQ-BW-NEXT: vmovdqa (%rcx), %ymm12 +; AVX512DQ-BW-NEXT: vmovdqa (%r8), %ymm7 +; AVX512DQ-BW-NEXT: vmovdqa (%r9), %ymm8 +; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm9[0],ymm10[0],ymm9[1],ymm10[1],ymm9[2],ymm10[2],ymm9[3],ymm10[3],ymm9[4],ymm10[4],ymm9[5],ymm10[5],ymm9[6],ymm10[6],ymm9[7],ymm10[7],ymm9[16],ymm10[16],ymm9[17],ymm10[17],ymm9[18],ymm10[18],ymm9[19],ymm10[19],ymm9[20],ymm10[20],ymm9[21],ymm10[21],ymm9[22],ymm10[22],ymm9[23],ymm10[23] +; AVX512DQ-BW-NEXT: vmovdqa (%rsi), %xmm1 +; AVX512DQ-BW-NEXT: vmovdqa (%rdi), %xmm2 +; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm2[8],xmm1[8],xmm2[9],xmm1[9],xmm2[10],xmm1[10],xmm2[11],xmm1[11],xmm2[12],xmm1[12],xmm2[13],xmm1[13],xmm2[14],xmm1[14],xmm2[15],xmm1[15] +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm0, %zmm3, %zmm0 +; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} zmm3 = [4,3,6,5,4,3,6,5,4,3,6,5,7,7,7,7,24,27,26,25,24,27,26,25,24,27,26,25,28,29,30,29] +; AVX512DQ-BW-NEXT: vpermw %zmm0, %zmm3, %zmm0 +; AVX512DQ-BW-NEXT: vmovdqa (%rcx), %xmm3 +; AVX512DQ-BW-NEXT: vmovdqa (%rdx), %xmm4 +; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm4[8],xmm3[8],xmm4[9],xmm3[9],xmm4[10],xmm3[10],xmm4[11],xmm3[11],xmm4[12],xmm3[12],xmm4[13],xmm3[13],xmm4[14],xmm3[14],xmm4[15],xmm3[15] +; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} ymm6 = [5,4,3,6,5,4,3,6,5,4,3,6,7,7,7,7] +; AVX512DQ-BW-NEXT: vpermw %ymm5, %ymm6, %ymm5 +; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} ymm6 = ymm11[0],ymm12[0],ymm11[1],ymm12[1],ymm11[2],ymm12[2],ymm11[3],ymm12[3],ymm11[4],ymm12[4],ymm11[5],ymm12[5],ymm11[6],ymm12[6],ymm11[7],ymm12[7],ymm11[16],ymm12[16],ymm11[17],ymm12[17],ymm11[18],ymm12[18],ymm11[19],ymm12[19],ymm11[20],ymm12[20],ymm11[21],ymm12[21],ymm11[22],ymm12[22],ymm11[23],ymm12[23] +; AVX512DQ-BW-NEXT: vprold $16, %ymm6, %ymm6 +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,2,2,3] +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm6, %zmm5, %zmm5 +; AVX512DQ-BW-NEXT: movl $613566756, %ecx # imm = 0x24924924 ; AVX512DQ-BW-NEXT: kmovd %ecx, %k1 -; AVX512DQ-BW-NEXT: vmovdqu16 %ymm7, %ymm8 {%k1} -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm8, %zmm0, %zmm7 -; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm8 = xmm10[0],xmm9[0],xmm10[1],xmm9[1],xmm10[2],xmm9[2],xmm10[3],xmm9[3],xmm10[4],xmm9[4],xmm10[5],xmm9[5],xmm10[6],xmm9[6],xmm10[7],xmm9[7] -; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} ymm13 = [0,3,2,1,0,3,2,1,0,3,2,1,4,5,6,5] -; AVX512DQ-BW-NEXT: vpermw %ymm8, %ymm13, %ymm8 -; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm13 = xmm12[0],xmm11[0],xmm12[1],xmm11[1],xmm12[2],xmm11[2],xmm12[3],xmm11[3],xmm12[4],xmm11[4],xmm12[5],xmm11[5],xmm12[6],xmm11[6],xmm12[7],xmm11[7] -; AVX512DQ-BW-NEXT: vprold $16, %xmm13, %xmm13 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm13 = ymm13[0,0,0,1] -; AVX512DQ-BW-NEXT: movw $9362, %cx # imm = 0x2492 +; AVX512DQ-BW-NEXT: vmovdqu16 %zmm5, %zmm0 {%k1} +; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} ymm13 = ymm7[0],ymm8[0],ymm7[1],ymm8[1],ymm7[2],ymm8[2],ymm7[3],ymm8[3],ymm7[4],ymm8[4],ymm7[5],ymm8[5],ymm7[6],ymm8[6],ymm7[7],ymm8[7],ymm7[16],ymm8[16],ymm7[17],ymm8[17],ymm7[18],ymm8[18],ymm7[19],ymm8[19],ymm7[20],ymm8[20],ymm7[21],ymm8[21],ymm7[22],ymm8[22],ymm7[23],ymm8[23] +; AVX512DQ-BW-NEXT: vmovdqa (%r9), %xmm5 +; AVX512DQ-BW-NEXT: vmovdqa (%r8), %xmm6 +; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm14 = xmm6[8],xmm5[8],xmm6[9],xmm5[9],xmm6[10],xmm5[10],xmm6[11],xmm5[11],xmm6[12],xmm5[12],xmm6[13],xmm5[13],xmm6[14],xmm5[14],xmm6[15],xmm5[15] +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm13, %zmm14, %zmm13 +; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} zmm14 = [2,5,4,3,2,5,4,3,2,5,4,3,6,5,6,7,26,25,24,27,26,25,24,27,26,25,24,27,28,28,28,28] +; AVX512DQ-BW-NEXT: movl $1227133513, %ecx # imm = 0x49249249 ; AVX512DQ-BW-NEXT: kmovd %ecx, %k2 -; AVX512DQ-BW-NEXT: vmovdqu16 %ymm13, %ymm8 {%k2} -; AVX512DQ-BW-NEXT: vshufi64x2 {{.*#+}} zmm7 = zmm8[0,1,2,3],zmm7[4,5,6,7] -; AVX512DQ-BW-NEXT: vpbroadcastq {{.*#+}} ymm8 = [6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0] -; AVX512DQ-BW-NEXT: vmovdqa (%r9), %xmm13 -; AVX512DQ-BW-NEXT: vpshufb %xmm8, %xmm13, %xmm14 -; AVX512DQ-BW-NEXT: vmovdqa (%r8), %xmm15 -; AVX512DQ-BW-NEXT: vpshufb %xmm8, %xmm15, %xmm16 -; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm14 = xmm16[0],xmm14[0],xmm16[1],xmm14[1],xmm16[2],xmm14[2],xmm16[3],xmm14[3],xmm16[4],xmm14[4],xmm16[5],xmm14[5],xmm16[6],xmm14[6],xmm16[7],xmm14[7] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm14 = ymm14[0,0,0,1] -; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm16 = xmm15[0],xmm13[0],xmm15[1],xmm13[1],xmm15[2],xmm13[2],xmm15[3],xmm13[3],xmm15[4],xmm13[4],xmm15[5],xmm13[5],xmm15[6],xmm13[6],xmm15[7],xmm13[7] -; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} ymm17 = [2,1,0,3,2,1,0,3,2,1,0,3,4,4,4,4] -; AVX512DQ-BW-NEXT: vpermw %ymm16, %ymm17, %ymm16 -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm14, %zmm16, %zmm14 -; AVX512DQ-BW-NEXT: movl $613566756, %ecx # imm = 0x24924924 -; AVX512DQ-BW-NEXT: kmovd %ecx, %k3 -; AVX512DQ-BW-NEXT: vmovdqu16 %zmm14, %zmm7 {%k3} -; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} ymm14 = ymm3[0],ymm5[0],ymm3[1],ymm5[1],ymm3[2],ymm5[2],ymm3[3],ymm5[3],ymm3[4],ymm5[4],ymm3[5],ymm5[5],ymm3[6],ymm5[6],ymm3[7],ymm5[7],ymm3[16],ymm5[16],ymm3[17],ymm5[17],ymm3[18],ymm5[18],ymm3[19],ymm5[19],ymm3[20],ymm5[20],ymm3[21],ymm5[21],ymm3[22],ymm5[22],ymm3[23],ymm5[23] -; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} ymm16 = [8,11,10,9,8,11,10,9,8,11,10,9,12,13,14,13] -; AVX512DQ-BW-NEXT: vpermw %ymm14, %ymm16, %ymm14 -; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} ymm16 = ymm2[0],ymm4[0],ymm2[1],ymm4[1],ymm2[2],ymm4[2],ymm2[3],ymm4[3],ymm2[4],ymm4[4],ymm2[5],ymm4[5],ymm2[6],ymm4[6],ymm2[7],ymm4[7],ymm2[16],ymm4[16],ymm2[17],ymm4[17],ymm2[18],ymm4[18],ymm2[19],ymm4[19],ymm2[20],ymm4[20],ymm2[21],ymm4[21],ymm2[22],ymm4[22],ymm2[23],ymm4[23] -; AVX512DQ-BW-NEXT: vprold $16, %ymm16, %ymm16 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm16 = ymm16[2,2,2,3] -; AVX512DQ-BW-NEXT: vmovdqu16 %ymm16, %ymm14 {%k2} -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm14, %zmm0, %zmm14 -; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm11 = xmm12[8],xmm11[8],xmm12[9],xmm11[9],xmm12[10],xmm11[10],xmm12[11],xmm11[11],xmm12[12],xmm11[12],xmm12[13],xmm11[13],xmm12[14],xmm11[14],xmm12[15],xmm11[15] -; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm9 = xmm10[8],xmm9[8],xmm10[9],xmm9[9],xmm10[10],xmm9[10],xmm10[11],xmm9[11],xmm10[12],xmm9[12],xmm10[13],xmm9[13],xmm10[14],xmm9[14],xmm10[15],xmm9[15] -; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} ymm10 = [4,3,6,5,4,3,6,5,4,3,6,5,7,7,7,7] +; AVX512DQ-BW-NEXT: vpermw %zmm13, %zmm14, %zmm0 {%k2} +; AVX512DQ-BW-NEXT: vpbroadcastq {{.*#+}} ymm13 = [8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0] +; AVX512DQ-BW-NEXT: vpshufb %ymm13, %ymm10, %ymm14 +; AVX512DQ-BW-NEXT: vpshufb %ymm13, %ymm9, %ymm13 +; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} ymm13 = ymm13[0],ymm14[0],ymm13[1],ymm14[1],ymm13[2],ymm14[2],ymm13[3],ymm14[3],ymm13[4],ymm14[4],ymm13[5],ymm14[5],ymm13[6],ymm14[6],ymm13[7],ymm14[7],ymm13[16],ymm14[16],ymm13[17],ymm14[17],ymm13[18],ymm14[18],ymm13[19],ymm14[19],ymm13[20],ymm14[20],ymm13[21],ymm14[21],ymm13[22],ymm14[22],ymm13[23],ymm14[23] +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,2,2,3] +; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} ymm14 = ymm11[8],ymm12[8],ymm11[9],ymm12[9],ymm11[10],ymm12[10],ymm11[11],ymm12[11],ymm11[12],ymm12[12],ymm11[13],ymm12[13],ymm11[14],ymm12[14],ymm11[15],ymm12[15],ymm11[24],ymm12[24],ymm11[25],ymm12[25],ymm11[26],ymm12[26],ymm11[27],ymm12[27],ymm11[28],ymm12[28],ymm11[29],ymm12[29],ymm11[30],ymm12[30],ymm11[31],ymm12[31] +; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} ymm15 = [13,12,11,14,13,12,11,14,13,12,11,14,15,15,15,15] +; AVX512DQ-BW-NEXT: vpermw %ymm14, %ymm15, %ymm14 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm14, %zmm13, %zmm13 +; AVX512DQ-BW-NEXT: vpbroadcastq {{.*#+}} ymm14 = [5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10] +; AVX512DQ-BW-NEXT: vpshufb %ymm14, %ymm12, %ymm12 +; AVX512DQ-BW-NEXT: vpshufb %ymm14, %ymm11, %ymm11 +; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} ymm11 = ymm11[0],ymm12[0],ymm11[1],ymm12[1],ymm11[2],ymm12[2],ymm11[3],ymm12[3],ymm11[4],ymm12[4],ymm11[5],ymm12[5],ymm11[6],ymm12[6],ymm11[7],ymm12[7],ymm11[16],ymm12[16],ymm11[17],ymm12[17],ymm11[18],ymm12[18],ymm11[19],ymm12[19],ymm11[20],ymm12[20],ymm11[21],ymm12[21],ymm11[22],ymm12[22],ymm11[23],ymm12[23] +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,2,2,3] +; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} ymm9 = ymm9[8],ymm10[8],ymm9[9],ymm10[9],ymm9[10],ymm10[10],ymm9[11],ymm10[11],ymm9[12],ymm10[12],ymm9[13],ymm10[13],ymm9[14],ymm10[14],ymm9[15],ymm10[15],ymm9[24],ymm10[24],ymm9[25],ymm10[25],ymm9[26],ymm10[26],ymm9[27],ymm10[27],ymm9[28],ymm10[28],ymm9[29],ymm10[29],ymm9[30],ymm10[30],ymm9[31],ymm10[31] +; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} ymm10 = [12,11,14,13,12,11,14,13,12,11,14,13,15,15,15,15] ; AVX512DQ-BW-NEXT: vpermw %ymm9, %ymm10, %ymm9 -; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} ymm10 = [5,4,3,6,5,4,3,6,5,4,3,6,7,7,7,7] -; AVX512DQ-BW-NEXT: vpermw %ymm11, %ymm10, %ymm9 {%k1} -; AVX512DQ-BW-NEXT: vshufi64x2 {{.*#+}} zmm9 = zmm9[0,1,2,3],zmm14[4,5,6,7] -; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} ymm10 = ymm0[0],ymm1[0],ymm0[1],ymm1[1],ymm0[2],ymm1[2],ymm0[3],ymm1[3],ymm0[4],ymm1[4],ymm0[5],ymm1[5],ymm0[6],ymm1[6],ymm0[7],ymm1[7],ymm0[16],ymm1[16],ymm0[17],ymm1[17],ymm0[18],ymm1[18],ymm0[19],ymm1[19],ymm0[20],ymm1[20],ymm0[21],ymm1[21],ymm0[22],ymm1[22],ymm0[23],ymm1[23] -; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm11 = xmm15[8],xmm13[8],xmm15[9],xmm13[9],xmm15[10],xmm13[10],xmm15[11],xmm13[11],xmm15[12],xmm13[12],xmm15[13],xmm13[13],xmm15[14],xmm13[14],xmm15[15],xmm13[15] -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm10, %zmm11, %zmm10 -; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} zmm11 = [2,5,4,3,2,5,4,3,2,5,4,3,6,5,6,7,26,25,24,27,26,25,24,27,26,25,24,27,28,28,28,28] -; AVX512DQ-BW-NEXT: movl $1227133513, %ecx # imm = 0x49249249 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm9, %zmm11, %zmm9 +; AVX512DQ-BW-NEXT: movl $1227114788, %ecx # imm = 0x49244924 ; AVX512DQ-BW-NEXT: kmovd %ecx, %k2 -; AVX512DQ-BW-NEXT: vpermw %zmm10, %zmm11, %zmm9 {%k2} -; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} ymm10 = ymm2[8],ymm4[8],ymm2[9],ymm4[9],ymm2[10],ymm4[10],ymm2[11],ymm4[11],ymm2[12],ymm4[12],ymm2[13],ymm4[13],ymm2[14],ymm4[14],ymm2[15],ymm4[15],ymm2[24],ymm4[24],ymm2[25],ymm4[25],ymm2[26],ymm4[26],ymm2[27],ymm4[27],ymm2[28],ymm4[28],ymm2[29],ymm4[29],ymm2[30],ymm4[30],ymm2[31],ymm4[31] -; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} ymm11 = ymm3[8],ymm5[8],ymm3[9],ymm5[9],ymm3[10],ymm5[10],ymm3[11],ymm5[11],ymm3[12],ymm5[12],ymm3[13],ymm5[13],ymm3[14],ymm5[14],ymm3[15],ymm5[15],ymm3[24],ymm5[24],ymm3[25],ymm5[25],ymm3[26],ymm5[26],ymm3[27],ymm5[27],ymm3[28],ymm5[28],ymm3[29],ymm5[29],ymm3[30],ymm5[30],ymm3[31],ymm5[31] -; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} ymm12 = [12,11,14,13,12,11,14,13,12,11,14,13,15,15,15,15] -; AVX512DQ-BW-NEXT: vpermw %ymm11, %ymm12, %ymm11 -; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} ymm12 = [13,12,11,14,13,12,11,14,13,12,11,14,15,15,15,15] -; AVX512DQ-BW-NEXT: vpermw %ymm10, %ymm12, %ymm11 {%k1} -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm11, %zmm0, %zmm10 -; AVX512DQ-BW-NEXT: vpbroadcastq {{.*#+}} ymm11 = [8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0] -; AVX512DQ-BW-NEXT: vpshufb %ymm11, %ymm5, %ymm5 -; AVX512DQ-BW-NEXT: vpshufb %ymm11, %ymm3, %ymm3 -; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} ymm3 = ymm3[0],ymm5[0],ymm3[1],ymm5[1],ymm3[2],ymm5[2],ymm3[3],ymm5[3],ymm3[4],ymm5[4],ymm3[5],ymm5[5],ymm3[6],ymm5[6],ymm3[7],ymm5[7],ymm3[16],ymm5[16],ymm3[17],ymm5[17],ymm3[18],ymm5[18],ymm3[19],ymm5[19],ymm3[20],ymm5[20],ymm3[21],ymm5[21],ymm3[22],ymm5[22],ymm3[23],ymm5[23] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,2,3] -; AVX512DQ-BW-NEXT: vpshufb %ymm6, %ymm4, %ymm4 -; AVX512DQ-BW-NEXT: vpshufb %ymm6, %ymm2, %ymm2 -; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} ymm2 = ymm2[0],ymm4[0],ymm2[1],ymm4[1],ymm2[2],ymm4[2],ymm2[3],ymm4[3],ymm2[4],ymm4[4],ymm2[5],ymm4[5],ymm2[6],ymm4[6],ymm2[7],ymm4[7],ymm2[16],ymm4[16],ymm2[17],ymm4[17],ymm2[18],ymm4[18],ymm2[19],ymm4[19],ymm2[20],ymm4[20],ymm2[21],ymm4[21],ymm2[22],ymm4[22],ymm2[23],ymm4[23] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,2,3] -; AVX512DQ-BW-NEXT: vmovdqu16 %ymm3, %ymm2 {%k1} -; AVX512DQ-BW-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm2[0,1,2,3],zmm10[4,5,6,7] -; AVX512DQ-BW-NEXT: vpshufb %ymm8, %ymm1, %ymm3 -; AVX512DQ-BW-NEXT: vpshufb %ymm8, %ymm0, %ymm4 -; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} ymm3 = ymm4[0],ymm3[0],ymm4[1],ymm3[1],ymm4[2],ymm3[2],ymm4[3],ymm3[3],ymm4[4],ymm3[4],ymm4[5],ymm3[5],ymm4[6],ymm3[6],ymm4[7],ymm3[7],ymm4[16],ymm3[16],ymm4[17],ymm3[17],ymm4[18],ymm3[18],ymm4[19],ymm3[19],ymm4[20],ymm3[20],ymm4[21],ymm3[21],ymm4[22],ymm3[22],ymm4[23],ymm3[23] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,2,3] -; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} ymm0 = ymm0[8],ymm1[8],ymm0[9],ymm1[9],ymm0[10],ymm1[10],ymm0[11],ymm1[11],ymm0[12],ymm1[12],ymm0[13],ymm1[13],ymm0[14],ymm1[14],ymm0[15],ymm1[15],ymm0[24],ymm1[24],ymm0[25],ymm1[25],ymm0[26],ymm1[26],ymm0[27],ymm1[27],ymm0[28],ymm1[28],ymm0[29],ymm1[29],ymm0[30],ymm1[30],ymm0[31],ymm1[31] -; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} ymm1 = [10,13,12,11,10,13,12,11,10,13,12,11,14,13,14,15] -; AVX512DQ-BW-NEXT: vpermw %ymm0, %ymm1, %ymm0 -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm0, %zmm3, %zmm0 +; AVX512DQ-BW-NEXT: vmovdqu16 %zmm13, %zmm9 {%k2} +; AVX512DQ-BW-NEXT: vpbroadcastq {{.*#+}} ymm10 = [6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0] +; AVX512DQ-BW-NEXT: vpshufb %ymm10, %ymm8, %ymm11 +; AVX512DQ-BW-NEXT: vpshufb %ymm10, %ymm7, %ymm12 +; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} ymm11 = ymm12[0],ymm11[0],ymm12[1],ymm11[1],ymm12[2],ymm11[2],ymm12[3],ymm11[3],ymm12[4],ymm11[4],ymm12[5],ymm11[5],ymm12[6],ymm11[6],ymm12[7],ymm11[7],ymm12[16],ymm11[16],ymm12[17],ymm11[17],ymm12[18],ymm11[18],ymm12[19],ymm11[19],ymm12[20],ymm11[20],ymm12[21],ymm11[21],ymm12[22],ymm11[22],ymm12[23],ymm11[23] +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,2,2,3] +; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} ymm7 = ymm7[8],ymm8[8],ymm7[9],ymm8[9],ymm7[10],ymm8[10],ymm7[11],ymm8[11],ymm7[12],ymm8[12],ymm7[13],ymm8[13],ymm7[14],ymm8[14],ymm7[15],ymm8[15],ymm7[24],ymm8[24],ymm7[25],ymm8[25],ymm7[26],ymm8[26],ymm7[27],ymm8[27],ymm7[28],ymm8[28],ymm7[29],ymm8[29],ymm7[30],ymm8[30],ymm7[31],ymm8[31] +; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} ymm8 = [10,13,12,11,10,13,12,11,10,13,12,11,14,13,14,15] +; AVX512DQ-BW-NEXT: vpermw %ymm7, %ymm8, %ymm7 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm7, %zmm11, %zmm7 ; AVX512DQ-BW-NEXT: movl $-1840700270, %ecx # imm = 0x92492492 -; AVX512DQ-BW-NEXT: kmovd %ecx, %k1 -; AVX512DQ-BW-NEXT: vmovdqu16 %zmm0, %zmm2 {%k1} -; AVX512DQ-BW-NEXT: vmovdqa64 %zmm2, 128(%rax) -; AVX512DQ-BW-NEXT: vmovdqa64 %zmm9, 64(%rax) +; AVX512DQ-BW-NEXT: kmovd %ecx, %k2 +; AVX512DQ-BW-NEXT: vmovdqu16 %zmm7, %zmm9 {%k2} +; AVX512DQ-BW-NEXT: vpshufb %xmm14, %xmm3, %xmm7 +; AVX512DQ-BW-NEXT: vpshufb %xmm14, %xmm4, %xmm8 +; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm7 = xmm8[0],xmm7[0],xmm8[1],xmm7[1],xmm8[2],xmm7[2],xmm8[3],xmm7[3],xmm8[4],xmm7[4],xmm8[5],xmm7[5],xmm8[6],xmm7[6],xmm8[7],xmm7[7] +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm7 = ymm7[0,0,0,1] +; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm8 = xmm2[0],xmm1[0],xmm2[1],xmm1[1],xmm2[2],xmm1[2],xmm2[3],xmm1[3],xmm2[4],xmm1[4],xmm2[5],xmm1[5],xmm2[6],xmm1[6],xmm2[7],xmm1[7] +; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} ymm11 = [0,3,2,1,0,3,2,1,0,3,2,1,4,5,6,5] +; AVX512DQ-BW-NEXT: vpermw %ymm8, %ymm11, %ymm8 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm7, %zmm8, %zmm7 +; AVX512DQ-BW-NEXT: vpbroadcastq {{.*#+}} xmm8 = [8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0] +; AVX512DQ-BW-NEXT: vpshufb %xmm8, %xmm1, %xmm1 +; AVX512DQ-BW-NEXT: vpshufb %xmm8, %xmm2, %xmm2 +; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm2[8],xmm1[8],xmm2[9],xmm1[9],xmm2[10],xmm1[10],xmm2[11],xmm1[11],xmm2[12],xmm1[12],xmm2[13],xmm1[13],xmm2[14],xmm1[14],xmm2[15],xmm1[15] +; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm4[0],xmm3[0],xmm4[1],xmm3[1],xmm4[2],xmm3[2],xmm4[3],xmm3[3],xmm4[4],xmm3[4],xmm4[5],xmm3[5],xmm4[6],xmm3[6],xmm4[7],xmm3[7] +; AVX512DQ-BW-NEXT: vprold $16, %xmm2, %xmm2 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm1 +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm1 = zmm1[0,0,0,1,4,4,4,5] +; AVX512DQ-BW-NEXT: movl $1227105426, %ecx # imm = 0x49242492 +; AVX512DQ-BW-NEXT: kmovd %ecx, %k2 +; AVX512DQ-BW-NEXT: vmovdqu16 %zmm1, %zmm7 {%k2} +; AVX512DQ-BW-NEXT: vpshufb %xmm10, %xmm5, %xmm1 +; AVX512DQ-BW-NEXT: vpshufb %xmm10, %xmm6, %xmm2 +; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[1],xmm1[1],xmm2[2],xmm1[2],xmm2[3],xmm1[3],xmm2[4],xmm1[4],xmm2[5],xmm1[5],xmm2[6],xmm1[6],xmm2[7],xmm1[7] +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,0,0,1] +; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm6[0],xmm5[0],xmm6[1],xmm5[1],xmm6[2],xmm5[2],xmm6[3],xmm5[3],xmm6[4],xmm5[4],xmm6[5],xmm5[5],xmm6[6],xmm5[6],xmm6[7],xmm5[7] +; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} ymm3 = [2,1,0,3,2,1,0,3,2,1,0,3,4,4,4,4] +; AVX512DQ-BW-NEXT: vpermw %ymm2, %ymm3, %ymm2 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm1 +; AVX512DQ-BW-NEXT: vmovdqu16 %zmm1, %zmm7 {%k1} ; AVX512DQ-BW-NEXT: vmovdqa64 %zmm7, (%rax) +; AVX512DQ-BW-NEXT: vmovdqa64 %zmm9, 128(%rax) +; AVX512DQ-BW-NEXT: vmovdqa64 %zmm0, 64(%rax) ; AVX512DQ-BW-NEXT: vzeroupper ; AVX512DQ-BW-NEXT: retq ; ; AVX512DQ-BW-FCP-LABEL: store_i8_stride6_vf32: ; AVX512DQ-BW-FCP: # %bb.0: ; AVX512DQ-BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdi), %ymm3 -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rsi), %ymm5 -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdx), %ymm2 -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rcx), %ymm4 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdi), %ymm2 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rsi), %ymm3 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdx), %ymm5 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rcx), %ymm6 ; AVX512DQ-BW-FCP-NEXT: vmovdqa (%r8), %ymm0 ; AVX512DQ-BW-FCP-NEXT: vmovdqa (%r9), %ymm1 -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rcx), %xmm9 -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdx), %xmm10 -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm6 = xmm10[0],xmm9[0],xmm10[1],xmm9[1],xmm10[2],xmm9[2],xmm10[3],xmm9[3],xmm10[4],xmm9[4],xmm10[5],xmm9[5],xmm10[6],xmm9[6],xmm10[7],xmm9[7] -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rsi), %xmm11 +; AVX512DQ-BW-FCP-NEXT: vpbroadcastq {{.*#+}} ymm4 = [8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0] +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm4, %ymm3, %ymm7 +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm4, %ymm2, %ymm4 +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm4 = ymm4[0],ymm7[0],ymm4[1],ymm7[1],ymm4[2],ymm7[2],ymm4[3],ymm7[3],ymm4[4],ymm7[4],ymm4[5],ymm7[5],ymm4[6],ymm7[6],ymm4[7],ymm7[7],ymm4[16],ymm7[16],ymm4[17],ymm7[17],ymm4[18],ymm7[18],ymm4[19],ymm7[19],ymm4[20],ymm7[20],ymm4[21],ymm7[21],ymm4[22],ymm7[22],ymm4[23],ymm7[23] +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,2,2,3] +; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} ymm7 = ymm5[8],ymm6[8],ymm5[9],ymm6[9],ymm5[10],ymm6[10],ymm5[11],ymm6[11],ymm5[12],ymm6[12],ymm5[13],ymm6[13],ymm5[14],ymm6[14],ymm5[15],ymm6[15],ymm5[24],ymm6[24],ymm5[25],ymm6[25],ymm5[26],ymm6[26],ymm5[27],ymm6[27],ymm5[28],ymm6[28],ymm5[29],ymm6[29],ymm5[30],ymm6[30],ymm5[31],ymm6[31] +; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm8 = [13,12,11,14,13,12,11,14,13,12,11,14,15,15,15,15] +; AVX512DQ-BW-FCP-NEXT: vpermw %ymm7, %ymm8, %ymm7 +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm4, %zmm7 +; AVX512DQ-BW-FCP-NEXT: vpbroadcastq {{.*#+}} ymm8 = [5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10] +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm8, %ymm6, %ymm4 +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm8, %ymm5, %ymm9 +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm4 = ymm9[0],ymm4[0],ymm9[1],ymm4[1],ymm9[2],ymm4[2],ymm9[3],ymm4[3],ymm9[4],ymm4[4],ymm9[5],ymm4[5],ymm9[6],ymm4[6],ymm9[7],ymm4[7],ymm9[16],ymm4[16],ymm9[17],ymm4[17],ymm9[18],ymm4[18],ymm9[19],ymm4[19],ymm9[20],ymm4[20],ymm9[21],ymm4[21],ymm9[22],ymm4[22],ymm9[23],ymm4[23] +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,2,2,3] +; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} ymm9 = ymm2[8],ymm3[8],ymm2[9],ymm3[9],ymm2[10],ymm3[10],ymm2[11],ymm3[11],ymm2[12],ymm3[12],ymm2[13],ymm3[13],ymm2[14],ymm3[14],ymm2[15],ymm3[15],ymm2[24],ymm3[24],ymm2[25],ymm3[25],ymm2[26],ymm3[26],ymm2[27],ymm3[27],ymm2[28],ymm3[28],ymm2[29],ymm3[29],ymm2[30],ymm3[30],ymm2[31],ymm3[31] +; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm10 = [12,11,14,13,12,11,14,13,12,11,14,13,15,15,15,15] +; AVX512DQ-BW-FCP-NEXT: vpermw %ymm9, %ymm10, %ymm9 +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm9, %zmm4, %zmm4 +; AVX512DQ-BW-FCP-NEXT: movl $1227114788, %r10d # imm = 0x49244924 +; AVX512DQ-BW-FCP-NEXT: kmovd %r10d, %k1 +; AVX512DQ-BW-FCP-NEXT: vmovdqu16 %zmm7, %zmm4 {%k1} +; AVX512DQ-BW-FCP-NEXT: vpbroadcastq {{.*#+}} ymm7 = [6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0] +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm7, %ymm1, %ymm9 +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm7, %ymm0, %ymm10 +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm9 = ymm10[0],ymm9[0],ymm10[1],ymm9[1],ymm10[2],ymm9[2],ymm10[3],ymm9[3],ymm10[4],ymm9[4],ymm10[5],ymm9[5],ymm10[6],ymm9[6],ymm10[7],ymm9[7],ymm10[16],ymm9[16],ymm10[17],ymm9[17],ymm10[18],ymm9[18],ymm10[19],ymm9[19],ymm10[20],ymm9[20],ymm10[21],ymm9[21],ymm10[22],ymm9[22],ymm10[23],ymm9[23] +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,2,2,3] +; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} ymm10 = ymm0[8],ymm1[8],ymm0[9],ymm1[9],ymm0[10],ymm1[10],ymm0[11],ymm1[11],ymm0[12],ymm1[12],ymm0[13],ymm1[13],ymm0[14],ymm1[14],ymm0[15],ymm1[15],ymm0[24],ymm1[24],ymm0[25],ymm1[25],ymm0[26],ymm1[26],ymm0[27],ymm1[27],ymm0[28],ymm1[28],ymm0[29],ymm1[29],ymm0[30],ymm1[30],ymm0[31],ymm1[31] +; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm11 = [10,13,12,11,10,13,12,11,10,13,12,11,14,13,14,15] +; AVX512DQ-BW-FCP-NEXT: vpermw %ymm10, %ymm11, %ymm10 +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm9, %zmm9 +; AVX512DQ-BW-FCP-NEXT: movl $-1840700270, %r10d # imm = 0x92492492 +; AVX512DQ-BW-FCP-NEXT: kmovd %r10d, %k1 +; AVX512DQ-BW-FCP-NEXT: vmovdqu16 %zmm9, %zmm4 {%k1} +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rsi), %xmm9 +; AVX512DQ-BW-FCP-NEXT: vpbroadcastq {{.*#+}} xmm10 = [8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm10, %xmm9, %xmm11 ; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdi), %xmm12 -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm7 = xmm12[0],xmm11[0],xmm12[1],xmm11[1],xmm12[2],xmm11[2],xmm12[3],xmm11[3],xmm12[4],xmm11[4],xmm12[5],xmm11[5],xmm12[6],xmm11[6],xmm12[7],xmm11[7] -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm8 = [0,3,2,1,0,3,2,1,0,3,2,1,4,5,6,5] -; AVX512DQ-BW-FCP-NEXT: vpermw %ymm7, %ymm8, %ymm8 -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm7 = [1,0,3,2,1,0,3,2,1,0,3,2,5,4,7,6] -; AVX512DQ-BW-FCP-NEXT: movw $9362, %cx # imm = 0x2492 -; AVX512DQ-BW-FCP-NEXT: kmovd %ecx, %k2 -; AVX512DQ-BW-FCP-NEXT: vpermw %ymm6, %ymm7, %ymm8 {%k2} -; AVX512DQ-BW-FCP-NEXT: vpbroadcastq {{.*#+}} xmm6 = [8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm6, %xmm11, %xmm7 -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm6, %xmm12, %xmm6 -; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm6[8],xmm7[8],xmm6[9],xmm7[9],xmm6[10],xmm7[10],xmm6[11],xmm7[11],xmm6[12],xmm7[12],xmm6[13],xmm7[13],xmm6[14],xmm7[14],xmm6[15],xmm7[15] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[0,0,0,1] -; AVX512DQ-BW-FCP-NEXT: vpbroadcastq {{.*#+}} ymm7 = [5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10,5,8,7,6,9,0,0,10] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm7, %xmm9, %xmm13 -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm7, %xmm10, %xmm14 -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm13 = xmm14[0],xmm13[0],xmm14[1],xmm13[1],xmm14[2],xmm13[2],xmm14[3],xmm13[3],xmm14[4],xmm13[4],xmm14[5],xmm13[5],xmm14[6],xmm13[6],xmm14[7],xmm13[7] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[0,0,0,1] -; AVX512DQ-BW-FCP-NEXT: movw $18724, %cx # imm = 0x4924 +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm10, %xmm12, %xmm10 +; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm10 = xmm10[8],xmm11[8],xmm10[9],xmm11[9],xmm10[10],xmm11[10],xmm10[11],xmm11[11],xmm10[12],xmm11[12],xmm10[13],xmm11[13],xmm10[14],xmm11[14],xmm10[15],xmm11[15] +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[0,0,0,1] +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rcx), %xmm11 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdx), %xmm13 +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm14 = xmm13[0],xmm11[0],xmm13[1],xmm11[1],xmm13[2],xmm11[2],xmm13[3],xmm11[3],xmm13[4],xmm11[4],xmm13[5],xmm11[5],xmm13[6],xmm11[6],xmm13[7],xmm11[7] +; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm15 = [1,0,3,2,1,0,3,2,1,0,3,2,5,4,7,6] +; AVX512DQ-BW-FCP-NEXT: vpermw %ymm14, %ymm15, %ymm14 +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm14, %zmm10 +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm8, %xmm11, %xmm14 +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm8, %xmm13, %xmm8 +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm8 = xmm8[0],xmm14[0],xmm8[1],xmm14[1],xmm8[2],xmm14[2],xmm8[3],xmm14[3],xmm8[4],xmm14[4],xmm8[5],xmm14[5],xmm8[6],xmm14[6],xmm8[7],xmm14[7] +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[0,0,0,1] +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm14 = xmm12[0],xmm9[0],xmm12[1],xmm9[1],xmm12[2],xmm9[2],xmm12[3],xmm9[3],xmm12[4],xmm9[4],xmm12[5],xmm9[5],xmm12[6],xmm9[6],xmm12[7],xmm9[7] +; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm15 = [0,3,2,1,0,3,2,1,0,3,2,1,4,5,6,5] +; AVX512DQ-BW-FCP-NEXT: vpermw %ymm14, %ymm15, %ymm14 +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm8, %zmm14, %zmm8 +; AVX512DQ-BW-FCP-NEXT: movl $1227105426, %ecx # imm = 0x49242492 ; AVX512DQ-BW-FCP-NEXT: kmovd %ecx, %k1 -; AVX512DQ-BW-FCP-NEXT: vmovdqu16 %ymm6, %ymm13 {%k1} -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm13, %zmm0, %zmm6 -; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm6 = zmm8[0,1,2,3],zmm6[4,5,6,7] -; AVX512DQ-BW-FCP-NEXT: vpbroadcastq {{.*#+}} ymm8 = [6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0,6,5,8,7,0,9,0,0] -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%r9), %xmm13 -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm8, %xmm13, %xmm14 +; AVX512DQ-BW-FCP-NEXT: vmovdqu16 %zmm10, %zmm8 {%k1} +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%r9), %xmm10 +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm7, %xmm10, %xmm14 ; AVX512DQ-BW-FCP-NEXT: vmovdqa (%r8), %xmm15 -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm8, %xmm15, %xmm16 -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm14 = xmm16[0],xmm14[0],xmm16[1],xmm14[1],xmm16[2],xmm14[2],xmm16[3],xmm14[3],xmm16[4],xmm14[4],xmm16[5],xmm14[5],xmm16[6],xmm14[6],xmm16[7],xmm14[7] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm14 = ymm14[0,0,0,1] -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm16 = xmm15[0],xmm13[0],xmm15[1],xmm13[1],xmm15[2],xmm13[2],xmm15[3],xmm13[3],xmm15[4],xmm13[4],xmm15[5],xmm13[5],xmm15[6],xmm13[6],xmm15[7],xmm13[7] -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm17 = [2,1,0,3,2,1,0,3,2,1,0,3,4,4,4,4] -; AVX512DQ-BW-FCP-NEXT: vpermw %ymm16, %ymm17, %ymm16 -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm14, %zmm16, %zmm14 +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm7, %xmm15, %xmm7 +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm7 = xmm7[0],xmm14[0],xmm7[1],xmm14[1],xmm7[2],xmm14[2],xmm7[3],xmm14[3],xmm7[4],xmm14[4],xmm7[5],xmm14[5],xmm7[6],xmm14[6],xmm7[7],xmm14[7] +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[0,0,0,1] +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm14 = xmm15[0],xmm10[0],xmm15[1],xmm10[1],xmm15[2],xmm10[2],xmm15[3],xmm10[3],xmm15[4],xmm10[4],xmm15[5],xmm10[5],xmm15[6],xmm10[6],xmm15[7],xmm10[7] +; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm16 = [2,1,0,3,2,1,0,3,2,1,0,3,4,4,4,4] +; AVX512DQ-BW-FCP-NEXT: vpermw %ymm14, %ymm16, %ymm14 +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm14, %zmm7 ; AVX512DQ-BW-FCP-NEXT: movl $613566756, %ecx # imm = 0x24924924 -; AVX512DQ-BW-FCP-NEXT: kmovd %ecx, %k3 -; AVX512DQ-BW-FCP-NEXT: vmovdqu16 %zmm14, %zmm6 {%k3} -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm14 = ymm2[0],ymm4[0],ymm2[1],ymm4[1],ymm2[2],ymm4[2],ymm2[3],ymm4[3],ymm2[4],ymm4[4],ymm2[5],ymm4[5],ymm2[6],ymm4[6],ymm2[7],ymm4[7],ymm2[16],ymm4[16],ymm2[17],ymm4[17],ymm2[18],ymm4[18],ymm2[19],ymm4[19],ymm2[20],ymm4[20],ymm2[21],ymm4[21],ymm2[22],ymm4[22],ymm2[23],ymm4[23] -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm16 = ymm3[0],ymm5[0],ymm3[1],ymm5[1],ymm3[2],ymm5[2],ymm3[3],ymm5[3],ymm3[4],ymm5[4],ymm3[5],ymm5[5],ymm3[6],ymm5[6],ymm3[7],ymm5[7],ymm3[16],ymm5[16],ymm3[17],ymm5[17],ymm3[18],ymm5[18],ymm3[19],ymm5[19],ymm3[20],ymm5[20],ymm3[21],ymm5[21],ymm3[22],ymm5[22],ymm3[23],ymm5[23] -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm17 = [8,11,10,9,8,11,10,9,8,11,10,9,12,13,14,13] -; AVX512DQ-BW-FCP-NEXT: vpermw %ymm16, %ymm17, %ymm16 -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm17 = [9,8,11,10,9,8,11,10,9,8,11,10,13,12,15,14] -; AVX512DQ-BW-FCP-NEXT: vpermw %ymm14, %ymm17, %ymm16 {%k2} -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm16, %zmm0, %zmm14 -; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm9 = xmm10[8],xmm9[8],xmm10[9],xmm9[9],xmm10[10],xmm9[10],xmm10[11],xmm9[11],xmm10[12],xmm9[12],xmm10[13],xmm9[13],xmm10[14],xmm9[14],xmm10[15],xmm9[15] -; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm10 = xmm12[8],xmm11[8],xmm12[9],xmm11[9],xmm12[10],xmm11[10],xmm12[11],xmm11[11],xmm12[12],xmm11[12],xmm12[13],xmm11[13],xmm12[14],xmm11[14],xmm12[15],xmm11[15] -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm11 = [4,3,6,5,4,3,6,5,4,3,6,5,7,7,7,7] -; AVX512DQ-BW-FCP-NEXT: vpermw %ymm10, %ymm11, %ymm10 -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm11 = [5,4,3,6,5,4,3,6,5,4,3,6,7,7,7,7] -; AVX512DQ-BW-FCP-NEXT: vpermw %ymm9, %ymm11, %ymm10 {%k1} -; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm9 = zmm10[0,1,2,3],zmm14[4,5,6,7] -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm10 = ymm0[0],ymm1[0],ymm0[1],ymm1[1],ymm0[2],ymm1[2],ymm0[3],ymm1[3],ymm0[4],ymm1[4],ymm0[5],ymm1[5],ymm0[6],ymm1[6],ymm0[7],ymm1[7],ymm0[16],ymm1[16],ymm0[17],ymm1[17],ymm0[18],ymm1[18],ymm0[19],ymm1[19],ymm0[20],ymm1[20],ymm0[21],ymm1[21],ymm0[22],ymm1[22],ymm0[23],ymm1[23] -; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm11 = xmm15[8],xmm13[8],xmm15[9],xmm13[9],xmm15[10],xmm13[10],xmm15[11],xmm13[11],xmm15[12],xmm13[12],xmm15[13],xmm13[13],xmm15[14],xmm13[14],xmm15[15],xmm13[15] -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm11, %zmm10 -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm11 = [2,5,4,3,2,5,4,3,2,5,4,3,6,5,6,7,26,25,24,27,26,25,24,27,26,25,24,27,28,28,28,28] +; AVX512DQ-BW-FCP-NEXT: kmovd %ecx, %k1 +; AVX512DQ-BW-FCP-NEXT: vmovdqu16 %zmm7, %zmm8 {%k1} +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm5 = ymm5[0],ymm6[0],ymm5[1],ymm6[1],ymm5[2],ymm6[2],ymm5[3],ymm6[3],ymm5[4],ymm6[4],ymm5[5],ymm6[5],ymm5[6],ymm6[6],ymm5[7],ymm6[7],ymm5[16],ymm6[16],ymm5[17],ymm6[17],ymm5[18],ymm6[18],ymm5[19],ymm6[19],ymm5[20],ymm6[20],ymm5[21],ymm6[21],ymm5[22],ymm6[22],ymm5[23],ymm6[23] +; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm13[8],xmm11[8],xmm13[9],xmm11[9],xmm13[10],xmm11[10],xmm13[11],xmm11[11],xmm13[12],xmm11[12],xmm13[13],xmm11[13],xmm13[14],xmm11[14],xmm13[15],xmm11[15] +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm5, %zmm6, %zmm5 +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm2 = ymm2[0],ymm3[0],ymm2[1],ymm3[1],ymm2[2],ymm3[2],ymm2[3],ymm3[3],ymm2[4],ymm3[4],ymm2[5],ymm3[5],ymm2[6],ymm3[6],ymm2[7],ymm3[7],ymm2[16],ymm3[16],ymm2[17],ymm3[17],ymm2[18],ymm3[18],ymm2[19],ymm3[19],ymm2[20],ymm3[20],ymm2[21],ymm3[21],ymm2[22],ymm3[22],ymm2[23],ymm3[23] +; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm3 = xmm12[8],xmm9[8],xmm12[9],xmm9[9],xmm12[10],xmm9[10],xmm12[11],xmm9[11],xmm12[12],xmm9[12],xmm12[13],xmm9[13],xmm12[14],xmm9[14],xmm12[15],xmm9[15] +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm2 +; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm3 = [4,3,6,5,4,3,6,5,4,3,6,5,7,7,7,7,24,27,26,25,24,27,26,25,24,27,26,25,28,29,30,29] +; AVX512DQ-BW-FCP-NEXT: vpermw %zmm2, %zmm3, %zmm2 +; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm3 = [5,4,3,6,5,4,3,6,5,4,3,6,7,7,7,7,25,24,27,26,25,24,27,26,25,24,27,26,29,28,31,30] +; AVX512DQ-BW-FCP-NEXT: vpermw %zmm5, %zmm3, %zmm2 {%k1} +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm0 = ymm0[0],ymm1[0],ymm0[1],ymm1[1],ymm0[2],ymm1[2],ymm0[3],ymm1[3],ymm0[4],ymm1[4],ymm0[5],ymm1[5],ymm0[6],ymm1[6],ymm0[7],ymm1[7],ymm0[16],ymm1[16],ymm0[17],ymm1[17],ymm0[18],ymm1[18],ymm0[19],ymm1[19],ymm0[20],ymm1[20],ymm0[21],ymm1[21],ymm0[22],ymm1[22],ymm0[23],ymm1[23] +; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm15[8],xmm10[8],xmm15[9],xmm10[9],xmm15[10],xmm10[10],xmm15[11],xmm10[11],xmm15[12],xmm10[12],xmm15[13],xmm10[13],xmm15[14],xmm10[14],xmm15[15],xmm10[15] +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm1 = [2,5,4,3,2,5,4,3,2,5,4,3,6,5,6,7,26,25,24,27,26,25,24,27,26,25,24,27,28,28,28,28] ; AVX512DQ-BW-FCP-NEXT: movl $1227133513, %ecx # imm = 0x49249249 -; AVX512DQ-BW-FCP-NEXT: kmovd %ecx, %k2 -; AVX512DQ-BW-FCP-NEXT: vpermw %zmm10, %zmm11, %zmm9 {%k2} -; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} ymm10 = ymm2[8],ymm4[8],ymm2[9],ymm4[9],ymm2[10],ymm4[10],ymm2[11],ymm4[11],ymm2[12],ymm4[12],ymm2[13],ymm4[13],ymm2[14],ymm4[14],ymm2[15],ymm4[15],ymm2[24],ymm4[24],ymm2[25],ymm4[25],ymm2[26],ymm4[26],ymm2[27],ymm4[27],ymm2[28],ymm4[28],ymm2[29],ymm4[29],ymm2[30],ymm4[30],ymm2[31],ymm4[31] -; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} ymm11 = ymm3[8],ymm5[8],ymm3[9],ymm5[9],ymm3[10],ymm5[10],ymm3[11],ymm5[11],ymm3[12],ymm5[12],ymm3[13],ymm5[13],ymm3[14],ymm5[14],ymm3[15],ymm5[15],ymm3[24],ymm5[24],ymm3[25],ymm5[25],ymm3[26],ymm5[26],ymm3[27],ymm5[27],ymm3[28],ymm5[28],ymm3[29],ymm5[29],ymm3[30],ymm5[30],ymm3[31],ymm5[31] -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm12 = [12,11,14,13,12,11,14,13,12,11,14,13,15,15,15,15] -; AVX512DQ-BW-FCP-NEXT: vpermw %ymm11, %ymm12, %ymm11 -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm12 = [13,12,11,14,13,12,11,14,13,12,11,14,15,15,15,15] -; AVX512DQ-BW-FCP-NEXT: vpermw %ymm10, %ymm12, %ymm11 {%k1} -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm0, %zmm10 -; AVX512DQ-BW-FCP-NEXT: vpbroadcastq {{.*#+}} ymm11 = [8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0,8,7,6,9,0,0,10,0] -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm11, %ymm5, %ymm5 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm11, %ymm3, %ymm3 -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm3 = ymm3[0],ymm5[0],ymm3[1],ymm5[1],ymm3[2],ymm5[2],ymm3[3],ymm5[3],ymm3[4],ymm5[4],ymm3[5],ymm5[5],ymm3[6],ymm5[6],ymm3[7],ymm5[7],ymm3[16],ymm5[16],ymm3[17],ymm5[17],ymm3[18],ymm5[18],ymm3[19],ymm5[19],ymm3[20],ymm5[20],ymm3[21],ymm5[21],ymm3[22],ymm5[22],ymm3[23],ymm5[23] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,2,3] -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm7, %ymm4, %ymm4 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm7, %ymm2, %ymm2 -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm2 = ymm2[0],ymm4[0],ymm2[1],ymm4[1],ymm2[2],ymm4[2],ymm2[3],ymm4[3],ymm2[4],ymm4[4],ymm2[5],ymm4[5],ymm2[6],ymm4[6],ymm2[7],ymm4[7],ymm2[16],ymm4[16],ymm2[17],ymm4[17],ymm2[18],ymm4[18],ymm2[19],ymm4[19],ymm2[20],ymm4[20],ymm2[21],ymm4[21],ymm2[22],ymm4[22],ymm2[23],ymm4[23] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,2,2,3] -; AVX512DQ-BW-FCP-NEXT: vmovdqu16 %ymm3, %ymm2 {%k1} -; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm2[0,1,2,3],zmm10[4,5,6,7] -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm8, %ymm1, %ymm3 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm8, %ymm0, %ymm4 -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} ymm3 = ymm4[0],ymm3[0],ymm4[1],ymm3[1],ymm4[2],ymm3[2],ymm4[3],ymm3[3],ymm4[4],ymm3[4],ymm4[5],ymm3[5],ymm4[6],ymm3[6],ymm4[7],ymm3[7],ymm4[16],ymm3[16],ymm4[17],ymm3[17],ymm4[18],ymm3[18],ymm4[19],ymm3[19],ymm4[20],ymm3[20],ymm4[21],ymm3[21],ymm4[22],ymm3[22],ymm4[23],ymm3[23] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,2,2,3] -; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} ymm0 = ymm0[8],ymm1[8],ymm0[9],ymm1[9],ymm0[10],ymm1[10],ymm0[11],ymm1[11],ymm0[12],ymm1[12],ymm0[13],ymm1[13],ymm0[14],ymm1[14],ymm0[15],ymm1[15],ymm0[24],ymm1[24],ymm0[25],ymm1[25],ymm0[26],ymm1[26],ymm0[27],ymm1[27],ymm0[28],ymm1[28],ymm0[29],ymm1[29],ymm0[30],ymm1[30],ymm0[31],ymm1[31] -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm1 = [10,13,12,11,10,13,12,11,10,13,12,11,14,13,14,15] -; AVX512DQ-BW-FCP-NEXT: vpermw %ymm0, %ymm1, %ymm0 -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm3, %zmm0 -; AVX512DQ-BW-FCP-NEXT: movl $-1840700270, %ecx # imm = 0x92492492 ; AVX512DQ-BW-FCP-NEXT: kmovd %ecx, %k1 -; AVX512DQ-BW-FCP-NEXT: vmovdqu16 %zmm0, %zmm2 {%k1} -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm2, 128(%rax) -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm9, 64(%rax) -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm6, (%rax) +; AVX512DQ-BW-FCP-NEXT: vpermw %zmm0, %zmm1, %zmm2 {%k1} +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm2, 64(%rax) +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm8, (%rax) +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm4, 128(%rax) ; AVX512DQ-BW-FCP-NEXT: vzeroupper ; AVX512DQ-BW-FCP-NEXT: retq %in.vec0 = load <32 x i8>, ptr %in.vecptr0, align 64 diff --git a/llvm/test/CodeGen/X86/vector-interleaved-store-i8-stride-7.ll b/llvm/test/CodeGen/X86/vector-interleaved-store-i8-stride-7.ll index 0495e240ba968aaf6b780787dfd5cce1ca041b13..8b6ba51506ab793f22f5f2f5bd6ad0ba7686e9fd 100644 --- a/llvm/test/CodeGen/X86/vector-interleaved-store-i8-stride-7.ll +++ b/llvm/test/CodeGen/X86/vector-interleaved-store-i8-stride-7.ll @@ -3689,10 +3689,9 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-NEXT: vmovdqa {{.*#+}} ymm9 = [255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u] ; AVX2-NEXT: vpblendvb %ymm9, %ymm0, %ymm8, %ymm0 ; AVX2-NEXT: vpshufb {{.*#+}} ymm8 = ymm7[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm7[27],zero,ymm7[27,28,29,30],zero,ymm7[28],zero,ymm7[26,27,30,31],zero,ymm7[29] -; AVX2-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] ; AVX2-NEXT: vpshufb {{.*#+}} ymm9 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm2[27],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero -; AVX2-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,3,2,3] ; AVX2-NEXT: vpor %ymm8, %ymm9, %ymm8 +; AVX2-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] ; AVX2-NEXT: vmovdqa {{.*#+}} ymm9 = [255,0,0,u,255,255,255,255,0,0,u,255,255,255,255,0,0,u,255,255,255,255,0,0,u,255,255,255,255,0,0,u] ; AVX2-NEXT: vpblendvb %ymm9, %ymm0, %ymm8, %ymm0 ; AVX2-NEXT: vpshufb {{.*#+}} ymm8 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] @@ -3772,18 +3771,16 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-NEXT: vpblendvb %ymm7, %ymm1, %ymm0, %ymm0 ; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] ; AVX2-NEXT: vpshufb {{.*#+}} ymm1 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm5[18],zero,zero,zero,zero,ymm5[21],zero,ymm5[19],zero,zero,zero,zero,ymm5[22],zero,ymm5[20] -; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-NEXT: vpshufb {{.*#+}} ymm7 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,zero,zero,zero,ymm3[21],zero,ymm3[19],zero,zero,zero,zero,ymm3[22],zero,ymm3[20],zero -; AVX2-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] ; AVX2-NEXT: vpor %ymm1, %ymm7, %ymm1 +; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-NEXT: vmovdqa {{.*#+}} ymm7 = [255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u] ; AVX2-NEXT: vpblendvb %ymm7, %ymm1, %ymm0, %ymm0 ; AVX2-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[20],zero,ymm2[18],zero,zero,zero,zero,ymm2[21],zero,ymm2[19],zero,zero,zero,zero,ymm2[22] -; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm12 # 32-byte Reload ; AVX2-NEXT: vpshufb {{.*#+}} ymm7 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,20],zero,ymm12[18],zero,zero,zero,zero,ymm12[21],zero,ymm12[19],zero,zero,zero,zero,ymm12[22],zero -; AVX2-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] ; AVX2-NEXT: vpor %ymm1, %ymm7, %ymm1 +; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm11 # 32-byte Reload ; AVX2-NEXT: vpshuflw {{.*#+}} ymm7 = ymm11[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] ; AVX2-NEXT: vpshufd {{.*#+}} ymm7 = ymm7[0,1,1,3,4,5,5,7] @@ -3793,23 +3790,20 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-NEXT: vmovdqa {{.*#+}} ymm7 = [255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0] ; AVX2-NEXT: vpblendvb %ymm7, %ymm0, %ymm1, %ymm0 ; AVX2-NEXT: vpshufb {{.*#+}} ymm1 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm4[23],zero,ymm4[27,20,21,26],zero,ymm4[24],zero,ymm4[26,27,26,27],zero,ymm4[25] -; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-NEXT: vpshufb {{.*#+}} ymm7 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm6[23],zero,zero,zero,zero,ymm6[26],zero,ymm6[24],zero,zero,zero,zero,ymm6[27],zero -; AVX2-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] ; AVX2-NEXT: vpor %ymm1, %ymm7, %ymm1 +; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-NEXT: vpshufb {{.*#+}} ymm7 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm5[25],zero,ymm5[23],zero,zero,zero,zero,ymm5[26],zero,ymm5[24],zero,zero,zero,zero -; AVX2-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] ; AVX2-NEXT: vpshufb {{.*#+}} ymm8 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[25],zero,ymm3[23],zero,zero,zero,zero,ymm3[26],zero,ymm3[24],zero,zero,zero,zero,ymm3[27] -; AVX2-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] ; AVX2-NEXT: vpor %ymm7, %ymm8, %ymm7 +; AVX2-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] ; AVX2-NEXT: vmovdqa {{.*#+}} ymm8 = [u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0] ; AVX2-NEXT: vpblendvb %ymm8, %ymm1, %ymm7, %ymm1 ; AVX2-NEXT: vpshufb {{.*#+}} ymm7 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[25],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero -; AVX2-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] ; AVX2-NEXT: vpshufb {{.*#+}} ymm8 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm12[25],zero,ymm12[23],zero,zero,zero,zero,ymm12[26],zero,ymm12[24],zero,zero,zero ; AVX2-NEXT: vmovdqa %ymm12, %ymm13 -; AVX2-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] ; AVX2-NEXT: vpor %ymm7, %ymm8, %ymm7 +; AVX2-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] ; AVX2-NEXT: vpshufb {{.*#+}} ymm8 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] ; AVX2-NEXT: vmovdqa %ymm11, %ymm12 ; AVX2-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] @@ -3919,22 +3913,19 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm11 = [255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255] ; AVX2-FP-NEXT: vpblendvb %ymm11, %ymm9, %ymm10, %ymm9 ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm10 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[17,18,19,30],zero,ymm0[28],zero,ymm0[28,29,30,31],zero,ymm0[29],zero,ymm0[31] -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm11 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29],zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] ; AVX2-FP-NEXT: vpor %ymm10, %ymm11, %ymm10 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm11 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm3[30],zero,ymm3[28],zero,zero,zero,zero,ymm3[31],zero,ymm3[29],zero,zero,zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm12 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29],zero,zero,zero,zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FP-NEXT: vpor %ymm11, %ymm12, %ymm11 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm12 = [255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u] ; AVX2-FP-NEXT: vpblendvb %ymm12, %ymm10, %ymm11, %ymm10 ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm11 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[27],zero,ymm6[27,28,29,30],zero,ymm6[28],zero,ymm6[26,27,30,31],zero,ymm6[29] -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm12 = ymm8[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm8[27],zero,zero,zero,zero,ymm8[30],zero,ymm8[28],zero,zero,zero,zero,ymm8[31],zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FP-NEXT: vpor %ymm11, %ymm12, %ymm11 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm12 = [255,0,0,u,255,255,255,255,0,0,u,255,255,255,255,0,0,u,255,255,255,255,0,0,u,255,255,255,255,0,0,u] ; AVX2-FP-NEXT: vpblendvb %ymm12, %ymm10, %ymm11, %ymm10 ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm11 = ymm7[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] @@ -3942,22 +3933,19 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm12 = [255,255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0] ; AVX2-FP-NEXT: vpblendvb %ymm12, %ymm10, %ymm11, %ymm10 ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm11 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[23],zero,ymm1[27,20,21,26],zero,ymm1[24],zero,ymm1[26,27,26,27],zero,ymm1[25] -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm12 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm3[23],zero,zero,zero,zero,ymm3[26],zero,ymm3[24],zero,zero,zero,zero,ymm3[27],zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FP-NEXT: vpor %ymm11, %ymm12, %ymm11 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm12 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[25],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero,zero,zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm13 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[25],zero,ymm0[23],zero,zero,zero,zero,ymm0[26],zero,ymm0[24],zero,zero,zero,zero,ymm0[27] -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] ; AVX2-FP-NEXT: vpor %ymm12, %ymm13, %ymm12 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm13 = [u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0] ; AVX2-FP-NEXT: vpblendvb %ymm13, %ymm11, %ymm12, %ymm11 ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm12 = ymm8[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm8[25],zero,ymm8[23],zero,zero,zero,zero,ymm8[26],zero,ymm8[24],zero,zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm13 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm6[25],zero,ymm6[23],zero,zero,zero,zero,ymm6[26],zero,ymm6[24],zero,zero,zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] ; AVX2-FP-NEXT: vpor %ymm12, %ymm13, %ymm12 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm13 = ymm7[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] ; AVX2-FP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm14 = [0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u] @@ -3965,22 +3953,19 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm13 = [0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255] ; AVX2-FP-NEXT: vpblendvb %ymm13, %ymm11, %ymm12, %ymm11 ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm12 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[18],zero,zero,zero,zero,ymm2[21],zero,ymm2[19],zero,zero,zero,zero,ymm2[22],zero,ymm2[20] -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm13 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,zero,zero,zero,ymm0[21],zero,ymm0[19],zero,zero,zero,zero,ymm0[22],zero,ymm0[20],zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] ; AVX2-FP-NEXT: vpor %ymm12, %ymm13, %ymm12 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm13 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm3[21],zero,ymm3[19],zero,zero,zero,zero,ymm3[22],zero,ymm3[20],zero,zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm14 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm1[21],zero,ymm1[19],zero,zero,zero,zero,ymm1[22],zero,ymm1[20],zero,zero,zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm14 = ymm14[2,3,2,3] ; AVX2-FP-NEXT: vpor %ymm13, %ymm14, %ymm13 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm14 = [255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u] ; AVX2-FP-NEXT: vpblendvb %ymm14, %ymm12, %ymm13, %ymm12 ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm13 = ymm8[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm8[20],zero,ymm8[18],zero,zero,zero,zero,ymm8[21],zero,ymm8[19],zero,zero,zero,zero,ymm8[22] -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm14 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,20],zero,ymm6[18],zero,zero,zero,zero,ymm6[21],zero,ymm6[19],zero,zero,zero,zero,ymm6[22],zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm14 = ymm14[2,3,2,3] ; AVX2-FP-NEXT: vpor %ymm13, %ymm14, %ymm13 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm14 = ymm7[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,20,21,18,19,18,19,20,21,18,19,20,21,28,29,30,31] ; AVX2-FP-NEXT: vpermq {{.*#+}} ymm14 = ymm14[2,2,3,2] ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm15 = [u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255] @@ -4089,46 +4074,40 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm11 = [255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255] ; AVX2-FCP-NEXT: vpblendvb %ymm11, %ymm9, %ymm10, %ymm9 ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[18],zero,zero,zero,zero,ymm2[21],zero,ymm2[19],zero,zero,zero,zero,ymm2[22],zero,ymm2[20] -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,zero,zero,zero,ymm0[21],zero,ymm0[19],zero,zero,zero,zero,ymm0[22],zero,ymm0[20],zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] ; AVX2-FCP-NEXT: vpor %ymm10, %ymm11, %ymm10 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm3[21],zero,ymm3[19],zero,zero,zero,zero,ymm3[22],zero,ymm3[20],zero,zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm1[21],zero,ymm1[19],zero,zero,zero,zero,ymm1[22],zero,ymm1[20],zero,zero,zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FCP-NEXT: vpor %ymm11, %ymm12, %ymm11 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm12 = [255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u] ; AVX2-FCP-NEXT: vpblendvb %ymm12, %ymm10, %ymm11, %ymm10 ; AVX2-FCP-NEXT: vpshuflw {{.*#+}} ymm11 = ymm7[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] ; AVX2-FCP-NEXT: vpmovsxbd {{.*#+}} ymm12 = [4,5,4,5,5,7,4,5] ; AVX2-FCP-NEXT: vpermd %ymm11, %ymm12, %ymm11 ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm8[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm8[20],zero,ymm8[18],zero,zero,zero,zero,ymm8[21],zero,ymm8[19],zero,zero,zero,zero,ymm8[22] -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm13 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,20],zero,ymm6[18],zero,zero,zero,zero,ymm6[21],zero,ymm6[19],zero,zero,zero,zero,ymm6[22],zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] ; AVX2-FCP-NEXT: vpor %ymm12, %ymm13, %ymm12 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm13 = [u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255] ; AVX2-FCP-NEXT: vpblendvb %ymm13, %ymm12, %ymm11, %ymm11 ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm12 = [255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0] ; AVX2-FCP-NEXT: vpblendvb %ymm12, %ymm10, %ymm11, %ymm10 ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[17,18,19,30],zero,ymm0[28],zero,ymm0[28,29,30,31],zero,ymm0[29],zero,ymm0[31] -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29],zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FCP-NEXT: vpor %ymm11, %ymm12, %ymm11 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm3[30],zero,ymm3[28],zero,zero,zero,zero,ymm3[31],zero,ymm3[29],zero,zero,zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm13 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29],zero,zero,zero,zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] ; AVX2-FCP-NEXT: vpor %ymm12, %ymm13, %ymm12 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm13 = [255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u] ; AVX2-FCP-NEXT: vpblendvb %ymm13, %ymm11, %ymm12, %ymm11 ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[27],zero,ymm6[27,28,29,30],zero,ymm6[28],zero,ymm6[26,27,30,31],zero,ymm6[29] -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm13 = ymm8[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm8[27],zero,zero,zero,zero,ymm8[30],zero,ymm8[28],zero,zero,zero,zero,ymm8[31],zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] ; AVX2-FCP-NEXT: vpor %ymm12, %ymm13, %ymm12 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm13 = [255,0,0,u,255,255,255,255,0,0,u,255,255,255,255,0,0,u,255,255,255,255,0,0,u,255,255,255,255,0,0,u] ; AVX2-FCP-NEXT: vpblendvb %ymm13, %ymm11, %ymm12, %ymm11 ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm7[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] @@ -4136,22 +4115,19 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm13 = [255,255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0,255,255,255,255,255,255,0] ; AVX2-FCP-NEXT: vpblendvb %ymm13, %ymm11, %ymm12, %ymm11 ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[23],zero,ymm1[27,20,21,26],zero,ymm1[24],zero,ymm1[26,27,26,27],zero,ymm1[25] -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm13 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm3[23],zero,zero,zero,zero,ymm3[26],zero,ymm3[24],zero,zero,zero,zero,ymm3[27],zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] ; AVX2-FCP-NEXT: vpor %ymm12, %ymm13, %ymm12 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm13 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[25],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero,zero,zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm14 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[25],zero,ymm0[23],zero,zero,zero,zero,ymm0[26],zero,ymm0[24],zero,zero,zero,zero,ymm0[27] -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm14 = ymm14[2,3,2,3] ; AVX2-FCP-NEXT: vpor %ymm13, %ymm14, %ymm13 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm14 = [u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0] ; AVX2-FCP-NEXT: vpblendvb %ymm14, %ymm12, %ymm13, %ymm12 ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm13 = ymm8[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm8[25],zero,ymm8[23],zero,zero,zero,zero,ymm8[26],zero,ymm8[24],zero,zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm14 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm6[25],zero,ymm6[23],zero,zero,zero,zero,ymm6[26],zero,ymm6[24],zero,zero,zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm14 = ymm14[2,3,2,3] ; AVX2-FCP-NEXT: vpor %ymm13, %ymm14, %ymm13 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm14 = ymm7[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] ; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm14 = ymm14[2,3,2,3] ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm15 = [0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u] @@ -4189,153 +4165,138 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512: # %bb.0: ; AVX512-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512-NEXT: movq {{[0-9]+}}(%rsp), %r10 -; AVX512-NEXT: vmovdqa (%rdi), %ymm2 -; AVX512-NEXT: vmovdqa (%rsi), %ymm1 -; AVX512-NEXT: vmovdqa (%rdx), %ymm11 -; AVX512-NEXT: vmovdqa (%rcx), %ymm3 -; AVX512-NEXT: vmovdqa (%r8), %ymm5 -; AVX512-NEXT: vmovdqa (%r9), %ymm6 -; AVX512-NEXT: vmovdqa (%r10), %ymm4 -; AVX512-NEXT: vpshufb {{.*#+}} ymm7 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,u,u,u,u,26,27,24,25] -; AVX512-NEXT: vpshuflw {{.*#+}} ymm8 = ymm4[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] -; AVX512-NEXT: vpmovsxbd {{.*#+}} zmm9 = [0,5,4,0,5,0,4,0,20,21,0,23,0,21,0,23] -; AVX512-NEXT: vpermi2d %zmm7, %zmm8, %zmm9 -; AVX512-NEXT: vpshufb {{.*#+}} ymm7 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[20],zero,ymm6[18],zero,zero,zero,zero,ymm6[21],zero,ymm6[19],zero,zero,zero,zero,ymm6[22] -; AVX512-NEXT: vpshufb {{.*#+}} ymm8 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm6[25],zero,ymm6[23],zero,zero,zero,zero,ymm6[26],zero,ymm6[24],zero,zero +; AVX512-NEXT: vmovdqa (%rdi), %ymm3 +; AVX512-NEXT: vmovdqa (%rsi), %ymm4 +; AVX512-NEXT: vmovdqa (%rdx), %ymm5 +; AVX512-NEXT: vmovdqa (%rcx), %ymm6 +; AVX512-NEXT: vmovdqa (%r8), %ymm1 +; AVX512-NEXT: vmovdqa (%r9), %ymm2 +; AVX512-NEXT: vmovdqa (%r10), %ymm0 +; AVX512-NEXT: vpshufb {{.*#+}} ymm7 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[18],zero,zero,zero,zero,ymm6[21],zero,ymm6[19],zero,zero,zero,zero,ymm6[22],zero,ymm6[20] +; AVX512-NEXT: vpshufb {{.*#+}} ymm8 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[23],zero,zero,zero,zero,ymm3[26],zero,ymm3[24],zero,zero,zero,zero,ymm3[27],zero,ymm3[25] ; AVX512-NEXT: vinserti64x4 $1, %ymm8, %zmm7, %zmm7 ; AVX512-NEXT: vpermq {{.*#+}} zmm7 = zmm7[2,3,2,3,6,7,6,7] -; AVX512-NEXT: vpshufb {{.*#+}} ymm8 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,20],zero,ymm5[18],zero,ymm5[20,21,20,21],zero,ymm5[19],zero,ymm5[19,20,21,22],zero -; AVX512-NEXT: vpshufb {{.*#+}} ymm10 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,ymm5[23],zero,ymm5[23,24,25,26],zero,ymm5[24],zero,ymm5[30,31] -; AVX512-NEXT: vinserti64x4 $1, %ymm10, %zmm8, %zmm8 +; AVX512-NEXT: vpshufb {{.*#+}} ymm8 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,ymm5[18,19,20,21],zero,ymm5[19],zero,ymm5[25,26,27,22],zero,ymm5[20],zero +; AVX512-NEXT: vpshufb {{.*#+}} ymm9 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm4[23,u,u,u],zero,ymm4[26],zero,ymm4[24,u,u,u],zero,ymm4[27],zero +; AVX512-NEXT: vinserti64x4 $1, %ymm9, %zmm8, %zmm8 ; AVX512-NEXT: vpermq {{.*#+}} zmm8 = zmm8[2,3,2,3,6,7,6,7] ; AVX512-NEXT: vporq %zmm7, %zmm8, %zmm7 -; AVX512-NEXT: vpternlogd $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm9, %zmm7 -; AVX512-NEXT: vpshufb {{.*#+}} ymm8 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25,u,23,u,u,u,u,26,u,24,u,u,u,u,27,u] -; AVX512-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] -; AVX512-NEXT: vbroadcasti32x4 {{.*#+}} ymm16 = [18374967954648269055,71777218572844800,18374967954648269055,71777218572844800] -; AVX512-NEXT: # ymm16 = mem[0,1,2,3,0,1,2,3] -; AVX512-NEXT: vpandq %ymm16, %ymm8, %ymm8 -; AVX512-NEXT: vpshufb {{.*#+}} ymm9 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,ymm11[18,19,20,21],zero,ymm11[19],zero,ymm11[25,26,27,22],zero,ymm11[20],zero -; AVX512-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,3,2,3] -; AVX512-NEXT: vinserti64x4 $1, %ymm8, %zmm9, %zmm8 -; AVX512-NEXT: vpshufb {{.*#+}} ymm9 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[18],zero,zero,zero,zero,ymm3[21],zero,ymm3[19],zero,zero,zero,zero,ymm3[22],zero,ymm3[20] -; AVX512-NEXT: vpshufb {{.*#+}} ymm10 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero,zero,zero,ymm2[27],zero,ymm2[25] +; AVX512-NEXT: vpshufb {{.*#+}} ymm8 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm4[21],zero,ymm4[19],zero,zero,zero,zero,ymm4[22],zero,ymm4[20],zero,zero +; AVX512-NEXT: vpshufb {{.*#+}} ymm9 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm6[25],zero,ymm6[23],zero,zero,zero,zero,ymm6[26],zero,ymm6[24],zero,zero,zero,zero +; AVX512-NEXT: vinserti64x4 $1, %ymm9, %zmm8, %zmm8 +; AVX512-NEXT: vpermq {{.*#+}} zmm8 = zmm8[2,3,2,3,6,7,6,7] +; AVX512-NEXT: vpshufb {{.*#+}} ymm9 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19,20,21],zero,ymm3[19],zero,ymm3[21,20,21,22],zero,ymm3[20],zero,ymm3[22,23] +; AVX512-NEXT: vpshufb {{.*#+}} ymm10 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,ymm5[23],zero,ymm5[21,22,23,26],zero,ymm5[24],zero,ymm5[28,29,26,27] ; AVX512-NEXT: vinserti64x4 $1, %ymm10, %zmm9, %zmm9 ; AVX512-NEXT: vpermq {{.*#+}} zmm9 = zmm9[2,3,2,3,6,7,6,7] -; AVX512-NEXT: vporq %zmm9, %zmm8, %zmm9 -; AVX512-NEXT: vpshuflw {{.*#+}} ymm8 = ymm2[1,2,2,3,4,5,6,7,9,10,10,11,12,13,14,15] -; AVX512-NEXT: vpshufd {{.*#+}} ymm8 = ymm8[0,0,1,1,4,4,5,5] -; AVX512-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] -; AVX512-NEXT: vbroadcasti32x4 {{.*#+}} ymm17 = [18374966859431673855,18446463693966278655,18374966859431673855,18446463693966278655] -; AVX512-NEXT: # ymm17 = mem[0,1,2,3,0,1,2,3] -; AVX512-NEXT: vpandq %ymm17, %ymm8, %ymm8 -; AVX512-NEXT: vpshufb {{.*#+}} ymm10 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,ymm11[23],zero,ymm11[21,22,23,26],zero,ymm11[24],zero,ymm11[28,29,26,27] -; AVX512-NEXT: vmovdqa64 %ymm11, %ymm20 -; AVX512-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] -; AVX512-NEXT: vinserti64x4 $1, %ymm10, %zmm8, %zmm8 -; AVX512-NEXT: vpshufb {{.*#+}} ymm10 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm1[21],zero,ymm1[19],zero,zero,zero,zero,ymm1[22],zero,ymm1[20],zero,zero -; AVX512-NEXT: vpshufb {{.*#+}} ymm11 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm3[25],zero,ymm3[23],zero,zero,zero,zero,ymm3[26],zero,ymm3[24],zero,zero,zero,zero -; AVX512-NEXT: vinserti64x4 $1, %ymm11, %zmm10, %zmm10 -; AVX512-NEXT: vpermq {{.*#+}} zmm10 = zmm10[2,3,2,3,6,7,6,7] -; AVX512-NEXT: vporq %zmm10, %zmm8, %zmm8 -; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm9, %zmm8 -; AVX512-NEXT: vpternlogq $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm7, %zmm8 -; AVX512-NEXT: vmovdqa (%rsi), %xmm11 -; AVX512-NEXT: vpshufb {{.*#+}} xmm7 = xmm11[u],zero,xmm11[7],zero,xmm11[5,u,u,u],zero,xmm11[8],zero,xmm11[6,u,u,u],zero -; AVX512-NEXT: vmovdqa (%rdi), %xmm12 -; AVX512-NEXT: vpshufb {{.*#+}} xmm9 = xmm12[u,7],zero,xmm12[5],zero,xmm12[u,u,u,8],zero,xmm12[6],zero,xmm12[u,u,u,9] -; AVX512-NEXT: vpor %xmm7, %xmm9, %xmm7 -; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm9 = xmm12[0],xmm11[0],xmm12[1],xmm11[1],xmm12[2],xmm11[2],xmm12[3],xmm11[3],xmm12[4],xmm11[4],xmm12[5],xmm11[5],xmm12[6],xmm11[6],xmm12[7],xmm11[7] -; AVX512-NEXT: vpshufb {{.*#+}} xmm9 = xmm9[0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] -; AVX512-NEXT: vinserti32x4 $2, %xmm7, %zmm9, %zmm7 -; AVX512-NEXT: vpermq {{.*#+}} zmm10 = zmm7[0,1,0,1,4,5,4,5] -; AVX512-NEXT: vmovdqa (%rcx), %xmm7 -; AVX512-NEXT: vpshufb {{.*#+}} xmm13 = xmm7[u,u,u],zero,xmm7[7],zero,xmm7[5,u,u,u],zero,xmm7[8],zero,xmm7[6,u,u] -; AVX512-NEXT: vmovdqa (%rdx), %xmm9 -; AVX512-NEXT: vpshufb {{.*#+}} xmm14 = xmm9[u,u,u,7],zero,xmm9[5],zero,xmm9[u,u,u,8],zero,xmm9[6],zero,xmm9[u,u] -; AVX512-NEXT: vpor %xmm13, %xmm14, %xmm13 -; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm14 = xmm9[0],xmm7[0],xmm9[1],xmm7[1],xmm9[2],xmm7[2],xmm9[3],xmm7[3],xmm9[4],xmm7[4],xmm9[5],xmm7[5],xmm9[6],xmm7[6],xmm9[7],xmm7[7] -; AVX512-NEXT: vpshufb {{.*#+}} xmm14 = xmm14[4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] -; AVX512-NEXT: vinserti32x4 $2, %xmm13, %zmm14, %zmm13 -; AVX512-NEXT: vpermq {{.*#+}} zmm18 = zmm13[0,1,0,1,4,5,4,5] -; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm10, %zmm18 -; AVX512-NEXT: vmovdqa (%r9), %xmm13 -; AVX512-NEXT: vpshufb {{.*#+}} xmm10 = zero,xmm13[4,u,u,u],zero,xmm13[7],zero,xmm13[5,u,u,u],zero,xmm13[8],zero,xmm13[6] -; AVX512-NEXT: vmovdqa (%r8), %xmm14 -; AVX512-NEXT: vpshufb {{.*#+}} xmm15 = xmm14[4],zero,xmm14[u,u,u,7],zero,xmm14[5],zero,xmm14[u,u,u,8],zero,xmm14[6],zero -; AVX512-NEXT: vpor %xmm10, %xmm15, %xmm10 -; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm15 = xmm14[0],xmm13[0],xmm14[1],xmm13[1],xmm14[2],xmm13[2],xmm14[3],xmm13[3],xmm14[4],xmm13[4],xmm14[5],xmm13[5],xmm14[6],xmm13[6],xmm14[7],xmm13[7] -; AVX512-NEXT: vpshufb {{.*#+}} xmm15 = xmm15[u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] -; AVX512-NEXT: vinserti32x4 $2, %xmm10, %zmm15, %zmm10 -; AVX512-NEXT: vpermq {{.*#+}} zmm19 = zmm10[0,1,0,1,4,5,4,5] -; AVX512-NEXT: vmovdqa (%r10), %xmm15 -; AVX512-NEXT: vpshufb {{.*#+}} xmm10 = xmm15[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] -; AVX512-NEXT: vpshuflw {{.*#+}} xmm0 = xmm15[1,1,0,0,4,5,6,7] -; AVX512-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[0,1,2,0] -; AVX512-NEXT: vinserti64x4 $1, %ymm10, %zmm0, %zmm0 -; AVX512-NEXT: vpermq {{.*#+}} zmm10 = zmm0[0,0,1,0,4,4,5,4] -; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm19, %zmm10 -; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm18, %zmm10 -; AVX512-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,ymm1[14,u,u],zero,zero,zero,zero,ymm1[15,u,u],zero,zero,zero,zero,ymm1[16,u,u],zero,zero,zero,zero,ymm1[17,u,u],zero,zero,zero,zero,ymm1[18] +; AVX512-NEXT: vporq %zmm8, %zmm9, %zmm8 +; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm7, %zmm8 +; AVX512-NEXT: vpshufb {{.*#+}} ymm7 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,u,u,u,u,26,27,24,25] +; AVX512-NEXT: vpshuflw {{.*#+}} ymm9 = ymm0[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] +; AVX512-NEXT: vmovdqa64 %ymm0, %ymm18 +; AVX512-NEXT: vpmovsxbd {{.*#+}} zmm10 = [0,5,4,0,5,0,4,0,20,21,0,23,0,21,0,23] +; AVX512-NEXT: vpermi2d %zmm7, %zmm9, %zmm10 +; AVX512-NEXT: vpshufb {{.*#+}} ymm7 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[20],zero,ymm2[18],zero,zero,zero,zero,ymm2[21],zero,ymm2[19],zero,zero,zero,zero,ymm2[22] +; AVX512-NEXT: vpshufb {{.*#+}} ymm9 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[25],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero +; AVX512-NEXT: vinserti64x4 $1, %ymm9, %zmm7, %zmm7 +; AVX512-NEXT: vpermq {{.*#+}} zmm7 = zmm7[2,3,2,3,6,7,6,7] +; AVX512-NEXT: vpshufb {{.*#+}} ymm9 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,20],zero,ymm1[18],zero,ymm1[20,21,20,21],zero,ymm1[19],zero,ymm1[19,20,21,22],zero +; AVX512-NEXT: vpshufb {{.*#+}} ymm11 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,ymm1[23],zero,ymm1[23,24,25,26],zero,ymm1[24],zero,ymm1[30,31] ; AVX512-NEXT: vmovdqa64 %ymm1, %ymm19 -; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[0,1,14],zero,ymm2[u,u,0,1,14,15],zero,ymm2[u,u,13,2,3,16],zero,ymm2[u,u,28,29,16,17],zero,ymm2[u,u,19,28,29,18],zero -; AVX512-NEXT: vmovdqa64 %ymm2, %ymm18 +; AVX512-NEXT: vinserti64x4 $1, %ymm11, %zmm9, %zmm9 +; AVX512-NEXT: vpermq {{.*#+}} zmm9 = zmm9[2,3,2,3,6,7,6,7] +; AVX512-NEXT: vporq %zmm7, %zmm9, %zmm7 +; AVX512-NEXT: vpternlogd $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm10, %zmm7 +; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm8, %zmm7 +; AVX512-NEXT: vmovdqa (%rsi), %xmm9 +; AVX512-NEXT: vpshufb {{.*#+}} xmm8 = xmm9[u],zero,xmm9[7],zero,xmm9[5,u,u,u],zero,xmm9[8],zero,xmm9[6,u,u,u],zero +; AVX512-NEXT: vmovdqa (%rdi), %xmm10 +; AVX512-NEXT: vpshufb {{.*#+}} xmm11 = xmm10[u,7],zero,xmm10[5],zero,xmm10[u,u,u,8],zero,xmm10[6],zero,xmm10[u,u,u,9] +; AVX512-NEXT: vpor %xmm8, %xmm11, %xmm8 +; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm11 = xmm10[0],xmm9[0],xmm10[1],xmm9[1],xmm10[2],xmm9[2],xmm10[3],xmm9[3],xmm10[4],xmm9[4],xmm10[5],xmm9[5],xmm10[6],xmm9[6],xmm10[7],xmm9[7] +; AVX512-NEXT: vpshufb {{.*#+}} xmm11 = xmm11[0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] +; AVX512-NEXT: vinserti32x4 $2, %xmm8, %zmm11, %zmm8 +; AVX512-NEXT: vpermq {{.*#+}} zmm8 = zmm8[0,1,0,1,4,5,4,5] +; AVX512-NEXT: vmovdqa (%rcx), %xmm14 +; AVX512-NEXT: vpshufb {{.*#+}} xmm11 = xmm14[u,u,u],zero,xmm14[7],zero,xmm14[5,u,u,u],zero,xmm14[8],zero,xmm14[6,u,u] +; AVX512-NEXT: vmovdqa (%rdx), %xmm15 +; AVX512-NEXT: vpshufb {{.*#+}} xmm12 = xmm15[u,u,u,7],zero,xmm15[5],zero,xmm15[u,u,u,8],zero,xmm15[6],zero,xmm15[u,u] +; AVX512-NEXT: vpor %xmm11, %xmm12, %xmm11 +; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm12 = xmm15[0],xmm14[0],xmm15[1],xmm14[1],xmm15[2],xmm14[2],xmm15[3],xmm14[3],xmm15[4],xmm14[4],xmm15[5],xmm14[5],xmm15[6],xmm14[6],xmm15[7],xmm14[7] +; AVX512-NEXT: vpshufb {{.*#+}} xmm12 = xmm12[4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] +; AVX512-NEXT: vinserti32x4 $2, %xmm11, %zmm12, %zmm11 +; AVX512-NEXT: vpermq {{.*#+}} zmm16 = zmm11[0,1,0,1,4,5,4,5] +; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm8, %zmm16 +; AVX512-NEXT: vmovdqa (%r9), %xmm11 +; AVX512-NEXT: vpshufb {{.*#+}} xmm8 = zero,xmm11[4,u,u,u],zero,xmm11[7],zero,xmm11[5,u,u,u],zero,xmm11[8],zero,xmm11[6] +; AVX512-NEXT: vmovdqa (%r8), %xmm12 +; AVX512-NEXT: vpshufb {{.*#+}} xmm13 = xmm12[4],zero,xmm12[u,u,u,7],zero,xmm12[5],zero,xmm12[u,u,u,8],zero,xmm12[6],zero +; AVX512-NEXT: vpor %xmm8, %xmm13, %xmm8 +; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm13 = xmm12[0],xmm11[0],xmm12[1],xmm11[1],xmm12[2],xmm11[2],xmm12[3],xmm11[3],xmm12[4],xmm11[4],xmm12[5],xmm11[5],xmm12[6],xmm11[6],xmm12[7],xmm11[7] +; AVX512-NEXT: vpshufb {{.*#+}} xmm13 = xmm13[u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] +; AVX512-NEXT: vinserti32x4 $2, %xmm8, %zmm13, %zmm8 +; AVX512-NEXT: vpermq {{.*#+}} zmm17 = zmm8[0,1,0,1,4,5,4,5] +; AVX512-NEXT: vmovdqa (%r10), %xmm13 +; AVX512-NEXT: vpshufb {{.*#+}} xmm8 = xmm13[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] +; AVX512-NEXT: vpshuflw {{.*#+}} xmm0 = xmm13[1,1,0,0,4,5,6,7] +; AVX512-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[0,1,2,0] +; AVX512-NEXT: vinserti64x4 $1, %ymm8, %zmm0, %zmm0 +; AVX512-NEXT: vpermq {{.*#+}} zmm8 = zmm0[0,0,1,0,4,4,5,4] +; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm17, %zmm8 +; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm16, %zmm8 +; AVX512-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,ymm4[14,u,u],zero,zero,zero,zero,ymm4[15,u,u],zero,zero,zero,zero,ymm4[16,u,u],zero,zero,zero,zero,ymm4[17,u,u],zero,zero,zero,zero,ymm4[18] +; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm3[0,1,14],zero,ymm3[u,u,0,1,14,15],zero,ymm3[u,u,13,2,3,16],zero,ymm3[u,u,28,29,16,17],zero,ymm3[u,u,19,28,29,18],zero ; AVX512-NEXT: vpor %ymm0, %ymm1, %ymm0 -; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm7[8],xmm9[8],xmm7[9],xmm9[9],xmm7[10],xmm9[10],xmm7[11],xmm9[11],xmm7[12],xmm9[12],xmm7[13],xmm9[13],xmm7[14],xmm9[14],xmm7[15],xmm9[15] +; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm14[8],xmm15[8],xmm14[9],xmm15[9],xmm14[10],xmm15[10],xmm14[11],xmm15[11],xmm14[12],xmm15[12],xmm14[13],xmm15[13],xmm14[14],xmm15[14],xmm14[15],xmm15[15] ; AVX512-NEXT: vpshufb {{.*#+}} xmm1 = xmm1[6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] ; AVX512-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,1,0,1] ; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 -; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm3[u,u,u,u],zero,ymm3[14,u,u,u,u,u],zero,ymm3[15,u,u,u,u,u],zero,ymm3[16,u,u,u,u,u],zero,ymm3[17,u,u,u,u,u] -; AVX512-NEXT: vmovdqa64 %ymm20, %ymm2 -; AVX512-NEXT: vpshufb {{.*#+}} ymm7 = ymm2[u,u,u,u,14],zero,ymm2[u,u,u,u,u,15],zero,ymm2[u,u,u,u,u,16],zero,ymm2[u,u,u,u,u,17],zero,ymm2[u,u,u,u,u] -; AVX512-NEXT: vpor %ymm1, %ymm7, %ymm1 -; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm11[8],xmm12[8],xmm11[9],xmm12[9],xmm11[10],xmm12[10],xmm11[11],xmm12[11],xmm11[12],xmm12[12],xmm11[13],xmm12[13],xmm11[14],xmm12[14],xmm11[15],xmm12[15] -; AVX512-NEXT: vpshufb {{.*#+}} xmm7 = xmm7[2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] -; AVX512-NEXT: vpermq {{.*#+}} ymm7 = ymm7[0,1,0,1] -; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm7, %zmm1 +; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm6[u,u,u,u],zero,ymm6[14,u,u,u,u,u],zero,ymm6[15,u,u,u,u,u],zero,ymm6[16,u,u,u,u,u],zero,ymm6[17,u,u,u,u,u] +; AVX512-NEXT: vpshufb {{.*#+}} ymm14 = ymm5[u,u,u,u,14],zero,ymm5[u,u,u,u,u,15],zero,ymm5[u,u,u,u,u,16],zero,ymm5[u,u,u,u,u,17],zero,ymm5[u,u,u,u,u] +; AVX512-NEXT: vpor %ymm1, %ymm14, %ymm1 +; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm9 = xmm9[8],xmm10[8],xmm9[9],xmm10[9],xmm9[10],xmm10[10],xmm9[11],xmm10[11],xmm9[12],xmm10[12],xmm9[13],xmm10[13],xmm9[14],xmm10[14],xmm9[15],xmm10[15] +; AVX512-NEXT: vpshufb {{.*#+}} xmm9 = xmm9[2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] +; AVX512-NEXT: vpermq {{.*#+}} ymm9 = ymm9[0,1,0,1] +; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm9, %zmm1 ; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm1 -; AVX512-NEXT: vpshufb {{.*#+}} ymm0 = zero,ymm5[u,u,u,u,u,14],zero,ymm5[u,u,u,u,u,15],zero,ymm5[u,u,u,u,u,16],zero,ymm5[u,u,u,u,u,17],zero,ymm5[u,u,u] -; AVX512-NEXT: vpshufb {{.*#+}} ymm7 = ymm6[13,u,u,u,u,u],zero,ymm6[14,u,u,u,u,u],zero,ymm6[15,u,u,u,u,u],zero,ymm6[16,u,u,u,u,u],zero,ymm6[17,u,u,u] -; AVX512-NEXT: vpor %ymm0, %ymm7, %ymm0 -; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm14[8],xmm13[8],xmm14[9],xmm13[9],xmm14[10],xmm13[10],xmm14[11],xmm13[11],xmm14[12],xmm13[12],xmm14[13],xmm13[13],xmm14[14],xmm13[14],xmm14[15],xmm13[15] -; AVX512-NEXT: vpshufb {{.*#+}} xmm7 = xmm7[u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] -; AVX512-NEXT: vpermq {{.*#+}} ymm7 = ymm7[0,1,0,1] -; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm7, %zmm0 -; AVX512-NEXT: vpshufhw {{.*#+}} xmm7 = xmm15[0,1,2,3,4,5,5,6] -; AVX512-NEXT: vpshufd {{.*#+}} xmm7 = xmm7[2,2,3,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm7 = ymm7[0,1,0,1] -; AVX512-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm7, %ymm7 -; AVX512-NEXT: vpshufb {{.*#+}} ymm9 = zero,ymm4[13,u,u,u,u],zero,zero,ymm4[14,u,u,u,u],zero,zero,ymm4[15,u,u,u,u],zero,zero,ymm4[16,u,u,u,u],zero,zero,ymm4[17,u,u] -; AVX512-NEXT: vinserti64x4 $1, %ymm9, %zmm7, %zmm7 -; AVX512-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm7 -; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm7 -; AVX512-NEXT: vpshufb {{.*#+}} ymm0 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29,u,27,u,u,u,u,30,u,28,u,u,u,u,31,u] +; AVX512-NEXT: vmovdqa64 %ymm19, %ymm14 +; AVX512-NEXT: vpshufb {{.*#+}} ymm0 = zero,ymm14[u,u,u,u,u,14],zero,ymm14[u,u,u,u,u,15],zero,ymm14[u,u,u,u,u,16],zero,ymm14[u,u,u,u,u,17],zero,ymm14[u,u,u] +; AVX512-NEXT: vpshufb {{.*#+}} ymm9 = ymm2[13,u,u,u,u,u],zero,ymm2[14,u,u,u,u,u],zero,ymm2[15,u,u,u,u,u],zero,ymm2[16,u,u,u,u,u],zero,ymm2[17,u,u,u] +; AVX512-NEXT: vpor %ymm0, %ymm9, %ymm0 +; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm9 = xmm12[8],xmm11[8],xmm12[9],xmm11[9],xmm12[10],xmm11[10],xmm12[11],xmm11[11],xmm12[12],xmm11[12],xmm12[13],xmm11[13],xmm12[14],xmm11[14],xmm12[15],xmm11[15] +; AVX512-NEXT: vpshufb {{.*#+}} xmm9 = xmm9[u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] +; AVX512-NEXT: vpermq {{.*#+}} ymm9 = ymm9[0,1,0,1] +; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm9, %zmm0 +; AVX512-NEXT: vpshufhw {{.*#+}} xmm9 = xmm13[0,1,2,3,4,5,5,6] +; AVX512-NEXT: vpshufd {{.*#+}} xmm9 = xmm9[2,2,3,3] +; AVX512-NEXT: vpermq {{.*#+}} ymm9 = ymm9[0,1,0,1] +; AVX512-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm9, %ymm9 +; AVX512-NEXT: vmovdqa64 %ymm18, %ymm11 +; AVX512-NEXT: vpshufb {{.*#+}} ymm10 = zero,ymm11[13,u,u,u,u],zero,zero,ymm11[14,u,u,u,u],zero,zero,ymm11[15,u,u,u,u],zero,zero,ymm11[16,u,u,u,u],zero,zero,ymm11[17,u,u] +; AVX512-NEXT: vinserti64x4 $1, %ymm10, %zmm9, %zmm9 +; AVX512-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm9 +; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm9 +; AVX512-NEXT: vpshufb {{.*#+}} ymm0 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero,ymm5[29],zero,zero +; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u,u,u],zero,ymm6[30],zero,ymm6[28,u,u,u],zero,ymm6[31],zero,ymm6[29,u] +; AVX512-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm5[27],zero,zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero,ymm5[29] +; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm4[30],zero,ymm4[28],zero,zero,zero,zero,ymm4[31],zero,ymm4[29],zero,zero,zero +; AVX512-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,30],zero,ymm3[28],zero,ymm3[30,31,30,31],zero,ymm3[29],zero,ymm3[31,28,29] +; AVX512-NEXT: vpor %ymm1, %ymm3, %ymm1 ; AVX512-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512-NEXT: vpternlogq $248, %ymm16, %ymm0, %ymm1 -; AVX512-NEXT: vpshufb {{.*#+}} ymm0 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] +; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1 +; AVX512-NEXT: vpshufb {{.*#+}} ymm0 = ymm14[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm14[27],zero,zero,zero,zero,ymm14[30],zero,ymm14[28],zero,zero,zero,zero,ymm14[31],zero,ymm14[29] +; AVX512-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm2[27,u,u,u],zero,ymm2[30],zero,ymm2[28,u,u,u],zero,ymm2[31],zero +; AVX512-NEXT: vpor %ymm0, %ymm2, %ymm0 ; AVX512-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm0 -; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u,u,u,u,30,u,28,u,u,u,u,31,u,29,u] -; AVX512-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29],zero,zero +; AVX512-NEXT: vpshufb {{.*#+}} ymm2 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] ; AVX512-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] -; AVX512-NEXT: vpternlogq $248, %ymm17, %ymm1, %ymm2 -; AVX512-NEXT: vmovdqa64 %ymm19, %ymm1 -; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29],zero,zero,zero -; AVX512-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512-NEXT: vmovdqa64 %ymm18, %ymm3 -; AVX512-NEXT: vpshufhw {{.*#+}} ymm3 = ymm3[0,1,2,3,6,7,7,6,8,9,10,11,14,15,15,14] -; AVX512-NEXT: vpshufd {{.*#+}} ymm3 = ymm3[2,2,3,3,6,6,7,7] -; AVX512-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,3,2,3] -; AVX512-NEXT: vpternlogq $236, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm3 -; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm3 -; AVX512-NEXT: vpternlogq $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm3 -; AVX512-NEXT: vmovdqa %ymm3, 192(%rax) -; AVX512-NEXT: vmovdqa64 %zmm10, (%rax) -; AVX512-NEXT: vmovdqa64 %zmm8, 128(%rax) -; AVX512-NEXT: vmovdqa64 %zmm7, 64(%rax) +; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm2 +; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm2 +; AVX512-NEXT: vmovdqa %ymm2, 192(%rax) +; AVX512-NEXT: vmovdqa64 %zmm8, (%rax) +; AVX512-NEXT: vmovdqa64 %zmm7, 128(%rax) +; AVX512-NEXT: vmovdqa64 %zmm9, 64(%rax) ; AVX512-NEXT: vzeroupper ; AVX512-NEXT: retq ; @@ -4343,12 +4304,12 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512-FCP: # %bb.0: ; AVX512-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r10 -; AVX512-FCP-NEXT: vmovdqa (%rdi), %ymm2 +; AVX512-FCP-NEXT: vmovdqa (%rdi), %ymm3 ; AVX512-FCP-NEXT: vmovdqa (%rsi), %ymm4 ; AVX512-FCP-NEXT: vmovdqa (%rdx), %ymm5 ; AVX512-FCP-NEXT: vmovdqa (%rcx), %ymm6 ; AVX512-FCP-NEXT: vmovdqa (%r8), %ymm1 -; AVX512-FCP-NEXT: vmovdqa (%r9), %ymm3 +; AVX512-FCP-NEXT: vmovdqa (%r9), %ymm2 ; AVX512-FCP-NEXT: vmovdqa64 (%r10), %ymm17 ; AVX512-FCP-NEXT: vmovdqa (%rsi), %xmm8 ; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm7 = xmm8[u],zero,xmm8[7],zero,xmm8[5,u,u,u],zero,xmm8[8],zero,xmm8[6,u,u,u],zero @@ -4388,7 +4349,7 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512-FCP-NEXT: vpternlogd $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm16, %zmm7 ; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm15, %zmm7 ; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,ymm4[14,u,u],zero,zero,zero,zero,ymm4[15,u,u],zero,zero,zero,zero,ymm4[16,u,u],zero,zero,zero,zero,ymm4[17,u,u],zero,zero,zero,zero,ymm4[18] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm15 = ymm2[0,1,14],zero,ymm2[u,u,0,1,14,15],zero,ymm2[u,u,13,2,3,16],zero,ymm2[u,u,28,29,16,17],zero,ymm2[u,u,19,28,29,18],zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm15 = ymm3[0,1,14],zero,ymm3[u,u,0,1,14,15],zero,ymm3[u,u,13,2,3,16],zero,ymm3[u,u,28,29,16,17],zero,ymm3[u,u,19,28,29,18],zero ; AVX512-FCP-NEXT: vpor %ymm0, %ymm15, %ymm0 ; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm11 = xmm11[8],xmm12[8],xmm11[9],xmm12[9],xmm11[10],xmm12[10],xmm11[11],xmm12[11],xmm11[12],xmm12[12],xmm11[13],xmm12[13],xmm11[14],xmm12[14],xmm11[15],xmm12[15] ; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm11 = xmm11[6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] @@ -4403,7 +4364,7 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm8, %zmm9 ; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm9 ; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,ymm1[u,u,u,u,u,14],zero,ymm1[u,u,u,u,u,15],zero,ymm1[u,u,u,u,u,16],zero,ymm1[u,u,u,u,u,17],zero,ymm1[u,u,u] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm3[13,u,u,u,u,u],zero,ymm3[14,u,u,u,u,u],zero,ymm3[15,u,u,u,u,u],zero,ymm3[16,u,u,u,u,u],zero,ymm3[17,u,u,u] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm2[13,u,u,u,u,u],zero,ymm2[14,u,u,u,u,u],zero,ymm2[15,u,u,u,u,u],zero,ymm2[16,u,u,u,u,u],zero,ymm2[17,u,u,u] ; AVX512-FCP-NEXT: vpor %ymm0, %ymm8, %ymm0 ; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm8 = xmm14[8],xmm13[8],xmm14[9],xmm13[9],xmm14[10],xmm13[10],xmm14[11],xmm13[11],xmm14[12],xmm13[12],xmm14[13],xmm13[13],xmm14[14],xmm13[14],xmm14[15],xmm13[15] ; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm8 = xmm8[u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] @@ -4414,74 +4375,67 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512-FCP-NEXT: # ymm10 = mem[0,1,0,1] ; AVX512-FCP-NEXT: vpermd %ymm8, %ymm10, %ymm8 ; AVX512-FCP-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm8, %ymm8 -; AVX512-FCP-NEXT: vmovdqa64 %ymm17, %ymm13 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm10 = zero,ymm13[13,u,u,u,u],zero,zero,ymm13[14,u,u,u,u],zero,zero,ymm13[15,u,u,u,u],zero,zero,ymm13[16,u,u,u,u],zero,zero,ymm13[17,u,u] +; AVX512-FCP-NEXT: vmovdqa64 %ymm17, %ymm12 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm10 = zero,ymm12[13,u,u,u,u],zero,zero,ymm12[14,u,u,u,u],zero,zero,ymm12[15,u,u,u,u],zero,zero,ymm12[16,u,u,u,u],zero,zero,ymm12[17,u,u] ; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm8, %zmm8 ; AVX512-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm8 ; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm9, %zmm8 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25,u,23,u,u,u,u,26,u,24,u,u,u,u,27,u] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm9 = [18374967954648269055,71777218572844800,18374967954648269055,71777218572844800] -; AVX512-FCP-NEXT: # ymm9 = mem[0,1,0,1] -; AVX512-FCP-NEXT: vpand %ymm0, %ymm9, %ymm0 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,ymm5[18,19,20,21],zero,ymm5[19],zero,ymm5[25,26,27,22],zero,ymm5[20],zero -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm10, %zmm0 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[18],zero,zero,zero,zero,ymm6[21],zero,ymm6[19],zero,zero,zero,zero,ymm6[22],zero,ymm6[20] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero,zero,zero,ymm2[27],zero,ymm2[25] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[18],zero,zero,zero,zero,ymm6[21],zero,ymm6[19],zero,zero,zero,zero,ymm6[22],zero,ymm6[20] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[23],zero,zero,zero,zero,ymm3[26],zero,ymm3[24],zero,zero,zero,zero,ymm3[27],zero,ymm3[25] +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm9, %zmm0, %zmm0 +; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm0 = zmm0[2,3,2,3,6,7,6,7] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,ymm5[18,19,20,21],zero,ymm5[19],zero,ymm5[25,26,27,22],zero,ymm5[20],zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm4[23,u,u,u],zero,ymm4[26],zero,ymm4[24,u,u,u],zero,ymm4[27],zero +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm9, %zmm9 +; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm9 = zmm9[2,3,2,3,6,7,6,7] +; AVX512-FCP-NEXT: vporq %zmm0, %zmm9, %zmm0 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm4[21],zero,ymm4[19],zero,zero,zero,zero,ymm4[22],zero,ymm4[20],zero,zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm6[25],zero,ymm6[23],zero,zero,zero,zero,ymm6[26],zero,ymm6[24],zero,zero,zero,zero +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm9, %zmm9 +; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm9 = zmm9[2,3,2,3,6,7,6,7] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19,20,21],zero,ymm3[19],zero,ymm3[21,20,21,22],zero,ymm3[20],zero,ymm3[22,23] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,ymm5[23],zero,ymm5[21,22,23,26],zero,ymm5[24],zero,ymm5[28,29,26,27] ; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm10, %zmm10 ; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm10 = zmm10[2,3,2,3,6,7,6,7] -; AVX512-FCP-NEXT: vporq %zmm10, %zmm0, %zmm0 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm4[21],zero,ymm4[19],zero,zero,zero,zero,ymm4[22],zero,ymm4[20],zero,zero -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm6[25],zero,ymm6[23],zero,zero,zero,zero,ymm6[26],zero,ymm6[24],zero,zero,zero,zero +; AVX512-FCP-NEXT: vporq %zmm9, %zmm10, %zmm9 +; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm9 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[20],zero,ymm2[18],zero,zero,zero,zero,ymm2[21],zero,ymm2[19],zero,zero,zero,zero,ymm2[22] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[25],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm0, %zmm0 +; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm0 = zmm0[2,3,2,3,6,7,6,7] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,20],zero,ymm1[18],zero,ymm1[20,21,20,21],zero,ymm1[19],zero,ymm1[19,20,21,22],zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,ymm1[23],zero,ymm1[23,24,25,26],zero,ymm1[24],zero,ymm1[30,31] ; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm10, %zmm10 ; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm10 = zmm10[2,3,2,3,6,7,6,7] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19,20,21],zero,ymm2[19],zero,ymm2[21,20,21,22],zero,ymm2[20],zero,ymm2[22,23] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,ymm5[23],zero,ymm5[21,22,23,26],zero,ymm5[24],zero,ymm5[28,29,26,27] -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm12, %zmm11, %zmm11 -; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm11 = zmm11[2,3,2,3,6,7,6,7] -; AVX512-FCP-NEXT: vporq %zmm10, %zmm11, %zmm10 +; AVX512-FCP-NEXT: vporq %zmm0, %zmm10, %zmm0 +; AVX512-FCP-NEXT: vpshuflw {{.*#+}} ymm10 = ymm12[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] +; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} ymm11 = [0,5,4,0,5,0,4,0] +; AVX512-FCP-NEXT: vpermd %ymm10, %ymm11, %ymm10 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm10, %zmm10 ; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm10 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[20],zero,ymm3[18],zero,zero,zero,zero,ymm3[21],zero,ymm3[19],zero,zero,zero,zero,ymm3[22] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm3[25],zero,ymm3[23],zero,zero,zero,zero,ymm3[26],zero,ymm3[24],zero,zero -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm0, %zmm0 -; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm0 = zmm0[2,3,2,3,6,7,6,7] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,20],zero,ymm1[18],zero,ymm1[20,21,20,21],zero,ymm1[19],zero,ymm1[19,20,21,22],zero -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,ymm1[23],zero,ymm1[23,24,25,26],zero,ymm1[24],zero,ymm1[30,31] -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm12, %zmm11, %zmm11 -; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm11 = zmm11[2,3,2,3,6,7,6,7] -; AVX512-FCP-NEXT: vporq %zmm0, %zmm11, %zmm0 -; AVX512-FCP-NEXT: vpshuflw {{.*#+}} ymm11 = ymm13[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] -; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} ymm12 = [0,5,4,0,5,0,4,0] -; AVX512-FCP-NEXT: vpermd %ymm11, %ymm12, %ymm11 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm13[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm12, %zmm11, %zmm11 -; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm11 -; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm10, %zmm11 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u,u,u,u,30,u,28,u,u,u,u,31,u,29,u] +; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm9, %zmm10 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero,ymm5[29],zero,zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u,u,u],zero,ymm6[30],zero,ymm6[28,u,u,u],zero,ymm6[31],zero,ymm6[29,u] +; AVX512-FCP-NEXT: vpor %ymm0, %ymm5, %ymm0 ; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero,ymm5[29],zero,zero -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,3,2,3] -; AVX512-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm5 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm4[30],zero,ymm4[28],zero,zero,zero,zero,ymm4[31],zero,ymm4[29],zero,zero,zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm4[30],zero,ymm4[28],zero,zero,zero,zero,ymm4[31],zero,ymm4[29],zero,zero,zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,30],zero,ymm3[28],zero,ymm3[30,31,30,31],zero,ymm3[29],zero,ymm3[31,28,29] +; AVX512-FCP-NEXT: vpor %ymm4, %ymm3, %ymm3 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,3,2,3] +; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm3 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[27],zero,zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm2[27,u,u,u],zero,ymm2[30],zero,ymm2[28,u,u,u],zero,ymm2[31],zero +; AVX512-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,30],zero,ymm2[28],zero,ymm2[30,31,30,31],zero,ymm2[29],zero,ymm2[31,28,29] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] -; AVX512-FCP-NEXT: vpor %ymm0, %ymm2, %ymm0 -; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm5, %ymm0 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29,u,27,u,u,u,u,30,u,28,u,u,u,u,31,u] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[27],zero,zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] ; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512-FCP-NEXT: vpternlogq $248, %ymm9, %ymm2, %ymm1 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm13[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] -; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm2 -; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm2 -; AVX512-FCP-NEXT: vmovdqa %ymm2, 192(%rax) +; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1 +; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm3, %ymm1 +; AVX512-FCP-NEXT: vmovdqa %ymm1, 192(%rax) ; AVX512-FCP-NEXT: vmovdqa64 %zmm7, (%rax) -; AVX512-FCP-NEXT: vmovdqa64 %zmm11, 128(%rax) +; AVX512-FCP-NEXT: vmovdqa64 %zmm10, 128(%rax) ; AVX512-FCP-NEXT: vmovdqa64 %zmm8, 64(%rax) ; AVX512-FCP-NEXT: vzeroupper ; AVX512-FCP-NEXT: retq @@ -4490,153 +4444,138 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ: # %bb.0: ; AVX512DQ-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512DQ-NEXT: movq {{[0-9]+}}(%rsp), %r10 -; AVX512DQ-NEXT: vmovdqa (%rdi), %ymm2 -; AVX512DQ-NEXT: vmovdqa (%rsi), %ymm1 -; AVX512DQ-NEXT: vmovdqa (%rdx), %ymm11 -; AVX512DQ-NEXT: vmovdqa (%rcx), %ymm3 -; AVX512DQ-NEXT: vmovdqa (%r8), %ymm5 -; AVX512DQ-NEXT: vmovdqa (%r9), %ymm6 -; AVX512DQ-NEXT: vmovdqa (%r10), %ymm4 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm7 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,u,u,u,u,26,27,24,25] -; AVX512DQ-NEXT: vpshuflw {{.*#+}} ymm8 = ymm4[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] -; AVX512DQ-NEXT: vpmovsxbd {{.*#+}} zmm9 = [0,5,4,0,5,0,4,0,20,21,0,23,0,21,0,23] -; AVX512DQ-NEXT: vpermi2d %zmm7, %zmm8, %zmm9 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm7 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[20],zero,ymm6[18],zero,zero,zero,zero,ymm6[21],zero,ymm6[19],zero,zero,zero,zero,ymm6[22] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm8 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm6[25],zero,ymm6[23],zero,zero,zero,zero,ymm6[26],zero,ymm6[24],zero,zero +; AVX512DQ-NEXT: vmovdqa (%rdi), %ymm3 +; AVX512DQ-NEXT: vmovdqa (%rsi), %ymm4 +; AVX512DQ-NEXT: vmovdqa (%rdx), %ymm5 +; AVX512DQ-NEXT: vmovdqa (%rcx), %ymm6 +; AVX512DQ-NEXT: vmovdqa (%r8), %ymm1 +; AVX512DQ-NEXT: vmovdqa (%r9), %ymm2 +; AVX512DQ-NEXT: vmovdqa (%r10), %ymm0 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm7 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[18],zero,zero,zero,zero,ymm6[21],zero,ymm6[19],zero,zero,zero,zero,ymm6[22],zero,ymm6[20] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm8 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[23],zero,zero,zero,zero,ymm3[26],zero,ymm3[24],zero,zero,zero,zero,ymm3[27],zero,ymm3[25] ; AVX512DQ-NEXT: vinserti64x4 $1, %ymm8, %zmm7, %zmm7 ; AVX512DQ-NEXT: vpermq {{.*#+}} zmm7 = zmm7[2,3,2,3,6,7,6,7] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm8 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,20],zero,ymm5[18],zero,ymm5[20,21,20,21],zero,ymm5[19],zero,ymm5[19,20,21,22],zero -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm10 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,ymm5[23],zero,ymm5[23,24,25,26],zero,ymm5[24],zero,ymm5[30,31] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm10, %zmm8, %zmm8 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm8 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,ymm5[18,19,20,21],zero,ymm5[19],zero,ymm5[25,26,27,22],zero,ymm5[20],zero +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm9 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm4[23,u,u,u],zero,ymm4[26],zero,ymm4[24,u,u,u],zero,ymm4[27],zero +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm9, %zmm8, %zmm8 ; AVX512DQ-NEXT: vpermq {{.*#+}} zmm8 = zmm8[2,3,2,3,6,7,6,7] ; AVX512DQ-NEXT: vporq %zmm7, %zmm8, %zmm7 -; AVX512DQ-NEXT: vpternlogd $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm9, %zmm7 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm8 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25,u,23,u,u,u,u,26,u,24,u,u,u,u,27,u] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] -; AVX512DQ-NEXT: vbroadcasti32x4 {{.*#+}} ymm16 = [18374967954648269055,71777218572844800,18374967954648269055,71777218572844800] -; AVX512DQ-NEXT: # ymm16 = mem[0,1,2,3,0,1,2,3] -; AVX512DQ-NEXT: vpandq %ymm16, %ymm8, %ymm8 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm9 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,ymm11[18,19,20,21],zero,ymm11[19],zero,ymm11[25,26,27,22],zero,ymm11[20],zero -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,3,2,3] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm8, %zmm9, %zmm8 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm9 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[18],zero,zero,zero,zero,ymm3[21],zero,ymm3[19],zero,zero,zero,zero,ymm3[22],zero,ymm3[20] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm10 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero,zero,zero,ymm2[27],zero,ymm2[25] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm8 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm4[21],zero,ymm4[19],zero,zero,zero,zero,ymm4[22],zero,ymm4[20],zero,zero +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm9 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm6[25],zero,ymm6[23],zero,zero,zero,zero,ymm6[26],zero,ymm6[24],zero,zero,zero,zero +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm9, %zmm8, %zmm8 +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm8 = zmm8[2,3,2,3,6,7,6,7] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm9 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19,20,21],zero,ymm3[19],zero,ymm3[21,20,21,22],zero,ymm3[20],zero,ymm3[22,23] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm10 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,ymm5[23],zero,ymm5[21,22,23,26],zero,ymm5[24],zero,ymm5[28,29,26,27] ; AVX512DQ-NEXT: vinserti64x4 $1, %ymm10, %zmm9, %zmm9 ; AVX512DQ-NEXT: vpermq {{.*#+}} zmm9 = zmm9[2,3,2,3,6,7,6,7] -; AVX512DQ-NEXT: vporq %zmm9, %zmm8, %zmm9 -; AVX512DQ-NEXT: vpshuflw {{.*#+}} ymm8 = ymm2[1,2,2,3,4,5,6,7,9,10,10,11,12,13,14,15] -; AVX512DQ-NEXT: vpshufd {{.*#+}} ymm8 = ymm8[0,0,1,1,4,4,5,5] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] -; AVX512DQ-NEXT: vbroadcasti32x4 {{.*#+}} ymm17 = [18374966859431673855,18446463693966278655,18374966859431673855,18446463693966278655] -; AVX512DQ-NEXT: # ymm17 = mem[0,1,2,3,0,1,2,3] -; AVX512DQ-NEXT: vpandq %ymm17, %ymm8, %ymm8 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm10 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,ymm11[23],zero,ymm11[21,22,23,26],zero,ymm11[24],zero,ymm11[28,29,26,27] -; AVX512DQ-NEXT: vmovdqa64 %ymm11, %ymm20 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm10, %zmm8, %zmm8 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm10 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm1[21],zero,ymm1[19],zero,zero,zero,zero,ymm1[22],zero,ymm1[20],zero,zero -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm11 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm3[25],zero,ymm3[23],zero,zero,zero,zero,ymm3[26],zero,ymm3[24],zero,zero,zero,zero -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm11, %zmm10, %zmm10 -; AVX512DQ-NEXT: vpermq {{.*#+}} zmm10 = zmm10[2,3,2,3,6,7,6,7] -; AVX512DQ-NEXT: vporq %zmm10, %zmm8, %zmm8 -; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm9, %zmm8 -; AVX512DQ-NEXT: vpternlogq $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm7, %zmm8 -; AVX512DQ-NEXT: vmovdqa (%rsi), %xmm11 -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm7 = xmm11[u],zero,xmm11[7],zero,xmm11[5,u,u,u],zero,xmm11[8],zero,xmm11[6,u,u,u],zero -; AVX512DQ-NEXT: vmovdqa (%rdi), %xmm12 -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm9 = xmm12[u,7],zero,xmm12[5],zero,xmm12[u,u,u,8],zero,xmm12[6],zero,xmm12[u,u,u,9] -; AVX512DQ-NEXT: vpor %xmm7, %xmm9, %xmm7 -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm9 = xmm12[0],xmm11[0],xmm12[1],xmm11[1],xmm12[2],xmm11[2],xmm12[3],xmm11[3],xmm12[4],xmm11[4],xmm12[5],xmm11[5],xmm12[6],xmm11[6],xmm12[7],xmm11[7] -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm9 = xmm9[0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] -; AVX512DQ-NEXT: vinserti32x4 $2, %xmm7, %zmm9, %zmm7 -; AVX512DQ-NEXT: vpermq {{.*#+}} zmm10 = zmm7[0,1,0,1,4,5,4,5] -; AVX512DQ-NEXT: vmovdqa (%rcx), %xmm7 -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm13 = xmm7[u,u,u],zero,xmm7[7],zero,xmm7[5,u,u,u],zero,xmm7[8],zero,xmm7[6,u,u] -; AVX512DQ-NEXT: vmovdqa (%rdx), %xmm9 -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm14 = xmm9[u,u,u,7],zero,xmm9[5],zero,xmm9[u,u,u,8],zero,xmm9[6],zero,xmm9[u,u] -; AVX512DQ-NEXT: vpor %xmm13, %xmm14, %xmm13 -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm14 = xmm9[0],xmm7[0],xmm9[1],xmm7[1],xmm9[2],xmm7[2],xmm9[3],xmm7[3],xmm9[4],xmm7[4],xmm9[5],xmm7[5],xmm9[6],xmm7[6],xmm9[7],xmm7[7] -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm14 = xmm14[4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] -; AVX512DQ-NEXT: vinserti32x4 $2, %xmm13, %zmm14, %zmm13 -; AVX512DQ-NEXT: vpermq {{.*#+}} zmm18 = zmm13[0,1,0,1,4,5,4,5] -; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm10, %zmm18 -; AVX512DQ-NEXT: vmovdqa (%r9), %xmm13 -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm10 = zero,xmm13[4,u,u,u],zero,xmm13[7],zero,xmm13[5,u,u,u],zero,xmm13[8],zero,xmm13[6] -; AVX512DQ-NEXT: vmovdqa (%r8), %xmm14 -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm15 = xmm14[4],zero,xmm14[u,u,u,7],zero,xmm14[5],zero,xmm14[u,u,u,8],zero,xmm14[6],zero -; AVX512DQ-NEXT: vpor %xmm10, %xmm15, %xmm10 -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm15 = xmm14[0],xmm13[0],xmm14[1],xmm13[1],xmm14[2],xmm13[2],xmm14[3],xmm13[3],xmm14[4],xmm13[4],xmm14[5],xmm13[5],xmm14[6],xmm13[6],xmm14[7],xmm13[7] -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm15 = xmm15[u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] -; AVX512DQ-NEXT: vinserti32x4 $2, %xmm10, %zmm15, %zmm10 -; AVX512DQ-NEXT: vpermq {{.*#+}} zmm19 = zmm10[0,1,0,1,4,5,4,5] -; AVX512DQ-NEXT: vmovdqa (%r10), %xmm15 -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm10 = xmm15[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] -; AVX512DQ-NEXT: vpshuflw {{.*#+}} xmm0 = xmm15[1,1,0,0,4,5,6,7] -; AVX512DQ-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[0,1,2,0] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm10, %zmm0, %zmm0 -; AVX512DQ-NEXT: vpermq {{.*#+}} zmm10 = zmm0[0,0,1,0,4,4,5,4] -; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm19, %zmm10 -; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm18, %zmm10 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,ymm1[14,u,u],zero,zero,zero,zero,ymm1[15,u,u],zero,zero,zero,zero,ymm1[16,u,u],zero,zero,zero,zero,ymm1[17,u,u],zero,zero,zero,zero,ymm1[18] +; AVX512DQ-NEXT: vporq %zmm8, %zmm9, %zmm8 +; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm7, %zmm8 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm7 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,u,u,u,u,26,27,24,25] +; AVX512DQ-NEXT: vpshuflw {{.*#+}} ymm9 = ymm0[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] +; AVX512DQ-NEXT: vmovdqa64 %ymm0, %ymm18 +; AVX512DQ-NEXT: vpmovsxbd {{.*#+}} zmm10 = [0,5,4,0,5,0,4,0,20,21,0,23,0,21,0,23] +; AVX512DQ-NEXT: vpermi2d %zmm7, %zmm9, %zmm10 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm7 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[20],zero,ymm2[18],zero,zero,zero,zero,ymm2[21],zero,ymm2[19],zero,zero,zero,zero,ymm2[22] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm9 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[25],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm9, %zmm7, %zmm7 +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm7 = zmm7[2,3,2,3,6,7,6,7] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm9 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,20],zero,ymm1[18],zero,ymm1[20,21,20,21],zero,ymm1[19],zero,ymm1[19,20,21,22],zero +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm11 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,ymm1[23],zero,ymm1[23,24,25,26],zero,ymm1[24],zero,ymm1[30,31] ; AVX512DQ-NEXT: vmovdqa64 %ymm1, %ymm19 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[0,1,14],zero,ymm2[u,u,0,1,14,15],zero,ymm2[u,u,13,2,3,16],zero,ymm2[u,u,28,29,16,17],zero,ymm2[u,u,19,28,29,18],zero -; AVX512DQ-NEXT: vmovdqa64 %ymm2, %ymm18 +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm11, %zmm9, %zmm9 +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm9 = zmm9[2,3,2,3,6,7,6,7] +; AVX512DQ-NEXT: vporq %zmm7, %zmm9, %zmm7 +; AVX512DQ-NEXT: vpternlogd $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm10, %zmm7 +; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm8, %zmm7 +; AVX512DQ-NEXT: vmovdqa (%rsi), %xmm9 +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm8 = xmm9[u],zero,xmm9[7],zero,xmm9[5,u,u,u],zero,xmm9[8],zero,xmm9[6,u,u,u],zero +; AVX512DQ-NEXT: vmovdqa (%rdi), %xmm10 +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm11 = xmm10[u,7],zero,xmm10[5],zero,xmm10[u,u,u,8],zero,xmm10[6],zero,xmm10[u,u,u,9] +; AVX512DQ-NEXT: vpor %xmm8, %xmm11, %xmm8 +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm11 = xmm10[0],xmm9[0],xmm10[1],xmm9[1],xmm10[2],xmm9[2],xmm10[3],xmm9[3],xmm10[4],xmm9[4],xmm10[5],xmm9[5],xmm10[6],xmm9[6],xmm10[7],xmm9[7] +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm11 = xmm11[0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] +; AVX512DQ-NEXT: vinserti32x4 $2, %xmm8, %zmm11, %zmm8 +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm8 = zmm8[0,1,0,1,4,5,4,5] +; AVX512DQ-NEXT: vmovdqa (%rcx), %xmm14 +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm11 = xmm14[u,u,u],zero,xmm14[7],zero,xmm14[5,u,u,u],zero,xmm14[8],zero,xmm14[6,u,u] +; AVX512DQ-NEXT: vmovdqa (%rdx), %xmm15 +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm12 = xmm15[u,u,u,7],zero,xmm15[5],zero,xmm15[u,u,u,8],zero,xmm15[6],zero,xmm15[u,u] +; AVX512DQ-NEXT: vpor %xmm11, %xmm12, %xmm11 +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm12 = xmm15[0],xmm14[0],xmm15[1],xmm14[1],xmm15[2],xmm14[2],xmm15[3],xmm14[3],xmm15[4],xmm14[4],xmm15[5],xmm14[5],xmm15[6],xmm14[6],xmm15[7],xmm14[7] +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm12 = xmm12[4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] +; AVX512DQ-NEXT: vinserti32x4 $2, %xmm11, %zmm12, %zmm11 +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm16 = zmm11[0,1,0,1,4,5,4,5] +; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm8, %zmm16 +; AVX512DQ-NEXT: vmovdqa (%r9), %xmm11 +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm8 = zero,xmm11[4,u,u,u],zero,xmm11[7],zero,xmm11[5,u,u,u],zero,xmm11[8],zero,xmm11[6] +; AVX512DQ-NEXT: vmovdqa (%r8), %xmm12 +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm13 = xmm12[4],zero,xmm12[u,u,u,7],zero,xmm12[5],zero,xmm12[u,u,u,8],zero,xmm12[6],zero +; AVX512DQ-NEXT: vpor %xmm8, %xmm13, %xmm8 +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm13 = xmm12[0],xmm11[0],xmm12[1],xmm11[1],xmm12[2],xmm11[2],xmm12[3],xmm11[3],xmm12[4],xmm11[4],xmm12[5],xmm11[5],xmm12[6],xmm11[6],xmm12[7],xmm11[7] +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm13 = xmm13[u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] +; AVX512DQ-NEXT: vinserti32x4 $2, %xmm8, %zmm13, %zmm8 +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm17 = zmm8[0,1,0,1,4,5,4,5] +; AVX512DQ-NEXT: vmovdqa (%r10), %xmm13 +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm8 = xmm13[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] +; AVX512DQ-NEXT: vpshuflw {{.*#+}} xmm0 = xmm13[1,1,0,0,4,5,6,7] +; AVX512DQ-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[0,1,2,0] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm8, %zmm0, %zmm0 +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm8 = zmm0[0,0,1,0,4,4,5,4] +; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm17, %zmm8 +; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm16, %zmm8 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,ymm4[14,u,u],zero,zero,zero,zero,ymm4[15,u,u],zero,zero,zero,zero,ymm4[16,u,u],zero,zero,zero,zero,ymm4[17,u,u],zero,zero,zero,zero,ymm4[18] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm3[0,1,14],zero,ymm3[u,u,0,1,14,15],zero,ymm3[u,u,13,2,3,16],zero,ymm3[u,u,28,29,16,17],zero,ymm3[u,u,19,28,29,18],zero ; AVX512DQ-NEXT: vpor %ymm0, %ymm1, %ymm0 -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm7[8],xmm9[8],xmm7[9],xmm9[9],xmm7[10],xmm9[10],xmm7[11],xmm9[11],xmm7[12],xmm9[12],xmm7[13],xmm9[13],xmm7[14],xmm9[14],xmm7[15],xmm9[15] +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm14[8],xmm15[8],xmm14[9],xmm15[9],xmm14[10],xmm15[10],xmm14[11],xmm15[11],xmm14[12],xmm15[12],xmm14[13],xmm15[13],xmm14[14],xmm15[14],xmm14[15],xmm15[15] ; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm1 = xmm1[6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] ; AVX512DQ-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,1,0,1] ; AVX512DQ-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm3[u,u,u,u],zero,ymm3[14,u,u,u,u,u],zero,ymm3[15,u,u,u,u,u],zero,ymm3[16,u,u,u,u,u],zero,ymm3[17,u,u,u,u,u] -; AVX512DQ-NEXT: vmovdqa64 %ymm20, %ymm2 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm7 = ymm2[u,u,u,u,14],zero,ymm2[u,u,u,u,u,15],zero,ymm2[u,u,u,u,u,16],zero,ymm2[u,u,u,u,u,17],zero,ymm2[u,u,u,u,u] -; AVX512DQ-NEXT: vpor %ymm1, %ymm7, %ymm1 -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm11[8],xmm12[8],xmm11[9],xmm12[9],xmm11[10],xmm12[10],xmm11[11],xmm12[11],xmm11[12],xmm12[12],xmm11[13],xmm12[13],xmm11[14],xmm12[14],xmm11[15],xmm12[15] -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm7 = xmm7[2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm7 = ymm7[0,1,0,1] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm1, %zmm7, %zmm1 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm6[u,u,u,u],zero,ymm6[14,u,u,u,u,u],zero,ymm6[15,u,u,u,u,u],zero,ymm6[16,u,u,u,u,u],zero,ymm6[17,u,u,u,u,u] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm14 = ymm5[u,u,u,u,14],zero,ymm5[u,u,u,u,u,15],zero,ymm5[u,u,u,u,u,16],zero,ymm5[u,u,u,u,u,17],zero,ymm5[u,u,u,u,u] +; AVX512DQ-NEXT: vpor %ymm1, %ymm14, %ymm1 +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm9 = xmm9[8],xmm10[8],xmm9[9],xmm10[9],xmm9[10],xmm10[10],xmm9[11],xmm10[11],xmm9[12],xmm10[12],xmm9[13],xmm10[13],xmm9[14],xmm10[14],xmm9[15],xmm10[15] +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm9 = xmm9[2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm9 = ymm9[0,1,0,1] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm1, %zmm9, %zmm1 ; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm1 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm0 = zero,ymm5[u,u,u,u,u,14],zero,ymm5[u,u,u,u,u,15],zero,ymm5[u,u,u,u,u,16],zero,ymm5[u,u,u,u,u,17],zero,ymm5[u,u,u] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm7 = ymm6[13,u,u,u,u,u],zero,ymm6[14,u,u,u,u,u],zero,ymm6[15,u,u,u,u,u],zero,ymm6[16,u,u,u,u,u],zero,ymm6[17,u,u,u] -; AVX512DQ-NEXT: vpor %ymm0, %ymm7, %ymm0 -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm14[8],xmm13[8],xmm14[9],xmm13[9],xmm14[10],xmm13[10],xmm14[11],xmm13[11],xmm14[12],xmm13[12],xmm14[13],xmm13[13],xmm14[14],xmm13[14],xmm14[15],xmm13[15] -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm7 = xmm7[u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm7 = ymm7[0,1,0,1] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm0, %zmm7, %zmm0 -; AVX512DQ-NEXT: vpshufhw {{.*#+}} xmm7 = xmm15[0,1,2,3,4,5,5,6] -; AVX512DQ-NEXT: vpshufd {{.*#+}} xmm7 = xmm7[2,2,3,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm7 = ymm7[0,1,0,1] -; AVX512DQ-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm7, %ymm7 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm9 = zero,ymm4[13,u,u,u,u],zero,zero,ymm4[14,u,u,u,u],zero,zero,ymm4[15,u,u,u,u],zero,zero,ymm4[16,u,u,u,u],zero,zero,ymm4[17,u,u] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm9, %zmm7, %zmm7 -; AVX512DQ-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm7 -; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm7 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm0 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29,u,27,u,u,u,u,30,u,28,u,u,u,u,31,u] +; AVX512DQ-NEXT: vmovdqa64 %ymm19, %ymm14 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm0 = zero,ymm14[u,u,u,u,u,14],zero,ymm14[u,u,u,u,u,15],zero,ymm14[u,u,u,u,u,16],zero,ymm14[u,u,u,u,u,17],zero,ymm14[u,u,u] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm9 = ymm2[13,u,u,u,u,u],zero,ymm2[14,u,u,u,u,u],zero,ymm2[15,u,u,u,u,u],zero,ymm2[16,u,u,u,u,u],zero,ymm2[17,u,u,u] +; AVX512DQ-NEXT: vpor %ymm0, %ymm9, %ymm0 +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm9 = xmm12[8],xmm11[8],xmm12[9],xmm11[9],xmm12[10],xmm11[10],xmm12[11],xmm11[11],xmm12[12],xmm11[12],xmm12[13],xmm11[13],xmm12[14],xmm11[14],xmm12[15],xmm11[15] +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm9 = xmm9[u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm9 = ymm9[0,1,0,1] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm0, %zmm9, %zmm0 +; AVX512DQ-NEXT: vpshufhw {{.*#+}} xmm9 = xmm13[0,1,2,3,4,5,5,6] +; AVX512DQ-NEXT: vpshufd {{.*#+}} xmm9 = xmm9[2,2,3,3] +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm9 = ymm9[0,1,0,1] +; AVX512DQ-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm9, %ymm9 +; AVX512DQ-NEXT: vmovdqa64 %ymm18, %ymm11 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm10 = zero,ymm11[13,u,u,u,u],zero,zero,ymm11[14,u,u,u,u],zero,zero,ymm11[15,u,u,u,u],zero,zero,ymm11[16,u,u,u,u],zero,zero,ymm11[17,u,u] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm10, %zmm9, %zmm9 +; AVX512DQ-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm9 +; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm9 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm0 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero,ymm5[29],zero,zero +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u,u,u],zero,ymm6[30],zero,ymm6[28,u,u,u],zero,ymm6[31],zero,ymm6[29,u] +; AVX512DQ-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512DQ-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm5[27],zero,zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero,ymm5[29] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm4[30],zero,ymm4[28],zero,zero,zero,zero,ymm4[31],zero,ymm4[29],zero,zero,zero +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,30],zero,ymm3[28],zero,ymm3[30,31,30,31],zero,ymm3[29],zero,ymm3[31,28,29] +; AVX512DQ-NEXT: vpor %ymm1, %ymm3, %ymm1 ; AVX512DQ-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512DQ-NEXT: vpternlogq $248, %ymm16, %ymm0, %ymm1 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm0 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] +; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm0 = ymm14[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm14[27],zero,zero,zero,zero,ymm14[30],zero,ymm14[28],zero,zero,zero,zero,ymm14[31],zero,ymm14[29] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm2[27,u,u,u],zero,ymm2[30],zero,ymm2[28,u,u,u],zero,ymm2[31],zero +; AVX512DQ-NEXT: vpor %ymm0, %ymm2, %ymm0 ; AVX512DQ-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm0 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u,u,u,u,30,u,28,u,u,u,u,31,u,29,u] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29],zero,zero +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm2 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] ; AVX512DQ-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] -; AVX512DQ-NEXT: vpternlogq $248, %ymm17, %ymm1, %ymm2 -; AVX512DQ-NEXT: vmovdqa64 %ymm19, %ymm1 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29],zero,zero,zero -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512DQ-NEXT: vmovdqa64 %ymm18, %ymm3 -; AVX512DQ-NEXT: vpshufhw {{.*#+}} ymm3 = ymm3[0,1,2,3,6,7,7,6,8,9,10,11,14,15,15,14] -; AVX512DQ-NEXT: vpshufd {{.*#+}} ymm3 = ymm3[2,2,3,3,6,6,7,7] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,3,2,3] -; AVX512DQ-NEXT: vpternlogq $236, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm3 -; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm3 -; AVX512DQ-NEXT: vpternlogq $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm3 -; AVX512DQ-NEXT: vmovdqa %ymm3, 192(%rax) -; AVX512DQ-NEXT: vmovdqa64 %zmm10, (%rax) -; AVX512DQ-NEXT: vmovdqa64 %zmm8, 128(%rax) -; AVX512DQ-NEXT: vmovdqa64 %zmm7, 64(%rax) +; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm2 +; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm2 +; AVX512DQ-NEXT: vmovdqa %ymm2, 192(%rax) +; AVX512DQ-NEXT: vmovdqa64 %zmm8, (%rax) +; AVX512DQ-NEXT: vmovdqa64 %zmm7, 128(%rax) +; AVX512DQ-NEXT: vmovdqa64 %zmm9, 64(%rax) ; AVX512DQ-NEXT: vzeroupper ; AVX512DQ-NEXT: retq ; @@ -4644,12 +4583,12 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-FCP: # %bb.0: ; AVX512DQ-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512DQ-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r10 -; AVX512DQ-FCP-NEXT: vmovdqa (%rdi), %ymm2 +; AVX512DQ-FCP-NEXT: vmovdqa (%rdi), %ymm3 ; AVX512DQ-FCP-NEXT: vmovdqa (%rsi), %ymm4 ; AVX512DQ-FCP-NEXT: vmovdqa (%rdx), %ymm5 ; AVX512DQ-FCP-NEXT: vmovdqa (%rcx), %ymm6 ; AVX512DQ-FCP-NEXT: vmovdqa (%r8), %ymm1 -; AVX512DQ-FCP-NEXT: vmovdqa (%r9), %ymm3 +; AVX512DQ-FCP-NEXT: vmovdqa (%r9), %ymm2 ; AVX512DQ-FCP-NEXT: vmovdqa64 (%r10), %ymm17 ; AVX512DQ-FCP-NEXT: vmovdqa (%rsi), %xmm8 ; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm7 = xmm8[u],zero,xmm8[7],zero,xmm8[5,u,u,u],zero,xmm8[8],zero,xmm8[6,u,u,u],zero @@ -4689,7 +4628,7 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-FCP-NEXT: vpternlogd $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm16, %zmm7 ; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm15, %zmm7 ; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,ymm4[14,u,u],zero,zero,zero,zero,ymm4[15,u,u],zero,zero,zero,zero,ymm4[16,u,u],zero,zero,zero,zero,ymm4[17,u,u],zero,zero,zero,zero,ymm4[18] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm15 = ymm2[0,1,14],zero,ymm2[u,u,0,1,14,15],zero,ymm2[u,u,13,2,3,16],zero,ymm2[u,u,28,29,16,17],zero,ymm2[u,u,19,28,29,18],zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm15 = ymm3[0,1,14],zero,ymm3[u,u,0,1,14,15],zero,ymm3[u,u,13,2,3,16],zero,ymm3[u,u,28,29,16,17],zero,ymm3[u,u,19,28,29,18],zero ; AVX512DQ-FCP-NEXT: vpor %ymm0, %ymm15, %ymm0 ; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm11 = xmm11[8],xmm12[8],xmm11[9],xmm12[9],xmm11[10],xmm12[10],xmm11[11],xmm12[11],xmm11[12],xmm12[12],xmm11[13],xmm12[13],xmm11[14],xmm12[14],xmm11[15],xmm12[15] ; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm11 = xmm11[6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] @@ -4704,7 +4643,7 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm8, %zmm9 ; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm9 ; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,ymm1[u,u,u,u,u,14],zero,ymm1[u,u,u,u,u,15],zero,ymm1[u,u,u,u,u,16],zero,ymm1[u,u,u,u,u,17],zero,ymm1[u,u,u] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm3[13,u,u,u,u,u],zero,ymm3[14,u,u,u,u,u],zero,ymm3[15,u,u,u,u,u],zero,ymm3[16,u,u,u,u,u],zero,ymm3[17,u,u,u] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm2[13,u,u,u,u,u],zero,ymm2[14,u,u,u,u,u],zero,ymm2[15,u,u,u,u,u],zero,ymm2[16,u,u,u,u,u],zero,ymm2[17,u,u,u] ; AVX512DQ-FCP-NEXT: vpor %ymm0, %ymm8, %ymm0 ; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm8 = xmm14[8],xmm13[8],xmm14[9],xmm13[9],xmm14[10],xmm13[10],xmm14[11],xmm13[11],xmm14[12],xmm13[12],xmm14[13],xmm13[13],xmm14[14],xmm13[14],xmm14[15],xmm13[15] ; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm8 = xmm8[u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] @@ -4715,74 +4654,67 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-FCP-NEXT: # ymm10 = mem[0,1,0,1] ; AVX512DQ-FCP-NEXT: vpermd %ymm8, %ymm10, %ymm8 ; AVX512DQ-FCP-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm8, %ymm8 -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm17, %ymm13 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm10 = zero,ymm13[13,u,u,u,u],zero,zero,ymm13[14,u,u,u,u],zero,zero,ymm13[15,u,u,u,u],zero,zero,ymm13[16,u,u,u,u],zero,zero,ymm13[17,u,u] +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm17, %ymm12 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm10 = zero,ymm12[13,u,u,u,u],zero,zero,ymm12[14,u,u,u,u],zero,zero,ymm12[15,u,u,u,u],zero,zero,ymm12[16,u,u,u,u],zero,zero,ymm12[17,u,u] ; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm8, %zmm8 ; AVX512DQ-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm8 ; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm9, %zmm8 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25,u,23,u,u,u,u,26,u,24,u,u,u,u,27,u] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm9 = [18374967954648269055,71777218572844800,18374967954648269055,71777218572844800] -; AVX512DQ-FCP-NEXT: # ymm9 = mem[0,1,0,1] -; AVX512DQ-FCP-NEXT: vpand %ymm0, %ymm9, %ymm0 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,ymm5[18,19,20,21],zero,ymm5[19],zero,ymm5[25,26,27,22],zero,ymm5[20],zero -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm10, %zmm0 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[18],zero,zero,zero,zero,ymm6[21],zero,ymm6[19],zero,zero,zero,zero,ymm6[22],zero,ymm6[20] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero,zero,zero,ymm2[27],zero,ymm2[25] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[18],zero,zero,zero,zero,ymm6[21],zero,ymm6[19],zero,zero,zero,zero,ymm6[22],zero,ymm6[20] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[23],zero,zero,zero,zero,ymm3[26],zero,ymm3[24],zero,zero,zero,zero,ymm3[27],zero,ymm3[25] +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm9, %zmm0, %zmm0 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm0 = zmm0[2,3,2,3,6,7,6,7] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,ymm5[18,19,20,21],zero,ymm5[19],zero,ymm5[25,26,27,22],zero,ymm5[20],zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm4[23,u,u,u],zero,ymm4[26],zero,ymm4[24,u,u,u],zero,ymm4[27],zero +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm9, %zmm9 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm9 = zmm9[2,3,2,3,6,7,6,7] +; AVX512DQ-FCP-NEXT: vporq %zmm0, %zmm9, %zmm0 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm4[21],zero,ymm4[19],zero,zero,zero,zero,ymm4[22],zero,ymm4[20],zero,zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm6[25],zero,ymm6[23],zero,zero,zero,zero,ymm6[26],zero,ymm6[24],zero,zero,zero,zero +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm9, %zmm9 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm9 = zmm9[2,3,2,3,6,7,6,7] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19,20,21],zero,ymm3[19],zero,ymm3[21,20,21,22],zero,ymm3[20],zero,ymm3[22,23] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,ymm5[23],zero,ymm5[21,22,23,26],zero,ymm5[24],zero,ymm5[28,29,26,27] ; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm10, %zmm10 ; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm10 = zmm10[2,3,2,3,6,7,6,7] -; AVX512DQ-FCP-NEXT: vporq %zmm10, %zmm0, %zmm0 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm4[21],zero,ymm4[19],zero,zero,zero,zero,ymm4[22],zero,ymm4[20],zero,zero -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm6[25],zero,ymm6[23],zero,zero,zero,zero,ymm6[26],zero,ymm6[24],zero,zero,zero,zero +; AVX512DQ-FCP-NEXT: vporq %zmm9, %zmm10, %zmm9 +; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm9 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[20],zero,ymm2[18],zero,zero,zero,zero,ymm2[21],zero,ymm2[19],zero,zero,zero,zero,ymm2[22] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[25],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm0, %zmm0 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm0 = zmm0[2,3,2,3,6,7,6,7] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,20],zero,ymm1[18],zero,ymm1[20,21,20,21],zero,ymm1[19],zero,ymm1[19,20,21,22],zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,ymm1[23],zero,ymm1[23,24,25,26],zero,ymm1[24],zero,ymm1[30,31] ; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm10, %zmm10 ; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm10 = zmm10[2,3,2,3,6,7,6,7] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19,20,21],zero,ymm2[19],zero,ymm2[21,20,21,22],zero,ymm2[20],zero,ymm2[22,23] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,ymm5[23],zero,ymm5[21,22,23,26],zero,ymm5[24],zero,ymm5[28,29,26,27] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm12, %zmm11, %zmm11 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm11 = zmm11[2,3,2,3,6,7,6,7] -; AVX512DQ-FCP-NEXT: vporq %zmm10, %zmm11, %zmm10 +; AVX512DQ-FCP-NEXT: vporq %zmm0, %zmm10, %zmm0 +; AVX512DQ-FCP-NEXT: vpshuflw {{.*#+}} ymm10 = ymm12[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] +; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} ymm11 = [0,5,4,0,5,0,4,0] +; AVX512DQ-FCP-NEXT: vpermd %ymm10, %ymm11, %ymm10 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm10, %zmm10 ; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm10 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[20],zero,ymm3[18],zero,zero,zero,zero,ymm3[21],zero,ymm3[19],zero,zero,zero,zero,ymm3[22] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm3[25],zero,ymm3[23],zero,zero,zero,zero,ymm3[26],zero,ymm3[24],zero,zero -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm0, %zmm0 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm0 = zmm0[2,3,2,3,6,7,6,7] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,20],zero,ymm1[18],zero,ymm1[20,21,20,21],zero,ymm1[19],zero,ymm1[19,20,21,22],zero -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,ymm1[23],zero,ymm1[23,24,25,26],zero,ymm1[24],zero,ymm1[30,31] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm12, %zmm11, %zmm11 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm11 = zmm11[2,3,2,3,6,7,6,7] -; AVX512DQ-FCP-NEXT: vporq %zmm0, %zmm11, %zmm0 -; AVX512DQ-FCP-NEXT: vpshuflw {{.*#+}} ymm11 = ymm13[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] -; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} ymm12 = [0,5,4,0,5,0,4,0] -; AVX512DQ-FCP-NEXT: vpermd %ymm11, %ymm12, %ymm11 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm13[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm12, %zmm11, %zmm11 -; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm11 -; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm10, %zmm11 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u,u,u,u,30,u,28,u,u,u,u,31,u,29,u] +; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm9, %zmm10 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero,ymm5[29],zero,zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u,u,u],zero,ymm6[30],zero,ymm6[28,u,u,u],zero,ymm6[31],zero,ymm6[29,u] +; AVX512DQ-FCP-NEXT: vpor %ymm0, %ymm5, %ymm0 ; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero,ymm5[29],zero,zero -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm5 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm4[30],zero,ymm4[28],zero,zero,zero,zero,ymm4[31],zero,ymm4[29],zero,zero,zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm4[30],zero,ymm4[28],zero,zero,zero,zero,ymm4[31],zero,ymm4[29],zero,zero,zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,30],zero,ymm3[28],zero,ymm3[30,31,30,31],zero,ymm3[29],zero,ymm3[31,28,29] +; AVX512DQ-FCP-NEXT: vpor %ymm4, %ymm3, %ymm3 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,3,2,3] +; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm3 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[27],zero,zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm2[27,u,u,u],zero,ymm2[30],zero,ymm2[28,u,u,u],zero,ymm2[31],zero +; AVX512DQ-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,30],zero,ymm2[28],zero,ymm2[30,31,30,31],zero,ymm2[29],zero,ymm2[31,28,29] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpor %ymm0, %ymm2, %ymm0 -; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm5, %ymm0 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29,u,27,u,u,u,u,30,u,28,u,u,u,u,31,u] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[27],zero,zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] ; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpternlogq $248, %ymm9, %ymm2, %ymm1 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm13[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm2 -; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm2 -; AVX512DQ-FCP-NEXT: vmovdqa %ymm2, 192(%rax) +; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm1 +; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm3, %ymm1 +; AVX512DQ-FCP-NEXT: vmovdqa %ymm1, 192(%rax) ; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm7, (%rax) -; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm11, 128(%rax) +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm10, 128(%rax) ; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm8, 64(%rax) ; AVX512DQ-FCP-NEXT: vzeroupper ; AVX512DQ-FCP-NEXT: retq @@ -4841,33 +4773,29 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-NEXT: vmovdqu8 %zmm9, %zmm0 {%k1} ; AVX512BW-NEXT: vinserti64x4 $1, %ymm2, %zmm1, %zmm9 ; AVX512BW-NEXT: vpshufb {{.*#+}} zmm9 = zmm9[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,zmm9[18,19,20,21],zero,zmm9[19],zero,zmm9[25,26,27,22],zero,zmm9[20],zero,zmm9[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,57],zero,zmm9[55],zero,zero,zero,zero,zmm9[58],zero,zmm9[56],zero,zero,zero,zero,zmm9[59],zero -; AVX512BW-NEXT: vpermq {{.*#+}} zmm9 = zmm9[2,3,2,3,6,7,6,7] ; AVX512BW-NEXT: vinserti64x4 $1, %ymm4, %zmm3, %zmm15 ; AVX512BW-NEXT: vpshufb {{.*#+}} zmm15 = zmm15[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm15[18],zero,zero,zero,zero,zmm15[21],zero,zmm15[19],zero,zero,zero,zero,zmm15[22],zero,zmm15[20,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm15[55],zero,zero,zero,zero,zmm15[58],zero,zmm15[56],zero,zero,zero,zero,zmm15[59],zero,zmm15[57] -; AVX512BW-NEXT: vpermq {{.*#+}} zmm15 = zmm15[2,3,2,3,6,7,6,7] ; AVX512BW-NEXT: vporq %zmm9, %zmm15, %zmm9 +; AVX512BW-NEXT: vpermq {{.*#+}} zmm9 = zmm9[2,3,2,3,6,7,6,7] ; AVX512BW-NEXT: vpshuflw {{.*#+}} ymm15 = ymm4[1,2,2,3,4,5,6,7,9,10,10,11,12,13,14,15] ; AVX512BW-NEXT: vpshufd {{.*#+}} ymm15 = ymm15[0,0,1,1,4,4,5,5] ; AVX512BW-NEXT: movl $676341840, %ecx # imm = 0x28502850 ; AVX512BW-NEXT: kmovd %ecx, %k1 ; AVX512BW-NEXT: vpshufb {{.*#+}} ymm15 {%k1} = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,21,u,19,u,u,u,u,22,u,20,u,u] -; AVX512BW-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,3,2,3] ; AVX512BW-NEXT: vpshufb {{.*#+}} ymm16 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,ymm1[23],zero,ymm1[21,22,23,26],zero,ymm1[24],zero,ymm1[28,29,26,27] -; AVX512BW-NEXT: vpermq {{.*#+}} ymm16 = ymm16[2,3,2,3] ; AVX512BW-NEXT: vpshufb {{.*#+}} ymm17 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm3[25],zero,ymm3[23],zero,zero,zero,zero,ymm3[26],zero,ymm3[24],zero,zero,zero,zero -; AVX512BW-NEXT: vpermq {{.*#+}} ymm17 = ymm17[2,3,2,3] ; AVX512BW-NEXT: vporq %ymm16, %ymm17, %ymm16 ; AVX512BW-NEXT: vinserti64x4 $1, %ymm16, %zmm15, %zmm15 +; AVX512BW-NEXT: vpermq {{.*#+}} zmm15 = zmm15[2,3,2,3,6,7,6,7] ; AVX512BW-NEXT: movabsq $-9005497107459067808, %rcx # imm = 0x83060C180C183060 ; AVX512BW-NEXT: kmovq %rcx, %k2 ; AVX512BW-NEXT: vmovdqu8 %zmm15, %zmm9 {%k2} ; AVX512BW-NEXT: vpmovsxbw {{.*#+}} zmm15 = [10,9,9,10,10,9,9,10,9,10,14,15,10,9,9,10,27,29,28,27,28,29,29,28,27,29,28,27,28,29,29,28] ; AVX512BW-NEXT: vpermw %zmm7, %zmm15, %zmm15 ; AVX512BW-NEXT: vpshufb {{.*#+}} zmm16 = zmm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,20],zero,zmm6[18],zero,zmm6[20,21,20,21],zero,zmm6[19],zero,zmm6[19,20,21,22],zero,zmm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,56,57,56,57],zero,zmm6[55],zero,zmm6[55,56,57,58],zero,zmm6[56],zero,zmm6[62,63] -; AVX512BW-NEXT: vpermq {{.*#+}} zmm16 = zmm16[2,3,2,3,6,7,6,7] ; AVX512BW-NEXT: vpshufb {{.*#+}} zmm17 = zmm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm5[20],zero,zmm5[18],zero,zero,zero,zero,zmm5[21],zero,zmm5[19],zero,zero,zero,zero,zmm5[22,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm5[57],zero,zmm5[55],zero,zero,zero,zero,zmm5[58],zero,zmm5[56],zero,zero -; AVX512BW-NEXT: vpermq {{.*#+}} zmm17 = zmm17[2,3,2,3,6,7,6,7] ; AVX512BW-NEXT: vporq %zmm16, %zmm17, %zmm16 +; AVX512BW-NEXT: vpermq {{.*#+}} zmm16 = zmm16[2,3,2,3,6,7,6,7] ; AVX512BW-NEXT: movabsq $1161999626690365456, %rcx # imm = 0x1020408102040810 ; AVX512BW-NEXT: kmovq %rcx, %k2 ; AVX512BW-NEXT: vmovdqu8 %zmm15, %zmm16 {%k2} @@ -4924,10 +4852,9 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-NEXT: # ymm2 = mem[0,1,0,1] ; AVX512BW-NEXT: vpermw %ymm7, %ymm2, %ymm2 ; AVX512BW-NEXT: vpshufb {{.*#+}} ymm3 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm5[27],zero,zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero -; AVX512BW-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,3,2,3] ; AVX512BW-NEXT: vpshufb {{.*#+}} ymm4 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[27],zero,zero,zero,zero,ymm6[30],zero,ymm6[28],zero,zero,zero,zero,ymm6[31],zero,ymm6[29] -; AVX512BW-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,2,3] ; AVX512BW-NEXT: vpor %ymm3, %ymm4, %ymm3 +; AVX512BW-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,3,2,3] ; AVX512BW-NEXT: movl $-2130574328, %ecx # imm = 0x81020408 ; AVX512BW-NEXT: kmovd %ecx, %k1 ; AVX512BW-NEXT: vmovdqu8 %ymm2, %ymm3 {%k1} @@ -4945,8 +4872,8 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-FCP: # %bb.0: ; AVX512BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r10 -; AVX512BW-FCP-NEXT: vmovdqa (%rdi), %ymm4 -; AVX512BW-FCP-NEXT: vmovdqa (%rsi), %ymm3 +; AVX512BW-FCP-NEXT: vmovdqa (%rdi), %ymm3 +; AVX512BW-FCP-NEXT: vmovdqa (%rsi), %ymm4 ; AVX512BW-FCP-NEXT: vmovdqa (%rdx), %ymm1 ; AVX512BW-FCP-NEXT: vmovdqa (%rcx), %ymm2 ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm1[0,1,0,1,14],zero,ymm1[14,15,0,1,14,15],zero,ymm1[13,14,15,16,17,16],zero,ymm1[30,31,30,31,16,17],zero,ymm1[31,28,29,30,31] @@ -4958,8 +4885,8 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} xmm5 = xmm5[2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] ; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm5[0,1,0,1] ; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm5, %zmm5 -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm4[0,1,14],zero,ymm4[12,13,0,1,14,15],zero,ymm4[3,12,13,2,3,16],zero,ymm4[30,31,28,29,16,17],zero,ymm4[31,18,19,28,29,18],zero -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,zero,ymm3[14],zero,zero,zero,zero,zero,zero,ymm3[15],zero,zero,zero,zero,zero,zero,ymm3[16],zero,zero,zero,zero,zero,zero,ymm3[17],zero,zero,zero,zero,zero,zero,ymm3[18] +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm3[0,1,14],zero,ymm3[12,13,0,1,14,15],zero,ymm3[3,12,13,2,3,16],zero,ymm3[30,31,28,29,16,17],zero,ymm3[31,18,19,28,29,18],zero +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,zero,ymm4[14],zero,zero,zero,zero,zero,zero,ymm4[15],zero,zero,zero,zero,zero,zero,ymm4[16],zero,zero,zero,zero,zero,zero,ymm4[17],zero,zero,zero,zero,zero,zero,ymm4[18] ; AVX512BW-FCP-NEXT: vpor %ymm0, %ymm6, %ymm0 ; AVX512BW-FCP-NEXT: vmovdqa (%rdx), %xmm12 ; AVX512BW-FCP-NEXT: vmovdqa (%rcx), %xmm14 @@ -4993,30 +4920,27 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-FCP-NEXT: movabsq $4066998693416279096, %rcx # imm = 0x3870E1C3870E1C38 ; AVX512BW-FCP-NEXT: kmovq %rcx, %k1 ; AVX512BW-FCP-NEXT: vmovdqu8 %zmm10, %zmm0 {%k1} -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm4, %zmm10 +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm3, %zmm10 ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm10 = zmm10[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19,20,21],zero,zmm10[19],zero,zmm10[21,20,21,22],zero,zmm10[20],zero,zmm10[22,23,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,56,57],zero,zmm10[55],zero,zmm10[53,54,55,58],zero,zmm10[56],zero,zmm10[60,61,58,59] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm10 = zmm10[2,3,2,3,6,7,6,7] -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm15 +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm4, %zmm15 ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm15 = zmm15[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm15[21],zero,zmm15[19],zero,zero,zero,zero,zmm15[22],zero,zmm15[20],zero,zero,zmm15[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zmm15[57],zero,zmm15[55],zero,zero,zero,zero,zmm15[58],zero,zmm15[56],zero,zero,zero,zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm15 = zmm15[2,3,2,3,6,7,6,7] -; AVX512BW-FCP-NEXT: vporq %zmm10, %zmm15, %zmm15 -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm3, %zmm1, %zmm10 +; AVX512BW-FCP-NEXT: vporq %zmm10, %zmm15, %zmm10 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm15 = zmm10[2,3,2,3,6,7,6,7] +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm1, %zmm10 ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm10 = zmm10[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,zmm10[18,19,20,21],zero,zmm10[19],zero,zmm10[25,26,27,22],zero,zmm10[20],zero,zmm10[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,57],zero,zmm10[55],zero,zero,zero,zero,zmm10[58],zero,zmm10[56],zero,zero,zero,zero,zmm10[59],zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm10 = zmm10[2,3,2,3,6,7,6,7] -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm2, %zmm16 +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm3, %zmm2, %zmm16 ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm16 = zmm16[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm16[18],zero,zero,zero,zero,zmm16[21],zero,zmm16[19],zero,zero,zero,zero,zmm16[22],zero,zmm16[20,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm16[55],zero,zero,zero,zero,zmm16[58],zero,zmm16[56],zero,zero,zero,zero,zmm16[59],zero,zmm16[57] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm16 = zmm16[2,3,2,3,6,7,6,7] ; AVX512BW-FCP-NEXT: vporq %zmm10, %zmm16, %zmm10 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm10 = zmm10[2,3,2,3,6,7,6,7] ; AVX512BW-FCP-NEXT: movabsq $-9005497107459067808, %rcx # imm = 0x83060C180C183060 ; AVX512BW-FCP-NEXT: kmovq %rcx, %k1 ; AVX512BW-FCP-NEXT: vmovdqu8 %zmm15, %zmm10 {%k1} ; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm15 = [10,9,9,10,10,9,9,10,9,10,14,15,10,9,9,10,27,29,28,27,28,29,29,28,27,29,28,27,28,29,29,28] ; AVX512BW-FCP-NEXT: vpermw %zmm7, %zmm15, %zmm15 ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm16 = zmm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,20],zero,zmm6[18],zero,zmm6[20,21,20,21],zero,zmm6[19],zero,zmm6[19,20,21,22],zero,zmm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,56,57,56,57],zero,zmm6[55],zero,zmm6[55,56,57,58],zero,zmm6[56],zero,zmm6[62,63] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm16 = zmm16[2,3,2,3,6,7,6,7] ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm17 = zmm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm5[20],zero,zmm5[18],zero,zero,zero,zero,zmm5[21],zero,zmm5[19],zero,zero,zero,zero,zmm5[22,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm5[57],zero,zmm5[55],zero,zero,zero,zero,zmm5[58],zero,zmm5[56],zero,zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm17 = zmm17[2,3,2,3,6,7,6,7] ; AVX512BW-FCP-NEXT: vporq %zmm16, %zmm17, %zmm16 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm16 = zmm16[2,3,2,3,6,7,6,7] ; AVX512BW-FCP-NEXT: movabsq $1161999626690365456, %rcx # imm = 0x1020408102040810 ; AVX512BW-FCP-NEXT: kmovq %rcx, %k1 ; AVX512BW-FCP-NEXT: vmovdqu8 %zmm15, %zmm16 {%k1} @@ -5055,16 +4979,14 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-FCP-NEXT: movabsq $8133997386832558192, %rcx # imm = 0x70E1C3870E1C3870 ; AVX512BW-FCP-NEXT: kmovq %rcx, %k1 ; AVX512BW-FCP-NEXT: vmovdqu8 %zmm9, %zmm8 {%k1} -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,30],zero,ymm4[28],zero,ymm4[30,31,30,31],zero,ymm4[29],zero,ymm4[31,28,29] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,2,3] -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm3[30],zero,ymm3[28],zero,zero,zero,zero,ymm3[31],zero,ymm3[29],zero,zero,zero +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,30],zero,ymm3[28],zero,ymm3[30,31,30,31],zero,ymm3[29],zero,ymm3[31,28,29] +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm4[30],zero,ymm4[28],zero,zero,zero,zero,ymm4[31],zero,ymm4[29],zero,zero,zero +; AVX512BW-FCP-NEXT: vpor %ymm3, %ymm4, %ymm3 ; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,3,2,3] -; AVX512BW-FCP-NEXT: vpor %ymm4, %ymm3, %ymm3 ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29],zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29],zero,zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX512BW-FCP-NEXT: vpor %ymm2, %ymm1, %ymm1 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX512BW-FCP-NEXT: movl $101455920, %ecx # imm = 0x60C1830 ; AVX512BW-FCP-NEXT: kmovd %ecx, %k1 ; AVX512BW-FCP-NEXT: vmovdqu8 %ymm3, %ymm1 {%k1} @@ -5072,10 +4994,9 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-FCP-NEXT: # ymm2 = mem[0,1,0,1] ; AVX512BW-FCP-NEXT: vpermw %ymm7, %ymm2, %ymm2 ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm5[27],zero,zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,3,2,3] ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[27],zero,zero,zero,zero,ymm6[30],zero,ymm6[28],zero,zero,zero,zero,ymm6[31],zero,ymm6[29] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,2,3] ; AVX512BW-FCP-NEXT: vpor %ymm3, %ymm4, %ymm3 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,3,2,3] ; AVX512BW-FCP-NEXT: movl $-2130574328, %ecx # imm = 0x81020408 ; AVX512BW-FCP-NEXT: kmovd %ecx, %k1 ; AVX512BW-FCP-NEXT: vmovdqu8 %ymm2, %ymm3 {%k1} @@ -5143,33 +5064,29 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-NEXT: vmovdqu8 %zmm9, %zmm0 {%k1} ; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm2, %zmm1, %zmm9 ; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} zmm9 = zmm9[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,zmm9[18,19,20,21],zero,zmm9[19],zero,zmm9[25,26,27,22],zero,zmm9[20],zero,zmm9[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,57],zero,zmm9[55],zero,zero,zero,zero,zmm9[58],zero,zmm9[56],zero,zero,zero,zero,zmm9[59],zero -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm9 = zmm9[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm4, %zmm3, %zmm15 ; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} zmm15 = zmm15[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm15[18],zero,zero,zero,zero,zmm15[21],zero,zmm15[19],zero,zero,zero,zero,zmm15[22],zero,zmm15[20,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm15[55],zero,zero,zero,zero,zmm15[58],zero,zmm15[56],zero,zero,zero,zero,zmm15[59],zero,zmm15[57] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm15 = zmm15[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-NEXT: vporq %zmm9, %zmm15, %zmm9 +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm9 = zmm9[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-NEXT: vpshuflw {{.*#+}} ymm15 = ymm4[1,2,2,3,4,5,6,7,9,10,10,11,12,13,14,15] ; AVX512DQ-BW-NEXT: vpshufd {{.*#+}} ymm15 = ymm15[0,0,1,1,4,4,5,5] ; AVX512DQ-BW-NEXT: movl $676341840, %ecx # imm = 0x28502850 ; AVX512DQ-BW-NEXT: kmovd %ecx, %k1 ; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm15 {%k1} = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,21,u,19,u,u,u,u,22,u,20,u,u] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,3,2,3] ; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm16 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,ymm1[23],zero,ymm1[21,22,23,26],zero,ymm1[24],zero,ymm1[28,29,26,27] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm16 = ymm16[2,3,2,3] ; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm17 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm3[25],zero,ymm3[23],zero,zero,zero,zero,ymm3[26],zero,ymm3[24],zero,zero,zero,zero -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm17 = ymm17[2,3,2,3] ; AVX512DQ-BW-NEXT: vporq %ymm16, %ymm17, %ymm16 ; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm16, %zmm15, %zmm15 +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm15 = zmm15[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-NEXT: movabsq $-9005497107459067808, %rcx # imm = 0x83060C180C183060 ; AVX512DQ-BW-NEXT: kmovq %rcx, %k2 ; AVX512DQ-BW-NEXT: vmovdqu8 %zmm15, %zmm9 {%k2} ; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} zmm15 = [10,9,9,10,10,9,9,10,9,10,14,15,10,9,9,10,27,29,28,27,28,29,29,28,27,29,28,27,28,29,29,28] ; AVX512DQ-BW-NEXT: vpermw %zmm7, %zmm15, %zmm15 ; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} zmm16 = zmm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,20],zero,zmm6[18],zero,zmm6[20,21,20,21],zero,zmm6[19],zero,zmm6[19,20,21,22],zero,zmm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,56,57,56,57],zero,zmm6[55],zero,zmm6[55,56,57,58],zero,zmm6[56],zero,zmm6[62,63] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm16 = zmm16[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} zmm17 = zmm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm5[20],zero,zmm5[18],zero,zero,zero,zero,zmm5[21],zero,zmm5[19],zero,zero,zero,zero,zmm5[22,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm5[57],zero,zmm5[55],zero,zero,zero,zero,zmm5[58],zero,zmm5[56],zero,zero -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm17 = zmm17[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-NEXT: vporq %zmm16, %zmm17, %zmm16 +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm16 = zmm16[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-NEXT: movabsq $1161999626690365456, %rcx # imm = 0x1020408102040810 ; AVX512DQ-BW-NEXT: kmovq %rcx, %k2 ; AVX512DQ-BW-NEXT: vmovdqu8 %zmm15, %zmm16 {%k2} @@ -5226,10 +5143,9 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-NEXT: # ymm2 = mem[0,1,0,1] ; AVX512DQ-BW-NEXT: vpermw %ymm7, %ymm2, %ymm2 ; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm3 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm5[27],zero,zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,3,2,3] ; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm4 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[27],zero,zero,zero,zero,ymm6[30],zero,ymm6[28],zero,zero,zero,zero,ymm6[31],zero,ymm6[29] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,2,3] ; AVX512DQ-BW-NEXT: vpor %ymm3, %ymm4, %ymm3 +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,3,2,3] ; AVX512DQ-BW-NEXT: movl $-2130574328, %ecx # imm = 0x81020408 ; AVX512DQ-BW-NEXT: kmovd %ecx, %k1 ; AVX512DQ-BW-NEXT: vmovdqu8 %ymm2, %ymm3 {%k1} @@ -5247,8 +5163,8 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-FCP: # %bb.0: ; AVX512DQ-BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512DQ-BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %r10 -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdi), %ymm4 -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rsi), %ymm3 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdi), %ymm3 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rsi), %ymm4 ; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdx), %ymm1 ; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rcx), %ymm2 ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm1[0,1,0,1,14],zero,ymm1[14,15,0,1,14,15],zero,ymm1[13,14,15,16,17,16],zero,ymm1[30,31,30,31,16,17],zero,ymm1[31,28,29,30,31] @@ -5260,8 +5176,8 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} xmm5 = xmm5[2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] ; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm5[0,1,0,1] ; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm5, %zmm5 -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm4[0,1,14],zero,ymm4[12,13,0,1,14,15],zero,ymm4[3,12,13,2,3,16],zero,ymm4[30,31,28,29,16,17],zero,ymm4[31,18,19,28,29,18],zero -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,zero,ymm3[14],zero,zero,zero,zero,zero,zero,ymm3[15],zero,zero,zero,zero,zero,zero,ymm3[16],zero,zero,zero,zero,zero,zero,ymm3[17],zero,zero,zero,zero,zero,zero,ymm3[18] +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm3[0,1,14],zero,ymm3[12,13,0,1,14,15],zero,ymm3[3,12,13,2,3,16],zero,ymm3[30,31,28,29,16,17],zero,ymm3[31,18,19,28,29,18],zero +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,zero,ymm4[14],zero,zero,zero,zero,zero,zero,ymm4[15],zero,zero,zero,zero,zero,zero,ymm4[16],zero,zero,zero,zero,zero,zero,ymm4[17],zero,zero,zero,zero,zero,zero,ymm4[18] ; AVX512DQ-BW-FCP-NEXT: vpor %ymm0, %ymm6, %ymm0 ; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdx), %xmm12 ; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rcx), %xmm14 @@ -5295,30 +5211,27 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-FCP-NEXT: movabsq $4066998693416279096, %rcx # imm = 0x3870E1C3870E1C38 ; AVX512DQ-BW-FCP-NEXT: kmovq %rcx, %k1 ; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm10, %zmm0 {%k1} -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm4, %zmm10 +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm3, %zmm10 ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm10 = zmm10[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18,19,20,21],zero,zmm10[19],zero,zmm10[21,20,21,22],zero,zmm10[20],zero,zmm10[22,23,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,56,57],zero,zmm10[55],zero,zmm10[53,54,55,58],zero,zmm10[56],zero,zmm10[60,61,58,59] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm10 = zmm10[2,3,2,3,6,7,6,7] -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm15 +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm4, %zmm15 ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm15 = zmm15[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm15[21],zero,zmm15[19],zero,zero,zero,zero,zmm15[22],zero,zmm15[20],zero,zero,zmm15[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zmm15[57],zero,zmm15[55],zero,zero,zero,zero,zmm15[58],zero,zmm15[56],zero,zero,zero,zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm15 = zmm15[2,3,2,3,6,7,6,7] -; AVX512DQ-BW-FCP-NEXT: vporq %zmm10, %zmm15, %zmm15 -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm3, %zmm1, %zmm10 +; AVX512DQ-BW-FCP-NEXT: vporq %zmm10, %zmm15, %zmm10 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm15 = zmm10[2,3,2,3,6,7,6,7] +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm1, %zmm10 ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm10 = zmm10[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,zmm10[18,19,20,21],zero,zmm10[19],zero,zmm10[25,26,27,22],zero,zmm10[20],zero,zmm10[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,57],zero,zmm10[55],zero,zero,zero,zero,zmm10[58],zero,zmm10[56],zero,zero,zero,zero,zmm10[59],zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm10 = zmm10[2,3,2,3,6,7,6,7] -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm2, %zmm16 +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm3, %zmm2, %zmm16 ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm16 = zmm16[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm16[18],zero,zero,zero,zero,zmm16[21],zero,zmm16[19],zero,zero,zero,zero,zmm16[22],zero,zmm16[20,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm16[55],zero,zero,zero,zero,zmm16[58],zero,zmm16[56],zero,zero,zero,zero,zmm16[59],zero,zmm16[57] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm16 = zmm16[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-FCP-NEXT: vporq %zmm10, %zmm16, %zmm10 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm10 = zmm10[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-FCP-NEXT: movabsq $-9005497107459067808, %rcx # imm = 0x83060C180C183060 ; AVX512DQ-BW-FCP-NEXT: kmovq %rcx, %k1 ; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm15, %zmm10 {%k1} ; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm15 = [10,9,9,10,10,9,9,10,9,10,14,15,10,9,9,10,27,29,28,27,28,29,29,28,27,29,28,27,28,29,29,28] ; AVX512DQ-BW-FCP-NEXT: vpermw %zmm7, %zmm15, %zmm15 ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm16 = zmm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,20],zero,zmm6[18],zero,zmm6[20,21,20,21],zero,zmm6[19],zero,zmm6[19,20,21,22],zero,zmm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,56,57,56,57],zero,zmm6[55],zero,zmm6[55,56,57,58],zero,zmm6[56],zero,zmm6[62,63] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm16 = zmm16[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm17 = zmm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm5[20],zero,zmm5[18],zero,zero,zero,zero,zmm5[21],zero,zmm5[19],zero,zero,zero,zero,zmm5[22,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm5[57],zero,zmm5[55],zero,zero,zero,zero,zmm5[58],zero,zmm5[56],zero,zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm17 = zmm17[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-FCP-NEXT: vporq %zmm16, %zmm17, %zmm16 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm16 = zmm16[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-FCP-NEXT: movabsq $1161999626690365456, %rcx # imm = 0x1020408102040810 ; AVX512DQ-BW-FCP-NEXT: kmovq %rcx, %k1 ; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm15, %zmm16 {%k1} @@ -5357,16 +5270,14 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-FCP-NEXT: movabsq $8133997386832558192, %rcx # imm = 0x70E1C3870E1C3870 ; AVX512DQ-BW-FCP-NEXT: kmovq %rcx, %k1 ; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm9, %zmm8 {%k1} -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,30],zero,ymm4[28],zero,ymm4[30,31,30,31],zero,ymm4[29],zero,ymm4[31,28,29] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,2,3] -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm3[30],zero,ymm3[28],zero,zero,zero,zero,ymm3[31],zero,ymm3[29],zero,zero,zero +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,30],zero,ymm3[28],zero,ymm3[30,31,30,31],zero,ymm3[29],zero,ymm3[31,28,29] +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm4[30],zero,ymm4[28],zero,zero,zero,zero,ymm4[31],zero,ymm4[29],zero,zero,zero +; AVX512DQ-BW-FCP-NEXT: vpor %ymm3, %ymm4, %ymm3 ; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,3,2,3] -; AVX512DQ-BW-FCP-NEXT: vpor %ymm4, %ymm3, %ymm3 ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29],zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29],zero,zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX512DQ-BW-FCP-NEXT: vpor %ymm2, %ymm1, %ymm1 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX512DQ-BW-FCP-NEXT: movl $101455920, %ecx # imm = 0x60C1830 ; AVX512DQ-BW-FCP-NEXT: kmovd %ecx, %k1 ; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %ymm3, %ymm1 {%k1} @@ -5374,10 +5285,9 @@ define void @store_i8_stride7_vf32(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-FCP-NEXT: # ymm2 = mem[0,1,0,1] ; AVX512DQ-BW-FCP-NEXT: vpermw %ymm7, %ymm2, %ymm2 ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm5[27],zero,zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,3,2,3] ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[27],zero,zero,zero,zero,ymm6[30],zero,ymm6[28],zero,zero,zero,zero,ymm6[31],zero,ymm6[29] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,2,3] ; AVX512DQ-BW-FCP-NEXT: vpor %ymm3, %ymm4, %ymm3 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,3,2,3] ; AVX512DQ-BW-FCP-NEXT: movl $-2130574328, %ecx # imm = 0x81020408 ; AVX512DQ-BW-FCP-NEXT: kmovd %ecx, %k1 ; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %ymm2, %ymm3 {%k1} @@ -7376,8 +7286,8 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX2-NEXT: vmovdqa 32(%rdi), %ymm0 ; AVX2-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-NEXT: vmovdqa 32(%rsi), %ymm1 -; AVX2-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX2-NEXT: vmovdqa 32(%rsi), %ymm2 +; AVX2-NEXT: vmovdqu %ymm2, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-NEXT: vmovdqa 32(%rdx), %ymm6 ; AVX2-NEXT: vmovdqu %ymm6, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-NEXT: vmovdqa 32(%rcx), %ymm7 @@ -7389,15 +7299,13 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-NEXT: vmovdqa 32(%rax), %ymm3 ; AVX2-NEXT: vmovdqu %ymm3, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm0[23],zero,ymm0[27,20,21,26],zero,ymm0[24],zero,ymm0[26,27,26,27],zero,ymm0[25] -; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX2-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm1[23],zero,zero,zero,zero,ymm1[26],zero,ymm1[24],zero,zero,zero,zero,ymm1[27],zero -; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] +; AVX2-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero,zero,zero,ymm2[27],zero ; AVX2-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] ; AVX2-NEXT: vpshufb {{.*#+}} ymm1 = ymm7[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm7[25],zero,ymm7[23],zero,zero,zero,zero,ymm7[26],zero,ymm7[24],zero,zero,zero,zero -; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-NEXT: vpshufb {{.*#+}} ymm2 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm6[25],zero,ymm6[23],zero,zero,zero,zero,ymm6[26],zero,ymm6[24],zero,zero,zero,zero,ymm6[27] -; AVX2-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] ; AVX2-NEXT: vpor %ymm1, %ymm2, %ymm1 +; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-NEXT: vmovdqa {{.*#+}} ymm2 = [u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0] ; AVX2-NEXT: vpblendvb %ymm2, %ymm0, %ymm1, %ymm0 ; AVX2-NEXT: vpshufb {{.*#+}} ymm1 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25,22,23,22,23,24,25,26,27,24,25,30,31] @@ -7415,17 +7323,16 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-NEXT: vmovdqa (%r8), %ymm0 ; AVX2-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[27],zero,ymm0[27,28,29,30],zero,ymm0[28],zero,ymm0[26,27,30,31],zero,ymm0[29] -; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] ; AVX2-NEXT: vmovdqa (%r9), %ymm1 ; AVX2-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX2-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[27],zero,ymm0[27,28,29,30],zero,ymm0[28],zero,ymm0[26,27,30,31],zero,ymm0[29] ; AVX2-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm1[27],zero,zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero -; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX2-NEXT: vmovdqa (%rax), %ymm1 ; AVX2-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] ; AVX2-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] +; AVX2-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] ; AVX2-NEXT: vmovdqa {{.*#+}} ymm2 = [u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0] ; AVX2-NEXT: vpblendvb %ymm2, %ymm0, %ymm1, %ymm0 ; AVX2-NEXT: vmovdqa (%rdx), %ymm1 @@ -7622,12 +7529,11 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-NEXT: # ymm3 = mem[0,1,0,1] ; AVX2-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload ; AVX2-NEXT: vpshufb %ymm3, %ymm0, %ymm2 -; AVX2-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] ; AVX2-NEXT: vmovdqa {{.*#+}} ymm4 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128] ; AVX2-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload ; AVX2-NEXT: vpshufb %ymm4, %ymm0, %ymm5 -; AVX2-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,3,2,3] ; AVX2-NEXT: vpor %ymm2, %ymm5, %ymm2 +; AVX2-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] ; AVX2-NEXT: vpshuflw $150, {{[-0-9]+}}(%r{{[sb]}}p), %ymm5 # 32-byte Folded Reload ; AVX2-NEXT: # ymm5 = mem[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] ; AVX2-NEXT: vpshufd {{.*#+}} ymm5 = ymm5[0,1,1,3,4,5,5,7] @@ -7635,15 +7541,14 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-NEXT: vmovdqa {{.*#+}} ymm6 = [u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255] ; AVX2-NEXT: vpblendvb %ymm6, %ymm2, %ymm5, %ymm0 ; AVX2-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm14 # 32-byte Reload -; AVX2-NEXT: vpshufb %ymm3, %ymm14, %ymm3 -; AVX2-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,3,2,3] +; AVX2-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm8 # 32-byte Reload +; AVX2-NEXT: vpshufb %ymm3, %ymm8, %ymm3 ; AVX2-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm13 # 32-byte Reload ; AVX2-NEXT: vpshufb %ymm4, %ymm13, %ymm4 -; AVX2-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,2,3] ; AVX2-NEXT: vpor %ymm3, %ymm4, %ymm3 -; AVX2-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm8 # 32-byte Reload -; AVX2-NEXT: vpshuflw {{.*#+}} ymm4 = ymm8[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] +; AVX2-NEXT: vpermq {{.*#+}} ymm3 = ymm3[2,3,2,3] +; AVX2-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm14 # 32-byte Reload +; AVX2-NEXT: vpshuflw {{.*#+}} ymm4 = ymm14[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] ; AVX2-NEXT: vpshufd {{.*#+}} ymm4 = ymm4[0,1,1,3,4,5,5,7] ; AVX2-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,2,3,2] ; AVX2-NEXT: vpblendvb %ymm6, %ymm3, %ymm4, %ymm0 @@ -7665,24 +7570,22 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-NEXT: vpblendvb %ymm7, %ymm6, %ymm5, %ymm5 ; AVX2-NEXT: vbroadcasti128 {{.*#+}} ymm6 = [128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20] ; AVX2-NEXT: # ymm6 = mem[0,1,0,1] -; AVX2-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm10 # 32-byte Reload -; AVX2-NEXT: vpshufb %ymm6, %ymm10, %ymm7 -; AVX2-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] -; AVX2-NEXT: vmovdqa {{.*#+}} ymm3 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128] ; AVX2-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload -; AVX2-NEXT: vpshufb %ymm3, %ymm2, %ymm9 -; AVX2-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,3,2,3] +; AVX2-NEXT: vpshufb %ymm6, %ymm2, %ymm7 +; AVX2-NEXT: vmovdqa {{.*#+}} ymm3 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128] +; AVX2-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm10 # 32-byte Reload +; AVX2-NEXT: vpshufb %ymm3, %ymm10, %ymm9 ; AVX2-NEXT: vpor %ymm7, %ymm9, %ymm7 +; AVX2-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] ; AVX2-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,2,3] ; AVX2-NEXT: vmovdqa {{.*#+}} ymm9 = [255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u] ; AVX2-NEXT: vpblendvb %ymm9, %ymm7, %ymm4, %ymm4 ; AVX2-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm15 # 32-byte Reload ; AVX2-NEXT: vpshufb %ymm6, %ymm15, %ymm6 -; AVX2-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,3,2,3] ; AVX2-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm12 # 32-byte Reload ; AVX2-NEXT: vpshufb %ymm3, %ymm12, %ymm7 -; AVX2-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] ; AVX2-NEXT: vpor %ymm6, %ymm7, %ymm6 +; AVX2-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,3,2,3] ; AVX2-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,3,2,3] ; AVX2-NEXT: vpblendvb %ymm9, %ymm6, %ymm5, %ymm5 ; AVX2-NEXT: vmovdqa {{.*#+}} ymm6 = [255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0] @@ -7693,26 +7596,22 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-NEXT: vpblendvb %ymm6, %ymm5, %ymm3, %ymm3 ; AVX2-NEXT: vmovdqu %ymm3, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-NEXT: vpshufb {{.*#+}} ymm4 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm0[23],zero,ymm0[27,20,21,26],zero,ymm0[24],zero,ymm0[26,27,26,27],zero,ymm0[25] -; AVX2-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,2,3] ; AVX2-NEXT: vmovdqa %ymm1, %ymm0 ; AVX2-NEXT: vpshufb {{.*#+}} ymm5 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm1[23],zero,zero,zero,zero,ymm1[26],zero,ymm1[24],zero,zero,zero,zero,ymm1[27],zero -; AVX2-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,3,2,3] ; AVX2-NEXT: vpor %ymm4, %ymm5, %ymm4 ; AVX2-NEXT: vpshufb {{.*#+}} ymm5 = ymm15[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm15[25],zero,ymm15[23],zero,zero,zero,zero,ymm15[26],zero,ymm15[24],zero,zero,zero,zero -; AVX2-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,3,2,3] ; AVX2-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm12[25],zero,ymm12[23],zero,zero,zero,zero,ymm12[26],zero,ymm12[24],zero,zero,zero,zero,ymm12[27] -; AVX2-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,3,2,3] ; AVX2-NEXT: vpor %ymm5, %ymm6, %ymm5 +; AVX2-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,2,3] +; AVX2-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,3,2,3] ; AVX2-NEXT: vmovdqa {{.*#+}} ymm3 = [u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0] ; AVX2-NEXT: vpblendvb %ymm3, %ymm4, %ymm5, %ymm4 -; AVX2-NEXT: vpshufb {{.*#+}} ymm5 = ymm14[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm14[25],zero,ymm14[23],zero,zero,zero,zero,ymm14[26],zero,ymm14[24],zero,zero -; AVX2-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,3,2,3] +; AVX2-NEXT: vpshufb {{.*#+}} ymm5 = ymm8[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm8[25],zero,ymm8[23],zero,zero,zero,zero,ymm8[26],zero,ymm8[24],zero,zero ; AVX2-NEXT: vpshufb {{.*#+}} ymm6 = ymm13[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm13[25],zero,ymm13[23],zero,zero,zero,zero,ymm13[26],zero,ymm13[24],zero,zero,zero -; AVX2-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,3,2,3] ; AVX2-NEXT: vpor %ymm5, %ymm6, %ymm5 -; AVX2-NEXT: vpshufb {{.*#+}} ymm6 = ymm8[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] -; AVX2-NEXT: vmovdqa %ymm8, %ymm14 +; AVX2-NEXT: vpshufb {{.*#+}} ymm6 = ymm14[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] ; AVX2-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,3,2,3] +; AVX2-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,3,2,3] ; AVX2-NEXT: vmovdqa {{.*#+}} ymm7 = [0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u] ; AVX2-NEXT: vpblendvb %ymm7, %ymm5, %ymm6, %ymm5 ; AVX2-NEXT: vmovdqa {{.*#+}} ymm6 = [0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255] @@ -7725,10 +7624,11 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-NEXT: vpshufb %ymm7, %ymm4, %ymm8 ; AVX2-NEXT: vpor %ymm5, %ymm8, %ymm5 ; AVX2-NEXT: vmovdqa {{.*#+}} ymm8 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] -; AVX2-NEXT: vpshufb %ymm8, %ymm10, %ymm9 -; AVX2-NEXT: vmovdqa %ymm10, %ymm3 -; AVX2-NEXT: vmovdqa {{.*#+}} ymm10 = [128,128,0,128,14,128,128,128,128,1,128,15,128,128,128,128,128,128,16,128,30,128,128,128,128,17,128,31,128,128,128,128] -; AVX2-NEXT: vpshufb %ymm10, %ymm2, %ymm11 +; AVX2-NEXT: vpshufb %ymm8, %ymm2, %ymm9 +; AVX2-NEXT: vmovdqa %ymm2, %ymm3 +; AVX2-NEXT: vmovdqa {{.*#+}} ymm1 = [128,128,0,128,14,128,128,128,128,1,128,15,128,128,128,128,128,128,16,128,30,128,128,128,128,17,128,31,128,128,128,128] +; AVX2-NEXT: vpshufb %ymm1, %ymm10, %ymm11 +; AVX2-NEXT: vmovdqa %ymm10, %ymm2 ; AVX2-NEXT: vpor %ymm9, %ymm11, %ymm9 ; AVX2-NEXT: vmovdqa {{.*#+}} ymm11 = [u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255] ; AVX2-NEXT: vpblendvb %ymm11, %ymm5, %ymm9, %ymm5 @@ -7737,7 +7637,7 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-NEXT: vpshufb %ymm7, %ymm0, %ymm7 ; AVX2-NEXT: vpor %ymm6, %ymm7, %ymm6 ; AVX2-NEXT: vpshufb %ymm8, %ymm15, %ymm7 -; AVX2-NEXT: vpshufb %ymm10, %ymm12, %ymm8 +; AVX2-NEXT: vpshufb %ymm1, %ymm12, %ymm8 ; AVX2-NEXT: vpor %ymm7, %ymm8, %ymm7 ; AVX2-NEXT: vpblendvb %ymm11, %ymm6, %ymm7, %ymm6 ; AVX2-NEXT: vmovdqa {{.*#+}} ymm7 = [128,1,2,3,0,128,14,128,0,1,0,1,128,15,128,15,128,17,18,19,16,128,30,128,16,17,16,17,128,31,128,31] @@ -7820,7 +7720,7 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; ; AVX2-FP-LABEL: store_i8_stride7_vf64: ; AVX2-FP: # %bb.0: -; AVX2-FP-NEXT: subq $648, %rsp # imm = 0x288 +; AVX2-FP-NEXT: subq $616, %rsp # imm = 0x268 ; AVX2-FP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX2-FP-NEXT: vmovdqa 32(%rdi), %ymm1 ; AVX2-FP-NEXT: vmovdqa 32(%rsi), %ymm7 @@ -7832,20 +7732,18 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm1[23],zero,ymm1[27,20,21,26],zero,ymm1[24],zero,ymm1[26,27,26,27],zero,ymm1[25] ; AVX2-FP-NEXT: vmovdqa %ymm1, %ymm8 ; AVX2-FP-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm1 = ymm7[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm7[23],zero,zero,zero,zero,ymm7[26],zero,ymm7[24],zero,zero,zero,zero,ymm7[27],zero ; AVX2-FP-NEXT: vmovdqa %ymm7, %ymm9 ; AVX2-FP-NEXT: vmovdqu %ymm7, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-FP-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[25],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero,zero,zero ; AVX2-FP-NEXT: vmovdqa %ymm2, %ymm7 ; AVX2-FP-NEXT: vmovdqu %ymm2, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm2 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm6[25],zero,ymm6[23],zero,zero,zero,zero,ymm6[26],zero,ymm6[24],zero,zero,zero,zero,ymm6[27] ; AVX2-FP-NEXT: vmovdqu %ymm6, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] ; AVX2-FP-NEXT: vpor %ymm1, %ymm2, %ymm1 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm2 = [u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0] ; AVX2-FP-NEXT: vpblendvb %ymm2, %ymm0, %ymm1, %ymm0 ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm1 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25,22,23,22,23,24,25,26,27,24,25,30,31] @@ -7865,15 +7763,13 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FP-NEXT: vpblendvb %ymm2, %ymm0, %ymm1, %ymm0 ; AVX2-FP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm6[17,18,19,30],zero,ymm6[28],zero,ymm6[28,29,30,31],zero,ymm6[29],zero,ymm6[31] -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm1 = ymm7[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,zero,zero,ymm7[30],zero,ymm7[28],zero,zero,zero,zero,ymm7[31],zero,ymm7[29],zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-FP-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm1 = ymm9[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm9[30],zero,ymm9[28],zero,zero,zero,zero,ymm9[31],zero,ymm9[29],zero,zero,zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm2 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm8[30],zero,ymm8[28],zero,zero,zero,zero,ymm8[31],zero,ymm8[29],zero,zero,zero,zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] ; AVX2-FP-NEXT: vpor %ymm1, %ymm2, %ymm1 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm2 = [255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u] ; AVX2-FP-NEXT: vpblendvb %ymm2, %ymm0, %ymm1, %ymm0 ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm1 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,26,27,26,27,30,31,30,31,28,29,28,29,28,29,28,29] @@ -8052,184 +7948,167 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-FP-NEXT: vmovdqa (%rdx), %ymm1 ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm1[17,18,19,30],zero,ymm1[28],zero,ymm1[28,29,30,31],zero,ymm1[29],zero,ymm1[31] -; AVX2-FP-NEXT: vmovdqa %ymm1, %ymm4 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX2-FP-NEXT: vmovdqa (%rcx), %ymm2 -; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29],zero -; AVX2-FP-NEXT: vmovdqa %ymm2, %ymm10 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] +; AVX2-FP-NEXT: vmovdqa %ymm1, %ymm3 +; AVX2-FP-NEXT: vmovdqa (%rcx), %ymm5 +; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm1 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero,ymm5[29],zero ; AVX2-FP-NEXT: vpor %ymm0, %ymm1, %ymm2 -; AVX2-FP-NEXT: vmovdqa (%rsi), %ymm1 -; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm0 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29],zero,zero,zero -; AVX2-FP-NEXT: vmovdqa %ymm1, %ymm12 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm3 = ymm0[2,3,2,3] -; AVX2-FP-NEXT: vmovdqa (%rdi), %ymm5 -; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero,ymm5[29],zero,zero,zero,zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,3,2,3] -; AVX2-FP-NEXT: vpor %ymm3, %ymm6, %ymm3 -; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm0 = [255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u] -; AVX2-FP-NEXT: vpblendvb %ymm0, %ymm2, %ymm3, %ymm6 -; AVX2-FP-NEXT: vmovdqa (%r8), %ymm0 -; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm2 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[27],zero,ymm0[27,28,29,30],zero,ymm0[28],zero,ymm0[26,27,30,31],zero,ymm0[29] -; AVX2-FP-NEXT: vmovdqa %ymm0, %ymm1 -; AVX2-FP-NEXT: vmovdqu %ymm0, (%rsp) # 32-byte Spill +; AVX2-FP-NEXT: vmovdqa (%rsi), %ymm0 +; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm4 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm0[30],zero,ymm0[28],zero,zero,zero,zero,ymm0[31],zero,ymm0[29],zero,zero,zero +; AVX2-FP-NEXT: vmovdqa %ymm0, %ymm11 +; AVX2-FP-NEXT: vmovdqa (%rdi), %ymm13 +; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm13[30],zero,ymm13[28],zero,zero,zero,zero,ymm13[31],zero,ymm13[29],zero,zero,zero,zero +; AVX2-FP-NEXT: vpor %ymm4, %ymm6, %ymm4 ; AVX2-FP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] -; AVX2-FP-NEXT: vmovdqa (%r9), %ymm0 -; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm7 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm0[27],zero,zero,zero,zero,ymm0[30],zero,ymm0[28],zero,zero,zero,zero,ymm0[31],zero -; AVX2-FP-NEXT: vmovdqa %ymm0, %ymm3 -; AVX2-FP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,2,3] +; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm0 = [255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u] +; AVX2-FP-NEXT: vpblendvb %ymm0, %ymm2, %ymm4, %ymm6 +; AVX2-FP-NEXT: vmovdqa (%r8), %ymm14 +; AVX2-FP-NEXT: vmovdqa (%r9), %ymm1 +; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm2 = ymm14[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm14[27],zero,ymm14[27,28,29,30],zero,ymm14[28],zero,ymm14[26,27,30,31],zero,ymm14[29] +; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm7 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm1[27],zero,zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero +; AVX2-FP-NEXT: vmovdqu %ymm1, (%rsp) # 32-byte Spill ; AVX2-FP-NEXT: vpor %ymm2, %ymm7, %ymm7 ; AVX2-FP-NEXT: vmovdqa (%rax), %ymm0 ; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm8 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] -; AVX2-FP-NEXT: vmovdqa %ymm0, %ymm11 +; AVX2-FP-NEXT: vmovdqa %ymm0, %ymm10 ; AVX2-FP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-FP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm9 = [u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0] ; AVX2-FP-NEXT: vpblendvb %ymm9, %ymm7, %ymm8, %ymm7 ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm8 = [255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0] ; AVX2-FP-NEXT: vpblendvb %ymm8, %ymm6, %ymm7, %ymm0 ; AVX2-FP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm5[23],zero,ymm5[27,20,21,26],zero,ymm5[24],zero,ymm5[26,27,26,27],zero,ymm5[25] +; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm13[23],zero,ymm13[27,20,21,26],zero,ymm13[24],zero,ymm13[26,27,26,27],zero,ymm13[25] +; AVX2-FP-NEXT: vmovdqu %ymm13, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm8 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm11[23],zero,zero,zero,zero,ymm11[26],zero,ymm11[24],zero,zero,zero,zero,ymm11[27],zero +; AVX2-FP-NEXT: vmovdqa %ymm11, %ymm2 +; AVX2-FP-NEXT: vpor %ymm6, %ymm8, %ymm6 +; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm8 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm5[25],zero,ymm5[23],zero,zero,zero,zero,ymm5[26],zero,ymm5[24],zero,zero,zero,zero +; AVX2-FP-NEXT: vmovdqu %ymm3, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm9 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm3[25],zero,ymm3[23],zero,zero,zero,zero,ymm3[26],zero,ymm3[24],zero,zero,zero,zero,ymm3[27] +; AVX2-FP-NEXT: vpor %ymm8, %ymm9, %ymm8 ; AVX2-FP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,3,2,3] -; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm7 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm12[23],zero,zero,zero,zero,ymm12[26],zero,ymm12[24],zero,zero,zero,zero,ymm12[27],zero -; AVX2-FP-NEXT: vmovdqa %ymm12, %ymm14 -; AVX2-FP-NEXT: vmovdqu %ymm12, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] -; AVX2-FP-NEXT: vpor %ymm6, %ymm7, %ymm6 -; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm7 = ymm10[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm10[25],zero,ymm10[23],zero,zero,zero,zero,ymm10[26],zero,ymm10[24],zero,zero,zero,zero -; AVX2-FP-NEXT: vmovdqa %ymm10, %ymm13 -; AVX2-FP-NEXT: vmovdqu %ymm10, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] -; AVX2-FP-NEXT: vmovdqa %ymm4, %ymm2 -; AVX2-FP-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm8 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm4[25],zero,ymm4[23],zero,zero,zero,zero,ymm4[26],zero,ymm4[24],zero,zero,zero,zero,ymm4[27] ; AVX2-FP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] -; AVX2-FP-NEXT: vpor %ymm7, %ymm8, %ymm7 ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm0 = [u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0] -; AVX2-FP-NEXT: vpblendvb %ymm0, %ymm6, %ymm7, %ymm6 -; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm7 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm3[25],zero,ymm3[23],zero,zero,zero,zero,ymm3[26],zero,ymm3[24],zero,zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] -; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm8 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm1[25],zero,ymm1[23],zero,zero,zero,zero,ymm1[26],zero,ymm1[24],zero,zero,zero -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] -; AVX2-FP-NEXT: vpor %ymm7, %ymm8, %ymm7 -; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm8 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] +; AVX2-FP-NEXT: vpblendvb %ymm0, %ymm6, %ymm8, %ymm6 +; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm8 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm1[25],zero,ymm1[23],zero,zero,zero,zero,ymm1[26],zero,ymm1[24],zero,zero +; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm9 = ymm14[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm14[25],zero,ymm14[23],zero,zero,zero,zero,ymm14[26],zero,ymm14[24],zero,zero,zero +; AVX2-FP-NEXT: vmovdqu %ymm14, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX2-FP-NEXT: vpor %ymm8, %ymm9, %ymm8 +; AVX2-FP-NEXT: vpshufb {{.*#+}} ymm9 = ymm10[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,3,2,3] ; AVX2-FP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] -; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm9 = [0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u] -; AVX2-FP-NEXT: vpblendvb %ymm9, %ymm7, %ymm8, %ymm7 -; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm8 = [0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255] -; AVX2-FP-NEXT: vpblendvb %ymm8, %ymm6, %ymm7, %ymm0 +; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm10 = [0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u] +; AVX2-FP-NEXT: vpblendvb %ymm10, %ymm8, %ymm9, %ymm8 +; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm9 = [0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255] +; AVX2-FP-NEXT: vpblendvb %ymm9, %ymm6, %ymm8, %ymm0 ; AVX2-FP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FP-NEXT: vbroadcasti128 {{.*#+}} ymm8 = [128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20] -; AVX2-FP-NEXT: # ymm8 = mem[0,1,0,1] +; AVX2-FP-NEXT: vbroadcasti128 {{.*#+}} ymm9 = [128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20] +; AVX2-FP-NEXT: # ymm9 = mem[0,1,0,1] ; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX2-FP-NEXT: vpshufb %ymm8, %ymm0, %ymm7 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] -; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm9 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128] -; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm6 # 32-byte Reload -; AVX2-FP-NEXT: vpshufb %ymm9, %ymm6, %ymm10 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] -; AVX2-FP-NEXT: vpor %ymm7, %ymm10, %ymm7 -; AVX2-FP-NEXT: vbroadcasti128 {{.*#+}} ymm10 = [128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128] -; AVX2-FP-NEXT: # ymm10 = mem[0,1,0,1] -; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm4 # 32-byte Reload -; AVX2-FP-NEXT: vpshufb %ymm10, %ymm4, %ymm11 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] -; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm12 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128,128] +; AVX2-FP-NEXT: vpshufb %ymm9, %ymm0, %ymm8 +; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm10 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128] +; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload +; AVX2-FP-NEXT: vpshufb %ymm10, %ymm0, %ymm11 +; AVX2-FP-NEXT: vpor %ymm8, %ymm11, %ymm8 +; AVX2-FP-NEXT: vbroadcasti128 {{.*#+}} ymm11 = [128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128] +; AVX2-FP-NEXT: # ymm11 = mem[0,1,0,1] +; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm7 # 32-byte Reload +; AVX2-FP-NEXT: vpshufb %ymm11, %ymm7, %ymm12 +; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm0 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128,128] ; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm1 # 32-byte Reload -; AVX2-FP-NEXT: vpshufb %ymm12, %ymm1, %ymm15 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,3,2,3] -; AVX2-FP-NEXT: vpor %ymm11, %ymm15, %ymm11 -; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm15 = [255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u] -; AVX2-FP-NEXT: vpblendvb %ymm15, %ymm7, %ymm11, %ymm0 -; AVX2-FP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FP-NEXT: vpshufb %ymm8, %ymm13, %ymm8 +; AVX2-FP-NEXT: vpshufb %ymm0, %ymm1, %ymm15 +; AVX2-FP-NEXT: vpor %ymm12, %ymm15, %ymm12 ; AVX2-FP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] -; AVX2-FP-NEXT: vpshufb %ymm9, %ymm2, %ymm9 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,3,2,3] -; AVX2-FP-NEXT: vpor %ymm8, %ymm9, %ymm8 -; AVX2-FP-NEXT: vpshufb %ymm10, %ymm14, %ymm9 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] +; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm15 = [255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u] +; AVX2-FP-NEXT: vpblendvb %ymm15, %ymm8, %ymm12, %ymm4 +; AVX2-FP-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX2-FP-NEXT: vpshufb %ymm9, %ymm5, %ymm9 +; AVX2-FP-NEXT: vpshufb %ymm10, %ymm3, %ymm10 +; AVX2-FP-NEXT: vpor %ymm9, %ymm10, %ymm9 +; AVX2-FP-NEXT: vmovdqa %ymm2, %ymm3 +; AVX2-FP-NEXT: vpshufb %ymm11, %ymm2, %ymm10 +; AVX2-FP-NEXT: vpshufb %ymm0, %ymm13, %ymm11 +; AVX2-FP-NEXT: vpor %ymm10, %ymm11, %ymm10 ; AVX2-FP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,3,2,3] -; AVX2-FP-NEXT: vpshufb %ymm12, %ymm5, %ymm10 ; AVX2-FP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] -; AVX2-FP-NEXT: vpor %ymm9, %ymm10, %ymm9 -; AVX2-FP-NEXT: vpblendvb %ymm15, %ymm8, %ymm9, %ymm8 -; AVX2-FP-NEXT: vbroadcasti128 {{.*#+}} ymm9 = [128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22] -; AVX2-FP-NEXT: # ymm9 = mem[0,1,0,1] -; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm14 # 32-byte Reload -; AVX2-FP-NEXT: vpshufb %ymm9, %ymm14, %ymm10 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] -; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm11 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128] -; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm3 # 32-byte Reload -; AVX2-FP-NEXT: vpshufb %ymm11, %ymm3, %ymm12 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] -; AVX2-FP-NEXT: vpor %ymm10, %ymm12, %ymm10 -; AVX2-FP-NEXT: vbroadcasti128 {{.*#+}} ymm12 = [20,21,18,19,18,19,20,21,18,19,20,21,28,29,30,31,20,21,18,19,18,19,20,21,18,19,20,21,28,29,30,31] -; AVX2-FP-NEXT: # ymm12 = mem[0,1,0,1] -; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm13 # 32-byte Reload -; AVX2-FP-NEXT: vpshufb %ymm12, %ymm13, %ymm15 +; AVX2-FP-NEXT: vpblendvb %ymm15, %ymm9, %ymm10, %ymm9 +; AVX2-FP-NEXT: vbroadcasti128 {{.*#+}} ymm10 = [128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22] +; AVX2-FP-NEXT: # ymm10 = mem[0,1,0,1] +; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm8 # 32-byte Reload +; AVX2-FP-NEXT: vpshufb %ymm10, %ymm8, %ymm11 +; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm12 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128] +; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm4 # 32-byte Reload +; AVX2-FP-NEXT: vpshufb %ymm12, %ymm4, %ymm13 +; AVX2-FP-NEXT: vpor %ymm11, %ymm13, %ymm11 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] +; AVX2-FP-NEXT: vbroadcasti128 {{.*#+}} ymm13 = [20,21,18,19,18,19,20,21,18,19,20,21,28,29,30,31,20,21,18,19,18,19,20,21,18,19,20,21,28,29,30,31] +; AVX2-FP-NEXT: # ymm13 = mem[0,1,0,1] +; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm6 # 32-byte Reload +; AVX2-FP-NEXT: vpshufb %ymm13, %ymm6, %ymm15 ; AVX2-FP-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,2,3,2] ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm0 = [u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255] -; AVX2-FP-NEXT: vpblendvb %ymm0, %ymm10, %ymm15, %ymm10 -; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm15 # 32-byte Reload -; AVX2-FP-NEXT: vpshufb %ymm9, %ymm15, %ymm9 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,3,2,3] -; AVX2-FP-NEXT: vmovdqu (%rsp), %ymm2 # 32-byte Reload -; AVX2-FP-NEXT: vpshufb %ymm11, %ymm2, %ymm11 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] -; AVX2-FP-NEXT: vpor %ymm9, %ymm11, %ymm9 -; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm7 # 32-byte Reload -; AVX2-FP-NEXT: vpshufb %ymm12, %ymm7, %ymm11 -; AVX2-FP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,2,3,2] -; AVX2-FP-NEXT: vpblendvb %ymm0, %ymm9, %ymm11, %ymm0 -; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm9 = [255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0] -; AVX2-FP-NEXT: vpblendvb %ymm9, {{[-0-9]+}}(%r{{[sb]}}p), %ymm10, %ymm10 # 32-byte Folded Reload -; AVX2-FP-NEXT: vmovdqu %ymm10, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FP-NEXT: vpblendvb %ymm9, %ymm8, %ymm0, %ymm8 +; AVX2-FP-NEXT: vpblendvb %ymm0, %ymm11, %ymm15, %ymm11 +; AVX2-FP-NEXT: vmovdqu (%rsp), %ymm15 # 32-byte Reload +; AVX2-FP-NEXT: vpshufb %ymm10, %ymm15, %ymm10 +; AVX2-FP-NEXT: vpshufb %ymm12, %ymm14, %ymm12 +; AVX2-FP-NEXT: vpor %ymm10, %ymm12, %ymm10 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] +; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload +; AVX2-FP-NEXT: vpshufb %ymm13, %ymm2, %ymm12 +; AVX2-FP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,2,3,2] +; AVX2-FP-NEXT: vpblendvb %ymm0, %ymm10, %ymm12, %ymm0 +; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm10 = [255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0] +; AVX2-FP-NEXT: vpblendvb %ymm10, {{[-0-9]+}}(%r{{[sb]}}p), %ymm11, %ymm11 # 32-byte Folded Reload +; AVX2-FP-NEXT: vmovdqu %ymm11, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX2-FP-NEXT: vpblendvb %ymm10, %ymm9, %ymm0, %ymm9 ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm0 = [128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128,128,18] -; AVX2-FP-NEXT: vpshufb %ymm0, %ymm4, %ymm9 -; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm10 = [0,128,14,128,128,128,128,1,128,15,128,128,128,128,2,128,16,128,30,128,128,128,128,17,128,31,128,128,128,128,18,128] -; AVX2-FP-NEXT: vpshufb %ymm10, %ymm1, %ymm11 -; AVX2-FP-NEXT: vpor %ymm9, %ymm11, %ymm9 -; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm11 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] -; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm1 # 32-byte Reload +; AVX2-FP-NEXT: vpshufb %ymm0, %ymm7, %ymm10 +; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm11 = [0,128,14,128,128,128,128,1,128,15,128,128,128,128,2,128,16,128,30,128,128,128,128,17,128,31,128,128,128,128,18,128] ; AVX2-FP-NEXT: vpshufb %ymm11, %ymm1, %ymm12 -; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm4 = [128,128,0,128,14,128,128,128,128,1,128,15,128,128,128,128,128,128,16,128,30,128,128,128,128,17,128,31,128,128,128,128] -; AVX2-FP-NEXT: vpshufb %ymm4, %ymm6, %ymm6 -; AVX2-FP-NEXT: vpor %ymm6, %ymm12, %ymm6 -; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm12 = [u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255] -; AVX2-FP-NEXT: vpblendvb %ymm12, %ymm9, %ymm6, %ymm9 +; AVX2-FP-NEXT: vpor %ymm10, %ymm12, %ymm10 +; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm12 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] ; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm1 # 32-byte Reload -; AVX2-FP-NEXT: vpshufb %ymm0, %ymm1, %ymm0 -; AVX2-FP-NEXT: vpshufb %ymm10, %ymm5, %ymm1 -; AVX2-FP-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX2-FP-NEXT: vpshufb %ymm12, %ymm1, %ymm13 +; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm14 = [128,128,0,128,14,128,128,128,128,1,128,15,128,128,128,128,128,128,16,128,30,128,128,128,128,17,128,31,128,128,128,128] +; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm1 # 32-byte Reload +; AVX2-FP-NEXT: vpshufb %ymm14, %ymm1, %ymm7 +; AVX2-FP-NEXT: vpor %ymm7, %ymm13, %ymm7 +; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm13 = [u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255] +; AVX2-FP-NEXT: vpblendvb %ymm13, %ymm10, %ymm7, %ymm10 +; AVX2-FP-NEXT: vpshufb %ymm0, %ymm3, %ymm0 ; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm1 # 32-byte Reload ; AVX2-FP-NEXT: vpshufb %ymm11, %ymm1, %ymm1 -; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm5 # 32-byte Reload -; AVX2-FP-NEXT: vpshufb %ymm4, %ymm5, %ymm4 -; AVX2-FP-NEXT: vpor %ymm1, %ymm4, %ymm1 -; AVX2-FP-NEXT: vpblendvb %ymm12, %ymm0, %ymm1, %ymm0 +; AVX2-FP-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX2-FP-NEXT: vpshufb %ymm12, %ymm5, %ymm1 +; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm3 # 32-byte Reload +; AVX2-FP-NEXT: vpshufb %ymm14, %ymm3, %ymm3 +; AVX2-FP-NEXT: vpor %ymm1, %ymm3, %ymm1 +; AVX2-FP-NEXT: vpblendvb %ymm13, %ymm0, %ymm1, %ymm0 ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm1 = [128,1,2,3,0,128,14,128,0,1,0,1,128,15,128,15,128,17,18,19,16,128,30,128,16,17,16,17,128,31,128,31] -; AVX2-FP-NEXT: vpshufb %ymm1, %ymm3, %ymm4 +; AVX2-FP-NEXT: vpshufb %ymm1, %ymm4, %ymm3 ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm5 = [13,128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128] -; AVX2-FP-NEXT: vpshufb %ymm5, %ymm14, %ymm6 -; AVX2-FP-NEXT: vpor %ymm4, %ymm6, %ymm4 -; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm6 = [12,13,2,3,12,13,0,1,14,15,2,3,0,1,14,15,28,29,18,19,28,29,16,17,30,31,18,19,16,17,30,31] -; AVX2-FP-NEXT: vpshufb %ymm6, %ymm13, %ymm10 -; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm11 = [255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u] -; AVX2-FP-NEXT: vpblendvb %ymm11, %ymm4, %ymm10, %ymm4 -; AVX2-FP-NEXT: vpshufb %ymm1, %ymm2, %ymm1 -; AVX2-FP-NEXT: vpshufb %ymm5, %ymm15, %ymm3 -; AVX2-FP-NEXT: vpor %ymm1, %ymm3, %ymm1 -; AVX2-FP-NEXT: vpshufb %ymm6, %ymm7, %ymm2 -; AVX2-FP-NEXT: vpblendvb %ymm11, %ymm1, %ymm2, %ymm1 +; AVX2-FP-NEXT: vpshufb %ymm5, %ymm8, %ymm7 +; AVX2-FP-NEXT: vpor %ymm3, %ymm7, %ymm3 +; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm7 = [12,13,2,3,12,13,0,1,14,15,2,3,0,1,14,15,28,29,18,19,28,29,16,17,30,31,18,19,16,17,30,31] +; AVX2-FP-NEXT: vpshufb %ymm7, %ymm6, %ymm11 +; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm12 = [255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u] +; AVX2-FP-NEXT: vpblendvb %ymm12, %ymm3, %ymm11, %ymm3 +; AVX2-FP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm4 # 32-byte Reload +; AVX2-FP-NEXT: vpshufb %ymm1, %ymm4, %ymm1 +; AVX2-FP-NEXT: vpshufb %ymm5, %ymm15, %ymm4 +; AVX2-FP-NEXT: vpor %ymm1, %ymm4, %ymm1 +; AVX2-FP-NEXT: vpshufb %ymm7, %ymm2, %ymm2 +; AVX2-FP-NEXT: vpblendvb %ymm12, %ymm1, %ymm2, %ymm1 ; AVX2-FP-NEXT: vmovdqa {{.*#+}} ymm2 = [0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255] -; AVX2-FP-NEXT: vpblendvb %ymm2, %ymm9, %ymm4, %ymm3 +; AVX2-FP-NEXT: vpblendvb %ymm2, %ymm10, %ymm3, %ymm3 ; AVX2-FP-NEXT: vpblendvb %ymm2, %ymm0, %ymm1, %ymm0 ; AVX2-FP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX2-FP-NEXT: vmovdqa %ymm0, 96(%rax) ; AVX2-FP-NEXT: vmovdqa %ymm3, 320(%rax) -; AVX2-FP-NEXT: vmovdqa %ymm8, 128(%rax) +; AVX2-FP-NEXT: vmovdqa %ymm9, 128(%rax) ; AVX2-FP-NEXT: vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload ; AVX2-FP-NEXT: vmovaps %ymm0, 352(%rax) ; AVX2-FP-NEXT: vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload @@ -8252,13 +8131,13 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FP-NEXT: vmovaps %ymm0, 416(%rax) ; AVX2-FP-NEXT: vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload ; AVX2-FP-NEXT: vmovaps %ymm0, 384(%rax) -; AVX2-FP-NEXT: addq $648, %rsp # imm = 0x288 +; AVX2-FP-NEXT: addq $616, %rsp # imm = 0x268 ; AVX2-FP-NEXT: vzeroupper ; AVX2-FP-NEXT: retq ; ; AVX2-FCP-LABEL: store_i8_stride7_vf64: ; AVX2-FCP: # %bb.0: -; AVX2-FCP-NEXT: subq $648, %rsp # imm = 0x288 +; AVX2-FCP-NEXT: subq $616, %rsp # imm = 0x268 ; AVX2-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX2-FCP-NEXT: vmovdqa 32(%rdi), %ymm1 ; AVX2-FCP-NEXT: vmovdqa 32(%rsi), %ymm7 @@ -8270,20 +8149,18 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm1[23],zero,ymm1[27,20,21,26],zero,ymm1[24],zero,ymm1[26,27,26,27],zero,ymm1[25] ; AVX2-FCP-NEXT: vmovdqa %ymm1, %ymm8 ; AVX2-FCP-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm7[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm7[23],zero,zero,zero,zero,ymm7[26],zero,ymm7[24],zero,zero,zero,zero,ymm7[27],zero ; AVX2-FCP-NEXT: vmovdqa %ymm7, %ymm9 ; AVX2-FCP-NEXT: vmovdqu %ymm7, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[25],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero,zero,zero ; AVX2-FCP-NEXT: vmovdqa %ymm2, %ymm7 ; AVX2-FCP-NEXT: vmovdqu %ymm2, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm2 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm6[25],zero,ymm6[23],zero,zero,zero,zero,ymm6[26],zero,ymm6[24],zero,zero,zero,zero,ymm6[27] ; AVX2-FCP-NEXT: vmovdqu %ymm6, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] ; AVX2-FCP-NEXT: vpor %ymm1, %ymm2, %ymm1 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm2 = [u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0] ; AVX2-FCP-NEXT: vpblendvb %ymm2, %ymm0, %ymm1, %ymm0 ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25,22,23,22,23,24,25,26,27,24,25,30,31] @@ -8303,15 +8180,13 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FCP-NEXT: vpblendvb %ymm2, %ymm0, %ymm1, %ymm0 ; AVX2-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm6[17,18,19,30],zero,ymm6[28],zero,ymm6[28,29,30,31],zero,ymm6[29],zero,ymm6[31] -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm7[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,zero,zero,ymm7[30],zero,ymm7[28],zero,zero,zero,zero,ymm7[31],zero,ymm7[29],zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm9[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm9[30],zero,ymm9[28],zero,zero,zero,zero,ymm9[31],zero,ymm9[29],zero,zero,zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm2 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm8[30],zero,ymm8[28],zero,zero,zero,zero,ymm8[31],zero,ymm8[29],zero,zero,zero,zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] ; AVX2-FCP-NEXT: vpor %ymm1, %ymm2, %ymm1 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm2 = [255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u] ; AVX2-FCP-NEXT: vpblendvb %ymm2, %ymm0, %ymm1, %ymm0 ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,26,27,26,27,30,31,30,31,28,29,28,29,28,29,28,29] @@ -8332,7 +8207,7 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FCP-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill ; AVX2-FCP-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] ; AVX2-FCP-NEXT: vmovdqa %xmm1, %xmm14 -; AVX2-FCP-NEXT: vmovdqa %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX2-FCP-NEXT: vmovdqa %xmm1, (%rsp) # 16-byte Spill ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} xmm1 = [0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] ; AVX2-FCP-NEXT: vpshufb %xmm1, %xmm0, %xmm0 ; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,1,0,1] @@ -8349,7 +8224,7 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FCP-NEXT: vmovdqa (%rdi), %xmm12 ; AVX2-FCP-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm12[0],xmm11[0],xmm12[1],xmm11[1],xmm12[2],xmm11[2],xmm12[3],xmm11[3],xmm12[4],xmm11[4],xmm12[5],xmm11[5],xmm12[6],xmm11[6],xmm12[7],xmm11[7] ; AVX2-FCP-NEXT: vmovdqa %xmm12, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX2-FCP-NEXT: vmovdqa %xmm11, (%rsp) # 16-byte Spill +; AVX2-FCP-NEXT: vmovdqa %xmm11, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill ; AVX2-FCP-NEXT: vpshufb %xmm1, %xmm0, %xmm0 ; AVX2-FCP-NEXT: vmovdqa (%rcx), %xmm2 ; AVX2-FCP-NEXT: vmovdqa %xmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill @@ -8445,7 +8320,7 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FCP-NEXT: vpblendvb %ymm2, %ymm1, %ymm0, %ymm0 ; AVX2-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-FCP-NEXT: vpunpckhbw {{.*#+}} xmm0 = xmm10[8],xmm7[8],xmm10[9],xmm7[9],xmm10[10],xmm7[10],xmm10[11],xmm7[11],xmm10[12],xmm7[12],xmm10[13],xmm7[13],xmm10[14],xmm7[14],xmm10[15],xmm7[15] -; AVX2-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload +; AVX2-FCP-NEXT: vmovdqa (%rsp), %xmm1 # 16-byte Reload ; AVX2-FCP-NEXT: vpunpckhbw {{[-0-9]+}}(%r{{[sb]}}p), %xmm1, %xmm1 # 16-byte Folded Reload ; AVX2-FCP-NEXT: # xmm1 = xmm1[8],mem[8],xmm1[9],mem[9],xmm1[10],mem[10],xmm1[11],mem[11],xmm1[12],mem[12],xmm1[13],mem[13],xmm1[14],mem[14],xmm1[15],mem[15] ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} xmm2 = [6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] @@ -8458,7 +8333,7 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FCP-NEXT: vpblendvb %ymm6, %ymm0, %ymm1, %ymm0 ; AVX2-FCP-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm5[8],xmm4[8],xmm5[9],xmm4[9],xmm5[10],xmm4[10],xmm5[11],xmm4[11],xmm5[12],xmm4[12],xmm5[13],xmm4[13],xmm5[14],xmm4[14],xmm5[15],xmm4[15] ; AVX2-FCP-NEXT: vpshufb %xmm2, %xmm1, %xmm1 -; AVX2-FCP-NEXT: vmovdqa (%rsp), %xmm2 # 16-byte Reload +; AVX2-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm2 # 16-byte Reload ; AVX2-FCP-NEXT: vpunpckhbw {{[-0-9]+}}(%r{{[sb]}}p), %xmm2, %xmm2 # 16-byte Folded Reload ; AVX2-FCP-NEXT: # xmm2 = xmm2[8],mem[8],xmm2[9],mem[9],xmm2[10],mem[10],xmm2[11],mem[11],xmm2[12],mem[12],xmm2[13],mem[13],xmm2[14],mem[14],xmm2[15],mem[15] ; AVX2-FCP-NEXT: vpshufb %xmm3, %xmm2, %xmm2 @@ -8488,186 +8363,167 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-FCP-NEXT: vmovdqa (%rdx), %ymm1 ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm1[17,18,19,30],zero,ymm1[28],zero,ymm1[28,29,30,31],zero,ymm1[29],zero,ymm1[31] -; AVX2-FCP-NEXT: vmovdqa %ymm1, %ymm4 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX2-FCP-NEXT: vmovdqa (%rcx), %ymm2 -; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29],zero -; AVX2-FCP-NEXT: vmovdqa %ymm2, %ymm10 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] +; AVX2-FCP-NEXT: vmovdqa %ymm1, %ymm3 +; AVX2-FCP-NEXT: vmovdqa (%rcx), %ymm5 +; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero,ymm5[29],zero ; AVX2-FCP-NEXT: vpor %ymm0, %ymm1, %ymm2 -; AVX2-FCP-NEXT: vmovdqa (%rsi), %ymm5 -; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero,ymm5[29],zero,zero,zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm3 = ymm0[2,3,2,3] -; AVX2-FCP-NEXT: vmovdqa (%rdi), %ymm0 -; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm0[30],zero,ymm0[28],zero,zero,zero,zero,ymm0[31],zero,ymm0[29],zero,zero,zero,zero -; AVX2-FCP-NEXT: vmovdqa %ymm0, %ymm12 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,3,2,3] -; AVX2-FCP-NEXT: vpor %ymm3, %ymm6, %ymm3 -; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm0 = [255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u] -; AVX2-FCP-NEXT: vpblendvb %ymm0, %ymm2, %ymm3, %ymm6 -; AVX2-FCP-NEXT: vmovdqa (%r8), %ymm0 -; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[27],zero,ymm0[27,28,29,30],zero,ymm0[28],zero,ymm0[26,27,30,31],zero,ymm0[29] -; AVX2-FCP-NEXT: vmovdqa %ymm0, %ymm1 -; AVX2-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX2-FCP-NEXT: vmovdqa (%rsi), %ymm0 +; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm0[30],zero,ymm0[28],zero,zero,zero,zero,ymm0[31],zero,ymm0[29],zero,zero,zero +; AVX2-FCP-NEXT: vmovdqa %ymm0, %ymm11 +; AVX2-FCP-NEXT: vmovdqa (%rdi), %ymm13 +; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm13[30],zero,ymm13[28],zero,zero,zero,zero,ymm13[31],zero,ymm13[29],zero,zero,zero,zero +; AVX2-FCP-NEXT: vpor %ymm4, %ymm6, %ymm4 ; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] -; AVX2-FCP-NEXT: vmovdqa (%r9), %ymm0 -; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm0[27],zero,zero,zero,zero,ymm0[30],zero,ymm0[28],zero,zero,zero,zero,ymm0[31],zero -; AVX2-FCP-NEXT: vmovdqa %ymm0, %ymm3 -; AVX2-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,2,3] +; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm0 = [255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u] +; AVX2-FCP-NEXT: vpblendvb %ymm0, %ymm2, %ymm4, %ymm6 +; AVX2-FCP-NEXT: vmovdqa (%r8), %ymm14 +; AVX2-FCP-NEXT: vmovdqa (%r9), %ymm1 +; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm14[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm14[27],zero,ymm14[27,28,29,30],zero,ymm14[28],zero,ymm14[26,27,30,31],zero,ymm14[29] +; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm1[27],zero,zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero +; AVX2-FCP-NEXT: vmovdqu %ymm1, (%rsp) # 32-byte Spill ; AVX2-FCP-NEXT: vpor %ymm2, %ymm7, %ymm7 ; AVX2-FCP-NEXT: vmovdqa (%rax), %ymm0 ; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] -; AVX2-FCP-NEXT: vmovdqa %ymm0, %ymm11 -; AVX2-FCP-NEXT: vmovdqu %ymm0, (%rsp) # 32-byte Spill +; AVX2-FCP-NEXT: vmovdqa %ymm0, %ymm10 +; AVX2-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm9 = [u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0] ; AVX2-FCP-NEXT: vpblendvb %ymm9, %ymm7, %ymm8, %ymm7 ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm8 = [255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0] ; AVX2-FCP-NEXT: vpblendvb %ymm8, %ymm6, %ymm7, %ymm0 ; AVX2-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm12[23],zero,ymm12[27,20,21,26],zero,ymm12[24],zero,ymm12[26,27,26,27],zero,ymm12[25] -; AVX2-FCP-NEXT: vmovdqa %ymm12, %ymm13 -; AVX2-FCP-NEXT: vmovdqu %ymm12, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm13[23],zero,ymm13[27,20,21,26],zero,ymm13[24],zero,ymm13[26,27,26,27],zero,ymm13[25] +; AVX2-FCP-NEXT: vmovdqu %ymm13, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm11[23],zero,zero,zero,zero,ymm11[26],zero,ymm11[24],zero,zero,zero,zero,ymm11[27],zero +; AVX2-FCP-NEXT: vmovdqa %ymm11, %ymm2 +; AVX2-FCP-NEXT: vpor %ymm6, %ymm8, %ymm6 +; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm5[25],zero,ymm5[23],zero,zero,zero,zero,ymm5[26],zero,ymm5[24],zero,zero,zero,zero +; AVX2-FCP-NEXT: vmovdqu %ymm3, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm9 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm3[25],zero,ymm3[23],zero,zero,zero,zero,ymm3[26],zero,ymm3[24],zero,zero,zero,zero,ymm3[27] +; AVX2-FCP-NEXT: vpor %ymm8, %ymm9, %ymm8 ; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,3,2,3] -; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm5[23],zero,zero,zero,zero,ymm5[26],zero,ymm5[24],zero,zero,zero,zero,ymm5[27],zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] -; AVX2-FCP-NEXT: vpor %ymm6, %ymm7, %ymm6 -; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm10[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm10[25],zero,ymm10[23],zero,zero,zero,zero,ymm10[26],zero,ymm10[24],zero,zero,zero,zero -; AVX2-FCP-NEXT: vmovdqa %ymm10, %ymm14 -; AVX2-FCP-NEXT: vmovdqu %ymm10, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] -; AVX2-FCP-NEXT: vmovdqa %ymm4, %ymm2 -; AVX2-FCP-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm8 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm4[25],zero,ymm4[23],zero,zero,zero,zero,ymm4[26],zero,ymm4[24],zero,zero,zero,zero,ymm4[27] ; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] -; AVX2-FCP-NEXT: vpor %ymm7, %ymm8, %ymm7 ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm0 = [u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0] -; AVX2-FCP-NEXT: vpblendvb %ymm0, %ymm6, %ymm7, %ymm6 -; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm3[25],zero,ymm3[23],zero,zero,zero,zero,ymm3[26],zero,ymm3[24],zero,zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] -; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm1[25],zero,ymm1[23],zero,zero,zero,zero,ymm1[26],zero,ymm1[24],zero,zero,zero -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] -; AVX2-FCP-NEXT: vpor %ymm7, %ymm8, %ymm7 -; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] +; AVX2-FCP-NEXT: vpblendvb %ymm0, %ymm6, %ymm8, %ymm6 +; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm1[25],zero,ymm1[23],zero,zero,zero,zero,ymm1[26],zero,ymm1[24],zero,zero +; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm14[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm14[25],zero,ymm14[23],zero,zero,zero,zero,ymm14[26],zero,ymm14[24],zero,zero,zero +; AVX2-FCP-NEXT: vmovdqu %ymm14, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX2-FCP-NEXT: vpor %ymm8, %ymm9, %ymm8 +; AVX2-FCP-NEXT: vpshufb {{.*#+}} ymm9 = ymm10[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,3,2,3] ; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] -; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm9 = [0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u] -; AVX2-FCP-NEXT: vpblendvb %ymm9, %ymm7, %ymm8, %ymm7 -; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm8 = [0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255] -; AVX2-FCP-NEXT: vpblendvb %ymm8, %ymm6, %ymm7, %ymm0 +; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm10 = [0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u] +; AVX2-FCP-NEXT: vpblendvb %ymm10, %ymm8, %ymm9, %ymm8 +; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm9 = [0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255] +; AVX2-FCP-NEXT: vpblendvb %ymm9, %ymm6, %ymm8, %ymm0 ; AVX2-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm8 = [128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20] -; AVX2-FCP-NEXT: # ymm8 = mem[0,1,0,1] +; AVX2-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm9 = [128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20] +; AVX2-FCP-NEXT: # ymm9 = mem[0,1,0,1] ; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX2-FCP-NEXT: vpshufb %ymm8, %ymm0, %ymm7 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[2,3,2,3] -; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm9 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128] -; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm6 # 32-byte Reload -; AVX2-FCP-NEXT: vpshufb %ymm9, %ymm6, %ymm10 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] -; AVX2-FCP-NEXT: vpor %ymm7, %ymm10, %ymm7 -; AVX2-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm10 = [128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128] -; AVX2-FCP-NEXT: # ymm10 = mem[0,1,0,1] -; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm4 # 32-byte Reload -; AVX2-FCP-NEXT: vpshufb %ymm10, %ymm4, %ymm11 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] -; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm12 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128,128] +; AVX2-FCP-NEXT: vpshufb %ymm9, %ymm0, %ymm8 +; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm10 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128] +; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload +; AVX2-FCP-NEXT: vpshufb %ymm10, %ymm0, %ymm11 +; AVX2-FCP-NEXT: vpor %ymm8, %ymm11, %ymm8 +; AVX2-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm11 = [128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128] +; AVX2-FCP-NEXT: # ymm11 = mem[0,1,0,1] +; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm7 # 32-byte Reload +; AVX2-FCP-NEXT: vpshufb %ymm11, %ymm7, %ymm12 +; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm0 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128,128] ; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm1 # 32-byte Reload -; AVX2-FCP-NEXT: vpshufb %ymm12, %ymm1, %ymm15 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,3,2,3] -; AVX2-FCP-NEXT: vpor %ymm11, %ymm15, %ymm11 -; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm15 = [255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u] -; AVX2-FCP-NEXT: vpblendvb %ymm15, %ymm7, %ymm11, %ymm0 -; AVX2-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FCP-NEXT: vpshufb %ymm8, %ymm14, %ymm8 +; AVX2-FCP-NEXT: vpshufb %ymm0, %ymm1, %ymm15 +; AVX2-FCP-NEXT: vpor %ymm12, %ymm15, %ymm12 ; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] -; AVX2-FCP-NEXT: vpshufb %ymm9, %ymm2, %ymm9 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,3,2,3] -; AVX2-FCP-NEXT: vpor %ymm8, %ymm9, %ymm8 -; AVX2-FCP-NEXT: vpshufb %ymm10, %ymm5, %ymm9 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,3,2,3] -; AVX2-FCP-NEXT: vpshufb %ymm12, %ymm13, %ymm10 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] -; AVX2-FCP-NEXT: vpor %ymm9, %ymm10, %ymm9 -; AVX2-FCP-NEXT: vpblendvb %ymm15, %ymm8, %ymm9, %ymm8 -; AVX2-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm9 = [128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22] -; AVX2-FCP-NEXT: # ymm9 = mem[0,1,0,1] -; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm14 # 32-byte Reload -; AVX2-FCP-NEXT: vpshufb %ymm9, %ymm14, %ymm10 -; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] -; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm11 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128] -; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm3 # 32-byte Reload -; AVX2-FCP-NEXT: vpshufb %ymm11, %ymm3, %ymm12 ; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] -; AVX2-FCP-NEXT: vpor %ymm10, %ymm12, %ymm10 -; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm13 # 32-byte Reload -; AVX2-FCP-NEXT: vpshuflw {{.*#+}} ymm12 = ymm13[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] -; AVX2-FCP-NEXT: vpmovsxbd {{.*#+}} ymm15 = [4,5,4,5,5,7,4,5] -; AVX2-FCP-NEXT: vpermd %ymm12, %ymm15, %ymm12 -; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm0 = [u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255] -; AVX2-FCP-NEXT: vpblendvb %ymm0, %ymm10, %ymm12, %ymm10 -; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload -; AVX2-FCP-NEXT: vpshufb %ymm9, %ymm2, %ymm9 +; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm15 = [255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u,u,0,0,255,255,u,u] +; AVX2-FCP-NEXT: vpblendvb %ymm15, %ymm8, %ymm12, %ymm4 +; AVX2-FCP-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX2-FCP-NEXT: vpshufb %ymm9, %ymm5, %ymm9 +; AVX2-FCP-NEXT: vpshufb %ymm10, %ymm3, %ymm10 +; AVX2-FCP-NEXT: vpor %ymm9, %ymm10, %ymm9 +; AVX2-FCP-NEXT: vmovdqa %ymm2, %ymm3 +; AVX2-FCP-NEXT: vpshufb %ymm11, %ymm2, %ymm10 +; AVX2-FCP-NEXT: vpshufb %ymm0, %ymm13, %ymm11 +; AVX2-FCP-NEXT: vpor %ymm10, %ymm11, %ymm10 ; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,3,2,3] +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] +; AVX2-FCP-NEXT: vpblendvb %ymm15, %ymm9, %ymm10, %ymm9 +; AVX2-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm10 = [128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22] +; AVX2-FCP-NEXT: # ymm10 = mem[0,1,0,1] +; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm8 # 32-byte Reload +; AVX2-FCP-NEXT: vpshufb %ymm10, %ymm8, %ymm11 +; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm12 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128] ; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload -; AVX2-FCP-NEXT: vpshufb %ymm11, %ymm2, %ymm11 +; AVX2-FCP-NEXT: vpshufb %ymm12, %ymm2, %ymm13 +; AVX2-FCP-NEXT: vpor %ymm11, %ymm13, %ymm11 ; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] -; AVX2-FCP-NEXT: vpor %ymm9, %ymm11, %ymm9 -; AVX2-FCP-NEXT: vmovdqu (%rsp), %ymm7 # 32-byte Reload -; AVX2-FCP-NEXT: vpshuflw {{.*#+}} ymm11 = ymm7[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] -; AVX2-FCP-NEXT: vpermd %ymm11, %ymm15, %ymm11 -; AVX2-FCP-NEXT: vpblendvb %ymm0, %ymm9, %ymm11, %ymm0 -; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm9 = [255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0] -; AVX2-FCP-NEXT: vpblendvb %ymm9, {{[-0-9]+}}(%r{{[sb]}}p), %ymm10, %ymm10 # 32-byte Folded Reload -; AVX2-FCP-NEXT: vmovdqu %ymm10, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX2-FCP-NEXT: vpblendvb %ymm9, %ymm8, %ymm0, %ymm8 +; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm6 # 32-byte Reload +; AVX2-FCP-NEXT: vpshuflw {{.*#+}} ymm13 = ymm6[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] +; AVX2-FCP-NEXT: vpmovsxbd {{.*#+}} ymm15 = [4,5,4,5,5,7,4,5] +; AVX2-FCP-NEXT: vpermd %ymm13, %ymm15, %ymm13 +; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm0 = [u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255] +; AVX2-FCP-NEXT: vpblendvb %ymm0, %ymm11, %ymm13, %ymm11 +; AVX2-FCP-NEXT: vmovdqu (%rsp), %ymm4 # 32-byte Reload +; AVX2-FCP-NEXT: vpshufb %ymm10, %ymm4, %ymm10 +; AVX2-FCP-NEXT: vpshufb %ymm12, %ymm14, %ymm12 +; AVX2-FCP-NEXT: vpor %ymm10, %ymm12, %ymm10 +; AVX2-FCP-NEXT: vpshuflw $150, {{[-0-9]+}}(%r{{[sb]}}p), %ymm12 # 32-byte Folded Reload +; AVX2-FCP-NEXT: # ymm12 = mem[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] +; AVX2-FCP-NEXT: vpermd %ymm12, %ymm15, %ymm12 +; AVX2-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] +; AVX2-FCP-NEXT: vpblendvb %ymm0, %ymm10, %ymm12, %ymm0 +; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm10 = [255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0] +; AVX2-FCP-NEXT: vpblendvb %ymm10, {{[-0-9]+}}(%r{{[sb]}}p), %ymm11, %ymm14 # 32-byte Folded Reload +; AVX2-FCP-NEXT: vpblendvb %ymm10, %ymm9, %ymm0, %ymm9 ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm0 = [128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128,128,18] -; AVX2-FCP-NEXT: vpshufb %ymm0, %ymm4, %ymm9 -; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm10 = [0,128,14,128,128,128,128,1,128,15,128,128,128,128,2,128,16,128,30,128,128,128,128,17,128,31,128,128,128,128,18,128] -; AVX2-FCP-NEXT: vpshufb %ymm10, %ymm1, %ymm11 -; AVX2-FCP-NEXT: vpor %ymm9, %ymm11, %ymm9 -; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm11 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] -; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm1 # 32-byte Reload +; AVX2-FCP-NEXT: vpshufb %ymm0, %ymm7, %ymm10 +; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm11 = [0,128,14,128,128,128,128,1,128,15,128,128,128,128,2,128,16,128,30,128,128,128,128,17,128,31,128,128,128,128,18,128] ; AVX2-FCP-NEXT: vpshufb %ymm11, %ymm1, %ymm12 +; AVX2-FCP-NEXT: vpor %ymm10, %ymm12, %ymm10 +; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm12 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] +; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm1 # 32-byte Reload +; AVX2-FCP-NEXT: vpshufb %ymm12, %ymm1, %ymm13 ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm15 = [128,128,0,128,14,128,128,128,128,1,128,15,128,128,128,128,128,128,16,128,30,128,128,128,128,17,128,31,128,128,128,128] -; AVX2-FCP-NEXT: vpshufb %ymm15, %ymm6, %ymm6 -; AVX2-FCP-NEXT: vpor %ymm6, %ymm12, %ymm6 -; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm12 = [u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255] -; AVX2-FCP-NEXT: vpblendvb %ymm12, %ymm9, %ymm6, %ymm9 -; AVX2-FCP-NEXT: vpshufb %ymm0, %ymm5, %ymm0 ; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm1 # 32-byte Reload -; AVX2-FCP-NEXT: vpshufb %ymm10, %ymm1, %ymm1 -; AVX2-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX2-FCP-NEXT: vpshufb %ymm15, %ymm1, %ymm7 +; AVX2-FCP-NEXT: vpor %ymm7, %ymm13, %ymm7 +; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm13 = [u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255,0,0,u,u,u,255,255] +; AVX2-FCP-NEXT: vpblendvb %ymm13, %ymm10, %ymm7, %ymm10 +; AVX2-FCP-NEXT: vpshufb %ymm0, %ymm3, %ymm0 ; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm1 # 32-byte Reload ; AVX2-FCP-NEXT: vpshufb %ymm11, %ymm1, %ymm1 -; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm4 # 32-byte Reload -; AVX2-FCP-NEXT: vpshufb %ymm15, %ymm4, %ymm4 -; AVX2-FCP-NEXT: vpor %ymm1, %ymm4, %ymm1 -; AVX2-FCP-NEXT: vpblendvb %ymm12, %ymm0, %ymm1, %ymm0 +; AVX2-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX2-FCP-NEXT: vpshufb %ymm12, %ymm5, %ymm1 +; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm3 # 32-byte Reload +; AVX2-FCP-NEXT: vpshufb %ymm15, %ymm3, %ymm3 +; AVX2-FCP-NEXT: vpor %ymm1, %ymm3, %ymm1 +; AVX2-FCP-NEXT: vpblendvb %ymm13, %ymm0, %ymm1, %ymm0 ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm1 = [128,1,2,3,0,128,14,128,0,1,0,1,128,15,128,15,128,17,18,19,16,128,30,128,16,17,16,17,128,31,128,31] -; AVX2-FCP-NEXT: vpshufb %ymm1, %ymm3, %ymm4 +; AVX2-FCP-NEXT: vpshufb %ymm1, %ymm2, %ymm3 ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm5 = [13,128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128] -; AVX2-FCP-NEXT: vpshufb %ymm5, %ymm14, %ymm6 -; AVX2-FCP-NEXT: vpor %ymm4, %ymm6, %ymm4 -; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm6 = [12,13,2,3,12,13,0,1,14,15,2,3,0,1,14,15,28,29,18,19,28,29,16,17,30,31,18,19,16,17,30,31] -; AVX2-FCP-NEXT: vpshufb %ymm6, %ymm13, %ymm10 -; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm11 = [255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u] -; AVX2-FCP-NEXT: vpblendvb %ymm11, %ymm4, %ymm10, %ymm4 +; AVX2-FCP-NEXT: vpshufb %ymm5, %ymm8, %ymm7 +; AVX2-FCP-NEXT: vpor %ymm3, %ymm7, %ymm3 +; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm7 = [12,13,2,3,12,13,0,1,14,15,2,3,0,1,14,15,28,29,18,19,28,29,16,17,30,31,18,19,16,17,30,31] +; AVX2-FCP-NEXT: vpshufb %ymm7, %ymm6, %ymm11 +; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm12 = [255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u,u,u,255,255,0,u,u] +; AVX2-FCP-NEXT: vpblendvb %ymm12, %ymm3, %ymm11, %ymm3 +; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload ; AVX2-FCP-NEXT: vpshufb %ymm1, %ymm2, %ymm1 +; AVX2-FCP-NEXT: vpshufb %ymm5, %ymm4, %ymm4 +; AVX2-FCP-NEXT: vpor %ymm1, %ymm4, %ymm1 ; AVX2-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload -; AVX2-FCP-NEXT: vpshufb %ymm5, %ymm2, %ymm3 -; AVX2-FCP-NEXT: vpor %ymm1, %ymm3, %ymm1 -; AVX2-FCP-NEXT: vpshufb %ymm6, %ymm7, %ymm2 -; AVX2-FCP-NEXT: vpblendvb %ymm11, %ymm1, %ymm2, %ymm1 +; AVX2-FCP-NEXT: vpshufb %ymm7, %ymm2, %ymm2 +; AVX2-FCP-NEXT: vpblendvb %ymm12, %ymm1, %ymm2, %ymm1 ; AVX2-FCP-NEXT: vmovdqa {{.*#+}} ymm2 = [0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255,255,255,0,0,0,255,255] -; AVX2-FCP-NEXT: vpblendvb %ymm2, %ymm9, %ymm4, %ymm3 +; AVX2-FCP-NEXT: vpblendvb %ymm2, %ymm10, %ymm3, %ymm3 ; AVX2-FCP-NEXT: vpblendvb %ymm2, %ymm0, %ymm1, %ymm0 ; AVX2-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX2-FCP-NEXT: vmovdqa %ymm0, 96(%rax) ; AVX2-FCP-NEXT: vmovdqa %ymm3, 320(%rax) -; AVX2-FCP-NEXT: vmovdqa %ymm8, 128(%rax) -; AVX2-FCP-NEXT: vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX2-FCP-NEXT: vmovaps %ymm0, 352(%rax) +; AVX2-FCP-NEXT: vmovdqa %ymm9, 128(%rax) +; AVX2-FCP-NEXT: vmovdqa %ymm14, 352(%rax) ; AVX2-FCP-NEXT: vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload ; AVX2-FCP-NEXT: vmovaps %ymm0, 160(%rax) ; AVX2-FCP-NEXT: vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload @@ -8688,1747 +8544,1675 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX2-FCP-NEXT: vmovaps %ymm0, 416(%rax) ; AVX2-FCP-NEXT: vmovups {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload ; AVX2-FCP-NEXT: vmovaps %ymm0, 384(%rax) -; AVX2-FCP-NEXT: addq $648, %rsp # imm = 0x288 +; AVX2-FCP-NEXT: addq $616, %rsp # imm = 0x268 ; AVX2-FCP-NEXT: vzeroupper ; AVX2-FCP-NEXT: retq ; ; AVX512-LABEL: store_i8_stride7_vf64: ; AVX512: # %bb.0: -; AVX512-NEXT: subq $1448, %rsp # imm = 0x5A8 -; AVX512-NEXT: vmovdqa (%rsi), %ymm1 -; AVX512-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,ymm1[14],zero,zero,zero,zero,zero,zero,ymm1[15],zero,zero,zero,zero,zero,zero,ymm1[16],zero,zero,zero,zero,zero,zero,ymm1[17],zero,zero,zero,zero,zero,zero,ymm1[18] -; AVX512-NEXT: vmovdqa %ymm1, %ymm10 -; AVX512-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512-NEXT: subq $1720, %rsp # imm = 0x6B8 +; AVX512-NEXT: vmovdqa (%rsi), %ymm7 +; AVX512-NEXT: vmovdqa {{.*#+}} ymm2 = [128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128,128,18] +; AVX512-NEXT: vpshufb %ymm2, %ymm7, %ymm0 +; AVX512-NEXT: vmovdqa64 %ymm2, %ymm26 ; AVX512-NEXT: vmovdqa (%rdi), %ymm2 -; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[0,1,14],zero,ymm2[12,13,0,1,14,15],zero,ymm2[3,12,13,2,3,16],zero,ymm2[30,31,28,29,16,17],zero,ymm2[31,18,19,28,29,18],zero -; AVX512-NEXT: vmovdqa %ymm2, %ymm14 -; AVX512-NEXT: vmovdqu %ymm2, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512-NEXT: vmovdqa {{.*#+}} ymm3 = [0,1,14,128,12,13,0,1,14,15,128,3,12,13,2,3,16,128,30,31,28,29,16,17,128,31,18,19,28,29,18,128] +; AVX512-NEXT: vpshufb %ymm3, %ymm2, %ymm1 +; AVX512-NEXT: vmovdqa64 %ymm3, %ymm25 +; AVX512-NEXT: vmovdqa64 %ymm2, %ymm18 ; AVX512-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-NEXT: vmovdqa (%rcx), %ymm6 -; AVX512-NEXT: vmovdqa {{.*#+}} ymm1 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] -; AVX512-NEXT: vpshufb %ymm1, %ymm6, %ymm0 -; AVX512-NEXT: vmovdqa64 %ymm1, %ymm23 +; AVX512-NEXT: vmovdqa (%rcx), %ymm14 +; AVX512-NEXT: vmovdqa {{.*#+}} ymm2 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] +; AVX512-NEXT: vpshufb %ymm2, %ymm14, %ymm0 +; AVX512-NEXT: vmovdqa64 %ymm2, %ymm28 ; AVX512-NEXT: vmovdqa (%rdx), %ymm8 -; AVX512-NEXT: vmovdqa {{.*#+}} ymm2 = [0,1,0,1,14,128,14,15,0,1,14,15,128,13,14,15,16,17,16,128,30,31,30,31,16,17,128,31,28,29,30,31] -; AVX512-NEXT: vpshufb %ymm2, %ymm8, %ymm1 -; AVX512-NEXT: vmovdqa64 %ymm2, %ymm17 +; AVX512-NEXT: vmovdqa {{.*#+}} ymm3 = [0,1,0,1,14,128,14,15,0,1,14,15,128,13,14,15,16,17,16,128,30,31,30,31,16,17,128,31,28,29,30,31] +; AVX512-NEXT: vpshufb %ymm3, %ymm8, %ymm1 +; AVX512-NEXT: vmovdqa64 %ymm3, %ymm23 +; AVX512-NEXT: vmovdqu %ymm8, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX512-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-NEXT: vmovdqa (%r8), %ymm0 -; AVX512-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512-NEXT: vmovdqa (%r8), %ymm15 ; AVX512-NEXT: vmovdqa {{.*#+}} ymm2 = [128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128] -; AVX512-NEXT: vpshufb %ymm2, %ymm0, %ymm0 -; AVX512-NEXT: vmovdqa64 %ymm2, %ymm18 -; AVX512-NEXT: vmovdqa (%r9), %ymm1 -; AVX512-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512-NEXT: vpshufb %ymm2, %ymm15, %ymm0 +; AVX512-NEXT: vmovdqa64 %ymm2, %ymm24 +; AVX512-NEXT: vmovdqa (%r9), %ymm2 ; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm3 = [13,0,0,0,128,16,128,14,0,0,0,128,17,128,15,0,13,0,0,0,128,16,128,14,0,0,0,128,17,128,15,0] ; AVX512-NEXT: # ymm3 = mem[0,1,0,1] -; AVX512-NEXT: vpshufb %ymm3, %ymm1, %ymm1 -; AVX512-NEXT: vmovdqa64 %ymm3, %ymm22 -; AVX512-NEXT: vporq %ymm0, %ymm1, %ymm24 -; AVX512-NEXT: vmovdqa 32(%r9), %ymm11 -; AVX512-NEXT: vmovdqa 32(%r8), %ymm1 -; AVX512-NEXT: vpshufb {{.*#+}} ymm0 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[27],zero,zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29] -; AVX512-NEXT: vmovdqa %ymm1, %ymm13 -; AVX512-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm11[25],zero,ymm11[23],zero,zero,zero,zero,ymm11[26],zero,ymm11[24],zero,zero +; AVX512-NEXT: vpshufb %ymm3, %ymm2, %ymm1 +; AVX512-NEXT: vmovdqa64 %ymm3, %ymm27 +; AVX512-NEXT: vmovdqa64 %ymm2, %ymm19 +; AVX512-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX512-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512-NEXT: vmovdqa 32(%rsi), %ymm10 +; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm6 = [128,128,128,30,128,28,128,128,128,128,31,128,29,128,128,128,128,128,128,30,128,28,128,128,128,128,31,128,29,128,128,128] +; AVX512-NEXT: # ymm6 = mem[0,1,0,1] +; AVX512-NEXT: vpshufb %ymm6, %ymm10, %ymm0 +; AVX512-NEXT: vmovdqa 32(%rdi), %ymm9 +; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm9[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm9[23],zero,zero,zero,zero,ymm9[26],zero,ymm9[24],zero,zero,zero,zero,ymm9[27],zero,ymm9[25] ; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 ; AVX512-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-NEXT: vmovdqa 32(%rcx), %ymm7 -; AVX512-NEXT: vmovdqa 32(%rdx), %ymm9 -; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm9[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm9[30],zero,ymm9[28],zero,zero,zero,zero,ymm9[31],zero,ymm9[29],zero,zero -; AVX512-NEXT: vmovdqu %ymm9, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm0 = [128,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128,128,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128] +; AVX512-NEXT: vmovdqa {{.*#+}} ymm1 = [12,13,14,128,12,128,14,15,14,15,128,13,128,15,12,13,28,29,30,128,28,128,30,31,30,31,128,29,128,31,28,29] +; AVX512-NEXT: vpshufb %ymm1, %ymm9, %ymm0 +; AVX512-NEXT: vmovdqa64 %ymm1, %ymm16 +; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm10[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm10[23,u,u,u],zero,ymm10[26],zero,ymm10[24,u,u,u],zero,ymm10[27],zero +; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-NEXT: vmovdqa 32(%rdx), %ymm5 +; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [128,128,128,128,30,128,28,128,128,128,128,31,128,29,128,128,128,128,128,128,30,128,28,128,128,128,128,31,128,29,128,128] +; AVX512-NEXT: # ymm1 = mem[0,1,0,1] +; AVX512-NEXT: vpshufb %ymm1, %ymm5, %ymm2 +; AVX512-NEXT: vmovdqa 32(%rcx), %ymm4 +; AVX512-NEXT: vpshufb {{.*#+}} ymm3 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm4[25],zero,ymm4[23],zero,zero,zero,zero,ymm4[26],zero,ymm4[24],zero,zero,zero,zero +; AVX512-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm2 +; AVX512-NEXT: vmovdqu64 %zmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm0 = [27,0,0,0,128,30,128,28,0,0,0,128,31,128,29,0,27,0,0,0,128,30,128,28,0,0,0,128,31,128,29,0] ; AVX512-NEXT: # ymm0 = mem[0,1,0,1] -; AVX512-NEXT: vpshufb %ymm0, %ymm7, %ymm2 -; AVX512-NEXT: vmovdqu %ymm7, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm1 -; AVX512-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-NEXT: vmovdqa 32(%rsi), %ymm5 -; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero,ymm5[29],zero,zero,zero -; AVX512-NEXT: vmovdqa 32(%rdi), %ymm4 -; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm3 = [128,23,128,128,128,128,26,128,24,128,128,128,128,27,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128,25] -; AVX512-NEXT: # ymm3 = mem[0,1,0,1] -; AVX512-NEXT: vpshufb %ymm3, %ymm4, %ymm2 -; AVX512-NEXT: vmovdqa64 %ymm4, %ymm20 -; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm1 -; AVX512-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-NEXT: vpshufb %ymm0, %ymm4, %ymm2 +; AVX512-NEXT: vmovdqa64 %ymm0, %ymm20 +; AVX512-NEXT: vpshufb {{.*#+}} ymm3 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,ymm5[23],zero,ymm5[21,22,23,26],zero,ymm5[24],zero,ymm5[28,29,26,27] +; AVX512-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm2 +; AVX512-NEXT: vmovdqu64 %zmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-NEXT: vmovdqa 32(%r8), %ymm3 +; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm0 = [128,27,128,128,128,128,30,128,28,128,128,128,128,31,128,29,128,27,128,128,128,128,30,128,28,128,128,128,128,31,128,29] +; AVX512-NEXT: # ymm0 = mem[0,1,0,1] +; AVX512-NEXT: vpshufb %ymm0, %ymm3, %ymm11 +; AVX512-NEXT: vmovdqa64 %ymm0, %ymm21 +; AVX512-NEXT: vmovdqa 32(%r9), %ymm2 +; AVX512-NEXT: vpshufb {{.*#+}} ymm12 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[25],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero +; AVX512-NEXT: vinserti64x4 $1, %ymm11, %zmm12, %zmm11 +; AVX512-NEXT: vmovdqu64 %zmm11, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm11 = [29,128,27,0,0,0,128,30,128,28,0,0,0,128,31,128,29,128,27,0,0,0,128,30,128,28,0,0,0,128,31,128] +; AVX512-NEXT: # ymm11 = mem[0,1,0,1] +; AVX512-NEXT: vpshufb %ymm11, %ymm2, %ymm12 +; AVX512-NEXT: vpshufb {{.*#+}} ymm13 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,ymm3[23],zero,ymm3[23,24,25,26],zero,ymm3[24],zero,ymm3[30,31] +; AVX512-NEXT: vinserti64x4 $1, %ymm12, %zmm13, %zmm12 +; AVX512-NEXT: vmovdqu64 %zmm12, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill ; AVX512-NEXT: movq {{[0-9]+}}(%rsp), %rax -; AVX512-NEXT: vmovdqa 32(%rax), %ymm4 -; AVX512-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] -; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] -; AVX512-NEXT: # ymm2 = mem[0,1,0,1] -; AVX512-NEXT: vpshufb %ymm2, %ymm4, %ymm4 -; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm4, %zmm1 -; AVX512-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-NEXT: vpshufb %ymm3, %ymm14, %ymm1 -; AVX512-NEXT: vpshufb {{.*#+}} ymm3 = ymm10[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm10[21],zero,ymm10[19],zero,zero,zero,zero,ymm10[22],zero,ymm10[20],zero,zero -; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm3, %zmm1 -; AVX512-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-NEXT: vmovdqu %ymm6, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-NEXT: vpshufb %ymm0, %ymm6, %ymm0 -; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[18],zero,zero,zero,zero,ymm6[21],zero,ymm6[19],zero,zero,zero,zero,ymm6[22],zero,ymm6[20] -; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-NEXT: vmovdqa 32(%rax), %ymm0 +; AVX512-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512-NEXT: vpshufb {{.*#+}} ymm12 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] +; AVX512-NEXT: vpshufb {{.*#+}} ymm13 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] +; AVX512-NEXT: vinserti64x4 $1, %ymm12, %zmm13, %zmm12 +; AVX512-NEXT: vmovdqu64 %zmm12, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-NEXT: vpshufb %ymm6, %ymm7, %ymm6 +; AVX512-NEXT: vmovdqa64 %ymm7, %ymm17 +; AVX512-NEXT: vmovdqa64 %ymm18, %ymm13 +; AVX512-NEXT: vmovdqa64 %ymm16, %ymm0 +; AVX512-NEXT: vpshufb %ymm0, %ymm13, %ymm7 +; AVX512-NEXT: vpor %ymm6, %ymm7, %ymm0 ; AVX512-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-NEXT: vpshufb {{.*#+}} ymm0 = ymm8[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,ymm8[23],zero,ymm8[21,22,23,26],zero,ymm8[24],zero,ymm8[28,29,26,27] -; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm8[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,ymm8[18,19,20,21],zero,ymm8[19],zero,ymm8[25,26,27,22],zero,ymm8[20],zero -; AVX512-NEXT: vmovdqa64 %ymm8, %ymm19 -; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-NEXT: vpshufb %ymm1, %ymm8, %ymm6 +; AVX512-NEXT: vmovdqa64 %ymm20, %ymm0 +; AVX512-NEXT: vpshufb %ymm0, %ymm14, %ymm7 +; AVX512-NEXT: vmovdqa64 %ymm14, %ymm22 +; AVX512-NEXT: vpor %ymm6, %ymm7, %ymm0 ; AVX512-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-NEXT: vmovdqa (%rax), %ymm1 -; AVX512-NEXT: vpshufb %ymm2, %ymm1, %ymm0 -; AVX512-NEXT: vpmovsxbd {{.*#+}} zmm16 = [0,5,4,0,5,0,4,0,20,21,0,23,0,21,0,23] -; AVX512-NEXT: vpshuflw {{.*#+}} ymm2 = ymm1[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] -; AVX512-NEXT: vpermi2d %zmm0, %zmm2, %zmm16 -; AVX512-NEXT: vmovdqa 32(%rdx), %xmm3 -; AVX512-NEXT: vmovdqa 32(%rcx), %xmm0 +; AVX512-NEXT: vmovdqa64 %ymm21, %ymm0 +; AVX512-NEXT: vpshufb %ymm0, %ymm15, %ymm6 +; AVX512-NEXT: vmovdqa64 %ymm15, %ymm16 +; AVX512-NEXT: vmovdqa64 %ymm19, %ymm15 +; AVX512-NEXT: vpshufb %ymm11, %ymm15, %ymm7 +; AVX512-NEXT: vpor %ymm6, %ymm7, %ymm0 +; AVX512-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-NEXT: vmovdqa 32(%rdx), %xmm0 ; AVX512-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512-NEXT: vmovdqa {{.*#+}} xmm2 = [u,u,u,128,7,128,5,u,u,u,128,8,128,6,u,u] -; AVX512-NEXT: vpshufb %xmm2, %xmm0, %xmm0 -; AVX512-NEXT: vmovdqa64 %xmm2, %xmm29 -; AVX512-NEXT: vmovdqa {{.*#+}} xmm4 = [u,u,u,7,128,5,128,u,u,u,8,128,6,128,u,u] -; AVX512-NEXT: vpshufb %xmm4, %xmm3, %xmm2 -; AVX512-NEXT: vmovdqa64 %xmm4, %xmm31 -; AVX512-NEXT: vmovdqa64 %xmm3, %xmm30 -; AVX512-NEXT: vpor %xmm0, %xmm2, %xmm0 +; AVX512-NEXT: vmovdqa 32(%rcx), %xmm1 +; AVX512-NEXT: vmovdqa %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512-NEXT: vmovdqa {{.*#+}} xmm11 = [u,u,u,128,7,128,5,u,u,u,128,8,128,6,u,u] +; AVX512-NEXT: vpshufb %xmm11, %xmm1, %xmm6 +; AVX512-NEXT: vmovdqa {{.*#+}} xmm12 = [u,u,u,7,128,5,128,u,u,u,8,128,6,128,u,u] +; AVX512-NEXT: vpshufb %xmm12, %xmm0, %xmm7 +; AVX512-NEXT: vpor %xmm6, %xmm7, %xmm0 ; AVX512-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-NEXT: vmovdqa 32(%rdi), %xmm3 -; AVX512-NEXT: vmovdqa 32(%rsi), %xmm4 -; AVX512-NEXT: vmovdqa {{.*#+}} xmm12 = [u,128,7,128,5,u,u,u,128,8,128,6,u,u,u,128] -; AVX512-NEXT: vpshufb %xmm12, %xmm4, %xmm0 -; AVX512-NEXT: vmovdqa {{.*#+}} xmm15 = [u,7,128,5,128,u,u,u,8,128,6,128,u,u,u,9] -; AVX512-NEXT: vpshufb %xmm15, %xmm3, %xmm2 -; AVX512-NEXT: vmovdqa64 %xmm3, %xmm21 -; AVX512-NEXT: vpor %xmm0, %xmm2, %xmm0 +; AVX512-NEXT: vmovdqa 32(%rdi), %xmm0 +; AVX512-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512-NEXT: vmovdqa 32(%rsi), %xmm14 +; AVX512-NEXT: vmovdqa {{.*#+}} xmm6 = [u,128,7,128,5,u,u,u,128,8,128,6,u,u,u,128] +; AVX512-NEXT: vpshufb %xmm6, %xmm14, %xmm7 +; AVX512-NEXT: vmovdqa {{.*#+}} xmm1 = [u,7,128,5,128,u,u,u,8,128,6,128,u,u,u,9] +; AVX512-NEXT: vpshufb %xmm1, %xmm0, %xmm8 +; AVX512-NEXT: vmovdqa64 %xmm1, %xmm18 +; AVX512-NEXT: vpor %xmm7, %xmm8, %xmm0 ; AVX512-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-NEXT: vpmovsxbd {{.*#+}} zmm3 = [0,0,0,0,2,3,0,1,0,18,0,19,18,0,19,0] -; AVX512-NEXT: vmovdqa 32(%rax), %xmm2 -; AVX512-NEXT: vmovdqa %xmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512-NEXT: vpshufhw {{.*#+}} xmm0 = xmm2[0,1,2,3,4,5,5,6] -; AVX512-NEXT: vpshufb {{.*#+}} xmm2 = xmm2[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] -; AVX512-NEXT: vpermi2d %zmm0, %zmm2, %zmm3 -; AVX512-NEXT: vmovdqu64 %zmm3, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,0,0,0,2,3,0,1,0,18,0,19,18,0,19,0] +; AVX512-NEXT: vmovdqa 32(%rax), %xmm0 +; AVX512-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512-NEXT: vpshufhw {{.*#+}} xmm7 = xmm0[0,1,2,3,4,5,5,6] +; AVX512-NEXT: vpshufb {{.*#+}} xmm8 = xmm0[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] +; AVX512-NEXT: vpermi2d %zmm7, %zmm8, %zmm1 +; AVX512-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill ; AVX512-NEXT: vmovdqa 32(%r9), %xmm0 -; AVX512-NEXT: vmovdqa 32(%r8), %xmm2 -; AVX512-NEXT: vmovdqa {{.*#+}} xmm6 = [128,4,u,u,u,128,7,128,5,u,u,u,128,8,128,6] -; AVX512-NEXT: vpshufb %xmm6, %xmm0, %xmm8 -; AVX512-NEXT: vmovdqa64 %xmm0, %xmm28 -; AVX512-NEXT: vmovdqa {{.*#+}} xmm14 = [4,128,u,u,u,7,128,5,128,u,u,u,8,128,6,128] -; AVX512-NEXT: vpshufb %xmm14, %xmm2, %xmm10 -; AVX512-NEXT: vmovdqa %xmm2, %xmm3 -; AVX512-NEXT: vporq %xmm8, %xmm10, %xmm26 +; AVX512-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512-NEXT: vmovdqa 32(%r8), %xmm1 +; AVX512-NEXT: vmovdqa {{.*#+}} xmm8 = [128,4,u,u,u,128,7,128,5,u,u,u,128,8,128,6] +; AVX512-NEXT: vpshufb %xmm8, %xmm0, %xmm7 +; AVX512-NEXT: vmovdqa64 %xmm8, %xmm20 +; AVX512-NEXT: vmovdqa {{.*#+}} xmm0 = [4,128,u,u,u,7,128,5,128,u,u,u,8,128,6,128] +; AVX512-NEXT: vpshufb %xmm0, %xmm1, %xmm8 +; AVX512-NEXT: vmovdqa64 %xmm0, %xmm30 +; AVX512-NEXT: vmovdqa64 %xmm1, %xmm29 +; AVX512-NEXT: vpor %xmm7, %xmm8, %xmm0 +; AVX512-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-NEXT: vmovdqa64 %ymm28, %ymm0 +; AVX512-NEXT: vpshufb %ymm0, %ymm4, %ymm7 ; AVX512-NEXT: vmovdqa64 %ymm23, %ymm0 -; AVX512-NEXT: vpshufb %ymm0, %ymm7, %ymm8 -; AVX512-NEXT: vmovdqa64 %ymm17, %ymm0 -; AVX512-NEXT: vpshufb %ymm0, %ymm9, %ymm10 -; AVX512-NEXT: vpor %ymm8, %ymm10, %ymm0 +; AVX512-NEXT: vpshufb %ymm0, %ymm5, %ymm8 +; AVX512-NEXT: vpor %ymm7, %ymm8, %ymm0 ; AVX512-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-NEXT: vpshufb {{.*#+}} ymm8 = zero,zero,zero,ymm5[14],zero,zero,zero,zero,zero,zero,ymm5[15],zero,zero,zero,zero,zero,zero,ymm5[16],zero,zero,zero,zero,zero,zero,ymm5[17],zero,zero,zero,zero,zero,zero,ymm5[18] -; AVX512-NEXT: vmovdqa64 %ymm5, %ymm23 -; AVX512-NEXT: vmovdqa64 %ymm20, %ymm0 -; AVX512-NEXT: vpshufb {{.*#+}} ymm10 = ymm0[0,1,14],zero,ymm0[12,13,0,1,14,15],zero,ymm0[3,12,13,2,3,16],zero,ymm0[30,31,28,29,16,17],zero,ymm0[31,18,19,28,29,18],zero -; AVX512-NEXT: vpor %ymm8, %ymm10, %ymm2 -; AVX512-NEXT: vmovdqu64 %zmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-NEXT: vmovdqa64 %ymm18, %ymm2 -; AVX512-NEXT: vpshufb %ymm2, %ymm13, %ymm8 -; AVX512-NEXT: vmovdqa64 %ymm22, %ymm2 -; AVX512-NEXT: vpshufb %ymm2, %ymm11, %ymm10 -; AVX512-NEXT: vmovdqa64 %ymm11, %ymm27 -; AVX512-NEXT: vpor %ymm8, %ymm10, %ymm2 +; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20] +; AVX512-NEXT: # ymm1 = mem[0,1,0,1] +; AVX512-NEXT: vpshufb %ymm1, %ymm4, %ymm0 +; AVX512-NEXT: vmovdqa64 %ymm1, %ymm21 +; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm4 = [18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128,18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128] +; AVX512-NEXT: # ymm4 = mem[0,1,0,1] +; AVX512-NEXT: vpshufb %ymm4, %ymm5, %ymm1 +; AVX512-NEXT: vmovdqa64 %ymm4, %ymm19 +; AVX512-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX512-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512-NEXT: vmovdqa64 %ymm26, %ymm0 +; AVX512-NEXT: vpshufb %ymm0, %ymm10, %ymm0 +; AVX512-NEXT: vmovdqa64 %ymm25, %ymm1 +; AVX512-NEXT: vpshufb %ymm1, %ymm9, %ymm1 +; AVX512-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX512-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm7 = [128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128] +; AVX512-NEXT: # ymm7 = mem[0,1,0,1] +; AVX512-NEXT: vpshufb %ymm7, %ymm10, %ymm0 +; AVX512-NEXT: vmovdqa {{.*#+}} ymm1 = [2,3,4,5,128,3,128,5,4,5,6,128,4,128,6,7,18,19,20,21,128,19,128,21,20,21,22,128,20,128,22,23] +; AVX512-NEXT: vpshufb %ymm1, %ymm9, %ymm4 +; AVX512-NEXT: vpor %ymm0, %ymm4, %ymm0 +; AVX512-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm10 = [128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22] +; AVX512-NEXT: # ymm10 = mem[0,1,0,1] +; AVX512-NEXT: vpshufb %ymm10, %ymm2, %ymm4 +; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm0 = [20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128,20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128] +; AVX512-NEXT: # ymm0 = mem[0,1,0,1] +; AVX512-NEXT: vpshufb %ymm0, %ymm3, %ymm5 +; AVX512-NEXT: vpor %ymm4, %ymm5, %ymm4 +; AVX512-NEXT: vmovdqu64 %zmm4, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-NEXT: vmovdqa64 %ymm24, %ymm4 +; AVX512-NEXT: vpshufb %ymm4, %ymm3, %ymm3 +; AVX512-NEXT: vmovdqa64 %ymm27, %ymm4 +; AVX512-NEXT: vpshufb %ymm4, %ymm2, %ymm2 +; AVX512-NEXT: vpor %ymm3, %ymm2, %ymm2 ; AVX512-NEXT: vmovdqu64 %zmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-NEXT: vmovdqa (%rsi), %xmm2 -; AVX512-NEXT: vpshufb %xmm12, %xmm2, %xmm5 -; AVX512-NEXT: vmovdqa64 %xmm2, %xmm25 -; AVX512-NEXT: vmovdqa (%rdi), %xmm12 -; AVX512-NEXT: vpshufb %xmm15, %xmm12, %xmm9 -; AVX512-NEXT: vporq %xmm5, %xmm9, %xmm22 -; AVX512-NEXT: vmovdqa (%rcx), %xmm13 -; AVX512-NEXT: vmovdqa64 %xmm29, %xmm2 -; AVX512-NEXT: vpshufb %xmm2, %xmm13, %xmm7 -; AVX512-NEXT: vmovdqa (%rdx), %xmm9 -; AVX512-NEXT: vmovdqa64 %xmm31, %xmm2 -; AVX512-NEXT: vpshufb %xmm2, %xmm9, %xmm10 -; AVX512-NEXT: vpor %xmm7, %xmm10, %xmm2 +; AVX512-NEXT: vmovdqa (%rsi), %xmm3 +; AVX512-NEXT: vpshufb %xmm6, %xmm3, %xmm2 +; AVX512-NEXT: vmovdqa64 %xmm3, %xmm31 +; AVX512-NEXT: vmovdqa (%rdi), %xmm4 +; AVX512-NEXT: vmovdqa64 %xmm18, %xmm3 +; AVX512-NEXT: vpshufb %xmm3, %xmm4, %xmm3 +; AVX512-NEXT: vmovdqa64 %xmm4, %xmm28 +; AVX512-NEXT: vpor %xmm2, %xmm3, %xmm2 ; AVX512-NEXT: vmovdqa %xmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512-NEXT: vmovdqa (%r9), %xmm2 +; AVX512-NEXT: vmovdqa (%rcx), %xmm3 +; AVX512-NEXT: vpshufb %xmm11, %xmm3, %xmm2 +; AVX512-NEXT: vmovdqa %xmm3, %xmm6 +; AVX512-NEXT: vmovdqa (%rdx), %xmm4 +; AVX512-NEXT: vpshufb %xmm12, %xmm4, %xmm3 +; AVX512-NEXT: vmovdqa64 %xmm4, %xmm18 +; AVX512-NEXT: vpor %xmm2, %xmm3, %xmm2 ; AVX512-NEXT: vmovdqa %xmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512-NEXT: vpshufb %xmm6, %xmm2, %xmm6 -; AVX512-NEXT: vmovdqa (%r8), %xmm5 -; AVX512-NEXT: vmovdqa %xmm5, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512-NEXT: vpshufb %xmm14, %xmm5, %xmm11 -; AVX512-NEXT: vpor %xmm6, %xmm11, %xmm6 -; AVX512-NEXT: vmovdqu64 %zmm6, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-NEXT: vinserti64x4 $1, %ymm24, %zmm0, %zmm6 -; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm11 = xmm5[8],xmm2[8],xmm5[9],xmm2[9],xmm5[10],xmm2[10],xmm5[11],xmm2[11],xmm5[12],xmm2[12],xmm5[13],xmm2[13],xmm5[14],xmm2[14],xmm5[15],xmm2[15] -; AVX512-NEXT: vmovdqa {{.*#+}} xmm7 = [u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] -; AVX512-NEXT: vpshufb %xmm7, %xmm11, %xmm11 -; AVX512-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm11[0,1,0,1],zmm6[4,5,6,7] +; AVX512-NEXT: vmovdqa (%r9), %xmm3 +; AVX512-NEXT: vmovdqa64 %xmm20, %xmm2 +; AVX512-NEXT: vpshufb %xmm2, %xmm3, %xmm2 +; AVX512-NEXT: vmovdqa %xmm3, %xmm8 +; AVX512-NEXT: vmovdqa (%r8), %xmm3 +; AVX512-NEXT: vmovdqa64 %xmm30, %xmm4 +; AVX512-NEXT: vpshufb %xmm4, %xmm3, %xmm4 +; AVX512-NEXT: vmovdqa %xmm3, %xmm9 +; AVX512-NEXT: vpor %xmm2, %xmm4, %xmm2 ; AVX512-NEXT: vmovdqu64 %zmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-NEXT: vmovdqa (%rax), %xmm10 -; AVX512-NEXT: vpshufhw {{.*#+}} xmm11 = xmm10[0,1,2,3,4,5,5,6] -; AVX512-NEXT: vpshufd {{.*#+}} xmm11 = xmm11[2,2,3,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm11 = ymm11[0,1,0,1] -; AVX512-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm11, %ymm11 -; AVX512-NEXT: vpshufb {{.*#+}} ymm14 = zero,ymm1[13],zero,zero,zero,zero,zero,zero,ymm1[14],zero,zero,zero,zero,zero,zero,ymm1[15],zero,zero,zero,zero,zero,zero,ymm1[16],zero,zero,zero,zero,zero,zero,ymm1[17],zero,zero -; AVX512-NEXT: vinserti64x4 $1, %ymm14, %zmm11, %zmm24 -; AVX512-NEXT: vmovdqa64 %ymm19, %ymm2 -; AVX512-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29],zero,zero -; AVX512-NEXT: vmovdqa64 %ymm2, %ymm18 -; AVX512-NEXT: vpbroadcastq {{.*#+}} ymm5 = [13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14] +; AVX512-NEXT: vpshufb {{.*#+}} ymm2 = ymm13[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm13[23],zero,zero,zero,zero,ymm13[26],zero,ymm13[24],zero,zero,zero,zero,ymm13[27],zero,ymm13[25] +; AVX512-NEXT: vmovdqa64 %ymm17, %ymm3 +; AVX512-NEXT: vpshufb %ymm7, %ymm3, %ymm4 +; AVX512-NEXT: vinserti64x4 $1, %ymm2, %zmm4, %zmm2 +; AVX512-NEXT: vmovdqu64 %zmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-NEXT: vpshufb {{.*#+}} ymm2 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm3[23,u,u,u],zero,ymm3[26],zero,ymm3[24,u,u,u],zero,ymm3[27],zero +; AVX512-NEXT: vpshufb %ymm1, %ymm13, %ymm1 +; AVX512-NEXT: vinserti64x4 $1, %ymm2, %zmm1, %zmm1 +; AVX512-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-NEXT: vmovdqa64 %ymm22, %ymm2 +; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[25],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero,zero,zero +; AVX512-NEXT: vmovdqa64 %ymm21, %ymm3 +; AVX512-NEXT: vpshufb %ymm3, %ymm2, %ymm2 +; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm1 +; AVX512-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill ; AVX512-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload -; AVX512-NEXT: vpshufb %ymm5, %ymm2, %ymm11 -; AVX512-NEXT: vmovdqa64 %ymm5, %ymm29 -; AVX512-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] -; AVX512-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm14 # 32-byte Reload -; AVX512-NEXT: vpshufb {{.*#+}} ymm15 = ymm14[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm14[27],zero,zero,zero,zero,ymm14[30],zero,ymm14[28],zero,zero,zero,zero,ymm14[31],zero,ymm14[29] -; AVX512-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,3,2,3] -; AVX512-NEXT: vmovdqa64 {{.*#+}} zmm31 = [18374967954648269055,71777218572844800,18374967954648269055,71777218572844800,18446463693966278655,18446742978476179455,18446463693966278655,18446742978476179455] -; AVX512-NEXT: vpternlogq $248, %ymm31, %ymm11, %ymm15 -; AVX512-NEXT: vmovdqa64 %xmm28, %xmm6 -; AVX512-NEXT: vmovdqa %xmm3, %xmm8 -; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm11 = xmm3[0],xmm6[0],xmm3[1],xmm6[1],xmm3[2],xmm6[2],xmm3[3],xmm6[3],xmm3[4],xmm6[4],xmm3[5],xmm6[5],xmm3[6],xmm6[6],xmm3[7],xmm6[7] -; AVX512-NEXT: vpshufb {{.*#+}} xmm11 = xmm11[u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] -; AVX512-NEXT: vshufi64x2 {{.*#+}} zmm5 = zmm15[0,1,2,3],zmm11[0,1,0,1] -; AVX512-NEXT: vmovdqu64 %zmm5, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] -; AVX512-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-NEXT: vpshufhw {{.*#+}} ymm1 = ymm0[0,1,2,3,6,7,7,6,8,9,10,11,14,15,15,14] -; AVX512-NEXT: vmovdqa64 %ymm20, %ymm17 -; AVX512-NEXT: vpshufd {{.*#+}} ymm1 = ymm1[2,2,3,3,6,6,7,7] -; AVX512-NEXT: vpbroadcastq {{.*#+}} ymm11 = [9,8,7,0,0,0,11,10,9,8,7,0,0,0,11,10,9,8,7,0,0,0,11,10,9,8,7,0,0,0,11,10] -; AVX512-NEXT: vmovdqa64 %ymm23, %ymm5 -; AVX512-NEXT: vpshufb %ymm11, %ymm5, %ymm15 -; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm15, %zmm19 -; AVX512-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm0[30],zero,ymm0[28],zero,zero,zero,zero,ymm0[31],zero,ymm0[29],zero,zero,zero -; AVX512-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-NEXT: vpshufb %ymm11, %ymm0, %ymm1 -; AVX512-NEXT: vpshuflw $233, {{[-0-9]+}}(%r{{[sb]}}p), %ymm11 # 32-byte Folded Reload -; AVX512-NEXT: # ymm11 = mem[1,2,2,3,4,5,6,7,9,10,10,11,12,13,14,15] -; AVX512-NEXT: vpshufd {{.*#+}} ymm11 = ymm11[0,0,1,1,4,4,5,5] -; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm11, %zmm23 -; AVX512-NEXT: vmovdqa64 %xmm30, %xmm0 +; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,ymm2[23],zero,ymm2[21,22,23,26],zero,ymm2[24],zero,ymm2[28,29,26,27] +; AVX512-NEXT: vmovdqa64 %ymm19, %ymm3 +; AVX512-NEXT: vpshufb %ymm3, %ymm2, %ymm2 +; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm30 +; AVX512-NEXT: vpshufb {{.*#+}} ymm1 = ymm15[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm15[25],zero,ymm15[23],zero,zero,zero,zero,ymm15[26],zero,ymm15[24],zero,zero +; AVX512-NEXT: vmovdqa64 %ymm16, %ymm3 +; AVX512-NEXT: vpshufb {{.*#+}} ymm2 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,ymm3[23],zero,ymm3[23,24,25,26],zero,ymm3[24],zero,ymm3[30,31] +; AVX512-NEXT: vpor %ymm1, %ymm2, %ymm1 +; AVX512-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-NEXT: vpshufb %ymm10, %ymm15, %ymm1 +; AVX512-NEXT: vpshufb %ymm0, %ymm3, %ymm0 +; AVX512-NEXT: vpor %ymm1, %ymm0, %ymm0 +; AVX512-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-NEXT: vmovdqa (%rax), %ymm4 +; AVX512-NEXT: vpshufb {{.*#+}} ymm0 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] +; AVX512-NEXT: vpmovsxbd {{.*#+}} zmm15 = [0,5,4,0,5,0,4,0,20,21,0,23,0,21,0,23] +; AVX512-NEXT: vpshuflw {{.*#+}} ymm1 = ymm4[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] +; AVX512-NEXT: vpermi2d %zmm0, %zmm1, %zmm15 +; AVX512-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm0, %zmm0 # 32-byte Folded Reload +; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm9[8],xmm8[8],xmm9[9],xmm8[9],xmm9[10],xmm8[10],xmm9[11],xmm8[11],xmm9[12],xmm8[12],xmm9[13],xmm8[13],xmm9[14],xmm8[14],xmm9[15],xmm8[15] +; AVX512-NEXT: vmovdqa64 %xmm9, %xmm21 +; AVX512-NEXT: vmovdqa64 %xmm8, %xmm22 +; AVX512-NEXT: vmovdqa {{.*#+}} xmm2 = [u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] +; AVX512-NEXT: vpshufb %xmm2, %xmm1, %xmm1 +; AVX512-NEXT: vmovdqa64 %xmm2, %xmm24 +; AVX512-NEXT: vshufi64x2 {{.*#+}} zmm23 = zmm1[0,1,0,1],zmm0[4,5,6,7] +; AVX512-NEXT: vmovdqa (%rax), %xmm11 +; AVX512-NEXT: vpshufhw {{.*#+}} xmm1 = xmm11[0,1,2,3,4,5,5,6] +; AVX512-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[2,2,3,3] +; AVX512-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,1,0,1] +; AVX512-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm1 +; AVX512-NEXT: vmovdqa {{.*#+}} ymm9 = [128,13,128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128] +; AVX512-NEXT: vpshufb %ymm9, %ymm4, %ymm2 +; AVX512-NEXT: vinserti64x4 $1, %ymm2, %zmm1, %zmm16 +; AVX512-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm10 # 16-byte Reload +; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm10[0],xmm14[0],xmm10[1],xmm14[1],xmm10[2],xmm14[2],xmm10[3],xmm14[3],xmm10[4],xmm14[4],xmm10[5],xmm14[5],xmm10[6],xmm14[6],xmm10[7],xmm14[7] +; AVX512-NEXT: vmovdqa {{.*#+}} xmm0 = [0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] +; AVX512-NEXT: vpshufb %xmm0, %xmm2, %xmm2 +; AVX512-NEXT: vmovdqa64 %xmm0, %xmm27 +; AVX512-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm0 # 64-byte Reload +; AVX512-NEXT: vshufi64x2 {{.*#+}} zmm12 = zmm0[2,3,2,3],zmm2[0,1,0,1] +; AVX512-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm2 # 16-byte Reload ; AVX512-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload -; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm11 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] -; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm15 = xmm13[8],xmm9[8],xmm13[9],xmm9[9],xmm13[10],xmm9[10],xmm13[11],xmm9[11],xmm13[12],xmm9[12],xmm13[13],xmm9[13],xmm13[14],xmm9[14],xmm13[15],xmm9[15] -; AVX512-NEXT: vmovdqa {{.*#+}} xmm0 = [6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] -; AVX512-NEXT: vpshufb %xmm0, %xmm15, %xmm3 -; AVX512-NEXT: vmovdqu %ymm3, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-NEXT: vpshufb %xmm0, %xmm1, %xmm0 +; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm3 = xmm2[0],xmm1[0],xmm2[1],xmm1[1],xmm2[2],xmm1[2],xmm2[3],xmm1[3],xmm2[4],xmm1[4],xmm2[5],xmm1[5],xmm2[6],xmm1[6],xmm2[7],xmm1[7] +; AVX512-NEXT: vmovdqa {{.*#+}} xmm0 = [4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] +; AVX512-NEXT: vpshufb %xmm0, %xmm3, %xmm3 +; AVX512-NEXT: vmovdqa64 %xmm0, %xmm26 +; AVX512-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm0 # 64-byte Reload +; AVX512-NEXT: vshufi64x2 {{.*#+}} zmm17 = zmm0[2,3,2,3],zmm3[0,1,0,1] +; AVX512-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm5 # 16-byte Reload +; AVX512-NEXT: vmovdqa64 %xmm29, %xmm3 +; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm13 = xmm3[0],xmm5[0],xmm3[1],xmm5[1],xmm3[2],xmm5[2],xmm3[3],xmm5[3],xmm3[4],xmm5[4],xmm3[5],xmm5[5],xmm3[6],xmm5[6],xmm3[7],xmm5[7] +; AVX512-NEXT: vmovdqa {{.*#+}} xmm0 = [u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] +; AVX512-NEXT: vpshufb %xmm0, %xmm13, %xmm13 +; AVX512-NEXT: vmovdqa64 %xmm0, %xmm25 +; AVX512-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm0 # 64-byte Reload +; AVX512-NEXT: vshufi64x2 {{.*#+}} zmm29 = zmm0[2,3,2,3],zmm13[0,1,0,1] +; AVX512-NEXT: vpshufb {{.*#+}} ymm0 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] +; AVX512-NEXT: vmovdqa64 %ymm0, %ymm20 +; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm0 = xmm1[8],xmm2[8],xmm1[9],xmm2[9],xmm1[10],xmm2[10],xmm1[11],xmm2[11],xmm1[12],xmm2[12],xmm1[13],xmm2[13],xmm1[14],xmm2[14],xmm1[15],xmm2[15] +; AVX512-NEXT: vmovdqa %xmm6, %xmm8 +; AVX512-NEXT: vmovdqa64 %xmm18, %xmm7 +; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm6[8],xmm7[8],xmm6[9],xmm7[9],xmm6[10],xmm7[10],xmm6[11],xmm7[11],xmm6[12],xmm7[12],xmm6[13],xmm7[13],xmm6[14],xmm7[14],xmm6[15],xmm7[15] +; AVX512-NEXT: vmovdqa {{.*#+}} xmm1 = [6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] +; AVX512-NEXT: vpshufb %xmm1, %xmm4, %xmm2 +; AVX512-NEXT: vmovdqa64 %ymm2, %ymm18 +; AVX512-NEXT: vpshufb %xmm1, %xmm0, %xmm0 ; AVX512-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm1 # 64-byte Reload -; AVX512-NEXT: vinserti32x4 $2, %xmm0, %zmm1, %zmm30 -; AVX512-NEXT: vmovdqa64 %xmm21, %xmm0 -; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm15 = xmm0[0],xmm4[0],xmm0[1],xmm4[1],xmm0[2],xmm4[2],xmm0[3],xmm4[3],xmm0[4],xmm4[4],xmm0[5],xmm4[5],xmm0[6],xmm4[6],xmm0[7],xmm4[7] -; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm0 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] -; AVX512-NEXT: vmovdqa64 %xmm25, %xmm3 -; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm3[8],xmm12[8],xmm3[9],xmm12[9],xmm3[10],xmm12[10],xmm3[11],xmm12[11],xmm3[12],xmm12[12],xmm3[13],xmm12[13],xmm3[14],xmm12[14],xmm3[15],xmm12[15] -; AVX512-NEXT: vmovdqa {{.*#+}} xmm4 = [2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] -; AVX512-NEXT: vpshufb %xmm4, %xmm1, %xmm1 -; AVX512-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-NEXT: vpshufb %xmm4, %xmm0, %xmm0 +; AVX512-NEXT: vinserti32x4 $2, %xmm0, %zmm1, %zmm19 +; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm14[8],xmm10[8],xmm14[9],xmm10[9],xmm14[10],xmm10[10],xmm14[11],xmm10[11],xmm14[12],xmm10[12],xmm14[13],xmm10[13],xmm14[14],xmm10[14],xmm14[15],xmm10[15] +; AVX512-NEXT: vmovdqa64 %xmm31, %xmm6 +; AVX512-NEXT: vmovdqa64 %xmm28, %xmm4 +; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm14 = xmm6[8],xmm4[8],xmm6[9],xmm4[9],xmm6[10],xmm4[10],xmm6[11],xmm4[11],xmm6[12],xmm4[12],xmm6[13],xmm4[13],xmm6[14],xmm4[14],xmm6[15],xmm4[15] +; AVX512-NEXT: vmovdqa {{.*#+}} xmm0 = [2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] +; AVX512-NEXT: vpshufb %xmm0, %xmm14, %xmm13 +; AVX512-NEXT: vpshufb %xmm0, %xmm1, %xmm0 ; AVX512-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm1 # 64-byte Reload -; AVX512-NEXT: vinserti32x4 $2, %xmm0, %zmm1, %zmm21 -; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm0 = xmm8[8],xmm6[8],xmm8[9],xmm6[9],xmm8[10],xmm6[10],xmm8[11],xmm6[11],xmm8[12],xmm6[12],xmm8[13],xmm6[13],xmm8[14],xmm6[14],xmm8[15],xmm6[15] -; AVX512-NEXT: vpshufb %xmm7, %xmm0, %xmm0 -; AVX512-NEXT: vshufi64x2 {{.*#+}} zmm26 = zmm26[0,1,0,1],zmm0[0,1,0,1] -; AVX512-NEXT: vpbroadcastq {{.*#+}} ymm1 = [11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12] -; AVX512-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX512-NEXT: vpshufb %ymm1, %ymm0, %ymm6 -; AVX512-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX512-NEXT: vpshufb %ymm1, %ymm0, %ymm8 -; AVX512-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[18],zero,zero,zero,zero,ymm0[21],zero,ymm0[19],zero,zero,zero,zero,ymm0[22],zero,ymm0[20] -; AVX512-NEXT: vmovdqa64 %ymm0, %ymm28 -; AVX512-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX512-NEXT: vpshufb {{.*#+}} ymm7 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,ymm0[23],zero,ymm0[21,22,23,26],zero,ymm0[24],zero,ymm0[28,29,26,27] -; AVX512-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,ymm0[18,19,20,21],zero,ymm0[19],zero,ymm0[25,26,27,22],zero,ymm0[20],zero -; AVX512-NEXT: vmovdqa64 %ymm0, %ymm20 -; AVX512-NEXT: vpshufb {{.*#+}} ymm5 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm5[21],zero,ymm5[19],zero,zero,zero,zero,ymm5[22],zero,ymm5[20],zero,zero -; AVX512-NEXT: vmovdqa64 %ymm27, %ymm1 -; AVX512-NEXT: vmovdqa64 %ymm29, %ymm0 -; AVX512-NEXT: vpshufb %ymm0, %ymm1, %ymm4 -; AVX512-NEXT: vmovdqa %ymm2, %ymm0 -; AVX512-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[25],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero -; AVX512-NEXT: vmovdqu %ymm2, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22] -; AVX512-NEXT: # ymm2 = mem[0,1,0,1] -; AVX512-NEXT: vpshufb %ymm2, %ymm0, %ymm0 -; AVX512-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-NEXT: vpshufb %ymm2, %ymm1, %ymm0 -; AVX512-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [24,25,24,25,128,23,128,23,24,25,26,128,24,128,30,31,24,25,24,25,128,23,128,23,24,25,26,128,24,128,30,31] -; AVX512-NEXT: # ymm2 = mem[0,1,0,1] -; AVX512-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX512-NEXT: vpshufb %ymm2, %ymm0, %ymm1 -; AVX512-NEXT: vpshufb %ymm2, %ymm14, %ymm2 -; AVX512-NEXT: vmovdqa64 %ymm2, %ymm27 -; AVX512-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128,20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128] -; AVX512-NEXT: # ymm2 = mem[0,1,0,1] -; AVX512-NEXT: vpshufb %ymm2, %ymm14, %ymm14 -; AVX512-NEXT: vmovdqa64 %ymm14, %ymm25 -; AVX512-NEXT: vpshufb %ymm2, %ymm0, %ymm0 -; AVX512-NEXT: vmovdqa64 %ymm0, %ymm29 -; AVX512-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX512-NEXT: vpshufb {{.*#+}} ymm2 = zero,ymm0[13],zero,zero,zero,zero,zero,zero,ymm0[14],zero,zero,zero,zero,zero,zero,ymm0[15],zero,zero,zero,zero,zero,zero,ymm0[16],zero,zero,zero,zero,zero,zero,ymm0[17],zero,zero -; AVX512-NEXT: vpshuflw {{.*#+}} ymm14 = ymm0[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] -; AVX512-NEXT: vpshufd {{.*#+}} ymm14 = ymm14[0,1,1,3,4,5,5,7] -; AVX512-NEXT: vpermq {{.*#+}} ymm14 = ymm14[2,2,3,2] -; AVX512-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm14, %ymm14 -; AVX512-NEXT: vinserti64x4 $1, %ymm14, %zmm2, %zmm2 -; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm12 = xmm12[0],xmm3[0],xmm12[1],xmm3[1],xmm12[2],xmm3[2],xmm12[3],xmm3[3],xmm12[4],xmm3[4],xmm12[5],xmm3[5],xmm12[6],xmm3[6],xmm12[7],xmm3[7] -; AVX512-NEXT: vmovdqa {{.*#+}} xmm14 = [0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] -; AVX512-NEXT: vpshufb %xmm14, %xmm15, %xmm15 -; AVX512-NEXT: vpshufb %xmm14, %xmm12, %xmm12 -; AVX512-NEXT: vinserti32x4 $2, %xmm22, %zmm12, %zmm0 -; AVX512-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm13 = xmm9[0],xmm13[0],xmm9[1],xmm13[1],xmm9[2],xmm13[2],xmm9[3],xmm13[3],xmm9[4],xmm13[4],xmm9[5],xmm13[5],xmm9[6],xmm13[6],xmm9[7],xmm13[7] -; AVX512-NEXT: vmovdqa {{.*#+}} xmm14 = [4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] -; AVX512-NEXT: vpshufb %xmm14, %xmm11, %xmm9 -; AVX512-NEXT: vpshufb %xmm14, %xmm13, %xmm11 -; AVX512-NEXT: vpermq {{.*#+}} ymm13 = ymm6[2,3,2,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm14 = ymm18[2,3,2,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm22 = ymm4[2,3,2,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm6 = ymm8[2,3,2,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm0 = ymm7[2,3,2,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm4 = ymm5[2,3,2,3] -; AVX512-NEXT: vmovdqa64 %ymm17, %ymm3 -; AVX512-NEXT: vpshuflw {{.*#+}} ymm3 = ymm3[1,2,2,3,4,5,6,7,9,10,10,11,12,13,14,15] -; AVX512-NEXT: vpshufd {{.*#+}} ymm3 = ymm3[0,0,1,1,4,4,5,5] -; AVX512-NEXT: vinserti32x4 $2, {{[-0-9]+}}(%r{{[sb]}}p), %zmm11, %zmm12 # 16-byte Folded Reload -; AVX512-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm5 # 16-byte Reload -; AVX512-NEXT: vpunpcklbw {{[-0-9]+}}(%r{{[sb]}}p), %xmm5, %xmm5 # 16-byte Folded Reload -; AVX512-NEXT: # xmm5 = xmm5[0],mem[0],xmm5[1],mem[1],xmm5[2],mem[2],xmm5[3],mem[3],xmm5[4],mem[4],xmm5[5],mem[5],xmm5[6],mem[6],xmm5[7],mem[7] -; AVX512-NEXT: vpshufb {{.*#+}} xmm5 = xmm5[u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] -; AVX512-NEXT: vshufi64x2 $0, {{[-0-9]+}}(%r{{[sb]}}p), %zmm5, %zmm11 # 64-byte Folded Reload -; AVX512-NEXT: # zmm11 = zmm5[0,1,0,1],mem[0,1,0,1] -; AVX512-NEXT: vpshufb {{.*#+}} xmm5 = xmm10[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] -; AVX512-NEXT: vpshuflw {{.*#+}} xmm7 = xmm10[1,1,0,0,4,5,6,7] -; AVX512-NEXT: vpshufd {{.*#+}} xmm7 = xmm7[0,1,2,0] -; AVX512-NEXT: vinserti64x4 $1, %ymm5, %zmm7, %zmm7 -; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm10 # 64-byte Folded Reload -; AVX512-NEXT: # zmm10 = mem[2,3,2,3,6,7,6,7] -; AVX512-NEXT: vpermq {{.*#+}} zmm5 = zmm19[2,3,2,3,6,7,6,7] -; AVX512-NEXT: vpternlogq $236, %zmm31, %zmm10, %zmm5 -; AVX512-NEXT: vpandq %ymm31, %ymm22, %ymm10 -; AVX512-NEXT: vinserti64x4 $1, %ymm10, %zmm1, %zmm1 -; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm10 # 64-byte Folded Reload -; AVX512-NEXT: # zmm10 = mem[2,3,2,3,6,7,6,7] -; AVX512-NEXT: vporq %zmm10, %zmm1, %zmm1 -; AVX512-NEXT: vmovdqa64 {{.*#+}} zmm10 = [18374966859431673855,18446463693966278655,18374966859431673855,18446463693966278655,18374967954648269055,71777218572844800,18374967954648269055,71777218572844800] -; AVX512-NEXT: vpand %ymm6, %ymm10, %ymm6 -; AVX512-NEXT: vinserti64x4 $1, %ymm6, %zmm0, %zmm0 -; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm6 # 64-byte Folded Reload -; AVX512-NEXT: # zmm6 = mem[2,3,2,3,6,7,6,7] -; AVX512-NEXT: vporq %zmm6, %zmm0, %zmm0 -; AVX512-NEXT: vpternlogq $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm5 -; AVX512-NEXT: vmovdqa64 {{.*#+}} zmm0 = [255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255] -; AVX512-NEXT: vpternlogq $226, %zmm1, %zmm0, %zmm5 -; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm1 # 64-byte Folded Reload -; AVX512-NEXT: # zmm1 = mem[2,3,2,3,6,7,6,7] -; AVX512-NEXT: vpermq {{.*#+}} zmm6 = zmm23[2,3,2,3,6,7,6,7] -; AVX512-NEXT: vpternlogq $236, %zmm10, %zmm1, %zmm6 -; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm1 # 64-byte Folded Reload -; AVX512-NEXT: # zmm1 = mem[2,3,2,3,6,7,6,7] -; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm17 # 64-byte Folded Reload -; AVX512-NEXT: # zmm17 = mem[2,3,2,3,6,7,6,7] -; AVX512-NEXT: vporq %zmm1, %zmm17, %zmm1 -; AVX512-NEXT: vpternlogq $226, %zmm6, %zmm0, %zmm1 -; AVX512-NEXT: vpermq {{.*#+}} zmm6 = zmm30[0,1,0,1,4,5,4,5] -; AVX512-NEXT: vpermq {{.*#+}} zmm17 = zmm21[0,1,0,1,4,5,4,5] -; AVX512-NEXT: vpternlogq $226, %zmm6, %zmm0, %zmm17 -; AVX512-NEXT: vpternlogq $248, %ymm10, %ymm13, %ymm14 -; AVX512-NEXT: vpermq {{.*#+}} ymm0 = ymm3[2,3,2,3] -; AVX512-NEXT: vpternlogq $236, %ymm10, %ymm4, %ymm0 -; AVX512-NEXT: vpermq {{.*#+}} ymm3 = ymm9[0,1,0,1] -; AVX512-NEXT: vinserti64x4 $1, %ymm3, %zmm14, %zmm3 -; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %ymm4 # 32-byte Folded Reload -; AVX512-NEXT: # ymm4 = mem[2,3,2,3] -; AVX512-NEXT: vpshufhw $190, {{[-0-9]+}}(%r{{[sb]}}p), %ymm6 # 32-byte Folded Reload -; AVX512-NEXT: # ymm6 = mem[0,1,2,3,6,7,7,6,8,9,10,11,14,15,15,14] -; AVX512-NEXT: vpshufd {{.*#+}} ymm6 = ymm6[2,2,3,3,6,6,7,7] -; AVX512-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,3,2,3] -; AVX512-NEXT: vpternlogq $236, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm4, %ymm6 -; AVX512-NEXT: vpermq {{.*#+}} ymm4 = ymm15[0,1,0,1] -; AVX512-NEXT: vinserti64x4 $1, %ymm4, %zmm6, %zmm4 -; AVX512-NEXT: vmovdqa64 {{.*#+}} zmm6 = [255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255] -; AVX512-NEXT: vpternlogq $184, %zmm3, %zmm6, %zmm4 -; AVX512-NEXT: vpermq {{.*#+}} ymm3 = ymm28[2,3,2,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm8 = ymm20[2,3,2,3] -; AVX512-NEXT: vpor %ymm3, %ymm8, %ymm3 -; AVX512-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm8 # 64-byte Reload -; AVX512-NEXT: vinserti64x4 $1, %ymm3, %zmm8, %zmm3 -; AVX512-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm8 # 64-byte Reload -; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm8, %zmm0 -; AVX512-NEXT: vpermq $68, {{[-0-9]+}}(%r{{[sb]}}p), %ymm8 # 32-byte Folded Reload -; AVX512-NEXT: # ymm8 = mem[0,1,0,1] -; AVX512-NEXT: vpermq $68, {{[-0-9]+}}(%r{{[sb]}}p), %ymm10 # 32-byte Folded Reload -; AVX512-NEXT: # ymm10 = mem[0,1,0,1] -; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %ymm13 # 32-byte Folded Reload -; AVX512-NEXT: # ymm13 = mem[2,3,2,3] -; AVX512-NEXT: vpshuflw $5, {{[-0-9]+}}(%r{{[sb]}}p), %xmm14 # 16-byte Folded Reload -; AVX512-NEXT: # xmm14 = mem[1,1,0,0,4,5,6,7] -; AVX512-NEXT: vpshufd {{.*#+}} xmm14 = xmm14[0,1,2,0] -; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %ymm15 # 32-byte Folded Reload -; AVX512-NEXT: # ymm15 = mem[2,3,2,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm18 = ymm27[2,3,2,3] -; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %ymm19 # 32-byte Folded Reload -; AVX512-NEXT: # ymm19 = mem[2,3,2,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm20 = ymm25[2,3,2,3] -; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %ymm21 # 32-byte Folded Reload -; AVX512-NEXT: # ymm21 = mem[2,3,2,3] -; AVX512-NEXT: vpermq {{.*#+}} ymm22 = ymm29[2,3,2,3] -; AVX512-NEXT: vpternlogq $226, %zmm3, %zmm6, %zmm0 -; AVX512-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm8, %zmm3 # 32-byte Folded Reload -; AVX512-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm10, %zmm6 # 32-byte Folded Reload -; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm3, %zmm6 +; AVX512-NEXT: vinserti32x4 $2, %xmm0, %zmm1, %zmm0 +; AVX512-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm3[8],xmm5[8],xmm3[9],xmm5[9],xmm3[10],xmm5[10],xmm3[11],xmm5[11],xmm3[12],xmm5[12],xmm3[13],xmm5[13],xmm3[14],xmm5[14],xmm3[15],xmm5[15] +; AVX512-NEXT: vmovdqa64 %xmm24, %xmm2 +; AVX512-NEXT: vpshufb %xmm2, %xmm1, %xmm1 +; AVX512-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Reload +; AVX512-NEXT: vshufi64x2 {{.*#+}} zmm14 = zmm2[0,1,0,1],zmm1[0,1,0,1] +; AVX512-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm10 # 32-byte Reload +; AVX512-NEXT: vpshufb %ymm9, %ymm10, %ymm1 +; AVX512-NEXT: vpshuflw {{.*#+}} ymm9 = ymm10[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] +; AVX512-NEXT: vpshufd {{.*#+}} ymm9 = ymm9[0,1,1,3,4,5,5,7] +; AVX512-NEXT: vmovdqa64 {{.*#+}} zmm10 = [255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255] +; AVX512-NEXT: vpternlogq $226, %zmm12, %zmm10, %zmm17 +; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Folded Reload +; AVX512-NEXT: # ymm2 = mem[2,3,2,3] ; AVX512-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload -; AVX512-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm3, %zmm24 -; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm6, %zmm24 -; AVX512-NEXT: vpermq {{.*#+}} ymm3 = ymm14[0,0,1,0] -; AVX512-NEXT: vinserti64x4 $1, %ymm3, %zmm13, %zmm3 -; AVX512-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm6 # 64-byte Reload -; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm6, %zmm3 -; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm4, %zmm3 +; AVX512-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm2 +; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %ymm28 # 32-byte Folded Reload +; AVX512-NEXT: # ymm28 = mem[2,3,2,3] +; AVX512-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload +; AVX512-NEXT: vinserti64x4 $1, %ymm28, %zmm3, %zmm28 +; AVX512-NEXT: vpternlogq $226, %zmm2, %zmm10, %zmm28 +; AVX512-NEXT: vpermq {{.*#+}} ymm2 = ymm9[2,2,3,2] +; AVX512-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm2 +; AVX512-NEXT: vinserti64x4 $1, %ymm2, %zmm1, %zmm10 +; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm4[0],xmm6[0],xmm4[1],xmm6[1],xmm4[2],xmm6[2],xmm4[3],xmm6[3],xmm4[4],xmm6[4],xmm4[5],xmm6[5],xmm4[6],xmm6[6],xmm4[7],xmm6[7] +; AVX512-NEXT: vmovdqa64 %xmm27, %xmm2 +; AVX512-NEXT: vpshufb %xmm2, %xmm1, %xmm1 +; AVX512-NEXT: vinserti32x4 $2, {{[-0-9]+}}(%r{{[sb]}}p), %zmm1, %zmm27 # 16-byte Folded Reload +; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm7[0],xmm8[0],xmm7[1],xmm8[1],xmm7[2],xmm8[2],xmm7[3],xmm8[3],xmm7[4],xmm8[4],xmm7[5],xmm8[5],xmm7[6],xmm8[6],xmm7[7],xmm8[7] +; AVX512-NEXT: vmovdqa64 %xmm26, %xmm1 +; AVX512-NEXT: vpshufb %xmm1, %xmm2, %xmm2 +; AVX512-NEXT: vinserti32x4 $2, {{[-0-9]+}}(%r{{[sb]}}p), %zmm2, %zmm2 # 16-byte Folded Reload +; AVX512-NEXT: vmovdqa64 %xmm21, %xmm1 +; AVX512-NEXT: vmovdqa64 %xmm22, %xmm3 +; AVX512-NEXT: vpunpcklbw {{.*#+}} xmm8 = xmm1[0],xmm3[0],xmm1[1],xmm3[1],xmm1[2],xmm3[2],xmm1[3],xmm3[3],xmm1[4],xmm3[4],xmm1[5],xmm3[5],xmm1[6],xmm3[6],xmm1[7],xmm3[7] +; AVX512-NEXT: vmovdqa64 %xmm25, %xmm1 +; AVX512-NEXT: vpshufb %xmm1, %xmm8, %xmm8 +; AVX512-NEXT: vshufi64x2 $0, {{[-0-9]+}}(%r{{[sb]}}p), %zmm8, %zmm8 # 64-byte Folded Reload +; AVX512-NEXT: # zmm8 = zmm8[0,1,0,1],mem[0,1,0,1] +; AVX512-NEXT: vpshufb {{.*#+}} xmm9 = xmm11[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] +; AVX512-NEXT: vpshuflw {{.*#+}} xmm5 = xmm11[1,1,0,0,4,5,6,7] +; AVX512-NEXT: vpshufd {{.*#+}} xmm5 = xmm5[0,1,2,0] +; AVX512-NEXT: vinserti64x4 $1, %ymm9, %zmm5, %zmm5 +; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm9 # 64-byte Folded Reload +; AVX512-NEXT: # zmm9 = mem[2,3,2,3,6,7,6,7] +; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm11 # 64-byte Folded Reload +; AVX512-NEXT: # zmm11 = mem[2,3,2,3,6,7,6,7] +; AVX512-NEXT: vporq %zmm9, %zmm11, %zmm9 +; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm11 # 64-byte Folded Reload +; AVX512-NEXT: # zmm11 = mem[2,3,2,3,6,7,6,7] +; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm12 # 64-byte Folded Reload +; AVX512-NEXT: # zmm12 = mem[2,3,2,3,6,7,6,7] +; AVX512-NEXT: vporq %zmm11, %zmm12, %zmm11 +; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm9, %zmm11 +; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm9 # 64-byte Folded Reload +; AVX512-NEXT: # zmm9 = mem[2,3,2,3,6,7,6,7] +; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm12 # 64-byte Folded Reload +; AVX512-NEXT: # zmm12 = mem[2,3,2,3,6,7,6,7] +; AVX512-NEXT: vporq %zmm9, %zmm12, %zmm9 +; AVX512-NEXT: vmovdqa64 {{.*#+}} zmm12 = [255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255] +; AVX512-NEXT: vpternlogq $184, %zmm11, %zmm12, %zmm9 +; AVX512-NEXT: vpermq {{.*#+}} ymm11 = ymm13[0,1,0,1] +; AVX512-NEXT: vpermq {{.*#+}} ymm4 = ymm18[0,1,0,1] +; AVX512-NEXT: vpermq {{.*#+}} ymm3 = ymm20[2,3,2,3] +; AVX512-NEXT: vpshuflw $5, {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Folded Reload +; AVX512-NEXT: # xmm1 = mem[1,1,0,0,4,5,6,7] +; AVX512-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[0,1,2,0] +; AVX512-NEXT: vpermq {{.*#+}} zmm13 = zmm19[0,1,0,1,4,5,4,5] +; AVX512-NEXT: vpermq {{.*#+}} zmm0 = zmm0[0,1,0,1,4,5,4,5] +; AVX512-NEXT: vpternlogq $226, %zmm13, %zmm12, %zmm0 +; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm13 # 64-byte Folded Reload +; AVX512-NEXT: # zmm13 = mem[2,3,2,3,6,7,6,7] +; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm21 # 64-byte Folded Reload +; AVX512-NEXT: # zmm21 = mem[2,3,2,3,6,7,6,7] +; AVX512-NEXT: vporq %zmm13, %zmm21, %zmm13 +; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm20 # 64-byte Folded Reload +; AVX512-NEXT: # zmm20 = mem[2,3,2,3,6,7,6,7] +; AVX512-NEXT: vpermq {{.*#+}} zmm18 = zmm30[2,3,2,3,6,7,6,7] +; AVX512-NEXT: vporq %zmm20, %zmm18, %zmm18 +; AVX512-NEXT: vpternlogq $226, %zmm13, %zmm12, %zmm18 +; AVX512-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm11, %zmm11 # 32-byte Folded Reload +; AVX512-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm4, %zmm4 # 32-byte Folded Reload +; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm11, %zmm4 +; AVX512-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm23, %zmm16 +; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm4, %zmm16 ; AVX512-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm4 # 64-byte Folded Reload ; AVX512-NEXT: # zmm4 = mem[2,3,2,3,6,7,6,7] -; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm4 -; AVX512-NEXT: vporq %ymm15, %ymm18, %ymm5 -; AVX512-NEXT: vporq %ymm19, %ymm20, %ymm6 -; AVX512-NEXT: vshufi64x2 {{.*#+}} zmm5 = zmm6[0,1,2,3],zmm5[0,1,2,3] -; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm16 -; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm16 -; AVX512-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm1 # 64-byte Reload -; AVX512-NEXT: vpternlogd $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm26 -; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm17, %zmm26 -; AVX512-NEXT: vporq %ymm21, %ymm22, %ymm1 -; AVX512-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm5 # 64-byte Reload -; AVX512-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm5[0,1,2,3],zmm1[0,1,2,3] -; AVX512-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm2 +; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm9, %zmm4 +; AVX512-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,0,1,0] +; AVX512-NEXT: vinserti64x4 $1, %ymm1, %zmm3, %zmm1 +; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm29, %zmm1 +; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm17, %zmm1 +; AVX512-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload +; AVX512-NEXT: vpternlogd $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm3, %zmm14 +; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm14 +; AVX512-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm0 # 64-byte Reload +; AVX512-NEXT: vshufi64x2 $84, {{[-0-9]+}}(%r{{[sb]}}p), %zmm0, %zmm0 # 64-byte Folded Reload +; AVX512-NEXT: # zmm0 = zmm0[0,1,2,3],mem[2,3,2,3] +; AVX512-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm10 +; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm28, %zmm10 +; AVX512-NEXT: vpermq {{.*#+}} zmm0 = zmm27[0,1,0,1,4,5,4,5] +; AVX512-NEXT: vpermq {{.*#+}} zmm2 = zmm2[0,1,0,1,4,5,4,5] ; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm2 -; AVX512-NEXT: vpermq $68, {{[-0-9]+}}(%r{{[sb]}}p), %zmm0 # 64-byte Folded Reload -; AVX512-NEXT: # zmm0 = mem[0,1,0,1,4,5,4,5] -; AVX512-NEXT: vpermq {{.*#+}} zmm1 = zmm12[0,1,0,1,4,5,4,5] -; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm1 -; AVX512-NEXT: vpermq {{.*#+}} zmm0 = zmm7[0,0,1,0,4,4,5,4] -; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm11, %zmm0 -; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm0 +; AVX512-NEXT: vpermq {{.*#+}} zmm0 = zmm5[0,0,1,0,4,4,5,4] +; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm8, %zmm0 +; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm0 +; AVX512-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Reload +; AVX512-NEXT: vshufi64x2 $85, {{[-0-9]+}}(%r{{[sb]}}p), %zmm2, %zmm2 # 64-byte Folded Reload +; AVX512-NEXT: # zmm2 = zmm2[2,3,2,3],mem[2,3,2,3] +; AVX512-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm15 +; AVX512-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm18, %zmm15 ; AVX512-NEXT: movq {{[0-9]+}}(%rsp), %rax +; AVX512-NEXT: vmovdqa64 %zmm15, 128(%rax) ; AVX512-NEXT: vmovdqa64 %zmm0, (%rax) -; AVX512-NEXT: vmovdqa64 %zmm2, 320(%rax) -; AVX512-NEXT: vmovdqa64 %zmm26, 256(%rax) -; AVX512-NEXT: vmovdqa64 %zmm16, 128(%rax) +; AVX512-NEXT: vmovdqa64 %zmm10, 320(%rax) +; AVX512-NEXT: vmovdqa64 %zmm14, 256(%rax) +; AVX512-NEXT: vmovdqa64 %zmm1, 192(%rax) ; AVX512-NEXT: vmovdqa64 %zmm4, 384(%rax) -; AVX512-NEXT: vmovdqa64 %zmm3, 192(%rax) -; AVX512-NEXT: vmovdqa64 %zmm24, 64(%rax) -; AVX512-NEXT: addq $1448, %rsp # imm = 0x5A8 +; AVX512-NEXT: vmovdqa64 %zmm16, 64(%rax) +; AVX512-NEXT: addq $1720, %rsp # imm = 0x6B8 ; AVX512-NEXT: vzeroupper ; AVX512-NEXT: retq ; ; AVX512-FCP-LABEL: store_i8_stride7_vf64: ; AVX512-FCP: # %bb.0: -; AVX512-FCP-NEXT: subq $1256, %rsp # imm = 0x4E8 -; AVX512-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax -; AVX512-FCP-NEXT: vmovdqa 32(%rcx), %ymm2 -; AVX512-FCP-NEXT: vmovdqa 32(%rdx), %ymm1 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29],zero,zero -; AVX512-FCP-NEXT: vmovdqa %ymm1, %ymm14 -; AVX512-FCP-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[25],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero,zero,zero -; AVX512-FCP-NEXT: vmovdqa %ymm2, %ymm13 +; AVX512-FCP-NEXT: subq $1432, %rsp # imm = 0x598 +; AVX512-FCP-NEXT: vmovdqa 32(%rsi), %ymm2 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29],zero,zero,zero +; AVX512-FCP-NEXT: vmovdqa 32(%rdi), %ymm3 +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm15 = [128,23,128,128,128,128,26,128,24,128,128,128,128,27,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128,25] +; AVX512-FCP-NEXT: # ymm15 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm15, %ymm3, %ymm1 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,30],zero,ymm3[28],zero,ymm3[30,31,30,31],zero,ymm3[29],zero,ymm3[31,28,29] +; AVX512-FCP-NEXT: vmovdqa64 %ymm3, %ymm25 +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm3 = [25,128,23,0,0,0,128,26,128,24,0,0,0,128,27,128,25,128,23,0,0,0,128,26,128,24,0,0,0,128,27,128] +; AVX512-FCP-NEXT: # ymm3 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm3, %ymm2, %ymm1 +; AVX512-FCP-NEXT: vmovdqa64 %ymm3, %ymm27 +; AVX512-FCP-NEXT: vmovdqa64 %ymm2, %ymm18 ; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 ; AVX512-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-FCP-NEXT: vmovdqa 32(%rsi), %ymm1 -; AVX512-FCP-NEXT: vmovdqa 32(%rdi), %ymm2 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29],zero,zero,zero -; AVX512-FCP-NEXT: vmovdqa64 %ymm1, %ymm16 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero,zero,zero,ymm2[27],zero,ymm2[25] +; AVX512-FCP-NEXT: vmovdqa 32(%rdx), %ymm2 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29],zero,zero +; AVX512-FCP-NEXT: vmovdqa 32(%rcx), %ymm3 +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm4 = [128,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128,128,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128] +; AVX512-FCP-NEXT: # ymm4 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm4, %ymm3, %ymm1 +; AVX512-FCP-NEXT: vmovdqa64 %ymm4, %ymm28 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u,u,u],zero,ymm3[30],zero,ymm3[28,u,u,u],zero,ymm3[31],zero,ymm3[29,u] +; AVX512-FCP-NEXT: vmovdqa64 %ymm3, %ymm19 +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm3 = [24,25,128,23,128,21,22,23,26,128,24,128,28,29,26,27,24,25,128,23,128,21,22,23,26,128,24,128,28,29,26,27] +; AVX512-FCP-NEXT: # ymm3 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm3, %ymm2, %ymm1 +; AVX512-FCP-NEXT: vmovdqa64 %ymm3, %ymm24 ; AVX512-FCP-NEXT: vmovdqa64 %ymm2, %ymm17 ; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 ; AVX512-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-FCP-NEXT: vmovdqa 32(%r9), %ymm4 -; AVX512-FCP-NEXT: vmovdqa 32(%r8), %ymm1 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[27],zero,zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29] -; AVX512-FCP-NEXT: vmovdqa64 %ymm1, %ymm18 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm4[25],zero,ymm4[23],zero,zero,zero,zero,ymm4[26],zero,ymm4[24],zero,zero -; AVX512-FCP-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512-FCP-NEXT: vmovdqa 32(%r8), %ymm3 +; AVX512-FCP-NEXT: vmovdqu %ymm3, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[27],zero,zero,zero,zero,ymm3[30],zero,ymm3[28],zero,zero,zero,zero,ymm3[31],zero,ymm3[29] +; AVX512-FCP-NEXT: vmovdqa 32(%r9), %ymm2 +; AVX512-FCP-NEXT: vmovdqu %ymm2, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm4 = [128,128,128,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128,128,128,25,128,23,128,128,128,128,26,128,24,128,128] +; AVX512-FCP-NEXT: # ymm4 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm4, %ymm2, %ymm1 +; AVX512-FCP-NEXT: vmovdqa64 %ymm4, %ymm23 ; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 ; AVX512-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm2[27,u,u,u],zero,ymm2[30],zero,ymm2[28,u,u,u],zero,ymm2[31],zero +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [24,25,24,25,128,23,128,23,24,25,26,128,24,128,30,31,24,25,24,25,128,23,128,23,24,25,26,128,24,128,30,31] +; AVX512-FCP-NEXT: # ymm2 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm2, %ymm3, %ymm1 +; AVX512-FCP-NEXT: vmovdqa64 %ymm2, %ymm22 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512-FCP-NEXT: vmovdqa 32(%rax), %ymm1 ; AVX512-FCP-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] ; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] ; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 ; AVX512-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-FCP-NEXT: vmovdqa (%rsi), %ymm1 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,ymm1[14],zero,zero,zero,zero,zero,zero,ymm1[15],zero,zero,zero,zero,zero,zero,ymm1[16],zero,zero,zero,zero,zero,zero,ymm1[17],zero,zero,zero,zero,zero,zero,ymm1[18] -; AVX512-FCP-NEXT: vmovdqa64 %ymm1, %ymm23 -; AVX512-FCP-NEXT: vmovdqa (%rdi), %ymm1 -; AVX512-FCP-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[0,1,14],zero,ymm1[12,13,0,1,14,15],zero,ymm1[3,12,13,2,3,16],zero,ymm1[30,31,28,29,16,17],zero,ymm1[31,18,19,28,29,18],zero +; AVX512-FCP-NEXT: vmovdqa (%rsi), %ymm5 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,ymm5[14],zero,zero,zero,zero,zero,zero,ymm5[15],zero,zero,zero,zero,zero,zero,ymm5[16],zero,zero,zero,zero,zero,zero,ymm5[17],zero,zero,zero,zero,zero,zero,ymm5[18] +; AVX512-FCP-NEXT: vmovdqa (%rdi), %ymm4 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm4[0,1,14],zero,ymm4[12,13,0,1,14,15],zero,ymm4[3,12,13,2,3,16],zero,ymm4[30,31,28,29,16,17],zero,ymm4[31,18,19,28,29,18],zero ; AVX512-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-FCP-NEXT: vmovdqa (%rcx), %ymm1 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm7 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] -; AVX512-FCP-NEXT: vpshufb %ymm7, %ymm1, %ymm0 -; AVX512-FCP-NEXT: vmovdqa64 %ymm1, %ymm26 +; AVX512-FCP-NEXT: vmovdqa (%rcx), %ymm3 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,zero,zero,ymm3[14],zero,zero,zero,zero,zero,zero,ymm3[15],zero,zero,zero,zero,zero,zero,ymm3[16],zero,zero,zero,zero,zero,zero,ymm3[17],zero,zero,zero,zero,zero ; AVX512-FCP-NEXT: vmovdqa (%rdx), %ymm2 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm1 = [0,1,0,1,14,128,14,15,0,1,14,15,128,13,14,15,16,17,16,128,30,31,30,31,16,17,128,31,28,29,30,31] -; AVX512-FCP-NEXT: vpshufb %ymm1, %ymm2, %ymm3 -; AVX512-FCP-NEXT: vpor %ymm0, %ymm3, %ymm0 -; AVX512-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-FCP-NEXT: vmovdqa (%r8), %ymm0 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[0,1,0,1,14],zero,ymm2[14,15,0,1,14,15],zero,ymm2[13,14,15,16,17,16],zero,ymm2[30,31,30,31,16,17],zero,ymm2[31,28,29,30,31] +; AVX512-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm5 = [128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128] -; AVX512-FCP-NEXT: vpshufb %ymm5, %ymm0, %ymm3 -; AVX512-FCP-NEXT: vmovdqa64 %ymm5, %ymm25 -; AVX512-FCP-NEXT: vmovdqa (%r9), %ymm5 -; AVX512-FCP-NEXT: vmovdqu %ymm5, (%rsp) # 32-byte Spill -; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm0 = [13,0,0,0,128,16,128,14,0,0,0,128,17,128,15,0,13,0,0,0,128,16,128,14,0,0,0,128,17,128,15,0] -; AVX512-FCP-NEXT: # ymm0 = mem[0,1,0,1] -; AVX512-FCP-NEXT: vpshufb %ymm0, %ymm5, %ymm5 -; AVX512-FCP-NEXT: vmovdqa64 %ymm0, %ymm30 -; AVX512-FCP-NEXT: vporq %ymm3, %ymm5, %ymm24 -; AVX512-FCP-NEXT: vmovdqa 32(%rdx), %xmm3 -; AVX512-FCP-NEXT: vmovdqa 32(%rcx), %xmm6 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm8 = [u,u,u,128,7,128,5,u,u,u,128,8,128,6,u,u] -; AVX512-FCP-NEXT: vpshufb %xmm8, %xmm6, %xmm5 -; AVX512-FCP-NEXT: vmovdqa64 %xmm6, %xmm28 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm9 = [u,u,u,7,128,5,128,u,u,u,8,128,6,128,u,u] -; AVX512-FCP-NEXT: vpshufb %xmm9, %xmm3, %xmm6 -; AVX512-FCP-NEXT: vmovdqa64 %xmm9, %xmm19 -; AVX512-FCP-NEXT: vmovdqa64 %xmm3, %xmm29 -; AVX512-FCP-NEXT: vpor %xmm5, %xmm6, %xmm3 -; AVX512-FCP-NEXT: vmovdqu64 %zmm3, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-FCP-NEXT: vmovdqa 32(%rdi), %xmm10 -; AVX512-FCP-NEXT: vmovdqa 32(%rsi), %xmm6 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm11 = [u,128,7,128,5,u,u,u,128,8,128,6,u,u,u,128] -; AVX512-FCP-NEXT: vpshufb %xmm11, %xmm6, %xmm5 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm3 = [u,7,128,5,128,u,u,u,8,128,6,128,u,u,u,9] -; AVX512-FCP-NEXT: vpshufb %xmm3, %xmm10, %xmm9 -; AVX512-FCP-NEXT: vmovdqa64 %xmm10, %xmm27 -; AVX512-FCP-NEXT: vpor %xmm5, %xmm9, %xmm5 -; AVX512-FCP-NEXT: vmovdqu64 %zmm5, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-FCP-NEXT: vmovdqa 32(%r9), %xmm15 -; AVX512-FCP-NEXT: vmovdqa 32(%r8), %xmm10 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm5 = [128,4,u,u,u,128,7,128,5,u,u,u,128,8,128,6] -; AVX512-FCP-NEXT: vpshufb %xmm5, %xmm15, %xmm9 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm0 = [4,128,u,u,u,7,128,5,128,u,u,u,8,128,6,128] -; AVX512-FCP-NEXT: vpshufb %xmm0, %xmm10, %xmm12 -; AVX512-FCP-NEXT: vmovdqa64 %xmm0, %xmm21 -; AVX512-FCP-NEXT: vporq %xmm9, %xmm12, %xmm22 -; AVX512-FCP-NEXT: vpshufb %ymm7, %ymm13, %ymm7 -; AVX512-FCP-NEXT: vmovdqa64 %ymm13, %ymm20 -; AVX512-FCP-NEXT: vpshufb %ymm1, %ymm14, %ymm1 -; AVX512-FCP-NEXT: vpor %ymm7, %ymm1, %ymm1 -; AVX512-FCP-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-FCP-NEXT: vmovdqa64 %ymm16, %ymm7 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = zero,zero,zero,ymm7[14],zero,zero,zero,zero,zero,zero,ymm7[15],zero,zero,zero,zero,zero,zero,ymm7[16],zero,zero,zero,zero,zero,zero,ymm7[17],zero,zero,zero,zero,zero,zero,ymm7[18] -; AVX512-FCP-NEXT: vmovdqa64 %ymm17, %ymm7 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm7[0,1,14],zero,ymm7[12,13,0,1,14,15],zero,ymm7[3,12,13,2,3,16],zero,ymm7[30,31,28,29,16,17],zero,ymm7[31,18,19,28,29,18],zero -; AVX512-FCP-NEXT: vpor %ymm1, %ymm7, %ymm1 -; AVX512-FCP-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-FCP-NEXT: vmovdqa64 %ymm18, %ymm1 -; AVX512-FCP-NEXT: vmovdqu64 %ymm18, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-FCP-NEXT: vmovdqa64 %ymm25, %ymm7 -; AVX512-FCP-NEXT: vpshufb %ymm7, %ymm1, %ymm1 -; AVX512-FCP-NEXT: vmovdqa64 %ymm30, %ymm0 -; AVX512-FCP-NEXT: vpshufb %ymm0, %ymm4, %ymm0 -; AVX512-FCP-NEXT: vpor %ymm1, %ymm0, %ymm0 -; AVX512-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-FCP-NEXT: vmovdqa (%rsi), %xmm13 -; AVX512-FCP-NEXT: vpshufb %xmm11, %xmm13, %xmm0 +; AVX512-FCP-NEXT: vmovdqa (%r8), %ymm1 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,zero,zero,zero,zero,ymm1[14],zero,zero,zero,zero,zero,zero,ymm1[15],zero,zero,zero,zero,zero,zero,ymm1[16],zero,zero,zero,zero,zero,zero,ymm1[17],zero,zero,zero,zero +; AVX512-FCP-NEXT: vmovdqa (%r9), %ymm0 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm0[13,u,u,u,u,u],zero,ymm0[14,u,u,u,u,u],zero,ymm0[15,u,u,u,u,u],zero,ymm0[16,u,u,u,u,u],zero,ymm0[17,u,u,u] +; AVX512-FCP-NEXT: vpor %ymm6, %ymm7, %ymm6 +; AVX512-FCP-NEXT: vmovdqu %ymm6, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512-FCP-NEXT: vmovdqa 32(%rdx), %xmm9 +; AVX512-FCP-NEXT: vmovdqa %xmm9, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512-FCP-NEXT: vmovdqa 32(%rcx), %xmm7 +; AVX512-FCP-NEXT: vmovdqa %xmm7, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm6 = [u,u,u,128,7,128,5,u,u,u,128,8,128,6,u,u] +; AVX512-FCP-NEXT: vpshufb %xmm6, %xmm7, %xmm7 +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm8 = [u,u,u,7,128,5,128,u,u,u,8,128,6,128,u,u] +; AVX512-FCP-NEXT: vpshufb %xmm8, %xmm9, %xmm9 +; AVX512-FCP-NEXT: vpor %xmm7, %xmm9, %xmm7 +; AVX512-FCP-NEXT: vmovdqu64 %zmm7, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-FCP-NEXT: vmovdqa 32(%rdi), %xmm11 +; AVX512-FCP-NEXT: vmovdqa %xmm11, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512-FCP-NEXT: vmovdqa 32(%rsi), %xmm9 +; AVX512-FCP-NEXT: vmovdqa %xmm9, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm7 = [u,128,7,128,5,u,u,u,128,8,128,6,u,u,u,128] +; AVX512-FCP-NEXT: vpshufb %xmm7, %xmm9, %xmm9 +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm10 = [u,7,128,5,128,u,u,u,8,128,6,128,u,u,u,9] +; AVX512-FCP-NEXT: vpshufb %xmm10, %xmm11, %xmm11 +; AVX512-FCP-NEXT: vpor %xmm9, %xmm11, %xmm9 +; AVX512-FCP-NEXT: vmovdqu64 %zmm9, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-FCP-NEXT: vmovdqa 32(%r9), %xmm9 +; AVX512-FCP-NEXT: vmovdqa %xmm9, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512-FCP-NEXT: vmovdqa 32(%r8), %xmm14 +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm12 = [128,4,u,u,u,128,7,128,5,u,u,u,128,8,128,6] +; AVX512-FCP-NEXT: vpshufb %xmm12, %xmm9, %xmm9 +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm13 = [4,128,u,u,u,7,128,5,128,u,u,u,8,128,6,128] +; AVX512-FCP-NEXT: vpshufb %xmm13, %xmm14, %xmm11 +; AVX512-FCP-NEXT: vmovdqa64 %xmm14, %xmm30 +; AVX512-FCP-NEXT: vpor %xmm9, %xmm11, %xmm9 +; AVX512-FCP-NEXT: vmovdqu64 %zmm9, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-FCP-NEXT: vmovdqa (%rsi), %xmm9 +; AVX512-FCP-NEXT: vpshufb %xmm7, %xmm9, %xmm7 +; AVX512-FCP-NEXT: vmovdqa64 %xmm9, %xmm26 ; AVX512-FCP-NEXT: vmovdqa (%rdi), %xmm9 -; AVX512-FCP-NEXT: vpshufb %xmm3, %xmm9, %xmm1 -; AVX512-FCP-NEXT: vporq %xmm0, %xmm1, %xmm31 -; AVX512-FCP-NEXT: vmovdqa (%rcx), %xmm14 -; AVX512-FCP-NEXT: vpshufb %xmm8, %xmm14, %xmm0 -; AVX512-FCP-NEXT: vmovdqa (%rdx), %xmm8 -; AVX512-FCP-NEXT: vmovdqa64 %xmm19, %xmm1 -; AVX512-FCP-NEXT: vpshufb %xmm1, %xmm8, %xmm1 -; AVX512-FCP-NEXT: vpor %xmm0, %xmm1, %xmm0 -; AVX512-FCP-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512-FCP-NEXT: vmovdqa (%r9), %xmm1 -; AVX512-FCP-NEXT: vpshufb %xmm5, %xmm1, %xmm0 -; AVX512-FCP-NEXT: vmovdqa %xmm1, %xmm3 -; AVX512-FCP-NEXT: vmovdqa %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512-FCP-NEXT: vmovdqa (%r8), %xmm4 -; AVX512-FCP-NEXT: vmovdqa64 %xmm21, %xmm1 -; AVX512-FCP-NEXT: vpshufb %xmm1, %xmm4, %xmm1 -; AVX512-FCP-NEXT: vmovdqa %xmm4, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512-FCP-NEXT: vpor %xmm0, %xmm1, %xmm0 +; AVX512-FCP-NEXT: vpshufb %xmm10, %xmm9, %xmm10 +; AVX512-FCP-NEXT: vmovdqa64 %xmm9, %xmm21 +; AVX512-FCP-NEXT: vpor %xmm7, %xmm10, %xmm7 +; AVX512-FCP-NEXT: vmovdqa %xmm7, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512-FCP-NEXT: vmovdqa (%rcx), %xmm7 +; AVX512-FCP-NEXT: vpshufb %xmm6, %xmm7, %xmm6 +; AVX512-FCP-NEXT: vmovdqa (%rdx), %xmm10 +; AVX512-FCP-NEXT: vpshufb %xmm8, %xmm10, %xmm8 +; AVX512-FCP-NEXT: vpor %xmm6, %xmm8, %xmm6 +; AVX512-FCP-NEXT: vmovdqa %xmm6, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512-FCP-NEXT: vmovdqa (%r9), %xmm11 +; AVX512-FCP-NEXT: vpshufb %xmm12, %xmm11, %xmm12 +; AVX512-FCP-NEXT: vmovdqa (%r8), %xmm6 +; AVX512-FCP-NEXT: vpshufb %xmm13, %xmm6, %xmm13 +; AVX512-FCP-NEXT: vmovdqa %xmm6, %xmm9 +; AVX512-FCP-NEXT: vporq %xmm12, %xmm13, %xmm31 +; AVX512-FCP-NEXT: vpshufb %ymm15, %ymm4, %ymm12 +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm8 = [128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128] +; AVX512-FCP-NEXT: # ymm8 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm8, %ymm5, %ymm13 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm12, %zmm13, %zmm6 +; AVX512-FCP-NEXT: vmovdqu64 %zmm6, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-FCP-NEXT: vmovdqa64 %ymm27, %ymm6 +; AVX512-FCP-NEXT: vpshufb %ymm6, %ymm5, %ymm12 +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm6 = [18,19,20,21,128,19,128,21,20,21,22,128,20,128,22,23,18,19,20,21,128,19,128,21,20,21,22,128,20,128,22,23] +; AVX512-FCP-NEXT: # ymm6 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm6, %ymm4, %ymm13 +; AVX512-FCP-NEXT: vmovdqa64 %ymm6, %ymm20 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm12, %zmm13, %zmm29 +; AVX512-FCP-NEXT: vmovdqa64 %ymm28, %ymm6 +; AVX512-FCP-NEXT: vpshufb %ymm6, %ymm3, %ymm12 +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm6 = [128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20] +; AVX512-FCP-NEXT: # ymm6 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm6, %ymm3, %ymm13 +; AVX512-FCP-NEXT: vmovdqa64 %ymm6, %ymm16 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm12, %zmm13, %zmm28 +; AVX512-FCP-NEXT: vmovdqa64 %ymm24, %ymm6 +; AVX512-FCP-NEXT: vpshufb %ymm6, %ymm2, %ymm13 +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm12 = [18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128,18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128] +; AVX512-FCP-NEXT: # ymm12 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm12, %ymm2, %ymm15 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm13, %zmm15, %zmm27 +; AVX512-FCP-NEXT: vmovdqa64 %ymm23, %ymm6 +; AVX512-FCP-NEXT: vpshufb %ymm6, %ymm0, %ymm13 +; AVX512-FCP-NEXT: vmovdqa64 %ymm22, %ymm6 +; AVX512-FCP-NEXT: vpshufb %ymm6, %ymm1, %ymm15 +; AVX512-FCP-NEXT: vpor %ymm13, %ymm15, %ymm6 +; AVX512-FCP-NEXT: vmovdqu64 %zmm6, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm6 = [128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22] +; AVX512-FCP-NEXT: # ymm6 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm6, %ymm0, %ymm15 +; AVX512-FCP-NEXT: vmovdqa64 %ymm6, %ymm24 +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm13 = [20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128,20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128] +; AVX512-FCP-NEXT: # ymm13 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vpshufb %ymm13, %ymm1, %ymm14 +; AVX512-FCP-NEXT: vpor %ymm15, %ymm14, %ymm6 +; AVX512-FCP-NEXT: vmovdqu64 %zmm6, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero,ymm5[29],zero,zero,zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,30],zero,ymm4[28],zero,ymm4[30,31,30,31],zero,ymm4[29],zero,ymm4[31,28,29] +; AVX512-FCP-NEXT: vpor %ymm5, %ymm4, %ymm4 +; AVX512-FCP-NEXT: vmovdqu64 %zmm4, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29],zero,zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u,u,u],zero,ymm3[30],zero,ymm3[28,u,u,u],zero,ymm3[31],zero,ymm3[29,u] +; AVX512-FCP-NEXT: vporq %ymm2, %ymm3, %ymm23 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[27],zero,zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm0[27,u,u,u],zero,ymm0[30],zero,ymm0[28,u,u,u],zero,ymm0[31],zero +; AVX512-FCP-NEXT: vporq %ymm1, %ymm0, %ymm22 +; AVX512-FCP-NEXT: vmovdqa64 %ymm19, %ymm2 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,zero,zero,ymm2[14],zero,zero,zero,zero,zero,zero,ymm2[15],zero,zero,zero,zero,zero,zero,ymm2[16],zero,zero,zero,zero,zero,zero,ymm2[17],zero,zero,zero,zero,zero +; AVX512-FCP-NEXT: vmovdqa64 %ymm17, %ymm3 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm3[0,1,0,1,14],zero,ymm3[14,15,0,1,14,15],zero,ymm3[13,14,15,16,17,16],zero,ymm3[30,31,30,31,16,17],zero,ymm3[31,28,29,30,31] +; AVX512-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[23],zero,zero,zero,zero,ymm0[26],zero,ymm0[24],zero,zero,zero,zero,ymm0[27],zero,ymm0[25] -; AVX512-FCP-NEXT: vmovdqa64 %ymm23, %ymm12 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm12[21],zero,ymm12[19],zero,zero,zero,zero,ymm12[22],zero,ymm12[20],zero,zero -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-FCP-NEXT: vmovdqa64 %ymm16, %ymm0 +; AVX512-FCP-NEXT: vpshufb %ymm0, %ymm2, %ymm0 +; AVX512-FCP-NEXT: vpshufb %ymm12, %ymm3, %ymm1 +; AVX512-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX512-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512-FCP-NEXT: vmovdqa64 %ymm18, %ymm3 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,ymm3[14],zero,zero,zero,zero,zero,zero,ymm3[15],zero,zero,zero,zero,zero,zero,ymm3[16],zero,zero,zero,zero,zero,zero,ymm3[17],zero,zero,zero,zero,zero,zero,ymm3[18] +; AVX512-FCP-NEXT: vmovdqa64 %ymm25, %ymm2 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[0,1,14],zero,ymm2[12,13,0,1,14,15],zero,ymm2[3,12,13,2,3,16],zero,ymm2[30,31,28,29,16,17],zero,ymm2[31,18,19,28,29,18],zero +; AVX512-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-FCP-NEXT: vmovdqa64 %ymm26, %ymm11 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm11[25],zero,ymm11[23],zero,zero,zero,zero,ymm11[26],zero,ymm11[24],zero,zero,zero,zero -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm11[18],zero,zero,zero,zero,ymm11[21],zero,ymm11[19],zero,zero,zero,zero,ymm11[22],zero,ymm11[20] -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-FCP-NEXT: vpshufb %ymm8, %ymm3, %ymm0 +; AVX512-FCP-NEXT: vmovdqa64 %ymm20, %ymm1 +; AVX512-FCP-NEXT: vpshufb %ymm1, %ymm2, %ymm1 +; AVX512-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX512-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm3 # 32-byte Reload +; AVX512-FCP-NEXT: vmovdqa64 %ymm24, %ymm0 +; AVX512-FCP-NEXT: vpshufb %ymm0, %ymm3, %ymm0 +; AVX512-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload +; AVX512-FCP-NEXT: vpshufb %ymm13, %ymm2, %ymm1 +; AVX512-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [24,25,128,23,128,21,22,23,26,128,24,128,28,29,26,27,24,25,128,23,128,21,22,23,26,128,24,128,28,29,26,27] -; AVX512-FCP-NEXT: # ymm1 = mem[0,1,0,1] -; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm5 = [18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128,18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128] -; AVX512-FCP-NEXT: # ymm5 = mem[0,1,0,1] -; AVX512-FCP-NEXT: vpshufb %ymm1, %ymm2, %ymm0 -; AVX512-FCP-NEXT: vmovdqa64 %ymm1, %ymm19 -; AVX512-FCP-NEXT: vpshufb %ymm5, %ymm2, %ymm1 -; AVX512-FCP-NEXT: vmovdqa64 %ymm5, %ymm30 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,zero,zero,zero,ymm2[14],zero,zero,zero,zero,zero,zero,ymm2[15],zero,zero,zero,zero,zero,zero,ymm2[16],zero,zero,zero,zero,zero,zero,ymm2[17],zero,zero,zero,zero +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm3[13,u,u,u,u,u],zero,ymm3[14,u,u,u,u,u],zero,ymm3[15,u,u,u,u,u],zero,ymm3[16,u,u,u,u,u],zero,ymm3[17,u,u,u] +; AVX512-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm24, %zmm0, %zmm0 -; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm4[8],xmm3[8],xmm4[9],xmm3[9],xmm4[10],xmm3[10],xmm4[11],xmm3[11],xmm4[12],xmm3[12],xmm4[13],xmm3[13],xmm4[14],xmm3[14],xmm4[15],xmm3[15] -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm3 = [u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] -; AVX512-FCP-NEXT: vpshufb %xmm3, %xmm1, %xmm1 +; AVX512-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm0, %zmm0 # 32-byte Folded Reload +; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm9[8],xmm11[8],xmm9[9],xmm11[9],xmm9[10],xmm11[10],xmm9[11],xmm11[11],xmm9[12],xmm11[12],xmm9[13],xmm11[13],xmm9[14],xmm11[14],xmm9[15],xmm11[15] +; AVX512-FCP-NEXT: vmovdqa %xmm9, %xmm8 +; AVX512-FCP-NEXT: vmovdqa64 %xmm11, %xmm17 +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm9 = [u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] +; AVX512-FCP-NEXT: vpshufb %xmm9, %xmm1, %xmm1 ; AVX512-FCP-NEXT: vshufi64x2 {{.*#+}} zmm0 = zmm1[0,1,0,1],zmm0[4,5,6,7] ; AVX512-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [2,2,3,3,2,2,3,3] -; AVX512-FCP-NEXT: # ymm1 = mem[0,1,0,1] +; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm6 = [2,2,3,3,2,2,3,3] +; AVX512-FCP-NEXT: # ymm6 = mem[0,1,0,1] ; AVX512-FCP-NEXT: vmovdqa (%rax), %xmm0 -; AVX512-FCP-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512-FCP-NEXT: vpshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,4,5,5,6] -; AVX512-FCP-NEXT: vpermd %ymm0, %ymm1, %ymm0 -; AVX512-FCP-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 -; AVX512-FCP-NEXT: vmovdqa (%rax), %ymm4 -; AVX512-FCP-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} ymm5 = [128,13,128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128] -; AVX512-FCP-NEXT: vpshufb %ymm5, %ymm4, %ymm4 -; AVX512-FCP-NEXT: vmovdqa64 %ymm5, %ymm18 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm0, %zmm24 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29],zero,zero -; AVX512-FCP-NEXT: vmovdqa64 %ymm0, %ymm23 -; AVX512-FCP-NEXT: vpbroadcastq {{.*#+}} ymm2 = [13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14] -; AVX512-FCP-NEXT: vmovdqu (%rsp), %ymm0 # 32-byte Reload -; AVX512-FCP-NEXT: vpshufb %ymm2, %ymm0, %ymm0 -; AVX512-FCP-NEXT: vmovdqa64 %ymm2, %ymm25 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX512-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[27],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] -; AVX512-FCP-NEXT: vbroadcasti32x4 {{.*#+}} ymm26 = [18374967954648269055,71777218572844800,18374967954648269055,71777218572844800] -; AVX512-FCP-NEXT: # ymm26 = mem[0,1,2,3,0,1,2,3] -; AVX512-FCP-NEXT: vpternlogq $248, %ymm26, %ymm0, %ymm2 -; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm10[0],xmm15[0],xmm10[1],xmm15[1],xmm10[2],xmm15[2],xmm10[3],xmm15[3],xmm10[4],xmm15[4],xmm10[5],xmm15[5],xmm10[6],xmm15[6],xmm10[7],xmm15[7] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] -; AVX512-FCP-NEXT: vshufi64x2 {{.*#+}} zmm21 = zmm2[0,1,2,3],zmm0[0,1,0,1] -; AVX512-FCP-NEXT: vmovdqa64 %xmm29, %xmm0 -; AVX512-FCP-NEXT: vmovdqa64 %xmm28, %xmm2 -; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm7 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3],xmm0[4],xmm2[4],xmm0[5],xmm2[5],xmm0[6],xmm2[6],xmm0[7],xmm2[7] -; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm0 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] -; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm14[8],xmm8[8],xmm14[9],xmm8[9],xmm14[10],xmm8[10],xmm14[11],xmm8[11],xmm14[12],xmm8[12],xmm14[13],xmm8[13],xmm14[14],xmm8[14],xmm14[15],xmm8[15] -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm4 = [6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] -; AVX512-FCP-NEXT: vpshufb %xmm4, %xmm2, %xmm2 -; AVX512-FCP-NEXT: vmovdqu %ymm2, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-FCP-NEXT: vpshufb %xmm4, %xmm0, %xmm0 -; AVX512-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Reload -; AVX512-FCP-NEXT: vinserti32x4 $2, %xmm0, %zmm2, %zmm28 -; AVX512-FCP-NEXT: vmovdqa64 %xmm27, %xmm0 -; AVX512-FCP-NEXT: vmovdqa %xmm6, %xmm2 -; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm6 = xmm0[0],xmm6[0],xmm0[1],xmm6[1],xmm0[2],xmm6[2],xmm0[3],xmm6[3],xmm0[4],xmm6[4],xmm0[5],xmm6[5],xmm0[6],xmm6[6],xmm0[7],xmm6[7] -; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] -; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm13[8],xmm9[8],xmm13[9],xmm9[9],xmm13[10],xmm9[10],xmm13[11],xmm9[11],xmm13[12],xmm9[12],xmm13[13],xmm9[13],xmm13[14],xmm9[14],xmm13[15],xmm9[15] -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm5 = [2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] -; AVX512-FCP-NEXT: vpshufb %xmm5, %xmm4, %xmm0 -; AVX512-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-FCP-NEXT: vpshufb %xmm5, %xmm2, %xmm2 -; AVX512-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm0 # 64-byte Reload -; AVX512-FCP-NEXT: vinserti32x4 $2, %xmm2, %zmm0, %zmm27 -; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm10[8],xmm15[8],xmm10[9],xmm15[9],xmm10[10],xmm15[10],xmm10[11],xmm15[11],xmm10[12],xmm15[12],xmm10[13],xmm15[13],xmm10[14],xmm15[14],xmm10[15],xmm15[15] -; AVX512-FCP-NEXT: vpshufb %xmm3, %xmm2, %xmm2 -; AVX512-FCP-NEXT: vshufi64x2 {{.*#+}} zmm0 = zmm22[0,1,0,1],zmm2[0,1,0,1] -; AVX512-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-FCP-NEXT: vmovdqa 32(%rax), %xmm0 -; AVX512-FCP-NEXT: vpshufhw {{.*#+}} xmm2 = xmm0[0,1,2,3,4,5,5,6] -; AVX512-FCP-NEXT: vmovdqa64 %xmm0, %xmm29 -; AVX512-FCP-NEXT: vpermd %ymm2, %ymm1, %ymm0 -; AVX512-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512-FCP-NEXT: vpbroadcastq {{.*#+}} ymm1 = [11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12] -; AVX512-FCP-NEXT: vpshufb %ymm1, %ymm11, %ymm5 -; AVX512-FCP-NEXT: vmovdqa64 %ymm20, %ymm0 -; AVX512-FCP-NEXT: vpshufb %ymm1, %ymm0, %ymm1 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm22 = ymm1[2,3,2,3] -; AVX512-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload -; AVX512-FCP-NEXT: vmovdqa64 %ymm19, %ymm1 -; AVX512-FCP-NEXT: vpshufb %ymm1, %ymm2, %ymm1 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm20 = ymm1[2,3,2,3] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[18],zero,zero,zero,zero,ymm0[21],zero,ymm0[19],zero,zero,zero,zero,ymm0[22],zero,ymm0[20] -; AVX512-FCP-NEXT: vmovdqa64 %ymm30, %ymm0 -; AVX512-FCP-NEXT: vpshufb %ymm0, %ymm2, %ymm4 -; AVX512-FCP-NEXT: vpbroadcastq {{.*#+}} ymm2 = [9,8,7,0,0,0,11,10,9,8,7,0,0,0,11,10,9,8,7,0,0,0,11,10,9,8,7,0,0,0,11,10] -; AVX512-FCP-NEXT: vmovdqa64 %ymm16, %ymm0 -; AVX512-FCP-NEXT: vpshufb %ymm2, %ymm0, %ymm1 -; AVX512-FCP-NEXT: vmovdqa64 %ymm2, %ymm30 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm19 = ymm1[2,3,2,3] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm0[21],zero,ymm0[19],zero,zero,zero,zero,ymm0[22],zero,ymm0[20],zero,zero -; AVX512-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX512-FCP-NEXT: vmovdqa64 %ymm18, %ymm1 -; AVX512-FCP-NEXT: vpshufb %ymm1, %ymm0, %ymm3 -; AVX512-FCP-NEXT: vpshuflw {{.*#+}} ymm0 = ymm0[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] -; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} ymm1 = [4,5,4,5,5,7,4,5] -; AVX512-FCP-NEXT: vpermd %ymm0, %ymm1, %ymm0 -; AVX512-FCP-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm3, %zmm16 -; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm9[0],xmm13[0],xmm9[1],xmm13[1],xmm9[2],xmm13[2],xmm9[3],xmm13[3],xmm9[4],xmm13[4],xmm9[5],xmm13[5],xmm9[6],xmm13[6],xmm9[7],xmm13[7] -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm9 = [0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] -; AVX512-FCP-NEXT: vpshufb %xmm9, %xmm6, %xmm6 -; AVX512-FCP-NEXT: vpshufb %xmm9, %xmm0, %xmm0 -; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm9 = [28,29,30,128,28,128,30,31,30,31,128,29,128,31,28,29,28,29,30,128,28,128,30,31,30,31,128,29,128,31,28,29] -; AVX512-FCP-NEXT: # ymm9 = mem[0,1,0,1] -; AVX512-FCP-NEXT: vmovdqa64 %ymm17, %ymm3 -; AVX512-FCP-NEXT: vpshufb %ymm9, %ymm3, %ymm15 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm17 = ymm15[2,3,2,3] -; AVX512-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm1 # 32-byte Reload -; AVX512-FCP-NEXT: vmovdqa64 %ymm25, %ymm2 -; AVX512-FCP-NEXT: vpshufb %ymm2, %ymm1, %ymm13 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm18 = ymm13[2,3,2,3] -; AVX512-FCP-NEXT: vinserti32x4 $2, %xmm31, %zmm0, %zmm0 -; AVX512-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm8[0],xmm14[0],xmm8[1],xmm14[1],xmm8[2],xmm14[2],xmm8[3],xmm14[3],xmm8[4],xmm14[4],xmm8[5],xmm14[5],xmm8[6],xmm14[6],xmm8[7],xmm14[7] -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm8 = [4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] -; AVX512-FCP-NEXT: vpshufb %xmm8, %xmm7, %xmm7 -; AVX512-FCP-NEXT: vpshufb %xmm8, %xmm0, %xmm13 -; AVX512-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,ymm0[23],zero,ymm0[23,24,25,26],zero,ymm0[24],zero,ymm0[30,31] +; AVX512-FCP-NEXT: vpshufhw {{.*#+}} xmm1 = xmm0[0,1,2,3,4,5,5,6] +; AVX512-FCP-NEXT: vmovdqa64 %xmm0, %xmm19 +; AVX512-FCP-NEXT: vpermd %ymm1, %ymm6, %ymm1 +; AVX512-FCP-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm3 +; AVX512-FCP-NEXT: vmovdqa (%rax), %ymm12 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm5 = zero,ymm12[13],zero,zero,zero,zero,zero,zero,ymm12[14],zero,zero,zero,zero,zero,zero,ymm12[15],zero,zero,zero,zero,zero,zero,ymm12[16],zero,zero,zero,zero,zero,zero,ymm12[17],zero,zero +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm5, %zmm3, %zmm20 +; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm7[8],xmm10[8],xmm7[9],xmm10[9],xmm7[10],xmm10[10],xmm7[11],xmm10[11],xmm7[12],xmm10[12],xmm7[13],xmm10[13],xmm7[14],xmm10[14],xmm7[15],xmm10[15] +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm1 = [6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] +; AVX512-FCP-NEXT: vpshufb %xmm1, %xmm5, %xmm0 ; AVX512-FCP-NEXT: vmovdqa64 %ymm0, %ymm25 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm15 = ymm8[2,3,2,3] -; AVX512-FCP-NEXT: vmovdqa %ymm12, %ymm1 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm12[30],zero,ymm12[28],zero,zero,zero,zero,ymm12[31],zero,ymm12[29],zero,zero,zero -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] -; AVX512-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload -; AVX512-FCP-NEXT: vpshufb %ymm9, %ymm2, %ymm9 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,3,2,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[0,1,0,1] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,3,2,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm23[2,3,2,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[0,1,0,1] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,2,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm11[2,3,2,3] -; AVX512-FCP-NEXT: vinserti32x4 $2, {{[-0-9]+}}(%r{{[sb]}}p), %zmm13, %zmm31 # 16-byte Folded Reload -; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm11 = [18,19,20,21,128,19,128,21,20,21,22,128,20,128,22,23,18,19,20,21,128,19,128,21,20,21,22,128,20,128,22,23] -; AVX512-FCP-NEXT: # ymm11 = mem[0,1,0,1] -; AVX512-FCP-NEXT: vpshufb %ymm11, %ymm3, %ymm14 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm14 = ymm14[2,3,2,3] -; AVX512-FCP-NEXT: vmovdqa64 %ymm30, %ymm3 -; AVX512-FCP-NEXT: vpshufb %ymm3, %ymm1, %ymm13 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] -; AVX512-FCP-NEXT: vpshufb %ymm11, %ymm2, %ymm1 -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512-FCP-NEXT: vpor %ymm12, %ymm9, %ymm9 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm6, %zmm9, %zmm6 -; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm9 = [18374966859431673855,18446463693966278655,18374966859431673855,18446463693966278655] -; AVX512-FCP-NEXT: # ymm9 = mem[0,1,0,1] -; AVX512-FCP-NEXT: vpternlogq $248, %ymm9, %ymm5, %ymm0 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm0, %zmm7 -; AVX512-FCP-NEXT: vmovdqa64 {{.*#+}} zmm0 = [255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255] -; AVX512-FCP-NEXT: vpternlogq $226, %zmm6, %zmm0, %zmm7 -; AVX512-FCP-NEXT: vpor %ymm4, %ymm10, %ymm4 +; AVX512-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm11 # 16-byte Reload +; AVX512-FCP-NEXT: vmovdqa64 {{[-0-9]+}}(%r{{[sb]}}p), %xmm16 # 16-byte Reload +; AVX512-FCP-NEXT: vmovdqa64 %xmm16, %xmm2 +; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm11[8],xmm2[8],xmm11[9],xmm2[9],xmm11[10],xmm2[10],xmm11[11],xmm2[11],xmm11[12],xmm2[12],xmm11[13],xmm2[13],xmm11[14],xmm2[14],xmm11[15],xmm2[15] +; AVX512-FCP-NEXT: vpshufb %xmm1, %xmm5, %xmm1 ; AVX512-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Reload -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm2, %zmm4 -; AVX512-FCP-NEXT: vpor %ymm8, %ymm14, %ymm2 +; AVX512-FCP-NEXT: vinserti32x4 $2, %xmm1, %zmm2, %zmm18 +; AVX512-FCP-NEXT: vmovdqa64 %xmm26, %xmm2 +; AVX512-FCP-NEXT: vmovdqa64 %xmm21, %xmm0 +; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm1 = [2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] +; AVX512-FCP-NEXT: vpshufb %xmm1, %xmm5, %xmm3 +; AVX512-FCP-NEXT: vmovdqa64 %ymm3, %ymm21 +; AVX512-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm14 # 16-byte Reload +; AVX512-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm4 # 16-byte Reload +; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm13 = xmm14[8],xmm4[8],xmm14[9],xmm4[9],xmm14[10],xmm4[10],xmm14[11],xmm4[11],xmm14[12],xmm4[12],xmm14[13],xmm4[13],xmm14[14],xmm4[14],xmm14[15],xmm4[15] +; AVX512-FCP-NEXT: vpshufb %xmm1, %xmm13, %xmm1 ; AVX512-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm5 -; AVX512-FCP-NEXT: vpternlogq $226, %zmm4, %zmm0, %zmm5 -; AVX512-FCP-NEXT: vpandq %ymm9, %ymm22, %ymm0 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm20, %zmm0 -; AVX512-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Folded Reload -; AVX512-FCP-NEXT: # zmm2 = mem[2,3,2,3,6,7,6,7] -; AVX512-FCP-NEXT: vporq %zmm2, %zmm0, %zmm0 -; AVX512-FCP-NEXT: vpandq %ymm26, %ymm19, %ymm2 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm17, %zmm2, %zmm2 -; AVX512-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm4 # 64-byte Folded Reload -; AVX512-FCP-NEXT: # zmm4 = mem[2,3,2,3,6,7,6,7] -; AVX512-FCP-NEXT: vporq %zmm4, %zmm2, %zmm2 -; AVX512-FCP-NEXT: vpternlogq $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm2 -; AVX512-FCP-NEXT: vpandq %ymm26, %ymm18, %ymm0 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm15, %zmm0 -; AVX512-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm4 # 64-byte Folded Reload -; AVX512-FCP-NEXT: # zmm4 = mem[2,3,2,3,6,7,6,7] -; AVX512-FCP-NEXT: vporq %zmm4, %zmm0, %zmm0 -; AVX512-FCP-NEXT: vmovdqa64 {{.*#+}} zmm4 = [255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255] -; AVX512-FCP-NEXT: vpternlogq $184, %zmm2, %zmm4, %zmm0 -; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm2 = zmm28[0,1,0,1,4,5,4,5] -; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm8 = zmm27[0,1,0,1,4,5,4,5] -; AVX512-FCP-NEXT: vpternlogq $226, %zmm2, %zmm4, %zmm8 -; AVX512-FCP-NEXT: vpandq %ymm26, %ymm13, %ymm2 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm1, %zmm1 -; AVX512-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Folded Reload -; AVX512-FCP-NEXT: # zmm2 = mem[2,3,2,3,6,7,6,7] -; AVX512-FCP-NEXT: vporq %zmm2, %zmm1, %zmm1 -; AVX512-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Folded Reload -; AVX512-FCP-NEXT: # zmm2 = mem[2,3,2,3,6,7,6,7] -; AVX512-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm6 # 64-byte Folded Reload -; AVX512-FCP-NEXT: # zmm6 = mem[2,3,2,3,6,7,6,7] -; AVX512-FCP-NEXT: vporq %zmm2, %zmm6, %zmm9 -; AVX512-FCP-NEXT: vpternlogq $226, %zmm1, %zmm4, %zmm9 -; AVX512-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload -; AVX512-FCP-NEXT: vpunpcklbw {{[-0-9]+}}(%r{{[sb]}}p), %xmm1, %xmm1 # 16-byte Folded Reload -; AVX512-FCP-NEXT: # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1],xmm1[2],mem[2],xmm1[3],mem[3],xmm1[4],mem[4],xmm1[5],mem[5],xmm1[6],mem[6],xmm1[7],mem[7] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} xmm1 = xmm1[u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] -; AVX512-FCP-NEXT: vshufi64x2 $0, {{[-0-9]+}}(%r{{[sb]}}p), %zmm1, %zmm18 # 64-byte Folded Reload -; AVX512-FCP-NEXT: # zmm18 = zmm1[0,1,0,1],mem[0,1,0,1] -; AVX512-FCP-NEXT: vmovdqa64 %xmm29, %xmm3 -; AVX512-FCP-NEXT: vpshuflw {{.*#+}} xmm2 = xmm3[1,1,0,0,4,5,6,7] -; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} ymm4 = [0,1,0,1,2,0,0,1] -; AVX512-FCP-NEXT: vpermd %ymm2, %ymm4, %ymm19 -; AVX512-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload -; AVX512-FCP-NEXT: vpshuflw {{.*#+}} xmm6 = xmm1[1,1,0,0,4,5,6,7] -; AVX512-FCP-NEXT: vpermd %ymm6, %ymm4, %ymm17 -; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm6 = [4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] -; AVX512-FCP-NEXT: vpshufb %xmm6, %xmm3, %xmm10 -; AVX512-FCP-NEXT: vpshufb %xmm6, %xmm1, %xmm6 -; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm11 = [128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22] -; AVX512-FCP-NEXT: # ymm11 = mem[0,1,0,1] -; AVX512-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm1 # 32-byte Reload -; AVX512-FCP-NEXT: vpshufb %ymm11, %ymm1, %ymm12 -; AVX512-FCP-NEXT: vmovdqu (%rsp), %ymm1 # 32-byte Reload -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm13 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm1[25],zero,ymm1[23],zero,zero,zero,zero,ymm1[26],zero,ymm1[24],zero,zero -; AVX512-FCP-NEXT: vpshufb %ymm11, %ymm1, %ymm11 -; AVX512-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm14 = [20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128,20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128] -; AVX512-FCP-NEXT: # ymm14 = mem[0,1,0,1] -; AVX512-FCP-NEXT: vmovdqa64 %ymm25, %ymm1 -; AVX512-FCP-NEXT: vpshufb %ymm14, %ymm1, %ymm15 -; AVX512-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,ymm2[23],zero,ymm2[23,24,25,26],zero,ymm2[24],zero,ymm2[30,31] -; AVX512-FCP-NEXT: vpshufb %ymm14, %ymm2, %ymm14 -; AVX512-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm3 # 32-byte Reload -; AVX512-FCP-NEXT: vpshuflw {{.*#+}} ymm4 = ymm3[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] -; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} ymm2 = [4,5,4,5,5,7,4,5] -; AVX512-FCP-NEXT: vpermd %ymm4, %ymm2, %ymm20 -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] -; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] -; AVX512-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm22 # 64-byte Folded Reload -; AVX512-FCP-NEXT: # zmm22 = mem[2,3,2,3,6,7,6,7] -; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm22 -; AVX512-FCP-NEXT: vpermq $68, {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Folded Reload -; AVX512-FCP-NEXT: # ymm0 = mem[0,1,0,1] -; AVX512-FCP-NEXT: vpermq $68, {{[-0-9]+}}(%r{{[sb]}}p), %ymm23 # 32-byte Folded Reload -; AVX512-FCP-NEXT: # ymm23 = mem[0,1,0,1] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[0,0,1,0] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,3,2,3] +; AVX512-FCP-NEXT: vinserti32x4 $2, %xmm1, %zmm3, %zmm13 +; AVX512-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm15 # 16-byte Reload +; AVX512-FCP-NEXT: vmovdqa64 %xmm30, %xmm5 +; AVX512-FCP-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm5[8],xmm15[8],xmm5[9],xmm15[9],xmm5[10],xmm15[10],xmm5[11],xmm15[11],xmm5[12],xmm15[12],xmm5[13],xmm15[13],xmm5[14],xmm15[14],xmm5[15],xmm15[15] +; AVX512-FCP-NEXT: vpshufb %xmm9, %xmm1, %xmm1 +; AVX512-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload +; AVX512-FCP-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm3[0,1,0,1],zmm1[0,1,0,1] +; AVX512-FCP-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512-FCP-NEXT: vmovdqa 32(%rax), %xmm3 +; AVX512-FCP-NEXT: vpshufhw {{.*#+}} xmm1 = xmm3[0,1,2,3,4,5,5,6] +; AVX512-FCP-NEXT: vpermd %ymm1, %ymm6, %ymm26 +; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3],xmm0[4],xmm2[4],xmm0[5],xmm2[5],xmm0[6],xmm2[6],xmm0[7],xmm2[7] +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm1 = [0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] +; AVX512-FCP-NEXT: vpshufb %xmm1, %xmm0, %xmm0 +; AVX512-FCP-NEXT: vinserti32x4 $2, {{[-0-9]+}}(%r{{[sb]}}p), %zmm0, %zmm24 # 16-byte Folded Reload +; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm9 = xmm10[0],xmm7[0],xmm10[1],xmm7[1],xmm10[2],xmm7[2],xmm10[3],xmm7[3],xmm10[4],xmm7[4],xmm10[5],xmm7[5],xmm10[6],xmm7[6],xmm10[7],xmm7[7] +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm0 = [4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] +; AVX512-FCP-NEXT: vpshufb %xmm0, %xmm9, %xmm9 +; AVX512-FCP-NEXT: vinserti32x4 $2, {{[-0-9]+}}(%r{{[sb]}}p), %zmm9, %zmm9 # 16-byte Folded Reload +; AVX512-FCP-NEXT: vmovdqa64 %xmm17, %xmm2 +; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm8 = xmm8[0],xmm2[0],xmm8[1],xmm2[1],xmm8[2],xmm2[2],xmm8[3],xmm2[3],xmm8[4],xmm2[4],xmm8[5],xmm2[5],xmm8[6],xmm2[6],xmm8[7],xmm2[7] +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm6 = [u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] +; AVX512-FCP-NEXT: vpshufb %xmm6, %xmm8, %xmm8 +; AVX512-FCP-NEXT: vshufi64x2 {{.*#+}} zmm8 = zmm8[0,1,0,1],zmm31[0,1,0,1] +; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm14 = xmm4[0],xmm14[0],xmm4[1],xmm14[1],xmm4[2],xmm14[2],xmm4[3],xmm14[3],xmm4[4],xmm14[4],xmm4[5],xmm14[5],xmm4[6],xmm14[6],xmm4[7],xmm14[7] +; AVX512-FCP-NEXT: vpshufb %xmm1, %xmm14, %xmm1 +; AVX512-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm14 # 64-byte Folded Reload +; AVX512-FCP-NEXT: # zmm14 = mem[2,3,2,3,6,7,6,7] +; AVX512-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm31 # 64-byte Folded Reload +; AVX512-FCP-NEXT: # zmm31 = mem[2,3,2,3,6,7,6,7] +; AVX512-FCP-NEXT: vporq %zmm14, %zmm31, %zmm14 +; AVX512-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm31 # 64-byte Folded Reload +; AVX512-FCP-NEXT: # zmm31 = mem[2,3,2,3,6,7,6,7] +; AVX512-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm30 # 64-byte Folded Reload +; AVX512-FCP-NEXT: # zmm30 = mem[2,3,2,3,6,7,6,7] +; AVX512-FCP-NEXT: vporq %zmm31, %zmm30, %zmm30 +; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm14, %zmm30 +; AVX512-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm14 # 64-byte Folded Reload +; AVX512-FCP-NEXT: # zmm14 = mem[2,3,2,3,6,7,6,7] +; AVX512-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm31 # 64-byte Folded Reload +; AVX512-FCP-NEXT: # zmm31 = mem[2,3,2,3,6,7,6,7] +; AVX512-FCP-NEXT: vporq %zmm14, %zmm31, %zmm14 +; AVX512-FCP-NEXT: vmovdqa64 {{.*#+}} zmm31 = [255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255] +; AVX512-FCP-NEXT: vpternlogq $184, %zmm30, %zmm31, %zmm14 +; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm7 = zmm18[0,1,0,1,4,5,4,5] +; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm13 = zmm13[0,1,0,1,4,5,4,5] +; AVX512-FCP-NEXT: vpternlogq $226, %zmm7, %zmm31, %zmm13 +; AVX512-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm7 # 64-byte Folded Reload +; AVX512-FCP-NEXT: # zmm7 = mem[2,3,2,3,6,7,6,7] +; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm29 = zmm29[2,3,2,3,6,7,6,7] +; AVX512-FCP-NEXT: vporq %zmm7, %zmm29, %zmm7 +; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm28 = zmm28[2,3,2,3,6,7,6,7] +; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm27 = zmm27[2,3,2,3,6,7,6,7] +; AVX512-FCP-NEXT: vporq %zmm28, %zmm27, %zmm27 +; AVX512-FCP-NEXT: vpternlogq $226, %zmm7, %zmm31, %zmm27 +; AVX512-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Reload +; AVX512-FCP-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm2[2,3,2,3],zmm1[0,1,0,1] +; AVX512-FCP-NEXT: vmovdqa64 %xmm16, %xmm2 +; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm7 = xmm2[0],xmm11[0],xmm2[1],xmm11[1],xmm2[2],xmm11[2],xmm2[3],xmm11[3],xmm2[4],xmm11[4],xmm2[5],xmm11[5],xmm2[6],xmm11[6],xmm2[7],xmm11[7] +; AVX512-FCP-NEXT: vpshufb %xmm0, %xmm7, %xmm7 +; AVX512-FCP-NEXT: vshufi64x2 {{.*#+}} zmm7 = zmm23[2,3,2,3],zmm7[0,1,0,1] +; AVX512-FCP-NEXT: vpunpcklbw {{.*#+}} xmm10 = xmm5[0],xmm15[0],xmm5[1],xmm15[1],xmm5[2],xmm15[2],xmm5[3],xmm15[3],xmm5[4],xmm15[4],xmm5[5],xmm15[5],xmm5[6],xmm15[6],xmm5[7],xmm15[7] +; AVX512-FCP-NEXT: vpshufb %xmm6, %xmm10, %xmm10 +; AVX512-FCP-NEXT: vshufi64x2 {{.*#+}} zmm22 = zmm22[2,3,2,3],zmm10[0,1,0,1] +; AVX512-FCP-NEXT: vmovdqa64 %xmm19, %xmm2 +; AVX512-FCP-NEXT: vpshuflw {{.*#+}} xmm11 = xmm2[1,1,0,0,4,5,6,7] +; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} ymm17 = [0,1,0,1,2,0,0,1] +; AVX512-FCP-NEXT: vpermd %ymm11, %ymm17, %ymm28 +; AVX512-FCP-NEXT: vmovdqa {{.*#+}} xmm0 = [4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] +; AVX512-FCP-NEXT: vpshufb %xmm0, %xmm2, %xmm6 +; AVX512-FCP-NEXT: vpshufb %xmm0, %xmm3, %xmm0 +; AVX512-FCP-NEXT: vpshuflw {{.*#+}} xmm4 = xmm3[1,1,0,0,4,5,6,7] +; AVX512-FCP-NEXT: vpermd %ymm4, %ymm17, %ymm17 +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] +; AVX512-FCP-NEXT: vpshuflw {{.*#+}} ymm2 = ymm12[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] +; AVX512-FCP-NEXT: vpmovsxbd {{.*#+}} ymm23 = [4,5,4,5,5,7,4,5] +; AVX512-FCP-NEXT: vpermd %ymm2, %ymm23, %ymm2 +; AVX512-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm15 # 32-byte Reload +; AVX512-FCP-NEXT: vpshufb {{.*#+}} ymm11 = zero,ymm15[13],zero,zero,zero,zero,zero,zero,ymm15[14],zero,zero,zero,zero,zero,zero,ymm15[15],zero,zero,zero,zero,zero,zero,ymm15[16],zero,zero,zero,zero,zero,zero,ymm15[17],zero,zero +; AVX512-FCP-NEXT: vpshuflw {{.*#+}} ymm15 = ymm15[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] +; AVX512-FCP-NEXT: vpermd %ymm15, %ymm23, %ymm15 +; AVX512-FCP-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm15, %ymm15 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm15, %zmm11, %zmm11 +; AVX512-FCP-NEXT: vmovdqa64 {{.*#+}} zmm15 = [255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255] +; AVX512-FCP-NEXT: vpternlogq $226, %zmm1, %zmm15, %zmm7 +; AVX512-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %ymm1 # 32-byte Folded Reload +; AVX512-FCP-NEXT: # ymm1 = mem[2,3,2,3] +; AVX512-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm3, %zmm1 +; AVX512-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %ymm18 # 32-byte Folded Reload +; AVX512-FCP-NEXT: # ymm18 = mem[2,3,2,3] +; AVX512-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm18, %zmm3, %zmm18 +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm21[0,1,0,1] +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm19 = ymm25[0,1,0,1] +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,0,1,0] ; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[0,0,1,0] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] -; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm14 = ymm14[2,3,2,3] +; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] ; AVX512-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,2,3] -; AVX512-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm0, %zmm0 # 32-byte Folded Reload -; AVX512-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm23, %zmm23 # 32-byte Folded Reload -; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm23 -; AVX512-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm0 # 64-byte Reload -; AVX512-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm24 -; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm23, %zmm24 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm19, %zmm2, %zmm0 -; AVX512-FCP-NEXT: vpternlogd $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm21 -; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm7, %zmm21 -; AVX512-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm10, %zmm0 # 32-byte Folded Reload -; AVX512-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Reload -; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm0 -; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm8, %zmm0 -; AVX512-FCP-NEXT: vpor %ymm12, %ymm15, %ymm2 -; AVX512-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm7 # 64-byte Reload -; AVX512-FCP-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm7[0,1,2,3],zmm2[0,1,2,3] -; AVX512-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm16 -; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm16 -; AVX512-FCP-NEXT: vpermq $68, {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Folded Reload -; AVX512-FCP-NEXT: # zmm2 = mem[0,1,0,1,4,5,4,5] -; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm5 = zmm31[0,1,0,1,4,5,4,5] -; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm5 -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm6, %zmm17, %zmm2 -; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm18, %zmm2 -; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm2 -; AVX512-FCP-NEXT: vpor %ymm1, %ymm13, %ymm1 -; AVX512-FCP-NEXT: vpor %ymm11, %ymm14, %ymm5 -; AVX512-FCP-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm5[0,1,2,3],zmm1[0,1,2,3] -; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm20, %zmm4 -; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm4 -; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm9, %zmm4 +; AVX512-FCP-NEXT: vpternlogq $226, %zmm1, %zmm15, %zmm18 +; AVX512-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm1 # 64-byte Folded Reload +; AVX512-FCP-NEXT: # zmm1 = mem[2,3,2,3,6,7,6,7] +; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm14, %zmm1 +; AVX512-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm5, %zmm5 # 32-byte Folded Reload +; AVX512-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm19, %zmm14 # 32-byte Folded Reload +; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm14 +; AVX512-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload +; AVX512-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm3, %zmm20 +; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm14, %zmm20 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm26, %zmm0, %zmm0 +; AVX512-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload +; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm3, %zmm0 +; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm13, %zmm0 +; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm5 = zmm24[0,1,0,1,4,5,4,5] +; AVX512-FCP-NEXT: vpermq {{.*#+}} zmm9 = zmm9[0,1,0,1,4,5,4,5] +; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm9 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm6, %zmm28, %zmm5 +; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm8, %zmm5 +; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm9, %zmm5 +; AVX512-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload +; AVX512-FCP-NEXT: vshufi64x2 $85, {{[-0-9]+}}(%r{{[sb]}}p), %zmm3, %zmm6 # 64-byte Folded Reload +; AVX512-FCP-NEXT: # zmm6 = zmm3[2,3,2,3],mem[2,3,2,3] +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm2, %zmm2 +; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm6, %zmm2 +; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm27, %zmm2 +; AVX512-FCP-NEXT: vinserti64x4 $1, %ymm17, %zmm4, %zmm4 +; AVX512-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm22, %zmm4 +; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm7, %zmm4 +; AVX512-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload +; AVX512-FCP-NEXT: vshufi64x2 $84, {{[-0-9]+}}(%r{{[sb]}}p), %zmm3, %zmm6 # 64-byte Folded Reload +; AVX512-FCP-NEXT: # zmm6 = zmm3[0,1,2,3],mem[2,3,2,3] +; AVX512-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm6, %zmm11 +; AVX512-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm18, %zmm11 ; AVX512-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax -; AVX512-FCP-NEXT: vmovdqa64 %zmm4, 128(%rax) -; AVX512-FCP-NEXT: vmovdqa64 %zmm2, (%rax) -; AVX512-FCP-NEXT: vmovdqa64 %zmm16, 320(%rax) +; AVX512-FCP-NEXT: vmovdqa64 %zmm11, 320(%rax) +; AVX512-FCP-NEXT: vmovdqa64 %zmm4, 192(%rax) +; AVX512-FCP-NEXT: vmovdqa64 %zmm2, 128(%rax) +; AVX512-FCP-NEXT: vmovdqa64 %zmm5, (%rax) ; AVX512-FCP-NEXT: vmovdqa64 %zmm0, 256(%rax) -; AVX512-FCP-NEXT: vmovdqa64 %zmm21, 192(%rax) -; AVX512-FCP-NEXT: vmovdqa64 %zmm24, 64(%rax) -; AVX512-FCP-NEXT: vmovdqa64 %zmm22, 384(%rax) -; AVX512-FCP-NEXT: addq $1256, %rsp # imm = 0x4E8 +; AVX512-FCP-NEXT: vmovdqa64 %zmm20, 64(%rax) +; AVX512-FCP-NEXT: vmovdqa64 %zmm1, 384(%rax) +; AVX512-FCP-NEXT: addq $1432, %rsp # imm = 0x598 ; AVX512-FCP-NEXT: vzeroupper ; AVX512-FCP-NEXT: retq ; ; AVX512DQ-LABEL: store_i8_stride7_vf64: ; AVX512DQ: # %bb.0: -; AVX512DQ-NEXT: subq $1448, %rsp # imm = 0x5A8 -; AVX512DQ-NEXT: vmovdqa (%rsi), %ymm1 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,ymm1[14],zero,zero,zero,zero,zero,zero,ymm1[15],zero,zero,zero,zero,zero,zero,ymm1[16],zero,zero,zero,zero,zero,zero,ymm1[17],zero,zero,zero,zero,zero,zero,ymm1[18] -; AVX512DQ-NEXT: vmovdqa %ymm1, %ymm10 -; AVX512DQ-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-NEXT: subq $1720, %rsp # imm = 0x6B8 +; AVX512DQ-NEXT: vmovdqa (%rsi), %ymm7 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm2 = [128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128,128,18] +; AVX512DQ-NEXT: vpshufb %ymm2, %ymm7, %ymm0 +; AVX512DQ-NEXT: vmovdqa64 %ymm2, %ymm26 ; AVX512DQ-NEXT: vmovdqa (%rdi), %ymm2 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[0,1,14],zero,ymm2[12,13,0,1,14,15],zero,ymm2[3,12,13,2,3,16],zero,ymm2[30,31,28,29,16,17],zero,ymm2[31,18,19,28,29,18],zero -; AVX512DQ-NEXT: vmovdqa %ymm2, %ymm14 -; AVX512DQ-NEXT: vmovdqu %ymm2, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm3 = [0,1,14,128,12,13,0,1,14,15,128,3,12,13,2,3,16,128,30,31,28,29,16,17,128,31,18,19,28,29,18,128] +; AVX512DQ-NEXT: vpshufb %ymm3, %ymm2, %ymm1 +; AVX512DQ-NEXT: vmovdqa64 %ymm3, %ymm25 +; AVX512DQ-NEXT: vmovdqa64 %ymm2, %ymm18 ; AVX512DQ-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512DQ-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-NEXT: vmovdqa (%rcx), %ymm6 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm1 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] -; AVX512DQ-NEXT: vpshufb %ymm1, %ymm6, %ymm0 -; AVX512DQ-NEXT: vmovdqa64 %ymm1, %ymm23 +; AVX512DQ-NEXT: vmovdqa (%rcx), %ymm14 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm2 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] +; AVX512DQ-NEXT: vpshufb %ymm2, %ymm14, %ymm0 +; AVX512DQ-NEXT: vmovdqa64 %ymm2, %ymm28 ; AVX512DQ-NEXT: vmovdqa (%rdx), %ymm8 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm2 = [0,1,0,1,14,128,14,15,0,1,14,15,128,13,14,15,16,17,16,128,30,31,30,31,16,17,128,31,28,29,30,31] -; AVX512DQ-NEXT: vpshufb %ymm2, %ymm8, %ymm1 -; AVX512DQ-NEXT: vmovdqa64 %ymm2, %ymm17 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm3 = [0,1,0,1,14,128,14,15,0,1,14,15,128,13,14,15,16,17,16,128,30,31,30,31,16,17,128,31,28,29,30,31] +; AVX512DQ-NEXT: vpshufb %ymm3, %ymm8, %ymm1 +; AVX512DQ-NEXT: vmovdqa64 %ymm3, %ymm23 +; AVX512DQ-NEXT: vmovdqu %ymm8, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX512DQ-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512DQ-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-NEXT: vmovdqa (%r8), %ymm0 -; AVX512DQ-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-NEXT: vmovdqa (%r8), %ymm15 ; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm2 = [128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128] -; AVX512DQ-NEXT: vpshufb %ymm2, %ymm0, %ymm0 -; AVX512DQ-NEXT: vmovdqa64 %ymm2, %ymm18 -; AVX512DQ-NEXT: vmovdqa (%r9), %ymm1 -; AVX512DQ-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-NEXT: vpshufb %ymm2, %ymm15, %ymm0 +; AVX512DQ-NEXT: vmovdqa64 %ymm2, %ymm24 +; AVX512DQ-NEXT: vmovdqa (%r9), %ymm2 ; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm3 = [13,0,0,0,128,16,128,14,0,0,0,128,17,128,15,0,13,0,0,0,128,16,128,14,0,0,0,128,17,128,15,0] ; AVX512DQ-NEXT: # ymm3 = mem[0,1,0,1] -; AVX512DQ-NEXT: vpshufb %ymm3, %ymm1, %ymm1 -; AVX512DQ-NEXT: vmovdqa64 %ymm3, %ymm22 -; AVX512DQ-NEXT: vporq %ymm0, %ymm1, %ymm24 -; AVX512DQ-NEXT: vmovdqa 32(%r9), %ymm11 -; AVX512DQ-NEXT: vmovdqa 32(%r8), %ymm1 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm0 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[27],zero,zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29] -; AVX512DQ-NEXT: vmovdqa %ymm1, %ymm13 -; AVX512DQ-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm11[25],zero,ymm11[23],zero,zero,zero,zero,ymm11[26],zero,ymm11[24],zero,zero +; AVX512DQ-NEXT: vpshufb %ymm3, %ymm2, %ymm1 +; AVX512DQ-NEXT: vmovdqa64 %ymm3, %ymm27 +; AVX512DQ-NEXT: vmovdqa64 %ymm2, %ymm19 +; AVX512DQ-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX512DQ-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-NEXT: vmovdqa 32(%rsi), %ymm10 +; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm6 = [128,128,128,30,128,28,128,128,128,128,31,128,29,128,128,128,128,128,128,30,128,28,128,128,128,128,31,128,29,128,128,128] +; AVX512DQ-NEXT: # ymm6 = mem[0,1,0,1] +; AVX512DQ-NEXT: vpshufb %ymm6, %ymm10, %ymm0 +; AVX512DQ-NEXT: vmovdqa 32(%rdi), %ymm9 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm9[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm9[23],zero,zero,zero,zero,ymm9[26],zero,ymm9[24],zero,zero,zero,zero,ymm9[27],zero,ymm9[25] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512DQ-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm1 = [12,13,14,128,12,128,14,15,14,15,128,13,128,15,12,13,28,29,30,128,28,128,30,31,30,31,128,29,128,31,28,29] +; AVX512DQ-NEXT: vpshufb %ymm1, %ymm9, %ymm0 +; AVX512DQ-NEXT: vmovdqa64 %ymm1, %ymm16 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm10[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm10[23,u,u,u],zero,ymm10[26],zero,ymm10[24,u,u,u],zero,ymm10[27],zero ; AVX512DQ-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 ; AVX512DQ-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-NEXT: vmovdqa 32(%rcx), %ymm7 -; AVX512DQ-NEXT: vmovdqa 32(%rdx), %ymm9 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm9[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm9[30],zero,ymm9[28],zero,zero,zero,zero,ymm9[31],zero,ymm9[29],zero,zero -; AVX512DQ-NEXT: vmovdqu %ymm9, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm0 = [128,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128,128,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128] +; AVX512DQ-NEXT: vmovdqa 32(%rdx), %ymm5 +; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [128,128,128,128,30,128,28,128,128,128,128,31,128,29,128,128,128,128,128,128,30,128,28,128,128,128,128,31,128,29,128,128] +; AVX512DQ-NEXT: # ymm1 = mem[0,1,0,1] +; AVX512DQ-NEXT: vpshufb %ymm1, %ymm5, %ymm2 +; AVX512DQ-NEXT: vmovdqa 32(%rcx), %ymm4 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm3 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm4[25],zero,ymm4[23],zero,zero,zero,zero,ymm4[26],zero,ymm4[24],zero,zero,zero,zero +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm2 +; AVX512DQ-NEXT: vmovdqu64 %zmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm0 = [27,0,0,0,128,30,128,28,0,0,0,128,31,128,29,0,27,0,0,0,128,30,128,28,0,0,0,128,31,128,29,0] ; AVX512DQ-NEXT: # ymm0 = mem[0,1,0,1] -; AVX512DQ-NEXT: vpshufb %ymm0, %ymm7, %ymm2 -; AVX512DQ-NEXT: vmovdqu %ymm7, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm1 -; AVX512DQ-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-NEXT: vmovdqa 32(%rsi), %ymm5 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero,ymm5[29],zero,zero,zero -; AVX512DQ-NEXT: vmovdqa 32(%rdi), %ymm4 -; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm3 = [128,23,128,128,128,128,26,128,24,128,128,128,128,27,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128,25] -; AVX512DQ-NEXT: # ymm3 = mem[0,1,0,1] -; AVX512DQ-NEXT: vpshufb %ymm3, %ymm4, %ymm2 -; AVX512DQ-NEXT: vmovdqa64 %ymm4, %ymm20 -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm1 -; AVX512DQ-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-NEXT: vpshufb %ymm0, %ymm4, %ymm2 +; AVX512DQ-NEXT: vmovdqa64 %ymm0, %ymm20 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm3 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,ymm5[23],zero,ymm5[21,22,23,26],zero,ymm5[24],zero,ymm5[28,29,26,27] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm2 +; AVX512DQ-NEXT: vmovdqu64 %zmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-NEXT: vmovdqa 32(%r8), %ymm3 +; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm0 = [128,27,128,128,128,128,30,128,28,128,128,128,128,31,128,29,128,27,128,128,128,128,30,128,28,128,128,128,128,31,128,29] +; AVX512DQ-NEXT: # ymm0 = mem[0,1,0,1] +; AVX512DQ-NEXT: vpshufb %ymm0, %ymm3, %ymm11 +; AVX512DQ-NEXT: vmovdqa64 %ymm0, %ymm21 +; AVX512DQ-NEXT: vmovdqa 32(%r9), %ymm2 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm12 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[25],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm11, %zmm12, %zmm11 +; AVX512DQ-NEXT: vmovdqu64 %zmm11, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm11 = [29,128,27,0,0,0,128,30,128,28,0,0,0,128,31,128,29,128,27,0,0,0,128,30,128,28,0,0,0,128,31,128] +; AVX512DQ-NEXT: # ymm11 = mem[0,1,0,1] +; AVX512DQ-NEXT: vpshufb %ymm11, %ymm2, %ymm12 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm13 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,ymm3[23],zero,ymm3[23,24,25,26],zero,ymm3[24],zero,ymm3[30,31] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm12, %zmm13, %zmm12 +; AVX512DQ-NEXT: vmovdqu64 %zmm12, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill ; AVX512DQ-NEXT: movq {{[0-9]+}}(%rsp), %rax -; AVX512DQ-NEXT: vmovdqa 32(%rax), %ymm4 -; AVX512DQ-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] -; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] -; AVX512DQ-NEXT: # ymm2 = mem[0,1,0,1] -; AVX512DQ-NEXT: vpshufb %ymm2, %ymm4, %ymm4 -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm1, %zmm4, %zmm1 -; AVX512DQ-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-NEXT: vpshufb %ymm3, %ymm14, %ymm1 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm3 = ymm10[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm10[21],zero,ymm10[19],zero,zero,zero,zero,ymm10[22],zero,ymm10[20],zero,zero -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm1, %zmm3, %zmm1 -; AVX512DQ-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-NEXT: vmovdqu %ymm6, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-NEXT: vpshufb %ymm0, %ymm6, %ymm0 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[18],zero,zero,zero,zero,ymm6[21],zero,ymm6[19],zero,zero,zero,zero,ymm6[22],zero,ymm6[20] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512DQ-NEXT: vmovdqa 32(%rax), %ymm0 +; AVX512DQ-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm12 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm13 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm12, %zmm13, %zmm12 +; AVX512DQ-NEXT: vmovdqu64 %zmm12, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-NEXT: vpshufb %ymm6, %ymm7, %ymm6 +; AVX512DQ-NEXT: vmovdqa64 %ymm7, %ymm17 +; AVX512DQ-NEXT: vmovdqa64 %ymm18, %ymm13 +; AVX512DQ-NEXT: vmovdqa64 %ymm16, %ymm0 +; AVX512DQ-NEXT: vpshufb %ymm0, %ymm13, %ymm7 +; AVX512DQ-NEXT: vpor %ymm6, %ymm7, %ymm0 ; AVX512DQ-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm0 = ymm8[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,ymm8[23],zero,ymm8[21,22,23,26],zero,ymm8[24],zero,ymm8[28,29,26,27] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm8[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,ymm8[18,19,20,21],zero,ymm8[19],zero,ymm8[25,26,27,22],zero,ymm8[20],zero -; AVX512DQ-NEXT: vmovdqa64 %ymm8, %ymm19 -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512DQ-NEXT: vpshufb %ymm1, %ymm8, %ymm6 +; AVX512DQ-NEXT: vmovdqa64 %ymm20, %ymm0 +; AVX512DQ-NEXT: vpshufb %ymm0, %ymm14, %ymm7 +; AVX512DQ-NEXT: vmovdqa64 %ymm14, %ymm22 +; AVX512DQ-NEXT: vpor %ymm6, %ymm7, %ymm0 +; AVX512DQ-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-NEXT: vmovdqa64 %ymm21, %ymm0 +; AVX512DQ-NEXT: vpshufb %ymm0, %ymm15, %ymm6 +; AVX512DQ-NEXT: vmovdqa64 %ymm15, %ymm16 +; AVX512DQ-NEXT: vmovdqa64 %ymm19, %ymm15 +; AVX512DQ-NEXT: vpshufb %ymm11, %ymm15, %ymm7 +; AVX512DQ-NEXT: vpor %ymm6, %ymm7, %ymm0 ; AVX512DQ-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-NEXT: vmovdqa (%rax), %ymm1 -; AVX512DQ-NEXT: vpshufb %ymm2, %ymm1, %ymm0 -; AVX512DQ-NEXT: vpmovsxbd {{.*#+}} zmm16 = [0,5,4,0,5,0,4,0,20,21,0,23,0,21,0,23] -; AVX512DQ-NEXT: vpshuflw {{.*#+}} ymm2 = ymm1[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] -; AVX512DQ-NEXT: vpermi2d %zmm0, %zmm2, %zmm16 -; AVX512DQ-NEXT: vmovdqa 32(%rdx), %xmm3 -; AVX512DQ-NEXT: vmovdqa 32(%rcx), %xmm0 +; AVX512DQ-NEXT: vmovdqa 32(%rdx), %xmm0 ; AVX512DQ-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm2 = [u,u,u,128,7,128,5,u,u,u,128,8,128,6,u,u] -; AVX512DQ-NEXT: vpshufb %xmm2, %xmm0, %xmm0 -; AVX512DQ-NEXT: vmovdqa64 %xmm2, %xmm29 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm4 = [u,u,u,7,128,5,128,u,u,u,8,128,6,128,u,u] -; AVX512DQ-NEXT: vpshufb %xmm4, %xmm3, %xmm2 -; AVX512DQ-NEXT: vmovdqa64 %xmm4, %xmm31 -; AVX512DQ-NEXT: vmovdqa64 %xmm3, %xmm30 -; AVX512DQ-NEXT: vpor %xmm0, %xmm2, %xmm0 +; AVX512DQ-NEXT: vmovdqa 32(%rcx), %xmm1 +; AVX512DQ-NEXT: vmovdqa %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm11 = [u,u,u,128,7,128,5,u,u,u,128,8,128,6,u,u] +; AVX512DQ-NEXT: vpshufb %xmm11, %xmm1, %xmm6 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm12 = [u,u,u,7,128,5,128,u,u,u,8,128,6,128,u,u] +; AVX512DQ-NEXT: vpshufb %xmm12, %xmm0, %xmm7 +; AVX512DQ-NEXT: vpor %xmm6, %xmm7, %xmm0 ; AVX512DQ-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-NEXT: vmovdqa 32(%rdi), %xmm3 -; AVX512DQ-NEXT: vmovdqa 32(%rsi), %xmm4 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm12 = [u,128,7,128,5,u,u,u,128,8,128,6,u,u,u,128] -; AVX512DQ-NEXT: vpshufb %xmm12, %xmm4, %xmm0 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm15 = [u,7,128,5,128,u,u,u,8,128,6,128,u,u,u,9] -; AVX512DQ-NEXT: vpshufb %xmm15, %xmm3, %xmm2 -; AVX512DQ-NEXT: vmovdqa64 %xmm3, %xmm21 -; AVX512DQ-NEXT: vpor %xmm0, %xmm2, %xmm0 +; AVX512DQ-NEXT: vmovdqa 32(%rdi), %xmm0 +; AVX512DQ-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512DQ-NEXT: vmovdqa 32(%rsi), %xmm14 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm6 = [u,128,7,128,5,u,u,u,128,8,128,6,u,u,u,128] +; AVX512DQ-NEXT: vpshufb %xmm6, %xmm14, %xmm7 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm1 = [u,7,128,5,128,u,u,u,8,128,6,128,u,u,u,9] +; AVX512DQ-NEXT: vpshufb %xmm1, %xmm0, %xmm8 +; AVX512DQ-NEXT: vmovdqa64 %xmm1, %xmm18 +; AVX512DQ-NEXT: vpor %xmm7, %xmm8, %xmm0 ; AVX512DQ-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-NEXT: vpmovsxbd {{.*#+}} zmm3 = [0,0,0,0,2,3,0,1,0,18,0,19,18,0,19,0] -; AVX512DQ-NEXT: vmovdqa 32(%rax), %xmm2 -; AVX512DQ-NEXT: vmovdqa %xmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512DQ-NEXT: vpshufhw {{.*#+}} xmm0 = xmm2[0,1,2,3,4,5,5,6] -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm2 = xmm2[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] -; AVX512DQ-NEXT: vpermi2d %zmm0, %zmm2, %zmm3 -; AVX512DQ-NEXT: vmovdqu64 %zmm3, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-NEXT: vpmovsxbd {{.*#+}} zmm1 = [0,0,0,0,2,3,0,1,0,18,0,19,18,0,19,0] +; AVX512DQ-NEXT: vmovdqa 32(%rax), %xmm0 +; AVX512DQ-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512DQ-NEXT: vpshufhw {{.*#+}} xmm7 = xmm0[0,1,2,3,4,5,5,6] +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm8 = xmm0[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] +; AVX512DQ-NEXT: vpermi2d %zmm7, %zmm8, %zmm1 +; AVX512DQ-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill ; AVX512DQ-NEXT: vmovdqa 32(%r9), %xmm0 -; AVX512DQ-NEXT: vmovdqa 32(%r8), %xmm2 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm6 = [128,4,u,u,u,128,7,128,5,u,u,u,128,8,128,6] -; AVX512DQ-NEXT: vpshufb %xmm6, %xmm0, %xmm8 -; AVX512DQ-NEXT: vmovdqa64 %xmm0, %xmm28 -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm14 = [4,128,u,u,u,7,128,5,128,u,u,u,8,128,6,128] -; AVX512DQ-NEXT: vpshufb %xmm14, %xmm2, %xmm10 -; AVX512DQ-NEXT: vmovdqa %xmm2, %xmm3 -; AVX512DQ-NEXT: vporq %xmm8, %xmm10, %xmm26 +; AVX512DQ-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512DQ-NEXT: vmovdqa 32(%r8), %xmm1 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm8 = [128,4,u,u,u,128,7,128,5,u,u,u,128,8,128,6] +; AVX512DQ-NEXT: vpshufb %xmm8, %xmm0, %xmm7 +; AVX512DQ-NEXT: vmovdqa64 %xmm8, %xmm20 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm0 = [4,128,u,u,u,7,128,5,128,u,u,u,8,128,6,128] +; AVX512DQ-NEXT: vpshufb %xmm0, %xmm1, %xmm8 +; AVX512DQ-NEXT: vmovdqa64 %xmm0, %xmm30 +; AVX512DQ-NEXT: vmovdqa64 %xmm1, %xmm29 +; AVX512DQ-NEXT: vpor %xmm7, %xmm8, %xmm0 +; AVX512DQ-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-NEXT: vmovdqa64 %ymm28, %ymm0 +; AVX512DQ-NEXT: vpshufb %ymm0, %ymm4, %ymm7 ; AVX512DQ-NEXT: vmovdqa64 %ymm23, %ymm0 -; AVX512DQ-NEXT: vpshufb %ymm0, %ymm7, %ymm8 -; AVX512DQ-NEXT: vmovdqa64 %ymm17, %ymm0 -; AVX512DQ-NEXT: vpshufb %ymm0, %ymm9, %ymm10 -; AVX512DQ-NEXT: vpor %ymm8, %ymm10, %ymm0 +; AVX512DQ-NEXT: vpshufb %ymm0, %ymm5, %ymm8 +; AVX512DQ-NEXT: vpor %ymm7, %ymm8, %ymm0 ; AVX512DQ-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm8 = zero,zero,zero,ymm5[14],zero,zero,zero,zero,zero,zero,ymm5[15],zero,zero,zero,zero,zero,zero,ymm5[16],zero,zero,zero,zero,zero,zero,ymm5[17],zero,zero,zero,zero,zero,zero,ymm5[18] -; AVX512DQ-NEXT: vmovdqa64 %ymm5, %ymm23 -; AVX512DQ-NEXT: vmovdqa64 %ymm20, %ymm0 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm10 = ymm0[0,1,14],zero,ymm0[12,13,0,1,14,15],zero,ymm0[3,12,13,2,3,16],zero,ymm0[30,31,28,29,16,17],zero,ymm0[31,18,19,28,29,18],zero -; AVX512DQ-NEXT: vpor %ymm8, %ymm10, %ymm2 -; AVX512DQ-NEXT: vmovdqu64 %zmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-NEXT: vmovdqa64 %ymm18, %ymm2 -; AVX512DQ-NEXT: vpshufb %ymm2, %ymm13, %ymm8 -; AVX512DQ-NEXT: vmovdqa64 %ymm22, %ymm2 -; AVX512DQ-NEXT: vpshufb %ymm2, %ymm11, %ymm10 -; AVX512DQ-NEXT: vmovdqa64 %ymm11, %ymm27 -; AVX512DQ-NEXT: vpor %ymm8, %ymm10, %ymm2 +; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20] +; AVX512DQ-NEXT: # ymm1 = mem[0,1,0,1] +; AVX512DQ-NEXT: vpshufb %ymm1, %ymm4, %ymm0 +; AVX512DQ-NEXT: vmovdqa64 %ymm1, %ymm21 +; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm4 = [18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128,18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128] +; AVX512DQ-NEXT: # ymm4 = mem[0,1,0,1] +; AVX512DQ-NEXT: vpshufb %ymm4, %ymm5, %ymm1 +; AVX512DQ-NEXT: vmovdqa64 %ymm4, %ymm19 +; AVX512DQ-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX512DQ-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-NEXT: vmovdqa64 %ymm26, %ymm0 +; AVX512DQ-NEXT: vpshufb %ymm0, %ymm10, %ymm0 +; AVX512DQ-NEXT: vmovdqa64 %ymm25, %ymm1 +; AVX512DQ-NEXT: vpshufb %ymm1, %ymm9, %ymm1 +; AVX512DQ-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX512DQ-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm7 = [128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128] +; AVX512DQ-NEXT: # ymm7 = mem[0,1,0,1] +; AVX512DQ-NEXT: vpshufb %ymm7, %ymm10, %ymm0 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm1 = [2,3,4,5,128,3,128,5,4,5,6,128,4,128,6,7,18,19,20,21,128,19,128,21,20,21,22,128,20,128,22,23] +; AVX512DQ-NEXT: vpshufb %ymm1, %ymm9, %ymm4 +; AVX512DQ-NEXT: vpor %ymm0, %ymm4, %ymm0 +; AVX512DQ-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm10 = [128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22] +; AVX512DQ-NEXT: # ymm10 = mem[0,1,0,1] +; AVX512DQ-NEXT: vpshufb %ymm10, %ymm2, %ymm4 +; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm0 = [20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128,20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128] +; AVX512DQ-NEXT: # ymm0 = mem[0,1,0,1] +; AVX512DQ-NEXT: vpshufb %ymm0, %ymm3, %ymm5 +; AVX512DQ-NEXT: vpor %ymm4, %ymm5, %ymm4 +; AVX512DQ-NEXT: vmovdqu64 %zmm4, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-NEXT: vmovdqa64 %ymm24, %ymm4 +; AVX512DQ-NEXT: vpshufb %ymm4, %ymm3, %ymm3 +; AVX512DQ-NEXT: vmovdqa64 %ymm27, %ymm4 +; AVX512DQ-NEXT: vpshufb %ymm4, %ymm2, %ymm2 +; AVX512DQ-NEXT: vpor %ymm3, %ymm2, %ymm2 ; AVX512DQ-NEXT: vmovdqu64 %zmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-NEXT: vmovdqa (%rsi), %xmm2 -; AVX512DQ-NEXT: vpshufb %xmm12, %xmm2, %xmm5 -; AVX512DQ-NEXT: vmovdqa64 %xmm2, %xmm25 -; AVX512DQ-NEXT: vmovdqa (%rdi), %xmm12 -; AVX512DQ-NEXT: vpshufb %xmm15, %xmm12, %xmm9 -; AVX512DQ-NEXT: vporq %xmm5, %xmm9, %xmm22 -; AVX512DQ-NEXT: vmovdqa (%rcx), %xmm13 -; AVX512DQ-NEXT: vmovdqa64 %xmm29, %xmm2 -; AVX512DQ-NEXT: vpshufb %xmm2, %xmm13, %xmm7 -; AVX512DQ-NEXT: vmovdqa (%rdx), %xmm9 -; AVX512DQ-NEXT: vmovdqa64 %xmm31, %xmm2 -; AVX512DQ-NEXT: vpshufb %xmm2, %xmm9, %xmm10 -; AVX512DQ-NEXT: vpor %xmm7, %xmm10, %xmm2 +; AVX512DQ-NEXT: vmovdqa (%rsi), %xmm3 +; AVX512DQ-NEXT: vpshufb %xmm6, %xmm3, %xmm2 +; AVX512DQ-NEXT: vmovdqa64 %xmm3, %xmm31 +; AVX512DQ-NEXT: vmovdqa (%rdi), %xmm4 +; AVX512DQ-NEXT: vmovdqa64 %xmm18, %xmm3 +; AVX512DQ-NEXT: vpshufb %xmm3, %xmm4, %xmm3 +; AVX512DQ-NEXT: vmovdqa64 %xmm4, %xmm28 +; AVX512DQ-NEXT: vpor %xmm2, %xmm3, %xmm2 ; AVX512DQ-NEXT: vmovdqa %xmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512DQ-NEXT: vmovdqa (%r9), %xmm2 +; AVX512DQ-NEXT: vmovdqa (%rcx), %xmm3 +; AVX512DQ-NEXT: vpshufb %xmm11, %xmm3, %xmm2 +; AVX512DQ-NEXT: vmovdqa %xmm3, %xmm6 +; AVX512DQ-NEXT: vmovdqa (%rdx), %xmm4 +; AVX512DQ-NEXT: vpshufb %xmm12, %xmm4, %xmm3 +; AVX512DQ-NEXT: vmovdqa64 %xmm4, %xmm18 +; AVX512DQ-NEXT: vpor %xmm2, %xmm3, %xmm2 ; AVX512DQ-NEXT: vmovdqa %xmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512DQ-NEXT: vpshufb %xmm6, %xmm2, %xmm6 -; AVX512DQ-NEXT: vmovdqa (%r8), %xmm5 -; AVX512DQ-NEXT: vmovdqa %xmm5, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512DQ-NEXT: vpshufb %xmm14, %xmm5, %xmm11 -; AVX512DQ-NEXT: vpor %xmm6, %xmm11, %xmm6 -; AVX512DQ-NEXT: vmovdqu64 %zmm6, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm24, %zmm0, %zmm6 -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm11 = xmm5[8],xmm2[8],xmm5[9],xmm2[9],xmm5[10],xmm2[10],xmm5[11],xmm2[11],xmm5[12],xmm2[12],xmm5[13],xmm2[13],xmm5[14],xmm2[14],xmm5[15],xmm2[15] -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm7 = [u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] -; AVX512DQ-NEXT: vpshufb %xmm7, %xmm11, %xmm11 -; AVX512DQ-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm11[0,1,0,1],zmm6[4,5,6,7] +; AVX512DQ-NEXT: vmovdqa (%r9), %xmm3 +; AVX512DQ-NEXT: vmovdqa64 %xmm20, %xmm2 +; AVX512DQ-NEXT: vpshufb %xmm2, %xmm3, %xmm2 +; AVX512DQ-NEXT: vmovdqa %xmm3, %xmm8 +; AVX512DQ-NEXT: vmovdqa (%r8), %xmm3 +; AVX512DQ-NEXT: vmovdqa64 %xmm30, %xmm4 +; AVX512DQ-NEXT: vpshufb %xmm4, %xmm3, %xmm4 +; AVX512DQ-NEXT: vmovdqa %xmm3, %xmm9 +; AVX512DQ-NEXT: vpor %xmm2, %xmm4, %xmm2 +; AVX512DQ-NEXT: vmovdqu64 %zmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm2 = ymm13[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm13[23],zero,zero,zero,zero,ymm13[26],zero,ymm13[24],zero,zero,zero,zero,ymm13[27],zero,ymm13[25] +; AVX512DQ-NEXT: vmovdqa64 %ymm17, %ymm3 +; AVX512DQ-NEXT: vpshufb %ymm7, %ymm3, %ymm4 +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm2, %zmm4, %zmm2 ; AVX512DQ-NEXT: vmovdqu64 %zmm2, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-NEXT: vmovdqa (%rax), %xmm10 -; AVX512DQ-NEXT: vpshufhw {{.*#+}} xmm11 = xmm10[0,1,2,3,4,5,5,6] -; AVX512DQ-NEXT: vpshufd {{.*#+}} xmm11 = xmm11[2,2,3,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm11 = ymm11[0,1,0,1] -; AVX512DQ-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm11, %ymm11 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm14 = zero,ymm1[13],zero,zero,zero,zero,zero,zero,ymm1[14],zero,zero,zero,zero,zero,zero,ymm1[15],zero,zero,zero,zero,zero,zero,ymm1[16],zero,zero,zero,zero,zero,zero,ymm1[17],zero,zero -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm14, %zmm11, %zmm24 -; AVX512DQ-NEXT: vmovdqa64 %ymm19, %ymm2 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29],zero,zero -; AVX512DQ-NEXT: vmovdqa64 %ymm2, %ymm18 -; AVX512DQ-NEXT: vpbroadcastq {{.*#+}} ymm5 = [13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm2 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,ymm3[23,u,u,u],zero,ymm3[26],zero,ymm3[24,u,u,u],zero,ymm3[27],zero +; AVX512DQ-NEXT: vpshufb %ymm1, %ymm13, %ymm1 +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm2, %zmm1, %zmm1 +; AVX512DQ-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-NEXT: vmovdqa64 %ymm22, %ymm2 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[25],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero,zero,zero +; AVX512DQ-NEXT: vmovdqa64 %ymm21, %ymm3 +; AVX512DQ-NEXT: vpshufb %ymm3, %ymm2, %ymm2 +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm1 +; AVX512DQ-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill ; AVX512DQ-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload -; AVX512DQ-NEXT: vpshufb %ymm5, %ymm2, %ymm11 -; AVX512DQ-NEXT: vmovdqa64 %ymm5, %ymm29 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] -; AVX512DQ-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm14 # 32-byte Reload -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm15 = ymm14[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm14[27],zero,zero,zero,zero,ymm14[30],zero,ymm14[28],zero,zero,zero,zero,ymm14[31],zero,ymm14[29] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,3,2,3] -; AVX512DQ-NEXT: vmovdqa64 {{.*#+}} zmm31 = [18374967954648269055,71777218572844800,18374967954648269055,71777218572844800,18446463693966278655,18446742978476179455,18446463693966278655,18446742978476179455] -; AVX512DQ-NEXT: vpternlogq $248, %ymm31, %ymm11, %ymm15 -; AVX512DQ-NEXT: vmovdqa64 %xmm28, %xmm6 -; AVX512DQ-NEXT: vmovdqa %xmm3, %xmm8 -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm11 = xmm3[0],xmm6[0],xmm3[1],xmm6[1],xmm3[2],xmm6[2],xmm3[3],xmm6[3],xmm3[4],xmm6[4],xmm3[5],xmm6[5],xmm3[6],xmm6[6],xmm3[7],xmm6[7] -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm11 = xmm11[u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] -; AVX512DQ-NEXT: vshufi64x2 {{.*#+}} zmm5 = zmm15[0,1,2,3],zmm11[0,1,0,1] -; AVX512DQ-NEXT: vmovdqu64 %zmm5, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] -; AVX512DQ-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-NEXT: vpshufhw {{.*#+}} ymm1 = ymm0[0,1,2,3,6,7,7,6,8,9,10,11,14,15,15,14] -; AVX512DQ-NEXT: vmovdqa64 %ymm20, %ymm17 -; AVX512DQ-NEXT: vpshufd {{.*#+}} ymm1 = ymm1[2,2,3,3,6,6,7,7] -; AVX512DQ-NEXT: vpbroadcastq {{.*#+}} ymm11 = [9,8,7,0,0,0,11,10,9,8,7,0,0,0,11,10,9,8,7,0,0,0,11,10,9,8,7,0,0,0,11,10] -; AVX512DQ-NEXT: vmovdqa64 %ymm23, %ymm5 -; AVX512DQ-NEXT: vpshufb %ymm11, %ymm5, %ymm15 -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm1, %zmm15, %zmm19 -; AVX512DQ-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm0[30],zero,ymm0[28],zero,zero,zero,zero,ymm0[31],zero,ymm0[29],zero,zero,zero -; AVX512DQ-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-NEXT: vpshufb %ymm11, %ymm0, %ymm1 -; AVX512DQ-NEXT: vpshuflw $233, {{[-0-9]+}}(%r{{[sb]}}p), %ymm11 # 32-byte Folded Reload -; AVX512DQ-NEXT: # ymm11 = mem[1,2,2,3,4,5,6,7,9,10,10,11,12,13,14,15] -; AVX512DQ-NEXT: vpshufd {{.*#+}} ymm11 = ymm11[0,0,1,1,4,4,5,5] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm1, %zmm11, %zmm23 -; AVX512DQ-NEXT: vmovdqa64 %xmm30, %xmm0 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,ymm2[23],zero,ymm2[21,22,23,26],zero,ymm2[24],zero,ymm2[28,29,26,27] +; AVX512DQ-NEXT: vmovdqa64 %ymm19, %ymm3 +; AVX512DQ-NEXT: vpshufb %ymm3, %ymm2, %ymm2 +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm30 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm1 = ymm15[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm15[25],zero,ymm15[23],zero,zero,zero,zero,ymm15[26],zero,ymm15[24],zero,zero +; AVX512DQ-NEXT: vmovdqa64 %ymm16, %ymm3 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm2 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,ymm3[23],zero,ymm3[23,24,25,26],zero,ymm3[24],zero,ymm3[30,31] +; AVX512DQ-NEXT: vpor %ymm1, %ymm2, %ymm1 +; AVX512DQ-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-NEXT: vpshufb %ymm10, %ymm15, %ymm1 +; AVX512DQ-NEXT: vpshufb %ymm0, %ymm3, %ymm0 +; AVX512DQ-NEXT: vpor %ymm1, %ymm0, %ymm0 +; AVX512DQ-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-NEXT: vmovdqa (%rax), %ymm4 +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm0 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] +; AVX512DQ-NEXT: vpmovsxbd {{.*#+}} zmm15 = [0,5,4,0,5,0,4,0,20,21,0,23,0,21,0,23] +; AVX512DQ-NEXT: vpshuflw {{.*#+}} ymm1 = ymm4[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] +; AVX512DQ-NEXT: vpermi2d %zmm0, %zmm1, %zmm15 +; AVX512DQ-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm0, %zmm0 # 32-byte Folded Reload +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm9[8],xmm8[8],xmm9[9],xmm8[9],xmm9[10],xmm8[10],xmm9[11],xmm8[11],xmm9[12],xmm8[12],xmm9[13],xmm8[13],xmm9[14],xmm8[14],xmm9[15],xmm8[15] +; AVX512DQ-NEXT: vmovdqa64 %xmm9, %xmm21 +; AVX512DQ-NEXT: vmovdqa64 %xmm8, %xmm22 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm2 = [u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] +; AVX512DQ-NEXT: vpshufb %xmm2, %xmm1, %xmm1 +; AVX512DQ-NEXT: vmovdqa64 %xmm2, %xmm24 +; AVX512DQ-NEXT: vshufi64x2 {{.*#+}} zmm23 = zmm1[0,1,0,1],zmm0[4,5,6,7] +; AVX512DQ-NEXT: vmovdqa (%rax), %xmm11 +; AVX512DQ-NEXT: vpshufhw {{.*#+}} xmm1 = xmm11[0,1,2,3,4,5,5,6] +; AVX512DQ-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[2,2,3,3] +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,1,0,1] +; AVX512DQ-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm1 +; AVX512DQ-NEXT: vmovdqa {{.*#+}} ymm9 = [128,13,128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128] +; AVX512DQ-NEXT: vpshufb %ymm9, %ymm4, %ymm2 +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm2, %zmm1, %zmm16 +; AVX512DQ-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm10 # 16-byte Reload +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm10[0],xmm14[0],xmm10[1],xmm14[1],xmm10[2],xmm14[2],xmm10[3],xmm14[3],xmm10[4],xmm14[4],xmm10[5],xmm14[5],xmm10[6],xmm14[6],xmm10[7],xmm14[7] +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm0 = [0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] +; AVX512DQ-NEXT: vpshufb %xmm0, %xmm2, %xmm2 +; AVX512DQ-NEXT: vmovdqa64 %xmm0, %xmm27 +; AVX512DQ-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm0 # 64-byte Reload +; AVX512DQ-NEXT: vshufi64x2 {{.*#+}} zmm12 = zmm0[2,3,2,3],zmm2[0,1,0,1] +; AVX512DQ-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm2 # 16-byte Reload ; AVX512DQ-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm11 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm15 = xmm13[8],xmm9[8],xmm13[9],xmm9[9],xmm13[10],xmm9[10],xmm13[11],xmm9[11],xmm13[12],xmm9[12],xmm13[13],xmm9[13],xmm13[14],xmm9[14],xmm13[15],xmm9[15] -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm0 = [6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] -; AVX512DQ-NEXT: vpshufb %xmm0, %xmm15, %xmm3 -; AVX512DQ-NEXT: vmovdqu %ymm3, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-NEXT: vpshufb %xmm0, %xmm1, %xmm0 +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm3 = xmm2[0],xmm1[0],xmm2[1],xmm1[1],xmm2[2],xmm1[2],xmm2[3],xmm1[3],xmm2[4],xmm1[4],xmm2[5],xmm1[5],xmm2[6],xmm1[6],xmm2[7],xmm1[7] +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm0 = [4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] +; AVX512DQ-NEXT: vpshufb %xmm0, %xmm3, %xmm3 +; AVX512DQ-NEXT: vmovdqa64 %xmm0, %xmm26 +; AVX512DQ-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm0 # 64-byte Reload +; AVX512DQ-NEXT: vshufi64x2 {{.*#+}} zmm17 = zmm0[2,3,2,3],zmm3[0,1,0,1] +; AVX512DQ-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm5 # 16-byte Reload +; AVX512DQ-NEXT: vmovdqa64 %xmm29, %xmm3 +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm13 = xmm3[0],xmm5[0],xmm3[1],xmm5[1],xmm3[2],xmm5[2],xmm3[3],xmm5[3],xmm3[4],xmm5[4],xmm3[5],xmm5[5],xmm3[6],xmm5[6],xmm3[7],xmm5[7] +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm0 = [u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] +; AVX512DQ-NEXT: vpshufb %xmm0, %xmm13, %xmm13 +; AVX512DQ-NEXT: vmovdqa64 %xmm0, %xmm25 +; AVX512DQ-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm0 # 64-byte Reload +; AVX512DQ-NEXT: vshufi64x2 {{.*#+}} zmm29 = zmm0[2,3,2,3],zmm13[0,1,0,1] +; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm0 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] +; AVX512DQ-NEXT: vmovdqa64 %ymm0, %ymm20 +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm0 = xmm1[8],xmm2[8],xmm1[9],xmm2[9],xmm1[10],xmm2[10],xmm1[11],xmm2[11],xmm1[12],xmm2[12],xmm1[13],xmm2[13],xmm1[14],xmm2[14],xmm1[15],xmm2[15] +; AVX512DQ-NEXT: vmovdqa %xmm6, %xmm8 +; AVX512DQ-NEXT: vmovdqa64 %xmm18, %xmm7 +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm6[8],xmm7[8],xmm6[9],xmm7[9],xmm6[10],xmm7[10],xmm6[11],xmm7[11],xmm6[12],xmm7[12],xmm6[13],xmm7[13],xmm6[14],xmm7[14],xmm6[15],xmm7[15] +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm1 = [6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] +; AVX512DQ-NEXT: vpshufb %xmm1, %xmm4, %xmm2 +; AVX512DQ-NEXT: vmovdqa64 %ymm2, %ymm18 +; AVX512DQ-NEXT: vpshufb %xmm1, %xmm0, %xmm0 ; AVX512DQ-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm1 # 64-byte Reload -; AVX512DQ-NEXT: vinserti32x4 $2, %xmm0, %zmm1, %zmm30 -; AVX512DQ-NEXT: vmovdqa64 %xmm21, %xmm0 -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm15 = xmm0[0],xmm4[0],xmm0[1],xmm4[1],xmm0[2],xmm4[2],xmm0[3],xmm4[3],xmm0[4],xmm4[4],xmm0[5],xmm4[5],xmm0[6],xmm4[6],xmm0[7],xmm4[7] -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm0 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] -; AVX512DQ-NEXT: vmovdqa64 %xmm25, %xmm3 -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm3[8],xmm12[8],xmm3[9],xmm12[9],xmm3[10],xmm12[10],xmm3[11],xmm12[11],xmm3[12],xmm12[12],xmm3[13],xmm12[13],xmm3[14],xmm12[14],xmm3[15],xmm12[15] -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm4 = [2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] -; AVX512DQ-NEXT: vpshufb %xmm4, %xmm1, %xmm1 -; AVX512DQ-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-NEXT: vpshufb %xmm4, %xmm0, %xmm0 +; AVX512DQ-NEXT: vinserti32x4 $2, %xmm0, %zmm1, %zmm19 +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm14[8],xmm10[8],xmm14[9],xmm10[9],xmm14[10],xmm10[10],xmm14[11],xmm10[11],xmm14[12],xmm10[12],xmm14[13],xmm10[13],xmm14[14],xmm10[14],xmm14[15],xmm10[15] +; AVX512DQ-NEXT: vmovdqa64 %xmm31, %xmm6 +; AVX512DQ-NEXT: vmovdqa64 %xmm28, %xmm4 +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm14 = xmm6[8],xmm4[8],xmm6[9],xmm4[9],xmm6[10],xmm4[10],xmm6[11],xmm4[11],xmm6[12],xmm4[12],xmm6[13],xmm4[13],xmm6[14],xmm4[14],xmm6[15],xmm4[15] +; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm0 = [2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] +; AVX512DQ-NEXT: vpshufb %xmm0, %xmm14, %xmm13 +; AVX512DQ-NEXT: vpshufb %xmm0, %xmm1, %xmm0 ; AVX512DQ-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm1 # 64-byte Reload -; AVX512DQ-NEXT: vinserti32x4 $2, %xmm0, %zmm1, %zmm21 -; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm0 = xmm8[8],xmm6[8],xmm8[9],xmm6[9],xmm8[10],xmm6[10],xmm8[11],xmm6[11],xmm8[12],xmm6[12],xmm8[13],xmm6[13],xmm8[14],xmm6[14],xmm8[15],xmm6[15] -; AVX512DQ-NEXT: vpshufb %xmm7, %xmm0, %xmm0 -; AVX512DQ-NEXT: vshufi64x2 {{.*#+}} zmm26 = zmm26[0,1,0,1],zmm0[0,1,0,1] -; AVX512DQ-NEXT: vpbroadcastq {{.*#+}} ymm1 = [11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12] -; AVX512DQ-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX512DQ-NEXT: vpshufb %ymm1, %ymm0, %ymm6 -; AVX512DQ-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX512DQ-NEXT: vpshufb %ymm1, %ymm0, %ymm8 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[18],zero,zero,zero,zero,ymm0[21],zero,ymm0[19],zero,zero,zero,zero,ymm0[22],zero,ymm0[20] -; AVX512DQ-NEXT: vmovdqa64 %ymm0, %ymm28 -; AVX512DQ-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm7 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,ymm0[23],zero,ymm0[21,22,23,26],zero,ymm0[24],zero,ymm0[28,29,26,27] -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,18],zero,ymm0[18,19,20,21],zero,ymm0[19],zero,ymm0[25,26,27,22],zero,ymm0[20],zero -; AVX512DQ-NEXT: vmovdqa64 %ymm0, %ymm20 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm5 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm5[21],zero,ymm5[19],zero,zero,zero,zero,ymm5[22],zero,ymm5[20],zero,zero -; AVX512DQ-NEXT: vmovdqa64 %ymm27, %ymm1 -; AVX512DQ-NEXT: vmovdqa64 %ymm29, %ymm0 -; AVX512DQ-NEXT: vpshufb %ymm0, %ymm1, %ymm4 -; AVX512DQ-NEXT: vmovdqa %ymm2, %ymm0 -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[25],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero -; AVX512DQ-NEXT: vmovdqu %ymm2, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22] -; AVX512DQ-NEXT: # ymm2 = mem[0,1,0,1] -; AVX512DQ-NEXT: vpshufb %ymm2, %ymm0, %ymm0 -; AVX512DQ-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-NEXT: vpshufb %ymm2, %ymm1, %ymm0 -; AVX512DQ-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [24,25,24,25,128,23,128,23,24,25,26,128,24,128,30,31,24,25,24,25,128,23,128,23,24,25,26,128,24,128,30,31] -; AVX512DQ-NEXT: # ymm2 = mem[0,1,0,1] -; AVX512DQ-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX512DQ-NEXT: vpshufb %ymm2, %ymm0, %ymm1 -; AVX512DQ-NEXT: vpshufb %ymm2, %ymm14, %ymm2 -; AVX512DQ-NEXT: vmovdqa64 %ymm2, %ymm27 -; AVX512DQ-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128,20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128] -; AVX512DQ-NEXT: # ymm2 = mem[0,1,0,1] -; AVX512DQ-NEXT: vpshufb %ymm2, %ymm14, %ymm14 -; AVX512DQ-NEXT: vmovdqa64 %ymm14, %ymm25 -; AVX512DQ-NEXT: vpshufb %ymm2, %ymm0, %ymm0 -; AVX512DQ-NEXT: vmovdqa64 %ymm0, %ymm29 -; AVX512DQ-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX512DQ-NEXT: vpshufb {{.*#+}} ymm2 = zero,ymm0[13],zero,zero,zero,zero,zero,zero,ymm0[14],zero,zero,zero,zero,zero,zero,ymm0[15],zero,zero,zero,zero,zero,zero,ymm0[16],zero,zero,zero,zero,zero,zero,ymm0[17],zero,zero -; AVX512DQ-NEXT: vpshuflw {{.*#+}} ymm14 = ymm0[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] -; AVX512DQ-NEXT: vpshufd {{.*#+}} ymm14 = ymm14[0,1,1,3,4,5,5,7] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm14 = ymm14[2,2,3,2] -; AVX512DQ-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm14, %ymm14 -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm14, %zmm2, %zmm2 -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm12 = xmm12[0],xmm3[0],xmm12[1],xmm3[1],xmm12[2],xmm3[2],xmm12[3],xmm3[3],xmm12[4],xmm3[4],xmm12[5],xmm3[5],xmm12[6],xmm3[6],xmm12[7],xmm3[7] -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm14 = [0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] -; AVX512DQ-NEXT: vpshufb %xmm14, %xmm15, %xmm15 -; AVX512DQ-NEXT: vpshufb %xmm14, %xmm12, %xmm12 -; AVX512DQ-NEXT: vinserti32x4 $2, %xmm22, %zmm12, %zmm0 -; AVX512DQ-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm13 = xmm9[0],xmm13[0],xmm9[1],xmm13[1],xmm9[2],xmm13[2],xmm9[3],xmm13[3],xmm9[4],xmm13[4],xmm9[5],xmm13[5],xmm9[6],xmm13[6],xmm9[7],xmm13[7] -; AVX512DQ-NEXT: vmovdqa {{.*#+}} xmm14 = [4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] -; AVX512DQ-NEXT: vpshufb %xmm14, %xmm11, %xmm9 -; AVX512DQ-NEXT: vpshufb %xmm14, %xmm13, %xmm11 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm13 = ymm6[2,3,2,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm14 = ymm18[2,3,2,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm22 = ymm4[2,3,2,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm6 = ymm8[2,3,2,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm0 = ymm7[2,3,2,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm4 = ymm5[2,3,2,3] -; AVX512DQ-NEXT: vmovdqa64 %ymm17, %ymm3 -; AVX512DQ-NEXT: vpshuflw {{.*#+}} ymm3 = ymm3[1,2,2,3,4,5,6,7,9,10,10,11,12,13,14,15] -; AVX512DQ-NEXT: vpshufd {{.*#+}} ymm3 = ymm3[0,0,1,1,4,4,5,5] -; AVX512DQ-NEXT: vinserti32x4 $2, {{[-0-9]+}}(%r{{[sb]}}p), %zmm11, %zmm12 # 16-byte Folded Reload -; AVX512DQ-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm5 # 16-byte Reload -; AVX512DQ-NEXT: vpunpcklbw {{[-0-9]+}}(%r{{[sb]}}p), %xmm5, %xmm5 # 16-byte Folded Reload -; AVX512DQ-NEXT: # xmm5 = xmm5[0],mem[0],xmm5[1],mem[1],xmm5[2],mem[2],xmm5[3],mem[3],xmm5[4],mem[4],xmm5[5],mem[5],xmm5[6],mem[6],xmm5[7],mem[7] -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm5 = xmm5[u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] -; AVX512DQ-NEXT: vshufi64x2 $0, {{[-0-9]+}}(%r{{[sb]}}p), %zmm5, %zmm11 # 64-byte Folded Reload -; AVX512DQ-NEXT: # zmm11 = zmm5[0,1,0,1],mem[0,1,0,1] -; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm5 = xmm10[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] -; AVX512DQ-NEXT: vpshuflw {{.*#+}} xmm7 = xmm10[1,1,0,0,4,5,6,7] -; AVX512DQ-NEXT: vpshufd {{.*#+}} xmm7 = xmm7[0,1,2,0] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm5, %zmm7, %zmm7 -; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm10 # 64-byte Folded Reload -; AVX512DQ-NEXT: # zmm10 = mem[2,3,2,3,6,7,6,7] -; AVX512DQ-NEXT: vpermq {{.*#+}} zmm5 = zmm19[2,3,2,3,6,7,6,7] -; AVX512DQ-NEXT: vpternlogq $236, %zmm31, %zmm10, %zmm5 -; AVX512DQ-NEXT: vpandq %ymm31, %ymm22, %ymm10 -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm10, %zmm1, %zmm1 -; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm10 # 64-byte Folded Reload -; AVX512DQ-NEXT: # zmm10 = mem[2,3,2,3,6,7,6,7] -; AVX512DQ-NEXT: vporq %zmm10, %zmm1, %zmm1 -; AVX512DQ-NEXT: vmovdqa64 {{.*#+}} zmm10 = [18374966859431673855,18446463693966278655,18374966859431673855,18446463693966278655,18374967954648269055,71777218572844800,18374967954648269055,71777218572844800] -; AVX512DQ-NEXT: vpand %ymm6, %ymm10, %ymm6 -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm6, %zmm0, %zmm0 -; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm6 # 64-byte Folded Reload -; AVX512DQ-NEXT: # zmm6 = mem[2,3,2,3,6,7,6,7] -; AVX512DQ-NEXT: vporq %zmm6, %zmm0, %zmm0 -; AVX512DQ-NEXT: vpternlogq $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm5 -; AVX512DQ-NEXT: vmovdqa64 {{.*#+}} zmm0 = [255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255] -; AVX512DQ-NEXT: vpternlogq $226, %zmm1, %zmm0, %zmm5 -; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm1 # 64-byte Folded Reload -; AVX512DQ-NEXT: # zmm1 = mem[2,3,2,3,6,7,6,7] -; AVX512DQ-NEXT: vpermq {{.*#+}} zmm6 = zmm23[2,3,2,3,6,7,6,7] -; AVX512DQ-NEXT: vpternlogq $236, %zmm10, %zmm1, %zmm6 -; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm1 # 64-byte Folded Reload -; AVX512DQ-NEXT: # zmm1 = mem[2,3,2,3,6,7,6,7] -; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm17 # 64-byte Folded Reload -; AVX512DQ-NEXT: # zmm17 = mem[2,3,2,3,6,7,6,7] -; AVX512DQ-NEXT: vporq %zmm1, %zmm17, %zmm1 -; AVX512DQ-NEXT: vpternlogq $226, %zmm6, %zmm0, %zmm1 -; AVX512DQ-NEXT: vpermq {{.*#+}} zmm6 = zmm30[0,1,0,1,4,5,4,5] -; AVX512DQ-NEXT: vpermq {{.*#+}} zmm17 = zmm21[0,1,0,1,4,5,4,5] -; AVX512DQ-NEXT: vpternlogq $226, %zmm6, %zmm0, %zmm17 -; AVX512DQ-NEXT: vpternlogq $248, %ymm10, %ymm13, %ymm14 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm0 = ymm3[2,3,2,3] -; AVX512DQ-NEXT: vpternlogq $236, %ymm10, %ymm4, %ymm0 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm3 = ymm9[0,1,0,1] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm3, %zmm14, %zmm3 -; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %ymm4 # 32-byte Folded Reload -; AVX512DQ-NEXT: # ymm4 = mem[2,3,2,3] -; AVX512DQ-NEXT: vpshufhw $190, {{[-0-9]+}}(%r{{[sb]}}p), %ymm6 # 32-byte Folded Reload -; AVX512DQ-NEXT: # ymm6 = mem[0,1,2,3,6,7,7,6,8,9,10,11,14,15,15,14] -; AVX512DQ-NEXT: vpshufd {{.*#+}} ymm6 = ymm6[2,2,3,3,6,6,7,7] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,3,2,3] -; AVX512DQ-NEXT: vpternlogq $236, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm4, %ymm6 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm4 = ymm15[0,1,0,1] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm4, %zmm6, %zmm4 -; AVX512DQ-NEXT: vmovdqa64 {{.*#+}} zmm6 = [255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255] -; AVX512DQ-NEXT: vpternlogq $184, %zmm3, %zmm6, %zmm4 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm3 = ymm28[2,3,2,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm8 = ymm20[2,3,2,3] -; AVX512DQ-NEXT: vpor %ymm3, %ymm8, %ymm3 -; AVX512DQ-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm8 # 64-byte Reload -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm3, %zmm8, %zmm3 -; AVX512DQ-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm8 # 64-byte Reload -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm0, %zmm8, %zmm0 -; AVX512DQ-NEXT: vpermq $68, {{[-0-9]+}}(%r{{[sb]}}p), %ymm8 # 32-byte Folded Reload -; AVX512DQ-NEXT: # ymm8 = mem[0,1,0,1] -; AVX512DQ-NEXT: vpermq $68, {{[-0-9]+}}(%r{{[sb]}}p), %ymm10 # 32-byte Folded Reload -; AVX512DQ-NEXT: # ymm10 = mem[0,1,0,1] -; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %ymm13 # 32-byte Folded Reload -; AVX512DQ-NEXT: # ymm13 = mem[2,3,2,3] -; AVX512DQ-NEXT: vpshuflw $5, {{[-0-9]+}}(%r{{[sb]}}p), %xmm14 # 16-byte Folded Reload -; AVX512DQ-NEXT: # xmm14 = mem[1,1,0,0,4,5,6,7] -; AVX512DQ-NEXT: vpshufd {{.*#+}} xmm14 = xmm14[0,1,2,0] -; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %ymm15 # 32-byte Folded Reload -; AVX512DQ-NEXT: # ymm15 = mem[2,3,2,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm18 = ymm27[2,3,2,3] -; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %ymm19 # 32-byte Folded Reload -; AVX512DQ-NEXT: # ymm19 = mem[2,3,2,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm20 = ymm25[2,3,2,3] -; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %ymm21 # 32-byte Folded Reload -; AVX512DQ-NEXT: # ymm21 = mem[2,3,2,3] -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm22 = ymm29[2,3,2,3] -; AVX512DQ-NEXT: vpternlogq $226, %zmm3, %zmm6, %zmm0 -; AVX512DQ-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm8, %zmm3 # 32-byte Folded Reload -; AVX512DQ-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm10, %zmm6 # 32-byte Folded Reload -; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm3, %zmm6 +; AVX512DQ-NEXT: vinserti32x4 $2, %xmm0, %zmm1, %zmm0 +; AVX512DQ-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm3[8],xmm5[8],xmm3[9],xmm5[9],xmm3[10],xmm5[10],xmm3[11],xmm5[11],xmm3[12],xmm5[12],xmm3[13],xmm5[13],xmm3[14],xmm5[14],xmm3[15],xmm5[15] +; AVX512DQ-NEXT: vmovdqa64 %xmm24, %xmm2 +; AVX512DQ-NEXT: vpshufb %xmm2, %xmm1, %xmm1 +; AVX512DQ-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Reload +; AVX512DQ-NEXT: vshufi64x2 {{.*#+}} zmm14 = zmm2[0,1,0,1],zmm1[0,1,0,1] +; AVX512DQ-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm10 # 32-byte Reload +; AVX512DQ-NEXT: vpshufb %ymm9, %ymm10, %ymm1 +; AVX512DQ-NEXT: vpshuflw {{.*#+}} ymm9 = ymm10[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] +; AVX512DQ-NEXT: vpshufd {{.*#+}} ymm9 = ymm9[0,1,1,3,4,5,5,7] +; AVX512DQ-NEXT: vmovdqa64 {{.*#+}} zmm10 = [255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255] +; AVX512DQ-NEXT: vpternlogq $226, %zmm12, %zmm10, %zmm17 +; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Folded Reload +; AVX512DQ-NEXT: # ymm2 = mem[2,3,2,3] ; AVX512DQ-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload -; AVX512DQ-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm3, %zmm24 -; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm6, %zmm24 -; AVX512DQ-NEXT: vpermq {{.*#+}} ymm3 = ymm14[0,0,1,0] -; AVX512DQ-NEXT: vinserti64x4 $1, %ymm3, %zmm13, %zmm3 -; AVX512DQ-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm6 # 64-byte Reload -; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm6, %zmm3 -; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm4, %zmm3 +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm2 +; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %ymm28 # 32-byte Folded Reload +; AVX512DQ-NEXT: # ymm28 = mem[2,3,2,3] +; AVX512DQ-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm28, %zmm3, %zmm28 +; AVX512DQ-NEXT: vpternlogq $226, %zmm2, %zmm10, %zmm28 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm2 = ymm9[2,2,3,2] +; AVX512DQ-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm2 +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm2, %zmm1, %zmm10 +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm4[0],xmm6[0],xmm4[1],xmm6[1],xmm4[2],xmm6[2],xmm4[3],xmm6[3],xmm4[4],xmm6[4],xmm4[5],xmm6[5],xmm4[6],xmm6[6],xmm4[7],xmm6[7] +; AVX512DQ-NEXT: vmovdqa64 %xmm27, %xmm2 +; AVX512DQ-NEXT: vpshufb %xmm2, %xmm1, %xmm1 +; AVX512DQ-NEXT: vinserti32x4 $2, {{[-0-9]+}}(%r{{[sb]}}p), %zmm1, %zmm27 # 16-byte Folded Reload +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm7[0],xmm8[0],xmm7[1],xmm8[1],xmm7[2],xmm8[2],xmm7[3],xmm8[3],xmm7[4],xmm8[4],xmm7[5],xmm8[5],xmm7[6],xmm8[6],xmm7[7],xmm8[7] +; AVX512DQ-NEXT: vmovdqa64 %xmm26, %xmm1 +; AVX512DQ-NEXT: vpshufb %xmm1, %xmm2, %xmm2 +; AVX512DQ-NEXT: vinserti32x4 $2, {{[-0-9]+}}(%r{{[sb]}}p), %zmm2, %zmm2 # 16-byte Folded Reload +; AVX512DQ-NEXT: vmovdqa64 %xmm21, %xmm1 +; AVX512DQ-NEXT: vmovdqa64 %xmm22, %xmm3 +; AVX512DQ-NEXT: vpunpcklbw {{.*#+}} xmm8 = xmm1[0],xmm3[0],xmm1[1],xmm3[1],xmm1[2],xmm3[2],xmm1[3],xmm3[3],xmm1[4],xmm3[4],xmm1[5],xmm3[5],xmm1[6],xmm3[6],xmm1[7],xmm3[7] +; AVX512DQ-NEXT: vmovdqa64 %xmm25, %xmm1 +; AVX512DQ-NEXT: vpshufb %xmm1, %xmm8, %xmm8 +; AVX512DQ-NEXT: vshufi64x2 $0, {{[-0-9]+}}(%r{{[sb]}}p), %zmm8, %zmm8 # 64-byte Folded Reload +; AVX512DQ-NEXT: # zmm8 = zmm8[0,1,0,1],mem[0,1,0,1] +; AVX512DQ-NEXT: vpshufb {{.*#+}} xmm9 = xmm11[4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] +; AVX512DQ-NEXT: vpshuflw {{.*#+}} xmm5 = xmm11[1,1,0,0,4,5,6,7] +; AVX512DQ-NEXT: vpshufd {{.*#+}} xmm5 = xmm5[0,1,2,0] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm9, %zmm5, %zmm5 +; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm9 # 64-byte Folded Reload +; AVX512DQ-NEXT: # zmm9 = mem[2,3,2,3,6,7,6,7] +; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm11 # 64-byte Folded Reload +; AVX512DQ-NEXT: # zmm11 = mem[2,3,2,3,6,7,6,7] +; AVX512DQ-NEXT: vporq %zmm9, %zmm11, %zmm9 +; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm11 # 64-byte Folded Reload +; AVX512DQ-NEXT: # zmm11 = mem[2,3,2,3,6,7,6,7] +; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm12 # 64-byte Folded Reload +; AVX512DQ-NEXT: # zmm12 = mem[2,3,2,3,6,7,6,7] +; AVX512DQ-NEXT: vporq %zmm11, %zmm12, %zmm11 +; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm9, %zmm11 +; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm9 # 64-byte Folded Reload +; AVX512DQ-NEXT: # zmm9 = mem[2,3,2,3,6,7,6,7] +; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm12 # 64-byte Folded Reload +; AVX512DQ-NEXT: # zmm12 = mem[2,3,2,3,6,7,6,7] +; AVX512DQ-NEXT: vporq %zmm9, %zmm12, %zmm9 +; AVX512DQ-NEXT: vmovdqa64 {{.*#+}} zmm12 = [255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255] +; AVX512DQ-NEXT: vpternlogq $184, %zmm11, %zmm12, %zmm9 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm11 = ymm13[0,1,0,1] +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm4 = ymm18[0,1,0,1] +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm3 = ymm20[2,3,2,3] +; AVX512DQ-NEXT: vpshuflw $5, {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Folded Reload +; AVX512DQ-NEXT: # xmm1 = mem[1,1,0,0,4,5,6,7] +; AVX512DQ-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[0,1,2,0] +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm13 = zmm19[0,1,0,1,4,5,4,5] +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm0 = zmm0[0,1,0,1,4,5,4,5] +; AVX512DQ-NEXT: vpternlogq $226, %zmm13, %zmm12, %zmm0 +; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm13 # 64-byte Folded Reload +; AVX512DQ-NEXT: # zmm13 = mem[2,3,2,3,6,7,6,7] +; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm21 # 64-byte Folded Reload +; AVX512DQ-NEXT: # zmm21 = mem[2,3,2,3,6,7,6,7] +; AVX512DQ-NEXT: vporq %zmm13, %zmm21, %zmm13 +; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm20 # 64-byte Folded Reload +; AVX512DQ-NEXT: # zmm20 = mem[2,3,2,3,6,7,6,7] +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm18 = zmm30[2,3,2,3,6,7,6,7] +; AVX512DQ-NEXT: vporq %zmm20, %zmm18, %zmm18 +; AVX512DQ-NEXT: vpternlogq $226, %zmm13, %zmm12, %zmm18 +; AVX512DQ-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm11, %zmm11 # 32-byte Folded Reload +; AVX512DQ-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm4, %zmm4 # 32-byte Folded Reload +; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm11, %zmm4 +; AVX512DQ-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm23, %zmm16 +; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm4, %zmm16 ; AVX512DQ-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm4 # 64-byte Folded Reload ; AVX512DQ-NEXT: # zmm4 = mem[2,3,2,3,6,7,6,7] -; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm4 -; AVX512DQ-NEXT: vporq %ymm15, %ymm18, %ymm5 -; AVX512DQ-NEXT: vporq %ymm19, %ymm20, %ymm6 -; AVX512DQ-NEXT: vshufi64x2 {{.*#+}} zmm5 = zmm6[0,1,2,3],zmm5[0,1,2,3] -; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm16 -; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm16 -; AVX512DQ-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm1 # 64-byte Reload -; AVX512DQ-NEXT: vpternlogd $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm26 -; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm17, %zmm26 -; AVX512DQ-NEXT: vporq %ymm21, %ymm22, %ymm1 -; AVX512DQ-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm5 # 64-byte Reload -; AVX512DQ-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm5[0,1,2,3],zmm1[0,1,2,3] -; AVX512DQ-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm2 +; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm9, %zmm4 +; AVX512DQ-NEXT: vpermq {{.*#+}} ymm1 = ymm1[0,0,1,0] +; AVX512DQ-NEXT: vinserti64x4 $1, %ymm1, %zmm3, %zmm1 +; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm29, %zmm1 +; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm17, %zmm1 +; AVX512DQ-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload +; AVX512DQ-NEXT: vpternlogd $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm3, %zmm14 +; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm14 +; AVX512DQ-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm0 # 64-byte Reload +; AVX512DQ-NEXT: vshufi64x2 $84, {{[-0-9]+}}(%r{{[sb]}}p), %zmm0, %zmm0 # 64-byte Folded Reload +; AVX512DQ-NEXT: # zmm0 = zmm0[0,1,2,3],mem[2,3,2,3] +; AVX512DQ-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm10 +; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm28, %zmm10 +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm0 = zmm27[0,1,0,1,4,5,4,5] +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm2 = zmm2[0,1,0,1,4,5,4,5] ; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm2 -; AVX512DQ-NEXT: vpermq $68, {{[-0-9]+}}(%r{{[sb]}}p), %zmm0 # 64-byte Folded Reload -; AVX512DQ-NEXT: # zmm0 = mem[0,1,0,1,4,5,4,5] -; AVX512DQ-NEXT: vpermq {{.*#+}} zmm1 = zmm12[0,1,0,1,4,5,4,5] -; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm1 -; AVX512DQ-NEXT: vpermq {{.*#+}} zmm0 = zmm7[0,0,1,0,4,4,5,4] -; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm11, %zmm0 -; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm0 +; AVX512DQ-NEXT: vpermq {{.*#+}} zmm0 = zmm5[0,0,1,0,4,4,5,4] +; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm8, %zmm0 +; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm0 +; AVX512DQ-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Reload +; AVX512DQ-NEXT: vshufi64x2 $85, {{[-0-9]+}}(%r{{[sb]}}p), %zmm2, %zmm2 # 64-byte Folded Reload +; AVX512DQ-NEXT: # zmm2 = zmm2[2,3,2,3],mem[2,3,2,3] +; AVX512DQ-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm15 +; AVX512DQ-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm18, %zmm15 ; AVX512DQ-NEXT: movq {{[0-9]+}}(%rsp), %rax +; AVX512DQ-NEXT: vmovdqa64 %zmm15, 128(%rax) ; AVX512DQ-NEXT: vmovdqa64 %zmm0, (%rax) -; AVX512DQ-NEXT: vmovdqa64 %zmm2, 320(%rax) -; AVX512DQ-NEXT: vmovdqa64 %zmm26, 256(%rax) -; AVX512DQ-NEXT: vmovdqa64 %zmm16, 128(%rax) +; AVX512DQ-NEXT: vmovdqa64 %zmm10, 320(%rax) +; AVX512DQ-NEXT: vmovdqa64 %zmm14, 256(%rax) +; AVX512DQ-NEXT: vmovdqa64 %zmm1, 192(%rax) ; AVX512DQ-NEXT: vmovdqa64 %zmm4, 384(%rax) -; AVX512DQ-NEXT: vmovdqa64 %zmm3, 192(%rax) -; AVX512DQ-NEXT: vmovdqa64 %zmm24, 64(%rax) -; AVX512DQ-NEXT: addq $1448, %rsp # imm = 0x5A8 +; AVX512DQ-NEXT: vmovdqa64 %zmm16, 64(%rax) +; AVX512DQ-NEXT: addq $1720, %rsp # imm = 0x6B8 ; AVX512DQ-NEXT: vzeroupper ; AVX512DQ-NEXT: retq ; ; AVX512DQ-FCP-LABEL: store_i8_stride7_vf64: ; AVX512DQ-FCP: # %bb.0: -; AVX512DQ-FCP-NEXT: subq $1256, %rsp # imm = 0x4E8 -; AVX512DQ-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax -; AVX512DQ-FCP-NEXT: vmovdqa 32(%rcx), %ymm2 -; AVX512DQ-FCP-NEXT: vmovdqa 32(%rdx), %ymm1 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29],zero,zero -; AVX512DQ-FCP-NEXT: vmovdqa %ymm1, %ymm14 -; AVX512DQ-FCP-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm2[25],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero,zero,zero -; AVX512DQ-FCP-NEXT: vmovdqa %ymm2, %ymm13 +; AVX512DQ-FCP-NEXT: subq $1432, %rsp # imm = 0x598 +; AVX512DQ-FCP-NEXT: vmovdqa 32(%rsi), %ymm2 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29],zero,zero,zero +; AVX512DQ-FCP-NEXT: vmovdqa 32(%rdi), %ymm3 +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm15 = [128,23,128,128,128,128,26,128,24,128,128,128,128,27,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128,25] +; AVX512DQ-FCP-NEXT: # ymm15 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm15, %ymm3, %ymm1 ; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 ; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa 32(%rsi), %ymm1 -; AVX512DQ-FCP-NEXT: vmovdqa 32(%rdi), %ymm2 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29],zero,zero,zero -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm1, %ymm16 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[23],zero,zero,zero,zero,ymm2[26],zero,ymm2[24],zero,zero,zero,zero,ymm2[27],zero,ymm2[25] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,30],zero,ymm3[28],zero,ymm3[30,31,30,31],zero,ymm3[29],zero,ymm3[31,28,29] +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm3, %ymm25 +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm3 = [25,128,23,0,0,0,128,26,128,24,0,0,0,128,27,128,25,128,23,0,0,0,128,26,128,24,0,0,0,128,27,128] +; AVX512DQ-FCP-NEXT: # ymm3 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm3, %ymm2, %ymm1 +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm3, %ymm27 +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm2, %ymm18 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-FCP-NEXT: vmovdqa 32(%rdx), %ymm2 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29],zero,zero +; AVX512DQ-FCP-NEXT: vmovdqa 32(%rcx), %ymm3 +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm4 = [128,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128,128,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128] +; AVX512DQ-FCP-NEXT: # ymm4 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm4, %ymm3, %ymm1 +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm4, %ymm28 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u,u,u],zero,ymm3[30],zero,ymm3[28,u,u,u],zero,ymm3[31],zero,ymm3[29,u] +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm3, %ymm19 +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm3 = [24,25,128,23,128,21,22,23,26,128,24,128,28,29,26,27,24,25,128,23,128,21,22,23,26,128,24,128,28,29,26,27] +; AVX512DQ-FCP-NEXT: # ymm3 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm3, %ymm2, %ymm1 +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm3, %ymm24 ; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm2, %ymm17 ; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 ; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa 32(%r9), %ymm4 -; AVX512DQ-FCP-NEXT: vmovdqa 32(%r8), %ymm1 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[27],zero,zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29] -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm1, %ymm18 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm4[25],zero,ymm4[23],zero,zero,zero,zero,ymm4[26],zero,ymm4[24],zero,zero -; AVX512DQ-FCP-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-FCP-NEXT: vmovdqa 32(%r8), %ymm3 +; AVX512DQ-FCP-NEXT: vmovdqu %ymm3, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm3[27],zero,zero,zero,zero,ymm3[30],zero,ymm3[28],zero,zero,zero,zero,ymm3[31],zero,ymm3[29] +; AVX512DQ-FCP-NEXT: vmovdqa 32(%r9), %ymm2 +; AVX512DQ-FCP-NEXT: vmovdqu %ymm2, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm4 = [128,128,128,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128,128,128,25,128,23,128,128,128,128,26,128,24,128,128] +; AVX512DQ-FCP-NEXT: # ymm4 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm4, %ymm2, %ymm1 +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm4, %ymm23 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm2[27,u,u,u],zero,ymm2[30],zero,ymm2[28,u,u,u],zero,ymm2[31],zero +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [24,25,24,25,128,23,128,23,24,25,26,128,24,128,30,31,24,25,24,25,128,23,128,23,24,25,26,128,24,128,30,31] +; AVX512DQ-FCP-NEXT: # ymm2 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm2, %ymm3, %ymm1 +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm2, %ymm22 ; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 ; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512DQ-FCP-NEXT: vmovdqa 32(%rax), %ymm1 ; AVX512DQ-FCP-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill ; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] ; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] ; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 ; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa (%rsi), %ymm1 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,ymm1[14],zero,zero,zero,zero,zero,zero,ymm1[15],zero,zero,zero,zero,zero,zero,ymm1[16],zero,zero,zero,zero,zero,zero,ymm1[17],zero,zero,zero,zero,zero,zero,ymm1[18] -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm1, %ymm23 -; AVX512DQ-FCP-NEXT: vmovdqa (%rdi), %ymm1 -; AVX512DQ-FCP-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[0,1,14],zero,ymm1[12,13,0,1,14,15],zero,ymm1[3,12,13,2,3,16],zero,ymm1[30,31,28,29,16,17],zero,ymm1[31,18,19,28,29,18],zero +; AVX512DQ-FCP-NEXT: vmovdqa (%rsi), %ymm5 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,ymm5[14],zero,zero,zero,zero,zero,zero,ymm5[15],zero,zero,zero,zero,zero,zero,ymm5[16],zero,zero,zero,zero,zero,zero,ymm5[17],zero,zero,zero,zero,zero,zero,ymm5[18] +; AVX512DQ-FCP-NEXT: vmovdqa (%rdi), %ymm4 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm4[0,1,14],zero,ymm4[12,13,0,1,14,15],zero,ymm4[3,12,13,2,3,16],zero,ymm4[30,31,28,29,16,17],zero,ymm4[31,18,19,28,29,18],zero ; AVX512DQ-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512DQ-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa (%rcx), %ymm1 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm7 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] -; AVX512DQ-FCP-NEXT: vpshufb %ymm7, %ymm1, %ymm0 -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm1, %ymm26 +; AVX512DQ-FCP-NEXT: vmovdqa (%rcx), %ymm3 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,zero,zero,ymm3[14],zero,zero,zero,zero,zero,zero,ymm3[15],zero,zero,zero,zero,zero,zero,ymm3[16],zero,zero,zero,zero,zero,zero,ymm3[17],zero,zero,zero,zero,zero ; AVX512DQ-FCP-NEXT: vmovdqa (%rdx), %ymm2 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm1 = [0,1,0,1,14,128,14,15,0,1,14,15,128,13,14,15,16,17,16,128,30,31,30,31,16,17,128,31,28,29,30,31] -; AVX512DQ-FCP-NEXT: vpshufb %ymm1, %ymm2, %ymm3 -; AVX512DQ-FCP-NEXT: vpor %ymm0, %ymm3, %ymm0 -; AVX512DQ-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa (%r8), %ymm0 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[0,1,0,1,14],zero,ymm2[14,15,0,1,14,15],zero,ymm2[13,14,15,16,17,16],zero,ymm2[30,31,30,31,16,17],zero,ymm2[31,28,29,30,31] +; AVX512DQ-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512DQ-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm5 = [128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128] -; AVX512DQ-FCP-NEXT: vpshufb %ymm5, %ymm0, %ymm3 -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm5, %ymm25 -; AVX512DQ-FCP-NEXT: vmovdqa (%r9), %ymm5 -; AVX512DQ-FCP-NEXT: vmovdqu %ymm5, (%rsp) # 32-byte Spill -; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm0 = [13,0,0,0,128,16,128,14,0,0,0,128,17,128,15,0,13,0,0,0,128,16,128,14,0,0,0,128,17,128,15,0] -; AVX512DQ-FCP-NEXT: # ymm0 = mem[0,1,0,1] -; AVX512DQ-FCP-NEXT: vpshufb %ymm0, %ymm5, %ymm5 -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm0, %ymm30 -; AVX512DQ-FCP-NEXT: vporq %ymm3, %ymm5, %ymm24 -; AVX512DQ-FCP-NEXT: vmovdqa 32(%rdx), %xmm3 -; AVX512DQ-FCP-NEXT: vmovdqa 32(%rcx), %xmm6 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm8 = [u,u,u,128,7,128,5,u,u,u,128,8,128,6,u,u] -; AVX512DQ-FCP-NEXT: vpshufb %xmm8, %xmm6, %xmm5 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm6, %xmm28 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm9 = [u,u,u,7,128,5,128,u,u,u,8,128,6,128,u,u] -; AVX512DQ-FCP-NEXT: vpshufb %xmm9, %xmm3, %xmm6 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm9, %xmm19 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm3, %xmm29 -; AVX512DQ-FCP-NEXT: vpor %xmm5, %xmm6, %xmm3 -; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm3, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa 32(%rdi), %xmm10 -; AVX512DQ-FCP-NEXT: vmovdqa 32(%rsi), %xmm6 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm11 = [u,128,7,128,5,u,u,u,128,8,128,6,u,u,u,128] -; AVX512DQ-FCP-NEXT: vpshufb %xmm11, %xmm6, %xmm5 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm3 = [u,7,128,5,128,u,u,u,8,128,6,128,u,u,u,9] -; AVX512DQ-FCP-NEXT: vpshufb %xmm3, %xmm10, %xmm9 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm10, %xmm27 -; AVX512DQ-FCP-NEXT: vpor %xmm5, %xmm9, %xmm5 -; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm5, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa 32(%r9), %xmm15 -; AVX512DQ-FCP-NEXT: vmovdqa 32(%r8), %xmm10 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm5 = [128,4,u,u,u,128,7,128,5,u,u,u,128,8,128,6] -; AVX512DQ-FCP-NEXT: vpshufb %xmm5, %xmm15, %xmm9 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm0 = [4,128,u,u,u,7,128,5,128,u,u,u,8,128,6,128] -; AVX512DQ-FCP-NEXT: vpshufb %xmm0, %xmm10, %xmm12 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm0, %xmm21 -; AVX512DQ-FCP-NEXT: vporq %xmm9, %xmm12, %xmm22 -; AVX512DQ-FCP-NEXT: vpshufb %ymm7, %ymm13, %ymm7 -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm13, %ymm20 -; AVX512DQ-FCP-NEXT: vpshufb %ymm1, %ymm14, %ymm1 -; AVX512DQ-FCP-NEXT: vpor %ymm7, %ymm1, %ymm1 -; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm16, %ymm7 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = zero,zero,zero,ymm7[14],zero,zero,zero,zero,zero,zero,ymm7[15],zero,zero,zero,zero,zero,zero,ymm7[16],zero,zero,zero,zero,zero,zero,ymm7[17],zero,zero,zero,zero,zero,zero,ymm7[18] -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm17, %ymm7 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm7[0,1,14],zero,ymm7[12,13,0,1,14,15],zero,ymm7[3,12,13,2,3,16],zero,ymm7[30,31,28,29,16,17],zero,ymm7[31,18,19,28,29,18],zero -; AVX512DQ-FCP-NEXT: vpor %ymm1, %ymm7, %ymm1 -; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm18, %ymm1 -; AVX512DQ-FCP-NEXT: vmovdqu64 %ymm18, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm25, %ymm7 -; AVX512DQ-FCP-NEXT: vpshufb %ymm7, %ymm1, %ymm1 -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm30, %ymm0 -; AVX512DQ-FCP-NEXT: vpshufb %ymm0, %ymm4, %ymm0 -; AVX512DQ-FCP-NEXT: vpor %ymm1, %ymm0, %ymm0 -; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa (%rsi), %xmm13 -; AVX512DQ-FCP-NEXT: vpshufb %xmm11, %xmm13, %xmm0 +; AVX512DQ-FCP-NEXT: vmovdqa (%r8), %ymm1 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm6 = zero,zero,zero,zero,zero,zero,ymm1[14],zero,zero,zero,zero,zero,zero,ymm1[15],zero,zero,zero,zero,zero,zero,ymm1[16],zero,zero,zero,zero,zero,zero,ymm1[17],zero,zero,zero,zero +; AVX512DQ-FCP-NEXT: vmovdqa (%r9), %ymm0 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm7 = ymm0[13,u,u,u,u,u],zero,ymm0[14,u,u,u,u,u],zero,ymm0[15,u,u,u,u,u],zero,ymm0[16,u,u,u,u,u],zero,ymm0[17,u,u,u] +; AVX512DQ-FCP-NEXT: vpor %ymm6, %ymm7, %ymm6 +; AVX512DQ-FCP-NEXT: vmovdqu %ymm6, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-FCP-NEXT: vmovdqa 32(%rdx), %xmm9 +; AVX512DQ-FCP-NEXT: vmovdqa %xmm9, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512DQ-FCP-NEXT: vmovdqa 32(%rcx), %xmm7 +; AVX512DQ-FCP-NEXT: vmovdqa %xmm7, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm6 = [u,u,u,128,7,128,5,u,u,u,128,8,128,6,u,u] +; AVX512DQ-FCP-NEXT: vpshufb %xmm6, %xmm7, %xmm7 +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm8 = [u,u,u,7,128,5,128,u,u,u,8,128,6,128,u,u] +; AVX512DQ-FCP-NEXT: vpshufb %xmm8, %xmm9, %xmm9 +; AVX512DQ-FCP-NEXT: vpor %xmm7, %xmm9, %xmm7 +; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm7, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-FCP-NEXT: vmovdqa 32(%rdi), %xmm11 +; AVX512DQ-FCP-NEXT: vmovdqa %xmm11, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512DQ-FCP-NEXT: vmovdqa 32(%rsi), %xmm9 +; AVX512DQ-FCP-NEXT: vmovdqa %xmm9, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm7 = [u,128,7,128,5,u,u,u,128,8,128,6,u,u,u,128] +; AVX512DQ-FCP-NEXT: vpshufb %xmm7, %xmm9, %xmm9 +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm10 = [u,7,128,5,128,u,u,u,8,128,6,128,u,u,u,9] +; AVX512DQ-FCP-NEXT: vpshufb %xmm10, %xmm11, %xmm11 +; AVX512DQ-FCP-NEXT: vpor %xmm9, %xmm11, %xmm9 +; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm9, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-FCP-NEXT: vmovdqa 32(%r9), %xmm9 +; AVX512DQ-FCP-NEXT: vmovdqa %xmm9, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512DQ-FCP-NEXT: vmovdqa 32(%r8), %xmm14 +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm12 = [128,4,u,u,u,128,7,128,5,u,u,u,128,8,128,6] +; AVX512DQ-FCP-NEXT: vpshufb %xmm12, %xmm9, %xmm9 +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm13 = [4,128,u,u,u,7,128,5,128,u,u,u,8,128,6,128] +; AVX512DQ-FCP-NEXT: vpshufb %xmm13, %xmm14, %xmm11 +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm14, %xmm30 +; AVX512DQ-FCP-NEXT: vpor %xmm9, %xmm11, %xmm9 +; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm9, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-FCP-NEXT: vmovdqa (%rsi), %xmm9 +; AVX512DQ-FCP-NEXT: vpshufb %xmm7, %xmm9, %xmm7 +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm9, %xmm26 ; AVX512DQ-FCP-NEXT: vmovdqa (%rdi), %xmm9 -; AVX512DQ-FCP-NEXT: vpshufb %xmm3, %xmm9, %xmm1 -; AVX512DQ-FCP-NEXT: vporq %xmm0, %xmm1, %xmm31 -; AVX512DQ-FCP-NEXT: vmovdqa (%rcx), %xmm14 -; AVX512DQ-FCP-NEXT: vpshufb %xmm8, %xmm14, %xmm0 -; AVX512DQ-FCP-NEXT: vmovdqa (%rdx), %xmm8 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm19, %xmm1 -; AVX512DQ-FCP-NEXT: vpshufb %xmm1, %xmm8, %xmm1 -; AVX512DQ-FCP-NEXT: vpor %xmm0, %xmm1, %xmm0 -; AVX512DQ-FCP-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa (%r9), %xmm1 -; AVX512DQ-FCP-NEXT: vpshufb %xmm5, %xmm1, %xmm0 -; AVX512DQ-FCP-NEXT: vmovdqa %xmm1, %xmm3 -; AVX512DQ-FCP-NEXT: vmovdqa %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa (%r8), %xmm4 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm21, %xmm1 -; AVX512DQ-FCP-NEXT: vpshufb %xmm1, %xmm4, %xmm1 -; AVX512DQ-FCP-NEXT: vmovdqa %xmm4, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512DQ-FCP-NEXT: vpor %xmm0, %xmm1, %xmm0 +; AVX512DQ-FCP-NEXT: vpshufb %xmm10, %xmm9, %xmm10 +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm9, %xmm21 +; AVX512DQ-FCP-NEXT: vpor %xmm7, %xmm10, %xmm7 +; AVX512DQ-FCP-NEXT: vmovdqa %xmm7, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512DQ-FCP-NEXT: vmovdqa (%rcx), %xmm7 +; AVX512DQ-FCP-NEXT: vpshufb %xmm6, %xmm7, %xmm6 +; AVX512DQ-FCP-NEXT: vmovdqa (%rdx), %xmm10 +; AVX512DQ-FCP-NEXT: vpshufb %xmm8, %xmm10, %xmm8 +; AVX512DQ-FCP-NEXT: vpor %xmm6, %xmm8, %xmm6 +; AVX512DQ-FCP-NEXT: vmovdqa %xmm6, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512DQ-FCP-NEXT: vmovdqa (%r9), %xmm11 +; AVX512DQ-FCP-NEXT: vpshufb %xmm12, %xmm11, %xmm12 +; AVX512DQ-FCP-NEXT: vmovdqa (%r8), %xmm6 +; AVX512DQ-FCP-NEXT: vpshufb %xmm13, %xmm6, %xmm13 +; AVX512DQ-FCP-NEXT: vmovdqa %xmm6, %xmm9 +; AVX512DQ-FCP-NEXT: vporq %xmm12, %xmm13, %xmm31 +; AVX512DQ-FCP-NEXT: vpshufb %ymm15, %ymm4, %ymm12 +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm8 = [128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128] +; AVX512DQ-FCP-NEXT: # ymm8 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm8, %ymm5, %ymm13 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm12, %zmm13, %zmm6 +; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm6, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm27, %ymm6 +; AVX512DQ-FCP-NEXT: vpshufb %ymm6, %ymm5, %ymm12 +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm6 = [18,19,20,21,128,19,128,21,20,21,22,128,20,128,22,23,18,19,20,21,128,19,128,21,20,21,22,128,20,128,22,23] +; AVX512DQ-FCP-NEXT: # ymm6 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm6, %ymm4, %ymm13 +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm6, %ymm20 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm12, %zmm13, %zmm29 +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm28, %ymm6 +; AVX512DQ-FCP-NEXT: vpshufb %ymm6, %ymm3, %ymm12 +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm6 = [128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20] +; AVX512DQ-FCP-NEXT: # ymm6 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm6, %ymm3, %ymm13 +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm6, %ymm16 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm12, %zmm13, %zmm28 +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm24, %ymm6 +; AVX512DQ-FCP-NEXT: vpshufb %ymm6, %ymm2, %ymm13 +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm12 = [18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128,18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128] +; AVX512DQ-FCP-NEXT: # ymm12 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm12, %ymm2, %ymm15 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm13, %zmm15, %zmm27 +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm23, %ymm6 +; AVX512DQ-FCP-NEXT: vpshufb %ymm6, %ymm0, %ymm13 +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm22, %ymm6 +; AVX512DQ-FCP-NEXT: vpshufb %ymm6, %ymm1, %ymm15 +; AVX512DQ-FCP-NEXT: vpor %ymm13, %ymm15, %ymm6 +; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm6, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm6 = [128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22] +; AVX512DQ-FCP-NEXT: # ymm6 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm6, %ymm0, %ymm15 +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm6, %ymm24 +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm13 = [20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128,20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128] +; AVX512DQ-FCP-NEXT: # ymm13 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpshufb %ymm13, %ymm1, %ymm14 +; AVX512DQ-FCP-NEXT: vpor %ymm15, %ymm14, %ymm6 +; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm6, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero,ymm5[29],zero,zero,zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,30],zero,ymm4[28],zero,ymm4[30,31,30,31],zero,ymm4[29],zero,ymm4[31,28,29] +; AVX512DQ-FCP-NEXT: vpor %ymm5, %ymm4, %ymm4 +; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm4, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29],zero,zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27,u,u,u],zero,ymm3[30],zero,ymm3[28,u,u,u],zero,ymm3[31],zero,ymm3[29,u] +; AVX512DQ-FCP-NEXT: vporq %ymm2, %ymm3, %ymm23 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm1[27],zero,zero,zero,zero,ymm1[30],zero,ymm1[28],zero,zero,zero,zero,ymm1[31],zero,ymm1[29] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm0[27,u,u,u],zero,ymm0[30],zero,ymm0[28,u,u,u],zero,ymm0[31],zero +; AVX512DQ-FCP-NEXT: vporq %ymm1, %ymm0, %ymm22 +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm19, %ymm2 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,zero,zero,ymm2[14],zero,zero,zero,zero,zero,zero,ymm2[15],zero,zero,zero,zero,zero,zero,ymm2[16],zero,zero,zero,zero,zero,zero,ymm2[17],zero,zero,zero,zero,zero +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm17, %ymm3 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm3[0,1,0,1,14],zero,ymm3[14,15,0,1,14,15],zero,ymm3[13,14,15,16,17,16],zero,ymm3[30,31,30,31,16,17],zero,ymm3[31,28,29,30,31] +; AVX512DQ-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[23],zero,zero,zero,zero,ymm0[26],zero,ymm0[24],zero,zero,zero,zero,ymm0[27],zero,ymm0[25] -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm23, %ymm12 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm12[21],zero,ymm12[19],zero,zero,zero,zero,ymm12[22],zero,ymm12[20],zero,zero -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm16, %ymm0 +; AVX512DQ-FCP-NEXT: vpshufb %ymm0, %ymm2, %ymm0 +; AVX512DQ-FCP-NEXT: vpshufb %ymm12, %ymm3, %ymm1 +; AVX512DQ-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX512DQ-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm18, %ymm3 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,ymm3[14],zero,zero,zero,zero,zero,zero,ymm3[15],zero,zero,zero,zero,zero,zero,ymm3[16],zero,zero,zero,zero,zero,zero,ymm3[17],zero,zero,zero,zero,zero,zero,ymm3[18] +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm25, %ymm2 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[0,1,14],zero,ymm2[12,13,0,1,14,15],zero,ymm2[3,12,13,2,3,16],zero,ymm2[30,31,28,29,16,17],zero,ymm2[31,18,19,28,29,18],zero +; AVX512DQ-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm26, %ymm11 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm11[25],zero,ymm11[23],zero,zero,zero,zero,ymm11[26],zero,ymm11[24],zero,zero,zero,zero -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm11[18],zero,zero,zero,zero,ymm11[21],zero,ymm11[19],zero,zero,zero,zero,ymm11[22],zero,ymm11[20] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512DQ-FCP-NEXT: vpshufb %ymm8, %ymm3, %ymm0 +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm20, %ymm1 +; AVX512DQ-FCP-NEXT: vpshufb %ymm1, %ymm2, %ymm1 +; AVX512DQ-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX512DQ-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm3 # 32-byte Reload +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm24, %ymm0 +; AVX512DQ-FCP-NEXT: vpshufb %ymm0, %ymm3, %ymm0 +; AVX512DQ-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload +; AVX512DQ-FCP-NEXT: vpshufb %ymm13, %ymm2, %ymm1 +; AVX512DQ-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [24,25,128,23,128,21,22,23,26,128,24,128,28,29,26,27,24,25,128,23,128,21,22,23,26,128,24,128,28,29,26,27] -; AVX512DQ-FCP-NEXT: # ymm1 = mem[0,1,0,1] -; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm5 = [18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128,18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128] -; AVX512DQ-FCP-NEXT: # ymm5 = mem[0,1,0,1] -; AVX512DQ-FCP-NEXT: vpshufb %ymm1, %ymm2, %ymm0 -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm1, %ymm19 -; AVX512DQ-FCP-NEXT: vpshufb %ymm5, %ymm2, %ymm1 -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm5, %ymm30 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm0 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,zero,zero,zero,ymm2[14],zero,zero,zero,zero,zero,zero,ymm2[15],zero,zero,zero,zero,zero,zero,ymm2[16],zero,zero,zero,zero,zero,zero,ymm2[17],zero,zero,zero,zero +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm3[13,u,u,u,u,u],zero,ymm3[14,u,u,u,u,u],zero,ymm3[15,u,u,u,u,u],zero,ymm3[16,u,u,u,u,u],zero,ymm3[17,u,u,u] +; AVX512DQ-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 ; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm24, %zmm0, %zmm0 -; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm4[8],xmm3[8],xmm4[9],xmm3[9],xmm4[10],xmm3[10],xmm4[11],xmm3[11],xmm4[12],xmm3[12],xmm4[13],xmm3[13],xmm4[14],xmm3[14],xmm4[15],xmm3[15] -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm3 = [u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] -; AVX512DQ-FCP-NEXT: vpshufb %xmm3, %xmm1, %xmm1 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm0, %zmm0 # 32-byte Folded Reload +; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm9[8],xmm11[8],xmm9[9],xmm11[9],xmm9[10],xmm11[10],xmm9[11],xmm11[11],xmm9[12],xmm11[12],xmm9[13],xmm11[13],xmm9[14],xmm11[14],xmm9[15],xmm11[15] +; AVX512DQ-FCP-NEXT: vmovdqa %xmm9, %xmm8 +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm11, %xmm17 +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm9 = [u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] +; AVX512DQ-FCP-NEXT: vpshufb %xmm9, %xmm1, %xmm1 ; AVX512DQ-FCP-NEXT: vshufi64x2 {{.*#+}} zmm0 = zmm1[0,1,0,1],zmm0[4,5,6,7] ; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [2,2,3,3,2,2,3,3] -; AVX512DQ-FCP-NEXT: # ymm1 = mem[0,1,0,1] +; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm6 = [2,2,3,3,2,2,3,3] +; AVX512DQ-FCP-NEXT: # ymm6 = mem[0,1,0,1] ; AVX512DQ-FCP-NEXT: vmovdqa (%rax), %xmm0 -; AVX512DQ-FCP-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512DQ-FCP-NEXT: vpshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,4,5,5,6] -; AVX512DQ-FCP-NEXT: vpermd %ymm0, %ymm1, %ymm0 -; AVX512DQ-FCP-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 -; AVX512DQ-FCP-NEXT: vmovdqa (%rax), %ymm4 -; AVX512DQ-FCP-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} ymm5 = [128,13,128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128] -; AVX512DQ-FCP-NEXT: vpshufb %ymm5, %ymm4, %ymm4 -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm5, %ymm18 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm0, %zmm24 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29],zero,zero -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm0, %ymm23 -; AVX512DQ-FCP-NEXT: vpbroadcastq {{.*#+}} ymm2 = [13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14] -; AVX512DQ-FCP-NEXT: vmovdqu (%rsp), %ymm0 # 32-byte Reload -; AVX512DQ-FCP-NEXT: vpshufb %ymm2, %ymm0, %ymm0 -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm2, %ymm25 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX512DQ-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm2[27],zero,zero,zero,zero,ymm2[30],zero,ymm2[28],zero,zero,zero,zero,ymm2[31],zero,ymm2[29] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] -; AVX512DQ-FCP-NEXT: vbroadcasti32x4 {{.*#+}} ymm26 = [18374967954648269055,71777218572844800,18374967954648269055,71777218572844800] -; AVX512DQ-FCP-NEXT: # ymm26 = mem[0,1,2,3,0,1,2,3] -; AVX512DQ-FCP-NEXT: vpternlogq $248, %ymm26, %ymm0, %ymm2 -; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm10[0],xmm15[0],xmm10[1],xmm15[1],xmm10[2],xmm15[2],xmm10[3],xmm15[3],xmm10[4],xmm15[4],xmm10[5],xmm15[5],xmm10[6],xmm15[6],xmm10[7],xmm15[7] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] -; AVX512DQ-FCP-NEXT: vshufi64x2 {{.*#+}} zmm21 = zmm2[0,1,2,3],zmm0[0,1,0,1] -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm29, %xmm0 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm28, %xmm2 -; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm7 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3],xmm0[4],xmm2[4],xmm0[5],xmm2[5],xmm0[6],xmm2[6],xmm0[7],xmm2[7] -; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm0 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] -; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm14[8],xmm8[8],xmm14[9],xmm8[9],xmm14[10],xmm8[10],xmm14[11],xmm8[11],xmm14[12],xmm8[12],xmm14[13],xmm8[13],xmm14[14],xmm8[14],xmm14[15],xmm8[15] -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm4 = [6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] -; AVX512DQ-FCP-NEXT: vpshufb %xmm4, %xmm2, %xmm2 -; AVX512DQ-FCP-NEXT: vmovdqu %ymm2, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-FCP-NEXT: vpshufb %xmm4, %xmm0, %xmm0 -; AVX512DQ-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Reload -; AVX512DQ-FCP-NEXT: vinserti32x4 $2, %xmm0, %zmm2, %zmm28 -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm27, %xmm0 -; AVX512DQ-FCP-NEXT: vmovdqa %xmm6, %xmm2 -; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm6 = xmm0[0],xmm6[0],xmm0[1],xmm6[1],xmm0[2],xmm6[2],xmm0[3],xmm6[3],xmm0[4],xmm6[4],xmm0[5],xmm6[5],xmm0[6],xmm6[6],xmm0[7],xmm6[7] -; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] -; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm13[8],xmm9[8],xmm13[9],xmm9[9],xmm13[10],xmm9[10],xmm13[11],xmm9[11],xmm13[12],xmm9[12],xmm13[13],xmm9[13],xmm13[14],xmm9[14],xmm13[15],xmm9[15] -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm5 = [2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] -; AVX512DQ-FCP-NEXT: vpshufb %xmm5, %xmm4, %xmm0 -; AVX512DQ-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-FCP-NEXT: vpshufb %xmm5, %xmm2, %xmm2 -; AVX512DQ-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm0 # 64-byte Reload -; AVX512DQ-FCP-NEXT: vinserti32x4 $2, %xmm2, %zmm0, %zmm27 -; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm10[8],xmm15[8],xmm10[9],xmm15[9],xmm10[10],xmm15[10],xmm10[11],xmm15[11],xmm10[12],xmm15[12],xmm10[13],xmm15[13],xmm10[14],xmm15[14],xmm10[15],xmm15[15] -; AVX512DQ-FCP-NEXT: vpshufb %xmm3, %xmm2, %xmm2 -; AVX512DQ-FCP-NEXT: vshufi64x2 {{.*#+}} zmm0 = zmm22[0,1,0,1],zmm2[0,1,0,1] -; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-FCP-NEXT: vmovdqa 32(%rax), %xmm0 -; AVX512DQ-FCP-NEXT: vpshufhw {{.*#+}} xmm2 = xmm0[0,1,2,3,4,5,5,6] -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm0, %xmm29 -; AVX512DQ-FCP-NEXT: vpermd %ymm2, %ymm1, %ymm0 -; AVX512DQ-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-FCP-NEXT: vpbroadcastq {{.*#+}} ymm1 = [11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12] -; AVX512DQ-FCP-NEXT: vpshufb %ymm1, %ymm11, %ymm5 -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm20, %ymm0 -; AVX512DQ-FCP-NEXT: vpshufb %ymm1, %ymm0, %ymm1 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm22 = ymm1[2,3,2,3] -; AVX512DQ-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm19, %ymm1 -; AVX512DQ-FCP-NEXT: vpshufb %ymm1, %ymm2, %ymm1 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm20 = ymm1[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm0[18],zero,zero,zero,zero,ymm0[21],zero,ymm0[19],zero,zero,zero,zero,ymm0[22],zero,ymm0[20] -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm30, %ymm0 -; AVX512DQ-FCP-NEXT: vpshufb %ymm0, %ymm2, %ymm4 -; AVX512DQ-FCP-NEXT: vpbroadcastq {{.*#+}} ymm2 = [9,8,7,0,0,0,11,10,9,8,7,0,0,0,11,10,9,8,7,0,0,0,11,10,9,8,7,0,0,0,11,10] -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm16, %ymm0 -; AVX512DQ-FCP-NEXT: vpshufb %ymm2, %ymm0, %ymm1 -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm2, %ymm30 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm19 = ymm1[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm11 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm0[21],zero,ymm0[19],zero,zero,zero,zero,ymm0[22],zero,ymm0[20],zero,zero -; AVX512DQ-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm18, %ymm1 -; AVX512DQ-FCP-NEXT: vpshufb %ymm1, %ymm0, %ymm3 -; AVX512DQ-FCP-NEXT: vpshuflw {{.*#+}} ymm0 = ymm0[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] -; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} ymm1 = [4,5,4,5,5,7,4,5] -; AVX512DQ-FCP-NEXT: vpermd %ymm0, %ymm1, %ymm0 -; AVX512DQ-FCP-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm3, %zmm16 -; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm9[0],xmm13[0],xmm9[1],xmm13[1],xmm9[2],xmm13[2],xmm9[3],xmm13[3],xmm9[4],xmm13[4],xmm9[5],xmm13[5],xmm9[6],xmm13[6],xmm9[7],xmm13[7] -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm9 = [0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] -; AVX512DQ-FCP-NEXT: vpshufb %xmm9, %xmm6, %xmm6 -; AVX512DQ-FCP-NEXT: vpshufb %xmm9, %xmm0, %xmm0 -; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm9 = [28,29,30,128,28,128,30,31,30,31,128,29,128,31,28,29,28,29,30,128,28,128,30,31,30,31,128,29,128,31,28,29] -; AVX512DQ-FCP-NEXT: # ymm9 = mem[0,1,0,1] -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm17, %ymm3 -; AVX512DQ-FCP-NEXT: vpshufb %ymm9, %ymm3, %ymm15 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm17 = ymm15[2,3,2,3] -; AVX512DQ-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm1 # 32-byte Reload -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm25, %ymm2 -; AVX512DQ-FCP-NEXT: vpshufb %ymm2, %ymm1, %ymm13 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm18 = ymm13[2,3,2,3] -; AVX512DQ-FCP-NEXT: vinserti32x4 $2, %xmm31, %zmm0, %zmm0 -; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill -; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm8[0],xmm14[0],xmm8[1],xmm14[1],xmm8[2],xmm14[2],xmm8[3],xmm14[3],xmm8[4],xmm14[4],xmm8[5],xmm14[5],xmm8[6],xmm14[6],xmm8[7],xmm14[7] -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm8 = [4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] -; AVX512DQ-FCP-NEXT: vpshufb %xmm8, %xmm7, %xmm7 -; AVX512DQ-FCP-NEXT: vpshufb %xmm8, %xmm0, %xmm13 -; AVX512DQ-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Reload -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm8 = ymm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,ymm0[23],zero,ymm0[23,24,25,26],zero,ymm0[24],zero,ymm0[30,31] +; AVX512DQ-FCP-NEXT: vpshufhw {{.*#+}} xmm1 = xmm0[0,1,2,3,4,5,5,6] +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm0, %xmm19 +; AVX512DQ-FCP-NEXT: vpermd %ymm1, %ymm6, %ymm1 +; AVX512DQ-FCP-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm1, %ymm3 +; AVX512DQ-FCP-NEXT: vmovdqa (%rax), %ymm12 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm5 = zero,ymm12[13],zero,zero,zero,zero,zero,zero,ymm12[14],zero,zero,zero,zero,zero,zero,ymm12[15],zero,zero,zero,zero,zero,zero,ymm12[16],zero,zero,zero,zero,zero,zero,ymm12[17],zero,zero +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm5, %zmm3, %zmm20 +; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm7[8],xmm10[8],xmm7[9],xmm10[9],xmm7[10],xmm10[10],xmm7[11],xmm10[11],xmm7[12],xmm10[12],xmm7[13],xmm10[13],xmm7[14],xmm10[14],xmm7[15],xmm10[15] +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm1 = [6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] +; AVX512DQ-FCP-NEXT: vpshufb %xmm1, %xmm5, %xmm0 ; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm0, %ymm25 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm15 = ymm8[2,3,2,3] -; AVX512DQ-FCP-NEXT: vmovdqa %ymm12, %ymm1 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm12 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm12[30],zero,ymm12[28],zero,zero,zero,zero,ymm12[31],zero,ymm12[29],zero,zero,zero -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] -; AVX512DQ-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload -; AVX512DQ-FCP-NEXT: vpshufb %ymm9, %ymm2, %ymm9 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[0,1,0,1] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm23[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm7 = ymm7[0,1,0,1] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm8 = ymm11[2,3,2,3] -; AVX512DQ-FCP-NEXT: vinserti32x4 $2, {{[-0-9]+}}(%r{{[sb]}}p), %zmm13, %zmm31 # 16-byte Folded Reload -; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm11 = [18,19,20,21,128,19,128,21,20,21,22,128,20,128,22,23,18,19,20,21,128,19,128,21,20,21,22,128,20,128,22,23] -; AVX512DQ-FCP-NEXT: # ymm11 = mem[0,1,0,1] -; AVX512DQ-FCP-NEXT: vpshufb %ymm11, %ymm3, %ymm14 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm14 = ymm14[2,3,2,3] -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm30, %ymm3 -; AVX512DQ-FCP-NEXT: vpshufb %ymm3, %ymm1, %ymm13 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpshufb %ymm11, %ymm2, %ymm1 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpor %ymm12, %ymm9, %ymm9 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm6, %zmm9, %zmm6 -; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm9 = [18374966859431673855,18446463693966278655,18374966859431673855,18446463693966278655] -; AVX512DQ-FCP-NEXT: # ymm9 = mem[0,1,0,1] -; AVX512DQ-FCP-NEXT: vpternlogq $248, %ymm9, %ymm5, %ymm0 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm0, %zmm7 -; AVX512DQ-FCP-NEXT: vmovdqa64 {{.*#+}} zmm0 = [255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255] -; AVX512DQ-FCP-NEXT: vpternlogq $226, %zmm6, %zmm0, %zmm7 -; AVX512DQ-FCP-NEXT: vpor %ymm4, %ymm10, %ymm4 +; AVX512DQ-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm11 # 16-byte Reload +; AVX512DQ-FCP-NEXT: vmovdqa64 {{[-0-9]+}}(%r{{[sb]}}p), %xmm16 # 16-byte Reload +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm16, %xmm2 +; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm11[8],xmm2[8],xmm11[9],xmm2[9],xmm11[10],xmm2[10],xmm11[11],xmm2[11],xmm11[12],xmm2[12],xmm11[13],xmm2[13],xmm11[14],xmm2[14],xmm11[15],xmm2[15] +; AVX512DQ-FCP-NEXT: vpshufb %xmm1, %xmm5, %xmm1 ; AVX512DQ-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Reload -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm2, %zmm4 -; AVX512DQ-FCP-NEXT: vpor %ymm8, %ymm14, %ymm2 +; AVX512DQ-FCP-NEXT: vinserti32x4 $2, %xmm1, %zmm2, %zmm18 +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm26, %xmm2 +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm21, %xmm0 +; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm1 = [2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] +; AVX512DQ-FCP-NEXT: vpshufb %xmm1, %xmm5, %xmm3 +; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm3, %ymm21 +; AVX512DQ-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm14 # 16-byte Reload +; AVX512DQ-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm4 # 16-byte Reload +; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm13 = xmm14[8],xmm4[8],xmm14[9],xmm4[9],xmm14[10],xmm4[10],xmm14[11],xmm4[11],xmm14[12],xmm4[12],xmm14[13],xmm4[13],xmm14[14],xmm4[14],xmm14[15],xmm4[15] +; AVX512DQ-FCP-NEXT: vpshufb %xmm1, %xmm13, %xmm1 ; AVX512DQ-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm3, %zmm5 -; AVX512DQ-FCP-NEXT: vpternlogq $226, %zmm4, %zmm0, %zmm5 -; AVX512DQ-FCP-NEXT: vpandq %ymm9, %ymm22, %ymm0 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm20, %zmm0 -; AVX512DQ-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Folded Reload -; AVX512DQ-FCP-NEXT: # zmm2 = mem[2,3,2,3,6,7,6,7] -; AVX512DQ-FCP-NEXT: vporq %zmm2, %zmm0, %zmm0 -; AVX512DQ-FCP-NEXT: vpandq %ymm26, %ymm19, %ymm2 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm17, %zmm2, %zmm2 -; AVX512DQ-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm4 # 64-byte Folded Reload -; AVX512DQ-FCP-NEXT: # zmm4 = mem[2,3,2,3,6,7,6,7] -; AVX512DQ-FCP-NEXT: vporq %zmm4, %zmm2, %zmm2 -; AVX512DQ-FCP-NEXT: vpternlogq $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm2 -; AVX512DQ-FCP-NEXT: vpandq %ymm26, %ymm18, %ymm0 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm15, %zmm0 -; AVX512DQ-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm4 # 64-byte Folded Reload -; AVX512DQ-FCP-NEXT: # zmm4 = mem[2,3,2,3,6,7,6,7] -; AVX512DQ-FCP-NEXT: vporq %zmm4, %zmm0, %zmm0 -; AVX512DQ-FCP-NEXT: vmovdqa64 {{.*#+}} zmm4 = [255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255] -; AVX512DQ-FCP-NEXT: vpternlogq $184, %zmm2, %zmm4, %zmm0 -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm2 = zmm28[0,1,0,1,4,5,4,5] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm8 = zmm27[0,1,0,1,4,5,4,5] -; AVX512DQ-FCP-NEXT: vpternlogq $226, %zmm2, %zmm4, %zmm8 -; AVX512DQ-FCP-NEXT: vpandq %ymm26, %ymm13, %ymm2 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm1, %zmm1 -; AVX512DQ-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Folded Reload -; AVX512DQ-FCP-NEXT: # zmm2 = mem[2,3,2,3,6,7,6,7] -; AVX512DQ-FCP-NEXT: vporq %zmm2, %zmm1, %zmm1 -; AVX512DQ-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Folded Reload -; AVX512DQ-FCP-NEXT: # zmm2 = mem[2,3,2,3,6,7,6,7] -; AVX512DQ-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm6 # 64-byte Folded Reload -; AVX512DQ-FCP-NEXT: # zmm6 = mem[2,3,2,3,6,7,6,7] -; AVX512DQ-FCP-NEXT: vporq %zmm2, %zmm6, %zmm9 -; AVX512DQ-FCP-NEXT: vpternlogq $226, %zmm1, %zmm4, %zmm9 -; AVX512DQ-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload -; AVX512DQ-FCP-NEXT: vpunpcklbw {{[-0-9]+}}(%r{{[sb]}}p), %xmm1, %xmm1 # 16-byte Folded Reload -; AVX512DQ-FCP-NEXT: # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1],xmm1[2],mem[2],xmm1[3],mem[3],xmm1[4],mem[4],xmm1[5],mem[5],xmm1[6],mem[6],xmm1[7],mem[7] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} xmm1 = xmm1[u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] -; AVX512DQ-FCP-NEXT: vshufi64x2 $0, {{[-0-9]+}}(%r{{[sb]}}p), %zmm1, %zmm18 # 64-byte Folded Reload -; AVX512DQ-FCP-NEXT: # zmm18 = zmm1[0,1,0,1],mem[0,1,0,1] -; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm29, %xmm3 -; AVX512DQ-FCP-NEXT: vpshuflw {{.*#+}} xmm2 = xmm3[1,1,0,0,4,5,6,7] -; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} ymm4 = [0,1,0,1,2,0,0,1] -; AVX512DQ-FCP-NEXT: vpermd %ymm2, %ymm4, %ymm19 -; AVX512DQ-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload -; AVX512DQ-FCP-NEXT: vpshuflw {{.*#+}} xmm6 = xmm1[1,1,0,0,4,5,6,7] -; AVX512DQ-FCP-NEXT: vpermd %ymm6, %ymm4, %ymm17 -; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm6 = [4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] -; AVX512DQ-FCP-NEXT: vpshufb %xmm6, %xmm3, %xmm10 -; AVX512DQ-FCP-NEXT: vpshufb %xmm6, %xmm1, %xmm6 -; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm11 = [128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22] -; AVX512DQ-FCP-NEXT: # ymm11 = mem[0,1,0,1] -; AVX512DQ-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm1 # 32-byte Reload -; AVX512DQ-FCP-NEXT: vpshufb %ymm11, %ymm1, %ymm12 -; AVX512DQ-FCP-NEXT: vmovdqu (%rsp), %ymm1 # 32-byte Reload -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm13 = ymm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm1[25],zero,ymm1[23],zero,zero,zero,zero,ymm1[26],zero,ymm1[24],zero,zero -; AVX512DQ-FCP-NEXT: vpshufb %ymm11, %ymm1, %ymm11 -; AVX512DQ-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm14 = [20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128,20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128] -; AVX512DQ-FCP-NEXT: # ymm14 = mem[0,1,0,1] -; AVX512DQ-FCP-NEXT: vmovdqa64 %ymm25, %ymm1 -; AVX512DQ-FCP-NEXT: vpshufb %ymm14, %ymm1, %ymm15 -; AVX512DQ-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm2 # 32-byte Reload -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,ymm2[23],zero,ymm2[23,24,25,26],zero,ymm2[24],zero,ymm2[30,31] -; AVX512DQ-FCP-NEXT: vpshufb %ymm14, %ymm2, %ymm14 -; AVX512DQ-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm3 # 32-byte Reload -; AVX512DQ-FCP-NEXT: vpshuflw {{.*#+}} ymm4 = ymm3[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] -; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} ymm2 = [4,5,4,5,5,7,4,5] -; AVX512DQ-FCP-NEXT: vpermd %ymm4, %ymm2, %ymm20 -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] -; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] -; AVX512DQ-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm22 # 64-byte Folded Reload -; AVX512DQ-FCP-NEXT: # zmm22 = mem[2,3,2,3,6,7,6,7] -; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm22 -; AVX512DQ-FCP-NEXT: vpermq $68, {{[-0-9]+}}(%r{{[sb]}}p), %ymm0 # 32-byte Folded Reload -; AVX512DQ-FCP-NEXT: # ymm0 = mem[0,1,0,1] -; AVX512DQ-FCP-NEXT: vpermq $68, {{[-0-9]+}}(%r{{[sb]}}p), %ymm23 # 32-byte Folded Reload -; AVX512DQ-FCP-NEXT: # ymm23 = mem[0,1,0,1] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm2 = ymm2[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[0,0,1,0] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm12 = ymm12[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,3,2,3] +; AVX512DQ-FCP-NEXT: vinserti32x4 $2, %xmm1, %zmm3, %zmm13 +; AVX512DQ-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm15 # 16-byte Reload +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm30, %xmm5 +; AVX512DQ-FCP-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm5[8],xmm15[8],xmm5[9],xmm15[9],xmm5[10],xmm15[10],xmm5[11],xmm15[11],xmm5[12],xmm15[12],xmm5[13],xmm15[13],xmm5[14],xmm15[14],xmm5[15],xmm15[15] +; AVX512DQ-FCP-NEXT: vpshufb %xmm9, %xmm1, %xmm1 +; AVX512DQ-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload +; AVX512DQ-FCP-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm3[0,1,0,1],zmm1[0,1,0,1] +; AVX512DQ-FCP-NEXT: vmovdqu64 %zmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 64-byte Spill +; AVX512DQ-FCP-NEXT: vmovdqa 32(%rax), %xmm3 +; AVX512DQ-FCP-NEXT: vpshufhw {{.*#+}} xmm1 = xmm3[0,1,2,3,4,5,5,6] +; AVX512DQ-FCP-NEXT: vpermd %ymm1, %ymm6, %ymm26 +; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3],xmm0[4],xmm2[4],xmm0[5],xmm2[5],xmm0[6],xmm2[6],xmm0[7],xmm2[7] +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm1 = [0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] +; AVX512DQ-FCP-NEXT: vpshufb %xmm1, %xmm0, %xmm0 +; AVX512DQ-FCP-NEXT: vinserti32x4 $2, {{[-0-9]+}}(%r{{[sb]}}p), %zmm0, %zmm24 # 16-byte Folded Reload +; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm9 = xmm10[0],xmm7[0],xmm10[1],xmm7[1],xmm10[2],xmm7[2],xmm10[3],xmm7[3],xmm10[4],xmm7[4],xmm10[5],xmm7[5],xmm10[6],xmm7[6],xmm10[7],xmm7[7] +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm0 = [4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] +; AVX512DQ-FCP-NEXT: vpshufb %xmm0, %xmm9, %xmm9 +; AVX512DQ-FCP-NEXT: vinserti32x4 $2, {{[-0-9]+}}(%r{{[sb]}}p), %zmm9, %zmm9 # 16-byte Folded Reload +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm17, %xmm2 +; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm8 = xmm8[0],xmm2[0],xmm8[1],xmm2[1],xmm8[2],xmm2[2],xmm8[3],xmm2[3],xmm8[4],xmm2[4],xmm8[5],xmm2[5],xmm8[6],xmm2[6],xmm8[7],xmm2[7] +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm6 = [u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] +; AVX512DQ-FCP-NEXT: vpshufb %xmm6, %xmm8, %xmm8 +; AVX512DQ-FCP-NEXT: vshufi64x2 {{.*#+}} zmm8 = zmm8[0,1,0,1],zmm31[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm14 = xmm4[0],xmm14[0],xmm4[1],xmm14[1],xmm4[2],xmm14[2],xmm4[3],xmm14[3],xmm4[4],xmm14[4],xmm4[5],xmm14[5],xmm4[6],xmm14[6],xmm4[7],xmm14[7] +; AVX512DQ-FCP-NEXT: vpshufb %xmm1, %xmm14, %xmm1 +; AVX512DQ-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm14 # 64-byte Folded Reload +; AVX512DQ-FCP-NEXT: # zmm14 = mem[2,3,2,3,6,7,6,7] +; AVX512DQ-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm31 # 64-byte Folded Reload +; AVX512DQ-FCP-NEXT: # zmm31 = mem[2,3,2,3,6,7,6,7] +; AVX512DQ-FCP-NEXT: vporq %zmm14, %zmm31, %zmm14 +; AVX512DQ-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm31 # 64-byte Folded Reload +; AVX512DQ-FCP-NEXT: # zmm31 = mem[2,3,2,3,6,7,6,7] +; AVX512DQ-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm30 # 64-byte Folded Reload +; AVX512DQ-FCP-NEXT: # zmm30 = mem[2,3,2,3,6,7,6,7] +; AVX512DQ-FCP-NEXT: vporq %zmm31, %zmm30, %zmm30 +; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm14, %zmm30 +; AVX512DQ-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm14 # 64-byte Folded Reload +; AVX512DQ-FCP-NEXT: # zmm14 = mem[2,3,2,3,6,7,6,7] +; AVX512DQ-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm31 # 64-byte Folded Reload +; AVX512DQ-FCP-NEXT: # zmm31 = mem[2,3,2,3,6,7,6,7] +; AVX512DQ-FCP-NEXT: vporq %zmm14, %zmm31, %zmm14 +; AVX512DQ-FCP-NEXT: vmovdqa64 {{.*#+}} zmm31 = [255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255] +; AVX512DQ-FCP-NEXT: vpternlogq $184, %zmm30, %zmm31, %zmm14 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm7 = zmm18[0,1,0,1,4,5,4,5] +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm13 = zmm13[0,1,0,1,4,5,4,5] +; AVX512DQ-FCP-NEXT: vpternlogq $226, %zmm7, %zmm31, %zmm13 +; AVX512DQ-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm7 # 64-byte Folded Reload +; AVX512DQ-FCP-NEXT: # zmm7 = mem[2,3,2,3,6,7,6,7] +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm29 = zmm29[2,3,2,3,6,7,6,7] +; AVX512DQ-FCP-NEXT: vporq %zmm7, %zmm29, %zmm7 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm28 = zmm28[2,3,2,3,6,7,6,7] +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm27 = zmm27[2,3,2,3,6,7,6,7] +; AVX512DQ-FCP-NEXT: vporq %zmm28, %zmm27, %zmm27 +; AVX512DQ-FCP-NEXT: vpternlogq $226, %zmm7, %zmm31, %zmm27 +; AVX512DQ-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Reload +; AVX512DQ-FCP-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm2[2,3,2,3],zmm1[0,1,0,1] +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm16, %xmm2 +; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm7 = xmm2[0],xmm11[0],xmm2[1],xmm11[1],xmm2[2],xmm11[2],xmm2[3],xmm11[3],xmm2[4],xmm11[4],xmm2[5],xmm11[5],xmm2[6],xmm11[6],xmm2[7],xmm11[7] +; AVX512DQ-FCP-NEXT: vpshufb %xmm0, %xmm7, %xmm7 +; AVX512DQ-FCP-NEXT: vshufi64x2 {{.*#+}} zmm7 = zmm23[2,3,2,3],zmm7[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpunpcklbw {{.*#+}} xmm10 = xmm5[0],xmm15[0],xmm5[1],xmm15[1],xmm5[2],xmm15[2],xmm5[3],xmm15[3],xmm5[4],xmm15[4],xmm5[5],xmm15[5],xmm5[6],xmm15[6],xmm5[7],xmm15[7] +; AVX512DQ-FCP-NEXT: vpshufb %xmm6, %xmm10, %xmm10 +; AVX512DQ-FCP-NEXT: vshufi64x2 {{.*#+}} zmm22 = zmm22[2,3,2,3],zmm10[0,1,0,1] +; AVX512DQ-FCP-NEXT: vmovdqa64 %xmm19, %xmm2 +; AVX512DQ-FCP-NEXT: vpshuflw {{.*#+}} xmm11 = xmm2[1,1,0,0,4,5,6,7] +; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} ymm17 = [0,1,0,1,2,0,0,1] +; AVX512DQ-FCP-NEXT: vpermd %ymm11, %ymm17, %ymm28 +; AVX512DQ-FCP-NEXT: vmovdqa {{.*#+}} xmm0 = [4,5,4,5,4,5,8,9,6,7,6,7,6,7,6,7] +; AVX512DQ-FCP-NEXT: vpshufb %xmm0, %xmm2, %xmm6 +; AVX512DQ-FCP-NEXT: vpshufb %xmm0, %xmm3, %xmm0 +; AVX512DQ-FCP-NEXT: vpshuflw {{.*#+}} xmm4 = xmm3[1,1,0,0,4,5,6,7] +; AVX512DQ-FCP-NEXT: vpermd %ymm4, %ymm17, %ymm17 +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm10 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,22,23,26,27,24,25,22,23,24,25,26,27,26,27,24,25] +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm12[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,26,27,28,29,30,31,30,31,28,29,28,29,30,31] +; AVX512DQ-FCP-NEXT: vpshuflw {{.*#+}} ymm2 = ymm12[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] +; AVX512DQ-FCP-NEXT: vpmovsxbd {{.*#+}} ymm23 = [4,5,4,5,5,7,4,5] +; AVX512DQ-FCP-NEXT: vpermd %ymm2, %ymm23, %ymm2 +; AVX512DQ-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm15 # 32-byte Reload +; AVX512DQ-FCP-NEXT: vpshufb {{.*#+}} ymm11 = zero,ymm15[13],zero,zero,zero,zero,zero,zero,ymm15[14],zero,zero,zero,zero,zero,zero,ymm15[15],zero,zero,zero,zero,zero,zero,ymm15[16],zero,zero,zero,zero,zero,zero,ymm15[17],zero,zero +; AVX512DQ-FCP-NEXT: vpshuflw {{.*#+}} ymm15 = ymm15[2,1,1,2,4,5,6,7,10,9,9,10,12,13,14,15] +; AVX512DQ-FCP-NEXT: vpermd %ymm15, %ymm23, %ymm15 +; AVX512DQ-FCP-NEXT: vpand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm15, %ymm15 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm15, %zmm11, %zmm11 +; AVX512DQ-FCP-NEXT: vmovdqa64 {{.*#+}} zmm15 = [255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255,255,255,255,0,0,255,255] +; AVX512DQ-FCP-NEXT: vpternlogq $226, %zmm1, %zmm15, %zmm7 +; AVX512DQ-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %ymm1 # 32-byte Folded Reload +; AVX512DQ-FCP-NEXT: # ymm1 = mem[2,3,2,3] +; AVX512DQ-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm3, %zmm1 +; AVX512DQ-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %ymm18 # 32-byte Folded Reload +; AVX512DQ-FCP-NEXT: # ymm18 = mem[2,3,2,3] +; AVX512DQ-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm18, %zmm3, %zmm18 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm21[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm19 = ymm25[0,1,0,1] +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,0,1,0] ; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[0,0,1,0] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm13 = ymm13[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm14 = ymm14[2,3,2,3] +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] ; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,2,3] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm0, %zmm0 # 32-byte Folded Reload -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm23, %zmm23 # 32-byte Folded Reload -; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm23 -; AVX512DQ-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm0 # 64-byte Reload -; AVX512DQ-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm24 -; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm23, %zmm24 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm19, %zmm2, %zmm0 -; AVX512DQ-FCP-NEXT: vpternlogd $228, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm0, %zmm21 -; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm7, %zmm21 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm10, %zmm0 # 32-byte Folded Reload -; AVX512DQ-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Reload -; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm0 -; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm8, %zmm0 -; AVX512DQ-FCP-NEXT: vpor %ymm12, %ymm15, %ymm2 -; AVX512DQ-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm7 # 64-byte Reload -; AVX512DQ-FCP-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm7[0,1,2,3],zmm2[0,1,2,3] -; AVX512DQ-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm16 -; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm16 -; AVX512DQ-FCP-NEXT: vpermq $68, {{[-0-9]+}}(%r{{[sb]}}p), %zmm2 # 64-byte Folded Reload -; AVX512DQ-FCP-NEXT: # zmm2 = mem[0,1,0,1,4,5,4,5] -; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm5 = zmm31[0,1,0,1,4,5,4,5] -; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm2, %zmm5 -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm6, %zmm17, %zmm2 -; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm18, %zmm2 -; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm2 -; AVX512DQ-FCP-NEXT: vpor %ymm1, %ymm13, %ymm1 -; AVX512DQ-FCP-NEXT: vpor %ymm11, %ymm14, %ymm5 -; AVX512DQ-FCP-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm5[0,1,2,3],zmm1[0,1,2,3] -; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm20, %zmm4 -; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm1, %zmm4 -; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm9, %zmm4 +; AVX512DQ-FCP-NEXT: vpternlogq $226, %zmm1, %zmm15, %zmm18 +; AVX512DQ-FCP-NEXT: vpermq $238, {{[-0-9]+}}(%r{{[sb]}}p), %zmm1 # 64-byte Folded Reload +; AVX512DQ-FCP-NEXT: # zmm1 = mem[2,3,2,3,6,7,6,7] +; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm14, %zmm1 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm5, %zmm5 # 32-byte Folded Reload +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm19, %zmm14 # 32-byte Folded Reload +; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm14 +; AVX512DQ-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload +; AVX512DQ-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm3, %zmm20 +; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm14, %zmm20 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm26, %zmm0, %zmm0 +; AVX512DQ-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload +; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm3, %zmm0 +; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm13, %zmm0 +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm5 = zmm24[0,1,0,1,4,5,4,5] +; AVX512DQ-FCP-NEXT: vpermq {{.*#+}} zmm9 = zmm9[0,1,0,1,4,5,4,5] +; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm5, %zmm9 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm6, %zmm28, %zmm5 +; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm8, %zmm5 +; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm9, %zmm5 +; AVX512DQ-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload +; AVX512DQ-FCP-NEXT: vshufi64x2 $85, {{[-0-9]+}}(%r{{[sb]}}p), %zmm3, %zmm6 # 64-byte Folded Reload +; AVX512DQ-FCP-NEXT: # zmm6 = zmm3[2,3,2,3],mem[2,3,2,3] +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm10, %zmm2, %zmm2 +; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm6, %zmm2 +; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm27, %zmm2 +; AVX512DQ-FCP-NEXT: vinserti64x4 $1, %ymm17, %zmm4, %zmm4 +; AVX512DQ-FCP-NEXT: vpternlogd $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm22, %zmm4 +; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm7, %zmm4 +; AVX512DQ-FCP-NEXT: vmovdqu64 {{[-0-9]+}}(%r{{[sb]}}p), %zmm3 # 64-byte Reload +; AVX512DQ-FCP-NEXT: vshufi64x2 $84, {{[-0-9]+}}(%r{{[sb]}}p), %zmm3, %zmm6 # 64-byte Folded Reload +; AVX512DQ-FCP-NEXT: # zmm6 = zmm3[0,1,2,3],mem[2,3,2,3] +; AVX512DQ-FCP-NEXT: vpternlogq $248, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm6, %zmm11 +; AVX512DQ-FCP-NEXT: vpternlogq $216, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %zmm18, %zmm11 ; AVX512DQ-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax -; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm4, 128(%rax) -; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm2, (%rax) -; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm16, 320(%rax) +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm11, 320(%rax) +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm4, 192(%rax) +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm2, 128(%rax) +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm5, (%rax) ; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm0, 256(%rax) -; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm21, 192(%rax) -; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm24, 64(%rax) -; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm22, 384(%rax) -; AVX512DQ-FCP-NEXT: addq $1256, %rsp # imm = 0x4E8 +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm20, 64(%rax) +; AVX512DQ-FCP-NEXT: vmovdqa64 %zmm1, 384(%rax) +; AVX512DQ-FCP-NEXT: addq $1432, %rsp # imm = 0x598 ; AVX512DQ-FCP-NEXT: vzeroupper ; AVX512DQ-FCP-NEXT: retq ; @@ -10436,8 +10220,8 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW: # %bb.0: ; AVX512BW-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512BW-NEXT: vmovdqa (%rax), %ymm13 -; AVX512BW-NEXT: vmovdqa64 {{.*#+}} ymm27 = [12,13,2,3,12,13,0,1,14,15,2,3,0,1,14,15,28,29,18,19,28,29,16,17,30,31,18,19,16,17,30,31] -; AVX512BW-NEXT: vpshufb %ymm27, %ymm13, %ymm0 +; AVX512BW-NEXT: vmovdqa64 {{.*#+}} ymm26 = [12,13,2,3,12,13,0,1,14,15,2,3,0,1,14,15,28,29,18,19,28,29,16,17,30,31,18,19,16,17,30,31] +; AVX512BW-NEXT: vpshufb %ymm26, %ymm13, %ymm0 ; AVX512BW-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [4,5,4,5,5,6,5,6,4,5,4,5,5,6,5,6] ; AVX512BW-NEXT: # ymm1 = mem[0,1,0,1] ; AVX512BW-NEXT: vpermw %ymm13, %ymm1, %ymm1 @@ -10446,12 +10230,13 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-NEXT: vmovdqa64 {{.*#+}} ymm17 = [13,128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128] ; AVX512BW-NEXT: vpshufb %ymm17, %ymm9, %ymm1 ; AVX512BW-NEXT: vmovdqa (%r8), %ymm10 -; AVX512BW-NEXT: vmovdqa64 {{.*#+}} ymm22 = [128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128] -; AVX512BW-NEXT: vpshufb %ymm22, %ymm10, %ymm2 +; AVX512BW-NEXT: vmovdqa64 {{.*#+}} ymm21 = [128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128] +; AVX512BW-NEXT: vpshufb %ymm21, %ymm10, %ymm2 ; AVX512BW-NEXT: vpor %ymm1, %ymm2, %ymm2 -; AVX512BW-NEXT: vmovdqa (%r9), %xmm12 -; AVX512BW-NEXT: vmovdqa (%r8), %xmm3 -; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm3[8],xmm12[8],xmm3[9],xmm12[9],xmm3[10],xmm12[10],xmm3[11],xmm12[11],xmm3[12],xmm12[12],xmm3[13],xmm12[13],xmm3[14],xmm12[14],xmm3[15],xmm12[15] +; AVX512BW-NEXT: vmovdqa (%r9), %xmm1 +; AVX512BW-NEXT: vmovdqa %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512BW-NEXT: vmovdqa (%r8), %xmm12 +; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm12[8],xmm1[8],xmm12[9],xmm1[9],xmm12[10],xmm1[10],xmm12[11],xmm1[11],xmm12[12],xmm1[12],xmm12[13],xmm1[13],xmm12[14],xmm1[14],xmm12[15],xmm1[15] ; AVX512BW-NEXT: vpshufb {{.*#+}} xmm4 = xmm4[u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] ; AVX512BW-NEXT: vpermq {{.*#+}} ymm4 = ymm4[0,1,0,1] ; AVX512BW-NEXT: vinserti64x4 $1, %ymm2, %zmm4, %zmm8 @@ -10461,270 +10246,257 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-NEXT: vmovdqa (%rdx), %ymm14 ; AVX512BW-NEXT: vmovdqa {{.*#+}} ymm0 = [0,1,0,1,14,128,14,15,0,1,14,15,128,13,14,15,16,17,16,128,30,31,30,31,16,17,128,31,28,29,30,31] ; AVX512BW-NEXT: vpshufb %ymm0, %ymm14, %ymm2 -; AVX512BW-NEXT: vmovdqa64 (%rcx), %ymm16 -; AVX512BW-NEXT: vmovdqa64 {{.*#+}} ymm23 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] -; AVX512BW-NEXT: vpshufb %ymm23, %ymm16, %ymm4 +; AVX512BW-NEXT: vmovdqa (%rcx), %ymm15 +; AVX512BW-NEXT: vmovdqa64 {{.*#+}} ymm20 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] +; AVX512BW-NEXT: vpshufb %ymm20, %ymm15, %ymm4 ; AVX512BW-NEXT: vpor %ymm2, %ymm4, %ymm2 ; AVX512BW-NEXT: vmovdqa (%rdx), %xmm4 ; AVX512BW-NEXT: vmovdqa (%rcx), %xmm5 ; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm5[8],xmm4[8],xmm5[9],xmm4[9],xmm5[10],xmm4[10],xmm5[11],xmm4[11],xmm5[12],xmm4[12],xmm5[13],xmm4[13],xmm5[14],xmm4[14],xmm5[15],xmm4[15] ; AVX512BW-NEXT: vpshufb {{.*#+}} xmm6 = xmm6[6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] ; AVX512BW-NEXT: vpermq {{.*#+}} ymm6 = ymm6[0,1,0,1] -; AVX512BW-NEXT: vinserti64x4 $1, %ymm2, %zmm6, %zmm20 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm2, %zmm6, %zmm22 ; AVX512BW-NEXT: vmovdqa64 (%rdi), %ymm18 ; AVX512BW-NEXT: vmovdqa64 {{.*#+}} ymm24 = [0,1,14,128,12,13,0,1,14,15,128,3,12,13,2,3,16,128,30,31,28,29,16,17,128,31,18,19,28,29,18,128] ; AVX512BW-NEXT: vpshufb %ymm24, %ymm18, %ymm2 ; AVX512BW-NEXT: vmovdqa64 (%rsi), %ymm19 -; AVX512BW-NEXT: vmovdqa64 {{.*#+}} ymm26 = [128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128,128,18] -; AVX512BW-NEXT: vpshufb %ymm26, %ymm19, %ymm6 +; AVX512BW-NEXT: vmovdqa64 {{.*#+}} ymm25 = [128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128,128,18] +; AVX512BW-NEXT: vpshufb %ymm25, %ymm19, %ymm6 ; AVX512BW-NEXT: vpor %ymm2, %ymm6, %ymm2 ; AVX512BW-NEXT: vmovdqa (%rdi), %xmm6 ; AVX512BW-NEXT: vmovdqa (%rsi), %xmm7 -; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm21 = xmm7[8],xmm6[8],xmm7[9],xmm6[9],xmm7[10],xmm6[10],xmm7[11],xmm6[11],xmm7[12],xmm6[12],xmm7[13],xmm6[13],xmm7[14],xmm6[14],xmm7[15],xmm6[15] -; AVX512BW-NEXT: vpshufb {{.*#+}} xmm21 = xmm21[2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] -; AVX512BW-NEXT: vpermq {{.*#+}} ymm21 = ymm21[0,1,0,1] -; AVX512BW-NEXT: vinserti64x4 $1, %ymm2, %zmm21, %zmm2 +; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm23 = xmm7[8],xmm6[8],xmm7[9],xmm6[9],xmm7[10],xmm6[10],xmm7[11],xmm6[11],xmm7[12],xmm6[12],xmm7[13],xmm6[13],xmm7[14],xmm6[14],xmm7[15],xmm6[15] +; AVX512BW-NEXT: vpshufb {{.*#+}} xmm23 = xmm23[2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] +; AVX512BW-NEXT: vpermq {{.*#+}} ymm23 = ymm23[0,1,0,1] +; AVX512BW-NEXT: vinserti64x4 $1, %ymm2, %zmm23, %zmm3 ; AVX512BW-NEXT: movabsq $435749860008887046, %r10 # imm = 0x60C183060C18306 ; AVX512BW-NEXT: kmovq %r10, %k1 -; AVX512BW-NEXT: vmovdqu8 %zmm20, %zmm2 {%k1} +; AVX512BW-NEXT: vmovdqu8 %zmm22, %zmm3 {%k1} ; AVX512BW-NEXT: movabsq $4066998693416279096, %r10 # imm = 0x3870E1C3870E1C38 ; AVX512BW-NEXT: kmovq %r10, %k1 -; AVX512BW-NEXT: vmovdqu8 %zmm8, %zmm2 {%k1} -; AVX512BW-NEXT: vmovdqa64 {{.*#+}} zmm20 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,24,25,128,23,128,21,22,23,26,128,24,128,28,29,26,27] +; AVX512BW-NEXT: vmovdqu8 %zmm8, %zmm3 {%k1} ; AVX512BW-NEXT: vmovdqa64 32(%rdx), %ymm29 +; AVX512BW-NEXT: vpshufb %ymm0, %ymm29, %ymm0 +; AVX512BW-NEXT: vmovdqa64 32(%rcx), %ymm30 +; AVX512BW-NEXT: vpshufb %ymm20, %ymm30, %ymm8 +; AVX512BW-NEXT: vpor %ymm0, %ymm8, %ymm0 +; AVX512BW-NEXT: vmovdqa64 {{.*#+}} zmm20 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,24,25,128,23,128,21,22,23,26,128,24,128,28,29,26,27] ; AVX512BW-NEXT: vpshufb %ymm20, %ymm29, %ymm8 +; AVX512BW-NEXT: vmovdqa64 {{.*#+}} zmm22 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128] +; AVX512BW-NEXT: vpshufb %ymm22, %ymm30, %ymm23 +; AVX512BW-NEXT: vporq %ymm8, %ymm23, %ymm8 ; AVX512BW-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] -; AVX512BW-NEXT: vmovdqa64 {{.*#+}} zmm21 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128] -; AVX512BW-NEXT: vmovdqa64 32(%rcx), %ymm30 -; AVX512BW-NEXT: vpshufb %ymm21, %ymm30, %ymm25 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm25 = ymm25[2,3,2,3] -; AVX512BW-NEXT: vporq %ymm8, %ymm25, %ymm8 -; AVX512BW-NEXT: vpshufb %ymm0, %ymm29, %ymm0 -; AVX512BW-NEXT: vpshufb %ymm23, %ymm30, %ymm23 -; AVX512BW-NEXT: vporq %ymm0, %ymm23, %ymm0 ; AVX512BW-NEXT: vinserti64x4 $1, %ymm8, %zmm0, %zmm0 ; AVX512BW-NEXT: vmovdqa64 32(%rsi), %ymm28 -; AVX512BW-NEXT: vmovdqa 32(%rdi), %ymm15 -; AVX512BW-NEXT: vpshuflw {{.*#+}} ymm8 = ymm15[1,2,2,3,4,5,6,7,9,10,10,11,12,13,14,15] +; AVX512BW-NEXT: vmovdqa64 32(%rdi), %ymm16 +; AVX512BW-NEXT: vpshuflw {{.*#+}} ymm8 = ymm16[1,2,2,3,4,5,6,7,9,10,10,11,12,13,14,15] ; AVX512BW-NEXT: vpshufd {{.*#+}} ymm8 = ymm8[0,0,1,1,4,4,5,5] -; AVX512BW-NEXT: vpbroadcastd {{.*#+}} ymm25 = [5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6] +; AVX512BW-NEXT: vpbroadcastd {{.*#+}} ymm23 = [5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6] ; AVX512BW-NEXT: movl $676341840, %r10d # imm = 0x28502850 ; AVX512BW-NEXT: kmovd %r10d, %k1 -; AVX512BW-NEXT: vpshufb %ymm25, %ymm28, %ymm8 {%k1} +; AVX512BW-NEXT: vpshufb %ymm23, %ymm28, %ymm8 {%k1} ; AVX512BW-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] -; AVX512BW-NEXT: vpshufb %ymm24, %ymm15, %ymm23 -; AVX512BW-NEXT: vpshufb %ymm26, %ymm28, %ymm24 -; AVX512BW-NEXT: vporq %ymm23, %ymm24, %ymm23 -; AVX512BW-NEXT: vinserti64x4 $1, %ymm8, %zmm23, %zmm8 +; AVX512BW-NEXT: vpshufb %ymm24, %ymm16, %ymm24 +; AVX512BW-NEXT: vpshufb %ymm25, %ymm28, %ymm25 +; AVX512BW-NEXT: vporq %ymm24, %ymm25, %ymm24 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm8, %zmm24, %zmm8 ; AVX512BW-NEXT: movabsq $3485998880071096368, %r10 # imm = 0x3060C183060C1830 ; AVX512BW-NEXT: kmovq %r10, %k2 ; AVX512BW-NEXT: vmovdqu8 %zmm0, %zmm8 {%k2} -; AVX512BW-NEXT: vmovdqa64 {{.*#+}} zmm23 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,24,25,24,25,128,23,128,23,24,25,26,128,24,128,30,31] -; AVX512BW-NEXT: vmovdqa64 32(%r8), %ymm31 -; AVX512BW-NEXT: vpshufb %ymm23, %ymm31, %ymm0 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm26 = ymm0[2,3,2,3] -; AVX512BW-NEXT: vmovdqa64 {{.*#+}} zmm24 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,128,128,25,128,23,128,128,128,128,26,128,24,128,128] -; AVX512BW-NEXT: vmovdqa 32(%r9), %ymm0 -; AVX512BW-NEXT: vpshufb %ymm24, %ymm0, %ymm11 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] -; AVX512BW-NEXT: vporq %ymm26, %ymm11, %ymm11 -; AVX512BW-NEXT: vpshufb %ymm17, %ymm0, %ymm17 -; AVX512BW-NEXT: vpshufb %ymm22, %ymm31, %ymm22 -; AVX512BW-NEXT: vporq %ymm17, %ymm22, %ymm17 -; AVX512BW-NEXT: vinserti64x4 $1, %ymm11, %zmm17, %zmm11 +; AVX512BW-NEXT: vmovdqa64 32(%r9), %ymm31 +; AVX512BW-NEXT: vpshufb %ymm17, %ymm31, %ymm17 +; AVX512BW-NEXT: vmovdqa 32(%r8), %ymm1 +; AVX512BW-NEXT: vpshufb %ymm21, %ymm1, %ymm21 +; AVX512BW-NEXT: vporq %ymm17, %ymm21, %ymm17 +; AVX512BW-NEXT: vmovdqa64 {{.*#+}} zmm24 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,24,25,24,25,128,23,128,23,24,25,26,128,24,128,30,31] +; AVX512BW-NEXT: vpshufb %ymm24, %ymm1, %ymm21 +; AVX512BW-NEXT: vmovdqa64 {{.*#+}} zmm25 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,128,128,25,128,23,128,128,128,128,26,128,24,128,128] +; AVX512BW-NEXT: vpshufb %ymm25, %ymm31, %ymm27 +; AVX512BW-NEXT: vporq %ymm21, %ymm27, %ymm21 +; AVX512BW-NEXT: vpermq {{.*#+}} ymm21 = ymm21[2,3,2,3] +; AVX512BW-NEXT: vinserti64x4 $1, %ymm21, %zmm17, %zmm21 ; AVX512BW-NEXT: vmovdqa64 32(%rax), %ymm17 -; AVX512BW-NEXT: vpshufb %ymm27, %ymm17, %ymm22 +; AVX512BW-NEXT: vpshufb %ymm26, %ymm17, %ymm27 ; AVX512BW-NEXT: vpmovsxbw {{.*#+}} zmm26 = [10,9,9,10,10,9,9,10,9,10,14,15,10,9,9,10,27,29,28,27,28,29,29,28,27,29,28,27,28,29,29,28] -; AVX512BW-NEXT: vpermw %ymm17, %ymm26, %ymm27 -; AVX512BW-NEXT: vinserti64x4 $1, %ymm27, %zmm22, %zmm22 +; AVX512BW-NEXT: vpermw %ymm17, %ymm26, %ymm11 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm11, %zmm27, %zmm11 ; AVX512BW-NEXT: movabsq $145249953336295682, %r10 # imm = 0x204081020408102 ; AVX512BW-NEXT: kmovq %r10, %k3 -; AVX512BW-NEXT: vmovdqu8 %zmm22, %zmm11 {%k3} +; AVX512BW-NEXT: vmovdqu8 %zmm11, %zmm21 {%k3} ; AVX512BW-NEXT: movabsq $-4357498600088870461, %r10 # imm = 0xC3870E1C3870E1C3 ; AVX512BW-NEXT: kmovq %r10, %k3 -; AVX512BW-NEXT: vmovdqu8 %zmm11, %zmm8 {%k3} -; AVX512BW-NEXT: vpshufhw {{.*#+}} ymm11 = ymm15[0,1,2,3,6,7,7,6,8,9,10,11,14,15,15,14] +; AVX512BW-NEXT: vmovdqu8 %zmm21, %zmm8 {%k3} +; AVX512BW-NEXT: vpshufhw {{.*#+}} ymm11 = ymm16[0,1,2,3,6,7,7,6,8,9,10,11,14,15,15,14] ; AVX512BW-NEXT: vpshufd {{.*#+}} ymm11 = ymm11[2,2,3,3,6,6,7,7] ; AVX512BW-NEXT: movl $338170920, %r10d # imm = 0x14281428 ; AVX512BW-NEXT: kmovd %r10d, %k4 ; AVX512BW-NEXT: vpbroadcastd {{.*#+}} ymm27 = [13,12,15,14,13,12,15,14,13,12,15,14,13,12,15,14,13,12,15,14,13,12,15,14,13,12,15,14,13,12,15,14] ; AVX512BW-NEXT: vpshufb %ymm27, %ymm28, %ymm11 {%k4} -; AVX512BW-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [25,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128] -; AVX512BW-NEXT: # ymm1 = mem[0,1,0,1] -; AVX512BW-NEXT: vpshufb %ymm1, %ymm28, %ymm22 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm22 = ymm22[2,3,2,3] +; AVX512BW-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [25,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128] +; AVX512BW-NEXT: # ymm2 = mem[0,1,0,1] +; AVX512BW-NEXT: vpshufb %ymm2, %ymm28, %ymm21 ; AVX512BW-NEXT: vmovdqa64 {{.*#+}} ymm28 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128,25] -; AVX512BW-NEXT: vpshufb %ymm28, %ymm15, %ymm15 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,3,2,3] -; AVX512BW-NEXT: vporq %ymm22, %ymm15, %ymm15 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] -; AVX512BW-NEXT: vinserti64x4 $1, %ymm11, %zmm15, %zmm15 -; AVX512BW-NEXT: vpshufb {{.*#+}} ymm11 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm29[24,25],zero,ymm29[23],zero,ymm29[21,22,23,26],zero,ymm29[24],zero,ymm29[28,29,26,27] -; AVX512BW-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] -; AVX512BW-NEXT: vpshufb {{.*#+}} ymm22 = ymm30[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm30[25],zero,ymm30[23],zero,zero,zero,zero,ymm30[26],zero,ymm30[24],zero,zero,zero,zero -; AVX512BW-NEXT: vpermq {{.*#+}} ymm22 = ymm22[2,3,2,3] -; AVX512BW-NEXT: vporq %ymm11, %ymm22, %ymm22 +; AVX512BW-NEXT: vpshufb %ymm28, %ymm16, %ymm16 +; AVX512BW-NEXT: vporq %ymm21, %ymm16, %ymm16 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm11, %zmm16, %zmm16 +; AVX512BW-NEXT: vpshufhw {{.*#+}} ymm11 = ymm29[0,1,2,3,7,6,6,7,8,9,10,11,15,14,14,15] +; AVX512BW-NEXT: vpshufd {{.*#+}} ymm21 = ymm11[0,2,3,3,4,6,7,7] ; AVX512BW-NEXT: vpbroadcastq {{.*#+}} ymm11 = [11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12] -; AVX512BW-NEXT: vpshufb %ymm11, %ymm30, %ymm30 -; AVX512BW-NEXT: vpshufhw {{.*#+}} ymm29 = ymm29[0,1,2,3,7,6,6,7,8,9,10,11,15,14,14,15] -; AVX512BW-NEXT: vpshufd {{.*#+}} ymm29 = ymm29[0,2,3,3,4,6,7,7] -; AVX512BW-NEXT: vmovdqu8 %ymm29, %ymm30 {%k1} -; AVX512BW-NEXT: vpermq {{.*#+}} ymm29 = ymm30[2,3,2,3] -; AVX512BW-NEXT: vinserti64x4 $1, %ymm29, %zmm22, %zmm22 +; AVX512BW-NEXT: vpshufb %ymm11, %ymm30, %ymm0 +; AVX512BW-NEXT: vmovdqu8 %ymm21, %ymm0 {%k1} +; AVX512BW-NEXT: vpshufb {{.*#+}} ymm21 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm29[24,25],zero,ymm29[23],zero,ymm29[21,22,23,26],zero,ymm29[24],zero,ymm29[28,29,26,27] +; AVX512BW-NEXT: vpshufb {{.*#+}} ymm29 = ymm30[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm30[25],zero,ymm30[23],zero,zero,zero,zero,ymm30[26],zero,ymm30[24],zero,zero,zero,zero +; AVX512BW-NEXT: vporq %ymm21, %ymm29, %ymm21 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm0, %zmm21, %zmm0 +; AVX512BW-NEXT: vpermq {{.*#+}} zmm16 = zmm16[2,3,2,3,6,7,6,7] +; AVX512BW-NEXT: vpermq {{.*#+}} zmm0 = zmm0[2,3,2,3,6,7,6,7] ; AVX512BW-NEXT: movabsq $1742999440035548184, %r10 # imm = 0x183060C183060C18 ; AVX512BW-NEXT: kmovq %r10, %k3 -; AVX512BW-NEXT: vmovdqu8 %zmm22, %zmm15 {%k3} -; AVX512BW-NEXT: vmovdqa64 (%r9), %zmm29 -; AVX512BW-NEXT: vshufi64x2 {{.*#+}} zmm22 = zmm31[0,1,2,3],zmm29[4,5,6,7] -; AVX512BW-NEXT: vpshufb {{.*#+}} zmm22 = zmm22[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,zmm22[23],zero,zmm22[23,24,25,26],zero,zmm22[24],zero,zmm22[30,31,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,61],zero,zmm22[59],zero,zero,zero,zero,zmm22[62],zero,zmm22[60],zero,zero,zero,zero,zmm22[63],zero -; AVX512BW-NEXT: vpermq {{.*#+}} zmm22 = zmm22[2,3,2,3,6,7,6,7] -; AVX512BW-NEXT: vmovdqa64 (%r8), %zmm30 -; AVX512BW-NEXT: vshufi64x2 {{.*#+}} zmm0 = zmm0[0,1,2,3],zmm30[4,5,6,7] -; AVX512BW-NEXT: vpshufb {{.*#+}} zmm0 = zmm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm0[25],zero,zmm0[23],zero,zero,zero,zero,zmm0[26],zero,zmm0[24],zero,zero,zmm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm0[59],zero,zero,zero,zero,zmm0[62],zero,zmm0[60],zero,zero,zero,zero,zmm0[63],zero,zmm0[61] -; AVX512BW-NEXT: vpermq {{.*#+}} zmm0 = zmm0[2,3,2,3,6,7,6,7] -; AVX512BW-NEXT: vporq %zmm22, %zmm0, %zmm0 +; AVX512BW-NEXT: vmovdqu8 %zmm0, %zmm16 {%k3} +; AVX512BW-NEXT: vmovdqa64 (%r9), %zmm0 +; AVX512BW-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm1[0,1,2,3],zmm0[4,5,6,7] +; AVX512BW-NEXT: vpshufb {{.*#+}} zmm1 = zmm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,zmm1[23],zero,zmm1[23,24,25,26],zero,zmm1[24],zero,zmm1[30,31,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,61],zero,zmm1[59],zero,zero,zero,zero,zmm1[62],zero,zmm1[60],zero,zero,zero,zero,zmm1[63],zero +; AVX512BW-NEXT: vmovdqa64 (%r8), %zmm29 +; AVX512BW-NEXT: vshufi64x2 {{.*#+}} zmm21 = zmm31[0,1,2,3],zmm29[4,5,6,7] +; AVX512BW-NEXT: vpshufb {{.*#+}} zmm21 = zmm21[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm21[25],zero,zmm21[23],zero,zero,zero,zero,zmm21[26],zero,zmm21[24],zero,zero,zmm21[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm21[59],zero,zero,zero,zero,zmm21[62],zero,zmm21[60],zero,zero,zero,zero,zmm21[63],zero,zmm21[61] +; AVX512BW-NEXT: vporq %zmm1, %zmm21, %zmm1 +; AVX512BW-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] ; AVX512BW-NEXT: movabsq $6971997760142192736, %r10 # imm = 0x60C183060C183060 ; AVX512BW-NEXT: kmovq %r10, %k3 -; AVX512BW-NEXT: vmovdqu8 %zmm0, %zmm15 {%k3} -; AVX512BW-NEXT: vmovdqa64 (%rax), %zmm22 -; AVX512BW-NEXT: vpmovsxbw {{.*#+}} zmm0 = [11,13,12,11,12,13,13,12,11,13,12,11,12,13,13,12,62,61,62,63,63,62,62,63,62,61,62,63,63,62,62,63] -; AVX512BW-NEXT: vpermi2w %zmm22, %zmm17, %zmm0 +; AVX512BW-NEXT: vmovdqu8 %zmm1, %zmm16 {%k3} +; AVX512BW-NEXT: vmovdqa64 (%rax), %zmm21 +; AVX512BW-NEXT: vpmovsxbw {{.*#+}} zmm1 = [11,13,12,11,12,13,13,12,11,13,12,11,12,13,13,12,62,61,62,63,63,62,62,63,62,61,62,63,63,62,62,63] +; AVX512BW-NEXT: vpermi2w %zmm21, %zmm17, %zmm1 ; AVX512BW-NEXT: movabsq $-9150747060186627967, %rax # imm = 0x8102040810204081 ; AVX512BW-NEXT: kmovq %rax, %k5 -; AVX512BW-NEXT: vmovdqu8 %zmm0, %zmm15 {%k5} -; AVX512BW-NEXT: vpshuflw {{.*#+}} ymm0 = ymm18[1,2,2,3,4,5,6,7,9,10,10,11,12,13,14,15] -; AVX512BW-NEXT: vpshufd {{.*#+}} ymm0 = ymm0[0,0,1,1,4,4,5,5] -; AVX512BW-NEXT: vpshufb %ymm25, %ymm19, %ymm0 {%k1} -; AVX512BW-NEXT: vpshufb %ymm1, %ymm19, %ymm1 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512BW-NEXT: vpshufb %ymm28, %ymm18, %ymm25 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm25 = ymm25[2,3,2,3] -; AVX512BW-NEXT: vporq %ymm1, %ymm25, %ymm1 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX512BW-NEXT: vinserti64x4 $1, %ymm1, %zmm0, %zmm0 -; AVX512BW-NEXT: vmovdqa64 (%rdx), %zmm1 -; AVX512BW-NEXT: vinserti64x4 $1, %ymm14, %zmm1, %zmm1 -; AVX512BW-NEXT: vpshufb %zmm20, %zmm1, %zmm1 +; AVX512BW-NEXT: vmovdqu8 %zmm1, %zmm16 {%k5} +; AVX512BW-NEXT: vpshuflw {{.*#+}} ymm1 = ymm18[1,2,2,3,4,5,6,7,9,10,10,11,12,13,14,15] +; AVX512BW-NEXT: vpshufd {{.*#+}} ymm1 = ymm1[0,0,1,1,4,4,5,5] +; AVX512BW-NEXT: vpshufb %ymm23, %ymm19, %ymm1 {%k1} +; AVX512BW-NEXT: vpshufb %ymm2, %ymm19, %ymm2 +; AVX512BW-NEXT: vpshufb %ymm28, %ymm18, %ymm23 +; AVX512BW-NEXT: vporq %ymm2, %ymm23, %ymm2 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm2, %zmm1, %zmm1 +; AVX512BW-NEXT: vmovdqa64 (%rdx), %zmm2 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm14, %zmm2, %zmm2 +; AVX512BW-NEXT: vpshufb %zmm20, %zmm2, %zmm2 ; AVX512BW-NEXT: vmovdqa64 (%rcx), %zmm20 -; AVX512BW-NEXT: vinserti64x4 $1, %ymm16, %zmm20, %zmm20 -; AVX512BW-NEXT: vpshufb %zmm21, %zmm20, %zmm20 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm15, %zmm20, %zmm20 +; AVX512BW-NEXT: vpshufb %zmm22, %zmm20, %zmm20 +; AVX512BW-NEXT: vporq %zmm2, %zmm20, %zmm2 ; AVX512BW-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] -; AVX512BW-NEXT: vpermq {{.*#+}} zmm20 = zmm20[2,3,2,3,6,7,6,7] -; AVX512BW-NEXT: vporq %zmm1, %zmm20, %zmm20 -; AVX512BW-NEXT: vmovdqu8 %zmm0, %zmm20 {%k3} -; AVX512BW-NEXT: vmovdqa64 32(%r9), %xmm21 -; AVX512BW-NEXT: vinserti64x4 $1, %ymm10, %zmm30, %zmm0 -; AVX512BW-NEXT: vpshufb %zmm23, %zmm0, %zmm0 -; AVX512BW-NEXT: vmovdqa64 32(%r8), %xmm23 -; AVX512BW-NEXT: vinserti64x4 $1, %ymm9, %zmm29, %zmm1 +; AVX512BW-NEXT: vpermq {{.*#+}} zmm20 = zmm2[2,3,2,3,6,7,6,7] +; AVX512BW-NEXT: vmovdqu8 %zmm1, %zmm20 {%k3} +; AVX512BW-NEXT: vmovdqa64 32(%r9), %xmm22 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm10, %zmm29, %zmm1 ; AVX512BW-NEXT: vpshufb %zmm24, %zmm1, %zmm1 -; AVX512BW-NEXT: vmovdqa64 32(%rdx), %xmm24 -; AVX512BW-NEXT: vpermq {{.*#+}} zmm0 = zmm0[2,3,2,3,6,7,6,7] +; AVX512BW-NEXT: vmovdqa64 32(%r8), %xmm23 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm9, %zmm0, %zmm0 +; AVX512BW-NEXT: vpshufb %zmm25, %zmm0, %zmm2 +; AVX512BW-NEXT: vmovdqa 32(%rdx), %xmm0 +; AVX512BW-NEXT: vporq %zmm1, %zmm2, %zmm1 +; AVX512BW-NEXT: vmovdqa 32(%rcx), %xmm2 ; AVX512BW-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] -; AVX512BW-NEXT: vporq %zmm0, %zmm1, %zmm1 -; AVX512BW-NEXT: vmovdqa64 32(%rcx), %xmm25 -; AVX512BW-NEXT: vinserti64x4 $1, %ymm13, %zmm22, %zmm13 -; AVX512BW-NEXT: vpermw %zmm13, %zmm26, %zmm0 +; AVX512BW-NEXT: vinserti64x4 $1, %ymm13, %zmm21, %zmm13 +; AVX512BW-NEXT: vpermw %zmm13, %zmm26, %zmm24 ; AVX512BW-NEXT: movabsq $1161999626690365456, %rax # imm = 0x1020408102040810 ; AVX512BW-NEXT: kmovq %rax, %k5 -; AVX512BW-NEXT: vmovdqu8 %zmm0, %zmm1 {%k5} -; AVX512BW-NEXT: vmovdqa 32(%rdi), %xmm0 +; AVX512BW-NEXT: vmovdqu8 %zmm24, %zmm1 {%k5} +; AVX512BW-NEXT: vmovdqa64 32(%rdi), %xmm24 ; AVX512BW-NEXT: movabsq $2033499346708139548, %rax # imm = 0x1C3870E1C3870E1C ; AVX512BW-NEXT: kmovq %rax, %k5 ; AVX512BW-NEXT: vmovdqu8 %zmm1, %zmm20 {%k5} ; AVX512BW-NEXT: vmovdqa 32(%rsi), %xmm1 ; AVX512BW-NEXT: vpshufhw {{.*#+}} ymm18 = ymm18[0,1,2,3,6,7,7,6,8,9,10,11,14,15,15,14] -; AVX512BW-NEXT: vpshufd {{.*#+}} ymm26 = ymm18[2,2,3,3,6,6,7,7] -; AVX512BW-NEXT: vpshufb %ymm27, %ymm19, %ymm26 {%k4} -; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm19 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] +; AVX512BW-NEXT: vpshufd {{.*#+}} ymm25 = ymm18[2,2,3,3,6,6,7,7] +; AVX512BW-NEXT: vpshufb %ymm27, %ymm19, %ymm25 {%k4} +; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm19 = xmm24[0],xmm1[0],xmm24[1],xmm1[1],xmm24[2],xmm1[2],xmm24[3],xmm1[3],xmm24[4],xmm1[4],xmm24[5],xmm1[5],xmm24[6],xmm1[6],xmm24[7],xmm1[7] ; AVX512BW-NEXT: vmovdqa64 {{.*#+}} xmm18 = [0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] ; AVX512BW-NEXT: vpshufb %xmm18, %xmm19, %xmm19 -; AVX512BW-NEXT: vshufi64x2 {{.*#+}} zmm19 = zmm26[2,3,2,3],zmm19[0,1,0,1] -; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm26 = xmm24[0],xmm25[0],xmm24[1],xmm25[1],xmm24[2],xmm25[2],xmm24[3],xmm25[3],xmm24[4],xmm25[4],xmm24[5],xmm25[5],xmm24[6],xmm25[6],xmm24[7],xmm25[7] -; AVX512BW-NEXT: vpshufb %ymm11, %ymm16, %ymm11 -; AVX512BW-NEXT: vmovdqa64 {{.*#+}} xmm16 = [4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] -; AVX512BW-NEXT: vpshufb %xmm16, %xmm26, %xmm26 +; AVX512BW-NEXT: vshufi64x2 {{.*#+}} zmm25 = zmm25[2,3,2,3],zmm19[0,1,0,1] +; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm26 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3],xmm0[4],xmm2[4],xmm0[5],xmm2[5],xmm0[6],xmm2[6],xmm0[7],xmm2[7] +; AVX512BW-NEXT: vpshufb %ymm11, %ymm15, %ymm11 +; AVX512BW-NEXT: vmovdqa64 {{.*#+}} xmm19 = [4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] +; AVX512BW-NEXT: vpshufb %xmm19, %xmm26, %xmm15 ; AVX512BW-NEXT: vpshufhw {{.*#+}} ymm14 = ymm14[0,1,2,3,7,6,6,7,8,9,10,11,15,14,14,15] ; AVX512BW-NEXT: vpshufd {{.*#+}} ymm14 = ymm14[0,2,3,3,4,6,7,7] ; AVX512BW-NEXT: vmovdqu8 %ymm14, %ymm11 {%k1} -; AVX512BW-NEXT: vshufi64x2 {{.*#+}} zmm14 = zmm11[2,3,2,3],zmm26[0,1,0,1] -; AVX512BW-NEXT: vmovdqu8 %zmm19, %zmm14 {%k2} +; AVX512BW-NEXT: vshufi64x2 {{.*#+}} zmm14 = zmm11[2,3,2,3],zmm15[0,1,0,1] +; AVX512BW-NEXT: vmovdqu8 %zmm25, %zmm14 {%k2} +; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm11 = xmm23[0],xmm22[0],xmm23[1],xmm22[1],xmm23[2],xmm22[2],xmm23[3],xmm22[3],xmm23[4],xmm22[4],xmm23[5],xmm22[5],xmm23[6],xmm22[6],xmm23[7],xmm22[7] +; AVX512BW-NEXT: vmovdqa {{.*#+}} xmm15 = [u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] +; AVX512BW-NEXT: vpshufb %xmm15, %xmm11, %xmm11 ; AVX512BW-NEXT: vpshufb {{.*#+}} ymm9 = ymm9[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm9[27],zero,zero,zero,zero,ymm9[30],zero,ymm9[28],zero,zero,zero,zero,ymm9[31],zero -; AVX512BW-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,3,2,3] ; AVX512BW-NEXT: vpshufb {{.*#+}} ymm10 = ymm10[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm10[27],zero,zero,zero,zero,ymm10[30],zero,ymm10[28],zero,zero,zero,zero,ymm10[31],zero,ymm10[29] -; AVX512BW-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] -; AVX512BW-NEXT: vpor %ymm9, %ymm10, %ymm10 -; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm11 = xmm23[0],xmm21[0],xmm23[1],xmm21[1],xmm23[2],xmm21[2],xmm23[3],xmm21[3],xmm23[4],xmm21[4],xmm23[5],xmm21[5],xmm23[6],xmm21[6],xmm23[7],xmm21[7] -; AVX512BW-NEXT: vmovdqa {{.*#+}} xmm9 = [u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] -; AVX512BW-NEXT: vpshufb %xmm9, %xmm11, %xmm11 -; AVX512BW-NEXT: vpermq {{.*#+}} ymm11 = ymm11[0,1,0,1] -; AVX512BW-NEXT: vinserti64x4 $1, %ymm11, %zmm10, %zmm10 -; AVX512BW-NEXT: vpmovsxbw {{.*#+}} zmm11 = [14,13,14,15,15,14,14,15,14,13,14,15,15,14,14,15,17,17,16,16,17,17,16,16,20,21,17,17,17,17,16,16] -; AVX512BW-NEXT: vpermw %zmm22, %zmm11, %zmm11 +; AVX512BW-NEXT: vpor %ymm9, %ymm10, %ymm9 +; AVX512BW-NEXT: vshufi64x2 {{.*#+}} zmm9 = zmm9[2,3,2,3],zmm11[0,1,0,1] +; AVX512BW-NEXT: vpmovsxbw {{.*#+}} zmm10 = [14,13,14,15,15,14,14,15,14,13,14,15,15,14,14,15,17,17,16,16,17,17,16,16,20,21,17,17,17,17,16,16] +; AVX512BW-NEXT: vpermw %zmm21, %zmm10, %zmm10 ; AVX512BW-NEXT: movabsq $580999813345182728, %rax # imm = 0x810204081020408 ; AVX512BW-NEXT: kmovq %rax, %k1 -; AVX512BW-NEXT: vmovdqu8 %zmm11, %zmm10 {%k1} +; AVX512BW-NEXT: vmovdqu8 %zmm10, %zmm9 {%k1} ; AVX512BW-NEXT: movabsq $1016749673354069774, %rax # imm = 0xE1C3870E1C3870E ; AVX512BW-NEXT: kmovq %rax, %k1 -; AVX512BW-NEXT: vmovdqu8 %zmm10, %zmm14 {%k1} -; AVX512BW-NEXT: vmovdqa {{.*#+}} xmm11 = [u,u,u,128,7,128,5,u,u,u,128,8,128,6,u,u] -; AVX512BW-NEXT: vpshufb %xmm11, %xmm25, %xmm10 -; AVX512BW-NEXT: vmovdqa64 {{.*#+}} xmm19 = [u,u,u,7,128,5,128,u,u,u,8,128,6,128,u,u] -; AVX512BW-NEXT: vpshufb %xmm19, %xmm24, %xmm26 -; AVX512BW-NEXT: vporq %xmm10, %xmm26, %xmm10 -; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm24 = xmm25[8],xmm24[8],xmm25[9],xmm24[9],xmm25[10],xmm24[10],xmm25[11],xmm24[11],xmm25[12],xmm24[12],xmm25[13],xmm24[13],xmm25[14],xmm24[14],xmm25[15],xmm24[15] -; AVX512BW-NEXT: vpshufb {{.*#+}} xmm24 = xmm24[6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] -; AVX512BW-NEXT: vinserti32x4 $2, %xmm24, %zmm10, %zmm10 -; AVX512BW-NEXT: vmovdqa64 {{.*#+}} xmm24 = [u,128,7,128,5,u,u,u,128,8,128,6,u,u,u,128] -; AVX512BW-NEXT: vpshufb %xmm24, %xmm1, %xmm25 -; AVX512BW-NEXT: vmovdqa64 {{.*#+}} xmm26 = [u,7,128,5,128,u,u,u,8,128,6,128,u,u,u,9] -; AVX512BW-NEXT: vpshufb %xmm26, %xmm0, %xmm27 -; AVX512BW-NEXT: vporq %xmm25, %xmm27, %xmm25 -; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm0 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; AVX512BW-NEXT: vpermq {{.*#+}} zmm1 = zmm10[0,1,0,1,4,5,4,5] -; AVX512BW-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] -; AVX512BW-NEXT: vinserti32x4 $2, %xmm0, %zmm25, %zmm0 -; AVX512BW-NEXT: vpermq {{.*#+}} zmm10 = zmm0[0,1,0,1,4,5,4,5] -; AVX512BW-NEXT: vmovdqu8 %zmm1, %zmm10 {%k3} +; AVX512BW-NEXT: vmovdqu8 %zmm9, %zmm14 {%k1} +; AVX512BW-NEXT: vmovdqa {{.*#+}} xmm10 = [u,u,u,128,7,128,5,u,u,u,128,8,128,6,u,u] +; AVX512BW-NEXT: vpshufb %xmm10, %xmm2, %xmm9 +; AVX512BW-NEXT: vmovdqa {{.*#+}} xmm11 = [u,u,u,7,128,5,128,u,u,u,8,128,6,128,u,u] +; AVX512BW-NEXT: vpshufb %xmm11, %xmm0, %xmm25 +; AVX512BW-NEXT: vporq %xmm9, %xmm25, %xmm9 +; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm0 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; AVX512BW-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] +; AVX512BW-NEXT: vinserti32x4 $2, %xmm0, %zmm9, %zmm0 +; AVX512BW-NEXT: vmovdqa {{.*#+}} xmm2 = [u,128,7,128,5,u,u,u,128,8,128,6,u,u,u,128] +; AVX512BW-NEXT: vpshufb %xmm2, %xmm1, %xmm9 +; AVX512BW-NEXT: vmovdqa64 {{.*#+}} xmm25 = [u,7,128,5,128,u,u,u,8,128,6,128,u,u,u,9] +; AVX512BW-NEXT: vpshufb %xmm25, %xmm24, %xmm26 +; AVX512BW-NEXT: vporq %xmm9, %xmm26, %xmm9 +; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm1[8],xmm24[8],xmm1[9],xmm24[9],xmm1[10],xmm24[10],xmm1[11],xmm24[11],xmm1[12],xmm24[12],xmm1[13],xmm24[13],xmm1[14],xmm24[14],xmm1[15],xmm24[15] +; AVX512BW-NEXT: vpermq {{.*#+}} zmm0 = zmm0[0,1,0,1,4,5,4,5] +; AVX512BW-NEXT: vpshufb {{.*#+}} xmm1 = xmm1[2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] +; AVX512BW-NEXT: vinserti32x4 $2, %xmm1, %zmm9, %zmm1 +; AVX512BW-NEXT: vpermq {{.*#+}} zmm9 = zmm1[0,1,0,1,4,5,4,5] +; AVX512BW-NEXT: vmovdqu8 %zmm0, %zmm9 {%k3} ; AVX512BW-NEXT: vmovdqa {{.*#+}} xmm0 = [128,4,u,u,u,128,7,128,5,u,u,u,128,8,128,6] -; AVX512BW-NEXT: vpshufb %xmm0, %xmm21, %xmm1 -; AVX512BW-NEXT: vpmovsxbw {{.*#+}} zmm25 = [2,2,2,4,2,2,2,4,3,3,3,3,2,2,2,4,52,53,52,53,53,54,53,54,52,53,52,53,53,54,53,54] -; AVX512BW-NEXT: vpermi2w %zmm22, %zmm17, %zmm25 +; AVX512BW-NEXT: vpshufb %xmm0, %xmm22, %xmm1 +; AVX512BW-NEXT: vpmovsxbw {{.*#+}} zmm24 = [2,2,2,4,2,2,2,4,3,3,3,3,2,2,2,4,52,53,52,53,53,54,53,54,52,53,52,53,53,54,53,54] +; AVX512BW-NEXT: vpermi2w %zmm21, %zmm17, %zmm24 ; AVX512BW-NEXT: vmovdqa64 {{.*#+}} xmm17 = [4,128,u,u,u,7,128,5,128,u,u,u,8,128,6,128] -; AVX512BW-NEXT: vpshufb %xmm17, %xmm23, %xmm22 -; AVX512BW-NEXT: vporq %xmm1, %xmm22, %xmm1 -; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm21 = xmm23[8],xmm21[8],xmm23[9],xmm21[9],xmm23[10],xmm21[10],xmm23[11],xmm21[11],xmm23[12],xmm21[12],xmm23[13],xmm21[13],xmm23[14],xmm21[14],xmm23[15],xmm21[15] +; AVX512BW-NEXT: vpshufb %xmm17, %xmm23, %xmm21 +; AVX512BW-NEXT: vporq %xmm1, %xmm21, %xmm1 +; AVX512BW-NEXT: vpunpckhbw {{.*#+}} xmm21 = xmm23[8],xmm22[8],xmm23[9],xmm22[9],xmm23[10],xmm22[10],xmm23[11],xmm22[11],xmm23[12],xmm22[12],xmm23[13],xmm22[13],xmm23[14],xmm22[14],xmm23[15],xmm22[15] ; AVX512BW-NEXT: vpshufb {{.*#+}} xmm21 = xmm21[u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] ; AVX512BW-NEXT: vinserti32x4 $2, %xmm21, %zmm1, %zmm1 ; AVX512BW-NEXT: vpermq {{.*#+}} zmm1 = zmm1[0,1,0,1,4,5,4,5] ; AVX512BW-NEXT: movabsq $290499906672591364, %rax # imm = 0x408102040810204 ; AVX512BW-NEXT: kmovq %rax, %k1 -; AVX512BW-NEXT: vmovdqu8 %zmm25, %zmm1 {%k1} +; AVX512BW-NEXT: vmovdqu8 %zmm24, %zmm1 {%k1} ; AVX512BW-NEXT: movabsq $-8714997200177740921, %rax # imm = 0x870E1C3870E1C387 ; AVX512BW-NEXT: kmovq %rax, %k1 -; AVX512BW-NEXT: vmovdqu8 %zmm1, %zmm10 {%k1} -; AVX512BW-NEXT: vpshufb %xmm11, %xmm5, %xmm1 -; AVX512BW-NEXT: vpshufb %xmm19, %xmm4, %xmm11 -; AVX512BW-NEXT: vpor %xmm1, %xmm11, %xmm1 +; AVX512BW-NEXT: vmovdqu8 %zmm1, %zmm9 {%k1} +; AVX512BW-NEXT: vpshufb %xmm10, %xmm5, %xmm1 +; AVX512BW-NEXT: vpshufb %xmm11, %xmm4, %xmm10 +; AVX512BW-NEXT: vpor %xmm1, %xmm10, %xmm1 ; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm4 = xmm4[0],xmm5[0],xmm4[1],xmm5[1],xmm4[2],xmm5[2],xmm4[3],xmm5[3],xmm4[4],xmm5[4],xmm4[5],xmm5[5],xmm4[6],xmm5[6],xmm4[7],xmm5[7] -; AVX512BW-NEXT: vpshufb %xmm16, %xmm4, %xmm4 +; AVX512BW-NEXT: vpshufb %xmm19, %xmm4, %xmm4 ; AVX512BW-NEXT: vinserti32x4 $2, %xmm1, %zmm4, %zmm1 -; AVX512BW-NEXT: vpshufb %xmm24, %xmm7, %xmm4 -; AVX512BW-NEXT: vpshufb %xmm26, %xmm6, %xmm5 -; AVX512BW-NEXT: vpor %xmm4, %xmm5, %xmm4 -; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm5 = xmm6[0],xmm7[0],xmm6[1],xmm7[1],xmm6[2],xmm7[2],xmm6[3],xmm7[3],xmm6[4],xmm7[4],xmm6[5],xmm7[5],xmm6[6],xmm7[6],xmm6[7],xmm7[7] -; AVX512BW-NEXT: vpshufb %xmm18, %xmm5, %xmm5 -; AVX512BW-NEXT: vinserti32x4 $2, %xmm4, %zmm5, %zmm4 +; AVX512BW-NEXT: vpshufb %xmm2, %xmm7, %xmm2 +; AVX512BW-NEXT: vpshufb %xmm25, %xmm6, %xmm4 +; AVX512BW-NEXT: vpor %xmm2, %xmm4, %xmm2 +; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm4 = xmm6[0],xmm7[0],xmm6[1],xmm7[1],xmm6[2],xmm7[2],xmm6[3],xmm7[3],xmm6[4],xmm7[4],xmm6[5],xmm7[5],xmm6[6],xmm7[6],xmm6[7],xmm7[7] +; AVX512BW-NEXT: vpshufb %xmm18, %xmm4, %xmm4 +; AVX512BW-NEXT: vinserti32x4 $2, %xmm2, %zmm4, %zmm2 ; AVX512BW-NEXT: vpermq {{.*#+}} zmm1 = zmm1[0,1,0,1,4,5,4,5] -; AVX512BW-NEXT: vpermq {{.*#+}} zmm4 = zmm4[0,1,0,1,4,5,4,5] +; AVX512BW-NEXT: vpermq {{.*#+}} zmm2 = zmm2[0,1,0,1,4,5,4,5] ; AVX512BW-NEXT: movabsq $871499720017774092, %rax # imm = 0xC183060C183060C ; AVX512BW-NEXT: kmovq %rax, %k1 -; AVX512BW-NEXT: vmovdqu8 %zmm1, %zmm4 {%k1} -; AVX512BW-NEXT: vpshufb %xmm0, %xmm12, %xmm0 -; AVX512BW-NEXT: vpshufb %xmm17, %xmm3, %xmm1 +; AVX512BW-NEXT: vmovdqu8 %zmm1, %zmm2 {%k1} +; AVX512BW-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm4 # 16-byte Reload +; AVX512BW-NEXT: vpshufb %xmm0, %xmm4, %xmm0 +; AVX512BW-NEXT: vpshufb %xmm17, %xmm12, %xmm1 ; AVX512BW-NEXT: vpor %xmm0, %xmm1, %xmm0 -; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm3[0],xmm12[0],xmm3[1],xmm12[1],xmm3[2],xmm12[2],xmm3[3],xmm12[3],xmm3[4],xmm12[4],xmm3[5],xmm12[5],xmm3[6],xmm12[6],xmm3[7],xmm12[7] -; AVX512BW-NEXT: vpshufb %xmm9, %xmm1, %xmm1 +; AVX512BW-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm12[0],xmm4[0],xmm12[1],xmm4[1],xmm12[2],xmm4[2],xmm12[3],xmm4[3],xmm12[4],xmm4[4],xmm12[5],xmm4[5],xmm12[6],xmm4[6],xmm12[7],xmm4[7] +; AVX512BW-NEXT: vpshufb %xmm15, %xmm1, %xmm1 ; AVX512BW-NEXT: vinserti32x4 $2, %xmm0, %zmm1, %zmm0 ; AVX512BW-NEXT: vpmovsxbw {{.*#+}} zmm1 = [1,1,0,0,1,1,0,0,4,5,1,1,1,1,0,0,18,18,18,20,18,18,18,20,19,19,19,19,18,18,18,20] ; AVX512BW-NEXT: vpermw %zmm13, %zmm1, %zmm1 @@ -10734,334 +10506,319 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512BW-NEXT: vmovdqu8 %zmm1, %zmm0 {%k1} ; AVX512BW-NEXT: movabsq $8133997386832558192, %rax # imm = 0x70E1C3870E1C3870 ; AVX512BW-NEXT: kmovq %rax, %k1 -; AVX512BW-NEXT: vmovdqu8 %zmm0, %zmm4 {%k1} +; AVX512BW-NEXT: vmovdqu8 %zmm0, %zmm2 {%k1} ; AVX512BW-NEXT: movq {{[0-9]+}}(%rsp), %rax -; AVX512BW-NEXT: vmovdqa64 %zmm4, (%rax) +; AVX512BW-NEXT: vmovdqa64 %zmm2, (%rax) ; AVX512BW-NEXT: vmovdqa64 %zmm8, 320(%rax) -; AVX512BW-NEXT: vmovdqa64 %zmm10, 256(%rax) +; AVX512BW-NEXT: vmovdqa64 %zmm9, 256(%rax) ; AVX512BW-NEXT: vmovdqa64 %zmm14, 192(%rax) ; AVX512BW-NEXT: vmovdqa64 %zmm20, 128(%rax) -; AVX512BW-NEXT: vmovdqa64 %zmm2, 64(%rax) -; AVX512BW-NEXT: vmovdqa64 %zmm15, 384(%rax) +; AVX512BW-NEXT: vmovdqa64 %zmm3, 64(%rax) +; AVX512BW-NEXT: vmovdqa64 %zmm16, 384(%rax) ; AVX512BW-NEXT: vzeroupper ; AVX512BW-NEXT: retq ; ; AVX512BW-FCP-LABEL: store_i8_stride7_vf64: ; AVX512BW-FCP: # %bb.0: -; AVX512BW-FCP-NEXT: subq $40, %rsp +; AVX512BW-FCP-NEXT: subq $104, %rsp ; AVX512BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax -; AVX512BW-FCP-NEXT: vmovdqa (%rax), %ymm0 -; AVX512BW-FCP-NEXT: vmovdqu %ymm0, (%rsp) # 32-byte Spill -; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} ymm28 = [12,13,2,3,12,13,0,1,14,15,2,3,0,1,14,15,28,29,18,19,28,29,16,17,30,31,18,19,16,17,30,31] -; AVX512BW-FCP-NEXT: vpshufb %ymm28, %ymm0, %ymm1 -; AVX512BW-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [4,5,4,5,5,6,5,6,4,5,4,5,5,6,5,6] -; AVX512BW-FCP-NEXT: # ymm2 = mem[0,1,0,1] -; AVX512BW-FCP-NEXT: vpermw %ymm0, %ymm2, %ymm2 -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm2 -; AVX512BW-FCP-NEXT: vmovdqa (%r9), %ymm0 -; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} ymm1 = [13,128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128] -; AVX512BW-FCP-NEXT: vpshufb %ymm1, %ymm0, %ymm3 -; AVX512BW-FCP-NEXT: vmovdqa64 %ymm0, %ymm19 -; AVX512BW-FCP-NEXT: vmovdqa64 (%r8), %ymm20 -; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} ymm22 = [128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128] -; AVX512BW-FCP-NEXT: vpshufb %ymm22, %ymm20, %ymm4 +; AVX512BW-FCP-NEXT: vmovdqa (%rax), %ymm2 +; AVX512BW-FCP-NEXT: vmovdqu %ymm2, (%rsp) # 32-byte Spill +; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} ymm20 = [12,13,2,3,12,13,0,1,14,15,2,3,0,1,14,15,28,29,18,19,28,29,16,17,30,31,18,19,16,17,30,31] +; AVX512BW-FCP-NEXT: vpshufb %ymm20, %ymm2, %ymm0 +; AVX512BW-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [4,5,4,5,5,6,5,6,4,5,4,5,5,6,5,6] +; AVX512BW-FCP-NEXT: # ymm1 = mem[0,1,0,1] +; AVX512BW-FCP-NEXT: vpermw %ymm2, %ymm1, %ymm1 +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm2 +; AVX512BW-FCP-NEXT: vmovdqa (%r9), %ymm1 +; AVX512BW-FCP-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} ymm0 = [13,128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128] +; AVX512BW-FCP-NEXT: vpshufb %ymm0, %ymm1, %ymm3 +; AVX512BW-FCP-NEXT: vmovdqa (%r8), %ymm4 +; AVX512BW-FCP-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} ymm1 = [128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128] +; AVX512BW-FCP-NEXT: vpshufb %ymm1, %ymm4, %ymm4 ; AVX512BW-FCP-NEXT: vpor %ymm3, %ymm4, %ymm3 -; AVX512BW-FCP-NEXT: vmovdqa (%r9), %xmm0 -; AVX512BW-FCP-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512BW-FCP-NEXT: vmovdqa (%r8), %xmm4 -; AVX512BW-FCP-NEXT: vmovdqa %xmm4, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] +; AVX512BW-FCP-NEXT: vmovdqa64 (%r9), %xmm16 +; AVX512BW-FCP-NEXT: vmovdqa (%r8), %xmm15 +; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm15[8],xmm16[8],xmm15[9],xmm16[9],xmm15[10],xmm16[10],xmm15[11],xmm16[11],xmm15[12],xmm16[12],xmm15[13],xmm16[13],xmm15[14],xmm16[14],xmm15[15],xmm16[15] ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} xmm4 = xmm4[u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] ; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[0,1,0,1] ; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm3, %zmm4, %zmm3 ; AVX512BW-FCP-NEXT: movabsq $2323999253380730912, %r10 # imm = 0x2040810204081020 ; AVX512BW-FCP-NEXT: kmovq %r10, %k1 ; AVX512BW-FCP-NEXT: vmovdqu8 %zmm2, %zmm3 {%k1} -; AVX512BW-FCP-NEXT: vmovdqa (%rdx), %ymm0 -; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} ymm4 = [0,1,0,1,14,128,14,15,0,1,14,15,128,13,14,15,16,17,16,128,30,31,30,31,16,17,128,31,28,29,30,31] -; AVX512BW-FCP-NEXT: vpshufb %ymm4, %ymm0, %ymm2 -; AVX512BW-FCP-NEXT: vmovdqa %ymm0, %ymm9 -; AVX512BW-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512BW-FCP-NEXT: vmovdqa (%rcx), %ymm0 -; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} ymm11 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] -; AVX512BW-FCP-NEXT: vpshufb %ymm11, %ymm0, %ymm5 -; AVX512BW-FCP-NEXT: vmovdqa64 %ymm0, %ymm18 -; AVX512BW-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512BW-FCP-NEXT: vpor %ymm2, %ymm5, %ymm2 -; AVX512BW-FCP-NEXT: vmovdqa (%rdx), %xmm14 -; AVX512BW-FCP-NEXT: vmovdqa (%rcx), %xmm15 -; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm15[8],xmm14[8],xmm15[9],xmm14[9],xmm15[10],xmm14[10],xmm15[11],xmm14[11],xmm15[12],xmm14[12],xmm15[13],xmm14[13],xmm15[14],xmm14[14],xmm15[15],xmm14[15] -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} xmm5 = xmm5[6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm5[0,1,0,1] -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm5, %zmm2 -; AVX512BW-FCP-NEXT: vmovdqa (%rdi), %ymm0 -; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} ymm12 = [0,1,14,128,12,13,0,1,14,15,128,3,12,13,2,3,16,128,30,31,28,29,16,17,128,31,18,19,28,29,18,128] -; AVX512BW-FCP-NEXT: vpshufb %ymm12, %ymm0, %ymm5 -; AVX512BW-FCP-NEXT: vmovdqa %ymm0, %ymm6 -; AVX512BW-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512BW-FCP-NEXT: vmovdqa64 (%rsi), %ymm24 -; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} ymm21 = [128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128,128,18] -; AVX512BW-FCP-NEXT: vpshufb %ymm21, %ymm24, %ymm16 -; AVX512BW-FCP-NEXT: vporq %ymm5, %ymm16, %ymm5 -; AVX512BW-FCP-NEXT: vmovdqa64 (%rdi), %xmm16 -; AVX512BW-FCP-NEXT: vmovdqa64 (%rsi), %xmm17 -; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm25 = xmm17[8],xmm16[8],xmm17[9],xmm16[9],xmm17[10],xmm16[10],xmm17[11],xmm16[11],xmm17[12],xmm16[12],xmm17[13],xmm16[13],xmm17[14],xmm16[14],xmm17[15],xmm16[15] -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} xmm25 = xmm25[2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm25 = ymm25[0,1,0,1] -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm5, %zmm25, %zmm13 +; AVX512BW-FCP-NEXT: vmovdqa (%rdx), %ymm4 +; AVX512BW-FCP-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} ymm2 = [0,1,0,1,14,128,14,15,0,1,14,15,128,13,14,15,16,17,16,128,30,31,30,31,16,17,128,31,28,29,30,31] +; AVX512BW-FCP-NEXT: vpshufb %ymm2, %ymm4, %ymm4 +; AVX512BW-FCP-NEXT: vmovdqa (%rcx), %ymm6 +; AVX512BW-FCP-NEXT: vmovdqu %ymm6, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} ymm5 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] +; AVX512BW-FCP-NEXT: vpshufb %ymm5, %ymm6, %ymm6 +; AVX512BW-FCP-NEXT: vpor %ymm4, %ymm6, %ymm4 +; AVX512BW-FCP-NEXT: vmovdqa64 (%rdx), %xmm17 +; AVX512BW-FCP-NEXT: vmovdqa64 (%rcx), %xmm19 +; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm19[8],xmm17[8],xmm19[9],xmm17[9],xmm19[10],xmm17[10],xmm19[11],xmm17[11],xmm19[12],xmm17[12],xmm19[13],xmm17[13],xmm19[14],xmm17[14],xmm19[15],xmm17[15] +; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} xmm29 = [6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] +; AVX512BW-FCP-NEXT: vpshufb %xmm29, %xmm6, %xmm6 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[0,1,0,1] +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm6, %zmm4 +; AVX512BW-FCP-NEXT: vmovdqa (%rdi), %ymm6 +; AVX512BW-FCP-NEXT: vmovdqu %ymm6, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} ymm9 = [0,1,14,128,12,13,0,1,14,15,128,3,12,13,2,3,16,128,30,31,28,29,16,17,128,31,18,19,28,29,18,128] +; AVX512BW-FCP-NEXT: vpshufb %ymm9, %ymm6, %ymm6 +; AVX512BW-FCP-NEXT: vmovdqa (%rsi), %ymm7 +; AVX512BW-FCP-NEXT: vmovdqu %ymm7, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} ymm23 = [128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128,128,18] +; AVX512BW-FCP-NEXT: vpshufb %ymm23, %ymm7, %ymm21 +; AVX512BW-FCP-NEXT: vporq %ymm6, %ymm21, %ymm6 +; AVX512BW-FCP-NEXT: vmovdqa64 (%rdi), %xmm21 +; AVX512BW-FCP-NEXT: vmovdqa64 (%rsi), %xmm22 +; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm24 = xmm22[8],xmm21[8],xmm22[9],xmm21[9],xmm22[10],xmm21[10],xmm22[11],xmm21[11],xmm22[12],xmm21[12],xmm22[13],xmm21[13],xmm22[14],xmm21[14],xmm22[15],xmm21[15] +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm7 = [2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] +; AVX512BW-FCP-NEXT: vpshufb %xmm7, %xmm24, %xmm24 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm24 = ymm24[0,1,0,1] +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm6, %zmm24, %zmm14 ; AVX512BW-FCP-NEXT: movabsq $435749860008887046, %r10 # imm = 0x60C183060C18306 ; AVX512BW-FCP-NEXT: kmovq %r10, %k1 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm2, %zmm13 {%k1} +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm4, %zmm14 {%k1} ; AVX512BW-FCP-NEXT: movabsq $4066998693416279096, %r10 # imm = 0x3870E1C3870E1C38 ; AVX512BW-FCP-NEXT: kmovq %r10, %k1 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm3, %zmm13 {%k1} -; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm0 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,24,25,128,23,128,21,22,23,26,128,24,128,28,29,26,27] -; AVX512BW-FCP-NEXT: vmovdqa 32(%rdx), %ymm2 -; AVX512BW-FCP-NEXT: vpshufb %ymm0, %ymm2, %ymm3 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm25 = ymm3[2,3,2,3] -; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm0 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128] -; AVX512BW-FCP-NEXT: vmovdqa 32(%rcx), %ymm3 -; AVX512BW-FCP-NEXT: vpshufb %ymm0, %ymm3, %ymm26 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm26 = ymm26[2,3,2,3] -; AVX512BW-FCP-NEXT: vporq %ymm25, %ymm26, %ymm25 -; AVX512BW-FCP-NEXT: vpshufb %ymm4, %ymm2, %ymm4 -; AVX512BW-FCP-NEXT: vpshufb %ymm11, %ymm3, %ymm11 -; AVX512BW-FCP-NEXT: vpor %ymm4, %ymm11, %ymm4 -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm25, %zmm4, %zmm4 -; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm0 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,19,20,21,128,19,128,21,20,21,22,128,20,128,22,23,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128] -; AVX512BW-FCP-NEXT: vmovdqa 32(%rdi), %ymm11 -; AVX512BW-FCP-NEXT: vpshufb %ymm0, %ymm11, %ymm25 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm25 = ymm25[2,3,2,3] -; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm0 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128,25] -; AVX512BW-FCP-NEXT: vmovdqa64 32(%rsi), %ymm27 -; AVX512BW-FCP-NEXT: vpshufb %ymm0, %ymm27, %ymm26 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm26 = ymm26[2,3,2,3] -; AVX512BW-FCP-NEXT: vporq %ymm25, %ymm26, %ymm25 -; AVX512BW-FCP-NEXT: vpshufb %ymm12, %ymm11, %ymm12 -; AVX512BW-FCP-NEXT: vpshufb %ymm21, %ymm27, %ymm21 -; AVX512BW-FCP-NEXT: vporq %ymm12, %ymm21, %ymm12 -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm25, %zmm12, %zmm12 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm3, %zmm14 {%k1} +; AVX512BW-FCP-NEXT: vmovdqa 32(%rdx), %ymm3 +; AVX512BW-FCP-NEXT: vpshufb %ymm2, %ymm3, %ymm4 +; AVX512BW-FCP-NEXT: vmovdqa 32(%rcx), %ymm2 +; AVX512BW-FCP-NEXT: vpshufb %ymm5, %ymm2, %ymm5 +; AVX512BW-FCP-NEXT: vpor %ymm4, %ymm5, %ymm4 +; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm5 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,24,25,128,23,128,21,22,23,26,128,24,128,28,29,26,27] +; AVX512BW-FCP-NEXT: vpshufb %ymm5, %ymm3, %ymm5 +; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm6 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128] +; AVX512BW-FCP-NEXT: vpshufb %ymm6, %ymm2, %ymm24 +; AVX512BW-FCP-NEXT: vporq %ymm5, %ymm24, %ymm5 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,3,2,3] +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm5, %zmm4, %zmm4 +; AVX512BW-FCP-NEXT: vmovdqa 32(%rdi), %ymm5 +; AVX512BW-FCP-NEXT: vpshufb %ymm9, %ymm5, %ymm9 +; AVX512BW-FCP-NEXT: vmovdqa64 32(%rsi), %ymm25 +; AVX512BW-FCP-NEXT: vpshufb %ymm23, %ymm25, %ymm23 +; AVX512BW-FCP-NEXT: vporq %ymm9, %ymm23, %ymm9 +; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm6 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,19,20,21,128,19,128,21,20,21,22,128,20,128,22,23,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128] +; AVX512BW-FCP-NEXT: vpshufb %ymm6, %ymm5, %ymm23 +; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm6 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128,25] +; AVX512BW-FCP-NEXT: vpshufb %ymm6, %ymm25, %ymm24 +; AVX512BW-FCP-NEXT: vporq %ymm23, %ymm24, %ymm23 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm23 = ymm23[2,3,2,3] +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm23, %zmm9, %zmm9 ; AVX512BW-FCP-NEXT: movabsq $3485998880071096368, %r10 # imm = 0x3060C183060C1830 -; AVX512BW-FCP-NEXT: kmovq %r10, %k2 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm4, %zmm12 {%k2} -; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm0 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,24,25,24,25,128,23,128,23,24,25,26,128,24,128,30,31] -; AVX512BW-FCP-NEXT: vmovdqa 32(%r8), %ymm4 -; AVX512BW-FCP-NEXT: vpshufb %ymm0, %ymm4, %ymm21 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm25 = ymm21[2,3,2,3] -; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm5 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,128,128,25,128,23,128,128,128,128,26,128,24,128,128] -; AVX512BW-FCP-NEXT: vmovdqa 32(%r9), %ymm0 -; AVX512BW-FCP-NEXT: vpshufb %ymm5, %ymm0, %ymm26 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm26 = ymm26[2,3,2,3] -; AVX512BW-FCP-NEXT: vporq %ymm25, %ymm26, %ymm25 -; AVX512BW-FCP-NEXT: vpshufb %ymm1, %ymm0, %ymm1 -; AVX512BW-FCP-NEXT: vpshufb %ymm22, %ymm4, %ymm22 -; AVX512BW-FCP-NEXT: vporq %ymm1, %ymm22, %ymm1 -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm25, %zmm1, %zmm1 -; AVX512BW-FCP-NEXT: vmovdqa64 32(%rax), %ymm31 -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm22 = [10,9,9,10,10,9,9,10,9,10,14,15,10,9,9,10] -; AVX512BW-FCP-NEXT: vpermw %ymm31, %ymm22, %ymm22 -; AVX512BW-FCP-NEXT: vpshufb %ymm28, %ymm31, %ymm25 -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm22, %zmm25, %zmm22 -; AVX512BW-FCP-NEXT: movabsq $145249953336295682, %r10 # imm = 0x204081020408102 ; AVX512BW-FCP-NEXT: kmovq %r10, %k1 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm22, %zmm1 {%k1} +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm4, %zmm9 {%k1} +; AVX512BW-FCP-NEXT: vmovdqa 32(%r9), %ymm4 +; AVX512BW-FCP-NEXT: vpshufb %ymm0, %ymm4, %ymm0 +; AVX512BW-FCP-NEXT: vmovdqa64 32(%r8), %ymm28 +; AVX512BW-FCP-NEXT: vpshufb %ymm1, %ymm28, %ymm1 +; AVX512BW-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm1 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,24,25,24,25,128,23,128,23,24,25,26,128,24,128,30,31] +; AVX512BW-FCP-NEXT: vpshufb %ymm1, %ymm28, %ymm1 +; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm6 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,128,128,25,128,23,128,128,128,128,26,128,24,128,128] +; AVX512BW-FCP-NEXT: vpshufb %ymm6, %ymm4, %ymm23 +; AVX512BW-FCP-NEXT: vporq %ymm1, %ymm23, %ymm1 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm0, %zmm1 +; AVX512BW-FCP-NEXT: vmovdqa 32(%rax), %ymm6 +; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm23 = [10,9,9,10,10,9,9,10,9,10,14,15,10,9,9,10] +; AVX512BW-FCP-NEXT: vpermw %ymm6, %ymm23, %ymm23 +; AVX512BW-FCP-NEXT: vpshufb %ymm20, %ymm6, %ymm20 +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm23, %zmm20, %zmm20 +; AVX512BW-FCP-NEXT: movabsq $145249953336295682, %r10 # imm = 0x204081020408102 +; AVX512BW-FCP-NEXT: kmovq %r10, %k2 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm20, %zmm1 {%k2} ; AVX512BW-FCP-NEXT: movabsq $-4357498600088870461, %r10 # imm = 0xC3870E1C3870E1C3 -; AVX512BW-FCP-NEXT: kmovq %r10, %k1 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm12 {%k1} -; AVX512BW-FCP-NEXT: vmovdqa64 (%rcx), %zmm25 -; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm2[0,1,2,3],zmm25[4,5,6,7] +; AVX512BW-FCP-NEXT: kmovq %r10, %k2 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm9 {%k2} +; AVX512BW-FCP-NEXT: vmovdqa64 (%rcx), %zmm23 +; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm3[0,1,2,3],zmm23[4,5,6,7] ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm1 = zmm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,zmm1[23],zero,zmm1[21,22,23,26],zero,zmm1[24],zero,zmm1[28,29,26,27,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,59],zero,zero,zero,zero,zmm1[62],zero,zmm1[60],zero,zero,zero,zero,zmm1[63],zero,zmm1[61],zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] -; AVX512BW-FCP-NEXT: vmovdqa64 (%rdx), %zmm26 -; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm3[0,1,2,3],zmm26[4,5,6,7] +; AVX512BW-FCP-NEXT: vmovdqa64 (%rdx), %zmm24 +; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm2[0,1,2,3],zmm24[4,5,6,7] ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm2 = zmm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zmm2[25],zero,zmm2[23],zero,zero,zero,zero,zmm2[26],zero,zmm2[24],zero,zero,zero,zero,zmm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm2[62],zero,zmm2[60],zero,zero,zero,zero,zmm2[63],zero,zmm2[61],zero,zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm2 = zmm2[2,3,2,3,6,7,6,7] ; AVX512BW-FCP-NEXT: vporq %zmm1, %zmm2, %zmm1 -; AVX512BW-FCP-NEXT: vmovdqa64 (%rdi), %zmm28 -; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm27[0,1,2,3],zmm28[4,5,6,7] +; AVX512BW-FCP-NEXT: vmovdqa64 (%rdi), %zmm26 +; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm25[0,1,2,3],zmm26[4,5,6,7] ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm2 = zmm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,zmm2[23],zero,zero,zero,zero,zmm2[26],zero,zmm2[24],zero,zero,zero,zero,zmm2[27],zero,zmm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,60,61,62],zero,zmm2[60],zero,zmm2[62,63,62,63],zero,zmm2[61],zero,zmm2[63,60,61] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm2 = zmm2[2,3,2,3,6,7,6,7] -; AVX512BW-FCP-NEXT: vmovdqa64 (%rsi), %zmm29 -; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm3 = zmm11[0,1,2,3],zmm29[4,5,6,7] +; AVX512BW-FCP-NEXT: vmovdqa64 (%rsi), %zmm27 +; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm3 = zmm5[0,1,2,3],zmm27[4,5,6,7] ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm3 = zmm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm3[23],zero,zero,zero,zero,zmm3[26],zero,zmm3[24],zero,zero,zero,zero,zmm3[27],zero,zmm3[25,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zmm3[62],zero,zmm3[60],zero,zero,zero,zero,zmm3[63],zero,zmm3[61],zero,zero,zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm3 = zmm3[2,3,2,3,6,7,6,7] -; AVX512BW-FCP-NEXT: vporq %zmm2, %zmm3, %zmm22 +; AVX512BW-FCP-NEXT: vporq %zmm2, %zmm3, %zmm2 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm20 = zmm2[2,3,2,3,6,7,6,7] ; AVX512BW-FCP-NEXT: movabsq $1742999440035548184, %r10 # imm = 0x183060C183060C18 -; AVX512BW-FCP-NEXT: kmovq %r10, %k1 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm22 {%k1} -; AVX512BW-FCP-NEXT: vmovdqa64 (%r9), %zmm27 -; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm4[0,1,2,3],zmm27[4,5,6,7] +; AVX512BW-FCP-NEXT: kmovq %r10, %k2 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm20 {%k2} +; AVX512BW-FCP-NEXT: vmovdqa64 (%r9), %zmm25 +; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm28[0,1,2,3],zmm25[4,5,6,7] ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm1 = zmm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,zmm1[23],zero,zmm1[23,24,25,26],zero,zmm1[24],zero,zmm1[30,31,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,61],zero,zmm1[59],zero,zero,zero,zero,zmm1[62],zero,zmm1[60],zero,zero,zero,zero,zmm1[63],zero +; AVX512BW-FCP-NEXT: vmovdqa64 (%r8), %zmm28 +; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm4[0,1,2,3],zmm28[4,5,6,7] +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm2 = zmm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm2[25],zero,zmm2[23],zero,zero,zero,zero,zmm2[26],zero,zmm2[24],zero,zero,zmm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm2[59],zero,zero,zero,zero,zmm2[62],zero,zmm2[60],zero,zero,zero,zero,zmm2[63],zero,zmm2[61] +; AVX512BW-FCP-NEXT: vporq %zmm1, %zmm2, %zmm1 ; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] -; AVX512BW-FCP-NEXT: vmovdqa64 (%r8), %zmm30 -; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm0 = zmm0[0,1,2,3],zmm30[4,5,6,7] -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm0 = zmm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm0[25],zero,zmm0[23],zero,zero,zero,zero,zmm0[26],zero,zmm0[24],zero,zero,zmm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm0[59],zero,zero,zero,zero,zmm0[62],zero,zmm0[60],zero,zero,zero,zero,zmm0[63],zero,zmm0[61] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm0 = zmm0[2,3,2,3,6,7,6,7] -; AVX512BW-FCP-NEXT: vporq %zmm1, %zmm0, %zmm0 ; AVX512BW-FCP-NEXT: movabsq $6971997760142192736, %r10 # imm = 0x60C183060C183060 -; AVX512BW-FCP-NEXT: kmovq %r10, %k1 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm0, %zmm22 {%k1} -; AVX512BW-FCP-NEXT: vmovdqa64 (%rax), %zmm10 -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm0 = [11,13,12,11,12,13,13,12,11,13,12,11,12,13,13,12,62,61,62,63,63,62,62,63,62,61,62,63,63,62,62,63] -; AVX512BW-FCP-NEXT: vpermi2w %zmm10, %zmm31, %zmm0 +; AVX512BW-FCP-NEXT: kmovq %r10, %k2 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm20 {%k2} +; AVX512BW-FCP-NEXT: vmovdqa64 (%rax), %zmm31 +; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm1 = [11,13,12,11,12,13,13,12,11,13,12,11,12,13,13,12,62,61,62,63,63,62,62,63,62,61,62,63,63,62,62,63] +; AVX512BW-FCP-NEXT: vpermi2w %zmm31, %zmm6, %zmm1 ; AVX512BW-FCP-NEXT: movabsq $-9150747060186627967, %rax # imm = 0x8102040810204081 ; AVX512BW-FCP-NEXT: kmovq %rax, %k3 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm0, %zmm22 {%k3} -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,30],zero,ymm6[28],zero,ymm6[30,31,30,31],zero,ymm6[29],zero,ymm6[31,28,29] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm24[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm24[30],zero,ymm24[28],zero,zero,zero,zero,ymm24[31],zero,ymm24[29],zero,zero,zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512BW-FCP-NEXT: vpor %ymm0, %ymm1, %ymm1 -; AVX512BW-FCP-NEXT: vmovdqa 32(%rdi), %xmm8 -; AVX512BW-FCP-NEXT: vmovdqa 32(%rsi), %xmm7 -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm4 = xmm8[0],xmm7[0],xmm8[1],xmm7[1],xmm8[2],xmm7[2],xmm8[3],xmm7[3],xmm8[4],xmm7[4],xmm8[5],xmm7[5],xmm8[6],xmm7[6],xmm8[7],xmm7[7] -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} xmm4 = xmm4[0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[0,1,0,1] -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm1, %zmm6 -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm18[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,zero,zero,ymm18[30],zero,ymm18[28],zero,zero,zero,zero,ymm18[31],zero,ymm18[29],zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm9[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm9[30],zero,ymm9[28],zero,zero,zero,zero,ymm9[31],zero,ymm9[29],zero,zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,2,3] -; AVX512BW-FCP-NEXT: vpor %ymm1, %ymm4, %ymm4 -; AVX512BW-FCP-NEXT: vmovdqa 32(%rdx), %xmm2 -; AVX512BW-FCP-NEXT: vmovdqa 32(%rcx), %xmm1 -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm2[0],xmm1[0],xmm2[1],xmm1[1],xmm2[2],xmm1[2],xmm2[3],xmm1[3],xmm2[4],xmm1[4],xmm2[5],xmm1[5],xmm2[6],xmm1[6],xmm2[7],xmm1[7] -; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} xmm18 = [4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] -; AVX512BW-FCP-NEXT: vpshufb %xmm18, %xmm0, %xmm0 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,1,0,1] -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm4, %zmm9 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm6, %zmm9 {%k2} -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm19[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm19[27],zero,zero,zero,zero,ymm19[30],zero,ymm19[28],zero,zero,zero,zero,ymm19[31],zero -; AVX512BW-FCP-NEXT: vmovdqa64 %ymm19, %ymm21 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm6 = ymm20[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm20[27],zero,zero,zero,zero,ymm20[30],zero,ymm20[28],zero,zero,zero,zero,ymm20[31],zero,ymm20[29] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,3,2,3] -; AVX512BW-FCP-NEXT: vpor %ymm0, %ymm6, %ymm3 -; AVX512BW-FCP-NEXT: vmovdqa 32(%r9), %xmm5 -; AVX512BW-FCP-NEXT: vmovdqa 32(%r8), %xmm4 -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm4[0],xmm5[0],xmm4[1],xmm5[1],xmm4[2],xmm5[2],xmm4[3],xmm5[3],xmm4[4],xmm5[4],xmm4[5],xmm5[5],xmm4[6],xmm5[6],xmm4[7],xmm5[7] -; AVX512BW-FCP-NEXT: vmovdqa64 {{.*#+}} xmm19 = [u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] -; AVX512BW-FCP-NEXT: vpshufb %xmm19, %xmm0, %xmm0 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,1,0,1] -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm3, %zmm0 -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm3 = [14,13,14,15,15,14,14,15,14,13,14,15,15,14,14,15,17,17,16,16,17,17,16,16,20,21,17,17,17,17,16,16] -; AVX512BW-FCP-NEXT: vpermw %zmm10, %zmm3, %zmm3 -; AVX512BW-FCP-NEXT: movabsq $580999813345182728, %rax # imm = 0x810204081020408 -; AVX512BW-FCP-NEXT: kmovq %rax, %k2 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm3, %zmm0 {%k2} -; AVX512BW-FCP-NEXT: movabsq $1016749673354069774, %rax # imm = 0xE1C3870E1C3870E -; AVX512BW-FCP-NEXT: kmovq %rax, %k2 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm0, %zmm9 {%k2} -; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm11 = [u,u,u,128,7,128,5,u,u,u,128,8,128,6,u,u] -; AVX512BW-FCP-NEXT: vpshufb %xmm11, %xmm1, %xmm3 -; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm6 = [u,u,u,7,128,5,128,u,u,u,8,128,6,128,u,u] -; AVX512BW-FCP-NEXT: vpshufb %xmm6, %xmm2, %xmm23 -; AVX512BW-FCP-NEXT: vporq %xmm3, %xmm23, %xmm3 -; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm1[8],xmm2[8],xmm1[9],xmm2[9],xmm1[10],xmm2[10],xmm1[11],xmm2[11],xmm1[12],xmm2[12],xmm1[13],xmm2[13],xmm1[14],xmm2[14],xmm1[15],xmm2[15] -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} xmm1 = xmm1[6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] -; AVX512BW-FCP-NEXT: vinserti32x4 $2, %xmm1, %zmm3, %zmm1 -; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm2 = [u,128,7,128,5,u,u,u,128,8,128,6,u,u,u,128] -; AVX512BW-FCP-NEXT: vpshufb %xmm2, %xmm7, %xmm3 -; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm0 = [u,7,128,5,128,u,u,u,8,128,6,128,u,u,u,9] -; AVX512BW-FCP-NEXT: vpshufb %xmm0, %xmm8, %xmm23 -; AVX512BW-FCP-NEXT: vporq %xmm3, %xmm23, %xmm3 -; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm7[8],xmm8[8],xmm7[9],xmm8[9],xmm7[10],xmm8[10],xmm7[11],xmm8[11],xmm7[12],xmm8[12],xmm7[13],xmm8[13],xmm7[14],xmm8[14],xmm7[15],xmm8[15] -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} xmm7 = xmm7[2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] -; AVX512BW-FCP-NEXT: vinserti32x4 $2, %xmm7, %zmm3, %zmm3 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm1 = zmm1[0,1,0,1,4,5,4,5] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm23 = zmm3[0,1,0,1,4,5,4,5] -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm23 {%k1} -; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm1 = [128,4,u,u,u,128,7,128,5,u,u,u,128,8,128,6] -; AVX512BW-FCP-NEXT: vpshufb %xmm1, %xmm5, %xmm3 -; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm7 = [4,128,u,u,u,7,128,5,128,u,u,u,8,128,6,128] -; AVX512BW-FCP-NEXT: vpshufb %xmm7, %xmm4, %xmm8 -; AVX512BW-FCP-NEXT: vpor %xmm3, %xmm8, %xmm3 -; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm4[8],xmm5[8],xmm4[9],xmm5[9],xmm4[10],xmm5[10],xmm4[11],xmm5[11],xmm4[12],xmm5[12],xmm4[13],xmm5[13],xmm4[14],xmm5[14],xmm4[15],xmm5[15] -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} xmm4 = xmm4[u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] -; AVX512BW-FCP-NEXT: vinserti32x4 $2, %xmm4, %zmm3, %zmm3 -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm4 = [2,2,2,4,2,2,2,4,3,3,3,3,2,2,2,4,52,53,52,53,53,54,53,54,52,53,52,53,53,54,53,54] -; AVX512BW-FCP-NEXT: vpermi2w %zmm10, %zmm31, %zmm4 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm20 {%k3} +; AVX512BW-FCP-NEXT: vmovdqa 32(%rdx), %xmm5 +; AVX512BW-FCP-NEXT: vmovdqa 32(%rcx), %xmm4 +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm13 = [u,u,u,128,7,128,5,u,u,u,128,8,128,6,u,u] +; AVX512BW-FCP-NEXT: vpshufb %xmm13, %xmm4, %xmm1 +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm12 = [u,u,u,7,128,5,128,u,u,u,8,128,6,128,u,u] +; AVX512BW-FCP-NEXT: vpshufb %xmm12, %xmm5, %xmm2 +; AVX512BW-FCP-NEXT: vpor %xmm1, %xmm2, %xmm1 +; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm4[8],xmm5[8],xmm4[9],xmm5[9],xmm4[10],xmm5[10],xmm4[11],xmm5[11],xmm4[12],xmm5[12],xmm4[13],xmm5[13],xmm4[14],xmm5[14],xmm4[15],xmm5[15] +; AVX512BW-FCP-NEXT: vpshufb %xmm29, %xmm2, %xmm2 +; AVX512BW-FCP-NEXT: vinserti32x4 $2, %xmm2, %zmm1, %zmm3 +; AVX512BW-FCP-NEXT: vmovdqa 32(%rdi), %xmm2 +; AVX512BW-FCP-NEXT: vmovdqa 32(%rsi), %xmm1 +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm11 = [u,128,7,128,5,u,u,u,128,8,128,6,u,u,u,128] +; AVX512BW-FCP-NEXT: vpshufb %xmm11, %xmm1, %xmm29 +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm8 = [u,7,128,5,128,u,u,u,8,128,6,128,u,u,u,9] +; AVX512BW-FCP-NEXT: vpshufb %xmm8, %xmm2, %xmm30 +; AVX512BW-FCP-NEXT: vporq %xmm29, %xmm30, %xmm29 +; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm30 = xmm1[8],xmm2[8],xmm1[9],xmm2[9],xmm1[10],xmm2[10],xmm1[11],xmm2[11],xmm1[12],xmm2[12],xmm1[13],xmm2[13],xmm1[14],xmm2[14],xmm1[15],xmm2[15] +; AVX512BW-FCP-NEXT: vpshufb %xmm7, %xmm30, %xmm30 +; AVX512BW-FCP-NEXT: vinserti32x4 $2, %xmm30, %zmm29, %zmm29 ; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm3 = zmm3[0,1,0,1,4,5,4,5] +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm29 = zmm29[0,1,0,1,4,5,4,5] +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm3, %zmm29 {%k2} +; AVX512BW-FCP-NEXT: vmovdqa64 32(%r9), %xmm30 +; AVX512BW-FCP-NEXT: vmovdqa 32(%r8), %xmm3 +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm10 = [128,4,u,u,u,128,7,128,5,u,u,u,128,8,128,6] +; AVX512BW-FCP-NEXT: vpshufb %xmm10, %xmm30, %xmm0 +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm7 = [4,128,u,u,u,7,128,5,128,u,u,u,8,128,6,128] +; AVX512BW-FCP-NEXT: vpshufb %xmm7, %xmm3, %xmm18 +; AVX512BW-FCP-NEXT: vporq %xmm0, %xmm18, %xmm0 +; AVX512BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm18 = xmm3[8],xmm30[8],xmm3[9],xmm30[9],xmm3[10],xmm30[10],xmm3[11],xmm30[11],xmm3[12],xmm30[12],xmm3[13],xmm30[13],xmm3[14],xmm30[14],xmm3[15],xmm30[15] +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} xmm18 = xmm18[u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] +; AVX512BW-FCP-NEXT: vinserti32x4 $2, %xmm18, %zmm0, %zmm0 +; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm18 = [2,2,2,4,2,2,2,4,3,3,3,3,2,2,2,4,52,53,52,53,53,54,53,54,52,53,52,53,53,54,53,54] +; AVX512BW-FCP-NEXT: vpermi2w %zmm31, %zmm6, %zmm18 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm0 = zmm0[0,1,0,1,4,5,4,5] ; AVX512BW-FCP-NEXT: movabsq $290499906672591364, %rax # imm = 0x408102040810204 -; AVX512BW-FCP-NEXT: kmovq %rax, %k2 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm4, %zmm3 {%k2} +; AVX512BW-FCP-NEXT: kmovq %rax, %k3 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm18, %zmm0 {%k3} ; AVX512BW-FCP-NEXT: movabsq $-8714997200177740921, %rax # imm = 0x870E1C3870E1C387 -; AVX512BW-FCP-NEXT: kmovq %rax, %k2 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm3, %zmm23 {%k2} -; AVX512BW-FCP-NEXT: vpshufb %xmm11, %xmm15, %xmm3 -; AVX512BW-FCP-NEXT: vpshufb %xmm6, %xmm14, %xmm4 -; AVX512BW-FCP-NEXT: vpor %xmm3, %xmm4, %xmm3 -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm4 = xmm14[0],xmm15[0],xmm14[1],xmm15[1],xmm14[2],xmm15[2],xmm14[3],xmm15[3],xmm14[4],xmm15[4],xmm14[5],xmm15[5],xmm14[6],xmm15[6],xmm14[7],xmm15[7] -; AVX512BW-FCP-NEXT: vpshufb %xmm18, %xmm4, %xmm4 -; AVX512BW-FCP-NEXT: vinserti32x4 $2, %xmm3, %zmm4, %zmm3 -; AVX512BW-FCP-NEXT: vpshufb %xmm2, %xmm17, %xmm2 -; AVX512BW-FCP-NEXT: vpshufb %xmm0, %xmm16, %xmm0 -; AVX512BW-FCP-NEXT: vpor %xmm2, %xmm0, %xmm0 -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm16[0],xmm17[0],xmm16[1],xmm17[1],xmm16[2],xmm17[2],xmm16[3],xmm17[3],xmm16[4],xmm17[4],xmm16[5],xmm17[5],xmm16[6],xmm17[6],xmm16[7],xmm17[7] -; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} xmm2 = xmm2[0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] -; AVX512BW-FCP-NEXT: vinserti32x4 $2, %xmm0, %zmm2, %zmm0 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm2 = zmm3[0,1,0,1,4,5,4,5] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm0 = zmm0[0,1,0,1,4,5,4,5] +; AVX512BW-FCP-NEXT: kmovq %rax, %k3 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm0, %zmm29 {%k3} +; AVX512BW-FCP-NEXT: vpshufb %xmm13, %xmm19, %xmm0 +; AVX512BW-FCP-NEXT: vpshufb %xmm12, %xmm17, %xmm6 +; AVX512BW-FCP-NEXT: vpor %xmm0, %xmm6, %xmm0 +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm6 = xmm17[0],xmm19[0],xmm17[1],xmm19[1],xmm17[2],xmm19[2],xmm17[3],xmm19[3],xmm17[4],xmm19[4],xmm17[5],xmm19[5],xmm17[6],xmm19[6],xmm17[7],xmm19[7] +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm12 = [4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] +; AVX512BW-FCP-NEXT: vpshufb %xmm12, %xmm6, %xmm6 +; AVX512BW-FCP-NEXT: vinserti32x4 $2, %xmm0, %zmm6, %zmm0 +; AVX512BW-FCP-NEXT: vpshufb %xmm11, %xmm22, %xmm6 +; AVX512BW-FCP-NEXT: vpshufb %xmm8, %xmm21, %xmm8 +; AVX512BW-FCP-NEXT: vpor %xmm6, %xmm8, %xmm6 +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm8 = xmm21[0],xmm22[0],xmm21[1],xmm22[1],xmm21[2],xmm22[2],xmm21[3],xmm22[3],xmm21[4],xmm22[4],xmm21[5],xmm22[5],xmm21[6],xmm22[6],xmm21[7],xmm22[7] +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm11 = [0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] +; AVX512BW-FCP-NEXT: vpshufb %xmm11, %xmm8, %xmm8 +; AVX512BW-FCP-NEXT: vinserti32x4 $2, %xmm6, %zmm8, %zmm6 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm8 = zmm0[0,1,0,1,4,5,4,5] +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm0 = zmm6[0,1,0,1,4,5,4,5] ; AVX512BW-FCP-NEXT: movabsq $871499720017774092, %rax # imm = 0xC183060C183060C -; AVX512BW-FCP-NEXT: kmovq %rax, %k2 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm2, %zmm0 {%k2} -; AVX512BW-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm3 # 16-byte Reload -; AVX512BW-FCP-NEXT: vpshufb %xmm1, %xmm3, %xmm1 -; AVX512BW-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm4 # 16-byte Reload -; AVX512BW-FCP-NEXT: vpshufb %xmm7, %xmm4, %xmm2 -; AVX512BW-FCP-NEXT: vpor %xmm1, %xmm2, %xmm1 -; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm4[0],xmm3[0],xmm4[1],xmm3[1],xmm4[2],xmm3[2],xmm4[3],xmm3[3],xmm4[4],xmm3[4],xmm4[5],xmm3[5],xmm4[6],xmm3[6],xmm4[7],xmm3[7] -; AVX512BW-FCP-NEXT: vpshufb %xmm19, %xmm2, %xmm2 -; AVX512BW-FCP-NEXT: vinserti32x4 $2, %xmm1, %zmm2, %zmm1 -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm1 = zmm1[0,1,0,1,4,5,4,5] -; AVX512BW-FCP-NEXT: vinserti64x4 $1, (%rsp), %zmm10, %zmm2 # 32-byte Folded Reload -; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm3 = [1,1,0,0,1,1,0,0,4,5,1,1,1,1,0,0,18,18,18,20,18,18,18,20,19,19,19,19,18,18,18,20] -; AVX512BW-FCP-NEXT: vpermw %zmm2, %zmm3, %zmm3 +; AVX512BW-FCP-NEXT: kmovq %rax, %k3 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm8, %zmm0 {%k3} +; AVX512BW-FCP-NEXT: vpshufb %xmm10, %xmm16, %xmm6 +; AVX512BW-FCP-NEXT: vpshufb %xmm7, %xmm15, %xmm7 +; AVX512BW-FCP-NEXT: vpor %xmm6, %xmm7, %xmm6 +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm7 = xmm15[0],xmm16[0],xmm15[1],xmm16[1],xmm15[2],xmm16[2],xmm15[3],xmm16[3],xmm15[4],xmm16[4],xmm15[5],xmm16[5],xmm15[6],xmm16[6],xmm15[7],xmm16[7] +; AVX512BW-FCP-NEXT: vmovdqa {{.*#+}} xmm10 = [u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] +; AVX512BW-FCP-NEXT: vpshufb %xmm10, %xmm7, %xmm7 +; AVX512BW-FCP-NEXT: vinserti32x4 $2, %xmm6, %zmm7, %zmm6 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm6 = zmm6[0,1,0,1,4,5,4,5] +; AVX512BW-FCP-NEXT: vinserti64x4 $1, (%rsp), %zmm31, %zmm8 # 32-byte Folded Reload +; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm7 = [1,1,0,0,1,1,0,0,4,5,1,1,1,1,0,0,18,18,18,20,18,18,18,20,19,19,19,19,18,18,18,20] +; AVX512BW-FCP-NEXT: vpermw %zmm8, %zmm7, %zmm7 ; AVX512BW-FCP-NEXT: movabsq $4647998506761461824, %rax # imm = 0x4081020408102040 -; AVX512BW-FCP-NEXT: kmovq %rax, %k2 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm3, %zmm1 {%k2} +; AVX512BW-FCP-NEXT: kmovq %rax, %k3 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm7, %zmm6 {%k3} ; AVX512BW-FCP-NEXT: movabsq $8133997386832558192, %rax # imm = 0x70E1C3870E1C3870 -; AVX512BW-FCP-NEXT: kmovq %rax, %k2 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm0 {%k2} -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm24, %zmm28, %zmm1 +; AVX512BW-FCP-NEXT: kmovq %rax, %k3 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm6, %zmm0 {%k3} +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[1],xmm1[1],xmm2[2],xmm1[2],xmm2[3],xmm1[3],xmm2[4],xmm1[4],xmm2[5],xmm1[5],xmm2[6],xmm1[6],xmm2[7],xmm1[7] +; AVX512BW-FCP-NEXT: vpshufb %xmm11, %xmm1, %xmm1 +; AVX512BW-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm13 # 32-byte Reload +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm13[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,30],zero,ymm13[28],zero,ymm13[30,31,30,31],zero,ymm13[29],zero,ymm13[31,28,29] +; AVX512BW-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm15 # 32-byte Reload +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm6 = ymm15[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm15[30],zero,ymm15[28],zero,zero,zero,zero,ymm15[31],zero,ymm15[29],zero,zero,zero +; AVX512BW-FCP-NEXT: vpor %ymm2, %ymm6, %ymm2 +; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm2[2,3,2,3],zmm1[0,1,0,1] +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm5[0],xmm4[0],xmm5[1],xmm4[1],xmm5[2],xmm4[2],xmm5[3],xmm4[3],xmm5[4],xmm4[4],xmm5[5],xmm4[5],xmm5[6],xmm4[6],xmm5[7],xmm4[7] +; AVX512BW-FCP-NEXT: vpshufb %xmm12, %xmm2, %xmm2 +; AVX512BW-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm11 # 32-byte Reload +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,zero,zero,ymm11[30],zero,ymm11[28],zero,zero,zero,zero,ymm11[31],zero,ymm11[29],zero +; AVX512BW-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm7 # 32-byte Reload +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm7[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm7[30],zero,ymm7[28],zero,zero,zero,zero,ymm7[31],zero,ymm7[29],zero,zero +; AVX512BW-FCP-NEXT: vpor %ymm4, %ymm5, %ymm4 +; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm4[2,3,2,3],zmm2[0,1,0,1] +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm2 {%k1} +; AVX512BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm3[0],xmm30[0],xmm3[1],xmm30[1],xmm3[2],xmm30[2],xmm3[3],xmm30[3],xmm3[4],xmm30[4],xmm3[5],xmm30[5],xmm3[6],xmm30[6],xmm3[7],xmm30[7] +; AVX512BW-FCP-NEXT: vpshufb %xmm10, %xmm1, %xmm1 +; AVX512BW-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm5 # 32-byte Reload +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm5[27],zero,zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero +; AVX512BW-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm6 # 32-byte Reload +; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[27],zero,zero,zero,zero,ymm6[30],zero,ymm6[28],zero,zero,zero,zero,ymm6[31],zero,ymm6[29] +; AVX512BW-FCP-NEXT: vpor %ymm3, %ymm4, %ymm3 +; AVX512BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm3[2,3,2,3],zmm1[0,1,0,1] +; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm3 = [14,13,14,15,15,14,14,15,14,13,14,15,15,14,14,15,17,17,16,16,17,17,16,16,20,21,17,17,17,17,16,16] +; AVX512BW-FCP-NEXT: vpermw %zmm31, %zmm3, %zmm3 +; AVX512BW-FCP-NEXT: movabsq $580999813345182728, %rax # imm = 0x810204081020408 +; AVX512BW-FCP-NEXT: kmovq %rax, %k1 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm3, %zmm1 {%k1} +; AVX512BW-FCP-NEXT: movabsq $1016749673354069774, %rax # imm = 0xE1C3870E1C3870E +; AVX512BW-FCP-NEXT: kmovq %rax, %k1 +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm2 {%k1} +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm15, %zmm26, %zmm1 ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm1 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zmm1[18,19,20,21],zero,zmm1[19],zero,zmm1[21,20,21,22],zero,zmm1[20],zero,zmm1[22,23,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,57],zero,zmm1[55],zero,zero,zero,zero,zmm1[58],zero,zmm1[56],zero,zero,zero,zero,zmm1[59],zero -; AVX512BW-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm29, %zmm3 # 32-byte Folded Reload +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm13, %zmm27, %zmm3 ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm3 = zmm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm3[21],zero,zmm3[19],zero,zero,zero,zero,zmm3[22],zero,zmm3[20],zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zmm3[55],zero,zero,zero,zero,zmm3[58],zero,zmm3[56],zero,zero,zero,zero,zmm3[59],zero,zmm3[57] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm3 = zmm3[2,3,2,3,6,7,6,7] ; AVX512BW-FCP-NEXT: vporq %zmm1, %zmm3, %zmm1 -; AVX512BW-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm26, %zmm3 # 32-byte Folded Reload +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm24, %zmm3 ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm3 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zmm3[18],zero,zmm3[18,19,20,21],zero,zmm3[19],zero,zmm3[25,26,27,22],zero,zmm3[20],zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zmm3[56,57],zero,zmm3[55],zero,zmm3[53,54,55,58],zero,zmm3[56],zero,zmm3[60,61,58,59] -; AVX512BW-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm25, %zmm4 # 32-byte Folded Reload +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm23, %zmm4 ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm4 = zmm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm4[18],zero,zero,zero,zero,zmm4[21],zero,zmm4[19],zero,zero,zero,zero,zmm4[22],zero,zmm4[20,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zmm4[57],zero,zmm4[55],zero,zero,zero,zero,zmm4[58],zero,zmm4[56],zero,zero,zero,zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm3 = zmm3[2,3,2,3,6,7,6,7] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm4 = zmm4[2,3,2,3,6,7,6,7] ; AVX512BW-FCP-NEXT: vporq %zmm3, %zmm4, %zmm3 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm3 {%k1} -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm20, %zmm30, %zmm1 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm3 = zmm3[2,3,2,3,6,7,6,7] +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm3 {%k2} +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm6, %zmm28, %zmm1 ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm1 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zmm1[20],zero,zmm1[18],zero,zmm1[20,21,20,21],zero,zmm1[19],zero,zmm1[19,20,21,22],zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zmm1[56,57,56,57],zero,zmm1[55],zero,zmm1[55,56,57,58],zero,zmm1[56],zero,zmm1[62,63] -; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm21, %zmm27, %zmm4 +; AVX512BW-FCP-NEXT: vinserti64x4 $1, %ymm5, %zmm25, %zmm4 ; AVX512BW-FCP-NEXT: vpshufb {{.*#+}} zmm4 = zmm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm4[20],zero,zmm4[18],zero,zero,zero,zero,zmm4[21],zero,zmm4[19],zero,zero,zero,zero,zmm4[22,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm4[57],zero,zmm4[55],zero,zero,zero,zero,zmm4[58],zero,zmm4[56],zero,zero -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] -; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm4 = zmm4[2,3,2,3,6,7,6,7] ; AVX512BW-FCP-NEXT: vporq %zmm1, %zmm4, %zmm1 ; AVX512BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm4 = [10,9,9,10,10,9,9,10,9,10,14,15,10,9,9,10,27,29,28,27,28,29,29,28,27,29,28,27,28,29,29,28] -; AVX512BW-FCP-NEXT: vpermw %zmm2, %zmm4, %zmm2 +; AVX512BW-FCP-NEXT: vpermw %zmm8, %zmm4, %zmm4 +; AVX512BW-FCP-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] ; AVX512BW-FCP-NEXT: movabsq $1161999626690365456, %rax # imm = 0x1020408102040810 ; AVX512BW-FCP-NEXT: kmovq %rax, %k1 -; AVX512BW-FCP-NEXT: vmovdqu8 %zmm2, %zmm1 {%k1} +; AVX512BW-FCP-NEXT: vmovdqu8 %zmm4, %zmm1 {%k1} ; AVX512BW-FCP-NEXT: movabsq $2033499346708139548, %rax # imm = 0x1C3870E1C3870E1C ; AVX512BW-FCP-NEXT: kmovq %rax, %k1 ; AVX512BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm3 {%k1} ; AVX512BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512BW-FCP-NEXT: vmovdqa64 %zmm3, 128(%rax) -; AVX512BW-FCP-NEXT: vmovdqa64 %zmm12, 320(%rax) +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm9, 320(%rax) +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm2, 192(%rax) ; AVX512BW-FCP-NEXT: vmovdqa64 %zmm0, (%rax) -; AVX512BW-FCP-NEXT: vmovdqa64 %zmm23, 256(%rax) -; AVX512BW-FCP-NEXT: vmovdqa64 %zmm9, 192(%rax) -; AVX512BW-FCP-NEXT: vmovdqa64 %zmm13, 64(%rax) -; AVX512BW-FCP-NEXT: vmovdqa64 %zmm22, 384(%rax) -; AVX512BW-FCP-NEXT: addq $40, %rsp +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm29, 256(%rax) +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm14, 64(%rax) +; AVX512BW-FCP-NEXT: vmovdqa64 %zmm20, 384(%rax) +; AVX512BW-FCP-NEXT: addq $104, %rsp ; AVX512BW-FCP-NEXT: vzeroupper ; AVX512BW-FCP-NEXT: retq ; @@ -11069,8 +10826,8 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW: # %bb.0: ; AVX512DQ-BW-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512DQ-BW-NEXT: vmovdqa (%rax), %ymm13 -; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} ymm27 = [12,13,2,3,12,13,0,1,14,15,2,3,0,1,14,15,28,29,18,19,28,29,16,17,30,31,18,19,16,17,30,31] -; AVX512DQ-BW-NEXT: vpshufb %ymm27, %ymm13, %ymm0 +; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} ymm26 = [12,13,2,3,12,13,0,1,14,15,2,3,0,1,14,15,28,29,18,19,28,29,16,17,30,31,18,19,16,17,30,31] +; AVX512DQ-BW-NEXT: vpshufb %ymm26, %ymm13, %ymm0 ; AVX512DQ-BW-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [4,5,4,5,5,6,5,6,4,5,4,5,5,6,5,6] ; AVX512DQ-BW-NEXT: # ymm1 = mem[0,1,0,1] ; AVX512DQ-BW-NEXT: vpermw %ymm13, %ymm1, %ymm1 @@ -11079,12 +10836,13 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} ymm17 = [13,128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128] ; AVX512DQ-BW-NEXT: vpshufb %ymm17, %ymm9, %ymm1 ; AVX512DQ-BW-NEXT: vmovdqa (%r8), %ymm10 -; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} ymm22 = [128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128] -; AVX512DQ-BW-NEXT: vpshufb %ymm22, %ymm10, %ymm2 +; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} ymm21 = [128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128] +; AVX512DQ-BW-NEXT: vpshufb %ymm21, %ymm10, %ymm2 ; AVX512DQ-BW-NEXT: vpor %ymm1, %ymm2, %ymm2 -; AVX512DQ-BW-NEXT: vmovdqa (%r9), %xmm12 -; AVX512DQ-BW-NEXT: vmovdqa (%r8), %xmm3 -; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm3[8],xmm12[8],xmm3[9],xmm12[9],xmm3[10],xmm12[10],xmm3[11],xmm12[11],xmm3[12],xmm12[12],xmm3[13],xmm12[13],xmm3[14],xmm12[14],xmm3[15],xmm12[15] +; AVX512DQ-BW-NEXT: vmovdqa (%r9), %xmm1 +; AVX512DQ-BW-NEXT: vmovdqa %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill +; AVX512DQ-BW-NEXT: vmovdqa (%r8), %xmm12 +; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm12[8],xmm1[8],xmm12[9],xmm1[9],xmm12[10],xmm1[10],xmm12[11],xmm1[11],xmm12[12],xmm1[12],xmm12[13],xmm1[13],xmm12[14],xmm1[14],xmm12[15],xmm1[15] ; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} xmm4 = xmm4[u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] ; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm4 = ymm4[0,1,0,1] ; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm2, %zmm4, %zmm8 @@ -11094,270 +10852,257 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-NEXT: vmovdqa (%rdx), %ymm14 ; AVX512DQ-BW-NEXT: vmovdqa {{.*#+}} ymm0 = [0,1,0,1,14,128,14,15,0,1,14,15,128,13,14,15,16,17,16,128,30,31,30,31,16,17,128,31,28,29,30,31] ; AVX512DQ-BW-NEXT: vpshufb %ymm0, %ymm14, %ymm2 -; AVX512DQ-BW-NEXT: vmovdqa64 (%rcx), %ymm16 -; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} ymm23 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] -; AVX512DQ-BW-NEXT: vpshufb %ymm23, %ymm16, %ymm4 +; AVX512DQ-BW-NEXT: vmovdqa (%rcx), %ymm15 +; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} ymm20 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] +; AVX512DQ-BW-NEXT: vpshufb %ymm20, %ymm15, %ymm4 ; AVX512DQ-BW-NEXT: vpor %ymm2, %ymm4, %ymm2 ; AVX512DQ-BW-NEXT: vmovdqa (%rdx), %xmm4 ; AVX512DQ-BW-NEXT: vmovdqa (%rcx), %xmm5 ; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm5[8],xmm4[8],xmm5[9],xmm4[9],xmm5[10],xmm4[10],xmm5[11],xmm4[11],xmm5[12],xmm4[12],xmm5[13],xmm4[13],xmm5[14],xmm4[14],xmm5[15],xmm4[15] ; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} xmm6 = xmm6[6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] ; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm6 = ymm6[0,1,0,1] -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm2, %zmm6, %zmm20 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm2, %zmm6, %zmm22 ; AVX512DQ-BW-NEXT: vmovdqa64 (%rdi), %ymm18 ; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} ymm24 = [0,1,14,128,12,13,0,1,14,15,128,3,12,13,2,3,16,128,30,31,28,29,16,17,128,31,18,19,28,29,18,128] ; AVX512DQ-BW-NEXT: vpshufb %ymm24, %ymm18, %ymm2 ; AVX512DQ-BW-NEXT: vmovdqa64 (%rsi), %ymm19 -; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} ymm26 = [128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128,128,18] -; AVX512DQ-BW-NEXT: vpshufb %ymm26, %ymm19, %ymm6 +; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} ymm25 = [128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128,128,18] +; AVX512DQ-BW-NEXT: vpshufb %ymm25, %ymm19, %ymm6 ; AVX512DQ-BW-NEXT: vpor %ymm2, %ymm6, %ymm2 ; AVX512DQ-BW-NEXT: vmovdqa (%rdi), %xmm6 ; AVX512DQ-BW-NEXT: vmovdqa (%rsi), %xmm7 -; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm21 = xmm7[8],xmm6[8],xmm7[9],xmm6[9],xmm7[10],xmm6[10],xmm7[11],xmm6[11],xmm7[12],xmm6[12],xmm7[13],xmm6[13],xmm7[14],xmm6[14],xmm7[15],xmm6[15] -; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} xmm21 = xmm21[2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm21 = ymm21[0,1,0,1] -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm2, %zmm21, %zmm2 +; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm23 = xmm7[8],xmm6[8],xmm7[9],xmm6[9],xmm7[10],xmm6[10],xmm7[11],xmm6[11],xmm7[12],xmm6[12],xmm7[13],xmm6[13],xmm7[14],xmm6[14],xmm7[15],xmm6[15] +; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} xmm23 = xmm23[2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm23 = ymm23[0,1,0,1] +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm2, %zmm23, %zmm3 ; AVX512DQ-BW-NEXT: movabsq $435749860008887046, %r10 # imm = 0x60C183060C18306 ; AVX512DQ-BW-NEXT: kmovq %r10, %k1 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm20, %zmm2 {%k1} +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm22, %zmm3 {%k1} ; AVX512DQ-BW-NEXT: movabsq $4066998693416279096, %r10 # imm = 0x3870E1C3870E1C38 ; AVX512DQ-BW-NEXT: kmovq %r10, %k1 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm8, %zmm2 {%k1} -; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} zmm20 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,24,25,128,23,128,21,22,23,26,128,24,128,28,29,26,27] +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm8, %zmm3 {%k1} ; AVX512DQ-BW-NEXT: vmovdqa64 32(%rdx), %ymm29 +; AVX512DQ-BW-NEXT: vpshufb %ymm0, %ymm29, %ymm0 +; AVX512DQ-BW-NEXT: vmovdqa64 32(%rcx), %ymm30 +; AVX512DQ-BW-NEXT: vpshufb %ymm20, %ymm30, %ymm8 +; AVX512DQ-BW-NEXT: vpor %ymm0, %ymm8, %ymm0 +; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} zmm20 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,24,25,128,23,128,21,22,23,26,128,24,128,28,29,26,27] ; AVX512DQ-BW-NEXT: vpshufb %ymm20, %ymm29, %ymm8 +; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} zmm22 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128] +; AVX512DQ-BW-NEXT: vpshufb %ymm22, %ymm30, %ymm23 +; AVX512DQ-BW-NEXT: vporq %ymm8, %ymm23, %ymm8 ; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] -; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} zmm21 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128] -; AVX512DQ-BW-NEXT: vmovdqa64 32(%rcx), %ymm30 -; AVX512DQ-BW-NEXT: vpshufb %ymm21, %ymm30, %ymm25 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm25 = ymm25[2,3,2,3] -; AVX512DQ-BW-NEXT: vporq %ymm8, %ymm25, %ymm8 -; AVX512DQ-BW-NEXT: vpshufb %ymm0, %ymm29, %ymm0 -; AVX512DQ-BW-NEXT: vpshufb %ymm23, %ymm30, %ymm23 -; AVX512DQ-BW-NEXT: vporq %ymm0, %ymm23, %ymm0 ; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm8, %zmm0, %zmm0 ; AVX512DQ-BW-NEXT: vmovdqa64 32(%rsi), %ymm28 -; AVX512DQ-BW-NEXT: vmovdqa 32(%rdi), %ymm15 -; AVX512DQ-BW-NEXT: vpshuflw {{.*#+}} ymm8 = ymm15[1,2,2,3,4,5,6,7,9,10,10,11,12,13,14,15] +; AVX512DQ-BW-NEXT: vmovdqa64 32(%rdi), %ymm16 +; AVX512DQ-BW-NEXT: vpshuflw {{.*#+}} ymm8 = ymm16[1,2,2,3,4,5,6,7,9,10,10,11,12,13,14,15] ; AVX512DQ-BW-NEXT: vpshufd {{.*#+}} ymm8 = ymm8[0,0,1,1,4,4,5,5] -; AVX512DQ-BW-NEXT: vpbroadcastd {{.*#+}} ymm25 = [5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6] +; AVX512DQ-BW-NEXT: vpbroadcastd {{.*#+}} ymm23 = [5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6,5,4,3,6] ; AVX512DQ-BW-NEXT: movl $676341840, %r10d # imm = 0x28502850 ; AVX512DQ-BW-NEXT: kmovd %r10d, %k1 -; AVX512DQ-BW-NEXT: vpshufb %ymm25, %ymm28, %ymm8 {%k1} +; AVX512DQ-BW-NEXT: vpshufb %ymm23, %ymm28, %ymm8 {%k1} ; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm8 = ymm8[2,3,2,3] -; AVX512DQ-BW-NEXT: vpshufb %ymm24, %ymm15, %ymm23 -; AVX512DQ-BW-NEXT: vpshufb %ymm26, %ymm28, %ymm24 -; AVX512DQ-BW-NEXT: vporq %ymm23, %ymm24, %ymm23 -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm8, %zmm23, %zmm8 +; AVX512DQ-BW-NEXT: vpshufb %ymm24, %ymm16, %ymm24 +; AVX512DQ-BW-NEXT: vpshufb %ymm25, %ymm28, %ymm25 +; AVX512DQ-BW-NEXT: vporq %ymm24, %ymm25, %ymm24 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm8, %zmm24, %zmm8 ; AVX512DQ-BW-NEXT: movabsq $3485998880071096368, %r10 # imm = 0x3060C183060C1830 ; AVX512DQ-BW-NEXT: kmovq %r10, %k2 ; AVX512DQ-BW-NEXT: vmovdqu8 %zmm0, %zmm8 {%k2} -; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} zmm23 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,24,25,24,25,128,23,128,23,24,25,26,128,24,128,30,31] -; AVX512DQ-BW-NEXT: vmovdqa64 32(%r8), %ymm31 -; AVX512DQ-BW-NEXT: vpshufb %ymm23, %ymm31, %ymm0 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm26 = ymm0[2,3,2,3] -; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} zmm24 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,128,128,25,128,23,128,128,128,128,26,128,24,128,128] -; AVX512DQ-BW-NEXT: vmovdqa 32(%r9), %ymm0 -; AVX512DQ-BW-NEXT: vpshufb %ymm24, %ymm0, %ymm11 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] -; AVX512DQ-BW-NEXT: vporq %ymm26, %ymm11, %ymm11 -; AVX512DQ-BW-NEXT: vpshufb %ymm17, %ymm0, %ymm17 -; AVX512DQ-BW-NEXT: vpshufb %ymm22, %ymm31, %ymm22 -; AVX512DQ-BW-NEXT: vporq %ymm17, %ymm22, %ymm17 -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm11, %zmm17, %zmm11 +; AVX512DQ-BW-NEXT: vmovdqa64 32(%r9), %ymm31 +; AVX512DQ-BW-NEXT: vpshufb %ymm17, %ymm31, %ymm17 +; AVX512DQ-BW-NEXT: vmovdqa 32(%r8), %ymm1 +; AVX512DQ-BW-NEXT: vpshufb %ymm21, %ymm1, %ymm21 +; AVX512DQ-BW-NEXT: vporq %ymm17, %ymm21, %ymm17 +; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} zmm24 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,24,25,24,25,128,23,128,23,24,25,26,128,24,128,30,31] +; AVX512DQ-BW-NEXT: vpshufb %ymm24, %ymm1, %ymm21 +; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} zmm25 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,128,128,25,128,23,128,128,128,128,26,128,24,128,128] +; AVX512DQ-BW-NEXT: vpshufb %ymm25, %ymm31, %ymm27 +; AVX512DQ-BW-NEXT: vporq %ymm21, %ymm27, %ymm21 +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm21 = ymm21[2,3,2,3] +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm21, %zmm17, %zmm21 ; AVX512DQ-BW-NEXT: vmovdqa64 32(%rax), %ymm17 -; AVX512DQ-BW-NEXT: vpshufb %ymm27, %ymm17, %ymm22 +; AVX512DQ-BW-NEXT: vpshufb %ymm26, %ymm17, %ymm27 ; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} zmm26 = [10,9,9,10,10,9,9,10,9,10,14,15,10,9,9,10,27,29,28,27,28,29,29,28,27,29,28,27,28,29,29,28] -; AVX512DQ-BW-NEXT: vpermw %ymm17, %ymm26, %ymm27 -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm27, %zmm22, %zmm22 +; AVX512DQ-BW-NEXT: vpermw %ymm17, %ymm26, %ymm11 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm11, %zmm27, %zmm11 ; AVX512DQ-BW-NEXT: movabsq $145249953336295682, %r10 # imm = 0x204081020408102 ; AVX512DQ-BW-NEXT: kmovq %r10, %k3 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm22, %zmm11 {%k3} +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm11, %zmm21 {%k3} ; AVX512DQ-BW-NEXT: movabsq $-4357498600088870461, %r10 # imm = 0xC3870E1C3870E1C3 ; AVX512DQ-BW-NEXT: kmovq %r10, %k3 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm11, %zmm8 {%k3} -; AVX512DQ-BW-NEXT: vpshufhw {{.*#+}} ymm11 = ymm15[0,1,2,3,6,7,7,6,8,9,10,11,14,15,15,14] +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm21, %zmm8 {%k3} +; AVX512DQ-BW-NEXT: vpshufhw {{.*#+}} ymm11 = ymm16[0,1,2,3,6,7,7,6,8,9,10,11,14,15,15,14] ; AVX512DQ-BW-NEXT: vpshufd {{.*#+}} ymm11 = ymm11[2,2,3,3,6,6,7,7] ; AVX512DQ-BW-NEXT: movl $338170920, %r10d # imm = 0x14281428 ; AVX512DQ-BW-NEXT: kmovd %r10d, %k4 ; AVX512DQ-BW-NEXT: vpbroadcastd {{.*#+}} ymm27 = [13,12,15,14,13,12,15,14,13,12,15,14,13,12,15,14,13,12,15,14,13,12,15,14,13,12,15,14,13,12,15,14] ; AVX512DQ-BW-NEXT: vpshufb %ymm27, %ymm28, %ymm11 {%k4} -; AVX512DQ-BW-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [25,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128] -; AVX512DQ-BW-NEXT: # ymm1 = mem[0,1,0,1] -; AVX512DQ-BW-NEXT: vpshufb %ymm1, %ymm28, %ymm22 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm22 = ymm22[2,3,2,3] +; AVX512DQ-BW-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [25,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128] +; AVX512DQ-BW-NEXT: # ymm2 = mem[0,1,0,1] +; AVX512DQ-BW-NEXT: vpshufb %ymm2, %ymm28, %ymm21 ; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} ymm28 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128,25] -; AVX512DQ-BW-NEXT: vpshufb %ymm28, %ymm15, %ymm15 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm15 = ymm15[2,3,2,3] -; AVX512DQ-BW-NEXT: vporq %ymm22, %ymm15, %ymm15 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm11, %zmm15, %zmm15 -; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm11 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm29[24,25],zero,ymm29[23],zero,ymm29[21,22,23,26],zero,ymm29[24],zero,ymm29[28,29,26,27] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm11 = ymm11[2,3,2,3] -; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm22 = ymm30[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm30[25],zero,ymm30[23],zero,zero,zero,zero,ymm30[26],zero,ymm30[24],zero,zero,zero,zero -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm22 = ymm22[2,3,2,3] -; AVX512DQ-BW-NEXT: vporq %ymm11, %ymm22, %ymm22 +; AVX512DQ-BW-NEXT: vpshufb %ymm28, %ymm16, %ymm16 +; AVX512DQ-BW-NEXT: vporq %ymm21, %ymm16, %ymm16 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm11, %zmm16, %zmm16 +; AVX512DQ-BW-NEXT: vpshufhw {{.*#+}} ymm11 = ymm29[0,1,2,3,7,6,6,7,8,9,10,11,15,14,14,15] +; AVX512DQ-BW-NEXT: vpshufd {{.*#+}} ymm21 = ymm11[0,2,3,3,4,6,7,7] ; AVX512DQ-BW-NEXT: vpbroadcastq {{.*#+}} ymm11 = [11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12,11,0,0,0,15,14,13,12] -; AVX512DQ-BW-NEXT: vpshufb %ymm11, %ymm30, %ymm30 -; AVX512DQ-BW-NEXT: vpshufhw {{.*#+}} ymm29 = ymm29[0,1,2,3,7,6,6,7,8,9,10,11,15,14,14,15] -; AVX512DQ-BW-NEXT: vpshufd {{.*#+}} ymm29 = ymm29[0,2,3,3,4,6,7,7] -; AVX512DQ-BW-NEXT: vmovdqu8 %ymm29, %ymm30 {%k1} -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm29 = ymm30[2,3,2,3] -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm29, %zmm22, %zmm22 +; AVX512DQ-BW-NEXT: vpshufb %ymm11, %ymm30, %ymm0 +; AVX512DQ-BW-NEXT: vmovdqu8 %ymm21, %ymm0 {%k1} +; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm21 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm29[24,25],zero,ymm29[23],zero,ymm29[21,22,23,26],zero,ymm29[24],zero,ymm29[28,29,26,27] +; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm29 = ymm30[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,ymm30[25],zero,ymm30[23],zero,zero,zero,zero,ymm30[26],zero,ymm30[24],zero,zero,zero,zero +; AVX512DQ-BW-NEXT: vporq %ymm21, %ymm29, %ymm21 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm0, %zmm21, %zmm0 +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm16 = zmm16[2,3,2,3,6,7,6,7] +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm0 = zmm0[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-NEXT: movabsq $1742999440035548184, %r10 # imm = 0x183060C183060C18 ; AVX512DQ-BW-NEXT: kmovq %r10, %k3 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm22, %zmm15 {%k3} -; AVX512DQ-BW-NEXT: vmovdqa64 (%r9), %zmm29 -; AVX512DQ-BW-NEXT: vshufi64x2 {{.*#+}} zmm22 = zmm31[0,1,2,3],zmm29[4,5,6,7] -; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} zmm22 = zmm22[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,zmm22[23],zero,zmm22[23,24,25,26],zero,zmm22[24],zero,zmm22[30,31,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,61],zero,zmm22[59],zero,zero,zero,zero,zmm22[62],zero,zmm22[60],zero,zero,zero,zero,zmm22[63],zero -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm22 = zmm22[2,3,2,3,6,7,6,7] -; AVX512DQ-BW-NEXT: vmovdqa64 (%r8), %zmm30 -; AVX512DQ-BW-NEXT: vshufi64x2 {{.*#+}} zmm0 = zmm0[0,1,2,3],zmm30[4,5,6,7] -; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} zmm0 = zmm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm0[25],zero,zmm0[23],zero,zero,zero,zero,zmm0[26],zero,zmm0[24],zero,zero,zmm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm0[59],zero,zero,zero,zero,zmm0[62],zero,zmm0[60],zero,zero,zero,zero,zmm0[63],zero,zmm0[61] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm0 = zmm0[2,3,2,3,6,7,6,7] -; AVX512DQ-BW-NEXT: vporq %zmm22, %zmm0, %zmm0 +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm0, %zmm16 {%k3} +; AVX512DQ-BW-NEXT: vmovdqa64 (%r9), %zmm0 +; AVX512DQ-BW-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm1[0,1,2,3],zmm0[4,5,6,7] +; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} zmm1 = zmm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,zmm1[23],zero,zmm1[23,24,25,26],zero,zmm1[24],zero,zmm1[30,31,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,61],zero,zmm1[59],zero,zero,zero,zero,zmm1[62],zero,zmm1[60],zero,zero,zero,zero,zmm1[63],zero +; AVX512DQ-BW-NEXT: vmovdqa64 (%r8), %zmm29 +; AVX512DQ-BW-NEXT: vshufi64x2 {{.*#+}} zmm21 = zmm31[0,1,2,3],zmm29[4,5,6,7] +; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} zmm21 = zmm21[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm21[25],zero,zmm21[23],zero,zero,zero,zero,zmm21[26],zero,zmm21[24],zero,zero,zmm21[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm21[59],zero,zero,zero,zero,zmm21[62],zero,zmm21[60],zero,zero,zero,zero,zmm21[63],zero,zmm21[61] +; AVX512DQ-BW-NEXT: vporq %zmm1, %zmm21, %zmm1 +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-NEXT: movabsq $6971997760142192736, %r10 # imm = 0x60C183060C183060 ; AVX512DQ-BW-NEXT: kmovq %r10, %k3 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm0, %zmm15 {%k3} -; AVX512DQ-BW-NEXT: vmovdqa64 (%rax), %zmm22 -; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} zmm0 = [11,13,12,11,12,13,13,12,11,13,12,11,12,13,13,12,62,61,62,63,63,62,62,63,62,61,62,63,63,62,62,63] -; AVX512DQ-BW-NEXT: vpermi2w %zmm22, %zmm17, %zmm0 +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm1, %zmm16 {%k3} +; AVX512DQ-BW-NEXT: vmovdqa64 (%rax), %zmm21 +; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} zmm1 = [11,13,12,11,12,13,13,12,11,13,12,11,12,13,13,12,62,61,62,63,63,62,62,63,62,61,62,63,63,62,62,63] +; AVX512DQ-BW-NEXT: vpermi2w %zmm21, %zmm17, %zmm1 ; AVX512DQ-BW-NEXT: movabsq $-9150747060186627967, %rax # imm = 0x8102040810204081 ; AVX512DQ-BW-NEXT: kmovq %rax, %k5 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm0, %zmm15 {%k5} -; AVX512DQ-BW-NEXT: vpshuflw {{.*#+}} ymm0 = ymm18[1,2,2,3,4,5,6,7,9,10,10,11,12,13,14,15] -; AVX512DQ-BW-NEXT: vpshufd {{.*#+}} ymm0 = ymm0[0,0,1,1,4,4,5,5] -; AVX512DQ-BW-NEXT: vpshufb %ymm25, %ymm19, %ymm0 {%k1} -; AVX512DQ-BW-NEXT: vpshufb %ymm1, %ymm19, %ymm1 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512DQ-BW-NEXT: vpshufb %ymm28, %ymm18, %ymm25 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm25 = ymm25[2,3,2,3] -; AVX512DQ-BW-NEXT: vporq %ymm1, %ymm25, %ymm1 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm1, %zmm0, %zmm0 -; AVX512DQ-BW-NEXT: vmovdqa64 (%rdx), %zmm1 -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm14, %zmm1, %zmm1 -; AVX512DQ-BW-NEXT: vpshufb %zmm20, %zmm1, %zmm1 +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm1, %zmm16 {%k5} +; AVX512DQ-BW-NEXT: vpshuflw {{.*#+}} ymm1 = ymm18[1,2,2,3,4,5,6,7,9,10,10,11,12,13,14,15] +; AVX512DQ-BW-NEXT: vpshufd {{.*#+}} ymm1 = ymm1[0,0,1,1,4,4,5,5] +; AVX512DQ-BW-NEXT: vpshufb %ymm23, %ymm19, %ymm1 {%k1} +; AVX512DQ-BW-NEXT: vpshufb %ymm2, %ymm19, %ymm2 +; AVX512DQ-BW-NEXT: vpshufb %ymm28, %ymm18, %ymm23 +; AVX512DQ-BW-NEXT: vporq %ymm2, %ymm23, %ymm2 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm2, %zmm1, %zmm1 +; AVX512DQ-BW-NEXT: vmovdqa64 (%rdx), %zmm2 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm14, %zmm2, %zmm2 +; AVX512DQ-BW-NEXT: vpshufb %zmm20, %zmm2, %zmm2 ; AVX512DQ-BW-NEXT: vmovdqa64 (%rcx), %zmm20 -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm16, %zmm20, %zmm20 -; AVX512DQ-BW-NEXT: vpshufb %zmm21, %zmm20, %zmm20 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm15, %zmm20, %zmm20 +; AVX512DQ-BW-NEXT: vpshufb %zmm22, %zmm20, %zmm20 +; AVX512DQ-BW-NEXT: vporq %zmm2, %zmm20, %zmm2 ; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm20 = zmm20[2,3,2,3,6,7,6,7] -; AVX512DQ-BW-NEXT: vporq %zmm1, %zmm20, %zmm20 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm0, %zmm20 {%k3} -; AVX512DQ-BW-NEXT: vmovdqa64 32(%r9), %xmm21 -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm10, %zmm30, %zmm0 -; AVX512DQ-BW-NEXT: vpshufb %zmm23, %zmm0, %zmm0 -; AVX512DQ-BW-NEXT: vmovdqa64 32(%r8), %xmm23 -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm9, %zmm29, %zmm1 +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm20 = zmm2[2,3,2,3,6,7,6,7] +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm1, %zmm20 {%k3} +; AVX512DQ-BW-NEXT: vmovdqa64 32(%r9), %xmm22 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm10, %zmm29, %zmm1 ; AVX512DQ-BW-NEXT: vpshufb %zmm24, %zmm1, %zmm1 -; AVX512DQ-BW-NEXT: vmovdqa64 32(%rdx), %xmm24 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm0 = zmm0[2,3,2,3,6,7,6,7] +; AVX512DQ-BW-NEXT: vmovdqa64 32(%r8), %xmm23 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm9, %zmm0, %zmm0 +; AVX512DQ-BW-NEXT: vpshufb %zmm25, %zmm0, %zmm2 +; AVX512DQ-BW-NEXT: vmovdqa 32(%rdx), %xmm0 +; AVX512DQ-BW-NEXT: vporq %zmm1, %zmm2, %zmm1 +; AVX512DQ-BW-NEXT: vmovdqa 32(%rcx), %xmm2 ; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] -; AVX512DQ-BW-NEXT: vporq %zmm0, %zmm1, %zmm1 -; AVX512DQ-BW-NEXT: vmovdqa64 32(%rcx), %xmm25 -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm13, %zmm22, %zmm13 -; AVX512DQ-BW-NEXT: vpermw %zmm13, %zmm26, %zmm0 +; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm13, %zmm21, %zmm13 +; AVX512DQ-BW-NEXT: vpermw %zmm13, %zmm26, %zmm24 ; AVX512DQ-BW-NEXT: movabsq $1161999626690365456, %rax # imm = 0x1020408102040810 ; AVX512DQ-BW-NEXT: kmovq %rax, %k5 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm0, %zmm1 {%k5} -; AVX512DQ-BW-NEXT: vmovdqa 32(%rdi), %xmm0 +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm24, %zmm1 {%k5} +; AVX512DQ-BW-NEXT: vmovdqa64 32(%rdi), %xmm24 ; AVX512DQ-BW-NEXT: movabsq $2033499346708139548, %rax # imm = 0x1C3870E1C3870E1C ; AVX512DQ-BW-NEXT: kmovq %rax, %k5 ; AVX512DQ-BW-NEXT: vmovdqu8 %zmm1, %zmm20 {%k5} ; AVX512DQ-BW-NEXT: vmovdqa 32(%rsi), %xmm1 ; AVX512DQ-BW-NEXT: vpshufhw {{.*#+}} ymm18 = ymm18[0,1,2,3,6,7,7,6,8,9,10,11,14,15,15,14] -; AVX512DQ-BW-NEXT: vpshufd {{.*#+}} ymm26 = ymm18[2,2,3,3,6,6,7,7] -; AVX512DQ-BW-NEXT: vpshufb %ymm27, %ymm19, %ymm26 {%k4} -; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm19 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7] +; AVX512DQ-BW-NEXT: vpshufd {{.*#+}} ymm25 = ymm18[2,2,3,3,6,6,7,7] +; AVX512DQ-BW-NEXT: vpshufb %ymm27, %ymm19, %ymm25 {%k4} +; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm19 = xmm24[0],xmm1[0],xmm24[1],xmm1[1],xmm24[2],xmm1[2],xmm24[3],xmm1[3],xmm24[4],xmm1[4],xmm24[5],xmm1[5],xmm24[6],xmm1[6],xmm24[7],xmm1[7] ; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} xmm18 = [0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] ; AVX512DQ-BW-NEXT: vpshufb %xmm18, %xmm19, %xmm19 -; AVX512DQ-BW-NEXT: vshufi64x2 {{.*#+}} zmm19 = zmm26[2,3,2,3],zmm19[0,1,0,1] -; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm26 = xmm24[0],xmm25[0],xmm24[1],xmm25[1],xmm24[2],xmm25[2],xmm24[3],xmm25[3],xmm24[4],xmm25[4],xmm24[5],xmm25[5],xmm24[6],xmm25[6],xmm24[7],xmm25[7] -; AVX512DQ-BW-NEXT: vpshufb %ymm11, %ymm16, %ymm11 -; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} xmm16 = [4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] -; AVX512DQ-BW-NEXT: vpshufb %xmm16, %xmm26, %xmm26 +; AVX512DQ-BW-NEXT: vshufi64x2 {{.*#+}} zmm25 = zmm25[2,3,2,3],zmm19[0,1,0,1] +; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm26 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3],xmm0[4],xmm2[4],xmm0[5],xmm2[5],xmm0[6],xmm2[6],xmm0[7],xmm2[7] +; AVX512DQ-BW-NEXT: vpshufb %ymm11, %ymm15, %ymm11 +; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} xmm19 = [4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] +; AVX512DQ-BW-NEXT: vpshufb %xmm19, %xmm26, %xmm15 ; AVX512DQ-BW-NEXT: vpshufhw {{.*#+}} ymm14 = ymm14[0,1,2,3,7,6,6,7,8,9,10,11,15,14,14,15] ; AVX512DQ-BW-NEXT: vpshufd {{.*#+}} ymm14 = ymm14[0,2,3,3,4,6,7,7] ; AVX512DQ-BW-NEXT: vmovdqu8 %ymm14, %ymm11 {%k1} -; AVX512DQ-BW-NEXT: vshufi64x2 {{.*#+}} zmm14 = zmm11[2,3,2,3],zmm26[0,1,0,1] -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm19, %zmm14 {%k2} +; AVX512DQ-BW-NEXT: vshufi64x2 {{.*#+}} zmm14 = zmm11[2,3,2,3],zmm15[0,1,0,1] +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm25, %zmm14 {%k2} +; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm11 = xmm23[0],xmm22[0],xmm23[1],xmm22[1],xmm23[2],xmm22[2],xmm23[3],xmm22[3],xmm23[4],xmm22[4],xmm23[5],xmm22[5],xmm23[6],xmm22[6],xmm23[7],xmm22[7] +; AVX512DQ-BW-NEXT: vmovdqa {{.*#+}} xmm15 = [u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] +; AVX512DQ-BW-NEXT: vpshufb %xmm15, %xmm11, %xmm11 ; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm9 = ymm9[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm9[27],zero,zero,zero,zero,ymm9[30],zero,ymm9[28],zero,zero,zero,zero,ymm9[31],zero -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm9 = ymm9[2,3,2,3] ; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} ymm10 = ymm10[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm10[27],zero,zero,zero,zero,ymm10[30],zero,ymm10[28],zero,zero,zero,zero,ymm10[31],zero,ymm10[29] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm10 = ymm10[2,3,2,3] -; AVX512DQ-BW-NEXT: vpor %ymm9, %ymm10, %ymm10 -; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm11 = xmm23[0],xmm21[0],xmm23[1],xmm21[1],xmm23[2],xmm21[2],xmm23[3],xmm21[3],xmm23[4],xmm21[4],xmm23[5],xmm21[5],xmm23[6],xmm21[6],xmm23[7],xmm21[7] -; AVX512DQ-BW-NEXT: vmovdqa {{.*#+}} xmm9 = [u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] -; AVX512DQ-BW-NEXT: vpshufb %xmm9, %xmm11, %xmm11 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} ymm11 = ymm11[0,1,0,1] -; AVX512DQ-BW-NEXT: vinserti64x4 $1, %ymm11, %zmm10, %zmm10 -; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} zmm11 = [14,13,14,15,15,14,14,15,14,13,14,15,15,14,14,15,17,17,16,16,17,17,16,16,20,21,17,17,17,17,16,16] -; AVX512DQ-BW-NEXT: vpermw %zmm22, %zmm11, %zmm11 +; AVX512DQ-BW-NEXT: vpor %ymm9, %ymm10, %ymm9 +; AVX512DQ-BW-NEXT: vshufi64x2 {{.*#+}} zmm9 = zmm9[2,3,2,3],zmm11[0,1,0,1] +; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} zmm10 = [14,13,14,15,15,14,14,15,14,13,14,15,15,14,14,15,17,17,16,16,17,17,16,16,20,21,17,17,17,17,16,16] +; AVX512DQ-BW-NEXT: vpermw %zmm21, %zmm10, %zmm10 ; AVX512DQ-BW-NEXT: movabsq $580999813345182728, %rax # imm = 0x810204081020408 ; AVX512DQ-BW-NEXT: kmovq %rax, %k1 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm11, %zmm10 {%k1} +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm10, %zmm9 {%k1} ; AVX512DQ-BW-NEXT: movabsq $1016749673354069774, %rax # imm = 0xE1C3870E1C3870E ; AVX512DQ-BW-NEXT: kmovq %rax, %k1 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm10, %zmm14 {%k1} -; AVX512DQ-BW-NEXT: vmovdqa {{.*#+}} xmm11 = [u,u,u,128,7,128,5,u,u,u,128,8,128,6,u,u] -; AVX512DQ-BW-NEXT: vpshufb %xmm11, %xmm25, %xmm10 -; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} xmm19 = [u,u,u,7,128,5,128,u,u,u,8,128,6,128,u,u] -; AVX512DQ-BW-NEXT: vpshufb %xmm19, %xmm24, %xmm26 -; AVX512DQ-BW-NEXT: vporq %xmm10, %xmm26, %xmm10 -; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm24 = xmm25[8],xmm24[8],xmm25[9],xmm24[9],xmm25[10],xmm24[10],xmm25[11],xmm24[11],xmm25[12],xmm24[12],xmm25[13],xmm24[13],xmm25[14],xmm24[14],xmm25[15],xmm24[15] -; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} xmm24 = xmm24[6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] -; AVX512DQ-BW-NEXT: vinserti32x4 $2, %xmm24, %zmm10, %zmm10 -; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} xmm24 = [u,128,7,128,5,u,u,u,128,8,128,6,u,u,u,128] -; AVX512DQ-BW-NEXT: vpshufb %xmm24, %xmm1, %xmm25 -; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} xmm26 = [u,7,128,5,128,u,u,u,8,128,6,128,u,u,u,9] -; AVX512DQ-BW-NEXT: vpshufb %xmm26, %xmm0, %xmm27 -; AVX512DQ-BW-NEXT: vporq %xmm25, %xmm27, %xmm25 -; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm0 = xmm1[8],xmm0[8],xmm1[9],xmm0[9],xmm1[10],xmm0[10],xmm1[11],xmm0[11],xmm1[12],xmm0[12],xmm1[13],xmm0[13],xmm1[14],xmm0[14],xmm1[15],xmm0[15] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm1 = zmm10[0,1,0,1,4,5,4,5] -; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] -; AVX512DQ-BW-NEXT: vinserti32x4 $2, %xmm0, %zmm25, %zmm0 -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm10 = zmm0[0,1,0,1,4,5,4,5] -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm1, %zmm10 {%k3} +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm9, %zmm14 {%k1} +; AVX512DQ-BW-NEXT: vmovdqa {{.*#+}} xmm10 = [u,u,u,128,7,128,5,u,u,u,128,8,128,6,u,u] +; AVX512DQ-BW-NEXT: vpshufb %xmm10, %xmm2, %xmm9 +; AVX512DQ-BW-NEXT: vmovdqa {{.*#+}} xmm11 = [u,u,u,7,128,5,128,u,u,u,8,128,6,128,u,u] +; AVX512DQ-BW-NEXT: vpshufb %xmm11, %xmm0, %xmm25 +; AVX512DQ-BW-NEXT: vporq %xmm9, %xmm25, %xmm9 +; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm0 = xmm2[8],xmm0[8],xmm2[9],xmm0[9],xmm2[10],xmm0[10],xmm2[11],xmm0[11],xmm2[12],xmm0[12],xmm2[13],xmm0[13],xmm2[14],xmm0[14],xmm2[15],xmm0[15] +; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} xmm0 = xmm0[6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] +; AVX512DQ-BW-NEXT: vinserti32x4 $2, %xmm0, %zmm9, %zmm0 +; AVX512DQ-BW-NEXT: vmovdqa {{.*#+}} xmm2 = [u,128,7,128,5,u,u,u,128,8,128,6,u,u,u,128] +; AVX512DQ-BW-NEXT: vpshufb %xmm2, %xmm1, %xmm9 +; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} xmm25 = [u,7,128,5,128,u,u,u,8,128,6,128,u,u,u,9] +; AVX512DQ-BW-NEXT: vpshufb %xmm25, %xmm24, %xmm26 +; AVX512DQ-BW-NEXT: vporq %xmm9, %xmm26, %xmm9 +; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm1[8],xmm24[8],xmm1[9],xmm24[9],xmm1[10],xmm24[10],xmm1[11],xmm24[11],xmm1[12],xmm24[12],xmm1[13],xmm24[13],xmm1[14],xmm24[14],xmm1[15],xmm24[15] +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm0 = zmm0[0,1,0,1,4,5,4,5] +; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} xmm1 = xmm1[2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] +; AVX512DQ-BW-NEXT: vinserti32x4 $2, %xmm1, %zmm9, %zmm1 +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm9 = zmm1[0,1,0,1,4,5,4,5] +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm0, %zmm9 {%k3} ; AVX512DQ-BW-NEXT: vmovdqa {{.*#+}} xmm0 = [128,4,u,u,u,128,7,128,5,u,u,u,128,8,128,6] -; AVX512DQ-BW-NEXT: vpshufb %xmm0, %xmm21, %xmm1 -; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} zmm25 = [2,2,2,4,2,2,2,4,3,3,3,3,2,2,2,4,52,53,52,53,53,54,53,54,52,53,52,53,53,54,53,54] -; AVX512DQ-BW-NEXT: vpermi2w %zmm22, %zmm17, %zmm25 +; AVX512DQ-BW-NEXT: vpshufb %xmm0, %xmm22, %xmm1 +; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} zmm24 = [2,2,2,4,2,2,2,4,3,3,3,3,2,2,2,4,52,53,52,53,53,54,53,54,52,53,52,53,53,54,53,54] +; AVX512DQ-BW-NEXT: vpermi2w %zmm21, %zmm17, %zmm24 ; AVX512DQ-BW-NEXT: vmovdqa64 {{.*#+}} xmm17 = [4,128,u,u,u,7,128,5,128,u,u,u,8,128,6,128] -; AVX512DQ-BW-NEXT: vpshufb %xmm17, %xmm23, %xmm22 -; AVX512DQ-BW-NEXT: vporq %xmm1, %xmm22, %xmm1 -; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm21 = xmm23[8],xmm21[8],xmm23[9],xmm21[9],xmm23[10],xmm21[10],xmm23[11],xmm21[11],xmm23[12],xmm21[12],xmm23[13],xmm21[13],xmm23[14],xmm21[14],xmm23[15],xmm21[15] +; AVX512DQ-BW-NEXT: vpshufb %xmm17, %xmm23, %xmm21 +; AVX512DQ-BW-NEXT: vporq %xmm1, %xmm21, %xmm1 +; AVX512DQ-BW-NEXT: vpunpckhbw {{.*#+}} xmm21 = xmm23[8],xmm22[8],xmm23[9],xmm22[9],xmm23[10],xmm22[10],xmm23[11],xmm22[11],xmm23[12],xmm22[12],xmm23[13],xmm22[13],xmm23[14],xmm22[14],xmm23[15],xmm22[15] ; AVX512DQ-BW-NEXT: vpshufb {{.*#+}} xmm21 = xmm21[u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] ; AVX512DQ-BW-NEXT: vinserti32x4 $2, %xmm21, %zmm1, %zmm1 ; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm1 = zmm1[0,1,0,1,4,5,4,5] ; AVX512DQ-BW-NEXT: movabsq $290499906672591364, %rax # imm = 0x408102040810204 ; AVX512DQ-BW-NEXT: kmovq %rax, %k1 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm25, %zmm1 {%k1} +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm24, %zmm1 {%k1} ; AVX512DQ-BW-NEXT: movabsq $-8714997200177740921, %rax # imm = 0x870E1C3870E1C387 ; AVX512DQ-BW-NEXT: kmovq %rax, %k1 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm1, %zmm10 {%k1} -; AVX512DQ-BW-NEXT: vpshufb %xmm11, %xmm5, %xmm1 -; AVX512DQ-BW-NEXT: vpshufb %xmm19, %xmm4, %xmm11 -; AVX512DQ-BW-NEXT: vpor %xmm1, %xmm11, %xmm1 +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm1, %zmm9 {%k1} +; AVX512DQ-BW-NEXT: vpshufb %xmm10, %xmm5, %xmm1 +; AVX512DQ-BW-NEXT: vpshufb %xmm11, %xmm4, %xmm10 +; AVX512DQ-BW-NEXT: vpor %xmm1, %xmm10, %xmm1 ; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm4 = xmm4[0],xmm5[0],xmm4[1],xmm5[1],xmm4[2],xmm5[2],xmm4[3],xmm5[3],xmm4[4],xmm5[4],xmm4[5],xmm5[5],xmm4[6],xmm5[6],xmm4[7],xmm5[7] -; AVX512DQ-BW-NEXT: vpshufb %xmm16, %xmm4, %xmm4 +; AVX512DQ-BW-NEXT: vpshufb %xmm19, %xmm4, %xmm4 ; AVX512DQ-BW-NEXT: vinserti32x4 $2, %xmm1, %zmm4, %zmm1 -; AVX512DQ-BW-NEXT: vpshufb %xmm24, %xmm7, %xmm4 -; AVX512DQ-BW-NEXT: vpshufb %xmm26, %xmm6, %xmm5 -; AVX512DQ-BW-NEXT: vpor %xmm4, %xmm5, %xmm4 -; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm5 = xmm6[0],xmm7[0],xmm6[1],xmm7[1],xmm6[2],xmm7[2],xmm6[3],xmm7[3],xmm6[4],xmm7[4],xmm6[5],xmm7[5],xmm6[6],xmm7[6],xmm6[7],xmm7[7] -; AVX512DQ-BW-NEXT: vpshufb %xmm18, %xmm5, %xmm5 -; AVX512DQ-BW-NEXT: vinserti32x4 $2, %xmm4, %zmm5, %zmm4 +; AVX512DQ-BW-NEXT: vpshufb %xmm2, %xmm7, %xmm2 +; AVX512DQ-BW-NEXT: vpshufb %xmm25, %xmm6, %xmm4 +; AVX512DQ-BW-NEXT: vpor %xmm2, %xmm4, %xmm2 +; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm4 = xmm6[0],xmm7[0],xmm6[1],xmm7[1],xmm6[2],xmm7[2],xmm6[3],xmm7[3],xmm6[4],xmm7[4],xmm6[5],xmm7[5],xmm6[6],xmm7[6],xmm6[7],xmm7[7] +; AVX512DQ-BW-NEXT: vpshufb %xmm18, %xmm4, %xmm4 +; AVX512DQ-BW-NEXT: vinserti32x4 $2, %xmm2, %zmm4, %zmm2 ; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm1 = zmm1[0,1,0,1,4,5,4,5] -; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm4 = zmm4[0,1,0,1,4,5,4,5] +; AVX512DQ-BW-NEXT: vpermq {{.*#+}} zmm2 = zmm2[0,1,0,1,4,5,4,5] ; AVX512DQ-BW-NEXT: movabsq $871499720017774092, %rax # imm = 0xC183060C183060C ; AVX512DQ-BW-NEXT: kmovq %rax, %k1 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm1, %zmm4 {%k1} -; AVX512DQ-BW-NEXT: vpshufb %xmm0, %xmm12, %xmm0 -; AVX512DQ-BW-NEXT: vpshufb %xmm17, %xmm3, %xmm1 +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm1, %zmm2 {%k1} +; AVX512DQ-BW-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm4 # 16-byte Reload +; AVX512DQ-BW-NEXT: vpshufb %xmm0, %xmm4, %xmm0 +; AVX512DQ-BW-NEXT: vpshufb %xmm17, %xmm12, %xmm1 ; AVX512DQ-BW-NEXT: vpor %xmm0, %xmm1, %xmm0 -; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm3[0],xmm12[0],xmm3[1],xmm12[1],xmm3[2],xmm12[2],xmm3[3],xmm12[3],xmm3[4],xmm12[4],xmm3[5],xmm12[5],xmm3[6],xmm12[6],xmm3[7],xmm12[7] -; AVX512DQ-BW-NEXT: vpshufb %xmm9, %xmm1, %xmm1 +; AVX512DQ-BW-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm12[0],xmm4[0],xmm12[1],xmm4[1],xmm12[2],xmm4[2],xmm12[3],xmm4[3],xmm12[4],xmm4[4],xmm12[5],xmm4[5],xmm12[6],xmm4[6],xmm12[7],xmm4[7] +; AVX512DQ-BW-NEXT: vpshufb %xmm15, %xmm1, %xmm1 ; AVX512DQ-BW-NEXT: vinserti32x4 $2, %xmm0, %zmm1, %zmm0 ; AVX512DQ-BW-NEXT: vpmovsxbw {{.*#+}} zmm1 = [1,1,0,0,1,1,0,0,4,5,1,1,1,1,0,0,18,18,18,20,18,18,18,20,19,19,19,19,18,18,18,20] ; AVX512DQ-BW-NEXT: vpermw %zmm13, %zmm1, %zmm1 @@ -11367,334 +11112,319 @@ define void @store_i8_stride7_vf64(ptr %in.vecptr0, ptr %in.vecptr1, ptr %in.vec ; AVX512DQ-BW-NEXT: vmovdqu8 %zmm1, %zmm0 {%k1} ; AVX512DQ-BW-NEXT: movabsq $8133997386832558192, %rax # imm = 0x70E1C3870E1C3870 ; AVX512DQ-BW-NEXT: kmovq %rax, %k1 -; AVX512DQ-BW-NEXT: vmovdqu8 %zmm0, %zmm4 {%k1} +; AVX512DQ-BW-NEXT: vmovdqu8 %zmm0, %zmm2 {%k1} ; AVX512DQ-BW-NEXT: movq {{[0-9]+}}(%rsp), %rax -; AVX512DQ-BW-NEXT: vmovdqa64 %zmm4, (%rax) +; AVX512DQ-BW-NEXT: vmovdqa64 %zmm2, (%rax) ; AVX512DQ-BW-NEXT: vmovdqa64 %zmm8, 320(%rax) -; AVX512DQ-BW-NEXT: vmovdqa64 %zmm10, 256(%rax) +; AVX512DQ-BW-NEXT: vmovdqa64 %zmm9, 256(%rax) ; AVX512DQ-BW-NEXT: vmovdqa64 %zmm14, 192(%rax) ; AVX512DQ-BW-NEXT: vmovdqa64 %zmm20, 128(%rax) -; AVX512DQ-BW-NEXT: vmovdqa64 %zmm2, 64(%rax) -; AVX512DQ-BW-NEXT: vmovdqa64 %zmm15, 384(%rax) +; AVX512DQ-BW-NEXT: vmovdqa64 %zmm3, 64(%rax) +; AVX512DQ-BW-NEXT: vmovdqa64 %zmm16, 384(%rax) ; AVX512DQ-BW-NEXT: vzeroupper ; AVX512DQ-BW-NEXT: retq ; ; AVX512DQ-BW-FCP-LABEL: store_i8_stride7_vf64: ; AVX512DQ-BW-FCP: # %bb.0: -; AVX512DQ-BW-FCP-NEXT: subq $40, %rsp +; AVX512DQ-BW-FCP-NEXT: subq $104, %rsp ; AVX512DQ-BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rax), %ymm0 -; AVX512DQ-BW-FCP-NEXT: vmovdqu %ymm0, (%rsp) # 32-byte Spill -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} ymm28 = [12,13,2,3,12,13,0,1,14,15,2,3,0,1,14,15,28,29,18,19,28,29,16,17,30,31,18,19,16,17,30,31] -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm28, %ymm0, %ymm1 -; AVX512DQ-BW-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm2 = [4,5,4,5,5,6,5,6,4,5,4,5,5,6,5,6] -; AVX512DQ-BW-FCP-NEXT: # ymm2 = mem[0,1,0,1] -; AVX512DQ-BW-FCP-NEXT: vpermw %ymm0, %ymm2, %ymm2 -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm2, %zmm2 -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%r9), %ymm0 -; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} ymm1 = [13,128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128] -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm1, %ymm0, %ymm3 -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %ymm0, %ymm19 -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%r8), %ymm20 -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} ymm22 = [128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128] -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm22, %ymm20, %ymm4 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rax), %ymm2 +; AVX512DQ-BW-FCP-NEXT: vmovdqu %ymm2, (%rsp) # 32-byte Spill +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} ymm20 = [12,13,2,3,12,13,0,1,14,15,2,3,0,1,14,15,28,29,18,19,28,29,16,17,30,31,18,19,16,17,30,31] +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm20, %ymm2, %ymm0 +; AVX512DQ-BW-FCP-NEXT: vbroadcasti128 {{.*#+}} ymm1 = [4,5,4,5,5,6,5,6,4,5,4,5,5,6,5,6] +; AVX512DQ-BW-FCP-NEXT: # ymm1 = mem[0,1,0,1] +; AVX512DQ-BW-FCP-NEXT: vpermw %ymm2, %ymm1, %ymm1 +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm2 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%r9), %ymm1 +; AVX512DQ-BW-FCP-NEXT: vmovdqu %ymm1, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} ymm0 = [13,128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128] +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm0, %ymm1, %ymm3 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%r8), %ymm4 +; AVX512DQ-BW-FCP-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} ymm1 = [128,128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128] +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm1, %ymm4, %ymm4 ; AVX512DQ-BW-FCP-NEXT: vpor %ymm3, %ymm4, %ymm3 -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%r9), %xmm0 -; AVX512DQ-BW-FCP-NEXT: vmovdqa %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%r8), %xmm4 -; AVX512DQ-BW-FCP-NEXT: vmovdqa %xmm4, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill -; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm4[8],xmm0[8],xmm4[9],xmm0[9],xmm4[10],xmm0[10],xmm4[11],xmm0[11],xmm4[12],xmm0[12],xmm4[13],xmm0[13],xmm4[14],xmm0[14],xmm4[15],xmm0[15] +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%r9), %xmm16 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%r8), %xmm15 +; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm15[8],xmm16[8],xmm15[9],xmm16[9],xmm15[10],xmm16[10],xmm15[11],xmm16[11],xmm15[12],xmm16[12],xmm15[13],xmm16[13],xmm15[14],xmm16[14],xmm15[15],xmm16[15] ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} xmm4 = xmm4[u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] ; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[0,1,0,1] ; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm3, %zmm4, %zmm3 ; AVX512DQ-BW-FCP-NEXT: movabsq $2323999253380730912, %r10 # imm = 0x2040810204081020 ; AVX512DQ-BW-FCP-NEXT: kmovq %r10, %k1 ; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm2, %zmm3 {%k1} -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdx), %ymm0 -; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} ymm4 = [0,1,0,1,14,128,14,15,0,1,14,15,128,13,14,15,16,17,16,128,30,31,30,31,16,17,128,31,28,29,30,31] -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm4, %ymm0, %ymm2 -; AVX512DQ-BW-FCP-NEXT: vmovdqa %ymm0, %ymm9 -; AVX512DQ-BW-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rcx), %ymm0 -; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} ymm11 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm11, %ymm0, %ymm5 -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %ymm0, %ymm18 -; AVX512DQ-BW-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-BW-FCP-NEXT: vpor %ymm2, %ymm5, %ymm2 -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdx), %xmm14 -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rcx), %xmm15 -; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm5 = xmm15[8],xmm14[8],xmm15[9],xmm14[9],xmm15[10],xmm14[10],xmm15[11],xmm14[11],xmm15[12],xmm14[12],xmm15[13],xmm14[13],xmm15[14],xmm14[14],xmm15[15],xmm14[15] -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} xmm5 = xmm5[6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm5[0,1,0,1] -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm2, %zmm5, %zmm2 -; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdi), %ymm0 -; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} ymm12 = [0,1,14,128,12,13,0,1,14,15,128,3,12,13,2,3,16,128,30,31,28,29,16,17,128,31,18,19,28,29,18,128] -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm12, %ymm0, %ymm5 -; AVX512DQ-BW-FCP-NEXT: vmovdqa %ymm0, %ymm6 -; AVX512DQ-BW-FCP-NEXT: vmovdqu %ymm0, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rsi), %ymm24 -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} ymm21 = [128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128,128,18] -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm21, %ymm24, %ymm16 -; AVX512DQ-BW-FCP-NEXT: vporq %ymm5, %ymm16, %ymm5 -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rdi), %xmm16 -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rsi), %xmm17 -; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm25 = xmm17[8],xmm16[8],xmm17[9],xmm16[9],xmm17[10],xmm16[10],xmm17[11],xmm16[11],xmm17[12],xmm16[12],xmm17[13],xmm16[13],xmm17[14],xmm16[14],xmm17[15],xmm16[15] -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} xmm25 = xmm25[2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm25 = ymm25[0,1,0,1] -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm5, %zmm25, %zmm13 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdx), %ymm4 +; AVX512DQ-BW-FCP-NEXT: vmovdqu %ymm4, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} ymm2 = [0,1,0,1,14,128,14,15,0,1,14,15,128,13,14,15,16,17,16,128,30,31,30,31,16,17,128,31,28,29,30,31] +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm2, %ymm4, %ymm4 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rcx), %ymm6 +; AVX512DQ-BW-FCP-NEXT: vmovdqu %ymm6, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} ymm5 = [128,128,128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128] +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm5, %ymm6, %ymm6 +; AVX512DQ-BW-FCP-NEXT: vpor %ymm4, %ymm6, %ymm4 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rdx), %xmm17 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rcx), %xmm19 +; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm6 = xmm19[8],xmm17[8],xmm19[9],xmm17[9],xmm19[10],xmm17[10],xmm19[11],xmm17[11],xmm19[12],xmm17[12],xmm19[13],xmm17[13],xmm19[14],xmm17[14],xmm19[15],xmm17[15] +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} xmm29 = [6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm29, %xmm6, %xmm6 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[0,1,0,1] +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm6, %zmm4 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rdi), %ymm6 +; AVX512DQ-BW-FCP-NEXT: vmovdqu %ymm6, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} ymm9 = [0,1,14,128,12,13,0,1,14,15,128,3,12,13,2,3,16,128,30,31,28,29,16,17,128,31,18,19,28,29,18,128] +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm9, %ymm6, %ymm6 +; AVX512DQ-BW-FCP-NEXT: vmovdqa (%rsi), %ymm7 +; AVX512DQ-BW-FCP-NEXT: vmovdqu %ymm7, {{[-0-9]+}}(%r{{[sb]}}p) # 32-byte Spill +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} ymm23 = [128,128,128,14,128,128,128,128,128,128,15,128,128,128,128,128,128,16,128,128,128,128,128,128,17,128,128,128,128,128,128,18] +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm23, %ymm7, %ymm21 +; AVX512DQ-BW-FCP-NEXT: vporq %ymm6, %ymm21, %ymm6 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rdi), %xmm21 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rsi), %xmm22 +; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm24 = xmm22[8],xmm21[8],xmm22[9],xmm21[9],xmm22[10],xmm21[10],xmm22[11],xmm21[11],xmm22[12],xmm21[12],xmm22[13],xmm21[13],xmm22[14],xmm21[14],xmm22[15],xmm21[15] +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm7 = [2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm7, %xmm24, %xmm24 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm24 = ymm24[0,1,0,1] +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm6, %zmm24, %zmm14 ; AVX512DQ-BW-FCP-NEXT: movabsq $435749860008887046, %r10 # imm = 0x60C183060C18306 ; AVX512DQ-BW-FCP-NEXT: kmovq %r10, %k1 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm2, %zmm13 {%k1} +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm4, %zmm14 {%k1} ; AVX512DQ-BW-FCP-NEXT: movabsq $4066998693416279096, %r10 # imm = 0x3870E1C3870E1C38 ; AVX512DQ-BW-FCP-NEXT: kmovq %r10, %k1 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm3, %zmm13 {%k1} -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm0 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,24,25,128,23,128,21,22,23,26,128,24,128,28,29,26,27] -; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rdx), %ymm2 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm0, %ymm2, %ymm3 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm25 = ymm3[2,3,2,3] -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm0 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128] -; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rcx), %ymm3 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm0, %ymm3, %ymm26 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm26 = ymm26[2,3,2,3] -; AVX512DQ-BW-FCP-NEXT: vporq %ymm25, %ymm26, %ymm25 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm4, %ymm2, %ymm4 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm11, %ymm3, %ymm11 -; AVX512DQ-BW-FCP-NEXT: vpor %ymm4, %ymm11, %ymm4 -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm25, %zmm4, %zmm4 -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm0 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,19,20,21,128,19,128,21,20,21,22,128,20,128,22,23,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128] -; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rdi), %ymm11 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm0, %ymm11, %ymm25 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm25 = ymm25[2,3,2,3] -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm0 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128,25] -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 32(%rsi), %ymm27 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm0, %ymm27, %ymm26 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm26 = ymm26[2,3,2,3] -; AVX512DQ-BW-FCP-NEXT: vporq %ymm25, %ymm26, %ymm25 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm12, %ymm11, %ymm12 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm21, %ymm27, %ymm21 -; AVX512DQ-BW-FCP-NEXT: vporq %ymm12, %ymm21, %ymm12 -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm25, %zmm12, %zmm12 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm3, %zmm14 {%k1} +; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rdx), %ymm3 +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm2, %ymm3, %ymm4 +; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rcx), %ymm2 +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm5, %ymm2, %ymm5 +; AVX512DQ-BW-FCP-NEXT: vpor %ymm4, %ymm5, %ymm4 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm5 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,128,18,19,20,21,128,19,128,25,26,27,22,128,20,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,24,25,128,23,128,21,22,23,26,128,24,128,28,29,26,27] +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm5, %ymm3, %ymm5 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm6 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,18,128,128,128,128,21,128,19,128,128,128,128,22,128,20,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,25,128,23,128,128,128,128,26,128,24,128,128,128,128] +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm6, %ymm2, %ymm24 +; AVX512DQ-BW-FCP-NEXT: vporq %ymm5, %ymm24, %ymm5 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm5 = ymm5[2,3,2,3] +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm5, %zmm4, %zmm4 +; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rdi), %ymm5 +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm9, %ymm5, %ymm9 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 32(%rsi), %ymm25 +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm23, %ymm25, %ymm23 +; AVX512DQ-BW-FCP-NEXT: vporq %ymm9, %ymm23, %ymm9 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm6 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,18,19,20,21,128,19,128,21,20,21,22,128,20,128,22,23,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128] +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm6, %ymm5, %ymm23 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm6 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,128,128,21,128,19,128,128,128,128,22,128,20,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,23,128,128,128,128,26,128,24,128,128,128,128,27,128,25] +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm6, %ymm25, %ymm24 +; AVX512DQ-BW-FCP-NEXT: vporq %ymm23, %ymm24, %ymm23 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm23 = ymm23[2,3,2,3] +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm23, %zmm9, %zmm9 ; AVX512DQ-BW-FCP-NEXT: movabsq $3485998880071096368, %r10 # imm = 0x3060C183060C1830 -; AVX512DQ-BW-FCP-NEXT: kmovq %r10, %k2 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm4, %zmm12 {%k2} -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm0 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,24,25,24,25,128,23,128,23,24,25,26,128,24,128,30,31] -; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%r8), %ymm4 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm0, %ymm4, %ymm21 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm25 = ymm21[2,3,2,3] -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm5 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,128,128,25,128,23,128,128,128,128,26,128,24,128,128] -; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%r9), %ymm0 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm5, %ymm0, %ymm26 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm26 = ymm26[2,3,2,3] -; AVX512DQ-BW-FCP-NEXT: vporq %ymm25, %ymm26, %ymm25 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm1, %ymm0, %ymm1 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm22, %ymm4, %ymm22 -; AVX512DQ-BW-FCP-NEXT: vporq %ymm1, %ymm22, %ymm1 -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm25, %zmm1, %zmm1 -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 32(%rax), %ymm31 -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm22 = [10,9,9,10,10,9,9,10,9,10,14,15,10,9,9,10] -; AVX512DQ-BW-FCP-NEXT: vpermw %ymm31, %ymm22, %ymm22 -; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm28, %ymm31, %ymm25 -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm22, %zmm25, %zmm22 -; AVX512DQ-BW-FCP-NEXT: movabsq $145249953336295682, %r10 # imm = 0x204081020408102 ; AVX512DQ-BW-FCP-NEXT: kmovq %r10, %k1 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm22, %zmm1 {%k1} +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm4, %zmm9 {%k1} +; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%r9), %ymm4 +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm0, %ymm4, %ymm0 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 32(%r8), %ymm28 +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm1, %ymm28, %ymm1 +; AVX512DQ-BW-FCP-NEXT: vpor %ymm0, %ymm1, %ymm0 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm1 = [128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,20,128,18,128,20,21,20,21,128,19,128,19,20,21,22,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,24,25,24,25,128,23,128,23,24,25,26,128,24,128,30,31] +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm1, %ymm28, %ymm1 +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} zmm6 = [u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,20,128,18,128,128,128,128,21,128,19,128,128,128,128,22,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,128,128,128,128,25,128,23,128,128,128,128,26,128,24,128,128] +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm6, %ymm4, %ymm23 +; AVX512DQ-BW-FCP-NEXT: vporq %ymm1, %ymm23, %ymm1 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm1, %zmm0, %zmm1 +; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rax), %ymm6 +; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} ymm23 = [10,9,9,10,10,9,9,10,9,10,14,15,10,9,9,10] +; AVX512DQ-BW-FCP-NEXT: vpermw %ymm6, %ymm23, %ymm23 +; AVX512DQ-BW-FCP-NEXT: vpshufb %ymm20, %ymm6, %ymm20 +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm23, %zmm20, %zmm20 +; AVX512DQ-BW-FCP-NEXT: movabsq $145249953336295682, %r10 # imm = 0x204081020408102 +; AVX512DQ-BW-FCP-NEXT: kmovq %r10, %k2 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm20, %zmm1 {%k2} ; AVX512DQ-BW-FCP-NEXT: movabsq $-4357498600088870461, %r10 # imm = 0xC3870E1C3870E1C3 -; AVX512DQ-BW-FCP-NEXT: kmovq %r10, %k1 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm12 {%k1} -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rcx), %zmm25 -; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm2[0,1,2,3],zmm25[4,5,6,7] +; AVX512DQ-BW-FCP-NEXT: kmovq %r10, %k2 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm9 {%k2} +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rcx), %zmm23 +; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm3[0,1,2,3],zmm23[4,5,6,7] ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm1 = zmm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25],zero,zmm1[23],zero,zmm1[21,22,23,26],zero,zmm1[24],zero,zmm1[28,29,26,27,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,59],zero,zero,zero,zero,zmm1[62],zero,zmm1[60],zero,zero,zero,zero,zmm1[63],zero,zmm1[61],zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rdx), %zmm26 -; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm3[0,1,2,3],zmm26[4,5,6,7] +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rdx), %zmm24 +; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm2[0,1,2,3],zmm24[4,5,6,7] ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm2 = zmm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zmm2[25],zero,zmm2[23],zero,zero,zero,zero,zmm2[26],zero,zmm2[24],zero,zero,zero,zero,zmm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm2[62],zero,zmm2[60],zero,zero,zero,zero,zmm2[63],zero,zmm2[61],zero,zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm2 = zmm2[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-FCP-NEXT: vporq %zmm1, %zmm2, %zmm1 -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rdi), %zmm28 -; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm27[0,1,2,3],zmm28[4,5,6,7] +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rdi), %zmm26 +; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm25[0,1,2,3],zmm26[4,5,6,7] ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm2 = zmm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,25],zero,zmm2[23],zero,zero,zero,zero,zmm2[26],zero,zmm2[24],zero,zero,zero,zero,zmm2[27],zero,zmm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,60,61,62],zero,zmm2[60],zero,zmm2[62,63,62,63],zero,zmm2[61],zero,zmm2[63,60,61] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm2 = zmm2[2,3,2,3,6,7,6,7] -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rsi), %zmm29 -; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm3 = zmm11[0,1,2,3],zmm29[4,5,6,7] +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rsi), %zmm27 +; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm3 = zmm5[0,1,2,3],zmm27[4,5,6,7] ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm3 = zmm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm3[23],zero,zero,zero,zero,zmm3[26],zero,zmm3[24],zero,zero,zero,zero,zmm3[27],zero,zmm3[25,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zmm3[62],zero,zmm3[60],zero,zero,zero,zero,zmm3[63],zero,zmm3[61],zero,zero,zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm3 = zmm3[2,3,2,3,6,7,6,7] -; AVX512DQ-BW-FCP-NEXT: vporq %zmm2, %zmm3, %zmm22 +; AVX512DQ-BW-FCP-NEXT: vporq %zmm2, %zmm3, %zmm2 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm20 = zmm2[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-FCP-NEXT: movabsq $1742999440035548184, %r10 # imm = 0x183060C183060C18 -; AVX512DQ-BW-FCP-NEXT: kmovq %r10, %k1 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm22 {%k1} -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%r9), %zmm27 -; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm4[0,1,2,3],zmm27[4,5,6,7] +; AVX512DQ-BW-FCP-NEXT: kmovq %r10, %k2 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm20 {%k2} +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%r9), %zmm25 +; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm28[0,1,2,3],zmm25[4,5,6,7] ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm1 = zmm1[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,24,25,24,25],zero,zmm1[23],zero,zmm1[23,24,25,26],zero,zmm1[24],zero,zmm1[30,31,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,61],zero,zmm1[59],zero,zero,zero,zero,zmm1[62],zero,zmm1[60],zero,zero,zero,zero,zmm1[63],zero +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%r8), %zmm28 +; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm4[0,1,2,3],zmm28[4,5,6,7] +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm2 = zmm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm2[25],zero,zmm2[23],zero,zero,zero,zero,zmm2[26],zero,zmm2[24],zero,zero,zmm2[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm2[59],zero,zero,zero,zero,zmm2[62],zero,zmm2[60],zero,zero,zero,zero,zmm2[63],zero,zmm2[61] +; AVX512DQ-BW-FCP-NEXT: vporq %zmm1, %zmm2, %zmm1 ; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%r8), %zmm30 -; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm0 = zmm0[0,1,2,3],zmm30[4,5,6,7] -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm0 = zmm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm0[25],zero,zmm0[23],zero,zero,zero,zero,zmm0[26],zero,zmm0[24],zero,zero,zmm0[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm0[59],zero,zero,zero,zero,zmm0[62],zero,zmm0[60],zero,zero,zero,zero,zmm0[63],zero,zmm0[61] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm0 = zmm0[2,3,2,3,6,7,6,7] -; AVX512DQ-BW-FCP-NEXT: vporq %zmm1, %zmm0, %zmm0 ; AVX512DQ-BW-FCP-NEXT: movabsq $6971997760142192736, %r10 # imm = 0x60C183060C183060 -; AVX512DQ-BW-FCP-NEXT: kmovq %r10, %k1 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm0, %zmm22 {%k1} -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rax), %zmm10 -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm0 = [11,13,12,11,12,13,13,12,11,13,12,11,12,13,13,12,62,61,62,63,63,62,62,63,62,61,62,63,63,62,62,63] -; AVX512DQ-BW-FCP-NEXT: vpermi2w %zmm10, %zmm31, %zmm0 +; AVX512DQ-BW-FCP-NEXT: kmovq %r10, %k2 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm20 {%k2} +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 (%rax), %zmm31 +; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm1 = [11,13,12,11,12,13,13,12,11,13,12,11,12,13,13,12,62,61,62,63,63,62,62,63,62,61,62,63,63,62,62,63] +; AVX512DQ-BW-FCP-NEXT: vpermi2w %zmm31, %zmm6, %zmm1 ; AVX512DQ-BW-FCP-NEXT: movabsq $-9150747060186627967, %rax # imm = 0x8102040810204081 ; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k3 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm0, %zmm22 {%k3} -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,30],zero,ymm6[28],zero,ymm6[30,31,30,31],zero,ymm6[29],zero,ymm6[31,28,29] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm24[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm24[30],zero,ymm24[28],zero,zero,zero,zero,ymm24[31],zero,ymm24[29],zero,zero,zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512DQ-BW-FCP-NEXT: vpor %ymm0, %ymm1, %ymm1 -; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rdi), %xmm8 -; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rsi), %xmm7 -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm4 = xmm8[0],xmm7[0],xmm8[1],xmm7[1],xmm8[2],xmm7[2],xmm8[3],xmm7[3],xmm8[4],xmm7[4],xmm8[5],xmm7[5],xmm8[6],xmm7[6],xmm8[7],xmm7[7] -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} xmm4 = xmm4[0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[0,1,0,1] -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm4, %zmm1, %zmm6 -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm1 = ymm18[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,zero,zero,ymm18[30],zero,ymm18[28],zero,zero,zero,zero,ymm18[31],zero,ymm18[29],zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm1 = ymm1[2,3,2,3] -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm9[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm9[30],zero,ymm9[28],zero,zero,zero,zero,ymm9[31],zero,ymm9[29],zero,zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm4 = ymm4[2,3,2,3] -; AVX512DQ-BW-FCP-NEXT: vpor %ymm1, %ymm4, %ymm4 -; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rdx), %xmm2 -; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rcx), %xmm1 -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm2[0],xmm1[0],xmm2[1],xmm1[1],xmm2[2],xmm1[2],xmm2[3],xmm1[3],xmm2[4],xmm1[4],xmm2[5],xmm1[5],xmm2[6],xmm1[6],xmm2[7],xmm1[7] -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} xmm18 = [4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm18, %xmm0, %xmm0 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,1,0,1] -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm4, %zmm9 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm6, %zmm9 {%k2} -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm0 = ymm19[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm19[27],zero,zero,zero,zero,ymm19[30],zero,ymm19[28],zero,zero,zero,zero,ymm19[31],zero -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %ymm19, %ymm21 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[2,3,2,3] -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm6 = ymm20[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm20[27],zero,zero,zero,zero,ymm20[30],zero,ymm20[28],zero,zero,zero,zero,ymm20[31],zero,ymm20[29] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm6 = ymm6[2,3,2,3] -; AVX512DQ-BW-FCP-NEXT: vpor %ymm0, %ymm6, %ymm3 -; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%r9), %xmm5 -; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%r8), %xmm4 -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm0 = xmm4[0],xmm5[0],xmm4[1],xmm5[1],xmm4[2],xmm5[2],xmm4[3],xmm5[3],xmm4[4],xmm5[4],xmm4[5],xmm5[5],xmm4[6],xmm5[6],xmm4[7],xmm5[7] -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 {{.*#+}} xmm19 = [u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm19, %xmm0, %xmm0 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} ymm0 = ymm0[0,1,0,1] -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm0, %zmm3, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm3 = [14,13,14,15,15,14,14,15,14,13,14,15,15,14,14,15,17,17,16,16,17,17,16,16,20,21,17,17,17,17,16,16] -; AVX512DQ-BW-FCP-NEXT: vpermw %zmm10, %zmm3, %zmm3 -; AVX512DQ-BW-FCP-NEXT: movabsq $580999813345182728, %rax # imm = 0x810204081020408 -; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k2 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm3, %zmm0 {%k2} -; AVX512DQ-BW-FCP-NEXT: movabsq $1016749673354069774, %rax # imm = 0xE1C3870E1C3870E -; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k2 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm0, %zmm9 {%k2} -; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm11 = [u,u,u,128,7,128,5,u,u,u,128,8,128,6,u,u] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm11, %xmm1, %xmm3 -; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm6 = [u,u,u,7,128,5,128,u,u,u,8,128,6,128,u,u] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm6, %xmm2, %xmm23 -; AVX512DQ-BW-FCP-NEXT: vporq %xmm3, %xmm23, %xmm3 -; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm1 = xmm1[8],xmm2[8],xmm1[9],xmm2[9],xmm1[10],xmm2[10],xmm1[11],xmm2[11],xmm1[12],xmm2[12],xmm1[13],xmm2[13],xmm1[14],xmm2[14],xmm1[15],xmm2[15] -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} xmm1 = xmm1[6,3,2,u,u,u,9,8,5,4,u,u,u,11,10,7] -; AVX512DQ-BW-FCP-NEXT: vinserti32x4 $2, %xmm1, %zmm3, %zmm1 -; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm2 = [u,128,7,128,5,u,u,u,128,8,128,6,u,u,u,128] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm2, %xmm7, %xmm3 -; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm0 = [u,7,128,5,128,u,u,u,8,128,6,128,u,u,u,9] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm0, %xmm8, %xmm23 -; AVX512DQ-BW-FCP-NEXT: vporq %xmm3, %xmm23, %xmm3 -; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm7 = xmm7[8],xmm8[8],xmm7[9],xmm8[9],xmm7[10],xmm8[10],xmm7[11],xmm8[11],xmm7[12],xmm8[12],xmm7[13],xmm8[13],xmm7[14],xmm8[14],xmm7[15],xmm8[15] -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} xmm7 = xmm7[2,u,u,u,9,8,5,4,u,u,u,11,10,7,6,u] -; AVX512DQ-BW-FCP-NEXT: vinserti32x4 $2, %xmm7, %zmm3, %zmm3 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm1 = zmm1[0,1,0,1,4,5,4,5] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm23 = zmm3[0,1,0,1,4,5,4,5] -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm23 {%k1} -; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm1 = [128,4,u,u,u,128,7,128,5,u,u,u,128,8,128,6] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm1, %xmm5, %xmm3 -; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm7 = [4,128,u,u,u,7,128,5,128,u,u,u,8,128,6,128] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm7, %xmm4, %xmm8 -; AVX512DQ-BW-FCP-NEXT: vpor %xmm3, %xmm8, %xmm3 -; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm4 = xmm4[8],xmm5[8],xmm4[9],xmm5[9],xmm4[10],xmm5[10],xmm4[11],xmm5[11],xmm4[12],xmm5[12],xmm4[13],xmm5[13],xmm4[14],xmm5[14],xmm4[15],xmm5[15] -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} xmm4 = xmm4[u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] -; AVX512DQ-BW-FCP-NEXT: vinserti32x4 $2, %xmm4, %zmm3, %zmm3 -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm4 = [2,2,2,4,2,2,2,4,3,3,3,3,2,2,2,4,52,53,52,53,53,54,53,54,52,53,52,53,53,54,53,54] -; AVX512DQ-BW-FCP-NEXT: vpermi2w %zmm10, %zmm31, %zmm4 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm20 {%k3} +; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rdx), %xmm5 +; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rcx), %xmm4 +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm13 = [u,u,u,128,7,128,5,u,u,u,128,8,128,6,u,u] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm13, %xmm4, %xmm1 +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm12 = [u,u,u,7,128,5,128,u,u,u,8,128,6,128,u,u] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm12, %xmm5, %xmm2 +; AVX512DQ-BW-FCP-NEXT: vpor %xmm1, %xmm2, %xmm1 +; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm2 = xmm4[8],xmm5[8],xmm4[9],xmm5[9],xmm4[10],xmm5[10],xmm4[11],xmm5[11],xmm4[12],xmm5[12],xmm4[13],xmm5[13],xmm4[14],xmm5[14],xmm4[15],xmm5[15] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm29, %xmm2, %xmm2 +; AVX512DQ-BW-FCP-NEXT: vinserti32x4 $2, %xmm2, %zmm1, %zmm3 +; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rdi), %xmm2 +; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%rsi), %xmm1 +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm11 = [u,128,7,128,5,u,u,u,128,8,128,6,u,u,u,128] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm11, %xmm1, %xmm29 +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm8 = [u,7,128,5,128,u,u,u,8,128,6,128,u,u,u,9] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm8, %xmm2, %xmm30 +; AVX512DQ-BW-FCP-NEXT: vporq %xmm29, %xmm30, %xmm29 +; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm30 = xmm1[8],xmm2[8],xmm1[9],xmm2[9],xmm1[10],xmm2[10],xmm1[11],xmm2[11],xmm1[12],xmm2[12],xmm1[13],xmm2[13],xmm1[14],xmm2[14],xmm1[15],xmm2[15] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm7, %xmm30, %xmm30 +; AVX512DQ-BW-FCP-NEXT: vinserti32x4 $2, %xmm30, %zmm29, %zmm29 ; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm3 = zmm3[0,1,0,1,4,5,4,5] +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm29 = zmm29[0,1,0,1,4,5,4,5] +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm3, %zmm29 {%k2} +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 32(%r9), %xmm30 +; AVX512DQ-BW-FCP-NEXT: vmovdqa 32(%r8), %xmm3 +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm10 = [128,4,u,u,u,128,7,128,5,u,u,u,128,8,128,6] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm10, %xmm30, %xmm0 +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm7 = [4,128,u,u,u,7,128,5,128,u,u,u,8,128,6,128] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm7, %xmm3, %xmm18 +; AVX512DQ-BW-FCP-NEXT: vporq %xmm0, %xmm18, %xmm0 +; AVX512DQ-BW-FCP-NEXT: vpunpckhbw {{.*#+}} xmm18 = xmm3[8],xmm30[8],xmm3[9],xmm30[9],xmm3[10],xmm30[10],xmm3[11],xmm30[11],xmm3[12],xmm30[12],xmm3[13],xmm30[13],xmm3[14],xmm30[14],xmm3[15],xmm30[15] +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} xmm18 = xmm18[u,6,7,2,3,u,u,u,8,9,4,5,u,u,u,10] +; AVX512DQ-BW-FCP-NEXT: vinserti32x4 $2, %xmm18, %zmm0, %zmm0 +; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm18 = [2,2,2,4,2,2,2,4,3,3,3,3,2,2,2,4,52,53,52,53,53,54,53,54,52,53,52,53,53,54,53,54] +; AVX512DQ-BW-FCP-NEXT: vpermi2w %zmm31, %zmm6, %zmm18 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm0 = zmm0[0,1,0,1,4,5,4,5] ; AVX512DQ-BW-FCP-NEXT: movabsq $290499906672591364, %rax # imm = 0x408102040810204 -; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k2 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm4, %zmm3 {%k2} +; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k3 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm18, %zmm0 {%k3} ; AVX512DQ-BW-FCP-NEXT: movabsq $-8714997200177740921, %rax # imm = 0x870E1C3870E1C387 -; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k2 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm3, %zmm23 {%k2} -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm11, %xmm15, %xmm3 -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm6, %xmm14, %xmm4 -; AVX512DQ-BW-FCP-NEXT: vpor %xmm3, %xmm4, %xmm3 -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm4 = xmm14[0],xmm15[0],xmm14[1],xmm15[1],xmm14[2],xmm15[2],xmm14[3],xmm15[3],xmm14[4],xmm15[4],xmm14[5],xmm15[5],xmm14[6],xmm15[6],xmm14[7],xmm15[7] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm18, %xmm4, %xmm4 -; AVX512DQ-BW-FCP-NEXT: vinserti32x4 $2, %xmm3, %zmm4, %zmm3 -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm2, %xmm17, %xmm2 -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm0, %xmm16, %xmm0 -; AVX512DQ-BW-FCP-NEXT: vpor %xmm2, %xmm0, %xmm0 -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm16[0],xmm17[0],xmm16[1],xmm17[1],xmm16[2],xmm17[2],xmm16[3],xmm17[3],xmm16[4],xmm17[4],xmm16[5],xmm17[5],xmm16[6],xmm17[6],xmm16[7],xmm17[7] -; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} xmm2 = xmm2[0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] -; AVX512DQ-BW-FCP-NEXT: vinserti32x4 $2, %xmm0, %zmm2, %zmm0 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm2 = zmm3[0,1,0,1,4,5,4,5] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm0 = zmm0[0,1,0,1,4,5,4,5] +; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k3 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm0, %zmm29 {%k3} +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm13, %xmm19, %xmm0 +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm12, %xmm17, %xmm6 +; AVX512DQ-BW-FCP-NEXT: vpor %xmm0, %xmm6, %xmm0 +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm6 = xmm17[0],xmm19[0],xmm17[1],xmm19[1],xmm17[2],xmm19[2],xmm17[3],xmm19[3],xmm17[4],xmm19[4],xmm17[5],xmm19[5],xmm17[6],xmm19[6],xmm17[7],xmm19[7] +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm12 = [4,5,0,1,u,u,u,6,7,2,3,u,u,u,8,9] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm12, %xmm6, %xmm6 +; AVX512DQ-BW-FCP-NEXT: vinserti32x4 $2, %xmm0, %zmm6, %zmm0 +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm11, %xmm22, %xmm6 +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm8, %xmm21, %xmm8 +; AVX512DQ-BW-FCP-NEXT: vpor %xmm6, %xmm8, %xmm6 +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm8 = xmm21[0],xmm22[0],xmm21[1],xmm22[1],xmm21[2],xmm22[2],xmm21[3],xmm22[3],xmm21[4],xmm22[4],xmm21[5],xmm22[5],xmm21[6],xmm22[6],xmm21[7],xmm22[7] +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm11 = [0,1,u,u,u,6,7,2,3,u,u,u,8,9,4,5] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm11, %xmm8, %xmm8 +; AVX512DQ-BW-FCP-NEXT: vinserti32x4 $2, %xmm6, %zmm8, %zmm6 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm8 = zmm0[0,1,0,1,4,5,4,5] +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm0 = zmm6[0,1,0,1,4,5,4,5] ; AVX512DQ-BW-FCP-NEXT: movabsq $871499720017774092, %rax # imm = 0xC183060C183060C -; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k2 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm2, %zmm0 {%k2} -; AVX512DQ-BW-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm3 # 16-byte Reload -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm1, %xmm3, %xmm1 -; AVX512DQ-BW-FCP-NEXT: vmovdqa {{[-0-9]+}}(%r{{[sb]}}p), %xmm4 # 16-byte Reload -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm7, %xmm4, %xmm2 -; AVX512DQ-BW-FCP-NEXT: vpor %xmm1, %xmm2, %xmm1 -; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm4[0],xmm3[0],xmm4[1],xmm3[1],xmm4[2],xmm3[2],xmm4[3],xmm3[3],xmm4[4],xmm3[4],xmm4[5],xmm3[5],xmm4[6],xmm3[6],xmm4[7],xmm3[7] -; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm19, %xmm2, %xmm2 -; AVX512DQ-BW-FCP-NEXT: vinserti32x4 $2, %xmm1, %zmm2, %zmm1 -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm1 = zmm1[0,1,0,1,4,5,4,5] -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, (%rsp), %zmm10, %zmm2 # 32-byte Folded Reload -; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm3 = [1,1,0,0,1,1,0,0,4,5,1,1,1,1,0,0,18,18,18,20,18,18,18,20,19,19,19,19,18,18,18,20] -; AVX512DQ-BW-FCP-NEXT: vpermw %zmm2, %zmm3, %zmm3 +; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k3 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm8, %zmm0 {%k3} +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm10, %xmm16, %xmm6 +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm7, %xmm15, %xmm7 +; AVX512DQ-BW-FCP-NEXT: vpor %xmm6, %xmm7, %xmm6 +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm7 = xmm15[0],xmm16[0],xmm15[1],xmm16[1],xmm15[2],xmm16[2],xmm15[3],xmm16[3],xmm15[4],xmm16[4],xmm15[5],xmm16[5],xmm15[6],xmm16[6],xmm15[7],xmm16[7] +; AVX512DQ-BW-FCP-NEXT: vmovdqa {{.*#+}} xmm10 = [u,u,4,5,0,1,u,u,u,6,7,2,3,u,u,u] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm10, %xmm7, %xmm7 +; AVX512DQ-BW-FCP-NEXT: vinserti32x4 $2, %xmm6, %zmm7, %zmm6 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm6 = zmm6[0,1,0,1,4,5,4,5] +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, (%rsp), %zmm31, %zmm8 # 32-byte Folded Reload +; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm7 = [1,1,0,0,1,1,0,0,4,5,1,1,1,1,0,0,18,18,18,20,18,18,18,20,19,19,19,19,18,18,18,20] +; AVX512DQ-BW-FCP-NEXT: vpermw %zmm8, %zmm7, %zmm7 ; AVX512DQ-BW-FCP-NEXT: movabsq $4647998506761461824, %rax # imm = 0x4081020408102040 -; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k2 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm3, %zmm1 {%k2} +; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k3 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm7, %zmm6 {%k3} ; AVX512DQ-BW-FCP-NEXT: movabsq $8133997386832558192, %rax # imm = 0x70E1C3870E1C3870 -; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k2 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm0 {%k2} -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm24, %zmm28, %zmm1 +; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k3 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm6, %zmm0 {%k3} +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm2[0],xmm1[0],xmm2[1],xmm1[1],xmm2[2],xmm1[2],xmm2[3],xmm1[3],xmm2[4],xmm1[4],xmm2[5],xmm1[5],xmm2[6],xmm1[6],xmm2[7],xmm1[7] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm11, %xmm1, %xmm1 +; AVX512DQ-BW-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm13 # 32-byte Reload +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm2 = ymm13[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,28,29,30],zero,ymm13[28],zero,ymm13[30,31,30,31],zero,ymm13[29],zero,ymm13[31,28,29] +; AVX512DQ-BW-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm15 # 32-byte Reload +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm6 = ymm15[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,ymm15[30],zero,ymm15[28],zero,zero,zero,zero,ymm15[31],zero,ymm15[29],zero,zero,zero +; AVX512DQ-BW-FCP-NEXT: vpor %ymm2, %ymm6, %ymm2 +; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm2[2,3,2,3],zmm1[0,1,0,1] +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm2 = xmm5[0],xmm4[0],xmm5[1],xmm4[1],xmm5[2],xmm4[2],xmm5[3],xmm4[3],xmm5[4],xmm4[4],xmm5[5],xmm4[5],xmm5[6],xmm4[6],xmm5[7],xmm4[7] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm12, %xmm2, %xmm2 +; AVX512DQ-BW-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm11 # 32-byte Reload +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm11[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,27],zero,zero,zero,zero,ymm11[30],zero,ymm11[28],zero,zero,zero,zero,ymm11[31],zero,ymm11[29],zero +; AVX512DQ-BW-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm7 # 32-byte Reload +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm5 = ymm7[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,ymm7[30],zero,ymm7[28],zero,zero,zero,zero,ymm7[31],zero,ymm7[29],zero,zero +; AVX512DQ-BW-FCP-NEXT: vpor %ymm4, %ymm5, %ymm4 +; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm2 = zmm4[2,3,2,3],zmm2[0,1,0,1] +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm2 {%k1} +; AVX512DQ-BW-FCP-NEXT: vpunpcklbw {{.*#+}} xmm1 = xmm3[0],xmm30[0],xmm3[1],xmm30[1],xmm3[2],xmm30[2],xmm3[3],xmm30[3],xmm3[4],xmm30[4],xmm3[5],xmm30[5],xmm3[6],xmm30[6],xmm3[7],xmm30[7] +; AVX512DQ-BW-FCP-NEXT: vpshufb %xmm10, %xmm1, %xmm1 +; AVX512DQ-BW-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm5 # 32-byte Reload +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm3 = ymm5[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,29],zero,ymm5[27],zero,zero,zero,zero,ymm5[30],zero,ymm5[28],zero,zero,zero,zero,ymm5[31],zero +; AVX512DQ-BW-FCP-NEXT: vmovdqu {{[-0-9]+}}(%r{{[sb]}}p), %ymm6 # 32-byte Reload +; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} ymm4 = ymm6[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,ymm6[27],zero,zero,zero,zero,ymm6[30],zero,ymm6[28],zero,zero,zero,zero,ymm6[31],zero,ymm6[29] +; AVX512DQ-BW-FCP-NEXT: vpor %ymm3, %ymm4, %ymm3 +; AVX512DQ-BW-FCP-NEXT: vshufi64x2 {{.*#+}} zmm1 = zmm3[2,3,2,3],zmm1[0,1,0,1] +; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm3 = [14,13,14,15,15,14,14,15,14,13,14,15,15,14,14,15,17,17,16,16,17,17,16,16,20,21,17,17,17,17,16,16] +; AVX512DQ-BW-FCP-NEXT: vpermw %zmm31, %zmm3, %zmm3 +; AVX512DQ-BW-FCP-NEXT: movabsq $580999813345182728, %rax # imm = 0x810204081020408 +; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k1 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm3, %zmm1 {%k1} +; AVX512DQ-BW-FCP-NEXT: movabsq $1016749673354069774, %rax # imm = 0xE1C3870E1C3870E +; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k1 +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm2 {%k1} +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm15, %zmm26, %zmm1 ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm1 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zmm1[18,19,20,21],zero,zmm1[19],zero,zmm1[21,20,21,22],zero,zmm1[20],zero,zmm1[22,23,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,57],zero,zmm1[55],zero,zero,zero,zero,zmm1[58],zero,zmm1[56],zero,zero,zero,zero,zmm1[59],zero -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm29, %zmm3 # 32-byte Folded Reload +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm13, %zmm27, %zmm3 ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm3 = zmm3[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm3[21],zero,zmm3[19],zero,zero,zero,zero,zmm3[22],zero,zmm3[20],zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zmm3[55],zero,zero,zero,zero,zmm3[58],zero,zmm3[56],zero,zero,zero,zero,zmm3[59],zero,zmm3[57] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm3 = zmm3[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-FCP-NEXT: vporq %zmm1, %zmm3, %zmm1 -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm26, %zmm3 # 32-byte Folded Reload +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm7, %zmm24, %zmm3 ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm3 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zmm3[18],zero,zmm3[18,19,20,21],zero,zmm3[19],zero,zmm3[25,26,27,22],zero,zmm3[20],zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zmm3[56,57],zero,zmm3[55],zero,zmm3[53,54,55,58],zero,zmm3[56],zero,zmm3[60,61,58,59] -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, {{[-0-9]+}}(%r{{[sb]}}p), %zmm25, %zmm4 # 32-byte Folded Reload +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm11, %zmm23, %zmm4 ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm4 = zmm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm4[18],zero,zero,zero,zero,zmm4[21],zero,zmm4[19],zero,zero,zero,zero,zmm4[22],zero,zmm4[20,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zmm4[57],zero,zmm4[55],zero,zero,zero,zero,zmm4[58],zero,zmm4[56],zero,zero,zero,zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm3 = zmm3[2,3,2,3,6,7,6,7] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm4 = zmm4[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-FCP-NEXT: vporq %zmm3, %zmm4, %zmm3 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm3 {%k1} -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm20, %zmm30, %zmm1 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm3 = zmm3[2,3,2,3,6,7,6,7] +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm3 {%k2} +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm6, %zmm28, %zmm1 ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm1 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zmm1[20],zero,zmm1[18],zero,zmm1[20,21,20,21],zero,zmm1[19],zero,zmm1[19,20,21,22],zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zmm1[56,57,56,57],zero,zmm1[55],zero,zmm1[55,56,57,58],zero,zmm1[56],zero,zmm1[62,63] -; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm21, %zmm27, %zmm4 +; AVX512DQ-BW-FCP-NEXT: vinserti64x4 $1, %ymm5, %zmm25, %zmm4 ; AVX512DQ-BW-FCP-NEXT: vpshufb {{.*#+}} zmm4 = zmm4[u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zmm4[20],zero,zmm4[18],zero,zero,zero,zero,zmm4[21],zero,zmm4[19],zero,zero,zero,zero,zmm4[22,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u,u],zero,zero,zero,zero,zmm4[57],zero,zmm4[55],zero,zero,zero,zero,zmm4[58],zero,zmm4[56],zero,zero -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] -; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm4 = zmm4[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-FCP-NEXT: vporq %zmm1, %zmm4, %zmm1 ; AVX512DQ-BW-FCP-NEXT: vpmovsxbw {{.*#+}} zmm4 = [10,9,9,10,10,9,9,10,9,10,14,15,10,9,9,10,27,29,28,27,28,29,29,28,27,29,28,27,28,29,29,28] -; AVX512DQ-BW-FCP-NEXT: vpermw %zmm2, %zmm4, %zmm2 +; AVX512DQ-BW-FCP-NEXT: vpermw %zmm8, %zmm4, %zmm4 +; AVX512DQ-BW-FCP-NEXT: vpermq {{.*#+}} zmm1 = zmm1[2,3,2,3,6,7,6,7] ; AVX512DQ-BW-FCP-NEXT: movabsq $1161999626690365456, %rax # imm = 0x1020408102040810 ; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k1 -; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm2, %zmm1 {%k1} +; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm4, %zmm1 {%k1} ; AVX512DQ-BW-FCP-NEXT: movabsq $2033499346708139548, %rax # imm = 0x1C3870E1C3870E1C ; AVX512DQ-BW-FCP-NEXT: kmovq %rax, %k1 ; AVX512DQ-BW-FCP-NEXT: vmovdqu8 %zmm1, %zmm3 {%k1} ; AVX512DQ-BW-FCP-NEXT: movq {{[0-9]+}}(%rsp), %rax ; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm3, 128(%rax) -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm12, 320(%rax) +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm9, 320(%rax) +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm2, 192(%rax) ; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm0, (%rax) -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm23, 256(%rax) -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm9, 192(%rax) -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm13, 64(%rax) -; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm22, 384(%rax) -; AVX512DQ-BW-FCP-NEXT: addq $40, %rsp +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm29, 256(%rax) +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm14, 64(%rax) +; AVX512DQ-BW-FCP-NEXT: vmovdqa64 %zmm20, 384(%rax) +; AVX512DQ-BW-FCP-NEXT: addq $104, %rsp ; AVX512DQ-BW-FCP-NEXT: vzeroupper ; AVX512DQ-BW-FCP-NEXT: retq %in.vec0 = load <64 x i8>, ptr %in.vecptr0, align 64 diff --git a/llvm/test/CodeGen/X86/vector-shuffle-512-v16.ll b/llvm/test/CodeGen/X86/vector-shuffle-512-v16.ll index dfa7f2dbdaeeecada707741b412e0879402f85d8..c981d973fef3eda51cd31e3f317963d2680a6006 100644 --- a/llvm/test/CodeGen/X86/vector-shuffle-512-v16.ll +++ b/llvm/test/CodeGen/X86/vector-shuffle-512-v16.ll @@ -177,6 +177,36 @@ define <16 x float> @shuffle_v16f32_02_03_16_17_06_07_20_21_10_11_24_25_14_15_28 ret <16 x float> %shuffle } +; PR86076 +define <16 x float> @shuffle_f32_v16f32_00_08_01_09_02_10_03_11_04_12_05_13_06_14_07_15(float %a0, float %a1) { +; ALL-LABEL: shuffle_f32_v16f32_00_08_01_09_02_10_03_11_04_12_05_13_06_14_07_15: +; ALL: # %bb.0: +; ALL-NEXT: vbroadcastss %xmm0, %ymm0 +; ALL-NEXT: vbroadcastss %xmm1, %ymm1 +; ALL-NEXT: vunpcklps {{.*#+}} ymm0 = ymm0[0],ymm1[0],ymm0[1],ymm1[1],ymm0[4],ymm1[4],ymm0[5],ymm1[5] +; ALL-NEXT: vinsertf64x4 $1, %ymm0, %zmm0, %zmm0 +; ALL-NEXT: retq + %v0 = insertelement <8 x float> poison, float %a0, i64 0 + %v1 = insertelement <8 x float> poison, float %a1, i64 0 + %b0 = shufflevector <8 x float> %v0, <8 x float> poison, <8 x i32> zeroinitializer + %b1 = shufflevector <8 x float> %v1, <8 x float> poison, <8 x i32> zeroinitializer + %r = shufflevector <8 x float> %b0, <8 x float> %b1, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15> + ret <16 x float> %r +} + +; PR86076 +define <16 x float> @shuffle_f32_v16f32_00_08_00_08_00_08_00_08_00_08_00_08_00_08_00_08(float %a0, float %a1) { +; ALL-LABEL: shuffle_f32_v16f32_00_08_00_08_00_08_00_08_00_08_00_08_00_08_00_08: +; ALL: # %bb.0: +; ALL-NEXT: vinsertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],zero,zero +; ALL-NEXT: vbroadcastsd %xmm0, %zmm0 +; ALL-NEXT: retq + %v0 = insertelement <8 x float> poison, float %a0, i64 0 + %v1 = insertelement <8 x float> poison, float %a1, i64 0 + %sv = shufflevector <8 x float> %v0, <8 x float> %v1, <16 x i32> <i32 0, i32 8, i32 0, i32 8, i32 0, i32 8, i32 0, i32 8, i32 0, i32 8, i32 0, i32 8, i32 0, i32 8, i32 0, i32 8> + ret <16 x float> %sv +} + define <16 x i32> @shuffle_v16i32_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00(<16 x i32> %a, <16 x i32> %b) { ; ALL-LABEL: shuffle_v16i32_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00: ; ALL: # %bb.0: diff --git a/llvm/test/CodeGen/X86/vpdpwssd.ll b/llvm/test/CodeGen/X86/vpdpwssd.ll new file mode 100644 index 0000000000000000000000000000000000000000..e6a07b4aeb2719af722a4ecd91bfd47af1e81987 --- /dev/null +++ b/llvm/test/CodeGen/X86/vpdpwssd.ll @@ -0,0 +1,12 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=znver4 | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512vnni,+fast-dpwssd | FileCheck %s + +define <16 x i32> @vpdpwssd_test(<16 x i32> %0, <16 x i32> %1, <16 x i32> %2) { +; CHECK-LABEL: vpdpwssd_test: +; CHECK: # %bb.0: +; CHECK-NEXT: vpdpwssd %zmm2, %zmm1, %zmm0 +; CHECK-NEXT: retq + %4 = tail call <16 x i32> @llvm.x86.avx512.vpdpwssd.512(<16 x i32> %0, <16 x i32> %1, <16 x i32> %2) + ret <16 x i32> %4 +} diff --git a/llvm/test/CodeGen/X86/widen_fadd.ll b/llvm/test/CodeGen/X86/widen_fadd.ll index 68f2ed4368044c9ad861e21f9e3298a8afe78c65..be249ddc0cca3a3d933ff3d7a9466c053ddf7eef 100644 --- a/llvm/test/CodeGen/X86/widen_fadd.ll +++ b/llvm/test/CodeGen/X86/widen_fadd.ll @@ -1,10 +1,10 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefixes=SSE ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse4.1 | FileCheck %s --check-prefixes=SSE -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefixes=AVX,AVX1OR2 -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=AVX,AVX1OR2 -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f | FileCheck %s --check-prefixes=AVX,AVX512F -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512vl | FileCheck %s --check-prefixes=AVX,AVX512VL +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefixes=AVX,AVX1OR2,AVX1 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=AVX,AVX1OR2,AVX2 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f | FileCheck %s --check-prefixes=AVX,AVX512,AVX512F +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512vl | FileCheck %s --check-prefixes=AVX,AVX512,AVX512VL define void @widen_fadd_v2f32_v4f32(ptr %a0, ptr %b0, ptr %c0) { ; SSE-LABEL: widen_fadd_v2f32_v4f32: @@ -364,3 +364,86 @@ define void @widen_fadd_v2f32_v16f32(ptr %a0, ptr %b0, ptr %c0) { store <2 x float> %vc14, ptr %c14, align 4 ret void } + +define <8 x float> @widen_fadd_v4f32_v8f32_const(<4 x float> %x, <4 x float> %y) { +; SSE-LABEL: widen_fadd_v4f32_v8f32_const: +; SSE: # %bb.0: +; SSE-NEXT: movaps {{.*#+}} xmm2 = [2.0E+0,2.0E+0,2.0E+0,2.0E+0] +; SSE-NEXT: addps %xmm2, %xmm0 +; SSE-NEXT: addps %xmm2, %xmm1 +; SSE-NEXT: retq +; +; AVX1-LABEL: widen_fadd_v4f32_v8f32_const: +; AVX1: # %bb.0: +; AVX1-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX1-NEXT: vaddps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: widen_fadd_v4f32_v8f32_const: +; AVX2: # %bb.0: +; AVX2-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0 +; AVX2-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX2-NEXT: vbroadcastss {{.*#+}} ymm1 = [2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0] +; AVX2-NEXT: vaddps %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: retq +; +; AVX512F-LABEL: widen_fadd_v4f32_v8f32_const: +; AVX512F: # %bb.0: +; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0 +; AVX512F-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX512F-NEXT: vbroadcastss {{.*#+}} ymm1 = [2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0] +; AVX512F-NEXT: vaddps %ymm1, %ymm0, %ymm0 +; AVX512F-NEXT: retq +; +; AVX512VL-LABEL: widen_fadd_v4f32_v8f32_const: +; AVX512VL: # %bb.0: +; AVX512VL-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0 +; AVX512VL-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX512VL-NEXT: vaddps {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm0, %ymm0 +; AVX512VL-NEXT: retq + %x2 = fadd <4 x float> %x, <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00> + %y2 = fadd <4 x float> %y, <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00> + %r = shufflevector <4 x float> %x2, <4 x float> %y2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> + ret <8 x float> %r +} + +define <16 x float> @widen_fadd_v4f32_v16f32_const(<4 x float> %x, <4 x float> %y, <4 x float> %z, <4 x float> %w) { +; SSE-LABEL: widen_fadd_v4f32_v16f32_const: +; SSE: # %bb.0: +; SSE-NEXT: movaps {{.*#+}} xmm4 = [2.0E+0,2.0E+0,2.0E+0,2.0E+0] +; SSE-NEXT: addps %xmm4, %xmm0 +; SSE-NEXT: addps %xmm4, %xmm1 +; SSE-NEXT: addps %xmm4, %xmm2 +; SSE-NEXT: addps %xmm4, %xmm3 +; SSE-NEXT: retq +; +; AVX1OR2-LABEL: widen_fadd_v4f32_v16f32_const: +; AVX1OR2: # %bb.0: +; AVX1OR2-NEXT: # kill: def $xmm2 killed $xmm2 def $ymm2 +; AVX1OR2-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0 +; AVX1OR2-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX1OR2-NEXT: vbroadcastss {{.*#+}} ymm1 = [2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0] +; AVX1OR2-NEXT: vaddps %ymm1, %ymm0, %ymm0 +; AVX1OR2-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 +; AVX1OR2-NEXT: vaddps %ymm1, %ymm2, %ymm1 +; AVX1OR2-NEXT: retq +; +; AVX512-LABEL: widen_fadd_v4f32_v16f32_const: +; AVX512: # %bb.0: +; AVX512-NEXT: # kill: def $xmm2 killed $xmm2 def $ymm2 +; AVX512-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0 +; AVX512-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 +; AVX512-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX512-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 +; AVX512-NEXT: vaddps {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm0, %zmm0 +; AVX512-NEXT: retq + %x2 = fadd <4 x float> %x, <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00> + %y2 = fadd <4 x float> %y, <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00> + %z2 = fadd <4 x float> %z, <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00> + %w2 = fadd <4 x float> %w, <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00> + %r0 = shufflevector <4 x float> %x2, <4 x float> %y2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> + %r1 = shufflevector <4 x float> %z2, <4 x float> %w2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> + %r = shufflevector <8 x float> %r0, <8 x float> %r1, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> + ret <16 x float> %r +} diff --git a/llvm/test/CodeGen/X86/widen_fmul.ll b/llvm/test/CodeGen/X86/widen_fmul.ll index ac208da9ee11a78b4b8072384d5ef41e9aa877da..9aa9d63e7fcbd079f6ba45f5bc5fcc7ff93b651c 100644 --- a/llvm/test/CodeGen/X86/widen_fmul.ll +++ b/llvm/test/CodeGen/X86/widen_fmul.ll @@ -1,10 +1,10 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefixes=SSE ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse4.1 | FileCheck %s --check-prefixes=SSE -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefixes=AVX,AVX1OR2 -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=AVX,AVX1OR2 -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f | FileCheck %s --check-prefixes=AVX,AVX512F -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512vl | FileCheck %s --check-prefixes=AVX,AVX512VL +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefixes=AVX,AVX1OR2,AVX1 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=AVX,AVX1OR2,AVX2 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f | FileCheck %s --check-prefixes=AVX,AVX512,AVX512F +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512vl | FileCheck %s --check-prefixes=AVX,AVX512,AVX512VL define void @widen_fmul_v2f32_v4f32(ptr %a0, ptr %b0, ptr %c0) { ; SSE-LABEL: widen_fmul_v2f32_v4f32: @@ -364,3 +364,86 @@ define void @widen_fmul_v2f32_v16f32(ptr %a0, ptr %b0, ptr %c0) { store <2 x float> %vc14, ptr %c14, align 4 ret void } + +define <8 x float> @widen_fmul_v4f32_v8f32_const(<4 x float> %x, <4 x float> %y) { +; SSE-LABEL: widen_fmul_v4f32_v8f32_const: +; SSE: # %bb.0: +; SSE-NEXT: movaps {{.*#+}} xmm2 = [3.0E+0,3.0E+0,3.0E+0,3.0E+0] +; SSE-NEXT: mulps %xmm2, %xmm0 +; SSE-NEXT: mulps %xmm2, %xmm1 +; SSE-NEXT: retq +; +; AVX1-LABEL: widen_fmul_v4f32_v8f32_const: +; AVX1: # %bb.0: +; AVX1-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX1-NEXT: vmulps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: widen_fmul_v4f32_v8f32_const: +; AVX2: # %bb.0: +; AVX2-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0 +; AVX2-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX2-NEXT: vbroadcastss {{.*#+}} ymm1 = [3.0E+0,3.0E+0,3.0E+0,3.0E+0,3.0E+0,3.0E+0,3.0E+0,3.0E+0] +; AVX2-NEXT: vmulps %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: retq +; +; AVX512F-LABEL: widen_fmul_v4f32_v8f32_const: +; AVX512F: # %bb.0: +; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0 +; AVX512F-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX512F-NEXT: vbroadcastss {{.*#+}} ymm1 = [3.0E+0,3.0E+0,3.0E+0,3.0E+0,3.0E+0,3.0E+0,3.0E+0,3.0E+0] +; AVX512F-NEXT: vmulps %ymm1, %ymm0, %ymm0 +; AVX512F-NEXT: retq +; +; AVX512VL-LABEL: widen_fmul_v4f32_v8f32_const: +; AVX512VL: # %bb.0: +; AVX512VL-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0 +; AVX512VL-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX512VL-NEXT: vmulps {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm0, %ymm0 +; AVX512VL-NEXT: retq + %x2 = fmul <4 x float> %x, <float 3.000000e+00, float 3.000000e+00, float 3.000000e+00, float 3.000000e+00> + %y2 = fmul <4 x float> %y, <float 3.000000e+00, float 3.000000e+00, float 3.000000e+00, float 3.000000e+00> + %r = shufflevector <4 x float> %x2, <4 x float> %y2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> + ret <8 x float> %r +} + +define <16 x float> @widen_fmul_v4f32_v16f32_const(<4 x float> %x, <4 x float> %y, <4 x float> %z, <4 x float> %w) { +; SSE-LABEL: widen_fmul_v4f32_v16f32_const: +; SSE: # %bb.0: +; SSE-NEXT: movaps {{.*#+}} xmm4 = [3.0E+0,3.0E+0,3.0E+0,3.0E+0] +; SSE-NEXT: mulps %xmm4, %xmm0 +; SSE-NEXT: mulps %xmm4, %xmm1 +; SSE-NEXT: mulps %xmm4, %xmm2 +; SSE-NEXT: mulps %xmm4, %xmm3 +; SSE-NEXT: retq +; +; AVX1OR2-LABEL: widen_fmul_v4f32_v16f32_const: +; AVX1OR2: # %bb.0: +; AVX1OR2-NEXT: # kill: def $xmm2 killed $xmm2 def $ymm2 +; AVX1OR2-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0 +; AVX1OR2-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX1OR2-NEXT: vbroadcastss {{.*#+}} ymm1 = [3.0E+0,3.0E+0,3.0E+0,3.0E+0,3.0E+0,3.0E+0,3.0E+0,3.0E+0] +; AVX1OR2-NEXT: vmulps %ymm1, %ymm0, %ymm0 +; AVX1OR2-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 +; AVX1OR2-NEXT: vmulps %ymm1, %ymm2, %ymm1 +; AVX1OR2-NEXT: retq +; +; AVX512-LABEL: widen_fmul_v4f32_v16f32_const: +; AVX512: # %bb.0: +; AVX512-NEXT: # kill: def $xmm2 killed $xmm2 def $ymm2 +; AVX512-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0 +; AVX512-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 +; AVX512-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX512-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 +; AVX512-NEXT: vmulps {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm0, %zmm0 +; AVX512-NEXT: retq + %x2 = fmul <4 x float> %x, <float 3.000000e+00, float 3.000000e+00, float 3.000000e+00, float 3.000000e+00> + %y2 = fmul <4 x float> %y, <float 3.000000e+00, float 3.000000e+00, float 3.000000e+00, float 3.000000e+00> + %z2 = fmul <4 x float> %z, <float 3.000000e+00, float 3.000000e+00, float 3.000000e+00, float 3.000000e+00> + %w2 = fmul <4 x float> %w, <float 3.000000e+00, float 3.000000e+00, float 3.000000e+00, float 3.000000e+00> + %r0 = shufflevector <4 x float> %x2, <4 x float> %y2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> + %r1 = shufflevector <4 x float> %z2, <4 x float> %w2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> + %r = shufflevector <8 x float> %r0, <8 x float> %r1, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> + ret <16 x float> %r +} diff --git a/llvm/test/CodeGen/X86/widen_fsub.ll b/llvm/test/CodeGen/X86/widen_fsub.ll index 90cf455ba61fc6670ee810713d5f5e1d89197119..60e54ab71abcfffcc453d1ce23a4aad0a3104889 100644 --- a/llvm/test/CodeGen/X86/widen_fsub.ll +++ b/llvm/test/CodeGen/X86/widen_fsub.ll @@ -1,10 +1,10 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefixes=SSE ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse4.1 | FileCheck %s --check-prefixes=SSE -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefixes=AVX,AVX1OR2 -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=AVX,AVX1OR2 -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f | FileCheck %s --check-prefixes=AVX,AVX512F -; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512vl | FileCheck %s --check-prefixes=AVX,AVX512VL +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefixes=AVX,AVX1OR2,AVX1 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=AVX,AVX1OR2,AVX2 +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f | FileCheck %s --check-prefixes=AVX,AVX512,AVX512F +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512vl | FileCheck %s --check-prefixes=AVX,AVX512,AVX512VL define void @widen_fsub_v2f32_v4f32(ptr %a0, ptr %b0, ptr %c0) { ; SSE-LABEL: widen_fsub_v2f32_v4f32: @@ -364,3 +364,86 @@ define void @widen_fsub_v2f32_v16f32(ptr %a0, ptr %b0, ptr %c0) { store <2 x float> %vc14, ptr %c14, align 4 ret void } + +define <8 x float> @widen_fsub_v4f32_v8f32_const(<4 x float> %x, <4 x float> %y) { +; SSE-LABEL: widen_fsub_v4f32_v8f32_const: +; SSE: # %bb.0: +; SSE-NEXT: movaps {{.*#+}} xmm2 = [2.0E+0,2.0E+0,2.0E+0,2.0E+0] +; SSE-NEXT: subps %xmm2, %xmm0 +; SSE-NEXT: subps %xmm2, %xmm1 +; SSE-NEXT: retq +; +; AVX1-LABEL: widen_fsub_v4f32_v8f32_const: +; AVX1: # %bb.0: +; AVX1-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0 +; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX1-NEXT: vaddps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm0, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: widen_fsub_v4f32_v8f32_const: +; AVX2: # %bb.0: +; AVX2-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0 +; AVX2-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX2-NEXT: vbroadcastss {{.*#+}} ymm1 = [-2.0E+0,-2.0E+0,-2.0E+0,-2.0E+0,-2.0E+0,-2.0E+0,-2.0E+0,-2.0E+0] +; AVX2-NEXT: vaddps %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: retq +; +; AVX512F-LABEL: widen_fsub_v4f32_v8f32_const: +; AVX512F: # %bb.0: +; AVX512F-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0 +; AVX512F-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX512F-NEXT: vbroadcastss {{.*#+}} ymm1 = [-2.0E+0,-2.0E+0,-2.0E+0,-2.0E+0,-2.0E+0,-2.0E+0,-2.0E+0,-2.0E+0] +; AVX512F-NEXT: vaddps %ymm1, %ymm0, %ymm0 +; AVX512F-NEXT: retq +; +; AVX512VL-LABEL: widen_fsub_v4f32_v8f32_const: +; AVX512VL: # %bb.0: +; AVX512VL-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0 +; AVX512VL-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX512VL-NEXT: vaddps {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to8}, %ymm0, %ymm0 +; AVX512VL-NEXT: retq + %x2 = fsub <4 x float> %x, <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00> + %y2 = fsub <4 x float> %y, <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00> + %r = shufflevector <4 x float> %x2, <4 x float> %y2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> + ret <8 x float> %r +} + +define <16 x float> @widen_fsub_v4f32_v16f32_const(<4 x float> %x, <4 x float> %y, <4 x float> %z, <4 x float> %w) { +; SSE-LABEL: widen_fsub_v4f32_v16f32_const: +; SSE: # %bb.0: +; SSE-NEXT: movaps {{.*#+}} xmm4 = [2.0E+0,2.0E+0,2.0E+0,2.0E+0] +; SSE-NEXT: subps %xmm4, %xmm0 +; SSE-NEXT: subps %xmm4, %xmm1 +; SSE-NEXT: subps %xmm4, %xmm2 +; SSE-NEXT: subps %xmm4, %xmm3 +; SSE-NEXT: retq +; +; AVX1OR2-LABEL: widen_fsub_v4f32_v16f32_const: +; AVX1OR2: # %bb.0: +; AVX1OR2-NEXT: # kill: def $xmm2 killed $xmm2 def $ymm2 +; AVX1OR2-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0 +; AVX1OR2-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX1OR2-NEXT: vbroadcastss {{.*#+}} ymm1 = [-2.0E+0,-2.0E+0,-2.0E+0,-2.0E+0,-2.0E+0,-2.0E+0,-2.0E+0,-2.0E+0] +; AVX1OR2-NEXT: vaddps %ymm1, %ymm0, %ymm0 +; AVX1OR2-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 +; AVX1OR2-NEXT: vaddps %ymm1, %ymm2, %ymm1 +; AVX1OR2-NEXT: retq +; +; AVX512-LABEL: widen_fsub_v4f32_v16f32_const: +; AVX512: # %bb.0: +; AVX512-NEXT: # kill: def $xmm2 killed $xmm2 def $ymm2 +; AVX512-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0 +; AVX512-NEXT: vinsertf128 $1, %xmm3, %ymm2, %ymm2 +; AVX512-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; AVX512-NEXT: vinsertf64x4 $1, %ymm2, %zmm0, %zmm0 +; AVX512-NEXT: vaddps {{\.?LCPI[0-9]+_[0-9]+}}(%rip){1to16}, %zmm0, %zmm0 +; AVX512-NEXT: retq + %x2 = fsub <4 x float> %x, <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00> + %y2 = fsub <4 x float> %y, <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00> + %z2 = fsub <4 x float> %z, <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00> + %w2 = fsub <4 x float> %w, <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00> + %r0 = shufflevector <4 x float> %x2, <4 x float> %y2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> + %r1 = shufflevector <4 x float> %z2, <4 x float> %w2, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> + %r = shufflevector <8 x float> %r0, <8 x float> %r1, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> + ret <16 x float> %r +} diff --git a/llvm/test/DebugInfo/AArch64/ptrauth.ll b/llvm/test/DebugInfo/AArch64/ptrauth.ll new file mode 100644 index 0000000000000000000000000000000000000000..5d9099f05704ba313bf166488bb7f18401de43c6 --- /dev/null +++ b/llvm/test/DebugInfo/AArch64/ptrauth.ll @@ -0,0 +1,70 @@ +; RUN: llc %s -filetype=obj -mtriple arm64e-apple-darwin -o - \ +; RUN: | llvm-dwarfdump - | FileCheck %s + +; CHECK: DW_AT_type (0x{{0+}}[[TY:.*]] "void *__ptrauth(4, 0, 0x04d2)") +; CHECK: 0x{{0+}}[[TY]]: DW_TAG_LLVM_ptrauth_type +; CHECK-NEXT: DW_AT_type {{.*}}"void *" +; CHECK-NEXT: DW_AT_LLVM_ptrauth_key (0x04) +; CHECK-NEXT: DW_AT_LLVM_ptrauth_extra_discriminator (0x04d2) + +; CHECK: DW_AT_type (0x{{0+}}[[TY:.*]] "void *__ptrauth(4, 1, 0x04d3)") +; CHECK: 0x{{0+}}[[TY]]: DW_TAG_LLVM_ptrauth_type +; CHECK-NEXT: DW_AT_type {{.*}}"void *" +; CHECK-NEXT: DW_AT_LLVM_ptrauth_key (0x04) +; CHECK-NEXT: DW_AT_LLVM_ptrauth_address_discriminated (true) +; CHECK-NEXT: DW_AT_LLVM_ptrauth_extra_discriminator (0x04d3) + +; CHECK: DW_AT_type (0x{{0+}}[[TY:.*]] "void *__ptrauth(4, 1, 0x04d4, "isa-pointer")") +; CHECK: 0x{{0+}}[[TY]]: DW_TAG_LLVM_ptrauth_type +; CHECK-NEXT: DW_AT_type {{.*}}"void *" +; CHECK-NEXT: DW_AT_LLVM_ptrauth_key (0x04) +; CHECK-NEXT: DW_AT_LLVM_ptrauth_address_discriminated (true) +; CHECK-NEXT: DW_AT_LLVM_ptrauth_extra_discriminator (0x04d4) +; CHECK-NEXT: DW_AT_LLVM_ptrauth_isa_pointer (true) + +; CHECK: DW_AT_type (0x{{0+}}[[TY:.*]] "void *__ptrauth(4, 1, 0x04d5, "authenticates-null-values")") +; CHECK: 0x{{0+}}[[TY]]: DW_TAG_LLVM_ptrauth_type +; CHECK-NEXT: DW_AT_type {{.*}}"void *" +; CHECK-NEXT: DW_AT_LLVM_ptrauth_key (0x04) +; CHECK-NEXT: DW_AT_LLVM_ptrauth_address_discriminated (true) +; CHECK-NEXT: DW_AT_LLVM_ptrauth_extra_discriminator (0x04d5) +; CHECK-NEXT: DW_AT_LLVM_ptrauth_authenticates_null_values (true) + +; CHECK: DW_AT_type (0x{{0+}}[[TY:.*]] "void *__ptrauth(4, 1, 0x04d6, "isa-pointer,authenticates-null-values")") +; CHECK: 0x{{0+}}[[TY]]: DW_TAG_LLVM_ptrauth_type +; CHECK-NEXT: DW_AT_type {{.*}}"void *" +; CHECK-NEXT: DW_AT_LLVM_ptrauth_key (0x04) +; CHECK-NEXT: DW_AT_LLVM_ptrauth_address_discriminated (true) +; CHECK-NEXT: DW_AT_LLVM_ptrauth_extra_discriminator (0x04d6) +; CHECK-NEXT: DW_AT_LLVM_ptrauth_isa_pointer (true) +; CHECK-NEXT: DW_AT_LLVM_ptrauth_authenticates_null_values (true) + +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + +@p = global ptr null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!10} +!llvm.module.flags = !{!19, !20} + +!0 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression()) +!1 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!2 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression()) +!3 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression()) +!4 = !DIGlobalVariableExpression(var: !9, expr: !DIExpression()) +!5 = distinct !DIGlobalVariable(name: "p1", scope: !10, file: !11, line: 1, type: !14, isLocal: false, isDefinition: true) +!6 = distinct !DIGlobalVariable(name: "p2", scope: !10, file: !11, line: 1, type: !15, isLocal: false, isDefinition: true) +!7 = distinct !DIGlobalVariable(name: "p3", scope: !10, file: !11, line: 1, type: !16, isLocal: false, isDefinition: true) +!8 = distinct !DIGlobalVariable(name: "p4", scope: !10, file: !11, line: 1, type: !17, isLocal: false, isDefinition: true) +!9 = distinct !DIGlobalVariable(name: "p5", scope: !10, file: !11, line: 1, type: !18, isLocal: false, isDefinition: true) +!10 = distinct !DICompileUnit(language: DW_LANG_C99, file: !11, emissionKind: FullDebug, globals: !13) +!11 = !DIFile(filename: "/tmp/p.c", directory: "/") +!12 = !{} +!13 = !{!0,!1,!2,!3,!4} +!14 = !DIDerivedType(tag: DW_TAG_LLVM_ptrauth_type, baseType: !21, ptrAuthKey: 4, ptrAuthIsAddressDiscriminated: false, ptrAuthExtraDiscriminator: 1234) +!15 = !DIDerivedType(tag: DW_TAG_LLVM_ptrauth_type, baseType: !21, ptrAuthKey: 4, ptrAuthIsAddressDiscriminated: true, ptrAuthExtraDiscriminator: 1235) +!16 = !DIDerivedType(tag: DW_TAG_LLVM_ptrauth_type, baseType: !21, ptrAuthKey: 4, ptrAuthIsAddressDiscriminated: true, ptrAuthExtraDiscriminator: 1236, ptrAuthIsaPointer: true) +!17 = !DIDerivedType(tag: DW_TAG_LLVM_ptrauth_type, baseType: !21, ptrAuthKey: 4, ptrAuthIsAddressDiscriminated: true, ptrAuthExtraDiscriminator: 1237, ptrAuthAuthenticatesNullValues: true) +!18 = !DIDerivedType(tag: DW_TAG_LLVM_ptrauth_type, baseType: !21, ptrAuthKey: 4, ptrAuthIsAddressDiscriminated: true, ptrAuthExtraDiscriminator: 1238, ptrAuthIsaPointer: true, ptrAuthAuthenticatesNullValues: true) +!19 = !{i32 2, !"Dwarf Version", i32 4} +!20 = !{i32 2, !"Debug Info Version", i32 3} +!21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null) diff --git a/llvm/test/DebugInfo/ARM/hardware-loop-phi-insertion.ll b/llvm/test/DebugInfo/ARM/hardware-loop-phi-insertion.ll new file mode 100644 index 0000000000000000000000000000000000000000..9240bf25b6f63ff7ddadb3f241e387a545cfd0c2 --- /dev/null +++ b/llvm/test/DebugInfo/ARM/hardware-loop-phi-insertion.ll @@ -0,0 +1,84 @@ +; RUN: llc --stop-after=hardware-loops < %s | FileCheck %s + +;; Tests that Hardware Loop Insertion does not insert new phi nodes after debug +;; records when they appear immediately after the last existing phi node. + +; CHECK-LABEL: for.body: +; CHECK-NEXT: = phi i32 +; CHECK-NEXT: = phi i32 +; CHECK-NEXT: call void @llvm.dbg.value + +source_filename = "repro.c" +target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" +target triple = "thumbv8.1m.main-arm-none-eabi" + +@z = dso_local local_unnamed_addr global i32 42, align 4, !dbg !0 +@arr = dso_local local_unnamed_addr global [10 x i32] zeroinitializer, align 4, !dbg !5 + +define dso_local void @func1() local_unnamed_addr #0 !dbg !18 { +entry: + %0 = load i32, ptr @z, align 4, !tbaa !26 + br label %for.body, !dbg !30 + +for.body: ; preds = %entry, %for.body + %p1.04 = phi ptr [ @arr, %entry ], [ %incdec.ptr, %for.body ] + %i.03 = phi i32 [ 0, %entry ], [ %inc, %for.body ] + tail call void @llvm.dbg.value(metadata ptr %p1.04, metadata !23, metadata !DIExpression()), !dbg !25 + store i32 %0, ptr %p1.04, align 4, !dbg !32, !tbaa !26 + %inc = add nuw nsw i32 %i.03, 1, !dbg !34 + %incdec.ptr = getelementptr inbounds i8, ptr %p1.04, i32 4, !dbg !35 + %exitcond.not = icmp eq i32 %inc, 10, !dbg !36 + br i1 %exitcond.not, label %for.end, label %for.body, !dbg !30, !llvm.loop !37 + +for.end: ; preds = %for.body + ret void, !dbg !41 +} + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!11, !12, !13, !14, !15, !16} +!llvm.ident = !{!17} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "z", scope: !2, file: !3, line: 2, type: !8, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C11, file: !3, producer: "clang version 19.0.0git", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "repro.c", directory: "/home/gbtozers/dev/upstream-llvm") +!4 = !{!0, !5} +!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression()) +!6 = distinct !DIGlobalVariable(name: "arr", scope: !2, file: !3, line: 1, type: !7, isLocal: false, isDefinition: true) +!7 = !DICompositeType(tag: DW_TAG_array_type, baseType: !8, size: 320, elements: !9) +!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!9 = !{!10} +!10 = !DISubrange(count: 10) +!11 = !{i32 7, !"Dwarf Version", i32 5} +!12 = !{i32 2, !"Debug Info Version", i32 3} +!13 = !{i32 1, !"wchar_size", i32 4} +!14 = !{i32 1, !"min_enum_size", i32 4} +!15 = !{i32 7, !"frame-pointer", i32 2} +!16 = !{i32 7, !"debug-info-assignment-tracking", i1 true} +!17 = !{!"clang version 19.0.0git"} +!18 = distinct !DISubprogram(name: "func1", scope: !3, file: !3, line: 4, type: !19, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !21) +!19 = !DISubroutineType(types: !20) +!20 = !{null} +!21 = !{!23} +!22 = !DILocalVariable(name: "i", scope: !18, file: !3, line: 6, type: !8) +!23 = !DILocalVariable(name: "p1", scope: !18, file: !3, line: 7, type: !24) +!24 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 32) +!25 = !DILocation(line: 0, scope: !18) +!26 = !{!27, !27, i64 0} +!27 = !{!"int", !28, i64 0} +!28 = !{!"omnipotent char", !29, i64 0} +!29 = !{!"Simple C/C++ TBAA"} +!30 = !DILocation(line: 8, column: 3, scope: !31) +!31 = distinct !DILexicalBlock(scope: !18, file: !3, line: 8, column: 3) +!32 = !DILocation(line: 9, column: 10, scope: !33) +!33 = distinct !DILexicalBlock(scope: !31, file: !3, line: 8, column: 3) +!34 = !DILocation(line: 8, column: 27, scope: !33) +!35 = !DILocation(line: 8, column: 32, scope: !33) +!36 = !DILocation(line: 8, column: 21, scope: !33) +!37 = distinct !{!37, !30, !38, !39, !40} +!38 = !DILocation(line: 9, column: 12, scope: !31) +!39 = !{!"llvm.loop.mustprogress"} +!40 = !{!"llvm.loop.unroll.disable"} +!41 = !DILocation(line: 10, column: 1, scope: !18) diff --git a/llvm/test/DebugInfo/MIR/InstrRef/memory-operand-folding-tieddef.mir b/llvm/test/DebugInfo/MIR/InstrRef/memory-operand-folding-tieddef.mir index cece656d08978c71c6780d3d892997d74bad1b81..5ebd1a89ae92176fa47c8ab90c7b62ac1bf3ea57 100644 --- a/llvm/test/DebugInfo/MIR/InstrRef/memory-operand-folding-tieddef.mir +++ b/llvm/test/DebugInfo/MIR/InstrRef/memory-operand-folding-tieddef.mir @@ -100,6 +100,7 @@ registers: - { id: 38, class: gr8 } frameInfo: maxAlignment: 1 + adjustsStack: true hasCalls: true machineFunctionInfo: {} body: | diff --git a/llvm/test/DebugInfo/MIR/InstrRef/memory-operand-load-folding.mir b/llvm/test/DebugInfo/MIR/InstrRef/memory-operand-load-folding.mir index f0af93804048316beff5d986ba744ec314f88672..b0bff30c4c8206b249b6a5fa348836539b453b7c 100644 --- a/llvm/test/DebugInfo/MIR/InstrRef/memory-operand-load-folding.mir +++ b/llvm/test/DebugInfo/MIR/InstrRef/memory-operand-load-folding.mir @@ -87,6 +87,7 @@ liveins: - { reg: '$edi', virtual-reg: '%0' } - { reg: '$xmm0', virtual-reg: '%1' } frameInfo: + adjustsStack: true hasCalls: true body: | bb.0.if.then: diff --git a/llvm/test/DebugInfo/MIR/InstrRef/phi-coalesce-subreg.mir b/llvm/test/DebugInfo/MIR/InstrRef/phi-coalesce-subreg.mir index 51d3f7e1a6a4eff8850be85c2e822467ced7a2f9..d73d8a3759061576a575c00dfc39ed7032272ab6 100644 --- a/llvm/test/DebugInfo/MIR/InstrRef/phi-coalesce-subreg.mir +++ b/llvm/test/DebugInfo/MIR/InstrRef/phi-coalesce-subreg.mir @@ -97,6 +97,7 @@ liveins: - { reg: '$esi', virtual-reg: '%4' } frameInfo: maxAlignment: 1 + adjustsStack: true hasCalls: true machineFunctionInfo: {} body: | diff --git a/llvm/test/DebugInfo/MIR/InstrRef/phi-coalescing.mir b/llvm/test/DebugInfo/MIR/InstrRef/phi-coalescing.mir index bc1c7ebac6cef814540e13cb228d2fb4c0c9f206..6460263c6025a8ee12d8a3ce46b4096a44d2ca6b 100644 --- a/llvm/test/DebugInfo/MIR/InstrRef/phi-coalescing.mir +++ b/llvm/test/DebugInfo/MIR/InstrRef/phi-coalescing.mir @@ -106,6 +106,7 @@ liveins: - { reg: '$rsi', virtual-reg: '%5' } frameInfo: maxAlignment: 1 + adjustsStack: true hasCalls: true machineFunctionInfo: {} body: | diff --git a/llvm/test/DebugInfo/MIR/InstrRef/phi-on-stack-coalesced.mir b/llvm/test/DebugInfo/MIR/InstrRef/phi-on-stack-coalesced.mir index d59333e73fbce8ac94da6ae10673d0a14af18e1a..68c9bf6c89dde23975b8efabe2f3cd912d9010de 100644 --- a/llvm/test/DebugInfo/MIR/InstrRef/phi-on-stack-coalesced.mir +++ b/llvm/test/DebugInfo/MIR/InstrRef/phi-on-stack-coalesced.mir @@ -70,6 +70,7 @@ liveins: - { reg: '$esi', virtual-reg: '%2' } frameInfo: maxAlignment: 1 + adjustsStack: true hasCalls: true machineFunctionInfo: {} body: | diff --git a/llvm/test/DebugInfo/MIR/InstrRef/phi-on-stack-coalesced2.mir b/llvm/test/DebugInfo/MIR/InstrRef/phi-on-stack-coalesced2.mir index ab2647d3b45a1560976d3579345bb4e9f71cad6d..cf17af4ba43080a4ccad29136a3c731fa402db50 100644 --- a/llvm/test/DebugInfo/MIR/InstrRef/phi-on-stack-coalesced2.mir +++ b/llvm/test/DebugInfo/MIR/InstrRef/phi-on-stack-coalesced2.mir @@ -71,6 +71,7 @@ liveins: - { reg: '$esi', virtual-reg: '%2' } frameInfo: maxAlignment: 1 + adjustsStack: true hasCalls: true machineFunctionInfo: {} body: | diff --git a/llvm/test/DebugInfo/MIR/InstrRef/phi-regallocd-to-stack.mir b/llvm/test/DebugInfo/MIR/InstrRef/phi-regallocd-to-stack.mir index 0fe80980e4e6ff864533eedb01a839444de85009..cb35bd892eea585de0aab01edaec1778b0002e3c 100644 --- a/llvm/test/DebugInfo/MIR/InstrRef/phi-regallocd-to-stack.mir +++ b/llvm/test/DebugInfo/MIR/InstrRef/phi-regallocd-to-stack.mir @@ -65,6 +65,7 @@ liveins: - { reg: '$esi', virtual-reg: '%2' } frameInfo: maxAlignment: 1 + adjustsStack: true hasCalls: true machineFunctionInfo: {} body: | diff --git a/llvm/test/DebugInfo/MIR/InstrRef/phi-through-regalloc.mir b/llvm/test/DebugInfo/MIR/InstrRef/phi-through-regalloc.mir index 2a031b295a1e11ce06c9c96ea8fb016f6c9fc5db..61dcec49b74cd724eca27d3622d17c022833ffbf 100644 --- a/llvm/test/DebugInfo/MIR/InstrRef/phi-through-regalloc.mir +++ b/llvm/test/DebugInfo/MIR/InstrRef/phi-through-regalloc.mir @@ -94,6 +94,7 @@ liveins: - { reg: '$esi', virtual-reg: '%2' } frameInfo: maxAlignment: 1 + adjustsStack: true hasCalls: true machineFunctionInfo: {} body: | diff --git a/llvm/test/DebugInfo/MIR/InstrRef/stack-coloring-dbg-phi.mir b/llvm/test/DebugInfo/MIR/InstrRef/stack-coloring-dbg-phi.mir index 47a7b460e43ef0023640baf722f88ad39231c007..e80ed2e3e8eb3fa1f624a105dd9af7e84fb9139a 100644 --- a/llvm/test/DebugInfo/MIR/InstrRef/stack-coloring-dbg-phi.mir +++ b/llvm/test/DebugInfo/MIR/InstrRef/stack-coloring-dbg-phi.mir @@ -106,6 +106,7 @@ liveins: - { reg: '$rdi', virtual-reg: '%15' } frameInfo: maxAlignment: 8 + adjustsStack: true hasCalls: true stack: - { id: 0, size: 8, alignment: 8 } diff --git a/llvm/test/DebugInfo/MIR/InstrRef/survives-livedebugvars.mir b/llvm/test/DebugInfo/MIR/InstrRef/survives-livedebugvars.mir index 3e806e43ca9e67624ff3a1aa676da4c28f5bc708..6dbd2cd4faa712ddf858889e46fb775ae99dc245 100644 --- a/llvm/test/DebugInfo/MIR/InstrRef/survives-livedebugvars.mir +++ b/llvm/test/DebugInfo/MIR/InstrRef/survives-livedebugvars.mir @@ -113,6 +113,7 @@ liveins: - { reg: '$rdi', virtual-reg: '%2' } - { reg: '$esi', virtual-reg: '%4' } frameInfo: + adjustsStack: true hasCalls: true machineFunctionInfo: {} body: | diff --git a/llvm/test/DebugInfo/MIR/Mips/livedebugvars-stop-trimming-loc.mir b/llvm/test/DebugInfo/MIR/Mips/livedebugvars-stop-trimming-loc.mir index 35ab906efc904288b6458efd4c1a969fc8bbdc4f..5df70096e9305d11dba311d2559c3ea2b5bbe20d 100644 --- a/llvm/test/DebugInfo/MIR/Mips/livedebugvars-stop-trimming-loc.mir +++ b/llvm/test/DebugInfo/MIR/Mips/livedebugvars-stop-trimming-loc.mir @@ -72,6 +72,8 @@ name: fn2 alignment: 4 tracksRegLiveness: true +frameInfo: + adjustsStack: true registers: - { id: 0, class: gpr32, preferred-register: '' } - { id: 1, class: gpr32, preferred-register: '' } diff --git a/llvm/test/DebugInfo/MIR/X86/debug-loc-0.mir b/llvm/test/DebugInfo/MIR/X86/debug-loc-0.mir index 56a4d835aaa5971d125ba145b5d25bb8dfd7f55a..0b007456be1e6fe0a47b1117324131f33288e130 100644 --- a/llvm/test/DebugInfo/MIR/X86/debug-loc-0.mir +++ b/llvm/test/DebugInfo/MIR/X86/debug-loc-0.mir @@ -75,7 +75,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 8 - adjustsStack: false + adjustsStack: true hasCalls: true stackProtector: '' maxCallFrameSize: 4294967295 diff --git a/llvm/test/DebugInfo/MIR/X86/live-debug-vars-unused-arg-debugonly.mir b/llvm/test/DebugInfo/MIR/X86/live-debug-vars-unused-arg-debugonly.mir index 3cb9da8fdfe3b8c28487203468a013d5571707e5..4d48774a78dd719542d58d09921cc0957a44fe26 100644 --- a/llvm/test/DebugInfo/MIR/X86/live-debug-vars-unused-arg-debugonly.mir +++ b/llvm/test/DebugInfo/MIR/X86/live-debug-vars-unused-arg-debugonly.mir @@ -116,7 +116,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 0 - adjustsStack: false + adjustsStack: true hasCalls: true stackProtector: '' maxCallFrameSize: 4294967295 diff --git a/llvm/test/DebugInfo/MIR/X86/live-debug-vars-unused-arg.mir b/llvm/test/DebugInfo/MIR/X86/live-debug-vars-unused-arg.mir index 35d12b52af896c22e08afe1fdc32315130e525ff..e618f48f527b8853e134ed0646ac2a814a4b3db8 100644 --- a/llvm/test/DebugInfo/MIR/X86/live-debug-vars-unused-arg.mir +++ b/llvm/test/DebugInfo/MIR/X86/live-debug-vars-unused-arg.mir @@ -114,7 +114,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 0 - adjustsStack: false + adjustsStack: true hasCalls: true stackProtector: '' maxCallFrameSize: 4294967295 diff --git a/llvm/test/DebugInfo/MIR/X86/livedebugvars-crossbb-interval.mir b/llvm/test/DebugInfo/MIR/X86/livedebugvars-crossbb-interval.mir index 037306a2ca95ede7f2876b6442cf9cb297a989e5..42ee73dde96592620c581441e77d5fc949cc98f9 100644 --- a/llvm/test/DebugInfo/MIR/X86/livedebugvars-crossbb-interval.mir +++ b/llvm/test/DebugInfo/MIR/X86/livedebugvars-crossbb-interval.mir @@ -100,6 +100,7 @@ liveins: - { reg: '$rdi', virtual-reg: '%2' } - { reg: '$esi', virtual-reg: '%4' } frameInfo: + adjustsStack: true hasCalls: true machineFunctionInfo: {} body: | diff --git a/llvm/test/DebugInfo/MIR/X86/prolog-epilog-indirection.mir b/llvm/test/DebugInfo/MIR/X86/prolog-epilog-indirection.mir index 6941467fe0e4a387ad1de4870940783194b9f509..4df967ce034939c165542e4502ca373a96cb3172 100644 --- a/llvm/test/DebugInfo/MIR/X86/prolog-epilog-indirection.mir +++ b/llvm/test/DebugInfo/MIR/X86/prolog-epilog-indirection.mir @@ -104,6 +104,7 @@ alignment: 16 tracksRegLiveness: true frameInfo: maxAlignment: 4 + adjustsStack: true hasCalls: true stack: - { id: 0, name: l_1081, type: default, offset: 0, size: 4, alignment: 4, diff --git a/llvm/test/DebugInfo/NVPTX/no-extra-loc.ll b/llvm/test/DebugInfo/NVPTX/no-extra-loc.ll new file mode 100644 index 0000000000000000000000000000000000000000..6d3a69beffe87592e9a2e5ae748e8b3940139337 --- /dev/null +++ b/llvm/test/DebugInfo/NVPTX/no-extra-loc.ll @@ -0,0 +1,26 @@ +; RUN: llc < %s -mtriple=nvptx64-nvidia-cuda | FileCheck %s +; RUN: %if ptxas %{ llc < %s -mtriple=nvptx64-nvidia-cuda | %ptxas-verify %} + + +define i32 @foo(i32 %a, i32 %b) !dbg !3 { + +; CHECK: .loc [[FILE:[0-9]+]] 26 0 // extra-lineinfo.cu:26:0 +; CHECK-NOT: .loc [[FILE]] 26 0 // extra-lineinfo.cu:26:0 +; CHECK: .file [[FILE]] "/test/directory/extra-lineinfo.cu" + + %add = add i32 %b, %a, !dbg !6 + ret i32 %add, !dbg !6 +} + +!llvm.dbg.cu = !{!0} +!nvvm.annotations = !{} +!llvm.module.flags = !{!2} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: DebugDirectivesOnly) +!1 = !DIFile(filename: "extra-lineinfo.cu", directory: "/test/directory/") +!2 = !{i32 1, !"Debug Info Version", i32 3} +!3 = distinct !DISubprogram(name: "kernel", linkageName: "foo", scope: !1, file: !1, line: 123, type: !4, scopeLine: 26, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!4 = !DISubroutineType(types: !5) +!5 = !{} +!6 = !DILocation(line: 40, column: 22, scope: !31) +!31 = distinct !DILexicalBlock(scope: !3, file: !1, line: 3, column: 17) diff --git a/llvm/test/DebugInfo/X86/dbg-value-funcarg-duplicates.ll b/llvm/test/DebugInfo/X86/dbg-value-funcarg-duplicates.ll new file mode 100644 index 0000000000000000000000000000000000000000..e61b7256345ca544eb911636accb278f9746d477 --- /dev/null +++ b/llvm/test/DebugInfo/X86/dbg-value-funcarg-duplicates.ll @@ -0,0 +1,65 @@ +; RUN: llc -mtriple=x86_64-unknown-linux-gnu -start-after=codegenprepare -stop-before=finalize-isel -o - %s -experimental-debug-variable-locations=false | FileCheck %s + +; Input to this test was created by reducing a Swift file using bugpoint + +; CHECK-DAG: ![[LHS:.*]] = !DILocalVariable(name: "lhs" + +define hidden i64 @"_wideDivide42"(ptr %0, ptr %1, ptr %2, i64 %3, i64 %4, i64 %5, i64 %6, i64 %7, i64 %8) local_unnamed_addr !dbg !16 { +; CHECK-LABEL: name: _wideDivide42 +; CHECK-NOT: DBG_VALUE +; CHECK: DBG_VALUE $rcx, $noreg, ![[LHS]], !DIExpression(DW_OP_LLVM_fragment, 0, 64) +; CHECK-NEXT: DBG_VALUE $r8, $noreg, ![[LHS]], !DIExpression(DW_OP_LLVM_fragment, 64, 64) +; CHECK-NEXT: DBG_VALUE $r9, $noreg, ![[LHS]], !DIExpression(DW_OP_LLVM_fragment, 128, 64) +; CHECK-NEXT: DBG_VALUE %fixed-stack.{{.+}}, ![[LHS]], !DIExpression(DW_OP_LLVM_fragment, 192, 64) +; The duplicates should be removed: +; CHECK-NOT: DBG_VALUE + +entry: + %9 = alloca i64, align 8 + call void @llvm.dbg.value(metadata i64 %3, metadata !24, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64)), !dbg !67 + call void @llvm.dbg.value(metadata i64 %4, metadata !24, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 64)), !dbg !67 + call void @llvm.dbg.value(metadata i64 %3, metadata !24, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64)), !dbg !67 + call void @llvm.dbg.value(metadata i64 %4, metadata !24, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 64)), !dbg !67 + call void @llvm.dbg.value(metadata i64 %5, metadata !24, metadata !DIExpression(DW_OP_LLVM_fragment, 128, 64)), !dbg !67 + call void @llvm.dbg.value(metadata i64 %6, metadata !24, metadata !DIExpression(DW_OP_LLVM_fragment, 192, 64)), !dbg !67 + br i1 poison, label %11, label %10, !dbg !68 + +10: ; preds = %entry + tail call void asm sideeffect "", "n"(i32 7) #7 + unreachable + +11: ; preds = %entry + tail call void @abort() + unreachable +} + +declare void @abort() + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +attributes #7 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!13} +!llvm.linker.options = !{!14, !15} + +!0 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !1, producer: "Swift", isOptimized: true, runtimeVersion: 6, emissionKind: FullDebug) +!1 = !DIFile(filename: "Int128.swift", directory: "") +!13 = !{i32 2, !"Debug Info Version", i32 3} +!14 = !{!"-lswiftCore"} +!15 = !{!"-lobjc"} +!16 = distinct !DISubprogram(name: "_wideDivide42", scope: !0, file: !1, line: 222, type: !17, scopeLine: 222, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !23) +!17 = !DISubroutineType(types: !18) +!18 = !{!19, !20, !20, !20, !20, !20, !20} +!19 = !DICompositeType(tag: DW_TAG_structure_type, name: "4 x UInt64", flags: DIFlagFwdDecl, runtimeLang: DW_LANG_Swift) +!20 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "UInt64", scope: !1, file: !1, size: 64, elements: !22, runtimeLang: DW_LANG_Swift) +!22 = !{} +!23 = !{!24, !27} +!24 = !DILocalVariable(name: "lhs", arg: 1, scope: !16, file: !1, line: 223, type: !25, flags: DIFlagArtificial) +!25 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !26) +!26 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "2 x 2 x UInt64", file: !1, size: 256, elements: !22, runtimeLang: DW_LANG_Swift) +!27 = !DILocalVariable(name: "rhs", arg: 2, scope: !16, file: !1, line: 223, type: !28, flags: DIFlagArtificial) +!28 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !29) +!29 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "2 x UInt64", file: !1, size: 128, elements: !22, runtimeLang: DW_LANG_Swift) +!67 = !DILocation(line: 0, scope: !16) +!68 = !DILocation(line: 225, column: 9, scope: !16) diff --git a/llvm/test/DebugInfo/X86/live-debug-vars-dse.mir b/llvm/test/DebugInfo/X86/live-debug-vars-dse.mir index 9443ed5e332c134befded3677c5a9d473ca9819f..908889063584c2d189b4936e0422fc0aae4c864b 100644 --- a/llvm/test/DebugInfo/X86/live-debug-vars-dse.mir +++ b/llvm/test/DebugInfo/X86/live-debug-vars-dse.mir @@ -107,7 +107,7 @@ frameInfo: stackSize: 0 offsetAdjustment: 0 maxAlignment: 8 - adjustsStack: false + adjustsStack: true hasCalls: true stackProtector: '' maxCallFrameSize: 4294967295 diff --git a/llvm/test/DebugInfo/X86/live-debug-vars-intervals.mir b/llvm/test/DebugInfo/X86/live-debug-vars-intervals.mir index c5b6d7381ace9aaec3ab06aaadab6225c54b5363..3beaf8996e4f07b6e6afb48a9532ef3103f0a277 100644 --- a/llvm/test/DebugInfo/X86/live-debug-vars-intervals.mir +++ b/llvm/test/DebugInfo/X86/live-debug-vars-intervals.mir @@ -99,6 +99,8 @@ --- name: f1 tracksRegLiveness: true +frameInfo: + adjustsStack: true stack: - { id: 0, name: x.addr, type: default, offset: 0, size: 4, alignment: 4, stack-id: default, callee-saved-register: '', callee-saved-restored: true, @@ -127,6 +129,8 @@ body: | --- name: f2 tracksRegLiveness: true +frameInfo: + adjustsStack: true stack: - { id: 0, name: x.addr, type: default, offset: 0, size: 4, alignment: 4, stack-id: default, callee-saved-register: '', callee-saved-restored: true, diff --git a/llvm/test/DebugInfo/X86/prolog-params.mir b/llvm/test/DebugInfo/X86/prolog-params.mir index af21bc85ccd746ed8bda0d30b37755ef37eafd81..6629dca810f9542d5dbb38355305dbc292579d23 100644 --- a/llvm/test/DebugInfo/X86/prolog-params.mir +++ b/llvm/test/DebugInfo/X86/prolog-params.mir @@ -98,6 +98,8 @@ fixedStack: isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true } - { id: 2, type: default, offset: 0, size: 4, alignment: 16, stack-id: default, isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true } +frameInfo: + adjustsStack: true stack: - { id: 0, name: arr, type: default, offset: 0, size: 8, alignment: 4, stack-id: default, callee-saved-register: '', callee-saved-restored: true } diff --git a/llvm/test/DebugInfo/X86/tu-to-non-tu.ll b/llvm/test/DebugInfo/X86/tu-to-non-tu.ll index 3ad97adbb5adafc4a0b9244fd54a144b5428c35f..f80bd8b978963e64cef769d03f597499122d08a4 100644 --- a/llvm/test/DebugInfo/X86/tu-to-non-tu.ll +++ b/llvm/test/DebugInfo/X86/tu-to-non-tu.ll @@ -156,14 +156,14 @@ %struct.templ_non_tu.1 = type { ptr } @_ZTV6non_tu = dso_local unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI6non_tu, ptr @_ZN6non_tu2f1Ev] }, align 8 -@v1 = dso_local global { { ptr } } { { ptr } { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV6non_tu, i32 0, inrange i32 0, i32 2) } }, align 8, !dbg !0 +@v1 = dso_local global { { ptr } } { { ptr } { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV6non_tu, i32 0, i32 0, i32 2) } }, align 8, !dbg !0 @v5 = dso_local global %struct.ref_internal zeroinitializer, align 1, !dbg !5 @_ZTV12templ_non_tuIiE = dso_local unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI12templ_non_tuIiE, ptr @_ZN12templ_non_tuIiE2f1Ev] }, align 8 -@v2 = dso_local global { { ptr } } { { ptr } { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV12templ_non_tuIiE, i32 0, inrange i32 0, i32 2) } }, align 8, !dbg !13 +@v2 = dso_local global { { ptr } } { { ptr } { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV12templ_non_tuIiE, i32 0, i32 0, i32 2) } }, align 8, !dbg !13 @_ZTV12templ_non_tuIlE = dso_local unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI12templ_non_tuIlE, ptr @_ZN12templ_non_tuIlE2f1Ev] }, align 8 -@v3 = dso_local global { { ptr } } { { ptr } { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV12templ_non_tuIlE, i32 0, inrange i32 0, i32 2) } }, align 8, !dbg !32 +@v3 = dso_local global { { ptr } } { { ptr } { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV12templ_non_tuIlE, i32 0, i32 0, i32 2) } }, align 8, !dbg !32 @_ZTV12templ_non_tuIbE = dso_local unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI12templ_non_tuIbE, ptr @_ZN12templ_non_tuIbE2f1Ev] }, align 8 -@v4 = dso_local global { { ptr } } { { ptr } { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV12templ_non_tuIbE, i32 0, inrange i32 0, i32 2) } }, align 8, !dbg !46 +@v4 = dso_local global { { ptr } } { { ptr } { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV12templ_non_tuIbE, i32 0, i32 0, i32 2) } }, align 8, !dbg !46 @v6 = dso_local global %class.ref_internal_template zeroinitializer, align 1, !dbg !60 @v7 = dso_local global %class.ref_from_ref_internal_template zeroinitializer, align 1, !dbg !69 @_ZTVN10__cxxabiv117__class_type_infoE = external dso_local global ptr diff --git a/llvm/test/DebugInfo/dpvalue-print-nocrash.ll b/llvm/test/DebugInfo/dpvalue-print-nocrash.ll index 0a618c6780d1d8b3cc560ac0c4a177efdc5e8321..d8cb542285c89b16eb4b5fb10686482929476ad0 100755 --- a/llvm/test/DebugInfo/dpvalue-print-nocrash.ll +++ b/llvm/test/DebugInfo/dpvalue-print-nocrash.ll @@ -1,4 +1,4 @@ -;; Tests that we can debug-print DPValues that have no markers attached. +;; Tests that we can debug-print DbgVariableRecords that have no markers attached. ; RUN: opt -passes="instcombine" -debug %s -o /dev/null 2>&1 | FileCheck %s ; REQUIRES: asserts diff --git a/llvm/test/DebugInfo/print-non-instruction-debug-info.ll b/llvm/test/DebugInfo/print-non-instruction-debug-info.ll index 2e765619fcb8964fcb894e88f3225db90036e902..490f24ff76ff56830c16684577407ae2a93e10db 100644 --- a/llvm/test/DebugInfo/print-non-instruction-debug-info.ll +++ b/llvm/test/DebugInfo/print-non-instruction-debug-info.ll @@ -26,6 +26,8 @@ ; CHECK-NEXT: {{^}} store i32 %[[VAL_ADD]]{{.+}}, !DIAssignID ![[ASSIGNID:[0-9]+]] ; OLDDBG-NEXT: call void @llvm.dbg.assign(metadata i32 %[[VAL_ADD]], metadata ![[VAR_B]], metadata !DIExpression(), metadata ![[ASSIGNID]], metadata ptr %[[VAL_B]], metadata !DIExpression()), !dbg ![[LOC_4:[0-9]+]] ; NEWDBG-NEXT: {{^}} #dbg_assign(i32 %[[VAL_ADD]], ![[VAR_B]], !DIExpression(), ![[ASSIGNID]], ptr %[[VAL_B]], !DIExpression(), ![[LOC_4:[0-9]+]]) +; OLDDBG-NEXT: call void @llvm.dbg.assign(metadata ![[EMPTY:[0-9]+]], metadata ![[VAR_B]], metadata !DIExpression(), metadata ![[ASSIGNID]], metadata ![[EMPTY]], metadata !DIExpression()), !dbg ![[LOC_4]] +; NEWDBG-NEXT: {{^}} #dbg_assign(![[EMPTY:[0-9]+]], ![[VAR_B]], !DIExpression(), ![[ASSIGNID]], ![[EMPTY]], !DIExpression(), ![[LOC_4]]) ; CHECK-NEXT: {{^}} ret i32 ; OLDDBG-DAG: declare void @llvm.dbg.value @@ -40,6 +42,7 @@ ; CHECK-DAG: ![[LOC_3]] = !DILocation(line: 3, column: 25 ; CHECK-DAG: ![[LOC_4]] = !DILocation(line: 3, column: 30 ; CHECK-DAG: ![[LABEL_ID]] = !DILabel( +; CHECK-DAG: ![[EMPTY]] = !{} define dso_local i32 @f(i32 %a) !dbg !7 { entry: @@ -51,6 +54,7 @@ entry: call void @llvm.dbg.label(metadata !50), !dbg !32 store i32 %add, ptr %b, !dbg !32, !DIAssignID !40 call void @llvm.dbg.assign(metadata i32 %add, metadata !21, metadata !DIExpression(), metadata !40, metadata ptr %b, metadata !DIExpression()), !dbg !33 + call void @llvm.dbg.assign(metadata !2, metadata !21, metadata !DIExpression(), metadata !40, metadata !2, metadata !DIExpression()), !dbg !33 ret i32 %add, !dbg !33 } diff --git a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_section_start_and_stop_symbols.s b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_section_start_and_stop_symbols.s new file mode 100644 index 0000000000000000000000000000000000000000..f8e7ba96f006847e813f316a73da5b5c15dc66dd --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_section_start_and_stop_symbols.s @@ -0,0 +1,43 @@ +# RUN: llvm-mc -triple=aarch64-unknown-linux-gnu -position-independent \ +# RUN: -filetype=obj -o %t.o %s +# RUN: llvm-jitlink -noexec -check %s %t.o + + .text + .file "elf_section_start_stop.c" + .globl main + .p2align 2 + .type main,@function +main: + adrp x8, z + adrp x9, y + ldr w8, [x8, :lo12:z] + ldr w9, [x9, :lo12:y] + sub w0, w8, w9 + ret +.Lfunc_end0: + .size main, .Lfunc_end0-main + + .type x,@object + .section custom_section,"aw",@progbits + .globl x + .p2align 2 +x: + .word 42 + .size x, 4 + +# jitlink-check: *{8}z = (*{8}y) + 4 + + .type y,@object + .data + .globl y + .p2align 3, 0x0 +y: + .xword __start_custom_section + .size y, 8 + + .type z,@object + .globl z + .p2align 3, 0x0 +z: + .xword __stop_custom_section + .size z, 8 diff --git a/llvm/test/ExecutionEngine/JITLink/AArch64/MachO_section_start_and_stop_symbols.s b/llvm/test/ExecutionEngine/JITLink/AArch64/MachO_section_start_and_stop_symbols.s new file mode 100644 index 0000000000000000000000000000000000000000..8862dd8a28fa542b9562da22862546401bda5dab --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/AArch64/MachO_section_start_and_stop_symbols.s @@ -0,0 +1,30 @@ +# RUN: llvm-mc -triple=arm64-apple-darwin24 -filetype=obj -o %t.o %s +# RUN: llvm-jitlink -noexec -check %s %t.o + +# jitlink-check: *{8}_z = (*{8}_y) + 4 + + .section __TEXT,__text,regular,pure_instructions + .globl _main + .p2align 2 +_main: + mov w0, #0 + ret + + .section __DATA,__custom_section + .globl _x + .p2align 2, 0x0 +_x: + .long 42 + + .section __DATA,__data + .globl _y + .p2align 3, 0x0 +_y: + .quad section$start$__DATA$__custom_section + + .globl _z + .p2align 3, 0x0 +_z: + .quad section$end$__DATA$__custom_section + +.subsections_via_symbols diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll b/llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll new file mode 100644 index 0000000000000000000000000000000000000000..f9040afd1c0166b09f97ce6f8e17a33aa312c514 --- /dev/null +++ b/llvm/test/Instrumentation/HWAddressSanitizer/globals-access.ll @@ -0,0 +1,46 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --global-value-regex "x" --version 4 +; RUN: opt < %s -S -passes=hwasan -mtriple=aarch64-linux-gnu -hwasan-globals=0 | FileCheck %s --check-prefixes=NOGLOB +; RUN: opt < %s -S -passes=hwasan -mtriple=aarch64-linux-gnu -hwasan-globals=1 | FileCheck %s + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" + +@x = dso_local global i32 0, align 4 + +;. +; NOGLOB: @x = dso_local global i32 0, align 4 +;. +; CHECK: @x = alias i32, inttoptr (i64 add (i64 ptrtoint (ptr @x.hwasan to i64), i64 5260204364768739328) to ptr) +;. +define dso_local noundef i32 @_Z3tmpv() sanitize_hwaddress { +; NOGLOB-LABEL: define dso_local noundef i32 @_Z3tmpv( +; NOGLOB-SAME: ) #[[ATTR0:[0-9]+]] { +; NOGLOB-NEXT: entry: +; NOGLOB-NEXT: [[TMP0:%.*]] = load i32, ptr @x, align 4 +; NOGLOB-NEXT: ret i32 [[TMP0]] +; +; CHECK-LABEL: define dso_local noundef i32 @_Z3tmpv( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP12:%.*]] = load i64, ptr @__hwasan_tls, align 8 +; CHECK-NEXT: [[TMP1:%.*]] = or i64 [[TMP12]], 4294967295 +; CHECK-NEXT: [[HWASAN_SHADOW:%.*]] = add i64 [[TMP1]], 1 +; CHECK-NEXT: [[TMP2:%.*]] = inttoptr i64 [[HWASAN_SHADOW]] to ptr +; CHECK-NEXT: [[TMP3:%.*]] = lshr i64 ptrtoint (ptr @x to i64), 56 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i64 [[TMP3]] to i8 +; CHECK-NEXT: [[TMP5:%.*]] = and i64 ptrtoint (ptr @x to i64), 72057594037927935 +; CHECK-NEXT: [[TMP6:%.*]] = lshr i64 [[TMP5]], 4 +; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP2]], i64 [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = load i8, ptr [[TMP7]], align 1 +; CHECK-NEXT: [[TMP9:%.*]] = icmp ne i8 [[TMP4]], [[TMP8]] +; CHECK-NEXT: br i1 [[TMP9]], label [[TMP10:%.*]], label [[TMP11:%.*]], !prof [[PROF2:![0-9]+]] +; CHECK: 10: +; CHECK-NEXT: call void @llvm.hwasan.check.memaccess.shortgranules(ptr [[TMP2]], ptr @x, i32 2) +; CHECK-NEXT: br label [[TMP11]] +; CHECK: 11: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @x, align 4 +; CHECK-NEXT: ret i32 [[TMP0]] +; +entry: + %0 = load i32, ptr @x, align 4 + ret i32 %0 +} diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope-setjmp.ll b/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope-setjmp.ll index 4bb846bff27456c9c4d99bf30c6045c57471208b..62fd7a1671569382bc26b155041f7e5d31ba5b1d 100644 --- a/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope-setjmp.ll +++ b/llvm/test/Instrumentation/HWAddressSanitizer/use-after-scope-setjmp.ll @@ -48,13 +48,12 @@ define dso_local noundef i1 @_Z6targetv() sanitize_hwaddress { ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP26]], i8 [[TMP22]], i64 256, i1 false) ; CHECK-NEXT: [[CALL:%.*]] = call i32 @setjmp(ptr noundef @jbuf) ; CHECK-NEXT: switch i32 [[CALL]], label [[WHILE_BODY:%.*]] [ -; CHECK-NEXT: i32 1, label [[RETURN:%.*]] -; CHECK-NEXT: i32 2, label [[SW_BB1:%.*]] +; CHECK-NEXT: i32 1, label [[RETURN:%.*]] +; CHECK-NEXT: i32 2, label [[SW_BB1:%.*]] ; CHECK-NEXT: ] ; CHECK: sw.bb1: ; CHECK-NEXT: br label [[RETURN]] ; CHECK: while.body: -; CHECK-NEXT: call void @llvm.hwasan.check.memaccess(ptr [[TMP16]], ptr @stackbuf, i32 19) ; CHECK-NEXT: store ptr [[BUF_HWASAN]], ptr @stackbuf, align 8 ; CHECK-NEXT: call void @may_jump() ; CHECK-NEXT: br label [[RETURN]] diff --git a/llvm/test/Instrumentation/InstrProfiling/Coro/coro-split-musttail6.ll b/llvm/test/Instrumentation/InstrProfiling/Coro/coro-split-musttail6.ll index 5d068872fcace07933f00a7c7df9bf4f0be92cbd..4359d5305d4d91cdb8a55bfd39faff9203507f87 100644 --- a/llvm/test/Instrumentation/InstrProfiling/Coro/coro-split-musttail6.ll +++ b/llvm/test/Instrumentation/InstrProfiling/Coro/coro-split-musttail6.ll @@ -85,7 +85,6 @@ exit: ret void } -; FIXME: The fakeresume1 here should be marked as musttail. ; Verify that in the resume part resume call is marked with musttail. ; CHECK-LABEL: @f.resume( ; CHECK: musttail call fastcc void @fakeresume1(ptr align 8 null) diff --git a/llvm/test/Instrumentation/InstrProfiling/Coro/coro-split-musttail7.ll b/llvm/test/Instrumentation/InstrProfiling/Coro/coro-split-musttail7.ll index 6ea81c6ff0b0961883a6651bb27da2993d5e2e09..2a14be0f921806e7c380f9cb4f3d30f170df15f5 100644 --- a/llvm/test/Instrumentation/InstrProfiling/Coro/coro-split-musttail7.ll +++ b/llvm/test/Instrumentation/InstrProfiling/Coro/coro-split-musttail7.ll @@ -88,7 +88,6 @@ exit: ret void } -; FIXME: The fakeresume1 here should be marked as musttail. ; Verify that in the resume part resume call is marked with musttail. ; CHECK-LABEL: @f.resume( ; CHECK: musttail call fastcc void @fakeresume1(ptr align 8 null) diff --git a/llvm/test/Instrumentation/MemorySanitizer/AArch64/vararg_shadow.ll b/llvm/test/Instrumentation/MemorySanitizer/AArch64/vararg_shadow.ll index 96ac4b6088c31c81e908387871dc5c10e74a83f5..9133b329deb2634e76f33a66fe45e58388efa368 100644 --- a/llvm/test/Instrumentation/MemorySanitizer/AArch64/vararg_shadow.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/AArch64/vararg_shadow.ll @@ -758,7 +758,7 @@ define linkonce_odr dso_local void @_Z5test2IcEvT_iz(i8 noundef %t, i32 noundef ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 193514046488576 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 32, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 0 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -808,7 +808,7 @@ define linkonce_odr dso_local void @_Z5test2IcEvT_iz(i8 noundef %t, i32 noundef ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP52]], ptr align 16 [[TMP53]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -851,7 +851,7 @@ define linkonce_odr dso_local void @_Z5test2IiEvT_iz(i32 noundef %t, i32 noundef ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 193514046488576 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 32, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 0 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -901,7 +901,7 @@ define linkonce_odr dso_local void @_Z5test2IiEvT_iz(i32 noundef %t, i32 noundef ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP52]], ptr align 16 [[TMP53]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -936,7 +936,7 @@ define linkonce_odr dso_local void @_Z5test2IfEvT_iz(float noundef %t, i32 nound ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 193514046488576 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 32, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 0 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -986,7 +986,7 @@ define linkonce_odr dso_local void @_Z5test2IfEvT_iz(float noundef %t, i32 nound ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP52]], ptr align 16 [[TMP53]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -1021,7 +1021,7 @@ define linkonce_odr dso_local void @_Z5test2IdEvT_iz(double noundef %t, i32 noun ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 193514046488576 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 32, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 0 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -1071,7 +1071,7 @@ define linkonce_odr dso_local void @_Z5test2IdEvT_iz(double noundef %t, i32 noun ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP52]], ptr align 16 [[TMP53]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -1106,7 +1106,7 @@ define linkonce_odr dso_local void @_Z5test2IeEvT_iz(fp128 noundef %t, i32 nound ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 193514046488576 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 32, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 0 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -1156,7 +1156,7 @@ define linkonce_odr dso_local void @_Z5test2IeEvT_iz(fp128 noundef %t, i32 nound ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP52]], ptr align 16 [[TMP53]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -1191,7 +1191,7 @@ define linkonce_odr dso_local void @_Z5test2I6IntIntEvT_iz(i64 %t.coerce, i32 no ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 193514046488576 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 32, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 0 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -1241,7 +1241,7 @@ define linkonce_odr dso_local void @_Z5test2I6IntIntEvT_iz(i64 %t.coerce, i32 no ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP52]], ptr align 16 [[TMP53]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -1276,7 +1276,7 @@ define linkonce_odr dso_local void @_Z5test2I10Int64Int64EvT_iz([2 x i64] %t.coe ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 193514046488576 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 32, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 0 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -1326,7 +1326,7 @@ define linkonce_odr dso_local void @_Z5test2I10Int64Int64EvT_iz([2 x i64] %t.coe ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP52]], ptr align 16 [[TMP53]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -1361,7 +1361,7 @@ define linkonce_odr dso_local void @_Z5test2I12DoubleDoubleEvT_iz([2 x double] a ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 193514046488576 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 32, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 0 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -1411,7 +1411,7 @@ define linkonce_odr dso_local void @_Z5test2I12DoubleDoubleEvT_iz([2 x double] a ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP52]], ptr align 16 [[TMP53]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -1446,7 +1446,7 @@ define linkonce_odr dso_local void @_Z5test2I7Double4EvT_iz([4 x double] alignst ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 193514046488576 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 32, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 0 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -1496,7 +1496,7 @@ define linkonce_odr dso_local void @_Z5test2I7Double4EvT_iz([4 x double] alignst ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP52]], ptr align 16 [[TMP53]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -1531,7 +1531,7 @@ define linkonce_odr dso_local void @_Z5test2I11DoubleFloatEvT_iz([2 x i64] %t.co ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 193514046488576 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 32, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 0 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -1581,7 +1581,7 @@ define linkonce_odr dso_local void @_Z5test2I11DoubleFloatEvT_iz([2 x i64] %t.co ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP52]], ptr align 16 [[TMP53]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -1616,7 +1616,7 @@ define linkonce_odr dso_local void @_Z5test2I11LongDouble2EvT_iz([2 x fp128] ali ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 193514046488576 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 32, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 0 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -1666,7 +1666,7 @@ define linkonce_odr dso_local void @_Z5test2I11LongDouble2EvT_iz([2 x fp128] ali ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP52]], ptr align 16 [[TMP53]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -1701,7 +1701,7 @@ define linkonce_odr dso_local void @_Z5test2I11LongDouble4EvT_iz([4 x fp128] ali ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 193514046488576 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 32, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 0 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -1751,7 +1751,7 @@ define linkonce_odr dso_local void @_Z5test2I11LongDouble4EvT_iz([4 x fp128] ali ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP52]], ptr align 16 [[TMP53]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg-kernel.ll b/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg-kernel.ll index 1535fccfc21107ab077ae59693a371efaf8a440d..e0b5907719afcb0eac965723d58971ab1bcbe8a2 100644 --- a/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg-kernel.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/SystemZ/vararg-kernel.ll @@ -39,7 +39,7 @@ define i64 @foo(i64 %guard, ...) #1 { ; Only 56 bytes of the register save area is copied, because of ; "use-soft-float". -; CHECK: call void @llvm.va_start(ptr %vl) +; CHECK: call void @llvm.va_start.p0(ptr %vl) ; CHECK: [[VlAddr:%.*]] = ptrtoint ptr %vl to i64 ; CHECK: [[RegSaveAreaAddrAddr:%.*]] = add i64 [[VlAddr]], 24 ; CHECK: [[RegSaveAreaAddr:%.*]] = inttoptr i64 [[RegSaveAreaAddrAddr]] to ptr diff --git a/llvm/test/Instrumentation/MemorySanitizer/X86/vararg_shadow.ll b/llvm/test/Instrumentation/MemorySanitizer/X86/vararg_shadow.ll index aff4d2c55ad6fccc5d393f09c29f7664b9bea6fa..205101564dfe0993be5386931becda455618fede 100644 --- a/llvm/test/Instrumentation/MemorySanitizer/X86/vararg_shadow.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/X86/vararg_shadow.ll @@ -560,7 +560,7 @@ define linkonce_odr dso_local void @_Z5test2IcEvT_iz(i8 noundef signext %t, i32 ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 87960930222080 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 24, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 16 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -580,7 +580,7 @@ define linkonce_odr dso_local void @_Z5test2IcEvT_iz(i8 noundef signext %t, i32 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP23]], ptr align 16 [[TMP24]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -623,7 +623,7 @@ define linkonce_odr dso_local void @_Z5test2IiEvT_iz(i32 noundef %t, i32 noundef ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 87960930222080 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 24, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 16 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -643,7 +643,7 @@ define linkonce_odr dso_local void @_Z5test2IiEvT_iz(i32 noundef %t, i32 noundef ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP23]], ptr align 16 [[TMP24]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -678,7 +678,7 @@ define linkonce_odr dso_local void @_Z5test2IfEvT_iz(float noundef %t, i32 nound ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 87960930222080 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 24, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 16 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -698,7 +698,7 @@ define linkonce_odr dso_local void @_Z5test2IfEvT_iz(float noundef %t, i32 nound ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP23]], ptr align 16 [[TMP24]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -733,7 +733,7 @@ define linkonce_odr dso_local void @_Z5test2IdEvT_iz(double noundef %t, i32 noun ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 87960930222080 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 24, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 16 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -753,7 +753,7 @@ define linkonce_odr dso_local void @_Z5test2IdEvT_iz(double noundef %t, i32 noun ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP23]], ptr align 16 [[TMP24]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -788,7 +788,7 @@ define linkonce_odr dso_local void @_Z5test2IeEvT_iz(x86_fp80 noundef %t, i32 no ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 87960930222080 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 24, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 16 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -808,7 +808,7 @@ define linkonce_odr dso_local void @_Z5test2IeEvT_iz(x86_fp80 noundef %t, i32 no ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP23]], ptr align 16 [[TMP24]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -843,7 +843,7 @@ define linkonce_odr dso_local void @_Z5test2I6IntIntEvT_iz(i64 %t.coerce, i32 no ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 87960930222080 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 24, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 16 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -863,7 +863,7 @@ define linkonce_odr dso_local void @_Z5test2I6IntIntEvT_iz(i64 %t.coerce, i32 no ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP23]], ptr align 16 [[TMP24]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -898,7 +898,7 @@ define linkonce_odr dso_local void @_Z5test2I10Int64Int64EvT_iz(i64 %t.coerce0, ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 87960930222080 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 24, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 16 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -918,7 +918,7 @@ define linkonce_odr dso_local void @_Z5test2I10Int64Int64EvT_iz(i64 %t.coerce0, ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP23]], ptr align 16 [[TMP24]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -953,7 +953,7 @@ define linkonce_odr dso_local void @_Z5test2I12DoubleDoubleEvT_iz(double %t.coer ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 87960930222080 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 24, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 16 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -973,7 +973,7 @@ define linkonce_odr dso_local void @_Z5test2I12DoubleDoubleEvT_iz(double %t.coer ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP23]], ptr align 16 [[TMP24]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -1008,7 +1008,7 @@ define linkonce_odr dso_local void @_Z5test2I7Double4EvT_iz(ptr noundef byval(%s ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 87960930222080 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 24, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 16 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -1028,7 +1028,7 @@ define linkonce_odr dso_local void @_Z5test2I7Double4EvT_iz(ptr noundef byval(%s ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP23]], ptr align 16 [[TMP24]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -1063,7 +1063,7 @@ define linkonce_odr dso_local void @_Z5test2I11DoubleFloatEvT_iz(double %t.coerc ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 87960930222080 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 24, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 16 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -1083,7 +1083,7 @@ define linkonce_odr dso_local void @_Z5test2I11DoubleFloatEvT_iz(double %t.coerc ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP23]], ptr align 16 [[TMP24]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -1118,7 +1118,7 @@ define linkonce_odr dso_local void @_Z5test2I11LongDouble2EvT_iz(ptr noundef byv ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 87960930222080 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 24, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 16 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -1138,7 +1138,7 @@ define linkonce_odr dso_local void @_Z5test2I11LongDouble2EvT_iz(ptr noundef byv ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP23]], ptr align 16 [[TMP24]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; @@ -1173,7 +1173,7 @@ define linkonce_odr dso_local void @_Z5test2I11LongDouble4EvT_iz(ptr noundef byv ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 87960930222080 ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 24, i1 false) -; CHECK-NEXT: call void @llvm.va_start(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[ARGS]] to i64 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 16 ; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr @@ -1193,7 +1193,7 @@ define linkonce_odr dso_local void @_Z5test2I11LongDouble4EvT_iz(ptr noundef byv ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 16 [[TMP23]], ptr align 16 [[TMP24]], i64 [[TMP0]], i1 false) ; CHECK-NEXT: store i64 0, ptr @__msan_param_tls, align 8 ; CHECK-NEXT: call void @_Z3usePv(ptr noundef nonnull [[ARGS]]) -; CHECK-NEXT: call void @llvm.va_end(ptr nonnull [[ARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr nonnull [[ARGS]]) ; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 24, ptr nonnull [[ARGS]]) ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Instrumentation/MemorySanitizer/msan_debug_info.ll b/llvm/test/Instrumentation/MemorySanitizer/msan_debug_info.ll index 21f3311a57efa6a42776eed663d575f1ee2750af..f07f3ad06e60779c57707624a98573e58839d637 100644 --- a/llvm/test/Instrumentation/MemorySanitizer/msan_debug_info.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/msan_debug_info.ll @@ -542,7 +542,7 @@ define void @VAStart(i32 %x, ...) sanitize_memory { ; CHECK-NEXT: [[TMP29:%.*]] = add i64 [[TMP27]], 17592186044416, !dbg [[DBG11]] ; CHECK-NEXT: [[TMP30:%.*]] = inttoptr i64 [[TMP29]] to ptr, !dbg [[DBG11]] ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP28]], i8 0, i64 24, i1 false), !dbg [[DBG11]] -; CHECK-NEXT: call void @llvm.va_start(ptr [[VA]]), !dbg [[DBG11]] +; CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VA]]), !dbg [[DBG11]] ; CHECK-NEXT: [[TMP31:%.*]] = ptrtoint ptr [[VA]] to i64, !dbg [[DBG11]] ; CHECK-NEXT: [[TMP32:%.*]] = add i64 [[TMP31]], 16, !dbg [[DBG11]] ; CHECK-NEXT: [[TMP33:%.*]] = inttoptr i64 [[TMP32]] to ptr, !dbg [[DBG11]] diff --git a/llvm/test/Instrumentation/ThreadSanitizer/atomic.ll b/llvm/test/Instrumentation/ThreadSanitizer/atomic.ll index 76afc4bf007c2d72e9eed341e238142ce107735a..8b387cd4962979ae551af064e57593b5d8db70f2 100644 --- a/llvm/test/Instrumentation/ThreadSanitizer/atomic.ll +++ b/llvm/test/Instrumentation/ThreadSanitizer/atomic.ll @@ -78,6 +78,26 @@ entry: ; CHECK-LABEL: atomic8_xchg_monotonic ; CHECK: call i8 @__tsan_atomic8_exchange(ptr %a, i8 0, i32 0), !dbg +define void @atomic8_xchg_monotonic_ptr(ptr %a, ptr %b) nounwind uwtable { +entry: + atomicrmw xchg ptr %a, ptr %b monotonic, !dbg !7 + ret void, !dbg !7 +} +; CHECK-LABEL: atomic8_xchg_monotonic_ptr +; CHECK: [[ARG:%.*]] = ptrtoint ptr %b to i64, !dbg +; CHECK: [[RES:%.*]] = call i64 @__tsan_atomic64_exchange(ptr %a, i64 [[ARG]], i32 0), !dbg +; CHECK: [[CAST:%.*]] = inttoptr i64 [[RES]] to ptr, !dbg + +define void @atomic8_xchg_monotonic_float(ptr %a, float %b) nounwind uwtable { +entry: + atomicrmw xchg ptr %a, float %b monotonic, !dbg !7 + ret void, !dbg !7 +} +; CHECK-LABEL: atomic8_xchg_monotonic_float +; CHECK: [[ARG:%.*]] = bitcast float %b to i32, !dbg +; CHECK: [[RES:%.*]] = call i32 @__tsan_atomic32_exchange(ptr %a, i32 [[ARG]], i32 0), !dbg +; CHECK: [[CAST:%.*]] = bitcast i32 [[RES]] to float, !dbg + define void @atomic8_add_monotonic(ptr %a) nounwind uwtable { entry: atomicrmw add ptr %a, i8 0 monotonic, !dbg !7 diff --git a/llvm/test/LTO/AArch64/link-branch-target-enforcement.ll b/llvm/test/LTO/AArch64/link-branch-target-enforcement.ll index 74d9c86881d52cd172b3bb72e7161e38af31b8ba..ccf8cf67ede6dccd08cbbfb80a9cfb0dcb90aebd 100644 --- a/llvm/test/LTO/AArch64/link-branch-target-enforcement.ll +++ b/llvm/test/LTO/AArch64/link-branch-target-enforcement.ll @@ -32,7 +32,6 @@ entry: ; CHECK-DUMP: <main>: ; CHECK-DUMP: bl 0x8 <main+0x8> ; CHECK-DUMP: <foo>: -; CHECK-DUMP: paciasp ; `main` doesn't support BTI while `foo` does, so in the binary ; we should see only PAC which is supported by both. diff --git a/llvm/test/LTO/AArch64/link-sign-return-address.ll b/llvm/test/LTO/AArch64/link-sign-return-address.ll deleted file mode 100644 index c25857ceed7b40ee2870cfc8bcda43a85166f12a..0000000000000000000000000000000000000000 --- a/llvm/test/LTO/AArch64/link-sign-return-address.ll +++ /dev/null @@ -1,43 +0,0 @@ -; Testcase to check that module with different branch-target-enforcement can -; be mixed. -; -; RUN: llvm-as %s -o %t1.bc -; RUN: llvm-as %p/Inputs/foo.ll -o %t2.bc -; RUN: llvm-lto -exported-symbol main \ -; RUN: -exported-symbol foo \ -; RUN: -filetype=obj \ -; RUN: %t2.bc %t1.bc \ -; RUN: -o %t1.exe 2>&1 -; RUN: llvm-objdump -d %t1.exe | FileCheck --check-prefix=CHECK-DUMP %s -; RUN: llvm-readelf -n %t1.exe | FileCheck --allow-empty --check-prefix=CHECK-PROP %s - -target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" -target triple = "aarch64-unknown-linux-gnu" - -declare i32 @foo(); - -define i32 @main() { -entry: - %add = call i32 @foo() - ret i32 %add -} - -!llvm.module.flags = !{!0, !1, !2, !3 } -!0 = !{i32 8, !"branch-target-enforcement", i32 0} -!1 = !{i32 8, !"sign-return-address", i32 0} -!2 = !{i32 8, !"sign-return-address-all", i32 0} -!3 = !{i32 8, !"sign-return-address-with-bkey", i32 0} - -; CHECK-DUMP: <foo>: -; CHECK-DUMP: paciasp -; CHECK-DUMP: mov w0, #0x2a -; CHECK-DUMP: autiasp -; CHECK-DUMP: ret -; CHECK-DUMP: <main>: -; CHECK-DUMP-NOT: paciasp -; CHECK-DUMP: str x30, -; CHECK-DUMP: bl 0x14 <main+0x4> - -; `main` doesn't support PAC sign-return-address while `foo` does, so in the binary -; we should not see anything. -; CHECK-PROP-NOT: Properties: aarch64 feature: PAC \ No newline at end of file diff --git a/llvm/test/Linker/link-arm-and-thumb.ll b/llvm/test/Linker/link-arm-and-thumb.ll index 37bd8c37f8b5e56b5eea5a360101fc8c19164cb2..a90f2128e4430a42e4a92427321d487b6d0e21be 100644 --- a/llvm/test/Linker/link-arm-and-thumb.ll +++ b/llvm/test/Linker/link-arm-and-thumb.ll @@ -13,12 +13,11 @@ entry: ret i32 %add } -; CHECK: define i32 @main() [[MAIN_ATTRS:#[0-9]+]] +; CHECK: define i32 @main() { ; CHECK: define i32 @foo(i32 %a, i32 %b) [[ARM_ATTRS:#[0-9]+]] ; CHECK: define i32 @bar(i32 %a, i32 %b) [[THUMB_ATTRS:#[0-9]+]] -; CHECK: attributes [[MAIN_ATTRS]] = { {{.*}} } -; CHECK: attributes [[ARM_ATTRS]] = { {{.*}} "target-features"="-thumb-mode" } -; CHECK: attributes [[THUMB_ATTRS]] = { {{.*}} "target-features"="+thumb-mode" } +; CHECK: attributes [[ARM_ATTRS]] = { "target-features"="-thumb-mode" } +; CHECK: attributes [[THUMB_ATTRS]] = { "target-features"="+thumb-mode" } ; STDERR-NOT: warning: Linking two modules of different target triples: diff --git a/llvm/test/MC/AArch64/coff-relocations.s b/llvm/test/MC/AArch64/coff-relocations.s index fb67a21992c6df3d0c49cf16c4def5f7348ee3e3..2370fd9fb43653840142cc994cb54859bd08cec1 100644 --- a/llvm/test/MC/AArch64/coff-relocations.s +++ b/llvm/test/MC/AArch64/coff-relocations.s @@ -1,7 +1,11 @@ // RUN: llvm-mc -triple aarch64-windows -filetype obj -o %t.obj %s -// RUN: llvm-readobj -r %t.obj | FileCheck %s +// RUN: llvm-mc -triple arm64ec-windows -filetype obj -o %t-ec.obj %s +// RUN: llvm-readobj -r %t.obj | FileCheck %s --check-prefixes=CHECK,CHECK-ARM64 +// RUN: llvm-readobj -r %t-ec.obj | FileCheck %s --check-prefixes=CHECK,CHECK-ARM64EC // RUN: llvm-objdump --no-print-imm-hex -d %t.obj | FileCheck %s --check-prefix=DISASM +// RUN: llvm-objdump --no-print-imm-hex -d %t-ec.obj | FileCheck %s --check-prefix=DISASM // RUN: llvm-objdump -s %t.obj | FileCheck %s --check-prefix=DATA +// RUN: llvm-objdump -s %t-ec.obj | FileCheck %s --check-prefix=DATA // IMAGE_REL_ARM64_ADDR32 .Linfo_foo: @@ -71,8 +75,10 @@ tbz x0, #0, target // IMAGE_REL_ARM64_REL32 because IMAGE_REL_ARM64_REL64 does not exist. .xword .Linfo_foo - .Ltable -// CHECK: Format: COFF-ARM64 -// CHECK: Arch: aarch64 +// CHECK-ARM64: Format: COFF-ARM64 +// CHECK-ARM64EC: Format: COFF-ARM64EC +// CHECK-ARM64: Arch: aarch64 +// CHECK-ARM64EC: Arch: aarch64 // CHECK: AddressSize: 64bit // CHECK: Relocations [ // CHECK: Section (1) .text { diff --git a/llvm/test/MC/AArch64/constant-pool-sizes.s b/llvm/test/MC/AArch64/constant-pool-sizes.s new file mode 100644 index 0000000000000000000000000000000000000000..279402af025f34ea57f5bdfbf69cff311611f551 --- /dev/null +++ b/llvm/test/MC/AArch64/constant-pool-sizes.s @@ -0,0 +1,25 @@ +// RUN: llvm-mc -triple aarch64-none-linux-gnu %s | FileCheck %s + + ldr w0, =symbol + ldr x1, =symbol + + ldr w2, =1234567890 + ldr x3, =1234567890 + +// CHECK: ldr w0, .Ltmp0 +// CHECK: ldr x1, .Ltmp1 +// CHECK: ldr w2, .Ltmp2 +// CHECK: ldr x3, .Ltmp3 + +// CHECK: .p2align 2, 0x0 +// CHECK-NEXT:.Ltmp0: +// CHECK-NEXT: .word symbol +// CHECK: .p2align 3, 0x0 +// CHECK-NEXT:.Ltmp1: +// CHECK-NEXT: .xword symbol +// CHECK: .p2align 2, 0x0 +// CHECK-NEXT:.Ltmp2: +// CHECK-NEXT: .word 1234567890 +// CHECK: .p2align 3, 0x0 +// CHECK-NEXT:.Ltmp3: +// CHECK-NEXT: .xword 1234567890 diff --git a/llvm/test/MC/AMDGPU/gfx11_asm_sop1.s b/llvm/test/MC/AMDGPU/gfx11_asm_sop1.s index 8a7f64331317edc1dc8035e4574324a19b90e369..c4029b0658b2e2aece4b490de4ea68b9f45ef507 100644 --- a/llvm/test/MC/AMDGPU/gfx11_asm_sop1.s +++ b/llvm/test/MC/AMDGPU/gfx11_asm_sop1.s @@ -2964,6 +2964,9 @@ s_sendmsg_rtn_b32 s0, sendmsg(MSG_RTN_SAVE_WAVE) s_sendmsg_rtn_b32 s0, sendmsg(MSG_RTN_GET_TBA) // GFX11: encoding: [0x85,0x4c,0x80,0xbe] +s_sendmsg_rtn_b32 s0, sendmsg(MSG_RTN_GET_TBA_TO_PC) +// GFX11: encoding: [0x86,0x4c,0x80,0xbe] + s_ctz_i32_b32 s5, s1 // GFX11: encoding: [0x01,0x08,0x85,0xbe] diff --git a/llvm/test/MC/AMDGPU/gfx11_asm_vinterp.s b/llvm/test/MC/AMDGPU/gfx11_asm_vinterp.s deleted file mode 100644 index fdfbf65c0e3cf302f877ad3667d51f3ca84a7d34..0000000000000000000000000000000000000000 --- a/llvm/test/MC/AMDGPU/gfx11_asm_vinterp.s +++ /dev/null @@ -1,278 +0,0 @@ -// RUN: llvm-mc -triple=amdgcn -mcpu=gfx1100 -show-encoding %s | FileCheck -check-prefix=GCN %s -// RUN: llvm-mc -triple=amdgcn -mcpu=gfx1200 -show-encoding %s | FileCheck -check-prefix=GCN %s - -v_interp_p10_f32 v0, v1, v2, v3 -// GCN: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f32 v1, v10, v20, v30 -// GCN: v_interp_p10_f32 v1, v10, v20, v30 wait_exp:0 ; encoding: [0x01,0x00,0x00,0xcd,0x0a,0x29,0x7a,0x04] - -v_interp_p10_f32 v2, v11, v21, v31 -// GCN: v_interp_p10_f32 v2, v11, v21, v31 wait_exp:0 ; encoding: [0x02,0x00,0x00,0xcd,0x0b,0x2b,0x7e,0x04] - -v_interp_p10_f32 v3, v12, v22, v32 -// GCN: v_interp_p10_f32 v3, v12, v22, v32 wait_exp:0 ; encoding: [0x03,0x00,0x00,0xcd,0x0c,0x2d,0x82,0x04] - -v_interp_p10_f32 v0, v1, v2, v3 clamp -// GCN: v_interp_p10_f32 v0, v1, v2, v3 clamp wait_exp:0 ; encoding: [0x00,0x80,0x00,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f32 v0, -v1, v2, v3 -// GCN: v_interp_p10_f32 v0, -v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x24] - -v_interp_p10_f32 v0, v1, -v2, v3 -// GCN: v_interp_p10_f32 v0, v1, -v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x44] - -v_interp_p10_f32 v0, v1, v2, -v3 -// GCN: v_interp_p10_f32 v0, v1, v2, -v3 wait_exp:0 ; encoding: [0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x84] - -v_interp_p10_f32 v0, v1, v2, v3 wait_exp:0 -// GCN: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f32 v0, v1, v2, v3 wait_exp:1 -// GCN: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:1 ; encoding: [0x00,0x01,0x00,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f32 v0, v1, v2, v3 wait_exp:7 -// GCN: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:7 ; encoding: [0x00,0x07,0x00,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f32 v0, v1, v2, v3 clamp wait_exp:7 -// GCN: v_interp_p10_f32 v0, v1, v2, v3 clamp wait_exp:7 ; encoding: [0x00,0x87,0x00,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f32 v0, v1, v2, v3 -// GCN: v_interp_p2_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f32 v1, v10, v20, v30 -// GCN: v_interp_p2_f32 v1, v10, v20, v30 wait_exp:0 ; encoding: [0x01,0x00,0x01,0xcd,0x0a,0x29,0x7a,0x04] - -v_interp_p2_f32 v2, v11, v21, v31 -// GCN: v_interp_p2_f32 v2, v11, v21, v31 wait_exp:0 ; encoding: [0x02,0x00,0x01,0xcd,0x0b,0x2b,0x7e,0x04] - -v_interp_p2_f32 v3, v12, v22, v32 -// GCN: v_interp_p2_f32 v3, v12, v22, v32 wait_exp:0 ; encoding: [0x03,0x00,0x01,0xcd,0x0c,0x2d,0x82,0x04] - -v_interp_p2_f32 v0, v1, v2, v3 clamp -// GCN: v_interp_p2_f32 v0, v1, v2, v3 clamp wait_exp:0 ; encoding: [0x00,0x80,0x01,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f32 v0, -v1, v2, v3 -// GCN: v_interp_p2_f32 v0, -v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x24] - -v_interp_p2_f32 v0, v1, -v2, v3 -// GCN: v_interp_p2_f32 v0, v1, -v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x44] - -v_interp_p2_f32 v0, v1, v2, -v3 -// GCN: v_interp_p2_f32 v0, v1, v2, -v3 wait_exp:0 ; encoding: [0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x84] - -v_interp_p2_f32 v0, v1, v2, v3 wait_exp:0 -// GCN: v_interp_p2_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f32 v0, v1, v2, v3 wait_exp:1 -// GCN: v_interp_p2_f32 v0, v1, v2, v3 wait_exp:1 ; encoding: [0x00,0x01,0x01,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f32 v0, v1, v2, v3 wait_exp:7 -// GCN: v_interp_p2_f32 v0, v1, v2, v3 wait_exp:7 ; encoding: [0x00,0x07,0x01,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f32 v0, v1, v2, v3 clamp wait_exp:7 -// GCN: v_interp_p2_f32 v0, v1, v2, v3 clamp wait_exp:7 ; encoding: [0x00,0x87,0x01,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f16_f32 v0, v1, v2, v3 -// GCN: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f16_f32 v0, -v1, v2, v3 -// GCN: v_interp_p10_f16_f32 v0, -v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x24] - -v_interp_p10_f16_f32 v0, v1, -v2, v3 -// GCN: v_interp_p10_f16_f32 v0, v1, -v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x44] - -v_interp_p10_f16_f32 v0, v1, v2, -v3 -// GCN: v_interp_p10_f16_f32 v0, v1, v2, -v3 wait_exp:0 ; encoding: [0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x84] - -v_interp_p10_f16_f32 v0, v1, v2, v3 clamp -// GCN: v_interp_p10_f16_f32 v0, v1, v2, v3 clamp wait_exp:0 ; encoding: [0x00,0x80,0x02,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:0 -// GCN: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:1 -// GCN: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:1 ; encoding: [0x00,0x01,0x02,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:7 -// GCN: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:7 ; encoding: [0x00,0x07,0x02,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,0] -// GCN: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] -// GCN: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] wait_exp:0 ; encoding: [0x00,0x08,0x02,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] -// GCN: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] wait_exp:0 ; encoding: [0x00,0x10,0x02,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] -// GCN: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] wait_exp:0 ; encoding: [0x00,0x20,0x02,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] -// GCN: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] wait_exp:0 ; encoding: [0x00,0x40,0x02,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] -// GCN: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] wait_exp:0 ; encoding: [0x00,0x78,0x02,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5 -// GCN: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5 ; encoding: [0x00,0x4d,0x02,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5 -// GCN: v_interp_p10_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5 ; encoding: [0x00,0xcd,0x02,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5 -// GCN: v_interp_p10_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5 ; encoding: [0x00,0xcd,0x02,0xcd,0x01,0x05,0x0e,0xe4] - -v_interp_p2_f16_f32 v0, v1, v2, v3 -// GCN: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f16_f32 v0, -v1, v2, v3 -// GCN: v_interp_p2_f16_f32 v0, -v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x24] - -v_interp_p2_f16_f32 v0, v1, -v2, v3 -// GCN: v_interp_p2_f16_f32 v0, v1, -v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x44] - -v_interp_p2_f16_f32 v0, v1, v2, -v3 -// GCN: v_interp_p2_f16_f32 v0, v1, v2, -v3 wait_exp:0 ; encoding: [0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x84] - -v_interp_p2_f16_f32 v0, v1, v2, v3 clamp -// GCN: v_interp_p2_f16_f32 v0, v1, v2, v3 clamp wait_exp:0 ; encoding: [0x00,0x80,0x03,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:0 -// GCN: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:1 -// GCN: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:1 ; encoding: [0x00,0x01,0x03,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:7 -// GCN: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:7 ; encoding: [0x00,0x07,0x03,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,0] -// GCN: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] -// GCN: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] wait_exp:0 ; encoding: [0x00,0x08,0x03,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] -// GCN: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] wait_exp:0 ; encoding: [0x00,0x10,0x03,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] -// GCN: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] wait_exp:0 ; encoding: [0x00,0x20,0x03,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] -// GCN: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] wait_exp:0 ; encoding: [0x00,0x40,0x03,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] -// GCN: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] wait_exp:0 ; encoding: [0x00,0x78,0x03,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5 -// GCN: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5 ; encoding: [0x00,0x4d,0x03,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5 -// GCN: v_interp_p2_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5 ; encoding: [0x00,0xcd,0x03,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5 -// GCN: v_interp_p2_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5 ; encoding: [0x00,0xcd,0x03,0xcd,0x01,0x05,0x0e,0xe4] - -v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 -// GCN: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_rtz_f16_f32 v0, -v1, v2, v3 -// GCN: v_interp_p10_rtz_f16_f32 v0, -v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x24] - -v_interp_p10_rtz_f16_f32 v0, v1, -v2, v3 -// GCN: v_interp_p10_rtz_f16_f32 v0, v1, -v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x44] - -v_interp_p10_rtz_f16_f32 v0, v1, v2, -v3 -// GCN: v_interp_p10_rtz_f16_f32 v0, v1, v2, -v3 wait_exp:0 ; encoding: [0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x84] - -v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 clamp -// GCN: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 clamp wait_exp:0 ; encoding: [0x00,0x80,0x04,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0 -// GCN: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:1 -// GCN: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:1 ; encoding: [0x00,0x01,0x04,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:7 -// GCN: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:7 ; encoding: [0x00,0x07,0x04,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,0] -// GCN: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] -// GCN: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] wait_exp:0 ; encoding: [0x00,0x08,0x04,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] -// GCN: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] wait_exp:0 ; encoding: [0x00,0x10,0x04,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] -// GCN: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] wait_exp:0 ; encoding: [0x00,0x20,0x04,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] -// GCN: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] wait_exp:0 ; encoding: [0x00,0x40,0x04,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] -// GCN: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] wait_exp:0 ; encoding: [0x00,0x78,0x04,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5 -// GCN: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5 ; encoding: [0x00,0x4d,0x04,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5 -// GCN: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5 ; encoding: [0x00,0xcd,0x04,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p10_rtz_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5 -// GCN: v_interp_p10_rtz_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5 ; encoding: [0x00,0xcd,0x04,0xcd,0x01,0x05,0x0e,0xe4] - -v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 -// GCN: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_rtz_f16_f32 v0, -v1, v2, v3 -// GCN: v_interp_p2_rtz_f16_f32 v0, -v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x24] - -v_interp_p2_rtz_f16_f32 v0, v1, -v2, v3 -// GCN: v_interp_p2_rtz_f16_f32 v0, v1, -v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x44] - -v_interp_p2_rtz_f16_f32 v0, v1, v2, -v3 -// GCN: v_interp_p2_rtz_f16_f32 v0, v1, v2, -v3 wait_exp:0 ; encoding: [0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x84] - -v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 clamp -// GCN: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 clamp wait_exp:0 ; encoding: [0x00,0x80,0x05,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0 -// GCN: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:1 -// GCN: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:1 ; encoding: [0x00,0x01,0x05,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:7 -// GCN: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:7 ; encoding: [0x00,0x07,0x05,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,0] -// GCN: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] -// GCN: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] wait_exp:0 ; encoding: [0x00,0x08,0x05,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] -// GCN: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] wait_exp:0 ; encoding: [0x00,0x10,0x05,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] -// GCN: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] wait_exp:0 ; encoding: [0x00,0x20,0x05,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] -// GCN: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] wait_exp:0 ; encoding: [0x00,0x40,0x05,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] -// GCN: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] wait_exp:0 ; encoding: [0x00,0x78,0x05,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5 -// GCN: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5 ; encoding: [0x00,0x4d,0x05,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5 -// GCN: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5 ; encoding: [0x00,0xcd,0x05,0xcd,0x01,0x05,0x0e,0x04] - -v_interp_p2_rtz_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5 -// GCN: v_interp_p2_rtz_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5 ; encoding: [0x00,0xcd,0x05,0xcd,0x01,0x05,0x0e,0xe4] diff --git a/llvm/test/MC/AMDGPU/gfx12_asm_sop1.s b/llvm/test/MC/AMDGPU/gfx12_asm_sop1.s index 4fd355f10f341a489eb0c2c576bc4100dc65c6e0..939320e9ef2dce3e6220874fd3c550775cbd1c4b 100644 --- a/llvm/test/MC/AMDGPU/gfx12_asm_sop1.s +++ b/llvm/test/MC/AMDGPU/gfx12_asm_sop1.s @@ -3708,9 +3708,12 @@ s_sendmsg_rtn_b32 s0, sendmsg(MSG_RTN_SAVE_WAVE) s_sendmsg_rtn_b32 s0, sendmsg(MSG_RTN_GET_TBA) // GFX12: encoding: [0x85,0x4c,0x80,0xbe] -s_sendmsg_rtn_b32 s0, sendmsg(MSG_RTN_GET_SE_AID_ID) +s_sendmsg_rtn_b32 s0, sendmsg(MSG_RTN_GET_TBA_TO_PC) // GFX12: encoding: [0x86,0x4c,0x80,0xbe] +s_sendmsg_rtn_b32 s0, sendmsg(MSG_RTN_GET_SE_AID_ID) +// GFX12: encoding: [0x87,0x4c,0x80,0xbe] + s_ctz_i32_b32 s5, s1 // GFX12: encoding: [0x01,0x08,0x85,0xbe] diff --git a/llvm/test/MC/AMDGPU/gfx12_asm_vbuffer_mubuf.s b/llvm/test/MC/AMDGPU/gfx12_asm_vbuffer_mubuf.s index 08ec5b3f6a5220f659b164e8dcbe1143deb7fc07..efeaf8339f6928e60723c14c969759f909aa939b 100644 --- a/llvm/test/MC/AMDGPU/gfx12_asm_vbuffer_mubuf.s +++ b/llvm/test/MC/AMDGPU/gfx12_asm_vbuffer_mubuf.s @@ -3970,70 +3970,70 @@ buffer_atomic_max_u64 v[5:6], off, s[8:11], s3 offset:8388607 dlc buffer_atomic_max_u64 v[5:6], off, s[8:11], s3 offset:8388607 glc slc dlc // GFX12-ERR: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:8388607 +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:8388607 // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x10,0x80,0x00,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v255, off, s[8:11], s3 offset:8388607 +buffer_atomic_min_num_f32 v255, off, s[8:11], s3 offset:8388607 // GFX12: encoding: [0x03,0x40,0x14,0xc4,0xff,0x10,0x80,0x00,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, off, s[12:15], s3 offset:8388607 +buffer_atomic_min_num_f32 v5, off, s[12:15], s3 offset:8388607 // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x18,0x80,0x00,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, off, s[96:99], s3 offset:8388607 +buffer_atomic_min_num_f32 v5, off, s[96:99], s3 offset:8388607 // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0xc0,0x80,0x00,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, off, s[8:11], s101 offset:8388607 +buffer_atomic_min_num_f32 v5, off, s[8:11], s101 offset:8388607 // GFX12: encoding: [0x65,0x40,0x14,0xc4,0x05,0x10,0x80,0x00,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, off, s[8:11], m0 offset:8388607 +buffer_atomic_min_num_f32 v5, off, s[8:11], m0 offset:8388607 // GFX12: encoding: [0x7d,0x40,0x14,0xc4,0x05,0x10,0x80,0x00,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, off, s[8:11], 0 offset:8388607 +buffer_atomic_min_num_f32 v5, off, s[8:11], 0 offset:8388607 // GFX12-ERR: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction -buffer_atomic_min_f32 v5, off, s[8:11], -1 offset:8388607 +buffer_atomic_min_num_f32 v5, off, s[8:11], -1 offset:8388607 // GFX12-ERR: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction -buffer_atomic_min_f32 v5, off, s[8:11], 0.5 offset:8388607 +buffer_atomic_min_num_f32 v5, off, s[8:11], 0.5 offset:8388607 // GFX12-ERR: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction -buffer_atomic_min_f32 v5, off, s[8:11], -4.0 offset:8388607 +buffer_atomic_min_num_f32 v5, off, s[8:11], -4.0 offset:8388607 // GFX12-ERR: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction -buffer_atomic_min_f32 v5, v0, s[8:11], s3 idxen offset:8388607 +buffer_atomic_min_num_f32 v5, v0, s[8:11], s3 idxen offset:8388607 // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x10,0x80,0x80,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, v0, s[8:11], s3 offen offset:8388607 +buffer_atomic_min_num_f32 v5, v0, s[8:11], s3 offen offset:8388607 // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x10,0x80,0x40,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, off, s[8:11], s3 +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x10,0x80,0x00,0x00,0x00,0x00,0x00] -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:0 +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:0 // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x10,0x80,0x00,0x00,0x00,0x00,0x00] -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:7 +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:7 // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x10,0x80,0x00,0x00,0x07,0x00,0x00] -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:8388607 th:TH_ATOMIC_RETURN +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:8388607 th:TH_ATOMIC_RETURN // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x10,0x90,0x00,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:8388607 th:TH_ATOMIC_RT_RETURN scope:SCOPE_SE +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:8388607 th:TH_ATOMIC_RT_RETURN scope:SCOPE_SE // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x10,0x94,0x00,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:8388607 th:TH_ATOMIC_CASCADE_NT scope:SCOPE_DEV +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:8388607 th:TH_ATOMIC_CASCADE_NT scope:SCOPE_DEV // GFX12: encoding: [0x03,0x40,0x14,0xc4,0x05,0x10,0xe8,0x00,0x00,0xff,0xff,0x7f] -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:8388607 glc +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:8388607 glc // GFX12-ERR: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:8388607 slc +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:8388607 slc // GFX12-ERR: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:8388607 dlc +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:8388607 dlc // GFX12-ERR: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction -buffer_atomic_min_f32 v5, off, s[8:11], s3 offset:8388607 glc slc dlc +buffer_atomic_min_num_f32 v5, off, s[8:11], s3 offset:8388607 glc slc dlc // GFX12-ERR: :[[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction buffer_atomic_min_i32 v5, off, s[8:11], s3 offset:8388607 diff --git a/llvm/test/MC/AMDGPU/hsa-amdgpu-exprs.s b/llvm/test/MC/AMDGPU/hsa-amdgpu-exprs.s new file mode 100644 index 0000000000000000000000000000000000000000..4623500987be8812c3db7c67e2f43834a373fcf0 --- /dev/null +++ b/llvm/test/MC/AMDGPU/hsa-amdgpu-exprs.s @@ -0,0 +1,27 @@ +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx90a < %s | FileCheck --check-prefix=ASM %s +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx90a -filetype=obj < %s > %t +// RUN: llvm-objdump -s -j .rodata %t | FileCheck --check-prefix=OBJDUMP %s + +// OBJDUMP: 0000 00000000 0f000000 00000000 00000000 + +.text + +.p2align 8 +.type caller,@function +caller: + s_endpgm + +.rodata + +.p2align 6 +.amdhsa_kernel caller + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_private_segment_fixed_size max(7, callee1.private_seg_size, callee2.private_seg_size) +.end_amdhsa_kernel + +.set callee1.private_seg_size, 4 +.set callee2.private_seg_size, 15 + +// ASM: .amdhsa_private_segment_fixed_size max(7, callee1.private_seg_size, callee2.private_seg_size) diff --git a/llvm/test/MC/AMDGPU/hsa-gfx12-v4.s b/llvm/test/MC/AMDGPU/hsa-gfx12-v4.s index 8b90e20bb87d1f71d4194f1a74094866eb3af112..7b591904e877fdb2de0c78b4589aa16720429845 100644 --- a/llvm/test/MC/AMDGPU/hsa-gfx12-v4.s +++ b/llvm/test/MC/AMDGPU/hsa-gfx12-v4.s @@ -29,7 +29,7 @@ // OBJDUMP-NEXT: 0000 00000000 00000000 00000000 00000000 // OBJDUMP-NEXT: 0010 00000000 00000000 00000000 00000000 // OBJDUMP-NEXT: 0020 00000000 00000000 00000000 00000000 -// OBJDUMP-NEXT: 0030 00000c60 80000000 00000000 00000000 +// OBJDUMP-NEXT: 0030 00000c60 80000000 00040000 00000000 // complete // OBJDUMP-NEXT: 0040 01000000 01000000 08000000 00000000 // OBJDUMP-NEXT: 0050 00000000 00000000 00000000 00000000 @@ -39,12 +39,12 @@ // OBJDUMP-NEXT: 0080 00000000 00000000 00000000 00000000 // OBJDUMP-NEXT: 0090 00000000 00000000 00000000 00000000 // OBJDUMP-NEXT: 00a0 00000000 00000000 00000000 00000000 -// OBJDUMP-NEXT: 00b0 00000060 80000000 00000000 00000000 +// OBJDUMP-NEXT: 00b0 00000060 80000000 00040000 00000000 // disabled_user_sgpr // OBJDUMP-NEXT: 00c0 00000000 00000000 00000000 00000000 // OBJDUMP-NEXT: 00d0 00000000 00000000 00000000 00000000 // OBJDUMP-NEXT: 00e0 00000000 00000000 00000000 00000000 -// OBJDUMP-NEXT: 00f0 00000c60 80000000 00000000 00000000 +// OBJDUMP-NEXT: 00f0 00000c60 80000000 00040000 00000000 .text // ASM: .text diff --git a/llvm/test/MC/AMDGPU/hsa-sym-expr-failure.s b/llvm/test/MC/AMDGPU/hsa-sym-expr-failure.s new file mode 100644 index 0000000000000000000000000000000000000000..fab3e893352b21add7506690dfeb228339e977cd --- /dev/null +++ b/llvm/test/MC/AMDGPU/hsa-sym-expr-failure.s @@ -0,0 +1,281 @@ +// RUN: not llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx90a %s 2>&1 | FileCheck --check-prefix=ASM %s + +// Some expression currently require (immediately) solvable expressions, i.e., +// they don't depend on yet-unknown symbolic values. + +.text +// ASM: .text + +.amdhsa_code_object_version 4 +// ASM: .amdhsa_code_object_version 4 + +.p2align 8 +.type user_sgpr_count,@function +user_sgpr_count: + s_endpgm + +.p2align 6 +.amdhsa_kernel user_sgpr_count + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_count defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_count + +.p2align 8 +.type user_sgpr_private_segment_buffer,@function +user_sgpr_private_segment_buffer: + s_endpgm + +.amdhsa_kernel user_sgpr_private_segment_buffer + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_private_segment_buffer defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer + +.p2align 8 +.type user_sgpr_kernarg_preload_length,@function +user_sgpr_kernarg_preload_length: + s_endpgm + +.amdhsa_kernel user_sgpr_kernarg_preload_length + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_kernarg_preload_length defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_preload_length defined_boolean + +.p2align 8 +.type user_sgpr_kernarg_preload_offset,@function +user_sgpr_kernarg_preload_offset: + s_endpgm + +.amdhsa_kernel user_sgpr_kernarg_preload_offset + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_kernarg_preload_offset defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_preload_offset defined_boolean + +.p2align 8 +.type user_sgpr_dispatch_ptr,@function +user_sgpr_dispatch_ptr: + s_endpgm + +.p2align 6 +.amdhsa_kernel user_sgpr_dispatch_ptr + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_dispatch_ptr defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr + +.p2align 8 +.type user_sgpr_queue_ptr,@function +user_sgpr_queue_ptr: + s_endpgm + +.p2align 6 +.amdhsa_kernel user_sgpr_queue_ptr + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_queue_ptr defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr + +.p2align 8 +.type user_sgpr_kernarg_segment_ptr,@function +user_sgpr_kernarg_segment_ptr: + s_endpgm + +.p2align 6 +.amdhsa_kernel user_sgpr_kernarg_segment_ptr + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_kernarg_segment_ptr defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr + +.p2align 8 +.type user_sgpr_dispatch_id,@function +user_sgpr_dispatch_id: + s_endpgm + +.p2align 6 +.amdhsa_kernel user_sgpr_dispatch_id + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_dispatch_id defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id + +.p2align 8 +.type user_sgpr_flat_scratch_init,@function +user_sgpr_flat_scratch_init: + s_endpgm + +.p2align 6 +.amdhsa_kernel user_sgpr_flat_scratch_init + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_flat_scratch_init defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init + +.p2align 8 +.type user_sgpr_private_segment_size,@function +user_sgpr_private_segment_size: + s_endpgm + +.p2align 6 +.amdhsa_kernel user_sgpr_private_segment_size + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_user_sgpr_private_segment_size defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size + +.p2align 8 +.type wavefront_size32,@function +wavefront_size32: + s_endpgm + +.p2align 6 +.amdhsa_kernel wavefront_size32 + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_wavefront_size32 defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_wavefront_size32 + +.p2align 8 +.type next_free_vgpr,@function +next_free_vgpr: + s_endpgm + +.p2align 6 +.amdhsa_kernel next_free_vgpr + .amdhsa_next_free_vgpr defined_boolean + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_next_free_vgpr + +.p2align 8 +.type next_free_sgpr,@function +next_free_sgpr: + s_endpgm + +.p2align 6 +.amdhsa_kernel next_free_sgpr + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr defined_boolean + .amdhsa_accum_offset 4 +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_next_free_sgpr + +.p2align 8 +.type accum_offset,@function +accum_offset: + s_endpgm + +.p2align 6 +.amdhsa_kernel accum_offset + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_accum_offset + +.p2align 8 +.type reserve_vcc,@function +reserve_vcc: + s_endpgm + +.p2align 6 +.amdhsa_kernel reserve_vcc + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_reserve_vcc defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_reserve_vcc + +.p2align 8 +.type reserve_flat_scratch,@function +reserve_flat_scratch: + s_endpgm + +.p2align 6 +.amdhsa_kernel reserve_flat_scratch + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_reserve_flat_scratch defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_reserve_flat_scratch + +.p2align 8 +.type shared_vgpr_count,@function +shared_vgpr_count: + s_endpgm + +.p2align 6 +.amdhsa_kernel shared_vgpr_count + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 + .amdhsa_shared_vgpr_count defined_boolean +.end_amdhsa_kernel + +// ASM: error: directive should have resolvable expression +// ASM-NEXT: .amdhsa_shared_vgpr_count + +.set defined_boolean, 1 + +// ASM: .set defined_boolean, 1 +// ASM-NEXT: .no_dead_strip defined_boolean diff --git a/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx10.s b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx10.s new file mode 100644 index 0000000000000000000000000000000000000000..95af59c413ae6dea0d0b185a0284cf6e366654c3 --- /dev/null +++ b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx10.s @@ -0,0 +1,190 @@ +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx1010 < %s | FileCheck --check-prefix=ASM %s +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx1010 -filetype=obj < %s > %t +// RUN: llvm-objdump -s -j .rodata %t | FileCheck --check-prefix=OBJDUMP %s + +// When going from asm -> asm, the expressions should remain the same (i.e., symbolic). +// When going from asm -> obj, the expressions should get resolved (through fixups), + +// OBJDUMP: Contents of section .rodata +// expr_defined_later +// OBJDUMP-NEXT: 0000 2b000000 2c000000 00000000 00000000 +// OBJDUMP-NEXT: 0010 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0020 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0030 00f0afe4 801f007f 000c0000 00000000 +// expr_defined +// OBJDUMP-NEXT: 0040 2a000000 2b000000 00000000 00000000 +// OBJDUMP-NEXT: 0050 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0060 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0070 00f0afe4 801f007f 000c0000 00000000 + +.text +// ASM: .text + +.amdhsa_code_object_version 4 +// ASM: .amdhsa_code_object_version 4 + +.p2align 8 +.type expr_defined_later,@function +expr_defined_later: + s_endpgm + +.p2align 8 +.type expr_defined,@function +expr_defined: + s_endpgm + +.rodata +// ASM: .rodata + +.p2align 6 +.amdhsa_kernel expr_defined_later + .amdhsa_group_segment_fixed_size defined_value+2 + .amdhsa_private_segment_fixed_size defined_value+3 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_fp16_overflow defined_boolean + .amdhsa_workgroup_processor_mode defined_boolean + .amdhsa_memory_ordered defined_boolean + .amdhsa_forward_progress defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +.set defined_value, 41 +.set defined_2_bits, 3 +.set defined_boolean, 1 + +.p2align 6 +.amdhsa_kernel expr_defined + .amdhsa_group_segment_fixed_size defined_value+1 + .amdhsa_private_segment_fixed_size defined_value+2 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_fp16_overflow defined_boolean + .amdhsa_workgroup_processor_mode defined_boolean + .amdhsa_memory_ordered defined_boolean + .amdhsa_forward_progress defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +// ASM: .amdhsa_kernel expr_defined_later +// ASM-NEXT: .amdhsa_group_segment_fixed_size defined_value+2 +// ASM-NEXT: .amdhsa_private_segment_fixed_size defined_value+3 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&62)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&1)>>0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&2)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&4)>>2 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&8)>>3 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&16)>>4 +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&32)>>5 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&64)>>6 +// ASM-NEXT: .amdhsa_wavefront_size32 (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&1024)>>10 +// ASM-NEXT: .amdhsa_system_sgpr_private_segment_wavefront_offset (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&1)>>0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&128)>>7 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&256)>>8 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&512)>>9 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&1024)>>10 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&6144)>>11 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_reserve_xnack_mask 1 +// ASM-NEXT: .amdhsa_float_round_mode_32 (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&12288)>>12 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&49152)>>14 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&196608)>>16 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&786432)>>18 +// ASM-NEXT: .amdhsa_dx10_clamp (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&2097152)>>21 +// ASM-NEXT: .amdhsa_ieee_mode (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&8388608)>>23 +// ASM-NEXT: .amdhsa_fp16_overflow (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&67108864)>>26 +// ASM-NEXT: .amdhsa_workgroup_processor_mode (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&536870912)>>29 +// ASM-NEXT: .amdhsa_memory_ordered (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&1073741824)>>30 +// ASM-NEXT: .amdhsa_forward_progress (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&2147483648)>>31 +// ASM-NEXT: .amdhsa_shared_vgpr_count 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&16777216)>>24 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&33554432)>>25 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&67108864)>>26 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&134217728)>>27 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&268435456)>>28 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&536870912)>>29 +// ASM-NEXT: .amdhsa_exception_int_div_zero (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&1073741824)>>30 +// ASM-NEXT: .end_amdhsa_kernel + +// ASM: .set defined_value, 41 +// ASM-NEXT: .no_dead_strip defined_value +// ASM-NEXT: .set defined_2_bits, 3 +// ASM-NEXT: .no_dead_strip defined_2_bits +// ASM-NEXT: .set defined_boolean, 1 +// ASM-NEXT: .no_dead_strip defined_boolean + +// ASM: .amdhsa_kernel expr_defined +// ASM-NEXT: .amdhsa_group_segment_fixed_size 42 +// ASM-NEXT: .amdhsa_private_segment_fixed_size 43 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id 0 +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size 0 +// ASM-NEXT: .amdhsa_wavefront_size32 1 +// ASM-NEXT: .amdhsa_system_sgpr_private_segment_wavefront_offset 0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info 1 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id 3 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_reserve_xnack_mask 1 +// ASM-NEXT: .amdhsa_float_round_mode_32 3 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 3 +// ASM-NEXT: .amdhsa_dx10_clamp 1 +// ASM-NEXT: .amdhsa_ieee_mode 1 +// ASM-NEXT: .amdhsa_fp16_overflow 1 +// ASM-NEXT: .amdhsa_workgroup_processor_mode 1 +// ASM-NEXT: .amdhsa_memory_ordered 1 +// ASM-NEXT: .amdhsa_forward_progress 1 +// ASM-NEXT: .amdhsa_shared_vgpr_count 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op 1 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact 1 +// ASM-NEXT: .amdhsa_exception_int_div_zero 1 +// ASM-NEXT: .end_amdhsa_kernel diff --git a/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx11.s b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx11.s new file mode 100644 index 0000000000000000000000000000000000000000..e1107fb69ba410908ed159abacdb513e2d5223a6 --- /dev/null +++ b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx11.s @@ -0,0 +1,186 @@ +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx1100 < %s | FileCheck --check-prefix=ASM %s +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx1100 -filetype=obj < %s > %t +// RUN: llvm-objdump -s -j .rodata %t | FileCheck --check-prefix=OBJDUMP %s + +// When going from asm -> asm, the expressions should remain the same (i.e., symbolic). +// When going from asm -> obj, the expressions should get resolved (through fixups), + +// OBJDUMP: Contents of section .rodata +// expr_defined_later +// OBJDUMP-NEXT: 0000 2b000000 2c000000 00000000 00000000 +// OBJDUMP-NEXT: 0010 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0020 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0030 00f0afe4 811f007f 000c0000 00000000 +// expr_defined +// OBJDUMP-NEXT: 0040 2a000000 2b000000 00000000 00000000 +// OBJDUMP-NEXT: 0050 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0060 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0070 00f0afe4 811f007f 000c0000 00000000 + +.text +// ASM: .text + +.amdhsa_code_object_version 4 +// ASM: .amdhsa_code_object_version 4 + +.p2align 8 +.type expr_defined_later,@function +expr_defined_later: + s_endpgm + +.p2align 8 +.type expr_defined,@function +expr_defined: + s_endpgm + +.rodata +// ASM: .rodata + +.p2align 6 +.amdhsa_kernel expr_defined_later + .amdhsa_group_segment_fixed_size defined_value+2 + .amdhsa_private_segment_fixed_size defined_value+3 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_fp16_overflow defined_boolean + .amdhsa_workgroup_processor_mode defined_boolean + .amdhsa_memory_ordered defined_boolean + .amdhsa_forward_progress defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_enable_private_segment defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +.set defined_value, 41 +.set defined_2_bits, 3 +.set defined_boolean, 1 + +.p2align 6 +.amdhsa_kernel expr_defined + .amdhsa_group_segment_fixed_size defined_value+1 + .amdhsa_private_segment_fixed_size defined_value+2 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_fp16_overflow defined_boolean + .amdhsa_workgroup_processor_mode defined_boolean + .amdhsa_memory_ordered defined_boolean + .amdhsa_forward_progress defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_enable_private_segment defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +// ASM: .amdhsa_kernel expr_defined_later +// ASM-NEXT: .amdhsa_group_segment_fixed_size defined_value+2 +// ASM-NEXT: .amdhsa_private_segment_fixed_size defined_value+3 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&62)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&2)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&4)>>2 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&8)>>3 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&16)>>4 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&64)>>6 +// ASM-NEXT: .amdhsa_wavefront_size32 (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&1024)>>10 +// ASM-NEXT: .amdhsa_enable_private_segment (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&1)>>0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&128)>>7 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&256)>>8 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&512)>>9 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&1024)>>10 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&6144)>>11 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_float_round_mode_32 (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&12288)>>12 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&49152)>>14 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&196608)>>16 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&786432)>>18 +// ASM-NEXT: .amdhsa_dx10_clamp (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&2097152)>>21 +// ASM-NEXT: .amdhsa_ieee_mode (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&8388608)>>23 +// ASM-NEXT: .amdhsa_fp16_overflow (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&67108864)>>26 +// ASM-NEXT: .amdhsa_workgroup_processor_mode (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&536870912)>>29 +// ASM-NEXT: .amdhsa_memory_ordered (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&1073741824)>>30 +// ASM-NEXT: .amdhsa_forward_progress (((((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(0<<0))&(~960))|(0<<6))&2147483648)>>31 +// ASM-NEXT: .amdhsa_shared_vgpr_count 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&16777216)>>24 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&33554432)>>25 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&67108864)>>26 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&134217728)>>27 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&268435456)>>28 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&536870912)>>29 +// ASM-NEXT: .amdhsa_exception_int_div_zero (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&1073741824)>>30 +// ASM-NEXT: .end_amdhsa_kernel + +// ASM: .set defined_value, 41 +// ASM-NEXT: .no_dead_strip defined_value +// ASM-NEXT: .set defined_2_bits, 3 +// ASM-NEXT: .no_dead_strip defined_2_bits +// ASM-NEXT: .set defined_boolean, 1 +// ASM-NEXT: .no_dead_strip defined_boolean + +// ASM: .amdhsa_kernel expr_defined +// ASM-NEXT: .amdhsa_group_segment_fixed_size 42 +// ASM-NEXT: .amdhsa_private_segment_fixed_size 43 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size 0 +// ASM-NEXT: .amdhsa_wavefront_size32 1 +// ASM-NEXT: .amdhsa_enable_private_segment 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info 1 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id 3 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_float_round_mode_32 3 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 3 +// ASM-NEXT: .amdhsa_dx10_clamp 1 +// ASM-NEXT: .amdhsa_ieee_mode 1 +// ASM-NEXT: .amdhsa_fp16_overflow 1 +// ASM-NEXT: .amdhsa_workgroup_processor_mode 1 +// ASM-NEXT: .amdhsa_memory_ordered 1 +// ASM-NEXT: .amdhsa_forward_progress 1 +// ASM-NEXT: .amdhsa_shared_vgpr_count 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op 1 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact 1 +// ASM-NEXT: .amdhsa_exception_int_div_zero 1 +// ASM-NEXT: .end_amdhsa_kernel diff --git a/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx12.s b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx12.s new file mode 100644 index 0000000000000000000000000000000000000000..449616d35186b7a907cf2a88724e5ac21307d4ee --- /dev/null +++ b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx12.s @@ -0,0 +1,184 @@ +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx1200 < %s | FileCheck --check-prefix=ASM %s +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx1200 -filetype=obj < %s > %t +// RUN: llvm-objdump -s -j .rodata %t | FileCheck --check-prefix=OBJDUMP %s + +// When going from asm -> asm, the expressions should remain the same (i.e., symbolic). +// When going from asm -> obj, the expressions should get resolved (through fixups), + +// OBJDUMP: Contents of section .rodata +// expr_defined_later +// OBJDUMP-NEXT: 0000 2b000000 2c000000 00000000 00000000 +// OBJDUMP-NEXT: 0010 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0020 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0030 00f02fe4 811f007f 000c0000 00000000 +// expr_defined +// OBJDUMP-NEXT: 0040 2a000000 2b000000 00000000 00000000 +// OBJDUMP-NEXT: 0050 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0060 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0070 00f02fe4 811f007f 000c0000 00000000 + +.text +// ASM: .text + +.amdhsa_code_object_version 4 +// ASM: .amdhsa_code_object_version 4 + +.p2align 8 +.type expr_defined_later,@function +expr_defined_later: + s_endpgm + +.p2align 8 +.type expr_defined,@function +expr_defined: + s_endpgm + +.rodata +// ASM: .rodata + +.p2align 6 +.amdhsa_kernel expr_defined_later + .amdhsa_group_segment_fixed_size defined_value+2 + .amdhsa_private_segment_fixed_size defined_value+3 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_fp16_overflow defined_boolean + .amdhsa_workgroup_processor_mode defined_boolean + .amdhsa_memory_ordered defined_boolean + .amdhsa_forward_progress defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_round_robin_scheduling defined_boolean + .amdhsa_enable_private_segment defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +.set defined_value, 41 +.set defined_2_bits, 3 +.set defined_boolean, 1 + +.p2align 6 +.amdhsa_kernel expr_defined + .amdhsa_group_segment_fixed_size defined_value+1 + .amdhsa_private_segment_fixed_size defined_value+2 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_fp16_overflow defined_boolean + .amdhsa_workgroup_processor_mode defined_boolean + .amdhsa_memory_ordered defined_boolean + .amdhsa_forward_progress defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_round_robin_scheduling defined_boolean + .amdhsa_enable_private_segment defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +// ASM: .amdhsa_kernel expr_defined_later +// ASM-NEXT: .amdhsa_group_segment_fixed_size defined_value+2 +// ASM-NEXT: .amdhsa_private_segment_fixed_size defined_value+3 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&62)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&2)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&4)>>2 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&8)>>3 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&16)>>4 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&64)>>6 +// ASM-NEXT: .amdhsa_wavefront_size32 (((((0&(~1024))|(1<<10))&(~2048))|(defined_boolean<<11))&1024)>>10 +// ASM-NEXT: .amdhsa_enable_private_segment (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&1)>>0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&128)>>7 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&256)>>8 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&512)>>9 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&1024)>>10 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&6144)>>11 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_float_round_mode_32 (((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(0<<0))&(~960))|(0<<6))&12288)>>12 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 (((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(0<<0))&(~960))|(0<<6))&49152)>>14 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 (((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(0<<0))&(~960))|(0<<6))&196608)>>16 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 (((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(0<<0))&(~960))|(0<<6))&786432)>>18 +// ASM-NEXT: .amdhsa_fp16_overflow (((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(0<<0))&(~960))|(0<<6))&67108864)>>26 +// ASM-NEXT: .amdhsa_workgroup_processor_mode (((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(0<<0))&(~960))|(0<<6))&536870912)>>29 +// ASM-NEXT: .amdhsa_memory_ordered (((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(0<<0))&(~960))|(0<<6))&1073741824)>>30 +// ASM-NEXT: .amdhsa_forward_progress (((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(0<<0))&(~960))|(0<<6))&2147483648)>>31 +// ASM-NEXT: .amdhsa_round_robin_scheduling (((((((((((((((((((((((((((((0&(~786432))|(3<<18))&(~536870912))|(1<<29))&(~1073741824))|(1<<30))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(0<<0))&(~960))|(0<<6))&2097152)>>21 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&16777216)>>24 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&33554432)>>25 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&67108864)>>26 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&134217728)>>27 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&268435456)>>28 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&536870912)>>29 +// ASM-NEXT: .amdhsa_exception_int_div_zero (((((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&1073741824)>>30 +// ASM-NEXT: .end_amdhsa_kernel + +// ASM: .set defined_value, 41 +// ASM-NEXT: .no_dead_strip defined_value +// ASM-NEXT: .set defined_2_bits, 3 +// ASM-NEXT: .no_dead_strip defined_2_bits +// ASM-NEXT: .set defined_boolean, 1 +// ASM-NEXT: .no_dead_strip defined_boolean + +// ASM: .amdhsa_kernel expr_defined +// ASM-NEXT: .amdhsa_group_segment_fixed_size 42 +// ASM-NEXT: .amdhsa_private_segment_fixed_size 43 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size 0 +// ASM-NEXT: .amdhsa_wavefront_size32 1 +// ASM-NEXT: .amdhsa_enable_private_segment 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info 1 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id 3 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_float_round_mode_32 3 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 3 +// ASM-NEXT: .amdhsa_fp16_overflow 1 +// ASM-NEXT: .amdhsa_workgroup_processor_mode 1 +// ASM-NEXT: .amdhsa_memory_ordered 1 +// ASM-NEXT: .amdhsa_forward_progress 1 +// ASM-NEXT: .amdhsa_round_robin_scheduling 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op 1 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact 1 +// ASM-NEXT: .amdhsa_exception_int_div_zero 1 +// ASM-NEXT: .end_amdhsa_kernel diff --git a/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx7.s b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx7.s new file mode 100644 index 0000000000000000000000000000000000000000..c7e05441b45ff7b68c453b76b7a7ac9c99e87098 --- /dev/null +++ b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx7.s @@ -0,0 +1,168 @@ +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx700 < %s | FileCheck --check-prefix=ASM %s +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx700 -filetype=obj < %s > %t +// RUN: llvm-objdump -s -j .rodata %t | FileCheck --check-prefix=OBJDUMP %s + +// When going from asm -> asm, the expressions should remain the same (i.e., symbolic). +// When going from asm -> obj, the expressions should get resolved (through fixups), + +// OBJDUMP: Contents of section .rodata +// expr_defined_later +// OBJDUMP-NEXT: 0000 2b000000 2c000000 00000000 00000000 +// OBJDUMP-NEXT: 0010 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0020 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0030 00f0af00 801f007f 00080000 00000000 +// expr_defined +// OBJDUMP-NEXT: 0040 2a000000 2b000000 00000000 00000000 +// OBJDUMP-NEXT: 0050 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0060 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0070 00f0af00 801f007f 00080000 00000000 + +.text +// ASM: .text + +.amdhsa_code_object_version 4 +// ASM: .amdhsa_code_object_version 4 + +.p2align 8 +.type expr_defined_later,@function +expr_defined_later: + s_endpgm + +.p2align 8 +.type expr_defined,@function +expr_defined: + s_endpgm + +.rodata +// ASM: .rodata + +.p2align 6 +.amdhsa_kernel expr_defined_later + .amdhsa_group_segment_fixed_size defined_value+2 + .amdhsa_private_segment_fixed_size defined_value+3 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +.set defined_value, 41 +.set defined_2_bits, 3 +.set defined_boolean, 1 + +.p2align 6 +.amdhsa_kernel expr_defined + .amdhsa_group_segment_fixed_size defined_value+1 + .amdhsa_private_segment_fixed_size defined_value+2 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +// ASM: .amdhsa_kernel expr_defined_later +// ASM-NEXT: .amdhsa_group_segment_fixed_size defined_value+2 +// ASM-NEXT: .amdhsa_private_segment_fixed_size defined_value+3 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&62)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer (((0&(~2048))|(defined_boolean<<11))&1)>>0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr (((0&(~2048))|(defined_boolean<<11))&2)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr (((0&(~2048))|(defined_boolean<<11))&4)>>2 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr (((0&(~2048))|(defined_boolean<<11))&8)>>3 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id (((0&(~2048))|(defined_boolean<<11))&16)>>4 +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init (((0&(~2048))|(defined_boolean<<11))&32)>>5 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size (((0&(~2048))|(defined_boolean<<11))&64)>>6 +// ASM-NEXT: .amdhsa_system_sgpr_private_segment_wavefront_offset (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&1)>>0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&128)>>7 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&256)>>8 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&512)>>9 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&1024)>>10 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&6144)>>11 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_float_round_mode_32 (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&12288)>>12 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&49152)>>14 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&196608)>>16 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&786432)>>18 +// ASM-NEXT: .amdhsa_dx10_clamp (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&2097152)>>21 +// ASM-NEXT: .amdhsa_ieee_mode (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&8388608)>>23 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&16777216)>>24 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&33554432)>>25 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&67108864)>>26 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&134217728)>>27 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&268435456)>>28 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&536870912)>>29 +// ASM-NEXT: .amdhsa_exception_int_div_zero (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&1073741824)>>30 +// ASM-NEXT: .end_amdhsa_kernel + +// ASM: .set defined_value, 41 +// ASM-NEXT: .no_dead_strip defined_value +// ASM-NEXT: .set defined_2_bits, 3 +// ASM-NEXT: .no_dead_strip defined_2_bits +// ASM-NEXT: .set defined_boolean, 1 +// ASM-NEXT: .no_dead_strip defined_boolean + +// ASM: .amdhsa_kernel expr_defined +// ASM-NEXT: .amdhsa_group_segment_fixed_size 42 +// ASM-NEXT: .amdhsa_private_segment_fixed_size 43 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id 0 +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size 0 +// ASM-NEXT: .amdhsa_system_sgpr_private_segment_wavefront_offset 0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info 1 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id 3 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_float_round_mode_32 3 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 3 +// ASM-NEXT: .amdhsa_dx10_clamp 1 +// ASM-NEXT: .amdhsa_ieee_mode 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op 1 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact 1 +// ASM-NEXT: .amdhsa_exception_int_div_zero 1 +// ASM-NEXT: .end_amdhsa_kernel diff --git a/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx8.s b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx8.s new file mode 100644 index 0000000000000000000000000000000000000000..49a5015987a651fa6680b22439ce6ebf7e0841a9 --- /dev/null +++ b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx8.s @@ -0,0 +1,171 @@ +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx801 < %s | FileCheck --check-prefix=ASM %s + +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx801 -filetype=obj < %s > %t +// RUN: llvm-objdump -s -j .rodata %t | FileCheck --check-prefix=OBJDUMP %s + +// When going from asm -> asm, the expressions should remain the same (i.e., symbolic). +// When going from asm -> obj, the expressions should get resolved (through fixups), + +// OBJDUMP: Contents of section .rodata +// expr_defined_later +// OBJDUMP-NEXT: 0000 2b000000 2c000000 00000000 00000000 +// OBJDUMP-NEXT: 0010 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0020 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0030 00f0af00 801f007f 00080000 00000000 +// expr_defined +// OBJDUMP-NEXT: 0040 2a000000 2b000000 00000000 00000000 +// OBJDUMP-NEXT: 0050 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0060 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0070 00f0af00 801f007f 00080000 00000000 + +.text +// ASM: .text + +.amdhsa_code_object_version 4 +// ASM: .amdhsa_code_object_version 4 + +.p2align 8 +.type expr_defined_later,@function +expr_defined_later: + s_endpgm + +.p2align 8 +.type expr_defined,@function +expr_defined: + s_endpgm + +.rodata +// ASM: .rodata + +.p2align 6 +.amdhsa_kernel expr_defined_later + .amdhsa_group_segment_fixed_size defined_value+2 + .amdhsa_private_segment_fixed_size defined_value+3 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +.set defined_value, 41 +.set defined_2_bits, 3 +.set defined_boolean, 1 + +.p2align 6 +.amdhsa_kernel expr_defined + .amdhsa_group_segment_fixed_size defined_value+1 + .amdhsa_private_segment_fixed_size defined_value+2 + .amdhsa_system_vgpr_workitem_id defined_2_bits + .amdhsa_float_round_mode_32 defined_2_bits + .amdhsa_float_round_mode_16_64 defined_2_bits + .amdhsa_float_denorm_mode_32 defined_2_bits + .amdhsa_float_denorm_mode_16_64 defined_2_bits + .amdhsa_system_sgpr_workgroup_id_x defined_boolean + .amdhsa_system_sgpr_workgroup_id_y defined_boolean + .amdhsa_system_sgpr_workgroup_id_z defined_boolean + .amdhsa_system_sgpr_workgroup_info defined_boolean + .amdhsa_exception_fp_ieee_invalid_op defined_boolean + .amdhsa_exception_fp_denorm_src defined_boolean + .amdhsa_exception_fp_ieee_div_zero defined_boolean + .amdhsa_exception_fp_ieee_overflow defined_boolean + .amdhsa_exception_fp_ieee_underflow defined_boolean + .amdhsa_exception_fp_ieee_inexact defined_boolean + .amdhsa_exception_int_div_zero defined_boolean + .amdhsa_uses_dynamic_stack defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 +.end_amdhsa_kernel + +// ASM: .amdhsa_kernel expr_defined_later +// ASM-NEXT: .amdhsa_group_segment_fixed_size defined_value+2 +// ASM-NEXT: .amdhsa_private_segment_fixed_size defined_value+3 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&62)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer (((0&(~2048))|(defined_boolean<<11))&1)>>0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr (((0&(~2048))|(defined_boolean<<11))&2)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr (((0&(~2048))|(defined_boolean<<11))&4)>>2 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr (((0&(~2048))|(defined_boolean<<11))&8)>>3 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id (((0&(~2048))|(defined_boolean<<11))&16)>>4 +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init (((0&(~2048))|(defined_boolean<<11))&32)>>5 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size (((0&(~2048))|(defined_boolean<<11))&64)>>6 +// ASM-NEXT: .amdhsa_system_sgpr_private_segment_wavefront_offset (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&1)>>0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&128)>>7 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&256)>>8 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&512)>>9 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&1024)>>10 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&6144)>>11 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_reserve_xnack_mask 1 +// ASM-NEXT: .amdhsa_float_round_mode_32 (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&12288)>>12 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&49152)>>14 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&196608)>>16 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&786432)>>18 +// ASM-NEXT: .amdhsa_dx10_clamp (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&2097152)>>21 +// ASM-NEXT: .amdhsa_ieee_mode (((((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~12288))|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~63))|(0<<0))&(~960))|(0<<6))&8388608)>>23 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&16777216)>>24 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&33554432)>>25 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&67108864)>>26 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&134217728)>>27 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&268435456)>>28 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&536870912)>>29 +// ASM-NEXT: .amdhsa_exception_int_div_zero (((((((((((((((((((((((((((((0&(~128))|(1<<7))&(~6144))|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~62))|(0<<1))&1073741824)>>30 +// ASM-NEXT: .end_amdhsa_kernel + +// ASM: .set defined_value, 41 +// ASM-NEXT: .no_dead_strip defined_value +// ASM-NEXT: .set defined_2_bits, 3 +// ASM-NEXT: .no_dead_strip defined_2_bits +// ASM-NEXT: .set defined_boolean, 1 +// ASM-NEXT: .no_dead_strip defined_boolean + +// ASM: .amdhsa_kernel expr_defined +// ASM-NEXT: .amdhsa_group_segment_fixed_size 42 +// ASM-NEXT: .amdhsa_private_segment_fixed_size 43 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id 0 +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size 0 +// ASM-NEXT: .amdhsa_system_sgpr_private_segment_wavefront_offset 0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info 1 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id 3 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_reserve_xnack_mask 1 +// ASM-NEXT: .amdhsa_float_round_mode_32 3 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 3 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 3 +// ASM-NEXT: .amdhsa_dx10_clamp 1 +// ASM-NEXT: .amdhsa_ieee_mode 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op 1 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact 1 +// ASM-NEXT: .amdhsa_exception_int_div_zero 1 +// ASM-NEXT: .end_amdhsa_kernel diff --git a/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx90a.s b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx90a.s new file mode 100644 index 0000000000000000000000000000000000000000..b7f89239160fcff428d0a894e5be8c75dfc2483a --- /dev/null +++ b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx90a.s @@ -0,0 +1,148 @@ +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx90a < %s | FileCheck --check-prefix=ASM %s +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx90a -filetype=obj < %s > %t +// RUN: llvm-objdump -s -j .rodata %t | FileCheck --check-prefix=OBJDUMP %s + +// When going from asm -> asm, the expressions should remain the same (i.e., symbolic). +// When going from asm -> obj, the expressions should get resolved (through fixups), + +// OBJDUMP: Contents of section .rodata +// expr_defined_later +// OBJDUMP-NEXT: 0000 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0010 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0020 00000000 00000000 00000000 00000100 +// OBJDUMP-NEXT: 0030 0000ac04 81000000 00000000 00000000 +// expr_defined +// OBJDUMP-NEXT: 0040 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0050 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0060 00000000 00000000 00000000 00000100 +// OBJDUMP-NEXT: 0070 0000ac04 81000000 00000000 00000000 + +.text +// ASM: .text + +.amdhsa_code_object_version 4 +// ASM: .amdhsa_code_object_version 4 + +.p2align 8 +.type expr_defined_later,@function +expr_defined_later: + s_endpgm + +.p2align 8 +.type expr_defined,@function +expr_defined: + s_endpgm + +.rodata +// ASM: .rodata + +.p2align 6 +.amdhsa_kernel expr_defined_later + .amdhsa_system_sgpr_private_segment_wavefront_offset defined_boolean + .amdhsa_dx10_clamp defined_boolean + .amdhsa_ieee_mode defined_boolean + .amdhsa_fp16_overflow defined_boolean + .amdhsa_tg_split defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 +.end_amdhsa_kernel + +.set defined_boolean, 1 + +.p2align 6 +.amdhsa_kernel expr_defined + .amdhsa_system_sgpr_private_segment_wavefront_offset defined_boolean + .amdhsa_dx10_clamp defined_boolean + .amdhsa_ieee_mode defined_boolean + .amdhsa_fp16_overflow defined_boolean + .amdhsa_tg_split defined_boolean + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 +.end_amdhsa_kernel + +// ASM: .amdhsa_kernel expr_defined_later +// ASM-NEXT: .amdhsa_group_segment_fixed_size 0 +// ASM-NEXT: .amdhsa_private_segment_fixed_size 0 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&62)>>1 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id 0 +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_preload_length 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_preload_offset 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size 0 +// ASM-NEXT: .amdhsa_system_sgpr_private_segment_wavefront_offset (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&1)>>0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&128)>>7 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&256)>>8 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&512)>>9 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&1024)>>10 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&6144)>>11 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_accum_offset (((((((0&(~65536))|(defined_boolean<<16))&(~63))|(0<<0))&63)>>0)+1)*4 +// ASM-NEXT: .amdhsa_reserve_xnack_mask 1 +// ASM-NEXT: .amdhsa_float_round_mode_32 (((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~2097152))|(defined_boolean<<21))&(~8388608))|(defined_boolean<<23))&(~67108864))|(defined_boolean<<26))&(~63))|(0<<0))&(~960))|(0<<6))&12288)>>12 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 (((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~2097152))|(defined_boolean<<21))&(~8388608))|(defined_boolean<<23))&(~67108864))|(defined_boolean<<26))&(~63))|(0<<0))&(~960))|(0<<6))&49152)>>14 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 (((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~2097152))|(defined_boolean<<21))&(~8388608))|(defined_boolean<<23))&(~67108864))|(defined_boolean<<26))&(~63))|(0<<0))&(~960))|(0<<6))&196608)>>16 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 (((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~2097152))|(defined_boolean<<21))&(~8388608))|(defined_boolean<<23))&(~67108864))|(defined_boolean<<26))&(~63))|(0<<0))&(~960))|(0<<6))&786432)>>18 +// ASM-NEXT: .amdhsa_dx10_clamp (((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~2097152))|(defined_boolean<<21))&(~8388608))|(defined_boolean<<23))&(~67108864))|(defined_boolean<<26))&(~63))|(0<<0))&(~960))|(0<<6))&2097152)>>21 +// ASM-NEXT: .amdhsa_ieee_mode (((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~2097152))|(defined_boolean<<21))&(~8388608))|(defined_boolean<<23))&(~67108864))|(defined_boolean<<26))&(~63))|(0<<0))&(~960))|(0<<6))&8388608)>>23 +// ASM-NEXT: .amdhsa_fp16_overflow (((((((((((((((((0&(~786432))|(3<<18))&(~2097152))|(1<<21))&(~8388608))|(1<<23))&(~2097152))|(defined_boolean<<21))&(~8388608))|(defined_boolean<<23))&(~67108864))|(defined_boolean<<26))&(~63))|(0<<0))&(~960))|(0<<6))&67108864)>>26 +// ASM-NEXT: .amdhsa_tg_split (((((0&(~65536))|(defined_boolean<<16))&(~63))|(0<<0))&65536)>>16 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&16777216)>>24 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&33554432)>>25 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&67108864)>>26 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&134217728)>>27 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&268435456)>>28 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&536870912)>>29 +// ASM-NEXT: .amdhsa_exception_int_div_zero (((((((0&(~128))|(1<<7))&(~1))|(defined_boolean<<0))&(~62))|(0<<1))&1073741824)>>30 +// ASM-NEXT: .end_amdhsa_kernel + +// ASM: .set defined_boolean, 1 +// ASM-NEXT: .no_dead_strip defined_boolean + +// ASM: .amdhsa_kernel expr_defined +// ASM-NEXT: .amdhsa_group_segment_fixed_size 0 +// ASM-NEXT: .amdhsa_private_segment_fixed_size 0 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id 0 +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_preload_length 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_preload_offset 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size 0 +// ASM-NEXT: .amdhsa_system_sgpr_private_segment_wavefront_offset 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y 0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z 0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info 0 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id 0 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_accum_offset 4 +// ASM-NEXT: .amdhsa_reserve_xnack_mask 1 +// ASM-NEXT: .amdhsa_float_round_mode_32 0 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 0 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 0 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 3 +// ASM-NEXT: .amdhsa_dx10_clamp 1 +// ASM-NEXT: .amdhsa_ieee_mode 1 +// ASM-NEXT: .amdhsa_fp16_overflow 1 +// ASM-NEXT: .amdhsa_tg_split 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op 0 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact 0 +// ASM-NEXT: .amdhsa_exception_int_div_zero 0 +// ASM-NEXT: .end_amdhsa_kernel diff --git a/llvm/test/MC/AMDGPU/hsa-tg-split.s b/llvm/test/MC/AMDGPU/hsa-tg-split.s new file mode 100644 index 0000000000000000000000000000000000000000..5a4d3e2c279c502d55fedfd662125e6089dd2deb --- /dev/null +++ b/llvm/test/MC/AMDGPU/hsa-tg-split.s @@ -0,0 +1,74 @@ +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx90a -mattr=+xnack,+tgsplit < %s | FileCheck --check-prefix=ASM %s +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx90a -mattr=+xnack,+tgsplit -filetype=obj < %s > %t +// RUN: llvm-objdump -s -j .rodata %t | FileCheck --check-prefix=OBJDUMP %s + +// OBJDUMP: Contents of section .rodata +// OBJDUMP-NEXT: 0000 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0010 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0020 00000000 00000000 00000000 00000100 +// OBJDUMP-NEXT: 0030 0000ac00 80000000 00000000 00000000 + +.text +// ASM: .text + +.amdgcn_target "amdgcn-amd-amdhsa--gfx90a:xnack+" +// ASM: .amdgcn_target "amdgcn-amd-amdhsa--gfx90a:xnack+" + +.amdhsa_code_object_version 4 +// ASM: .amdhsa_code_object_version 4 + +.p2align 8 +.type minimal,@function +minimal: + s_endpgm + +.rodata +// ASM: .rodata + +.p2align 6 +.amdhsa_kernel minimal + .amdhsa_next_free_vgpr 0 + .amdhsa_next_free_sgpr 0 + .amdhsa_accum_offset 4 +.end_amdhsa_kernel + +// ASM: .amdhsa_kernel minimal +// ASM-NEXT: .amdhsa_group_segment_fixed_size 0 +// ASM-NEXT: .amdhsa_private_segment_fixed_size 0 +// ASM-NEXT: .amdhsa_kernarg_size 0 +// ASM-NEXT: .amdhsa_user_sgpr_count 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_buffer 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_queue_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_segment_ptr 0 +// ASM-NEXT: .amdhsa_user_sgpr_dispatch_id 0 +// ASM-NEXT: .amdhsa_user_sgpr_flat_scratch_init 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_preload_length 0 +// ASM-NEXT: .amdhsa_user_sgpr_kernarg_preload_offset 0 +// ASM-NEXT: .amdhsa_user_sgpr_private_segment_size 0 +// ASM-NEXT: .amdhsa_system_sgpr_private_segment_wavefront_offset 0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_x 1 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_y 0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_id_z 0 +// ASM-NEXT: .amdhsa_system_sgpr_workgroup_info 0 +// ASM-NEXT: .amdhsa_system_vgpr_workitem_id 0 +// ASM-NEXT: .amdhsa_next_free_vgpr 0 +// ASM-NEXT: .amdhsa_next_free_sgpr 0 +// ASM-NEXT: .amdhsa_accum_offset 4 +// ASM-NEXT: .amdhsa_reserve_xnack_mask 1 +// ASM-NEXT: .amdhsa_float_round_mode_32 0 +// ASM-NEXT: .amdhsa_float_round_mode_16_64 0 +// ASM-NEXT: .amdhsa_float_denorm_mode_32 0 +// ASM-NEXT: .amdhsa_float_denorm_mode_16_64 3 +// ASM-NEXT: .amdhsa_dx10_clamp 1 +// ASM-NEXT: .amdhsa_ieee_mode 1 +// ASM-NEXT: .amdhsa_fp16_overflow 0 +// ASM-NEXT: .amdhsa_tg_split 1 +// ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op 0 +// ASM-NEXT: .amdhsa_exception_fp_denorm_src 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_overflow 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_underflow 0 +// ASM-NEXT: .amdhsa_exception_fp_ieee_inexact 0 +// ASM-NEXT: .amdhsa_exception_int_div_zero 0 +// ASM-NEXT: .end_amdhsa_kernel diff --git a/llvm/test/MC/AMDGPU/mcexpr_amd.s b/llvm/test/MC/AMDGPU/mcexpr_amd.s new file mode 100644 index 0000000000000000000000000000000000000000..a9639c3acc305a9bd0829dbd743dff5dbd106f69 --- /dev/null +++ b/llvm/test/MC/AMDGPU/mcexpr_amd.s @@ -0,0 +1,130 @@ +// RUN: llvm-mc -triple amdgcn-amd-amdhsa < %s | FileCheck --check-prefix=ASM %s +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -filetype=obj < %s > %t +// RUN: llvm-objdump --syms %t | FileCheck --check-prefix=OBJDUMP %s + +// OBJDUMP: SYMBOL TABLE: +// OBJDUMP-NEXT: 0000000000000000 l *ABS* 0000000000000000 zero +// OBJDUMP-NEXT: 0000000000000001 l *ABS* 0000000000000000 one +// OBJDUMP-NEXT: 0000000000000002 l *ABS* 0000000000000000 two +// OBJDUMP-NEXT: 0000000000000003 l *ABS* 0000000000000000 three +// OBJDUMP-NEXT: 7fffffffffffffff l *ABS* 0000000000000000 i64_max +// OBJDUMP-NEXT: 8000000000000000 l *ABS* 0000000000000000 i64_min +// OBJDUMP-NEXT: 0000000000000005 l *ABS* 0000000000000000 max_expression_all +// OBJDUMP-NEXT: 0000000000000005 l *ABS* 0000000000000000 five +// OBJDUMP-NEXT: 0000000000000004 l *ABS* 0000000000000000 four +// OBJDUMP-NEXT: 0000000000000002 l *ABS* 0000000000000000 max_expression_two +// OBJDUMP-NEXT: 0000000000000001 l *ABS* 0000000000000000 max_expression_one +// OBJDUMP-NEXT: 000000000000000a l *ABS* 0000000000000000 max_literals +// OBJDUMP-NEXT: 000000000000000f l *ABS* 0000000000000000 max_with_max_sym +// OBJDUMP-NEXT: 000000000000000f l *ABS* 0000000000000000 max +// OBJDUMP-NEXT: ffffffffffffffff l *ABS* 0000000000000000 neg_one +// OBJDUMP-NEXT: ffffffffffffffff l *ABS* 0000000000000000 max_neg_numbers +// OBJDUMP-NEXT: ffffffffffffffff l *ABS* 0000000000000000 max_neg_number +// OBJDUMP-NEXT: 0000000000000003 l *ABS* 0000000000000000 max_with_subexpr +// OBJDUMP-NEXT: 0000000000000006 l *ABS* 0000000000000000 max_as_subexpr +// OBJDUMP-NEXT: 0000000000000005 l *ABS* 0000000000000000 max_recursive_subexpr +// OBJDUMP-NEXT: 7fffffffffffffff l *ABS* 0000000000000000 max_expr_one_max +// OBJDUMP-NEXT: 7fffffffffffffff l *ABS* 0000000000000000 max_expr_two_max +// OBJDUMP-NEXT: 7fffffffffffffff l *ABS* 0000000000000000 max_expr_three_max +// OBJDUMP-NEXT: 8000000000000000 l *ABS* 0000000000000000 max_expr_one_min +// OBJDUMP-NEXT: 0000000000000003 l *ABS* 0000000000000000 max_expr_two_min +// OBJDUMP-NEXT: 0000000000989680 l *ABS* 0000000000000000 max_expr_three_min +// OBJDUMP-NEXT: 0000000000000007 l *ABS* 0000000000000000 or_expression_all +// OBJDUMP-NEXT: 0000000000000003 l *ABS* 0000000000000000 or_expression_two +// OBJDUMP-NEXT: 0000000000000001 l *ABS* 0000000000000000 or_expression_one +// OBJDUMP-NEXT: 000000000000000f l *ABS* 0000000000000000 or_literals +// OBJDUMP-NEXT: 0000000000000000 l *ABS* 0000000000000000 or_false +// OBJDUMP-NEXT: 00000000000000ff l *ABS* 0000000000000000 or_with_or_sym +// OBJDUMP-NEXT: 00000000000000ff l *ABS* 0000000000000000 or +// OBJDUMP-NEXT: 0000000000000003 l *ABS* 0000000000000000 or_with_subexpr +// OBJDUMP-NEXT: 0000000000000008 l *ABS* 0000000000000000 or_as_subexpr +// OBJDUMP-NEXT: 0000000000000007 l *ABS* 0000000000000000 or_recursive_subexpr + +// ASM: .set zero, 0 +// ASM: .set one, 1 +// ASM: .set two, 2 +// ASM: .set three, 3 +// ASM: .set i64_max, 9223372036854775807 +// ASM: .set i64_min, -9223372036854775808 + +.set zero, 0 +.set one, 1 +.set two, 2 +.set three, 3 +.set i64_max, 0x7FFFFFFFFFFFFFFF +.set i64_min, 0x8000000000000000 + +// ASM: .set max_expression_all, max(1, 2, five, 3, four) +// ASM: .set max_expression_two, 2 +// ASM: .set max_expression_one, 1 +// ASM: .set max_literals, 10 +// ASM: .set max_with_max_sym, max(max, 4, 3, 1, 2) + +.set max_expression_all, max(one, two, five, three, four) +.set max_expression_two, max(one, two) +.set max_expression_one, max(one) +.set max_literals, max(1,2,3,4,5,6,7,8,9,10) +.set max_with_max_sym, max(max, 4, 3, one, two) + +// ASM: .set max_neg_numbers, -1 +// ASM: .set max_neg_number, -1 + +.set neg_one, -1 +.set max_neg_numbers, max(-5, -4, -3, -2, neg_one) +.set max_neg_number, max(neg_one) + +// ASM: .set max_with_subexpr, 3 +// ASM: .set max_as_subexpr, 1+(max(4, 3, five)) +// ASM: .set max_recursive_subexpr, max(max(1, four), 3, max_expression_all) + +.set max_with_subexpr, max(((one | 3) << 3) / 8) +.set max_as_subexpr, 1 + max(4, 3, five) +.set max_recursive_subexpr, max(max(one, four), three, max_expression_all) + +// ASM: .set max_expr_one_max, 9223372036854775807 +// ASM: .set max_expr_two_max, max(9223372036854775807, five) +// ASM: .set max_expr_three_max, max(9223372036854775807, five, 10000000) + +.set max_expr_one_max, max(i64_max) +.set max_expr_two_max, max(i64_max, five) +.set max_expr_three_max, max(i64_max, five, 10000000) + +// ASM: .set max_expr_one_min, -9223372036854775808 +// ASM: .set max_expr_two_min, 3 +// ASM: .set max_expr_three_min, 10000000 + +.set max_expr_one_min, max(i64_min) +.set max_expr_two_min, max(i64_min, three) +.set max_expr_three_min, max(i64_min, three, 10000000) + +// ASM: .set or_expression_all, or(1, 2, five, 3, four) +// ASM: .set or_expression_two, 3 +// ASM: .set or_expression_one, 1 +// ASM: .set or_literals, 15 +// ASM: .set or_false, 0 +// ASM: .set or_with_or_sym, or(or, 4, 3, 1, 2) + +.set or_expression_all, or(one, two, five, three, four) +.set or_expression_two, or(one, two) +.set or_expression_one, or(one) +.set or_literals, or(1,2,3,4,5,6,7,8,9,10) +.set or_false, or(zero, 0, (2-2), 5 > 6) +.set or_with_or_sym, or(or, 4, 3, one, two) + +// ASM: .set or_with_subexpr, 3 +// ASM: .set or_as_subexpr, 1+(or(4, 3, five)) +// ASM: .set or_recursive_subexpr, or(or(1, four), 3, or_expression_all) + +.set or_with_subexpr, or(((one | 3) << 3) / 8) +.set or_as_subexpr, 1 + or(4, 3, five) +.set or_recursive_subexpr, or(or(one, four), three, or_expression_all) + +// ASM: .set four, 4 +// ASM: .set five, 5 +// ASM: .set max, 15 +// ASM: .set or, 255 + +.set four, 4 +.set five, 5 +.set max, 0xF +.set or, 0xFF diff --git a/llvm/test/MC/AMDGPU/mcexpr_amd_err.s b/llvm/test/MC/AMDGPU/mcexpr_amd_err.s new file mode 100644 index 0000000000000000000000000000000000000000..ea02e0136272189e61107b294b1606b1c5ecc6d7 --- /dev/null +++ b/llvm/test/MC/AMDGPU/mcexpr_amd_err.s @@ -0,0 +1,53 @@ +// RUN: not llvm-mc -triple amdgcn-amd-amdhsa %s 2>&1 | FileCheck --check-prefix=ASM %s + +.set one, 1 +.set two, 2 +.set three, 3 + +.set max_empty, max() +// ASM: :[[@LINE-1]]:{{[0-9]+}}: error: empty max expression +// ASM: :[[@LINE-2]]:{{[0-9]+}}: error: missing expression + +.set or_empty, or() +// ASM: :[[@LINE-1]]:{{[0-9]+}}: error: empty or expression +// ASM: :[[@LINE-2]]:{{[0-9]+}}: error: missing expression + +.set max_post_aux_comma, max(one,) +// ASM: :[[@LINE-1]]:{{[0-9]+}}: error: mismatch of commas in max expression +// ASM: :[[@LINE-2]]:{{[0-9]+}}: error: missing expression + +.set max_pre_aux_comma, max(,one) +// asm: :[[@line-1]]:{{[0-9]+}}: error: unknown token in expression +// ASM: :[[@LINE-2]]:{{[0-9]+}}: error: missing expression + +.set max_double_comma, max(one,, two) +// ASM: :[[@LINE-1]]:{{[0-9]+}}: error: unknown token in expression +// ASM: :[[@LINE-2]]:{{[0-9]+}}: error: missing expression + +.set max_no_comma, max(one two) +// ASM: :[[@LINE-1]]:{{[0-9]+}}: error: unexpected token in max expression +// ASM: :[[@LINE-2]]:{{[0-9]+}}: error: missing expression + +.set max_missing_paren, max(two +// ASM: :[[@LINE-1]]:{{[0-9]+}}: error: unexpected token in max expression +// ASM: :[[@LINE-2]]:{{[0-9]+}}: error: missing expression + +.set max_expression_one, max(three, four, +// ASM: :[[@LINE-1]]:{{[0-9]+}}: error: unknown token in expression +// ASM: :[[@LINE-2]]:{{[0-9]+}}: error: missing expression + +.set or_expression_one, or(four, five +// ASM: :[[@LINE-1]]:{{[0-9]+}}: error: unexpected token in or expression +// ASM: :[[@LINE-2]]:{{[0-9]+}}: error: missing expression + +.set max_no_lparen, max four, five) +// ASM: :[[@LINE-1]]:{{[0-9]+}}: error: expected newline + +.set max_no_paren, max one, two, three +// ASM: :[[@LINE-1]]:{{[0-9]+}}: error: expected newline + +.set max_rparen_only, max) +// ASM: :[[@LINE-1]]:{{[0-9]+}}: error: expected newline + +.set four, 4 +.set five, 5 diff --git a/llvm/test/MC/AMDGPU/vinterp-fake16.s b/llvm/test/MC/AMDGPU/vinterp-fake16.s new file mode 100644 index 0000000000000000000000000000000000000000..33dacdd92c317b8465196ebf4055b4a5f09805f9 --- /dev/null +++ b/llvm/test/MC/AMDGPU/vinterp-fake16.s @@ -0,0 +1,182 @@ +// RUN: llvm-mc -triple=amdgcn -mcpu=gfx1100 -mattr=-real-true16 -show-encoding %s | FileCheck -check-prefix=GCN %s +// RUN: llvm-mc -triple=amdgcn -mcpu=gfx1200 -mattr=-real-true16 -show-encoding %s | FileCheck -check-prefix=GCN %s + +v_interp_p10_f32 v0, v1, v2, v3 +// GCN: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p10_f32 v1, v10, v20, v30 +// GCN: v_interp_p10_f32 v1, v10, v20, v30 wait_exp:0 ; encoding: [0x01,0x00,0x00,0xcd,0x0a,0x29,0x7a,0x04] + +v_interp_p10_f32 v2, v11, v21, v31 +// GCN: v_interp_p10_f32 v2, v11, v21, v31 wait_exp:0 ; encoding: [0x02,0x00,0x00,0xcd,0x0b,0x2b,0x7e,0x04] + +v_interp_p10_f32 v3, v12, v22, v32 +// GCN: v_interp_p10_f32 v3, v12, v22, v32 wait_exp:0 ; encoding: [0x03,0x00,0x00,0xcd,0x0c,0x2d,0x82,0x04] + +v_interp_p10_f32 v0, v1, v2, v3 clamp +// GCN: v_interp_p10_f32 v0, v1, v2, v3 clamp wait_exp:0 ; encoding: [0x00,0x80,0x00,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p10_f32 v0, -v1, v2, v3 +// GCN: v_interp_p10_f32 v0, -v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x24] + +v_interp_p10_f32 v0, v1, -v2, v3 +// GCN: v_interp_p10_f32 v0, v1, -v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x44] + +v_interp_p10_f32 v0, v1, v2, -v3 +// GCN: v_interp_p10_f32 v0, v1, v2, -v3 wait_exp:0 ; encoding: [0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x84] + +v_interp_p10_f32 v0, v1, v2, v3 wait_exp:0 +// GCN: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p10_f32 v0, v1, v2, v3 wait_exp:1 +// GCN: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:1 ; encoding: [0x00,0x01,0x00,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p10_f32 v0, v1, v2, v3 wait_exp:7 +// GCN: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:7 ; encoding: [0x00,0x07,0x00,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p10_f32 v0, v1, v2, v3 clamp wait_exp:7 +// GCN: v_interp_p10_f32 v0, v1, v2, v3 clamp wait_exp:7 ; encoding: [0x00,0x87,0x00,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p2_f32 v0, v1, v2, v3 +// GCN: v_interp_p2_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p2_f32 v1, v10, v20, v30 +// GCN: v_interp_p2_f32 v1, v10, v20, v30 wait_exp:0 ; encoding: [0x01,0x00,0x01,0xcd,0x0a,0x29,0x7a,0x04] + +v_interp_p2_f32 v2, v11, v21, v31 +// GCN: v_interp_p2_f32 v2, v11, v21, v31 wait_exp:0 ; encoding: [0x02,0x00,0x01,0xcd,0x0b,0x2b,0x7e,0x04] + +v_interp_p2_f32 v3, v12, v22, v32 +// GCN: v_interp_p2_f32 v3, v12, v22, v32 wait_exp:0 ; encoding: [0x03,0x00,0x01,0xcd,0x0c,0x2d,0x82,0x04] + +v_interp_p2_f32 v0, v1, v2, v3 clamp +// GCN: v_interp_p2_f32 v0, v1, v2, v3 clamp wait_exp:0 ; encoding: [0x00,0x80,0x01,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p2_f32 v0, -v1, v2, v3 +// GCN: v_interp_p2_f32 v0, -v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x24] + +v_interp_p2_f32 v0, v1, -v2, v3 +// GCN: v_interp_p2_f32 v0, v1, -v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x44] + +v_interp_p2_f32 v0, v1, v2, -v3 +// GCN: v_interp_p2_f32 v0, v1, v2, -v3 wait_exp:0 ; encoding: [0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x84] + +v_interp_p2_f32 v0, v1, v2, v3 wait_exp:0 +// GCN: v_interp_p2_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p2_f32 v0, v1, v2, v3 wait_exp:1 +// GCN: v_interp_p2_f32 v0, v1, v2, v3 wait_exp:1 ; encoding: [0x00,0x01,0x01,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p2_f32 v0, v1, v2, v3 wait_exp:7 +// GCN: v_interp_p2_f32 v0, v1, v2, v3 wait_exp:7 ; encoding: [0x00,0x07,0x01,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p2_f32 v0, v1, v2, v3 clamp wait_exp:7 +// GCN: v_interp_p2_f32 v0, v1, v2, v3 clamp wait_exp:7 ; encoding: [0x00,0x87,0x01,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p10_f16_f32 v0, v1, v2, v3 +// GFX11: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p10_f16_f32 v0, -v1, v2, v3 +// GFX11: v_interp_p10_f16_f32 v0, -v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x24] + +v_interp_p10_f16_f32 v0, v1, -v2, v3 +// GFX11: v_interp_p10_f16_f32 v0, v1, -v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x44] + +v_interp_p10_f16_f32 v0, v1, v2, -v3 +// GFX11: v_interp_p10_f16_f32 v0, v1, v2, -v3 wait_exp:0 ; encoding: [0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x84] + +v_interp_p10_f16_f32 v0, v1, v2, v3 clamp +// GFX11: v_interp_p10_f16_f32 v0, v1, v2, v3 clamp wait_exp:0 ; encoding: [0x00,0x80,0x02,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:0 +// GFX11: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:1 +// GFX11: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:1 ; encoding: [0x00,0x01,0x02,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:7 +// GFX11: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:7 ; encoding: [0x00,0x07,0x02,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p10_f16_f32 v0, v1, v2, v3 +// GFX11: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p2_f16_f32 v0, v1, v2, v3 +// GFX11: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p2_f16_f32 v0, -v1, v2, v3 +// GFX11: v_interp_p2_f16_f32 v0, -v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x24] + +v_interp_p2_f16_f32 v0, v1, -v2, v3 +// GFX11: v_interp_p2_f16_f32 v0, v1, -v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x44] + +v_interp_p2_f16_f32 v0, v1, v2, -v3 +// GFX11: v_interp_p2_f16_f32 v0, v1, v2, -v3 wait_exp:0 ; encoding: [0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x84] + +v_interp_p2_f16_f32 v0, v1, v2, v3 clamp +// GFX11: v_interp_p2_f16_f32 v0, v1, v2, v3 clamp wait_exp:0 ; encoding: [0x00,0x80,0x03,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:0 +// GFX11: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:1 +// GFX11: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:1 ; encoding: [0x00,0x01,0x03,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:7 +// GFX11: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:7 ; encoding: [0x00,0x07,0x03,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p2_f16_f32 v0, v1, v2, v3 +// GFX11: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 +// GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p10_rtz_f16_f32 v0, -v1, v2, v3 +// GFX11: v_interp_p10_rtz_f16_f32 v0, -v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x24] + +v_interp_p10_rtz_f16_f32 v0, v1, -v2, v3 +// GFX11: v_interp_p10_rtz_f16_f32 v0, v1, -v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x44] + +v_interp_p10_rtz_f16_f32 v0, v1, v2, -v3 +// GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, -v3 wait_exp:0 ; encoding: [0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x84] + +v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 clamp +// GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 clamp wait_exp:0 ; encoding: [0x00,0x80,0x04,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0 +// GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:1 +// GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:1 ; encoding: [0x00,0x01,0x04,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:7 +// GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:7 ; encoding: [0x00,0x07,0x04,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 +// GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 +// GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p2_rtz_f16_f32 v0, -v1, v2, v3 +// GFX11: v_interp_p2_rtz_f16_f32 v0, -v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x24] + +v_interp_p2_rtz_f16_f32 v0, v1, -v2, v3 +// GFX11: v_interp_p2_rtz_f16_f32 v0, v1, -v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x44] + +v_interp_p2_rtz_f16_f32 v0, v1, v2, -v3 +// GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, -v3 wait_exp:0 ; encoding: [0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x84] + +v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 clamp +// GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 clamp wait_exp:0 ; encoding: [0x00,0x80,0x05,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0 +// GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:1 +// GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:1 ; encoding: [0x00,0x01,0x05,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:7 +// GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:7 ; encoding: [0x00,0x07,0x05,0xcd,0x01,0x05,0x0e,0x04] + +v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 +// GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x04] diff --git a/llvm/test/MC/ARM/arm-branch-errors.s b/llvm/test/MC/ARM/arm-branch-errors.s index bbf6445f5c18a4ab817094c7002afc60292ab578..5d7ae12fb3bc0064b10424d02b83f544e6a750a7 100644 --- a/llvm/test/MC/ARM/arm-branch-errors.s +++ b/llvm/test/MC/ARM/arm-branch-errors.s @@ -10,13 +10,13 @@ @ CHECK: error: invalid instruction, any one of the following would fix this: @ CHECK: b #2 -@ CHECK: note: instruction requires: thumb @ CHECK: note: invalid operand for instruction +@ CHECK: note: instruction requires: thumb @ CHECK: error: invalid instruction, any one of the following would fix this: @ CHECK: bl #2 @ CHECK: note: instruction requires: thumb @ CHECK: note: invalid operand for instruction @ CHECK: error: invalid instruction, any one of the following would fix this: @ CHECK: beq #2 -@ CHECK: note: instruction requires: thumb @ CHECK: note: invalid operand for instruction +@ CHECK: note: instruction requires: thumb diff --git a/llvm/test/MC/ARM/arm11-hint-instr.s b/llvm/test/MC/ARM/arm11-hint-instr.s index 4193a686870aba2e0d47f2b18d5c1616b26ee365..d9eaa5a89ab230f224275f2c364a1f6afd8b9269 100644 --- a/llvm/test/MC/ARM/arm11-hint-instr.s +++ b/llvm/test/MC/ARM/arm11-hint-instr.s @@ -65,7 +65,13 @@ @ CHECK-THUMB: wfe @ encoding: [0x20,0xbf] @ CHECK-THUMB: wfi @ encoding: [0x30,0xbf] @ CHECK-THUMB: sev @ encoding: [0x40,0xbf] -@ CHECK-ERROR-THUMB: error: instruction requires: v7 clrex +@ CHECK-ERROR-THUMB: error: invalid instruction, any one of the following would fix this: +@ CHECK-ERROR-THUMB: clrex +@ CHECK-ERROR-THUMB: ^ +@ CHECK-ERROR-THUMB: note: instruction requires: v7 clrex +@ CHECK-ERROR-THUMB: clrex +@ CHECK-ERROR-THUMB: ^ +@ CHECK-ERROR-THUMB: note: instruction requires: arm-mode @ CHECK-ERROR-THUMB: clrex @ CHECK-ERROR-THUMB: ^ diff --git a/llvm/test/MC/ARM/basic-arm-instructions.s b/llvm/test/MC/ARM/basic-arm-instructions.s index 055f3ce316153d087882c91db8365e80d5bae286..9f3a5cd4afa792df9edaf9ccf8a1796ed6641f89 100644 --- a/llvm/test/MC/ARM/basic-arm-instructions.s +++ b/llvm/test/MC/ARM/basic-arm-instructions.s @@ -1202,6 +1202,10 @@ Lforward: @ CHECK: ldrex r1, [r7] @ encoding: [0x9f,0x1f,0x97,0xe1] @ CHECK: ldrexd r6, r7, [r8] @ encoding: [0x9f,0x6f,0xb8,0xe1] +@ GNU alias + ldrexd r6, [r8] +@ CHECK: ldrexd r6, r7, [r8] @ encoding: [0x9f,0x6f,0xb8,0xe1] + @------------------------------------------------------------------------------ @ LDRHT @------------------------------------------------------------------------------ @@ -1774,6 +1778,9 @@ Lforward: pkhtb r2, r2, r3, asr #31 pkhtb r2, r2, r3, asr #15 + it ne + pkhtbne r2, r2, r3, asr #15 + @ CHECK: pkhbt r2, r2, r3 @ encoding: [0x13,0x20,0x82,0xe6] @ CHECK: pkhbt r2, r2, r3, lsl #31 @ encoding: [0x93,0x2f,0x82,0xe6] @ CHECK: pkhbt r2, r2, r3 @ encoding: [0x13,0x20,0x82,0xe6] @@ -1782,6 +1789,7 @@ Lforward: @ CHECK: pkhbt r2, r3, r2 @ encoding: [0x12,0x20,0x83,0xe6] @ CHECK: pkhtb r2, r2, r3, asr #31 @ encoding: [0xd3,0x2f,0x82,0xe6] @ CHECK: pkhtb r2, r2, r3, asr #15 @ encoding: [0xd3,0x27,0x82,0xe6] +@ CHECK: pkhtbne r2, r2, r3, asr #15 @ encoding: [0xd3,0x27,0x82,0x16] @------------------------------------------------------------------------------ @ FIXME: PLD @@ -2900,6 +2908,10 @@ Lforward: @ CHECK: strex r2, r1, [r7] @ encoding: [0x91,0x2f,0x87,0xe1] @ CHECK: strexd r6, r2, r3, [r8] @ encoding: [0x92,0x6f,0xa8,0xe1] +@ GNU alias + strexd r6, r2, [r8] +@ CHECK: strexd r6, r2, r3, [r8] @ encoding: [0x92,0x6f,0xa8,0xe1] + @------------------------------------------------------------------------------ @ STR @------------------------------------------------------------------------------ diff --git a/llvm/test/MC/ARM/cde-fp-vec.s b/llvm/test/MC/ARM/cde-fp-vec.s index 4b139579b719ba86551f2d7a18ed05aae9a6142a..fa18ffa766e2e3cd7114774cea942c0b9c9d54ab 100644 --- a/llvm/test/MC/ARM/cde-fp-vec.s +++ b/llvm/test/MC/ARM/cde-fp-vec.s @@ -12,7 +12,7 @@ ittt eq vcx1a p1, s7, #2047 // ERROR: [[@LINE+1]]:{{[0-9]+}}: error: instructions in IT block must be predicable vcx2 p0, d0, d15, #0 -// ERROR-FP: [[@LINE+2]]:{{[0-9]+}}: error: invalid instruction +// ERROR-FP: [[@LINE+2]]:{{[0-9]+}}: error: instruction requires: mve // ERROR-MVE: [[@LINE+1]]:{{[0-9]+}}: error: instructions in IT block must be predicable vcx3 p0, q0, q7, q0, #12 nop @@ -33,12 +33,15 @@ vcx1a p1, d3, #2047 // ERROR-FP: [[@LINE+1]]:{{[0-9]+}}: error: invalid instruction, any one of the following would fix this: vcx1 p0, q1, #1234 // CHECK-MVE-NEXT: vcx1a p1, q5, #4095 @ encoding: [0x2f,0xfd,0xff,0xa1] -// ERROR-FP: [[@LINE+1]]:{{[0-9]+}}: error: invalid instruction +// ERROR-FP: [[@LINE+1]]:{{[0-9]+}}: error: instruction requires: mve vcx1a p1, q5, #4095 // ERROR: [[@LINE+1]]:{{[0-9]+}}: error: invalid instruction vcx1a p1, s7, s7, #2047 -// ERROR: [[@LINE+1]]:{{[0-9]+}}: error: operand must be an immediate in the range [0,2047] +// ERROR-FP: [[@LINE+4]]:{{[0-9]+}}: error: operand must be an immediate in the range [0,2047] +// ERROR-MVE: [[@LINE+3]]:{{[0-9]+}}: error: invalid instruction, any one of the following would fix this +// ERROR-MVE: [[@LINE+2]]:{{[0-9]+}}: note: operand must be a register in range [q0, q7] +// ERROR-MVE: [[@LINE+1]]:{{[0-9]+}}: note: operand must be an immediate in the range [0,2047] vcx1 p0, d0, #2048 // ERROR-FP: [[@LINE+1]]:{{[0-9]+}}: error: operand must be an immediate in the range [0,2047] vcx1a p1, s0, #2048 @@ -51,10 +54,13 @@ vcx1 p8, d0, #1234 vcx1 p0, d16, #1234 // ERROR: [[@LINE+1]]:{{[0-9]+}}: error: invalid instruction vcx1 p0, s32, #1234 -// ERROR-FP: [[@LINE+4]]:{{[0-9]+}}: error: invalid instruction, any one of the following would fix this: -// ERROR-FP: [[@LINE+3]]:{{[0-9]+}}: note: operand must be a register in range [s0, s31] -// ERROR-FP: [[@LINE+2]]:{{[0-9]+}}: note: operand must be a register in range [d0, d15] -// ERROR-MVE: [[@LINE+1]]:{{[0-9]+}}: error: operand must be a register in range [q0, q7] +// ERROR-FP: [[@LINE+7]]:{{[0-9]+}}: error: invalid instruction, any one of the following would fix this: +// ERROR-FP: [[@LINE+6]]:{{[0-9]+}}: note: operand must be a register in range [s0, s31] +// ERROR-FP: [[@LINE+5]]:{{[0-9]+}}: note: operand must be a register in range [d0, d15] +// ERROR-MVE: [[@LINE+4]]:{{[0-9]+}}: error: invalid instruction, any one of the following would fix this: +// ERROR-MVE: [[@LINE+3]]:{{[0-9]+}}: note: operand must be a register in range [q0, q7] +// ERROR-MVE: [[@LINE+2]]:{{[0-9]+}}: note: operand must be a register in range [s0, s31] +// ERROR-MVE: [[@LINE+1]]:{{[0-9]+}}: note: operand must be a register in range [d0, d15] vcx1 p0, q8, #1234 // ERROR: [[@LINE+3]]:{{[0-9]+}}: error: invalid instruction, any one of the following would fix this: // ERROR: [[@LINE+2]]:{{[0-9]+}}: note: operand must be a register in range [s0, s31] @@ -116,7 +122,7 @@ vcx3a p1, d1, d11, d12, #8 // ERROR-MVE: [[@LINE+2]]:{{[0-9]+}}: error: operand must be an immediate in the range [0,15] // ERROR-FP: error: invalid instruction vcx3a p1, q1, q2, q3, #16 -// ERROR-MVE: [[@LINE+2]]:{{[0-9]+}}: error: invalid instruction +// ERROR-MVE: [[@LINE+2]]:{{[0-9]+}}: error: operand must be a register in range [d0, d15] // ERROR-FP: [[@LINE+1]]:{{[0-9]+}}: error: operand must be a register in range [d0, d15] vcx3 p0, d0, q0, d7, #1 // ERROR: [[@LINE+1]]:{{[0-9]+}}: error: operand must be a register in range [s0, s31] diff --git a/llvm/test/MC/ARM/cde-vec-pred.s b/llvm/test/MC/ARM/cde-vec-pred.s index 6274fafa1224a4fbbb9b9b592248f9b55f29a93e..9932f8d000337c1dc87dd22d47c6b390b7f3e0a0 100644 --- a/llvm/test/MC/ARM/cde-vec-pred.s +++ b/llvm/test/MC/ARM/cde-vec-pred.s @@ -19,7 +19,7 @@ vcx3at p1, q3, q7, q6, #15 vcx3e p0, q0, q2, q0, #12 vpt.i8 eq, q0, q0 -// ERROR: [[@LINE+1]]:{{[0-9]+}}: error: incorrect predication in VPT block; got 'none', but expected 't' +// ERROR: error: incorrect predication in VPT block; got 'none', but expected 't' vcx1 p0, q1, #1234 vpt.i8 eq, q0, q0 diff --git a/llvm/test/MC/ARM/cps.s b/llvm/test/MC/ARM/cps.s index bafdfdea537b8b3bff5dbe0318b122fca0523d4a..1034ed93810dd44adb0dfdb081c70c7aa32d77a4 100644 --- a/llvm/test/MC/ARM/cps.s +++ b/llvm/test/MC/ARM/cps.s @@ -26,6 +26,6 @@ @ V6-ERRORS: note: too many operands for instruction @ V6-ERRORS: error: invalid instruction, any one of the following would fix this: @ V6-ERRORS: cps #0 -@ V6-ERRORS: note: too few operands for instruction @ V6-ERRORS: note: instruction requires: arm-mode @ V6-ERRORS: note: instruction requires: thumb2 +@ V6-ERRORS: note: too few operands for instruction diff --git a/llvm/test/MC/ARM/diagnostics.s b/llvm/test/MC/ARM/diagnostics.s index e6d80ea7a6280c3626deaf73e339324f66db8805..fa23a7da1e404892215e9974036e6589aba730d8 100644 --- a/llvm/test/MC/ARM/diagnostics.s +++ b/llvm/test/MC/ARM/diagnostics.s @@ -288,7 +288,7 @@ @ CHECK-ERRORS: error: 'asr' shift amount must be in range [1,32] @ CHECK-ERRORS: ssat r8, #1, r10, asr #33 @ CHECK-ERRORS: ^ -@ CHECK-ERRORS: error: shift operator 'asr' or 'lsl' expected +@ CHECK-ERRORS: error: operand must be a register in range [r0, r14] @ CHECK-ERRORS: ssat r8, #1, r10, lsr #5 @ CHECK-ERRORS: ^ @ CHECK-ERRORS: error: '#' expected diff --git a/llvm/test/MC/ARM/directive-arch_extension-crypto.s b/llvm/test/MC/ARM/directive-arch_extension-crypto.s index 8d3cd9e5e1d0dafe25be40fe76a134af3e941cf3..05b6d9e040188ed087abfadb5d0de980b2e25c7d 100644 --- a/llvm/test/MC/ARM/directive-arch_extension-crypto.s +++ b/llvm/test/MC/ARM/directive-arch_extension-crypto.s @@ -10,15 +10,16 @@ .syntax unified .arch_extension crypto -@ CHECK-V7: error: architectural extension 'crypto' is not allowed for the current base architecture +@ CHECK-V7: architectural extension 'crypto' is not allowed for the current base architecture @ CHECK-V7-NEXT: .arch_extension crypto @ CHECK-V7-NEXT: ^ .type crypto,%function crypto: vmull.p64 q0, d0, d1 -@ CHECK-V7: error: instruction requires: aes armv8 - +@ CHECK-V7: error: invalid instruction, any one of the following would fix this: +@ CHECK-V7: note: invalid operand for instruction +@ CHECK-V7: note: instruction requires: aes armv8 aesd.8 q0, q1 @ CHECK-V7: error: instruction requires: aes armv8 aese.8 q0, q1 @@ -51,14 +52,18 @@ crypto: @ CHECK-V7: error: instruction requires: sha2 armv8 .arch_extension nocrypto +@ CHECK-V7: error: architectural extension 'sha2' is not allowed for the current base architecture +@ CHECK-V7: error: architectural extension 'aes' is not allowed for the current base architecture @ CHECK-V7: error: architectural extension 'crypto' is not allowed for the current base architecture -@ CHECK-V7-NEXT: .arch_extension nocrypto +@ CHECK-V7-NEXT: .arch_extension nocrypto @ CHECK-V7-NEXT: ^ .type nocrypto,%function nocrypto: vmull.p64 q0, d0, d1 -@ CHECK-V7: error: instruction requires: aes armv8 +@ CHECK-V7: error: invalid instruction, any one of the following +@ CHECK-V7: note: invalid operand for instruction +@ CHECK-V7: note: instruction requires: aes armv8 @ CHECK-V8: error: instruction requires: aes aesd.8 q0, q1 diff --git a/llvm/test/MC/ARM/invalid-fp-armv8.s b/llvm/test/MC/ARM/invalid-fp-armv8.s index dca0e448d1140fc0a475ea3fe2f53f55bef5e3cf..c8ce261791cfd03df1e6bbeeadef6e35a907303a 100644 --- a/llvm/test/MC/ARM/invalid-fp-armv8.s +++ b/llvm/test/MC/ARM/invalid-fp-armv8.s @@ -88,6 +88,8 @@ vrinta.f64.f64 s3, q0 vrintn.f32.f32 d3, d0 @ V8: error: instruction requires: NEON vrintp.f32 q3, q0 -@ V8: error: instruction requires: NEON +@ V8: error: invalid instruction, any one of the following would fix this: +@ V8: note: instruction requires: mve.fp +@ V8: note: instruction requires: NEON vrintmlt.f32 q3, q0 @ V8: error: instruction 'vrintm' is not predicable, but condition code specified diff --git a/llvm/test/MC/ARM/load-store-acquire-release-v8-thumb.s b/llvm/test/MC/ARM/load-store-acquire-release-v8-thumb.s index be8d3c324e68231e20fef312e8eda4c44b5f9d85..b802bfdb28f7de556238f072fc564c3b1ea3e366 100644 --- a/llvm/test/MC/ARM/load-store-acquire-release-v8-thumb.s +++ b/llvm/test/MC/ARM/load-store-acquire-release-v8-thumb.s @@ -14,6 +14,10 @@ @ CHECK-V7: error: instruction requires: acquire/release @ CHECK-V7: error: instruction requires: acquire/release +@ GNU alias + ldaexd r6, [r8] +@ CHECK: ldaexd r6, r7, [r8] @ encoding: [0xd8,0xe8,0xff,0x67] + stlexb r1, r3, [r4] stlexh r4, r2, [r5] stlex r2, r1, [r7] @@ -27,6 +31,10 @@ @ CHECK-V7: error: instruction requires: acquire/release @ CHECK-V7: error: instruction requires: acquire/release +@ GNU alias + stlexd r6, r2, [r8] +@ CHECK: stlexd r6, r2, r3, [r8] @ encoding: [0xc8,0xe8,0xf6,0x23] + lda r5, [r6] ldab r5, [r6] ldah r12, [r9] diff --git a/llvm/test/MC/ARM/load-store-acquire-release-v8.s b/llvm/test/MC/ARM/load-store-acquire-release-v8.s index 273519e050b1c5377baa02bb95db7dc8f0317056..edfe14c93e4ead564ff028f3179f298c8ea6566c 100644 --- a/llvm/test/MC/ARM/load-store-acquire-release-v8.s +++ b/llvm/test/MC/ARM/load-store-acquire-release-v8.s @@ -1,4 +1,5 @@ -@ RUN: llvm-mc -triple=armv8 -show-encoding < %s | FileCheck %s +@ RUN: not llvm-mc -triple=armv8 -show-encoding < %s 2> %t | FileCheck %s +@ RUN: FileCheck %s < %t --check-prefix=CHECK-ERROR @ RUN: not llvm-mc -triple=armv7 -show-encoding < %s 2>&1 | FileCheck %s --check-prefix=CHECK-V7 ldaexb r3, [r4] ldaexh r2, [r5] @@ -14,6 +15,13 @@ @ CHECK-V7: instruction requires: acquire/release @ CHECK-V7: instruction requires: acquire/release + ldaexd r2, r4, [r8] +@ CHECK-ERROR: error: destination operands must be sequential + +@ GNU alias + ldaexd r6, [r8] +@ CHECK: ldaexd r6, r7, [r8] @ encoding: [0x9f,0x6e,0xb8,0xe1] + stlexb r1, r3, [r4] stlexh r4, r2, [r5] stlex r2, r1, [r7] @@ -27,6 +35,13 @@ @ CHECK-V7: instruction requires: acquire/release @ CHECK-V7: instruction requires: acquire/release + stlexd r6, r2, r4, [r8] +@ CHECK-ERROR: error: source operands must be sequential + +@ GNU alias + stlexd r6, r2, [r8] +@ CHECK: stlexd r6, r2, r3, [r8] @ encoding: [0x92,0x6e,0xa8,0xe1] + lda r5, [r6] ldab r5, [r6] ldah r12, [r9] diff --git a/llvm/test/MC/ARM/lsl-zero-errors.s b/llvm/test/MC/ARM/lsl-zero-errors.s index e021aa9eb986d5854a82dc7751eba2343b32a9db..1e51c587211d1b5a5b6dc368da7aa21f8d8d136b 100644 --- a/llvm/test/MC/ARM/lsl-zero-errors.s +++ b/llvm/test/MC/ARM/lsl-zero-errors.s @@ -55,22 +55,22 @@ // CHECK-NONARM: error: invalid instruction, any one of the following would fix this: // CHECK-NONARM-NEXT: mov pc, r0, lsl #0 -// CHECK-NONARM: note: operand must be a register in range [r0, r15] // CHECK-THUMBV7: note: operand must be a register in range [r0, r12] or r14 // CHECK-THUMBV8: note: operand must be a register in range [r0, r14] +// CHECK-NONARM: note: operand must be a register in range [r0, r15] // CHECK-NONARM: error: invalid instruction, any one of the following would fix this: // CHECK-NONARM-NEXT: mov r0, pc, lsl #0 -// CHECK-NONARM: note: operand must be a register in range [r0, r15] // CHECK-NONARM: note: invalid operand for instruction // CHECK-NONARM: note: invalid operand for instruction // CHECK-NONARM: note: operand must be an immediate in the range [256,65535] +// CHECK-NONARM: note: operand must be a register in range [r0, r15] // CHECK-NONARM: error: invalid instruction, any one of the following would fix this: // CHECK-NONARM-NEXT: mov pc, pc, lsl #0 -// CHECK-NONARM: note: operand must be a register in range [r0, r15] // CHECK-THUMBV7: note: operand must be a register in range [r0, r12] or r14 // CHECK-THUMBV8: note: operand must be a register in range [r0, r14] +// CHECK-NONARM: note: operand must be a register in range [r0, r15] // CHECK-NONARM: error: invalid instruction, any one of the following would fix this: // CHECK-NONARM-NEXT: movs pc, r0, lsl #0 @@ -134,8 +134,8 @@ // FIXME: We should consistently have the "requires ARMv8" error here // CHECK-THUMBV7: error: invalid instruction, any one of the following would fix this: // CHECK-THUMBV7-NEXT: mov sp, sp, lsl #0 -// CHECK-THUMBV7: note: operand must be a register in range [r0, r15] // CHECK-THUMBV7: note: operand must be a register in range [r0, r12] or r14 +// CHECK-THUMBV7: note: operand must be a register in range [r0, r15] // CHECK-THUMBV7: error: invalid instruction, any one of the following would fix this: // CHECK-THUMBV7-NEXT: movs sp, sp, lsl #0 diff --git a/llvm/test/MC/ARM/mve-load-store.s b/llvm/test/MC/ARM/mve-load-store.s index 5c6d2a172b252c461cc92519b1efd24585ce7132..797ab1e22dd0107cf22f325ef1fc73da0e32f1dd 100644 --- a/llvm/test/MC/ARM/mve-load-store.s +++ b/llvm/test/MC/ARM/mve-load-store.s @@ -5,55 +5,55 @@ # RUN: FileCheck --check-prefix=ERROR-NOMVE < %t %s # CHECK: vldrb.u8 q0, [r0] @ encoding: [0x90,0xed,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q0, [r0] # CHECK: vldrb.u8 q1, [r0] @ encoding: [0x90,0xed,0x00,0x3e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q1, [r0] # CHECK: vldrb.u8 q0, [r11] @ encoding: [0x9b,0xed,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q0, [r11] # CHECK: vldrb.u8 q3, [r11] @ encoding: [0x9b,0xed,0x00,0x7e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q3, [r11] # CHECK: vldrb.u8 q0, [r4, #56] @ encoding: [0x94,0xed,0x38,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q0, [r4, #56] # CHECK: vldrb.u8 q4, [r4, #56] @ encoding: [0x94,0xed,0x38,0x9e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q4, [r4, #56] # CHECK: vldrb.u8 q0, [r8, #56] @ encoding: [0x98,0xed,0x38,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q0, [r8, #56] # CHECK: vldrb.u8 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x38,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q5, [r4, #56]! # CHECK: vldrb.u8 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x38,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q5, [r4, #56]! # CHECK: vldrb.u8 q5, [r4], #-25 @ encoding: [0x34,0xec,0x19,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q5, [r4], #-25 # CHECK: vldrb.u8 q5, [r10], #-25 @ encoding: [0x3a,0xec,0x19,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q5, [r10], #-25 # CHECK: vldrb.u8 q5, [sp, #-25] @ encoding: [0x1d,0xed,0x19,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q5, [sp, #-25] # CHECK: vldrb.u8 q5, [sp, #-127] @ encoding: [0x1d,0xed,0x7f,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q5, [sp, #-127] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: invalid operand for instruction @@ -69,55 +69,55 @@ vldrb.u8 q0, [r0, #-128]! vldrb.u8 q0, [r0], #128 # CHECK: vstrb.8 q0, [r0] @ encoding: [0x80,0xed,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q0, [r0] # CHECK: vstrb.8 q1, [r0] @ encoding: [0x80,0xed,0x00,0x3e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q1, [r0] # CHECK: vstrb.8 q0, [r11] @ encoding: [0x8b,0xed,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q0, [r11] # CHECK: vstrb.8 q3, [r11] @ encoding: [0x8b,0xed,0x00,0x7e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q3, [r11] # CHECK: vstrb.8 q0, [r4, #56] @ encoding: [0x84,0xed,0x38,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q0, [r4, #56] # CHECK: vstrb.8 q4, [r4, #56] @ encoding: [0x84,0xed,0x38,0x9e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q4, [r4, #56] # CHECK: vstrb.8 q0, [r8, #56] @ encoding: [0x88,0xed,0x38,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q0, [r8, #56] # CHECK: vstrb.8 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x38,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q5, [r4, #56]! # CHECK: vstrb.8 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x38,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q5, [r4, #56]! # CHECK: vstrb.8 q5, [r4], #-25 @ encoding: [0x24,0xec,0x19,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q5, [r4], #-25 # CHECK: vstrb.8 q5, [r10], #-25 @ encoding: [0x2a,0xec,0x19,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q5, [r10], #-25 # CHECK: vstrb.8 q5, [sp, #-25] @ encoding: [0x0d,0xed,0x19,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q5, [sp, #-25] # CHECK: vstrb.8 q5, [sp, #127] @ encoding: [0x8d,0xed,0x7f,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q5, [sp, #127] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: invalid operand for instruction @@ -133,735 +133,735 @@ vstrb.u8 q0, [r0, #-128]! vstrb.u8 q0, [r0], #128 # CHECK: vldrb.u16 q0, [r0] @ encoding: [0x90,0xfd,0x80,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q0, [r0] # CHECK: vldrb.u16 q1, [r0] @ encoding: [0x90,0xfd,0x80,0x2e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q1, [r0] # CHECK: vldrb.u16 q0, [r7] @ encoding: [0x97,0xfd,0x80,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q0, [r7] # CHECK: vldrb.u16 q3, [r7] @ encoding: [0x97,0xfd,0x80,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q3, [r7] # CHECK: vldrb.u16 q0, [r4, #56] @ encoding: [0x94,0xfd,0xb8,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q0, [r4, #56] # CHECK: vldrb.u16 q4, [r4, #56] @ encoding: [0x94,0xfd,0xb8,0x8e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q4, [r4, #56] # CHECK: vldrb.u16 q0, [r2, #56] @ encoding: [0x92,0xfd,0xb8,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q0, [r2, #56] # CHECK: vldrb.u16 q5, [r4, #56]! @ encoding: [0xb4,0xfd,0xb8,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q5, [r4, #56]! # CHECK: vldrb.u16 q5, [r4, #56]! @ encoding: [0xb4,0xfd,0xb8,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q5, [r4, #56]! # CHECK: vldrb.u16 q5, [r4], #-1 @ encoding: [0x34,0xfc,0x81,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q5, [r4], #-1 # CHECK: vldrb.u16 q5, [r3], #-25 @ encoding: [0x33,0xfc,0x99,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q5, [r3], #-25 # CHECK: vldrb.u16 q5, [r6, #-25] @ encoding: [0x16,0xfd,0x99,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q5, [r6, #-25] # CHECK: vldrb.u16 q5, [r6, #-64] @ encoding: [0x16,0xfd,0xc0,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q5, [r6, #-64] # CHECK: vldrb.s16 q0, [r0] @ encoding: [0x90,0xed,0x80,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q0, [r0] # CHECK: vldrb.s16 q1, [r0] @ encoding: [0x90,0xed,0x80,0x2e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q1, [r0] # CHECK: vldrb.s16 q0, [r7] @ encoding: [0x97,0xed,0x80,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q0, [r7] # CHECK: vldrb.s16 q3, [r7] @ encoding: [0x97,0xed,0x80,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q3, [r7] # CHECK: vldrb.s16 q0, [r4, #56] @ encoding: [0x94,0xed,0xb8,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q0, [r4, #56] # CHECK: vldrb.s16 q4, [r4, #56] @ encoding: [0x94,0xed,0xb8,0x8e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q4, [r4, #56] # CHECK: vldrb.s16 q0, [r2, #56] @ encoding: [0x92,0xed,0xb8,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q0, [r2, #56] # CHECK: vldrb.s16 q5, [r4, #56]! @ encoding: [0xb4,0xed,0xb8,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q5, [r4, #56]! # CHECK: vldrb.s16 q5, [r4, #56]! @ encoding: [0xb4,0xed,0xb8,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q5, [r4, #56]! # CHECK: vldrb.s16 q5, [r4], #-25 @ encoding: [0x34,0xec,0x99,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q5, [r4], #-25 # CHECK: vldrb.s16 q5, [r3], #-25 @ encoding: [0x33,0xec,0x99,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q5, [r3], #-25 # CHECK: vldrb.s16 q5, [r6, #-25] @ encoding: [0x16,0xed,0x99,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q5, [r6, #-25] # CHECK: vldrb.s16 q5, [r6, #-64] @ encoding: [0x16,0xed,0xc0,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q5, [r6, #-64] # CHECK: vstrb.16 q0, [r0] @ encoding: [0x80,0xed,0x80,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q0, [r0] # CHECK: vstrb.16 q1, [r0] @ encoding: [0x80,0xed,0x80,0x2e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q1, [r0] # CHECK: vstrb.16 q0, [r7] @ encoding: [0x87,0xed,0x80,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q0, [r7] # CHECK: vstrb.16 q3, [r7] @ encoding: [0x87,0xed,0x80,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q3, [r7] # CHECK: vstrb.16 q0, [r4, #56] @ encoding: [0x84,0xed,0xb8,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q0, [r4, #56] # CHECK: vstrb.16 q4, [r4, #56] @ encoding: [0x84,0xed,0xb8,0x8e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q4, [r4, #56] # CHECK: vstrb.16 q0, [r5, #56] @ encoding: [0x85,0xed,0xb8,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q0, [r5, #56] # CHECK: vstrb.16 q5, [r4, #56]! @ encoding: [0xa4,0xed,0xb8,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q5, [r4, #56]! # CHECK: vstrb.16 q5, [r4, #56]! @ encoding: [0xa4,0xed,0xb8,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q5, [r4, #56]! # CHECK: vstrb.16 q5, [r4], #-25 @ encoding: [0x24,0xec,0x99,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q5, [r4], #-25 # CHECK: vstrb.16 q5, [r3], #-25 @ encoding: [0x23,0xec,0x99,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q5, [r3], #-25 # CHECK: vstrb.16 q5, [r2, #-25] @ encoding: [0x02,0xed,0x99,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q5, [r2, #-25] # CHECK: vstrb.16 q5, [r2, #-64] @ encoding: [0x02,0xed,0xc0,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q5, [r2, #-64] # CHECK: vldrb.u32 q0, [r0] @ encoding: [0x90,0xfd,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q0, [r0] # CHECK: vldrb.u32 q1, [r0] @ encoding: [0x90,0xfd,0x00,0x2f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q1, [r0] # CHECK: vldrb.u32 q0, [r7] @ encoding: [0x97,0xfd,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q0, [r7] # CHECK: vldrb.u32 q3, [r7] @ encoding: [0x97,0xfd,0x00,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q3, [r7] # CHECK: vldrb.u32 q0, [r4, #56] @ encoding: [0x94,0xfd,0x38,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q0, [r4, #56] # CHECK: vldrb.u32 q4, [r4, #56] @ encoding: [0x94,0xfd,0x38,0x8f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q4, [r4, #56] # CHECK: vldrb.u32 q0, [r2, #56] @ encoding: [0x92,0xfd,0x38,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q0, [r2, #56] # CHECK: vldrb.u32 q5, [r4, #56]! @ encoding: [0xb4,0xfd,0x38,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q5, [r4, #56]! # CHECK: vldrb.u32 q5, [r4, #56]! @ encoding: [0xb4,0xfd,0x38,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q5, [r4, #56]! # CHECK: vldrb.u32 q5, [r4], #-25 @ encoding: [0x34,0xfc,0x19,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q5, [r4], #-25 # CHECK: vldrb.u32 q5, [r3], #-25 @ encoding: [0x33,0xfc,0x19,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q5, [r3], #-25 # CHECK: vldrb.u32 q5, [r6, #-25] @ encoding: [0x16,0xfd,0x19,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q5, [r6, #-25] # CHECK: vldrb.u32 q5, [r6, #-64] @ encoding: [0x16,0xfd,0x40,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q5, [r6, #-64] # CHECK: vldrb.s32 q0, [r0] @ encoding: [0x90,0xed,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q0, [r0] # CHECK: vldrb.s32 q1, [r0] @ encoding: [0x90,0xed,0x00,0x2f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q1, [r0] # CHECK: vldrb.s32 q0, [r7] @ encoding: [0x97,0xed,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q0, [r7] # CHECK: vldrb.s32 q3, [r7] @ encoding: [0x97,0xed,0x00,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q3, [r7] # CHECK: vldrb.s32 q0, [r4, #56] @ encoding: [0x94,0xed,0x38,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q0, [r4, #56] # CHECK: vldrb.s32 q4, [r4, #56] @ encoding: [0x94,0xed,0x38,0x8f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q4, [r4, #56] # CHECK: vldrb.s32 q0, [r2, #56] @ encoding: [0x92,0xed,0x38,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q0, [r2, #56] # CHECK: vldrb.s32 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x38,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q5, [r4, #56]! # CHECK: vldrb.s32 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x38,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q5, [r4, #56]! # CHECK: vldrb.s32 q5, [r4], #-25 @ encoding: [0x34,0xec,0x19,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q5, [r4], #-25 # CHECK: vldrb.s32 q5, [r3], #-25 @ encoding: [0x33,0xec,0x19,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q5, [r3], #-25 # CHECK: vldrb.s32 q5, [r6, #-25] @ encoding: [0x16,0xed,0x19,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q5, [r6, #-25] # CHECK: vldrb.s32 q5, [r6, #-64] @ encoding: [0x16,0xed,0x40,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q5, [r6, #-64] # CHECK: vstrb.32 q0, [r0] @ encoding: [0x80,0xed,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q0, [r0] # CHECK: vstrb.32 q1, [r0] @ encoding: [0x80,0xed,0x00,0x2f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q1, [r0] # CHECK: vstrb.32 q0, [r7] @ encoding: [0x87,0xed,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q0, [r7] # CHECK: vstrb.32 q3, [r7] @ encoding: [0x87,0xed,0x00,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q3, [r7] # CHECK: vstrb.32 q0, [r4, #56] @ encoding: [0x84,0xed,0x38,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q0, [r4, #56] # CHECK: vstrb.32 q4, [r4, #56] @ encoding: [0x84,0xed,0x38,0x8f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q4, [r4, #56] # CHECK: vstrb.32 q0, [r5, #56] @ encoding: [0x85,0xed,0x38,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q0, [r5, #56] # CHECK: vstrb.32 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x38,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q5, [r4, #56]! # CHECK: vstrb.32 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x38,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q5, [r4, #56]! # CHECK: vstrb.32 q5, [r4], #-25 @ encoding: [0x24,0xec,0x19,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q5, [r4], #-25 # CHECK: vstrb.32 q5, [r3], #-25 @ encoding: [0x23,0xec,0x19,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q5, [r3], #-25 # CHECK: vstrb.32 q5, [r2, #-25] @ encoding: [0x02,0xed,0x19,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q5, [r2, #-25] # CHECK: vstrb.32 q5, [r2, #-64] @ encoding: [0x02,0xed,0x40,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q5, [r2, #-64] # CHECK: vldrh.u16 q0, [r0] @ encoding: [0x90,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q0, [r0] # CHECK: vldrh.u16 q1, [r0] @ encoding: [0x90,0xed,0x80,0x3e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q1, [r0] # CHECK: vldrh.u16 q0, [r11] @ encoding: [0x9b,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q0, [r11] # CHECK: vldrh.u16 q3, [r11] @ encoding: [0x9b,0xed,0x80,0x7e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q3, [r11] # CHECK: vldrh.u16 q0, [r4, #56] @ encoding: [0x94,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q0, [r4, #56] # CHECK: vldrh.u16 q4, [r4, #56] @ encoding: [0x94,0xed,0x9c,0x9e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q4, [r4, #56] # CHECK: vldrh.u16 q0, [r8, #56] @ encoding: [0x98,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q0, [r8, #56] # CHECK: vldrh.u16 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q5, [r4, #56]! # CHECK: vldrh.u16 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q5, [r4, #56]! # CHECK: vldrh.u16 q5, [r4], #-26 @ encoding: [0x34,0xec,0x8d,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q5, [r4], #-26 # CHECK: vldrh.u16 q5, [r10], #-26 @ encoding: [0x3a,0xec,0x8d,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q5, [r10], #-26 # CHECK: vldrh.u16 q5, [sp, #-26] @ encoding: [0x1d,0xed,0x8d,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q5, [sp, #-26] # CHECK: vldrh.u16 q5, [sp, #-64] @ encoding: [0x1d,0xed,0xa0,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q5, [sp, #-64] # CHECK: vldrh.u16 q5, [sp, #-254] @ encoding: [0x1d,0xed,0xff,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q5, [sp, #-254] # CHECK: vldrh.u16 q5, [r10], #254 @ encoding: [0xba,0xec,0xff,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q5, [r10], #254 # CHECK: vstrh.16 q0, [r0] @ encoding: [0x80,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q0, [r0] # CHECK: vstrh.16 q1, [r0] @ encoding: [0x80,0xed,0x80,0x3e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q1, [r0] # CHECK: vstrh.16 q0, [r11] @ encoding: [0x8b,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q0, [r11] # CHECK: vstrh.16 q3, [r11] @ encoding: [0x8b,0xed,0x80,0x7e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q3, [r11] # CHECK: vstrh.16 q0, [r4, #56] @ encoding: [0x84,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q0, [r4, #56] # CHECK: vstrh.16 q4, [r4, #56] @ encoding: [0x84,0xed,0x9c,0x9e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q4, [r4, #56] # CHECK: vstrh.16 q0, [r8, #56] @ encoding: [0x88,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q0, [r8, #56] # CHECK: vstrh.16 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q5, [r4, #56]! # CHECK: vstrh.16 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q5, [r4, #56]! # CHECK: vstrh.16 q5, [r4], #-26 @ encoding: [0x24,0xec,0x8d,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q5, [r4], #-26 # CHECK: vstrh.16 q5, [r10], #-26 @ encoding: [0x2a,0xec,0x8d,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q5, [r10], #-26 # CHECK: vstrh.16 q5, [sp, #-26] @ encoding: [0x0d,0xed,0x8d,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q5, [sp, #-26] # CHECK: vstrh.16 q5, [sp, #-64] @ encoding: [0x0d,0xed,0xa0,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q5, [sp, #-64] # CHECK: vstrh.16 q5, [sp, #-254] @ encoding: [0x0d,0xed,0xff,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q5, [sp, #-254] # CHECK: vstrh.16 q5, [r10], #254 @ encoding: [0xaa,0xec,0xff,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q5, [r10], #254 # CHECK: vldrh.u32 q0, [r0] @ encoding: [0x98,0xfd,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q0, [r0] # CHECK: vldrh.u32 q1, [r0] @ encoding: [0x98,0xfd,0x00,0x2f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q1, [r0] # CHECK: vldrh.u32 q0, [r7] @ encoding: [0x9f,0xfd,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q0, [r7] # CHECK: vldrh.u32 q3, [r7] @ encoding: [0x9f,0xfd,0x00,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q3, [r7] # CHECK: vldrh.u32 q0, [r4, #56] @ encoding: [0x9c,0xfd,0x1c,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q0, [r4, #56] # CHECK: vldrh.u32 q4, [r4, #56] @ encoding: [0x9c,0xfd,0x1c,0x8f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q4, [r4, #56] # CHECK: vldrh.u32 q0, [r2, #56] @ encoding: [0x9a,0xfd,0x1c,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q0, [r2, #56] # CHECK: vldrh.u32 q5, [r4, #56]! @ encoding: [0xbc,0xfd,0x1c,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q5, [r4, #56]! # CHECK: vldrh.u32 q5, [r4, #56]! @ encoding: [0xbc,0xfd,0x1c,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q5, [r4, #56]! # CHECK: vldrh.u32 q5, [r4], #-26 @ encoding: [0x3c,0xfc,0x0d,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q5, [r4], #-26 # CHECK: vldrh.u32 q5, [r3], #-26 @ encoding: [0x3b,0xfc,0x0d,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q5, [r3], #-26 # CHECK: vldrh.u32 q5, [r6, #-26] @ encoding: [0x1e,0xfd,0x0d,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q5, [r6, #-26] # CHECK: vldrh.u32 q5, [r6, #-64] @ encoding: [0x1e,0xfd,0x20,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q5, [r6, #-64] # CHECK: vldrh.u32 q5, [r6, #-254] @ encoding: [0x1e,0xfd,0x7f,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q5, [r6, #-254] # CHECK: vldrh.u32 q5, [r4, #254]! @ encoding: [0xbc,0xfd,0x7f,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q5, [r4, #254]! # CHECK: vldrh.s32 q0, [r0] @ encoding: [0x98,0xed,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q0, [r0] # CHECK: vldrh.s32 q1, [r0] @ encoding: [0x98,0xed,0x00,0x2f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q1, [r0] # CHECK: vldrh.s32 q0, [r7] @ encoding: [0x9f,0xed,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q0, [r7] # CHECK: vldrh.s32 q3, [r7] @ encoding: [0x9f,0xed,0x00,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q3, [r7] # CHECK: vldrh.s32 q0, [r4, #56] @ encoding: [0x9c,0xed,0x1c,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q0, [r4, #56] # CHECK: vldrh.s32 q4, [r4, #56] @ encoding: [0x9c,0xed,0x1c,0x8f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q4, [r4, #56] # CHECK: vldrh.s32 q0, [r2, #56] @ encoding: [0x9a,0xed,0x1c,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q0, [r2, #56] # CHECK: vldrh.s32 q5, [r4, #56]! @ encoding: [0xbc,0xed,0x1c,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q5, [r4, #56]! # CHECK: vldrh.s32 q5, [r4, #56]! @ encoding: [0xbc,0xed,0x1c,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q5, [r4, #56]! # CHECK: vldrh.s32 q5, [r4], #-26 @ encoding: [0x3c,0xec,0x0d,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q5, [r4], #-26 # CHECK: vldrh.s32 q5, [r3], #-26 @ encoding: [0x3b,0xec,0x0d,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q5, [r3], #-26 # CHECK: vldrh.s32 q5, [r6, #-26] @ encoding: [0x1e,0xed,0x0d,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q5, [r6, #-26] # CHECK: vldrh.s32 q5, [r6, #-64] @ encoding: [0x1e,0xed,0x20,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q5, [r6, #-64] # CHECK: vldrh.s32 q5, [r6, #-254] @ encoding: [0x1e,0xed,0x7f,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q5, [r6, #-254] # CHECK: vldrh.s32 q5, [r4, #254]! @ encoding: [0xbc,0xed,0x7f,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q5, [r4, #254]! # CHECK: vstrh.32 q0, [r0] @ encoding: [0x88,0xed,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q0, [r0] # CHECK: vstrh.32 q1, [r0] @ encoding: [0x88,0xed,0x00,0x2f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q1, [r0] # CHECK: vstrh.32 q0, [r7] @ encoding: [0x8f,0xed,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q0, [r7] # CHECK: vstrh.32 q3, [r7] @ encoding: [0x8f,0xed,0x00,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q3, [r7] # CHECK: vstrh.32 q0, [r4, #56] @ encoding: [0x8c,0xed,0x1c,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q0, [r4, #56] # CHECK: vstrh.32 q4, [r4, #56] @ encoding: [0x8c,0xed,0x1c,0x8f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q4, [r4, #56] # CHECK: vstrh.32 q0, [r5, #56] @ encoding: [0x8d,0xed,0x1c,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q0, [r5, #56] # CHECK: vstrh.32 q5, [r4, #56]! @ encoding: [0xac,0xed,0x1c,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q5, [r4, #56]! # CHECK: vstrh.32 q5, [r4, #56]! @ encoding: [0xac,0xed,0x1c,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q5, [r4, #56]! # CHECK: vstrh.32 q5, [r4], #-26 @ encoding: [0x2c,0xec,0x0d,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q5, [r4], #-26 # CHECK: vstrh.32 q5, [r3], #-26 @ encoding: [0x2b,0xec,0x0d,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q5, [r3], #-26 # CHECK: vstrh.32 q5, [r2, #-26] @ encoding: [0x0a,0xed,0x0d,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q5, [r2, #-26] # CHECK: vstrh.32 q5, [r2, #-64] @ encoding: [0x0a,0xed,0x20,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q5, [r2, #-64] # CHECK: vstrh.32 q5, [r2, #-254] @ encoding: [0x0a,0xed,0x7f,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q5, [r2, #-254] # CHECK: vstrh.32 q5, [r4, #254]! @ encoding: [0xac,0xed,0x7f,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q5, [r4, #254]! # CHECK: vldrw.u32 q0, [r0] @ encoding: [0x90,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [r0] # CHECK: vldrw.u32 q1, [r0] @ encoding: [0x90,0xed,0x00,0x3f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q1, [r0] # CHECK: vldrw.u32 q0, [r11] @ encoding: [0x9b,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [r11] # CHECK: vldrw.u32 q3, [r11] @ encoding: [0x9b,0xed,0x00,0x7f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q3, [r11] # CHECK: vldrw.u32 q0, [r4, #56] @ encoding: [0x94,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [r4, #56] # CHECK: vldrw.u32 q4, [r4, #56] @ encoding: [0x94,0xed,0x0e,0x9f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q4, [r4, #56] # CHECK: vldrw.u32 q0, [r8, #56] @ encoding: [0x98,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [r8, #56] # CHECK: vldrw.u32 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q5, [r4, #56]! # CHECK: vldrw.u32 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q5, [r4, #56]! # CHECK: vldrw.u32 q5, [r4], #-28 @ encoding: [0x34,0xec,0x07,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q5, [r4], #-28 # CHECK: vldrw.u32 q5, [r10], #-28 @ encoding: [0x3a,0xec,0x07,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q5, [r10], #-28 # CHECK: vldrw.u32 q5, [sp, #-28] @ encoding: [0x1d,0xed,0x07,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q5, [sp, #-28] # CHECK: vldrw.u32 q5, [sp, #-64] @ encoding: [0x1d,0xed,0x10,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q5, [sp, #-64] # CHECK: vldrw.u32 q5, [sp, #-508] @ encoding: [0x1d,0xed,0x7f,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q5, [sp, #-508] # CHECK: vldrw.u32 q5, [r4, #508]! @ encoding: [0xb4,0xed,0x7f,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q5, [r4, #508]! # CHECK: vstrw.32 q0, [r0] @ encoding: [0x80,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q0, [r0] # CHECK: vstrw.32 q1, [r0] @ encoding: [0x80,0xed,0x00,0x3f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q1, [r0] # CHECK: vstrw.32 q0, [r11] @ encoding: [0x8b,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q0, [r11] # CHECK: vstrw.32 q3, [r11] @ encoding: [0x8b,0xed,0x00,0x7f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q3, [r11] # CHECK: vstrw.32 q0, [r4, #56] @ encoding: [0x84,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q0, [r4, #56] # CHECK: vstrw.32 q4, [r4, #56] @ encoding: [0x84,0xed,0x0e,0x9f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q4, [r4, #56] # CHECK: vstrw.32 q0, [r8, #56] @ encoding: [0x88,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q0, [r8, #56] # CHECK: vstrw.32 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q5, [r4, #56]! # CHECK: vstrw.32 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q5, [r4, #56]! # CHECK: vstrw.32 q5, [r4], #-28 @ encoding: [0x24,0xec,0x07,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q5, [r4], #-28 # CHECK: vstrw.32 q5, [r10], #-28 @ encoding: [0x2a,0xec,0x07,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q5, [r10], #-28 # CHECK: vstrw.32 q5, [sp, #-28] @ encoding: [0x0d,0xed,0x07,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q5, [sp, #-28] # CHECK: vstrw.32 q5, [sp, #-64] @ encoding: [0x0d,0xed,0x10,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q5, [sp, #-64] # CHECK: vstrw.32 q5, [sp, #-508] @ encoding: [0x0d,0xed,0x7f,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q5, [sp, #-508] # CHECK: vstrw.32 q5, [r4, #508]! @ encoding: [0xa4,0xed,0x7f,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q5, [r4, #508]! # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: invalid operand for instruction @@ -885,271 +885,271 @@ vstrw.32 q5, [sp, #-3] vstrw.32 q5, [sp, #512] # CHECK: vldrb.u8 q0, [r0, q1] @ encoding: [0x90,0xfc,0x02,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q0, [r0, q1] # CHECK: vldrb.u8 q3, [r10, q1] @ encoding: [0x9a,0xfc,0x02,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q3, [r10, q1] # CHECK: vldrb.u16 q0, [r0, q1] @ encoding: [0x90,0xfc,0x82,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q0, [r0, q1] # CHECK: vldrb.u16 q3, [r9, q1] @ encoding: [0x99,0xfc,0x82,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q3, [r9, q1] # CHECK: vldrb.s16 q0, [r0, q1] @ encoding: [0x90,0xec,0x82,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q0, [r0, q1] # CHECK: vldrb.s16 q3, [sp, q1] @ encoding: [0x9d,0xec,0x82,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q3, [sp, q1] # CHECK: vldrb.u32 q0, [r0, q1] @ encoding: [0x90,0xfc,0x02,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q0, [r0, q1] # CHECK: vldrb.u32 q3, [r0, q1] @ encoding: [0x90,0xfc,0x02,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q3, [r0, q1] # CHECK: vldrb.s32 q0, [r0, q1] @ encoding: [0x90,0xec,0x02,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q0, [r0, q1] # CHECK: vldrb.s32 q3, [r0, q1] @ encoding: [0x90,0xec,0x02,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q3, [r0, q1] # CHECK: vldrh.u16 q0, [r0, q1] @ encoding: [0x90,0xfc,0x92,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q0, [r0, q1] # CHECK: vldrh.u16 q3, [r0, q1] @ encoding: [0x90,0xfc,0x92,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q3, [r0, q1] # CHECK: vldrh.u32 q0, [r0, q1] @ encoding: [0x90,0xfc,0x12,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q0, [r0, q1] # CHECK: vldrh.u32 q3, [r0, q1] @ encoding: [0x90,0xfc,0x12,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q3, [r0, q1] # CHECK: vldrh.s32 q0, [r0, q1] @ encoding: [0x90,0xec,0x12,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q0, [r0, q1] # CHECK: vldrh.s32 q3, [r0, q1] @ encoding: [0x90,0xec,0x12,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q3, [r0, q1] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q0, [r0, q0, uxtw #1] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q0, [r0, q0, uxtw #1] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q0, [r0, q0, uxtw #1] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [r0, q0, uxtw #2] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q0, [r0, q0, uxtw #3] # CHECK: vldrh.u16 q0, [r0, q1, uxtw #1] @ encoding: [0x90,0xfc,0x93,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q0, [r0, q1, uxtw #1] # CHECK: vldrw.u32 q0, [r0, q1] @ encoding: [0x90,0xfc,0x42,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [r0, q1] # CHECK: vldrw.u32 q3, [r0, q1] @ encoding: [0x90,0xfc,0x42,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q3, [r0, q1] # CHECK: vldrw.u32 q0, [r0, q1, uxtw #2] @ encoding: [0x90,0xfc,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [r0, q1, uxtw #2] # CHECK: vldrw.u32 q0, [sp, q1, uxtw #2] @ encoding: [0x9d,0xfc,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [sp, q1, uxtw #2] # CHECK: vldrd.u64 q0, [r0, q1] @ encoding: [0x90,0xfc,0xd2,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q0, [r0, q1] # CHECK: vldrd.u64 q3, [r0, q1] @ encoding: [0x90,0xfc,0xd2,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q3, [r0, q1] # CHECK: vldrd.u64 q0, [r0, q1, uxtw #3] @ encoding: [0x90,0xfc,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q0, [r0, q1, uxtw #3] # CHECK: vldrd.u64 q0, [sp, q1, uxtw #3] @ encoding: [0x9d,0xfc,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q0, [sp, q1, uxtw #3] # CHECK: vstrb.8 q0, [r0, q1] @ encoding: [0x80,0xec,0x02,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q0, [r0, q1] # CHECK: vstrb.8 q3, [r10, q1] @ encoding: [0x8a,0xec,0x02,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q3, [r10, q1] # CHECK: vstrb.8 q3, [r0, q3] @ encoding: [0x80,0xec,0x06,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q3, [r0, q3] # CHECK: vstrb.16 q0, [r0, q1] @ encoding: [0x80,0xec,0x82,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q0, [r0, q1] # CHECK: vstrb.16 q3, [sp, q1] @ encoding: [0x8d,0xec,0x82,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q3, [sp, q1] # CHECK: vstrb.16 q3, [r0, q3] @ encoding: [0x80,0xec,0x86,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q3, [r0, q3] # CHECK: vstrb.32 q0, [r0, q1] @ encoding: [0x80,0xec,0x02,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q0, [r0, q1] # CHECK: vstrb.32 q3, [r0, q1] @ encoding: [0x80,0xec,0x02,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q3, [r0, q1] # CHECK: vstrb.32 q3, [r0, q3] @ encoding: [0x80,0xec,0x06,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q3, [r0, q3] # CHECK: vstrh.16 q0, [r0, q1] @ encoding: [0x80,0xec,0x92,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q0, [r0, q1] # CHECK: vstrh.16 q3, [r0, q1] @ encoding: [0x80,0xec,0x92,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q3, [r0, q1] # CHECK: vstrh.16 q3, [r0, q3] @ encoding: [0x80,0xec,0x96,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q3, [r0, q3] # CHECK: vstrh.32 q0, [r0, q1] @ encoding: [0x80,0xec,0x12,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q0, [r0, q1] # CHECK: vstrh.32 q3, [r0, q1] @ encoding: [0x80,0xec,0x12,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q3, [r0, q1] # CHECK: vstrh.32 q3, [r0, q3] @ encoding: [0x80,0xec,0x16,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q3, [r0, q3] # CHECK: vstrh.16 q0, [r0, q1, uxtw #1] @ encoding: [0x80,0xec,0x93,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q0, [r0, q1, uxtw #1] # CHECK: vstrh.32 q3, [r8, q3, uxtw #1] @ encoding: [0x88,0xec,0x17,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q3, [r8, q3, uxtw #1] # CHECK: vstrw.32 q0, [r0, q1] @ encoding: [0x80,0xec,0x42,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q0, [r0, q1] # CHECK: vstrw.32 q3, [r0, q1] @ encoding: [0x80,0xec,0x42,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q3, [r0, q1] # CHECK: vstrw.32 q3, [r0, q3] @ encoding: [0x80,0xec,0x46,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q3, [r0, q3] # CHECK: vstrw.32 q0, [r0, q1, uxtw #2] @ encoding: [0x80,0xec,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q0, [r0, q1, uxtw #2] # CHECK: vstrw.32 q0, [sp, q1, uxtw #2] @ encoding: [0x8d,0xec,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q0, [sp, q1, uxtw #2] # CHECK: vstrd.64 q0, [r0, q1] @ encoding: [0x80,0xec,0xd2,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q0, [r0, q1] # CHECK: vstrd.64 q3, [r0, q1] @ encoding: [0x80,0xec,0xd2,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q3, [r0, q1] # CHECK: vstrd.64 q3, [r0, q3] @ encoding: [0x80,0xec,0xd6,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q3, [r0, q3] # CHECK: vstrd.64 q0, [r0, q1, uxtw #3] @ encoding: [0x80,0xec,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q0, [r0, q1, uxtw #3] # CHECK: vstrd.64 q0, [sp, q1, uxtw #3] @ encoding: [0x8d,0xec,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q0, [sp, q1, uxtw #3] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: operand must be a register in range [q0, q7] @@ -1189,79 +1189,79 @@ vstrh.16 q0, [r0, q1, uxtw #2] vstrb.32 q0, [r11, q1, uxtw #1] # CHECK: vldrw.u32 q0, [q1] @ encoding: [0x92,0xfd,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [q1] # CHECK: vldrw.u32 q7, [q1] @ encoding: [0x92,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q7, [q1] # CHECK: vldrw.u32 q7, [q1]! @ encoding: [0xb2,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q7, [q1]! # CHECK: vldrw.u32 q7, [q1, #4] @ encoding: [0x92,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q7, [q1, #4] # CHECK: vldrw.u32 q7, [q1, #-4] @ encoding: [0x12,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q7, [q1, #-4] # CHECK: vldrw.u32 q7, [q1, #508] @ encoding: [0x92,0xfd,0x7f,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q7, [q1, #508] # CHECK: vldrw.u32 q7, [q1, #-508] @ encoding: [0x12,0xfd,0x7f,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q7, [q1, #-508] # CHECK: vldrw.u32 q7, [q1, #264] @ encoding: [0x92,0xfd,0x42,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q7, [q1, #264] # CHECK: vldrw.u32 q7, [q1, #4]! @ encoding: [0xb2,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q7, [q1, #4]! # CHECK: vstrw.32 q0, [q1] @ encoding: [0x82,0xfd,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q0, [q1] # CHECK: vstrw.32 q1, [q1] @ encoding: [0x82,0xfd,0x00,0x3e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q1, [q1] # CHECK: vstrw.32 q7, [q1] @ encoding: [0x82,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q7, [q1] # CHECK: vstrw.32 q7, [q1]! @ encoding: [0xa2,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q7, [q1]! # CHECK: vstrw.32 q7, [q7] @ encoding: [0x8e,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q7, [q7] # CHECK: vstrw.32 q7, [q1, #4] @ encoding: [0x82,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q7, [q1, #4] # CHECK: vstrw.32 q7, [q1, #-4] @ encoding: [0x02,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q7, [q1, #-4] # CHECK: vstrw.32 q7, [q1, #508] @ encoding: [0x82,0xfd,0x7f,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q7, [q1, #508] # CHECK: vstrw.32 q7, [q1, #-508] @ encoding: [0x02,0xfd,0x7f,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q7, [q1, #-508] # CHECK: vstrw.32 q7, [q1, #264]! @ encoding: [0xa2,0xfd,0x42,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q7, [q1, #264]! # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: operand must be a register in range [q0, q7] @@ -1277,103 +1277,103 @@ vstrw.32 q4, [q1, #3]! vldrw.u32 q7, [q1, #512] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector pointer register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.32 q1, [q1, #264] # CHECK: vldrd.u64 q0, [q1] @ encoding: [0x92,0xfd,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q0, [q1] # CHECK: vldrd.u64 q7, [q1] @ encoding: [0x92,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1] # CHECK: vldrd.u64 q7, [q1]! @ encoding: [0xb2,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1]! # CHECK: vldrd.u64 q7, [q1, #8] @ encoding: [0x92,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1, #8] # CHECK: vldrd.u64 q7, [q1, #-8] @ encoding: [0x12,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1, #-8] # CHECK: vldrd.u64 q7, [q1, #1016] @ encoding: [0x92,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1, #1016] # CHECK: vldrd.u64 q7, [q1, #-1016] @ encoding: [0x12,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1, #-1016] # CHECK: vldrd.u64 q7, [q1, #264] @ encoding: [0x92,0xfd,0x21,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1, #264] # CHECK: vldrd.u64 q7, [q1, #624] @ encoding: [0x92,0xfd,0x4e,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1, #624] # CHECK: vldrd.u64 q7, [q1, #264] @ encoding: [0x92,0xfd,0x21,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1, #264] # CHECK: vldrd.u64 q7, [q1, #-1016]! @ encoding: [0x32,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1, #-1016]! # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector pointer register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q6, [q6] # CHECK: vstrd.64 q0, [q1] @ encoding: [0x82,0xfd,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q0, [q1] # CHECK: vstrd.64 q1, [q1] @ encoding: [0x82,0xfd,0x00,0x3f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q1, [q1] # CHECK: vstrd.64 q7, [q1] @ encoding: [0x82,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q1] # CHECK: vstrd.64 q7, [q1]! @ encoding: [0xa2,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q1]! # CHECK: vstrd.64 q7, [q7] @ encoding: [0x8e,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q7] # CHECK: vstrd.64 q7, [q1, #8] @ encoding: [0x82,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q1, #8] # CHECK: vstrd.64 q7, [q1, #-8]! @ encoding: [0x22,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q1, #-8]! # CHECK: vstrd.64 q7, [q1, #1016] @ encoding: [0x82,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q1, #1016] # CHECK: vstrd.64 q7, [q1, #-1016] @ encoding: [0x02,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q1, #-1016] # CHECK: vstrd.64 q7, [q1, #264] @ encoding: [0x82,0xfd,0x21,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q1, #264] # CHECK: vstrd.64 q7, [q1, #624] @ encoding: [0x82,0xfd,0x4e,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q1, #624] # CHECK: vstrd.64 q7, [q1, #264] @ encoding: [0x82,0xfd,0x21,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q1, #264] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: operand must be a register in range [q0, q7] @@ -1393,547 +1393,547 @@ vstrd.64 q4, [q1, #3] vstrd.64 q4, [q1, #4] # CHECK: vldrb.u8 q0, [r0] @ encoding: [0x90,0xed,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s8 q0, [r0] # CHECK: vldrb.u8 q0, [r0] @ encoding: [0x90,0xed,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.8 q0, [r0] # CHECK: vldrb.u8 q0, [r8, #56] @ encoding: [0x98,0xed,0x38,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s8 q0, [r8, #56] # CHECK: vldrb.u8 q0, [r8, #56] @ encoding: [0x98,0xed,0x38,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.8 q0, [r8, #56] # CHECK: vldrb.u8 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x38,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s8 q5, [r4, #56]! # CHECK: vldrb.u8 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x38,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.8 q5, [r4, #56]! # CHECK: vstrb.8 q0, [r0] @ encoding: [0x80,0xed,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.u8 q0, [r0] # CHECK: vstrb.8 q0, [r0] @ encoding: [0x80,0xed,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.s8 q0, [r0] # CHECK: vstrb.8 q4, [r4, #56] @ encoding: [0x84,0xed,0x38,0x9e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.u8 q4, [r4, #56] # CHECK: vstrb.8 q4, [r4, #56] @ encoding: [0x84,0xed,0x38,0x9e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.s8 q4, [r4, #56] # CHECK: vstrb.8 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x38,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.u8 q5, [r4, #56]! # CHECK: vstrb.8 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x38,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.s8 q5, [r4, #56]! # CHECK: vldrh.u16 q0, [r0] @ encoding: [0x90,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s16 q0, [r0] # CHECK: vldrh.u16 q0, [r0] @ encoding: [0x90,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.f16 q0, [r0] # CHECK: vldrh.u16 q0, [r0] @ encoding: [0x90,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.16 q0, [r0] # CHECK: vldrh.u16 q0, [r4, #56] @ encoding: [0x94,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s16 q0, [r4, #56] # CHECK: vldrh.u16 q0, [r4, #56] @ encoding: [0x94,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.f16 q0, [r4, #56] # CHECK: vldrh.u16 q0, [r4, #56] @ encoding: [0x94,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.16 q0, [r4, #56] # CHECK: vldrh.u16 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s16 q5, [r4, #56]! # CHECK: vldrh.u16 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.f16 q5, [r4, #56]! # CHECK: vldrh.u16 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.16 q5, [r4, #56]! # CHECK: vstrh.16 q0, [r0] @ encoding: [0x80,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.u16 q0, [r0] # CHECK: vstrh.16 q0, [r0] @ encoding: [0x80,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.s16 q0, [r0] # CHECK: vstrh.16 q0, [r0] @ encoding: [0x80,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.f16 q0, [r0] # CHECK: vstrh.16 q0, [r4, #56] @ encoding: [0x84,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.u16 q0, [r4, #56] # CHECK: vstrh.16 q0, [r4, #56] @ encoding: [0x84,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.s16 q0, [r4, #56] # CHECK: vstrh.16 q0, [r4, #56] @ encoding: [0x84,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.f16 q0, [r4, #56] # CHECK: vstrh.16 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.u16 q5, [r4, #56]! # CHECK: vstrh.16 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.s16 q5, [r4, #56]! # CHECK: vstrh.16 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.f16 q5, [r4, #56]! # CHECK: vldrw.u32 q0, [r0] @ encoding: [0x90,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.s32 q0, [r0] # CHECK: vldrw.u32 q0, [r0] @ encoding: [0x90,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.f32 q0, [r0] # CHECK: vldrw.u32 q0, [r0] @ encoding: [0x90,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.32 q0, [r0] # CHECK: vldrw.u32 q0, [r4, #56] @ encoding: [0x94,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.s32 q0, [r4, #56] # CHECK: vldrw.u32 q0, [r4, #56] @ encoding: [0x94,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.f32 q0, [r4, #56] # CHECK: vldrw.u32 q0, [r4, #56] @ encoding: [0x94,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.32 q0, [r4, #56] # CHECK: vldrw.u32 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.s32 q5, [r4, #56]! # CHECK: vldrw.u32 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.f32 q5, [r4, #56]! # CHECK: vldrw.u32 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.32 q5, [r4, #56]! # CHECK: vstrw.32 q0, [r0] @ encoding: [0x80,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.u32 q0, [r0] # CHECK: vstrw.32 q0, [r0] @ encoding: [0x80,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.s32 q0, [r0] # CHECK: vstrw.32 q0, [r0] @ encoding: [0x80,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.f32 q0, [r0] # CHECK: vstrw.32 q0, [r4, #56] @ encoding: [0x84,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.u32 q0, [r4, #56] # CHECK: vstrw.32 q0, [r4, #56] @ encoding: [0x84,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.s32 q0, [r4, #56] # CHECK: vstrw.32 q0, [r4, #56] @ encoding: [0x84,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.f32 q0, [r4, #56] # CHECK: vstrw.32 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.u32 q5, [r4, #56]! # CHECK: vstrw.32 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.s32 q5, [r4, #56]! # CHECK: vstrw.32 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.f32 q5, [r4, #56]! # CHECK: vldrb.u8 q0, [r0, q1] @ encoding: [0x90,0xfc,0x02,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s8 q0, [r0, q1] # CHECK: vldrb.u8 q0, [r0, q1] @ encoding: [0x90,0xfc,0x02,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.8 q0, [r0, q1] # CHECK: vldrh.u16 q3, [r0, q1] @ encoding: [0x90,0xfc,0x92,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s16 q3, [r0, q1] # CHECK: vldrh.u16 q3, [r0, q1] @ encoding: [0x90,0xfc,0x92,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.f16 q3, [r0, q1] # CHECK: vldrh.u16 q3, [r0, q1] @ encoding: [0x90,0xfc,0x92,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.16 q3, [r0, q1] # CHECK: vldrh.u16 q0, [r0, q1, uxtw #1] @ encoding: [0x90,0xfc,0x93,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s16 q0, [r0, q1, uxtw #1] # CHECK: vldrh.u16 q0, [r0, q1, uxtw #1] @ encoding: [0x90,0xfc,0x93,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.f16 q0, [r0, q1, uxtw #1] # CHECK: vldrh.u16 q0, [r0, q1, uxtw #1] @ encoding: [0x90,0xfc,0x93,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.16 q0, [r0, q1, uxtw #1] # CHECK: vldrw.u32 q0, [r0, q1] @ encoding: [0x90,0xfc,0x42,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.s32 q0, [r0, q1] # CHECK: vldrw.u32 q0, [r0, q1] @ encoding: [0x90,0xfc,0x42,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.f32 q0, [r0, q1] # CHECK: vldrw.u32 q0, [r0, q1] @ encoding: [0x90,0xfc,0x42,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.32 q0, [r0, q1] # CHECK: vldrw.u32 q0, [r0, q1, uxtw #2] @ encoding: [0x90,0xfc,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.s32 q0, [r0, q1, uxtw #2] # CHECK: vldrw.u32 q0, [r0, q1, uxtw #2] @ encoding: [0x90,0xfc,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.f32 q0, [r0, q1, uxtw #2] # CHECK: vldrw.u32 q0, [r0, q1, uxtw #2] @ encoding: [0x90,0xfc,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.32 q0, [r0, q1, uxtw #2] # CHECK: vldrd.u64 q0, [r0, q1] @ encoding: [0x90,0xfc,0xd2,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.s64 q0, [r0, q1] # CHECK: vldrd.u64 q0, [r0, q1] @ encoding: [0x90,0xfc,0xd2,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.f64 q0, [r0, q1] # CHECK: vldrd.u64 q0, [r0, q1] @ encoding: [0x90,0xfc,0xd2,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.64 q0, [r0, q1] # CHECK: vldrd.u64 q0, [r0, q1, uxtw #3] @ encoding: [0x90,0xfc,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.s64 q0, [r0, q1, uxtw #3] # CHECK: vldrd.u64 q0, [r0, q1, uxtw #3] @ encoding: [0x90,0xfc,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.f64 q0, [r0, q1, uxtw #3] # CHECK: vldrd.u64 q0, [r0, q1, uxtw #3] @ encoding: [0x90,0xfc,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.64 q0, [r0, q1, uxtw #3] # CHECK: vstrb.8 q0, [r0, q1] @ encoding: [0x80,0xec,0x02,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.u8 q0, [r0, q1] # CHECK: vstrb.8 q0, [r0, q1] @ encoding: [0x80,0xec,0x02,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.s8 q0, [r0, q1] # CHECK: vstrh.16 q3, [r0, q1] @ encoding: [0x80,0xec,0x92,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.u16 q3, [r0, q1] # CHECK: vstrh.16 q3, [r0, q1] @ encoding: [0x80,0xec,0x92,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.s16 q3, [r0, q1] # CHECK: vstrh.16 q3, [r0, q1] @ encoding: [0x80,0xec,0x92,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.f16 q3, [r0, q1] # CHECK: vstrh.16 q0, [r0, q1, uxtw #1] @ encoding: [0x80,0xec,0x93,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.u16 q0, [r0, q1, uxtw #1] # CHECK: vstrh.16 q0, [r0, q1, uxtw #1] @ encoding: [0x80,0xec,0x93,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.s16 q0, [r0, q1, uxtw #1] # CHECK: vstrh.16 q0, [r0, q1, uxtw #1] @ encoding: [0x80,0xec,0x93,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.f16 q0, [r0, q1, uxtw #1] # CHECK: vstrw.32 q0, [r0, q1] @ encoding: [0x80,0xec,0x42,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.u32 q0, [r0, q1] # CHECK: vstrw.32 q0, [r0, q1] @ encoding: [0x80,0xec,0x42,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.s32 q0, [r0, q1] # CHECK: vstrw.32 q0, [r0, q1] @ encoding: [0x80,0xec,0x42,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.f32 q0, [r0, q1] # CHECK: vstrw.32 q0, [r0, q1, uxtw #2] @ encoding: [0x80,0xec,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.u32 q0, [r0, q1, uxtw #2] # CHECK: vstrw.32 q0, [r0, q1, uxtw #2] @ encoding: [0x80,0xec,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.s32 q0, [r0, q1, uxtw #2] # CHECK: vstrw.32 q0, [r0, q1, uxtw #2] @ encoding: [0x80,0xec,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.f32 q0, [r0, q1, uxtw #2] # CHECK: vstrd.64 q3, [r0, q1] @ encoding: [0x80,0xec,0xd2,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.u64 q3, [r0, q1] # CHECK: vstrd.64 q3, [r0, q1] @ encoding: [0x80,0xec,0xd2,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.s64 q3, [r0, q1] # CHECK: vstrd.64 q3, [r0, q1] @ encoding: [0x80,0xec,0xd2,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.f64 q3, [r0, q1] # CHECK: vstrd.64 q0, [r0, q1, uxtw #3] @ encoding: [0x80,0xec,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.u64 q0, [r0, q1, uxtw #3] # CHECK: vstrd.64 q0, [r0, q1, uxtw #3] @ encoding: [0x80,0xec,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.s64 q0, [r0, q1, uxtw #3] # CHECK: vstrd.64 q0, [r0, q1, uxtw #3] @ encoding: [0x80,0xec,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.f64 q0, [r0, q1, uxtw #3] # CHECK: vldrw.u32 q0, [q1] @ encoding: [0x92,0xfd,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.s32 q0, [q1] # CHECK: vldrw.u32 q0, [q1] @ encoding: [0x92,0xfd,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.f32 q0, [q1] # CHECK: vldrw.u32 q0, [q1] @ encoding: [0x92,0xfd,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.32 q0, [q1] # CHECK: vldrw.u32 q7, [q1]! @ encoding: [0xb2,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.s32 q7, [q1]! # CHECK: vldrw.u32 q7, [q1]! @ encoding: [0xb2,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.f32 q7, [q1]! # CHECK: vldrw.u32 q7, [q1]! @ encoding: [0xb2,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.32 q7, [q1]! # CHECK: vldrw.u32 q7, [q1, #4] @ encoding: [0x92,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.s32 q7, [q1, #4] # CHECK: vldrw.u32 q7, [q1, #4] @ encoding: [0x92,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.f32 q7, [q1, #4] # CHECK: vldrw.u32 q7, [q1, #4] @ encoding: [0x92,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.32 q7, [q1, #4] # CHECK: vldrw.u32 q7, [q1, #4]! @ encoding: [0xb2,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.s32 q7, [q1, #4]! # CHECK: vldrw.u32 q7, [q1, #4]! @ encoding: [0xb2,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.f32 q7, [q1, #4]! # CHECK: vldrw.u32 q7, [q1, #4]! @ encoding: [0xb2,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q7, [q1, #4]! # CHECK: vstrw.32 q0, [q1] @ encoding: [0x82,0xfd,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.u32 q0, [q1] # CHECK: vstrw.32 q0, [q1] @ encoding: [0x82,0xfd,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.s32 q0, [q1] # CHECK: vstrw.32 q0, [q1] @ encoding: [0x82,0xfd,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.f32 q0, [q1] # CHECK: vstrw.32 q7, [q1]! @ encoding: [0xa2,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.u32 q7, [q1]! # CHECK: vstrw.32 q7, [q1]! @ encoding: [0xa2,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.s32 q7, [q1]! # CHECK: vstrw.32 q7, [q1]! @ encoding: [0xa2,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.f32 q7, [q1]! # CHECK: vstrw.32 q7, [q1, #508] @ encoding: [0x82,0xfd,0x7f,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.u32 q7, [q1, #508] # CHECK: vstrw.32 q7, [q1, #508] @ encoding: [0x82,0xfd,0x7f,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.s32 q7, [q1, #508] # CHECK: vstrw.32 q7, [q1, #508] @ encoding: [0x82,0xfd,0x7f,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.f32 q7, [q1, #508] # CHECK: vstrw.32 q7, [q1, #264]! @ encoding: [0xa2,0xfd,0x42,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.u32 q7, [q1, #264]! # CHECK: vstrw.32 q7, [q1, #264]! @ encoding: [0xa2,0xfd,0x42,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.s32 q7, [q1, #264]! # CHECK: vstrw.32 q7, [q1, #264]! @ encoding: [0xa2,0xfd,0x42,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.f32 q7, [q1, #264]! # CHECK: vldrd.u64 q0, [q1] @ encoding: [0x92,0xfd,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.s64 q0, [q1] # CHECK: vldrd.u64 q0, [q1] @ encoding: [0x92,0xfd,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.f64 q0, [q1] # CHECK: vldrd.u64 q0, [q1] @ encoding: [0x92,0xfd,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.64 q0, [q1] # CHECK: vldrd.u64 q7, [q1]! @ encoding: [0xb2,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.s64 q7, [q1]! # CHECK: vldrd.u64 q7, [q1]! @ encoding: [0xb2,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.f64 q7, [q1]! # CHECK: vldrd.u64 q7, [q1]! @ encoding: [0xb2,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.64 q7, [q1]! # CHECK: vldrd.u64 q7, [q1, #8] @ encoding: [0x92,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.s64 q7, [q1, #8] # CHECK: vldrd.u64 q7, [q1, #8] @ encoding: [0x92,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.f64 q7, [q1, #8] # CHECK: vldrd.u64 q7, [q1, #8] @ encoding: [0x92,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.64 q7, [q1, #8] # CHECK: vldrd.u64 q7, [q1, #-1016]! @ encoding: [0x32,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.s64 q7, [q1, #-1016]! # CHECK: vldrd.u64 q7, [q1, #-1016]! @ encoding: [0x32,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.f64 q7, [q1, #-1016]! # CHECK: vldrd.u64 q7, [q1, #-1016]! @ encoding: [0x32,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.64 q7, [q1, #-1016]! # CHECK: vstrd.64 q0, [q1] @ encoding: [0x82,0xfd,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.u64 q0, [q1] # CHECK: vstrd.64 q0, [q1] @ encoding: [0x82,0xfd,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.s64 q0, [q1] # CHECK: vstrd.64 q0, [q1] @ encoding: [0x82,0xfd,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.f64 q0, [q1] # CHECK: vstrd.64 q7, [q1]! @ encoding: [0xa2,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.u64 q7, [q1]! # CHECK: vstrd.64 q7, [q1]! @ encoding: [0xa2,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.s64 q7, [q1]! # CHECK: vstrd.64 q7, [q1]! @ encoding: [0xa2,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.f64 q7, [q1]! # CHECK: vstrd.64 q7, [q1, #1016] @ encoding: [0x82,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.u64 q7, [q1, #1016] # CHECK: vstrd.64 q7, [q1, #1016] @ encoding: [0x82,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.s64 q7, [q1, #1016] # CHECK: vstrd.64 q7, [q1, #1016] @ encoding: [0x82,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.f64 q7, [q1, #1016] # CHECK: vstrd.64 q7, [q1, #-8]! @ encoding: [0x22,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.u64 q7, [q1, #-8]! # CHECK: vstrd.64 q7, [q1, #-8]! @ encoding: [0x22,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.s64 q7, [q1, #-8]! # CHECK: vstrd.64 q7, [q1, #-8]! @ encoding: [0x22,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.f64 q7, [q1, #-8]! vpste diff --git a/llvm/test/MC/ARM/mve-misc.s b/llvm/test/MC/ARM/mve-misc.s index f3af9e0afe64fbcb27263c05d0978f6c647373c3..251a77b4710dcdd71a32f573d72785713a68c20b 100644 --- a/llvm/test/MC/ARM/mve-misc.s +++ b/llvm/test/MC/ARM/mve-misc.s @@ -7,63 +7,63 @@ # RUN: FileCheck --check-prefix=ERROR-NOMVE < %t %s # CHECK: vpsel q0, q5, q2 @ encoding: [0x3b,0xfe,0x05,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vpsel q0, q5, q2 # CHECK: vpnot @ encoding: [0x31,0xfe,0x4d,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vpnot # CHECK: wlstp.8 lr, r0, #1668 @ encoding: [0x00,0xf0,0x43,0xc3] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.8 lr, r0, #1668 # CHECK: wlstp.16 lr, r0, #1668 @ encoding: [0x10,0xf0,0x43,0xc3] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.16 lr, r0, #1668 # CHECK: wlstp.32 lr, r4, #2706 @ encoding: [0x24,0xf0,0x49,0xcd] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.32 lr, r4, #2706 # CHECK: wlstp.64 lr, lr, #3026 @ encoding: [0x3e,0xf0,0xe9,0xcd] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.64 lr, lr, #3026 # CHECK: wlstp.8 lr, r5, #3436 @ encoding: [0x05,0xf0,0xb7,0xc6] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.8 lr, r5, #3436 # CHECK: wlstp.16 lr, r1, #1060 @ encoding: [0x11,0xf0,0x13,0xc2] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.16 lr, r1, #1060 # CHECK: wlstp.32 lr, r7, #4036 @ encoding: [0x27,0xf0,0xe3,0xc7] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.32 lr, r7, #4036 # CHECK: wlstp.8 lr, r1, #538 @ encoding: [0x01,0xf0,0x0d,0xc9] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.8 lr, r1, #538 # CHECK: wlstp.8 lr, r10, #1404 @ encoding: [0x0a,0xf0,0xbf,0xc2] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.8 lr, r10, #1404 # CHECK: wlstp.8 lr, r10, #1408 @ encoding: [0x0a,0xf0,0xc1,0xc2] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.8 lr, r10, #1408 # CHECK: wlstp.8 lr, r10, #2358 @ encoding: [0x0a,0xf0,0x9b,0xcc] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.8 lr, r10, #2358 # CHECK: wlstp.8 lr, r10, #4086 @ encoding: [0x0a,0xf0,0xfb,0xcf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.8 lr, r10, #4086 # CHECK: wlstp.8 lr, r11, #1442 @ encoding: [0x0b,0xf0,0xd1,0xca] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.8 lr, r11, #1442 # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: loop end is out of range or not a positive multiple of 2 @@ -87,39 +87,39 @@ wlstp.16 lr, sp, #1442 wlstp.32 r10, r11, #1442 # CHECK: wlstp.8 lr, r1, .Lendloop @ encoding: [0x01'A',0xf0'A',0x01'A',0xc0'A'] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.8 lr, r1, .Lendloop # CHECK: wlstp.16 lr, r2, .Lendloop @ encoding: [0x12'A',0xf0'A',0x01'A',0xc0'A'] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.16 lr, r2, .Lendloop # CHECK: wlstp.32 lr, r3, .Lendloop @ encoding: [0x23'A',0xf0'A',0x01'A',0xc0'A'] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.32 lr, r3, .Lendloop # CHECK: wlstp.64 lr, r5, .Lendloop @ encoding: [0x35'A',0xf0'A',0x01'A',0xc0'A'] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.64 lr, r5, .Lendloop # CHECK: wlstp.64 lr, r5, #0 @ encoding: [0x35,0xf0,0x01,0xc0] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.64 lr, r5, #0 # CHECK: dlstp.8 lr, r5 @ encoding: [0x05,0xf0,0x01,0xe0] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve dlstp.8 lr, r5 # CHECK: dlstp.16 lr, r5 @ encoding: [0x15,0xf0,0x01,0xe0] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve dlstp.16 lr, r5 # CHECK: dlstp.32 lr, r7 @ encoding: [0x27,0xf0,0x01,0xe0] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve dlstp.32 lr, r7 # CHECK: dlstp.64 lr, r2 @ encoding: [0x32,0xf0,0x01,0xe0] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve dlstp.64 lr, r2 # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: operand must be a register in range [r0, r12] or r14 @@ -135,15 +135,15 @@ dlstp.64 r10, r0 dlstp.64 lr, pc # CHECK: letp lr, #-2 @ encoding: [0x1f,0xf0,0x01,0xc8] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve letp lr, #-2 # CHECK: letp lr, #-8 @ encoding: [0x1f,0xf0,0x05,0xc0] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve letp lr, #-8 # CHECK: letp lr, #-4094 @ encoding: [0x1f,0xf0,0xff,0xcf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve letp lr, #-4094 # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: invalid operand for instruction @@ -159,7 +159,7 @@ letp lr, #8 letp lr, #-4096 # CHECK: letp lr, .Lstartloop @ encoding: [0x1f'A',0xf0'A',0x01'A',0xc0'A'] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve letp lr, .Lstartloop # CHECK: lctp @ encoding: [0x0f,0xf0,0x01,0xe0] @@ -172,8 +172,11 @@ it eq # ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve lctpeq +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vpste +# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction vpselt.s16 q0, q1, q2 +# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction vpsele.i32 q0, q1, q2 # CHECK: vpste @ encoding: [0x71,0xfe,0x4d,0x8f] # CHECK: vpselt q0, q1, q2 @ encoding: [0x33,0xfe,0x05,0x0f] diff --git a/llvm/test/MC/ARM/neon-complex.s b/llvm/test/MC/ARM/neon-complex.s index 0d428b596c94c029ec8e15633c75339e414f54ea..6054a08dc82e89a019b077be5affd5bac39f3f1d 100644 --- a/llvm/test/MC/ARM/neon-complex.s +++ b/llvm/test/MC/ARM/neon-complex.s @@ -29,8 +29,10 @@ // FP16-ARM: vcmla.f16 q0, q1, q2, #0 @ encoding: [0x44,0x08,0x22,0xfc] // FP16-THUMB: vcmla.f16 q0, q1, q2, #0 @ encoding: [0x22,0xfc,0x44,0x08] // NO-FP16-STDERR: :[[@LINE-3]]:{{[0-9]*}}: note: instruction requires: full half-float -// V82A: :[[@LINE-4]]:{{[0-9]*}}: error: instruction requires: armv8.3a -// NO-NEON_STDERR: :[[@LINE-5]]:{{[0-9]*}}: error: instruction requires: NEON +// V82A: :[[@LINE-4]]:{{[0-9]*}}: error: invalid instruction, any one of the following would fix this: +// V82A: :[[@LINE-5]]:{{[0-9]*}}: note: instruction requires: mve.fp +// V82A: :[[@LINE-6]]:{{[0-9]*}}: note: instruction requires: armv8.3a +// NO-NEON_STDERR: :[[@LINE-7]]:{{[0-9]*}}: error: instruction requires: NEON vcmla.f32 d0, d1, d2, #0 // ARM: vcmla.f32 d0, d1, d2, #0 @ encoding: [0x02,0x08,0x31,0xfc] // THUMB: vcmla.f32 d0, d1, d2, #0 @ encoding: [0x31,0xfc,0x02,0x08] @@ -39,8 +41,10 @@ vcmla.f32 q0, q1, q2, #0 // ARM: vcmla.f32 q0, q1, q2, #0 @ encoding: [0x44,0x08,0x32,0xfc] // THUMB: vcmla.f32 q0, q1, q2, #0 @ encoding: [0x32,0xfc,0x44,0x08] -// V82A: :[[@LINE-3]]:{{[0-9]*}}: error: instruction requires: armv8.3a -// NO-NEON_STDERR: :[[@LINE-4]]:{{[0-9]*}}: error: instruction requires: NEON +// V82A: :[[@LINE-3]]:{{[0-9]*}}: error: invalid instruction, any one of the following would fix this: +// V82A: :[[@LINE-4]]:{{[0-9]*}}: note: instruction requires: mve.fp +// V82A: :[[@LINE-5]]:{{[0-9]*}}: note: instruction requires: armv8.3a +// NO-NEON_STDERR: :[[@LINE-6]]:{{[0-9]*}}: error: instruction requires: NEON // Valid rotations vcmla.f32 d0, d1, d2, #90 @@ -83,8 +87,10 @@ // FP16-ARM: vcadd.f16 q0, q1, q2, #90 @ encoding: [0x44,0x08,0x82,0xfc] // FP16-THUMB: vcadd.f16 q0, q1, q2, #90 @ encoding: [0x82,0xfc,0x44,0x08] // NO-FP16-STDERR: :[[@LINE-3]]:{{[0-9]*}}: note: instruction requires: full half-float -// V82A: :[[@LINE-4]]:{{[0-9]*}}: error: instruction requires: armv8.3a -// NO-NEON_STDERR: :[[@LINE-5]]:{{[0-9]*}}: error: instruction requires: NEON +// V82A: :[[@LINE-4]]:{{[0-9]*}}: error: invalid instruction, any one of the following would fix this: +// V82A: :[[@LINE-5]]:{{[0-9]*}}: note: instruction requires: mve.fp +// V82A: :[[@LINE-6]]:{{[0-9]*}}: note: instruction requires: armv8.3a +// NO-NEON_STDERR: :[[@LINE-7]]:{{[0-9]*}}: error: instruction requires: NEON vcadd.f32 d0, d1, d2, #90 // ARM: vcadd.f32 d0, d1, d2, #90 @ encoding: [0x02,0x08,0x91,0xfc] // THUMB: vcadd.f32 d0, d1, d2, #90 @ encoding: [0x91,0xfc,0x02,0x08] @@ -93,8 +99,10 @@ vcadd.f32 q0, q1, q2, #90 // ARM: vcadd.f32 q0, q1, q2, #90 @ encoding: [0x44,0x08,0x92,0xfc] // THUMB: vcadd.f32 q0, q1, q2, #90 @ encoding: [0x92,0xfc,0x44,0x08] -// V82A: :[[@LINE-3]]:{{[0-9]*}}: error: instruction requires: armv8.3a -// NO-NEON_STDERR: :[[@LINE-4]]:{{[0-9]*}}: error: instruction requires: NEON +// V82A: :[[@LINE-3]]:{{[0-9]*}}: error: invalid instruction, any one of the following would fix this: +// V82A: :[[@LINE-4]]:{{[0-9]*}}: note: instruction requires: mve.fp +// V82A: :[[@LINE-5]]:{{[0-9]*}}: note: instruction requires: armv8.3a +// NO-NEON_STDERR: :[[@LINE-6]]:{{[0-9]*}}: error: instruction requires: NEON // Valid rotations vcadd.f32 d0, d1, d2, #270 diff --git a/llvm/test/MC/ARM/no-mve.s b/llvm/test/MC/ARM/no-mve.s index 668db402dc66ddaac83c11b3b2e314752eef4715..2435ced45a370e3762b85bb716dc3c0506e011df 100644 --- a/llvm/test/MC/ARM/no-mve.s +++ b/llvm/test/MC/ARM/no-mve.s @@ -4,13 +4,13 @@ # RUN: FileCheck --check-prefix=CHECK-MVE < %t %s # CHECK-MVE: instruction requires: mve.fp -# CHECK: invalid instruction +# CHECK: instruction requires: mve.fp vcadd.f32 q1, q2, q3, #270 # CHECK-MVE: instruction requires: mve.fp -# CHECK: invalid instruction +# CHECK: instruction requires: mve.fp vadd.f32 q1, q2, q3 # CHECK-MVE: vadd.i16 q1, q2, q3 @ encoding: [0x14,0xef,0x46,0x28] -# CHECK: invalid instruction +# CHECK: instruction requires: mve vadd.i16 q1, q2, q3 diff --git a/llvm/test/MC/ARM/not-armv4.s b/llvm/test/MC/ARM/not-armv4.s index c62c50c26c31d5611838694edf1d52f6afe26345..b65b12976f78a8aa37fdf90dee942b44714098d3 100644 --- a/llvm/test/MC/ARM/not-armv4.s +++ b/llvm/test/MC/ARM/not-armv4.s @@ -1,13 +1,21 @@ @ RUN: not llvm-mc < %s -triple armv4-unknown-unknown -show-encoding 2>&1 | FileCheck %s @ PR18524 -@ CHECK: instruction requires: armv5t +@ CHECK: error: invalid instruction, any one of the following would fix this: +@ CHECK: note: instruction requires: armv5t +@ CHECK: note: instruction requires: thumb2 clz r4,r9 -@ CHECK: instruction requires: armv6t2 +@ CHECK: error: invalid instruction, any one of the following would fix this: +@ CHECK: note: instruction requires: armv6t2 +@ CHECK: note: instruction requires: thumb2 rbit r4,r9 @ CHECK: error: instruction requires: armv6t2 movw r4,#0x1234 -@ CHECK: error: instruction requires: armv6t2 + +@ CHECK: error: invalid instruction, any one of the following would fix this: +@ CHECK: note: invalid operand for instruction +@ CHECK: note: operand must be a register in range [r0, r15] +@ CHECK: note: instruction requires: armv6t2 mov r4,#0x1234 diff --git a/llvm/test/MC/ARM/register-token-source-loc.s b/llvm/test/MC/ARM/register-token-source-loc.s index afb6ba0c61a39eb1fa204f93aabe808749fd1b61..7560f95999e71ba92b805cccc74c991087bf1301 100644 --- a/llvm/test/MC/ARM/register-token-source-loc.s +++ b/llvm/test/MC/ARM/register-token-source-loc.s @@ -3,6 +3,9 @@ // CHECK: error: invalid instruction, any one of the following would fix this: // CHECK-NEXT: add sp, r0, #4 // CHECK-NEXT: ^ +// CHECK-NEXT: note: operand must be a register in range [r0, r7] +// CHECK-NEXT: add sp, r0, #4 +// CHECK-NEXT: ^ // CHECK-NEXT: note: operand must be a register sp // CHECK-NEXT: add sp, r0, #4 // CHECK-NEXT: ^ diff --git a/llvm/test/MC/ARM/tMOVSr.s b/llvm/test/MC/ARM/tMOVSr.s index 198c90aa5ceb46da62daf06be1e99b128ffde8b4..09602fecd68513d198116aaaafcc46f628903717 100644 --- a/llvm/test/MC/ARM/tMOVSr.s +++ b/llvm/test/MC/ARM/tMOVSr.s @@ -1,6 +1,7 @@ @ REQUIRES: asserts -@ RUN: llvm-mc --triple=thumbv8 --debug %s 2>&1 | FileCheck %s --match-full-lines +@ RUN: llvm-mc --triple=thumbv8 %s --show-encoding 2>&1 | FileCheck %s --match-full-lines -@ CHECK: Changed to: <MCInst #{{[0-9]+}} tMOVSr <MCOperand Reg:{{[0-9]+}}> <MCOperand Reg:{{[0-9]+}}>> +// Note this makes sure the narrow instruciton is selected +@ CHECK: movs r2, r3 @ encoding: [0x1a,0x00] .text movs r2, r3 diff --git a/llvm/test/MC/ARM/thumb-diagnostics.s b/llvm/test/MC/ARM/thumb-diagnostics.s index cacd7f21cb9d361ed34290db1e1d4b240a8cc10b..171d60ac13f9a84449c1ab40ec5f79b3926b1f76 100644 --- a/llvm/test/MC/ARM/thumb-diagnostics.s +++ b/llvm/test/MC/ARM/thumb-diagnostics.s @@ -28,9 +28,12 @@ @ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: instruction variant requires Thumb2 @ CHECK-ERRORS: note: operand must be a register sp -@ CHECK-ERRORS-V5: error: instruction variant requires ARMv6 or later +@ CHECK-ERRORS-V5: error: invalid instruction, any one of the following would fix this: @ CHECK-ERRORS-V5: mov r2, r3 @ CHECK-ERRORS-V5: ^ +@ CHECK-ERRORS-V5: note: instruction requires: arm-mode +@ CHECK-ERRORS-V5: note: operand must be an immediate in the range [0,255] or a relocatable expression +@ CHECK-ERRORS-V5: note: instruction variant requires ARMv6 or later @ Immediates where registers were expected adds #0, r1, r2 @@ -225,10 +228,11 @@ @ Mismatched source/destination operands for MUL instruction. muls r1, r2, r3 -@ CHECK-ERRORS: error: destination register must match source register +@ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: @ CHECK-ERRORS: muls r1, r2, r3 -@ CHECK-ERRORS: ^ - +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: note: destination register must match a source register +@ CHECK-ERRORS: note: too many operands for instruction @ Out of range immediates for STR instruction. str r2, [r7, #-1] @@ -274,30 +278,33 @@ @ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: @ CHECK-ERRORS: add sp, #-1 @ CHECK-ERRORS: ^ +@ CHECK-ERRORS: note: instruction requires: thumb2 +@ CHECK-ERRORS: add sp, #-1 +@ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: operand must be a register in range [r0, r15] @ CHECK-ERRORS: add sp, #-1 @ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: invalid operand for instruction @ CHECK-ERRORS: add sp, #-1 @ CHECK-ERRORS: ^ -@ CHECK-ERRORS: note: instruction requires: thumb2 -@ CHECK-ERRORS: add sp, #-1 -@ CHECK-ERRORS: ^ @ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: @ CHECK-ERRORS: add sp, #3 @ CHECK-ERRORS: ^ +@ CHECK-ERRORS: note: instruction requires: thumb2 +@ CHECK-ERRORS: add sp, #3 +@ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: operand must be a register in range [r0, r15] @ CHECK-ERRORS: add sp, #3 @ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: invalid operand for instruction @ CHECK-ERRORS: add sp, #3 @ CHECK-ERRORS: ^ -@ CHECK-ERRORS: note: instruction requires: thumb2 -@ CHECK-ERRORS: add sp, #3 -@ CHECK-ERRORS: ^ @ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: @ CHECK-ERRORS: add sp, sp, #512 @ CHECK-ERRORS: ^ +@ CHECK-ERRORS: note: instruction requires: thumb2 +@ CHECK-ERRORS: add sp, sp, #512 +@ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: operand must be a register in range [r0, r15] @ CHECK-ERRORS: add sp, sp, #512 @ CHECK-ERRORS: ^ @@ -305,9 +312,6 @@ @ CHECK-ERRORS: add sp, sp, #512 @ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: instruction requires: thumb2 -@ CHECK-ERRORS: add sp, sp, #512 -@ CHECK-ERRORS: ^ -@ CHECK-ERRORS: error: instruction requires: thumb2 @ CHECK-ERRORS: add r2, sp, #1024 @ CHECK-ERRORS: ^ add r2, sp, ip @@ -407,7 +411,8 @@ adds adds r0 @ CHECK-ERRORS: error: too few operands for instruction -@ CHECK-ERRORS: error: too few operands for instruction +@ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: +@ CHECK-ERRORS: note: too few operands for instruction @------------------------------------------------------------------------------ @ Out of range width for SBFX/UBFX diff --git a/llvm/test/MC/ARM/thumb-mov.s b/llvm/test/MC/ARM/thumb-mov.s index 6f662f3ee2c720bec516ddec57c28193b4f1e409..e910722f2edf495e2e3793dc769d882b3fb33792 100644 --- a/llvm/test/MC/ARM/thumb-mov.s +++ b/llvm/test/MC/ARM/thumb-mov.s @@ -58,10 +58,16 @@ movs sp, r0 movs r0, sp movs sp, sp -// CHECK-V7: error: instruction variant requires ARMv8 or later +// CHECK-V7: error: invalid instruction, any one of the following would fix this: // CHECK-V7-NEXT: movs sp, r0 -// CHECK-V7: instruction variant requires ARMv8 or later +// CHECK-V7: note: instruction variant requires ARMv8 or later +// CHECK-V7: note: operand must be a register in range [r0, r7] +// CHECK-V7: error: invalid instruction, any one of the following would fix this: // CHECK-V7-NEXT: movs r0, sp +// CHECK-V7: note: instruction variant requires ARMv8 or later +// CHECK-V7: note: invalid operand for instruction +// CHECK-V7: note: operand must be an immediate in the range [0,255] or a relocatable expression +// CHECK-V7: note: operand must be a register in range [r0, r7] // CHECK-V7: error: instruction variant requires ARMv8 or later // CHECK-V7-NEXT: movs sp, sp // CHECK-V8: movs.w sp, r0 @ encoding: [0x5f,0xea,0x00,0x0d] @@ -69,8 +75,9 @@ // CHECK-V8: movs.w sp, sp @ encoding: [0x5f,0xea,0x0d,0x0d] mov.w sp, sp -// CHECK-V7: error: instruction variant requires ARMv8 or later +// CHECK-V7: error: invalid instruction, any one of the following would fix this: // CHECK-V7-NEXT: mov.w sp, sp +// CHECK-V7: note: instruction variant requires ARMv8 or later // CHECK-V8: mov.w sp, sp @ encoding: [0x4f,0xea,0x0d,0x0d] movs.w sp, r0 @@ -78,8 +85,9 @@ movs.w sp, sp // CHECK-V7: error: instruction variant requires ARMv8 or later // CHECK-V7-NEXT: movs.w sp, r0 -// CHECK-V7: instruction variant requires ARMv8 or later +// CHECK-V7: error: invalid instruction, any one of the following would fix this: // CHECK-V7-NEXT: movs.w r0, sp +// CHECK-V7: note: instruction variant requires ARMv8 or later // CHECK-V7: error: instruction variant requires ARMv8 or later // CHECK-V7-NEXT: movs.w sp, sp // CHECK-V8: movs.w sp, r0 @ encoding: [0x5f,0xea,0x00,0x0d] diff --git a/llvm/test/MC/ARM/thumb2-diagnostics.s b/llvm/test/MC/ARM/thumb2-diagnostics.s index 45efd3c62120c1e615d4a82726d227bf74a772d0..afb12ce43098128dad6cb32fb5ddfd6bd5089034 100644 --- a/llvm/test/MC/ARM/thumb2-diagnostics.s +++ b/llvm/test/MC/ARM/thumb2-diagnostics.s @@ -156,7 +156,9 @@ foo2: adds adds r0 @ CHECK-ERRORS: error: too few operands for instruction -@ CHECK-ERRORS: error: too few operands for instruction +@ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: +@ CHECK-ERRORS: note: too few operands for instruction +@ CHECK-ERRORS: note: operand must be a register in range [r0, r15] tst sp, #3 tst sp, r5 diff --git a/llvm/test/MC/ARM/vfp4.s b/llvm/test/MC/ARM/vfp4.s index 37d03bb53de8e9f1db4f514f5ae47b98391b113f..f3bc5750f43128436e81e41d28429caf0bab8015 100644 --- a/llvm/test/MC/ARM/vfp4.s +++ b/llvm/test/MC/ARM/vfp4.s @@ -23,7 +23,7 @@ vfma.f32 d16, d18, d17 @ ARM: vfma.f32 q2, q4, q0 @ encoding: [0x50,0x4c,0x08,0xf2] @ THUMB: vfma.f32 q2, q4, q0 @ encoding: [0x08,0xef,0x50,0x4c] -@ THUMB_V7EM-ERRORS: error: invalid instruction +@ THUMB_V7EM-ERRORS: error: instruction requires: mve.fp @ THUMB_V7EM-ERRORS-NEXT: vfma.f32 q2, q4, q0 vfma.f32 q2, q4, q0 @@ -57,7 +57,7 @@ vfms.f32 d16, d18, d17 @ ARM: vfms.f32 q2, q4, q0 @ encoding: [0x50,0x4c,0x28,0xf2] @ THUMB: vfms.f32 q2, q4, q0 @ encoding: [0x28,0xef,0x50,0x4c] -@ THUMB_V7EM-ERRORS: error: invalid instruction +@ THUMB_V7EM-ERRORS: error: instruction requires: mve.fp @ THUMB_V7EM-ERRORS-NEXT: vfms.f32 q2, q4, q0 vfms.f32 q2, q4, q0 diff --git a/llvm/test/MC/BPF/insn-unit.s b/llvm/test/MC/BPF/insn-unit.s index 224eb7381aa234064b021bd20da4b6fdef879825..84735d196030d6392ab52a3d07805b0ba5d3a7eb 100644 --- a/llvm/test/MC/BPF/insn-unit.s +++ b/llvm/test/MC/BPF/insn-unit.s @@ -65,8 +65,10 @@ // CHECK: 8d 02 00 00 00 00 00 00 callx r2 // ======== BPF_JMP Class ======== + may_goto Llabel0 // BPF_JCOND | BPF_K if r1 & r2 goto Llabel0 // BPF_JSET | BPF_X if r1 & 0xffff goto Llabel0 // BPF_JSET | BPF_K +// CHECK: e5 00 1e 00 00 00 00 00 may_goto +30 // CHECK: 4d 21 1d 00 00 00 00 00 if r1 & r2 goto +29 // CHECK: 45 01 1c 00 ff ff 00 00 if r1 & 65535 goto +28 diff --git a/llvm/test/MC/COFF/dwarf5lineinfo.s b/llvm/test/MC/COFF/dwarf5lineinfo.s new file mode 100644 index 0000000000000000000000000000000000000000..f0789feb2085089381f488598b6cf3eb160bab57 --- /dev/null +++ b/llvm/test/MC/COFF/dwarf5lineinfo.s @@ -0,0 +1,13 @@ +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-windows-gnu %s -o - | llvm-readobj -r - | FileCheck %s + +// CHECK: Relocations [ +// CHECK: Section (4) .debug_line { +// CHECK: 0x22 IMAGE_REL_AMD64_SECREL .debug_line_str (8) +// CHECK: 0x2C IMAGE_REL_AMD64_SECREL .debug_line_str (8) +// CHECK: 0x36 IMAGE_REL_AMD64_ADDR64 .text (0) +// CHECK: } + +main: + .file 0 "/" "test.c" + .loc 0 1 0 + retq diff --git a/llvm/test/MC/Disassembler/AMDGPU/gfx11_dasm_sop1.txt b/llvm/test/MC/Disassembler/AMDGPU/gfx11_dasm_sop1.txt index fbb95450dbbe2f246d0b07743dcae30db719c7a4..929f3d2129be923e526f9b9018587d0c97089290 100644 --- a/llvm/test/MC/Disassembler/AMDGPU/gfx11_dasm_sop1.txt +++ b/llvm/test/MC/Disassembler/AMDGPU/gfx11_dasm_sop1.txt @@ -2536,6 +2536,9 @@ # GFX11: s_sendmsg_rtn_b32 s0, sendmsg(MSG_RTN_GET_TBA) ; encoding: [0x85,0x4c,0x80,0xbe] 0x85,0x4c,0x80,0xbe +# GFX11: s_sendmsg_rtn_b32 s0, sendmsg(MSG_RTN_GET_TBA_TO_PC) ; encoding: [0x86,0x4c,0x80,0xbe] +0x86,0x4c,0x80,0xbe + # GFX11: s_setpc_b64 s[0:1] ; encoding: [0x00,0x48,0x80,0xbe] 0x00,0x48,0x80,0xbe diff --git a/llvm/test/MC/Disassembler/AMDGPU/gfx11_dasm_vinterp.txt b/llvm/test/MC/Disassembler/AMDGPU/gfx11_dasm_vinterp.txt deleted file mode 100644 index b22fd5e289faef3515fdb2b417f38b37d76b8f65..0000000000000000000000000000000000000000 --- a/llvm/test/MC/Disassembler/AMDGPU/gfx11_dasm_vinterp.txt +++ /dev/null @@ -1,251 +0,0 @@ -# RUN: llvm-mc -triple=amdgcn -mcpu=gfx1100 -disassemble %s | FileCheck -strict-whitespace -check-prefix=GFX11 %s - -# GFX11: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x04 - -# Check that unused bits in the encoding are ignored. -# GFX11: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x80,0xcd,0x01,0x05,0x0e,0x1c - -# GFX11: v_interp_p10_f32 v1, v10, v20, v30 wait_exp:0{{$}} -0x01,0x00,0x00,0xcd,0x0a,0x29,0x7a,0x04 - -# GFX11: v_interp_p10_f32 v2, v11, v21, v31 wait_exp:0{{$}} -0x02,0x00,0x00,0xcd,0x0b,0x2b,0x7e,0x04 - -# GFX11: v_interp_p10_f32 v3, v12, v22, v32 wait_exp:0{{$}} -0x03,0x00,0x00,0xcd,0x0c,0x2d,0x82,0x04 - -# GFX11: v_interp_p10_f32 v0, v1, v2, v3 clamp wait_exp:0{{$}} -0x00,0x80,0x00,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_f32 v0, -v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x24 - -# GFX11: v_interp_p10_f32 v0, v1, -v2, v3 wait_exp:0{{$}} -0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x44 - -# GFX11: v_interp_p10_f32 v0, v1, v2, -v3 wait_exp:0{{$}} -0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x84 - -# GFX11: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:1{{$}} -0x00,0x01,0x00,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:7{{$}} -0x00,0x07,0x00,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_f32 v0, v1, v2, v3 clamp wait_exp:7{{$}} -0x00,0x87,0x00,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_f32 v0, v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_f32 v1, v10, v20, v30 wait_exp:0{{$}} -0x01,0x00,0x01,0xcd,0x0a,0x29,0x7a,0x04 - -# GFX11: v_interp_p2_f32 v2, v11, v21, v31 wait_exp:0{{$}} -0x02,0x00,0x01,0xcd,0x0b,0x2b,0x7e,0x04 - -# GFX11: v_interp_p2_f32 v3, v12, v22, v32 wait_exp:0{{$}} -0x03,0x00,0x01,0xcd,0x0c,0x2d,0x82,0x04 - -# GFX11: v_interp_p2_f32 v0, v1, v2, v3 clamp wait_exp:0{{$}} -0x00,0x80,0x01,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_f32 v0, -v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x24 - -# GFX11: v_interp_p2_f32 v0, v1, -v2, v3 wait_exp:0{{$}} -0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x44 - -# GFX11: v_interp_p2_f32 v0, v1, v2, -v3 wait_exp:0{{$}} -0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x84 - -# GFX11: v_interp_p2_f32 v0, v1, v2, v3 wait_exp:1{{$}} -0x00,0x01,0x01,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_f32 v0, v1, v2, v3 wait_exp:7{{$}} -0x00,0x07,0x01,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_f32 v0, v1, v2, v3 clamp wait_exp:7{{$}} -0x00,0x87,0x01,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_f16_f32 v0, -v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x24 - -# GFX11: v_interp_p10_f16_f32 v0, v1, -v2, v3 wait_exp:0{{$}} -0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x44 - -# GFX11: v_interp_p10_f16_f32 v0, v1, v2, -v3 wait_exp:0{{$}} -0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x84 - -# GFX11: v_interp_p10_f16_f32 v0, v1, v2, v3 clamp wait_exp:0{{$}} -0x00,0x80,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:1{{$}} -0x00,0x01,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:7{{$}} -0x00,0x07,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] wait_exp:0{{$}} -0x00,0x08,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] wait_exp:0{{$}} -0x00,0x10,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] wait_exp:0{{$}} -0x00,0x20,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] wait_exp:0{{$}} -0x00,0x40,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] wait_exp:0{{$}} -0x00,0x78,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0x4d,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0xcd,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0xcd,0x02,0xcd,0x01,0x05,0x0e,0xe4 - -# GFX11: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_f16_f32 v0, -v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x24 - -# GFX11: v_interp_p2_f16_f32 v0, v1, -v2, v3 wait_exp:0{{$}} -0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x44 - -# GFX11: v_interp_p2_f16_f32 v0, v1, v2, -v3 wait_exp:0{{$}} -0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x84 - -# GFX11: v_interp_p2_f16_f32 v0, v1, v2, v3 clamp wait_exp:0{{$}} -0x00,0x80,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:1{{$}} -0x00,0x01,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:7{{$}} -0x00,0x07,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] wait_exp:0{{$}} -0x00,0x08,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] wait_exp:0{{$}} -0x00,0x10,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] wait_exp:0{{$}} -0x00,0x20,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] wait_exp:0{{$}} -0x00,0x40,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] wait_exp:0{{$}} -0x00,0x78,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0x4d,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0xcd,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0xcd,0x03,0xcd,0x01,0x05,0x0e,0xe4 - -# GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_rtz_f16_f32 v0, -v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x24 - -# GFX11: v_interp_p10_rtz_f16_f32 v0, v1, -v2, v3 wait_exp:0{{$}} -0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x44 - -# GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, -v3 wait_exp:0{{$}} -0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x84 - -# GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 clamp wait_exp:0{{$}} -0x00,0x80,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:1{{$}} -0x00,0x01,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:7{{$}} -0x00,0x07,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] wait_exp:0{{$}} -0x00,0x08,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] wait_exp:0{{$}} -0x00,0x10,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] wait_exp:0{{$}} -0x00,0x20,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] wait_exp:0{{$}} -0x00,0x40,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] wait_exp:0{{$}} -0x00,0x78,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0x4d,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0xcd,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p10_rtz_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0xcd,0x04,0xcd,0x01,0x05,0x0e,0xe4 - -# GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_rtz_f16_f32 v0, -v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x24 - -# GFX11: v_interp_p2_rtz_f16_f32 v0, v1, -v2, v3 wait_exp:0{{$}} -0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x44 - -# GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, -v3 wait_exp:0{{$}} -0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x84 - -# GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 clamp wait_exp:0{{$}} -0x00,0x80,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:1{{$}} -0x00,0x01,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:7{{$}} -0x00,0x07,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] wait_exp:0{{$}} -0x00,0x08,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] wait_exp:0{{$}} -0x00,0x10,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] wait_exp:0{{$}} -0x00,0x20,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] wait_exp:0{{$}} -0x00,0x40,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] wait_exp:0{{$}} -0x00,0x78,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0x4d,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0xcd,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX11: v_interp_p2_rtz_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0xcd,0x05,0xcd,0x01,0x05,0x0e,0xe4 diff --git a/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_features.txt b/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_features.txt index 0c4427cff63ea6f0b08b5972e293789a6fd94245..1be97b242284de005585b893b7184d306a05df4b 100644 --- a/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_features.txt +++ b/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_features.txt @@ -12,8 +12,13 @@ # GFX12: v_add3_u32_e64_dpp v5, v1, 42, v0 dpp8:[7,6,5,4,3,2,1,0] ; encoding: [0x05,0x00,0x55,0xd6,0xe9,0x54,0x01,0x04,0x01,0x77,0x39,0x05] 0x05,0x00,0x55,0xd6,0xe9,0x54,0x01,0x04,0x01,0x77,0x39,0x05 -# GFX1150: v_add3_u32_e64_dpp v5, v1, s2, s3 dpp8:[7,6,5,4,3,2,1,0] ; encoding: [0x05,0x00,0x55,0xd6,0xe9,0x04,0x0c,0x00,0x01,0x77,0x39,0x05] +# GFX12: v_add3_u32_e64_dpp v5, v1, s2, s3 dpp8:[7,6,5,4,3,2,1,0] ; encoding: [0x05,0x00,0x55,0xd6,0xe9,0x04,0x0c,0x00,0x01,0x77,0x39,0x05] 0x05,0x00,0x55,0xd6,0xe9,0x04,0x0c,0x00,0x01,0x77,0x39,0x05 -# GFX1150: v_cmp_ne_i32_e64_dpp vcc_lo, v1, s2 dpp8:[7,6,5,4,3,2,1,0] ; encoding: [0x6a,0x00,0x45,0xd4,0xe9,0x04,0x00,0x00,0x01,0x77,0x39,0x05] +# GFX12: v_cmp_ne_i32_e64_dpp vcc_lo, v1, s2 dpp8:[7,6,5,4,3,2,1,0] ; encoding: [0x6a,0x00,0x45,0xd4,0xe9,0x04,0x00,0x00,0x01,0x77,0x39,0x05] 0x6a,0x00,0x45,0xd4,0xe9,0x04,0x00,0x00,0x01,0x77,0x39,0x05 + +# Check that unused bits in the encoding are ignored. +# This is more strict than the check in vinterp-fake16.txt and is GFX12 specific. +# GFX12: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:0 ; encoding: [0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x04] +0x00,0x00,0xe0,0xcd,0x01,0x05,0x0e,0x1c diff --git a/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_sop1.txt b/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_sop1.txt index c87cea1205681d555862455038499b8cfa93c21c..f8c235f77b5f56231f1545275937ea3d4c7809a9 100644 --- a/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_sop1.txt +++ b/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_sop1.txt @@ -3279,9 +3279,12 @@ # GFX12: s_sendmsg_rtn_b32 s0, sendmsg(MSG_RTN_GET_TBA) ; encoding: [0x85,0x4c,0x80,0xbe] 0x85,0x4c,0x80,0xbe -# GFX12: s_sendmsg_rtn_b32 s0, sendmsg(MSG_RTN_GET_SE_AID_ID) ; encoding: [0x86,0x4c,0x80,0xbe] +# GFX12: s_sendmsg_rtn_b32 s0, sendmsg(MSG_RTN_GET_TBA_TO_PC) ; encoding: [0x86,0x4c,0x80,0xbe] 0x86,0x4c,0x80,0xbe +# GFX12: s_sendmsg_rtn_b32 s0, sendmsg(MSG_RTN_GET_SE_AID_ID) ; encoding: [0x87,0x4c,0x80,0xbe] +0x87,0x4c,0x80,0xbe + # GFX12: s_setpc_b64 s[0:1] ; encoding: [0x00,0x48,0x80,0xbe] 0x00,0x48,0x80,0xbe diff --git a/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_vinterp.txt b/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_vinterp.txt deleted file mode 100644 index 977cd732947cdd35881e8bfc6d7000c854ed96fc..0000000000000000000000000000000000000000 --- a/llvm/test/MC/Disassembler/AMDGPU/gfx12_dasm_vinterp.txt +++ /dev/null @@ -1,251 +0,0 @@ -# RUN: llvm-mc -triple=amdgcn -mcpu=gfx1200 -disassemble %s | FileCheck -strict-whitespace -check-prefix=GFX12 %s - -# GFX12: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x04 - -# Check that unused bits in the encoding are ignored. -# GFX12: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0xe0,0xcd,0x01,0x05,0x0e,0x1c - -# GFX12: v_interp_p10_f32 v1, v10, v20, v30 wait_exp:0{{$}} -0x01,0x00,0x00,0xcd,0x0a,0x29,0x7a,0x04 - -# GFX12: v_interp_p10_f32 v2, v11, v21, v31 wait_exp:0{{$}} -0x02,0x00,0x00,0xcd,0x0b,0x2b,0x7e,0x04 - -# GFX12: v_interp_p10_f32 v3, v12, v22, v32 wait_exp:0{{$}} -0x03,0x00,0x00,0xcd,0x0c,0x2d,0x82,0x04 - -# GFX12: v_interp_p10_f32 v0, v1, v2, v3 clamp wait_exp:0{{$}} -0x00,0x80,0x00,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_f32 v0, -v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x24 - -# GFX12: v_interp_p10_f32 v0, v1, -v2, v3 wait_exp:0{{$}} -0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x44 - -# GFX12: v_interp_p10_f32 v0, v1, v2, -v3 wait_exp:0{{$}} -0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x84 - -# GFX12: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:1{{$}} -0x00,0x01,0x00,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:7{{$}} -0x00,0x07,0x00,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_f32 v0, v1, v2, v3 clamp wait_exp:7{{$}} -0x00,0x87,0x00,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_f32 v0, v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_f32 v1, v10, v20, v30 wait_exp:0{{$}} -0x01,0x00,0x01,0xcd,0x0a,0x29,0x7a,0x04 - -# GFX12: v_interp_p2_f32 v2, v11, v21, v31 wait_exp:0{{$}} -0x02,0x00,0x01,0xcd,0x0b,0x2b,0x7e,0x04 - -# GFX12: v_interp_p2_f32 v3, v12, v22, v32 wait_exp:0{{$}} -0x03,0x00,0x01,0xcd,0x0c,0x2d,0x82,0x04 - -# GFX12: v_interp_p2_f32 v0, v1, v2, v3 clamp wait_exp:0{{$}} -0x00,0x80,0x01,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_f32 v0, -v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x24 - -# GFX12: v_interp_p2_f32 v0, v1, -v2, v3 wait_exp:0{{$}} -0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x44 - -# GFX12: v_interp_p2_f32 v0, v1, v2, -v3 wait_exp:0{{$}} -0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x84 - -# GFX12: v_interp_p2_f32 v0, v1, v2, v3 wait_exp:1{{$}} -0x00,0x01,0x01,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_f32 v0, v1, v2, v3 wait_exp:7{{$}} -0x00,0x07,0x01,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_f32 v0, v1, v2, v3 clamp wait_exp:7{{$}} -0x00,0x87,0x01,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_f16_f32 v0, -v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x24 - -# GFX12: v_interp_p10_f16_f32 v0, v1, -v2, v3 wait_exp:0{{$}} -0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x44 - -# GFX12: v_interp_p10_f16_f32 v0, v1, v2, -v3 wait_exp:0{{$}} -0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x84 - -# GFX12: v_interp_p10_f16_f32 v0, v1, v2, v3 clamp wait_exp:0{{$}} -0x00,0x80,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:1{{$}} -0x00,0x01,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:7{{$}} -0x00,0x07,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] wait_exp:0{{$}} -0x00,0x08,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] wait_exp:0{{$}} -0x00,0x10,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] wait_exp:0{{$}} -0x00,0x20,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] wait_exp:0{{$}} -0x00,0x40,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] wait_exp:0{{$}} -0x00,0x78,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0x4d,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0xcd,0x02,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0xcd,0x02,0xcd,0x01,0x05,0x0e,0xe4 - -# GFX12: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_f16_f32 v0, -v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x24 - -# GFX12: v_interp_p2_f16_f32 v0, v1, -v2, v3 wait_exp:0{{$}} -0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x44 - -# GFX12: v_interp_p2_f16_f32 v0, v1, v2, -v3 wait_exp:0{{$}} -0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x84 - -# GFX12: v_interp_p2_f16_f32 v0, v1, v2, v3 clamp wait_exp:0{{$}} -0x00,0x80,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:1{{$}} -0x00,0x01,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:7{{$}} -0x00,0x07,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] wait_exp:0{{$}} -0x00,0x08,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] wait_exp:0{{$}} -0x00,0x10,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] wait_exp:0{{$}} -0x00,0x20,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] wait_exp:0{{$}} -0x00,0x40,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] wait_exp:0{{$}} -0x00,0x78,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0x4d,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0xcd,0x03,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0xcd,0x03,0xcd,0x01,0x05,0x0e,0xe4 - -# GFX12: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_rtz_f16_f32 v0, -v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x24 - -# GFX12: v_interp_p10_rtz_f16_f32 v0, v1, -v2, v3 wait_exp:0{{$}} -0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x44 - -# GFX12: v_interp_p10_rtz_f16_f32 v0, v1, v2, -v3 wait_exp:0{{$}} -0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x84 - -# GFX12: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 clamp wait_exp:0{{$}} -0x00,0x80,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:1{{$}} -0x00,0x01,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:7{{$}} -0x00,0x07,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] wait_exp:0{{$}} -0x00,0x08,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] wait_exp:0{{$}} -0x00,0x10,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] wait_exp:0{{$}} -0x00,0x20,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] wait_exp:0{{$}} -0x00,0x40,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] wait_exp:0{{$}} -0x00,0x78,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0x4d,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0xcd,0x04,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p10_rtz_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0xcd,0x04,0xcd,0x01,0x05,0x0e,0xe4 - -# GFX12: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_rtz_f16_f32 v0, -v1, v2, v3 wait_exp:0{{$}} -0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x24 - -# GFX12: v_interp_p2_rtz_f16_f32 v0, v1, -v2, v3 wait_exp:0{{$}} -0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x44 - -# GFX12: v_interp_p2_rtz_f16_f32 v0, v1, v2, -v3 wait_exp:0{{$}} -0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x84 - -# GFX12: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 clamp wait_exp:0{{$}} -0x00,0x80,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:1{{$}} -0x00,0x01,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:7{{$}} -0x00,0x07,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] wait_exp:0{{$}} -0x00,0x08,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] wait_exp:0{{$}} -0x00,0x10,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] wait_exp:0{{$}} -0x00,0x20,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] wait_exp:0{{$}} -0x00,0x40,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] wait_exp:0{{$}} -0x00,0x78,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0x4d,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0xcd,0x05,0xcd,0x01,0x05,0x0e,0x04 - -# GFX12: v_interp_p2_rtz_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} -0x00,0xcd,0x05,0xcd,0x01,0x05,0x0e,0xe4 diff --git a/llvm/test/MC/Disassembler/AMDGPU/vinterp-fake16.txt b/llvm/test/MC/Disassembler/AMDGPU/vinterp-fake16.txt new file mode 100644 index 0000000000000000000000000000000000000000..239f1d8b3058da865a060c9aba9e049dc9214281 --- /dev/null +++ b/llvm/test/MC/Disassembler/AMDGPU/vinterp-fake16.txt @@ -0,0 +1,252 @@ +# RUN: llvm-mc -triple=amdgcn -mcpu=gfx1100 -mattr=-real-true16 -disassemble %s | FileCheck -strict-whitespace -check-prefix=CHECK %s +# RUN: llvm-mc -triple=amdgcn -mcpu=gfx1200 -mattr=-real-true16 -disassemble %s | FileCheck -strict-whitespace -check-prefix=CHECK %s + +# CHECK: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:0{{$}} +0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x04 + +# Check that unused bits in the encoding are ignored. +# CHECK: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:0{{$}} +0x00,0x00,0x80,0xcd,0x01,0x05,0x0e,0x1c + +# CHECK: v_interp_p10_f32 v1, v10, v20, v30 wait_exp:0{{$}} +0x01,0x00,0x00,0xcd,0x0a,0x29,0x7a,0x04 + +# CHECK: v_interp_p10_f32 v2, v11, v21, v31 wait_exp:0{{$}} +0x02,0x00,0x00,0xcd,0x0b,0x2b,0x7e,0x04 + +# CHECK: v_interp_p10_f32 v3, v12, v22, v32 wait_exp:0{{$}} +0x03,0x00,0x00,0xcd,0x0c,0x2d,0x82,0x04 + +# CHECK: v_interp_p10_f32 v0, v1, v2, v3 clamp wait_exp:0{{$}} +0x00,0x80,0x00,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_f32 v0, -v1, v2, v3 wait_exp:0{{$}} +0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x24 + +# CHECK: v_interp_p10_f32 v0, v1, -v2, v3 wait_exp:0{{$}} +0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x44 + +# CHECK: v_interp_p10_f32 v0, v1, v2, -v3 wait_exp:0{{$}} +0x00,0x00,0x00,0xcd,0x01,0x05,0x0e,0x84 + +# CHECK: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:1{{$}} +0x00,0x01,0x00,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_f32 v0, v1, v2, v3 wait_exp:7{{$}} +0x00,0x07,0x00,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_f32 v0, v1, v2, v3 clamp wait_exp:7{{$}} +0x00,0x87,0x00,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_f32 v0, v1, v2, v3 wait_exp:0{{$}} +0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_f32 v1, v10, v20, v30 wait_exp:0{{$}} +0x01,0x00,0x01,0xcd,0x0a,0x29,0x7a,0x04 + +# CHECK: v_interp_p2_f32 v2, v11, v21, v31 wait_exp:0{{$}} +0x02,0x00,0x01,0xcd,0x0b,0x2b,0x7e,0x04 + +# CHECK: v_interp_p2_f32 v3, v12, v22, v32 wait_exp:0{{$}} +0x03,0x00,0x01,0xcd,0x0c,0x2d,0x82,0x04 + +# CHECK: v_interp_p2_f32 v0, v1, v2, v3 clamp wait_exp:0{{$}} +0x00,0x80,0x01,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_f32 v0, -v1, v2, v3 wait_exp:0{{$}} +0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x24 + +# CHECK: v_interp_p2_f32 v0, v1, -v2, v3 wait_exp:0{{$}} +0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x44 + +# CHECK: v_interp_p2_f32 v0, v1, v2, -v3 wait_exp:0{{$}} +0x00,0x00,0x01,0xcd,0x01,0x05,0x0e,0x84 + +# CHECK: v_interp_p2_f32 v0, v1, v2, v3 wait_exp:1{{$}} +0x00,0x01,0x01,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_f32 v0, v1, v2, v3 wait_exp:7{{$}} +0x00,0x07,0x01,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_f32 v0, v1, v2, v3 clamp wait_exp:7{{$}} +0x00,0x87,0x01,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:0{{$}} +0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_f16_f32 v0, -v1, v2, v3 wait_exp:0{{$}} +0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x24 + +# CHECK: v_interp_p10_f16_f32 v0, v1, -v2, v3 wait_exp:0{{$}} +0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x44 + +# CHECK: v_interp_p10_f16_f32 v0, v1, v2, -v3 wait_exp:0{{$}} +0x00,0x00,0x02,0xcd,0x01,0x05,0x0e,0x84 + +# CHECK: v_interp_p10_f16_f32 v0, v1, v2, v3 clamp wait_exp:0{{$}} +0x00,0x80,0x02,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:1{{$}} +0x00,0x01,0x02,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_f16_f32 v0, v1, v2, v3 wait_exp:7{{$}} +0x00,0x07,0x02,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] wait_exp:0{{$}} +0x00,0x08,0x02,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] wait_exp:0{{$}} +0x00,0x10,0x02,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] wait_exp:0{{$}} +0x00,0x20,0x02,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] wait_exp:0{{$}} +0x00,0x40,0x02,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] wait_exp:0{{$}} +0x00,0x78,0x02,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5{{$}} +0x00,0x4d,0x02,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} +0x00,0xcd,0x02,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} +0x00,0xcd,0x02,0xcd,0x01,0x05,0x0e,0xe4 + +# CHECK: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:0{{$}} +0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_f16_f32 v0, -v1, v2, v3 wait_exp:0{{$}} +0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x24 + +# CHECK: v_interp_p2_f16_f32 v0, v1, -v2, v3 wait_exp:0{{$}} +0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x44 + +# CHECK: v_interp_p2_f16_f32 v0, v1, v2, -v3 wait_exp:0{{$}} +0x00,0x00,0x03,0xcd,0x01,0x05,0x0e,0x84 + +# CHECK: v_interp_p2_f16_f32 v0, v1, v2, v3 clamp wait_exp:0{{$}} +0x00,0x80,0x03,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:1{{$}} +0x00,0x01,0x03,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_f16_f32 v0, v1, v2, v3 wait_exp:7{{$}} +0x00,0x07,0x03,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] wait_exp:0{{$}} +0x00,0x08,0x03,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] wait_exp:0{{$}} +0x00,0x10,0x03,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] wait_exp:0{{$}} +0x00,0x20,0x03,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] wait_exp:0{{$}} +0x00,0x40,0x03,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] wait_exp:0{{$}} +0x00,0x78,0x03,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5{{$}} +0x00,0x4d,0x03,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} +0x00,0xcd,0x03,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} +0x00,0xcd,0x03,0xcd,0x01,0x05,0x0e,0xe4 + +# CHECK: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0{{$}} +0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_rtz_f16_f32 v0, -v1, v2, v3 wait_exp:0{{$}} +0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x24 + +# CHECK: v_interp_p10_rtz_f16_f32 v0, v1, -v2, v3 wait_exp:0{{$}} +0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x44 + +# CHECK: v_interp_p10_rtz_f16_f32 v0, v1, v2, -v3 wait_exp:0{{$}} +0x00,0x00,0x04,0xcd,0x01,0x05,0x0e,0x84 + +# CHECK: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 clamp wait_exp:0{{$}} +0x00,0x80,0x04,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:1{{$}} +0x00,0x01,0x04,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 wait_exp:7{{$}} +0x00,0x07,0x04,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] wait_exp:0{{$}} +0x00,0x08,0x04,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] wait_exp:0{{$}} +0x00,0x10,0x04,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] wait_exp:0{{$}} +0x00,0x20,0x04,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] wait_exp:0{{$}} +0x00,0x40,0x04,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] wait_exp:0{{$}} +0x00,0x78,0x04,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5{{$}} +0x00,0x4d,0x04,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_rtz_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} +0x00,0xcd,0x04,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p10_rtz_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} +0x00,0xcd,0x04,0xcd,0x01,0x05,0x0e,0xe4 + +# CHECK: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:0{{$}} +0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_rtz_f16_f32 v0, -v1, v2, v3 wait_exp:0{{$}} +0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x24 + +# CHECK: v_interp_p2_rtz_f16_f32 v0, v1, -v2, v3 wait_exp:0{{$}} +0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x44 + +# CHECK: v_interp_p2_rtz_f16_f32 v0, v1, v2, -v3 wait_exp:0{{$}} +0x00,0x00,0x05,0xcd,0x01,0x05,0x0e,0x84 + +# CHECK: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 clamp wait_exp:0{{$}} +0x00,0x80,0x05,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:1{{$}} +0x00,0x01,0x05,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 wait_exp:7{{$}} +0x00,0x07,0x05,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,0] wait_exp:0{{$}} +0x00,0x08,0x05,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,1,0,0] wait_exp:0{{$}} +0x00,0x10,0x05,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,1,0] wait_exp:0{{$}} +0x00,0x20,0x05,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[0,0,0,1] wait_exp:0{{$}} +0x00,0x40,0x05,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,1,1,1] wait_exp:0{{$}} +0x00,0x78,0x05,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 op_sel:[1,0,0,1] wait_exp:5{{$}} +0x00,0x4d,0x05,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_rtz_f16_f32 v0, v1, v2, v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} +0x00,0xcd,0x05,0xcd,0x01,0x05,0x0e,0x04 + +# CHECK: v_interp_p2_rtz_f16_f32 v0, -v1, -v2, -v3 clamp op_sel:[1,0,0,1] wait_exp:5{{$}} +0x00,0xcd,0x05,0xcd,0x01,0x05,0x0e,0xe4 diff --git a/llvm/test/MC/Disassembler/X86/apx/cfcmov.txt b/llvm/test/MC/Disassembler/X86/apx/cfcmov.txt new file mode 100644 index 0000000000000000000000000000000000000000..4ecaa4b6a14a91c258a06a07aadb4e9b9608a83b --- /dev/null +++ b/llvm/test/MC/Disassembler/X86/apx/cfcmov.txt @@ -0,0 +1,842 @@ +# RUN: llvm-mc --disassemble %s -triple=x86_64 | FileCheck %s --check-prefixes=ATT +# RUN: llvm-mc --disassemble %s -triple=x86_64 -x86-asm-syntax=intel --output-asm-variant=1 | FileCheck %s --check-prefixes=INTEL + +# ATT: cfcmovbw %r17w, %r21w, %r25w +# INTEL: cfcmovb r25w, r21w, r17w +0x62,0xec,0x35,0x14,0x42,0xe9 + +# ATT: cfcmovbw %r17w, %r21w +# INTEL: cfcmovb r21w, r17w +0x62,0xec,0x7d,0x0c,0x42,0xcd + +# ATT: cfcmovbw %r17w, 291(%r28,%r29,4) +# INTEL: cfcmovb word ptr [r28 + 4*r29 + 291], r17w +0x62,0x8c,0x79,0x0c,0x42,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovbl %r18d, %r22d, %r26d +# INTEL: cfcmovb r26d, r22d, r18d +0x62,0xec,0x2c,0x14,0x42,0xf2 + +# ATT: cfcmovbl %r18d, %r22d +# INTEL: cfcmovb r22d, r18d +0x62,0xec,0x7c,0x0c,0x42,0xd6 + +# ATT: cfcmovbl %r18d, 291(%r28,%r29,4) +# INTEL: cfcmovb dword ptr [r28 + 4*r29 + 291], r18d +0x62,0x8c,0x78,0x0c,0x42,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovbq %r19, %r23, %r27 +# INTEL: cfcmovb r27, r23, r19 +0x62,0xec,0xa4,0x14,0x42,0xfb + +# ATT: cfcmovbq %r19, %r23 +# INTEL: cfcmovb r23, r19 +0x62,0xec,0xfc,0x0c,0x42,0xdf + +# ATT: cfcmovbq %r19, 291(%r28,%r29,4) +# INTEL: cfcmovb qword ptr [r28 + 4*r29 + 291], r19 +0x62,0x8c,0xf8,0x0c,0x42,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovbw 291(%r28,%r29,4), %r17w, %r21w +# INTEL: cfcmovb r21w, r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x51,0x14,0x42,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovbw 291(%r28,%r29,4), %r17w +# INTEL: cfcmovb r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x79,0x08,0x42,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovbl 291(%r28,%r29,4), %r18d, %r22d +# INTEL: cfcmovb r22d, r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x48,0x14,0x42,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovbl 291(%r28,%r29,4), %r18d +# INTEL: cfcmovb r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x78,0x08,0x42,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovbq 291(%r28,%r29,4), %r19, %r23 +# INTEL: cfcmovb r23, r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xc0,0x14,0x42,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovbq 291(%r28,%r29,4), %r19 +# INTEL: cfcmovb r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xf8,0x08,0x42,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovbew %r17w, %r21w, %r25w +# INTEL: cfcmovbe r25w, r21w, r17w +0x62,0xec,0x35,0x14,0x46,0xe9 + +# ATT: cfcmovbew %r17w, %r21w +# INTEL: cfcmovbe r21w, r17w +0x62,0xec,0x7d,0x0c,0x46,0xcd + +# ATT: cfcmovbew %r17w, 291(%r28,%r29,4) +# INTEL: cfcmovbe word ptr [r28 + 4*r29 + 291], r17w +0x62,0x8c,0x79,0x0c,0x46,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovbel %r18d, %r22d, %r26d +# INTEL: cfcmovbe r26d, r22d, r18d +0x62,0xec,0x2c,0x14,0x46,0xf2 + +# ATT: cfcmovbel %r18d, %r22d +# INTEL: cfcmovbe r22d, r18d +0x62,0xec,0x7c,0x0c,0x46,0xd6 + +# ATT: cfcmovbel %r18d, 291(%r28,%r29,4) +# INTEL: cfcmovbe dword ptr [r28 + 4*r29 + 291], r18d +0x62,0x8c,0x78,0x0c,0x46,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovbeq %r19, %r23, %r27 +# INTEL: cfcmovbe r27, r23, r19 +0x62,0xec,0xa4,0x14,0x46,0xfb + +# ATT: cfcmovbeq %r19, %r23 +# INTEL: cfcmovbe r23, r19 +0x62,0xec,0xfc,0x0c,0x46,0xdf + +# ATT: cfcmovbeq %r19, 291(%r28,%r29,4) +# INTEL: cfcmovbe qword ptr [r28 + 4*r29 + 291], r19 +0x62,0x8c,0xf8,0x0c,0x46,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovbew 291(%r28,%r29,4), %r17w, %r21w +# INTEL: cfcmovbe r21w, r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x51,0x14,0x46,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovbew 291(%r28,%r29,4), %r17w +# INTEL: cfcmovbe r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x79,0x08,0x46,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovbel 291(%r28,%r29,4), %r18d, %r22d +# INTEL: cfcmovbe r22d, r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x48,0x14,0x46,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovbel 291(%r28,%r29,4), %r18d +# INTEL: cfcmovbe r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x78,0x08,0x46,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovbeq 291(%r28,%r29,4), %r19, %r23 +# INTEL: cfcmovbe r23, r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xc0,0x14,0x46,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovbeq 291(%r28,%r29,4), %r19 +# INTEL: cfcmovbe r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xf8,0x08,0x46,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovlw %r17w, %r21w, %r25w +# INTEL: cfcmovl r25w, r21w, r17w +0x62,0xec,0x35,0x14,0x4c,0xe9 + +# ATT: cfcmovlw %r17w, %r21w +# INTEL: cfcmovl r21w, r17w +0x62,0xec,0x7d,0x0c,0x4c,0xcd + +# ATT: cfcmovlw %r17w, 291(%r28,%r29,4) +# INTEL: cfcmovl word ptr [r28 + 4*r29 + 291], r17w +0x62,0x8c,0x79,0x0c,0x4c,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovll %r18d, %r22d, %r26d +# INTEL: cfcmovl r26d, r22d, r18d +0x62,0xec,0x2c,0x14,0x4c,0xf2 + +# ATT: cfcmovll %r18d, %r22d +# INTEL: cfcmovl r22d, r18d +0x62,0xec,0x7c,0x0c,0x4c,0xd6 + +# ATT: cfcmovll %r18d, 291(%r28,%r29,4) +# INTEL: cfcmovl dword ptr [r28 + 4*r29 + 291], r18d +0x62,0x8c,0x78,0x0c,0x4c,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovlq %r19, %r23, %r27 +# INTEL: cfcmovl r27, r23, r19 +0x62,0xec,0xa4,0x14,0x4c,0xfb + +# ATT: cfcmovlq %r19, %r23 +# INTEL: cfcmovl r23, r19 +0x62,0xec,0xfc,0x0c,0x4c,0xdf + +# ATT: cfcmovlq %r19, 291(%r28,%r29,4) +# INTEL: cfcmovl qword ptr [r28 + 4*r29 + 291], r19 +0x62,0x8c,0xf8,0x0c,0x4c,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovlw 291(%r28,%r29,4), %r17w, %r21w +# INTEL: cfcmovl r21w, r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x51,0x14,0x4c,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovlw 291(%r28,%r29,4), %r17w +# INTEL: cfcmovl r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x79,0x08,0x4c,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovll 291(%r28,%r29,4), %r18d, %r22d +# INTEL: cfcmovl r22d, r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x48,0x14,0x4c,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovll 291(%r28,%r29,4), %r18d +# INTEL: cfcmovl r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x78,0x08,0x4c,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovlq 291(%r28,%r29,4), %r19, %r23 +# INTEL: cfcmovl r23, r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xc0,0x14,0x4c,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovlq 291(%r28,%r29,4), %r19 +# INTEL: cfcmovl r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xf8,0x08,0x4c,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovlew %r17w, %r21w, %r25w +# INTEL: cfcmovle r25w, r21w, r17w +0x62,0xec,0x35,0x14,0x4e,0xe9 + +# ATT: cfcmovlew %r17w, %r21w +# INTEL: cfcmovle r21w, r17w +0x62,0xec,0x7d,0x0c,0x4e,0xcd + +# ATT: cfcmovlew %r17w, 291(%r28,%r29,4) +# INTEL: cfcmovle word ptr [r28 + 4*r29 + 291], r17w +0x62,0x8c,0x79,0x0c,0x4e,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovlel %r18d, %r22d, %r26d +# INTEL: cfcmovle r26d, r22d, r18d +0x62,0xec,0x2c,0x14,0x4e,0xf2 + +# ATT: cfcmovlel %r18d, %r22d +# INTEL: cfcmovle r22d, r18d +0x62,0xec,0x7c,0x0c,0x4e,0xd6 + +# ATT: cfcmovlel %r18d, 291(%r28,%r29,4) +# INTEL: cfcmovle dword ptr [r28 + 4*r29 + 291], r18d +0x62,0x8c,0x78,0x0c,0x4e,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovleq %r19, %r23, %r27 +# INTEL: cfcmovle r27, r23, r19 +0x62,0xec,0xa4,0x14,0x4e,0xfb + +# ATT: cfcmovleq %r19, %r23 +# INTEL: cfcmovle r23, r19 +0x62,0xec,0xfc,0x0c,0x4e,0xdf + +# ATT: cfcmovleq %r19, 291(%r28,%r29,4) +# INTEL: cfcmovle qword ptr [r28 + 4*r29 + 291], r19 +0x62,0x8c,0xf8,0x0c,0x4e,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovlew 291(%r28,%r29,4), %r17w, %r21w +# INTEL: cfcmovle r21w, r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x51,0x14,0x4e,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovlew 291(%r28,%r29,4), %r17w +# INTEL: cfcmovle r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x79,0x08,0x4e,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovlel 291(%r28,%r29,4), %r18d, %r22d +# INTEL: cfcmovle r22d, r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x48,0x14,0x4e,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovlel 291(%r28,%r29,4), %r18d +# INTEL: cfcmovle r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x78,0x08,0x4e,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovleq 291(%r28,%r29,4), %r19, %r23 +# INTEL: cfcmovle r23, r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xc0,0x14,0x4e,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovleq 291(%r28,%r29,4), %r19 +# INTEL: cfcmovle r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xf8,0x08,0x4e,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovaew %r17w, %r21w, %r25w +# INTEL: cfcmovae r25w, r21w, r17w +0x62,0xec,0x35,0x14,0x43,0xe9 + +# ATT: cfcmovaew %r17w, %r21w +# INTEL: cfcmovae r21w, r17w +0x62,0xec,0x7d,0x0c,0x43,0xcd + +# ATT: cfcmovaew %r17w, 291(%r28,%r29,4) +# INTEL: cfcmovae word ptr [r28 + 4*r29 + 291], r17w +0x62,0x8c,0x79,0x0c,0x43,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovael %r18d, %r22d, %r26d +# INTEL: cfcmovae r26d, r22d, r18d +0x62,0xec,0x2c,0x14,0x43,0xf2 + +# ATT: cfcmovael %r18d, %r22d +# INTEL: cfcmovae r22d, r18d +0x62,0xec,0x7c,0x0c,0x43,0xd6 + +# ATT: cfcmovael %r18d, 291(%r28,%r29,4) +# INTEL: cfcmovae dword ptr [r28 + 4*r29 + 291], r18d +0x62,0x8c,0x78,0x0c,0x43,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovaeq %r19, %r23, %r27 +# INTEL: cfcmovae r27, r23, r19 +0x62,0xec,0xa4,0x14,0x43,0xfb + +# ATT: cfcmovaeq %r19, %r23 +# INTEL: cfcmovae r23, r19 +0x62,0xec,0xfc,0x0c,0x43,0xdf + +# ATT: cfcmovaeq %r19, 291(%r28,%r29,4) +# INTEL: cfcmovae qword ptr [r28 + 4*r29 + 291], r19 +0x62,0x8c,0xf8,0x0c,0x43,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovaew 291(%r28,%r29,4), %r17w, %r21w +# INTEL: cfcmovae r21w, r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x51,0x14,0x43,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovaew 291(%r28,%r29,4), %r17w +# INTEL: cfcmovae r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x79,0x08,0x43,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovael 291(%r28,%r29,4), %r18d, %r22d +# INTEL: cfcmovae r22d, r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x48,0x14,0x43,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovael 291(%r28,%r29,4), %r18d +# INTEL: cfcmovae r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x78,0x08,0x43,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovaeq 291(%r28,%r29,4), %r19, %r23 +# INTEL: cfcmovae r23, r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xc0,0x14,0x43,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovaeq 291(%r28,%r29,4), %r19 +# INTEL: cfcmovae r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xf8,0x08,0x43,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovaw %r17w, %r21w, %r25w +# INTEL: cfcmova r25w, r21w, r17w +0x62,0xec,0x35,0x14,0x47,0xe9 + +# ATT: cfcmovaw %r17w, %r21w +# INTEL: cfcmova r21w, r17w +0x62,0xec,0x7d,0x0c,0x47,0xcd + +# ATT: cfcmovaw %r17w, 291(%r28,%r29,4) +# INTEL: cfcmova word ptr [r28 + 4*r29 + 291], r17w +0x62,0x8c,0x79,0x0c,0x47,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmoval %r18d, %r22d, %r26d +# INTEL: cfcmova r26d, r22d, r18d +0x62,0xec,0x2c,0x14,0x47,0xf2 + +# ATT: cfcmoval %r18d, %r22d +# INTEL: cfcmova r22d, r18d +0x62,0xec,0x7c,0x0c,0x47,0xd6 + +# ATT: cfcmoval %r18d, 291(%r28,%r29,4) +# INTEL: cfcmova dword ptr [r28 + 4*r29 + 291], r18d +0x62,0x8c,0x78,0x0c,0x47,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovaq %r19, %r23, %r27 +# INTEL: cfcmova r27, r23, r19 +0x62,0xec,0xa4,0x14,0x47,0xfb + +# ATT: cfcmovaq %r19, %r23 +# INTEL: cfcmova r23, r19 +0x62,0xec,0xfc,0x0c,0x47,0xdf + +# ATT: cfcmovaq %r19, 291(%r28,%r29,4) +# INTEL: cfcmova qword ptr [r28 + 4*r29 + 291], r19 +0x62,0x8c,0xf8,0x0c,0x47,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovaw 291(%r28,%r29,4), %r17w, %r21w +# INTEL: cfcmova r21w, r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x51,0x14,0x47,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovaw 291(%r28,%r29,4), %r17w +# INTEL: cfcmova r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x79,0x08,0x47,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmoval 291(%r28,%r29,4), %r18d, %r22d +# INTEL: cfcmova r22d, r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x48,0x14,0x47,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmoval 291(%r28,%r29,4), %r18d +# INTEL: cfcmova r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x78,0x08,0x47,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovaq 291(%r28,%r29,4), %r19, %r23 +# INTEL: cfcmova r23, r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xc0,0x14,0x47,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovaq 291(%r28,%r29,4), %r19 +# INTEL: cfcmova r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xf8,0x08,0x47,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovgew %r17w, %r21w, %r25w +# INTEL: cfcmovge r25w, r21w, r17w +0x62,0xec,0x35,0x14,0x4d,0xe9 + +# ATT: cfcmovgew %r17w, %r21w +# INTEL: cfcmovge r21w, r17w +0x62,0xec,0x7d,0x0c,0x4d,0xcd + +# ATT: cfcmovgew %r17w, 291(%r28,%r29,4) +# INTEL: cfcmovge word ptr [r28 + 4*r29 + 291], r17w +0x62,0x8c,0x79,0x0c,0x4d,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovgel %r18d, %r22d, %r26d +# INTEL: cfcmovge r26d, r22d, r18d +0x62,0xec,0x2c,0x14,0x4d,0xf2 + +# ATT: cfcmovgel %r18d, %r22d +# INTEL: cfcmovge r22d, r18d +0x62,0xec,0x7c,0x0c,0x4d,0xd6 + +# ATT: cfcmovgel %r18d, 291(%r28,%r29,4) +# INTEL: cfcmovge dword ptr [r28 + 4*r29 + 291], r18d +0x62,0x8c,0x78,0x0c,0x4d,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovgeq %r19, %r23, %r27 +# INTEL: cfcmovge r27, r23, r19 +0x62,0xec,0xa4,0x14,0x4d,0xfb + +# ATT: cfcmovgeq %r19, %r23 +# INTEL: cfcmovge r23, r19 +0x62,0xec,0xfc,0x0c,0x4d,0xdf + +# ATT: cfcmovgeq %r19, 291(%r28,%r29,4) +# INTEL: cfcmovge qword ptr [r28 + 4*r29 + 291], r19 +0x62,0x8c,0xf8,0x0c,0x4d,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovgew 291(%r28,%r29,4), %r17w, %r21w +# INTEL: cfcmovge r21w, r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x51,0x14,0x4d,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovgew 291(%r28,%r29,4), %r17w +# INTEL: cfcmovge r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x79,0x08,0x4d,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovgel 291(%r28,%r29,4), %r18d, %r22d +# INTEL: cfcmovge r22d, r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x48,0x14,0x4d,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovgel 291(%r28,%r29,4), %r18d +# INTEL: cfcmovge r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x78,0x08,0x4d,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovgeq 291(%r28,%r29,4), %r19, %r23 +# INTEL: cfcmovge r23, r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xc0,0x14,0x4d,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovgeq 291(%r28,%r29,4), %r19 +# INTEL: cfcmovge r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xf8,0x08,0x4d,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnow %r17w, %r21w, %r25w +# INTEL: cfcmovno r25w, r21w, r17w +0x62,0xec,0x35,0x14,0x41,0xe9 + +# ATT: cfcmovnow %r17w, %r21w +# INTEL: cfcmovno r21w, r17w +0x62,0xec,0x7d,0x0c,0x41,0xcd + +# ATT: cfcmovnow %r17w, 291(%r28,%r29,4) +# INTEL: cfcmovno word ptr [r28 + 4*r29 + 291], r17w +0x62,0x8c,0x79,0x0c,0x41,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnol %r18d, %r22d, %r26d +# INTEL: cfcmovno r26d, r22d, r18d +0x62,0xec,0x2c,0x14,0x41,0xf2 + +# ATT: cfcmovnol %r18d, %r22d +# INTEL: cfcmovno r22d, r18d +0x62,0xec,0x7c,0x0c,0x41,0xd6 + +# ATT: cfcmovnol %r18d, 291(%r28,%r29,4) +# INTEL: cfcmovno dword ptr [r28 + 4*r29 + 291], r18d +0x62,0x8c,0x78,0x0c,0x41,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnoq %r19, %r23, %r27 +# INTEL: cfcmovno r27, r23, r19 +0x62,0xec,0xa4,0x14,0x41,0xfb + +# ATT: cfcmovnoq %r19, %r23 +# INTEL: cfcmovno r23, r19 +0x62,0xec,0xfc,0x0c,0x41,0xdf + +# ATT: cfcmovnoq %r19, 291(%r28,%r29,4) +# INTEL: cfcmovno qword ptr [r28 + 4*r29 + 291], r19 +0x62,0x8c,0xf8,0x0c,0x41,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnow 291(%r28,%r29,4), %r17w, %r21w +# INTEL: cfcmovno r21w, r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x51,0x14,0x41,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnow 291(%r28,%r29,4), %r17w +# INTEL: cfcmovno r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x79,0x08,0x41,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnol 291(%r28,%r29,4), %r18d, %r22d +# INTEL: cfcmovno r22d, r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x48,0x14,0x41,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnol 291(%r28,%r29,4), %r18d +# INTEL: cfcmovno r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x78,0x08,0x41,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnoq 291(%r28,%r29,4), %r19, %r23 +# INTEL: cfcmovno r23, r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xc0,0x14,0x41,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnoq 291(%r28,%r29,4), %r19 +# INTEL: cfcmovno r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xf8,0x08,0x41,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnpw %r17w, %r21w, %r25w +# INTEL: cfcmovnp r25w, r21w, r17w +0x62,0xec,0x35,0x14,0x4b,0xe9 + +# ATT: cfcmovnpw %r17w, %r21w +# INTEL: cfcmovnp r21w, r17w +0x62,0xec,0x7d,0x0c,0x4b,0xcd + +# ATT: cfcmovnpw %r17w, 291(%r28,%r29,4) +# INTEL: cfcmovnp word ptr [r28 + 4*r29 + 291], r17w +0x62,0x8c,0x79,0x0c,0x4b,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnpl %r18d, %r22d, %r26d +# INTEL: cfcmovnp r26d, r22d, r18d +0x62,0xec,0x2c,0x14,0x4b,0xf2 + +# ATT: cfcmovnpl %r18d, %r22d +# INTEL: cfcmovnp r22d, r18d +0x62,0xec,0x7c,0x0c,0x4b,0xd6 + +# ATT: cfcmovnpl %r18d, 291(%r28,%r29,4) +# INTEL: cfcmovnp dword ptr [r28 + 4*r29 + 291], r18d +0x62,0x8c,0x78,0x0c,0x4b,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnpq %r19, %r23, %r27 +# INTEL: cfcmovnp r27, r23, r19 +0x62,0xec,0xa4,0x14,0x4b,0xfb + +# ATT: cfcmovnpq %r19, %r23 +# INTEL: cfcmovnp r23, r19 +0x62,0xec,0xfc,0x0c,0x4b,0xdf + +# ATT: cfcmovnpq %r19, 291(%r28,%r29,4) +# INTEL: cfcmovnp qword ptr [r28 + 4*r29 + 291], r19 +0x62,0x8c,0xf8,0x0c,0x4b,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnpw 291(%r28,%r29,4), %r17w, %r21w +# INTEL: cfcmovnp r21w, r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x51,0x14,0x4b,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnpw 291(%r28,%r29,4), %r17w +# INTEL: cfcmovnp r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x79,0x08,0x4b,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnpl 291(%r28,%r29,4), %r18d, %r22d +# INTEL: cfcmovnp r22d, r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x48,0x14,0x4b,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnpl 291(%r28,%r29,4), %r18d +# INTEL: cfcmovnp r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x78,0x08,0x4b,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnpq 291(%r28,%r29,4), %r19, %r23 +# INTEL: cfcmovnp r23, r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xc0,0x14,0x4b,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnpq 291(%r28,%r29,4), %r19 +# INTEL: cfcmovnp r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xf8,0x08,0x4b,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnsw %r17w, %r21w, %r25w +# INTEL: cfcmovns r25w, r21w, r17w +0x62,0xec,0x35,0x14,0x49,0xe9 + +# ATT: cfcmovnsw %r17w, %r21w +# INTEL: cfcmovns r21w, r17w +0x62,0xec,0x7d,0x0c,0x49,0xcd + +# ATT: cfcmovnsw %r17w, 291(%r28,%r29,4) +# INTEL: cfcmovns word ptr [r28 + 4*r29 + 291], r17w +0x62,0x8c,0x79,0x0c,0x49,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnsl %r18d, %r22d, %r26d +# INTEL: cfcmovns r26d, r22d, r18d +0x62,0xec,0x2c,0x14,0x49,0xf2 + +# ATT: cfcmovnsl %r18d, %r22d +# INTEL: cfcmovns r22d, r18d +0x62,0xec,0x7c,0x0c,0x49,0xd6 + +# ATT: cfcmovnsl %r18d, 291(%r28,%r29,4) +# INTEL: cfcmovns dword ptr [r28 + 4*r29 + 291], r18d +0x62,0x8c,0x78,0x0c,0x49,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnsq %r19, %r23, %r27 +# INTEL: cfcmovns r27, r23, r19 +0x62,0xec,0xa4,0x14,0x49,0xfb + +# ATT: cfcmovnsq %r19, %r23 +# INTEL: cfcmovns r23, r19 +0x62,0xec,0xfc,0x0c,0x49,0xdf + +# ATT: cfcmovnsq %r19, 291(%r28,%r29,4) +# INTEL: cfcmovns qword ptr [r28 + 4*r29 + 291], r19 +0x62,0x8c,0xf8,0x0c,0x49,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnsw 291(%r28,%r29,4), %r17w, %r21w +# INTEL: cfcmovns r21w, r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x51,0x14,0x49,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnsw 291(%r28,%r29,4), %r17w +# INTEL: cfcmovns r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x79,0x08,0x49,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnsl 291(%r28,%r29,4), %r18d, %r22d +# INTEL: cfcmovns r22d, r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x48,0x14,0x49,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnsl 291(%r28,%r29,4), %r18d +# INTEL: cfcmovns r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x78,0x08,0x49,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnsq 291(%r28,%r29,4), %r19, %r23 +# INTEL: cfcmovns r23, r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xc0,0x14,0x49,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnsq 291(%r28,%r29,4), %r19 +# INTEL: cfcmovns r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xf8,0x08,0x49,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnew %r17w, %r21w, %r25w +# INTEL: cfcmovne r25w, r21w, r17w +0x62,0xec,0x35,0x14,0x45,0xe9 + +# ATT: cfcmovnew %r17w, %r21w +# INTEL: cfcmovne r21w, r17w +0x62,0xec,0x7d,0x0c,0x45,0xcd + +# ATT: cfcmovnew %r17w, 291(%r28,%r29,4) +# INTEL: cfcmovne word ptr [r28 + 4*r29 + 291], r17w +0x62,0x8c,0x79,0x0c,0x45,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnel %r18d, %r22d, %r26d +# INTEL: cfcmovne r26d, r22d, r18d +0x62,0xec,0x2c,0x14,0x45,0xf2 + +# ATT: cfcmovnel %r18d, %r22d +# INTEL: cfcmovne r22d, r18d +0x62,0xec,0x7c,0x0c,0x45,0xd6 + +# ATT: cfcmovnel %r18d, 291(%r28,%r29,4) +# INTEL: cfcmovne dword ptr [r28 + 4*r29 + 291], r18d +0x62,0x8c,0x78,0x0c,0x45,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovneq %r19, %r23, %r27 +# INTEL: cfcmovne r27, r23, r19 +0x62,0xec,0xa4,0x14,0x45,0xfb + +# ATT: cfcmovneq %r19, %r23 +# INTEL: cfcmovne r23, r19 +0x62,0xec,0xfc,0x0c,0x45,0xdf + +# ATT: cfcmovneq %r19, 291(%r28,%r29,4) +# INTEL: cfcmovne qword ptr [r28 + 4*r29 + 291], r19 +0x62,0x8c,0xf8,0x0c,0x45,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnew 291(%r28,%r29,4), %r17w, %r21w +# INTEL: cfcmovne r21w, r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x51,0x14,0x45,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnew 291(%r28,%r29,4), %r17w +# INTEL: cfcmovne r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x79,0x08,0x45,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnel 291(%r28,%r29,4), %r18d, %r22d +# INTEL: cfcmovne r22d, r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x48,0x14,0x45,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovnel 291(%r28,%r29,4), %r18d +# INTEL: cfcmovne r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x78,0x08,0x45,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovneq 291(%r28,%r29,4), %r19, %r23 +# INTEL: cfcmovne r23, r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xc0,0x14,0x45,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovneq 291(%r28,%r29,4), %r19 +# INTEL: cfcmovne r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xf8,0x08,0x45,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovpw %r17w, %r21w, %r25w +# INTEL: cfcmovp r25w, r21w, r17w +0x62,0xec,0x35,0x14,0x4a,0xe9 + +# ATT: cfcmovpw %r17w, %r21w +# INTEL: cfcmovp r21w, r17w +0x62,0xec,0x7d,0x0c,0x4a,0xcd + +# ATT: cfcmovpw %r17w, 291(%r28,%r29,4) +# INTEL: cfcmovp word ptr [r28 + 4*r29 + 291], r17w +0x62,0x8c,0x79,0x0c,0x4a,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovpl %r18d, %r22d, %r26d +# INTEL: cfcmovp r26d, r22d, r18d +0x62,0xec,0x2c,0x14,0x4a,0xf2 + +# ATT: cfcmovpl %r18d, %r22d +# INTEL: cfcmovp r22d, r18d +0x62,0xec,0x7c,0x0c,0x4a,0xd6 + +# ATT: cfcmovpl %r18d, 291(%r28,%r29,4) +# INTEL: cfcmovp dword ptr [r28 + 4*r29 + 291], r18d +0x62,0x8c,0x78,0x0c,0x4a,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovpq %r19, %r23, %r27 +# INTEL: cfcmovp r27, r23, r19 +0x62,0xec,0xa4,0x14,0x4a,0xfb + +# ATT: cfcmovpq %r19, %r23 +# INTEL: cfcmovp r23, r19 +0x62,0xec,0xfc,0x0c,0x4a,0xdf + +# ATT: cfcmovpq %r19, 291(%r28,%r29,4) +# INTEL: cfcmovp qword ptr [r28 + 4*r29 + 291], r19 +0x62,0x8c,0xf8,0x0c,0x4a,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovpw 291(%r28,%r29,4), %r17w, %r21w +# INTEL: cfcmovp r21w, r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x51,0x14,0x4a,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovpw 291(%r28,%r29,4), %r17w +# INTEL: cfcmovp r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x79,0x08,0x4a,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovpl 291(%r28,%r29,4), %r18d, %r22d +# INTEL: cfcmovp r22d, r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x48,0x14,0x4a,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovpl 291(%r28,%r29,4), %r18d +# INTEL: cfcmovp r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x78,0x08,0x4a,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovpq 291(%r28,%r29,4), %r19, %r23 +# INTEL: cfcmovp r23, r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xc0,0x14,0x4a,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovpq 291(%r28,%r29,4), %r19 +# INTEL: cfcmovp r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xf8,0x08,0x4a,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovsw %r17w, %r21w, %r25w +# INTEL: cfcmovs r25w, r21w, r17w +0x62,0xec,0x35,0x14,0x48,0xe9 + +# ATT: cfcmovsw %r17w, %r21w +# INTEL: cfcmovs r21w, r17w +0x62,0xec,0x7d,0x0c,0x48,0xcd + +# ATT: cfcmovsw %r17w, 291(%r28,%r29,4) +# INTEL: cfcmovs word ptr [r28 + 4*r29 + 291], r17w +0x62,0x8c,0x79,0x0c,0x48,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovsl %r18d, %r22d, %r26d +# INTEL: cfcmovs r26d, r22d, r18d +0x62,0xec,0x2c,0x14,0x48,0xf2 + +# ATT: cfcmovsl %r18d, %r22d +# INTEL: cfcmovs r22d, r18d +0x62,0xec,0x7c,0x0c,0x48,0xd6 + +# ATT: cfcmovsl %r18d, 291(%r28,%r29,4) +# INTEL: cfcmovs dword ptr [r28 + 4*r29 + 291], r18d +0x62,0x8c,0x78,0x0c,0x48,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovsq %r19, %r23, %r27 +# INTEL: cfcmovs r27, r23, r19 +0x62,0xec,0xa4,0x14,0x48,0xfb + +# ATT: cfcmovsq %r19, %r23 +# INTEL: cfcmovs r23, r19 +0x62,0xec,0xfc,0x0c,0x48,0xdf + +# ATT: cfcmovsq %r19, 291(%r28,%r29,4) +# INTEL: cfcmovs qword ptr [r28 + 4*r29 + 291], r19 +0x62,0x8c,0xf8,0x0c,0x48,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovsw 291(%r28,%r29,4), %r17w, %r21w +# INTEL: cfcmovs r21w, r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x51,0x14,0x48,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovsw 291(%r28,%r29,4), %r17w +# INTEL: cfcmovs r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x79,0x08,0x48,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovsl 291(%r28,%r29,4), %r18d, %r22d +# INTEL: cfcmovs r22d, r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x48,0x14,0x48,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovsl 291(%r28,%r29,4), %r18d +# INTEL: cfcmovs r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x78,0x08,0x48,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovsq 291(%r28,%r29,4), %r19, %r23 +# INTEL: cfcmovs r23, r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xc0,0x14,0x48,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovsq 291(%r28,%r29,4), %r19 +# INTEL: cfcmovs r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xf8,0x08,0x48,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovew %r17w, %r21w, %r25w +# INTEL: cfcmove r25w, r21w, r17w +0x62,0xec,0x35,0x14,0x44,0xe9 + +# ATT: cfcmovew %r17w, %r21w +# INTEL: cfcmove r21w, r17w +0x62,0xec,0x7d,0x0c,0x44,0xcd + +# ATT: cfcmovew %r17w, 291(%r28,%r29,4) +# INTEL: cfcmove word ptr [r28 + 4*r29 + 291], r17w +0x62,0x8c,0x79,0x0c,0x44,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovel %r18d, %r22d, %r26d +# INTEL: cfcmove r26d, r22d, r18d +0x62,0xec,0x2c,0x14,0x44,0xf2 + +# ATT: cfcmovel %r18d, %r22d +# INTEL: cfcmove r22d, r18d +0x62,0xec,0x7c,0x0c,0x44,0xd6 + +# ATT: cfcmovel %r18d, 291(%r28,%r29,4) +# INTEL: cfcmove dword ptr [r28 + 4*r29 + 291], r18d +0x62,0x8c,0x78,0x0c,0x44,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmoveq %r19, %r23, %r27 +# INTEL: cfcmove r27, r23, r19 +0x62,0xec,0xa4,0x14,0x44,0xfb + +# ATT: cfcmoveq %r19, %r23 +# INTEL: cfcmove r23, r19 +0x62,0xec,0xfc,0x0c,0x44,0xdf + +# ATT: cfcmoveq %r19, 291(%r28,%r29,4) +# INTEL: cfcmove qword ptr [r28 + 4*r29 + 291], r19 +0x62,0x8c,0xf8,0x0c,0x44,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovew 291(%r28,%r29,4), %r17w, %r21w +# INTEL: cfcmove r21w, r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x51,0x14,0x44,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovew 291(%r28,%r29,4), %r17w +# INTEL: cfcmove r17w, word ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x79,0x08,0x44,0x8c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovel 291(%r28,%r29,4), %r18d, %r22d +# INTEL: cfcmove r22d, r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x48,0x14,0x44,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmovel 291(%r28,%r29,4), %r18d +# INTEL: cfcmove r18d, dword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0x78,0x08,0x44,0x94,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmoveq 291(%r28,%r29,4), %r19, %r23 +# INTEL: cfcmove r23, r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xc0,0x14,0x44,0x9c,0xac,0x23,0x01,0x00,0x00 + +# ATT: cfcmoveq 291(%r28,%r29,4), %r19 +# INTEL: cfcmove r19, qword ptr [r28 + 4*r29 + 291] +0x62,0x8c,0xf8,0x08,0x44,0x9c,0xac,0x23,0x01,0x00,0x00 diff --git a/llvm/test/MC/Disassembler/X86/apx/cmov.txt b/llvm/test/MC/Disassembler/X86/apx/cmov.txt new file mode 100644 index 0000000000000000000000000000000000000000..cc96fb17e0085e212a7b2d46a204a04df7abd262 --- /dev/null +++ b/llvm/test/MC/Disassembler/X86/apx/cmov.txt @@ -0,0 +1,386 @@ +# RUN: llvm-mc -triple x86_64 -disassemble %s | FileCheck %s --check-prefix=ATT +# RUN: llvm-mc -triple x86_64 -disassemble -output-asm-variant=1 %s | FileCheck %s --check-prefix=INTEL + +# ATT: cmovbw %dx, %ax, %r9w +# INTEL: cmovb r9w, ax, dx +0x62,0xf4,0x35,0x18,0x42,0xc2 + +# ATT: cmovbl %ecx, %edx, %r10d +# INTEL: cmovb r10d, edx, ecx +0x62,0xf4,0x2c,0x18,0x42,0xd1 + +# ATT: cmovbq %r9, %r15, %r11 +# INTEL: cmovb r11, r15, r9 +0x62,0x54,0xa4,0x18,0x42,0xf9 + +# ATT: cmovbw 123(%r8,%rax,4), %dx, %ax +# INTEL: cmovb ax, dx, word ptr [r8 + 4*rax + 123] +0x62,0xd4,0x7d,0x18,0x42,0x54,0x80,0x7b + +# ATT: cmovbl 123(%r8,%rax,4), %ecx, %edx +# INTEL: cmovb edx, ecx, dword ptr [r8 + 4*rax + 123] +0x62,0xd4,0x6c,0x18,0x42,0x4c,0x80,0x7b + +# ATT: cmovbq 123(%r8,%rax,4), %r9, %r15 +# INTEL: cmovb r15, r9, qword ptr [r8 + 4*rax + 123] +0x62,0x54,0x84,0x18,0x42,0x4c,0x80,0x7b + +# ATT: cmovbew %dx, %ax, %r9w +# INTEL: cmovbe r9w, ax, dx +0x62,0xf4,0x35,0x18,0x46,0xc2 + +# ATT: cmovbel %ecx, %edx, %r10d +# INTEL: cmovbe r10d, edx, ecx +0x62,0xf4,0x2c,0x18,0x46,0xd1 + +# ATT: cmovbeq %r9, %r15, %r11 +# INTEL: cmovbe r11, r15, r9 +0x62,0x54,0xa4,0x18,0x46,0xf9 + +# ATT: cmovbew 123(%r8,%rax,4), %dx, %ax +# INTEL: cmovbe ax, dx, word ptr [r8 + 4*rax + 123] +0x62,0xd4,0x7d,0x18,0x46,0x54,0x80,0x7b + +# ATT: cmovbel 123(%r8,%rax,4), %ecx, %edx +# INTEL: cmovbe edx, ecx, dword ptr [r8 + 4*rax + 123] +0x62,0xd4,0x6c,0x18,0x46,0x4c,0x80,0x7b + +# ATT: cmovbeq 123(%r8,%rax,4), %r9, %r15 +# INTEL: cmovbe r15, r9, qword ptr [r8 + 4*rax + 123] +0x62,0x54,0x84,0x18,0x46,0x4c,0x80,0x7b + +# ATT: cmovlw %dx, %ax, %r9w +# INTEL: cmovl r9w, ax, dx +0x62,0xf4,0x35,0x18,0x4c,0xc2 + +# ATT: cmovll %ecx, %edx, %r10d +# INTEL: cmovl r10d, edx, ecx +0x62,0xf4,0x2c,0x18,0x4c,0xd1 + +# ATT: cmovlq %r9, %r15, %r11 +# INTEL: cmovl r11, r15, r9 +0x62,0x54,0xa4,0x18,0x4c,0xf9 + +# ATT: cmovlw 123(%r8,%rax,4), %dx, %ax +# INTEL: cmovl ax, dx, word ptr [r8 + 4*rax + 123] +0x62,0xd4,0x7d,0x18,0x4c,0x54,0x80,0x7b + +# ATT: cmovll 123(%r8,%rax,4), %ecx, %edx +# INTEL: cmovl edx, ecx, dword ptr [r8 + 4*rax + 123] +0x62,0xd4,0x6c,0x18,0x4c,0x4c,0x80,0x7b + +# ATT: cmovlq 123(%r8,%rax,4), %r9, %r15 +# INTEL: cmovl r15, r9, qword ptr [r8 + 4*rax + 123] +0x62,0x54,0x84,0x18,0x4c,0x4c,0x80,0x7b + +# ATT: cmovlew %dx, %ax, %r9w +# INTEL: cmovle r9w, ax, dx +0x62,0xf4,0x35,0x18,0x4e,0xc2 + +# ATT: cmovlel %ecx, %edx, %r10d +# INTEL: cmovle r10d, edx, ecx +0x62,0xf4,0x2c,0x18,0x4e,0xd1 + +# ATT: cmovleq %r9, %r15, %r11 +# INTEL: cmovle r11, r15, r9 +0x62,0x54,0xa4,0x18,0x4e,0xf9 + +# ATT: cmovlew 123(%r8,%rax,4), %dx, %ax +# INTEL: cmovle ax, dx, word ptr [r8 + 4*rax + 123] +0x62,0xd4,0x7d,0x18,0x4e,0x54,0x80,0x7b + +# ATT: cmovlel 123(%r8,%rax,4), %ecx, %edx +# INTEL: cmovle edx, ecx, dword ptr [r8 + 4*rax + 123] +0x62,0xd4,0x6c,0x18,0x4e,0x4c,0x80,0x7b + +# ATT: cmovleq 123(%r8,%rax,4), %r9, %r15 +# INTEL: cmovle r15, r9, qword ptr [r8 + 4*rax + 123] +0x62,0x54,0x84,0x18,0x4e,0x4c,0x80,0x7b + +# ATT: cmovaew %dx, %ax, %r9w +# INTEL: cmovae r9w, ax, dx +0x62,0xf4,0x35,0x18,0x43,0xc2 + +# ATT: cmovael %ecx, %edx, %r10d +# INTEL: cmovae r10d, edx, ecx +0x62,0xf4,0x2c,0x18,0x43,0xd1 + +# ATT: cmovaeq %r9, %r15, %r11 +# INTEL: cmovae r11, r15, r9 +0x62,0x54,0xa4,0x18,0x43,0xf9 + +# ATT: cmovaew 123(%r8,%rax,4), %dx, %ax +# INTEL: cmovae ax, dx, word ptr [r8 + 4*rax + 123] +0x62,0xd4,0x7d,0x18,0x43,0x54,0x80,0x7b + +# ATT: cmovael 123(%r8,%rax,4), %ecx, %edx +# INTEL: cmovae edx, ecx, dword ptr [r8 + 4*rax + 123] +0x62,0xd4,0x6c,0x18,0x43,0x4c,0x80,0x7b + +# ATT: cmovaeq 123(%r8,%rax,4), %r9, %r15 +# INTEL: cmovae r15, r9, qword ptr [r8 + 4*rax + 123] +0x62,0x54,0x84,0x18,0x43,0x4c,0x80,0x7b + +# ATT: cmovaw %dx, %ax, %r9w +# INTEL: cmova r9w, ax, dx +0x62,0xf4,0x35,0x18,0x47,0xc2 + +# ATT: cmoval %ecx, %edx, %r10d +# INTEL: cmova r10d, edx, ecx +0x62,0xf4,0x2c,0x18,0x47,0xd1 + +# ATT: cmovaq %r9, %r15, %r11 +# INTEL: cmova r11, r15, r9 +0x62,0x54,0xa4,0x18,0x47,0xf9 + +# ATT: cmovaw 123(%r8,%rax,4), %dx, %ax +# INTEL: cmova ax, dx, word ptr [r8 + 4*rax + 123] +0x62,0xd4,0x7d,0x18,0x47,0x54,0x80,0x7b + +# ATT: cmoval 123(%r8,%rax,4), %ecx, %edx +# INTEL: cmova edx, ecx, dword ptr [r8 + 4*rax + 123] +0x62,0xd4,0x6c,0x18,0x47,0x4c,0x80,0x7b + +# ATT: cmovaq 123(%r8,%rax,4), %r9, %r15 +# INTEL: cmova r15, r9, qword ptr [r8 + 4*rax + 123] +0x62,0x54,0x84,0x18,0x47,0x4c,0x80,0x7b + +# ATT: cmovgew %dx, %ax, %r9w +# INTEL: cmovge r9w, ax, dx +0x62,0xf4,0x35,0x18,0x4d,0xc2 + +# ATT: cmovgel %ecx, %edx, %r10d +# INTEL: cmovge r10d, edx, ecx +0x62,0xf4,0x2c,0x18,0x4d,0xd1 + +# ATT: cmovgeq %r9, %r15, %r11 +# INTEL: cmovge r11, r15, r9 +0x62,0x54,0xa4,0x18,0x4d,0xf9 + +# ATT: cmovgew 123(%r8,%rax,4), %dx, %ax +# INTEL: cmovge ax, dx, word ptr [r8 + 4*rax + 123] +0x62,0xd4,0x7d,0x18,0x4d,0x54,0x80,0x7b + +# ATT: cmovgel 123(%r8,%rax,4), %ecx, %edx +# INTEL: cmovge edx, ecx, dword ptr [r8 + 4*rax + 123] +0x62,0xd4,0x6c,0x18,0x4d,0x4c,0x80,0x7b + +# ATT: cmovgeq 123(%r8,%rax,4), %r9, %r15 +# INTEL: cmovge r15, r9, qword ptr [r8 + 4*rax + 123] +0x62,0x54,0x84,0x18,0x4d,0x4c,0x80,0x7b + +# ATT: cmovgw %dx, %ax, %r9w +# INTEL: cmovg r9w, ax, dx +0x62,0xf4,0x35,0x18,0x4f,0xc2 + +# ATT: cmovgl %ecx, %edx, %r10d +# INTEL: cmovg r10d, edx, ecx +0x62,0xf4,0x2c,0x18,0x4f,0xd1 + +# ATT: cmovgq %r9, %r15, %r11 +# INTEL: cmovg r11, r15, r9 +0x62,0x54,0xa4,0x18,0x4f,0xf9 + +# ATT: cmovgw 123(%r8,%rax,4), %dx, %ax +# INTEL: cmovg ax, dx, word ptr [r8 + 4*rax + 123] +0x62,0xd4,0x7d,0x18,0x4f,0x54,0x80,0x7b + +# ATT: cmovgl 123(%r8,%rax,4), %ecx, %edx +# INTEL: cmovg edx, ecx, dword ptr [r8 + 4*rax + 123] +0x62,0xd4,0x6c,0x18,0x4f,0x4c,0x80,0x7b + +# ATT: cmovgq 123(%r8,%rax,4), %r9, %r15 +# INTEL: cmovg r15, r9, qword ptr [r8 + 4*rax + 123] +0x62,0x54,0x84,0x18,0x4f,0x4c,0x80,0x7b + +# ATT: cmovnow %dx, %ax, %r9w +# INTEL: cmovno r9w, ax, dx +0x62,0xf4,0x35,0x18,0x41,0xc2 + +# ATT: cmovnol %ecx, %edx, %r10d +# INTEL: cmovno r10d, edx, ecx +0x62,0xf4,0x2c,0x18,0x41,0xd1 + +# ATT: cmovnoq %r9, %r15, %r11 +# INTEL: cmovno r11, r15, r9 +0x62,0x54,0xa4,0x18,0x41,0xf9 + +# ATT: cmovnow 123(%r8,%rax,4), %dx, %ax +# INTEL: cmovno ax, dx, word ptr [r8 + 4*rax + 123] +0x62,0xd4,0x7d,0x18,0x41,0x54,0x80,0x7b + +# ATT: cmovnol 123(%r8,%rax,4), %ecx, %edx +# INTEL: cmovno edx, ecx, dword ptr [r8 + 4*rax + 123] +0x62,0xd4,0x6c,0x18,0x41,0x4c,0x80,0x7b + +# ATT: cmovnoq 123(%r8,%rax,4), %r9, %r15 +# INTEL: cmovno r15, r9, qword ptr [r8 + 4*rax + 123] +0x62,0x54,0x84,0x18,0x41,0x4c,0x80,0x7b + +# ATT: cmovnpw %dx, %ax, %r9w +# INTEL: cmovnp r9w, ax, dx +0x62,0xf4,0x35,0x18,0x4b,0xc2 + +# ATT: cmovnpl %ecx, %edx, %r10d +# INTEL: cmovnp r10d, edx, ecx +0x62,0xf4,0x2c,0x18,0x4b,0xd1 + +# ATT: cmovnpq %r9, %r15, %r11 +# INTEL: cmovnp r11, r15, r9 +0x62,0x54,0xa4,0x18,0x4b,0xf9 + +# ATT: cmovnpw 123(%r8,%rax,4), %dx, %ax +# INTEL: cmovnp ax, dx, word ptr [r8 + 4*rax + 123] +0x62,0xd4,0x7d,0x18,0x4b,0x54,0x80,0x7b + +# ATT: cmovnpl 123(%r8,%rax,4), %ecx, %edx +# INTEL: cmovnp edx, ecx, dword ptr [r8 + 4*rax + 123] +0x62,0xd4,0x6c,0x18,0x4b,0x4c,0x80,0x7b + +# ATT: cmovnpq 123(%r8,%rax,4), %r9, %r15 +# INTEL: cmovnp r15, r9, qword ptr [r8 + 4*rax + 123] +0x62,0x54,0x84,0x18,0x4b,0x4c,0x80,0x7b + +# ATT: cmovnsw %dx, %ax, %r9w +# INTEL: cmovns r9w, ax, dx +0x62,0xf4,0x35,0x18,0x49,0xc2 + +# ATT: cmovnsl %ecx, %edx, %r10d +# INTEL: cmovns r10d, edx, ecx +0x62,0xf4,0x2c,0x18,0x49,0xd1 + +# ATT: cmovnsq %r9, %r15, %r11 +# INTEL: cmovns r11, r15, r9 +0x62,0x54,0xa4,0x18,0x49,0xf9 + +# ATT: cmovnsw 123(%r8,%rax,4), %dx, %ax +# INTEL: cmovns ax, dx, word ptr [r8 + 4*rax + 123] +0x62,0xd4,0x7d,0x18,0x49,0x54,0x80,0x7b + +# ATT: cmovnsl 123(%r8,%rax,4), %ecx, %edx +# INTEL: cmovns edx, ecx, dword ptr [r8 + 4*rax + 123] +0x62,0xd4,0x6c,0x18,0x49,0x4c,0x80,0x7b + +# ATT: cmovnsq 123(%r8,%rax,4), %r9, %r15 +# INTEL: cmovns r15, r9, qword ptr [r8 + 4*rax + 123] +0x62,0x54,0x84,0x18,0x49,0x4c,0x80,0x7b + +# ATT: cmovnew %dx, %ax, %r9w +# INTEL: cmovne r9w, ax, dx +0x62,0xf4,0x35,0x18,0x45,0xc2 + +# ATT: cmovnel %ecx, %edx, %r10d +# INTEL: cmovne r10d, edx, ecx +0x62,0xf4,0x2c,0x18,0x45,0xd1 + +# ATT: cmovneq %r9, %r15, %r11 +# INTEL: cmovne r11, r15, r9 +0x62,0x54,0xa4,0x18,0x45,0xf9 + +# ATT: cmovnew 123(%r8,%rax,4), %dx, %ax +# INTEL: cmovne ax, dx, word ptr [r8 + 4*rax + 123] +0x62,0xd4,0x7d,0x18,0x45,0x54,0x80,0x7b + +# ATT: cmovnel 123(%r8,%rax,4), %ecx, %edx +# INTEL: cmovne edx, ecx, dword ptr [r8 + 4*rax + 123] +0x62,0xd4,0x6c,0x18,0x45,0x4c,0x80,0x7b + +# ATT: cmovneq 123(%r8,%rax,4), %r9, %r15 +# INTEL: cmovne r15, r9, qword ptr [r8 + 4*rax + 123] +0x62,0x54,0x84,0x18,0x45,0x4c,0x80,0x7b + +# ATT: cmovow %dx, %ax, %r9w +# INTEL: cmovo r9w, ax, dx +0x62,0xf4,0x35,0x18,0x40,0xc2 + +# ATT: cmovol %ecx, %edx, %r10d +# INTEL: cmovo r10d, edx, ecx +0x62,0xf4,0x2c,0x18,0x40,0xd1 + +# ATT: cmovoq %r9, %r15, %r11 +# INTEL: cmovo r11, r15, r9 +0x62,0x54,0xa4,0x18,0x40,0xf9 + +# ATT: cmovow 123(%r8,%rax,4), %dx, %ax +# INTEL: cmovo ax, dx, word ptr [r8 + 4*rax + 123] +0x62,0xd4,0x7d,0x18,0x40,0x54,0x80,0x7b + +# ATT: cmovol 123(%r8,%rax,4), %ecx, %edx +# INTEL: cmovo edx, ecx, dword ptr [r8 + 4*rax + 123] +0x62,0xd4,0x6c,0x18,0x40,0x4c,0x80,0x7b + +# ATT: cmovoq 123(%r8,%rax,4), %r9, %r15 +# INTEL: cmovo r15, r9, qword ptr [r8 + 4*rax + 123] +0x62,0x54,0x84,0x18,0x40,0x4c,0x80,0x7b + +# ATT: cmovpw %dx, %ax, %r9w +# INTEL: cmovp r9w, ax, dx +0x62,0xf4,0x35,0x18,0x4a,0xc2 + +# ATT: cmovpl %ecx, %edx, %r10d +# INTEL: cmovp r10d, edx, ecx +0x62,0xf4,0x2c,0x18,0x4a,0xd1 + +# ATT: cmovpq %r9, %r15, %r11 +# INTEL: cmovp r11, r15, r9 +0x62,0x54,0xa4,0x18,0x4a,0xf9 + +# ATT: cmovpw 123(%r8,%rax,4), %dx, %ax +# INTEL: cmovp ax, dx, word ptr [r8 + 4*rax + 123] +0x62,0xd4,0x7d,0x18,0x4a,0x54,0x80,0x7b + +# ATT: cmovpl 123(%r8,%rax,4), %ecx, %edx +# INTEL: cmovp edx, ecx, dword ptr [r8 + 4*rax + 123] +0x62,0xd4,0x6c,0x18,0x4a,0x4c,0x80,0x7b + +# ATT: cmovpq 123(%r8,%rax,4), %r9, %r15 +# INTEL: cmovp r15, r9, qword ptr [r8 + 4*rax + 123] +0x62,0x54,0x84,0x18,0x4a,0x4c,0x80,0x7b + +# ATT: cmovsw %dx, %ax, %r9w +# INTEL: cmovs r9w, ax, dx +0x62,0xf4,0x35,0x18,0x48,0xc2 + +# ATT: cmovsl %ecx, %edx, %r10d +# INTEL: cmovs r10d, edx, ecx +0x62,0xf4,0x2c,0x18,0x48,0xd1 + +# ATT: cmovsq %r9, %r15, %r11 +# INTEL: cmovs r11, r15, r9 +0x62,0x54,0xa4,0x18,0x48,0xf9 + +# ATT: cmovsw 123(%r8,%rax,4), %dx, %ax +# INTEL: cmovs ax, dx, word ptr [r8 + 4*rax + 123] +0x62,0xd4,0x7d,0x18,0x48,0x54,0x80,0x7b + +# ATT: cmovsl 123(%r8,%rax,4), %ecx, %edx +# INTEL: cmovs edx, ecx, dword ptr [r8 + 4*rax + 123] +0x62,0xd4,0x6c,0x18,0x48,0x4c,0x80,0x7b + +# ATT: cmovsq 123(%r8,%rax,4), %r9, %r15 +# INTEL: cmovs r15, r9, qword ptr [r8 + 4*rax + 123] +0x62,0x54,0x84,0x18,0x48,0x4c,0x80,0x7b + +# ATT: cmovew %dx, %ax, %r9w +# INTEL: cmove r9w, ax, dx +0x62,0xf4,0x35,0x18,0x44,0xc2 + +# ATT: cmovel %ecx, %edx, %r10d +# INTEL: cmove r10d, edx, ecx +0x62,0xf4,0x2c,0x18,0x44,0xd1 + +# ATT: cmoveq %r9, %r15, %r11 +# INTEL: cmove r11, r15, r9 +0x62,0x54,0xa4,0x18,0x44,0xf9 + +# ATT: cmovew 123(%r8,%rax,4), %dx, %ax +# INTEL: cmove ax, dx, word ptr [r8 + 4*rax + 123] +0x62,0xd4,0x7d,0x18,0x44,0x54,0x80,0x7b + +# ATT: cmovel 123(%r8,%rax,4), %ecx, %edx +# INTEL: cmove edx, ecx, dword ptr [r8 + 4*rax + 123] +0x62,0xd4,0x6c,0x18,0x44,0x4c,0x80,0x7b + +# ATT: cmoveq 123(%r8,%rax,4), %r9, %r15 +# INTEL: cmove r15, r9, qword ptr [r8 + 4*rax + 123] +0x62,0x54,0x84,0x18,0x44,0x4c,0x80,0x7b diff --git a/llvm/test/MC/Disassembler/X86/apx/evex-format.txt b/llvm/test/MC/Disassembler/X86/apx/evex-format.txt index 1c1f70b096bed9d4d8caba4a61b477edc06ceb1c..1156f5c409922a45ed3fbebbf7b48f5dbe9c2298 100644 --- a/llvm/test/MC/Disassembler/X86/apx/evex-format.txt +++ b/llvm/test/MC/Disassembler/X86/apx/evex-format.txt @@ -11,6 +11,12 @@ # INTEL: add r18, qword ptr [r17 + 123], r16 0x62,0xec,0xec,0x10,0x01,0x41,0x7b +## MRMDestMemCC + +# ATT: cfcmovbq %r16, 123(%r17,%r18,4) +# INTEL: cfcmovb qword ptr [r17 + 4*r18 + 123], r16 +0x62,0xec,0xf8,0x0c,0x42,0x44,0x91,0x7b + ## MRMSrcMem # ATT: vbroadcasti32x4 (%r16,%r17), %zmm0 @@ -21,6 +27,16 @@ # INTEL: sub r18, r17, qword ptr [r16 + 123] 0x62,0xec,0xec,0x10,0x2b,0x48,0x7b +## MRMSrcMemCC + +# ATT: cfcmovbq 123(%r16,%r17,4), %r18 +# INTEL: cfcmovb r18, qword ptr [r16 + 4*r17 + 123] +0x62,0xec,0xf8,0x08,0x42,0x54,0x88,0x7b + +# ATT: cfcmovbq 123(%r16,%r17,4), %r18, %r19 +# INTEL: cfcmovb r19, r18, qword ptr [r16 + 4*r17 + 123] +0x62,0xec,0xe0,0x14,0x42,0x54,0x88,0x7b + ## MRM0m # ATT: vprorq $0, (%r16,%r17), %zmm0 @@ -123,12 +139,28 @@ # INTEL: {nf} add r17, r16 0x62,0xec,0xfc,0x0c,0x01,0xc1 +## MRMDestRegCC + +# ATT: cfcmovbq %r16, %r17 +# INTEL: cfcmovb r17, r16 +0x62,0xec,0xfc,0x0c,0x42,0xc1 + ## MRMSrcReg # ATT: mulxq %r16, %r17, %r18 # INTEL: mulx r18, r17, r16 0x62,0xea,0xf7,0x00,0xf6,0xd0 +## MRMSrcRegCC + +# ATT: cfcmovbq %r16, %r17, %r18 +# INTEL: cfcmovb r18, r17, r16 +0x62,0xec,0xec,0x14,0x42,0xc8 + +# ATT: cfcmovlq %r16, %r17, %r18 +# INTEL: cfcmovl r18, r17, r16 +0x62,0xec,0xec,0x14,0x4c,0xc8 + ## MRMSrcReg4VOp3 # ATT: bzhiq %r19, %r23, %r27 diff --git a/llvm/test/MC/Disassembler/X86/apx/imulzu.txt b/llvm/test/MC/Disassembler/X86/apx/imulzu.txt new file mode 100644 index 0000000000000000000000000000000000000000..86142e0540970be1a2639820b86305575f2fb38d --- /dev/null +++ b/llvm/test/MC/Disassembler/X86/apx/imulzu.txt @@ -0,0 +1,50 @@ +# RUN: llvm-mc -triple x86_64 -disassemble %s | FileCheck %s --check-prefix=ATT +# RUN: llvm-mc -triple x86_64 -disassemble -output-asm-variant=1 %s | FileCheck %s --check-prefix=INTEL + +# ATT: imulzuw $123, %dx, %dx +# INTEL: imulzu dx, dx, 123 +0x62,0xf4,0x7d,0x18,0x6b,0xd2,0x7b + +# ATT: imulzul $123, %ecx, %ecx +# INTEL: imulzu ecx, ecx, 123 +0x62,0xf4,0x7c,0x18,0x6b,0xc9,0x7b + +# ATT: imulzuq $123, %r9, %r9 +# INTEL: imulzu r9, r9, 123 +0x62,0x54,0xfc,0x18,0x6b,0xc9,0x7b + +# ATT: imulzuw $123, 291(%r8,%rax,4), %dx +# INTEL: imulzu dx, word ptr [r8 + 4*rax + 291], 123 +0x62,0xd4,0x7d,0x18,0x6b,0x94,0x80,0x23,0x01,0x00,0x00,0x7b + +# ATT: imulzul $123, 291(%r8,%rax,4), %ecx +# INTEL: imulzu ecx, dword ptr [r8 + 4*rax + 291], 123 +0x62,0xd4,0x7c,0x18,0x6b,0x8c,0x80,0x23,0x01,0x00,0x00,0x7b + +# ATT: imulzuq $123, 291(%r8,%rax,4), %r9 +# INTEL: imulzu r9, qword ptr [r8 + 4*rax + 291], 123 +0x62,0x54,0xfc,0x18,0x6b,0x8c,0x80,0x23,0x01,0x00,0x00,0x7b + +# ATT: imulzuw $1234, %dx, %dx +# INTEL: imulzu dx, dx, 1234 +0x62,0xf4,0x7d,0x18,0x69,0xd2,0xd2,0x04 + +# ATT: imulzuw $1234, 291(%r8,%rax,4), %dx +# INTEL: imulzu dx, word ptr [r8 + 4*rax + 291], 1234 +0x62,0xd4,0x7d,0x18,0x69,0x94,0x80,0x23,0x01,0x00,0x00,0xd2,0x04 + +# ATT: imulzul $123456, %ecx, %ecx +# INTEL: imulzu ecx, ecx, 123456 +0x62,0xf4,0x7c,0x18,0x69,0xc9,0x40,0xe2,0x01,0x00 + +# ATT: imulzuq $123456, %r9, %r9 +# INTEL: imulzu r9, r9, 123456 +0x62,0x54,0xfc,0x18,0x69,0xc9,0x40,0xe2,0x01,0x00 + +# ATT: imulzul $123456, 291(%r8,%rax,4), %ecx +# INTEL: imulzu ecx, dword ptr [r8 + 4*rax + 291], 123456 +0x62,0xd4,0x7c,0x18,0x69,0x8c,0x80,0x23,0x01,0x00,0x00,0x40,0xe2,0x01,0x00 + +# ATT: imulzuq $123456, 291(%r8,%rax,4), %r9 +# INTEL: imulzu r9, qword ptr [r8 + 4*rax + 291], 123456 +0x62,0x54,0xfc,0x18,0x69,0x8c,0x80,0x23,0x01,0x00,0x00,0x40,0xe2,0x01,0x00 diff --git a/llvm/test/MC/Disassembler/X86/apx/reverse-encoding.txt b/llvm/test/MC/Disassembler/X86/apx/reverse-encoding.txt index 9e812e370146bac4262035d6fc001ab5a4aca215..fd12d904a4a46d647fd870e868b5032caad33c83 100644 --- a/llvm/test/MC/Disassembler/X86/apx/reverse-encoding.txt +++ b/llvm/test/MC/Disassembler/X86/apx/reverse-encoding.txt @@ -430,3 +430,17 @@ # ATT: ccmpoq {dfv=} %r16, %r17 # INTEL: ccmpo {dfv=} r17, r16 0x62,0xec,0x84,0x00,0x3b,0xc8 + +## cfcmov + +# ATT: cfcmovbew %r16w, %r17w +# INTEL: cfcmovbe r17w, r16w +0x62,0xec,0x7d,0x08,0x46,0xc8 + +# ATT: cfcmovbel %r16d, %r17d +# INTEL: cfcmovbe r17d, r16d +0x62,0xec,0x7c,0x08,0x46,0xc8 + +# ATT: cfcmovbeq %r16, %r17 +# INTEL: cfcmovbe r17, r16 +0x62,0xec,0xfc,0x08,0x46,0xc8 diff --git a/llvm/test/MC/GOFF/ppa1.ll b/llvm/test/MC/GOFF/ppa1.ll index 40fc9e93780db60250a34313e87a98a76874524d..13971c7ec8e72d8f50f87382b49796c85aa38450 100644 --- a/llvm/test/MC/GOFF/ppa1.ll +++ b/llvm/test/MC/GOFF/ppa1.ll @@ -1,7 +1,7 @@ ; RUN: llc -mtriple s390x-ibm-zos < %s | FileCheck %s ; REQUIRES: systemz-registered-target -; CHECK: @@EPM_void_test_0: * @void_test +; CHECK: L#EPM_void_test_0: * @void_test ; CHECK: * XPLINK Routine Layout Entry ; CHECK: .long 12779717 * Eyecatcher 0x00C300C500C500 ; CHECK: .short 197 @@ -11,9 +11,9 @@ ; CHECK: * Entry Flags ; CHECK: * Bit 1: 1 = Leaf function ; CHECK: * Bit 2: 0 = Does not use alloca -; CHECK: @@func_end0: +; CHECK: L#func_end0: ; CHECK: .section ".ppa1" -; CHECK: @@PPA1_void_test_0: * PPA1 +; CHECK: L#PPA1_void_test_0: * PPA1 ; CHECK: .byte 2 * Version ; CHECK: .byte 206 * LE Signature X'CE' ; CHECK: .short 0 * Saved GPR Mask @@ -25,8 +25,8 @@ ; CHECK: .byte 0 * PPA1 Flags 3 ; CHECK: .byte 129 * PPA1 Flags 4 ; CHECK: .short 0 * Length/4 of Parms -; CHECK: .long @@func_end0-@@EPM_void_test_0 * Length of Code -; CHECK: .long @@EPM_void_test_0-@@PPA1_void_test_0 +; CHECK: .long L#func_end0-L#EPM_void_test_0 * Length of Code +; CHECK: .long L#EPM_void_test_0-L#PPA1_void_test_0 ; CHECK: .section ".text" ; CHECK: * -- End function define void @void_test() { diff --git a/llvm/test/MC/Hexagon/directive-attribute-err.s b/llvm/test/MC/Hexagon/directive-attribute-err.s new file mode 100644 index 0000000000000000000000000000000000000000..52b145b1ff28a1907edbf6739fde7b10419e9867 --- /dev/null +++ b/llvm/test/MC/Hexagon/directive-attribute-err.s @@ -0,0 +1,24 @@ +/// attribute parsing error cases. + +// RUN: not llvm-mc -triple=hexagon -filetype=asm %s 2>&1 \ +// RUN: | FileCheck %s + + .attribute Tag_unknown_name, 0 +// CHECK: [[#@LINE-1]]:14: error: attribute name not recognized: Tag_unknown_name +// CHECK-NEXT: .attribute Tag_unknown_name + + .attribute [non_constant_expression], 0 +// CHECK: [[#@LINE-1]]:14: error: expected numeric constant +// CHECK-NEXT: .attribute [non_constant_expression], 0 + + .attribute 42, "forty two" +// CHECK: [[#@LINE-1]]:18: error: expected numeric constant +// CHECK-NEXT: .attribute 42, "forty two" + + .attribute Tag_arch, "v75" +// CHECK: [[#@LINE-1]]:24: error: expected numeric constant +// CHECK-NEXT: .attribute Tag_arch, "v75" + + .attribute 0 +// CHECK: :[[#@LINE-1]]:15: error: expected comma +// CHECK-NEXT: .attribute 0 diff --git a/llvm/test/MC/Hexagon/directive-attribute.s b/llvm/test/MC/Hexagon/directive-attribute.s new file mode 100644 index 0000000000000000000000000000000000000000..d7c893061e18ab56acf1f1453743cffa0a660951 --- /dev/null +++ b/llvm/test/MC/Hexagon/directive-attribute.s @@ -0,0 +1,41 @@ +/// Check .attribute parsing. + +// RUN: llvm-mc -triple=hexagon -filetype=obj %s | llvm-readelf -A - | \ +// RUN: FileCheck %s --match-full-lines --implicit-check-not={{.}} + +.attribute 4, 71 // Tag_arch +.attribute Tag_cabac, 1 +.attribute Tag_hvx_arch, 68 +.attribute 7, 1 // Tag_hvx_qfloat + +// CHECK: BuildAttributes { +// CHECK-NEXT: FormatVersion: 0x41 +// CHECK-NEXT: Section 1 { +// CHECK-NEXT: SectionLength: 25 +// CHECK-NEXT: Vendor: hexagon +// CHECK-NEXT: Tag: Tag_File (0x1) +// CHECK-NEXT: Size: 13 +// CHECK-NEXT: FileAttributes { +// CHECK-NEXT: Attribute { +// CHECK-NEXT: Tag: 4 +// CHECK-NEXT: TagName: arch +// CHECK-NEXT: Value: 71 +// CHECK-NEXT: } +// CHECK-NEXT: Attribute { +// CHECK-NEXT: Tag: 10 +// CHECK-NEXT: TagName: cabac +// CHECK-NEXT: Value: 1 +// CHECK-NEXT: } +// CHECK-NEXT: Attribute { +// CHECK-NEXT: Tag: 5 +// CHECK-NEXT: TagName: hvx_arch +// CHECK-NEXT: Value: 68 +// CHECK-NEXT: } +// CHECK-NEXT: Attribute { +// CHECK-NEXT: Tag: 7 +// CHECK-NEXT: TagName: hvx_qfloat +// CHECK-NEXT: Value: 1 +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: } diff --git a/llvm/test/MC/Hexagon/hexagon_attributes.s b/llvm/test/MC/Hexagon/hexagon_attributes.s new file mode 100644 index 0000000000000000000000000000000000000000..e90536030d977fafbc877c8ee4f3c703786cb582 --- /dev/null +++ b/llvm/test/MC/Hexagon/hexagon_attributes.s @@ -0,0 +1,94 @@ +/// Check that file attributes are recorded in a .hexagon.attributes section. + +q0&=vcmp.gt(v0.bf,v0.bf) // hvxv73, hvx-qfloat +r3:2=cround(r1:0,#0x0) // v67, audio +v3:0.w=vrmpyz(v0.b,r0.b) // hvxv73, zreg +v1:0.sf=vadd(v0.bf,v0.bf) // hvxv73, hvx-ieee-fp + +// RUN: llvm-mc --mattr=+v67,+hvxv73,+hvx-qfloat,+hvx-ieee-fp,+zreg,+audio %s \ +// RUN: -triple=hexagon -filetype=obj --hexagon-add-build-attributes -o %t.o + +// RUN: llvm-readelf -A %t.o | \ +// RUN: FileCheck %s --match-full-lines --implicit-check-not={{.}} --check-prefix=READELF + +/// llvm-objudmp should be able to determine subtarget features +/// without manually passing in features when an attribute section is present. +// RUN: llvm-objdump -d %t.o | FileCheck %s --check-prefix=OBJDUMP + +// RUN: llvm-mc --mattr=+v67,+hvxv73,+hvx-qfloat,+hvx-ieee-fp,+zreg,+audio %s \ +// RUN: -triple=hexagon -filetype=asm --hexagon-add-build-attributes | \ +// RUN: FileCheck %s --match-full-lines --implicit-check-not={{.}} --check-prefix=ASM + +// READELF: BuildAttributes { +// READELF-NEXT: FormatVersion: 0x41 +// READELF-NEXT: Section 1 { +// READELF-NEXT: SectionLength: 31 +// READELF-NEXT: Vendor: hexagon +// READELF-NEXT: Tag: Tag_File (0x1) +// READELF-NEXT: Size: 19 +// READELF-NEXT: FileAttributes { +// READELF-NEXT: Attribute { +// READELF-NEXT: Tag: 4 +// READELF-NEXT: TagName: arch +// READELF-NEXT: Value: 67 +// READELF-NEXT: } +// READELF-NEXT: Attribute { +// READELF-NEXT: Tag: 5 +// READELF-NEXT: TagName: hvx_arch +// READELF-NEXT: Value: 73 +// READELF-NEXT: } +// READELF-NEXT: Attribute { +// READELF-NEXT: Tag: 6 +// READELF-NEXT: TagName: hvx_ieeefp +// READELF-NEXT: Value: 1 +// READELF-NEXT: } +// READELF-NEXT: Attribute { +// READELF-NEXT: Tag: 7 +// READELF-NEXT: TagName: hvx_qfloat +// READELF-NEXT: Value: 1 +// READELF-NEXT: } +// READELF-NEXT: Attribute { +// READELF-NEXT: Tag: 8 +// READELF-NEXT: TagName: zreg +// READELF-NEXT: Value: 1 +// READELF-NEXT: } +// READELF-NEXT: Attribute { +// READELF-NEXT: Tag: 9 +// READELF-NEXT: TagName: audio +// READELF-NEXT: Value: 1 +// READELF-NEXT: } +// READELF-NEXT: Attribute { +// READELF-NEXT: Tag: 10 +// READELF-NEXT: TagName: cabac +// READELF-NEXT: Value: 1 +// READELF-NEXT: } +// READELF-NEXT: } +// READELF-NEXT: } +// READELF-NEXT: } + +// OBJDUMP: 1c80e0d0 { q0 &= vcmp.gt(v0.bf,v0.bf) } +// OBJDUMP-NEXT: 8ce0c042 { r3:2 = cround(r1:0,#0x0) } +// OBJDUMP-NEXT: 19e8c000 { v3:0.w = vrmpyz(v0.b,r0.b) } +// OBJDUMP-NEXT: 1d40e0c0 { v1:0.sf = vadd(v0.bf,v0.bf) } + +// ASM: .attribute 4, 67 // Tag_arch +// ASM-NEXT: .attribute 5, 73 // Tag_hvx_arch +// ASM-NEXT: .attribute 6, 1 // Tag_hvx_ieeefp +// ASM-NEXT: .attribute 7, 1 // Tag_hvx_qfloat +// ASM-NEXT: .attribute 8, 1 // Tag_zreg +// ASM-NEXT: .attribute 9, 1 // Tag_audio +// ASM-NEXT: .attribute 10, 1 // Tag_cabac +// ASM-NEXT: .text +// ASM-EMPTY: +// ASM-NEXT: { +// ASM-NEXT: q0 &= vcmp.gt(v0.bf,v0.bf) +// ASM-NEXT: } +// ASM-NEXT: { +// ASM-NEXT: r3:2 = cround(r1:0,#0) +// ASM-NEXT: } +// ASM-NEXT: { +// ASM-NEXT: v3:0.w = vrmpyz(v0.b,r0.b) +// ASM-NEXT: } +// ASM-NEXT: { +// ASM-NEXT: v1:0.sf = vadd(v0.bf,v0.bf) +// ASM-NEXT: } diff --git a/llvm/test/MC/LoongArch/Macros/macros-li-bad.s b/llvm/test/MC/LoongArch/Macros/macros-li-bad.s index 194b86bfed2733557a536d6623a4e7421681afd1..c880a01020059b8548ab7fb1ecf7cb52266840af 100644 --- a/llvm/test/MC/LoongArch/Macros/macros-li-bad.s +++ b/llvm/test/MC/LoongArch/Macros/macros-li-bad.s @@ -5,3 +5,9 @@ li.w $a0, 0x100000000 li.d $a0, 0x10000000000000000 # CHECK: :[[#@LINE-1]]:11: error: unknown operand + +li.w $a0, non_const_val +# CHECK: :[[#@LINE-1]]:11: error: operand must be a 32 bit immediate + +li.d $a0, non_const_val +# CHECK: :[[#@LINE-1]]:11: error: operand must be a 64 bit immediate diff --git a/llvm/test/MC/RISCV/rv32-machine-csr-names.s b/llvm/test/MC/RISCV/rv32-machine-csr-names.s index e7a6d9ce718f2c2c1646afd8bd9c344cbfd72710..016f448d8dac63ba472c54c198f2ba4b6f8bab03 100644 --- a/llvm/test/MC/RISCV/rv32-machine-csr-names.s +++ b/llvm/test/MC/RISCV/rv32-machine-csr-names.s @@ -1149,3 +1149,59 @@ csrrs t2, 0x319, zero csrrs t1, miph, zero # uimm12 csrrs t2, 0x354, zero + +################################################ +# Resumable Non-Maskable Interrupts(Smrnmi) CSRs +################################################ + +# mnscratch +# name +# CHECK-INST: csrrs t1, mnscratch, zero +# CHECK-ENC: encoding: [0x73,0x23,0x00,0x74] +# CHECK-INST-ALIAS: csrr t1, mnscratch +# uimm12 +# CHECK-INST: csrrs t2, mnscratch, zero +# CHECK-ENC: encoding: [0xf3,0x23,0x00,0x74] +# CHECK-INST-ALIAS: csrr t2, mnscratch +csrrs t1, mnscratch, zero +# uimm12 +csrrs t2, 0x740, zero + +# mnepc +# name +# CHECK-INST: csrrs t1, mnepc, zero +# CHECK-ENC: encoding: [0x73,0x23,0x10,0x74] +# CHECK-INST-ALIAS: csrr t1, mnepc +# uimm12 +# CHECK-INST: csrrs t2, mnepc, zero +# CHECK-ENC: encoding: [0xf3,0x23,0x10,0x74] +# CHECK-INST-ALIAS: csrr t2, mnepc +csrrs t1, mnepc, zero +# uimm12 +csrrs t2, 0x741, zero + +# mncause +# name +# CHECK-INST: csrrs t1, mncause, zero +# CHECK-ENC: encoding: [0x73,0x23,0x20,0x74] +# CHECK-INST-ALIAS: csrr t1, mncause +# uimm12 +# CHECK-INST: csrrs t2, mncause, zero +# CHECK-ENC: encoding: [0xf3,0x23,0x20,0x74] +# CHECK-INST-ALIAS: csrr t2, mncause +csrrs t1, mncause, zero +# uimm12 +csrrs t2, 0x742, zero + +# mnstatus +# name +# CHECK-INST: csrrs t1, mnstatus, zero +# CHECK-ENC: encoding: [0x73,0x23,0x40,0x74] +# CHECK-INST-ALIAS: csrr t1, mnstatus +# uimm12 +# CHECK-INST: csrrs t2, mnstatus, zero +# CHECK-ENC: encoding: [0xf3,0x23,0x40,0x74] +# CHECK-INST-ALIAS: csrr t2, mnstatus +csrrs t1, mnstatus, zero +# uimm12 +csrrs t2, 0x744, zero diff --git a/llvm/test/MC/RISCV/rv32zcmp-invalid.s b/llvm/test/MC/RISCV/rv32zcmp-invalid.s index cb99bba0aaa1e80e419702a30d66e6a9dfd6a774..1acea187585f886b864c450547c6d0f7e27a4fa4 100644 --- a/llvm/test/MC/RISCV/rv32zcmp-invalid.s +++ b/llvm/test/MC/RISCV/rv32zcmp-invalid.s @@ -15,3 +15,15 @@ cm.popretz {ra, s0-s10}, 112 # CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment cm.popretz {ra, s0-s1}, 112 + +# CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment +cm.push {ra}, 16 + +# CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment +cm.pop {ra, s0-s1}, -32 + +# CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment +cm.push {ra}, -8 + +# CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment +cm.pop {ra, s0-s1}, -40 diff --git a/llvm/test/MC/RISCV/rv64zcmp-invalid.s b/llvm/test/MC/RISCV/rv64zcmp-invalid.s index 103934583495f34f090f0de678667f96443fa997..bf34554095ea5b5d4b6101140ba7e651872ad23d 100644 --- a/llvm/test/MC/RISCV/rv64zcmp-invalid.s +++ b/llvm/test/MC/RISCV/rv64zcmp-invalid.s @@ -15,3 +15,15 @@ cm.popretz {ra, s0-s10}, 112 # CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment cm.popretz {ra, s0-s1}, 112 + +# CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment +cm.push {ra}, 16 + +# CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment +cm.pop {ra, s0-s1}, -32 + +# CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment +cm.push {ra}, -15 + +# CHECK-ERROR: error: stack adjustment is invalid for this instruction and register list; refer to Zc spec for a detailed range of stack adjustment +cm.pop {ra, s0-s1}, -33 diff --git a/llvm/test/MC/RISCV/rvv/zvkned-invalid.s b/llvm/test/MC/RISCV/rvv/zvkned-invalid.s new file mode 100644 index 0000000000000000000000000000000000000000..9230bc08e3fa29a6a0c9af14010bc6cf46f6cbbb --- /dev/null +++ b/llvm/test/MC/RISCV/rvv/zvkned-invalid.s @@ -0,0 +1,23 @@ +# RUN: not llvm-mc -triple=riscv64 --mattr=+zve64x --mattr=+zvkned %s 2>&1 \ +# RUN: | FileCheck %s --check-prefix=CHECK-ERROR + +vaesdf.vs v10, v10 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vaesdf.vs v10, v10 + +vaesef.vs v11, v11 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vaesef.vs v11, v11 + +vaesdm.vs v12, v12 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vaesdm.vs v12, v12 + +vaesem.vs v13, v13 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vaesem.vs v13, v13 + +vaesz.vs v14, v14 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vaesz.vs v14, v14 + diff --git a/llvm/test/MC/RISCV/rvv/zvknh-invalid.s b/llvm/test/MC/RISCV/rvv/zvknh-invalid.s new file mode 100644 index 0000000000000000000000000000000000000000..d9902511c0e1062bf52e05385e280c2611f717c3 --- /dev/null +++ b/llvm/test/MC/RISCV/rvv/zvknh-invalid.s @@ -0,0 +1,26 @@ +# RUN: not llvm-mc -triple=riscv64 --mattr=+zve64x --mattr=+zvknha %s 2>&1 \ +# RUN: | FileCheck %s --check-prefix=CHECK-ERROR + +vsha2ms.vv v10, v10, v11 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vsha2ms.vv v10, v10, v11 + +vsha2ms.vv v11, v10, v11 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vsha2ms.vv v11, v10, v11 + +vsha2ch.vv v12, v12, v11 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vsha2ch.vv v12, v12, v11 + +vsha2ch.vv v11, v12, v11 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vsha2ch.vv v11, v12, v11 + +vsha2cl.vv v13, v13, v15 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vsha2cl.vv v13, v13, v15 + +vsha2cl.vv v15, v13, v15 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vsha2cl.vv v15, v13, v15 diff --git a/llvm/test/MC/RISCV/rvv/zvksed-invalid.s b/llvm/test/MC/RISCV/rvv/zvksed-invalid.s new file mode 100644 index 0000000000000000000000000000000000000000..41df8d3bc2961b620bb54071a5cb0daa7ed1c651 --- /dev/null +++ b/llvm/test/MC/RISCV/rvv/zvksed-invalid.s @@ -0,0 +1,6 @@ +# RUN: not llvm-mc -triple=riscv64 --mattr=+zve64x --mattr=+zvksed %s 2>&1 \ +# RUN: | FileCheck %s --check-prefix=CHECK-ERROR + +vsm4r.vs v10, v10 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vsm4r.vs v10, v10 diff --git a/llvm/test/MC/RISCV/rvv/zvksh-invalid.s b/llvm/test/MC/RISCV/rvv/zvksh-invalid.s new file mode 100644 index 0000000000000000000000000000000000000000..cccec44b81919e652d558037be804cbb6cc6e938 --- /dev/null +++ b/llvm/test/MC/RISCV/rvv/zvksh-invalid.s @@ -0,0 +1,10 @@ +# RUN: not llvm-mc -triple=riscv64 --mattr=+zve64x --mattr=+zvksh %s 2>&1 \ +# RUN: | FileCheck %s --check-prefix=CHECK-ERROR + +vsm3me.vv v10, v10, v8 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vsm3me.vv v10, v10, v8 + +vsm3c.vi v9, v9, 7 +# CHECK-ERROR: The destination vector register group cannot overlap the source vector register group. +# CHECK-ERROR-LABEL: vsm3c.vi v9, v9, 7 diff --git a/llvm/test/MC/RISCV/rvv/zvksh.s b/llvm/test/MC/RISCV/rvv/zvksh.s index ca6cb49d30793f9debe49ff0b731e9d5b01558ee..06251ff6efe5c9ba1ec3405c0bfb129ad64a827f 100644 --- a/llvm/test/MC/RISCV/rvv/zvksh.s +++ b/llvm/test/MC/RISCV/rvv/zvksh.s @@ -19,3 +19,10 @@ vsm3me.vv v10, v9, v8 # CHECK-ENCODING: [0x77,0x25,0x94,0x82] # CHECK-ERROR: instruction requires the following: 'Zvksh' (SM3 Hash Function Instructions){{$}} # CHECK-UNKNOWN: 77 25 94 82 <unknown> + +# vs1 is allowed to overlap, but not vs2. +vsm3me.vv v10, v9, v10 +# CHECK-INST: vsm3me.vv v10, v9, v10 +# CHECK-ENCODING: [0x77,0x25,0x95,0x82] +# CHECK-ERROR: instruction requires the following: 'Zvksh' (SM3 Hash Function Instructions){{$}} +# CHECK-UNKNOWN: 77 25 95 82 <unknown> diff --git a/llvm/test/MC/RISCV/xsifive-invalid.s b/llvm/test/MC/RISCV/xsifive-invalid.s new file mode 100644 index 0000000000000000000000000000000000000000..5210d29f9d3630f9c835fa1490039eee20db13ce --- /dev/null +++ b/llvm/test/MC/RISCV/xsifive-invalid.s @@ -0,0 +1,20 @@ +# RUN: not llvm-mc -triple riscv32 < %s 2>&1 | FileCheck %s +# RUN: not llvm-mc -triple riscv64 < %s 2>&1 | FileCheck %s + +sf.cflush.d.l1 0x10 # CHECK: :[[@LINE]]:16: error: invalid operand for instruction + +sf.cdiscard.d.l1 0x10 # CHECK: :[[@LINE]]:18: error: invalid operand for instruction + +sf.cflush.d.l1 x0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'XSiFivecflushdlone' (SiFive sf.cflush.d.l1 Instruction){{$}} + +sf.cflush.d.l1 x7 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'XSiFivecflushdlone' (SiFive sf.cflush.d.l1 Instruction){{$}} + +sf.cdiscard.d.l1 x0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'XSiFivecdiscarddlone' (SiFive sf.cdiscard.d.l1 Instruction){{$}} + +sf.cdiscard.d.l1 x7 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'XSiFivecdiscarddlone' (SiFive sf.cdiscard.d.l1 Instruction){{$}} + +sf.cease x1 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + +sf.cease 0x10 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction + +sf.cease # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'XSfcease' (SiFive sf.cease Instruction){{$}} diff --git a/llvm/test/MC/RISCV/xsifive-valid.s b/llvm/test/MC/RISCV/xsifive-valid.s new file mode 100644 index 0000000000000000000000000000000000000000..8aa0ab1bd8ba3b791b25a0598899bcac04aa2e90 --- /dev/null +++ b/llvm/test/MC/RISCV/xsifive-valid.s @@ -0,0 +1,36 @@ +# RUN: llvm-mc %s -triple=riscv32 -mattr=+xsifivecdiscarddlone,+xsifivecflushdlone,+xsfcease -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s +# RUN: llvm-mc %s -triple=riscv64 -mattr=+xsifivecdiscarddlone,+xsifivecflushdlone,+xsfcease -riscv-no-aliases -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s +# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+xsifivecdiscarddlone,+xsifivecflushdlone,+xsfcease < %s \ +# RUN: | llvm-objdump --mattr=+xsifivecdiscarddlone,+xsifivecflushdlone,+xsfcease -M no-aliases -d - \ +# RUN: | FileCheck -check-prefix=CHECK-INST %s +# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+xsifivecdiscarddlone,+xsifivecflushdlone,+xsfcease < %s \ +# RUN: | llvm-objdump --mattr=+xsifivecdiscarddlone,+xsifivecflushdlone,+xsfcease -M no-aliases -d - \ +# RUN: | FileCheck -check-prefix=CHECK-INST %s + +# CHECK-INST: sf.cflush.d.l1 zero +# CHECK-ENC: encoding: [0x73,0x00,0x00,0xfc] +sf.cflush.d.l1 x0 +# CHECK-INST: sf.cflush.d.l1 zero +# CHECK-ENC: encoding: [0x73,0x00,0x00,0xfc] +sf.cflush.d.l1 + +# CHECK-INST: sf.cflush.d.l1 t2 +# CHECK-ENC: encoding: [0x73,0x80,0x03,0xfc] +sf.cflush.d.l1 x7 + +# CHECK-INST: sf.cdiscard.d.l1 zero +# CHECK-ENC: encoding: [0x73,0x00,0x20,0xfc] +sf.cdiscard.d.l1 x0 +# CHECK-INST: sf.cdiscard.d.l1 zero +# CHECK-ENC: encoding: [0x73,0x00,0x20,0xfc] +sf.cdiscard.d.l1 + +# CHECK-INST: sf.cdiscard.d.l1 t2 +# CHECK-ENC: encoding: [0x73,0x80,0x23,0xfc] +sf.cdiscard.d.l1 x7 + +# CHECK-INST: sf.cease +# CHECK-ENC: encoding: [0x73,0x00,0x50,0x30] +sf.cease diff --git a/llvm/test/MC/WebAssembly/module-asm.ll b/llvm/test/MC/WebAssembly/module-asm.ll new file mode 100644 index 0000000000000000000000000000000000000000..d451bec0020900fdbfa22eefed73880e31aedba2 --- /dev/null +++ b/llvm/test/MC/WebAssembly/module-asm.ll @@ -0,0 +1,25 @@ +; Ensure that symbols from module ASM are properly exported. +; +; Regression test for https://github.com/llvm/llvm-project/issues/85578. + +; RUN: llc -mtriple=wasm32-unknown-unknown -filetype=obj %s -o - | obj2yaml | FileCheck %s + +module asm "test_func:" +module asm " .globl test_func" +module asm " .functype test_func (i32) -> (i32)" +module asm " .export_name test_func, test_export" +module asm " end_function" + +; CHECK: - Type: TYPE +; CHECK-NEXT: Signatures: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: ParamTypes: +; CHECK-NEXT: - I32 +; CHECK-NEXT: ReturnTypes: +; CHECK-NEXT: - I32 + +; CHECK: - Type: EXPORT +; CHECK-NEXT: Exports: +; CHECK-NEXT: - Name: test_export +; CHECK-NEXT: Kind: FUNCTION +; CHECK-NEXT: Index: 0 diff --git a/llvm/test/MC/X86/apx/cfcmov-att.s b/llvm/test/MC/X86/apx/cfcmov-att.s new file mode 100644 index 0000000000000000000000000000000000000000..a6947ca7bc0deb747077fb782baaedd23606f90d --- /dev/null +++ b/llvm/test/MC/X86/apx/cfcmov-att.s @@ -0,0 +1,841 @@ +# RUN: llvm-mc -triple x86_64 --show-encoding %s | FileCheck %s + +# CHECK: cfcmovbw %r17w, %r21w, %r25w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x42,0xe9] + cfcmovbw %r17w, %r21w, %r25w + +# CHECK: cfcmovbw %r17w, %r21w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x42,0xcd] + cfcmovbw %r17w, %r21w + +# CHECK: cfcmovbw %r17w, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x42,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovbw %r17w, 291(%r28,%r29,4) + +# CHECK: cfcmovbl %r18d, %r22d, %r26d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x42,0xf2] + cfcmovbl %r18d, %r22d, %r26d + +# CHECK: cfcmovbl %r18d, %r22d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x42,0xd6] + cfcmovbl %r18d, %r22d + +# CHECK: cfcmovbl %r18d, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x42,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovbl %r18d, 291(%r28,%r29,4) + +# CHECK: cfcmovbq %r19, %r23, %r27 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x42,0xfb] + cfcmovbq %r19, %r23, %r27 + +# CHECK: cfcmovbq %r19, %r23 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x42,0xdf] + cfcmovbq %r19, %r23 + +# CHECK: cfcmovbq %r19, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x42,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovbq %r19, 291(%r28,%r29,4) + +# CHECK: cfcmovbw 291(%r28,%r29,4), %r17w, %r21w +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x42,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovbw 291(%r28,%r29,4), %r17w, %r21w + +# CHECK: cfcmovbw 291(%r28,%r29,4), %r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x42,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovbw 291(%r28,%r29,4), %r17w + +# CHECK: cfcmovbl 291(%r28,%r29,4), %r18d, %r22d +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x42,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovbl 291(%r28,%r29,4), %r18d, %r22d + +# CHECK: cfcmovbl 291(%r28,%r29,4), %r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x42,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovbl 291(%r28,%r29,4), %r18d + +# CHECK: cfcmovbq 291(%r28,%r29,4), %r19, %r23 +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x42,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovbq 291(%r28,%r29,4), %r19, %r23 + +# CHECK: cfcmovbq 291(%r28,%r29,4), %r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x42,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovbq 291(%r28,%r29,4), %r19 + +# CHECK: cfcmovbew %r17w, %r21w, %r25w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x46,0xe9] + cfcmovbew %r17w, %r21w, %r25w + +# CHECK: cfcmovbew %r17w, %r21w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x46,0xcd] + cfcmovbew %r17w, %r21w + +# CHECK: cfcmovbew %r17w, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x46,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovbew %r17w, 291(%r28,%r29,4) + +# CHECK: cfcmovbel %r18d, %r22d, %r26d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x46,0xf2] + cfcmovbel %r18d, %r22d, %r26d + +# CHECK: cfcmovbel %r18d, %r22d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x46,0xd6] + cfcmovbel %r18d, %r22d + +# CHECK: cfcmovbel %r18d, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x46,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovbel %r18d, 291(%r28,%r29,4) + +# CHECK: cfcmovbeq %r19, %r23, %r27 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x46,0xfb] + cfcmovbeq %r19, %r23, %r27 + +# CHECK: cfcmovbeq %r19, %r23 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x46,0xdf] + cfcmovbeq %r19, %r23 + +# CHECK: cfcmovbeq %r19, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x46,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovbeq %r19, 291(%r28,%r29,4) + +# CHECK: cfcmovbew 291(%r28,%r29,4), %r17w, %r21w +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x46,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovbew 291(%r28,%r29,4), %r17w, %r21w + +# CHECK: cfcmovbew 291(%r28,%r29,4), %r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x46,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovbew 291(%r28,%r29,4), %r17w + +# CHECK: cfcmovbel 291(%r28,%r29,4), %r18d, %r22d +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x46,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovbel 291(%r28,%r29,4), %r18d, %r22d + +# CHECK: cfcmovbel 291(%r28,%r29,4), %r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x46,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovbel 291(%r28,%r29,4), %r18d + +# CHECK: cfcmovbeq 291(%r28,%r29,4), %r19, %r23 +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x46,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovbeq 291(%r28,%r29,4), %r19, %r23 + +# CHECK: cfcmovbeq 291(%r28,%r29,4), %r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x46,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovbeq 291(%r28,%r29,4), %r19 + +# CHECK: cfcmovlw %r17w, %r21w, %r25w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x4c,0xe9] + cfcmovlw %r17w, %r21w, %r25w + +# CHECK: cfcmovlw %r17w, %r21w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x4c,0xcd] + cfcmovlw %r17w, %r21w + +# CHECK: cfcmovlw %r17w, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x4c,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovlw %r17w, 291(%r28,%r29,4) + +# CHECK: cfcmovll %r18d, %r22d, %r26d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x4c,0xf2] + cfcmovll %r18d, %r22d, %r26d + +# CHECK: cfcmovll %r18d, %r22d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x4c,0xd6] + cfcmovll %r18d, %r22d + +# CHECK: cfcmovll %r18d, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x4c,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovll %r18d, 291(%r28,%r29,4) + +# CHECK: cfcmovlq %r19, %r23, %r27 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x4c,0xfb] + cfcmovlq %r19, %r23, %r27 + +# CHECK: cfcmovlq %r19, %r23 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x4c,0xdf] + cfcmovlq %r19, %r23 + +# CHECK: cfcmovlq %r19, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x4c,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovlq %r19, 291(%r28,%r29,4) + +# CHECK: cfcmovlw 291(%r28,%r29,4), %r17w, %r21w +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x4c,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovlw 291(%r28,%r29,4), %r17w, %r21w + +# CHECK: cfcmovlw 291(%r28,%r29,4), %r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x4c,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovlw 291(%r28,%r29,4), %r17w + +# CHECK: cfcmovll 291(%r28,%r29,4), %r18d, %r22d +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x4c,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovll 291(%r28,%r29,4), %r18d, %r22d + +# CHECK: cfcmovll 291(%r28,%r29,4), %r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x4c,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovll 291(%r28,%r29,4), %r18d + +# CHECK: cfcmovlq 291(%r28,%r29,4), %r19, %r23 +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x4c,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovlq 291(%r28,%r29,4), %r19, %r23 + +# CHECK: cfcmovlq 291(%r28,%r29,4), %r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x4c,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovlq 291(%r28,%r29,4), %r19 + +# CHECK: cfcmovlew %r17w, %r21w, %r25w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x4e,0xe9] + cfcmovlew %r17w, %r21w, %r25w + +# CHECK: cfcmovlew %r17w, %r21w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x4e,0xcd] + cfcmovlew %r17w, %r21w + +# CHECK: cfcmovlew %r17w, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x4e,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovlew %r17w, 291(%r28,%r29,4) + +# CHECK: cfcmovlel %r18d, %r22d, %r26d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x4e,0xf2] + cfcmovlel %r18d, %r22d, %r26d + +# CHECK: cfcmovlel %r18d, %r22d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x4e,0xd6] + cfcmovlel %r18d, %r22d + +# CHECK: cfcmovlel %r18d, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x4e,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovlel %r18d, 291(%r28,%r29,4) + +# CHECK: cfcmovleq %r19, %r23, %r27 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x4e,0xfb] + cfcmovleq %r19, %r23, %r27 + +# CHECK: cfcmovleq %r19, %r23 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x4e,0xdf] + cfcmovleq %r19, %r23 + +# CHECK: cfcmovleq %r19, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x4e,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovleq %r19, 291(%r28,%r29,4) + +# CHECK: cfcmovlew 291(%r28,%r29,4), %r17w, %r21w +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x4e,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovlew 291(%r28,%r29,4), %r17w, %r21w + +# CHECK: cfcmovlew 291(%r28,%r29,4), %r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x4e,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovlew 291(%r28,%r29,4), %r17w + +# CHECK: cfcmovlel 291(%r28,%r29,4), %r18d, %r22d +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x4e,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovlel 291(%r28,%r29,4), %r18d, %r22d + +# CHECK: cfcmovlel 291(%r28,%r29,4), %r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x4e,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovlel 291(%r28,%r29,4), %r18d + +# CHECK: cfcmovleq 291(%r28,%r29,4), %r19, %r23 +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x4e,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovleq 291(%r28,%r29,4), %r19, %r23 + +# CHECK: cfcmovleq 291(%r28,%r29,4), %r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x4e,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovleq 291(%r28,%r29,4), %r19 + +# CHECK: cfcmovaew %r17w, %r21w, %r25w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x43,0xe9] + cfcmovaew %r17w, %r21w, %r25w + +# CHECK: cfcmovaew %r17w, %r21w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x43,0xcd] + cfcmovaew %r17w, %r21w + +# CHECK: cfcmovaew %r17w, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x43,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovaew %r17w, 291(%r28,%r29,4) + +# CHECK: cfcmovael %r18d, %r22d, %r26d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x43,0xf2] + cfcmovael %r18d, %r22d, %r26d + +# CHECK: cfcmovael %r18d, %r22d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x43,0xd6] + cfcmovael %r18d, %r22d + +# CHECK: cfcmovael %r18d, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x43,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovael %r18d, 291(%r28,%r29,4) + +# CHECK: cfcmovaeq %r19, %r23, %r27 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x43,0xfb] + cfcmovaeq %r19, %r23, %r27 + +# CHECK: cfcmovaeq %r19, %r23 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x43,0xdf] + cfcmovaeq %r19, %r23 + +# CHECK: cfcmovaeq %r19, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x43,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovaeq %r19, 291(%r28,%r29,4) + +# CHECK: cfcmovaew 291(%r28,%r29,4), %r17w, %r21w +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x43,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovaew 291(%r28,%r29,4), %r17w, %r21w + +# CHECK: cfcmovaew 291(%r28,%r29,4), %r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x43,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovaew 291(%r28,%r29,4), %r17w + +# CHECK: cfcmovael 291(%r28,%r29,4), %r18d, %r22d +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x43,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovael 291(%r28,%r29,4), %r18d, %r22d + +# CHECK: cfcmovael 291(%r28,%r29,4), %r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x43,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovael 291(%r28,%r29,4), %r18d + +# CHECK: cfcmovaeq 291(%r28,%r29,4), %r19, %r23 +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x43,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovaeq 291(%r28,%r29,4), %r19, %r23 + +# CHECK: cfcmovaeq 291(%r28,%r29,4), %r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x43,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovaeq 291(%r28,%r29,4), %r19 + +# CHECK: cfcmovaw %r17w, %r21w, %r25w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x47,0xe9] + cfcmovaw %r17w, %r21w, %r25w + +# CHECK: cfcmovaw %r17w, %r21w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x47,0xcd] + cfcmovaw %r17w, %r21w + +# CHECK: cfcmovaw %r17w, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x47,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovaw %r17w, 291(%r28,%r29,4) + +# CHECK: cfcmoval %r18d, %r22d, %r26d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x47,0xf2] + cfcmoval %r18d, %r22d, %r26d + +# CHECK: cfcmoval %r18d, %r22d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x47,0xd6] + cfcmoval %r18d, %r22d + +# CHECK: cfcmoval %r18d, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x47,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmoval %r18d, 291(%r28,%r29,4) + +# CHECK: cfcmovaq %r19, %r23, %r27 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x47,0xfb] + cfcmovaq %r19, %r23, %r27 + +# CHECK: cfcmovaq %r19, %r23 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x47,0xdf] + cfcmovaq %r19, %r23 + +# CHECK: cfcmovaq %r19, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x47,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovaq %r19, 291(%r28,%r29,4) + +# CHECK: cfcmovaw 291(%r28,%r29,4), %r17w, %r21w +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x47,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovaw 291(%r28,%r29,4), %r17w, %r21w + +# CHECK: cfcmovaw 291(%r28,%r29,4), %r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x47,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovaw 291(%r28,%r29,4), %r17w + +# CHECK: cfcmoval 291(%r28,%r29,4), %r18d, %r22d +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x47,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmoval 291(%r28,%r29,4), %r18d, %r22d + +# CHECK: cfcmoval 291(%r28,%r29,4), %r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x47,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmoval 291(%r28,%r29,4), %r18d + +# CHECK: cfcmovaq 291(%r28,%r29,4), %r19, %r23 +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x47,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovaq 291(%r28,%r29,4), %r19, %r23 + +# CHECK: cfcmovaq 291(%r28,%r29,4), %r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x47,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovaq 291(%r28,%r29,4), %r19 + +# CHECK: cfcmovgew %r17w, %r21w, %r25w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x4d,0xe9] + cfcmovgew %r17w, %r21w, %r25w + +# CHECK: cfcmovgew %r17w, %r21w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x4d,0xcd] + cfcmovgew %r17w, %r21w + +# CHECK: cfcmovgew %r17w, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x4d,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovgew %r17w, 291(%r28,%r29,4) + +# CHECK: cfcmovgel %r18d, %r22d, %r26d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x4d,0xf2] + cfcmovgel %r18d, %r22d, %r26d + +# CHECK: cfcmovgel %r18d, %r22d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x4d,0xd6] + cfcmovgel %r18d, %r22d + +# CHECK: cfcmovgel %r18d, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x4d,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovgel %r18d, 291(%r28,%r29,4) + +# CHECK: cfcmovgeq %r19, %r23, %r27 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x4d,0xfb] + cfcmovgeq %r19, %r23, %r27 + +# CHECK: cfcmovgeq %r19, %r23 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x4d,0xdf] + cfcmovgeq %r19, %r23 + +# CHECK: cfcmovgeq %r19, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x4d,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovgeq %r19, 291(%r28,%r29,4) + +# CHECK: cfcmovgew 291(%r28,%r29,4), %r17w, %r21w +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x4d,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovgew 291(%r28,%r29,4), %r17w, %r21w + +# CHECK: cfcmovgew 291(%r28,%r29,4), %r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x4d,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovgew 291(%r28,%r29,4), %r17w + +# CHECK: cfcmovgel 291(%r28,%r29,4), %r18d, %r22d +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x4d,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovgel 291(%r28,%r29,4), %r18d, %r22d + +# CHECK: cfcmovgel 291(%r28,%r29,4), %r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x4d,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovgel 291(%r28,%r29,4), %r18d + +# CHECK: cfcmovgeq 291(%r28,%r29,4), %r19, %r23 +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x4d,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovgeq 291(%r28,%r29,4), %r19, %r23 + +# CHECK: cfcmovgeq 291(%r28,%r29,4), %r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x4d,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovgeq 291(%r28,%r29,4), %r19 + +# CHECK: cfcmovnow %r17w, %r21w, %r25w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x41,0xe9] + cfcmovnow %r17w, %r21w, %r25w + +# CHECK: cfcmovnow %r17w, %r21w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x41,0xcd] + cfcmovnow %r17w, %r21w + +# CHECK: cfcmovnow %r17w, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x41,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovnow %r17w, 291(%r28,%r29,4) + +# CHECK: cfcmovnol %r18d, %r22d, %r26d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x41,0xf2] + cfcmovnol %r18d, %r22d, %r26d + +# CHECK: cfcmovnol %r18d, %r22d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x41,0xd6] + cfcmovnol %r18d, %r22d + +# CHECK: cfcmovnol %r18d, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x41,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovnol %r18d, 291(%r28,%r29,4) + +# CHECK: cfcmovnoq %r19, %r23, %r27 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x41,0xfb] + cfcmovnoq %r19, %r23, %r27 + +# CHECK: cfcmovnoq %r19, %r23 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x41,0xdf] + cfcmovnoq %r19, %r23 + +# CHECK: cfcmovnoq %r19, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x41,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovnoq %r19, 291(%r28,%r29,4) + +# CHECK: cfcmovnow 291(%r28,%r29,4), %r17w, %r21w +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x41,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovnow 291(%r28,%r29,4), %r17w, %r21w + +# CHECK: cfcmovnow 291(%r28,%r29,4), %r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x41,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovnow 291(%r28,%r29,4), %r17w + +# CHECK: cfcmovnol 291(%r28,%r29,4), %r18d, %r22d +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x41,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovnol 291(%r28,%r29,4), %r18d, %r22d + +# CHECK: cfcmovnol 291(%r28,%r29,4), %r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x41,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovnol 291(%r28,%r29,4), %r18d + +# CHECK: cfcmovnoq 291(%r28,%r29,4), %r19, %r23 +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x41,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovnoq 291(%r28,%r29,4), %r19, %r23 + +# CHECK: cfcmovnoq 291(%r28,%r29,4), %r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x41,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovnoq 291(%r28,%r29,4), %r19 + +# CHECK: cfcmovnpw %r17w, %r21w, %r25w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x4b,0xe9] + cfcmovnpw %r17w, %r21w, %r25w + +# CHECK: cfcmovnpw %r17w, %r21w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x4b,0xcd] + cfcmovnpw %r17w, %r21w + +# CHECK: cfcmovnpw %r17w, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x4b,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovnpw %r17w, 291(%r28,%r29,4) + +# CHECK: cfcmovnpl %r18d, %r22d, %r26d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x4b,0xf2] + cfcmovnpl %r18d, %r22d, %r26d + +# CHECK: cfcmovnpl %r18d, %r22d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x4b,0xd6] + cfcmovnpl %r18d, %r22d + +# CHECK: cfcmovnpl %r18d, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x4b,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovnpl %r18d, 291(%r28,%r29,4) + +# CHECK: cfcmovnpq %r19, %r23, %r27 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x4b,0xfb] + cfcmovnpq %r19, %r23, %r27 + +# CHECK: cfcmovnpq %r19, %r23 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x4b,0xdf] + cfcmovnpq %r19, %r23 + +# CHECK: cfcmovnpq %r19, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x4b,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovnpq %r19, 291(%r28,%r29,4) + +# CHECK: cfcmovnpw 291(%r28,%r29,4), %r17w, %r21w +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x4b,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovnpw 291(%r28,%r29,4), %r17w, %r21w + +# CHECK: cfcmovnpw 291(%r28,%r29,4), %r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x4b,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovnpw 291(%r28,%r29,4), %r17w + +# CHECK: cfcmovnpl 291(%r28,%r29,4), %r18d, %r22d +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x4b,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovnpl 291(%r28,%r29,4), %r18d, %r22d + +# CHECK: cfcmovnpl 291(%r28,%r29,4), %r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x4b,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovnpl 291(%r28,%r29,4), %r18d + +# CHECK: cfcmovnpq 291(%r28,%r29,4), %r19, %r23 +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x4b,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovnpq 291(%r28,%r29,4), %r19, %r23 + +# CHECK: cfcmovnpq 291(%r28,%r29,4), %r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x4b,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovnpq 291(%r28,%r29,4), %r19 + +# CHECK: cfcmovnsw %r17w, %r21w, %r25w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x49,0xe9] + cfcmovnsw %r17w, %r21w, %r25w + +# CHECK: cfcmovnsw %r17w, %r21w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x49,0xcd] + cfcmovnsw %r17w, %r21w + +# CHECK: cfcmovnsw %r17w, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x49,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovnsw %r17w, 291(%r28,%r29,4) + +# CHECK: cfcmovnsl %r18d, %r22d, %r26d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x49,0xf2] + cfcmovnsl %r18d, %r22d, %r26d + +# CHECK: cfcmovnsl %r18d, %r22d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x49,0xd6] + cfcmovnsl %r18d, %r22d + +# CHECK: cfcmovnsl %r18d, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x49,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovnsl %r18d, 291(%r28,%r29,4) + +# CHECK: cfcmovnsq %r19, %r23, %r27 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x49,0xfb] + cfcmovnsq %r19, %r23, %r27 + +# CHECK: cfcmovnsq %r19, %r23 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x49,0xdf] + cfcmovnsq %r19, %r23 + +# CHECK: cfcmovnsq %r19, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x49,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovnsq %r19, 291(%r28,%r29,4) + +# CHECK: cfcmovnsw 291(%r28,%r29,4), %r17w, %r21w +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x49,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovnsw 291(%r28,%r29,4), %r17w, %r21w + +# CHECK: cfcmovnsw 291(%r28,%r29,4), %r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x49,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovnsw 291(%r28,%r29,4), %r17w + +# CHECK: cfcmovnsl 291(%r28,%r29,4), %r18d, %r22d +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x49,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovnsl 291(%r28,%r29,4), %r18d, %r22d + +# CHECK: cfcmovnsl 291(%r28,%r29,4), %r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x49,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovnsl 291(%r28,%r29,4), %r18d + +# CHECK: cfcmovnsq 291(%r28,%r29,4), %r19, %r23 +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x49,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovnsq 291(%r28,%r29,4), %r19, %r23 + +# CHECK: cfcmovnsq 291(%r28,%r29,4), %r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x49,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovnsq 291(%r28,%r29,4), %r19 + +# CHECK: cfcmovnew %r17w, %r21w, %r25w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x45,0xe9] + cfcmovnew %r17w, %r21w, %r25w + +# CHECK: cfcmovnew %r17w, %r21w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x45,0xcd] + cfcmovnew %r17w, %r21w + +# CHECK: cfcmovnew %r17w, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x45,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovnew %r17w, 291(%r28,%r29,4) + +# CHECK: cfcmovnel %r18d, %r22d, %r26d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x45,0xf2] + cfcmovnel %r18d, %r22d, %r26d + +# CHECK: cfcmovnel %r18d, %r22d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x45,0xd6] + cfcmovnel %r18d, %r22d + +# CHECK: cfcmovnel %r18d, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x45,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovnel %r18d, 291(%r28,%r29,4) + +# CHECK: cfcmovneq %r19, %r23, %r27 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x45,0xfb] + cfcmovneq %r19, %r23, %r27 + +# CHECK: cfcmovneq %r19, %r23 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x45,0xdf] + cfcmovneq %r19, %r23 + +# CHECK: cfcmovneq %r19, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x45,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovneq %r19, 291(%r28,%r29,4) + +# CHECK: cfcmovnew 291(%r28,%r29,4), %r17w, %r21w +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x45,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovnew 291(%r28,%r29,4), %r17w, %r21w + +# CHECK: cfcmovnew 291(%r28,%r29,4), %r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x45,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovnew 291(%r28,%r29,4), %r17w + +# CHECK: cfcmovnel 291(%r28,%r29,4), %r18d, %r22d +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x45,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovnel 291(%r28,%r29,4), %r18d, %r22d + +# CHECK: cfcmovnel 291(%r28,%r29,4), %r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x45,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovnel 291(%r28,%r29,4), %r18d + +# CHECK: cfcmovneq 291(%r28,%r29,4), %r19, %r23 +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x45,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovneq 291(%r28,%r29,4), %r19, %r23 + +# CHECK: cfcmovneq 291(%r28,%r29,4), %r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x45,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovneq 291(%r28,%r29,4), %r19 + +# CHECK: cfcmovpw %r17w, %r21w, %r25w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x4a,0xe9] + cfcmovpw %r17w, %r21w, %r25w + +# CHECK: cfcmovpw %r17w, %r21w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x4a,0xcd] + cfcmovpw %r17w, %r21w + +# CHECK: cfcmovpw %r17w, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x4a,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovpw %r17w, 291(%r28,%r29,4) + +# CHECK: cfcmovpl %r18d, %r22d, %r26d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x4a,0xf2] + cfcmovpl %r18d, %r22d, %r26d + +# CHECK: cfcmovpl %r18d, %r22d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x4a,0xd6] + cfcmovpl %r18d, %r22d + +# CHECK: cfcmovpl %r18d, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x4a,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovpl %r18d, 291(%r28,%r29,4) + +# CHECK: cfcmovpq %r19, %r23, %r27 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x4a,0xfb] + cfcmovpq %r19, %r23, %r27 + +# CHECK: cfcmovpq %r19, %r23 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x4a,0xdf] + cfcmovpq %r19, %r23 + +# CHECK: cfcmovpq %r19, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x4a,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovpq %r19, 291(%r28,%r29,4) + +# CHECK: cfcmovpw 291(%r28,%r29,4), %r17w, %r21w +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x4a,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovpw 291(%r28,%r29,4), %r17w, %r21w + +# CHECK: cfcmovpw 291(%r28,%r29,4), %r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x4a,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovpw 291(%r28,%r29,4), %r17w + +# CHECK: cfcmovpl 291(%r28,%r29,4), %r18d, %r22d +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x4a,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovpl 291(%r28,%r29,4), %r18d, %r22d + +# CHECK: cfcmovpl 291(%r28,%r29,4), %r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x4a,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovpl 291(%r28,%r29,4), %r18d + +# CHECK: cfcmovpq 291(%r28,%r29,4), %r19, %r23 +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x4a,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovpq 291(%r28,%r29,4), %r19, %r23 + +# CHECK: cfcmovpq 291(%r28,%r29,4), %r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x4a,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovpq 291(%r28,%r29,4), %r19 + +# CHECK: cfcmovsw %r17w, %r21w, %r25w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x48,0xe9] + cfcmovsw %r17w, %r21w, %r25w + +# CHECK: cfcmovsw %r17w, %r21w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x48,0xcd] + cfcmovsw %r17w, %r21w + +# CHECK: cfcmovsw %r17w, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x48,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovsw %r17w, 291(%r28,%r29,4) + +# CHECK: cfcmovsl %r18d, %r22d, %r26d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x48,0xf2] + cfcmovsl %r18d, %r22d, %r26d + +# CHECK: cfcmovsl %r18d, %r22d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x48,0xd6] + cfcmovsl %r18d, %r22d + +# CHECK: cfcmovsl %r18d, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x48,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovsl %r18d, 291(%r28,%r29,4) + +# CHECK: cfcmovsq %r19, %r23, %r27 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x48,0xfb] + cfcmovsq %r19, %r23, %r27 + +# CHECK: cfcmovsq %r19, %r23 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x48,0xdf] + cfcmovsq %r19, %r23 + +# CHECK: cfcmovsq %r19, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x48,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovsq %r19, 291(%r28,%r29,4) + +# CHECK: cfcmovsw 291(%r28,%r29,4), %r17w, %r21w +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x48,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovsw 291(%r28,%r29,4), %r17w, %r21w + +# CHECK: cfcmovsw 291(%r28,%r29,4), %r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x48,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovsw 291(%r28,%r29,4), %r17w + +# CHECK: cfcmovsl 291(%r28,%r29,4), %r18d, %r22d +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x48,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovsl 291(%r28,%r29,4), %r18d, %r22d + +# CHECK: cfcmovsl 291(%r28,%r29,4), %r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x48,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovsl 291(%r28,%r29,4), %r18d + +# CHECK: cfcmovsq 291(%r28,%r29,4), %r19, %r23 +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x48,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovsq 291(%r28,%r29,4), %r19, %r23 + +# CHECK: cfcmovsq 291(%r28,%r29,4), %r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x48,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovsq 291(%r28,%r29,4), %r19 + +# CHECK: cfcmovew %r17w, %r21w, %r25w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x44,0xe9] + cfcmovew %r17w, %r21w, %r25w + +# CHECK: cfcmovew %r17w, %r21w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x44,0xcd] + cfcmovew %r17w, %r21w + +# CHECK: cfcmovew %r17w, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x44,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovew %r17w, 291(%r28,%r29,4) + +# CHECK: cfcmovel %r18d, %r22d, %r26d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x44,0xf2] + cfcmovel %r18d, %r22d, %r26d + +# CHECK: cfcmovel %r18d, %r22d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x44,0xd6] + cfcmovel %r18d, %r22d + +# CHECK: cfcmovel %r18d, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x44,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovel %r18d, 291(%r28,%r29,4) + +# CHECK: cfcmoveq %r19, %r23, %r27 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x44,0xfb] + cfcmoveq %r19, %r23, %r27 + +# CHECK: cfcmoveq %r19, %r23 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x44,0xdf] + cfcmoveq %r19, %r23 + +# CHECK: cfcmoveq %r19, 291(%r28,%r29,4) +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x44,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmoveq %r19, 291(%r28,%r29,4) + +# CHECK: cfcmovew 291(%r28,%r29,4), %r17w, %r21w +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x44,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovew 291(%r28,%r29,4), %r17w, %r21w + +# CHECK: cfcmovew 291(%r28,%r29,4), %r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x44,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovew 291(%r28,%r29,4), %r17w + +# CHECK: cfcmovel 291(%r28,%r29,4), %r18d, %r22d +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x44,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovel 291(%r28,%r29,4), %r18d, %r22d + +# CHECK: cfcmovel 291(%r28,%r29,4), %r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x44,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovel 291(%r28,%r29,4), %r18d + +# CHECK: cfcmoveq 291(%r28,%r29,4), %r19, %r23 +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x44,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmoveq 291(%r28,%r29,4), %r19, %r23 + +# CHECK: cfcmoveq 291(%r28,%r29,4), %r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x44,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmoveq 291(%r28,%r29,4), %r19 diff --git a/llvm/test/MC/X86/apx/cfcmov-intel.s b/llvm/test/MC/X86/apx/cfcmov-intel.s new file mode 100644 index 0000000000000000000000000000000000000000..58b145d7fef2e5b8c28c921bb4cf89837c8a15c0 --- /dev/null +++ b/llvm/test/MC/X86/apx/cfcmov-intel.s @@ -0,0 +1,841 @@ +# RUN: llvm-mc -triple x86_64 -x86-asm-syntax=intel -output-asm-variant=1 --show-encoding %s | FileCheck %s + +# CHECK: cfcmovb r25w, r21w, r17w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x42,0xe9] + cfcmovb r25w, r21w, r17w + +# CHECK: cfcmovb r21w, r17w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x42,0xcd] + cfcmovb r21w, r17w + +# CHECK: cfcmovb word ptr [r28 + 4*r29 + 291], r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x42,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovb word ptr [r28 + 4*r29 + 291], r17w + +# CHECK: cfcmovb r26d, r22d, r18d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x42,0xf2] + cfcmovb r26d, r22d, r18d + +# CHECK: cfcmovb r22d, r18d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x42,0xd6] + cfcmovb r22d, r18d + +# CHECK: cfcmovb dword ptr [r28 + 4*r29 + 291], r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x42,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovb dword ptr [r28 + 4*r29 + 291], r18d + +# CHECK: cfcmovb r27, r23, r19 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x42,0xfb] + cfcmovb r27, r23, r19 + +# CHECK: cfcmovb r23, r19 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x42,0xdf] + cfcmovb r23, r19 + +# CHECK: cfcmovb qword ptr [r28 + 4*r29 + 291], r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x42,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovb qword ptr [r28 + 4*r29 + 291], r19 + +# CHECK: cfcmovb r21w, r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x42,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovb r21w, r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovb r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x42,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovb r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovb r22d, r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x42,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovb r22d, r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovb r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x42,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovb r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovb r23, r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x42,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovb r23, r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovb r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x42,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovb r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovbe r25w, r21w, r17w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x46,0xe9] + cfcmovbe r25w, r21w, r17w + +# CHECK: cfcmovbe r21w, r17w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x46,0xcd] + cfcmovbe r21w, r17w + +# CHECK: cfcmovbe word ptr [r28 + 4*r29 + 291], r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x46,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovbe word ptr [r28 + 4*r29 + 291], r17w + +# CHECK: cfcmovbe r26d, r22d, r18d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x46,0xf2] + cfcmovbe r26d, r22d, r18d + +# CHECK: cfcmovbe r22d, r18d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x46,0xd6] + cfcmovbe r22d, r18d + +# CHECK: cfcmovbe dword ptr [r28 + 4*r29 + 291], r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x46,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovbe dword ptr [r28 + 4*r29 + 291], r18d + +# CHECK: cfcmovbe r27, r23, r19 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x46,0xfb] + cfcmovbe r27, r23, r19 + +# CHECK: cfcmovbe r23, r19 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x46,0xdf] + cfcmovbe r23, r19 + +# CHECK: cfcmovbe qword ptr [r28 + 4*r29 + 291], r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x46,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovbe qword ptr [r28 + 4*r29 + 291], r19 + +# CHECK: cfcmovbe r21w, r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x46,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovbe r21w, r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovbe r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x46,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovbe r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovbe r22d, r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x46,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovbe r22d, r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovbe r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x46,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovbe r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovbe r23, r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x46,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovbe r23, r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovbe r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x46,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovbe r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovl r25w, r21w, r17w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x4c,0xe9] + cfcmovl r25w, r21w, r17w + +# CHECK: cfcmovl r21w, r17w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x4c,0xcd] + cfcmovl r21w, r17w + +# CHECK: cfcmovl word ptr [r28 + 4*r29 + 291], r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x4c,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovl word ptr [r28 + 4*r29 + 291], r17w + +# CHECK: cfcmovl r26d, r22d, r18d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x4c,0xf2] + cfcmovl r26d, r22d, r18d + +# CHECK: cfcmovl r22d, r18d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x4c,0xd6] + cfcmovl r22d, r18d + +# CHECK: cfcmovl dword ptr [r28 + 4*r29 + 291], r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x4c,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovl dword ptr [r28 + 4*r29 + 291], r18d + +# CHECK: cfcmovl r27, r23, r19 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x4c,0xfb] + cfcmovl r27, r23, r19 + +# CHECK: cfcmovl r23, r19 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x4c,0xdf] + cfcmovl r23, r19 + +# CHECK: cfcmovl qword ptr [r28 + 4*r29 + 291], r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x4c,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovl qword ptr [r28 + 4*r29 + 291], r19 + +# CHECK: cfcmovl r21w, r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x4c,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovl r21w, r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovl r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x4c,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovl r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovl r22d, r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x4c,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovl r22d, r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovl r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x4c,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovl r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovl r23, r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x4c,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovl r23, r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovl r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x4c,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovl r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovle r25w, r21w, r17w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x4e,0xe9] + cfcmovle r25w, r21w, r17w + +# CHECK: cfcmovle r21w, r17w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x4e,0xcd] + cfcmovle r21w, r17w + +# CHECK: cfcmovle word ptr [r28 + 4*r29 + 291], r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x4e,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovle word ptr [r28 + 4*r29 + 291], r17w + +# CHECK: cfcmovle r26d, r22d, r18d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x4e,0xf2] + cfcmovle r26d, r22d, r18d + +# CHECK: cfcmovle r22d, r18d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x4e,0xd6] + cfcmovle r22d, r18d + +# CHECK: cfcmovle dword ptr [r28 + 4*r29 + 291], r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x4e,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovle dword ptr [r28 + 4*r29 + 291], r18d + +# CHECK: cfcmovle r27, r23, r19 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x4e,0xfb] + cfcmovle r27, r23, r19 + +# CHECK: cfcmovle r23, r19 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x4e,0xdf] + cfcmovle r23, r19 + +# CHECK: cfcmovle qword ptr [r28 + 4*r29 + 291], r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x4e,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovle qword ptr [r28 + 4*r29 + 291], r19 + +# CHECK: cfcmovle r21w, r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x4e,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovle r21w, r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovle r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x4e,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovle r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovle r22d, r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x4e,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovle r22d, r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovle r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x4e,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovle r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovle r23, r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x4e,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovle r23, r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovle r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x4e,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovle r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovae r25w, r21w, r17w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x43,0xe9] + cfcmovae r25w, r21w, r17w + +# CHECK: cfcmovae r21w, r17w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x43,0xcd] + cfcmovae r21w, r17w + +# CHECK: cfcmovae word ptr [r28 + 4*r29 + 291], r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x43,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovae word ptr [r28 + 4*r29 + 291], r17w + +# CHECK: cfcmovae r26d, r22d, r18d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x43,0xf2] + cfcmovae r26d, r22d, r18d + +# CHECK: cfcmovae r22d, r18d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x43,0xd6] + cfcmovae r22d, r18d + +# CHECK: cfcmovae dword ptr [r28 + 4*r29 + 291], r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x43,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovae dword ptr [r28 + 4*r29 + 291], r18d + +# CHECK: cfcmovae r27, r23, r19 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x43,0xfb] + cfcmovae r27, r23, r19 + +# CHECK: cfcmovae r23, r19 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x43,0xdf] + cfcmovae r23, r19 + +# CHECK: cfcmovae qword ptr [r28 + 4*r29 + 291], r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x43,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovae qword ptr [r28 + 4*r29 + 291], r19 + +# CHECK: cfcmovae r21w, r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x43,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovae r21w, r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovae r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x43,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovae r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovae r22d, r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x43,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovae r22d, r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovae r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x43,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovae r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovae r23, r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x43,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovae r23, r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovae r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x43,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovae r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmova r25w, r21w, r17w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x47,0xe9] + cfcmova r25w, r21w, r17w + +# CHECK: cfcmova r21w, r17w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x47,0xcd] + cfcmova r21w, r17w + +# CHECK: cfcmova word ptr [r28 + 4*r29 + 291], r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x47,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmova word ptr [r28 + 4*r29 + 291], r17w + +# CHECK: cfcmova r26d, r22d, r18d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x47,0xf2] + cfcmova r26d, r22d, r18d + +# CHECK: cfcmova r22d, r18d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x47,0xd6] + cfcmova r22d, r18d + +# CHECK: cfcmova dword ptr [r28 + 4*r29 + 291], r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x47,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmova dword ptr [r28 + 4*r29 + 291], r18d + +# CHECK: cfcmova r27, r23, r19 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x47,0xfb] + cfcmova r27, r23, r19 + +# CHECK: cfcmova r23, r19 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x47,0xdf] + cfcmova r23, r19 + +# CHECK: cfcmova qword ptr [r28 + 4*r29 + 291], r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x47,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmova qword ptr [r28 + 4*r29 + 291], r19 + +# CHECK: cfcmova r21w, r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x47,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmova r21w, r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmova r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x47,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmova r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmova r22d, r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x47,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmova r22d, r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmova r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x47,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmova r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmova r23, r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x47,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmova r23, r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmova r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x47,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmova r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovge r25w, r21w, r17w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x4d,0xe9] + cfcmovge r25w, r21w, r17w + +# CHECK: cfcmovge r21w, r17w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x4d,0xcd] + cfcmovge r21w, r17w + +# CHECK: cfcmovge word ptr [r28 + 4*r29 + 291], r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x4d,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovge word ptr [r28 + 4*r29 + 291], r17w + +# CHECK: cfcmovge r26d, r22d, r18d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x4d,0xf2] + cfcmovge r26d, r22d, r18d + +# CHECK: cfcmovge r22d, r18d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x4d,0xd6] + cfcmovge r22d, r18d + +# CHECK: cfcmovge dword ptr [r28 + 4*r29 + 291], r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x4d,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovge dword ptr [r28 + 4*r29 + 291], r18d + +# CHECK: cfcmovge r27, r23, r19 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x4d,0xfb] + cfcmovge r27, r23, r19 + +# CHECK: cfcmovge r23, r19 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x4d,0xdf] + cfcmovge r23, r19 + +# CHECK: cfcmovge qword ptr [r28 + 4*r29 + 291], r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x4d,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovge qword ptr [r28 + 4*r29 + 291], r19 + +# CHECK: cfcmovge r21w, r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x4d,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovge r21w, r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovge r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x4d,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovge r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovge r22d, r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x4d,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovge r22d, r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovge r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x4d,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovge r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovge r23, r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x4d,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovge r23, r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovge r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x4d,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovge r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovno r25w, r21w, r17w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x41,0xe9] + cfcmovno r25w, r21w, r17w + +# CHECK: cfcmovno r21w, r17w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x41,0xcd] + cfcmovno r21w, r17w + +# CHECK: cfcmovno word ptr [r28 + 4*r29 + 291], r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x41,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovno word ptr [r28 + 4*r29 + 291], r17w + +# CHECK: cfcmovno r26d, r22d, r18d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x41,0xf2] + cfcmovno r26d, r22d, r18d + +# CHECK: cfcmovno r22d, r18d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x41,0xd6] + cfcmovno r22d, r18d + +# CHECK: cfcmovno dword ptr [r28 + 4*r29 + 291], r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x41,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovno dword ptr [r28 + 4*r29 + 291], r18d + +# CHECK: cfcmovno r27, r23, r19 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x41,0xfb] + cfcmovno r27, r23, r19 + +# CHECK: cfcmovno r23, r19 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x41,0xdf] + cfcmovno r23, r19 + +# CHECK: cfcmovno qword ptr [r28 + 4*r29 + 291], r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x41,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovno qword ptr [r28 + 4*r29 + 291], r19 + +# CHECK: cfcmovno r21w, r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x41,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovno r21w, r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovno r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x41,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovno r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovno r22d, r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x41,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovno r22d, r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovno r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x41,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovno r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovno r23, r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x41,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovno r23, r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovno r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x41,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovno r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovnp r25w, r21w, r17w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x4b,0xe9] + cfcmovnp r25w, r21w, r17w + +# CHECK: cfcmovnp r21w, r17w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x4b,0xcd] + cfcmovnp r21w, r17w + +# CHECK: cfcmovnp word ptr [r28 + 4*r29 + 291], r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x4b,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovnp word ptr [r28 + 4*r29 + 291], r17w + +# CHECK: cfcmovnp r26d, r22d, r18d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x4b,0xf2] + cfcmovnp r26d, r22d, r18d + +# CHECK: cfcmovnp r22d, r18d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x4b,0xd6] + cfcmovnp r22d, r18d + +# CHECK: cfcmovnp dword ptr [r28 + 4*r29 + 291], r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x4b,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovnp dword ptr [r28 + 4*r29 + 291], r18d + +# CHECK: cfcmovnp r27, r23, r19 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x4b,0xfb] + cfcmovnp r27, r23, r19 + +# CHECK: cfcmovnp r23, r19 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x4b,0xdf] + cfcmovnp r23, r19 + +# CHECK: cfcmovnp qword ptr [r28 + 4*r29 + 291], r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x4b,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovnp qword ptr [r28 + 4*r29 + 291], r19 + +# CHECK: cfcmovnp r21w, r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x4b,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovnp r21w, r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovnp r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x4b,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovnp r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovnp r22d, r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x4b,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovnp r22d, r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovnp r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x4b,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovnp r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovnp r23, r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x4b,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovnp r23, r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovnp r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x4b,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovnp r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovns r25w, r21w, r17w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x49,0xe9] + cfcmovns r25w, r21w, r17w + +# CHECK: cfcmovns r21w, r17w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x49,0xcd] + cfcmovns r21w, r17w + +# CHECK: cfcmovns word ptr [r28 + 4*r29 + 291], r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x49,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovns word ptr [r28 + 4*r29 + 291], r17w + +# CHECK: cfcmovns r26d, r22d, r18d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x49,0xf2] + cfcmovns r26d, r22d, r18d + +# CHECK: cfcmovns r22d, r18d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x49,0xd6] + cfcmovns r22d, r18d + +# CHECK: cfcmovns dword ptr [r28 + 4*r29 + 291], r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x49,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovns dword ptr [r28 + 4*r29 + 291], r18d + +# CHECK: cfcmovns r27, r23, r19 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x49,0xfb] + cfcmovns r27, r23, r19 + +# CHECK: cfcmovns r23, r19 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x49,0xdf] + cfcmovns r23, r19 + +# CHECK: cfcmovns qword ptr [r28 + 4*r29 + 291], r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x49,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovns qword ptr [r28 + 4*r29 + 291], r19 + +# CHECK: cfcmovns r21w, r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x49,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovns r21w, r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovns r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x49,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovns r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovns r22d, r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x49,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovns r22d, r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovns r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x49,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovns r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovns r23, r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x49,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovns r23, r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovns r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x49,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovns r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovne r25w, r21w, r17w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x45,0xe9] + cfcmovne r25w, r21w, r17w + +# CHECK: cfcmovne r21w, r17w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x45,0xcd] + cfcmovne r21w, r17w + +# CHECK: cfcmovne word ptr [r28 + 4*r29 + 291], r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x45,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovne word ptr [r28 + 4*r29 + 291], r17w + +# CHECK: cfcmovne r26d, r22d, r18d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x45,0xf2] + cfcmovne r26d, r22d, r18d + +# CHECK: cfcmovne r22d, r18d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x45,0xd6] + cfcmovne r22d, r18d + +# CHECK: cfcmovne dword ptr [r28 + 4*r29 + 291], r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x45,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovne dword ptr [r28 + 4*r29 + 291], r18d + +# CHECK: cfcmovne r27, r23, r19 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x45,0xfb] + cfcmovne r27, r23, r19 + +# CHECK: cfcmovne r23, r19 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x45,0xdf] + cfcmovne r23, r19 + +# CHECK: cfcmovne qword ptr [r28 + 4*r29 + 291], r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x45,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovne qword ptr [r28 + 4*r29 + 291], r19 + +# CHECK: cfcmovne r21w, r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x45,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovne r21w, r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovne r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x45,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovne r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovne r22d, r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x45,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovne r22d, r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovne r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x45,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovne r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovne r23, r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x45,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovne r23, r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovne r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x45,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovne r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovp r25w, r21w, r17w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x4a,0xe9] + cfcmovp r25w, r21w, r17w + +# CHECK: cfcmovp r21w, r17w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x4a,0xcd] + cfcmovp r21w, r17w + +# CHECK: cfcmovp word ptr [r28 + 4*r29 + 291], r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x4a,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovp word ptr [r28 + 4*r29 + 291], r17w + +# CHECK: cfcmovp r26d, r22d, r18d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x4a,0xf2] + cfcmovp r26d, r22d, r18d + +# CHECK: cfcmovp r22d, r18d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x4a,0xd6] + cfcmovp r22d, r18d + +# CHECK: cfcmovp dword ptr [r28 + 4*r29 + 291], r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x4a,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovp dword ptr [r28 + 4*r29 + 291], r18d + +# CHECK: cfcmovp r27, r23, r19 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x4a,0xfb] + cfcmovp r27, r23, r19 + +# CHECK: cfcmovp r23, r19 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x4a,0xdf] + cfcmovp r23, r19 + +# CHECK: cfcmovp qword ptr [r28 + 4*r29 + 291], r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x4a,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovp qword ptr [r28 + 4*r29 + 291], r19 + +# CHECK: cfcmovp r21w, r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x4a,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovp r21w, r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovp r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x4a,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovp r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovp r22d, r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x4a,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovp r22d, r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovp r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x4a,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovp r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovp r23, r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x4a,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovp r23, r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovp r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x4a,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovp r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovs r25w, r21w, r17w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x48,0xe9] + cfcmovs r25w, r21w, r17w + +# CHECK: cfcmovs r21w, r17w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x48,0xcd] + cfcmovs r21w, r17w + +# CHECK: cfcmovs word ptr [r28 + 4*r29 + 291], r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x48,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovs word ptr [r28 + 4*r29 + 291], r17w + +# CHECK: cfcmovs r26d, r22d, r18d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x48,0xf2] + cfcmovs r26d, r22d, r18d + +# CHECK: cfcmovs r22d, r18d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x48,0xd6] + cfcmovs r22d, r18d + +# CHECK: cfcmovs dword ptr [r28 + 4*r29 + 291], r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x48,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovs dword ptr [r28 + 4*r29 + 291], r18d + +# CHECK: cfcmovs r27, r23, r19 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x48,0xfb] + cfcmovs r27, r23, r19 + +# CHECK: cfcmovs r23, r19 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x48,0xdf] + cfcmovs r23, r19 + +# CHECK: cfcmovs qword ptr [r28 + 4*r29 + 291], r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x48,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovs qword ptr [r28 + 4*r29 + 291], r19 + +# CHECK: cfcmovs r21w, r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x48,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovs r21w, r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovs r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x48,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmovs r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovs r22d, r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x48,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovs r22d, r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovs r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x48,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmovs r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovs r23, r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x48,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovs r23, r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmovs r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x48,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmovs r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmove r25w, r21w, r17w +# CHECK: encoding: [0x62,0xec,0x35,0x14,0x44,0xe9] + cfcmove r25w, r21w, r17w + +# CHECK: cfcmove r21w, r17w +# CHECK: encoding: [0x62,0xec,0x7d,0x0c,0x44,0xcd] + cfcmove r21w, r17w + +# CHECK: cfcmove word ptr [r28 + 4*r29 + 291], r17w +# CHECK: encoding: [0x62,0x8c,0x79,0x0c,0x44,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmove word ptr [r28 + 4*r29 + 291], r17w + +# CHECK: cfcmove r26d, r22d, r18d +# CHECK: encoding: [0x62,0xec,0x2c,0x14,0x44,0xf2] + cfcmove r26d, r22d, r18d + +# CHECK: cfcmove r22d, r18d +# CHECK: encoding: [0x62,0xec,0x7c,0x0c,0x44,0xd6] + cfcmove r22d, r18d + +# CHECK: cfcmove dword ptr [r28 + 4*r29 + 291], r18d +# CHECK: encoding: [0x62,0x8c,0x78,0x0c,0x44,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmove dword ptr [r28 + 4*r29 + 291], r18d + +# CHECK: cfcmove r27, r23, r19 +# CHECK: encoding: [0x62,0xec,0xa4,0x14,0x44,0xfb] + cfcmove r27, r23, r19 + +# CHECK: cfcmove r23, r19 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x44,0xdf] + cfcmove r23, r19 + +# CHECK: cfcmove qword ptr [r28 + 4*r29 + 291], r19 +# CHECK: encoding: [0x62,0x8c,0xf8,0x0c,0x44,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmove qword ptr [r28 + 4*r29 + 291], r19 + +# CHECK: cfcmove r21w, r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x51,0x14,0x44,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmove r21w, r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmove r17w, word ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x79,0x08,0x44,0x8c,0xac,0x23,0x01,0x00,0x00] + cfcmove r17w, word ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmove r22d, r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x48,0x14,0x44,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmove r22d, r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmove r18d, dword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0x78,0x08,0x44,0x94,0xac,0x23,0x01,0x00,0x00] + cfcmove r18d, dword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmove r23, r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xc0,0x14,0x44,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmove r23, r19, qword ptr [r28 + 4*r29 + 291] + +# CHECK: cfcmove r19, qword ptr [r28 + 4*r29 + 291] +# CHECK: encoding: [0x62,0x8c,0xf8,0x08,0x44,0x9c,0xac,0x23,0x01,0x00,0x00] + cfcmove r19, qword ptr [r28 + 4*r29 + 291] diff --git a/llvm/test/MC/X86/apx/cmov-att.s b/llvm/test/MC/X86/apx/cmov-att.s new file mode 100644 index 0000000000000000000000000000000000000000..4b8e6786d80159aecae49a50966732750ec790e2 --- /dev/null +++ b/llvm/test/MC/X86/apx/cmov-att.s @@ -0,0 +1,293 @@ +# RUN: llvm-mc -triple x86_64 -show-encoding %s | FileCheck %s +# RUN: not llvm-mc -triple i386 -show-encoding %s 2>&1 | FileCheck %s --check-prefix=ERROR + +# ERROR-COUNT-96: error: +# ERROR-NOT: error: +# CHECK: cmovbw %dx, %ax, %r9w +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x42,0xc2] + cmovbw %dx, %ax, %r9w +# CHECK: cmovbl %ecx, %edx, %r10d +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x42,0xd1] + cmovbl %ecx, %edx, %r10d +# CHECK: cmovbq %r9, %r15, %r11 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x42,0xf9] + cmovbq %r9, %r15, %r11 +# CHECK: cmovbw 123(%r8,%rax,4), %dx, %ax +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x42,0x54,0x80,0x7b] + cmovbw 123(%r8,%rax,4), %dx, %ax +# CHECK: cmovbl 123(%r8,%rax,4), %ecx, %edx +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x42,0x4c,0x80,0x7b] + cmovbl 123(%r8,%rax,4), %ecx, %edx +# CHECK: cmovbq 123(%r8,%rax,4), %r9, %r15 +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x42,0x4c,0x80,0x7b] + cmovbq 123(%r8,%rax,4), %r9, %r15 +# CHECK: cmovbew %dx, %ax, %r9w +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x46,0xc2] + cmovbew %dx, %ax, %r9w +# CHECK: cmovbel %ecx, %edx, %r10d +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x46,0xd1] + cmovbel %ecx, %edx, %r10d +# CHECK: cmovbeq %r9, %r15, %r11 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x46,0xf9] + cmovbeq %r9, %r15, %r11 +# CHECK: cmovbew 123(%r8,%rax,4), %dx, %ax +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x46,0x54,0x80,0x7b] + cmovbew 123(%r8,%rax,4), %dx, %ax +# CHECK: cmovbel 123(%r8,%rax,4), %ecx, %edx +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x46,0x4c,0x80,0x7b] + cmovbel 123(%r8,%rax,4), %ecx, %edx +# CHECK: cmovbeq 123(%r8,%rax,4), %r9, %r15 +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x46,0x4c,0x80,0x7b] + cmovbeq 123(%r8,%rax,4), %r9, %r15 +# CHECK: cmovlw %dx, %ax, %r9w +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x4c,0xc2] + cmovlw %dx, %ax, %r9w +# CHECK: cmovll %ecx, %edx, %r10d +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x4c,0xd1] + cmovll %ecx, %edx, %r10d +# CHECK: cmovlq %r9, %r15, %r11 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x4c,0xf9] + cmovlq %r9, %r15, %r11 +# CHECK: cmovlw 123(%r8,%rax,4), %dx, %ax +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x4c,0x54,0x80,0x7b] + cmovlw 123(%r8,%rax,4), %dx, %ax +# CHECK: cmovll 123(%r8,%rax,4), %ecx, %edx +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x4c,0x4c,0x80,0x7b] + cmovll 123(%r8,%rax,4), %ecx, %edx +# CHECK: cmovlq 123(%r8,%rax,4), %r9, %r15 +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x4c,0x4c,0x80,0x7b] + cmovlq 123(%r8,%rax,4), %r9, %r15 +# CHECK: cmovlew %dx, %ax, %r9w +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x4e,0xc2] + cmovlew %dx, %ax, %r9w +# CHECK: cmovlel %ecx, %edx, %r10d +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x4e,0xd1] + cmovlel %ecx, %edx, %r10d +# CHECK: cmovleq %r9, %r15, %r11 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x4e,0xf9] + cmovleq %r9, %r15, %r11 +# CHECK: cmovlew 123(%r8,%rax,4), %dx, %ax +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x4e,0x54,0x80,0x7b] + cmovlew 123(%r8,%rax,4), %dx, %ax +# CHECK: cmovlel 123(%r8,%rax,4), %ecx, %edx +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x4e,0x4c,0x80,0x7b] + cmovlel 123(%r8,%rax,4), %ecx, %edx +# CHECK: cmovleq 123(%r8,%rax,4), %r9, %r15 +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x4e,0x4c,0x80,0x7b] + cmovleq 123(%r8,%rax,4), %r9, %r15 +# CHECK: cmovaew %dx, %ax, %r9w +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x43,0xc2] + cmovaew %dx, %ax, %r9w +# CHECK: cmovael %ecx, %edx, %r10d +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x43,0xd1] + cmovael %ecx, %edx, %r10d +# CHECK: cmovaeq %r9, %r15, %r11 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x43,0xf9] + cmovaeq %r9, %r15, %r11 +# CHECK: cmovaew 123(%r8,%rax,4), %dx, %ax +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x43,0x54,0x80,0x7b] + cmovaew 123(%r8,%rax,4), %dx, %ax +# CHECK: cmovael 123(%r8,%rax,4), %ecx, %edx +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x43,0x4c,0x80,0x7b] + cmovael 123(%r8,%rax,4), %ecx, %edx +# CHECK: cmovaeq 123(%r8,%rax,4), %r9, %r15 +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x43,0x4c,0x80,0x7b] + cmovaeq 123(%r8,%rax,4), %r9, %r15 +# CHECK: cmovaw %dx, %ax, %r9w +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x47,0xc2] + cmovaw %dx, %ax, %r9w +# CHECK: cmoval %ecx, %edx, %r10d +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x47,0xd1] + cmoval %ecx, %edx, %r10d +# CHECK: cmovaq %r9, %r15, %r11 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x47,0xf9] + cmovaq %r9, %r15, %r11 +# CHECK: cmovaw 123(%r8,%rax,4), %dx, %ax +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x47,0x54,0x80,0x7b] + cmovaw 123(%r8,%rax,4), %dx, %ax +# CHECK: cmoval 123(%r8,%rax,4), %ecx, %edx +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x47,0x4c,0x80,0x7b] + cmoval 123(%r8,%rax,4), %ecx, %edx +# CHECK: cmovaq 123(%r8,%rax,4), %r9, %r15 +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x47,0x4c,0x80,0x7b] + cmovaq 123(%r8,%rax,4), %r9, %r15 +# CHECK: cmovgew %dx, %ax, %r9w +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x4d,0xc2] + cmovgew %dx, %ax, %r9w +# CHECK: cmovgel %ecx, %edx, %r10d +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x4d,0xd1] + cmovgel %ecx, %edx, %r10d +# CHECK: cmovgeq %r9, %r15, %r11 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x4d,0xf9] + cmovgeq %r9, %r15, %r11 +# CHECK: cmovgew 123(%r8,%rax,4), %dx, %ax +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x4d,0x54,0x80,0x7b] + cmovgew 123(%r8,%rax,4), %dx, %ax +# CHECK: cmovgel 123(%r8,%rax,4), %ecx, %edx +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x4d,0x4c,0x80,0x7b] + cmovgel 123(%r8,%rax,4), %ecx, %edx +# CHECK: cmovgeq 123(%r8,%rax,4), %r9, %r15 +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x4d,0x4c,0x80,0x7b] + cmovgeq 123(%r8,%rax,4), %r9, %r15 +# CHECK: cmovgw %dx, %ax, %r9w +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x4f,0xc2] + cmovgw %dx, %ax, %r9w +# CHECK: cmovgl %ecx, %edx, %r10d +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x4f,0xd1] + cmovgl %ecx, %edx, %r10d +# CHECK: cmovgq %r9, %r15, %r11 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x4f,0xf9] + cmovgq %r9, %r15, %r11 +# CHECK: cmovgw 123(%r8,%rax,4), %dx, %ax +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x4f,0x54,0x80,0x7b] + cmovgw 123(%r8,%rax,4), %dx, %ax +# CHECK: cmovgl 123(%r8,%rax,4), %ecx, %edx +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x4f,0x4c,0x80,0x7b] + cmovgl 123(%r8,%rax,4), %ecx, %edx +# CHECK: cmovgq 123(%r8,%rax,4), %r9, %r15 +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x4f,0x4c,0x80,0x7b] + cmovgq 123(%r8,%rax,4), %r9, %r15 +# CHECK: cmovnow %dx, %ax, %r9w +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x41,0xc2] + cmovnow %dx, %ax, %r9w +# CHECK: cmovnol %ecx, %edx, %r10d +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x41,0xd1] + cmovnol %ecx, %edx, %r10d +# CHECK: cmovnoq %r9, %r15, %r11 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x41,0xf9] + cmovnoq %r9, %r15, %r11 +# CHECK: cmovnow 123(%r8,%rax,4), %dx, %ax +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x41,0x54,0x80,0x7b] + cmovnow 123(%r8,%rax,4), %dx, %ax +# CHECK: cmovnol 123(%r8,%rax,4), %ecx, %edx +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x41,0x4c,0x80,0x7b] + cmovnol 123(%r8,%rax,4), %ecx, %edx +# CHECK: cmovnoq 123(%r8,%rax,4), %r9, %r15 +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x41,0x4c,0x80,0x7b] + cmovnoq 123(%r8,%rax,4), %r9, %r15 +# CHECK: cmovnpw %dx, %ax, %r9w +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x4b,0xc2] + cmovnpw %dx, %ax, %r9w +# CHECK: cmovnpl %ecx, %edx, %r10d +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x4b,0xd1] + cmovnpl %ecx, %edx, %r10d +# CHECK: cmovnpq %r9, %r15, %r11 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x4b,0xf9] + cmovnpq %r9, %r15, %r11 +# CHECK: cmovnpw 123(%r8,%rax,4), %dx, %ax +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x4b,0x54,0x80,0x7b] + cmovnpw 123(%r8,%rax,4), %dx, %ax +# CHECK: cmovnpl 123(%r8,%rax,4), %ecx, %edx +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x4b,0x4c,0x80,0x7b] + cmovnpl 123(%r8,%rax,4), %ecx, %edx +# CHECK: cmovnpq 123(%r8,%rax,4), %r9, %r15 +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x4b,0x4c,0x80,0x7b] + cmovnpq 123(%r8,%rax,4), %r9, %r15 +# CHECK: cmovnsw %dx, %ax, %r9w +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x49,0xc2] + cmovnsw %dx, %ax, %r9w +# CHECK: cmovnsl %ecx, %edx, %r10d +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x49,0xd1] + cmovnsl %ecx, %edx, %r10d +# CHECK: cmovnsq %r9, %r15, %r11 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x49,0xf9] + cmovnsq %r9, %r15, %r11 +# CHECK: cmovnsw 123(%r8,%rax,4), %dx, %ax +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x49,0x54,0x80,0x7b] + cmovnsw 123(%r8,%rax,4), %dx, %ax +# CHECK: cmovnsl 123(%r8,%rax,4), %ecx, %edx +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x49,0x4c,0x80,0x7b] + cmovnsl 123(%r8,%rax,4), %ecx, %edx +# CHECK: cmovnsq 123(%r8,%rax,4), %r9, %r15 +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x49,0x4c,0x80,0x7b] + cmovnsq 123(%r8,%rax,4), %r9, %r15 +# CHECK: cmovnew %dx, %ax, %r9w +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x45,0xc2] + cmovnew %dx, %ax, %r9w +# CHECK: cmovnel %ecx, %edx, %r10d +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x45,0xd1] + cmovnel %ecx, %edx, %r10d +# CHECK: cmovneq %r9, %r15, %r11 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x45,0xf9] + cmovneq %r9, %r15, %r11 +# CHECK: cmovnew 123(%r8,%rax,4), %dx, %ax +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x45,0x54,0x80,0x7b] + cmovnew 123(%r8,%rax,4), %dx, %ax +# CHECK: cmovnel 123(%r8,%rax,4), %ecx, %edx +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x45,0x4c,0x80,0x7b] + cmovnel 123(%r8,%rax,4), %ecx, %edx +# CHECK: cmovneq 123(%r8,%rax,4), %r9, %r15 +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x45,0x4c,0x80,0x7b] + cmovneq 123(%r8,%rax,4), %r9, %r15 +# CHECK: cmovow %dx, %ax, %r9w +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x40,0xc2] + cmovow %dx, %ax, %r9w +# CHECK: cmovol %ecx, %edx, %r10d +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x40,0xd1] + cmovol %ecx, %edx, %r10d +# CHECK: cmovoq %r9, %r15, %r11 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x40,0xf9] + cmovoq %r9, %r15, %r11 +# CHECK: cmovow 123(%r8,%rax,4), %dx, %ax +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x40,0x54,0x80,0x7b] + cmovow 123(%r8,%rax,4), %dx, %ax +# CHECK: cmovol 123(%r8,%rax,4), %ecx, %edx +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x40,0x4c,0x80,0x7b] + cmovol 123(%r8,%rax,4), %ecx, %edx +# CHECK: cmovoq 123(%r8,%rax,4), %r9, %r15 +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x40,0x4c,0x80,0x7b] + cmovoq 123(%r8,%rax,4), %r9, %r15 +# CHECK: cmovpw %dx, %ax, %r9w +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x4a,0xc2] + cmovpw %dx, %ax, %r9w +# CHECK: cmovpl %ecx, %edx, %r10d +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x4a,0xd1] + cmovpl %ecx, %edx, %r10d +# CHECK: cmovpq %r9, %r15, %r11 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x4a,0xf9] + cmovpq %r9, %r15, %r11 +# CHECK: cmovpw 123(%r8,%rax,4), %dx, %ax +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x4a,0x54,0x80,0x7b] + cmovpw 123(%r8,%rax,4), %dx, %ax +# CHECK: cmovpl 123(%r8,%rax,4), %ecx, %edx +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x4a,0x4c,0x80,0x7b] + cmovpl 123(%r8,%rax,4), %ecx, %edx +# CHECK: cmovpq 123(%r8,%rax,4), %r9, %r15 +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x4a,0x4c,0x80,0x7b] + cmovpq 123(%r8,%rax,4), %r9, %r15 +# CHECK: cmovsw %dx, %ax, %r9w +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x48,0xc2] + cmovsw %dx, %ax, %r9w +# CHECK: cmovsl %ecx, %edx, %r10d +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x48,0xd1] + cmovsl %ecx, %edx, %r10d +# CHECK: cmovsq %r9, %r15, %r11 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x48,0xf9] + cmovsq %r9, %r15, %r11 +# CHECK: cmovsw 123(%r8,%rax,4), %dx, %ax +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x48,0x54,0x80,0x7b] + cmovsw 123(%r8,%rax,4), %dx, %ax +# CHECK: cmovsl 123(%r8,%rax,4), %ecx, %edx +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x48,0x4c,0x80,0x7b] + cmovsl 123(%r8,%rax,4), %ecx, %edx +# CHECK: cmovsq 123(%r8,%rax,4), %r9, %r15 +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x48,0x4c,0x80,0x7b] + cmovsq 123(%r8,%rax,4), %r9, %r15 +# CHECK: cmovew %dx, %ax, %r9w +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x44,0xc2] + cmovew %dx, %ax, %r9w +# CHECK: cmovel %ecx, %edx, %r10d +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x44,0xd1] + cmovel %ecx, %edx, %r10d +# CHECK: cmoveq %r9, %r15, %r11 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x44,0xf9] + cmoveq %r9, %r15, %r11 +# CHECK: cmovew 123(%r8,%rax,4), %dx, %ax +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x44,0x54,0x80,0x7b] + cmovew 123(%r8,%rax,4), %dx, %ax +# CHECK: cmovel 123(%r8,%rax,4), %ecx, %edx +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x44,0x4c,0x80,0x7b] + cmovel 123(%r8,%rax,4), %ecx, %edx +# CHECK: cmoveq 123(%r8,%rax,4), %r9, %r15 +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x44,0x4c,0x80,0x7b] + cmoveq 123(%r8,%rax,4), %r9, %r15 diff --git a/llvm/test/MC/X86/apx/cmov-intel.s b/llvm/test/MC/X86/apx/cmov-intel.s new file mode 100644 index 0000000000000000000000000000000000000000..f481346bc347086d5c4ea0ab71148b802eccfb82 --- /dev/null +++ b/llvm/test/MC/X86/apx/cmov-intel.s @@ -0,0 +1,290 @@ +# RUN: llvm-mc -triple x86_64 -show-encoding -x86-asm-syntax=intel -output-asm-variant=1 %s | FileCheck %s + +# CHECK: cmovb r9w, ax, dx +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x42,0xc2] + cmovb r9w, ax, dx +# CHECK: cmovb r10d, edx, ecx +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x42,0xd1] + cmovb r10d, edx, ecx +# CHECK: cmovb r11, r15, r9 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x42,0xf9] + cmovb r11, r15, r9 +# CHECK: cmovb ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x42,0x54,0x80,0x7b] + cmovb ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: cmovb edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x42,0x4c,0x80,0x7b] + cmovb edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: cmovb r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x42,0x4c,0x80,0x7b] + cmovb r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: cmovbe r9w, ax, dx +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x46,0xc2] + cmovbe r9w, ax, dx +# CHECK: cmovbe r10d, edx, ecx +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x46,0xd1] + cmovbe r10d, edx, ecx +# CHECK: cmovbe r11, r15, r9 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x46,0xf9] + cmovbe r11, r15, r9 +# CHECK: cmovbe ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x46,0x54,0x80,0x7b] + cmovbe ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: cmovbe edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x46,0x4c,0x80,0x7b] + cmovbe edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: cmovbe r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x46,0x4c,0x80,0x7b] + cmovbe r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: cmovl r9w, ax, dx +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x4c,0xc2] + cmovl r9w, ax, dx +# CHECK: cmovl r10d, edx, ecx +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x4c,0xd1] + cmovl r10d, edx, ecx +# CHECK: cmovl r11, r15, r9 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x4c,0xf9] + cmovl r11, r15, r9 +# CHECK: cmovl ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x4c,0x54,0x80,0x7b] + cmovl ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: cmovl edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x4c,0x4c,0x80,0x7b] + cmovl edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: cmovl r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x4c,0x4c,0x80,0x7b] + cmovl r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: cmovle r9w, ax, dx +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x4e,0xc2] + cmovle r9w, ax, dx +# CHECK: cmovle r10d, edx, ecx +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x4e,0xd1] + cmovle r10d, edx, ecx +# CHECK: cmovle r11, r15, r9 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x4e,0xf9] + cmovle r11, r15, r9 +# CHECK: cmovle ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x4e,0x54,0x80,0x7b] + cmovle ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: cmovle edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x4e,0x4c,0x80,0x7b] + cmovle edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: cmovle r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x4e,0x4c,0x80,0x7b] + cmovle r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: cmovae r9w, ax, dx +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x43,0xc2] + cmovae r9w, ax, dx +# CHECK: cmovae r10d, edx, ecx +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x43,0xd1] + cmovae r10d, edx, ecx +# CHECK: cmovae r11, r15, r9 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x43,0xf9] + cmovae r11, r15, r9 +# CHECK: cmovae ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x43,0x54,0x80,0x7b] + cmovae ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: cmovae edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x43,0x4c,0x80,0x7b] + cmovae edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: cmovae r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x43,0x4c,0x80,0x7b] + cmovae r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: cmova r9w, ax, dx +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x47,0xc2] + cmova r9w, ax, dx +# CHECK: cmova r10d, edx, ecx +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x47,0xd1] + cmova r10d, edx, ecx +# CHECK: cmova r11, r15, r9 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x47,0xf9] + cmova r11, r15, r9 +# CHECK: cmova ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x47,0x54,0x80,0x7b] + cmova ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: cmova edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x47,0x4c,0x80,0x7b] + cmova edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: cmova r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x47,0x4c,0x80,0x7b] + cmova r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: cmovge r9w, ax, dx +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x4d,0xc2] + cmovge r9w, ax, dx +# CHECK: cmovge r10d, edx, ecx +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x4d,0xd1] + cmovge r10d, edx, ecx +# CHECK: cmovge r11, r15, r9 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x4d,0xf9] + cmovge r11, r15, r9 +# CHECK: cmovge ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x4d,0x54,0x80,0x7b] + cmovge ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: cmovge edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x4d,0x4c,0x80,0x7b] + cmovge edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: cmovge r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x4d,0x4c,0x80,0x7b] + cmovge r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: cmovg r9w, ax, dx +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x4f,0xc2] + cmovg r9w, ax, dx +# CHECK: cmovg r10d, edx, ecx +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x4f,0xd1] + cmovg r10d, edx, ecx +# CHECK: cmovg r11, r15, r9 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x4f,0xf9] + cmovg r11, r15, r9 +# CHECK: cmovg ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x4f,0x54,0x80,0x7b] + cmovg ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: cmovg edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x4f,0x4c,0x80,0x7b] + cmovg edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: cmovg r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x4f,0x4c,0x80,0x7b] + cmovg r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: cmovno r9w, ax, dx +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x41,0xc2] + cmovno r9w, ax, dx +# CHECK: cmovno r10d, edx, ecx +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x41,0xd1] + cmovno r10d, edx, ecx +# CHECK: cmovno r11, r15, r9 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x41,0xf9] + cmovno r11, r15, r9 +# CHECK: cmovno ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x41,0x54,0x80,0x7b] + cmovno ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: cmovno edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x41,0x4c,0x80,0x7b] + cmovno edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: cmovno r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x41,0x4c,0x80,0x7b] + cmovno r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: cmovnp r9w, ax, dx +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x4b,0xc2] + cmovnp r9w, ax, dx +# CHECK: cmovnp r10d, edx, ecx +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x4b,0xd1] + cmovnp r10d, edx, ecx +# CHECK: cmovnp r11, r15, r9 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x4b,0xf9] + cmovnp r11, r15, r9 +# CHECK: cmovnp ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x4b,0x54,0x80,0x7b] + cmovnp ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: cmovnp edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x4b,0x4c,0x80,0x7b] + cmovnp edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: cmovnp r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x4b,0x4c,0x80,0x7b] + cmovnp r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: cmovns r9w, ax, dx +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x49,0xc2] + cmovns r9w, ax, dx +# CHECK: cmovns r10d, edx, ecx +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x49,0xd1] + cmovns r10d, edx, ecx +# CHECK: cmovns r11, r15, r9 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x49,0xf9] + cmovns r11, r15, r9 +# CHECK: cmovns ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x49,0x54,0x80,0x7b] + cmovns ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: cmovns edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x49,0x4c,0x80,0x7b] + cmovns edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: cmovns r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x49,0x4c,0x80,0x7b] + cmovns r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: cmovne r9w, ax, dx +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x45,0xc2] + cmovne r9w, ax, dx +# CHECK: cmovne r10d, edx, ecx +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x45,0xd1] + cmovne r10d, edx, ecx +# CHECK: cmovne r11, r15, r9 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x45,0xf9] + cmovne r11, r15, r9 +# CHECK: cmovne ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x45,0x54,0x80,0x7b] + cmovne ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: cmovne edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x45,0x4c,0x80,0x7b] + cmovne edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: cmovne r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x45,0x4c,0x80,0x7b] + cmovne r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: cmovo r9w, ax, dx +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x40,0xc2] + cmovo r9w, ax, dx +# CHECK: cmovo r10d, edx, ecx +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x40,0xd1] + cmovo r10d, edx, ecx +# CHECK: cmovo r11, r15, r9 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x40,0xf9] + cmovo r11, r15, r9 +# CHECK: cmovo ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x40,0x54,0x80,0x7b] + cmovo ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: cmovo edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x40,0x4c,0x80,0x7b] + cmovo edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: cmovo r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x40,0x4c,0x80,0x7b] + cmovo r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: cmovp r9w, ax, dx +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x4a,0xc2] + cmovp r9w, ax, dx +# CHECK: cmovp r10d, edx, ecx +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x4a,0xd1] + cmovp r10d, edx, ecx +# CHECK: cmovp r11, r15, r9 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x4a,0xf9] + cmovp r11, r15, r9 +# CHECK: cmovp ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x4a,0x54,0x80,0x7b] + cmovp ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: cmovp edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x4a,0x4c,0x80,0x7b] + cmovp edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: cmovp r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x4a,0x4c,0x80,0x7b] + cmovp r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: cmovs r9w, ax, dx +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x48,0xc2] + cmovs r9w, ax, dx +# CHECK: cmovs r10d, edx, ecx +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x48,0xd1] + cmovs r10d, edx, ecx +# CHECK: cmovs r11, r15, r9 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x48,0xf9] + cmovs r11, r15, r9 +# CHECK: cmovs ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x48,0x54,0x80,0x7b] + cmovs ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: cmovs edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x48,0x4c,0x80,0x7b] + cmovs edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: cmovs r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x48,0x4c,0x80,0x7b] + cmovs r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: cmove r9w, ax, dx +# CHECK: encoding: [0x62,0xf4,0x35,0x18,0x44,0xc2] + cmove r9w, ax, dx +# CHECK: cmove r10d, edx, ecx +# CHECK: encoding: [0x62,0xf4,0x2c,0x18,0x44,0xd1] + cmove r10d, edx, ecx +# CHECK: cmove r11, r15, r9 +# CHECK: encoding: [0x62,0x54,0xa4,0x18,0x44,0xf9] + cmove r11, r15, r9 +# CHECK: cmove ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x44,0x54,0x80,0x7b] + cmove ax, dx, word ptr [r8 + 4*rax + 123] +# CHECK: cmove edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0xd4,0x6c,0x18,0x44,0x4c,0x80,0x7b] + cmove edx, ecx, dword ptr [r8 + 4*rax + 123] +# CHECK: cmove r15, r9, qword ptr [r8 + 4*rax + 123] +# CHECK: encoding: [0x62,0x54,0x84,0x18,0x44,0x4c,0x80,0x7b] + cmove r15, r9, qword ptr [r8 + 4*rax + 123] diff --git a/llvm/test/MC/X86/apx/evex-format-att.s b/llvm/test/MC/X86/apx/evex-format-att.s index 055a29fe00f32cc20385c4f1a815958ea8ede3bb..36df3f3757dc3f3f1f78f5c754f83b3e12d58f33 100644 --- a/llvm/test/MC/X86/apx/evex-format-att.s +++ b/llvm/test/MC/X86/apx/evex-format-att.s @@ -10,6 +10,12 @@ # CHECK: encoding: [0x62,0xec,0xec,0x10,0x01,0x41,0x7b] addq %r16, 123(%r17), %r18 +## MRMDestMemCC + +# CHECK: cfcmovbq %r16, 123(%r17,%r18,4) +# CHECK: encoding: [0x62,0xec,0xf8,0x0c,0x42,0x44,0x91,0x7b] + cfcmovbq %r16, 123(%r17,%r18,4) + ## MRMSrcMem # CHECK: vbroadcasti32x4 (%r16,%r17), %zmm0 @@ -20,6 +26,16 @@ # CHECK: encoding: [0x62,0xec,0xec,0x10,0x2b,0x48,0x7b] subq 123(%r16), %r17, %r18 +## MRMSrcMemCC + +# CHECK: cfcmovbq 123(%r16,%r17,4), %r18 +# CHECK: encoding: [0x62,0xec,0xf8,0x08,0x42,0x54,0x88,0x7b] + cfcmovbq 123(%r16,%r17,4), %r18 + +# CHECK: cfcmovbq 123(%r16,%r17,4), %r18, %r19 +# CHECK: encoding: [0x62,0xec,0xe0,0x14,0x42,0x54,0x88,0x7b] + cfcmovbq 123(%r16,%r17,4), %r18, %r19 + ## MRM0m # CHECK: vprorq $0, (%r16,%r17), %zmm0 @@ -122,12 +138,24 @@ # CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x01,0xc1] {nf} addq %r16, %r17 +## MRMDestRegCC + +# CHECK: cfcmovbq %r16, %r17 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x42,0xc1] + cfcmovbq %r16, %r17 + ## MRMSrcReg # CHECK: mulxq %r16, %r17, %r18 # CHECK: encoding: [0x62,0xea,0xf7,0x00,0xf6,0xd0] mulxq %r16, %r17, %r18 +## MRMSrcRegCC + +# CHECK: cfcmovbq %r16, %r17, %r18 +# CHECK: encoding: [0x62,0xec,0xec,0x14,0x42,0xc8] + cfcmovbq %r16, %r17, %r18 + ## MRMSrcReg4VOp3 # CHECK: bzhiq %r19, %r23, %r27 diff --git a/llvm/test/MC/X86/apx/evex-format-intel.s b/llvm/test/MC/X86/apx/evex-format-intel.s index 06b56078aab90463d87cb8649e05c19763166744..2b346e0e858063738def2cfb7f6ce191a8ac1d1d 100644 --- a/llvm/test/MC/X86/apx/evex-format-intel.s +++ b/llvm/test/MC/X86/apx/evex-format-intel.s @@ -10,6 +10,12 @@ # CHECK: encoding: [0x62,0xec,0xec,0x10,0x01,0x41,0x7b] add r18, qword ptr [r17 + 123], r16 +## MRMDestMemCC + +# CHECK: cfcmovb qword ptr [r17 + 4*r18 + 123], r16 +# CHECK: encoding: [0x62,0xec,0xf8,0x0c,0x42,0x44,0x91,0x7b] + cfcmovb qword ptr [r17 + 4*r18 + 123], r16 + ## MRMSrcMem # CHECK: vbroadcasti32x4 zmm0, xmmword ptr [r16 + r17] @@ -20,6 +26,16 @@ # CHECK: encoding: [0x62,0xec,0xec,0x10,0x2b,0x48,0x7b] sub r18, r17, qword ptr [r16 + 123] +## MRMSrcMemCC + +# CHECK: cfcmovb r18, qword ptr [r16 + 4*r17 + 123] +# CHECK: encoding: [0x62,0xec,0xf8,0x08,0x42,0x54,0x88,0x7b] + cfcmovb r18, qword ptr [r16 + 4*r17 + 123] + +# CHECK: cfcmovb r19, r18, qword ptr [r16 + 4*r17 + 123] +# CHECK: encoding: [0x62,0xec,0xe0,0x14,0x42,0x54,0x88,0x7b] + cfcmovb r19, r18, qword ptr [r16 + 4*r17 + 123] + ## MRM0m # CHECK: vprorq zmm0, zmmword ptr [r16 + r17], 0 @@ -122,12 +138,24 @@ # CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x01,0xc1] {nf} add r17, r16 +## MRMDestRegCC + +# CHECK: cfcmovb r17, r16 +# CHECK: encoding: [0x62,0xec,0xfc,0x0c,0x42,0xc1] + cfcmovb r17, r16 + ## MRMSrcReg # CHECK: mulx r18, r17, r16 # CHECK: encoding: [0x62,0xea,0xf7,0x00,0xf6,0xd0] mulx r18, r17, r16 +## MRMSrcRegCC + +# CHECK: cfcmovb r18, r17, r16 +# CHECK: encoding: [0x62,0xec,0xec,0x14,0x42,0xc8] + cfcmovb r18, r17, r16 + ## MRMSrcReg4VOp3 # CHECK: bzhi r27, r23, r19 diff --git a/llvm/test/MC/X86/apx/imulzu-att.s b/llvm/test/MC/X86/apx/imulzu-att.s new file mode 100644 index 0000000000000000000000000000000000000000..f56bfa77e1ce2840771a3fe221a0f886ae393044 --- /dev/null +++ b/llvm/test/MC/X86/apx/imulzu-att.s @@ -0,0 +1,41 @@ +# RUN: llvm-mc -triple x86_64 -show-encoding %s | FileCheck %s +# RUN: not llvm-mc -triple i386 -show-encoding %s 2>&1 | FileCheck %s --check-prefix=ERROR + +# ERROR-COUNT-12: error: +# ERROR-NOT: error: +# CHECK: imulzuw $123, %dx, %dx +# CHECK: encoding: [0x62,0xf4,0x7d,0x18,0x6b,0xd2,0x7b] + imulzuw $123, %dx, %dx +# CHECK: imulzul $123, %ecx, %ecx +# CHECK: encoding: [0x62,0xf4,0x7c,0x18,0x6b,0xc9,0x7b] + imulzul $123, %ecx, %ecx +# CHECK: imulzuq $123, %r9, %r9 +# CHECK: encoding: [0x62,0x54,0xfc,0x18,0x6b,0xc9,0x7b] + imulzuq $123, %r9, %r9 +# CHECK: imulzuw $123, 291(%r8,%rax,4), %dx +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x6b,0x94,0x80,0x23,0x01,0x00,0x00,0x7b] + imulzuw $123, 291(%r8,%rax,4), %dx +# CHECK: imulzul $123, 291(%r8,%rax,4), %ecx +# CHECK: encoding: [0x62,0xd4,0x7c,0x18,0x6b,0x8c,0x80,0x23,0x01,0x00,0x00,0x7b] + imulzul $123, 291(%r8,%rax,4), %ecx +# CHECK: imulzuq $123, 291(%r8,%rax,4), %r9 +# CHECK: encoding: [0x62,0x54,0xfc,0x18,0x6b,0x8c,0x80,0x23,0x01,0x00,0x00,0x7b] + imulzuq $123, 291(%r8,%rax,4), %r9 +# CHECK: imulzuw $1234, %dx, %dx +# CHECK: encoding: [0x62,0xf4,0x7d,0x18,0x69,0xd2,0xd2,0x04] + imulzuw $1234, %dx, %dx +# CHECK: imulzuw $1234, 291(%r8,%rax,4), %dx +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x69,0x94,0x80,0x23,0x01,0x00,0x00,0xd2,0x04] + imulzuw $1234, 291(%r8,%rax,4), %dx +# CHECK: imulzul $123456, %ecx, %ecx +# CHECK: encoding: [0x62,0xf4,0x7c,0x18,0x69,0xc9,0x40,0xe2,0x01,0x00] + imulzul $123456, %ecx, %ecx +# CHECK: imulzuq $123456, %r9, %r9 +# CHECK: encoding: [0x62,0x54,0xfc,0x18,0x69,0xc9,0x40,0xe2,0x01,0x00] + imulzuq $123456, %r9, %r9 +# CHECK: imulzul $123456, 291(%r8,%rax,4), %ecx +# CHECK: encoding: [0x62,0xd4,0x7c,0x18,0x69,0x8c,0x80,0x23,0x01,0x00,0x00,0x40,0xe2,0x01,0x00] + imulzul $123456, 291(%r8,%rax,4), %ecx +# CHECK: imulzuq $123456, 291(%r8,%rax,4), %r9 +# CHECK: encoding: [0x62,0x54,0xfc,0x18,0x69,0x8c,0x80,0x23,0x01,0x00,0x00,0x40,0xe2,0x01,0x00] + imulzuq $123456, 291(%r8,%rax,4), %r9 diff --git a/llvm/test/MC/X86/apx/imulzu-intel.s b/llvm/test/MC/X86/apx/imulzu-intel.s new file mode 100644 index 0000000000000000000000000000000000000000..3a01fdca1489509bcae9d99a7ab2ea0777abd4aa --- /dev/null +++ b/llvm/test/MC/X86/apx/imulzu-intel.s @@ -0,0 +1,38 @@ +# RUN: llvm-mc -triple x86_64 -show-encoding -x86-asm-syntax=intel -output-asm-variant=1 %s | FileCheck %s + +# CHECK: imulzu dx, dx, 123 +# CHECK: encoding: [0x62,0xf4,0x7d,0x18,0x6b,0xd2,0x7b] + imulzu dx, dx, 123 +# CHECK: imulzu ecx, ecx, 123 +# CHECK: encoding: [0x62,0xf4,0x7c,0x18,0x6b,0xc9,0x7b] + imulzu ecx, ecx, 123 +# CHECK: imulzu r9, r9, 123 +# CHECK: encoding: [0x62,0x54,0xfc,0x18,0x6b,0xc9,0x7b] + imulzu r9, r9, 123 +# CHECK: imulzu dx, word ptr [r8 + 4*rax + 291], 123 +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x6b,0x94,0x80,0x23,0x01,0x00,0x00,0x7b] + imulzu dx, word ptr [r8 + 4*rax + 291], 123 +# CHECK: imulzu ecx, dword ptr [r8 + 4*rax + 291], 123 +# CHECK: encoding: [0x62,0xd4,0x7c,0x18,0x6b,0x8c,0x80,0x23,0x01,0x00,0x00,0x7b] + imulzu ecx, dword ptr [r8 + 4*rax + 291], 123 +# CHECK: imulzu r9, qword ptr [r8 + 4*rax + 291], 123 +# CHECK: encoding: [0x62,0x54,0xfc,0x18,0x6b,0x8c,0x80,0x23,0x01,0x00,0x00,0x7b] + imulzu r9, qword ptr [r8 + 4*rax + 291], 123 +# CHECK: imulzu dx, dx, 1234 +# CHECK: encoding: [0x62,0xf4,0x7d,0x18,0x69,0xd2,0xd2,0x04] + imulzu dx, dx, 1234 +# CHECK: imulzu dx, word ptr [r8 + 4*rax + 291], 1234 +# CHECK: encoding: [0x62,0xd4,0x7d,0x18,0x69,0x94,0x80,0x23,0x01,0x00,0x00,0xd2,0x04] + imulzu dx, word ptr [r8 + 4*rax + 291], 1234 +# CHECK: imulzu ecx, ecx, 123456 +# CHECK: encoding: [0x62,0xf4,0x7c,0x18,0x69,0xc9,0x40,0xe2,0x01,0x00] + imulzu ecx, ecx, 123456 +# CHECK: imulzu r9, r9, 123456 +# CHECK: encoding: [0x62,0x54,0xfc,0x18,0x69,0xc9,0x40,0xe2,0x01,0x00] + imulzu r9, r9, 123456 +# CHECK: imulzu ecx, dword ptr [r8 + 4*rax + 291], 123456 +# CHECK: encoding: [0x62,0xd4,0x7c,0x18,0x69,0x8c,0x80,0x23,0x01,0x00,0x00,0x40,0xe2,0x01,0x00] + imulzu ecx, dword ptr [r8 + 4*rax + 291], 123456 +# CHECK: imulzu r9, qword ptr [r8 + 4*rax + 291], 123456 +# CHECK: encoding: [0x62,0x54,0xfc,0x18,0x69,0x8c,0x80,0x23,0x01,0x00,0x00,0x40,0xe2,0x01,0x00] + imulzu r9, qword ptr [r8 + 4*rax + 291], 123456 diff --git a/llvm/test/MachineVerifier/test_adjustsstack.mir b/llvm/test/MachineVerifier/test_adjustsstack.mir new file mode 100644 index 0000000000000000000000000000000000000000..d333737e000cc60f14ea2235068177fd5081ad3a --- /dev/null +++ b/llvm/test/MachineVerifier/test_adjustsstack.mir @@ -0,0 +1,26 @@ +# RUN: not --crash llc -o - -start-before=twoaddressinstruction -verify-machineinstrs %s 2>&1 \ +# RUN: | FileCheck %s +# REQUIRES: aarch64-registered-target +--- | + target triple = "aarch64-unknown-linux" + declare i32 @bar(i32) nounwind + define i32 @foo() nounwind { + call i32 @bar(i32 0) + ret i32 0 + } +... +--- +name: foo +registers: + - { id: 0, class: gpr32 } +body: | + bb.0 (%ir-block.0): + ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp + %0 = COPY $wzr + $w0 = COPY %0 + BL @bar, csr_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit $w0, implicit-def $sp, implicit-def $w0 + ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp + $w0 = COPY killed %0 + RET_ReallyLR implicit $w0 +... +# CHECK-LABEL: Bad machine code: AdjustsStack not set in presence of a frame pseudo instruction. diff --git a/llvm/test/MachineVerifier/test_g_splat_vector.mir b/llvm/test/MachineVerifier/test_g_splat_vector.mir index 0d1d8a3e6dcc64a6901c82aa8b344d265e675344..00074349776fa778d008cc818db5870fd1b7202d 100644 --- a/llvm/test/MachineVerifier/test_g_splat_vector.mir +++ b/llvm/test/MachineVerifier/test_g_splat_vector.mir @@ -22,6 +22,6 @@ body: | ; CHECK: Source type must be a scalar %6:_(<vscale x 2 x s32>) = G_SPLAT_VECTOR %2 - ; CHECK: Element type of the destination must be the same type as the source type - %7:_(<vscale x 2 x s64>) = G_SPLAT_VECTOR %0 + ; CHECK: Element type of the destination must be the same size or smaller than the source type + %7:_(<vscale x 2 x s128>) = G_SPLAT_VECTOR %0 ... diff --git a/llvm/test/MachineVerifier/test_g_ubsantrap.mir b/llvm/test/MachineVerifier/test_g_ubsantrap.mir new file mode 100644 index 0000000000000000000000000000000000000000..d2b219d8650aca84524b3c61650c7fceb18522ab --- /dev/null +++ b/llvm/test/MachineVerifier/test_g_ubsantrap.mir @@ -0,0 +1,18 @@ +# RUN: not --crash llc -o - -mtriple=arm64 -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s +# REQUIRES: aarch64-registered-target + +--- +name: test_ubsantrap +tracksRegLiveness: true +liveins: +body: | + bb.0: + + ; CHECK: Crash kind must be 8 bit wide + G_UBSANTRAP 4096 + + ; CHECK: Crash kind must be an immediate + %5:_(s32) = IMPLICIT_DEF + G_UBSANTRAP %5 + +... diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv3-amplification.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv3-amplification.yaml new file mode 100644 index 0000000000000000000000000000000000000000..09885bd529f05f3ef395bfae0eedd645e665b7fe --- /dev/null +++ b/llvm/test/ObjectYAML/DXContainer/PSVv3-amplification.yaml @@ -0,0 +1,97 @@ +# RUN: yaml2obj %s | obj2yaml | FileCheck %s + +--- !dxcontainer +Header: + Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] + Version: + Major: 1 + Minor: 0 + PartCount: 2 +Parts: + - Name: PSV0 + Size: 144 + PSVInfo: + Version: 3 + ShaderStage: 14 + PayloadSizeInBytes: 4092 + MinimumWaveLaneCount: 0 + MaximumWaveLaneCount: 4294967295 + UsesViewID: 0 + SigInputVectors: 0 + SigOutputVectors: [ 8, 16, 32, 64 ] + NumThreadsX: 512 + NumThreadsY: 1024 + NumThreadsZ: 2048 + EntryName: ASEntry + ResourceStride: 24 + Resources: + - Type: 1 + Space: 2 + LowerBound: 3 + UpperBound: 4 + Kind: 5 + Flags: 6 + - Type: 128 + Space: 32768 + LowerBound: 8388608 + UpperBound: 2147483648 + Kind: 65535 + Flags: 16776960 + SigInputElements: [] + SigOutputElements: [] + SigPatchOrPrimElements: [] + InputOutputMap: + - [ ] + - [ ] + - [ ] + - [ ] + - Name: DXIL + Size: 24 + Program: + MajorVersion: 6 + MinorVersion: 0 + ShaderKind: 14 + Size: 6 + DXILMajorVersion: 0 + DXILMinorVersion: 1 + DXILSize: 0 +... + +# CHECK: Name: PSV0 +# CHECK: PSVInfo: +# CHECK-NEXT: Version: 3 +# CHECK-NEXT: ShaderStage: 14 +# CHECK-NEXT: PayloadSizeInBytes: 4092 +# CHECK-NEXT: MinimumWaveLaneCount: 0 +# CHECK-NEXT: MaximumWaveLaneCount: 4294967295 +# CHECK-NEXT: UsesViewID: 0 +# CHECK-NEXT: SigInputVectors: 0 +# CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ] +# CHECK-NEXT: NumThreadsX: 512 +# CHECK-NEXT: NumThreadsY: 1024 +# CHECK-NEXT: NumThreadsZ: 2048 +# CHECK-NEXT: EntryName: ASEntry +# CHECK-NEXT: ResourceStride: 24 +# CHECK-NEXT: Resources: +# CHECK-NEXT: - Type: 1 +# CHECK-NEXT: Space: 2 +# CHECK-NEXT: LowerBound: 3 +# CHECK-NEXT: UpperBound: 4 +# CHECK-NEXT: Kind: 5 +# CHECK-NEXT: Flags: 6 +# CHECK-NEXT: - Type: 128 +# CHECK-NEXT: Space: 32768 +# CHECK-NEXT: LowerBound: 8388608 +# CHECK-NEXT: UpperBound: 2147483648 +# CHECK-NEXT: Kind: 65535 +# CHECK-NEXT: Flags: 16776960 +# CHECK-NEXT: SigInputElements: [] +# CHECK-NEXT: SigOutputElements: [] +# CHECK-NEXT: SigPatchOrPrimElements: [] +# CHECK-NEXT: InputOutputMap: +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: Name diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv3-compute.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv3-compute.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ee6fb112c772226bcc0d0f914df961ea6d0fdb11 --- /dev/null +++ b/llvm/test/ObjectYAML/DXContainer/PSVv3-compute.yaml @@ -0,0 +1,95 @@ +# RUN: yaml2obj %s | obj2yaml | FileCheck %s + +--- !dxcontainer +Header: + Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] + Version: + Major: 1 + Minor: 0 + PartCount: 2 +Parts: + - Name: PSV0 + Size: 144 + PSVInfo: + Version: 3 + ShaderStage: 5 + MinimumWaveLaneCount: 0 + MaximumWaveLaneCount: 4294967295 + UsesViewID: 0 + SigInputVectors: 0 + SigOutputVectors: [ 8, 16, 32, 64 ] + NumThreadsX: 512 + NumThreadsY: 1024 + NumThreadsZ: 2048 + EntryName: CSEntry + ResourceStride: 24 + Resources: + - Type: 1 + Space: 2 + LowerBound: 3 + UpperBound: 4 + Kind: 5 + Flags: 6 + - Type: 128 + Space: 32768 + LowerBound: 8388608 + UpperBound: 2147483648 + Kind: 65535 + Flags: 16776960 + SigInputElements: [] + SigOutputElements: [] + SigPatchOrPrimElements: [] + InputOutputMap: + - [ ] + - [ ] + - [ ] + - [ ] + - Name: DXIL + Size: 24 + Program: + MajorVersion: 6 + MinorVersion: 0 + ShaderKind: 5 + Size: 6 + DXILMajorVersion: 0 + DXILMinorVersion: 1 + DXILSize: 0 +... + +# CHECK: Name: PSV0 +# CHECK: PSVInfo: +# CHECK-NEXT: Version: 3 +# CHECK-NEXT: ShaderStage: 5 +# CHECK-NEXT: MinimumWaveLaneCount: 0 +# CHECK-NEXT: MaximumWaveLaneCount: 4294967295 +# CHECK-NEXT: UsesViewID: 0 +# CHECK-NEXT: SigInputVectors: 0 +# CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ] +# CHECK-NEXT: NumThreadsX: 512 +# CHECK-NEXT: NumThreadsY: 1024 +# CHECK-NEXT: NumThreadsZ: 2048 +# CHECK-NEXT: EntryName: CSEntry +# CHECK-NEXT: ResourceStride: 24 +# CHECK-NEXT: Resources: +# CHECK-NEXT: - Type: 1 +# CHECK-NEXT: Space: 2 +# CHECK-NEXT: LowerBound: 3 +# CHECK-NEXT: UpperBound: 4 +# CHECK-NEXT: Kind: 5 +# CHECK-NEXT: Flags: 6 +# CHECK-NEXT: - Type: 128 +# CHECK-NEXT: Space: 32768 +# CHECK-NEXT: LowerBound: 8388608 +# CHECK-NEXT: UpperBound: 2147483648 +# CHECK-NEXT: Kind: 65535 +# CHECK-NEXT: Flags: 16776960 +# CHECK-NEXT: SigInputElements: [] +# CHECK-NEXT: SigOutputElements: [] +# CHECK-NEXT: SigPatchOrPrimElements: [] +# CHECK-NEXT: InputOutputMap: +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: Name diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv3-domain.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv3-domain.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dd367deae88e472194c75ea6e4fb8092b7f16088 --- /dev/null +++ b/llvm/test/ObjectYAML/DXContainer/PSVv3-domain.yaml @@ -0,0 +1,105 @@ +# RUN: yaml2obj %s | obj2yaml | FileCheck %s + +--- !dxcontainer +Header: + Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] + Version: + Major: 1 + Minor: 0 + PartCount: 2 +Parts: + - Name: PSV0 + Size: 144 + PSVInfo: + Version: 3 + ShaderStage: 4 + InputControlPointCount: 1024 + OutputPositionPresent: 1 + TessellatorDomain: 2056 + MinimumWaveLaneCount: 0 + MaximumWaveLaneCount: 4294967295 + UsesViewID: 0 + SigPatchConstOrPrimVectors: 0 + SigInputVectors: 0 + SigOutputVectors: [ 0, 16, 32, 64 ] + NumThreadsX: 512 + NumThreadsY: 1024 + NumThreadsZ: 2048 + EntryName: DSEntry + ResourceStride: 24 + Resources: + - Type: 1 + Space: 2 + LowerBound: 3 + UpperBound: 4 + Kind: 5 + Flags: 6 + - Type: 128 + Space: 32768 + LowerBound: 8388608 + UpperBound: 2147483648 + Kind: 65535 + Flags: 16776960 + SigInputElements: [] + SigOutputElements: [] + SigPatchOrPrimElements: [] + InputOutputMap: + - [ ] + - [ ] + - [ ] + - [ ] + PatchOutputMap: [] + - Name: DXIL + Size: 24 + Program: + MajorVersion: 6 + MinorVersion: 0 + ShaderKind: 4 + Size: 6 + DXILMajorVersion: 0 + DXILMinorVersion: 1 + DXILSize: 0 +... + +# CHECK: Name: PSV0 +# CHECK: PSVInfo: +# CHECK-NEXT: Version: 3 +# CHECK-NEXT: ShaderStage: 4 +# CHECK-NEXT: InputControlPointCount: 1024 +# CHECK-NEXT: OutputPositionPresent: 1 +# CHECK-NEXT: TessellatorDomain: 2056 +# CHECK-NEXT: MinimumWaveLaneCount: 0 +# CHECK-NEXT: MaximumWaveLaneCount: 4294967295 +# CHECK-NEXT: UsesViewID: 0 +# CHECK-NEXT: SigPatchConstOrPrimVectors: 0 +# CHECK-NEXT: SigInputVectors: 0 +# CHECK-NEXT: SigOutputVectors: [ 0, 16, 32, 64 ] +# CHECK-NEXT: NumThreadsX: 512 +# CHECK-NEXT: NumThreadsY: 1024 +# CHECK-NEXT: NumThreadsZ: 2048 +# CHECK-NEXT: EntryName: DSEntry +# CHECK-NEXT: ResourceStride: 24 +# CHECK-NEXT: Resources: +# CHECK-NEXT: - Type: 1 +# CHECK-NEXT: Space: 2 +# CHECK-NEXT: LowerBound: 3 +# CHECK-NEXT: UpperBound: 4 +# CHECK-NEXT: Kind: 5 +# CHECK-NEXT: Flags: 6 +# CHECK-NEXT: - Type: 128 +# CHECK-NEXT: Space: 32768 +# CHECK-NEXT: LowerBound: 8388608 +# CHECK-NEXT: UpperBound: 2147483648 +# CHECK-NEXT: Kind: 65535 +# CHECK-NEXT: Flags: 16776960 +# CHECK-NEXT: SigInputElements: [] +# CHECK-NEXT: SigOutputElements: [] +# CHECK-NEXT: SigPatchOrPrimElements: [] +# CHECK-NEXT: InputOutputMap: +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: PatchOutputMap: [ ] +# CHECK-NEXT: Name diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv3-geometry.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv3-geometry.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4c7680b63b02b633ea563ed75f54596a33b797d5 --- /dev/null +++ b/llvm/test/ObjectYAML/DXContainer/PSVv3-geometry.yaml @@ -0,0 +1,105 @@ +# RUN: yaml2obj %s | obj2yaml | FileCheck %s + +--- !dxcontainer +Header: + Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] + Version: + Major: 1 + Minor: 0 + PartCount: 2 +Parts: + - Name: PSV0 + Size: 144 + PSVInfo: + Version: 3 + ShaderStage: 2 + InputPrimitive: 1024 + OutputTopology: 4096 + OutputStreamMask: 2056 + OutputPositionPresent: 1 + MinimumWaveLaneCount: 0 + MaximumWaveLaneCount: 4294967295 + UsesViewID: 0 + MaxVertexCount: 4096 + SigInputVectors: 0 + SigOutputVectors: [ 8, 16, 32, 64 ] + NumThreadsX: 512 + NumThreadsY: 1024 + NumThreadsZ: 2048 + EntryName: GSEntry + ResourceStride: 24 + Resources: + - Type: 1 + Space: 2 + LowerBound: 3 + UpperBound: 4 + Kind: 5 + Flags: 6 + - Type: 128 + Space: 32768 + LowerBound: 8388608 + UpperBound: 2147483648 + Kind: 65535 + Flags: 16776960 + SigInputElements: [] + SigOutputElements: [] + SigPatchOrPrimElements: [] + InputOutputMap: + - [ ] + - [ ] + - [ ] + - [ ] + - Name: DXIL + Size: 24 + Program: + MajorVersion: 6 + MinorVersion: 0 + ShaderKind: 2 + Size: 6 + DXILMajorVersion: 0 + DXILMinorVersion: 1 + DXILSize: 0 +... + +# CHECK: Name: PSV0 +# CHECK: PSVInfo: +# CHECK-NEXT: Version: 3 +# CHECK-NEXT: ShaderStage: 2 +# CHECK-NEXT: InputPrimitive: 1024 +# CHECK-NEXT: OutputTopology: 4096 +# CHECK-NEXT: OutputStreamMask: 2056 +# CHECK-NEXT: OutputPositionPresent: 1 +# CHECK-NEXT: MinimumWaveLaneCount: 0 +# CHECK-NEXT: MaximumWaveLaneCount: 4294967295 +# CHECK-NEXT: UsesViewID: 0 +# CHECK-NEXT: MaxVertexCount: 4096 +# CHECK-NEXT: SigInputVectors: 0 +# CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ] +# CHECK-NEXT: NumThreadsX: 512 +# CHECK-NEXT: NumThreadsY: 1024 +# CHECK-NEXT: NumThreadsZ: 2048 +# CHECK-NEXT: EntryName: GSEntry +# CHECK-NEXT: ResourceStride: 24 +# CHECK-NEXT: Resources: +# CHECK-NEXT: - Type: 1 +# CHECK-NEXT: Space: 2 +# CHECK-NEXT: LowerBound: 3 +# CHECK-NEXT: UpperBound: 4 +# CHECK-NEXT: Kind: 5 +# CHECK-NEXT: Flags: 6 +# CHECK-NEXT: - Type: 128 +# CHECK-NEXT: Space: 32768 +# CHECK-NEXT: LowerBound: 8388608 +# CHECK-NEXT: UpperBound: 2147483648 +# CHECK-NEXT: Kind: 65535 +# CHECK-NEXT: Flags: 16776960 +# CHECK-NEXT: SigInputElements: [] +# CHECK-NEXT: SigOutputElements: [] +# CHECK-NEXT: SigPatchOrPrimElements: [] +# CHECK-NEXT: InputOutputMap: +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: Name diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv3-hull.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv3-hull.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3bbad8a9b0ee62744ace599df86e941bc91cbd75 --- /dev/null +++ b/llvm/test/ObjectYAML/DXContainer/PSVv3-hull.yaml @@ -0,0 +1,107 @@ +# RUN: yaml2obj %s | obj2yaml | FileCheck %s + +--- !dxcontainer +Header: + Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] + Version: + Major: 1 + Minor: 0 + PartCount: 2 +Parts: + - Name: PSV0 + Size: 144 + PSVInfo: + Version: 3 + ShaderStage: 3 + InputControlPointCount: 1024 + OutputControlPointCount: 4096 + TessellatorDomain: 2056 + TessellatorOutputPrimitive: 8192 + MinimumWaveLaneCount: 0 + MaximumWaveLaneCount: 4294967295 + UsesViewID: 0 + SigPatchConstOrPrimVectors: 0 + SigInputVectors: 0 + SigOutputVectors: [ 0, 16, 32, 64 ] + NumThreadsX: 512 + NumThreadsY: 1024 + NumThreadsZ: 2048 + EntryName: HSEntry + ResourceStride: 24 + Resources: + - Type: 1 + Space: 2 + LowerBound: 3 + UpperBound: 4 + Kind: 5 + Flags: 6 + - Type: 128 + Space: 32768 + LowerBound: 8388608 + UpperBound: 2147483648 + Kind: 65535 + Flags: 16776960 + SigInputElements: [] + SigOutputElements: [] + SigPatchOrPrimElements: [] + InputOutputMap: + - [ ] + - [ ] + - [ ] + - [ ] + InputPatchMap: [] + - Name: DXIL + Size: 24 + Program: + MajorVersion: 6 + MinorVersion: 0 + ShaderKind: 3 + Size: 6 + DXILMajorVersion: 0 + DXILMinorVersion: 1 + DXILSize: 0 +... + +# CHECK: Name: PSV0 +# CHECK: PSVInfo: +# CHECK-NEXT: Version: 3 +# CHECK-NEXT: ShaderStage: 3 +# CHECK-NEXT: InputControlPointCount: 1024 +# CHECK-NEXT: OutputControlPointCount: 4096 +# CHECK-NEXT: TessellatorDomain: 2056 +# CHECK-NEXT: TessellatorOutputPrimitive: 8192 +# CHECK-NEXT: MinimumWaveLaneCount: 0 +# CHECK-NEXT: MaximumWaveLaneCount: 4294967295 +# CHECK-NEXT: UsesViewID: 0 +# CHECK-NEXT: SigPatchConstOrPrimVectors: 0 +# CHECK-NEXT: SigInputVectors: 0 +# CHECK-NEXT: SigOutputVectors: [ 0, 16, 32, 64 ] +# CHECK-NEXT: NumThreadsX: 512 +# CHECK-NEXT: NumThreadsY: 1024 +# CHECK-NEXT: NumThreadsZ: 2048 +# CHECK-NEXT: EntryName: HSEntry +# CHECK-NEXT: ResourceStride: 24 +# CHECK-NEXT: Resources: +# CHECK-NEXT: - Type: 1 +# CHECK-NEXT: Space: 2 +# CHECK-NEXT: LowerBound: 3 +# CHECK-NEXT: UpperBound: 4 +# CHECK-NEXT: Kind: 5 +# CHECK-NEXT: Flags: 6 +# CHECK-NEXT: - Type: 128 +# CHECK-NEXT: Space: 32768 +# CHECK-NEXT: LowerBound: 8388608 +# CHECK-NEXT: UpperBound: 2147483648 +# CHECK-NEXT: Kind: 65535 +# CHECK-NEXT: Flags: 16776960 +# CHECK-NEXT: SigInputElements: [] +# CHECK-NEXT: SigOutputElements: [] +# CHECK-NEXT: SigPatchOrPrimElements: [] +# CHECK-NEXT: InputOutputMap: +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: InputPatchMap: [ ] +# CHECK-NEXT: Name diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv3-mesh.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv3-mesh.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c5ea1fcf078087000b89112e8ca3721c40c1fbe0 --- /dev/null +++ b/llvm/test/ObjectYAML/DXContainer/PSVv3-mesh.yaml @@ -0,0 +1,109 @@ +# RUN: yaml2obj %s | obj2yaml | FileCheck %s + +--- !dxcontainer +Header: + Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] + Version: + Major: 1 + Minor: 0 + PartCount: 2 +Parts: + - Name: PSV0 + Size: 144 + PSVInfo: + Version: 3 + ShaderStage: 13 + GroupSharedBytesUsed: 1024 + GroupSharedBytesDependentOnViewID: 2056 + PayloadSizeInBytes: 4092 + MaxOutputVertices: 8196 + MaxOutputPrimitives: 4092 + MinimumWaveLaneCount: 0 + MaximumWaveLaneCount: 4294967295 + UsesViewID: 0 + SigPrimVectors: 128 + MeshOutputTopology: 16 + SigInputVectors: 0 + SigOutputVectors: [ 8, 16, 32, 64 ] + NumThreadsX: 512 + NumThreadsY: 1024 + NumThreadsZ: 2048 + EntryName: MSEntry + ResourceStride: 24 + Resources: + - Type: 1 + Space: 2 + LowerBound: 3 + UpperBound: 4 + Kind: 5 + Flags: 6 + - Type: 128 + Space: 32768 + LowerBound: 8388608 + UpperBound: 2147483648 + Kind: 65535 + Flags: 16776960 + SigInputElements: [] + SigOutputElements: [] + SigPatchOrPrimElements: [] + InputOutputMap: + - [ ] + - [ ] + - [ ] + - [ ] + - Name: DXIL + Size: 24 + Program: + MajorVersion: 6 + MinorVersion: 0 + ShaderKind: 13 + Size: 6 + DXILMajorVersion: 0 + DXILMinorVersion: 1 + DXILSize: 0 +... + +# CHECK: Name: PSV0 +# CHECK: PSVInfo: +# CHECK-NEXT: Version: 3 +# CHECK-NEXT: ShaderStage: 13 +# CHECK-NEXT: GroupSharedBytesUsed: 1024 +# CHECK-NEXT: GroupSharedBytesDependentOnViewID: 2056 +# CHECK-NEXT: PayloadSizeInBytes: 4092 +# CHECK-NEXT: MaxOutputVertices: 8196 +# CHECK-NEXT: MaxOutputPrimitives: 4092 +# CHECK-NEXT: MinimumWaveLaneCount: 0 +# CHECK-NEXT: MaximumWaveLaneCount: 4294967295 +# CHECK-NEXT: UsesViewID: 0 +# CHECK-NEXT: SigPrimVectors: 128 +# CHECK-NEXT: MeshOutputTopology: 16 +# CHECK-NEXT: SigInputVectors: 0 +# CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ] +# CHECK-NEXT: NumThreadsX: 512 +# CHECK-NEXT: NumThreadsY: 1024 +# CHECK-NEXT: NumThreadsZ: 2048 +# CHECK-NEXT: EntryName: MSEntry +# CHECK-NEXT: ResourceStride: 24 +# CHECK-NEXT: Resources: +# CHECK-NEXT: - Type: 1 +# CHECK-NEXT: Space: 2 +# CHECK-NEXT: LowerBound: 3 +# CHECK-NEXT: UpperBound: 4 +# CHECK-NEXT: Kind: 5 +# CHECK-NEXT: Flags: 6 +# CHECK-NEXT: - Type: 128 +# CHECK-NEXT: Space: 32768 +# CHECK-NEXT: LowerBound: 8388608 +# CHECK-NEXT: UpperBound: 2147483648 +# CHECK-NEXT: Kind: 65535 +# CHECK-NEXT: Flags: 16776960 +# CHECK-NEXT: SigInputElements: [] +# CHECK-NEXT: SigOutputElements: [] +# CHECK-NEXT: SigPatchOrPrimElements: [] +# CHECK-NEXT: InputOutputMap: +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: Name diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv3-pixel.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv3-pixel.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b28d5ec8074d853d76994c1a36be59eba92e1494 --- /dev/null +++ b/llvm/test/ObjectYAML/DXContainer/PSVv3-pixel.yaml @@ -0,0 +1,99 @@ +# RUN: yaml2obj %s | obj2yaml | FileCheck %s + +--- !dxcontainer +Header: + Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] + Version: + Major: 1 + Minor: 0 + PartCount: 2 +Parts: + - Name: PSV0 + Size: 144 + PSVInfo: + Version: 3 + ShaderStage: 0 + DepthOutput: 7 + SampleFrequency: 96 + MinimumWaveLaneCount: 0 + MaximumWaveLaneCount: 4294967295 + UsesViewID: 0 + SigInputVectors: 0 + SigOutputVectors: [ 8, 16, 32, 64 ] + NumThreadsX: 512 + NumThreadsY: 1024 + NumThreadsZ: 2048 + EntryName: PSEntry + ResourceStride: 24 + Resources: + - Type: 1 + Space: 2 + LowerBound: 3 + UpperBound: 4 + Kind: 5 + Flags: 6 + - Type: 128 + Space: 32768 + LowerBound: 8388608 + UpperBound: 2147483648 + Kind: 65535 + Flags: 16776960 + SigInputElements: [] + SigOutputElements: [] + SigPatchOrPrimElements: [] + InputOutputMap: + - [ ] + - [ ] + - [ ] + - [ ] + - Name: DXIL + Size: 24 + Program: + MajorVersion: 6 + MinorVersion: 0 + ShaderKind: 0 + Size: 6 + DXILMajorVersion: 0 + DXILMinorVersion: 1 + DXILSize: 0 +... + +# CHECK: Name: PSV0 +# CHECK: PSVInfo: +# CHECK-NEXT: Version: 3 +# CHECK-NEXT: ShaderStage: 0 +# CHECK-NEXT: DepthOutput: 7 +# CHECK-NEXT: SampleFrequency: 96 +# CHECK-NEXT: MinimumWaveLaneCount: 0 +# CHECK-NEXT: MaximumWaveLaneCount: 4294967295 +# CHECK-NEXT: UsesViewID: 0 +# CHECK-NEXT: SigInputVectors: 0 +# CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ] +# CHECK-NEXT: NumThreadsX: 512 +# CHECK-NEXT: NumThreadsY: 1024 +# CHECK-NEXT: NumThreadsZ: 2048 +# CHECK-NEXT: EntryName: PSEntry +# CHECK-NEXT: ResourceStride: 24 +# CHECK-NEXT: Resources: +# CHECK-NEXT: - Type: 1 +# CHECK-NEXT: Space: 2 +# CHECK-NEXT: LowerBound: 3 +# CHECK-NEXT: UpperBound: 4 +# CHECK-NEXT: Kind: 5 +# CHECK-NEXT: Flags: 6 +# CHECK-NEXT: - Type: 128 +# CHECK-NEXT: Space: 32768 +# CHECK-NEXT: LowerBound: 8388608 +# CHECK-NEXT: UpperBound: 2147483648 +# CHECK-NEXT: Kind: 65535 +# CHECK-NEXT: Flags: 16776960 +# CHECK-NEXT: SigInputElements: [] +# CHECK-NEXT: SigOutputElements: [] +# CHECK-NEXT: SigPatchOrPrimElements: [] +# CHECK-NEXT: InputOutputMap: +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: Name diff --git a/llvm/test/ObjectYAML/DXContainer/PSVv3-vertex.yaml b/llvm/test/ObjectYAML/DXContainer/PSVv3-vertex.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d1fb55839931caead325b899865c72b332c5951c --- /dev/null +++ b/llvm/test/ObjectYAML/DXContainer/PSVv3-vertex.yaml @@ -0,0 +1,97 @@ +# RUN: yaml2obj %s | obj2yaml | FileCheck %s + +--- !dxcontainer +Header: + Hash: [ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ] + Version: + Major: 1 + Minor: 0 + PartCount: 2 +Parts: + - Name: PSV0 + Size: 144 + PSVInfo: + Version: 3 + ShaderStage: 1 + OutputPositionPresent: 1 + MinimumWaveLaneCount: 0 + MaximumWaveLaneCount: 4294967295 + UsesViewID: 0 + SigInputVectors: 0 + SigOutputVectors: [ 8, 16, 32, 64 ] + NumThreadsX: 512 + NumThreadsY: 1024 + NumThreadsZ: 2048 + EntryName: VSEntry + ResourceStride: 24 + Resources: + - Type: 1 + Space: 2 + LowerBound: 3 + UpperBound: 4 + Kind: 5 + Flags: 6 + - Type: 128 + Space: 32768 + LowerBound: 8388608 + UpperBound: 2147483648 + Kind: 65535 + Flags: 16776960 + SigInputElements: [] + SigOutputElements: [] + SigPatchOrPrimElements: [] + InputOutputMap: + - [ ] + - [ ] + - [ ] + - [ ] + - Name: DXIL + Size: 24 + Program: + MajorVersion: 6 + MinorVersion: 0 + ShaderKind: 1 + Size: 6 + DXILMajorVersion: 0 + DXILMinorVersion: 1 + DXILSize: 0 +... + +# CHECK: Name: PSV0 +# CHECK: PSVInfo: +# CHECK-NEXT: Version: 3 +# CHECK-NEXT: ShaderStage: 1 +# CHECK-NEXT: OutputPositionPresent: 1 +# CHECK-NEXT: MinimumWaveLaneCount: 0 +# CHECK-NEXT: MaximumWaveLaneCount: 4294967295 +# CHECK-NEXT: UsesViewID: 0 +# CHECK-NEXT: SigInputVectors: 0 +# CHECK-NEXT: SigOutputVectors: [ 8, 16, 32, 64 ] +# CHECK-NEXT: NumThreadsX: 512 +# CHECK-NEXT: NumThreadsY: 1024 +# CHECK-NEXT: NumThreadsZ: 2048 +# CHECK-NEXT: EntryName: VSEntry +# CHECK-NEXT: ResourceStride: 24 +# CHECK-NEXT: Resources: +# CHECK-NEXT: - Type: 1 +# CHECK-NEXT: Space: 2 +# CHECK-NEXT: LowerBound: 3 +# CHECK-NEXT: UpperBound: 4 +# CHECK-NEXT: Kind: 5 +# CHECK-NEXT: Flags: 6 +# CHECK-NEXT: - Type: 128 +# CHECK-NEXT: Space: 32768 +# CHECK-NEXT: LowerBound: 8388608 +# CHECK-NEXT: UpperBound: 2147483648 +# CHECK-NEXT: Kind: 65535 +# CHECK-NEXT: Flags: 16776960 +# CHECK-NEXT: SigInputElements: [] +# CHECK-NEXT: SigOutputElements: [] +# CHECK-NEXT: SigPatchOrPrimElements: [] +# CHECK-NEXT: InputOutputMap: +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: - [ ] +# CHECK-NEXT: Name diff --git a/llvm/test/Other/optimize-inrange-gep.ll b/llvm/test/Other/optimize-inrange-gep.ll index cc2bd15b5b22cc2b1db04388de8159b57013843b..2eae34bdb09b1d8d7b0bb60bf0dd87ff92c84c24 100644 --- a/llvm/test/Other/optimize-inrange-gep.ll +++ b/llvm/test/Other/optimize-inrange-gep.ll @@ -1,4 +1,5 @@ -; RUN: opt -O0 -S < %s | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -O0 -S < %s | FileCheck %s --check-prefix=O0 ; RUN: opt -O1 -S < %s | FileCheck %s ; RUN: opt -O2 -S < %s | FileCheck %s ; RUN: opt -O3 -S < %s | FileCheck %s @@ -7,12 +8,21 @@ target datalayout = "e-p:64:64" -; Make sure that optimizations do not optimize inrange GEP. +; Make sure that optimizations do not lose inrange information. @vtable = constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr null] } define void @foo(ptr %p) { - ;CHECK: store ptr getelementptr {{.*}} ({ [3 x ptr] }, ptr @vtable, i{{.*}} 0, inrange i32 0, i{{.*}} 3), ptr %p - store ptr getelementptr ({ [3 x ptr] }, ptr @vtable, i32 0, inrange i32 0, i32 3), ptr %p +; O0-LABEL: define void @foo( +; O0-SAME: ptr [[P:%.*]]) { +; O0-NEXT: store ptr getelementptr inrange(-24, 0) ({ [3 x ptr], [3 x ptr] }, ptr @vtable, i32 0, i32 0, i32 3), ptr [[P]], align 8 +; O0-NEXT: ret void +; +; CHECK-LABEL: define void @foo( +; CHECK-SAME: ptr nocapture writeonly [[P:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: store ptr getelementptr inbounds inrange(-24, 0) ({ [3 x ptr] }, ptr @vtable, i64 1, i32 0, i64 0), ptr [[P]], align 8 +; CHECK-NEXT: ret void +; + store ptr getelementptr inrange(-24, 0) ({ [3 x ptr], [3 x ptr] }, ptr @vtable, i32 0, i32 0, i32 3), ptr %p ret void } diff --git a/llvm/test/TableGen/ConcatenatedSubregs.td b/llvm/test/TableGen/ConcatenatedSubregs.td index 5b354c94dca52c301d4958a6ce438142c0eb9533..ea4e7f01a2e2dac0c335194ce84096f07fd768e8 100644 --- a/llvm/test/TableGen/ConcatenatedSubregs.td +++ b/llvm/test/TableGen/ConcatenatedSubregs.td @@ -90,16 +90,19 @@ def TestTarget : Target; // CHECK-LABEL: RegisterClass DRegs: // CHECK-LABEL: SubRegIndex ssub1: -// CHECK: Offset, Size: 16, 16 +// CHECK: Offset: { Default:16 } +// CHECK: Size: { Default:16 } // CHECK-LABEL: SubRegIndex sub0: // CHECK-LABEL: SubRegIndex sub1: // CHECK-LABEL: SubRegIndex sub2: // Check inferred indexes: // CHECK-LABEL: SubRegIndex ssub1_ssub2: -// CHECK: Offset, Size: 16, 65535 +// CHECK: Offset: { Default:16 } +// CHECK: Size: { Default:65535 } // CHECK-LABEL: SubRegIndex ssub3_ssub4: // CHECK-LABEL: SubRegIndex ssub0_ssub1_ssub2_ssub3: -// CHECK: Offset, Size: 65535, 65535 +// CHECK: Offset: { Default:65535 } +// CHECK: Size: { Default:65535 } // CHECK-LABEL: SubRegIndex ssub1_ssub2_ssub3_ssub4: // Check that all subregs are generated on some examples diff --git a/llvm/test/TableGen/ConstraintChecking3.td b/llvm/test/TableGen/ConstraintChecking3.td index 2d5fe6b7ef9699e32d2c2a3df299d758903abaf9..886e6d52a039fe9e8dcba3bb3c313c2719a9d851 100644 --- a/llvm/test/TableGen/ConstraintChecking3.td +++ b/llvm/test/TableGen/ConstraintChecking3.td @@ -4,5 +4,5 @@ include "ConstraintChecking.inc" // (This is illegal because the '=' has to be surrounded by whitespace) -// CHECK: [[FILE]]:[[@LINE+1]]:5: error: Illegal format for tied-to constraint in 'Foo' +// CHECK: [[FILE]]:[[@LINE+1]]:5: error: Unrecognized constraint '$dest1=$dest2' in 'Foo' def Foo : TestInstructionWithConstraints<"$dest1=$dest2">; diff --git a/llvm/test/TableGen/ConstraintChecking8.td b/llvm/test/TableGen/ConstraintChecking8.td new file mode 100644 index 0000000000000000000000000000000000000000..37d35150911ef299810ffdc9893b8672026eae36 --- /dev/null +++ b/llvm/test/TableGen/ConstraintChecking8.td @@ -0,0 +1,34 @@ +// RUN: not llvm-tblgen -gen-asm-writer -DT0 -I %p -I %p/../../include %s 2>&1 | FileCheck %s -DFILE=%s +// RUN: not llvm-tblgen -gen-asm-writer -DT1 -I %p -I %p/../../include %s 2>&1 | FileCheck %s -DFILE=%s --check-prefix=CHECK1 +// RUN: not llvm-tblgen -gen-asm-writer -DT2 -I %p -I %p/../../include %s 2>&1 | FileCheck %s -DFILE=%s --check-prefix=CHECK2 +// RUN: not llvm-tblgen -gen-asm-writer -DT3 -I %p -I %p/../../include %s 2>&1 | FileCheck %s -DFILE=%s --check-prefix=CHECK3 +// RUN: not llvm-tblgen -gen-asm-writer -DT4 -I %p -I %p/../../include %s 2>&1 | FileCheck %s -DFILE=%s --check-prefix=CHECK4 + +include "ConstraintChecking.inc" + +// Make sure exactly the token "=" appears. + +#ifdef T0 +// CHECK: [[FILE]]:[[@LINE+1]]:5: error: Unrecognized constraint '$dest1 != $src2' in 'Foo' +def Foo : TestInstructionWithConstraints<"$dest1 != $src2">; +#endif + +#ifdef T1 +// CHECK1: [[FILE]]:[[@LINE+1]]:5: error: Unrecognized constraint '$dest1 == $src2' in 'Foo' +def Foo : TestInstructionWithConstraints<"$dest1 == $src2">; +#endif + +#ifdef T2 +// CHECK2: [[FILE]]:[[@LINE+1]]:5: error: Unrecognized constraint '= $rhs' in 'Foo' +def Foo : TestInstructionWithConstraints<"= $rhs">; +#endif + +#ifdef T3 +// CHECK3: [[FILE]]:[[@LINE+1]]:5: error: Unrecognized constraint '$lhs =' in 'Foo' +def Foo : TestInstructionWithConstraints<"$lhs =">; +#endif + +#ifdef T4 +// CHECK4: [[FILE]]:[[@LINE+1]]:5: error: Unrecognized constraint '=' in 'Foo' +def Foo : TestInstructionWithConstraints<"=">; +#endif diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td index 5cf4e044a0fb8dd2770c45398904d8ad46bf5d61..0189d3d056fc068bc1f409730c26293f0ef4ec1a 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td @@ -114,14 +114,17 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: void GenMyCombiner::runCustomAction(unsigned ApplyID, const MatcherState &State, NewMIVector &OutMIs) const { // CHECK-NEXT: switch(ApplyID) { // CHECK-NEXT: case GICXXCustomAction_CombineApplyGICombiner0:{ +// CHECK-NEXT: Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]); // CHECK-NEXT: APPLY // CHECK-NEXT: return; // CHECK-NEXT: } // CHECK-NEXT: case GICXXCustomAction_CombineApplyGICombiner1:{ +// CHECK-NEXT: Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]); // CHECK-NEXT: APPLY MatchInfos.MDInfo0, MatchInfos.MDInfo1 // CHECK-NEXT: return; // CHECK-NEXT: } // CHECK-NEXT: case GICXXCustomAction_CombineApplyGICombiner2:{ +// CHECK-NEXT: Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]); // CHECK-NEXT: APPLY State.MIs[1]->getOperand(1) State.MIs[0]->getOperand(1) OutMIs[0] // CHECK-NEXT: return; // CHECK-NEXT: } diff --git a/llvm/test/TableGen/HwModeEncodeDecode2.td b/llvm/test/TableGen/HwModeEncodeDecode2.td index 5159501d8148eba5bee1bf271f228b25e7aad23d..cf96dda6c8bf3b40e9b98153b8bfbb63b6262a28 100644 --- a/llvm/test/TableGen/HwModeEncodeDecode2.td +++ b/llvm/test/TableGen/HwModeEncodeDecode2.td @@ -1,6 +1,6 @@ // RUN: llvm-tblgen -gen-disassembler -I %p/../../include %s | \ // RUN: FileCheck %s --check-prefix=DECODER -// RUN: llvm-tblgen -gen-disassembler --suppress-per-hwmode-duplicates -I \ +// RUN: llvm-tblgen -gen-disassembler --suppress-per-hwmode-duplicates=O2 -I \ // RUN: %p/../../include %s | FileCheck %s --check-prefix=DECODER-SUPPRESS // Test duplicate table suppression for per-HwMode decoders. @@ -105,11 +105,10 @@ let OutOperandList = (outs) in { // DECODER-DAG: Opcode: fooTypeEncA:baz // DECODER-DAG: Opcode: bar - -// DECODER-SUPPRESS-LABEL: DecoderTableAlt_AllModes32[] = -// DECODER-SUPPRESS-DAG: Opcode: unrelated -// DECODER-SUPPRESS-LABEL: DecoderTable_AllModes32[] = +// DECODER-SUPPRESS-LABEL: DecoderTable32[] = // DECODER-SUPPRESS-DAG: Opcode: bar +// DECODER-SUPPRESS-LABEL: DecoderTableAlt32[] = +// DECODER-SUPPRESS-DAG: Opcode: unrelated // DECODER-SUPPRESS-LABEL: DecoderTable_ModeA32[] = // DECODER-SUPPRESS-DAG: Opcode: fooTypeEncA:foo // DECODER-SUPPRESS-NOT: Opcode: bar diff --git a/llvm/test/TableGen/HwModeEncodeDecode3.td b/llvm/test/TableGen/HwModeEncodeDecode3.td index 406e52d25be7065a80a8b45c3102448df0c10976..8e0266b2c55af920155dda22ed9972413e14b34a 100644 --- a/llvm/test/TableGen/HwModeEncodeDecode3.td +++ b/llvm/test/TableGen/HwModeEncodeDecode3.td @@ -2,8 +2,10 @@ // RUN: FileCheck %s --check-prefix=ENCODER // RUN: llvm-tblgen -gen-disassembler -I %p/../../include %s | \ // RUN: FileCheck %s --check-prefix=DECODER -// RUN: llvm-tblgen -gen-disassembler --suppress-per-hwmode-duplicates -I \ -// RUN: %p/../../include %s | FileCheck %s --check-prefix=DECODER-SUPPRESS +// RUN: llvm-tblgen -gen-disassembler --suppress-per-hwmode-duplicates=O1 -I \ +// RUN: %p/../../include %s | FileCheck %s --check-prefix=DECODER-SUPPRESS-O1 +// RUN: llvm-tblgen -gen-disassembler --suppress-per-hwmode-duplicates=O2 -I \ +// RUN: %p/../../include %s | FileCheck %s --check-prefix=DECODER-SUPPRESS-O2 include "llvm/Target/Target.td" @@ -99,16 +101,20 @@ def unrelated: Instruction { } -// DECODER-LABEL: DecoderTableAlt_DefaultMode32[] = +// Under default settings, using 'HwMode' to dictate instruction encodings results in +// significant duplication of DecoderTables. The three tables ‘DecoderTableAlt32’, +// ‘DecoderTableAlt_ModeA32’, and ‘DecoderTableAlt_ModeB32’ are exact duplicates and +// could effectively be merged into one. +// DECODER-LABEL: DecoderTable32[] = +// DECODER-DAG: Opcode: bar +// DECODER-LABEL: DecoderTable64[] = +// DECODER-DAG: Opcode: fooTypeEncDefault:foo +// DECODER-LABEL: DecoderTableAlt32[] = // DECODER-DAG: Opcode: unrelated // DECODER-LABEL: DecoderTableAlt_ModeA32[] = // DECODER-DAG: Opcode: unrelated // DECODER-LABEL: DecoderTableAlt_ModeB32[] = // DECODER-DAG: Opcode: unrelated -// DECODER-LABEL: DecoderTable_DefaultMode32[] = -// DECODER-DAG: Opcode: bar -// DECODER-LABEL: DecoderTable_DefaultMode64[] = -// DECODER-DAG: Opcode: fooTypeEncDefault:foo // DECODER-LABEL: DecoderTable_ModeA32[] = // DECODER-DAG: Opcode: fooTypeEncA:foo // DECODER-DAG: Opcode: bar @@ -117,21 +123,42 @@ def unrelated: Instruction { // DECODER-DAG: Opcode: fooTypeEncA:baz // DECODER-DAG: Opcode: bar - -// DECODER-SUPPRESS-LABEL: DecoderTableAlt_AllModes32[] = -// DECODER-SUPPRESS-DAG: Opcode: unrelated -// DECODER-SUPPRESS-LABEL: DecoderTable_AllModes32[] = -// DECODER-SUPPRESS-DAG: Opcode: bar -// DECODER-SUPPRESS-LABEL: DecoderTable_DefaultMode64[] = -// DECODER-SUPPRESS-NOT: Opcode: bar -// DECODER-SUPPRESS-DAG: Opcode: fooTypeEncDefault:foo -// DECODER-SUPPRESS-LABEL: DecoderTable_ModeA32[] = -// DECODER-SUPPRESS-DAG: Opcode: fooTypeEncA:foo -// DECODER-SUPPRESS-NOT: Opcode: bar -// DECODER-SUPPRESS-LABEL: DecoderTable_ModeB32[] = -// DECODER-SUPPRESS-DAG: Opcode: fooTypeEncB:foo -// DECODER-SUPPRESS-DAG: Opcode: fooTypeEncA:baz -// DECODER-SUPPRESS-NOT: Opcode: bar +// Under the 'O1' optimization level, unnecessary duplicate tables will be eliminated, +// reducing the three ‘Alt’ tables down to just one. +// DECODER-SUPPRESS-O1-LABEL: DecoderTable32[] = +// DECODER-SUPPRESS-O1-DAG: Opcode: bar +// DECODER-SUPPRESS-O1-LABEL: DecoderTable64[] = +// DECODER-SUPPRESS-O1-DAG: Opcode: fooTypeEncDefault:foo +// DECODER-SUPPRESS-O1-LABEL: DecoderTableAlt32[] = +// DECODER-SUPPRESS-O1-DAG: Opcode: unrelated +// DECODER-SUPPRESS-O1-LABEL: DecoderTable_ModeA32[] = +// DECODER-SUPPRESS-O1-DAG: Opcode: fooTypeEncA:foo +// DECODER-SUPPRESS-O1-DAG: Opcode: bar +// DECODER-SUPPRESS-O1-LABEL: DecoderTable_ModeB32[] = +// DECODER-SUPPRESS-O1-DAG: Opcode: fooTypeEncB:foo +// DECODER-SUPPRESS-O1-DAG: Opcode: fooTypeEncA:baz +// DECODER-SUPPRESS-O1-DAG: Opcode: bar + +// Under the 'O2' optimization condition, instructions possessing the 'EncodingByHwMode' +// attribute will be extracted from their original DecoderNamespace and placed into their +// respective HwMode tables. Meanwhile, other instructions that do not have the 'EncodingByHwMode' +// attribute but are within the same DecoderNamespace will be stored in the 'Default' table. This +// approach will significantly reduce instruction redundancy, but it necessitates users to thoroughly +// consider the interplay between HwMode and DecoderNamespace for their instructions. +// DECODER-SUPPRESS-O2-LABEL: DecoderTable32[] = +// DECODER-SUPPRESS-O2-DAG: Opcode: bar +// DECODER-SUPPRESS-O2-LABEL: DecoderTable64[] = +// DECODER-SUPPRESS-O2-NOT: Opcode: bar +// DECODER-SUPPRESS-O2-DAG: Opcode: fooTypeEncDefault:foo +// DECODER-SUPPRESS-O2-LABEL: DecoderTableAlt32[] = +// DECODER-SUPPRESS-O2-DAG: Opcode: unrelated +// DECODER-SUPPRESS-O2-LABEL: DecoderTable_ModeA32[] = +// DECODER-SUPPRESS-O2-DAG: Opcode: fooTypeEncA:foo +// DECODER-SUPPRESS-O2-NOT: Opcode: bar +// DECODER-SUPPRESS-O2-LABEL: DecoderTable_ModeB32[] = +// DECODER-SUPPRESS-O2-DAG: Opcode: fooTypeEncB:foo +// DECODER-SUPPRESS-O2-DAG: Opcode: fooTypeEncA:baz +// DECODER-SUPPRESS-O2-NOT: Opcode: bar // ENCODER-LABEL: static const uint64_t InstBits_DefaultMode[] = { // ENCODER: UINT64_C(2), // bar diff --git a/llvm/test/TableGen/HwModeSubRegs.td b/llvm/test/TableGen/HwModeSubRegs.td new file mode 100644 index 0000000000000000000000000000000000000000..2bf7a917979d9936eb22d0e2c7f513fccf474e8f --- /dev/null +++ b/llvm/test/TableGen/HwModeSubRegs.td @@ -0,0 +1,75 @@ +// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o /dev/null 2>&1 | FileCheck %s +include "llvm/Target/Target.td" + +def HasFeat : Predicate<"Subtarget->hasFeat()">; + +def TestMode : HwMode<"+feat1", [HasFeat]>; + +class MyReg<string n> + : Register<n> { + let Namespace = "Test"; +} +class MyClass<int size, list<ValueType> types, dag registers> + : RegisterClass<"Test", types, size, registers> { + let Size = size; +} + +def X0 : MyReg<"x0">; +def X1 : MyReg<"x1">; +def X2 : MyReg<"x2">; +def X3 : MyReg<"x3">; +def X4 : MyReg<"x4">; +def X5 : MyReg<"x5">; +def X6 : MyReg<"x6">; +def X7 : MyReg<"x7">; +def X8 : MyReg<"x8">; +def X9 : MyReg<"x9">; +def X10 : MyReg<"x10">; +def X11 : MyReg<"x11">; +def X12 : MyReg<"x12">; +def X13 : MyReg<"x13">; +def X14 : MyReg<"x14">; +def X15 : MyReg<"x15">; + +def ModeVT : ValueTypeByHwMode<[DefaultMode, TestMode], + [i32, i64]>; +let RegInfos = RegInfoByHwMode<[DefaultMode, TestMode], + [RegInfo<32,32,32>, RegInfo<64,64,64>]> in +def XRegs : MyClass<32, [ModeVT], (sequence "X%u", 0, 15)>; + +def sub_even : SubRegIndex<32> { + let SubRegRanges = SubRegRangeByHwMode<[DefaultMode, TestMode], + [SubRegRange<32>, SubRegRange<64>]>; +} +def sub_odd : SubRegIndex<32, 32> { + let SubRegRanges = SubRegRangeByHwMode<[DefaultMode, TestMode], + [SubRegRange<32, 32>, SubRegRange<64, 64>]>; +} + +def XPairs : RegisterTuples<[sub_even, sub_odd], + [(decimate (rotl XRegs, 0), 2), + (decimate (rotl XRegs, 1), 2)]>; + +let RegInfos = RegInfoByHwMode<[DefaultMode, TestMode], + [RegInfo<64,64,32>, RegInfo<128,128,64>]> in +def XPairsClass : MyClass<64, [untyped], (add XPairs)>; + +def TestTarget : Target; + +// CHECK-LABEL: RegisterClass XRegs: +// CHECK: SpillSize: { Default:32 TestMode:64 } +// CHECK: SpillAlignment: { Default:32 TestMode:64 } +// CHECK: Regs: X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 + +// CHECK-LABEL: RegisterClass XPairsClass: +// CHECK: SpillSize: { Default:64 TestMode:128 } +// CHECK: SpillAlignment: { Default:32 TestMode:64 } +// CHECK: CoveredBySubRegs: 1 +// CHECK: Regs: X0_X1 X2_X3 X4_X5 X6_X7 X8_X9 X10_X11 X12_X13 X14_X15 + +// CHECK-LABEL: SubRegIndex sub_even: +// CHECK: Offset: { Default:0 TestMode:0 } +// CHECK: Size: { Default:32 TestMode:64 } +// CHECK-LABEL: SubRegIndex sub_odd: +// CHECK: Offset: { Default:32 TestMode:64 } +// CHECK: Size: { Default:32 TestMode:64 } diff --git a/llvm/test/TableGen/MacroFusion.td b/llvm/test/TableGen/MacroFusion.td index ce76e7f0f7fa64ed205f9c7fda42eb95e9cead24..6cf22f5447150b2fcd846ad46fd373e85b28c131 100644 --- a/llvm/test/TableGen/MacroFusion.td +++ b/llvm/test/TableGen/MacroFusion.td @@ -33,6 +33,8 @@ let Namespace = "Test" in { def Inst0 : TestInst<0>; def Inst1 : TestInst<1>; +let isCommutable = true in +def Inst2 : TestInst<2>; def BothFusionPredicate: BothFusionPredicateWithMCInstPredicate<CheckRegOperand<0, X0>>; def TestBothFusionPredicate: Fusion<"test-both-fusion-predicate", "HasBothFusionPredicate", @@ -42,16 +44,32 @@ def TestBothFusionPredicate: Fusion<"test-both-fusion-predicate", "HasBothFusion def TestFusion: SimpleFusion<"test-fusion", "HasTestFusion", "Test Fusion", CheckOpcode<[Inst0]>, CheckAll<[ - CheckOpcode<[Inst1]>, - CheckRegOperand<0, X0> + CheckOpcode<[Inst1]>, + CheckRegOperand<0, X0> ]>>; +let IsCommutable = 1 in +def TestCommutableFusion: SimpleFusion<"test-commutable-fusion", "HasTestCommutableFusion", + "Test Commutable Fusion", + CheckOpcode<[Inst0]>, + CheckAll<[ + CheckOpcode<[Inst1]>, + CheckRegOperand<0, X0> + ]>>; + +def TestSingleFusion: SingleFusion<"test-single-fusion", "HasTestSingleFusion", + "Test SingleFusion", + Inst0, Inst2, + secondInstPred=CheckRegOperand<0, X0>>; + // CHECK-PREDICATOR: #ifdef GET_Test_MACRO_FUSION_PRED_DECL // CHECK-PREDICATOR-NEXT: #undef GET_Test_MACRO_FUSION_PRED_DECL // CHECK-PREDICATOR-EMPTY: // CHECK-PREDICATOR-NEXT: namespace llvm { // CHECK-PREDICATOR-NEXT: bool isTestBothFusionPredicate(const TargetInstrInfo &, const TargetSubtargetInfo &, const MachineInstr *, const MachineInstr &); +// CHECK-PREDICATOR-NEXT: bool isTestCommutableFusion(const TargetInstrInfo &, const TargetSubtargetInfo &, const MachineInstr *, const MachineInstr &); // CHECK-PREDICATOR-NEXT: bool isTestFusion(const TargetInstrInfo &, const TargetSubtargetInfo &, const MachineInstr *, const MachineInstr &); +// CHECK-PREDICATOR-NEXT: bool isTestSingleFusion(const TargetInstrInfo &, const TargetSubtargetInfo &, const MachineInstr *, const MachineInstr &); // CHECK-PREDICATOR-NEXT: } // end namespace llvm // CHECK-PREDICATOR-EMPTY: // CHECK-PREDICATOR-NEXT: #endif @@ -65,7 +83,7 @@ def TestFusion: SimpleFusion<"test-fusion", "HasTestFusion", "Test Fusion", // CHECK-PREDICATOR-NEXT: const TargetSubtargetInfo &STI, // CHECK-PREDICATOR-NEXT: const MachineInstr *FirstMI, // CHECK-PREDICATOR-NEXT: const MachineInstr &SecondMI) { -// CHECK-PREDICATOR-NEXT: auto &MRI = SecondMI.getMF()->getRegInfo(); +// CHECK-PREDICATOR-NEXT: {{[[]}}{{[[]}}maybe_unused{{[]]}}{{[]]}} auto &MRI = SecondMI.getMF()->getRegInfo(); // CHECK-PREDICATOR-NEXT: { // CHECK-PREDICATOR-NEXT: const MachineInstr *MI = FirstMI; // CHECK-PREDICATOR-NEXT: if (MI->getOperand(0).getReg() != Test::X0) @@ -78,12 +96,12 @@ def TestFusion: SimpleFusion<"test-fusion", "HasTestFusion", "Test Fusion", // CHECK-PREDICATOR-NEXT: } // CHECK-PREDICATOR-NEXT: return true; // CHECK-PREDICATOR-NEXT: } -// CHECK-PREDICATOR-NEXT: bool isTestFusion( +// CHECK-PREDICATOR-NEXT: bool isTestCommutableFusion( // CHECK-PREDICATOR-NEXT: const TargetInstrInfo &TII, // CHECK-PREDICATOR-NEXT: const TargetSubtargetInfo &STI, // CHECK-PREDICATOR-NEXT: const MachineInstr *FirstMI, // CHECK-PREDICATOR-NEXT: const MachineInstr &SecondMI) { -// CHECK-PREDICATOR-NEXT: auto &MRI = SecondMI.getMF()->getRegInfo(); +// CHECK-PREDICATOR-NEXT: {{[[]}}{{[[]}}maybe_unused{{[]]}}{{[]]}} auto &MRI = SecondMI.getMF()->getRegInfo(); // CHECK-PREDICATOR-NEXT: { // CHECK-PREDICATOR-NEXT: const MachineInstr *MI = &SecondMI; // CHECK-PREDICATOR-NEXT: if (!( @@ -99,14 +117,58 @@ def TestFusion: SimpleFusion<"test-fusion", "HasTestFusion", "Test Fusion", // CHECK-PREDICATOR-NEXT: if (( MI->getOpcode() != Test::Inst0 )) // CHECK-PREDICATOR-NEXT: return false; // CHECK-PREDICATOR-NEXT: } +// CHECK-PREDICATOR-NEXT: if (!SecondMI.getOperand(0).getReg().isVirtual()) { +// CHECK-PREDICATOR-NEXT: if (SecondMI.getOperand(0).getReg() != SecondMI.getOperand(1).getReg()) { +// CHECK-PREDICATOR-NEXT: if (!SecondMI.getDesc().isCommutable()) +// CHECK-PREDICATOR-NEXT: return false; +// CHECK-PREDICATOR-NEXT: unsigned SrcOpIdx1 = 1, SrcOpIdx2 = TargetInstrInfo::CommuteAnyOperandIndex; +// CHECK-PREDICATOR-NEXT: if (TII.findCommutedOpIndices(SecondMI, SrcOpIdx1, SrcOpIdx2)) +// CHECK-PREDICATOR-NEXT: if (SecondMI.getOperand(0).getReg() != SecondMI.getOperand(SrcOpIdx2).getReg()) +// CHECK-PREDICATOR-NEXT: return false; +// CHECK-PREDICATOR-NEXT: } +// CHECK-PREDICATOR-NEXT: } +// CHECK-PREDICATOR-NEXT: { +// CHECK-PREDICATOR-NEXT: Register FirstDest = FirstMI->getOperand(0).getReg(); +// CHECK-PREDICATOR-NEXT: if (FirstDest.isVirtual() && !MRI.hasOneNonDBGUse(FirstDest)) +// CHECK-PREDICATOR-NEXT: return false; +// CHECK-PREDICATOR-NEXT: } +// CHECK-PREDICATOR-NEXT: if (!(FirstMI->getOperand(0).isReg() && +// CHECK-PREDICATOR-NEXT: SecondMI.getOperand(1).isReg() && +// CHECK-PREDICATOR-NEXT: FirstMI->getOperand(0).getReg() == SecondMI.getOperand(1).getReg())) { +// CHECK-PREDICATOR-NEXT: if (!SecondMI.getDesc().isCommutable()) +// CHECK-PREDICATOR-NEXT: return false; +// CHECK-PREDICATOR-NEXT: unsigned SrcOpIdx1 = 1, SrcOpIdx2 = TargetInstrInfo::CommuteAnyOperandIndex; +// CHECK-PREDICATOR-NEXT: if (TII.findCommutedOpIndices(SecondMI, SrcOpIdx1, SrcOpIdx2)) +// CHECK-PREDICATOR-NEXT: if (FirstMI->getOperand(0).getReg() != SecondMI.getOperand(SrcOpIdx2).getReg()) +// CHECK-PREDICATOR-NEXT: return false; +// CHECK-PREDICATOR-NEXT: } +// CHECK-PREDICATOR-NEXT: return true; +// CHECK-PREDICATOR-NEXT: } +// CHECK-PREDICATOR-NEXT: bool isTestFusion( +// CHECK-PREDICATOR-NEXT: const TargetInstrInfo &TII, +// CHECK-PREDICATOR-NEXT: const TargetSubtargetInfo &STI, +// CHECK-PREDICATOR-NEXT: const MachineInstr *FirstMI, +// CHECK-PREDICATOR-NEXT: const MachineInstr &SecondMI) { +// CHECK-PREDICATOR-NEXT: {{[[]}}{{[[]}}maybe_unused{{[]]}}{{[]]}} auto &MRI = SecondMI.getMF()->getRegInfo(); // CHECK-PREDICATOR-NEXT: { // CHECK-PREDICATOR-NEXT: const MachineInstr *MI = &SecondMI; // CHECK-PREDICATOR-NEXT: if (!( -// CHECK-PREDICATOR-NEXT: MI->getOperand(0).getReg().isVirtual() -// CHECK-PREDICATOR-NEXT: || MI->getOperand(0).getReg() == MI->getOperand(1).getReg() +// CHECK-PREDICATOR-NEXT: ( MI->getOpcode() == Test::Inst1 ) +// CHECK-PREDICATOR-NEXT: && MI->getOperand(0).getReg() == Test::X0 // CHECK-PREDICATOR-NEXT: )) // CHECK-PREDICATOR-NEXT: return false; // CHECK-PREDICATOR-NEXT: } +// CHECK-PREDICATOR-NEXT: if (!FirstMI) +// CHECK-PREDICATOR-NEXT: return true; +// CHECK-PREDICATOR-NEXT: { +// CHECK-PREDICATOR-NEXT: const MachineInstr *MI = FirstMI; +// CHECK-PREDICATOR-NEXT: if (( MI->getOpcode() != Test::Inst0 )) +// CHECK-PREDICATOR-NEXT: return false; +// CHECK-PREDICATOR-NEXT: } +// CHECK-PREDICATOR-NEXT: if (!SecondMI.getOperand(0).getReg().isVirtual()) { +// CHECK-PREDICATOR-NEXT: if (SecondMI.getOperand(0).getReg() != SecondMI.getOperand(1).getReg()) +// CHECK-PREDICATOR-NEXT: return false; +// CHECK-PREDICATOR-NEXT: } // CHECK-PREDICATOR-NEXT: { // CHECK-PREDICATOR-NEXT: Register FirstDest = FirstMI->getOperand(0).getReg(); // CHECK-PREDICATOR-NEXT: if (FirstDest.isVirtual() && !MRI.hasOneNonDBGUse(FirstDest)) @@ -118,12 +180,66 @@ def TestFusion: SimpleFusion<"test-fusion", "HasTestFusion", "Test Fusion", // CHECK-PREDICATOR-NEXT: return false; // CHECK-PREDICATOR-NEXT: return true; // CHECK-PREDICATOR-NEXT: } +// CHECK-PREDICATOR-NEXT: bool isTestSingleFusion( +// CHECK-PREDICATOR-NEXT: const TargetInstrInfo &TII, +// CHECK-PREDICATOR-NEXT: const TargetSubtargetInfo &STI, +// CHECK-PREDICATOR-NEXT: const MachineInstr *FirstMI, +// CHECK-PREDICATOR-NEXT: const MachineInstr &SecondMI) { +// CHECK-PREDICATOR-NEXT: {{[[]}}{{[[]}}maybe_unused{{[]]}}{{[]]}} auto &MRI = SecondMI.getMF()->getRegInfo(); +// CHECK-PREDICATOR-NEXT: { +// CHECK-PREDICATOR-NEXT: const MachineInstr *MI = &SecondMI; +// CHECK-PREDICATOR-NEXT: if (!( +// CHECK-PREDICATOR-NEXT: ( MI->getOpcode() == Test::Inst2 ) +// CHECK-PREDICATOR-NEXT: && MI->getOperand(0).getReg() == Test::X0 +// CHECK-PREDICATOR-NEXT: )) +// CHECK-PREDICATOR-NEXT: return false; +// CHECK-PREDICATOR-NEXT: } +// CHECK-PREDICATOR-NEXT: if (!FirstMI) +// CHECK-PREDICATOR-NEXT: return true; +// CHECK-PREDICATOR-NEXT: { +// CHECK-PREDICATOR-NEXT: const MachineInstr *MI = FirstMI; +// CHECK-PREDICATOR-NEXT: if (!( +// CHECK-PREDICATOR-NEXT: ( MI->getOpcode() == Test::Inst0 ) +// CHECK-PREDICATOR-NEXT: && true +// CHECK-PREDICATOR-NEXT: )) +// CHECK-PREDICATOR-NEXT: return false; +// CHECK-PREDICATOR-NEXT: } +// CHECK-PREDICATOR-NEXT: if (!SecondMI.getOperand(0).getReg().isVirtual()) { +// CHECK-PREDICATOR-NEXT: if (SecondMI.getOperand(0).getReg() != SecondMI.getOperand(1).getReg()) { +// CHECK-PREDICATOR-NEXT: if (!SecondMI.getDesc().isCommutable()) +// CHECK-PREDICATOR-NEXT: return false; +// CHECK-PREDICATOR-NEXT: unsigned SrcOpIdx1 = 1, SrcOpIdx2 = TargetInstrInfo::CommuteAnyOperandIndex; +// CHECK-PREDICATOR-NEXT: if (TII.findCommutedOpIndices(SecondMI, SrcOpIdx1, SrcOpIdx2)) +// CHECK-PREDICATOR-NEXT: if (SecondMI.getOperand(0).getReg() != SecondMI.getOperand(SrcOpIdx2).getReg()) +// CHECK-PREDICATOR-NEXT: return false; +// CHECK-PREDICATOR-NEXT: } +// CHECK-PREDICATOR-NEXT: } +// CHECK-PREDICATOR-NEXT: { +// CHECK-PREDICATOR-NEXT: Register FirstDest = FirstMI->getOperand(0).getReg(); +// CHECK-PREDICATOR-NEXT: if (FirstDest.isVirtual() && !MRI.hasOneNonDBGUse(FirstDest)) +// CHECK-PREDICATOR-NEXT: return false; +// CHECK-PREDICATOR-NEXT: } +// CHECK-PREDICATOR-NEXT: if (!(FirstMI->getOperand(0).isReg() && +// CHECK-PREDICATOR-NEXT: SecondMI.getOperand(1).isReg() && +// CHECK-PREDICATOR-NEXT: FirstMI->getOperand(0).getReg() == SecondMI.getOperand(1).getReg())) { +// CHECK-PREDICATOR-NEXT: if (!SecondMI.getDesc().isCommutable()) +// CHECK-PREDICATOR-NEXT: return false; +// CHECK-PREDICATOR-NEXT: unsigned SrcOpIdx1 = 1, SrcOpIdx2 = TargetInstrInfo::CommuteAnyOperandIndex; +// CHECK-PREDICATOR-NEXT: if (TII.findCommutedOpIndices(SecondMI, SrcOpIdx1, SrcOpIdx2)) +// CHECK-PREDICATOR-NEXT: if (FirstMI->getOperand(0).getReg() != SecondMI.getOperand(SrcOpIdx2).getReg()) +// CHECK-PREDICATOR-NEXT: return false; +// CHECK-PREDICATOR-NEXT: } +// CHECK-PREDICATOR-NEXT: return true; +// CHECK-PREDICATOR-NEXT: } // CHECK-PREDICATOR-NEXT: } // end namespace llvm // CHECK-PREDICATOR-EMPTY: // CHECK-PREDICATOR-NEXT: #endif // Check that we have generated target subfeature. +// CHECK-SUBTARGET: { "test-both-fusion-predicate", "Test BothFusionPredicate", Test::TestBothFusionPredicate +// CHECK-SUBTARGET: { "test-commutable-fusion", "Test Commutable Fusion", Test::TestCommutableFusion // CHECK-SUBTARGET: { "test-fusion", "Test Fusion", Test::TestFusion +// CHECK-SUBTARGET: { "test-single-fusion", "Test SingleFusion", Test::TestSingleFusion // Check that we have generated `getMacroFusions()` function. // CHECK-SUBTARGET: std::vector<MacroFusionPredTy> getMacroFusions() const override; @@ -131,6 +247,8 @@ def TestFusion: SimpleFusion<"test-fusion", "HasTestFusion", "Test Fusion", // CHECK-SUBTARGET: std::vector<MacroFusionPredTy> TestGenSubtargetInfo::getMacroFusions() const { // CHECK-SUBTARGET-NEXT: std::vector<MacroFusionPredTy> Fusions; // CHECK-SUBTARGET-NEXT: if (hasFeature(Test::TestBothFusionPredicate)) Fusions.push_back(llvm::isTestBothFusionPredicate); +// CHECK-SUBTARGET-NEXT: if (hasFeature(Test::TestCommutableFusion)) Fusions.push_back(llvm::isTestCommutableFusion); // CHECK-SUBTARGET-NEXT: if (hasFeature(Test::TestFusion)) Fusions.push_back(llvm::isTestFusion); +// CHECK-SUBTARGET-NEXT: if (hasFeature(Test::TestSingleFusion)) Fusions.push_back(llvm::isTestSingleFusion); // CHECK-SUBTARGET-NEXT: return Fusions; // CHECK-SUBTARGET-NEXT: } diff --git a/llvm/test/TableGen/x86-fold-tables.inc b/llvm/test/TableGen/x86-fold-tables.inc index eea4f87cae9cec4f5560decd679630d48cfa9bad..4ab5567f6287634c9bae7142a0d635a12c482462 100644 --- a/llvm/test/TableGen/x86-fold-tables.inc +++ b/llvm/test/TableGen/x86-fold-tables.inc @@ -756,6 +756,12 @@ static const X86FoldTableEntry Table1[] = { {X86::IMUL64rri32_NF, X86::IMUL64rmi32_NF, 0}, {X86::IMUL64rri8, X86::IMUL64rmi8, 0}, {X86::IMUL64rri8_NF, X86::IMUL64rmi8_NF, 0}, + {X86::IMULZU16rri, X86::IMULZU16rmi, 0}, + {X86::IMULZU16rri8, X86::IMULZU16rmi8, 0}, + {X86::IMULZU32rri, X86::IMULZU32rmi, 0}, + {X86::IMULZU32rri8, X86::IMULZU32rmi8, 0}, + {X86::IMULZU64rri32, X86::IMULZU64rmi32, 0}, + {X86::IMULZU64rri8, X86::IMULZU64rmi8, 0}, {X86::INC16r_ND, X86::INC16m_ND, 0}, {X86::INC16r_NF_ND, X86::INC16m_NF_ND, 0}, {X86::INC32r_ND, X86::INC32m_ND, 0}, @@ -1937,8 +1943,11 @@ static const X86FoldTableEntry Table2[] = { {X86::BLENDVPDrr0, X86::BLENDVPDrm0, TB_ALIGN_16}, {X86::BLENDVPSrr0, X86::BLENDVPSrm0, TB_ALIGN_16}, {X86::CMOV16rr, X86::CMOV16rm, 0}, + {X86::CMOV16rr_ND, X86::CMOV16rm_ND, 0}, {X86::CMOV32rr, X86::CMOV32rm, 0}, + {X86::CMOV32rr_ND, X86::CMOV32rm_ND, 0}, {X86::CMOV64rr, X86::CMOV64rm, 0}, + {X86::CMOV64rr_ND, X86::CMOV64rm_ND, 0}, {X86::CMPPDrri, X86::CMPPDrmi, TB_ALIGN_16}, {X86::CMPPSrri, X86::CMPPSrmi, TB_ALIGN_16}, {X86::CMPSDrri, X86::CMPSDrmi, 0}, diff --git a/llvm/test/ThinLTO/X86/Inputs/devirt_single_hybrid_bar.ll b/llvm/test/ThinLTO/X86/Inputs/devirt_single_hybrid_bar.ll index 721d6efb7b53f8031e32d24979ee449e23c5335a..d8c6525ed6065fa1a7408e74a9e75edd62ee9ad3 100644 --- a/llvm/test/ThinLTO/X86/Inputs/devirt_single_hybrid_bar.ll +++ b/llvm/test/ThinLTO/X86/Inputs/devirt_single_hybrid_bar.ll @@ -23,7 +23,7 @@ define hidden i32 @_Z3barv() local_unnamed_addr #0 { entry: %b = alloca %struct.A, align 8 call void @llvm.lifetime.start.p0(i64 8, ptr nonnull %b) - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %b, align 8, !tbaa !4 + store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %b, align 8, !tbaa !4 %call = call i32 @_Z3fooP1A(ptr nonnull %b) %add = add nsw i32 %call, 10 call void @llvm.lifetime.end.p0(i64 8, ptr nonnull %b) #4 diff --git a/llvm/test/ThinLTO/X86/devirt_after_filtering_unreachable.ll b/llvm/test/ThinLTO/X86/devirt_after_filtering_unreachable.ll index 68b83debef7d35a63e603c93547a6e3fb5acf84a..39f42da77d81618809179eed0aec9119b10cd989 100644 --- a/llvm/test/ThinLTO/X86/devirt_after_filtering_unreachable.ll +++ b/llvm/test/ThinLTO/X86/devirt_after_filtering_unreachable.ll @@ -71,7 +71,7 @@ target triple = "x86_64-unknown-linux-gnu" define hidden i32 @main() { entry: %call = tail call ptr @_Znwm(i64 8) - store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV7Derived, i64 0, inrange i32 0, i64 2), ptr %call + store ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV7Derived, i64 0, i32 0, i64 2), ptr %call tail call void @_Z3fooP4Base(ptr nonnull %call) ret i32 0 } diff --git a/llvm/test/ThinLTO/X86/devirt_external_comdat_same_guid.ll b/llvm/test/ThinLTO/X86/devirt_external_comdat_same_guid.ll index 241753256804360468935ef93278ecaa1f2ab625..1f0737b71925418241c55b57611fc10adbe356f8 100644 --- a/llvm/test/ThinLTO/X86/devirt_external_comdat_same_guid.ll +++ b/llvm/test/ThinLTO/X86/devirt_external_comdat_same_guid.ll @@ -51,7 +51,7 @@ define i32 @_ZN1B1nEi(ptr %this, i32 %a) #0 comdat($_ZTV1B) { ; Ensures that vtable of B is live so that we will attempt devirt. define dso_local i32 @use_B(ptr %a) { entry: - store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1B, i64 0, inrange i32 0, i64 2), ptr %a, align 8 + store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1B, i64 0, i32 0, i64 2), ptr %a, align 8 ret i32 0 } diff --git a/llvm/test/ThinLTO/X86/devirt_local_same_guid.ll b/llvm/test/ThinLTO/X86/devirt_local_same_guid.ll index 3efea8de3fbc6b88d049b41c851f654e6e8ea60f..2205545e32507a031df17e88f1b81f209ea853a5 100644 --- a/llvm/test/ThinLTO/X86/devirt_local_same_guid.ll +++ b/llvm/test/ThinLTO/X86/devirt_local_same_guid.ll @@ -37,7 +37,7 @@ define internal i32 @_ZN1B1nEi(ptr %this, i32 %a) #0 { ; Ensures that vtable of B is live so that we will attempt devirt. define dso_local i32 @use_B(ptr %a) { entry: - store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1B, i64 0, inrange i32 0, i64 2), ptr %a, align 8 + store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1B, i64 0, i32 0, i64 2), ptr %a, align 8 ret i32 0 } diff --git a/llvm/test/ThinLTO/X86/lower_type_test_phi.ll b/llvm/test/ThinLTO/X86/lower_type_test_phi.ll index 722ffe3cc2282cfc92f00a2dc982139136fa94f9..81d85f64584fa28499047c3525b94420f5e46605 100644 --- a/llvm/test/ThinLTO/X86/lower_type_test_phi.ll +++ b/llvm/test/ThinLTO/X86/lower_type_test_phi.ll @@ -117,7 +117,7 @@ $_ZTV2D2 = comdat any define ptr @_Z2b1v() { entry: %call = tail call ptr @_Znwm(i64 8) - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV2D1, i64 0, inrange i32 0, i64 2), ptr %call, align 8 + store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV2D1, i64 0, i32 0, i64 2), ptr %call, align 8 ret ptr %call } @@ -126,7 +126,7 @@ declare ptr @_Znwm(i64) define ptr @_Z2b2v() { entry: %call = tail call ptr @_Znwm(i64 8) - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV2D2, i64 0, inrange i32 0, i64 2), ptr %call, align 8 + store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV2D2, i64 0, i32 0, i64 2), ptr %call, align 8 ret ptr %call } diff --git a/llvm/test/ThinLTO/X86/nodevirt-nonpromoted-typeid.ll b/llvm/test/ThinLTO/X86/nodevirt-nonpromoted-typeid.ll index c6e61edcd97a94d8b1dcf82f32fe5c4cd69c148b..7d71c595fbb1685e54b7fbe4007c6fb76fc56dd6 100644 --- a/llvm/test/ThinLTO/X86/nodevirt-nonpromoted-typeid.ll +++ b/llvm/test/ThinLTO/X86/nodevirt-nonpromoted-typeid.ll @@ -55,7 +55,7 @@ entry: %this.addr = alloca ptr, align 8 store ptr %this, ptr %this.addr, align 8 %this1 = load ptr, ptr %this.addr - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1D, i64 0, inrange i32 0, i64 2), ptr %this1, align 8 + store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1D, i64 0, i32 0, i64 2), ptr %this1, align 8 ret void } diff --git a/llvm/test/ThinLTO/X86/pseudo-probe-desc-import.ll b/llvm/test/ThinLTO/X86/pseudo-probe-desc-import.ll index 21dd8c0fe924148c0bba1e85c1ff65bcbbf30d83..f915aaccc06e1762799bad4586f4e36c32f8811e 100644 --- a/llvm/test/ThinLTO/X86/pseudo-probe-desc-import.ll +++ b/llvm/test/ThinLTO/X86/pseudo-probe-desc-import.ll @@ -12,8 +12,8 @@ ; RUN: llvm-lto -thinlto-action=import %t3.bc -thinlto-index=%t3.index.bc -o /dev/null 2>&1 | FileCheck %s --check-prefix=WARN -; CHECK-NOT: {i64 6699318081062747564, i64 4294967295, !"foo" -; CHECK: !{i64 -2624081020897602054, i64 281479271677951, !"main" +; CHECK-NOT: {i64 6699318081062747564, i64 [[#]], !"foo" +; CHECK: !{i64 -2624081020897602054, i64 [[#]], !"main" ; WARN: warning: Pseudo-probe ignored: source module '{{.*}}' is compiled with -fpseudo-probe-for-profiling while destination module '{{.*}}' is not diff --git a/llvm/test/ThinLTO/X86/type_test_noindircall.ll b/llvm/test/ThinLTO/X86/type_test_noindircall.ll index 2d0faaa2560237b44bebf0eef680b900b1705867..cc85e44c280621fb9519d609b1615d166693301a 100644 --- a/llvm/test/ThinLTO/X86/type_test_noindircall.ll +++ b/llvm/test/ThinLTO/X86/type_test_noindircall.ll @@ -38,8 +38,8 @@ target triple = "x86_64-grtev4-linux-gnu" define internal void @_ZN12_GLOBAL__N_18RealFileD2Ev(ptr %this) unnamed_addr #0 align 2 { entry: ; CHECK-IR: store - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN12_GLOBAL__N_18RealFileE, i64 0, inrange i32 0, i64 2), ptr %this, align 8 - %0 = tail call i1 @llvm.type.test(ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN12_GLOBAL__N_18RealFileE, i64 0, inrange i32 0, i64 2), metadata !"4$09c6cc733fc6accb91e5d7b87cb48f2d") + store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN12_GLOBAL__N_18RealFileE, i64 0, i32 0, i64 2), ptr %this, align 8 + %0 = tail call i1 @llvm.type.test(ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN12_GLOBAL__N_18RealFileE, i64 0, i32 0, i64 2), metadata !"4$09c6cc733fc6accb91e5d7b87cb48f2d") tail call void @llvm.assume(i1 %0) ; CHECK-IR-NEXT: ret void ret void diff --git a/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-rmw-fadd.ll b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-rmw-fadd.ll index b6e6b260249523ac0e3a5222f960475d8686c3fe..a5d4c329446f9db0e68d6ec0beb3e3f05d678d37 100644 --- a/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-rmw-fadd.ll +++ b/llvm/test/Transforms/AtomicExpand/AMDGPU/expand-atomic-rmw-fadd.ll @@ -3028,7 +3028,7 @@ define bfloat @test_atomicrmw_fadd_bf16_global_system_align4(ptr addrspace(1) %p define bfloat @test_atomicrmw_fadd_bf16_local_strictfp(ptr addrspace(3) %ptr, bfloat %value) #2 { ; CI-LABEL: @test_atomicrmw_fadd_bf16_local_strictfp( -; CI-NEXT: [[ALIGNEDADDR:%.*]] = call ptr addrspace(3) @llvm.ptrmask.p3.i32(ptr addrspace(3) [[PTR:%.*]], i32 -4) +; CI-NEXT: [[ALIGNEDADDR:%.*]] = call ptr addrspace(3) @llvm.ptrmask.p3.i32(ptr addrspace(3) [[PTR:%.*]], i32 -4) #[[ATTR6]] ; CI-NEXT: [[TMP1:%.*]] = ptrtoint ptr addrspace(3) [[PTR]] to i32 ; CI-NEXT: [[PTRLSB:%.*]] = and i32 [[TMP1]], 3 ; CI-NEXT: [[TMP2:%.*]] = shl i32 [[PTRLSB]], 3 @@ -3041,7 +3041,7 @@ define bfloat @test_atomicrmw_fadd_bf16_local_strictfp(ptr addrspace(3) %ptr, bf ; CI-NEXT: [[SHIFTED:%.*]] = lshr i32 [[LOADED]], [[TMP2]] ; CI-NEXT: [[EXTRACTED:%.*]] = trunc i32 [[SHIFTED]] to i16 ; CI-NEXT: [[TMP4:%.*]] = bitcast i16 [[EXTRACTED]] to bfloat -; CI-NEXT: [[NEW:%.*]] = fadd bfloat [[TMP4]], [[VALUE:%.*]] +; CI-NEXT: [[NEW:%.*]] = call bfloat @llvm.experimental.constrained.fadd.bf16(bfloat [[TMP4]], bfloat [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR6]] ; CI-NEXT: [[TMP5:%.*]] = bitcast bfloat [[NEW]] to i16 ; CI-NEXT: [[EXTENDED:%.*]] = zext i16 [[TMP5]] to i32 ; CI-NEXT: [[SHIFTED1:%.*]] = shl nuw i32 [[EXTENDED]], [[TMP2]] @@ -3058,7 +3058,7 @@ define bfloat @test_atomicrmw_fadd_bf16_local_strictfp(ptr addrspace(3) %ptr, bf ; CI-NEXT: ret bfloat [[TMP7]] ; ; GFX9-LABEL: @test_atomicrmw_fadd_bf16_local_strictfp( -; GFX9-NEXT: [[ALIGNEDADDR:%.*]] = call ptr addrspace(3) @llvm.ptrmask.p3.i32(ptr addrspace(3) [[PTR:%.*]], i32 -4) +; GFX9-NEXT: [[ALIGNEDADDR:%.*]] = call ptr addrspace(3) @llvm.ptrmask.p3.i32(ptr addrspace(3) [[PTR:%.*]], i32 -4) #[[ATTR6]] ; GFX9-NEXT: [[TMP1:%.*]] = ptrtoint ptr addrspace(3) [[PTR]] to i32 ; GFX9-NEXT: [[PTRLSB:%.*]] = and i32 [[TMP1]], 3 ; GFX9-NEXT: [[TMP2:%.*]] = shl i32 [[PTRLSB]], 3 @@ -3071,7 +3071,7 @@ define bfloat @test_atomicrmw_fadd_bf16_local_strictfp(ptr addrspace(3) %ptr, bf ; GFX9-NEXT: [[SHIFTED:%.*]] = lshr i32 [[LOADED]], [[TMP2]] ; GFX9-NEXT: [[EXTRACTED:%.*]] = trunc i32 [[SHIFTED]] to i16 ; GFX9-NEXT: [[TMP4:%.*]] = bitcast i16 [[EXTRACTED]] to bfloat -; GFX9-NEXT: [[NEW:%.*]] = fadd bfloat [[TMP4]], [[VALUE:%.*]] +; GFX9-NEXT: [[NEW:%.*]] = call bfloat @llvm.experimental.constrained.fadd.bf16(bfloat [[TMP4]], bfloat [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR6]] ; GFX9-NEXT: [[TMP5:%.*]] = bitcast bfloat [[NEW]] to i16 ; GFX9-NEXT: [[EXTENDED:%.*]] = zext i16 [[TMP5]] to i32 ; GFX9-NEXT: [[SHIFTED1:%.*]] = shl nuw i32 [[EXTENDED]], [[TMP2]] @@ -3088,7 +3088,7 @@ define bfloat @test_atomicrmw_fadd_bf16_local_strictfp(ptr addrspace(3) %ptr, bf ; GFX9-NEXT: ret bfloat [[TMP7]] ; ; GFX908-LABEL: @test_atomicrmw_fadd_bf16_local_strictfp( -; GFX908-NEXT: [[ALIGNEDADDR:%.*]] = call ptr addrspace(3) @llvm.ptrmask.p3.i32(ptr addrspace(3) [[PTR:%.*]], i32 -4) +; GFX908-NEXT: [[ALIGNEDADDR:%.*]] = call ptr addrspace(3) @llvm.ptrmask.p3.i32(ptr addrspace(3) [[PTR:%.*]], i32 -4) #[[ATTR6]] ; GFX908-NEXT: [[TMP1:%.*]] = ptrtoint ptr addrspace(3) [[PTR]] to i32 ; GFX908-NEXT: [[PTRLSB:%.*]] = and i32 [[TMP1]], 3 ; GFX908-NEXT: [[TMP2:%.*]] = shl i32 [[PTRLSB]], 3 @@ -3101,7 +3101,7 @@ define bfloat @test_atomicrmw_fadd_bf16_local_strictfp(ptr addrspace(3) %ptr, bf ; GFX908-NEXT: [[SHIFTED:%.*]] = lshr i32 [[LOADED]], [[TMP2]] ; GFX908-NEXT: [[EXTRACTED:%.*]] = trunc i32 [[SHIFTED]] to i16 ; GFX908-NEXT: [[TMP4:%.*]] = bitcast i16 [[EXTRACTED]] to bfloat -; GFX908-NEXT: [[NEW:%.*]] = fadd bfloat [[TMP4]], [[VALUE:%.*]] +; GFX908-NEXT: [[NEW:%.*]] = call bfloat @llvm.experimental.constrained.fadd.bf16(bfloat [[TMP4]], bfloat [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR6]] ; GFX908-NEXT: [[TMP5:%.*]] = bitcast bfloat [[NEW]] to i16 ; GFX908-NEXT: [[EXTENDED:%.*]] = zext i16 [[TMP5]] to i32 ; GFX908-NEXT: [[SHIFTED1:%.*]] = shl nuw i32 [[EXTENDED]], [[TMP2]] @@ -3118,7 +3118,7 @@ define bfloat @test_atomicrmw_fadd_bf16_local_strictfp(ptr addrspace(3) %ptr, bf ; GFX908-NEXT: ret bfloat [[TMP7]] ; ; GFX90A-LABEL: @test_atomicrmw_fadd_bf16_local_strictfp( -; GFX90A-NEXT: [[ALIGNEDADDR:%.*]] = call ptr addrspace(3) @llvm.ptrmask.p3.i32(ptr addrspace(3) [[PTR:%.*]], i32 -4) +; GFX90A-NEXT: [[ALIGNEDADDR:%.*]] = call ptr addrspace(3) @llvm.ptrmask.p3.i32(ptr addrspace(3) [[PTR:%.*]], i32 -4) #[[ATTR6:[0-9]+]] ; GFX90A-NEXT: [[TMP1:%.*]] = ptrtoint ptr addrspace(3) [[PTR]] to i32 ; GFX90A-NEXT: [[PTRLSB:%.*]] = and i32 [[TMP1]], 3 ; GFX90A-NEXT: [[TMP2:%.*]] = shl i32 [[PTRLSB]], 3 @@ -3131,7 +3131,7 @@ define bfloat @test_atomicrmw_fadd_bf16_local_strictfp(ptr addrspace(3) %ptr, bf ; GFX90A-NEXT: [[SHIFTED:%.*]] = lshr i32 [[LOADED]], [[TMP2]] ; GFX90A-NEXT: [[EXTRACTED:%.*]] = trunc i32 [[SHIFTED]] to i16 ; GFX90A-NEXT: [[TMP4:%.*]] = bitcast i16 [[EXTRACTED]] to bfloat -; GFX90A-NEXT: [[NEW:%.*]] = fadd bfloat [[TMP4]], [[VALUE:%.*]] +; GFX90A-NEXT: [[NEW:%.*]] = call bfloat @llvm.experimental.constrained.fadd.bf16(bfloat [[TMP4]], bfloat [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR6]] ; GFX90A-NEXT: [[TMP5:%.*]] = bitcast bfloat [[NEW]] to i16 ; GFX90A-NEXT: [[EXTENDED:%.*]] = zext i16 [[TMP5]] to i32 ; GFX90A-NEXT: [[SHIFTED1:%.*]] = shl nuw i32 [[EXTENDED]], [[TMP2]] @@ -3148,7 +3148,7 @@ define bfloat @test_atomicrmw_fadd_bf16_local_strictfp(ptr addrspace(3) %ptr, bf ; GFX90A-NEXT: ret bfloat [[TMP7]] ; ; GFX940-LABEL: @test_atomicrmw_fadd_bf16_local_strictfp( -; GFX940-NEXT: [[ALIGNEDADDR:%.*]] = call ptr addrspace(3) @llvm.ptrmask.p3.i32(ptr addrspace(3) [[PTR:%.*]], i32 -4) +; GFX940-NEXT: [[ALIGNEDADDR:%.*]] = call ptr addrspace(3) @llvm.ptrmask.p3.i32(ptr addrspace(3) [[PTR:%.*]], i32 -4) #[[ATTR6:[0-9]+]] ; GFX940-NEXT: [[TMP1:%.*]] = ptrtoint ptr addrspace(3) [[PTR]] to i32 ; GFX940-NEXT: [[PTRLSB:%.*]] = and i32 [[TMP1]], 3 ; GFX940-NEXT: [[TMP2:%.*]] = shl i32 [[PTRLSB]], 3 @@ -3161,7 +3161,7 @@ define bfloat @test_atomicrmw_fadd_bf16_local_strictfp(ptr addrspace(3) %ptr, bf ; GFX940-NEXT: [[SHIFTED:%.*]] = lshr i32 [[LOADED]], [[TMP2]] ; GFX940-NEXT: [[EXTRACTED:%.*]] = trunc i32 [[SHIFTED]] to i16 ; GFX940-NEXT: [[TMP4:%.*]] = bitcast i16 [[EXTRACTED]] to bfloat -; GFX940-NEXT: [[NEW:%.*]] = fadd bfloat [[TMP4]], [[VALUE:%.*]] +; GFX940-NEXT: [[NEW:%.*]] = call bfloat @llvm.experimental.constrained.fadd.bf16(bfloat [[TMP4]], bfloat [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR6]] ; GFX940-NEXT: [[TMP5:%.*]] = bitcast bfloat [[NEW]] to i16 ; GFX940-NEXT: [[EXTENDED:%.*]] = zext i16 [[TMP5]] to i32 ; GFX940-NEXT: [[SHIFTED1:%.*]] = shl nuw i32 [[EXTENDED]], [[TMP2]] @@ -3178,7 +3178,7 @@ define bfloat @test_atomicrmw_fadd_bf16_local_strictfp(ptr addrspace(3) %ptr, bf ; GFX940-NEXT: ret bfloat [[TMP7]] ; ; GFX11-LABEL: @test_atomicrmw_fadd_bf16_local_strictfp( -; GFX11-NEXT: [[ALIGNEDADDR:%.*]] = call ptr addrspace(3) @llvm.ptrmask.p3.i32(ptr addrspace(3) [[PTR:%.*]], i32 -4) +; GFX11-NEXT: [[ALIGNEDADDR:%.*]] = call ptr addrspace(3) @llvm.ptrmask.p3.i32(ptr addrspace(3) [[PTR:%.*]], i32 -4) #[[ATTR6]] ; GFX11-NEXT: [[TMP1:%.*]] = ptrtoint ptr addrspace(3) [[PTR]] to i32 ; GFX11-NEXT: [[PTRLSB:%.*]] = and i32 [[TMP1]], 3 ; GFX11-NEXT: [[TMP2:%.*]] = shl i32 [[PTRLSB]], 3 @@ -3191,7 +3191,7 @@ define bfloat @test_atomicrmw_fadd_bf16_local_strictfp(ptr addrspace(3) %ptr, bf ; GFX11-NEXT: [[SHIFTED:%.*]] = lshr i32 [[LOADED]], [[TMP2]] ; GFX11-NEXT: [[EXTRACTED:%.*]] = trunc i32 [[SHIFTED]] to i16 ; GFX11-NEXT: [[TMP4:%.*]] = bitcast i16 [[EXTRACTED]] to bfloat -; GFX11-NEXT: [[NEW:%.*]] = fadd bfloat [[TMP4]], [[VALUE:%.*]] +; GFX11-NEXT: [[NEW:%.*]] = call bfloat @llvm.experimental.constrained.fadd.bf16(bfloat [[TMP4]], bfloat [[VALUE:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR6]] ; GFX11-NEXT: [[TMP5:%.*]] = bitcast bfloat [[NEW]] to i16 ; GFX11-NEXT: [[EXTENDED:%.*]] = zext i16 [[TMP5]] to i32 ; GFX11-NEXT: [[SHIFTED1:%.*]] = shl nuw i32 [[EXTENDED]], [[TMP2]] diff --git a/llvm/test/Transforms/Attributor/align.ll b/llvm/test/Transforms/Attributor/align.ll index 5103b6f1f1e909587827cfb853e563762d0e04d1..9880e53fd43a59c07a9c8653a6b6d1b6e26352a9 100644 --- a/llvm/test/Transforms/Attributor/align.ll +++ b/llvm/test/Transforms/Attributor/align.ll @@ -11,10 +11,10 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; TEST 1 ;; ;. -; CHECK: @[[A1:[a-zA-Z0-9_$"\\.-]+]] = common global i8 0, align 8 -; CHECK: @[[A2:[a-zA-Z0-9_$"\\.-]+]] = common global i8 0, align 16 -; CHECK: @[[CND:[a-zA-Z0-9_$"\\.-]+]] = external global i1 -; CHECK: @[[G:[a-zA-Z0-9_$"\\.-]+]] = global i8 0, align 32 +; CHECK: @a1 = common global i8 0, align 8 +; CHECK: @a2 = common global i8 0, align 16 +; CHECK: @cnd = external global i1 +; CHECK: @G = global i8 0, align 32 ;. define ptr @test1(ptr align 8 %0) #0 { ; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable @@ -158,18 +158,31 @@ define internal ptr @f1(ptr readnone %0) local_unnamed_addr #0 { ; Function Attrs: nounwind readnone ssp uwtable define ptr @f2(ptr readnone %0) local_unnamed_addr #0 { -; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable -; CHECK-LABEL: define {{[^@]+}}@f2 -; CHECK-SAME: (ptr nofree readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR0]] { -; CHECK-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null -; CHECK-NEXT: br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]] -; CHECK: 3: -; CHECK-NEXT: br label [[TMP5:%.*]] -; CHECK: 4: -; CHECK-NEXT: br label [[TMP5]] -; CHECK: 5: -; CHECK-NEXT: [[TMP6:%.*]] = phi ptr [ [[TMP0]], [[TMP3]] ], [ @a1, [[TMP4]] ] -; CHECK-NEXT: ret ptr [[TMP6]] +; TUNIT: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable +; TUNIT-LABEL: define {{[^@]+}}@f2 +; TUNIT-SAME: (ptr nofree readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR0]] { +; TUNIT-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null +; TUNIT-NEXT: br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]] +; TUNIT: 3: +; TUNIT-NEXT: br label [[TMP5:%.*]] +; TUNIT: 4: +; TUNIT-NEXT: br label [[TMP5]] +; TUNIT: 5: +; TUNIT-NEXT: [[TMP6:%.*]] = phi ptr [ [[TMP0]], [[TMP3]] ], [ @a1, [[TMP4]] ] +; TUNIT-NEXT: ret ptr [[TMP6]] +; +; CGSCC: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable +; CGSCC-LABEL: define {{[^@]+}}@f2 +; CGSCC-SAME: (ptr nofree readnone [[TMP0:%.*]]) local_unnamed_addr #[[ATTR0]] { +; CGSCC-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null +; CGSCC-NEXT: br i1 [[TMP2]], label [[TMP4:%.*]], label [[TMP3:%.*]] +; CGSCC: 3: +; CGSCC-NEXT: br label [[TMP5:%.*]] +; CGSCC: 4: +; CGSCC-NEXT: br label [[TMP5]] +; CGSCC: 5: +; CGSCC-NEXT: [[TMP6:%.*]] = phi ptr [ [[TMP0]], [[TMP3]] ], [ @a1, [[TMP4]] ] +; CGSCC-NEXT: ret ptr [[TMP6]] ; %2 = icmp eq ptr %0, null br i1 %2, label %5, label %3 @@ -222,7 +235,7 @@ define align 4 ptr @test7() #0 { ; CGSCC: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable ; CGSCC-LABEL: define {{[^@]+}}@test7 ; CGSCC-SAME: () #[[ATTR1:[0-9]+]] { -; CGSCC-NEXT: [[C:%.*]] = tail call noundef nonnull align 8 dereferenceable(1) ptr @f1() #[[ATTR14:[0-9]+]] +; CGSCC-NEXT: [[C:%.*]] = tail call noundef nonnull align 8 dereferenceable(1) ptr @f1() #[[ATTR15:[0-9]+]] ; CGSCC-NEXT: ret ptr [[C]] ; %c = tail call ptr @f1(ptr align 8 dereferenceable(1) @a1) @@ -933,7 +946,7 @@ define i32 @musttail_caller_1(ptr %p) { ; TUNIT-NEXT: [[C:%.*]] = load i1, ptr @cnd, align 1 ; TUNIT-NEXT: br i1 [[C]], label [[MT:%.*]], label [[EXIT:%.*]] ; TUNIT: mt: -; TUNIT-NEXT: [[V:%.*]] = musttail call i32 @musttail_callee_1(ptr nocapture nofree noundef readonly [[P]]) #[[ATTR12:[0-9]+]] +; TUNIT-NEXT: [[V:%.*]] = musttail call i32 @musttail_callee_1(ptr nocapture nofree noundef readonly [[P]]) #[[ATTR13:[0-9]+]] ; TUNIT-NEXT: ret i32 [[V]] ; TUNIT: exit: ; TUNIT-NEXT: ret i32 0 @@ -944,7 +957,7 @@ define i32 @musttail_caller_1(ptr %p) { ; CGSCC-NEXT: [[C:%.*]] = load i1, ptr @cnd, align 1 ; CGSCC-NEXT: br i1 [[C]], label [[MT:%.*]], label [[EXIT:%.*]] ; CGSCC: mt: -; CGSCC-NEXT: [[V:%.*]] = musttail call i32 @musttail_callee_1(ptr nocapture nofree noundef nonnull readonly dereferenceable(4) [[P]]) #[[ATTR15:[0-9]+]] +; CGSCC-NEXT: [[V:%.*]] = musttail call i32 @musttail_callee_1(ptr nocapture nofree noundef nonnull readonly dereferenceable(4) [[P]]) #[[ATTR16:[0-9]+]] ; CGSCC-NEXT: ret i32 [[V]] ; CGSCC: exit: ; CGSCC-NEXT: ret i32 0 @@ -1076,13 +1089,13 @@ define ptr @aligned_8_return_caller(ptr align(16) %a, i1 %c1, i1 %c2) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define {{[^@]+}}@aligned_8_return_caller ; TUNIT-SAME: (ptr nofree readnone align 16 "no-capture-maybe-returned" [[A:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR10]] { -; TUNIT-NEXT: [[R:%.*]] = call align 8 ptr @aligned_8_return(ptr noalias nofree readnone align 16 "no-capture-maybe-returned" [[A]], i1 noundef [[C1]], i1 [[C2]]) #[[ATTR13:[0-9]+]] +; TUNIT-NEXT: [[R:%.*]] = call align 8 ptr @aligned_8_return(ptr noalias nofree readnone align 16 "no-capture-maybe-returned" [[A]], i1 noundef [[C1]], i1 [[C2]]) #[[ATTR14:[0-9]+]] ; TUNIT-NEXT: ret ptr [[R]] ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define {{[^@]+}}@aligned_8_return_caller ; CGSCC-SAME: (ptr nofree readnone align 16 [[A:%.*]], i1 noundef [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR13:[0-9]+]] { -; CGSCC-NEXT: [[R:%.*]] = call align 8 ptr @aligned_8_return(ptr noalias nofree readnone align 16 [[A]], i1 noundef [[C1]], i1 [[C2]]) #[[ATTR14]] +; CGSCC-NEXT: [[R:%.*]] = call align 8 ptr @aligned_8_return(ptr noalias nofree readnone align 16 [[A]], i1 noundef [[C1]], i1 [[C2]]) #[[ATTR15]] ; CGSCC-NEXT: ret ptr [[R]] ; %r = call ptr @aligned_8_return(ptr %a, i1 %c1, i1 %c2) @@ -1101,6 +1114,104 @@ entry: ret i32 0 } +define i64 @infer_align_atomicrmw(ptr align 4 %p) { +; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) +; TUNIT-LABEL: define {{[^@]+}}@infer_align_atomicrmw +; TUNIT-SAME: (ptr nocapture nofree align 16 [[P:%.*]]) #[[ATTR12:[0-9]+]] { +; TUNIT-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 +; TUNIT-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 +; TUNIT-NEXT: [[RET:%.*]] = atomicrmw add ptr [[ARRAYIDX1]], i64 4 seq_cst, align 16 +; TUNIT-NEXT: ret i64 [[RET]] +; +; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) +; CGSCC-LABEL: define {{[^@]+}}@infer_align_atomicrmw +; CGSCC-SAME: (ptr nocapture nofree align 16 [[P:%.*]]) #[[ATTR14:[0-9]+]] { +; CGSCC-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 +; CGSCC-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 +; CGSCC-NEXT: [[RET:%.*]] = atomicrmw add ptr [[ARRAYIDX1]], i64 4 seq_cst, align 16 +; CGSCC-NEXT: ret i64 [[RET]] +; + %arrayidx0 = getelementptr i64, ptr %p, i64 1 + %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3 + %ret = atomicrmw add ptr %arrayidx1, i64 4 seq_cst, align 16 + ret i64 %ret +} + +define ptr @infer_align_atomicrmw_ptr(ptr align 4 %p, ptr %val) { +; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) +; TUNIT-LABEL: define {{[^@]+}}@infer_align_atomicrmw_ptr +; TUNIT-SAME: (ptr nocapture nofree align 16 [[P:%.*]], ptr nofree [[VAL:%.*]]) #[[ATTR12]] { +; TUNIT-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 +; TUNIT-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 +; TUNIT-NEXT: [[RET:%.*]] = atomicrmw xchg ptr [[ARRAYIDX1]], ptr [[VAL]] seq_cst, align 16 +; TUNIT-NEXT: ret ptr [[RET]] +; +; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) +; CGSCC-LABEL: define {{[^@]+}}@infer_align_atomicrmw_ptr +; CGSCC-SAME: (ptr nocapture nofree align 16 [[P:%.*]], ptr nofree [[VAL:%.*]]) #[[ATTR14]] { +; CGSCC-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 +; CGSCC-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 +; CGSCC-NEXT: [[RET:%.*]] = atomicrmw xchg ptr [[ARRAYIDX1]], ptr [[VAL]] seq_cst, align 16 +; CGSCC-NEXT: ret ptr [[RET]] +; + %arrayidx0 = getelementptr i64, ptr %p, i64 1 + %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3 + %ret = atomicrmw xchg ptr %arrayidx1, ptr %val seq_cst, align 16 + ret ptr %ret +} + +define i64 @infer_align_cmpxchg(ptr align 4 %p) { +; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) +; TUNIT-LABEL: define {{[^@]+}}@infer_align_cmpxchg +; TUNIT-SAME: (ptr nocapture nofree align 16 [[P:%.*]]) #[[ATTR12]] { +; TUNIT-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 +; TUNIT-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 +; TUNIT-NEXT: [[CMPX:%.*]] = cmpxchg ptr [[ARRAYIDX1]], i64 4, i64 1 seq_cst seq_cst, align 16 +; TUNIT-NEXT: [[RET:%.*]] = extractvalue { i64, i1 } [[CMPX]], 0 +; TUNIT-NEXT: ret i64 [[RET]] +; +; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) +; CGSCC-LABEL: define {{[^@]+}}@infer_align_cmpxchg +; CGSCC-SAME: (ptr nocapture nofree align 16 [[P:%.*]]) #[[ATTR14]] { +; CGSCC-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 +; CGSCC-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 +; CGSCC-NEXT: [[CMPX:%.*]] = cmpxchg ptr [[ARRAYIDX1]], i64 4, i64 1 seq_cst seq_cst, align 16 +; CGSCC-NEXT: [[RET:%.*]] = extractvalue { i64, i1 } [[CMPX]], 0 +; CGSCC-NEXT: ret i64 [[RET]] +; + %arrayidx0 = getelementptr i64, ptr %p, i64 1 + %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3 + %cmpx = cmpxchg ptr %arrayidx1, i64 4, i64 1 seq_cst seq_cst, align 16 + %ret = extractvalue { i64, i1 } %cmpx, 0 + ret i64 %ret +} + +define ptr @infer_align_cmpxchg_ptr(ptr align 4 %p, ptr %cmp0, ptr %cmp1) { +; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) +; TUNIT-LABEL: define {{[^@]+}}@infer_align_cmpxchg_ptr +; TUNIT-SAME: (ptr nocapture nofree align 16 [[P:%.*]], ptr nofree [[CMP0:%.*]], ptr nofree [[CMP1:%.*]]) #[[ATTR12]] { +; TUNIT-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 +; TUNIT-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 +; TUNIT-NEXT: [[CMPX:%.*]] = cmpxchg ptr [[ARRAYIDX1]], ptr [[CMP0]], ptr [[CMP1]] seq_cst seq_cst, align 16 +; TUNIT-NEXT: [[RET:%.*]] = extractvalue { ptr, i1 } [[CMPX]], 0 +; TUNIT-NEXT: ret ptr [[RET]] +; +; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) +; CGSCC-LABEL: define {{[^@]+}}@infer_align_cmpxchg_ptr +; CGSCC-SAME: (ptr nocapture nofree align 16 [[P:%.*]], ptr nofree [[CMP0:%.*]], ptr nofree [[CMP1:%.*]]) #[[ATTR14]] { +; CGSCC-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, ptr [[P]], i64 1 +; CGSCC-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, ptr [[ARRAYIDX0]], i64 3 +; CGSCC-NEXT: [[CMPX:%.*]] = cmpxchg ptr [[ARRAYIDX1]], ptr [[CMP0]], ptr [[CMP1]] seq_cst seq_cst, align 16 +; CGSCC-NEXT: [[RET:%.*]] = extractvalue { ptr, i1 } [[CMPX]], 0 +; CGSCC-NEXT: ret ptr [[RET]] +; + %arrayidx0 = getelementptr i64, ptr %p, i64 1 + %arrayidx1 = getelementptr i64, ptr %arrayidx0, i64 3 + %cmpx = cmpxchg ptr %arrayidx1, ptr %cmp0, ptr %cmp1 seq_cst seq_cst, align 16 + %ret = extractvalue { ptr, i1 } %cmpx, 0 + ret ptr %ret +} + declare void @implicit_cast_callee(i64) attributes #0 = { nounwind uwtable noinline } @@ -1119,8 +1230,9 @@ attributes #2 = { null_pointer_is_valid } ; TUNIT: attributes #[[ATTR9]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) } ; TUNIT: attributes #[[ATTR10]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } ; TUNIT: attributes #[[ATTR11]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(read) } -; TUNIT: attributes #[[ATTR12]] = { nofree nosync nounwind willreturn memory(read) } -; TUNIT: attributes #[[ATTR13]] = { nofree nosync nounwind willreturn } +; TUNIT: attributes #[[ATTR12]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) } +; TUNIT: attributes #[[ATTR13]] = { nofree nosync nounwind willreturn memory(read) } +; TUNIT: attributes #[[ATTR14]] = { nofree nosync nounwind willreturn } ;. ; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable } ; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable } @@ -1136,6 +1248,7 @@ attributes #2 = { null_pointer_is_valid } ; CGSCC: attributes #[[ATTR11]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } ; CGSCC: attributes #[[ATTR12]] = { mustprogress nofree nosync nounwind willreturn memory(read) } ; CGSCC: attributes #[[ATTR13]] = { mustprogress nofree nosync nounwind willreturn memory(none) } -; CGSCC: attributes #[[ATTR14]] = { nofree nosync willreturn } -; CGSCC: attributes #[[ATTR15]] = { nofree willreturn memory(read) } +; CGSCC: attributes #[[ATTR14]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) } +; CGSCC: attributes #[[ATTR15]] = { nofree nosync willreturn } +; CGSCC: attributes #[[ATTR16]] = { nofree willreturn memory(read) } ;. diff --git a/llvm/test/Transforms/Attributor/nocapture-1.ll b/llvm/test/Transforms/Attributor/nocapture-1.ll index 7d2f0a1351a454169be468eaca96ab2346a4420b..f61388f71c4607bdda759d49b4b26e33578b72d8 100644 --- a/llvm/test/Transforms/Attributor/nocapture-1.ll +++ b/llvm/test/Transforms/Attributor/nocapture-1.ll @@ -524,13 +524,13 @@ define void @test6_2(ptr %x6_2, ptr %y6_2, ptr %z6_2) { define void @test_cmpxchg(ptr %p) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) ; TUNIT-LABEL: define {{[^@]+}}@test_cmpxchg -; TUNIT-SAME: (ptr nocapture nofree noundef nonnull dereferenceable(4) [[P:%.*]]) #[[ATTR8:[0-9]+]] { +; TUNIT-SAME: (ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR8:[0-9]+]] { ; TUNIT-NEXT: [[TMP1:%.*]] = cmpxchg ptr [[P]], i32 0, i32 1 acquire monotonic, align 4 ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) ; CGSCC-LABEL: define {{[^@]+}}@test_cmpxchg -; CGSCC-SAME: (ptr nocapture nofree noundef nonnull dereferenceable(4) [[P:%.*]]) #[[ATTR11:[0-9]+]] { +; CGSCC-SAME: (ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR11:[0-9]+]] { ; CGSCC-NEXT: [[TMP1:%.*]] = cmpxchg ptr [[P]], i32 0, i32 1 acquire monotonic, align 4 ; CGSCC-NEXT: ret void ; @@ -541,13 +541,13 @@ define void @test_cmpxchg(ptr %p) { define void @test_cmpxchg_ptr(ptr %p, ptr %q) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) ; TUNIT-LABEL: define {{[^@]+}}@test_cmpxchg_ptr -; TUNIT-SAME: (ptr nocapture nofree noundef nonnull dereferenceable(8) [[P:%.*]], ptr nofree [[Q:%.*]]) #[[ATTR8]] { +; TUNIT-SAME: (ptr nocapture nofree noundef nonnull align 8 dereferenceable(8) [[P:%.*]], ptr nofree [[Q:%.*]]) #[[ATTR8]] { ; TUNIT-NEXT: [[TMP1:%.*]] = cmpxchg ptr [[P]], ptr null, ptr [[Q]] acquire monotonic, align 8 ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) ; CGSCC-LABEL: define {{[^@]+}}@test_cmpxchg_ptr -; CGSCC-SAME: (ptr nocapture nofree noundef nonnull dereferenceable(8) [[P:%.*]], ptr nofree [[Q:%.*]]) #[[ATTR11]] { +; CGSCC-SAME: (ptr nocapture nofree noundef nonnull align 8 dereferenceable(8) [[P:%.*]], ptr nofree [[Q:%.*]]) #[[ATTR11]] { ; CGSCC-NEXT: [[TMP1:%.*]] = cmpxchg ptr [[P]], ptr null, ptr [[Q]] acquire monotonic, align 8 ; CGSCC-NEXT: ret void ; @@ -558,13 +558,13 @@ define void @test_cmpxchg_ptr(ptr %p, ptr %q) { define void @test_atomicrmw(ptr %p) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) ; TUNIT-LABEL: define {{[^@]+}}@test_atomicrmw -; TUNIT-SAME: (ptr nocapture nofree noundef nonnull dereferenceable(4) [[P:%.*]]) #[[ATTR8]] { +; TUNIT-SAME: (ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR8]] { ; TUNIT-NEXT: [[TMP1:%.*]] = atomicrmw add ptr [[P]], i32 1 seq_cst, align 4 ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) ; CGSCC-LABEL: define {{[^@]+}}@test_atomicrmw -; CGSCC-SAME: (ptr nocapture nofree noundef nonnull dereferenceable(4) [[P:%.*]]) #[[ATTR11]] { +; CGSCC-SAME: (ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR11]] { ; CGSCC-NEXT: [[TMP1:%.*]] = atomicrmw add ptr [[P]], i32 1 seq_cst, align 4 ; CGSCC-NEXT: ret void ; diff --git a/llvm/test/Transforms/Attributor/nofpclass-implied-by-fcmp.ll b/llvm/test/Transforms/Attributor/nofpclass-implied-by-fcmp.ll index d64f8cf3e56dc142b881ccd68ca0e629a90bee4d..05c57052e674d712eefc49cdb63b688c48f56f6e 100644 --- a/llvm/test/Transforms/Attributor/nofpclass-implied-by-fcmp.ll +++ b/llvm/test/Transforms/Attributor/nofpclass-implied-by-fcmp.ll @@ -2641,8 +2641,8 @@ define float @assume_false_smallest_normal(float %arg) { } define float @clamp_false_nan(float %arg) { -; CHECK-LABEL: define nofpclass(nan inf nzero sub norm) float @clamp_false_nan( -; CHECK-SAME: float returned nofpclass(nan inf nzero sub norm) [[ARG:%.*]]) #[[ATTR2]] { +; CHECK-LABEL: define float @clamp_false_nan( +; CHECK-SAME: float returned [[ARG:%.*]]) #[[ATTR2]] { ; CHECK-NEXT: ret float [[ARG]] ; %fcmp = fcmp false float %arg, 0x7FF8000000000000 @@ -2784,12 +2784,12 @@ define float @clamp_true_smallest_normal_0.0(float %arg) { } define float @clamp_true_nan(float %arg) { -; CHECK-LABEL: define noundef nofpclass(nan inf nzero sub norm) float @clamp_true_nan( -; CHECK-SAME: float nofpclass(nan inf nzero sub norm) [[ARG:%.*]]) #[[ATTR2]] { -; CHECK-NEXT: ret float 0.000000e+00 +; CHECK-LABEL: define float @clamp_true_nan( +; CHECK-SAME: float returned [[ARG:%.*]]) #[[ATTR2]] { +; CHECK-NEXT: ret float [[ARG]] ; %fcmp = fcmp true float %arg, 0x7FF8000000000000 - %select = select i1 %fcmp, float 0.0, float %arg + %select = select i1 %fcmp, float %arg, float 0.0 ret float %select } diff --git a/llvm/test/Transforms/Attributor/nofpclass.ll b/llvm/test/Transforms/Attributor/nofpclass.ll index 442464cde3894823444a76884c5a715d1037e210..4df647cf3bb5b200c830e3b6a1e3c01b85b8885b 100644 --- a/llvm/test/Transforms/Attributor/nofpclass.ll +++ b/llvm/test/Transforms/Attributor/nofpclass.ll @@ -1813,7 +1813,7 @@ define double @fpext(float nofpclass(inf nan) %arg) { define float @atomicrmw_fadd(ptr %ptr, float nofpclass(inf nan) %val) { ; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) ; CHECK-LABEL: define float @atomicrmw_fadd -; CHECK-SAME: (ptr nocapture nofree noundef nonnull dereferenceable(4) [[PTR:%.*]], float nofpclass(nan inf) [[VAL:%.*]]) #[[ATTR6:[0-9]+]] { +; CHECK-SAME: (ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[PTR:%.*]], float nofpclass(nan inf) [[VAL:%.*]]) #[[ATTR6:[0-9]+]] { ; CHECK-NEXT: [[RESULT:%.*]] = atomicrmw fadd ptr [[PTR]], float [[VAL]] seq_cst, align 4 ; CHECK-NEXT: ret float [[RESULT]] ; diff --git a/llvm/test/Transforms/CodeGenPrepare/AArch64/fpclass-test.ll b/llvm/test/Transforms/CodeGenPrepare/AArch64/fpclass-test.ll new file mode 100644 index 0000000000000000000000000000000000000000..63ab22e96ad2adc0029587c8ebdfd31606577b4f --- /dev/null +++ b/llvm/test/Transforms/CodeGenPrepare/AArch64/fpclass-test.ll @@ -0,0 +1,134 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -codegenprepare -S -mtriple=aarch64 < %s | FileCheck %s + +define i1 @test_is_inf_or_nan(double %arg) { +; CHECK-LABEL: define i1 @test_is_inf_or_nan( +; CHECK-SAME: double [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f64(double [[ARG]], i32 519) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call double @llvm.fabs.f64(double %arg) + %ret = fcmp ueq double %abs, 0x7FF0000000000000 + ret i1 %ret +} + +define i1 @test_is_not_inf_or_nan(double %arg) { +; CHECK-LABEL: define i1 @test_is_not_inf_or_nan( +; CHECK-SAME: double [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f64(double [[ARG]], i32 504) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call double @llvm.fabs.f64(double %arg) + %ret = fcmp one double %abs, 0x7FF0000000000000 + ret i1 %ret +} + +define i1 @test_is_inf(double %arg) { +; CHECK-LABEL: define i1 @test_is_inf( +; CHECK-SAME: double [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f64(double [[ARG]], i32 516) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call double @llvm.fabs.f64(double %arg) + %ret = fcmp oeq double %abs, 0x7FF0000000000000 + ret i1 %ret +} + +define i1 @test_is_not_inf(double %arg) { +; CHECK-LABEL: define i1 @test_is_not_inf( +; CHECK-SAME: double [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f64(double [[ARG]], i32 507) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call double @llvm.fabs.f64(double %arg) + %ret = fcmp une double %abs, 0x7FF0000000000000 + ret i1 %ret +} + +define <vscale x 2 x i1> @test_vec_is_inf_or_nan(<vscale x 2 x double> %arg) { +; CHECK-LABEL: define <vscale x 2 x i1> @test_vec_is_inf_or_nan( +; CHECK-SAME: <vscale x 2 x double> [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 2 x i1> @llvm.is.fpclass.nxv2f64(<vscale x 2 x double> [[ARG]], i32 519) +; CHECK-NEXT: ret <vscale x 2 x i1> [[TMP1]] +; + %abs = tail call <vscale x 2 x double> @llvm.fabs.nxv2f64(<vscale x 2 x double> %arg) + %ret = fcmp ueq <vscale x 2 x double> %abs, splat (double 0x7FF0000000000000) + ret <vscale x 2 x i1> %ret +} + +define <vscale x 2 x i1> @test_vec_is_not_inf_or_nan(<vscale x 2 x double> %arg) { +; CHECK-LABEL: define <vscale x 2 x i1> @test_vec_is_not_inf_or_nan( +; CHECK-SAME: <vscale x 2 x double> [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 2 x i1> @llvm.is.fpclass.nxv2f64(<vscale x 2 x double> [[ARG]], i32 504) +; CHECK-NEXT: ret <vscale x 2 x i1> [[TMP1]] +; + %abs = tail call <vscale x 2 x double> @llvm.fabs.nxv2f64(<vscale x 2 x double> %arg) + %ret = fcmp one <vscale x 2 x double> %abs, splat (double 0x7FF0000000000000) + ret <vscale x 2 x i1> %ret +} + +define <vscale x 2 x i1> @test_vec_is_inf(<vscale x 2 x double> %arg) { +; CHECK-LABEL: define <vscale x 2 x i1> @test_vec_is_inf( +; CHECK-SAME: <vscale x 2 x double> [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 2 x i1> @llvm.is.fpclass.nxv2f64(<vscale x 2 x double> [[ARG]], i32 516) +; CHECK-NEXT: ret <vscale x 2 x i1> [[TMP1]] +; + %abs = tail call <vscale x 2 x double> @llvm.fabs.nxv2f64(<vscale x 2 x double> %arg) + %ret = fcmp oeq <vscale x 2 x double> %abs, splat (double 0x7FF0000000000000) + ret <vscale x 2 x i1> %ret +} + +define <vscale x 2 x i1> @test_vec_is_not_inf(<vscale x 2 x double> %arg) { +; CHECK-LABEL: define <vscale x 2 x i1> @test_vec_is_not_inf( +; CHECK-SAME: <vscale x 2 x double> [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 2 x i1> @llvm.is.fpclass.nxv2f64(<vscale x 2 x double> [[ARG]], i32 507) +; CHECK-NEXT: ret <vscale x 2 x i1> [[TMP1]] +; + %abs = tail call <vscale x 2 x double> @llvm.fabs.nxv2f64(<vscale x 2 x double> %arg) + %ret = fcmp une <vscale x 2 x double> %abs, splat (double 0x7FF0000000000000) + ret <vscale x 2 x i1> %ret +} + +define i1 @test_fp128_is_inf_or_nan(fp128 %arg) { +; CHECK-LABEL: define i1 @test_fp128_is_inf_or_nan( +; CHECK-SAME: fp128 [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f128(fp128 [[ARG]], i32 519) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call fp128 @llvm.fabs.f128(fp128 %arg) + %ret = fcmp ueq fp128 %abs, 0xL00000000000000007FFF000000000000 + ret i1 %ret +} + +define i1 @test_fp128_is_not_inf_or_nan(fp128 %arg) { +; CHECK-LABEL: define i1 @test_fp128_is_not_inf_or_nan( +; CHECK-SAME: fp128 [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f128(fp128 [[ARG]], i32 504) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call fp128 @llvm.fabs.f128(fp128 %arg) + %ret = fcmp one fp128 %abs, 0xL00000000000000007FFF000000000000 + ret i1 %ret +} + +define i1 @test_fp128_is_inf(fp128 %arg) { +; CHECK-LABEL: define i1 @test_fp128_is_inf( +; CHECK-SAME: fp128 [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f128(fp128 [[ARG]], i32 516) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call fp128 @llvm.fabs.f128(fp128 %arg) + %ret = fcmp oeq fp128 %abs, 0xL00000000000000007FFF000000000000 + ret i1 %ret +} + +define i1 @test_fp128_is_not_inf(fp128 %arg) { +; CHECK-LABEL: define i1 @test_fp128_is_not_inf( +; CHECK-SAME: fp128 [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f128(fp128 [[ARG]], i32 507) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call fp128 @llvm.fabs.f128(fp128 %arg) + %ret = fcmp une fp128 %abs, 0xL00000000000000007FFF000000000000 + ret i1 %ret +} diff --git a/llvm/test/Transforms/CodeGenPrepare/RISCV/fpclass-test.ll b/llvm/test/Transforms/CodeGenPrepare/RISCV/fpclass-test.ll new file mode 100644 index 0000000000000000000000000000000000000000..7c00218bdcce3d82c3353775f8ff7e86315f8bab --- /dev/null +++ b/llvm/test/Transforms/CodeGenPrepare/RISCV/fpclass-test.ll @@ -0,0 +1,134 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -codegenprepare -S -mtriple=riscv64 < %s | FileCheck %s + +define i1 @test_is_inf_or_nan(double %arg) { +; CHECK-LABEL: define i1 @test_is_inf_or_nan( +; CHECK-SAME: double [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f64(double [[ARG]], i32 519) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call double @llvm.fabs.f64(double %arg) + %ret = fcmp ueq double %abs, 0x7FF0000000000000 + ret i1 %ret +} + +define i1 @test_is_not_inf_or_nan(double %arg) { +; CHECK-LABEL: define i1 @test_is_not_inf_or_nan( +; CHECK-SAME: double [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f64(double [[ARG]], i32 504) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call double @llvm.fabs.f64(double %arg) + %ret = fcmp one double %abs, 0x7FF0000000000000 + ret i1 %ret +} + +define i1 @test_is_inf(double %arg) { +; CHECK-LABEL: define i1 @test_is_inf( +; CHECK-SAME: double [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f64(double [[ARG]], i32 516) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call double @llvm.fabs.f64(double %arg) + %ret = fcmp oeq double %abs, 0x7FF0000000000000 + ret i1 %ret +} + +define i1 @test_is_not_inf(double %arg) { +; CHECK-LABEL: define i1 @test_is_not_inf( +; CHECK-SAME: double [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f64(double [[ARG]], i32 507) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call double @llvm.fabs.f64(double %arg) + %ret = fcmp une double %abs, 0x7FF0000000000000 + ret i1 %ret +} + +define <vscale x 4 x i1> @test_vec_is_inf_or_nan(<vscale x 4 x double> %arg) { +; CHECK-LABEL: define <vscale x 4 x i1> @test_vec_is_inf_or_nan( +; CHECK-SAME: <vscale x 4 x double> [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 4 x i1> @llvm.is.fpclass.nxv4f64(<vscale x 4 x double> [[ARG]], i32 519) +; CHECK-NEXT: ret <vscale x 4 x i1> [[TMP1]] +; + %abs = tail call <vscale x 4 x double> @llvm.fabs.nxv4f64(<vscale x 4 x double> %arg) + %ret = fcmp ueq <vscale x 4 x double> %abs, splat (double 0x7FF0000000000000) + ret <vscale x 4 x i1> %ret +} + +define <vscale x 4 x i1> @test_vec_is_not_inf_or_nan(<vscale x 4 x double> %arg) { +; CHECK-LABEL: define <vscale x 4 x i1> @test_vec_is_not_inf_or_nan( +; CHECK-SAME: <vscale x 4 x double> [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 4 x i1> @llvm.is.fpclass.nxv4f64(<vscale x 4 x double> [[ARG]], i32 504) +; CHECK-NEXT: ret <vscale x 4 x i1> [[TMP1]] +; + %abs = tail call <vscale x 4 x double> @llvm.fabs.nxv4f64(<vscale x 4 x double> %arg) + %ret = fcmp one <vscale x 4 x double> %abs, splat (double 0x7FF0000000000000) + ret <vscale x 4 x i1> %ret +} + +define <vscale x 4 x i1> @test_vec_is_inf(<vscale x 4 x double> %arg) { +; CHECK-LABEL: define <vscale x 4 x i1> @test_vec_is_inf( +; CHECK-SAME: <vscale x 4 x double> [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 4 x i1> @llvm.is.fpclass.nxv4f64(<vscale x 4 x double> [[ARG]], i32 516) +; CHECK-NEXT: ret <vscale x 4 x i1> [[TMP1]] +; + %abs = tail call <vscale x 4 x double> @llvm.fabs.nxv4f64(<vscale x 4 x double> %arg) + %ret = fcmp oeq <vscale x 4 x double> %abs, splat (double 0x7FF0000000000000) + ret <vscale x 4 x i1> %ret +} + +define <vscale x 4 x i1> @test_vec_is_not_inf(<vscale x 4 x double> %arg) { +; CHECK-LABEL: define <vscale x 4 x i1> @test_vec_is_not_inf( +; CHECK-SAME: <vscale x 4 x double> [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 4 x i1> @llvm.is.fpclass.nxv4f64(<vscale x 4 x double> [[ARG]], i32 507) +; CHECK-NEXT: ret <vscale x 4 x i1> [[TMP1]] +; + %abs = tail call <vscale x 4 x double> @llvm.fabs.nxv4f64(<vscale x 4 x double> %arg) + %ret = fcmp une <vscale x 4 x double> %abs, splat (double 0x7FF0000000000000) + ret <vscale x 4 x i1> %ret +} + +define i1 @test_fp128_is_inf_or_nan(fp128 %arg) { +; CHECK-LABEL: define i1 @test_fp128_is_inf_or_nan( +; CHECK-SAME: fp128 [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f128(fp128 [[ARG]], i32 519) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call fp128 @llvm.fabs.f128(fp128 %arg) + %ret = fcmp ueq fp128 %abs, 0xL00000000000000007FFF000000000000 + ret i1 %ret +} + +define i1 @test_fp128_is_not_inf_or_nan(fp128 %arg) { +; CHECK-LABEL: define i1 @test_fp128_is_not_inf_or_nan( +; CHECK-SAME: fp128 [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f128(fp128 [[ARG]], i32 504) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call fp128 @llvm.fabs.f128(fp128 %arg) + %ret = fcmp one fp128 %abs, 0xL00000000000000007FFF000000000000 + ret i1 %ret +} + +define i1 @test_fp128_is_inf(fp128 %arg) { +; CHECK-LABEL: define i1 @test_fp128_is_inf( +; CHECK-SAME: fp128 [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f128(fp128 [[ARG]], i32 516) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call fp128 @llvm.fabs.f128(fp128 %arg) + %ret = fcmp oeq fp128 %abs, 0xL00000000000000007FFF000000000000 + ret i1 %ret +} + +define i1 @test_fp128_is_not_inf(fp128 %arg) { +; CHECK-LABEL: define i1 @test_fp128_is_not_inf( +; CHECK-SAME: fp128 [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f128(fp128 [[ARG]], i32 507) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call fp128 @llvm.fabs.f128(fp128 %arg) + %ret = fcmp une fp128 %abs, 0xL00000000000000007FFF000000000000 + ret i1 %ret +} diff --git a/llvm/test/Transforms/CodeGenPrepare/X86/fpclass-test.ll b/llvm/test/Transforms/CodeGenPrepare/X86/fpclass-test.ll new file mode 100644 index 0000000000000000000000000000000000000000..525caeb3e79a10d398985c52ce1019de6b2b86ef --- /dev/null +++ b/llvm/test/Transforms/CodeGenPrepare/X86/fpclass-test.ll @@ -0,0 +1,178 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -codegenprepare -S -mtriple=x86_64-unknown-unknown < %s | FileCheck %s + +define i1 @test_is_inf_or_nan(double %arg) { +; CHECK-LABEL: define i1 @test_is_inf_or_nan( +; CHECK-SAME: double [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f64(double [[ARG]], i32 519) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call double @llvm.fabs.f64(double %arg) + %ret = fcmp ueq double %abs, 0x7FF0000000000000 + ret i1 %ret +} + +define i1 @test_is_not_inf_or_nan(double %arg) { +; CHECK-LABEL: define i1 @test_is_not_inf_or_nan( +; CHECK-SAME: double [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f64(double [[ARG]], i32 504) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call double @llvm.fabs.f64(double %arg) + %ret = fcmp one double %abs, 0x7FF0000000000000 + ret i1 %ret +} + +define i1 @test_is_inf(double %arg) { +; CHECK-LABEL: define i1 @test_is_inf( +; CHECK-SAME: double [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f64(double [[ARG]], i32 516) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call double @llvm.fabs.f64(double %arg) + %ret = fcmp oeq double %abs, 0x7FF0000000000000 + ret i1 %ret +} + +define i1 @test_is_not_inf(double %arg) { +; CHECK-LABEL: define i1 @test_is_not_inf( +; CHECK-SAME: double [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f64(double [[ARG]], i32 507) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call double @llvm.fabs.f64(double %arg) + %ret = fcmp une double %abs, 0x7FF0000000000000 + ret i1 %ret +} + +define <4 x i1> @test_vec_is_inf_or_nan(<4 x double> %arg) { +; CHECK-LABEL: define <4 x i1> @test_vec_is_inf_or_nan( +; CHECK-SAME: <4 x double> [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.is.fpclass.v4f64(<4 x double> [[ARG]], i32 519) +; CHECK-NEXT: ret <4 x i1> [[TMP1]] +; + %abs = tail call <4 x double> @llvm.fabs.v4f64(<4 x double> %arg) + %ret = fcmp ueq <4 x double> %abs, splat (double 0x7FF0000000000000) + ret <4 x i1> %ret +} + +define <4 x i1> @test_vec_is_not_inf_or_nan(<4 x double> %arg) { +; CHECK-LABEL: define <4 x i1> @test_vec_is_not_inf_or_nan( +; CHECK-SAME: <4 x double> [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.is.fpclass.v4f64(<4 x double> [[ARG]], i32 504) +; CHECK-NEXT: ret <4 x i1> [[TMP1]] +; + %abs = tail call <4 x double> @llvm.fabs.v4f64(<4 x double> %arg) + %ret = fcmp one <4 x double> %abs, splat (double 0x7FF0000000000000) + ret <4 x i1> %ret +} + +define <4 x i1> @test_vec_is_inf(<4 x double> %arg) { +; CHECK-LABEL: define <4 x i1> @test_vec_is_inf( +; CHECK-SAME: <4 x double> [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.is.fpclass.v4f64(<4 x double> [[ARG]], i32 516) +; CHECK-NEXT: ret <4 x i1> [[TMP1]] +; + %abs = tail call <4 x double> @llvm.fabs.v4f64(<4 x double> %arg) + %ret = fcmp oeq <4 x double> %abs, splat (double 0x7FF0000000000000) + ret <4 x i1> %ret +} + +define <4 x i1> @test_vec_is_not_inf(<4 x double> %arg) { +; CHECK-LABEL: define <4 x i1> @test_vec_is_not_inf( +; CHECK-SAME: <4 x double> [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i1> @llvm.is.fpclass.v4f64(<4 x double> [[ARG]], i32 507) +; CHECK-NEXT: ret <4 x i1> [[TMP1]] +; + %abs = tail call <4 x double> @llvm.fabs.v4f64(<4 x double> %arg) + %ret = fcmp une <4 x double> %abs, splat (double 0x7FF0000000000000) + ret <4 x i1> %ret +} + +define i1 @test_fp128_is_inf_or_nan(fp128 %arg) { +; CHECK-LABEL: define i1 @test_fp128_is_inf_or_nan( +; CHECK-SAME: fp128 [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f128(fp128 [[ARG]], i32 519) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call fp128 @llvm.fabs.f128(fp128 %arg) + %ret = fcmp ueq fp128 %abs, 0xL00000000000000007FFF000000000000 + ret i1 %ret +} + +define i1 @test_fp128_is_not_inf_or_nan(fp128 %arg) { +; CHECK-LABEL: define i1 @test_fp128_is_not_inf_or_nan( +; CHECK-SAME: fp128 [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f128(fp128 [[ARG]], i32 504) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call fp128 @llvm.fabs.f128(fp128 %arg) + %ret = fcmp one fp128 %abs, 0xL00000000000000007FFF000000000000 + ret i1 %ret +} + +define i1 @test_fp128_is_inf(fp128 %arg) { +; CHECK-LABEL: define i1 @test_fp128_is_inf( +; CHECK-SAME: fp128 [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f128(fp128 [[ARG]], i32 516) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call fp128 @llvm.fabs.f128(fp128 %arg) + %ret = fcmp oeq fp128 %abs, 0xL00000000000000007FFF000000000000 + ret i1 %ret +} + +define i1 @test_fp128_is_not_inf(fp128 %arg) { +; CHECK-LABEL: define i1 @test_fp128_is_not_inf( +; CHECK-SAME: fp128 [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f128(fp128 [[ARG]], i32 507) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call fp128 @llvm.fabs.f128(fp128 %arg) + %ret = fcmp une fp128 %abs, 0xL00000000000000007FFF000000000000 + ret i1 %ret +} + +define i1 @test_x86_fp80_is_inf_or_nan(x86_fp80 %arg) { +; CHECK-LABEL: define i1 @test_x86_fp80_is_inf_or_nan( +; CHECK-SAME: x86_fp80 [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f80(x86_fp80 [[ARG]], i32 519) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call x86_fp80 @llvm.fabs.f80(x86_fp80 %arg) + %ret = fcmp ueq x86_fp80 %abs, 0xK7FFF8000000000000000 + ret i1 %ret +} + +define i1 @test_x86_fp80_is_not_inf_or_nan(x86_fp80 %arg) { +; CHECK-LABEL: define i1 @test_x86_fp80_is_not_inf_or_nan( +; CHECK-SAME: x86_fp80 [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f80(x86_fp80 [[ARG]], i32 504) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call x86_fp80 @llvm.fabs.f80(x86_fp80 %arg) + %ret = fcmp one x86_fp80 %abs, 0xK7FFF8000000000000000 + ret i1 %ret +} + +define i1 @test_x86_fp80_is_inf(x86_fp80 %arg) { +; CHECK-LABEL: define i1 @test_x86_fp80_is_inf( +; CHECK-SAME: x86_fp80 [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f80(x86_fp80 [[ARG]], i32 516) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call x86_fp80 @llvm.fabs.f80(x86_fp80 %arg) + %ret = fcmp oeq x86_fp80 %abs, 0xK7FFF8000000000000000 + ret i1 %ret +} + +define i1 @test_x86_fp80_is_not_inf(x86_fp80 %arg) { +; CHECK-LABEL: define i1 @test_x86_fp80_is_not_inf( +; CHECK-SAME: x86_fp80 [[ARG:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.is.fpclass.f80(x86_fp80 [[ARG]], i32 507) +; CHECK-NEXT: ret i1 [[TMP1]] +; + %abs = tail call x86_fp80 @llvm.fabs.f80(x86_fp80 %arg) + %ret = fcmp une x86_fp80 %abs, 0xK7FFF8000000000000000 + ret i1 %ret +} diff --git a/llvm/test/Transforms/ConstantHoisting/AArch64/large-immediate.ll b/llvm/test/Transforms/ConstantHoisting/AArch64/large-immediate.ll index 196a104adc0233fc310d99b4d099e0d9e82779a9..6d8890d71e2be95ce54228daf991b06e508d8ee5 100644 --- a/llvm/test/Transforms/ConstantHoisting/AArch64/large-immediate.ll +++ b/llvm/test/Transforms/ConstantHoisting/AArch64/large-immediate.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3 -; RUN: opt -mtriple=arm64-darwin-unknown -S -passes=consthoist < %s | FileCheck %s +; RUN: opt -mtriple=arm64-darwin-unknown -S -passes=consthoist < %s | FileCheck %s --check-prefixes=CHECK,CV +; RUN: opt -mtriple=arm64-darwin-unknown -S -passes=consthoist -use-constant-int-for-fixed-length-splat -use-constant-int-for-scalable-splat < %s | FileCheck %s --check-prefixes=CHECK,CI define i128 @test1(i128 %a) { ; CHECK-LABEL: define i128 @test1( @@ -122,13 +123,37 @@ define i64 @sdiv_minsize(i64 %a) minsize { } define <2 x i64> @sdiv_v2i64(<2 x i64> %a) { -; CHECK-LABEL: define <2 x i64> @sdiv_v2i64( -; CHECK-SAME: <2 x i64> [[A:%.*]]) { -; CHECK-NEXT: [[TMP1:%.*]] = sdiv <2 x i64> [[A]], <i64 4294967087, i64 4294967087> -; CHECK-NEXT: [[TMP2:%.*]] = add <2 x i64> [[TMP1]], <i64 4294967087, i64 4294967087> -; CHECK-NEXT: ret <2 x i64> [[TMP2]] +; CV-LABEL: define <2 x i64> @sdiv_v2i64( +; CV-SAME: <2 x i64> [[A:%.*]]) { +; CV-NEXT: [[TMP1:%.*]] = sdiv <2 x i64> [[A]], <i64 4294967087, i64 4294967087> +; CV-NEXT: [[TMP2:%.*]] = add <2 x i64> [[TMP1]], <i64 4294967087, i64 4294967087> +; CV-NEXT: ret <2 x i64> [[TMP2]] +; +; CI-LABEL: define <2 x i64> @sdiv_v2i64( +; CI-SAME: <2 x i64> [[A:%.*]]) { +; CI-NEXT: [[TMP1:%.*]] = sdiv <2 x i64> [[A]], splat (i64 4294967087) +; CI-NEXT: [[TMP2:%.*]] = add <2 x i64> [[TMP1]], splat (i64 4294967087) +; CI-NEXT: ret <2 x i64> [[TMP2]] ; %1 = sdiv <2 x i64> %a, <i64 4294967087, i64 4294967087> %2 = add <2 x i64> %1, <i64 4294967087, i64 4294967087> ret <2 x i64> %2 } + +define <vscale x 2 x i64> @sdiv_nxv2i64(<vscale x 2 x i64> %a) { +; CV-LABEL: define <vscale x 2 x i64> @sdiv_nxv2i64( +; CV-SAME: <vscale x 2 x i64> [[A:%.*]]) { +; CV-NEXT: [[TMP1:%.*]] = sdiv <vscale x 2 x i64> [[A]], shufflevector (<vscale x 2 x i64> insertelement (<vscale x 2 x i64> poison, i64 4294967087, i64 0), <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer) +; CV-NEXT: [[TMP2:%.*]] = add <vscale x 2 x i64> [[TMP1]], shufflevector (<vscale x 2 x i64> insertelement (<vscale x 2 x i64> poison, i64 4294967087, i64 0), <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer) +; CV-NEXT: ret <vscale x 2 x i64> [[TMP2]] +; +; CI-LABEL: define <vscale x 2 x i64> @sdiv_nxv2i64( +; CI-SAME: <vscale x 2 x i64> [[A:%.*]]) { +; CI-NEXT: [[TMP1:%.*]] = sdiv <vscale x 2 x i64> [[A]], splat (i64 4294967087) +; CI-NEXT: [[TMP2:%.*]] = add <vscale x 2 x i64> [[TMP1]], splat (i64 4294967087) +; CI-NEXT: ret <vscale x 2 x i64> [[TMP2]] +; + %1 = sdiv <vscale x 2 x i64> %a, splat (i64 4294967087) + %2 = add <vscale x 2 x i64> %1, splat (i64 4294967087) + ret <vscale x 2 x i64> %2 +} diff --git a/llvm/test/Transforms/Coroutines/coro-split-musttail6.ll b/llvm/test/Transforms/Coroutines/coro-split-musttail6.ll index 9c2b1ece1624bc99a7c0d763f3a799268fe57a6c..d9dba92ec4eb7ee4da66d03e180434dba2d43ff7 100644 --- a/llvm/test/Transforms/Coroutines/coro-split-musttail6.ll +++ b/llvm/test/Transforms/Coroutines/coro-split-musttail6.ll @@ -88,7 +88,6 @@ exit: ret void } -; FIXME: The fakeresume1 here should be marked as musttail. ; Verify that in the resume part resume call is marked with musttail. ; CHECK-LABEL: @f.resume( ; CHECK: musttail call fastcc void @fakeresume1(ptr align 8 null) diff --git a/llvm/test/Transforms/Coroutines/coro-split-musttail7.ll b/llvm/test/Transforms/Coroutines/coro-split-musttail7.ll index 860032bd3cf8e5249e3026e6edaa2dee1d2fdba0..d0d5005587bda66fce323446dc1f5dc94f55f257 100644 --- a/llvm/test/Transforms/Coroutines/coro-split-musttail7.ll +++ b/llvm/test/Transforms/Coroutines/coro-split-musttail7.ll @@ -1,6 +1,6 @@ ; Tests that sinked lifetime markers wouldn't provent optimization ; to convert a resuming call to a musttail call. -; The difference between this and coro-split-musttail5.ll and coro-split-musttail5.ll +; The difference between this and coro-split-musttail5.ll and coro-split-musttail6.ll ; is that this contains dead instruction generated during the transformation, ; which makes the optimization harder. ; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s @@ -8,7 +8,7 @@ declare void @fakeresume1(ptr align 8) -define void @g() #0 { +define i64 @g() #0 { entry: %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null) %alloc = call ptr @malloc(i64 16) #3 @@ -27,6 +27,11 @@ await.suspend: %save2 = call token @llvm.coro.save(ptr null) call fastcc void @fakeresume1(ptr align 8 null) %suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false) + + ; These (non-trivially) dead instructions are in the way. + %gep = getelementptr inbounds i64, ptr %alloc.var, i32 0 + %foo = ptrtoint ptr %gep to i64 + switch i8 %suspend2, label %exit [ i8 0, label %await.ready i8 1, label %exit @@ -36,8 +41,9 @@ await.ready: call void @llvm.lifetime.end.p0(i64 1, ptr %alloc.var) br label %exit exit: + %result = phi i64 [0, %entry], [0, %entry], [%foo, %await.suspend], [%foo, %await.suspend], [%foo, %await.ready] call i1 @llvm.coro.end(ptr null, i1 false, token none) - ret void + ret i64 %result } ; Verify that in the resume part resume call is marked with musttail. @@ -88,7 +94,6 @@ exit: ret void } -; FIXME: The fakeresume1 here should be marked as musttail. ; Verify that in the resume part resume call is marked with musttail. ; CHECK-LABEL: @f.resume( ; CHECK: musttail call fastcc void @fakeresume1(ptr align 8 null) diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll b/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll index 8dce9ef9fa435007bd1c4f468848ccdd5fab7c1d..701d867416a13e061adcae9af1c392ecc0d0719d 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll @@ -870,6 +870,33 @@ out: ret i1 false } +define i1 @clamp_high1_or(i32 noundef %a) { +; CHECK-LABEL: @clamp_high1_or( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5 +; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] +; CHECK: a_guard: +; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp eq i32 [[A]], 5 +; CHECK-NEXT: [[ADD:%.*]] = or disjoint i32 [[A]], 1 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 5, i32 [[ADD]] +; CHECK-NEXT: ret i1 false +; CHECK: out: +; CHECK-NEXT: ret i1 false +; +entry: + %cmp = icmp sle i32 %a, 5 + br i1 %cmp, label %a_guard, label %out + +a_guard: + %sel_cmp = icmp eq i32 %a, 5 + %add = or disjoint i32 %a, 1 + %sel = select i1 %sel_cmp, i32 5, i32 %add + %res = icmp eq i32 %sel, 6 + ret i1 %res +out: + ret i1 false +} + define i1 @clamp_high2(i32 noundef %a) { ; CHECK-LABEL: @clamp_high2( ; CHECK-NEXT: entry: @@ -897,6 +924,35 @@ out: ret i1 false } + +define i1 @clamp_high2_or_disjoint(i32 noundef %a) { +; CHECK-LABEL: @clamp_high2_or_disjoint( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[A:%.*]], 5 +; CHECK-NEXT: br i1 [[CMP]], label [[A_GUARD:%.*]], label [[OUT:%.*]] +; CHECK: a_guard: +; CHECK-NEXT: [[SEL_CMP:%.*]] = icmp ne i32 [[A]], 5 +; CHECK-NEXT: [[ADD:%.*]] = or disjoint i32 [[A]], 1 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[SEL_CMP]], i32 [[ADD]], i32 5 +; CHECK-NEXT: ret i1 false +; CHECK: out: +; CHECK-NEXT: ret i1 false +; +entry: + %cmp = icmp sle i32 %a, 5 + br i1 %cmp, label %a_guard, label %out + +a_guard: + %sel_cmp = icmp ne i32 %a, 5 + %add = or disjoint i32 %a, 1 + %sel = select i1 %sel_cmp, i32 %add, i32 5 + %res = icmp eq i32 %sel, 6 + ret i1 %res +out: + ret i1 false +} + + define i1 @clamp_high3(i32 noundef %a) { ; CHECK-LABEL: @clamp_high3( ; CHECK-NEXT: entry: diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll b/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll index 101820a4c65f23b17639addd1bdc6be8f3f0cdf7..b5337b9ddc24875bfd61585a0afe9e7613d36148 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll @@ -587,6 +587,26 @@ define i1 @test_assume_cmp_with_offset(i64 %idx) { ret i1 %cmp2 } +define i1 @test_assume_cmp_with_offset_or(i64 %idx, i1 %other) { +; CHECK-LABEL: @test_assume_cmp_with_offset_or( +; CHECK-NEXT: [[IDX_OFF1:%.*]] = or disjoint i64 [[IDX:%.*]], 5 +; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i64 [[IDX_OFF1]], 10 +; CHECK-NEXT: br i1 [[CMP1]], label [[T:%.*]], label [[F:%.*]] +; CHECK: T: +; CHECK-NEXT: ret i1 true +; CHECK: F: +; CHECK-NEXT: ret i1 [[CMP2:%.*]] +; + %idx.off1 = or disjoint i64 %idx, 5 + %cmp1 = icmp ugt i64 %idx.off1, 10 + br i1 %cmp1, label %T, label %F +T: + %cmp2 = icmp ugt i64 %idx, 2 + ret i1 %cmp2 +F: + ret i1 %other +} + define void @test_cmp_phi(i8 %a) { ; CHECK-LABEL: @test_cmp_phi( ; CHECK-NEXT: entry: diff --git a/llvm/test/Transforms/DFAJumpThreading/dfa-unfold-select.ll b/llvm/test/Transforms/DFAJumpThreading/dfa-unfold-select.ll index df725b9a7fa47d1fa554c0f7e04c14d9c8ee7af7..696bd55d2dfdd9ca875f54823c4386f99ad2f8dc 100644 --- a/llvm/test/Transforms/DFAJumpThreading/dfa-unfold-select.ll +++ b/llvm/test/Transforms/DFAJumpThreading/dfa-unfold-select.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -passes=dfa-jump-threading %s | FileCheck %s +; RUN: opt -S -passes=dfa-jump-threading -dfa-early-exit-heuristic=false %s | FileCheck %s ; These tests check if selects are unfolded properly for jump threading ; opportunities. There are three different patterns to consider: diff --git a/llvm/test/Transforms/DFAJumpThreading/unpredictable-heuristic.ll b/llvm/test/Transforms/DFAJumpThreading/unpredictable-heuristic.ll new file mode 100644 index 0000000000000000000000000000000000000000..9743f0acc8165ec6e41430b37641da8eff2cd457 --- /dev/null +++ b/llvm/test/Transforms/DFAJumpThreading/unpredictable-heuristic.ll @@ -0,0 +1,124 @@ +; REQUIRES: asserts +; RUN: opt -S -passes=dfa-jump-threading %s -debug-only=dfa-jump-threading 2>&1 | FileCheck %s + +; CHECK-COUNT-3: Exiting early due to unpredictability heuristic. + +@.str.1 = private unnamed_addr constant [3 x i8] c"10\00", align 1 +@.str.2 = private unnamed_addr constant [3 x i8] c"30\00", align 1 +@.str.3 = private unnamed_addr constant [3 x i8] c"20\00", align 1 +@.str.4 = private unnamed_addr constant [3 x i8] c"40\00", align 1 + +define void @test1(i32 noundef %num, i32 noundef %num2) { +entry: + br label %while.body + +while.body: ; preds = %entry, %sw.epilog + %num.addr.0 = phi i32 [ %num, %entry ], [ %num.addr.1, %sw.epilog ] + switch i32 %num.addr.0, label %sw.default [ + i32 10, label %sw.bb + i32 30, label %sw.bb1 + i32 20, label %sw.bb2 + i32 40, label %sw.bb3 + ] + +sw.bb: ; preds = %while.body + %call.i = tail call i32 @bar(ptr noundef nonnull @.str.1) + br label %sw.epilog + +sw.bb1: ; preds = %while.body + %call.i4 = tail call i32 @bar(ptr noundef nonnull @.str.2) + br label %sw.epilog + +sw.bb2: ; preds = %while.body + %call.i5 = tail call i32 @bar(ptr noundef nonnull @.str.3) + br label %sw.epilog + +sw.bb3: ; preds = %while.body + %call.i6 = tail call i32 @bar(ptr noundef nonnull @.str.4) + %call = tail call noundef i32 @foo() + %add = add nsw i32 %call, %num2 + br label %sw.epilog + +sw.default: ; preds = %while.body + ret void + +sw.epilog: ; preds = %sw.bb3, %sw.bb2, %sw.bb1, %sw.bb + %num.addr.1 = phi i32 [ %add, %sw.bb3 ], [ 40, %sw.bb2 ], [ 20, %sw.bb1 ], [ 30, %sw.bb ] + br label %while.body +} + + +define void @test2(i32 noundef %num, i32 noundef %num2) { +entry: + br label %while.body + +while.body: ; preds = %entry, %sw.epilog + %num.addr.0 = phi i32 [ %num, %entry ], [ %num.addr.1, %sw.epilog ] + switch i32 %num.addr.0, label %sw.default [ + i32 10, label %sw.epilog + i32 30, label %sw.bb1 + i32 20, label %sw.bb2 + i32 40, label %sw.bb3 + ] + +sw.bb1: ; preds = %while.body + br label %sw.epilog + +sw.bb2: ; preds = %while.body + br label %sw.epilog + +sw.bb3: ; preds = %while.body + br label %sw.epilog + +sw.default: ; preds = %while.body + ret void + +sw.epilog: ; preds = %while.body, %sw.bb3, %sw.bb2, %sw.bb1 + %.str.4.sink = phi ptr [ @.str.4, %sw.bb3 ], [ @.str.3, %sw.bb2 ], [ @.str.2, %sw.bb1 ], [ @.str.1, %while.body ] + %num.addr.1 = phi i32 [ %num2, %sw.bb3 ], [ 40, %sw.bb2 ], [ 20, %sw.bb1 ], [ 30, %while.body ] + %call.i6 = tail call i32 @bar(ptr noundef nonnull %.str.4.sink) + br label %while.body +} + + +define void @test3(i32 noundef %num, i32 noundef %num2) { +entry: + %add = add nsw i32 %num2, 40 + br label %while.body + +while.body: ; preds = %entry, %sw.epilog + %num.addr.0 = phi i32 [ %num, %entry ], [ %num.addr.1, %sw.epilog ] + switch i32 %num.addr.0, label %sw.default [ + i32 10, label %sw.bb + i32 30, label %sw.bb1 + i32 20, label %sw.bb2 + i32 40, label %sw.bb3 + ] + +sw.bb: ; preds = %while.body + %call.i = tail call i32 @bar(ptr noundef nonnull @.str.1) + br label %sw.epilog + +sw.bb1: ; preds = %while.body + %call.i5 = tail call i32 @bar(ptr noundef nonnull @.str.2) + br label %sw.epilog + +sw.bb2: ; preds = %while.body + %call.i6 = tail call i32 @bar(ptr noundef nonnull @.str.3) + br label %sw.epilog + +sw.bb3: ; preds = %while.body + %call.i7 = tail call i32 @bar(ptr noundef nonnull @.str.4) + br label %sw.epilog + +sw.default: ; preds = %while.body + ret void + +sw.epilog: ; preds = %sw.bb3, %sw.bb2, %sw.bb1, %sw.bb + %num.addr.1 = phi i32 [ %add, %sw.bb3 ], [ 40, %sw.bb2 ], [ 20, %sw.bb1 ], [ 30, %sw.bb ] + br label %while.body +} + + +declare noundef i32 @foo() +declare noundef i32 @bar(ptr nocapture noundef readonly) diff --git a/llvm/test/Transforms/ExpandLargeDivRem/X86/vector.ll b/llvm/test/Transforms/ExpandLargeDivRem/X86/vector.ll new file mode 100644 index 0000000000000000000000000000000000000000..5b7fd0086759e0d5bfe6d343221968c989c866e5 --- /dev/null +++ b/llvm/test/Transforms/ExpandLargeDivRem/X86/vector.ll @@ -0,0 +1,536 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -mtriple=x86_64-- -expand-large-div-rem -expand-div-rem-bits 128 < %s | FileCheck %s +; RUN: opt -S -mtriple=x86_64-- -passes=expand-large-div-rem -expand-div-rem-bits 128 < %s | FileCheck %s + +define <2 x i129> @sdiv129(<2 x i129> %a, <2 x i129> %b) nounwind { +; CHECK-LABEL: define <2 x i129> @sdiv129( +; CHECK-SAME: <2 x i129> [[A:%.*]], <2 x i129> [[B:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: _udiv-special-cases_udiv-special-cases: +; CHECK-NEXT: [[TMP0:%.*]] = extractelement <2 x i129> [[A]], i64 0 +; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x i129> [[B]], i64 0 +; CHECK-NEXT: [[TMP2:%.*]] = freeze i129 [[TMP0]] +; CHECK-NEXT: [[TMP3:%.*]] = freeze i129 [[TMP1]] +; CHECK-NEXT: [[TMP4:%.*]] = ashr i129 [[TMP2]], 128 +; CHECK-NEXT: [[TMP5:%.*]] = ashr i129 [[TMP3]], 128 +; CHECK-NEXT: [[TMP6:%.*]] = xor i129 [[TMP4]], [[TMP2]] +; CHECK-NEXT: [[TMP7:%.*]] = sub i129 [[TMP6]], [[TMP4]] +; CHECK-NEXT: [[TMP8:%.*]] = xor i129 [[TMP5]], [[TMP3]] +; CHECK-NEXT: [[TMP9:%.*]] = sub i129 [[TMP8]], [[TMP5]] +; CHECK-NEXT: [[TMP10:%.*]] = xor i129 [[TMP5]], [[TMP4]] +; CHECK-NEXT: [[TMP11:%.*]] = freeze i129 [[TMP9]] +; CHECK-NEXT: [[TMP12:%.*]] = freeze i129 [[TMP7]] +; CHECK-NEXT: [[TMP13:%.*]] = icmp eq i129 [[TMP11]], 0 +; CHECK-NEXT: [[TMP14:%.*]] = icmp eq i129 [[TMP12]], 0 +; CHECK-NEXT: [[TMP15:%.*]] = or i1 [[TMP13]], [[TMP14]] +; CHECK-NEXT: [[TMP16:%.*]] = call i129 @llvm.ctlz.i129(i129 [[TMP11]], i1 true) +; CHECK-NEXT: [[TMP17:%.*]] = call i129 @llvm.ctlz.i129(i129 [[TMP12]], i1 true) +; CHECK-NEXT: [[TMP18:%.*]] = sub i129 [[TMP16]], [[TMP17]] +; CHECK-NEXT: [[TMP19:%.*]] = icmp ugt i129 [[TMP18]], 128 +; CHECK-NEXT: [[TMP20:%.*]] = select i1 [[TMP15]], i1 true, i1 [[TMP19]] +; CHECK-NEXT: [[TMP21:%.*]] = icmp eq i129 [[TMP18]], 128 +; CHECK-NEXT: [[TMP22:%.*]] = select i1 [[TMP20]], i129 0, i129 [[TMP12]] +; CHECK-NEXT: [[TMP23:%.*]] = select i1 [[TMP20]], i1 true, i1 [[TMP21]] +; CHECK-NEXT: br i1 [[TMP23]], label [[UDIV_END1:%.*]], label [[UDIV_BB15:%.*]] +; CHECK: udiv-loop-exit2: +; CHECK-NEXT: [[TMP24:%.*]] = phi i129 [ 0, [[UDIV_BB15]] ], [ [[TMP39:%.*]], [[UDIV_DO_WHILE3:%.*]] ] +; CHECK-NEXT: [[TMP25:%.*]] = phi i129 [ [[TMP48:%.*]], [[UDIV_BB15]] ], [ [[TMP36:%.*]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP26:%.*]] = shl i129 [[TMP25]], 1 +; CHECK-NEXT: [[TMP27:%.*]] = or i129 [[TMP24]], [[TMP26]] +; CHECK-NEXT: br label [[UDIV_END1]] +; CHECK: udiv-do-while3: +; CHECK-NEXT: [[TMP28:%.*]] = phi i129 [ 0, [[UDIV_PREHEADER4:%.*]] ], [ [[TMP39]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP29:%.*]] = phi i129 [ [[TMP46:%.*]], [[UDIV_PREHEADER4]] ], [ [[TMP42:%.*]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP30:%.*]] = phi i129 [ [[TMP44:%.*]], [[UDIV_PREHEADER4]] ], [ [[TMP41:%.*]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP31:%.*]] = phi i129 [ [[TMP48]], [[UDIV_PREHEADER4]] ], [ [[TMP36]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP32:%.*]] = shl i129 [[TMP30]], 1 +; CHECK-NEXT: [[TMP33:%.*]] = lshr i129 [[TMP31]], 128 +; CHECK-NEXT: [[TMP34:%.*]] = or i129 [[TMP32]], [[TMP33]] +; CHECK-NEXT: [[TMP35:%.*]] = shl i129 [[TMP31]], 1 +; CHECK-NEXT: [[TMP36]] = or i129 [[TMP28]], [[TMP35]] +; CHECK-NEXT: [[TMP37:%.*]] = sub i129 [[TMP45:%.*]], [[TMP34]] +; CHECK-NEXT: [[TMP38:%.*]] = ashr i129 [[TMP37]], 128 +; CHECK-NEXT: [[TMP39]] = and i129 [[TMP38]], 1 +; CHECK-NEXT: [[TMP40:%.*]] = and i129 [[TMP38]], [[TMP11]] +; CHECK-NEXT: [[TMP41]] = sub i129 [[TMP34]], [[TMP40]] +; CHECK-NEXT: [[TMP42]] = add i129 [[TMP29]], -1 +; CHECK-NEXT: [[TMP43:%.*]] = icmp eq i129 [[TMP42]], 0 +; CHECK-NEXT: br i1 [[TMP43]], label [[UDIV_LOOP_EXIT2:%.*]], label [[UDIV_DO_WHILE3]] +; CHECK: udiv-preheader4: +; CHECK-NEXT: [[TMP44]] = lshr i129 [[TMP12]], [[TMP46]] +; CHECK-NEXT: [[TMP45]] = add i129 [[TMP11]], -1 +; CHECK-NEXT: br label [[UDIV_DO_WHILE3]] +; CHECK: udiv-bb15: +; CHECK-NEXT: [[TMP46]] = add i129 [[TMP18]], 1 +; CHECK-NEXT: [[TMP47:%.*]] = sub i129 128, [[TMP18]] +; CHECK-NEXT: [[TMP48]] = shl i129 [[TMP12]], [[TMP47]] +; CHECK-NEXT: [[TMP49:%.*]] = icmp eq i129 [[TMP46]], 0 +; CHECK-NEXT: br i1 [[TMP49]], label [[UDIV_LOOP_EXIT2]], label [[UDIV_PREHEADER4]] +; CHECK: udiv-end1: +; CHECK-NEXT: [[TMP50:%.*]] = phi i129 [ [[TMP27]], [[UDIV_LOOP_EXIT2]] ], [ [[TMP22]], [[_UDIV_SPECIAL_CASES_UDIV_SPECIAL_CASES:%.*]] ] +; CHECK-NEXT: [[TMP51:%.*]] = xor i129 [[TMP50]], [[TMP10]] +; CHECK-NEXT: [[TMP52:%.*]] = sub i129 [[TMP51]], [[TMP10]] +; CHECK-NEXT: [[TMP53:%.*]] = insertelement <2 x i129> poison, i129 [[TMP52]], i64 0 +; CHECK-NEXT: [[TMP54:%.*]] = extractelement <2 x i129> [[A]], i64 1 +; CHECK-NEXT: [[TMP55:%.*]] = extractelement <2 x i129> [[B]], i64 1 +; CHECK-NEXT: [[TMP56:%.*]] = freeze i129 [[TMP54]] +; CHECK-NEXT: [[TMP57:%.*]] = freeze i129 [[TMP55]] +; CHECK-NEXT: [[TMP58:%.*]] = ashr i129 [[TMP56]], 128 +; CHECK-NEXT: [[TMP59:%.*]] = ashr i129 [[TMP57]], 128 +; CHECK-NEXT: [[TMP60:%.*]] = xor i129 [[TMP58]], [[TMP56]] +; CHECK-NEXT: [[TMP61:%.*]] = sub i129 [[TMP60]], [[TMP58]] +; CHECK-NEXT: [[TMP62:%.*]] = xor i129 [[TMP59]], [[TMP57]] +; CHECK-NEXT: [[TMP63:%.*]] = sub i129 [[TMP62]], [[TMP59]] +; CHECK-NEXT: [[TMP64:%.*]] = xor i129 [[TMP59]], [[TMP58]] +; CHECK-NEXT: [[TMP65:%.*]] = freeze i129 [[TMP63]] +; CHECK-NEXT: [[TMP66:%.*]] = freeze i129 [[TMP61]] +; CHECK-NEXT: [[TMP67:%.*]] = icmp eq i129 [[TMP65]], 0 +; CHECK-NEXT: [[TMP68:%.*]] = icmp eq i129 [[TMP66]], 0 +; CHECK-NEXT: [[TMP69:%.*]] = or i1 [[TMP67]], [[TMP68]] +; CHECK-NEXT: [[TMP70:%.*]] = call i129 @llvm.ctlz.i129(i129 [[TMP65]], i1 true) +; CHECK-NEXT: [[TMP71:%.*]] = call i129 @llvm.ctlz.i129(i129 [[TMP66]], i1 true) +; CHECK-NEXT: [[TMP72:%.*]] = sub i129 [[TMP70]], [[TMP71]] +; CHECK-NEXT: [[TMP73:%.*]] = icmp ugt i129 [[TMP72]], 128 +; CHECK-NEXT: [[TMP74:%.*]] = select i1 [[TMP69]], i1 true, i1 [[TMP73]] +; CHECK-NEXT: [[TMP75:%.*]] = icmp eq i129 [[TMP72]], 128 +; CHECK-NEXT: [[TMP76:%.*]] = select i1 [[TMP74]], i129 0, i129 [[TMP66]] +; CHECK-NEXT: [[TMP77:%.*]] = select i1 [[TMP74]], i1 true, i1 [[TMP75]] +; CHECK-NEXT: br i1 [[TMP77]], label [[UDIV_END:%.*]], label [[UDIV_BB1:%.*]] +; CHECK: udiv-loop-exit: +; CHECK-NEXT: [[TMP78:%.*]] = phi i129 [ 0, [[UDIV_BB1]] ], [ [[TMP93:%.*]], [[UDIV_DO_WHILE:%.*]] ] +; CHECK-NEXT: [[TMP79:%.*]] = phi i129 [ [[TMP102:%.*]], [[UDIV_BB1]] ], [ [[TMP90:%.*]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP80:%.*]] = shl i129 [[TMP79]], 1 +; CHECK-NEXT: [[TMP81:%.*]] = or i129 [[TMP78]], [[TMP80]] +; CHECK-NEXT: br label [[UDIV_END]] +; CHECK: udiv-do-while: +; CHECK-NEXT: [[TMP82:%.*]] = phi i129 [ 0, [[UDIV_PREHEADER:%.*]] ], [ [[TMP93]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP83:%.*]] = phi i129 [ [[TMP100:%.*]], [[UDIV_PREHEADER]] ], [ [[TMP96:%.*]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP84:%.*]] = phi i129 [ [[TMP98:%.*]], [[UDIV_PREHEADER]] ], [ [[TMP95:%.*]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP85:%.*]] = phi i129 [ [[TMP102]], [[UDIV_PREHEADER]] ], [ [[TMP90]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP86:%.*]] = shl i129 [[TMP84]], 1 +; CHECK-NEXT: [[TMP87:%.*]] = lshr i129 [[TMP85]], 128 +; CHECK-NEXT: [[TMP88:%.*]] = or i129 [[TMP86]], [[TMP87]] +; CHECK-NEXT: [[TMP89:%.*]] = shl i129 [[TMP85]], 1 +; CHECK-NEXT: [[TMP90]] = or i129 [[TMP82]], [[TMP89]] +; CHECK-NEXT: [[TMP91:%.*]] = sub i129 [[TMP99:%.*]], [[TMP88]] +; CHECK-NEXT: [[TMP92:%.*]] = ashr i129 [[TMP91]], 128 +; CHECK-NEXT: [[TMP93]] = and i129 [[TMP92]], 1 +; CHECK-NEXT: [[TMP94:%.*]] = and i129 [[TMP92]], [[TMP65]] +; CHECK-NEXT: [[TMP95]] = sub i129 [[TMP88]], [[TMP94]] +; CHECK-NEXT: [[TMP96]] = add i129 [[TMP83]], -1 +; CHECK-NEXT: [[TMP97:%.*]] = icmp eq i129 [[TMP96]], 0 +; CHECK-NEXT: br i1 [[TMP97]], label [[UDIV_LOOP_EXIT:%.*]], label [[UDIV_DO_WHILE]] +; CHECK: udiv-preheader: +; CHECK-NEXT: [[TMP98]] = lshr i129 [[TMP66]], [[TMP100]] +; CHECK-NEXT: [[TMP99]] = add i129 [[TMP65]], -1 +; CHECK-NEXT: br label [[UDIV_DO_WHILE]] +; CHECK: udiv-bb1: +; CHECK-NEXT: [[TMP100]] = add i129 [[TMP72]], 1 +; CHECK-NEXT: [[TMP101:%.*]] = sub i129 128, [[TMP72]] +; CHECK-NEXT: [[TMP102]] = shl i129 [[TMP66]], [[TMP101]] +; CHECK-NEXT: [[TMP103:%.*]] = icmp eq i129 [[TMP100]], 0 +; CHECK-NEXT: br i1 [[TMP103]], label [[UDIV_LOOP_EXIT]], label [[UDIV_PREHEADER]] +; CHECK: udiv-end: +; CHECK-NEXT: [[TMP104:%.*]] = phi i129 [ [[TMP81]], [[UDIV_LOOP_EXIT]] ], [ [[TMP76]], [[UDIV_END1]] ] +; CHECK-NEXT: [[TMP105:%.*]] = xor i129 [[TMP104]], [[TMP64]] +; CHECK-NEXT: [[TMP106:%.*]] = sub i129 [[TMP105]], [[TMP64]] +; CHECK-NEXT: [[TMP107:%.*]] = insertelement <2 x i129> [[TMP53]], i129 [[TMP106]], i64 1 +; CHECK-NEXT: ret <2 x i129> [[TMP107]] +; + %res = sdiv <2 x i129> %a, %b + ret <2 x i129> %res +} + +define <2 x i129> @udiv129(<2 x i129> %a, <2 x i129> %b) nounwind { +; CHECK-LABEL: define <2 x i129> @udiv129( +; CHECK-SAME: <2 x i129> [[A:%.*]], <2 x i129> [[B:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: _udiv-special-cases_udiv-special-cases: +; CHECK-NEXT: [[TMP0:%.*]] = extractelement <2 x i129> [[A]], i64 0 +; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x i129> [[B]], i64 0 +; CHECK-NEXT: [[TMP2:%.*]] = freeze i129 [[TMP1]] +; CHECK-NEXT: [[TMP3:%.*]] = freeze i129 [[TMP0]] +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i129 [[TMP2]], 0 +; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i129 [[TMP3]], 0 +; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[TMP4]], [[TMP5]] +; CHECK-NEXT: [[TMP7:%.*]] = call i129 @llvm.ctlz.i129(i129 [[TMP2]], i1 true) +; CHECK-NEXT: [[TMP8:%.*]] = call i129 @llvm.ctlz.i129(i129 [[TMP3]], i1 true) +; CHECK-NEXT: [[TMP9:%.*]] = sub i129 [[TMP7]], [[TMP8]] +; CHECK-NEXT: [[TMP10:%.*]] = icmp ugt i129 [[TMP9]], 128 +; CHECK-NEXT: [[TMP11:%.*]] = select i1 [[TMP6]], i1 true, i1 [[TMP10]] +; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i129 [[TMP9]], 128 +; CHECK-NEXT: [[TMP13:%.*]] = select i1 [[TMP11]], i129 0, i129 [[TMP3]] +; CHECK-NEXT: [[TMP14:%.*]] = select i1 [[TMP11]], i1 true, i1 [[TMP12]] +; CHECK-NEXT: br i1 [[TMP14]], label [[UDIV_END1:%.*]], label [[UDIV_BB15:%.*]] +; CHECK: udiv-loop-exit2: +; CHECK-NEXT: [[TMP15:%.*]] = phi i129 [ 0, [[UDIV_BB15]] ], [ [[TMP30:%.*]], [[UDIV_DO_WHILE3:%.*]] ] +; CHECK-NEXT: [[TMP16:%.*]] = phi i129 [ [[TMP39:%.*]], [[UDIV_BB15]] ], [ [[TMP27:%.*]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP17:%.*]] = shl i129 [[TMP16]], 1 +; CHECK-NEXT: [[TMP18:%.*]] = or i129 [[TMP15]], [[TMP17]] +; CHECK-NEXT: br label [[UDIV_END1]] +; CHECK: udiv-do-while3: +; CHECK-NEXT: [[TMP19:%.*]] = phi i129 [ 0, [[UDIV_PREHEADER4:%.*]] ], [ [[TMP30]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP20:%.*]] = phi i129 [ [[TMP37:%.*]], [[UDIV_PREHEADER4]] ], [ [[TMP33:%.*]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP21:%.*]] = phi i129 [ [[TMP35:%.*]], [[UDIV_PREHEADER4]] ], [ [[TMP32:%.*]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP22:%.*]] = phi i129 [ [[TMP39]], [[UDIV_PREHEADER4]] ], [ [[TMP27]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP23:%.*]] = shl i129 [[TMP21]], 1 +; CHECK-NEXT: [[TMP24:%.*]] = lshr i129 [[TMP22]], 128 +; CHECK-NEXT: [[TMP25:%.*]] = or i129 [[TMP23]], [[TMP24]] +; CHECK-NEXT: [[TMP26:%.*]] = shl i129 [[TMP22]], 1 +; CHECK-NEXT: [[TMP27]] = or i129 [[TMP19]], [[TMP26]] +; CHECK-NEXT: [[TMP28:%.*]] = sub i129 [[TMP36:%.*]], [[TMP25]] +; CHECK-NEXT: [[TMP29:%.*]] = ashr i129 [[TMP28]], 128 +; CHECK-NEXT: [[TMP30]] = and i129 [[TMP29]], 1 +; CHECK-NEXT: [[TMP31:%.*]] = and i129 [[TMP29]], [[TMP2]] +; CHECK-NEXT: [[TMP32]] = sub i129 [[TMP25]], [[TMP31]] +; CHECK-NEXT: [[TMP33]] = add i129 [[TMP20]], -1 +; CHECK-NEXT: [[TMP34:%.*]] = icmp eq i129 [[TMP33]], 0 +; CHECK-NEXT: br i1 [[TMP34]], label [[UDIV_LOOP_EXIT2:%.*]], label [[UDIV_DO_WHILE3]] +; CHECK: udiv-preheader4: +; CHECK-NEXT: [[TMP35]] = lshr i129 [[TMP3]], [[TMP37]] +; CHECK-NEXT: [[TMP36]] = add i129 [[TMP2]], -1 +; CHECK-NEXT: br label [[UDIV_DO_WHILE3]] +; CHECK: udiv-bb15: +; CHECK-NEXT: [[TMP37]] = add i129 [[TMP9]], 1 +; CHECK-NEXT: [[TMP38:%.*]] = sub i129 128, [[TMP9]] +; CHECK-NEXT: [[TMP39]] = shl i129 [[TMP3]], [[TMP38]] +; CHECK-NEXT: [[TMP40:%.*]] = icmp eq i129 [[TMP37]], 0 +; CHECK-NEXT: br i1 [[TMP40]], label [[UDIV_LOOP_EXIT2]], label [[UDIV_PREHEADER4]] +; CHECK: udiv-end1: +; CHECK-NEXT: [[TMP41:%.*]] = phi i129 [ [[TMP18]], [[UDIV_LOOP_EXIT2]] ], [ [[TMP13]], [[_UDIV_SPECIAL_CASES_UDIV_SPECIAL_CASES:%.*]] ] +; CHECK-NEXT: [[TMP42:%.*]] = insertelement <2 x i129> poison, i129 [[TMP41]], i64 0 +; CHECK-NEXT: [[TMP43:%.*]] = extractelement <2 x i129> [[A]], i64 1 +; CHECK-NEXT: [[TMP44:%.*]] = extractelement <2 x i129> [[B]], i64 1 +; CHECK-NEXT: [[TMP45:%.*]] = freeze i129 [[TMP44]] +; CHECK-NEXT: [[TMP46:%.*]] = freeze i129 [[TMP43]] +; CHECK-NEXT: [[TMP47:%.*]] = icmp eq i129 [[TMP45]], 0 +; CHECK-NEXT: [[TMP48:%.*]] = icmp eq i129 [[TMP46]], 0 +; CHECK-NEXT: [[TMP49:%.*]] = or i1 [[TMP47]], [[TMP48]] +; CHECK-NEXT: [[TMP50:%.*]] = call i129 @llvm.ctlz.i129(i129 [[TMP45]], i1 true) +; CHECK-NEXT: [[TMP51:%.*]] = call i129 @llvm.ctlz.i129(i129 [[TMP46]], i1 true) +; CHECK-NEXT: [[TMP52:%.*]] = sub i129 [[TMP50]], [[TMP51]] +; CHECK-NEXT: [[TMP53:%.*]] = icmp ugt i129 [[TMP52]], 128 +; CHECK-NEXT: [[TMP54:%.*]] = select i1 [[TMP49]], i1 true, i1 [[TMP53]] +; CHECK-NEXT: [[TMP55:%.*]] = icmp eq i129 [[TMP52]], 128 +; CHECK-NEXT: [[TMP56:%.*]] = select i1 [[TMP54]], i129 0, i129 [[TMP46]] +; CHECK-NEXT: [[TMP57:%.*]] = select i1 [[TMP54]], i1 true, i1 [[TMP55]] +; CHECK-NEXT: br i1 [[TMP57]], label [[UDIV_END:%.*]], label [[UDIV_BB1:%.*]] +; CHECK: udiv-loop-exit: +; CHECK-NEXT: [[TMP58:%.*]] = phi i129 [ 0, [[UDIV_BB1]] ], [ [[TMP73:%.*]], [[UDIV_DO_WHILE:%.*]] ] +; CHECK-NEXT: [[TMP59:%.*]] = phi i129 [ [[TMP82:%.*]], [[UDIV_BB1]] ], [ [[TMP70:%.*]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP60:%.*]] = shl i129 [[TMP59]], 1 +; CHECK-NEXT: [[TMP61:%.*]] = or i129 [[TMP58]], [[TMP60]] +; CHECK-NEXT: br label [[UDIV_END]] +; CHECK: udiv-do-while: +; CHECK-NEXT: [[TMP62:%.*]] = phi i129 [ 0, [[UDIV_PREHEADER:%.*]] ], [ [[TMP73]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP63:%.*]] = phi i129 [ [[TMP80:%.*]], [[UDIV_PREHEADER]] ], [ [[TMP76:%.*]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP64:%.*]] = phi i129 [ [[TMP78:%.*]], [[UDIV_PREHEADER]] ], [ [[TMP75:%.*]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP65:%.*]] = phi i129 [ [[TMP82]], [[UDIV_PREHEADER]] ], [ [[TMP70]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP66:%.*]] = shl i129 [[TMP64]], 1 +; CHECK-NEXT: [[TMP67:%.*]] = lshr i129 [[TMP65]], 128 +; CHECK-NEXT: [[TMP68:%.*]] = or i129 [[TMP66]], [[TMP67]] +; CHECK-NEXT: [[TMP69:%.*]] = shl i129 [[TMP65]], 1 +; CHECK-NEXT: [[TMP70]] = or i129 [[TMP62]], [[TMP69]] +; CHECK-NEXT: [[TMP71:%.*]] = sub i129 [[TMP79:%.*]], [[TMP68]] +; CHECK-NEXT: [[TMP72:%.*]] = ashr i129 [[TMP71]], 128 +; CHECK-NEXT: [[TMP73]] = and i129 [[TMP72]], 1 +; CHECK-NEXT: [[TMP74:%.*]] = and i129 [[TMP72]], [[TMP45]] +; CHECK-NEXT: [[TMP75]] = sub i129 [[TMP68]], [[TMP74]] +; CHECK-NEXT: [[TMP76]] = add i129 [[TMP63]], -1 +; CHECK-NEXT: [[TMP77:%.*]] = icmp eq i129 [[TMP76]], 0 +; CHECK-NEXT: br i1 [[TMP77]], label [[UDIV_LOOP_EXIT:%.*]], label [[UDIV_DO_WHILE]] +; CHECK: udiv-preheader: +; CHECK-NEXT: [[TMP78]] = lshr i129 [[TMP46]], [[TMP80]] +; CHECK-NEXT: [[TMP79]] = add i129 [[TMP45]], -1 +; CHECK-NEXT: br label [[UDIV_DO_WHILE]] +; CHECK: udiv-bb1: +; CHECK-NEXT: [[TMP80]] = add i129 [[TMP52]], 1 +; CHECK-NEXT: [[TMP81:%.*]] = sub i129 128, [[TMP52]] +; CHECK-NEXT: [[TMP82]] = shl i129 [[TMP46]], [[TMP81]] +; CHECK-NEXT: [[TMP83:%.*]] = icmp eq i129 [[TMP80]], 0 +; CHECK-NEXT: br i1 [[TMP83]], label [[UDIV_LOOP_EXIT]], label [[UDIV_PREHEADER]] +; CHECK: udiv-end: +; CHECK-NEXT: [[TMP84:%.*]] = phi i129 [ [[TMP61]], [[UDIV_LOOP_EXIT]] ], [ [[TMP56]], [[UDIV_END1]] ] +; CHECK-NEXT: [[TMP85:%.*]] = insertelement <2 x i129> [[TMP42]], i129 [[TMP84]], i64 1 +; CHECK-NEXT: ret <2 x i129> [[TMP85]] +; + %res = udiv <2 x i129> %a, %b + ret <2 x i129> %res +} + +define <2 x i129> @srem129(<2 x i129> %a, <2 x i129> %b) nounwind { +; CHECK-LABEL: define <2 x i129> @srem129( +; CHECK-SAME: <2 x i129> [[A:%.*]], <2 x i129> [[B:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: _udiv-special-cases_udiv-special-cases: +; CHECK-NEXT: [[TMP0:%.*]] = extractelement <2 x i129> [[A]], i64 0 +; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x i129> [[B]], i64 0 +; CHECK-NEXT: [[TMP2:%.*]] = freeze i129 [[TMP0]] +; CHECK-NEXT: [[TMP3:%.*]] = freeze i129 [[TMP1]] +; CHECK-NEXT: [[TMP4:%.*]] = ashr i129 [[TMP2]], 128 +; CHECK-NEXT: [[TMP5:%.*]] = ashr i129 [[TMP3]], 128 +; CHECK-NEXT: [[TMP6:%.*]] = xor i129 [[TMP2]], [[TMP4]] +; CHECK-NEXT: [[TMP7:%.*]] = xor i129 [[TMP3]], [[TMP5]] +; CHECK-NEXT: [[TMP8:%.*]] = sub i129 [[TMP6]], [[TMP4]] +; CHECK-NEXT: [[TMP9:%.*]] = sub i129 [[TMP7]], [[TMP5]] +; CHECK-NEXT: [[TMP10:%.*]] = freeze i129 [[TMP8]] +; CHECK-NEXT: [[TMP11:%.*]] = freeze i129 [[TMP9]] +; CHECK-NEXT: [[TMP12:%.*]] = freeze i129 [[TMP11]] +; CHECK-NEXT: [[TMP13:%.*]] = freeze i129 [[TMP10]] +; CHECK-NEXT: [[TMP14:%.*]] = icmp eq i129 [[TMP12]], 0 +; CHECK-NEXT: [[TMP15:%.*]] = icmp eq i129 [[TMP13]], 0 +; CHECK-NEXT: [[TMP16:%.*]] = or i1 [[TMP14]], [[TMP15]] +; CHECK-NEXT: [[TMP17:%.*]] = call i129 @llvm.ctlz.i129(i129 [[TMP12]], i1 true) +; CHECK-NEXT: [[TMP18:%.*]] = call i129 @llvm.ctlz.i129(i129 [[TMP13]], i1 true) +; CHECK-NEXT: [[TMP19:%.*]] = sub i129 [[TMP17]], [[TMP18]] +; CHECK-NEXT: [[TMP20:%.*]] = icmp ugt i129 [[TMP19]], 128 +; CHECK-NEXT: [[TMP21:%.*]] = select i1 [[TMP16]], i1 true, i1 [[TMP20]] +; CHECK-NEXT: [[TMP22:%.*]] = icmp eq i129 [[TMP19]], 128 +; CHECK-NEXT: [[TMP23:%.*]] = select i1 [[TMP21]], i129 0, i129 [[TMP13]] +; CHECK-NEXT: [[TMP24:%.*]] = select i1 [[TMP21]], i1 true, i1 [[TMP22]] +; CHECK-NEXT: br i1 [[TMP24]], label [[UDIV_END1:%.*]], label [[UDIV_BB15:%.*]] +; CHECK: udiv-loop-exit2: +; CHECK-NEXT: [[TMP25:%.*]] = phi i129 [ 0, [[UDIV_BB15]] ], [ [[TMP40:%.*]], [[UDIV_DO_WHILE3:%.*]] ] +; CHECK-NEXT: [[TMP26:%.*]] = phi i129 [ [[TMP49:%.*]], [[UDIV_BB15]] ], [ [[TMP37:%.*]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP27:%.*]] = shl i129 [[TMP26]], 1 +; CHECK-NEXT: [[TMP28:%.*]] = or i129 [[TMP25]], [[TMP27]] +; CHECK-NEXT: br label [[UDIV_END1]] +; CHECK: udiv-do-while3: +; CHECK-NEXT: [[TMP29:%.*]] = phi i129 [ 0, [[UDIV_PREHEADER4:%.*]] ], [ [[TMP40]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP30:%.*]] = phi i129 [ [[TMP47:%.*]], [[UDIV_PREHEADER4]] ], [ [[TMP43:%.*]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP31:%.*]] = phi i129 [ [[TMP45:%.*]], [[UDIV_PREHEADER4]] ], [ [[TMP42:%.*]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP32:%.*]] = phi i129 [ [[TMP49]], [[UDIV_PREHEADER4]] ], [ [[TMP37]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP33:%.*]] = shl i129 [[TMP31]], 1 +; CHECK-NEXT: [[TMP34:%.*]] = lshr i129 [[TMP32]], 128 +; CHECK-NEXT: [[TMP35:%.*]] = or i129 [[TMP33]], [[TMP34]] +; CHECK-NEXT: [[TMP36:%.*]] = shl i129 [[TMP32]], 1 +; CHECK-NEXT: [[TMP37]] = or i129 [[TMP29]], [[TMP36]] +; CHECK-NEXT: [[TMP38:%.*]] = sub i129 [[TMP46:%.*]], [[TMP35]] +; CHECK-NEXT: [[TMP39:%.*]] = ashr i129 [[TMP38]], 128 +; CHECK-NEXT: [[TMP40]] = and i129 [[TMP39]], 1 +; CHECK-NEXT: [[TMP41:%.*]] = and i129 [[TMP39]], [[TMP12]] +; CHECK-NEXT: [[TMP42]] = sub i129 [[TMP35]], [[TMP41]] +; CHECK-NEXT: [[TMP43]] = add i129 [[TMP30]], -1 +; CHECK-NEXT: [[TMP44:%.*]] = icmp eq i129 [[TMP43]], 0 +; CHECK-NEXT: br i1 [[TMP44]], label [[UDIV_LOOP_EXIT2:%.*]], label [[UDIV_DO_WHILE3]] +; CHECK: udiv-preheader4: +; CHECK-NEXT: [[TMP45]] = lshr i129 [[TMP13]], [[TMP47]] +; CHECK-NEXT: [[TMP46]] = add i129 [[TMP12]], -1 +; CHECK-NEXT: br label [[UDIV_DO_WHILE3]] +; CHECK: udiv-bb15: +; CHECK-NEXT: [[TMP47]] = add i129 [[TMP19]], 1 +; CHECK-NEXT: [[TMP48:%.*]] = sub i129 128, [[TMP19]] +; CHECK-NEXT: [[TMP49]] = shl i129 [[TMP13]], [[TMP48]] +; CHECK-NEXT: [[TMP50:%.*]] = icmp eq i129 [[TMP47]], 0 +; CHECK-NEXT: br i1 [[TMP50]], label [[UDIV_LOOP_EXIT2]], label [[UDIV_PREHEADER4]] +; CHECK: udiv-end1: +; CHECK-NEXT: [[TMP51:%.*]] = phi i129 [ [[TMP28]], [[UDIV_LOOP_EXIT2]] ], [ [[TMP23]], [[_UDIV_SPECIAL_CASES_UDIV_SPECIAL_CASES:%.*]] ] +; CHECK-NEXT: [[TMP52:%.*]] = mul i129 [[TMP11]], [[TMP51]] +; CHECK-NEXT: [[TMP53:%.*]] = sub i129 [[TMP10]], [[TMP52]] +; CHECK-NEXT: [[TMP54:%.*]] = xor i129 [[TMP53]], [[TMP4]] +; CHECK-NEXT: [[TMP55:%.*]] = sub i129 [[TMP54]], [[TMP4]] +; CHECK-NEXT: [[TMP56:%.*]] = insertelement <2 x i129> poison, i129 [[TMP55]], i64 0 +; CHECK-NEXT: [[TMP57:%.*]] = extractelement <2 x i129> [[A]], i64 1 +; CHECK-NEXT: [[TMP58:%.*]] = extractelement <2 x i129> [[B]], i64 1 +; CHECK-NEXT: [[TMP59:%.*]] = freeze i129 [[TMP57]] +; CHECK-NEXT: [[TMP60:%.*]] = freeze i129 [[TMP58]] +; CHECK-NEXT: [[TMP61:%.*]] = ashr i129 [[TMP59]], 128 +; CHECK-NEXT: [[TMP62:%.*]] = ashr i129 [[TMP60]], 128 +; CHECK-NEXT: [[TMP63:%.*]] = xor i129 [[TMP59]], [[TMP61]] +; CHECK-NEXT: [[TMP64:%.*]] = xor i129 [[TMP60]], [[TMP62]] +; CHECK-NEXT: [[TMP65:%.*]] = sub i129 [[TMP63]], [[TMP61]] +; CHECK-NEXT: [[TMP66:%.*]] = sub i129 [[TMP64]], [[TMP62]] +; CHECK-NEXT: [[TMP67:%.*]] = freeze i129 [[TMP65]] +; CHECK-NEXT: [[TMP68:%.*]] = freeze i129 [[TMP66]] +; CHECK-NEXT: [[TMP69:%.*]] = freeze i129 [[TMP68]] +; CHECK-NEXT: [[TMP70:%.*]] = freeze i129 [[TMP67]] +; CHECK-NEXT: [[TMP71:%.*]] = icmp eq i129 [[TMP69]], 0 +; CHECK-NEXT: [[TMP72:%.*]] = icmp eq i129 [[TMP70]], 0 +; CHECK-NEXT: [[TMP73:%.*]] = or i1 [[TMP71]], [[TMP72]] +; CHECK-NEXT: [[TMP74:%.*]] = call i129 @llvm.ctlz.i129(i129 [[TMP69]], i1 true) +; CHECK-NEXT: [[TMP75:%.*]] = call i129 @llvm.ctlz.i129(i129 [[TMP70]], i1 true) +; CHECK-NEXT: [[TMP76:%.*]] = sub i129 [[TMP74]], [[TMP75]] +; CHECK-NEXT: [[TMP77:%.*]] = icmp ugt i129 [[TMP76]], 128 +; CHECK-NEXT: [[TMP78:%.*]] = select i1 [[TMP73]], i1 true, i1 [[TMP77]] +; CHECK-NEXT: [[TMP79:%.*]] = icmp eq i129 [[TMP76]], 128 +; CHECK-NEXT: [[TMP80:%.*]] = select i1 [[TMP78]], i129 0, i129 [[TMP70]] +; CHECK-NEXT: [[TMP81:%.*]] = select i1 [[TMP78]], i1 true, i1 [[TMP79]] +; CHECK-NEXT: br i1 [[TMP81]], label [[UDIV_END:%.*]], label [[UDIV_BB1:%.*]] +; CHECK: udiv-loop-exit: +; CHECK-NEXT: [[TMP82:%.*]] = phi i129 [ 0, [[UDIV_BB1]] ], [ [[TMP97:%.*]], [[UDIV_DO_WHILE:%.*]] ] +; CHECK-NEXT: [[TMP83:%.*]] = phi i129 [ [[TMP106:%.*]], [[UDIV_BB1]] ], [ [[TMP94:%.*]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP84:%.*]] = shl i129 [[TMP83]], 1 +; CHECK-NEXT: [[TMP85:%.*]] = or i129 [[TMP82]], [[TMP84]] +; CHECK-NEXT: br label [[UDIV_END]] +; CHECK: udiv-do-while: +; CHECK-NEXT: [[TMP86:%.*]] = phi i129 [ 0, [[UDIV_PREHEADER:%.*]] ], [ [[TMP97]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP87:%.*]] = phi i129 [ [[TMP104:%.*]], [[UDIV_PREHEADER]] ], [ [[TMP100:%.*]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP88:%.*]] = phi i129 [ [[TMP102:%.*]], [[UDIV_PREHEADER]] ], [ [[TMP99:%.*]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP89:%.*]] = phi i129 [ [[TMP106]], [[UDIV_PREHEADER]] ], [ [[TMP94]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP90:%.*]] = shl i129 [[TMP88]], 1 +; CHECK-NEXT: [[TMP91:%.*]] = lshr i129 [[TMP89]], 128 +; CHECK-NEXT: [[TMP92:%.*]] = or i129 [[TMP90]], [[TMP91]] +; CHECK-NEXT: [[TMP93:%.*]] = shl i129 [[TMP89]], 1 +; CHECK-NEXT: [[TMP94]] = or i129 [[TMP86]], [[TMP93]] +; CHECK-NEXT: [[TMP95:%.*]] = sub i129 [[TMP103:%.*]], [[TMP92]] +; CHECK-NEXT: [[TMP96:%.*]] = ashr i129 [[TMP95]], 128 +; CHECK-NEXT: [[TMP97]] = and i129 [[TMP96]], 1 +; CHECK-NEXT: [[TMP98:%.*]] = and i129 [[TMP96]], [[TMP69]] +; CHECK-NEXT: [[TMP99]] = sub i129 [[TMP92]], [[TMP98]] +; CHECK-NEXT: [[TMP100]] = add i129 [[TMP87]], -1 +; CHECK-NEXT: [[TMP101:%.*]] = icmp eq i129 [[TMP100]], 0 +; CHECK-NEXT: br i1 [[TMP101]], label [[UDIV_LOOP_EXIT:%.*]], label [[UDIV_DO_WHILE]] +; CHECK: udiv-preheader: +; CHECK-NEXT: [[TMP102]] = lshr i129 [[TMP70]], [[TMP104]] +; CHECK-NEXT: [[TMP103]] = add i129 [[TMP69]], -1 +; CHECK-NEXT: br label [[UDIV_DO_WHILE]] +; CHECK: udiv-bb1: +; CHECK-NEXT: [[TMP104]] = add i129 [[TMP76]], 1 +; CHECK-NEXT: [[TMP105:%.*]] = sub i129 128, [[TMP76]] +; CHECK-NEXT: [[TMP106]] = shl i129 [[TMP70]], [[TMP105]] +; CHECK-NEXT: [[TMP107:%.*]] = icmp eq i129 [[TMP104]], 0 +; CHECK-NEXT: br i1 [[TMP107]], label [[UDIV_LOOP_EXIT]], label [[UDIV_PREHEADER]] +; CHECK: udiv-end: +; CHECK-NEXT: [[TMP108:%.*]] = phi i129 [ [[TMP85]], [[UDIV_LOOP_EXIT]] ], [ [[TMP80]], [[UDIV_END1]] ] +; CHECK-NEXT: [[TMP109:%.*]] = mul i129 [[TMP68]], [[TMP108]] +; CHECK-NEXT: [[TMP110:%.*]] = sub i129 [[TMP67]], [[TMP109]] +; CHECK-NEXT: [[TMP111:%.*]] = xor i129 [[TMP110]], [[TMP61]] +; CHECK-NEXT: [[TMP112:%.*]] = sub i129 [[TMP111]], [[TMP61]] +; CHECK-NEXT: [[TMP113:%.*]] = insertelement <2 x i129> [[TMP56]], i129 [[TMP112]], i64 1 +; CHECK-NEXT: ret <2 x i129> [[TMP113]] +; + %res = srem <2 x i129> %a, %b + ret <2 x i129> %res +} + +define <2 x i129> @urem129(<2 x i129> %a, <2 x i129> %b) nounwind { +; CHECK-LABEL: define <2 x i129> @urem129( +; CHECK-SAME: <2 x i129> [[A:%.*]], <2 x i129> [[B:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: _udiv-special-cases_udiv-special-cases: +; CHECK-NEXT: [[TMP0:%.*]] = extractelement <2 x i129> [[A]], i64 0 +; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x i129> [[B]], i64 0 +; CHECK-NEXT: [[TMP2:%.*]] = freeze i129 [[TMP0]] +; CHECK-NEXT: [[TMP3:%.*]] = freeze i129 [[TMP1]] +; CHECK-NEXT: [[TMP4:%.*]] = freeze i129 [[TMP3]] +; CHECK-NEXT: [[TMP5:%.*]] = freeze i129 [[TMP2]] +; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i129 [[TMP4]], 0 +; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i129 [[TMP5]], 0 +; CHECK-NEXT: [[TMP8:%.*]] = or i1 [[TMP6]], [[TMP7]] +; CHECK-NEXT: [[TMP9:%.*]] = call i129 @llvm.ctlz.i129(i129 [[TMP4]], i1 true) +; CHECK-NEXT: [[TMP10:%.*]] = call i129 @llvm.ctlz.i129(i129 [[TMP5]], i1 true) +; CHECK-NEXT: [[TMP11:%.*]] = sub i129 [[TMP9]], [[TMP10]] +; CHECK-NEXT: [[TMP12:%.*]] = icmp ugt i129 [[TMP11]], 128 +; CHECK-NEXT: [[TMP13:%.*]] = select i1 [[TMP8]], i1 true, i1 [[TMP12]] +; CHECK-NEXT: [[TMP14:%.*]] = icmp eq i129 [[TMP11]], 128 +; CHECK-NEXT: [[TMP15:%.*]] = select i1 [[TMP13]], i129 0, i129 [[TMP5]] +; CHECK-NEXT: [[TMP16:%.*]] = select i1 [[TMP13]], i1 true, i1 [[TMP14]] +; CHECK-NEXT: br i1 [[TMP16]], label [[UDIV_END1:%.*]], label [[UDIV_BB15:%.*]] +; CHECK: udiv-loop-exit2: +; CHECK-NEXT: [[TMP17:%.*]] = phi i129 [ 0, [[UDIV_BB15]] ], [ [[TMP32:%.*]], [[UDIV_DO_WHILE3:%.*]] ] +; CHECK-NEXT: [[TMP18:%.*]] = phi i129 [ [[TMP41:%.*]], [[UDIV_BB15]] ], [ [[TMP29:%.*]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP19:%.*]] = shl i129 [[TMP18]], 1 +; CHECK-NEXT: [[TMP20:%.*]] = or i129 [[TMP17]], [[TMP19]] +; CHECK-NEXT: br label [[UDIV_END1]] +; CHECK: udiv-do-while3: +; CHECK-NEXT: [[TMP21:%.*]] = phi i129 [ 0, [[UDIV_PREHEADER4:%.*]] ], [ [[TMP32]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP22:%.*]] = phi i129 [ [[TMP39:%.*]], [[UDIV_PREHEADER4]] ], [ [[TMP35:%.*]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP23:%.*]] = phi i129 [ [[TMP37:%.*]], [[UDIV_PREHEADER4]] ], [ [[TMP34:%.*]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP24:%.*]] = phi i129 [ [[TMP41]], [[UDIV_PREHEADER4]] ], [ [[TMP29]], [[UDIV_DO_WHILE3]] ] +; CHECK-NEXT: [[TMP25:%.*]] = shl i129 [[TMP23]], 1 +; CHECK-NEXT: [[TMP26:%.*]] = lshr i129 [[TMP24]], 128 +; CHECK-NEXT: [[TMP27:%.*]] = or i129 [[TMP25]], [[TMP26]] +; CHECK-NEXT: [[TMP28:%.*]] = shl i129 [[TMP24]], 1 +; CHECK-NEXT: [[TMP29]] = or i129 [[TMP21]], [[TMP28]] +; CHECK-NEXT: [[TMP30:%.*]] = sub i129 [[TMP38:%.*]], [[TMP27]] +; CHECK-NEXT: [[TMP31:%.*]] = ashr i129 [[TMP30]], 128 +; CHECK-NEXT: [[TMP32]] = and i129 [[TMP31]], 1 +; CHECK-NEXT: [[TMP33:%.*]] = and i129 [[TMP31]], [[TMP4]] +; CHECK-NEXT: [[TMP34]] = sub i129 [[TMP27]], [[TMP33]] +; CHECK-NEXT: [[TMP35]] = add i129 [[TMP22]], -1 +; CHECK-NEXT: [[TMP36:%.*]] = icmp eq i129 [[TMP35]], 0 +; CHECK-NEXT: br i1 [[TMP36]], label [[UDIV_LOOP_EXIT2:%.*]], label [[UDIV_DO_WHILE3]] +; CHECK: udiv-preheader4: +; CHECK-NEXT: [[TMP37]] = lshr i129 [[TMP5]], [[TMP39]] +; CHECK-NEXT: [[TMP38]] = add i129 [[TMP4]], -1 +; CHECK-NEXT: br label [[UDIV_DO_WHILE3]] +; CHECK: udiv-bb15: +; CHECK-NEXT: [[TMP39]] = add i129 [[TMP11]], 1 +; CHECK-NEXT: [[TMP40:%.*]] = sub i129 128, [[TMP11]] +; CHECK-NEXT: [[TMP41]] = shl i129 [[TMP5]], [[TMP40]] +; CHECK-NEXT: [[TMP42:%.*]] = icmp eq i129 [[TMP39]], 0 +; CHECK-NEXT: br i1 [[TMP42]], label [[UDIV_LOOP_EXIT2]], label [[UDIV_PREHEADER4]] +; CHECK: udiv-end1: +; CHECK-NEXT: [[TMP43:%.*]] = phi i129 [ [[TMP20]], [[UDIV_LOOP_EXIT2]] ], [ [[TMP15]], [[_UDIV_SPECIAL_CASES_UDIV_SPECIAL_CASES:%.*]] ] +; CHECK-NEXT: [[TMP44:%.*]] = mul i129 [[TMP3]], [[TMP43]] +; CHECK-NEXT: [[TMP45:%.*]] = sub i129 [[TMP2]], [[TMP44]] +; CHECK-NEXT: [[TMP46:%.*]] = insertelement <2 x i129> poison, i129 [[TMP45]], i64 0 +; CHECK-NEXT: [[TMP47:%.*]] = extractelement <2 x i129> [[A]], i64 1 +; CHECK-NEXT: [[TMP48:%.*]] = extractelement <2 x i129> [[B]], i64 1 +; CHECK-NEXT: [[TMP49:%.*]] = freeze i129 [[TMP47]] +; CHECK-NEXT: [[TMP50:%.*]] = freeze i129 [[TMP48]] +; CHECK-NEXT: [[TMP51:%.*]] = freeze i129 [[TMP50]] +; CHECK-NEXT: [[TMP52:%.*]] = freeze i129 [[TMP49]] +; CHECK-NEXT: [[TMP53:%.*]] = icmp eq i129 [[TMP51]], 0 +; CHECK-NEXT: [[TMP54:%.*]] = icmp eq i129 [[TMP52]], 0 +; CHECK-NEXT: [[TMP55:%.*]] = or i1 [[TMP53]], [[TMP54]] +; CHECK-NEXT: [[TMP56:%.*]] = call i129 @llvm.ctlz.i129(i129 [[TMP51]], i1 true) +; CHECK-NEXT: [[TMP57:%.*]] = call i129 @llvm.ctlz.i129(i129 [[TMP52]], i1 true) +; CHECK-NEXT: [[TMP58:%.*]] = sub i129 [[TMP56]], [[TMP57]] +; CHECK-NEXT: [[TMP59:%.*]] = icmp ugt i129 [[TMP58]], 128 +; CHECK-NEXT: [[TMP60:%.*]] = select i1 [[TMP55]], i1 true, i1 [[TMP59]] +; CHECK-NEXT: [[TMP61:%.*]] = icmp eq i129 [[TMP58]], 128 +; CHECK-NEXT: [[TMP62:%.*]] = select i1 [[TMP60]], i129 0, i129 [[TMP52]] +; CHECK-NEXT: [[TMP63:%.*]] = select i1 [[TMP60]], i1 true, i1 [[TMP61]] +; CHECK-NEXT: br i1 [[TMP63]], label [[UDIV_END:%.*]], label [[UDIV_BB1:%.*]] +; CHECK: udiv-loop-exit: +; CHECK-NEXT: [[TMP64:%.*]] = phi i129 [ 0, [[UDIV_BB1]] ], [ [[TMP79:%.*]], [[UDIV_DO_WHILE:%.*]] ] +; CHECK-NEXT: [[TMP65:%.*]] = phi i129 [ [[TMP88:%.*]], [[UDIV_BB1]] ], [ [[TMP76:%.*]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP66:%.*]] = shl i129 [[TMP65]], 1 +; CHECK-NEXT: [[TMP67:%.*]] = or i129 [[TMP64]], [[TMP66]] +; CHECK-NEXT: br label [[UDIV_END]] +; CHECK: udiv-do-while: +; CHECK-NEXT: [[TMP68:%.*]] = phi i129 [ 0, [[UDIV_PREHEADER:%.*]] ], [ [[TMP79]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP69:%.*]] = phi i129 [ [[TMP86:%.*]], [[UDIV_PREHEADER]] ], [ [[TMP82:%.*]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP70:%.*]] = phi i129 [ [[TMP84:%.*]], [[UDIV_PREHEADER]] ], [ [[TMP81:%.*]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP71:%.*]] = phi i129 [ [[TMP88]], [[UDIV_PREHEADER]] ], [ [[TMP76]], [[UDIV_DO_WHILE]] ] +; CHECK-NEXT: [[TMP72:%.*]] = shl i129 [[TMP70]], 1 +; CHECK-NEXT: [[TMP73:%.*]] = lshr i129 [[TMP71]], 128 +; CHECK-NEXT: [[TMP74:%.*]] = or i129 [[TMP72]], [[TMP73]] +; CHECK-NEXT: [[TMP75:%.*]] = shl i129 [[TMP71]], 1 +; CHECK-NEXT: [[TMP76]] = or i129 [[TMP68]], [[TMP75]] +; CHECK-NEXT: [[TMP77:%.*]] = sub i129 [[TMP85:%.*]], [[TMP74]] +; CHECK-NEXT: [[TMP78:%.*]] = ashr i129 [[TMP77]], 128 +; CHECK-NEXT: [[TMP79]] = and i129 [[TMP78]], 1 +; CHECK-NEXT: [[TMP80:%.*]] = and i129 [[TMP78]], [[TMP51]] +; CHECK-NEXT: [[TMP81]] = sub i129 [[TMP74]], [[TMP80]] +; CHECK-NEXT: [[TMP82]] = add i129 [[TMP69]], -1 +; CHECK-NEXT: [[TMP83:%.*]] = icmp eq i129 [[TMP82]], 0 +; CHECK-NEXT: br i1 [[TMP83]], label [[UDIV_LOOP_EXIT:%.*]], label [[UDIV_DO_WHILE]] +; CHECK: udiv-preheader: +; CHECK-NEXT: [[TMP84]] = lshr i129 [[TMP52]], [[TMP86]] +; CHECK-NEXT: [[TMP85]] = add i129 [[TMP51]], -1 +; CHECK-NEXT: br label [[UDIV_DO_WHILE]] +; CHECK: udiv-bb1: +; CHECK-NEXT: [[TMP86]] = add i129 [[TMP58]], 1 +; CHECK-NEXT: [[TMP87:%.*]] = sub i129 128, [[TMP58]] +; CHECK-NEXT: [[TMP88]] = shl i129 [[TMP52]], [[TMP87]] +; CHECK-NEXT: [[TMP89:%.*]] = icmp eq i129 [[TMP86]], 0 +; CHECK-NEXT: br i1 [[TMP89]], label [[UDIV_LOOP_EXIT]], label [[UDIV_PREHEADER]] +; CHECK: udiv-end: +; CHECK-NEXT: [[TMP90:%.*]] = phi i129 [ [[TMP67]], [[UDIV_LOOP_EXIT]] ], [ [[TMP62]], [[UDIV_END1]] ] +; CHECK-NEXT: [[TMP91:%.*]] = mul i129 [[TMP50]], [[TMP90]] +; CHECK-NEXT: [[TMP92:%.*]] = sub i129 [[TMP49]], [[TMP91]] +; CHECK-NEXT: [[TMP93:%.*]] = insertelement <2 x i129> [[TMP46]], i129 [[TMP92]], i64 1 +; CHECK-NEXT: ret <2 x i129> [[TMP93]] +; + %res = urem <2 x i129> %a, %b + ret <2 x i129> %res +} + + +define <vscale x 2 x i129> @sdiv129_scalable(<vscale x 2 x i129> %a, <vscale x 2 x i129> %b) nounwind { +; CHECK-LABEL: define <vscale x 2 x i129> @sdiv129_scalable( +; CHECK-SAME: <vscale x 2 x i129> [[A:%.*]], <vscale x 2 x i129> [[B:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: [[RES:%.*]] = sdiv <vscale x 2 x i129> [[A]], [[B]] +; CHECK-NEXT: ret <vscale x 2 x i129> [[RES]] +; + %res = sdiv <vscale x 2 x i129> %a, %b + ret <vscale x 2 x i129> %res +} diff --git a/llvm/test/Transforms/ExpandLargeFpConvert/X86/expand-large-fp-convert-fptosi129.ll b/llvm/test/Transforms/ExpandLargeFpConvert/X86/expand-large-fp-convert-fptosi129.ll index 77bbd5f0bb4258b77a0da5fbfd1cca157e454d3f..75130c27f4737655934dd2999f9d2f771147df9d 100644 --- a/llvm/test/Transforms/ExpandLargeFpConvert/X86/expand-large-fp-convert-fptosi129.ll +++ b/llvm/test/Transforms/ExpandLargeFpConvert/X86/expand-large-fp-convert-fptosi129.ll @@ -27,7 +27,7 @@ define i129 @floattosi129(float %a) { ; CHECK-NEXT: br i1 [[TMP8]], label [[FP_TO_I_CLEANUP:%.*]], label [[FP_TO_I_IF_END:%.*]] ; CHECK: fp-to-i-if-end: ; CHECK-NEXT: [[TMP9:%.*]] = add i129 [[TMP5]], -256 -; CHECK-NEXT: [[TMP10:%.*]] = icmp ult i129 [[TMP9]], 4294967167 +; CHECK-NEXT: [[TMP10:%.*]] = icmp ult i129 [[TMP9]], -129 ; CHECK-NEXT: br i1 [[TMP10]], label [[FP_TO_I_IF_THEN5:%.*]], label [[FP_TO_I_IF_END9:%.*]] ; CHECK: fp-to-i-if-then5: ; CHECK-NEXT: [[TMP11:%.*]] = select i1 [[TMP2]], i129 340282366920938463463374607431768211455, i129 -340282366920938463463374607431768211456 @@ -41,7 +41,7 @@ define i129 @floattosi129(float %a) { ; CHECK-NEXT: [[TMP15:%.*]] = mul i129 [[TMP14]], [[TMP3]] ; CHECK-NEXT: br label [[FP_TO_I_CLEANUP]] ; CHECK: fp-to-i-if-else: -; CHECK-NEXT: [[TMP16:%.*]] = add i129 [[TMP5]], 4294967146 +; CHECK-NEXT: [[TMP16:%.*]] = add i129 [[TMP5]], -150 ; CHECK-NEXT: [[TMP17:%.*]] = shl i129 [[TMP7]], [[TMP16]] ; CHECK-NEXT: [[TMP18:%.*]] = mul i129 [[TMP17]], [[TMP3]] ; CHECK-NEXT: br label [[FP_TO_I_CLEANUP]] @@ -68,7 +68,7 @@ define i129 @doubletosi129(double %a) { ; CHECK-NEXT: br i1 [[TMP8]], label [[FP_TO_I_CLEANUP:%.*]], label [[FP_TO_I_IF_END:%.*]] ; CHECK: fp-to-i-if-end: ; CHECK-NEXT: [[TMP9:%.*]] = add i129 [[TMP5]], -1152 -; CHECK-NEXT: [[TMP10:%.*]] = icmp ult i129 [[TMP9]], 4294967167 +; CHECK-NEXT: [[TMP10:%.*]] = icmp ult i129 [[TMP9]], -129 ; CHECK-NEXT: br i1 [[TMP10]], label [[FP_TO_I_IF_THEN5:%.*]], label [[FP_TO_I_IF_END9:%.*]] ; CHECK: fp-to-i-if-then5: ; CHECK-NEXT: [[TMP11:%.*]] = select i1 [[TMP2]], i129 340282366920938463463374607431768211455, i129 -340282366920938463463374607431768211456 @@ -82,7 +82,7 @@ define i129 @doubletosi129(double %a) { ; CHECK-NEXT: [[TMP15:%.*]] = mul i129 [[TMP14]], [[TMP3]] ; CHECK-NEXT: br label [[FP_TO_I_CLEANUP]] ; CHECK: fp-to-i-if-else: -; CHECK-NEXT: [[TMP16:%.*]] = add i129 [[TMP5]], 4294966221 +; CHECK-NEXT: [[TMP16:%.*]] = add i129 [[TMP5]], -1075 ; CHECK-NEXT: [[TMP17:%.*]] = shl i129 [[TMP7]], [[TMP16]] ; CHECK-NEXT: [[TMP18:%.*]] = mul i129 [[TMP17]], [[TMP3]] ; CHECK-NEXT: br label [[FP_TO_I_CLEANUP]] @@ -110,7 +110,7 @@ define i129 @x86_fp80tosi129(x86_fp80 %a) { ; CHECK-NEXT: br i1 [[TMP9]], label [[FP_TO_I_CLEANUP:%.*]], label [[FP_TO_I_IF_END:%.*]] ; CHECK: fp-to-i-if-end: ; CHECK-NEXT: [[TMP10:%.*]] = add i129 [[TMP6]], -16512 -; CHECK-NEXT: [[TMP11:%.*]] = icmp ult i129 [[TMP10]], 4294967167 +; CHECK-NEXT: [[TMP11:%.*]] = icmp ult i129 [[TMP10]], -129 ; CHECK-NEXT: br i1 [[TMP11]], label [[FP_TO_I_IF_THEN5:%.*]], label [[FP_TO_I_IF_END9:%.*]] ; CHECK: fp-to-i-if-then5: ; CHECK-NEXT: [[TMP12:%.*]] = select i1 [[TMP3]], i129 340282366920938463463374607431768211455, i129 -340282366920938463463374607431768211456 @@ -124,7 +124,7 @@ define i129 @x86_fp80tosi129(x86_fp80 %a) { ; CHECK-NEXT: [[TMP16:%.*]] = mul i129 [[TMP15]], [[TMP4]] ; CHECK-NEXT: br label [[FP_TO_I_CLEANUP]] ; CHECK: fp-to-i-if-else: -; CHECK-NEXT: [[TMP17:%.*]] = add i129 [[TMP6]], 4294950801 +; CHECK-NEXT: [[TMP17:%.*]] = add i129 [[TMP6]], -16495 ; CHECK-NEXT: [[TMP18:%.*]] = shl i129 [[TMP8]], [[TMP17]] ; CHECK-NEXT: [[TMP19:%.*]] = mul i129 [[TMP18]], [[TMP4]] ; CHECK-NEXT: br label [[FP_TO_I_CLEANUP]] @@ -151,7 +151,7 @@ define i129 @fp128tosi129(fp128 %a) { ; CHECK-NEXT: br i1 [[TMP8]], label [[FP_TO_I_CLEANUP:%.*]], label [[FP_TO_I_IF_END:%.*]] ; CHECK: fp-to-i-if-end: ; CHECK-NEXT: [[TMP9:%.*]] = add i129 [[TMP5]], -16512 -; CHECK-NEXT: [[TMP10:%.*]] = icmp ult i129 [[TMP9]], 4294967167 +; CHECK-NEXT: [[TMP10:%.*]] = icmp ult i129 [[TMP9]], -129 ; CHECK-NEXT: br i1 [[TMP10]], label [[FP_TO_I_IF_THEN5:%.*]], label [[FP_TO_I_IF_END9:%.*]] ; CHECK: fp-to-i-if-then5: ; CHECK-NEXT: [[TMP11:%.*]] = select i1 [[TMP2]], i129 340282366920938463463374607431768211455, i129 -340282366920938463463374607431768211456 @@ -165,7 +165,7 @@ define i129 @fp128tosi129(fp128 %a) { ; CHECK-NEXT: [[TMP15:%.*]] = mul i129 [[TMP14]], [[TMP3]] ; CHECK-NEXT: br label [[FP_TO_I_CLEANUP]] ; CHECK: fp-to-i-if-else: -; CHECK-NEXT: [[TMP16:%.*]] = add i129 [[TMP5]], 4294950801 +; CHECK-NEXT: [[TMP16:%.*]] = add i129 [[TMP5]], -16495 ; CHECK-NEXT: [[TMP17:%.*]] = shl i129 [[TMP7]], [[TMP16]] ; CHECK-NEXT: [[TMP18:%.*]] = mul i129 [[TMP17]], [[TMP3]] ; CHECK-NEXT: br label [[FP_TO_I_CLEANUP]] diff --git a/llvm/test/Transforms/ExpandLargeFpConvert/X86/expand-large-fp-convert-fptoui129.ll b/llvm/test/Transforms/ExpandLargeFpConvert/X86/expand-large-fp-convert-fptoui129.ll index 67d9eb533a3e7b4d61815cb55d9294d5d8a1eb6e..ed630d7934c3a87a6d73d9da28dfa78ca9e9c060 100644 --- a/llvm/test/Transforms/ExpandLargeFpConvert/X86/expand-large-fp-convert-fptoui129.ll +++ b/llvm/test/Transforms/ExpandLargeFpConvert/X86/expand-large-fp-convert-fptoui129.ll @@ -27,7 +27,7 @@ define i129 @floattoui129(float %a) { ; CHECK-NEXT: br i1 [[TMP8]], label [[FP_TO_I_CLEANUP:%.*]], label [[FP_TO_I_IF_END:%.*]] ; CHECK: fp-to-i-if-end: ; CHECK-NEXT: [[TMP9:%.*]] = add i129 [[TMP5]], -256 -; CHECK-NEXT: [[TMP10:%.*]] = icmp ult i129 [[TMP9]], 4294967167 +; CHECK-NEXT: [[TMP10:%.*]] = icmp ult i129 [[TMP9]], -129 ; CHECK-NEXT: br i1 [[TMP10]], label [[FP_TO_I_IF_THEN5:%.*]], label [[FP_TO_I_IF_END9:%.*]] ; CHECK: fp-to-i-if-then5: ; CHECK-NEXT: [[TMP11:%.*]] = select i1 [[TMP2]], i129 340282366920938463463374607431768211455, i129 -340282366920938463463374607431768211456 @@ -41,7 +41,7 @@ define i129 @floattoui129(float %a) { ; CHECK-NEXT: [[TMP15:%.*]] = mul i129 [[TMP14]], [[TMP3]] ; CHECK-NEXT: br label [[FP_TO_I_CLEANUP]] ; CHECK: fp-to-i-if-else: -; CHECK-NEXT: [[TMP16:%.*]] = add i129 [[TMP5]], 4294967146 +; CHECK-NEXT: [[TMP16:%.*]] = add i129 [[TMP5]], -150 ; CHECK-NEXT: [[TMP17:%.*]] = shl i129 [[TMP7]], [[TMP16]] ; CHECK-NEXT: [[TMP18:%.*]] = mul i129 [[TMP17]], [[TMP3]] ; CHECK-NEXT: br label [[FP_TO_I_CLEANUP]] @@ -68,7 +68,7 @@ define i129 @doubletoui129(double %a) { ; CHECK-NEXT: br i1 [[TMP8]], label [[FP_TO_I_CLEANUP:%.*]], label [[FP_TO_I_IF_END:%.*]] ; CHECK: fp-to-i-if-end: ; CHECK-NEXT: [[TMP9:%.*]] = add i129 [[TMP5]], -1152 -; CHECK-NEXT: [[TMP10:%.*]] = icmp ult i129 [[TMP9]], 4294967167 +; CHECK-NEXT: [[TMP10:%.*]] = icmp ult i129 [[TMP9]], -129 ; CHECK-NEXT: br i1 [[TMP10]], label [[FP_TO_I_IF_THEN5:%.*]], label [[FP_TO_I_IF_END9:%.*]] ; CHECK: fp-to-i-if-then5: ; CHECK-NEXT: [[TMP11:%.*]] = select i1 [[TMP2]], i129 340282366920938463463374607431768211455, i129 -340282366920938463463374607431768211456 @@ -82,7 +82,7 @@ define i129 @doubletoui129(double %a) { ; CHECK-NEXT: [[TMP15:%.*]] = mul i129 [[TMP14]], [[TMP3]] ; CHECK-NEXT: br label [[FP_TO_I_CLEANUP]] ; CHECK: fp-to-i-if-else: -; CHECK-NEXT: [[TMP16:%.*]] = add i129 [[TMP5]], 4294966221 +; CHECK-NEXT: [[TMP16:%.*]] = add i129 [[TMP5]], -1075 ; CHECK-NEXT: [[TMP17:%.*]] = shl i129 [[TMP7]], [[TMP16]] ; CHECK-NEXT: [[TMP18:%.*]] = mul i129 [[TMP17]], [[TMP3]] ; CHECK-NEXT: br label [[FP_TO_I_CLEANUP]] @@ -110,7 +110,7 @@ define i129 @x86_fp80toui129(x86_fp80 %a) { ; CHECK-NEXT: br i1 [[TMP9]], label [[FP_TO_I_CLEANUP:%.*]], label [[FP_TO_I_IF_END:%.*]] ; CHECK: fp-to-i-if-end: ; CHECK-NEXT: [[TMP10:%.*]] = add i129 [[TMP6]], -16512 -; CHECK-NEXT: [[TMP11:%.*]] = icmp ult i129 [[TMP10]], 4294967167 +; CHECK-NEXT: [[TMP11:%.*]] = icmp ult i129 [[TMP10]], -129 ; CHECK-NEXT: br i1 [[TMP11]], label [[FP_TO_I_IF_THEN5:%.*]], label [[FP_TO_I_IF_END9:%.*]] ; CHECK: fp-to-i-if-then5: ; CHECK-NEXT: [[TMP12:%.*]] = select i1 [[TMP3]], i129 340282366920938463463374607431768211455, i129 -340282366920938463463374607431768211456 @@ -124,7 +124,7 @@ define i129 @x86_fp80toui129(x86_fp80 %a) { ; CHECK-NEXT: [[TMP16:%.*]] = mul i129 [[TMP15]], [[TMP4]] ; CHECK-NEXT: br label [[FP_TO_I_CLEANUP]] ; CHECK: fp-to-i-if-else: -; CHECK-NEXT: [[TMP17:%.*]] = add i129 [[TMP6]], 4294950801 +; CHECK-NEXT: [[TMP17:%.*]] = add i129 [[TMP6]], -16495 ; CHECK-NEXT: [[TMP18:%.*]] = shl i129 [[TMP8]], [[TMP17]] ; CHECK-NEXT: [[TMP19:%.*]] = mul i129 [[TMP18]], [[TMP4]] ; CHECK-NEXT: br label [[FP_TO_I_CLEANUP]] @@ -151,7 +151,7 @@ define i129 @fp128toui129(fp128 %a) { ; CHECK-NEXT: br i1 [[TMP8]], label [[FP_TO_I_CLEANUP:%.*]], label [[FP_TO_I_IF_END:%.*]] ; CHECK: fp-to-i-if-end: ; CHECK-NEXT: [[TMP9:%.*]] = add i129 [[TMP5]], -16512 -; CHECK-NEXT: [[TMP10:%.*]] = icmp ult i129 [[TMP9]], 4294967167 +; CHECK-NEXT: [[TMP10:%.*]] = icmp ult i129 [[TMP9]], -129 ; CHECK-NEXT: br i1 [[TMP10]], label [[FP_TO_I_IF_THEN5:%.*]], label [[FP_TO_I_IF_END9:%.*]] ; CHECK: fp-to-i-if-then5: ; CHECK-NEXT: [[TMP11:%.*]] = select i1 [[TMP2]], i129 340282366920938463463374607431768211455, i129 -340282366920938463463374607431768211456 @@ -165,7 +165,7 @@ define i129 @fp128toui129(fp128 %a) { ; CHECK-NEXT: [[TMP15:%.*]] = mul i129 [[TMP14]], [[TMP3]] ; CHECK-NEXT: br label [[FP_TO_I_CLEANUP]] ; CHECK: fp-to-i-if-else: -; CHECK-NEXT: [[TMP16:%.*]] = add i129 [[TMP5]], 4294950801 +; CHECK-NEXT: [[TMP16:%.*]] = add i129 [[TMP5]], -16495 ; CHECK-NEXT: [[TMP17:%.*]] = shl i129 [[TMP7]], [[TMP16]] ; CHECK-NEXT: [[TMP18:%.*]] = mul i129 [[TMP17]], [[TMP3]] ; CHECK-NEXT: br label [[FP_TO_I_CLEANUP]] diff --git a/llvm/test/Transforms/ExpandLargeFpConvert/X86/expand-large-fp-convert-si129tofp.ll b/llvm/test/Transforms/ExpandLargeFpConvert/X86/expand-large-fp-convert-si129tofp.ll index 3961fec5b3be1889f2bd76b3053189463aa318d7..76f5248302badcbc834448418369b9a049a71d03 100644 --- a/llvm/test/Transforms/ExpandLargeFpConvert/X86/expand-large-fp-convert-si129tofp.ll +++ b/llvm/test/Transforms/ExpandLargeFpConvert/X86/expand-large-fp-convert-si129tofp.ll @@ -15,12 +15,12 @@ define half @si129tohalf(i129 %a) { ; CHECK-NEXT: [[TMP5:%.*]] = trunc i129 [[TMP4]] to i32 ; CHECK-NEXT: [[TMP6:%.*]] = sub i32 129, [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = sub i32 128, [[TMP5]] -; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i32 [[TMP7]], 24 +; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i32 [[TMP6]], 24 ; CHECK-NEXT: br i1 [[TMP8]], label [[ITOFP_IF_THEN4:%.*]], label [[ITOFP_IF_ELSE:%.*]] ; CHECK: itofp-if-then4: ; CHECK-NEXT: switch i32 [[TMP6]], label [[ITOFP_SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 25, label [[ITOFP_SW_BB:%.*]] -; CHECK-NEXT: i32 26, label [[ITOFP_SW_EPILOG:%.*]] +; CHECK-NEXT: i32 25, label [[ITOFP_SW_BB:%.*]] +; CHECK-NEXT: i32 26, label [[ITOFP_SW_EPILOG:%.*]] ; CHECK-NEXT: ] ; CHECK: itofp-sw-bb: ; CHECK-NEXT: [[TMP9:%.*]] = shl i129 [[TMP3]], 1 @@ -100,12 +100,12 @@ define float @si129tofloat(i129 %a) { ; CHECK-NEXT: [[TMP5:%.*]] = trunc i129 [[TMP4]] to i32 ; CHECK-NEXT: [[TMP6:%.*]] = sub i32 129, [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = sub i32 128, [[TMP5]] -; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i32 [[TMP7]], 24 +; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i32 [[TMP6]], 24 ; CHECK-NEXT: br i1 [[TMP8]], label [[ITOFP_IF_THEN4:%.*]], label [[ITOFP_IF_ELSE:%.*]] ; CHECK: itofp-if-then4: ; CHECK-NEXT: switch i32 [[TMP6]], label [[ITOFP_SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 25, label [[ITOFP_SW_BB:%.*]] -; CHECK-NEXT: i32 26, label [[ITOFP_SW_EPILOG:%.*]] +; CHECK-NEXT: i32 25, label [[ITOFP_SW_BB:%.*]] +; CHECK-NEXT: i32 26, label [[ITOFP_SW_EPILOG:%.*]] ; CHECK-NEXT: ] ; CHECK: itofp-sw-bb: ; CHECK-NEXT: [[TMP9:%.*]] = shl i129 [[TMP3]], 1 @@ -184,12 +184,12 @@ define double @si129todouble(i129 %a) { ; CHECK-NEXT: [[TMP5:%.*]] = trunc i129 [[TMP4]] to i32 ; CHECK-NEXT: [[TMP6:%.*]] = sub i32 129, [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = sub i32 128, [[TMP5]] -; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i32 [[TMP7]], 53 +; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i32 [[TMP6]], 53 ; CHECK-NEXT: br i1 [[TMP8]], label [[ITOFP_IF_THEN4:%.*]], label [[ITOFP_IF_ELSE:%.*]] ; CHECK: itofp-if-then4: ; CHECK-NEXT: switch i32 [[TMP6]], label [[ITOFP_SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 54, label [[ITOFP_SW_BB:%.*]] -; CHECK-NEXT: i32 55, label [[ITOFP_SW_EPILOG:%.*]] +; CHECK-NEXT: i32 54, label [[ITOFP_SW_BB:%.*]] +; CHECK-NEXT: i32 55, label [[ITOFP_SW_EPILOG:%.*]] ; CHECK-NEXT: ] ; CHECK: itofp-sw-bb: ; CHECK-NEXT: [[TMP9:%.*]] = shl i129 [[TMP3]], 1 @@ -273,12 +273,12 @@ define x86_fp80 @si129tox86_fp80(i129 %a) { ; CHECK-NEXT: [[TMP5:%.*]] = trunc i129 [[TMP4]] to i32 ; CHECK-NEXT: [[TMP6:%.*]] = sub i129 129, [[TMP4]] ; CHECK-NEXT: [[TMP7:%.*]] = sub i129 128, [[TMP4]] -; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i129 [[TMP7]], 113 +; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i129 [[TMP6]], 113 ; CHECK-NEXT: br i1 [[TMP8]], label [[ITOFP_IF_THEN4:%.*]], label [[ITOFP_IF_ELSE:%.*]] ; CHECK: itofp-if-then4: ; CHECK-NEXT: switch i129 [[TMP6]], label [[ITOFP_SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i129 114, label [[ITOFP_SW_BB:%.*]] -; CHECK-NEXT: i129 115, label [[ITOFP_SW_EPILOG:%.*]] +; CHECK-NEXT: i129 114, label [[ITOFP_SW_BB:%.*]] +; CHECK-NEXT: i129 115, label [[ITOFP_SW_EPILOG:%.*]] ; CHECK-NEXT: ] ; CHECK: itofp-sw-bb: ; CHECK-NEXT: [[TMP9:%.*]] = shl i129 [[TMP3]], 1 @@ -357,12 +357,12 @@ define fp128 @si129tofp128(i129 %a) { ; CHECK-NEXT: [[TMP5:%.*]] = trunc i129 [[TMP4]] to i32 ; CHECK-NEXT: [[TMP6:%.*]] = sub i129 129, [[TMP4]] ; CHECK-NEXT: [[TMP7:%.*]] = sub i129 128, [[TMP4]] -; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i129 [[TMP7]], 113 +; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i129 [[TMP6]], 113 ; CHECK-NEXT: br i1 [[TMP8]], label [[ITOFP_IF_THEN4:%.*]], label [[ITOFP_IF_ELSE:%.*]] ; CHECK: itofp-if-then4: ; CHECK-NEXT: switch i129 [[TMP6]], label [[ITOFP_SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i129 114, label [[ITOFP_SW_BB:%.*]] -; CHECK-NEXT: i129 115, label [[ITOFP_SW_EPILOG:%.*]] +; CHECK-NEXT: i129 114, label [[ITOFP_SW_BB:%.*]] +; CHECK-NEXT: i129 115, label [[ITOFP_SW_EPILOG:%.*]] ; CHECK-NEXT: ] ; CHECK: itofp-sw-bb: ; CHECK-NEXT: [[TMP9:%.*]] = shl i129 [[TMP3]], 1 diff --git a/llvm/test/Transforms/ExpandLargeFpConvert/X86/expand-large-fp-convert-ui129tofp.ll b/llvm/test/Transforms/ExpandLargeFpConvert/X86/expand-large-fp-convert-ui129tofp.ll index e05ff198ecc33b8506dff2954bf35ff66c34cdaf..96d87a5cace98baf82911d2e9ff9eb880b267efb 100644 --- a/llvm/test/Transforms/ExpandLargeFpConvert/X86/expand-large-fp-convert-ui129tofp.ll +++ b/llvm/test/Transforms/ExpandLargeFpConvert/X86/expand-large-fp-convert-ui129tofp.ll @@ -15,12 +15,12 @@ define half @ui129tohalf(i129 %a) { ; CHECK-NEXT: [[TMP5:%.*]] = trunc i129 [[TMP4]] to i32 ; CHECK-NEXT: [[TMP6:%.*]] = sub i32 129, [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = sub i32 128, [[TMP5]] -; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i32 [[TMP7]], 24 +; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i32 [[TMP6]], 24 ; CHECK-NEXT: br i1 [[TMP8]], label [[ITOFP_IF_THEN4:%.*]], label [[ITOFP_IF_ELSE:%.*]] ; CHECK: itofp-if-then4: ; CHECK-NEXT: switch i32 [[TMP6]], label [[ITOFP_SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 25, label [[ITOFP_SW_BB:%.*]] -; CHECK-NEXT: i32 26, label [[ITOFP_SW_EPILOG:%.*]] +; CHECK-NEXT: i32 25, label [[ITOFP_SW_BB:%.*]] +; CHECK-NEXT: i32 26, label [[ITOFP_SW_EPILOG:%.*]] ; CHECK-NEXT: ] ; CHECK: itofp-sw-bb: ; CHECK-NEXT: [[TMP9:%.*]] = shl i129 [[A]], 1 @@ -100,12 +100,12 @@ define float @ui129tofloat(i129 %a) { ; CHECK-NEXT: [[TMP5:%.*]] = trunc i129 [[TMP4]] to i32 ; CHECK-NEXT: [[TMP6:%.*]] = sub i32 129, [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = sub i32 128, [[TMP5]] -; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i32 [[TMP7]], 24 +; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i32 [[TMP6]], 24 ; CHECK-NEXT: br i1 [[TMP8]], label [[ITOFP_IF_THEN4:%.*]], label [[ITOFP_IF_ELSE:%.*]] ; CHECK: itofp-if-then4: ; CHECK-NEXT: switch i32 [[TMP6]], label [[ITOFP_SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 25, label [[ITOFP_SW_BB:%.*]] -; CHECK-NEXT: i32 26, label [[ITOFP_SW_EPILOG:%.*]] +; CHECK-NEXT: i32 25, label [[ITOFP_SW_BB:%.*]] +; CHECK-NEXT: i32 26, label [[ITOFP_SW_EPILOG:%.*]] ; CHECK-NEXT: ] ; CHECK: itofp-sw-bb: ; CHECK-NEXT: [[TMP9:%.*]] = shl i129 [[A]], 1 @@ -184,12 +184,12 @@ define double @ui129todouble(i129 %a) { ; CHECK-NEXT: [[TMP5:%.*]] = trunc i129 [[TMP4]] to i32 ; CHECK-NEXT: [[TMP6:%.*]] = sub i32 129, [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = sub i32 128, [[TMP5]] -; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i32 [[TMP7]], 53 +; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i32 [[TMP6]], 53 ; CHECK-NEXT: br i1 [[TMP8]], label [[ITOFP_IF_THEN4:%.*]], label [[ITOFP_IF_ELSE:%.*]] ; CHECK: itofp-if-then4: ; CHECK-NEXT: switch i32 [[TMP6]], label [[ITOFP_SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i32 54, label [[ITOFP_SW_BB:%.*]] -; CHECK-NEXT: i32 55, label [[ITOFP_SW_EPILOG:%.*]] +; CHECK-NEXT: i32 54, label [[ITOFP_SW_BB:%.*]] +; CHECK-NEXT: i32 55, label [[ITOFP_SW_EPILOG:%.*]] ; CHECK-NEXT: ] ; CHECK: itofp-sw-bb: ; CHECK-NEXT: [[TMP9:%.*]] = shl i129 [[A]], 1 @@ -273,12 +273,12 @@ define x86_fp80 @ui129tox86_fp80(i129 %a) { ; CHECK-NEXT: [[TMP5:%.*]] = trunc i129 [[TMP4]] to i32 ; CHECK-NEXT: [[TMP6:%.*]] = sub i129 129, [[TMP4]] ; CHECK-NEXT: [[TMP7:%.*]] = sub i129 128, [[TMP4]] -; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i129 [[TMP7]], 113 +; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i129 [[TMP6]], 113 ; CHECK-NEXT: br i1 [[TMP8]], label [[ITOFP_IF_THEN4:%.*]], label [[ITOFP_IF_ELSE:%.*]] ; CHECK: itofp-if-then4: ; CHECK-NEXT: switch i129 [[TMP6]], label [[ITOFP_SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i129 114, label [[ITOFP_SW_BB:%.*]] -; CHECK-NEXT: i129 115, label [[ITOFP_SW_EPILOG:%.*]] +; CHECK-NEXT: i129 114, label [[ITOFP_SW_BB:%.*]] +; CHECK-NEXT: i129 115, label [[ITOFP_SW_EPILOG:%.*]] ; CHECK-NEXT: ] ; CHECK: itofp-sw-bb: ; CHECK-NEXT: [[TMP9:%.*]] = shl i129 [[A]], 1 @@ -357,12 +357,12 @@ define fp128 @ui129tofp128(i129 %a) { ; CHECK-NEXT: [[TMP5:%.*]] = trunc i129 [[TMP4]] to i32 ; CHECK-NEXT: [[TMP6:%.*]] = sub i129 129, [[TMP4]] ; CHECK-NEXT: [[TMP7:%.*]] = sub i129 128, [[TMP4]] -; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i129 [[TMP7]], 113 +; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt i129 [[TMP6]], 113 ; CHECK-NEXT: br i1 [[TMP8]], label [[ITOFP_IF_THEN4:%.*]], label [[ITOFP_IF_ELSE:%.*]] ; CHECK: itofp-if-then4: ; CHECK-NEXT: switch i129 [[TMP6]], label [[ITOFP_SW_DEFAULT:%.*]] [ -; CHECK-NEXT: i129 114, label [[ITOFP_SW_BB:%.*]] -; CHECK-NEXT: i129 115, label [[ITOFP_SW_EPILOG:%.*]] +; CHECK-NEXT: i129 114, label [[ITOFP_SW_BB:%.*]] +; CHECK-NEXT: i129 115, label [[ITOFP_SW_EPILOG:%.*]] ; CHECK-NEXT: ] ; CHECK: itofp-sw-bb: ; CHECK-NEXT: [[TMP9:%.*]] = shl i129 [[A]], 1 diff --git a/llvm/test/Transforms/Float2Int/basic.ll b/llvm/test/Transforms/Float2Int/basic.ll index 2854a83179b7eb68de840643c371a669e12bdc7b..32f5ca2a053c15103d9946924a73e9ebd54e8514 100644 --- a/llvm/test/Transforms/Float2Int/basic.ll +++ b/llvm/test/Transforms/Float2Int/basic.ll @@ -1,16 +1,35 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -passes='float2int' -S | FileCheck %s +; RUN: opt < %s -passes='float2int' -S | FileCheck %s -check-prefixes=CHECK,NONE +; RUN: opt < %s -passes='float2int' -S --data-layout="n64" | FileCheck %s -check-prefixes=CHECK,ONLY64 +; RUN: opt < %s -passes='float2int' -S --data-layout="n8:16:32:64"| FileCheck %s -check-prefixes=CHECK,MULTIPLE +; RUN: opt < %s -passes=float2int -S --data-layout="e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"| FileCheck %s -check-prefixes=CHECK,PR-79158 ; ; Positive tests ; define i16 @simple1(i8 %a) { -; CHECK-LABEL: @simple1( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[T21:%.*]] = add i32 [[TMP1]], 1 -; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i16 -; CHECK-NEXT: ret i16 [[TMP2]] +; NONE-LABEL: @simple1( +; NONE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; NONE-NEXT: [[T21:%.*]] = add i32 [[TMP1]], 1 +; NONE-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i16 +; NONE-NEXT: ret i16 [[TMP2]] +; +; ONLY64-LABEL: @simple1( +; ONLY64-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i64 +; ONLY64-NEXT: [[T21:%.*]] = add i64 [[TMP1]], 1 +; ONLY64-NEXT: [[TMP2:%.*]] = trunc i64 [[T21]] to i16 +; ONLY64-NEXT: ret i16 [[TMP2]] +; +; MULTIPLE-LABEL: @simple1( +; MULTIPLE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; MULTIPLE-NEXT: [[T21:%.*]] = add i16 [[TMP1]], 1 +; MULTIPLE-NEXT: ret i16 [[T21]] +; +; PR-79158-LABEL: @simple1( +; PR-79158-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; PR-79158-NEXT: [[T21:%.*]] = add i16 [[TMP1]], 1 +; PR-79158-NEXT: ret i16 [[T21]] ; %t1 = uitofp i8 %a to float %t2 = fadd float %t1, 1.0 @@ -19,11 +38,29 @@ define i16 @simple1(i8 %a) { } define i8 @simple2(i8 %a) { -; CHECK-LABEL: @simple2( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[T21:%.*]] = sub i32 [[TMP1]], 1 -; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i8 -; CHECK-NEXT: ret i8 [[TMP2]] +; NONE-LABEL: @simple2( +; NONE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; NONE-NEXT: [[T21:%.*]] = sub i32 [[TMP1]], 1 +; NONE-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i8 +; NONE-NEXT: ret i8 [[TMP2]] +; +; ONLY64-LABEL: @simple2( +; ONLY64-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i64 +; ONLY64-NEXT: [[T21:%.*]] = sub i64 [[TMP1]], 1 +; ONLY64-NEXT: [[TMP2:%.*]] = trunc i64 [[T21]] to i8 +; ONLY64-NEXT: ret i8 [[TMP2]] +; +; MULTIPLE-LABEL: @simple2( +; MULTIPLE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; MULTIPLE-NEXT: [[T21:%.*]] = sub i16 [[TMP1]], 1 +; MULTIPLE-NEXT: [[TMP2:%.*]] = trunc i16 [[T21]] to i8 +; MULTIPLE-NEXT: ret i8 [[TMP2]] +; +; PR-79158-LABEL: @simple2( +; PR-79158-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; PR-79158-NEXT: [[T21:%.*]] = sub i16 [[TMP1]], 1 +; PR-79158-NEXT: [[TMP2:%.*]] = trunc i16 [[T21]] to i8 +; PR-79158-NEXT: ret i8 [[TMP2]] ; %t1 = uitofp i8 %a to float %t2 = fsub float %t1, 1.0 @@ -32,10 +69,28 @@ define i8 @simple2(i8 %a) { } define i32 @simple3(i8 %a) { -; CHECK-LABEL: @simple3( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[T21:%.*]] = sub i32 [[TMP1]], 1 -; CHECK-NEXT: ret i32 [[T21]] +; NONE-LABEL: @simple3( +; NONE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; NONE-NEXT: [[T21:%.*]] = sub i32 [[TMP1]], 1 +; NONE-NEXT: ret i32 [[T21]] +; +; ONLY64-LABEL: @simple3( +; ONLY64-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i64 +; ONLY64-NEXT: [[T21:%.*]] = sub i64 [[TMP1]], 1 +; ONLY64-NEXT: [[TMP2:%.*]] = trunc i64 [[T21]] to i32 +; ONLY64-NEXT: ret i32 [[TMP2]] +; +; MULTIPLE-LABEL: @simple3( +; MULTIPLE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; MULTIPLE-NEXT: [[T21:%.*]] = sub i16 [[TMP1]], 1 +; MULTIPLE-NEXT: [[TMP2:%.*]] = zext i16 [[T21]] to i32 +; MULTIPLE-NEXT: ret i32 [[TMP2]] +; +; PR-79158-LABEL: @simple3( +; PR-79158-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; PR-79158-NEXT: [[T21:%.*]] = sub i16 [[TMP1]], 1 +; PR-79158-NEXT: [[TMP2:%.*]] = zext i16 [[T21]] to i32 +; PR-79158-NEXT: ret i32 [[TMP2]] ; %t1 = uitofp i8 %a to float %t2 = fsub float %t1, 1.0 @@ -44,11 +99,29 @@ define i32 @simple3(i8 %a) { } define i1 @cmp(i8 %a, i8 %b) { -; CHECK-LABEL: @cmp( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 -; CHECK-NEXT: [[T31:%.*]] = icmp slt i32 [[TMP1]], [[TMP2]] -; CHECK-NEXT: ret i1 [[T31]] +; NONE-LABEL: @cmp( +; NONE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; NONE-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 +; NONE-NEXT: [[T31:%.*]] = icmp slt i32 [[TMP1]], [[TMP2]] +; NONE-NEXT: ret i1 [[T31]] +; +; ONLY64-LABEL: @cmp( +; ONLY64-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i64 +; ONLY64-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i64 +; ONLY64-NEXT: [[T31:%.*]] = icmp slt i64 [[TMP1]], [[TMP2]] +; ONLY64-NEXT: ret i1 [[T31]] +; +; MULTIPLE-LABEL: @cmp( +; MULTIPLE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; MULTIPLE-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i16 +; MULTIPLE-NEXT: [[T31:%.*]] = icmp slt i16 [[TMP1]], [[TMP2]] +; MULTIPLE-NEXT: ret i1 [[T31]] +; +; PR-79158-LABEL: @cmp( +; PR-79158-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; PR-79158-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i16 +; PR-79158-NEXT: [[T31:%.*]] = icmp slt i16 [[TMP1]], [[TMP2]] +; PR-79158-NEXT: ret i1 [[T31]] ; %t1 = uitofp i8 %a to float %t2 = uitofp i8 %b to float @@ -70,12 +143,34 @@ define i32 @simple4(i32 %a) { } define i32 @simple5(i8 %a, i8 %b) { -; CHECK-LABEL: @simple5( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 -; CHECK-NEXT: [[T31:%.*]] = add i32 [[TMP1]], 1 -; CHECK-NEXT: [[T42:%.*]] = mul i32 [[T31]], [[TMP2]] -; CHECK-NEXT: ret i32 [[T42]] +; NONE-LABEL: @simple5( +; NONE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; NONE-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 +; NONE-NEXT: [[T31:%.*]] = add i32 [[TMP1]], 1 +; NONE-NEXT: [[T42:%.*]] = mul i32 [[T31]], [[TMP2]] +; NONE-NEXT: ret i32 [[T42]] +; +; ONLY64-LABEL: @simple5( +; ONLY64-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i64 +; ONLY64-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i64 +; ONLY64-NEXT: [[T31:%.*]] = add i64 [[TMP1]], 1 +; ONLY64-NEXT: [[T42:%.*]] = mul i64 [[T31]], [[TMP2]] +; ONLY64-NEXT: [[TMP3:%.*]] = trunc i64 [[T42]] to i32 +; ONLY64-NEXT: ret i32 [[TMP3]] +; +; MULTIPLE-LABEL: @simple5( +; MULTIPLE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; MULTIPLE-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 +; MULTIPLE-NEXT: [[T31:%.*]] = add i32 [[TMP1]], 1 +; MULTIPLE-NEXT: [[T42:%.*]] = mul i32 [[T31]], [[TMP2]] +; MULTIPLE-NEXT: ret i32 [[T42]] +; +; PR-79158-LABEL: @simple5( +; PR-79158-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; PR-79158-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 +; PR-79158-NEXT: [[T31:%.*]] = add i32 [[TMP1]], 1 +; PR-79158-NEXT: [[T42:%.*]] = mul i32 [[T31]], [[TMP2]] +; PR-79158-NEXT: ret i32 [[T42]] ; %t1 = uitofp i8 %a to float %t2 = uitofp i8 %b to float @@ -86,12 +181,34 @@ define i32 @simple5(i8 %a, i8 %b) { } define i32 @simple6(i8 %a, i8 %b) { -; CHECK-LABEL: @simple6( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 -; CHECK-NEXT: [[T31:%.*]] = sub i32 0, [[TMP1]] -; CHECK-NEXT: [[T42:%.*]] = mul i32 [[T31]], [[TMP2]] -; CHECK-NEXT: ret i32 [[T42]] +; NONE-LABEL: @simple6( +; NONE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; NONE-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 +; NONE-NEXT: [[T31:%.*]] = sub i32 0, [[TMP1]] +; NONE-NEXT: [[T42:%.*]] = mul i32 [[T31]], [[TMP2]] +; NONE-NEXT: ret i32 [[T42]] +; +; ONLY64-LABEL: @simple6( +; ONLY64-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i64 +; ONLY64-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i64 +; ONLY64-NEXT: [[T31:%.*]] = sub i64 0, [[TMP1]] +; ONLY64-NEXT: [[T42:%.*]] = mul i64 [[T31]], [[TMP2]] +; ONLY64-NEXT: [[TMP3:%.*]] = trunc i64 [[T42]] to i32 +; ONLY64-NEXT: ret i32 [[TMP3]] +; +; MULTIPLE-LABEL: @simple6( +; MULTIPLE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; MULTIPLE-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 +; MULTIPLE-NEXT: [[T31:%.*]] = sub i32 0, [[TMP1]] +; MULTIPLE-NEXT: [[T42:%.*]] = mul i32 [[T31]], [[TMP2]] +; MULTIPLE-NEXT: ret i32 [[T42]] +; +; PR-79158-LABEL: @simple6( +; PR-79158-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; PR-79158-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 +; PR-79158-NEXT: [[T31:%.*]] = sub i32 0, [[TMP1]] +; PR-79158-NEXT: [[T42:%.*]] = mul i32 [[T31]], [[TMP2]] +; PR-79158-NEXT: ret i32 [[T42]] ; %t1 = uitofp i8 %a to float %t2 = uitofp i8 %b to float @@ -105,15 +222,48 @@ define i32 @simple6(i8 %a, i8 %b) { ; cause failure of the other. define i32 @multi1(i8 %a, i8 %b, i8 %c, float %d) { -; CHECK-LABEL: @multi1( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 -; CHECK-NEXT: [[FC:%.*]] = uitofp i8 [[C:%.*]] to float -; CHECK-NEXT: [[X1:%.*]] = add i32 [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[Z:%.*]] = fadd float [[FC]], [[D:%.*]] -; CHECK-NEXT: [[W:%.*]] = fptoui float [[Z]] to i32 -; CHECK-NEXT: [[R:%.*]] = add i32 [[X1]], [[W]] -; CHECK-NEXT: ret i32 [[R]] +; NONE-LABEL: @multi1( +; NONE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; NONE-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i32 +; NONE-NEXT: [[FC:%.*]] = uitofp i8 [[C:%.*]] to float +; NONE-NEXT: [[X1:%.*]] = add i32 [[TMP1]], [[TMP2]] +; NONE-NEXT: [[Z:%.*]] = fadd float [[FC]], [[D:%.*]] +; NONE-NEXT: [[W:%.*]] = fptoui float [[Z]] to i32 +; NONE-NEXT: [[R:%.*]] = add i32 [[X1]], [[W]] +; NONE-NEXT: ret i32 [[R]] +; +; ONLY64-LABEL: @multi1( +; ONLY64-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i64 +; ONLY64-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i64 +; ONLY64-NEXT: [[FC:%.*]] = uitofp i8 [[C:%.*]] to float +; ONLY64-NEXT: [[X1:%.*]] = add i64 [[TMP1]], [[TMP2]] +; ONLY64-NEXT: [[TMP3:%.*]] = trunc i64 [[X1]] to i32 +; ONLY64-NEXT: [[Z:%.*]] = fadd float [[FC]], [[D:%.*]] +; ONLY64-NEXT: [[W:%.*]] = fptoui float [[Z]] to i32 +; ONLY64-NEXT: [[R:%.*]] = add i32 [[TMP3]], [[W]] +; ONLY64-NEXT: ret i32 [[R]] +; +; MULTIPLE-LABEL: @multi1( +; MULTIPLE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; MULTIPLE-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i16 +; MULTIPLE-NEXT: [[FC:%.*]] = uitofp i8 [[C:%.*]] to float +; MULTIPLE-NEXT: [[X1:%.*]] = add i16 [[TMP1]], [[TMP2]] +; MULTIPLE-NEXT: [[TMP3:%.*]] = zext i16 [[X1]] to i32 +; MULTIPLE-NEXT: [[Z:%.*]] = fadd float [[FC]], [[D:%.*]] +; MULTIPLE-NEXT: [[W:%.*]] = fptoui float [[Z]] to i32 +; MULTIPLE-NEXT: [[R:%.*]] = add i32 [[TMP3]], [[W]] +; MULTIPLE-NEXT: ret i32 [[R]] +; +; PR-79158-LABEL: @multi1( +; PR-79158-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; PR-79158-NEXT: [[TMP2:%.*]] = zext i8 [[B:%.*]] to i16 +; PR-79158-NEXT: [[FC:%.*]] = uitofp i8 [[C:%.*]] to float +; PR-79158-NEXT: [[X1:%.*]] = add i16 [[TMP1]], [[TMP2]] +; PR-79158-NEXT: [[TMP3:%.*]] = zext i16 [[X1]] to i32 +; PR-79158-NEXT: [[Z:%.*]] = fadd float [[FC]], [[D:%.*]] +; PR-79158-NEXT: [[W:%.*]] = fptoui float [[Z]] to i32 +; PR-79158-NEXT: [[R:%.*]] = add i32 [[TMP3]], [[W]] +; PR-79158-NEXT: ret i32 [[R]] ; %fa = uitofp i8 %a to float %fb = uitofp i8 %b to float @@ -127,11 +277,27 @@ define i32 @multi1(i8 %a, i8 %b, i8 %c, float %d) { } define i16 @simple_negzero(i8 %a) { -; CHECK-LABEL: @simple_negzero( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[T21:%.*]] = add i32 [[TMP1]], 0 -; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i16 -; CHECK-NEXT: ret i16 [[TMP2]] +; NONE-LABEL: @simple_negzero( +; NONE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; NONE-NEXT: [[T21:%.*]] = add i32 [[TMP1]], 0 +; NONE-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i16 +; NONE-NEXT: ret i16 [[TMP2]] +; +; ONLY64-LABEL: @simple_negzero( +; ONLY64-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i64 +; ONLY64-NEXT: [[T21:%.*]] = add i64 [[TMP1]], 0 +; ONLY64-NEXT: [[TMP2:%.*]] = trunc i64 [[T21]] to i16 +; ONLY64-NEXT: ret i16 [[TMP2]] +; +; MULTIPLE-LABEL: @simple_negzero( +; MULTIPLE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; MULTIPLE-NEXT: [[T21:%.*]] = add i16 [[TMP1]], 0 +; MULTIPLE-NEXT: ret i16 [[T21]] +; +; PR-79158-LABEL: @simple_negzero( +; PR-79158-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; PR-79158-NEXT: [[T21:%.*]] = add i16 [[TMP1]], 0 +; PR-79158-NEXT: ret i16 [[T21]] ; %t1 = uitofp i8 %a to float %t2 = fadd fast float %t1, -0.0 @@ -140,12 +306,33 @@ define i16 @simple_negzero(i8 %a) { } define i32 @simple_negative(i8 %call) { -; CHECK-LABEL: @simple_negative( -; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[CALL:%.*]] to i32 -; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[TMP1]], -3 -; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[MUL1]] to i8 -; CHECK-NEXT: [[CONV3:%.*]] = sext i8 [[TMP2]] to i32 -; CHECK-NEXT: ret i32 [[CONV3]] +; NONE-LABEL: @simple_negative( +; NONE-NEXT: [[TMP1:%.*]] = sext i8 [[CALL:%.*]] to i32 +; NONE-NEXT: [[MUL1:%.*]] = mul i32 [[TMP1]], -3 +; NONE-NEXT: [[TMP2:%.*]] = trunc i32 [[MUL1]] to i8 +; NONE-NEXT: [[CONV3:%.*]] = sext i8 [[TMP2]] to i32 +; NONE-NEXT: ret i32 [[CONV3]] +; +; ONLY64-LABEL: @simple_negative( +; ONLY64-NEXT: [[TMP1:%.*]] = sext i8 [[CALL:%.*]] to i64 +; ONLY64-NEXT: [[MUL1:%.*]] = mul i64 [[TMP1]], -3 +; ONLY64-NEXT: [[TMP2:%.*]] = trunc i64 [[MUL1]] to i8 +; ONLY64-NEXT: [[CONV3:%.*]] = sext i8 [[TMP2]] to i32 +; ONLY64-NEXT: ret i32 [[CONV3]] +; +; MULTIPLE-LABEL: @simple_negative( +; MULTIPLE-NEXT: [[TMP1:%.*]] = sext i8 [[CALL:%.*]] to i16 +; MULTIPLE-NEXT: [[MUL1:%.*]] = mul i16 [[TMP1]], -3 +; MULTIPLE-NEXT: [[TMP2:%.*]] = trunc i16 [[MUL1]] to i8 +; MULTIPLE-NEXT: [[CONV3:%.*]] = sext i8 [[TMP2]] to i32 +; MULTIPLE-NEXT: ret i32 [[CONV3]] +; +; PR-79158-LABEL: @simple_negative( +; PR-79158-NEXT: [[TMP1:%.*]] = sext i8 [[CALL:%.*]] to i16 +; PR-79158-NEXT: [[MUL1:%.*]] = mul i16 [[TMP1]], -3 +; PR-79158-NEXT: [[TMP2:%.*]] = trunc i16 [[MUL1]] to i8 +; PR-79158-NEXT: [[CONV3:%.*]] = sext i8 [[TMP2]] to i32 +; PR-79158-NEXT: ret i32 [[CONV3]] ; %conv1 = sitofp i8 %call to float %mul = fmul float %conv1, -3.000000e+00 @@ -155,11 +342,27 @@ define i32 @simple_negative(i8 %call) { } define i16 @simple_fneg(i8 %a) { -; CHECK-LABEL: @simple_fneg( -; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 -; CHECK-NEXT: [[T21:%.*]] = sub i32 0, [[TMP1]] -; CHECK-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i16 -; CHECK-NEXT: ret i16 [[TMP2]] +; NONE-LABEL: @simple_fneg( +; NONE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i32 +; NONE-NEXT: [[T21:%.*]] = sub i32 0, [[TMP1]] +; NONE-NEXT: [[TMP2:%.*]] = trunc i32 [[T21]] to i16 +; NONE-NEXT: ret i16 [[TMP2]] +; +; ONLY64-LABEL: @simple_fneg( +; ONLY64-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i64 +; ONLY64-NEXT: [[T21:%.*]] = sub i64 0, [[TMP1]] +; ONLY64-NEXT: [[TMP2:%.*]] = trunc i64 [[T21]] to i16 +; ONLY64-NEXT: ret i16 [[TMP2]] +; +; MULTIPLE-LABEL: @simple_fneg( +; MULTIPLE-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; MULTIPLE-NEXT: [[T21:%.*]] = sub i16 0, [[TMP1]] +; MULTIPLE-NEXT: ret i16 [[T21]] +; +; PR-79158-LABEL: @simple_fneg( +; PR-79158-NEXT: [[TMP1:%.*]] = zext i8 [[A:%.*]] to i16 +; PR-79158-NEXT: [[T21:%.*]] = sub i16 0, [[TMP1]] +; PR-79158-NEXT: ret i16 [[T21]] ; %t1 = uitofp i8 %a to float %t2 = fneg fast float %t1 diff --git a/llvm/test/Transforms/Float2Int/pr79158.ll b/llvm/test/Transforms/Float2Int/pr79158.ll new file mode 100644 index 0000000000000000000000000000000000000000..639a8ac9934f52d8e5a571082163fd352b3892fe --- /dev/null +++ b/llvm/test/Transforms/Float2Int/pr79158.ll @@ -0,0 +1,73 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt < %s -passes=float2int -S | FileCheck %s -check-prefixes=CHECK,NONE +; RUN: opt < %s -passes=float2int -S --data-layout="n64" | FileCheck %s -check-prefixes=CHECK,ONLY64 +; RUN: opt < %s -passes=float2int -S --data-layout="n8:16:32:64"| FileCheck %s -check-prefixes=CHECK,MULTIPLE +; RUN: opt < %s -passes=float2int -S --data-layout="e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"| FileCheck %s -check-prefixes=CHECK,PR-79158 + +define i32 @pr79158(i32 %x) { +; CHECK-LABEL: define i32 @pr79158( +; CHECK-SAME: i32 [[X:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], 0 +; CHECK-NEXT: [[TMP0:%.*]] = zext i1 [[CMP]] to i64 +; CHECK-NEXT: [[MUL1:%.*]] = mul i64 [[TMP0]], 4294967295 +; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[MUL1]] to i32 +; CHECK-NEXT: ret i32 [[TMP1]] +; +entry: + %cmp = icmp sgt i32 %x, 0 + %conv = uitofp i1 %cmp to double + %mul = fmul double %conv, 0x41EFFFFFFFE00000 + %conv1 = fptoui double %mul to i32 + ret i32 %conv1 +} + +define i32 @pr79158_2(i32 %x) { +; NONE-LABEL: define i32 @pr79158_2( +; NONE-SAME: i32 [[X:%.*]]) { +; NONE-NEXT: entry: +; NONE-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], 0 +; NONE-NEXT: [[TMP0:%.*]] = zext i1 [[CMP]] to i32 +; NONE-NEXT: [[MUL1:%.*]] = mul i32 [[TMP0]], 255 +; NONE-NEXT: [[TMP1:%.*]] = trunc i32 [[MUL1]] to i8 +; NONE-NEXT: [[CONV2:%.*]] = zext i8 [[TMP1]] to i32 +; NONE-NEXT: ret i32 [[CONV2]] +; +; ONLY64-LABEL: define i32 @pr79158_2( +; ONLY64-SAME: i32 [[X:%.*]]) { +; ONLY64-NEXT: entry: +; ONLY64-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], 0 +; ONLY64-NEXT: [[TMP0:%.*]] = zext i1 [[CMP]] to i64 +; ONLY64-NEXT: [[MUL1:%.*]] = mul i64 [[TMP0]], 255 +; ONLY64-NEXT: [[TMP1:%.*]] = trunc i64 [[MUL1]] to i8 +; ONLY64-NEXT: [[CONV2:%.*]] = zext i8 [[TMP1]] to i32 +; ONLY64-NEXT: ret i32 [[CONV2]] +; +; MULTIPLE-LABEL: define i32 @pr79158_2( +; MULTIPLE-SAME: i32 [[X:%.*]]) { +; MULTIPLE-NEXT: entry: +; MULTIPLE-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], 0 +; MULTIPLE-NEXT: [[TMP0:%.*]] = zext i1 [[CMP]] to i16 +; MULTIPLE-NEXT: [[MUL1:%.*]] = mul i16 [[TMP0]], 255 +; MULTIPLE-NEXT: [[TMP1:%.*]] = trunc i16 [[MUL1]] to i8 +; MULTIPLE-NEXT: [[CONV2:%.*]] = zext i8 [[TMP1]] to i32 +; MULTIPLE-NEXT: ret i32 [[CONV2]] +; +; PR-79158-LABEL: define i32 @pr79158_2( +; PR-79158-SAME: i32 [[X:%.*]]) { +; PR-79158-NEXT: entry: +; PR-79158-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], 0 +; PR-79158-NEXT: [[TMP0:%.*]] = zext i1 [[CMP]] to i16 +; PR-79158-NEXT: [[MUL1:%.*]] = mul i16 [[TMP0]], 255 +; PR-79158-NEXT: [[TMP1:%.*]] = trunc i16 [[MUL1]] to i8 +; PR-79158-NEXT: [[CONV2:%.*]] = zext i8 [[TMP1]] to i32 +; PR-79158-NEXT: ret i32 [[CONV2]] +; +entry: + %cmp = icmp sgt i32 %x, 0 + %conv = uitofp i1 %cmp to float + %mul = fmul float %conv, 2.550000e+02 + %conv1 = fptoui float %mul to i8 + %conv2 = zext i8 %conv1 to i32 + ret i32 %conv2 +} diff --git a/llvm/test/Transforms/FunctionAttrs/noundef.ll b/llvm/test/Transforms/FunctionAttrs/noundef.ll index 946b562f39553efe3df2292f64b9cff1ba437779..9ab37082a303293f84bd2ad5c5550c418fc56e15 100644 --- a/llvm/test/Transforms/FunctionAttrs/noundef.ll +++ b/llvm/test/Transforms/FunctionAttrs/noundef.ll @@ -1,6 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes='function-attrs' -S | FileCheck %s +@g_var = external global [0 x i8] + define i32 @test_ret_constant() { ; CHECK-LABEL: define noundef i32 @test_ret_constant( ; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { @@ -152,3 +154,15 @@ define i32 @test_ret_constant_msan() sanitize_memory { ; ret i32 0 } + +define i64 @test_trunc_with_constexpr() { +; CHECK-LABEL: define noundef i64 @test_trunc_with_constexpr( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: [[ADD:%.*]] = add i32 trunc (i64 sub (i64 0, i64 ptrtoint (ptr @g_var to i64)) to i32), 1 +; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[ADD]] to i64 +; CHECK-NEXT: ret i64 [[CONV]] +; + %add = add i32 trunc (i64 sub (i64 0, i64 ptrtoint (ptr @g_var to i64)) to i32), 1 + %conv = sext i32 %add to i64 + ret i64 %conv +} diff --git a/llvm/test/Transforms/GVNHoist/hoist-merge-geps.ll b/llvm/test/Transforms/GVNHoist/hoist-merge-geps.ll new file mode 100644 index 0000000000000000000000000000000000000000..b3b5916c7f26f2d65b305a9d92686044f2dce75f --- /dev/null +++ b/llvm/test/Transforms/GVNHoist/hoist-merge-geps.ll @@ -0,0 +1,63 @@ +; RUN: opt -S -passes=gvn-hoist < %s | FileCheck %s + +define dso_local void @func(i32 noundef %a, ptr noundef %b) !dbg !10 { +; Check the merged debug location of hoisted GEP +; CHECK: entry +; CHECK: %{{[a-zA-Z0-9_]*}} = getelementptr {{.*}} !dbg [[MERGED_DL:![0-9]+]] +; CHECK: [[MERGED_DL]] = !DILocation(line: 0, scope: !{{[0-9]+}}) +entry: + tail call void @llvm.dbg.value(metadata i32 %a, metadata !16, metadata !DIExpression()), !dbg !17 + tail call void @llvm.dbg.value(metadata ptr %b, metadata !18, metadata !DIExpression()), !dbg !17 + %tobool = icmp ne i32 %a, 0, !dbg !19 + br i1 %tobool, label %if.then, label %if.else, !dbg !21 + +if.then: ; preds = %entry + %arrayidx = getelementptr inbounds i32, ptr %b, i64 1, !dbg !22 + store i32 1, ptr %arrayidx, align 4, !dbg !24 + br label %if.end, !dbg !25 + +if.else: ; preds = %entry + %arrayidx1 = getelementptr inbounds i32, ptr %b, i64 1, !dbg !26 + store i32 1, ptr %arrayidx1, align 4, !dbg !28 + br label %if.end + +if.end: ; preds = %if.else, %if.then + ret void, !dbg !29 +} + +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 19.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "main.c", directory: "/root/llvm-test/GVNHoist") +!2 = !{i32 7, !"Dwarf Version", i32 5} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"PIE Level", i32 2} +!7 = !{i32 7, !"uwtable", i32 2} +!8 = !{i32 7, !"frame-pointer", i32 2} +!10 = distinct !DISubprogram(name: "func", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !15) +!11 = !DISubroutineType(types: !12) +!12 = !{null, !13, !14} +!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!14 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64) +!15 = !{} +!16 = !DILocalVariable(name: "a", arg: 1, scope: !10, file: !1, line: 1, type: !13) +!17 = !DILocation(line: 0, scope: !10) +!18 = !DILocalVariable(name: "b", arg: 2, scope: !10, file: !1, line: 1, type: !14) +!19 = !DILocation(line: 2, column: 9, scope: !20) +!20 = distinct !DILexicalBlock(scope: !10, file: !1, line: 2, column: 9) +!21 = !DILocation(line: 2, column: 9, scope: !10) +!22 = !DILocation(line: 3, column: 9, scope: !23) +!23 = distinct !DILexicalBlock(scope: !20, file: !1, line: 2, column: 12) +!24 = !DILocation(line: 3, column: 14, scope: !23) +!25 = !DILocation(line: 4, column: 5, scope: !23) +!26 = !DILocation(line: 5, column: 9, scope: !27) +!27 = distinct !DILexicalBlock(scope: !20, file: !1, line: 4, column: 12) +!28 = !DILocation(line: 5, column: 14, scope: !27) +!29 = !DILocation(line: 7, column: 1, scope: !10) diff --git a/llvm/test/Transforms/GlobalDCE/virtual-functions-base-call.ll b/llvm/test/Transforms/GlobalDCE/virtual-functions-base-call.ll index 8ef2d895a029066da3a2765a81abf1e7c77b6451..baf5c7272dfe333baf723fd9f3a54f82c44a3b8b 100644 --- a/llvm/test/Transforms/GlobalDCE/virtual-functions-base-call.ll +++ b/llvm/test/Transforms/GlobalDCE/virtual-functions-base-call.ll @@ -45,13 +45,13 @@ entry: define hidden void @_ZN1AC2Ev(ptr nocapture %this) { entry: - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } define hidden void @_ZN1BC2Ev(ptr nocapture %this) { entry: - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1B, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } diff --git a/llvm/test/Transforms/GlobalDCE/virtual-functions-base-pointer-call.ll b/llvm/test/Transforms/GlobalDCE/virtual-functions-base-pointer-call.ll index 09979690da6d8baf98bed0684ba72ad8702e70a5..47a80f843c93ee6926f34d0dfe2fb3d7bcd7d4e8 100644 --- a/llvm/test/Transforms/GlobalDCE/virtual-functions-base-pointer-call.ll +++ b/llvm/test/Transforms/GlobalDCE/virtual-functions-base-pointer-call.ll @@ -65,13 +65,13 @@ entry: define hidden void @_ZN1AC2Ev(ptr nocapture %this) { entry: - store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } define hidden void @_ZN1BC2Ev(ptr nocapture %this) { entry: - store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1B, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV1B, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } diff --git a/llvm/test/Transforms/GlobalDCE/virtual-functions-derived-call.ll b/llvm/test/Transforms/GlobalDCE/virtual-functions-derived-call.ll index 896675f7655f909f4d0516085ff5244cf46fd6f0..50b68254395603d43c5ad35ceccf68f311d998ef 100644 --- a/llvm/test/Transforms/GlobalDCE/virtual-functions-derived-call.ll +++ b/llvm/test/Transforms/GlobalDCE/virtual-functions-derived-call.ll @@ -45,13 +45,13 @@ entry: define hidden void @_ZN1AC2Ev(ptr nocapture %this) { entry: - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } define hidden void @_ZN1BC2Ev(ptr nocapture %this) { entry: - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1B, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } diff --git a/llvm/test/Transforms/GlobalDCE/virtual-functions-derived-pointer-call.ll b/llvm/test/Transforms/GlobalDCE/virtual-functions-derived-pointer-call.ll index bdf97d25ac3f1df6182cf4b0e723d3a3cf63f779..e5dea7ad9a81c3d79a56811295fe148f17769b67 100644 --- a/llvm/test/Transforms/GlobalDCE/virtual-functions-derived-pointer-call.ll +++ b/llvm/test/Transforms/GlobalDCE/virtual-functions-derived-pointer-call.ll @@ -67,13 +67,13 @@ entry: define hidden void @_ZN1AC2Ev(ptr nocapture %this) { entry: - store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } define hidden void @_ZN1BC2Ev(ptr nocapture %this) { entry: - store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1B, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV1B, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } diff --git a/llvm/test/Transforms/GlobalDCE/virtual-functions-novfe.ll b/llvm/test/Transforms/GlobalDCE/virtual-functions-novfe.ll index 01475c8911fc2dc14b66becacb0e27add3196f07..04f654c5e0b989e5f42344768d88c9ec62a629a2 100644 --- a/llvm/test/Transforms/GlobalDCE/virtual-functions-novfe.ll +++ b/llvm/test/Transforms/GlobalDCE/virtual-functions-novfe.ll @@ -39,8 +39,8 @@ entry: define dso_local i32 @test_A() { entry: %call = tail call ptr @_Znwm(i64 8) - store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %call, align 8 - %0 = tail call { ptr, i1 } @llvm.type.checked.load(ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), i32 0, metadata !"_ZTS1A"), !nosanitize !9 + store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %call, align 8 + %0 = tail call { ptr, i1 } @llvm.type.checked.load(ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), i32 0, metadata !"_ZTS1A"), !nosanitize !9 %1 = extractvalue { ptr, i1 } %0, 0, !nosanitize !9 %call1 = tail call i32 %1(ptr nonnull %call) ret i32 %call1 diff --git a/llvm/test/Transforms/GlobalDCE/virtual-functions-visibility-post-lto.ll b/llvm/test/Transforms/GlobalDCE/virtual-functions-visibility-post-lto.ll index 0fac0fbca109927f7d4d039351b5b660805e0fdd..dde36d46f6b976e5ba0c9181d6f8a7177c4134f0 100644 --- a/llvm/test/Transforms/GlobalDCE/virtual-functions-visibility-post-lto.ll +++ b/llvm/test/Transforms/GlobalDCE/virtual-functions-visibility-post-lto.ll @@ -18,7 +18,7 @@ target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" define internal void @_ZN1AC2Ev(ptr %this) { entry: - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } @@ -43,7 +43,7 @@ entry: define internal void @_ZN1BC2Ev(ptr %this) { entry: - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1B, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } @@ -68,7 +68,7 @@ entry: define internal void @_ZN1CC2Ev(ptr %this) { entry: - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1C, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1C, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } diff --git a/llvm/test/Transforms/GlobalDCE/virtual-functions-visibility-pre-lto.ll b/llvm/test/Transforms/GlobalDCE/virtual-functions-visibility-pre-lto.ll index 7875d38c8c0b1752c6c5b2e913876e7a98cb66da..ac9c362e1fd6811f73dcaf347d47cf4a88cf67d7 100644 --- a/llvm/test/Transforms/GlobalDCE/virtual-functions-visibility-pre-lto.ll +++ b/llvm/test/Transforms/GlobalDCE/virtual-functions-visibility-pre-lto.ll @@ -12,7 +12,7 @@ target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" define internal void @_ZN1AC2Ev(ptr %this) { entry: - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } @@ -36,7 +36,7 @@ entry: define internal void @_ZN1BC2Ev(ptr %this) { entry: - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1B, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } @@ -60,7 +60,7 @@ entry: define internal void @_ZN1CC2Ev(ptr %this) { entry: - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1C, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1C, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } diff --git a/llvm/test/Transforms/GlobalDCE/virtual-functions.ll b/llvm/test/Transforms/GlobalDCE/virtual-functions.ll index e00f8a7fdfecde4d00abecded5a52aafc21f09c5..0d9b51ca8c5f68ce26f13676a52a24a6ba9306b1 100644 --- a/llvm/test/Transforms/GlobalDCE/virtual-functions.ll +++ b/llvm/test/Transforms/GlobalDCE/virtual-functions.ll @@ -38,8 +38,8 @@ entry: define dso_local i32 @test_A() { entry: %call = tail call ptr @_Znwm(i64 8) - store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %call, align 8 - %0 = tail call { ptr, i1 } @llvm.type.checked.load(ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), i32 0, metadata !"_ZTS1A"), !nosanitize !9 + store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %call, align 8 + %0 = tail call { ptr, i1 } @llvm.type.checked.load(ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), i32 0, metadata !"_ZTS1A"), !nosanitize !9 %1 = extractvalue { ptr, i1 } %0, 0, !nosanitize !9 %call1 = tail call i32 %1(ptr nonnull %call) ret i32 %call1 diff --git a/llvm/test/Transforms/GlobalDCE/vtable-rtti.ll b/llvm/test/Transforms/GlobalDCE/vtable-rtti.ll index 2eb761e8ab1af040b2a2a7cd1f2f0975318ff4fb..c4a45ffaf63a8077c2fd110c46aa92d5c771a246 100644 --- a/llvm/test/Transforms/GlobalDCE/vtable-rtti.ll +++ b/llvm/test/Transforms/GlobalDCE/vtable-rtti.ll @@ -16,7 +16,7 @@ target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" define internal void @_ZN1AC2Ev(ptr %this) { entry: - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } diff --git a/llvm/test/Transforms/GlobalOpt/inalloca-varargs.ll b/llvm/test/Transforms/GlobalOpt/inalloca-varargs.ll index 188210782edd981f8262199d71c43a45b6926e9c..4c5a448d12c482b694143438e2cba566c065dd04 100644 --- a/llvm/test/Transforms/GlobalOpt/inalloca-varargs.ll +++ b/llvm/test/Transforms/GlobalOpt/inalloca-varargs.ll @@ -23,7 +23,7 @@ define internal i32 @i(ptr inalloca(ptr) %a, ...) { ; CHECK-LABEL: define {{[^@]+}}@i ; CHECK-SAME: (ptr inalloca(ptr) [[A:%.*]], ...) unnamed_addr { ; CHECK-NEXT: [[AP:%.*]] = alloca ptr, align 4 -; CHECK-NEXT: call void @llvm.va_start(ptr [[AP]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr [[AP]]) ; CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[AP]], align 4 ; CHECK-NEXT: [[L:%.*]] = load i32, ptr [[ARGP_CUR]], align 4 ; CHECK-NEXT: ret i32 [[L]] diff --git a/llvm/test/Transforms/GlobalSplit/basic.ll b/llvm/test/Transforms/GlobalSplit/basic.ll index c47bdd64e02f511f0914d097a0cb6d1f713e260c..eb1515741763cfa1dcb75d98e4921aa179220d22 100644 --- a/llvm/test/Transforms/GlobalSplit/basic.ll +++ b/llvm/test/Transforms/GlobalSplit/basic.ll @@ -3,11 +3,11 @@ target datalayout = "e-p:64:64" target triple = "x86_64-unknown-linux-gnu" -; CHECK: @vtt = constant [3 x ptr] [ptr @global.0, ptr getelementptr inbounds ([2 x ptr], ptr @global.0, i32 0, i32 1), ptr @global.1] +; CHECK: @vtt = constant [3 x ptr] [ptr @global.0, ptr getelementptr inbounds (i8, ptr @global.0, i64 8), ptr @global.1] @vtt = constant [3 x ptr] [ - ptr getelementptr ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, inrange i32 0, i32 0), - ptr getelementptr ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, inrange i32 0, i32 1), - ptr getelementptr ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, inrange i32 1, i32 0) + ptr getelementptr inrange(0, 16) ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, i32 0, i32 0), + ptr getelementptr inrange(-8, 8) ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, i32 0, i32 1), + ptr getelementptr inrange(0, 8) ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, i32 1, i32 0) ] ; CHECK-NOT: @global = @@ -22,25 +22,25 @@ target triple = "x86_64-unknown-linux-gnu" ; CHECK: define ptr @f1() define ptr @f1() { ; CHECK-NEXT: ret ptr @global.0 - ret ptr getelementptr ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, inrange i32 0, i32 0) + ret ptr getelementptr inrange(0, 16) ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, i32 0, i32 0) } ; CHECK: define ptr @f2() define ptr @f2() { - ; CHECK-NEXT: ret ptr getelementptr inbounds ([2 x ptr], ptr @global.0, i32 0, i32 1) - ret ptr getelementptr ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, inrange i32 0, i32 1) + ; CHECK-NEXT: ret ptr getelementptr inbounds (i8, ptr @global.0, i64 8) + ret ptr getelementptr inrange(-8, 8) ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, i32 0, i32 1) } ; CHECK: define ptr @f3() define ptr @f3() { - ; CHECK-NEXT: ret ptr getelementptr inbounds ([2 x ptr], ptr @global.0, i64 1, i32 0) - ret ptr getelementptr ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, inrange i32 0, i32 2) + ; CHECK-NEXT: ret ptr getelementptr (i8, ptr @global.0, i64 16) + ret ptr getelementptr inrange(-16, 0) ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, i32 0, i32 2) } ; CHECK: define ptr @f4() define ptr @f4() { ; CHECK-NEXT: ret ptr @global.1 - ret ptr getelementptr ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, inrange i32 1, i32 0) + ret ptr getelementptr inrange(0, 8) ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, i32 1, i32 0) } define void @foo() { diff --git a/llvm/test/Transforms/GlobalSplit/non-beneficial.ll b/llvm/test/Transforms/GlobalSplit/non-beneficial.ll index a7c50c985c907ad47a4716b8a25a2d46a4bdce5e..5e27623dd6e9c78e66671c453154983e0f01a22f 100644 --- a/llvm/test/Transforms/GlobalSplit/non-beneficial.ll +++ b/llvm/test/Transforms/GlobalSplit/non-beneficial.ll @@ -10,7 +10,7 @@ target triple = "x86_64-unknown-linux-gnu" } define ptr @f() { - ret ptr getelementptr ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, inrange i32 0, i32 0) + ret ptr getelementptr inrange(0, 16) ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, i32 0, i32 0) } define ptr @g() { diff --git a/llvm/test/Transforms/GlobalSplit/nonlocal.ll b/llvm/test/Transforms/GlobalSplit/nonlocal.ll index 38169a8bea479f9024e4572a856f2e766e021b6d..0e639135feb61dc54f54aa31800c3619e704328e 100644 --- a/llvm/test/Transforms/GlobalSplit/nonlocal.ll +++ b/llvm/test/Transforms/GlobalSplit/nonlocal.ll @@ -10,7 +10,7 @@ target triple = "x86_64-unknown-linux-gnu" } define ptr @f() { - ret ptr getelementptr ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, inrange i32 0, i32 0) + ret ptr getelementptr inrange(0, 16) ({ [2 x ptr], [1 x ptr] }, ptr @global, i32 0, i32 0, i32 0) } define ptr @g() { diff --git a/llvm/test/Transforms/HotColdSplit/outline-disjoint-diamonds.ll b/llvm/test/Transforms/HotColdSplit/outline-disjoint-diamonds.ll index 0c055981260b2b2e142513ed1781d7bfcab290c0..55013aa96551d0d1c8761f1b13e5b43eca193886 100644 --- a/llvm/test/Transforms/HotColdSplit/outline-disjoint-diamonds.ll +++ b/llvm/test/Transforms/HotColdSplit/outline-disjoint-diamonds.ll @@ -2,9 +2,9 @@ ; CHECK-LABEL: define {{.*}}@fun ; CHECK: call {{.*}}@fun.cold.1( -; CHECK-NEXT: ret void +; CHECK-NEXT: unreachable ; CHECK: call {{.*}}@fun.cold.2( -; CHECK-NEXT: ret void +; CHECK-NEXT: unreachable define void @fun() { entry: br i1 undef, label %A.then, label %A.else diff --git a/llvm/test/Transforms/IRCE/compound-loop-bound.ll b/llvm/test/Transforms/IRCE/compound-loop-bound.ll index 0930d19e22154fc00cd709f1646b4abe2743e9b9..e50d8c6127f40112519b56b03c44a7ad4b265120 100644 --- a/llvm/test/Transforms/IRCE/compound-loop-bound.ll +++ b/llvm/test/Transforms/IRCE/compound-loop-bound.ll @@ -16,23 +16,56 @@ define void @incrementing_loop(ptr %arr, ptr %len_ptr, i32 %K, i32 %M) { ; CHECK-NEXT: br i1 [[AND]], label [[PREHEADER:%.*]], label [[EXIT:%.*]] ; CHECK: preheader: ; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[K]], i32 [[M]]) +; CHECK-NEXT: [[SMIN1:%.*]] = call i32 @llvm.smin.i32(i32 [[LEN]], i32 [[M]]) +; CHECK-NEXT: [[SMIN2:%.*]] = call i32 @llvm.smin.i32(i32 [[SMIN1]], i32 [[K]]) +; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN2]], i32 0) +; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]] +; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] +; CHECK: loop.preheader: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ] -; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1 +; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] +; CHECK-NEXT: [[IDX_NEXT]] = add nsw i32 [[IDX]], 1 ; CHECK-NEXT: [[GUARD:%.*]] = icmp slt i32 [[IDX]], [[LEN]] -; CHECK-NEXT: br i1 [[GUARD]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]] +; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT3:%.*]] ; CHECK: in.bounds: ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]] ; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4 ; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], [[SMIN]] -; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] +; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] +; CHECK: main.exit.selector: +; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ] +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], [[SMIN]] +; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]] +; CHECK: main.pseudo.exit: +; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] +; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] +; CHECK-NEXT: br label [[POSTLOOP:%.*]] +; CHECK: out.of.bounds.loopexit: +; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] +; CHECK: out.of.bounds.loopexit3: +; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] ; CHECK: out.of.bounds: ; CHECK-NEXT: ret void +; CHECK: exit.loopexit.loopexit: +; CHECK-NEXT: br label [[EXIT_LOOPEXIT]] ; CHECK: exit.loopexit: ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: ret void +; CHECK: postloop: +; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]] +; CHECK: loop.postloop: +; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ] +; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 1 +; CHECK-NEXT: [[GUARD_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[LEN]] +; CHECK-NEXT: br i1 [[GUARD_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] +; CHECK: in.bounds.postloop: +; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]] +; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 4 +; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], [[SMIN]] +; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP1:![0-9]+]], !loop_constrainer.loop.clone !6 ; entry: %len = load i32, ptr %len_ptr, !range !0 @@ -78,24 +111,58 @@ define void @decrementing_loop(ptr %arr, ptr %len_ptr, i32 %K, i32 %M) { ; CHECK-NEXT: [[AND:%.*]] = and i1 [[CHECK0]], [[CHECK1]] ; CHECK-NEXT: br i1 [[AND]], label [[PREHEADER:%.*]], label [[EXIT:%.*]] ; CHECK: preheader: -; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[K]], i32 [[M]]) +; CHECK-NEXT: [[INDVAR_START:%.*]] = call i32 @llvm.smin.i32(i32 [[K]], i32 [[M]]) +; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDVAR_START]], 1 +; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[LEN]], i32 [[TMP0]]) +; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN]], i32 0) +; CHECK-NEXT: [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[SMAX]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[INDVAR_START]], [[EXIT_PRELOOP_AT]] +; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]] +; CHECK: loop.preloop.preheader: +; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]] +; CHECK: mainloop: ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[SMIN]], [[PREHEADER]] ], [ [[IDX_DEC:%.*]], [[IN_BOUNDS:%.*]] ] -; CHECK-NEXT: [[IDX_DEC]] = sub i32 [[IDX]], 1 +; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_DEC:%.*]], [[IN_BOUNDS:%.*]] ] +; CHECK-NEXT: [[IDX_DEC]] = sub nsw i32 [[IDX]], 1 ; CHECK-NEXT: [[GUARD:%.*]] = icmp slt i32 [[IDX]], [[LEN]] -; CHECK-NEXT: br i1 [[GUARD]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]] +; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]] ; CHECK: in.bounds: ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]] ; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4 ; CHECK-NEXT: [[NEXT:%.*]] = icmp sgt i32 [[IDX_DEC]], -1 -; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] +; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] +; CHECK: out.of.bounds.loopexit: +; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] +; CHECK: out.of.bounds.loopexit1: +; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] ; CHECK: out.of.bounds: ; CHECK-NEXT: ret void +; CHECK: exit.loopexit.loopexit: +; CHECK-NEXT: br label [[EXIT_LOOPEXIT:%.*]] ; CHECK: exit.loopexit: ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: ret void +; CHECK: loop.preloop: +; CHECK-NEXT: [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_DEC_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ [[INDVAR_START]], [[LOOP_PRELOOP_PREHEADER]] ] +; CHECK-NEXT: [[IDX_DEC_PRELOOP]] = sub i32 [[IDX_PRELOOP]], 1 +; CHECK-NEXT: [[GUARD_PRELOOP:%.*]] = icmp slt i32 [[IDX_PRELOOP]], [[LEN]] +; CHECK-NEXT: br i1 [[GUARD_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] +; CHECK: in.bounds.preloop: +; CHECK-NEXT: [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]] +; CHECK-NEXT: store i32 0, ptr [[ADDR_PRELOOP]], align 4 +; CHECK-NEXT: [[NEXT_PRELOOP:%.*]] = icmp sgt i32 [[IDX_DEC_PRELOOP]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[IDX_DEC_PRELOOP]], [[EXIT_PRELOOP_AT]] +; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP7:![0-9]+]], !loop_constrainer.loop.clone !6 +; CHECK: preloop.exit.selector: +; CHECK-NEXT: [[IDX_DEC_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_DEC_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ] +; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[IDX_DEC_PRELOOP_LCSSA]], -1 +; CHECK-NEXT: br i1 [[TMP3]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT]] +; CHECK: preloop.pseudo.exit: +; CHECK-NEXT: [[IDX_PRELOOP_COPY]] = phi i32 [ [[INDVAR_START]], [[PREHEADER]] ], [ [[IDX_DEC_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ] +; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ [[INDVAR_START]], [[PREHEADER]] ], [ [[IDX_DEC_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ] +; CHECK-NEXT: br label [[MAINLOOP]] ; entry: %len = load i32, ptr %len_ptr, !range !0 diff --git a/llvm/test/Transforms/IROutliner/illegal-vaarg.ll b/llvm/test/Transforms/IROutliner/illegal-vaarg.ll index ef365d6eaddb5b4c6eb49acd28de6480b10a2a73..38dfd25e039e6d7e29bd31ca1049fdebfd2ae372 100644 --- a/llvm/test/Transforms/IROutliner/illegal-vaarg.ll +++ b/llvm/test/Transforms/IROutliner/illegal-vaarg.ll @@ -17,10 +17,10 @@ define i32 @func1(i32 %a, double %b, ptr %v, ...) nounwind { ; CHECK-NEXT: [[AP:%.*]] = alloca ptr, align 4 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4 ; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[A:%.*]], ptr [[A_ADDR]], double [[B:%.*]], ptr [[B_ADDR]]) -; CHECK-NEXT: call void @llvm.va_start(ptr [[AP]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr [[AP]]) ; CHECK-NEXT: [[TMP0:%.*]] = va_arg ptr [[AP]], i32 -; CHECK-NEXT: call void @llvm.va_copy(ptr [[V:%.*]], ptr [[AP]]) -; CHECK-NEXT: call void @llvm.va_end(ptr [[AP]]) +; CHECK-NEXT: call void @llvm.va_copy.p0(ptr [[V:%.*]], ptr [[AP]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr [[AP]]) ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 -1, ptr [[TMP_LOC]]) ; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[TMP0]], ptr [[C]], ptr [[TMP_LOC]]) ; CHECK-NEXT: [[TMP_RELOAD:%.*]] = load i32, ptr [[TMP_LOC]], align 4 @@ -52,10 +52,10 @@ define i32 @func2(i32 %a, double %b, ptr %v, ...) nounwind { ; CHECK-NEXT: [[AP:%.*]] = alloca ptr, align 4 ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4 ; CHECK-NEXT: call void @outlined_ir_func_0(i32 [[A:%.*]], ptr [[A_ADDR]], double [[B:%.*]], ptr [[B_ADDR]]) -; CHECK-NEXT: call void @llvm.va_start(ptr [[AP]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr [[AP]]) ; CHECK-NEXT: [[TMP0:%.*]] = va_arg ptr [[AP]], i32 -; CHECK-NEXT: call void @llvm.va_copy(ptr [[V:%.*]], ptr [[AP]]) -; CHECK-NEXT: call void @llvm.va_end(ptr [[AP]]) +; CHECK-NEXT: call void @llvm.va_copy.p0(ptr [[V:%.*]], ptr [[AP]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr [[AP]]) ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 -1, ptr [[TMP_LOC]]) ; CHECK-NEXT: call void @outlined_ir_func_1(i32 [[TMP0]], ptr [[C]], ptr [[TMP_LOC]]) ; CHECK-NEXT: [[TMP_RELOAD:%.*]] = load i32, ptr [[TMP_LOC]], align 4 diff --git a/llvm/test/Transforms/IROutliner/outline-vaarg-intrinsic.ll b/llvm/test/Transforms/IROutliner/outline-vaarg-intrinsic.ll index 9f565de960575b80b5364f13ffa52e44f1dded95..2d526086fae49c0d868d4c38b38355e1c601d17a 100644 --- a/llvm/test/Transforms/IROutliner/outline-vaarg-intrinsic.ll +++ b/llvm/test/Transforms/IROutliner/outline-vaarg-intrinsic.ll @@ -51,7 +51,7 @@ entry: ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4 ; CHECK-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 ; CHECK-NEXT: store double [[B]], ptr [[B_ADDR]], align 8 -; CHECK-NEXT: call void @llvm.va_start(ptr [[AP]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr [[AP]]) ; CHECK-NEXT: [[TMP0:%.*]] = va_arg ptr [[AP]], i32 ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 -1, ptr [[TMP_LOC]]) ; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[V]], ptr [[AP]], i32 [[TMP0]], ptr [[C]], ptr [[TMP_LOC]]) @@ -70,7 +70,7 @@ entry: ; CHECK-NEXT: [[C:%.*]] = alloca i32, align 4 ; CHECK-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4 ; CHECK-NEXT: store double [[B]], ptr [[B_ADDR]], align 8 -; CHECK-NEXT: call void @llvm.va_start(ptr [[AP]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr [[AP]]) ; CHECK-NEXT: [[TMP0:%.*]] = va_arg ptr [[AP]], i32 ; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 -1, ptr [[TMP_LOC]]) ; CHECK-NEXT: call void @outlined_ir_func_0(ptr [[V]], ptr [[AP]], i32 [[TMP0]], ptr [[C]], ptr [[TMP_LOC]]) @@ -84,8 +84,8 @@ entry: ; CHECK-NEXT: newFuncRoot: ; CHECK-NEXT: br label [[ENTRY_TO_OUTLINE:%.*]] ; CHECK: entry_to_outline: -; CHECK-NEXT: call void @llvm.va_copy(ptr [[TMP0]], ptr [[TMP1]]) -; CHECK-NEXT: call void @llvm.va_end(ptr [[TMP1]]) +; CHECK-NEXT: call void @llvm.va_copy.p0(ptr [[TMP0]], ptr [[TMP1]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr [[TMP1]]) ; CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP3]], align 4 ; CHECK-NEXT: [[TMP:%.*]] = load i32, ptr [[TMP3]], align 4 ; CHECK-NEXT: br label [[ENTRY_AFTER_OUTLINE_EXITSTUB:%.*]] diff --git a/llvm/test/Transforms/IROutliner/outlining-no-return-functions.ll b/llvm/test/Transforms/IROutliner/outlining-no-return-functions.ll index 6b12207a32dff8f47e3ca7d94a2853a489e31491..d2c41376f6b2c8eeeab9a766f40e2b05d53520e6 100644 --- a/llvm/test/Transforms/IROutliner/outlining-no-return-functions.ll +++ b/llvm/test/Transforms/IROutliner/outlining-no-return-functions.ll @@ -29,19 +29,19 @@ bb1: ; CHECK-LABEL: @f1( ; CHECK-NEXT: bb: ; CHECK-NEXT: call void @outlined_ir_func_0() -; CHECK-NEXT: ret void +; CHECK-NEXT: unreachable ; ; ; CHECK-LABEL: @f2( ; CHECK-NEXT: bb: ; CHECK-NEXT: call void @outlined_ir_func_0() -; CHECK-NEXT: ret void +; CHECK-NEXT: unreachable ; ; ; CHECK-LABEL: @f3( ; CHECK-NEXT: bb: ; CHECK-NEXT: call void @outlined_ir_func_0() -; CHECK-NEXT: ret void +; CHECK-NEXT: unreachable ; ; ; CHECK-LABEL: define internal void @outlined_ir_func_0( diff --git a/llvm/test/Transforms/IndVarSimplify/iv-widen-elim-ext.ll b/llvm/test/Transforms/IndVarSimplify/iv-widen-elim-ext.ll index 0e21bf8ba347a8044e655bb1a57a73d60d385dc0..59a0241bfe9fdeb9526af349f7b95c2db83698c3 100644 --- a/llvm/test/Transforms/IndVarSimplify/iv-widen-elim-ext.ll +++ b/llvm/test/Transforms/IndVarSimplify/iv-widen-elim-ext.ll @@ -493,3 +493,55 @@ for.body: ; preds = %for.body.lr.ph, %fo %cmp = icmp ult i32 %add, %length br i1 %cmp, label %for.body, label %for.cond.cleanup.loopexit } + +; Test that we can handle shl and disjoint or in getExtendedOperandRecurrence. +define void @foo7(i32 %n, ptr %a, i32 %x) { +; CHECK-LABEL: @foo7( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_LR_PH:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.lr.ph: +; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[X:%.*]], 2 +; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[ADD1]] to i64 +; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[N]] to i64 +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: ret void +; CHECK: for.body: +; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_LR_PH]] ] +; CHECK-NEXT: [[TMP2:%.*]] = shl nsw i64 [[INDVARS_IV]], 1 +; CHECK-NEXT: [[TMP3:%.*]] = or disjoint i64 [[TMP2]], 1 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = trunc i64 [[INDVARS_IV]] to i32 +; CHECK-NEXT: store i32 [[TMP4]], ptr [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], [[TMP0]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT]], [[TMP1]] +; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] +; +entry: + %cmp6 = icmp sgt i32 %n, 0 + br i1 %cmp6, label %for.body.lr.ph, label %for.cond.cleanup + +for.body.lr.ph: ; preds = %entry + %add1 = add nsw i32 %x, 2 + br label %for.body + +for.cond.cleanup.loopexit: ; preds = %for.body + br label %for.cond.cleanup + +for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit, %entry + ret void + +for.body: ; preds = %for.body.lr.ph, %for.body + %i.07 = phi i32 [ 0, %for.body.lr.ph ], [ %add2, %for.body ] + %mul = shl nsw i32 %i.07, 1 + %add = or disjoint i32 %mul, 1 + %idxprom = sext i32 %add to i64 + %arrayidx = getelementptr inbounds i32, ptr %a, i64 %idxprom + store i32 %i.07, ptr %arrayidx, align 4 + %add2 = add nsw i32 %add1, %i.07 + %cmp = icmp slt i32 %add2, %n + br i1 %cmp, label %for.body, label %for.cond.cleanup.loopexit +} diff --git a/llvm/test/Transforms/Inline/RISCV/inline-target-features.ll b/llvm/test/Transforms/Inline/RISCV/inline-target-features.ll new file mode 100644 index 0000000000000000000000000000000000000000..b626a229a737d5bdcfd09fa544a115b24fd86e41 --- /dev/null +++ b/llvm/test/Transforms/Inline/RISCV/inline-target-features.ll @@ -0,0 +1,34 @@ +; RUN: opt < %s -mtriple=riscv64-unknown-linux-gnu -S -passes=inline | FileCheck %s +; RUN: opt < %s -mtriple=riscv64-unknown-linux-gnu -S -passes='cgscc(inline)' | FileCheck %s +; Check that we only inline when we have compatible target attributes. + +target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128" +target triple = "riscv64-unknown-linux-gnu" + +define i32 @foo() #0 { +entry: + %call = call i32 (...) @baz() + ret i32 %call +; CHECK-LABEL: foo +; CHECK: call i32 (...) @baz() +} +declare i32 @baz(...) #0 + +define i32 @bar() #1 { +entry: + %call = call i32 @foo() + ret i32 %call +; CHECK-LABEL: bar +; CHECK: call i32 (...) @baz() +} + +define i32 @qux() #0 { +entry: + %call = call i32 @bar() + ret i32 %call +; CHECK-LABEL: qux +; CHECK: call i32 @bar() +} + +attributes #0 = { "target-cpu"="generic-rv64" "target-features"="+f,+d" } +attributes #1 = { "target-cpu"="generic-rv64" "target-features"="+f,+d,+m,+v" } diff --git a/llvm/test/Transforms/Inline/RISCV/lit.local.cfg b/llvm/test/Transforms/Inline/RISCV/lit.local.cfg new file mode 100644 index 0000000000000000000000000000000000000000..17351748513d988dafcd023797140940f95beb91 --- /dev/null +++ b/llvm/test/Transforms/Inline/RISCV/lit.local.cfg @@ -0,0 +1,2 @@ +if not "RISCV" in config.root.targets: + config.unsupported = True diff --git a/llvm/test/Transforms/Inline/devirtualize-4.ll b/llvm/test/Transforms/Inline/devirtualize-4.ll index fae364313ea028d29c77fd49a61403025658860a..d29360f73b4739e389ba8ebfd12b08b4ee74d7d3 100644 --- a/llvm/test/Transforms/Inline/devirtualize-4.ll +++ b/llvm/test/Transforms/Inline/devirtualize-4.ll @@ -60,7 +60,7 @@ declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) define linkonce_odr dso_local void @_ZN4ImplC2Ev(ptr %this) unnamed_addr align 2 { entry: call void @_ZN9InterfaceC2Ev(ptr %this) - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV4Impl, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV4Impl, i64 0, i32 0, i64 2), ptr %this, align 8 %f = getelementptr inbounds %class.Impl, ptr %this, i64 0, i32 1 store i32 3, ptr %f, align 8 ret void @@ -78,7 +78,7 @@ declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) define linkonce_odr dso_local void @_ZN9InterfaceC2Ev(ptr %this) unnamed_addr align 2 { entry: - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV9Interface, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV9Interface, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } @@ -185,7 +185,7 @@ entry: define linkonce_odr void @_ZN1AC2Ev(ptr %this) align 2 { entry: - store ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, inrange i32 0, i64 2), ptr %this, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [4 x ptr] }, ptr @_ZTV1A, i64 0, i32 0, i64 2), ptr %this, align 8 ret void } diff --git a/llvm/test/Transforms/Inline/update_invoke_prof.ll b/llvm/test/Transforms/Inline/update_invoke_prof.ll new file mode 100644 index 0000000000000000000000000000000000000000..5f09c7cf8fe0952367f6cb5b7d4b64c5a5a92242 --- /dev/null +++ b/llvm/test/Transforms/Inline/update_invoke_prof.ll @@ -0,0 +1,64 @@ +; A pre-commit test to show that branch weights and value profiles associated with invoke are not updated. +; RUN: opt < %s -passes='require<profile-summary>,cgscc(inline)' -S | FileCheck %s + +declare i32 @__gxx_personality_v0(...) + +define void @caller(ptr %func) personality ptr @__gxx_personality_v0 !prof !15 { + call void @callee(ptr %func), !prof !16 + ret void +} + +declare void @inner_callee(ptr %func) + +define void @callee(ptr %func) personality ptr @__gxx_personality_v0 !prof !17 { + invoke void %func() + to label %next unwind label %lpad, !prof !18 + +next: + invoke void @inner_callee(ptr %func) + to label %ret unwind label %lpad, !prof !19 + +lpad: + %exn = landingpad {ptr, i32} + cleanup + unreachable + +ret: + ret void +} + +!llvm.module.flags = !{!1} +!1 = !{i32 1, !"ProfileSummary", !2} +!2 = !{!3, !4, !5, !6, !7, !8, !9, !10} +!3 = !{!"ProfileFormat", !"SampleProfile"} +!4 = !{!"TotalCount", i64 10000} +!5 = !{!"MaxCount", i64 10} +!6 = !{!"MaxInternalCount", i64 1} +!7 = !{!"MaxFunctionCount", i64 2000} +!8 = !{!"NumCounts", i64 2} +!9 = !{!"NumFunctions", i64 2} +!10 = !{!"DetailedSummary", !11} +!11 = !{!12, !13, !14} +!12 = !{i32 10000, i64 100, i32 1} +!13 = !{i32 999000, i64 100, i32 1} +!14 = !{i32 999999, i64 1, i32 2} +!15 = !{!"function_entry_count", i64 1000} +!16 = !{!"branch_weights", i64 1000} +!17 = !{!"function_entry_count", i32 1500} +!18 = !{!"VP", i32 0, i64 1500, i64 123, i64 900, i64 456, i64 600} +!19 = !{!"branch_weights", i32 1500} + +; CHECK-LABEL: @caller( +; CHECK: invoke void %func( +; CHECK-NEXT: {{.*}} !prof ![[PROF1:[0-9]+]] +; CHECK: invoke void @inner_callee( +; CHECK-NEXT: {{.*}} !prof ![[PROF2:[0-9]+]] + +; CHECK-LABL: @callee( +; CHECK: invoke void %func( +; CHECK-NEXT: {{.*}} !prof ![[PROF1]] +; CHECK: invoke void @inner_callee( +; CHECK-NEXT: {{.*}} !prof ![[PROF2]] + +; CHECK: ![[PROF1]] = !{!"VP", i32 0, i64 1500, i64 123, i64 900, i64 456, i64 600} +; CHECK: ![[PROF2]] = !{!"branch_weights", i32 1500} diff --git a/llvm/test/Transforms/Inline/update_value_profile.ll b/llvm/test/Transforms/Inline/update_value_profile.ll new file mode 100644 index 0000000000000000000000000000000000000000..daa95e93b68ec52ddd63d58c85295ba08cc4d1f8 --- /dev/null +++ b/llvm/test/Transforms/Inline/update_value_profile.ll @@ -0,0 +1,81 @@ +; RUN: opt < %s -passes='require<profile-summary>,cgscc(inline)' -inline-threshold=100 -S | FileCheck %s +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; When 'callee' is inlined into caller1 and caller2, the indirect call value +; profiles of the inlined copy should be scaled based on callers' profiles, +; and the indirect call value profiles in 'callee' should be updated. +define i32 @callee(ptr %0, i32 %1) !prof !20 { +; CHECK-LABEL: define i32 @callee( +; CHECK-SAME: ptr [[TMP0:%.*]], i32 [[TMP1:%.*]]) !prof [[PROF0:![0-9]+]] { +; CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP0]], align 8 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 8 +; CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 +; CHECK-NEXT: [[TMP6:%.*]] = tail call i32 [[TMP5]](ptr [[TMP0]], i32 [[TMP1]]), !prof [[PROF1:![0-9]+]] +; CHECK-NEXT: ret i32 [[TMP6]] +; + %3 = load ptr, ptr %0 + %5 = getelementptr inbounds i8, ptr %3, i64 8 + %6 = load ptr, ptr %5 + %7 = tail call i32 %6(ptr %0, i32 %1), !prof !17 + ret i32 %7 +} + +define i32 @caller1(i32 %0) !prof !18 { +; CHECK-LABEL: define i32 @caller1( +; CHECK-SAME: i32 [[TMP0:%.*]]) !prof [[PROF2:![0-9]+]] { +; CHECK-NEXT: [[TMP2:%.*]] = tail call ptr @_Z10createTypei(i32 [[TMP0]]) +; CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP2]], align 8 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 8 +; CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 +; CHECK-NEXT: [[TMP6:%.*]] = tail call i32 [[TMP5]](ptr [[TMP2]], i32 [[TMP0]]), !prof [[PROF3:![0-9]+]] +; CHECK-NEXT: ret i32 [[TMP6]] +; + %2 = tail call ptr @_Z10createTypei(i32 %0) + %3 = tail call i32 @callee(ptr %2, i32 %0) + ret i32 %3 +} + +define i32 @caller2(i32 %0) !prof !19 { +; CHECK-LABEL: define i32 @caller2( +; CHECK-SAME: i32 [[TMP0:%.*]]) !prof [[PROF4:![0-9]+]] { +; CHECK-NEXT: [[TMP2:%.*]] = tail call ptr @_Z10createTypei(i32 [[TMP0]]) +; CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP2]], align 8 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 8 +; CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP4]], align 8 +; CHECK-NEXT: [[TMP6:%.*]] = tail call i32 [[TMP5]](ptr [[TMP2]], i32 [[TMP0]]), !prof [[PROF5:![0-9]+]] +; CHECK-NEXT: ret i32 [[TMP6]] +; + %2 = tail call ptr @_Z10createTypei(i32 %0) + %3 = tail call i32 @callee(ptr %2, i32 %0) + ret i32 %3 +} + +declare ptr @_Z10createTypei(i32) + +!1 = !{i32 1, !"ProfileSummary", !2} +!2 = !{!3, !4, !5, !6, !7, !8, !9, !10} +!3 = !{!"ProfileFormat", !"InstrProf"} +!4 = !{!"TotalCount", i64 10000} +!5 = !{!"MaxCount", i64 10} +!6 = !{!"MaxInternalCount", i64 1} +!7 = !{!"MaxFunctionCount", i64 1000} +!8 = !{!"NumCounts", i64 3} +!9 = !{!"NumFunctions", i64 3} +!10 = !{!"DetailedSummary", !11} +!11 = !{!12, !13, !14} +!12 = !{i32 10000, i64 100, i32 1} +!13 = !{i32 999000, i64 100, i32 1} +!14 = !{i32 999999, i64 1, i32 2} +!17 = !{!"VP", i32 0, i64 1600, i64 123, i64 1000, i64 456, i64 600} +!18 = !{!"function_entry_count", i64 1000} +!19 = !{!"function_entry_count", i64 600} +!20 = !{!"function_entry_count", i64 1700} +;. +; CHECK: [[PROF0]] = !{!"function_entry_count", i64 100} +; CHECK: [[PROF1]] = !{!"VP", i32 0, i64 94, i64 123, i64 58, i64 456, i64 35} +; CHECK: [[PROF2]] = !{!"function_entry_count", i64 1000} +; CHECK: [[PROF3]] = !{!"VP", i32 0, i64 941, i64 123, i64 588, i64 456, i64 352} +; CHECK: [[PROF4]] = !{!"function_entry_count", i64 600} +; CHECK: [[PROF5]] = !{!"VP", i32 0, i64 564, i64 123, i64 352, i64 456, i64 211} +;. diff --git a/llvm/test/Transforms/InstCombine/X86/x86-avx512-inseltpoison.ll b/llvm/test/Transforms/InstCombine/X86/x86-avx512-inseltpoison.ll index 9b990480709c972d1bfb8725918a8c749bb10433..80d8e1b16ed28bb1feda060ecc6a65225735e03a 100644 --- a/llvm/test/Transforms/InstCombine/X86/x86-avx512-inseltpoison.ll +++ b/llvm/test/Transforms/InstCombine/X86/x86-avx512-inseltpoison.ll @@ -39,10 +39,9 @@ define <4 x float> @test_add_ss_mask(<4 x float> %a, <4 x float> %b, <4 x float> ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x float> [[A:%.*]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = fadd float [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i8 [[MASK:%.*]] to i1 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float [[TMP5]], float [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP4]], float [[TMP3]], float [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[A]], float [[TMP6]], i64 0 ; CHECK-NEXT: ret <4 x float> [[TMP7]] ; @@ -117,10 +116,9 @@ define <2 x double> @test_add_sd_mask(<2 x double> %a, <2 x double> %b, <2 x dou ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x double> [[A:%.*]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = fadd double [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i8 [[MASK:%.*]] to i1 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double [[TMP5]], double [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP4]], double [[TMP3]], double [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x double> [[A]], double [[TMP6]], i64 0 ; CHECK-NEXT: ret <2 x double> [[TMP7]] ; @@ -191,10 +189,9 @@ define <4 x float> @test_sub_ss_mask(<4 x float> %a, <4 x float> %b, <4 x float> ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x float> [[A:%.*]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = fsub float [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i8 [[MASK:%.*]] to i1 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float [[TMP5]], float [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP4]], float [[TMP3]], float [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[A]], float [[TMP6]], i64 0 ; CHECK-NEXT: ret <4 x float> [[TMP7]] ; @@ -269,10 +266,9 @@ define <2 x double> @test_sub_sd_mask(<2 x double> %a, <2 x double> %b, <2 x dou ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x double> [[A:%.*]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = fsub double [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i8 [[MASK:%.*]] to i1 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double [[TMP5]], double [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP4]], double [[TMP3]], double [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x double> [[A]], double [[TMP6]], i64 0 ; CHECK-NEXT: ret <2 x double> [[TMP7]] ; @@ -343,10 +339,9 @@ define <4 x float> @test_mul_ss_mask(<4 x float> %a, <4 x float> %b, <4 x float> ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x float> [[A:%.*]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = fmul float [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i8 [[MASK:%.*]] to i1 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float [[TMP5]], float [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP4]], float [[TMP3]], float [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[A]], float [[TMP6]], i64 0 ; CHECK-NEXT: ret <4 x float> [[TMP7]] ; @@ -421,10 +416,9 @@ define <2 x double> @test_mul_sd_mask(<2 x double> %a, <2 x double> %b, <2 x dou ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x double> [[A:%.*]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = fmul double [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i8 [[MASK:%.*]] to i1 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double [[TMP5]], double [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP4]], double [[TMP3]], double [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x double> [[A]], double [[TMP6]], i64 0 ; CHECK-NEXT: ret <2 x double> [[TMP7]] ; @@ -495,10 +489,9 @@ define <4 x float> @test_div_ss_mask(<4 x float> %a, <4 x float> %b, <4 x float> ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x float> [[A:%.*]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = fdiv float [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i8 [[MASK:%.*]] to i1 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float [[TMP5]], float [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP4]], float [[TMP3]], float [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[A]], float [[TMP6]], i64 0 ; CHECK-NEXT: ret <4 x float> [[TMP7]] ; @@ -573,10 +566,9 @@ define <2 x double> @test_div_sd_mask(<2 x double> %a, <2 x double> %b, <2 x dou ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x double> [[A:%.*]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = fdiv double [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i8 [[MASK:%.*]] to i1 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double [[TMP5]], double [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP4]], double [[TMP3]], double [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x double> [[A]], double [[TMP6]], i64 0 ; CHECK-NEXT: ret <2 x double> [[TMP7]] ; @@ -981,9 +973,8 @@ define <4 x float> @test_mask_vfmadd_ss(<4 x float> %a, <4 x float> %b, <4 x flo ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call float @llvm.fma.f32(float [[TMP1]], float [[TMP2]], float [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float [[TMP1]], float [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP4]], float [[TMP1]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[A]], float [[TMP6]], i64 0 ; CHECK-NEXT: ret <4 x float> [[TMP7]] ; @@ -1011,9 +1002,8 @@ define float @test_mask_vfmadd_ss_0(<4 x float> %a, <4 x float> %b, <4 x float> ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call float @llvm.fma.f32(float [[TMP1]], float [[TMP2]], float [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float [[TMP1]], float [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP4]], float [[TMP1]] ; CHECK-NEXT: ret float [[TMP6]] ; %1 = insertelement <4 x float> %a, float 1.000000e+00, i32 1 @@ -1060,9 +1050,8 @@ define <2 x double> @test_mask_vfmadd_sd(<2 x double> %a, <2 x double> %b, <2 x ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call double @llvm.fma.f64(double [[TMP1]], double [[TMP2]], double [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double [[TMP1]], double [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], double [[TMP4]], double [[TMP1]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x double> [[A]], double [[TMP6]], i64 0 ; CHECK-NEXT: ret <2 x double> [[TMP7]] ; @@ -1086,9 +1075,8 @@ define double @test_mask_vfmadd_sd_0(<2 x double> %a, <2 x double> %b, <2 x doub ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call double @llvm.fma.f64(double [[TMP1]], double [[TMP2]], double [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double [[TMP1]], double [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], double [[TMP4]], double [[TMP1]] ; CHECK-NEXT: ret double [[TMP6]] ; %1 = insertelement <2 x double> %a, double 1.000000e+00, i32 1 @@ -1129,9 +1117,8 @@ define <4 x float> @test_maskz_vfmadd_ss(<4 x float> %a, <4 x float> %b, <4 x fl ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call float @llvm.fma.f32(float [[TMP1]], float [[TMP2]], float [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float 0.000000e+00, float [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP4]], float 0.000000e+00 ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[A]], float [[TMP6]], i64 0 ; CHECK-NEXT: ret <4 x float> [[TMP7]] ; @@ -1159,9 +1146,8 @@ define float @test_maskz_vfmadd_ss_0(<4 x float> %a, <4 x float> %b, <4 x float> ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call float @llvm.fma.f32(float [[TMP1]], float [[TMP2]], float [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float 0.000000e+00, float [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP4]], float 0.000000e+00 ; CHECK-NEXT: ret float [[TMP6]] ; %1 = insertelement <4 x float> %a, float 1.000000e+00, i32 1 @@ -1206,9 +1192,8 @@ define <2 x double> @test_maskz_vfmadd_sd(<2 x double> %a, <2 x double> %b, <2 x ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call double @llvm.fma.f64(double [[TMP1]], double [[TMP2]], double [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double 0.000000e+00, double [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], double [[TMP4]], double 0.000000e+00 ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x double> [[A]], double [[TMP6]], i64 0 ; CHECK-NEXT: ret <2 x double> [[TMP7]] ; @@ -1232,9 +1217,8 @@ define double @test_maskz_vfmadd_sd_0(<2 x double> %a, <2 x double> %b, <2 x dou ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call double @llvm.fma.f64(double [[TMP1]], double [[TMP2]], double [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double 0.000000e+00, double [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], double [[TMP4]], double 0.000000e+00 ; CHECK-NEXT: ret double [[TMP6]] ; %1 = insertelement <2 x double> %a, double 1.000000e+00, i32 1 @@ -1275,9 +1259,8 @@ define <4 x float> @test_mask3_vfmadd_ss(<4 x float> %a, <4 x float> %b, <4 x fl ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call float @llvm.fma.f32(float [[TMP1]], float [[TMP2]], float [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float [[TMP3]], float [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP4]], float [[TMP3]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[C]], float [[TMP6]], i64 0 ; CHECK-NEXT: ret <4 x float> [[TMP7]] ; @@ -1305,9 +1288,8 @@ define float @test_mask3_vfmadd_ss_0(<4 x float> %a, <4 x float> %b, <4 x float> ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call float @llvm.fma.f32(float [[TMP1]], float [[TMP2]], float [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float [[TMP3]], float [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP4]], float [[TMP3]] ; CHECK-NEXT: ret float [[TMP6]] ; %1 = insertelement <4 x float> %c, float 1.000000e+00, i32 1 @@ -1352,9 +1334,8 @@ define <2 x double> @test_mask3_vfmadd_sd(<2 x double> %a, <2 x double> %b, <2 x ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call double @llvm.fma.f64(double [[TMP1]], double [[TMP2]], double [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double [[TMP3]], double [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], double [[TMP4]], double [[TMP3]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x double> [[C]], double [[TMP6]], i64 0 ; CHECK-NEXT: ret <2 x double> [[TMP7]] ; @@ -1378,9 +1359,8 @@ define double @test_mask3_vfmadd_sd_0(<2 x double> %a, <2 x double> %b, <2 x dou ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call double @llvm.fma.f64(double [[TMP1]], double [[TMP2]], double [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double [[TMP3]], double [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], double [[TMP4]], double [[TMP3]] ; CHECK-NEXT: ret double [[TMP6]] ; %1 = insertelement <2 x double> %c, double 1.000000e+00, i32 1 @@ -1423,9 +1403,8 @@ define <4 x float> @test_mask3_vfmsub_ss(<4 x float> %a, <4 x float> %b, <4 x fl ; CHECK-NEXT: [[TMP4:%.*]] = fneg float [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = call float @llvm.fma.f32(float [[TMP1]], float [[TMP2]], float [[TMP4]]) ; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x float> [[C]], i64 0 -; CHECK-NEXT: [[TMP7:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP7]], 0 -; CHECK-NEXT: [[TMP8:%.*]] = select i1 [[DOTNOT]], float [[TMP6]], float [[TMP5]] +; CHECK-NEXT: [[TMP7:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], float [[TMP5]], float [[TMP6]] ; CHECK-NEXT: [[TMP9:%.*]] = insertelement <4 x float> [[C]], float [[TMP8]], i64 0 ; CHECK-NEXT: ret <4 x float> [[TMP9]] ; @@ -1457,9 +1436,8 @@ define float @test_mask3_vfmsub_ss_0(<4 x float> %a, <4 x float> %b, <4 x float> ; CHECK-NEXT: [[TMP4:%.*]] = fneg float [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = call float @llvm.fma.f32(float [[TMP1]], float [[TMP2]], float [[TMP4]]) ; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x float> [[C]], i64 0 -; CHECK-NEXT: [[TMP7:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP7]], 0 -; CHECK-NEXT: [[TMP8:%.*]] = select i1 [[DOTNOT]], float [[TMP6]], float [[TMP5]] +; CHECK-NEXT: [[TMP7:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], float [[TMP5]], float [[TMP6]] ; CHECK-NEXT: ret float [[TMP8]] ; %1 = insertelement <4 x float> %c, float 1.000000e+00, i32 1 @@ -1532,9 +1510,8 @@ define <2 x double> @test_mask3_vfmsub_sd(<2 x double> %a, <2 x double> %b, <2 x ; CHECK-NEXT: [[TMP4:%.*]] = fneg double [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = call double @llvm.fma.f64(double [[TMP1]], double [[TMP2]], double [[TMP4]]) ; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x double> [[C]], i64 0 -; CHECK-NEXT: [[TMP7:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP7]], 0 -; CHECK-NEXT: [[TMP8:%.*]] = select i1 [[DOTNOT]], double [[TMP6]], double [[TMP5]] +; CHECK-NEXT: [[TMP7:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], double [[TMP5]], double [[TMP6]] ; CHECK-NEXT: [[TMP9:%.*]] = insertelement <2 x double> [[C]], double [[TMP8]], i64 0 ; CHECK-NEXT: ret <2 x double> [[TMP9]] ; @@ -1562,9 +1539,8 @@ define double @test_mask3_vfmsub_sd_0(<2 x double> %a, <2 x double> %b, <2 x dou ; CHECK-NEXT: [[TMP4:%.*]] = fneg double [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = call double @llvm.fma.f64(double [[TMP1]], double [[TMP2]], double [[TMP4]]) ; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x double> [[C]], i64 0 -; CHECK-NEXT: [[TMP7:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP7]], 0 -; CHECK-NEXT: [[TMP8:%.*]] = select i1 [[DOTNOT]], double [[TMP6]], double [[TMP5]] +; CHECK-NEXT: [[TMP7:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], double [[TMP5]], double [[TMP6]] ; CHECK-NEXT: ret double [[TMP8]] ; %1 = insertelement <2 x double> %c, double 1.000000e+00, i32 1 @@ -1632,9 +1608,8 @@ define <4 x float> @test_mask3_vfnmsub_ss(<4 x float> %a, <4 x float> %b, <4 x f ; CHECK-NEXT: [[TMP5:%.*]] = fneg float [[TMP4]] ; CHECK-NEXT: [[TMP6:%.*]] = call float @llvm.fma.f32(float [[TMP2]], float [[TMP3]], float [[TMP5]]) ; CHECK-NEXT: [[TMP7:%.*]] = extractelement <4 x float> [[C]], i64 0 -; CHECK-NEXT: [[TMP8:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP8]], 0 -; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[DOTNOT]], float [[TMP7]], float [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP8]], float [[TMP6]], float [[TMP7]] ; CHECK-NEXT: [[TMP10:%.*]] = insertelement <4 x float> [[C]], float [[TMP9]], i64 0 ; CHECK-NEXT: ret <4 x float> [[TMP10]] ; @@ -1668,9 +1643,8 @@ define float @test_mask3_vfnmsub_ss_0(<4 x float> %a, <4 x float> %b, <4 x float ; CHECK-NEXT: [[TMP5:%.*]] = fneg float [[TMP4]] ; CHECK-NEXT: [[TMP6:%.*]] = call float @llvm.fma.f32(float [[TMP2]], float [[TMP3]], float [[TMP5]]) ; CHECK-NEXT: [[TMP7:%.*]] = extractelement <4 x float> [[C]], i64 0 -; CHECK-NEXT: [[TMP8:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP8]], 0 -; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[DOTNOT]], float [[TMP7]], float [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP8]], float [[TMP6]], float [[TMP7]] ; CHECK-NEXT: ret float [[TMP9]] ; %1 = insertelement <4 x float> %c, float 1.000000e+00, i32 1 @@ -1747,9 +1721,8 @@ define <2 x double> @test_mask3_vfnmsub_sd(<2 x double> %a, <2 x double> %b, <2 ; CHECK-NEXT: [[TMP5:%.*]] = fneg double [[TMP4]] ; CHECK-NEXT: [[TMP6:%.*]] = call double @llvm.fma.f64(double [[TMP2]], double [[TMP3]], double [[TMP5]]) ; CHECK-NEXT: [[TMP7:%.*]] = extractelement <2 x double> [[C]], i64 0 -; CHECK-NEXT: [[TMP8:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP8]], 0 -; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[DOTNOT]], double [[TMP7]], double [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP8]], double [[TMP6]], double [[TMP7]] ; CHECK-NEXT: [[TMP10:%.*]] = insertelement <2 x double> [[C]], double [[TMP9]], i64 0 ; CHECK-NEXT: ret <2 x double> [[TMP10]] ; @@ -1779,9 +1752,8 @@ define double @test_mask3_vfnmsub_sd_0(<2 x double> %a, <2 x double> %b, <2 x do ; CHECK-NEXT: [[TMP5:%.*]] = fneg double [[TMP4]] ; CHECK-NEXT: [[TMP6:%.*]] = call double @llvm.fma.f64(double [[TMP2]], double [[TMP3]], double [[TMP5]]) ; CHECK-NEXT: [[TMP7:%.*]] = extractelement <2 x double> [[C]], i64 0 -; CHECK-NEXT: [[TMP8:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP8]], 0 -; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[DOTNOT]], double [[TMP7]], double [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP8]], double [[TMP6]], double [[TMP7]] ; CHECK-NEXT: ret double [[TMP9]] ; %1 = insertelement <2 x double> %c, double 1.000000e+00, i32 1 diff --git a/llvm/test/Transforms/InstCombine/X86/x86-avx512.ll b/llvm/test/Transforms/InstCombine/X86/x86-avx512.ll index c10c922f66432458e3a72eb4b353c5c3b77663fe..906e84b607481191828989b182dbd15eecba9db4 100644 --- a/llvm/test/Transforms/InstCombine/X86/x86-avx512.ll +++ b/llvm/test/Transforms/InstCombine/X86/x86-avx512.ll @@ -39,10 +39,9 @@ define <4 x float> @test_add_ss_mask(<4 x float> %a, <4 x float> %b, <4 x float> ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x float> [[A:%.*]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = fadd float [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i8 [[MASK:%.*]] to i1 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float [[TMP5]], float [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP4]], float [[TMP3]], float [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[A]], float [[TMP6]], i64 0 ; CHECK-NEXT: ret <4 x float> [[TMP7]] ; @@ -117,10 +116,9 @@ define <2 x double> @test_add_sd_mask(<2 x double> %a, <2 x double> %b, <2 x dou ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x double> [[A:%.*]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = fadd double [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i8 [[MASK:%.*]] to i1 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double [[TMP5]], double [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP4]], double [[TMP3]], double [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x double> [[A]], double [[TMP6]], i64 0 ; CHECK-NEXT: ret <2 x double> [[TMP7]] ; @@ -191,10 +189,9 @@ define <4 x float> @test_sub_ss_mask(<4 x float> %a, <4 x float> %b, <4 x float> ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x float> [[A:%.*]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = fsub float [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i8 [[MASK:%.*]] to i1 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float [[TMP5]], float [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP4]], float [[TMP3]], float [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[A]], float [[TMP6]], i64 0 ; CHECK-NEXT: ret <4 x float> [[TMP7]] ; @@ -269,10 +266,9 @@ define <2 x double> @test_sub_sd_mask(<2 x double> %a, <2 x double> %b, <2 x dou ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x double> [[A:%.*]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = fsub double [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i8 [[MASK:%.*]] to i1 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double [[TMP5]], double [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP4]], double [[TMP3]], double [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x double> [[A]], double [[TMP6]], i64 0 ; CHECK-NEXT: ret <2 x double> [[TMP7]] ; @@ -343,10 +339,9 @@ define <4 x float> @test_mul_ss_mask(<4 x float> %a, <4 x float> %b, <4 x float> ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x float> [[A:%.*]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = fmul float [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i8 [[MASK:%.*]] to i1 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float [[TMP5]], float [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP4]], float [[TMP3]], float [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[A]], float [[TMP6]], i64 0 ; CHECK-NEXT: ret <4 x float> [[TMP7]] ; @@ -421,10 +416,9 @@ define <2 x double> @test_mul_sd_mask(<2 x double> %a, <2 x double> %b, <2 x dou ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x double> [[A:%.*]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = fmul double [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i8 [[MASK:%.*]] to i1 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double [[TMP5]], double [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP4]], double [[TMP3]], double [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x double> [[A]], double [[TMP6]], i64 0 ; CHECK-NEXT: ret <2 x double> [[TMP7]] ; @@ -495,10 +489,9 @@ define <4 x float> @test_div_ss_mask(<4 x float> %a, <4 x float> %b, <4 x float> ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x float> [[A:%.*]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = fdiv float [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i8 [[MASK:%.*]] to i1 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float [[TMP5]], float [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP4]], float [[TMP3]], float [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[A]], float [[TMP6]], i64 0 ; CHECK-NEXT: ret <4 x float> [[TMP7]] ; @@ -573,10 +566,9 @@ define <2 x double> @test_div_sd_mask(<2 x double> %a, <2 x double> %b, <2 x dou ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x double> [[A:%.*]], i64 0 ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = fdiv double [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = trunc i8 [[MASK:%.*]] to i1 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double [[TMP5]], double [[TMP3]] +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP4]], double [[TMP3]], double [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x double> [[A]], double [[TMP6]], i64 0 ; CHECK-NEXT: ret <2 x double> [[TMP7]] ; @@ -981,9 +973,8 @@ define <4 x float> @test_mask_vfmadd_ss(<4 x float> %a, <4 x float> %b, <4 x flo ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call float @llvm.fma.f32(float [[TMP1]], float [[TMP2]], float [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float [[TMP1]], float [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP4]], float [[TMP1]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[A]], float [[TMP6]], i64 0 ; CHECK-NEXT: ret <4 x float> [[TMP7]] ; @@ -1011,9 +1002,8 @@ define float @test_mask_vfmadd_ss_0(<4 x float> %a, <4 x float> %b, <4 x float> ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call float @llvm.fma.f32(float [[TMP1]], float [[TMP2]], float [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float [[TMP1]], float [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP4]], float [[TMP1]] ; CHECK-NEXT: ret float [[TMP6]] ; %1 = insertelement <4 x float> %a, float 1.000000e+00, i32 1 @@ -1060,9 +1050,8 @@ define <2 x double> @test_mask_vfmadd_sd(<2 x double> %a, <2 x double> %b, <2 x ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call double @llvm.fma.f64(double [[TMP1]], double [[TMP2]], double [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double [[TMP1]], double [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], double [[TMP4]], double [[TMP1]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x double> [[A]], double [[TMP6]], i64 0 ; CHECK-NEXT: ret <2 x double> [[TMP7]] ; @@ -1086,9 +1075,8 @@ define double @test_mask_vfmadd_sd_0(<2 x double> %a, <2 x double> %b, <2 x doub ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call double @llvm.fma.f64(double [[TMP1]], double [[TMP2]], double [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double [[TMP1]], double [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], double [[TMP4]], double [[TMP1]] ; CHECK-NEXT: ret double [[TMP6]] ; %1 = insertelement <2 x double> %a, double 1.000000e+00, i32 1 @@ -1129,9 +1117,8 @@ define <4 x float> @test_maskz_vfmadd_ss(<4 x float> %a, <4 x float> %b, <4 x fl ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call float @llvm.fma.f32(float [[TMP1]], float [[TMP2]], float [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float 0.000000e+00, float [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP4]], float 0.000000e+00 ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[A]], float [[TMP6]], i64 0 ; CHECK-NEXT: ret <4 x float> [[TMP7]] ; @@ -1159,9 +1146,8 @@ define float @test_maskz_vfmadd_ss_0(<4 x float> %a, <4 x float> %b, <4 x float> ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call float @llvm.fma.f32(float [[TMP1]], float [[TMP2]], float [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float 0.000000e+00, float [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP4]], float 0.000000e+00 ; CHECK-NEXT: ret float [[TMP6]] ; %1 = insertelement <4 x float> %a, float 1.000000e+00, i32 1 @@ -1206,9 +1192,8 @@ define <2 x double> @test_maskz_vfmadd_sd(<2 x double> %a, <2 x double> %b, <2 x ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call double @llvm.fma.f64(double [[TMP1]], double [[TMP2]], double [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double 0.000000e+00, double [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], double [[TMP4]], double 0.000000e+00 ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x double> [[A]], double [[TMP6]], i64 0 ; CHECK-NEXT: ret <2 x double> [[TMP7]] ; @@ -1232,9 +1217,8 @@ define double @test_maskz_vfmadd_sd_0(<2 x double> %a, <2 x double> %b, <2 x dou ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call double @llvm.fma.f64(double [[TMP1]], double [[TMP2]], double [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double 0.000000e+00, double [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], double [[TMP4]], double 0.000000e+00 ; CHECK-NEXT: ret double [[TMP6]] ; %1 = insertelement <2 x double> %a, double 1.000000e+00, i32 1 @@ -1275,9 +1259,8 @@ define <4 x float> @test_mask3_vfmadd_ss(<4 x float> %a, <4 x float> %b, <4 x fl ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call float @llvm.fma.f32(float [[TMP1]], float [[TMP2]], float [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float [[TMP3]], float [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP4]], float [[TMP3]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x float> [[C]], float [[TMP6]], i64 0 ; CHECK-NEXT: ret <4 x float> [[TMP7]] ; @@ -1305,9 +1288,8 @@ define float @test_mask3_vfmadd_ss_0(<4 x float> %a, <4 x float> %b, <4 x float> ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x float> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x float> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call float @llvm.fma.f32(float [[TMP1]], float [[TMP2]], float [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], float [[TMP3]], float [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], float [[TMP4]], float [[TMP3]] ; CHECK-NEXT: ret float [[TMP6]] ; %1 = insertelement <4 x float> %c, float 1.000000e+00, i32 1 @@ -1352,9 +1334,8 @@ define <2 x double> @test_mask3_vfmadd_sd(<2 x double> %a, <2 x double> %b, <2 x ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call double @llvm.fma.f64(double [[TMP1]], double [[TMP2]], double [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double [[TMP3]], double [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], double [[TMP4]], double [[TMP3]] ; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x double> [[C]], double [[TMP6]], i64 0 ; CHECK-NEXT: ret <2 x double> [[TMP7]] ; @@ -1378,9 +1359,8 @@ define double @test_mask3_vfmadd_sd_0(<2 x double> %a, <2 x double> %b, <2 x dou ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[B:%.*]], i64 0 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x double> [[C:%.*]], i64 0 ; CHECK-NEXT: [[TMP4:%.*]] = call double @llvm.fma.f64(double [[TMP1]], double [[TMP2]], double [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP5]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[DOTNOT]], double [[TMP3]], double [[TMP4]] +; CHECK-NEXT: [[TMP5:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP6:%.*]] = select i1 [[TMP5]], double [[TMP4]], double [[TMP3]] ; CHECK-NEXT: ret double [[TMP6]] ; %1 = insertelement <2 x double> %c, double 1.000000e+00, i32 1 @@ -1423,9 +1403,8 @@ define <4 x float> @test_mask3_vfmsub_ss(<4 x float> %a, <4 x float> %b, <4 x fl ; CHECK-NEXT: [[TMP4:%.*]] = fneg float [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = call float @llvm.fma.f32(float [[TMP1]], float [[TMP2]], float [[TMP4]]) ; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x float> [[C]], i64 0 -; CHECK-NEXT: [[TMP7:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP7]], 0 -; CHECK-NEXT: [[TMP8:%.*]] = select i1 [[DOTNOT]], float [[TMP6]], float [[TMP5]] +; CHECK-NEXT: [[TMP7:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], float [[TMP5]], float [[TMP6]] ; CHECK-NEXT: [[TMP9:%.*]] = insertelement <4 x float> [[C]], float [[TMP8]], i64 0 ; CHECK-NEXT: ret <4 x float> [[TMP9]] ; @@ -1457,9 +1436,8 @@ define float @test_mask3_vfmsub_ss_0(<4 x float> %a, <4 x float> %b, <4 x float> ; CHECK-NEXT: [[TMP4:%.*]] = fneg float [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = call float @llvm.fma.f32(float [[TMP1]], float [[TMP2]], float [[TMP4]]) ; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x float> [[C]], i64 0 -; CHECK-NEXT: [[TMP7:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP7]], 0 -; CHECK-NEXT: [[TMP8:%.*]] = select i1 [[DOTNOT]], float [[TMP6]], float [[TMP5]] +; CHECK-NEXT: [[TMP7:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], float [[TMP5]], float [[TMP6]] ; CHECK-NEXT: ret float [[TMP8]] ; %1 = insertelement <4 x float> %c, float 1.000000e+00, i32 1 @@ -1532,9 +1510,8 @@ define <2 x double> @test_mask3_vfmsub_sd(<2 x double> %a, <2 x double> %b, <2 x ; CHECK-NEXT: [[TMP4:%.*]] = fneg double [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = call double @llvm.fma.f64(double [[TMP1]], double [[TMP2]], double [[TMP4]]) ; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x double> [[C]], i64 0 -; CHECK-NEXT: [[TMP7:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP7]], 0 -; CHECK-NEXT: [[TMP8:%.*]] = select i1 [[DOTNOT]], double [[TMP6]], double [[TMP5]] +; CHECK-NEXT: [[TMP7:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], double [[TMP5]], double [[TMP6]] ; CHECK-NEXT: [[TMP9:%.*]] = insertelement <2 x double> [[C]], double [[TMP8]], i64 0 ; CHECK-NEXT: ret <2 x double> [[TMP9]] ; @@ -1562,9 +1539,8 @@ define double @test_mask3_vfmsub_sd_0(<2 x double> %a, <2 x double> %b, <2 x dou ; CHECK-NEXT: [[TMP4:%.*]] = fneg double [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = call double @llvm.fma.f64(double [[TMP1]], double [[TMP2]], double [[TMP4]]) ; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x double> [[C]], i64 0 -; CHECK-NEXT: [[TMP7:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP7]], 0 -; CHECK-NEXT: [[TMP8:%.*]] = select i1 [[DOTNOT]], double [[TMP6]], double [[TMP5]] +; CHECK-NEXT: [[TMP7:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP8:%.*]] = select i1 [[TMP7]], double [[TMP5]], double [[TMP6]] ; CHECK-NEXT: ret double [[TMP8]] ; %1 = insertelement <2 x double> %c, double 1.000000e+00, i32 1 @@ -1632,9 +1608,8 @@ define <4 x float> @test_mask3_vfnmsub_ss(<4 x float> %a, <4 x float> %b, <4 x f ; CHECK-NEXT: [[TMP5:%.*]] = fneg float [[TMP4]] ; CHECK-NEXT: [[TMP6:%.*]] = call float @llvm.fma.f32(float [[TMP2]], float [[TMP3]], float [[TMP5]]) ; CHECK-NEXT: [[TMP7:%.*]] = extractelement <4 x float> [[C]], i64 0 -; CHECK-NEXT: [[TMP8:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP8]], 0 -; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[DOTNOT]], float [[TMP7]], float [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP8]], float [[TMP6]], float [[TMP7]] ; CHECK-NEXT: [[TMP10:%.*]] = insertelement <4 x float> [[C]], float [[TMP9]], i64 0 ; CHECK-NEXT: ret <4 x float> [[TMP10]] ; @@ -1668,9 +1643,8 @@ define float @test_mask3_vfnmsub_ss_0(<4 x float> %a, <4 x float> %b, <4 x float ; CHECK-NEXT: [[TMP5:%.*]] = fneg float [[TMP4]] ; CHECK-NEXT: [[TMP6:%.*]] = call float @llvm.fma.f32(float [[TMP2]], float [[TMP3]], float [[TMP5]]) ; CHECK-NEXT: [[TMP7:%.*]] = extractelement <4 x float> [[C]], i64 0 -; CHECK-NEXT: [[TMP8:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP8]], 0 -; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[DOTNOT]], float [[TMP7]], float [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP8]], float [[TMP6]], float [[TMP7]] ; CHECK-NEXT: ret float [[TMP9]] ; %1 = insertelement <4 x float> %c, float 1.000000e+00, i32 1 @@ -1747,9 +1721,8 @@ define <2 x double> @test_mask3_vfnmsub_sd(<2 x double> %a, <2 x double> %b, <2 ; CHECK-NEXT: [[TMP5:%.*]] = fneg double [[TMP4]] ; CHECK-NEXT: [[TMP6:%.*]] = call double @llvm.fma.f64(double [[TMP2]], double [[TMP3]], double [[TMP5]]) ; CHECK-NEXT: [[TMP7:%.*]] = extractelement <2 x double> [[C]], i64 0 -; CHECK-NEXT: [[TMP8:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP8]], 0 -; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[DOTNOT]], double [[TMP7]], double [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP8]], double [[TMP6]], double [[TMP7]] ; CHECK-NEXT: [[TMP10:%.*]] = insertelement <2 x double> [[C]], double [[TMP9]], i64 0 ; CHECK-NEXT: ret <2 x double> [[TMP10]] ; @@ -1779,9 +1752,8 @@ define double @test_mask3_vfnmsub_sd_0(<2 x double> %a, <2 x double> %b, <2 x do ; CHECK-NEXT: [[TMP5:%.*]] = fneg double [[TMP4]] ; CHECK-NEXT: [[TMP6:%.*]] = call double @llvm.fma.f64(double [[TMP2]], double [[TMP3]], double [[TMP5]]) ; CHECK-NEXT: [[TMP7:%.*]] = extractelement <2 x double> [[C]], i64 0 -; CHECK-NEXT: [[TMP8:%.*]] = and i8 [[MASK:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i8 [[TMP8]], 0 -; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[DOTNOT]], double [[TMP7]], double [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = trunc i8 [[MASK:%.*]] to i1 +; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP8]], double [[TMP6]], double [[TMP7]] ; CHECK-NEXT: ret double [[TMP9]] ; %1 = insertelement <2 x double> %c, double 1.000000e+00, i32 1 diff --git a/llvm/test/Transforms/InstCombine/add.ll b/llvm/test/Transforms/InstCombine/add.ll index 522dcf8db27f42c11df91dadd66d0d529b616b79..ec3aca26514caf1ac057e698d2fe1b8136374d3b 100644 --- a/llvm/test/Transforms/InstCombine/add.ll +++ b/llvm/test/Transforms/InstCombine/add.ll @@ -3986,5 +3986,81 @@ define i32 @add_reduce_sqr_sum_varC_invalid2(i32 %a, i32 %b) { ret i32 %ab2 } +define i32 @fold_sext_addition_or_disjoint(i8 %x) { +; CHECK-LABEL: @fold_sext_addition_or_disjoint( +; CHECK-NEXT: [[SE:%.*]] = sext i8 [[XX:%.*]] to i32 +; CHECK-NEXT: [[R:%.*]] = add nsw i32 [[SE]], 1246 +; CHECK-NEXT: ret i32 [[R]] +; + %xx = or disjoint i8 %x, 12 + %se = sext i8 %xx to i32 + %r = add i32 %se, 1234 + ret i32 %r +} + +define i32 @fold_sext_addition_fail(i8 %x) { +; CHECK-LABEL: @fold_sext_addition_fail( +; CHECK-NEXT: [[XX:%.*]] = or i8 [[X:%.*]], 12 +; CHECK-NEXT: [[SE:%.*]] = sext i8 [[XX]] to i32 +; CHECK-NEXT: [[R:%.*]] = add nsw i32 [[SE]], 1234 +; CHECK-NEXT: ret i32 [[R]] +; + %xx = or i8 %x, 12 + %se = sext i8 %xx to i32 + %r = add i32 %se, 1234 + ret i32 %r +} + +define i32 @fold_zext_addition_or_disjoint(i8 %x) { +; CHECK-LABEL: @fold_zext_addition_or_disjoint( +; CHECK-NEXT: [[SE:%.*]] = zext i8 [[XX:%.*]] to i32 +; CHECK-NEXT: [[R:%.*]] = add nuw nsw i32 [[SE]], 1246 +; CHECK-NEXT: ret i32 [[R]] +; + %xx = or disjoint i8 %x, 12 + %se = zext i8 %xx to i32 + %r = add i32 %se, 1234 + ret i32 %r +} + +define i32 @fold_zext_addition_or_disjoint2(i8 %x) { +; CHECK-LABEL: @fold_zext_addition_or_disjoint2( +; CHECK-NEXT: [[XX:%.*]] = add nuw i8 [[X:%.*]], 4 +; CHECK-NEXT: [[SE:%.*]] = zext i8 [[XX]] to i32 +; CHECK-NEXT: ret i32 [[SE]] +; + %xx = or disjoint i8 %x, 18 + %se = zext i8 %xx to i32 + %r = add i32 %se, -14 + ret i32 %r +} + +define i32 @fold_zext_addition_fail(i8 %x) { +; CHECK-LABEL: @fold_zext_addition_fail( +; CHECK-NEXT: [[XX:%.*]] = or i8 [[X:%.*]], 12 +; CHECK-NEXT: [[SE:%.*]] = zext i8 [[XX]] to i32 +; CHECK-NEXT: [[R:%.*]] = add nuw nsw i32 [[SE]], 1234 +; CHECK-NEXT: ret i32 [[R]] +; + %xx = or i8 %x, 12 + %se = zext i8 %xx to i32 + %r = add i32 %se, 1234 + ret i32 %r +} + +define i32 @fold_zext_addition_fail2(i8 %x) { +; CHECK-LABEL: @fold_zext_addition_fail2( +; CHECK-NEXT: [[XX:%.*]] = or i8 [[X:%.*]], 18 +; CHECK-NEXT: [[SE:%.*]] = zext i8 [[XX]] to i32 +; CHECK-NEXT: [[R:%.*]] = add nsw i32 [[SE]], -14 +; CHECK-NEXT: ret i32 [[R]] +; + %xx = or i8 %x, 18 + %se = zext i8 %xx to i32 + %r = add i32 %se, -14 + ret i32 %r +} + + declare void @llvm.assume(i1) declare void @fake_func(i32) diff --git a/llvm/test/Transforms/InstCombine/allow-checks.ll b/llvm/test/Transforms/InstCombine/allow-checks.ll new file mode 100644 index 0000000000000000000000000000000000000000..873b7c3014a88119451f3b76e9ea7c60328e3144 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/allow-checks.ll @@ -0,0 +1,44 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -passes=instcombine -S | FileCheck %s --implicit-check-not="call i1 @llvm.allow" + +define i1 @test_runtime() { +; CHECK-LABEL: @test_runtime( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[HOT:%.*]] = call i1 @llvm.allow.runtime.check(metadata !"test") +; CHECK-NEXT: ret i1 [[HOT]] +; +entry: + %allow = call i1 @llvm.allow.runtime.check(metadata !"test") + ret i1 %allow +} + +define void @test_runtime_void() { +; CHECK-LABEL: @test_runtime_void( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret void +; +entry: + %allow = call i1 @llvm.allow.runtime.check(metadata !"test") + ret void +} + +define i1 @test_ubsan() { +; CHECK-LABEL: @test_ubsan( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[HOT:%.*]] = call i1 @llvm.allow.ubsan.check(i8 11) +; CHECK-NEXT: ret i1 [[HOT]] +; +entry: + %allow = call i1 @llvm.allow.ubsan.check(i8 11) + ret i1 %allow +} + +define void @test_ubsan_void() { +; CHECK-LABEL: @test_ubsan_void( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret void +; +entry: + %allow = call i1 @llvm.allow.ubsan.check(i8 11) + ret void +} diff --git a/llvm/test/Transforms/InstCombine/and-or-implied-cond-not.ll b/llvm/test/Transforms/InstCombine/and-or-implied-cond-not.ll new file mode 100644 index 0000000000000000000000000000000000000000..89b3164018ac9abbf9af69eec54514b9a59f58de --- /dev/null +++ b/llvm/test/Transforms/InstCombine/and-or-implied-cond-not.ll @@ -0,0 +1,69 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +define i1 @test_imply_not1(i32 %depth) { +; CHECK-LABEL: define i1 @test_imply_not1( +; CHECK-SAME: i32 [[DEPTH:%.*]]) { +; CHECK-NEXT: [[CMP1_NOT1:%.*]] = icmp eq i32 [[DEPTH]], 16 +; CHECK-NEXT: call void @use(i1 [[CMP1_NOT1]]) +; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[DEPTH]], 8 +; CHECK-NEXT: call void @use(i1 [[CMP2]]) +; CHECK-NEXT: br i1 [[CMP1_NOT1]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]] +; CHECK: if.then: +; CHECK-NEXT: call void @func1() +; CHECK-NEXT: unreachable +; CHECK: if.else: +; CHECK-NEXT: call void @func2() +; CHECK-NEXT: unreachable +; + %cmp1 = icmp eq i32 %depth, 16 + call void @use(i1 %cmp1) + %cmp2 = icmp slt i32 %depth, 8 + call void @use(i1 %cmp2) + %cmp.not = xor i1 %cmp1, true + %brmerge = or i1 %cmp2, %cmp.not + br i1 %brmerge, label %if.then, label %if.else +if.then: + call void @func1() + unreachable + +if.else: + call void @func2() + unreachable +} + +define i1 @test_imply_not2(i32 %a, i1 %cmp2) { +; CHECK-LABEL: define i1 @test_imply_not2( +; CHECK-SAME: i32 [[A:%.*]], i1 [[CMP2:%.*]]) { +; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A]], 0 +; CHECK-NEXT: [[BRMERGE:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP2]] +; CHECK-NEXT: ret i1 [[BRMERGE]] +; + %cmp1 = icmp eq i32 %a, 0 + %or.cond = select i1 %cmp1, i1 %cmp2, i1 false + %cmp.not = xor i1 %cmp1, true + %brmerge = or i1 %or.cond, %cmp.not + ret i1 %brmerge +} + +define i1 @test_imply_not3(i32 %a, i32 %b, i1 %cond) { +; CHECK-LABEL: define i1 @test_imply_not3( +; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i1 [[COND:%.*]]) { +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A]], [[B]] +; CHECK-NEXT: call void @use(i1 [[CMP1]]) +; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[A]], [[B]] +; CHECK-NEXT: [[AND:%.*]] = select i1 [[CMP2]], i1 [[COND]], i1 false +; CHECK-NEXT: ret i1 [[AND]] +; + %cmp1 = icmp eq i32 %a, %b + call void @use(i1 %cmp1) + %cmp2 = icmp slt i32 %a, %b + %cmp.not = xor i1 %cmp1, true + %sel = select i1 %cmp.not, i1 %cond, i1 false + %and = and i1 %cmp2, %sel + ret i1 %and +} + +declare void @func1() +declare void @func2() +declare void @use(i1) diff --git a/llvm/test/Transforms/InstCombine/apint-shl-trunc.ll b/llvm/test/Transforms/InstCombine/apint-shl-trunc.ll index 2d72a4ff8c0dfafa080b937027052a6ca425c992..e2346987737a29dea5763ccbe1148616e4130daa 100644 --- a/llvm/test/Transforms/InstCombine/apint-shl-trunc.ll +++ b/llvm/test/Transforms/InstCombine/apint-shl-trunc.ll @@ -3,9 +3,8 @@ define i1 @test0(i39 %X, i39 %A) { ; CHECK-LABEL: @test0( -; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i39 1, [[A:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = and i39 [[TMP1]], [[X:%.*]] -; CHECK-NEXT: [[D:%.*]] = icmp ne i39 [[TMP2]], 0 +; CHECK-NEXT: [[B:%.*]] = lshr i39 [[X:%.*]], [[A:%.*]] +; CHECK-NEXT: [[D:%.*]] = trunc i39 [[B]] to i1 ; CHECK-NEXT: ret i1 [[D]] ; %B = lshr i39 %X, %A @@ -15,9 +14,8 @@ define i1 @test0(i39 %X, i39 %A) { define i1 @test1(i799 %X, i799 %A) { ; CHECK-LABEL: @test1( -; CHECK-NEXT: [[TMP1:%.*]] = shl nuw i799 1, [[A:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = and i799 [[TMP1]], [[X:%.*]] -; CHECK-NEXT: [[D:%.*]] = icmp ne i799 [[TMP2]], 0 +; CHECK-NEXT: [[B:%.*]] = lshr i799 [[X:%.*]], [[A:%.*]] +; CHECK-NEXT: [[D:%.*]] = trunc i799 [[B]] to i1 ; CHECK-NEXT: ret i1 [[D]] ; %B = lshr i799 %X, %A diff --git a/llvm/test/Transforms/InstCombine/assume.ll b/llvm/test/Transforms/InstCombine/assume.ll index 927f0a86b0a252ada688c16117e54bf662ebf110..87c75fb2b55592712ca4a29e1c56af3a87ba88be 100644 --- a/llvm/test/Transforms/InstCombine/assume.ll +++ b/llvm/test/Transforms/InstCombine/assume.ll @@ -386,7 +386,7 @@ define i1 @nonnull5(ptr %a) { define i32 @assumption_conflicts_with_known_bits(i32 %a, i32 %b) { ; CHECK-LABEL: @assumption_conflicts_with_known_bits( ; CHECK-NEXT: store i1 true, ptr poison, align 1 -; CHECK-NEXT: ret i32 1 +; CHECK-NEXT: ret i32 poison ; %and1 = and i32 %b, 3 %B1 = lshr i32 %and1, %and1 diff --git a/llvm/test/Transforms/InstCombine/binop-itofp.ll b/llvm/test/Transforms/InstCombine/binop-itofp.ll index 7d2b872985d5c269f99e8b77e1a2d5f3b7fa4bee..cd9ec1e59203ff5262d562dd67b37756eb2bc390 100644 --- a/llvm/test/Transforms/InstCombine/binop-itofp.ll +++ b/llvm/test/Transforms/InstCombine/binop-itofp.ll @@ -1004,3 +1004,125 @@ define float @test_ui_add_with_signed_constant(i32 %shr.i) { %add = fadd float %sub, -16383.0 ret float %add } + + +;; Reduced form of bug noticed due to #82555 +define float @missed_nonzero_check_on_constant_for_si_fmul(i1 %c, i1 %.b, ptr %g_2345) { +; CHECK-LABEL: @missed_nonzero_check_on_constant_for_si_fmul( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C:%.*]], i32 65529, i32 53264 +; CHECK-NEXT: [[CONV_I:%.*]] = trunc i32 [[SEL]] to i16 +; CHECK-NEXT: [[CONV1_I:%.*]] = sitofp i16 [[CONV_I]] to float +; CHECK-NEXT: [[MUL3_I_I:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[CONV1_I]]) +; CHECK-NEXT: store i32 [[SEL]], ptr [[G_2345:%.*]], align 4 +; CHECK-NEXT: ret float [[MUL3_I_I]] +; + %sel = select i1 %c, i32 65529, i32 53264 + %conv.i = trunc i32 %sel to i16 + %conv1.i = sitofp i16 %conv.i to float + %mul3.i.i = fmul float %conv1.i, 0.000000e+00 + store i32 %sel, ptr %g_2345, align 4 + ret float %mul3.i.i +} + +define <2 x float> @missed_nonzero_check_on_constant_for_si_fmul_vec(i1 %c, i1 %.b, ptr %g_2345) { +; CHECK-LABEL: @missed_nonzero_check_on_constant_for_si_fmul_vec( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C:%.*]], i32 65529, i32 53264 +; CHECK-NEXT: [[CONV_I_S:%.*]] = trunc i32 [[SEL]] to i16 +; CHECK-NEXT: [[CONV_I_V:%.*]] = insertelement <2 x i16> poison, i16 [[CONV_I_S]], i64 0 +; CHECK-NEXT: [[CONV_I:%.*]] = shufflevector <2 x i16> [[CONV_I_V]], <2 x i16> poison, <2 x i32> zeroinitializer +; CHECK-NEXT: [[CONV1_I:%.*]] = sitofp <2 x i16> [[CONV_I]] to <2 x float> +; CHECK-NEXT: [[MUL3_I_I:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> zeroinitializer, <2 x float> [[CONV1_I]]) +; CHECK-NEXT: store i32 [[SEL]], ptr [[G_2345:%.*]], align 4 +; CHECK-NEXT: ret <2 x float> [[MUL3_I_I]] +; + %sel = select i1 %c, i32 65529, i32 53264 + %conv.i.s = trunc i32 %sel to i16 + %conv.i.v = insertelement <2 x i16> poison, i16 %conv.i.s, i64 0 + %conv.i = insertelement <2 x i16> %conv.i.v, i16 %conv.i.s, i64 1 + %conv1.i = sitofp <2 x i16> %conv.i to <2 x float> + %mul3.i.i = fmul <2 x float> %conv1.i, zeroinitializer + store i32 %sel, ptr %g_2345, align 4 + ret <2 x float> %mul3.i.i +} + +define float @negzero_check_on_constant_for_si_fmul(i1 %c, i1 %.b, ptr %g_2345) { +; CHECK-LABEL: @negzero_check_on_constant_for_si_fmul( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C:%.*]], i32 65529, i32 53264 +; CHECK-NEXT: [[CONV_I:%.*]] = trunc i32 [[SEL]] to i16 +; CHECK-NEXT: [[CONV1_I:%.*]] = sitofp i16 [[CONV_I]] to float +; CHECK-NEXT: [[TMP1:%.*]] = fneg float [[CONV1_I]] +; CHECK-NEXT: [[MUL3_I_I:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[TMP1]]) +; CHECK-NEXT: store i32 [[SEL]], ptr [[G_2345:%.*]], align 4 +; CHECK-NEXT: ret float [[MUL3_I_I]] +; + %sel = select i1 %c, i32 65529, i32 53264 + %conv.i = trunc i32 %sel to i16 + %conv1.i = sitofp i16 %conv.i to float + %mul3.i.i = fmul float %conv1.i, -0.000000e+00 + store i32 %sel, ptr %g_2345, align 4 + ret float %mul3.i.i +} + +define <2 x float> @nonzero_check_on_constant_for_si_fmul_vec_w_undef(i1 %c, i1 %.b, ptr %g_2345) { +; CHECK-LABEL: @nonzero_check_on_constant_for_si_fmul_vec_w_undef( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C:%.*]], i32 65529, i32 53264 +; CHECK-NEXT: [[CONV_I_S:%.*]] = trunc i32 [[SEL]] to i16 +; CHECK-NEXT: [[CONV_I_V:%.*]] = insertelement <2 x i16> poison, i16 [[CONV_I_S]], i64 0 +; CHECK-NEXT: [[CONV_I:%.*]] = shufflevector <2 x i16> [[CONV_I_V]], <2 x i16> poison, <2 x i32> zeroinitializer +; CHECK-NEXT: [[CONV1_I:%.*]] = sitofp <2 x i16> [[CONV_I]] to <2 x float> +; CHECK-NEXT: [[MUL3_I_I:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> zeroinitializer, <2 x float> [[CONV1_I]]) +; CHECK-NEXT: store i32 [[SEL]], ptr [[G_2345:%.*]], align 4 +; CHECK-NEXT: ret <2 x float> [[MUL3_I_I]] +; + %sel = select i1 %c, i32 65529, i32 53264 + %conv.i.s = trunc i32 %sel to i16 + %conv.i.v = insertelement <2 x i16> poison, i16 %conv.i.s, i64 0 + %conv.i = insertelement <2 x i16> %conv.i.v, i16 %conv.i.s, i64 1 + %conv1.i = sitofp <2 x i16> %conv.i to <2 x float> + %mul3.i.i = fmul <2 x float> %conv1.i, <float undef, float 0.000000e+00> + store i32 %sel, ptr %g_2345, align 4 + ret <2 x float> %mul3.i.i +} + +define <2 x float> @nonzero_check_on_constant_for_si_fmul_nz_vec_w_undef(i1 %c, i1 %.b, ptr %g_2345) { +; CHECK-LABEL: @nonzero_check_on_constant_for_si_fmul_nz_vec_w_undef( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C:%.*]], i32 65529, i32 53264 +; CHECK-NEXT: [[CONV_I_S:%.*]] = trunc i32 [[SEL]] to i16 +; CHECK-NEXT: [[CONV_I_V:%.*]] = insertelement <2 x i16> poison, i16 [[CONV_I_S]], i64 0 +; CHECK-NEXT: [[CONV_I:%.*]] = shufflevector <2 x i16> [[CONV_I_V]], <2 x i16> poison, <2 x i32> zeroinitializer +; CHECK-NEXT: [[CONV1_I:%.*]] = sitofp <2 x i16> [[CONV_I]] to <2 x float> +; CHECK-NEXT: [[MUL3_I_I:%.*]] = fmul <2 x float> [[CONV1_I]], <float undef, float 1.000000e+00> +; CHECK-NEXT: store i32 [[SEL]], ptr [[G_2345:%.*]], align 4 +; CHECK-NEXT: ret <2 x float> [[MUL3_I_I]] +; + %sel = select i1 %c, i32 65529, i32 53264 + %conv.i.s = trunc i32 %sel to i16 + %conv.i.v = insertelement <2 x i16> poison, i16 %conv.i.s, i64 0 + %conv.i = insertelement <2 x i16> %conv.i.v, i16 %conv.i.s, i64 1 + %conv1.i = sitofp <2 x i16> %conv.i to <2 x float> + %mul3.i.i = fmul <2 x float> %conv1.i, <float undef, float 1.000000e+00> + store i32 %sel, ptr %g_2345, align 4 + ret <2 x float> %mul3.i.i +} + +define <2 x float> @nonzero_check_on_constant_for_si_fmul_negz_vec_w_undef(i1 %c, i1 %.b, ptr %g_2345) { +; CHECK-LABEL: @nonzero_check_on_constant_for_si_fmul_negz_vec_w_undef( +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C:%.*]], i32 65529, i32 53264 +; CHECK-NEXT: [[CONV_I_S:%.*]] = trunc i32 [[SEL]] to i16 +; CHECK-NEXT: [[CONV_I_V:%.*]] = insertelement <2 x i16> poison, i16 [[CONV_I_S]], i64 0 +; CHECK-NEXT: [[CONV_I:%.*]] = shufflevector <2 x i16> [[CONV_I_V]], <2 x i16> poison, <2 x i32> zeroinitializer +; CHECK-NEXT: [[CONV1_I:%.*]] = sitofp <2 x i16> [[CONV_I]] to <2 x float> +; CHECK-NEXT: [[TMP1:%.*]] = fneg <2 x float> [[CONV1_I]] +; CHECK-NEXT: [[MUL3_I_I:%.*]] = call <2 x float> @llvm.copysign.v2f32(<2 x float> zeroinitializer, <2 x float> [[TMP1]]) +; CHECK-NEXT: store i32 [[SEL]], ptr [[G_2345:%.*]], align 4 +; CHECK-NEXT: ret <2 x float> [[MUL3_I_I]] +; + %sel = select i1 %c, i32 65529, i32 53264 + %conv.i.s = trunc i32 %sel to i16 + %conv.i.v = insertelement <2 x i16> poison, i16 %conv.i.s, i64 0 + %conv.i = insertelement <2 x i16> %conv.i.v, i16 %conv.i.s, i64 1 + %conv1.i = sitofp <2 x i16> %conv.i to <2 x float> + %mul3.i.i = fmul <2 x float> %conv1.i, <float undef, float -0.000000e+00> + store i32 %sel, ptr %g_2345, align 4 + ret <2 x float> %mul3.i.i +} diff --git a/llvm/test/Transforms/InstCombine/builtin-hot.ll b/llvm/test/Transforms/InstCombine/builtin-hot.ll deleted file mode 100644 index 8d338875d7adb56f8bdde11ed0796e9542373e00..0000000000000000000000000000000000000000 --- a/llvm/test/Transforms/InstCombine/builtin-hot.ll +++ /dev/null @@ -1,25 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -passes=instcombine -S | FileCheck %s - -define i1 @test() { -; CHECK-LABEL: @test( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[HOT:%.*]] = call i1 @llvm.experimental.hot() -; CHECK-NEXT: ret i1 [[HOT]] -; -entry: - %hot = call i1 @llvm.experimental.hot() - ret i1 %hot -} - -define void @test_void() { -; CHECK-LABEL: @test_void( -; CHECK-NEXT: entry: -; CHECK-NEXT: ret void -; -entry: - %hot = call i1 @llvm.experimental.hot() - ret void -} - -declare i1 @llvm.expect.hot() nounwind diff --git a/llvm/test/Transforms/InstCombine/cast.ll b/llvm/test/Transforms/InstCombine/cast.ll index 85433a99f2caec0e7ae9913d3220512008e39f55..97554e9462043c41c7731e1c66b60b05d67067ca 100644 --- a/llvm/test/Transforms/InstCombine/cast.ll +++ b/llvm/test/Transforms/InstCombine/cast.ll @@ -1399,8 +1399,7 @@ define float @sitofp_zext(i16 %a) { define i1 @PR23309(i32 %A, i32 %B) { ; ALL-LABEL: @PR23309( ; ALL-NEXT: [[SUB:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] -; ALL-NEXT: [[TMP1:%.*]] = and i32 [[SUB]], 1 -; ALL-NEXT: [[TRUNC:%.*]] = icmp ne i32 [[TMP1]], 0 +; ALL-NEXT: [[TRUNC:%.*]] = trunc i32 [[SUB]] to i1 ; ALL-NEXT: ret i1 [[TRUNC]] ; %add = add i32 %A, -4 @@ -1412,8 +1411,7 @@ define i1 @PR23309(i32 %A, i32 %B) { define i1 @PR23309v2(i32 %A, i32 %B) { ; ALL-LABEL: @PR23309v2( ; ALL-NEXT: [[SUB:%.*]] = add i32 [[A:%.*]], [[B:%.*]] -; ALL-NEXT: [[TMP1:%.*]] = and i32 [[SUB]], 1 -; ALL-NEXT: [[TRUNC:%.*]] = icmp ne i32 [[TMP1]], 0 +; ALL-NEXT: [[TRUNC:%.*]] = trunc i32 [[SUB]] to i1 ; ALL-NEXT: ret i1 [[TRUNC]] ; %add = add i32 %A, -4 diff --git a/llvm/test/Transforms/InstCombine/catchswitch-phi.ll b/llvm/test/Transforms/InstCombine/catchswitch-phi.ll index 038847609b0f90c1839750fbd611e037e4ecea45..cb87ee67a4518744c3f9a00daf7ca0d178e5b348 100644 --- a/llvm/test/Transforms/InstCombine/catchswitch-phi.ll +++ b/llvm/test/Transforms/InstCombine/catchswitch-phi.ll @@ -24,11 +24,11 @@ define void @test0(i1 %c1) personality ptr @__gxx_wasm_personality_v0 { ; CHECK: bb1: ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i32 4 ; CHECK-NEXT: invoke void @foo() -; CHECK-NEXT: to label [[BB3:%.*]] unwind label [[BB4:%.*]] +; CHECK-NEXT: to label [[BB3:%.*]] unwind label [[BB4:%.*]] ; CHECK: bb2: ; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i32 4 ; CHECK-NEXT: invoke void @foo() -; CHECK-NEXT: to label [[BB3]] unwind label [[BB4]] +; CHECK-NEXT: to label [[BB3]] unwind label [[BB4]] ; CHECK: bb3: ; CHECK-NEXT: unreachable ; CHECK: bb4: @@ -37,7 +37,7 @@ define void @test0(i1 %c1) personality ptr @__gxx_wasm_personality_v0 { ; CHECK: bb5: ; CHECK-NEXT: [[TMP5:%.*]] = catchpad within [[TMP4]] [ptr null] ; CHECK-NEXT: invoke void @foo() [ "funclet"(token [[TMP5]]) ] -; CHECK-NEXT: to label [[BB6:%.*]] unwind label [[BB7]] +; CHECK-NEXT: to label [[BB6:%.*]] unwind label [[BB7]] ; CHECK: bb6: ; CHECK-NEXT: unreachable ; CHECK: bb7: @@ -89,10 +89,10 @@ define void @test1() personality ptr @__gxx_wasm_personality_v0 { ; CHECK-LABEL: @test1( ; CHECK-NEXT: entry: ; CHECK-NEXT: invoke void @foo() -; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[CATCH_DISPATCH1:%.*]] +; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[CATCH_DISPATCH1:%.*]] ; CHECK: invoke.cont: ; CHECK-NEXT: [[CALL:%.*]] = invoke i32 @baz() -; CHECK-NEXT: to label [[INVOKE_CONT1:%.*]] unwind label [[CATCH_DISPATCH:%.*]] +; CHECK-NEXT: to label [[INVOKE_CONT1:%.*]] unwind label [[CATCH_DISPATCH:%.*]] ; CHECK: invoke.cont1: ; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[CALL]], 0 ; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] @@ -101,7 +101,7 @@ define void @test1() personality ptr @__gxx_wasm_personality_v0 { ; CHECK: if.end: ; CHECK-NEXT: [[AP_0:%.*]] = phi i8 [ 1, [[IF_THEN]] ], [ 0, [[INVOKE_CONT1]] ] ; CHECK-NEXT: invoke void @foo() -; CHECK-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[CATCH_DISPATCH]] +; CHECK-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[CATCH_DISPATCH]] ; CHECK: invoke.cont2: ; CHECK-NEXT: br label [[TRY_CONT:%.*]] ; CHECK: catch.dispatch: @@ -114,17 +114,16 @@ define void @test1() personality ptr @__gxx_wasm_personality_v0 { ; CHECK-NEXT: catchret from [[TMP1]] to label [[TRY_CONT]] ; CHECK: rethrow: ; CHECK-NEXT: invoke void @llvm.wasm.rethrow() #[[ATTR0:[0-9]+]] [ "funclet"(token [[TMP1]]) ] -; CHECK-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[CATCH_DISPATCH1]] +; CHECK-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[CATCH_DISPATCH1]] ; CHECK: catch.dispatch1: ; CHECK-NEXT: [[AP_2:%.*]] = phi i8 [ [[AP_1]], [[CATCH_DISPATCH]] ], [ [[AP_1]], [[RETHROW]] ], [ 0, [[ENTRY:%.*]] ] ; CHECK-NEXT: [[TMP2:%.*]] = catchswitch within none [label %catch.start1] unwind to caller ; CHECK: catch.start1: ; CHECK-NEXT: [[TMP3:%.*]] = catchpad within [[TMP2]] [ptr null] -; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[AP_2]], 1 -; CHECK-NEXT: [[TOBOOL1_NOT:%.*]] = icmp eq i8 [[TMP0]], 0 +; CHECK-NEXT: [[TOBOOL1_NOT:%.*]] = trunc i8 [[AP_2]] to i1 ; CHECK-NEXT: br i1 [[TOBOOL1_NOT]], label [[IF_END1:%.*]], label [[IF_THEN1:%.*]] ; CHECK: if.then1: -; CHECK-NEXT: br label [[IF_END1]] +; CHECK-NEXT: br label [[IF_THEN1]] ; CHECK: if.end1: ; CHECK-NEXT: catchret from [[TMP3]] to label [[TRY_CONT]] ; CHECK: try.cont: diff --git a/llvm/test/Transforms/InstCombine/copysign-fneg-fabs.ll b/llvm/test/Transforms/InstCombine/copysign-fneg-fabs.ll index af939cf74399abf3da96f41cf972a4ecf8876a45..a63eeab6a4b1e9ce608792b0e829b63632769063 100644 --- a/llvm/test/Transforms/InstCombine/copysign-fneg-fabs.ll +++ b/llvm/test/Transforms/InstCombine/copysign-fneg-fabs.ll @@ -275,6 +275,85 @@ define half @fneg_fabs_copysign_multi_use_fabs(half %x, half %y, ptr %ptr) { ret half %fabs.copysign } +define half @copysign_pos(half %a) { +; CHECK-LABEL: @copysign_pos( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RET:%.*]] = call half @llvm.copysign.f16(half 0xH3C00, half [[A:%.*]]) +; CHECK-NEXT: ret half [[RET]] +; +entry: + %ret = call half @llvm.copysign.f16(half 0xH3C00, half %a) + ret half %ret +} + +define half @copysign_neg(half %a) { +; CHECK-LABEL: @copysign_neg( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RET:%.*]] = call half @llvm.copysign.f16(half 0xH3C00, half [[A:%.*]]) +; CHECK-NEXT: ret half [[RET]] +; +entry: + %ret = call half @llvm.copysign.f16(half 0xHBC00, half %a) + ret half %ret +} + +define half @copysign_negzero(half %a) { +; CHECK-LABEL: @copysign_negzero( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RET:%.*]] = call half @llvm.copysign.f16(half 0xH0000, half [[A:%.*]]) +; CHECK-NEXT: ret half [[RET]] +; +entry: + %ret = call half @llvm.copysign.f16(half 0xH8000, half %a) + ret half %ret +} + +define half @copysign_negnan(half %a) { +; CHECK-LABEL: @copysign_negnan( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RET:%.*]] = call half @llvm.copysign.f16(half 0xH7E00, half [[A:%.*]]) +; CHECK-NEXT: ret half [[RET]] +; +entry: + %ret = call half @llvm.copysign.f16(half 0xHFE00, half %a) + ret half %ret +} + +define half @copysign_neginf(half %a) { +; CHECK-LABEL: @copysign_neginf( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RET:%.*]] = call half @llvm.copysign.f16(half 0xH7C00, half [[A:%.*]]) +; CHECK-NEXT: ret half [[RET]] +; +entry: + %ret = call half @llvm.copysign.f16(half 0xHFC00, half %a) + ret half %ret +} + +define <4 x half> @copysign_splat(<4 x half> %a) { +; CHECK-LABEL: @copysign_splat( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RET:%.*]] = call <4 x half> @llvm.copysign.v4f16(<4 x half> <half 0xH3C00, half 0xH3C00, half 0xH3C00, half 0xH3C00>, <4 x half> [[A:%.*]]) +; CHECK-NEXT: ret <4 x half> [[RET]] +; +entry: + %ret = call <4 x half> @llvm.copysign.v4f16(<4 x half> splat(half 0xHBC00), <4 x half> %a) + ret <4 x half> %ret +} + +; TODO: Support constant folding of fabs + +define <4 x half> @copysign_vec4(<4 x half> %a) { +; CHECK-LABEL: @copysign_vec4( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RET:%.*]] = call <4 x half> @llvm.copysign.v4f16(<4 x half> <half 0xH3C00, half 0xHBC00, half undef, half poison>, <4 x half> [[A:%.*]]) +; CHECK-NEXT: ret <4 x half> [[RET]] +; +entry: + %ret = call <4 x half> @llvm.copysign.v4f16(<4 x half> <half 0xH3C00, half 0xHBC00, half undef, half poison>, <4 x half> %a) + ret <4 x half> %ret +} + declare half @llvm.fabs.f16(half) declare <2 x half> @llvm.fabs.v2f16(<2 x half>) declare half @llvm.copysign.f16(half, half) diff --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll index 1309dee817cf6595c6ce694c99471c1b17c9acb9..e8a25ff44d02966709758005d465d88dcf71b9cb 100644 --- a/llvm/test/Transforms/InstCombine/div.ll +++ b/llvm/test/Transforms/InstCombine/div.ll @@ -1810,3 +1810,25 @@ define i6 @udiv_distribute_mul_nsw_add_nuw(i6 %x) { %div = udiv i6 %add, 3 ret i6 %div } + +define i32 @fold_disjoint_or_over_sdiv(i32 %x) { +; CHECK-LABEL: @fold_disjoint_or_over_sdiv( +; CHECK-NEXT: [[R:%.*]] = add nsw i32 [[X:%.*]], 9 +; CHECK-NEXT: ret i32 [[R]] +; + %mul = mul nsw i32 %x, 9 + %or = or disjoint i32 %mul, 81 + %r = sdiv i32 %or, 9 + ret i32 %r +} + +define i32 @fold_disjoint_or_over_udiv(i32 %x) { +; CHECK-LABEL: @fold_disjoint_or_over_udiv( +; CHECK-NEXT: [[R:%.*]] = add nuw i32 [[X:%.*]], 9 +; CHECK-NEXT: ret i32 [[R]] +; + %mul = mul nuw i32 %x, 9 + %or = or disjoint i32 %mul, 81 + %r = udiv i32 %or, 9 + ret i32 %r +} diff --git a/llvm/test/Transforms/InstCombine/extract-select-agg.ll b/llvm/test/Transforms/InstCombine/extract-select-agg.ll new file mode 100644 index 0000000000000000000000000000000000000000..6ba6b1a575601d0f2b63a1b489425a1db0139946 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/extract-select-agg.ll @@ -0,0 +1,83 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +define i64 @test_select_agg_constant_agg(i64 %val, i1 %cond) { +; CHECK-LABEL: define i64 @test_select_agg_constant_agg( +; CHECK-SAME: i64 [[VAL:%.*]], i1 [[COND:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RET:%.*]] = zext i1 [[COND]] to i64 +; CHECK-NEXT: ret i64 [[RET]] +; +entry: + %sel = select i1 %cond, { i64, i64 } {i64 1, i64 2}, { i64, i64 } {i64 0, i64 3} + %ret = extractvalue { i64, i64 } %sel, 0 + ret i64 %ret +} + +define void @test_select_agg_constant_agg_multiuse(i64 %val, i1 %cond) { +; CHECK-LABEL: define void @test_select_agg_constant_agg_multiuse( +; CHECK-SAME: i64 [[VAL:%.*]], i1 [[COND:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RET:%.*]] = zext i1 [[COND]] to i64 +; CHECK-NEXT: call void @use(i64 [[RET]]) +; CHECK-NEXT: [[V1:%.*]] = select i1 [[COND]], i64 2, i64 3 +; CHECK-NEXT: call void @use(i64 [[V1]]) +; CHECK-NEXT: ret void +; +entry: + %sel = select i1 %cond, { i64, i64 } {i64 1, i64 2}, { i64, i64 } {i64 0, i64 3} + %v0 = extractvalue { i64, i64 } %sel, 0 + call void @use(i64 %v0) + %v1 = extractvalue { i64, i64 } %sel, 1 + call void @use(i64 %v1) + ret void +} + +; TODO: it can be folded to zext i1 %cond to i64 +define i64 @test_select_agg_constant(i64 %val, i1 %cond) { +; CHECK-LABEL: define i64 @test_select_agg_constant( +; CHECK-SAME: i64 [[VAL:%.*]], i1 [[COND:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = insertvalue { i64, i64 } { i64 1, i64 poison }, i64 [[VAL]], 1 +; CHECK-NEXT: [[B:%.*]] = insertvalue { i64, i64 } { i64 0, i64 poison }, i64 [[VAL]], 1 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], { i64, i64 } [[A]], { i64, i64 } [[B]] +; CHECK-NEXT: [[RET:%.*]] = extractvalue { i64, i64 } [[SEL]], 0 +; CHECK-NEXT: ret i64 [[RET]] +; +entry: + %a = insertvalue { i64, i64 } { i64 1, i64 poison }, i64 %val, 1 + %b = insertvalue { i64, i64 } { i64 0, i64 poison }, i64 %val, 1 + %sel = select i1 %cond, { i64, i64 } %a, { i64, i64 } %b + %ret = extractvalue { i64, i64 } %sel, 0 + ret i64 %ret +} + +define void @test_select_agg_multiuse(i1 %cond, i64 %v1, i64 %v2, i64 %v3, i64 %v4) { +; CHECK-LABEL: define void @test_select_agg_multiuse( +; CHECK-SAME: i1 [[COND:%.*]], i64 [[V1:%.*]], i64 [[V2:%.*]], i64 [[V3:%.*]], i64 [[V4:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A0:%.*]] = insertvalue { i64, i64 } poison, i64 [[V1]], 0 +; CHECK-NEXT: [[A1:%.*]] = insertvalue { i64, i64 } [[A0]], i64 [[V2]], 1 +; CHECK-NEXT: [[B0:%.*]] = insertvalue { i64, i64 } poison, i64 [[V3]], 0 +; CHECK-NEXT: [[B1:%.*]] = insertvalue { i64, i64 } [[B0]], i64 [[V4]], 1 +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], { i64, i64 } [[A1]], { i64, i64 } [[B1]] +; CHECK-NEXT: [[X:%.*]] = extractvalue { i64, i64 } [[SEL]], 0 +; CHECK-NEXT: call void @use(i64 [[X]]) +; CHECK-NEXT: [[Y:%.*]] = extractvalue { i64, i64 } [[SEL]], 1 +; CHECK-NEXT: call void @use(i64 [[Y]]) +; CHECK-NEXT: ret void +; +entry: + %a0 = insertvalue { i64, i64 } poison, i64 %v1, 0 + %a1 = insertvalue { i64, i64 } %a0, i64 %v2, 1 + %b0 = insertvalue { i64, i64 } poison, i64 %v3, 0 + %b1 = insertvalue { i64, i64 } %b0, i64 %v4, 1 + %sel = select i1 %cond, { i64, i64 } %a1, { i64, i64 } %b1 + %x = extractvalue { i64, i64 } %sel, 0 + call void @use(i64 %x) + %y = extractvalue { i64, i64 } %sel, 1 + call void @use(i64 %y) + ret void +} + +declare void @use(i64) diff --git a/llvm/test/Transforms/InstCombine/fcmp.ll b/llvm/test/Transforms/InstCombine/fcmp.ll index 159c84d0dd8aa916c9978209e4f830447bc9216c..f2701d16d0f3d1a6a4638f4c4d334cb357f5be33 100644 --- a/llvm/test/Transforms/InstCombine/fcmp.ll +++ b/llvm/test/Transforms/InstCombine/fcmp.ll @@ -644,7 +644,7 @@ define <2 x i1> @is_signbit_set_anyzero(<2 x double> %x) { define i1 @is_signbit_clear(double %x) { ; CHECK-LABEL: @is_signbit_clear( -; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double -4.200000e+01, double [[X:%.*]]) +; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 4.200000e+01, double [[X:%.*]]) ; CHECK-NEXT: [[R:%.*]] = fcmp ogt double [[S]], 0.000000e+00 ; CHECK-NEXT: ret i1 [[R]] ; @@ -655,7 +655,7 @@ define i1 @is_signbit_clear(double %x) { define i1 @is_signbit_clear_1(double %x) { ; CHECK-LABEL: @is_signbit_clear_1( -; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double -4.200000e+01, double [[X:%.*]]) +; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 4.200000e+01, double [[X:%.*]]) ; CHECK-NEXT: [[R:%.*]] = fcmp ugt double [[S]], 0.000000e+00 ; CHECK-NEXT: ret i1 [[R]] ; @@ -666,7 +666,7 @@ define i1 @is_signbit_clear_1(double %x) { define i1 @is_signbit_clear_2(double %x) { ; CHECK-LABEL: @is_signbit_clear_2( -; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double -4.200000e+01, double [[X:%.*]]) +; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 4.200000e+01, double [[X:%.*]]) ; CHECK-NEXT: [[R:%.*]] = fcmp oge double [[S]], 0.000000e+00 ; CHECK-NEXT: ret i1 [[R]] ; @@ -677,7 +677,7 @@ define i1 @is_signbit_clear_2(double %x) { define i1 @is_signbit_clear_3(double %x) { ; CHECK-LABEL: @is_signbit_clear_3( -; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double -4.200000e+01, double [[X:%.*]]) +; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 4.200000e+01, double [[X:%.*]]) ; CHECK-NEXT: [[R:%.*]] = fcmp uge double [[S]], 0.000000e+00 ; CHECK-NEXT: ret i1 [[R]] ; @@ -705,7 +705,7 @@ define i1 @is_signbit_set_extra_use(double %x, ptr %p) { define i1 @is_signbit_clear_nonzero(double %x) { ; CHECK-LABEL: @is_signbit_clear_nonzero( -; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double -4.200000e+01, double [[X:%.*]]) +; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 4.200000e+01, double [[X:%.*]]) ; CHECK-NEXT: [[R:%.*]] = fcmp ogt double [[S]], 1.000000e+00 ; CHECK-NEXT: ret i1 [[R]] ; diff --git a/llvm/test/Transforms/InstCombine/fmul.ll b/llvm/test/Transforms/InstCombine/fmul.ll index 7e7373e6ef5bdd9b1fdc13c49d9b273af81e8e0a..f6435f0032891ef0a6cfcf4cc5d87817dac2d332 100644 --- a/llvm/test/Transforms/InstCombine/fmul.ll +++ b/llvm/test/Transforms/InstCombine/fmul.ll @@ -1093,11 +1093,11 @@ for.body: define double @fmul_negated_constant_expression(double %x) { ; CHECK-LABEL: @fmul_negated_constant_expression( -; CHECK-NEXT: [[FSUB:%.*]] = fneg double bitcast (i64 ptrtoint (ptr getelementptr inbounds ({ [2 x ptr] }, ptr @g, i64 0, inrange i32 0, i64 2) to i64) to double) +; CHECK-NEXT: [[FSUB:%.*]] = fneg double bitcast (i64 ptrtoint (ptr getelementptr inbounds ({ [2 x ptr] }, ptr @g, i64 1, i32 0, i64 0) to i64) to double) ; CHECK-NEXT: [[R:%.*]] = fmul double [[FSUB]], [[X:%.*]] ; CHECK-NEXT: ret double [[R]] ; - %fsub = fsub double -0.000000e+00, bitcast (i64 ptrtoint (ptr getelementptr inbounds ({ [2 x ptr] }, ptr @g, i64 0, inrange i32 0, i64 2) to i64) to double) + %fsub = fsub double -0.000000e+00, bitcast (i64 ptrtoint (ptr getelementptr inbounds ({ [2 x ptr] }, ptr @g, i64 0, i32 0, i64 2) to i64) to double) %r = fmul double %x, %fsub ret double %r } @@ -1250,7 +1250,7 @@ define half @mul_zero_nnan(half %x) { define <2 x float> @mul_zero_nnan_vec_poison(<2 x float> %x) { ; CHECK-LABEL: @mul_zero_nnan_vec_poison( -; CHECK-NEXT: [[R:%.*]] = call nnan <2 x float> @llvm.copysign.v2f32(<2 x float> <float 0.000000e+00, float poison>, <2 x float> [[X:%.*]]) +; CHECK-NEXT: [[R:%.*]] = call nnan <2 x float> @llvm.copysign.v2f32(<2 x float> zeroinitializer, <2 x float> [[X:%.*]]) ; CHECK-NEXT: ret <2 x float> [[R]] ; %r = fmul nnan <2 x float> %x, <float 0.0, float poison> @@ -1268,13 +1268,104 @@ define half @mul_zero(half %x) { ret half %r } -; TODO: This could be fneg+copysign. - define half @mul_negzero_nnan(half %x) { ; CHECK-LABEL: @mul_negzero_nnan( -; CHECK-NEXT: [[R:%.*]] = fmul nnan half [[X:%.*]], 0xH8000 +; CHECK-NEXT: [[TMP1:%.*]] = fneg nnan half [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = call nnan half @llvm.copysign.f16(half 0xH0000, half [[TMP1]]) ; CHECK-NEXT: ret half [[R]] ; %r = fmul nnan half %x, -0.0 ret half %r } + +define float @mul_pos_zero_nnan_ninf(float nofpclass(inf nan) %a) { +; CHECK-LABEL: @mul_pos_zero_nnan_ninf( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RET:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[A:%.*]]) +; CHECK-NEXT: ret float [[RET]] +; +entry: + %ret = fmul float %a, 0.000000e+00 + ret float %ret +} + +define float @mul_pos_zero_nnan(float nofpclass(nan) %a) { +; CHECK-LABEL: @mul_pos_zero_nnan( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RET:%.*]] = fmul float [[A:%.*]], 0.000000e+00 +; CHECK-NEXT: ret float [[RET]] +; +entry: + %ret = fmul float %a, 0.000000e+00 + ret float %ret +} + +define float @mul_pos_zero_nnan_ninf_fmf(float nofpclass(nan) %a) { +; CHECK-LABEL: @mul_pos_zero_nnan_ninf_fmf( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RET:%.*]] = call ninf float @llvm.copysign.f32(float 0.000000e+00, float [[A:%.*]]) +; CHECK-NEXT: ret float [[RET]] +; +entry: + %ret = fmul ninf float %a, 0.000000e+00 + ret float %ret +} + +define float @mul_neg_zero_nnan_ninf(float nofpclass(inf nan) %a) { +; CHECK-LABEL: @mul_neg_zero_nnan_ninf( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = fneg float [[A:%.*]] +; CHECK-NEXT: [[RET:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[TMP0]]) +; CHECK-NEXT: ret float [[RET]] +; +entry: + %ret = fmul float %a, -0.000000e+00 + ret float %ret +} + +define float @mul_neg_zero_nnan_fmf(float %a) { +; CHECK-LABEL: @mul_neg_zero_nnan_fmf( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = fneg nnan float [[A:%.*]] +; CHECK-NEXT: [[RET:%.*]] = call nnan float @llvm.copysign.f32(float 0.000000e+00, float [[TMP0]]) +; CHECK-NEXT: ret float [[RET]] +; +entry: + %ret = fmul nnan float %a, -0.000000e+00 + ret float %ret +} + +define float @mul_neg_zero_nnan_ninf_fmf(float nofpclass(inf nan) %a) { +; CHECK-LABEL: @mul_neg_zero_nnan_ninf_fmf( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = fneg nnan ninf float [[A:%.*]] +; CHECK-NEXT: [[RET:%.*]] = call nnan ninf float @llvm.copysign.f32(float 0.000000e+00, float [[TMP0]]) +; CHECK-NEXT: ret float [[RET]] +; +entry: + %ret = fmul nnan ninf float %a, -0.000000e+00 + ret float %ret +} + +define <3 x float> @mul_neg_zero_nnan_ninf_vec(<3 x float> nofpclass(inf nan) %a) { +; CHECK-LABEL: @mul_neg_zero_nnan_ninf_vec( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = fneg <3 x float> [[A:%.*]] +; CHECK-NEXT: [[RET:%.*]] = call <3 x float> @llvm.copysign.v3f32(<3 x float> zeroinitializer, <3 x float> [[TMP0]]) +; CHECK-NEXT: ret <3 x float> [[RET]] +; +entry: + %ret = fmul <3 x float> %a, <float -0.0, float undef, float poison> + ret <3 x float> %ret +} + +define <3 x float> @mul_mixed_zero_nnan_ninf_vec(<3 x float> nofpclass(inf nan) %a) { +; CHECK-LABEL: @mul_mixed_zero_nnan_ninf_vec( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RET:%.*]] = fmul <3 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00, float poison> +; CHECK-NEXT: ret <3 x float> [[RET]] +; +entry: + %ret = fmul <3 x float> %a, <float -0.0, float 0.0, float poison> + ret <3 x float> %ret +} diff --git a/llvm/test/Transforms/InstCombine/fold-select-fmul-if-zero.ll b/llvm/test/Transforms/InstCombine/fold-select-fmul-if-zero.ll index a7adcd1ac61e7f60e53cca89c46fb67fb6415eff..dedd12f8cc7a3d08ef8af5e02512317887beb3ed 100644 --- a/llvm/test/Transforms/InstCombine/fold-select-fmul-if-zero.ll +++ b/llvm/test/Transforms/InstCombine/fold-select-fmul-if-zero.ll @@ -427,13 +427,13 @@ define float @fmul_by_snan_if_0_oeq_zero_f32(float %x) { define float @fmul_by_var_if_0_oeq_zero_f32(float %x, float %y) { ; CHECK-LABEL: @fmul_by_var_if_0_oeq_zero_f32( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul float [[SCALED_X]], [[X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; %x.is.zero = fcmp oeq float %x, 0.0 %scaled.x = fmul float %x, %y - %scaled.if.denormal = select i1 %x.is.zero, float %scaled.x, float %x + %scaled.if.denormal = select nnan i1 %x.is.zero, float %scaled.x, float %x ret float %scaled.if.denormal } @@ -441,14 +441,14 @@ define float @fmul_by_fabs_var_if_0_oeq_zero_f32(float %x, float %y) { ; CHECK-LABEL: @fmul_by_fabs_var_if_0_oeq_zero_f32( ; CHECK-NEXT: [[Y_FABS:%.*]] = call float @llvm.fabs.f32(float [[Y:%.*]]) ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select i1 [[X_IS_ZERO]], float [[Y_FABS]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[Y_FABS]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul float [[SCALED_X]], [[X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; %y.fabs = call float @llvm.fabs.f32(float %y) %x.is.zero = fcmp oeq float %x, 0.0 %scaled.x = fmul float %x, %y.fabs - %scaled.if.denormal = select i1 %x.is.zero, float %scaled.x, float %x + %scaled.if.denormal = select nnan i1 %x.is.zero, float %scaled.x, float %x ret float %scaled.if.denormal } @@ -467,13 +467,13 @@ define float @fmul_by_fabs_nnan_ninf_var_if_0_oeq_zero_f32(float %x, float %y) { define float @fmul_by_var_if_0_oeq_zero_f32_nsz_fmul(float %x, float %y) { ; CHECK-LABEL: @fmul_by_var_if_0_oeq_zero_f32_nsz_fmul( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul nsz float [[SCALED_X]], [[X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; %x.is.zero = fcmp oeq float %x, 0.0 %scaled.x = fmul nsz float %x, %y - %scaled.if.denormal = select i1 %x.is.zero, float %scaled.x, float %x + %scaled.if.denormal = select nnan i1 %x.is.zero, float %scaled.x, float %x ret float %scaled.if.denormal } @@ -481,13 +481,13 @@ define float @fmul_by_var_if_0_oeq_zero_f32_nsz_fmul(float %x, float %y) { define float @fmul_by_var_if_0_oeq_zero_f32_nsz_ninf_fmul(float %x, float %y) { ; CHECK-LABEL: @fmul_by_var_if_0_oeq_zero_f32_nsz_ninf_fmul( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul ninf nsz float [[SCALED_X]], [[X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; %x.is.zero = fcmp oeq float %x, 0.0 %scaled.x = fmul nsz ninf float %x, %y - %scaled.if.denormal = select i1 %x.is.zero, float %scaled.x, float %x + %scaled.if.denormal = select nnan i1 %x.is.zero, float %scaled.x, float %x ret float %scaled.if.denormal } @@ -495,13 +495,13 @@ define float @fmul_by_var_if_0_oeq_zero_f32_nsz_ninf_fmul(float %x, float %y) { define float @fmul_by_var_if_0_oeq_zero_f32_nsz_nnan_fmul(float %x, float %y) { ; CHECK-LABEL: @fmul_by_var_if_0_oeq_zero_f32_nsz_nnan_fmul( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul nnan nsz float [[SCALED_X]], [[X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; %x.is.zero = fcmp oeq float %x, 0.0 %scaled.x = fmul nsz nnan float %x, %y - %scaled.if.denormal = select i1 %x.is.zero, float %scaled.x, float %x + %scaled.if.denormal = select nnan i1 %x.is.zero, float %scaled.x, float %x ret float %scaled.if.denormal } @@ -509,13 +509,13 @@ define float @fmul_by_var_if_0_oeq_zero_f32_nsz_nnan_fmul(float %x, float %y) { define float @fmul_by_var_if_0_oeq_zero_f32_nnan_ninf_fmul(float %x, float %y) { ; CHECK-LABEL: @fmul_by_var_if_0_oeq_zero_f32_nnan_ninf_fmul( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul nnan ninf float [[SCALED_X]], [[X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; %x.is.zero = fcmp oeq float %x, 0.0 %scaled.x = fmul nnan ninf float %x, %y - %scaled.if.denormal = select i1 %x.is.zero, float %scaled.x, float %x + %scaled.if.denormal = select nnan i1 %x.is.zero, float %scaled.x, float %x ret float %scaled.if.denormal } @@ -558,26 +558,26 @@ define float @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_select_nsz_inverted(f define float @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_nsz(float %x, float %y) { ; CHECK-LABEL: @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_nsz( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul nnan ninf nsz float [[SCALED_X]], [[X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; %x.is.zero = fcmp oeq float %x, 0.0 %scaled.x = fmul nnan ninf nsz float %x, %y - %scaled.if.denormal = select i1 %x.is.zero, float %scaled.x, float %x + %scaled.if.denormal = select nnan i1 %x.is.zero, float %scaled.x, float %x ret float %scaled.if.denormal } define float @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_nsz_commuted(float %x, float %y) { ; CHECK-LABEL: @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_nsz_commuted( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul nnan ninf nsz float [[SCALED_X]], [[X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; %x.is.zero = fcmp oeq float %x, 0.0 %scaled.x = fmul nnan ninf nsz float %y, %x - %scaled.if.denormal = select i1 %x.is.zero, float %scaled.x, float %x + %scaled.if.denormal = select nnan i1 %x.is.zero, float %scaled.x, float %x ret float %scaled.if.denormal } @@ -585,26 +585,26 @@ define float @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_nsz_commuted(float %x define float @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_select_known_never_negzero(float %x, float nofpclass(nzero) %y) { ; CHECK-LABEL: @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_select_known_never_negzero( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul nnan ninf float [[SCALED_X]], [[X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; %x.is.zero = fcmp oeq float %x, 0.0 %scaled.x = fmul nnan ninf float %x, %y - %scaled.if.denormal = select i1 %x.is.zero, float %scaled.x, float %x + %scaled.if.denormal = select nnan i1 %x.is.zero, float %scaled.x, float %x ret float %scaled.if.denormal } define float @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_select_known_never_negzero_negsub(float %x, float nofpclass(nzero nsub) %y) { ; CHECK-LABEL: @fmul_by_var_if_0_oeq_zero_f32_fmul_nnan_ninf_select_known_never_negzero_negsub( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul nnan ninf float [[SCALED_X]], [[X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; %x.is.zero = fcmp oeq float %x, 0.0 %scaled.x = fmul nnan ninf float %x, %y - %scaled.if.denormal = select i1 %x.is.zero, float %scaled.x, float %x + %scaled.if.denormal = select nnan i1 %x.is.zero, float %scaled.x, float %x ret float %scaled.if.denormal } @@ -622,26 +622,26 @@ define float @fmul_by_var_if_0_oeq_zero_f32_known_never_nan_inf_select_nsz(float define float @fmul_by_var_if_0_oeq_zero_f32_fmul_known_never_nan_inf_negzero(float %x, float nofpclass(nan inf nzero) %y) { ; CHECK-LABEL: @fmul_by_var_if_0_oeq_zero_f32_fmul_known_never_nan_inf_negzero( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul float [[SCALED_X]], [[X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; %x.is.zero = fcmp oeq float %x, 0.0 %scaled.x = fmul float %x, %y - %scaled.if.denormal = select i1 %x.is.zero, float %scaled.x, float %x + %scaled.if.denormal = select nnan i1 %x.is.zero, float %scaled.x, float %x ret float %scaled.if.denormal } define float @fmul_by_var_if_0_oeq_zero_f32_fmul_known_never_nan_inf_negzero_nsub(float %x, float nofpclass(nan inf nzero nsub) %y) { ; CHECK-LABEL: @fmul_by_var_if_0_oeq_zero_f32_fmul_known_never_nan_inf_negzero_nsub( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[Y:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul float [[SCALED_X]], [[X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; %x.is.zero = fcmp oeq float %x, 0.0 %scaled.x = fmul float %x, %y - %scaled.if.denormal = select i1 %x.is.zero, float %scaled.x, float %x + %scaled.if.denormal = select nnan i1 %x.is.zero, float %scaled.x, float %x ret float %scaled.if.denormal } @@ -692,26 +692,26 @@ define float @fmul_by_var_if_not_one_0_zero_f32_assume_finite_fmul_nsz(float %x, define float @fmul_by_self_if_0_oeq_zero_f32(float %x) { ; CHECK-LABEL: @fmul_by_self_if_0_oeq_zero_f32( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select i1 [[X_IS_ZERO]], float [[X]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[X]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul float [[SCALED_X]], [[X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; %x.is.zero = fcmp oeq float %x, 0.0 %scaled.x = fmul float %x, %x - %scaled.if.denormal = select i1 %x.is.zero, float %scaled.x, float %x + %scaled.if.denormal = select nnan i1 %x.is.zero, float %scaled.x, float %x ret float %scaled.if.denormal } define float @fmul_by_self_if_0_oeq_zero_f32_fmul_nnan_ninf_nsz(float %x) { ; CHECK-LABEL: @fmul_by_self_if_0_oeq_zero_f32_fmul_nnan_ninf_nsz( ; CHECK-NEXT: [[X_IS_ZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 -; CHECK-NEXT: [[SCALED_X:%.*]] = select i1 [[X_IS_ZERO]], float [[X]], float 1.000000e+00 +; CHECK-NEXT: [[SCALED_X:%.*]] = select nnan i1 [[X_IS_ZERO]], float [[X]], float 1.000000e+00 ; CHECK-NEXT: [[SCALED_IF_DENORMAL:%.*]] = fmul nnan ninf nsz float [[SCALED_X]], [[X]] ; CHECK-NEXT: ret float [[SCALED_IF_DENORMAL]] ; %x.is.zero = fcmp oeq float %x, 0.0 %scaled.x = fmul nnan ninf nsz float %x, %x - %scaled.if.denormal = select i1 %x.is.zero, float %scaled.x, float %x + %scaled.if.denormal = select nnan i1 %x.is.zero, float %scaled.x, float %x ret float %scaled.if.denormal } diff --git a/llvm/test/Transforms/InstCombine/fpcast.ll b/llvm/test/Transforms/InstCombine/fpcast.ll index 3e5c6fd20b12dac51e8a4cc5e4b5224ed77ad6b0..ac4b88fcddd7ec71f36467a9d7ce2ae895869a01 100644 --- a/llvm/test/Transforms/InstCombine/fpcast.ll +++ b/llvm/test/Transforms/InstCombine/fpcast.ll @@ -347,3 +347,88 @@ define double @masked_uint_to_fpext3(i32 %x) { %r = fpext float %f to double ret double %r } + +define i32 @fptosi_nonnorm(float nofpclass(norm) %x) { +; CHECK-LABEL: @fptosi_nonnorm( +; CHECK-NEXT: ret i32 0 +; + %ret = fptosi float %x to i32 + ret i32 %ret +} + +define i32 @fptoui_nonnorm(float nofpclass(pnorm) %x) { +; CHECK-LABEL: @fptoui_nonnorm( +; CHECK-NEXT: ret i32 0 +; + %ret = fptoui float %x to i32 + ret i32 %ret +} + +define i32 @fptosi_nonnnorm(float nofpclass(nnorm) %x) { +; CHECK-LABEL: @fptosi_nonnnorm( +; CHECK-NEXT: [[RET:%.*]] = fptosi float [[X:%.*]] to i32 +; CHECK-NEXT: ret i32 [[RET]] +; + %ret = fptosi float %x to i32 + ret i32 %ret +} + +define i32 @fptoui_nonnnorm(float nofpclass(nnorm) %x) { +; CHECK-LABEL: @fptoui_nonnnorm( +; CHECK-NEXT: [[RET:%.*]] = fptoui float [[X:%.*]] to i32 +; CHECK-NEXT: ret i32 [[RET]] +; + %ret = fptoui float %x to i32 + ret i32 %ret +} + +define i32 @fptosi_nonnorm_copysign(float %x) { +; CHECK-LABEL: @fptosi_nonnorm_copysign( +; CHECK-NEXT: ret i32 0 +; + %val = call float @llvm.copysign.f32(float 0.0, float %x) + %ret = fptosi float %val to i32 + ret i32 %ret +} + +define <2 x i32> @fptosi_nonnorm_copysign_vec(<2 x float> %x) { +; CHECK-LABEL: @fptosi_nonnorm_copysign_vec( +; CHECK-NEXT: ret <2 x i32> zeroinitializer +; + %val = call <2 x float> @llvm.copysign.v2f32(<2 x float> zeroinitializer, <2 x float> %x) + %ret = fptosi <2 x float> %val to <2 x i32> + ret <2 x i32> %ret +} + +define i32 @fptosi_nonnorm_fmul(float %x) { +; CHECK-LABEL: @fptosi_nonnorm_fmul( +; CHECK-NEXT: [[SEL:%.*]] = fmul float [[X:%.*]], 0.000000e+00 +; CHECK-NEXT: [[RET:%.*]] = fptosi float [[SEL]] to i32 +; CHECK-NEXT: ret i32 [[RET]] +; + %sel = fmul float %x, 0.000000e+00 + %ret = fptosi float %sel to i32 + ret i32 %ret +} + +define i32 @fptosi_select(i1 %cond) { +; CHECK-LABEL: @fptosi_select( +; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND:%.*]], i32 1, i32 -1 +; CHECK-NEXT: ret i32 [[RET]] +; + %sel = select i1 %cond, float 1.0, float -1.0 + %ret = fptosi float %sel to i32 + ret i32 %ret +} + +define i32 @mul_pos_zero_convert(i32 %a) { +; CHECK-LABEL: @mul_pos_zero_convert( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret i32 0 +; +entry: + %fp = sitofp i32 %a to float + %ret = fmul float %fp, 0.000000e+00 + %conv = fptosi float %ret to i32 + ret i32 %conv +} diff --git a/llvm/test/Transforms/InstCombine/freeze.ll b/llvm/test/Transforms/InstCombine/freeze.ll index da59101d5710cb513049ed335841a4047c67ac14..e8105b6287d0c5376d0cf718f97987c403d4125c 100644 --- a/llvm/test/Transforms/InstCombine/freeze.ll +++ b/llvm/test/Transforms/InstCombine/freeze.ll @@ -1049,7 +1049,7 @@ exit: define ptr @freeze_load_noundef(ptr %ptr) { ; CHECK-LABEL: @freeze_load_noundef( -; CHECK-NEXT: [[P:%.*]] = load ptr, ptr [[PTR:%.*]], align 8, !noundef !0 +; CHECK-NEXT: [[P:%.*]] = load ptr, ptr [[PTR:%.*]], align 8, !noundef [[META0:![0-9]+]] ; CHECK-NEXT: ret ptr [[P]] ; %p = load ptr, ptr %ptr, !noundef !0 @@ -1059,7 +1059,7 @@ define ptr @freeze_load_noundef(ptr %ptr) { define ptr @freeze_load_dereferenceable(ptr %ptr) { ; CHECK-LABEL: @freeze_load_dereferenceable( -; CHECK-NEXT: [[P:%.*]] = load ptr, ptr [[PTR:%.*]], align 8, !dereferenceable !1 +; CHECK-NEXT: [[P:%.*]] = load ptr, ptr [[PTR:%.*]], align 8, !dereferenceable [[META1:![0-9]+]] ; CHECK-NEXT: ret ptr [[P]] ; %p = load ptr, ptr %ptr, !dereferenceable !1 @@ -1138,6 +1138,17 @@ define i32 @propagate_drop_flags_or(i32 %arg) { ret i32 %v1.fr } +define i32 @propagate_drop_flags_trunc(i64 %arg) { +; CHECK-LABEL: @propagate_drop_flags_trunc( +; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i64 [[ARG:%.*]] +; CHECK-NEXT: [[V1:%.*]] = trunc i64 [[ARG_FR]] to i32 +; CHECK-NEXT: ret i32 [[V1]] +; + %v1 = trunc nsw nuw i64 %arg to i32 + %v1.fr = freeze i32 %v1 + ret i32 %v1.fr +} + !0 = !{} !1 = !{i64 4} !2 = !{i32 0, i32 100} @@ -1145,8 +1156,8 @@ define i32 @propagate_drop_flags_or(i32 %arg) { ; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } ; CHECK: attributes #[[ATTR1]] = { nounwind } ;. -; CHECK: [[META0:![0-9]+]] = !{} -; CHECK: [[META1:![0-9]+]] = !{i64 4} +; CHECK: [[META0]] = !{} +; CHECK: [[META1]] = !{i64 4} ; CHECK: [[RNG2]] = !{i32 0, i32 100} ; CHECK: [[RNG3]] = !{i32 0, i32 33} ;. diff --git a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll index 07060922895846db74afbc18adc014aaa68d2051..5de3e89d7027abca78bba46aad57b22acec89e0f 100644 --- a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll +++ b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll @@ -226,12 +226,11 @@ define i1 @src_is_mask_shl_lshr(i8 %x_in, i8 %y, i1 %cond) { define i1 @src_is_mask_shl_lshr_fail_not_allones(i8 %x_in, i8 %y, i1 %cond) { ; CHECK-LABEL: @src_is_mask_shl_lshr_fail_not_allones( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 -1, [[Y:%.*]] ; CHECK-NEXT: [[MASK:%.*]] = and i8 [[TMP1]], -2 -; CHECK-NEXT: [[NOTMASK:%.*]] = xor i8 [[MASK]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[NOTMASK]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[AND]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[X_IN:%.*]], -124 +; CHECK-NEXT: [[TMP3:%.*]] = or i8 [[TMP2]], [[MASK]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP3]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -471,6 +470,24 @@ define i1 @src_is_notmask_x_xor_neg_x(i8 %x_in, i8 %y, i1 %cond) { ret i1 %r } +define i1 @src_is_notmask_x_xor_neg_x_inv(i8 %x_in, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_is_notmask_x_xor_neg_x_inv( +; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 +; CHECK-NEXT: [[NEG_Y:%.*]] = add i8 [[Y:%.*]], -1 +; CHECK-NEXT: [[NOTMASK0:%.*]] = xor i8 [[NEG_Y]], [[Y]] +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[COND:%.*]], i8 [[NOTMASK0]], i8 7 +; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[TMP3]] +; CHECK-NEXT: ret i1 [[R]] +; + %x = xor i8 %x_in, 123 + %neg_y = sub i8 0, %y + %nmask0 = xor i8 %y, %neg_y + %notmask = select i1 %cond, i8 %nmask0, i8 -8 + %and = and i8 %notmask, %x + %r = icmp eq i8 %and, 0 + ret i1 %r +} + define i1 @src_is_notmask_shl_fail_multiuse_invert(i8 %x_in, i8 %y, i1 %cond) { ; CHECK-LABEL: @src_is_notmask_shl_fail_multiuse_invert( ; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 122 @@ -572,11 +589,10 @@ define i1 @src_is_notmask_neg_p2(i8 %x_in, i8 %y) { define i1 @src_is_notmask_neg_p2_fail_not_invertable(i8 %x_in, i8 %y) { ; CHECK-LABEL: @src_is_notmask_neg_p2_fail_not_invertable( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 -; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], -1 -; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[Y]], -1 -; CHECK-NEXT: [[TMP3:%.*]] = and i8 [[TMP1]], [[TMP2]] -; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[X]], [[TMP3]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X_IN:%.*]], -124 +; CHECK-NEXT: [[TMP2:%.*]] = sub i8 0, [[Y:%.*]] +; CHECK-NEXT: [[TMP3:%.*]] = or i8 [[TMP2]], [[Y]] +; CHECK-NEXT: [[R:%.*]] = icmp uge i8 [[TMP1]], [[TMP3]] ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -657,3 +673,238 @@ define i1 @src_is_mask_const_sge(i8 %x_in) { %r = icmp sge i8 %and, %x ret i1 %r } + +define i1 @src_x_and_mask_slt(i8 %x, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_x_and_mask_slt( +; CHECK-NEXT: [[MASK0:%.*]] = lshr i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[MASK:%.*]] = select i1 [[COND:%.*]], i8 [[MASK0]], i8 0 +; CHECK-NEXT: [[MASK_POS:%.*]] = icmp sgt i8 [[MASK]], -1 +; CHECK-NEXT: call void @llvm.assume(i1 [[MASK_POS]]) +; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[MASK]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %mask0 = lshr i8 -1, %y + %mask = select i1 %cond, i8 %mask0, i8 0 + %mask_pos = icmp sge i8 %mask, 0 + call void @llvm.assume(i1 %mask_pos) + %and = and i8 %x, %mask + %r = icmp slt i8 %and, %x + ret i1 %r +} + +define i1 @src_x_and_mask_sge(i8 %x, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_x_and_mask_sge( +; CHECK-NEXT: [[MASK0:%.*]] = lshr i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[MASK:%.*]] = select i1 [[COND:%.*]], i8 [[MASK0]], i8 0 +; CHECK-NEXT: [[MASK_POS:%.*]] = icmp sgt i8 [[MASK]], -1 +; CHECK-NEXT: call void @llvm.assume(i1 [[MASK_POS]]) +; CHECK-NEXT: [[R:%.*]] = icmp sge i8 [[MASK]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %mask0 = lshr i8 -1, %y + %mask = select i1 %cond, i8 %mask0, i8 0 + %mask_pos = icmp sge i8 %mask, 0 + call void @llvm.assume(i1 %mask_pos) + %and = and i8 %x, %mask + %r = icmp sge i8 %and, %x + ret i1 %r +} + +define i1 @src_x_and_mask_slt_fail_maybe_neg(i8 %x, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_x_and_mask_slt_fail_maybe_neg( +; CHECK-NEXT: [[MASK0:%.*]] = lshr i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[MASK:%.*]] = select i1 [[COND:%.*]], i8 [[MASK0]], i8 0 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %mask0 = lshr i8 -1, %y + %mask = select i1 %cond, i8 %mask0, i8 0 + %and = and i8 %x, %mask + %r = icmp slt i8 %and, %x + ret i1 %r +} + +define i1 @src_x_and_mask_sge_fail_maybe_neg(i8 %x, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_x_and_mask_sge_fail_maybe_neg( +; CHECK-NEXT: [[MASK0:%.*]] = lshr i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[MASK:%.*]] = select i1 [[COND:%.*]], i8 [[MASK0]], i8 0 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[MASK]], [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sge i8 [[AND]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %mask0 = lshr i8 -1, %y + %mask = select i1 %cond, i8 %mask0, i8 0 + %and = and i8 %x, %mask + %r = icmp sge i8 %and, %x + ret i1 %r +} + +define i1 @src_x_and_nmask_eq(i8 %x, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_x_and_nmask_eq( +; CHECK-NEXT: [[NOT_MASK0:%.*]] = shl nsw i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[R1:%.*]] = icmp ule i8 [[NOT_MASK0]], [[X:%.*]] +; CHECK-NEXT: [[NOT_COND:%.*]] = xor i1 [[COND:%.*]], true +; CHECK-NEXT: [[R:%.*]] = select i1 [[NOT_COND]], i1 true, i1 [[R1]] +; CHECK-NEXT: ret i1 [[R]] +; + %not_mask0 = shl i8 -1, %y + %not_mask = select i1 %cond, i8 %not_mask0, i8 0 + %and = and i8 %x, %not_mask + %r = icmp eq i8 %not_mask, %and + ret i1 %r +} + +define i1 @src_x_and_nmask_ne(i8 %x, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_x_and_nmask_ne( +; CHECK-NEXT: [[NOT_MASK0:%.*]] = shl nsw i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[R1:%.*]] = icmp ugt i8 [[NOT_MASK0]], [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[COND:%.*]], i1 [[R1]], i1 false +; CHECK-NEXT: ret i1 [[R]] +; + %not_mask0 = shl i8 -1, %y + %not_mask = select i1 %cond, i8 %not_mask0, i8 0 + %and = and i8 %x, %not_mask + %r = icmp ne i8 %and, %not_mask + ret i1 %r +} + +define i1 @src_x_and_nmask_ult(i8 %x, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_x_and_nmask_ult( +; CHECK-NEXT: [[NOT_MASK0:%.*]] = shl nsw i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[R1:%.*]] = icmp ugt i8 [[NOT_MASK0]], [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[COND:%.*]], i1 [[R1]], i1 false +; CHECK-NEXT: ret i1 [[R]] +; + %not_mask0 = shl i8 -1, %y + %not_mask = select i1 %cond, i8 %not_mask0, i8 0 + %and = and i8 %x, %not_mask + %r = icmp ult i8 %and, %not_mask + ret i1 %r +} + +define i1 @src_x_and_nmask_uge(i8 %x, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_x_and_nmask_uge( +; CHECK-NEXT: [[NOT_MASK0:%.*]] = shl nsw i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[R1:%.*]] = icmp ule i8 [[NOT_MASK0]], [[X:%.*]] +; CHECK-NEXT: [[NOT_COND:%.*]] = xor i1 [[COND:%.*]], true +; CHECK-NEXT: [[R:%.*]] = select i1 [[NOT_COND]], i1 true, i1 [[R1]] +; CHECK-NEXT: ret i1 [[R]] +; + %not_mask0 = shl i8 -1, %y + %not_mask = select i1 %cond, i8 %not_mask0, i8 0 + %and = and i8 %x, %not_mask + %r = icmp uge i8 %and, %not_mask + ret i1 %r +} + +define i1 @src_x_and_nmask_slt(i8 %x, i8 %y) { +; CHECK-LABEL: @src_x_and_nmask_slt( +; CHECK-NEXT: [[NOT_MASK:%.*]] = shl nsw i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[NOT_MASK]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %not_mask = shl i8 -1, %y + %and = and i8 %x, %not_mask + %r = icmp slt i8 %and, %not_mask + ret i1 %r +} + +define i1 @src_x_and_nmask_sge(i8 %x, i8 %y) { +; CHECK-LABEL: @src_x_and_nmask_sge( +; CHECK-NEXT: [[NOT_MASK:%.*]] = shl nsw i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sle i8 [[NOT_MASK]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %not_mask = shl i8 -1, %y + %and = and i8 %x, %not_mask + %r = icmp sge i8 %and, %not_mask + ret i1 %r +} + +define i1 @src_x_and_nmask_slt_fail_maybe_z(i8 %x, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_x_and_nmask_slt_fail_maybe_z( +; CHECK-NEXT: [[NOT_MASK0:%.*]] = shl nsw i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[NOT_MASK:%.*]] = select i1 [[COND:%.*]], i8 [[NOT_MASK0]], i8 0 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[NOT_MASK]], [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[AND]], [[NOT_MASK]] +; CHECK-NEXT: ret i1 [[R]] +; + %not_mask0 = shl i8 -1, %y + %not_mask = select i1 %cond, i8 %not_mask0, i8 0 + %and = and i8 %x, %not_mask + %r = icmp slt i8 %and, %not_mask + ret i1 %r +} + +define i1 @src_x_and_nmask_sge_fail_maybe_z(i8 %x, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_x_and_nmask_sge_fail_maybe_z( +; CHECK-NEXT: [[NOT_MASK0:%.*]] = shl nsw i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[NOT_MASK:%.*]] = select i1 [[COND:%.*]], i8 [[NOT_MASK0]], i8 0 +; CHECK-NEXT: [[AND:%.*]] = and i8 [[NOT_MASK]], [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp sge i8 [[AND]], [[NOT_MASK]] +; CHECK-NEXT: ret i1 [[R]] +; + %not_mask0 = shl i8 -1, %y + %not_mask = select i1 %cond, i8 %not_mask0, i8 0 + %and = and i8 %x, %not_mask + %r = icmp sge i8 %and, %not_mask + ret i1 %r +} + +define i1 @src_x_or_mask_eq(i8 %x, i8 %y, i8 %z, i1 %c2, i1 %cond) { +; CHECK-LABEL: @src_x_or_mask_eq( +; CHECK-NEXT: [[MASK0:%.*]] = lshr i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[MASK:%.*]] = select i1 [[COND:%.*]], i8 [[MASK0]], i8 0 +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X:%.*]], -124 +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C2:%.*]], i8 [[TMP1]], i8 -46 +; CHECK-NEXT: [[TMP3:%.*]] = call i8 @llvm.umax.i8(i8 [[Z:%.*]], i8 [[TMP2]]) +; CHECK-NEXT: [[TMP4:%.*]] = add i8 [[TMP3]], -12 +; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[TMP4]], [[MASK]] +; CHECK-NEXT: ret i1 [[R]] +; + %mask0 = lshr i8 -1, %y + %mask = select i1 %cond, i8 %mask0, i8 0 + %nx = xor i8 %x, 123 + %nx_c = select i1 %c2, i8 %nx, i8 45 + %nz = xor i8 %z, -1 + %nx_cc = call i8 @llvm.umin.i8(i8 %nz, i8 %nx_c) + %nx_ccc = add i8 %nx_cc, 12 + %or = or i8 %nx_ccc, %mask + %r = icmp eq i8 %or, -1 + ret i1 %r +} + +define i1 @src_x_or_mask_ne(i8 %x, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_x_or_mask_ne( +; CHECK-NEXT: [[MASK0:%.*]] = lshr i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[MASK:%.*]] = select i1 [[COND:%.*]], i8 [[MASK0]], i8 0 +; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[MASK]], [[X:%.*]] +; CHECK-NEXT: ret i1 [[R]] +; + %mask0 = lshr i8 -1, %y + %mask = select i1 %cond, i8 %mask0, i8 0 + %nx = xor i8 %x, -1 + %or = or i8 %mask, %nx + %r = icmp ne i8 %or, -1 + ret i1 %r +} + +define i1 @src_x_or_mask_ne_fail_multiuse(i8 %x, i8 %y, i1 %cond) { +; CHECK-LABEL: @src_x_or_mask_ne_fail_multiuse( +; CHECK-NEXT: [[MASK0:%.*]] = lshr i8 -1, [[Y:%.*]] +; CHECK-NEXT: [[MASK:%.*]] = select i1 [[COND:%.*]], i8 [[MASK0]], i8 0 +; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 +; CHECK-NEXT: [[OR:%.*]] = or i8 [[MASK]], [[NX]] +; CHECK-NEXT: call void @use.i8(i8 [[OR]]) +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[OR]], -1 +; CHECK-NEXT: ret i1 [[R]] +; + %mask0 = lshr i8 -1, %y + %mask = select i1 %cond, i8 %mask0, i8 0 + %nx = xor i8 %x, -1 + %or = or i8 %mask, %nx + call void @use.i8(i8 %or) + %r = icmp ne i8 %or, -1 + ret i1 %r +} diff --git a/llvm/test/Transforms/InstCombine/icmp-mul-and.ll b/llvm/test/Transforms/InstCombine/icmp-mul-and.ll index d5f5641392c0c57dd541e9abe61d5f6de738b8d2..7e7f087ca7112c18537ad99d10bc1498c0c47d74 100644 --- a/llvm/test/Transforms/InstCombine/icmp-mul-and.ll +++ b/llvm/test/Transforms/InstCombine/icmp-mul-and.ll @@ -267,10 +267,10 @@ define i1 @pr51551_neg1(i32 %x, i32 %y) { define i1 @pr51551_neg2(i32 %x, i32 %y) { ; CHECK-LABEL: @pr51551_neg2( -; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[Y:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP1]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[Y:%.*]] to i1 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[X:%.*]], 7 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: [[DOTNOT:%.*]] = xor i1 [[TMP1]], true ; CHECK-NEXT: [[CMP:%.*]] = select i1 [[DOTNOT]], i1 true, i1 [[CMP1]] ; CHECK-NEXT: ret i1 [[CMP]] ; diff --git a/llvm/test/Transforms/InstCombine/icmp-mul-zext.ll b/llvm/test/Transforms/InstCombine/icmp-mul-zext.ll index adf78723b1302aad9b6e33a08f611d9f19bae456..d858c91becb5701029da923662527a849d3b3bce 100644 --- a/llvm/test/Transforms/InstCombine/icmp-mul-zext.ll +++ b/llvm/test/Transforms/InstCombine/icmp-mul-zext.ll @@ -128,12 +128,12 @@ define i1 @PR46561(i1 %a, i1 %x, i1 %y, i8 %z) { ; CHECK-NEXT: br i1 [[A:%.*]], label [[COND_TRUE:%.*]], label [[END:%.*]] ; CHECK: cond.true: ; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[Z:%.*]], 1 -; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[TMP0]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = trunc i8 [[Z:%.*]] to i1 ; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[MULBOOL]], [[TMP1]] +; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[TMP2]], true ; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[P:%.*]] = phi i1 [ [[TMP2]], [[COND_TRUE]] ], [ false, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[P:%.*]] = phi i1 [ [[TMP3]], [[COND_TRUE]] ], [ false, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i1 [[P]] ; entry: diff --git a/llvm/test/Transforms/InstCombine/icmp-select-implies-common-op.ll b/llvm/test/Transforms/InstCombine/icmp-select-implies-common-op.ll new file mode 100644 index 0000000000000000000000000000000000000000..bacdb54f787d6ae5455c503d73156ff303003075 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/icmp-select-implies-common-op.ll @@ -0,0 +1,93 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -passes=instcombine < %s | FileCheck %s + +define i1 @sgt_3_impliesF_eq_2(i8 %x, i8 %y) { +; CHECK-LABEL: @sgt_3_impliesF_eq_2( +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 4 +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[SEL:%.*]], [[X]] +; CHECK-NEXT: [[CMP3:%.*]] = select i1 [[CMP]], i1 [[CMP2]], i1 false +; CHECK-NEXT: ret i1 [[CMP3]] +; + %cmp = icmp sgt i8 %x, 3 + %sel = select i1 %cmp, i8 2, i8 %y + %cmp2 = icmp eq i8 %sel, %x + ret i1 %cmp2 +} + +define i1 @sgt_3_impliesT_sgt_2(i8 %x, i8 %y) { +; CHECK-LABEL: @sgt_3_impliesT_sgt_2( +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 4 +; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[SEL:%.*]], [[X]] +; CHECK-NEXT: [[CMP3:%.*]] = select i1 [[CMP]], i1 [[CMP2]], i1 false +; CHECK-NEXT: ret i1 [[CMP3]] +; + %cmp = icmp sgt i8 %x, 3 + %sel = select i1 %cmp, i8 2, i8 %y + %cmp2 = icmp sgt i8 %sel, %x + ret i1 %cmp2 +} + +define i1 @sgt_x_impliesF_eq_smin_todo(i8 %x, i8 %y, i8 %z) { +; CHECK-LABEL: @sgt_x_impliesF_eq_smin_todo( +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i8 -128, i8 [[Y:%.*]] +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[SEL]], [[X]] +; CHECK-NEXT: ret i1 [[CMP2]] +; + %cmp = icmp sgt i8 %x, %z + %sel = select i1 %cmp, i8 -128, i8 %y + %cmp2 = icmp eq i8 %sel, %x + ret i1 %cmp2 +} + +define i1 @slt_x_impliesT_ne_smin_todo(i8 %x, i8 %y, i8 %z) { +; CHECK-LABEL: @slt_x_impliesT_ne_smin_todo( +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], [[Z:%.*]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i8 127, i8 [[Y:%.*]] +; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[SEL]], [[X]] +; CHECK-NEXT: ret i1 [[CMP2]] +; + %cmp = icmp slt i8 %x, %z + %sel = select i1 %cmp, i8 127, i8 %y + %cmp2 = icmp ne i8 %x, %sel + ret i1 %cmp2 +} + +define i1 @ult_x_impliesT_eq_umax_todo(i8 %x, i8 %y, i8 %z) { +; CHECK-LABEL: @ult_x_impliesT_eq_umax_todo( +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[Z:%.*]], [[X:%.*]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i8 -1, i8 [[Y:%.*]] +; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[SEL]], [[X]] +; CHECK-NEXT: ret i1 [[CMP2]] +; + %cmp = icmp ugt i8 %z, %x + %sel = select i1 %cmp, i8 255, i8 %y + %cmp2 = icmp ne i8 %sel, %x + ret i1 %cmp2 +} + +define i1 @ult_1_impliesF_eq_1(i8 %x, i8 %y) { +; CHECK-LABEL: @ult_1_impliesF_eq_1( +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[SEL:%.*]], 0 +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[X:%.*]], [[SEL]] +; CHECK-NEXT: [[CMP3:%.*]] = select i1 [[CMP]], i1 [[CMP2]], i1 false +; CHECK-NEXT: ret i1 [[CMP3]] +; + %cmp = icmp ult i8 %x, 1 + %sel = select i1 %cmp, i8 1, i8 %y + %cmp2 = icmp eq i8 %x, %sel + ret i1 %cmp2 +} + +define i1 @ugt_x_impliesF_eq_umin_todo(i8 %x, i8 %y, i8 %z) { +; CHECK-LABEL: @ugt_x_impliesF_eq_umin_todo( +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[Z:%.*]], [[X:%.*]] +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i8 0, i8 [[Y:%.*]] +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[SEL]], [[X]] +; CHECK-NEXT: ret i1 [[CMP2]] +; + %cmp = icmp ugt i8 %z, %x + %sel = select i1 %cmp, i8 0, i8 %y + %cmp2 = icmp eq i8 %x, %sel + ret i1 %cmp2 +} diff --git a/llvm/test/Transforms/InstCombine/intrinsic-select.ll b/llvm/test/Transforms/InstCombine/intrinsic-select.ll index a203b28bcb82a884b70099ba9a52f208db1623ab..f37226bbd5b09c7592a451fdc4f4815a90072e06 100644 --- a/llvm/test/Transforms/InstCombine/intrinsic-select.ll +++ b/llvm/test/Transforms/InstCombine/intrinsic-select.ll @@ -240,3 +240,43 @@ define i32 @vec_to_scalar_select_vector(<2 x i1> %b) { %c = call i32 @llvm.vector.reduce.add.v2i32(<2 x i32> %s) ret i32 %c } + +define i8 @test_drop_noundef(i1 %cond, i8 %val) { +; CHECK-LABEL: @test_drop_noundef( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = call i8 @llvm.smin.i8(i8 [[VAL:%.*]], i8 0) +; CHECK-NEXT: [[RET:%.*]] = select i1 [[COND:%.*]], i8 -1, i8 [[TMP0]] +; CHECK-NEXT: ret i8 [[RET]] +; +entry: + %sel = select i1 %cond, i8 -1, i8 %val + %ret = call noundef i8 @llvm.smin.i8(i8 %sel, i8 0) + ret i8 %ret +} + +define i1 @pr85536(i32 %a) { +; CHECK-LABEL: @pr85536( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i32 [[A:%.*]], 31 +; CHECK-NEXT: [[SHL1:%.*]] = shl nsw i32 -1, [[A]] +; CHECK-NEXT: [[ZEXT:%.*]] = zext i32 [[SHL1]] to i64 +; CHECK-NEXT: [[SHL2:%.*]] = shl i64 [[ZEXT]], 48 +; CHECK-NEXT: [[SHR:%.*]] = ashr exact i64 [[SHL2]], 48 +; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.smin.i64(i64 [[SHR]], i64 0) +; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 65535 +; CHECK-NEXT: [[RET1:%.*]] = icmp eq i64 [[TMP1]], 0 +; CHECK-NEXT: [[RET:%.*]] = select i1 [[CMP1]], i1 [[RET1]], i1 false +; CHECK-NEXT: ret i1 [[RET]] +; +entry: + %cmp1 = icmp ugt i32 %a, 30 + %shl1 = shl nsw i32 -1, %a + %zext = zext i32 %shl1 to i64 + %shl2 = shl i64 %zext, 48 + %shr = ashr exact i64 %shl2, 48 + %sel = select i1 %cmp1, i64 -1, i64 %shr + %smin = call noundef i64 @llvm.smin.i64(i64 %sel, i64 0) + %masked = and i64 %smin, 65535 + %ret = icmp eq i64 %masked, 0 + ret i1 %ret +} diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll index 58c283815cf9103c0c95b5eaed1808161c2fc8ac..5305c78f6912311362f687303fe74d91aeb74ddb 100644 --- a/llvm/test/Transforms/InstCombine/known-bits.ll +++ b/llvm/test/Transforms/InstCombine/known-bits.ll @@ -483,5 +483,56 @@ if.else: ret i64 13 } +define i1 @test_icmp_or_distjoint(i8 %n, i1 %other) { +; CHECK-LABEL: @test_icmp_or_distjoint( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[N_OR:%.*]] = or disjoint i8 [[N:%.*]], 16 +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[N_OR]], -111 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: ret i1 true +; CHECK: if.else: +; CHECK-NEXT: ret i1 [[OTHER:%.*]] +; +entry: + %n_or = or disjoint i8 %n, 16 + %cmp = icmp ugt i8 %n_or, 145 + br i1 %cmp, label %if.then, label %if.else + +if.then: + %r = icmp slt i8 %n, 0 + ret i1 %r + +if.else: + ret i1 %other +} + +define i1 @test_icmp_or_fail_missing_disjoint(i8 %n, i1 %other) { +; CHECK-LABEL: @test_icmp_or_fail_missing_disjoint( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[N_OR:%.*]] = or i8 [[N:%.*]], 16 +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[N_OR]], -111 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[N]], 0 +; CHECK-NEXT: ret i1 [[R]] +; CHECK: if.else: +; CHECK-NEXT: ret i1 [[OTHER:%.*]] +; +entry: + %n_or = or i8 %n, 16 + %cmp = icmp ugt i8 %n_or, 145 + br i1 %cmp, label %if.then, label %if.else + +if.then: + %r = icmp slt i8 %n, 0 + ret i1 %r + +if.else: + ret i1 %other +} + + + declare void @use(i1) declare void @sink(i8) diff --git a/llvm/test/Transforms/InstCombine/mul-masked-bits.ll b/llvm/test/Transforms/InstCombine/mul-masked-bits.ll index da7cc2db09781b0d0ef17a8f32eec02aed98f14a..e940ae3fec163b73f128db476e16e1149072311d 100644 --- a/llvm/test/Transforms/InstCombine/mul-masked-bits.ll +++ b/llvm/test/Transforms/InstCombine/mul-masked-bits.ll @@ -214,9 +214,8 @@ define i64 @scalar_mul_bit_x0_y0_uses(i64 %x, i64 %y) { define i64 @scalar_mul_bit_x0_y1(i64 %x, i64 %y) { ; CHECK-LABEL: @scalar_mul_bit_x0_y1( ; CHECK-NEXT: [[AND2:%.*]] = and i64 [[Y:%.*]], 2 -; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[X:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i64 [[TMP1]], 0 -; CHECK-NEXT: [[MUL:%.*]] = select i1 [[DOTNOT]], i64 0, i64 [[AND2]] +; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i1 +; CHECK-NEXT: [[MUL:%.*]] = select i1 [[TMP1]], i64 [[AND2]], i64 0 ; CHECK-NEXT: ret i64 [[MUL]] ; %and1 = and i64 %x, 1 @@ -228,9 +227,8 @@ define i64 @scalar_mul_bit_x0_y1(i64 %x, i64 %y) { define i64 @scalar_mul_bit_x0_yC(i64 %x, i64 %y, i64 %c) { ; CHECK-LABEL: @scalar_mul_bit_x0_yC( ; CHECK-NEXT: [[AND2:%.*]] = and i64 [[Y:%.*]], [[C:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[X:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i64 [[TMP1]], 0 -; CHECK-NEXT: [[MUL:%.*]] = select i1 [[DOTNOT]], i64 0, i64 [[AND2]] +; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i1 +; CHECK-NEXT: [[MUL:%.*]] = select i1 [[TMP1]], i64 [[AND2]], i64 0 ; CHECK-NEXT: ret i64 [[MUL]] ; %and1 = and i64 %x, 1 diff --git a/llvm/test/Transforms/InstCombine/mul.ll b/llvm/test/Transforms/InstCombine/mul.ll index e7141d7c25ad21c348329d2f475cf5229cfa9e8c..d4a689c60786e043d7bbe88ce6b357be1e05723a 100644 --- a/llvm/test/Transforms/InstCombine/mul.ll +++ b/llvm/test/Transforms/InstCombine/mul.ll @@ -684,9 +684,8 @@ define <2 x i32> @signbit_mul_vec_commute(<2 x i32> %a, <2 x i32> %b) { define i32 @lowbit_mul(i32 %a, i32 %b) { ; CHECK-LABEL: @lowbit_mul( -; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], 1 -; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[TMP1]], 0 -; CHECK-NEXT: [[E:%.*]] = select i1 [[DOTNOT]], i32 0, i32 [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[A:%.*]] to i1 +; CHECK-NEXT: [[E:%.*]] = select i1 [[TMP1]], i32 [[B:%.*]], i32 0 ; CHECK-NEXT: ret i32 [[E]] ; %d = and i32 %a, 1 @@ -2049,3 +2048,94 @@ define i32 @zext_negpow2_use(i8 %x) { %r = mul i32 %zx, -16777216 ; -1 << 24 ret i32 %r } + +define i32 @mul_sext_icmp_with_zero(i32 %x) { +; CHECK-LABEL: @mul_sext_icmp_with_zero( +; CHECK-NEXT: ret i32 0 +; + %cmp = icmp eq i32 %x, 0 + %sext = sext i1 %cmp to i32 + %mul = mul i32 %sext, %x + ret i32 %mul +} + +define i32 @test_mul_sext_bool(i1 %x, i32 %y) { +; CHECK-LABEL: @test_mul_sext_bool( +; CHECK-NEXT: [[Y_NEG:%.*]] = sub i32 0, [[Y:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[Y_NEG]], i32 0 +; CHECK-NEXT: ret i32 [[MUL]] +; + %sext = sext i1 %x to i32 + %mul = mul i32 %sext, %y + ret i32 %mul +} + +define i32 @test_mul_sext_bool_nuw(i1 %x, i32 %y) { +; CHECK-LABEL: @test_mul_sext_bool_nuw( +; CHECK-NEXT: [[Y_NEG:%.*]] = sub i32 0, [[Y:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[Y_NEG]], i32 0 +; CHECK-NEXT: ret i32 [[MUL]] +; + %sext = sext i1 %x to i32 + %mul = mul nuw i32 %sext, %y + ret i32 %mul +} + +define i32 @test_mul_sext_bool_nsw(i1 %x, i32 %y) { +; CHECK-LABEL: @test_mul_sext_bool_nsw( +; CHECK-NEXT: [[Y_NEG:%.*]] = sub nsw i32 0, [[Y:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[Y_NEG]], i32 0 +; CHECK-NEXT: ret i32 [[MUL]] +; + %sext = sext i1 %x to i32 + %mul = mul nsw i32 %sext, %y + ret i32 %mul +} + +define i32 @test_mul_sext_bool_nuw_nsw(i1 %x, i32 %y) { +; CHECK-LABEL: @test_mul_sext_bool_nuw_nsw( +; CHECK-NEXT: [[Y_NEG:%.*]] = sub nsw i32 0, [[Y:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[Y_NEG]], i32 0 +; CHECK-NEXT: ret i32 [[MUL]] +; + %sext = sext i1 %x to i32 + %mul = mul nuw nsw i32 %sext, %y + ret i32 %mul +} + +define i32 @test_mul_sext_bool_commuted(i1 %x, i32 %y) { +; CHECK-LABEL: @test_mul_sext_bool_commuted( +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[Y:%.*]], -2 +; CHECK-NEXT: [[YY_NEG1:%.*]] = add i32 [[TMP1]], 1 +; CHECK-NEXT: [[MUL:%.*]] = select i1 [[X:%.*]], i32 [[YY_NEG1]], i32 0 +; CHECK-NEXT: ret i32 [[MUL]] +; + %yy = xor i32 %y, 1 + %sext = sext i1 %x to i32 + %mul = mul i32 %yy, %sext + ret i32 %mul +} + +define i32 @test_mul_sext_nonbool(i2 %x, i32 %y) { +; CHECK-LABEL: @test_mul_sext_nonbool( +; CHECK-NEXT: [[SEXT:%.*]] = sext i2 [[X:%.*]] to i32 +; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SEXT]], [[Y:%.*]] +; CHECK-NEXT: ret i32 [[MUL]] +; + %sext = sext i2 %x to i32 + %mul = mul i32 %sext, %y + ret i32 %mul +} + +define i32 @test_mul_sext_multiuse(i1 %x, i32 %y) { +; CHECK-LABEL: @test_mul_sext_multiuse( +; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[X:%.*]] to i32 +; CHECK-NEXT: tail call void @use(i32 [[SEXT]]) +; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[SEXT]], [[Y:%.*]] +; CHECK-NEXT: ret i32 [[MUL]] +; + %sext = sext i1 %x to i32 + tail call void @use(i32 %sext) + %mul = mul i32 %sext, %y + ret i32 %mul +} diff --git a/llvm/test/Transforms/InstCombine/not.ll b/llvm/test/Transforms/InstCombine/not.ll index f277d13eee930c67631b828a6ed3f0b431adcb2f..98b5d980415602737481152e19c939dcd0e08fa0 100644 --- a/llvm/test/Transforms/InstCombine/not.ll +++ b/llvm/test/Transforms/InstCombine/not.ll @@ -3,6 +3,8 @@ declare void @use1(i1) declare void @use8(i8) +declare void @f1() +declare void @f2() define i32 @test1(i32 %A) { ; CHECK-LABEL: @test1( @@ -858,3 +860,204 @@ define i32 @test_zext(i32 %a, i32 %b){ %not = xor i32 %add, -1 ret i32 %not } + +define void @test_invert_demorgan_or(i32 %a, i32 %b, i1 %cond) { +; CHECK-LABEL: @test_invert_demorgan_or( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[B:%.*]], 0 +; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[B1:%.*]], 0 +; CHECK-NEXT: [[OR_NOT1:%.*]] = and i1 [[CMP2]], [[CMP3]] +; CHECK-NEXT: [[MERGE:%.*]] = and i1 [[OR_NOT1]], [[COND:%.*]] +; CHECK-NEXT: br i1 [[MERGE]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: call void @f1() +; CHECK-NEXT: unreachable +; CHECK: if.else: +; CHECK-NEXT: call void @f2() +; CHECK-NEXT: unreachable +; +entry: + %cmp1 = icmp eq i32 %a, 0 + %cmp2 = icmp ne i32 %b, 0 + %or = or i1 %cmp1, %cmp2 + %not = xor i1 %cond, true + %merge = or i1 %not, %or + br i1 %merge, label %if.then, label %if.else +if.then: + call void @f1() + unreachable +if.else: + call void @f2() + unreachable +} + +define i1 @test_invert_demorgan_or2(i64 %a, i64 %b, i64 %c) { +; CHECK-LABEL: @test_invert_demorgan_or2( +; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[A:%.*]], 24 +; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[B:%.*]], 60 +; CHECK-NEXT: [[OR1_NOT1:%.*]] = and i1 [[CMP1]], [[CMP2]] +; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i64 [[C:%.*]], 60 +; CHECK-NEXT: [[NOT:%.*]] = and i1 [[OR1_NOT1]], [[CMP3]] +; CHECK-NEXT: ret i1 [[NOT]] +; + %cmp1 = icmp ugt i64 %a, 23 + %cmp2 = icmp ugt i64 %b, 59 + %or1 = or i1 %cmp1, %cmp2 + %cmp3 = icmp ugt i64 %c, 59 + %or2 = or i1 %or1, %cmp3 + %not = xor i1 %or2, true + ret i1 %not +} + +define i1 @test_invert_demorgan_or3(i32 %a, i32 %b) { +; CHECK-LABEL: @test_invert_demorgan_or3( +; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[A:%.*]], 178206 +; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[B:%.*]], -196608 +; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[TMP1]], -1506 +; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[B]], -917760 +; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i32 [[TMP2]], -716213 +; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[B]], -1114112 +; CHECK-NEXT: [[CMP4:%.*]] = icmp ult i32 [[TMP3]], -196112 +; CHECK-NEXT: [[OR1_NOT2:%.*]] = and i1 [[CMP1]], [[CMP2]] +; CHECK-NEXT: [[OR2_NOT1:%.*]] = and i1 [[OR1_NOT2]], [[CMP3]] +; CHECK-NEXT: [[NOT:%.*]] = and i1 [[OR2_NOT1]], [[CMP4]] +; CHECK-NEXT: ret i1 [[NOT]] +; + %cmp1 = icmp eq i32 %a, 178206 + %v1 = add i32 %b, -195102 + %cmp2 = icmp ult i32 %v1, 1506 + %v2 = add i32 %b, -201547 + %cmp3 = icmp ult i32 %v2, 716213 + %v3 = add i32 %b, -918000 + %cmp4 = icmp ult i32 %v3, 196112 + %or1 = or i1 %cmp1, %cmp2 + %or2 = or i1 %or1, %cmp3 + %or3 = or i1 %or2, %cmp4 + %not = xor i1 %or3, true + ret i1 %not +} + +define i1 @test_invert_demorgan_logical_or(i64 %x, i64 %y) { +; CHECK-LABEL: @test_invert_demorgan_logical_or( +; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i64 [[X:%.*]], 27 +; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i64 [[Y:%.*]], 0 +; CHECK-NEXT: [[SEL_NOT1:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 false +; CHECK-NEXT: [[CMP3:%.*]] = icmp ne i64 [[X]], 0 +; CHECK-NEXT: [[NOT:%.*]] = and i1 [[CMP3]], [[SEL_NOT1]] +; CHECK-NEXT: ret i1 [[NOT]] +; + %cmp1 = icmp eq i64 %x, 27 + %cmp2 = icmp eq i64 %y, 0 + %sel = select i1 %cmp1, i1 true, i1 %cmp2 + %cmp3 = icmp eq i64 %x, 0 + %or = or i1 %cmp3, %sel + %not = xor i1 %or, true + ret i1 %not +} + +define i1 @test_invert_demorgan_and(i32 %a, i32 %b, i1 %cond) { +; CHECK-LABEL: @test_invert_demorgan_and( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[B:%.*]], 0 +; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[B1:%.*]], 0 +; CHECK-NEXT: [[AND_NOT1:%.*]] = or i1 [[CMP2]], [[CMP3]] +; CHECK-NEXT: [[MERGE:%.*]] = or i1 [[AND_NOT1]], [[COND:%.*]] +; CHECK-NEXT: br i1 [[MERGE]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: call void @f1() +; CHECK-NEXT: unreachable +; CHECK: if.else: +; CHECK-NEXT: call void @f2() +; CHECK-NEXT: unreachable +; +entry: + %cmp1 = icmp eq i32 %a, 0 + %cmp2 = icmp ne i32 %b, 0 + %and = and i1 %cmp1, %cmp2 + %not = xor i1 %cond, true + %merge = and i1 %not, %and + br i1 %merge, label %if.then, label %if.else +if.then: + call void @f1() + unreachable +if.else: + call void @f2() + unreachable +} + +define i64 @test_invert_demorgan_and2(i64 %x) { +; CHECK-LABEL: @test_invert_demorgan_and2( +; CHECK-NEXT: [[TMP1:%.*]] = sub i64 0, [[X:%.*]] +; CHECK-NEXT: [[SUB:%.*]] = or i64 [[TMP1]], -9223372036854775808 +; CHECK-NEXT: ret i64 [[SUB]] +; + %add = add i64 %x, 9223372036854775807 + %and = and i64 %add, 9223372036854775807 + %sub = xor i64 %and, -1 + ret i64 %sub +} + +define i1 @test_invert_demorgan_and3(i32 %a, i32 %b) { +; CHECK-LABEL: @test_invert_demorgan_and3( +; CHECK-NEXT: [[ADD:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[AND:%.*]] = and i32 [[ADD]], 4095 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 4095 +; CHECK-NEXT: ret i1 [[CMP]] +; + %not = xor i32 %a, -1 + %add = add i32 %b, %not + %and = and i32 %add, 4095 + %cmp = icmp eq i32 %and, 0 + ret i1 %cmp +} + +define i1 @test_invert_demorgan_logical_and(i64 %x, i64 %y) { +; CHECK-LABEL: @test_invert_demorgan_logical_and( +; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i64 [[X:%.*]], 27 +; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i64 [[Y:%.*]], 0 +; CHECK-NEXT: [[SEL_NOT1:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP2]] +; CHECK-NEXT: [[CMP3:%.*]] = icmp ne i64 [[X]], 0 +; CHECK-NEXT: [[NOT:%.*]] = and i1 [[CMP3]], [[SEL_NOT1]] +; CHECK-NEXT: ret i1 [[NOT]] +; + %cmp1 = icmp eq i64 %x, 27 + %cmp2 = icmp eq i64 %y, 0 + %sel = select i1 %cmp1, i1 %cmp2, i1 false + %cmp3 = icmp eq i64 %x, 0 + %or = or i1 %cmp3, %sel + %not = xor i1 %or, true + ret i1 %not +} + +define i1 @test_invert_demorgan_and_multiuse(i32 %a, i32 %b, i1 %cond) { +; CHECK-LABEL: @test_invert_demorgan_and_multiuse( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0 +; CHECK-NEXT: call void @use1(i1 [[CMP1]]) +; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[B:%.*]], 0 +; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[COND:%.*]], true +; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[CMP2]], [[NOT]] +; CHECK-NEXT: [[MERGE:%.*]] = and i1 [[TMP0]], [[CMP1]] +; CHECK-NEXT: br i1 [[MERGE]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: call void @f1() +; CHECK-NEXT: unreachable +; CHECK: if.else: +; CHECK-NEXT: call void @f2() +; CHECK-NEXT: unreachable +; +entry: + %cmp1 = icmp eq i32 %a, 0 + call void @use1(i1 %cmp1) + %cmp2 = icmp ne i32 %b, 0 + %and = and i1 %cmp1, %cmp2 + %not = xor i1 %cond, true + %merge = and i1 %not, %and + br i1 %merge, label %if.then, label %if.else +if.then: + call void @f1() + unreachable +if.else: + call void @f2() + unreachable +} diff --git a/llvm/test/Transforms/InstCombine/phi.ll b/llvm/test/Transforms/InstCombine/phi.ll index e1ae6c1ea47579787b5b92be25299badfa026436..7eb508ebb55378456309807fbe396c408dbfb13b 100644 --- a/llvm/test/Transforms/InstCombine/phi.ll +++ b/llvm/test/Transforms/InstCombine/phi.ll @@ -116,8 +116,8 @@ define i32 @test6(i16 %A, i1 %b) { ; CHECK: BB1: ; CHECK-NEXT: br label [[BB2]] ; CHECK: BB2: -; CHECK-NEXT: [[B:%.*]] = zext i16 [[A:%.*]] to i32 -; CHECK-NEXT: ret i32 [[B]] +; CHECK-NEXT: [[C:%.*]] = zext i16 [[A:%.*]] to i32 +; CHECK-NEXT: ret i32 [[C]] ; BB0: %X = zext i16 %A to i32 @@ -129,8 +129,8 @@ BB1: BB2: ;; Suck casts into phi - %B = phi i32 [ %X, %BB0 ], [ %Y, %BB1 ] - ret i32 %B + %c = phi i32 [ %X, %BB0 ], [ %Y, %BB1 ] + ret i32 %c } define i32 @test_dead_cycle(i32 %A, i1 %cond) { @@ -232,8 +232,8 @@ define ptr @test8(ptr %A, i1 %b) { ; CHECK: BB1: ; CHECK-NEXT: br label [[BB2]] ; CHECK: BB2: -; CHECK-NEXT: [[B:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 4 -; CHECK-NEXT: ret ptr [[B]] +; CHECK-NEXT: [[C:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 4 +; CHECK-NEXT: ret ptr [[C]] ; BB0: %X = getelementptr inbounds { i32, i32 }, ptr %A, i32 0, i32 1 @@ -245,8 +245,8 @@ BB1: BB2: ;; Suck GEPs into phi - %B = phi ptr [ %X, %BB0 ], [ %Y, %BB1 ] - ret ptr %B + %c = phi ptr [ %X, %BB0 ], [ %Y, %BB1 ] + ret ptr %c } define i32 @test9(ptr %A, ptr %B) { @@ -489,9 +489,8 @@ define i64 @test15b(i64 %A, i1 %b) { ; CHECK-NEXT: [[Y_OFF0:%.*]] = phi i64 [ [[A]], [[ENTRY]] ], [ [[C]], [[ONE]] ] ; CHECK-NEXT: [[Y_OFF64]] = phi i64 [ [[A]], [[ENTRY]] ], [ 0, [[ONE]] ] ; CHECK-NEXT: [[D:%.*]] = call i64 @test15a(i64 [[Y_OFF64]]) -; CHECK-NEXT: [[TMP0:%.*]] = and i64 [[D]], 1 -; CHECK-NEXT: [[D1_NOT:%.*]] = icmp eq i64 [[TMP0]], 0 -; CHECK-NEXT: br i1 [[D1_NOT]], label [[END:%.*]], label [[ONE]] +; CHECK-NEXT: [[D1:%.*]] = trunc i64 [[D]] to i1 +; CHECK-NEXT: br i1 [[D1]], label [[ONE]], label [[END:%.*]] ; CHECK: end: ; CHECK-NEXT: ret i64 [[Y_OFF0]] ; diff --git a/llvm/test/Transforms/InstCombine/powi.ll b/llvm/test/Transforms/InstCombine/powi.ll index 89efbb6f45361133f9da38fe4d95765e27595797..6c0575e8b71971352102c1ed79eb28cf5d4a2b00 100644 --- a/llvm/test/Transforms/InstCombine/powi.ll +++ b/llvm/test/Transforms/InstCombine/powi.ll @@ -125,22 +125,55 @@ entry: ret double %mul } -define double @powi_fmul_powi_no_reassoc(double %x, i32 %y, i32 %z) { -; CHECK-LABEL: @powi_fmul_powi_no_reassoc( +; Negative test: Missing reassoc flag on fmul +define double @powi_fmul_powi_no_reassoc1(double %x, i32 %y, i32 %z) { +; CHECK-LABEL: @powi_fmul_powi_no_reassoc1( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) -; CHECK-NEXT: [[P2:%.*]] = tail call double @llvm.powi.f64.i32(double [[X]], i32 [[Z:%.*]]) +; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) +; CHECK-NEXT: [[P2:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X]], i32 [[Z:%.*]]) ; CHECK-NEXT: [[MUL:%.*]] = fmul double [[P2]], [[P1]] ; CHECK-NEXT: ret double [[MUL]] ; entry: - %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %y) - %p2 = tail call double @llvm.powi.f64.i32(double %x, i32 %z) + %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y) + %p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z) %mul = fmul double %p2, %p1 ret double %mul } +; Negative test: Missing reassoc flag on 2nd operand +define double @powi_fmul_powi_no_reassoc2(double %x, i32 %y, i32 %z) { +; CHECK-LABEL: @powi_fmul_powi_no_reassoc2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) +; CHECK-NEXT: [[P2:%.*]] = tail call double @llvm.powi.f64.i32(double [[X]], i32 [[Z:%.*]]) +; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P2]], [[P1]] +; CHECK-NEXT: ret double [[MUL]] +; +entry: + %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y) + %p2 = tail call double @llvm.powi.f64.i32(double %x, i32 %z) + %mul = fmul reassoc double %p2, %p1 + ret double %mul +} + +; Negative test: Missing reassoc flag on 1st operand +define double @powi_fmul_powi_no_reassoc3(double %x, i32 %y, i32 %z) { +; CHECK-LABEL: @powi_fmul_powi_no_reassoc3( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) +; CHECK-NEXT: [[P2:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X]], i32 [[Z:%.*]]) +; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P2]], [[P1]] +; CHECK-NEXT: ret double [[MUL]] +; +entry: + %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %y) + %p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z) + %mul = fmul reassoc double %p2, %p1 + ret double %mul +} +; All of the fmul and its operands should have the reassoc flags define double @powi_fmul_powi(double %x, i32 %y, i32 %z) { ; CHECK-LABEL: @powi_fmul_powi( ; CHECK-NEXT: entry: @@ -149,8 +182,8 @@ define double @powi_fmul_powi(double %x, i32 %y, i32 %z) { ; CHECK-NEXT: ret double [[MUL]] ; entry: - %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %y) - %p2 = tail call double @llvm.powi.f64.i32(double %x, i32 %z) + %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y) + %p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z) %mul = fmul reassoc double %p2, %p1 ret double %mul } @@ -163,8 +196,8 @@ define double @powi_fmul_powi_fast_on_fmul(double %x, i32 %y, i32 %z) { ; CHECK-NEXT: ret double [[MUL]] ; entry: - %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %y) - %p2 = tail call double @llvm.powi.f64.i32(double %x, i32 %z) + %p1 = tail call fast double @llvm.powi.f64.i32(double %x, i32 %y) + %p2 = tail call fast double @llvm.powi.f64.i32(double %x, i32 %z) %mul = fmul fast double %p2, %p1 ret double %mul } @@ -192,8 +225,23 @@ define double @powi_fmul_powi_same_power(double %x, i32 %y, i32 %z) { ; CHECK-NEXT: ret double [[MUL]] ; entry: - %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %y) - %p2 = tail call double @llvm.powi.f64.i32(double %x, i32 %y) + %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y) + %p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y) + %mul = fmul reassoc double %p2, %p1 + ret double %mul +} + +define double @powi_fmul_powi_different_integer_types(double %x, i32 %y, i16 %z) { +; CHECK-LABEL: @powi_fmul_powi_different_integer_types( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) +; CHECK-NEXT: [[P2:%.*]] = tail call reassoc double @llvm.powi.f64.i16(double [[X]], i16 [[Z:%.*]]) +; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P2]], [[P1]] +; CHECK-NEXT: ret double [[MUL]] +; +entry: + %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y) + %p2 = tail call reassoc double @llvm.powi.f64.i16(double %x, i16 %z) %mul = fmul reassoc double %p2, %p1 ret double %mul } @@ -201,16 +249,16 @@ entry: define double @powi_fmul_powi_use_first(double %x, i32 %y, i32 %z) { ; CHECK-LABEL: @powi_fmul_powi_use_first( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) +; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) ; CHECK-NEXT: tail call void @use(double [[P1]]) ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[Y]], [[Z:%.*]] ; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X]], i32 [[TMP0]]) ; CHECK-NEXT: ret double [[MUL]] ; entry: - %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %y) + %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y) tail call void @use(double %p1) - %p2 = tail call double @llvm.powi.f64.i32(double %x, i32 %z) + %p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z) %mul = fmul reassoc double %p1, %p2 ret double %mul } @@ -218,16 +266,16 @@ entry: define double @powi_fmul_powi_use_second(double %x, i32 %y, i32 %z) { ; CHECK-LABEL: @powi_fmul_powi_use_second( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Z:%.*]]) +; CHECK-NEXT: [[P1:%.*]] = tail call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Z:%.*]]) ; CHECK-NEXT: tail call void @use(double [[P1]]) ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[Y:%.*]], [[Z]] ; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X]], i32 [[TMP0]]) ; CHECK-NEXT: ret double [[MUL]] ; entry: - %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 %z) + %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %z) tail call void @use(double %p1) - %p2 = tail call double @llvm.powi.f64.i32(double %x, i32 %y) + %p2 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 %y) %mul = fmul reassoc double %p2, %p1 ret double %mul } @@ -265,7 +313,7 @@ define double @fdiv_pow_powi(double %x) { ; CHECK-NEXT: [[DIV:%.*]] = fmul reassoc nnan double [[X:%.*]], [[X]] ; CHECK-NEXT: ret double [[DIV]] ; - %p1 = call double @llvm.powi.f64.i32(double %x, i32 3) + %p1 = call reassoc double @llvm.powi.f64.i32(double %x, i32 3) %div = fdiv reassoc nnan double %p1, %x ret double %div } @@ -275,7 +323,7 @@ define float @fdiv_powf_powi(float %x) { ; CHECK-NEXT: [[DIV:%.*]] = call reassoc nnan float @llvm.powi.f32.i32(float [[X:%.*]], i32 99) ; CHECK-NEXT: ret float [[DIV]] ; - %p1 = call float @llvm.powi.f32.i32(float %x, i32 100) + %p1 = call reassoc float @llvm.powi.f32.i32(float %x, i32 100) %div = fdiv reassoc nnan float %p1, %x ret float %div } @@ -299,10 +347,21 @@ define double @fdiv_pow_powi_multi_use(double %x) { define float @fdiv_powf_powi_missing_reassoc(float %x) { ; CHECK-LABEL: @fdiv_powf_powi_missing_reassoc( ; CHECK-NEXT: [[P1:%.*]] = call float @llvm.powi.f32.i32(float [[X:%.*]], i32 100) -; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan float [[P1]], [[X]] +; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan float [[P1]], [[X]] ; CHECK-NEXT: ret float [[DIV]] ; %p1 = call float @llvm.powi.f32.i32(float %x, i32 100) + %div = fdiv reassoc nnan float %p1, %x + ret float %div +} + +define float @fdiv_powf_powi_missing_reassoc1(float %x) { +; CHECK-LABEL: @fdiv_powf_powi_missing_reassoc1( +; CHECK-NEXT: [[P1:%.*]] = call reassoc float @llvm.powi.f32.i32(float [[X:%.*]], i32 100) +; CHECK-NEXT: [[DIV:%.*]] = fdiv nnan float [[P1]], [[X]] +; CHECK-NEXT: ret float [[DIV]] +; + %p1 = call reassoc float @llvm.powi.f32.i32(float %x, i32 100) %div = fdiv nnan float %p1, %x ret float %div } @@ -333,11 +392,60 @@ define double @fdiv_pow_powi_negative(double %x) { ; Negative test: The 2nd powi argument is a variable define double @fdiv_pow_powi_negative_variable(double %x, i32 %y) { ; CHECK-LABEL: @fdiv_pow_powi_negative_variable( -; CHECK-NEXT: [[P1:%.*]] = call double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) +; CHECK-NEXT: [[P1:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 [[Y:%.*]]) ; CHECK-NEXT: [[DIV:%.*]] = fdiv reassoc nnan double [[P1]], [[X]] ; CHECK-NEXT: ret double [[DIV]] ; - %p1 = call double @llvm.powi.f64.i32(double %x, i32 %y) + %p1 = call reassoc double @llvm.powi.f64.i32(double %x, i32 %y) %div = fdiv reassoc nnan double %p1, %x ret double %div } + +; powi(X, Y) * X --> powi(X, Y+1) +define double @powi_fmul_powi_x(double noundef %x) { +; CHECK-LABEL: @powi_fmul_powi_x( +; CHECK-NEXT: [[MUL:%.*]] = call reassoc double @llvm.powi.f64.i32(double [[X:%.*]], i32 4) +; CHECK-NEXT: ret double [[MUL]] +; + %p1 = tail call reassoc double @llvm.powi.f64.i32(double %x, i32 3) + %mul = fmul reassoc double %p1, %x + ret double %mul +} + +; Negative test: Multi-use +define double @powi_fmul_powi_x_multi_use(double noundef %x) { +; CHECK-LABEL: @powi_fmul_powi_x_multi_use( +; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 3) +; CHECK-NEXT: tail call void @use(double [[P1]]) +; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P1]], [[X]] +; CHECK-NEXT: ret double [[MUL]] +; + %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 3) + tail call void @use(double %p1) + %mul = fmul reassoc double %p1, %x + ret double %mul +} + +; Negative test: Miss fmf flag +define double @powi_fmul_powi_x_missing_reassoc(double noundef %x) { +; CHECK-LABEL: @powi_fmul_powi_x_missing_reassoc( +; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 3) +; CHECK-NEXT: [[MUL:%.*]] = fmul double [[P1]], [[X]] +; CHECK-NEXT: ret double [[MUL]] +; + %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 3) + %mul = fmul double %p1, %x + ret double %mul +} + +; Negative test: overflow +define double @powi_fmul_powi_x_overflow(double noundef %x) { +; CHECK-LABEL: @powi_fmul_powi_x_overflow( +; CHECK-NEXT: [[P1:%.*]] = tail call double @llvm.powi.f64.i32(double [[X:%.*]], i32 2147483647) +; CHECK-NEXT: [[MUL:%.*]] = fmul reassoc double [[P1]], [[X]] +; CHECK-NEXT: ret double [[MUL]] +; + %p1 = tail call double @llvm.powi.f64.i32(double %x, i32 2147483647) ; INT_MAX + %mul = fmul reassoc double %p1, %x + ret double %mul +} diff --git a/llvm/test/Transforms/InstCombine/pr63791.ll b/llvm/test/Transforms/InstCombine/pr63791.ll index 78cc1130fb33f0cdbab6c6ba5050681b696693ff..73a559f9892612f49e69be7d2bcf0d75bd7b4a08 100644 --- a/llvm/test/Transforms/InstCombine/pr63791.ll +++ b/llvm/test/Transforms/InstCombine/pr63791.ll @@ -15,7 +15,7 @@ define void @y() { ; CHECK-NEXT: store i1 true, ptr poison, align 1 ; CHECK-NEXT: br i1 poison, label [[FOR_COND_I]], label [[FOR_COND5_PREHEADER_I]] ; CHECK: for.cond5.preheader.i: -; CHECK-NEXT: br i1 false, label [[FOR_INC19_I:%.*]], label [[FOR_COND1_LOOPEXIT_I:%.*]] +; CHECK-NEXT: br i1 true, label [[FOR_COND1_LOOPEXIT_I:%.*]], label [[FOR_INC19_I:%.*]] ; CHECK: for.inc19.i: ; CHECK-NEXT: br i1 poison, label [[FOR_INC19_I]], label [[FOR_COND1_LOOPEXIT_I]] ; diff --git a/llvm/test/Transforms/InstCombine/ptr-int-cast.ll b/llvm/test/Transforms/InstCombine/ptr-int-cast.ll index 6f5814e1a28237e9b9e59d29bfb72cb352301f3c..69b8f6953d61e4a9cdb8f3b9d4687ef0f03d5501 100644 --- a/llvm/test/Transforms/InstCombine/ptr-int-cast.ll +++ b/llvm/test/Transforms/InstCombine/ptr-int-cast.ll @@ -6,8 +6,7 @@ define i1 @test1(ptr %x) nounwind { ; CHECK-LABEL: @test1( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[X:%.*]] to i64 -; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 1 -; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i64 [[TMP1]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP0]] to i1 ; CHECK-NEXT: ret i1 [[TMP2]] ; entry: diff --git a/llvm/test/Transforms/InstCombine/reduction-add-sext-zext-i1.ll b/llvm/test/Transforms/InstCombine/reduction-add-sext-zext-i1.ll index bbb8d848be6f4f770a9915b34c681955086cd7b8..ad55b506a108bbdc9c889c73b05f974409b80f8b 100644 --- a/llvm/test/Transforms/InstCombine/reduction-add-sext-zext-i1.ll +++ b/llvm/test/Transforms/InstCombine/reduction-add-sext-zext-i1.ll @@ -5,8 +5,7 @@ define i1 @reduce_add_self(<8 x i1> %x) { ; CHECK-LABEL: @reduce_add_self( ; CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i1> [[X:%.*]] to i8 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ctpop.i8(i8 [[TMP1]]), !range [[RNG0:![0-9]+]] -; CHECK-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 1 -; CHECK-NEXT: [[RES:%.*]] = icmp ne i8 [[TMP3]], 0 +; CHECK-NEXT: [[RES:%.*]] = trunc i8 [[TMP2]] to i1 ; CHECK-NEXT: ret i1 [[RES]] ; %res = call i1 @llvm.vector.reduce.add.v8i32(<8 x i1> %x) diff --git a/llvm/test/Transforms/InstCombine/reduction-xor-sext-zext-i1.ll b/llvm/test/Transforms/InstCombine/reduction-xor-sext-zext-i1.ll index 97b6f7b6d96cdcea0cb85ed928e37e8e277ef557..84ac9369b5ff066c0211ef34cf5dc7535bf258c9 100644 --- a/llvm/test/Transforms/InstCombine/reduction-xor-sext-zext-i1.ll +++ b/llvm/test/Transforms/InstCombine/reduction-xor-sext-zext-i1.ll @@ -5,8 +5,7 @@ define i1 @reduce_xor_self(<8 x i1> %x) { ; CHECK-LABEL: @reduce_xor_self( ; CHECK-NEXT: [[TMP1:%.*]] = bitcast <8 x i1> [[X:%.*]] to i8 ; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ctpop.i8(i8 [[TMP1]]), !range [[RNG0:![0-9]+]] -; CHECK-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 1 -; CHECK-NEXT: [[RES:%.*]] = icmp ne i8 [[TMP3]], 0 +; CHECK-NEXT: [[RES:%.*]] = trunc i8 [[TMP2]] to i1 ; CHECK-NEXT: ret i1 [[RES]] ; %res = call i1 @llvm.vector.reduce.xor.v8i32(<8 x i1> %x) @@ -17,9 +16,8 @@ define i32 @reduce_xor_sext(<4 x i1> %x) { ; CHECK-LABEL: @reduce_xor_sext( ; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i1> [[X:%.*]] to i4 ; CHECK-NEXT: [[TMP2:%.*]] = call i4 @llvm.ctpop.i4(i4 [[TMP1]]), !range [[RNG1:![0-9]+]] -; CHECK-NEXT: [[TMP3:%.*]] = and i4 [[TMP2]], 1 -; CHECK-NEXT: [[SEXT:%.*]] = sub nsw i4 0, [[TMP3]] -; CHECK-NEXT: [[RES:%.*]] = sext i4 [[SEXT]] to i32 +; CHECK-NEXT: [[TMP3:%.*]] = trunc i4 [[TMP2]] to i1 +; CHECK-NEXT: [[RES:%.*]] = sext i1 [[TMP3]] to i32 ; CHECK-NEXT: ret i32 [[RES]] ; %sext = sext <4 x i1> %x to <4 x i32> @@ -57,9 +55,8 @@ define i8 @reduce_xor_zext_long(<128 x i1> %x) { ; CHECK-LABEL: @reduce_xor_zext_long( ; CHECK-NEXT: [[TMP1:%.*]] = bitcast <128 x i1> [[X:%.*]] to i128 ; CHECK-NEXT: [[TMP2:%.*]] = call i128 @llvm.ctpop.i128(i128 [[TMP1]]), !range [[RNG3:![0-9]+]] -; CHECK-NEXT: [[TMP3:%.*]] = trunc i128 [[TMP2]] to i8 -; CHECK-NEXT: [[TMP4:%.*]] = and i8 [[TMP3]], 1 -; CHECK-NEXT: [[RES:%.*]] = sub nsw i8 0, [[TMP4]] +; CHECK-NEXT: [[TMP3:%.*]] = trunc i128 [[TMP2]] to i1 +; CHECK-NEXT: [[RES:%.*]] = sext i1 [[TMP3]] to i8 ; CHECK-NEXT: ret i8 [[RES]] ; %sext = sext <128 x i1> %x to <128 x i8> @@ -72,9 +69,8 @@ define i8 @reduce_xor_zext_long_external_use(<128 x i1> %x) { ; CHECK-LABEL: @reduce_xor_zext_long_external_use( ; CHECK-NEXT: [[TMP1:%.*]] = bitcast <128 x i1> [[X:%.*]] to i128 ; CHECK-NEXT: [[TMP2:%.*]] = call i128 @llvm.ctpop.i128(i128 [[TMP1]]), !range [[RNG3]] -; CHECK-NEXT: [[TMP3:%.*]] = trunc i128 [[TMP2]] to i8 -; CHECK-NEXT: [[TMP4:%.*]] = and i8 [[TMP3]], 1 -; CHECK-NEXT: [[RES:%.*]] = sub nsw i8 0, [[TMP4]] +; CHECK-NEXT: [[TMP3:%.*]] = trunc i128 [[TMP2]] to i1 +; CHECK-NEXT: [[RES:%.*]] = sext i1 [[TMP3]] to i8 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <128 x i1> [[X]], i64 0 ; CHECK-NEXT: [[EXT:%.*]] = sext i1 [[TMP5]] to i8 ; CHECK-NEXT: store i8 [[EXT]], ptr @glob, align 1 diff --git a/llvm/test/Transforms/InstCombine/sadd-with-overflow.ll b/llvm/test/Transforms/InstCombine/sadd-with-overflow.ll index 4b37ccbe3370b67de96ee7363e5c716a204d02e1..729ca03ddfd15028c68dcdad148eac9d8090e1ce 100644 --- a/llvm/test/Transforms/InstCombine/sadd-with-overflow.ll +++ b/llvm/test/Transforms/InstCombine/sadd-with-overflow.ll @@ -122,3 +122,35 @@ define { i32, i1 } @fold_sub_simple(i32 %x) { %b = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 30) ret { i32, i1 } %b } + +define { i32, i1 } @fold_with_distjoin_or(i32 %x) { +; CHECK-LABEL: @fold_with_distjoin_or( +; CHECK-NEXT: [[B:%.*]] = add i32 [[X:%.*]], 6 +; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[B]], 0 +; CHECK-NEXT: ret { i32, i1 } [[TMP1]] +; + %a = or disjoint i32 %x, 13 + %b = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 -7) + ret { i32, i1 } %b +} + +define { i32, i1 } @fold_with_disjoint_or2(i32 %x) { +; CHECK-LABEL: @fold_with_disjoint_or2( +; CHECK-NEXT: [[B:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X:%.*]], i32 127) +; CHECK-NEXT: ret { i32, i1 } [[B]] +; + %a = or disjoint i32 %x, 100 + %b = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 27) + ret { i32, i1 } %b +} + +define { i32, i1 } @fold_with_or_fail(i32 %x) { +; CHECK-LABEL: @fold_with_or_fail( +; CHECK-NEXT: [[A:%.*]] = or i32 [[X:%.*]], 100 +; CHECK-NEXT: [[B:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[A]], i32 27) +; CHECK-NEXT: ret { i32, i1 } [[B]] +; + %a = or i32 %x, 100 + %b = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32 27) + ret { i32, i1 } %b +} diff --git a/llvm/test/Transforms/InstCombine/scalarization.ll b/llvm/test/Transforms/InstCombine/scalarization.ll index fe6dc526bd50ee6965cc388cd821036775b1992d..7e645ef7e883e4cd7a841afb3b9589aae746bae8 100644 --- a/llvm/test/Transforms/InstCombine/scalarization.ll +++ b/llvm/test/Transforms/InstCombine/scalarization.ll @@ -341,6 +341,17 @@ define i1 @extractelt_vector_fcmp_constrhs_dynidx(<2 x float> %arg, i32 %idx) { ret i1 %ext } +define i1 @extractelt_vector_fcmp_copy_flags(<4 x float> %x) { +; CHECK-LABEL: @extractelt_vector_fcmp_copy_flags( +; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x float> [[X:%.*]], i64 2 +; CHECK-NEXT: [[TMP2:%.*]] = fcmp nsz arcp oeq float [[TMP1]], 0.000000e+00 +; CHECK-NEXT: ret i1 [[TMP2]] +; + %cmp = fcmp nsz arcp oeq <4 x float> %x, zeroinitializer + %r = extractelement <4 x i1> %cmp, i32 2 + ret i1 %r +} + define i1 @extractelt_vector_fcmp_not_cheap_to_scalarize_multi_use(<2 x float> %arg0, <2 x float> %arg1, <2 x float> %arg2, i32 %idx) { ; ; CHECK-LABEL: @extractelt_vector_fcmp_not_cheap_to_scalarize_multi_use( diff --git a/llvm/test/Transforms/InstCombine/select-binop-foldable-floating-point.ll b/llvm/test/Transforms/InstCombine/select-binop-foldable-floating-point.ll index 496854c7d731abce99f8365d28f5ceecbbcdeb04..77ff16a8b2e3d86a6bea05a70353fa7de891073f 100644 --- a/llvm/test/Transforms/InstCombine/select-binop-foldable-floating-point.ll +++ b/llvm/test/Transforms/InstCombine/select-binop-foldable-floating-point.ll @@ -1,8 +1,19 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=instcombine -S | FileCheck %s -define float @select_fadd(i1 %cond, float %A, float %B) { -; CHECK-LABEL: @select_fadd( +define float @select_maybe_nan_fadd(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_maybe_nan_fadd( +; CHECK-NEXT: [[C:%.*]] = fadd float [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[D:%.*]] = select i1 [[COND:%.*]], float [[C]], float [[A]] +; CHECK-NEXT: ret float [[D]] +; + %C = fadd float %A, %B + %D = select i1 %cond, float %C, float %A + ret float %D +} + +define float @select_fpclass_fadd(i1 %cond, float nofpclass(nan) %A, float %B) { +; CHECK-LABEL: @select_fpclass_fadd( ; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float [[B:%.*]], float -0.000000e+00 ; CHECK-NEXT: [[D:%.*]] = fadd float [[C]], [[A:%.*]] ; CHECK-NEXT: ret float [[D]] @@ -12,41 +23,52 @@ define float @select_fadd(i1 %cond, float %A, float %B) { ret float %D } -define float @select_fadd_swapped(i1 %cond, float %A, float %B) { -; CHECK-LABEL: @select_fadd_swapped( -; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float -0.000000e+00, float [[B:%.*]] +define float @select_nnan_fadd(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_nnan_fadd( +; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float [[B:%.*]], float -0.000000e+00 ; CHECK-NEXT: [[D:%.*]] = fadd float [[C]], [[A:%.*]] ; CHECK-NEXT: ret float [[D]] ; %C = fadd float %A, %B - %D = select i1 %cond, float %A, float %C + %D = select nnan i1 %cond, float %C, float %A ret float %D } -define float @select_fadd_fast_math(i1 %cond, float %A, float %B) { -; CHECK-LABEL: @select_fadd_fast_math( -; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float [[B:%.*]], float -0.000000e+00 +define float @select_nnan_fadd_swapped(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_nnan_fadd_swapped( +; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float -0.000000e+00, float [[B:%.*]] +; CHECK-NEXT: [[D:%.*]] = fadd float [[C]], [[A:%.*]] +; CHECK-NEXT: ret float [[D]] +; + %C = fadd float %A, %B + %D = select nnan i1 %cond, float %A, float %C + ret float %D +} + +define float @select_nnan_fadd_fast_math(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_nnan_fadd_fast_math( +; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float [[B:%.*]], float -0.000000e+00 ; CHECK-NEXT: [[D:%.*]] = fadd fast float [[C]], [[A:%.*]] ; CHECK-NEXT: ret float [[D]] ; %C = fadd fast float %A, %B - %D = select i1 %cond, float %C, float %A + %D = select nnan i1 %cond, float %C, float %A ret float %D } -define float @select_fadd_swapped_fast_math(i1 %cond, float %A, float %B) { -; CHECK-LABEL: @select_fadd_swapped_fast_math( -; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float -0.000000e+00, float [[B:%.*]] +define float @select_nnan_fadd_swapped_fast_math(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_nnan_fadd_swapped_fast_math( +; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float -0.000000e+00, float [[B:%.*]] ; CHECK-NEXT: [[D:%.*]] = fadd fast float [[C]], [[A:%.*]] ; CHECK-NEXT: ret float [[D]] ; %C = fadd fast float %A, %B - %D = select i1 %cond, float %A, float %C + %D = select nnan i1 %cond, float %A, float %C ret float %D } -define <4 x float> @select_nsz_fadd_v4f32(<4 x i1> %cond, <4 x float> %A, <4 x float> %B) { -; CHECK-LABEL: @select_nsz_fadd_v4f32( +define <4 x float> @select_nnan_nsz_fadd_v4f32(<4 x i1> %cond, <4 x float> %A, <4 x float> %B) { +; CHECK-LABEL: @select_nnan_nsz_fadd_v4f32( ; CHECK-NEXT: [[C:%.*]] = select nnan nsz <4 x i1> [[COND:%.*]], <4 x float> [[B:%.*]], <4 x float> zeroinitializer ; CHECK-NEXT: [[D:%.*]] = fadd nnan nsz <4 x float> [[C]], [[A:%.*]] ; CHECK-NEXT: ret <4 x float> [[D]] @@ -56,202 +78,202 @@ define <4 x float> @select_nsz_fadd_v4f32(<4 x i1> %cond, <4 x float> %A, <4 x f ret <4 x float> %D } -define <vscale x 4 x float> @select_nsz_fadd_nxv4f32(<vscale x 4 x i1> %cond, <vscale x 4 x float> %A, <vscale x 4 x float> %B) { -; CHECK-LABEL: @select_nsz_fadd_nxv4f32( +define <vscale x 4 x float> @select_nnan_nsz_fadd_nxv4f32(<vscale x 4 x i1> %cond, <vscale x 4 x float> %A, <vscale x 4 x float> %B) { +; CHECK-LABEL: @select_nnan_nsz_fadd_nxv4f32( ; CHECK-NEXT: [[C:%.*]] = select nnan nsz <vscale x 4 x i1> [[COND:%.*]], <vscale x 4 x float> [[B:%.*]], <vscale x 4 x float> zeroinitializer ; CHECK-NEXT: [[D:%.*]] = fadd nnan nsz <vscale x 4 x float> [[C]], [[A:%.*]] ; CHECK-NEXT: ret <vscale x 4 x float> [[D]] ; - %C = fadd nsz nnan <vscale x 4 x float> %A, %B - %D = select nsz nnan <vscale x 4 x i1> %cond, <vscale x 4 x float> %C, <vscale x 4 x float> %A + %C = fadd nnan nsz <vscale x 4 x float> %A, %B + %D = select nnan nsz <vscale x 4 x i1> %cond, <vscale x 4 x float> %C, <vscale x 4 x float> %A ret <vscale x 4 x float> %D } -define <vscale x 4 x float> @select_nsz_fadd_nxv4f32_swapops(<vscale x 4 x i1> %cond, <vscale x 4 x float> %A, <vscale x 4 x float> %B) { -; CHECK-LABEL: @select_nsz_fadd_nxv4f32_swapops( +define <vscale x 4 x float> @select_nnan_nsz_fadd_nxv4f32_swapops(<vscale x 4 x i1> %cond, <vscale x 4 x float> %A, <vscale x 4 x float> %B) { +; CHECK-LABEL: @select_nnan_nsz_fadd_nxv4f32_swapops( ; CHECK-NEXT: [[C:%.*]] = select fast <vscale x 4 x i1> [[COND:%.*]], <vscale x 4 x float> zeroinitializer, <vscale x 4 x float> [[B:%.*]] ; CHECK-NEXT: [[D:%.*]] = fadd fast <vscale x 4 x float> [[C]], [[A:%.*]] ; CHECK-NEXT: ret <vscale x 4 x float> [[D]] ; %C = fadd fast <vscale x 4 x float> %A, %B - %D = select fast <vscale x 4 x i1> %cond, <vscale x 4 x float> %A, <vscale x 4 x float> %C + %D = select nnan fast <vscale x 4 x i1> %cond, <vscale x 4 x float> %A, <vscale x 4 x float> %C ret <vscale x 4 x float> %D } -define float @select_fmul(i1 %cond, float %A, float %B) { -; CHECK-LABEL: @select_fmul( -; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float [[B:%.*]], float 1.000000e+00 +define float @select_nnan_fmul(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_nnan_fmul( +; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float [[B:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[D:%.*]] = fmul float [[C]], [[A:%.*]] ; CHECK-NEXT: ret float [[D]] ; %C = fmul float %A, %B - %D = select i1 %cond, float %C, float %A + %D = select nnan i1 %cond, float %C, float %A ret float %D } -define float @select_fmul_swapped(i1 %cond, float %A, float %B) { -; CHECK-LABEL: @select_fmul_swapped( -; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float 1.000000e+00, float [[B:%.*]] +define float @select_nnan_fmul_swapped(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_nnan_fmul_swapped( +; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float 1.000000e+00, float [[B:%.*]] ; CHECK-NEXT: [[D:%.*]] = fmul float [[C]], [[A:%.*]] ; CHECK-NEXT: ret float [[D]] ; %C = fmul float %A, %B - %D = select i1 %cond, float %A, float %C + %D = select nnan i1 %cond, float %A, float %C ret float %D } -define float @select_fmul_fast_math(i1 %cond, float %A, float %B) { -; CHECK-LABEL: @select_fmul_fast_math( -; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float [[B:%.*]], float 1.000000e+00 +define float @select_nnan_fmul_fast_math(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_nnan_fmul_fast_math( +; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float [[B:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[D:%.*]] = fmul fast float [[C]], [[A:%.*]] ; CHECK-NEXT: ret float [[D]] ; %C = fmul fast float %A, %B - %D = select i1 %cond, float %C, float %A + %D = select nnan i1 %cond, float %C, float %A ret float %D } -define float @select_fmul_swapped_fast_math(i1 %cond, float %A, float %B) { -; CHECK-LABEL: @select_fmul_swapped_fast_math( -; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float 1.000000e+00, float [[B:%.*]] +define float @select_nnan_fmul_swapped_fast_math(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_nnan_fmul_swapped_fast_math( +; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float 1.000000e+00, float [[B:%.*]] ; CHECK-NEXT: [[D:%.*]] = fmul fast float [[C]], [[A:%.*]] ; CHECK-NEXT: ret float [[D]] ; %C = fmul fast float %A, %B - %D = select i1 %cond, float %A, float %C + %D = select nnan i1 %cond, float %A, float %C ret float %D } -define float @select_fsub(i1 %cond, float %A, float %B) { -; CHECK-LABEL: @select_fsub( -; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float [[B:%.*]], float 0.000000e+00 +define float @select_nnan_fsub(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_nnan_fsub( +; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float [[B:%.*]], float 0.000000e+00 ; CHECK-NEXT: [[D:%.*]] = fsub float [[A:%.*]], [[C]] ; CHECK-NEXT: ret float [[D]] ; %C = fsub float %A, %B - %D = select i1 %cond, float %C, float %A + %D = select nnan i1 %cond, float %C, float %A ret float %D } -define float @select_fsub_swapped(i1 %cond, float %A, float %B) { -; CHECK-LABEL: @select_fsub_swapped( -; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float 0.000000e+00, float [[B:%.*]] +define float @select_nnan_fsub_swapped(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_nnan_fsub_swapped( +; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float 0.000000e+00, float [[B:%.*]] ; CHECK-NEXT: [[D:%.*]] = fsub float [[A:%.*]], [[C]] ; CHECK-NEXT: ret float [[D]] ; %C = fsub float %A, %B - %D = select i1 %cond, float %A, float %C + %D = select nnan i1 %cond, float %A, float %C ret float %D } -define float @select_fsub_fast_math(i1 %cond, float %A, float %B) { -; CHECK-LABEL: @select_fsub_fast_math( -; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float [[B:%.*]], float 0.000000e+00 +define float @select_nnan_fsub_fast_math(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_nnan_fsub_fast_math( +; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float [[B:%.*]], float 0.000000e+00 ; CHECK-NEXT: [[D:%.*]] = fsub fast float [[A:%.*]], [[C]] ; CHECK-NEXT: ret float [[D]] ; %C = fsub fast float %A, %B - %D = select i1 %cond, float %C, float %A + %D = select nnan i1 %cond, float %C, float %A ret float %D } -define float @select_fsub_swapped_fast_math(i1 %cond, float %A, float %B) { -; CHECK-LABEL: @select_fsub_swapped_fast_math( -; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float 0.000000e+00, float [[B:%.*]] +define float @select_nnan_fsub_swapped_fast_math(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_nnan_fsub_swapped_fast_math( +; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float 0.000000e+00, float [[B:%.*]] ; CHECK-NEXT: [[D:%.*]] = fsub fast float [[A:%.*]], [[C]] ; CHECK-NEXT: ret float [[D]] ; %C = fsub fast float %A, %B - %D = select i1 %cond, float %A, float %C + %D = select nnan i1 %cond, float %A, float %C ret float %D } -define <4 x float> @select_nsz_fsub_v4f32(<4 x i1> %cond, <4 x float> %A, <4 x float> %B) { -; CHECK-LABEL: @select_nsz_fsub_v4f32( -; CHECK-NEXT: [[C:%.*]] = select nsz <4 x i1> [[COND:%.*]], <4 x float> [[B:%.*]], <4 x float> zeroinitializer +define <4 x float> @select_nnan_nsz_fsub_v4f32(<4 x i1> %cond, <4 x float> %A, <4 x float> %B) { +; CHECK-LABEL: @select_nnan_nsz_fsub_v4f32( +; CHECK-NEXT: [[C:%.*]] = select nnan nsz <4 x i1> [[COND:%.*]], <4 x float> [[B:%.*]], <4 x float> zeroinitializer ; CHECK-NEXT: [[D:%.*]] = fsub <4 x float> [[A:%.*]], [[C]] ; CHECK-NEXT: ret <4 x float> [[D]] ; %C = fsub <4 x float> %A, %B - %D = select nsz <4 x i1> %cond, <4 x float> %C, <4 x float> %A + %D = select nnan nsz <4 x i1> %cond, <4 x float> %C, <4 x float> %A ret <4 x float> %D } -define <vscale x 4 x float> @select_nsz_fsub_nxv4f32(<vscale x 4 x i1> %cond, <vscale x 4 x float> %A, <vscale x 4 x float> %B) { -; CHECK-LABEL: @select_nsz_fsub_nxv4f32( -; CHECK-NEXT: [[C:%.*]] = select nsz <vscale x 4 x i1> [[COND:%.*]], <vscale x 4 x float> [[B:%.*]], <vscale x 4 x float> zeroinitializer +define <vscale x 4 x float> @select_nnan_nsz_fsub_nxv4f32(<vscale x 4 x i1> %cond, <vscale x 4 x float> %A, <vscale x 4 x float> %B) { +; CHECK-LABEL: @select_nnan_nsz_fsub_nxv4f32( +; CHECK-NEXT: [[C:%.*]] = select nnan nsz <vscale x 4 x i1> [[COND:%.*]], <vscale x 4 x float> [[B:%.*]], <vscale x 4 x float> zeroinitializer ; CHECK-NEXT: [[D:%.*]] = fsub <vscale x 4 x float> [[A:%.*]], [[C]] ; CHECK-NEXT: ret <vscale x 4 x float> [[D]] ; %C = fsub <vscale x 4 x float> %A, %B - %D = select nsz <vscale x 4 x i1> %cond, <vscale x 4 x float> %C, <vscale x 4 x float> %A + %D = select nnan nsz <vscale x 4 x i1> %cond, <vscale x 4 x float> %C, <vscale x 4 x float> %A ret <vscale x 4 x float> %D } ; 'fsub' can only fold on the amount subtracted. -define float @select_fsub_invalid(i1 %cond, float %A, float %B) { -; CHECK-LABEL: @select_fsub_invalid( +define float @select_nnan_fsub_invalid(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_nnan_fsub_invalid( ; CHECK-NEXT: [[C:%.*]] = fsub float [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[D:%.*]] = select i1 [[COND:%.*]], float [[C]], float [[A]] +; CHECK-NEXT: [[D:%.*]] = select nnan i1 [[COND:%.*]], float [[C]], float [[A]] ; CHECK-NEXT: ret float [[D]] ; %C = fsub float %B, %A - %D = select i1 %cond, float %C, float %A + %D = select nnan i1 %cond, float %C, float %A ret float %D } -define float @select_fdiv(i1 %cond, float %A, float %B) { -; CHECK-LABEL: @select_fdiv( -; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float [[B:%.*]], float 1.000000e+00 +define float @select_nnan_fdiv(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_nnan_fdiv( +; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float [[B:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[D:%.*]] = fdiv float [[A:%.*]], [[C]] ; CHECK-NEXT: ret float [[D]] ; %C = fdiv float %A, %B - %D = select i1 %cond, float %C, float %A + %D = select nnan i1 %cond, float %C, float %A ret float %D } -define float @select_fdiv_swapped(i1 %cond, float %A, float %B) { -; CHECK-LABEL: @select_fdiv_swapped( -; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float 1.000000e+00, float [[B:%.*]] +define float @select_nnan_fdiv_swapped(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_nnan_fdiv_swapped( +; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float 1.000000e+00, float [[B:%.*]] ; CHECK-NEXT: [[D:%.*]] = fdiv float [[A:%.*]], [[C]] ; CHECK-NEXT: ret float [[D]] ; %C = fdiv float %A, %B - %D = select i1 %cond, float %A, float %C + %D = select nnan i1 %cond, float %A, float %C ret float %D } -define float @select_fdiv_fast_math(i1 %cond, float %A, float %B) { -; CHECK-LABEL: @select_fdiv_fast_math( -; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float [[B:%.*]], float 1.000000e+00 +define float @select_nnan_fdiv_fast_math(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_nnan_fdiv_fast_math( +; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float [[B:%.*]], float 1.000000e+00 ; CHECK-NEXT: [[D:%.*]] = fdiv fast float [[A:%.*]], [[C]] ; CHECK-NEXT: ret float [[D]] ; %C = fdiv fast float %A, %B - %D = select i1 %cond, float %C, float %A + %D = select nnan i1 %cond, float %C, float %A ret float %D } -define float @select_fdiv_swapped_fast_math(i1 %cond, float %A, float %B) { -; CHECK-LABEL: @select_fdiv_swapped_fast_math( -; CHECK-NEXT: [[C:%.*]] = select i1 [[COND:%.*]], float 1.000000e+00, float [[B:%.*]] +define float @select_nnan_fdiv_swapped_fast_math(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_nnan_fdiv_swapped_fast_math( +; CHECK-NEXT: [[C:%.*]] = select nnan i1 [[COND:%.*]], float 1.000000e+00, float [[B:%.*]] ; CHECK-NEXT: [[D:%.*]] = fdiv fast float [[A:%.*]], [[C]] ; CHECK-NEXT: ret float [[D]] ; %C = fdiv fast float %A, %B - %D = select i1 %cond, float %A, float %C + %D = select nnan i1 %cond, float %A, float %C ret float %D } ; 'fdiv' can only fold on the divisor amount. -define float @select_fdiv_invalid(i1 %cond, float %A, float %B) { -; CHECK-LABEL: @select_fdiv_invalid( +define float @select_nnan_fdiv_invalid(i1 %cond, float %A, float %B) { +; CHECK-LABEL: @select_nnan_fdiv_invalid( ; CHECK-NEXT: [[C:%.*]] = fdiv float [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[D:%.*]] = select i1 [[COND:%.*]], float [[C]], float [[A]] +; CHECK-NEXT: [[D:%.*]] = select nnan i1 [[COND:%.*]], float [[C]], float [[A]] ; CHECK-NEXT: ret float [[D]] ; %C = fdiv float %B, %A - %D = select i1 %cond, float %C, float %A + %D = select nnan i1 %cond, float %C, float %A ret float %D } diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll index a84904106eced48edda99fc64f24c7ba09d3f487..278cabdff9ed3e3cd4492a234ceeb0772641aed5 100644 --- a/llvm/test/Transforms/InstCombine/select.ll +++ b/llvm/test/Transforms/InstCombine/select.ll @@ -2925,10 +2925,8 @@ define i8 @select_replacement_loop3(i32 noundef %x) { define i16 @select_replacement_loop4(i16 noundef %p_12) { ; CHECK-LABEL: @select_replacement_loop4( -; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i16 [[P_12:%.*]], 2 -; CHECK-NEXT: [[AND1:%.*]] = and i16 [[P_12]], 1 -; CHECK-NEXT: [[AND2:%.*]] = select i1 [[CMP1]], i16 [[AND1]], i16 0 -; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i16 [[AND2]], [[P_12]] +; CHECK-NEXT: [[AND1:%.*]] = and i16 [[P_12:%.*]], 1 +; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i16 [[P_12]], 2 ; CHECK-NEXT: [[AND3:%.*]] = select i1 [[CMP2]], i16 [[AND1]], i16 0 ; CHECK-NEXT: ret i16 [[AND3]] ; @@ -3708,3 +3706,59 @@ define i32 @src_select_xxory_eq0_xorxy_y(i32 %x, i32 %y) { %cond = select i1 %xor0, i32 %xor, i32 %y ret i32 %cond } + +define i32 @sequence_select_with_same_cond_false(i1 %c1, i1 %c2){ +; CHECK-LABEL: @sequence_select_with_same_cond_false( +; CHECK-NEXT: [[S1:%.*]] = select i1 [[C1:%.*]], i32 23, i32 45 +; CHECK-NEXT: [[S2:%.*]] = select i1 [[C2:%.*]], i32 666, i32 [[S1]] +; CHECK-NEXT: [[S3:%.*]] = select i1 [[C1]], i32 789, i32 [[S2]] +; CHECK-NEXT: ret i32 [[S3]] +; + %s1 = select i1 %c1, i32 23, i32 45 + %s2 = select i1 %c2, i32 666, i32 %s1 + %s3 = select i1 %c1, i32 789, i32 %s2 + ret i32 %s3 +} + +define i32 @sequence_select_with_same_cond_true(i1 %c1, i1 %c2){ +; CHECK-LABEL: @sequence_select_with_same_cond_true( +; CHECK-NEXT: [[S1:%.*]] = select i1 [[C1:%.*]], i32 45, i32 23 +; CHECK-NEXT: [[S2:%.*]] = select i1 [[C2:%.*]], i32 [[S1]], i32 666 +; CHECK-NEXT: [[S3:%.*]] = select i1 [[C1]], i32 [[S2]], i32 789 +; CHECK-NEXT: ret i32 [[S3]] +; + %s1 = select i1 %c1, i32 45, i32 23 + %s2 = select i1 %c2, i32 %s1, i32 666 + %s3 = select i1 %c1, i32 %s2, i32 789 + ret i32 %s3 +} + +define double @sequence_select_with_same_cond_double(double %a, i1 %c1, i1 %c2, double %r1, double %r2){ +; CHECK-LABEL: @sequence_select_with_same_cond_double( +; CHECK-NEXT: [[S1:%.*]] = select i1 [[C1:%.*]], double 1.000000e+00, double 0.000000e+00 +; CHECK-NEXT: [[S2:%.*]] = select i1 [[C2:%.*]], double [[S1]], double 2.000000e+00 +; CHECK-NEXT: [[S3:%.*]] = select i1 [[C1]], double [[S2]], double 3.000000e+00 +; CHECK-NEXT: ret double [[S3]] +; + %s1 = select i1 %c1, double 1.0, double 0.0 + %s2 = select i1 %c2, double %s1, double 2.0 + %s3 = select i1 %c1, double %s2, double 3.0 + ret double %s3 +} + +declare void @use32(i32) + +define i32 @sequence_select_with_same_cond_extra_use(i1 %c1, i1 %c2){ +; CHECK-LABEL: @sequence_select_with_same_cond_extra_use( +; CHECK-NEXT: [[S1:%.*]] = select i1 [[C1:%.*]], i32 23, i32 45 +; CHECK-NEXT: call void @use32(i32 [[S1]]) +; CHECK-NEXT: [[S2:%.*]] = select i1 [[C2:%.*]], i32 666, i32 [[S1]] +; CHECK-NEXT: [[S3:%.*]] = select i1 [[C1]], i32 789, i32 [[S2]] +; CHECK-NEXT: ret i32 [[S3]] +; + %s1 = select i1 %c1, i32 23, i32 45 + call void @use32(i32 %s1) + %s2 = select i1 %c2, i32 666, i32 %s1 + %s3 = select i1 %c1, i32 789, i32 %s2 + ret i32 %s3 +} diff --git a/llvm/test/Transforms/InstCombine/select_meta.ll b/llvm/test/Transforms/InstCombine/select_meta.ll index cd133101736cfc084b84cf421fb452079b6afc27..aa794e82e0fdc646b698fd3c8d7b8a8d4be0dcfe 100644 --- a/llvm/test/Transforms/InstCombine/select_meta.ll +++ b/llvm/test/Transforms/InstCombine/select_meta.ll @@ -360,23 +360,23 @@ define i128 @select_ashr(i1 %cond, i128 %x, i128 %y) { define double @select_fmul(i1 %cond, double %x, double %y) { ; CHECK-LABEL: @select_fmul( -; CHECK-NEXT: [[OP:%.*]] = select i1 [[COND:%.*]], double [[Y:%.*]], double 1.000000e+00, !prof [[PROF0]], !unpredictable [[META2]] +; CHECK-NEXT: [[OP:%.*]] = select nnan i1 [[COND:%.*]], double [[Y:%.*]], double 1.000000e+00, !prof [[PROF0]], !unpredictable [[META2]] ; CHECK-NEXT: [[RET:%.*]] = fmul double [[OP]], [[X:%.*]] ; CHECK-NEXT: ret double [[RET]] ; %op = fmul double %x, %y - %ret = select i1 %cond, double %op, double %x, !prof !1, !unpredictable !3 + %ret = select nnan i1 %cond, double %op, double %x, !prof !1, !unpredictable !3 ret double %ret } define <2 x float> @select_fdiv(i1 %cond, <2 x float> %x, <2 x float> %y) { ; CHECK-LABEL: @select_fdiv( -; CHECK-NEXT: [[OP:%.*]] = select i1 [[COND:%.*]], <2 x float> [[Y:%.*]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, !prof [[PROF0]], !unpredictable [[META2]] +; CHECK-NEXT: [[OP:%.*]] = select nnan i1 [[COND:%.*]], <2 x float> [[Y:%.*]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, !prof [[PROF0]], !unpredictable [[META2]] ; CHECK-NEXT: [[RET:%.*]] = fdiv <2 x float> [[X:%.*]], [[OP]] ; CHECK-NEXT: ret <2 x float> [[RET]] ; %op = fdiv <2 x float> %x, %y - %ret = select i1 %cond, <2 x float> %op, <2 x float> %x, !prof !1, !unpredictable !3 + %ret = select nnan i1 %cond, <2 x float> %op, <2 x float> %x, !prof !1, !unpredictable !3 ret <2 x float> %ret } diff --git a/llvm/test/Transforms/InstCombine/shift-add.ll b/llvm/test/Transforms/InstCombine/shift-add.ll index 1b25675059930b2ff5261557be7e9978b3b177a3..aa3a238e0949cee5b2ae11bcb1c5b12c4d531d56 100644 --- a/llvm/test/Transforms/InstCombine/shift-add.ll +++ b/llvm/test/Transforms/InstCombine/shift-add.ll @@ -775,3 +775,32 @@ define <3 x i32> @add3_i96(<3 x i32> %0, <3 x i32> %1) { %25 = insertelement <3 x i32> %24, i32 %20, i32 2 ret <3 x i32> %25 } + +define i8 @shl_fold_or_disjoint_cnt(i8 %x) { +; CHECK-LABEL: @shl_fold_or_disjoint_cnt( +; CHECK-NEXT: [[R:%.*]] = shl i8 16, [[X:%.*]] +; CHECK-NEXT: ret i8 [[R]] +; + %a = or disjoint i8 %x, 3 + %r = shl i8 2, %a + ret i8 %r +} + +define <2 x i8> @ashr_fold_or_disjoint_cnt(<2 x i8> %x) { +; CHECK-LABEL: @ashr_fold_or_disjoint_cnt( +; CHECK-NEXT: [[R:%.*]] = lshr <2 x i8> <i8 0, i8 1>, [[X:%.*]] +; CHECK-NEXT: ret <2 x i8> [[R]] +; + %a = or disjoint <2 x i8> %x, <i8 3, i8 1> + %r = ashr <2 x i8> <i8 2, i8 3>, %a + ret <2 x i8> %r +} + +define <2 x i8> @lshr_fold_or_disjoint_cnt_out_of_bounds(<2 x i8> %x) { +; CHECK-LABEL: @lshr_fold_or_disjoint_cnt_out_of_bounds( +; CHECK-NEXT: ret <2 x i8> zeroinitializer +; + %a = or disjoint <2 x i8> %x, <i8 3, i8 8> + %r = lshr <2 x i8> <i8 2, i8 3>, %a + ret <2 x i8> %r +} diff --git a/llvm/test/Transforms/InstCombine/shift-cttz-ctlz.ll b/llvm/test/Transforms/InstCombine/shift-cttz-ctlz.ll new file mode 100644 index 0000000000000000000000000000000000000000..2b2f820c9a095608edb1addadd9481857fba0fb2 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/shift-cttz-ctlz.ll @@ -0,0 +1,93 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +define i32 @shl_cttz_false(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @shl_cttz_false( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CTTZ:%.*]] = call i32 @llvm.cttz.i32(i32 [[Y]], i1 true), !range [[RNG0:![0-9]+]] +; CHECK-NEXT: [[RES:%.*]] = shl i32 [[X]], [[CTTZ]] +; CHECK-NEXT: ret i32 [[RES]] +; +entry: + %cttz = call i32 @llvm.cttz.i32(i32 %y, i1 false) + %res = shl i32 %x, %cttz + ret i32 %res +} + +define i32 @shl_ctlz_false(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @shl_ctlz_false( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CTTZ:%.*]] = call i32 @llvm.ctlz.i32(i32 [[Y]], i1 true), !range [[RNG0]] +; CHECK-NEXT: [[RES:%.*]] = shl i32 [[X]], [[CTTZ]] +; CHECK-NEXT: ret i32 [[RES]] +; +entry: + %cttz = call i32 @llvm.ctlz.i32(i32 %y, i1 false) + %res = shl i32 %x, %cttz + ret i32 %res +} + +define i32 @lshr_cttz_false(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @lshr_cttz_false( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CTTZ:%.*]] = call i32 @llvm.cttz.i32(i32 [[Y]], i1 true), !range [[RNG0]] +; CHECK-NEXT: [[RES:%.*]] = lshr i32 [[X]], [[CTTZ]] +; CHECK-NEXT: ret i32 [[RES]] +; +entry: + %cttz = call i32 @llvm.cttz.i32(i32 %y, i1 false) + %res = lshr i32 %x, %cttz + ret i32 %res +} + +define i32 @ashr_cttz_false(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @ashr_cttz_false( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CTTZ:%.*]] = call i32 @llvm.cttz.i32(i32 [[Y]], i1 true), !range [[RNG0]] +; CHECK-NEXT: [[RES:%.*]] = ashr i32 [[X]], [[CTTZ]] +; CHECK-NEXT: ret i32 [[RES]] +; +entry: + %cttz = call i32 @llvm.cttz.i32(i32 %y, i1 false) + %res = ashr i32 %x, %cttz + ret i32 %res +} + +define i32 @shl_cttz_false_multiuse(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @shl_cttz_false_multiuse( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CTTZ:%.*]] = call i32 @llvm.cttz.i32(i32 [[Y]], i1 false), !range [[RNG0]] +; CHECK-NEXT: call void @use(i32 [[CTTZ]]) +; CHECK-NEXT: [[RES:%.*]] = shl i32 [[X]], [[CTTZ]] +; CHECK-NEXT: ret i32 [[RES]] +; +entry: + %cttz = call i32 @llvm.cttz.i32(i32 %y, i1 false) + call void @use(i32 %cttz) + %res = shl i32 %x, %cttz + ret i32 %res +} + +define i32 @shl_cttz_as_lhs(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @shl_cttz_as_lhs( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CTTZ:%.*]] = call i32 @llvm.cttz.i32(i32 [[Y]], i1 false), !range [[RNG0]] +; CHECK-NEXT: [[RES:%.*]] = shl i32 [[CTTZ]], [[X]] +; CHECK-NEXT: ret i32 [[RES]] +; +entry: + %cttz = call i32 @llvm.cttz.i32(i32 %y, i1 false) + %res = shl i32 %cttz, %x + ret i32 %res +} + +declare void @use(i32) +;. +; CHECK: [[RNG0]] = !{i32 0, i32 33} +;. diff --git a/llvm/test/Transforms/InstCombine/shift.ll b/llvm/test/Transforms/InstCombine/shift.ll index 62f32c28683711ba3b56ea2fe700040fa7daa1e2..bef7fc81a7d1f9330e1aedddb3792dec81030af1 100644 --- a/llvm/test/Transforms/InstCombine/shift.ll +++ b/llvm/test/Transforms/InstCombine/shift.ll @@ -1751,12 +1751,11 @@ define void @ashr_out_of_range_1(ptr %A) { ; CHECK-NEXT: [[L:%.*]] = load i177, ptr [[A:%.*]], align 4 ; CHECK-NEXT: [[L_FROZEN:%.*]] = freeze i177 [[L]] ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i177 [[L_FROZEN]], -1 -; CHECK-NEXT: [[B:%.*]] = select i1 [[TMP1]], i177 0, i177 [[L_FROZEN]] -; CHECK-NEXT: [[TMP2:%.*]] = trunc i177 [[B]] to i64 +; CHECK-NEXT: [[TMP6:%.*]] = trunc i177 [[L_FROZEN]] to i64 +; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP6]] ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i177, ptr [[A]], i64 [[TMP2]] ; CHECK-NEXT: [[G11:%.*]] = getelementptr i8, ptr [[TMP3]], i64 -24 -; CHECK-NEXT: [[C17:%.*]] = icmp sgt i177 [[B]], [[L_FROZEN]] -; CHECK-NEXT: [[TMP4:%.*]] = sext i1 [[C17]] to i64 +; CHECK-NEXT: [[TMP4:%.*]] = sext i1 [[TMP1]] to i64 ; CHECK-NEXT: [[G62:%.*]] = getelementptr i177, ptr [[G11]], i64 [[TMP4]] ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i177 [[L_FROZEN]], -1 ; CHECK-NEXT: [[B28:%.*]] = select i1 [[TMP5]], i177 0, i177 [[L_FROZEN]] diff --git a/llvm/test/Transforms/InstCombine/shuffle_select-inseltpoison.ll b/llvm/test/Transforms/InstCombine/shuffle_select-inseltpoison.ll index 44ec77e471bb41ab0bff520020aeca455d4fa6a6..f573ff36d2cea4cef20a86924da983be620d8c93 100644 --- a/llvm/test/Transforms/InstCombine/shuffle_select-inseltpoison.ll +++ b/llvm/test/Transforms/InstCombine/shuffle_select-inseltpoison.ll @@ -336,7 +336,18 @@ define <4 x i32> @srem(<4 x i32> %v) { ; Try FP ops/types. -define <4 x float> @fadd(<4 x float> %v) { +define <4 x float> @fadd_maybe_nan(<4 x float> %v) { +; CHECK-LABEL: @fadd_maybe_nan( +; CHECK-NEXT: [[B:%.*]] = fadd <4 x float> [[V:%.*]], <float 4.100000e+01, float 4.200000e+01, float poison, float poison> +; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x float> [[B]], <4 x float> [[V]], <4 x i32> <i32 0, i32 1, i32 6, i32 7> +; CHECK-NEXT: ret <4 x float> [[S]] +; + %b = fadd <4 x float> %v, <float 41.0, float 42.0, float 43.0, float 44.0> + %s = shufflevector <4 x float> %b, <4 x float> %v, <4 x i32> <i32 0, i32 1, i32 6, i32 7> + ret <4 x float> %s +} + +define <4 x float> @fadd(<4 x float> nofpclass(nan) %v) { ; CHECK-LABEL: @fadd( ; CHECK-NEXT: [[S:%.*]] = fadd <4 x float> [[V:%.*]], <float 4.100000e+01, float 4.200000e+01, float -0.000000e+00, float -0.000000e+00> ; CHECK-NEXT: ret <4 x float> [[S]] @@ -359,7 +370,7 @@ define <4 x double> @fsub(<4 x double> %v) { ; Propagate any FMF. -define <4 x float> @fmul(<4 x float> %v) { +define <4 x float> @fmul(<4 x float> nofpclass(nan) %v) { ; CHECK-LABEL: @fmul( ; CHECK-NEXT: [[S:%.*]] = fmul nnan ninf <4 x float> [[V:%.*]], <float 4.100000e+01, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00> ; CHECK-NEXT: ret <4 x float> [[S]] @@ -380,7 +391,7 @@ define <4 x double> @fdiv_constant_op0(<4 x double> %v) { ret <4 x double> %s } -define <4 x double> @fdiv_constant_op1(<4 x double> %v) { +define <4 x double> @fdiv_constant_op1(<4 x double> nofpclass(nan) %v) { ; CHECK-LABEL: @fdiv_constant_op1( ; CHECK-NEXT: [[S:%.*]] = fdiv reassoc <4 x double> [[V:%.*]], <double undef, double 1.000000e+00, double 4.300000e+01, double 4.400000e+01> ; CHECK-NEXT: ret <4 x double> [[S]] diff --git a/llvm/test/Transforms/InstCombine/shuffle_select.ll b/llvm/test/Transforms/InstCombine/shuffle_select.ll index a1b0d782b554f95915589f195efcfe0c551ae01c..efadb5c3c10940d54e854c0849f778e0506c05e9 100644 --- a/llvm/test/Transforms/InstCombine/shuffle_select.ll +++ b/llvm/test/Transforms/InstCombine/shuffle_select.ll @@ -336,7 +336,18 @@ define <4 x i32> @srem(<4 x i32> %v) { ; Try FP ops/types. -define <4 x float> @fadd(<4 x float> %v) { +define <4 x float> @fadd_maybe_nan(<4 x float> %v) { +; CHECK-LABEL: @fadd_maybe_nan( +; CHECK-NEXT: [[B:%.*]] = fadd <4 x float> [[V:%.*]], <float 4.100000e+01, float 4.200000e+01, float poison, float poison> +; CHECK-NEXT: [[S:%.*]] = shufflevector <4 x float> [[B]], <4 x float> [[V]], <4 x i32> <i32 0, i32 1, i32 6, i32 7> +; CHECK-NEXT: ret <4 x float> [[S]] +; + %b = fadd <4 x float> %v, <float 41.0, float 42.0, float 43.0, float 44.0> + %s = shufflevector <4 x float> %b, <4 x float> %v, <4 x i32> <i32 0, i32 1, i32 6, i32 7> + ret <4 x float> %s +} + +define <4 x float> @fadd(<4 x float> nofpclass(nan) %v) { ; CHECK-LABEL: @fadd( ; CHECK-NEXT: [[S:%.*]] = fadd <4 x float> [[V:%.*]], <float 4.100000e+01, float 4.200000e+01, float -0.000000e+00, float -0.000000e+00> ; CHECK-NEXT: ret <4 x float> [[S]] @@ -359,7 +370,7 @@ define <4 x double> @fsub(<4 x double> %v) { ; Propagate any FMF. -define <4 x float> @fmul(<4 x float> %v) { +define <4 x float> @fmul(<4 x float> nofpclass(nan) %v) { ; CHECK-LABEL: @fmul( ; CHECK-NEXT: [[S:%.*]] = fmul nnan ninf <4 x float> [[V:%.*]], <float 4.100000e+01, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00> ; CHECK-NEXT: ret <4 x float> [[S]] @@ -380,7 +391,7 @@ define <4 x double> @fdiv_constant_op0(<4 x double> %v) { ret <4 x double> %s } -define <4 x double> @fdiv_constant_op1(<4 x double> %v) { +define <4 x double> @fdiv_constant_op1(<4 x double> nofpclass(nan) %v) { ; CHECK-LABEL: @fdiv_constant_op1( ; CHECK-NEXT: [[S:%.*]] = fdiv reassoc <4 x double> [[V:%.*]], <double undef, double 1.000000e+00, double 4.300000e+01, double 4.400000e+01> ; CHECK-NEXT: ret <4 x double> [[S]] diff --git a/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll b/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll index 2e1ff0a21a3def9c18e934533a87c2c1f5f389d4..461c9b0fb1e0c0ac9f8ce0bd4176d015315c4417 100644 --- a/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll +++ b/llvm/test/Transforms/InstCombine/sub-xor-cmp.ll @@ -117,11 +117,9 @@ define i64 @sext_diff_i1_xor_sub_1(i64 %a, i1 %b, i1 %c) { define i64 @sext_multi_uses(i64 %a, i1 %b, i64 %x) { ; CHECK-LABEL: define i64 @sext_multi_uses( ; CHECK-SAME: i64 [[A:%.*]], i1 [[B:%.*]], i64 [[X:%.*]]) { -; CHECK-NEXT: [[C:%.*]] = sext i1 [[B]] to i64 -; CHECK-NEXT: [[TMP1:%.*]] = sub i64 0, [[A]] -; CHECK-NEXT: [[E:%.*]] = select i1 [[B]], i64 [[TMP1]], i64 [[A]] -; CHECK-NEXT: [[F:%.*]] = mul i64 [[C]], [[X]] -; CHECK-NEXT: [[R:%.*]] = add i64 [[F]], [[E]] +; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[X]], [[A]] +; CHECK-NEXT: [[TMP2:%.*]] = sub i64 0, [[TMP1]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[B]], i64 [[TMP2]], i64 [[A]] ; CHECK-NEXT: ret i64 [[R]] ; %c = sext i1 %b to i64 diff --git a/llvm/test/Transforms/InstCombine/trunc.ll b/llvm/test/Transforms/InstCombine/trunc.ll index c6bc06d666d0aed29cbb4029cc4834ad6c9a0fb5..760825d6b1da0d574ad0487c0a4de04ad0b21c7a 100644 --- a/llvm/test/Transforms/InstCombine/trunc.ll +++ b/llvm/test/Transforms/InstCombine/trunc.ll @@ -1021,3 +1021,40 @@ define i16 @PR44545(i32 %t0, i32 %data) { %sub = add nsw i16 %cast, -1 ret i16 %sub } + +; Make sure that SimplifyDemandedBits drops the nowrap flags +define i8 @drop_nsw_trunc(i16 %x, i16 %y) { +; CHECK-LABEL: @drop_nsw_trunc( +; CHECK-NEXT: [[AND2:%.*]] = and i16 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[RES:%.*]] = trunc i16 [[AND2]] to i8 +; CHECK-NEXT: ret i8 [[RES]] +; + %and = and i16 %x, 255 + %and2 = and i16 %and, %y + %res = trunc nsw i16 %and2 to i8 + ret i8 %res +} + +define i8 @drop_nuw_trunc(i16 %x, i16 %y) { +; CHECK-LABEL: @drop_nuw_trunc( +; CHECK-NEXT: [[AND2:%.*]] = and i16 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[B:%.*]] = trunc i16 [[AND2]] to i8 +; CHECK-NEXT: ret i8 [[B]] +; + %and = and i16 %x, 255 + %and2 = and i16 %and, %y + %res = trunc nuw i16 %and2 to i8 + ret i8 %res +} + +define i8 @drop_both_trunc(i16 %x, i16 %y) { +; CHECK-LABEL: @drop_both_trunc( +; CHECK-NEXT: [[AND2:%.*]] = and i16 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[RES:%.*]] = trunc i16 [[AND2]] to i8 +; CHECK-NEXT: ret i8 [[RES]] +; + %and = and i16 %x, 255 + %and2 = and i16 %and, %y + %res = trunc nuw nsw i16 %and2 to i8 + ret i8 %res +} diff --git a/llvm/test/Transforms/InstCombine/uadd-with-overflow.ll b/llvm/test/Transforms/InstCombine/uadd-with-overflow.ll index 28d309baaa41d35554c52b4f1a8cb51cbc527d45..fd5d38bb38ddc79c1126e02867c5129f3a27ab35 100644 --- a/llvm/test/Transforms/InstCombine/uadd-with-overflow.ll +++ b/llvm/test/Transforms/InstCombine/uadd-with-overflow.ll @@ -124,3 +124,26 @@ define { i32, i1 } @no_fold_wrapped_add(i32 %x) { %b = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 30, i32 %a) ret { i32, i1 } %b } + + +define { <2 x i32>, <2 x i1> } @fold_simple_splat_with_disjoint_or_constant(<2 x i32> %x) { +; CHECK-LABEL: @fold_simple_splat_with_disjoint_or_constant( +; CHECK-NEXT: [[B:%.*]] = call { <2 x i32>, <2 x i1> } @llvm.uadd.with.overflow.v2i32(<2 x i32> [[X:%.*]], <2 x i32> <i32 42, i32 42>) +; CHECK-NEXT: ret { <2 x i32>, <2 x i1> } [[B]] +; + %a = or disjoint <2 x i32> %x, <i32 12, i32 12> + %b = tail call { <2 x i32>, <2 x i1> } @llvm.uadd.with.overflow.v2i32(<2 x i32> %a, <2 x i32> <i32 30, i32 30>) + ret { <2 x i32>, <2 x i1> } %b +} + + +define { <2 x i32>, <2 x i1> } @fold_simple_splat_constant_with_or_fail(<2 x i32> %x) { +; CHECK-LABEL: @fold_simple_splat_constant_with_or_fail( +; CHECK-NEXT: [[A:%.*]] = or <2 x i32> [[X:%.*]], <i32 12, i32 12> +; CHECK-NEXT: [[B:%.*]] = tail call { <2 x i32>, <2 x i1> } @llvm.uadd.with.overflow.v2i32(<2 x i32> [[A]], <2 x i32> <i32 30, i32 30>) +; CHECK-NEXT: ret { <2 x i32>, <2 x i1> } [[B]] +; + %a = or <2 x i32> %x, <i32 12, i32 12> + %b = tail call { <2 x i32>, <2 x i1> } @llvm.uadd.with.overflow.v2i32(<2 x i32> %a, <2 x i32> <i32 30, i32 30>) + ret { <2 x i32>, <2 x i1> } %b +} diff --git a/llvm/test/Transforms/InstCombine/zext.ll b/llvm/test/Transforms/InstCombine/zext.ll index edbd4850fb1190b374e3416dbb0ecb6c2c5848e8..88cd9c70af40d8b3d16f09d0075ce5f55c361514 100644 --- a/llvm/test/Transforms/InstCombine/zext.ll +++ b/llvm/test/Transforms/InstCombine/zext.ll @@ -836,3 +836,34 @@ define i64 @zext_nneg_demanded_constant(i8 %a) nounwind { %c = and i64 %b, 254 ret i64 %c } + +define i32 @zext_nneg_i1(i1 %x) { +; CHECK-LABEL: @zext_nneg_i1( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret i32 0 +; +entry: + %res = zext nneg i1 %x to i32 + ret i32 %res +} + +define <2 x i32> @zext_nneg_i1_vec(<2 x i1> %x) { +; CHECK-LABEL: @zext_nneg_i1_vec( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret <2 x i32> zeroinitializer +; +entry: + %res = zext nneg <2 x i1> %x to <2 x i32> + ret <2 x i32> %res +} + +define i32 @zext_nneg_i2(i2 %x) { +; CHECK-LABEL: @zext_nneg_i2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RES:%.*]] = zext nneg i2 [[X:%.*]] to i32 +; CHECK-NEXT: ret i32 [[RES]] +; +entry: + %res = zext nneg i2 %x to i32 + ret i32 %res +} diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/gep.ll b/llvm/test/Transforms/InstSimplify/ConstProp/gep.ll index 6dd34a481df134b8760cffdc7faf98906c7173cf..d91349a570b7155be1bca058bbf8eb4acd4e1258 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/gep.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/gep.ll @@ -11,21 +11,21 @@ target triple = "x86_64-unknown-linux-gnu" define ptr @f0() { ; CHECK-LABEL: @f0( -; CHECK-NEXT: ret ptr getelementptr inbounds ([3 x ptr], ptr @vt, inrange i64 0, i64 2) +; CHECK-NEXT: ret ptr getelementptr inbounds inrange(-16, 8) ([3 x ptr], ptr @vt, i64 0, i64 2) ; - ret ptr getelementptr (ptr, ptr getelementptr inbounds ([3 x ptr], ptr @vt, inrange i64 0, i64 1), i64 1) + ret ptr getelementptr (ptr, ptr getelementptr inbounds inrange(-8, 16) ([3 x ptr], ptr @vt, i64 0, i64 1), i64 1) } define ptr @f1() { ; CHECK-LABEL: @f1( -; CHECK-NEXT: ret ptr getelementptr inbounds ([3 x ptr], ptr @vt, i64 0, i64 2) +; CHECK-NEXT: ret ptr getelementptr inbounds inrange(-8, 0) ([3 x ptr], ptr @vt, i64 0, i64 2) ; - ret ptr getelementptr (ptr, ptr getelementptr inbounds ([3 x ptr], ptr @vt, i64 0, inrange i64 1), i64 1) + ret ptr getelementptr (ptr, ptr getelementptr inbounds inrange(0, 8) ([3 x ptr], ptr @vt, i64 0, i64 1), i64 1) } define ptr @f2() { ; CHECK-LABEL: @f2( -; CHECK-NEXT: ret ptr getelementptr ([3 x ptr], ptr @vt, i64 1, i64 1) +; CHECK-NEXT: ret ptr getelementptr inrange(-24, -16) ([3 x ptr], ptr @vt, i64 1, i64 1) ; - ret ptr getelementptr (ptr, ptr getelementptr inbounds ([3 x ptr], ptr @vt, i64 0, inrange i64 1), i64 3) + ret ptr getelementptr (ptr, ptr getelementptr inbounds inrange(0, 8) ([3 x ptr], ptr @vt, i64 0, i64 1), i64 3) } diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/icmp-global.ll b/llvm/test/Transforms/InstSimplify/ConstProp/icmp-global.ll index 3851bd090aef9f47aba73e7a04821189c29598aa..b4afb7bd4a2b0e9d8ff386e5b2f65598b901a4aa 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/icmp-global.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/icmp-global.ll @@ -298,3 +298,11 @@ bb: %cmp = icmp eq ptr blockaddress(@blockaddr_no_cfi, %bb), no_cfi @func ret i1 %cmp } + +define i1 @global_no_cfi_dso_local_equivalent() { +; CHECK-LABEL: @global_no_cfi_dso_local_equivalent( +; CHECK-NEXT: ret i1 icmp eq (ptr dso_local_equivalent @func, ptr no_cfi @func) +; + %cmp = icmp eq ptr dso_local_equivalent @func, no_cfi @func + ret i1 %cmp +} diff --git a/llvm/test/Transforms/InstSimplify/floating-point-arithmetic.ll b/llvm/test/Transforms/InstSimplify/floating-point-arithmetic.ll index b8244b1d508c629ea4bdd3f5e5c664c77db22de9..5d17504c09df67f8a73df5cfaacae9244196d1ce 100644 --- a/llvm/test/Transforms/InstSimplify/floating-point-arithmetic.ll +++ b/llvm/test/Transforms/InstSimplify/floating-point-arithmetic.ll @@ -211,6 +211,50 @@ define double @fmul_nnan_ninf_nneg_n0.0_commute(i127 %x) { ret double %r } +define float @src_mul_nzero_neg(float nofpclass(inf nan pzero psub pnorm) %f) { +; CHECK-LABEL: @src_mul_nzero_neg( +; CHECK-NEXT: ret float 0.000000e+00 +; + %r = fmul float %f, -0.0 + ret float %r +} + +define <2 x float> @src_mul_zero_neg(<2 x float> nofpclass(inf nan pzero psub pnorm) %f) { +; CHECK-LABEL: @src_mul_zero_neg( +; CHECK-NEXT: ret <2 x float> <float -0.000000e+00, float -0.000000e+00> +; + %r = fmul <2 x float> <float 0.0, float 0.0>, %f + ret <2 x float> %r +} + +define <2 x float> @src_mul_zero_and_nzero_neg(<2 x float> nofpclass(inf nan pzero psub pnorm) %f) { +; CHECK-LABEL: @src_mul_zero_and_nzero_neg( +; CHECK-NEXT: ret <2 x float> <float 0.000000e+00, float -0.000000e+00> +; + %r = fmul <2 x float> <float -0.0, float 0.0>, %f + ret <2 x float> %r +} + + +define float @src_muladd_zero_neg(float nofpclass(inf nan pzero psub pnorm) %f, float %add) { +; CHECK-LABEL: @src_muladd_zero_neg( +; CHECK-NEXT: [[R:%.*]] = call float @llvm.fmuladd.f32(float [[F:%.*]], float 0.000000e+00, float [[ADD:%.*]]) +; CHECK-NEXT: ret float [[R]] +; + %r = call float @llvm.fmuladd.f32(float %f, float 0.0, float %add) + ret float %r +} + +define float @src_fma_nzero_neg(float nofpclass(inf nan pzero psub pnorm) %f, float %add) { +; CHECK-LABEL: @src_fma_nzero_neg( +; CHECK-NEXT: [[R:%.*]] = call float @llvm.fma.f32(float -0.000000e+00, float [[F:%.*]], float [[ADD:%.*]]) +; CHECK-NEXT: ret float [[R]] +; + %r = call float @llvm.fma.f32(float -0.0, float %f, float %add) + ret float %r +} + + ; Make sure we can infer %x can't be 0 based on assumes. define { float, float } @test_fmul_0_assumed_finite(float %x) { ; CHECK-LABEL: @test_fmul_0_assumed_finite( diff --git a/llvm/test/Transforms/InstSimplify/icmp-constant.ll b/llvm/test/Transforms/InstSimplify/icmp-constant.ll index 04261f6f40b7c333b5d812d7940feff6c1bb7c78..99bf11bd4e8c472693f4d68f40a6b8b247990492 100644 --- a/llvm/test/Transforms/InstSimplify/icmp-constant.ll +++ b/llvm/test/Transforms/InstSimplify/icmp-constant.ll @@ -1140,3 +1140,131 @@ define <2 x i1> @heterogeneous_constvector(<2 x i8> %x) { %c = icmp ult <2 x i8> %x, <i8 undef, i8 poison> ret <2 x i1> %c } + +define i1 @icmp_eq_constant_range_attr(i8 range(i8 0, 10) %i) { +; CHECK-LABEL: @icmp_eq_constant_range_attr( +; CHECK-NEXT: ret i1 false +; + %cmp = icmp eq i8 %i, 10 + ret i1 %cmp +} + +define i1 @neg_icmp_eq_constant_range_attr(i8 range(i8 0, 11) %i) { +; CHECK-LABEL: @neg_icmp_eq_constant_range_attr( +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[I:%.*]], 10 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = icmp eq i8 %i, 10 + ret i1 %cmp +} + +declare range(i8 1, 0) i8 @returns_non_ten_range_helper() +declare range(i8 -1, 1) i8 @returns_contain_ten_range_helper() + +define i1 @icmp_eq_constant_range_return() { +; CHECK-LABEL: @icmp_eq_constant_range_return( +; CHECK-NEXT: [[I:%.*]] = call i8 @returns_non_ten_range_helper() +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[I]], 10 +; CHECK-NEXT: ret i1 [[CMP]] +; + %i = call i8 @returns_non_ten_range_helper() + %cmp = icmp eq i8 %i, 10 + ret i1 %cmp +} + +define i1 @neg_icmp_eq_constant_range_return() { +; CHECK-LABEL: @neg_icmp_eq_constant_range_return( +; CHECK-NEXT: [[I:%.*]] = call i8 @returns_contain_ten_range_helper() +; CHECK-NEXT: ret i1 false +; + %i = call i8 @returns_contain_ten_range_helper() + %cmp = icmp eq i8 %i, 10 + ret i1 %cmp +} + +declare i8 @returns_i8_helper() + +define i1 @icmp_eq_constant_range_call() { +; CHECK-LABEL: @icmp_eq_constant_range_call( +; CHECK-NEXT: [[I:%.*]] = call range(i8 0, 10) i8 @returns_i8_helper() +; CHECK-NEXT: ret i1 false +; + %i = call range(i8 0, 10) i8 @returns_i8_helper() + %cmp = icmp eq i8 %i, 10 + ret i1 %cmp +} + +define i1 @neg_icmp_eq_constant_range_call() { +; CHECK-LABEL: @neg_icmp_eq_constant_range_call( +; CHECK-NEXT: [[I:%.*]] = call range(i8 0, 11) i8 @returns_i8_helper() +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[I]], 10 +; CHECK-NEXT: ret i1 [[CMP]] +; + %i = call range(i8 0, 11) i8 @returns_i8_helper() + %cmp = icmp eq i8 %i, 10 + ret i1 %cmp +} + +define <2 x i1> @icmp_eq_constant_range_attr_vec(<2 x i8> range(i8 0, 10) %i) { +; CHECK-LABEL: @icmp_eq_constant_range_attr_vec( +; CHECK-NEXT: ret <2 x i1> zeroinitializer +; + %cmp = icmp eq <2 x i8> %i, <i8 10, i8 10> + ret <2 x i1> %cmp +} + +define <2 x i1> @neg_icmp_eq_constant_range_attr_vec(<2 x i8> range(i8 0, 11) %i) { +; CHECK-LABEL: @neg_icmp_eq_constant_range_attr_vec( +; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[I:%.*]], <i8 10, i8 10> +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %cmp = icmp eq <2 x i8> %i, <i8 10, i8 10> + ret <2 x i1> %cmp +} + +declare range(i8 0, 10) <2 x i8> @returns_non_ten_range_helper_vec() +declare range(i8 0, 11) <2 x i8> @returns_contain_ten_range_helper_vec() + +define <2 x i1> @icmp_eq_constant_range_return_vec() { +; CHECK-LABEL: @icmp_eq_constant_range_return_vec( +; CHECK-NEXT: [[I:%.*]] = call <2 x i8> @returns_non_ten_range_helper_vec() +; CHECK-NEXT: ret <2 x i1> zeroinitializer +; + %i = call <2 x i8> @returns_non_ten_range_helper_vec() + %cmp = icmp eq <2 x i8> %i, <i8 10, i8 10> + ret <2 x i1> %cmp +} + +define <2 x i1> @neg_icmp_eq_constant_range_return_vec() { +; CHECK-LABEL: @neg_icmp_eq_constant_range_return_vec( +; CHECK-NEXT: [[I:%.*]] = call <2 x i8> @returns_contain_ten_range_helper_vec() +; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[I]], <i8 10, i8 10> +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %i = call <2 x i8> @returns_contain_ten_range_helper_vec() + %cmp = icmp eq <2 x i8> %i, <i8 10, i8 10> + ret <2 x i1> %cmp +} + +declare <2 x i8> @returns_i8_helper_vec() + +define <2 x i1> @icmp_eq_constant_range_call_vec() { +; CHECK-LABEL: @icmp_eq_constant_range_call_vec( +; CHECK-NEXT: [[I:%.*]] = call range(i8 0, 10) <2 x i8> @returns_i8_helper_vec() +; CHECK-NEXT: ret <2 x i1> zeroinitializer +; + %i = call range(i8 0, 10) <2 x i8> @returns_i8_helper_vec() + %cmp = icmp eq <2 x i8> %i, <i8 10, i8 10> + ret <2 x i1> %cmp +} + +define <2 x i1> @neg_icmp_eq_constant_range_call_vec() { +; CHECK-LABEL: @neg_icmp_eq_constant_range_call_vec( +; CHECK-NEXT: [[I:%.*]] = call range(i8 0, 11) <2 x i8> @returns_i8_helper_vec() +; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[I]], <i8 10, i8 10> +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %i = call range(i8 0, 11) <2 x i8> @returns_i8_helper_vec() + %cmp = icmp eq <2 x i8> %i, <i8 10, i8 10> + ret <2 x i1> %cmp +} diff --git a/llvm/test/Transforms/InstSimplify/shift-knownbits.ll b/llvm/test/Transforms/InstSimplify/shift-knownbits.ll index c2256f4b14af83160b98df65d0ef96d99cffd3f8..6bf03779379ec731fba97b3a7d68b9cfd5360153 100644 --- a/llvm/test/Transforms/InstSimplify/shift-knownbits.ll +++ b/llvm/test/Transforms/InstSimplify/shift-knownbits.ll @@ -14,6 +14,145 @@ define i32 @shl_amount_is_known_bogus(i32 %a, i32 %b) { ret i32 %shl } +define i32 @shl_amount_is_known_bogus_range_attr(i32 %a, i32 range(i32 32, 64) %b) { +; CHECK-LABEL: @shl_amount_is_known_bogus_range_attr( +; CHECK-NEXT: ret i32 poison +; + %shl = shl i32 %a, %b + ret i32 %shl +} + +define i32 @neg_shl_amount_is_known_bogus_range_attr(i32 %a, i32 range(i32 0, 32) %b) { +; CHECK-LABEL: @neg_shl_amount_is_known_bogus_range_attr( +; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: ret i32 [[SHL]] +; + %shl = shl i32 %a, %b + ret i32 %shl +} + +declare range(i32 32, 64) i32 @returns_out_of_range_helper() +declare range(i32 0, 32) i32 @returns_in_range_helper() + +define i32 @shl_amount_is_known_bogus_range_return(i32 %a) { +; CHECK-LABEL: @shl_amount_is_known_bogus_range_return( +; CHECK-NEXT: [[B:%.*]] = call i32 @returns_out_of_range_helper() +; CHECK-NEXT: ret i32 poison +; + %b = call i32 @returns_out_of_range_helper() + %shl = shl i32 %a, %b + ret i32 %shl +} + +define i32 @neg_shl_amount_is_known_bogus_range_return(i32 %a) { +; CHECK-LABEL: @neg_shl_amount_is_known_bogus_range_return( +; CHECK-NEXT: [[B:%.*]] = call i32 @returns_in_range_helper() +; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A:%.*]], [[B]] +; CHECK-NEXT: ret i32 [[SHL]] +; + %b = call i32 @returns_in_range_helper() + %shl = shl i32 %a, %b + ret i32 %shl +} + +declare i32 @returns_i32_helper() + +define i32 @shl_amount_is_known_bogus_range_call(i32 %a) { +; CHECK-LABEL: @shl_amount_is_known_bogus_range_call( +; CHECK-NEXT: [[B:%.*]] = call range(i32 32, 64) i32 @returns_i32_helper() +; CHECK-NEXT: ret i32 poison +; + %b = call range(i32 32, 64) i32 @returns_i32_helper() + %shl = shl i32 %a, %b + ret i32 %shl +} + +define i32 @neg_shl_amount_is_known_bogus_range_call(i32 %a) { +; CHECK-LABEL: @neg_shl_amount_is_known_bogus_range_call( +; CHECK-NEXT: [[B:%.*]] = call range(i32 0, 32) i32 @returns_i32_helper() +; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A:%.*]], [[B]] +; CHECK-NEXT: ret i32 [[SHL]] +; + %b = call range(i32 0, 32) i32 @returns_i32_helper() + %shl = shl i32 %a, %b + ret i32 %shl +} + +define <2 x i32> @shl_amount_is_known_bogus_range_attr_vec(<2 x i32> %a, <2 x i32> range(i32 32, 64) %b) { +; CHECK-LABEL: @shl_amount_is_known_bogus_range_attr_vec( +; CHECK-NEXT: ret <2 x i32> poison +; + %shl = shl <2 x i32> %a, %b + ret <2 x i32> %shl +} + +define <2 x i32> @neg_shl_amount_is_known_bogus_range_attr_vec(<2 x i32> %a, <2 x i32> range(i32 0, 32) %b) { +; CHECK-LABEL: @neg_shl_amount_is_known_bogus_range_attr_vec( +; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i32> [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: ret <2 x i32> [[SHL]] +; + %shl = shl <2 x i32> %a, %b + ret <2 x i32> %shl +} + +declare range(i32 32, 64) <2 x i32> @returns_out_of_range_helper_vec() +declare range(i32 0, 32) <2 x i32> @returns_in_range_helper_vec() + +define <2 x i32> @shl_amount_is_known_bogus_range_return_vec(<2 x i32> %a) { +; CHECK-LABEL: @shl_amount_is_known_bogus_range_return_vec( +; CHECK-NEXT: [[B:%.*]] = call <2 x i32> @returns_out_of_range_helper_vec() +; CHECK-NEXT: ret <2 x i32> poison +; + %b = call <2 x i32> @returns_out_of_range_helper_vec() + %shl = shl <2 x i32> %a, %b + ret <2 x i32> %shl +} + +define <2 x i32> @neg_shl_amount_is_known_bogus_range_return_vec(<2 x i32> %a) { +; CHECK-LABEL: @neg_shl_amount_is_known_bogus_range_return_vec( +; CHECK-NEXT: [[B:%.*]] = call <2 x i32> @returns_in_range_helper_vec() +; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i32> [[A:%.*]], [[B]] +; CHECK-NEXT: ret <2 x i32> [[SHL]] +; + %b = call <2 x i32> @returns_in_range_helper_vec() + %shl = shl <2 x i32> %a, %b + ret <2 x i32> %shl +} + +declare <2 x i32> @returns_i32_helper_vec() + +define <2 x i32> @shl_amount_is_known_bogus_range_call_vec(<2 x i32> %a) { +; CHECK-LABEL: @shl_amount_is_known_bogus_range_call_vec( +; CHECK-NEXT: [[B:%.*]] = call range(i32 32, 64) <2 x i32> @returns_i32_helper_vec() +; CHECK-NEXT: ret <2 x i32> poison +; + %b = call range(i32 32, 64) <2 x i32> @returns_i32_helper_vec() + %shl = shl <2 x i32> %a, %b + ret <2 x i32> %shl +} + +define <2 x i32> @neg_shl_amount_is_known_bogus_range_call_vec(<2 x i32> %a) { +; CHECK-LABEL: @neg_shl_amount_is_known_bogus_range_call_vec( +; CHECK-NEXT: [[B:%.*]] = call range(i32 0, 32) <2 x i32> @returns_i32_helper_vec() +; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i32> [[A:%.*]], [[B]] +; CHECK-NEXT: ret <2 x i32> [[SHL]] +; + %b = call range(i32 0, 32) <2 x i32> @returns_i32_helper_vec() + %shl = shl <2 x i32> %a, %b + ret <2 x i32> %shl +} + +define i32 @shl_amount_is_not_known_bogus_range_call_and_range_metadata(i32 %a) { +; CHECK-LABEL: @shl_amount_is_not_known_bogus_range_call_and_range_metadata( +; CHECK-NEXT: [[B:%.*]] = call range(i32 0, 32) i32 @returns_i32_helper(), !range [[RNG0:![0-9]+]] +; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A:%.*]], [[B]] +; CHECK-NEXT: ret i32 [[SHL]] +; + %b = call range(i32 0, 32) i32 @returns_i32_helper(), !range !{ i32 32, i32 64 } + %shl = shl i32 %a, %b + ret i32 %shl +} + ; Check some weird types and the other shift ops. define i31 @lshr_amount_is_known_bogus(i31 %a, i31 %b) { diff --git a/llvm/test/Transforms/Internalize/vcall-visibility.ll b/llvm/test/Transforms/Internalize/vcall-visibility.ll index c2fe8c3a01e9a25ef8ad98cb3f097c0f235ef5f9..ee6753534419d3777f0ff184d2fcbd6c0d910aac 100644 --- a/llvm/test/Transforms/Internalize/vcall-visibility.ll +++ b/llvm/test/Transforms/Internalize/vcall-visibility.ll @@ -42,7 +42,7 @@ entry: define hidden noalias nonnull ptr @_Z6make_dv() { entry: %call = tail call ptr @_Znwm(i64 8) #3 - store ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTVN12_GLOBAL__N_11DE, i64 0, inrange i32 0, i64 2), ptr %call, align 8 + store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTVN12_GLOBAL__N_11DE, i64 0, i32 0, i64 2), ptr %call, align 8 ret ptr %call } diff --git a/llvm/test/Transforms/LICM/expr-reassociate-int.ll b/llvm/test/Transforms/LICM/expr-reassociate-int.ll index 63548974fb31854f5170f83a9da7efe02f786dce..70288731e31c6dae587681aeb48db94cf3994047 100644 --- a/llvm/test/Transforms/LICM/expr-reassociate-int.ll +++ b/llvm/test/Transforms/LICM/expr-reassociate-int.ll @@ -23,7 +23,7 @@ define void @innermost_loop_1d_shouldhoist(i32 %i, i64 %d1, i64 %delta, ptr %cel ; CHECK-LABEL: define void @innermost_loop_1d_shouldhoist ; CHECK-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[MUL_1:%.*]] = mul i64 [[DELTA]], [[D1]] +; CHECK-NEXT: [[MUL_1:%.*]] = mul nuw nsw i64 [[DELTA]], [[D1]] ; CHECK-NEXT: br label [[FOR_COND:%.*]] ; CHECK: for.cond: ; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] @@ -55,7 +55,7 @@ for.body: %idxprom.j.1 = zext i32 %add.j.1 to i64 %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1 %cell.1 = load i64, ptr %arrayidx.j.1, align 8 - %mul.1 = mul i64 %delta, %d1 + %mul.1 = mul nsw nuw i64 %delta, %d1 %mul.2 = mul i64 %mul.1, %cell.1 %idxprom.j = zext i32 %j to i64 %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j @@ -130,8 +130,8 @@ define void @innermost_loop_2d(i32 %i, i64 %d1, i64 %d2, i64 %delta, ptr %cells) ; CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 ; CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] ; CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; CONSTRAINED-NEXT: [[MUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]] -; CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[MUL_2]], [[MUL_1]] +; CONSTRAINED-NEXT: [[MUL_2:%.*]] = mul nuw nsw i64 [[CELL_2]], [[D2]] +; CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add nuw nsw i64 [[MUL_2]], [[MUL_1]] ; CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD]], [[DELTA]] ; CONSTRAINED-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 ; CONSTRAINED-NEXT: br label [[FOR_COND]] @@ -155,8 +155,8 @@ for.body: %idxprom.j = zext i32 %j to i64 %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j %cell.2 = load i64, ptr %arrayidx.j, align 8 - %mul.2 = mul i64 %cell.2, %d2 - %reass.add = add i64 %mul.2, %mul.1 + %mul.2 = mul nsw nuw i64 %cell.2, %d2 + %reass.add = add nsw nuw i64 %mul.2, %mul.1 %reass.mul = mul i64 %reass.add, %delta store i64 %reass.mul, ptr %arrayidx.j, align 8 br label %for.cond @@ -243,10 +243,10 @@ define void @innermost_loop_3d(i32 %i, i64 %d1, i64 %d2, i64 %d3, i64 %delta, pt ; CONSTRAINED-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 ; CONSTRAINED-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] ; CONSTRAINED-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 -; CONSTRAINED-NEXT: [[MUL_3:%.*]] = mul i64 [[CELL_3]], [[D3]] -; CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[MUL_2]], [[MUL_1]] -; CONSTRAINED-NEXT: [[REASS_ADD1:%.*]] = add i64 [[REASS_ADD]], [[MUL_3]] -; CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD1]], [[DELTA]] +; CONSTRAINED-NEXT: [[MUL_3:%.*]] = mul nuw nsw i64 [[CELL_3]], [[D3]] +; CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add nuw nsw i64 [[MUL_2]], [[MUL_1]] +; CONSTRAINED-NEXT: [[REASS_ADD1:%.*]] = add nuw nsw i64 [[REASS_ADD]], [[MUL_3]] +; CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul nuw nsw i64 [[REASS_ADD1]], [[DELTA]] ; CONSTRAINED-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J_2]], align 8 ; CONSTRAINED-NEXT: br label [[FOR_COND]] ; CONSTRAINED: for.end: @@ -274,10 +274,10 @@ for.body: %idxprom.j.2 = zext i32 %add.j.2 to i64 %arrayidx.j.2 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.2 %cell.3 = load i64, ptr %arrayidx.j.2, align 8 - %mul.3 = mul i64 %cell.3, %d3 - %reass.add = add i64 %mul.2, %mul.1 - %reass.add1 = add i64 %reass.add, %mul.3 - %reass.mul = mul i64 %reass.add1, %delta + %mul.3 = mul nsw nuw i64 %cell.3, %d3 + %reass.add = add nsw nuw i64 %mul.2, %mul.1 + %reass.add1 = add nsw nuw i64 %reass.add, %mul.3 + %reass.mul = mul nsw nuw i64 %reass.add1, %delta store i64 %reass.mul, ptr %arrayidx.j.2, align 8 br label %for.cond @@ -362,3 +362,34 @@ for.body: for.end: ret void } + +; Make sure we drop poison flags on the mul in the loop. +define i32 @pr85457(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @pr85457 +; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i32 [[X]], [[Y]] +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 +; CHECK-NEXT: [[MUL0:%.*]] = mul i32 [[FACTOR_OP_MUL]], [[IV]] +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[MUL0]], 1 +; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] +; CHECK: exit: +; CHECK-NEXT: ret i32 0 +; +entry: + br label %loop + +loop: + %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop ] + %iv.next = add nuw nsw i32 %iv, 1 + %mul0 = mul nuw nsw i32 %x, %iv + %mul1 = mul nuw i32 %mul0, %y + %cmp = icmp slt i32 %mul1, 1 + br i1 %cmp, label %exit, label %loop + +exit: + ret i32 0 +} diff --git a/llvm/test/Transforms/LoopIdiom/AArch64/byte-compare-index.ll b/llvm/test/Transforms/LoopIdiom/AArch64/byte-compare-index.ll index e6a0c5f45375fd8eee628ce05e89624a549dbb58..daa64f2e2ea7c01d9d8ee58a206ee94fdaeb39eb 100644 --- a/llvm/test/Transforms/LoopIdiom/AArch64/byte-compare-index.ll +++ b/llvm/test/Transforms/LoopIdiom/AArch64/byte-compare-index.ll @@ -2,6 +2,9 @@ ; RUN: opt -aarch64-lit -aarch64-lit-verify -verify-dom-info -mtriple aarch64-unknown-linux-gnu -mattr=+sve -S < %s | FileCheck %s ; RUN: opt -aarch64-lit -simplifycfg -mtriple aarch64-unknown-linux-gnu -mattr=+sve -S < %s | FileCheck %s --check-prefix=LOOP-DEL ; RUN: opt -aarch64-lit -mtriple aarch64-unknown-linux-gnu -S < %s | FileCheck %s --check-prefix=NO-TRANSFORM +; RUN: opt -p aarch64-lit -aarch64-lit-verify -verify-dom-info -mtriple aarch64-unknown-linux-gnu -mattr=+sve -S < %s | FileCheck %s +; RUN: opt -passes='function(loop(aarch64-lit)),simplifycfg' -mtriple aarch64-unknown-linux-gnu -mattr=+sve -S < %s | FileCheck %s --check-prefix=LOOP-DEL +; RUN: opt -p aarch64-lit -mtriple aarch64-unknown-linux-gnu -S < %s | FileCheck %s --check-prefix=NO-TRANSFORM define i32 @compare_bytes_simple(ptr %a, ptr %b, i32 %len, i32 %extra, i32 %n) { ; CHECK-LABEL: define i32 @compare_bytes_simple( @@ -780,7 +783,7 @@ define i32 @compare_bytes_extra_cmp(ptr %a, ptr %b, i32 %len, i32 %n, i32 %x) { ; CHECK-NEXT: [[LEN_ADDR:%.*]] = phi i32 [ [[LEN]], [[MISMATCH_END]] ], [ [[MISMATCH_RESULT]], [[WHILE_BODY:%.*]] ] ; CHECK-NEXT: [[INC:%.*]] = add i32 [[LEN_ADDR]], 1 ; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[MISMATCH_RESULT]], [[N]] -; CHECK-NEXT: br i1 [[CMP_NOT]], label [[WHILE_END]], label [[WHILE_BODY]] +; CHECK-NEXT: br i1 [[CMP_NOT]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]] ; CHECK: while.body: ; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[MISMATCH_RESULT]] to i64 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[IDXPROM]] @@ -788,11 +791,14 @@ define i32 @compare_bytes_extra_cmp(ptr %a, ptr %b, i32 %len, i32 %n, i32 %x) { ; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i8, ptr [[B]], i64 [[IDXPROM]] ; CHECK-NEXT: [[TMP46:%.*]] = load i8, ptr [[ARRAYIDX2]], align 1 ; CHECK-NEXT: [[CMP_NOT2:%.*]] = icmp eq i8 [[TMP45]], [[TMP46]] -; CHECK-NEXT: br i1 [[CMP_NOT2]], label [[WHILE_COND]], label [[WHILE_END]] +; CHECK-NEXT: br i1 [[CMP_NOT2]], label [[WHILE_COND]], label [[WHILE_END_LOOPEXIT]] ; CHECK: byte.compare: +; CHECK-NEXT: br label [[WHILE_END_LOOPEXIT]] +; CHECK: while.end.loopexit: +; CHECK-NEXT: [[INC_LCSSA1:%.*]] = phi i32 [ [[MISMATCH_RESULT]], [[WHILE_COND]] ], [ [[MISMATCH_RESULT]], [[WHILE_BODY]] ], [ [[MISMATCH_RESULT]], [[BYTE_COMPARE]] ] ; CHECK-NEXT: br label [[WHILE_END]] ; CHECK: while.end: -; CHECK-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[MISMATCH_RESULT]], [[WHILE_BODY]] ], [ [[MISMATCH_RESULT]], [[WHILE_COND]] ], [ [[X]], [[ENTRY:%.*]] ], [ [[MISMATCH_RESULT]], [[BYTE_COMPARE]] ] +; CHECK-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[X]], [[ENTRY:%.*]] ], [ [[INC_LCSSA1]], [[WHILE_END_LOOPEXIT]] ] ; CHECK-NEXT: ret i32 [[INC_LCSSA]] ; ; LOOP-DEL-LABEL: define i32 @compare_bytes_extra_cmp( @@ -884,7 +890,7 @@ define i32 @compare_bytes_extra_cmp(ptr %a, ptr %b, i32 %len, i32 %n, i32 %x) { ; NO-TRANSFORM-NEXT: [[LEN_ADDR:%.*]] = phi i32 [ [[LEN]], [[PH]] ], [ [[INC:%.*]], [[WHILE_BODY:%.*]] ] ; NO-TRANSFORM-NEXT: [[INC]] = add i32 [[LEN_ADDR]], 1 ; NO-TRANSFORM-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[INC]], [[N]] -; NO-TRANSFORM-NEXT: br i1 [[CMP_NOT]], label [[WHILE_END]], label [[WHILE_BODY]] +; NO-TRANSFORM-NEXT: br i1 [[CMP_NOT]], label [[WHILE_END_LOOPEXIT:%.*]], label [[WHILE_BODY]] ; NO-TRANSFORM: while.body: ; NO-TRANSFORM-NEXT: [[IDXPROM:%.*]] = zext i32 [[INC]] to i64 ; NO-TRANSFORM-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[IDXPROM]] @@ -892,9 +898,12 @@ define i32 @compare_bytes_extra_cmp(ptr %a, ptr %b, i32 %len, i32 %n, i32 %x) { ; NO-TRANSFORM-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i8, ptr [[B]], i64 [[IDXPROM]] ; NO-TRANSFORM-NEXT: [[TMP1:%.*]] = load i8, ptr [[ARRAYIDX2]], align 1 ; NO-TRANSFORM-NEXT: [[CMP_NOT2:%.*]] = icmp eq i8 [[TMP0]], [[TMP1]] -; NO-TRANSFORM-NEXT: br i1 [[CMP_NOT2]], label [[WHILE_COND]], label [[WHILE_END]] +; NO-TRANSFORM-NEXT: br i1 [[CMP_NOT2]], label [[WHILE_COND]], label [[WHILE_END_LOOPEXIT]] +; NO-TRANSFORM: while.end.loopexit: +; NO-TRANSFORM-NEXT: [[INC_LCSSA1:%.*]] = phi i32 [ [[INC]], [[WHILE_COND]] ], [ [[INC]], [[WHILE_BODY]] ] +; NO-TRANSFORM-NEXT: br label [[WHILE_END]] ; NO-TRANSFORM: while.end: -; NO-TRANSFORM-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[INC]], [[WHILE_BODY]] ], [ [[INC]], [[WHILE_COND]] ], [ [[X]], [[ENTRY:%.*]] ] +; NO-TRANSFORM-NEXT: [[INC_LCSSA:%.*]] = phi i32 [ [[X]], [[ENTRY:%.*]] ], [ [[INC_LCSSA1]], [[WHILE_END_LOOPEXIT]] ] ; NO-TRANSFORM-NEXT: ret i32 [[INC_LCSSA]] ; entry: @@ -908,7 +917,7 @@ while.cond: %len.addr = phi i32 [ %len, %ph ], [ %inc, %while.body ] %inc = add i32 %len.addr, 1 %cmp.not = icmp eq i32 %inc, %n - br i1 %cmp.not, label %while.end, label %while.body + br i1 %cmp.not, label %while.end.loopexit, label %while.body while.body: %idxprom = zext i32 %inc to i64 @@ -917,10 +926,14 @@ while.body: %arrayidx2 = getelementptr inbounds i8, ptr %b, i64 %idxprom %1 = load i8, ptr %arrayidx2 %cmp.not2 = icmp eq i8 %0, %1 - br i1 %cmp.not2, label %while.cond, label %while.end + br i1 %cmp.not2, label %while.cond, label %while.end.loopexit + +while.end.loopexit: + %inc.lcssa1 = phi i32 [ %inc, %while.cond ], [ %inc, %while.body ] + br label %while.end while.end: - %inc.lcssa = phi i32 [ %inc, %while.body ], [ %inc, %while.cond ], [ %x, %entry ] + %inc.lcssa = phi i32 [ %x, %entry ], [ %inc.lcssa1, %while.end.loopexit ] ret i32 %inc.lcssa } diff --git a/llvm/test/Transforms/LoopLoadElim/versioning-scev-invalidation.ll b/llvm/test/Transforms/LoopLoadElim/versioning-scev-invalidation.ll index 4b0bc908eddfa5c2b1da56fbce77bf2fbbc33913..63470a943515b6e85eaa13928e9a729c87ff43a1 100644 --- a/llvm/test/Transforms/LoopLoadElim/versioning-scev-invalidation.ll +++ b/llvm/test/Transforms/LoopLoadElim/versioning-scev-invalidation.ll @@ -63,8 +63,8 @@ define void @g(ptr %dst.1, ptr %start, i64 %N) { ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[INDEX]], 0 -; CHECK-NEXT: [[TMP4:%.*]] = mul i64 [[TMP3]], 8 +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = mul i64 [[INDEX]], 8 +; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[OFFSET_IDX]], 0 ; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[LCSSA_PTR_IV_1]], i64 [[TMP4]] ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr double, ptr [[NEXT_GEP]], i32 0 ; CHECK-NEXT: store <4 x double> zeroinitializer, ptr [[TMP5]], align 8 diff --git a/llvm/test/Transforms/LoopRotate/dbgvalue.ll b/llvm/test/Transforms/LoopRotate/dbgvalue.ll index 92cc886bc81c10752aae3f2b286aae71506bab28..9ecc31e1bd2d3bf0948babcf07a1ffb83dd3963a 100644 --- a/llvm/test/Transforms/LoopRotate/dbgvalue.ll +++ b/llvm/test/Transforms/LoopRotate/dbgvalue.ll @@ -220,7 +220,7 @@ for.end: ; Test that dbg.value intrinsincs adjacent to the `icmp slt i32 0, 0` get ; rotated as expected. The icmp is loop-invariant and so gets hoisted to the -; preheader via a different code path. This is more difficult for DPValue +; preheader via a different code path. This is more difficult for DbgVariableRecord ; debug-info records to handle, because they have to get detached and moved ; somewhere else during rotation. define void @invariant_hoist() !dbg !70 { diff --git a/llvm/test/Transforms/LoopRotate/update-branch-weights.ll b/llvm/test/Transforms/LoopRotate/update-branch-weights.ll index 5d742b64e0adbf473ccdcf1eb0a6c10164cc017b..9a1f36ec5ff2bebd94efa163ef4fe7d262af52b6 100644 --- a/llvm/test/Transforms/LoopRotate/update-branch-weights.ll +++ b/llvm/test/Transforms/LoopRotate/update-branch-weights.ll @@ -232,6 +232,46 @@ loop_exit: ret void } +; BFI_BEFORE-LABEL: block-frequency-info: func6_inaccurate_branch_weight +; BFI_BEFORE: - entry: {{.*}} count = 1024 +; BFI_BEFORE: - loop_header: {{.*}} count = 2047 +; BFI_BEFORE: - loop_body: {{.*}} count = 1023 +; BFI_BEFORE: - loop_exit: {{.*}} count = 1024 + +; BFI_AFTER-LABEL: block-frequency-info: func6_inaccurate_branch_weight +; BFI_AFTER: - entry: {{.*}} count = 1024 +; BFI_AFTER: - loop_body: {{.*}} count = 1024 +; BFI_AFTER: - loop_exit: {{.*}} count = 1024 + +; IR-LABEL: define void @func6_inaccurate_branch_weight( +; IR: entry: +; IR: br label %loop_body +; IR: loop_body: +; IR: br i1 %cmp, label %loop_body, label %loop_exit, !prof [[PROF_FUNC6_0:![0-9]+]] +; IR: loop_exit: +; IR: ret void + +; Branch weight from sample-based PGO may be inaccurate due to sampling. +; Count for loop_body in following case should be not less than loop_exit. +; However this may not hold for Sample-based PGO. +define void @func6_inaccurate_branch_weight() !prof !3 { +entry: + br label %loop_header + +loop_header: + %i = phi i32 [0, %entry], [%i_inc, %loop_body] + %cmp = icmp slt i32 %i, 2 + br i1 %cmp, label %loop_body, label %loop_exit, !prof !9 + +loop_body: + store volatile i32 %i, ptr @g, align 4 + %i_inc = add i32 %i, 1 + br label %loop_header + +loop_exit: + ret void +} + !0 = !{!"function_entry_count", i64 1} !1 = !{!"branch_weights", i32 1000, i32 1} !2 = !{!"branch_weights", i32 3000, i32 1000} @@ -241,6 +281,7 @@ loop_exit: !6 = !{!"branch_weights", i32 0, i32 1} !7 = !{!"branch_weights", i32 1, i32 0} !8 = !{!"branch_weights", i32 0, i32 0} +!9 = !{!"branch_weights", i32 1023, i32 1024} ; IR: [[PROF_FUNC0_0]] = !{!"branch_weights", i32 2000, i32 1000} ; IR: [[PROF_FUNC0_1]] = !{!"branch_weights", i32 999, i32 1} @@ -251,3 +292,4 @@ loop_exit: ; IR: [[PROF_FUNC3_0]] = !{!"branch_weights", i32 0, i32 1} ; IR: [[PROF_FUNC4_0]] = !{!"branch_weights", i32 1, i32 0} ; IR: [[PROF_FUNC5_0]] = !{!"branch_weights", i32 0, i32 0} +; IR: [[PROF_FUNC6_0]] = !{!"branch_weights", i32 0, i32 1024} diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/epilog-vectorization-widen-inductions.ll b/llvm/test/Transforms/LoopVectorize/AArch64/epilog-vectorization-widen-inductions.ll index 24c59fdb47b6133ed700052b5c493bade5288a30..00ec396107dcb512e6a36b4def6c9521f56275c7 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/epilog-vectorization-widen-inductions.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/epilog-vectorization-widen-inductions.ll @@ -11,76 +11,74 @@ define void @test_widen_ptr_induction(ptr %ptr.start.1) { ; CHECK: vector.main.loop.iter.check: ; CHECK-NEXT: br i1 false, label [[VEC_EPILOG_PH:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[IND_END:%.*]] = getelementptr i8, ptr [[PTR_START_1:%.*]], i64 10000 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0 -; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[PTR_START_1]], i64 [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[INDEX]], 1 -; CHECK-NEXT: [[NEXT_GEP1:%.*]] = getelementptr i8, ptr [[PTR_START_1]], i64 [[TMP1]] -; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x ptr> poison, ptr [[NEXT_GEP]], i32 0 -; CHECK-NEXT: [[TMP3:%.*]] = insertelement <2 x ptr> [[TMP2]], ptr [[NEXT_GEP1]], i32 1 -; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[INDEX]], 2 -; CHECK-NEXT: [[NEXT_GEP2:%.*]] = getelementptr i8, ptr [[PTR_START_1]], i64 [[TMP4]] -; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[INDEX]], 3 -; CHECK-NEXT: [[NEXT_GEP3:%.*]] = getelementptr i8, ptr [[PTR_START_1]], i64 [[TMP5]] -; CHECK-NEXT: [[TMP6:%.*]] = insertelement <2 x ptr> poison, ptr [[NEXT_GEP2]], i32 0 -; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x ptr> [[TMP6]], ptr [[NEXT_GEP3]], i32 1 -; CHECK-NEXT: [[TMP8:%.*]] = icmp ne <2 x ptr> [[TMP3]], zeroinitializer -; CHECK-NEXT: [[TMP9:%.*]] = icmp ne <2 x ptr> [[TMP7]], zeroinitializer -; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x i1> [[TMP8]], i32 0 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP10]]) -; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x i1> [[TMP8]], i32 1 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP11]]) -; CHECK-NEXT: [[TMP12:%.*]] = extractelement <2 x i1> [[TMP9]], i32 0 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP12]]) -; CHECK-NEXT: [[TMP13:%.*]] = extractelement <2 x i1> [[TMP9]], i32 1 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP13]]) -; CHECK-NEXT: [[TMP14:%.*]] = getelementptr i8, ptr [[NEXT_GEP]], i32 0 -; CHECK-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[NEXT_GEP]], i32 2 -; CHECK-NEXT: store <2 x i8> zeroinitializer, ptr [[TMP14]], align 1 -; CHECK-NEXT: store <2 x i8> zeroinitializer, ptr [[TMP15]], align 1 +; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[INDEX]], 2 +; CHECK-NEXT: [[TMP3:%.*]] = add i64 [[INDEX]], 3 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[PTR_START_1:%.*]], i64 [[TMP0]] +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[PTR_START_1]], i64 [[TMP1]] +; CHECK-NEXT: [[TMP6:%.*]] = insertelement <2 x ptr> poison, ptr [[TMP4]], i32 0 +; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x ptr> [[TMP6]], ptr [[TMP5]], i32 1 +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[PTR_START_1]], i64 [[TMP2]] +; CHECK-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[PTR_START_1]], i64 [[TMP3]] +; CHECK-NEXT: [[TMP10:%.*]] = insertelement <2 x ptr> poison, ptr [[TMP8]], i32 0 +; CHECK-NEXT: [[TMP11:%.*]] = insertelement <2 x ptr> [[TMP10]], ptr [[TMP9]], i32 1 +; CHECK-NEXT: [[TMP12:%.*]] = icmp ne <2 x ptr> [[TMP7]], zeroinitializer +; CHECK-NEXT: [[TMP13:%.*]] = icmp ne <2 x ptr> [[TMP11]], zeroinitializer +; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x i1> [[TMP12]], i32 0 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP14]]) +; CHECK-NEXT: [[TMP15:%.*]] = extractelement <2 x i1> [[TMP12]], i32 1 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP15]]) +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x i1> [[TMP13]], i32 0 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP16]]) +; CHECK-NEXT: [[TMP17:%.*]] = extractelement <2 x i1> [[TMP13]], i32 1 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP17]]) +; CHECK-NEXT: [[TMP18:%.*]] = getelementptr i8, ptr [[TMP4]], i32 0 +; CHECK-NEXT: [[TMP19:%.*]] = getelementptr i8, ptr [[TMP4]], i32 2 +; CHECK-NEXT: store <2 x i8> zeroinitializer, ptr [[TMP18]], align 1 +; CHECK-NEXT: store <2 x i8> zeroinitializer, ptr [[TMP19]], align 1 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP16:%.*]] = icmp eq i64 [[INDEX_NEXT]], 10000 -; CHECK-NEXT: br i1 [[TMP16]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], {{!llvm.loop ![0-9]+}} +; CHECK-NEXT: [[TMP20:%.*]] = icmp eq i64 [[INDEX_NEXT]], 10000 +; CHECK-NEXT: br i1 [[TMP20]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], {{!llvm.loop ![0-9]+}} ; CHECK: middle.block: ; CHECK-NEXT: br i1 false, label [[EXIT:%.*]], label [[VEC_EPILOG_ITER_CHECK:%.*]] ; CHECK: vec.epilog.iter.check: -; CHECK-NEXT: [[IND_END6:%.*]] = getelementptr i8, ptr [[PTR_START_1]], i64 10000 +; CHECK-NEXT: [[IND_END1:%.*]] = getelementptr i8, ptr [[PTR_START_1]], i64 10000 ; CHECK-NEXT: br i1 true, label [[VEC_EPILOG_SCALAR_PH]], label [[VEC_EPILOG_PH]] ; CHECK: vec.epilog.ph: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi ptr [ [[IND_END]], [[VEC_EPILOG_ITER_CHECK]] ], [ [[PTR_START_1]], [[VECTOR_MAIN_LOOP_ITER_CHECK]] ] ; CHECK-NEXT: [[VEC_EPILOG_RESUME_VAL:%.*]] = phi i64 [ 10000, [[VEC_EPILOG_ITER_CHECK]] ], [ 0, [[VECTOR_MAIN_LOOP_ITER_CHECK]] ] -; CHECK-NEXT: [[IND_END5:%.*]] = getelementptr i8, ptr [[PTR_START_1]], i64 10000 +; CHECK-NEXT: [[IND_END:%.*]] = getelementptr i8, ptr [[PTR_START_1]], i64 10000 ; CHECK-NEXT: br label [[VEC_EPILOG_VECTOR_BODY:%.*]] ; CHECK: vec.epilog.vector.body: -; CHECK-NEXT: [[INDEX8:%.*]] = phi i64 [ [[VEC_EPILOG_RESUME_VAL]], [[VEC_EPILOG_PH]] ], [ [[INDEX_NEXT11:%.*]], [[VEC_EPILOG_VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP17:%.*]] = add i64 [[INDEX8]], 0 -; CHECK-NEXT: [[NEXT_GEP9:%.*]] = getelementptr i8, ptr [[PTR_START_1]], i64 [[TMP17]] -; CHECK-NEXT: [[TMP18:%.*]] = add i64 [[INDEX8]], 1 -; CHECK-NEXT: [[NEXT_GEP10:%.*]] = getelementptr i8, ptr [[PTR_START_1]], i64 [[TMP18]] -; CHECK-NEXT: [[TMP19:%.*]] = insertelement <2 x ptr> poison, ptr [[NEXT_GEP9]], i32 0 -; CHECK-NEXT: [[TMP20:%.*]] = insertelement <2 x ptr> [[TMP19]], ptr [[NEXT_GEP10]], i32 1 -; CHECK-NEXT: [[TMP21:%.*]] = icmp ne <2 x ptr> [[TMP20]], zeroinitializer -; CHECK-NEXT: [[TMP22:%.*]] = extractelement <2 x i1> [[TMP21]], i32 0 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP22]]) -; CHECK-NEXT: [[TMP23:%.*]] = extractelement <2 x i1> [[TMP21]], i32 1 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP23]]) -; CHECK-NEXT: [[TMP24:%.*]] = getelementptr i8, ptr [[NEXT_GEP9]], i32 0 -; CHECK-NEXT: store <2 x i8> zeroinitializer, ptr [[TMP24]], align 1 -; CHECK-NEXT: [[INDEX_NEXT11]] = add nuw i64 [[INDEX8]], 2 -; CHECK-NEXT: [[TMP25:%.*]] = icmp eq i64 [[INDEX_NEXT11]], 10000 -; CHECK-NEXT: br i1 [[TMP25]], label [[VEC_EPILOG_MIDDLE_BLOCK:%.*]], label [[VEC_EPILOG_VECTOR_BODY]], {{!llvm.loop ![0-9]+}} +; CHECK-NEXT: [[INDEX3:%.*]] = phi i64 [ [[VEC_EPILOG_RESUME_VAL]], [[VEC_EPILOG_PH]] ], [ [[INDEX_NEXT4:%.*]], [[VEC_EPILOG_VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP21:%.*]] = add i64 [[INDEX3]], 0 +; CHECK-NEXT: [[TMP22:%.*]] = add i64 [[INDEX3]], 1 +; CHECK-NEXT: [[TMP23:%.*]] = getelementptr i8, ptr [[PTR_START_1]], i64 [[TMP21]] +; CHECK-NEXT: [[TMP24:%.*]] = getelementptr i8, ptr [[PTR_START_1]], i64 [[TMP22]] +; CHECK-NEXT: [[TMP25:%.*]] = insertelement <2 x ptr> poison, ptr [[TMP23]], i32 0 +; CHECK-NEXT: [[TMP26:%.*]] = insertelement <2 x ptr> [[TMP25]], ptr [[TMP24]], i32 1 +; CHECK-NEXT: [[TMP27:%.*]] = icmp ne <2 x ptr> [[TMP26]], zeroinitializer +; CHECK-NEXT: [[TMP28:%.*]] = extractelement <2 x i1> [[TMP27]], i32 0 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP28]]) +; CHECK-NEXT: [[TMP29:%.*]] = extractelement <2 x i1> [[TMP27]], i32 1 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP29]]) +; CHECK-NEXT: [[TMP30:%.*]] = getelementptr i8, ptr [[TMP23]], i32 0 +; CHECK-NEXT: store <2 x i8> zeroinitializer, ptr [[TMP30]], align 1 +; CHECK-NEXT: [[INDEX_NEXT4]] = add nuw i64 [[INDEX3]], 2 +; CHECK-NEXT: [[TMP31:%.*]] = icmp eq i64 [[INDEX_NEXT4]], 10000 +; CHECK-NEXT: br i1 [[TMP31]], label [[VEC_EPILOG_MIDDLE_BLOCK:%.*]], label [[VEC_EPILOG_VECTOR_BODY]], {{!llvm.loop ![0-9]+}} ; CHECK: vec.epilog.middle.block: ; CHECK-NEXT: br i1 false, label [[EXIT]], label [[VEC_EPILOG_SCALAR_PH]] ; CHECK: vec.epilog.scalar.ph: -; CHECK-NEXT: [[BC_RESUME_VAL4:%.*]] = phi i64 [ 10000, [[VEC_EPILOG_MIDDLE_BLOCK]] ], [ 10000, [[VEC_EPILOG_ITER_CHECK]] ], [ 0, [[ITER_CHECK:%.*]] ] -; CHECK-NEXT: [[BC_RESUME_VAL7:%.*]] = phi ptr [ [[IND_END5]], [[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[IND_END6]], [[VEC_EPILOG_ITER_CHECK]] ], [ [[PTR_START_1]], [[ITER_CHECK]] ] +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 10000, [[VEC_EPILOG_MIDDLE_BLOCK]] ], [ 10000, [[VEC_EPILOG_ITER_CHECK]] ], [ 0, [[ITER_CHECK:%.*]] ] +; CHECK-NEXT: [[BC_RESUME_VAL2:%.*]] = phi ptr [ [[IND_END]], [[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[IND_END1]], [[VEC_EPILOG_ITER_CHECK]] ], [ [[PTR_START_1]], [[ITER_CHECK]] ] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL4]], [[VEC_EPILOG_SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[BC_RESUME_VAL7]], [[VEC_EPILOG_SCALAR_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[VEC_EPILOG_SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[BC_RESUME_VAL2]], [[VEC_EPILOG_SCALAR_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ] ; CHECK-NEXT: [[CMP_I_I_I_I:%.*]] = icmp ne ptr [[PTR_IV]], null ; CHECK-NEXT: tail call void @llvm.assume(i1 [[CMP_I_I_I_I]]) ; CHECK-NEXT: store i8 0, ptr [[PTR_IV]], align 1 diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/masked-call.ll b/llvm/test/Transforms/LoopVectorize/AArch64/masked-call.ll index 1e79c3e1e8dc2df136049aa035870f411c21dcd6..b91579106261a6096025a3e2a0f91c4de72d33d0 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/masked-call.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/masked-call.ll @@ -99,7 +99,7 @@ define void @test_widen(ptr noalias %a, ptr readnone %b) #4 { ; TFA_INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK_ENTRY1:%.*]] = call <vscale x 2 x i1> @llvm.get.active.lane.mask.nxv2i1.i64(i64 [[TMP8]], i64 1025) ; TFA_INTERLEAVE-NEXT: br label [[VECTOR_BODY:%.*]] ; TFA_INTERLEAVE: vector.body: -; TFA_INTERLEAVE-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT4:%.*]], [[VECTOR_BODY]] ] +; TFA_INTERLEAVE-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] ; TFA_INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK:%.*]] = phi <vscale x 2 x i1> [ [[ACTIVE_LANE_MASK_ENTRY]], [[ENTRY]] ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], [[VECTOR_BODY]] ] ; TFA_INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK2:%.*]] = phi <vscale x 2 x i1> [ [[ACTIVE_LANE_MASK_ENTRY1]], [[ENTRY]] ], [ [[ACTIVE_LANE_MASK_NEXT5:%.*]], [[VECTOR_BODY]] ] ; TFA_INTERLEAVE-NEXT: [[TMP9:%.*]] = getelementptr i64, ptr [[B:%.*]], i64 [[INDEX]] @@ -117,7 +117,6 @@ define void @test_widen(ptr noalias %a, ptr readnone %b) #4 { ; TFA_INTERLEAVE-NEXT: call void @llvm.masked.store.nxv2i64.p0(<vscale x 2 x i64> [[TMP13]], ptr [[TMP15]], i32 8, <vscale x 2 x i1> [[ACTIVE_LANE_MASK]]) ; TFA_INTERLEAVE-NEXT: call void @llvm.masked.store.nxv2i64.p0(<vscale x 2 x i64> [[TMP14]], ptr [[TMP18]], i32 8, <vscale x 2 x i1> [[ACTIVE_LANE_MASK2]]) ; TFA_INTERLEAVE-NEXT: [[INDEX_NEXT:%.*]] = add i64 [[INDEX]], [[TMP6]] -; TFA_INTERLEAVE-NEXT: [[INDEX_NEXT4]] = add i64 [[INDEX]], [[TMP6]] ; TFA_INTERLEAVE-NEXT: [[TMP19:%.*]] = call i64 @llvm.vscale.i64() ; TFA_INTERLEAVE-NEXT: [[TMP20:%.*]] = mul i64 [[TMP19]], 2 ; TFA_INTERLEAVE-NEXT: [[TMP21:%.*]] = add i64 [[INDEX_NEXT]], [[TMP20]] @@ -254,7 +253,7 @@ define void @test_if_then(ptr noalias %a, ptr readnone %b) #4 { ; TFA_INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK_ENTRY1:%.*]] = call <vscale x 2 x i1> @llvm.get.active.lane.mask.nxv2i1.i64(i64 [[TMP8]], i64 1025) ; TFA_INTERLEAVE-NEXT: br label [[VECTOR_BODY:%.*]] ; TFA_INTERLEAVE: vector.body: -; TFA_INTERLEAVE-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT5:%.*]], [[VECTOR_BODY]] ] +; TFA_INTERLEAVE-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] ; TFA_INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK:%.*]] = phi <vscale x 2 x i1> [ [[ACTIVE_LANE_MASK_ENTRY]], [[ENTRY]] ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], [[VECTOR_BODY]] ] ; TFA_INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK2:%.*]] = phi <vscale x 2 x i1> [ [[ACTIVE_LANE_MASK_ENTRY1]], [[ENTRY]] ], [ [[ACTIVE_LANE_MASK_NEXT6:%.*]], [[VECTOR_BODY]] ] ; TFA_INTERLEAVE-NEXT: [[TMP9:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 [[INDEX]] @@ -284,7 +283,6 @@ define void @test_if_then(ptr noalias %a, ptr readnone %b) #4 { ; TFA_INTERLEAVE-NEXT: call void @llvm.masked.store.nxv2i64.p0(<vscale x 2 x i64> [[PREDPHI]], ptr [[TMP25]], i32 8, <vscale x 2 x i1> [[TMP23]]) ; TFA_INTERLEAVE-NEXT: call void @llvm.masked.store.nxv2i64.p0(<vscale x 2 x i64> [[PREDPHI4]], ptr [[TMP28]], i32 8, <vscale x 2 x i1> [[TMP24]]) ; TFA_INTERLEAVE-NEXT: [[INDEX_NEXT:%.*]] = add i64 [[INDEX]], [[TMP6]] -; TFA_INTERLEAVE-NEXT: [[INDEX_NEXT5]] = add i64 [[INDEX]], [[TMP6]] ; TFA_INTERLEAVE-NEXT: [[TMP29:%.*]] = call i64 @llvm.vscale.i64() ; TFA_INTERLEAVE-NEXT: [[TMP30:%.*]] = mul i64 [[TMP29]], 2 ; TFA_INTERLEAVE-NEXT: [[TMP31:%.*]] = add i64 [[INDEX_NEXT]], [[TMP30]] @@ -437,7 +435,7 @@ define void @test_widen_if_then_else(ptr noalias %a, ptr readnone %b) #4 { ; TFA_INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK_ENTRY1:%.*]] = call <vscale x 2 x i1> @llvm.get.active.lane.mask.nxv2i1.i64(i64 [[TMP8]], i64 1025) ; TFA_INTERLEAVE-NEXT: br label [[VECTOR_BODY:%.*]] ; TFA_INTERLEAVE: vector.body: -; TFA_INTERLEAVE-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT5:%.*]], [[VECTOR_BODY]] ] +; TFA_INTERLEAVE-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] ; TFA_INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK:%.*]] = phi <vscale x 2 x i1> [ [[ACTIVE_LANE_MASK_ENTRY]], [[ENTRY]] ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], [[VECTOR_BODY]] ] ; TFA_INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK2:%.*]] = phi <vscale x 2 x i1> [ [[ACTIVE_LANE_MASK_ENTRY1]], [[ENTRY]] ], [ [[ACTIVE_LANE_MASK_NEXT6:%.*]], [[VECTOR_BODY]] ] ; TFA_INTERLEAVE-NEXT: [[TMP9:%.*]] = getelementptr inbounds i64, ptr [[A:%.*]], i64 [[INDEX]] @@ -469,7 +467,6 @@ define void @test_widen_if_then_else(ptr noalias %a, ptr readnone %b) #4 { ; TFA_INTERLEAVE-NEXT: call void @llvm.masked.store.nxv2i64.p0(<vscale x 2 x i64> [[PREDPHI]], ptr [[TMP27]], i32 8, <vscale x 2 x i1> [[TMP25]]) ; TFA_INTERLEAVE-NEXT: call void @llvm.masked.store.nxv2i64.p0(<vscale x 2 x i64> [[PREDPHI4]], ptr [[TMP30]], i32 8, <vscale x 2 x i1> [[TMP26]]) ; TFA_INTERLEAVE-NEXT: [[INDEX_NEXT:%.*]] = add i64 [[INDEX]], [[TMP6]] -; TFA_INTERLEAVE-NEXT: [[INDEX_NEXT5]] = add i64 [[INDEX]], [[TMP6]] ; TFA_INTERLEAVE-NEXT: [[TMP31:%.*]] = call i64 @llvm.vscale.i64() ; TFA_INTERLEAVE-NEXT: [[TMP32:%.*]] = mul i64 [[TMP31]], 2 ; TFA_INTERLEAVE-NEXT: [[TMP33:%.*]] = add i64 [[INDEX_NEXT]], [[TMP32]] @@ -771,7 +768,7 @@ define void @test_widen_optmask(ptr noalias %a, ptr readnone %b) #4 { ; TFA_INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK_ENTRY1:%.*]] = call <vscale x 2 x i1> @llvm.get.active.lane.mask.nxv2i1.i64(i64 [[TMP8]], i64 1025) ; TFA_INTERLEAVE-NEXT: br label [[VECTOR_BODY:%.*]] ; TFA_INTERLEAVE: vector.body: -; TFA_INTERLEAVE-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT4:%.*]], [[VECTOR_BODY]] ] +; TFA_INTERLEAVE-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] ; TFA_INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK:%.*]] = phi <vscale x 2 x i1> [ [[ACTIVE_LANE_MASK_ENTRY]], [[ENTRY]] ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], [[VECTOR_BODY]] ] ; TFA_INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK2:%.*]] = phi <vscale x 2 x i1> [ [[ACTIVE_LANE_MASK_ENTRY1]], [[ENTRY]] ], [ [[ACTIVE_LANE_MASK_NEXT5:%.*]], [[VECTOR_BODY]] ] ; TFA_INTERLEAVE-NEXT: [[TMP9:%.*]] = getelementptr i64, ptr [[B:%.*]], i64 [[INDEX]] @@ -789,7 +786,6 @@ define void @test_widen_optmask(ptr noalias %a, ptr readnone %b) #4 { ; TFA_INTERLEAVE-NEXT: call void @llvm.masked.store.nxv2i64.p0(<vscale x 2 x i64> [[TMP13]], ptr [[TMP15]], i32 8, <vscale x 2 x i1> [[ACTIVE_LANE_MASK]]) ; TFA_INTERLEAVE-NEXT: call void @llvm.masked.store.nxv2i64.p0(<vscale x 2 x i64> [[TMP14]], ptr [[TMP18]], i32 8, <vscale x 2 x i1> [[ACTIVE_LANE_MASK2]]) ; TFA_INTERLEAVE-NEXT: [[INDEX_NEXT:%.*]] = add i64 [[INDEX]], [[TMP6]] -; TFA_INTERLEAVE-NEXT: [[INDEX_NEXT4]] = add i64 [[INDEX]], [[TMP6]] ; TFA_INTERLEAVE-NEXT: [[TMP19:%.*]] = call i64 @llvm.vscale.i64() ; TFA_INTERLEAVE-NEXT: [[TMP20:%.*]] = mul i64 [[TMP19]], 2 ; TFA_INTERLEAVE-NEXT: [[TMP21:%.*]] = add i64 [[INDEX_NEXT]], [[TMP20]] @@ -970,7 +966,7 @@ define double @test_widen_fmuladd_and_call(ptr noalias %a, ptr readnone %b, doub ; TFA_INTERLEAVE-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <vscale x 2 x double> [[BROADCAST_SPLATINSERT]], <vscale x 2 x double> poison, <vscale x 2 x i32> zeroinitializer ; TFA_INTERLEAVE-NEXT: br label [[VECTOR_BODY:%.*]] ; TFA_INTERLEAVE: vector.body: -; TFA_INTERLEAVE-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT4:%.*]], [[VECTOR_BODY]] ] +; TFA_INTERLEAVE-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] ; TFA_INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK:%.*]] = phi <vscale x 2 x i1> [ [[ACTIVE_LANE_MASK_ENTRY]], [[ENTRY]] ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], [[VECTOR_BODY]] ] ; TFA_INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK2:%.*]] = phi <vscale x 2 x i1> [ [[ACTIVE_LANE_MASK_ENTRY1]], [[ENTRY]] ], [ [[ACTIVE_LANE_MASK_NEXT5:%.*]], [[VECTOR_BODY]] ] ; TFA_INTERLEAVE-NEXT: [[VEC_PHI:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[TMP26:%.*]], [[VECTOR_BODY]] ] @@ -997,7 +993,6 @@ define double @test_widen_fmuladd_and_call(ptr noalias %a, ptr readnone %b, doub ; TFA_INTERLEAVE-NEXT: [[TMP25:%.*]] = select <vscale x 2 x i1> [[ACTIVE_LANE_MASK2]], <vscale x 2 x double> [[TMP14]], <vscale x 2 x double> shufflevector (<vscale x 2 x double> insertelement (<vscale x 2 x double> poison, double -0.000000e+00, i64 0), <vscale x 2 x double> poison, <vscale x 2 x i32> zeroinitializer) ; TFA_INTERLEAVE-NEXT: [[TMP26]] = call double @llvm.vector.reduce.fadd.nxv2f64(double [[TMP24]], <vscale x 2 x double> [[TMP25]]) ; TFA_INTERLEAVE-NEXT: [[INDEX_NEXT:%.*]] = add i64 [[INDEX]], [[TMP6]] -; TFA_INTERLEAVE-NEXT: [[INDEX_NEXT4]] = add i64 [[INDEX]], [[TMP6]] ; TFA_INTERLEAVE-NEXT: [[TMP27:%.*]] = call i64 @llvm.vscale.i64() ; TFA_INTERLEAVE-NEXT: [[TMP28:%.*]] = mul i64 [[TMP27]], 2 ; TFA_INTERLEAVE-NEXT: [[TMP29:%.*]] = add i64 [[INDEX_NEXT]], [[TMP28]] diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/pr73894.ll b/llvm/test/Transforms/LoopVectorize/AArch64/pr73894.ll index 1970ac966535dbd674d7b39784cc6e1c95724925..809d2e8f7ea1ad6daa4236415f74dfef41b98b8b 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/pr73894.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/pr73894.ll @@ -20,7 +20,7 @@ define i32 @pr70988() { ; CHECK-NEXT: [[ACTIVE_LANE_MASK_ENTRY1:%.*]] = icmp ult i64 1, [[UMAX]] ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT6:%.*]], [[PRED_LOAD_CONTINUE5:%.*]] ] +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_LOAD_CONTINUE5:%.*]] ] ; CHECK-NEXT: [[ACTIVE_LANE_MASK:%.*]] = phi i1 [ [[ACTIVE_LANE_MASK_ENTRY]], [[VECTOR_PH]] ], [ [[ACTIVE_LANE_MASK_NEXT:%.*]], [[PRED_LOAD_CONTINUE5]] ] ; CHECK-NEXT: [[ACTIVE_LANE_MASK2:%.*]] = phi i1 [ [[ACTIVE_LANE_MASK_ENTRY1]], [[VECTOR_PH]] ], [ [[ACTIVE_LANE_MASK_NEXT7:%.*]], [[PRED_LOAD_CONTINUE5]] ] ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[TMP17:%.*]], [[PRED_LOAD_CONTINUE5]] ] @@ -50,7 +50,6 @@ define i32 @pr70988() { ; CHECK-NEXT: [[TMP17]] = select i1 [[ACTIVE_LANE_MASK]], i32 [[TMP15]], i32 [[VEC_PHI]] ; CHECK-NEXT: [[TMP18]] = select i1 [[ACTIVE_LANE_MASK2]], i32 [[TMP16]], i32 [[VEC_PHI3]] ; CHECK-NEXT: [[INDEX_NEXT:%.*]] = add i64 [[INDEX]], 2 -; CHECK-NEXT: [[INDEX_NEXT6]] = add i64 [[INDEX]], 2 ; CHECK-NEXT: [[TMP19:%.*]] = add i64 [[INDEX_NEXT]], 1 ; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = icmp ult i64 [[INDEX_NEXT]], [[UMAX]] ; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT7]] = icmp ult i64 [[TMP19]], [[UMAX]] diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/scalable-strict-fadd.ll b/llvm/test/Transforms/LoopVectorize/AArch64/scalable-strict-fadd.ll index fc67fb5aded6a8de2165fa16eb742407ffc04410..ad6e8534f318005a8735ee1de76b49c4bc91b209 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/scalable-strict-fadd.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/scalable-strict-fadd.ll @@ -403,21 +403,6 @@ define float @fadd_strict_unroll(ptr noalias nocapture readonly %a, i64 %n) #0 { ; CHECK-ORDERED-TF-NEXT: [[TMP7:%.*]] = sub i64 [[N]], [[TMP6]] ; CHECK-ORDERED-TF-NEXT: [[TMP8:%.*]] = icmp ugt i64 [[N]], [[TMP6]] ; CHECK-ORDERED-TF-NEXT: [[TMP9:%.*]] = select i1 [[TMP8]], i64 [[TMP7]], i64 0 -; CHECK-ORDERED-TF-NEXT: [[TMP10:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-ORDERED-TF-NEXT: [[TMP11:%.*]] = mul i64 [[TMP10]], 32 -; CHECK-ORDERED-TF-NEXT: [[TMP12:%.*]] = sub i64 [[N]], [[TMP11]] -; CHECK-ORDERED-TF-NEXT: [[TMP13:%.*]] = icmp ugt i64 [[N]], [[TMP11]] -; CHECK-ORDERED-TF-NEXT: [[TMP14:%.*]] = select i1 [[TMP13]], i64 [[TMP12]], i64 0 -; CHECK-ORDERED-TF-NEXT: [[TMP15:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-ORDERED-TF-NEXT: [[TMP16:%.*]] = mul i64 [[TMP15]], 32 -; CHECK-ORDERED-TF-NEXT: [[TMP17:%.*]] = sub i64 [[N]], [[TMP16]] -; CHECK-ORDERED-TF-NEXT: [[TMP18:%.*]] = icmp ugt i64 [[N]], [[TMP16]] -; CHECK-ORDERED-TF-NEXT: [[TMP19:%.*]] = select i1 [[TMP18]], i64 [[TMP17]], i64 0 -; CHECK-ORDERED-TF-NEXT: [[TMP20:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-ORDERED-TF-NEXT: [[TMP21:%.*]] = mul i64 [[TMP20]], 32 -; CHECK-ORDERED-TF-NEXT: [[TMP22:%.*]] = sub i64 [[N]], [[TMP21]] -; CHECK-ORDERED-TF-NEXT: [[TMP23:%.*]] = icmp ugt i64 [[N]], [[TMP21]] -; CHECK-ORDERED-TF-NEXT: [[TMP24:%.*]] = select i1 [[TMP23]], i64 [[TMP22]], i64 0 ; CHECK-ORDERED-TF-NEXT: [[TMP25:%.*]] = call i64 @llvm.vscale.i64() ; CHECK-ORDERED-TF-NEXT: [[TMP26:%.*]] = mul i64 [[TMP25]], 8 ; CHECK-ORDERED-TF-NEXT: [[INDEX_PART_NEXT:%.*]] = add i64 0, [[TMP26]] @@ -492,9 +477,9 @@ define float @fadd_strict_unroll(ptr noalias nocapture readonly %a, i64 %n) #0 { ; CHECK-ORDERED-TF-NEXT: [[TMP78:%.*]] = mul i64 [[TMP77]], 24 ; CHECK-ORDERED-TF-NEXT: [[TMP79:%.*]] = add i64 [[INDEX]], [[TMP78]] ; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[INDEX]], i64 [[TMP9]]) -; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT12]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[TMP73]], i64 [[TMP14]]) -; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT13]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[TMP76]], i64 [[TMP19]]) -; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT14]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[TMP79]], i64 [[TMP24]]) +; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT12]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[TMP73]], i64 [[TMP9]]) +; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT13]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[TMP76]], i64 [[TMP9]]) +; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT14]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[TMP79]], i64 [[TMP9]]) ; CHECK-ORDERED-TF-NEXT: [[TMP80:%.*]] = xor <vscale x 8 x i1> [[ACTIVE_LANE_MASK_NEXT]], shufflevector (<vscale x 8 x i1> insertelement (<vscale x 8 x i1> poison, i1 true, i64 0), <vscale x 8 x i1> poison, <vscale x 8 x i32> zeroinitializer) ; CHECK-ORDERED-TF-NEXT: [[TMP81:%.*]] = xor <vscale x 8 x i1> [[ACTIVE_LANE_MASK_NEXT12]], shufflevector (<vscale x 8 x i1> insertelement (<vscale x 8 x i1> poison, i1 true, i64 0), <vscale x 8 x i1> poison, <vscale x 8 x i32> zeroinitializer) ; CHECK-ORDERED-TF-NEXT: [[TMP82:%.*]] = xor <vscale x 8 x i1> [[ACTIVE_LANE_MASK_NEXT13]], shufflevector (<vscale x 8 x i1> insertelement (<vscale x 8 x i1> poison, i1 true, i64 0), <vscale x 8 x i1> poison, <vscale x 8 x i32> zeroinitializer) @@ -1715,21 +1700,6 @@ define float @fmuladd_strict(ptr %a, ptr %b, i64 %n) #0 { ; CHECK-ORDERED-TF-NEXT: [[TMP7:%.*]] = sub i64 [[N]], [[TMP6]] ; CHECK-ORDERED-TF-NEXT: [[TMP8:%.*]] = icmp ugt i64 [[N]], [[TMP6]] ; CHECK-ORDERED-TF-NEXT: [[TMP9:%.*]] = select i1 [[TMP8]], i64 [[TMP7]], i64 0 -; CHECK-ORDERED-TF-NEXT: [[TMP10:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-ORDERED-TF-NEXT: [[TMP11:%.*]] = mul i64 [[TMP10]], 32 -; CHECK-ORDERED-TF-NEXT: [[TMP12:%.*]] = sub i64 [[N]], [[TMP11]] -; CHECK-ORDERED-TF-NEXT: [[TMP13:%.*]] = icmp ugt i64 [[N]], [[TMP11]] -; CHECK-ORDERED-TF-NEXT: [[TMP14:%.*]] = select i1 [[TMP13]], i64 [[TMP12]], i64 0 -; CHECK-ORDERED-TF-NEXT: [[TMP15:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-ORDERED-TF-NEXT: [[TMP16:%.*]] = mul i64 [[TMP15]], 32 -; CHECK-ORDERED-TF-NEXT: [[TMP17:%.*]] = sub i64 [[N]], [[TMP16]] -; CHECK-ORDERED-TF-NEXT: [[TMP18:%.*]] = icmp ugt i64 [[N]], [[TMP16]] -; CHECK-ORDERED-TF-NEXT: [[TMP19:%.*]] = select i1 [[TMP18]], i64 [[TMP17]], i64 0 -; CHECK-ORDERED-TF-NEXT: [[TMP20:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-ORDERED-TF-NEXT: [[TMP21:%.*]] = mul i64 [[TMP20]], 32 -; CHECK-ORDERED-TF-NEXT: [[TMP22:%.*]] = sub i64 [[N]], [[TMP21]] -; CHECK-ORDERED-TF-NEXT: [[TMP23:%.*]] = icmp ugt i64 [[N]], [[TMP21]] -; CHECK-ORDERED-TF-NEXT: [[TMP24:%.*]] = select i1 [[TMP23]], i64 [[TMP22]], i64 0 ; CHECK-ORDERED-TF-NEXT: [[TMP25:%.*]] = call i64 @llvm.vscale.i64() ; CHECK-ORDERED-TF-NEXT: [[TMP26:%.*]] = mul i64 [[TMP25]], 8 ; CHECK-ORDERED-TF-NEXT: [[INDEX_PART_NEXT:%.*]] = add i64 0, [[TMP26]] @@ -1826,9 +1796,9 @@ define float @fmuladd_strict(ptr %a, ptr %b, i64 %n) #0 { ; CHECK-ORDERED-TF-NEXT: [[TMP96:%.*]] = mul i64 [[TMP95]], 24 ; CHECK-ORDERED-TF-NEXT: [[TMP97:%.*]] = add i64 [[INDEX]], [[TMP96]] ; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[INDEX]], i64 [[TMP9]]) -; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT16]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[TMP91]], i64 [[TMP14]]) -; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT17]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[TMP94]], i64 [[TMP19]]) -; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT18]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[TMP97]], i64 [[TMP24]]) +; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT16]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[TMP91]], i64 [[TMP9]]) +; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT17]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[TMP94]], i64 [[TMP9]]) +; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT18]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[TMP97]], i64 [[TMP9]]) ; CHECK-ORDERED-TF-NEXT: [[TMP98:%.*]] = xor <vscale x 8 x i1> [[ACTIVE_LANE_MASK_NEXT]], shufflevector (<vscale x 8 x i1> insertelement (<vscale x 8 x i1> poison, i1 true, i64 0), <vscale x 8 x i1> poison, <vscale x 8 x i32> zeroinitializer) ; CHECK-ORDERED-TF-NEXT: [[TMP99:%.*]] = xor <vscale x 8 x i1> [[ACTIVE_LANE_MASK_NEXT16]], shufflevector (<vscale x 8 x i1> insertelement (<vscale x 8 x i1> poison, i1 true, i64 0), <vscale x 8 x i1> poison, <vscale x 8 x i32> zeroinitializer) ; CHECK-ORDERED-TF-NEXT: [[TMP100:%.*]] = xor <vscale x 8 x i1> [[ACTIVE_LANE_MASK_NEXT17]], shufflevector (<vscale x 8 x i1> insertelement (<vscale x 8 x i1> poison, i1 true, i64 0), <vscale x 8 x i1> poison, <vscale x 8 x i32> zeroinitializer) @@ -2129,21 +2099,6 @@ define float @fmuladd_strict_fmf(ptr %a, ptr %b, i64 %n) #0 { ; CHECK-ORDERED-TF-NEXT: [[TMP7:%.*]] = sub i64 [[N]], [[TMP6]] ; CHECK-ORDERED-TF-NEXT: [[TMP8:%.*]] = icmp ugt i64 [[N]], [[TMP6]] ; CHECK-ORDERED-TF-NEXT: [[TMP9:%.*]] = select i1 [[TMP8]], i64 [[TMP7]], i64 0 -; CHECK-ORDERED-TF-NEXT: [[TMP10:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-ORDERED-TF-NEXT: [[TMP11:%.*]] = mul i64 [[TMP10]], 32 -; CHECK-ORDERED-TF-NEXT: [[TMP12:%.*]] = sub i64 [[N]], [[TMP11]] -; CHECK-ORDERED-TF-NEXT: [[TMP13:%.*]] = icmp ugt i64 [[N]], [[TMP11]] -; CHECK-ORDERED-TF-NEXT: [[TMP14:%.*]] = select i1 [[TMP13]], i64 [[TMP12]], i64 0 -; CHECK-ORDERED-TF-NEXT: [[TMP15:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-ORDERED-TF-NEXT: [[TMP16:%.*]] = mul i64 [[TMP15]], 32 -; CHECK-ORDERED-TF-NEXT: [[TMP17:%.*]] = sub i64 [[N]], [[TMP16]] -; CHECK-ORDERED-TF-NEXT: [[TMP18:%.*]] = icmp ugt i64 [[N]], [[TMP16]] -; CHECK-ORDERED-TF-NEXT: [[TMP19:%.*]] = select i1 [[TMP18]], i64 [[TMP17]], i64 0 -; CHECK-ORDERED-TF-NEXT: [[TMP20:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-ORDERED-TF-NEXT: [[TMP21:%.*]] = mul i64 [[TMP20]], 32 -; CHECK-ORDERED-TF-NEXT: [[TMP22:%.*]] = sub i64 [[N]], [[TMP21]] -; CHECK-ORDERED-TF-NEXT: [[TMP23:%.*]] = icmp ugt i64 [[N]], [[TMP21]] -; CHECK-ORDERED-TF-NEXT: [[TMP24:%.*]] = select i1 [[TMP23]], i64 [[TMP22]], i64 0 ; CHECK-ORDERED-TF-NEXT: [[TMP25:%.*]] = call i64 @llvm.vscale.i64() ; CHECK-ORDERED-TF-NEXT: [[TMP26:%.*]] = mul i64 [[TMP25]], 8 ; CHECK-ORDERED-TF-NEXT: [[INDEX_PART_NEXT:%.*]] = add i64 0, [[TMP26]] @@ -2240,9 +2195,9 @@ define float @fmuladd_strict_fmf(ptr %a, ptr %b, i64 %n) #0 { ; CHECK-ORDERED-TF-NEXT: [[TMP96:%.*]] = mul i64 [[TMP95]], 24 ; CHECK-ORDERED-TF-NEXT: [[TMP97:%.*]] = add i64 [[INDEX]], [[TMP96]] ; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[INDEX]], i64 [[TMP9]]) -; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT16]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[TMP91]], i64 [[TMP14]]) -; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT17]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[TMP94]], i64 [[TMP19]]) -; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT18]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[TMP97]], i64 [[TMP24]]) +; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT16]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[TMP91]], i64 [[TMP9]]) +; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT17]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[TMP94]], i64 [[TMP9]]) +; CHECK-ORDERED-TF-NEXT: [[ACTIVE_LANE_MASK_NEXT18]] = call <vscale x 8 x i1> @llvm.get.active.lane.mask.nxv8i1.i64(i64 [[TMP97]], i64 [[TMP9]]) ; CHECK-ORDERED-TF-NEXT: [[TMP98:%.*]] = xor <vscale x 8 x i1> [[ACTIVE_LANE_MASK_NEXT]], shufflevector (<vscale x 8 x i1> insertelement (<vscale x 8 x i1> poison, i1 true, i64 0), <vscale x 8 x i1> poison, <vscale x 8 x i32> zeroinitializer) ; CHECK-ORDERED-TF-NEXT: [[TMP99:%.*]] = xor <vscale x 8 x i1> [[ACTIVE_LANE_MASK_NEXT16]], shufflevector (<vscale x 8 x i1> insertelement (<vscale x 8 x i1> poison, i1 true, i64 0), <vscale x 8 x i1> poison, <vscale x 8 x i32> zeroinitializer) ; CHECK-ORDERED-TF-NEXT: [[TMP100:%.*]] = xor <vscale x 8 x i1> [[ACTIVE_LANE_MASK_NEXT17]], shufflevector (<vscale x 8 x i1> insertelement (<vscale x 8 x i1> poison, i1 true, i64 0), <vscale x 8 x i1> poison, <vscale x 8 x i32> zeroinitializer) diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/sve-epilog-vect.ll b/llvm/test/Transforms/LoopVectorize/AArch64/sve-epilog-vect.ll index 24d2127ee171a0cb821ef397ccccb42ce180c244..12889c2acc8e5fea08d692a5eef1883ec9a1c09d 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/sve-epilog-vect.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/sve-epilog-vect.ll @@ -146,13 +146,13 @@ define void @main_vf_vscale_x_16(ptr %A) #0 { ; CHECK-VF8-NEXT: [[VEC_EPILOG_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[VEC_EPILOG_ITER_CHECK]] ], [ 0, [[VECTOR_MAIN_LOOP_ITER_CHECK]] ] ; CHECK-VF8-NEXT: br label [[VEC_EPILOG_VECTOR_BODY:%.*]] ; CHECK-VF8: vec.epilog.vector.body: -; CHECK-VF8-NEXT: [[INDEX2:%.*]] = phi i64 [ [[VEC_EPILOG_RESUME_VAL]], [[VEC_EPILOG_PH]] ], [ [[INDEX_NEXT3:%.*]], [[VEC_EPILOG_VECTOR_BODY]] ] -; CHECK-VF8-NEXT: [[TMP19:%.*]] = add i64 [[INDEX2]], 0 +; CHECK-VF8-NEXT: [[INDEX1:%.*]] = phi i64 [ [[VEC_EPILOG_RESUME_VAL]], [[VEC_EPILOG_PH]] ], [ [[INDEX_NEXT2:%.*]], [[VEC_EPILOG_VECTOR_BODY]] ] +; CHECK-VF8-NEXT: [[TMP19:%.*]] = add i64 [[INDEX1]], 0 ; CHECK-VF8-NEXT: [[TMP20:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[TMP19]] ; CHECK-VF8-NEXT: [[TMP21:%.*]] = getelementptr inbounds i8, ptr [[TMP20]], i32 0 ; CHECK-VF8-NEXT: store <8 x i8> <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1>, ptr [[TMP21]], align 1 -; CHECK-VF8-NEXT: [[INDEX_NEXT3]] = add nuw i64 [[INDEX2]], 8 -; CHECK-VF8-NEXT: [[TMP22:%.*]] = icmp eq i64 [[INDEX_NEXT3]], 1024 +; CHECK-VF8-NEXT: [[INDEX_NEXT2]] = add nuw i64 [[INDEX1]], 8 +; CHECK-VF8-NEXT: [[TMP22:%.*]] = icmp eq i64 [[INDEX_NEXT2]], 1024 ; CHECK-VF8-NEXT: br i1 [[TMP22]], label [[VEC_EPILOG_MIDDLE_BLOCK:%.*]], label [[VEC_EPILOG_VECTOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]] ; CHECK-VF8: vec.epilog.middle.block: ; CHECK-VF8-NEXT: br i1 true, label [[EXIT]], label [[VEC_EPILOG_SCALAR_PH]] @@ -246,13 +246,13 @@ define void @main_vf_vscale_x_2(ptr %A) #0 vscale_range(8, 8) { ; CHECK-NEXT: [[VEC_EPILOG_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[VEC_EPILOG_ITER_CHECK]] ], [ 0, [[VECTOR_MAIN_LOOP_ITER_CHECK]] ] ; CHECK-NEXT: br label [[VEC_EPILOG_VECTOR_BODY:%.*]] ; CHECK: vec.epilog.vector.body: -; CHECK-NEXT: [[INDEX2:%.*]] = phi i64 [ [[VEC_EPILOG_RESUME_VAL]], [[VEC_EPILOG_PH]] ], [ [[INDEX_NEXT3:%.*]], [[VEC_EPILOG_VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP19:%.*]] = add i64 [[INDEX2]], 0 +; CHECK-NEXT: [[INDEX1:%.*]] = phi i64 [ [[VEC_EPILOG_RESUME_VAL]], [[VEC_EPILOG_PH]] ], [ [[INDEX_NEXT2:%.*]], [[VEC_EPILOG_VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP19:%.*]] = add i64 [[INDEX1]], 0 ; CHECK-NEXT: [[TMP20:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[TMP19]] ; CHECK-NEXT: [[TMP21:%.*]] = getelementptr inbounds i64, ptr [[TMP20]], i32 0 ; CHECK-NEXT: store <8 x i64> <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1>, ptr [[TMP21]], align 1 -; CHECK-NEXT: [[INDEX_NEXT3]] = add nuw i64 [[INDEX2]], 8 -; CHECK-NEXT: [[TMP22:%.*]] = icmp eq i64 [[INDEX_NEXT3]], 1024 +; CHECK-NEXT: [[INDEX_NEXT2]] = add nuw i64 [[INDEX1]], 8 +; CHECK-NEXT: [[TMP22:%.*]] = icmp eq i64 [[INDEX_NEXT2]], 1024 ; CHECK-NEXT: br i1 [[TMP22]], label [[VEC_EPILOG_MIDDLE_BLOCK:%.*]], label [[VEC_EPILOG_VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] ; CHECK: vec.epilog.middle.block: ; CHECK-NEXT: br i1 true, label [[EXIT]], label [[VEC_EPILOG_SCALAR_PH]] @@ -315,13 +315,13 @@ define void @main_vf_vscale_x_2(ptr %A) #0 vscale_range(8, 8) { ; CHECK-VF8-NEXT: [[VEC_EPILOG_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[VEC_EPILOG_ITER_CHECK]] ], [ 0, [[VECTOR_MAIN_LOOP_ITER_CHECK]] ] ; CHECK-VF8-NEXT: br label [[VEC_EPILOG_VECTOR_BODY:%.*]] ; CHECK-VF8: vec.epilog.vector.body: -; CHECK-VF8-NEXT: [[INDEX2:%.*]] = phi i64 [ [[VEC_EPILOG_RESUME_VAL]], [[VEC_EPILOG_PH]] ], [ [[INDEX_NEXT3:%.*]], [[VEC_EPILOG_VECTOR_BODY]] ] -; CHECK-VF8-NEXT: [[TMP19:%.*]] = add i64 [[INDEX2]], 0 +; CHECK-VF8-NEXT: [[INDEX1:%.*]] = phi i64 [ [[VEC_EPILOG_RESUME_VAL]], [[VEC_EPILOG_PH]] ], [ [[INDEX_NEXT2:%.*]], [[VEC_EPILOG_VECTOR_BODY]] ] +; CHECK-VF8-NEXT: [[TMP19:%.*]] = add i64 [[INDEX1]], 0 ; CHECK-VF8-NEXT: [[TMP20:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 [[TMP19]] ; CHECK-VF8-NEXT: [[TMP21:%.*]] = getelementptr inbounds i64, ptr [[TMP20]], i32 0 ; CHECK-VF8-NEXT: store <8 x i64> <i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1>, ptr [[TMP21]], align 1 -; CHECK-VF8-NEXT: [[INDEX_NEXT3]] = add nuw i64 [[INDEX2]], 8 -; CHECK-VF8-NEXT: [[TMP22:%.*]] = icmp eq i64 [[INDEX_NEXT3]], 1024 +; CHECK-VF8-NEXT: [[INDEX_NEXT2]] = add nuw i64 [[INDEX1]], 8 +; CHECK-VF8-NEXT: [[TMP22:%.*]] = icmp eq i64 [[INDEX_NEXT2]], 1024 ; CHECK-VF8-NEXT: br i1 [[TMP22]], label [[VEC_EPILOG_MIDDLE_BLOCK:%.*]], label [[VEC_EPILOG_VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] ; CHECK-VF8: vec.epilog.middle.block: ; CHECK-VF8-NEXT: br i1 true, label [[EXIT]], label [[VEC_EPILOG_SCALAR_PH]] @@ -374,66 +374,65 @@ define void @test_pr57912_pointer_induction(ptr %start) #0 { ; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 10000, [[N_MOD_VF]] ; CHECK-NEXT: [[TMP6:%.*]] = call i64 @llvm.vscale.i64() ; CHECK-NEXT: [[TMP7:%.*]] = mul i64 [[TMP6]], 32 -; CHECK-NEXT: [[IND_END:%.*]] = getelementptr i8, ptr [[START:%.*]], i64 [[N_VEC]] ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] ; CHECK-NEXT: [[TMP8:%.*]] = add i64 [[INDEX]], 0 -; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[START]], i64 [[TMP8]] ; CHECK-NEXT: [[TMP9:%.*]] = call i64 @llvm.vscale.i64() ; CHECK-NEXT: [[TMP10:%.*]] = mul i64 [[TMP9]], 16 ; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], 0 -; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[INDEX]], [[TMP11]] -; CHECK-NEXT: [[NEXT_GEP2:%.*]] = getelementptr i8, ptr [[START]], i64 [[TMP12]] -; CHECK-NEXT: [[TMP13:%.*]] = getelementptr i8, ptr [[NEXT_GEP]], i32 0 -; CHECK-NEXT: [[TMP14:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP15:%.*]] = mul i64 [[TMP14]], 16 -; CHECK-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[NEXT_GEP]], i64 [[TMP15]] -; CHECK-NEXT: store <vscale x 16 x i8> zeroinitializer, ptr [[TMP13]], align 1 +; CHECK-NEXT: [[TMP12:%.*]] = mul i64 [[TMP11]], 1 +; CHECK-NEXT: [[TMP13:%.*]] = add i64 [[INDEX]], [[TMP12]] +; CHECK-NEXT: [[TMP14:%.*]] = getelementptr i8, ptr [[START:%.*]], i64 [[TMP8]] +; CHECK-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr [[START]], i64 [[TMP13]] +; CHECK-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[TMP14]], i32 0 +; CHECK-NEXT: [[TMP17:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP18:%.*]] = mul i64 [[TMP17]], 16 +; CHECK-NEXT: [[TMP19:%.*]] = getelementptr i8, ptr [[TMP14]], i64 [[TMP18]] ; CHECK-NEXT: store <vscale x 16 x i8> zeroinitializer, ptr [[TMP16]], align 1 +; CHECK-NEXT: store <vscale x 16 x i8> zeroinitializer, ptr [[TMP19]], align 1 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP7]] -; CHECK-NEXT: [[TMP17:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP17]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] +; CHECK-NEXT: [[TMP20:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP20]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] ; CHECK: middle.block: ; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 10000, [[N_VEC]] ; CHECK-NEXT: br i1 [[CMP_N]], label [[EXIT:%.*]], label [[VEC_EPILOG_ITER_CHECK:%.*]] ; CHECK: vec.epilog.iter.check: -; CHECK-NEXT: [[IND_END7:%.*]] = getelementptr i8, ptr [[START]], i64 [[N_VEC]] +; CHECK-NEXT: [[IND_END4:%.*]] = getelementptr i8, ptr [[START]], i64 [[N_VEC]] ; CHECK-NEXT: [[N_VEC_REMAINING:%.*]] = sub i64 10000, [[N_VEC]] -; CHECK-NEXT: [[TMP18:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP19:%.*]] = mul i64 [[TMP18]], 8 -; CHECK-NEXT: [[MIN_EPILOG_ITERS_CHECK:%.*]] = icmp ult i64 [[N_VEC_REMAINING]], [[TMP19]] +; CHECK-NEXT: [[TMP21:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP22:%.*]] = mul i64 [[TMP21]], 8 +; CHECK-NEXT: [[MIN_EPILOG_ITERS_CHECK:%.*]] = icmp ult i64 [[N_VEC_REMAINING]], [[TMP22]] ; CHECK-NEXT: br i1 [[MIN_EPILOG_ITERS_CHECK]], label [[VEC_EPILOG_SCALAR_PH]], label [[VEC_EPILOG_PH]] ; CHECK: vec.epilog.ph: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi ptr [ [[IND_END]], [[VEC_EPILOG_ITER_CHECK]] ], [ [[START]], [[VECTOR_MAIN_LOOP_ITER_CHECK]] ] ; CHECK-NEXT: [[VEC_EPILOG_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[VEC_EPILOG_ITER_CHECK]] ], [ 0, [[VECTOR_MAIN_LOOP_ITER_CHECK]] ] -; CHECK-NEXT: [[TMP20:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP21:%.*]] = mul i64 [[TMP20]], 8 -; CHECK-NEXT: [[N_MOD_VF3:%.*]] = urem i64 10000, [[TMP21]] -; CHECK-NEXT: [[N_VEC4:%.*]] = sub i64 10000, [[N_MOD_VF3]] -; CHECK-NEXT: [[IND_END6:%.*]] = getelementptr i8, ptr [[START]], i64 [[N_VEC4]] -; CHECK-NEXT: [[TMP22:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP23:%.*]] = mul i64 [[TMP22]], 8 +; CHECK-NEXT: [[TMP23:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP24:%.*]] = mul i64 [[TMP23]], 8 +; CHECK-NEXT: [[N_MOD_VF2:%.*]] = urem i64 10000, [[TMP24]] +; CHECK-NEXT: [[N_VEC3:%.*]] = sub i64 10000, [[N_MOD_VF2]] +; CHECK-NEXT: [[IND_END:%.*]] = getelementptr i8, ptr [[START]], i64 [[N_VEC3]] +; CHECK-NEXT: [[TMP25:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP26:%.*]] = mul i64 [[TMP25]], 8 ; CHECK-NEXT: br label [[VEC_EPILOG_VECTOR_BODY:%.*]] ; CHECK: vec.epilog.vector.body: -; CHECK-NEXT: [[INDEX10:%.*]] = phi i64 [ [[VEC_EPILOG_RESUME_VAL]], [[VEC_EPILOG_PH]] ], [ [[INDEX_NEXT12:%.*]], [[VEC_EPILOG_VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP24:%.*]] = add i64 [[INDEX10]], 0 -; CHECK-NEXT: [[NEXT_GEP11:%.*]] = getelementptr i8, ptr [[START]], i64 [[TMP24]] -; CHECK-NEXT: [[TMP25:%.*]] = getelementptr i8, ptr [[NEXT_GEP11]], i32 0 -; CHECK-NEXT: store <vscale x 8 x i8> zeroinitializer, ptr [[TMP25]], align 1 -; CHECK-NEXT: [[INDEX_NEXT12]] = add nuw i64 [[INDEX10]], [[TMP23]] -; CHECK-NEXT: [[TMP26:%.*]] = icmp eq i64 [[INDEX_NEXT12]], [[N_VEC4]] -; CHECK-NEXT: br i1 [[TMP26]], label [[VEC_EPILOG_MIDDLE_BLOCK:%.*]], label [[VEC_EPILOG_VECTOR_BODY]], !llvm.loop [[LOOP9:![0-9]+]] +; CHECK-NEXT: [[INDEX7:%.*]] = phi i64 [ [[VEC_EPILOG_RESUME_VAL]], [[VEC_EPILOG_PH]] ], [ [[INDEX_NEXT8:%.*]], [[VEC_EPILOG_VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP27:%.*]] = add i64 [[INDEX7]], 0 +; CHECK-NEXT: [[TMP28:%.*]] = getelementptr i8, ptr [[START]], i64 [[TMP27]] +; CHECK-NEXT: [[TMP29:%.*]] = getelementptr i8, ptr [[TMP28]], i32 0 +; CHECK-NEXT: store <vscale x 8 x i8> zeroinitializer, ptr [[TMP29]], align 1 +; CHECK-NEXT: [[INDEX_NEXT8]] = add nuw i64 [[INDEX7]], [[TMP26]] +; CHECK-NEXT: [[TMP30:%.*]] = icmp eq i64 [[INDEX_NEXT8]], [[N_VEC3]] +; CHECK-NEXT: br i1 [[TMP30]], label [[VEC_EPILOG_MIDDLE_BLOCK:%.*]], label [[VEC_EPILOG_VECTOR_BODY]], !llvm.loop [[LOOP9:![0-9]+]] ; CHECK: vec.epilog.middle.block: -; CHECK-NEXT: [[CMP_N9:%.*]] = icmp eq i64 10000, [[N_VEC4]] -; CHECK-NEXT: br i1 [[CMP_N9]], label [[EXIT]], label [[VEC_EPILOG_SCALAR_PH]] +; CHECK-NEXT: [[CMP_N6:%.*]] = icmp eq i64 10000, [[N_VEC3]] +; CHECK-NEXT: br i1 [[CMP_N6]], label [[EXIT]], label [[VEC_EPILOG_SCALAR_PH]] ; CHECK: vec.epilog.scalar.ph: -; CHECK-NEXT: [[BC_RESUME_VAL5:%.*]] = phi i64 [ [[N_VEC4]], [[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[N_VEC]], [[VEC_EPILOG_ITER_CHECK]] ], [ 0, [[ITER_CHECK:%.*]] ] -; CHECK-NEXT: [[BC_RESUME_VAL8:%.*]] = phi ptr [ [[IND_END6]], [[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[IND_END7]], [[VEC_EPILOG_ITER_CHECK]] ], [ [[START]], [[ITER_CHECK]] ] +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC3]], [[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[N_VEC]], [[VEC_EPILOG_ITER_CHECK]] ], [ 0, [[ITER_CHECK:%.*]] ] +; CHECK-NEXT: [[BC_RESUME_VAL5:%.*]] = phi ptr [ [[IND_END]], [[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[IND_END4]], [[VEC_EPILOG_ITER_CHECK]] ], [ [[START]], [[ITER_CHECK]] ] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL5]], [[VEC_EPILOG_SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[BC_RESUME_VAL8]], [[VEC_EPILOG_SCALAR_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[VEC_EPILOG_SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[BC_RESUME_VAL5]], [[VEC_EPILOG_SCALAR_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ] ; CHECK-NEXT: store i8 0, ptr [[PTR_IV]], align 1 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i64 1 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 @@ -457,57 +456,56 @@ define void @test_pr57912_pointer_induction(ptr %start) #0 { ; CHECK-VF8-NEXT: [[N_VEC:%.*]] = sub i64 10000, [[N_MOD_VF]] ; CHECK-VF8-NEXT: [[TMP4:%.*]] = call i64 @llvm.vscale.i64() ; CHECK-VF8-NEXT: [[TMP5:%.*]] = mul i64 [[TMP4]], 32 -; CHECK-VF8-NEXT: [[IND_END:%.*]] = getelementptr i8, ptr [[START:%.*]], i64 [[N_VEC]] ; CHECK-VF8-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK-VF8: vector.body: ; CHECK-VF8-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] ; CHECK-VF8-NEXT: [[TMP6:%.*]] = add i64 [[INDEX]], 0 -; CHECK-VF8-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[START]], i64 [[TMP6]] ; CHECK-VF8-NEXT: [[TMP7:%.*]] = call i64 @llvm.vscale.i64() ; CHECK-VF8-NEXT: [[TMP8:%.*]] = mul i64 [[TMP7]], 16 ; CHECK-VF8-NEXT: [[TMP9:%.*]] = add i64 [[TMP8]], 0 -; CHECK-VF8-NEXT: [[TMP10:%.*]] = add i64 [[INDEX]], [[TMP9]] -; CHECK-VF8-NEXT: [[NEXT_GEP1:%.*]] = getelementptr i8, ptr [[START]], i64 [[TMP10]] -; CHECK-VF8-NEXT: [[TMP11:%.*]] = getelementptr i8, ptr [[NEXT_GEP]], i32 0 -; CHECK-VF8-NEXT: [[TMP12:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-VF8-NEXT: [[TMP13:%.*]] = mul i64 [[TMP12]], 16 -; CHECK-VF8-NEXT: [[TMP14:%.*]] = getelementptr i8, ptr [[NEXT_GEP]], i64 [[TMP13]] -; CHECK-VF8-NEXT: store <vscale x 16 x i8> zeroinitializer, ptr [[TMP11]], align 1 +; CHECK-VF8-NEXT: [[TMP10:%.*]] = mul i64 [[TMP9]], 1 +; CHECK-VF8-NEXT: [[TMP11:%.*]] = add i64 [[INDEX]], [[TMP10]] +; CHECK-VF8-NEXT: [[TMP12:%.*]] = getelementptr i8, ptr [[START:%.*]], i64 [[TMP6]] +; CHECK-VF8-NEXT: [[TMP13:%.*]] = getelementptr i8, ptr [[START]], i64 [[TMP11]] +; CHECK-VF8-NEXT: [[TMP14:%.*]] = getelementptr i8, ptr [[TMP12]], i32 0 +; CHECK-VF8-NEXT: [[TMP15:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-VF8-NEXT: [[TMP16:%.*]] = mul i64 [[TMP15]], 16 +; CHECK-VF8-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[TMP12]], i64 [[TMP16]] ; CHECK-VF8-NEXT: store <vscale x 16 x i8> zeroinitializer, ptr [[TMP14]], align 1 +; CHECK-VF8-NEXT: store <vscale x 16 x i8> zeroinitializer, ptr [[TMP17]], align 1 ; CHECK-VF8-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP5]] -; CHECK-VF8-NEXT: [[TMP15:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-VF8-NEXT: br i1 [[TMP15]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] +; CHECK-VF8-NEXT: [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-VF8-NEXT: br i1 [[TMP18]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] ; CHECK-VF8: middle.block: ; CHECK-VF8-NEXT: [[CMP_N:%.*]] = icmp eq i64 10000, [[N_VEC]] ; CHECK-VF8-NEXT: br i1 [[CMP_N]], label [[EXIT:%.*]], label [[VEC_EPILOG_ITER_CHECK:%.*]] ; CHECK-VF8: vec.epilog.iter.check: -; CHECK-VF8-NEXT: [[IND_END4:%.*]] = getelementptr i8, ptr [[START]], i64 [[N_VEC]] +; CHECK-VF8-NEXT: [[IND_END1:%.*]] = getelementptr i8, ptr [[START]], i64 [[N_VEC]] ; CHECK-VF8-NEXT: [[N_VEC_REMAINING:%.*]] = sub i64 10000, [[N_VEC]] ; CHECK-VF8-NEXT: [[MIN_EPILOG_ITERS_CHECK:%.*]] = icmp ult i64 [[N_VEC_REMAINING]], 8 ; CHECK-VF8-NEXT: br i1 [[MIN_EPILOG_ITERS_CHECK]], label [[VEC_EPILOG_SCALAR_PH]], label [[VEC_EPILOG_PH]] ; CHECK-VF8: vec.epilog.ph: -; CHECK-VF8-NEXT: [[BC_RESUME_VAL:%.*]] = phi ptr [ [[IND_END]], [[VEC_EPILOG_ITER_CHECK]] ], [ [[START]], [[VECTOR_MAIN_LOOP_ITER_CHECK]] ] ; CHECK-VF8-NEXT: [[VEC_EPILOG_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[VEC_EPILOG_ITER_CHECK]] ], [ 0, [[VECTOR_MAIN_LOOP_ITER_CHECK]] ] -; CHECK-VF8-NEXT: [[IND_END3:%.*]] = getelementptr i8, ptr [[START]], i64 10000 +; CHECK-VF8-NEXT: [[IND_END:%.*]] = getelementptr i8, ptr [[START]], i64 10000 ; CHECK-VF8-NEXT: br label [[VEC_EPILOG_VECTOR_BODY:%.*]] ; CHECK-VF8: vec.epilog.vector.body: -; CHECK-VF8-NEXT: [[INDEX7:%.*]] = phi i64 [ [[VEC_EPILOG_RESUME_VAL]], [[VEC_EPILOG_PH]] ], [ [[INDEX_NEXT9:%.*]], [[VEC_EPILOG_VECTOR_BODY]] ] -; CHECK-VF8-NEXT: [[TMP16:%.*]] = add i64 [[INDEX7]], 0 -; CHECK-VF8-NEXT: [[NEXT_GEP8:%.*]] = getelementptr i8, ptr [[START]], i64 [[TMP16]] -; CHECK-VF8-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[NEXT_GEP8]], i32 0 -; CHECK-VF8-NEXT: store <8 x i8> zeroinitializer, ptr [[TMP17]], align 1 -; CHECK-VF8-NEXT: [[INDEX_NEXT9]] = add nuw i64 [[INDEX7]], 8 -; CHECK-VF8-NEXT: [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT9]], 10000 -; CHECK-VF8-NEXT: br i1 [[TMP18]], label [[VEC_EPILOG_MIDDLE_BLOCK:%.*]], label [[VEC_EPILOG_VECTOR_BODY]], !llvm.loop [[LOOP9:![0-9]+]] +; CHECK-VF8-NEXT: [[INDEX3:%.*]] = phi i64 [ [[VEC_EPILOG_RESUME_VAL]], [[VEC_EPILOG_PH]] ], [ [[INDEX_NEXT4:%.*]], [[VEC_EPILOG_VECTOR_BODY]] ] +; CHECK-VF8-NEXT: [[TMP19:%.*]] = add i64 [[INDEX3]], 0 +; CHECK-VF8-NEXT: [[TMP20:%.*]] = getelementptr i8, ptr [[START]], i64 [[TMP19]] +; CHECK-VF8-NEXT: [[TMP21:%.*]] = getelementptr i8, ptr [[TMP20]], i32 0 +; CHECK-VF8-NEXT: store <8 x i8> zeroinitializer, ptr [[TMP21]], align 1 +; CHECK-VF8-NEXT: [[INDEX_NEXT4]] = add nuw i64 [[INDEX3]], 8 +; CHECK-VF8-NEXT: [[TMP22:%.*]] = icmp eq i64 [[INDEX_NEXT4]], 10000 +; CHECK-VF8-NEXT: br i1 [[TMP22]], label [[VEC_EPILOG_MIDDLE_BLOCK:%.*]], label [[VEC_EPILOG_VECTOR_BODY]], !llvm.loop [[LOOP9:![0-9]+]] ; CHECK-VF8: vec.epilog.middle.block: ; CHECK-VF8-NEXT: br i1 true, label [[EXIT]], label [[VEC_EPILOG_SCALAR_PH]] ; CHECK-VF8: vec.epilog.scalar.ph: -; CHECK-VF8-NEXT: [[BC_RESUME_VAL2:%.*]] = phi i64 [ 10000, [[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[N_VEC]], [[VEC_EPILOG_ITER_CHECK]] ], [ 0, [[ITER_CHECK:%.*]] ] -; CHECK-VF8-NEXT: [[BC_RESUME_VAL5:%.*]] = phi ptr [ [[IND_END3]], [[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[IND_END4]], [[VEC_EPILOG_ITER_CHECK]] ], [ [[START]], [[ITER_CHECK]] ] +; CHECK-VF8-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 10000, [[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[N_VEC]], [[VEC_EPILOG_ITER_CHECK]] ], [ 0, [[ITER_CHECK:%.*]] ] +; CHECK-VF8-NEXT: [[BC_RESUME_VAL2:%.*]] = phi ptr [ [[IND_END]], [[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[IND_END1]], [[VEC_EPILOG_ITER_CHECK]] ], [ [[START]], [[ITER_CHECK]] ] ; CHECK-VF8-NEXT: br label [[LOOP:%.*]] ; CHECK-VF8: loop: -; CHECK-VF8-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL2]], [[VEC_EPILOG_SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] -; CHECK-VF8-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[BC_RESUME_VAL5]], [[VEC_EPILOG_SCALAR_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-VF8-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[VEC_EPILOG_SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-VF8-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[BC_RESUME_VAL2]], [[VEC_EPILOG_SCALAR_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP]] ] ; CHECK-VF8-NEXT: store i8 0, ptr [[PTR_IV]], align 1 ; CHECK-VF8-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i8, ptr [[PTR_IV]], i64 1 ; CHECK-VF8-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/sve-live-out-pointer-induction.ll b/llvm/test/Transforms/LoopVectorize/AArch64/sve-live-out-pointer-induction.ll index cfb0f9e59ecbc5a13dc203f734256cb8743afc51..8b64d7a083662e82ba4aae78dcf710b5a857ae59 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/sve-live-out-pointer-induction.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/sve-live-out-pointer-induction.ll @@ -23,54 +23,54 @@ define ptr @test(ptr %start.1, ptr %start.2, ptr %end) { ; CHECK-NEXT: [[IND_END:%.*]] = getelementptr i8, ptr [[START_1:%.*]], i64 [[TMP8]] ; CHECK-NEXT: [[TMP9:%.*]] = mul i64 [[N_VEC]], 8 ; CHECK-NEXT: [[IND_END3:%.*]] = getelementptr i8, ptr [[START_2]], i64 [[TMP9]] -; CHECK-NEXT: [[TMP33:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP34:%.*]] = mul i64 [[TMP33]], 4 +; CHECK-NEXT: [[TMP10:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP11:%.*]] = mul i64 [[TMP10]], 4 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[POINTER_PHI:%.*]] = phi ptr [ [[START_1]], [[VECTOR_PH]] ], [ [[PTR_IND:%.*]], [[VECTOR_BODY]] ] ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP10:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP11:%.*]] = mul i64 [[TMP10]], 2 -; CHECK-NEXT: [[TMP12:%.*]] = mul i64 [[TMP11]], 2 -; CHECK-NEXT: [[TMP13:%.*]] = mul i64 8, [[TMP12]] -; CHECK-NEXT: [[TMP14:%.*]] = mul i64 [[TMP11]], 0 -; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 2 x i64> poison, i64 [[TMP14]], i64 0 +; CHECK-NEXT: [[TMP12:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP13:%.*]] = mul i64 [[TMP12]], 2 +; CHECK-NEXT: [[TMP14:%.*]] = mul i64 [[TMP13]], 2 +; CHECK-NEXT: [[TMP15:%.*]] = mul i64 8, [[TMP14]] +; CHECK-NEXT: [[TMP16:%.*]] = mul i64 [[TMP13]], 0 +; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 2 x i64> poison, i64 [[TMP16]], i64 0 ; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <vscale x 2 x i64> [[DOTSPLATINSERT]], <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer -; CHECK-NEXT: [[TMP15:%.*]] = call <vscale x 2 x i64> @llvm.experimental.stepvector.nxv2i64() -; CHECK-NEXT: [[TMP16:%.*]] = add <vscale x 2 x i64> [[DOTSPLAT]], [[TMP15]] -; CHECK-NEXT: [[VECTOR_GEP:%.*]] = mul <vscale x 2 x i64> [[TMP16]], shufflevector (<vscale x 2 x i64> insertelement (<vscale x 2 x i64> poison, i64 8, i64 0), <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer) -; CHECK-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[POINTER_PHI]], <vscale x 2 x i64> [[VECTOR_GEP]] -; CHECK-NEXT: [[TMP18:%.*]] = mul i64 [[TMP11]], 1 -; CHECK-NEXT: [[DOTSPLATINSERT5:%.*]] = insertelement <vscale x 2 x i64> poison, i64 [[TMP18]], i64 0 +; CHECK-NEXT: [[TMP17:%.*]] = call <vscale x 2 x i64> @llvm.experimental.stepvector.nxv2i64() +; CHECK-NEXT: [[TMP18:%.*]] = add <vscale x 2 x i64> [[DOTSPLAT]], [[TMP17]] +; CHECK-NEXT: [[VECTOR_GEP:%.*]] = mul <vscale x 2 x i64> [[TMP18]], shufflevector (<vscale x 2 x i64> insertelement (<vscale x 2 x i64> poison, i64 8, i64 0), <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer) +; CHECK-NEXT: [[TMP19:%.*]] = getelementptr i8, ptr [[POINTER_PHI]], <vscale x 2 x i64> [[VECTOR_GEP]] +; CHECK-NEXT: [[TMP20:%.*]] = mul i64 [[TMP13]], 1 +; CHECK-NEXT: [[DOTSPLATINSERT5:%.*]] = insertelement <vscale x 2 x i64> poison, i64 [[TMP20]], i64 0 ; CHECK-NEXT: [[DOTSPLAT6:%.*]] = shufflevector <vscale x 2 x i64> [[DOTSPLATINSERT5]], <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer -; CHECK-NEXT: [[TMP19:%.*]] = call <vscale x 2 x i64> @llvm.experimental.stepvector.nxv2i64() -; CHECK-NEXT: [[TMP20:%.*]] = add <vscale x 2 x i64> [[DOTSPLAT6]], [[TMP19]] -; CHECK-NEXT: [[VECTOR_GEP7:%.*]] = mul <vscale x 2 x i64> [[TMP20]], shufflevector (<vscale x 2 x i64> insertelement (<vscale x 2 x i64> poison, i64 8, i64 0), <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer) -; CHECK-NEXT: [[TMP21:%.*]] = getelementptr i8, ptr [[POINTER_PHI]], <vscale x 2 x i64> [[VECTOR_GEP7]] -; CHECK-NEXT: [[TMP22:%.*]] = add i64 [[INDEX]], 0 -; CHECK-NEXT: [[TMP23:%.*]] = mul i64 [[TMP22]], 8 -; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[START_2]], i64 [[TMP23]] -; CHECK-NEXT: [[TMP24:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP25:%.*]] = mul i64 [[TMP24]], 2 -; CHECK-NEXT: [[TMP26:%.*]] = add i64 [[TMP25]], 0 -; CHECK-NEXT: [[TMP27:%.*]] = add i64 [[INDEX]], [[TMP26]] +; CHECK-NEXT: [[TMP21:%.*]] = call <vscale x 2 x i64> @llvm.experimental.stepvector.nxv2i64() +; CHECK-NEXT: [[TMP22:%.*]] = add <vscale x 2 x i64> [[DOTSPLAT6]], [[TMP21]] +; CHECK-NEXT: [[VECTOR_GEP7:%.*]] = mul <vscale x 2 x i64> [[TMP22]], shufflevector (<vscale x 2 x i64> insertelement (<vscale x 2 x i64> poison, i64 8, i64 0), <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer) +; CHECK-NEXT: [[TMP23:%.*]] = getelementptr i8, ptr [[POINTER_PHI]], <vscale x 2 x i64> [[VECTOR_GEP7]] +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = mul i64 [[INDEX]], 8 +; CHECK-NEXT: [[TMP24:%.*]] = add i64 [[OFFSET_IDX]], 0 +; CHECK-NEXT: [[TMP25:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP26:%.*]] = mul i64 [[TMP25]], 2 +; CHECK-NEXT: [[TMP27:%.*]] = add i64 [[TMP26]], 0 ; CHECK-NEXT: [[TMP28:%.*]] = mul i64 [[TMP27]], 8 -; CHECK-NEXT: [[NEXT_GEP8:%.*]] = getelementptr i8, ptr [[START_2]], i64 [[TMP28]] -; CHECK-NEXT: [[TMP29:%.*]] = getelementptr i64, ptr [[NEXT_GEP]], i32 0 -; CHECK-NEXT: [[TMP30:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP31:%.*]] = mul i64 [[TMP30]], 2 -; CHECK-NEXT: [[TMP32:%.*]] = getelementptr i64, ptr [[NEXT_GEP]], i64 [[TMP31]] -; CHECK-NEXT: store <vscale x 2 x i64> zeroinitializer, ptr [[TMP29]], align 8 +; CHECK-NEXT: [[TMP29:%.*]] = add i64 [[OFFSET_IDX]], [[TMP28]] +; CHECK-NEXT: [[TMP30:%.*]] = getelementptr i8, ptr [[START_2]], i64 [[TMP24]] +; CHECK-NEXT: [[TMP31:%.*]] = getelementptr i8, ptr [[START_2]], i64 [[TMP29]] +; CHECK-NEXT: [[TMP32:%.*]] = getelementptr i64, ptr [[TMP30]], i32 0 +; CHECK-NEXT: [[TMP33:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP34:%.*]] = mul i64 [[TMP33]], 2 +; CHECK-NEXT: [[TMP35:%.*]] = getelementptr i64, ptr [[TMP30]], i64 [[TMP34]] ; CHECK-NEXT: store <vscale x 2 x i64> zeroinitializer, ptr [[TMP32]], align 8 -; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP34]] -; CHECK-NEXT: [[PTR_IND]] = getelementptr i8, ptr [[POINTER_PHI]], i64 [[TMP13]] -; CHECK-NEXT: [[TMP35:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP35]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK-NEXT: store <vscale x 2 x i64> zeroinitializer, ptr [[TMP35]], align 8 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP11]] +; CHECK-NEXT: [[PTR_IND]] = getelementptr i8, ptr [[POINTER_PHI]], i64 [[TMP15]] +; CHECK-NEXT: [[TMP36:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP36]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] ; CHECK: middle.block: ; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP3]], [[N_VEC]] ; CHECK-NEXT: [[CMO:%.*]] = sub i64 [[N_VEC]], 1 -; CHECK-NEXT: [[TMP36:%.*]] = mul i64 [[CMO]], 8 -; CHECK-NEXT: [[IND_ESCAPE:%.*]] = getelementptr i8, ptr [[START_1]], i64 [[TMP36]] +; CHECK-NEXT: [[TMP37:%.*]] = mul i64 [[CMO]], 8 +; CHECK-NEXT: [[IND_ESCAPE:%.*]] = getelementptr i8, ptr [[START_1]], i64 [[TMP37]] ; CHECK-NEXT: br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: ; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi ptr [ [[IND_END]], [[MIDDLE_BLOCK]] ], [ [[START_1]], [[ENTRY:%.*]] ] diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/sve-tail-folding-unroll.ll b/llvm/test/Transforms/LoopVectorize/AArch64/sve-tail-folding-unroll.ll index 1a6e83a61ce74e6ec35253ea69aeddb65a68d3d9..2acc1ddbffea4633f0f0fd7fa6ec0a1a071fd67a 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/sve-tail-folding-unroll.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/sve-tail-folding-unroll.ll @@ -25,21 +25,6 @@ define void @simple_memset(i32 %val, ptr %ptr, i64 %n) #0 { ; CHECK-NEXT: [[TMP7:%.*]] = sub i64 [[UMAX]], [[TMP6]] ; CHECK-NEXT: [[TMP8:%.*]] = icmp ugt i64 [[UMAX]], [[TMP6]] ; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP8]], i64 [[TMP7]], i64 0 -; CHECK-NEXT: [[TMP10:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP11:%.*]] = mul i64 [[TMP10]], 16 -; CHECK-NEXT: [[TMP12:%.*]] = sub i64 [[UMAX]], [[TMP11]] -; CHECK-NEXT: [[TMP13:%.*]] = icmp ugt i64 [[UMAX]], [[TMP11]] -; CHECK-NEXT: [[TMP14:%.*]] = select i1 [[TMP13]], i64 [[TMP12]], i64 0 -; CHECK-NEXT: [[TMP15:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP16:%.*]] = mul i64 [[TMP15]], 16 -; CHECK-NEXT: [[TMP17:%.*]] = sub i64 [[UMAX]], [[TMP16]] -; CHECK-NEXT: [[TMP18:%.*]] = icmp ugt i64 [[UMAX]], [[TMP16]] -; CHECK-NEXT: [[TMP19:%.*]] = select i1 [[TMP18]], i64 [[TMP17]], i64 0 -; CHECK-NEXT: [[TMP20:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP21:%.*]] = mul i64 [[TMP20]], 16 -; CHECK-NEXT: [[TMP22:%.*]] = sub i64 [[UMAX]], [[TMP21]] -; CHECK-NEXT: [[TMP23:%.*]] = icmp ugt i64 [[UMAX]], [[TMP21]] -; CHECK-NEXT: [[TMP24:%.*]] = select i1 [[TMP23]], i64 [[TMP22]], i64 0 ; CHECK-NEXT: [[TMP25:%.*]] = call i64 @llvm.vscale.i64() ; CHECK-NEXT: [[TMP26:%.*]] = mul i64 [[TMP25]], 4 ; CHECK-NEXT: [[INDEX_PART_NEXT:%.*]] = add i64 0, [[TMP26]] @@ -107,9 +92,9 @@ define void @simple_memset(i32 %val, ptr %ptr, i64 %n) #0 { ; CHECK-NEXT: [[TMP70:%.*]] = mul i64 [[TMP69]], 12 ; CHECK-NEXT: [[TMP71:%.*]] = add i64 [[INDEX6]], [[TMP70]] ; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[INDEX6]], i64 [[TMP9]]) -; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT11]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[TMP65]], i64 [[TMP14]]) -; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT12]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[TMP68]], i64 [[TMP19]]) -; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT13]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[TMP71]], i64 [[TMP24]]) +; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT11]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[TMP65]], i64 [[TMP9]]) +; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT12]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[TMP68]], i64 [[TMP9]]) +; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT13]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[TMP71]], i64 [[TMP9]]) ; CHECK-NEXT: [[TMP72:%.*]] = xor <vscale x 4 x i1> [[ACTIVE_LANE_MASK_NEXT]], shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i64 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer) ; CHECK-NEXT: [[TMP73:%.*]] = xor <vscale x 4 x i1> [[ACTIVE_LANE_MASK_NEXT11]], shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i64 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer) ; CHECK-NEXT: [[TMP74:%.*]] = xor <vscale x 4 x i1> [[ACTIVE_LANE_MASK_NEXT12]], shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i64 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer) @@ -167,21 +152,6 @@ define void @cond_memset(i32 %val, ptr noalias readonly %cond_ptr, ptr noalias % ; CHECK-NEXT: [[TMP7:%.*]] = sub i64 [[UMAX]], [[TMP6]] ; CHECK-NEXT: [[TMP8:%.*]] = icmp ugt i64 [[UMAX]], [[TMP6]] ; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[TMP8]], i64 [[TMP7]], i64 0 -; CHECK-NEXT: [[TMP10:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP11:%.*]] = mul i64 [[TMP10]], 16 -; CHECK-NEXT: [[TMP12:%.*]] = sub i64 [[UMAX]], [[TMP11]] -; CHECK-NEXT: [[TMP13:%.*]] = icmp ugt i64 [[UMAX]], [[TMP11]] -; CHECK-NEXT: [[TMP14:%.*]] = select i1 [[TMP13]], i64 [[TMP12]], i64 0 -; CHECK-NEXT: [[TMP15:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP16:%.*]] = mul i64 [[TMP15]], 16 -; CHECK-NEXT: [[TMP17:%.*]] = sub i64 [[UMAX]], [[TMP16]] -; CHECK-NEXT: [[TMP18:%.*]] = icmp ugt i64 [[UMAX]], [[TMP16]] -; CHECK-NEXT: [[TMP19:%.*]] = select i1 [[TMP18]], i64 [[TMP17]], i64 0 -; CHECK-NEXT: [[TMP20:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP21:%.*]] = mul i64 [[TMP20]], 16 -; CHECK-NEXT: [[TMP22:%.*]] = sub i64 [[UMAX]], [[TMP21]] -; CHECK-NEXT: [[TMP23:%.*]] = icmp ugt i64 [[UMAX]], [[TMP21]] -; CHECK-NEXT: [[TMP24:%.*]] = select i1 [[TMP23]], i64 [[TMP22]], i64 0 ; CHECK-NEXT: [[TMP25:%.*]] = call i64 @llvm.vscale.i64() ; CHECK-NEXT: [[TMP26:%.*]] = mul i64 [[TMP25]], 4 ; CHECK-NEXT: [[INDEX_PART_NEXT:%.*]] = add i64 0, [[TMP26]] @@ -275,9 +245,9 @@ define void @cond_memset(i32 %val, ptr noalias readonly %cond_ptr, ptr noalias % ; CHECK-NEXT: [[TMP92:%.*]] = mul i64 [[TMP91]], 12 ; CHECK-NEXT: [[TMP93:%.*]] = add i64 [[INDEX6]], [[TMP92]] ; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[INDEX6]], i64 [[TMP9]]) -; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT14]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[TMP87]], i64 [[TMP14]]) -; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT15]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[TMP90]], i64 [[TMP19]]) -; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT16]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[TMP93]], i64 [[TMP24]]) +; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT14]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[TMP87]], i64 [[TMP9]]) +; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT15]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[TMP90]], i64 [[TMP9]]) +; CHECK-NEXT: [[ACTIVE_LANE_MASK_NEXT16]] = call <vscale x 4 x i1> @llvm.get.active.lane.mask.nxv4i1.i64(i64 [[TMP93]], i64 [[TMP9]]) ; CHECK-NEXT: [[TMP94:%.*]] = xor <vscale x 4 x i1> [[ACTIVE_LANE_MASK_NEXT]], shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i64 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer) ; CHECK-NEXT: [[TMP95:%.*]] = xor <vscale x 4 x i1> [[ACTIVE_LANE_MASK_NEXT14]], shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i64 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer) ; CHECK-NEXT: [[TMP96:%.*]] = xor <vscale x 4 x i1> [[ACTIVE_LANE_MASK_NEXT15]], shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i64 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer) diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/sve-widen-gep.ll b/llvm/test/Transforms/LoopVectorize/AArch64/sve-widen-gep.ll index 899fcce5c02aba1a12c8fb40e710b373768ea909..3bab341e1c248a8d1a62e7ce9db9c4cf3f5735dd 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/sve-widen-gep.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/sve-widen-gep.ll @@ -19,10 +19,12 @@ target triple = "aarch64-unknown-linux-gnu" ; CHECK-NEXT: <x1> vector loop: { ; CHECK-NEXT: vector.body: ; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION -; CHECK-NEXT: EMIT ir<%ptr.iv.1> = WIDEN-POINTER-INDUCTION ir<%start.1>, 8 ; CHECK-NEXT: EMIT ir<%ptr.iv.2> = WIDEN-POINTER-INDUCTION ir<%start.2>, 1 +; CHECK-NEXT: vp<[[PTR_IDX:%.+]]> = DERIVED-IV ir<0> + vp<[[CAN_IV]]> * ir<8> +; CHECK-NEXT: vp<[[PTR_IDX_STEPS:%.+]]> = SCALAR-STEPS vp<[[PTR_IDX]]>, ir<8> +; CHECK-NEXT: EMIT vp<[[PTR_IV_1:%.+]]> = ptradd ir<%start.1>, vp<[[PTR_IDX_STEPS]]> ; CHECK-NEXT: WIDEN-GEP Var[Inv] ir<%ptr.iv.2.next> = getelementptr inbounds ir<%ptr.iv.2>, ir<1> -; CHECK-NEXT: vp<[[VEC_PTR:%.+]]> = vector-pointer ir<%ptr.iv.1> +; CHECK-NEXT: vp<[[VEC_PTR:%.+]]> = vector-pointer vp<[[PTR_IV_1]]> ; CHECK-NEXT: WIDEN store vp<[[VEC_PTR]]>, ir<%ptr.iv.2.next> ; CHECK-NEXT: vp<[[VEC_PTR2:%.+]]> = vector-pointer ir<%ptr.iv.2> ; CHECK-NEXT: WIDEN ir<%lv> = load vp<[[VEC_PTR2]]> @@ -59,9 +61,6 @@ define void @pointer_induction_used_as_vector(ptr noalias %start.1, ptr noalias ; CHECK: vector.body: ; CHECK-NEXT: [[POINTER_PHI:%.*]] = phi ptr [ [[START_2]], [[VECTOR_PH]] ], [ [[PTR_IND:%.*]], [[VECTOR_BODY]] ] ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[INDEX]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = mul i64 [[TMP5]], 8 -; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[START_1]], i64 [[TMP6]] ; CHECK-NEXT: [[TMP7:%.*]] = call i64 @llvm.vscale.i64() ; CHECK-NEXT: [[TMP8:%.*]] = mul i64 [[TMP7]], 2 ; CHECK-NEXT: [[TMP9:%.*]] = mul i64 [[TMP8]], 1 @@ -73,6 +72,9 @@ define void @pointer_induction_used_as_vector(ptr noalias %start.1, ptr noalias ; CHECK-NEXT: [[TMP13:%.*]] = add <vscale x 2 x i64> [[DOTSPLAT]], [[TMP12]] ; CHECK-NEXT: [[VECTOR_GEP:%.*]] = mul <vscale x 2 x i64> [[TMP13]], shufflevector (<vscale x 2 x i64> insertelement (<vscale x 2 x i64> poison, i64 1, i64 0), <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer) ; CHECK-NEXT: [[TMP14:%.*]] = getelementptr i8, ptr [[POINTER_PHI]], <vscale x 2 x i64> [[VECTOR_GEP]] +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = mul i64 [[INDEX]], 8 +; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[OFFSET_IDX]], 0 +; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[START_1]], i64 [[TMP5]] ; CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds i8, <vscale x 2 x ptr> [[TMP14]], i64 1 ; CHECK-NEXT: [[TMP16:%.*]] = getelementptr ptr, ptr [[NEXT_GEP]], i32 0 ; CHECK-NEXT: store <vscale x 2 x ptr> [[TMP15]], ptr [[TMP16]], align 8 diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/sve-widen-phi.ll b/llvm/test/Transforms/LoopVectorize/AArch64/sve-widen-phi.ll index 7226048c478d487459dfb18b7251fb06e73b9cff..126ceac7325a44369b805f82a5b4ff33852d3ed9 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/sve-widen-phi.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/sve-widen-phi.ll @@ -32,21 +32,20 @@ define void @widen_ptr_phi_unrolled(ptr noalias nocapture %a, ptr noalias nocapt ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP6:%.*]] = shl i64 [[INDEX]], 3 -; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[C]], i64 [[TMP6]] -; CHECK-NEXT: [[TMP7:%.*]] = call i64 @llvm.vscale.i64() -; CHECK-NEXT: [[TMP8:%.*]] = shl nuw nsw i64 [[TMP7]], 5 -; CHECK-NEXT: [[TMP9:%.*]] = shl i64 [[INDEX]], 3 -; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[C]], i64 [[TMP8]] -; CHECK-NEXT: [[NEXT_GEP2:%.*]] = getelementptr i8, ptr [[TMP10]], i64 [[TMP9]] -; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <vscale x 8 x i32>, ptr [[NEXT_GEP]], align 4 -; CHECK-NEXT: [[WIDE_VEC3:%.*]] = load <vscale x 8 x i32>, ptr [[NEXT_GEP2]], align 4 +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = shl i64 [[INDEX]], 3 +; CHECK-NEXT: [[TMP6:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP7:%.*]] = shl nuw nsw i64 [[TMP6]], 5 +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[C]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[C]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[TMP9]], i64 [[TMP7]] +; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <vscale x 8 x i32>, ptr [[TMP8]], align 4 +; CHECK-NEXT: [[WIDE_VEC2:%.*]] = load <vscale x 8 x i32>, ptr [[TMP10]], align 4 ; CHECK-NEXT: [[STRIDED_VEC:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.experimental.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[WIDE_VEC]]) ; CHECK-NEXT: [[TMP11:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 0 ; CHECK-NEXT: [[TMP12:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC]], 1 -; CHECK-NEXT: [[STRIDED_VEC4:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.experimental.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[WIDE_VEC3]]) -; CHECK-NEXT: [[TMP13:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC4]], 0 -; CHECK-NEXT: [[TMP14:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC4]], 1 +; CHECK-NEXT: [[STRIDED_VEC3:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.experimental.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[WIDE_VEC2]]) +; CHECK-NEXT: [[TMP13:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC3]], 0 +; CHECK-NEXT: [[TMP14:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[STRIDED_VEC3]], 1 ; CHECK-NEXT: [[TMP15:%.*]] = add nsw <vscale x 4 x i32> [[TMP11]], shufflevector (<vscale x 4 x i32> insertelement (<vscale x 4 x i32> poison, i32 1, i64 0), <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer) ; CHECK-NEXT: [[TMP16:%.*]] = add nsw <vscale x 4 x i32> [[TMP13]], shufflevector (<vscale x 4 x i32> insertelement (<vscale x 4 x i32> poison, i32 1, i64 0), <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer) ; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDEX]] @@ -148,21 +147,21 @@ define void @widen_2ptrs_phi_unrolled(ptr noalias nocapture %dst, ptr noalias no ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP7:%.*]] = shl i64 [[INDEX]], 2 -; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[TMP7]] -; CHECK-NEXT: [[TMP8:%.*]] = shl i64 [[INDEX]], 2 -; CHECK-NEXT: [[NEXT_GEP5:%.*]] = getelementptr i8, ptr [[DST]], i64 [[TMP8]] +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = shl i64 [[INDEX]], 2 +; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[OFFSET_IDX4:%.*]] = shl i64 [[INDEX]], 2 +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[DST]], i64 [[OFFSET_IDX4]] ; CHECK-NEXT: [[TMP9:%.*]] = call i64 @llvm.vscale.i64() ; CHECK-NEXT: [[TMP10:%.*]] = shl nuw nsw i64 [[TMP9]], 2 -; CHECK-NEXT: [[TMP11:%.*]] = getelementptr i32, ptr [[NEXT_GEP]], i64 [[TMP10]] -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <vscale x 4 x i32>, ptr [[NEXT_GEP]], align 4 -; CHECK-NEXT: [[WIDE_LOAD7:%.*]] = load <vscale x 4 x i32>, ptr [[TMP11]], align 4 +; CHECK-NEXT: [[TMP11:%.*]] = getelementptr i32, ptr [[TMP7]], i64 [[TMP10]] +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <vscale x 4 x i32>, ptr [[TMP7]], align 4 +; CHECK-NEXT: [[WIDE_LOAD5:%.*]] = load <vscale x 4 x i32>, ptr [[TMP11]], align 4 ; CHECK-NEXT: [[TMP12:%.*]] = shl nsw <vscale x 4 x i32> [[WIDE_LOAD]], shufflevector (<vscale x 4 x i32> insertelement (<vscale x 4 x i32> poison, i32 1, i64 0), <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer) -; CHECK-NEXT: [[TMP13:%.*]] = shl nsw <vscale x 4 x i32> [[WIDE_LOAD7]], shufflevector (<vscale x 4 x i32> insertelement (<vscale x 4 x i32> poison, i32 1, i64 0), <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer) +; CHECK-NEXT: [[TMP13:%.*]] = shl nsw <vscale x 4 x i32> [[WIDE_LOAD5]], shufflevector (<vscale x 4 x i32> insertelement (<vscale x 4 x i32> poison, i32 1, i64 0), <vscale x 4 x i32> poison, <vscale x 4 x i32> zeroinitializer) ; CHECK-NEXT: [[TMP14:%.*]] = call i64 @llvm.vscale.i64() ; CHECK-NEXT: [[TMP15:%.*]] = shl nuw nsw i64 [[TMP14]], 2 -; CHECK-NEXT: [[TMP16:%.*]] = getelementptr i32, ptr [[NEXT_GEP5]], i64 [[TMP15]] -; CHECK-NEXT: store <vscale x 4 x i32> [[TMP12]], ptr [[NEXT_GEP5]], align 4 +; CHECK-NEXT: [[TMP16:%.*]] = getelementptr i32, ptr [[TMP8]], i64 [[TMP15]] +; CHECK-NEXT: store <vscale x 4 x i32> [[TMP12]], ptr [[TMP8]], align 4 ; CHECK-NEXT: store <vscale x 4 x i32> [[TMP13]], ptr [[TMP16]], align 4 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP6]] ; CHECK-NEXT: [[TMP17:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] @@ -246,12 +245,12 @@ define i32 @pointer_iv_mixed(ptr noalias %a, ptr noalias %b, i64 %n) #0 { ; CHECK-NEXT: [[TMP9:%.*]] = call <vscale x 2 x i64> @llvm.experimental.stepvector.nxv2i64() ; CHECK-NEXT: [[VECTOR_GEP:%.*]] = shl <vscale x 2 x i64> [[TMP9]], shufflevector (<vscale x 2 x i64> insertelement (<vscale x 2 x i64> poison, i64 2, i64 0), <vscale x 2 x i64> poison, <vscale x 2 x i32> zeroinitializer) ; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i8, ptr [[POINTER_PHI]], <vscale x 2 x i64> [[VECTOR_GEP]] -; CHECK-NEXT: [[TMP11:%.*]] = shl i64 [[INDEX]], 3 -; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP11]] +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = shl i64 [[INDEX]], 3 +; CHECK-NEXT: [[TMP11:%.*]] = getelementptr i8, ptr [[B]], i64 [[OFFSET_IDX]] ; CHECK-NEXT: [[TMP12:%.*]] = extractelement <vscale x 2 x ptr> [[TMP10]], i64 0 ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <vscale x 2 x i32>, ptr [[TMP12]], align 8 ; CHECK-NEXT: [[TMP13]] = add <vscale x 2 x i32> [[WIDE_LOAD]], [[VEC_PHI]] -; CHECK-NEXT: store <vscale x 2 x ptr> [[TMP10]], ptr [[NEXT_GEP]], align 8 +; CHECK-NEXT: store <vscale x 2 x ptr> [[TMP10]], ptr [[TMP11]], align 8 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP6]] ; CHECK-NEXT: [[PTR_IND]] = getelementptr i8, ptr [[POINTER_PHI]], i64 [[TMP8]] ; CHECK-NEXT: [[TMP14:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/uniform-args-call-variants.ll b/llvm/test/Transforms/LoopVectorize/AArch64/uniform-args-call-variants.ll index 4957bbeda671180fa2ad4dbf7c31cdb932172270..d8f14f30295b647c1841200a237833c2313f0e81 100644 --- a/llvm/test/Transforms/LoopVectorize/AArch64/uniform-args-call-variants.ll +++ b/llvm/test/Transforms/LoopVectorize/AArch64/uniform-args-call-variants.ll @@ -40,9 +40,6 @@ define void @test_uniform(ptr noalias %dst, ptr readonly %src, i64 %uniform , i6 ; INTERLEAVE-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64() ; INTERLEAVE-NEXT: [[TMP3:%.*]] = shl i64 [[TMP2]], 2 ; INTERLEAVE-NEXT: [[TMP4:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[N]], i64 [[TMP3]]) -; INTERLEAVE-NEXT: [[TMP5:%.*]] = call i64 @llvm.vscale.i64() -; INTERLEAVE-NEXT: [[TMP6:%.*]] = shl i64 [[TMP5]], 2 -; INTERLEAVE-NEXT: [[TMP7:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[N]], i64 [[TMP6]]) ; INTERLEAVE-NEXT: [[TMP8:%.*]] = call i64 @llvm.vscale.i64() ; INTERLEAVE-NEXT: [[TMP9:%.*]] = shl i64 [[TMP8]], 1 ; INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK_ENTRY:%.*]] = call <vscale x 2 x i1> @llvm.get.active.lane.mask.nxv2i1.i64(i64 0, i64 [[N]]) @@ -71,7 +68,7 @@ define void @test_uniform(ptr noalias %dst, ptr readonly %src, i64 %uniform , i6 ; INTERLEAVE-NEXT: [[TMP21:%.*]] = shl i64 [[TMP20]], 1 ; INTERLEAVE-NEXT: [[TMP22:%.*]] = add i64 [[INDEX]], [[TMP21]] ; INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call <vscale x 2 x i1> @llvm.get.active.lane.mask.nxv2i1.i64(i64 [[INDEX]], i64 [[TMP4]]) -; INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK_NEXT4]] = call <vscale x 2 x i1> @llvm.get.active.lane.mask.nxv2i1.i64(i64 [[TMP22]], i64 [[TMP7]]) +; INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK_NEXT4]] = call <vscale x 2 x i1> @llvm.get.active.lane.mask.nxv2i1.i64(i64 [[TMP22]], i64 [[TMP4]]) ; INTERLEAVE-NEXT: [[TMP23:%.*]] = extractelement <vscale x 2 x i1> [[ACTIVE_LANE_MASK_NEXT]], i64 0 ; INTERLEAVE-NEXT: br i1 [[TMP23]], label [[VECTOR_BODY]], label [[FOR_COND_CLEANUP:%.*]], !llvm.loop [[LOOP0:![0-9]+]] ; INTERLEAVE: for.cond.cleanup: @@ -129,9 +126,6 @@ define void @test_uniform_smaller_scalar(ptr noalias %dst, ptr readonly %src, i3 ; INTERLEAVE-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64() ; INTERLEAVE-NEXT: [[TMP3:%.*]] = shl i64 [[TMP2]], 2 ; INTERLEAVE-NEXT: [[TMP4:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[N]], i64 [[TMP3]]) -; INTERLEAVE-NEXT: [[TMP5:%.*]] = call i64 @llvm.vscale.i64() -; INTERLEAVE-NEXT: [[TMP6:%.*]] = shl i64 [[TMP5]], 2 -; INTERLEAVE-NEXT: [[TMP7:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[N]], i64 [[TMP6]]) ; INTERLEAVE-NEXT: [[TMP8:%.*]] = call i64 @llvm.vscale.i64() ; INTERLEAVE-NEXT: [[TMP9:%.*]] = shl i64 [[TMP8]], 1 ; INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK_ENTRY:%.*]] = call <vscale x 2 x i1> @llvm.get.active.lane.mask.nxv2i1.i64(i64 0, i64 [[N]]) @@ -160,7 +154,7 @@ define void @test_uniform_smaller_scalar(ptr noalias %dst, ptr readonly %src, i3 ; INTERLEAVE-NEXT: [[TMP21:%.*]] = shl i64 [[TMP20]], 1 ; INTERLEAVE-NEXT: [[TMP22:%.*]] = add i64 [[INDEX]], [[TMP21]] ; INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = call <vscale x 2 x i1> @llvm.get.active.lane.mask.nxv2i1.i64(i64 [[INDEX]], i64 [[TMP4]]) -; INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK_NEXT4]] = call <vscale x 2 x i1> @llvm.get.active.lane.mask.nxv2i1.i64(i64 [[TMP22]], i64 [[TMP7]]) +; INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK_NEXT4]] = call <vscale x 2 x i1> @llvm.get.active.lane.mask.nxv2i1.i64(i64 [[TMP22]], i64 [[TMP4]]) ; INTERLEAVE-NEXT: [[TMP23:%.*]] = extractelement <vscale x 2 x i1> [[ACTIVE_LANE_MASK_NEXT]], i64 0 ; INTERLEAVE-NEXT: br i1 [[TMP23]], label [[VECTOR_BODY]], label [[FOR_COND_CLEANUP:%.*]], !llvm.loop [[LOOP3:![0-9]+]] ; INTERLEAVE: for.cond.cleanup: @@ -207,7 +201,6 @@ define void @test_uniform_not_invariant(ptr noalias %dst, ptr readonly %src, i64 ; INTERLEAVE-SAME: (ptr noalias [[DST:%.*]], ptr readonly [[SRC:%.*]], i64 [[N:%.*]]) #[[ATTR0]] { ; INTERLEAVE-NEXT: entry: ; INTERLEAVE-NEXT: [[TMP0:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[N]], i64 2) -; INTERLEAVE-NEXT: [[TMP1:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[N]], i64 2) ; INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK_ENTRY:%.*]] = icmp ne i64 [[N]], 0 ; INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK_ENTRY1:%.*]] = icmp ugt i64 [[N]], 1 ; INTERLEAVE-NEXT: br label [[VECTOR_BODY:%.*]] @@ -237,7 +230,7 @@ define void @test_uniform_not_invariant(ptr noalias %dst, ptr readonly %src, i64 ; INTERLEAVE-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 2 ; INTERLEAVE-NEXT: [[TMP11:%.*]] = or disjoint i64 [[INDEX]], 1 ; INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK_NEXT]] = icmp ult i64 [[INDEX]], [[TMP0]] -; INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK_NEXT5]] = icmp ult i64 [[TMP11]], [[TMP1]] +; INTERLEAVE-NEXT: [[ACTIVE_LANE_MASK_NEXT5]] = icmp ult i64 [[TMP11]], [[TMP0]] ; INTERLEAVE-NEXT: br i1 [[ACTIVE_LANE_MASK_NEXT]], label [[VECTOR_BODY]], label [[FOR_COND_CLEANUP:%.*]], !llvm.loop [[LOOP4:![0-9]+]] ; INTERLEAVE: for.cond.cleanup: ; INTERLEAVE-NEXT: ret void diff --git a/llvm/test/Transforms/LoopVectorize/ARM/mve-selectandorcost.ll b/llvm/test/Transforms/LoopVectorize/ARM/mve-selectandorcost.ll index 938e1deab0b6c9c9f3661be203132a1bf885c416..69538343356693888da899f232e8d1a42b1effc3 100644 --- a/llvm/test/Transforms/LoopVectorize/ARM/mve-selectandorcost.ll +++ b/llvm/test/Transforms/LoopVectorize/ARM/mve-selectandorcost.ll @@ -45,8 +45,8 @@ define float @test(ptr nocapture readonly %pA, ptr nocapture readonly %pB, i32 % ; CHECK-NEXT: [[TMP9:%.*]] = fsub fast <4 x float> [[WIDE_LOAD]], [[WIDE_LOAD6]] ; CHECK-NEXT: [[TMP10:%.*]] = call fast <4 x float> @llvm.fabs.v4f32(<4 x float> [[TMP9]]) ; CHECK-NEXT: [[TMP11:%.*]] = fdiv fast <4 x float> [[TMP10]], [[TMP8]] -; CHECK-NEXT: [[TMP12:%.*]] = select <4 x i1> [[DOTNOT8]], <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, <4 x float> [[TMP11]] -; CHECK-NEXT: [[PREDPHI]] = fadd fast <4 x float> [[VEC_PHI]], [[TMP12]] +; CHECK-NEXT: [[TMP12:%.*]] = fadd fast <4 x float> [[TMP11]], [[VEC_PHI]] +; CHECK-NEXT: [[PREDPHI]] = select <4 x i1> [[DOTNOT8]], <4 x float> [[VEC_PHI]], <4 x float> [[TMP12]] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4 ; CHECK-NEXT: [[TMP13:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] ; CHECK-NEXT: br i1 [[TMP13]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] diff --git a/llvm/test/Transforms/LoopVectorize/RISCV/pr87378-vpinstruction-or-drop-poison-generating-flags.ll b/llvm/test/Transforms/LoopVectorize/RISCV/pr87378-vpinstruction-or-drop-poison-generating-flags.ll new file mode 100644 index 0000000000000000000000000000000000000000..4e38630209b2d49b79317e890d381f37d4484e15 --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/RISCV/pr87378-vpinstruction-or-drop-poison-generating-flags.ll @@ -0,0 +1,132 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -p loop-vectorize -mattr="+v" -S %s | FileCheck %s + +target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128" +target triple = "riscv64-unknown-linux-gnu" + +; Test case for https://github.com/llvm/llvm-project/issues/87378. +define void @pr87378_vpinstruction_or_drop_poison_generating_flags(ptr %arg, i64 %a, i64 %b, i64 %c) { +; CHECK-LABEL: define void @pr87378_vpinstruction_or_drop_poison_generating_flags( +; CHECK-SAME: ptr [[ARG:%.*]], i64 [[A:%.*]], i64 [[B:%.*]], i64 [[C:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP1:%.*]] = mul i64 [[TMP0]], 8 +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 1001, [[TMP1]] +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP3:%.*]] = mul i64 [[TMP2]], 8 +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 1001, [[TMP3]] +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 1001, [[N_MOD_VF]] +; CHECK-NEXT: [[TMP4:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP5:%.*]] = mul i64 [[TMP4]], 8 +; CHECK-NEXT: [[TMP6:%.*]] = call <vscale x 8 x i64> @llvm.experimental.stepvector.nxv8i64() +; CHECK-NEXT: [[TMP7:%.*]] = add <vscale x 8 x i64> [[TMP6]], zeroinitializer +; CHECK-NEXT: [[TMP8:%.*]] = mul <vscale x 8 x i64> [[TMP7]], shufflevector (<vscale x 8 x i64> insertelement (<vscale x 8 x i64> poison, i64 1, i64 0), <vscale x 8 x i64> poison, <vscale x 8 x i32> zeroinitializer) +; CHECK-NEXT: [[INDUCTION:%.*]] = add <vscale x 8 x i64> zeroinitializer, [[TMP8]] +; CHECK-NEXT: [[TMP9:%.*]] = call i64 @llvm.vscale.i64() +; CHECK-NEXT: [[TMP10:%.*]] = mul i64 [[TMP9]], 8 +; CHECK-NEXT: [[TMP11:%.*]] = mul i64 1, [[TMP10]] +; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <vscale x 8 x i64> poison, i64 [[TMP11]], i64 0 +; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <vscale x 8 x i64> [[DOTSPLATINSERT]], <vscale x 8 x i64> poison, <vscale x 8 x i32> zeroinitializer +; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <vscale x 8 x i64> poison, i64 [[A]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <vscale x 8 x i64> [[BROADCAST_SPLATINSERT]], <vscale x 8 x i64> poison, <vscale x 8 x i32> zeroinitializer +; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <vscale x 8 x i64> poison, i64 [[B]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <vscale x 8 x i64> [[BROADCAST_SPLATINSERT1]], <vscale x 8 x i64> poison, <vscale x 8 x i32> zeroinitializer +; CHECK-NEXT: [[BROADCAST_SPLATINSERT3:%.*]] = insertelement <vscale x 8 x i64> poison, i64 [[C]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT4:%.*]] = shufflevector <vscale x 8 x i64> [[BROADCAST_SPLATINSERT3]], <vscale x 8 x i64> poison, <vscale x 8 x i32> zeroinitializer +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_IND:%.*]] = phi <vscale x 8 x i64> [ [[INDUCTION]], [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[INDEX]], 0 +; CHECK-NEXT: [[BROADCAST_SPLATINSERT5:%.*]] = insertelement <vscale x 8 x i64> poison, i64 [[TMP12]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT6:%.*]] = shufflevector <vscale x 8 x i64> [[BROADCAST_SPLATINSERT5]], <vscale x 8 x i64> poison, <vscale x 8 x i32> zeroinitializer +; CHECK-NEXT: [[TMP13:%.*]] = icmp ule <vscale x 8 x i64> [[VEC_IND]], [[BROADCAST_SPLAT]] +; CHECK-NEXT: [[TMP14:%.*]] = icmp ule <vscale x 8 x i64> [[VEC_IND]], [[BROADCAST_SPLAT2]] +; CHECK-NEXT: [[TMP15:%.*]] = select <vscale x 8 x i1> [[TMP13]], <vscale x 8 x i1> [[TMP14]], <vscale x 8 x i1> zeroinitializer +; CHECK-NEXT: [[TMP16:%.*]] = xor <vscale x 8 x i1> [[TMP13]], shufflevector (<vscale x 8 x i1> insertelement (<vscale x 8 x i1> poison, i1 true, i64 0), <vscale x 8 x i1> poison, <vscale x 8 x i32> zeroinitializer) +; CHECK-NEXT: [[TMP17:%.*]] = or <vscale x 8 x i1> [[TMP15]], [[TMP16]] +; CHECK-NEXT: [[TMP18:%.*]] = icmp ule <vscale x 8 x i64> [[VEC_IND]], [[BROADCAST_SPLAT4]] +; CHECK-NEXT: [[TMP19:%.*]] = select <vscale x 8 x i1> [[TMP17]], <vscale x 8 x i1> [[TMP18]], <vscale x 8 x i1> zeroinitializer +; CHECK-NEXT: [[TMP20:%.*]] = xor <vscale x 8 x i1> [[TMP14]], shufflevector (<vscale x 8 x i1> insertelement (<vscale x 8 x i1> poison, i1 true, i64 0), <vscale x 8 x i1> poison, <vscale x 8 x i32> zeroinitializer) +; CHECK-NEXT: [[TMP21:%.*]] = select <vscale x 8 x i1> [[TMP13]], <vscale x 8 x i1> [[TMP20]], <vscale x 8 x i1> zeroinitializer +; CHECK-NEXT: [[TMP22:%.*]] = or <vscale x 8 x i1> [[TMP19]], [[TMP21]] +; CHECK-NEXT: [[PREDPHI:%.*]] = select <vscale x 8 x i1> [[TMP19]], <vscale x 8 x i64> [[BROADCAST_SPLAT6]], <vscale x 8 x i64> shufflevector (<vscale x 8 x i64> insertelement (<vscale x 8 x i64> poison, i64 poison, i64 0), <vscale x 8 x i64> poison, <vscale x 8 x i32> zeroinitializer) +; CHECK-NEXT: [[TMP23:%.*]] = extractelement <vscale x 8 x i64> [[PREDPHI]], i32 0 +; CHECK-NEXT: [[TMP24:%.*]] = getelementptr i16, ptr [[ARG]], i64 [[TMP23]] +; CHECK-NEXT: [[TMP25:%.*]] = getelementptr i16, ptr [[TMP24]], i32 0 +; CHECK-NEXT: call void @llvm.masked.store.nxv8i16.p0(<vscale x 8 x i16> zeroinitializer, ptr [[TMP25]], i32 2, <vscale x 8 x i1> [[TMP22]]) +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP5]] +; CHECK-NEXT: [[VEC_IND_NEXT]] = add <vscale x 8 x i64> [[VEC_IND]], [[DOTSPLAT]] +; CHECK-NEXT: [[TMP26:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP26]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK: middle.block: +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 1001, [[N_VEC]] +; CHECK-NEXT: br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] +; CHECK: loop.header: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ] +; CHECK-NEXT: [[C_1:%.*]] = icmp ule i64 [[IV]], [[A]] +; CHECK-NEXT: br i1 [[C_1]], label [[THEN_1:%.*]], label [[ELSE_1:%.*]] +; CHECK: then.1: +; CHECK-NEXT: [[C_2:%.*]] = icmp ule i64 [[IV]], [[B]] +; CHECK-NEXT: br i1 [[C_2]], label [[ELSE_1]], label [[MERGE:%.*]] +; CHECK: else.1: +; CHECK-NEXT: [[C_3:%.*]] = icmp ule i64 [[IV]], [[C]] +; CHECK-NEXT: br i1 [[C_3]], label [[THEN_2:%.*]], label [[LOOP_LATCH]] +; CHECK: then.2: +; CHECK-NEXT: br label [[MERGE]] +; CHECK: merge: +; CHECK-NEXT: [[IDX:%.*]] = phi i64 [ poison, [[THEN_1]] ], [ [[IV]], [[THEN_2]] ] +; CHECK-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr i16, ptr [[ARG]], i64 [[IDX]] +; CHECK-NEXT: store i16 0, ptr [[GETELEMENTPTR]], align 2 +; CHECK-NEXT: br label [[LOOP_LATCH]] +; CHECK: loop.latch: +; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 1 +; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i64 [[IV]], 1000 +; CHECK-NEXT: br i1 [[ICMP]], label [[EXIT]], label [[LOOP_HEADER]], !llvm.loop [[LOOP3:![0-9]+]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + br label %loop.header + +loop.header: + %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ] + %c.1 = icmp ule i64 %iv, %a + br i1 %c.1, label %then.1, label %else.1 + +then.1: + %c.2 = icmp ule i64 %iv, %b + br i1 %c.2, label %else.1, label %merge + +else.1: + %c.3 = icmp ule i64 %iv, %c + br i1 %c.3, label %then.2, label %loop.latch + +then.2: + br label %merge + +merge: + %idx = phi i64 [ poison, %then.1 ], [ %iv, %then.2 ] + %getelementptr = getelementptr i16, ptr %arg, i64 %idx + store i16 0, ptr %getelementptr, align 2 + br label %loop.latch + +loop.latch: + %iv.next = add i64 %iv, 1 + %icmp = icmp eq i64 %iv, 1000 + br i1 %icmp, label %exit, label %loop.header + +exit: + ret void +} +;. +; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]} +; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1} +; CHECK: [[META2]] = !{!"llvm.loop.unroll.runtime.disable"} +; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META2]], [[META1]]} +;. diff --git a/llvm/test/Transforms/LoopVectorize/X86/gather_scatter.ll b/llvm/test/Transforms/LoopVectorize/X86/gather_scatter.ll index e9541c1ee035f2de622698ae8ba5a1a26970436f..6516b05ab4ede91bfcb2aa04c3037810cb4457be 100644 --- a/llvm/test/Transforms/LoopVectorize/X86/gather_scatter.ll +++ b/llvm/test/Transforms/LoopVectorize/X86/gather_scatter.ll @@ -639,87 +639,84 @@ define void @test_gather_not_profitable_pr48429(i32 %d, ptr readonly noalias %pt ; AVX512: vector.ph: ; AVX512-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[TMP3]], 16 ; AVX512-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP3]], [[N_MOD_VF]] -; AVX512-NEXT: [[TMP13:%.*]] = mul i64 [[N_VEC]], 4 -; AVX512-NEXT: [[IND_END:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[TMP13]] -; AVX512-NEXT: [[TMP14:%.*]] = mul i64 [[N_VEC]], 64 -; AVX512-NEXT: [[IND_END9:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[TMP14]] +; AVX512-NEXT: [[TMP13:%.*]] = mul i64 [[N_VEC]], 64 +; AVX512-NEXT: [[IND_END:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[TMP13]] ; AVX512-NEXT: br label [[VECTOR_BODY:%.*]] ; AVX512: vector.body: ; AVX512-NEXT: [[POINTER_PHI:%.*]] = phi ptr [ [[DEST]], [[VECTOR_PH]] ], [ [[PTR_IND:%.*]], [[VECTOR_BODY]] ] ; AVX512-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; AVX512-NEXT: [[TMP15:%.*]] = add i64 [[INDEX]], 0 -; AVX512-NEXT: [[TMP16:%.*]] = mul i64 [[TMP15]], 4 -; AVX512-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[TMP16]] -; AVX512-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr [[POINTER_PHI]], <16 x i64> <i64 0, i64 64, i64 128, i64 192, i64 256, i64 320, i64 384, i64 448, i64 512, i64 576, i64 640, i64 704, i64 768, i64 832, i64 896, i64 960> -; AVX512-NEXT: [[TMP18:%.*]] = getelementptr inbounds float, ptr [[NEXT_GEP]], i64 [[IDXPROM]] -; AVX512-NEXT: [[TMP19:%.*]] = getelementptr inbounds float, ptr [[TMP18]], i32 0 -; AVX512-NEXT: [[WIDE_LOAD:%.*]] = load <16 x float>, ptr [[TMP19]], align 4, !alias.scope !8 -; AVX512-NEXT: call void @llvm.masked.scatter.v16f32.v16p0(<16 x float> [[WIDE_LOAD]], <16 x ptr> [[TMP17]], i32 4, <16 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>), !alias.scope !11, !noalias !13 -; AVX512-NEXT: [[TMP20:%.*]] = getelementptr float, ptr [[NEXT_GEP]], i32 0 -; AVX512-NEXT: [[WIDE_LOAD8:%.*]] = load <16 x float>, ptr [[TMP20]], align 4, !alias.scope !15 -; AVX512-NEXT: [[TMP21:%.*]] = getelementptr inbounds float, <16 x ptr> [[TMP17]], i64 1 -; AVX512-NEXT: call void @llvm.masked.scatter.v16f32.v16p0(<16 x float> [[WIDE_LOAD8]], <16 x ptr> [[TMP21]], i32 4, <16 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>), !alias.scope !11, !noalias !13 +; AVX512-NEXT: [[TMP14:%.*]] = getelementptr i8, ptr [[POINTER_PHI]], <16 x i64> <i64 0, i64 64, i64 128, i64 192, i64 256, i64 320, i64 384, i64 448, i64 512, i64 576, i64 640, i64 704, i64 768, i64 832, i64 896, i64 960> +; AVX512-NEXT: [[OFFSET_IDX:%.*]] = mul i64 [[INDEX]], 4 +; AVX512-NEXT: [[TMP15:%.*]] = add i64 [[OFFSET_IDX]], 0 +; AVX512-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[TMP15]] +; AVX512-NEXT: [[TMP17:%.*]] = getelementptr inbounds float, ptr [[TMP16]], i64 [[IDXPROM]] +; AVX512-NEXT: [[TMP18:%.*]] = getelementptr inbounds float, ptr [[TMP17]], i32 0 +; AVX512-NEXT: [[WIDE_LOAD:%.*]] = load <16 x float>, ptr [[TMP18]], align 4, !alias.scope [[META8:![0-9]+]] +; AVX512-NEXT: call void @llvm.masked.scatter.v16f32.v16p0(<16 x float> [[WIDE_LOAD]], <16 x ptr> [[TMP14]], i32 4, <16 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>), !alias.scope [[META11:![0-9]+]], !noalias [[META13:![0-9]+]] +; AVX512-NEXT: [[TMP19:%.*]] = getelementptr float, ptr [[TMP16]], i32 0 +; AVX512-NEXT: [[WIDE_LOAD8:%.*]] = load <16 x float>, ptr [[TMP19]], align 4, !alias.scope [[META15:![0-9]+]] +; AVX512-NEXT: [[TMP20:%.*]] = getelementptr inbounds float, <16 x ptr> [[TMP14]], i64 1 +; AVX512-NEXT: call void @llvm.masked.scatter.v16f32.v16p0(<16 x float> [[WIDE_LOAD8]], <16 x ptr> [[TMP20]], i32 4, <16 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>), !alias.scope [[META11]], !noalias [[META13]] ; AVX512-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 16 ; AVX512-NEXT: [[PTR_IND]] = getelementptr i8, ptr [[POINTER_PHI]], i64 1024 -; AVX512-NEXT: [[TMP22:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; AVX512-NEXT: br i1 [[TMP22]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]] +; AVX512-NEXT: [[TMP21:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; AVX512-NEXT: br i1 [[TMP21]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]] ; AVX512: middle.block: ; AVX512-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP3]], [[N_VEC]] ; AVX512-NEXT: br i1 [[CMP_N]], label [[FOR_END]], label [[VEC_EPILOG_ITER_CHECK:%.*]] ; AVX512: vec.epilog.iter.check: -; AVX512-NEXT: [[TMP23:%.*]] = mul i64 [[N_VEC]], 64 -; AVX512-NEXT: [[IND_END17:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[TMP23]] -; AVX512-NEXT: [[TMP24:%.*]] = mul i64 [[N_VEC]], 4 -; AVX512-NEXT: [[IND_END14:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[TMP24]] +; AVX512-NEXT: [[TMP22:%.*]] = mul i64 [[N_VEC]], 64 +; AVX512-NEXT: [[IND_END15:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[TMP22]] +; AVX512-NEXT: [[TMP23:%.*]] = mul i64 [[N_VEC]], 4 +; AVX512-NEXT: [[IND_END12:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[TMP23]] ; AVX512-NEXT: [[N_VEC_REMAINING:%.*]] = sub i64 [[TMP3]], [[N_VEC]] ; AVX512-NEXT: [[MIN_EPILOG_ITERS_CHECK:%.*]] = icmp ult i64 [[N_VEC_REMAINING]], 8 ; AVX512-NEXT: br i1 [[MIN_EPILOG_ITERS_CHECK]], label [[VEC_EPILOG_SCALAR_PH]], label [[VEC_EPILOG_PH]] ; AVX512: vec.epilog.ph: -; AVX512-NEXT: [[BC_RESUME_VAL:%.*]] = phi ptr [ [[IND_END]], [[VEC_EPILOG_ITER_CHECK]] ], [ [[PTR]], [[VECTOR_MAIN_LOOP_ITER_CHECK]] ] -; AVX512-NEXT: [[BC_RESUME_VAL10:%.*]] = phi ptr [ [[IND_END9]], [[VEC_EPILOG_ITER_CHECK]] ], [ [[DEST]], [[VECTOR_MAIN_LOOP_ITER_CHECK]] ] +; AVX512-NEXT: [[BC_RESUME_VAL:%.*]] = phi ptr [ [[IND_END]], [[VEC_EPILOG_ITER_CHECK]] ], [ [[DEST]], [[VECTOR_MAIN_LOOP_ITER_CHECK]] ] ; AVX512-NEXT: [[VEC_EPILOG_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[VEC_EPILOG_ITER_CHECK]] ], [ 0, [[VECTOR_MAIN_LOOP_ITER_CHECK]] ] -; AVX512-NEXT: [[N_MOD_VF11:%.*]] = urem i64 [[TMP3]], 8 -; AVX512-NEXT: [[N_VEC12:%.*]] = sub i64 [[TMP3]], [[N_MOD_VF11]] -; AVX512-NEXT: [[TMP25:%.*]] = mul i64 [[N_VEC12]], 4 -; AVX512-NEXT: [[IND_END13:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[TMP25]] -; AVX512-NEXT: [[TMP26:%.*]] = mul i64 [[N_VEC12]], 64 -; AVX512-NEXT: [[IND_END16:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[TMP26]] +; AVX512-NEXT: [[N_MOD_VF9:%.*]] = urem i64 [[TMP3]], 8 +; AVX512-NEXT: [[N_VEC10:%.*]] = sub i64 [[TMP3]], [[N_MOD_VF9]] +; AVX512-NEXT: [[TMP24:%.*]] = mul i64 [[N_VEC10]], 4 +; AVX512-NEXT: [[IND_END11:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[TMP24]] +; AVX512-NEXT: [[TMP25:%.*]] = mul i64 [[N_VEC10]], 64 +; AVX512-NEXT: [[IND_END14:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[TMP25]] ; AVX512-NEXT: br label [[VEC_EPILOG_VECTOR_BODY:%.*]] ; AVX512: vec.epilog.vector.body: -; AVX512-NEXT: [[POINTER_PHI22:%.*]] = phi ptr [ [[BC_RESUME_VAL10]], [[VEC_EPILOG_PH]] ], [ [[PTR_IND23:%.*]], [[VEC_EPILOG_VECTOR_BODY]] ] -; AVX512-NEXT: [[INDEX20:%.*]] = phi i64 [ [[VEC_EPILOG_RESUME_VAL]], [[VEC_EPILOG_PH]] ], [ [[INDEX_NEXT26:%.*]], [[VEC_EPILOG_VECTOR_BODY]] ] -; AVX512-NEXT: [[TMP27:%.*]] = add i64 [[INDEX20]], 0 -; AVX512-NEXT: [[TMP28:%.*]] = mul i64 [[TMP27]], 4 -; AVX512-NEXT: [[NEXT_GEP21:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[TMP28]] -; AVX512-NEXT: [[TMP29:%.*]] = getelementptr i8, ptr [[POINTER_PHI22]], <8 x i64> <i64 0, i64 64, i64 128, i64 192, i64 256, i64 320, i64 384, i64 448> -; AVX512-NEXT: [[TMP30:%.*]] = getelementptr inbounds float, ptr [[NEXT_GEP21]], i64 [[IDXPROM]] -; AVX512-NEXT: [[TMP31:%.*]] = getelementptr inbounds float, ptr [[TMP30]], i32 0 -; AVX512-NEXT: [[WIDE_LOAD24:%.*]] = load <8 x float>, ptr [[TMP31]], align 4, !alias.scope !17 -; AVX512-NEXT: call void @llvm.masked.scatter.v8f32.v8p0(<8 x float> [[WIDE_LOAD24]], <8 x ptr> [[TMP29]], i32 4, <8 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>), !alias.scope !20, !noalias !22 -; AVX512-NEXT: [[TMP32:%.*]] = getelementptr float, ptr [[NEXT_GEP21]], i32 0 -; AVX512-NEXT: [[WIDE_LOAD25:%.*]] = load <8 x float>, ptr [[TMP32]], align 4, !alias.scope !24 -; AVX512-NEXT: [[TMP33:%.*]] = getelementptr inbounds float, <8 x ptr> [[TMP29]], i64 1 -; AVX512-NEXT: call void @llvm.masked.scatter.v8f32.v8p0(<8 x float> [[WIDE_LOAD25]], <8 x ptr> [[TMP33]], i32 4, <8 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>), !alias.scope !20, !noalias !22 -; AVX512-NEXT: [[INDEX_NEXT26]] = add nuw i64 [[INDEX20]], 8 -; AVX512-NEXT: [[PTR_IND23]] = getelementptr i8, ptr [[POINTER_PHI22]], i64 512 -; AVX512-NEXT: [[TMP34:%.*]] = icmp eq i64 [[INDEX_NEXT26]], [[N_VEC12]] -; AVX512-NEXT: br i1 [[TMP34]], label [[VEC_EPILOG_MIDDLE_BLOCK:%.*]], label [[VEC_EPILOG_VECTOR_BODY]], !llvm.loop [[LOOP25:![0-9]+]] +; AVX512-NEXT: [[POINTER_PHI19:%.*]] = phi ptr [ [[BC_RESUME_VAL]], [[VEC_EPILOG_PH]] ], [ [[PTR_IND20:%.*]], [[VEC_EPILOG_VECTOR_BODY]] ] +; AVX512-NEXT: [[INDEX18:%.*]] = phi i64 [ [[VEC_EPILOG_RESUME_VAL]], [[VEC_EPILOG_PH]] ], [ [[INDEX_NEXT24:%.*]], [[VEC_EPILOG_VECTOR_BODY]] ] +; AVX512-NEXT: [[TMP26:%.*]] = getelementptr i8, ptr [[POINTER_PHI19]], <8 x i64> <i64 0, i64 64, i64 128, i64 192, i64 256, i64 320, i64 384, i64 448> +; AVX512-NEXT: [[OFFSET_IDX21:%.*]] = mul i64 [[INDEX18]], 4 +; AVX512-NEXT: [[TMP27:%.*]] = add i64 [[OFFSET_IDX21]], 0 +; AVX512-NEXT: [[TMP28:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[TMP27]] +; AVX512-NEXT: [[TMP29:%.*]] = getelementptr inbounds float, ptr [[TMP28]], i64 [[IDXPROM]] +; AVX512-NEXT: [[TMP30:%.*]] = getelementptr inbounds float, ptr [[TMP29]], i32 0 +; AVX512-NEXT: [[WIDE_LOAD22:%.*]] = load <8 x float>, ptr [[TMP30]], align 4, !alias.scope [[META17:![0-9]+]] +; AVX512-NEXT: call void @llvm.masked.scatter.v8f32.v8p0(<8 x float> [[WIDE_LOAD22]], <8 x ptr> [[TMP26]], i32 4, <8 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>), !alias.scope [[META20:![0-9]+]], !noalias [[META22:![0-9]+]] +; AVX512-NEXT: [[TMP31:%.*]] = getelementptr float, ptr [[TMP28]], i32 0 +; AVX512-NEXT: [[WIDE_LOAD23:%.*]] = load <8 x float>, ptr [[TMP31]], align 4, !alias.scope [[META24:![0-9]+]] +; AVX512-NEXT: [[TMP32:%.*]] = getelementptr inbounds float, <8 x ptr> [[TMP26]], i64 1 +; AVX512-NEXT: call void @llvm.masked.scatter.v8f32.v8p0(<8 x float> [[WIDE_LOAD23]], <8 x ptr> [[TMP32]], i32 4, <8 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>), !alias.scope [[META20]], !noalias [[META22]] +; AVX512-NEXT: [[INDEX_NEXT24]] = add nuw i64 [[INDEX18]], 8 +; AVX512-NEXT: [[PTR_IND20]] = getelementptr i8, ptr [[POINTER_PHI19]], i64 512 +; AVX512-NEXT: [[TMP33:%.*]] = icmp eq i64 [[INDEX_NEXT24]], [[N_VEC10]] +; AVX512-NEXT: br i1 [[TMP33]], label [[VEC_EPILOG_MIDDLE_BLOCK:%.*]], label [[VEC_EPILOG_VECTOR_BODY]], !llvm.loop [[LOOP25:![0-9]+]] ; AVX512: vec.epilog.middle.block: -; AVX512-NEXT: [[CMP_N19:%.*]] = icmp eq i64 [[TMP3]], [[N_VEC12]] -; AVX512-NEXT: br i1 [[CMP_N19]], label [[FOR_END]], label [[VEC_EPILOG_SCALAR_PH]] +; AVX512-NEXT: [[CMP_N17:%.*]] = icmp eq i64 [[TMP3]], [[N_VEC10]] +; AVX512-NEXT: br i1 [[CMP_N17]], label [[FOR_END]], label [[VEC_EPILOG_SCALAR_PH]] ; AVX512: vec.epilog.scalar.ph: -; AVX512-NEXT: [[BC_RESUME_VAL15:%.*]] = phi ptr [ [[IND_END13]], [[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[IND_END14]], [[VEC_EPILOG_ITER_CHECK]] ], [ [[PTR]], [[VECTOR_MEMCHECK]] ], [ [[PTR]], [[ITER_CHECK]] ] -; AVX512-NEXT: [[BC_RESUME_VAL18:%.*]] = phi ptr [ [[IND_END16]], [[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[IND_END17]], [[VEC_EPILOG_ITER_CHECK]] ], [ [[DEST]], [[VECTOR_MEMCHECK]] ], [ [[DEST]], [[ITER_CHECK]] ] +; AVX512-NEXT: [[BC_RESUME_VAL13:%.*]] = phi ptr [ [[IND_END11]], [[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[IND_END12]], [[VEC_EPILOG_ITER_CHECK]] ], [ [[PTR]], [[VECTOR_MEMCHECK]] ], [ [[PTR]], [[ITER_CHECK]] ] +; AVX512-NEXT: [[BC_RESUME_VAL16:%.*]] = phi ptr [ [[IND_END14]], [[VEC_EPILOG_MIDDLE_BLOCK]] ], [ [[IND_END15]], [[VEC_EPILOG_ITER_CHECK]] ], [ [[DEST]], [[VECTOR_MEMCHECK]] ], [ [[DEST]], [[ITER_CHECK]] ] ; AVX512-NEXT: br label [[FOR_BODY:%.*]] ; AVX512: for.body: -; AVX512-NEXT: [[PTR_ADDR_012:%.*]] = phi ptr [ [[BC_RESUME_VAL15]], [[VEC_EPILOG_SCALAR_PH]] ], [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ] -; AVX512-NEXT: [[DEST_ADDR_011:%.*]] = phi ptr [ [[BC_RESUME_VAL18]], [[VEC_EPILOG_SCALAR_PH]] ], [ [[ADD_PTR6:%.*]], [[FOR_BODY]] ] +; AVX512-NEXT: [[PTR_ADDR_012:%.*]] = phi ptr [ [[BC_RESUME_VAL13]], [[VEC_EPILOG_SCALAR_PH]] ], [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ] +; AVX512-NEXT: [[DEST_ADDR_011:%.*]] = phi ptr [ [[BC_RESUME_VAL16]], [[VEC_EPILOG_SCALAR_PH]] ], [ [[ADD_PTR6:%.*]], [[FOR_BODY]] ] ; AVX512-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, ptr [[PTR_ADDR_012]], i64 [[IDXPROM]] -; AVX512-NEXT: [[TMP35:%.*]] = load float, ptr [[ARRAYIDX]], align 4 -; AVX512-NEXT: store float [[TMP35]], ptr [[DEST_ADDR_011]], align 4 -; AVX512-NEXT: [[TMP36:%.*]] = load float, ptr [[PTR_ADDR_012]], align 4 +; AVX512-NEXT: [[TMP34:%.*]] = load float, ptr [[ARRAYIDX]], align 4 +; AVX512-NEXT: store float [[TMP34]], ptr [[DEST_ADDR_011]], align 4 +; AVX512-NEXT: [[TMP35:%.*]] = load float, ptr [[PTR_ADDR_012]], align 4 ; AVX512-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds float, ptr [[DEST_ADDR_011]], i64 1 -; AVX512-NEXT: store float [[TMP36]], ptr [[ARRAYIDX5]], align 4 +; AVX512-NEXT: store float [[TMP35]], ptr [[ARRAYIDX5]], align 4 ; AVX512-NEXT: [[INCDEC_PTR]] = getelementptr inbounds float, ptr [[PTR_ADDR_012]], i64 1 ; AVX512-NEXT: [[ADD_PTR6]] = getelementptr inbounds float, ptr [[DEST_ADDR_011]], i64 16 ; AVX512-NEXT: [[CMP_NOT:%.*]] = icmp eq ptr [[INCDEC_PTR]], [[ADD_PTR]] @@ -774,30 +771,29 @@ define void @test_gather_not_profitable_pr48429(i32 %d, ptr readonly noalias %pt ; FVW2-NEXT: br label [[VECTOR_BODY:%.*]] ; FVW2: vector.body: ; FVW2-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; FVW2-NEXT: [[TMP15:%.*]] = add i64 [[INDEX]], 0 -; FVW2-NEXT: [[TMP16:%.*]] = mul i64 [[TMP15]], 4 -; FVW2-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[TMP16]] -; FVW2-NEXT: [[TMP17:%.*]] = add i64 [[INDEX]], 0 -; FVW2-NEXT: [[TMP18:%.*]] = mul i64 [[TMP17]], 64 -; FVW2-NEXT: [[NEXT_GEP9:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[TMP18]] -; FVW2-NEXT: [[TMP19:%.*]] = add i64 [[INDEX]], 1 -; FVW2-NEXT: [[TMP20:%.*]] = mul i64 [[TMP19]], 64 -; FVW2-NEXT: [[NEXT_GEP10:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[TMP20]] -; FVW2-NEXT: [[TMP21:%.*]] = getelementptr inbounds float, ptr [[NEXT_GEP]], i64 [[IDXPROM]] +; FVW2-NEXT: [[OFFSET_IDX:%.*]] = mul i64 [[INDEX]], 4 +; FVW2-NEXT: [[TMP15:%.*]] = add i64 [[OFFSET_IDX]], 0 +; FVW2-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr [[PTR]], i64 [[TMP15]] +; FVW2-NEXT: [[OFFSET_IDX9:%.*]] = mul i64 [[INDEX]], 64 +; FVW2-NEXT: [[TMP17:%.*]] = add i64 [[OFFSET_IDX9]], 0 +; FVW2-NEXT: [[TMP18:%.*]] = add i64 [[OFFSET_IDX9]], 64 +; FVW2-NEXT: [[TMP19:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[TMP17]] +; FVW2-NEXT: [[TMP20:%.*]] = getelementptr i8, ptr [[DEST]], i64 [[TMP18]] +; FVW2-NEXT: [[TMP21:%.*]] = getelementptr inbounds float, ptr [[TMP16]], i64 [[IDXPROM]] ; FVW2-NEXT: [[TMP22:%.*]] = getelementptr inbounds float, ptr [[TMP21]], i32 0 -; FVW2-NEXT: [[WIDE_LOAD:%.*]] = load <2 x float>, ptr [[TMP22]], align 4, !alias.scope !8 +; FVW2-NEXT: [[WIDE_LOAD:%.*]] = load <2 x float>, ptr [[TMP22]], align 4, !alias.scope [[META8:![0-9]+]] ; FVW2-NEXT: [[TMP23:%.*]] = extractelement <2 x float> [[WIDE_LOAD]], i32 0 -; FVW2-NEXT: store float [[TMP23]], ptr [[NEXT_GEP9]], align 4, !alias.scope !11, !noalias !13 +; FVW2-NEXT: store float [[TMP23]], ptr [[TMP19]], align 4, !alias.scope [[META11:![0-9]+]], !noalias [[META13:![0-9]+]] ; FVW2-NEXT: [[TMP24:%.*]] = extractelement <2 x float> [[WIDE_LOAD]], i32 1 -; FVW2-NEXT: store float [[TMP24]], ptr [[NEXT_GEP10]], align 4, !alias.scope !11, !noalias !13 -; FVW2-NEXT: [[TMP25:%.*]] = getelementptr float, ptr [[NEXT_GEP]], i32 0 -; FVW2-NEXT: [[WIDE_LOAD11:%.*]] = load <2 x float>, ptr [[TMP25]], align 4, !alias.scope !15 -; FVW2-NEXT: [[TMP26:%.*]] = getelementptr inbounds float, ptr [[NEXT_GEP9]], i64 1 -; FVW2-NEXT: [[TMP27:%.*]] = getelementptr inbounds float, ptr [[NEXT_GEP10]], i64 1 -; FVW2-NEXT: [[TMP28:%.*]] = extractelement <2 x float> [[WIDE_LOAD11]], i32 0 -; FVW2-NEXT: store float [[TMP28]], ptr [[TMP26]], align 4, !alias.scope !11, !noalias !13 -; FVW2-NEXT: [[TMP29:%.*]] = extractelement <2 x float> [[WIDE_LOAD11]], i32 1 -; FVW2-NEXT: store float [[TMP29]], ptr [[TMP27]], align 4, !alias.scope !11, !noalias !13 +; FVW2-NEXT: store float [[TMP24]], ptr [[TMP20]], align 4, !alias.scope [[META11]], !noalias [[META13]] +; FVW2-NEXT: [[TMP25:%.*]] = getelementptr float, ptr [[TMP16]], i32 0 +; FVW2-NEXT: [[WIDE_LOAD10:%.*]] = load <2 x float>, ptr [[TMP25]], align 4, !alias.scope [[META15:![0-9]+]] +; FVW2-NEXT: [[TMP26:%.*]] = getelementptr inbounds float, ptr [[TMP19]], i64 1 +; FVW2-NEXT: [[TMP27:%.*]] = getelementptr inbounds float, ptr [[TMP20]], i64 1 +; FVW2-NEXT: [[TMP28:%.*]] = extractelement <2 x float> [[WIDE_LOAD10]], i32 0 +; FVW2-NEXT: store float [[TMP28]], ptr [[TMP26]], align 4, !alias.scope [[META11]], !noalias [[META13]] +; FVW2-NEXT: [[TMP29:%.*]] = extractelement <2 x float> [[WIDE_LOAD10]], i32 1 +; FVW2-NEXT: store float [[TMP29]], ptr [[TMP27]], align 4, !alias.scope [[META11]], !noalias [[META13]] ; FVW2-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2 ; FVW2-NEXT: [[TMP30:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] ; FVW2-NEXT: br i1 [[TMP30]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]] diff --git a/llvm/test/Transforms/LoopVectorize/X86/interleave-opaque-pointers.ll b/llvm/test/Transforms/LoopVectorize/X86/interleave-opaque-pointers.ll index 022912f3b8552e6e406e62942f1778941a189094..1b0118e137e73527b72516ce83802e564c91283b 100644 --- a/llvm/test/Transforms/LoopVectorize/X86/interleave-opaque-pointers.ll +++ b/llvm/test/Transforms/LoopVectorize/X86/interleave-opaque-pointers.ll @@ -25,15 +25,14 @@ define void @test_pr55375_interleave_opaque_ptr(ptr %start, ptr %end) { ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[INDEX]], 0 -; CHECK-NEXT: [[TMP6:%.*]] = mul i64 [[TMP5]], 16 -; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[START]], i64 [[TMP6]] -; CHECK-NEXT: [[TMP7:%.*]] = add i64 [[INDEX]], 1 -; CHECK-NEXT: [[TMP8:%.*]] = mul i64 [[TMP7]], 16 -; CHECK-NEXT: [[NEXT_GEP3:%.*]] = getelementptr i8, ptr [[START]], i64 [[TMP8]] -; CHECK-NEXT: [[TMP9:%.*]] = insertelement <2 x ptr> poison, ptr [[NEXT_GEP]], i32 0 -; CHECK-NEXT: [[TMP10:%.*]] = insertelement <2 x ptr> [[TMP9]], ptr [[NEXT_GEP3]], i32 1 -; CHECK-NEXT: [[TMP11:%.*]] = getelementptr ptr, ptr [[NEXT_GEP]], i32 0 +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = mul i64 [[INDEX]], 16 +; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[OFFSET_IDX]], 0 +; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[OFFSET_IDX]], 16 +; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[START]], i64 [[TMP5]] +; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i8, ptr [[START]], i64 [[TMP6]] +; CHECK-NEXT: [[TMP9:%.*]] = insertelement <2 x ptr> poison, ptr [[TMP7]], i32 0 +; CHECK-NEXT: [[TMP10:%.*]] = insertelement <2 x ptr> [[TMP9]], ptr [[TMP8]], i32 1 +; CHECK-NEXT: [[TMP11:%.*]] = getelementptr ptr, ptr [[TMP7]], i32 0 ; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <2 x ptr> zeroinitializer, <2 x ptr> [[TMP10]], <4 x i32> <i32 0, i32 1, i32 2, i32 3> ; CHECK-NEXT: [[INTERLEAVED_VEC:%.*]] = shufflevector <4 x ptr> [[TMP12]], <4 x ptr> poison, <4 x i32> <i32 0, i32 2, i32 1, i32 3> ; CHECK-NEXT: store <4 x ptr> [[INTERLEAVED_VEC]], ptr [[TMP11]], align 8 @@ -53,7 +52,7 @@ define void @test_pr55375_interleave_opaque_ptr(ptr %start, ptr %end) { ; CHECK-NEXT: store ptr null, ptr [[IV]], align 8 ; CHECK-NEXT: [[IV_NEXT]] = getelementptr inbounds [[PAIR]], ptr [[IV]], i64 1 ; CHECK-NEXT: [[EC:%.*]] = icmp eq ptr [[IV_NEXT]], [[END]] -; CHECK-NEXT: br i1 [[EC]], label [[EXIT]], label [[LOOP]], !llvm.loop [[LOOP2:![0-9]+]] +; CHECK-NEXT: br i1 [[EC]], label [[EXIT]], label [[LOOP]], !llvm.loop [[LOOP3:![0-9]+]] ; CHECK: exit: ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll b/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll index 14acb6f57aa0c97bc2d206f2fdfd857bcd167381..3f38abc75a5837ac3f347ec33658fcbb934904f0 100644 --- a/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll +++ b/llvm/test/Transforms/LoopVectorize/X86/pr81872.ll @@ -29,7 +29,7 @@ define void @test(ptr noundef align 8 dereferenceable_or_null(16) %arr) #0 { ; CHECK-NEXT: [[TMP2:%.*]] = and <4 x i64> [[VEC_IND]], <i64 1, i64 1, i64 1, i64 1> ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq <4 x i64> [[TMP2]], zeroinitializer ; CHECK-NEXT: [[TMP4:%.*]] = select <4 x i1> [[TMP1]], <4 x i1> [[TMP3]], <4 x i1> zeroinitializer -; CHECK-NEXT: [[TMP5:%.*]] = or i64 [[TMP0]], 1 +; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[TMP0]], 1 ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr i64, ptr [[ARR]], i64 [[TMP5]] ; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i64, ptr [[TMP6]], i32 0 ; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i64, ptr [[TMP7]], i32 -3 diff --git a/llvm/test/Transforms/LoopVectorize/X86/small-size.ll b/llvm/test/Transforms/LoopVectorize/X86/small-size.ll index 51d2648205030d1d5a5a40ca8534d00b8ab4d906..dc474fbf67ce8b12a1eaba0292d1ee50c11fb8aa 100644 --- a/llvm/test/Transforms/LoopVectorize/X86/small-size.ll +++ b/llvm/test/Transforms/LoopVectorize/X86/small-size.ll @@ -273,64 +273,58 @@ define void @example3(i32 %n, ptr noalias nocapture %p, ptr noalias nocapture %q ; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i64> [[BROADCAST_SPLATINSERT]], <4 x i64> poison, <4 x i32> zeroinitializer ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_STORE_CONTINUE19:%.*]] ] -; CHECK-NEXT: [[BROADCAST_SPLATINSERT12:%.*]] = insertelement <4 x i64> poison, i64 [[INDEX]], i64 0 -; CHECK-NEXT: [[BROADCAST_SPLAT13:%.*]] = shufflevector <4 x i64> [[BROADCAST_SPLATINSERT12]], <4 x i64> poison, <4 x i32> zeroinitializer -; CHECK-NEXT: [[VEC_IV:%.*]] = or disjoint <4 x i64> [[BROADCAST_SPLAT13]], <i64 0, i64 1, i64 2, i64 3> +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_STORE_CONTINUE20:%.*]] ] +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = shl i64 [[INDEX]], 2 +; CHECK-NEXT: [[OFFSET_IDX8:%.*]] = shl i64 [[INDEX]], 2 +; CHECK-NEXT: [[BROADCAST_SPLATINSERT13:%.*]] = insertelement <4 x i64> poison, i64 [[INDEX]], i64 0 +; CHECK-NEXT: [[BROADCAST_SPLAT14:%.*]] = shufflevector <4 x i64> [[BROADCAST_SPLATINSERT13]], <4 x i64> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[VEC_IV:%.*]] = or disjoint <4 x i64> [[BROADCAST_SPLAT14]], <i64 0, i64 1, i64 2, i64 3> ; CHECK-NEXT: [[TMP3:%.*]] = icmp ule <4 x i64> [[VEC_IV]], [[BROADCAST_SPLAT]] ; CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x i1> [[TMP3]], i64 0 ; CHECK-NEXT: br i1 [[TMP4]], label [[PRED_STORE_IF:%.*]], label [[PRED_STORE_CONTINUE:%.*]] ; CHECK: pred.store.if: -; CHECK-NEXT: [[TMP5:%.*]] = shl i64 [[INDEX]], 2 -; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[TMP5]] -; CHECK-NEXT: [[TMP6:%.*]] = shl i64 [[INDEX]], 2 -; CHECK-NEXT: [[NEXT_GEP8:%.*]] = getelementptr i8, ptr [[Q:%.*]], i64 [[TMP6]] -; CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[NEXT_GEP8]], align 16 -; CHECK-NEXT: store i32 [[TMP7]], ptr [[NEXT_GEP]], align 16 +; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[NEXT_GEP9:%.*]] = getelementptr i8, ptr [[Q:%.*]], i64 [[OFFSET_IDX8]] +; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[NEXT_GEP9]], align 16 +; CHECK-NEXT: store i32 [[TMP5]], ptr [[NEXT_GEP]], align 16 ; CHECK-NEXT: br label [[PRED_STORE_CONTINUE]] ; CHECK: pred.store.continue: -; CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x i1> [[TMP3]], i64 1 -; CHECK-NEXT: br i1 [[TMP8]], label [[PRED_STORE_IF14:%.*]], label [[PRED_STORE_CONTINUE15:%.*]] -; CHECK: pred.store.if14: -; CHECK-NEXT: [[TMP9:%.*]] = shl i64 [[INDEX]], 2 -; CHECK-NEXT: [[TMP10:%.*]] = or disjoint i64 [[TMP9]], 4 -; CHECK-NEXT: [[NEXT_GEP5:%.*]] = getelementptr i8, ptr [[P]], i64 [[TMP10]] -; CHECK-NEXT: [[TMP11:%.*]] = shl i64 [[INDEX]], 2 -; CHECK-NEXT: [[TMP12:%.*]] = or disjoint i64 [[TMP11]], 4 -; CHECK-NEXT: [[NEXT_GEP9:%.*]] = getelementptr i8, ptr [[Q]], i64 [[TMP12]] -; CHECK-NEXT: [[TMP13:%.*]] = load i32, ptr [[NEXT_GEP9]], align 16 -; CHECK-NEXT: store i32 [[TMP13]], ptr [[NEXT_GEP5]], align 16 -; CHECK-NEXT: br label [[PRED_STORE_CONTINUE15]] -; CHECK: pred.store.continue15: -; CHECK-NEXT: [[TMP14:%.*]] = extractelement <4 x i1> [[TMP3]], i64 2 -; CHECK-NEXT: br i1 [[TMP14]], label [[PRED_STORE_IF16:%.*]], label [[PRED_STORE_CONTINUE17:%.*]] -; CHECK: pred.store.if16: -; CHECK-NEXT: [[TMP15:%.*]] = shl i64 [[INDEX]], 2 -; CHECK-NEXT: [[TMP16:%.*]] = or disjoint i64 [[TMP15]], 8 -; CHECK-NEXT: [[NEXT_GEP6:%.*]] = getelementptr i8, ptr [[P]], i64 [[TMP16]] -; CHECK-NEXT: [[TMP17:%.*]] = shl i64 [[INDEX]], 2 -; CHECK-NEXT: [[TMP18:%.*]] = or disjoint i64 [[TMP17]], 8 -; CHECK-NEXT: [[NEXT_GEP10:%.*]] = getelementptr i8, ptr [[Q]], i64 [[TMP18]] -; CHECK-NEXT: [[TMP19:%.*]] = load i32, ptr [[NEXT_GEP10]], align 16 -; CHECK-NEXT: store i32 [[TMP19]], ptr [[NEXT_GEP6]], align 16 -; CHECK-NEXT: br label [[PRED_STORE_CONTINUE17]] -; CHECK: pred.store.continue17: -; CHECK-NEXT: [[TMP20:%.*]] = extractelement <4 x i1> [[TMP3]], i64 3 -; CHECK-NEXT: br i1 [[TMP20]], label [[PRED_STORE_IF18:%.*]], label [[PRED_STORE_CONTINUE19]] -; CHECK: pred.store.if18: -; CHECK-NEXT: [[TMP21:%.*]] = shl i64 [[INDEX]], 2 -; CHECK-NEXT: [[TMP22:%.*]] = or disjoint i64 [[TMP21]], 12 -; CHECK-NEXT: [[NEXT_GEP7:%.*]] = getelementptr i8, ptr [[P]], i64 [[TMP22]] -; CHECK-NEXT: [[TMP23:%.*]] = shl i64 [[INDEX]], 2 -; CHECK-NEXT: [[TMP24:%.*]] = or disjoint i64 [[TMP23]], 12 -; CHECK-NEXT: [[NEXT_GEP11:%.*]] = getelementptr i8, ptr [[Q]], i64 [[TMP24]] -; CHECK-NEXT: [[TMP25:%.*]] = load i32, ptr [[NEXT_GEP11]], align 16 -; CHECK-NEXT: store i32 [[TMP25]], ptr [[NEXT_GEP7]], align 16 -; CHECK-NEXT: br label [[PRED_STORE_CONTINUE19]] -; CHECK: pred.store.continue19: +; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x i1> [[TMP3]], i64 1 +; CHECK-NEXT: br i1 [[TMP6]], label [[PRED_STORE_IF15:%.*]], label [[PRED_STORE_CONTINUE16:%.*]] +; CHECK: pred.store.if15: +; CHECK-NEXT: [[TMP7:%.*]] = or disjoint i64 [[OFFSET_IDX]], 4 +; CHECK-NEXT: [[NEXT_GEP5:%.*]] = getelementptr i8, ptr [[P]], i64 [[TMP7]] +; CHECK-NEXT: [[TMP8:%.*]] = or disjoint i64 [[OFFSET_IDX8]], 4 +; CHECK-NEXT: [[NEXT_GEP10:%.*]] = getelementptr i8, ptr [[Q]], i64 [[TMP8]] +; CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[NEXT_GEP10]], align 16 +; CHECK-NEXT: store i32 [[TMP9]], ptr [[NEXT_GEP5]], align 16 +; CHECK-NEXT: br label [[PRED_STORE_CONTINUE16]] +; CHECK: pred.store.continue16: +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <4 x i1> [[TMP3]], i64 2 +; CHECK-NEXT: br i1 [[TMP10]], label [[PRED_STORE_IF17:%.*]], label [[PRED_STORE_CONTINUE18:%.*]] +; CHECK: pred.store.if17: +; CHECK-NEXT: [[TMP11:%.*]] = or disjoint i64 [[OFFSET_IDX]], 8 +; CHECK-NEXT: [[NEXT_GEP6:%.*]] = getelementptr i8, ptr [[P]], i64 [[TMP11]] +; CHECK-NEXT: [[TMP12:%.*]] = or disjoint i64 [[OFFSET_IDX8]], 8 +; CHECK-NEXT: [[NEXT_GEP11:%.*]] = getelementptr i8, ptr [[Q]], i64 [[TMP12]] +; CHECK-NEXT: [[TMP13:%.*]] = load i32, ptr [[NEXT_GEP11]], align 16 +; CHECK-NEXT: store i32 [[TMP13]], ptr [[NEXT_GEP6]], align 16 +; CHECK-NEXT: br label [[PRED_STORE_CONTINUE18]] +; CHECK: pred.store.continue18: +; CHECK-NEXT: [[TMP14:%.*]] = extractelement <4 x i1> [[TMP3]], i64 3 +; CHECK-NEXT: br i1 [[TMP14]], label [[PRED_STORE_IF19:%.*]], label [[PRED_STORE_CONTINUE20]] +; CHECK: pred.store.if19: +; CHECK-NEXT: [[TMP15:%.*]] = or disjoint i64 [[OFFSET_IDX]], 12 +; CHECK-NEXT: [[NEXT_GEP7:%.*]] = getelementptr i8, ptr [[P]], i64 [[TMP15]] +; CHECK-NEXT: [[TMP16:%.*]] = or disjoint i64 [[OFFSET_IDX8]], 12 +; CHECK-NEXT: [[NEXT_GEP12:%.*]] = getelementptr i8, ptr [[Q]], i64 [[TMP16]] +; CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[NEXT_GEP12]], align 16 +; CHECK-NEXT: store i32 [[TMP17]], ptr [[NEXT_GEP7]], align 16 +; CHECK-NEXT: br label [[PRED_STORE_CONTINUE20]] +; CHECK: pred.store.continue20: ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP26:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP26]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] +; CHECK-NEXT: [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP18]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP8:![0-9]+]] ; CHECK: middle.block: ; CHECK-NEXT: br i1 true, label [[DOT_CRIT_EDGE_LOOPEXIT:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: @@ -410,24 +404,24 @@ define void @example23b(ptr noalias nocapture %src, ptr noalias nocapture %dst) ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[INDEX]], 1 -; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 [[TMP1]] -; CHECK-NEXT: [[TMP2:%.*]] = shl i64 [[INDEX]], 2 -; CHECK-NEXT: [[NEXT_GEP4:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[TMP2]] +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = shl i64 [[INDEX]], 1 +; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[OFFSET_IDX4:%.*]] = shl i64 [[INDEX]], 2 +; CHECK-NEXT: [[NEXT_GEP5:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[OFFSET_IDX4]] ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i16>, ptr [[NEXT_GEP]], align 2 -; CHECK-NEXT: [[TMP3:%.*]] = zext <4 x i16> [[WIDE_LOAD]] to <4 x i32> -; CHECK-NEXT: [[TMP4:%.*]] = shl nuw nsw <4 x i32> [[TMP3]], <i32 7, i32 7, i32 7, i32 7> -; CHECK-NEXT: store <4 x i32> [[TMP4]], ptr [[NEXT_GEP4]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i16> [[WIDE_LOAD]] to <4 x i32> +; CHECK-NEXT: [[TMP2:%.*]] = shl nuw nsw <4 x i32> [[TMP1]], <i32 7, i32 7, i32 7, i32 7> +; CHECK-NEXT: store <4 x i32> [[TMP2]], ptr [[NEXT_GEP5]], align 4 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 -; CHECK-NEXT: br i1 [[TMP5]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]] +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP3]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP10:![0-9]+]] ; CHECK: middle.block: -; CHECK-NEXT: br i1 true, label [[TMP7:%.*]], label [[SCALAR_PH]] +; CHECK-NEXT: br i1 true, label [[TMP5:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: -; CHECK-NEXT: br label [[TMP6:%.*]] -; CHECK: 6: -; CHECK-NEXT: br i1 poison, label [[TMP7]], label [[TMP6]], !llvm.loop [[LOOP11:![0-9]+]] -; CHECK: 7: +; CHECK-NEXT: br label [[TMP4:%.*]] +; CHECK: 4: +; CHECK-NEXT: br i1 poison, label [[TMP5]], label [[TMP4]], !llvm.loop [[LOOP11:![0-9]+]] +; CHECK: 5: ; CHECK-NEXT: ret void ; br label %1 @@ -457,7 +451,9 @@ define void @example23c(ptr noalias nocapture %src, ptr noalias nocapture %dst) ; CHECK: vector.ph: ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_STORE_CONTINUE16:%.*]] ] +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_STORE_CONTINUE17:%.*]] ] +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = shl i64 [[INDEX]], 1 +; CHECK-NEXT: [[OFFSET_IDX7:%.*]] = shl i64 [[INDEX]], 2 ; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i64> poison, i64 [[INDEX]], i64 0 ; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i64> [[BROADCAST_SPLATINSERT]], <4 x i64> poison, <4 x i32> zeroinitializer ; CHECK-NEXT: [[VEC_IV:%.*]] = or disjoint <4 x i64> [[BROADCAST_SPLAT]], <i64 0, i64 1, i64 2, i64 3> @@ -465,71 +461,63 @@ define void @example23c(ptr noalias nocapture %src, ptr noalias nocapture %dst) ; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x i1> [[TMP1]], i64 0 ; CHECK-NEXT: br i1 [[TMP2]], label [[PRED_STORE_IF:%.*]], label [[PRED_STORE_CONTINUE:%.*]] ; CHECK: pred.store.if: -; CHECK-NEXT: [[TMP3:%.*]] = shl i64 [[INDEX]], 2 -; CHECK-NEXT: [[NEXT_GEP7:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[TMP3]] -; CHECK-NEXT: [[TMP4:%.*]] = shl i64 [[INDEX]], 1 -; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 [[TMP4]] -; CHECK-NEXT: [[TMP5:%.*]] = load i16, ptr [[NEXT_GEP]], align 2 -; CHECK-NEXT: [[TMP6:%.*]] = zext i16 [[TMP5]] to i32 -; CHECK-NEXT: [[TMP7:%.*]] = shl nuw nsw i32 [[TMP6]], 7 -; CHECK-NEXT: store i32 [[TMP7]], ptr [[NEXT_GEP7]], align 4 +; CHECK-NEXT: [[NEXT_GEP8:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[OFFSET_IDX7]] +; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 [[OFFSET_IDX]] +; CHECK-NEXT: [[TMP3:%.*]] = load i16, ptr [[NEXT_GEP]], align 2 +; CHECK-NEXT: [[TMP4:%.*]] = zext i16 [[TMP3]] to i32 +; CHECK-NEXT: [[TMP5:%.*]] = shl nuw nsw i32 [[TMP4]], 7 +; CHECK-NEXT: store i32 [[TMP5]], ptr [[NEXT_GEP8]], align 4 ; CHECK-NEXT: br label [[PRED_STORE_CONTINUE]] ; CHECK: pred.store.continue: -; CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x i1> [[TMP1]], i64 1 -; CHECK-NEXT: br i1 [[TMP8]], label [[PRED_STORE_IF11:%.*]], label [[PRED_STORE_CONTINUE12:%.*]] -; CHECK: pred.store.if11: -; CHECK-NEXT: [[TMP9:%.*]] = shl i64 [[INDEX]], 2 -; CHECK-NEXT: [[TMP10:%.*]] = or disjoint i64 [[TMP9]], 4 -; CHECK-NEXT: [[NEXT_GEP8:%.*]] = getelementptr i8, ptr [[DST]], i64 [[TMP10]] -; CHECK-NEXT: [[TMP11:%.*]] = shl i64 [[INDEX]], 1 -; CHECK-NEXT: [[TMP12:%.*]] = or disjoint i64 [[TMP11]], 2 -; CHECK-NEXT: [[NEXT_GEP4:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[TMP12]] -; CHECK-NEXT: [[TMP13:%.*]] = load i16, ptr [[NEXT_GEP4]], align 2 -; CHECK-NEXT: [[TMP14:%.*]] = zext i16 [[TMP13]] to i32 -; CHECK-NEXT: [[TMP15:%.*]] = shl nuw nsw i32 [[TMP14]], 7 -; CHECK-NEXT: store i32 [[TMP15]], ptr [[NEXT_GEP8]], align 4 -; CHECK-NEXT: br label [[PRED_STORE_CONTINUE12]] -; CHECK: pred.store.continue12: -; CHECK-NEXT: [[TMP16:%.*]] = extractelement <4 x i1> [[TMP1]], i64 2 -; CHECK-NEXT: br i1 [[TMP16]], label [[PRED_STORE_IF13:%.*]], label [[PRED_STORE_CONTINUE14:%.*]] -; CHECK: pred.store.if13: -; CHECK-NEXT: [[TMP17:%.*]] = shl i64 [[INDEX]], 2 -; CHECK-NEXT: [[TMP18:%.*]] = or disjoint i64 [[TMP17]], 8 -; CHECK-NEXT: [[NEXT_GEP9:%.*]] = getelementptr i8, ptr [[DST]], i64 [[TMP18]] -; CHECK-NEXT: [[TMP19:%.*]] = shl i64 [[INDEX]], 1 -; CHECK-NEXT: [[TMP20:%.*]] = or disjoint i64 [[TMP19]], 4 -; CHECK-NEXT: [[NEXT_GEP5:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[TMP20]] -; CHECK-NEXT: [[TMP21:%.*]] = load i16, ptr [[NEXT_GEP5]], align 2 +; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x i1> [[TMP1]], i64 1 +; CHECK-NEXT: br i1 [[TMP6]], label [[PRED_STORE_IF12:%.*]], label [[PRED_STORE_CONTINUE13:%.*]] +; CHECK: pred.store.if12: +; CHECK-NEXT: [[TMP7:%.*]] = or disjoint i64 [[OFFSET_IDX7]], 4 +; CHECK-NEXT: [[NEXT_GEP9:%.*]] = getelementptr i8, ptr [[DST]], i64 [[TMP7]] +; CHECK-NEXT: [[TMP8:%.*]] = or disjoint i64 [[OFFSET_IDX]], 2 +; CHECK-NEXT: [[NEXT_GEP4:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[TMP8]] +; CHECK-NEXT: [[TMP9:%.*]] = load i16, ptr [[NEXT_GEP4]], align 2 +; CHECK-NEXT: [[TMP10:%.*]] = zext i16 [[TMP9]] to i32 +; CHECK-NEXT: [[TMP11:%.*]] = shl nuw nsw i32 [[TMP10]], 7 +; CHECK-NEXT: store i32 [[TMP11]], ptr [[NEXT_GEP9]], align 4 +; CHECK-NEXT: br label [[PRED_STORE_CONTINUE13]] +; CHECK: pred.store.continue13: +; CHECK-NEXT: [[TMP12:%.*]] = extractelement <4 x i1> [[TMP1]], i64 2 +; CHECK-NEXT: br i1 [[TMP12]], label [[PRED_STORE_IF14:%.*]], label [[PRED_STORE_CONTINUE15:%.*]] +; CHECK: pred.store.if14: +; CHECK-NEXT: [[TMP13:%.*]] = or disjoint i64 [[OFFSET_IDX7]], 8 +; CHECK-NEXT: [[NEXT_GEP10:%.*]] = getelementptr i8, ptr [[DST]], i64 [[TMP13]] +; CHECK-NEXT: [[TMP14:%.*]] = or disjoint i64 [[OFFSET_IDX]], 4 +; CHECK-NEXT: [[NEXT_GEP5:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[TMP14]] +; CHECK-NEXT: [[TMP15:%.*]] = load i16, ptr [[NEXT_GEP5]], align 2 +; CHECK-NEXT: [[TMP16:%.*]] = zext i16 [[TMP15]] to i32 +; CHECK-NEXT: [[TMP17:%.*]] = shl nuw nsw i32 [[TMP16]], 7 +; CHECK-NEXT: store i32 [[TMP17]], ptr [[NEXT_GEP10]], align 4 +; CHECK-NEXT: br label [[PRED_STORE_CONTINUE15]] +; CHECK: pred.store.continue15: +; CHECK-NEXT: [[TMP18:%.*]] = extractelement <4 x i1> [[TMP1]], i64 3 +; CHECK-NEXT: br i1 [[TMP18]], label [[PRED_STORE_IF16:%.*]], label [[PRED_STORE_CONTINUE17]] +; CHECK: pred.store.if16: +; CHECK-NEXT: [[TMP19:%.*]] = or disjoint i64 [[OFFSET_IDX7]], 12 +; CHECK-NEXT: [[NEXT_GEP11:%.*]] = getelementptr i8, ptr [[DST]], i64 [[TMP19]] +; CHECK-NEXT: [[TMP20:%.*]] = or disjoint i64 [[OFFSET_IDX]], 6 +; CHECK-NEXT: [[NEXT_GEP6:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[TMP20]] +; CHECK-NEXT: [[TMP21:%.*]] = load i16, ptr [[NEXT_GEP6]], align 2 ; CHECK-NEXT: [[TMP22:%.*]] = zext i16 [[TMP21]] to i32 ; CHECK-NEXT: [[TMP23:%.*]] = shl nuw nsw i32 [[TMP22]], 7 -; CHECK-NEXT: store i32 [[TMP23]], ptr [[NEXT_GEP9]], align 4 -; CHECK-NEXT: br label [[PRED_STORE_CONTINUE14]] -; CHECK: pred.store.continue14: -; CHECK-NEXT: [[TMP24:%.*]] = extractelement <4 x i1> [[TMP1]], i64 3 -; CHECK-NEXT: br i1 [[TMP24]], label [[PRED_STORE_IF15:%.*]], label [[PRED_STORE_CONTINUE16]] -; CHECK: pred.store.if15: -; CHECK-NEXT: [[TMP25:%.*]] = shl i64 [[INDEX]], 2 -; CHECK-NEXT: [[TMP26:%.*]] = or disjoint i64 [[TMP25]], 12 -; CHECK-NEXT: [[NEXT_GEP10:%.*]] = getelementptr i8, ptr [[DST]], i64 [[TMP26]] -; CHECK-NEXT: [[TMP27:%.*]] = shl i64 [[INDEX]], 1 -; CHECK-NEXT: [[TMP28:%.*]] = or disjoint i64 [[TMP27]], 6 -; CHECK-NEXT: [[NEXT_GEP6:%.*]] = getelementptr i8, ptr [[SRC]], i64 [[TMP28]] -; CHECK-NEXT: [[TMP29:%.*]] = load i16, ptr [[NEXT_GEP6]], align 2 -; CHECK-NEXT: [[TMP30:%.*]] = zext i16 [[TMP29]] to i32 -; CHECK-NEXT: [[TMP31:%.*]] = shl nuw nsw i32 [[TMP30]], 7 -; CHECK-NEXT: store i32 [[TMP31]], ptr [[NEXT_GEP10]], align 4 -; CHECK-NEXT: br label [[PRED_STORE_CONTINUE16]] -; CHECK: pred.store.continue16: +; CHECK-NEXT: store i32 [[TMP23]], ptr [[NEXT_GEP11]], align 4 +; CHECK-NEXT: br label [[PRED_STORE_CONTINUE17]] +; CHECK: pred.store.continue17: ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP32:%.*]] = icmp eq i64 [[INDEX_NEXT]], 260 -; CHECK-NEXT: br i1 [[TMP32]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP12:![0-9]+]] +; CHECK-NEXT: [[TMP24:%.*]] = icmp eq i64 [[INDEX_NEXT]], 260 +; CHECK-NEXT: br i1 [[TMP24]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP12:![0-9]+]] ; CHECK: middle.block: -; CHECK-NEXT: br i1 true, label [[TMP34:%.*]], label [[SCALAR_PH]] +; CHECK-NEXT: br i1 true, label [[TMP26:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: -; CHECK-NEXT: br label [[TMP33:%.*]] -; CHECK: 33: -; CHECK-NEXT: br i1 poison, label [[TMP34]], label [[TMP33]], !llvm.loop [[LOOP13:![0-9]+]] -; CHECK: 34: +; CHECK-NEXT: br label [[TMP25:%.*]] +; CHECK: 25: +; CHECK-NEXT: br i1 poison, label [[TMP26]], label [[TMP25]], !llvm.loop [[LOOP13:![0-9]+]] +; CHECK: 26: ; CHECK-NEXT: ret void ; br label %1 diff --git a/llvm/test/Transforms/LoopVectorize/consecutive-ptr-uniforms.ll b/llvm/test/Transforms/LoopVectorize/consecutive-ptr-uniforms.ll index cc7c1d8a618878e2bde7ab3fc21c234a88a16aed..1e23f02ee2b16646863e511c87f3119a9c78aef9 100644 --- a/llvm/test/Transforms/LoopVectorize/consecutive-ptr-uniforms.ll +++ b/llvm/test/Transforms/LoopVectorize/consecutive-ptr-uniforms.ll @@ -311,15 +311,12 @@ for.end: ; INTER: vector.body ; INTER: %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ] ; INTER: %[[I0:.+]] = shl i64 %index, 4 +; INTER: %[[I1:.+]] = or disjoint i64 %[[I0]], 16 +; INTER: %[[I2:.+]] = or disjoint i64 %[[I0]], 32 +; INTER: %[[I3:.+]] = or disjoint i64 %[[I0]], 48 ; INTER: %next.gep = getelementptr i8, ptr %a, i64 %[[I0]] -; INTER: %[[S1:.+]] = shl i64 %index, 4 -; INTER: %[[I1:.+]] = or disjoint i64 %[[S1]], 16 ; INTER: %next.gep2 = getelementptr i8, ptr %a, i64 %[[I1]] -; INTER: %[[S2:.+]] = shl i64 %index, 4 -; INTER: %[[I2:.+]] = or disjoint i64 %[[S2]], 32 ; INTER: %next.gep3 = getelementptr i8, ptr %a, i64 %[[I2]] -; INTER: %[[S3:.+]] = shl i64 %index, 4 -; INTER: %[[I3:.+]] = or disjoint i64 %[[S3]], 48 ; INTER: %next.gep4 = getelementptr i8, ptr %a, i64 %[[I3]] ; INTER: br i1 {{.*}}, label %middle.block, label %vector.body ; @@ -361,15 +358,12 @@ for.end: ; CHECK: vector.body ; CHECK: %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ] ; CHECK: [[SHL1:%.+]] = shl i64 %index, 4 +; CHECK: %[[I1:.+]] = or disjoint i64 [[SHL1]], 16 +; CHECK: %[[I2:.+]] = or disjoint i64 [[SHL1]], 32 +; CHECK: %[[I3:.+]] = or disjoint i64 [[SHL1]], 48 ; CHECK: %next.gep = getelementptr i8, ptr %a, i64 [[SHL1]] -; CHECK: [[SHL2:%.+]] = shl i64 %index, 4 -; CHECK: %[[I1:.+]] = or disjoint i64 [[SHL2]], 16 ; CHECK: %next.gep2 = getelementptr i8, ptr %a, i64 %[[I1]] -; CHECK: [[SHL3:%.+]] = shl i64 %index, 4 -; CHECK: %[[I2:.+]] = or disjoint i64 [[SHL3]], 32 ; CHECK: %next.gep3 = getelementptr i8, ptr %a, i64 %[[I2]] -; CHECK: [[SHL4:%.+]] = shl i64 %index, 4 -; CHECK: %[[I3:.+]] = or disjoint i64 [[SHL4]], 48 ; CHECK: %next.gep4 = getelementptr i8, ptr %a, i64 %[[I3]] ; CHECK: br i1 {{.*}}, label %middle.block, label %vector.body ; diff --git a/llvm/test/Transforms/LoopVectorize/dbg-outer-loop-vect.ll b/llvm/test/Transforms/LoopVectorize/dbg-outer-loop-vect.ll index 7f209634fe053d2886019eaff45cf6612c7c29cf..2c665a417ab5993c723eb13f4d10d30fca07b2fa 100644 --- a/llvm/test/Transforms/LoopVectorize/dbg-outer-loop-vect.ll +++ b/llvm/test/Transforms/LoopVectorize/dbg-outer-loop-vect.ll @@ -7,7 +7,7 @@ define void @foo(ptr %h) !dbg !4 { ; CHECK-LABEL: define void @foo( ; CHECK-SAME: ptr [[H:%.*]]) !dbg [[DBG4:![0-9]+]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 0, metadata [[META11:![0-9]+]], metadata !DIExpression()), !dbg [[DBG20:![0-9]+]] +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 0, metadata [[META11:![0-9]+]], metadata !DIExpression()), !dbg [[DBG20:![0-9]+]] ; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]], !dbg [[DBG21:![0-9]+]] ; CHECK: vector.ph: ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]], !dbg [[DBG21]] @@ -27,15 +27,15 @@ define void @foo(ptr %h) !dbg !4 { ; CHECK-NEXT: call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32> <i32 3, i32 3, i32 3, i32 3>, <4 x ptr> [[TMP3]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>), !dbg [[DBG22]] ; CHECK-NEXT: [[TMP4]] = add nuw nsw <4 x i64> [[VEC_PHI]], <i64 1, i64 1, i64 1, i64 1>, !dbg [[DBG24:![0-9]+]] ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq <4 x i64> [[TMP4]], <i64 5, i64 5, i64 5, i64 5>, !dbg [[DBG25:![0-9]+]] -; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x i1> [[TMP5]], i32 0 -; CHECK-NEXT: br i1 [[TMP6]], label [[FOR_COND_CLEANUP32]], label [[FOR_COND5_PREHEADER1]] +; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x i1> [[TMP5]], i32 0, !dbg [[DBG26:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP6]], label [[FOR_COND_CLEANUP32]], label [[FOR_COND5_PREHEADER1]], !dbg [[DBG26]] ; CHECK: for.cond.cleanup32: -; CHECK-NEXT: [[TMP7:%.*]] = add nuw nsw <4 x i64> [[VEC_IND]], <i64 1, i64 1, i64 1, i64 1>, !dbg [[DBG26:![0-9]+]] -; CHECK-NEXT: [[TMP8:%.*]] = icmp eq <4 x i64> [[TMP7]], <i64 23, i64 23, i64 23, i64 23>, !dbg [[DBG27:![0-9]+]] +; CHECK-NEXT: [[TMP7:%.*]] = add nuw nsw <4 x i64> [[VEC_IND]], <i64 1, i64 1, i64 1, i64 1>, !dbg [[DBG27:![0-9]+]] +; CHECK-NEXT: [[TMP8:%.*]] = icmp eq <4 x i64> [[TMP7]], <i64 23, i64 23, i64 23, i64 23>, !dbg [[DBG28:![0-9]+]] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 ; CHECK-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], <i64 4, i64 4, i64 4, i64 4> ; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], 20 -; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP28:![0-9]+]] +; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP29:![0-9]+]] ; CHECK: middle.block: ; CHECK-NEXT: br i1 false, label [[EXIT:%.*]], label [[SCALAR_PH]], !dbg [[DBG21]] ; CHECK: scalar.ph: @@ -43,8 +43,8 @@ define void @foo(ptr %h) !dbg !4 { ; CHECK-NEXT: br label [[FOR_COND1_PREHEADER:%.*]], !dbg [[DBG21]] ; CHECK: for.cond1.preheader: ; CHECK-NEXT: [[I_023:%.*]] = phi i64 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INC13:%.*]], [[FOR_COND_CLEANUP3:%.*]] ] -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 [[I_023]], metadata [[META11]], metadata !DIExpression()), !dbg [[DBG20]] -; CHECK-NEXT: br label [[FOR_COND5_PREHEADER:%.*]], !dbg [[DBG32:![0-9]+]] +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 [[I_023]], metadata [[META11]], metadata !DIExpression()), !dbg [[DBG20]] +; CHECK-NEXT: br label [[FOR_COND5_PREHEADER:%.*]], !dbg [[DBG26]] ; CHECK: for.cond5.preheader: ; CHECK-NEXT: [[L_022:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER]] ], [ [[INC10:%.*]], [[FOR_COND5_PREHEADER]] ] ; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i32, ptr [[H]], i64 [[L_022]] @@ -57,11 +57,11 @@ define void @foo(ptr %h) !dbg !4 { ; CHECK-NEXT: store i32 3, ptr [[ARRAYIDX_3]], align 4, !dbg [[DBG22]] ; CHECK-NEXT: [[INC10]] = add nuw nsw i64 [[L_022]], 1, !dbg [[DBG24]] ; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INC10]], 5, !dbg [[DBG25]] -; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP3]], label [[FOR_COND5_PREHEADER]], !dbg [[DBG32]] +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP3]], label [[FOR_COND5_PREHEADER]], !dbg [[DBG26]] ; CHECK: for.cond.cleanup3: -; CHECK-NEXT: [[INC13]] = add nuw nsw i64 [[I_023]], 1, !dbg [[DBG26]] -; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 [[INC13]], metadata [[META11]], metadata !DIExpression()), !dbg [[DBG20]] -; CHECK-NEXT: [[EXITCOND24_NOT:%.*]] = icmp eq i64 [[INC13]], 23, !dbg [[DBG27]] +; CHECK-NEXT: [[INC13]] = add nuw nsw i64 [[I_023]], 1, !dbg [[DBG27]] +; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i64 [[INC13]], metadata [[META11]], metadata !DIExpression()), !dbg [[DBG20]] +; CHECK-NEXT: [[EXITCOND24_NOT:%.*]] = icmp eq i64 [[INC13]], 23, !dbg [[DBG28]] ; CHECK-NEXT: br i1 [[EXITCOND24_NOT]], label [[EXIT]], label [[FOR_COND1_PREHEADER]], !dbg [[DBG21]], !llvm.loop [[LOOP34:![0-9]+]] ; CHECK: exit: ; CHECK-NEXT: ret void, !dbg [[DBG35:![0-9]+]] @@ -163,14 +163,14 @@ declare void @llvm.dbg.value(metadata, metadata, metadata) ; CHECK: [[META23]] = distinct !DILexicalBlock(scope: [[META18]], file: [[META1]], line: 12, column: 7) ; CHECK: [[DBG24]] = !DILocation(line: 11, column: 32, scope: [[META19]]) ; CHECK: [[DBG25]] = !DILocation(line: 11, column: 26, scope: [[META19]]) -; CHECK: [[DBG26]] = !DILocation(line: 10, column: 30, scope: [[META16]]) -; CHECK: [[DBG27]] = !DILocation(line: 10, column: 24, scope: [[META16]]) -; CHECK: [[LOOP28]] = distinct !{[[LOOP28]], [[DBG21]], [[META29:![0-9]+]], [[META30:![0-9]+]], [[META31:![0-9]+]]} -; CHECK: [[META29]] = !DILocation(line: 13, column: 13, scope: [[META12]]) -; CHECK: [[META30]] = !{!"llvm.loop.isvectorized", i32 1} -; CHECK: [[META31]] = !{!"llvm.loop.unroll.runtime.disable"} -; CHECK: [[DBG32]] = !DILocation(line: 11, column: 5, scope: [[META15]]) +; CHECK: [[DBG26]] = !DILocation(line: 11, column: 5, scope: [[META15]]) +; CHECK: [[DBG27]] = !DILocation(line: 10, column: 30, scope: [[META16]]) +; CHECK: [[DBG28]] = !DILocation(line: 10, column: 24, scope: [[META16]]) +; CHECK: [[LOOP29]] = distinct !{[[LOOP29]], [[DBG21]], [[META30:![0-9]+]], [[META31:![0-9]+]], [[META32:![0-9]+]]} +; CHECK: [[META30]] = !DILocation(line: 13, column: 13, scope: [[META12]]) +; CHECK: [[META31]] = !{!"llvm.loop.isvectorized", i32 1} +; CHECK: [[META32]] = !{!"llvm.loop.unroll.runtime.disable"} ; CHECK: [[DBG33]] = !DILocation(line: 13, column: 2, scope: [[META23]]) -; CHECK: [[LOOP34]] = distinct !{[[LOOP34]], [[DBG21]], [[META29]], [[META30]]} +; CHECK: [[LOOP34]] = distinct !{[[LOOP34]], [[DBG21]], [[META30]], [[META31]]} ; CHECK: [[DBG35]] = !DILocation(line: 14, column: 1, scope: [[DBG4]]) ;. diff --git a/llvm/test/Transforms/LoopVectorize/first-order-recurrence.ll b/llvm/test/Transforms/LoopVectorize/first-order-recurrence.ll index b451d4b4e5462d77a276be6232aba0a0672ec5b5..0a37e5ea0ca007d16b27e80da2a7e039197d756c 100644 --- a/llvm/test/Transforms/LoopVectorize/first-order-recurrence.ll +++ b/llvm/test/Transforms/LoopVectorize/first-order-recurrence.ll @@ -1537,92 +1537,85 @@ define i32 @PR33613(ptr %b, double %j, i32 %d) { ; UNROLL-NO-IC-NEXT: br label [[VECTOR_BODY:%.*]] ; UNROLL-NO-IC: vector.body: ; UNROLL-NO-IC-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; UNROLL-NO-IC-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP48:%.*]], [[VECTOR_BODY]] ] -; UNROLL-NO-IC-NEXT: [[VEC_PHI9:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP49:%.*]], [[VECTOR_BODY]] ] -; UNROLL-NO-IC-NEXT: [[VECTOR_RECUR:%.*]] = phi <4 x double> [ [[VECTOR_RECUR_INIT]], [[VECTOR_PH]] ], [ [[TMP39:%.*]], [[VECTOR_BODY]] ] -; UNROLL-NO-IC-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0 -; UNROLL-NO-IC-NEXT: [[TMP1:%.*]] = mul i64 [[TMP0]], 200 -; UNROLL-NO-IC-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP1]] -; UNROLL-NO-IC-NEXT: [[TMP2:%.*]] = add i64 [[INDEX]], 1 -; UNROLL-NO-IC-NEXT: [[TMP3:%.*]] = mul i64 [[TMP2]], 200 -; UNROLL-NO-IC-NEXT: [[NEXT_GEP2:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP3]] -; UNROLL-NO-IC-NEXT: [[TMP4:%.*]] = add i64 [[INDEX]], 2 -; UNROLL-NO-IC-NEXT: [[TMP5:%.*]] = mul i64 [[TMP4]], 200 -; UNROLL-NO-IC-NEXT: [[NEXT_GEP3:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP5]] -; UNROLL-NO-IC-NEXT: [[TMP6:%.*]] = add i64 [[INDEX]], 3 -; UNROLL-NO-IC-NEXT: [[TMP7:%.*]] = mul i64 [[TMP6]], 200 -; UNROLL-NO-IC-NEXT: [[NEXT_GEP4:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP7]] -; UNROLL-NO-IC-NEXT: [[TMP8:%.*]] = add i64 [[INDEX]], 4 -; UNROLL-NO-IC-NEXT: [[TMP9:%.*]] = mul i64 [[TMP8]], 200 -; UNROLL-NO-IC-NEXT: [[NEXT_GEP5:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP9]] -; UNROLL-NO-IC-NEXT: [[TMP10:%.*]] = add i64 [[INDEX]], 5 -; UNROLL-NO-IC-NEXT: [[TMP11:%.*]] = mul i64 [[TMP10]], 200 -; UNROLL-NO-IC-NEXT: [[NEXT_GEP6:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP11]] -; UNROLL-NO-IC-NEXT: [[TMP12:%.*]] = add i64 [[INDEX]], 6 -; UNROLL-NO-IC-NEXT: [[TMP13:%.*]] = mul i64 [[TMP12]], 200 -; UNROLL-NO-IC-NEXT: [[NEXT_GEP7:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP13]] -; UNROLL-NO-IC-NEXT: [[TMP14:%.*]] = add i64 [[INDEX]], 7 -; UNROLL-NO-IC-NEXT: [[TMP15:%.*]] = mul i64 [[TMP14]], 200 -; UNROLL-NO-IC-NEXT: [[NEXT_GEP8:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP15]] -; UNROLL-NO-IC-NEXT: [[TMP16:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP]], i64 [[IDXPROM]] -; UNROLL-NO-IC-NEXT: [[TMP17:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP2]], i64 [[IDXPROM]] -; UNROLL-NO-IC-NEXT: [[TMP18:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP3]], i64 [[IDXPROM]] -; UNROLL-NO-IC-NEXT: [[TMP19:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP4]], i64 [[IDXPROM]] -; UNROLL-NO-IC-NEXT: [[TMP20:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP5]], i64 [[IDXPROM]] -; UNROLL-NO-IC-NEXT: [[TMP21:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP6]], i64 [[IDXPROM]] -; UNROLL-NO-IC-NEXT: [[TMP22:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP7]], i64 [[IDXPROM]] -; UNROLL-NO-IC-NEXT: [[TMP23:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP8]], i64 [[IDXPROM]] -; UNROLL-NO-IC-NEXT: [[TMP24:%.*]] = load double, ptr [[TMP16]], align 8 -; UNROLL-NO-IC-NEXT: [[TMP25:%.*]] = load double, ptr [[TMP17]], align 8 -; UNROLL-NO-IC-NEXT: [[TMP26:%.*]] = load double, ptr [[TMP18]], align 8 -; UNROLL-NO-IC-NEXT: [[TMP27:%.*]] = load double, ptr [[TMP19]], align 8 +; UNROLL-NO-IC-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP40:%.*]], [[VECTOR_BODY]] ] +; UNROLL-NO-IC-NEXT: [[VEC_PHI2:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP41:%.*]], [[VECTOR_BODY]] ] +; UNROLL-NO-IC-NEXT: [[VECTOR_RECUR:%.*]] = phi <4 x double> [ [[VECTOR_RECUR_INIT]], [[VECTOR_PH]] ], [ [[TMP31:%.*]], [[VECTOR_BODY]] ] +; UNROLL-NO-IC-NEXT: [[OFFSET_IDX:%.*]] = mul i64 [[INDEX]], 200 +; UNROLL-NO-IC-NEXT: [[TMP0:%.*]] = add i64 [[OFFSET_IDX]], 0 +; UNROLL-NO-IC-NEXT: [[TMP1:%.*]] = add i64 [[OFFSET_IDX]], 200 +; UNROLL-NO-IC-NEXT: [[TMP2:%.*]] = add i64 [[OFFSET_IDX]], 400 +; UNROLL-NO-IC-NEXT: [[TMP3:%.*]] = add i64 [[OFFSET_IDX]], 600 +; UNROLL-NO-IC-NEXT: [[TMP4:%.*]] = add i64 [[OFFSET_IDX]], 800 +; UNROLL-NO-IC-NEXT: [[TMP5:%.*]] = add i64 [[OFFSET_IDX]], 1000 +; UNROLL-NO-IC-NEXT: [[TMP6:%.*]] = add i64 [[OFFSET_IDX]], 1200 +; UNROLL-NO-IC-NEXT: [[TMP7:%.*]] = add i64 [[OFFSET_IDX]], 1400 +; UNROLL-NO-IC-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP0]] +; UNROLL-NO-IC-NEXT: [[NEXT_GEP3:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP1]] +; UNROLL-NO-IC-NEXT: [[NEXT_GEP4:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP2]] +; UNROLL-NO-IC-NEXT: [[NEXT_GEP5:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP3]] +; UNROLL-NO-IC-NEXT: [[NEXT_GEP6:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP4]] +; UNROLL-NO-IC-NEXT: [[NEXT_GEP7:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP5]] +; UNROLL-NO-IC-NEXT: [[NEXT_GEP8:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP6]] +; UNROLL-NO-IC-NEXT: [[NEXT_GEP9:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP7]] +; UNROLL-NO-IC-NEXT: [[TMP8:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP]], i64 [[IDXPROM]] +; UNROLL-NO-IC-NEXT: [[TMP9:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP3]], i64 [[IDXPROM]] +; UNROLL-NO-IC-NEXT: [[TMP10:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP4]], i64 [[IDXPROM]] +; UNROLL-NO-IC-NEXT: [[TMP11:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP5]], i64 [[IDXPROM]] +; UNROLL-NO-IC-NEXT: [[TMP12:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP6]], i64 [[IDXPROM]] +; UNROLL-NO-IC-NEXT: [[TMP13:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP7]], i64 [[IDXPROM]] +; UNROLL-NO-IC-NEXT: [[TMP14:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP8]], i64 [[IDXPROM]] +; UNROLL-NO-IC-NEXT: [[TMP15:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP9]], i64 [[IDXPROM]] +; UNROLL-NO-IC-NEXT: [[TMP16:%.*]] = load double, ptr [[TMP8]], align 8 +; UNROLL-NO-IC-NEXT: [[TMP17:%.*]] = load double, ptr [[TMP9]], align 8 +; UNROLL-NO-IC-NEXT: [[TMP18:%.*]] = load double, ptr [[TMP10]], align 8 +; UNROLL-NO-IC-NEXT: [[TMP19:%.*]] = load double, ptr [[TMP11]], align 8 +; UNROLL-NO-IC-NEXT: [[TMP20:%.*]] = insertelement <4 x double> poison, double [[TMP16]], i32 0 +; UNROLL-NO-IC-NEXT: [[TMP21:%.*]] = insertelement <4 x double> [[TMP20]], double [[TMP17]], i32 1 +; UNROLL-NO-IC-NEXT: [[TMP22:%.*]] = insertelement <4 x double> [[TMP21]], double [[TMP18]], i32 2 +; UNROLL-NO-IC-NEXT: [[TMP23:%.*]] = insertelement <4 x double> [[TMP22]], double [[TMP19]], i32 3 +; UNROLL-NO-IC-NEXT: [[TMP24:%.*]] = load double, ptr [[TMP12]], align 8 +; UNROLL-NO-IC-NEXT: [[TMP25:%.*]] = load double, ptr [[TMP13]], align 8 +; UNROLL-NO-IC-NEXT: [[TMP26:%.*]] = load double, ptr [[TMP14]], align 8 +; UNROLL-NO-IC-NEXT: [[TMP27:%.*]] = load double, ptr [[TMP15]], align 8 ; UNROLL-NO-IC-NEXT: [[TMP28:%.*]] = insertelement <4 x double> poison, double [[TMP24]], i32 0 ; UNROLL-NO-IC-NEXT: [[TMP29:%.*]] = insertelement <4 x double> [[TMP28]], double [[TMP25]], i32 1 ; UNROLL-NO-IC-NEXT: [[TMP30:%.*]] = insertelement <4 x double> [[TMP29]], double [[TMP26]], i32 2 -; UNROLL-NO-IC-NEXT: [[TMP31:%.*]] = insertelement <4 x double> [[TMP30]], double [[TMP27]], i32 3 -; UNROLL-NO-IC-NEXT: [[TMP32:%.*]] = load double, ptr [[TMP20]], align 8 -; UNROLL-NO-IC-NEXT: [[TMP33:%.*]] = load double, ptr [[TMP21]], align 8 -; UNROLL-NO-IC-NEXT: [[TMP34:%.*]] = load double, ptr [[TMP22]], align 8 -; UNROLL-NO-IC-NEXT: [[TMP35:%.*]] = load double, ptr [[TMP23]], align 8 -; UNROLL-NO-IC-NEXT: [[TMP36:%.*]] = insertelement <4 x double> poison, double [[TMP32]], i32 0 -; UNROLL-NO-IC-NEXT: [[TMP37:%.*]] = insertelement <4 x double> [[TMP36]], double [[TMP33]], i32 1 -; UNROLL-NO-IC-NEXT: [[TMP38:%.*]] = insertelement <4 x double> [[TMP37]], double [[TMP34]], i32 2 -; UNROLL-NO-IC-NEXT: [[TMP39]] = insertelement <4 x double> [[TMP38]], double [[TMP35]], i32 3 -; UNROLL-NO-IC-NEXT: [[TMP40:%.*]] = shufflevector <4 x double> [[VECTOR_RECUR]], <4 x double> [[TMP31]], <4 x i32> <i32 3, i32 4, i32 5, i32 6> -; UNROLL-NO-IC-NEXT: [[TMP41:%.*]] = shufflevector <4 x double> [[TMP31]], <4 x double> [[TMP39]], <4 x i32> <i32 3, i32 4, i32 5, i32 6> -; UNROLL-NO-IC-NEXT: [[TMP42:%.*]] = fmul <4 x double> [[TMP40]], [[TMP31]] -; UNROLL-NO-IC-NEXT: [[TMP43:%.*]] = fmul <4 x double> [[TMP41]], [[TMP39]] -; UNROLL-NO-IC-NEXT: [[TMP44:%.*]] = fcmp une <4 x double> [[TMP42]], zeroinitializer -; UNROLL-NO-IC-NEXT: [[TMP45:%.*]] = fcmp une <4 x double> [[TMP43]], zeroinitializer -; UNROLL-NO-IC-NEXT: [[TMP46:%.*]] = zext <4 x i1> [[TMP44]] to <4 x i32> -; UNROLL-NO-IC-NEXT: [[TMP47:%.*]] = zext <4 x i1> [[TMP45]] to <4 x i32> -; UNROLL-NO-IC-NEXT: [[TMP48]] = add <4 x i32> [[VEC_PHI]], [[TMP46]] -; UNROLL-NO-IC-NEXT: [[TMP49]] = add <4 x i32> [[VEC_PHI9]], [[TMP47]] +; UNROLL-NO-IC-NEXT: [[TMP31]] = insertelement <4 x double> [[TMP30]], double [[TMP27]], i32 3 +; UNROLL-NO-IC-NEXT: [[TMP32:%.*]] = shufflevector <4 x double> [[VECTOR_RECUR]], <4 x double> [[TMP23]], <4 x i32> <i32 3, i32 4, i32 5, i32 6> +; UNROLL-NO-IC-NEXT: [[TMP33:%.*]] = shufflevector <4 x double> [[TMP23]], <4 x double> [[TMP31]], <4 x i32> <i32 3, i32 4, i32 5, i32 6> +; UNROLL-NO-IC-NEXT: [[TMP34:%.*]] = fmul <4 x double> [[TMP32]], [[TMP23]] +; UNROLL-NO-IC-NEXT: [[TMP35:%.*]] = fmul <4 x double> [[TMP33]], [[TMP31]] +; UNROLL-NO-IC-NEXT: [[TMP36:%.*]] = fcmp une <4 x double> [[TMP34]], zeroinitializer +; UNROLL-NO-IC-NEXT: [[TMP37:%.*]] = fcmp une <4 x double> [[TMP35]], zeroinitializer +; UNROLL-NO-IC-NEXT: [[TMP38:%.*]] = zext <4 x i1> [[TMP36]] to <4 x i32> +; UNROLL-NO-IC-NEXT: [[TMP39:%.*]] = zext <4 x i1> [[TMP37]] to <4 x i32> +; UNROLL-NO-IC-NEXT: [[TMP40]] = add <4 x i32> [[VEC_PHI]], [[TMP38]] +; UNROLL-NO-IC-NEXT: [[TMP41]] = add <4 x i32> [[VEC_PHI2]], [[TMP39]] ; UNROLL-NO-IC-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 8 -; UNROLL-NO-IC-NEXT: [[TMP50:%.*]] = icmp eq i64 [[INDEX_NEXT]], 10240 -; UNROLL-NO-IC-NEXT: br i1 [[TMP50]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]] +; UNROLL-NO-IC-NEXT: [[TMP42:%.*]] = icmp eq i64 [[INDEX_NEXT]], 10240 +; UNROLL-NO-IC-NEXT: br i1 [[TMP42]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]] ; UNROLL-NO-IC: middle.block: -; UNROLL-NO-IC-NEXT: [[BIN_RDX:%.*]] = add <4 x i32> [[TMP49]], [[TMP48]] -; UNROLL-NO-IC-NEXT: [[TMP51:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[BIN_RDX]]) -; UNROLL-NO-IC-NEXT: [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x double> [[TMP39]], i32 3 +; UNROLL-NO-IC-NEXT: [[BIN_RDX:%.*]] = add <4 x i32> [[TMP41]], [[TMP40]] +; UNROLL-NO-IC-NEXT: [[TMP43:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[BIN_RDX]]) +; UNROLL-NO-IC-NEXT: [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x double> [[TMP31]], i32 3 ; UNROLL-NO-IC-NEXT: br i1 true, label [[FOR_COND_CLEANUP:%.*]], label [[SCALAR_PH]] ; UNROLL-NO-IC: scalar.ph: ; UNROLL-NO-IC-NEXT: [[SCALAR_RECUR_INIT:%.*]] = phi double [ [[J]], [[ENTRY:%.*]] ], [ [[VECTOR_RECUR_EXTRACT]], [[MIDDLE_BLOCK]] ] ; UNROLL-NO-IC-NEXT: [[BC_RESUME_VAL:%.*]] = phi ptr [ [[IND_END]], [[MIDDLE_BLOCK]] ], [ [[B]], [[ENTRY]] ] ; UNROLL-NO-IC-NEXT: [[BC_RESUME_VAL1:%.*]] = phi i32 [ 10240, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY]] ] -; UNROLL-NO-IC-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[TMP51]], [[MIDDLE_BLOCK]] ] +; UNROLL-NO-IC-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[TMP43]], [[MIDDLE_BLOCK]] ] ; UNROLL-NO-IC-NEXT: br label [[FOR_BODY:%.*]] ; UNROLL-NO-IC: for.cond.cleanup: -; UNROLL-NO-IC-NEXT: [[A_1_LCSSA:%.*]] = phi i32 [ [[A_1:%.*]], [[FOR_BODY]] ], [ [[TMP51]], [[MIDDLE_BLOCK]] ] +; UNROLL-NO-IC-NEXT: [[A_1_LCSSA:%.*]] = phi i32 [ [[A_1:%.*]], [[FOR_BODY]] ], [ [[TMP43]], [[MIDDLE_BLOCK]] ] ; UNROLL-NO-IC-NEXT: ret i32 [[A_1_LCSSA]] ; UNROLL-NO-IC: for.body: ; UNROLL-NO-IC-NEXT: [[B_ADDR_012:%.*]] = phi ptr [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[ADD_PTR:%.*]], [[FOR_BODY]] ] ; UNROLL-NO-IC-NEXT: [[I_011:%.*]] = phi i32 [ [[BC_RESUME_VAL1]], [[SCALAR_PH]] ], [ [[INC1:%.*]], [[FOR_BODY]] ] ; UNROLL-NO-IC-NEXT: [[A_010:%.*]] = phi i32 [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ], [ [[A_1]], [[FOR_BODY]] ] -; UNROLL-NO-IC-NEXT: [[SCALAR_RECUR:%.*]] = phi double [ [[SCALAR_RECUR_INIT]], [[SCALAR_PH]] ], [ [[TMP52:%.*]], [[FOR_BODY]] ] +; UNROLL-NO-IC-NEXT: [[SCALAR_RECUR:%.*]] = phi double [ [[SCALAR_RECUR_INIT]], [[SCALAR_PH]] ], [ [[TMP44:%.*]], [[FOR_BODY]] ] ; UNROLL-NO-IC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[B_ADDR_012]], i64 [[IDXPROM]] -; UNROLL-NO-IC-NEXT: [[TMP52]] = load double, ptr [[ARRAYIDX]], align 8 -; UNROLL-NO-IC-NEXT: [[MUL:%.*]] = fmul double [[SCALAR_RECUR]], [[TMP52]] +; UNROLL-NO-IC-NEXT: [[TMP44]] = load double, ptr [[ARRAYIDX]], align 8 +; UNROLL-NO-IC-NEXT: [[MUL:%.*]] = fmul double [[SCALAR_RECUR]], [[TMP44]] ; UNROLL-NO-IC-NEXT: [[TOBOOL:%.*]] = fcmp une double [[MUL]], 0.000000e+00 ; UNROLL-NO-IC-NEXT: [[INC:%.*]] = zext i1 [[TOBOOL]] to i32 ; UNROLL-NO-IC-NEXT: [[A_1]] = add nsw i32 [[A_010]], [[INC]] @@ -1640,35 +1633,34 @@ define i32 @PR33613(ptr %b, double %j, i32 %d) { ; UNROLL-NO-VF-NEXT: br label [[VECTOR_BODY:%.*]] ; UNROLL-NO-VF: vector.body: ; UNROLL-NO-VF-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; UNROLL-NO-VF-NEXT: [[VEC_PHI:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[TMP14:%.*]], [[VECTOR_BODY]] ] -; UNROLL-NO-VF-NEXT: [[VEC_PHI3:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[TMP15:%.*]], [[VECTOR_BODY]] ] -; UNROLL-NO-VF-NEXT: [[VECTOR_RECUR:%.*]] = phi double [ [[J:%.*]], [[VECTOR_PH]] ], [ [[TMP7:%.*]], [[VECTOR_BODY]] ] -; UNROLL-NO-VF-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0 -; UNROLL-NO-VF-NEXT: [[TMP1:%.*]] = mul i64 [[TMP0]], 200 -; UNROLL-NO-VF-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP1]] -; UNROLL-NO-VF-NEXT: [[TMP2:%.*]] = add i64 [[INDEX]], 1 -; UNROLL-NO-VF-NEXT: [[TMP3:%.*]] = mul i64 [[TMP2]], 200 -; UNROLL-NO-VF-NEXT: [[NEXT_GEP2:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP3]] -; UNROLL-NO-VF-NEXT: [[TMP4:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP]], i64 [[IDXPROM]] -; UNROLL-NO-VF-NEXT: [[TMP5:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP2]], i64 [[IDXPROM]] -; UNROLL-NO-VF-NEXT: [[TMP6:%.*]] = load double, ptr [[TMP4]], align 8 -; UNROLL-NO-VF-NEXT: [[TMP7]] = load double, ptr [[TMP5]], align 8 -; UNROLL-NO-VF-NEXT: [[TMP8:%.*]] = fmul double [[VECTOR_RECUR]], [[TMP6]] -; UNROLL-NO-VF-NEXT: [[TMP9:%.*]] = fmul double [[TMP6]], [[TMP7]] -; UNROLL-NO-VF-NEXT: [[TMP10:%.*]] = fcmp une double [[TMP8]], 0.000000e+00 -; UNROLL-NO-VF-NEXT: [[TMP11:%.*]] = fcmp une double [[TMP9]], 0.000000e+00 -; UNROLL-NO-VF-NEXT: [[TMP12:%.*]] = zext i1 [[TMP10]] to i32 -; UNROLL-NO-VF-NEXT: [[TMP13:%.*]] = zext i1 [[TMP11]] to i32 -; UNROLL-NO-VF-NEXT: [[TMP14]] = add i32 [[VEC_PHI]], [[TMP12]] -; UNROLL-NO-VF-NEXT: [[TMP15]] = add i32 [[VEC_PHI3]], [[TMP13]] +; UNROLL-NO-VF-NEXT: [[VEC_PHI:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[TMP12:%.*]], [[VECTOR_BODY]] ] +; UNROLL-NO-VF-NEXT: [[VEC_PHI2:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[TMP13:%.*]], [[VECTOR_BODY]] ] +; UNROLL-NO-VF-NEXT: [[VECTOR_RECUR:%.*]] = phi double [ [[J:%.*]], [[VECTOR_PH]] ], [ [[TMP5:%.*]], [[VECTOR_BODY]] ] +; UNROLL-NO-VF-NEXT: [[OFFSET_IDX:%.*]] = mul i64 [[INDEX]], 200 +; UNROLL-NO-VF-NEXT: [[TMP0:%.*]] = add i64 [[OFFSET_IDX]], 0 +; UNROLL-NO-VF-NEXT: [[TMP1:%.*]] = add i64 [[OFFSET_IDX]], 200 +; UNROLL-NO-VF-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP0]] +; UNROLL-NO-VF-NEXT: [[NEXT_GEP3:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP1]] +; UNROLL-NO-VF-NEXT: [[TMP2:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP]], i64 [[IDXPROM]] +; UNROLL-NO-VF-NEXT: [[TMP3:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP3]], i64 [[IDXPROM]] +; UNROLL-NO-VF-NEXT: [[TMP4:%.*]] = load double, ptr [[TMP2]], align 8 +; UNROLL-NO-VF-NEXT: [[TMP5]] = load double, ptr [[TMP3]], align 8 +; UNROLL-NO-VF-NEXT: [[TMP6:%.*]] = fmul double [[VECTOR_RECUR]], [[TMP4]] +; UNROLL-NO-VF-NEXT: [[TMP7:%.*]] = fmul double [[TMP4]], [[TMP5]] +; UNROLL-NO-VF-NEXT: [[TMP8:%.*]] = fcmp une double [[TMP6]], 0.000000e+00 +; UNROLL-NO-VF-NEXT: [[TMP9:%.*]] = fcmp une double [[TMP7]], 0.000000e+00 +; UNROLL-NO-VF-NEXT: [[TMP10:%.*]] = zext i1 [[TMP8]] to i32 +; UNROLL-NO-VF-NEXT: [[TMP11:%.*]] = zext i1 [[TMP9]] to i32 +; UNROLL-NO-VF-NEXT: [[TMP12]] = add i32 [[VEC_PHI]], [[TMP10]] +; UNROLL-NO-VF-NEXT: [[TMP13]] = add i32 [[VEC_PHI2]], [[TMP11]] ; UNROLL-NO-VF-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2 -; UNROLL-NO-VF-NEXT: [[TMP16:%.*]] = icmp eq i64 [[INDEX_NEXT]], 10240 -; UNROLL-NO-VF-NEXT: br i1 [[TMP16]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]] +; UNROLL-NO-VF-NEXT: [[TMP14:%.*]] = icmp eq i64 [[INDEX_NEXT]], 10240 +; UNROLL-NO-VF-NEXT: br i1 [[TMP14]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]] ; UNROLL-NO-VF: middle.block: -; UNROLL-NO-VF-NEXT: [[BIN_RDX:%.*]] = add i32 [[TMP15]], [[TMP14]] +; UNROLL-NO-VF-NEXT: [[BIN_RDX:%.*]] = add i32 [[TMP13]], [[TMP12]] ; UNROLL-NO-VF-NEXT: br i1 true, label [[FOR_COND_CLEANUP:%.*]], label [[SCALAR_PH]] ; UNROLL-NO-VF: scalar.ph: -; UNROLL-NO-VF-NEXT: [[SCALAR_RECUR_INIT:%.*]] = phi double [ [[J]], [[ENTRY:%.*]] ], [ [[TMP7]], [[MIDDLE_BLOCK]] ] +; UNROLL-NO-VF-NEXT: [[SCALAR_RECUR_INIT:%.*]] = phi double [ [[J]], [[ENTRY:%.*]] ], [ [[TMP5]], [[MIDDLE_BLOCK]] ] ; UNROLL-NO-VF-NEXT: [[BC_RESUME_VAL:%.*]] = phi ptr [ [[IND_END]], [[MIDDLE_BLOCK]] ], [ [[B]], [[ENTRY]] ] ; UNROLL-NO-VF-NEXT: [[BC_RESUME_VAL1:%.*]] = phi i32 [ 10240, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY]] ] ; UNROLL-NO-VF-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[BIN_RDX]], [[MIDDLE_BLOCK]] ] @@ -1680,10 +1672,10 @@ define i32 @PR33613(ptr %b, double %j, i32 %d) { ; UNROLL-NO-VF-NEXT: [[B_ADDR_012:%.*]] = phi ptr [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[ADD_PTR:%.*]], [[FOR_BODY]] ] ; UNROLL-NO-VF-NEXT: [[I_011:%.*]] = phi i32 [ [[BC_RESUME_VAL1]], [[SCALAR_PH]] ], [ [[INC1:%.*]], [[FOR_BODY]] ] ; UNROLL-NO-VF-NEXT: [[A_010:%.*]] = phi i32 [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ], [ [[A_1]], [[FOR_BODY]] ] -; UNROLL-NO-VF-NEXT: [[SCALAR_RECUR:%.*]] = phi double [ [[SCALAR_RECUR_INIT]], [[SCALAR_PH]] ], [ [[TMP17:%.*]], [[FOR_BODY]] ] +; UNROLL-NO-VF-NEXT: [[SCALAR_RECUR:%.*]] = phi double [ [[SCALAR_RECUR_INIT]], [[SCALAR_PH]] ], [ [[TMP15:%.*]], [[FOR_BODY]] ] ; UNROLL-NO-VF-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[B_ADDR_012]], i64 [[IDXPROM]] -; UNROLL-NO-VF-NEXT: [[TMP17]] = load double, ptr [[ARRAYIDX]], align 8 -; UNROLL-NO-VF-NEXT: [[MUL:%.*]] = fmul double [[SCALAR_RECUR]], [[TMP17]] +; UNROLL-NO-VF-NEXT: [[TMP15]] = load double, ptr [[ARRAYIDX]], align 8 +; UNROLL-NO-VF-NEXT: [[MUL:%.*]] = fmul double [[SCALAR_RECUR]], [[TMP15]] ; UNROLL-NO-VF-NEXT: [[TOBOOL:%.*]] = fcmp une double [[MUL]], 0.000000e+00 ; UNROLL-NO-VF-NEXT: [[INC:%.*]] = zext i1 [[TOBOOL]] to i32 ; UNROLL-NO-VF-NEXT: [[A_1]] = add nsw i32 [[A_010]], [[INC]] @@ -1702,61 +1694,58 @@ define i32 @PR33613(ptr %b, double %j, i32 %d) { ; SINK-AFTER-NEXT: br label [[VECTOR_BODY:%.*]] ; SINK-AFTER: vector.body: ; SINK-AFTER-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; SINK-AFTER-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP24:%.*]], [[VECTOR_BODY]] ] -; SINK-AFTER-NEXT: [[VECTOR_RECUR:%.*]] = phi <4 x double> [ [[VECTOR_RECUR_INIT]], [[VECTOR_PH]] ], [ [[TMP19:%.*]], [[VECTOR_BODY]] ] -; SINK-AFTER-NEXT: [[TMP0:%.*]] = add i64 [[INDEX]], 0 -; SINK-AFTER-NEXT: [[TMP1:%.*]] = mul i64 [[TMP0]], 200 -; SINK-AFTER-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP1]] -; SINK-AFTER-NEXT: [[TMP2:%.*]] = add i64 [[INDEX]], 1 -; SINK-AFTER-NEXT: [[TMP3:%.*]] = mul i64 [[TMP2]], 200 -; SINK-AFTER-NEXT: [[NEXT_GEP2:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP3]] -; SINK-AFTER-NEXT: [[TMP4:%.*]] = add i64 [[INDEX]], 2 -; SINK-AFTER-NEXT: [[TMP5:%.*]] = mul i64 [[TMP4]], 200 -; SINK-AFTER-NEXT: [[NEXT_GEP3:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP5]] -; SINK-AFTER-NEXT: [[TMP6:%.*]] = add i64 [[INDEX]], 3 -; SINK-AFTER-NEXT: [[TMP7:%.*]] = mul i64 [[TMP6]], 200 -; SINK-AFTER-NEXT: [[NEXT_GEP4:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP7]] -; SINK-AFTER-NEXT: [[TMP8:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP]], i64 [[IDXPROM]] -; SINK-AFTER-NEXT: [[TMP9:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP2]], i64 [[IDXPROM]] -; SINK-AFTER-NEXT: [[TMP10:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP3]], i64 [[IDXPROM]] -; SINK-AFTER-NEXT: [[TMP11:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP4]], i64 [[IDXPROM]] -; SINK-AFTER-NEXT: [[TMP12:%.*]] = load double, ptr [[TMP8]], align 8 -; SINK-AFTER-NEXT: [[TMP13:%.*]] = load double, ptr [[TMP9]], align 8 -; SINK-AFTER-NEXT: [[TMP14:%.*]] = load double, ptr [[TMP10]], align 8 -; SINK-AFTER-NEXT: [[TMP15:%.*]] = load double, ptr [[TMP11]], align 8 -; SINK-AFTER-NEXT: [[TMP16:%.*]] = insertelement <4 x double> poison, double [[TMP12]], i32 0 -; SINK-AFTER-NEXT: [[TMP17:%.*]] = insertelement <4 x double> [[TMP16]], double [[TMP13]], i32 1 -; SINK-AFTER-NEXT: [[TMP18:%.*]] = insertelement <4 x double> [[TMP17]], double [[TMP14]], i32 2 -; SINK-AFTER-NEXT: [[TMP19]] = insertelement <4 x double> [[TMP18]], double [[TMP15]], i32 3 -; SINK-AFTER-NEXT: [[TMP20:%.*]] = shufflevector <4 x double> [[VECTOR_RECUR]], <4 x double> [[TMP19]], <4 x i32> <i32 3, i32 4, i32 5, i32 6> -; SINK-AFTER-NEXT: [[TMP21:%.*]] = fmul <4 x double> [[TMP20]], [[TMP19]] -; SINK-AFTER-NEXT: [[TMP22:%.*]] = fcmp une <4 x double> [[TMP21]], zeroinitializer -; SINK-AFTER-NEXT: [[TMP23:%.*]] = zext <4 x i1> [[TMP22]] to <4 x i32> -; SINK-AFTER-NEXT: [[TMP24]] = add <4 x i32> [[VEC_PHI]], [[TMP23]] +; SINK-AFTER-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP20:%.*]], [[VECTOR_BODY]] ] +; SINK-AFTER-NEXT: [[VECTOR_RECUR:%.*]] = phi <4 x double> [ [[VECTOR_RECUR_INIT]], [[VECTOR_PH]] ], [ [[TMP15:%.*]], [[VECTOR_BODY]] ] +; SINK-AFTER-NEXT: [[OFFSET_IDX:%.*]] = mul i64 [[INDEX]], 200 +; SINK-AFTER-NEXT: [[TMP0:%.*]] = add i64 [[OFFSET_IDX]], 0 +; SINK-AFTER-NEXT: [[TMP1:%.*]] = add i64 [[OFFSET_IDX]], 200 +; SINK-AFTER-NEXT: [[TMP2:%.*]] = add i64 [[OFFSET_IDX]], 400 +; SINK-AFTER-NEXT: [[TMP3:%.*]] = add i64 [[OFFSET_IDX]], 600 +; SINK-AFTER-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP0]] +; SINK-AFTER-NEXT: [[NEXT_GEP2:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP1]] +; SINK-AFTER-NEXT: [[NEXT_GEP3:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP2]] +; SINK-AFTER-NEXT: [[NEXT_GEP4:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP3]] +; SINK-AFTER-NEXT: [[TMP4:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP]], i64 [[IDXPROM]] +; SINK-AFTER-NEXT: [[TMP5:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP2]], i64 [[IDXPROM]] +; SINK-AFTER-NEXT: [[TMP6:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP3]], i64 [[IDXPROM]] +; SINK-AFTER-NEXT: [[TMP7:%.*]] = getelementptr inbounds double, ptr [[NEXT_GEP4]], i64 [[IDXPROM]] +; SINK-AFTER-NEXT: [[TMP8:%.*]] = load double, ptr [[TMP4]], align 8 +; SINK-AFTER-NEXT: [[TMP9:%.*]] = load double, ptr [[TMP5]], align 8 +; SINK-AFTER-NEXT: [[TMP10:%.*]] = load double, ptr [[TMP6]], align 8 +; SINK-AFTER-NEXT: [[TMP11:%.*]] = load double, ptr [[TMP7]], align 8 +; SINK-AFTER-NEXT: [[TMP12:%.*]] = insertelement <4 x double> poison, double [[TMP8]], i32 0 +; SINK-AFTER-NEXT: [[TMP13:%.*]] = insertelement <4 x double> [[TMP12]], double [[TMP9]], i32 1 +; SINK-AFTER-NEXT: [[TMP14:%.*]] = insertelement <4 x double> [[TMP13]], double [[TMP10]], i32 2 +; SINK-AFTER-NEXT: [[TMP15]] = insertelement <4 x double> [[TMP14]], double [[TMP11]], i32 3 +; SINK-AFTER-NEXT: [[TMP16:%.*]] = shufflevector <4 x double> [[VECTOR_RECUR]], <4 x double> [[TMP15]], <4 x i32> <i32 3, i32 4, i32 5, i32 6> +; SINK-AFTER-NEXT: [[TMP17:%.*]] = fmul <4 x double> [[TMP16]], [[TMP15]] +; SINK-AFTER-NEXT: [[TMP18:%.*]] = fcmp une <4 x double> [[TMP17]], zeroinitializer +; SINK-AFTER-NEXT: [[TMP19:%.*]] = zext <4 x i1> [[TMP18]] to <4 x i32> +; SINK-AFTER-NEXT: [[TMP20]] = add <4 x i32> [[VEC_PHI]], [[TMP19]] ; SINK-AFTER-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 -; SINK-AFTER-NEXT: [[TMP25:%.*]] = icmp eq i64 [[INDEX_NEXT]], 10240 -; SINK-AFTER-NEXT: br i1 [[TMP25]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]] +; SINK-AFTER-NEXT: [[TMP21:%.*]] = icmp eq i64 [[INDEX_NEXT]], 10240 +; SINK-AFTER-NEXT: br i1 [[TMP21]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP16:![0-9]+]] ; SINK-AFTER: middle.block: -; SINK-AFTER-NEXT: [[TMP26:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[TMP24]]) -; SINK-AFTER-NEXT: [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x double> [[TMP19]], i32 3 +; SINK-AFTER-NEXT: [[TMP22:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[TMP20]]) +; SINK-AFTER-NEXT: [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x double> [[TMP15]], i32 3 ; SINK-AFTER-NEXT: br i1 true, label [[FOR_COND_CLEANUP:%.*]], label [[SCALAR_PH]] ; SINK-AFTER: scalar.ph: ; SINK-AFTER-NEXT: [[SCALAR_RECUR_INIT:%.*]] = phi double [ [[J]], [[ENTRY:%.*]] ], [ [[VECTOR_RECUR_EXTRACT]], [[MIDDLE_BLOCK]] ] ; SINK-AFTER-NEXT: [[BC_RESUME_VAL:%.*]] = phi ptr [ [[IND_END]], [[MIDDLE_BLOCK]] ], [ [[B]], [[ENTRY]] ] ; SINK-AFTER-NEXT: [[BC_RESUME_VAL1:%.*]] = phi i32 [ 10240, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY]] ] -; SINK-AFTER-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[TMP26]], [[MIDDLE_BLOCK]] ] +; SINK-AFTER-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[TMP22]], [[MIDDLE_BLOCK]] ] ; SINK-AFTER-NEXT: br label [[FOR_BODY:%.*]] ; SINK-AFTER: for.cond.cleanup: -; SINK-AFTER-NEXT: [[A_1_LCSSA:%.*]] = phi i32 [ [[A_1:%.*]], [[FOR_BODY]] ], [ [[TMP26]], [[MIDDLE_BLOCK]] ] +; SINK-AFTER-NEXT: [[A_1_LCSSA:%.*]] = phi i32 [ [[A_1:%.*]], [[FOR_BODY]] ], [ [[TMP22]], [[MIDDLE_BLOCK]] ] ; SINK-AFTER-NEXT: ret i32 [[A_1_LCSSA]] ; SINK-AFTER: for.body: ; SINK-AFTER-NEXT: [[B_ADDR_012:%.*]] = phi ptr [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[ADD_PTR:%.*]], [[FOR_BODY]] ] ; SINK-AFTER-NEXT: [[I_011:%.*]] = phi i32 [ [[BC_RESUME_VAL1]], [[SCALAR_PH]] ], [ [[INC1:%.*]], [[FOR_BODY]] ] ; SINK-AFTER-NEXT: [[A_010:%.*]] = phi i32 [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ], [ [[A_1]], [[FOR_BODY]] ] -; SINK-AFTER-NEXT: [[SCALAR_RECUR:%.*]] = phi double [ [[SCALAR_RECUR_INIT]], [[SCALAR_PH]] ], [ [[TMP27:%.*]], [[FOR_BODY]] ] +; SINK-AFTER-NEXT: [[SCALAR_RECUR:%.*]] = phi double [ [[SCALAR_RECUR_INIT]], [[SCALAR_PH]] ], [ [[TMP23:%.*]], [[FOR_BODY]] ] ; SINK-AFTER-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[B_ADDR_012]], i64 [[IDXPROM]] -; SINK-AFTER-NEXT: [[TMP27]] = load double, ptr [[ARRAYIDX]], align 8 -; SINK-AFTER-NEXT: [[MUL:%.*]] = fmul double [[SCALAR_RECUR]], [[TMP27]] +; SINK-AFTER-NEXT: [[TMP23]] = load double, ptr [[ARRAYIDX]], align 8 +; SINK-AFTER-NEXT: [[MUL:%.*]] = fmul double [[SCALAR_RECUR]], [[TMP23]] ; SINK-AFTER-NEXT: [[TOBOOL:%.*]] = fcmp une double [[MUL]], 0.000000e+00 ; SINK-AFTER-NEXT: [[INC:%.*]] = zext i1 [[TOBOOL]] to i32 ; SINK-AFTER-NEXT: [[A_1]] = add nsw i32 [[A_010]], [[INC]] diff --git a/llvm/test/Transforms/LoopVectorize/pointer-induction-unroll.ll b/llvm/test/Transforms/LoopVectorize/pointer-induction-unroll.ll index 410947704fead13b590efcad158c1dc74f6d5953..31d862a3438ae986be865fd52d9ada28801154dc 100644 --- a/llvm/test/Transforms/LoopVectorize/pointer-induction-unroll.ll +++ b/llvm/test/Transforms/LoopVectorize/pointer-induction-unroll.ll @@ -32,35 +32,36 @@ define void @non_constant_scalar_expansion(i32 %0, ptr %call) { ; STRIDED-NEXT: br label [[VECTOR_BODY:%.*]] ; STRIDED: vector.body: ; STRIDED-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; STRIDED-NEXT: [[TMP4:%.*]] = add i64 [[INDEX]], 0 -; STRIDED-NEXT: [[TMP5:%.*]] = mul i64 [[TMP4]], [[TMP1]] -; STRIDED-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr null, i64 [[TMP5]] -; STRIDED-NEXT: [[TMP6:%.*]] = add i64 [[INDEX]], 1 -; STRIDED-NEXT: [[TMP7:%.*]] = mul i64 [[TMP6]], [[TMP1]] -; STRIDED-NEXT: [[NEXT_GEP2:%.*]] = getelementptr i8, ptr null, i64 [[TMP7]] -; STRIDED-NEXT: [[TMP8:%.*]] = add i64 [[INDEX]], 2 -; STRIDED-NEXT: [[TMP9:%.*]] = mul i64 [[TMP8]], [[TMP1]] -; STRIDED-NEXT: [[NEXT_GEP3:%.*]] = getelementptr i8, ptr null, i64 [[TMP9]] -; STRIDED-NEXT: [[TMP10:%.*]] = add i64 [[INDEX]], 3 -; STRIDED-NEXT: [[TMP11:%.*]] = mul i64 [[TMP10]], [[TMP1]] -; STRIDED-NEXT: [[NEXT_GEP4:%.*]] = getelementptr i8, ptr null, i64 [[TMP11]] ; STRIDED-NEXT: [[DOTCAST:%.*]] = trunc i64 [[INDEX]] to i32 ; STRIDED-NEXT: [[OFFSET_IDX:%.*]] = add i32 30, [[DOTCAST]] -; STRIDED-NEXT: [[TMP12:%.*]] = add i32 [[OFFSET_IDX]], 0 -; STRIDED-NEXT: [[TMP13:%.*]] = add i32 [[OFFSET_IDX]], 1 -; STRIDED-NEXT: [[TMP14:%.*]] = add i32 [[OFFSET_IDX]], 2 -; STRIDED-NEXT: [[TMP15:%.*]] = add i32 [[OFFSET_IDX]], 3 -; STRIDED-NEXT: [[TMP16:%.*]] = getelementptr ptr, ptr [[CALL:%.*]], i32 [[TMP12]] -; STRIDED-NEXT: [[TMP17:%.*]] = getelementptr ptr, ptr [[CALL]], i32 [[TMP13]] -; STRIDED-NEXT: [[TMP18:%.*]] = getelementptr ptr, ptr [[CALL]], i32 [[TMP14]] -; STRIDED-NEXT: [[TMP19:%.*]] = getelementptr ptr, ptr [[CALL]], i32 [[TMP15]] -; STRIDED-NEXT: store ptr [[NEXT_GEP]], ptr [[TMP16]], align 4 -; STRIDED-NEXT: store ptr [[NEXT_GEP2]], ptr [[TMP17]], align 4 -; STRIDED-NEXT: store ptr [[NEXT_GEP3]], ptr [[TMP18]], align 4 -; STRIDED-NEXT: store ptr [[NEXT_GEP4]], ptr [[TMP19]], align 4 +; STRIDED-NEXT: [[TMP3:%.*]] = add i32 [[OFFSET_IDX]], 0 +; STRIDED-NEXT: [[TMP4:%.*]] = add i32 [[OFFSET_IDX]], 1 +; STRIDED-NEXT: [[TMP5:%.*]] = add i32 [[OFFSET_IDX]], 2 +; STRIDED-NEXT: [[TMP6:%.*]] = add i32 [[OFFSET_IDX]], 3 +; STRIDED-NEXT: [[OFFSET_IDX2:%.*]] = mul i64 [[INDEX]], [[TMP1]] +; STRIDED-NEXT: [[TMP7:%.*]] = mul i64 0, [[TMP1]] +; STRIDED-NEXT: [[TMP8:%.*]] = add i64 [[OFFSET_IDX2]], [[TMP7]] +; STRIDED-NEXT: [[TMP9:%.*]] = mul i64 1, [[TMP1]] +; STRIDED-NEXT: [[TMP10:%.*]] = add i64 [[OFFSET_IDX2]], [[TMP9]] +; STRIDED-NEXT: [[TMP11:%.*]] = mul i64 2, [[TMP1]] +; STRIDED-NEXT: [[TMP12:%.*]] = add i64 [[OFFSET_IDX2]], [[TMP11]] +; STRIDED-NEXT: [[TMP13:%.*]] = mul i64 3, [[TMP1]] +; STRIDED-NEXT: [[TMP14:%.*]] = add i64 [[OFFSET_IDX2]], [[TMP13]] +; STRIDED-NEXT: [[TMP15:%.*]] = getelementptr i8, ptr null, i64 [[TMP8]] +; STRIDED-NEXT: [[TMP16:%.*]] = getelementptr i8, ptr null, i64 [[TMP10]] +; STRIDED-NEXT: [[TMP17:%.*]] = getelementptr i8, ptr null, i64 [[TMP12]] +; STRIDED-NEXT: [[TMP18:%.*]] = getelementptr i8, ptr null, i64 [[TMP14]] +; STRIDED-NEXT: [[TMP19:%.*]] = getelementptr ptr, ptr [[CALL:%.*]], i32 [[TMP3]] +; STRIDED-NEXT: [[TMP20:%.*]] = getelementptr ptr, ptr [[CALL]], i32 [[TMP4]] +; STRIDED-NEXT: [[TMP21:%.*]] = getelementptr ptr, ptr [[CALL]], i32 [[TMP5]] +; STRIDED-NEXT: [[TMP22:%.*]] = getelementptr ptr, ptr [[CALL]], i32 [[TMP6]] +; STRIDED-NEXT: store ptr [[TMP15]], ptr [[TMP19]], align 4 +; STRIDED-NEXT: store ptr [[TMP16]], ptr [[TMP20]], align 4 +; STRIDED-NEXT: store ptr [[TMP17]], ptr [[TMP21]], align 4 +; STRIDED-NEXT: store ptr [[TMP18]], ptr [[TMP22]], align 4 ; STRIDED-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 -; STRIDED-NEXT: [[TMP20:%.*]] = icmp eq i64 [[INDEX_NEXT]], 4294967264 -; STRIDED-NEXT: br i1 [[TMP20]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; STRIDED-NEXT: [[TMP23:%.*]] = icmp eq i64 [[INDEX_NEXT]], 4294967264 +; STRIDED-NEXT: br i1 [[TMP23]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] ; STRIDED: middle.block: ; STRIDED-NEXT: br i1 false, label [[FOR_END:%.*]], label [[SCALAR_PH]] ; STRIDED: scalar.ph: @@ -68,13 +69,13 @@ define void @non_constant_scalar_expansion(i32 %0, ptr %call) { ; STRIDED-NEXT: [[BC_RESUME_VAL1:%.*]] = phi ptr [ [[IND_END]], [[MIDDLE_BLOCK]] ], [ null, [[ENTRY]] ] ; STRIDED-NEXT: br label [[FOR_COND:%.*]] ; STRIDED: for.cond: -; STRIDED-NEXT: [[TMP21:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INC:%.*]], [[FOR_COND]] ] +; STRIDED-NEXT: [[TMP24:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[INC:%.*]], [[FOR_COND]] ] ; STRIDED-NEXT: [[P_0:%.*]] = phi ptr [ [[BC_RESUME_VAL1]], [[SCALAR_PH]] ], [ [[ADD_PTR:%.*]], [[FOR_COND]] ] ; STRIDED-NEXT: [[ADD_PTR]] = getelementptr i8, ptr [[P_0]], i32 [[MUL]] -; STRIDED-NEXT: [[ARRAYIDX:%.*]] = getelementptr ptr, ptr [[CALL]], i32 [[TMP21]] +; STRIDED-NEXT: [[ARRAYIDX:%.*]] = getelementptr ptr, ptr [[CALL]], i32 [[TMP24]] ; STRIDED-NEXT: store ptr [[P_0]], ptr [[ARRAYIDX]], align 4 -; STRIDED-NEXT: [[INC]] = add i32 [[TMP21]], 1 -; STRIDED-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[TMP21]], 0 +; STRIDED-NEXT: [[INC]] = add i32 [[TMP24]], 1 +; STRIDED-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[TMP24]], 0 ; STRIDED-NEXT: br i1 [[TOBOOL_NOT]], label [[FOR_END]], label [[FOR_COND]], !llvm.loop [[LOOP3:![0-9]+]] ; STRIDED: for.end: ; STRIDED-NEXT: ret void diff --git a/llvm/test/Transforms/LoopVectorize/pointer-induction.ll b/llvm/test/Transforms/LoopVectorize/pointer-induction.ll index 27f6f7b1cb4e6ac7709e6abd2d84445af149a4ab..35037968160c61354600fdcaf40f3cf9ee8d456b 100644 --- a/llvm/test/Transforms/LoopVectorize/pointer-induction.ll +++ b/llvm/test/Transforms/LoopVectorize/pointer-induction.ll @@ -23,56 +23,53 @@ define void @a(ptr readnone %b) { ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_STORE_CONTINUE10:%.*]] ] -; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[INDEX]], 0 -; CHECK-NEXT: [[TMP3:%.*]] = mul i64 [[TMP2]], -1 -; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr null, i64 [[TMP3]] -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[NEXT_GEP]], i64 -1 -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[TMP4]], i32 0 -; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i8, ptr [[TMP5]], i32 -3 -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[TMP6]], align 1 +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = sub i64 0, [[INDEX]] +; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[OFFSET_IDX]], 0 +; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr null, i64 [[TMP2]] +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[NEXT_GEP]], i64 -1 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i32 0 +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[TMP4]], i32 -3 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[TMP5]], align 1 ; CHECK-NEXT: [[REVERSE:%.*]] = shufflevector <4 x i8> [[WIDE_LOAD]], <4 x i8> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> -; CHECK-NEXT: [[TMP7:%.*]] = icmp eq <4 x i8> [[REVERSE]], zeroinitializer -; CHECK-NEXT: [[TMP8:%.*]] = xor <4 x i1> [[TMP7]], <i1 true, i1 true, i1 true, i1 true> -; CHECK-NEXT: [[TMP9:%.*]] = extractelement <4 x i1> [[TMP8]], i32 0 -; CHECK-NEXT: br i1 [[TMP9]], label [[PRED_STORE_IF:%.*]], label [[PRED_STORE_CONTINUE:%.*]] +; CHECK-NEXT: [[TMP6:%.*]] = icmp eq <4 x i8> [[REVERSE]], zeroinitializer +; CHECK-NEXT: [[TMP7:%.*]] = xor <4 x i1> [[TMP6]], <i1 true, i1 true, i1 true, i1 true> +; CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x i1> [[TMP7]], i32 0 +; CHECK-NEXT: br i1 [[TMP8]], label [[PRED_STORE_IF:%.*]], label [[PRED_STORE_CONTINUE:%.*]] ; CHECK: pred.store.if: -; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i8, ptr [[NEXT_GEP]], i64 -1 -; CHECK-NEXT: store i8 95, ptr [[TMP10]], align 1 +; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i8, ptr [[NEXT_GEP]], i64 -1 +; CHECK-NEXT: store i8 95, ptr [[TMP9]], align 1 ; CHECK-NEXT: br label [[PRED_STORE_CONTINUE]] ; CHECK: pred.store.continue: -; CHECK-NEXT: [[TMP11:%.*]] = extractelement <4 x i1> [[TMP8]], i32 1 -; CHECK-NEXT: br i1 [[TMP11]], label [[PRED_STORE_IF5:%.*]], label [[PRED_STORE_CONTINUE6:%.*]] +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <4 x i1> [[TMP7]], i32 1 +; CHECK-NEXT: br i1 [[TMP10]], label [[PRED_STORE_IF5:%.*]], label [[PRED_STORE_CONTINUE6:%.*]] ; CHECK: pred.store.if5: -; CHECK-NEXT: [[TMP12:%.*]] = add i64 [[INDEX]], 1 -; CHECK-NEXT: [[TMP13:%.*]] = mul i64 [[TMP12]], -1 -; CHECK-NEXT: [[NEXT_GEP2:%.*]] = getelementptr i8, ptr null, i64 [[TMP13]] -; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds i8, ptr [[NEXT_GEP2]], i64 -1 -; CHECK-NEXT: store i8 95, ptr [[TMP14]], align 1 +; CHECK-NEXT: [[TMP11:%.*]] = add i64 [[OFFSET_IDX]], -1 +; CHECK-NEXT: [[NEXT_GEP2:%.*]] = getelementptr i8, ptr null, i64 [[TMP11]] +; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i8, ptr [[NEXT_GEP2]], i64 -1 +; CHECK-NEXT: store i8 95, ptr [[TMP12]], align 1 ; CHECK-NEXT: br label [[PRED_STORE_CONTINUE6]] ; CHECK: pred.store.continue6: -; CHECK-NEXT: [[TMP15:%.*]] = extractelement <4 x i1> [[TMP8]], i32 2 -; CHECK-NEXT: br i1 [[TMP15]], label [[PRED_STORE_IF7:%.*]], label [[PRED_STORE_CONTINUE8:%.*]] +; CHECK-NEXT: [[TMP13:%.*]] = extractelement <4 x i1> [[TMP7]], i32 2 +; CHECK-NEXT: br i1 [[TMP13]], label [[PRED_STORE_IF7:%.*]], label [[PRED_STORE_CONTINUE8:%.*]] ; CHECK: pred.store.if7: -; CHECK-NEXT: [[TMP16:%.*]] = add i64 [[INDEX]], 2 -; CHECK-NEXT: [[TMP17:%.*]] = mul i64 [[TMP16]], -1 -; CHECK-NEXT: [[NEXT_GEP3:%.*]] = getelementptr i8, ptr null, i64 [[TMP17]] -; CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds i8, ptr [[NEXT_GEP3]], i64 -1 -; CHECK-NEXT: store i8 95, ptr [[TMP18]], align 1 +; CHECK-NEXT: [[TMP14:%.*]] = add i64 [[OFFSET_IDX]], -2 +; CHECK-NEXT: [[NEXT_GEP3:%.*]] = getelementptr i8, ptr null, i64 [[TMP14]] +; CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds i8, ptr [[NEXT_GEP3]], i64 -1 +; CHECK-NEXT: store i8 95, ptr [[TMP15]], align 1 ; CHECK-NEXT: br label [[PRED_STORE_CONTINUE8]] ; CHECK: pred.store.continue8: -; CHECK-NEXT: [[TMP19:%.*]] = extractelement <4 x i1> [[TMP8]], i32 3 -; CHECK-NEXT: br i1 [[TMP19]], label [[PRED_STORE_IF9:%.*]], label [[PRED_STORE_CONTINUE10]] +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <4 x i1> [[TMP7]], i32 3 +; CHECK-NEXT: br i1 [[TMP16]], label [[PRED_STORE_IF9:%.*]], label [[PRED_STORE_CONTINUE10]] ; CHECK: pred.store.if9: -; CHECK-NEXT: [[TMP20:%.*]] = add i64 [[INDEX]], 3 -; CHECK-NEXT: [[TMP21:%.*]] = mul i64 [[TMP20]], -1 -; CHECK-NEXT: [[NEXT_GEP4:%.*]] = getelementptr i8, ptr null, i64 [[TMP21]] -; CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds i8, ptr [[NEXT_GEP4]], i64 -1 -; CHECK-NEXT: store i8 95, ptr [[TMP22]], align 1 +; CHECK-NEXT: [[TMP17:%.*]] = add i64 [[OFFSET_IDX]], -3 +; CHECK-NEXT: [[NEXT_GEP4:%.*]] = getelementptr i8, ptr null, i64 [[TMP17]] +; CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds i8, ptr [[NEXT_GEP4]], i64 -1 +; CHECK-NEXT: store i8 95, ptr [[TMP18]], align 1 ; CHECK-NEXT: br label [[PRED_STORE_CONTINUE10]] ; CHECK: pred.store.continue10: ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP23:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP23]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK-NEXT: [[TMP19:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP19]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] ; CHECK: middle.block: ; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP0]], [[N_VEC]] ; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]] @@ -86,8 +83,8 @@ define void @a(ptr readnone %b) { ; CHECK: for.body: ; CHECK-NEXT: [[C_05:%.*]] = phi ptr [ [[INCDEC_PTR:%.*]], [[IF_END:%.*]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] ; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i8, ptr [[C_05]], i64 -1 -; CHECK-NEXT: [[TMP24:%.*]] = load i8, ptr [[INCDEC_PTR]], align 1 -; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i8 [[TMP24]], 0 +; CHECK-NEXT: [[TMP20:%.*]] = load i8, ptr [[INCDEC_PTR]], align 1 +; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i8 [[TMP20]], 0 ; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END]], label [[IF_THEN:%.*]] ; CHECK: if.then: ; CHECK-NEXT: store i8 95, ptr [[INCDEC_PTR]], align 1 @@ -145,22 +142,22 @@ define void @pointer_induction_used_as_vector(ptr noalias %start.1, ptr noalias ; CHECK: vector.body: ; CHECK-NEXT: [[POINTER_PHI:%.*]] = phi ptr [ [[START_2]], [[VECTOR_PH]] ], [ [[PTR_IND:%.*]], [[VECTOR_BODY]] ] ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[INDEX]], 0 -; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 8 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[POINTER_PHI]], <4 x i64> <i64 0, i64 1, i64 2, i64 3> +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = mul i64 [[INDEX]], 8 +; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[OFFSET_IDX]], 0 ; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[START_1]], i64 [[TMP2]] -; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[POINTER_PHI]], <4 x i64> <i64 0, i64 1, i64 2, i64 3> -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, <4 x ptr> [[TMP3]], i64 1 -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr ptr, ptr [[NEXT_GEP]], i32 0 -; CHECK-NEXT: store <4 x ptr> [[TMP4]], ptr [[TMP5]], align 8 -; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x ptr> [[TMP3]], i32 0 -; CHECK-NEXT: [[TMP7:%.*]] = getelementptr i8, ptr [[TMP6]], i32 0 -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[TMP7]], align 1 -; CHECK-NEXT: [[TMP8:%.*]] = add <4 x i8> [[WIDE_LOAD]], <i8 1, i8 1, i8 1, i8 1> -; CHECK-NEXT: store <4 x i8> [[TMP8]], ptr [[TMP7]], align 1 +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, <4 x ptr> [[TMP1]], i64 1 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr ptr, ptr [[NEXT_GEP]], i32 0 +; CHECK-NEXT: store <4 x ptr> [[TMP3]], ptr [[TMP4]], align 8 +; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x ptr> [[TMP1]], i32 0 +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr i8, ptr [[TMP5]], i32 0 +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[TMP6]], align 1 +; CHECK-NEXT: [[TMP7:%.*]] = add <4 x i8> [[WIDE_LOAD]], <i8 1, i8 1, i8 1, i8 1> +; CHECK-NEXT: store <4 x i8> [[TMP7]], ptr [[TMP6]], align 1 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 ; CHECK-NEXT: [[PTR_IND]] = getelementptr i8, ptr [[POINTER_PHI]], i64 4 -; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] +; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP8]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] ; CHECK: middle.block: ; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[N]], [[N_VEC]] ; CHECK-NEXT: br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]] diff --git a/llvm/test/Transforms/LoopVectorize/reduction-inloop-cond.ll b/llvm/test/Transforms/LoopVectorize/reduction-inloop-cond.ll index 3ba57821bc31b0df43e9b6dd627832beb47c8526..873f6364f8281160decb3b17e15548e589dcf929 100644 --- a/llvm/test/Transforms/LoopVectorize/reduction-inloop-cond.ll +++ b/llvm/test/Transforms/LoopVectorize/reduction-inloop-cond.ll @@ -850,8 +850,8 @@ define float @cond_cond(ptr noalias %src1, ptr noalias %src2, ptr noalias %cond, ; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE6]] ; CHECK: pred.load.continue6: ; CHECK-NEXT: [[TMP24:%.*]] = phi <4 x float> [ [[TMP19]], [[PRED_LOAD_CONTINUE4]] ], [ [[TMP23]], [[PRED_LOAD_IF5]] ] -; CHECK-NEXT: [[TMP25:%.*]] = select <4 x i1> [[TMP4]], <4 x float> [[TMP24]], <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00> -; CHECK-NEXT: [[PREDPHI:%.*]] = fadd fast <4 x float> [[VEC_PHI]], [[TMP25]] +; CHECK-NEXT: [[TMP25:%.*]] = fadd fast <4 x float> [[TMP24]], [[VEC_PHI]] +; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> [[TMP4]], <4 x float> [[TMP25]], <4 x float> [[VEC_PHI]] ; CHECK-NEXT: [[TMP26:%.*]] = fcmp fast oeq <4 x float> [[WIDE_LOAD]], <float 7.000000e+00, float 7.000000e+00, float 7.000000e+00, float 7.000000e+00> ; CHECK-NEXT: [[TMP27:%.*]] = extractelement <4 x i1> [[TMP26]], i64 0 ; CHECK-NEXT: br i1 [[TMP27]], label [[PRED_LOAD_IF7:%.*]], label [[PRED_LOAD_CONTINUE8:%.*]] @@ -889,8 +889,8 @@ define float @cond_cond(ptr noalias %src1, ptr noalias %src2, ptr noalias %cond, ; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE14]] ; CHECK: pred.load.continue14: ; CHECK-NEXT: [[TMP46:%.*]] = phi <4 x float> [ [[TMP41]], [[PRED_LOAD_CONTINUE12]] ], [ [[TMP45]], [[PRED_LOAD_IF13]] ] -; CHECK-NEXT: [[TMP47:%.*]] = select <4 x i1> [[TMP26]], <4 x float> [[TMP46]], <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00> -; CHECK-NEXT: [[PREDPHI15]] = fadd fast <4 x float> [[PREDPHI]], [[TMP47]] +; CHECK-NEXT: [[TMP47:%.*]] = fadd fast <4 x float> [[TMP46]], [[PREDPHI]] +; CHECK-NEXT: [[PREDPHI15]] = select <4 x i1> [[TMP26]], <4 x float> [[TMP47]], <4 x float> [[PREDPHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 ; CHECK-NEXT: [[TMP48:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] ; CHECK-NEXT: br i1 [[TMP48]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP14:![0-9]+]] diff --git a/llvm/test/Transforms/LoopVectorize/reduction-inloop-pred.ll b/llvm/test/Transforms/LoopVectorize/reduction-inloop-pred.ll index b1c5ccbead64e5d0617d1e791fbb25aa8a17004b..e79f0983a63785a2a6d298afd2fa481d49018eb5 100644 --- a/llvm/test/Transforms/LoopVectorize/reduction-inloop-pred.ll +++ b/llvm/test/Transforms/LoopVectorize/reduction-inloop-pred.ll @@ -65,7 +65,7 @@ define i32 @reduction_sum_single(ptr noalias nocapture %A) { ; CHECK: scalar.ph: ; CHECK-NEXT: br label [[DOTLR_PH:%.*]] ; CHECK: .lr.ph: -; CHECK-NEXT: br i1 poison, label [[DOT_CRIT_EDGE]], label [[DOTLR_PH]], !llvm.loop [[LOOP2:![0-9]+]] +; CHECK-NEXT: br i1 poison, label [[DOT_CRIT_EDGE]], label [[DOTLR_PH]], !llvm.loop [[LOOP3:![0-9]+]] ; CHECK: ._crit_edge: ; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ poison, [[DOTLR_PH]] ], [ [[TMP26]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]] @@ -1173,7 +1173,7 @@ define i32 @reduction_min(ptr nocapture %A, ptr nocapture %B) { ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_LOAD_CONTINUE6:%.*]] ] ; CHECK-NEXT: [[VEC_IND:%.*]] = phi <4 x i64> [ <i64 0, i64 1, i64 2, i64 3>, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[PRED_LOAD_CONTINUE6]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi i32 [ 1000, [[VECTOR_PH]] ], [ [[TMP26:%.*]], [[PRED_LOAD_CONTINUE6]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi i32 [ 1000, [[VECTOR_PH]] ], [ [[RDX_MINMAX:%.*]], [[PRED_LOAD_CONTINUE6]] ] ; CHECK-NEXT: [[TMP0:%.*]] = icmp ult <4 x i64> [[VEC_IND]], <i64 257, i64 257, i64 257, i64 257> ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x i1> [[TMP0]], i64 0 ; CHECK-NEXT: br i1 [[TMP1]], label [[PRED_LOAD_IF:%.*]], label [[PRED_LOAD_CONTINUE:%.*]] @@ -1216,11 +1216,11 @@ define i32 @reduction_min(ptr nocapture %A, ptr nocapture %B) { ; CHECK-NEXT: [[TMP23:%.*]] = phi <4 x i32> [ [[TMP17]], [[PRED_LOAD_CONTINUE4]] ], [ [[TMP22]], [[PRED_LOAD_IF5]] ] ; CHECK-NEXT: [[TMP24:%.*]] = select <4 x i1> [[TMP0]], <4 x i32> [[TMP23]], <4 x i32> <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647> ; CHECK-NEXT: [[TMP25:%.*]] = call i32 @llvm.vector.reduce.smin.v4i32(<4 x i32> [[TMP24]]) -; CHECK-NEXT: [[TMP26]] = call i32 @llvm.smin.i32(i32 [[TMP25]], i32 [[VEC_PHI]]) +; CHECK-NEXT: [[RDX_MINMAX]] = call i32 @llvm.smin.i32(i32 [[TMP25]], i32 [[VEC_PHI]]) ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 ; CHECK-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], <i64 4, i64 4, i64 4, i64 4> -; CHECK-NEXT: [[TMP27:%.*]] = icmp eq i64 [[INDEX_NEXT]], 260 -; CHECK-NEXT: br i1 [[TMP27]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP24:![0-9]+]] +; CHECK-NEXT: [[TMP26:%.*]] = icmp eq i64 [[INDEX_NEXT]], 260 +; CHECK-NEXT: br i1 [[TMP26]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP24:![0-9]+]] ; CHECK: middle.block: ; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: @@ -1228,7 +1228,7 @@ define i32 @reduction_min(ptr nocapture %A, ptr nocapture %B) { ; CHECK: for.body: ; CHECK-NEXT: br i1 poison, label [[FOR_END]], label [[FOR_BODY]], !llvm.loop [[LOOP25:![0-9]+]] ; CHECK: for.end: -; CHECK-NEXT: [[RESULT_0_LCSSA:%.*]] = phi i32 [ poison, [[FOR_BODY]] ], [ [[TMP26]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: [[RESULT_0_LCSSA:%.*]] = phi i32 [ poison, [[FOR_BODY]] ], [ [[RDX_MINMAX]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret i32 [[RESULT_0_LCSSA]] ; entry: @@ -1260,7 +1260,7 @@ define i32 @reduction_max(ptr nocapture %A, ptr nocapture %B) { ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_LOAD_CONTINUE6:%.*]] ] ; CHECK-NEXT: [[VEC_IND:%.*]] = phi <4 x i64> [ <i64 0, i64 1, i64 2, i64 3>, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[PRED_LOAD_CONTINUE6]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi i32 [ 1000, [[VECTOR_PH]] ], [ [[TMP26:%.*]], [[PRED_LOAD_CONTINUE6]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi i32 [ 1000, [[VECTOR_PH]] ], [ [[RDX_MINMAX:%.*]], [[PRED_LOAD_CONTINUE6]] ] ; CHECK-NEXT: [[TMP0:%.*]] = icmp ult <4 x i64> [[VEC_IND]], <i64 257, i64 257, i64 257, i64 257> ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x i1> [[TMP0]], i64 0 ; CHECK-NEXT: br i1 [[TMP1]], label [[PRED_LOAD_IF:%.*]], label [[PRED_LOAD_CONTINUE:%.*]] @@ -1303,11 +1303,11 @@ define i32 @reduction_max(ptr nocapture %A, ptr nocapture %B) { ; CHECK-NEXT: [[TMP23:%.*]] = phi <4 x i32> [ [[TMP17]], [[PRED_LOAD_CONTINUE4]] ], [ [[TMP22]], [[PRED_LOAD_IF5]] ] ; CHECK-NEXT: [[TMP24:%.*]] = select <4 x i1> [[TMP0]], <4 x i32> [[TMP23]], <4 x i32> zeroinitializer ; CHECK-NEXT: [[TMP25:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[TMP24]]) -; CHECK-NEXT: [[TMP26]] = call i32 @llvm.umax.i32(i32 [[TMP25]], i32 [[VEC_PHI]]) +; CHECK-NEXT: [[RDX_MINMAX]] = call i32 @llvm.umax.i32(i32 [[TMP25]], i32 [[VEC_PHI]]) ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 ; CHECK-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], <i64 4, i64 4, i64 4, i64 4> -; CHECK-NEXT: [[TMP27:%.*]] = icmp eq i64 [[INDEX_NEXT]], 260 -; CHECK-NEXT: br i1 [[TMP27]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP26:![0-9]+]] +; CHECK-NEXT: [[TMP26:%.*]] = icmp eq i64 [[INDEX_NEXT]], 260 +; CHECK-NEXT: br i1 [[TMP26]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP26:![0-9]+]] ; CHECK: middle.block: ; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: @@ -1315,7 +1315,7 @@ define i32 @reduction_max(ptr nocapture %A, ptr nocapture %B) { ; CHECK: for.body: ; CHECK-NEXT: br i1 poison, label [[FOR_END]], label [[FOR_BODY]], !llvm.loop [[LOOP27:![0-9]+]] ; CHECK: for.end: -; CHECK-NEXT: [[RESULT_0_LCSSA:%.*]] = phi i32 [ poison, [[FOR_BODY]] ], [ [[TMP26]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: [[RESULT_0_LCSSA:%.*]] = phi i32 [ poison, [[FOR_BODY]] ], [ [[RDX_MINMAX]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret i32 [[RESULT_0_LCSSA]] ; entry: @@ -1351,25 +1351,25 @@ define float @reduction_conditional(ptr %A, ptr %B, ptr %C, float %S) { ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x float> [ [[TMP0]], [[VECTOR_PH]] ], [ [[PREDPHI3:%.*]], [[VECTOR_BODY]] ] ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds float, ptr [[A:%.*]], i64 [[INDEX]] ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x float>, ptr [[TMP1]], align 4 -; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds float, ptr [[B:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x float>, ptr [[TMP3]], align 4 -; CHECK-NEXT: [[TMP5:%.*]] = fcmp ogt <4 x float> [[WIDE_LOAD]], [[WIDE_LOAD1]] -; CHECK-NEXT: [[TMP6:%.*]] = fcmp ule <4 x float> [[WIDE_LOAD1]], <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00> -; CHECK-NEXT: [[TMP8:%.*]] = and <4 x i1> [[TMP5]], [[TMP6]] -; CHECK-NEXT: [[TMP7:%.*]] = fcmp ogt <4 x float> [[WIDE_LOAD]], <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00> -; CHECK-NEXT: [[TMP9:%.*]] = and <4 x i1> [[TMP8]], [[TMP7]] -; CHECK-NEXT: [[TMP10:%.*]] = xor <4 x i1> [[TMP7]], <i1 true, i1 true, i1 true, i1 true> -; CHECK-NEXT: [[TMP11:%.*]] = and <4 x i1> [[TMP8]], [[TMP10]] -; CHECK-NEXT: [[TMP12:%.*]] = xor <4 x i1> [[TMP5]], <i1 true, i1 true, i1 true, i1 true> -; CHECK-NEXT: [[PREDPHI_V:%.*]] = select <4 x i1> [[TMP9]], <4 x float> [[WIDE_LOAD1]], <4 x float> [[WIDE_LOAD]] -; CHECK-NEXT: [[TMP13:%.*]] = select <4 x i1> [[TMP12]], <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i1> [[TMP11]] -; CHECK-NEXT: [[PREDPHI2:%.*]] = select <4 x i1> [[TMP13]], <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, <4 x float> [[PREDPHI_V]] -; CHECK-NEXT: [[PREDPHI3]] = fadd fast <4 x float> [[VEC_PHI]], [[PREDPHI2]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds float, ptr [[B:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x float>, ptr [[TMP2]], align 4 +; CHECK-NEXT: [[TMP3:%.*]] = fcmp ogt <4 x float> [[WIDE_LOAD]], [[WIDE_LOAD1]] +; CHECK-NEXT: [[TMP4:%.*]] = fcmp ule <4 x float> [[WIDE_LOAD1]], <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00> +; CHECK-NEXT: [[TMP5:%.*]] = and <4 x i1> [[TMP3]], [[TMP4]] +; CHECK-NEXT: [[TMP6:%.*]] = fcmp ogt <4 x float> [[WIDE_LOAD]], <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00> +; CHECK-NEXT: [[TMP7:%.*]] = and <4 x i1> [[TMP5]], [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = xor <4 x i1> [[TMP6]], <i1 true, i1 true, i1 true, i1 true> +; CHECK-NEXT: [[TMP9:%.*]] = and <4 x i1> [[TMP5]], [[TMP8]] +; CHECK-NEXT: [[TMP10:%.*]] = xor <4 x i1> [[TMP3]], <i1 true, i1 true, i1 true, i1 true> +; CHECK-NEXT: [[PREDPHI_V:%.*]] = select <4 x i1> [[TMP7]], <4 x float> [[WIDE_LOAD1]], <4 x float> [[WIDE_LOAD]] +; CHECK-NEXT: [[PREDPHI:%.*]] = fadd fast <4 x float> [[VEC_PHI]], [[PREDPHI_V]] +; CHECK-NEXT: [[TMP11:%.*]] = select <4 x i1> [[TMP10]], <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i1> [[TMP9]] +; CHECK-NEXT: [[PREDPHI3]] = select <4 x i1> [[TMP11]], <4 x float> [[VEC_PHI]], <4 x float> [[PREDPHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP14:%.*]] = icmp eq i64 [[INDEX_NEXT]], 128 -; CHECK-NEXT: br i1 [[TMP14]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP28:![0-9]+]] +; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i64 [[INDEX_NEXT]], 128 +; CHECK-NEXT: br i1 [[TMP12]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP28:![0-9]+]] ; CHECK: middle.block: -; CHECK-NEXT: [[TMP15:%.*]] = call fast float @llvm.vector.reduce.fadd.v4f32(float -0.000000e+00, <4 x float> [[PREDPHI3]]) +; CHECK-NEXT: [[TMP13:%.*]] = call fast float @llvm.vector.reduce.fadd.v4f32(float -0.000000e+00, <4 x float> [[PREDPHI3]]) ; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: ; CHECK-NEXT: br label [[FOR_BODY:%.*]] @@ -1386,7 +1386,7 @@ define float @reduction_conditional(ptr %A, ptr %B, ptr %C, float %S) { ; CHECK: for.inc: ; CHECK-NEXT: br i1 poison, label [[FOR_BODY]], label [[FOR_END]], !llvm.loop [[LOOP29:![0-9]+]] ; CHECK: for.end: -; CHECK-NEXT: [[SUM_1_LCSSA:%.*]] = phi float [ poison, [[FOR_INC]] ], [ [[TMP15]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: [[SUM_1_LCSSA:%.*]] = phi float [ poison, [[FOR_INC]] ], [ [[TMP13]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret float [[SUM_1_LCSSA]] ; entry: diff --git a/llvm/test/Transforms/LoopVectorize/reduction-inloop.ll b/llvm/test/Transforms/LoopVectorize/reduction-inloop.ll index d85241167d0cd858714aa2eabeb319fc7d62d78f..204d021f06571be52dd486e2fb01330809496ed2 100644 --- a/llvm/test/Transforms/LoopVectorize/reduction-inloop.ll +++ b/llvm/test/Transforms/LoopVectorize/reduction-inloop.ll @@ -690,16 +690,16 @@ define float @reduction_conditional(ptr %A, ptr %B, ptr %C, float %S) { ; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x float>, ptr [[TMP2]], align 4 ; CHECK-NEXT: [[TMP3:%.*]] = fcmp ogt <4 x float> [[WIDE_LOAD]], [[WIDE_LOAD1]] ; CHECK-NEXT: [[TMP4:%.*]] = fcmp ule <4 x float> [[WIDE_LOAD1]], <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00> -; CHECK-NEXT: [[TMP6:%.*]] = and <4 x i1> [[TMP3]], [[TMP4]] -; CHECK-NEXT: [[TMP5:%.*]] = fcmp ogt <4 x float> [[WIDE_LOAD]], <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00> -; CHECK-NEXT: [[TMP7:%.*]] = and <4 x i1> [[TMP6]], [[TMP5]] -; CHECK-NEXT: [[TMP8:%.*]] = xor <4 x i1> [[TMP5]], <i1 true, i1 true, i1 true, i1 true> -; CHECK-NEXT: [[TMP9:%.*]] = and <4 x i1> [[TMP6]], [[TMP8]] +; CHECK-NEXT: [[TMP5:%.*]] = and <4 x i1> [[TMP3]], [[TMP4]] +; CHECK-NEXT: [[TMP6:%.*]] = fcmp ogt <4 x float> [[WIDE_LOAD]], <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00> +; CHECK-NEXT: [[TMP7:%.*]] = and <4 x i1> [[TMP5]], [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = xor <4 x i1> [[TMP6]], <i1 true, i1 true, i1 true, i1 true> +; CHECK-NEXT: [[TMP9:%.*]] = and <4 x i1> [[TMP5]], [[TMP8]] ; CHECK-NEXT: [[TMP10:%.*]] = xor <4 x i1> [[TMP3]], <i1 true, i1 true, i1 true, i1 true> ; CHECK-NEXT: [[PREDPHI_V:%.*]] = select <4 x i1> [[TMP7]], <4 x float> [[WIDE_LOAD1]], <4 x float> [[WIDE_LOAD]] +; CHECK-NEXT: [[PREDPHI:%.*]] = fadd fast <4 x float> [[VEC_PHI]], [[PREDPHI_V]] ; CHECK-NEXT: [[TMP11:%.*]] = select <4 x i1> [[TMP10]], <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i1> [[TMP9]] -; CHECK-NEXT: [[PREDPHI2:%.*]] = select <4 x i1> [[TMP11]], <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, <4 x float> [[PREDPHI_V]] -; CHECK-NEXT: [[PREDPHI3]] = fadd fast <4 x float> [[VEC_PHI]], [[PREDPHI2]] +; CHECK-NEXT: [[PREDPHI3]] = select <4 x i1> [[TMP11]], <4 x float> [[VEC_PHI]], <4 x float> [[PREDPHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 ; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i64 [[INDEX_NEXT]], 128 ; CHECK-NEXT: br i1 [[TMP12]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP28:![0-9]+]] @@ -1354,9 +1354,8 @@ define i32 @predicated_or_dominates_reduction(ptr %b) { ; CHECK: pred.load.continue6: ; CHECK-NEXT: [[TMP43:%.*]] = phi <4 x i32> [ [[TMP37]], [[PRED_LOAD_CONTINUE4]] ], [ [[TMP42]], [[PRED_LOAD_IF5]] ] ; CHECK-NEXT: [[TMP44:%.*]] = icmp ne <4 x i32> [[TMP43]], zeroinitializer -; CHECK-NEXT: [[TMP45:%.*]] = select <4 x i1> [[TMP19]], <4 x i1> [[TMP44]], <4 x i1> zeroinitializer ; CHECK-NEXT: [[TMP46:%.*]] = xor <4 x i1> [[TMP19]], <i1 true, i1 true, i1 true, i1 true> -; CHECK-NEXT: [[TMP47:%.*]] = or <4 x i1> [[TMP45]], [[TMP46]] +; CHECK-NEXT: [[TMP47:%.*]] = select <4 x i1> [[TMP46]], <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i1> [[TMP44]] ; CHECK-NEXT: [[TMP48:%.*]] = bitcast <4 x i1> [[TMP47]] to i4 ; CHECK-NEXT: [[TMP49:%.*]] = call i4 @llvm.ctpop.i4(i4 [[TMP48]]), !range [[RNG42:![0-9]+]] ; CHECK-NEXT: [[TMP50:%.*]] = zext nneg i4 [[TMP49]] to i32 diff --git a/llvm/test/Transforms/LoopVectorize/reduction.ll b/llvm/test/Transforms/LoopVectorize/reduction.ll index ba82bac6fad266478e7a790e24f427c88153ea41..a47a38510eeeb3ea8080fcc1173ceb69f626d114 100644 --- a/llvm/test/Transforms/LoopVectorize/reduction.ll +++ b/llvm/test/Transforms/LoopVectorize/reduction.ll @@ -761,16 +761,16 @@ define float @reduction_conditional(ptr %A, ptr %B, ptr %C, float %S) { ; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x float>, ptr [[TMP2]], align 4 ; CHECK-NEXT: [[TMP3:%.*]] = fcmp ogt <4 x float> [[WIDE_LOAD]], [[WIDE_LOAD1]] ; CHECK-NEXT: [[TMP4:%.*]] = fcmp ule <4 x float> [[WIDE_LOAD1]], <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00> -; CHECK-NEXT: [[TMP6:%.*]] = and <4 x i1> [[TMP3]], [[TMP4]] -; CHECK-NEXT: [[TMP5:%.*]] = fcmp ogt <4 x float> [[WIDE_LOAD]], <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00> -; CHECK-NEXT: [[TMP7:%.*]] = and <4 x i1> [[TMP6]], [[TMP5]] -; CHECK-NEXT: [[TMP8:%.*]] = xor <4 x i1> [[TMP5]], <i1 true, i1 true, i1 true, i1 true> -; CHECK-NEXT: [[TMP9:%.*]] = and <4 x i1> [[TMP6]], [[TMP8]] +; CHECK-NEXT: [[TMP5:%.*]] = and <4 x i1> [[TMP3]], [[TMP4]] +; CHECK-NEXT: [[TMP6:%.*]] = fcmp ogt <4 x float> [[WIDE_LOAD]], <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00> +; CHECK-NEXT: [[TMP7:%.*]] = and <4 x i1> [[TMP5]], [[TMP6]] +; CHECK-NEXT: [[TMP8:%.*]] = xor <4 x i1> [[TMP6]], <i1 true, i1 true, i1 true, i1 true> +; CHECK-NEXT: [[TMP9:%.*]] = and <4 x i1> [[TMP5]], [[TMP8]] ; CHECK-NEXT: [[TMP10:%.*]] = xor <4 x i1> [[TMP3]], <i1 true, i1 true, i1 true, i1 true> ; CHECK-NEXT: [[PREDPHI_V:%.*]] = select <4 x i1> [[TMP7]], <4 x float> [[WIDE_LOAD1]], <4 x float> [[WIDE_LOAD]] +; CHECK-NEXT: [[PREDPHI:%.*]] = fadd fast <4 x float> [[VEC_PHI]], [[PREDPHI_V]] ; CHECK-NEXT: [[TMP11:%.*]] = select <4 x i1> [[TMP10]], <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i1> [[TMP9]] -; CHECK-NEXT: [[PREDPHI2:%.*]] = select <4 x i1> [[TMP11]], <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, <4 x float> [[PREDPHI_V]] -; CHECK-NEXT: [[PREDPHI3]] = fadd fast <4 x float> [[VEC_PHI]], [[PREDPHI2]] +; CHECK-NEXT: [[PREDPHI3]] = select <4 x i1> [[TMP11]], <4 x float> [[VEC_PHI]], <4 x float> [[PREDPHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 ; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i64 [[INDEX_NEXT]], 128 ; CHECK-NEXT: br i1 [[TMP12]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP20:![0-9]+]] diff --git a/llvm/test/Transforms/LoopVectorize/tail-folding-vectorization-factor-1.ll b/llvm/test/Transforms/LoopVectorize/tail-folding-vectorization-factor-1.ll index 0c659a550b31e13a29ecc5a4ab3604e985ab806b..92ca77bc841ca1748cb538fef46a0f386e268ab0 100644 --- a/llvm/test/Transforms/LoopVectorize/tail-folding-vectorization-factor-1.ll +++ b/llvm/test/Transforms/LoopVectorize/tail-folding-vectorization-factor-1.ll @@ -92,6 +92,7 @@ define void @VF1-VPWidenCanonicalIVRecipeExe(ptr %ptr1) { ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_STORE_CONTINUE12:%.*]] ] +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = mul i64 [[INDEX]], 8 ; CHECK-NEXT: [[VEC_IV:%.*]] = add i64 [[INDEX]], 0 ; CHECK-NEXT: [[VEC_IV4:%.*]] = add i64 [[INDEX]], 1 ; CHECK-NEXT: [[VEC_IV5:%.*]] = add i64 [[INDEX]], 2 @@ -102,39 +103,35 @@ define void @VF1-VPWidenCanonicalIVRecipeExe(ptr %ptr1) { ; CHECK-NEXT: [[TMP3:%.*]] = icmp ule i64 [[VEC_IV6]], 14 ; CHECK-NEXT: br i1 [[TMP0]], label [[PRED_STORE_IF:%.*]], label [[PRED_STORE_CONTINUE:%.*]] ; CHECK: pred.store.if: -; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[INDEX]], 0 -; CHECK-NEXT: [[TMP5:%.*]] = mul i64 [[TMP4]], 8 -; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[PTR1]], i64 [[TMP5]] +; CHECK-NEXT: [[TMP4:%.*]] = add i64 [[OFFSET_IDX]], 0 +; CHECK-NEXT: [[NEXT_GEP:%.*]] = getelementptr i8, ptr [[PTR1]], i64 [[TMP4]] ; CHECK-NEXT: store double 0.000000e+00, ptr [[NEXT_GEP]], align 8 ; CHECK-NEXT: br label [[PRED_STORE_CONTINUE]] ; CHECK: pred.store.continue: ; CHECK-NEXT: br i1 [[TMP1]], label [[PRED_STORE_IF7:%.*]], label [[PRED_STORE_CONTINUE8:%.*]] ; CHECK: pred.store.if7: -; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[INDEX]], 1 -; CHECK-NEXT: [[TMP7:%.*]] = mul i64 [[TMP6]], 8 -; CHECK-NEXT: [[NEXT_GEP1:%.*]] = getelementptr i8, ptr [[PTR1]], i64 [[TMP7]] +; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[OFFSET_IDX]], 8 +; CHECK-NEXT: [[NEXT_GEP1:%.*]] = getelementptr i8, ptr [[PTR1]], i64 [[TMP5]] ; CHECK-NEXT: store double 0.000000e+00, ptr [[NEXT_GEP1]], align 8 ; CHECK-NEXT: br label [[PRED_STORE_CONTINUE8]] ; CHECK: pred.store.continue8: ; CHECK-NEXT: br i1 [[TMP2]], label [[PRED_STORE_IF9:%.*]], label [[PRED_STORE_CONTINUE10:%.*]] ; CHECK: pred.store.if9: -; CHECK-NEXT: [[TMP8:%.*]] = add i64 [[INDEX]], 2 -; CHECK-NEXT: [[TMP9:%.*]] = mul i64 [[TMP8]], 8 -; CHECK-NEXT: [[NEXT_GEP2:%.*]] = getelementptr i8, ptr [[PTR1]], i64 [[TMP9]] +; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[OFFSET_IDX]], 16 +; CHECK-NEXT: [[NEXT_GEP2:%.*]] = getelementptr i8, ptr [[PTR1]], i64 [[TMP6]] ; CHECK-NEXT: store double 0.000000e+00, ptr [[NEXT_GEP2]], align 8 ; CHECK-NEXT: br label [[PRED_STORE_CONTINUE10]] ; CHECK: pred.store.continue10: ; CHECK-NEXT: br i1 [[TMP3]], label [[PRED_STORE_IF11:%.*]], label [[PRED_STORE_CONTINUE12]] ; CHECK: pred.store.if11: -; CHECK-NEXT: [[TMP10:%.*]] = add i64 [[INDEX]], 3 -; CHECK-NEXT: [[TMP11:%.*]] = mul i64 [[TMP10]], 8 -; CHECK-NEXT: [[NEXT_GEP3:%.*]] = getelementptr i8, ptr [[PTR1]], i64 [[TMP11]] +; CHECK-NEXT: [[TMP7:%.*]] = add i64 [[OFFSET_IDX]], 24 +; CHECK-NEXT: [[NEXT_GEP3:%.*]] = getelementptr i8, ptr [[PTR1]], i64 [[TMP7]] ; CHECK-NEXT: store double 0.000000e+00, ptr [[NEXT_GEP3]], align 8 ; CHECK-NEXT: br label [[PRED_STORE_CONTINUE12]] ; CHECK: pred.store.continue12: ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i64 [[INDEX_NEXT]], 16 -; CHECK-NEXT: br i1 [[TMP12]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] +; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], 16 +; CHECK-NEXT: br i1 [[TMP8]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] ; CHECK: middle.block: ; CHECK-NEXT: br i1 true, label [[FOR_COND_CLEANUP:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: diff --git a/llvm/test/Transforms/LoopVectorize/vplan-printing-before-execute.ll b/llvm/test/Transforms/LoopVectorize/vplan-printing-before-execute.ll index 1dddbfe20a2ed7ebef832be10c58b85e9060334f..ca9dfdc6f6d29d3593985545430957baf5fb0e17 100644 --- a/llvm/test/Transforms/LoopVectorize/vplan-printing-before-execute.ll +++ b/llvm/test/Transforms/LoopVectorize/vplan-printing-before-execute.ll @@ -23,11 +23,12 @@ define void @test_tc_less_than_16(ptr %A, i64 %N) { ; CHECK-NEXT: <x1> vector loop: { ; CHECK-NEXT: vector.body: ; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION ir<0>, vp<[[CAN_IV_NEXT:%.+]]> -; CHECK-NEXT: EMIT ir<%p.src> = WIDEN-POINTER-INDUCTION ir<%A>, 1 -; CHECK-NEXT: vp<[[VPTR:%.]]> = vector-pointer ir<%p.src> +; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1> +; CHECK-NEXT: EMIT vp<[[PADD:%.+]]> = ptradd ir<%A>, vp<[[STEPS]]> +; CHECK-NEXT: vp<[[VPTR:%.]]> = vector-pointer vp<[[PADD]]> ; CHECK-NEXT: WIDEN ir<%l> = load vp<[[VPTR]]> ; CHECK-NEXT: WIDEN ir<%add> = add nsw ir<%l>, ir<10> -; CHECK-NEXT: vp<[[VPTR2:%.+]]> = vector-pointer ir<%p.src> +; CHECK-NEXT: vp<[[VPTR2:%.+]]> = vector-pointer vp<[[PADD]]> ; CHECK-NEXT: WIDEN store vp<[[VPTR2]]>, ir<%add> ; CHECK-NEXT: EMIT vp<[[CAN_IV_NEXT]]> = add nuw vp<[[CAN_IV:%.+]]>, vp<[[VFxUF]]> ; CHECK-NEXT: EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VTC]]> @@ -54,11 +55,12 @@ define void @test_tc_less_than_16(ptr %A, i64 %N) { ; CHECK-NEXT: <x1> vector loop: { ; CHECK-NEXT: vector.body: ; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION ir<0>, vp<[[CAN_IV_NEXT:%.+]]> -; CHECK-NEXT: EMIT ir<%p.src> = WIDEN-POINTER-INDUCTION ir<%A>, 1 -; CHECK-NEXT: vp<[[VPTR:%.]]> = vector-pointer ir<%p.src> +; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1> +; CHECK-NEXT: EMIT vp<[[PADD:%.+]]> = ptradd ir<%A>, vp<[[STEPS]]> +; CHECK-NEXT: vp<[[VPTR:%.]]> = vector-pointer vp<[[PADD]]> ; CHECK-NEXT: WIDEN ir<%l> = load vp<[[VPTR]]> ; CHECK-NEXT: WIDEN ir<%add> = add nsw ir<%l>, ir<10> -; CHECK-NEXT: vp<[[VPTR2:%.+]]> = vector-pointer ir<%p.src> +; CHECK-NEXT: vp<[[VPTR2:%.+]]> = vector-pointer vp<[[PADD]]> ; CHECK-NEXT: WIDEN store vp<[[VPTR2]]>, ir<%add> ; CHECK-NEXT: EMIT vp<[[CAN_IV_NEXT]]> = add nuw vp<[[CAN_IV:%.+]]>, vp<[[VFxUF]]> ; CHECK-NEXT: EMIT branch-on-cond ir<true> diff --git a/llvm/test/Transforms/LoopVectorize/vplan-sink-scalars-and-merge.ll b/llvm/test/Transforms/LoopVectorize/vplan-sink-scalars-and-merge.ll index 9b9c3e704852a11cdb1142b4b901cbe7306ca7d3..89b3a6da16c1ffb8c21541655e52235016d7880f 100644 --- a/llvm/test/Transforms/LoopVectorize/vplan-sink-scalars-and-merge.ll +++ b/llvm/test/Transforms/LoopVectorize/vplan-sink-scalars-and-merge.ll @@ -1113,8 +1113,10 @@ define void @ptr_induction_remove_dead_recipe(ptr %start, ptr %end) { ; CHECK-NEXT: <x1> vector loop: { ; CHECK-NEXT: vector.body: ; CHECK-NEXT: EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION -; CHECK-NEXT: EMIT ir<%ptr.iv> = WIDEN-POINTER-INDUCTION ir<%start>, -1 -; CHECK-NEXT: CLONE ir<%ptr.iv.next> = getelementptr inbounds ir<%ptr.iv>, ir<-1> +; CHECK-NEXT: vp<[[DEV_IV:%.+]]> = DERIVED-IV ir<0> + vp<%3> * ir<-1> +; CHECK-NEXT: vp<[[STEPS:%.+]]> = SCALAR-STEPS vp<[[DEV_IV]]>, ir<-1> +; CHECK-NEXT: EMIT vp<[[PTR_IV:%.+]]> = ptradd ir<%start>, vp<[[STEPS]]> +; CHECK-NEXT: CLONE ir<%ptr.iv.next> = getelementptr inbounds vp<[[PTR_IV]]>, ir<-1> ; CHECK-NEXT: vp<[[VEC_PTR:%.+]]> = vector-pointer (reverse) ir<%ptr.iv.next> ; CHECK-NEXT: WIDEN ir<%l> = load vp<[[VEC_PTR]]> ; CHECK-NEXT: WIDEN ir<%c.1> = icmp eq ir<%l>, ir<0> @@ -1127,7 +1129,7 @@ define void @ptr_induction_remove_dead_recipe(ptr %start, ptr %end) { ; CHECK-NEXT: Successor(s): pred.store.if, pred.store.continue ; CHECK-EMPTY: ; CHECK-NEXT: pred.store.if: -; CHECK-NEXT: REPLICATE ir<%ptr.iv.next> = getelementptr inbounds ir<%ptr.iv>, ir<-1> +; CHECK-NEXT: REPLICATE ir<%ptr.iv.next> = getelementptr inbounds vp<[[PTR_IV]]>, ir<-1> ; CHECK-NEXT: REPLICATE store ir<95>, ir<%ptr.iv.next> ; CHECK-NEXT: Successor(s): pred.store.continue ; CHECK-EMPTY: diff --git a/llvm/test/Transforms/LowerMatrixIntrinsics/multiply-fused-lifetime-ends.ll b/llvm/test/Transforms/LowerMatrixIntrinsics/multiply-fused-lifetime-ends.ll index ef8665b7969097ee7282d51307c1a3e3387e5ad7..bdd0c6f728ae7874b257e8b1ae87ca9ddd2123b2 100644 --- a/llvm/test/Transforms/LowerMatrixIntrinsics/multiply-fused-lifetime-ends.ll +++ b/llvm/test/Transforms/LowerMatrixIntrinsics/multiply-fused-lifetime-ends.ll @@ -6,15 +6,11 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" ; Tests to make sure no loads are introduced after a lifetime.end by multiply ; fusion. -; FIXME: Currently the tests are mis-compiled, with loads being introduced after -; llvm.lifetime.end calls. - define void @lifetime_for_first_arg_before_multiply(ptr noalias %B, ptr noalias %C) { ; CHECK-LABEL: @lifetime_for_first_arg_before_multiply( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A:%.*]] = alloca <4 x double>, align 32 ; CHECK-NEXT: call void @init(ptr [[A]]) -; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[A]]) ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0 ; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 ; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 @@ -77,6 +73,7 @@ define void @lifetime_for_first_arg_before_multiply(ptr noalias %B, ptr noalias ; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8 ; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2 ; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8 +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[A]]) ; CHECK-NEXT: ret void ; entry: @@ -95,7 +92,6 @@ define void @lifetime_for_second_arg_before_multiply(ptr noalias %A, ptr noalias ; CHECK-NEXT: entry: ; CHECK-NEXT: [[B:%.*]] = alloca <4 x double>, align 32 ; CHECK-NEXT: call void @init(ptr [[B]]) -; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[B]]) ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A:%.*]], i64 0 ; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 ; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 @@ -158,6 +154,7 @@ define void @lifetime_for_second_arg_before_multiply(ptr noalias %A, ptr noalias ; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8 ; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2 ; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8 +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[B]]) ; CHECK-NEXT: ret void ; entry: @@ -177,7 +174,6 @@ define void @lifetime_for_first_arg_before_multiply_load_from_offset(ptr noalias ; CHECK-NEXT: [[A:%.*]] = alloca <8 x double>, align 64 ; CHECK-NEXT: call void @init(ptr [[A]]) ; CHECK-NEXT: [[GEP_8:%.*]] = getelementptr i8, ptr [[A]], i64 8 -; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[A]]) ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[GEP_8]], i64 0 ; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 ; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 @@ -240,6 +236,7 @@ define void @lifetime_for_first_arg_before_multiply_load_from_offset(ptr noalias ; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8 ; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2 ; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8 +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[A]]) ; CHECK-NEXT: ret void ; entry: @@ -261,7 +258,6 @@ define void @lifetime_for_first_arg_before_multiply_lifetime_does_not_dominate(p ; CHECK-NEXT: call void @init(ptr [[A]]) ; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] ; CHECK: then: -; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[A]]) ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0 @@ -352,7 +348,6 @@ define void @lifetime_for_second_arg_before_multiply_lifetime_does_not_dominate( ; CHECK-NEXT: call void @init(ptr [[B]]) ; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] ; CHECK: then: -; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[B]]) ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A:%.*]], i64 0 @@ -441,10 +436,9 @@ define void @lifetime_for_ptr_first_arg_before_multiply(ptr noalias %A, ptr noal ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] ; CHECK: then: -; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[A:%.*]]) ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: -; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0 +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A:%.*]], i64 0 ; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 ; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 ; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 @@ -528,15 +522,104 @@ define void @lifetime_for_both_ptr_args_before_multiply(ptr noalias %A, ptr noal ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] ; CHECK: then: -; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[B:%.*]]) -; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[A:%.*]]) ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: -; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0 +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A:%.*]], i64 0 ; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 ; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 ; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B]], i64 0 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B:%.*]], i64 0 +; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8 +; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2 +; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8 +; CHECK-NEXT: [[BLOCK:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x double> poison, double [[TMP2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = fmul contract <1 x double> [[BLOCK]], [[SPLAT_SPLAT]] +; CHECK-NEXT: [[BLOCK5:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <1 x double> poison, double [[TMP4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT6]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK5]], <1 x double> [[SPLAT_SPLAT7]], <1 x double> [[TMP3]]) +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <1 x double> [[TMP5]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP6]], <2 x i32> <i32 2, i32 1> +; CHECK-NEXT: [[BLOCK8:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[BLOCK9:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT10:%.*]] = insertelement <1 x double> poison, double [[TMP8]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT11:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT10]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = fmul contract <1 x double> [[BLOCK9]], [[SPLAT_SPLAT11]] +; CHECK-NEXT: [[BLOCK12:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <1 x double> poison, double [[TMP10]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT13]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP11:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK12]], <1 x double> [[SPLAT_SPLAT14]], <1 x double> [[TMP9]]) +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <1 x double> [[TMP11]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> [[TMP12]], <2 x i32> <i32 0, i32 2> +; CHECK-NEXT: [[BLOCK15:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT16:%.*]] = insertelement <1 x double> poison, double [[TMP14]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT17:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT16]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP15:%.*]] = fmul contract <1 x double> [[BLOCK15]], [[SPLAT_SPLAT17]] +; CHECK-NEXT: [[BLOCK18:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT19:%.*]] = insertelement <1 x double> poison, double [[TMP16]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT20:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT19]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP17:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK18]], <1 x double> [[SPLAT_SPLAT20]], <1 x double> [[TMP15]]) +; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <1 x double> [[TMP17]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP18]], <2 x i32> <i32 2, i32 1> +; CHECK-NEXT: [[BLOCK21:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[BLOCK22:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP20:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT23:%.*]] = insertelement <1 x double> poison, double [[TMP20]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT24:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT23]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP21:%.*]] = fmul contract <1 x double> [[BLOCK22]], [[SPLAT_SPLAT24]] +; CHECK-NEXT: [[BLOCK25:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP22:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT26:%.*]] = insertelement <1 x double> poison, double [[TMP22]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT27:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT26]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP23:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK25]], <1 x double> [[SPLAT_SPLAT27]], <1 x double> [[TMP21]]) +; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <1 x double> [[TMP23]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP25:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP24]], <2 x i32> <i32 0, i32 2> +; CHECK-NEXT: [[TMP26:%.*]] = getelementptr double, ptr [[C1:%.*]], i64 0 +; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8 +; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2 +; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8 +; CHECK-NEXT: ret void +; +entry: + %a = load <4 x double>, ptr %A, align 8 + %b = load <4 x double>, ptr %B, align 8 + br i1 %c.0, label %then, label %exit + +then: + call void @llvm.lifetime.end(i64 -1, ptr %B) + call void @llvm.lifetime.end(i64 -1, ptr %A) + br label %exit + +exit: + %m = call <4 x double> @llvm.matrix.multiply(<4 x double> %a, <4 x double> %b, i32 2, i32 2, i32 2) + store <4 x double> %m, ptr %C, align 8 + ret void +} + +define void @multiple_unrelated_lifetimes(ptr noalias %A, ptr noalias %B, ptr noalias %C, i1 %c.0) { +; CHECK-LABEL: @multiple_unrelated_lifetimes( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ALLOC_1:%.*]] = alloca i32, align 4 +; CHECK-NEXT: [[ALLOC_2:%.*]] = alloca i32, align 4 +; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] +; CHECK: then: +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[ALLOC_1]]) +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[ALLOC_2]]) +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A:%.*]], i64 0 +; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 +; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 +; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B:%.*]], i64 0 ; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8 ; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2 ; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8 @@ -597,13 +680,17 @@ define void @lifetime_for_both_ptr_args_before_multiply(ptr noalias %A, ptr noal ; CHECK-NEXT: ret void ; entry: + %alloc.1 = alloca i32 + %alloc.2 = alloca i32 %a = load <4 x double>, ptr %A, align 8 %b = load <4 x double>, ptr %B, align 8 br i1 %c.0, label %then, label %exit then: call void @llvm.lifetime.end(i64 -1, ptr %B) + call void @llvm.lifetime.end(i64 -1, ptr %alloc.1) call void @llvm.lifetime.end(i64 -1, ptr %A) + call void @llvm.lifetime.end(i64 -1, ptr %alloc.2) br label %exit exit: @@ -618,7 +705,6 @@ define void @lifetime_for_ptr_select_before_multiply(ptr noalias %A, ptr noalias ; CHECK-NEXT: [[P:%.*]] = select i1 [[C_0:%.*]], ptr [[A:%.*]], ptr [[B:%.*]] ; CHECK-NEXT: br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] ; CHECK: then: -; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[P]]) ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[P]], i64 0 @@ -701,6 +787,374 @@ exit: ret void } +define void @lifetimes_for_args_in_different_blocks(ptr noalias %B, ptr noalias %C, i1 %c.0) { +; CHECK-LABEL: @lifetimes_for_args_in_different_blocks( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = alloca <4 x double>, align 32 +; CHECK-NEXT: call void @init(ptr [[A]]) +; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] +; CHECK: then: +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0 +; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 +; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 +; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B:%.*]], i64 0 +; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8 +; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2 +; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8 +; CHECK-NEXT: [[BLOCK:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x double> poison, double [[TMP2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = fmul contract <1 x double> [[BLOCK]], [[SPLAT_SPLAT]] +; CHECK-NEXT: [[BLOCK5:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <1 x double> poison, double [[TMP4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT6]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK5]], <1 x double> [[SPLAT_SPLAT7]], <1 x double> [[TMP3]]) +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <1 x double> [[TMP5]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP6]], <2 x i32> <i32 2, i32 1> +; CHECK-NEXT: [[BLOCK8:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[BLOCK9:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT10:%.*]] = insertelement <1 x double> poison, double [[TMP8]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT11:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT10]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = fmul contract <1 x double> [[BLOCK9]], [[SPLAT_SPLAT11]] +; CHECK-NEXT: [[BLOCK12:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <1 x double> poison, double [[TMP10]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT13]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP11:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK12]], <1 x double> [[SPLAT_SPLAT14]], <1 x double> [[TMP9]]) +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <1 x double> [[TMP11]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> [[TMP12]], <2 x i32> <i32 0, i32 2> +; CHECK-NEXT: [[BLOCK15:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT16:%.*]] = insertelement <1 x double> poison, double [[TMP14]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT17:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT16]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP15:%.*]] = fmul contract <1 x double> [[BLOCK15]], [[SPLAT_SPLAT17]] +; CHECK-NEXT: [[BLOCK18:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT19:%.*]] = insertelement <1 x double> poison, double [[TMP16]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT20:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT19]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP17:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK18]], <1 x double> [[SPLAT_SPLAT20]], <1 x double> [[TMP15]]) +; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <1 x double> [[TMP17]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP18]], <2 x i32> <i32 2, i32 1> +; CHECK-NEXT: [[BLOCK21:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[BLOCK22:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP20:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT23:%.*]] = insertelement <1 x double> poison, double [[TMP20]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT24:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT23]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP21:%.*]] = fmul contract <1 x double> [[BLOCK22]], [[SPLAT_SPLAT24]] +; CHECK-NEXT: [[BLOCK25:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP22:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT26:%.*]] = insertelement <1 x double> poison, double [[TMP22]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT27:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT26]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP23:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK25]], <1 x double> [[SPLAT_SPLAT27]], <1 x double> [[TMP21]]) +; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <1 x double> [[TMP23]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP25:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP24]], <2 x i32> <i32 0, i32 2> +; CHECK-NEXT: [[TMP26:%.*]] = getelementptr double, ptr [[C1:%.*]], i64 0 +; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8 +; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2 +; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8 +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[A]]) +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[B]]) +; CHECK-NEXT: ret void +; +entry: + %A = alloca <4 x double> + call void @init(ptr %A) + br i1 %c.0, label %then, label %exit + +then: + %a = load <4 x double>, ptr %A, align 8 + %b = load <4 x double>, ptr %B, align 8 + %m = call <4 x double> @llvm.matrix.multiply(<4 x double> %a, <4 x double> %b, i32 2, i32 2, i32 2) + store <4 x double> %m, ptr %C, align 8 + br label %exit + +exit: + call void @llvm.lifetime.end(i64 -1, ptr %A) + call void @llvm.lifetime.end(i64 -1, ptr %B) + ret void +} + +define void @lifetimes_for_args_in_different_blocks2(ptr noalias %B, ptr noalias %C, i1 %c.0) { +; CHECK-LABEL: @lifetimes_for_args_in_different_blocks2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = alloca <4 x double>, align 32 +; CHECK-NEXT: call void @init(ptr [[A]]) +; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] +; CHECK: then: +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[A]]) +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 -1, ptr [[B:%.*]]) +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0 +; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 +; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 +; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B]], i64 0 +; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8 +; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2 +; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8 +; CHECK-NEXT: [[BLOCK:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x double> poison, double [[TMP2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = fmul contract <1 x double> [[BLOCK]], [[SPLAT_SPLAT]] +; CHECK-NEXT: [[BLOCK5:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <1 x double> poison, double [[TMP4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT6]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK5]], <1 x double> [[SPLAT_SPLAT7]], <1 x double> [[TMP3]]) +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <1 x double> [[TMP5]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP6]], <2 x i32> <i32 2, i32 1> +; CHECK-NEXT: [[BLOCK8:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[BLOCK9:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT10:%.*]] = insertelement <1 x double> poison, double [[TMP8]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT11:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT10]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = fmul contract <1 x double> [[BLOCK9]], [[SPLAT_SPLAT11]] +; CHECK-NEXT: [[BLOCK12:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <1 x double> poison, double [[TMP10]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT13]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP11:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK12]], <1 x double> [[SPLAT_SPLAT14]], <1 x double> [[TMP9]]) +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <1 x double> [[TMP11]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> [[TMP12]], <2 x i32> <i32 0, i32 2> +; CHECK-NEXT: [[BLOCK15:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT16:%.*]] = insertelement <1 x double> poison, double [[TMP14]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT17:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT16]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP15:%.*]] = fmul contract <1 x double> [[BLOCK15]], [[SPLAT_SPLAT17]] +; CHECK-NEXT: [[BLOCK18:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT19:%.*]] = insertelement <1 x double> poison, double [[TMP16]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT20:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT19]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP17:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK18]], <1 x double> [[SPLAT_SPLAT20]], <1 x double> [[TMP15]]) +; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <1 x double> [[TMP17]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP18]], <2 x i32> <i32 2, i32 1> +; CHECK-NEXT: [[BLOCK21:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[BLOCK22:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP20:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT23:%.*]] = insertelement <1 x double> poison, double [[TMP20]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT24:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT23]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP21:%.*]] = fmul contract <1 x double> [[BLOCK22]], [[SPLAT_SPLAT24]] +; CHECK-NEXT: [[BLOCK25:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP22:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT26:%.*]] = insertelement <1 x double> poison, double [[TMP22]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT27:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT26]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP23:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK25]], <1 x double> [[SPLAT_SPLAT27]], <1 x double> [[TMP21]]) +; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <1 x double> [[TMP23]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP25:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP24]], <2 x i32> <i32 0, i32 2> +; CHECK-NEXT: [[TMP26:%.*]] = getelementptr double, ptr [[C1:%.*]], i64 0 +; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8 +; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2 +; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8 +; CHECK-NEXT: ret void +; +entry: + %A = alloca <4 x double> + call void @init(ptr %A) + br i1 %c.0, label %then, label %exit + +then: + call void @llvm.lifetime.end(i64 -1, ptr %A) + call void @llvm.lifetime.end(i64 -1, ptr %B) + br label %exit + +exit: + %a = load <4 x double>, ptr %A, align 8 + %b = load <4 x double>, ptr %B, align 8 + %m = call <4 x double> @llvm.matrix.multiply(<4 x double> %a, <4 x double> %b, i32 2, i32 2, i32 2) + store <4 x double> %m, ptr %C, align 8 + ret void +} + +define void @lifetimes_for_args_load0_in_different_block(ptr noalias %B, ptr noalias %C, i1 %c.0) { +; CHECK-LABEL: @lifetimes_for_args_load0_in_different_block( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = alloca <4 x double>, align 32 +; CHECK-NEXT: call void @init(ptr [[A]]) +; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] +; CHECK: then: +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0 +; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 +; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 +; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B:%.*]], i64 0 +; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8 +; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2 +; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8 +; CHECK-NEXT: [[BLOCK:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x double> poison, double [[TMP2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = fmul contract <1 x double> [[BLOCK]], [[SPLAT_SPLAT]] +; CHECK-NEXT: [[BLOCK5:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <1 x double> poison, double [[TMP4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT6]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK5]], <1 x double> [[SPLAT_SPLAT7]], <1 x double> [[TMP3]]) +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <1 x double> [[TMP5]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP6]], <2 x i32> <i32 2, i32 1> +; CHECK-NEXT: [[BLOCK8:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[BLOCK9:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT10:%.*]] = insertelement <1 x double> poison, double [[TMP8]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT11:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT10]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = fmul contract <1 x double> [[BLOCK9]], [[SPLAT_SPLAT11]] +; CHECK-NEXT: [[BLOCK12:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <1 x double> poison, double [[TMP10]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT13]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP11:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK12]], <1 x double> [[SPLAT_SPLAT14]], <1 x double> [[TMP9]]) +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <1 x double> [[TMP11]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> [[TMP12]], <2 x i32> <i32 0, i32 2> +; CHECK-NEXT: [[BLOCK15:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT16:%.*]] = insertelement <1 x double> poison, double [[TMP14]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT17:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT16]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP15:%.*]] = fmul contract <1 x double> [[BLOCK15]], [[SPLAT_SPLAT17]] +; CHECK-NEXT: [[BLOCK18:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT19:%.*]] = insertelement <1 x double> poison, double [[TMP16]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT20:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT19]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP17:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK18]], <1 x double> [[SPLAT_SPLAT20]], <1 x double> [[TMP15]]) +; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <1 x double> [[TMP17]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP18]], <2 x i32> <i32 2, i32 1> +; CHECK-NEXT: [[BLOCK21:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[BLOCK22:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP20:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT23:%.*]] = insertelement <1 x double> poison, double [[TMP20]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT24:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT23]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP21:%.*]] = fmul contract <1 x double> [[BLOCK22]], [[SPLAT_SPLAT24]] +; CHECK-NEXT: [[BLOCK25:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP22:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT26:%.*]] = insertelement <1 x double> poison, double [[TMP22]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT27:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT26]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP23:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK25]], <1 x double> [[SPLAT_SPLAT27]], <1 x double> [[TMP21]]) +; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <1 x double> [[TMP23]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP25:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP24]], <2 x i32> <i32 0, i32 2> +; CHECK-NEXT: [[TMP26:%.*]] = getelementptr double, ptr [[C1:%.*]], i64 0 +; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8 +; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2 +; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8 +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + %A = alloca <4 x double> + call void @init(ptr %A) + %a = load <4 x double>, ptr %A, align 8 + call void @llvm.lifetime.end(i64 -1, ptr %A) + br i1 %c.0, label %then, label %exit + +then: + %b = load <4 x double>, ptr %B, align 8 + %m = call <4 x double> @llvm.matrix.multiply(<4 x double> %a, <4 x double> %b, i32 2, i32 2, i32 2) + store <4 x double> %m, ptr %C, align 8 + br label %exit + +exit: + call void @llvm.lifetime.end(i64 -1, ptr %B) + ret void +} + +define void @lifetimes_for_args_load1_in_different_block(ptr noalias %B, ptr noalias %C, i1 %c.0) { +; CHECK-LABEL: @lifetimes_for_args_load1_in_different_block( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = alloca <4 x double>, align 32 +; CHECK-NEXT: call void @init(ptr [[A]]) +; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN:%.*]], label [[EXIT:%.*]] +; CHECK: then: +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr double, ptr [[A]], i64 0 +; CHECK-NEXT: [[COL_LOAD:%.*]] = load <2 x double>, ptr [[TMP0]], align 8 +; CHECK-NEXT: [[VEC_GEP:%.*]] = getelementptr double, ptr [[TMP0]], i64 2 +; CHECK-NEXT: [[COL_LOAD1:%.*]] = load <2 x double>, ptr [[VEC_GEP]], align 8 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr double, ptr [[B:%.*]], i64 0 +; CHECK-NEXT: [[COL_LOAD2:%.*]] = load <2 x double>, ptr [[TMP1]], align 8 +; CHECK-NEXT: [[VEC_GEP3:%.*]] = getelementptr double, ptr [[TMP1]], i64 2 +; CHECK-NEXT: [[COL_LOAD4:%.*]] = load <2 x double>, ptr [[VEC_GEP3]], align 8 +; CHECK-NEXT: [[BLOCK:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x double> poison, double [[TMP2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = fmul contract <1 x double> [[BLOCK]], [[SPLAT_SPLAT]] +; CHECK-NEXT: [[BLOCK5:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT6:%.*]] = insertelement <1 x double> poison, double [[TMP4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT7:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT6]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK5]], <1 x double> [[SPLAT_SPLAT7]], <1 x double> [[TMP3]]) +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <1 x double> [[TMP5]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP6]], <2 x i32> <i32 2, i32 1> +; CHECK-NEXT: [[BLOCK8:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[BLOCK9:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP8:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT10:%.*]] = insertelement <1 x double> poison, double [[TMP8]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT11:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT10]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = fmul contract <1 x double> [[BLOCK9]], [[SPLAT_SPLAT11]] +; CHECK-NEXT: [[BLOCK12:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x double> [[COL_LOAD2]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT13:%.*]] = insertelement <1 x double> poison, double [[TMP10]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT14:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT13]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP11:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK12]], <1 x double> [[SPLAT_SPLAT14]], <1 x double> [[TMP9]]) +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <1 x double> [[TMP11]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <2 x double> [[TMP7]], <2 x double> [[TMP12]], <2 x i32> <i32 0, i32 2> +; CHECK-NEXT: [[BLOCK15:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP14:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT16:%.*]] = insertelement <1 x double> poison, double [[TMP14]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT17:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT16]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP15:%.*]] = fmul contract <1 x double> [[BLOCK15]], [[SPLAT_SPLAT17]] +; CHECK-NEXT: [[BLOCK18:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP16:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT19:%.*]] = insertelement <1 x double> poison, double [[TMP16]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT20:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT19]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP17:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK18]], <1 x double> [[SPLAT_SPLAT20]], <1 x double> [[TMP15]]) +; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <1 x double> [[TMP17]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP19:%.*]] = shufflevector <2 x double> zeroinitializer, <2 x double> [[TMP18]], <2 x i32> <i32 2, i32 1> +; CHECK-NEXT: [[BLOCK21:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[BLOCK22:%.*]] = shufflevector <2 x double> [[COL_LOAD]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP20:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLATINSERT23:%.*]] = insertelement <1 x double> poison, double [[TMP20]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT24:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT23]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP21:%.*]] = fmul contract <1 x double> [[BLOCK22]], [[SPLAT_SPLAT24]] +; CHECK-NEXT: [[BLOCK25:%.*]] = shufflevector <2 x double> [[COL_LOAD1]], <2 x double> poison, <1 x i32> <i32 1> +; CHECK-NEXT: [[TMP22:%.*]] = extractelement <2 x double> [[COL_LOAD4]], i64 1 +; CHECK-NEXT: [[SPLAT_SPLATINSERT26:%.*]] = insertelement <1 x double> poison, double [[TMP22]], i64 0 +; CHECK-NEXT: [[SPLAT_SPLAT27:%.*]] = shufflevector <1 x double> [[SPLAT_SPLATINSERT26]], <1 x double> poison, <1 x i32> zeroinitializer +; CHECK-NEXT: [[TMP23:%.*]] = call contract <1 x double> @llvm.fmuladd.v1f64(<1 x double> [[BLOCK25]], <1 x double> [[SPLAT_SPLAT27]], <1 x double> [[TMP21]]) +; CHECK-NEXT: [[TMP24:%.*]] = shufflevector <1 x double> [[TMP23]], <1 x double> poison, <2 x i32> <i32 0, i32 poison> +; CHECK-NEXT: [[TMP25:%.*]] = shufflevector <2 x double> [[TMP19]], <2 x double> [[TMP24]], <2 x i32> <i32 0, i32 2> +; CHECK-NEXT: [[TMP26:%.*]] = getelementptr double, ptr [[C1:%.*]], i64 0 +; CHECK-NEXT: store <2 x double> [[TMP13]], ptr [[TMP26]], align 8 +; CHECK-NEXT: [[VEC_GEP28:%.*]] = getelementptr double, ptr [[TMP26]], i64 2 +; CHECK-NEXT: store <2 x double> [[TMP25]], ptr [[VEC_GEP28]], align 8 +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + %A = alloca <4 x double> + call void @init(ptr %A) + %b = load <4 x double>, ptr %B, align 8 + call void @llvm.lifetime.end(i64 -1, ptr %B) + br i1 %c.0, label %then, label %exit + +then: + %a = load <4 x double>, ptr %A, align 8 + %m = call <4 x double> @llvm.matrix.multiply(<4 x double> %a, <4 x double> %b, i32 2, i32 2, i32 2) + store <4 x double> %m, ptr %C, align 8 + br label %exit + +exit: + call void @llvm.lifetime.end(i64 -1, ptr %A) + ret void +} + declare void @init(ptr) declare void @llvm.lifetime.end(i64, ptr) diff --git a/llvm/test/Transforms/MergeFunc/constexpr.ll b/llvm/test/Transforms/MergeFunc/constexpr.ll index 9fb7806017422651bb9601689454ee3577b53735..3946fd6a066ff5d546ccc6718e4ef1e19ae02006 100644 --- a/llvm/test/Transforms/MergeFunc/constexpr.ll +++ b/llvm/test/Transforms/MergeFunc/constexpr.ll @@ -66,9 +66,9 @@ define i64 @f8() unnamed_addr { define ptr @f10() unnamed_addr { ; CHECK-LABEL: define ptr @f10() unnamed_addr { -; CHECK-NEXT: ret ptr getelementptr ([4 x i32], ptr @g1, i64 0, inrange i64 1) +; CHECK-NEXT: ret ptr getelementptr inrange(0, 4) ([4 x i32], ptr @g1, i64 0, i64 1) ; - ret ptr getelementptr ([4 x i32], ptr @g1, i64 0, inrange i64 1) + ret ptr getelementptr inrange(0, 4) ([4 x i32], ptr @g1, i64 0, i64 1) } define ptr @f11() unnamed_addr { @@ -80,7 +80,7 @@ define ptr @f11() unnamed_addr { define ptr @f12() unnamed_addr { ; CHECK-LABEL: define ptr @f12() unnamed_addr { -; CHECK-NEXT: ret ptr getelementptr ([4 x i32], ptr @g1, inrange i64 0, i64 1) +; CHECK-NEXT: ret ptr getelementptr inrange(-4, 12) ([4 x i32], ptr @g1, i64 0, i64 1) ; - ret ptr getelementptr ([4 x i32], ptr @g1, inrange i64 0, i64 1) + ret ptr getelementptr inrange(-4, 12) ([4 x i32], ptr @g1, i64 0, i64 1) } diff --git a/llvm/test/Transforms/NewGVN/2007-07-25-DominatedLoop.ll b/llvm/test/Transforms/NewGVN/2007-07-25-DominatedLoop.ll index 978f061ac4fd87ccae9c636976a83d3ca2ab6475..6f0ef197338c2849c50ebeb4ec6a000b95a5d9b3 100644 --- a/llvm/test/Transforms/NewGVN/2007-07-25-DominatedLoop.ll +++ b/llvm/test/Transforms/NewGVN/2007-07-25-DominatedLoop.ll @@ -1,86 +1,87 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn | llvm-dis - %struct.PerlInterpreter = type { i8 } + %struct.PerlInterpreter = type { i8 } @PL_sv_count = external global i32 ; <ptr> [#uses=2] define void @perl_destruct(ptr %sv_interp) { entry: - br i1 false, label %cond_next25, label %cond_true16 + br i1 false, label %cond_next25, label %cond_true16 cond_true16: ; preds = %entry - ret void + ret void cond_next25: ; preds = %entry - br i1 false, label %cond_next33, label %cond_true32 + br i1 false, label %cond_next33, label %cond_true32 cond_true32: ; preds = %cond_next25 - ret void + ret void cond_next33: ; preds = %cond_next25 - br i1 false, label %cond_next61, label %cond_true.i46 + br i1 false, label %cond_next61, label %cond_true.i46 cond_true.i46: ; preds = %cond_next33 - ret void + ret void cond_next61: ; preds = %cond_next33 - br i1 false, label %cond_next69, label %cond_true66 + br i1 false, label %cond_next69, label %cond_true66 cond_true66: ; preds = %cond_next61 - ret void + ret void cond_next69: ; preds = %cond_next61 - br i1 false, label %Perl_safefree.exit52, label %cond_true.i50 + br i1 false, label %Perl_safefree.exit52, label %cond_true.i50 cond_true.i50: ; preds = %cond_next69 - ret void + ret void Perl_safefree.exit52: ; preds = %cond_next69 - br i1 false, label %cond_next80, label %cond_true77 + br i1 false, label %cond_next80, label %cond_true77 cond_true77: ; preds = %Perl_safefree.exit52 - ret void + ret void cond_next80: ; preds = %Perl_safefree.exit52 - br i1 false, label %Perl_safefree.exit56, label %cond_true.i54 + br i1 false, label %Perl_safefree.exit56, label %cond_true.i54 cond_true.i54: ; preds = %cond_next80 - ret void + ret void Perl_safefree.exit56: ; preds = %cond_next80 - br i1 false, label %Perl_safefree.exit60, label %cond_true.i58 + br i1 false, label %Perl_safefree.exit60, label %cond_true.i58 cond_true.i58: ; preds = %Perl_safefree.exit56 - ret void + ret void Perl_safefree.exit60: ; preds = %Perl_safefree.exit56 - br i1 false, label %Perl_safefree.exit64, label %cond_true.i62 + br i1 false, label %Perl_safefree.exit64, label %cond_true.i62 cond_true.i62: ; preds = %Perl_safefree.exit60 - ret void + ret void Perl_safefree.exit64: ; preds = %Perl_safefree.exit60 - br i1 false, label %Perl_safefree.exit68, label %cond_true.i66 + br i1 false, label %Perl_safefree.exit68, label %cond_true.i66 cond_true.i66: ; preds = %Perl_safefree.exit64 - ret void + ret void Perl_safefree.exit68: ; preds = %Perl_safefree.exit64 - br i1 false, label %cond_next150, label %cond_true23.i + br i1 false, label %cond_next150, label %cond_true23.i cond_true23.i: ; preds = %Perl_safefree.exit68 - ret void + ret void cond_next150: ; preds = %Perl_safefree.exit68 - %tmp16092 = load i32, ptr @PL_sv_count, align 4 ; <i32> [#uses=0] - br label %cond_next165 + %tmp16092 = load i32, ptr @PL_sv_count, align 4 ; <i32> [#uses=0] + br label %cond_next165 bb157: ; preds = %cond_next165 - %tmp158 = load i32, ptr @PL_sv_count, align 4 ; <i32> [#uses=0] - br label %cond_next165 + %tmp158 = load i32, ptr @PL_sv_count, align 4 ; <i32> [#uses=0] + br label %cond_next165 cond_next165: ; preds = %bb157, %cond_next150 - br i1 false, label %bb171, label %bb157 + br i1 false, label %bb171, label %bb157 bb171: ; preds = %cond_next165 - ret void + ret void } diff --git a/llvm/test/Transforms/NewGVN/2007-07-25-InfiniteLoop.ll b/llvm/test/Transforms/NewGVN/2007-07-25-InfiniteLoop.ll index abb6fbe5030f7197e4f3fae687b00aab60f7319d..5202a2bc6466b9248cc38e1deb2b5d80908f9ffa 100644 --- a/llvm/test/Transforms/NewGVN/2007-07-25-InfiniteLoop.ll +++ b/llvm/test/Transforms/NewGVN/2007-07-25-InfiniteLoop.ll @@ -1,15 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn -S | FileCheck %s - %struct.INT2 = type { i32, i32 } + %struct.INT2 = type { i32, i32 } @blkshifts = external global ptr ; <ptr> [#uses=2] define i32 @xcompact() { +; CHECK-LABEL: define i32 @xcompact() { +; CHECK-NEXT: entry: +; CHECK-NEXT: store ptr null, ptr @blkshifts, align 4 +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: br label [[BB]] +; entry: - store ptr null, ptr @blkshifts, align 4 - br label %bb + store ptr null, ptr @blkshifts, align 4 + br label %bb bb: ; preds = %bb, %entry - %tmp10 = load ptr, ptr @blkshifts, align 4 ; <ptr> [#uses=0] -; CHECK-NOT: %tmp10 - br label %bb + %tmp10 = load ptr, ptr @blkshifts, align 4 ; <ptr> [#uses=0] + br label %bb } diff --git a/llvm/test/Transforms/NewGVN/2007-07-25-Loop.ll b/llvm/test/Transforms/NewGVN/2007-07-25-Loop.ll index 336f390459b94ca79e34f561f2b5b98a9be160d6..2ee599c11d4199d2805fc27d936b64dc227a9dd3 100644 --- a/llvm/test/Transforms/NewGVN/2007-07-25-Loop.ll +++ b/llvm/test/Transforms/NewGVN/2007-07-25-Loop.ll @@ -1,15 +1,16 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn | llvm-dis - %struct.s_segment_inf = type { float, i32, i16, i16, float, float, i32, float, float } + %struct.s_segment_inf = type { float, i32, i16, i16, float, float, i32, float, float } define void @print_arch(ptr %arch_file, i32 %route_type, i64 %det_routing_arch.0.0, i64 %det_routing_arch.0.1, i64 %det_routing_arch.0.2, i64 %det_routing_arch.0.3, i64 %det_routing_arch.0.4, ptr %segment_inf, i64 %timing_inf.0.0, i64 %timing_inf.0.1, i64 %timing_inf.0.2, i64 %timing_inf.0.3, i64 %timing_inf.0.4, i32 %timing_inf.1) { entry: - br i1 false, label %bb278, label %bb344 + br i1 false, label %bb278, label %bb344 bb278: ; preds = %bb278, %entry - br i1 false, label %bb278, label %bb344 + br i1 false, label %bb278, label %bb344 bb344: ; preds = %bb278, %entry - %tmp38758 = load i16, ptr null, align 2 ; <i16> [#uses=0] - ret void + %tmp38758 = load i16, ptr null, align 2 ; <i16> [#uses=0] + ret void } diff --git a/llvm/test/Transforms/NewGVN/2007-07-25-NestedLoop.ll b/llvm/test/Transforms/NewGVN/2007-07-25-NestedLoop.ll index c46f2b7630aca99afc7a04f008b2ccd10c5915d9..e7461c2f32bf889e94c8d9f94c124b3bd7d47612 100644 --- a/llvm/test/Transforms/NewGVN/2007-07-25-NestedLoop.ll +++ b/llvm/test/Transforms/NewGVN/2007-07-25-NestedLoop.ll @@ -1,38 +1,39 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn | llvm-dis - %struct.TypHeader = type { i32, ptr, [3 x i8], i8 } + %struct.TypHeader = type { i32, ptr, [3 x i8], i8 } define ptr @LtRec(ptr %hdL, ptr %hdR) { entry: - br i1 false, label %bb556.preheader, label %bb534.preheader + br i1 false, label %bb556.preheader, label %bb534.preheader bb534.preheader: ; preds = %entry - ret ptr null + ret ptr null bb556.preheader: ; preds = %entry - %tmp56119 = getelementptr %struct.TypHeader, ptr %hdR, i32 0, i32 0 ; <ptr> [#uses=1] - %tmp56220 = load i32, ptr %tmp56119 ; <i32> [#uses=0] - br i1 false, label %bb.nph23, label %bb675.preheader + %tmp56119 = getelementptr %struct.TypHeader, ptr %hdR, i32 0, i32 0 ; <ptr> [#uses=1] + %tmp56220 = load i32, ptr %tmp56119 ; <i32> [#uses=0] + br i1 false, label %bb.nph23, label %bb675.preheader bb.nph23: ; preds = %bb556.preheader - ret ptr null + ret ptr null bb656: ; preds = %bb675.outer, %bb656 - %tmp678 = load i32, ptr %tmp677 ; <i32> [#uses=0] - br i1 false, label %bb684, label %bb656 + %tmp678 = load i32, ptr %tmp677 ; <i32> [#uses=0] + br i1 false, label %bb684, label %bb656 bb684: ; preds = %bb675.outer, %bb656 - br i1 false, label %bb924.preheader, label %bb675.outer + br i1 false, label %bb924.preheader, label %bb675.outer bb675.outer: ; preds = %bb675.preheader, %bb684 - %tmp67812 = load i32, ptr %tmp67711 ; <i32> [#uses=0] - br i1 false, label %bb684, label %bb656 + %tmp67812 = load i32, ptr %tmp67711 ; <i32> [#uses=0] + br i1 false, label %bb684, label %bb656 bb675.preheader: ; preds = %bb556.preheader - %tmp67711 = getelementptr %struct.TypHeader, ptr %hdR, i32 0, i32 0 ; <ptr> [#uses=1] - %tmp677 = getelementptr %struct.TypHeader, ptr %hdR, i32 0, i32 0 ; <ptr> [#uses=1] - br label %bb675.outer + %tmp67711 = getelementptr %struct.TypHeader, ptr %hdR, i32 0, i32 0 ; <ptr> [#uses=1] + %tmp677 = getelementptr %struct.TypHeader, ptr %hdR, i32 0, i32 0 ; <ptr> [#uses=1] + br label %bb675.outer bb924.preheader: ; preds = %bb684 - ret ptr null + ret ptr null } diff --git a/llvm/test/Transforms/NewGVN/2007-07-25-SinglePredecessor.ll b/llvm/test/Transforms/NewGVN/2007-07-25-SinglePredecessor.ll index 0b0597f44ee7ea7a245379c29395a0072eda654c..6fafce30475698b3bc9b4e7003f73dbe00d4d9ed 100644 --- a/llvm/test/Transforms/NewGVN/2007-07-25-SinglePredecessor.ll +++ b/llvm/test/Transforms/NewGVN/2007-07-25-SinglePredecessor.ll @@ -1,29 +1,30 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn | llvm-dis - %struct.ggBRDF = type { ptr } - %struct.ggBox3 = type { %struct.ggPoint3, %struct.ggPoint3 } - %struct.ggMaterialRecord = type { %struct.ggPoint2, %struct.ggBox3, %struct.ggBox3, %struct.ggSpectrum, %struct.ggSpectrum, %struct.ggSpectrum, ptr, i32, i32, i32, i32 } - %struct.ggONB3 = type { %struct.ggPoint3, %struct.ggPoint3, %struct.ggPoint3 } - %struct.ggPoint2 = type { [2 x double] } - %struct.ggPoint3 = type { [3 x double] } - %struct.ggSpectrum = type { [8 x float] } - %struct.mrViewingHitRecord = type { double, %struct.ggPoint3, %struct.ggONB3, %struct.ggPoint2, double, %struct.ggSpectrum, %struct.ggSpectrum, i32, i32, i32, i32 } - %struct.mrXEllipticalCylinder = type { %struct.ggBRDF, float, float, float, float, float, float } + %struct.ggBRDF = type { ptr } + %struct.ggBox3 = type { %struct.ggPoint3, %struct.ggPoint3 } + %struct.ggMaterialRecord = type { %struct.ggPoint2, %struct.ggBox3, %struct.ggBox3, %struct.ggSpectrum, %struct.ggSpectrum, %struct.ggSpectrum, ptr, i32, i32, i32, i32 } + %struct.ggONB3 = type { %struct.ggPoint3, %struct.ggPoint3, %struct.ggPoint3 } + %struct.ggPoint2 = type { [2 x double] } + %struct.ggPoint3 = type { [3 x double] } + %struct.ggSpectrum = type { [8 x float] } + %struct.mrViewingHitRecord = type { double, %struct.ggPoint3, %struct.ggONB3, %struct.ggPoint2, double, %struct.ggSpectrum, %struct.ggSpectrum, i32, i32, i32, i32 } + %struct.mrXEllipticalCylinder = type { %struct.ggBRDF, float, float, float, float, float, float } define i32 @_ZNK21mrZEllipticalCylinder10viewingHitERK6ggRay3dddR18mrViewingHitRecordR16ggMaterialRecord(ptr %this, ptr %ray, double %unnamed_arg, double %tmin, double %tmax, ptr %VHR, ptr %unnamed_arg2) { entry: - %tmp80.i = getelementptr %struct.mrViewingHitRecord, ptr %VHR, i32 0, i32 1, i32 0, i32 0 ; <ptr> [#uses=1] - store double 0.000000e+00, ptr %tmp80.i - br i1 false, label %return, label %cond_next.i + %tmp80.i = getelementptr %struct.mrViewingHitRecord, ptr %VHR, i32 0, i32 1, i32 0, i32 0 ; <ptr> [#uses=1] + store double 0.000000e+00, ptr %tmp80.i + br i1 false, label %return, label %cond_next.i cond_next.i: ; preds = %entry - br i1 false, label %return, label %cond_true + br i1 false, label %return, label %cond_true cond_true: ; preds = %cond_next.i - %tmp3.i8 = getelementptr %struct.mrViewingHitRecord, ptr %VHR, i32 0, i32 1, i32 0, i32 0 ; <ptr> [#uses=1] - %tmp46 = load double, ptr %tmp3.i8 ; <double> [#uses=0] - ret i32 1 + %tmp3.i8 = getelementptr %struct.mrViewingHitRecord, ptr %VHR, i32 0, i32 1, i32 0, i32 0 ; <ptr> [#uses=1] + %tmp46 = load double, ptr %tmp3.i8 ; <double> [#uses=0] + ret i32 1 return: ; preds = %cond_next.i, %entry - ret i32 0 + ret i32 0 } diff --git a/llvm/test/Transforms/NewGVN/2007-07-26-NonRedundant.ll b/llvm/test/Transforms/NewGVN/2007-07-26-NonRedundant.ll index 8d3bfcd1367bf5ffaf3746ea31c836c8de924d8a..a64901e71b05a5bbef2424b16d7aa7276e62cf8c 100644 --- a/llvm/test/Transforms/NewGVN/2007-07-26-NonRedundant.ll +++ b/llvm/test/Transforms/NewGVN/2007-07-26-NonRedundant.ll @@ -1,16 +1,17 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn | llvm-dis @bsLive = external global i32 ; <ptr> [#uses=2] define i32 @bsR(i32 %n) { entry: - br i1 false, label %cond_next, label %bb19 + br i1 false, label %cond_next, label %bb19 cond_next: ; preds = %entry - store i32 0, ptr @bsLive, align 4 - br label %bb19 + store i32 0, ptr @bsLive, align 4 + br label %bb19 bb19: ; preds = %cond_next, %entry - %tmp29 = load i32, ptr @bsLive, align 4 ; <i32> [#uses=0] - ret i32 0 + %tmp29 = load i32, ptr @bsLive, align 4 ; <i32> [#uses=0] + ret i32 0 } diff --git a/llvm/test/Transforms/NewGVN/2007-07-26-PhiErasure.ll b/llvm/test/Transforms/NewGVN/2007-07-26-PhiErasure.ll index 22d64324c2352e5e49126a649a9bd14ea5d1ea8d..46f9b84a7e378389a141203945e2fc0c9b51f841 100644 --- a/llvm/test/Transforms/NewGVN/2007-07-26-PhiErasure.ll +++ b/llvm/test/Transforms/NewGVN/2007-07-26-PhiErasure.ll @@ -20,7 +20,7 @@ define i32 @reload(ptr %first, i32 %global, ptr %dumpfile) { ; CHECK: cond_next2943: ; CHECK-NEXT: br i1 false, label [[BB2982_PREHEADER:%.*]], label [[BB2928]] ; CHECK: bb2982.preheader: -; CHECK-NEXT: store i8 poison, ptr null +; CHECK-NEXT: store i8 poison, ptr null, align 1 ; CHECK-NEXT: ret i32 poison ; cond_next2835.1: ; preds = %cond_next2861 diff --git a/llvm/test/Transforms/NewGVN/2007-07-30-PredIDom.ll b/llvm/test/Transforms/NewGVN/2007-07-30-PredIDom.ll index 59da31c5e33e0584811ec4170db6e4a853b1a224..c70846054caf5a9ea768dfdf2fe8e78390e5a9d4 100644 --- a/llvm/test/Transforms/NewGVN/2007-07-30-PredIDom.ll +++ b/llvm/test/Transforms/NewGVN/2007-07-30-PredIDom.ll @@ -1,274 +1,275 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn | llvm-dis - %"struct.Block::$_16" = type { i32 } - %struct.Exp = type { ptr, i32, i32, i32, ptr, ptr, %"struct.Exp::$_10", %"struct.Block::$_16", %"struct.Exp::$_12" } - %"struct.Exp::$_10" = type { ptr } - %"struct.Exp::$_12" = type { ptr } - %struct.Exp_ = type { i32, i32, i32, i32, ptr } - %struct.Id = type { ptr, i32, i32, i32, %"struct.Id::$_13" } - %"struct.Id::$_13" = type { double } + %"struct.Block::$_16" = type { i32 } + %struct.Exp = type { ptr, i32, i32, i32, ptr, ptr, %"struct.Exp::$_10", %"struct.Block::$_16", %"struct.Exp::$_12" } + %"struct.Exp::$_10" = type { ptr } + %"struct.Exp::$_12" = type { ptr } + %struct.Exp_ = type { i32, i32, i32, i32, ptr } + %struct.Id = type { ptr, i32, i32, i32, %"struct.Id::$_13" } + %"struct.Id::$_13" = type { double } define ptr @_ZN3Exp8toStringEj(ptr %this, i32 %nextpc) { entry: - switch i32 0, label %bb970 [ - i32 1, label %bb - i32 2, label %bb39 - i32 3, label %bb195 - i32 4, label %bb270 - i32 5, label %bb418 - i32 6, label %bb633 - i32 7, label %bb810 - i32 8, label %bb882 - i32 9, label %bb925 - ] + switch i32 0, label %bb970 [ + i32 1, label %bb + i32 2, label %bb39 + i32 3, label %bb195 + i32 4, label %bb270 + i32 5, label %bb418 + i32 6, label %bb633 + i32 7, label %bb810 + i32 8, label %bb882 + i32 9, label %bb925 + ] bb: ; preds = %entry - store ptr null, ptr null - br label %return + store ptr null, ptr null + br label %return bb39: ; preds = %entry - br i1 false, label %cond_true, label %cond_false132 + br i1 false, label %cond_true, label %cond_false132 cond_true: ; preds = %bb39 - br i1 false, label %cond_true73, label %cond_false + br i1 false, label %cond_true73, label %cond_false cond_true73: ; preds = %cond_true - br i1 false, label %cond_true108, label %cond_next + br i1 false, label %cond_true108, label %cond_next cond_true108: ; preds = %cond_true73 - br label %cond_next + br label %cond_next cond_next: ; preds = %cond_true108, %cond_true73 - br label %cond_next131 + br label %cond_next131 cond_false: ; preds = %cond_true - br label %cond_next131 + br label %cond_next131 cond_next131: ; preds = %cond_false, %cond_next - br label %cond_next141 + br label %cond_next141 cond_false132: ; preds = %bb39 - br label %cond_next141 + br label %cond_next141 cond_next141: ; preds = %cond_false132, %cond_next131 - br i1 false, label %cond_true169, label %cond_false175 + br i1 false, label %cond_true169, label %cond_false175 cond_true169: ; preds = %cond_next141 - br label %cond_next181 + br label %cond_next181 cond_false175: ; preds = %cond_next141 - br label %cond_next181 + br label %cond_next181 cond_next181: ; preds = %cond_false175, %cond_true169 - br i1 false, label %cond_true189, label %cond_next191 + br i1 false, label %cond_true189, label %cond_next191 cond_true189: ; preds = %cond_next181 - br label %cond_next191 + br label %cond_next191 cond_next191: ; preds = %cond_true189, %cond_next181 - store ptr null, ptr null - br label %return + store ptr null, ptr null + br label %return bb195: ; preds = %entry - br i1 false, label %cond_true248, label %cond_false250 + br i1 false, label %cond_true248, label %cond_false250 cond_true248: ; preds = %bb195 - br label %cond_next252 + br label %cond_next252 cond_false250: ; preds = %bb195 - br label %cond_next252 + br label %cond_next252 cond_next252: ; preds = %cond_false250, %cond_true248 - br i1 false, label %cond_true265, label %cond_next267 + br i1 false, label %cond_true265, label %cond_next267 cond_true265: ; preds = %cond_next252 - br label %cond_next267 + br label %cond_next267 cond_next267: ; preds = %cond_true265, %cond_next252 - store ptr null, ptr null - br label %return + store ptr null, ptr null + br label %return bb270: ; preds = %entry - br i1 false, label %cond_true338, label %cond_false340 + br i1 false, label %cond_true338, label %cond_false340 cond_true338: ; preds = %bb270 - br label %cond_next342 + br label %cond_next342 cond_false340: ; preds = %bb270 - br label %cond_next342 + br label %cond_next342 cond_next342: ; preds = %cond_false340, %cond_true338 - br i1 false, label %cond_true362, label %cond_false364 + br i1 false, label %cond_true362, label %cond_false364 cond_true362: ; preds = %cond_next342 - br label %cond_next366 + br label %cond_next366 cond_false364: ; preds = %cond_next342 - br label %cond_next366 + br label %cond_next366 cond_next366: ; preds = %cond_false364, %cond_true362 - br i1 false, label %cond_true393, label %cond_next395 + br i1 false, label %cond_true393, label %cond_next395 cond_true393: ; preds = %cond_next366 - br label %cond_next395 + br label %cond_next395 cond_next395: ; preds = %cond_true393, %cond_next366 - br i1 false, label %cond_true406, label %cond_next408 + br i1 false, label %cond_true406, label %cond_next408 cond_true406: ; preds = %cond_next395 - br label %cond_next408 + br label %cond_next408 cond_next408: ; preds = %cond_true406, %cond_next395 - br i1 false, label %cond_true413, label %cond_next415 + br i1 false, label %cond_true413, label %cond_next415 cond_true413: ; preds = %cond_next408 - br label %cond_next415 + br label %cond_next415 cond_next415: ; preds = %cond_true413, %cond_next408 - store ptr null, ptr null - br label %return + store ptr null, ptr null + br label %return bb418: ; preds = %entry - br i1 false, label %cond_true512, label %cond_false514 + br i1 false, label %cond_true512, label %cond_false514 cond_true512: ; preds = %bb418 - br label %cond_next516 + br label %cond_next516 cond_false514: ; preds = %bb418 - br label %cond_next516 + br label %cond_next516 cond_next516: ; preds = %cond_false514, %cond_true512 - br i1 false, label %cond_true536, label %cond_false538 + br i1 false, label %cond_true536, label %cond_false538 cond_true536: ; preds = %cond_next516 - br label %cond_next540 + br label %cond_next540 cond_false538: ; preds = %cond_next516 - br label %cond_next540 + br label %cond_next540 cond_next540: ; preds = %cond_false538, %cond_true536 - br i1 false, label %cond_true560, label %cond_false562 + br i1 false, label %cond_true560, label %cond_false562 cond_true560: ; preds = %cond_next540 - br label %cond_next564 + br label %cond_next564 cond_false562: ; preds = %cond_next540 - br label %cond_next564 + br label %cond_next564 cond_next564: ; preds = %cond_false562, %cond_true560 - br i1 false, label %cond_true597, label %cond_next599 + br i1 false, label %cond_true597, label %cond_next599 cond_true597: ; preds = %cond_next564 - br label %cond_next599 + br label %cond_next599 cond_next599: ; preds = %cond_true597, %cond_next564 - br i1 false, label %cond_true614, label %cond_next616 + br i1 false, label %cond_true614, label %cond_next616 cond_true614: ; preds = %cond_next599 - br label %cond_next616 + br label %cond_next616 cond_next616: ; preds = %cond_true614, %cond_next599 - br i1 false, label %cond_true621, label %cond_next623 + br i1 false, label %cond_true621, label %cond_next623 cond_true621: ; preds = %cond_next616 - br label %cond_next623 + br label %cond_next623 cond_next623: ; preds = %cond_true621, %cond_next616 - br i1 false, label %cond_true628, label %cond_next630 + br i1 false, label %cond_true628, label %cond_next630 cond_true628: ; preds = %cond_next623 - br label %cond_next630 + br label %cond_next630 cond_next630: ; preds = %cond_true628, %cond_next623 - store ptr null, ptr null - br label %return + store ptr null, ptr null + br label %return bb633: ; preds = %entry - br i1 false, label %cond_true667, label %cond_next669 + br i1 false, label %cond_true667, label %cond_next669 cond_true667: ; preds = %bb633 - br label %cond_next669 + br label %cond_next669 cond_next669: ; preds = %cond_true667, %bb633 - br i1 false, label %cond_true678, label %cond_next791 + br i1 false, label %cond_true678, label %cond_next791 cond_true678: ; preds = %cond_next669 - br label %bb735 + br label %bb735 bb679: ; preds = %bb735 - br i1 false, label %cond_true729, label %cond_next731 + br i1 false, label %cond_true729, label %cond_next731 cond_true729: ; preds = %bb679 - br label %cond_next731 + br label %cond_next731 cond_next731: ; preds = %cond_true729, %bb679 - br label %bb735 + br label %bb735 bb735: ; preds = %cond_next731, %cond_true678 - br i1 false, label %bb679, label %bb743 + br i1 false, label %bb679, label %bb743 bb743: ; preds = %bb735 - br i1 false, label %cond_true788, label %cond_next790 + br i1 false, label %cond_true788, label %cond_next790 cond_true788: ; preds = %bb743 - br label %cond_next790 + br label %cond_next790 cond_next790: ; preds = %cond_true788, %bb743 - br label %cond_next791 + br label %cond_next791 cond_next791: ; preds = %cond_next790, %cond_next669 - br i1 false, label %cond_true805, label %cond_next807 + br i1 false, label %cond_true805, label %cond_next807 cond_true805: ; preds = %cond_next791 - br label %cond_next807 + br label %cond_next807 cond_next807: ; preds = %cond_true805, %cond_next791 - store ptr null, ptr null - br label %return + store ptr null, ptr null + br label %return bb810: ; preds = %entry - br i1 false, label %cond_true870, label %cond_next872 + br i1 false, label %cond_true870, label %cond_next872 cond_true870: ; preds = %bb810 - br label %cond_next872 + br label %cond_next872 cond_next872: ; preds = %cond_true870, %bb810 - br i1 false, label %cond_true877, label %cond_next879 + br i1 false, label %cond_true877, label %cond_next879 cond_true877: ; preds = %cond_next872 - br label %cond_next879 + br label %cond_next879 cond_next879: ; preds = %cond_true877, %cond_next872 - store ptr null, ptr null - br label %return + store ptr null, ptr null + br label %return bb882: ; preds = %entry - br i1 false, label %cond_true920, label %cond_next922 + br i1 false, label %cond_true920, label %cond_next922 cond_true920: ; preds = %bb882 - br label %cond_next922 + br label %cond_next922 cond_next922: ; preds = %cond_true920, %bb882 - store ptr null, ptr null - br label %return + store ptr null, ptr null + br label %return bb925: ; preds = %entry - br i1 false, label %cond_true965, label %cond_next967 + br i1 false, label %cond_true965, label %cond_next967 cond_true965: ; preds = %bb925 - br label %cond_next967 + br label %cond_next967 cond_next967: ; preds = %cond_true965, %bb925 - store ptr null, ptr null - br label %return + store ptr null, ptr null + br label %return bb970: ; preds = %entry - unreachable - ; No predecessors! - store ptr null, ptr null - br label %return + unreachable + ; No predecessors! + store ptr null, ptr null + br label %return return: ; preds = %0, %cond_next967, %cond_next922, %cond_next879, %cond_next807, %cond_next630, %cond_next415, %cond_next267, %cond_next191, %bb - %retval980 = load ptr, ptr null ; <ptr> [#uses=1] - ret ptr %retval980 + %retval980 = load ptr, ptr null ; <ptr> [#uses=1] + ret ptr %retval980 } diff --git a/llvm/test/Transforms/NewGVN/2007-07-31-RedundantPhi.ll b/llvm/test/Transforms/NewGVN/2007-07-31-RedundantPhi.ll index 934fffc986f8152370fa36b919dccbc35e77eb86..5411bcc7d406ad34481ffcb2bcf1dbe306cf033e 100644 --- a/llvm/test/Transforms/NewGVN/2007-07-31-RedundantPhi.ll +++ b/llvm/test/Transforms/NewGVN/2007-07-31-RedundantPhi.ll @@ -1,23 +1,37 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn -S | FileCheck %s @img_width = external global i16 ; <ptr> [#uses=2] define i32 @smpUMHEXBipredIntegerPelBlockMotionSearch(ptr %cur_pic, i16 signext %ref, i32 %list, i32 %pic_pix_x, i32 %pic_pix_y, i32 %blocktype, i16 signext %pred_mv_x1, i16 signext %pred_mv_y1, i16 signext %pred_mv_x2, i16 signext %pred_mv_y2, ptr %mv_x, ptr %mv_y, ptr %s_mv_x, ptr %s_mv_y, i32 %search_range, i32 %min_mcost, i32 %lambda_factor) { +; CHECK-LABEL: define i32 @smpUMHEXBipredIntegerPelBlockMotionSearch( +; CHECK-SAME: ptr [[CUR_PIC:%.*]], i16 signext [[REF:%.*]], i32 [[LIST:%.*]], i32 [[PIC_PIX_X:%.*]], i32 [[PIC_PIX_Y:%.*]], i32 [[BLOCKTYPE:%.*]], i16 signext [[PRED_MV_X1:%.*]], i16 signext [[PRED_MV_Y1:%.*]], i16 signext [[PRED_MV_X2:%.*]], i16 signext [[PRED_MV_Y2:%.*]], ptr [[MV_X:%.*]], ptr [[MV_Y:%.*]], ptr [[S_MV_X:%.*]], ptr [[S_MV_Y:%.*]], i32 [[SEARCH_RANGE:%.*]], i32 [[MIN_MCOST:%.*]], i32 [[LAMBDA_FACTOR:%.*]]) { +; CHECK-NEXT: cond_next143: +; CHECK-NEXT: store i16 0, ptr @img_width, align 2 +; CHECK-NEXT: br i1 false, label [[COND_NEXT449:%.*]], label [[COND_FALSE434:%.*]] +; CHECK: cond_false434: +; CHECK-NEXT: br label [[COND_NEXT449]] +; CHECK: cond_next449: +; CHECK-NEXT: br i1 false, label [[COND_NEXT698:%.*]], label [[COND_FALSE470:%.*]] +; CHECK: cond_false470: +; CHECK-NEXT: br label [[COND_NEXT698]] +; CHECK: cond_next698: +; CHECK-NEXT: ret i32 0 +; cond_next143: ; preds = %entry - store i16 0, ptr @img_width, align 2 - br i1 false, label %cond_next449, label %cond_false434 + store i16 0, ptr @img_width, align 2 + br i1 false, label %cond_next449, label %cond_false434 cond_false434: ; preds = %cond_true415 - br label %cond_next449 + br label %cond_next449 cond_next449: ; preds = %cond_false434, %cond_true415 - br i1 false, label %cond_next698, label %cond_false470 + br i1 false, label %cond_next698, label %cond_false470 cond_false470: ; preds = %cond_next449 - br label %cond_next698 + br label %cond_next698 cond_next698: ; preds = %cond_true492 - %tmp701 = load i16, ptr @img_width, align 2 ; <i16> [#uses=0] -; CHECK-NOT: %tmp701 = - ret i32 0 + %tmp701 = load i16, ptr @img_width, align 2 ; <i16> [#uses=0] + ret i32 0 } diff --git a/llvm/test/Transforms/NewGVN/2008-02-13-NewPHI.ll b/llvm/test/Transforms/NewGVN/2008-02-13-NewPHI.ll index b2440fbced41f49cbe6ee1baf5469cbc2c257f13..49d6de7d7a0f6991fc9de559d7970c92471759f8 100644 --- a/llvm/test/Transforms/NewGVN/2008-02-13-NewPHI.ll +++ b/llvm/test/Transforms/NewGVN/2008-02-13-NewPHI.ll @@ -1,22 +1,23 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn ; PR2032 define i32 @sscal(i32 %n, double %sa1, ptr %sx, i32 %incx) { entry: - %sx_addr = alloca ptr ; <ptr> [#uses=3] - store ptr %sx, ptr %sx_addr, align 4 - br label %bb33 + %sx_addr = alloca ptr ; <ptr> [#uses=3] + store ptr %sx, ptr %sx_addr, align 4 + br label %bb33 bb: ; preds = %bb33 - %tmp27 = load ptr, ptr %sx_addr, align 4 ; <ptr> [#uses=1] - store float 0.000000e+00, ptr %tmp27, align 4 - store ptr null, ptr %sx_addr, align 4 - br label %bb33 + %tmp27 = load ptr, ptr %sx_addr, align 4 ; <ptr> [#uses=1] + store float 0.000000e+00, ptr %tmp27, align 4 + store ptr null, ptr %sx_addr, align 4 + br label %bb33 bb33: ; preds = %bb, %entry - br i1 false, label %bb, label %return + br i1 false, label %bb, label %return return: ; preds = %bb33 - %retval59 = load i32, ptr null, align 4 ; <i32> [#uses=1] - ret i32 %retval59 + %retval59 = load i32, ptr null, align 4 ; <i32> [#uses=1] + ret i32 %retval59 } diff --git a/llvm/test/Transforms/NewGVN/2008-07-02-Unreachable.ll b/llvm/test/Transforms/NewGVN/2008-07-02-Unreachable.ll index 0c1891e46d2675fae38a58a6ffe89206b818b47c..cf591d7e2a79a0c08d72c353dc2a364f2eceb4ea 100644 --- a/llvm/test/Transforms/NewGVN/2008-07-02-Unreachable.ll +++ b/llvm/test/Transforms/NewGVN/2008-07-02-Unreachable.ll @@ -1,36 +1,62 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn -S | FileCheck %s ; PR2503 @g_3 = external global i8 ; <ptr> [#uses=2] define i8 @func_1(i32 %x, i32 %y) nounwind { +; CHECK-LABEL: define i8 @func_1( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], [[Y]] +; CHECK-NEXT: br i1 [[CMP]], label [[IFELSE:%.*]], label [[IFTHEN:%.*]] +; CHECK: ifthen: +; CHECK-NEXT: br label [[IFEND:%.*]] +; CHECK: ifelse: +; CHECK-NEXT: [[TMP3:%.*]] = load i8, ptr @g_3, align 1 +; CHECK-NEXT: store i8 [[TMP3]], ptr [[A]], align 1 +; CHECK-NEXT: br label [[AFTERFOR:%.*]] +; CHECK: forcond: +; CHECK-NEXT: store i8 poison, ptr null, align 1 +; CHECK-NEXT: br i1 false, label [[AFTERFOR]], label [[FORBODY:%.*]] +; CHECK: forbody: +; CHECK-NEXT: store i8 poison, ptr null, align 1 +; CHECK-NEXT: br label [[FORINC:%.*]] +; CHECK: forinc: +; CHECK-NEXT: store i8 poison, ptr null, align 1 +; CHECK-NEXT: br label [[FORCOND:%.*]] +; CHECK: afterfor: +; CHECK-NEXT: ret i8 [[TMP3]] +; CHECK: ifend: +; CHECK-NEXT: ret i8 0 +; entry: %A = alloca i8 - %cmp = icmp eq i32 %x, %y - br i1 %cmp, label %ifelse, label %ifthen + %cmp = icmp eq i32 %x, %y + br i1 %cmp, label %ifelse, label %ifthen ifthen: ; preds = %entry - br label %ifend + br label %ifend ifelse: ; preds = %entry - %tmp3 = load i8, ptr @g_3 ; <i8> [#uses=0] - store i8 %tmp3, ptr %A - br label %afterfor + %tmp3 = load i8, ptr @g_3 ; <i8> [#uses=0] + store i8 %tmp3, ptr %A + br label %afterfor forcond: ; preds = %forinc - br i1 false, label %afterfor, label %forbody + br i1 false, label %afterfor, label %forbody forbody: ; preds = %forcond - br label %forinc + br label %forinc forinc: ; preds = %forbody - br label %forcond + br label %forcond afterfor: ; preds = %forcond, %forcond.thread - %tmp10 = load i8, ptr @g_3 ; <i8> [#uses=0] - ret i8 %tmp10 -; CHECK: ret i8 %tmp3 + %tmp10 = load i8, ptr @g_3 ; <i8> [#uses=0] + ret i8 %tmp10 ifend: ; preds = %afterfor, %ifthen - ret i8 0 + ret i8 0 } diff --git a/llvm/test/Transforms/NewGVN/2008-12-09-SelfRemove.ll b/llvm/test/Transforms/NewGVN/2008-12-09-SelfRemove.ll index a2e252d065d2fbcf86bd21a24ca4c4ec429d39d9..95cb229f17f586d4d64740305db8034ef8e887d7 100644 --- a/llvm/test/Transforms/NewGVN/2008-12-09-SelfRemove.ll +++ b/llvm/test/Transforms/NewGVN/2008-12-09-SelfRemove.ll @@ -1,38 +1,41 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn -S | FileCheck %s target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target triple = "i386-apple-darwin9.5" - %struct.anon = type { ptr, i32 } - %struct.d_print_info = type { i32, ptr, i32, i32, ptr, ptr, i32 } - %struct.d_print_mod = type { ptr, ptr, i32, ptr } - %struct.d_print_template = type { ptr, ptr } - %struct.demangle_component = type { i32, { %struct.anon } } + %struct.anon = type { ptr, i32 } + %struct.d_print_info = type { i32, ptr, i32, i32, ptr, ptr, i32 } + %struct.d_print_mod = type { ptr, ptr, i32, ptr } + %struct.d_print_template = type { ptr, ptr } + %struct.demangle_component = type { i32, { %struct.anon } } define void @d_print_mod_list(ptr %dpi, ptr %mods, i32 %suffix) nounwind { +; CHECK-LABEL: define void @d_print_mod_list( +; CHECK-SAME: ptr [[DPI:%.*]], ptr [[MODS:%.*]], i32 [[SUFFIX:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_D_PRINT_INFO:%.*]], ptr [[DPI]], i32 0, i32 1 +; CHECK-NEXT: br i1 false, label [[RETURN:%.*]], label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: br label [[BB21:%.*]] +; CHECK: bb21: +; CHECK-NEXT: br label [[BB21]] +; CHECK: return: +; CHECK-NEXT: store i8 poison, ptr null, align 1 +; CHECK-NEXT: ret void +; entry: - %0 = getelementptr %struct.d_print_info, ptr %dpi, i32 0, i32 1 ; <ptr> [#uses=1] - br i1 false, label %return, label %bb + %0 = getelementptr %struct.d_print_info, ptr %dpi, i32 0, i32 1 ; <ptr> [#uses=1] + br i1 false, label %return, label %bb bb: ; preds = %entry - %1 = load ptr, ptr %0, align 4 ; <ptr> [#uses=0] - %2 = getelementptr %struct.d_print_info, ptr %dpi, i32 0, i32 1 ; <ptr> [#uses=0] - br label %bb21 + %1 = load ptr, ptr %0, align 4 ; <ptr> [#uses=0] + %2 = getelementptr %struct.d_print_info, ptr %dpi, i32 0, i32 1 ; <ptr> [#uses=0] + br label %bb21 bb21: ; preds = %bb21, %bb - br label %bb21 + br label %bb21 return: ; preds = %entry - ret void + ret void } -; CHECK: define void @d_print_mod_list(ptr %dpi, ptr %mods, i32 %suffix) #0 { -; CHECK: entry: -; CHECK: %0 = getelementptr %struct.d_print_info, ptr %dpi, i32 0, i32 1 -; CHECK: br i1 false, label %return, label %bb -; CHECK: bb: -; CHECK: br label %bb21 -; CHECK: bb21: -; CHECK: br label %bb21 -; CHECK: return: -; CHECK: ret void -; CHECK: } diff --git a/llvm/test/Transforms/NewGVN/2008-12-12-RLE-Crash.ll b/llvm/test/Transforms/NewGVN/2008-12-12-RLE-Crash.ll index bb51f72752a2573c76e85f3aab54d1a3c741039c..3df35a159328372b5a6876c07c30b2a8f1d59b76 100644 --- a/llvm/test/Transforms/NewGVN/2008-12-12-RLE-Crash.ll +++ b/llvm/test/Transforms/NewGVN/2008-12-12-RLE-Crash.ll @@ -1,35 +1,36 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn | llvm-dis target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target triple = "i386-apple-darwin7" define i32 @main(i32 %argc, ptr %argv) nounwind { entry: - br label %bb84 + br label %bb84 bb41: ; preds = %bb82 - %tmp = load i8, ptr %opt.0, align 1 ; <i8> [#uses=0] - %tmp1 = getelementptr i8, ptr %opt.0, i32 1 ; <ptr> [#uses=2] - switch i32 0, label %bb81 [ - i32 102, label %bb82 - i32 110, label %bb79 - i32 118, label %bb80 - ] + %tmp = load i8, ptr %opt.0, align 1 ; <i8> [#uses=0] + %tmp1 = getelementptr i8, ptr %opt.0, i32 1 ; <ptr> [#uses=2] + switch i32 0, label %bb81 [ + i32 102, label %bb82 + i32 110, label %bb79 + i32 118, label %bb80 + ] bb79: ; preds = %bb41 - br label %bb82 + br label %bb82 bb80: ; preds = %bb41 - ret i32 0 + ret i32 0 bb81: ; preds = %bb41 - ret i32 1 + ret i32 1 bb82: ; preds = %bb84, %bb79, %bb41 - %opt.0 = phi ptr [ %tmp3, %bb84 ], [ %tmp1, %bb79 ], [ %tmp1, %bb41 ] ; <ptr> [#uses=3] - %tmp2 = load i8, ptr %opt.0, align 1 ; <i8> [#uses=0] - br i1 false, label %bb84, label %bb41 + %opt.0 = phi ptr [ %tmp3, %bb84 ], [ %tmp1, %bb79 ], [ %tmp1, %bb41 ] ; <ptr> [#uses=3] + %tmp2 = load i8, ptr %opt.0, align 1 ; <i8> [#uses=0] + br i1 false, label %bb84, label %bb41 bb84: ; preds = %bb82, %entry - %tmp3 = getelementptr i8, ptr null, i32 1 ; <ptr> [#uses=1] - br label %bb82 + %tmp3 = getelementptr i8, ptr null, i32 1 ; <ptr> [#uses=1] + br label %bb82 } diff --git a/llvm/test/Transforms/NewGVN/2008-12-14-rle-reanalyze.ll b/llvm/test/Transforms/NewGVN/2008-12-14-rle-reanalyze.ll index 38d1240fd6a29c9a028a6c71715662c46a5ec9ae..821355664a7f09a965f81b01c1015d1de818ab4d 100644 --- a/llvm/test/Transforms/NewGVN/2008-12-14-rle-reanalyze.ll +++ b/llvm/test/Transforms/NewGVN/2008-12-14-rle-reanalyze.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn | llvm-dis target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target triple = "i386-apple-darwin7" @@ -5,14 +6,14 @@ target triple = "i386-apple-darwin7" define i32 @Quiesce(i32 %alpha, i32 %beta, i32 %wtm, i32 %ply) nounwind { entry: - br label %bb22 + br label %bb22 bb22: ; preds = %bb23, %bb22, %entry - br i1 false, label %bb23, label %bb22 + br i1 false, label %bb23, label %bb22 bb23: ; preds = %bb23, %bb22 - %sortv.233 = phi ptr [ @sort_value, %bb22 ], [ %sortv.2, %bb23 ] ; <ptr> [#uses=1] - %0 = load i32, ptr %sortv.233, align 4 ; <i32> [#uses=0] - %sortv.2 = getelementptr [256 x i32], ptr @sort_value, i32 0, i32 0 ; <ptr> [#uses=1] - br i1 false, label %bb23, label %bb22 + %sortv.233 = phi ptr [ @sort_value, %bb22 ], [ %sortv.2, %bb23 ] ; <ptr> [#uses=1] + %0 = load i32, ptr %sortv.233, align 4 ; <i32> [#uses=0] + %sortv.2 = getelementptr [256 x i32], ptr @sort_value, i32 0, i32 0 ; <ptr> [#uses=1] + br i1 false, label %bb23, label %bb22 } diff --git a/llvm/test/Transforms/NewGVN/2008-12-15-CacheVisited.ll b/llvm/test/Transforms/NewGVN/2008-12-15-CacheVisited.ll index 0b1761da0c33a1b34688d4b1e2ae4a64e563ac3c..ff9ecce88b458d1f0a8b57c3232c6c19c562e198 100644 --- a/llvm/test/Transforms/NewGVN/2008-12-15-CacheVisited.ll +++ b/llvm/test/Transforms/NewGVN/2008-12-15-CacheVisited.ll @@ -1,28 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn | llvm-dis ; Cached results must be added to and verified against the visited sets. ; PR3217 define fastcc void @gen_field_die(ptr %decl) nounwind { entry: - br i1 false, label %bb203, label %bb202 + br i1 false, label %bb203, label %bb202 bb202: ; preds = %entry - unreachable + unreachable bb203: ; preds = %entry - %tmp = getelementptr i32, ptr %decl, i32 1 ; <ptr> [#uses=1] - %tmp1 = load i32, ptr %tmp, align 4 ; <i32> [#uses=0] - br i1 false, label %bb207, label %bb204 + %tmp = getelementptr i32, ptr %decl, i32 1 ; <ptr> [#uses=1] + %tmp1 = load i32, ptr %tmp, align 4 ; <i32> [#uses=0] + br i1 false, label %bb207, label %bb204 bb204: ; preds = %bb203 - %tmp2 = getelementptr i32, ptr %decl, i32 1 ; <ptr> [#uses=1] - br label %bb208 + %tmp2 = getelementptr i32, ptr %decl, i32 1 ; <ptr> [#uses=1] + br label %bb208 bb207: ; preds = %bb203 - br label %bb208 + br label %bb208 bb208: ; preds = %bb207, %bb204 - %iftmp.1374.0.in = phi ptr [ null, %bb207 ], [ %tmp2, %bb204 ] ; <ptr> [#uses=1] - %iftmp.1374.0 = load i32, ptr %iftmp.1374.0.in ; <i32> [#uses=0] - unreachable + %iftmp.1374.0.in = phi ptr [ null, %bb207 ], [ %tmp2, %bb204 ] ; <ptr> [#uses=1] + %iftmp.1374.0 = load i32, ptr %iftmp.1374.0.in ; <i32> [#uses=0] + unreachable } diff --git a/llvm/test/Transforms/NewGVN/2009-01-21-SortInvalidation.ll b/llvm/test/Transforms/NewGVN/2009-01-21-SortInvalidation.ll index 8631cbd82f5d7682b472ccfd772a0f124beeb25b..1f0a32a87458493e126e259236dd962744bba3ab 100644 --- a/llvm/test/Transforms/NewGVN/2009-01-21-SortInvalidation.ll +++ b/llvm/test/Transforms/NewGVN/2009-01-21-SortInvalidation.ll @@ -1,55 +1,56 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn | llvm-dis ; PR3358 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" target triple = "x86_64-unknown-linux-gnu" - %struct.re_pattern_buffer = type { ptr, i64, i64, i64, ptr, ptr, i64, i8 } - %struct.re_registers = type { i32, ptr, ptr } + %struct.re_pattern_buffer = type { ptr, i64, i64, i64, ptr, ptr, i64, i8 } + %struct.re_registers = type { i32, ptr, ptr } define fastcc i32 @byte_re_match_2_internal(ptr nocapture %bufp, ptr %string1, i32 %size1, ptr %string2, i32 %size2, i32 %pos, ptr %regs, i32 %stop) nounwind { entry: - br label %bb159 + br label %bb159 succeed_label: ; preds = %bb159 - ret i32 0 + ret i32 0 bb159: ; preds = %bb664, %bb554, %bb159, %bb159, %bb159, %entry - %d.0 = phi ptr [ null, %entry ], [ %d.0, %bb159 ], [ %d.0, %bb554 ], [ %d.0, %bb159 ], [ %d.0, %bb159 ], [ %d.12, %bb664 ] ; <ptr> [#uses=5] - switch i32 0, label %bb661 [ - i32 0, label %bb159 - i32 1, label %succeed_label - i32 13, label %bb159 - i32 14, label %bb159 - i32 16, label %bb411 - i32 24, label %bb622 - i32 28, label %bb543 - ] + %d.0 = phi ptr [ null, %entry ], [ %d.0, %bb159 ], [ %d.0, %bb554 ], [ %d.0, %bb159 ], [ %d.0, %bb159 ], [ %d.12, %bb664 ] ; <ptr> [#uses=5] + switch i32 0, label %bb661 [ + i32 0, label %bb159 + i32 1, label %succeed_label + i32 13, label %bb159 + i32 14, label %bb159 + i32 16, label %bb411 + i32 24, label %bb622 + i32 28, label %bb543 + ] bb411: ; preds = %bb411, %bb159 - br label %bb411 + br label %bb411 bb543: ; preds = %bb159 - br i1 false, label %bb549, label %bb550 + br i1 false, label %bb549, label %bb550 bb549: ; preds = %bb543 - br label %bb554 + br label %bb554 bb550: ; preds = %bb543 - br i1 false, label %bb554, label %bb552 + br i1 false, label %bb554, label %bb552 bb552: ; preds = %bb550 - %0 = load i8, ptr %d.0, align 8 ; <i8> [#uses=0] - br label %bb554 + %0 = load i8, ptr %d.0, align 8 ; <i8> [#uses=0] + br label %bb554 bb554: ; preds = %bb552, %bb550, %bb549 - br i1 false, label %bb159, label %bb661 + br i1 false, label %bb159, label %bb661 bb622: ; preds = %bb622, %bb159 - br label %bb622 + br label %bb622 bb661: ; preds = %bb554, %bb159 - %d.12 = select i1 false, ptr null, ptr null ; <ptr> [#uses=1] - br label %bb664 + %d.12 = select i1 false, ptr null, ptr null ; <ptr> [#uses=1] + br label %bb664 bb664: ; preds = %bb664, %bb661 - br i1 false, label %bb159, label %bb664 + br i1 false, label %bb159, label %bb664 } diff --git a/llvm/test/Transforms/NewGVN/2009-01-22-SortInvalidation.ll b/llvm/test/Transforms/NewGVN/2009-01-22-SortInvalidation.ll index d8871700df6d8b14d283780fb81b24de8ab4443e..25f73dc8aa19d2b82449b7af0f35a27e3cfe1639 100644 --- a/llvm/test/Transforms/NewGVN/2009-01-22-SortInvalidation.ll +++ b/llvm/test/Transforms/NewGVN/2009-01-22-SortInvalidation.ll @@ -1,100 +1,101 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn | llvm-dis target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target triple = "i386-apple-darwin7" - %struct..4sPragmaType = type { ptr, i32 } - %struct.AggInfo = type { i8, i8, i32, ptr, i32, ptr, i32, i32, i32, ptr, i32, i32 } - %struct.AggInfo_col = type { ptr, i32, i32, i32, i32, ptr } - %struct.AggInfo_func = type { ptr, ptr, i32, i32 } - %struct.AuxData = type { ptr, ptr } - %struct.Bitvec = type { i32, i32, i32, { [125 x i32] } } - %struct.BtCursor = type { ptr, ptr, ptr, ptr, ptr, ptr, i32, ptr, i32, %struct.CellInfo, i8, i8, ptr, i64, i32, i8, ptr } - %struct.BtLock = type { ptr, i32, i8, ptr } - %struct.BtShared = type { ptr, ptr, ptr, ptr, i8, i8, i8, i8, i8, i8, i8, i8, i32, i16, i16, i32, i32, i32, i32, i8, i32, ptr, ptr, ptr, %struct.BusyHandler, i32, ptr, ptr, ptr } - %struct.Btree = type { ptr, ptr, i8, i8, i8, i32, ptr, ptr } - %struct.BtreeMutexArray = type { i32, [11 x ptr] } - %struct.BusyHandler = type { ptr, ptr, i32 } - %struct.CellInfo = type { ptr, i64, i32, i32, i16, i16, i16, i16 } - %struct.CollSeq = type { ptr, i8, i8, ptr, ptr, ptr } - %struct.Column = type { ptr, ptr, ptr, ptr, i8, i8, i8, i8 } - %struct.Context = type { i64, i32, %struct.Fifo } - %struct.CountCtx = type { i64 } - %struct.Cursor = type { ptr, i32, i64, i64, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i64, ptr, i32, ptr, i64, ptr, ptr, i32, i64, ptr, ptr, i32, i32, ptr, ptr, ptr } - %struct.Db = type { ptr, ptr, i8, i8, ptr, ptr, ptr } - %struct.Expr = type { i8, i8, i16, ptr, ptr, ptr, ptr, %struct..4sPragmaType, %struct..4sPragmaType, i32, i32, ptr, i32, i32, ptr, ptr, i32 } - %struct.ExprList = type { i32, i32, i32, ptr } - %struct.ExprList_item = type { ptr, ptr, i8, i8, i8 } - %struct.FKey = type { ptr, ptr, ptr, ptr, i32, ptr, i8, i8, i8, i8 } - %struct.Fifo = type { i32, ptr, ptr } - %struct.FifoPage = type { i32, i32, i32, ptr, [1 x i64] } - %struct.FuncDef = type { i16, i8, i8, i8, ptr, ptr, ptr, ptr, ptr, [1 x i8] } - %struct.Hash = type { i8, i8, i32, i32, ptr, ptr } - %struct.HashElem = type { ptr, ptr, ptr, ptr, i32 } - %struct.IdList = type { ptr, i32, i32 } - %struct.Index = type { ptr, i32, ptr, ptr, ptr, i32, i8, i8, ptr, ptr, ptr, ptr, ptr } - %struct.KeyInfo = type { ptr, i8, i8, i8, i32, ptr, [1 x ptr] } - %struct.Mem = type { %struct.CountCtx, double, ptr, ptr, i32, i16, i8, i8, ptr } - %struct.MemPage = type { i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i16, i16, i16, i16, i16, i16, [5 x %struct._OvflCell], ptr, ptr, ptr, i32, ptr } - %struct.Module = type { ptr, ptr, ptr, ptr } - %struct.Op = type { i8, i8, i8, i8, i32, i32, i32, { i32 } } - %struct.Pager = type { ptr, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, %struct.PagerLruList, ptr, ptr, ptr, i64, i64, i64, i64, i64, i32, ptr, ptr, i32, ptr, ptr, [16 x i8] } - %struct.PagerLruLink = type { ptr, ptr } - %struct.PagerLruList = type { ptr, ptr, ptr } - %struct.Parse = type { ptr, i32, ptr, ptr, i8, i8, i8, i8, i8, i8, i8, [8 x i32], i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, [12 x i32], i32, ptr, i32, i32, i32, i32, i32, ptr, i8, %struct..4sPragmaType, %struct..4sPragmaType, %struct..4sPragmaType, ptr, ptr, ptr, ptr, ptr, ptr, %struct..4sPragmaType, i8, ptr, i32 } - %struct.PgHdr = type { ptr, i32, ptr, ptr, %struct.PagerLruLink, ptr, i8, i8, i8, i8, i8, i16, ptr, ptr, ptr } - %struct.Schema = type { i32, %struct.Hash, %struct.Hash, %struct.Hash, %struct.Hash, ptr, i8, i8, i16, i32, ptr } - %struct.Select = type { ptr, i8, i8, i8, i8, i8, i8, i8, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, i32, i32, [3 x i32] } - %struct.SrcList = type { i16, i16, [1 x %struct.SrcList_item] } - %struct.SrcList_item = type { ptr, ptr, ptr, ptr, ptr, i8, i8, i32, ptr, ptr, i64 } - %struct.Table = type { ptr, i32, ptr, i32, ptr, i32, ptr, i32, ptr, ptr, ptr, ptr, i32, i8, i8, i8, i8, i8, i8, i8, ptr, ptr, i32, ptr, ptr } - %struct.TableLock = type { i32, i32, i8, ptr } - %struct.Trigger = type { ptr, ptr, i8, i8, ptr, ptr, %struct..4sPragmaType, ptr, ptr, ptr, ptr } - %struct.TriggerStack = type { ptr, i32, i32, i32, i32, i32, i32, ptr, ptr } - %struct.TriggerStep = type { i32, i32, ptr, ptr, %struct..4sPragmaType, ptr, ptr, ptr, ptr, ptr } - %struct.Vdbe = type { ptr, ptr, ptr, i32, i32, ptr, i32, i32, ptr, ptr, ptr, i32, ptr, i32, ptr, ptr, i32, i32, i32, ptr, i32, i32, %struct.Fifo, i32, i32, ptr, i32, i32, i32, i32, i32, [25 x i32], i32, i32, ptr, ptr, ptr, i8, i8, i8, i8, i8, i8, i32, i64, i32, %struct.BtreeMutexArray, i32, ptr, i32 } - %struct.VdbeFunc = type { ptr, i32, [1 x %struct.AuxData] } - %struct._OvflCell = type { ptr, i16 } - %struct._ht = type { i32, ptr } - %struct.anon = type { double } - %struct.sColMap = type { i32, ptr } - %struct.sqlite3 = type { ptr, i32, ptr, i32, i32, i32, i32, i8, i8, i8, i8, i32, ptr, i64, i64, i32, i32, i32, ptr, %struct.sqlite3InitInfo, i32, ptr, ptr, i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, %struct.anon, ptr, ptr, ptr, ptr, i32, %struct.Hash, ptr, ptr, i32, %struct.Hash, %struct.Hash, %struct.BusyHandler, i32, [2 x %struct.Db], i8 } - %struct.sqlite3InitInfo = type { i32, i32, i8 } - %struct.sqlite3_context = type { ptr, ptr, %struct.Mem, ptr, i32, ptr } - %struct.sqlite3_file = type { ptr } - %struct.sqlite3_index_constraint = type { i32, i8, i8, i32 } - %struct.sqlite3_index_constraint_usage = type { i32, i8 } - %struct.sqlite3_index_info = type { i32, ptr, i32, ptr, ptr, i32, ptr, i32, i32, double } - %struct.sqlite3_io_methods = type { i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr } - %struct.sqlite3_module = type { i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr } - %struct.sqlite3_mutex = type opaque - %struct.sqlite3_vfs = type { i32, i32, i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr } - %struct.sqlite3_vtab = type { ptr, i32, ptr } - %struct.sqlite3_vtab_cursor = type { ptr } + %struct..4sPragmaType = type { ptr, i32 } + %struct.AggInfo = type { i8, i8, i32, ptr, i32, ptr, i32, i32, i32, ptr, i32, i32 } + %struct.AggInfo_col = type { ptr, i32, i32, i32, i32, ptr } + %struct.AggInfo_func = type { ptr, ptr, i32, i32 } + %struct.AuxData = type { ptr, ptr } + %struct.Bitvec = type { i32, i32, i32, { [125 x i32] } } + %struct.BtCursor = type { ptr, ptr, ptr, ptr, ptr, ptr, i32, ptr, i32, %struct.CellInfo, i8, i8, ptr, i64, i32, i8, ptr } + %struct.BtLock = type { ptr, i32, i8, ptr } + %struct.BtShared = type { ptr, ptr, ptr, ptr, i8, i8, i8, i8, i8, i8, i8, i8, i32, i16, i16, i32, i32, i32, i32, i8, i32, ptr, ptr, ptr, %struct.BusyHandler, i32, ptr, ptr, ptr } + %struct.Btree = type { ptr, ptr, i8, i8, i8, i32, ptr, ptr } + %struct.BtreeMutexArray = type { i32, [11 x ptr] } + %struct.BusyHandler = type { ptr, ptr, i32 } + %struct.CellInfo = type { ptr, i64, i32, i32, i16, i16, i16, i16 } + %struct.CollSeq = type { ptr, i8, i8, ptr, ptr, ptr } + %struct.Column = type { ptr, ptr, ptr, ptr, i8, i8, i8, i8 } + %struct.Context = type { i64, i32, %struct.Fifo } + %struct.CountCtx = type { i64 } + %struct.Cursor = type { ptr, i32, i64, i64, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i64, ptr, i32, ptr, i64, ptr, ptr, i32, i64, ptr, ptr, i32, i32, ptr, ptr, ptr } + %struct.Db = type { ptr, ptr, i8, i8, ptr, ptr, ptr } + %struct.Expr = type { i8, i8, i16, ptr, ptr, ptr, ptr, %struct..4sPragmaType, %struct..4sPragmaType, i32, i32, ptr, i32, i32, ptr, ptr, i32 } + %struct.ExprList = type { i32, i32, i32, ptr } + %struct.ExprList_item = type { ptr, ptr, i8, i8, i8 } + %struct.FKey = type { ptr, ptr, ptr, ptr, i32, ptr, i8, i8, i8, i8 } + %struct.Fifo = type { i32, ptr, ptr } + %struct.FifoPage = type { i32, i32, i32, ptr, [1 x i64] } + %struct.FuncDef = type { i16, i8, i8, i8, ptr, ptr, ptr, ptr, ptr, [1 x i8] } + %struct.Hash = type { i8, i8, i32, i32, ptr, ptr } + %struct.HashElem = type { ptr, ptr, ptr, ptr, i32 } + %struct.IdList = type { ptr, i32, i32 } + %struct.Index = type { ptr, i32, ptr, ptr, ptr, i32, i8, i8, ptr, ptr, ptr, ptr, ptr } + %struct.KeyInfo = type { ptr, i8, i8, i8, i32, ptr, [1 x ptr] } + %struct.Mem = type { %struct.CountCtx, double, ptr, ptr, i32, i16, i8, i8, ptr } + %struct.MemPage = type { i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i16, i16, i16, i16, i16, i16, [5 x %struct._OvflCell], ptr, ptr, ptr, i32, ptr } + %struct.Module = type { ptr, ptr, ptr, ptr } + %struct.Op = type { i8, i8, i8, i8, i32, i32, i32, { i32 } } + %struct.Pager = type { ptr, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, %struct.PagerLruList, ptr, ptr, ptr, i64, i64, i64, i64, i64, i32, ptr, ptr, i32, ptr, ptr, [16 x i8] } + %struct.PagerLruLink = type { ptr, ptr } + %struct.PagerLruList = type { ptr, ptr, ptr } + %struct.Parse = type { ptr, i32, ptr, ptr, i8, i8, i8, i8, i8, i8, i8, [8 x i32], i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, [12 x i32], i32, ptr, i32, i32, i32, i32, i32, ptr, i8, %struct..4sPragmaType, %struct..4sPragmaType, %struct..4sPragmaType, ptr, ptr, ptr, ptr, ptr, ptr, %struct..4sPragmaType, i8, ptr, i32 } + %struct.PgHdr = type { ptr, i32, ptr, ptr, %struct.PagerLruLink, ptr, i8, i8, i8, i8, i8, i16, ptr, ptr, ptr } + %struct.Schema = type { i32, %struct.Hash, %struct.Hash, %struct.Hash, %struct.Hash, ptr, i8, i8, i16, i32, ptr } + %struct.Select = type { ptr, i8, i8, i8, i8, i8, i8, i8, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, i32, i32, [3 x i32] } + %struct.SrcList = type { i16, i16, [1 x %struct.SrcList_item] } + %struct.SrcList_item = type { ptr, ptr, ptr, ptr, ptr, i8, i8, i32, ptr, ptr, i64 } + %struct.Table = type { ptr, i32, ptr, i32, ptr, i32, ptr, i32, ptr, ptr, ptr, ptr, i32, i8, i8, i8, i8, i8, i8, i8, ptr, ptr, i32, ptr, ptr } + %struct.TableLock = type { i32, i32, i8, ptr } + %struct.Trigger = type { ptr, ptr, i8, i8, ptr, ptr, %struct..4sPragmaType, ptr, ptr, ptr, ptr } + %struct.TriggerStack = type { ptr, i32, i32, i32, i32, i32, i32, ptr, ptr } + %struct.TriggerStep = type { i32, i32, ptr, ptr, %struct..4sPragmaType, ptr, ptr, ptr, ptr, ptr } + %struct.Vdbe = type { ptr, ptr, ptr, i32, i32, ptr, i32, i32, ptr, ptr, ptr, i32, ptr, i32, ptr, ptr, i32, i32, i32, ptr, i32, i32, %struct.Fifo, i32, i32, ptr, i32, i32, i32, i32, i32, [25 x i32], i32, i32, ptr, ptr, ptr, i8, i8, i8, i8, i8, i8, i32, i64, i32, %struct.BtreeMutexArray, i32, ptr, i32 } + %struct.VdbeFunc = type { ptr, i32, [1 x %struct.AuxData] } + %struct._OvflCell = type { ptr, i16 } + %struct._ht = type { i32, ptr } + %struct.anon = type { double } + %struct.sColMap = type { i32, ptr } + %struct.sqlite3 = type { ptr, i32, ptr, i32, i32, i32, i32, i8, i8, i8, i8, i32, ptr, i64, i64, i32, i32, i32, ptr, %struct.sqlite3InitInfo, i32, ptr, ptr, i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, %struct.anon, ptr, ptr, ptr, ptr, i32, %struct.Hash, ptr, ptr, i32, %struct.Hash, %struct.Hash, %struct.BusyHandler, i32, [2 x %struct.Db], i8 } + %struct.sqlite3InitInfo = type { i32, i32, i8 } + %struct.sqlite3_context = type { ptr, ptr, %struct.Mem, ptr, i32, ptr } + %struct.sqlite3_file = type { ptr } + %struct.sqlite3_index_constraint = type { i32, i8, i8, i32 } + %struct.sqlite3_index_constraint_usage = type { i32, i8 } + %struct.sqlite3_index_info = type { i32, ptr, i32, ptr, ptr, i32, ptr, i32, i32, double } + %struct.sqlite3_io_methods = type { i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr } + %struct.sqlite3_module = type { i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr } + %struct.sqlite3_mutex = type opaque + %struct.sqlite3_vfs = type { i32, i32, i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr } + %struct.sqlite3_vtab = type { ptr, i32, ptr } + %struct.sqlite3_vtab_cursor = type { ptr } define fastcc void @sqlite3Insert(ptr %pParse, ptr %pTabList, ptr %pList, ptr %pSelect, ptr %pColumn, i32 %onError) nounwind { entry: - br i1 false, label %bb54, label %bb69.loopexit + br i1 false, label %bb54, label %bb69.loopexit bb54: ; preds = %entry - br label %bb69.loopexit + br label %bb69.loopexit bb59: ; preds = %bb63.preheader - %0 = load ptr, ptr %3, align 4 ; <ptr> [#uses=0] - br label %bb65 + %0 = load ptr, ptr %3, align 4 ; <ptr> [#uses=0] + br label %bb65 bb65: ; preds = %bb63.preheader, %bb59 - %1 = load ptr, ptr %4, align 4 ; <ptr> [#uses=0] - br i1 false, label %bb67, label %bb63.preheader + %1 = load ptr, ptr %4, align 4 ; <ptr> [#uses=0] + br i1 false, label %bb67, label %bb63.preheader bb67: ; preds = %bb65 - %2 = getelementptr %struct.IdList, ptr %pColumn, i32 0, i32 0 ; <ptr> [#uses=0] - unreachable + %2 = getelementptr %struct.IdList, ptr %pColumn, i32 0, i32 0 ; <ptr> [#uses=0] + unreachable bb69.loopexit: ; preds = %bb54, %entry - %3 = getelementptr %struct.IdList, ptr %pColumn, i32 0, i32 0 ; <ptr> [#uses=1] - %4 = getelementptr %struct.IdList, ptr %pColumn, i32 0, i32 0 ; <ptr> [#uses=1] - br label %bb63.preheader + %3 = getelementptr %struct.IdList, ptr %pColumn, i32 0, i32 0 ; <ptr> [#uses=1] + %4 = getelementptr %struct.IdList, ptr %pColumn, i32 0, i32 0 ; <ptr> [#uses=1] + br label %bb63.preheader bb63.preheader: ; preds = %bb69.loopexit, %bb65 - br i1 false, label %bb59, label %bb65 + br i1 false, label %bb59, label %bb65 } diff --git a/llvm/test/Transforms/NewGVN/2009-03-10-PREOnVoid.ll b/llvm/test/Transforms/NewGVN/2009-03-10-PREOnVoid.ll index 6aa79e0433d4866e010b29715b5bb62648a37477..83177e5498fe83f7bb9ddb3acb028ab498534527 100644 --- a/llvm/test/Transforms/NewGVN/2009-03-10-PREOnVoid.ll +++ b/llvm/test/Transforms/NewGVN/2009-03-10-PREOnVoid.ll @@ -1,21 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn -disable-output ; PR3775 ; ModuleID = 'bugpoint-reduced-simplified.bc' target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32" target triple = "i386-pc-linux-gnu" - %llvm.dbg.anchor.type = type { i32, i32 } - %"struct.__gnu_cxx::hash<ptr>" = type <{ i8 }> - %struct.__sched_param = type { i32 } - %struct._pthread_descr_struct = type opaque - %struct.pthread_attr_t = type { i32, i32, %struct.__sched_param, i32, i32, i32, i32, ptr, i32 } - %struct.pthread_mutex_t = type { i32, i32, ptr, i32, %llvm.dbg.anchor.type } - %"struct.std::_Rb_tree<ptr,std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > >,std::_Select1st<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,std::less<ptr>,std::allocator<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > > >" = type { %"struct.std::_Rb_tree<ptr,std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > >,std::_Select1st<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,std::less<ptr>,std::allocator<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > > >::_Rb_tree_impl<std::less<ptr>,false>" } - %"struct.std::_Rb_tree<ptr,std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > >,std::_Select1st<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,std::less<ptr>,std::allocator<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > > >::_Rb_tree_impl<std::less<ptr>,false>" = type { %"struct.__gnu_cxx::hash<ptr>", %"struct.std::_Rb_tree_node_base", i32 } - %"struct.std::_Rb_tree_iterator<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >" = type { ptr } - %"struct.std::_Rb_tree_node_base" = type { i32, ptr, ptr, ptr } - %"struct.std::pair<std::_Rb_tree_iterator<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,bool>" = type { %"struct.std::_Rb_tree_iterator<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >", i8 } - %"struct.std::pair<ptr const,ptr>" = type { ptr, ptr } + %llvm.dbg.anchor.type = type { i32, i32 } + %"struct.__gnu_cxx::hash<ptr>" = type <{ i8 }> + %struct.__sched_param = type { i32 } + %struct._pthread_descr_struct = type opaque + %struct.pthread_attr_t = type { i32, i32, %struct.__sched_param, i32, i32, i32, i32, ptr, i32 } + %struct.pthread_mutex_t = type { i32, i32, ptr, i32, %llvm.dbg.anchor.type } + %"struct.std::_Rb_tree<ptr,std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > >,std::_Select1st<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,std::less<ptr>,std::allocator<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > > >" = type { %"struct.std::_Rb_tree<ptr,std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > >,std::_Select1st<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,std::less<ptr>,std::allocator<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > > >::_Rb_tree_impl<std::less<ptr>,false>" } + %"struct.std::_Rb_tree<ptr,std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > >,std::_Select1st<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,std::less<ptr>,std::allocator<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > > >::_Rb_tree_impl<std::less<ptr>,false>" = type { %"struct.__gnu_cxx::hash<ptr>", %"struct.std::_Rb_tree_node_base", i32 } + %"struct.std::_Rb_tree_iterator<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >" = type { ptr } + %"struct.std::_Rb_tree_node_base" = type { i32, ptr, ptr, ptr } + %"struct.std::pair<std::_Rb_tree_iterator<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,bool>" = type { %"struct.std::_Rb_tree_iterator<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >", i8 } + %"struct.std::pair<ptr const,ptr>" = type { ptr, ptr } @_ZL20__gthrw_pthread_oncePiPFvvE = weak alias i32 (ptr, ptr), ptr @pthread_once ; <ptr> [#uses=0] @_ZL27__gthrw_pthread_getspecificj = weak alias ptr (i32), ptr @pthread_getspecific ; <ptr> [#uses=0] @@ -36,75 +37,75 @@ declare fastcc void @_ZNSt10_Select1stISt4pairIKPvS1_EEC1Ev() nounwind readnone define fastcc void @_ZNSt8_Rb_treeIPvSt4pairIKS0_S0_ESt10_Select1stIS3_ESt4lessIS0_ESaIS3_EE16_M_insert_uniqueERKS3_(ptr noalias nocapture sret(%"struct.std::pair<std::_Rb_tree_iterator<std::pair<ptr const, std::vector<ShadowInfo, std::allocator<ShadowInfo> > > >,bool>") %agg.result, ptr %this, ptr %__v) nounwind { entry: - br i1 false, label %bb7, label %bb + br i1 false, label %bb7, label %bb bb: ; preds = %bb, %entry - br i1 false, label %bb5, label %bb + br i1 false, label %bb5, label %bb bb5: ; preds = %bb - call fastcc void @_ZNSt10_Select1stISt4pairIKPvS1_EEC1Ev() nounwind - br i1 false, label %bb11, label %bb7 + call fastcc void @_ZNSt10_Select1stISt4pairIKPvS1_EEC1Ev() nounwind + br i1 false, label %bb11, label %bb7 bb7: ; preds = %bb5, %entry - br label %bb11 + br label %bb11 bb11: ; preds = %bb7, %bb5 - call fastcc void @_ZNSt10_Select1stISt4pairIKPvS1_EEC1Ev() nounwind - unreachable + call fastcc void @_ZNSt10_Select1stISt4pairIKPvS1_EEC1Ev() nounwind + unreachable } define i32 @pthread_once(ptr, ptr) { - ret i32 0 + ret i32 0 } define ptr @pthread_getspecific(i32) { - ret ptr null + ret ptr null } define i32 @pthread_setspecific(i32, ptr) { - ret i32 0 + ret i32 0 } define i32 @pthread_create(ptr, ptr, ptr, ptr) { - ret i32 0 + ret i32 0 } define i32 @pthread_cancel(i32) { - ret i32 0 + ret i32 0 } define i32 @pthread_mutex_lock(ptr) { - ret i32 0 + ret i32 0 } define i32 @pthread_mutex_trylock(ptr) { - ret i32 0 + ret i32 0 } define i32 @pthread_mutex_unlock(ptr) { - ret i32 0 + ret i32 0 } define i32 @pthread_mutex_init(ptr, ptr) { - ret i32 0 + ret i32 0 } define i32 @pthread_key_create(ptr, ptr) { - ret i32 0 + ret i32 0 } define i32 @pthread_key_delete(i32) { - ret i32 0 + ret i32 0 } define i32 @pthread_mutexattr_init(ptr) { - ret i32 0 + ret i32 0 } define i32 @pthread_mutexattr_settype(ptr, i32) { - ret i32 0 + ret i32 0 } define i32 @pthread_mutexattr_destroy(ptr) { - ret i32 0 + ret i32 0 } diff --git a/llvm/test/Transforms/NewGVN/2009-07-13-MemDepSortFail.ll b/llvm/test/Transforms/NewGVN/2009-07-13-MemDepSortFail.ll index 24ad1852780cdb6150abf926049e232d04dde513..9694ae47e977c5c0c8469a322f5fe3e7d4f679ea 100644 --- a/llvm/test/Transforms/NewGVN/2009-07-13-MemDepSortFail.ll +++ b/llvm/test/Transforms/NewGVN/2009-07-13-MemDepSortFail.ll @@ -1,67 +1,68 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn | llvm-dis ; PR4256 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32" target triple = "i386-pc-linux-gnu" - %llvm.dbg.anchor.type = type { i32, i32 } - %struct.cset = type { ptr, i8, i8, i32, ptr } - %struct.lmat = type { ptr, i32, ptr, ptr, ptr, ptr, ptr, ptr, i32, ptr, ptr, ptr, ptr, ptr } - %struct.re_guts = type { ptr, ptr, ptr, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, ptr, ptr, i32, i32, i32, i32, [1 x i8] } + %llvm.dbg.anchor.type = type { i32, i32 } + %struct.cset = type { ptr, i8, i8, i32, ptr } + %struct.lmat = type { ptr, i32, ptr, ptr, ptr, ptr, ptr, ptr, i32, ptr, ptr, ptr, ptr, ptr } + %struct.re_guts = type { ptr, ptr, ptr, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, ptr, ptr, i32, i32, i32, i32, [1 x i8] } define ptr @lbackref(ptr %m, ptr %start, ptr %stop, i32 %startst, i32 %stopst, i32 %lev, i32 %rec) nounwind { entry: - br label %bb63 + br label %bb63 bb: ; preds = %bb63 - switch i32 0, label %bb62 [ - i32 268435456, label %bb2 - i32 805306368, label %bb9 - i32 -1610612736, label %bb51 - ] + switch i32 0, label %bb62 [ + i32 268435456, label %bb2 + i32 805306368, label %bb9 + i32 -1610612736, label %bb51 + ] bb2: ; preds = %bb - br label %bb62 + br label %bb62 bb9: ; preds = %bb - %0 = load i8, ptr %sp.1, align 1 ; <i8> [#uses=0] - br label %bb62 + %0 = load i8, ptr %sp.1, align 1 ; <i8> [#uses=0] + br label %bb62 bb51: ; preds = %bb - %1 = load i8, ptr %sp.1, align 1 ; <i8> [#uses=0] - ret ptr null + %1 = load i8, ptr %sp.1, align 1 ; <i8> [#uses=0] + ret ptr null bb62: ; preds = %bb9, %bb2, %bb - br label %bb63 + br label %bb63 bb63: ; preds = %bb84, %bb69, %bb62, %entry - %sp.1 = phi ptr [ null, %bb62 ], [ %sp.1.lcssa, %bb84 ], [ %start, %entry ], [ %sp.1.lcssa, %bb69 ] ; <ptr> [#uses=3] - br i1 false, label %bb, label %bb65 + %sp.1 = phi ptr [ null, %bb62 ], [ %sp.1.lcssa, %bb84 ], [ %start, %entry ], [ %sp.1.lcssa, %bb69 ] ; <ptr> [#uses=3] + br i1 false, label %bb, label %bb65 bb65: ; preds = %bb63 - %sp.1.lcssa = phi ptr [ %sp.1, %bb63 ] ; <ptr> [#uses=4] - br i1 false, label %bb66, label %bb69 + %sp.1.lcssa = phi ptr [ %sp.1, %bb63 ] ; <ptr> [#uses=4] + br i1 false, label %bb66, label %bb69 bb66: ; preds = %bb65 - ret ptr null + ret ptr null bb69: ; preds = %bb65 - switch i32 0, label %bb108.loopexit2.loopexit.loopexit [ - i32 1342177280, label %bb63 - i32 1476395008, label %bb84 - i32 1879048192, label %bb104 - i32 2013265920, label %bb93 - ] + switch i32 0, label %bb108.loopexit2.loopexit.loopexit [ + i32 1342177280, label %bb63 + i32 1476395008, label %bb84 + i32 1879048192, label %bb104 + i32 2013265920, label %bb93 + ] bb84: ; preds = %bb69 - %2 = tail call ptr @lbackref(ptr %m, ptr %sp.1.lcssa, ptr %stop, i32 0, i32 %stopst, i32 0, i32 0) nounwind ; <ptr> [#uses=0] - br label %bb63 + %2 = tail call ptr @lbackref(ptr %m, ptr %sp.1.lcssa, ptr %stop, i32 0, i32 %stopst, i32 0, i32 0) nounwind ; <ptr> [#uses=0] + br label %bb63 bb93: ; preds = %bb69 - ret ptr null + ret ptr null bb104: ; preds = %bb69 - %sp.1.lcssa.lcssa33 = phi ptr [ %sp.1.lcssa, %bb69 ] ; <ptr> [#uses=0] - unreachable + %sp.1.lcssa.lcssa33 = phi ptr [ %sp.1.lcssa, %bb69 ] ; <ptr> [#uses=0] + unreachable bb108.loopexit2.loopexit.loopexit: ; preds = %bb69 - ret ptr null + ret ptr null } diff --git a/llvm/test/Transforms/NewGVN/2009-11-12-MemDepMallocBitCast.ll b/llvm/test/Transforms/NewGVN/2009-11-12-MemDepMallocBitCast.ll index 3eda7ca1b812c85d19a8c1550674630a585112ee..c49f651437cbb5c15645201d4773ee341c3e3a13 100644 --- a/llvm/test/Transforms/NewGVN/2009-11-12-MemDepMallocBitCast.ll +++ b/llvm/test/Transforms/NewGVN/2009-11-12-MemDepMallocBitCast.ll @@ -1,14 +1,19 @@ -; Test to make sure malloc's bitcast does not block detection of a store +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; Test to make sure malloc's bitcast does not block detection of a store ; to aliased memory; GVN should not optimize away the load in this program. ; RUN: opt < %s -passes=newgvn -S | FileCheck %s define i64 @test() { +; CHECK-LABEL: define i64 @test() { +; CHECK-NEXT: [[TMP1:%.*]] = tail call ptr @malloc(i64 mul (i64 ptrtoint (ptr getelementptr (i64, ptr null, i64 1) to i64), i64 4)) +; CHECK-NEXT: store i8 42, ptr [[TMP1]], align 1 +; CHECK-NEXT: [[Y:%.*]] = load i64, ptr [[TMP1]], align 4 +; CHECK-NEXT: ret i64 [[Y]] +; %1 = tail call ptr @malloc(i64 mul (i64 4, i64 ptrtoint (ptr getelementptr (i64, ptr null, i64 1) to i64))) ; <ptr> [#uses=2] store i8 42, ptr %1 %Y = load i64, ptr %1 ; <i64> [#uses=1] ret i64 %Y -; CHECK: %Y = load i64, ptr %1 -; CHECK: ret i64 %Y } declare noalias ptr @malloc(i64) diff --git a/llvm/test/Transforms/NewGVN/2010-03-31-RedundantPHIs.ll b/llvm/test/Transforms/NewGVN/2010-03-31-RedundantPHIs.ll index 321f3cff89a1e0661ff08c27bde5b38a08a9f976..c6fc7b99cdf8dfa04ac0ae4e734f5643aa8ec70c 100644 --- a/llvm/test/Transforms/NewGVN/2010-03-31-RedundantPHIs.ll +++ b/llvm/test/Transforms/NewGVN/2010-03-31-RedundantPHIs.ll @@ -1,9 +1,36 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn -S | FileCheck %s ; CHECK-NOT: load ; CHECK-NOT: phi define ptr @cat(ptr %s1, ...) nounwind { +; CHECK-LABEL: define ptr @cat( +; CHECK-SAME: ptr [[S1:%.*]], ...) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 undef, label [[BB:%.*]], label [[BB3:%.*]] +; CHECK: bb: +; CHECK-NEXT: unreachable +; CHECK: bb3: +; CHECK-NEXT: store ptr undef, ptr undef, align 4 +; CHECK-NEXT: br i1 undef, label [[BB5:%.*]], label [[BB6:%.*]] +; CHECK: bb5: +; CHECK-NEXT: unreachable +; CHECK: bb6: +; CHECK-NEXT: br label [[BB12:%.*]] +; CHECK: bb8: +; CHECK-NEXT: br i1 undef, label [[BB9:%.*]], label [[BB10:%.*]] +; CHECK: bb9: +; CHECK-NEXT: br label [[BB11:%.*]] +; CHECK: bb10: +; CHECK-NEXT: br label [[BB11]] +; CHECK: bb11: +; CHECK-NEXT: br label [[BB12]] +; CHECK: bb12: +; CHECK-NEXT: br i1 undef, label [[BB8:%.*]], label [[BB13:%.*]] +; CHECK: bb13: +; CHECK-NEXT: ret ptr undef +; entry: br i1 undef, label %bb, label %bb3 diff --git a/llvm/test/Transforms/NewGVN/2010-05-08-OneBit.ll b/llvm/test/Transforms/NewGVN/2010-05-08-OneBit.ll index 0d2d45a5e0d9ff733ec5c7fe3505f06661a7d31d..0a121ffab761f4623a97c8496ba7043539cf55ce 100644 --- a/llvm/test/Transforms/NewGVN/2010-05-08-OneBit.ll +++ b/llvm/test/Transforms/NewGVN/2010-05-08-OneBit.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn ; PR7052 @@ -12,7 +13,7 @@ entry: l117.i.i: ; preds = %entry invoke fastcc void @foo() - to label %.noexc5 unwind label %landing_pad + to label %.noexc5 unwind label %landing_pad .noexc5: ; preds = %l117.i.i unreachable @@ -22,7 +23,7 @@ k121.i.i: ; preds = %entry l129.i.i: ; preds = %k121.i.i invoke fastcc void @foo() - to label %.noexc7 unwind label %landing_pad + to label %.noexc7 unwind label %landing_pad .noexc7: ; preds = %l129.i.i unreachable @@ -34,7 +35,7 @@ k133.i.i: ; preds = %k121.i.i l147.i.i: ; preds = %k133.i.i invoke fastcc void @foo() - to label %.noexc10 unwind label %landing_pad + to label %.noexc10 unwind label %landing_pad .noexc10: ; preds = %l147.i.i unreachable @@ -44,10 +45,10 @@ k151.i.i: ; preds = %k133.i.i landing_pad: ; preds = %l147.i.i, %l129.i.i, %l117.i.i %exn = landingpad {ptr, i32} - cleanup + cleanup switch i32 undef, label %fin [ - i32 1, label %catch1 - i32 2, label %catch + i32 1, label %catch1 + i32 2, label %catch ] fin: ; preds = %landing_pad diff --git a/llvm/test/Transforms/NewGVN/2010-11-13-Simplify.ll b/llvm/test/Transforms/NewGVN/2010-11-13-Simplify.ll index b06570b0ebf8dd7e74e5215b02a898e6e6b123e4..3d12783ee53cc7d4a263d613d9ddce41f39bc785 100644 --- a/llvm/test/Transforms/NewGVN/2010-11-13-Simplify.ll +++ b/llvm/test/Transforms/NewGVN/2010-11-13-Simplify.ll @@ -1,9 +1,14 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn -S | FileCheck %s declare i32 @foo(i32) readnone define i1 @bar() { -; CHECK-LABEL: @bar( +; CHECK-LABEL: define i1 @bar() { +; CHECK-NEXT: [[A:%.*]] = call i32 @foo(i32 0) #[[ATTR0:[0-9]+]] +; CHECK-NEXT: [[X:%.*]] = call i32 @foo(i32 [[A]]) #[[ATTR0]] +; CHECK-NEXT: ret i1 true +; %a = call i32 @foo (i32 0) readnone %b = call i32 @foo (i32 0) readnone %c = and i32 %a, %b @@ -11,5 +16,4 @@ define i1 @bar() { %y = call i32 @foo (i32 %c) readnone %z = icmp eq i32 %x, %y ret i1 %z -; CHECK: ret i1 true -} +} diff --git a/llvm/test/Transforms/NewGVN/2011-04-27-phioperands.ll b/llvm/test/Transforms/NewGVN/2011-04-27-phioperands.ll index 3e8a5d84405eafa3570e11097c0e9296fae873ab..c039422be84ed1303fa62096b4f3177a77e16251 100644 --- a/llvm/test/Transforms/NewGVN/2011-04-27-phioperands.ll +++ b/llvm/test/Transforms/NewGVN/2011-04-27-phioperands.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -disable-output < %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-f128:128:128-n8:16:32:64" @@ -64,10 +65,10 @@ doemit.exit76.i: "<bb 64>.i": switch i32 undef, label %"<bb 5>" [ - i32 42, label %"<L54>.i" - i32 43, label %"<L55>.i" - i32 63, label %"<L56>.i" - i32 123, label %"<bb 5>.i258.i" + i32 42, label %"<L54>.i" + i32 43, label %"<L55>.i" + i32 63, label %"<L56>.i" + i32 123, label %"<bb 5>.i258.i" ] "<L54>.i": @@ -93,14 +94,14 @@ doemit.exit127.i: "<bb 5>": switch i32 undef, label %"<L39>.i" [ - i32 36, label %"<L19>.i" - i32 94, label %"<L18>.i" - i32 124, label %"<L98>.i" - i32 42, label %"<L99>.i" - i32 43, label %"<L99>.i" - i32 46, label %"<L24>.i" - i32 63, label %"<L99>.i" - i32 91, label %"<L28>.i" - i32 92, label %"<L29>.i" + i32 36, label %"<L19>.i" + i32 94, label %"<L18>.i" + i32 124, label %"<L98>.i" + i32 42, label %"<L99>.i" + i32 43, label %"<L99>.i" + i32 46, label %"<L24>.i" + i32 63, label %"<L99>.i" + i32 91, label %"<L28>.i" + i32 92, label %"<L29>.i" ] } diff --git a/llvm/test/Transforms/NewGVN/2011-07-07-MatchIntrinsicExtract.ll b/llvm/test/Transforms/NewGVN/2011-07-07-MatchIntrinsicExtract.ll index c547e8fac5e583be1799503295fb919ccf4b18f4..444385d81ab4165fc13b31ec51aac908faf485dd 100644 --- a/llvm/test/Transforms/NewGVN/2011-07-07-MatchIntrinsicExtract.ll +++ b/llvm/test/Transforms/NewGVN/2011-07-07-MatchIntrinsicExtract.ll @@ -1,9 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn -S | FileCheck %s ; %0 = type { i64, i1 } define i64 @test1(i64 %a, i64 %b) nounwind ssp { +; CHECK-LABEL: define i64 @test1( +; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[A]], i64 [[B]]) +; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i64, i1 } [[TMP0]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[TMP0]] poison, i64 [[TMP1]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1 +; CHECK-NEXT: [[TMP4:%.*]] = insertvalue [[TMP0]] [[TMP2]], i1 [[TMP3]], 1 +; CHECK-NEXT: [[UADD_0:%.*]] = extractvalue [[TMP0]] [[TMP4]], 0 +; CHECK-NEXT: [[ADD2:%.*]] = add i64 [[TMP1]], [[UADD_0]] +; CHECK-NEXT: ret i64 [[ADD2]] +; entry: %uadd = tail call %0 @llvm.uadd.with.overflow.i64(i64 %a, i64 %b) %uadd.0 = extractvalue %0 %uadd, 0 @@ -12,11 +25,20 @@ entry: ret i64 %add2 } -; CHECK-LABEL: @test1( -; CHECK-NOT: add1 -; CHECK: ret define i64 @test2(i64 %a, i64 %b) nounwind ssp { +; CHECK-LABEL: define i64 @test2( +; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[A]], i64 [[B]]) +; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i64, i1 } [[TMP0]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[TMP0]] poison, i64 [[TMP1]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1 +; CHECK-NEXT: [[TMP4:%.*]] = insertvalue [[TMP0]] [[TMP2]], i1 [[TMP3]], 1 +; CHECK-NEXT: [[USUB_0:%.*]] = extractvalue [[TMP0]] [[TMP4]], 0 +; CHECK-NEXT: [[ADD2:%.*]] = add i64 [[TMP1]], [[USUB_0]] +; CHECK-NEXT: ret i64 [[ADD2]] +; entry: %usub = tail call %0 @llvm.usub.with.overflow.i64(i64 %a, i64 %b) %usub.0 = extractvalue %0 %usub, 0 @@ -25,11 +47,20 @@ entry: ret i64 %add2 } -; CHECK-LABEL: @test2( -; CHECK-NOT: sub1 -; CHECK: ret define i64 @test3(i64 %a, i64 %b) nounwind ssp { +; CHECK-LABEL: define i64 @test3( +; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 [[A]], i64 [[B]]) +; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i64, i1 } [[TMP0]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[TMP0]] poison, i64 [[TMP1]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1 +; CHECK-NEXT: [[TMP4:%.*]] = insertvalue [[TMP0]] [[TMP2]], i1 [[TMP3]], 1 +; CHECK-NEXT: [[UMUL_0:%.*]] = extractvalue [[TMP0]] [[TMP4]], 0 +; CHECK-NEXT: [[ADD2:%.*]] = add i64 [[TMP1]], [[UMUL_0]] +; CHECK-NEXT: ret i64 [[ADD2]] +; entry: %umul = tail call %0 @llvm.umul.with.overflow.i64(i64 %a, i64 %b) %umul.0 = extractvalue %0 %umul, 0 @@ -38,11 +69,20 @@ entry: ret i64 %add2 } -; CHECK-LABEL: @test3( -; CHECK-NOT: mul1 -; CHECK: ret define i64 @test4(i64 %a, i64 %b) nounwind ssp { +; CHECK-LABEL: define i64 @test4( +; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 [[A]], i64 [[B]]) +; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i64, i1 } [[TMP0]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[TMP0]] poison, i64 [[TMP1]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1 +; CHECK-NEXT: [[TMP4:%.*]] = insertvalue [[TMP0]] [[TMP2]], i1 [[TMP3]], 1 +; CHECK-NEXT: [[SADD_0:%.*]] = extractvalue [[TMP0]] [[TMP4]], 0 +; CHECK-NEXT: [[ADD2:%.*]] = add i64 [[TMP1]], [[SADD_0]] +; CHECK-NEXT: ret i64 [[ADD2]] +; entry: %sadd = tail call %0 @llvm.sadd.with.overflow.i64(i64 %a, i64 %b) %sadd.0 = extractvalue %0 %sadd, 0 @@ -51,11 +91,20 @@ entry: ret i64 %add2 } -; CHECK-LABEL: @test4( -; CHECK-NOT: add1 -; CHECK: ret define i64 @test5(i64 %a, i64 %b) nounwind ssp { +; CHECK-LABEL: define i64 @test5( +; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = call { i64, i1 } @llvm.ssub.with.overflow.i64(i64 [[A]], i64 [[B]]) +; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i64, i1 } [[TMP0]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[TMP0]] poison, i64 [[TMP1]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1 +; CHECK-NEXT: [[TMP4:%.*]] = insertvalue [[TMP0]] [[TMP2]], i1 [[TMP3]], 1 +; CHECK-NEXT: [[SSUB_0:%.*]] = extractvalue [[TMP0]] [[TMP4]], 0 +; CHECK-NEXT: [[ADD2:%.*]] = add i64 [[TMP1]], [[SSUB_0]] +; CHECK-NEXT: ret i64 [[ADD2]] +; entry: %ssub = tail call %0 @llvm.ssub.with.overflow.i64(i64 %a, i64 %b) %ssub.0 = extractvalue %0 %ssub, 0 @@ -64,11 +113,20 @@ entry: ret i64 %add2 } -; CHECK-LABEL: @test5( -; CHECK-NOT: sub1 -; CHECK: ret define i64 @test6(i64 %a, i64 %b) nounwind ssp { +; CHECK-LABEL: define i64 @test6( +; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 [[A]], i64 [[B]]) +; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { i64, i1 } [[TMP0]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = insertvalue [[TMP0]] poison, i64 [[TMP1]], 0 +; CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1 +; CHECK-NEXT: [[TMP4:%.*]] = insertvalue [[TMP0]] [[TMP2]], i1 [[TMP3]], 1 +; CHECK-NEXT: [[SMUL_0:%.*]] = extractvalue [[TMP0]] [[TMP4]], 0 +; CHECK-NEXT: [[ADD2:%.*]] = add i64 [[TMP1]], [[SMUL_0]] +; CHECK-NEXT: ret i64 [[ADD2]] +; entry: %smul = tail call %0 @llvm.smul.with.overflow.i64(i64 %a, i64 %b) %smul.0 = extractvalue %0 %smul, 0 @@ -77,9 +135,6 @@ entry: ret i64 %add2 } -; CHECK-LABEL: @test6( -; CHECK-NOT: mul1 -; CHECK: ret declare void @exit(i32) noreturn declare %0 @llvm.uadd.with.overflow.i64(i64, i64) nounwind readnone diff --git a/llvm/test/Transforms/NewGVN/2011-09-07-TypeIdFor.ll b/llvm/test/Transforms/NewGVN/2011-09-07-TypeIdFor.ll index 46e3c2830920ce626f63617b0f1fb48837b1326d..675e7da26a1059f101d2d939b8605c849075b177 100644 --- a/llvm/test/Transforms/NewGVN/2011-09-07-TypeIdFor.ll +++ b/llvm/test/Transforms/NewGVN/2011-09-07-TypeIdFor.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn -S | FileCheck %s %struct.__fundamental_type_info_pseudo = type { %struct.__type_info_pseudo } %struct.__type_info_pseudo = type { ptr, ptr } @@ -18,26 +19,70 @@ declare void @__cxa_end_catch() declare i32 @__gxx_personality_v0(i32, i64, ptr, ptr) define void @_Z3foov() uwtable personality ptr @__gxx_personality_v0 { +; CHECK-LABEL: define void @_Z3foov( +; CHECK-SAME: ) #[[ATTR2:[0-9]+]] personality ptr @__gxx_personality_v0 { +; CHECK-NEXT: entry: +; CHECK-NEXT: invoke void @_Z4barv() +; CHECK-NEXT: to label [[RETURN:%.*]] unwind label [[LPAD:%.*]] +; CHECK: lpad: +; CHECK-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 } +; CHECK-NEXT: catch ptr @_ZTIi +; CHECK-NEXT: catch ptr @_ZTIb +; CHECK-NEXT: catch ptr @_ZTIi +; CHECK-NEXT: catch ptr @_ZTIb +; CHECK-NEXT: [[EXC_PTR2_I:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0 +; CHECK-NEXT: [[FILTER3_I:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1 +; CHECK-NEXT: [[TYPEID_I:%.*]] = tail call i32 @llvm.eh.typeid.for(ptr @_ZTIi) +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[FILTER3_I]], [[TYPEID_I]] +; CHECK-NEXT: br i1 [[TMP1]], label [[PPAD:%.*]], label [[NEXT:%.*]] +; CHECK: next: +; CHECK-NEXT: [[TYPEID1_I:%.*]] = tail call i32 @llvm.eh.typeid.for(ptr @_ZTIb) +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[FILTER3_I]], [[TYPEID1_I]] +; CHECK-NEXT: br i1 [[TMP2]], label [[PPAD2:%.*]], label [[NEXT2:%.*]] +; CHECK: ppad: +; CHECK-NEXT: [[TMP3:%.*]] = tail call ptr @__cxa_begin_catch(ptr [[EXC_PTR2_I]]) #[[ATTR1:[0-9]+]] +; CHECK-NEXT: tail call void @__cxa_end_catch() #[[ATTR1]] +; CHECK-NEXT: br label [[RETURN]] +; CHECK: ppad2: +; CHECK-NEXT: [[D_2073_5_I:%.*]] = tail call ptr @__cxa_begin_catch(ptr [[EXC_PTR2_I]]) #[[ATTR1]] +; CHECK-NEXT: tail call void @__cxa_end_catch() #[[ATTR1]] +; CHECK-NEXT: br label [[RETURN]] +; CHECK: next2: +; CHECK-NEXT: call void @_Z7cleanupv() +; CHECK-NEXT: br i1 [[TMP1]], label [[PPAD3:%.*]], label [[NEXT3:%.*]] +; CHECK: next3: +; CHECK-NEXT: br i1 [[TMP2]], label [[PPAD4:%.*]], label [[UNWIND:%.*]] +; CHECK: unwind: +; CHECK-NEXT: resume { ptr, i32 } [[TMP0]] +; CHECK: ppad3: +; CHECK-NEXT: [[TMP4:%.*]] = tail call ptr @__cxa_begin_catch(ptr [[EXC_PTR2_I]]) #[[ATTR1]] +; CHECK-NEXT: tail call void @__cxa_end_catch() #[[ATTR1]] +; CHECK-NEXT: br label [[RETURN]] +; CHECK: ppad4: +; CHECK-NEXT: [[D_2080_5:%.*]] = tail call ptr @__cxa_begin_catch(ptr [[EXC_PTR2_I]]) #[[ATTR1]] +; CHECK-NEXT: tail call void @__cxa_end_catch() #[[ATTR1]] +; CHECK-NEXT: br label [[RETURN]] +; CHECK: return: +; CHECK-NEXT: ret void +; entry: invoke void @_Z4barv() - to label %return unwind label %lpad + to label %return unwind label %lpad lpad: ; preds = %entry %0 = landingpad { ptr, i32 } - catch ptr @_ZTIi - catch ptr @_ZTIb - catch ptr @_ZTIi - catch ptr @_ZTIb + catch ptr @_ZTIi + catch ptr @_ZTIb + catch ptr @_ZTIi + catch ptr @_ZTIb %exc_ptr2.i = extractvalue { ptr, i32 } %0, 0 %filter3.i = extractvalue { ptr, i32 } %0, 1 %typeid.i = tail call i32 @llvm.eh.typeid.for(ptr @_ZTIi) -; CHECK: call i32 @llvm.eh.typeid.for %1 = icmp eq i32 %filter3.i, %typeid.i br i1 %1, label %ppad, label %next next: ; preds = %lpad %typeid1.i = tail call i32 @llvm.eh.typeid.for(ptr @_ZTIb) -; CHECK: call i32 @llvm.eh.typeid.for %2 = icmp eq i32 %filter3.i, %typeid1.i br i1 %2, label %ppad2, label %next2 @@ -54,7 +99,6 @@ ppad2: ; preds = %next next2: ; preds = %next call void @_Z7cleanupv() %typeid = tail call i32 @llvm.eh.typeid.for(ptr @_ZTIi) -; CHECK-NOT: call i32 @llvm.eh.typeid.for %4 = icmp eq i32 %filter3.i, %typeid br i1 %4, label %ppad3, label %next3 diff --git a/llvm/test/Transforms/NewGVN/2012-05-22-PreCrash.ll b/llvm/test/Transforms/NewGVN/2012-05-22-PreCrash.ll index 787a3ba70325e65833fceb90d0ea3990a3431a85..1357f2b809f74855d91cbb7bcd7db8341b59401e 100644 --- a/llvm/test/Transforms/NewGVN/2012-05-22-PreCrash.ll +++ b/llvm/test/Transforms/NewGVN/2012-05-22-PreCrash.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn ; PR12858 diff --git a/llvm/test/Transforms/NewGVN/2016-08-30-MaskedScatterGather-xfail-inseltpoison.ll b/llvm/test/Transforms/NewGVN/2016-08-30-MaskedScatterGather-xfail-inseltpoison.ll index 2fb275d7aaf4dea3bc79fa6ea5d91f3930d73bc0..7b3f33bd4dbea707d718cfc5860d24eefab03187 100644 --- a/llvm/test/Transforms/NewGVN/2016-08-30-MaskedScatterGather-xfail-inseltpoison.ll +++ b/llvm/test/Transforms/NewGVN/2016-08-30-MaskedScatterGather-xfail-inseltpoison.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; XFAIL: * ; RUN: opt < %s -passes=newgvn -S | FileCheck %s @@ -14,6 +15,25 @@ declare <2 x i32> @llvm.masked.gather.v2i32.v2p0(<2 x ptr>, i32, <2 x i1>, <2 x ; CHECK: llvm.masked.scatter ; CHECK: llvm.masked.gather define spir_kernel void @test(<2 x ptr> %in1, <2 x ptr> %in2, ptr %out) { +; CHECK-LABEL: define spir_kernel void @test( +; CHECK-SAME: <2 x ptr> [[IN1:%.*]], <2 x ptr> [[IN2:%.*]], ptr [[OUT:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP_0:%.*]] = alloca i32, align 4 +; CHECK-NEXT: [[TMP_1:%.*]] = alloca i32, align 4 +; CHECK-NEXT: [[TMP_I:%.*]] = insertelement <2 x ptr> poison, ptr [[TMP_0]], i32 0 +; CHECK-NEXT: [[TMP:%.*]] = insertelement <2 x ptr> [[TMP_I]], ptr [[TMP_1]], i32 1 +; CHECK-NEXT: [[IN1_V:%.*]] = call <2 x i32> @llvm.masked.gather.v2i32.v2p0(<2 x ptr> [[IN1]], i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) +; CHECK-NEXT: [[IN2_V:%.*]] = call <2 x i32> @llvm.masked.gather.v2i32.v2p0(<2 x ptr> [[IN2]], i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) +; CHECK-NEXT: call void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> [[IN1_V]], <2 x ptr> [[TMP]], i32 1, <2 x i1> <i1 true, i1 true>) +; CHECK-NEXT: call void @llvm.masked.scatter.v2i32.v2p0(<2 x i32> [[IN2_V]], <2 x ptr> [[TMP]], i32 1, <2 x i1> <i1 true, i1 true>) +; CHECK-NEXT: [[TMP_V_1:%.*]] = call <2 x i32> @llvm.masked.gather.v2i32.v2p0(<2 x ptr> [[TMP]], i32 1, <2 x i1> <i1 true, i1 true>, <2 x i32> undef) +; CHECK-NEXT: [[TMP_V_1_0:%.*]] = extractelement <2 x i32> [[TMP_V_1]], i32 0 +; CHECK-NEXT: [[TMP_V_1_1:%.*]] = extractelement <2 x i32> [[TMP_V_1]], i32 1 +; CHECK-NEXT: store i32 [[TMP_V_1_0]], ptr [[OUT]], align 4 +; CHECK-NEXT: [[OUT_1:%.*]] = getelementptr i32, ptr [[OUT]], i32 1 +; CHECK-NEXT: store i32 [[TMP_V_1_1]], ptr [[OUT_1]], align 4 +; CHECK-NEXT: ret void +; entry: ; Just some temporary storage %tmp.0 = alloca i32 diff --git a/llvm/test/Transforms/NewGVN/MemdepMiscompile.ll b/llvm/test/Transforms/NewGVN/MemdepMiscompile.ll index f2d1827d87b0d0d58e13c4fca526733bed4a4bdc..a3f1f4d8182fb36617a05cfa46767891eefcd655 100644 --- a/llvm/test/Transforms/NewGVN/MemdepMiscompile.ll +++ b/llvm/test/Transforms/NewGVN/MemdepMiscompile.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-apple-macosx10.7.0" @@ -7,14 +8,38 @@ target triple = "x86_64-apple-macosx10.7.0" ; Make sure we do not replace load %shouldExit in while.cond.backedge ; with a phi node where the value from while.body is 0. define i32 @test() nounwind ssp { +; CHECK-LABEL: define i32 @test( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SHOULDEXIT:%.*]] = alloca i32, align 4 +; CHECK-NEXT: [[TASKSIDLE:%.*]] = alloca i32, align 4 +; CHECK-NEXT: store i32 0, ptr [[SHOULDEXIT]], align 4 +; CHECK-NEXT: store i32 0, ptr [[TASKSIDLE]], align 4 +; CHECK-NEXT: call void @CTestInitialize(ptr [[TASKSIDLE]]) #[[ATTR1:[0-9]+]] +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[SHOULDEXIT]], align 4 +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[TMP0]], 0 +; CHECK-NEXT: br i1 [[CMP1]], label [[WHILE_BODY_LR_PH:%.*]], label [[WHILE_END:%.*]] +; CHECK: while.body.lr.ph: +; CHECK-NEXT: br label [[WHILE_BODY:%.*]] +; CHECK: while.body: +; CHECK-NEXT: call void @RunInMode(i32 100) #[[ATTR1]] +; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[TASKSIDLE]], align 4 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TMP1]], 0 +; CHECK-NEXT: br i1 [[TOBOOL]], label [[WHILE_COND_BACKEDGE:%.*]], label [[IF_THEN:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i32 0, ptr [[TASKSIDLE]], align 4 +; CHECK-NEXT: call void @TimerCreate(ptr [[SHOULDEXIT]]) #[[ATTR1]] +; CHECK-NEXT: br label [[WHILE_COND_BACKEDGE]] +; CHECK: while.cond.backedge: +; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[SHOULDEXIT]], align 4 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY]], label [[WHILE_COND_WHILE_END_CRIT_EDGE:%.*]] +; CHECK: while.cond.while.end_crit_edge: +; CHECK-NEXT: br label [[WHILE_END]] +; CHECK: while.end: +; CHECK-NEXT: ret i32 0 +; entry: -; CHECK: test() -; CHECK: while.body: -; CHECK: call void @RunInMode -; CHECK: br i1 %tobool, label %while.cond.backedge, label %if.then -; CHECK: while.cond.backedge: -; CHECK: load i32, ptr %shouldExit -; CHECK: br i1 %cmp, label %while.body %shouldExit = alloca i32, align 4 %tasksIdle = alloca i32, align 4 store i32 0, ptr %shouldExit, align 4 diff --git a/llvm/test/Transforms/NewGVN/addrspacecast.ll b/llvm/test/Transforms/NewGVN/addrspacecast.ll index fea8a2f3f85869ea1d85adf755c6260a3cd1af9b..394db28425d98b9892e67395ccd4ad69ed549e57 100644 --- a/llvm/test/Transforms/NewGVN/addrspacecast.ll +++ b/llvm/test/Transforms/NewGVN/addrspacecast.ll @@ -7,7 +7,7 @@ define ptr addrspace(1) @addrspacecast(ptr %ptr) { ; CHECK-NEXT: [[Z1:%.*]] = addrspacecast ptr [[PTR:%.*]] to ptr addrspace(1) ; CHECK-NEXT: br label [[BLOCK2:%.*]] ; CHECK: block2: -; CHECK-NEXT: store ptr addrspace(1) [[Z1]], ptr undef +; CHECK-NEXT: store ptr addrspace(1) [[Z1]], ptr undef, align 8 ; CHECK-NEXT: ret ptr addrspace(1) [[Z1]] ; block1: @@ -29,7 +29,7 @@ define ptr addrspace(1) @addrspacecast_different_result_types(ptr %ptr) { ; CHECK-NEXT: br label [[BLOCK2:%.*]] ; CHECK: block2: ; CHECK-NEXT: [[Z2:%.*]] = addrspacecast ptr [[PTR]] to ptr addrspace(1) -; CHECK-NEXT: store ptr addrspace(2) [[Z1]], ptr undef +; CHECK-NEXT: store ptr addrspace(2) [[Z1]], ptr undef, align 8 ; CHECK-NEXT: ret ptr addrspace(1) [[Z2]] ; block1: @@ -48,7 +48,7 @@ define ptr addrspace(1) @addrspacecast_simplify(ptr addrspace(1) %ptr) { ; CHECK-NEXT: [[CAST0:%.*]] = addrspacecast ptr addrspace(1) [[PTR:%.*]] to ptr ; CHECK-NEXT: br label [[BLOCK2:%.*]] ; CHECK: block2: -; CHECK-NEXT: store ptr addrspace(1) [[PTR]], ptr undef +; CHECK-NEXT: store ptr addrspace(1) [[PTR]], ptr undef, align 8 ; CHECK-NEXT: ret ptr addrspace(1) [[PTR]] ; block1: @@ -70,7 +70,7 @@ define ptr addrspace(1) @addrspacecast_constant() { ; CHECK-NEXT: store ptr undef, ptr @h, align 4 ; CHECK-NEXT: br label [[BLOCK2:%.*]] ; CHECK: block2: -; CHECK-NEXT: store ptr addrspace(1) undef, ptr undef +; CHECK-NEXT: store ptr addrspace(1) undef, ptr undef, align 8 ; CHECK-NEXT: ret ptr addrspace(1) undef ; block1: @@ -88,11 +88,11 @@ block2: define ptr addrspace(1) @addrspacecast_leader(ptr %arg.ptr) { ; CHECK-LABEL: @addrspacecast_leader( ; CHECK-NEXT: block1: -; CHECK-NEXT: [[LOAD0:%.*]] = load ptr, ptr [[ARG_PTR:%.*]] +; CHECK-NEXT: [[LOAD0:%.*]] = load ptr, ptr [[ARG_PTR:%.*]], align 8 ; CHECK-NEXT: [[Z1:%.*]] = addrspacecast ptr [[LOAD0]] to ptr addrspace(1) ; CHECK-NEXT: br label [[BLOCK2:%.*]] ; CHECK: block2: -; CHECK-NEXT: store ptr addrspace(1) [[Z1]], ptr undef +; CHECK-NEXT: store ptr addrspace(1) [[Z1]], ptr undef, align 8 ; CHECK-NEXT: ret ptr addrspace(1) [[Z1]] ; block1: diff --git a/llvm/test/Transforms/NewGVN/basic-cyclic-opt.ll b/llvm/test/Transforms/NewGVN/basic-cyclic-opt.ll index baef8b51fbc15ea6f474fbaa35a158a443f81b64..53190466963a195c4a0ff6f04b1befd25e56be92 100644 --- a/llvm/test/Transforms/NewGVN/basic-cyclic-opt.ll +++ b/llvm/test/Transforms/NewGVN/basic-cyclic-opt.ll @@ -245,7 +245,7 @@ bb23: ; preds = %bb4 define i8 @irreducible_memoryphi(ptr noalias %arg, ptr noalias %arg2) { ; CHECK-LABEL: @irreducible_memoryphi( ; CHECK-NEXT: bb: -; CHECK-NEXT: store i8 0, ptr [[ARG:%.*]] +; CHECK-NEXT: store i8 0, ptr [[ARG:%.*]], align 1 ; CHECK-NEXT: br i1 undef, label [[BB2:%.*]], label [[BB1:%.*]] ; CHECK: bb1: ; CHECK-NEXT: br label [[BB2]] diff --git a/llvm/test/Transforms/NewGVN/basic-undef-test.ll b/llvm/test/Transforms/NewGVN/basic-undef-test.ll index 5b731fc5f9fa07ec6dcd443ba10116a3c59e39b9..148c0227adf269d7c9a16b7effc70efa61c999f3 100644 --- a/llvm/test/Transforms/NewGVN/basic-undef-test.ll +++ b/llvm/test/Transforms/NewGVN/basic-undef-test.ll @@ -1,15 +1,21 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -S < %s | FileCheck %s ; ModuleID = 'test3.ll' target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" define i32 @main(ptr %foo) { +; CHECK-LABEL: define i32 @main( +; CHECK-SAME: ptr [[FOO:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[FOO]], align 4 +; CHECK-NEXT: store i32 5, ptr undef, align 4 +; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], [[TMP0]] +; CHECK-NEXT: ret i32 [[TMP1]] +; entry: -; CHECK: load i32, ptr %foo, align 4 %0 = load i32, ptr %foo, align 4 store i32 5, ptr undef, align 4 -; CHECK-NOT: load i32, ptr %foo, align 4 %1 = load i32, ptr %foo, align 4 -; CHECK: add i32 %0, %0 %2 = add i32 %0, %1 ret i32 %2 } diff --git a/llvm/test/Transforms/NewGVN/br-identical.ll b/llvm/test/Transforms/NewGVN/br-identical.ll index c99838525aa2d7dda792e4e83bdcda1e1ddbd493..23f43b01f443b688429d0eb9563dff6758533e5e 100644 --- a/llvm/test/Transforms/NewGVN/br-identical.ll +++ b/llvm/test/Transforms/NewGVN/br-identical.ll @@ -1,8 +1,32 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -S -o - %s | FileCheck %s ; If a branch has two identical successors, we cannot declare either dead. define void @widget(i1 %p) { +; CHECK-LABEL: define void @widget( +; CHECK-SAME: i1 [[P:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[BB2:%.*]] +; CHECK: bb2: +; CHECK-NEXT: [[T1:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[T2:%.*]], [[BB7:%.*]] ] +; CHECK-NEXT: [[T2]] = add i64 [[T1]], 1 +; CHECK-NEXT: [[T3:%.*]] = icmp ult i64 0, [[T2]] +; CHECK-NEXT: br i1 [[T3]], label [[BB3:%.*]], label [[BB4:%.*]] +; CHECK: bb3: +; CHECK-NEXT: [[T4:%.*]] = call i64 @f() +; CHECK-NEXT: br label [[BB4]] +; CHECK: bb4: +; CHECK-NEXT: br i1 [[P]], label [[BB5:%.*]], label [[BB6:%.*]] +; CHECK: bb5: +; CHECK-NEXT: br i1 true, label [[BB7]], label [[BB7]] +; CHECK: bb6: +; CHECK-NEXT: br i1 true, label [[BB7]], label [[BB7]] +; CHECK: bb7: +; CHECK-NEXT: br i1 [[P]], label [[BB2]], label [[BB8:%.*]] +; CHECK: bb8: +; CHECK-NEXT: ret void +; entry: br label %bb2 @@ -17,7 +41,6 @@ bb3: br label %bb4 bb4: - ; CHECK-NOT: phi {{.*}} undef %foo = phi i64 [ %t4, %bb3 ], [ 0, %bb2 ] br i1 %p, label %bb5, label %bb6 diff --git a/llvm/test/Transforms/NewGVN/calloc-load-removal.ll b/llvm/test/Transforms/NewGVN/calloc-load-removal.ll index a8a1e66d97d95fc0ee75ee7cc4a8fdbec0bb6abc..608f739e175fe304db8bf9b08c2d939e1d010ea3 100644 --- a/llvm/test/Transforms/NewGVN/calloc-load-removal.ll +++ b/llvm/test/Transforms/NewGVN/calloc-load-removal.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -S -passes=newgvn < %s | FileCheck %s ; Check that loads from calloc are recognized as being zero. @@ -5,14 +6,15 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3 ; Function Attrs: nounwind uwtable define i32 @test1() { +; CHECK-LABEL: define i32 @test1() { +; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias ptr @calloc(i64 1, i64 4) +; CHECK-NEXT: ret i32 0 +; %1 = tail call noalias ptr @calloc(i64 1, i64 4) ; This load is trivially constant zero %2 = load i32, ptr %1, align 4 ret i32 %2 -; CHECK-LABEL: @test1( -; CHECK-NOT: %2 = load i32, ptr %1, align 4 -; CHECK: ret i32 0 } declare noalias ptr @calloc(i64, i64) mustprogress nofree nounwind willreturn allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="malloc" diff --git a/llvm/test/Transforms/NewGVN/calls-readonly.ll b/llvm/test/Transforms/NewGVN/calls-readonly.ll index 68d74c1aeda7fd13ea09115375214410aeb3bd89..49f5d3aa685404a724379102b2439246006ba9ac 100644 --- a/llvm/test/Transforms/NewGVN/calls-readonly.ll +++ b/llvm/test/Transforms/NewGVN/calls-readonly.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn -S | FileCheck %s ; Should delete the second call to strlen even though the intervening strchr call exists. @@ -5,6 +6,22 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3 target triple = "i386-apple-darwin7" define ptr @test(ptr %P, ptr %Q, i32 %x, i32 %y) nounwind readonly { +; CHECK-LABEL: define ptr @test( +; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @strlen(ptr [[P]]) +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 0 +; CHECK-NEXT: br i1 [[TMP1]], label [[BB:%.*]], label [[BB1:%.*]] +; CHECK: bb: +; CHECK-NEXT: [[TMP2:%.*]] = sdiv i32 [[X]], [[Y]] +; CHECK-NEXT: br label [[BB1]] +; CHECK: bb1: +; CHECK-NEXT: [[X_ADDR_0:%.*]] = phi i32 [ [[TMP2]], [[BB]] ], [ [[X]], [[ENTRY:%.*]] ] +; CHECK-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr [[Q]], i32 97) +; CHECK-NEXT: [[TMP4:%.*]] = add i32 [[X_ADDR_0]], [[TMP0]] +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP3]], i32 [[X_ADDR_0]] +; CHECK-NEXT: ret ptr [[TMP5]] +; entry: %0 = tail call i32 @strlen(ptr %P) ; <i32> [#uses=2] %1 = icmp eq i32 %0, 0 ; <i1> [#uses=1] @@ -24,21 +41,6 @@ bb1: ; preds = %bb, %entry ret ptr %6 } -; CHECK: define ptr @test(ptr %P, ptr %Q, i32 %x, i32 %y) #0 { -; CHECK: entry: -; CHECK-NEXT: %0 = tail call i32 @strlen(ptr %P) -; CHECK-NEXT: %1 = icmp eq i32 %0, 0 -; CHECK-NEXT: br i1 %1, label %bb, label %bb1 -; CHECK: bb: -; CHECK-NEXT: %2 = sdiv i32 %x, %y -; CHECK-NEXT: br label %bb1 -; CHECK: bb1: -; CHECK-NEXT: %x_addr.0 = phi i32 [ %2, %bb ], [ %x, %entry ] -; CHECK-NEXT: %3 = tail call ptr @strchr(ptr %Q, i32 97) -; CHECK-NEXT: %4 = add i32 %x_addr.0, %0 -; CHECK-NEXT: %5 = getelementptr i8, ptr %3, i32 %x_addr.0 -; CHECK-NEXT: ret ptr %5 -; CHECK: } declare i32 @strlen(ptr) nounwind readonly diff --git a/llvm/test/Transforms/NewGVN/completeness.ll b/llvm/test/Transforms/NewGVN/completeness.ll index d968c785ceff0f478d47bc085a565bc82c89dd76..4841e2e958b281b3d88bd1ef7040e3a0a3d17954 100644 --- a/llvm/test/Transforms/NewGVN/completeness.ll +++ b/llvm/test/Transforms/NewGVN/completeness.ll @@ -6,9 +6,12 @@ define i32 @test1(i32, ptr) { ; CHECK-LABEL: @test1( ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP0:%.*]], 0 ; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]] -; CHECK: br label [[TMP6:%.*]] -; CHECK: br label [[TMP6]] -; CHECK: [[PHIOFOPS:%.*]] = phi i32 [ 105, [[TMP5]] ], [ 75, [[TMP4]] ] +; CHECK: 4: +; CHECK-NEXT: br label [[TMP6:%.*]] +; CHECK: 5: +; CHECK-NEXT: br label [[TMP6]] +; CHECK: 6: +; CHECK-NEXT: [[PHIOFOPS:%.*]] = phi i32 [ 105, [[TMP5]] ], [ 75, [[TMP4]] ] ; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ 5, [[TMP4]] ], [ 7, [[TMP5]] ] ; CHECK-NEXT: ret i32 [[PHIOFOPS]] ; @@ -31,9 +34,12 @@ define i32 @test1b(i32, ptr) { ; CHECK-LABEL: @test1b( ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP0:%.*]], 0 ; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]] -; CHECK: br label [[TMP6:%.*]] -; CHECK: br label [[TMP6]] -; CHECK: [[PHIOFOPS1:%.*]] = phi i32 [ 105, [[TMP5]] ], [ 75, [[TMP4]] ] +; CHECK: 4: +; CHECK-NEXT: br label [[TMP6:%.*]] +; CHECK: 5: +; CHECK-NEXT: br label [[TMP6]] +; CHECK: 6: +; CHECK-NEXT: [[PHIOFOPS1:%.*]] = phi i32 [ 105, [[TMP5]] ], [ 75, [[TMP4]] ] ; CHECK-NEXT: [[PHIOFOPS:%.*]] = phi i32 [ 1575, [[TMP5]] ], [ 1125, [[TMP4]] ] ; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ 5, [[TMP4]] ], [ 7, [[TMP5]] ] ; CHECK-NEXT: ret i32 [[PHIOFOPS]] @@ -58,9 +64,12 @@ define i32 @test2(i32) { ; CHECK-LABEL: @test2( ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP0:%.*]], 0 ; CHECK-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP4:%.*]] -; CHECK: br label [[TMP5:%.*]] -; CHECK: br label [[TMP5]] -; CHECK: [[DOT01:%.*]] = phi i32 [ 3, [[TMP3]] ], [ 2, [[TMP4]] ] +; CHECK: 3: +; CHECK-NEXT: br label [[TMP5:%.*]] +; CHECK: 4: +; CHECK-NEXT: br label [[TMP5]] +; CHECK: 5: +; CHECK-NEXT: [[DOT01:%.*]] = phi i32 [ 3, [[TMP3]] ], [ 2, [[TMP4]] ] ; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ 2, [[TMP3]] ], [ 3, [[TMP4]] ] ; CHECK-NEXT: ret i32 5 ; @@ -158,9 +167,12 @@ define i32 @test4(i32, ptr, ptr noalias, ptr noalias) { ; CHECK-NEXT: store i32 7, ptr [[TMP3:%.*]], align 4 ; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i32 [[TMP0:%.*]], 0 ; CHECK-NEXT: br i1 [[TMP5]], label [[TMP6:%.*]], label [[TMP7:%.*]] -; CHECK: br label [[TMP8:%.*]] -; CHECK: br label [[TMP8]] -; CHECK: [[DOT01:%.*]] = phi i32 [ 5, [[TMP6]] ], [ 7, [[TMP7]] ] +; CHECK: 6: +; CHECK-NEXT: br label [[TMP8:%.*]] +; CHECK: 7: +; CHECK-NEXT: br label [[TMP8]] +; CHECK: 8: +; CHECK-NEXT: [[DOT01:%.*]] = phi i32 [ 5, [[TMP6]] ], [ 7, [[TMP7]] ] ; CHECK-NEXT: [[DOT0:%.*]] = phi ptr [ [[TMP2]], [[TMP6]] ], [ [[TMP3]], [[TMP7]] ] ; CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[DOT0]], align 4 ; CHECK-NEXT: [[TMP10:%.*]] = mul nsw i32 [[TMP9]], 15 @@ -287,19 +299,19 @@ bb28: ; preds = %bb27, %bb define i8 @test6(ptr %addr) { ; CHECK-LABEL: @test6( ; CHECK-NEXT: entry-block: -; CHECK-NEXT: br label %main-loop +; CHECK-NEXT: br label [[MAIN_LOOP:%.*]] ; CHECK: main-loop: -; CHECK-NEXT: [[PHIOFOPS1:%.*]] = phi i1 [ true, %entry-block ], [ false, [[CORE:%.*]] ] -; CHECK-NEXT: [[PHIOFOPS:%.*]] = phi i1 [ false, %entry-block ], [ true, [[CORE]] ] -; CHECK-NEXT: [[PHI:%.*]] = phi i8 [ 0, %entry-block ], [ 1, [[CORE]] ] -; CHECK-NEXT: store volatile i8 0, ptr [[ADDR:%.*]] -; CHECK-NEXT: br i1 [[PHIOFOPS1]], label %busy-wait-phi-0, label [[EXIT:%.*]] +; CHECK-NEXT: [[PHIOFOPS1:%.*]] = phi i1 [ true, [[ENTRY_BLOCK:%.*]] ], [ false, [[CORE:%.*]] ] +; CHECK-NEXT: [[PHIOFOPS:%.*]] = phi i1 [ false, [[ENTRY_BLOCK]] ], [ true, [[CORE]] ] +; CHECK-NEXT: [[PHI:%.*]] = phi i8 [ 0, [[ENTRY_BLOCK]] ], [ 1, [[CORE]] ] +; CHECK-NEXT: store volatile i8 0, ptr [[ADDR:%.*]], align 1 +; CHECK-NEXT: br i1 [[PHIOFOPS1]], label [[BUSY_WAIT_PHI_0:%.*]], label [[EXIT:%.*]] ; CHECK: busy-wait-phi-0: -; CHECK-NEXT: [[LOAD:%.*]] = load volatile i8, ptr [[ADDR]] +; CHECK-NEXT: [[LOAD:%.*]] = load volatile i8, ptr [[ADDR]], align 1 ; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i8 [[LOAD]], 0 -; CHECK-NEXT: br i1 [[ICMP]], label %busy-wait-phi-0, label [[CORE]] +; CHECK-NEXT: br i1 [[ICMP]], label [[BUSY_WAIT_PHI_0]], label [[CORE]] ; CHECK: core: -; CHECK-NEXT: br i1 [[PHIOFOPS]], label [[TRAP:%.*]], label %main-loop +; CHECK-NEXT: br i1 [[PHIOFOPS]], label [[TRAP:%.*]], label [[MAIN_LOOP]] ; CHECK: trap: ; CHECK-NEXT: ret i8 1 ; CHECK: exit: @@ -507,13 +519,13 @@ declare ptr @wombat() define void @test12(ptr %p) { ; CHECK-LABEL: @test12( ; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = load i32, ptr %p +; CHECK-NEXT: [[TMP:%.*]] = load i32, ptr [[P:%.*]], align 4 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP]], 0 ; CHECK-NEXT: br i1 [[TMP1]], label [[BB2:%.*]], label [[BB8:%.*]] ; CHECK: bb2: ; CHECK-NEXT: br label [[BB3:%.*]] ; CHECK: bb3: -; CHECK-NEXT: br i1 true, label [[BB6:%.*]], label [[BB7]] +; CHECK-NEXT: br i1 true, label [[BB6:%.*]], label [[BB7:%.*]] ; CHECK: bb6: ; CHECK-NEXT: br label [[BB7]] ; CHECK: bb7: @@ -551,7 +563,7 @@ define void @test13() { ; CHECK-NEXT: bb: ; CHECK-NEXT: br label [[BB1:%.*]] ; CHECK: bb1: -; CHECK-NEXT: [[TMP:%.*]] = load i8, ptr null +; CHECK-NEXT: [[TMP:%.*]] = load i8, ptr null, align 1 ; CHECK-NEXT: br label [[BB3:%.*]] ; CHECK: bb3: ; CHECK-NEXT: [[PHIOFOPS:%.*]] = phi i8 [ [[TMP]], [[BB1]] ], [ [[TMP10:%.*]], [[BB3]] ] @@ -560,7 +572,7 @@ define void @test13() { ; CHECK-NEXT: [[TMP6]] = getelementptr i8, ptr [[TMP4]], i64 1 ; CHECK-NEXT: [[TMP8:%.*]] = sext i8 [[PHIOFOPS]] to i32 ; CHECK-NEXT: [[TMP9]] = mul i32 [[TMP5]], [[TMP8]] -; CHECK-NEXT: [[TMP10]] = load i8, ptr [[TMP6]] +; CHECK-NEXT: [[TMP10]] = load i8, ptr [[TMP6]], align 1 ; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i8 [[TMP10]], 0 ; CHECK-NEXT: br i1 [[TMP11]], label [[BB12:%.*]], label [[BB3]] ; CHECK: bb12: diff --git a/llvm/test/Transforms/NewGVN/cond_br.ll b/llvm/test/Transforms/NewGVN/cond_br.ll index 3dbeb394c7cfa702bf0e2b8f8d2505dedd2a91a9..930e5b30c08884c23feb6143da730b770b5f1418 100644 --- a/llvm/test/Transforms/NewGVN/cond_br.ll +++ b/llvm/test/Transforms/NewGVN/cond_br.ll @@ -1,12 +1,23 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -S < %s | FileCheck %s @y = external global i32 @z = external global i32 ; Function Attrs: nounwind ssp uwtable define void @foo(i32 %x) { -; CHECK: @foo(i32 %x) -; CHECK: %.pre = load i32, ptr @y -; CHECK: call void @bar(i32 %.pre) +; CHECK-LABEL: define void @foo( +; CHECK-SAME: i32 [[X:%.*]]) { +; CHECK-NEXT: [[DOTPRE:%.*]] = load i32, ptr @y, align 4 +; CHECK-NEXT: br i1 false, label [[IF_THEN:%.*]], label [[ENTRY_IF_END_CRIT_EDGE:%.*]] +; CHECK: entry.if.end_crit_edge: +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i8 poison, ptr null, align 1 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: tail call void @bar(i32 [[DOTPRE]]) +; CHECK-NEXT: ret void +; %t = sub i32 %x, %x %.pre = load i32, ptr @y, align 4 @@ -28,9 +39,21 @@ if.end: ; preds = %entry.if.end_crit_e } define void @foo2(i32 %x) { -; CHECK: @foo2(i32 %x) -; CHECK: %.pre = load i32, ptr @y -; CHECK: tail call void @bar(i32 %.pre) +; CHECK-LABEL: define void @foo2( +; CHECK-SAME: i32 [[X:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[DOTPRE:%.*]] = load i32, ptr @y, align 4 +; CHECK-NEXT: br i1 false, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i8 poison, ptr null, align 1 +; CHECK-NEXT: br label [[IF_END:%.*]] +; CHECK: if.else: +; CHECK-NEXT: store i32 1, ptr @z, align 4 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: tail call void @bar(i32 [[DOTPRE]]) +; CHECK-NEXT: ret void +; entry: %t = sub i32 %x, %x %.pre = load i32, ptr @y, align 4 diff --git a/llvm/test/Transforms/NewGVN/condprop.ll b/llvm/test/Transforms/NewGVN/condprop.ll index e685dfedab10959700c9fb12938738b06d7fb671..d97fd380c730b23340f6e12c9f1615b0c2baefa9 100644 --- a/llvm/test/Transforms/NewGVN/condprop.ll +++ b/llvm/test/Transforms/NewGVN/condprop.ll @@ -134,11 +134,11 @@ define void @test4(i1 %b, i32 %x) { ; CHECK-NEXT: br i1 [[B:%.*]], label [[SW:%.*]], label [[CASE3:%.*]] ; CHECK: sw: ; CHECK-NEXT: switch i32 [[X:%.*]], label [[DEFAULT:%.*]] [ -; CHECK-NEXT: i32 0, label [[CASE0:%.*]] -; CHECK-NEXT: i32 1, label [[CASE1:%.*]] -; CHECK-NEXT: i32 2, label [[CASE0]] -; CHECK-NEXT: i32 3, label [[CASE3]] -; CHECK-NEXT: i32 4, label [[DEFAULT]] +; CHECK-NEXT: i32 0, label [[CASE0:%.*]] +; CHECK-NEXT: i32 1, label [[CASE1:%.*]] +; CHECK-NEXT: i32 2, label [[CASE0]] +; CHECK-NEXT: i32 3, label [[CASE3]] +; CHECK-NEXT: i32 4, label [[DEFAULT]] ; CHECK-NEXT: ] ; CHECK: default: ; CHECK-NEXT: call void @bar(i32 [[X]]) diff --git a/llvm/test/Transforms/NewGVN/crash-no-aa.ll b/llvm/test/Transforms/NewGVN/crash-no-aa.ll index 55e2bcb00fb75876cdd6e6ab86289c89596179d6..30f2e379a376035efafaa656946277fe453ec9ef 100644 --- a/llvm/test/Transforms/NewGVN/crash-no-aa.ll +++ b/llvm/test/Transforms/NewGVN/crash-no-aa.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -disable-basic-aa -passes=newgvn -S < %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" diff --git a/llvm/test/Transforms/NewGVN/crash-usecounts.ll b/llvm/test/Transforms/NewGVN/crash-usecounts.ll index 5527beabbf34214c6f5300aab3ce23826f622d87..5cae740fd484c8e37db77c27261f00a6e9d6a949 100644 --- a/llvm/test/Transforms/NewGVN/crash-usecounts.ll +++ b/llvm/test/Transforms/NewGVN/crash-usecounts.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -disable-output < %s define void @test(i1 %arg, i1 %arg1) { diff --git a/llvm/test/Transforms/NewGVN/crash.ll b/llvm/test/Transforms/NewGVN/crash.ll index c886bd384eee2f41a6061ce07dd34b2cabb8ae31..26eaa766a0543499f2f5693736a863e7c3fd9966 100644 --- a/llvm/test/Transforms/NewGVN/crash.ll +++ b/llvm/test/Transforms/NewGVN/crash.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -disable-output < %s ; PR5631 @@ -106,7 +107,7 @@ if.then21.i: ret ptr undef do.body36.i: - %ivar38.i = load i64, ptr @g + %ivar38.i = load i64, ptr @g %add.ptr39.sum.i = add i64 %ivar38.i, 8 %tmp40.i = getelementptr inbounds i8, ptr %tmp18.i, i64 %add.ptr39.sum.i %tmp41.i = load i64, ptr %tmp40.i @@ -132,14 +133,14 @@ declare i32 @foo2() define i32 @test4() { entry: ret i32 0 - + dead: %P2 = getelementptr i32, ptr %P2, i32 52 %Q2 = getelementptr i32, ptr %Q2, i32 52 store i32 4, ptr %P2 %A = load i32, ptr %Q2 br i1 true, label %dead, label %dead2 - + dead2: ret i32 %A } diff --git a/llvm/test/Transforms/NewGVN/cyclic-phi-handling.ll b/llvm/test/Transforms/NewGVN/cyclic-phi-handling.ll index 4a2f0b972c9fe1a04498348516d57aeee0a1bd33..dc150799c849c6a818d111be30acb0c528ace425 100644 --- a/llvm/test/Transforms/NewGVN/cyclic-phi-handling.ll +++ b/llvm/test/Transforms/NewGVN/cyclic-phi-handling.ll @@ -5,15 +5,15 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" define void @foo(i32 %arg, i32 %arg1, ptr %arg2) { ; CHECK-LABEL: @foo( ; CHECK-NEXT: bb: -; CHECK-NEXT: br label %bb3 +; CHECK-NEXT: br label [[BB3:%.*]] ; CHECK: bb3: -; CHECK-NEXT: [[TMP:%.*]] = phi i32 [ %arg1, %bb ], [ [[TMP:%.*]]4, %bb7 ] -; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ %arg, %bb ], [ [[TMP]], %bb7 ] -; CHECK-NEXT: [[TMP5:%.*]] = call i32 %arg2(i32 [[TMP4]], i32 [[TMP]]) +; CHECK-NEXT: [[TMP:%.*]] = phi i32 [ [[ARG1:%.*]], [[BB:%.*]] ], [ [[TMP4:%.*]], [[BB7:%.*]] ] +; CHECK-NEXT: [[TMP4]] = phi i32 [ [[ARG:%.*]], [[BB]] ], [ [[TMP]], [[BB7]] ] +; CHECK-NEXT: [[TMP5:%.*]] = call i32 [[ARG2:%.*]](i32 [[TMP4]], i32 [[TMP]]) ; CHECK-NEXT: [[TMP6:%.*]] = icmp ne i32 [[TMP5]], 0 -; CHECK-NEXT: br i1 [[TMP6]], label %bb7, label %bb8 +; CHECK-NEXT: br i1 [[TMP6]], label [[BB7]], label [[BB8:%.*]] ; CHECK: bb7: -; CHECK-NEXT: br label %bb3 +; CHECK-NEXT: br label [[BB3]] ; CHECK: bb8: ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/NewGVN/dbg-redundant-load.ll b/llvm/test/Transforms/NewGVN/dbg-redundant-load.ll index 01d95aebdf2d41bcf5f786826530ffb129717b5b..cd2eca0de6d14026a31a7eb3ab2cf167839e4f11 100644 --- a/llvm/test/Transforms/NewGVN/dbg-redundant-load.ll +++ b/llvm/test/Transforms/NewGVN/dbg-redundant-load.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -S < %s | FileCheck %s ; Check that the redundant load from %if.then is removed. @@ -6,15 +7,22 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -; CHECK: @test_redundant_load( -; CHECK-LABEL: entry: -; CHECK-NEXT: load i32, ptr %Y, align 4, !dbg ![[LOC:[0-9]+]] -; CHECK-LABEL: if.then: -; CHECK-NOT: load -; CHECK-LABEL: if.end: -; CHECK: ![[LOC]] = !DILocation(line: 3, scope: !{{.*}}) define i32 @test_redundant_load(i32 %X, ptr %Y) !dbg !6 { +; CHECK-LABEL: define i32 @test_redundant_load( +; CHECK-SAME: i32 [[X:%.*]], ptr [[Y:%.*]]) !dbg [[DBG6:![0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[Y]], align 4, !dbg [[DBG8:![0-9]+]] +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], -1, !dbg [[DBG9:![0-9]+]] +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]], !dbg [[DBG9]] +; CHECK: if.then: +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP0]], !dbg [[DBG10:![0-9]+]] +; CHECK-NEXT: call void @foo(), !dbg [[DBG11:![0-9]+]] +; CHECK-NEXT: br label [[IF_END]], !dbg [[DBG12:![0-9]+]] +; CHECK: if.end: +; CHECK-NEXT: [[RESULT_0:%.*]] = phi i32 [ [[ADD]], [[IF_THEN]] ], [ [[TMP0]], [[ENTRY:%.*]] ] +; CHECK-NEXT: ret i32 [[RESULT_0]], !dbg [[DBG13:![0-9]+]] +; entry: %0 = load i32, ptr %Y, align 4, !dbg !8 %cmp = icmp sgt i32 %X, -1, !dbg !9 @@ -50,3 +58,16 @@ declare void @foo() !11 = !DILocation(line: 7, scope: !6) !12 = !DILocation(line: 8, scope: !6) !13 = !DILocation(line: 10, scope: !6) +;. +; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: [[META1:![0-9]+]], isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: [[META2:![0-9]+]]) +; CHECK: [[META1]] = !DIFile(filename: "test.cpp", directory: "") +; CHECK: [[META2]] = !{} +; CHECK: [[DBG6]] = distinct !DISubprogram(name: "test_redundant_load", scope: [[META1]], file: [[META1]], line: 2, type: [[META7:![0-9]+]], scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META2]]) +; CHECK: [[META7]] = !DISubroutineType(types: [[META2]]) +; CHECK: [[DBG8]] = !DILocation(line: 3, scope: [[DBG6]]) +; CHECK: [[DBG9]] = !DILocation(line: 5, scope: [[DBG6]]) +; CHECK: [[DBG10]] = !DILocation(line: 6, scope: [[DBG6]]) +; CHECK: [[DBG11]] = !DILocation(line: 7, scope: [[DBG6]]) +; CHECK: [[DBG12]] = !DILocation(line: 8, scope: [[DBG6]]) +; CHECK: [[DBG13]] = !DILocation(line: 10, scope: [[DBG6]]) +;. diff --git a/llvm/test/Transforms/NewGVN/edge.ll b/llvm/test/Transforms/NewGVN/edge.ll index 8699c85c9ed737f7c4f3695b0b7d80bae373861a..143e52cd139c5a3c21ecc0b571e60b20def7e1fc 100644 --- a/llvm/test/Transforms/NewGVN/edge.ll +++ b/llvm/test/Transforms/NewGVN/edge.ll @@ -1,7 +1,17 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -S < %s | FileCheck %s define i32 @f1(i32 %x) { - ; CHECK-LABEL: define i32 @f1( +; CHECK-LABEL: define i32 @f1( +; CHECK-SAME: i32 [[X:%.*]]) { +; CHECK-NEXT: bb0: +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[BB2:%.*]], label [[BB1:%.*]] +; CHECK: bb1: +; CHECK-NEXT: br label [[BB2]] +; CHECK: bb2: +; CHECK-NEXT: ret i32 [[X]] +; bb0: %cmp = icmp eq i32 %x, 0 br i1 %cmp, label %bb2, label %bb1 @@ -11,12 +21,19 @@ bb2: %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ] %foo = add i32 %cond, %x ret i32 %foo - ; CHECK: bb2: - ; CHECK: ret i32 %x } define i32 @f2(i32 %x) { - ; CHECK-LABEL: define i32 @f2( +; CHECK-LABEL: define i32 @f2( +; CHECK-SAME: i32 [[X:%.*]]) { +; CHECK-NEXT: bb0: +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[X]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[BB1:%.*]], label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: br label [[BB2]] +; CHECK: bb2: +; CHECK-NEXT: ret i32 [[X]] +; bb0: %cmp = icmp ne i32 %x, 0 br i1 %cmp, label %bb1, label %bb2 @@ -26,12 +43,20 @@ bb2: %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ] %foo = add i32 %cond, %x ret i32 %foo - ; CHECK: bb2: - ; CHECK: ret i32 %x } define i32 @f3(i32 %x) { - ; CHECK-LABEL: define i32 @f3( +; CHECK-LABEL: define i32 @f3( +; CHECK-SAME: i32 [[X:%.*]]) { +; CHECK-NEXT: bb0: +; CHECK-NEXT: switch i32 [[X]], label [[BB1:%.*]] [ +; CHECK-NEXT: i32 0, label [[BB2:%.*]] +; CHECK-NEXT: ] +; CHECK: bb1: +; CHECK-NEXT: br label [[BB2]] +; CHECK: bb2: +; CHECK-NEXT: ret i32 [[X]] +; bb0: switch i32 %x, label %bb1 [ i32 0, label %bb2] bb1: @@ -40,13 +65,21 @@ bb2: %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ] %foo = add i32 %cond, %x ret i32 %foo - ; CHECK: bb2: - ; CHECK: ret i32 %x } declare void @g(i1) define void @f4(ptr %x) { ; CHECK-LABEL: define void @f4( +; CHECK-SAME: ptr [[X:%.*]]) { +; CHECK-NEXT: bb0: +; CHECK-NEXT: [[Y:%.*]] = icmp eq ptr null, [[X]] +; CHECK-NEXT: br i1 [[Y]], label [[BB2:%.*]], label [[BB1:%.*]] +; CHECK: bb1: +; CHECK-NEXT: br label [[BB2]] +; CHECK: bb2: +; CHECK-NEXT: call void @g(i1 [[Y]]) +; CHECK-NEXT: ret void +; bb0: %y = icmp eq ptr null, %x br i1 %y, label %bb2, label %bb1 @@ -55,11 +88,22 @@ bb1: bb2: %zed = icmp eq ptr null, %x call void @g(i1 %zed) -; CHECK: call void @g(i1 %y) ret void } define double @fcmp_oeq_not_zero(double %x, double %y) { +; CHECK-LABEL: define double @fcmp_oeq_not_zero( +; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[Y]], 2.000000e+00 +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[RETURN:%.*]] +; CHECK: if: +; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], 2.000000e+00 +; CHECK-NEXT: br label [[RETURN]] +; CHECK: return: +; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[IF]] ], [ [[X]], [[ENTRY:%.*]] ] +; CHECK-NEXT: ret double [[RETVAL]] +; entry: %cmp = fcmp oeq double %y, 2.0 br i1 %cmp, label %if, label %return @@ -72,11 +116,21 @@ return: %retval = phi double [ %div, %if ], [ %x, %entry ] ret double %retval -; CHECK-LABEL: define double @fcmp_oeq_not_zero( -; CHECK: %div = fdiv double %x, 2.0 } define double @fcmp_une_not_zero(double %x, double %y) { +; CHECK-LABEL: define double @fcmp_une_not_zero( +; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[Y]], 2.000000e+00 +; CHECK-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[ELSE:%.*]] +; CHECK: else: +; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], 2.000000e+00 +; CHECK-NEXT: br label [[RETURN]] +; CHECK: return: +; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[ELSE]] ], [ [[X]], [[ENTRY:%.*]] ] +; CHECK-NEXT: ret double [[RETVAL]] +; entry: %cmp = fcmp une double %y, 2.0 br i1 %cmp, label %return, label %else @@ -89,14 +143,24 @@ return: %retval = phi double [ %div, %else ], [ %x, %entry ] ret double %retval -; CHECK-LABEL: define double @fcmp_une_not_zero( -; CHECK: %div = fdiv double %x, 2.0 } -; PR22376 - We can't propagate zero constants because -0.0 +; PR22376 - We can't propagate zero constants because -0.0 ; compares equal to 0.0. If %y is -0.0 in this test case, ; we would produce the wrong sign on the infinity return value. define double @fcmp_oeq_zero(double %x, double %y) { +; CHECK-LABEL: define double @fcmp_oeq_zero( +; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[Y]], 0.000000e+00 +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[RETURN:%.*]] +; CHECK: if: +; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], [[Y]] +; CHECK-NEXT: br label [[RETURN]] +; CHECK: return: +; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[IF]] ], [ [[X]], [[ENTRY:%.*]] ] +; CHECK-NEXT: ret double [[RETVAL]] +; entry: %cmp = fcmp oeq double %y, 0.0 br i1 %cmp, label %if, label %return @@ -109,11 +173,21 @@ return: %retval = phi double [ %div, %if ], [ %x, %entry ] ret double %retval -; CHECK-LABEL: define double @fcmp_oeq_zero( -; CHECK: %div = fdiv double %x, %y } define double @fcmp_une_zero(double %x, double %y) { +; CHECK-LABEL: define double @fcmp_une_zero( +; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[Y]], -0.000000e+00 +; CHECK-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[ELSE:%.*]] +; CHECK: else: +; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], [[Y]] +; CHECK-NEXT: br label [[RETURN]] +; CHECK: return: +; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[ELSE]] ], [ [[X]], [[ENTRY:%.*]] ] +; CHECK-NEXT: ret double [[RETVAL]] +; entry: %cmp = fcmp une double %y, -0.0 br i1 %cmp, label %return, label %else @@ -126,45 +200,65 @@ return: %retval = phi double [ %div, %else ], [ %x, %entry ] ret double %retval -; CHECK-LABEL: define double @fcmp_une_zero( -; CHECK: %div = fdiv double %x, %y } ; We also cannot propagate a value if it's not a constant. ; This is because the value could be 0.0 or -0.0. define double @fcmp_oeq_maybe_zero(double %x, double %y, double %z1, double %z2) { +; CHECK-LABEL: define double @fcmp_oeq_maybe_zero( +; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]], double [[Z1:%.*]], double [[Z2:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[Z:%.*]] = fadd double [[Z1]], [[Z2]] +; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[Y]], [[Z]] +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[RETURN:%.*]] +; CHECK: if: +; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], [[Z]] +; CHECK-NEXT: br label [[RETURN]] +; CHECK: return: +; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[IF]] ], [ [[X]], [[ENTRY:%.*]] ] +; CHECK-NEXT: ret double [[RETVAL]] +; entry: - %z = fadd double %z1, %z2 - %cmp = fcmp oeq double %y, %z - br i1 %cmp, label %if, label %return + %z = fadd double %z1, %z2 + %cmp = fcmp oeq double %y, %z + br i1 %cmp, label %if, label %return if: - %div = fdiv double %x, %z - br label %return + %div = fdiv double %x, %z + br label %return return: - %retval = phi double [ %div, %if ], [ %x, %entry ] - ret double %retval + %retval = phi double [ %div, %if ], [ %x, %entry ] + ret double %retval -; CHECK-LABEL: define double @fcmp_oeq_maybe_zero( -; CHECK: %div = fdiv double %x, %z } define double @fcmp_une_maybe_zero(double %x, double %y, double %z1, double %z2) { +; CHECK-LABEL: define double @fcmp_une_maybe_zero( +; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]], double [[Z1:%.*]], double [[Z2:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[Z:%.*]] = fadd double [[Z1]], [[Z2]] +; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[Y]], [[Z]] +; CHECK-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[ELSE:%.*]] +; CHECK: else: +; CHECK-NEXT: [[DIV:%.*]] = fdiv double [[X]], [[Z]] +; CHECK-NEXT: br label [[RETURN]] +; CHECK: return: +; CHECK-NEXT: [[RETVAL:%.*]] = phi double [ [[DIV]], [[ELSE]] ], [ [[X]], [[ENTRY:%.*]] ] +; CHECK-NEXT: ret double [[RETVAL]] +; entry: - %z = fadd double %z1, %z2 - %cmp = fcmp une double %y, %z - br i1 %cmp, label %return, label %else + %z = fadd double %z1, %z2 + %cmp = fcmp une double %y, %z + br i1 %cmp, label %return, label %else else: - %div = fdiv double %x, %z - br label %return + %div = fdiv double %x, %z + br label %return return: - %retval = phi double [ %div, %else ], [ %x, %entry ] - ret double %retval + %retval = phi double [ %div, %else ], [ %x, %entry ] + ret double %retval -; CHECK-LABEL: define double @fcmp_une_maybe_zero( -; CHECK: %div = fdiv double %x, %z } diff --git a/llvm/test/Transforms/NewGVN/eliminate-callsite-inline.ll b/llvm/test/Transforms/NewGVN/eliminate-callsite-inline.ll index 748485c03c18abb77339ccbdd1dbcc53d4a01015..6cf543840cfe91873221d433f2f4c838eb3d792c 100644 --- a/llvm/test/Transforms/NewGVN/eliminate-callsite-inline.ll +++ b/llvm/test/Transforms/NewGVN/eliminate-callsite-inline.ll @@ -1,15 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=inline,newgvn -S < %s | FileCheck %s -; CHECK-LABEL: @f2() -; CHECK-NEXT: ret void define void @f2() { +; CHECK-LABEL: define void @f2() { +; CHECK-NEXT: ret void +; call void @f1() call void @f1() ret void } define internal void @f1() #1 { +; CHECK-LABEL: define internal void @f1( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: ret void +; entry: ret void } diff --git a/llvm/test/Transforms/NewGVN/equivalent-phi.ll b/llvm/test/Transforms/NewGVN/equivalent-phi.ll index 925795d49af17cc28ad2c167cc8d254652c00a5d..ba4fc14fa2feb4abdf1d5340951fdb5b7ca74b2e 100644 --- a/llvm/test/Transforms/NewGVN/equivalent-phi.ll +++ b/llvm/test/Transforms/NewGVN/equivalent-phi.ll @@ -11,22 +11,22 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" define i32 @bar(i32 %arg, i32 %arg1, i32 %arg2) #0 { ; CHECK-LABEL: @bar( ; CHECK-NEXT: bb: -; CHECK-NEXT: br label %bb3 +; CHECK-NEXT: br label [[BB3:%.*]] ; CHECK: bb3: -; CHECK-NEXT: [[TMP:%.*]] = phi i32 [ %arg, %bb ], [ [[TMP:%.*]]15, %bb17 ] -; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ %arg2, %bb ], [ [[TMP18:%.*]], %bb17 ] -; CHECK-NEXT: [[TMP6:%.*]] = phi i32 [ 0, %bb ], [ [[TMP14:%.*]], %bb17 ] +; CHECK-NEXT: [[TMP:%.*]] = phi i32 [ [[ARG:%.*]], [[BB:%.*]] ], [ [[TMP15:%.*]], [[BB17:%.*]] ] +; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ [[ARG2:%.*]], [[BB]] ], [ [[TMP18:%.*]], [[BB17]] ] +; CHECK-NEXT: [[TMP6:%.*]] = phi i32 [ 0, [[BB]] ], [ [[TMP14:%.*]], [[BB17]] ] ; CHECK-NEXT: [[TMP7:%.*]] = sext i32 [[TMP]] to i64 ; CHECK-NEXT: [[TMP8:%.*]] = getelementptr inbounds [1024 x i32], ptr @global, i64 0, i64 [[TMP7]] ; CHECK-NEXT: [[TMP9:%.*]] = load i32, ptr [[TMP8]], align 4 ; CHECK-NEXT: [[TMP10:%.*]] = add nsw i32 [[TMP6]], [[TMP9]] ; CHECK-NEXT: [[TMP14]] = add nsw i32 [[TMP10]], [[TMP9]] -; CHECK-NEXT: [[TMP15:%.*]] = add nsw i32 [[TMP]], %arg1 -; CHECK-NEXT: br label %bb17 +; CHECK-NEXT: [[TMP15]] = add nsw i32 [[TMP]], [[ARG1:%.*]] +; CHECK-NEXT: br label [[BB17]] ; CHECK: bb17: ; CHECK-NEXT: [[TMP18]] = add i32 [[TMP4]], -1 ; CHECK-NEXT: [[TMP19:%.*]] = icmp ne i32 [[TMP4]], 0 -; CHECK-NEXT: br i1 [[TMP19]], label %bb3, label %bb20 +; CHECK-NEXT: br i1 [[TMP19]], label [[BB3]], label [[BB20:%.*]] ; CHECK: bb20: ; CHECK-NEXT: ret i32 [[TMP14]] ; diff --git a/llvm/test/Transforms/NewGVN/fold-const-expr.ll b/llvm/test/Transforms/NewGVN/fold-const-expr.ll index 2821791469494adb5fcac3e16db9bc0d84462367..54020b88d65a80d91995c52b329725977b836c42 100644 --- a/llvm/test/Transforms/NewGVN/fold-const-expr.ll +++ b/llvm/test/Transforms/NewGVN/fold-const-expr.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; GVN failed to do constant expression folding and expanded ; them unfolded in many places, producing exponentially large const ; expressions. As a result, the compilation never fisished. @@ -6,6 +7,16 @@ ; RUN: opt -passes=newgvn -S < %s | FileCheck %s %2 = type { i32, i32, i32, i32, i32 } define i32 @_Z16vector3util_mainv(i32 %x, i32 %y) { +; CHECK-LABEL: define i32 @_Z16vector3util_mainv( +; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = alloca [[TMP0:%.*]], align 4 +; CHECK-NEXT: [[TMP114:%.*]] = getelementptr inbounds [[TMP0]], ptr [[TMP1]], i64 0, i32 1 +; CHECK-NEXT: store <4 x i32> <i32 234567891, i32 345678912, i32 456789123, i32 0>, ptr [[TMP114]], align 4 +; CHECK-NEXT: store i32 310393545, ptr [[TMP114]], align 4 +; CHECK-NEXT: store i32 -383584258, ptr [[TMP114]], align 4 +; CHECK-NEXT: store i32 -57163022, ptr [[TMP114]], align 4 +; CHECK-NEXT: ret i32 0 +; %tmp1 = alloca %2, align 4 %tmp114 = getelementptr inbounds %2, ptr %tmp1, i64 0, i32 1 store <4 x i32> <i32 234567891, i32 345678912, i32 456789123, i32 0>, ptr %tmp114, align 4 @@ -36,7 +47,6 @@ define i32 @_Z16vector3util_mainv(i32 %x, i32 %y) { %tmp1739 = shl i32 %tmp1738, 22 %tmp1740 = xor i32 %tmp1739, %tmp1738 store i32 %tmp1740, ptr %tmp1683, align 4 -; CHECK: store i32 310393545, ptr %tmp114, align 4 %tmp1756 = getelementptr inbounds %2, ptr %tmp1, i64 0, i32 1 %tmp1761 = load i32, ptr %tmp1756, align 4 %tmp1766 = shl i32 %tmp1761, 5 @@ -64,7 +74,6 @@ define i32 @_Z16vector3util_mainv(i32 %x, i32 %y) { %tmp1812 = shl i32 %tmp1811, 22 %tmp1813 = xor i32 %tmp1812, %tmp1811 store i32 %tmp1813, ptr %tmp1756, align 4 -; CHECK: store i32 -383584258, ptr %tmp114, align 4 %tmp2645 = getelementptr inbounds %2, ptr %tmp1, i64 0, i32 1 %tmp2650 = load i32, ptr %tmp2645, align 4 %tmp2655 = shl i32 %tmp2650, 5 @@ -92,6 +101,5 @@ define i32 @_Z16vector3util_mainv(i32 %x, i32 %y) { %tmp2701 = shl i32 %tmp2700, 22 %tmp2702 = xor i32 %tmp2701, %tmp2700 store i32 %tmp2702, ptr %tmp2645, align 4 -; CHECK: store i32 -57163022, ptr %tmp114, align 4 ret i32 0 } diff --git a/llvm/test/Transforms/NewGVN/fpmath.ll b/llvm/test/Transforms/NewGVN/fpmath.ll index e8cec8af3e02123701b12db1036a9d0222f14f63..d936c01bbe7887b9a41167e05c9d285a5575a3d6 100644 --- a/llvm/test/Transforms/NewGVN/fpmath.ll +++ b/llvm/test/Transforms/NewGVN/fpmath.ll @@ -1,10 +1,13 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -S < %s | FileCheck %s define double @test1(double %x, double %y) { -; CHECK: @test1(double %x, double %y) -; CHECK: %add1 = fadd double %x, %y -; CHECK-NOT: fpmath -; CHECK: %foo = fadd double %add1, %add1 +; CHECK-LABEL: define double @test1( +; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { +; CHECK-NEXT: [[ADD1:%.*]] = fadd double [[X]], [[Y]] +; CHECK-NEXT: [[FOO:%.*]] = fadd double [[ADD1]], [[ADD1]] +; CHECK-NEXT: ret double [[FOO]] +; %add1 = fadd double %x, %y, !fpmath !0 %add2 = fadd double %x, %y %foo = fadd double %add1, %add2 @@ -12,9 +15,12 @@ define double @test1(double %x, double %y) { } define double @test2(double %x, double %y) { -; CHECK: @test2(double %x, double %y) -; CHECK: %add1 = fadd double %x, %y, !fpmath ![[MD0:[0-9]+]] -; CHECK: %foo = fadd double %add1, %add1 +; CHECK-LABEL: define double @test2( +; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { +; CHECK-NEXT: [[ADD1:%.*]] = fadd double [[X]], [[Y]], !fpmath [[META0:![0-9]+]] +; CHECK-NEXT: [[FOO:%.*]] = fadd double [[ADD1]], [[ADD1]] +; CHECK-NEXT: ret double [[FOO]] +; %add1 = fadd double %x, %y, !fpmath !0 %add2 = fadd double %x, %y, !fpmath !0 %foo = fadd double %add1, %add2 @@ -22,9 +28,12 @@ define double @test2(double %x, double %y) { } define double @test3(double %x, double %y) { -; CHECK: @test3(double %x, double %y) -; CHECK: %add1 = fadd double %x, %y, !fpmath ![[MD1:[0-9]+]] -; CHECK: %foo = fadd double %add1, %add1 +; CHECK-LABEL: define double @test3( +; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { +; CHECK-NEXT: [[ADD1:%.*]] = fadd double [[X]], [[Y]], !fpmath [[META1:![0-9]+]] +; CHECK-NEXT: [[FOO:%.*]] = fadd double [[ADD1]], [[ADD1]] +; CHECK-NEXT: ret double [[FOO]] +; %add1 = fadd double %x, %y, !fpmath !1 %add2 = fadd double %x, %y, !fpmath !0 %foo = fadd double %add1, %add2 @@ -32,9 +41,12 @@ define double @test3(double %x, double %y) { } define double @test4(double %x, double %y) { -; CHECK: @test4(double %x, double %y) -; CHECK: %add1 = fadd double %x, %y, !fpmath ![[MD1]] -; CHECK: %foo = fadd double %add1, %add1 +; CHECK-LABEL: define double @test4( +; CHECK-SAME: double [[X:%.*]], double [[Y:%.*]]) { +; CHECK-NEXT: [[ADD1:%.*]] = fadd double [[X]], [[Y]], !fpmath [[META1]] +; CHECK-NEXT: [[FOO:%.*]] = fadd double [[ADD1]], [[ADD1]] +; CHECK-NEXT: ret double [[FOO]] +; %add1 = fadd double %x, %y, !fpmath !0 %add2 = fadd double %x, %y, !fpmath !1 %foo = fadd double %add1, %add2 @@ -42,17 +54,22 @@ define double @test4(double %x, double %y) { } define double @test5(double %x) { -; CHECK: @test5(double %x) -; CHECK: %neg1 = fneg double %x, !fpmath ![[MD1]] -; CHECK: %foo = fadd double %neg1, %neg1 +; CHECK-LABEL: define double @test5( +; CHECK-SAME: double [[X:%.*]]) { +; CHECK-NEXT: [[NEG1:%.*]] = fneg double [[X]], !fpmath [[META1]] +; CHECK-NEXT: [[FOO:%.*]] = fadd double [[NEG1]], [[NEG1]] +; CHECK-NEXT: ret double [[FOO]] +; %neg1 = fneg double %x, !fpmath !0 %neg2 = fneg double %x, !fpmath !1 %foo = fadd double %neg1, %neg2 ret double %foo } -; CHECK: ![[MD0]] = !{float 5.000000e+00} -; CHECK: ![[MD1]] = !{float 2.500000e+00} !0 = !{ float 5.0 } !1 = !{ float 2.5 } +;. +; CHECK: [[META0]] = !{float 5.000000e+00} +; CHECK: [[META1]] = !{float 2.500000e+00} +;. diff --git a/llvm/test/Transforms/NewGVN/funclet.ll b/llvm/test/Transforms/NewGVN/funclet.ll index 3df3f940ec2d79176d41fa9ea790fca66c10bc8f..8c1cbd6b08fd7f8dc9e589ff2734446e661096e5 100644 --- a/llvm/test/Transforms/NewGVN/funclet.ll +++ b/llvm/test/Transforms/NewGVN/funclet.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -S < %s | FileCheck %s target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" target triple = "i686-pc-windows-msvc" @@ -8,13 +9,35 @@ target triple = "i686-pc-windows-msvc" @"_TI1?AUA@@" = external constant %eh.ThrowInfo define i8 @f() personality ptr @__CxxFrameHandler3 { +; CHECK-LABEL: define i8 @f() personality ptr @__CxxFrameHandler3 { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[B:%.*]] = alloca i8, align 1 +; CHECK-NEXT: [[C:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[B]], align 1 +; CHECK-NEXT: store i8 13, ptr [[C]], align 1 +; CHECK-NEXT: invoke void @_CxxThrowException(ptr [[B]], ptr nonnull @"_TI1?AUA@@") +; CHECK-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[CATCH_DISPATCH:%.*]] +; CHECK: catch.dispatch: +; CHECK-NEXT: [[CS1:%.*]] = catchswitch within none [label %catch] unwind to caller +; CHECK: catch: +; CHECK-NEXT: [[CATCHPAD:%.*]] = catchpad within [[CS1]] [ptr null, i32 64, ptr null] +; CHECK-NEXT: store i8 5, ptr [[B]], align 1 +; CHECK-NEXT: catchret from [[CATCHPAD]] to label [[TRY_CONT:%.*]] +; CHECK: try.cont: +; CHECK-NEXT: [[LOAD_B:%.*]] = load i8, ptr [[B]], align 1 +; CHECK-NEXT: [[LOAD_C:%.*]] = load i8, ptr [[C]], align 1 +; CHECK-NEXT: [[ADD:%.*]] = add i8 [[LOAD_B]], [[LOAD_C]] +; CHECK-NEXT: ret i8 [[ADD]] +; CHECK: unreachable: +; CHECK-NEXT: unreachable +; entry: %b = alloca i8 %c = alloca i8 store i8 42, ptr %b store i8 13, ptr %c invoke void @_CxxThrowException(ptr %b, ptr nonnull @"_TI1?AUA@@") - to label %unreachable unwind label %catch.dispatch + to label %unreachable unwind label %catch.dispatch catch.dispatch: ; preds = %entry %cs1 = catchswitch within none [label %catch] unwind to caller @@ -33,11 +56,6 @@ try.cont: ; preds = %catch unreachable: ; preds = %entry unreachable } -; CHECK-LABEL: define i8 @f( -; CHECK: %[[load_b:.*]] = load i8, ptr %b -; CHECK-NEXT: %[[load_c:.*]] = load i8, ptr %c -; CHECK-NEXT: %[[add:.*]] = add i8 %[[load_b]], %[[load_c]] -; CHECK-NEXT: ret i8 %[[add]] declare i32 @__CxxFrameHandler3(...) diff --git a/llvm/test/Transforms/NewGVN/int_sideeffect.ll b/llvm/test/Transforms/NewGVN/int_sideeffect.ll index f715d022ba010a76bfb15f459961d165357b77f6..a2c54bd38e93c5f18ac13e9f8598b327ff020360 100644 --- a/llvm/test/Transforms/NewGVN/int_sideeffect.ll +++ b/llvm/test/Transforms/NewGVN/int_sideeffect.ll @@ -1,27 +1,36 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -S < %s -passes=newgvn | FileCheck %s declare void @llvm.sideeffect() ; Store-to-load forwarding across a @llvm.sideeffect. -; CHECK-LABEL: s2l -; CHECK-NOT: load define float @s2l(ptr %p) { - store float 0.0, ptr %p - call void @llvm.sideeffect() - %t = load float, ptr %p - ret float %t +; CHECK-LABEL: define float @s2l( +; CHECK-SAME: ptr [[P:%.*]]) { +; CHECK-NEXT: store float 0.000000e+00, ptr [[P]], align 4 +; CHECK-NEXT: call void @llvm.sideeffect() +; CHECK-NEXT: ret float 0.000000e+00 +; + store float 0.0, ptr %p + call void @llvm.sideeffect() + %t = load float, ptr %p + ret float %t } ; Redundant load elimination across a @llvm.sideeffect. -; CHECK-LABEL: rle -; CHECK: load -; CHECK-NOT: load define float @rle(ptr %p) { - %r = load float, ptr %p - call void @llvm.sideeffect() - %s = load float, ptr %p - %t = fadd float %r, %s - ret float %t +; CHECK-LABEL: define float @rle( +; CHECK-SAME: ptr [[P:%.*]]) { +; CHECK-NEXT: [[R:%.*]] = load float, ptr [[P]], align 4 +; CHECK-NEXT: call void @llvm.sideeffect() +; CHECK-NEXT: [[T:%.*]] = fadd float [[R]], [[R]] +; CHECK-NEXT: ret float [[T]] +; + %r = load float, ptr %p + call void @llvm.sideeffect() + %s = load float, ptr %p + %t = fadd float %r, %s + ret float %t } diff --git a/llvm/test/Transforms/NewGVN/invariant.group.ll b/llvm/test/Transforms/NewGVN/invariant.group.ll index 81e733f84ddb11f3ab2930303cf66c623945bd51..7c14059c88c67702deaabdd889df7f0f220fe461 100644 --- a/llvm/test/Transforms/NewGVN/invariant.group.ll +++ b/llvm/test/Transforms/NewGVN/invariant.group.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn -S | FileCheck %s %struct.A = type { ptr } @@ -6,86 +7,131 @@ @unknownPtr = external global i8 -; CHECK-LABEL: define i8 @simple() { define i8 @simple() { +; CHECK-LABEL: define i8 @simple() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0:![0-9]+]] +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: ret i8 42 +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr, !invariant.group !0 - call void @foo(ptr %ptr) - - %a = load i8, ptr %ptr, !invariant.group !0 - %b = load i8, ptr %ptr, !invariant.group !0 - %c = load i8, ptr %ptr, !invariant.group !0 -; CHECK: ret i8 42 - ret i8 %a + %ptr = alloca i8 + store i8 42, ptr %ptr, !invariant.group !0 + call void @foo(ptr %ptr) + + %a = load i8, ptr %ptr, !invariant.group !0 + %b = load i8, ptr %ptr, !invariant.group !0 + %c = load i8, ptr %ptr, !invariant.group !0 + ret i8 %a } -; CHECK-LABEL: define i8 @optimizable1() { define i8 @optimizable1() { +; CHECK-LABEL: define i8 @optimizable1() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: [[PTR2:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[PTR]]) +; CHECK-NEXT: call void @foo(ptr [[PTR2]]) +; CHECK-NEXT: ret i8 42 +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr, !invariant.group !0 - %ptr2 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr) - %a = load i8, ptr %ptr, !invariant.group !0 - - call void @foo(ptr %ptr2); call to use %ptr2 -; CHECK: ret i8 42 - ret i8 %a + %ptr = alloca i8 + store i8 42, ptr %ptr, !invariant.group !0 + %ptr2 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr) + %a = load i8, ptr %ptr, !invariant.group !0 + + call void @foo(ptr %ptr2); call to use %ptr2 + ret i8 %a } -; CHECK-LABEL: define i8 @optimizable2() { define i8 @optimizable2() { +; CHECK-LABEL: define i8 @optimizable2() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: store i8 13, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @bar(i8 13) +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: ret i8 42 +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr, !invariant.group !0 - call void @foo(ptr %ptr) - - store i8 13, ptr %ptr ; can't use this store with invariant.group - %a = load i8, ptr %ptr - call void @bar(i8 %a) ; call to use %a - - call void @foo(ptr %ptr) - %b = load i8, ptr %ptr, !invariant.group !0 - -; CHECK: ret i8 42 - ret i8 %b + %ptr = alloca i8 + store i8 42, ptr %ptr, !invariant.group !0 + call void @foo(ptr %ptr) + + store i8 13, ptr %ptr ; can't use this store with invariant.group + %a = load i8, ptr %ptr + call void @bar(i8 %a) ; call to use %a + + call void @foo(ptr %ptr) + %b = load i8, ptr %ptr, !invariant.group !0 + + ret i8 %b } -; CHECK-LABEL: define i1 @proveEqualityForStrip( define i1 @proveEqualityForStrip(ptr %a) { +; CHECK-LABEL: define i1 @proveEqualityForStrip( +; CHECK-SAME: ptr [[A:%.*]]) { +; CHECK-NEXT: ret i1 true +; %b1 = call ptr @llvm.strip.invariant.group.p0(ptr %a) -; CHECK-NOT: llvm.strip.invariant.group %b2 = call ptr @llvm.strip.invariant.group.p0(ptr %a) %r = icmp eq ptr %b1, %b2 -; CHECK: ret i1 true ret i1 %r } -; CHECK-LABEL: define i8 @unoptimizable1() { define i8 @unoptimizable1() { +; CHECK-LABEL: define i8 @unoptimizable1() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: [[A:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: ret i8 [[A]] +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr - call void @foo(ptr %ptr) - %a = load i8, ptr %ptr, !invariant.group !0 -; CHECK: ret i8 %a - ret i8 %a + %ptr = alloca i8 + store i8 42, ptr %ptr + call void @foo(ptr %ptr) + %a = load i8, ptr %ptr, !invariant.group !0 + ret i8 %a } ; NewGVN doesn't support assumes. -; CHECK-LABEL: define void @indirectLoads() { define void @indirectLoads() { +; CHECK-LABEL: define void @indirectLoads() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = alloca ptr, align 8 +; CHECK-NEXT: [[CALL:%.*]] = call ptr @getPointer(ptr null) +; CHECK-NEXT: call void @_ZN1AC1Ev(ptr [[CALL]]) +; CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[CALL]], align 8, !invariant.group [[META0]] +; CHECK-NEXT: [[CMP_VTABLES:%.*]] = icmp eq ptr [[VTABLE]], getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2) +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_VTABLES]]) +; CHECK-NEXT: store ptr [[CALL]], ptr [[A]], align 8 +; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VTABLE]], align 8 +; CHECK-NEXT: call void [[TMP0]](ptr [[CALL]]) +; CHECK-NEXT: [[VTABLE2:%.*]] = load ptr, ptr [[CALL]], align 8, !invariant.group [[META0]] +; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VTABLE2]], align 8 +; CHECK-NEXT: call void [[TMP1]](ptr [[CALL]]) +; CHECK-NEXT: [[VTABLE4:%.*]] = load ptr, ptr [[CALL]], align 8, !invariant.group [[META0]] +; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VTABLE4]], align 8 +; CHECK-NEXT: call void [[TMP2]](ptr [[CALL]]) +; CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VTABLE]], align 8 +; CHECK-NEXT: call void [[TMP3]](ptr [[CALL]]) +; CHECK-NEXT: ret void +; entry: %a = alloca ptr, align 8 - - %call = call ptr @getPointer(ptr null) + + %call = call ptr @getPointer(ptr null) call void @_ZN1AC1Ev(ptr %call) - -; CHECK: %vtable = load {{.*}} !invariant.group + %vtable = load ptr, ptr %call, align 8, !invariant.group !0 %cmp.vtables = icmp eq ptr %vtable, getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2) call void @llvm.assume(i1 %cmp.vtables) - + store ptr %call, ptr %a, align 8 %0 = load ptr, ptr %a, align 8 @@ -98,36 +144,45 @@ entry: ; FIXME: call void @_ZN1A3fooEv( %vtable2 = load ptr, ptr %2, align 8, !invariant.group !0 %3 = load ptr, ptr %vtable2, align 8 - + call void %3(ptr %2) %4 = load ptr, ptr %a, align 8 - + %vtable4 = load ptr, ptr %4, align 8, !invariant.group !0 %5 = load ptr, ptr %vtable4, align 8 ; FIXME: call void @_ZN1A3fooEv( call void %5(ptr %4) - + %vtable5 = load ptr, ptr %call, align 8, !invariant.group !0 %6 = load ptr, ptr %vtable5, align 8 ; FIXME: call void @_ZN1A3fooEv( call void %6(ptr %4) - + ret void } ; NewGVN won't CSE loads with different pointee types. -; CHECK-LABEL: define void @combiningBitCastWithLoad() { define void @combiningBitCastWithLoad() { +; CHECK-LABEL: define void @combiningBitCastWithLoad() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A:%.*]] = alloca ptr, align 8 +; CHECK-NEXT: [[CALL:%.*]] = call ptr @getPointer(ptr null) +; CHECK-NEXT: call void @_ZN1AC1Ev(ptr [[CALL]]) +; CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[CALL]], align 8, !invariant.group [[META0]] +; CHECK-NEXT: store ptr [[CALL]], ptr [[A]], align 8 +; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VTABLE]], align 8 +; CHECK-NEXT: call void [[TMP0]](ptr [[CALL]]) +; CHECK-NEXT: ret void +; entry: %a = alloca ptr, align 8 - - %call = call ptr @getPointer(ptr null) + + %call = call ptr @getPointer(ptr null) call void @_ZN1AC1Ev(ptr %call) - -; CHECK: %vtable = load {{.*}} !invariant.group + %vtable = load ptr, ptr %call, align 8, !invariant.group !0 %cmp.vtables = icmp eq ptr %vtable, getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2) - + store ptr %call, ptr %a, align 8 ; FIXME-NOT: !invariant.group %0 = load ptr, ptr %a, align 8 @@ -139,173 +194,245 @@ entry: ret void } -; CHECK-LABEL:define void @loadCombine() { define void @loadCombine() { +; CHECK-LABEL: define void @loadCombine() { +; CHECK-NEXT: enter: +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: [[A:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @bar(i8 [[A]]) +; CHECK-NEXT: call void @bar(i8 [[A]]) +; CHECK-NEXT: ret void +; enter: %ptr = alloca i8 store i8 42, ptr %ptr call void @foo(ptr %ptr) -; CHECK: %[[A:.*]] = load i8, ptr %ptr, align 1, !invariant.group %a = load i8, ptr %ptr, !invariant.group !0 -; CHECK-NOT: load %b = load i8, ptr %ptr, !invariant.group !0 -; CHECK: call void @bar(i8 %[[A]]) call void @bar(i8 %a) -; CHECK: call void @bar(i8 %[[A]]) call void @bar(i8 %b) ret void } -; CHECK-LABEL: define void @loadCombine1() { define void @loadCombine1() { +; CHECK-LABEL: define void @loadCombine1() { +; CHECK-NEXT: enter: +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: [[C:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @bar(i8 [[C]]) +; CHECK-NEXT: call void @bar(i8 [[C]]) +; CHECK-NEXT: ret void +; enter: %ptr = alloca i8 store i8 42, ptr %ptr call void @foo(ptr %ptr) -; CHECK: %[[D:.*]] = load i8, ptr %ptr, align 1, !invariant.group %c = load i8, ptr %ptr -; CHECK-NOT: load %d = load i8, ptr %ptr, !invariant.group !0 -; CHECK: call void @bar(i8 %[[D]]) call void @bar(i8 %c) -; CHECK: call void @bar(i8 %[[D]]) call void @bar(i8 %d) ret void } -; CHECK-LABEL: define void @loadCombine2() { define void @loadCombine2() { +; CHECK-LABEL: define void @loadCombine2() { +; CHECK-NEXT: enter: +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: [[E:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @bar(i8 [[E]]) +; CHECK-NEXT: call void @bar(i8 [[E]]) +; CHECK-NEXT: ret void +; enter: %ptr = alloca i8 store i8 42, ptr %ptr call void @foo(ptr %ptr) -; CHECK: %[[E:.*]] = load i8, ptr %ptr, align 1, !invariant.group %e = load i8, ptr %ptr, !invariant.group !0 -; CHECK-NOT: load %f = load i8, ptr %ptr -; CHECK: call void @bar(i8 %[[E]]) call void @bar(i8 %e) -; CHECK: call void @bar(i8 %[[E]]) call void @bar(i8 %f) ret void } -; CHECK-LABEL: define void @loadCombine3() { define void @loadCombine3() { +; CHECK-LABEL: define void @loadCombine3() { +; CHECK-NEXT: enter: +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: [[E:%.*]] = load i8, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @bar(i8 [[E]]) +; CHECK-NEXT: call void @bar(i8 [[E]]) +; CHECK-NEXT: ret void +; enter: %ptr = alloca i8 store i8 42, ptr %ptr call void @foo(ptr %ptr) -; CHECK: %[[E:.*]] = load i8, ptr %ptr, align 1, !invariant.group %e = load i8, ptr %ptr, !invariant.group !0 -; CHECK-NOT: load %f = load i8, ptr %ptr, !invariant.group !0 -; CHECK: call void @bar(i8 %[[E]]) call void @bar(i8 %e) -; CHECK: call void @bar(i8 %[[E]]) call void @bar(i8 %f) ret void } -; CHECK-LABEL: define i8 @unoptimizable2() { define i8 @unoptimizable2() { +; CHECK-LABEL: define i8 @unoptimizable2() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: [[A:%.*]] = load i8, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: ret i8 [[A]] +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr - call void @foo(ptr %ptr) - %a = load i8, ptr %ptr - call void @foo(ptr %ptr) - %b = load i8, ptr %ptr, !invariant.group !0 - -; CHECK: ret i8 %a - ret i8 %a + %ptr = alloca i8 + store i8 42, ptr %ptr + call void @foo(ptr %ptr) + %a = load i8, ptr %ptr + call void @foo(ptr %ptr) + %b = load i8, ptr %ptr, !invariant.group !0 + + ret i8 %a } -; CHECK-LABEL: define i8 @unoptimizable3() { define i8 @unoptimizable3() { +; CHECK-LABEL: define i8 @unoptimizable3() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: [[PTR2:%.*]] = call ptr @getPointer(ptr [[PTR]]) +; CHECK-NEXT: [[A:%.*]] = load i8, ptr [[PTR2]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: ret i8 [[A]] +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr, !invariant.group !0 - %ptr2 = call ptr @getPointer(ptr %ptr) - %a = load i8, ptr %ptr2, !invariant.group !0 - -; CHECK: ret i8 %a - ret i8 %a + %ptr = alloca i8 + store i8 42, ptr %ptr, !invariant.group !0 + %ptr2 = call ptr @getPointer(ptr %ptr) + %a = load i8, ptr %ptr2, !invariant.group !0 + + ret i8 %a } ; NewGVN cares about the launder for some reason. -; CHECK-LABEL: define i8 @optimizable4() { define i8 @optimizable4() { +; CHECK-LABEL: define i8 @optimizable4() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1 +; CHECK-NEXT: [[PTR2:%.*]] = call ptr @llvm.launder.invariant.group.p0(ptr [[PTR]]) +; CHECK-NEXT: [[A:%.*]] = load i8, ptr [[PTR2]], align 1 +; CHECK-NEXT: ret i8 [[A]] +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr - %ptr2 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr) + %ptr = alloca i8 + store i8 42, ptr %ptr + %ptr2 = call ptr @llvm.launder.invariant.group.p0(ptr %ptr) ; FIXME-NOT: load - %a = load i8, ptr %ptr2 - + %a = load i8, ptr %ptr2 + ; FIXME: ret i8 42 - ret i8 %a + ret i8 %a } -; CHECK-LABEL: define i8 @volatile1() { define i8 @volatile1() { +; CHECK-LABEL: define i8 @volatile1() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: [[B:%.*]] = load volatile i8, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @bar(i8 [[B]]) +; CHECK-NEXT: [[C:%.*]] = load volatile i8, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @bar(i8 [[C]]) +; CHECK-NEXT: ret i8 42 +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr, !invariant.group !0 - call void @foo(ptr %ptr) - %a = load i8, ptr %ptr, !invariant.group !0 - %b = load volatile i8, ptr %ptr -; CHECK: call void @bar(i8 %b) - call void @bar(i8 %b) - - %c = load volatile i8, ptr %ptr, !invariant.group !0 + %ptr = alloca i8 + store i8 42, ptr %ptr, !invariant.group !0 + call void @foo(ptr %ptr) + %a = load i8, ptr %ptr, !invariant.group !0 + %b = load volatile i8, ptr %ptr + call void @bar(i8 %b) + + %c = load volatile i8, ptr %ptr, !invariant.group !0 ; We might be able to optimize this, but nobody cares -; CHECK: call void @bar(i8 %c) - call void @bar(i8 %c) -; CHECK: ret i8 42 - ret i8 %a + call void @bar(i8 %c) + ret i8 %a } -; CHECK-LABEL: define i8 @volatile2() { define i8 @volatile2() { +; CHECK-LABEL: define i8 @volatile2() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: [[B:%.*]] = load volatile i8, ptr [[PTR]], align 1 +; CHECK-NEXT: call void @bar(i8 [[B]]) +; CHECK-NEXT: [[C:%.*]] = load volatile i8, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @bar(i8 [[C]]) +; CHECK-NEXT: ret i8 42 +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr, !invariant.group !0 - call void @foo(ptr %ptr) - %a = load i8, ptr %ptr, !invariant.group !0 - %b = load volatile i8, ptr %ptr -; CHECK: call void @bar(i8 %b) - call void @bar(i8 %b) - - %c = load volatile i8, ptr %ptr, !invariant.group !0 + %ptr = alloca i8 + store i8 42, ptr %ptr, !invariant.group !0 + call void @foo(ptr %ptr) + %a = load i8, ptr %ptr, !invariant.group !0 + %b = load volatile i8, ptr %ptr + call void @bar(i8 %b) + + %c = load volatile i8, ptr %ptr, !invariant.group !0 ; We might be able to optimize this, but nobody cares -; CHECK: call void @bar(i8 %c) - call void @bar(i8 %c) -; CHECK: ret i8 42 - ret i8 %a + call void @bar(i8 %c) + ret i8 %a } -; CHECK-LABEL: define void @fun() { define void @fun() { +; CHECK-LABEL: define void @fun() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[PTR:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 42, ptr [[PTR]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @foo(ptr [[PTR]]) +; CHECK-NEXT: call void @bar(i8 42) +; CHECK-NEXT: ret void +; entry: - %ptr = alloca i8 - store i8 42, ptr %ptr, !invariant.group !0 - call void @foo(ptr %ptr) + %ptr = alloca i8 + store i8 42, ptr %ptr, !invariant.group !0 + call void @foo(ptr %ptr) - %a = load i8, ptr %ptr, !invariant.group !0 ; Can assume that value under %ptr didn't change -; CHECK: call void @bar(i8 42) - call void @bar(i8 %a) + %a = load i8, ptr %ptr, !invariant.group !0 ; Can assume that value under %ptr didn't change + call void @bar(i8 %a) - ret void + ret void } ; FIXME: NewGVN doesn't run instsimplify on a load from a vtable definition? ; This test checks if invariant.group understands gep with zeros -; CHECK-LABEL: define void @testGEP0() { define void @testGEP0() { +; CHECK-LABEL: define void @testGEP0() { +; CHECK-NEXT: [[A:%.*]] = alloca [[STRUCT_A:%.*]], align 8 +; CHECK-NEXT: store ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), ptr [[A]], align 8, !invariant.group [[META0]] +; CHECK-NEXT: call void @_ZN1A3fooEv(ptr nonnull dereferenceable(8) [[A]]) +; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr @unknownPtr, align 4 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0 +; CHECK-NEXT: br i1 [[TMP2]], label [[_Z1GR1A_EXIT:%.*]], label [[TMP3:%.*]] +; CHECK: 3: +; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), align 8 +; CHECK-NEXT: call void [[TMP4]](ptr nonnull [[A]]) +; CHECK-NEXT: br label [[_Z1GR1A_EXIT]] +; CHECK: _Z1gR1A.exit: +; CHECK-NEXT: ret void +; %a = alloca %struct.A, align 8 store ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), ptr %a, align 8, !invariant.group !0 -; CHECK: call void @_ZN1A3fooEv(ptr nonnull dereferenceable(8) %a) call void @_ZN1A3fooEv(ptr nonnull dereferenceable(8) %a) ; This call may change vptr %1 = load i8, ptr @unknownPtr, align 4 %2 = icmp eq i8 %1, 0 @@ -325,54 +452,93 @@ _Z1gR1A.exit: ; preds = %0, %3 ; Check if no optimizations are performed with global pointers. ; FIXME: we could do the optimizations if we would check if dependency comes ; from the same function. -; CHECK-LABEL: define void @testGlobal() { define void @testGlobal() { -; CHECK: %a = load i8, ptr @unknownPtr, align 1, !invariant.group !0 - %a = load i8, ptr @unknownPtr, !invariant.group !0 - call void @foo2(ptr @unknownPtr, i8 %a) -; CHECK: %1 = load i8, ptr @unknownPtr, align 1, !invariant.group !0 - %1 = load i8, ptr @unknownPtr, !invariant.group !0 - call void @bar(i8 %1) - - call void @fooBit(ptr @unknownPtr, i1 1) +; CHECK-LABEL: define void @testGlobal() { +; CHECK-NEXT: [[A:%.*]] = load i8, ptr @unknownPtr, align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @foo2(ptr @unknownPtr, i8 [[A]]) +; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr @unknownPtr, align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @bar(i8 [[TMP1]]) +; CHECK-NEXT: call void @fooBit(ptr @unknownPtr, i1 true) +; CHECK-NEXT: [[TMP2:%.*]] = load i1, ptr @unknownPtr, align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @fooBit(ptr @unknownPtr, i1 [[TMP2]]) +; CHECK-NEXT: [[TMP3:%.*]] = load i1, ptr @unknownPtr, align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @fooBit(ptr @unknownPtr, i1 [[TMP3]]) +; CHECK-NEXT: ret void +; + %a = load i8, ptr @unknownPtr, !invariant.group !0 + call void @foo2(ptr @unknownPtr, i8 %a) + %1 = load i8, ptr @unknownPtr, !invariant.group !0 + call void @bar(i8 %1) + + call void @fooBit(ptr @unknownPtr, i1 1) ; Adding regex because of canonicalization of bitcasts -; CHECK: %2 = load i1, ptr {{.*}}, !invariant.group !0 - %2 = load i1, ptr @unknownPtr, !invariant.group !0 - call void @fooBit(ptr @unknownPtr, i1 %2) -; CHECK: %3 = load i1, ptr {{.*}}, !invariant.group !0 - %3 = load i1, ptr @unknownPtr, !invariant.group !0 - call void @fooBit(ptr @unknownPtr, i1 %3) - ret void + %2 = load i1, ptr @unknownPtr, !invariant.group !0 + call void @fooBit(ptr @unknownPtr, i1 %2) + %3 = load i1, ptr @unknownPtr, !invariant.group !0 + call void @fooBit(ptr @unknownPtr, i1 %3) + ret void } ; Might be similar to above where NewGVN doesn't handle loads of different types from the same location. ; Not super important anyway. -; CHECK-LABEL: define void @testTrunc() { define void @testTrunc() { - %a = alloca i8 - call void @foo(ptr %a) -; CHECK: %b = load i8, ptr %a, align 1, !invariant.group !0 - %b = load i8, ptr %a, !invariant.group !0 - call void @foo2(ptr %a, i8 %b) - - %1 = load i8, ptr %a, !invariant.group !0 -; CHECK: call void @bar(i8 %b) - call void @bar(i8 %1) - - call void @fooBit(ptr %a, i1 1) +; CHECK-LABEL: define void @testTrunc() { +; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1 +; CHECK-NEXT: call void @foo(ptr [[A]]) +; CHECK-NEXT: [[B:%.*]] = load i8, ptr [[A]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @foo2(ptr [[A]], i8 [[B]]) +; CHECK-NEXT: call void @bar(i8 [[B]]) +; CHECK-NEXT: call void @fooBit(ptr [[A]], i1 true) +; CHECK-NEXT: [[TMP1:%.*]] = load i1, ptr [[A]], align 1, !invariant.group [[META0]] +; CHECK-NEXT: call void @fooBit(ptr [[A]], i1 [[TMP1]]) +; CHECK-NEXT: call void @fooBit(ptr [[A]], i1 [[TMP1]]) +; CHECK-NEXT: ret void +; + %a = alloca i8 + call void @foo(ptr %a) + %b = load i8, ptr %a, !invariant.group !0 + call void @foo2(ptr %a, i8 %b) + + %1 = load i8, ptr %a, !invariant.group !0 + call void @bar(i8 %1) + + call void @fooBit(ptr %a, i1 1) ; FIXME: %1 = trunc i8 %b to i1 - %2 = load i1, ptr %a, !invariant.group !0 + %2 = load i1, ptr %a, !invariant.group !0 ; FIXME-NEXT: call void @fooBit(ptr %a, i1 %1) - call void @fooBit(ptr %a, i1 %2) - %3 = load i1, ptr %a, !invariant.group !0 + call void @fooBit(ptr %a, i1 %2) + %3 = load i1, ptr %a, !invariant.group !0 ; FIXME-NEXT: call void @fooBit(ptr %a, i1 %1) - call void @fooBit(ptr %a, i1 %3) - ret void + call void @fooBit(ptr %a, i1 %3) + ret void } ; See comment in @testGEP0 on what NewGVN is lacking. -; CHECK-LABEL: define void @handling_loops() define void @handling_loops() { +; CHECK-LABEL: define void @handling_loops() { +; CHECK-NEXT: [[A:%.*]] = alloca [[STRUCT_A:%.*]], align 8 +; CHECK-NEXT: store ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), ptr [[A]], align 8, !invariant.group [[META0]] +; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr @unknownPtr, align 4 +; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i8 [[TMP1]], 0 +; CHECK-NEXT: br i1 [[TMP2]], label [[DOTLR_PH_I:%.*]], label [[_Z2G2R1A_EXIT:%.*]] +; CHECK: .lr.ph.i: +; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i8 [[TMP1]], 1 +; CHECK-NEXT: br i1 [[TMP3]], label [[DOT_CRIT_EDGE_PREHEADER:%.*]], label [[_Z2G2R1A_EXIT]] +; CHECK: ._crit_edge.preheader: +; CHECK-NEXT: br label [[DOT_CRIT_EDGE:%.*]] +; CHECK: ._crit_edge: +; CHECK-NEXT: [[TMP4:%.*]] = phi i8 [ [[TMP6:%.*]], [[DOT_CRIT_EDGE]] ], [ 1, [[DOT_CRIT_EDGE_PREHEADER]] ] +; CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), align 8 +; CHECK-NEXT: call void [[TMP5]](ptr nonnull [[A]]) +; CHECK-NEXT: [[TMP6]] = add nuw nsw i8 [[TMP4]], 1 +; CHECK-NEXT: [[TMP7:%.*]] = load i8, ptr @unknownPtr, align 4 +; CHECK-NEXT: [[TMP8:%.*]] = icmp slt i8 [[TMP6]], [[TMP7]] +; CHECK-NEXT: br i1 [[TMP8]], label [[DOT_CRIT_EDGE]], label [[_Z2G2R1A_EXIT_LOOPEXIT:%.*]] +; CHECK: _Z2g2R1A.exit.loopexit: +; CHECK-NEXT: br label [[_Z2G2R1A_EXIT]] +; CHECK: _Z2g2R1A.exit: +; CHECK-NEXT: ret void +; %a = alloca %struct.A, align 8 store ptr getelementptr inbounds ([3 x ptr], ptr @_ZTV1A, i64 0, i64 2), ptr %a, align 8, !invariant.group !0 %1 = load i8, ptr @unknownPtr, align 4 @@ -424,3 +590,6 @@ declare void @llvm.assume(i1 %cmp.vtables) #0 attributes #0 = { nounwind } !0 = !{} +;. +; CHECK: [[META0]] = !{} +;. diff --git a/llvm/test/Transforms/NewGVN/invariant.start.ll b/llvm/test/Transforms/NewGVN/invariant.start.ll index 100b79fd3bff285a1d2d67e36428606e440fbc3d..9bf1c5530006bd70bc6b6b97e759ede4a61b0385 100644 --- a/llvm/test/Transforms/NewGVN/invariant.start.ll +++ b/llvm/test/Transforms/NewGVN/invariant.start.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; Test to make sure llvm.invariant.start calls are not treated as clobbers. ; RUN: opt < %s -passes=newgvn -S | FileCheck %s @@ -7,10 +8,12 @@ declare void @llvm.invariant.end.p0(ptr, i64, ptr nocapture) nounwind ; We forward store to the load across the invariant.start intrinsic define i8 @forward_store() { -; CHECK-LABEL: @forward_store -; CHECK: call ptr @llvm.invariant.start.p0(i64 1, ptr %a) -; CHECK-NOT: load -; CHECK: ret i8 0 +; CHECK-LABEL: define i8 @forward_store() { +; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 0, ptr [[A]], align 1 +; CHECK-NEXT: [[I:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[A]]) +; CHECK-NEXT: ret i8 0 +; %a = alloca i8 store i8 0, ptr %a %i = call ptr @llvm.invariant.start.p0(i64 1, ptr %a) @@ -23,10 +26,18 @@ declare i8 @dummy(ptr nocapture) nounwind readonly ; We forward store to the load in the non-local analysis case, ; i.e. invariant.start is in another basic block. define i8 @forward_store_nonlocal(i1 %cond) { -; CHECK-LABEL: forward_store_nonlocal -; CHECK: call ptr @llvm.invariant.start.p0(i64 1, ptr %a) -; CHECK: ret i8 0 -; CHECK: ret i8 %val +; CHECK-LABEL: define i8 @forward_store_nonlocal( +; CHECK-SAME: i1 [[COND:%.*]]) { +; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 0, ptr [[A]], align 1 +; CHECK-NEXT: [[I:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[A]]) +; CHECK-NEXT: br i1 [[COND]], label [[LOADBLOCK:%.*]], label [[EXIT:%.*]] +; CHECK: loadblock: +; CHECK-NEXT: ret i8 0 +; CHECK: exit: +; CHECK-NEXT: [[VAL:%.*]] = call i8 @dummy(ptr [[A]]) +; CHECK-NEXT: ret i8 [[VAL]] +; %a = alloca i8 store i8 0, ptr %a %i = call ptr @llvm.invariant.start.p0(i64 1, ptr %a) @@ -43,12 +54,14 @@ exit: ; We should not value forward %foo to the invariant.end corresponding to %bar. define i8 @forward_store1() { -; CHECK-LABEL: forward_store1 -; CHECK: %foo = call ptr @llvm.invariant.start.p0 -; CHECK-NOT: load -; CHECK: %bar = call ptr @llvm.invariant.start.p0 -; CHECK: call void @llvm.invariant.end.p0(ptr %bar, i64 1, ptr %a) -; CHECK: ret i8 0 +; CHECK-LABEL: define i8 @forward_store1() { +; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 0, ptr [[A]], align 1 +; CHECK-NEXT: [[FOO:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[A]]) +; CHECK-NEXT: [[BAR:%.*]] = call ptr @llvm.invariant.start.p0(i64 1, ptr [[A]]) +; CHECK-NEXT: call void @llvm.invariant.end.p0(ptr [[BAR]], i64 1, ptr [[A]]) +; CHECK-NEXT: ret i8 0 +; %a = alloca i8 store i8 0, ptr %a %foo = call ptr @llvm.invariant.start.p0(i64 1, ptr %a) diff --git a/llvm/test/Transforms/NewGVN/lifetime-simple.ll b/llvm/test/Transforms/NewGVN/lifetime-simple.ll index 5d31101218ee6782d6c3845ec4f8806ffa83cf1d..55e46111fc9c93abaa5bcaf5925e70a3433580f9 100644 --- a/llvm/test/Transforms/NewGVN/lifetime-simple.ll +++ b/llvm/test/Transforms/NewGVN/lifetime-simple.ll @@ -1,12 +1,19 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn -S | FileCheck %s target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target triple = "i386-apple-darwin7" define i8 @test(ptr %P) nounwind { -; CHECK: lifetime.start -; CHECK-NOT: load -; CHECK: lifetime.end +; CHECK-LABEL: define i8 @test( +; CHECK-SAME: ptr [[P:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 32, ptr [[P]]) +; CHECK-NEXT: store i8 1, ptr [[P]], align 1 +; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 32, ptr [[P]]) +; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[P]], align 1 +; CHECK-NEXT: ret i8 [[TMP0]] +; entry: call void @llvm.lifetime.start.p0(i64 32, ptr %P) %0 = load i8, ptr %P diff --git a/llvm/test/Transforms/NewGVN/load-constant-mem.ll b/llvm/test/Transforms/NewGVN/load-constant-mem.ll index 06439c59f9d2d7967230c24620f2412f74a36d59..ae91147237fade93b9f599019ea4bddbcd025004 100644 --- a/llvm/test/Transforms/NewGVN/load-constant-mem.ll +++ b/llvm/test/Transforms/NewGVN/load-constant-mem.ll @@ -7,14 +7,14 @@ define i32 @test(ptr %p, i32 %i) nounwind { ; CHECK-LABEL: @test( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[P:%.*]] = getelementptr [4 x i32], ptr @G, i32 0, i32 [[I:%.*]] -; CHECK-NEXT: store i8 4, ptr [[P:%.*]] +; CHECK-NEXT: store i8 4, ptr [[P1:%.*]], align 1 ; CHECK-NEXT: ret i32 0 ; entry: - %P = getelementptr [4 x i32], ptr @G, i32 0, i32 %i - %A = load i32, ptr %P + %p.i = getelementptr [4 x i32], ptr @G, i32 0, i32 %i + %A = load i32, ptr %p.i store i8 4, ptr %p - %B = load i32, ptr %P + %B = load i32, ptr %p.i %C = sub i32 %A, %B ret i32 %C } diff --git a/llvm/test/Transforms/NewGVN/load-from-unreachable-predecessor.ll b/llvm/test/Transforms/NewGVN/load-from-unreachable-predecessor.ll index 74cb70066eb1dccd091ee80d8d53cbb15eac4f68..3ca9b9efbe4c2615e9029056678c9c39002d960d 100644 --- a/llvm/test/Transforms/NewGVN/load-from-unreachable-predecessor.ll +++ b/llvm/test/Transforms/NewGVN/load-from-unreachable-predecessor.ll @@ -1,12 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -S < %s | FileCheck %s ; Check that an unreachable predecessor to a PHI node doesn't cause a crash. ; PR21625. define i32 @f(ptr %f) { -; CHECK: bb0: +; CHECK-LABEL: define i32 @f( +; CHECK-SAME: ptr [[F:%.*]]) { +; CHECK-NEXT: bb0: +; CHECK-NEXT: br label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: store i8 poison, ptr null, align 1 +; CHECK-NEXT: br i1 false, label [[BB1:%.*]], label [[BB2]] +; CHECK: bb2: +; CHECK-NEXT: [[STOREMERGE:%.*]] = load i32, ptr null, align 4 +; CHECK-NEXT: ret i32 [[STOREMERGE]] +; ; Load should be removed, since it's ignored. -; CHECK-NEXT: br label bb0: %bar = load ptr, ptr %f br label %bb2 diff --git a/llvm/test/Transforms/NewGVN/loadforward.ll b/llvm/test/Transforms/NewGVN/loadforward.ll index d8a9022dc66f6b35a6c5c04c82259a9896f9709a..85ceafd433f45a03792dff9f981d9c9d0af281a5 100644 --- a/llvm/test/Transforms/NewGVN/loadforward.ll +++ b/llvm/test/Transforms/NewGVN/loadforward.ll @@ -9,8 +9,8 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ;; Test that we forward the first store to the second load define i16 @bazinga() { ; CHECK-LABEL: @bazinga( -; CHECK-NEXT: [[_TMP10:%.*]] = load i16, ptr getelementptr inbounds (%rec11, ptr @str, i64 0, i32 1) -; CHECK-NEXT: store i16 [[_TMP10]], ptr @str +; CHECK-NEXT: [[_TMP10:%.*]] = load i16, ptr getelementptr inbounds ([[REC11:%.*]], ptr @str, i64 0, i32 1), align 2 +; CHECK-NEXT: store i16 [[_TMP10]], ptr @str, align 2 ; CHECK-NEXT: [[_TMP15:%.*]] = icmp eq i16 [[_TMP10]], 3 ; CHECK-NEXT: [[_TMP16:%.*]] = select i1 [[_TMP15]], i16 1, i16 0 ; CHECK-NEXT: br label [[BB1:%.*]] diff --git a/llvm/test/Transforms/NewGVN/malloc-load-removal.ll b/llvm/test/Transforms/NewGVN/malloc-load-removal.ll index b487acfe93e4762b76edc7f932cb8ae8b16c14b8..3e11d9221c9dd223175a2075f63d13aafad1e140 100644 --- a/llvm/test/Transforms/NewGVN/malloc-load-removal.ll +++ b/llvm/test/Transforms/NewGVN/malloc-load-removal.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -S -passes=newgvn < %s | FileCheck %s ; PR13694 @@ -7,6 +8,17 @@ target triple = "x86_64-apple-macosx10.8.0" declare ptr @malloc(i64) nounwind allockind("alloc,uninitialized") allocsize(0) "alloc-family"="malloc" define noalias ptr @test1() nounwind uwtable ssp { +; CHECK-LABEL: define noalias ptr @test1( +; CHECK-SAME: ) #[[ATTR1:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i64 100) #[[ATTR2:[0-9]+]] +; CHECK-NEXT: br i1 undef, label [[IF_END:%.*]], label [[IF_THEN:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i8 0, ptr [[CALL]], align 1 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: ret ptr [[CALL]] +; entry: %call = tail call ptr @malloc(i64 100) nounwind %0 = load i8, ptr %call, align 1 @@ -20,14 +32,22 @@ if.then: ; preds = %entry if.end: ; preds = %if.then, %entry ret ptr %call -; CHECK-LABEL: @test1( -; CHECK-NOT: load -; CHECK-NOT: icmp } declare ptr @_Znwm(i64) nounwind define noalias ptr @test2() nounwind uwtable ssp { +; CHECK-LABEL: define noalias ptr @test2( +; CHECK-SAME: ) #[[ATTR1]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @_Znwm(i64 100) #[[ATTR2]] +; CHECK-NEXT: br i1 undef, label [[IF_END:%.*]], label [[IF_THEN:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i8 0, ptr [[CALL]], align 1 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: ret ptr [[CALL]] +; entry: %call = tail call ptr @_Znwm(i64 100) nounwind %0 = load i8, ptr %call, align 1 @@ -41,14 +61,22 @@ if.then: ; preds = %entry if.end: ; preds = %if.then, %entry ret ptr %call -; CHECK-LABEL: @test2( -; CHECK-NOT: load -; CHECK-NOT: icmp } declare ptr @aligned_alloc(i64 allocalign, i64) nounwind allockind("alloc,uninitialized,aligned") allocsize(1) "alloc-family"="malloc" define noalias ptr @test3() nounwind uwtable ssp { +; CHECK-LABEL: define noalias ptr @test3( +; CHECK-SAME: ) #[[ATTR1]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @aligned_alloc(i64 256, i64 32) #[[ATTR2]] +; CHECK-NEXT: br i1 undef, label [[IF_END:%.*]], label [[IF_THEN:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i8 0, ptr [[CALL]], align 1 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: ret ptr [[CALL]] +; entry: %call = tail call ptr @aligned_alloc(i64 256, i64 32) nounwind %0 = load i8, ptr %call, align 32 @@ -62,7 +90,4 @@ if.then: ; preds = %entry if.end: ; preds = %if.then, %entry ret ptr %call -; CHECK-LABEL: @test3( -; CHECK-NOT: load -; CHECK-NOT: icmp } diff --git a/llvm/test/Transforms/NewGVN/memory-handling.ll b/llvm/test/Transforms/NewGVN/memory-handling.ll index b1e1c4f2de3e1d6668387418843e2574e0300dc6..c72ff749ba410d4684181877791cc4cbf0850226 100644 --- a/llvm/test/Transforms/NewGVN/memory-handling.ll +++ b/llvm/test/Transforms/NewGVN/memory-handling.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ;; This test is really dependent on propagating a lot of memory info around, but in the end, not ;; screwing up a single add. ; RUN: opt < %s -passes=newgvn -S | FileCheck %s @@ -20,6 +21,121 @@ declare ptr @__ctype_b_loc() local_unnamed_addr #1 ; Function Attrs: nounwind uwtable define void @BuildMask(ptr nocapture readonly) local_unnamed_addr #0 { +; CHECK-LABEL: define void @BuildMask( +; CHECK-SAME: ptr nocapture readonly [[TMP0:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr align 16 @alPhrase, i8 0, i64 416, i1 false) +; CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr align 16 @aqMainMask, i8 0, i64 16, i1 false) +; CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr align 16 @aqMainSign, i8 0, i64 16, i1 false) +; CHECK-NEXT: br label [[DOTSINK_SPLIT:%.*]] +; CHECK: .sink.split: +; CHECK-NEXT: [[DOT0:%.*]] = phi ptr [ [[TMP0]], [[TMP1:%.*]] ], [ [[TMP3:%.*]], [[TMP14:%.*]] ] +; CHECK-NEXT: [[DOTSINK:%.*]] = phi i32 [ 0, [[TMP1]] ], [ [[TMP22:%.*]], [[TMP14]] ] +; CHECK-NEXT: store i32 [[DOTSINK]], ptr @cchPhraseLength, align 4, !tbaa [[TBAA1:![0-9]+]] +; CHECK-NEXT: br label [[TMP2:%.*]] +; CHECK: 2: +; CHECK-NEXT: [[DOT1:%.*]] = phi ptr [ [[DOT0]], [[DOTSINK_SPLIT]] ], [ [[TMP3]], [[TMP6:%.*]] ] +; CHECK-NEXT: [[TMP3]] = getelementptr inbounds i8, ptr [[DOT1]], i64 1 +; CHECK-NEXT: [[TMP4:%.*]] = load i8, ptr [[DOT1]], align 1 +; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: br i1 [[TMP5]], label [[DOTPREHEADER_PREHEADER:%.*]], label [[TMP6]] +; CHECK: .preheader.preheader: +; CHECK-NEXT: br label [[DOTPREHEADER:%.*]] +; CHECK: 6: +; CHECK-NEXT: [[TMP7:%.*]] = tail call ptr @__ctype_b_loc() #[[ATTR4:[0-9]+]] +; CHECK-NEXT: [[TMP8:%.*]] = load ptr, ptr [[TMP7]], align 8, !tbaa [[TBAA5:![0-9]+]] +; CHECK-NEXT: [[TMP9:%.*]] = sext i8 [[TMP4]] to i64 +; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i16, ptr [[TMP8]], i64 [[TMP9]] +; CHECK-NEXT: [[TMP11:%.*]] = load i16, ptr [[TMP10]], align 2, !tbaa [[TBAA7:![0-9]+]] +; CHECK-NEXT: [[TMP12:%.*]] = and i16 [[TMP11]], 1024 +; CHECK-NEXT: [[TMP13:%.*]] = icmp eq i16 [[TMP12]], 0 +; CHECK-NEXT: br i1 [[TMP13]], label [[TMP2]], label [[TMP14]] +; CHECK: 14: +; CHECK-NEXT: [[TMP15:%.*]] = sext i8 [[TMP4]] to i32 +; CHECK-NEXT: [[TMP16:%.*]] = tail call i32 @tolower(i32 [[TMP15]]) #[[ATTR5:[0-9]+]] +; CHECK-NEXT: [[TMP17:%.*]] = add nsw i32 [[TMP16]], -97 +; CHECK-NEXT: [[TMP18:%.*]] = sext i32 [[TMP17]] to i64 +; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds [26 x %struct.Letter], ptr @alPhrase, i64 0, i64 [[TMP18]], i32 0 +; CHECK-NEXT: [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 16, !tbaa [[TBAA9:![0-9]+]] +; CHECK-NEXT: [[TMP21:%.*]] = add i32 [[TMP20]], 1 +; CHECK-NEXT: store i32 [[TMP21]], ptr [[TMP19]], align 16, !tbaa [[TBAA9]] +; CHECK-NEXT: [[TMP22]] = add nsw i32 [[DOTSINK]], 1 +; CHECK-NEXT: br label [[DOTSINK_SPLIT]] +; CHECK: .preheader: +; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[DOTPREHEADER_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[TMP57:%.*]] ] +; CHECK-NEXT: [[DOT04961:%.*]] = phi i32 [ [[DOT2:%.*]], [[TMP57]] ], [ 0, [[DOTPREHEADER_PREHEADER]] ] +; CHECK-NEXT: [[DOT05160:%.*]] = phi i32 [ [[DOT253:%.*]], [[TMP57]] ], [ 0, [[DOTPREHEADER_PREHEADER]] ] +; CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds [26 x %struct.Letter], ptr @alPhrase, i64 0, i64 [[INDVARS_IV]], i32 0 +; CHECK-NEXT: [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 16, !tbaa [[TBAA9]] +; CHECK-NEXT: [[TMP25:%.*]] = icmp eq i32 [[TMP24]], 0 +; CHECK-NEXT: [[TMP26:%.*]] = getelementptr inbounds [26 x i32], ptr @auGlobalFrequency, i64 0, i64 [[INDVARS_IV]] +; CHECK-NEXT: br i1 [[TMP25]], label [[TMP27:%.*]], label [[TMP28:%.*]] +; CHECK: 27: +; CHECK-NEXT: store i32 -1, ptr [[TMP26]], align 4, !tbaa [[TBAA1]] +; CHECK-NEXT: br label [[TMP57]] +; CHECK: 28: +; CHECK-NEXT: store i32 0, ptr [[TMP26]], align 4, !tbaa [[TBAA1]] +; CHECK-NEXT: [[TMP29:%.*]] = zext i32 [[TMP24]] to i64 +; CHECK-NEXT: br i1 false, label [[DOT_CRIT_EDGE:%.*]], label [[DOTLR_PH_PREHEADER:%.*]] +; CHECK: .lr.ph.preheader: +; CHECK-NEXT: br label [[DOTLR_PH:%.*]] +; CHECK: .lr.ph: +; CHECK-NEXT: [[DOT04658:%.*]] = phi i64 [ [[TMP31:%.*]], [[DOTLR_PH]] ], [ 1, [[DOTLR_PH_PREHEADER]] ] +; CHECK-NEXT: [[DOT04857:%.*]] = phi i32 [ [[TMP30:%.*]], [[DOTLR_PH]] ], [ 1, [[DOTLR_PH_PREHEADER]] ] +; CHECK-NEXT: [[TMP30]] = add nuw nsw i32 [[DOT04857]], 1 +; CHECK-NEXT: [[TMP31]] = shl i64 [[DOT04658]], 1 +; CHECK-NEXT: [[TMP32:%.*]] = icmp ult i64 [[TMP29]], [[TMP31]] +; CHECK-NEXT: br i1 [[TMP32]], label [[DOT_CRIT_EDGE_LOOPEXIT:%.*]], label [[DOTLR_PH]] +; CHECK: ._crit_edge.loopexit: +; CHECK-NEXT: br label [[DOT_CRIT_EDGE]] +; CHECK: ._crit_edge: +; CHECK-NEXT: [[DOT048_LCSSA:%.*]] = phi i32 [ poison, [[TMP28]] ], [ [[TMP30]], [[DOT_CRIT_EDGE_LOOPEXIT]] ] +; CHECK-NEXT: [[DOT046_LCSSA:%.*]] = phi i64 [ poison, [[TMP28]] ], [ [[TMP31]], [[DOT_CRIT_EDGE_LOOPEXIT]] ] +; CHECK-NEXT: [[TMP33:%.*]] = add nsw i32 [[DOT048_LCSSA]], [[DOT04961]] +; CHECK-NEXT: [[TMP34:%.*]] = icmp ugt i32 [[TMP33]], 64 +; CHECK-NEXT: br i1 [[TMP34]], label [[TMP35:%.*]], label [[TMP39:%.*]] +; CHECK: 35: +; CHECK-NEXT: [[TMP36:%.*]] = add i32 [[DOT05160]], 1 +; CHECK-NEXT: [[TMP37:%.*]] = icmp ugt i32 [[TMP36]], 1 +; CHECK-NEXT: br i1 [[TMP37]], label [[TMP38:%.*]], label [[TMP39]] +; CHECK: 38: +; CHECK-NEXT: tail call void @Fatal(ptr @.str.7, i32 0) +; CHECK-NEXT: br label [[TMP39]] +; CHECK: 39: +; CHECK-NEXT: [[DOT152:%.*]] = phi i32 [ [[DOT05160]], [[DOT_CRIT_EDGE]] ], [ [[TMP36]], [[TMP38]] ], [ [[TMP36]], [[TMP35]] ] +; CHECK-NEXT: [[DOT150:%.*]] = phi i32 [ [[DOT04961]], [[DOT_CRIT_EDGE]] ], [ 0, [[TMP38]] ], [ 0, [[TMP35]] ] +; CHECK-NEXT: [[TMP40:%.*]] = add i64 [[DOT046_LCSSA]], 4294967295 +; CHECK-NEXT: [[TMP41:%.*]] = trunc i64 [[TMP40]] to i32 +; CHECK-NEXT: [[TMP42:%.*]] = getelementptr inbounds [26 x %struct.Letter], ptr @alPhrase, i64 0, i64 [[INDVARS_IV]], i32 2 +; CHECK-NEXT: store i32 [[TMP41]], ptr [[TMP42]], align 8, !tbaa [[TBAA11:![0-9]+]] +; CHECK-NEXT: [[TMP43:%.*]] = zext i32 [[DOT150]] to i64 +; CHECK-NEXT: [[DOT046_:%.*]] = shl i64 [[DOT046_LCSSA]], [[TMP43]] +; CHECK-NEXT: [[TMP44:%.*]] = zext i32 [[DOT152]] to i64 +; CHECK-NEXT: [[TMP45:%.*]] = getelementptr inbounds [2 x i64], ptr @aqMainSign, i64 0, i64 [[TMP44]] +; CHECK-NEXT: [[TMP46:%.*]] = load i64, ptr [[TMP45]], align 8, !tbaa [[TBAA12:![0-9]+]] +; CHECK-NEXT: [[TMP47:%.*]] = or i64 [[TMP46]], [[DOT046_]] +; CHECK-NEXT: store i64 [[TMP47]], ptr [[TMP45]], align 8, !tbaa [[TBAA12]] +; CHECK-NEXT: [[TMP48:%.*]] = load i32, ptr [[TMP23]], align 16, !tbaa [[TBAA9]] +; CHECK-NEXT: [[TMP49:%.*]] = zext i32 [[TMP48]] to i64 +; CHECK-NEXT: [[TMP50:%.*]] = shl i64 [[TMP49]], [[TMP43]] +; CHECK-NEXT: [[TMP51:%.*]] = getelementptr inbounds [2 x i64], ptr @aqMainMask, i64 0, i64 [[TMP44]] +; CHECK-NEXT: [[TMP52:%.*]] = load i64, ptr [[TMP51]], align 8, !tbaa [[TBAA12]] +; CHECK-NEXT: [[TMP53:%.*]] = or i64 [[TMP50]], [[TMP52]] +; CHECK-NEXT: store i64 [[TMP53]], ptr [[TMP51]], align 8, !tbaa [[TBAA12]] +; CHECK-NEXT: [[TMP54:%.*]] = getelementptr inbounds [26 x %struct.Letter], ptr @alPhrase, i64 0, i64 [[INDVARS_IV]], i32 1 +; CHECK-NEXT: store i32 [[DOT150]], ptr [[TMP54]], align 4, !tbaa [[TBAA14:![0-9]+]] +; CHECK-NEXT: [[TMP55:%.*]] = getelementptr inbounds [26 x %struct.Letter], ptr @alPhrase, i64 0, i64 [[INDVARS_IV]], i32 3 +; CHECK-NEXT: store i32 [[DOT152]], ptr [[TMP55]], align 4, !tbaa [[TBAA15:![0-9]+]] +; CHECK-NEXT: [[TMP56:%.*]] = add nsw i32 [[DOT150]], [[DOT048_LCSSA]] +; CHECK-NEXT: br label [[TMP57]] +; CHECK: 57: +; CHECK-NEXT: [[DOT253]] = phi i32 [ [[DOT05160]], [[TMP27]] ], [ [[DOT152]], [[TMP39]] ] +; CHECK-NEXT: [[DOT2]] = phi i32 [ [[DOT04961]], [[TMP27]] ], [ [[TMP56]], [[TMP39]] ] +; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], 26 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[DOTPREHEADER]], label [[TMP58:%.*]] +; CHECK: 58: +; CHECK-NEXT: ret void +; tail call void @llvm.memset.p0.i64(ptr align 16 @alPhrase, i8 0, i64 416, i1 false) tail call void @llvm.memset.p0.i64(ptr align 16 @aqMainMask, i8 0, i64 16, i1 false) tail call void @llvm.memset.p0.i64(ptr align 16 @aqMainSign, i8 0, i64 16, i1 false) @@ -113,7 +229,6 @@ define void @BuildMask(ptr nocapture readonly) local_unnamed_addr #0 { ; If we screw up the revisitation of the users of store of %sink above ; we will end up propagating and simplifying this to 1 in the final output ; because we keep an optimistic assumption we should not. -; CHECK: add i32 %.05160, 1 %37 = add i32 %.05160, 1 %38 = icmp ugt i32 %37, 1 br i1 %38, label %39, label %40 @@ -193,3 +308,20 @@ attributes #5 = { nounwind readonly } !14 = !{!"long", !3, i64 0} !15 = !{!11, !2, i64 4} !16 = !{!11, !2, i64 12} +;. +; CHECK: [[TBAA1]] = !{[[META2:![0-9]+]], [[META2]], i64 0} +; CHECK: [[META2]] = !{!"int", [[META3:![0-9]+]], i64 0} +; CHECK: [[META3]] = !{!"omnipotent char", [[META4:![0-9]+]], i64 0} +; CHECK: [[META4]] = !{!"Simple C/C++ TBAA"} +; CHECK: [[TBAA5]] = !{[[META6:![0-9]+]], [[META6]], i64 0} +; CHECK: [[META6]] = !{!"any pointer", [[META3]], i64 0} +; CHECK: [[TBAA7]] = !{[[META8:![0-9]+]], [[META8]], i64 0} +; CHECK: [[META8]] = !{!"short", [[META3]], i64 0} +; CHECK: [[TBAA9]] = !{[[META10:![0-9]+]], [[META2]], i64 0} +; CHECK: [[META10]] = !{!"", [[META2]], i64 0, [[META2]], i64 4, [[META2]], i64 8, [[META2]], i64 12} +; CHECK: [[TBAA11]] = !{[[META10]], [[META2]], i64 8} +; CHECK: [[TBAA12]] = !{[[META13:![0-9]+]], [[META13]], i64 0} +; CHECK: [[META13]] = !{!"long", [[META3]], i64 0} +; CHECK: [[TBAA14]] = !{[[META10]], [[META2]], i64 4} +; CHECK: [[TBAA15]] = !{[[META10]], [[META2]], i64 12} +;. diff --git a/llvm/test/Transforms/NewGVN/metadata-nonnull.ll b/llvm/test/Transforms/NewGVN/metadata-nonnull.ll index cd0922f901af4c2a08bc08756c80917924c38b57..5de4c581c051c3d2a67e432e0770255a38564ace 100644 --- a/llvm/test/Transforms/NewGVN/metadata-nonnull.ll +++ b/llvm/test/Transforms/NewGVN/metadata-nonnull.ll @@ -150,7 +150,7 @@ define ptr @test7(ptr %v0) { ; CHECK-LABEL: define ptr @test7 ; CHECK-SAME: (ptr [[V0:%.*]]) { ; CHECK-NEXT: top: -; CHECK-NEXT: [[V1:%.*]] = load ptr, ptr [[V0]], align 8, !nonnull !0 +; CHECK-NEXT: [[V1:%.*]] = load ptr, ptr [[V0]], align 8, !nonnull [[META0:![0-9]+]] ; CHECK-NEXT: call void @use2(ptr [[V1]]) ; CHECK-NEXT: br i1 undef, label [[BB1:%.*]], label [[BB2:%.*]] ; CHECK: bb1: diff --git a/llvm/test/Transforms/NewGVN/metadata-simplify.ll b/llvm/test/Transforms/NewGVN/metadata-simplify.ll index a84c581165c3ae36a41f8be9012c0ac7bc5dfb16..e981e3702d5601bdd739fddeb4ab03efb355b26e 100644 --- a/llvm/test/Transforms/NewGVN/metadata-simplify.ll +++ b/llvm/test/Transforms/NewGVN/metadata-simplify.ll @@ -9,11 +9,11 @@ define i1 @test1(ptr %arg, i1 %arg2) { ; CHECK-LABEL: @test1( ; CHECK-NEXT: br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] ; CHECK: bb1: -; CHECK-NEXT: [[LOAD1:%.*]] = load ptr, ptr [[ARG:%.*]], !nonnull !0 +; CHECK-NEXT: [[LOAD1:%.*]] = load ptr, ptr [[ARG:%.*]], align 8, !nonnull [[META0:![0-9]+]] ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq ptr [[LOAD1]], null ; CHECK-NEXT: ret i1 [[CMP1]] ; CHECK: bb2: -; CHECK-NEXT: [[LOAD2:%.*]] = load ptr, ptr [[ARG]] +; CHECK-NEXT: [[LOAD2:%.*]] = load ptr, ptr [[ARG]], align 8 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq ptr [[LOAD2]], null ; CHECK-NEXT: ret i1 [[CMP2]] ; @@ -34,11 +34,11 @@ define i1 @test2(ptr %arg, i1 %arg2) { ; CHECK-LABEL: @test2( ; CHECK-NEXT: br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] ; CHECK: bb1: -; CHECK-NEXT: [[LOAD1:%.*]] = load ptr, ptr [[ARG:%.*]] +; CHECK-NEXT: [[LOAD1:%.*]] = load ptr, ptr [[ARG:%.*]], align 8 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq ptr [[LOAD1]], null ; CHECK-NEXT: ret i1 [[CMP1]] ; CHECK: bb2: -; CHECK-NEXT: [[LOAD2:%.*]] = load ptr, ptr [[ARG]], !nonnull !0 +; CHECK-NEXT: [[LOAD2:%.*]] = load ptr, ptr [[ARG]], align 8, !nonnull [[META0]] ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq ptr [[LOAD2]], null ; CHECK-NEXT: ret i1 [[CMP2]] ; @@ -60,11 +60,11 @@ define i1 @test3(ptr %ptr, i1 %arg2) { ; CHECK-LABEL: @test3( ; CHECK-NEXT: br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] ; CHECK: bb1: -; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[PTR:%.*]], !range !1 +; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[PTR:%.*]], align 4, !range [[RNG1:![0-9]+]] ; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[LOAD1]], 999 ; CHECK-NEXT: ret i1 [[CMP1]] ; CHECK: bb2: -; CHECK-NEXT: [[LOAD2:%.*]] = load i32, ptr [[PTR]] +; CHECK-NEXT: [[LOAD2:%.*]] = load i32, ptr [[PTR]], align 4 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[LOAD2]], 999 ; CHECK-NEXT: ret i1 [[CMP2]] ; @@ -85,11 +85,11 @@ define i1 @test4(ptr %ptr, i1 %arg2) { ; CHECK-LABEL: @test4( ; CHECK-NEXT: br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] ; CHECK: bb1: -; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[PTR:%.*]] +; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[PTR:%.*]], align 4 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[LOAD1]], 999 ; CHECK-NEXT: ret i1 [[CMP1]] ; CHECK: bb2: -; CHECK-NEXT: [[LOAD2:%.*]] = load i32, ptr [[PTR]], !range !1 +; CHECK-NEXT: [[LOAD2:%.*]] = load i32, ptr [[PTR]], align 4, !range [[RNG1]] ; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i32 [[LOAD2]], 999 ; CHECK-NEXT: ret i1 [[CMP2]] ; @@ -110,11 +110,11 @@ define i1 @test5(ptr %ptr, i1 %arg2) { ; CHECK-LABEL: @test5( ; CHECK-NEXT: br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] ; CHECK: bb1: -; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[PTR:%.*]], !range !1 +; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[PTR:%.*]], align 4, !range [[RNG1]] ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[LOAD1]], 999 ; CHECK-NEXT: ret i1 [[CMP1]] ; CHECK: bb2: -; CHECK-NEXT: [[LOAD2:%.*]] = load i32, ptr [[PTR]] +; CHECK-NEXT: [[LOAD2:%.*]] = load i32, ptr [[PTR]], align 4 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[LOAD2]], 999 ; CHECK-NEXT: ret i1 [[CMP2]] ; @@ -135,11 +135,11 @@ define i1 @test6(ptr %ptr, i1 %arg2) { ; CHECK-LABEL: @test6( ; CHECK-NEXT: br i1 [[ARG2:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] ; CHECK: bb1: -; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[PTR:%.*]] +; CHECK-NEXT: [[LOAD1:%.*]] = load i32, ptr [[PTR:%.*]], align 4 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[LOAD1]], 999 ; CHECK-NEXT: ret i1 [[CMP1]] ; CHECK: bb2: -; CHECK-NEXT: [[LOAD2:%.*]] = load i32, ptr [[PTR]], !range !1 +; CHECK-NEXT: [[LOAD2:%.*]] = load i32, ptr [[PTR]], align 4, !range [[RNG1]] ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[LOAD2]], 999 ; CHECK-NEXT: ret i1 [[CMP2]] ; diff --git a/llvm/test/Transforms/NewGVN/noalias.ll b/llvm/test/Transforms/NewGVN/noalias.ll index 5f0c5dd8a3aeaf68067247c0b89c9486412efdeb..2cb5c196a7abf7df5caa6b269cd7b42473dbef92 100644 --- a/llvm/test/Transforms/NewGVN/noalias.ll +++ b/llvm/test/Transforms/NewGVN/noalias.ll @@ -1,10 +1,13 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -S < %s | FileCheck %s define i32 @test1(ptr %p, ptr %q) { -; CHECK-LABEL: @test1(ptr %p, ptr %q) -; CHECK: load i32, ptr %p -; CHECK-NOT: noalias -; CHECK: %c = add i32 %a, %a +; CHECK-LABEL: define i32 @test1( +; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { +; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4 +; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] +; CHECK-NEXT: ret i32 [[C]] +; %a = load i32, ptr %p, !noalias !3 %b = load i32, ptr %p %c = add i32 %a, %b @@ -12,9 +15,12 @@ define i32 @test1(ptr %p, ptr %q) { } define i32 @test2(ptr %p, ptr %q) { -; CHECK-LABEL: @test2(ptr %p, ptr %q) -; CHECK: load i32, ptr %p, align 4, !alias.scope ![[SCOPE1:[0-9]+]] -; CHECK: %c = add i32 %a, %a +; CHECK-LABEL: define i32 @test2( +; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { +; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4, !alias.scope [[META0:![0-9]+]] +; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] +; CHECK-NEXT: ret i32 [[C]] +; %a = load i32, ptr %p, !alias.scope !3 %b = load i32, ptr %p, !alias.scope !3 %c = add i32 %a, %b @@ -22,17 +28,18 @@ define i32 @test2(ptr %p, ptr %q) { } define i32 @test3(ptr %p, ptr %q) { -; CHECK-LABEL: @test3(ptr %p, ptr %q) -; CHECK: load i32, ptr %p, align 4, !alias.scope ![[SCOPE2:[0-9]+]] -; CHECK: %c = add i32 %a, %a +; CHECK-LABEL: define i32 @test3( +; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { +; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4, !alias.scope [[META3:![0-9]+]] +; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] +; CHECK-NEXT: ret i32 [[C]] +; %a = load i32, ptr %p, !alias.scope !4 %b = load i32, ptr %p, !alias.scope !5 %c = add i32 %a, %b ret i32 %c } -; CHECK: ![[SCOPE1]] = !{!{{[0-9]+}}} -; CHECK: ![[SCOPE2]] = !{!{{[0-9]+}}, !{{[0-9]+}}} declare i32 @foo(ptr) readonly !0 = distinct !{!0, !2, !"callee0: %a"} @@ -42,3 +49,10 @@ declare i32 @foo(ptr) readonly !3 = !{!0} !4 = !{!1} !5 = !{!0, !1} +;. +; CHECK: [[META0]] = !{[[META1:![0-9]+]]} +; CHECK: [[META1]] = distinct !{[[META1]], [[META2:![0-9]+]], !"callee0: %a"} +; CHECK: [[META2]] = distinct !{[[META2]], !"callee0"} +; CHECK: [[META3]] = !{[[META4:![0-9]+]], [[META1]]} +; CHECK: [[META4]] = distinct !{[[META4]], [[META2]], !"callee0: %b"} +;. diff --git a/llvm/test/Transforms/NewGVN/nomemlocation.ll b/llvm/test/Transforms/NewGVN/nomemlocation.ll index 0f716b30801b25dfab641ea1a8f92544651e2861..332e6c6304c31560ae8b5fc20ee119e31ecef9c9 100644 --- a/llvm/test/Transforms/NewGVN/nomemlocation.ll +++ b/llvm/test/Transforms/NewGVN/nomemlocation.ll @@ -1,8 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -S -p='newgvn' | FileCheck %s ; MemorySSA should be able to handle a clobber query with an empty MemoryLocation. -; CHECK: @userread define ptr @userread(ptr %p) { +; CHECK-LABEL: define ptr @userread( +; CHECK-SAME: ptr [[P:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[POS:%.*]] = phi i64 [ 1, [[ENTRY:%.*]] ], [ [[DIFF:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 [[POS]] +; CHECK-NEXT: [[LD:%.*]] = load ptr, ptr [[GEP]], align 8 +; CHECK-NEXT: [[READVAL:%.*]] = call i64 @fread(ptr noundef nonnull [[GEP]], i64 noundef 1, i64 noundef [[POS]], ptr noundef [[LD]]) +; CHECK-NEXT: [[READVALISPOS:%.*]] = icmp eq i64 [[READVAL]], [[POS]] +; CHECK-NEXT: call void @llvm.assume(i1 [[READVALISPOS]]) +; CHECK-NEXT: [[DIFF]] = sub i64 0, [[POS]] +; CHECK-NEXT: br label [[LOOP]] +; entry: br label %loop diff --git a/llvm/test/Transforms/NewGVN/non-integral-pointers.ll b/llvm/test/Transforms/NewGVN/non-integral-pointers.ll index 6119577d3b2422e04a9a9ba535953aca7b4b8ac4..1e3da6e295d16b2897d035b6d52e64b91a307a05 100644 --- a/llvm/test/Transforms/NewGVN/non-integral-pointers.ll +++ b/llvm/test/Transforms/NewGVN/non-integral-pointers.ll @@ -1,37 +1,55 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -S < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128-ni:4" target triple = "x86_64-unknown-linux-gnu" define void @f0(i1 %alwaysFalse, i64 %val, ptr %loc) { -; CHECK-LABEL: @f0( -; CHECK-NOT: inttoptr -; CHECK-NOT: ptrtoint - entry: +; CHECK-LABEL: define void @f0( +; CHECK-SAME: i1 [[ALWAYSFALSE:%.*]], i64 [[VAL:%.*]], ptr [[LOC:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: store i64 [[VAL]], ptr [[LOC]], align 8 +; CHECK-NEXT: br i1 [[ALWAYSFALSE]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]] +; CHECK: neverTaken: +; CHECK-NEXT: [[PTR:%.*]] = load ptr addrspace(4), ptr [[LOC]], align 8 +; CHECK-NEXT: store i8 5, ptr addrspace(4) [[PTR]], align 1 +; CHECK-NEXT: ret void +; CHECK: alwaysTaken: +; CHECK-NEXT: ret void +; + entry: store i64 %val, ptr %loc br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken - neverTaken: + neverTaken: %ptr = load ptr addrspace(4), ptr %loc store i8 5, ptr addrspace(4) %ptr ret void - alwaysTaken: + alwaysTaken: ret void } define i64 @f1(i1 %alwaysFalse, ptr addrspace(4) %val, ptr %loc) { -; CHECK-LABEL: @f1( -; CHECK-NOT: inttoptr -; CHECK-NOT: ptrtoint - entry: +; CHECK-LABEL: define i64 @f1( +; CHECK-SAME: i1 [[ALWAYSFALSE:%.*]], ptr addrspace(4) [[VAL:%.*]], ptr [[LOC:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: store ptr addrspace(4) [[VAL]], ptr [[LOC]], align 8 +; CHECK-NEXT: br i1 [[ALWAYSFALSE]], label [[NEVERTAKEN:%.*]], label [[ALWAYSTAKEN:%.*]] +; CHECK: neverTaken: +; CHECK-NEXT: [[INT:%.*]] = load i64, ptr [[LOC]], align 8 +; CHECK-NEXT: ret i64 [[INT]] +; CHECK: alwaysTaken: +; CHECK-NEXT: ret i64 42 +; + entry: store ptr addrspace(4) %val, ptr %loc br i1 %alwaysFalse, label %neverTaken, label %alwaysTaken - neverTaken: + neverTaken: %int = load i64, ptr %loc ret i64 %int - alwaysTaken: + alwaysTaken: ret i64 42 } diff --git a/llvm/test/Transforms/NewGVN/null-aliases-nothing.ll b/llvm/test/Transforms/NewGVN/null-aliases-nothing.ll index 666621119d4cb4b796cf16c1664f61ee4a0e689e..25295fac7400d9f78556f171f8001edbe5a93092 100644 --- a/llvm/test/Transforms/NewGVN/null-aliases-nothing.ll +++ b/llvm/test/Transforms/NewGVN/null-aliases-nothing.ll @@ -1,19 +1,25 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn -S | FileCheck %s %t = type { i32 } declare void @test1f(ptr) define void @test1(ptr noalias %stuff ) { - %before = load i32, ptr %stuff +; CHECK-LABEL: define void @test1( +; CHECK-SAME: ptr noalias [[STUFF:%.*]]) { +; CHECK-NEXT: [[BEFORE:%.*]] = load i32, ptr [[STUFF]], align 4 +; CHECK-NEXT: call void @test1f(ptr null) +; CHECK-NEXT: [[SUM:%.*]] = add i32 [[BEFORE]], [[BEFORE]] +; CHECK-NEXT: store i32 [[SUM]], ptr [[STUFF]], align 4 +; CHECK-NEXT: ret void +; + %before = load i32, ptr %stuff - call void @test1f(ptr null) + call void @test1f(ptr null) - %after = load i32, ptr %stuff ; <--- This should be a dead load - %sum = add i32 %before, %after + %after = load i32, ptr %stuff ; <--- This should be a dead load + %sum = add i32 %before, %after - store i32 %sum, ptr %stuff - ret void -; CHECK: load -; CHECK-NOT: load -; CHECK: ret void + store i32 %sum, ptr %stuff + ret void } diff --git a/llvm/test/Transforms/NewGVN/phi-edge-handling.ll b/llvm/test/Transforms/NewGVN/phi-edge-handling.ll index 8dfac7942210cee9f520ef555dede38b88a06ac7..0e871b6b261a4363841710c6fb6a2ffd57743cd3 100644 --- a/llvm/test/Transforms/NewGVN/phi-edge-handling.ll +++ b/llvm/test/Transforms/NewGVN/phi-edge-handling.ll @@ -9,8 +9,8 @@ define i16 @hoge() { ; CHECK-LABEL: @hoge( ; CHECK-NEXT: bb: ; CHECK-NEXT: switch i8 undef, label [[BB7:%.*]] [ -; CHECK-NEXT: i8 0, label [[BB1:%.*]] -; CHECK-NEXT: i8 12, label [[BB2:%.*]] +; CHECK-NEXT: i8 0, label [[BB1:%.*]] +; CHECK-NEXT: i8 12, label [[BB2:%.*]] ; CHECK-NEXT: ] ; CHECK: bb1: ; CHECK-NEXT: br label [[BB6:%.*]] diff --git a/llvm/test/Transforms/NewGVN/phi-of-ops-simplified-to-existing-value-then-changes-again.ll b/llvm/test/Transforms/NewGVN/phi-of-ops-simplified-to-existing-value-then-changes-again.ll index ac07148c75521f9cdf0c07bd7d24a0cb2cf0037e..573a4c0bd0bcb116a9c0951f2734ac5881b9421a 100644 --- a/llvm/test/Transforms/NewGVN/phi-of-ops-simplified-to-existing-value-then-changes-again.ll +++ b/llvm/test/Transforms/NewGVN/phi-of-ops-simplified-to-existing-value-then-changes-again.ll @@ -88,8 +88,8 @@ define void @pr42422(i1 %c.1, i1 %c.2) { ; CHECK: bb16: ; CHECK-NEXT: [[TMP17:%.*]] = phi i32 [ poison, [[BB15]] ], [ 1, [[BB14]] ], [ 9, [[BB7]] ] ; CHECK-NEXT: switch i32 [[TMP17]], label [[BB19]] [ -; CHECK-NEXT: i32 0, label [[BB6]] -; CHECK-NEXT: i32 9, label [[BB18:%.*]] +; CHECK-NEXT: i32 0, label [[BB6]] +; CHECK-NEXT: i32 9, label [[BB18:%.*]] ; CHECK-NEXT: ] ; CHECK: bb18: ; CHECK-NEXT: br label [[BB19]] diff --git a/llvm/test/Transforms/NewGVN/phi-translate-partial-alias.ll b/llvm/test/Transforms/NewGVN/phi-translate-partial-alias.ll index cb24b050a599e3152b14f589cfc523b1647ac39b..7dd41904970c07bcfd168b2a6b2e5f7993643656 100644 --- a/llvm/test/Transforms/NewGVN/phi-translate-partial-alias.ll +++ b/llvm/test/Transforms/NewGVN/phi-translate-partial-alias.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -S < %s | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-f128:128:128-n8:16:32:64" @@ -6,12 +7,19 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3 ; not actually redundant around the loop backedge, despite appearances ; if phi-translation is ignored. -; CHECK: define void @test0(ptr %begin) -; CHECK: loop: -; CHECK: %l0 = load i8, ptr %phi -; CHECK: call void @bar(i8 %l0) -; CHECK: %l1 = load i8, ptr %phi define void @test0(ptr %begin) { +; CHECK-LABEL: define void @test0( +; CHECK-SAME: ptr [[BEGIN:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[BEGIN]], [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[L0:%.*]] = load i8, ptr [[PHI]], align 1 +; CHECK-NEXT: call void @bar(i8 [[L0]]) +; CHECK-NEXT: [[L1:%.*]] = load i8, ptr [[PHI]], align 1 +; CHECK-NEXT: [[NEXT]] = getelementptr inbounds i8, ptr [[PHI]], i8 [[L1]] +; CHECK-NEXT: br label [[LOOP]] +; entry: br label %loop diff --git a/llvm/test/Transforms/NewGVN/pr17732.ll b/llvm/test/Transforms/NewGVN/pr17732.ll index 427543d3aae7a76483bf2866dcdc3e4dd9087ad0..e66547cb9e19331f5380d0e420e97a35b53f71e2 100644 --- a/llvm/test/Transforms/NewGVN/pr17732.ll +++ b/llvm/test/Transforms/NewGVN/pr17732.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -S -o - < %s | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @@ -12,6 +13,12 @@ target triple = "x86_64-unknown-linux-gnu" @vector_with_zeroinit = common global %struct.with_vector zeroinitializer, align 4 define i32 @main() { +; CHECK-LABEL: define i32 @main() { +; CHECK-NEXT: entry: +; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr align 4 @array_with_zeroinit, ptr align 4 @main.obj_with_array, i64 12, i1 false) +; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr align 4 @vector_with_zeroinit, ptr align 4 @main.obj_with_vector, i64 12, i1 false) +; CHECK-NEXT: ret i32 1 +; entry: tail call void @llvm.memcpy.p0.p0.i64(ptr align 4 @array_with_zeroinit, ptr align 4 @main.obj_with_array, i64 12, i1 false) %0 = load i8, ptr getelementptr inbounds (%struct.with_array, ptr @array_with_zeroinit, i64 0, i32 2), align 4 @@ -22,8 +29,6 @@ entry: %conv1 = sext i8 %1 to i32 %and = and i32 %conv0, %conv1 ret i32 %and -; CHECK-LABEL: define i32 @main( -; CHECK: ret i32 1 } declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture readonly, i64, i1) diff --git a/llvm/test/Transforms/NewGVN/pr17852.ll b/llvm/test/Transforms/NewGVN/pr17852.ll index 5858982ce1cd859bfcb15a2f08e8651ad078fa58..bffde124164448dc456db1dc4d7b36fd164a002e 100644 --- a/llvm/test/Transforms/NewGVN/pr17852.ll +++ b/llvm/test/Transforms/NewGVN/pr17852.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=newgvn target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" %struct.S0 = type { [2 x i8], [2 x i8], [4 x i8], [2 x i8], i32, i32, i32, i32 } diff --git a/llvm/test/Transforms/NewGVN/pr24397.ll b/llvm/test/Transforms/NewGVN/pr24397.ll index f3f112ae1fe3193404251514b4254610a38cded9..d9981443522e7fded3f7aa1c69abb79ed74df8b8 100644 --- a/llvm/test/Transforms/NewGVN/pr24397.ll +++ b/llvm/test/Transforms/NewGVN/pr24397.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -disable-output < %s target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Transforms/NewGVN/pr24426.ll b/llvm/test/Transforms/NewGVN/pr24426.ll index e8a88f5b267ab66ca6c9b4f61214f20e89c96914..8f0974aa0bd35624f188b5d92217bcd06b817613 100644 --- a/llvm/test/Transforms/NewGVN/pr24426.ll +++ b/llvm/test/Transforms/NewGVN/pr24426.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -passes=memcpyopt,mldst-motion,newgvn -S | FileCheck %s declare void @check(i8) @@ -5,11 +6,17 @@ declare void @check(i8) declare void @write(ptr %res) define void @test1() { +; CHECK-LABEL: define void @test1() { +; CHECK-NEXT: [[TMP1:%.*]] = alloca [10 x i8], align 1 +; CHECK-NEXT: call void @write(ptr [[TMP1]]) +; CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[TMP1]], align 1 +; CHECK-NEXT: call void @check(i8 [[TMP2]]) +; CHECK-NEXT: ret void +; %1 = alloca [10 x i8] call void @write(ptr %1) %2 = load i8, ptr %1 -; CHECK-NOT: undef call void @check(i8 %2) ret void diff --git a/llvm/test/Transforms/NewGVN/pr25440.ll b/llvm/test/Transforms/NewGVN/pr25440.ll index b3ebf447afc2e5cb7231744c94bb58388cae2c33..9d9c4cda3425819f6c71a46ef04657699d12619a 100644 --- a/llvm/test/Transforms/NewGVN/pr25440.ll +++ b/llvm/test/Transforms/NewGVN/pr25440.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ;RUN: opt -passes=newgvn -S < %s | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n8:16:32-S64" @@ -10,19 +11,51 @@ target triple = "thumbv7--linux-gnueabi" ; Function Attrs: nounwind define fastcc void @foo(ptr nocapture readonly %x) { -;CHECK-LABEL: foo +; CHECK-LABEL: define fastcc void @foo( +; CHECK-SAME: ptr nocapture readonly [[X:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[BB0:%.*]] +; CHECK: bb0: +; CHECK-NEXT: [[X_TR:%.*]] = phi ptr [ [[X]], [[ENTRY:%.*]] ], [ null, [[LAND_LHS_TRUE:%.*]] ] +; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[X_TR]], align 4 +; CHECK-NEXT: [[CONV:%.*]] = zext i16 [[TMP0]] to i32 +; CHECK-NEXT: switch i32 [[CONV]], label [[IF_END_50:%.*]] [ +; CHECK-NEXT: i32 43, label [[CLEANUP:%.*]] +; CHECK-NEXT: i32 52, label [[IF_THEN_5:%.*]] +; CHECK-NEXT: ] +; CHECK: if.then.5: +; CHECK-NEXT: br i1 undef, label [[LAND_LHS_TRUE]], label [[IF_THEN_26:%.*]] +; CHECK: land.lhs.true: +; CHECK-NEXT: br i1 undef, label [[CLEANUP]], label [[BB0]] +; CHECK: if.then.26: +; CHECK-NEXT: br i1 undef, label [[COND_END:%.*]], label [[COND_FALSE:%.*]] +; CHECK: cond.false: +; CHECK-NEXT: [[MODE:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[X_TR]], i32 0, i32 1 +; CHECK-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[MODE]], align 2 +; CHECK-NEXT: br label [[COND_END]] +; CHECK: cond.end: +; CHECK-NEXT: br i1 undef, label [[IF_THEN_44:%.*]], label [[CLEANUP]] +; CHECK: if.then.44: +; CHECK-NEXT: unreachable +; CHECK: if.end.50: +; CHECK-NEXT: [[ARRAYIDX52:%.*]] = getelementptr inbounds [0 x i32], ptr @length, i32 0, i32 [[CONV]] +; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX52]], align 4 +; CHECK-NEXT: br i1 undef, label [[FOR_BODY_57:%.*]], label [[CLEANUP]] +; CHECK: for.body.57: +; CHECK-NEXT: unreachable +; CHECK: cleanup: +; CHECK-NEXT: ret void +; entry: br label %bb0 bb0: ; preds = %land.lhs.true, %entry -;CHECK: bb0: %x.tr = phi ptr [ %x, %entry ], [ null, %land.lhs.true ] %0 = load i16, ptr %x.tr, align 4 -; CHECK: load i16, ptr %conv = zext i16 %0 to i32 switch i32 %conv, label %if.end.50 [ - i32 43, label %cleanup - i32 52, label %if.then.5 + i32 43, label %cleanup + i32 52, label %if.then.5 ] if.then.5: ; preds = %bb0 @@ -36,8 +69,6 @@ if.then.26: ; preds = %if.then.5 br i1 undef, label %cond.end, label %cond.false cond.false: ; preds = %if.then.26 -; CHECK: cond.false: -; CHECK: load i16 %mode = getelementptr inbounds %struct.a, ptr %x.tr.lcssa163, i32 0, i32 1 %bf.load = load i16, ptr %mode, align 2 %bf.shl = shl i16 %bf.load, 8 @@ -50,7 +81,6 @@ if.then.44: ; preds = %cond.end unreachable if.end.50: ; preds = %bb0 -;%CHECK: if.end.50: %conv.lcssa = phi i32 [ %conv, %bb0 ] %arrayidx52 = getelementptr inbounds [0 x i32], ptr @length, i32 0, i32 %conv.lcssa %1 = load i32, ptr %arrayidx52, align 4 @@ -68,7 +98,34 @@ cleanup: ; preds = %if.end.50, %cond.en @dfg_text = external global ptr, align 4 define void @dfg_lex() { -;CHECK-LABEL: dfg_lex +; CHECK-LABEL: define void @dfg_lex() { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[WHILE_BODYTHREAD_PRE_SPLIT:%.*]] +; CHECK: while.bodythread-pre-split: +; CHECK-NEXT: br i1 undef, label [[IF_THEN_14:%.*]], label [[IF_END_15:%.*]] +; CHECK: if.then.14: +; CHECK-NEXT: [[V1:%.*]] = load i32, ptr @dfg_text, align 4 +; CHECK-NEXT: br label [[IF_END_15]] +; CHECK: if.end.15: +; CHECK-NEXT: [[V2:%.*]] = load ptr, ptr @yy_c_buf_p, align 4 +; CHECK-NEXT: br label [[WHILE_COND_16:%.*]] +; CHECK: while.cond.16: +; CHECK-NEXT: br i1 undef, label [[WHILE_COND_16]], label [[WHILE_END:%.*]] +; CHECK: while.end: +; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[V2]], i32 undef +; CHECK-NEXT: store ptr [[ADD_PTR]], ptr @dfg_text, align 4 +; CHECK-NEXT: [[SUB_PTR_RHS_CAST25:%.*]] = ptrtoint ptr [[ADD_PTR]] to i32 +; CHECK-NEXT: switch i32 undef, label [[SW_DEFAULT:%.*]] [ +; CHECK-NEXT: i32 65, label [[WHILE_BODYTHREAD_PRE_SPLIT]] +; CHECK-NEXT: i32 3, label [[RETURN:%.*]] +; CHECK-NEXT: i32 57, label [[WHILE_BODYTHREAD_PRE_SPLIT]] +; CHECK-NEXT: i32 60, label [[IF_THEN_14]] +; CHECK-NEXT: ] +; CHECK: sw.default: +; CHECK-NEXT: unreachable +; CHECK: return: +; CHECK-NEXT: ret void +; entry: br label %while.bodythread-pre-split @@ -93,10 +150,10 @@ while.end: ; preds = %while.cond.16 %sub.ptr.rhs.cast25 = ptrtoint ptr %add.ptr to i32 %sub.ptr.sub26 = sub i32 0, %sub.ptr.rhs.cast25 switch i32 undef, label %sw.default [ - i32 65, label %while.bodythread-pre-split - i32 3, label %return - i32 57, label %while.bodythread-pre-split - i32 60, label %if.then.14 + i32 65, label %while.bodythread-pre-split + i32 3, label %return + i32 57, label %while.bodythread-pre-split + i32 60, label %if.then.14 ] sw.default: ; preds = %while.end diff --git a/llvm/test/Transforms/NewGVN/pr28562.ll b/llvm/test/Transforms/NewGVN/pr28562.ll index a62fdd31da7210eec5eb5945849863ab94f09535..320224c24b5bc02e8b43060835b68272ecbcca40 100644 --- a/llvm/test/Transforms/NewGVN/pr28562.ll +++ b/llvm/test/Transforms/NewGVN/pr28562.ll @@ -1,9 +1,12 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -S -passes=newgvn < %s | FileCheck %s define ptr @test1(ptr %a) { +; CHECK-LABEL: define ptr @test1( +; CHECK-SAME: ptr [[A:%.*]]) { +; CHECK-NEXT: [[X2:%.*]] = getelementptr i32, ptr [[A]], i32 10 +; CHECK-NEXT: ret ptr [[X2]] +; %x1 = getelementptr inbounds i32, ptr %a, i32 10 %x2 = getelementptr i32, ptr %a, i32 10 ret ptr %x2 -; CHECK-LABEL: @test1( -; CHECK: %[[x:.*]] = getelementptr i32, ptr %a, i32 10 -; CHECK: ret ptr %[[x]] } diff --git a/llvm/test/Transforms/NewGVN/pr31472.ll b/llvm/test/Transforms/NewGVN/pr31472.ll index 8bb9a14e813653bcb4cf7f37cde159da4ceb723d..8eeb61400f8141258feabbe467441f3f7cb08aed 100644 --- a/llvm/test/Transforms/NewGVN/pr31472.ll +++ b/llvm/test/Transforms/NewGVN/pr31472.ll @@ -9,11 +9,13 @@ target triple = "x86_64-apple-macosx10.12.0" define i32 @main() personality ptr @__gxx_personality_v0{ ; CHECK-LABEL: @main( ; CHECK-NEXT: [[TMP1:%.*]] = invoke i32 @foo() -; CHECK-NEXT: to label %good unwind label %bad +; CHECK-NEXT: to label [[GOOD:%.*]] unwind label [[BAD:%.*]] ; CHECK: good: ; CHECK-NEXT: ret i32 5 ; CHECK: bad: -; CHECK-NEXT: [[TMP2:%.*]] = landingpad { ptr, i32 +; CHECK-NEXT: [[TMP2:%.*]] = landingpad { ptr, i32 } +; CHECK-NEXT: cleanup +; CHECK-NEXT: resume { ptr, i32 } [[TMP2]] ; %1 = invoke i32 @foo() to label %good unwind label %bad diff --git a/llvm/test/Transforms/NewGVN/pr31483.ll b/llvm/test/Transforms/NewGVN/pr31483.ll index fe957dec72cf125f660e256ab8fc2179f25d40e8..82e9a2ab286ee554917e205363024aa65fbb595e 100644 --- a/llvm/test/Transforms/NewGVN/pr31483.ll +++ b/llvm/test/Transforms/NewGVN/pr31483.ll @@ -10,20 +10,20 @@ define signext i32 @ham(ptr %arg, ptr %arg1) #0 { ; CHECK-LABEL: @ham( ; CHECK-NEXT: bb: ; CHECK-NEXT: [[TMP:%.*]] = alloca ptr, align 8 -; CHECK-NEXT: store ptr %arg1, ptr [[TMP]], align 8 -; CHECK-NEXT: br label %bb2 +; CHECK-NEXT: store ptr [[ARG1:%.*]], ptr [[TMP]], align 8 +; CHECK-NEXT: br label [[BB2:%.*]] ; CHECK: bb2: -; CHECK-NEXT: [[TMP3:%.*]] = phi ptr [ %arg, %bb ], [ %tmp7, %bb22 ] +; CHECK-NEXT: [[TMP3:%.*]] = phi ptr [ [[ARG:%.*]], [[BB:%.*]] ], [ [[TMP7:%.*]], [[BB22:%.*]] ] ; CHECK-NEXT: [[TMP4:%.*]] = load i8, ptr [[TMP3]], align 1 ; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i8 [[TMP4]], 0 -; CHECK-NEXT: br i1 [[TMP5]], label %bb6, label %bb23 +; CHECK-NEXT: br i1 [[TMP5]], label [[BB6:%.*]], label [[BB23:%.*]] ; CHECK: bb6: -; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i32 1 +; CHECK-NEXT: [[TMP7]] = getelementptr inbounds i8, ptr [[TMP3]], i32 1 ; CHECK-NEXT: [[TMP9:%.*]] = zext i8 [[TMP4]] to i32 -; CHECK-NEXT: switch i32 [[TMP9]], label %bb22 [ -; CHECK-NEXT: i32 115, label %bb10 -; CHECK-NEXT: i32 105, label %bb16 -; CHECK-NEXT: i32 99, label %bb16 +; CHECK-NEXT: switch i32 [[TMP9]], label [[BB22]] [ +; CHECK-NEXT: i32 115, label [[BB10:%.*]] +; CHECK-NEXT: i32 105, label [[BB16:%.*]] +; CHECK-NEXT: i32 99, label [[BB16]] ; CHECK-NEXT: ] ; CHECK: bb10: ; CHECK-NEXT: [[TMP11:%.*]] = load ptr, ptr [[TMP]], align 8 @@ -31,17 +31,17 @@ define signext i32 @ham(ptr %arg, ptr %arg1) #0 { ; CHECK-NEXT: store ptr [[TMP12]], ptr [[TMP]], align 8 ; CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[TMP11]], align 8 ; CHECK-NEXT: [[TMP15:%.*]] = call signext i32 (ptr, ...) @zot(ptr @global, ptr [[TMP14]]) -; CHECK-NEXT: br label %bb22 +; CHECK-NEXT: br label [[BB22]] ; CHECK: bb16: ; CHECK-NEXT: [[TMP17:%.*]] = load ptr, ptr [[TMP]], align 8 ; CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds i8, ptr [[TMP17]], i64 8 ; CHECK-NEXT: store ptr [[TMP18]], ptr [[TMP]], align 8 ; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds i8, ptr [[TMP17]], i64 4 -; CHECK-NEXT: br label %bb22 +; CHECK-NEXT: br label [[BB22]] ; CHECK: bb22: -; CHECK-NEXT: br label %bb2 +; CHECK-NEXT: br label [[BB2]] ; CHECK: bb23: -; CHECK-NEXT: call void @llvm.va_end(ptr [[TMP]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr [[TMP]]) ; CHECK-NEXT: ret i32 undef ; bb: diff --git a/llvm/test/Transforms/NewGVN/pr31491.ll b/llvm/test/Transforms/NewGVN/pr31491.ll index 5f6b371333bbf09c67fcf0cc8c7bec44f29d5175..f27f13ed24e08ac8f1864936bdd32c4efdd46d12 100644 --- a/llvm/test/Transforms/NewGVN/pr31491.ll +++ b/llvm/test/Transforms/NewGVN/pr31491.ll @@ -7,13 +7,13 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" define internal i32 @pr31491() { ; CHECK-LABEL: @pr31491( ; CHECK-NEXT: bb5: -; CHECK-NEXT: br label %bb7 +; CHECK-NEXT: br label [[BB7:%.*]] ; CHECK: bb7: -; CHECK-NEXT: [[TMP:%.*]] = phi ptr [ [[TMP:%.*]]11, %bb10 ], [ undef, %bb5 ] -; CHECK-NEXT: br label %bb10 +; CHECK-NEXT: [[TMP:%.*]] = phi ptr [ [[TMP11:%.*]], [[BB10:%.*]] ], [ undef, [[BB5:%.*]] ] +; CHECK-NEXT: br label [[BB10]] ; CHECK: bb10: -; CHECK-NEXT: [[TMP11:%.*]] = tail call ptr @patatino(ptr [[TMP]]) -; CHECK-NEXT: br label %bb7 +; CHECK-NEXT: [[TMP11]] = tail call ptr @patatino(ptr [[TMP]]) +; CHECK-NEXT: br label [[BB7]] ; bb5: br label %bb7 diff --git a/llvm/test/Transforms/NewGVN/pr31501.ll b/llvm/test/Transforms/NewGVN/pr31501.ll index 55195fd6ada764696aaf0d77fc685aa87348a604..18bfcd1b9ca09c42c0aaa842c02bd03bc5faad28 100644 --- a/llvm/test/Transforms/NewGVN/pr31501.ll +++ b/llvm/test/Transforms/NewGVN/pr31501.ll @@ -52,30 +52,30 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" define weak_odr hidden ptr @quux(ptr %arg, ptr %arg1) local_unnamed_addr #0 align 2 { ; CHECK-LABEL: @quux( ; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds %struct.barney, ptr %arg, i64 0, i32 3, i32 0, i32 0, i32 0 -; CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 8, !tbaa !2 -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds %struct.barney, ptr %arg, i64 0, i32 3, i32 0, i32 0, i32 0, i32 0, i32 1 -; CHECK-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP4]], align 8, !tbaa !7 +; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds [[STRUCT_BARNEY:%.*]], ptr [[ARG:%.*]], i64 0, i32 3, i32 0, i32 0, i32 0 +; CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[TMP]], align 8, !tbaa [[TBAA2:![0-9]+]] +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_BARNEY]], ptr [[ARG]], i64 0, i32 3, i32 0, i32 0, i32 0, i32 0, i32 1 +; CHECK-NEXT: [[TMP6:%.*]] = load ptr, ptr [[TMP4]], align 8, !tbaa [[TBAA7:![0-9]+]] ; CHECK-NEXT: [[TMP7:%.*]] = icmp eq ptr [[TMP3]], [[TMP6]] -; CHECK-NEXT: br i1 [[TMP7]], label %bb21, label %bb8 +; CHECK-NEXT: br i1 [[TMP7]], label [[BB21:%.*]], label [[BB8:%.*]] ; CHECK: bb8: -; CHECK-NEXT: br label %bb11 +; CHECK-NEXT: br label [[BB11:%.*]] ; CHECK: bb9: ; CHECK-NEXT: [[TMP10:%.*]] = icmp eq ptr [[TMP18:%.*]], [[TMP6]] -; CHECK-NEXT: br i1 [[TMP10]], label %bb19, label %bb11 +; CHECK-NEXT: br i1 [[TMP10]], label [[BB19:%.*]], label [[BB11]] ; CHECK: bb11: -; CHECK-NEXT: [[TMP12:%.*]] = phi ptr [ [[TMP17:%.*]], %bb9 ], [ undef, %bb8 ] -; CHECK-NEXT: [[TMP13:%.*]] = phi ptr [ [[TMP18]], %bb9 ], [ [[TMP3]], %bb8 ] -; CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[TMP13]], align 8, !tbaa !8 -; CHECK-NEXT: [[TMP16:%.*]] = icmp eq ptr [[TMP15]], %arg1 +; CHECK-NEXT: [[TMP12:%.*]] = phi ptr [ [[TMP17:%.*]], [[BB9:%.*]] ], [ undef, [[BB8]] ] +; CHECK-NEXT: [[TMP13:%.*]] = phi ptr [ [[TMP18]], [[BB9]] ], [ [[TMP3]], [[BB8]] ] +; CHECK-NEXT: [[TMP15:%.*]] = load ptr, ptr [[TMP13]], align 8, !tbaa [[TBAA8:![0-9]+]] +; CHECK-NEXT: [[TMP16:%.*]] = icmp eq ptr [[TMP15]], [[ARG1:%.*]] ; CHECK-NEXT: [[TMP17]] = select i1 [[TMP16]], ptr [[TMP13]], ptr [[TMP12]] -; CHECK-NEXT: [[TMP18]] = getelementptr inbounds %struct.foo, ptr [[TMP13]], i64 1 -; CHECK-NEXT: br i1 [[TMP16]], label %bb19, label %bb9 +; CHECK-NEXT: [[TMP18]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr [[TMP13]], i64 1 +; CHECK-NEXT: br i1 [[TMP16]], label [[BB19]], label [[BB9]] ; CHECK: bb19: -; CHECK-NEXT: [[TMP20:%.*]] = phi ptr [ null, %bb9 ], [ [[TMP17]], %bb11 ] -; CHECK-NEXT: br label %bb21 +; CHECK-NEXT: [[TMP20:%.*]] = phi ptr [ null, [[BB9]] ], [ [[TMP17]], [[BB11]] ] +; CHECK-NEXT: br label [[BB21]] ; CHECK: bb21: -; CHECK-NEXT: [[TMP22:%.*]] = phi ptr [ null, %bb ], [ [[TMP20]], %bb19 ] +; CHECK-NEXT: [[TMP22:%.*]] = phi ptr [ null, [[BB:%.*]] ], [ [[TMP20]], [[BB19]] ] ; CHECK-NEXT: ret ptr [[TMP22]] ; bb: diff --git a/llvm/test/Transforms/NewGVN/pr31573.ll b/llvm/test/Transforms/NewGVN/pr31573.ll index 2382c487c19af022f1ec4dd2e44bb27f6415e853..7835e9d45a6713a81b50819e2f1f1137d000878f 100644 --- a/llvm/test/Transforms/NewGVN/pr31573.ll +++ b/llvm/test/Transforms/NewGVN/pr31573.ll @@ -10,7 +10,7 @@ define void @patatino(ptr %blah) { ; CHECK: while.cond: ; CHECK-NEXT: [[MEH:%.*]] = phi ptr [ [[BLAH:%.*]], [[ENTRY:%.*]] ], [ null, [[WHILE_BODY:%.*]] ] ; CHECK-NEXT: switch i32 undef, label [[WHILE_BODY]] [ -; CHECK-NEXT: i32 666, label [[WHILE_END:%.*]] +; CHECK-NEXT: i32 666, label [[WHILE_END:%.*]] ; CHECK-NEXT: ] ; CHECK: while.body: ; CHECK-NEXT: br label [[WHILE_COND]] diff --git a/llvm/test/Transforms/NewGVN/pr31594.ll b/llvm/test/Transforms/NewGVN/pr31594.ll index 47294d5640e468ec2fa9ddd277533738194d6cc7..d1a02d62934dee04d5a57f9eb09eb6f40286138c 100644 --- a/llvm/test/Transforms/NewGVN/pr31594.ll +++ b/llvm/test/Transforms/NewGVN/pr31594.ll @@ -10,8 +10,8 @@ define i1 @patatino(ptr %blah, i32 %choice) { ; CHECK: while.cond: ; CHECK-NEXT: [[FOO:%.*]] = phi ptr [ [[BLAH:%.*]], [[ENTRY:%.*]] ], [ null, [[WHILE_BODY:%.*]] ] ; CHECK-NEXT: switch i32 [[CHOICE:%.*]], label [[WHILE_BODY]] [ -; CHECK-NEXT: i32 -1, label [[WHILE_END:%.*]] -; CHECK-NEXT: i32 40, label [[LAND_END:%.*]] +; CHECK-NEXT: i32 -1, label [[WHILE_END:%.*]] +; CHECK-NEXT: i32 40, label [[LAND_END:%.*]] ; CHECK-NEXT: ] ; CHECK: land.end: ; CHECK-NEXT: br label [[WHILE_END]] @@ -66,7 +66,7 @@ define void @foo(ptr %arg) { ; CHECK: bb2: ; CHECK-NEXT: br label [[BB1]] ; CHECK: bb3: -; CHECK-NEXT: store i8 0, ptr [[TMP]], align 1, !g !0 +; CHECK-NEXT: store i8 0, ptr [[TMP]], align 1, !g [[META0:![0-9]+]] ; CHECK-NEXT: br label [[BB4:%.*]] ; CHECK: bb4: ; CHECK-NEXT: br label [[BB6:%.*]] @@ -74,13 +74,13 @@ define void @foo(ptr %arg) { ; CHECK-NEXT: br i1 undef, label [[BB9:%.*]], label [[BB7:%.*]] ; CHECK: bb7: ; CHECK-NEXT: switch i8 0, label [[BB6]] [ -; CHECK-NEXT: i8 6, label [[BB8:%.*]] +; CHECK-NEXT: i8 6, label [[BB8:%.*]] ; CHECK-NEXT: ] ; CHECK: bb8: ; CHECK-NEXT: store i8 poison, ptr null, align 1 ; CHECK-NEXT: br label [[BB4]] ; CHECK: bb9: -; CHECK-NEXT: store i8 0, ptr [[ARG]], align 1, !g !0 +; CHECK-NEXT: store i8 0, ptr [[ARG]], align 1, !g [[META0]] ; CHECK-NEXT: unreachable ; bb: diff --git a/llvm/test/Transforms/NewGVN/pr31613.ll b/llvm/test/Transforms/NewGVN/pr31613.ll index 943cdbc113dc405ff6905481c530feed6026b88a..0bcf86a57111892e6d310ef34f2fc154feb14ac7 100644 --- a/llvm/test/Transforms/NewGVN/pr31613.ll +++ b/llvm/test/Transforms/NewGVN/pr31613.ll @@ -74,7 +74,7 @@ declare void @c.d.p(i64, ptr) define void @e(i32 %a0, i32 %a1, ptr %p2) { ; CHECK-LABEL: @e( ; CHECK-NEXT: [[F:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 [[A0:%.*]], ptr [[F]], align 4, !g !0 +; CHECK-NEXT: store i32 [[A0:%.*]], ptr [[F]], align 4, !g [[META0:![0-9]+]] ; CHECK-NEXT: br label [[H:%.*]] ; CHECK: h: ; CHECK-NEXT: call void @c.d.p(i64 8, ptr undef) @@ -88,10 +88,10 @@ define void @e(i32 %a0, i32 %a1, ptr %p2) { ; CHECK-NEXT: br label [[R]] ; CHECK: r: ; CHECK-NEXT: switch i32 undef, label [[N:%.*]] [ -; CHECK-NEXT: i32 0, label [[S:%.*]] +; CHECK-NEXT: i32 0, label [[S:%.*]] ; CHECK-NEXT: ] ; CHECK: s: -; CHECK-NEXT: store i32 [[A1:%.*]], ptr [[F]], align 4, !g !0 +; CHECK-NEXT: store i32 [[A1:%.*]], ptr [[F]], align 4, !g [[META0]] ; CHECK-NEXT: br label [[H]] ; CHECK: n: ; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/NewGVN/pr31682.ll b/llvm/test/Transforms/NewGVN/pr31682.ll index 00a1bf2b84505a661beac643cb7ec1a33094d2c5..3d8c9e28635c661c3ed267b8236656806766a31a 100644 --- a/llvm/test/Transforms/NewGVN/pr31682.ll +++ b/llvm/test/Transforms/NewGVN/pr31682.ll @@ -9,7 +9,7 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" define void @bar() { ; CHECK-LABEL: @bar( ; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr @global +; CHECK-NEXT: [[TMP:%.*]] = load ptr, ptr @global, align 8 ; CHECK-NEXT: br label [[BB2:%.*]] ; CHECK: bb2: ; CHECK-NEXT: br i1 undef, label [[BB2]], label [[BB7:%.*]] diff --git a/llvm/test/Transforms/NewGVN/pr31758.ll b/llvm/test/Transforms/NewGVN/pr31758.ll index 43188430e34c22bfb3a5125258f8a845fb99a318..274d605802a6bc7860e6e8d347d5178de6dec83e 100644 --- a/llvm/test/Transforms/NewGVN/pr31758.ll +++ b/llvm/test/Transforms/NewGVN/pr31758.ll @@ -12,7 +12,7 @@ define void @tinkywinky() { ; CHECK: bb90: ; CHECK-NEXT: br label [[BB90]] ; CHECK: bb138: -; CHECK-NEXT: store i8 poison, ptr null +; CHECK-NEXT: store i8 poison, ptr null, align 1 ; CHECK-NEXT: br label [[BB138:%.*]] ; bb: diff --git a/llvm/test/Transforms/NewGVN/pr32607.ll b/llvm/test/Transforms/NewGVN/pr32607.ll index 4770724dc2baa8709a77c10a6cc270bb79b3af48..7460ab5ec27e04c70006739415b5b958824cc103 100644 --- a/llvm/test/Transforms/NewGVN/pr32607.ll +++ b/llvm/test/Transforms/NewGVN/pr32607.ll @@ -7,7 +7,7 @@ define hidden void @foo() { ; CHECK: if: ; CHECK-NEXT: br i1 false, label [[L50:%.*]], label [[IF]] ; CHECK: L50: -; CHECK-NEXT: store i8 poison, ptr null +; CHECK-NEXT: store i8 poison, ptr null, align 1 ; CHECK-NEXT: ret void ; top: diff --git a/llvm/test/Transforms/NewGVN/pr32836.ll b/llvm/test/Transforms/NewGVN/pr32836.ll index 5488655b3683d3a720010a85221b199cc62c8ef0..00f3fb07b20259a4abff42e7585356ca44c7e9da 100644 --- a/llvm/test/Transforms/NewGVN/pr32836.ll +++ b/llvm/test/Transforms/NewGVN/pr32836.ll @@ -5,19 +5,19 @@ @b = external global %struct.anon define void @tinkywinky(i1 %patatino) { ; CHECK-LABEL: @tinkywinky( -; CHECK-NEXT: store i32 8, ptr null +; CHECK-NEXT: store i32 8, ptr null, align 4 ; CHECK-NEXT: br i1 [[PATATINO:%.*]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] ; CHECK: if.then: ; CHECK-NEXT: br label [[L:%.*]] ; CHECK: L: ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: -; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr null -; CHECK-NEXT: [[BF_LOAD1:%.*]] = load i32, ptr @b +; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr null, align 4 +; CHECK-NEXT: [[BF_LOAD1:%.*]] = load i32, ptr @b, align 4 ; CHECK-NEXT: [[BF_VALUE:%.*]] = and i32 [[TMP1]], 536870911 ; CHECK-NEXT: [[BF_CLEAR:%.*]] = and i32 [[BF_LOAD1]], -536870912 ; CHECK-NEXT: [[BF_SET:%.*]] = or i32 [[BF_CLEAR]], [[BF_VALUE]] -; CHECK-NEXT: store i32 [[BF_SET]], ptr @b +; CHECK-NEXT: store i32 [[BF_SET]], ptr @b, align 4 ; CHECK-NEXT: br label [[LOR_END:%.*]] ; CHECK: lor.end: ; CHECK-NEXT: br label [[L]] diff --git a/llvm/test/Transforms/NewGVN/pr32838.ll b/llvm/test/Transforms/NewGVN/pr32838.ll index 5ba68fa15c24dc3b74528a59cbb312329ad3765f..87c93d9312e67c223788997bbee0a6823e2d1c45 100644 --- a/llvm/test/Transforms/NewGVN/pr32838.ll +++ b/llvm/test/Transforms/NewGVN/pr32838.ll @@ -10,7 +10,7 @@ define void @fn1(i64 noundef %arg) { ; CHECK: if.then: ; CHECK-NEXT: br i1 false, label [[FIRSTPHIBLOCK:%.*]], label [[TEMP:%.*]] ; CHECK: firstphiblock: -; CHECK-NEXT: br i1 undef, label %for.cond17thread-pre-split, label [[SECONDPHIBLOCK:%.*]] +; CHECK-NEXT: br i1 undef, label [[FOR_COND17THREAD_PRE_SPLIT:%.*]], label [[SECONDPHIBLOCK:%.*]] ; CHECK: secondphiblock: ; CHECK-NEXT: [[SECONDPHI:%.*]] = phi i64 [ [[THIRDPHI:%.*]], [[THIRDPHIBLOCK:%.*]] ], [ undef, [[FIRSTPHIBLOCK]] ] ; CHECK-NEXT: br i1 undef, label [[FIRSTPHIBLOCK]], label [[THIRDPHIBLOCK]] @@ -55,7 +55,7 @@ define void @fn2(i64 noundef %arg) { ; CHECK-NEXT: br i1 false, label [[FIRSTPHIBLOCK:%.*]], label [[TEMP:%.*]] ; CHECK: firstphiblock: ; CHECK-NEXT: [[FIRSTPHI:%.*]] = phi i64 [ poison, [[IF_THEN]] ], [ [[SECONDPHI:%.*]], [[SECONDPHIBLOCK:%.*]] ] -; CHECK-NEXT: br i1 undef, label %for.cond17thread-pre-split, label [[SECONDPHIBLOCK]] +; CHECK-NEXT: br i1 undef, label [[FOR_COND17THREAD_PRE_SPLIT:%.*]], label [[SECONDPHIBLOCK]] ; CHECK: secondphiblock: ; CHECK-NEXT: [[SECONDPHI]] = phi i64 [ [[THIRDPHI:%.*]], [[THIRDPHIBLOCK:%.*]] ], [ [[FIRSTPHI]], [[FIRSTPHIBLOCK]] ] ; CHECK-NEXT: br i1 undef, label [[FIRSTPHIBLOCK]], label [[THIRDPHIBLOCK]] @@ -65,7 +65,7 @@ define void @fn2(i64 noundef %arg) { ; CHECK: for.cond17thread-pre-split: ; CHECK-NEXT: br label [[COND_TRUE]] ; CHECK: cond.true: -; CHECK-NEXT: [[FOURTHPHI:%.*]] = phi i64 [ [[ARG:%.*]], [[ENTRY:%.*]] ], [ [[FIRSTPHI]], %for.cond17thread-pre-split ] +; CHECK-NEXT: [[FOURTHPHI:%.*]] = phi i64 [ [[ARG:%.*]], [[ENTRY:%.*]] ], [ [[FIRSTPHI]], [[FOR_COND17THREAD_PRE_SPLIT]] ] ; CHECK-NEXT: [[DIV]] = sdiv i64 [[FOURTHPHI]], 4 ; CHECK-NEXT: br label [[THIRDPHIBLOCK]] ; CHECK: temp: @@ -105,7 +105,7 @@ define void @fn3() { ; CHECK-NEXT: [[F_0:%.*]] = phi ptr [ @b, [[ENTRY:%.*]] ], [ @a, [[L1_LOOPEXIT:%.*]] ] ; CHECK-NEXT: br label [[FOR_COND:%.*]] ; CHECK: for.cond.loopexit: -; CHECK-NEXT: store i8 poison, ptr null +; CHECK-NEXT: store i8 poison, ptr null, align 1 ; CHECK-NEXT: br label [[FOR_COND]] ; CHECK: for.cond: ; CHECK-NEXT: br i1 undef, label [[FOR_END14:%.*]], label [[FOR_COND1_PREHEADER:%.*]] diff --git a/llvm/test/Transforms/NewGVN/pr32845.ll b/llvm/test/Transforms/NewGVN/pr32845.ll index d1182a627c59c3206e51b24dc21bc1e486a34ae0..29b81b8e1c66a412a9aa565a81a1bd76b8c46406 100644 --- a/llvm/test/Transforms/NewGVN/pr32845.ll +++ b/llvm/test/Transforms/NewGVN/pr32845.ll @@ -13,7 +13,7 @@ define void @tinkywinky() { ; CHECK-NEXT: [[F_0:%.*]] = phi ptr [ @b, [[ENTRY:%.*]] ], [ @a, [[L1_LOOPEXIT:%.*]] ] ; CHECK-NEXT: br label [[FOR_COND:%.*]] ; CHECK: for.cond.loopexit: -; CHECK-NEXT: store i8 poison, ptr null +; CHECK-NEXT: store i8 poison, ptr null, align 1 ; CHECK-NEXT: br label [[FOR_COND]] ; CHECK: for.cond: ; CHECK-NEXT: br i1 undef, label [[FOR_END14:%.*]], label [[FOR_COND1_PREHEADER:%.*]] diff --git a/llvm/test/Transforms/NewGVN/pr32852.ll b/llvm/test/Transforms/NewGVN/pr32852.ll index 4fd5cf1a95fa727f3d4b70967617bd8f23dca166..ad5badd82fdf005d2f10ac5cf9c45f78365483d8 100644 --- a/llvm/test/Transforms/NewGVN/pr32852.ll +++ b/llvm/test/Transforms/NewGVN/pr32852.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; Make sure GVN doesn't incorrectly think the branch terminating ; bb2 has a constant condition. ; RUN: opt -S -passes=newgvn %s | FileCheck %s @@ -6,13 +7,26 @@ @patatino = private unnamed_addr constant [3 x i8] c"0\0A\00" define void @tinkywinky() { +; CHECK-LABEL: define void @tinkywinky() { +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP:%.*]] = load i32, ptr @a, align 4 +; CHECK-NEXT: [[TMP1:%.*]] = icmp sge i32 [[TMP]], 0 +; CHECK-NEXT: br i1 [[TMP1]], label [[BB2:%.*]], label [[BB7:%.*]] +; CHECK: bb2: +; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP]], 0 +; CHECK-NEXT: br i1 [[TMP4]], label [[BB5:%.*]], label [[BB7]] +; CHECK: bb5: +; CHECK-NEXT: [[TMP6:%.*]] = call i32 (ptr, ...) @printf(ptr @patatino) +; CHECK-NEXT: br label [[BB7]] +; CHECK: bb7: +; CHECK-NEXT: ret void +; bb: %tmp = load i32, ptr @a %tmp1 = icmp sge i32 %tmp, 0 br i1 %tmp1, label %bb2, label %bb7 bb2: %tmp4 = icmp sgt i32 %tmp, 0 -; CHECK: br i1 %tmp4, label %bb5, label %bb7 br i1 %tmp4, label %bb5, label %bb7 bb5: %tmp6 = call i32 (ptr, ...) @printf(ptr @patatino) diff --git a/llvm/test/Transforms/NewGVN/pr32897.ll b/llvm/test/Transforms/NewGVN/pr32897.ll index 35a3b0040bcaac4384df5e4f311e61f6804b2823..881c3a8e3ef538330062894c8319dc85c260d21c 100644 --- a/llvm/test/Transforms/NewGVN/pr32897.ll +++ b/llvm/test/Transforms/NewGVN/pr32897.ll @@ -6,7 +6,7 @@ define void @tinkywinky(ptr %b) { ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[BODY:%.*]] ; CHECK: body: -; CHECK-NEXT: store i64 undef, ptr [[B:%.*]] +; CHECK-NEXT: store i64 undef, ptr [[B:%.*]], align 4 ; CHECK-NEXT: br i1 undef, label [[BODY]], label [[END:%.*]] ; CHECK: end: ; CHECK-NEXT: br label [[BODY]] diff --git a/llvm/test/Transforms/NewGVN/pr32934.ll b/llvm/test/Transforms/NewGVN/pr32934.ll index fa725f8888e7e3c3ed823ac28114f6d87b087cba..c8218c209face4a4fcb5675e1b21104aa601cf32 100644 --- a/llvm/test/Transforms/NewGVN/pr32934.ll +++ b/llvm/test/Transforms/NewGVN/pr32934.ll @@ -1,39 +1,41 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -S -passes=newgvn %s | FileCheck %s -; CHECK: define void @tinkywinky() { -; CHECK-NEXT: entry: -; CHECK-NEXT: %d = alloca i32, align 4 -; CHECK-NEXT: store i32 0, ptr null, align 4 -; CHECK-NEXT: br label %for.cond -; CHECK: for.cond: ; preds = %if.end, %entry -; CHECK-NEXT: %0 = load i32, ptr null, align 4 -; CHECK-NEXT: %cmp = icmp slt i32 %0, 1 -; CHECK-NEXT: br i1 %cmp, label %for.body, label %while.cond -; CHECK: for.body: ; preds = %for.cond -; CHECK-NEXT: %1 = load i32, ptr @a, align 4 -; CHECK-NEXT: store i32 %1, ptr %d, align 4 -; CHECK-NEXT: br label %L -; CHECK: L: ; preds = %if.then, %for.body -; CHECK-NEXT: %tobool = icmp ne i32 %1, 0 -; CHECK-NEXT: br i1 %tobool, label %if.then, label %if.end -; CHECK: if.then: ; preds = %L -; CHECK-NEXT: call void (ptr, ...) @printf(ptr @patatino) -; CHECK-NEXT: br label %L -; CHECK: if.end: ; preds = %L -; CHECK-NEXT: br label %for.cond -; CHECK: while.cond: ; preds = %while.body, %for.cond -; CHECK-NEXT: br i1 undef, label %while.body, label %while.end -; CHECK: while.body: ; preds = %while.cond -; CHECK-NEXT: call void (ptr, ...) @printf(ptr @patatino) -; CHECK-NEXT: br label %while.cond -; CHECK: while.end: -; CHECK-NEXT: %2 = load i32, ptr @a, align 4 -; CHECK-NEXT: store i32 %2, ptr undef, align 4 -; CHECK-NEXT: ret void @a = external global i32, align 4 @patatino = external unnamed_addr constant [2 x i8], align 1 define void @tinkywinky() { +; CHECK-LABEL: define void @tinkywinky() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[D:%.*]] = alloca i32, align 4 +; CHECK-NEXT: store i32 0, ptr null, align 4 +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr null, align 4 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 1 +; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[WHILE_COND:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @a, align 4 +; CHECK-NEXT: store i32 [[TMP1]], ptr [[D]], align 4 +; CHECK-NEXT: br label [[L:%.*]] +; CHECK: L: +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[TMP1]], 0 +; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] +; CHECK: if.then: +; CHECK-NEXT: call void (ptr, ...) @printf(ptr @patatino) +; CHECK-NEXT: br label [[L]] +; CHECK: if.end: +; CHECK-NEXT: br label [[FOR_COND]] +; CHECK: while.cond: +; CHECK-NEXT: br i1 undef, label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]] +; CHECK: while.body: +; CHECK-NEXT: call void (ptr, ...) @printf(ptr @patatino) +; CHECK-NEXT: br label [[WHILE_COND]] +; CHECK: while.end: +; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr @a, align 4 +; CHECK-NEXT: store i32 [[TMP2]], ptr undef, align 4 +; CHECK-NEXT: ret void +; entry: %d = alloca i32, align 4 store i32 0, ptr null, align 4 diff --git a/llvm/test/Transforms/NewGVN/pr32945.ll b/llvm/test/Transforms/NewGVN/pr32945.ll index ebf3813c65bd5a0e5e14aa860bc6cdd7f45684df..7aabe4df05952007275114ed7952774796585e10 100644 --- a/llvm/test/Transforms/NewGVN/pr32945.ll +++ b/llvm/test/Transforms/NewGVN/pr32945.ll @@ -1,9 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -S -passes=newgvn %s | FileCheck %s -; CHECK-NOT: call i32 @llvm.ssa.copy @d = external global i32 @e = external global i32 define void @tinkywinky() { +; CHECK-LABEL: define void @tinkywinky() { +; CHECK-NEXT: br i1 true, label [[LOR_LHS_FALSE:%.*]], label [[COND_TRUE:%.*]] +; CHECK: lor.lhs.false: +; CHECK-NEXT: [[TMP:%.*]] = load i32, ptr @d, align 4 +; CHECK-NEXT: [[PATATINO:%.*]] = load i32, ptr null, align 4 +; CHECK-NEXT: [[OR:%.*]] = or i32 [[TMP]], [[PATATINO]] +; CHECK-NEXT: store i32 [[OR]], ptr @d, align 4 +; CHECK-NEXT: br label [[COND_TRUE]] +; CHECK: cond.true: +; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @e, align 4 +; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr @d, align 4 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], [[TMP2]] +; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE6:%.*]], label [[COND_FALSE:%.*]] +; CHECK: cond.true6: +; CHECK-NEXT: [[CMP7:%.*]] = icmp slt i32 [[TMP1]], 0 +; CHECK-NEXT: br i1 [[CMP7]], label [[COND_FALSE]], label [[COND_FALSE]] +; CHECK: cond.false: +; CHECK-NEXT: ret void +; br i1 true, label %lor.lhs.false, label %cond.true lor.lhs.false: %tmp = load i32, ptr @d, align 4 diff --git a/llvm/test/Transforms/NewGVN/pr32952.ll b/llvm/test/Transforms/NewGVN/pr32952.ll index 5157bb27e6c59ba0d3b588b8f0c4a9873abab194..49e4843294f57487cc2b1bcd1b941d9a129f1527 100644 --- a/llvm/test/Transforms/NewGVN/pr32952.ll +++ b/llvm/test/Transforms/NewGVN/pr32952.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; PR32952: Don't erroneously consider congruent two phi nodes which ; have the same arguments but different incoming edges. ; RUN: opt -passes=newgvn -S %s | FileCheck %s @@ -6,6 +7,31 @@ @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 define i32 @tinkywinky() { +; CHECK-LABEL: define i32 @tinkywinky() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr @a, align 2 +; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[TMP0]] to i32 +; CHECK-NEXT: [[NEG:%.*]] = xor i32 [[CONV]], -1 +; CHECK-NEXT: [[CONV1:%.*]] = trunc i32 [[NEG]] to i16 +; CHECK-NEXT: [[CONV3:%.*]] = zext i16 [[CONV1]] to i32 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[CONV]], [[CONV3]] +; CHECK-NEXT: br i1 [[CMP]], label [[TINKY:%.*]], label [[WINKY:%.*]] +; CHECK: tinky: +; CHECK-NEXT: store i16 2, ptr @a, align 2 +; CHECK-NEXT: br label [[PATATINO:%.*]] +; CHECK: winky: +; CHECK-NEXT: br label [[PATATINO]] +; CHECK: patatino: +; CHECK-NEXT: [[MEH:%.*]] = phi i16 [ [[TMP0]], [[WINKY]] ], [ [[CONV1]], [[TINKY]] ] +; CHECK-NEXT: [[BANANA:%.*]] = phi i16 [ [[TMP0]], [[TINKY]] ], [ [[CONV1]], [[WINKY]] ] +; CHECK-NEXT: br label [[END:%.*]] +; CHECK: end: +; CHECK-NEXT: [[PROMOTED:%.*]] = zext i16 [[BANANA]] to i32 +; CHECK-NEXT: [[OTHER:%.*]] = zext i16 [[MEH]] to i32 +; CHECK-NEXT: [[FIRST:%.*]] = tail call i32 (ptr, ...) @printf(ptr @.str, i32 [[PROMOTED]]) +; CHECK-NEXT: [[SECOND:%.*]] = tail call i32 (ptr, ...) @printf(ptr @.str, i32 [[OTHER]]) +; CHECK-NEXT: ret i32 0 +; entry: %0 = load i16, ptr @a, align 2 %conv = sext i16 %0 to i32 @@ -23,15 +49,11 @@ winky: br label %patatino patatino: -; CHECK: %meh = phi i16 [ %0, %winky ], [ %conv1, %tinky ] -; CHECK: %banana = phi i16 [ %0, %tinky ], [ %conv1, %winky ] %meh = phi i16 [ %0, %winky ], [ %conv1, %tinky ] %banana = phi i16 [ %0, %tinky ], [ %conv1, %winky ] br label %end end: -; CHECK: %promoted = zext i16 %banana to i32 -; CHECK: %other = zext i16 %meh to i32 %promoted = zext i16 %banana to i32 %other = zext i16 %meh to i32 %first = tail call i32 (ptr, ...) @printf(ptr @.str, i32 %promoted) diff --git a/llvm/test/Transforms/NewGVN/pr33014.ll b/llvm/test/Transforms/NewGVN/pr33014.ll index f6e919770d6c6265ffedbe5bf6443e43dd858a77..04f9df2704a6c79211bc2228b8eba767b17f115f 100644 --- a/llvm/test/Transforms/NewGVN/pr33014.ll +++ b/llvm/test/Transforms/NewGVN/pr33014.ll @@ -1,33 +1,34 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; Make sure we don't end up in an infinite recursion in singleReachablePHIPath(). ; RUN: opt < %s -passes=newgvn -S | FileCheck %s @c = external global i64, align 8 -; CHECK-LABEL: define void @tinkywinky() { -; CHECK: entry: -; CHECK-NEXT: br i1 undef, label %l2, label %if.then -; CHECK: if.then: ; preds = %entry -; CHECK-NEXT: br label %for.body -; CHECK: ph: ; preds = %back, %ontrue -; CHECK-NEXT: br label %for.body -; CHECK: for.body: ; preds = %ph, %if.then -; CHECK-NEXT: br i1 undef, label %ontrue, label %onfalse -; CHECK: onfalse: ; preds = %for.body -; CHECK-NEXT: %patatino = load i64, ptr @c -; CHECK-NEXT: ret void -; CHECK: ontrue: ; preds = %for.body -; CHECK-NEXT: %dipsy = load i64, ptr @c -; CHECK-NEXT: br label %ph -; CHECK: back: ; preds = %l2 -; CHECK-NEXT: store i8 poison, ptr null -; CHECK-NEXT: br label %ph -; CHECK: end: ; preds = %l2 -; CHECK-NEXT: ret void -; CHECK: l2: ; preds = %entry -; CHECK-NEXT: br i1 false, label %back, label %end -; CHECK-NEXT: } define void @tinkywinky() { +; CHECK-LABEL: define void @tinkywinky() { +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 undef, label [[L2:%.*]], label [[IF_THEN:%.*]] +; CHECK: if.then: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: ph: +; CHECK-NEXT: br label [[FOR_BODY]] +; CHECK: for.body: +; CHECK-NEXT: br i1 undef, label [[ONTRUE:%.*]], label [[ONFALSE:%.*]] +; CHECK: onfalse: +; CHECK-NEXT: [[PATATINO:%.*]] = load i64, ptr @c, align 4 +; CHECK-NEXT: ret void +; CHECK: ontrue: +; CHECK-NEXT: [[DIPSY:%.*]] = load i64, ptr @c, align 4 +; CHECK-NEXT: br label [[PH:%.*]] +; CHECK: back: +; CHECK-NEXT: store i8 poison, ptr null, align 1 +; CHECK-NEXT: br label [[PH]] +; CHECK: end: +; CHECK-NEXT: ret void +; CHECK: l2: +; CHECK-NEXT: br i1 false, label [[BACK:%.*]], label [[END:%.*]] +; entry: br i1 undef, label %l2, label %if.then if.then: diff --git a/llvm/test/Transforms/NewGVN/pr33086.ll b/llvm/test/Transforms/NewGVN/pr33086.ll index 54802cdbd92585aa7685790ba4408a8142473e2c..ab6c00dd1777ff65b7fd633e805ce9a2c75307e4 100644 --- a/llvm/test/Transforms/NewGVN/pr33086.ll +++ b/llvm/test/Transforms/NewGVN/pr33086.ll @@ -1,31 +1,32 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -S %s | FileCheck %s ; REQUIRES: asserts -; CHECK-LABEL: define void @tinkywinky() { -; CHECK: entry: -; CHECK-NEXT: br i1 undef, label %for.cond18, label %for.cond.preheader -; CHECK: for.cond.preheader: -; CHECK-NEXT: br label %for.cond2thread-pre-split -; CHECK: for.cond2thread-pre-split: -; CHECK-NEXT: %conv24 = phi i32 [ 0, %for.cond.preheader ], [ %conv, %for.inc.split ] -; CHECK-NEXT: br label %for.inc.split -; CHECK: for.inc.split: -; CHECK-NEXT: %add = shl nsw i32 %conv24, 16 -; CHECK-NEXT: %sext23 = add i32 %add, 65536 -; CHECK-NEXT: %conv = ashr exact i32 %sext23, 16 -; CHECK-NEXT: %cmp = icmp slt i32 %sext23, 3604480 -; CHECK-NEXT: br i1 %cmp, label %for.cond2thread-pre-split, label %l1.loopexit -; CHECK: l1.loopexit: -; CHECK-NEXT: br label %l1 -; CHECK: l1: -; CHECK-NEXT: %0 = load i16, ptr null, align 2 -; CHECK-NEXT: %g.0.g.0..pr = load i16, ptr null, align 2 -; CHECK-NEXT: ret void -; CHECK: for.cond18: -; CHECK-NEXT: br label %l1 -; CHECK-NEXT: } define void @tinkywinky() { +; CHECK-LABEL: define void @tinkywinky() { +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 undef, label [[FOR_COND18:%.*]], label [[FOR_COND_PREHEADER:%.*]] +; CHECK: for.cond.preheader: +; CHECK-NEXT: br label [[FOR_COND2THREAD_PRE_SPLIT:%.*]] +; CHECK: for.cond2thread-pre-split: +; CHECK-NEXT: [[CONV24:%.*]] = phi i32 [ 0, [[FOR_COND_PREHEADER]] ], [ [[CONV:%.*]], [[FOR_INC_SPLIT:%.*]] ] +; CHECK-NEXT: br label [[FOR_INC_SPLIT]] +; CHECK: for.inc.split: +; CHECK-NEXT: [[ADD:%.*]] = shl nsw i32 [[CONV24]], 16 +; CHECK-NEXT: [[SEXT23:%.*]] = add i32 [[ADD]], 65536 +; CHECK-NEXT: [[CONV]] = ashr exact i32 [[SEXT23]], 16 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[SEXT23]], 3604480 +; CHECK-NEXT: br i1 [[CMP]], label [[FOR_COND2THREAD_PRE_SPLIT]], label [[L1_LOOPEXIT:%.*]] +; CHECK: l1.loopexit: +; CHECK-NEXT: br label [[L1:%.*]] +; CHECK: l1: +; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr null, align 2 +; CHECK-NEXT: [[G_0_G_0__PR:%.*]] = load i16, ptr null, align 2 +; CHECK-NEXT: ret void +; CHECK: for.cond18: +; CHECK-NEXT: br label [[L1]] +; entry: br i1 undef, label %for.cond18, label %for.cond.preheader diff --git a/llvm/test/Transforms/NewGVN/pr33116.ll b/llvm/test/Transforms/NewGVN/pr33116.ll index f5ef3ae7575ee559aaf982f63732aad24778b999..6609ef9e72dac6a65f18f26eb3e3cb3be4a723fd 100644 --- a/llvm/test/Transforms/NewGVN/pr33116.ll +++ b/llvm/test/Transforms/NewGVN/pr33116.ll @@ -13,7 +13,7 @@ define void @b() { ; CHECK: c: ; CHECK-NEXT: br i1 undef, label [[IF_G:%.*]], label [[IF_E]] ; CHECK: if.g: -; CHECK-NEXT: store i32 undef, ptr @a +; CHECK-NEXT: store i32 undef, ptr @a, align 4 ; CHECK-NEXT: br label [[WHILE_D]] ; CHECK: if.e: ; CHECK-NEXT: br label [[F]] diff --git a/llvm/test/Transforms/NewGVN/pr33187.ll b/llvm/test/Transforms/NewGVN/pr33187.ll index e5c3da2fb05a9e5a337db7b1447f3fa151206b66..37668bba3d5b60ece544fb4dcafbbab83b5d1ee6 100644 --- a/llvm/test/Transforms/NewGVN/pr33187.ll +++ b/llvm/test/Transforms/NewGVN/pr33187.ll @@ -30,7 +30,7 @@ define void @fn1() local_unnamed_addr #0 { ; CHECK: while.body12: ; CHECK-NEXT: br i1 undef, label [[IF_END18]], label [[L]] ; CHECK: L.loopexit: -; CHECK-NEXT: store i8 poison, ptr null +; CHECK-NEXT: store i8 poison, ptr null, align 1 ; CHECK-NEXT: br label [[L]] ; CHECK: L: ; CHECK-NEXT: [[H_125]] = phi i32 [ [[H_127]], [[WHILE_BODY12]] ], [ poison, [[L_LOOPEXIT]] ] @@ -114,13 +114,13 @@ attributes #0 = { nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="fals define void @a() { ; CHECK-LABEL: @a( ; CHECK-NEXT: b: -; CHECK-NEXT: store ptr null, ptr null +; CHECK-NEXT: store ptr null, ptr null, align 8 ; CHECK-NEXT: br label [[D:%.*]] ; CHECK: d: ; CHECK-NEXT: [[I:%.*]] = phi ptr [ null, [[B:%.*]] ], [ [[E:%.*]], [[F:%.*]] ] ; CHECK-NEXT: br i1 undef, label [[F]], label [[G:%.*]] ; CHECK: g: -; CHECK-NEXT: store ptr [[I]], ptr null +; CHECK-NEXT: store ptr [[I]], ptr null, align 8 ; CHECK-NEXT: unreachable ; CHECK: f: ; CHECK-NEXT: [[E]] = getelementptr i8, ptr [[I]], i64 1 diff --git a/llvm/test/Transforms/NewGVN/pr33196.ll b/llvm/test/Transforms/NewGVN/pr33196.ll index c312d5ec9793048ed4e2a70e2e9b3d5c1e3e1033..c04b895fa47e96f3cac8eff1640ae46c125ccfba 100644 --- a/llvm/test/Transforms/NewGVN/pr33196.ll +++ b/llvm/test/Transforms/NewGVN/pr33196.ll @@ -1,33 +1,6 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -S -passes=newgvn %s | FileCheck %s -; CHECK: define i32 @main() { -; CHECK-NEXT: entry: -; CHECK-NEXT: %tmp = load i32, ptr @d, align 4 -; CHECK-NEXT: %tmp1 = load i32, ptr @c, align 4 -; CHECK-NEXT: %tobool = icmp eq i32 %tmp1, -1 -; CHECK-NEXT: br i1 %tobool, label %if.end, label %if.then -; CHECK: if.then: -; CHECK-NEXT: br label %L -; CHECK: L: -; CHECK-NEXT: %e.0 = phi i32 [ 0, %if.then ], [ %e.1, %if.then4 ] -; CHECK-NEXT: br label %if.end -; CHECK: if.end: -; CHECK-NEXT: %e.1 = phi i32 [ %e.0, %L ], [ %tmp, %entry ] -; CHECK-NEXT: store i32 %e.1, ptr @a, align 4 -; CHECK-NEXT: %tmp2 = load i32, ptr @b, align 4 -; CHECK-NEXT: store i32 0, ptr @b, align 4 -; CHECK-NEXT: %sext = shl i32 %tmp2, 16 -; CHECK-NEXT: %conv1 = ashr exact i32 %sext, 16 -; CHECK-NEXT: %add = add nsw i32 %conv1, %tmp1 -; CHECK-NEXT: %add2 = add nsw i32 %add, %e.1 -; CHECK-NEXT: store i32 %add2, ptr @a, align 4 -; CHECK-NEXT: %tobool3 = icmp eq i32 %add2, 0 -; CHECK-NEXT: br i1 %tobool3, label %if.end5, label %if.then4 -; CHECK: if.then4: -; CHECK-NEXT: br label %L -; CHECK: if.end5: -; CHECK-NEXT: ret i32 0 -; CHECK-NEXT: } @d = global i32 1, align 4 @c = common global i32 0, align 4 @@ -35,6 +8,34 @@ @b = common global i32 0, align 4 define i32 @main() { +; CHECK-LABEL: define i32 @main() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP:%.*]] = load i32, ptr @d, align 4 +; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @c, align 4 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TMP1]], -1 +; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] +; CHECK: if.then: +; CHECK-NEXT: br label [[L:%.*]] +; CHECK: L: +; CHECK-NEXT: [[E_0:%.*]] = phi i32 [ 0, [[IF_THEN]] ], [ [[E_1:%.*]], [[IF_THEN4:%.*]] ] +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[E_1]] = phi i32 [ [[E_0]], [[L]] ], [ [[TMP]], [[ENTRY:%.*]] ] +; CHECK-NEXT: store i32 [[E_1]], ptr @a, align 4 +; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr @b, align 4 +; CHECK-NEXT: store i32 0, ptr @b, align 4 +; CHECK-NEXT: [[SEXT:%.*]] = shl i32 [[TMP2]], 16 +; CHECK-NEXT: [[CONV1:%.*]] = ashr exact i32 [[SEXT]], 16 +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV1]], [[TMP1]] +; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[ADD]], [[E_1]] +; CHECK-NEXT: store i32 [[ADD2]], ptr @a, align 4 +; CHECK-NEXT: [[TOBOOL3:%.*]] = icmp eq i32 [[ADD2]], 0 +; CHECK-NEXT: br i1 [[TOBOOL3]], label [[IF_END5:%.*]], label [[IF_THEN4]] +; CHECK: if.then4: +; CHECK-NEXT: br label [[L]] +; CHECK: if.end5: +; CHECK-NEXT: ret i32 0 +; entry: %tmp = load i32, ptr @d, align 4 %tmp1 = load i32, ptr @c, align 4 diff --git a/llvm/test/Transforms/NewGVN/pr33204.ll b/llvm/test/Transforms/NewGVN/pr33204.ll index 99c48241a75c687df27df9a30f91ada6c3925642..482e35e7fdb11f5c624353964d9d55107d52af20 100644 --- a/llvm/test/Transforms/NewGVN/pr33204.ll +++ b/llvm/test/Transforms/NewGVN/pr33204.ll @@ -20,10 +20,10 @@ define void @hoge(i32 %arg) { ; CHECK-NEXT: [[TMP:%.*]] = phi i32 [ 0, [[BB1:%.*]] ], [ [[ARG:%.*]], [[BB:%.*]] ] ; CHECK-NEXT: br label [[BB6:%.*]] ; CHECK: bb3: -; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr @global, align 4, !h !0 +; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr @global, align 4, !h [[META0:![0-9]+]] ; CHECK-NEXT: unreachable ; CHECK: bb6: -; CHECK-NEXT: store i32 [[TMP]], ptr @global.1, align 4, !h !0 +; CHECK-NEXT: store i32 [[TMP]], ptr @global.1, align 4, !h [[META0]] ; CHECK-NEXT: br i1 undef, label [[BB7:%.*]], label [[BB1]] ; CHECK: bb7: ; CHECK-NEXT: br i1 undef, label [[BB10:%.*]], label [[BB8:%.*]] @@ -33,7 +33,7 @@ define void @hoge(i32 %arg) { ; CHECK-NEXT: store i8 poison, ptr null, align 1 ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb10: -; CHECK-NEXT: store i32 0, ptr @global, align 4, !h !0 +; CHECK-NEXT: store i32 0, ptr @global, align 4, !h [[META0]] ; CHECK-NEXT: br label [[BB7]] ; bb: diff --git a/llvm/test/Transforms/NewGVN/pr33305.ll b/llvm/test/Transforms/NewGVN/pr33305.ll index f87cf08e2abf737ea0cdb946821a2a94a2010288..3a19f610defcd79db0eb764ca5f17278d1551c55 100644 --- a/llvm/test/Transforms/NewGVN/pr33305.ll +++ b/llvm/test/Transforms/NewGVN/pr33305.ll @@ -19,14 +19,14 @@ target triple = "x86_64-apple-macosx10.12.0" define i32 @main() local_unnamed_addr #0 { ; CHECK-LABEL: @main( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[DOTPR_I:%.*]] = load i32, ptr @c, align 4, !tbaa !3 +; CHECK-NEXT: [[DOTPR_I:%.*]] = load i32, ptr @c, align 4, !tbaa [[TBAA3:![0-9]+]] ; CHECK-NEXT: [[CMP13_I:%.*]] = icmp slt i32 [[DOTPR_I]], 1 ; CHECK-NEXT: br i1 [[CMP13_I]], label [[FOR_COND1_PREHEADER_LR_PH_I:%.*]], label [[ENTRY_FOR_END9_I_CRIT_EDGE:%.*]] ; CHECK: entry.for.end9.i_crit_edge: -; CHECK-NEXT: [[DOTPRE:%.*]] = load i32, ptr @h, align 4, !tbaa !3 +; CHECK-NEXT: [[DOTPRE:%.*]] = load i32, ptr @h, align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: br label [[FOR_END9_I:%.*]] ; CHECK: for.cond1.preheader.lr.ph.i: -; CHECK-NEXT: [[G_PROMOTED14_I:%.*]] = load i32, ptr @g, align 4, !tbaa !3 +; CHECK-NEXT: [[G_PROMOTED14_I:%.*]] = load i32, ptr @g, align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: br label [[FOR_COND1_PREHEADER_I:%.*]] ; CHECK: for.cond1.preheader.i: ; CHECK-NEXT: [[INC816_I:%.*]] = phi i32 [ [[DOTPR_I]], [[FOR_COND1_PREHEADER_LR_PH_I]] ], [ [[INC8_I:%.*]], [[FOR_INC7_I:%.*]] ] @@ -42,9 +42,9 @@ define i32 @main() local_unnamed_addr #0 { ; CHECK: lor.rhs.i: ; CHECK-NEXT: [[LNOT_I:%.*]] = xor i1 [[TOBOOL_I]], true ; CHECK-NEXT: [[LNOT_EXT_I:%.*]] = zext i1 [[LNOT_I]] to i32 -; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr @e, align 4, !tbaa !3 +; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr @e, align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[XOR_I:%.*]] = xor i32 [[TMP3]], [[LNOT_EXT_I]] -; CHECK-NEXT: store i32 [[XOR_I]], ptr @e, align 4, !tbaa !3 +; CHECK-NEXT: store i32 [[XOR_I]], ptr @e, align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: br label [[LOR_END_I]] ; CHECK: lor.end.i: ; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[INC12_I]], 1 @@ -55,28 +55,28 @@ define i32 @main() local_unnamed_addr #0 { ; CHECK-NEXT: [[CMP_I:%.*]] = icmp slt i32 [[INC816_I]], 0 ; CHECK-NEXT: br i1 [[CMP_I]], label [[FOR_COND1_PREHEADER_I]], label [[FOR_COND_FOR_END9_CRIT_EDGE_I:%.*]] ; CHECK: for.cond.for.end9_crit_edge.i: -; CHECK-NEXT: store i32 0, ptr @g, align 4, !tbaa !3 -; CHECK-NEXT: store i32 2, ptr @h, align 4, !tbaa !3 -; CHECK-NEXT: store i32 [[INC8_I]], ptr @c, align 4, !tbaa !3 +; CHECK-NEXT: store i32 0, ptr @g, align 4, !tbaa [[TBAA3]] +; CHECK-NEXT: store i32 2, ptr @h, align 4, !tbaa [[TBAA3]] +; CHECK-NEXT: store i32 [[INC8_I]], ptr @c, align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: br label [[FOR_END9_I]] ; CHECK: for.end9.i: ; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ [[DOTPRE]], [[ENTRY_FOR_END9_I_CRIT_EDGE]] ], [ 2, [[FOR_COND_FOR_END9_CRIT_EDGE_I]] ] -; CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr @b, align 8, !tbaa !7 -; CHECK-NEXT: store i32 [[TMP4]], ptr [[TMP5]], align 4, !tbaa !3 -; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr @e, align 4, !tbaa !3 +; CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr @b, align 8, !tbaa [[TBAA7:![0-9]+]] +; CHECK-NEXT: store i32 [[TMP4]], ptr [[TMP5]], align 4, !tbaa [[TBAA3]] +; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr @e, align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[CMP10_I:%.*]] = icmp slt i32 [[TMP6]], -1 ; CHECK-NEXT: br i1 [[CMP10_I]], label [[IF_THEN_I:%.*]], label [[FN1_EXIT:%.*]] ; CHECK: if.then.i: -; CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr @f, align 4, !tbaa !3 -; CHECK-NEXT: store i32 [[TMP7]], ptr [[TMP5]], align 4, !tbaa !3 +; CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr @f, align 4, !tbaa [[TBAA3]] +; CHECK-NEXT: store i32 [[TMP7]], ptr [[TMP5]], align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: br label [[FN1_EXIT]] ; CHECK: fn1.exit: -; CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr @a, align 4, !tbaa !3 +; CHECK-NEXT: [[TMP8:%.*]] = load i32, ptr @a, align 4, !tbaa [[TBAA3]] ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TMP8]], 0 ; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[PUTS2:%.*]] = tail call i32 @puts(ptr @str.2) -; CHECK-NEXT: tail call void @abort() +; CHECK-NEXT: tail call void @abort() #[[ATTR3:[0-9]+]] ; CHECK-NEXT: unreachable ; CHECK: if.end: ; CHECK-NEXT: [[PUTS:%.*]] = tail call i32 @puts(ptr @str) diff --git a/llvm/test/Transforms/NewGVN/pr33367.ll b/llvm/test/Transforms/NewGVN/pr33367.ll index dc5d190291e1ccc98a7ec60f5c1cc0bc17bdff70..597caa2b34ef28463aadf02685ebbaa39b02c521 100644 --- a/llvm/test/Transforms/NewGVN/pr33367.ll +++ b/llvm/test/Transforms/NewGVN/pr33367.ll @@ -11,19 +11,19 @@ define %MNR_struct @f000316011717_2(ptr %pDS, ptr %pCG) #2 { ; CHECK-NEXT: Entry: ; CHECK-NEXT: [[RESTART:%.*]] = alloca [[MNR_STRUCT:%.*]], align 8 ; CHECK-NEXT: [[PCARRY:%.*]] = getelementptr [[DS_STRUCT:%.*]], ptr [[PDS:%.*]], i32 0, i32 1 -; CHECK-NEXT: [[BASE:%.*]] = load ptr, ptr [[PDS]], align 8, !tbaa !14 +; CHECK-NEXT: [[BASE:%.*]] = load ptr, ptr [[PDS]], align 8, !tbaa [[TBAA14:![0-9]+]] ; CHECK-NEXT: [[ABSADDR:%.*]] = getelementptr i64, ptr [[BASE]], i64 9 -; CHECK-NEXT: [[EXTARGET:%.*]] = load i64, ptr [[ABSADDR]], align 8, !tbaa !4 +; CHECK-NEXT: [[EXTARGET:%.*]] = load i64, ptr [[ABSADDR]], align 8, !tbaa [[TBAA4:![0-9]+]] ; CHECK-NEXT: [[TEMPLATE:%.*]] = icmp eq i64 [[EXTARGET]], 8593987412 ; CHECK-NEXT: br i1 [[TEMPLATE]], label %"BB3.000316011731#1", label [[BB2_000316011731_5:%.*]] ; CHECK: "BB3.000316011731#1": ; CHECK-NEXT: [[PBASE8:%.*]] = getelementptr [32 x ptr], ptr [[PDS]], i64 0, i64 29 -; CHECK-NEXT: [[BASE9:%.*]] = load ptr, ptr [[PBASE8]], align 8, !tbaa !14 +; CHECK-NEXT: [[BASE9:%.*]] = load ptr, ptr [[PBASE8]], align 8, !tbaa [[TBAA14]] ; CHECK-NEXT: [[ABSADDR1:%.*]] = getelementptr i64, ptr [[BASE9]], i64 7 -; CHECK-NEXT: [[RMEM:%.*]] = load i64, ptr [[ABSADDR1]], align 8, !tbaa !4 +; CHECK-NEXT: [[RMEM:%.*]] = load i64, ptr [[ABSADDR1]], align 8, !tbaa [[TBAA4]] ; CHECK-NEXT: [[PWT:%.*]] = getelementptr [[DS_STRUCT]], ptr [[PDS]], i32 0, i32 2 ; CHECK-NEXT: [[PWTE:%.*]] = getelementptr [32 x i16], ptr [[PWT]], i64 0, i64 8593987412 -; CHECK-NEXT: [[SHIFTS:%.*]] = load i16, ptr [[PWTE]], align 2, !tbaa !18, !invariant.load !20 +; CHECK-NEXT: [[SHIFTS:%.*]] = load i16, ptr [[PWTE]], align 2, !tbaa [[TBAA18:![0-9]+]], !invariant.load [[META20:![0-9]+]] ; CHECK-NEXT: [[SLOWJ:%.*]] = icmp eq i16 [[SHIFTS]], 0 ; CHECK-NEXT: br i1 [[SLOWJ]], label [[BB2_000316011731_5]], label %"BB3.000316011731#1.1" ; CHECK: BB2.000316011731.5: @@ -34,22 +34,22 @@ define %MNR_struct @f000316011717_2(ptr %pDS, ptr %pCG) #2 { ; CHECK-NEXT: [[SHIFTS1:%.*]] = zext i16 [[SHIFTS]] to i64 ; CHECK-NEXT: [[VAL:%.*]] = call i64 @llvm.x86.bmi.bextr.64(i64 [[RMEM]], i64 [[SHIFTS1]]) ; CHECK-NEXT: [[PREG:%.*]] = getelementptr [64 x i64], ptr [[PCG:%.*]], i64 0, i64 12 -; CHECK-NEXT: store i64 [[VAL]], ptr [[PREG]], align 32, !tbaa !10 +; CHECK-NEXT: store i64 [[VAL]], ptr [[PREG]], align 32, !tbaa [[TBAA10:![0-9]+]] ; CHECK-NEXT: [[PREG2:%.*]] = getelementptr [64 x i64], ptr [[PCG]], i64 0, i64 14 -; CHECK-NEXT: [[REG:%.*]] = load i64, ptr [[PREG2]], align 16, !tbaa !12 -; CHECK-NEXT: [[BASE2:%.*]] = load ptr, ptr [[PBASE8]], align 8, !tbaa !14 +; CHECK-NEXT: [[REG:%.*]] = load i64, ptr [[PREG2]], align 16, !tbaa [[TBAA12:![0-9]+]] +; CHECK-NEXT: [[BASE2:%.*]] = load ptr, ptr [[PBASE8]], align 8, !tbaa [[TBAA14]] ; CHECK-NEXT: [[ABSADDR2:%.*]] = getelementptr i64, ptr [[BASE2]], i64 [[REG]] -; CHECK-NEXT: [[RMEM2:%.*]] = load i64, ptr [[ABSADDR2]], align 8, !tbaa !1 +; CHECK-NEXT: [[RMEM2:%.*]] = load i64, ptr [[ABSADDR2]], align 8, !tbaa [[TBAA1:![0-9]+]] ; CHECK-NEXT: [[PREG7:%.*]] = getelementptr [64 x i64], ptr [[PCG]], i64 0, i64 9 -; CHECK-NEXT: store i64 [[RMEM2]], ptr [[PREG7]], align 8, !tbaa !8 +; CHECK-NEXT: store i64 [[RMEM2]], ptr [[PREG7]], align 8, !tbaa [[TBAA8:![0-9]+]] ; CHECK-NEXT: [[ADD2C279:%.*]] = add i64 [[RMEM2]], [[VAL]] ; CHECK-NEXT: [[CCHK:%.*]] = icmp sge i64 [[ADD2C279]], 0 ; CHECK-NEXT: [[CFL:%.*]] = zext i1 [[CCHK]] to i8 -; CHECK-NEXT: store i8 [[CFL]], ptr [[PCARRY]], align 1, !tbaa !16 +; CHECK-NEXT: store i8 [[CFL]], ptr [[PCARRY]], align 1, !tbaa [[TBAA16:![0-9]+]] ; CHECK-NEXT: br label [[EXIT]] ; CHECK: Exit: ; CHECK-NEXT: [[RESTART378:%.*]] = load [[MNR_STRUCT]], ptr [[RESTART]], align 8 -; CHECK-NEXT: ret [[MNR_STRUCT]] %restart378 +; CHECK-NEXT: ret [[MNR_STRUCT]] [[RESTART378]] ; Entry: %restart = alloca %MNR_struct diff --git a/llvm/test/Transforms/NewGVN/pr34452.ll b/llvm/test/Transforms/NewGVN/pr34452.ll index f5d5fda343037ce072b9ba2ec8ac08609518ed39..9e65349a1b47be0ac6c9f8acc0d2d3df0e22a15e 100644 --- a/llvm/test/Transforms/NewGVN/pr34452.ll +++ b/llvm/test/Transforms/NewGVN/pr34452.ll @@ -9,7 +9,7 @@ source_filename = "bugpoint-output-09f7a24.bc" define void @sgrep() local_unnamed_addr #0 { ; CHECK-LABEL: @sgrep( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @WHOLELINE, align 4, !tbaa !1 +; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @WHOLELINE, align 4, !tbaa [[TBAA1:![0-9]+]] ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TMP0]], 0 ; CHECK-NEXT: [[DOT:%.*]] = select i1 [[TOBOOL]], i32 2048, i32 2047 ; CHECK-NEXT: br label [[WHILE_BODY_US:%.*]] diff --git a/llvm/test/Transforms/NewGVN/pr42422-phi-of-ops.ll b/llvm/test/Transforms/NewGVN/pr42422-phi-of-ops.ll index cbdf209d1ce50c4cc5b69faba240686dd3d358e2..1312f9f4f02967cbbd34e1c5b5900dbdff541121 100644 --- a/llvm/test/Transforms/NewGVN/pr42422-phi-of-ops.ll +++ b/llvm/test/Transforms/NewGVN/pr42422-phi-of-ops.ll @@ -40,8 +40,8 @@ define void @d() { ; CHECK: cleanup: ; CHECK-NEXT: [[CLEANUP_DEST:%.*]] = phi i32 [ poison, [[IF_END12]] ], [ 1, [[IF_THEN11]] ], [ 9, [[IF_THEN]] ] ; CHECK-NEXT: switch i32 [[CLEANUP_DEST]], label [[CLEANUP14]] [ -; CHECK-NEXT: i32 0, label [[FOR_COND4]] -; CHECK-NEXT: i32 9, label [[FOR_END13:%.*]] +; CHECK-NEXT: i32 0, label [[FOR_COND4]] +; CHECK-NEXT: i32 9, label [[FOR_END13:%.*]] ; CHECK-NEXT: ] ; CHECK: for.end13: ; CHECK-NEXT: br label [[CLEANUP14]] diff --git a/llvm/test/Transforms/NewGVN/pr43441.ll b/llvm/test/Transforms/NewGVN/pr43441.ll index 5c4a9c3bc7b5d155be0aa4e18b571b540d9032c6..a5f711dbd69e5f81ef55b9e38bc0cfb188ae2e04 100644 --- a/llvm/test/Transforms/NewGVN/pr43441.ll +++ b/llvm/test/Transforms/NewGVN/pr43441.ll @@ -1,15 +1,37 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -S < %s | FileCheck %s target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" -; CHECK-LABEL: @print_long_format() define dso_local void @print_long_format() #0 { +; CHECK-LABEL: define dso_local void @print_long_format( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: switch i32 undef, label [[SW_DEFAULT:%.*]] [ +; CHECK-NEXT: i32 1, label [[SW_BB:%.*]] +; CHECK-NEXT: i32 0, label [[SW_BB19:%.*]] +; CHECK-NEXT: i32 2, label [[SW_BB23:%.*]] +; CHECK-NEXT: ] +; CHECK: sw.bb: +; CHECK-NEXT: unreachable +; CHECK: sw.bb19: +; CHECK-NEXT: br i1 undef, label [[IF_THEN37:%.*]], label [[IF_END50:%.*]] +; CHECK: sw.bb23: +; CHECK-NEXT: unreachable +; CHECK: sw.default: +; CHECK-NEXT: unreachable +; CHECK: if.then37: +; CHECK-NEXT: unreachable +; CHECK: if.end50: +; CHECK-NEXT: [[CALL180:%.*]] = call i32 @timespec_cmp() #[[ATTR2:[0-9]+]] +; CHECK-NEXT: ret void +; entry: switch i32 undef, label %sw.default [ - i32 1, label %sw.bb - i32 0, label %sw.bb19 - i32 2, label %sw.bb23 + i32 1, label %sw.bb + i32 0, label %sw.bb19 + i32 2, label %sw.bb23 ] sw.bb: ; preds = %entry diff --git a/llvm/test/Transforms/NewGVN/pre-compare.ll b/llvm/test/Transforms/NewGVN/pre-compare.ll index 9fd20fcc76ed6965f1e129055d42ebc8fbe91823..8e4e5f813e89a28b97b4deadce35658bd1863a06 100644 --- a/llvm/test/Transforms/NewGVN/pre-compare.ll +++ b/llvm/test/Transforms/NewGVN/pre-compare.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -S < %s | FileCheck %s ; C source: @@ -37,6 +38,28 @@ @.str3 = private unnamed_addr constant [12 x i8] c"step 2: %d\0A\00", align 1 define void @f(i32 %x) noreturn nounwind uwtable ssp { +; CHECK-LABEL: define void @f( +; CHECK-SAME: i32 [[X:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X]], 1 +; CHECK-NEXT: br i1 [[CMP]], label [[FOR_COND_PREHEADER:%.*]], label [[IF_THEN:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[X]], 2 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP1]], ptr @.str, ptr @.str1 +; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @puts(ptr [[COND]]) #[[ATTR1:[0-9]+]] +; CHECK-NEXT: br label [[FOR_COND_PREHEADER]] +; CHECK: for.cond.preheader: +; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[X]], 2 +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: [[CALL2:%.*]] = tail call i32 @puts(ptr @.str2) #[[ATTR1]] +; CHECK-NEXT: br i1 [[CMP3]], label [[FOR_COND_BACKEDGE:%.*]], label [[IF_END5:%.*]] +; CHECK: if.end5: +; CHECK-NEXT: [[CALL6:%.*]] = tail call i32 (ptr, ...) @printf(ptr @.str3, i32 [[X]]) #[[ATTR1]] +; CHECK-NEXT: br label [[FOR_COND_BACKEDGE]] +; CHECK: for.cond.backedge: +; CHECK-NEXT: br label [[FOR_COND]] +; entry: %cmp = icmp eq i32 %x, 1 br i1 %cmp, label %for.cond.preheader, label %if.then diff --git a/llvm/test/Transforms/NewGVN/preserve-metadata-for-predicate-replacements.ll b/llvm/test/Transforms/NewGVN/preserve-metadata-for-predicate-replacements.ll index 1ca24af84e48aa8712028a8c5dc37c49473cfaec..a63ca131b5c0dd751b153a3b1597b93b5ee9931c 100644 --- a/llvm/test/Transforms/NewGVN/preserve-metadata-for-predicate-replacements.ll +++ b/llvm/test/Transforms/NewGVN/preserve-metadata-for-predicate-replacements.ll @@ -9,7 +9,7 @@ declare void @use(i32) define i32 @test(ptr %p1, ptr %p2, i1 %c) { ; CHECK-LABEL: @test( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[LV:%.*]] = load i32, ptr [[P1:%.*]], align 8, !tbaa !0 +; CHECK-NEXT: [[LV:%.*]] = load i32, ptr [[P1:%.*]], align 8, !tbaa [[TBAA0:![0-9]+]] ; CHECK-NEXT: [[CMP_1:%.*]] = icmp slt i32 [[LV]], 1 ; CHECK-NEXT: br i1 [[CMP_1]], label [[EXIT:%.*]], label [[IF_FALSE:%.*]] ; CHECK: if.false: diff --git a/llvm/test/Transforms/NewGVN/readattrs.ll b/llvm/test/Transforms/NewGVN/readattrs.ll index 049a2fc911687bb31b868b1715638670ad27fa8f..544fe45be24976808f74994654e3923a9d24a7f9 100644 --- a/llvm/test/Transforms/NewGVN/readattrs.ll +++ b/llvm/test/Transforms/NewGVN/readattrs.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -S -o - < %s | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" @@ -6,12 +7,15 @@ target triple = "x86_64-unknown-linux-gnu" declare void @use(ptr readonly nocapture) define i8 @test() { +; CHECK-LABEL: define i8 @test() { +; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1 +; CHECK-NEXT: store i8 1, ptr [[A]], align 1 +; CHECK-NEXT: call void @use(ptr [[A]]) +; CHECK-NEXT: ret i8 1 +; %a = alloca i8 store i8 1, ptr %a call void @use(ptr %a) %b = load i8, ptr %a ret i8 %b -; CHECK-LABEL: define i8 @test( -; CHECK: call void @use(ptr %a) -; CHECK-NEXT: ret i8 1 } diff --git a/llvm/test/Transforms/NewGVN/rle-nonlocal.ll b/llvm/test/Transforms/NewGVN/rle-nonlocal.ll index c2fb39100da45f1de050f7e2274664dccfde08c7..efdfd1f6dc7b5b826355be288ecc216e9609711f 100644 --- a/llvm/test/Transforms/NewGVN/rle-nonlocal.ll +++ b/llvm/test/Transforms/NewGVN/rle-nonlocal.ll @@ -7,14 +7,14 @@ define i32 @main(ptr %p, i32 %x, i32 %y) { ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: br i1 [[CMP]], label [[BLOCK2:%.*]], label [[BLOCK3:%.*]] ; CHECK: block2: -; CHECK-NEXT: [[A:%.*]] = load ptr, ptr [[P:%.*]] +; CHECK-NEXT: [[A:%.*]] = load ptr, ptr [[P:%.*]], align 8 ; CHECK-NEXT: br label [[BLOCK4:%.*]] ; CHECK: block3: -; CHECK-NEXT: [[B:%.*]] = load ptr, ptr [[P]] +; CHECK-NEXT: [[B:%.*]] = load ptr, ptr [[P]], align 8 ; CHECK-NEXT: br label [[BLOCK4]] ; CHECK: block4: ; CHECK-NEXT: [[EXISTINGPHI:%.*]] = phi ptr [ [[A]], [[BLOCK2]] ], [ [[B]], [[BLOCK3]] ] -; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[EXISTINGPHI]] +; CHECK-NEXT: [[C:%.*]] = load i32, ptr [[EXISTINGPHI]], align 4 ; CHECK-NEXT: [[E:%.*]] = add i32 [[C]], [[C]] ; CHECK-NEXT: ret i32 [[E]] ; diff --git a/llvm/test/Transforms/NewGVN/rle.ll b/llvm/test/Transforms/NewGVN/rle.ll index 1cfdc83f40da050b004bc3142dfa3f46c822001f..950c492d8736521678fdeeeaddbacc0bbd0b43dc 100644 --- a/llvm/test/Transforms/NewGVN/rle.ll +++ b/llvm/test/Transforms/NewGVN/rle.ll @@ -1,15 +1,19 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt < %s -data-layout="e-p:32:32:32-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-n8:16:32" -passes=newgvn,dce -S | FileCheck %s ; RUN: opt < %s -data-layout="E-p:32:32:32-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-n32" -passes=newgvn,dce -S | FileCheck %s ; memset -> i16 forwarding. define signext i16 @memset_to_i16_local(ptr %A) nounwind ssp { +; CHECK-LABEL: define signext i16 @memset_to_i16_local( +; CHECK-SAME: ptr [[A:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr [[A]], i8 1, i64 200, i1 false) +; CHECK-NEXT: ret i16 257 +; entry: tail call void @llvm.memset.p0.i64(ptr %A, i8 1, i64 200, i1 false) %arrayidx = getelementptr inbounds i16, ptr %A, i64 42 %tmp2 = load i16, ptr %arrayidx ret i16 %tmp2 -; CHECK-LABEL: @memset_to_i16_local( -; CHECK-NOT: load -; CHECK: ret i16 257 } @GCst = constant {i32, float, i32 } { i32 42, float 14., i32 97 } @@ -17,37 +21,48 @@ entry: ; memset -> float forwarding. define float @memcpy_to_float_local(ptr %A) nounwind ssp { +; CHECK-LABEL: define float @memcpy_to_float_local( +; CHECK-SAME: ptr [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr [[A]], ptr @GCst, i64 12, i1 false) +; CHECK-NEXT: ret float 1.400000e+01 +; entry: tail call void @llvm.memcpy.p0.p0.i64(ptr %A, ptr @GCst, i64 12, i1 false) %arrayidx = getelementptr inbounds float, ptr %A, i64 1 ; <ptr> [#uses=1] %tmp2 = load float, ptr %arrayidx ; <float> [#uses=1] ret float %tmp2 -; CHECK-LABEL: @memcpy_to_float_local( -; CHECK-NOT: load -; CHECK: ret float 1.400000e+01 } ; memcpy from address space 1 define float @memcpy_to_float_local_as1(ptr %A) nounwind ssp { +; CHECK-LABEL: define float @memcpy_to_float_local_as1( +; CHECK-SAME: ptr [[A:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: tail call void @llvm.memcpy.p0.p1.i64(ptr [[A]], ptr addrspace(1) @GCst_as1, i64 12, i1 false) +; CHECK-NEXT: ret float 1.400000e+01 +; entry: tail call void @llvm.memcpy.p0.p1.i64(ptr %A, ptr addrspace(1) @GCst_as1, i64 12, i1 false) %arrayidx = getelementptr inbounds float, ptr %A, i64 1 ; <ptr> [#uses=1] %tmp2 = load float, ptr %arrayidx ; <float> [#uses=1] ret float %tmp2 -; CHECK-LABEL: @memcpy_to_float_local_as1( -; CHECK-NOT: load -; CHECK: ret float 1.400000e+01 } ; PR6642 define i32 @memset_to_load() nounwind readnone { +; CHECK-LABEL: define i32 @memset_to_load( +; CHECK-SAME: ) #[[ATTR1:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[X:%.*]] = alloca [256 x i32], align 4 +; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[X]], i8 0, i64 1024, i1 false) +; CHECK-NEXT: ret i32 0 +; entry: %x = alloca [256 x i32], align 4 ; <ptr> [#uses=2] call void @llvm.memset.p0.i64(ptr align 4 %x, i8 0, i64 1024, i1 false) %arraydecay = getelementptr inbounds [256 x i32], ptr %x, i32 0, i32 0 ; <ptr> %tmp1 = load i32, ptr %arraydecay ; <i32> [#uses=1] ret i32 %tmp1 -; CHECK-LABEL: @memset_to_load( -; CHECK: ret i32 0 } declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1) nounwind diff --git a/llvm/test/Transforms/NewGVN/simp-to-self.ll b/llvm/test/Transforms/NewGVN/simp-to-self.ll index fb8a01962959bcf9bb774cb31c951165cb3308a8..f9a0ec257259a1c6f95a43c79908713818f9e42b 100644 --- a/llvm/test/Transforms/NewGVN/simp-to-self.ll +++ b/llvm/test/Transforms/NewGVN/simp-to-self.ll @@ -1,13 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -S < %s -passes=newgvn | FileCheck %s -; CHECK-LABEL: for.cond: -; CHECK-NEXT: %lv = load i32, ptr @a -; CHECK-NEXT: %bf.clear = and i32 %lv, -131072 -; CHECK-NEXT: %bf.set = or i32 1, %bf.clear -; CHECK-NEXT: br i1 %bc, label %for.cond, label %exit @a = external global i64 define void @fn1(i1 %bc) { +; CHECK-LABEL: define void @fn1( +; CHECK-SAME: i1 [[BC:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: [[LV:%.*]] = load i32, ptr @a, align 4 +; CHECK-NEXT: [[BF_CLEAR:%.*]] = and i32 [[LV]], -131072 +; CHECK-NEXT: [[BF_SET:%.*]] = or i32 1, [[BF_CLEAR]] +; CHECK-NEXT: br i1 [[BC]], label [[FOR_COND]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: store i32 [[BF_SET]], ptr @a, align 4 +; CHECK-NEXT: ret void +; entry: br label %for.cond diff --git a/llvm/test/Transforms/NewGVN/stale-loop-info.ll b/llvm/test/Transforms/NewGVN/stale-loop-info.ll index 8870824d38ad6d1864f10a3aebbe5f20371de77c..7abe80b005ecf29b926e0a82aa1b150cf404a63b 100644 --- a/llvm/test/Transforms/NewGVN/stale-loop-info.ll +++ b/llvm/test/Transforms/NewGVN/stale-loop-info.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes='require<loops>,newgvn' -S < %s | FileCheck %s ; This used to fail with ASAN enabled and if for some reason LoopInfo remained @@ -14,6 +15,29 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" declare void @snork.1(ptr) local_unnamed_addr #0 define hidden zeroext i1 @eggs(ptr %arg, i1 %arg2) unnamed_addr align 2 { +; CHECK-LABEL: define hidden zeroext i1 @eggs( +; CHECK-SAME: ptr [[ARG:%.*]], i1 [[ARG2:%.*]]) unnamed_addr align 2 { +; CHECK-NEXT: bb: +; CHECK-NEXT: br i1 [[ARG2]], label [[BB14:%.*]], label [[BB3:%.*]] +; CHECK: bb3: +; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds [[STRUCT_WIBBLE_1028:%.*]], ptr [[ARG]], i64 0, i32 2, i32 0, i32 0, i64 0 +; CHECK-NEXT: br label [[BB6:%.*]] +; CHECK: bb6: +; CHECK-NEXT: br label [[BB7:%.*]] +; CHECK: bb7: +; CHECK-NEXT: br i1 undef, label [[BB11:%.*]], label [[BB8:%.*]] +; CHECK: bb8: +; CHECK-NEXT: [[TMP9:%.*]] = load ptr, ptr [[TMP]], align 8 +; CHECK-NEXT: br label [[BB12:%.*]] +; CHECK: bb11: +; CHECK-NEXT: br label [[BB12]] +; CHECK: bb12: +; CHECK-NEXT: [[TMP13:%.*]] = phi ptr [ [[TMP]], [[BB11]] ], [ [[TMP9]], [[BB8]] ] +; CHECK-NEXT: call void @snork.1(ptr [[TMP13]]) #[[ATTR1:[0-9]+]] +; CHECK-NEXT: br label [[BB6]] +; CHECK: bb14: +; CHECK-NEXT: ret i1 false +; bb: br i1 %arg2, label %bb14, label %bb3 @@ -29,7 +53,6 @@ bb7: ; preds = %bb6 bb8: ; preds = %bb7 %tmp9 = load ptr, ptr %tmp, align 8 -; CHECK: %tmp9 = load ptr, ptr %tmp, align 8 br label %bb12 bb11: ; preds = %bb7 diff --git a/llvm/test/Transforms/NewGVN/tbaa.ll b/llvm/test/Transforms/NewGVN/tbaa.ll index e6d66dca0decffdbaaac724efe08734e14a96ab0..335e782acc8bcd0d5ee3ae5ef7ee82b6b0ef319e 100644 --- a/llvm/test/Transforms/NewGVN/tbaa.ll +++ b/llvm/test/Transforms/NewGVN/tbaa.ll @@ -1,10 +1,13 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -S < %s | FileCheck %s define i32 @test1(ptr %p, ptr %q) { -; CHECK-LABEL: @test1(ptr %p, ptr %q) -; CHECK: call i32 @foo(ptr %p) -; CHECK-NOT: tbaa -; CHECK: %c = add i32 %a, %a +; CHECK-LABEL: define i32 @test1( +; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { +; CHECK-NEXT: [[A:%.*]] = call i32 @foo(ptr [[P]]) +; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] +; CHECK-NEXT: ret i32 [[C]] +; %a = call i32 @foo(ptr %p), !tbaa !0 %b = call i32 @foo(ptr %p) %c = add i32 %a, %b @@ -12,9 +15,12 @@ define i32 @test1(ptr %p, ptr %q) { } define i32 @test2(ptr %p, ptr %q) { -; CHECK-LABEL: @test2(ptr %p, ptr %q) -; CHECK: call i32 @foo(ptr %p), !tbaa [[TAGC:!.*]] -; CHECK: %c = add i32 %a, %a +; CHECK-LABEL: define i32 @test2( +; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { +; CHECK-NEXT: [[A:%.*]] = call i32 @foo(ptr [[P]]), !tbaa [[TBAA0:![0-9]+]] +; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] +; CHECK-NEXT: ret i32 [[C]] +; %a = call i32 @foo(ptr %p), !tbaa !0 %b = call i32 @foo(ptr %p), !tbaa !0 %c = add i32 %a, %b @@ -22,9 +28,12 @@ define i32 @test2(ptr %p, ptr %q) { } define i32 @test3(ptr %p, ptr %q) { -; CHECK-LABEL: @test3(ptr %p, ptr %q) -; CHECK: call i32 @foo(ptr %p), !tbaa [[TAGB:!.*]] -; CHECK: %c = add i32 %a, %a +; CHECK-LABEL: define i32 @test3( +; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { +; CHECK-NEXT: [[A:%.*]] = call i32 @foo(ptr [[P]]), !tbaa [[TBAA4:![0-9]+]] +; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] +; CHECK-NEXT: ret i32 [[C]] +; %a = call i32 @foo(ptr %p), !tbaa !3 %b = call i32 @foo(ptr %p), !tbaa !3 %c = add i32 %a, %b @@ -32,9 +41,12 @@ define i32 @test3(ptr %p, ptr %q) { } define i32 @test4(ptr %p, ptr %q) { -; CHECK-LABEL: @test4(ptr %p, ptr %q) -; CHECK: call i32 @foo(ptr %p), !tbaa [[TAGA:!.*]] -; CHECK: %c = add i32 %a, %a +; CHECK-LABEL: define i32 @test4( +; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { +; CHECK-NEXT: [[A:%.*]] = call i32 @foo(ptr [[P]]), !tbaa [[TBAA6:![0-9]+]] +; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] +; CHECK-NEXT: ret i32 [[C]] +; %a = call i32 @foo(ptr %p), !tbaa !1 %b = call i32 @foo(ptr %p), !tbaa !0 %c = add i32 %a, %b @@ -42,9 +54,12 @@ define i32 @test4(ptr %p, ptr %q) { } define i32 @test5(ptr %p, ptr %q) { -; CHECK-LABEL: @test5(ptr %p, ptr %q) -; CHECK: call i32 @foo(ptr %p), !tbaa [[TAGA]] -; CHECK: %c = add i32 %a, %a +; CHECK-LABEL: define i32 @test5( +; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { +; CHECK-NEXT: [[A:%.*]] = call i32 @foo(ptr [[P]]), !tbaa [[TBAA6]] +; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] +; CHECK-NEXT: ret i32 [[C]] +; %a = call i32 @foo(ptr %p), !tbaa !0 %b = call i32 @foo(ptr %p), !tbaa !1 %c = add i32 %a, %b @@ -52,9 +67,12 @@ define i32 @test5(ptr %p, ptr %q) { } define i32 @test6(ptr %p, ptr %q) { -; CHECK-LABEL: @test6(ptr %p, ptr %q) -; CHECK: call i32 @foo(ptr %p), !tbaa [[TAGA]] -; CHECK: %c = add i32 %a, %a +; CHECK-LABEL: define i32 @test6( +; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { +; CHECK-NEXT: [[A:%.*]] = call i32 @foo(ptr [[P]]), !tbaa [[TBAA6]] +; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] +; CHECK-NEXT: ret i32 [[C]] +; %a = call i32 @foo(ptr %p), !tbaa !0 %b = call i32 @foo(ptr %p), !tbaa !3 %c = add i32 %a, %b @@ -62,10 +80,12 @@ define i32 @test6(ptr %p, ptr %q) { } define i32 @test7(ptr %p, ptr %q) { -; CHECK-LABEL: @test7(ptr %p, ptr %q) -; CHECK: call i32 @foo(ptr %p) -; CHECK-NOT: tbaa -; CHECK: %c = add i32 %a, %a +; CHECK-LABEL: define i32 @test7( +; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { +; CHECK-NEXT: [[A:%.*]] = call i32 @foo(ptr [[P]]) +; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] +; CHECK-NEXT: ret i32 [[C]] +; %a = call i32 @foo(ptr %p), !tbaa !4 %b = call i32 @foo(ptr %p), !tbaa !3 %c = add i32 %a, %b @@ -73,9 +93,11 @@ define i32 @test7(ptr %p, ptr %q) { } define i32 @test8(ptr %p, ptr %q) { -; CHECK-LABEL: @test8 -; CHECK-NEXT: store i32 15, ptr %p -; CHECK-NEXT: ret i32 0 +; CHECK-LABEL: define i32 @test8( +; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { +; CHECK-NEXT: store i32 15, ptr [[P]], align 4 +; CHECK-NEXT: ret i32 0 +; ; Since we know the location is invariant, we can forward the ; load across the potentially aliasing store. @@ -87,9 +109,11 @@ define i32 @test8(ptr %p, ptr %q) { } define i32 @test9(ptr %p, ptr %q) { -; CHECK-LABEL: @test9 -; CHECK-NEXT: call void @clobber() -; CHECK-NEXT: ret i32 0 +; CHECK-LABEL: define i32 @test9( +; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { +; CHECK-NEXT: call void @clobber() +; CHECK-NEXT: ret i32 0 +; ; Since we know the location is invariant, we can forward the ; load across the potentially aliasing store (within the call). @@ -103,9 +127,12 @@ define i32 @test9(ptr %p, ptr %q) { define i32 @test10(ptr %p, ptr %q) { ; If one access encloses the other, then the merged access is the enclosed one ; and not just the common final access type. -; CHECK-LABEL: @test10 -; CHECK: call i32 @foo(ptr %p), !tbaa [[TAG_X_i:!.*]] -; CHECK: %c = add i32 %a, %a +; CHECK-LABEL: define i32 @test10( +; CHECK-SAME: ptr [[P:%.*]], ptr [[Q:%.*]]) { +; CHECK-NEXT: [[A:%.*]] = call i32 @foo(ptr [[P]]), !tbaa [[TBAA7:![0-9]+]] +; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[A]] +; CHECK-NEXT: ret i32 [[C]] +; %a = call i32 @foo(ptr %p), !tbaa !15 ; TAG_X_i %b = call i32 @foo(ptr %p), !tbaa !19 ; TAG_Y_x_i %c = add i32 %a, %b @@ -115,12 +142,6 @@ define i32 @test10(ptr %p, ptr %q) { declare void @clobber() declare i32 @foo(ptr) readonly -; CHECK-DAG: [[TAGC]] = !{[[TYPEC:!.*]], [[TYPEC]], i64 0} -; CHECK-DAG: [[TYPEC]] = !{!"C", [[TYPEA:!.*]]} -; CHECK-DAG: [[TYPEA]] = !{!"A", !{{.*}}} -; CHECK-DAG: [[TAGB]] = !{[[TYPEB:!.*]], [[TYPEB]], i64 0} -; CHECK-DAG: [[TYPEB]] = !{!"B", [[TYPEA]]} -; CHECK-DAG: [[TAGA]] = !{[[TYPEA]], [[TYPEA]], i64 0} !0 = !{!5, !5, i64 0} !1 = !{!6, !6, i64 0} !2 = !{!"tbaa root"} @@ -132,9 +153,6 @@ declare i32 @foo(ptr) readonly !8 = !{!"another root"} !11 = !{!"scalar type", !8} -; CHECK-DAG: [[TAG_X_i]] = !{[[TYPE_X:!.*]], [[TYPE_int:!.*]], i64 0} -; CHECK-DAG: [[TYPE_X:!.*]] = !{!"struct X", [[TYPE_int]], i64 0} -; CHECK-DAG: [[TYPE_int]] = !{!"int", {{!.*}}, i64 0} !15 = !{!16, !17, i64 0} ; TAG_X_i !16 = !{!"struct X", !17, i64 0} ; struct X { int i; }; !17 = !{!"int", !18, i64 0} @@ -146,3 +164,16 @@ declare i32 @foo(ptr) readonly ; A TBAA structure who's only point is to have a constant location. !9 = !{!"yet another root"} !10 = !{!"node", !9, i64 1} +;. +; CHECK: [[TBAA0]] = !{[[META1:![0-9]+]], [[META1]], i64 0} +; CHECK: [[META1]] = !{!"C", [[META2:![0-9]+]]} +; CHECK: [[META2]] = !{!"A", [[META3:![0-9]+]]} +; CHECK: [[META3]] = !{!"tbaa root"} +; CHECK: [[TBAA4]] = !{[[META5:![0-9]+]], [[META5]], i64 0} +; CHECK: [[META5]] = !{!"B", [[META2]]} +; CHECK: [[TBAA6]] = !{[[META2]], [[META2]], i64 0} +; CHECK: [[TBAA7]] = !{[[META8:![0-9]+]], [[META9:![0-9]+]], i64 0} +; CHECK: [[META8]] = !{!"struct X", [[META9]], i64 0} +; CHECK: [[META9]] = !{!"int", [[META10:![0-9]+]], i64 0} +; CHECK: [[META10]] = !{!"char", [[META3]], i64 0} +;. diff --git a/llvm/test/Transforms/NewGVN/unreachable_block_infinite_loop.ll b/llvm/test/Transforms/NewGVN/unreachable_block_infinite_loop.ll index 7fbf50680a32e9811f796f15714eb67c76f3d61a..70e5e1a138da7e61421309fd4cce6823291be9c9 100644 --- a/llvm/test/Transforms/NewGVN/unreachable_block_infinite_loop.ll +++ b/llvm/test/Transforms/NewGVN/unreachable_block_infinite_loop.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -disable-output < %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" @@ -5,11 +6,11 @@ target triple = "x86_64-apple-darwin10.0" define i32 @test2() nounwind ssp { entry: - ret i32 0 + ret i32 0 unreachable_block: - %a = add i32 %a, 1 - ret i32 %a + %a = add i32 %a, 1 + ret i32 %a } define i32 @pr23096_test0() { diff --git a/llvm/test/Transforms/NewGVN/verify-memoryphi.ll b/llvm/test/Transforms/NewGVN/verify-memoryphi.ll index b863d23cffdc3f171da4ebaa923eecee47373e0d..2a1fcf35157f466351cbaf4402585c16f31da2be 100644 --- a/llvm/test/Transforms/NewGVN/verify-memoryphi.ll +++ b/llvm/test/Transforms/NewGVN/verify-memoryphi.ll @@ -1,21 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; Skip dead MemoryPhis when performing memory congruency verification ; in NewGVN. ; RUN: opt -S -passes=newgvn %s | FileCheck %s ; REQUIRES: asserts -; CHECK: define void @tinkywinky() { -; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 false, label %body, label %end -; CHECK: body: -; CHECK-NEXT: store i8 poison, ptr null -; CHECK-NEXT: br label %end -; CHECK: end: -; CHECK-NEXT: ret void -; CHECK-NEXT: } declare void @llvm.lifetime.start.p0(i64, ptr nocapture) define void @tinkywinky() { +; CHECK-LABEL: define void @tinkywinky() { +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 false, label [[BODY:%.*]], label [[END:%.*]] +; CHECK: body: +; CHECK-NEXT: store i8 poison, ptr null, align 1 +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: ret void +; entry: call void @llvm.lifetime.start.p0(i64 4, ptr undef) br i1 false, label %body, label %end diff --git a/llvm/test/Transforms/NewGVN/volatile-nonvolatile.ll b/llvm/test/Transforms/NewGVN/volatile-nonvolatile.ll index 2febea7e948196c38477688cdd6a28bd47b4b87c..d6daff99591f9a204d6601f74d1803176eb1c333 100644 --- a/llvm/test/Transforms/NewGVN/volatile-nonvolatile.ll +++ b/llvm/test/Transforms/NewGVN/volatile-nonvolatile.ll @@ -1,13 +1,19 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 ; RUN: opt -passes=newgvn -S < %s | FileCheck %s %struct.t = type { ptr } ; The loaded address and the location of the address itself are not aliased, ; so the second reload is not necessary. Check that it can be eliminated. -; CHECK-LABEL: test1 -; CHECK: load -; CHECK-NOT: load define void @test1(ptr nocapture readonly %p, i32 %v) #0 { +; CHECK-LABEL: define void @test1( +; CHECK-SAME: ptr nocapture readonly [[P:%.*]], i32 [[V:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 4, !tbaa [[TBAA0:![0-9]+]] +; CHECK-NEXT: store volatile i32 [[V]], ptr [[TMP0]], align 4, !tbaa [[TBAA5:![0-9]+]] +; CHECK-NEXT: store volatile i32 [[V]], ptr [[TMP0]], align 4, !tbaa [[TBAA5]] +; CHECK-NEXT: ret void +; entry: %0 = load ptr, ptr %p, align 4, !tbaa !1 store volatile i32 %v, ptr %0, align 4, !tbaa !6 @@ -18,11 +24,16 @@ entry: ; The store via the loaded address may overwrite the address itself. ; Make sure that both loads remain. -; CHECK-LABEL: test2 -; CHECK: load -; CHECK: store -; CHECK: load define void @test2(ptr nocapture readonly %p, i32 %v) #0 { +; CHECK-LABEL: define void @test2( +; CHECK-SAME: ptr nocapture readonly [[P:%.*]], i32 [[V:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[P]], align 4, !tbaa [[TBAA0]] +; CHECK-NEXT: store volatile i32 [[V]], ptr [[TMP0]], align 4, !tbaa [[TBAA0]] +; CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[P]], align 4, !tbaa [[TBAA0]] +; CHECK-NEXT: store volatile i32 [[V]], ptr [[TMP1]], align 4, !tbaa [[TBAA0]] +; CHECK-NEXT: ret void +; entry: %0 = load ptr, ptr %p, align 4, !tbaa !1 store volatile i32 %v, ptr %0, align 4, !tbaa !1 @@ -33,11 +44,16 @@ entry: ; The loads are ordered and non-monotonic. Although they are not aliased to ; the stores, make sure both are preserved. -; CHECK-LABEL: test3 -; CHECK: load -; CHECK: store -; CHECK: load define void @test3(ptr nocapture readonly %p, i32 %v) #0 { +; CHECK-LABEL: define void @test3( +; CHECK-SAME: ptr nocapture readonly [[P:%.*]], i32 [[V:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load atomic ptr, ptr [[P]] acquire, align 4, !tbaa [[TBAA0]] +; CHECK-NEXT: store volatile i32 [[V]], ptr [[TMP0]], align 4, !tbaa [[TBAA5]] +; CHECK-NEXT: [[TMP1:%.*]] = load atomic ptr, ptr [[P]] acquire, align 4, !tbaa [[TBAA0]] +; CHECK-NEXT: store volatile i32 [[V]], ptr [[TMP1]], align 4, !tbaa [[TBAA5]] +; CHECK-NEXT: ret void +; entry: %0 = load atomic ptr, ptr %p acquire, align 4, !tbaa !1 store volatile i32 %v, ptr %0, align 4, !tbaa !6 @@ -56,3 +72,12 @@ attributes #0 = { norecurse nounwind } !6 = !{!7, !7, i64 0} !7 = !{!"int", !4, i64 0} +;. +; CHECK: [[TBAA0]] = !{[[META1:![0-9]+]], [[META2:![0-9]+]], i64 0} +; CHECK: [[META1]] = !{!"", [[META2]], i64 0} +; CHECK: [[META2]] = !{!"any pointer", [[META3:![0-9]+]], i64 0} +; CHECK: [[META3]] = !{!"omnipotent char", [[META4:![0-9]+]], i64 0} +; CHECK: [[META4]] = !{!"Simple C/C++ TBAA"} +; CHECK: [[TBAA5]] = !{[[META6:![0-9]+]], [[META6]], i64 0} +; CHECK: [[META6]] = !{!"int", [[META3]], i64 0} +;. diff --git a/llvm/test/Transforms/PGOProfile/memop_profile_funclet_wasm.ll b/llvm/test/Transforms/PGOProfile/memop_profile_funclet_wasm.ll new file mode 100644 index 0000000000000000000000000000000000000000..f8dcb768c94cabee57b4e6797cdb1fc97486a11f --- /dev/null +++ b/llvm/test/Transforms/PGOProfile/memop_profile_funclet_wasm.ll @@ -0,0 +1,48 @@ +; RUN: opt < %s -passes=pgo-instr-gen -S | FileCheck %s --check-prefixes=CHECK,GEN +; RUN: opt < %s -passes=pgo-instr-gen,instrprof -S | FileCheck %s --check-prefixes=CHECK,LOWER + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +define void @wasm_funclet_op_bundle(ptr %p, ptr %dst, ptr %src) personality ptr @__gxx_wasm_personality_v0 { +entry: + invoke void @foo() + to label %try.cont unwind label %catch.dispatch + +catch.dispatch: ; preds = %entry + %0 = catchswitch within none [label %catch.start] unwind to caller + +catch.start: ; preds = %catch.dispatch + %1 = catchpad within %0 [ptr null] +; CHECK: %[[CATCHPAD:.*]] = catchpad + %2 = call ptr @llvm.wasm.get.exception(token %1) + %3 = call i32 @llvm.wasm.get.ehselector(token %1) + %4 = call ptr @__cxa_begin_catch(ptr %2) #3 [ "funclet"(token %1) ] + %tmp = load i32, ptr %p, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr %dst, ptr %src, i32 %tmp, i1 false) +; GEN: call void @llvm.instrprof.value.profile({{.*}}) [ "funclet"(token %[[CATCHPAD]]) ] +; LOWER: call void @__llvm_profile_instrument_memop({{.*}}) [ "funclet"(token %[[CATCHPAD]]) ] + call void @__cxa_end_catch() [ "funclet"(token %1) ] + catchret from %1 to label %try.cont + +try.cont: ; preds = %catch.start, %entry + ret void +} + +declare void @foo() +declare i32 @__gxx_wasm_personality_v0(...) +; Function Attrs: nocallback nofree nosync nounwind willreturn +declare ptr @llvm.wasm.get.exception(token) #0 +; Function Attrs: nocallback nofree nosync nounwind willreturn +declare i32 @llvm.wasm.get.ehselector(token) #0 +; Function Attrs: nounwind memory(none) +declare i32 @llvm.eh.typeid.for(ptr) #1 +declare ptr @__cxa_begin_catch(ptr) +declare void @__cxa_end_catch() +; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite) +declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) #2 + +attributes #0 = { nocallback nofree nosync nounwind willreturn } +attributes #1 = { nounwind memory(none) } +attributes #2 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } +attributes #3 = { nounwind } diff --git a/llvm/test/Transforms/PGOProfile/vtable_prof_unsupported.ll b/llvm/test/Transforms/PGOProfile/vtable_prof_unsupported.ll new file mode 100644 index 0000000000000000000000000000000000000000..f72a20fdc71a6e87bf391e87e8e30678c5044f4f --- /dev/null +++ b/llvm/test/Transforms/PGOProfile/vtable_prof_unsupported.ll @@ -0,0 +1,34 @@ +; RUN: opt < %s -passes=pgo-instr-gen -enable-vtable-value-profiling -S 2>&1 | FileCheck %s + +; Test that unsupported warning is emitted for non-ELF object files. +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" +target triple = "arm64-apple-macosx14.0.0" + +; CHECK: warning: {{.*}} VTable value profiling is presently not supported for non-ELF object formats + +@_ZTV4Base = constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @_ZN4Base4funcEi] }, !type !0, !type !1 +@_ZTV7Derived = constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @_ZN7Derived4funcEi] }, !type !0, !type !1, !type !2, !type !3 + +@llvm.compiler.used = appending global [2 x ptr] [ptr @_ZTV4Base, ptr @_ZTV7Derived], section "llvm.metadata" + +define i32 @_Z4funci(i32 %a) { +entry: + %call = call ptr @_Z10createTypev() + %vtable = load ptr, ptr %call + %0 = call i1 @llvm.public.type.test(ptr %vtable, metadata !"_ZTS7Derived") + call void @llvm.assume(i1 %0) + %1 = load ptr, ptr %vtable + %call1 = call i32 %1(ptr %call, i32 %a) + ret i32 %call1 +} + +declare ptr @_Z10createTypev() +declare i1 @llvm.public.type.test(ptr, metadata) +declare void @llvm.assume(i1) +declare i32 @_ZN4Base4funcEi(ptr, i32) +declare i32 @_ZN7Derived4funcEi(ptr , i32) + +!0 = !{i64 16, !"_ZTS4Base"} +!1 = !{i64 16, !"_ZTSM4BaseFiiE.virtual"} +!2 = !{i64 16, !"_ZTS7Derived"} +!3 = !{i64 16, !"_ZTSM7DerivedFiiE.virtual"} diff --git a/llvm/test/Transforms/PGOProfile/vtable_profile.ll b/llvm/test/Transforms/PGOProfile/vtable_profile.ll new file mode 100644 index 0000000000000000000000000000000000000000..a8440031e1493d72c440e4083c3f646fcc2fddaf --- /dev/null +++ b/llvm/test/Transforms/PGOProfile/vtable_profile.ll @@ -0,0 +1,98 @@ +; RUN: opt < %s -passes=pgo-instr-gen -enable-vtable-value-profiling -S 2>&1 | FileCheck %s --check-prefix=GEN --implicit-check-not="VTable value profiling is presently not supported" +; RUN: opt < %s -passes=pgo-instr-gen,instrprof -enable-vtable-value-profiling -S 2>&1 | FileCheck %s --check-prefix=LOWER --implicit-check-not="VTable value profiling is presently not supported" + +; __llvm_prf_vnm stores zlib-compressed vtable names. +; REQUIRES: zlib + +source_filename = "vtable_local.ll" +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; The test IR is generated based on the following C++ program. +; Base1 has external linkage and Base2 has local linkage. +; class Derived uses multiple inheritance so its virtual table +; global variable contains two vtables. func1 is loaded from +; the vtable compatible with class Base1, and func2 is loaded +; from the vtable compatible with class Base2. + +; class Base1 { +; public: +; virtual int func1(int a) ; +; }; +; +; namespace { +; class Base2 { +; public: +; __attribute__((noinline)) virtual int func2(int a) { +; return a; +; } +; }; +; } + +; class Derived : public Base1, public Base2 { +; public: +; Derived(int c) : v(c) {} +; private: +; int v; +; }; +; +; Derived* createType(); + +; int func(int a) { +; Derived* d = createType(); +; return d->func2(a) + d->func1(a); +; } + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@_ZTV7Derived = constant { [3 x ptr], [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @_ZN5Base15func1Ei], [3 x ptr] [ptr inttoptr (i64 -8 to ptr), ptr null, ptr @_ZN12_GLOBAL__N_15Base25func2Ei] }, !type !0, !type !3, !type !6, !type !8, !type !10 +@_ZTV5Base1 = available_externally constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @_ZN5Base15func1Ei] }, !type !0 +@_ZTVN12_GLOBAL__N_15Base2E = internal constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @_ZN12_GLOBAL__N_15Base25func2Ei] }, !type !11, !type !8; !vcall_visibility !12 +@llvm.compiler.used = appending global [1 x ptr] [ptr @_ZTV5Base1], section "llvm.metadata" + +; GEN: __llvm_profile_raw_version = comdat any +; GEN: __llvm_profile_raw_version = hidden constant i64 72057594037927946, comdat +; GEN: __profn__Z4funci = private constant [8 x i8] c"_Z4funci" + +; LOWER: $__profvt__ZTV7Derived = comdat nodeduplicate +; LOWER: $"__profvt_vtable_local.ll;_ZTVN12_GLOBAL__N_15Base2E" = comdat nodeduplicate +; LOWER: @__profvt__ZTV7Derived = global { i64, ptr, i32 } { i64 -4576307468236080025, ptr @_ZTV7Derived, i32 48 }, section "__llvm_prf_vtab", comdat, align 8 +; LOWER: @"__profvt_vtable_local.ll;_ZTVN12_GLOBAL__N_15Base2E" = internal global { i64, ptr, i32 } { i64 1419990121885302679, ptr @_ZTVN12_GLOBAL__N_15Base2E, i32 24 }, section "__llvm_prf_vtab", comdat, align 8 +; LOWER: @__llvm_prf_vnm = private constant [64 x i8] c"7>x\DA\8B\8F\0A\093wI-\CA,KMa,+IL\CAI\8D\CF\C9ON\CC\D1\CB\C9\B1\8E\07J\FA\19\1A\C5\BB\FB\F8;9\FA\C4\C7\FB\C5\1B\9A:%\16\A7\1A\B9\02\00\19:\12o", section "__llvm_prf_vns", align 1 +; LOWER: @llvm.used = appending global [5 x ptr] [ptr @__profvt__ZTV7Derived, ptr @"__profvt_vtable_local.ll;_ZTVN12_GLOBAL__N_15Base2E", ptr @__llvm_prf_vnodes, ptr @__llvm_prf_nm, ptr @__llvm_prf_vnm], section "llvm.metadata" + +define i32 @_Z4funci(i32 %a) { +entry: + %call = call ptr @_Z10createTypev() + %add.ptr = getelementptr inbounds i8, ptr %call, i64 8 + %vtable = load ptr, ptr %add.ptr +; GEN: [[P1:%[0-9]+]] = ptrtoint ptr %vtable to i64 +; GEN: call void @llvm.instrprof.value.profile(ptr @__profn__Z4funci, i64 [[CFGHash:[0-9]+]], i64 [[P1]], i32 2, i32 0) +; LOWER: [[P1:%[0-9]+]] = ptrtoint ptr %vtable to i64 +; LOWER: call void @__llvm_profile_instrument_target(i64 [[P1]], ptr @__profd__Z4funci, i32 2) + %vfunc1 = load ptr, ptr %vtable + %call1 = call i32 %vfunc1(ptr %add.ptr, i32 %a) + %vtable2 = load ptr, ptr %call +; GEN: [[P2:%[0-9]+]] = ptrtoint ptr %vtable2 to i64 +; GEN: call void @llvm.instrprof.value.profile(ptr @__profn__Z4funci, i64 [[CFGHash]], i64 [[P2]], i32 2, i32 1) +; LOWER: [[P2:%[0-9]+]] = ptrtoint ptr %vtable2 to i64 +; LOWER: call void @__llvm_profile_instrument_target(i64 [[P2]], ptr @__profd__Z4funci, i32 3) + %vfunc2 = load ptr, ptr %vtable2 + %call4 = call i32 %vfunc2(ptr %call, i32 %a) + %add = add nsw i32 %call1, %call4 + ret i32 %add +} + +declare ptr @_Z10createTypev() +declare i32 @_ZN12_GLOBAL__N_15Base25func2Ei(ptr %this, i32 %a) +declare i32 @_ZN5Base15func1Ei(ptr, i32) + +!0 = !{i64 16, !"_ZTS5Base1"} +!3 = !{i64 16, !"_ZTS7Derived"} +!6 = !{i64 40, !7} +!7 = distinct !{} +!8 = !{i64 16, !9} +!9 = distinct !{} +!10 = !{i64 40, !9} +!11 = !{i64 16, !7} diff --git a/llvm/test/Transforms/PhaseOrdering/AArch64/hoisting-sinking-required-for-vectorization.ll b/llvm/test/Transforms/PhaseOrdering/AArch64/hoisting-sinking-required-for-vectorization.ll index 33cfd0aa8574e01912eb684ba95ab0087147de03..ad100c399c08ed9b5df8bc7446bc0a667f09328e 100644 --- a/llvm/test/Transforms/PhaseOrdering/AArch64/hoisting-sinking-required-for-vectorization.ll +++ b/llvm/test/Transforms/PhaseOrdering/AArch64/hoisting-sinking-required-for-vectorization.ll @@ -164,10 +164,10 @@ define void @loop2(ptr %A, ptr %B, ptr %C, float %x) { ; CHECK-NEXT: [[TMP9:%.*]] = getelementptr i8, ptr [[TMP8]], i64 16 ; CHECK-NEXT: [[WIDE_LOAD10:%.*]] = load <4 x float>, ptr [[TMP8]], align 4, !alias.scope [[META9:![0-9]+]], !noalias [[META11:![0-9]+]] ; CHECK-NEXT: [[WIDE_LOAD11:%.*]] = load <4 x float>, ptr [[TMP9]], align 4, !alias.scope [[META9]], !noalias [[META11]] -; CHECK-NEXT: [[TMP10:%.*]] = select <4 x i1> [[TMP2]], <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, <4 x float> [[WIDE_LOAD10]] -; CHECK-NEXT: [[PREDPHI:%.*]] = fadd <4 x float> [[TMP6]], [[TMP10]] -; CHECK-NEXT: [[TMP11:%.*]] = select <4 x i1> [[TMP3]], <4 x float> <float -0.000000e+00, float -0.000000e+00, float -0.000000e+00, float -0.000000e+00>, <4 x float> [[WIDE_LOAD11]] -; CHECK-NEXT: [[PREDPHI12:%.*]] = fadd <4 x float> [[TMP7]], [[TMP11]] +; CHECK-NEXT: [[TMP10:%.*]] = fadd <4 x float> [[TMP6]], [[WIDE_LOAD10]] +; CHECK-NEXT: [[TMP11:%.*]] = fadd <4 x float> [[TMP7]], [[WIDE_LOAD11]] +; CHECK-NEXT: [[PREDPHI:%.*]] = select <4 x i1> [[TMP2]], <4 x float> [[TMP6]], <4 x float> [[TMP10]] +; CHECK-NEXT: [[PREDPHI12:%.*]] = select <4 x i1> [[TMP3]], <4 x float> [[TMP7]], <4 x float> [[TMP11]] ; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i8, ptr [[TMP8]], i64 16 ; CHECK-NEXT: store <4 x float> [[PREDPHI]], ptr [[TMP8]], align 4, !alias.scope [[META9]], !noalias [[META11]] ; CHECK-NEXT: store <4 x float> [[PREDPHI12]], ptr [[TMP12]], align 4, !alias.scope [[META9]], !noalias [[META11]] diff --git a/llvm/test/Transforms/PhaseOrdering/ARM/arm_mult_q15.ll b/llvm/test/Transforms/PhaseOrdering/ARM/arm_mult_q15.ll index 73bcee5fb74f0c63992038944c8445ddb99f4a77..36bcda4c43ca9b6691bf7921c5c5883cc3f38d9e 100644 --- a/llvm/test/Transforms/PhaseOrdering/ARM/arm_mult_q15.ll +++ b/llvm/test/Transforms/PhaseOrdering/ARM/arm_mult_q15.ll @@ -49,7 +49,7 @@ define void @arm_mult_q15(ptr %pSrcA, ptr %pSrcB, ptr noalias %pDst, i32 %blockS ; CHECK: middle.block: ; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[N_VEC]], [[BLOCKSIZE]] ; CHECK-NEXT: br i1 [[CMP_N]], label [[WHILE_END]], label [[WHILE_BODY_PREHEADER16]] -; CHECK: while.body.preheader16: +; CHECK: while.body.preheader18: ; CHECK-NEXT: [[BLKCNT_06_PH:%.*]] = phi i32 [ [[BLOCKSIZE]], [[WHILE_BODY_PREHEADER]] ], [ [[IND_END]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: [[PSRCA_ADDR_05_PH:%.*]] = phi ptr [ [[PSRCA]], [[WHILE_BODY_PREHEADER]] ], [ [[IND_END7]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: [[PDST_ADDR_04_PH:%.*]] = phi ptr [ [[PDST]], [[WHILE_BODY_PREHEADER]] ], [ [[IND_END9]], [[MIDDLE_BLOCK]] ] diff --git a/llvm/test/Transforms/PhaseOrdering/X86/merge-functions.ll b/llvm/test/Transforms/PhaseOrdering/X86/merge-functions.ll index 8f1c52c591631fb415c64affab5439f56ef73e25..708cdc9ca45ec8d1ed53a41b8da17508702bfdfb 100644 --- a/llvm/test/Transforms/PhaseOrdering/X86/merge-functions.ll +++ b/llvm/test/Transforms/PhaseOrdering/X86/merge-functions.ll @@ -14,8 +14,7 @@ define i1 @test1(i32 %c) { ; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[SWITCH_TABLEIDX]], 20 ; CHECK-NEXT: [[SWITCH_CAST:%.*]] = trunc i32 [[SWITCH_TABLEIDX]] to i20 ; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i20 -490991, [[SWITCH_CAST]] -; CHECK-NEXT: [[TMP1:%.*]] = and i20 [[SWITCH_DOWNSHIFT]], 1 -; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = icmp ne i20 [[TMP1]], 0 +; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i20 [[SWITCH_DOWNSHIFT]] to i1 ; CHECK-NEXT: [[I_0:%.*]] = select i1 [[TMP0]], i1 [[SWITCH_MASKED]], i1 false ; CHECK-NEXT: ret i1 [[I_0]] ; diff --git a/llvm/test/Transforms/PhaseOrdering/X86/pr67803.ll b/llvm/test/Transforms/PhaseOrdering/X86/pr67803.ll index 211c90b5604e667e45ee0196f0d634703799c05c..495ec0a633999af5d00b8a9e289ccc0d6af163dc 100644 --- a/llvm/test/Transforms/PhaseOrdering/X86/pr67803.ll +++ b/llvm/test/Transforms/PhaseOrdering/X86/pr67803.ll @@ -11,16 +11,14 @@ define <4 x i64> @PR67803(<4 x i64> %x, <4 x i64> %y, <4 x i64> %a, <4 x i64> %b ; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt <8 x i32> [[TMP0]], [[TMP1]] ; CHECK-NEXT: [[CMP_I21:%.*]] = shufflevector <8 x i1> [[TMP2]], <8 x i1> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3> ; CHECK-NEXT: [[SEXT_I22:%.*]] = sext <4 x i1> [[CMP_I21]] to <4 x i32> -; CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x i32> [[SEXT_I22]] to <2 x i64> ; CHECK-NEXT: [[CMP_I:%.*]] = shufflevector <8 x i1> [[TMP2]], <8 x i1> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7> ; CHECK-NEXT: [[SEXT_I:%.*]] = sext <4 x i1> [[CMP_I]] to <4 x i32> -; CHECK-NEXT: [[TMP4:%.*]] = bitcast <4 x i32> [[SEXT_I]] to <2 x i64> -; CHECK-NEXT: [[SHUFFLE_I:%.*]] = shufflevector <2 x i64> [[TMP3]], <2 x i64> [[TMP4]], <4 x i32> <i32 0, i32 1, i32 2, i32 3> +; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <4 x i32> [[SEXT_I22]], <4 x i32> [[SEXT_I]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7> ; CHECK-NEXT: [[TMP5:%.*]] = bitcast <4 x i64> [[A:%.*]] to <32 x i8> ; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <32 x i8> [[TMP5]], <32 x i8> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> ; CHECK-NEXT: [[TMP7:%.*]] = bitcast <4 x i64> [[B:%.*]] to <32 x i8> ; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <32 x i8> [[TMP7]], <32 x i8> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> -; CHECK-NEXT: [[TMP9:%.*]] = bitcast <4 x i64> [[SHUFFLE_I]] to <32 x i8> +; CHECK-NEXT: [[TMP9:%.*]] = bitcast <8 x i32> [[TMP3]] to <32 x i8> ; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <32 x i8> [[TMP9]], <32 x i8> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> ; CHECK-NEXT: [[TMP11:%.*]] = tail call <16 x i8> @llvm.x86.sse41.pblendvb(<16 x i8> [[TMP6]], <16 x i8> [[TMP8]], <16 x i8> [[TMP10]]) ; CHECK-NEXT: [[TMP12:%.*]] = bitcast <16 x i8> [[TMP11]] to <2 x i64> @@ -28,7 +26,7 @@ define <4 x i64> @PR67803(<4 x i64> %x, <4 x i64> %y, <4 x i64> %a, <4 x i64> %b ; CHECK-NEXT: [[TMP14:%.*]] = shufflevector <32 x i8> [[TMP13]], <32 x i8> poison, <16 x i32> <i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31> ; CHECK-NEXT: [[TMP15:%.*]] = bitcast <4 x i64> [[B]] to <32 x i8> ; CHECK-NEXT: [[TMP16:%.*]] = shufflevector <32 x i8> [[TMP15]], <32 x i8> poison, <16 x i32> <i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31> -; CHECK-NEXT: [[TMP17:%.*]] = bitcast <4 x i64> [[SHUFFLE_I]] to <32 x i8> +; CHECK-NEXT: [[TMP17:%.*]] = bitcast <8 x i32> [[TMP3]] to <32 x i8> ; CHECK-NEXT: [[TMP18:%.*]] = shufflevector <32 x i8> [[TMP17]], <32 x i8> poison, <16 x i32> <i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31> ; CHECK-NEXT: [[TMP19:%.*]] = tail call <16 x i8> @llvm.x86.sse41.pblendvb(<16 x i8> [[TMP14]], <16 x i8> [[TMP16]], <16 x i8> [[TMP18]]) ; CHECK-NEXT: [[TMP20:%.*]] = bitcast <16 x i8> [[TMP19]] to <2 x i64> diff --git a/llvm/test/Transforms/Reassociate/vaarg_movable.ll b/llvm/test/Transforms/Reassociate/vaarg_movable.ll index 337877a54a9071f6c5a8334e3481e84166dea571..4e45b219fccd5965e20fb40037e12efeb03c0a75 100644 --- a/llvm/test/Transforms/Reassociate/vaarg_movable.ll +++ b/llvm/test/Transforms/Reassociate/vaarg_movable.ll @@ -10,13 +10,13 @@ define i32 @func(i32 %dummy, ...) { ; ; CHECK-LABEL: @func( ; CHECK-NEXT: [[VARARGS:%.*]] = alloca ptr, align 8 -; CHECK-NEXT: call void @llvm.va_start(ptr [[VARARGS]]) +; CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VARARGS]]) ; CHECK-NEXT: [[V0:%.*]] = va_arg ptr [[VARARGS]], i32 ; CHECK-NEXT: [[V1:%.*]] = va_arg ptr [[VARARGS]], i32 ; CHECK-NEXT: [[V0_NEG:%.*]] = sub i32 0, [[V0]] ; CHECK-NEXT: [[SUB:%.*]] = add i32 [[V0_NEG]], 1 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[SUB]], [[V1]] -; CHECK-NEXT: call void @llvm.va_end(ptr [[VARARGS]]) +; CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VARARGS]]) ; CHECK-NEXT: ret i32 [[ADD]] ; %varargs = alloca ptr, align 8 diff --git a/llvm/test/Transforms/SCCP/add-nuw-nsw-flags.ll b/llvm/test/Transforms/SCCP/add-nuw-nsw-flags.ll index b8f5d5dba0c4b225460d886bd8358d9b1d4692c1..05d9acd19196293c4df87921b8f3b3b1ee0d6c3c 100644 --- a/llvm/test/Transforms/SCCP/add-nuw-nsw-flags.ll +++ b/llvm/test/Transforms/SCCP/add-nuw-nsw-flags.ll @@ -240,3 +240,32 @@ then: else: ret i16 0 } + +define i1 @test_add_nuw_sub(i32 %a) { +; CHECK-LABEL: @test_add_nuw_sub( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[A:%.*]], 10000 +; CHECK-NEXT: [[SUB:%.*]] = add i32 [[ADD]], -5000 +; CHECK-NEXT: ret i1 false +; +entry: + %add = add nuw i32 %a, 10000 + %sub = add i32 %add, -5000 + %cond = icmp ult i32 %sub, 5000 + ret i1 %cond +} + +define i1 @test_add_nsw_sub(i32 %a) { +; CHECK-LABEL: @test_add_nsw_sub( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A:%.*]], 10000 +; CHECK-NEXT: [[SUB:%.*]] = add nsw i32 [[ADD]], -5000 +; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[SUB]], 5000 +; CHECK-NEXT: ret i1 [[COND]] +; +entry: + %add = add nsw i32 %a, 10000 + %sub = add i32 %add, -5000 + %cond = icmp ult i32 %sub, 5000 + ret i1 %cond +} diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/ext-trunc.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/ext-trunc.ll index cef791633655a871c570927d6f1da9485c831fc6..5e3fd156666f5f2e63b3d571dd0965e7ec54615e 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/ext-trunc.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/ext-trunc.ll @@ -17,12 +17,13 @@ define void @test1(<4 x i16> %a, <4 x i16> %b, ptr %p) { ; CHECK-NEXT: [[GEP0:%.*]] = getelementptr inbounds i64, ptr [[P:%.*]], i64 [[S0]] ; CHECK-NEXT: [[LOAD0:%.*]] = load i64, ptr [[GEP0]], align 4 ; CHECK-NEXT: [[TMP0:%.*]] = shufflevector <4 x i32> [[SUB0]], <4 x i32> poison, <2 x i32> <i32 1, i32 2> -; CHECK-NEXT: [[TMP1:%.*]] = sext <2 x i32> [[TMP0]] to <2 x i64> -; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x i64> [[TMP1]], i32 0 +; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x i32> [[TMP0]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i64 ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i64, ptr [[P]], i64 [[TMP2]] ; CHECK-NEXT: [[LOAD1:%.*]] = load i64, ptr [[GEP1]], align 4 -; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x i64> [[TMP1]], i32 1 -; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i64, ptr [[P]], i64 [[TMP3]] +; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x i32> [[TMP0]], i32 1 +; CHECK-NEXT: [[TMP4:%.*]] = sext i32 [[TMP3]] to i64 +; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i64, ptr [[P]], i64 [[TMP4]] ; CHECK-NEXT: [[LOAD2:%.*]] = load i64, ptr [[GEP2]], align 4 ; CHECK-NEXT: [[E3:%.*]] = extractelement <4 x i32> [[SUB0]], i32 3 ; CHECK-NEXT: [[S3:%.*]] = sext i32 [[E3]] to i64 diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/gather-buildvector-with-minbitwidth-user.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/gather-buildvector-with-minbitwidth-user.ll new file mode 100644 index 0000000000000000000000000000000000000000..6907724729759ff26b6a1bc0586edc89bf535e58 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/gather-buildvector-with-minbitwidth-user.ll @@ -0,0 +1,89 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s + +define void @h() { +; CHECK-LABEL: define void @h() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, ptr null, i64 16 +; CHECK-NEXT: [[TMP0:%.*]] = insertelement <8 x i32> <i32 undef, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>, i32 0, i32 0 +; CHECK-NEXT: [[TMP1:%.*]] = trunc <8 x i32> [[TMP0]] to <8 x i1> +; CHECK-NEXT: [[TMP2:%.*]] = or <8 x i1> zeroinitializer, [[TMP1]] +; CHECK-NEXT: [[TMP4:%.*]] = or <8 x i1> [[TMP2]], zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = zext <8 x i1> [[TMP4]] to <8 x i16> +; CHECK-NEXT: store <8 x i16> [[TMP3]], ptr [[ARRAYIDX2]], align 2 +; CHECK-NEXT: ret void +; +entry: + %conv9 = zext i16 0 to i32 + %arrayidx2 = getelementptr i8, ptr null, i64 16 + %conv310 = zext i16 0 to i32 + %add4 = or i32 %conv310, %conv9 + %sub = or i32 %conv9, %conv310 + %conv15 = sext i16 0 to i32 + %shr = ashr i32 0, 0 + %arrayidx18 = getelementptr i8, ptr null, i64 24 + %conv19 = sext i16 0 to i32 + %sub20 = or i32 %shr, %conv19 + %shr29 = ashr i32 0, 0 + %add30 = or i32 %shr29, %conv15 + %sub39 = or i32 %sub, %sub20 + %conv40 = trunc i32 %sub39 to i16 + store i16 %conv40, ptr %arrayidx2, align 2 + %sub44 = or i32 %add4, %add30 + %conv45 = trunc i32 %sub44 to i16 + store i16 %conv45, ptr %arrayidx18, align 2 + %arrayidx2.1 = getelementptr i8, ptr null, i64 18 + %conv3.112 = zext i16 0 to i32 + %add4.1 = or i32 %conv3.112, 0 + %sub.1 = or i32 0, %conv3.112 + %conv15.1 = sext i16 0 to i32 + %shr.1 = ashr i32 0, 0 + %arrayidx18.1 = getelementptr i8, ptr null, i64 26 + %conv19.1 = sext i16 0 to i32 + %sub20.1 = or i32 %shr.1, %conv19.1 + %shr29.1 = ashr i32 0, 0 + %add30.1 = or i32 %shr29.1, %conv15.1 + %sub39.1 = or i32 %sub.1, %sub20.1 + %conv40.1 = trunc i32 %sub39.1 to i16 + store i16 %conv40.1, ptr %arrayidx2.1, align 2 + %sub44.1 = or i32 %add4.1, %add30.1 + %conv45.1 = trunc i32 %sub44.1 to i16 + store i16 %conv45.1, ptr %arrayidx18.1, align 2 + %conv.213 = zext i16 0 to i32 + %arrayidx2.2 = getelementptr i8, ptr null, i64 20 + %conv3.214 = zext i16 0 to i32 + %add4.2 = or i32 0, %conv.213 + %sub.2 = or i32 0, %conv3.214 + %conv15.2 = sext i16 0 to i32 + %shr.2 = ashr i32 0, 0 + %arrayidx18.2 = getelementptr i8, ptr null, i64 28 + %conv19.2 = sext i16 0 to i32 + %sub20.2 = or i32 %shr.2, %conv19.2 + %shr29.2 = ashr i32 0, 0 + %add30.2 = or i32 %shr29.2, %conv15.2 + %sub39.2 = or i32 %sub.2, %sub20.2 + %conv40.2 = trunc i32 %sub39.2 to i16 + store i16 %conv40.2, ptr %arrayidx2.2, align 2 + %sub44.2 = or i32 %add4.2, %add30.2 + %conv45.2 = trunc i32 %sub44.2 to i16 + store i16 %conv45.2, ptr %arrayidx18.2, align 2 + %conv.315 = zext i16 0 to i32 + %arrayidx2.3 = getelementptr i8, ptr null, i64 22 + %conv3.316 = zext i16 0 to i32 + %add4.3 = or i32 0, %conv.315 + %sub.3 = or i32 0, %conv3.316 + %conv15.3 = sext i16 0 to i32 + %shr.3 = ashr i32 0, 0 + %arrayidx18.3 = getelementptr i8, ptr null, i64 30 + %conv19.3 = sext i16 0 to i32 + %sub20.3 = or i32 %shr.3, %conv19.3 + %shr29.3 = ashr i32 0, 0 + %add30.3 = or i32 %shr29.3, %conv15.3 + %sub39.3 = or i32 %sub.3, %sub20.3 + %conv40.3 = trunc i32 %sub39.3 to i16 + store i16 %conv40.3, ptr %arrayidx2.3, align 2 + %sub44.3 = or i32 %add4.3, %add30.3 + %conv45.3 = trunc i32 %sub44.3 to i16 + store i16 %conv45.3, ptr %arrayidx18.3, align 2 + ret void +} diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/gather-with-minbith-user.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/gather-with-minbith-user.ll new file mode 100644 index 0000000000000000000000000000000000000000..d51ef0bce3a4e06133b832f974b470ee88f07596 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/gather-with-minbith-user.ll @@ -0,0 +1,90 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s + +define void @h() { +; CHECK-LABEL: define void @h() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, ptr null, i64 16 +; CHECK-NEXT: [[TMP0:%.*]] = trunc <8 x i32> zeroinitializer to <8 x i1> +; CHECK-NEXT: [[TMP1:%.*]] = sub <8 x i1> [[TMP0]], zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = add <8 x i1> [[TMP0]], zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <8 x i1> [[TMP1]], <8 x i1> [[TMP2]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 12, i32 13, i32 14, i32 15> +; CHECK-NEXT: [[TMP5:%.*]] = or <8 x i1> [[TMP3]], zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = zext <8 x i1> [[TMP5]] to <8 x i16> +; CHECK-NEXT: store <8 x i16> [[TMP4]], ptr [[ARRAYIDX2]], align 2 +; CHECK-NEXT: ret void +; +entry: + %conv9 = zext i16 0 to i32 + %arrayidx2 = getelementptr i8, ptr null, i64 16 + %conv310 = zext i16 0 to i32 + %add4 = add i32 %conv310, %conv9 + %sub = sub i32 0, %conv310 + %conv15 = sext i16 0 to i32 + %shr = ashr i32 0, 0 + %arrayidx18 = getelementptr i8, ptr null, i64 24 + %conv19 = sext i16 0 to i32 + %sub20 = sub i32 %shr, %conv19 + %shr29 = ashr i32 0, 0 + %add30 = add i32 %shr29, %conv15 + %sub39 = or i32 %sub, %sub20 + %conv40 = trunc i32 %sub39 to i16 + store i16 %conv40, ptr %arrayidx2, align 2 + %sub44 = or i32 %add4, %add30 + %conv45 = trunc i32 %sub44 to i16 + store i16 %conv45, ptr %arrayidx18, align 2 + %arrayidx2.1 = getelementptr i8, ptr null, i64 18 + %conv3.112 = zext i16 0 to i32 + %add4.1 = add i32 %conv3.112, 0 + %sub.1 = sub i32 0, %conv3.112 + %conv15.1 = sext i16 0 to i32 + %shr.1 = ashr i32 0, 0 + %arrayidx18.1 = getelementptr i8, ptr null, i64 26 + %conv19.1 = sext i16 0 to i32 + %sub20.1 = sub i32 %shr.1, %conv19.1 + %shr29.1 = ashr i32 0, 0 + %add30.1 = add i32 %shr29.1, %conv15.1 + %sub39.1 = or i32 %sub.1, %sub20.1 + %conv40.1 = trunc i32 %sub39.1 to i16 + store i16 %conv40.1, ptr %arrayidx2.1, align 2 + %sub44.1 = or i32 %add4.1, %add30.1 + %conv45.1 = trunc i32 %sub44.1 to i16 + store i16 %conv45.1, ptr %arrayidx18.1, align 2 + %conv.213 = zext i16 0 to i32 + %arrayidx2.2 = getelementptr i8, ptr null, i64 20 + %conv3.214 = zext i16 0 to i32 + %add4.2 = add i32 0, %conv.213 + %sub.2 = sub i32 0, %conv3.214 + %conv15.2 = sext i16 0 to i32 + %shr.2 = ashr i32 0, 0 + %arrayidx18.2 = getelementptr i8, ptr null, i64 28 + %conv19.2 = sext i16 0 to i32 + %sub20.2 = sub i32 %shr.2, %conv19.2 + %shr29.2 = ashr i32 0, 0 + %add30.2 = add i32 %shr29.2, %conv15.2 + %sub39.2 = or i32 %sub.2, %sub20.2 + %conv40.2 = trunc i32 %sub39.2 to i16 + store i16 %conv40.2, ptr %arrayidx2.2, align 2 + %sub44.2 = or i32 %add4.2, %add30.2 + %conv45.2 = trunc i32 %sub44.2 to i16 + store i16 %conv45.2, ptr %arrayidx18.2, align 2 + %conv.315 = zext i16 0 to i32 + %arrayidx2.3 = getelementptr i8, ptr null, i64 22 + %conv3.316 = zext i16 0 to i32 + %add4.3 = add i32 0, %conv.315 + %sub.3 = sub i32 0, %conv3.316 + %conv15.3 = sext i16 0 to i32 + %shr.3 = ashr i32 0, 0 + %arrayidx18.3 = getelementptr i8, ptr null, i64 30 + %conv19.3 = sext i16 0 to i32 + %sub20.3 = sub i32 %shr.3, %conv19.3 + %shr29.3 = ashr i32 0, 0 + %add30.3 = add i32 %shr29.3, %conv15.3 + %sub39.3 = or i32 %sub.3, %sub20.3 + %conv40.3 = trunc i32 %sub39.3 to i16 + store i16 %conv40.3, ptr %arrayidx2.3, align 2 + %sub44.3 = or i32 %add4.3, %add30.3 + %conv45.3 = trunc i32 %sub44.3 to i16 + store i16 %conv45.3, ptr %arrayidx18.3, align 2 + ret void +} diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/getelementptr2.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/getelementptr2.ll index 47485e514ec2fc43e482a4cec4008dd74515c010..1cce52060c479f7d0b4a111cc1377c90211c5e98 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/getelementptr2.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/getelementptr2.ll @@ -1,8 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ;test_i16_extend NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -mtriple=aarch64--linux-gnu -passes=slp-vectorizer,dce,instcombine -slp-threshold=-7 -pass-remarks-output=%t < %s | FileCheck %s +; RUN: opt -S -mtriple=aarch64--linux-gnu -passes=slp-vectorizer,dce,instcombine -slp-threshold=-5 -pass-remarks-output=%t < %s | FileCheck %s ; RUN: cat %t | FileCheck -check-prefix=YAML %s -; RUN: opt -S -mtriple=aarch64--linux-gnu -passes='slp-vectorizer,dce,instcombine' -slp-threshold=-7 -pass-remarks-output=%t < %s | FileCheck %s +; RUN: opt -S -mtriple=aarch64--linux-gnu -passes='slp-vectorizer,dce,instcombine' -slp-threshold=-5 -pass-remarks-output=%t < %s | FileCheck %s ; RUN: cat %t | FileCheck -check-prefix=YAML %s diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/horizontal.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/horizontal.ll index 1986b51ec9482835f019a6175876166be0c7f875..7c5f9847db1f4196cedd2edd6e446f959d2a2819 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/horizontal.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/horizontal.ll @@ -228,7 +228,7 @@ for.end: ; preds = %for.end.loopexit, % ; YAML-NEXT: Function: test_unrolled_select ; YAML-NEXT: Args: ; YAML-NEXT: - String: 'Vectorized horizontal reduction with cost ' -; YAML-NEXT: - Cost: '-36' +; YAML-NEXT: - Cost: '-41' ; YAML-NEXT: - String: ' and with tree size ' ; YAML-NEXT: - TreeSize: '10' @@ -246,15 +246,17 @@ define i32 @test_unrolled_select(ptr noalias nocapture readonly %blk1, ptr noali ; CHECK-NEXT: [[P2_045:%.*]] = phi ptr [ [[BLK2:%.*]], [[FOR_BODY_LR_PH]] ], [ [[ADD_PTR88:%.*]], [[IF_END_86]] ] ; CHECK-NEXT: [[P1_044:%.*]] = phi ptr [ [[BLK1:%.*]], [[FOR_BODY_LR_PH]] ], [ [[ADD_PTR:%.*]], [[IF_END_86]] ] ; CHECK-NEXT: [[TMP0:%.*]] = load <8 x i8>, ptr [[P1_044]], align 1 -; CHECK-NEXT: [[TMP1:%.*]] = zext <8 x i8> [[TMP0]] to <8 x i32> +; CHECK-NEXT: [[TMP1:%.*]] = zext <8 x i8> [[TMP0]] to <8 x i16> ; CHECK-NEXT: [[TMP2:%.*]] = load <8 x i8>, ptr [[P2_045]], align 1 -; CHECK-NEXT: [[TMP3:%.*]] = zext <8 x i8> [[TMP2]] to <8 x i32> -; CHECK-NEXT: [[TMP4:%.*]] = sub nsw <8 x i32> [[TMP1]], [[TMP3]] -; CHECK-NEXT: [[TMP5:%.*]] = icmp slt <8 x i32> [[TMP4]], zeroinitializer -; CHECK-NEXT: [[TMP6:%.*]] = sub nsw <8 x i32> zeroinitializer, [[TMP4]] -; CHECK-NEXT: [[TMP7:%.*]] = select <8 x i1> [[TMP5]], <8 x i32> [[TMP6]], <8 x i32> [[TMP4]] -; CHECK-NEXT: [[TMP8:%.*]] = call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> [[TMP7]]) -; CHECK-NEXT: [[OP_RDX]] = add i32 [[TMP8]], [[S_047]] +; CHECK-NEXT: [[TMP3:%.*]] = zext <8 x i8> [[TMP2]] to <8 x i16> +; CHECK-NEXT: [[TMP4:%.*]] = sub <8 x i16> [[TMP1]], [[TMP3]] +; CHECK-NEXT: [[TMP5:%.*]] = sext <8 x i16> [[TMP4]] to <8 x i32> +; CHECK-NEXT: [[TMP6:%.*]] = icmp slt <8 x i32> [[TMP5]], zeroinitializer +; CHECK-NEXT: [[TMP7:%.*]] = sub <8 x i16> zeroinitializer, [[TMP4]] +; CHECK-NEXT: [[TMP8:%.*]] = select <8 x i1> [[TMP6]], <8 x i16> [[TMP7]], <8 x i16> [[TMP4]] +; CHECK-NEXT: [[TMP9:%.*]] = sext <8 x i16> [[TMP8]] to <8 x i32> +; CHECK-NEXT: [[TMP10:%.*]] = call i32 @llvm.vector.reduce.add.v8i32(<8 x i32> [[TMP9]]) +; CHECK-NEXT: [[OP_RDX]] = add i32 [[TMP10]], [[S_047]] ; CHECK-NEXT: [[CMP83:%.*]] = icmp slt i32 [[OP_RDX]], [[LIM:%.*]] ; CHECK-NEXT: br i1 [[CMP83]], label [[IF_END_86]], label [[FOR_END_LOOPEXIT:%.*]] ; CHECK: if.end.86: diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/reduce-add-i64.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/reduce-add-i64.ll index d67fdc1cd6aa0e354dccd60a3156e925d9d45008..a7a7f642ced538d2ea27c317872947e8d44b395b 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/reduce-add-i64.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/reduce-add-i64.ll @@ -28,21 +28,11 @@ entry: define i64 @red_zext_ld_4xi64(ptr %ptr) { ; CHECK-LABEL: @red_zext_ld_4xi64( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[LD0:%.*]] = load i8, ptr [[PTR:%.*]], align 1 -; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[LD0]] to i64 -; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 1 -; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[GEP]], align 1 -; CHECK-NEXT: [[ZEXT_1:%.*]] = zext i8 [[LD1]] to i64 -; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i64 [[ZEXT]], [[ZEXT_1]] -; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 2 -; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[GEP_1]], align 1 -; CHECK-NEXT: [[ZEXT_2:%.*]] = zext i8 [[LD2]] to i64 -; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i64 [[ADD_1]], [[ZEXT_2]] -; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 3 -; CHECK-NEXT: [[LD3:%.*]] = load i8, ptr [[GEP_2]], align 1 -; CHECK-NEXT: [[ZEXT_3:%.*]] = zext i8 [[LD3]] to i64 -; CHECK-NEXT: [[ADD_3:%.*]] = add nuw nsw i64 [[ADD_2]], [[ZEXT_3]] -; CHECK-NEXT: ret i64 [[ADD_3]] +; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i8>, ptr [[PTR:%.*]], align 1 +; CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i8> [[TMP0]] to <4 x i16> +; CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.vector.reduce.add.v4i16(<4 x i16> [[TMP1]]) +; CHECK-NEXT: [[TMP3:%.*]] = zext i16 [[TMP2]] to i64 +; CHECK-NEXT: ret i64 [[TMP3]] ; entry: %ld0 = load i8, ptr %ptr diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/slp-frem.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/slp-frem.ll new file mode 100644 index 0000000000000000000000000000000000000000..a38f4bdc4640e9ec6a9294364efa47ad709d2a6c --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/slp-frem.ll @@ -0,0 +1,55 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt < %s -S -mtriple=aarch64 -vector-library=ArmPL -passes=slp-vectorizer | FileCheck %s + +@a = common global ptr null, align 8 + +define void @frem_v2double() { +; CHECK-LABEL: define void @frem_v2double() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load <2 x double>, ptr @a, align 8 +; CHECK-NEXT: [[TMP1:%.*]] = load <2 x double>, ptr @a, align 8 +; CHECK-NEXT: [[TMP2:%.*]] = frem <2 x double> [[TMP0]], [[TMP1]] +; CHECK-NEXT: store <2 x double> [[TMP2]], ptr @a, align 8 +; CHECK-NEXT: ret void +; +entry: + %a0 = load double, ptr getelementptr inbounds (double, ptr @a, i64 0), align 8 + %a1 = load double, ptr getelementptr inbounds (double, ptr @a, i64 1), align 8 + %b0 = load double, ptr getelementptr inbounds (double, ptr @a, i64 0), align 8 + %b1 = load double, ptr getelementptr inbounds (double, ptr @a, i64 1), align 8 + %r0 = frem double %a0, %b0 + %r1 = frem double %a1, %b1 + store double %r0, ptr getelementptr inbounds (double, ptr @a, i64 0), align 8 + store double %r1, ptr getelementptr inbounds (double, ptr @a, i64 1), align 8 + ret void +} + +define void @frem_v4float() { +; CHECK-LABEL: define void @frem_v4float() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr @a, align 8 +; CHECK-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr @a, align 8 +; CHECK-NEXT: [[TMP2:%.*]] = frem <4 x float> [[TMP0]], [[TMP1]] +; CHECK-NEXT: store <4 x float> [[TMP2]], ptr @a, align 8 +; CHECK-NEXT: ret void +; +entry: + %a0 = load float, ptr getelementptr inbounds (float, ptr @a, i64 0), align 8 + %a1 = load float, ptr getelementptr inbounds (float, ptr @a, i64 1), align 8 + %a2 = load float, ptr getelementptr inbounds (float, ptr @a, i64 2), align 8 + %a3 = load float, ptr getelementptr inbounds (float, ptr @a, i64 3), align 8 + %b0 = load float, ptr getelementptr inbounds (float, ptr @a, i64 0), align 8 + %b1 = load float, ptr getelementptr inbounds (float, ptr @a, i64 1), align 8 + %b2 = load float, ptr getelementptr inbounds (float, ptr @a, i64 2), align 8 + %b3 = load float, ptr getelementptr inbounds (float, ptr @a, i64 3), align 8 + %r0 = frem float %a0, %b0 + %r1 = frem float %a1, %b1 + %r2 = frem float %a2, %b2 + %r3 = frem float %a3, %b3 + store float %r0, ptr getelementptr inbounds (float, ptr @a, i64 0), align 8 + store float %r1, ptr getelementptr inbounds (float, ptr @a, i64 1), align 8 + store float %r2, ptr getelementptr inbounds (float, ptr @a, i64 2), align 8 + store float %r3, ptr getelementptr inbounds (float, ptr @a, i64 3), align 8 + ret void +} + diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/user-node-not-in-bitwidths.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/user-node-not-in-bitwidths.ll new file mode 100644 index 0000000000000000000000000000000000000000..6404cf4a2cd1d6f46cb463719db1d91ed14b78d6 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/user-node-not-in-bitwidths.ll @@ -0,0 +1,83 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s + +define void @h() { +; CHECK-LABEL: define void @h() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, ptr null, i64 16 +; CHECK-NEXT: store <8 x i16> zeroinitializer, ptr [[ARRAYIDX2]], align 2 +; CHECK-NEXT: ret void +; +entry: + %arrayidx2 = getelementptr i8, ptr null, i64 16 + %conv310 = zext i16 0 to i32 + %add4 = or i32 %conv310, 0 + %sub = or i32 0, %conv310 + %conv15 = sext i16 0 to i32 + %shr = ashr i32 %conv15, 0 + %arrayidx18 = getelementptr i8, ptr null, i64 24 + %conv19 = sext i16 0 to i32 + %sub20 = or i32 %shr, 0 + %shr29 = ashr i32 %conv19, 0 + %add30 = or i32 %shr29, %conv15 + %sub39 = or i32 %sub, %sub20 + %conv40 = trunc i32 %sub39 to i16 + store i16 %conv40, ptr %arrayidx2, align 2 + %sub44 = or i32 %add4, %add30 + %conv45 = trunc i32 %sub44 to i16 + store i16 %conv45, ptr %arrayidx18, align 2 + %arrayidx2.1 = getelementptr i8, ptr null, i64 18 + %conv3.112 = zext i16 0 to i32 + %add4.1 = or i32 %conv3.112, 0 + %sub.1 = or i32 0, %conv3.112 + %conv15.1 = sext i16 0 to i32 + %shr.1 = ashr i32 %conv15.1, 0 + %arrayidx18.1 = getelementptr i8, ptr null, i64 26 + %conv19.1 = sext i16 0 to i32 + %sub20.1 = or i32 %shr.1, 0 + %shr29.1 = ashr i32 %conv19.1, 0 + %add30.1 = or i32 %shr29.1, 0 + %sub39.1 = or i32 %sub.1, %sub20.1 + %conv40.1 = trunc i32 %sub39.1 to i16 + store i16 %conv40.1, ptr %arrayidx2.1, align 2 + %sub44.1 = or i32 %add4.1, %add30.1 + %conv45.1 = trunc i32 %sub44.1 to i16 + store i16 %conv45.1, ptr %arrayidx18.1, align 2 + %conv.213 = zext i16 0 to i32 + %arrayidx2.2 = getelementptr i8, ptr null, i64 20 + %conv3.214 = zext i16 0 to i32 + %add4.2 = or i32 0, %conv.213 + %sub.2 = or i32 0, %conv3.214 + %conv15.2 = sext i16 0 to i32 + %shr.2 = ashr i32 %conv15.2, 0 + %arrayidx18.2 = getelementptr i8, ptr null, i64 28 + %conv19.2 = sext i16 0 to i32 + %sub20.2 = or i32 %shr.2, 0 + %shr29.2 = ashr i32 %conv19.2, 0 + %add30.2 = or i32 %shr29.2, 0 + %sub39.2 = or i32 %sub.2, %sub20.2 + %conv40.2 = trunc i32 %sub39.2 to i16 + store i16 %conv40.2, ptr %arrayidx2.2, align 2 + %sub44.2 = or i32 %add4.2, %add30.2 + %conv45.2 = trunc i32 %sub44.2 to i16 + store i16 %conv45.2, ptr %arrayidx18.2, align 2 + %conv.315 = zext i16 0 to i32 + %arrayidx2.3 = getelementptr i8, ptr null, i64 22 + %conv3.316 = zext i16 0 to i32 + %add4.3 = or i32 0, %conv.315 + %sub.3 = or i32 0, %conv3.316 + %conv15.3 = sext i16 0 to i32 + %shr.3 = ashr i32 %conv15.3, 0 + %arrayidx18.3 = getelementptr i8, ptr null, i64 30 + %conv19.3 = sext i16 0 to i32 + %sub20.3 = or i32 %shr.3, 0 + %shr29.3 = ashr i32 %conv19.3, 0 + %add30.3 = or i32 %shr29.3, 0 + %sub39.3 = or i32 %sub.3, %sub20.3 + %conv40.3 = trunc i32 %sub39.3 to i16 + store i16 %conv40.3, ptr %arrayidx2.3, align 2 + %sub44.3 = or i32 %add4.3, %add30.3 + %conv45.3 = trunc i32 %sub44.3 to i16 + store i16 %conv45.3, ptr %arrayidx18.3, align 2 + ret void +} diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/complex-loads.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/complex-loads.ll index ed73f7b134465aa48922945275bed7f053dc089a..d87bdfe2689916d000644bb4ac861131e290c57b 100644 --- a/llvm/test/Transforms/SLPVectorizer/RISCV/complex-loads.ll +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/complex-loads.ll @@ -6,7 +6,7 @@ define i32 @test(ptr %pix1, ptr %pix2, i64 %idx.ext, i64 %idx.ext63, ptr %add.pt ; CHECK-SAME: ptr [[PIX1:%.*]], ptr [[PIX2:%.*]], i64 [[IDX_EXT:%.*]], i64 [[IDX_EXT63:%.*]], ptr [[ADD_PTR:%.*]], ptr [[ADD_PTR64:%.*]]) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[PIX1]], align 1 -; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[TMP0]] to i32 +; CHECK-NEXT: [[CONV1:%.*]] = zext i8 [[TMP0]] to i32 ; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x ptr> poison, ptr [[PIX1]], i32 0 ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x ptr> [[TMP1]], <2 x ptr> poison, <2 x i32> zeroinitializer ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, <2 x ptr> [[TMP2]], <2 x i64> <i64 4, i64 6> @@ -37,10 +37,10 @@ define i32 @test(ptr %pix1, ptr %pix2, i64 %idx.ext, i64 %idx.ext63, ptr %add.pt ; CHECK-NEXT: [[ARRAYIDX3_2:%.*]] = getelementptr i8, ptr [[ADD_PTR_1]], i64 4 ; CHECK-NEXT: [[ARRAYIDX5_2:%.*]] = getelementptr i8, ptr [[ADD_PTR64_1]], i64 4 ; CHECK-NEXT: [[TMP15:%.*]] = load <2 x i8>, ptr [[ADD_PTR_1]], align 1 -; CHECK-NEXT: [[TMP16:%.*]] = zext <2 x i8> [[TMP15]] to <2 x i32> +; CHECK-NEXT: [[TMP101:%.*]] = zext <2 x i8> [[TMP15]] to <2 x i32> ; CHECK-NEXT: [[TMP17:%.*]] = load <2 x i8>, ptr [[ADD_PTR64_1]], align 1 ; CHECK-NEXT: [[TMP18:%.*]] = zext <2 x i8> [[TMP17]] to <2 x i32> -; CHECK-NEXT: [[TMP19:%.*]] = sub <2 x i32> [[TMP16]], [[TMP18]] +; CHECK-NEXT: [[TMP19:%.*]] = sub <2 x i32> [[TMP101]], [[TMP18]] ; CHECK-NEXT: [[TMP20:%.*]] = load <2 x i8>, ptr [[ARRAYIDX3_2]], align 1 ; CHECK-NEXT: [[TMP21:%.*]] = zext <2 x i8> [[TMP20]] to <2 x i32> ; CHECK-NEXT: [[TMP22:%.*]] = load <2 x i8>, ptr [[ARRAYIDX5_2]], align 1 @@ -70,9 +70,9 @@ define i32 @test(ptr %pix1, ptr %pix2, i64 %idx.ext, i64 %idx.ext63, ptr %add.pt ; CHECK-NEXT: [[SUB45_2:%.*]] = sub i32 [[TMP39]], [[TMP40]] ; CHECK-NEXT: [[TMP41:%.*]] = extractelement <2 x i32> [[TMP38]], i32 0 ; CHECK-NEXT: [[TMP42:%.*]] = extractelement <2 x i32> [[TMP38]], i32 1 -; CHECK-NEXT: [[ADD46_2:%.*]] = add i32 [[TMP42]], [[TMP41]] +; CHECK-NEXT: [[CONV:%.*]] = add i32 [[TMP42]], [[TMP41]] ; CHECK-NEXT: [[SUB47_2:%.*]] = sub i32 [[TMP41]], [[TMP42]] -; CHECK-NEXT: [[ADD48_2:%.*]] = add i32 [[ADD46_2]], [[ADD44_2]] +; CHECK-NEXT: [[ADD48_2:%.*]] = add i32 [[CONV]], [[ADD44_2]] ; CHECK-NEXT: [[TMP43:%.*]] = load i8, ptr null, align 1 ; CHECK-NEXT: [[ARRAYIDX20_3:%.*]] = getelementptr i8, ptr null, i64 2 ; CHECK-NEXT: [[ARRAYIDX22_3:%.*]] = getelementptr i8, ptr null, i64 2 @@ -104,32 +104,32 @@ define i32 @test(ptr %pix1, ptr %pix2, i64 %idx.ext, i64 %idx.ext63, ptr %add.pt ; CHECK-NEXT: [[TMP69:%.*]] = sub <2 x i32> [[TMP66]], [[TMP68]] ; CHECK-NEXT: [[TMP70:%.*]] = shl <2 x i32> [[TMP69]], <i32 16, i32 16> ; CHECK-NEXT: [[TMP71:%.*]] = add <2 x i32> [[TMP70]], [[TMP63]] -; CHECK-NEXT: [[TMP72:%.*]] = add <2 x i32> [[TMP71]], [[TMP58]] +; CHECK-NEXT: [[TMP16:%.*]] = add <2 x i32> [[TMP71]], [[TMP58]] ; CHECK-NEXT: [[TMP73:%.*]] = sub <2 x i32> [[TMP58]], [[TMP71]] -; CHECK-NEXT: [[TMP74:%.*]] = extractelement <2 x i32> [[TMP72]], i32 0 -; CHECK-NEXT: [[TMP75:%.*]] = extractelement <2 x i32> [[TMP72]], i32 1 +; CHECK-NEXT: [[TMP74:%.*]] = extractelement <2 x i32> [[TMP16]], i32 0 +; CHECK-NEXT: [[TMP75:%.*]] = extractelement <2 x i32> [[TMP16]], i32 1 ; CHECK-NEXT: [[ADD48_3:%.*]] = add i32 [[TMP74]], [[TMP75]] ; CHECK-NEXT: [[ADD94:%.*]] = add i32 [[ADD48_3]], [[ADD48_2]] ; CHECK-NEXT: [[SUB102:%.*]] = sub i32 [[ADD48_2]], [[ADD48_3]] -; CHECK-NEXT: [[TMP76:%.*]] = extractelement <2 x i32> [[TMP47]], i32 1 -; CHECK-NEXT: [[SHR_I:%.*]] = lshr i32 [[TMP76]], 15 -; CHECK-NEXT: [[AND_I:%.*]] = and i32 [[SHR_I]], 65537 -; CHECK-NEXT: [[MUL_I:%.*]] = mul i32 [[AND_I]], 65535 -; CHECK-NEXT: [[SHR_I49:%.*]] = lshr i32 [[ADD46_2]], 15 -; CHECK-NEXT: [[AND_I50:%.*]] = and i32 [[SHR_I49]], 65537 -; CHECK-NEXT: [[MUL_I51:%.*]] = mul i32 [[AND_I50]], 65535 -; CHECK-NEXT: [[TMP77:%.*]] = extractelement <2 x i32> [[TMP16]], i32 0 -; CHECK-NEXT: [[SHR_I49_1:%.*]] = lshr i32 [[TMP77]], 15 -; CHECK-NEXT: [[AND_I50_1:%.*]] = and i32 [[SHR_I49_1]], 65537 -; CHECK-NEXT: [[MUL_I51_1:%.*]] = mul i32 [[AND_I50_1]], 65535 -; CHECK-NEXT: [[SHR_I49_2:%.*]] = lshr i32 [[CONV_1]], 15 +; CHECK-NEXT: [[TMP79:%.*]] = extractelement <2 x i32> [[TMP47]], i32 1 +; CHECK-NEXT: [[SHR_I49_2:%.*]] = lshr i32 [[TMP79]], 15 ; CHECK-NEXT: [[AND_I50_2:%.*]] = and i32 [[SHR_I49_2]], 65537 ; CHECK-NEXT: [[MUL_I51_2:%.*]] = mul i32 [[AND_I50_2]], 65535 ; CHECK-NEXT: [[SHR_I49_3:%.*]] = lshr i32 [[CONV]], 15 ; CHECK-NEXT: [[AND_I50_3:%.*]] = and i32 [[SHR_I49_3]], 65537 ; CHECK-NEXT: [[MUL_I51_3:%.*]] = mul i32 [[AND_I50_3]], 65535 +; CHECK-NEXT: [[TMP107:%.*]] = extractelement <2 x i32> [[TMP101]], i32 0 +; CHECK-NEXT: [[SHR_I49_1:%.*]] = lshr i32 [[TMP107]], 15 +; CHECK-NEXT: [[AND_I50_1:%.*]] = and i32 [[SHR_I49_1]], 65537 +; CHECK-NEXT: [[MUL_I51_1:%.*]] = mul i32 [[AND_I50_1]], 65535 +; CHECK-NEXT: [[SHR_I49_4:%.*]] = lshr i32 [[CONV_1]], 15 +; CHECK-NEXT: [[AND_I50_4:%.*]] = and i32 [[SHR_I49_4]], 65537 +; CHECK-NEXT: [[MUL_I51_4:%.*]] = mul i32 [[AND_I50_4]], 65535 +; CHECK-NEXT: [[SHR_I49_5:%.*]] = lshr i32 [[CONV1]], 15 +; CHECK-NEXT: [[AND_I50_5:%.*]] = and i32 [[SHR_I49_5]], 65537 +; CHECK-NEXT: [[MUL_I51_5:%.*]] = mul i32 [[AND_I50_5]], 65535 ; CHECK-NEXT: [[TMP78:%.*]] = load <2 x i8>, ptr [[ARRAYIDX8]], align 1 -; CHECK-NEXT: [[TMP79:%.*]] = zext <2 x i8> [[TMP78]] to <2 x i32> +; CHECK-NEXT: [[TMP102:%.*]] = zext <2 x i8> [[TMP78]] to <2 x i32> ; CHECK-NEXT: [[TMP80:%.*]] = insertelement <2 x ptr> [[TMP5]], ptr [[ARRAYIDX22]], i32 1 ; CHECK-NEXT: [[TMP81:%.*]] = call <2 x i8> @llvm.masked.gather.v2i8.v2p0(<2 x ptr> [[TMP80]], i32 1, <2 x i1> <i1 true, i1 true>, <2 x i8> poison) ; CHECK-NEXT: [[TMP82:%.*]] = zext <2 x i8> [[TMP81]] to <2 x i32> @@ -147,20 +147,20 @@ define i32 @test(ptr %pix1, ptr %pix2, i64 %idx.ext, i64 %idx.ext63, ptr %add.pt ; CHECK-NEXT: [[TMP94:%.*]] = zext <2 x i8> [[TMP93]] to <2 x i32> ; CHECK-NEXT: [[TMP95:%.*]] = sub <2 x i32> [[TMP92]], [[TMP94]] ; CHECK-NEXT: [[TMP96:%.*]] = shl <2 x i32> [[TMP95]], <i32 16, i32 16> -; CHECK-NEXT: [[TMP97:%.*]] = insertelement <2 x i32> [[TMP79]], i32 [[CONV33]], i32 1 +; CHECK-NEXT: [[TMP97:%.*]] = insertelement <2 x i32> [[TMP102]], i32 [[CONV33]], i32 1 ; CHECK-NEXT: [[TMP98:%.*]] = sub <2 x i32> [[TMP97]], [[TMP90]] -; CHECK-NEXT: [[TMP99:%.*]] = add <2 x i32> [[TMP96]], [[TMP98]] -; CHECK-NEXT: [[TMP100:%.*]] = insertelement <2 x i32> [[TMP79]], i32 [[CONV]], i32 0 -; CHECK-NEXT: [[TMP101:%.*]] = sub <2 x i32> [[TMP100]], [[TMP82]] -; CHECK-NEXT: [[TMP102:%.*]] = add <2 x i32> [[TMP88]], [[TMP101]] -; CHECK-NEXT: [[TMP103:%.*]] = shufflevector <2 x i32> [[TMP99]], <2 x i32> [[TMP102]], <2 x i32> <i32 0, i32 2> -; CHECK-NEXT: [[TMP104:%.*]] = add <2 x i32> [[TMP99]], [[TMP102]] -; CHECK-NEXT: [[TMP105:%.*]] = sub <2 x i32> [[TMP102]], [[TMP99]] -; CHECK-NEXT: [[TMP106:%.*]] = extractelement <2 x i32> [[TMP104]], i32 0 -; CHECK-NEXT: [[TMP107:%.*]] = extractelement <2 x i32> [[TMP104]], i32 1 -; CHECK-NEXT: [[ADD48:%.*]] = add i32 [[TMP107]], [[TMP106]] +; CHECK-NEXT: [[TMP104:%.*]] = add <2 x i32> [[TMP96]], [[TMP98]] +; CHECK-NEXT: [[TMP100:%.*]] = insertelement <2 x i32> [[TMP102]], i32 [[CONV1]], i32 0 +; CHECK-NEXT: [[TMP103:%.*]] = sub <2 x i32> [[TMP100]], [[TMP82]] +; CHECK-NEXT: [[TMP200:%.*]] = add <2 x i32> [[TMP88]], [[TMP103]] +; CHECK-NEXT: [[TMP128:%.*]] = shufflevector <2 x i32> [[TMP104]], <2 x i32> [[TMP200]], <2 x i32> <i32 0, i32 2> +; CHECK-NEXT: [[TMP165:%.*]] = add <2 x i32> [[TMP104]], [[TMP200]] +; CHECK-NEXT: [[TMP105:%.*]] = sub <2 x i32> [[TMP200]], [[TMP104]] +; CHECK-NEXT: [[TMP238:%.*]] = extractelement <2 x i32> [[TMP165]], i32 0 +; CHECK-NEXT: [[TMP143:%.*]] = extractelement <2 x i32> [[TMP165]], i32 1 +; CHECK-NEXT: [[ADD48:%.*]] = add i32 [[TMP143]], [[TMP238]] ; CHECK-NEXT: [[TMP108:%.*]] = extractelement <2 x i32> [[TMP105]], i32 1 -; CHECK-NEXT: [[SHR_I59:%.*]] = lshr i32 [[TMP107]], 15 +; CHECK-NEXT: [[SHR_I59:%.*]] = lshr i32 [[TMP143]], 15 ; CHECK-NEXT: [[AND_I60:%.*]] = and i32 [[SHR_I59]], 65537 ; CHECK-NEXT: [[MUL_I61:%.*]] = mul i32 [[AND_I60]], 65535 ; CHECK-NEXT: [[SHR_I59_1:%.*]] = lshr i32 [[TMP108]], 15 @@ -185,7 +185,7 @@ define i32 @test(ptr %pix1, ptr %pix2, i64 %idx.ext, i64 %idx.ext63, ptr %add.pt ; CHECK-NEXT: [[TMP125:%.*]] = shl <2 x i32> [[TMP124]], <i32 16, i32 16> ; CHECK-NEXT: [[TMP126:%.*]] = getelementptr i8, <2 x ptr> [[TMP120]], <2 x i64> <i64 1, i64 3> ; CHECK-NEXT: [[TMP127:%.*]] = call <2 x i8> @llvm.masked.gather.v2i8.v2p0(<2 x ptr> [[TMP126]], i32 1, <2 x i1> <i1 true, i1 true>, <2 x i8> poison) -; CHECK-NEXT: [[TMP128:%.*]] = zext <2 x i8> [[TMP127]] to <2 x i32> +; CHECK-NEXT: [[TMP153:%.*]] = zext <2 x i8> [[TMP127]] to <2 x i32> ; CHECK-NEXT: [[TMP129:%.*]] = getelementptr i8, <2 x ptr> [[TMP115]], <2 x i64> <i64 5, i64 7> ; CHECK-NEXT: [[TMP130:%.*]] = call <2 x i8> @llvm.masked.gather.v2i8.v2p0(<2 x ptr> [[TMP129]], i32 1, <2 x i1> <i1 true, i1 true>, <2 x i8> poison) ; CHECK-NEXT: [[TMP131:%.*]] = zext <2 x i8> [[TMP130]] to <2 x i32> @@ -195,15 +195,15 @@ define i32 @test(ptr %pix1, ptr %pix2, i64 %idx.ext, i64 %idx.ext63, ptr %add.pt ; CHECK-NEXT: [[TMP135:%.*]] = sub <2 x i32> [[TMP131]], [[TMP134]] ; CHECK-NEXT: [[TMP136:%.*]] = shl <2 x i32> [[TMP135]], <i32 16, i32 16> ; CHECK-NEXT: [[TMP137:%.*]] = insertelement <2 x i32> [[TMP110]], i32 [[CONV33_1]], i32 1 -; CHECK-NEXT: [[TMP138:%.*]] = sub <2 x i32> [[TMP137]], [[TMP128]] +; CHECK-NEXT: [[TMP138:%.*]] = sub <2 x i32> [[TMP137]], [[TMP153]] ; CHECK-NEXT: [[TMP139:%.*]] = add <2 x i32> [[TMP136]], [[TMP138]] ; CHECK-NEXT: [[TMP140:%.*]] = insertelement <2 x i32> [[TMP110]], i32 [[CONV_1]], i32 0 ; CHECK-NEXT: [[TMP141:%.*]] = sub <2 x i32> [[TMP140]], [[TMP113]] ; CHECK-NEXT: [[TMP142:%.*]] = add <2 x i32> [[TMP125]], [[TMP141]] -; CHECK-NEXT: [[TMP143:%.*]] = add <2 x i32> [[TMP139]], [[TMP142]] +; CHECK-NEXT: [[TMP257:%.*]] = add <2 x i32> [[TMP139]], [[TMP142]] ; CHECK-NEXT: [[TMP144:%.*]] = sub <2 x i32> [[TMP142]], [[TMP139]] -; CHECK-NEXT: [[TMP145:%.*]] = extractelement <2 x i32> [[TMP143]], i32 0 -; CHECK-NEXT: [[TMP146:%.*]] = extractelement <2 x i32> [[TMP143]], i32 1 +; CHECK-NEXT: [[TMP145:%.*]] = extractelement <2 x i32> [[TMP257]], i32 0 +; CHECK-NEXT: [[TMP146:%.*]] = extractelement <2 x i32> [[TMP257]], i32 1 ; CHECK-NEXT: [[ADD48_1:%.*]] = add i32 [[TMP146]], [[TMP145]] ; CHECK-NEXT: [[SHR_I54:%.*]] = lshr i32 [[TMP146]], 15 ; CHECK-NEXT: [[AND_I55:%.*]] = and i32 [[SHR_I54]], 65537 @@ -217,51 +217,51 @@ define i32 @test(ptr %pix1, ptr %pix2, i64 %idx.ext, i64 %idx.ext63, ptr %add.pt ; CHECK-NEXT: [[SUB104:%.*]] = sub i32 [[ADD78]], [[ADD94]] ; CHECK-NEXT: [[ADD105:%.*]] = add i32 [[SUB102]], [[SUB86]] ; CHECK-NEXT: [[SUB106:%.*]] = sub i32 [[SUB86]], [[SUB102]] -; CHECK-NEXT: [[ADD_I:%.*]] = add i32 [[MUL_I]], [[ADD103]] -; CHECK-NEXT: [[XOR_I:%.*]] = xor i32 [[ADD_I]], [[TMP76]] -; CHECK-NEXT: [[ADD_I52:%.*]] = add i32 [[MUL_I51]], [[ADD105]] -; CHECK-NEXT: [[XOR_I53:%.*]] = xor i32 [[ADD_I52]], [[ADD46_2]] +; CHECK-NEXT: [[ADD_I:%.*]] = add i32 [[MUL_I51_2]], [[ADD103]] +; CHECK-NEXT: [[XOR_I:%.*]] = xor i32 [[ADD_I]], [[TMP79]] +; CHECK-NEXT: [[ADD_I52:%.*]] = add i32 [[MUL_I51_3]], [[ADD105]] +; CHECK-NEXT: [[XOR_I53:%.*]] = xor i32 [[ADD_I52]], [[CONV]] ; CHECK-NEXT: [[ADD_I57:%.*]] = add i32 [[MUL_I56]], [[SUB104]] ; CHECK-NEXT: [[XOR_I58:%.*]] = xor i32 [[ADD_I57]], [[TMP146]] ; CHECK-NEXT: [[ADD_I62:%.*]] = add i32 [[MUL_I61]], [[SUB106]] -; CHECK-NEXT: [[XOR_I63:%.*]] = xor i32 [[ADD_I62]], [[TMP107]] +; CHECK-NEXT: [[XOR_I63:%.*]] = xor i32 [[ADD_I62]], [[TMP143]] ; CHECK-NEXT: [[ADD110:%.*]] = add i32 [[XOR_I53]], [[XOR_I]] ; CHECK-NEXT: [[ADD112:%.*]] = add i32 [[ADD110]], [[XOR_I58]] ; CHECK-NEXT: [[ADD113:%.*]] = add i32 [[ADD112]], [[XOR_I63]] ; CHECK-NEXT: [[TMP150:%.*]] = shufflevector <2 x i32> [[TMP105]], <2 x i32> poison, <2 x i32> <i32 1, i32 0> ; CHECK-NEXT: [[TMP151:%.*]] = insertelement <2 x i32> [[TMP150]], i32 [[SUB47_2]], i32 1 ; CHECK-NEXT: [[TMP152:%.*]] = insertelement <2 x i32> [[TMP105]], i32 [[SUB45_2]], i32 1 -; CHECK-NEXT: [[TMP153:%.*]] = add <2 x i32> [[TMP151]], [[TMP152]] +; CHECK-NEXT: [[TMP163:%.*]] = add <2 x i32> [[TMP151]], [[TMP152]] ; CHECK-NEXT: [[TMP154:%.*]] = shufflevector <2 x i32> [[TMP144]], <2 x i32> [[TMP73]], <2 x i32> <i32 1, i32 2> ; CHECK-NEXT: [[TMP155:%.*]] = shufflevector <2 x i32> [[TMP144]], <2 x i32> [[TMP73]], <2 x i32> <i32 0, i32 3> ; CHECK-NEXT: [[TMP156:%.*]] = add <2 x i32> [[TMP154]], [[TMP155]] -; CHECK-NEXT: [[TMP157:%.*]] = extractelement <2 x i32> [[TMP153]], i32 1 +; CHECK-NEXT: [[TMP157:%.*]] = extractelement <2 x i32> [[TMP163]], i32 1 ; CHECK-NEXT: [[TMP158:%.*]] = extractelement <2 x i32> [[TMP156]], i32 1 -; CHECK-NEXT: [[TMP159:%.*]] = shufflevector <2 x i32> [[TMP156]], <2 x i32> [[TMP153]], <2 x i32> <i32 1, i32 3> -; CHECK-NEXT: [[ADD94_1:%.*]] = add i32 [[TMP158]], [[TMP157]] -; CHECK-NEXT: [[TMP160:%.*]] = extractelement <2 x i32> [[TMP153]], i32 0 +; CHECK-NEXT: [[TMP159:%.*]] = shufflevector <2 x i32> [[TMP156]], <2 x i32> [[TMP163]], <2 x i32> <i32 1, i32 3> +; CHECK-NEXT: [[ADD78_2:%.*]] = add i32 [[TMP158]], [[TMP157]] +; CHECK-NEXT: [[TMP160:%.*]] = extractelement <2 x i32> [[TMP163]], i32 0 ; CHECK-NEXT: [[TMP161:%.*]] = extractelement <2 x i32> [[TMP156]], i32 0 -; CHECK-NEXT: [[TMP162:%.*]] = shufflevector <2 x i32> [[TMP156]], <2 x i32> [[TMP153]], <2 x i32> <i32 0, i32 2> -; CHECK-NEXT: [[ADD78_1:%.*]] = add i32 [[TMP161]], [[TMP160]] -; CHECK-NEXT: [[TMP163:%.*]] = sub <2 x i32> [[TMP153]], [[TMP156]] -; CHECK-NEXT: [[TMP164:%.*]] = extractelement <2 x i32> [[TMP163]], i32 0 -; CHECK-NEXT: [[TMP165:%.*]] = extractelement <2 x i32> [[TMP163]], i32 1 -; CHECK-NEXT: [[ADD105_1:%.*]] = add i32 [[TMP165]], [[TMP164]] -; CHECK-NEXT: [[SUB106_1:%.*]] = sub i32 [[TMP164]], [[TMP165]] +; CHECK-NEXT: [[TMP162:%.*]] = shufflevector <2 x i32> [[TMP156]], <2 x i32> [[TMP163]], <2 x i32> <i32 0, i32 2> +; CHECK-NEXT: [[ADD94_1:%.*]] = add i32 [[TMP161]], [[TMP160]] +; CHECK-NEXT: [[TMP164:%.*]] = sub <2 x i32> [[TMP163]], [[TMP156]] +; CHECK-NEXT: [[TMP173:%.*]] = extractelement <2 x i32> [[TMP164]], i32 0 +; CHECK-NEXT: [[TMP174:%.*]] = extractelement <2 x i32> [[TMP164]], i32 1 +; CHECK-NEXT: [[ADD105_1:%.*]] = add i32 [[TMP174]], [[TMP173]] +; CHECK-NEXT: [[SUB106_1:%.*]] = sub i32 [[TMP173]], [[TMP174]] ; CHECK-NEXT: [[ADD_I52_1:%.*]] = add i32 [[MUL_I51_1]], [[ADD105_1]] -; CHECK-NEXT: [[XOR_I53_1:%.*]] = xor i32 [[ADD_I52_1]], [[TMP77]] -; CHECK-NEXT: [[TMP166:%.*]] = shufflevector <2 x i32> [[TMP16]], <2 x i32> [[TMP144]], <2 x i32> <i32 1, i32 3> +; CHECK-NEXT: [[XOR_I53_1:%.*]] = xor i32 [[ADD_I52_1]], [[TMP107]] +; CHECK-NEXT: [[TMP166:%.*]] = shufflevector <2 x i32> [[TMP101]], <2 x i32> [[TMP144]], <2 x i32> <i32 1, i32 3> ; CHECK-NEXT: [[TMP167:%.*]] = lshr <2 x i32> [[TMP166]], <i32 15, i32 15> ; CHECK-NEXT: [[TMP168:%.*]] = and <2 x i32> [[TMP167]], <i32 65537, i32 65537> ; CHECK-NEXT: [[TMP169:%.*]] = mul <2 x i32> [[TMP168]], <i32 65535, i32 65535> -; CHECK-NEXT: [[TMP170:%.*]] = insertelement <2 x i32> poison, i32 [[ADD78_1]], i32 0 -; CHECK-NEXT: [[TMP171:%.*]] = shufflevector <2 x i32> [[TMP170]], <2 x i32> poison, <2 x i32> zeroinitializer ; CHECK-NEXT: [[TMP172:%.*]] = insertelement <2 x i32> poison, i32 [[ADD94_1]], i32 0 -; CHECK-NEXT: [[TMP173:%.*]] = shufflevector <2 x i32> [[TMP172]], <2 x i32> poison, <2 x i32> zeroinitializer -; CHECK-NEXT: [[TMP174:%.*]] = add <2 x i32> [[TMP171]], [[TMP173]] -; CHECK-NEXT: [[TMP175:%.*]] = sub <2 x i32> [[TMP171]], [[TMP173]] -; CHECK-NEXT: [[TMP176:%.*]] = shufflevector <2 x i32> [[TMP174]], <2 x i32> [[TMP175]], <2 x i32> <i32 0, i32 3> -; CHECK-NEXT: [[TMP177:%.*]] = add <2 x i32> [[TMP169]], [[TMP176]] +; CHECK-NEXT: [[TMP171:%.*]] = shufflevector <2 x i32> [[TMP172]], <2 x i32> poison, <2 x i32> zeroinitializer +; CHECK-NEXT: [[TMP208:%.*]] = insertelement <2 x i32> poison, i32 [[ADD78_2]], i32 0 +; CHECK-NEXT: [[TMP209:%.*]] = shufflevector <2 x i32> [[TMP208]], <2 x i32> poison, <2 x i32> zeroinitializer +; CHECK-NEXT: [[TMP282:%.*]] = add <2 x i32> [[TMP171]], [[TMP209]] +; CHECK-NEXT: [[TMP211:%.*]] = sub <2 x i32> [[TMP171]], [[TMP209]] +; CHECK-NEXT: [[TMP283:%.*]] = shufflevector <2 x i32> [[TMP282]], <2 x i32> [[TMP211]], <2 x i32> <i32 0, i32 3> +; CHECK-NEXT: [[TMP177:%.*]] = add <2 x i32> [[TMP169]], [[TMP283]] ; CHECK-NEXT: [[TMP178:%.*]] = xor <2 x i32> [[TMP177]], [[TMP166]] ; CHECK-NEXT: [[ADD_I62_1:%.*]] = add i32 [[MUL_I61_1]], [[SUB106_1]] ; CHECK-NEXT: [[XOR_I63_1:%.*]] = xor i32 [[ADD_I62_1]], [[TMP108]] @@ -271,90 +271,90 @@ define i32 @test(ptr %pix1, ptr %pix2, i64 %idx.ext, i64 %idx.ext63, ptr %add.pt ; CHECK-NEXT: [[TMP180:%.*]] = extractelement <2 x i32> [[TMP178]], i32 1 ; CHECK-NEXT: [[ADD112_1:%.*]] = add i32 [[ADD110_1]], [[TMP180]] ; CHECK-NEXT: [[ADD113_1:%.*]] = add i32 [[ADD112_1]], [[XOR_I63_1]] -; CHECK-NEXT: [[TMP181:%.*]] = shufflevector <2 x i32> [[TMP104]], <2 x i32> poison, <2 x i32> <i32 poison, i32 0> +; CHECK-NEXT: [[TMP181:%.*]] = shufflevector <2 x i32> [[TMP165]], <2 x i32> poison, <2 x i32> <i32 poison, i32 0> ; CHECK-NEXT: [[TMP182:%.*]] = insertelement <2 x i32> [[TMP181]], i32 [[ADD44_2]], i32 0 -; CHECK-NEXT: [[TMP183:%.*]] = insertelement <2 x i32> [[TMP104]], i32 [[ADD46_2]], i32 0 +; CHECK-NEXT: [[TMP183:%.*]] = insertelement <2 x i32> [[TMP165]], i32 [[CONV]], i32 0 ; CHECK-NEXT: [[TMP184:%.*]] = sub <2 x i32> [[TMP182]], [[TMP183]] -; CHECK-NEXT: [[TMP185:%.*]] = shufflevector <2 x i32> [[TMP72]], <2 x i32> [[TMP143]], <2 x i32> <i32 1, i32 2> -; CHECK-NEXT: [[TMP186:%.*]] = shufflevector <2 x i32> [[TMP72]], <2 x i32> [[TMP143]], <2 x i32> <i32 0, i32 3> +; CHECK-NEXT: [[TMP185:%.*]] = shufflevector <2 x i32> [[TMP16]], <2 x i32> [[TMP257]], <2 x i32> <i32 1, i32 2> +; CHECK-NEXT: [[TMP186:%.*]] = shufflevector <2 x i32> [[TMP16]], <2 x i32> [[TMP257]], <2 x i32> <i32 0, i32 3> ; CHECK-NEXT: [[TMP187:%.*]] = sub <2 x i32> [[TMP185]], [[TMP186]] ; CHECK-NEXT: [[TMP188:%.*]] = extractelement <2 x i32> [[TMP184]], i32 0 ; CHECK-NEXT: [[TMP189:%.*]] = extractelement <2 x i32> [[TMP187]], i32 0 ; CHECK-NEXT: [[TMP190:%.*]] = shufflevector <2 x i32> [[TMP187]], <2 x i32> [[TMP184]], <2 x i32> <i32 0, i32 2> -; CHECK-NEXT: [[ADD94_2:%.*]] = add i32 [[TMP189]], [[TMP188]] +; CHECK-NEXT: [[ADD94_4:%.*]] = add i32 [[TMP189]], [[TMP188]] ; CHECK-NEXT: [[TMP191:%.*]] = extractelement <2 x i32> [[TMP184]], i32 1 ; CHECK-NEXT: [[TMP192:%.*]] = extractelement <2 x i32> [[TMP187]], i32 1 ; CHECK-NEXT: [[TMP193:%.*]] = shufflevector <2 x i32> [[TMP187]], <2 x i32> [[TMP184]], <2 x i32> <i32 1, i32 3> -; CHECK-NEXT: [[ADD78_2:%.*]] = add i32 [[TMP192]], [[TMP191]] +; CHECK-NEXT: [[ADD94_2:%.*]] = add i32 [[TMP192]], [[TMP191]] ; CHECK-NEXT: [[TMP194:%.*]] = sub <2 x i32> [[TMP184]], [[TMP187]] -; CHECK-NEXT: [[TMP195:%.*]] = insertelement <2 x i32> poison, i32 [[ADD78_2]], i32 0 -; CHECK-NEXT: [[TMP196:%.*]] = shufflevector <2 x i32> [[TMP195]], <2 x i32> poison, <2 x i32> zeroinitializer -; CHECK-NEXT: [[TMP197:%.*]] = insertelement <2 x i32> poison, i32 [[ADD94_2]], i32 0 +; CHECK-NEXT: [[TMP244:%.*]] = insertelement <2 x i32> poison, i32 [[ADD94_2]], i32 0 +; CHECK-NEXT: [[TMP245:%.*]] = shufflevector <2 x i32> [[TMP244]], <2 x i32> poison, <2 x i32> zeroinitializer +; CHECK-NEXT: [[TMP197:%.*]] = insertelement <2 x i32> poison, i32 [[ADD94_4]], i32 0 ; CHECK-NEXT: [[TMP198:%.*]] = shufflevector <2 x i32> [[TMP197]], <2 x i32> poison, <2 x i32> zeroinitializer -; CHECK-NEXT: [[TMP199:%.*]] = add <2 x i32> [[TMP196]], [[TMP198]] -; CHECK-NEXT: [[TMP200:%.*]] = sub <2 x i32> [[TMP196]], [[TMP198]] -; CHECK-NEXT: [[TMP201:%.*]] = shufflevector <2 x i32> [[TMP199]], <2 x i32> [[TMP200]], <2 x i32> <i32 0, i32 3> -; CHECK-NEXT: [[TMP202:%.*]] = extractelement <2 x i32> [[TMP194]], i32 0 +; CHECK-NEXT: [[TMP246:%.*]] = add <2 x i32> [[TMP245]], [[TMP198]] +; CHECK-NEXT: [[TMP247:%.*]] = sub <2 x i32> [[TMP245]], [[TMP198]] +; CHECK-NEXT: [[TMP248:%.*]] = shufflevector <2 x i32> [[TMP246]], <2 x i32> [[TMP247]], <2 x i32> <i32 0, i32 3> +; CHECK-NEXT: [[TMP215:%.*]] = extractelement <2 x i32> [[TMP194]], i32 0 ; CHECK-NEXT: [[TMP203:%.*]] = extractelement <2 x i32> [[TMP194]], i32 1 -; CHECK-NEXT: [[ADD105_2:%.*]] = add i32 [[TMP202]], [[TMP203]] -; CHECK-NEXT: [[SUB106_2:%.*]] = sub i32 [[TMP203]], [[TMP202]] -; CHECK-NEXT: [[ADD_I52_2:%.*]] = add i32 [[MUL_I51_2]], [[ADD105_2]] +; CHECK-NEXT: [[ADD105_2:%.*]] = add i32 [[TMP215]], [[TMP203]] +; CHECK-NEXT: [[SUB106_2:%.*]] = sub i32 [[TMP203]], [[TMP215]] +; CHECK-NEXT: [[ADD_I52_2:%.*]] = add i32 [[MUL_I51_4]], [[ADD105_2]] ; CHECK-NEXT: [[XOR_I53_2:%.*]] = xor i32 [[ADD_I52_2]], [[CONV_1]] -; CHECK-NEXT: [[TMP204:%.*]] = add <2 x i32> [[TMP149]], [[TMP201]] -; CHECK-NEXT: [[TMP205:%.*]] = xor <2 x i32> [[TMP204]], [[TMP110]] -; CHECK-NEXT: [[SHR_I59_2:%.*]] = lshr i32 [[TMP106]], 15 +; CHECK-NEXT: [[TMP266:%.*]] = add <2 x i32> [[TMP149]], [[TMP248]] +; CHECK-NEXT: [[TMP267:%.*]] = xor <2 x i32> [[TMP266]], [[TMP110]] +; CHECK-NEXT: [[SHR_I59_2:%.*]] = lshr i32 [[TMP238]], 15 ; CHECK-NEXT: [[AND_I60_2:%.*]] = and i32 [[SHR_I59_2]], 65537 ; CHECK-NEXT: [[MUL_I61_2:%.*]] = mul i32 [[AND_I60_2]], 65535 ; CHECK-NEXT: [[ADD_I62_2:%.*]] = add i32 [[MUL_I61_2]], [[SUB106_2]] -; CHECK-NEXT: [[XOR_I63_2:%.*]] = xor i32 [[ADD_I62_2]], [[TMP106]] +; CHECK-NEXT: [[XOR_I63_2:%.*]] = xor i32 [[ADD_I62_2]], [[TMP238]] ; CHECK-NEXT: [[ADD108_2:%.*]] = add i32 [[XOR_I53_2]], [[ADD113_1]] -; CHECK-NEXT: [[TMP206:%.*]] = extractelement <2 x i32> [[TMP205]], i32 0 +; CHECK-NEXT: [[TMP206:%.*]] = extractelement <2 x i32> [[TMP267]], i32 0 ; CHECK-NEXT: [[ADD110_2:%.*]] = add i32 [[ADD108_2]], [[TMP206]] -; CHECK-NEXT: [[TMP207:%.*]] = extractelement <2 x i32> [[TMP205]], i32 1 +; CHECK-NEXT: [[TMP207:%.*]] = extractelement <2 x i32> [[TMP267]], i32 1 ; CHECK-NEXT: [[ADD112_2:%.*]] = add i32 [[ADD110_2]], [[TMP207]] ; CHECK-NEXT: [[ADD113_2:%.*]] = add i32 [[ADD112_2]], [[XOR_I63_2]] -; CHECK-NEXT: [[TMP208:%.*]] = insertelement <2 x i32> [[TMP150]], i32 [[SUB45_2]], i32 0 -; CHECK-NEXT: [[TMP209:%.*]] = insertelement <2 x i32> [[TMP105]], i32 [[SUB47_2]], i32 0 -; CHECK-NEXT: [[TMP210:%.*]] = sub <2 x i32> [[TMP208]], [[TMP209]] -; CHECK-NEXT: [[TMP211:%.*]] = shufflevector <2 x i32> [[TMP73]], <2 x i32> [[TMP144]], <2 x i32> <i32 1, i32 2> +; CHECK-NEXT: [[TMP221:%.*]] = insertelement <2 x i32> [[TMP150]], i32 [[SUB45_2]], i32 0 +; CHECK-NEXT: [[TMP222:%.*]] = insertelement <2 x i32> [[TMP105]], i32 [[SUB47_2]], i32 0 +; CHECK-NEXT: [[TMP210:%.*]] = sub <2 x i32> [[TMP221]], [[TMP222]] +; CHECK-NEXT: [[TMP225:%.*]] = shufflevector <2 x i32> [[TMP73]], <2 x i32> [[TMP144]], <2 x i32> <i32 1, i32 2> ; CHECK-NEXT: [[TMP212:%.*]] = shufflevector <2 x i32> [[TMP73]], <2 x i32> [[TMP144]], <2 x i32> <i32 0, i32 3> -; CHECK-NEXT: [[TMP213:%.*]] = sub <2 x i32> [[TMP211]], [[TMP212]] +; CHECK-NEXT: [[TMP226:%.*]] = sub <2 x i32> [[TMP225]], [[TMP212]] ; CHECK-NEXT: [[TMP214:%.*]] = extractelement <2 x i32> [[TMP210]], i32 0 -; CHECK-NEXT: [[TMP215:%.*]] = extractelement <2 x i32> [[TMP213]], i32 0 -; CHECK-NEXT: [[TMP216:%.*]] = shufflevector <2 x i32> [[TMP213]], <2 x i32> [[TMP210]], <2 x i32> <i32 0, i32 2> -; CHECK-NEXT: [[ADD94_3:%.*]] = add i32 [[TMP215]], [[TMP214]] +; CHECK-NEXT: [[TMP227:%.*]] = extractelement <2 x i32> [[TMP226]], i32 0 +; CHECK-NEXT: [[TMP216:%.*]] = shufflevector <2 x i32> [[TMP226]], <2 x i32> [[TMP210]], <2 x i32> <i32 0, i32 2> +; CHECK-NEXT: [[ADD94_3:%.*]] = add i32 [[TMP227]], [[TMP214]] ; CHECK-NEXT: [[TMP217:%.*]] = extractelement <2 x i32> [[TMP210]], i32 1 -; CHECK-NEXT: [[TMP218:%.*]] = extractelement <2 x i32> [[TMP213]], i32 1 -; CHECK-NEXT: [[TMP219:%.*]] = shufflevector <2 x i32> [[TMP213]], <2 x i32> [[TMP210]], <2 x i32> <i32 1, i32 3> -; CHECK-NEXT: [[ADD78_3:%.*]] = add i32 [[TMP218]], [[TMP217]] -; CHECK-NEXT: [[TMP220:%.*]] = sub <2 x i32> [[TMP210]], [[TMP213]] -; CHECK-NEXT: [[TMP221:%.*]] = insertelement <2 x i32> poison, i32 [[ADD78_3]], i32 0 -; CHECK-NEXT: [[TMP222:%.*]] = shufflevector <2 x i32> [[TMP221]], <2 x i32> poison, <2 x i32> zeroinitializer +; CHECK-NEXT: [[TMP218:%.*]] = extractelement <2 x i32> [[TMP226]], i32 1 +; CHECK-NEXT: [[TMP219:%.*]] = shufflevector <2 x i32> [[TMP226]], <2 x i32> [[TMP210]], <2 x i32> <i32 1, i32 3> +; CHECK-NEXT: [[SUB59:%.*]] = add i32 [[TMP218]], [[TMP217]] +; CHECK-NEXT: [[TMP220:%.*]] = sub <2 x i32> [[TMP210]], [[TMP226]] +; CHECK-NEXT: [[TMP274:%.*]] = insertelement <2 x i32> poison, i32 [[SUB59]], i32 0 +; CHECK-NEXT: [[TMP275:%.*]] = shufflevector <2 x i32> [[TMP274]], <2 x i32> poison, <2 x i32> zeroinitializer ; CHECK-NEXT: [[TMP223:%.*]] = insertelement <2 x i32> poison, i32 [[ADD94_3]], i32 0 ; CHECK-NEXT: [[TMP224:%.*]] = shufflevector <2 x i32> [[TMP223]], <2 x i32> poison, <2 x i32> zeroinitializer -; CHECK-NEXT: [[TMP225:%.*]] = add <2 x i32> [[TMP222]], [[TMP224]] -; CHECK-NEXT: [[TMP226:%.*]] = sub <2 x i32> [[TMP222]], [[TMP224]] -; CHECK-NEXT: [[TMP227:%.*]] = shufflevector <2 x i32> [[TMP225]], <2 x i32> [[TMP226]], <2 x i32> <i32 0, i32 3> +; CHECK-NEXT: [[TMP276:%.*]] = add <2 x i32> [[TMP275]], [[TMP224]] +; CHECK-NEXT: [[TMP277:%.*]] = sub <2 x i32> [[TMP275]], [[TMP224]] +; CHECK-NEXT: [[TMP278:%.*]] = shufflevector <2 x i32> [[TMP276]], <2 x i32> [[TMP277]], <2 x i32> <i32 0, i32 3> ; CHECK-NEXT: [[TMP228:%.*]] = extractelement <2 x i32> [[TMP220]], i32 0 ; CHECK-NEXT: [[TMP229:%.*]] = extractelement <2 x i32> [[TMP220]], i32 1 ; CHECK-NEXT: [[ADD105_3:%.*]] = add i32 [[TMP228]], [[TMP229]] ; CHECK-NEXT: [[SUB106_3:%.*]] = sub i32 [[TMP229]], [[TMP228]] -; CHECK-NEXT: [[ADD_I52_3:%.*]] = add i32 [[MUL_I51_3]], [[ADD105_3]] -; CHECK-NEXT: [[XOR_I53_3:%.*]] = xor i32 [[ADD_I52_3]], [[CONV]] -; CHECK-NEXT: [[TMP230:%.*]] = lshr <2 x i32> [[TMP79]], <i32 15, i32 15> +; CHECK-NEXT: [[ADD_I52_3:%.*]] = add i32 [[MUL_I51_5]], [[ADD105_3]] +; CHECK-NEXT: [[XOR_I53_3:%.*]] = xor i32 [[ADD_I52_3]], [[CONV1]] +; CHECK-NEXT: [[TMP230:%.*]] = lshr <2 x i32> [[TMP102]], <i32 15, i32 15> ; CHECK-NEXT: [[TMP231:%.*]] = and <2 x i32> [[TMP230]], <i32 65537, i32 65537> ; CHECK-NEXT: [[TMP232:%.*]] = mul <2 x i32> [[TMP231]], <i32 65535, i32 65535> -; CHECK-NEXT: [[TMP233:%.*]] = add <2 x i32> [[TMP232]], [[TMP227]] -; CHECK-NEXT: [[TMP234:%.*]] = xor <2 x i32> [[TMP233]], [[TMP79]] +; CHECK-NEXT: [[TMP286:%.*]] = add <2 x i32> [[TMP232]], [[TMP278]] +; CHECK-NEXT: [[TMP287:%.*]] = xor <2 x i32> [[TMP286]], [[TMP102]] ; CHECK-NEXT: [[SHR_I59_3:%.*]] = lshr i32 [[CONV33]], 15 ; CHECK-NEXT: [[AND_I60_3:%.*]] = and i32 [[SHR_I59_3]], 65537 ; CHECK-NEXT: [[MUL_I61_3:%.*]] = mul i32 [[AND_I60_3]], 65535 ; CHECK-NEXT: [[ADD_I62_3:%.*]] = add i32 [[MUL_I61_3]], [[SUB106_3]] ; CHECK-NEXT: [[XOR_I63_3:%.*]] = xor i32 [[ADD_I62_3]], [[CONV33]] ; CHECK-NEXT: [[ADD108_3:%.*]] = add i32 [[XOR_I53_3]], [[ADD113_2]] -; CHECK-NEXT: [[TMP235:%.*]] = extractelement <2 x i32> [[TMP234]], i32 0 +; CHECK-NEXT: [[TMP235:%.*]] = extractelement <2 x i32> [[TMP287]], i32 0 ; CHECK-NEXT: [[ADD110_3:%.*]] = add i32 [[ADD108_3]], [[TMP235]] -; CHECK-NEXT: [[TMP236:%.*]] = extractelement <2 x i32> [[TMP234]], i32 1 +; CHECK-NEXT: [[TMP236:%.*]] = extractelement <2 x i32> [[TMP287]], i32 1 ; CHECK-NEXT: [[ADD112_3:%.*]] = add i32 [[ADD110_3]], [[TMP236]] ; CHECK-NEXT: [[ADD113_3:%.*]] = add i32 [[ADD112_3]], [[XOR_I63_3]] ; CHECK-NEXT: ret i32 [[ADD113_3]] diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/init-ext-node-not-truncable.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/init-ext-node-not-truncable.ll new file mode 100644 index 0000000000000000000000000000000000000000..1166b1fca826b6093a7d2a872ef19e57c5344082 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/init-ext-node-not-truncable.ll @@ -0,0 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -mtriple=riscv64-unknown-linux-gnu -mattr="+v" < %s -slp-threshold=-5 | FileCheck %s + +@h = global [16 x i64] zeroinitializer + +define void @test() { +; CHECK-LABEL: define void @test( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: store <2 x i64> <i64 4294967295, i64 0>, ptr @h, align 8 +; CHECK-NEXT: ret void +; +entry: + %sext.0 = sext i8 0 to i32 + %sext.1 = sext i8 0 to i32 + + %lshr.0 = lshr i32 0, %sext.0 + %lshr.1 = lshr i32 0, %sext.1 + + %or.0 = or i32 %lshr.0, -1 + %or.1 = or i32 %lshr.1, 0 + + %zext.0 = zext i32 %or.0 to i64 + %zext.1 = zext i32 %or.1 to i64 + + store i64 %zext.0, ptr @h, align 8 + store i64 %zext.1, ptr getelementptr inbounds ([16 x i64], ptr @h, i64 0, i64 1), align 8 + ret void +} diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/mixed-extracts-types.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/mixed-extracts-types.ll new file mode 100644 index 0000000000000000000000000000000000000000..0d5c644b9cc0fc170ecf48f9953b51ec6fdfd5b5 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/mixed-extracts-types.ll @@ -0,0 +1,35 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -mtriple=riscv64-unknown-linux-gnu -mattr="+v" < %s | FileCheck %s + +define i32 @test() { +; CHECK-LABEL: define i32 @test( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <vscale x 4 x i8> zeroinitializer, i64 0 +; CHECK-NEXT: [[CONV5:%.*]] = sext i8 [[VECTOR_RECUR_EXTRACT]] to i32 +; CHECK-NEXT: store i32 [[CONV5]], ptr getelementptr ([0 x i32], ptr null, i64 0, i64 -14), align 4 +; CHECK-NEXT: [[TMP0:%.*]] = load <2 x i8>, ptr getelementptr ([9 x i8], ptr null, i64 -2, i64 5), align 1 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i8> [[TMP0]], zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i16> +; CHECK-NEXT: store <2 x i16> [[TMP2]], ptr getelementptr ([0 x i16], ptr null, i64 0, i64 -14), align 2 +; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x i8> [[TMP0]], i32 0 +; CHECK-NEXT: [[CONV5_1:%.*]] = sext i8 [[TMP3]] to i32 +; CHECK-NEXT: store i32 [[CONV5_1]], ptr getelementptr ([0 x i32], ptr null, i64 0, i64 -13), align 4 +; CHECK-NEXT: ret i32 0 +; +entry: + %vector.recur.extract = extractelement <vscale x 4 x i8> zeroinitializer, i64 0 + %0 = load i8, ptr getelementptr ([9 x i8], ptr null, i64 -2, i64 5), align 1 + %tobool1.not = icmp ne i8 %0, 0 + %conv2 = zext i1 %tobool1.not to i16 + store i16 %conv2, ptr getelementptr ([0 x i16], ptr null, i64 0, i64 -14), align 2 + %conv5 = sext i8 %vector.recur.extract to i32 + store i32 %conv5, ptr getelementptr ([0 x i32], ptr null, i64 0, i64 -14), align 4 + %1 = load i8, ptr getelementptr ([9 x i8], ptr null, i64 -2, i64 6), align 1 + %tobool1.not.1 = icmp ne i8 %1, 0 + %conv2.1 = zext i1 %tobool1.not.1 to i16 + store i16 %conv2.1, ptr getelementptr ([0 x i16], ptr null, i64 0, i64 -13), align 2 + %conv5.1 = sext i8 %0 to i32 + store i32 %conv5.1, ptr getelementptr ([0 x i32], ptr null, i64 0, i64 -13), align 4 + ret i32 0 +} diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/partial-vec-invalid-cost.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/partial-vec-invalid-cost.ll new file mode 100644 index 0000000000000000000000000000000000000000..6388cc2dedc73ad663fd50ca88ca5a6b07bc66c2 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/partial-vec-invalid-cost.ll @@ -0,0 +1,49 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt < %s -passes=slp-vectorizer -S | FileCheck %s + +target triple = "riscv64-unknown-linux-gnu" + +define void @partial_vec_invalid_cost() #0 { +; CHECK-LABEL: define void @partial_vec_invalid_cost( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> zeroinitializer) +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> zeroinitializer) +; CHECK-NEXT: [[OP_RDX3:%.*]] = or i32 [[TMP0]], [[TMP1]] +; CHECK-NEXT: [[STORE_THIS:%.*]] = zext i32 [[OP_RDX3]] to i96 +; CHECK-NEXT: store i96 [[STORE_THIS]], ptr null, align 16 +; CHECK-NEXT: ret void +; +entry: + + %lshr.1 = lshr i96 0, 0 ; These ops + %lshr.2 = lshr i96 0, 0 ; return an + %add.0 = add i96 0, 0 ; invalid + %add.1 = add i96 0, 0 ; vector cost. + + %trunc.i96.1 = trunc i96 %lshr.1 to i32 ; These ops + %trunc.i96.2 = trunc i96 %lshr.2 to i32 ; return an + %trunc.i96.3 = trunc i96 %add.0 to i32 ; invalid + %trunc.i96.4 = trunc i96 %add.1 to i32 ; vector cost. + + %or.0 = or i32 %trunc.i96.1, %trunc.i96.2 + %or.1 = or i32 %or.0, %trunc.i96.3 + %or.2 = or i32 %or.1, %trunc.i96.4 + + %zext.0 = zext i1 0 to i32 ; These + %zext.1 = zext i1 0 to i32 ; ops + %zext.2 = zext i1 0 to i32 ; are + %zext.3 = zext i1 0 to i32 ; vectorized + + %or.3 = or i32 %or.2, %zext.0 ; users + %or.4 = or i32 %or.3, %zext.1 ; of + %or.5 = or i32 %or.4, %zext.2 ; vectorized + %or.6 = or i32 %or.5, %zext.3 ; ops + + %store.this = zext i32 %or.6 to i96 + + store i96 %store.this, ptr null, align 16 + ret void +} + +attributes #0 = { "target-features"="+v" } diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/reduction-extension-after-bitwidth.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/reduction-extension-after-bitwidth.ll new file mode 100644 index 0000000000000000000000000000000000000000..7771e8369b61988efa544df4fd6fb6a7b05c03fc --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/reduction-extension-after-bitwidth.ll @@ -0,0 +1,33 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -mtriple=riscv64-unknown-linux-gnu -mattr="+v" --passes=slp-vectorizer < %s | FileCheck %s + +define i32 @test(ptr %0, ptr %1) { +; CHECK-LABEL: define i32 @test( +; CHECK-SAME: ptr [[TMP0:%.*]], ptr [[TMP1:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[LOAD_5:%.*]] = load i32, ptr [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.vector.reduce.and.v4i8(<4 x i8> <i8 1, i8 1, i8 1, i8 1>) +; CHECK-NEXT: [[TMP3:%.*]] = sext i8 [[TMP2]] to i32 +; CHECK-NEXT: [[OP_RDX:%.*]] = and i32 [[TMP3]], [[LOAD_5]] +; CHECK-NEXT: ret i32 [[OP_RDX]] +; +entry: + %zext.0 = zext i8 1 to i32 + %zext.1 = zext i8 1 to i32 + %zext.2 = zext i8 1 to i32 + %zext.3 = zext i8 1 to i32 + %select.zext.0 = select i1 false, i32 -1, i32 %zext.0 + %select.zext.1 = select i1 false, i32 0, i32 %zext.1 + %select.zext.2 = select i1 false, i32 0, i32 %zext.2 + %select.zext.3 = select i1 false, i32 0, i32 %zext.3 + + %load.5 = load i32, ptr %1, align 4 + + %and.0 = and i32 %load.5, %select.zext.0 + %and.1 = and i32 %and.0, %select.zext.1 + %and.2 = and i32 %and.1, %select.zext.2 + %and.3 = and i32 %and.2, %select.zext.3 + + ret i32 %and.3 +} + diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/reductions.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/reductions.ll index 000e7a56df3778104204e95b8891a02ddebe8695..500f10659f04cbf920071d91cecf80c3a47b8e34 100644 --- a/llvm/test/Transforms/SLPVectorizer/RISCV/reductions.ll +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/reductions.ll @@ -802,9 +802,10 @@ define i64 @red_zext_ld_4xi64(ptr %ptr) { ; CHECK-LABEL: @red_zext_ld_4xi64( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i8>, ptr [[PTR:%.*]], align 1 -; CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i8> [[TMP0]] to <4 x i64> -; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vector.reduce.add.v4i64(<4 x i64> [[TMP1]]) -; CHECK-NEXT: ret i64 [[TMP2]] +; CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i8> [[TMP0]] to <4 x i16> +; CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.vector.reduce.add.v4i16(<4 x i16> [[TMP1]]) +; CHECK-NEXT: [[TMP3:%.*]] = zext i16 [[TMP2]] to i64 +; CHECK-NEXT: ret i64 [[TMP3]] ; entry: %ld0 = load i8, ptr %ptr diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/small-tree-not-schedulable-bv-node.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/small-tree-not-schedulable-bv-node.ll new file mode 100644 index 0000000000000000000000000000000000000000..26f3fcae3a3334c56000b2b38a53ab8bd9b0e1b8 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/small-tree-not-schedulable-bv-node.ll @@ -0,0 +1,263 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -mtriple=riscv64-unknown-linux-gnu -slp-threshold=-100 -mattr=+v < %s | FileCheck %s + +define void @test1() personality ptr null { +; CHECK-LABEL: define void @test1( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] personality ptr null { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CALL33:%.*]] = invoke ptr null(i64 0, ptr null) +; CHECK-NEXT: to label [[INVOKE_CONT32:%.*]] unwind label [[LPAD31_LOOPEXIT:%.*]] +; CHECK: invoke.cont32: +; CHECK-NEXT: invoke void null(ptr null, ptr null) +; CHECK-NEXT: to label [[INVOKE_CONT37:%.*]] unwind label [[LPAD34_LOOPEXIT:%.*]] +; CHECK: invoke.cont37: +; CHECK-NEXT: unreachable +; CHECK: lpad31.loopexit: +; CHECK-NEXT: [[LPAD_LOOPEXIT:%.*]] = landingpad { ptr, i32 } +; CHECK-NEXT: cleanup +; CHECK-NEXT: br label [[EHCLEANUP47:%.*]] +; CHECK: lpad34.loopexit: +; CHECK-NEXT: [[DOTLCSSA101:%.*]] = phi ptr [ null, [[INVOKE_CONT32]] ] +; CHECK-NEXT: [[CALL33_LCSSA96:%.*]] = phi ptr [ [[CALL33]], [[INVOKE_CONT32]] ] +; CHECK-NEXT: [[LPAD_LOOPEXIT56:%.*]] = landingpad { ptr, i32 } +; CHECK-NEXT: cleanup +; CHECK-NEXT: br label [[LPAD34_BODY:%.*]] +; CHECK: lpad34.loopexit.split-lp: +; CHECK-NEXT: [[LPAD_LOOPEXIT_SPLIT_LP57:%.*]] = landingpad { ptr, i32 } +; CHECK-NEXT: cleanup +; CHECK-NEXT: br label [[LPAD34_BODY]] +; CHECK: lpad34.body: +; CHECK-NEXT: [[TMP0:%.*]] = phi ptr [ [[DOTLCSSA101]], [[LPAD34_LOOPEXIT]] ], [ null, [[LPAD34_LOOPEXIT_SPLIT_LP:%.*]] ] +; CHECK-NEXT: [[CALL3399:%.*]] = phi ptr [ [[CALL33_LCSSA96]], [[LPAD34_LOOPEXIT]] ], [ null, [[LPAD34_LOOPEXIT_SPLIT_LP]] ] +; CHECK-NEXT: br label [[EHCLEANUP47]] +; CHECK: ehcleanup47: +; CHECK-NEXT: resume { ptr, i32 } zeroinitializer +; +entry: + %call33 = invoke ptr null(i64 0, ptr null) + to label %invoke.cont32 unwind label %lpad31.loopexit + +invoke.cont32: + invoke void null(ptr null, ptr null) + to label %invoke.cont37 unwind label %lpad34.loopexit + +invoke.cont37: + unreachable + +lpad31.loopexit: + %lpad.loopexit = landingpad { ptr, i32 } + cleanup + br label %ehcleanup47 + +lpad34.loopexit: + %.lcssa101 = phi ptr [ null, %invoke.cont32 ] + %call33.lcssa96 = phi ptr [ %call33, %invoke.cont32 ] + %lpad.loopexit56 = landingpad { ptr, i32 } + cleanup + br label %lpad34.body + +lpad34.loopexit.split-lp: + %lpad.loopexit.split-lp57 = landingpad { ptr, i32 } + cleanup + br label %lpad34.body + +lpad34.body: + %0 = phi ptr [ %.lcssa101, %lpad34.loopexit ], [ null, %lpad34.loopexit.split-lp ] + %call3399 = phi ptr [ %call33.lcssa96, %lpad34.loopexit ], [ null, %lpad34.loopexit.split-lp ] + br label %ehcleanup47 + +ehcleanup47: + resume { ptr, i32 } zeroinitializer +} + +define i32 @test2(i64 %idx.ext.i48.pre-phi) { +; CHECK-LABEL: define i32 @test2( +; CHECK-SAME: i64 [[IDX_EXT_I48_PRE_PHI:%.*]]) #[[ATTR0]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[DO_ACTION:%.*]] +; CHECK: do_action: +; CHECK-NEXT: switch i32 0, label [[SW_DEFAULT:%.*]] [ +; CHECK-NEXT: i32 1, label [[CLEANUP185:%.*]] +; CHECK-NEXT: i32 2, label [[CLEANUP185]] +; CHECK-NEXT: i32 0, label [[CLEANUP185]] +; CHECK-NEXT: i32 4, label [[CLEANUP185]] +; CHECK-NEXT: i32 5, label [[CLEANUP185]] +; CHECK-NEXT: i32 6, label [[CLEANUP185]] +; CHECK-NEXT: i32 7, label [[CLEANUP185]] +; CHECK-NEXT: i32 8, label [[CLEANUP185]] +; CHECK-NEXT: i32 9, label [[CLEANUP185]] +; CHECK-NEXT: i32 10, label [[CLEANUP185]] +; CHECK-NEXT: i32 11, label [[CLEANUP185]] +; CHECK-NEXT: i32 12, label [[CLEANUP185]] +; CHECK-NEXT: i32 13, label [[CLEANUP185]] +; CHECK-NEXT: i32 14, label [[CLEANUP185]] +; CHECK-NEXT: i32 15, label [[CLEANUP185]] +; CHECK-NEXT: i32 16, label [[CLEANUP185]] +; CHECK-NEXT: i32 17, label [[CLEANUP185]] +; CHECK-NEXT: i32 18, label [[CLEANUP185]] +; CHECK-NEXT: i32 19, label [[CLEANUP185]] +; CHECK-NEXT: i32 20, label [[CLEANUP185]] +; CHECK-NEXT: i32 21, label [[CLEANUP185]] +; CHECK-NEXT: i32 22, label [[CLEANUP185]] +; CHECK-NEXT: i32 23, label [[CLEANUP185]] +; CHECK-NEXT: i32 24, label [[CLEANUP185]] +; CHECK-NEXT: i32 25, label [[CLEANUP185]] +; CHECK-NEXT: i32 26, label [[CLEANUP185]] +; CHECK-NEXT: i32 27, label [[CLEANUP185]] +; CHECK-NEXT: i32 28, label [[CLEANUP185]] +; CHECK-NEXT: i32 29, label [[CLEANUP185]] +; CHECK-NEXT: i32 30, label [[CLEANUP185]] +; CHECK-NEXT: i32 31, label [[CLEANUP185]] +; CHECK-NEXT: i32 32, label [[CLEANUP185]] +; CHECK-NEXT: i32 33, label [[CLEANUP185]] +; CHECK-NEXT: i32 34, label [[CLEANUP185]] +; CHECK-NEXT: i32 35, label [[CLEANUP185]] +; CHECK-NEXT: i32 36, label [[CLEANUP185]] +; CHECK-NEXT: i32 37, label [[CLEANUP185]] +; CHECK-NEXT: i32 38, label [[CLEANUP185]] +; CHECK-NEXT: i32 39, label [[CLEANUP185]] +; CHECK-NEXT: i32 40, label [[CLEANUP185]] +; CHECK-NEXT: i32 41, label [[CLEANUP185]] +; CHECK-NEXT: i32 42, label [[CLEANUP185]] +; CHECK-NEXT: i32 43, label [[CLEANUP185]] +; CHECK-NEXT: i32 44, label [[CLEANUP185]] +; CHECK-NEXT: i32 45, label [[CLEANUP185]] +; CHECK-NEXT: i32 46, label [[CLEANUP185]] +; CHECK-NEXT: i32 47, label [[CLEANUP185]] +; CHECK-NEXT: i32 48, label [[CLEANUP185]] +; CHECK-NEXT: i32 49, label [[CLEANUP185]] +; CHECK-NEXT: i32 50, label [[CLEANUP185]] +; CHECK-NEXT: i32 51, label [[CLEANUP185]] +; CHECK-NEXT: i32 52, label [[CLEANUP185]] +; CHECK-NEXT: i32 53, label [[CLEANUP185]] +; CHECK-NEXT: i32 54, label [[CLEANUP185]] +; CHECK-NEXT: i32 55, label [[CLEANUP185]] +; CHECK-NEXT: i32 56, label [[CLEANUP185]] +; CHECK-NEXT: i32 57, label [[DO_ACTION]] +; CHECK-NEXT: i32 58, label [[CLEANUP185]] +; CHECK-NEXT: i32 59, label [[CLEANUP185]] +; CHECK-NEXT: i32 60, label [[DO_ACTION]] +; CHECK-NEXT: i32 61, label [[DO_ACTION]] +; CHECK-NEXT: i32 62, label [[CLEANUP185]] +; CHECK-NEXT: i32 70, label [[SW_BB175:%.*]] +; CHECK-NEXT: i32 64, label [[CLEANUP185]] +; CHECK-NEXT: i32 65, label [[DO_ACTION]] +; CHECK-NEXT: i32 66, label [[DO_ACTION]] +; CHECK-NEXT: i32 67, label [[CLEANUP185]] +; CHECK-NEXT: i32 72, label [[CLEANUP185]] +; CHECK-NEXT: i32 69, label [[DO_ACTION]] +; CHECK-NEXT: i32 71, label [[CLEANUP185]] +; CHECK-NEXT: ] +; CHECK: yy_get_previous_state.exit.loopexit: +; CHECK-NEXT: br label [[YY_FIND_ACTION_BACKEDGE:%.*]] +; CHECK: yy_find_action.backedge: +; CHECK-NEXT: [[YY_BP_1_BE:%.*]] = phi ptr [ [[ADD_PTR_I49:%.*]], [[SW_BB175]] ], [ null, [[YY_GET_PREVIOUS_STATE_EXIT_LOOPEXIT:%.*]] ] +; CHECK-NEXT: [[YY_CP_2_BE:%.*]] = phi ptr [ [[ARRAYIDX178:%.*]], [[SW_BB175]] ], [ null, [[YY_GET_PREVIOUS_STATE_EXIT_LOOPEXIT]] ] +; CHECK-NEXT: br label [[DO_ACTION]] +; CHECK: sw.bb175: +; CHECK-NEXT: [[ARRAYIDX178]] = getelementptr i8, ptr null, i64 0 +; CHECK-NEXT: [[ADD_PTR_I49]] = getelementptr i8, ptr null, i64 [[IDX_EXT_I48_PRE_PHI]] +; CHECK-NEXT: [[CMP5_I50:%.*]] = icmp ult ptr [[ADD_PTR_I49]], [[ARRAYIDX178]] +; CHECK-NEXT: br label [[YY_FIND_ACTION_BACKEDGE]] +; CHECK: sw.default: +; CHECK-NEXT: unreachable +; CHECK: cleanup185: +; CHECK-NEXT: ret i32 0 +; +entry: + br label %do_action + +do_action: + switch i32 0, label %sw.default [ + i32 1, label %cleanup185 + i32 2, label %cleanup185 + i32 0, label %cleanup185 + i32 4, label %cleanup185 + i32 5, label %cleanup185 + i32 6, label %cleanup185 + i32 7, label %cleanup185 + i32 8, label %cleanup185 + i32 9, label %cleanup185 + i32 10, label %cleanup185 + i32 11, label %cleanup185 + i32 12, label %cleanup185 + i32 13, label %cleanup185 + i32 14, label %cleanup185 + i32 15, label %cleanup185 + i32 16, label %cleanup185 + i32 17, label %cleanup185 + i32 18, label %cleanup185 + i32 19, label %cleanup185 + i32 20, label %cleanup185 + i32 21, label %cleanup185 + i32 22, label %cleanup185 + i32 23, label %cleanup185 + i32 24, label %cleanup185 + i32 25, label %cleanup185 + i32 26, label %cleanup185 + i32 27, label %cleanup185 + i32 28, label %cleanup185 + i32 29, label %cleanup185 + i32 30, label %cleanup185 + i32 31, label %cleanup185 + i32 32, label %cleanup185 + i32 33, label %cleanup185 + i32 34, label %cleanup185 + i32 35, label %cleanup185 + i32 36, label %cleanup185 + i32 37, label %cleanup185 + i32 38, label %cleanup185 + i32 39, label %cleanup185 + i32 40, label %cleanup185 + i32 41, label %cleanup185 + i32 42, label %cleanup185 + i32 43, label %cleanup185 + i32 44, label %cleanup185 + i32 45, label %cleanup185 + i32 46, label %cleanup185 + i32 47, label %cleanup185 + i32 48, label %cleanup185 + i32 49, label %cleanup185 + i32 50, label %cleanup185 + i32 51, label %cleanup185 + i32 52, label %cleanup185 + i32 53, label %cleanup185 + i32 54, label %cleanup185 + i32 55, label %cleanup185 + i32 56, label %cleanup185 + i32 57, label %do_action + i32 58, label %cleanup185 + i32 59, label %cleanup185 + i32 60, label %do_action + i32 61, label %do_action + i32 62, label %cleanup185 + i32 70, label %sw.bb175 + i32 64, label %cleanup185 + i32 65, label %do_action + i32 66, label %do_action + i32 67, label %cleanup185 + i32 72, label %cleanup185 + i32 69, label %do_action + i32 71, label %cleanup185 + ] + +yy_get_previous_state.exit.loopexit: + br label %yy_find_action.backedge + +yy_find_action.backedge: + %yy_bp.1.be = phi ptr [ %add.ptr.i49, %sw.bb175 ], [ null, %yy_get_previous_state.exit.loopexit ] + %yy_cp.2.be = phi ptr [ %arrayidx178, %sw.bb175 ], [ null, %yy_get_previous_state.exit.loopexit ] + br label %do_action + +sw.bb175: + %arrayidx178 = getelementptr i8, ptr null, i64 0 + %add.ptr.i49 = getelementptr i8, ptr null, i64 %idx.ext.i48.pre-phi + %cmp5.i50 = icmp ult ptr %add.ptr.i49, %arrayidx178 + br label %yy_find_action.backedge + +sw.default: + unreachable + +cleanup185: + ret i32 0 +} diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/trunc-to-large-than-bw.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/trunc-to-large-than-bw.ll new file mode 100644 index 0000000000000000000000000000000000000000..2d69c7c984dcd2c6b6675dcedf738cd1317a41fd --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/trunc-to-large-than-bw.ll @@ -0,0 +1,40 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -mtriple=riscv64-unknown-linux-gnu -mattr="+v" < %s | FileCheck %s + +@c = global [12 x i64] zeroinitializer + +define i32 @test() { +; CHECK-LABEL: define i32 @test( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = call <4 x i64> @llvm.experimental.vp.strided.load.v4i64.p0.i64(ptr align 8 @c, i64 24, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, i32 4) +; CHECK-NEXT: [[TMP1:%.*]] = trunc <4 x i64> [[TMP0]] to <4 x i32> +; CHECK-NEXT: [[TMP2:%.*]] = and <4 x i32> [[TMP1]], <i32 65535, i32 65535, i32 65535, i32 65535> +; CHECK-NEXT: [[TMP3:%.*]] = xor <4 x i32> [[TMP2]], <i32 65535, i32 65535, i32 65535, i32 65535> +; CHECK-NEXT: [[TMP5:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[TMP3]]) +; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.umax.i32(i32 [[TMP5]], i32 1) +; CHECK-NEXT: ret i32 [[TMP6]] +; +entry: + %0 = load i64, ptr @c, align 8 + %conv = trunc i64 %0 to i32 + %conv3 = and i32 %conv, 65535 + %conv4 = xor i32 %conv3, 65535 + %.conv4 = tail call i32 @llvm.umax.i32(i32 1, i32 %conv4) + %1 = load i64, ptr getelementptr inbounds ([12 x i64], ptr @c, i64 0, i64 3), align 8 + %conv.1 = trunc i64 %1 to i32 + %conv3.1 = and i32 %conv.1, 65535 + %conv4.1 = xor i32 %conv3.1, 65535 + %.conv4.1 = tail call i32 @llvm.umax.i32(i32 %.conv4, i32 %conv4.1) + %2 = load i64, ptr getelementptr inbounds ([12 x i64], ptr @c, i64 0, i64 6), align 8 + %conv.2 = trunc i64 %2 to i32 + %conv3.2 = and i32 %conv.2, 65535 + %conv4.2 = xor i32 %conv3.2, 65535 + %.conv4.2 = tail call i32 @llvm.umax.i32(i32 %.conv4.1, i32 %conv4.2) + %3 = load i64, ptr getelementptr inbounds ([12 x i64], ptr @c, i64 0, i64 9), align 8 + %conv.3 = trunc i64 %3 to i32 + %conv3.3 = and i32 %conv.3, 65535 + %conv4.3 = xor i32 %conv3.3, 65535 + %.conv4.3 = tail call i32 @llvm.umax.i32(i32 %.conv4.2, i32 %conv4.3) + ret i32 %.conv4.3 +} diff --git a/llvm/test/Transforms/SLPVectorizer/SystemZ/ext-not-resized-op-resized.ll b/llvm/test/Transforms/SLPVectorizer/SystemZ/ext-not-resized-op-resized.ll new file mode 100644 index 0000000000000000000000000000000000000000..a7bb272b44dc4b9692a026424d705e628f0de0ad --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/SystemZ/ext-not-resized-op-resized.ll @@ -0,0 +1,48 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -mtriple=systemz-unknown -mcpu=z13 < %s | FileCheck %s + +define void @test(i64 %0, i1 %.cmp.i.2, i1 %1, ptr %a) { +; CHECK-LABEL: define void @test( +; CHECK-SAME: i64 [[TMP0:%.*]], i1 [[DOTCMP_I_2:%.*]], i1 [[TMP1:%.*]], ptr [[A:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[TMP3:%.*]] = insertelement <4 x i64> poison, i64 [[TMP0]], i32 0 +; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <4 x i64> [[TMP3]], <4 x i64> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = lshr <4 x i64> [[TMP4]], <i64 63, i64 63, i64 63, i64 63> +; CHECK-NEXT: [[TMP6:%.*]] = insertelement <4 x i1> poison, i1 [[DOTCMP_I_2]], i32 0 +; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x i1> [[TMP6]], i1 [[TMP1]], i32 1 +; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <4 x i1> [[TMP7]], <4 x i1> poison, <4 x i32> <i32 0, i32 0, i32 1, i32 0> +; CHECK-NEXT: [[TMP9:%.*]] = shufflevector <4 x i1> [[TMP7]], <4 x i1> poison, <4 x i32> <i32 1, i32 1, i32 0, i32 1> +; CHECK-NEXT: [[TMP10:%.*]] = trunc <4 x i64> [[TMP5]] to <4 x i1> +; CHECK-NEXT: [[TMP11:%.*]] = select <4 x i1> [[TMP9]], <4 x i1> [[TMP10]], <4 x i1> [[TMP8]] +; CHECK-NEXT: [[TMP12:%.*]] = zext <4 x i1> [[TMP11]] to <4 x i32> +; CHECK-NEXT: [[TMP13:%.*]] = xor <4 x i32> [[TMP12]], <i32 1, i32 1, i32 1, i32 1> +; CHECK-NEXT: [[TMP14:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP13]]) +; CHECK-NEXT: store i32 [[TMP14]], ptr [[A]], align 4 +; CHECK-NEXT: ret void +; + %.lobit.i.2 = lshr i64 %0, 63 + %3 = zext i1 %.cmp.i.2 to i64 + %4 = select i1 %1, i64 %.lobit.i.2, i64 %3 + %5 = trunc i64 %4 to i32 + %6 = xor i32 %5, 1 + %.lobit.i.3 = lshr i64 %0, 63 + %7 = zext i1 %.cmp.i.2 to i64 + %8 = select i1 %1, i64 %.lobit.i.3, i64 %7 + %9 = trunc i64 %8 to i32 + %10 = xor i32 %9, 1 + %11 = or i32 %10, %6 + %.lobit.i.4 = lshr i64 %0, 63 + %12 = zext i1 %1 to i64 + %13 = select i1 %.cmp.i.2, i64 %.lobit.i.4, i64 %12 + %14 = trunc i64 %13 to i32 + %15 = xor i32 %14, 1 + %16 = or i32 %15, %11 + %.lobit.i.5 = lshr i64 %0, 63 + %17 = zext i1 %.cmp.i.2 to i64 + %18 = select i1 %1, i64 %.lobit.i.5, i64 %17 + %19 = trunc i64 %18 to i32 + %20 = xor i32 %19, 1 + %21 = or i32 %20, %16 + store i32 %21, ptr %a, align 4 + ret void +} + diff --git a/llvm/test/Transforms/SLPVectorizer/SystemZ/minbitwidth-root-trunc.ll b/llvm/test/Transforms/SLPVectorizer/SystemZ/minbitwidth-root-trunc.ll new file mode 100644 index 0000000000000000000000000000000000000000..7b4e2b0ce9112e514d56037ff816f80499356d13 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/SystemZ/minbitwidth-root-trunc.ll @@ -0,0 +1,40 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -mtriple=systemz -mcpu=z15 %s | FileCheck %s + +define void @test(ptr %a, i8 %0, i16 %b.promoted.i) { +; CHECK-LABEL: define void @test( +; CHECK-SAME: ptr [[A:%.*]], i8 [[TMP0:%.*]], i16 [[B_PROMOTED_I:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP0]] to i128 +; CHECK-NEXT: [[TMP3:%.*]] = insertelement <4 x i16> poison, i16 [[B_PROMOTED_I]], i32 0 +; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <4 x i16> [[TMP3]], <4 x i16> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = insertelement <4 x i128> poison, i128 [[TMP2]], i32 0 +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <4 x i128> [[TMP5]], <4 x i128> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP7:%.*]] = trunc <4 x i128> [[TMP6]] to <4 x i16> +; CHECK-NEXT: [[TMP8:%.*]] = or <4 x i16> [[TMP4]], [[TMP7]] +; CHECK-NEXT: [[TMP9:%.*]] = call i16 @llvm.vector.reduce.and.v4i16(<4 x i16> [[TMP8]]) +; CHECK-NEXT: [[TMP11:%.*]] = zext i16 [[TMP9]] to i64 +; CHECK-NEXT: [[OP_RDX:%.*]] = and i64 [[TMP11]], 1 +; CHECK-NEXT: store i64 [[OP_RDX]], ptr [[A]], align 8 +; CHECK-NEXT: ret void +; + %2 = zext i8 %0 to i128 + %3 = zext i16 %b.promoted.i to i128 + %4 = or i128 %3, %2 + %5 = trunc i128 %4 to i64 + %6 = and i64 %5, 1 + %7 = zext i16 %b.promoted.i to i128 + %8 = or i128 %7, %2 + %9 = trunc i128 %8 to i64 + %10 = and i64 %6, %9 + %11 = zext i16 %b.promoted.i to i128 + %12 = or i128 %11, %2 + %13 = trunc i128 %12 to i64 + %14 = and i64 %10, %13 + %15 = zext i16 %b.promoted.i to i128 + %16 = or i128 %15, %2 + %17 = trunc i128 %16 to i64 + %18 = and i64 %14, %17 + store i64 %18, ptr %a, align 8 + ret void +} + diff --git a/llvm/test/Transforms/SLPVectorizer/X86/PR35777.ll b/llvm/test/Transforms/SLPVectorizer/X86/PR35777.ll index 4565d4928ba4ad14e13ad28013d158118362f17a..05511f843a68fa6d33f68052b130cc782c7367b5 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/PR35777.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/PR35777.ll @@ -15,11 +15,12 @@ define { i64, i64 } @patatino(double %arg) { ; CHECK-NEXT: [[TMP6:%.*]] = load <2 x double>, ptr getelementptr inbounds ([6 x double], ptr @global, i64 0, i64 4), align 16 ; CHECK-NEXT: [[TMP7:%.*]] = fadd <2 x double> [[TMP6]], [[TMP5]] ; CHECK-NEXT: [[TMP8:%.*]] = fptosi <2 x double> [[TMP7]] to <2 x i32> -; CHECK-NEXT: [[TMP9:%.*]] = sext <2 x i32> [[TMP8]] to <2 x i64> -; CHECK-NEXT: [[TMP10:%.*]] = extractelement <2 x i64> [[TMP9]], i32 0 +; CHECK-NEXT: [[TMP9:%.*]] = extractelement <2 x i32> [[TMP8]], i32 0 +; CHECK-NEXT: [[TMP10:%.*]] = sext i32 [[TMP9]] to i64 ; CHECK-NEXT: [[T16:%.*]] = insertvalue { i64, i64 } undef, i64 [[TMP10]], 0 -; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x i64> [[TMP9]], i32 1 -; CHECK-NEXT: [[T17:%.*]] = insertvalue { i64, i64 } [[T16]], i64 [[TMP11]], 1 +; CHECK-NEXT: [[TMP11:%.*]] = extractelement <2 x i32> [[TMP8]], i32 1 +; CHECK-NEXT: [[TMP12:%.*]] = sext i32 [[TMP11]] to i64 +; CHECK-NEXT: [[T17:%.*]] = insertvalue { i64, i64 } [[T16]], i64 [[TMP12]], 1 ; CHECK-NEXT: ret { i64, i64 } [[T17]] ; bb: diff --git a/llvm/test/Transforms/SLPVectorizer/X86/call-arg-reduced-by-minbitwidth.ll b/llvm/test/Transforms/SLPVectorizer/X86/call-arg-reduced-by-minbitwidth.ll new file mode 100644 index 0000000000000000000000000000000000000000..27c9655f94d3c5c41dbec2f24a5983fe92b3c16b --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/call-arg-reduced-by-minbitwidth.ll @@ -0,0 +1,82 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -mtriple=x86_64-pc-windows-msvc19.34.0 < %s | FileCheck %s + +define void @test(ptr %0, i8 %1, i1 %cmp12.i) { +; CHECK-LABEL: define void @test( +; CHECK-SAME: ptr [[TMP0:%.*]], i8 [[TMP1:%.*]], i1 [[CMP12_I:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP2:%.*]] = insertelement <8 x i1> poison, i1 [[CMP12_I]], i32 0 +; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <8 x i1> [[TMP2]], <8 x i1> poison, <8 x i32> zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = insertelement <8 x i8> poison, i8 [[TMP1]], i32 0 +; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <8 x i8> [[TMP4]], <8 x i8> poison, <8 x i32> zeroinitializer +; CHECK-NEXT: br label [[PRE:%.*]] +; CHECK: pre: +; CHECK-NEXT: [[TMP6:%.*]] = zext <8 x i8> [[TMP5]] to <8 x i32> +; CHECK-NEXT: [[TMP7:%.*]] = call <8 x i32> @llvm.umax.v8i32(<8 x i32> [[TMP6]], <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>) +; CHECK-NEXT: [[TMP8:%.*]] = trunc <8 x i32> [[TMP7]] to <8 x i8> +; CHECK-NEXT: [[TMP9:%.*]] = add <8 x i8> [[TMP8]], <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> +; CHECK-NEXT: [[TMP10:%.*]] = select <8 x i1> [[TMP3]], <8 x i8> [[TMP9]], <8 x i8> [[TMP5]] +; CHECK-NEXT: store <8 x i8> [[TMP10]], ptr [[TMP0]], align 1 +; CHECK-NEXT: br label [[PRE]] +; +entry: + %idx11 = getelementptr i8, ptr %0, i64 1 + %idx22 = getelementptr i8, ptr %0, i64 2 + %idx33 = getelementptr i8, ptr %0, i64 3 + %idx44 = getelementptr i8, ptr %0, i64 4 + %idx55 = getelementptr i8, ptr %0, i64 5 + %idx66 = getelementptr i8, ptr %0, i64 6 + %idx77 = getelementptr i8, ptr %0, i64 7 + br label %pre + +pre: + %conv.i = zext i8 %1 to i32 + %2 = tail call i32 @llvm.umax.i32(i32 %conv.i, i32 1) + %.sroa.speculated.i = add i32 %2, 1 + %intensity.0.i = select i1 %cmp12.i, i32 %.sroa.speculated.i, i32 %conv.i + %conv14.i = trunc i32 %intensity.0.i to i8 + store i8 %conv14.i, ptr %0, align 1 + %conv.i.1 = zext i8 %1 to i32 + %3 = tail call i32 @llvm.umax.i32(i32 %conv.i.1, i32 1) + %ss1 = add i32 %3, 1 + %ii1 = select i1 %cmp12.i, i32 %ss1, i32 %conv.i.1 + %conv14.i.1 = trunc i32 %ii1 to i8 + store i8 %conv14.i.1, ptr %idx11, align 1 + %conv.i.2 = zext i8 %1 to i32 + %4 = tail call i32 @llvm.umax.i32(i32 %conv.i.2, i32 1) + %ss2 = add i32 %4, 1 + %ii2 = select i1 %cmp12.i, i32 %ss2, i32 %conv.i.2 + %conv14.i.2 = trunc i32 %ii2 to i8 + store i8 %conv14.i.2, ptr %idx22, align 1 + %conv.i.3 = zext i8 %1 to i32 + %5 = tail call i32 @llvm.umax.i32(i32 %conv.i.3, i32 1) + %ss3 = add i32 %5, 1 + %ii3 = select i1 %cmp12.i, i32 %ss3, i32 %conv.i.3 + %conv14.i.3 = trunc i32 %ii3 to i8 + store i8 %conv14.i.3, ptr %idx33, align 1 + %conv.i.4 = zext i8 %1 to i32 + %6 = tail call i32 @llvm.umax.i32(i32 %conv.i.4, i32 1) + %ss4 = add i32 %6, 1 + %ii4 = select i1 %cmp12.i, i32 %ss4, i32 %conv.i.4 + %conv14.i.4 = trunc i32 %ii4 to i8 + store i8 %conv14.i.4, ptr %idx44, align 1 + %conv.i.5 = zext i8 %1 to i32 + %7 = tail call i32 @llvm.umax.i32(i32 %conv.i.5, i32 1) + %ss5 = add i32 %7, 1 + %ii5 = select i1 %cmp12.i, i32 %ss5, i32 %conv.i.5 + %conv14.i.5 = trunc i32 %ii5 to i8 + store i8 %conv14.i.5, ptr %idx55, align 1 + %conv.i.6 = zext i8 %1 to i32 + %8 = tail call i32 @llvm.umax.i32(i32 %conv.i.6, i32 1) + %ss6 = add i32 %8, 1 + %ii6 = select i1 %cmp12.i, i32 %ss6, i32 %conv.i.6 + %conv14.i.6 = trunc i32 %ii6 to i8 + store i8 %conv14.i.6, ptr %idx66, align 1 + %conv.i.7 = zext i8 %1 to i32 + %9 = tail call i32 @llvm.umax.i32(i32 %conv.i.7, i32 1) + %ss7 = add i32 %9, 1 + %ii7 = select i1 %cmp12.i, i32 %ss7, i32 %conv.i.7 + %conv14.i.7 = trunc i32 %ii7 to i8 + store i8 %conv14.i.7, ptr %idx77, align 1 + br label %pre +} diff --git a/llvm/test/Transforms/SLPVectorizer/X86/cmp-after-intrinsic-call-minbitwidth.ll b/llvm/test/Transforms/SLPVectorizer/X86/cmp-after-intrinsic-call-minbitwidth.ll new file mode 100644 index 0000000000000000000000000000000000000000..a05d4fdd6315b5b77d18c2127cd342665efa1781 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/cmp-after-intrinsic-call-minbitwidth.ll @@ -0,0 +1,40 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt --passes=slp-vectorizer -S -mtriple=x86_64-unknown-linux-gnu -mcpu=cascadelake < %s | FileCheck %s + +define void @test() { +; CHECK-LABEL: define void @test( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> zeroinitializer, <2 x i32> zeroinitializer) +; CHECK-NEXT: [[TMP1:%.*]] = select <2 x i1> zeroinitializer, <2 x i32> zeroinitializer, <2 x i32> [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i32> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[ADD:%.*]] = extractelement <2 x i32> [[TMP2]], i32 1 +; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[ADD]], 0 +; CHECK-NEXT: [[ADD45:%.*]] = extractelement <2 x i32> [[TMP2]], i32 0 +; CHECK-NEXT: [[ADD152:%.*]] = or i32 [[ADD45]], [[ADD]] +; CHECK-NEXT: [[IDXPROM153:%.*]] = sext i32 [[ADD152]] to i64 +; CHECK-NEXT: [[ARRAYIDX154:%.*]] = getelementptr i8, ptr null, i64 [[IDXPROM153]] +; CHECK-NEXT: [[CALL155:%.*]] = tail call i32 null(ptr null, i32 0, ptr [[ARRAYIDX154]], i32 0) +; CHECK-NEXT: ret void +; +entry: + %conv = sext i16 0 to i32 + %cmp.i = icmp sgt i32 0, %conv + %cond.i = tail call i32 @llvm.smin.i32(i32 %conv, i32 0) + %cond5.i = select i1 %cmp.i, i32 0, i32 %cond.i + %conv43 = sext i16 0 to i32 + %cmp.i6193 = icmp sgt i32 0, %conv43 + %cond.i6194 = tail call i32 @llvm.smin.i32(i32 %conv43, i32 0) + %cond5.i6195 = select i1 %cmp.i6193, i32 0, i32 %cond.i6194 + %add = or i32 %cond5.i, 0 + %shr = ashr i32 %add, 0 + %add45 = or i32 %cond5.i6195, 0 + %add152 = or i32 %add45, %add + %idxprom153 = sext i32 %add152 to i64 + %arrayidx154 = getelementptr i8, ptr null, i64 %idxprom153 + %call155 = tail call i32 null(ptr null, i32 0, ptr %arrayidx154, i32 0) + ret void +} + +declare i32 @llvm.smin.i32(i32, i32) + diff --git a/llvm/test/Transforms/SLPVectorizer/X86/crash_netbsd_decompress.ll b/llvm/test/Transforms/SLPVectorizer/X86/crash_netbsd_decompress.ll index 12b227cbeb3d3c8fe199204f6c8413b61564da2a..a153c3ceeaf5dcbe46489fe0f10e77c379c73148 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/crash_netbsd_decompress.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/crash_netbsd_decompress.ll @@ -25,8 +25,8 @@ define i32 @fn1() { ; CHECK-NEXT: store i32 [[AND]], ptr @a, align 4 ; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <2 x i32> [[TMP0]], <2 x i32> <i32 poison, i32 0>, <2 x i32> <i32 0, i32 3> ; CHECK-NEXT: switch i32 [[AND]], label [[IF_END:%.*]] [ -; CHECK-NEXT: i32 7, label [[SAVE_STATE_AND_RETURN]] -; CHECK-NEXT: i32 0, label [[SAVE_STATE_AND_RETURN]] +; CHECK-NEXT: i32 7, label [[SAVE_STATE_AND_RETURN]] +; CHECK-NEXT: i32 0, label [[SAVE_STATE_AND_RETURN]] ; CHECK-NEXT: ] ; CHECK: if.end: ; CHECK-NEXT: br label [[SAVE_STATE_AND_RETURN]] diff --git a/llvm/test/Transforms/SLPVectorizer/X86/ext-int-reduced-not-operand.ll b/llvm/test/Transforms/SLPVectorizer/X86/ext-int-reduced-not-operand.ll new file mode 100644 index 0000000000000000000000000000000000000000..05534fa961ee46b3d100072e8f6557ba08443c47 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/ext-int-reduced-not-operand.ll @@ -0,0 +1,34 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -slp-threshold=-99999 < %s | FileCheck %s + +define i64 @wombat() { +; CHECK-LABEL: define i64 @wombat() { +; CHECK-NEXT: bb: +; CHECK-NEXT: br label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: br label [[BB2]] +; CHECK: bb2: +; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ 0, [[BB1:%.*]] ] +; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x i32> poison, i32 [[PHI]], i32 0 +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x i32> [[TMP0]], <2 x i32> poison, <2 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = trunc <2 x i32> [[TMP1]] to <2 x i1> +; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x i1> [[TMP2]], i32 0 +; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i64 +; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i1> [[TMP2]], i32 1 +; CHECK-NEXT: [[TMP6:%.*]] = zext i1 [[TMP5]] to i64 +; CHECK-NEXT: [[OR:%.*]] = or i64 [[TMP4]], [[TMP6]] +; CHECK-NEXT: ret i64 [[OR]] +; +bb: + br label %bb2 + +bb1: + br label %bb2 + +bb2: + %phi = phi i32 [ 0, %bb ], [ 0, %bb1 ] + %zext = zext i32 %phi to i64 + %sext = sext i32 %phi to i64 + %or = or i64 %zext, %sext + ret i64 %or +} diff --git a/llvm/test/Transforms/SLPVectorizer/X86/gather-nodes-different-bb.ll b/llvm/test/Transforms/SLPVectorizer/X86/gather-nodes-different-bb.ll new file mode 100644 index 0000000000000000000000000000000000000000..2acbe89b97757f0a1e450ced6869421a56ea4533 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/gather-nodes-different-bb.ll @@ -0,0 +1,24 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -passes=slp-vectorizer -mtriple=x86_64-unknown-linux -mattr="-avx512pf,+avx512f,+avx512bw" -slp-threshold=-100 < %s | FileCheck %s + +define i1 @foo(i32 %a) { +; CHECK-LABEL: @foo( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = sub nsw i32 0, [[A:%.*]] +; CHECK-NEXT: br label [[BB4:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[LOCAL:%.*]] = sub nsw i32 0, 0 +; CHECK-NEXT: [[INS1:%.*]] = insertelement <2 x i32> poison, i32 [[TMP0]], i32 0 +; CHECK-NEXT: [[ADD:%.*]] = icmp eq i32 [[TMP0]], [[LOCAL]] +; CHECK-NEXT: ret i1 [[ADD]] +; +entry: + %0 = sub nsw i32 0, %a + br label %bb1 + +bb1: + %local = sub nsw i32 0, 0 + %ins1 = insertelement <2 x i32> poison, i32 %0, i32 0 + %add = icmp eq i32 %0, %local + ret i1 %add +} diff --git a/llvm/test/Transforms/SLPVectorizer/X86/int-bitcast-minbitwidth.ll b/llvm/test/Transforms/SLPVectorizer/X86/int-bitcast-minbitwidth.ll index a0af8e36b36c7999ee8497af3bd12ebe241eb0bf..f4a471493f1b3fa6b0ed0a0e0d2e8c4248d378c6 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/int-bitcast-minbitwidth.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/int-bitcast-minbitwidth.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 -; RUN: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -slp-threshold=-3 < %s | FileCheck %s +; RUN: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu -slp-threshold=-9 < %s | FileCheck %s define void @t(i64 %v) { ; CHECK-LABEL: define void @t( @@ -7,10 +7,9 @@ define void @t(i64 %v) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x i64> poison, i64 [[V]], i32 0 ; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i64> [[TMP0]], <4 x i64> poison, <4 x i32> zeroinitializer -; CHECK-NEXT: [[TMP2:%.*]] = trunc <4 x i64> [[TMP1]] to <4 x i16> -; CHECK-NEXT: [[TMP3:%.*]] = mul <4 x i16> [[TMP2]], <i16 5, i16 6, i16 3, i16 2> -; CHECK-NEXT: [[TMP4:%.*]] = call i16 @llvm.vector.reduce.or.v4i16(<4 x i16> [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = sext i16 [[TMP4]] to i32 +; CHECK-NEXT: [[TMP2:%.*]] = trunc <4 x i64> [[TMP1]] to <4 x i32> +; CHECK-NEXT: [[TMP3:%.*]] = mul <4 x i32> [[TMP2]], <i32 5, i32 6, i32 3, i32 2> +; CHECK-NEXT: [[TMP5:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP3]]) ; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[TMP5]], 65535 ; CHECK-NEXT: store i32 [[TMP6]], ptr null, align 4 ; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-icmp-to-trunc.ll b/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-icmp-to-trunc.ll new file mode 100644 index 0000000000000000000000000000000000000000..fc28d7ab4ee74614b3f49e0da865e4d6f28c68bf --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-icmp-to-trunc.ll @@ -0,0 +1,75 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux -mcpu=cascadelake < %s | FileCheck %s + +define i1 @test(ptr noalias %0, i64 %1, ptr noalias %p, ptr %p1) { +; CHECK-LABEL: define i1 @test( +; CHECK-SAME: ptr noalias [[TMP0:%.*]], i64 [[TMP1:%.*]], ptr noalias [[P:%.*]], ptr [[P1:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: newFuncRoot: +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 16 +; CHECK-NEXT: [[BF_LOAD_I1336:%.*]] = load i24, ptr [[TMP2]], align 16 +; CHECK-NEXT: [[AND_I_I_I1342:%.*]] = and i64 [[TMP1]], -16 +; CHECK-NEXT: [[TMP3:%.*]] = inttoptr i64 [[AND_I_I_I1342]] to ptr +; CHECK-NEXT: store ptr [[TMP3]], ptr [[P]], align 8 +; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 16 +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[TMP4]], i64 16 +; CHECK-NEXT: [[BF_LOAD_I1345:%.*]] = load i24, ptr [[TMP5]], align 16 +; CHECK-NEXT: [[TMP6:%.*]] = insertelement <2 x i24> poison, i24 [[BF_LOAD_I1336]], i32 0 +; CHECK-NEXT: [[TMP7:%.*]] = insertelement <2 x i24> [[TMP6]], i24 [[BF_LOAD_I1345]], i32 1 +; CHECK-NEXT: [[TMP8:%.*]] = and <2 x i24> [[TMP7]], <i24 255, i24 255> +; CHECK-NEXT: [[TMP9:%.*]] = icmp eq <2 x i24> [[TMP8]], <i24 24, i24 24> +; CHECK-NEXT: [[TMP10:%.*]] = select <2 x i1> [[TMP9]], <2 x i24> <i24 23, i24 23>, <2 x i24> [[TMP8]] +; CHECK-NEXT: [[TMP23:%.*]] = trunc <2 x i24> [[TMP10]] to <2 x i8> +; CHECK-NEXT: [[TMP11:%.*]] = zext <2 x i8> [[TMP23]] to <2 x i32> +; CHECK-NEXT: [[TMP12:%.*]] = and <2 x i32> [[TMP11]], <i32 254, i32 254> +; CHECK-NEXT: [[TMP13:%.*]] = icmp eq <2 x i32> [[TMP12]], <i32 4, i32 4> +; CHECK-NEXT: [[TMP25:%.*]] = select <2 x i1> [[TMP13]], <2 x i8> <i8 2, i8 2>, <2 x i8> [[TMP23]] +; CHECK-NEXT: [[TMP14:%.*]] = zext <2 x i8> [[TMP25]] to <2 x i32> +; CHECK-NEXT: [[TMP15:%.*]] = icmp eq <2 x i32> [[TMP14]], <i32 32, i32 32> +; CHECK-NEXT: [[TMP18:%.*]] = select <2 x i1> [[TMP15]], <2 x i8> <i8 31, i8 31>, <2 x i8> [[TMP25]] +; CHECK-NEXT: [[TMP16:%.*]] = zext <2 x i8> [[TMP18]] to <2 x i32> +; CHECK-NEXT: [[TMP17:%.*]] = icmp eq <2 x i32> [[TMP16]], <i32 54, i32 54> +; CHECK-NEXT: [[TMP21:%.*]] = select <2 x i1> [[TMP17]], <2 x i8> <i8 53, i8 53>, <2 x i8> [[TMP18]] +; CHECK-NEXT: [[TMP22:%.*]] = extractelement <2 x i8> [[TMP21]], i32 0 +; CHECK-NEXT: [[TMP19:%.*]] = zext i8 [[TMP22]] to i32 +; CHECK-NEXT: store i32 [[TMP19]], ptr [[P1]], align 4 +; CHECK-NEXT: [[TMP24:%.*]] = extractelement <2 x i8> [[TMP21]], i32 1 +; CHECK-NEXT: [[TMP20:%.*]] = zext i8 [[TMP24]] to i32 +; CHECK-NEXT: [[CMP210_NOT:%.*]] = icmp eq i32 [[TMP19]], [[TMP20]] +; CHECK-NEXT: ret i1 [[CMP210_NOT]] +; +newFuncRoot: + %2 = getelementptr inbounds i8, ptr %0, i64 16 + %bf.load.i1336 = load i24, ptr %2, align 16 + %bf.clear.i1337 = and i24 %bf.load.i1336, 255 + %and.i.i.i1342 = and i64 %1, -16 + %3 = inttoptr i64 %and.i.i.i1342 to ptr + store ptr %3, ptr %p, align 8 + %4 = load ptr, ptr %3, align 16 + %5 = getelementptr inbounds i8, ptr %4, i64 16 + %bf.load.i1345 = load i24, ptr %5, align 16 + %bf.clear.i1346 = and i24 %bf.load.i1345, 255 + %cmp182 = icmp eq i24 %bf.clear.i1337, 24 + %narrow = select i1 %cmp182, i24 23, i24 %bf.clear.i1337 + %s = zext nneg i24 %narrow to i32 + %cmp185 = icmp eq i24 %bf.clear.i1346, 24 + %narrow1790 = select i1 %cmp185, i24 23, i24 %bf.clear.i1346 + %s1139 = zext nneg i24 %narrow1790 to i32 + %6 = and i32 %s, 254 + %or.cond1132 = icmp eq i32 %6, 4 + %s1142 = select i1 %or.cond1132, i32 2, i32 %s + %7 = and i32 %s1139, 254 + %or.cond1133 = icmp eq i32 %7, 4 + %s1140 = select i1 %or.cond1133, i32 2, i32 %s1139 + %cmp198 = icmp eq i32 %s1142, 32 + %s1134 = select i1 %cmp198, i32 31, i32 %s1142 + %cmp201 = icmp eq i32 %s1140, 32 + %s1143 = select i1 %cmp201, i32 31, i32 %s1140 + %cmp204 = icmp eq i32 %s1134, 54 + %s1135 = select i1 %cmp204, i32 53, i32 %s1134 + store i32 %s1135, ptr %p1, align 4 + %cmp207 = icmp eq i32 %s1143, 54 + %s1141 = select i1 %cmp207, i32 53, i32 %s1143 + %cmp210.not = icmp eq i32 %s1135, %s1141 + ret i1 %cmp210.not +} + diff --git a/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-multiuse-with-insertelement.ll b/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-multiuse-with-insertelement.ll index 6e512fcbb739240824b8691e548cf49c40e7553f..6051638562b59b80b83b5fa9c51cc7078e5beaec 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-multiuse-with-insertelement.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-multiuse-with-insertelement.ll @@ -6,18 +6,17 @@ define void @test(i8 %0) { ; CHECK-SAME: i8 [[TMP0:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x i8> <i8 0, i8 poison>, i8 [[TMP0]], i32 1 -; CHECK-NEXT: [[TMP2:%.*]] = sext <2 x i8> [[TMP1]] to <2 x i16> -; CHECK-NEXT: [[TMP3:%.*]] = sext <2 x i16> [[TMP2]] to <2 x i32> -; CHECK-NEXT: [[TMP4:%.*]] = mul <2 x i16> [[TMP2]], zeroinitializer -; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i16> [[TMP4]], i32 0 -; CHECK-NEXT: [[TMP6:%.*]] = zext i16 [[TMP5]] to i32 -; CHECK-NEXT: [[TMP7:%.*]] = extractelement <2 x i16> [[TMP4]], i32 1 -; CHECK-NEXT: [[TMP8:%.*]] = zext i16 [[TMP7]] to i32 -; CHECK-NEXT: [[ADD:%.*]] = or i32 [[TMP6]], [[TMP8]] +; CHECK-NEXT: [[TMP2:%.*]] = sext <2 x i8> [[TMP1]] to <2 x i32> +; CHECK-NEXT: [[TMP3:%.*]] = mul <2 x i8> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x i8> [[TMP3]], i32 0 +; CHECK-NEXT: [[TMP5:%.*]] = zext i8 [[TMP4]] to i32 +; CHECK-NEXT: [[TMP6:%.*]] = extractelement <2 x i8> [[TMP3]], i32 1 +; CHECK-NEXT: [[TMP7:%.*]] = zext i8 [[TMP6]] to i32 +; CHECK-NEXT: [[ADD:%.*]] = or i32 [[TMP5]], [[TMP7]] ; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[ADD]], 1 ; CHECK-NEXT: [[CONV9:%.*]] = trunc i32 [[SHR]] to i8 ; CHECK-NEXT: store i8 [[CONV9]], ptr null, align 1 -; CHECK-NEXT: [[TMP9:%.*]] = shufflevector <2 x i32> [[TMP3]], <2 x i32> poison, <8 x i32> <i32 1, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison> +; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <2 x i32> [[TMP2]], <2 x i32> poison, <8 x i32> <i32 1, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison> ; CHECK-NEXT: ret void ; entry: diff --git a/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-node-but-not-operands.ll b/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-node-but-not-operands.ll new file mode 100644 index 0000000000000000000000000000000000000000..fcccaf202a91a133bb591a52fd3d184cbaf8c965 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-node-but-not-operands.ll @@ -0,0 +1,61 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt --passes=slp-vectorizer -S -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s + +define void @test() { +; CHECK-LABEL: define void @test() { +; CHECK-NEXT: entry: +; CHECK-NEXT: store <8 x i16> zeroinitializer, ptr null, align 2 +; CHECK-NEXT: ret void +; +entry: + %arrayidx8 = getelementptr i8, ptr null, i64 2 + %shr10 = ashr i32 0, 0 + %shr19 = lshr i32 0, 0 + %sub20 = or i32 %shr19, %shr10 + %xor21 = xor i32 %sub20, 0 + %conv22 = trunc i32 %xor21 to i16 + store i16 %conv22, ptr %arrayidx8, align 2 + %arrayidx28 = getelementptr i8, ptr null, i64 4 + %shr34 = lshr i32 0, 0 + %sub35 = or i32 %shr34, %shr10 + %xor36 = xor i32 %sub35, 0 + %conv37 = trunc i32 %xor36 to i16 + store i16 %conv37, ptr %arrayidx28, align 2 + %arrayidx43 = getelementptr i8, ptr null, i64 6 + %shr49 = lshr i32 0, 0 + %sub50 = or i32 %shr49, %shr10 + %xor51 = xor i32 %sub50, 0 + %conv52 = trunc i32 %xor51 to i16 + store i16 %conv52, ptr %arrayidx43, align 2 + %arrayidx.1 = getelementptr i8, ptr null, i64 8 + %shr.1 = lshr i32 0, 0 + %xor2.1 = xor i32 %shr.1, %shr10 + %sub3.1 = or i32 %xor2.1, 0 + %conv4.1 = trunc i32 %sub3.1 to i16 + store i16 %conv4.1, ptr %arrayidx.1, align 2 + %arrayidx8.1 = getelementptr i8, ptr null, i64 10 + %shr10.1 = ashr i32 0, 0 + %shr19.1 = lshr i32 0, 0 + %sub20.1 = or i32 %shr19.1, %shr10.1 + %xor21.1 = xor i32 %sub20.1, 0 + %conv22.1 = trunc i32 %xor21.1 to i16 + store i16 %conv22.1, ptr %arrayidx8.1, align 2 + %arrayidx28.1 = getelementptr i8, ptr null, i64 12 + %shr34.1 = lshr i32 0, 0 + %sub35.1 = or i32 %shr34.1, %shr10.1 + %xor36.1 = xor i32 %sub35.1, 0 + %conv37.1 = trunc i32 %xor36.1 to i16 + store i16 %conv37.1, ptr %arrayidx28.1, align 2 + %arrayidx43.1 = getelementptr i8, ptr null, i64 14 + %shr49.1 = lshr i32 0, 0 + %sub50.1 = or i32 %shr49.1, %shr10.1 + %xor51.1 = xor i32 %sub50.1, 0 + %conv52.1 = trunc i32 %xor51.1 to i16 + store i16 %conv52.1, ptr %arrayidx43.1, align 2 + %shr.2 = lshr i32 0, 0 + %xor2.2 = xor i32 %shr.2, %shr10.1 + %sub3.2 = or i32 %xor2.2, 0 + %conv4.2 = trunc i32 %sub3.2 to i16 + store i16 %conv4.2, ptr null, align 2 + ret void +} diff --git a/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-transformed-operand.ll b/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-transformed-operand.ll index 2c834616becc0d6b055b346c0a9bcee91e4de559..4acd63078b82ef70c54965ae28555c0a6cd2f475 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-transformed-operand.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-transformed-operand.ll @@ -6,15 +6,20 @@ define void @test(i64 %d.promoted.i) { ; CHECK-SAME: i64 [[D_PROMOTED_I:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[AND_1_I:%.*]] = and i64 0, [[D_PROMOTED_I]] +; CHECK-NEXT: [[TMP0:%.*]] = insertelement <8 x i64> <i64 0, i64 poison, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0>, i64 [[AND_1_I]], i32 1 +; CHECK-NEXT: [[TMP1:%.*]] = trunc <8 x i64> [[TMP0]] to <8 x i1> +; CHECK-NEXT: [[TMP2:%.*]] = mul <8 x i1> [[TMP1]], zeroinitializer ; CHECK-NEXT: [[AND_1_I_1:%.*]] = and i64 0, 0 -; CHECK-NEXT: [[TMP0:%.*]] = insertelement <16 x i64> <i64 0, i64 poison, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0, i64 poison, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0>, i64 [[AND_1_I_1]], i32 1 -; CHECK-NEXT: [[TMP1:%.*]] = insertelement <16 x i64> [[TMP0]], i64 [[AND_1_I]], i32 9 -; CHECK-NEXT: [[TMP2:%.*]] = trunc <16 x i64> [[TMP1]] to <16 x i1> -; CHECK-NEXT: [[TMP3:%.*]] = mul <16 x i1> [[TMP2]], zeroinitializer -; CHECK-NEXT: [[TMP4:%.*]] = call i1 @llvm.vector.reduce.or.v16i1(<16 x i1> [[TMP3]]) -; CHECK-NEXT: [[TMP5:%.*]] = zext i1 [[TMP4]] to i32 -; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[TMP5]], 0 -; CHECK-NEXT: store i32 [[TMP6]], ptr null, align 4 +; CHECK-NEXT: [[TMP3:%.*]] = insertelement <8 x i64> <i64 0, i64 poison, i64 0, i64 0, i64 0, i64 0, i64 0, i64 0>, i64 [[AND_1_I_1]], i32 1 +; CHECK-NEXT: [[TMP4:%.*]] = trunc <8 x i64> [[TMP3]] to <8 x i1> +; CHECK-NEXT: [[TMP5:%.*]] = mul <8 x i1> [[TMP4]], zeroinitializer +; CHECK-NEXT: [[TMP6:%.*]] = call i1 @llvm.vector.reduce.or.v8i1(<8 x i1> [[TMP5]]) +; CHECK-NEXT: [[TMP7:%.*]] = zext i1 [[TMP6]] to i32 +; CHECK-NEXT: [[TMP8:%.*]] = call i1 @llvm.vector.reduce.or.v8i1(<8 x i1> [[TMP2]]) +; CHECK-NEXT: [[TMP9:%.*]] = zext i1 [[TMP8]] to i32 +; CHECK-NEXT: [[OP_RDX:%.*]] = or i32 [[TMP7]], [[TMP9]] +; CHECK-NEXT: [[TMP10:%.*]] = and i32 [[OP_RDX]], 0 +; CHECK-NEXT: store i32 [[TMP10]], ptr null, align 4 ; CHECK-NEXT: ret void ; entry: diff --git a/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-user-not-min.ll b/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-user-not-min.ll new file mode 100644 index 0000000000000000000000000000000000000000..50b19d01ad58f1aa034a367212ee9dfe2f42dccd --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/minbitwidth-user-not-min.ll @@ -0,0 +1,49 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s + +define void @test(ptr %block, ptr noalias %pixels, i1 %b) { +; CHECK-LABEL: define void @test( +; CHECK-SAME: ptr [[BLOCK:%.*]], ptr noalias [[PIXELS:%.*]], i1 [[B:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x i1> <i1 true, i1 poison, i1 false, i1 false>, i1 [[B]], i32 1 +; CHECK-NEXT: [[TMP2:%.*]] = load <4 x i16>, ptr [[BLOCK]], align 2 +; CHECK-NEXT: [[TMP3:%.*]] = icmp ult <4 x i16> [[TMP2]], zeroinitializer +; CHECK-NEXT: [[TMP4:%.*]] = trunc <4 x i16> [[TMP2]] to <4 x i8> +; CHECK-NEXT: [[TMP1:%.*]] = sext <4 x i1> [[TMP0]] to <4 x i8> +; CHECK-NEXT: [[TMP5:%.*]] = select <4 x i1> [[TMP3]], <4 x i8> [[TMP4]], <4 x i8> [[TMP1]] +; CHECK-NEXT: store <4 x i8> [[TMP5]], ptr [[PIXELS]], align 1 +; CHECK-NEXT: ret void +; +entry: + %0 = load i16, ptr %block, align 2 + %tobool.not.i78 = icmp ult i16 %0, 0 + %conv.i80 = sext i1 true to i8 + %conv1.i81 = trunc i16 %0 to i8 + %retval.0.i82 = select i1 %tobool.not.i78, i8 %conv1.i81, i8 %conv.i80 + store i8 %retval.0.i82, ptr %pixels, align 1 + %arrayidx2 = getelementptr i8, ptr %block, i64 2 + %1 = load i16, ptr %arrayidx2, align 2 + %tobool.not.i73 = icmp ult i16 %1, 0 + %conv.i75 = sext i1 %b to i8 + %conv1.i76 = trunc i16 %1 to i8 + %retval.0.i77 = select i1 %tobool.not.i73, i8 %conv1.i76, i8 %conv.i75 + %arrayidx5 = getelementptr i8, ptr %pixels, i64 1 + store i8 %retval.0.i77, ptr %arrayidx5, align 1 + %arrayidx6 = getelementptr i8, ptr %block, i64 4 + %2 = load i16, ptr %arrayidx6, align 2 + %tobool.not.i68 = icmp ult i16 %2, 0 + %conv.i70 = sext i1 false to i8 + %conv1.i71 = trunc i16 %2 to i8 + %retval.0.i72 = select i1 %tobool.not.i68, i8 %conv1.i71, i8 %conv.i70 + %arrayidx9 = getelementptr i8, ptr %pixels, i64 2 + store i8 %retval.0.i72, ptr %arrayidx9, align 1 + %arrayidx10 = getelementptr i8, ptr %block, i64 6 + %3 = load i16, ptr %arrayidx10, align 2 + %tobool.not.i63 = icmp ult i16 %3, 0 + %conv.i65 = sext i1 false to i8 + %conv1.i66 = trunc i16 %3 to i8 + %retval.0.i67 = select i1 %tobool.not.i63, i8 %conv1.i66, i8 %conv.i65 + %arrayidx13 = getelementptr i8, ptr %pixels, i64 3 + store i8 %retval.0.i67, ptr %arrayidx13, align 1 + ret void +} diff --git a/llvm/test/Transforms/SLPVectorizer/X86/minimum-sizes.ll b/llvm/test/Transforms/SLPVectorizer/X86/minimum-sizes.ll index 651631de2c35ad75ef8ee80550137865061df98d..a316415dcc6b527bb326358034e50699630e2482 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/minimum-sizes.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/minimum-sizes.ll @@ -17,12 +17,15 @@ target triple = "x86_64-unknown-linux-gnu" define i8 @PR31243_zext(i8 %v0, i8 %v1, i8 %v2, i8 %v3, ptr %ptr) { ; SSE-LABEL: @PR31243_zext( ; SSE-NEXT: entry: -; SSE-NEXT: [[TMP0:%.*]] = or i8 [[V0:%.*]], 1 -; SSE-NEXT: [[TMP1:%.*]] = or i8 [[V1:%.*]], 1 -; SSE-NEXT: [[TMP2:%.*]] = zext i8 [[TMP0]] to i64 -; SSE-NEXT: [[T4:%.*]] = getelementptr inbounds i8, ptr [[PTR:%.*]], i64 [[TMP2]] -; SSE-NEXT: [[TMP3:%.*]] = zext i8 [[TMP1]] to i64 -; SSE-NEXT: [[T5:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[TMP3]] +; SSE-NEXT: [[TMP0:%.*]] = insertelement <2 x i8> poison, i8 [[V0:%.*]], i64 0 +; SSE-NEXT: [[TMP1:%.*]] = insertelement <2 x i8> [[TMP0]], i8 [[V1:%.*]], i64 1 +; SSE-NEXT: [[TMP2:%.*]] = or <2 x i8> [[TMP1]], <i8 1, i8 1> +; SSE-NEXT: [[TMP3:%.*]] = extractelement <2 x i8> [[TMP2]], i64 0 +; SSE-NEXT: [[TMP4:%.*]] = zext i8 [[TMP3]] to i64 +; SSE-NEXT: [[T4:%.*]] = getelementptr inbounds i8, ptr [[PTR:%.*]], i64 [[TMP4]] +; SSE-NEXT: [[TMP5:%.*]] = extractelement <2 x i8> [[TMP2]], i64 1 +; SSE-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i64 +; SSE-NEXT: [[T5:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[TMP6]] ; SSE-NEXT: [[T6:%.*]] = load i8, ptr [[T4]], align 1 ; SSE-NEXT: [[T7:%.*]] = load i8, ptr [[T5]], align 1 ; SSE-NEXT: [[T8:%.*]] = add i8 [[T6]], [[T7]] @@ -73,12 +76,15 @@ entry: define i8 @PR31243_sext(i8 %v0, i8 %v1, i8 %v2, i8 %v3, ptr %ptr) { ; SSE-LABEL: @PR31243_sext( ; SSE-NEXT: entry: -; SSE-NEXT: [[TMP0:%.*]] = or i8 [[V0:%.*]], 1 -; SSE-NEXT: [[TMP1:%.*]] = or i8 [[V1:%.*]], 1 -; SSE-NEXT: [[TMP2:%.*]] = sext i8 [[TMP0]] to i64 -; SSE-NEXT: [[T4:%.*]] = getelementptr inbounds i8, ptr [[PTR:%.*]], i64 [[TMP2]] -; SSE-NEXT: [[TMP3:%.*]] = sext i8 [[TMP1]] to i64 -; SSE-NEXT: [[T5:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[TMP3]] +; SSE-NEXT: [[TMP0:%.*]] = insertelement <2 x i8> poison, i8 [[V0:%.*]], i64 0 +; SSE-NEXT: [[TMP1:%.*]] = insertelement <2 x i8> [[TMP0]], i8 [[V1:%.*]], i64 1 +; SSE-NEXT: [[TMP2:%.*]] = or <2 x i8> [[TMP1]], <i8 1, i8 1> +; SSE-NEXT: [[TMP3:%.*]] = extractelement <2 x i8> [[TMP2]], i64 0 +; SSE-NEXT: [[TMP4:%.*]] = sext i8 [[TMP3]] to i64 +; SSE-NEXT: [[T4:%.*]] = getelementptr inbounds i8, ptr [[PTR:%.*]], i64 [[TMP4]] +; SSE-NEXT: [[TMP5:%.*]] = extractelement <2 x i8> [[TMP2]], i64 1 +; SSE-NEXT: [[TMP6:%.*]] = sext i8 [[TMP5]] to i64 +; SSE-NEXT: [[T5:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[TMP6]] ; SSE-NEXT: [[T6:%.*]] = load i8, ptr [[T4]], align 1 ; SSE-NEXT: [[T7:%.*]] = load i8, ptr [[T5]], align 1 ; SSE-NEXT: [[T8:%.*]] = add i8 [[T6]], [[T7]] @@ -89,13 +95,12 @@ define i8 @PR31243_sext(i8 %v0, i8 %v1, i8 %v2, i8 %v3, ptr %ptr) { ; AVX-NEXT: [[TMP0:%.*]] = insertelement <2 x i8> poison, i8 [[V0:%.*]], i64 0 ; AVX-NEXT: [[TMP1:%.*]] = insertelement <2 x i8> [[TMP0]], i8 [[V1:%.*]], i64 1 ; AVX-NEXT: [[TMP2:%.*]] = or <2 x i8> [[TMP1]], <i8 1, i8 1> -; AVX-NEXT: [[TMP3:%.*]] = sext <2 x i8> [[TMP2]] to <2 x i16> -; AVX-NEXT: [[TMP4:%.*]] = extractelement <2 x i16> [[TMP3]], i64 0 -; AVX-NEXT: [[TMP5:%.*]] = sext i16 [[TMP4]] to i64 -; AVX-NEXT: [[T4:%.*]] = getelementptr inbounds i8, ptr [[PTR:%.*]], i64 [[TMP5]] -; AVX-NEXT: [[TMP6:%.*]] = extractelement <2 x i16> [[TMP3]], i64 1 -; AVX-NEXT: [[TMP7:%.*]] = sext i16 [[TMP6]] to i64 -; AVX-NEXT: [[T5:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[TMP7]] +; AVX-NEXT: [[TMP3:%.*]] = extractelement <2 x i8> [[TMP2]], i64 0 +; AVX-NEXT: [[TMP4:%.*]] = sext i8 [[TMP3]] to i64 +; AVX-NEXT: [[T4:%.*]] = getelementptr inbounds i8, ptr [[PTR:%.*]], i64 [[TMP4]] +; AVX-NEXT: [[TMP5:%.*]] = extractelement <2 x i8> [[TMP2]], i64 1 +; AVX-NEXT: [[TMP6:%.*]] = sext i8 [[TMP5]] to i64 +; AVX-NEXT: [[T5:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[TMP6]] ; AVX-NEXT: [[T6:%.*]] = load i8, ptr [[T4]], align 1 ; AVX-NEXT: [[T7:%.*]] = load i8, ptr [[T5]], align 1 ; AVX-NEXT: [[T8:%.*]] = add i8 [[T6]], [[T7]] diff --git a/llvm/test/Transforms/SLPVectorizer/X86/phi-node-bitwidt-op-not.ll b/llvm/test/Transforms/SLPVectorizer/X86/phi-node-bitwidt-op-not.ll new file mode 100644 index 0000000000000000000000000000000000000000..f376ca71c776935ee7337a2b6f614a88127730c3 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/phi-node-bitwidt-op-not.ll @@ -0,0 +1,95 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S -passes=slp-vectorizer -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s + +define i32 @test(ptr %b, ptr %c, i32 %0, ptr %a, i1 %tobool3.not) { +; CHECK-LABEL: define i32 @test( +; CHECK-SAME: ptr [[B:%.*]], ptr [[C:%.*]], i32 [[TMP0:%.*]], ptr [[A:%.*]], i1 [[TOBOOL3_NOT:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[TOBOOL3_NOT]], label [[BB1:%.*]], label [[BB2:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i32> poison, i32 [[TMP0]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP3:%.*]] = ashr <4 x i32> [[TMP2]], <i32 16, i32 16, i32 16, i32 16> +; CHECK-NEXT: [[TMP4:%.*]] = icmp slt <4 x i32> [[TMP3]], [[TMP2]] +; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i1> [[TMP4]] to <4 x i16> +; CHECK-NEXT: br label [[BB3:%.*]] +; CHECK: bb2: +; CHECK-NEXT: [[TMP6:%.*]] = insertelement <4 x i32> poison, i32 [[TMP0]], i32 0 +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <4 x i32> [[TMP6]], <4 x i32> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP8:%.*]] = icmp sgt <4 x i32> [[TMP7]], zeroinitializer +; CHECK-NEXT: [[TMP9:%.*]] = zext <4 x i1> [[TMP8]] to <4 x i32> +; CHECK-NEXT: [[TMP10:%.*]] = insertelement <4 x i1> poison, i1 [[TOBOOL3_NOT]], i32 0 +; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <4 x i1> [[TMP10]], <4 x i1> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP12:%.*]] = select <4 x i1> [[TMP11]], <4 x i32> [[TMP7]], <4 x i32> [[TMP9]] +; CHECK-NEXT: [[TMP13:%.*]] = shl <4 x i32> [[TMP12]], <i32 16, i32 16, i32 16, i32 16> +; CHECK-NEXT: [[TMP14:%.*]] = ashr <4 x i32> [[TMP13]], <i32 16, i32 16, i32 16, i32 16> +; CHECK-NEXT: [[TMP15:%.*]] = trunc <4 x i32> [[TMP14]] to <4 x i16> +; CHECK-NEXT: br i1 true, label [[BB3]], label [[BB2]] +; CHECK: bb3: +; CHECK-NEXT: [[TMP16:%.*]] = phi <4 x i16> [ [[TMP5]], [[BB1]] ], [ [[TMP15]], [[BB2]] ] +; CHECK-NEXT: [[TMP17:%.*]] = extractelement <4 x i16> [[TMP16]], i32 0 +; CHECK-NEXT: [[TMP18:%.*]] = sext i16 [[TMP17]] to i32 +; CHECK-NEXT: store i32 [[TMP18]], ptr [[B]], align 16 +; CHECK-NEXT: [[TMP19:%.*]] = extractelement <4 x i16> [[TMP16]], i32 1 +; CHECK-NEXT: [[TMP20:%.*]] = sext i16 [[TMP19]] to i32 +; CHECK-NEXT: store i32 [[TMP20]], ptr [[A]], align 8 +; CHECK-NEXT: [[TMP21:%.*]] = extractelement <4 x i16> [[TMP16]], i32 2 +; CHECK-NEXT: [[TMP22:%.*]] = sext i16 [[TMP21]] to i32 +; CHECK-NEXT: store i32 [[TMP22]], ptr [[C]], align 16 +; CHECK-NEXT: [[TMP23:%.*]] = extractelement <4 x i16> [[TMP16]], i32 3 +; CHECK-NEXT: [[TMP24:%.*]] = sext i16 [[TMP23]] to i32 +; CHECK-NEXT: store i32 [[TMP24]], ptr [[B]], align 8 +; CHECK-NEXT: ret i32 0 +; +entry: + br i1 %tobool3.not, label %bb1, label %bb2 + +bb1: + %conv1.i.us = ashr i32 %0, 16 + %cmp2.i.us = icmp slt i32 %conv1.i.us, %0 + %sext26.us = zext i1 %cmp2.i.us to i32 + %conv1.i.us.5 = ashr i32 %0, 16 + %cmp2.i.us.5 = icmp slt i32 %conv1.i.us.5, %0 + %sext26.us.5 = zext i1 %cmp2.i.us.5 to i32 + %conv1.i.us.6 = ashr i32 %0, 16 + %cmp2.i.us.6 = icmp slt i32 %conv1.i.us.6, %0 + %sext26.us.6 = zext i1 %cmp2.i.us.6 to i32 + %conv1.i.us.7 = ashr i32 %0, 16 + %cmp2.i.us.7 = icmp slt i32 %conv1.i.us.7, %0 + %sext26.us.7 = zext i1 %cmp2.i.us.7 to i32 + br label %bb3 + +bb2: + %cmp2.i = icmp sgt i32 %0, 0 + %1 = zext i1 %cmp2.i to i32 + %cond.i = select i1 %tobool3.not, i32 %0, i32 %1 + %sext26 = shl i32 %cond.i, 16 + %conv13 = ashr i32 %sext26, 16 + %cmp2.i.5 = icmp sgt i32 %0, 0 + %2 = zext i1 %cmp2.i.5 to i32 + %cond.i.5 = select i1 %tobool3.not, i32 %0, i32 %2 + %sext26.5 = shl i32 %cond.i.5, 16 + %conv13.5 = ashr i32 %sext26.5, 16 + %cmp2.i.6 = icmp sgt i32 %0, 0 + %3 = zext i1 %cmp2.i.6 to i32 + %cond.i.6 = select i1 %tobool3.not, i32 %0, i32 %3 + %sext26.6 = shl i32 %cond.i.6, 16 + %conv13.6 = ashr i32 %sext26.6, 16 + %cmp2.i.7 = icmp sgt i32 %0, 0 + %4 = zext i1 %cmp2.i.7 to i32 + %cond.i.7 = select i1 %tobool3.not, i32 %0, i32 %4 + %sext26.7 = shl i32 %cond.i.7, 16 + %conv13.7 = ashr i32 %sext26.7, 16 + br i1 true, label %bb3, label %bb2 + +bb3: + %conv13p = phi i32 [ %sext26.us, %bb1 ], [ %conv13, %bb2 ] + %conv13.5p = phi i32 [ %sext26.us.5, %bb1 ], [ %conv13.5, %bb2 ] + %conv13.6p = phi i32 [ %sext26.us.6, %bb1 ], [ %conv13.6, %bb2 ] + %conv13.7p = phi i32 [ %sext26.us.7, %bb1 ], [ %conv13.7, %bb2 ] + store i32 %conv13p, ptr %b, align 16 + store i32 %conv13.5p, ptr %a, align 8 + store i32 %conv13.6p, ptr %c, align 16 + store i32 %conv13.7p, ptr %b, align 8 + ret i32 0 +} diff --git a/llvm/test/Transforms/SLPVectorizer/X86/phi-undef-input.ll b/llvm/test/Transforms/SLPVectorizer/X86/phi-undef-input.ll index 88f75c37846efcac85b2d6e49b33f9142dab9ded..3cc32c1fc7b28e932c53e6897087e14be0afe7ce 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/phi-undef-input.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/phi-undef-input.ll @@ -15,8 +15,8 @@ define i32 @phi3UndefInput(i1 %cond, i8 %arg0, i8 %arg1, i8 %arg2, i8 %arg3) { ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[TMP4:%.*]] = phi <4 x i8> [ [[TMP3]], [[BB2]] ], [ <i8 0, i8 undef, i8 undef, i8 undef>, [[ENTRY:%.*]] ] -; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i8> [[TMP4]] to <4 x i32> -; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP5]]) +; CHECK-NEXT: [[TMP5:%.*]] = call i8 @llvm.vector.reduce.or.v4i8(<4 x i8> [[TMP4]]) +; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 ; CHECK-NEXT: ret i32 [[TMP6]] ; entry: @@ -52,8 +52,8 @@ define i32 @phi2UndefInput(i1 %cond, i8 %arg0, i8 %arg1, i8 %arg2, i8 %arg3) { ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[TMP4:%.*]] = phi <4 x i8> [ [[TMP3]], [[BB2]] ], [ <i8 0, i8 0, i8 undef, i8 undef>, [[ENTRY:%.*]] ] -; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i8> [[TMP4]] to <4 x i32> -; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP5]]) +; CHECK-NEXT: [[TMP5:%.*]] = call i8 @llvm.vector.reduce.or.v4i8(<4 x i8> [[TMP4]]) +; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 ; CHECK-NEXT: ret i32 [[TMP6]] ; entry: @@ -89,8 +89,8 @@ define i32 @phi1UndefInput(i1 %cond, i8 %arg0, i8 %arg1, i8 %arg2, i8 %arg3) { ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[TMP4:%.*]] = phi <4 x i8> [ [[TMP3]], [[BB2]] ], [ <i8 0, i8 0, i8 0, i8 undef>, [[ENTRY:%.*]] ] -; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i8> [[TMP4]] to <4 x i32> -; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP5]]) +; CHECK-NEXT: [[TMP5:%.*]] = call i8 @llvm.vector.reduce.or.v4i8(<4 x i8> [[TMP4]]) +; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 ; CHECK-NEXT: ret i32 [[TMP6]] ; entry: @@ -127,8 +127,8 @@ define i32 @phi1Undef1PoisonInput(i1 %cond, i8 %arg0, i8 %arg1, i8 %arg2, i8 %ar ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[TMP4:%.*]] = phi <4 x i8> [ [[TMP3]], [[BB2]] ], [ <i8 0, i8 0, i8 poison, i8 undef>, [[ENTRY:%.*]] ] -; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i8> [[TMP4]] to <4 x i32> -; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP5]]) +; CHECK-NEXT: [[TMP5:%.*]] = call i8 @llvm.vector.reduce.or.v4i8(<4 x i8> [[TMP4]]) +; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 ; CHECK-NEXT: ret i32 [[TMP6]] ; entry: @@ -165,8 +165,8 @@ define i32 @phi1Undef2PoisonInputs(i1 %cond, i8 %arg0, i8 %arg1, i8 %arg2, i8 %a ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[TMP4:%.*]] = phi <4 x i8> [ [[TMP3]], [[BB2]] ], [ <i8 0, i8 poison, i8 poison, i8 undef>, [[ENTRY:%.*]] ] -; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i8> [[TMP4]] to <4 x i32> -; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP5]]) +; CHECK-NEXT: [[TMP5:%.*]] = call i8 @llvm.vector.reduce.or.v4i8(<4 x i8> [[TMP4]]) +; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 ; CHECK-NEXT: ret i32 [[TMP6]] ; entry: @@ -202,8 +202,8 @@ define i32 @phi1Undef1PoisonGapInput(i1 %cond, i8 %arg0, i8 %arg1, i8 %arg2, i8 ; CHECK-NEXT: br label [[BB3]] ; CHECK: bb3: ; CHECK-NEXT: [[TMP4:%.*]] = phi <4 x i8> [ [[TMP3]], [[BB2]] ], [ <i8 0, i8 0, i8 poison, i8 undef>, [[ENTRY:%.*]] ] -; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i8> [[TMP4]] to <4 x i32> -; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP5]]) +; CHECK-NEXT: [[TMP5:%.*]] = call i8 @llvm.vector.reduce.or.v4i8(<4 x i8> [[TMP4]]) +; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 ; CHECK-NEXT: ret i32 [[TMP6]] ; entry: diff --git a/llvm/test/Transforms/SLPVectorizer/X86/reorder-possible-strided-node.ll b/llvm/test/Transforms/SLPVectorizer/X86/reorder-possible-strided-node.ll index 6f5d3d3785e0c834251d0acddeec3e1f92349651..cfbbe14186b5018b21ff02f58798dd19dd53fa59 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/reorder-possible-strided-node.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/reorder-possible-strided-node.ll @@ -10,10 +10,8 @@ define void @test() { ; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr [[ARRAYIDX22]], align 4 ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> ; CHECK-NEXT: [[TMP3:%.*]] = mul <4 x i32> [[TMP2]], [[TMP0]] -; CHECK-NEXT: [[TMP4:%.*]] = sext <4 x i32> [[TMP3]] to <4 x i64> -; CHECK-NEXT: [[TMP5:%.*]] = ashr <4 x i64> [[TMP4]], zeroinitializer -; CHECK-NEXT: [[TMP6:%.*]] = trunc <4 x i64> [[TMP5]] to <4 x i32> -; CHECK-NEXT: store <4 x i32> [[TMP6]], ptr getelementptr inbounds ([4 x i32], ptr null, i64 8, i64 0), align 16 +; CHECK-NEXT: [[TMP4:%.*]] = ashr <4 x i32> [[TMP3]], zeroinitializer +; CHECK-NEXT: store <4 x i32> [[TMP4]], ptr getelementptr inbounds ([4 x i32], ptr null, i64 8, i64 0), align 16 ; CHECK-NEXT: ret void ; entry: @@ -108,3 +106,107 @@ entry: store i32 %conv27, ptr getelementptr inbounds ([4 x i32], ptr null, i64 8, i64 3), align 4 ret void } + +define void @test_div() { +; CHECK-LABEL: define void @test_div( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ARRAYIDX22:%.*]] = getelementptr i32, ptr null, i64 60 +; CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> getelementptr (i32, <4 x ptr> zeroinitializer, <4 x i64> <i64 1, i64 33, i64 7, i64 0>), i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> poison) +; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr [[ARRAYIDX22]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> +; CHECK-NEXT: [[TMP3:%.*]] = mul <4 x i32> [[TMP2]], [[TMP0]] +; CHECK-NEXT: [[TMP6:%.*]] = udiv <4 x i32> [[TMP3]], <i32 1, i32 2, i32 1, i32 2> +; CHECK-NEXT: store <4 x i32> [[TMP6]], ptr getelementptr inbounds ([4 x i32], ptr null, i64 8, i64 0), align 16 +; CHECK-NEXT: ret void +; +entry: + %arrayidx1 = getelementptr i32, ptr null, i64 1 + %0 = load i32, ptr %arrayidx1, align 4 + %arrayidx2 = getelementptr i32, ptr null, i64 63 + %1 = load i32, ptr %arrayidx2, align 4 + %mul = mul i32 %1, %0 + %conv = zext i32 %mul to i64 + %shr = udiv i64 %conv, 1 + %conv3 = trunc i64 %shr to i32 + store i32 %conv3, ptr getelementptr inbounds ([4 x i32], ptr null, i64 8, i64 0), align 16 + %arrayidx5 = getelementptr i32, ptr null, i64 33 + %2 = load i32, ptr %arrayidx5, align 4 + %arrayidx6 = getelementptr i32, ptr null, i64 62 + %3 = load i32, ptr %arrayidx6, align 4 + %mul7 = mul i32 %3, %2 + %conv8 = zext i32 %mul7 to i64 + %shr10 = udiv i64 %conv8, 2 + %conv11 = trunc i64 %shr10 to i32 + store i32 %conv11, ptr getelementptr inbounds ([4 x i32], ptr null, i64 8, i64 1), align 4 + %arrayidx13 = getelementptr i32, ptr null, i64 7 + %4 = load i32, ptr %arrayidx13, align 4 + %arrayidx14 = getelementptr i32, ptr null, i64 61 + %5 = load i32, ptr %arrayidx14, align 4 + %mul15 = mul i32 %5, %4 + %conv16 = zext i32 %mul15 to i64 + %shr18 = udiv i64 %conv16, 1 + %conv19 = trunc i64 %shr18 to i32 + store i32 %conv19, ptr getelementptr inbounds ([4 x i32], ptr null, i64 8, i64 2), align 8 + %6 = load i32, ptr null, align 4 + %arrayidx22 = getelementptr i32, ptr null, i64 60 + %7 = load i32, ptr %arrayidx22, align 4 + %mul23 = mul i32 %7, %6 + %conv24 = zext i32 %mul23 to i64 + %shr26 = udiv i64 %conv24, 2 + %conv27 = trunc i64 %shr26 to i32 + store i32 %conv27, ptr getelementptr inbounds ([4 x i32], ptr null, i64 8, i64 3), align 4 + ret void +} + +define void @test_rem() { +; CHECK-LABEL: define void @test_rem( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ARRAYIDX22:%.*]] = getelementptr i32, ptr null, i64 60 +; CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> getelementptr (i32, <4 x ptr> zeroinitializer, <4 x i64> <i64 1, i64 33, i64 7, i64 0>), i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> poison) +; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr [[ARRAYIDX22]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> +; CHECK-NEXT: [[TMP3:%.*]] = mul <4 x i32> [[TMP2]], [[TMP0]] +; CHECK-NEXT: [[TMP6:%.*]] = urem <4 x i32> [[TMP3]], <i32 1, i32 2, i32 1, i32 1> +; CHECK-NEXT: store <4 x i32> [[TMP6]], ptr getelementptr inbounds ([4 x i32], ptr null, i64 8, i64 0), align 16 +; CHECK-NEXT: ret void +; +entry: + %arrayidx1 = getelementptr i32, ptr null, i64 1 + %0 = load i32, ptr %arrayidx1, align 4 + %arrayidx2 = getelementptr i32, ptr null, i64 63 + %1 = load i32, ptr %arrayidx2, align 4 + %mul = mul i32 %1, %0 + %conv = zext i32 %mul to i64 + %shr = urem i64 %conv, 1 + %conv3 = trunc i64 %shr to i32 + store i32 %conv3, ptr getelementptr inbounds ([4 x i32], ptr null, i64 8, i64 0), align 16 + %arrayidx5 = getelementptr i32, ptr null, i64 33 + %2 = load i32, ptr %arrayidx5, align 4 + %arrayidx6 = getelementptr i32, ptr null, i64 62 + %3 = load i32, ptr %arrayidx6, align 4 + %mul7 = mul i32 %3, %2 + %conv8 = zext i32 %mul7 to i64 + %shr10 = urem i64 %conv8, 2 + %conv11 = trunc i64 %shr10 to i32 + store i32 %conv11, ptr getelementptr inbounds ([4 x i32], ptr null, i64 8, i64 1), align 4 + %arrayidx13 = getelementptr i32, ptr null, i64 7 + %4 = load i32, ptr %arrayidx13, align 4 + %arrayidx14 = getelementptr i32, ptr null, i64 61 + %5 = load i32, ptr %arrayidx14, align 4 + %mul15 = mul i32 %5, %4 + %conv16 = zext i32 %mul15 to i64 + %shr18 = urem i64 %conv16, 1 + %conv19 = trunc i64 %shr18 to i32 + store i32 %conv19, ptr getelementptr inbounds ([4 x i32], ptr null, i64 8, i64 2), align 8 + %6 = load i32, ptr null, align 4 + %arrayidx22 = getelementptr i32, ptr null, i64 60 + %7 = load i32, ptr %arrayidx22, align 4 + %mul23 = mul i32 %7, %6 + %conv24 = zext i32 %mul23 to i64 + %shr26 = urem i64 %conv24, 1 + %conv27 = trunc i64 %shr26 to i32 + store i32 %conv27, ptr getelementptr inbounds ([4 x i32], ptr null, i64 8, i64 3), align 4 + ret void +} diff --git a/llvm/test/Transforms/SLPVectorizer/X86/reorder_diamond_match.ll b/llvm/test/Transforms/SLPVectorizer/X86/reorder_diamond_match.ll index 86b1e1a801e32f8e84d1dcb8b507ff7ec10a3b67..9682567b173c3eb38d16904e9c6c83c717a05484 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/reorder_diamond_match.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/reorder_diamond_match.ll @@ -5,18 +5,19 @@ define void @test() { ; CHECK-LABEL: @test( ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr undef, i64 4 ; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [4 x [4 x i32]], ptr undef, i64 0, i64 1, i64 0 -; CHECK-NEXT: [[TMP4:%.*]] = load <4 x i8>, ptr [[TMP1]], align 1 -; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i8> [[TMP4]] to <4 x i32> -; CHECK-NEXT: [[TMP6:%.*]] = sub nsw <4 x i32> zeroinitializer, [[TMP5]] -; CHECK-NEXT: [[TMP7:%.*]] = shl nsw <4 x i32> [[TMP6]], zeroinitializer -; CHECK-NEXT: [[TMP8:%.*]] = add nsw <4 x i32> [[TMP7]], zeroinitializer -; CHECK-NEXT: [[TMP9:%.*]] = shufflevector <4 x i32> [[TMP8]], <4 x i32> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 2> -; CHECK-NEXT: [[TMP10:%.*]] = add nsw <4 x i32> [[TMP8]], [[TMP9]] -; CHECK-NEXT: [[TMP11:%.*]] = sub nsw <4 x i32> [[TMP8]], [[TMP9]] -; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <4 x i32> [[TMP10]], <4 x i32> [[TMP11]], <4 x i32> <i32 1, i32 4, i32 3, i32 6> -; CHECK-NEXT: [[TMP13:%.*]] = add nsw <4 x i32> zeroinitializer, [[TMP12]] -; CHECK-NEXT: [[TMP14:%.*]] = sub nsw <4 x i32> zeroinitializer, [[TMP12]] -; CHECK-NEXT: [[TMP15:%.*]] = shufflevector <4 x i32> [[TMP13]], <4 x i32> [[TMP14]], <4 x i32> <i32 0, i32 1, i32 6, i32 7> +; CHECK-NEXT: [[TMP3:%.*]] = load <4 x i8>, ptr [[TMP1]], align 1 +; CHECK-NEXT: [[TMP4:%.*]] = zext <4 x i8> [[TMP3]] to <4 x i16> +; CHECK-NEXT: [[TMP5:%.*]] = sub <4 x i16> zeroinitializer, [[TMP4]] +; CHECK-NEXT: [[TMP6:%.*]] = shl <4 x i16> [[TMP5]], zeroinitializer +; CHECK-NEXT: [[TMP7:%.*]] = add <4 x i16> [[TMP6]], zeroinitializer +; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <4 x i16> [[TMP7]], <4 x i16> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 2> +; CHECK-NEXT: [[TMP9:%.*]] = add <4 x i16> [[TMP7]], [[TMP8]] +; CHECK-NEXT: [[TMP10:%.*]] = sub <4 x i16> [[TMP7]], [[TMP8]] +; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <4 x i16> [[TMP9]], <4 x i16> [[TMP10]], <4 x i32> <i32 1, i32 4, i32 3, i32 6> +; CHECK-NEXT: [[TMP12:%.*]] = add <4 x i16> zeroinitializer, [[TMP11]] +; CHECK-NEXT: [[TMP13:%.*]] = sub <4 x i16> zeroinitializer, [[TMP11]] +; CHECK-NEXT: [[TMP14:%.*]] = shufflevector <4 x i16> [[TMP12]], <4 x i16> [[TMP13]], <4 x i32> <i32 0, i32 1, i32 6, i32 7> +; CHECK-NEXT: [[TMP15:%.*]] = sext <4 x i16> [[TMP14]] to <4 x i32> ; CHECK-NEXT: store <4 x i32> [[TMP15]], ptr [[TMP2]], align 16 ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/SLPVectorizer/X86/reorder_phi.ll b/llvm/test/Transforms/SLPVectorizer/X86/reorder_phi.ll index 65229d8acd889ef6789fa77b2f50030608764f78..f0e734d8c5aefec61dacfa5f9d6ab3a5dc97d17e 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/reorder_phi.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/reorder_phi.ll @@ -10,29 +10,29 @@ define void @foo (ptr %A, ptr %B, ptr %Result) { ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[TMP1:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[TMP18:%.*]], [[LOOP]] ] -; CHECK-NEXT: [[TMP2:%.*]] = phi <2 x float> [ zeroinitializer, [[ENTRY]] ], [ [[TMP17:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[TMP2:%.*]] = phi <2 x float> [ zeroinitializer, [[ENTRY]] ], [ [[TMP20:%.*]], [[LOOP]] ] ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_COMPLEX:%.*]], ptr [[A:%.*]], i64 [[TMP1]], i32 0 ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_COMPLEX]], ptr [[B:%.*]], i64 [[TMP1]], i32 0 ; CHECK-NEXT: [[TMP5:%.*]] = load float, ptr [[TMP4]], align 4 ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_COMPLEX]], ptr [[B]], i64 [[TMP1]], i32 1 ; CHECK-NEXT: [[TMP7:%.*]] = load float, ptr [[TMP6]], align 4 -; CHECK-NEXT: [[TMP9:%.*]] = load <2 x float>, ptr [[TMP3]], align 4 -; CHECK-NEXT: [[TMP10:%.*]] = insertelement <2 x float> poison, float [[TMP5]], i32 0 -; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <2 x float> [[TMP10]], <2 x float> poison, <2 x i32> zeroinitializer -; CHECK-NEXT: [[TMP11:%.*]] = fmul <2 x float> [[TMP9]], [[SHUFFLE]] +; CHECK-NEXT: [[TMP8:%.*]] = load <2 x float>, ptr [[TMP3]], align 4 +; CHECK-NEXT: [[TMP9:%.*]] = insertelement <2 x float> poison, float [[TMP5]], i32 0 +; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <2 x float> [[TMP9]], <2 x float> poison, <2 x i32> zeroinitializer +; CHECK-NEXT: [[TMP11:%.*]] = fmul <2 x float> [[TMP8]], [[TMP10]] ; CHECK-NEXT: [[TMP12:%.*]] = insertelement <2 x float> poison, float [[TMP7]], i32 0 -; CHECK-NEXT: [[SHUFFLE1:%.*]] = shufflevector <2 x float> [[TMP12]], <2 x float> poison, <2 x i32> zeroinitializer -; CHECK-NEXT: [[TMP13:%.*]] = fmul <2 x float> [[TMP9]], [[SHUFFLE1]] -; CHECK-NEXT: [[SHUFFLE2:%.*]] = shufflevector <2 x float> [[TMP13]], <2 x float> poison, <2 x i32> <i32 1, i32 0> -; CHECK-NEXT: [[TMP14:%.*]] = fsub <2 x float> [[TMP11]], [[SHUFFLE2]] -; CHECK-NEXT: [[TMP15:%.*]] = fadd <2 x float> [[TMP11]], [[SHUFFLE2]] -; CHECK-NEXT: [[TMP16:%.*]] = shufflevector <2 x float> [[TMP14]], <2 x float> [[TMP15]], <2 x i32> <i32 0, i32 3> -; CHECK-NEXT: [[TMP17]] = fadd <2 x float> [[TMP2]], [[TMP16]] +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <2 x float> [[TMP12]], <2 x float> poison, <2 x i32> zeroinitializer +; CHECK-NEXT: [[TMP14:%.*]] = fmul <2 x float> [[TMP8]], [[TMP13]] +; CHECK-NEXT: [[TMP15:%.*]] = shufflevector <2 x float> [[TMP14]], <2 x float> poison, <2 x i32> <i32 1, i32 0> +; CHECK-NEXT: [[TMP16:%.*]] = fsub <2 x float> [[TMP11]], [[TMP15]] +; CHECK-NEXT: [[TMP17:%.*]] = fadd <2 x float> [[TMP11]], [[TMP15]] +; CHECK-NEXT: [[TMP21:%.*]] = shufflevector <2 x float> [[TMP16]], <2 x float> [[TMP17]], <2 x i32> <i32 0, i32 3> +; CHECK-NEXT: [[TMP20]] = fadd <2 x float> [[TMP2]], [[TMP21]] ; CHECK-NEXT: [[TMP18]] = add nuw nsw i64 [[TMP1]], 1 ; CHECK-NEXT: [[TMP19:%.*]] = icmp eq i64 [[TMP18]], [[TMP0]] ; CHECK-NEXT: br i1 [[TMP19]], label [[EXIT:%.*]], label [[LOOP]] ; CHECK: exit: -; CHECK-NEXT: store <2 x float> [[TMP17]], ptr [[RESULT:%.*]], align 4 +; CHECK-NEXT: store <2 x float> [[TMP20]], ptr [[RESULT:%.*]], align 4 ; CHECK-NEXT: ret void ; entry: diff --git a/llvm/test/Transforms/SLPVectorizer/X86/resched.ll b/llvm/test/Transforms/SLPVectorizer/X86/resched.ll index 78c6d9516a3dec095a4be362b7351c1a56deb070..b7237cbb02bb3246dc4e4a92a3875a8b64785fe5 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/resched.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/resched.ll @@ -11,26 +11,26 @@ define fastcc void @_ZN12_GLOBAL__N_127PolynomialMultiplyRecognize9recognizeEv() ; CHECK: if.then22.i: ; CHECK-NEXT: [[SUB_I:%.*]] = add nsw i32 undef, -1 ; CHECK-NEXT: [[CONV31_I:%.*]] = and i32 undef, [[SUB_I]] -; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i32> poison, i32 [[CONV31_I]], i32 0 -; CHECK-NEXT: [[SHUFFLE1:%.*]] = shufflevector <4 x i32> [[TMP1]], <4 x i32> poison, <4 x i32> zeroinitializer -; CHECK-NEXT: [[TMP2:%.*]] = lshr <4 x i32> [[SHUFFLE1]], <i32 1, i32 2, i32 3, i32 4> +; CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x i32> poison, i32 [[CONV31_I]], i32 0 +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[TMP0]], <4 x i32> poison, <4 x i32> zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = lshr <4 x i32> [[TMP1]], <i32 1, i32 2, i32 3, i32 4> ; CHECK-NEXT: [[SHR_4_I_I:%.*]] = lshr i32 [[CONV31_I]], 5 ; CHECK-NEXT: [[SHR_5_I_I:%.*]] = lshr i32 [[CONV31_I]], 6 ; CHECK-NEXT: [[SHR_6_I_I:%.*]] = lshr i32 [[CONV31_I]], 7 ; CHECK-NEXT: [[TMP3:%.*]] = insertelement <8 x i32> poison, i32 [[CONV31_I]], i32 0 -; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <8 x i32> [[TMP3]], <8 x i32> poison, <8 x i32> zeroinitializer -; CHECK-NEXT: [[TMP4:%.*]] = lshr <8 x i32> [[SHUFFLE]], <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> -; CHECK-NEXT: [[TMP5:%.*]] = insertelement <16 x i32> poison, i32 [[SUB_I]], i32 0 -; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <4 x i32> [[TMP2]], <4 x i32> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison> -; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <16 x i32> [[TMP5]], <16 x i32> [[TMP6]], <16 x i32> <i32 0, i32 16, i32 17, i32 18, i32 19, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison> -; CHECK-NEXT: [[TMP8:%.*]] = insertelement <16 x i32> [[TMP7]], i32 [[SHR_4_I_I]], i32 5 -; CHECK-NEXT: [[TMP9:%.*]] = insertelement <16 x i32> [[TMP8]], i32 [[SHR_5_I_I]], i32 6 -; CHECK-NEXT: [[TMP10:%.*]] = insertelement <16 x i32> [[TMP9]], i32 [[SHR_6_I_I]], i32 7 -; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <8 x i32> [[TMP4]], <8 x i32> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison> -; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <16 x i32> [[TMP10]], <16 x i32> [[TMP11]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23> -; CHECK-NEXT: [[TMP13:%.*]] = trunc <16 x i32> [[TMP12]] to <16 x i8> -; CHECK-NEXT: [[TMP14:%.*]] = and <16 x i8> [[TMP13]], <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> -; CHECK-NEXT: store <16 x i8> [[TMP14]], ptr undef, align 1 +; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <8 x i32> [[TMP3]], <8 x i32> poison, <8 x i32> zeroinitializer +; CHECK-NEXT: [[TMP5:%.*]] = lshr <8 x i32> [[TMP4]], <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> +; CHECK-NEXT: [[TMP6:%.*]] = insertelement <16 x i32> poison, i32 [[SUB_I]], i32 0 +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <4 x i32> [[TMP2]], <4 x i32> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison> +; CHECK-NEXT: [[TMP8:%.*]] = shufflevector <16 x i32> [[TMP6]], <16 x i32> [[TMP7]], <16 x i32> <i32 0, i32 16, i32 17, i32 18, i32 19, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison> +; CHECK-NEXT: [[TMP9:%.*]] = insertelement <16 x i32> [[TMP8]], i32 [[SHR_4_I_I]], i32 5 +; CHECK-NEXT: [[TMP10:%.*]] = insertelement <16 x i32> [[TMP9]], i32 [[SHR_5_I_I]], i32 6 +; CHECK-NEXT: [[TMP11:%.*]] = insertelement <16 x i32> [[TMP10]], i32 [[SHR_6_I_I]], i32 7 +; CHECK-NEXT: [[TMP12:%.*]] = shufflevector <8 x i32> [[TMP5]], <8 x i32> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison> +; CHECK-NEXT: [[TMP13:%.*]] = shufflevector <16 x i32> [[TMP11]], <16 x i32> [[TMP12]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23> +; CHECK-NEXT: [[TMP14:%.*]] = trunc <16 x i32> [[TMP13]] to <16 x i8> +; CHECK-NEXT: [[TMP15:%.*]] = and <16 x i8> [[TMP14]], <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> +; CHECK-NEXT: store <16 x i8> [[TMP15]], ptr undef, align 1 ; CHECK-NEXT: unreachable ; CHECK: if.end50.i: ; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/SLPVectorizer/X86/reused-reductions-with-minbitwidth.ll b/llvm/test/Transforms/SLPVectorizer/X86/reused-reductions-with-minbitwidth.ll index 5d22b5a4873be3229a56f8b24f235677ed6b44a5..1d1fcec2a7aebaaf861f426f79a0f94e7ca1207c 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/reused-reductions-with-minbitwidth.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/reused-reductions-with-minbitwidth.ll @@ -7,12 +7,10 @@ define i1 @test(i1 %cmp5.not.31) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x i1> <i1 poison, i1 false, i1 false, i1 false>, i1 [[CMP5_NOT_31]], i32 0 ; CHECK-NEXT: [[TMP1:%.*]] = select <4 x i1> [[TMP0]], <4 x i32> zeroinitializer, <4 x i32> zeroinitializer -; CHECK-NEXT: [[TMP2:%.*]] = trunc <4 x i32> [[TMP1]] to <4 x i1> -; CHECK-NEXT: [[TMP3:%.*]] = zext <4 x i1> [[TMP2]] to <4 x i32> -; CHECK-NEXT: [[TMP4:%.*]] = mul <4 x i32> [[TMP3]], <i32 2, i32 1, i32 1, i32 1> -; CHECK-NEXT: [[TMP5:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[TMP4]]) -; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[TMP5]], 0 -; CHECK-NEXT: [[CMP_NOT_I_I:%.*]] = icmp eq i32 [[TMP6]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = mul <4 x i32> [[TMP1]], <i32 2, i32 1, i32 1, i32 1> +; CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[TMP2]]) +; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP3]], 0 +; CHECK-NEXT: [[CMP_NOT_I_I:%.*]] = icmp eq i32 [[TMP4]], 0 ; CHECK-NEXT: ret i1 [[CMP_NOT_I_I]] ; entry: diff --git a/llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll b/llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll new file mode 100644 index 0000000000000000000000000000000000000000..f1be11d0d0fc51671b734cd5c346709216af84ad --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/same-scalar-in-same-phi-extract.ll @@ -0,0 +1,76 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer -slp-threshold=-99999 -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s + +define void @test(i32 %arg) { +; CHECK-LABEL: define void @test( +; CHECK-SAME: i32 [[ARG:%.*]]) { +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x i32> <i32 poison, i32 0>, i32 [[ARG]], i32 0 +; CHECK-NEXT: br label [[BB2:%.*]] +; CHECK: bb2: +; CHECK-NEXT: switch i32 0, label [[BB10:%.*]] [ +; CHECK-NEXT: i32 0, label [[BB9:%.*]] +; CHECK-NEXT: i32 11, label [[BB9]] +; CHECK-NEXT: i32 1, label [[BB4:%.*]] +; CHECK-NEXT: ] +; CHECK: bb3: +; CHECK-NEXT: [[TMP1:%.*]] = extractelement <2 x i32> [[TMP0]], i32 0 +; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[TMP1]] to i64 +; CHECK-NEXT: switch i32 0, label [[BB10]] [ +; CHECK-NEXT: i32 18, label [[BB7:%.*]] +; CHECK-NEXT: i32 1, label [[BB7]] +; CHECK-NEXT: i32 0, label [[BB10]] +; CHECK-NEXT: ] +; CHECK: bb4: +; CHECK-NEXT: [[TMP3:%.*]] = phi <2 x i32> [ [[TMP0]], [[BB2]] ] +; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x i32> [[TMP3]], i32 0 +; CHECK-NEXT: [[TMP5:%.*]] = zext i32 [[TMP4]] to i64 +; CHECK-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr i32, ptr null, i64 [[TMP5]] +; CHECK-NEXT: [[TMP7:%.*]] = extractelement <2 x i32> [[TMP3]], i32 1 +; CHECK-NEXT: [[TMP6:%.*]] = zext i32 [[TMP7]] to i64 +; CHECK-NEXT: [[GETELEMENTPTR6:%.*]] = getelementptr i32, ptr null, i64 [[TMP6]] +; CHECK-NEXT: ret void +; CHECK: bb7: +; CHECK-NEXT: [[PHI8:%.*]] = phi i64 [ [[TMP2]], [[BB3:%.*]] ], [ [[TMP2]], [[BB3]] ] +; CHECK-NEXT: br label [[BB9]] +; CHECK: bb9: +; CHECK-NEXT: ret void +; CHECK: bb10: +; CHECK-NEXT: ret void +; +bb: + %zext = zext i32 %arg to i64 + %zext1 = zext i32 0 to i64 + br label %bb2 + +bb2: + switch i32 0, label %bb10 [ + i32 0, label %bb9 + i32 11, label %bb9 + i32 1, label %bb4 + ] + +bb3: + switch i32 0, label %bb10 [ + i32 18, label %bb7 + i32 1, label %bb7 + i32 0, label %bb10 + ] + +bb4: + %phi = phi i64 [ %zext, %bb2 ] + %phi5 = phi i64 [ %zext1, %bb2 ] + %getelementptr = getelementptr i32, ptr null, i64 %phi + %getelementptr6 = getelementptr i32, ptr null, i64 %phi5 + ret void + +bb7: + %phi8 = phi i64 [ %zext, %bb3 ], [ %zext, %bb3 ] + br label %bb9 + +bb9: + ret void + +bb10: + ret void +} diff --git a/llvm/test/Transforms/SLPVectorizer/X86/sext-inseltpoison.ll b/llvm/test/Transforms/SLPVectorizer/X86/sext-inseltpoison.ll index 5ae0ad932fdddbbd18a020995be9bec2c583e457..b64743aaa283c718a05c81c9b9a2b0e27558809e 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/sext-inseltpoison.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/sext-inseltpoison.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -mtriple=x86_64-unknown -passes=slp-vectorizer -S | FileCheck %s --check-prefixes=SSE,SSE2 -; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=slm -passes=slp-vectorizer -S | FileCheck %s --check-prefixes=SSE,SLM +; RUN: opt < %s -mtriple=x86_64-unknown -passes=slp-vectorizer -S | FileCheck %s --check-prefixes=SSE +; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=slm -passes=slp-vectorizer -S | FileCheck %s --check-prefixes=SSE ; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=corei7-avx -passes=slp-vectorizer -S | FileCheck %s --check-prefixes=AVX ; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=core-avx2 -passes=slp-vectorizer -S | FileCheck %s --check-prefixes=AVX ; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=knl -passes=slp-vectorizer -S | FileCheck %s --check-prefixes=AVX @@ -11,20 +11,10 @@ ; define <2 x i64> @loadext_2i8_to_2i64(ptr %p0) { -; SSE2-LABEL: @loadext_2i8_to_2i64( -; SSE2-NEXT: [[P1:%.*]] = getelementptr inbounds i8, ptr [[P0:%.*]], i64 1 -; SSE2-NEXT: [[I0:%.*]] = load i8, ptr [[P0]], align 1 -; SSE2-NEXT: [[I1:%.*]] = load i8, ptr [[P1]], align 1 -; SSE2-NEXT: [[X0:%.*]] = sext i8 [[I0]] to i64 -; SSE2-NEXT: [[X1:%.*]] = sext i8 [[I1]] to i64 -; SSE2-NEXT: [[V0:%.*]] = insertelement <2 x i64> poison, i64 [[X0]], i32 0 -; SSE2-NEXT: [[V1:%.*]] = insertelement <2 x i64> [[V0]], i64 [[X1]], i32 1 -; SSE2-NEXT: ret <2 x i64> [[V1]] -; -; SLM-LABEL: @loadext_2i8_to_2i64( -; SLM-NEXT: [[TMP2:%.*]] = load <2 x i8>, ptr [[P0:%.*]], align 1 -; SLM-NEXT: [[TMP3:%.*]] = sext <2 x i8> [[TMP2]] to <2 x i64> -; SLM-NEXT: ret <2 x i64> [[TMP3]] +; SSE-LABEL: @loadext_2i8_to_2i64( +; SSE-NEXT: [[TMP1:%.*]] = load <2 x i8>, ptr [[P0:%.*]], align 1 +; SSE-NEXT: [[TMP2:%.*]] = sext <2 x i8> [[TMP1]] to <2 x i64> +; SSE-NEXT: ret <2 x i64> [[TMP2]] ; ; AVX-LABEL: @loadext_2i8_to_2i64( ; AVX-NEXT: [[TMP2:%.*]] = load <2 x i8>, ptr [[P0:%.*]], align 1 diff --git a/llvm/test/Transforms/SLPVectorizer/X86/sext.ll b/llvm/test/Transforms/SLPVectorizer/X86/sext.ll index 7d38aeb0c3635714a1e29dceb852794fd89016ba..744a50906cfc48ad464a439d53d6f3d73cc48dac 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/sext.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/sext.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -mtriple=x86_64-unknown -passes=slp-vectorizer -S | FileCheck %s --check-prefixes=SSE,SSE2 -; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=slm -passes=slp-vectorizer -S | FileCheck %s --check-prefixes=SSE,SLM +; RUN: opt < %s -mtriple=x86_64-unknown -passes=slp-vectorizer -S | FileCheck %s --check-prefixes=SSE +; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=slm -passes=slp-vectorizer -S | FileCheck %s --check-prefixes=SSE ; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=corei7-avx -passes=slp-vectorizer -S | FileCheck %s --check-prefixes=AVX ; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=core-avx2 -passes=slp-vectorizer -S | FileCheck %s --check-prefixes=AVX ; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=knl -passes=slp-vectorizer -S | FileCheck %s --check-prefixes=AVX @@ -11,20 +11,10 @@ ; define <2 x i64> @loadext_2i8_to_2i64(ptr %p0) { -; SSE2-LABEL: @loadext_2i8_to_2i64( -; SSE2-NEXT: [[P1:%.*]] = getelementptr inbounds i8, ptr [[P0:%.*]], i64 1 -; SSE2-NEXT: [[I0:%.*]] = load i8, ptr [[P0]], align 1 -; SSE2-NEXT: [[I1:%.*]] = load i8, ptr [[P1]], align 1 -; SSE2-NEXT: [[X0:%.*]] = sext i8 [[I0]] to i64 -; SSE2-NEXT: [[X1:%.*]] = sext i8 [[I1]] to i64 -; SSE2-NEXT: [[V0:%.*]] = insertelement <2 x i64> undef, i64 [[X0]], i32 0 -; SSE2-NEXT: [[V1:%.*]] = insertelement <2 x i64> [[V0]], i64 [[X1]], i32 1 -; SSE2-NEXT: ret <2 x i64> [[V1]] -; -; SLM-LABEL: @loadext_2i8_to_2i64( -; SLM-NEXT: [[TMP2:%.*]] = load <2 x i8>, ptr [[P0:%.*]], align 1 -; SLM-NEXT: [[TMP3:%.*]] = sext <2 x i8> [[TMP2]] to <2 x i64> -; SLM-NEXT: ret <2 x i64> [[TMP3]] +; SSE-LABEL: @loadext_2i8_to_2i64( +; SSE-NEXT: [[TMP1:%.*]] = load <2 x i8>, ptr [[P0:%.*]], align 1 +; SSE-NEXT: [[TMP2:%.*]] = sext <2 x i8> [[TMP1]] to <2 x i64> +; SSE-NEXT: ret <2 x i64> [[TMP2]] ; ; AVX-LABEL: @loadext_2i8_to_2i64( ; AVX-NEXT: [[TMP2:%.*]] = load <2 x i8>, ptr [[P0:%.*]], align 1 diff --git a/llvm/test/Transforms/SLPVectorizer/X86/store-abs-minbitwidth.ll b/llvm/test/Transforms/SLPVectorizer/X86/store-abs-minbitwidth.ll new file mode 100644 index 0000000000000000000000000000000000000000..e8b854b7cea6cbe08151b308616c936fe9654e4f --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/X86/store-abs-minbitwidth.ll @@ -0,0 +1,70 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -S -mtriple=x86_64-unknown -mattr=+avx512vl -passes=slp-vectorizer -slp-threshold=-3 | FileCheck %s + + +define i32 @test(ptr noalias %in, ptr noalias %inn, ptr %out) { +; CHECK-LABEL: @test( +; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i8>, ptr [[IN:%.*]], align 1 +; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds i8, ptr [[IN]], i64 2 +; CHECK-NEXT: [[TMP2:%.*]] = load <2 x i8>, ptr [[GEP_2]], align 1 +; CHECK-NEXT: [[TMP3:%.*]] = load <2 x i8>, ptr [[INN:%.*]], align 1 +; CHECK-NEXT: [[GEP_5:%.*]] = getelementptr inbounds i8, ptr [[INN]], i64 2 +; CHECK-NEXT: [[TMP4:%.*]] = load <2 x i8>, ptr [[GEP_5]], align 1 +; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <2 x i8> [[TMP3]], <2 x i8> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison> +; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <2 x i8> [[TMP2]], <2 x i8> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison> +; CHECK-NEXT: [[TMP7:%.*]] = shufflevector <4 x i8> [[TMP5]], <4 x i8> [[TMP6]], <4 x i32> <i32 0, i32 1, i32 4, i32 5> +; CHECK-NEXT: [[TMP8:%.*]] = sext <4 x i8> [[TMP7]] to <4 x i32> +; CHECK-NEXT: [[TMP9:%.*]] = shufflevector <2 x i8> [[TMP1]], <2 x i8> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison> +; CHECK-NEXT: [[TMP10:%.*]] = shufflevector <2 x i8> [[TMP4]], <2 x i8> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison> +; CHECK-NEXT: [[TMP11:%.*]] = shufflevector <4 x i8> [[TMP9]], <4 x i8> [[TMP10]], <4 x i32> <i32 0, i32 1, i32 4, i32 5> +; CHECK-NEXT: [[TMP12:%.*]] = sext <4 x i8> [[TMP11]] to <4 x i32> +; CHECK-NEXT: [[TMP13:%.*]] = sub <4 x i32> [[TMP12]], [[TMP8]] +; CHECK-NEXT: [[TMP14:%.*]] = call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[TMP13]], i1 true) +; CHECK-NEXT: [[TMP15:%.*]] = trunc <4 x i32> [[TMP14]] to <4 x i16> +; CHECK-NEXT: store <4 x i16> [[TMP15]], ptr [[OUT:%.*]], align 2 +; CHECK-NEXT: ret i32 undef +; + %load.1 = load i8, ptr %in, align 1 + %gep.1 = getelementptr inbounds i8, ptr %in, i64 1 + %load.2 = load i8, ptr %gep.1, align 1 + %gep.2 = getelementptr inbounds i8, ptr %in, i64 2 + %load.3 = load i8, ptr %gep.2, align 1 + %gep.3 = getelementptr inbounds i8, ptr %in, i64 3 + %load.4 = load i8, ptr %gep.3, align 1 + %load.5 = load i8, ptr %inn, align 1 + %gep.4 = getelementptr inbounds i8, ptr %inn, i64 1 + %load.6 = load i8, ptr %gep.4, align 1 + %gep.5 = getelementptr inbounds i8, ptr %inn, i64 2 + %load.7 = load i8, ptr %gep.5, align 1 + %gep.6 = getelementptr inbounds i8, ptr %inn, i64 3 + %load.8 = load i8, ptr %gep.6, align 1 + %sext1 = sext i8 %load.1 to i32 + %sext2 = sext i8 %load.2 to i32 + %sext3 = sext i8 %load.3 to i32 + %sext4 = sext i8 %load.4 to i32 + %sext5 = sext i8 %load.5 to i32 + %sext6 = sext i8 %load.6 to i32 + %sext7 = sext i8 %load.7 to i32 + %sext8 = sext i8 %load.8 to i32 + %sub1 = sub i32 %sext1, %sext5 + %sub2 = sub i32 %sext2, %sext6 + %sub3 = sub i32 %sext7, %sext3 + %sub4 = sub i32 %sext8, %sext4 + %call1 = call i32 @llvm.abs(i32 %sub1, i1 true) + %call2 = call i32 @llvm.abs(i32 %sub2, i1 true) + %call3 = call i32 @llvm.abs(i32 %sub3, i1 true) + %call4 = call i32 @llvm.abs(i32 %sub4, i1 true) + %t1 = trunc i32 %call1 to i16 + %t2 = trunc i32 %call2 to i16 + %t3 = trunc i32 %call3 to i16 + %t4 = trunc i32 %call4 to i16 + %gep.8 = getelementptr inbounds i16, ptr %out, i64 1 + %gep.9 = getelementptr inbounds i16, ptr %out, i64 2 + %gep.10 = getelementptr inbounds i16, ptr %out, i64 3 + store i16 %t1, ptr %out, align 2 + store i16 %t2, ptr %gep.8, align 2 + store i16 %t3, ptr %gep.9, align 2 + store i16 %t4, ptr %gep.10, align 2 + + ret i32 undef +} diff --git a/llvm/test/Transforms/SLPVectorizer/X86/store-insertelement-minbitwidth.ll b/llvm/test/Transforms/SLPVectorizer/X86/store-insertelement-minbitwidth.ll index c1dd90d0e9a7bbf6fa9c5f0da46a022f4efb7d6d..2f6868d8dfd628ebdb682ecd95d10ee06e4b8f35 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/store-insertelement-minbitwidth.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/store-insertelement-minbitwidth.ll @@ -8,17 +8,18 @@ ; YAML-NEXT: Function: stores ; YAML-NEXT: Args: ; YAML-NEXT: - String: 'Stores SLP vectorized with cost ' -; YAML-NEXT: - Cost: '-3' +; YAML-NEXT: - Cost: '-7' ; YAML-NEXT: - String: ' and with tree size ' ; YAML-NEXT: - TreeSize: '6' define void @stores(ptr noalias %in, ptr noalias %inn, ptr noalias %out) { ; CHECK-LABEL: @stores( ; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i8>, ptr [[IN:%.*]], align 1 ; CHECK-NEXT: [[TMP2:%.*]] = load <4 x i8>, ptr [[INN:%.*]], align 1 -; CHECK-NEXT: [[TMP3:%.*]] = zext <4 x i8> [[TMP1]] to <4 x i64> -; CHECK-NEXT: [[TMP4:%.*]] = zext <4 x i8> [[TMP2]] to <4 x i64> -; CHECK-NEXT: [[TMP5:%.*]] = add <4 x i64> [[TMP3]], [[TMP4]] -; CHECK-NEXT: store <4 x i64> [[TMP5]], ptr [[OUT:%.*]], align 4 +; CHECK-NEXT: [[TMP3:%.*]] = zext <4 x i8> [[TMP1]] to <4 x i16> +; CHECK-NEXT: [[TMP4:%.*]] = zext <4 x i8> [[TMP2]] to <4 x i16> +; CHECK-NEXT: [[TMP5:%.*]] = add <4 x i16> [[TMP3]], [[TMP4]] +; CHECK-NEXT: [[TMP6:%.*]] = zext <4 x i16> [[TMP5]] to <4 x i64> +; CHECK-NEXT: store <4 x i64> [[TMP6]], ptr [[OUT:%.*]], align 4 ; CHECK-NEXT: ret void ; %load.1 = load i8, ptr %in, align 1 @@ -63,17 +64,18 @@ define void @stores(ptr noalias %in, ptr noalias %inn, ptr noalias %out) { ; YAML-NEXT: Function: insertelems ; YAML-NEXT: Args: ; YAML-NEXT: - String: 'SLP vectorized with cost ' -; YAML-NEXT: - Cost: '-5' +; YAML-NEXT: - Cost: '-9' ; YAML-NEXT: - String: ' and with tree size ' ; YAML-NEXT: - TreeSize: '6' define <4 x i64> @insertelems(ptr noalias %in, ptr noalias %inn) { ; CHECK-LABEL: @insertelems( ; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i8>, ptr [[IN:%.*]], align 1 ; CHECK-NEXT: [[TMP2:%.*]] = load <4 x i8>, ptr [[INN:%.*]], align 1 -; CHECK-NEXT: [[TMP3:%.*]] = zext <4 x i8> [[TMP1]] to <4 x i64> -; CHECK-NEXT: [[TMP4:%.*]] = zext <4 x i8> [[TMP2]] to <4 x i64> -; CHECK-NEXT: [[TMP5:%.*]] = add <4 x i64> [[TMP3]], [[TMP4]] -; CHECK-NEXT: ret <4 x i64> [[TMP5]] +; CHECK-NEXT: [[TMP3:%.*]] = zext <4 x i8> [[TMP1]] to <4 x i16> +; CHECK-NEXT: [[TMP4:%.*]] = zext <4 x i8> [[TMP2]] to <4 x i16> +; CHECK-NEXT: [[TMP5:%.*]] = add <4 x i16> [[TMP3]], [[TMP4]] +; CHECK-NEXT: [[TMP6:%.*]] = zext <4 x i16> [[TMP5]] to <4 x i64> +; CHECK-NEXT: ret <4 x i64> [[TMP6]] ; %load.1 = load i8, ptr %in, align 1 %gep.1 = getelementptr inbounds i8, ptr %in, i64 1 diff --git a/llvm/test/Transforms/SLPVectorizer/X86/vect_copyable_in_binops.ll b/llvm/test/Transforms/SLPVectorizer/X86/vect_copyable_in_binops.ll index 22cd408cd6dc7f359af36e922a3a97dcfb95c7f1..e8395fe69ea6bfbd0ff17a09014391502685349b 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/vect_copyable_in_binops.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/vect_copyable_in_binops.ll @@ -179,11 +179,11 @@ define void @addsub0(ptr noalias %dst, ptr noalias %src) { ; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[INCDEC_PTR]], align 4 ; CHECK-NEXT: [[INCDEC_PTR3:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 2 ; CHECK-NEXT: store i32 [[TMP1]], ptr [[INCDEC_PTR1]], align 4 -; CHECK-NEXT: [[TMP3:%.*]] = load <2 x i32>, ptr [[INCDEC_PTR2]], align 4 -; CHECK-NEXT: [[TMP4:%.*]] = add nsw <2 x i32> [[TMP3]], <i32 -2, i32 -3> -; CHECK-NEXT: [[TMP5:%.*]] = sub nsw <2 x i32> [[TMP3]], <i32 -2, i32 -3> -; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <2 x i32> [[TMP4]], <2 x i32> [[TMP5]], <2 x i32> <i32 0, i32 3> -; CHECK-NEXT: store <2 x i32> [[TMP6]], ptr [[INCDEC_PTR3]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = load <2 x i32>, ptr [[INCDEC_PTR2]], align 4 +; CHECK-NEXT: [[TMP3:%.*]] = add nsw <2 x i32> [[TMP2]], <i32 -2, i32 -3> +; CHECK-NEXT: [[TMP4:%.*]] = sub nsw <2 x i32> [[TMP2]], <i32 -2, i32 -3> +; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <2 x i32> [[TMP3]], <2 x i32> [[TMP4]], <2 x i32> <i32 0, i32 3> +; CHECK-NEXT: store <2 x i32> [[TMP5]], ptr [[INCDEC_PTR3]], align 4 ; CHECK-NEXT: ret void ; entry: @@ -212,11 +212,11 @@ define void @addsub1(ptr noalias %dst, ptr noalias %src) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[INCDEC_PTR2:%.*]] = getelementptr inbounds i32, ptr [[SRC:%.*]], i64 2 ; CHECK-NEXT: [[INCDEC_PTR3:%.*]] = getelementptr inbounds i32, ptr [[DST:%.*]], i64 2 -; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr [[SRC]], align 4 -; CHECK-NEXT: [[TMP2:%.*]] = add nsw <2 x i32> [[TMP1]], <i32 -1, i32 -1> -; CHECK-NEXT: [[TMP3:%.*]] = sub nsw <2 x i32> [[TMP1]], <i32 -1, i32 -1> -; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <2 x i32> [[TMP2]], <2 x i32> [[TMP3]], <2 x i32> <i32 0, i32 3> -; CHECK-NEXT: store <2 x i32> [[TMP4]], ptr [[DST]], align 4 +; CHECK-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr [[SRC]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = add nsw <2 x i32> [[TMP0]], <i32 -1, i32 -1> +; CHECK-NEXT: [[TMP2:%.*]] = sub nsw <2 x i32> [[TMP0]], <i32 -1, i32 -1> +; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <2 x i32> [[TMP1]], <2 x i32> [[TMP2]], <2 x i32> <i32 0, i32 3> +; CHECK-NEXT: store <2 x i32> [[TMP3]], ptr [[DST]], align 4 ; CHECK-NEXT: [[INCDEC_PTR4:%.*]] = getelementptr inbounds i32, ptr [[SRC]], i64 3 ; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[INCDEC_PTR2]], align 4 ; CHECK-NEXT: [[INCDEC_PTR6:%.*]] = getelementptr inbounds i32, ptr [[DST]], i64 3 @@ -531,11 +531,11 @@ define void @addsub0f(ptr noalias %dst, ptr noalias %src) { ; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[INCDEC_PTR]], align 4 ; CHECK-NEXT: [[INCDEC_PTR3:%.*]] = getelementptr inbounds float, ptr [[DST]], i64 2 ; CHECK-NEXT: store float [[TMP1]], ptr [[INCDEC_PTR1]], align 4 -; CHECK-NEXT: [[TMP3:%.*]] = load <2 x float>, ptr [[INCDEC_PTR2]], align 4 -; CHECK-NEXT: [[TMP4:%.*]] = fadd fast <2 x float> [[TMP3]], <float -2.000000e+00, float -3.000000e+00> -; CHECK-NEXT: [[TMP5:%.*]] = fsub fast <2 x float> [[TMP3]], <float -2.000000e+00, float -3.000000e+00> -; CHECK-NEXT: [[TMP6:%.*]] = shufflevector <2 x float> [[TMP4]], <2 x float> [[TMP5]], <2 x i32> <i32 0, i32 3> -; CHECK-NEXT: store <2 x float> [[TMP6]], ptr [[INCDEC_PTR3]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = load <2 x float>, ptr [[INCDEC_PTR2]], align 4 +; CHECK-NEXT: [[TMP3:%.*]] = fadd fast <2 x float> [[TMP2]], <float -2.000000e+00, float -3.000000e+00> +; CHECK-NEXT: [[TMP4:%.*]] = fsub fast <2 x float> [[TMP2]], <float -2.000000e+00, float -3.000000e+00> +; CHECK-NEXT: [[TMP5:%.*]] = shufflevector <2 x float> [[TMP3]], <2 x float> [[TMP4]], <2 x i32> <i32 0, i32 3> +; CHECK-NEXT: store <2 x float> [[TMP5]], ptr [[INCDEC_PTR3]], align 4 ; CHECK-NEXT: ret void ; entry: @@ -564,11 +564,11 @@ define void @addsub1f(ptr noalias %dst, ptr noalias %src) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[INCDEC_PTR2:%.*]] = getelementptr inbounds float, ptr [[SRC:%.*]], i64 2 ; CHECK-NEXT: [[INCDEC_PTR3:%.*]] = getelementptr inbounds float, ptr [[DST:%.*]], i64 2 -; CHECK-NEXT: [[TMP1:%.*]] = load <2 x float>, ptr [[SRC]], align 4 -; CHECK-NEXT: [[TMP2:%.*]] = fadd fast <2 x float> [[TMP1]], <float -1.000000e+00, float -1.000000e+00> -; CHECK-NEXT: [[TMP3:%.*]] = fsub fast <2 x float> [[TMP1]], <float -1.000000e+00, float -1.000000e+00> -; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <2 x float> [[TMP2]], <2 x float> [[TMP3]], <2 x i32> <i32 0, i32 3> -; CHECK-NEXT: store <2 x float> [[TMP4]], ptr [[DST]], align 4 +; CHECK-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr [[SRC]], align 4 +; CHECK-NEXT: [[TMP1:%.*]] = fadd fast <2 x float> [[TMP0]], <float -1.000000e+00, float -1.000000e+00> +; CHECK-NEXT: [[TMP2:%.*]] = fsub fast <2 x float> [[TMP0]], <float -1.000000e+00, float -1.000000e+00> +; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <2 x float> [[TMP1]], <2 x float> [[TMP2]], <2 x i32> <i32 0, i32 3> +; CHECK-NEXT: store <2 x float> [[TMP3]], ptr [[DST]], align 4 ; CHECK-NEXT: [[INCDEC_PTR4:%.*]] = getelementptr inbounds float, ptr [[SRC]], i64 3 ; CHECK-NEXT: [[TMP6:%.*]] = load float, ptr [[INCDEC_PTR2]], align 4 ; CHECK-NEXT: [[INCDEC_PTR6:%.*]] = getelementptr inbounds float, ptr [[DST]], i64 3 diff --git a/llvm/test/Transforms/SLPVectorizer/X86/zext-inseltpoison.ll b/llvm/test/Transforms/SLPVectorizer/X86/zext-inseltpoison.ll index d1f6c41e5c30ec2051a4ce24f5f7f30d79d7e702..27996a7064c0d80583cc20e2aab2e9e983ce9714 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/zext-inseltpoison.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/zext-inseltpoison.ll @@ -12,13 +12,8 @@ define <2 x i64> @loadext_2i8_to_2i64(ptr %p0) { ; SSE2-LABEL: @loadext_2i8_to_2i64( -; SSE2-NEXT: [[P1:%.*]] = getelementptr inbounds i8, ptr [[P0:%.*]], i64 1 -; SSE2-NEXT: [[I0:%.*]] = load i8, ptr [[P0]], align 1 -; SSE2-NEXT: [[I1:%.*]] = load i8, ptr [[P1]], align 1 -; SSE2-NEXT: [[X0:%.*]] = zext i8 [[I0]] to i64 -; SSE2-NEXT: [[X1:%.*]] = zext i8 [[I1]] to i64 -; SSE2-NEXT: [[V0:%.*]] = insertelement <2 x i64> poison, i64 [[X0]], i32 0 -; SSE2-NEXT: [[V1:%.*]] = insertelement <2 x i64> [[V0]], i64 [[X1]], i32 1 +; SSE2-NEXT: [[TMP1:%.*]] = load <2 x i8>, ptr [[P0:%.*]], align 1 +; SSE2-NEXT: [[V1:%.*]] = zext <2 x i8> [[TMP1]] to <2 x i64> ; SSE2-NEXT: ret <2 x i64> [[V1]] ; ; SLM-LABEL: @loadext_2i8_to_2i64( diff --git a/llvm/test/Transforms/SLPVectorizer/X86/zext.ll b/llvm/test/Transforms/SLPVectorizer/X86/zext.ll index 829e4bab20ffaf8e5640a88b32aaa6fb46ae9c42..94870420f2bfc61f86b6136fa5063ee4f22cb51f 100644 --- a/llvm/test/Transforms/SLPVectorizer/X86/zext.ll +++ b/llvm/test/Transforms/SLPVectorizer/X86/zext.ll @@ -12,13 +12,8 @@ define <2 x i64> @loadext_2i8_to_2i64(ptr %p0) { ; SSE2-LABEL: @loadext_2i8_to_2i64( -; SSE2-NEXT: [[P1:%.*]] = getelementptr inbounds i8, ptr [[P0:%.*]], i64 1 -; SSE2-NEXT: [[I0:%.*]] = load i8, ptr [[P0]], align 1 -; SSE2-NEXT: [[I1:%.*]] = load i8, ptr [[P1]], align 1 -; SSE2-NEXT: [[X0:%.*]] = zext i8 [[I0]] to i64 -; SSE2-NEXT: [[X1:%.*]] = zext i8 [[I1]] to i64 -; SSE2-NEXT: [[V0:%.*]] = insertelement <2 x i64> undef, i64 [[X0]], i32 0 -; SSE2-NEXT: [[V1:%.*]] = insertelement <2 x i64> [[V0]], i64 [[X1]], i32 1 +; SSE2-NEXT: [[TMP1:%.*]] = load <2 x i8>, ptr [[P0:%.*]], align 1 +; SSE2-NEXT: [[V1:%.*]] = zext <2 x i8> [[TMP1]] to <2 x i64> ; SSE2-NEXT: ret <2 x i64> [[V1]] ; ; SLM-LABEL: @loadext_2i8_to_2i64( diff --git a/llvm/test/Transforms/SLPVectorizer/alt-cmp-vectorize.ll b/llvm/test/Transforms/SLPVectorizer/alt-cmp-vectorize.ll index 061fbdb45a13bc3ae82be4ecdb661f8d67750d95..ff6f0bdd3db8f2f5c14c23c149470531930f511c 100644 --- a/llvm/test/Transforms/SLPVectorizer/alt-cmp-vectorize.ll +++ b/llvm/test/Transforms/SLPVectorizer/alt-cmp-vectorize.ll @@ -10,8 +10,8 @@ define i32 @alt_cmp(i16 %call46) { ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult <4 x i16> [[TMP0]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = icmp ugt <4 x i16> [[TMP0]], [[TMP1]] ; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <4 x i1> [[TMP2]], <4 x i1> [[TMP3]], <4 x i32> <i32 0, i32 5, i32 2, i32 3> -; CHECK-NEXT: [[TMP5:%.*]] = zext <4 x i1> [[TMP4]] to <4 x i16> -; CHECK-NEXT: [[TMP6:%.*]] = call i16 @llvm.vector.reduce.or.v4i16(<4 x i16> [[TMP5]]) +; CHECK-NEXT: [[TMP5:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[TMP4]]) +; CHECK-NEXT: [[TMP6:%.*]] = zext i1 [[TMP5]] to i16 ; CHECK-NEXT: [[OP_RDX:%.*]] = or i16 [[TMP6]], 0 ; CHECK-NEXT: [[EXT:%.*]] = zext i16 [[OP_RDX]] to i32 ; CHECK-NEXT: ret i32 [[EXT]] diff --git a/llvm/test/Transforms/SLPVectorizer/orig-btiwidth-les-projected.ll b/llvm/test/Transforms/SLPVectorizer/orig-btiwidth-les-projected.ll new file mode 100644 index 0000000000000000000000000000000000000000..531e964053482ec5f2c3c0709beb9fa7535d96b5 --- /dev/null +++ b/llvm/test/Transforms/SLPVectorizer/orig-btiwidth-les-projected.ll @@ -0,0 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt -S --passes=slp-vectorizer < %s | FileCheck %s + +define i32 @test(i4 %0) { +; CHECK-LABEL: define i32 @test( +; CHECK-SAME: i4 [[TMP0:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP1:%.*]] = trunc i8 0 to i4 +; CHECK-NEXT: [[TMP2:%.*]] = trunc i8 0 to i4 +; CHECK-NEXT: [[ADD_R:%.*]] = or i4 [[TMP1]], [[TMP0]] +; CHECK-NEXT: [[ADD_R14:%.*]] = or i4 0, [[TMP2]] +; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i4 [[ADD_R]], [[ADD_R14]] +; CHECK-NEXT: ret i32 0 +; +entry: + %1 = trunc i8 0 to i4 + %2 = trunc i8 0 to i4 + %add.r = or i4 %1, %0 + %add.r14 = or i4 0, %2 + %cmp.not = icmp eq i4 %add.r, %add.r14 + ret i32 0 +} diff --git a/llvm/test/Transforms/SampleProfile/Inputs/csspgo-import-list-preinliner.prof b/llvm/test/Transforms/SampleProfile/Inputs/csspgo-import-list-preinliner.prof new file mode 100644 index 0000000000000000000000000000000000000000..7388d574be5e8b59aa06a846c569961a27ab9daa --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/Inputs/csspgo-import-list-preinliner.prof @@ -0,0 +1,14 @@ +main:8001:0 + 1: 0 + 2: 2000 + 3: 2000 + 4: 0 + 5: 2000 + 6: 2000 + 7: 0 + 8: 0 + 9: bar:1 + 1: 1 + !CFGChecksum: 4294967295 + !Attributes: 2 + !CFGChecksum: 563088156202820 diff --git a/llvm/test/Transforms/SampleProfile/Inputs/pseudo-probe-callee-profile-mismatch.prof b/llvm/test/Transforms/SampleProfile/Inputs/pseudo-probe-callee-profile-mismatch.prof new file mode 100644 index 0000000000000000000000000000000000000000..76a8fc9d19a85d03c93e259a29b954be9f292b99 --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/Inputs/pseudo-probe-callee-profile-mismatch.prof @@ -0,0 +1,16 @@ +main:252:0 + 1: 0 + 2: 50 + 5: 50 + 7: bar:102 + 1: 51 + 2: baz:51 + 1: 51 + !CFGChecksum: 4294967295 + !Attributes: 3 + !CFGChecksum: 281479271677951 + !Attributes: 2 + !CFGChecksum: 281582081721716 +bar:1:1 + 1: 1 + !CFGChecksum: 281479271677951 diff --git a/llvm/test/Transforms/SampleProfile/csspgo-import-list-preinliner.ll b/llvm/test/Transforms/SampleProfile/csspgo-import-list-preinliner.ll new file mode 100644 index 0000000000000000000000000000000000000000..9e342f2b99da33d0244bce2ab309a3072243561b --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/csspgo-import-list-preinliner.ll @@ -0,0 +1,50 @@ +; RUN: opt < %s -passes='thinlto-pre-link<O2>' -pgo-kind=pgo-sample-use-pipeline -sample-profile-file=%S/Inputs/csspgo-import-list-preinliner.prof -S -profile-summary-cutoff-hot=100000 -sample-profile-use-preinliner=0 | FileCheck %s --check-prefix=DISABLE-PREINLINE +; RUN: opt < %s -passes='thinlto-pre-link<O2>' -pgo-kind=pgo-sample-use-pipeline -sample-profile-file=%S/Inputs/csspgo-import-list-preinliner.prof -S -profile-summary-cutoff-hot=100000 | FileCheck %s + +; The GUID of bar is -2012135647395072713 + +; DISABLE-PREINLINE-NOT: -2012135647395072713 +; CHECK: [[#]] = !{!"function_entry_count", i64 1, i64 -2012135647395072713} + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i32 @main() #0 { +entry: + br label %for.cond + +for.cond: ; preds = %for.cond, %entry + call void @llvm.pseudoprobe(i64 0, i64 0, i32 0, i64 0) + %call2 = call i32 @bar(), !dbg !9 + br label %for.cond +} + +declare i32 @bar() + +; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) +declare void @llvm.pseudoprobe(i64, i64, i32, i64) #1 + +attributes #0 = { "use-sample-profile" } +attributes #1 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!7} +!llvm.pseudo_probe_desc = !{!8} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 19.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "test.c", directory: "/home/", checksumkind: CSK_MD5, checksum: "1bff37d8b3f7858b0bc29ab4efdf9422") +!2 = !{!3} +!3 = !DIGlobalVariableExpression(var: !4, expr: !DIExpression()) +!4 = distinct !DIGlobalVariable(name: "x", scope: !0, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true) +!5 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !6) +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!7 = !{i32 2, !"Debug Info Version", i32 3} +!8 = !{i64 -2624081020897602054, i64 563108639284859, !"main"} +!9 = !DILocation(line: 11, column: 10, scope: !10) +!10 = !DILexicalBlockFile(scope: !11, file: !1, discriminator: 186646615) +!11 = distinct !DILexicalBlock(scope: !12, file: !1, line: 8, column: 40) +!12 = distinct !DILexicalBlock(scope: !13, file: !1, line: 8, column: 3) +!13 = distinct !DILexicalBlock(scope: !14, file: !1, line: 8, column: 3) +!14 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 6, type: !15, scopeLine: 7, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !16) +!15 = distinct !DISubroutineType(types: !16) +!16 = !{} diff --git a/llvm/test/Transforms/SampleProfile/csspgo-profile-checksum-mismatch-attr.ll b/llvm/test/Transforms/SampleProfile/csspgo-profile-checksum-mismatch-attr.ll new file mode 100644 index 0000000000000000000000000000000000000000..df56b55dcdf3c0532e5c91315e247c2af691af07 --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/csspgo-profile-checksum-mismatch-attr.ll @@ -0,0 +1,67 @@ +; REQUIRES: x86_64-linux +; REQUIRES: asserts +; RUN: opt < %s -passes='thinlto-pre-link<O2>' -pgo-kind=pgo-sample-use-pipeline -sample-profile-file=%S/Inputs/pseudo-probe-callee-profile-mismatch.prof -pass-remarks=inline -S -o %t 2>&1 | FileCheck %s --check-prefix=INLINE +; RUN: FileCheck %s < %t +; RUN: FileCheck %s < %t --check-prefix=MERGE + + +; Make sure bar is inlined into main for attr merging verification. +; INLINE: 'bar' inlined into 'main' + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i32 @baz() #0 { +entry: + ret i32 0 +} + +define i32 @bar() #0 !dbg !11 { +; CHECK: define {{.*}} @bar() {{.*}} #[[#BAR_ATTR:]] ! +entry: + %call = call i32 @baz() + ret i32 0 +} + +define i32 @main() #0 { +; MERGE: define {{.*}} @main() {{.*}} #[[#MAIN_ATTR:]] ! +entry: + br label %for.cond + +for.cond: ; preds = %for.cond, %entry + %call = call i32 @bar(), !dbg !14 + br label %for.cond +} + +; CHECK: attributes #[[#BAR_ATTR]] = {{{.*}} "profile-checksum-mismatch" {{.*}}} + +; Verify the attribute is not merged into the caller. +; MERGE-NOT: attributes #[[#MAIN_ATTR]] = {{{.*}} "profile-checksum-mismatch" {{.*}}} + +attributes #0 = { "use-sample-profile" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!7} +!llvm.pseudo_probe_desc = !{!8, !9, !10} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 19.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "test.c", directory: "/home", checksumkind: CSK_MD5, checksum: "0df0c950a93a603a7d13f0a9d4623642") +!2 = !{!3} +!3 = !DIGlobalVariableExpression(var: !4, expr: !DIExpression()) +!4 = distinct !DIGlobalVariable(name: "x", scope: !0, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true) +!5 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !6) +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!7 = !{i32 2, !"Debug Info Version", i32 3} +!8 = !{i64 7546896869197086323, i64 4294967295, !"baz"} +!9 = !{i64 -2012135647395072713, i64 281530612780802, !"bar"} +!10 = !{i64 -2624081020897602054, i64 281582081721716, !"main"} +!11 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 5, type: !12, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !13) +!12 = distinct !DISubroutineType(types: !13) +!13 = !{} +!14 = !DILocation(line: 15, column: 10, scope: !15) +!15 = !DILexicalBlockFile(scope: !16, file: !1, discriminator: 186646591) +!16 = distinct !DILexicalBlock(scope: !17, file: !1, line: 14, column: 40) +!17 = distinct !DILexicalBlock(scope: !18, file: !1, line: 14, column: 3) +!18 = distinct !DILexicalBlock(scope: !19, file: !1, line: 14, column: 3) +!19 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 12, type: !20, scopeLine: 13, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !13) +!20 = !DISubroutineType(types: !13) diff --git a/llvm/test/Transforms/SampleProfile/pseudo-probe-callee-profile-mismatch.ll b/llvm/test/Transforms/SampleProfile/pseudo-probe-callee-profile-mismatch.ll new file mode 100644 index 0000000000000000000000000000000000000000..4881937df101ac3f5cefe8008d9b2d23afd40cb1 --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/pseudo-probe-callee-profile-mismatch.ll @@ -0,0 +1,63 @@ +; REQUIRES: x86_64-linux +; REQUIRES: asserts +; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/pseudo-probe-callee-profile-mismatch.prof --salvage-stale-profile -S --debug-only=sample-profile,sample-profile-matcher,sample-profile-impl -pass-remarks=inline 2>&1 | FileCheck %s + + +; CHECK: Run stale profile matching for bar +; CHECK: Callsite with callee:baz is matched from 4 to 2 +; CHECK: 'baz' inlined into 'main' to match profiling context with (cost=always): preinliner at callsite bar:3:8.4 @ main:3:10.7 + +; CHECK: Probe descriptor missing for Function bar +; CHECK: Profile is invalid due to CFG mismatch for Function bar + + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define i32 @main() #0 { + %1 = call i32 @bar(), !dbg !13 + ret i32 0 +} + +define available_externally i32 @bar() #1 !dbg !21 { + %1 = call i32 @baz(), !dbg !23 + ret i32 0 +} + +define available_externally i32 @baz() #0 !dbg !25 { + ret i32 0 +} + +attributes #0 = { "use-sample-profile" } +attributes #1 = { "profile-checksum-mismatch" "use-sample-profile" } + +!llvm.dbg.cu = !{!0, !7, !9} +!llvm.module.flags = !{!11} +!llvm.pseudo_probe_desc = !{!12} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 19.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "test.c", directory: "/home/test", checksumkind: CSK_MD5, checksum: "7220f1a2d70ff869f1a6ab7958e3c393") +!2 = !{!3} +!3 = !DIGlobalVariableExpression(var: !4, expr: !DIExpression()) +!4 = distinct !DIGlobalVariable(name: "x", scope: !0, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true) +!5 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !6) +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!7 = distinct !DICompileUnit(language: DW_LANG_C11, file: !8, producer: "clang version 19.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!8 = !DIFile(filename: "test1.v1.c", directory: "/home/test", checksumkind: CSK_MD5, checksum: "76696bd6bfe16a9f227fe03cfdb6a82c") +!9 = distinct !DICompileUnit(language: DW_LANG_C11, file: !10, producer: "clang version 19.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!10 = !DIFile(filename: "test2.c", directory: "/home/test", checksumkind: CSK_MD5, checksum: "553093afc026f9c73562eb3b0c5b7532") +!11 = !{i32 2, !"Debug Info Version", i32 3} +!12 = !{i64 -2624081020897602054, i64 281582081721716, !"main"} +!13 = !DILocation(line: 8, column: 10, scope: !14) +!14 = !DILexicalBlockFile(scope: !15, file: !1, discriminator: 186646591) +!15 = distinct !DILexicalBlock(scope: !16, file: !1, line: 7, column: 40) +!16 = distinct !DILexicalBlock(scope: !17, file: !1, line: 7, column: 3) +!17 = distinct !DILexicalBlock(scope: !18, file: !1, line: 7, column: 3) +!18 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 5, type: !19, scopeLine: 6, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !20) +!19 = distinct !DISubroutineType(types: !20) +!20 = !{} +!21 = distinct !DISubprogram(name: "bar", scope: !8, file: !8, line: 3, type: !22, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !7, retainedNodes: !20) +!22 = !DISubroutineType(types: !20) +!23 = !DILocation(line: 6, column: 8, scope: !24) +!24 = !DILexicalBlockFile(scope: !21, file: !8, discriminator: 186646567) +!25 = distinct !DISubprogram(name: "baz", scope: !10, file: !10, line: 1, type: !22, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !9, retainedNodes: !20) diff --git a/llvm/test/Transforms/SampleProfile/pseudo-probe-eh.ll b/llvm/test/Transforms/SampleProfile/pseudo-probe-eh.ll index 697ef44fb7ed718f5bba848bbc0735146387a743..9954914bca438069d7ff6365677b5175091dd3ba 100644 --- a/llvm/test/Transforms/SampleProfile/pseudo-probe-eh.ll +++ b/llvm/test/Transforms/SampleProfile/pseudo-probe-eh.ll @@ -18,7 +18,7 @@ entry: to label %ret unwind label %lpad ret: -; CHECK: call void @llvm.pseudoprobe +; CHECK-NOT: call void @llvm.pseudoprobe ret void lpad: ; preds = %entry diff --git a/llvm/test/Transforms/SampleProfile/pseudo-probe-invoke.ll b/llvm/test/Transforms/SampleProfile/pseudo-probe-invoke.ll new file mode 100644 index 0000000000000000000000000000000000000000..822ab403dee2974cdbe2520afc66e728162f9142 --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/pseudo-probe-invoke.ll @@ -0,0 +1,155 @@ +; REQUIRES: x86_64-linux +; RUN: opt < %s -passes=pseudo-probe -S -o - | FileCheck %s + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +$__clang_call_terminate = comdat any + +@x = dso_local global i32 0, align 4, !dbg !0 + +; Function Attrs: mustprogress noinline nounwind uwtable +define dso_local void @_Z3barv() #0 personality ptr @__gxx_personality_v0 !dbg !14 { +entry: +; CHECK: call void @llvm.pseudoprobe(i64 -1069303473483922844, i64 1 + %0 = load volatile i32, ptr @x, align 4, !dbg !17, !tbaa !19 + %tobool = icmp ne i32 %0, 0, !dbg !17 + br i1 %tobool, label %if.then, label %if.else, !dbg !23 + +if.then: ; preds = %entry +; CHECK: call void @llvm.pseudoprobe(i64 -1069303473483922844, i64 2 + invoke void @_Z3foov() + to label %invoke.cont unwind label %terminate.lpad, !dbg !24 + +invoke.cont: ; preds = %if.then +; CHECK-NOT: call void @llvm.pseudoprobe(i64 -1069303473483922844, + invoke void @_Z3bazv() + to label %invoke.cont1 unwind label %terminate.lpad, !dbg !26 + +invoke.cont1: ; preds = %invoke.cont +; CHECK-NOT: call void @llvm.pseudoprobe(i64 -1069303473483922844, + br label %if.end, !dbg !27 + +if.else: ; preds = %entry +; CHECK: call void @llvm.pseudoprobe(i64 -1069303473483922844, i64 3 + invoke void @_Z3foov() + to label %invoke.cont2 unwind label %terminate.lpad, !dbg !28 + +invoke.cont2: ; preds = %if.else +; CHECK-NOT: call void @llvm.pseudoprobe(i64 -1069303473483922844, + br label %if.end + +if.end: ; preds = %invoke.cont2, %invoke.cont1 +; CHECK: call void @llvm.pseudoprobe(i64 -1069303473483922844, i64 4 + invoke void @_Z3foov() + to label %invoke.cont3 unwind label %terminate.lpad, !dbg !29 + +invoke.cont3: ; preds = %if.end +; CHECK-NOT: call void @llvm.pseudoprobe(i64 -1069303473483922844, + %1 = load volatile i32, ptr @x, align 4, !dbg !30, !tbaa !19 + %tobool4 = icmp ne i32 %1, 0, !dbg !30 + br i1 %tobool4, label %if.then5, label %if.end6, !dbg !32 + +if.then5: ; preds = %invoke.cont3 +; CHECK: call void @llvm.pseudoprobe(i64 -1069303473483922844, i64 5 + %2 = load volatile i32, ptr @x, align 4, !dbg !33, !tbaa !19 + %inc = add nsw i32 %2, 1, !dbg !33 + store volatile i32 %inc, ptr @x, align 4, !dbg !33, !tbaa !19 + br label %if.end6, !dbg !35 + +if.end6: ; preds = %if.then5, %invoke.cont3 +; CHECK: call void @llvm.pseudoprobe(i64 -1069303473483922844, i64 6 + ret void, !dbg !36 + +terminate.lpad: ; preds = %if.end, %if.else, %invoke.cont, %if.then +; CHECK-NOT: call void @llvm.pseudoprobe(i64 -1069303473483922844, + %3 = landingpad { ptr, i32 } + catch ptr null, !dbg !24 + %4 = extractvalue { ptr, i32 } %3, 0, !dbg !24 + call void @__clang_call_terminate(ptr %4) #3, !dbg !24 + unreachable, !dbg !24 +} + +; Function Attrs: mustprogress noinline nounwind uwtable +define dso_local void @_Z3foov() #0 !dbg !37 { +entry: + ret void, !dbg !38 +} + +declare i32 @__gxx_personality_v0(...) + +; Function Attrs: noinline noreturn nounwind uwtable +define linkonce_odr hidden void @__clang_call_terminate(ptr noundef %0) #1 comdat { + %2 = call ptr @__cxa_begin_catch(ptr %0) #4 + call void @_ZSt9terminatev() #3 + unreachable +} + +declare ptr @__cxa_begin_catch(ptr) + +declare void @_ZSt9terminatev() + +; Function Attrs: mustprogress noinline nounwind uwtable +define dso_local void @_Z3bazv() #0 !dbg !39 { +entry: + ret void, !dbg !40 +} + +; CHECK: ![[#]] = !{i64 -3270123626113159616, i64 4294967295, !"_Z3bazv"} + +attributes #0 = { mustprogress noinline nounwind uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { noinline noreturn nounwind uwtable "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #2 = { mustprogress noinline norecurse nounwind uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #3 = { noreturn nounwind } +attributes #4 = { nounwind } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!7, !8, !9, !10, !11, !12} +!llvm.ident = !{!13} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "x", scope: !2, file: !3, line: 1, type: !5, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 19.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "test.cpp", directory: "/home", checksumkind: CSK_MD5, checksum: "a4c7b0392f3fd9c8ebb85065159dbb02") +!4 = !{!0} +!5 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !6) +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!7 = !{i32 7, !"Dwarf Version", i32 5} +!8 = !{i32 2, !"Debug Info Version", i32 3} +!9 = !{i32 1, !"wchar_size", i32 4} +!10 = !{i32 8, !"PIC Level", i32 2} +!11 = !{i32 7, !"PIE Level", i32 2} +!12 = !{i32 7, !"uwtable", i32 2} +!13 = !{!"clang version 19.0.0"} +!14 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !3, file: !3, line: 4, type: !15, scopeLine: 4, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2) +!15 = !DISubroutineType(types: !16) +!16 = !{null} +!17 = !DILocation(line: 5, column: 6, scope: !18) +!18 = distinct !DILexicalBlock(scope: !14, file: !3, line: 5, column: 6) +!19 = !{!20, !20, i64 0} +!20 = !{!"int", !21, i64 0} +!21 = !{!"omnipotent char", !22, i64 0} +!22 = !{!"Simple C++ TBAA"} +!23 = !DILocation(line: 5, column: 6, scope: !14) +!24 = !DILocation(line: 6, column: 5, scope: !25) +!25 = distinct !DILexicalBlock(scope: !18, file: !3, line: 5, column: 9) +!26 = !DILocation(line: 7, column: 5, scope: !25) +!27 = !DILocation(line: 8, column: 3, scope: !25) +!28 = !DILocation(line: 9, column: 5, scope: !18) +!29 = !DILocation(line: 11, column: 3, scope: !14) +!30 = !DILocation(line: 12, column: 6, scope: !31) +!31 = distinct !DILexicalBlock(scope: !14, file: !3, line: 12, column: 6) +!32 = !DILocation(line: 12, column: 6, scope: !14) +!33 = !DILocation(line: 13, column: 5, scope: !34) +!34 = distinct !DILexicalBlock(scope: !31, file: !3, line: 12, column: 9) +!35 = !DILocation(line: 14, column: 5, scope: !34) +!36 = !DILocation(line: 17, column: 1, scope: !14) +!37 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !3, file: !3, line: 19, type: !15, scopeLine: 19, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2) +!38 = !DILocation(line: 19, column: 13, scope: !37) +!39 = distinct !DISubprogram(name: "baz", linkageName: "_Z3bazv", scope: !3, file: !3, line: 18, type: !15, scopeLine: 18, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2) +!40 = !DILocation(line: 18, column: 13, scope: !39) +!41 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 22, type: !42, scopeLine: 22, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2) +!42 = !DISubroutineType(types: !43) +!43 = !{!6} +!44 = !DILocation(line: 23, column: 3, scope: !41) +!45 = !DILocation(line: 24, column: 1, scope: !41) diff --git a/llvm/test/Transforms/SampleProfile/pseudo-probe-profile-mismatch-error.ll b/llvm/test/Transforms/SampleProfile/pseudo-probe-profile-mismatch-error.ll new file mode 100644 index 0000000000000000000000000000000000000000..2bb8f677f40ca8a0e19efb75f139333ca1d13bfc --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/pseudo-probe-profile-mismatch-error.ll @@ -0,0 +1,7 @@ +; REQUIRES: x86_64-linux +; RUN: not opt < %S/pseudo-probe-profile-mismatch.ll -passes=sample-profile -sample-profile-file=%S/Inputs/pseudo-probe-profile-mismatch.prof -min-functions-for-staleness-error=1 -precent-mismatch-for-staleness-error=1 -S 2>&1 | FileCheck %s +; RUN: opt < %S/pseudo-probe-profile-mismatch.ll -passes=sample-profile -sample-profile-file=%S/Inputs/pseudo-probe-profile-mismatch.prof -min-functions-for-staleness-error=3 -precent-mismatch-for-staleness-error=70 -S 2>&1 +; RUN: opt < %S/pseudo-probe-profile-mismatch.ll -passes=sample-profile -sample-profile-file=%S/Inputs/pseudo-probe-profile-mismatch.prof -min-functions-for-staleness-error=4 -precent-mismatch-for-staleness-error=1 -S 2>&1 + + +; CHECK: error: {{.*}}: The input profile significantly mismatches current source code. Please recollect profile to avoid performance regression. diff --git a/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching-lto.ll b/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching-lto.ll index 55225b415d4abcecab0656fe88186dd69116b678..7aabeeca2585b67026e1b28ac92acdb09f2a4da5 100644 --- a/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching-lto.ll +++ b/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching-lto.ll @@ -1,6 +1,6 @@ ; REQUIRES: x86_64-linux ; REQUIRES: asserts -; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/pseudo-probe-stale-profile-matching-lto.prof --salvage-stale-profile -S --debug-only=sample-profile,sample-profile-impl 2>&1 | FileCheck %s +; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/pseudo-probe-stale-profile-matching-lto.prof --salvage-stale-profile -S --debug-only=sample-profile,sample-profile-matcher,sample-profile-impl 2>&1 | FileCheck %s ; CHECK: Run stale profile matching for main @@ -106,7 +106,7 @@ define available_externally dso_local i32 @bar(i32 noundef %0) local_unnamed_add ret i32 %2, !dbg !132 } -attributes #0 = { nounwind uwtable "disable-tail-calls"="true" "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "use-sample-profile" } +attributes #0 = { nounwind uwtable "disable-tail-calls"="true" "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "use-sample-profile" "profile-checksum-mismatch"} attributes #1 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) } attributes #2 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } attributes #3 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable "disable-tail-calls"="true" "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "use-sample-profile" } diff --git a/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching.ll b/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching.ll index 89477ea5fecf1ee30a513b86cc95f255f8e57d6e..0d471e43d2a723ced9246d2027f4a8c517a8565c 100644 --- a/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching.ll +++ b/llvm/test/Transforms/SampleProfile/pseudo-probe-stale-profile-matching.ll @@ -1,6 +1,6 @@ ; REQUIRES: x86_64-linux ; REQUIRES: asserts -; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/pseudo-probe-stale-profile-matching.prof --salvage-stale-profile -S --debug-only=sample-profile,sample-profile-impl 2>&1 | FileCheck %s +; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/pseudo-probe-stale-profile-matching.prof --salvage-stale-profile -S --debug-only=sample-profile,sample-profile-matcher,sample-profile-impl 2>&1 | FileCheck %s ; The profiled source code: @@ -48,6 +48,8 @@ ; } ; } +; Verify not running profile matching for checksum matched function. +; CHECK-NOT: Run stale profile matching for bar ; CHECK: Run stale profile matching for main diff --git a/llvm/test/Transforms/SampleProfile/remarks-hotness.ll b/llvm/test/Transforms/SampleProfile/remarks-hotness.ll index b90b21e9e3c582608be5121b24bfdab90f3197c3..36fb3c58181703d106feccbf4aac415a49d8500f 100644 --- a/llvm/test/Transforms/SampleProfile/remarks-hotness.ll +++ b/llvm/test/Transforms/SampleProfile/remarks-hotness.ll @@ -24,7 +24,7 @@ ; YAML-PASS: --- !Passed ; YAML-PASS-NEXT: Pass: inline -; YAML-PASS-NEXT: Name: AlwaysInline +; YAML-PASS-NEXT: Name: Inlined ; YAML-PASS-NEXT: DebugLoc: { File: remarks-hotness.cpp, Line: 10, Column: 10 } ; YAML-PASS-NEXT: Function: _Z7caller1v ; YAML-PASS-NEXT: Hotness: 401 @@ -36,7 +36,7 @@ ; YAML-MISS-NEXT: Function: _Z7caller2v ; YAML-MISS-NEXT: Hotness: 2 -; CHECK-RPASS: '_Z7callee1v' inlined into '_Z7caller1v' with (cost=always): benefit over cost at callsite _Z7caller1v:1:10; (hotness: 401) +; CHECK-RPASS: '_Z7callee1v' inlined into '_Z7caller1v' with (cost=-30, threshold=4500) at callsite _Z7caller1v:1:10; (hotness: 401) ; CHECK-RPASS-NOT: '_Z7callee2v' not inlined into '_Z7caller2v' because it should never be inlined (cost=never): noinline function attribute (hotness: 2) ; ModuleID = 'remarks-hotness.cpp' diff --git a/llvm/test/Transforms/SimplifyCFG/HoistCode.ll b/llvm/test/Transforms/SimplifyCFG/HoistCode.ll index a081eddfc45660c780632b23bd89682c3bab1aac..4a4c94098ab94c03776c2d017fc570b2a0fc01ae 100644 --- a/llvm/test/Transforms/SimplifyCFG/HoistCode.ll +++ b/llvm/test/Transforms/SimplifyCFG/HoistCode.ll @@ -64,8 +64,8 @@ define float @PR39535min_switch(i64 %i, float %x) { ; CHECK-LABEL: @PR39535min_switch( ; CHECK-NEXT: entry: ; CHECK-NEXT: switch i64 [[I:%.*]], label [[END:%.*]] [ -; CHECK-NEXT: i64 1, label [[BB1:%.*]] -; CHECK-NEXT: i64 2, label [[BB2:%.*]] +; CHECK-NEXT: i64 1, label [[BB1:%.*]] +; CHECK-NEXT: i64 2, label [[BB2:%.*]] ; CHECK-NEXT: ] ; CHECK: bb1: ; CHECK-NEXT: br label [[END]] @@ -154,3 +154,33 @@ F: %z2 = or disjoint i32 %x, %y ret i32 %z2 } + +define i16 @hoist_trunc_flags_preserve(i1 %C, i32 %x) { +; CHECK-LABEL: @hoist_trunc_flags_preserve( +; CHECK-NEXT: common.ret: +; CHECK-NEXT: [[Z1:%.*]] = trunc nuw nsw i32 [[X:%.*]] to i16 +; CHECK-NEXT: ret i16 [[Z1]] +; + br i1 %C, label %T, label %F +T: + %z1 = trunc nsw nuw i32 %x to i16 + ret i16 %z1 +F: + %z2 = trunc nsw nuw i32 %x to i16 + ret i16 %z2 +} + +define i16 @hoist_trunc_flags_drop(i1 %C, i32 %x) { +; CHECK-LABEL: @hoist_trunc_flags_drop( +; CHECK-NEXT: common.ret: +; CHECK-NEXT: [[Z1:%.*]] = trunc i32 [[X:%.*]] to i16 +; CHECK-NEXT: ret i16 [[Z1]] +; + br i1 %C, label %T, label %F +T: + %z1 = trunc i32 %x to i16 + ret i16 %z1 +F: + %z2 = trunc nsw nuw i32 %x to i16 + ret i16 %z2 +} diff --git a/llvm/test/Transforms/SpeculativeExecution/PR46267.ll b/llvm/test/Transforms/SpeculativeExecution/PR46267.ll index d940ee6a7863d7b42cb2ea7190767dbe46f989c4..69dac2220d9a6473f9b22b3b37ae65e01274b667 100644 --- a/llvm/test/Transforms/SpeculativeExecution/PR46267.ll +++ b/llvm/test/Transforms/SpeculativeExecution/PR46267.ll @@ -31,7 +31,6 @@ define void @f(i32 %i) { entry: ; CHECK-LABEL: @f( ; CHECK: %a2 = add i32 %i, 0 -; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 %a2 br i1 undef, label %land.rhs, label %land.end land.rhs: ; preds = %entry @@ -42,6 +41,7 @@ land.rhs: ; preds = %entry ; CHECK-NEXT: %a0 = load i32, ptr undef, align 1 ; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 %a0 ; CHECK-NEXT: call void @llvm.dbg.label +; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 %a2 call void @llvm.dbg.label(metadata !11), !dbg !10 %y = alloca i32, align 4 call void @llvm.dbg.declare(metadata ptr %y, metadata !14, metadata !DIExpression()), !dbg !10 diff --git a/llvm/test/Transforms/TailCallElim/debugloc.ll b/llvm/test/Transforms/TailCallElim/debugloc.ll index 3abbd6552efce335893bb2c3c2dd75b03bed5f44..49957695a421b9f15ff9241123d9fc0b77d4752e 100644 --- a/llvm/test/Transforms/TailCallElim/debugloc.ll +++ b/llvm/test/Transforms/TailCallElim/debugloc.ll @@ -4,13 +4,13 @@ define void @foo() { entry: ; CHECK-LABEL: entry: -; CHECK: br label %tailrecurse, !dbg ![[DbgLoc:[0-9]+]] +; CHECK: br label %tailrecurse{{$}} call void @foo() ;; line 1 ret void ; CHECK-LABEL: tailrecurse: -; CHECK: br label %tailrecurse, !dbg ![[DbgLoc]] +; CHECK: br label %tailrecurse, !dbg ![[DbgLoc:[0-9]+]] } ;; Make sure tailrecurse has the call instruction's DL diff --git a/llvm/test/Transforms/ThinLTOBitcodeWriter/pr33536.ll b/llvm/test/Transforms/ThinLTOBitcodeWriter/pr33536.ll index 8e78921c556d58cc11ddd725acd1dbefbe224fdb..a51c1d24956a116ef73a860547704c6ad08f8a1b 100644 --- a/llvm/test/Transforms/ThinLTOBitcodeWriter/pr33536.ll +++ b/llvm/test/Transforms/ThinLTOBitcodeWriter/pr33536.ll @@ -12,7 +12,7 @@ target triple = "x86_64-unknown-linux-gnu" ; M0: @global = local_unnamed_addr global ; M1-NOT: @global -@global = local_unnamed_addr global %struct.hoge { %struct.widget { ptr getelementptr inbounds ({ [3 x ptr] }, ptr @global.1, i32 0, inrange i32 0, i32 2) } }, align 8 +@global = local_unnamed_addr global %struct.hoge { %struct.widget { ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @global.1, i32 0, i32 0, i32 2) } }, align 8 ; M0: @global.1 = external unnamed_addr constant ; M1: @global.1 = linkonce_odr unnamed_addr constant diff --git a/llvm/test/Transforms/VectorCombine/X86/shuffle-inseltpoison.ll b/llvm/test/Transforms/VectorCombine/X86/shuffle-inseltpoison.ll index 8c5c6656ca1795b37f69a0cc2ec3cfc0a81882ec..74a58c8d313611783a61464e3dcf80363c1f522a 100644 --- a/llvm/test/Transforms/VectorCombine/X86/shuffle-inseltpoison.ll +++ b/llvm/test/Transforms/VectorCombine/X86/shuffle-inseltpoison.ll @@ -133,8 +133,7 @@ define <2 x i64> @PR35454_1(<2 x i64> %v) { ; SSE-NEXT: ret <2 x i64> [[BC3]] ; ; AVX-LABEL: @PR35454_1( -; AVX-NEXT: [[BC:%.*]] = bitcast <2 x i64> [[V:%.*]] to <4 x i32> -; AVX-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[BC]] to <16 x i8> +; AVX-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[V:%.*]] to <16 x i8> ; AVX-NEXT: [[BC1:%.*]] = shufflevector <16 x i8> [[TMP1]], <16 x i8> poison, <16 x i32> <i32 12, i32 13, i32 14, i32 15, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3> ; AVX-NEXT: [[ADD:%.*]] = shl <16 x i8> [[BC1]], <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> ; AVX-NEXT: [[BC2:%.*]] = bitcast <16 x i8> [[ADD]] to <4 x i32> @@ -164,8 +163,7 @@ define <2 x i64> @PR35454_2(<2 x i64> %v) { ; SSE-NEXT: ret <2 x i64> [[BC3]] ; ; AVX-LABEL: @PR35454_2( -; AVX-NEXT: [[BC:%.*]] = bitcast <2 x i64> [[V:%.*]] to <4 x i32> -; AVX-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[BC]] to <8 x i16> +; AVX-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[V:%.*]] to <8 x i16> ; AVX-NEXT: [[BC1:%.*]] = shufflevector <8 x i16> [[TMP1]], <8 x i16> poison, <8 x i32> <i32 6, i32 7, i32 4, i32 5, i32 2, i32 3, i32 0, i32 1> ; AVX-NEXT: [[ADD:%.*]] = shl <8 x i16> [[BC1]], <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> ; AVX-NEXT: [[BC2:%.*]] = bitcast <8 x i16> [[ADD]] to <4 x i32> diff --git a/llvm/test/Transforms/VectorCombine/X86/shuffle.ll b/llvm/test/Transforms/VectorCombine/X86/shuffle.ll index 60cfc4d4b0707966f34c347c77f3095073faca02..d1484fd5ab33999895503f25b741b33a83858a52 100644 --- a/llvm/test/Transforms/VectorCombine/X86/shuffle.ll +++ b/llvm/test/Transforms/VectorCombine/X86/shuffle.ll @@ -133,8 +133,7 @@ define <2 x i64> @PR35454_1(<2 x i64> %v) { ; SSE-NEXT: ret <2 x i64> [[BC3]] ; ; AVX-LABEL: @PR35454_1( -; AVX-NEXT: [[BC:%.*]] = bitcast <2 x i64> [[V:%.*]] to <4 x i32> -; AVX-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[BC]] to <16 x i8> +; AVX-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[V:%.*]] to <16 x i8> ; AVX-NEXT: [[BC1:%.*]] = shufflevector <16 x i8> [[TMP1]], <16 x i8> poison, <16 x i32> <i32 12, i32 13, i32 14, i32 15, i32 8, i32 9, i32 10, i32 11, i32 4, i32 5, i32 6, i32 7, i32 0, i32 1, i32 2, i32 3> ; AVX-NEXT: [[ADD:%.*]] = shl <16 x i8> [[BC1]], <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1> ; AVX-NEXT: [[BC2:%.*]] = bitcast <16 x i8> [[ADD]] to <4 x i32> @@ -164,8 +163,7 @@ define <2 x i64> @PR35454_2(<2 x i64> %v) { ; SSE-NEXT: ret <2 x i64> [[BC3]] ; ; AVX-LABEL: @PR35454_2( -; AVX-NEXT: [[BC:%.*]] = bitcast <2 x i64> [[V:%.*]] to <4 x i32> -; AVX-NEXT: [[TMP1:%.*]] = bitcast <4 x i32> [[BC]] to <8 x i16> +; AVX-NEXT: [[TMP1:%.*]] = bitcast <2 x i64> [[V:%.*]] to <8 x i16> ; AVX-NEXT: [[BC1:%.*]] = shufflevector <8 x i16> [[TMP1]], <8 x i16> poison, <8 x i32> <i32 6, i32 7, i32 4, i32 5, i32 2, i32 3, i32 0, i32 1> ; AVX-NEXT: [[ADD:%.*]] = shl <8 x i16> [[BC1]], <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1> ; AVX-NEXT: [[BC2:%.*]] = bitcast <8 x i16> [[ADD]] to <4 x i32> diff --git a/llvm/test/Verifier/intrinsic-cmp.ll b/llvm/test/Verifier/intrinsic-cmp.ll new file mode 100644 index 0000000000000000000000000000000000000000..2224a5c5eba385947ae10d09a7c7808d39c59709 --- /dev/null +++ b/llvm/test/Verifier/intrinsic-cmp.ll @@ -0,0 +1,22 @@ +; RUN: not opt -S -passes=verify 2>&1 < %s | FileCheck %s + +define void @matching_vector_lens(<4 x i32> %arg1, <4 x i32> %arg2) { + ; CHECK: return type and arguments must have the same number of elements + %res = call <8 x i32> @llvm.scmp.v8i32.v4i32(<4 x i32> %arg1, <4 x i32> %arg2) + ret void +} + +define void @result_len_is_at_least_2bits_wide(i32 %arg1, i32 %arg2) { + ; CHECK: result type must be at least 2 bits wide + %res2 = call i1 @llvm.scmp.i1.i32(i32 %arg1, i32 %arg2) + ret void +} + +define void @both_args_are_vecs_or_neither(<4 x i32> %arg1, i32 %arg2) { + ; CHECK: ucmp/scmp argument and result types must both be either vector or scalar types + %res3 = call i2 @llvm.scmp.i2.v4i32(<4 x i32> %arg1, <4 x i32> %arg1) + ; CHECK: ucmp/scmp argument and result types must both be either vector or scalar types + %res4 = call <4 x i32> @llvm.scmp.v4i32.i32(i32 %arg2, i32 %arg2) + ret void +} + diff --git a/llvm/test/Verifier/tbaa-struct.ll b/llvm/test/Verifier/tbaa-struct.ll new file mode 100644 index 0000000000000000000000000000000000000000..b8ddc7cee496a940b8e4791be52dcc542037aacb --- /dev/null +++ b/llvm/test/Verifier/tbaa-struct.ll @@ -0,0 +1,40 @@ +; RUN: llvm-as < %s 2>&1 + +; FIXME: The verifer should reject the invalid !tbaa.struct nodes below. + +define void @test_overlapping_regions(ptr %a1) { + %ld = load i8, ptr %a1, align 1, !tbaa.struct !0 + ret void +} + +define void @test_size_not_integer(ptr %a1) { + store i8 1, ptr %a1, align 1, !tbaa.struct !5 + ret void +} + +define void @test_offset_not_integer(ptr %a1, ptr %a2) { + tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %a1, ptr align 8 %a2, i64 16, i1 false), !tbaa.struct !6 + ret void +} + +define void @test_tbaa_missing(ptr %a1, ptr %a2) { + tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %a1, ptr align 8 %a2, i64 16, i1 false), !tbaa.struct !7 + ret void +} + +define void @test_tbaa_invalid(ptr %a1) { + store i8 1, ptr %a1, align 1, !tbaa.struct !8 + ret void +} + +declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind + +!0 = !{i64 0, i64 4, !1, i64 1, i64 4, !1} +!1 = !{!2, !2, i64 0} +!2 = !{!"int", !3, i64 0} +!3 = !{!"omnipotent char", !4, i64 0} +!4 = !{!"Simple C++ TBAA"} +!5 = !{i64 0, !2, !1} +!6 = !{!2, i64 0, !1} +!7 = !{i64 0, i64 4, null} +!8 = !{i64 0, i64 4, !2} diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/lanai_isel.ll.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/lanai_isel.ll.expected index 80145c5e098e05dc64f89f658ad55e7db5a2b36d..71e82eca6c3e3f62ac2e56928ac1011f73cee9e9 100644 --- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/lanai_isel.ll.expected +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/lanai_isel.ll.expected @@ -7,7 +7,7 @@ define i64 @i64_test(i64 %i) nounwind readnone { ; CHECK-NEXT: t0: ch,glue = EntryToken ; CHECK-NEXT: t5: i32,ch = LDW_RI<Mem:(load (s32) from %fixed-stack.0)> TargetFrameIndex:i32<-2>, TargetConstant:i32<0>, TargetConstant:i32<0>, t0 ; CHECK-NEXT: t7: i32 = ADD_I_LO TargetFrameIndex:i32<0>, TargetConstant:i32<0> -; CHECK-NEXT: t29: i32 = OR_I_LO t7, TargetConstant:i32<4> +; CHECK-NEXT: t29: i32 = OR_I_LO disjoint t7, TargetConstant:i32<4> ; CHECK-NEXT: t22: i32,ch = LDW_RI<Mem:(dereferenceable load (s32) from %ir.loc + 4, basealign 8)> t29, TargetConstant:i32<0>, TargetConstant:i32<0>, t0 ; CHECK-NEXT: t24: i32 = ADD_R t5, t22, TargetConstant:i32<0> ; CHECK-NEXT: t3: i32,ch = LDW_RI<Mem:(load (s32) from %fixed-stack.1, align 8)> TargetFrameIndex:i32<-1>, TargetConstant:i32<0>, TargetConstant:i32<0>, t0 @@ -52,7 +52,7 @@ define i64 @i16_test(i16 %i) nounwind readnone { ; CHECK-NEXT: t33: i32,ch = CopyFromReg t0, Register:i32 $r0 ; CHECK-NEXT: t14: ch,glue = CopyToReg t0, Register:i32 $rv, t33 ; CHECK-NEXT: t1: i32 = ADD_I_LO TargetFrameIndex:i32<-1>, TargetConstant:i32<0> -; CHECK-NEXT: t21: i32 = OR_I_LO t1, TargetConstant:i32<2> +; CHECK-NEXT: t21: i32 = OR_I_LO disjoint t1, TargetConstant:i32<2> ; CHECK-NEXT: t23: i32,ch = LDHz_RI<Mem:(load (s16) from %fixed-stack.0 + 2, basealign 4)> t21, TargetConstant:i32<0>, TargetConstant:i32<0>, t0 ; CHECK-NEXT: t22: i32,ch = LDHz_RI<Mem:(dereferenceable load (s16) from %ir.loc)> TargetFrameIndex:i32<0>, TargetConstant:i32<0>, TargetConstant:i32<0>, t0 ; CHECK-NEXT: t24: i32 = ADD_R t23, t22, TargetConstant:i32<0> @@ -75,7 +75,7 @@ define i64 @i8_test(i8 %i) nounwind readnone { ; CHECK-NEXT: t33: i32,ch = CopyFromReg t0, Register:i32 $r0 ; CHECK-NEXT: t14: ch,glue = CopyToReg t0, Register:i32 $rv, t33 ; CHECK-NEXT: t1: i32 = ADD_I_LO TargetFrameIndex:i32<-1>, TargetConstant:i32<0> -; CHECK-NEXT: t21: i32 = OR_I_LO t1, TargetConstant:i32<3> +; CHECK-NEXT: t21: i32 = OR_I_LO disjoint t1, TargetConstant:i32<3> ; CHECK-NEXT: t23: i32,ch = LDBz_RI<Mem:(load (s8) from %fixed-stack.0 + 3, basealign 4)> t21, TargetConstant:i32<0>, TargetConstant:i32<0>, t0 ; CHECK-NEXT: t22: i32,ch = LDBz_RI<Mem:(dereferenceable load (s8) from %ir.loc)> TargetFrameIndex:i32<0>, TargetConstant:i32<0>, TargetConstant:i32<0>, t0 ; CHECK-NEXT: t24: i32 = ADD_R t23, t22, TargetConstant:i32<0> diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.expected index 02d8870c61365cc60efc1b84a9e51cf8d4d476af..775649cee0e764738446214be4ad79a0afe3141c 100644 --- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.expected +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.expected @@ -41,7 +41,7 @@ declare void @_Z10sideeffectv() ; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] ; CHECK: codeRepl: ; CHECK-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]] -; CHECK-NEXT: ret void +; CHECK-NEXT: unreachable ; CHECK: exit: ; CHECK-NEXT: ret void ; @@ -52,7 +52,7 @@ declare void @_Z10sideeffectv() ; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] ; CHECK: codeRepl: ; CHECK-NEXT: call void @bar.cold.1() #[[ATTR2]] -; CHECK-NEXT: ret void +; CHECK-NEXT: unreachable ; CHECK: exit: ; CHECK-NEXT: ret void ; diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.globals.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.globals.expected index 05e57774c260e8688ced4d61564a8aa1daaace92..a8086ae2157096ccbf6dcf132486d79ed6360ec9 100644 --- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.globals.expected +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.generated.globals.expected @@ -44,7 +44,7 @@ declare void @_Z10sideeffectv() ; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] ; CHECK: codeRepl: ; CHECK-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]] -; CHECK-NEXT: ret void +; CHECK-NEXT: unreachable ; CHECK: exit: ; CHECK-NEXT: ret void ; @@ -55,7 +55,7 @@ declare void @_Z10sideeffectv() ; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] ; CHECK: codeRepl: ; CHECK-NEXT: call void @bar.cold.1() #[[ATTR2]] -; CHECK-NEXT: ret void +; CHECK-NEXT: unreachable ; CHECK: exit: ; CHECK-NEXT: ret void ; diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.expected index 36bcbe32e036344cd6402cff7813891aca3fe733..57de350dec15e8bd40e6072fe7781d7b2d917354 100644 --- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.expected +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.expected @@ -12,7 +12,7 @@ define void @foo(i32) { ; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] ; CHECK: codeRepl: ; CHECK-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]] -; CHECK-NEXT: ret void +; CHECK-NEXT: unreachable ; CHECK: exit: ; CHECK-NEXT: ret void ; @@ -36,7 +36,7 @@ define void @bar(i32) { ; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] ; CHECK: codeRepl: ; CHECK-NEXT: call void @bar.cold.1() #[[ATTR2]] -; CHECK-NEXT: ret void +; CHECK-NEXT: unreachable ; CHECK: exit: ; CHECK-NEXT: ret void ; diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.globals.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.globals.expected index db7c692a7def98642c1befc95de5a6b789e83dde..696d5c6edee6f3e2ab6b1f94e25590c816fe5a92 100644 --- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.globals.expected +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs.ll.nogenerated.globals.expected @@ -15,7 +15,7 @@ define void @foo(i32) { ; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] ; CHECK: codeRepl: ; CHECK-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]] -; CHECK-NEXT: ret void +; CHECK-NEXT: unreachable ; CHECK: exit: ; CHECK-NEXT: ret void ; @@ -39,7 +39,7 @@ define void @bar(i32) { ; CHECK-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] ; CHECK: codeRepl: ; CHECK-NEXT: call void @bar.cold.1() #[[ATTR2]] -; CHECK-NEXT: ret void +; CHECK-NEXT: unreachable ; CHECK: exit: ; CHECK-NEXT: ret void ; diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.expected index 10399951e7fbcd1a8f31fc20cb13db7c62801311..5275870b4088d7483ec479b21defccb8786d333a 100644 --- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.expected +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.expected @@ -42,7 +42,7 @@ declare void @_Z10sideeffectv() ; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] ; REUSE: codeRepl: ; REUSE-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]] -; REUSE-NEXT: ret void +; REUSE-NEXT: unreachable ; REUSE: exit: ; REUSE-NEXT: ret void ; @@ -53,7 +53,7 @@ declare void @_Z10sideeffectv() ; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] ; REUSE: codeRepl: ; REUSE-NEXT: call void @bar.cold.1() #[[ATTR2]] -; REUSE-NEXT: ret void +; REUSE-NEXT: unreachable ; REUSE: exit: ; REUSE-NEXT: ret void ; diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.globals.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.globals.expected index 0001790e66ab37db30595fc7f48078a1177017de..712ccb25ae857771acf90b7928fb124f31d15735 100644 --- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.globals.expected +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.generated.globals.expected @@ -45,7 +45,7 @@ declare void @_Z10sideeffectv() ; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] ; REUSE: codeRepl: ; REUSE-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]] -; REUSE-NEXT: ret void +; REUSE-NEXT: unreachable ; REUSE: exit: ; REUSE-NEXT: ret void ; @@ -56,7 +56,7 @@ declare void @_Z10sideeffectv() ; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] ; REUSE: codeRepl: ; REUSE-NEXT: call void @bar.cold.1() #[[ATTR2]] -; REUSE-NEXT: ret void +; REUSE-NEXT: unreachable ; REUSE: exit: ; REUSE-NEXT: ret void ; diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.expected index e05a57d06413b915a702da32e41c9d2ba59bcdbf..b5b12b770522bf2d45aaa3840a887aac12d0790a 100644 --- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.expected +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.expected @@ -13,7 +13,7 @@ define void @foo(i32) { ; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] ; REUSE: codeRepl: ; REUSE-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]] -; REUSE-NEXT: ret void +; REUSE-NEXT: unreachable ; REUSE: exit: ; REUSE-NEXT: ret void ; @@ -37,7 +37,7 @@ define void @bar(i32) { ; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] ; REUSE: codeRepl: ; REUSE-NEXT: call void @bar.cold.1() #[[ATTR2]] -; REUSE-NEXT: ret void +; REUSE-NEXT: unreachable ; REUSE: exit: ; REUSE-NEXT: ret void ; diff --git a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.globals.expected b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.globals.expected index 17be222f15c125830ebd298d4d10f00bc97e291b..7e2b991cd6fccb064cfa33eba4d944714d712d67 100644 --- a/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.globals.expected +++ b/llvm/test/tools/UpdateTestChecks/update_test_checks/Inputs/generated_funcs_prefix_reuse.ll.nogenerated.globals.expected @@ -16,7 +16,7 @@ define void @foo(i32) { ; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] ; REUSE: codeRepl: ; REUSE-NEXT: call void @foo.cold.1() #[[ATTR2:[0-9]+]] -; REUSE-NEXT: ret void +; REUSE-NEXT: unreachable ; REUSE: exit: ; REUSE-NEXT: ret void ; @@ -40,7 +40,7 @@ define void @bar(i32) { ; REUSE-NEXT: br i1 [[TMP2]], label [[CODEREPL:%.*]], label [[EXIT:%.*]] ; REUSE: codeRepl: ; REUSE-NEXT: call void @bar.cold.1() #[[ATTR2]] -; REUSE-NEXT: ret void +; REUSE-NEXT: unreachable ; REUSE: exit: ; REUSE-NEXT: ret void ; diff --git a/llvm/test/tools/dsymutil/ARM/obfuscated.test b/llvm/test/tools/dsymutil/ARM/obfuscated.test deleted file mode 100644 index 3443b8e634692b4ba22f07d984a8ed4f33b98085..0000000000000000000000000000000000000000 --- a/llvm/test/tools/dsymutil/ARM/obfuscated.test +++ /dev/null @@ -1,200 +0,0 @@ -REQUIRES: system-darwin - -RUN: dsymutil --symbol-map %p/../Inputs/obfuscated.map %p/../Inputs/obfuscated.arm64 -f -o - \ -RUN: | llvm-dwarfdump -v - \ -RUN: | FileCheck %s - -RUN: dsymutil --accelerator=Pub --symbol-map %p/../Inputs/obfuscated.map %p/../Inputs/obfuscated.arm64 -f -o - \ -RUN: | llvm-dwarfdump -v - \ -RUN: | FileCheck --check-prefix=PUB %s - -RUN: dsymutil --symbol-map %p/../Inputs/obfuscated.map %p/../Inputs/obfuscated.arm64 -f -o - \ -RUN: | llvm-dwarfdump -v - \ -RUN: | FileCheck --check-prefix=NOHIDDEN %s - -RUN: dsymutil --symbol-map %p/../Inputs/obfuscated.2.map %p/../Inputs/obfuscated.2.arm64 -f -o - \ -RUN: | llvm-dwarfdump -v - \ -RUN: | FileCheck --check-prefix=NOHIDDEN %s - -// Run with plist and make sure dsymutil finds it. -RUN: mkdir -p %t.dSYM/Contents/Resources/DWARF/ -RUN: mkdir -p %t.mapdir -RUN: cp %p/../Inputs/obfuscated.arm64 %t.dSYM/Contents/Resources/DWARF/ -RUN: cp %p/../Inputs/E828A486-8433-3A5E-B6DB-A6294D28133D.plist %t.dSYM/Contents/Resources/ -RUN: cp %p/../Inputs/obfuscated.map %t.mapdir/506AA50A-6B26-3B37-86D2-DC6EBD57B720.bcsymbolmap -RUN: dsymutil --symbol-map %t.mapdir %t.dSYM 2>&1 | FileCheck --check-prefix=OBFUSCATING %s - -// Run without plist and make sure dsymutil doesn't crash. -RUN: rm %t.dSYM/Contents/Resources/E828A486-8433-3A5E-B6DB-A6294D28133D.plist -RUN: dsymutil --symbol-map %t.mapdir %t.dSYM 2>&1 | FileCheck --check-prefix=NOTOBFUSCATING %s - -// ---------------------------------------- -// Repeat the same steps for --linker parallel. -RUN: dsymutil --linker parallel --symbol-map %p/../Inputs/obfuscated.map %p/../Inputs/obfuscated.arm64 -f -o - \ -RUN: | llvm-dwarfdump -v - \ -RUN: | FileCheck %s - -RUN: dsymutil --linker parallel --accelerator=Pub --symbol-map %p/../Inputs/obfuscated.map %p/../Inputs/obfuscated.arm64 -f -o - \ -RUN: | llvm-dwarfdump -v - \ -RUN: | FileCheck --check-prefix=PUB %s - -RUN: dsymutil --linker parallel --symbol-map %p/../Inputs/obfuscated.map %p/../Inputs/obfuscated.arm64 -f -o - \ -RUN: | llvm-dwarfdump -v - \ -RUN: | FileCheck --check-prefix=NOHIDDEN %s - -RUN: dsymutil --linker parallel --symbol-map %p/../Inputs/obfuscated.2.map %p/../Inputs/obfuscated.2.arm64 -f -o - \ -RUN: | llvm-dwarfdump -v - \ -RUN: | FileCheck --check-prefix=NOHIDDEN %s - -// Run with plist and make sure dsymutil finds it. -RUN: mkdir -p %t.dSYM/Contents/Resources/DWARF/ -RUN: mkdir -p %t.mapdir -RUN: cp %p/../Inputs/obfuscated.arm64 %t.dSYM/Contents/Resources/DWARF/ -RUN: cp %p/../Inputs/E828A486-8433-3A5E-B6DB-A6294D28133D.plist %t.dSYM/Contents/Resources/ -RUN: cp %p/../Inputs/obfuscated.map %t.mapdir/506AA50A-6B26-3B37-86D2-DC6EBD57B720.bcsymbolmap -RUN: dsymutil --linker parallel --symbol-map %t.mapdir %t.dSYM 2>&1 | FileCheck --check-prefix=OBFUSCATING %s - -// Run without plist and make sure dsymutil doesn't crash. -RUN: rm %t.dSYM/Contents/Resources/E828A486-8433-3A5E-B6DB-A6294D28133D.plist -RUN: dsymutil --linker parallel --symbol-map %t.mapdir %t.dSYM 2>&1 | FileCheck --check-prefix=NOTOBFUSCATING %s - -OBFUSCATING-NOT: not unobfuscating - -NOTOBFUSCATING: not unobfuscating - -NOHIDDEN-NOT: __hidden# - -CHECK: .debug_info contents: - -CHECK: DW_TAG_compile_unit [1] * -CHECK: DW_AT_producer [DW_FORM_strp] ( {{.*}} "Apple LLVM version 7.0.0 (clang-700.2.38.2)") -CHECK: DW_AT_name [DW_FORM_strp] ( {{.*}} "main.c") -CHECK: DW_AT_comp_dir [DW_FORM_strp] ( {{.*}} "/Users/steven/dev/alpena/tests/src") -CHECK: DW_TAG_subprogram [2] -CHECK: DW_AT_name [DW_FORM_strp] ( {{.*}} "main") - -CHECK: DW_TAG_compile_unit [1] * -CHECK: DW_AT_producer [DW_FORM_strp] ( {{.*}} "Apple LLVM version 7.0.0 (clang-700.2.38.2)") -CHECK: DW_AT_name [DW_FORM_strp] ( {{.*}} "one.c") -CHECK: DW_AT_comp_dir [DW_FORM_strp] ( {{.*}} "/Users/steven/dev/alpena/tests/src") -CHECK: DW_TAG_subprogram [2] -CHECK: DW_AT_name [DW_FORM_strp] ( {{.*}} "one") - -CHECK: DW_TAG_compile_unit [1] * -CHECK: DW_AT_producer [DW_FORM_strp] ( {{.*}} "Apple LLVM version 7.0.0 (clang-700.2.38.2)") -CHECK: DW_AT_name [DW_FORM_strp] ( {{.*}} "two.c") -CHECK: DW_AT_comp_dir [DW_FORM_strp] ( {{.*}} "/Users/steven/dev/alpena/tests/src") -CHECK: DW_TAG_subprogram [2] -CHECK: DW_AT_name [DW_FORM_strp] ( {{.*}} "two") - -CHECK: DW_TAG_compile_unit [1] * -CHECK: DW_AT_producer [DW_FORM_strp] ( {{.*}} "Apple LLVM version 7.0.0 (clang-700.2.38.2)") -CHECK: DW_AT_name [DW_FORM_strp] ( {{.*}} "three.c") -CHECK: DW_AT_comp_dir [DW_FORM_strp] ( {{.*}} "/Users/steven/dev/alpena/tests/src") -CHECK: DW_TAG_subprogram [2] -CHECK: DW_AT_name [DW_FORM_strp] ( {{.*}} "three") - -CHECK: DW_TAG_compile_unit [1] * -CHECK: DW_AT_producer [DW_FORM_strp] ( {{.*}} "Apple LLVM version 7.0.0 (clang-700.2.38.2)") -CHECK: DW_AT_name [DW_FORM_strp] ( {{.*}} "four.c") -CHECK: DW_AT_stmt_list [DW_FORM_data4] (0x0000011e) -CHECK: DW_AT_comp_dir [DW_FORM_strp] ( {{.*}} "/Users/steven/dev/alpena/tests/src") -CHECK: DW_TAG_subprogram [2] -CHECK: DW_AT_name [DW_FORM_strp] ( {{.*}} "four") - -CHECK: DW_TAG_compile_unit [1] * -CHECK: DW_AT_producer [DW_FORM_strp] ( {{.*}} "Apple LLVM version 7.0.0 (clang-700.2.38.2)") -CHECK: DW_AT_name [DW_FORM_strp] ( {{.*}} "five.c") -CHECK: DW_AT_comp_dir [DW_FORM_strp] ( {{.*}} "/Users/steven/dev/alpena/tests/src") -CHECK: DW_TAG_subprogram [2] -CHECK: DW_AT_name [DW_FORM_strp] ( {{.*}} "five") - -CHECK: DW_TAG_compile_unit [1] * -CHECK: DW_AT_producer [DW_FORM_strp] ( {{.*}} "Apple LLVM version 7.0.0 (clang-700.2.38.2)") -CHECK: DW_AT_name [DW_FORM_strp] ( {{.*}} "six.c") -CHECK: DW_AT_comp_dir [DW_FORM_strp] ( {{.*}} "/Users/steven/dev/alpena/tests/src") -CHECK: DW_TAG_subprogram [2] -CHECK: DW_AT_name [DW_FORM_strp] ( {{.*}} "six") - -CHECK: .debug_line contents: -CHECK: file_names[ 1]: -CHECK: name: "main.c" -CHECK: dir_index: 0 -CHECK: mod_time: 0x00000000 -CHECK: file_names[ 1]: -CHECK: name: "one.c" -CHECK: dir_index: 0 -CHECK: mod_time: 0x00000000 -CHECK: length: 0x00000000 -CHECK: file_names[ 1]: -CHECK: name: "two.c" -CHECK: dir_index: 0 -CHECK: mod_time: 0x00000000 -CHECK: length: 0x00000000 -CHECK: file_names[ 1]: -CHECK: name: "three.c" -CHECK: dir_index: 0 -CHECK: mod_time: 0x00000000 -CHECK: length: 0x00000000 -CHECK: file_names[ 1]: -CHECK: name: "four.c" -CHECK: dir_index: 0 -CHECK: mod_time: 0x00000000 -CHECK: length: 0x00000000 -CHECK: file_names[ 1]: -CHECK: name: "five.c" -CHECK: dir_index: 0 -CHECK: mod_time: 0x00000000 -CHECK: length: 0x00000000 -CHECK: file_names[ 1]: -CHECK: name: "six.c" -CHECK: dir_index: 0 -CHECK: mod_time: 0x00000000 -CHECK: length: 0x00000000 - -PUB: .debug_pubnames contents: -PUB: length = 0x00000017, format = DWARF32, version = 0x0002, unit_offset = 0x00000000, unit_size = 0x00000044 -PUB: 0x0000002e "main" -PUB: length = 0x00000016, format = DWARF32, version = 0x0002, unit_offset = 0x00000044, unit_size = 0x00000044 -PUB: 0x0000002e "one" -PUB: length = 0x00000016, format = DWARF32, version = 0x0002, unit_offset = 0x00000088, unit_size = 0x00000044 -PUB: 0x0000002e "two" -PUB: length = 0x00000018, format = DWARF32, version = 0x0002, unit_offset = 0x000000cc, unit_size = 0x00000044 -PUB: 0x0000002e "three" -PUB: length = 0x00000017, format = DWARF32, version = 0x0002, unit_offset = 0x00000110, unit_size = 0x00000044 -PUB: 0x0000002e "four" -PUB: length = 0x00000017, format = DWARF32, version = 0x0002, unit_offset = 0x00000154, unit_size = 0x00000044 -PUB: 0x0000002e "five" -PUB: length = 0x00000016, format = DWARF32, version = 0x0002, unit_offset = 0x00000198, unit_size = 0x00000044 -PUB: 0x0000002e "six" - -CHECK: .apple_names contents: - -CHECK: String: 0x00000091 "five" -CHECK-NEXT: Data 0 [ -CHECK-NEXT: Atom[0]: 0x00000182 -CHECK-NEXT: ] -CHECK: String: 0x0000009c "six" -CHECK-NEXT: Data 0 [ -CHECK-NEXT: Atom[0]: 0x000001c6 -CHECK-NEXT: ] -CHECK: String: 0x00000078 "three" -CHECK-NEXT: Data 0 [ -CHECK-NEXT: Atom[0]: 0x000000fa -CHECK-NEXT: ] -CHECK: String: 0x0000006c "two" -CHECK-NEXT: Data 0 [ -CHECK-NEXT: Atom[0]: 0x000000b6 -CHECK-NEXT: ] -CHECK: String: 0x00000057 "main" -CHECK-NEXT: Data 0 [ -CHECK-NEXT: Atom[0]: 0x0000002e -CHECK-NEXT: ] -CHECK: String: 0x00000085 "four" -CHECK-NEXT: Data 0 [ -CHECK-NEXT: Atom[0]: 0x0000013e -CHECK-NEXT: ] -CHECK: String: 0x00000062 "one" -CHECK-NEXT: Data 0 [ -CHECK-NEXT: Atom[0]: 0x00000072 -CHECK-NEXT: ] diff --git a/llvm/test/tools/dsymutil/Inputs/obfuscated.2.arm64 b/llvm/test/tools/dsymutil/Inputs/obfuscated.2.arm64 deleted file mode 100644 index b40e023eb4916cca1fe38388ce12b030c1a51eda..0000000000000000000000000000000000000000 Binary files a/llvm/test/tools/dsymutil/Inputs/obfuscated.2.arm64 and /dev/null differ diff --git a/llvm/test/tools/dsymutil/Inputs/obfuscated.2.map b/llvm/test/tools/dsymutil/Inputs/obfuscated.2.map deleted file mode 100644 index 6efca5960311d63c3603770aa77c2e52b0d5c74d..0000000000000000000000000000000000000000 --- a/llvm/test/tools/dsymutil/Inputs/obfuscated.2.map +++ /dev/null @@ -1,22 +0,0 @@ -BCSymbolMap Version: 2.0 -_two -_three -_four -_five -_six -LLVM version 3.9.0 (ssh://git@stash.sd.apple.com/devtools/clang.git c74ae34bd917b77f9c848bd599dfde2813fb509f) -main -main.c -/Volumes/Data/dev/BitcodeBuildTests/unit -one -one.c -two -two.c -three -three.c -four -four.c -five -five.c -six -six.c diff --git a/llvm/test/tools/dsymutil/Inputs/obfuscated.arm64 b/llvm/test/tools/dsymutil/Inputs/obfuscated.arm64 deleted file mode 100644 index 8395798be17ff1aaea4397cd38c2b0f26f465cb0..0000000000000000000000000000000000000000 Binary files a/llvm/test/tools/dsymutil/Inputs/obfuscated.arm64 and /dev/null differ diff --git a/llvm/test/tools/dsymutil/Inputs/obfuscated.map b/llvm/test/tools/dsymutil/Inputs/obfuscated.map deleted file mode 100644 index 30fed8bf9b5a574f7562d53633bc328e7d394f51..0000000000000000000000000000000000000000 --- a/llvm/test/tools/dsymutil/Inputs/obfuscated.map +++ /dev/null @@ -1,17 +0,0 @@ -one -two -three -four -five -six -.str -Apple LLVM version 7.0.0 (clang-700.2.38.2) -main -main.c -/Users/steven/dev/alpena/tests/src -one.c -two.c -three.c -four.c -five.c -six.c diff --git a/llvm/test/tools/dsymutil/cmdline.test b/llvm/test/tools/dsymutil/cmdline.test index 36cf3f542695ca40edbeb59e1efaad87b1f5546c..814252b6e2306714bc3e694c02ee9405234b413d 100644 --- a/llvm/test/tools/dsymutil/cmdline.test +++ b/llvm/test/tools/dsymutil/cmdline.test @@ -28,7 +28,6 @@ CHECK: -remarks-output-format <format> CHECK: -remarks-prepend-path <path> CHECK: -reproducer <mode> CHECK: -statistics -CHECK: -symbol-map CHECK: -symtab CHECK: {{-S}} CHECK: -toolchain diff --git a/llvm/test/tools/dxil-dis/debug-info.ll b/llvm/test/tools/dxil-dis/debug-info.ll index 92dc65481e825fda8752388c9fe8db8ab0a48992..96e023338e5c269ec506cbf87fe0e6ff1a9a782a 100644 --- a/llvm/test/tools/dxil-dis/debug-info.ll +++ b/llvm/test/tools/dxil-dis/debug-info.ll @@ -1,4 +1,4 @@ -; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s +; RUN: llc --filetype=obj %s -o - -experimental-debuginfo-iterators=false | dxil-dis -o - | FileCheck %s target triple = "dxil-unknown-shadermodel6.7-library" target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" diff --git a/llvm/test/tools/llc/new-pm/machine-function-properties.mir b/llvm/test/tools/llc/new-pm/machine-function-properties.mir new file mode 100644 index 0000000000000000000000000000000000000000..a9eb88ec6988416ab6651a00a30fc34e54ae6643 --- /dev/null +++ b/llvm/test/tools/llc/new-pm/machine-function-properties.mir @@ -0,0 +1,12 @@ +# REQUIRES: asserts +# RUN: not --crash llc -mtriple=x86_64-pc-linux-gnu -passes=require-all-machine-function-properties -filetype=null %s 2>&1 | FileCheck %s + +# CHECK: MachineFunctionProperties required by RequireAllMachineFunctionPropertiesPass pass are not met by function f. + +--- +name: f +selected: false +body: | + bb.0: + RET 0 +... diff --git a/llvm/test/tools/llvm-ar/coff-symtab.test b/llvm/test/tools/llvm-ar/coff-symtab.test new file mode 100644 index 0000000000000000000000000000000000000000..4a574723a9bea833442db80f87a6553063fa8dfc --- /dev/null +++ b/llvm/test/tools/llvm-ar/coff-symtab.test @@ -0,0 +1,91 @@ +Verify that llvm-ar uses COFF archive format by ensuring that archive map is sorted. + +RUN: rm -rf %t.dir && split-file %s %t.dir && cd %t.dir + +RUN: yaml2obj coff-symtab.yaml -o coff-symtab.obj +RUN: llvm-ar crs out.a coff-symtab.obj +RUN: llvm-nm --print-armap out.a | FileCheck %s + +RUN: llvm-as coff-symtab.ll -o coff-symtab.bc +RUN: llvm-ar crs out2.a coff-symtab.bc +RUN: llvm-nm --print-armap out2.a | FileCheck %s + +RUN: yaml2obj elf.yaml -o coff-symtab.o +RUN: llvm-ar crs --format coff out3.a coff-symtab.o +RUN: llvm-nm --print-armap out3.a | FileCheck %s + +Create an empty archive with no symbol map, add a COFF file to it and check that the output archive is a COFF archive. + +RUN: llvm-ar --format coff rcS out4.a +RUN: llvm-ar rs out4.a coff-symtab.obj +RUN: llvm-nm --print-armap out4.a | FileCheck %s + +CHECK: Archive map +CHECK-NEXT: a in coff-symtab +CHECK-NEXT: b in coff-symtab +CHECK-NEXT: c in coff-symtab +CHECK-EMPTY: + +#--- coff-symtab.yaml +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_UNKNOWN + Characteristics: [ ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '' +symbols: + - Name: b + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: c + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: a + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... + + +#--- coff-symtab.ll +target triple = "x86_64-unknown-windows-msvc" + +define void @b() { ret void } +define void @c() { ret void } +define void @a() { ret void } + +#--- elf.yaml +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data : ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: '' +Symbols: + - Name: b + Binding: STB_GLOBAL + Section: .text + - Name: c + Binding: STB_GLOBAL + Section: .text + - Name: a + Binding: STB_GLOBAL + Section: .text +... diff --git a/llvm/test/tools/llvm-ar/ecsymbols.ll b/llvm/test/tools/llvm-ar/ecsymbols.ll new file mode 100644 index 0000000000000000000000000000000000000000..f49c991b59345c6c9937cccb0295dc937b7c5b9f --- /dev/null +++ b/llvm/test/tools/llvm-ar/ecsymbols.ll @@ -0,0 +1,19 @@ +;; Test that ECSYMBOLS section is created when ARM64EC bitcode is used. + +; RUN: llvm-as %s -o %t.bc +; RUN: rm -f %t.a +; RUN: llvm-ar cr %t.a %t.bc +; RUN: llvm-nm --print-armap %t.a | FileCheck %s + +; CHECK-NOT: Archive map +; CHECK: Archive EC map +; CHECK-NEXT: a in ecsymbols.ll.tmp.bc +; CHECK-NEXT: b in ecsymbols.ll.tmp.bc +; CHECK-NEXT: c in ecsymbols.ll.tmp.bc +; CHECK-EMPTY: + +target triple = "arm64ec-unknown-windows-msvc" + +define void @b() { ret void } +define void @c() { ret void } +define void @a() { ret void } diff --git a/llvm/test/tools/llvm-ar/ecsymbols.yaml b/llvm/test/tools/llvm-ar/ecsymbols.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6cfe78d160ed7079ee94d18f4b473a700324b57b --- /dev/null +++ b/llvm/test/tools/llvm-ar/ecsymbols.yaml @@ -0,0 +1,84 @@ +## Test that ECSYMBOLS section is created when ARM64EC is used. + +# RUN: yaml2obj %s -o %t.arm64ec.obj -DMACHINE=IMAGE_FILE_MACHINE_ARM64EC +# RUN: yaml2obj %s -o %t.arm64.obj -DMACHINE=IMAGE_FILE_MACHINE_ARM64 +# RUN: yaml2obj %s -o %t.amd64.obj -DMACHINE=IMAGE_FILE_MACHINE_AMD64 + +## Create ARM64EC archive. +# RUN: rm -f %t*.a +# RUN: llvm-ar cr %t1.a %t.arm64ec.obj +# RUN: llvm-nm --print-armap %t1.a | FileCheck --check-prefixes=NOMAP,ECMAP %s + +## Add ARM64 object to the archive. +# RUN: llvm-ar r %t1.a %t.arm64.obj +# RUN: llvm-nm --print-armap %t1.a | FileCheck --check-prefixes=MAP,ECMAP %s + +## Create ARM64 archive. +# RUN: llvm-ar cr %t2.a %t.arm64.obj +# RUN: llvm-nm --print-armap %t2.a | FileCheck --check-prefixes=MAP,NOECMAP %s + +## Add ARM64EC object to the archive. +# RUN: llvm-ar r %t2.a %t.arm64ec.obj +# RUN: llvm-nm --print-armap %t2.a | FileCheck --check-prefixes=MAP,ECMAP %s + +## Create mixed archive with ARM64 and ARM64EC members. +# RUN: llvm-ar cr %t3.a %t.arm64ec.obj %t.arm64.obj +# RUN: llvm-nm --print-armap %t3.a | FileCheck --check-prefixes=MAP,ECMAP %s + +## Create mixed archive with ARM64 and AMD64 members. +# RUN: llvm-ar cr %t4.a %t.amd64.obj %t.arm64.obj +# RUN: llvm-nm --print-armap %t4.a | FileCheck --check-prefixes=MAP,AMDECMAP %s + +## Create an archive with no symbol table. +# RUN: llvm-ar crS %t5.a %t.amd64.obj %t.arm64.obj +# RUN: llvm-nm --print-armap %t5.a | FileCheck --check-prefixes=NOMAP,NOECMAP %s + +# MAP: Archive map +# MAP-NEXT: a in ecsymbols.yaml.tmp.arm64.obj +# MAP-NEXT: b in ecsymbols.yaml.tmp.arm64.obj +# MAP-NEXT: c in ecsymbols.yaml.tmp.arm64.obj +# MAP-EMPTY: +# NOMAP-NOT: Archive map + +# ECMAP: Archive EC map +# ECMAP-NEXT: a in ecsymbols.yaml.tmp.arm64ec.obj +# ECMAP-NEXT: b in ecsymbols.yaml.tmp.arm64ec.obj +# ECMAP-NEXT: c in ecsymbols.yaml.tmp.arm64ec.obj +# ECMAP-EMPTY: +# NOECMAP-NOT: Archive EC map + +# AMDECMAP: Archive EC map +# AMDECMAP-NEXT: a in ecsymbols.yaml.tmp.amd64.obj +# AMDECMAP-NEXT: b in ecsymbols.yaml.tmp.amd64.obj +# AMDECMAP-NEXT: c in ecsymbols.yaml.tmp.amd64.obj +# AMDECMAP-EMPTY: + +--- !COFF +header: + Machine: [[MACHINE]] + Characteristics: [ ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 4 + SectionData: '' +symbols: + - Name: b + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: c + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: a + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/llvm/test/tools/llvm-ar/no-symtab.yaml b/llvm/test/tools/llvm-ar/no-symtab.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7370c9b323552210f53876d7d1fca855eb2093c6 --- /dev/null +++ b/llvm/test/tools/llvm-ar/no-symtab.yaml @@ -0,0 +1,32 @@ +## Create archives with no symtab in various formats and check that we can read them. + +# RUN: yaml2obj %s -o %t.o +# RUN: rm -f %t.*.a + +# RUN: llvm-ar --format=gnu rcS %t.gnu.a %t.o +# RUN: llvm-ar --format=coff rcS %t.coff.a %t.o +# RUN: llvm-ar --format=darwin rcS %t.darwin.a %t.o +# RUN: llvm-ar --format=bsd rcS %t.bsd.a %t.o +# RUN: llvm-ar --format=bigarchive rcS %t.bigarchive.a %t.o + +# RUN: llvm-nm --print-armap %t.gnu.a | FileCheck %s +# RUN: llvm-nm --print-armap %t.coff.a | FileCheck %s +# RUN: llvm-nm --print-armap %t.darwin.a | FileCheck %s +# RUN: llvm-nm --print-armap %t.bsd.a | FileCheck %s +# RUN: llvm-nm --print-armap %t.bigarchive.a | FileCheck %s + +# CHECK-NOT: Archive map + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS +Symbols: + - Name: symbol + Binding: STB_GLOBAL + Section: .text diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/dw-at-specification.test b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/dw-at-specification.test index 9c9118ea49f8ab4b251de7fb708fd66e46869663..b1b35e4f4fe3ede7e008e1feff7e1e37b8863a86 100644 --- a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/dw-at-specification.test +++ b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/dw-at-specification.test @@ -10,7 +10,7 @@ ; The above test compiled with clang++ produces both a DW_AT_type and ; DW_AT_specification on the definition die for S::Arr, which previously caused -; an assert in the LVELFReader: +; an assert in the LVDWARFReader: ; $ clang++ -g -c dw-at-specification.cpp -o dw-at-specification.o ; RUN: llvm-debuginfo-analyzer --attribute=level,format,producer \ diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/pr-57040-ignored-DW_FORM_implicit_const.test b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/pr-57040-ignored-DW_FORM_implicit_const.test index 7ee9f3118d0aa9b652a5302e37866aa91c9f1c4d..9df058c559805221c0ced82433b435af32985169 100644 --- a/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/pr-57040-ignored-DW_FORM_implicit_const.test +++ b/llvm/test/tools/llvm-debuginfo-analyzer/DWARF/pr-57040-ignored-DW_FORM_implicit_const.test @@ -14,7 +14,7 @@ ; DW_AT_decl_file DW_FORM_implicit_const 1 ; DW_AT_decl_line DW_FORM_data1 -; Attributes with DW_FORM_implicit_const being ignored by the ELFReader, +; Attributes with DW_FORM_implicit_const being ignored by the DWARFReader, ; causing {Parameter} and {TypeAlias} to omit line numbers. ; test.cpp diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-compare-logical-elements.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-compare-logical-elements.test new file mode 100644 index 0000000000000000000000000000000000000000..f52c9c7cc7164195b4c98f9e873adf0a7baf8c3f --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-compare-logical-elements.test @@ -0,0 +1,106 @@ +; REQUIRES: webassembly-registered-target + +; Test case 1 - General options + +; test.cpp +; 1 using INTPTR = const int *; +; 2 int foo(INTPTR ParamPtr, unsigned ParamUnsigned, bool ParamBool) { +; 3 if (ParamBool) { +; 4 typedef int INTEGER; +; 5 const INTEGER CONSTANT = 7; +; 6 return CONSTANT; +; 7 } +; 8 return ParamUnsigned; +; 9 } + +; Compare mode - Logical view. +; The output shows in view form the 'missing (-), added (+)' elements, +; giving more context by swapping the reference and target object files. + +; RUN: llvm-mc -arch=wasm32 -filetype=obj \ +; RUN: %p/Inputs/test-clang.s -o %t.test-clang.o + +; RUN: llvm-debuginfo-analyzer --attribute=level \ +; RUN: --compare=types \ +; RUN: --report=view \ +; RUN: --print=symbols,types \ +; RUN: %t.test-clang.o \ +; RUN: %p/../DWARF/Inputs/test-dwarf-gcc.o 2>&1 | \ +; RUN: FileCheck --strict-whitespace -check-prefix=ONE %s + +; ONE: Reference: '{{.*}}test-clang.o' +; ONE-NEXT: Target: 'test-dwarf-gcc.o' +; ONE-EMPTY: +; ONE-NEXT: Logical View: +; ONE-NEXT: [000] {File} '{{.*}}test-clang.o' +; ONE-EMPTY: +; ONE-NEXT: [001] {CompileUnit} 'test.cpp' +; ONE-NEXT: [002] 1 {TypeAlias} 'INTPTR' -> '* const int' +; ONE-NEXT: [002] 2 {Function} extern not_inlined 'foo' -> 'int' +; ONE-NEXT: [003] {Block} +; ONE-NEXT: [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER' +; ONE-NEXT: +[004] 4 {TypeAlias} 'INTEGER' -> 'int' +; ONE-NEXT: [003] 2 {Parameter} 'ParamBool' -> 'bool' +; ONE-NEXT: [003] 2 {Parameter} 'ParamPtr' -> 'INTPTR' +; ONE-NEXT: [003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int' +; ONE-NEXT: -[003] 4 {TypeAlias} 'INTEGER' -> 'int' + +; Compare mode - Logical elements. +; The output shows in tabular form the 'missing (-), added (+)' elements, +; giving more context by swapping the reference and target object files. + +; RUN: llvm-debuginfo-analyzer --attribute=level \ +; RUN: --compare=types \ +; RUN: --report=list \ +; RUN: --print=symbols,types,summary \ +; RUN: %t.test-clang.o \ +; RUN: %p/../DWARF/Inputs/test-dwarf-gcc.o 2>&1 | \ +; RUN: FileCheck --strict-whitespace -check-prefix=TWO %s + +; TWO: Reference: '{{.*}}test-clang.o' +; TWO-NEXT: Target: 'test-dwarf-gcc.o' +; TWO-EMPTY: +; TWO-NEXT: (1) Missing Types: +; TWO-NEXT: -[003] 4 {TypeAlias} 'INTEGER' -> 'int' +; TWO-EMPTY: +; TWO-NEXT: (1) Added Types: +; TWO-NEXT: +[004] 4 {TypeAlias} 'INTEGER' -> 'int' +; TWO-EMPTY: +; TWO-NEXT: ---------------------------------------- +; TWO-NEXT: Element Expected Missing Added +; TWO-NEXT: ---------------------------------------- +; TWO-NEXT: Scopes 4 0 0 +; TWO-NEXT: Symbols 0 0 0 +; TWO-NEXT: Types 2 1 1 +; TWO-NEXT: Lines 0 0 0 +; TWO-NEXT: ---------------------------------------- +; TWO-NEXT: Total 6 1 1 + +; Changing the 'Reference' and 'Target' order: + +; RUN: llvm-debuginfo-analyzer --attribute=level \ +; RUN: --compare=types \ +; RUN: --report=list \ +; RUN: --print=symbols,types,summary \ +; RUN: %p/../DWARF/Inputs/test-dwarf-gcc.o \ +; RUN: %t.test-clang.o 2>&1 | \ +; RUN: FileCheck --strict-whitespace -check-prefix=THR %s + +; THR: Reference: 'test-dwarf-gcc.o' +; THR-NEXT: Target: '{{.*}}test-clang.o' +; THR-EMPTY: +; THR-NEXT: (1) Missing Types: +; THR-NEXT: -[004] 4 {TypeAlias} 'INTEGER' -> 'int' +; THR-EMPTY: +; THR-NEXT: (1) Added Types: +; THR-NEXT: +[003] 4 {TypeAlias} 'INTEGER' -> 'int' +; THR-EMPTY: +; THR-NEXT: ---------------------------------------- +; THR-NEXT: Element Expected Missing Added +; THR-NEXT: ---------------------------------------- +; THR-NEXT: Scopes 4 0 0 +; THR-NEXT: Symbols 0 0 0 +; THR-NEXT: Types 2 1 1 +; THR-NEXT: Lines 0 0 0 +; THR-NEXT: ---------------------------------------- +; THR-NEXT: Total 6 1 1 diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-print-basic-details.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-print-basic-details.test new file mode 100644 index 0000000000000000000000000000000000000000..492708656333090975a6cc9fdcb0b5f5096ddb8b --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-print-basic-details.test @@ -0,0 +1,120 @@ +; REQUIRES: webassembly-registered-target + +; Test case 1 - General options. + +; test.cpp +; 1 using INTPTR = const int *; +; 2 int foo(INTPTR ParamPtr, unsigned ParamUnsigned, bool ParamBool) { +; 3 if (ParamBool) { +; 4 typedef int INTEGER; +; 5 const INTEGER CONSTANT = 7; +; 6 return CONSTANT; +; 7 } +; 8 return ParamUnsigned; +; 9 } + +; Print basic details. +; The following command prints basic details for all the logical elements +; sorted by the debug information internal offset; it includes its lexical +; level and debug info format. + +; RUN: llvm-mc -arch=wasm32 -filetype=obj \ +; RUN: %p/Inputs/test-clang.s -o %t.test-clang.o + +; RUN: llvm-debuginfo-analyzer --attribute=level,format \ +; RUN: --output-sort=offset \ +; RUN: --print=scopes,symbols,types,lines,instructions \ +; RUN: %t.test-clang.o 2>&1 | \ +; RUN: FileCheck --strict-whitespace -check-prefix=ONE %s + +; RUN: llvm-debuginfo-analyzer --attribute=level,format \ +; RUN: --output-sort=offset \ +; RUN: --print=elements \ +; RUN: %t.test-clang.o 2>&1 | \ +; RUN: FileCheck --strict-whitespace -check-prefix=ONE %s + +; ONE: Logical View: +; ONE-NEXT: [000] {File} '{{.*}}test-clang.o' -> WASM +; ONE-EMPTY: +; ONE-NEXT: [001] {CompileUnit} 'test.cpp' +; ONE-NEXT: [002] 2 {Function} extern not_inlined 'foo' -> 'int' +; ONE-NEXT: [003] 2 {Parameter} 'ParamPtr' -> 'INTPTR' +; ONE-NEXT: [003] 2 {Parameter} 'ParamUnsigned' -> 'unsigned int' +; ONE-NEXT: [003] 2 {Parameter} 'ParamBool' -> 'bool' +; ONE-NEXT: [003] {Block} +; ONE-NEXT: [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER' +; ONE-NEXT: [004] 5 {Line} +; ONE-NEXT: [004] {Code} 'i32.const 7' +; ONE-NEXT: [004] {Code} 'local.set 10' +; ONE-NEXT: [004] {Code} 'local.get 5' +; ONE-NEXT: [004] {Code} 'local.get 10' +; ONE-NEXT: [004] {Code} 'i32.store 12' +; ONE-NEXT: [004] 6 {Line} +; ONE-NEXT: [004] {Code} 'i32.const 7' +; ONE-NEXT: [004] {Code} 'local.set 11' +; ONE-NEXT: [004] {Code} 'local.get 5' +; ONE-NEXT: [004] {Code} 'local.get 11' +; ONE-NEXT: [004] {Code} 'i32.store 28' +; ONE-NEXT: [004] {Code} 'br 1' +; ONE-NEXT: [004] - {Line} +; ONE-NEXT: [004] {Code} 'end' +; ONE-NEXT: [003] 4 {TypeAlias} 'INTEGER' -> 'int' +; ONE-NEXT: [003] 2 {Line} +; ONE-NEXT: [003] {Code} 'nop' +; ONE-NEXT: [003] {Code} 'end' +; ONE-NEXT: [003] {Code} 'i64.div_s' +; ONE-NEXT: [003] {Code} 'global.get 0' +; ONE-NEXT: [003] {Code} 'local.set 3' +; ONE-NEXT: [003] {Code} 'i32.const 32' +; ONE-NEXT: [003] {Code} 'local.set 4' +; ONE-NEXT: [003] {Code} 'local.get 3' +; ONE-NEXT: [003] {Code} 'local.get 4' +; ONE-NEXT: [003] {Code} 'i32.sub' +; ONE-NEXT: [003] {Code} 'local.set 5' +; ONE-NEXT: [003] {Code} 'local.get 5' +; ONE-NEXT: [003] {Code} 'local.get 0' +; ONE-NEXT: [003] {Code} 'i32.store 24' +; ONE-NEXT: [003] {Code} 'local.get 5' +; ONE-NEXT: [003] {Code} 'local.get 1' +; ONE-NEXT: [003] {Code} 'i32.store 20' +; ONE-NEXT: [003] {Code} 'local.get 2' +; ONE-NEXT: [003] {Code} 'local.set 6' +; ONE-NEXT: [003] {Code} 'local.get 5' +; ONE-NEXT: [003] {Code} 'local.get 6' +; ONE-NEXT: [003] {Code} 'i32.store8 19' +; ONE-NEXT: [003] 3 {Line} +; ONE-NEXT: [003] {Code} 'local.get 5' +; ONE-NEXT: [003] {Code} 'i32.load8_u 19' +; ONE-NEXT: [003] {Code} 'local.set 7' +; ONE-NEXT: [003] 3 {Line} +; ONE-NEXT: [003] {Code} 'i32.const 1' +; ONE-NEXT: [003] {Code} 'local.set 8' +; ONE-NEXT: [003] {Code} 'local.get 7' +; ONE-NEXT: [003] {Code} 'local.get 8' +; ONE-NEXT: [003] {Code} 'i32.and' +; ONE-NEXT: [003] {Code} 'local.set 9' +; ONE-NEXT: [003] {Code} 'block' +; ONE-NEXT: [003] {Code} 'block' +; ONE-NEXT: [003] {Code} 'local.get 9' +; ONE-NEXT: [003] {Code} 'i32.eqz' +; ONE-NEXT: [003] {Code} 'br_if 0' +; ONE-NEXT: [003] 8 {Line} +; ONE-NEXT: [003] {Code} 'local.get 5' +; ONE-NEXT: [003] {Code} 'i32.load 20' +; ONE-NEXT: [003] {Code} 'local.set 12' +; ONE-NEXT: [003] 8 {Line} +; ONE-NEXT: [003] {Code} 'local.get 5' +; ONE-NEXT: [003] {Code} 'local.get 12' +; ONE-NEXT: [003] {Code} 'i32.store 28' +; ONE-NEXT: [003] - {Line} +; ONE-NEXT: [003] {Code} 'end' +; ONE-NEXT: [003] 9 {Line} +; ONE-NEXT: [003] {Code} 'local.get 5' +; ONE-NEXT: [003] {Code} 'i32.load 28' +; ONE-NEXT: [003] {Code} 'local.set 13' +; ONE-NEXT: [003] {Code} 'local.get 13' +; ONE-NEXT: [003] {Code} 'return' +; ONE-NEXT: [003] {Code} 'end' +; ONE-NEXT: [003] 9 {Line} +; ONE-NEXT: [003] {Code} 'unreachable' +; ONE-NEXT: [002] 1 {TypeAlias} 'INTPTR' -> '* const int' diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-select-logical-elements.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-select-logical-elements.test new file mode 100644 index 0000000000000000000000000000000000000000..f50cc2d291a5b92f5ddc7b85e9552aa9d3bebc2d --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/01-wasm-select-logical-elements.test @@ -0,0 +1,76 @@ +; REQUIRES: webassembly-registered-target + +; Test case 1 - General options + +; test.cpp +; 1 using INTPTR = const int *; +; 2 int foo(INTPTR ParamPtr, unsigned ParamUnsigned, bool ParamBool) { +; 3 if (ParamBool) { +; 4 typedef int INTEGER; +; 5 const INTEGER CONSTANT = 7; +; 6 return CONSTANT; +; 7 } +; 8 return ParamUnsigned; +; 9 } + +; Select logical elements. +; The following prints all 'instructions', 'symbols' and 'types' that +; contain 'BLOCK' or '.store' in their names or types, using a tab layout +; and given the number of matches. + +; RUN: llvm-mc -arch=wasm32 -filetype=obj \ +; RUN: %p/Inputs/test-clang.s -o %t.test-clang.o + +; RUN: llvm-debuginfo-analyzer --attribute=level \ +; RUN: --select-nocase --select-regex \ +; RUN: --select=BLOCK --select=.store \ +; RUN: --report=list \ +; RUN: --print=symbols,types,instructions,summary \ +; RUN: %t.test-clang.o 2>&1 | \ +; RUN: FileCheck --strict-whitespace -check-prefix=ONE %s + +; ONE: Logical View: +; ONE-NEXT: [000] {File} '{{.*}}test-clang.o' +; ONE-EMPTY: +; ONE-NEXT: [001] {CompileUnit} 'test.cpp' +; ONE-NEXT: [003] {Code} 'block' +; ONE-NEXT: [003] {Code} 'block' +; ONE-NEXT: [004] {Code} 'i32.store 12' +; ONE-NEXT: [003] {Code} 'i32.store 20' +; ONE-NEXT: [003] {Code} 'i32.store 24' +; ONE-NEXT: [004] {Code} 'i32.store 28' +; ONE-NEXT: [003] {Code} 'i32.store 28' +; ONE-NEXT: [003] {Code} 'i32.store8 19' +; ONE-EMPTY: +; ONE-NEXT: ----------------------------- +; ONE-NEXT: Element Total Printed +; ONE-NEXT: ----------------------------- +; ONE-NEXT: Scopes 3 0 +; ONE-NEXT: Symbols 4 0 +; ONE-NEXT: Types 2 0 +; ONE-NEXT: Lines 62 8 +; ONE-NEXT: ----------------------------- +; ONE-NEXT: Total 71 8 + +; RUN: llvm-debuginfo-analyzer --attribute=level \ +; RUN: --select-regex --select-nocase \ +; RUN: --select=INTe \ +; RUN: --report=list \ +; RUN: --print=symbols,types \ +; RUN: %t.test-clang.o \ +; RUN: %p/../DWARF/Inputs/test-dwarf-gcc.o 2>&1 | \ +; RUN: FileCheck --strict-whitespace -check-prefix=TWO %s + +; TWO: Logical View: +; TWO-NEXT: [000] {File} '{{.*}}test-clang.o' +; TWO-EMPTY: +; TWO-NEXT: [001] {CompileUnit} 'test.cpp' +; TWO-NEXT: [003] 4 {TypeAlias} 'INTEGER' -> 'int' +; TWO-NEXT: [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER' +; TWO-EMPTY: +; TWO-NEXT: Logical View: +; TWO-NEXT: [000] {File} 'test-dwarf-gcc.o' +; TWO-EMPTY: +; TWO-NEXT: [001] {CompileUnit} 'test.cpp' +; TWO-NEXT: [004] 4 {TypeAlias} 'INTEGER' -> 'int' +; TWO-NEXT: [004] 5 {Variable} 'CONSTANT' -> 'const INTEGER' diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/02-wasm-logical-lines.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/02-wasm-logical-lines.test new file mode 100644 index 0000000000000000000000000000000000000000..101f6abdc96b635a7df63e47aa524a195bad7975 --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/02-wasm-logical-lines.test @@ -0,0 +1,74 @@ +; REQUIRES: webassembly-registered-target + +; Test case 2 - Assembler instructions. + +; hello-world.cpp +; 1 extern int printf(const char * format, ... ); +; 2 +; 3 int main() +; 4 { +; 5 printf("Hello, World\n"); +; 6 return 0; +; 7 } + +; Logical lines. +; The logical views shows the intermixed lines and assembler instructions, +; allowing to compare the code generated by the different toolchains. + +; RUN: llvm-mc -arch=wasm32 -filetype=obj \ +; RUN: %p/Inputs/hello-world-clang.s -o %t.hello-world-clang.o + +; RUN: llvm-debuginfo-analyzer --attribute=level,format,producer \ +; RUN: --print=lines,instructions \ +; RUN: %t.hello-world-clang.o 2>&1 | \ +; RUN: FileCheck --strict-whitespace -check-prefix=ONE %s + +; ONE: Logical View: +; ONE-NEXT: [000] {File} '{{.*}}hello-world-clang.o' -> WASM +; ONE-EMPTY: +; ONE-NEXT: [001] {CompileUnit} 'hello-world.cpp' +; ONE-NEXT: [002] {Producer} 'clang version 19{{.*}}' +; ONE-NEXT: [002] 3 {Function} extern not_inlined 'main' -> 'int' +; ONE-NEXT: [003] 4 {Line} +; ONE-NEXT: [003] {Code} 'nop' +; ONE-NEXT: [003] {Code} 'rethrow 127' +; ONE-NEXT: [003] {Code} 'global.get 0' +; ONE-NEXT: [003] {Code} 'local.set 0' +; ONE-NEXT: [003] {Code} 'i32.const 16' +; ONE-NEXT: [003] {Code} 'local.set 1' +; ONE-NEXT: [003] {Code} 'local.get 0' +; ONE-NEXT: [003] {Code} 'local.get 1' +; ONE-NEXT: [003] {Code} 'i32.sub' +; ONE-NEXT: [003] {Code} 'local.set 2' +; ONE-NEXT: [003] {Code} 'local.get 2' +; ONE-NEXT: [003] {Code} 'global.set 0' +; ONE-NEXT: [003] {Code} 'i32.const 0' +; ONE-NEXT: [003] {Code} 'local.set 3' +; ONE-NEXT: [003] {Code} 'local.get 2' +; ONE-NEXT: [003] {Code} 'local.get 3' +; ONE-NEXT: [003] {Code} 'i32.store 12' +; ONE-NEXT: [003] 5 {Line} +; ONE-NEXT: [003] {Code} 'i32.const 0' +; ONE-NEXT: [003] {Code} 'local.set 4' +; ONE-NEXT: [003] {Code} 'i32.const 0' +; ONE-NEXT: [003] {Code} 'local.set 5' +; ONE-NEXT: [003] {Code} 'local.get 4' +; ONE-NEXT: [003] {Code} 'local.get 5' +; ONE-NEXT: [003] {Code} 'call 0' +; ONE-NEXT: [003] {Code} 'drop' +; ONE-NEXT: [003] 6 {Line} +; ONE-NEXT: [003] {Code} 'i32.const 0' +; ONE-NEXT: [003] {Code} 'local.set 6' +; ONE-NEXT: [003] {Code} 'i32.const 16' +; ONE-NEXT: [003] {Code} 'local.set 7' +; ONE-NEXT: [003] {Code} 'local.get 2' +; ONE-NEXT: [003] {Code} 'local.get 7' +; ONE-NEXT: [003] {Code} 'i32.add' +; ONE-NEXT: [003] {Code} 'local.set 8' +; ONE-NEXT: [003] {Code} 'local.get 8' +; ONE-NEXT: [003] {Code} 'global.set 0' +; ONE-NEXT: [003] {Code} 'local.get 6' +; ONE-NEXT: [003] {Code} 'return' +; ONE-NEXT: [003] {Code} 'end' +; ONE-NEXT: [003] 6 {Line} +; ONE-NEXT: [003] {Code} 'return' diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/03-wasm-incorrect-lexical-scope-typedef.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/03-wasm-incorrect-lexical-scope-typedef.test new file mode 100644 index 0000000000000000000000000000000000000000..eb05ecae8ccf61977595ef288d0c03797fde93ed --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/03-wasm-incorrect-lexical-scope-typedef.test @@ -0,0 +1,135 @@ +; REQUIRES: webassembly-registered-target + +; Test case 3 - Incorrect lexical scope for typedef. + +; pr-44884.cpp +; 1 int bar(float Input) { return (int)Input; } +; 2 +; 3 unsigned foo(char Param) { +; 4 typedef int INT; // ** Definition for INT ** +; 5 INT Value = Param; +; 6 { +; 7 typedef float FLOAT; // ** Definition for FLOAT ** +; 8 { +; 9 FLOAT Added = Value + Param; +; 10 Value = bar(Added); +; 11 } +; 12 } +; 13 return Value + Param; +; 14 } + +; The lines 4 and 7 contains 2 typedefs, defined at different lexical +; scopes. + +; The above test is used to illustrates a scope issue found in the +; Clang compiler. +; PR44884: https://bugs.llvm.org/show_bug.cgi?id=44884 +; PR44229: https://github.com/llvm/llvm-project/issues/44229 + +; In the following logical views, we can see that the Clang compiler +; emits both typedefs at the same lexical scope (3), which is wrong. +; GCC emit correct lexical scope for both typedefs. + +; RUN: llvm-mc -arch=wasm32 -filetype=obj \ +; RUN: %p/Inputs/pr-44884-clang.s -o %t.pr-44884-clang.o + +; RUN: llvm-debuginfo-analyzer --attribute=level,format,producer \ +; RUN: --output-sort=kind \ +; RUN: --print=symbols,types,lines \ +; RUN: %t.pr-44884-clang.o \ +; RUN: %p/../DWARF/Inputs/pr-44884-dwarf-gcc.o 2>&1 | \ +; RUN: FileCheck --strict-whitespace -check-prefix=ONE %s + +; ONE: Logical View: +; ONE-NEXT: [000] {File} '{{.*}}pr-44884-clang.o' -> WASM +; ONE-EMPTY: +; ONE-NEXT: [001] {CompileUnit} 'pr-44884.cpp' +; ONE-NEXT: [002] {Producer} 'clang version 19{{.*}}' +; ONE-NEXT: [002] 1 {Function} extern not_inlined 'bar' -> 'int' +; ONE-NEXT: [003] 1 {Parameter} 'Input' -> 'float' +; ONE-NEXT: [003] 1 {Line} +; ONE-NEXT: [003] 1 {Line} +; ONE-NEXT: [003] - {Line} +; ONE-NEXT: [003] 1 {Line} +; ONE-NEXT: [003] - {Line} +; ONE-NEXT: [003] 1 {Line} +; ONE-NEXT: [003] 1 {Line} +; ONE-NEXT: [003] 1 {Line} +; ONE-NEXT: [002] 3 {Function} extern not_inlined 'foo' -> 'unsigned int' +; ONE-NEXT: [003] {Block} +; ONE-NEXT: [004] 9 {Variable} 'Added' -> 'FLOAT' +; ONE-NEXT: [004] 9 {Line} +; ONE-NEXT: [004] 9 {Line} +; ONE-NEXT: [004] 9 {Line} +; ONE-NEXT: [004] 9 {Line} +; ONE-NEXT: [004] 9 {Line} +; ONE-NEXT: [004] 10 {Line} +; ONE-NEXT: [004] 10 {Line} +; ONE-NEXT: [004] 10 {Line} +; ONE-NEXT: [004] 13 {Line} +; ONE-NEXT: [003] 3 {Parameter} 'Param' -> 'char' +; ONE-NEXT: [003] 7 {TypeAlias} 'FLOAT' -> 'float' +; ONE-NEXT: [003] 4 {TypeAlias} 'INT' -> 'int' +; ONE-NEXT: [003] 5 {Variable} 'Value' -> 'INT' +; ONE-NEXT: [003] 3 {Line} +; ONE-NEXT: [003] 5 {Line} +; ONE-NEXT: [003] 5 {Line} +; ONE-NEXT: [003] 13 {Line} +; ONE-NEXT: [003] 13 {Line} +; ONE-NEXT: [003] 13 {Line} +; ONE-NEXT: [003] 13 {Line} +; ONE-EMPTY: +; ONE-NEXT: Logical View: +; ONE-NEXT: [000] {File} 'pr-44884-dwarf-gcc.o' -> elf64-x86-64 +; ONE-EMPTY: +; ONE-NEXT: [001] {CompileUnit} 'pr-44884.cpp' +; ONE-NEXT: [002] {Producer} 'GNU C++14 10.3.0 {{.*}}' +; ONE-NEXT: [002] 1 {Function} extern not_inlined 'bar' -> 'int' +; ONE-NEXT: [003] 1 {Parameter} 'Input' -> 'float' +; ONE-NEXT: [003] 1 {Line} +; ONE-NEXT: [003] 1 {Line} +; ONE-NEXT: [003] 1 {Line} +; ONE-NEXT: [002] 3 {Function} extern not_inlined 'foo' -> 'unsigned int' +; ONE-NEXT: [003] {Block} +; ONE-NEXT: [004] {Block} +; ONE-NEXT: [005] 9 {Variable} 'Added' -> 'FLOAT' +; ONE-NEXT: [005] 9 {Line} +; ONE-NEXT: [005] 9 {Line} +; ONE-NEXT: [005] 9 {Line} +; ONE-NEXT: [005] 10 {Line} +; ONE-NEXT: [005] 13 {Line} +; ONE-NEXT: [004] 7 {TypeAlias} 'FLOAT' -> 'float' +; ONE-NEXT: [003] 3 {Parameter} 'Param' -> 'char' +; ONE-NEXT: [003] 4 {TypeAlias} 'INT' -> 'int' +; ONE-NEXT: [003] 5 {Variable} 'Value' -> 'INT' +; ONE-NEXT: [003] 3 {Line} +; ONE-NEXT: [003] 5 {Line} +; ONE-NEXT: [003] 13 {Line} +; ONE-NEXT: [003] 14 {Line} +; ONE-NEXT: [003] 14 {Line} + +; Using the selection facilities, we can produce a simple tabular +; output showing just the logical types that are 'Typedef'. + +; RUN: llvm-debuginfo-analyzer --attribute=level,format \ +; RUN: --output-sort=name \ +; RUN: --select-types=Typedef \ +; RUN: --report=list \ +; RUN: --print=types \ +; RUN: %t.pr-44884-clang.o \ +; RUN: %p/../DWARF/Inputs/pr-44884-dwarf-gcc.o 2>&1 | \ +; RUN: FileCheck --strict-whitespace -check-prefix=TWO %s + +; TWO: Logical View: +; TWO-NEXT: [000] {File} '{{.*}}pr-44884-clang.o' -> WASM +; TWO-EMPTY: +; TWO-NEXT: [001] {CompileUnit} 'pr-44884.cpp' +; TWO-NEXT: [003] 7 {TypeAlias} 'FLOAT' -> 'float' +; TWO-NEXT: [003] 4 {TypeAlias} 'INT' -> 'int' +; TWO-EMPTY: +; TWO-NEXT: Logical View: +; TWO-NEXT: [000] {File} 'pr-44884-dwarf-gcc.o' -> elf64-x86-64 +; TWO-EMPTY: +; TWO-NEXT: [001] {CompileUnit} 'pr-44884.cpp' +; TWO-NEXT: [004] 7 {TypeAlias} 'FLOAT' -> 'float' +; TWO-NEXT: [003] 4 {TypeAlias} 'INT' -> 'int' diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/04-wasm-missing-nested-enumerators.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/04-wasm-missing-nested-enumerators.test new file mode 100644 index 0000000000000000000000000000000000000000..cafa51c41966c568e8b43ad50a705088f6f918a2 --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/04-wasm-missing-nested-enumerators.test @@ -0,0 +1,130 @@ +; REQUIRES: webassembly-registered-target + +; Test case 4 - Missing nested enumerations. + +; pr-46466.cpp +; 1 struct Struct { +; 2 union Union { +; 3 enum NestedEnum { RED, BLUE }; +; 4 }; +; 5 Union U; +; 6 }; +; 7 +; 8 Struct S; +; 9 int test() { +; 10 return S.U.BLUE; +; 11 } + +; The above test is used to illustrate a scope issue found in the Clang +; compiler. +; PR46466: https://bugs.llvm.org/show_bug.cgi?id=46466 +; PR45811: https://github.com/llvm/llvm-project/issues/45811 + +; In the following logical views, we can see that the DWARF debug +; information generated by the Clang compiler does not include any +; references to the enumerators 'RED' and 'BLUE'. The DWARF generated +; by GCC, does include such references. + +; RUN: llvm-mc -arch=wasm32 -filetype=obj \ +; RUN: %p/Inputs/pr-46466-clang.s -o %t.pr-46466-clang.o + +; RUN: llvm-debuginfo-analyzer --attribute=level,format,producer \ +; RUN: --output-sort=name \ +; RUN: --print=symbols,types \ +; RUN: %t.pr-46466-clang.o \ +; RUN: %p/../DWARF/Inputs/pr-46466-dwarf-gcc.o 2>&1 | \ +; RUN: FileCheck --strict-whitespace -check-prefix=ONE %s + +; ONE: Logical View: +; ONE-NEXT: [000] {File} '{{.*}}pr-46466-clang.o' -> WASM +; ONE-EMPTY: +; ONE-NEXT: [001] {CompileUnit} 'pr-46466.cpp' +; ONE-NEXT: [002] {Producer} 'clang version 19{{.*}}' +; ONE-NEXT: [002] 8 {Variable} extern 'S' -> 'Struct' +; ONE-NEXT: [002] 1 {Struct} 'Struct' +; ONE-NEXT: [003] 5 {Member} public 'U' -> 'Union' +; ONE-EMPTY: +; ONE-NEXT: Logical View: +; ONE-NEXT: [000] {File} 'pr-46466-dwarf-gcc.o' -> elf64-x86-64 +; ONE-EMPTY: +; ONE-NEXT: [001] {CompileUnit} 'pr-46466.cpp' +; ONE-NEXT: [002] {Producer} 'GNU C++14 10.3.0 {{.*}}' +; ONE-NEXT: [002] 8 {Variable} extern 'S' -> 'Struct' +; ONE-NEXT: [002] 1 {Struct} 'Struct' +; ONE-NEXT: [003] 5 {Member} public 'U' -> 'Union' +; ONE-NEXT: [003] 2 {Union} 'Union' +; ONE-NEXT: [004] 3 {Enumeration} 'NestedEnum' -> 'unsigned int' +; ONE-NEXT: [005] {Enumerator} 'BLUE' = '0x1' +; ONE-NEXT: [005] {Enumerator} 'RED' = '0x0' + +; Using the selection facilities, we can produce a logical view +; showing just the logical types that are 'Enumerator' and its +; parents. The logical view is sorted by the types name. + +; RUN: llvm-debuginfo-analyzer --attribute=level,format \ +; RUN: --output-sort=name \ +; RUN: --select-types=Enumerator \ +; RUN: --report=parents \ +; RUN: --print=types \ +; RUN: %t.pr-46466-clang.o \ +; RUN: %p/../DWARF/Inputs/pr-46466-dwarf-gcc.o 2>&1 | \ +; RUN: FileCheck --strict-whitespace -check-prefix=TWO %s + +; TWO: Logical View: +; TWO-NEXT: [000] {File} '{{.*}}pr-46466-clang.o' -> WASM +; TWO-EMPTY: +; TWO-NEXT: [001] {CompileUnit} 'pr-46466.cpp' +; TWO-EMPTY: +; TWO-NEXT: Logical View: +; TWO-NEXT: [000] {File} 'pr-46466-dwarf-gcc.o' -> elf64-x86-64 +; TWO-EMPTY: +; TWO-NEXT: [001] {CompileUnit} 'pr-46466.cpp' +; TWO-NEXT: [002] 1 {Struct} 'Struct' +; TWO-NEXT: [003] 2 {Union} 'Union' +; TWO-NEXT: [004] 3 {Enumeration} 'NestedEnum' -> 'unsigned int' +; TWO-NEXT: [005] {Enumerator} 'BLUE' = '0x1' +; TWO-NEXT: [005] {Enumerator} 'RED' = '0x0' + +; Using the selection facilities, we can produce a simple tabular output +; including a summary for the logical types that are 'Enumerator'. The +; logical view is sorted by the types name. + +; RUN: llvm-debuginfo-analyzer --attribute=level,format \ +; RUN: --output-sort=name \ +; RUN: --select-types=Enumerator \ +; RUN: --print=types,summary \ +; RUN: %t.pr-46466-clang.o \ +; RUN: %p/../DWARF/Inputs/pr-46466-dwarf-gcc.o 2>&1 | \ +; RUN: FileCheck --strict-whitespace -check-prefix=THR %s + +; THR: Logical View: +; THR-NEXT: [000] {File} '{{.*}}pr-46466-clang.o' -> WASM +; THR-EMPTY: +; THR-NEXT: [001] {CompileUnit} 'pr-46466.cpp' +; THR-EMPTY: +; THR-NEXT: ----------------------------- +; THR-NEXT: Element Total Printed +; THR-NEXT: ----------------------------- +; THR-NEXT: Scopes 4 0 +; THR-NEXT: Symbols 0 0 +; THR-NEXT: Types 0 0 +; THR-NEXT: Lines 0 0 +; THR-NEXT: ----------------------------- +; THR-NEXT: Total 4 0 +; THR-EMPTY: +; THR-NEXT: Logical View: +; THR-NEXT: [000] {File} 'pr-46466-dwarf-gcc.o' -> elf64-x86-64 +; THR-EMPTY: +; THR-NEXT: [001] {CompileUnit} 'pr-46466.cpp' +; THR-NEXT: [005] {Enumerator} 'BLUE' = '0x1' +; THR-NEXT: [005] {Enumerator} 'RED' = '0x0' +; THR-EMPTY: +; THR-NEXT: ----------------------------- +; THR-NEXT: Element Total Printed +; THR-NEXT: ----------------------------- +; THR-NEXT: Scopes 5 0 +; THR-NEXT: Symbols 0 0 +; THR-NEXT: Types 2 2 +; THR-NEXT: Lines 0 0 +; THR-NEXT: ----------------------------- +; THR-NEXT: Total 7 2 diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/05-wasm-incorrect-lexical-scope-variable.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/05-wasm-incorrect-lexical-scope-variable.test new file mode 100644 index 0000000000000000000000000000000000000000..4348161f8c5bade7f8885f749e7af85dcadb1019 --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/05-wasm-incorrect-lexical-scope-variable.test @@ -0,0 +1,114 @@ +; REQUIRES: webassembly-registered-target + +; Test case 5 - Incorrect lexical scope variable. + +; pr-43860.cpp +; 1 #include "definitions.h" +; 2 forceinline int InlineFunction(int Param) { +; 3 int Var_1 = Param; +; 4 { +; 5 int Var_2 = Param + Var_1; +; 6 Var_1 = Var_2; +; 7 } +; 8 return Var_1; +; 9 } +; 10 +; 11 int test(int Param_1, int Param_2) { +; 12 int A = Param_1; +; 13 A += InlineFunction(Param_2); +; 14 return A; +; 15 } + +; The above test is used to illustrate a variable issue found in the +; Clang compiler. +; PR43860: https://bugs.llvm.org/show_bug.cgi?id=43860 +; PR43205: https://github.com/llvm/llvm-project/issues/43205 + +; In the following logical views, we can see that the DWARF debug +; information generated by the Clang compiler shows the variables +; 'Var_1' and 'Var_2' are at the same lexical scope (4) in the function +; 'InlineFuction'. +; The DWARF generated by GCC/Clang show those variables at the correct +; lexical scope: '3' and '4' respectively. + +; RUN: llvm-mc -arch=wasm32 -filetype=obj \ +; RUN: %p/Inputs/pr-43860-clang.s -o %t.pr-43860-clang.o + +; RUN: llvm-debuginfo-analyzer --attribute=level,format,producer \ +; RUN: --output-sort=name \ +; RUN: --print=symbols \ +; RUN: %t.pr-43860-clang.o \ +; RUN: %p/../DWARF/Inputs/pr-43860-dwarf-gcc.o 2>&1 | \ +; RUN: FileCheck --strict-whitespace -check-prefix=ONE %s + +; ONE: Logical View: +; ONE-NEXT: [000] {File} '{{.*}}pr-43860-clang.o' -> WASM +; ONE-EMPTY: +; ONE-NEXT: [001] {CompileUnit} 'pr-43860.cpp' +; ONE-NEXT: [002] {Producer} 'clang version 19{{.*}}' +; ONE-NEXT: [002] 2 {Function} extern inlined 'InlineFunction' -> 'int' +; ONE-NEXT: [003] {Block} +; ONE-NEXT: [004] 5 {Variable} 'Var_2' -> 'int' +; ONE-NEXT: [003] 2 {Parameter} 'Param' -> 'int' +; ONE-NEXT: [003] 3 {Variable} 'Var_1' -> 'int' +; ONE-NEXT: [002] 11 {Function} extern not_inlined 'test' -> 'int' +; ONE-NEXT: [003] 12 {Variable} 'A' -> 'int' +; ONE-NEXT: [003] 13 {InlinedFunction} inlined 'InlineFunction' -> 'int' +; ONE-NEXT: [004] {Block} +; ONE-NEXT: [005] {Variable} 'Var_2' -> 'int' +; ONE-NEXT: [004] {Parameter} 'Param' -> 'int' +; ONE-NEXT: [004] {Variable} 'Var_1' -> 'int' +; ONE-NEXT: [003] 11 {Parameter} 'Param_1' -> 'int' +; ONE-NEXT: [003] 11 {Parameter} 'Param_2' -> 'int' +; ONE-EMPTY: +; ONE-NEXT: Logical View: +; ONE-NEXT: [000] {File} 'pr-43860-dwarf-gcc.o' -> elf64-x86-64 +; ONE-EMPTY: +; ONE-NEXT: [001] {CompileUnit} 'pr-43860.cpp' +; ONE-NEXT: [002] {Producer} 'GNU C++14 10.3.0 {{.*}}' +; ONE-NEXT: [002] 2 {Function} extern declared_inlined 'InlineFunction' -> 'int' +; ONE-NEXT: [003] {Block} +; ONE-NEXT: [004] 5 {Variable} 'Var_2' -> 'int' +; ONE-NEXT: [003] 2 {Parameter} 'Param' -> 'int' +; ONE-NEXT: [003] 3 {Variable} 'Var_1' -> 'int' +; ONE-NEXT: [002] 11 {Function} extern not_inlined 'test' -> 'int' +; ONE-NEXT: [003] 12 {Variable} 'A' -> 'int' +; ONE-NEXT: [003] 13 {InlinedFunction} declared_inlined 'InlineFunction' -> 'int' +; ONE-NEXT: [004] {Block} +; ONE-NEXT: [005] {Variable} 'Var_2' -> 'int' +; ONE-NEXT: [004] {Parameter} 'Param' -> 'int' +; ONE-NEXT: [004] {Variable} 'Var_1' -> 'int' +; ONE-NEXT: [003] 11 {Parameter} 'Param_1' -> 'int' +; ONE-NEXT: [003] 11 {Parameter} 'Param_2' -> 'int' + +; Using the selection facilities, we can produce a simple tabular output +; showing just the logical elements that have in their name the 'var' +; pattern. The logical view is sorted by the variables name. + +; RUN: llvm-debuginfo-analyzer --attribute=level,format \ +; RUN: --output-sort=name \ +; RUN: --select-regex --select-nocase \ +; RUN: --select=Var \ +; RUN: --report=list \ +; RUN: --print=symbols \ +; RUN: %t.pr-43860-clang.o \ +; RUN: %p/../DWARF/Inputs/pr-43860-dwarf-gcc.o 2>&1 | \ +; RUN: FileCheck --strict-whitespace -check-prefix=TWO %s + +; TWO: Logical View: +; TWO-NEXT: [000] {File} '{{.*}}pr-43860-clang.o' -> WASM +; TWO-EMPTY: +; TWO-NEXT: [001] {CompileUnit} 'pr-43860.cpp' +; TWO-NEXT: [004] {Variable} 'Var_1' -> 'int' +; TWO-NEXT: [003] 3 {Variable} 'Var_1' -> 'int' +; TWO-NEXT: [005] {Variable} 'Var_2' -> 'int' +; TWO-NEXT: [004] 5 {Variable} 'Var_2' -> 'int' +; TWO-EMPTY: +; TWO-NEXT: Logical View: +; TWO-NEXT: [000] {File} 'pr-43860-dwarf-gcc.o' -> elf64-x86-64 +; TWO-EMPTY: +; TWO-NEXT: [001] {CompileUnit} 'pr-43860.cpp' +; TWO-NEXT: [004] {Variable} 'Var_1' -> 'int' +; TWO-NEXT: [003] 3 {Variable} 'Var_1' -> 'int' +; TWO-NEXT: [005] {Variable} 'Var_2' -> 'int' +; TWO-NEXT: [004] 5 {Variable} 'Var_2' -> 'int' diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/06-wasm-full-logical-view.test b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/06-wasm-full-logical-view.test new file mode 100644 index 0000000000000000000000000000000000000000..81b78bac0321515d8606a4c1a58a5fe4b4e66248 --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/06-wasm-full-logical-view.test @@ -0,0 +1,158 @@ +; REQUIRES: webassembly-registered-target + +; Test case 6 - Full logical view + +; test.cpp +; 1 using INTPTR = const int *; +; 2 int foo(INTPTR ParamPtr, unsigned ParamUnsigned, bool ParamBool) { +; 3 if (ParamBool) { +; 4 typedef int INTEGER; +; 5 const INTEGER CONSTANT = 7; +; 6 return CONSTANT; +; 7 } +; 8 return ParamUnsigned; +; 9 } + +; Print low level details. +; The following command prints low level information that includes +; offsets within the debug information section, debug location +; operands, linkage names, etc. + +; RUN: llvm-mc -arch=wasm32 -filetype=obj \ +; RUN: %p/Inputs/test-clang.s -o %t.test-clang.o + +; RUN: llvm-debuginfo-analyzer --attribute=all \ +; RUN: --print=all \ +; RUN: %t.test-clang.o 2>&1 | \ +; RUN: FileCheck --strict-whitespace -check-prefix=ONE %s + +; ONE: Logical View: +; ONE-NEXT: [0x0000000000][000] {File} '{{.*}}test-clang.o' -> WASM +; ONE-EMPTY: +; ONE-NEXT: [0x000000000b][001] {CompileUnit} 'test.cpp' +; ONE-NEXT: [0x000000000b][002] {Producer} 'clang version 19{{.*}}' +; ONE-NEXT: {Directory} '{{.*}}/general' +; ONE-NEXT: {File} 'test.cpp' +; ONE-NEXT: {Public} 'foo' [0x0000000002:0x000000007f] +; ONE-NEXT: [0x000000000b][002] {Range} Lines 2:9 [0x0000000002:0x000000007f] +; ONE-NEXT: [0x00000000b3][002] {BaseType} 'bool' +; ONE-NEXT: [0x0000000090][002] {BaseType} 'int' +; ONE-NEXT: [0x00000000ac][002] {BaseType} 'unsigned int' +; ONE-EMPTY: +; ONE-NEXT: [0x0000000097][002] {Source} '{{.*}}general/test.cpp' +; ONE-NEXT: [0x0000000097][002] 1 {TypeAlias} 'INTPTR' -> [0x00000000a2]'* const int' +; ONE-NEXT: [0x0000000026][002] 2 {Function} extern not_inlined 'foo' -> [0x0000000090]'int' +; ONE-NEXT: [0x0000000026][003] {Range} Lines 2:9 [0x0000000002:0x000000007f] +; ONE-NEXT: [0x0000000026][003] {Linkage} 0x3 '_Z3fooPKijb' +; ONE-NEXT: [0x000000006c][003] {Block} +; ONE-NEXT: [0x000000006c][004] {Range} Lines 5:0 [0x000000004c:0x0000000064] +; ONE-NEXT: [0x0000000075][004] 5 {Variable} 'CONSTANT' -> [0x00000000ba]'const INTEGER' +; ONE-NEXT: [0x0000000075][005] {Coverage} 100.00% +; ONE-NEXT: [0x0000000076][005] {Location} +; ONE-NEXT: [0x0000000076][006] {Entry} fbreg 12 +; ONE-NEXT: [0x000000004c][004] 5 {Line} {NewStatement} '{{.*}}/general/test.cpp' +; ONE-NEXT: [0x000000004c][004] {Code} 'i32.const 7' +; ONE-NEXT: [0x000000004e][004] {Code} 'local.set 10' +; ONE-NEXT: [0x0000000050][004] {Code} 'local.get 5' +; ONE-NEXT: [0x0000000052][004] {Code} 'local.get 10' +; ONE-NEXT: [0x0000000054][004] {Code} 'i32.store 12' +; ONE-NEXT: [0x0000000057][004] 6 {Line} {NewStatement} '{{.*}}/general/test.cpp' +; ONE-NEXT: [0x0000000057][004] {Code} 'i32.const 7' +; ONE-NEXT: [0x0000000059][004] {Code} 'local.set 11' +; ONE-NEXT: [0x000000005b][004] {Code} 'local.get 5' +; ONE-NEXT: [0x000000005d][004] {Code} 'local.get 11' +; ONE-NEXT: [0x000000005f][004] {Code} 'i32.store 28' +; ONE-NEXT: [0x0000000062][004] {Code} 'br 1' +; ONE-NEXT: [0x0000000064][004] 0 {Line} '{{.*}}/general/test.cpp' +; ONE-NEXT: [0x0000000064][004] {Code} 'end' +; ONE-NEXT: [0x000000005e][003] 2 {Parameter} 'ParamBool' -> [0x00000000b3]'bool' +; ONE-NEXT: [0x000000005e][004] {Coverage} 100.00% +; ONE-NEXT: [0x000000005f][004] {Location} +; ONE-NEXT: [0x000000005f][005] {Entry} fbreg 19 +; ONE-NEXT: [0x0000000042][003] 2 {Parameter} 'ParamPtr' -> [0x0000000097]'INTPTR' +; ONE-NEXT: [0x0000000042][004] {Coverage} 100.00% +; ONE-NEXT: [0x0000000043][004] {Location} +; ONE-NEXT: [0x0000000043][005] {Entry} fbreg 24 +; ONE-NEXT: [0x0000000050][003] 2 {Parameter} 'ParamUnsigned' -> [0x00000000ac]'unsigned int' +; ONE-NEXT: [0x0000000050][004] {Coverage} 100.00% +; ONE-NEXT: [0x0000000051][004] {Location} +; ONE-NEXT: [0x0000000051][005] {Entry} fbreg 20 +; ONE-NEXT: [0x0000000084][003] 4 {TypeAlias} 'INTEGER' -> [0x0000000090]'int' +; ONE-NEXT: [0x0000000002][003] 2 {Line} {NewStatement} '{{.*}}/general/test.cpp' +; ONE-NEXT: [0x0000000002][003] {Code} 'nop' +; ONE-NEXT: [0x0000000003][003] {Code} 'end' +; ONE-NEXT: [0x0000000004][003] {Code} 'i64.div_s' +; ONE-NEXT: [0x0000000005][003] {Code} 'global.get 0' +; ONE-NEXT: [0x000000000b][003] {Code} 'local.set 3' +; ONE-NEXT: [0x000000000d][003] {Code} 'i32.const 32' +; ONE-NEXT: [0x000000000f][003] {Code} 'local.set 4' +; ONE-NEXT: [0x0000000011][003] {Code} 'local.get 3' +; ONE-NEXT: [0x0000000013][003] {Code} 'local.get 4' +; ONE-NEXT: [0x0000000015][003] {Code} 'i32.sub' +; ONE-NEXT: [0x0000000016][003] {Code} 'local.set 5' +; ONE-NEXT: [0x0000000018][003] {Code} 'local.get 5' +; ONE-NEXT: [0x000000001a][003] {Code} 'local.get 0' +; ONE-NEXT: [0x000000001c][003] {Code} 'i32.store 24' +; ONE-NEXT: [0x000000001f][003] {Code} 'local.get 5' +; ONE-NEXT: [0x0000000021][003] {Code} 'local.get 1' +; ONE-NEXT: [0x0000000023][003] {Code} 'i32.store 20' +; ONE-NEXT: [0x0000000026][003] {Code} 'local.get 2' +; ONE-NEXT: [0x0000000028][003] {Code} 'local.set 6' +; ONE-NEXT: [0x000000002a][003] {Code} 'local.get 5' +; ONE-NEXT: [0x000000002c][003] {Code} 'local.get 6' +; ONE-NEXT: [0x000000002e][003] {Code} 'i32.store8 19' +; ONE-NEXT: [0x0000000031][003] 3 {Line} {NewStatement} {PrologueEnd} '{{.*}}/general/test.cpp' +; ONE-NEXT: [0x0000000031][003] {Code} 'local.get 5' +; ONE-NEXT: [0x0000000033][003] {Code} 'i32.load8_u 19' +; ONE-NEXT: [0x0000000036][003] {Code} 'local.set 7' +; ONE-NEXT: [0x0000000038][003] 3 {Line} '{{.*}}/general/test.cpp' +; ONE-NEXT: [0x0000000038][003] {Code} 'i32.const 1' +; ONE-NEXT: [0x000000003a][003] {Code} 'local.set 8' +; ONE-NEXT: [0x000000003c][003] {Code} 'local.get 7' +; ONE-NEXT: [0x000000003e][003] {Code} 'local.get 8' +; ONE-NEXT: [0x0000000040][003] {Code} 'i32.and' +; ONE-NEXT: [0x0000000041][003] {Code} 'local.set 9' +; ONE-NEXT: [0x0000000043][003] {Code} 'block' +; ONE-NEXT: [0x0000000045][003] {Code} 'block' +; ONE-NEXT: [0x0000000047][003] {Code} 'local.get 9' +; ONE-NEXT: [0x0000000049][003] {Code} 'i32.eqz' +; ONE-NEXT: [0x000000004a][003] {Code} 'br_if 0' +; ONE-NEXT: [0x0000000065][003] 8 {Line} {NewStatement} '{{.*}}/general/test.cpp' +; ONE-NEXT: [0x0000000065][003] {Code} 'local.get 5' +; ONE-NEXT: [0x0000000067][003] {Code} 'i32.load 20' +; ONE-NEXT: [0x000000006a][003] {Code} 'local.set 12' +; ONE-NEXT: [0x000000006c][003] 8 {Line} '{{.*}}/general/test.cpp' +; ONE-NEXT: [0x000000006c][003] {Code} 'local.get 5' +; ONE-NEXT: [0x000000006e][003] {Code} 'local.get 12' +; ONE-NEXT: [0x0000000070][003] {Code} 'i32.store 28' +; ONE-NEXT: [0x0000000073][003] 0 {Line} '{{.*}}/general/test.cpp' +; ONE-NEXT: [0x0000000073][003] {Code} 'end' +; ONE-NEXT: [0x0000000074][003] 9 {Line} {NewStatement} '{{.*}}/general/test.cpp' +; ONE-NEXT: [0x0000000074][003] {Code} 'local.get 5' +; ONE-NEXT: [0x0000000076][003] {Code} 'i32.load 28' +; ONE-NEXT: [0x0000000079][003] {Code} 'local.set 13' +; ONE-NEXT: [0x000000007b][003] {Code} 'local.get 13' +; ONE-NEXT: [0x000000007d][003] {Code} 'return' +; ONE-NEXT: [0x000000007e][003] {Code} 'end' +; ONE-NEXT: [0x000000007f][003] 9 {Line} {NewStatement} {EndSequence} '{{.*}}/general/test.cpp' +; ONE-NEXT: [0x000000007f][003] {Code} 'unreachable' +; ONE-EMPTY: +; ONE-NEXT: ----------------------------- +; ONE-NEXT: Element Total Printed +; ONE-NEXT: ----------------------------- +; ONE-NEXT: Scopes 3 3 +; ONE-NEXT: Symbols 4 4 +; ONE-NEXT: Types 5 5 +; ONE-NEXT: Lines 73 73 +; ONE-NEXT: ----------------------------- +; ONE-NEXT: Total 85 85 +; ONE-EMPTY: +; ONE-NEXT: Scope Sizes: +; ONE-NEXT: 180 (100.00%) : [0x000000000b][001] {CompileUnit} 'test.cpp' +; ONE-NEXT: 105 ( 58.33%) : [0x0000000026][002] 2 {Function} extern not_inlined 'foo' -> [0x0000000090]'int' +; ONE-NEXT: 23 ( 12.78%) : [0x000000006c][003] {Block} +; ONE-EMPTY: +; ONE-NEXT: Totals by lexical level: +; ONE-NEXT: [001]: 180 (100.00%) +; ONE-NEXT: [002]: 105 ( 58.33%) +; ONE-NEXT: [003]: 23 ( 12.78%) diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/definitions.h b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/definitions.h new file mode 100644 index 0000000000000000000000000000000000000000..dfbd3db044dd808f77f491cd43854f9268d9c00a --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/definitions.h @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// Definitions. +//----------------------------------------------------------------------------- +#ifndef SUITE_DEFINITIONS_H +#define SUITE_DEFINITIONS_H + +#ifdef _MSC_VER +#define forceinline __forceinline +#define OPTIMIZE_OFF __pragma(optimize("", off)) +#define OPTIMIZE_ON __pragma(optimize("", on)) +#elif defined(__clang__) +#if __has_attribute(__always_inline__) +#define forceinline inline __attribute__((__always_inline__)) +#else +#define forceinline inline +#endif +#define OPTIMIZE_OFF _Pragma("clang optimize off") +#define OPTIMIZE_ON _Pragma("clang optimize on") +#elif defined(__GNUC__) +#define forceinline inline __attribute__((__always_inline__)) +#define OPTIMIZE_OFF _Pragma("GCC optimize off") +#define OPTIMIZE_ON _Pragma("GCC optimize on") +#else +#define forceinline inline +#define OPTIMIZE_OFF +#define OPTIMIZE_ON +#error +#endif + +#endif // SUITE_DEFINITIONS_H diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/hello-world-clang.s b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/hello-world-clang.s new file mode 100644 index 0000000000000000000000000000000000000000..bfba259b626b0f39c71c792844cb2ccc934d90c3 --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/hello-world-clang.s @@ -0,0 +1,286 @@ + .text + .file "hello-world.cpp" + .file 1 "/data/projects/scripts/regression-suite/input/general" "hello-world.cpp" + .globaltype __stack_pointer, i32 + .functype __original_main () -> (i32) + .functype _Z6printfPKcz (i32, i32) -> (i32) + .functype main (i32, i32) -> (i32) + .section .text.__original_main,"",@ + .hidden __original_main # -- Begin function __original_main + .globl __original_main + .type __original_main,@function +__original_main: # @__original_main +.Lfunc_begin0: + .loc 1 4 0 # hello-world.cpp:4:0 + .functype __original_main () -> (i32) + .local i32, i32, i32, i32, i32, i32, i32, i32, i32 +# %bb.0: # %entry + global.get __stack_pointer + local.set 0 + i32.const 16 + local.set 1 + local.get 0 + local.get 1 + i32.sub + local.set 2 + local.get 2 + global.set __stack_pointer + i32.const 0 + local.set 3 + local.get 2 + local.get 3 + i32.store 12 +.Ltmp0: + .loc 1 5 3 prologue_end # hello-world.cpp:5:3 + i32.const .L.str + local.set 4 + i32.const 0 + local.set 5 + local.get 4 + local.get 5 + call _Z6printfPKcz + drop + .loc 1 6 3 # hello-world.cpp:6:3 + i32.const 0 + local.set 6 + i32.const 16 + local.set 7 + local.get 2 + local.get 7 + i32.add + local.set 8 + local.get 8 + global.set __stack_pointer + local.get 6 + return + end_function +.Ltmp1: +.Lfunc_end0: + # -- End function + .section .text.main,"",@ + .hidden main # -- Begin function main + .globl main + .type main,@function +main: # @main +.Lfunc_begin1: + .functype main (i32, i32) -> (i32) + .local i32 +# %bb.0: # %body + call __original_main + local.set 2 + local.get 2 + return + end_function +.Lfunc_end1: + # -- End function + .type .L.str,@object # @.str + .section .rodata..L.str,"S",@ +.L.str: + .asciz "Hello, World\n" + .size .L.str, 14 + + .globl __main_void + .type __main_void,@function + .hidden __main_void +.set __main_void, __original_main + .section .debug_abbrev,"",@ + .int8 1 # Abbreviation Code + .int8 17 # DW_TAG_compile_unit + .int8 1 # DW_CHILDREN_yes + .int8 37 # DW_AT_producer + .int8 14 # DW_FORM_strp + .int8 19 # DW_AT_language + .int8 5 # DW_FORM_data2 + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 16 # DW_AT_stmt_list + .int8 23 # DW_FORM_sec_offset + .int8 27 # DW_AT_comp_dir + .int8 14 # DW_FORM_strp + .int8 17 # DW_AT_low_pc + .int8 1 # DW_FORM_addr + .int8 18 # DW_AT_high_pc + .int8 6 # DW_FORM_data4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 2 # Abbreviation Code + .int8 52 # DW_TAG_variable + .int8 0 # DW_CHILDREN_no + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 2 # DW_AT_location + .int8 24 # DW_FORM_exprloc + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 3 # Abbreviation Code + .int8 1 # DW_TAG_array_type + .int8 1 # DW_CHILDREN_yes + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 4 # Abbreviation Code + .int8 33 # DW_TAG_subrange_type + .int8 0 # DW_CHILDREN_no + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 55 # DW_AT_count + .int8 11 # DW_FORM_data1 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 5 # Abbreviation Code + .int8 38 # DW_TAG_const_type + .int8 0 # DW_CHILDREN_no + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 6 # Abbreviation Code + .int8 36 # DW_TAG_base_type + .int8 0 # DW_CHILDREN_no + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 62 # DW_AT_encoding + .int8 11 # DW_FORM_data1 + .int8 11 # DW_AT_byte_size + .int8 11 # DW_FORM_data1 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 7 # Abbreviation Code + .int8 36 # DW_TAG_base_type + .int8 0 # DW_CHILDREN_no + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 11 # DW_AT_byte_size + .int8 11 # DW_FORM_data1 + .int8 62 # DW_AT_encoding + .int8 11 # DW_FORM_data1 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 8 # Abbreviation Code + .int8 46 # DW_TAG_subprogram + .int8 0 # DW_CHILDREN_no + .int8 17 # DW_AT_low_pc + .int8 1 # DW_FORM_addr + .int8 18 # DW_AT_high_pc + .int8 6 # DW_FORM_data4 + .int8 64 # DW_AT_frame_base + .int8 24 # DW_FORM_exprloc + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 63 # DW_AT_external + .int8 25 # DW_FORM_flag_present + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 0 # EOM(3) + .section .debug_info,"",@ +.Lcu_begin0: + .int32 .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .int16 4 # DWARF version number + .int32 .debug_abbrev0 # Offset Into Abbrev. Section + .int8 4 # Address Size (in bytes) + .int8 1 # Abbrev [1] 0xb:0x67 DW_TAG_compile_unit + .int32 .Linfo_string0 # DW_AT_producer + .int16 33 # DW_AT_language + .int32 .Linfo_string1 # DW_AT_name + .int32 .Lline_table_start0 # DW_AT_stmt_list + .int32 .Linfo_string2 # DW_AT_comp_dir + .int32 .Lfunc_begin0 # DW_AT_low_pc + .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .int8 2 # Abbrev [2] 0x26:0xd DW_TAG_variable + .int32 51 # DW_AT_type + .int8 1 # DW_AT_decl_file + .int8 5 # DW_AT_decl_line + .int8 5 # DW_AT_location + .int8 3 + .int32 .L.str + .int8 3 # Abbrev [3] 0x33:0xc DW_TAG_array_type + .int32 63 # DW_AT_type + .int8 4 # Abbrev [4] 0x38:0x6 DW_TAG_subrange_type + .int32 75 # DW_AT_type + .int8 14 # DW_AT_count + .int8 0 # End Of Children Mark + .int8 5 # Abbrev [5] 0x3f:0x5 DW_TAG_const_type + .int32 68 # DW_AT_type + .int8 6 # Abbrev [6] 0x44:0x7 DW_TAG_base_type + .int32 .Linfo_string3 # DW_AT_name + .int8 6 # DW_AT_encoding + .int8 1 # DW_AT_byte_size + .int8 7 # Abbrev [7] 0x4b:0x7 DW_TAG_base_type + .int32 .Linfo_string4 # DW_AT_name + .int8 8 # DW_AT_byte_size + .int8 7 # DW_AT_encoding + .int8 8 # Abbrev [8] 0x52:0x18 DW_TAG_subprogram + .int32 .Lfunc_begin0 # DW_AT_low_pc + .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .int8 4 # DW_AT_frame_base + .int8 237 + .int8 0 + .int8 2 + .int8 159 + .int32 .Linfo_string5 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 3 # DW_AT_decl_line + .int32 106 # DW_AT_type + # DW_AT_external + .int8 6 # Abbrev [6] 0x6a:0x7 DW_TAG_base_type + .int32 .Linfo_string6 # DW_AT_name + .int8 5 # DW_AT_encoding + .int8 4 # DW_AT_byte_size + .int8 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str,"S",@ +.Linfo_string0: + .asciz "clang version 19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" # string offset=0 +.Linfo_string1: + .asciz "hello-world.cpp" # string offset=111 +.Linfo_string2: + .asciz "/data/projects/scripts/regression-suite/input/general" # string offset=127 +.Linfo_string3: + .asciz "char" # string offset=181 +.Linfo_string4: + .asciz "__ARRAY_SIZE_TYPE__" # string offset=186 +.Linfo_string5: + .asciz "main" # string offset=206 +.Linfo_string6: + .asciz "int" # string offset=211 + .ident "clang version 19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" + .no_dead_strip __indirect_function_table + .section .custom_section.producers,"",@ + .int8 2 + .int8 8 + .ascii "language" + .int8 1 + .int8 14 + .ascii "C_plus_plus_14" + .int8 0 + .int8 12 + .ascii "processed-by" + .int8 1 + .int8 5 + .ascii "clang" + .int8 96 + .ascii "19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" + .section .debug_str,"S",@ + .section .custom_section.target_features,"",@ + .int8 2 + .int8 43 + .int8 15 + .ascii "mutable-globals" + .int8 43 + .int8 8 + .ascii "sign-ext" + .section .debug_str,"S",@ + .section .debug_line,"",@ +.Lline_table_start0: diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/hello-world.cpp b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/hello-world.cpp new file mode 100644 index 0000000000000000000000000000000000000000..73a8e247e26ec36d8e4a55fb1f86799e61efaa87 --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/hello-world.cpp @@ -0,0 +1,7 @@ +extern int printf(const char * format, ... ); + +int main() +{ + printf("Hello, World\n"); + return 0; +} diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-43860-clang.s b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-43860-clang.s new file mode 100644 index 0000000000000000000000000000000000000000..fb70b36173fd978dac6a978b937090317ff46df1 --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-43860-clang.s @@ -0,0 +1,457 @@ + .text + .file "pr-43860.cpp" + .globaltype __stack_pointer, i32 + .functype _Z4testii (i32, i32) -> (i32) + .section .text._Z4testii,"",@ + .hidden _Z4testii # -- Begin function _Z4testii + .globl _Z4testii + .type _Z4testii,@function +_Z4testii: # @_Z4testii +.Lfunc_begin0: + .file 1 "/data/projects/scripts/regression-suite/input/general" "pr-43860.cpp" + .loc 1 11 0 # pr-43860.cpp:11:0 + .functype _Z4testii (i32, i32) -> (i32) + .local i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 +# %bb.0: # %entry + global.get __stack_pointer + local.set 2 + i32.const 32 + local.set 3 + local.get 2 + local.get 3 + i32.sub + local.set 4 + local.get 4 + local.get 0 + i32.store 16 + local.get 4 + local.get 1 + i32.store 12 +.Ltmp0: + .loc 1 12 11 prologue_end # pr-43860.cpp:12:11 + local.get 4 + i32.load 16 + local.set 5 + .loc 1 12 7 is_stmt 0 # pr-43860.cpp:12:7 + local.get 4 + local.get 5 + i32.store 8 + .loc 1 13 23 is_stmt 1 # pr-43860.cpp:13:23 + local.get 4 + i32.load 12 + local.set 6 + local.get 4 + local.get 6 + i32.store 28 +.Ltmp1: + .loc 1 3 15 # pr-43860.cpp:3:15 + local.get 4 + i32.load 28 + local.set 7 + .loc 1 3 7 is_stmt 0 # pr-43860.cpp:3:7 + local.get 4 + local.get 7 + i32.store 24 +.Ltmp2: + .loc 1 5 17 is_stmt 1 # pr-43860.cpp:5:17 + local.get 4 + i32.load 28 + local.set 8 + .loc 1 5 25 is_stmt 0 # pr-43860.cpp:5:25 + local.get 4 + i32.load 24 + local.set 9 + .loc 1 5 23 # pr-43860.cpp:5:23 + local.get 8 + local.get 9 + i32.add + local.set 10 + .loc 1 5 9 # pr-43860.cpp:5:9 + local.get 4 + local.get 10 + i32.store 20 + .loc 1 6 13 is_stmt 1 # pr-43860.cpp:6:13 + local.get 4 + i32.load 20 + local.set 11 + .loc 1 6 11 is_stmt 0 # pr-43860.cpp:6:11 + local.get 4 + local.get 11 + i32.store 24 +.Ltmp3: + .loc 1 8 10 is_stmt 1 # pr-43860.cpp:8:10 + local.get 4 + i32.load 24 + local.set 12 +.Ltmp4: + .loc 1 13 5 # pr-43860.cpp:13:5 + local.get 4 + i32.load 8 + local.set 13 + local.get 13 + local.get 12 + i32.add + local.set 14 + local.get 4 + local.get 14 + i32.store 8 + .loc 1 14 10 # pr-43860.cpp:14:10 + local.get 4 + i32.load 8 + local.set 15 + .loc 1 14 3 is_stmt 0 # pr-43860.cpp:14:3 + local.get 15 + return + end_function +.Ltmp5: +.Lfunc_end0: + # -- End function + .section .debug_abbrev,"",@ + .int8 1 # Abbreviation Code + .int8 17 # DW_TAG_compile_unit + .int8 1 # DW_CHILDREN_yes + .int8 37 # DW_AT_producer + .int8 14 # DW_FORM_strp + .int8 19 # DW_AT_language + .int8 5 # DW_FORM_data2 + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 16 # DW_AT_stmt_list + .int8 23 # DW_FORM_sec_offset + .int8 27 # DW_AT_comp_dir + .int8 14 # DW_FORM_strp + .int8 17 # DW_AT_low_pc + .int8 1 # DW_FORM_addr + .int8 18 # DW_AT_high_pc + .int8 6 # DW_FORM_data4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 2 # Abbreviation Code + .int8 46 # DW_TAG_subprogram + .int8 1 # DW_CHILDREN_yes + .int8 110 # DW_AT_linkage_name + .int8 14 # DW_FORM_strp + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 63 # DW_AT_external + .int8 25 # DW_FORM_flag_present + .int8 32 # DW_AT_inline + .int8 11 # DW_FORM_data1 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 3 # Abbreviation Code + .int8 5 # DW_TAG_formal_parameter + .int8 0 # DW_CHILDREN_no + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 4 # Abbreviation Code + .int8 52 # DW_TAG_variable + .int8 0 # DW_CHILDREN_no + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 5 # Abbreviation Code + .int8 11 # DW_TAG_lexical_block + .int8 1 # DW_CHILDREN_yes + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 6 # Abbreviation Code + .int8 36 # DW_TAG_base_type + .int8 0 # DW_CHILDREN_no + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 62 # DW_AT_encoding + .int8 11 # DW_FORM_data1 + .int8 11 # DW_AT_byte_size + .int8 11 # DW_FORM_data1 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 7 # Abbreviation Code + .int8 46 # DW_TAG_subprogram + .int8 1 # DW_CHILDREN_yes + .int8 17 # DW_AT_low_pc + .int8 1 # DW_FORM_addr + .int8 18 # DW_AT_high_pc + .int8 6 # DW_FORM_data4 + .int8 64 # DW_AT_frame_base + .int8 24 # DW_FORM_exprloc + .int8 110 # DW_AT_linkage_name + .int8 14 # DW_FORM_strp + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 63 # DW_AT_external + .int8 25 # DW_FORM_flag_present + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 8 # Abbreviation Code + .int8 5 # DW_TAG_formal_parameter + .int8 0 # DW_CHILDREN_no + .int8 2 # DW_AT_location + .int8 24 # DW_FORM_exprloc + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 9 # Abbreviation Code + .int8 52 # DW_TAG_variable + .int8 0 # DW_CHILDREN_no + .int8 2 # DW_AT_location + .int8 24 # DW_FORM_exprloc + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 10 # Abbreviation Code + .int8 29 # DW_TAG_inlined_subroutine + .int8 1 # DW_CHILDREN_yes + .int8 49 # DW_AT_abstract_origin + .int8 19 # DW_FORM_ref4 + .int8 17 # DW_AT_low_pc + .int8 1 # DW_FORM_addr + .int8 18 # DW_AT_high_pc + .int8 6 # DW_FORM_data4 + .int8 88 # DW_AT_call_file + .int8 11 # DW_FORM_data1 + .int8 89 # DW_AT_call_line + .int8 11 # DW_FORM_data1 + .int8 87 # DW_AT_call_column + .int8 11 # DW_FORM_data1 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 11 # Abbreviation Code + .int8 5 # DW_TAG_formal_parameter + .int8 0 # DW_CHILDREN_no + .int8 2 # DW_AT_location + .int8 24 # DW_FORM_exprloc + .int8 49 # DW_AT_abstract_origin + .int8 19 # DW_FORM_ref4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 12 # Abbreviation Code + .int8 52 # DW_TAG_variable + .int8 0 # DW_CHILDREN_no + .int8 2 # DW_AT_location + .int8 24 # DW_FORM_exprloc + .int8 49 # DW_AT_abstract_origin + .int8 19 # DW_FORM_ref4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 13 # Abbreviation Code + .int8 11 # DW_TAG_lexical_block + .int8 1 # DW_CHILDREN_yes + .int8 17 # DW_AT_low_pc + .int8 1 # DW_FORM_addr + .int8 18 # DW_AT_high_pc + .int8 6 # DW_FORM_data4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 0 # EOM(3) + .section .debug_info,"",@ +.Lcu_begin0: + .int32 .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .int16 4 # DWARF version number + .int32 .debug_abbrev0 # Offset Into Abbrev. Section + .int8 4 # Address Size (in bytes) + .int8 1 # Abbrev [1] 0xb:0xd1 DW_TAG_compile_unit + .int32 .Linfo_string0 # DW_AT_producer + .int16 33 # DW_AT_language + .int32 .Linfo_string1 # DW_AT_name + .int32 .Lline_table_start0 # DW_AT_stmt_list + .int32 .Linfo_string2 # DW_AT_comp_dir + .int32 .Lfunc_begin0 # DW_AT_low_pc + .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .int8 2 # Abbrev [2] 0x26:0x34 DW_TAG_subprogram + .int32 .Linfo_string3 # DW_AT_linkage_name + .int32 .Linfo_string4 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 2 # DW_AT_decl_line + .int32 90 # DW_AT_type + # DW_AT_external + .int8 1 # DW_AT_inline + .int8 3 # Abbrev [3] 0x36:0xb DW_TAG_formal_parameter + .int32 .Linfo_string6 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 2 # DW_AT_decl_line + .int32 90 # DW_AT_type + .int8 4 # Abbrev [4] 0x41:0xb DW_TAG_variable + .int32 .Linfo_string7 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 3 # DW_AT_decl_line + .int32 90 # DW_AT_type + .int8 5 # Abbrev [5] 0x4c:0xd DW_TAG_lexical_block + .int8 4 # Abbrev [4] 0x4d:0xb DW_TAG_variable + .int32 .Linfo_string8 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 5 # DW_AT_decl_line + .int32 90 # DW_AT_type + .int8 0 # End Of Children Mark + .int8 0 # End Of Children Mark + .int8 6 # Abbrev [6] 0x5a:0x7 DW_TAG_base_type + .int32 .Linfo_string5 # DW_AT_name + .int8 5 # DW_AT_encoding + .int8 4 # DW_AT_byte_size + .int8 7 # Abbrev [7] 0x61:0x7a DW_TAG_subprogram + .int32 .Lfunc_begin0 # DW_AT_low_pc + .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .int8 4 # DW_AT_frame_base + .int8 237 + .int8 0 + .int8 4 + .int8 159 + .int32 .Linfo_string9 # DW_AT_linkage_name + .int32 .Linfo_string10 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 11 # DW_AT_decl_line + .int32 90 # DW_AT_type + # DW_AT_external + .int8 8 # Abbrev [8] 0x7d:0xe DW_TAG_formal_parameter + .int8 2 # DW_AT_location + .int8 145 + .int8 16 + .int32 .Linfo_string11 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 11 # DW_AT_decl_line + .int32 90 # DW_AT_type + .int8 8 # Abbrev [8] 0x8b:0xe DW_TAG_formal_parameter + .int8 2 # DW_AT_location + .int8 145 + .int8 12 + .int32 .Linfo_string12 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 11 # DW_AT_decl_line + .int32 90 # DW_AT_type + .int8 9 # Abbrev [9] 0x99:0xe DW_TAG_variable + .int8 2 # DW_AT_location + .int8 145 + .int8 8 + .int32 .Linfo_string13 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 12 # DW_AT_decl_line + .int32 90 # DW_AT_type + .int8 10 # Abbrev [10] 0xa7:0x33 DW_TAG_inlined_subroutine + .int32 38 # DW_AT_abstract_origin + .int32 .Ltmp1 # DW_AT_low_pc + .int32 .Ltmp4-.Ltmp1 # DW_AT_high_pc + .int8 1 # DW_AT_call_file + .int8 13 # DW_AT_call_line + .int8 8 # DW_AT_call_column + .int8 11 # Abbrev [11] 0xb7:0x8 DW_TAG_formal_parameter + .int8 2 # DW_AT_location + .int8 145 + .int8 28 + .int32 54 # DW_AT_abstract_origin + .int8 12 # Abbrev [12] 0xbf:0x8 DW_TAG_variable + .int8 2 # DW_AT_location + .int8 145 + .int8 24 + .int32 65 # DW_AT_abstract_origin + .int8 13 # Abbrev [13] 0xc7:0x12 DW_TAG_lexical_block + .int32 .Ltmp2 # DW_AT_low_pc + .int32 .Ltmp3-.Ltmp2 # DW_AT_high_pc + .int8 12 # Abbrev [12] 0xd0:0x8 DW_TAG_variable + .int8 2 # DW_AT_location + .int8 145 + .int8 20 + .int32 77 # DW_AT_abstract_origin + .int8 0 # End Of Children Mark + .int8 0 # End Of Children Mark + .int8 0 # End Of Children Mark + .int8 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str,"S",@ +.Linfo_string0: + .asciz "clang version 19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" # string offset=0 +.Linfo_string1: + .asciz "pr-43860.cpp" # string offset=111 +.Linfo_string2: + .asciz "/data/projects/scripts/regression-suite/input/general" # string offset=124 +.Linfo_string3: + .asciz "_Z14InlineFunctioni" # string offset=178 +.Linfo_string4: + .asciz "InlineFunction" # string offset=198 +.Linfo_string5: + .asciz "int" # string offset=213 +.Linfo_string6: + .asciz "Param" # string offset=217 +.Linfo_string7: + .asciz "Var_1" # string offset=223 +.Linfo_string8: + .asciz "Var_2" # string offset=229 +.Linfo_string9: + .asciz "_Z4testii" # string offset=235 +.Linfo_string10: + .asciz "test" # string offset=245 +.Linfo_string11: + .asciz "Param_1" # string offset=250 +.Linfo_string12: + .asciz "Param_2" # string offset=258 +.Linfo_string13: + .asciz "A" # string offset=266 + .ident "clang version 19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" + .section .custom_section.producers,"",@ + .int8 2 + .int8 8 + .ascii "language" + .int8 1 + .int8 14 + .ascii "C_plus_plus_14" + .int8 0 + .int8 12 + .ascii "processed-by" + .int8 1 + .int8 5 + .ascii "clang" + .int8 96 + .ascii "19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" + .section .debug_str,"S",@ + .section .custom_section.target_features,"",@ + .int8 2 + .int8 43 + .int8 15 + .ascii "mutable-globals" + .int8 43 + .int8 8 + .ascii "sign-ext" + .section .debug_str,"S",@ + .section .debug_line,"",@ +.Lline_table_start0: diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-43860.cpp b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-43860.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a3d3b76c59e58657199e595b8194b5dfe218e596 --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-43860.cpp @@ -0,0 +1,15 @@ +#include "definitions.h" +forceinline int InlineFunction(int Param) { + int Var_1 = Param; + { + int Var_2 = Param + Var_1; + Var_1 = Var_2; + } + return Var_1; +} + +int test(int Param_1, int Param_2) { + int A = Param_1; + A += InlineFunction(Param_2); + return A; +} diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-44884-clang.s b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-44884-clang.s new file mode 100644 index 0000000000000000000000000000000000000000..af9875b1eee2a6fe0bbf922916074cb8cd7ec1f8 --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-44884-clang.s @@ -0,0 +1,488 @@ + .text + .file "pr-44884.cpp" + .globaltype __stack_pointer, i32 + .functype _Z3barf (f32) -> (i32) + .functype _Z3fooc (i32) -> (i32) + .section .text._Z3barf,"",@ + .hidden _Z3barf # -- Begin function _Z3barf + .globl _Z3barf + .type _Z3barf,@function +_Z3barf: # @_Z3barf +.Lfunc_begin0: + .file 1 "/data/projects/scripts/regression-suite/input/general" "pr-44884.cpp" + .loc 1 1 0 # pr-44884.cpp:1:0 + .functype _Z3barf (f32) -> (i32) + .local i32, i32, i32, f32, f32, f32, i32, i32, i32, i32, i32, i32 +# %bb.0: # %entry + global.get __stack_pointer + local.set 1 + i32.const 16 + local.set 2 + local.get 1 + local.get 2 + i32.sub + local.set 3 + local.get 3 + local.get 0 + f32.store 12 +.Ltmp0: + .loc 1 1 36 prologue_end # pr-44884.cpp:1:36 + local.get 3 + f32.load 12 + local.set 4 + local.get 4 + f32.abs + local.set 5 + f32.const 0x1p31 + local.set 6 + local.get 5 + local.get 6 + f32.lt + local.set 7 + local.get 7 + i32.eqz + local.set 8 + block + block + local.get 8 + br_if 0 # 0: down to label1 +# %bb.1: # %entry + local.get 4 + i32.trunc_f32_s + local.set 9 + local.get 9 + local.set 10 + br 1 # 1: down to label0 +.LBB0_2: # %entry + .loc 1 0 36 is_stmt 0 # pr-44884.cpp:0:36 + end_block # label1: + .loc 1 1 36 # pr-44884.cpp:1:36 + i32.const -2147483648 + local.set 11 + local.get 11 + local.set 10 +.LBB0_3: # %entry + .loc 1 0 36 # pr-44884.cpp:0:36 + end_block # label0: + .loc 1 1 36 # pr-44884.cpp:1:36 + local.get 10 + local.set 12 + .loc 1 1 24 # pr-44884.cpp:1:24 + local.get 12 + return + end_function +.Ltmp1: +.Lfunc_end0: + # -- End function + .section .text._Z3fooc,"",@ + .hidden _Z3fooc # -- Begin function _Z3fooc + .globl _Z3fooc + .type _Z3fooc,@function +_Z3fooc: # @_Z3fooc +.Lfunc_begin1: + .loc 1 3 0 is_stmt 1 # pr-44884.cpp:3:0 + .functype _Z3fooc (i32) -> (i32) + .local i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, f32, f32, i32, i32, i32, i32, i32, i32, i32, i32, i32 +# %bb.0: # %entry + global.get __stack_pointer + local.set 1 + i32.const 16 + local.set 2 + local.get 1 + local.get 2 + i32.sub + local.set 3 + local.get 3 + global.set __stack_pointer + local.get 3 + local.get 0 + i32.store8 15 +.Ltmp2: + .loc 1 5 15 prologue_end # pr-44884.cpp:5:15 + local.get 3 + i32.load8_u 15 + local.set 4 + i32.const 24 + local.set 5 + local.get 4 + local.get 5 + i32.shl + local.set 6 + local.get 6 + local.get 5 + i32.shr_s + local.set 7 + .loc 1 5 7 is_stmt 0 # pr-44884.cpp:5:7 + local.get 3 + local.get 7 + i32.store 8 +.Ltmp3: + .loc 1 9 21 is_stmt 1 # pr-44884.cpp:9:21 + local.get 3 + i32.load 8 + local.set 8 + .loc 1 9 29 is_stmt 0 # pr-44884.cpp:9:29 + local.get 3 + i32.load8_u 15 + local.set 9 + i32.const 24 + local.set 10 + local.get 9 + local.get 10 + i32.shl + local.set 11 + local.get 11 + local.get 10 + i32.shr_s + local.set 12 + .loc 1 9 27 # pr-44884.cpp:9:27 + local.get 8 + local.get 12 + i32.add + local.set 13 + .loc 1 9 21 # pr-44884.cpp:9:21 + local.get 13 + f32.convert_i32_s + local.set 14 + .loc 1 9 13 # pr-44884.cpp:9:13 + local.get 3 + local.get 14 + f32.store 4 + .loc 1 10 19 is_stmt 1 # pr-44884.cpp:10:19 + local.get 3 + f32.load 4 + local.set 15 + .loc 1 10 15 is_stmt 0 # pr-44884.cpp:10:15 + local.get 15 + call _Z3barf + local.set 16 + .loc 1 10 13 # pr-44884.cpp:10:13 + local.get 3 + local.get 16 + i32.store 8 +.Ltmp4: + .loc 1 13 10 is_stmt 1 # pr-44884.cpp:13:10 + local.get 3 + i32.load 8 + local.set 17 + .loc 1 13 18 is_stmt 0 # pr-44884.cpp:13:18 + local.get 3 + i32.load8_u 15 + local.set 18 + i32.const 24 + local.set 19 + local.get 18 + local.get 19 + i32.shl + local.set 20 + local.get 20 + local.get 19 + i32.shr_s + local.set 21 + .loc 1 13 16 # pr-44884.cpp:13:16 + local.get 17 + local.get 21 + i32.add + local.set 22 + .loc 1 13 3 # pr-44884.cpp:13:3 + i32.const 16 + local.set 23 + local.get 3 + local.get 23 + i32.add + local.set 24 + local.get 24 + global.set __stack_pointer + local.get 22 + return + end_function +.Ltmp5: +.Lfunc_end1: + # -- End function + .section .debug_abbrev,"",@ + .int8 1 # Abbreviation Code + .int8 17 # DW_TAG_compile_unit + .int8 1 # DW_CHILDREN_yes + .int8 37 # DW_AT_producer + .int8 14 # DW_FORM_strp + .int8 19 # DW_AT_language + .int8 5 # DW_FORM_data2 + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 16 # DW_AT_stmt_list + .int8 23 # DW_FORM_sec_offset + .int8 27 # DW_AT_comp_dir + .int8 14 # DW_FORM_strp + .int8 17 # DW_AT_low_pc + .int8 1 # DW_FORM_addr + .int8 85 # DW_AT_ranges + .int8 23 # DW_FORM_sec_offset + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 2 # Abbreviation Code + .int8 36 # DW_TAG_base_type + .int8 0 # DW_CHILDREN_no + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 62 # DW_AT_encoding + .int8 11 # DW_FORM_data1 + .int8 11 # DW_AT_byte_size + .int8 11 # DW_FORM_data1 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 3 # Abbreviation Code + .int8 46 # DW_TAG_subprogram + .int8 1 # DW_CHILDREN_yes + .int8 17 # DW_AT_low_pc + .int8 1 # DW_FORM_addr + .int8 18 # DW_AT_high_pc + .int8 6 # DW_FORM_data4 + .int8 64 # DW_AT_frame_base + .int8 24 # DW_FORM_exprloc + .int8 110 # DW_AT_linkage_name + .int8 14 # DW_FORM_strp + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 63 # DW_AT_external + .int8 25 # DW_FORM_flag_present + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 4 # Abbreviation Code + .int8 5 # DW_TAG_formal_parameter + .int8 0 # DW_CHILDREN_no + .int8 2 # DW_AT_location + .int8 24 # DW_FORM_exprloc + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 5 # Abbreviation Code + .int8 52 # DW_TAG_variable + .int8 0 # DW_CHILDREN_no + .int8 2 # DW_AT_location + .int8 24 # DW_FORM_exprloc + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 6 # Abbreviation Code + .int8 11 # DW_TAG_lexical_block + .int8 1 # DW_CHILDREN_yes + .int8 17 # DW_AT_low_pc + .int8 1 # DW_FORM_addr + .int8 18 # DW_AT_high_pc + .int8 6 # DW_FORM_data4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 7 # Abbreviation Code + .int8 22 # DW_TAG_typedef + .int8 0 # DW_CHILDREN_no + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 0 # EOM(3) + .section .debug_info,"",@ +.Lcu_begin0: + .int32 .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .int16 4 # DWARF version number + .int32 .debug_abbrev0 # Offset Into Abbrev. Section + .int8 4 # Address Size (in bytes) + .int8 1 # Abbrev [1] 0xb:0xca DW_TAG_compile_unit + .int32 .Linfo_string0 # DW_AT_producer + .int16 33 # DW_AT_language + .int32 .Linfo_string1 # DW_AT_name + .int32 .Lline_table_start0 # DW_AT_stmt_list + .int32 .Linfo_string2 # DW_AT_comp_dir + .int32 0 # DW_AT_low_pc + .int32 .Ldebug_ranges0 # DW_AT_ranges + .int8 2 # Abbrev [2] 0x26:0x7 DW_TAG_base_type + .int32 .Linfo_string3 # DW_AT_name + .int8 5 # DW_AT_encoding + .int8 4 # DW_AT_byte_size + .int8 3 # Abbrev [3] 0x2d:0x2b DW_TAG_subprogram + .int32 .Lfunc_begin0 # DW_AT_low_pc + .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .int8 4 # DW_AT_frame_base + .int8 237 + .int8 0 + .int8 3 + .int8 159 + .int32 .Linfo_string4 # DW_AT_linkage_name + .int32 .Linfo_string5 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 1 # DW_AT_decl_line + .int32 38 # DW_AT_type + # DW_AT_external + .int8 4 # Abbrev [4] 0x49:0xe DW_TAG_formal_parameter + .int8 2 # DW_AT_location + .int8 145 + .int8 12 + .int32 .Linfo_string9 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 1 # DW_AT_decl_line + .int32 198 # DW_AT_type + .int8 0 # End Of Children Mark + .int8 3 # Abbrev [3] 0x58:0x67 DW_TAG_subprogram + .int32 .Lfunc_begin1 # DW_AT_low_pc + .int32 .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .int8 4 # DW_AT_frame_base + .int8 237 + .int8 0 + .int8 3 + .int8 159 + .int32 .Linfo_string6 # DW_AT_linkage_name + .int32 .Linfo_string7 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 3 # DW_AT_decl_line + .int32 191 # DW_AT_type + # DW_AT_external + .int8 4 # Abbrev [4] 0x74:0xe DW_TAG_formal_parameter + .int8 2 # DW_AT_location + .int8 145 + .int8 15 + .int32 .Linfo_string11 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 3 # DW_AT_decl_line + .int32 205 # DW_AT_type + .int8 5 # Abbrev [5] 0x82:0xe DW_TAG_variable + .int8 2 # DW_AT_location + .int8 145 + .int8 8 + .int32 .Linfo_string13 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 5 # DW_AT_decl_line + .int32 168 # DW_AT_type + .int8 6 # Abbrev [6] 0x90:0x18 DW_TAG_lexical_block + .int32 .Ltmp3 # DW_AT_low_pc + .int32 .Ltmp4-.Ltmp3 # DW_AT_high_pc + .int8 5 # Abbrev [5] 0x99:0xe DW_TAG_variable + .int8 2 # DW_AT_location + .int8 145 + .int8 4 + .int32 .Linfo_string15 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 9 # DW_AT_decl_line + .int32 179 # DW_AT_type + .int8 0 # End Of Children Mark + .int8 7 # Abbrev [7] 0xa8:0xb DW_TAG_typedef + .int32 38 # DW_AT_type + .int32 .Linfo_string14 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 4 # DW_AT_decl_line + .int8 7 # Abbrev [7] 0xb3:0xb DW_TAG_typedef + .int32 198 # DW_AT_type + .int32 .Linfo_string16 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 7 # DW_AT_decl_line + .int8 0 # End Of Children Mark + .int8 2 # Abbrev [2] 0xbf:0x7 DW_TAG_base_type + .int32 .Linfo_string8 # DW_AT_name + .int8 7 # DW_AT_encoding + .int8 4 # DW_AT_byte_size + .int8 2 # Abbrev [2] 0xc6:0x7 DW_TAG_base_type + .int32 .Linfo_string10 # DW_AT_name + .int8 4 # DW_AT_encoding + .int8 4 # DW_AT_byte_size + .int8 2 # Abbrev [2] 0xcd:0x7 DW_TAG_base_type + .int32 .Linfo_string12 # DW_AT_name + .int8 6 # DW_AT_encoding + .int8 1 # DW_AT_byte_size + .int8 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_ranges,"",@ +.Ldebug_ranges0: + .int32 .Lfunc_begin0 + .int32 .Lfunc_end0 + .int32 .Lfunc_begin1 + .int32 .Lfunc_end1 + .int32 0 + .int32 0 + .section .debug_str,"S",@ +.Linfo_string0: + .asciz "clang version 19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" # string offset=0 +.Linfo_string1: + .asciz "pr-44884.cpp" # string offset=111 +.Linfo_string2: + .asciz "/data/projects/scripts/regression-suite/input/general" # string offset=124 +.Linfo_string3: + .asciz "int" # string offset=178 +.Linfo_string4: + .asciz "_Z3barf" # string offset=182 +.Linfo_string5: + .asciz "bar" # string offset=190 +.Linfo_string6: + .asciz "_Z3fooc" # string offset=194 +.Linfo_string7: + .asciz "foo" # string offset=202 +.Linfo_string8: + .asciz "unsigned int" # string offset=206 +.Linfo_string9: + .asciz "Input" # string offset=219 +.Linfo_string10: + .asciz "float" # string offset=225 +.Linfo_string11: + .asciz "Param" # string offset=231 +.Linfo_string12: + .asciz "char" # string offset=237 +.Linfo_string13: + .asciz "Value" # string offset=242 +.Linfo_string14: + .asciz "INT" # string offset=248 +.Linfo_string15: + .asciz "Added" # string offset=252 +.Linfo_string16: + .asciz "FLOAT" # string offset=258 + .ident "clang version 19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" + .section .custom_section.producers,"",@ + .int8 2 + .int8 8 + .ascii "language" + .int8 1 + .int8 14 + .ascii "C_plus_plus_14" + .int8 0 + .int8 12 + .ascii "processed-by" + .int8 1 + .int8 5 + .ascii "clang" + .int8 96 + .ascii "19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" + .section .debug_str,"S",@ + .section .custom_section.target_features,"",@ + .int8 2 + .int8 43 + .int8 15 + .ascii "mutable-globals" + .int8 43 + .int8 8 + .ascii "sign-ext" + .section .debug_str,"S",@ + .section .debug_line,"",@ +.Lline_table_start0: diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-44884.cpp b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-44884.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b47aae8e0b17b925581a103356a6cbeb3013aa5 --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-44884.cpp @@ -0,0 +1,14 @@ +int bar(float Input) { return (int)Input; } + +unsigned foo(char Param) { + typedef int INT; + INT Value = Param; + { + typedef float FLOAT; + { + FLOAT Added = Value + Param; + Value = bar(Added); + } + } + return Value + Param; +} diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-46466-clang.s b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-46466-clang.s new file mode 100644 index 0000000000000000000000000000000000000000..1056db0760eae7480cdf2ffacc836ea18f4bc37a --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-46466-clang.s @@ -0,0 +1,259 @@ + .text + .file "pr-46466.cpp" + .file 1 "/data/projects/scripts/regression-suite/input/general" "pr-46466.cpp" + .functype _Z4testv () -> (i32) + .section .text._Z4testv,"",@ + .hidden _Z4testv # -- Begin function _Z4testv + .globl _Z4testv + .type _Z4testv,@function +_Z4testv: # @_Z4testv +.Lfunc_begin0: + .functype _Z4testv () -> (i32) + .local i32 +# %bb.0: # %entry + .loc 1 10 3 prologue_end # pr-46466.cpp:10:3 + i32.const 1 + local.set 0 + local.get 0 + return + end_function +.Ltmp0: +.Lfunc_end0: + # -- End function + .hidden S # @S + .type S,@object + .section .bss.S,"",@ + .globl S +S: + .skip 1 + .size S, 1 + + .section .debug_abbrev,"",@ + .int8 1 # Abbreviation Code + .int8 17 # DW_TAG_compile_unit + .int8 1 # DW_CHILDREN_yes + .int8 37 # DW_AT_producer + .int8 14 # DW_FORM_strp + .int8 19 # DW_AT_language + .int8 5 # DW_FORM_data2 + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 16 # DW_AT_stmt_list + .int8 23 # DW_FORM_sec_offset + .int8 27 # DW_AT_comp_dir + .int8 14 # DW_FORM_strp + .int8 17 # DW_AT_low_pc + .int8 1 # DW_FORM_addr + .int8 18 # DW_AT_high_pc + .int8 6 # DW_FORM_data4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 2 # Abbreviation Code + .int8 52 # DW_TAG_variable + .int8 0 # DW_CHILDREN_no + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 63 # DW_AT_external + .int8 25 # DW_FORM_flag_present + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 2 # DW_AT_location + .int8 24 # DW_FORM_exprloc + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 3 # Abbreviation Code + .int8 19 # DW_TAG_structure_type + .int8 1 # DW_CHILDREN_yes + .int8 54 # DW_AT_calling_convention + .int8 11 # DW_FORM_data1 + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 11 # DW_AT_byte_size + .int8 11 # DW_FORM_data1 + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 4 # Abbreviation Code + .int8 13 # DW_TAG_member + .int8 0 # DW_CHILDREN_no + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 56 # DW_AT_data_member_location + .int8 11 # DW_FORM_data1 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 5 # Abbreviation Code + .int8 23 # DW_TAG_union_type + .int8 0 # DW_CHILDREN_no + .int8 54 # DW_AT_calling_convention + .int8 11 # DW_FORM_data1 + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 11 # DW_AT_byte_size + .int8 11 # DW_FORM_data1 + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 6 # Abbreviation Code + .int8 46 # DW_TAG_subprogram + .int8 0 # DW_CHILDREN_no + .int8 17 # DW_AT_low_pc + .int8 1 # DW_FORM_addr + .int8 18 # DW_AT_high_pc + .int8 6 # DW_FORM_data4 + .int8 64 # DW_AT_frame_base + .int8 24 # DW_FORM_exprloc + .int8 110 # DW_AT_linkage_name + .int8 14 # DW_FORM_strp + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 63 # DW_AT_external + .int8 25 # DW_FORM_flag_present + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 7 # Abbreviation Code + .int8 36 # DW_TAG_base_type + .int8 0 # DW_CHILDREN_no + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 62 # DW_AT_encoding + .int8 11 # DW_FORM_data1 + .int8 11 # DW_AT_byte_size + .int8 11 # DW_FORM_data1 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 0 # EOM(3) + .section .debug_info,"",@ +.Lcu_begin0: + .int32 .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .int16 4 # DWARF version number + .int32 .debug_abbrev0 # Offset Into Abbrev. Section + .int8 4 # Address Size (in bytes) + .int8 1 # Abbrev [1] 0xb:0x72 DW_TAG_compile_unit + .int32 .Linfo_string0 # DW_AT_producer + .int16 33 # DW_AT_language + .int32 .Linfo_string1 # DW_AT_name + .int32 .Lline_table_start0 # DW_AT_stmt_list + .int32 .Linfo_string2 # DW_AT_comp_dir + .int32 .Lfunc_begin0 # DW_AT_low_pc + .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .int8 2 # Abbrev [2] 0x26:0x11 DW_TAG_variable + .int32 .Linfo_string3 # DW_AT_name + .int32 55 # DW_AT_type + # DW_AT_external + .int8 1 # DW_AT_decl_file + .int8 8 # DW_AT_decl_line + .int8 5 # DW_AT_location + .int8 3 + .int32 S + .int8 3 # Abbrev [3] 0x37:0x1f DW_TAG_structure_type + .int8 5 # DW_AT_calling_convention + .int32 .Linfo_string6 # DW_AT_name + .int8 1 # DW_AT_byte_size + .int8 1 # DW_AT_decl_file + .int8 1 # DW_AT_decl_line + .int8 4 # Abbrev [4] 0x40:0xc DW_TAG_member + .int32 .Linfo_string4 # DW_AT_name + .int32 76 # DW_AT_type + .int8 1 # DW_AT_decl_file + .int8 5 # DW_AT_decl_line + .int8 0 # DW_AT_data_member_location + .int8 5 # Abbrev [5] 0x4c:0x9 DW_TAG_union_type + .int8 5 # DW_AT_calling_convention + .int32 .Linfo_string5 # DW_AT_name + .int8 1 # DW_AT_byte_size + .int8 1 # DW_AT_decl_file + .int8 2 # DW_AT_decl_line + .int8 0 # End Of Children Mark + .int8 6 # Abbrev [6] 0x56:0x1f DW_TAG_subprogram + .int32 .Lfunc_begin0 # DW_AT_low_pc + .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .int8 7 # DW_AT_frame_base + .int8 237 + .int8 3 + .int32 __stack_pointer + .int8 159 + .int32 .Linfo_string7 # DW_AT_linkage_name + .int32 .Linfo_string8 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 9 # DW_AT_decl_line + .int32 117 # DW_AT_type + # DW_AT_external + .int8 7 # Abbrev [7] 0x75:0x7 DW_TAG_base_type + .int32 .Linfo_string9 # DW_AT_name + .int8 5 # DW_AT_encoding + .int8 4 # DW_AT_byte_size + .int8 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str,"S",@ +.Linfo_string0: + .asciz "clang version 19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" # string offset=0 +.Linfo_string1: + .asciz "pr-46466.cpp" # string offset=111 +.Linfo_string2: + .asciz "/data/projects/scripts/regression-suite/input/general" # string offset=124 +.Linfo_string3: + .asciz "S" # string offset=178 +.Linfo_string4: + .asciz "U" # string offset=180 +.Linfo_string5: + .asciz "Union" # string offset=182 +.Linfo_string6: + .asciz "Struct" # string offset=188 +.Linfo_string7: + .asciz "_Z4testv" # string offset=195 +.Linfo_string8: + .asciz "test" # string offset=204 +.Linfo_string9: + .asciz "int" # string offset=209 + .ident "clang version 19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" + .section .custom_section.producers,"",@ + .int8 2 + .int8 8 + .ascii "language" + .int8 1 + .int8 14 + .ascii "C_plus_plus_14" + .int8 0 + .int8 12 + .ascii "processed-by" + .int8 1 + .int8 5 + .ascii "clang" + .int8 96 + .ascii "19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" + .section .debug_str,"S",@ + .section .custom_section.target_features,"",@ + .int8 2 + .int8 43 + .int8 15 + .ascii "mutable-globals" + .int8 43 + .int8 8 + .ascii "sign-ext" + .section .debug_str,"S",@ + .section .debug_line,"",@ +.Lline_table_start0: diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-46466.cpp b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-46466.cpp new file mode 100644 index 0000000000000000000000000000000000000000..28be9a5d60ec3be29543502a2fd6516f12521e70 --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/pr-46466.cpp @@ -0,0 +1,11 @@ +struct Struct { + union Union { + enum NestedEnum { RED, BLUE }; + }; + Union U; +}; + +Struct S; +int test() { + return S.U.BLUE; +} diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang.s b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang.s new file mode 100644 index 0000000000000000000000000000000000000000..02afaf70d0ea8e5bd9c49107ede9c97aaf6df697 --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test-clang.s @@ -0,0 +1,366 @@ + .text + .file "test.cpp" + .globaltype __stack_pointer, i32 + .functype _Z3fooPKijb (i32, i32, i32) -> (i32) + .section .text._Z3fooPKijb,"",@ + .hidden _Z3fooPKijb # -- Begin function _Z3fooPKijb + .globl _Z3fooPKijb + .type _Z3fooPKijb,@function +_Z3fooPKijb: # @_Z3fooPKijb +.Lfunc_begin0: + .file 1 "/data/projects/scripts/regression-suite/input/general" "test.cpp" + .loc 1 2 0 # test.cpp:2:0 + .functype _Z3fooPKijb (i32, i32, i32) -> (i32) + .local i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 +# %bb.0: # %entry + global.get __stack_pointer + local.set 3 + i32.const 32 + local.set 4 + local.get 3 + local.get 4 + i32.sub + local.set 5 + local.get 5 + local.get 0 + i32.store 24 + local.get 5 + local.get 1 + i32.store 20 + local.get 2 + local.set 6 + local.get 5 + local.get 6 + i32.store8 19 +.Ltmp0: + .loc 1 3 7 prologue_end # test.cpp:3:7 + local.get 5 + i32.load8_u 19 + local.set 7 +.Ltmp1: + .loc 1 3 7 is_stmt 0 # test.cpp:3:7 + i32.const 1 + local.set 8 + local.get 7 + local.get 8 + i32.and + local.set 9 + block + block + local.get 9 + i32.eqz + br_if 0 # 0: down to label1 +# %bb.1: # %if.then +.Ltmp2: + .loc 1 5 19 is_stmt 1 # test.cpp:5:19 + i32.const 7 + local.set 10 + local.get 5 + local.get 10 + i32.store 12 + .loc 1 6 5 # test.cpp:6:5 + i32.const 7 + local.set 11 + local.get 5 + local.get 11 + i32.store 28 + br 1 # 1: down to label0 +.Ltmp3: +.LBB0_2: # %if.end + .loc 1 0 5 is_stmt 0 # test.cpp:0:5 + end_block # label1: + .loc 1 8 10 is_stmt 1 # test.cpp:8:10 + local.get 5 + i32.load 20 + local.set 12 + .loc 1 8 3 is_stmt 0 # test.cpp:8:3 + local.get 5 + local.get 12 + i32.store 28 +.LBB0_3: # %return + .loc 1 0 3 # test.cpp:0:3 + end_block # label0: + .loc 1 9 1 is_stmt 1 # test.cpp:9:1 + local.get 5 + i32.load 28 + local.set 13 + local.get 13 + return + end_function +.Ltmp4: +.Lfunc_end0: + # -- End function + .section .debug_abbrev,"",@ + .int8 1 # Abbreviation Code + .int8 17 # DW_TAG_compile_unit + .int8 1 # DW_CHILDREN_yes + .int8 37 # DW_AT_producer + .int8 14 # DW_FORM_strp + .int8 19 # DW_AT_language + .int8 5 # DW_FORM_data2 + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 16 # DW_AT_stmt_list + .int8 23 # DW_FORM_sec_offset + .int8 27 # DW_AT_comp_dir + .int8 14 # DW_FORM_strp + .int8 17 # DW_AT_low_pc + .int8 1 # DW_FORM_addr + .int8 18 # DW_AT_high_pc + .int8 6 # DW_FORM_data4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 2 # Abbreviation Code + .int8 46 # DW_TAG_subprogram + .int8 1 # DW_CHILDREN_yes + .int8 17 # DW_AT_low_pc + .int8 1 # DW_FORM_addr + .int8 18 # DW_AT_high_pc + .int8 6 # DW_FORM_data4 + .int8 64 # DW_AT_frame_base + .int8 24 # DW_FORM_exprloc + .int8 110 # DW_AT_linkage_name + .int8 14 # DW_FORM_strp + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 63 # DW_AT_external + .int8 25 # DW_FORM_flag_present + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 3 # Abbreviation Code + .int8 5 # DW_TAG_formal_parameter + .int8 0 # DW_CHILDREN_no + .int8 2 # DW_AT_location + .int8 24 # DW_FORM_exprloc + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 4 # Abbreviation Code + .int8 11 # DW_TAG_lexical_block + .int8 1 # DW_CHILDREN_yes + .int8 17 # DW_AT_low_pc + .int8 1 # DW_FORM_addr + .int8 18 # DW_AT_high_pc + .int8 6 # DW_FORM_data4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 5 # Abbreviation Code + .int8 52 # DW_TAG_variable + .int8 0 # DW_CHILDREN_no + .int8 2 # DW_AT_location + .int8 24 # DW_FORM_exprloc + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 6 # Abbreviation Code + .int8 22 # DW_TAG_typedef + .int8 0 # DW_CHILDREN_no + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 58 # DW_AT_decl_file + .int8 11 # DW_FORM_data1 + .int8 59 # DW_AT_decl_line + .int8 11 # DW_FORM_data1 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 7 # Abbreviation Code + .int8 36 # DW_TAG_base_type + .int8 0 # DW_CHILDREN_no + .int8 3 # DW_AT_name + .int8 14 # DW_FORM_strp + .int8 62 # DW_AT_encoding + .int8 11 # DW_FORM_data1 + .int8 11 # DW_AT_byte_size + .int8 11 # DW_FORM_data1 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 8 # Abbreviation Code + .int8 15 # DW_TAG_pointer_type + .int8 0 # DW_CHILDREN_no + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 9 # Abbreviation Code + .int8 38 # DW_TAG_const_type + .int8 0 # DW_CHILDREN_no + .int8 73 # DW_AT_type + .int8 19 # DW_FORM_ref4 + .int8 0 # EOM(1) + .int8 0 # EOM(2) + .int8 0 # EOM(3) + .section .debug_info,"",@ +.Lcu_begin0: + .int32 .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .int16 4 # DWARF version number + .int32 .debug_abbrev0 # Offset Into Abbrev. Section + .int8 4 # Address Size (in bytes) + .int8 1 # Abbrev [1] 0xb:0xb5 DW_TAG_compile_unit + .int32 .Linfo_string0 # DW_AT_producer + .int16 33 # DW_AT_language + .int32 .Linfo_string1 # DW_AT_name + .int32 .Lline_table_start0 # DW_AT_stmt_list + .int32 .Linfo_string2 # DW_AT_comp_dir + .int32 .Lfunc_begin0 # DW_AT_low_pc + .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .int8 2 # Abbrev [2] 0x26:0x6a DW_TAG_subprogram + .int32 .Lfunc_begin0 # DW_AT_low_pc + .int32 .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .int8 4 # DW_AT_frame_base + .int8 237 + .int8 0 + .int8 5 + .int8 159 + .int32 .Linfo_string3 # DW_AT_linkage_name + .int32 .Linfo_string4 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 2 # DW_AT_decl_line + .int32 144 # DW_AT_type + # DW_AT_external + .int8 3 # Abbrev [3] 0x42:0xe DW_TAG_formal_parameter + .int8 2 # DW_AT_location + .int8 145 + .int8 24 + .int32 .Linfo_string6 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 2 # DW_AT_decl_line + .int32 151 # DW_AT_type + .int8 3 # Abbrev [3] 0x50:0xe DW_TAG_formal_parameter + .int8 2 # DW_AT_location + .int8 145 + .int8 20 + .int32 .Linfo_string8 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 2 # DW_AT_decl_line + .int32 172 # DW_AT_type + .int8 3 # Abbrev [3] 0x5e:0xe DW_TAG_formal_parameter + .int8 2 # DW_AT_location + .int8 145 + .int8 19 + .int32 .Linfo_string10 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 2 # DW_AT_decl_line + .int32 179 # DW_AT_type + .int8 4 # Abbrev [4] 0x6c:0x18 DW_TAG_lexical_block + .int32 .Ltmp2 # DW_AT_low_pc + .int32 .Ltmp3-.Ltmp2 # DW_AT_high_pc + .int8 5 # Abbrev [5] 0x75:0xe DW_TAG_variable + .int8 2 # DW_AT_location + .int8 145 + .int8 12 + .int32 .Linfo_string12 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 5 # DW_AT_decl_line + .int32 186 # DW_AT_type + .int8 0 # End Of Children Mark + .int8 6 # Abbrev [6] 0x84:0xb DW_TAG_typedef + .int32 144 # DW_AT_type + .int32 .Linfo_string13 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 4 # DW_AT_decl_line + .int8 0 # End Of Children Mark + .int8 7 # Abbrev [7] 0x90:0x7 DW_TAG_base_type + .int32 .Linfo_string5 # DW_AT_name + .int8 5 # DW_AT_encoding + .int8 4 # DW_AT_byte_size + .int8 6 # Abbrev [6] 0x97:0xb DW_TAG_typedef + .int32 162 # DW_AT_type + .int32 .Linfo_string7 # DW_AT_name + .int8 1 # DW_AT_decl_file + .int8 1 # DW_AT_decl_line + .int8 8 # Abbrev [8] 0xa2:0x5 DW_TAG_pointer_type + .int32 167 # DW_AT_type + .int8 9 # Abbrev [9] 0xa7:0x5 DW_TAG_const_type + .int32 144 # DW_AT_type + .int8 7 # Abbrev [7] 0xac:0x7 DW_TAG_base_type + .int32 .Linfo_string9 # DW_AT_name + .int8 7 # DW_AT_encoding + .int8 4 # DW_AT_byte_size + .int8 7 # Abbrev [7] 0xb3:0x7 DW_TAG_base_type + .int32 .Linfo_string11 # DW_AT_name + .int8 2 # DW_AT_encoding + .int8 1 # DW_AT_byte_size + .int8 9 # Abbrev [9] 0xba:0x5 DW_TAG_const_type + .int32 132 # DW_AT_type + .int8 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str,"S",@ +.Linfo_string0: + .asciz "clang version 19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" # string offset=0 +.Linfo_string1: + .asciz "test.cpp" # string offset=111 +.Linfo_string2: + .asciz "/data/projects/scripts/regression-suite/input/general" # string offset=120 +.Linfo_string3: + .asciz "_Z3fooPKijb" # string offset=174 +.Linfo_string4: + .asciz "foo" # string offset=186 +.Linfo_string5: + .asciz "int" # string offset=190 +.Linfo_string6: + .asciz "ParamPtr" # string offset=194 +.Linfo_string7: + .asciz "INTPTR" # string offset=203 +.Linfo_string8: + .asciz "ParamUnsigned" # string offset=210 +.Linfo_string9: + .asciz "unsigned int" # string offset=224 +.Linfo_string10: + .asciz "ParamBool" # string offset=237 +.Linfo_string11: + .asciz "bool" # string offset=247 +.Linfo_string12: + .asciz "CONSTANT" # string offset=252 +.Linfo_string13: + .asciz "INTEGER" # string offset=261 + .ident "clang version 19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" + .section .custom_section.producers,"",@ + .int8 2 + .int8 8 + .ascii "language" + .int8 1 + .int8 14 + .ascii "C_plus_plus_14" + .int8 0 + .int8 12 + .ascii "processed-by" + .int8 1 + .int8 5 + .ascii "clang" + .int8 96 + .ascii "19.0.0git (/data/projects/llvm-root/llvm-project/clang 2db6703f0c257d293df455e2dff8c1fb695c4100)" + .section .debug_str,"S",@ + .section .custom_section.target_features,"",@ + .int8 2 + .int8 43 + .int8 15 + .ascii "mutable-globals" + .int8 43 + .int8 8 + .ascii "sign-ext" + .section .debug_str,"S",@ + .section .debug_line,"",@ +.Lline_table_start0: diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test.cpp b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5cf39f47735844ad87cc5c63956fb60794d8a28a --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/Inputs/test.cpp @@ -0,0 +1,9 @@ +using INTPTR = const int *; +int foo(INTPTR ParamPtr, unsigned ParamUnsigned, bool ParamBool) { + if (ParamBool) { + typedef int INTEGER; + const INTEGER CONSTANT = 7; + return CONSTANT; + } + return ParamUnsigned; +} diff --git a/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/README.txt b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..6937bb0f41342d3bc2e1fa95b02e46717b662590 --- /dev/null +++ b/llvm/test/tools/llvm-debuginfo-analyzer/WebAssembly/README.txt @@ -0,0 +1,28 @@ +Notes: +------ +As we should avoid committing binaries (.wasm) to be used in tests, +instead we provide the '.cpp' source files and the '.s' files. + +- For the tests, only the '.s' files are required. +- We use the target 'wasm32' as the 'wasm64' is not standardized yet. + +How to generate .s from .cpp +---------------------------- +Use clang to generate the '.s'. + + clang --target=wasm32 -S -g Inputs/hello-world.cpp -o Inputs/hello-world-clang.s + clang --target=wasm32 -S -g Inputs/pr-43860.cpp -o Inputs/pr-43860-clang.s + clang --target=wasm32 -S -g Inputs/pr-44884.cpp -o Inputs/pr-44884-clang.s + clang --target=wasm32 -S -g Inputs/pr-46466.cpp -o Inputs/pr-46466-clang.s + clang --target=wasm32 -S -g Inputs/test.cpp -o Inputs/test-clang.s + +How to generate .o from .s +-------------------------------- +Each test executes one of the following commands in order to generate +the binary '.wasm' used by that specific test: + + llvm-mc -arch=wasm32 -filetype=obj %p/Inputs/hello-world-clang.s -o hello-world-clang.o + llvm-mc -arch=wasm32 -filetype=obj %p/Inputs/pr-43860-clang.s -o pr-43860-clang.o + llvm-mc -arch=wasm32 -filetype=obj %p/Inputs/pr-44884-clang.s -o pr-44884-clang.o + llvm-mc -arch=wasm32 -filetype=obj %p/Inputs/pr-46466-clang.s -o pr-46466-clang.o + llvm-mc -arch=wasm32 -filetype=obj %p/Inputs/test-clang.s -o test-clang.o diff --git a/llvm/test/tools/llvm-lib/arm64ec-implib.test b/llvm/test/tools/llvm-lib/arm64ec-implib.test index 00eddd2a47526846cf45296651250ba03007df7c..e9987d0ca2e6459e7db026cff05d8c42be0ae082 100644 --- a/llvm/test/tools/llvm-lib/arm64ec-implib.test +++ b/llvm/test/tools/llvm-lib/arm64ec-implib.test @@ -14,6 +14,8 @@ ARMAP-NEXT: Archive EC map ARMAP-NEXT: #expname in test.dll ARMAP-NEXT: #funcexp in test.dll ARMAP-NEXT: #mangledfunc in test.dll +ARMAP-NEXT: #manglednonamefunc in test.dll +ARMAP-NEXT: #nonamefunc in test.dll ARMAP-NEXT: ?test_cpp_func@@$$hYAHPEAX@Z in test.dll ARMAP-NEXT: ?test_cpp_func@@YAHPEAX@Z in test.dll ARMAP-NEXT: __IMPORT_DESCRIPTOR_test in test.dll @@ -23,28 +25,34 @@ ARMAP-NEXT: __imp_aux_?test_cpp_func@@YAHPEAX@Z in test.dll ARMAP-NEXT: __imp_aux_expname in test.dll ARMAP-NEXT: __imp_aux_funcexp in test.dll ARMAP-NEXT: __imp_aux_mangledfunc in test.dll +ARMAP-NEXT: __imp_aux_manglednonamefunc in test.dll +ARMAP-NEXT: __imp_aux_nonamefunc in test.dll ARMAP-NEXT: __imp_dataexp in test.dll ARMAP-NEXT: __imp_expname in test.dll ARMAP-NEXT: __imp_funcexp in test.dll ARMAP-NEXT: __imp_mangledfunc in test.dll +ARMAP-NEXT: __imp_manglednonamefunc in test.dll +ARMAP-NEXT: __imp_nonamefunc in test.dll ARMAP-NEXT: expname in test.dll ARMAP-NEXT: funcexp in test.dll ARMAP-NEXT: mangledfunc in test.dll +ARMAP-NEXT: manglednonamefunc in test.dll +ARMAP-NEXT: nonamefunc in test.dll ARMAP-NEXT: test_NULL_THUNK_DATA in test.dll RUN: llvm-readobj test.lib | FileCheck -check-prefix=READOBJ %s -READOBJ: File: test.lib(test.dll) +READOBJ: File: test{{.*}}.lib(test.dll) READOBJ-NEXT: Format: COFF-ARM64{{$}} READOBJ-NEXT: Arch: aarch64 READOBJ-NEXT: AddressSize: 64bit READOBJ-EMPTY: -READOBJ-NEXT: File: test.lib(test.dll) +READOBJ-NEXT: File: test{{.*}}.lib(test.dll) READOBJ-NEXT: Format: COFF-ARM64{{$}} READOBJ-NEXT: Arch: aarch64 READOBJ-NEXT: AddressSize: 64bit READOBJ-EMPTY: -READOBJ-NEXT: File: test.lib(test.dll) +READOBJ-NEXT: File: test{{.*}}.lib(test.dll) READOBJ-NEXT: Format: COFF-ARM64{{$}} READOBJ-NEXT: Arch: aarch64 READOBJ-NEXT: AddressSize: 64bit @@ -95,6 +103,30 @@ READOBJ-NEXT: Type: data READOBJ-NEXT: Name type: name READOBJ-NEXT: Export name: dataexp READOBJ-NEXT: Symbol: __imp_dataexp +READOBJ-EMPTY: +READOBJ-NEXT: File: test.dll +READOBJ-NEXT: Format: COFF-import-file-ARM64EC +READOBJ-NEXT: Type: code +READOBJ-NEXT: Name type: ordinal +READOBJ-NEXT: Symbol: __imp_nonamefunc +READOBJ-NEXT: Symbol: nonamefunc +READOBJ-NEXT: Symbol: __imp_aux_nonamefunc +READOBJ-NEXT: Symbol: #nonamefunc +READOBJ-EMPTY: +READOBJ-NEXT: File: test.dll +READOBJ-NEXT: Format: COFF-import-file-ARM64EC +READOBJ-NEXT: Type: code +READOBJ-NEXT: Name type: ordinal +READOBJ-NEXT: Symbol: __imp_manglednonamefunc +READOBJ-NEXT: Symbol: manglednonamefunc +READOBJ-NEXT: Symbol: __imp_aux_manglednonamefunc +READOBJ-NEXT: Symbol: #manglednonamefunc + + +Using -machine:arm64x gives the same output. +RUN: llvm-lib -machine:arm64x -def:test.def -out:testx.lib +RUN: llvm-nm --print-armap testx.lib | FileCheck -check-prefix=ARMAP %s +RUN: llvm-readobj testx.lib | FileCheck -check-prefix=READOBJ %s Creating a new lib containing the existing lib: RUN: llvm-lib -machine:arm64ec test.lib -out:test2.lib @@ -107,22 +139,28 @@ RUN: llvm-nm --print-armap testx.lib | FileCheck -check-prefix=ARMAPX %s ARMAPX: Archive map ARMAPX-NEXT: #mangledfunc in test.dll +ARMAPX-NEXT: #manglednonamefunc in test.dll ARMAPX-NEXT: ?test_cpp_func@@YAHPEAX@Z in test.dll ARMAPX-NEXT: __IMPORT_DESCRIPTOR_test in test.dll ARMAPX-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll ARMAPX-NEXT: __imp_#mangledfunc in test.dll +ARMAPX-NEXT: __imp_#manglednonamefunc in test.dll ARMAPX-NEXT: __imp_?test_cpp_func@@YAHPEAX@Z in test.dll ARMAPX-NEXT: __imp_dataexp in test.dll ARMAPX-NEXT: __imp_expname in test.dll ARMAPX-NEXT: __imp_funcexp in test.dll +ARMAPX-NEXT: __imp_nonamefunc in test.dll ARMAPX-NEXT: expname in test.dll ARMAPX-NEXT: funcexp in test.dll +ARMAPX-NEXT: nonamefunc in test.dll ARMAPX-NEXT: test_NULL_THUNK_DATA in test.dll ARMAPX-EMPTY: ARMAPX-NEXT: Archive EC map ARMAPX-NEXT: #expname in test.dll ARMAPX-NEXT: #funcexp in test.dll ARMAPX-NEXT: #mangledfunc in test.dll +ARMAPX-NEXT: #manglednonamefunc in test.dll +ARMAPX-NEXT: #nonamefunc in test.dll ARMAPX-NEXT: ?test_cpp_func@@$$hYAHPEAX@Z in test.dll ARMAPX-NEXT: ?test_cpp_func@@YAHPEAX@Z in test.dll ARMAPX-NEXT: __IMPORT_DESCRIPTOR_test in test.dll @@ -132,13 +170,19 @@ ARMAPX-NEXT: __imp_aux_?test_cpp_func@@YAHPEAX@Z in test.dll ARMAPX-NEXT: __imp_aux_expname in test.dll ARMAPX-NEXT: __imp_aux_funcexp in test.dll ARMAPX-NEXT: __imp_aux_mangledfunc in test.dll +ARMAPX-NEXT: __imp_aux_manglednonamefunc in test.dll +ARMAPX-NEXT: __imp_aux_nonamefunc in test.dll ARMAPX-NEXT: __imp_dataexp in test.dll ARMAPX-NEXT: __imp_expname in test.dll ARMAPX-NEXT: __imp_funcexp in test.dll ARMAPX-NEXT: __imp_mangledfunc in test.dll +ARMAPX-NEXT: __imp_manglednonamefunc in test.dll +ARMAPX-NEXT: __imp_nonamefunc in test.dll ARMAPX-NEXT: expname in test.dll ARMAPX-NEXT: funcexp in test.dll ARMAPX-NEXT: mangledfunc in test.dll +ARMAPX-NEXT: manglednonamefunc in test.dll +ARMAPX-NEXT: nonamefunc in test.dll ARMAPX-NEXT: test_NULL_THUNK_DATA in test.dll RUN: llvm-readobj testx.lib | FileCheck -check-prefix=READOBJX %s @@ -206,6 +250,24 @@ READOBJX-NEXT: Export name: dataexp READOBJX-NEXT: Symbol: __imp_dataexp READOBJX-EMPTY: READOBJX-NEXT: File: test.dll +READOBJX-NEXT: Format: COFF-import-file-ARM64EC +READOBJX-NEXT: Type: code +READOBJX-NEXT: Name type: ordinal +READOBJX-NEXT: Symbol: __imp_nonamefunc +READOBJX-NEXT: Symbol: nonamefunc +READOBJX-NEXT: Symbol: __imp_aux_nonamefunc +READOBJX-NEXT: Symbol: #nonamefunc +READOBJX-EMPTY: +READOBJX-NEXT: File: test.dll +READOBJX-NEXT: Format: COFF-import-file-ARM64EC +READOBJX-NEXT: Type: code +READOBJX-NEXT: Name type: ordinal +READOBJX-NEXT: Symbol: __imp_manglednonamefunc +READOBJX-NEXT: Symbol: manglednonamefunc +READOBJX-NEXT: Symbol: __imp_aux_manglednonamefunc +READOBJX-NEXT: Symbol: #manglednonamefunc +READOBJX-EMPTY: +READOBJX-NEXT: File: test.dll READOBJX-NEXT: Format: COFF-import-file-ARM64 READOBJX-NEXT: Type: code READOBJX-NEXT: Name type: name @@ -243,10 +305,26 @@ READOBJX-NEXT: Type: data READOBJX-NEXT: Name type: name READOBJX-NEXT: Export name: dataexp READOBJX-NEXT: Symbol: __imp_dataexp +READOBJX-EMPTY: +READOBJX-NEXT: File: test.dll +READOBJX-NEXT: Format: COFF-import-file-ARM64 +READOBJX-NEXT: Type: code +READOBJX-NEXT: Name type: ordinal +READOBJX-NEXT: Symbol: __imp_nonamefunc +READOBJX-NEXT: Symbol: nonamefunc +READOBJX-EMPTY: +READOBJX-NEXT: File: test.dll +READOBJX-NEXT: Format: COFF-import-file-ARM64 +READOBJX-NEXT: Type: code +READOBJX-NEXT: Name type: ordinal +READOBJX-NEXT: Symbol: __imp_#manglednonamefunc +READOBJX-NEXT: Symbol: #manglednonamefunc RUN: llvm-lib -machine:arm64ec -def:test.def -defArm64Native:test2.def -out:test2.lib +RUN: llvm-lib -machine:arm64ec -def:test.def -defArm64Native:test2.def -out:test2x.lib RUN: llvm-nm --print-armap test2.lib | FileCheck -check-prefix=ARMAPX2 %s +RUN: llvm-nm --print-armap test2x.lib | FileCheck -check-prefix=ARMAPX2 %s ARMAPX2: Archive map ARMAPX2-NEXT: __IMPORT_DESCRIPTOR_test2 in test2.dll @@ -259,6 +337,8 @@ ARMAPX2-NEXT: Archive EC map ARMAPX2-NEXT: #expname in test2.dll ARMAPX2-NEXT: #funcexp in test2.dll ARMAPX2-NEXT: #mangledfunc in test2.dll +ARMAPX2-NEXT: #manglednonamefunc in test2.dll +ARMAPX2-NEXT: #nonamefunc in test2.dll ARMAPX2-NEXT: ?test_cpp_func@@$$hYAHPEAX@Z in test2.dll ARMAPX2-NEXT: ?test_cpp_func@@YAHPEAX@Z in test2.dll ARMAPX2-NEXT: __IMPORT_DESCRIPTOR_test2 in test2.dll @@ -268,13 +348,19 @@ ARMAPX2-NEXT: __imp_aux_?test_cpp_func@@YAHPEAX@Z in test2.dll ARMAPX2-NEXT: __imp_aux_expname in test2.dll ARMAPX2-NEXT: __imp_aux_funcexp in test2.dll ARMAPX2-NEXT: __imp_aux_mangledfunc in test2.dll +ARMAPX2-NEXT: __imp_aux_manglednonamefunc in test2.dll +ARMAPX2-NEXT: __imp_aux_nonamefunc in test2.dll ARMAPX2-NEXT: __imp_dataexp in test2.dll ARMAPX2-NEXT: __imp_expname in test2.dll ARMAPX2-NEXT: __imp_funcexp in test2.dll ARMAPX2-NEXT: __imp_mangledfunc in test2.dll +ARMAPX2-NEXT: __imp_manglednonamefunc in test2.dll +ARMAPX2-NEXT: __imp_nonamefunc in test2.dll ARMAPX2-NEXT: expname in test2.dll ARMAPX2-NEXT: funcexp in test2.dll ARMAPX2-NEXT: mangledfunc in test2.dll +ARMAPX2-NEXT: manglednonamefunc in test2.dll +ARMAPX2-NEXT: nonamefunc in test2.dll ARMAPX2-NEXT: test2_NULL_THUNK_DATA in test2.dll ARMAPX2: test2.dll: @@ -305,6 +391,18 @@ ARMAPX2-NEXT: test2.dll: ARMAPX2-NEXT: 00000000 D __imp_dataexp ARMAPX2-EMPTY: ARMAPX2-NEXT: test2.dll: +ARMAPX2-NEXT: 00000000 T #nonamefunc +ARMAPX2-NEXT: 00000000 T __imp_aux_nonamefunc +ARMAPX2-NEXT: 00000000 T __imp_nonamefunc +ARMAPX2-NEXT: 00000000 T nonamefunc +ARMAPX2-EMPTY: +ARMAPX2-NEXT: test2.dll: +ARMAPX2-NEXT: 00000000 T #manglednonamefunc +ARMAPX2-NEXT: 00000000 T __imp_aux_manglednonamefunc +ARMAPX2-NEXT: 00000000 T __imp_manglednonamefunc +ARMAPX2-NEXT: 00000000 T manglednonamefunc +ARMAPX2-EMPTY: +ARMAPX2-NEXT: test2.dll: ARMAPX2-NEXT: 00000000 T __imp_otherfunc ARMAPX2-NEXT: 00000000 T otherfunc @@ -399,6 +497,8 @@ EXPORTS ?test_cpp_func@@YAHPEAX@Z expname=impname dataexp DATA + nonamefunc @1 NONAME + #manglednonamefunc @2 NONAME #--- test2.def LIBRARY test2.dll diff --git a/llvm/test/tools/llvm-lib/empty.test b/llvm/test/tools/llvm-lib/empty.test new file mode 100644 index 0000000000000000000000000000000000000000..37c841f8db46a49503313d18d0fb389b13d98f1f --- /dev/null +++ b/llvm/test/tools/llvm-lib/empty.test @@ -0,0 +1,27 @@ +Create import libraries with empty exports and make sure that archive symbols +are properly populated. + +RUN: split-file %s %t.dir && cd %t.dir + +RUN: llvm-lib -machine:arm64 -out:arm64.lib -def:test.def +RUN: llvm-nm --print-armap arm64.lib | FileCheck --check-prefixes=CHECK,NOECMAP %s + +RUN: llvm-lib -machine:arm64ec -out:arm64ec.lib -def:test.def +RUN: llvm-nm --print-armap arm64ec.lib | FileCheck --check-prefixes=CHECK,ECMAP %s + +CHECK: Archive map +CHECK-NEXT: __IMPORT_DESCRIPTOR_test in test.dll +CHECK-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll +CHECK-NEXT: test_NULL_THUNK_DATA in test.dll +CHECK-EMPTY: + +ECMAP: Archive EC map +ECMAP-NEXT: __IMPORT_DESCRIPTOR_test in test.dll +ECMAP-NEXT: __NULL_IMPORT_DESCRIPTOR in test.dll +ECMAP-NEXT: test_NULL_THUNK_DATA in test.dll + +NOECMAP-NOT: Archive EC map + +#--- test.def +LIBRARY test.dll +EXPORTS diff --git a/llvm/test/tools/llvm-mca/AArch64/Neoverse/V1-sve-instructions.s b/llvm/test/tools/llvm-mca/AArch64/Neoverse/V1-sve-instructions.s index efa81b0ffcd48b9b51f481dedcc582559ea367ec..f120f5feaf7ced024bf9d155350b01d96ad5b7cb 100644 --- a/llvm/test/tools/llvm-mca/AArch64/Neoverse/V1-sve-instructions.s +++ b/llvm/test/tools/llvm-mca/AArch64/Neoverse/V1-sve-instructions.s @@ -4093,8 +4093,8 @@ zip2 z31.s, z31.s, z31.s # CHECK-NEXT: 1 12 7.00 sdiv z0.s, p7/m, z0.s, z31.s # CHECK-NEXT: 1 20 7.00 sdivr z0.d, p7/m, z0.d, z31.d # CHECK-NEXT: 1 12 7.00 sdivr z0.s, p7/m, z0.s, z31.s -# CHECK-NEXT: 1 4 0.50 sdot z0.d, z1.h, z15.h[1] -# CHECK-NEXT: 1 4 0.50 sdot z0.d, z1.h, z31.h +# CHECK-NEXT: 1 4 1.00 sdot z0.d, z1.h, z15.h[1] +# CHECK-NEXT: 1 4 1.00 sdot z0.d, z1.h, z31.h # CHECK-NEXT: 1 3 0.50 sdot z0.s, z1.b, z31.b # CHECK-NEXT: 1 3 0.50 sdot z0.s, z1.b, z7.b[3] # CHECK-NEXT: 1 2 0.50 sel z23.b, p11, z13.b, z8.b @@ -4569,8 +4569,8 @@ zip2 z31.s, z31.s, z31.s # CHECK-NEXT: 1 12 7.00 udiv z0.s, p7/m, z0.s, z31.s # CHECK-NEXT: 1 20 7.00 udivr z0.d, p7/m, z0.d, z31.d # CHECK-NEXT: 1 12 7.00 udivr z0.s, p7/m, z0.s, z31.s -# CHECK-NEXT: 1 4 0.50 udot z0.d, z1.h, z15.h[1] -# CHECK-NEXT: 1 4 0.50 udot z0.d, z1.h, z31.h +# CHECK-NEXT: 1 4 1.00 udot z0.d, z1.h, z15.h[1] +# CHECK-NEXT: 1 4 1.00 udot z0.d, z1.h, z31.h # CHECK-NEXT: 1 3 0.50 udot z0.s, z1.b, z31.b # CHECK-NEXT: 1 3 0.50 udot z0.s, z1.b, z7.b[3] # CHECK-NEXT: 1 2 0.50 umax z0.b, z0.b, #0 @@ -4839,7 +4839,7 @@ zip2 z31.s, z31.s, z31.s # CHECK: Resource pressure per iteration: # CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] -# CHECK-NEXT: - - - - 88.67 500.67 500.67 797.50 2.50 92.50 92.50 1250.00 923.00 178.50 181.50 +# CHECK-NEXT: - - - - 88.67 500.67 500.67 797.50 2.50 92.50 92.50 1252.00 921.00 178.50 181.50 # CHECK: Resource pressure by instruction: # CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6.0] [6.1] [7] [8] [9] [10] Instructions: @@ -6521,8 +6521,8 @@ zip2 z31.s, z31.s, z31.s # CHECK-NEXT: - - - - - - - - - - - 7.00 - - - sdiv z0.s, p7/m, z0.s, z31.s # CHECK-NEXT: - - - - - - - - - - - 7.00 - - - sdivr z0.d, p7/m, z0.d, z31.d # CHECK-NEXT: - - - - - - - - - - - 7.00 - - - sdivr z0.s, p7/m, z0.s, z31.s -# CHECK-NEXT: - - - - - - - - - - - 0.50 0.50 - - sdot z0.d, z1.h, z15.h[1] -# CHECK-NEXT: - - - - - - - - - - - 0.50 0.50 - - sdot z0.d, z1.h, z31.h +# CHECK-NEXT: - - - - - - - - - - - 1.00 - - - sdot z0.d, z1.h, z15.h[1] +# CHECK-NEXT: - - - - - - - - - - - 1.00 - - - sdot z0.d, z1.h, z31.h # CHECK-NEXT: - - - - - - - - - - - 0.50 0.50 - - sdot z0.s, z1.b, z31.b # CHECK-NEXT: - - - - - - - - - - - 0.50 0.50 - - sdot z0.s, z1.b, z7.b[3] # CHECK-NEXT: - - - - - - - - - - - 0.50 0.50 - - sel z23.b, p11, z13.b, z8.b @@ -6997,8 +6997,8 @@ zip2 z31.s, z31.s, z31.s # CHECK-NEXT: - - - - - - - - - - - 7.00 - - - udiv z0.s, p7/m, z0.s, z31.s # CHECK-NEXT: - - - - - - - - - - - 7.00 - - - udivr z0.d, p7/m, z0.d, z31.d # CHECK-NEXT: - - - - - - - - - - - 7.00 - - - udivr z0.s, p7/m, z0.s, z31.s -# CHECK-NEXT: - - - - - - - - - - - 0.50 0.50 - - udot z0.d, z1.h, z15.h[1] -# CHECK-NEXT: - - - - - - - - - - - 0.50 0.50 - - udot z0.d, z1.h, z31.h +# CHECK-NEXT: - - - - - - - - - - - 1.00 - - - udot z0.d, z1.h, z15.h[1] +# CHECK-NEXT: - - - - - - - - - - - 1.00 - - - udot z0.d, z1.h, z31.h # CHECK-NEXT: - - - - - - - - - - - 0.50 0.50 - - udot z0.s, z1.b, z31.b # CHECK-NEXT: - - - - - - - - - - - 0.50 0.50 - - udot z0.s, z1.b, z7.b[3] # CHECK-NEXT: - - - - - - - - - - - 0.50 0.50 - - umax z0.b, z0.b, #0 diff --git a/llvm/test/tools/llvm-mca/AArch64/Neoverse/V2-sve-instructions.s b/llvm/test/tools/llvm-mca/AArch64/Neoverse/V2-sve-instructions.s index 4d6ce706b0527446b35e7e9b0ec235144e26a345..acd355682494993724b84cdb6b1c982fee051a2c 100644 --- a/llvm/test/tools/llvm-mca/AArch64/Neoverse/V2-sve-instructions.s +++ b/llvm/test/tools/llvm-mca/AArch64/Neoverse/V2-sve-instructions.s @@ -4278,9 +4278,9 @@ zip2 z31.s, z31.s, z31.s # CHECK-NEXT: 1 3 0.25 fscale z0.d, p7/m, z0.d, z31.d # CHECK-NEXT: 1 3 0.25 fscale z0.h, p7/m, z0.h, z31.h # CHECK-NEXT: 1 3 0.25 fscale z0.s, p7/m, z0.s, z31.s -# CHECK-NEXT: 1 16 14.00 fsqrt z31.d, p7/m, z31.d -# CHECK-NEXT: 1 13 12.00 fsqrt z31.h, p7/m, z31.h -# CHECK-NEXT: 1 10 9.00 fsqrt z31.s, p7/m, z31.s +# CHECK-NEXT: 1 16 7.00 fsqrt z31.d, p7/m, z31.d +# CHECK-NEXT: 1 13 6.00 fsqrt z31.h, p7/m, z31.h +# CHECK-NEXT: 1 10 4.50 fsqrt z31.s, p7/m, z31.s # CHECK-NEXT: 1 2 0.25 fsub z0.d, p0/m, z0.d, #0.5 # CHECK-NEXT: 1 2 0.25 fsub z0.d, p7/m, z0.d, z31.d # CHECK-NEXT: 1 2 0.25 fsub z0.d, z1.d, z31.d @@ -6861,7 +6861,7 @@ zip2 z31.s, z31.s, z31.s # CHECK: Resource pressure per iteration: # CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] -# CHECK-NEXT: - - - - 245.00 651.00 651.00 570.50 272.50 83.75 83.75 81.75 81.75 1554.25 1281.75 776.75 748.25 +# CHECK-NEXT: - - - - 245.00 651.00 651.00 570.50 272.50 83.75 83.75 81.75 81.75 1536.75 1281.75 794.25 748.25 # CHECK: Resource pressure by instruction: # CHECK-NEXT: [0.0] [0.1] [1.0] [1.1] [2] [3.0] [3.1] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] Instructions: @@ -7718,9 +7718,9 @@ zip2 z31.s, z31.s, z31.s # CHECK-NEXT: - - - - - - - - - - - - - 0.25 0.25 0.25 0.25 fscale z0.d, p7/m, z0.d, z31.d # CHECK-NEXT: - - - - - - - - - - - - - 0.25 0.25 0.25 0.25 fscale z0.h, p7/m, z0.h, z31.h # CHECK-NEXT: - - - - - - - - - - - - - 0.25 0.25 0.25 0.25 fscale z0.s, p7/m, z0.s, z31.s -# CHECK-NEXT: - - - - - - - - - - - - - 14.00 - - - fsqrt z31.d, p7/m, z31.d -# CHECK-NEXT: - - - - - - - - - - - - - 12.00 - - - fsqrt z31.h, p7/m, z31.h -# CHECK-NEXT: - - - - - - - - - - - - - 9.00 - - - fsqrt z31.s, p7/m, z31.s +# CHECK-NEXT: - - - - - - - - - - - - - 7.00 - 7.00 - fsqrt z31.d, p7/m, z31.d +# CHECK-NEXT: - - - - - - - - - - - - - 6.00 - 6.00 - fsqrt z31.h, p7/m, z31.h +# CHECK-NEXT: - - - - - - - - - - - - - 4.50 - 4.50 - fsqrt z31.s, p7/m, z31.s # CHECK-NEXT: - - - - - - - - - - - - - 0.25 0.25 0.25 0.25 fsub z0.d, p0/m, z0.d, #0.5 # CHECK-NEXT: - - - - - - - - - - - - - 0.25 0.25 0.25 0.25 fsub z0.d, p7/m, z0.d, z31.d # CHECK-NEXT: - - - - - - - - - - - - - 0.25 0.25 0.25 0.25 fsub z0.d, z1.d, z31.d diff --git a/llvm/test/tools/llvm-mca/ARM/cortex-a57-basic-instructions.s b/llvm/test/tools/llvm-mca/ARM/cortex-a57-basic-instructions.s index 2257e453e0a8127d5a951aeaec087f0f39408113..d686293c9b43098490f34e64b41bd7d24efff5bb 100644 --- a/llvm/test/tools/llvm-mca/ARM/cortex-a57-basic-instructions.s +++ b/llvm/test/tools/llvm-mca/ARM/cortex-a57-basic-instructions.s @@ -1023,7 +1023,7 @@ # CHECK-NEXT: 2 2 1.00 blxne r2 # CHECK-NEXT: 2 1 1.00 U blx #32424576 # CHECK-NEXT: 2 1 1.00 U blx #16212288 -# CHECK-NEXT: 1 1 1.00 U bx r2 +# CHECK-NEXT: 1 1 1.00 bx r2 # CHECK-NEXT: 1 1 1.00 U bxne r2 # CHECK-NEXT: 1 1 1.00 U bxj r2 # CHECK-NEXT: 1 1 1.00 U bxjne r2 diff --git a/llvm/test/tools/llvm-mca/RISCV/SiFive7/gpr-bypass.s b/llvm/test/tools/llvm-mca/RISCV/SiFive7/gpr-bypass.s index 892a5d14e8f3a5d95b628febc2ccccc53010130f..03f7de2fe9a4c22d1dd320880626a66f8998dc0a 100644 --- a/llvm/test/tools/llvm-mca/RISCV/SiFive7/gpr-bypass.s +++ b/llvm/test/tools/llvm-mca/RISCV/SiFive7/gpr-bypass.s @@ -180,10 +180,10 @@ jr a0 # CHECK-NEXT: 1 3 0.50 sext.b a0, a0 # CHECK-NEXT: 1 3 0.50 sext.h a0, a0 # CHECK-NEXT: 1 3 0.50 zext.h a0, a0 -# CHECK-NEXT: 1 3 0.50 min a0, a0, a0 -# CHECK-NEXT: 1 3 0.50 minu a0, a0, a0 -# CHECK-NEXT: 1 3 0.50 max a0, a0, a0 -# CHECK-NEXT: 1 3 0.50 maxu a0, a0, a0 +# CHECK-NEXT: 1 3 1.00 min a0, a0, a0 +# CHECK-NEXT: 1 3 1.00 minu a0, a0, a0 +# CHECK-NEXT: 1 3 1.00 max a0, a0, a0 +# CHECK-NEXT: 1 3 1.00 maxu a0, a0, a0 # CHECK-NEXT: 1 3 1.00 rol a0, a0, a0 # CHECK-NEXT: 1 3 1.00 ror a0, a0, a0 # CHECK-NEXT: 1 3 1.00 rori a0, a0, 1 @@ -225,7 +225,7 @@ jr a0 # CHECK: Resource pressure per iteration: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] -# CHECK-NEXT: - - 39.00 52.00 - - - - +# CHECK-NEXT: - - 37.00 54.00 - - - - # CHECK: Resource pressure by instruction: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] Instructions: @@ -289,9 +289,9 @@ jr a0 # CHECK-NEXT: - - - 1.00 - - - - sext.h a0, a0 # CHECK-NEXT: - - 1.00 - - - - - zext.h a0, a0 # CHECK-NEXT: - - - 1.00 - - - - min a0, a0, a0 -# CHECK-NEXT: - - 1.00 - - - - - minu a0, a0, a0 +# CHECK-NEXT: - - - 1.00 - - - - minu a0, a0, a0 # CHECK-NEXT: - - - 1.00 - - - - max a0, a0, a0 -# CHECK-NEXT: - - 1.00 - - - - - maxu a0, a0, a0 +# CHECK-NEXT: - - - 1.00 - - - - maxu a0, a0, a0 # CHECK-NEXT: - - - 1.00 - - - - rol a0, a0, a0 # CHECK-NEXT: - - - 1.00 - - - - ror a0, a0, a0 # CHECK-NEXT: - - - 1.00 - - - - rori a0, a0, 1 diff --git a/llvm/test/tools/llvm-mca/RISCV/SiFive7/vector-integer-arithmetic.s b/llvm/test/tools/llvm-mca/RISCV/SiFive7/vector-integer-arithmetic.s index 21459bc45d453b4b61289674ec612bfdc8a159d2..3b6fd7e150137e829e72e692406939e20b77aa28 100644 --- a/llvm/test/tools/llvm-mca/RISCV/SiFive7/vector-integer-arithmetic.s +++ b/llvm/test/tools/llvm-mca/RISCV/SiFive7/vector-integer-arithmetic.s @@ -399,6 +399,26 @@ vmseq.vv v4, v8, v12 vsetvli zero, zero, e64, m8, tu, mu vmseq.vx v4, v8, x10 +# Pseudo instructions +vsetvli zero, zero, e8, mf8, tu, mu +vmslt.vi v4, v8, 1 +vsetvli zero, zero, e8, mf4, tu, mu +vmsltu.vi v4, v8, 1 +vsetvli zero, zero, e8, mf2, tu, mu +vmsltu.vi v4, v8, 0 +vsetvli zero, zero, e8, m1, tu, mu +vmsgeu.vi v4, v8, 1 +vsetvli zero, zero, e8, m2, tu, mu +vmsge.vi v4, v8, 1 +vsetvli zero, zero, e8, m4, tu, mu +vmsgeu.vi v4, v8, 0 +vsetvli zero, zero, e16, mf4, tu, mu +vmsge.vi v4, v8, 0 +vsetvli zero, zero, e16, mf2, tu, mu +vmsge.vx v4, v8, x10 +vsetvli zero, zero, e16, m1, tu, mu +vmsgeu.vx v4, v8, x11 + # Vector Integer Min/Max Instructions vsetvli zero, zero, e8, mf8, tu, mu vminu.vv v4, v8, v12 @@ -754,14 +774,14 @@ vsetvli zero, zero, e64, m8, tu, mu vmv.v.v v4, v12 # CHECK: Iterations: 1 -# CHECK-NEXT: Instructions: 707 -# CHECK-NEXT: Total Cycles: 11962 -# CHECK-NEXT: Total uOps: 707 +# CHECK-NEXT: Instructions: 727 +# CHECK-NEXT: Total Cycles: 12018 +# CHECK-NEXT: Total uOps: 727 # CHECK: Dispatch Width: 2 # CHECK-NEXT: uOps Per Cycle: 0.06 # CHECK-NEXT: IPC: 0.06 -# CHECK-NEXT: Block RThroughput: 11549.0 +# CHECK-NEXT: Block RThroughput: 11583.0 # CHECK: Instruction Info: # CHECK-NEXT: [1]: #uOps @@ -1144,6 +1164,26 @@ vmv.v.v v4, v12 # CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e64, m8, tu, mu # CHECK-NEXT: 1 19 17.00 vmseq.vx v4, v8, a0 # CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e8, mf8, tu, mu +# CHECK-NEXT: 1 4 2.00 vmsle.vi v4, v8, 0 +# CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e8, mf4, tu, mu +# CHECK-NEXT: 1 4 2.00 vmsleu.vi v4, v8, 0 +# CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e8, mf2, tu, mu +# CHECK-NEXT: 1 4 2.00 vmsne.vv v4, v8, v8 +# CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e8, m1, tu, mu +# CHECK-NEXT: 1 5 3.00 vmsgtu.vi v4, v8, 0 +# CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e8, m2, tu, mu +# CHECK-NEXT: 1 7 5.00 vmsgt.vi v4, v8, 0 +# CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e8, m4, tu, mu +# CHECK-NEXT: 1 11 9.00 vmseq.vv v4, v8, v8 +# CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e16, mf4, tu, mu +# CHECK-NEXT: 1 4 2.00 vmsgt.vi v4, v8, -1 +# CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e16, mf2, tu, mu +# CHECK-NEXT: 1 4 2.00 vmslt.vx v4, v8, a0 +# CHECK-NEXT: 1 4 2.00 vmnot.m v4, v4 +# CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e16, m1, tu, mu +# CHECK-NEXT: 1 5 3.00 vmsltu.vx v4, v8, a1 +# CHECK-NEXT: 1 4 2.00 vmnot.m v4, v4 +# CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e8, mf8, tu, mu # CHECK-NEXT: 1 4 2.00 vminu.vv v4, v8, v12 # CHECK-NEXT: 1 3 1.00 U vsetvli zero, zero, e8, mf4, tu, mu # CHECK-NEXT: 1 4 2.00 vminu.vx v4, v8, a0 @@ -1492,7 +1532,7 @@ vmv.v.v v4, v12 # CHECK: Resource pressure per iteration: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] -# CHECK-NEXT: - - 333.00 - 11549.00 374.00 - - +# CHECK-NEXT: - - 342.00 - 11583.00 385.00 - - # CHECK: Resource pressure by instruction: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] Instructions: @@ -1868,6 +1908,26 @@ vmv.v.v v4, v12 # CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e64, m8, tu, mu # CHECK-NEXT: - - - - 17.00 1.00 - - vmseq.vx v4, v8, a0 # CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e8, mf8, tu, mu +# CHECK-NEXT: - - - - 2.00 1.00 - - vmsle.vi v4, v8, 0 +# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e8, mf4, tu, mu +# CHECK-NEXT: - - - - 2.00 1.00 - - vmsleu.vi v4, v8, 0 +# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e8, mf2, tu, mu +# CHECK-NEXT: - - - - 2.00 1.00 - - vmsne.vv v4, v8, v8 +# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e8, m1, tu, mu +# CHECK-NEXT: - - - - 3.00 1.00 - - vmsgtu.vi v4, v8, 0 +# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e8, m2, tu, mu +# CHECK-NEXT: - - - - 5.00 1.00 - - vmsgt.vi v4, v8, 0 +# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e8, m4, tu, mu +# CHECK-NEXT: - - - - 9.00 1.00 - - vmseq.vv v4, v8, v8 +# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e16, mf4, tu, mu +# CHECK-NEXT: - - - - 2.00 1.00 - - vmsgt.vi v4, v8, -1 +# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e16, mf2, tu, mu +# CHECK-NEXT: - - - - 2.00 1.00 - - vmslt.vx v4, v8, a0 +# CHECK-NEXT: - - - - 2.00 1.00 - - vmnot.m v4, v4 +# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e16, m1, tu, mu +# CHECK-NEXT: - - - - 3.00 1.00 - - vmsltu.vx v4, v8, a1 +# CHECK-NEXT: - - - - 2.00 1.00 - - vmnot.m v4, v4 +# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e8, mf8, tu, mu # CHECK-NEXT: - - - - 2.00 1.00 - - vminu.vv v4, v8, v12 # CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, zero, e8, mf4, tu, mu # CHECK-NEXT: - - - - 2.00 1.00 - - vminu.vx v4, v8, a0 diff --git a/llvm/test/tools/llvm-mca/X86/Broadwell/resources-avx1.s b/llvm/test/tools/llvm-mca/X86/Broadwell/resources-avx1.s index c33cc79bd6c18a6486ed25db0ff8f4cbc6c06132..98b8619f2e04f9f9107b768f7fe2c4c24630aeef 100644 --- a/llvm/test/tools/llvm-mca/X86/Broadwell/resources-avx1.s +++ b/llvm/test/tools/llvm-mca/X86/Broadwell/resources-avx1.s @@ -1564,30 +1564,30 @@ vzeroupper # CHECK-NEXT: 2 6 0.50 * vpsignw (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpslld $1, %xmm0, %xmm2 # CHECK-NEXT: 2 2 1.00 vpslld %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: 3 7 1.00 * vpslld (%rax), %xmm1, %xmm2 +# CHECK-NEXT: 2 7 1.00 * vpslld (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpslldq $1, %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpsllq $1, %xmm0, %xmm2 # CHECK-NEXT: 2 2 1.00 vpsllq %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: 3 7 1.00 * vpsllq (%rax), %xmm1, %xmm2 +# CHECK-NEXT: 2 7 1.00 * vpsllq (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpsllw $1, %xmm0, %xmm2 # CHECK-NEXT: 2 2 1.00 vpsllw %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: 3 7 1.00 * vpsllw (%rax), %xmm1, %xmm2 +# CHECK-NEXT: 2 7 1.00 * vpsllw (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpsrad $1, %xmm0, %xmm2 # CHECK-NEXT: 2 2 1.00 vpsrad %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: 3 7 1.00 * vpsrad (%rax), %xmm1, %xmm2 +# CHECK-NEXT: 2 7 1.00 * vpsrad (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpsraw $1, %xmm0, %xmm2 # CHECK-NEXT: 2 2 1.00 vpsraw %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: 3 7 1.00 * vpsraw (%rax), %xmm1, %xmm2 +# CHECK-NEXT: 2 7 1.00 * vpsraw (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpsrld $1, %xmm0, %xmm2 # CHECK-NEXT: 2 2 1.00 vpsrld %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: 3 7 1.00 * vpsrld (%rax), %xmm1, %xmm2 +# CHECK-NEXT: 2 7 1.00 * vpsrld (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpsrldq $1, %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpsrlq $1, %xmm0, %xmm2 # CHECK-NEXT: 2 2 1.00 vpsrlq %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: 3 7 1.00 * vpsrlq (%rax), %xmm1, %xmm2 +# CHECK-NEXT: 2 7 1.00 * vpsrlq (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpsrlw $1, %xmm0, %xmm2 # CHECK-NEXT: 2 2 1.00 vpsrlw %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: 3 7 1.00 * vpsrlw (%rax), %xmm1, %xmm2 +# CHECK-NEXT: 2 7 1.00 * vpsrlw (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 0.50 vpsubb %xmm0, %xmm1, %xmm2 # CHECK-NEXT: 2 6 0.50 * vpsubb (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 0.50 vpsubd %xmm0, %xmm1, %xmm2 @@ -1736,7 +1736,7 @@ vzeroupper # CHECK: Resource pressure per iteration: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] -# CHECK-NEXT: - 257.00 215.25 235.25 176.17 176.17 38.00 432.25 2.25 12.67 +# CHECK-NEXT: - 257.00 215.25 235.25 176.17 176.17 38.00 424.25 2.25 12.67 # CHECK: Resource pressure by instruction: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] Instructions: @@ -2274,30 +2274,30 @@ vzeroupper # CHECK-NEXT: - - - 0.50 0.50 0.50 - 0.50 - - vpsignw (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - vpslld $1, %xmm0, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - vpslld %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - vpslld (%rax), %xmm1, %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - vpslld (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - - - - - - 1.00 - - vpslldq $1, %xmm1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - vpsllq $1, %xmm0, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - vpsllq %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - vpsllq (%rax), %xmm1, %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - vpsllq (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - vpsllw $1, %xmm0, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - vpsllw %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - vpsllw (%rax), %xmm1, %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - vpsllw (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - vpsrad $1, %xmm0, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - vpsrad %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - vpsrad (%rax), %xmm1, %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - vpsrad (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - vpsraw $1, %xmm0, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - vpsraw %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - vpsraw (%rax), %xmm1, %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - vpsraw (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - vpsrld $1, %xmm0, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - vpsrld %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - vpsrld (%rax), %xmm1, %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - vpsrld (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - - - - - - 1.00 - - vpsrldq $1, %xmm1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - vpsrlq $1, %xmm0, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - vpsrlq %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - vpsrlq (%rax), %xmm1, %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - vpsrlq (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - vpsrlw $1, %xmm0, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - vpsrlw %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - vpsrlw (%rax), %xmm1, %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - vpsrlw (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - - 0.50 - - - 0.50 - - vpsubb %xmm0, %xmm1, %xmm2 # CHECK-NEXT: - - - 0.50 0.50 0.50 - 0.50 - - vpsubb (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - - 0.50 - - - 0.50 - - vpsubd %xmm0, %xmm1, %xmm2 diff --git a/llvm/test/tools/llvm-mca/X86/Broadwell/resources-sse2.s b/llvm/test/tools/llvm-mca/X86/Broadwell/resources-sse2.s index 5bed312b0fe1d27b79e1e3ac5bb7fa9059cdda7f..e76d90521afa9c8028eb955bd2ea5574c5e61954 100644 --- a/llvm/test/tools/llvm-mca/X86/Broadwell/resources-sse2.s +++ b/llvm/test/tools/llvm-mca/X86/Broadwell/resources-sse2.s @@ -596,30 +596,30 @@ xorpd (%rax), %xmm2 # CHECK-NEXT: 2 6 1.00 * pshuflw $1, (%rax), %xmm2 # CHECK-NEXT: 1 1 1.00 pslld $1, %xmm2 # CHECK-NEXT: 2 2 1.00 pslld %xmm0, %xmm2 -# CHECK-NEXT: 3 7 1.00 * pslld (%rax), %xmm2 +# CHECK-NEXT: 2 7 1.00 * pslld (%rax), %xmm2 # CHECK-NEXT: 1 1 1.00 pslldq $1, %xmm2 # CHECK-NEXT: 1 1 1.00 psllq $1, %xmm2 # CHECK-NEXT: 2 2 1.00 psllq %xmm0, %xmm2 -# CHECK-NEXT: 3 7 1.00 * psllq (%rax), %xmm2 +# CHECK-NEXT: 2 7 1.00 * psllq (%rax), %xmm2 # CHECK-NEXT: 1 1 1.00 psllw $1, %xmm2 # CHECK-NEXT: 2 2 1.00 psllw %xmm0, %xmm2 -# CHECK-NEXT: 3 7 1.00 * psllw (%rax), %xmm2 +# CHECK-NEXT: 2 7 1.00 * psllw (%rax), %xmm2 # CHECK-NEXT: 1 1 1.00 psrad $1, %xmm2 # CHECK-NEXT: 2 2 1.00 psrad %xmm0, %xmm2 -# CHECK-NEXT: 3 7 1.00 * psrad (%rax), %xmm2 +# CHECK-NEXT: 2 7 1.00 * psrad (%rax), %xmm2 # CHECK-NEXT: 1 1 1.00 psraw $1, %xmm2 # CHECK-NEXT: 2 2 1.00 psraw %xmm0, %xmm2 -# CHECK-NEXT: 3 7 1.00 * psraw (%rax), %xmm2 +# CHECK-NEXT: 2 7 1.00 * psraw (%rax), %xmm2 # CHECK-NEXT: 1 1 1.00 psrld $1, %xmm2 # CHECK-NEXT: 2 2 1.00 psrld %xmm0, %xmm2 -# CHECK-NEXT: 3 7 1.00 * psrld (%rax), %xmm2 +# CHECK-NEXT: 2 7 1.00 * psrld (%rax), %xmm2 # CHECK-NEXT: 1 1 1.00 psrldq $1, %xmm2 # CHECK-NEXT: 1 1 1.00 psrlq $1, %xmm2 # CHECK-NEXT: 2 2 1.00 psrlq %xmm0, %xmm2 -# CHECK-NEXT: 3 7 1.00 * psrlq (%rax), %xmm2 +# CHECK-NEXT: 2 7 1.00 * psrlq (%rax), %xmm2 # CHECK-NEXT: 1 1 1.00 psrlw $1, %xmm2 # CHECK-NEXT: 2 2 1.00 psrlw %xmm0, %xmm2 -# CHECK-NEXT: 3 7 1.00 * psrlw (%rax), %xmm2 +# CHECK-NEXT: 2 7 1.00 * psrlw (%rax), %xmm2 # CHECK-NEXT: 1 1 0.50 psubb %xmm0, %xmm2 # CHECK-NEXT: 2 6 0.50 * psubb (%rax), %xmm2 # CHECK-NEXT: 1 1 0.50 psubd %xmm0, %xmm2 @@ -689,7 +689,7 @@ xorpd (%rax), %xmm2 # CHECK: Resource pressure per iteration: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] -# CHECK-NEXT: - 78.00 70.75 95.75 63.17 63.17 14.00 127.25 2.25 4.67 +# CHECK-NEXT: - 78.00 70.75 95.75 63.17 63.17 14.00 119.25 2.25 4.67 # CHECK: Resource pressure by instruction: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] Instructions: @@ -882,30 +882,30 @@ xorpd (%rax), %xmm2 # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - pshuflw $1, (%rax), %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - pslld $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - pslld %xmm0, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - pslld (%rax), %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - pslld (%rax), %xmm2 # CHECK-NEXT: - - - - - - - 1.00 - - pslldq $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - psllq $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - psllq %xmm0, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - psllq (%rax), %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - psllq (%rax), %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - psllw $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - psllw %xmm0, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - psllw (%rax), %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - psllw (%rax), %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - psrad $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - psrad %xmm0, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - psrad (%rax), %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - psrad (%rax), %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - psraw $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - psraw %xmm0, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - psraw (%rax), %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - psraw (%rax), %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - psrld $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - psrld %xmm0, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - psrld (%rax), %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - psrld (%rax), %xmm2 # CHECK-NEXT: - - - - - - - 1.00 - - psrldq $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - psrlq $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - psrlq %xmm0, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - psrlq (%rax), %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - psrlq (%rax), %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - psrlw $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - psrlw %xmm0, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - psrlw (%rax), %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - psrlw (%rax), %xmm2 # CHECK-NEXT: - - - 0.50 - - - 0.50 - - psubb %xmm0, %xmm2 # CHECK-NEXT: - - - 0.50 0.50 0.50 - 0.50 - - psubb (%rax), %xmm2 # CHECK-NEXT: - - - 0.50 - - - 0.50 - - psubd %xmm0, %xmm2 diff --git a/llvm/test/tools/llvm-mca/X86/Haswell/resources-avx1.s b/llvm/test/tools/llvm-mca/X86/Haswell/resources-avx1.s index 3da547de54e36d1dcbd28538166f5a7ba97b652e..376070d7f4e0b649c7d77b60a2f79e2dfa4de0f5 100644 --- a/llvm/test/tools/llvm-mca/X86/Haswell/resources-avx1.s +++ b/llvm/test/tools/llvm-mca/X86/Haswell/resources-avx1.s @@ -1564,30 +1564,30 @@ vzeroupper # CHECK-NEXT: 2 7 0.50 * vpsignw (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpslld $1, %xmm0, %xmm2 # CHECK-NEXT: 2 2 1.00 vpslld %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: 3 8 1.00 * vpslld (%rax), %xmm1, %xmm2 +# CHECK-NEXT: 2 8 1.00 * vpslld (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpslldq $1, %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpsllq $1, %xmm0, %xmm2 # CHECK-NEXT: 2 2 1.00 vpsllq %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: 3 8 1.00 * vpsllq (%rax), %xmm1, %xmm2 +# CHECK-NEXT: 2 8 1.00 * vpsllq (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpsllw $1, %xmm0, %xmm2 # CHECK-NEXT: 2 2 1.00 vpsllw %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: 3 8 1.00 * vpsllw (%rax), %xmm1, %xmm2 +# CHECK-NEXT: 2 8 1.00 * vpsllw (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpsrad $1, %xmm0, %xmm2 # CHECK-NEXT: 2 2 1.00 vpsrad %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: 3 8 1.00 * vpsrad (%rax), %xmm1, %xmm2 +# CHECK-NEXT: 2 8 1.00 * vpsrad (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpsraw $1, %xmm0, %xmm2 # CHECK-NEXT: 2 2 1.00 vpsraw %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: 3 8 1.00 * vpsraw (%rax), %xmm1, %xmm2 +# CHECK-NEXT: 2 8 1.00 * vpsraw (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpsrld $1, %xmm0, %xmm2 # CHECK-NEXT: 2 2 1.00 vpsrld %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: 3 8 1.00 * vpsrld (%rax), %xmm1, %xmm2 +# CHECK-NEXT: 2 8 1.00 * vpsrld (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpsrldq $1, %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpsrlq $1, %xmm0, %xmm2 # CHECK-NEXT: 2 2 1.00 vpsrlq %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: 3 8 1.00 * vpsrlq (%rax), %xmm1, %xmm2 +# CHECK-NEXT: 2 8 1.00 * vpsrlq (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 1.00 vpsrlw $1, %xmm0, %xmm2 # CHECK-NEXT: 2 2 1.00 vpsrlw %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: 3 8 1.00 * vpsrlw (%rax), %xmm1, %xmm2 +# CHECK-NEXT: 2 8 1.00 * vpsrlw (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 0.50 vpsubb %xmm0, %xmm1, %xmm2 # CHECK-NEXT: 2 7 0.50 * vpsubb (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 0.50 vpsubd %xmm0, %xmm1, %xmm2 @@ -1736,7 +1736,7 @@ vzeroupper # CHECK: Resource pressure per iteration: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] -# CHECK-NEXT: - 336.00 214.58 236.58 176.17 176.17 38.00 435.58 2.25 12.67 +# CHECK-NEXT: - 336.00 214.58 236.58 176.17 176.17 38.00 427.58 2.25 12.67 # CHECK: Resource pressure by instruction: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] Instructions: @@ -2274,30 +2274,30 @@ vzeroupper # CHECK-NEXT: - - - 0.50 0.50 0.50 - 0.50 - - vpsignw (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - vpslld $1, %xmm0, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - vpslld %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - vpslld (%rax), %xmm1, %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - vpslld (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - - - - - - 1.00 - - vpslldq $1, %xmm1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - vpsllq $1, %xmm0, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - vpsllq %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - vpsllq (%rax), %xmm1, %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - vpsllq (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - vpsllw $1, %xmm0, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - vpsllw %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - vpsllw (%rax), %xmm1, %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - vpsllw (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - vpsrad $1, %xmm0, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - vpsrad %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - vpsrad (%rax), %xmm1, %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - vpsrad (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - vpsraw $1, %xmm0, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - vpsraw %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - vpsraw (%rax), %xmm1, %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - vpsraw (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - vpsrld $1, %xmm0, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - vpsrld %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - vpsrld (%rax), %xmm1, %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - vpsrld (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - - - - - - 1.00 - - vpsrldq $1, %xmm1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - vpsrlq $1, %xmm0, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - vpsrlq %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - vpsrlq (%rax), %xmm1, %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - vpsrlq (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - vpsrlw $1, %xmm0, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - vpsrlw %xmm0, %xmm1, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - vpsrlw (%rax), %xmm1, %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - vpsrlw (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - - 0.50 - - - 0.50 - - vpsubb %xmm0, %xmm1, %xmm2 # CHECK-NEXT: - - - 0.50 0.50 0.50 - 0.50 - - vpsubb (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - - 0.50 - - - 0.50 - - vpsubd %xmm0, %xmm1, %xmm2 diff --git a/llvm/test/tools/llvm-mca/X86/Haswell/resources-sse2.s b/llvm/test/tools/llvm-mca/X86/Haswell/resources-sse2.s index 3813ef4707a80148e0dde64768b112bdc8fb6304..3b4aeb37968fd589f53edd1d4e9a215b3213b5c6 100644 --- a/llvm/test/tools/llvm-mca/X86/Haswell/resources-sse2.s +++ b/llvm/test/tools/llvm-mca/X86/Haswell/resources-sse2.s @@ -596,30 +596,30 @@ xorpd (%rax), %xmm2 # CHECK-NEXT: 2 7 1.00 * pshuflw $1, (%rax), %xmm2 # CHECK-NEXT: 1 1 1.00 pslld $1, %xmm2 # CHECK-NEXT: 2 2 1.00 pslld %xmm0, %xmm2 -# CHECK-NEXT: 3 8 1.00 * pslld (%rax), %xmm2 +# CHECK-NEXT: 2 8 1.00 * pslld (%rax), %xmm2 # CHECK-NEXT: 1 1 1.00 pslldq $1, %xmm2 # CHECK-NEXT: 1 1 1.00 psllq $1, %xmm2 # CHECK-NEXT: 2 2 1.00 psllq %xmm0, %xmm2 -# CHECK-NEXT: 3 8 1.00 * psllq (%rax), %xmm2 +# CHECK-NEXT: 2 8 1.00 * psllq (%rax), %xmm2 # CHECK-NEXT: 1 1 1.00 psllw $1, %xmm2 # CHECK-NEXT: 2 2 1.00 psllw %xmm0, %xmm2 -# CHECK-NEXT: 3 8 1.00 * psllw (%rax), %xmm2 +# CHECK-NEXT: 2 8 1.00 * psllw (%rax), %xmm2 # CHECK-NEXT: 1 1 1.00 psrad $1, %xmm2 # CHECK-NEXT: 2 2 1.00 psrad %xmm0, %xmm2 -# CHECK-NEXT: 3 8 1.00 * psrad (%rax), %xmm2 +# CHECK-NEXT: 2 8 1.00 * psrad (%rax), %xmm2 # CHECK-NEXT: 1 1 1.00 psraw $1, %xmm2 # CHECK-NEXT: 2 2 1.00 psraw %xmm0, %xmm2 -# CHECK-NEXT: 3 8 1.00 * psraw (%rax), %xmm2 +# CHECK-NEXT: 2 8 1.00 * psraw (%rax), %xmm2 # CHECK-NEXT: 1 1 1.00 psrld $1, %xmm2 # CHECK-NEXT: 2 2 1.00 psrld %xmm0, %xmm2 -# CHECK-NEXT: 3 8 1.00 * psrld (%rax), %xmm2 +# CHECK-NEXT: 2 8 1.00 * psrld (%rax), %xmm2 # CHECK-NEXT: 1 1 1.00 psrldq $1, %xmm2 # CHECK-NEXT: 1 1 1.00 psrlq $1, %xmm2 # CHECK-NEXT: 2 2 1.00 psrlq %xmm0, %xmm2 -# CHECK-NEXT: 3 8 1.00 * psrlq (%rax), %xmm2 +# CHECK-NEXT: 2 8 1.00 * psrlq (%rax), %xmm2 # CHECK-NEXT: 1 1 1.00 psrlw $1, %xmm2 # CHECK-NEXT: 2 2 1.00 psrlw %xmm0, %xmm2 -# CHECK-NEXT: 3 8 1.00 * psrlw (%rax), %xmm2 +# CHECK-NEXT: 2 8 1.00 * psrlw (%rax), %xmm2 # CHECK-NEXT: 1 1 0.50 psubb %xmm0, %xmm2 # CHECK-NEXT: 2 7 0.50 * psubb (%rax), %xmm2 # CHECK-NEXT: 1 1 0.50 psubd %xmm0, %xmm2 @@ -689,7 +689,7 @@ xorpd (%rax), %xmm2 # CHECK: Resource pressure per iteration: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] -# CHECK-NEXT: - 112.00 70.75 95.75 63.17 63.17 14.00 127.25 2.25 4.67 +# CHECK-NEXT: - 112.00 70.75 95.75 63.17 63.17 14.00 119.25 2.25 4.67 # CHECK: Resource pressure by instruction: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] Instructions: @@ -882,30 +882,30 @@ xorpd (%rax), %xmm2 # CHECK-NEXT: - - - - 0.50 0.50 - 1.00 - - pshuflw $1, (%rax), %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - pslld $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - pslld %xmm0, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - pslld (%rax), %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - pslld (%rax), %xmm2 # CHECK-NEXT: - - - - - - - 1.00 - - pslldq $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - psllq $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - psllq %xmm0, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - psllq (%rax), %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - psllq (%rax), %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - psllw $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - psllw %xmm0, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - psllw (%rax), %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - psllw (%rax), %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - psrad $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - psrad %xmm0, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - psrad (%rax), %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - psrad (%rax), %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - psraw $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - psraw %xmm0, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - psraw (%rax), %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - psraw (%rax), %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - psrld $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - psrld %xmm0, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - psrld (%rax), %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - psrld (%rax), %xmm2 # CHECK-NEXT: - - - - - - - 1.00 - - psrldq $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - psrlq $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - psrlq %xmm0, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - psrlq (%rax), %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - psrlq (%rax), %xmm2 # CHECK-NEXT: - - 1.00 - - - - - - - psrlw $1, %xmm2 # CHECK-NEXT: - - 1.00 - - - - 1.00 - - psrlw %xmm0, %xmm2 -# CHECK-NEXT: - - 1.00 - 0.50 0.50 - 1.00 - - psrlw (%rax), %xmm2 +# CHECK-NEXT: - - 1.00 - 0.50 0.50 - - - - psrlw (%rax), %xmm2 # CHECK-NEXT: - - - 0.50 - - - 0.50 - - psubb %xmm0, %xmm2 # CHECK-NEXT: - - - 0.50 0.50 0.50 - 0.50 - - psubb (%rax), %xmm2 # CHECK-NEXT: - - - 0.50 - - - 0.50 - - psubd %xmm0, %xmm2 diff --git a/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-avx1.s b/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-avx1.s index f184d5579d06e5de40a75972e2233d113d852dbc..bd7a4894b45d6bb2c2f7d82be890cdf3dfcde730 100644 --- a/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-avx1.s +++ b/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-avx1.s @@ -1563,30 +1563,30 @@ vzeroupper # CHECK-NEXT: 1 1 0.50 vpsignw %xmm0, %xmm1, %xmm2 # CHECK-NEXT: 2 7 0.50 * vpsignw (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 0.50 vpslld $1, %xmm0, %xmm2 -# CHECK-NEXT: 2 2 1.00 vpslld %xmm0, %xmm1, %xmm2 +# CHECK-NEXT: 2 2 0.67 vpslld %xmm0, %xmm1, %xmm2 # CHECK-NEXT: 2 7 0.50 * vpslld (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 0.50 vpslldq $1, %xmm1, %xmm2 # CHECK-NEXT: 1 1 0.50 vpsllq $1, %xmm0, %xmm2 -# CHECK-NEXT: 2 2 1.00 vpsllq %xmm0, %xmm1, %xmm2 +# CHECK-NEXT: 2 2 0.67 vpsllq %xmm0, %xmm1, %xmm2 # CHECK-NEXT: 2 7 0.50 * vpsllq (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 0.50 vpsllw $1, %xmm0, %xmm2 -# CHECK-NEXT: 2 2 1.00 vpsllw %xmm0, %xmm1, %xmm2 +# CHECK-NEXT: 2 2 0.67 vpsllw %xmm0, %xmm1, %xmm2 # CHECK-NEXT: 2 7 0.50 * vpsllw (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 0.50 vpsrad $1, %xmm0, %xmm2 -# CHECK-NEXT: 2 2 1.00 vpsrad %xmm0, %xmm1, %xmm2 +# CHECK-NEXT: 2 2 0.67 vpsrad %xmm0, %xmm1, %xmm2 # CHECK-NEXT: 2 7 0.50 * vpsrad (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 0.50 vpsraw $1, %xmm0, %xmm2 -# CHECK-NEXT: 2 2 1.00 vpsraw %xmm0, %xmm1, %xmm2 +# CHECK-NEXT: 2 2 0.67 vpsraw %xmm0, %xmm1, %xmm2 # CHECK-NEXT: 2 7 0.50 * vpsraw (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 0.50 vpsrld $1, %xmm0, %xmm2 -# CHECK-NEXT: 2 2 1.00 vpsrld %xmm0, %xmm1, %xmm2 +# CHECK-NEXT: 2 2 0.67 vpsrld %xmm0, %xmm1, %xmm2 # CHECK-NEXT: 2 7 0.50 * vpsrld (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 0.50 vpsrldq $1, %xmm1, %xmm2 # CHECK-NEXT: 1 1 0.50 vpsrlq $1, %xmm0, %xmm2 -# CHECK-NEXT: 2 2 1.00 vpsrlq %xmm0, %xmm1, %xmm2 +# CHECK-NEXT: 2 2 0.67 vpsrlq %xmm0, %xmm1, %xmm2 # CHECK-NEXT: 2 7 0.50 * vpsrlq (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 0.50 vpsrlw $1, %xmm0, %xmm2 -# CHECK-NEXT: 2 2 1.00 vpsrlw %xmm0, %xmm1, %xmm2 +# CHECK-NEXT: 2 2 0.67 vpsrlw %xmm0, %xmm1, %xmm2 # CHECK-NEXT: 2 7 0.50 * vpsrlw (%rax), %xmm1, %xmm2 # CHECK-NEXT: 1 1 0.33 vpsubb %xmm0, %xmm1, %xmm2 # CHECK-NEXT: 2 7 0.50 * vpsubb (%rax), %xmm1, %xmm2 @@ -1738,7 +1738,7 @@ vzeroupper # CHECK: Resource pressure per iteration: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] -# CHECK-NEXT: - 126.00 322.92 233.92 160.50 160.50 19.00 295.92 6.25 19.00 19.00 19.00 +# CHECK-NEXT: - 126.00 322.92 237.92 160.50 160.50 19.00 291.92 6.25 19.00 19.00 19.00 # CHECK: Resource pressure by instruction: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] Instructions: @@ -2275,30 +2275,30 @@ vzeroupper # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - vpsignw %xmm0, %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsignw (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - vpslld $1, %xmm0, %xmm2 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpslld %xmm0, %xmm1, %xmm2 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - vpslld %xmm0, %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpslld (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - - 0.50 - - - 0.50 - - - - vpslldq $1, %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - vpsllq $1, %xmm0, %xmm2 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsllq %xmm0, %xmm1, %xmm2 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - vpsllq %xmm0, %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsllq (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - vpsllw $1, %xmm0, %xmm2 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsllw %xmm0, %xmm1, %xmm2 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - vpsllw %xmm0, %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsllw (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - vpsrad $1, %xmm0, %xmm2 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsrad %xmm0, %xmm1, %xmm2 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - vpsrad %xmm0, %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsrad (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - vpsraw $1, %xmm0, %xmm2 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsraw %xmm0, %xmm1, %xmm2 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - vpsraw %xmm0, %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsraw (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - vpsrld $1, %xmm0, %xmm2 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsrld %xmm0, %xmm1, %xmm2 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - vpsrld %xmm0, %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsrld (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - - 0.50 - - - 0.50 - - - - vpsrldq $1, %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - vpsrlq $1, %xmm0, %xmm2 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsrlq %xmm0, %xmm1, %xmm2 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - vpsrlq %xmm0, %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsrlq (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - vpsrlw $1, %xmm0, %xmm2 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsrlw %xmm0, %xmm1, %xmm2 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - vpsrlw %xmm0, %xmm1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsrlw (%rax), %xmm1, %xmm2 # CHECK-NEXT: - - 0.33 0.33 - - - 0.33 - - - - vpsubb %xmm0, %xmm1, %xmm2 # CHECK-NEXT: - - 0.33 0.33 0.50 0.50 - 0.33 - - - - vpsubb (%rax), %xmm1, %xmm2 diff --git a/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-avx512bwvl.s b/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-avx512bwvl.s index a0715cef8b00c852eaf0ea74cde1e3d766751f93..ee095f0d3bfc15641b1cbca9a4ee17e09280cf22 100644 --- a/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-avx512bwvl.s +++ b/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-avx512bwvl.s @@ -1768,11 +1768,11 @@ vpunpcklwd (%rax), %ymm17, %ymm19 {z}{k1} # CHECK-NEXT: 2 8 0.50 * vpsllw $0, (%rax), %ymm19 {%k1} # CHECK-NEXT: 1 1 0.50 vpsllw $0, %ymm16, %ymm19 {%k1} {z} # CHECK-NEXT: 2 8 0.50 * vpsllw $0, (%rax), %ymm19 {%k1} {z} -# CHECK-NEXT: 2 2 1.00 vpsllw %xmm16, %xmm17, %xmm19 +# CHECK-NEXT: 2 2 0.67 vpsllw %xmm16, %xmm17, %xmm19 # CHECK-NEXT: 2 7 0.50 * vpsllw (%rax), %xmm17, %xmm19 -# CHECK-NEXT: 2 2 1.00 vpsllw %xmm16, %xmm17, %xmm19 {%k1} +# CHECK-NEXT: 2 2 0.67 vpsllw %xmm16, %xmm17, %xmm19 {%k1} # CHECK-NEXT: 2 7 0.50 * vpsllw (%rax), %xmm17, %xmm19 {%k1} -# CHECK-NEXT: 2 2 1.00 vpsllw %xmm16, %xmm17, %xmm19 {%k1} {z} +# CHECK-NEXT: 2 2 0.67 vpsllw %xmm16, %xmm17, %xmm19 {%k1} {z} # CHECK-NEXT: 2 7 0.50 * vpsllw (%rax), %xmm17, %xmm19 {%k1} {z} # CHECK-NEXT: 2 4 1.00 vpsllw %xmm16, %ymm17, %ymm19 # CHECK-NEXT: 2 8 0.50 * vpsllw (%rax), %ymm17, %ymm19 @@ -1804,11 +1804,11 @@ vpunpcklwd (%rax), %ymm17, %ymm19 {z}{k1} # CHECK-NEXT: 2 8 0.50 * vpsraw $0, (%rax), %ymm19 {%k1} # CHECK-NEXT: 1 1 0.50 vpsraw $0, %ymm16, %ymm19 {%k1} {z} # CHECK-NEXT: 2 8 0.50 * vpsraw $0, (%rax), %ymm19 {%k1} {z} -# CHECK-NEXT: 2 2 1.00 vpsraw %xmm16, %xmm17, %xmm19 +# CHECK-NEXT: 2 2 0.67 vpsraw %xmm16, %xmm17, %xmm19 # CHECK-NEXT: 2 7 0.50 * vpsraw (%rax), %xmm17, %xmm19 -# CHECK-NEXT: 2 2 1.00 vpsraw %xmm16, %xmm17, %xmm19 {%k1} +# CHECK-NEXT: 2 2 0.67 vpsraw %xmm16, %xmm17, %xmm19 {%k1} # CHECK-NEXT: 2 7 0.50 * vpsraw (%rax), %xmm17, %xmm19 {%k1} -# CHECK-NEXT: 2 2 1.00 vpsraw %xmm16, %xmm17, %xmm19 {%k1} {z} +# CHECK-NEXT: 2 2 0.67 vpsraw %xmm16, %xmm17, %xmm19 {%k1} {z} # CHECK-NEXT: 2 7 0.50 * vpsraw (%rax), %xmm17, %xmm19 {%k1} {z} # CHECK-NEXT: 2 4 1.00 vpsraw %xmm16, %ymm17, %ymm19 # CHECK-NEXT: 2 8 0.50 * vpsraw (%rax), %ymm17, %ymm19 @@ -1844,11 +1844,11 @@ vpunpcklwd (%rax), %ymm17, %ymm19 {z}{k1} # CHECK-NEXT: 2 8 0.50 * vpsrlw $0, (%rax), %ymm19 {%k1} # CHECK-NEXT: 1 1 0.50 vpsrlw $0, %ymm16, %ymm19 {%k1} {z} # CHECK-NEXT: 2 8 0.50 * vpsrlw $0, (%rax), %ymm19 {%k1} {z} -# CHECK-NEXT: 2 2 1.00 vpsrlw %xmm16, %xmm17, %xmm19 +# CHECK-NEXT: 2 2 0.67 vpsrlw %xmm16, %xmm17, %xmm19 # CHECK-NEXT: 2 7 0.50 * vpsrlw (%rax), %xmm17, %xmm19 -# CHECK-NEXT: 2 2 1.00 vpsrlw %xmm16, %xmm17, %xmm19 {%k1} +# CHECK-NEXT: 2 2 0.67 vpsrlw %xmm16, %xmm17, %xmm19 {%k1} # CHECK-NEXT: 2 7 0.50 * vpsrlw (%rax), %xmm17, %xmm19 {%k1} -# CHECK-NEXT: 2 2 1.00 vpsrlw %xmm16, %xmm17, %xmm19 {%k1} {z} +# CHECK-NEXT: 2 2 0.67 vpsrlw %xmm16, %xmm17, %xmm19 {%k1} {z} # CHECK-NEXT: 2 7 0.50 * vpsrlw (%rax), %xmm17, %xmm19 {%k1} {z} # CHECK-NEXT: 2 4 1.00 vpsrlw %xmm16, %ymm17, %ymm19 # CHECK-NEXT: 2 8 0.50 * vpsrlw (%rax), %ymm17, %ymm19 @@ -2025,7 +2025,7 @@ vpunpcklwd (%rax), %ymm17, %ymm19 {z}{k1} # CHECK: Resource pressure per iteration: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] -# CHECK-NEXT: - - 255.33 303.33 216.00 216.00 10.00 451.33 - 10.00 10.00 10.00 +# CHECK-NEXT: - - 255.33 307.83 216.00 216.00 10.00 446.83 - 10.00 10.00 10.00 # CHECK: Resource pressure by instruction: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] Instructions: @@ -2705,11 +2705,11 @@ vpunpcklwd (%rax), %ymm17, %ymm19 {z}{k1} # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsllw $0, (%rax), %ymm19 {%k1} # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - vpsllw $0, %ymm16, %ymm19 {%k1} {z} # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsllw $0, (%rax), %ymm19 {%k1} {z} -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsllw %xmm16, %xmm17, %xmm19 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - vpsllw %xmm16, %xmm17, %xmm19 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsllw (%rax), %xmm17, %xmm19 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsllw %xmm16, %xmm17, %xmm19 {%k1} +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - vpsllw %xmm16, %xmm17, %xmm19 {%k1} # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsllw (%rax), %xmm17, %xmm19 {%k1} -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsllw %xmm16, %xmm17, %xmm19 {%k1} {z} +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - vpsllw %xmm16, %xmm17, %xmm19 {%k1} {z} # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsllw (%rax), %xmm17, %xmm19 {%k1} {z} # CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsllw %xmm16, %ymm17, %ymm19 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsllw (%rax), %ymm17, %ymm19 @@ -2741,11 +2741,11 @@ vpunpcklwd (%rax), %ymm17, %ymm19 {z}{k1} # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsraw $0, (%rax), %ymm19 {%k1} # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - vpsraw $0, %ymm16, %ymm19 {%k1} {z} # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsraw $0, (%rax), %ymm19 {%k1} {z} -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsraw %xmm16, %xmm17, %xmm19 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - vpsraw %xmm16, %xmm17, %xmm19 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsraw (%rax), %xmm17, %xmm19 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsraw %xmm16, %xmm17, %xmm19 {%k1} +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - vpsraw %xmm16, %xmm17, %xmm19 {%k1} # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsraw (%rax), %xmm17, %xmm19 {%k1} -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsraw %xmm16, %xmm17, %xmm19 {%k1} {z} +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - vpsraw %xmm16, %xmm17, %xmm19 {%k1} {z} # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsraw (%rax), %xmm17, %xmm19 {%k1} {z} # CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsraw %xmm16, %ymm17, %ymm19 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsraw (%rax), %ymm17, %ymm19 @@ -2781,11 +2781,11 @@ vpunpcklwd (%rax), %ymm17, %ymm19 {z}{k1} # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsrlw $0, (%rax), %ymm19 {%k1} # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - vpsrlw $0, %ymm16, %ymm19 {%k1} {z} # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsrlw $0, (%rax), %ymm19 {%k1} {z} -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsrlw %xmm16, %xmm17, %xmm19 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - vpsrlw %xmm16, %xmm17, %xmm19 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsrlw (%rax), %xmm17, %xmm19 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsrlw %xmm16, %xmm17, %xmm19 {%k1} +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - vpsrlw %xmm16, %xmm17, %xmm19 {%k1} # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsrlw (%rax), %xmm17, %xmm19 {%k1} -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsrlw %xmm16, %xmm17, %xmm19 {%k1} {z} +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - vpsrlw %xmm16, %xmm17, %xmm19 {%k1} {z} # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsrlw (%rax), %xmm17, %xmm19 {%k1} {z} # CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - vpsrlw %xmm16, %ymm17, %ymm19 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - vpsrlw (%rax), %ymm17, %ymm19 diff --git a/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-sse2.s b/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-sse2.s index a4a51280b8ca94e0a7a2672b69e3db4fcd6615cc..a1bf6c1e9862021367d03de437f7a6c11c6086cf 100644 --- a/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-sse2.s +++ b/llvm/test/tools/llvm-mca/X86/IceLakeServer/resources-sse2.s @@ -595,30 +595,30 @@ xorpd (%rax), %xmm2 # CHECK-NEXT: 1 1 0.50 pshuflw $1, %xmm0, %xmm2 # CHECK-NEXT: 2 7 0.50 * pshuflw $1, (%rax), %xmm2 # CHECK-NEXT: 1 1 0.50 pslld $1, %xmm2 -# CHECK-NEXT: 2 2 1.00 pslld %xmm0, %xmm2 +# CHECK-NEXT: 2 2 0.67 pslld %xmm0, %xmm2 # CHECK-NEXT: 2 7 0.50 * pslld (%rax), %xmm2 # CHECK-NEXT: 1 1 0.50 pslldq $1, %xmm2 # CHECK-NEXT: 1 1 0.50 psllq $1, %xmm2 -# CHECK-NEXT: 2 2 1.00 psllq %xmm0, %xmm2 +# CHECK-NEXT: 2 2 0.67 psllq %xmm0, %xmm2 # CHECK-NEXT: 2 7 0.50 * psllq (%rax), %xmm2 # CHECK-NEXT: 1 1 0.50 psllw $1, %xmm2 -# CHECK-NEXT: 2 2 1.00 psllw %xmm0, %xmm2 +# CHECK-NEXT: 2 2 0.67 psllw %xmm0, %xmm2 # CHECK-NEXT: 2 7 0.50 * psllw (%rax), %xmm2 # CHECK-NEXT: 1 1 0.50 psrad $1, %xmm2 -# CHECK-NEXT: 2 2 1.00 psrad %xmm0, %xmm2 +# CHECK-NEXT: 2 2 0.67 psrad %xmm0, %xmm2 # CHECK-NEXT: 2 7 0.50 * psrad (%rax), %xmm2 # CHECK-NEXT: 1 1 0.50 psraw $1, %xmm2 -# CHECK-NEXT: 2 2 1.00 psraw %xmm0, %xmm2 +# CHECK-NEXT: 2 2 0.67 psraw %xmm0, %xmm2 # CHECK-NEXT: 2 7 0.50 * psraw (%rax), %xmm2 # CHECK-NEXT: 1 1 0.50 psrld $1, %xmm2 -# CHECK-NEXT: 2 2 1.00 psrld %xmm0, %xmm2 +# CHECK-NEXT: 2 2 0.67 psrld %xmm0, %xmm2 # CHECK-NEXT: 2 7 0.50 * psrld (%rax), %xmm2 # CHECK-NEXT: 1 1 0.50 psrldq $1, %xmm2 # CHECK-NEXT: 1 1 0.50 psrlq $1, %xmm2 -# CHECK-NEXT: 2 2 1.00 psrlq %xmm0, %xmm2 +# CHECK-NEXT: 2 2 0.67 psrlq %xmm0, %xmm2 # CHECK-NEXT: 2 7 0.50 * psrlq (%rax), %xmm2 # CHECK-NEXT: 1 1 0.50 psrlw $1, %xmm2 -# CHECK-NEXT: 2 2 1.00 psrlw %xmm0, %xmm2 +# CHECK-NEXT: 2 2 0.67 psrlw %xmm0, %xmm2 # CHECK-NEXT: 2 7 0.50 * psrlw (%rax), %xmm2 # CHECK-NEXT: 1 1 0.33 psubb %xmm0, %xmm2 # CHECK-NEXT: 2 7 0.50 * psubb (%rax), %xmm2 @@ -691,7 +691,7 @@ xorpd (%rax), %xmm2 # CHECK: Resource pressure per iteration: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] -# CHECK-NEXT: - 40.00 106.92 98.92 58.50 58.50 7.50 76.42 1.75 8.00 8.00 7.50 +# CHECK-NEXT: - 40.00 106.92 102.92 58.50 58.50 7.50 72.42 1.75 8.00 8.00 7.50 # CHECK: Resource pressure by instruction: # CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] Instructions: @@ -883,30 +883,30 @@ xorpd (%rax), %xmm2 # CHECK-NEXT: - - - 0.50 - - - 0.50 - - - - pshuflw $1, %xmm0, %xmm2 # CHECK-NEXT: - - - 0.50 0.50 0.50 - 0.50 - - - - pshuflw $1, (%rax), %xmm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - pslld $1, %xmm2 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - pslld %xmm0, %xmm2 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - pslld %xmm0, %xmm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - pslld (%rax), %xmm2 # CHECK-NEXT: - - - 0.50 - - - 0.50 - - - - pslldq $1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - psllq $1, %xmm2 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - psllq %xmm0, %xmm2 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - psllq %xmm0, %xmm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - psllq (%rax), %xmm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - psllw $1, %xmm2 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - psllw %xmm0, %xmm2 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - psllw %xmm0, %xmm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - psllw (%rax), %xmm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - psrad $1, %xmm2 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - psrad %xmm0, %xmm2 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - psrad %xmm0, %xmm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - psrad (%rax), %xmm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - psraw $1, %xmm2 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - psraw %xmm0, %xmm2 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - psraw %xmm0, %xmm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - psraw (%rax), %xmm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - psrld $1, %xmm2 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - psrld %xmm0, %xmm2 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - psrld %xmm0, %xmm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - psrld (%rax), %xmm2 # CHECK-NEXT: - - - 0.50 - - - 0.50 - - - - psrldq $1, %xmm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - psrlq $1, %xmm2 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - psrlq %xmm0, %xmm2 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - psrlq %xmm0, %xmm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - psrlq (%rax), %xmm2 # CHECK-NEXT: - - 0.50 0.50 - - - - - - - - psrlw $1, %xmm2 -# CHECK-NEXT: - - 0.50 0.50 - - - 1.00 - - - - psrlw %xmm0, %xmm2 +# CHECK-NEXT: - - 0.50 1.00 - - - 0.50 - - - - psrlw %xmm0, %xmm2 # CHECK-NEXT: - - 0.50 0.50 0.50 0.50 - - - - - - psrlw (%rax), %xmm2 # CHECK-NEXT: - - 0.33 0.33 - - - 0.33 - - - - psubb %xmm0, %xmm2 # CHECK-NEXT: - - 0.33 0.33 0.50 0.50 - 0.33 - - - - psubb (%rax), %xmm2 diff --git a/llvm/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml b/llvm/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml index 67d8435fa486c180fa0db75eb7f5983b97f81da7..e2dfee9163a2b81edaa8c89703c08b4161ffec6b 100644 --- a/llvm/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml +++ b/llvm/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml @@ -43,6 +43,10 @@ Sections: Type: SHT_PROGBITS Flags: [ SHF_GROUP ] Content: '00' + - Name: .debug_alloc + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Content: 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f Symbols: - Type: STT_SECTION Section: .debug_foo diff --git a/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test b/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test index e1ebeed8d4fcb0b8d4cc833649b53dbd592870d4..056ae84ce4915f981828e4b387ea5669fce9b85e 100644 --- a/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test +++ b/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test @@ -12,8 +12,10 @@ # CHECK: Name Type Address Off Size ES Flg Lk Inf Al # COMPRESSED: .debug_foo PROGBITS 0000000000000000 000040 {{.*}} 00 C 0 0 8 # COMPRESSED-NEXT: .notdebug_foo PROGBITS 0000000000000000 {{.*}} 000008 00 0 0 0 +# COMPRESSED: .debug_alloc PROGBITS 0000000000000000 {{.*}} 000040 00 A 0 0 0 # UNCOMPRESSED: .debug_foo PROGBITS 0000000000000000 000040 000008 00 0 0 0 # UNCOMPRESSED-NEXT: .notdebug_foo PROGBITS 0000000000000000 {{.*}} 000008 00 0 0 0 +# UNCOMPRESSED: .debug_alloc PROGBITS 0000000000000000 {{.*}} 000040 00 A 0 0 0 ## Relocations do not change. # CHECK: Relocation section '.rela.debug_foo' at offset {{.*}} contains 2 entries: diff --git a/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zstd.test b/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zstd.test index d763131c4067de374d56f340552ba55e5fddefb2..bde1c2f311d0601be4b1f56ba2dc8b1a631f1e1e 100644 --- a/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zstd.test +++ b/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zstd.test @@ -12,8 +12,10 @@ # CHECK: Name Type Address Off Size ES Flg Lk Inf Al # COMPRESSED: .debug_foo PROGBITS 0000000000000000 000040 {{.*}} 00 C 0 0 8 # COMPRESSED-NEXT: .notdebug_foo PROGBITS 0000000000000000 {{.*}} 000008 00 0 0 0 +# COMPRESSED: .debug_alloc PROGBITS 0000000000000000 {{.*}} 000040 00 A 0 0 0 # DECOMPRESSED: .debug_foo PROGBITS 0000000000000000 000040 000008 00 0 0 0 # DECOMPRESSED-NEXT: .notdebug_foo PROGBITS 0000000000000000 {{.*}} 000008 00 0 0 0 +# DECOMPRESSED: .debug_alloc PROGBITS 0000000000000000 {{.*}} 000040 00 A 0 0 0 ## Relocations do not change. # CHECK: Relocation section '.rela.debug_foo' at offset {{.*}} contains 2 entries: diff --git a/llvm/test/tools/llvm-objcopy/ELF/decompress-sections.test b/llvm/test/tools/llvm-objcopy/ELF/decompress-sections.test new file mode 100644 index 0000000000000000000000000000000000000000..4258ddbe66a3e5f036714bddb603e291044360be --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/ELF/decompress-sections.test @@ -0,0 +1,36 @@ +# REQUIRES: zlib +## Test decompression for different sections. + +# RUN: yaml2obj %s -o %t +# RUN: llvm-objcopy --decompress-debug-sections %t %t.de +# RUN: llvm-readelf -S %t.de | FileCheck %s + +# CHECK: Name Type Address Off Size ES Flg Lk Inf Al +# CHECK: .debug_alloc PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 AC 0 0 0 +# CHECK-NEXT: .debug_nonalloc PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 0 0 1 +# CHECK-NEXT: .debugx PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 0 0 1 +# CHECK-NEXT: nodebug PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 C 0 0 0 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .debug_alloc + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_COMPRESSED ] + Content: 010000000000000040000000000000000100000000000000789cd36280002d3269002f800151 + - Name: .debug_nonalloc + Type: SHT_PROGBITS + Flags: [ SHF_COMPRESSED ] + Content: 010000000000000040000000000000000100000000000000789cd36280002d3269002f800151 + - Name: .debugx + Type: SHT_PROGBITS + Flags: [ SHF_COMPRESSED ] + Content: 010000000000000040000000000000000100000000000000789cd36280002d3269002f800151 + - Name: nodebug + Type: SHT_PROGBITS + Flags: [ SHF_COMPRESSED ] + Content: 010000000000000040000000000000000100000000000000789cd36280002d3269002f800151 diff --git a/llvm/test/tools/llvm-objcopy/ELF/discard-locals-rel.test b/llvm/test/tools/llvm-objcopy/ELF/discard-locals-rel.test index 3658eb376010a6573dffecd825c4c6b34035254d..00bb8fcf18205be4e3cfe5407994133b69c4acd9 100644 --- a/llvm/test/tools/llvm-objcopy/ELF/discard-locals-rel.test +++ b/llvm/test/tools/llvm-objcopy/ELF/discard-locals-rel.test @@ -1,5 +1,5 @@ # RUN: yaml2obj %s -o %t -# RUN: not llvm-objcopy --discard-locals %t %t2 2>&1 | FileCheck %s +# RUN: not llvm-objcopy --discard-locals %t %t2 2>&1 | FileCheck %s -DFILE=%t !ELF FileHeader: @@ -23,4 +23,4 @@ Symbols: Type: STT_FUNC Section: .text -# CHECK: not stripping symbol '.L.rel' because it is named in a relocation +# CHECK: error: '[[FILE]]': not stripping symbol '.L.rel' because it is named in a relocation diff --git a/llvm/test/tools/llvm-objcopy/ELF/skip-symbol.test b/llvm/test/tools/llvm-objcopy/ELF/skip-symbol.test new file mode 100644 index 0000000000000000000000000000000000000000..0f3ab808482ba5ff9c959100241cde05547f7f19 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/ELF/skip-symbol.test @@ -0,0 +1,100 @@ +## This test checks the functionality of options --skip-symbol and --skip-symbols. +# RUN: yaml2obj %s -o %t.o +# RUN: echo 'foo[2-3]' > %t.skip.regex + +## Check --skip-symbol functionality when changing symbol bindings. +# RUN: llvm-objcopy %t.o %t2.o --localize-hidden --skip-symbol=foo3 +# RUN: llvm-readelf -s %t2.o | FileCheck %s --check-prefix=LH-SYM +# LH-SYM-DAG: LOCAL HIDDEN 1 foo1 +# LH-SYM-DAG: LOCAL HIDDEN 1 foo2 +# LH-SYM-DAG: GLOBAL HIDDEN 1 foo3 +# LH-SYM-DAG: LOCAL HIDDEN 1 foo4 +# LH-SYM-DAG: LOCAL HIDDEN 1 foo5 + +## Check --skip-symbols functionality when changing symbol bindings. +# RUN: llvm-objcopy %t.o %t1.o --localize-hidden --skip-symbols=%t.skip.regex --regex +# RUN: llvm-readelf -s %t1.o | FileCheck %s --check-prefix=LH-SYMS +# LH-SYMS-DAG: LOCAL HIDDEN 1 foo1 +# LH-SYMS-DAG: GLOBAL HIDDEN 1 foo2 +# LH-SYMS-DAG: GLOBAL HIDDEN 1 foo3 +# LH-SYMS-DAG: LOCAL HIDDEN 1 foo4 +# LH-SYMS-DAG: LOCAL HIDDEN 1 foo5 + +## Check --skip-symbol functionality when changing symbol names. +# RUN: echo -e "foo1 bar1\nfoo2 bar2" > %t.renames.list +# RUN: llvm-objcopy %t.o %t4.o --redefine-syms=%t.renames.list \ +# RUN: --skip-symbol='fo*' --wildcard +# RUN: llvm-readelf -s %t4.o | FileCheck %s --check-prefix=RS-SYM +# RS-SYM-DAG: foo1 +# RS-SYM-DAG: foo2 +# RS-SYM-DAG: foo3 +# RS-SYM-DAG: foo4 +# RS-SYM-DAG: foo5 + +## Check --skip-symbols functionality when changing symbol names. +# RUN: llvm-objcopy %t.o %t3.o --redefine-syms=%t.renames.list \ +# RUN: --skip-symbols=%t.skip.regex --regex +# RUN: llvm-readelf -s %t3.o | FileCheck %s --check-prefix=RS-SYMS +# RS-SYMS-DAG: bar1 +# RS-SYMS-DAG: foo2 +# RS-SYMS-DAG: foo3 +# RS-SYMS-DAG: foo4 +# RS-SYMS-DAG: foo5 + +## Check the functionality when using skip options multiple times. +# RUN: echo "foo3" > %t.symbol0.list +# RUN: echo "foo4" > %t.symbol1.list +# RUN: llvm-objcopy %t.o %t5.o --set-symbol-visibility='foo*'=internal --wildcard \ +# RUN: --skip-symbol=foo1 --skip-symbol=foo2 \ +# RUN: --skip-symbols=%t.symbol0.list --skip-symbols=%t.symbol1.list +# RUN: llvm-readelf -s %t5.o | FileCheck %s --check-prefix=BOTH +# BOTH-DAG: GLOBAL HIDDEN 1 foo1 +# BOTH-DAG: GLOBAL HIDDEN 1 foo2 +# BOTH-DAG: GLOBAL HIDDEN 1 foo3 +# BOTH-DAG: GLOBAL HIDDEN 1 foo4 +## Only foo5 is not skipped. +# BOTH-DAG: GLOBAL INTERNAL 1 foo5 + +## Check that using an invalid symbol name regex generates an error. +# RUN: echo '*.' > %t.symbols.regex +# RUN: not llvm-objcopy %t.o --skip-symbols=%t.symbols.regex --regex 2>&1 | \ +# RUN: FileCheck %s --check-prefix=SYMBOL +# RUN: not llvm-objcopy %t.o --skip-symbol='*.' --regex 2>&1 | \ +# RUN: FileCheck %s --check-prefix=SYMBOL +# SYMBOL: error: cannot compile regular expression '*.': repetition-operator operand invalid + +## Check passing an invalid filename generates an error. +# RUN: not llvm-objcopy %t.o --skip-symbols=no_file 2>&1 | \ +# RUN: FileCheck %s --check-prefix=FILE -DMSG=%errc_ENOENT +# FILE: error: 'no_file': [[MSG]] + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS +Symbols: + - Name: foo1 + Section: .text + Binding: STB_GLOBAL + Other: [ STV_HIDDEN ] + - Name: foo2 + Section: .text + Binding: STB_GLOBAL + Other: [ STV_HIDDEN ] + - Name: foo3 + Section: .text + Binding: STB_GLOBAL + Other: [ STV_HIDDEN ] + - Name: foo4 + Section: .text + Binding: STB_GLOBAL + Other: [ STV_HIDDEN ] + - Name: foo5 + Section: .text + Binding: STB_GLOBAL + Other: [ STV_HIDDEN ] diff --git a/llvm/test/tools/llvm-objcopy/ELF/strip-reloc-symbol.test b/llvm/test/tools/llvm-objcopy/ELF/strip-reloc-symbol.test index 63c9e122d9a2169c1b2be654fe647f78bb92b081..941dacce2edf2925b892d247adade35c5641d3e9 100644 --- a/llvm/test/tools/llvm-objcopy/ELF/strip-reloc-symbol.test +++ b/llvm/test/tools/llvm-objcopy/ELF/strip-reloc-symbol.test @@ -1,5 +1,5 @@ # RUN: yaml2obj %s -o %t -# RUN: not llvm-objcopy -N foo %t %t2 2>&1 | FileCheck %s +# RUN: not llvm-objcopy -N foo %t %t2 2>&1 | FileCheck %s -DFILE=%t !ELF FileHeader: @@ -28,4 +28,4 @@ Symbols: Value: 0x1000 Size: 8 -# CHECK: not stripping symbol 'foo' because it is named in a relocation +# CHECK: error: '[[FILE]]': not stripping symbol 'foo' because it is named in a relocation diff --git a/llvm/test/tools/llvm-objdump/MachO/AArch64/Inputs/rel-method-lists-arm64.dylib b/llvm/test/tools/llvm-objdump/MachO/AArch64/Inputs/rel-method-lists-arm64.dylib new file mode 100755 index 0000000000000000000000000000000000000000..051e28f33d74949db5b9c3c9a875cf45b7486f48 Binary files /dev/null and b/llvm/test/tools/llvm-objdump/MachO/AArch64/Inputs/rel-method-lists-arm64.dylib differ diff --git a/llvm/test/tools/llvm-objdump/MachO/AArch64/Inputs/rel-method-lists-arm64_32.dylib b/llvm/test/tools/llvm-objdump/MachO/AArch64/Inputs/rel-method-lists-arm64_32.dylib new file mode 100755 index 0000000000000000000000000000000000000000..d3a339057abc349e5959a3a67077f0ae5c5bafe8 Binary files /dev/null and b/llvm/test/tools/llvm-objdump/MachO/AArch64/Inputs/rel-method-lists-arm64_32.dylib differ diff --git a/llvm/test/tools/llvm-objdump/MachO/AArch64/macho-relative-method-lists.test b/llvm/test/tools/llvm-objdump/MachO/AArch64/macho-relative-method-lists.test new file mode 100644 index 0000000000000000000000000000000000000000..b1b96a41a32939a5cca720885a0076421c5a67c7 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/MachO/AArch64/macho-relative-method-lists.test @@ -0,0 +1,86 @@ +RUN: llvm-objdump --macho --objc-meta-data %p/Inputs/rel-method-lists-arm64_32.dylib | FileCheck %s --check-prefix=CHK32 +RUN: llvm-otool -ov %p/Inputs/rel-method-lists-arm64_32.dylib | FileCheck %s --check-prefix=CHK32 + +RUN: llvm-objdump --macho --objc-meta-data %p/Inputs/rel-method-lists-arm64.dylib | FileCheck %s --check-prefix=CHK64 +RUN: llvm-otool -ov %p/Inputs/rel-method-lists-arm64.dylib | FileCheck %s --check-prefix=CHK64 + +CHK32: baseMethods 0x660 (struct method_list_t *) +CHK32-NEXT: entsize 12 (relative) +CHK32-NEXT: count 3 +CHK32-NEXT: name 0x144 (0x{{[0-9a-f]*}}) instance_method_00 +CHK32-NEXT: types 0x91 (0x{{[0-9a-f]*}}) v8@0:4 +CHK32-NEXT: imp 0xffffff18 (0x{{[0-9a-f]*}}) -[MyClass instance_method_00] +CHK32-NEXT: name 0x13c (0x{{[0-9a-f]*}}) instance_method_01 +CHK32-NEXT: types 0x85 (0x{{[0-9a-f]*}}) v8@0:4 +CHK32-NEXT: imp 0xffffff28 (0x{{[0-9a-f]*}}) -[MyClass instance_method_01] +CHK32-NEXT: name 0x134 (0x{{[0-9a-f]*}}) instance_method_02 +CHK32-NEXT: types 0x79 (0x{{[0-9a-f]*}}) v8@0:4 +CHK32-NEXT: imp 0xffffff38 (0x{{[0-9a-f]*}}) -[MyClass instance_method_02] + +CHK32: baseMethods 0x630 (struct method_list_t *) +CHK32-NEXT: entsize 12 (relative) +CHK32-NEXT: count 3 +CHK32-NEXT: name 0x180 (0x{{[0-9a-f]*}}) class_method_00 +CHK32-NEXT: types 0xc1 (0x{{[0-9a-f]*}}) v8@0:4 +CHK32-NEXT: imp 0xffffff9c (0x{{[0-9a-f]*}}) +[MyClass class_method_00] +CHK32-NEXT: name 0x178 (0x{{[0-9a-f]*}}) class_method_01 +CHK32-NEXT: types 0xb5 (0x{{[0-9a-f]*}}) v8@0:4 +CHK32-NEXT: imp 0xffffffac (0x{{[0-9a-f]*}}) +[MyClass class_method_01] +CHK32-NEXT: name 0x170 (0x{{[0-9a-f]*}}) class_method_02 +CHK32-NEXT: types 0xa9 (0x{{[0-9a-f]*}}) v8@0:4 +CHK32-NEXT: imp 0xffffffbc (0x{{[0-9a-f]*}}) +[MyClass class_method_02] + +CHK64: baseMethods 0x6e0 (struct method_list_t *) +CHK64-NEXT: entsize 12 (relative) +CHK64-NEXT: count 3 +CHK64-NEXT: name 0x188 (0x{{[0-9a-f]*}}) instance_method_00 +CHK64-NEXT: types 0x91 (0x{{[0-9a-f]*}}) v16@0:8 +CHK64-NEXT: imp 0xffffffa8 (0x{{[0-9a-f]*}}) -[MyClass instance_method_00] +CHK64-NEXT: name 0x184 (0x{{[0-9a-f]*}}) instance_method_01 +CHK64-NEXT: types 0x85 (0x{{[0-9a-f]*}}) v16@0:8 +CHK64-NEXT: imp 0xffffffa0 (0x{{[0-9a-f]*}}) -[MyClass instance_method_01] +CHK64-NEXT: name 0x180 (0x{{[0-9a-f]*}}) instance_method_02 +CHK64-NEXT: types 0x79 (0x{{[0-9a-f]*}}) v16@0:8 +CHK64-NEXT: imp 0xffffff98 (0x{{[0-9a-f]*}}) -[MyClass instance_method_02] + +CHK64: baseMethods 0x6b0 (struct method_list_t *) +CHK64-NEXT: entsize 12 (relative) +CHK64-NEXT: count 3 +CHK64-NEXT: name 0x1d0 (0x{{[0-9a-f]*}}) class_method_00 +CHK64-NEXT: types 0xc1 (0x{{[0-9a-f]*}}) v16@0:8 +CHK64-NEXT: imp 0xffffffe4 (0x{{[0-9a-f]*}}) +[MyClass class_method_00] +CHK64-NEXT: name 0x1cc (0x{{[0-9a-f]*}}) class_method_01 +CHK64-NEXT: types 0xb5 (0x{{[0-9a-f]*}}) v16@0:8 +CHK64-NEXT: imp 0xffffffdc (0x{{[0-9a-f]*}}) +[MyClass class_method_01] +CHK64-NEXT: name 0x1c8 (0x{{[0-9a-f]*}}) class_method_02 +CHK64-NEXT: types 0xa9 (0x{{[0-9a-f]*}}) v16@0:8 +CHK64-NEXT: imp 0xffffffd4 (0x{{[0-9a-f]*}}) +[MyClass class_method_02] + +######## Generate rel-method-lists-arm64.dylib ######## +// clang -c main.mm -o main.o -target arm64-apple-macos -arch arm64 +// ld64.ld64 -dylib -demangle -dynamic main.o -o rel-method-lists-arm64.dylib -syslibroot MacOSX14.2.sdk -segalign 0x10 -objc_relative_method_lists + +######## Generate rel-method-lists-arm64_32.dylib ######## +// clang -c main.mm -o main.o -target arm64_32-apple-watchos -arch arm64_32 +// ld64.ld64 -dylib -demangle -dynamic main.o -o rel-method-lists-arm64_32.dylib -syslibroot WatchOS.sdk -segalign 0x10 -objc_relative_method_lists + +// ~~~~~~~~~~~~~~~~~~~~~~~~~ main.mm ~~~~~~~~~~~~~~~~~~~~~~~~~ +__attribute__((objc_root_class)) +@interface MyClass +- (void)instance_method_00; +- (void)instance_method_01; +- (void)instance_method_02; ++ (void)class_method_00; ++ (void)class_method_01; ++ (void)class_method_02; +@end +@implementation MyClass +- (void)instance_method_00 {} +- (void)instance_method_01 {} +- (void)instance_method_02 {} ++ (void)class_method_00 {} ++ (void)class_method_01 {} ++ (void)class_method_02 {} +@end +void *_objc_empty_cache; +void *_objc_empty_vtable; diff --git a/llvm/test/tools/llvm-profdata/Inputs/vtable-value-prof.proftext b/llvm/test/tools/llvm-profdata/Inputs/vtable-value-prof.proftext new file mode 100644 index 0000000000000000000000000000000000000000..372f9f97b164547389a0cc736901c15ca2b722c4 --- /dev/null +++ b/llvm/test/tools/llvm-profdata/Inputs/vtable-value-prof.proftext @@ -0,0 +1,74 @@ +# IR level Instrumentation Flag +:ir +_Z10createTypei +# Func Hash: +146835647075900052 +# Num Counters: +2 +# Counter Values: +750 +250 + +_ZN8Derived15func1Eii +# Func Hash: +742261418966908927 +# Num Counters: +1 +# Counter Values: +250 + +_ZN8Derived15func2Eii +# Func Hash: +742261418966908927 +# Num Counters: +1 +# Counter Values: +250 + +main +# Func Hash: +1124236338992350536 +# Num Counters: +2 +# Counter Values: +1000 +1 +# Num Value Kinds: +2 +# ValueKind = IPVK_IndirectCallTarget: +0 +# NumValueSites: +2 +2 +vtable_prof.cc;_ZN12_GLOBAL__N_18Derived25func1Eii:750 +_ZN8Derived15func1Eii:250 +2 +vtable_prof.cc;_ZN12_GLOBAL__N_18Derived25func2Eii:750 +_ZN8Derived15func2Eii:250 +# ValueKind = IPVK_VTableTarget: +2 +# NumValueSites: +2 +2 +vtable_prof.cc;_ZTVN12_GLOBAL__N_18Derived2E:750 +_ZTV8Derived1:250 +2 +vtable_prof.cc;_ZTVN12_GLOBAL__N_18Derived2E:750 +_ZTV8Derived1:250 + +vtable_prof.cc;_ZN12_GLOBAL__N_18Derived25func1Eii +# Func Hash: +742261418966908927 +# Num Counters: +1 +# Counter Values: +750 + +vtable_prof.cc;_ZN12_GLOBAL__N_18Derived25func2Eii +# Func Hash: +742261418966908927 +# Num Counters: +1 +# Counter Values: +750 + diff --git a/llvm/test/tools/llvm-profdata/vtable-value-prof.test b/llvm/test/tools/llvm-profdata/vtable-value-prof.test new file mode 100644 index 0000000000000000000000000000000000000000..378c2e11b236bafca85d113396cc7dadd90e3670 --- /dev/null +++ b/llvm/test/tools/llvm-profdata/vtable-value-prof.test @@ -0,0 +1,83 @@ +; RUN: rm -rf %t && mkdir %t && cd %t + +; Generate indexed profiles from text profiles +RUN: llvm-profdata merge %S/Inputs/vtable-value-prof.proftext -o indexed.profdata + +; Show indexed profiles +RUN: llvm-profdata show --function=main --ic-targets --show-vtables indexed.profdata | FileCheck %s --check-prefix=INDEXED + +; Show text profiles +RUN: llvm-profdata show --function=main --ic-targets --show-vtables --text %S/Inputs/vtable-value-prof.proftext | FileCheck %s --check-prefix=ICTEXT + +; Convert indexed profiles to its textual output and show it. +RUN: llvm-profdata merge --text -o text-from-indexed.proftext indexed.profdata +RUN: llvm-profdata show --function=main --ic-targets --show-vtables text-from-indexed.proftext | FileCheck %s --check-prefix=INDEXED +RUN: llvm-profdata show --function=main --ic-targets --show-vtables --text text-from-indexed.proftext | FileCheck %s --check-prefix=ICTEXT + +INDEXED: Counters: +INDEXED-NEXT: main: +INDEXED-NEXT: Hash: 0x0f9a16fe6d398548 +INDEXED-NEXT: Counters: 2 +INDEXED-NEXT: Indirect Call Site Count: 2 +INDEXED-NEXT: Number of instrumented vtables: 2 +INDEXED-NEXT: Indirect Target Results: +INDEXED-NEXT: [ 0, {{.*}}vtable_prof.cc;_ZN12_GLOBAL__N_18Derived25func1Eii, 750 ] (75.00%) +INDEXED-NEXT: [ 0, _ZN8Derived15func1Eii, 250 ] (25.00%) +INDEXED-NEXT: [ 1, {{.*}}vtable_prof.cc;_ZN12_GLOBAL__N_18Derived25func2Eii, 750 ] (75.00%) +INDEXED-NEXT: [ 1, _ZN8Derived15func2Eii, 250 ] (25.00%) +INDEXED-NEXT: VTable Results: +INDEXED-NEXT: [ 0, {{.*}}vtable_prof.cc;_ZTVN12_GLOBAL__N_18Derived2E, 750 ] (75.00%) +INDEXED-NEXT: [ 0, _ZTV8Derived1, 250 ] (25.00%) +INDEXED-NEXT: [ 1, {{.*}}vtable_prof.cc;_ZTVN12_GLOBAL__N_18Derived2E, 750 ] (75.00%) +INDEXED-NEXT: [ 1, _ZTV8Derived1, 250 ] (25.00%) +INDEXED-NEXT: Instrumentation level: IR entry_first = 0 +INDEXED-NEXT: Functions shown: 1 +INDEXED-NEXT: Total functions: 6 +INDEXED-NEXT: Maximum function count: 1000 +INDEXED-NEXT: Maximum internal block count: 250 +INDEXED-NEXT: Statistics for indirect call sites profile: +INDEXED-NEXT: Total number of sites: 2 +INDEXED-NEXT: Total number of sites with values: 2 +INDEXED-NEXT: Total number of profiled values: 4 +INDEXED-NEXT: Value sites histogram: +INDEXED-NEXT: NumTargets, SiteCount +INDEXED-NEXT: 2, 2 +INDEXED-NEXT: Statistics for vtable profile: +INDEXED-NEXT: Total number of sites: 2 +INDEXED-NEXT: Total number of sites with values: 2 +INDEXED-NEXT: Total number of profiled values: 4 +INDEXED-NEXT: Value sites histogram: +INDEXED-NEXT: NumTargets, SiteCount +INDEXED-NEXT: 2, 2 + +ICTEXT: :ir +ICTEXT: main +ICTEXT: # Func Hash: +ICTEXT: 1124236338992350536 +ICTEXT: # Num Counters: +ICTEXT: 2 +ICTEXT: # Counter Values: +ICTEXT: 1000 +ICTEXT: 1 +ICTEXT: # Num Value Kinds: +ICTEXT: 2 +ICTEXT: # ValueKind = IPVK_IndirectCallTarget: +ICTEXT: 0 +ICTEXT: # NumValueSites: +ICTEXT: 2 +ICTEXT: 2 +ICTEXT: {{.*}}vtable_prof.cc;_ZN12_GLOBAL__N_18Derived25func1Eii:750 +ICTEXT: _ZN8Derived15func1Eii:250 +ICTEXT: 2 +ICTEXT: {{.*}}vtable_prof.cc;_ZN12_GLOBAL__N_18Derived25func2Eii:750 +ICTEXT: _ZN8Derived15func2Eii:250 +ICTEXT: # ValueKind = IPVK_VTableTarget: +ICTEXT: 2 +ICTEXT: # NumValueSites: +ICTEXT: 2 +ICTEXT: 2 +ICTEXT: {{.*}}vtable_prof.cc;_ZTVN12_GLOBAL__N_18Derived2E:750 +ICTEXT: _ZTV8Derived1:250 +ICTEXT: 2 +ICTEXT: {{.*}}vtable_prof.cc;_ZTVN12_GLOBAL__N_18Derived2E:750 +ICTEXT: _ZTV8Derived1:250 diff --git a/llvm/test/tools/llvm-profgen/Inputs/coff-profile.exe b/llvm/test/tools/llvm-profgen/Inputs/coff-profile.exe new file mode 100644 index 0000000000000000000000000000000000000000..309476a2437f04d9c76312bfea0d51ee760719e2 Binary files /dev/null and b/llvm/test/tools/llvm-profgen/Inputs/coff-profile.exe differ diff --git a/llvm/test/tools/llvm-profgen/Inputs/coff-profile.perfscript b/llvm/test/tools/llvm-profgen/Inputs/coff-profile.perfscript new file mode 100644 index 0000000000000000000000000000000000000000..96eb878c31667cb3b71ed279887b6b849866a65e --- /dev/null +++ b/llvm/test/tools/llvm-profgen/Inputs/coff-profile.perfscript @@ -0,0 +1,13 @@ +PERF_RECORD_MMAP2 5752/0: [0x7ff70a1b0000(0x640000) @ 0x1000 00:00 0 0]: r-xp c:\Users\haohaiwe\Desktop\coff-profile.exe + 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 + 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/-/X/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/-/X/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/-/X/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 + 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/-/X/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 + 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/-/X/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/-/X/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/-/X/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 + 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/-/X/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/-/X/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/-/X/A/0 + 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 + 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 + 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/-/X/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/-/X/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/-/X/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/-/X/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/-/X/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 + 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/-/X/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 + 0x7ff70a1b1415/0x7ff70a1b13b0/P/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/M/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/P/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/P/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/M/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/P/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/P/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/M/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/P/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/M/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/M/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/P/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/M/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/M/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/P/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/P/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/M/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/P/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/M/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/M/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/P/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/M/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/M/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/P/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/P/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/M/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/P/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/M/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/M/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/P/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/P/X/A/0 0x7ff70a1b1415/0x7ff70a1b13b0/M/X/A/0 + 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/-/X/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/-/X/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 + 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 0x7ff70a1b1482/0x7ff70a1b1430/P/-/A/0 diff --git a/llvm/test/tools/llvm-profgen/coff-profile.test b/llvm/test/tools/llvm-profgen/coff-profile.test new file mode 100644 index 0000000000000000000000000000000000000000..5578f731cac8307480e0a2a5ff56c4595f2bbd3d --- /dev/null +++ b/llvm/test/tools/llvm-profgen/coff-profile.test @@ -0,0 +1,79 @@ +; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/coff-profile.perfscript --binary=%S/Inputs/coff-profile.exe --output=%t +; RUN: FileCheck %s --input-file %t + +CHECK: main:31837:0 +CHECK-NEXT: 0: 0 +CHECK-NEXT: 3.1: 0 +CHECK-NEXT: 3.2: 0 +CHECK-NEXT: 8: 0 +CHECK-NEXT: 65501: 0 +CHECK-NEXT: 1: ??$init@HG@MyNameSpace2@@YAXHPEAG@Z:0 +CHECK-NEXT: 1: 0 +CHECK-NEXT: 1.1: 0 +CHECK-NEXT: 1.2: 0 +CHECK-NEXT: 2: 0 +CHECK-NEXT: 65514: 0 +CHECK-NEXT: 4: ?work1@?$MyClass@GH@MyNameSpace1@@QEAAXQEAGH@Z:3193 +CHECK-NEXT: 0: ?work@?$MyClass@GH@MyNameSpace1@@AEAAXQEAGHH@Z:3193 +CHECK-NEXT: 1.1: 31 +CHECK-NEXT: 1.2: 31 +CHECK-NEXT: 2: 31 +CHECK-NEXT: 3: 31 +CHECK-NEXT: 65530: 0 +CHECK-NEXT: 5: ?work2@?$MyClass@GH@MyNameSpace1@@QEAAXQEAGH@Z:28644 +CHECK-NEXT: 0: ?work@?$MyClass@GH@MyNameSpace1@@AEAAXQEAGHH@Z:28644 +CHECK-NEXT: 1.1: 341 +CHECK-NEXT: 1.2: 341 +CHECK-NEXT: 2: 341 +CHECK-NEXT: 3: 341 +CHECK-NEXT: 65530: 0 +CHECK-NEXT: 7: ?print@MyNameSpace2@@YAXPEAGH@Z:0 +CHECK-NEXT: 1: 0 + +; Original code +; clang-cl.exe -O2 -gdwarf -gline-tables-only coff-profile.cpp -fuse-ld=lld -Xclang -fdebug-info-for-profiling -link -debug:dwarf + +#include <stdio.h> + +namespace MyNameSpace1 { + +template <typename T1, typename T2> class MyClass { + void work(T1 map[], T2 n, T2 m) { + for (int i = 1; i < n; i++) { + map[i] = map[i - 1] * map[i - 1]; + map[i] += (i * map[i - 1]) / m + i % m; + } + } + +public: + void work1(T1 map[], T2 n) { work(map, n, 7); } + void work2(T1 map[], T2 n) { work(map, n, 3); } +}; + +} // namespace MyNameSpace1 + +namespace MyNameSpace2 { + +template <typename T1, typename T2> void init(T1 c, T2 *p) { + for (int i = 0; i < c * 1000000; i++) { + p[i] = i / 3 + (i * i) % 3; + } +} + +void print(unsigned short *p, int i) { + printf("%d %d %d\n", p[i * i * 100], p[i * i * 100 + 1], p[i * i * 100 + 2]); +} + +} // namespace MyNameSpace2 + +unsigned short M[3000000]; +int main(int argc, char *argv[]) { + MyNameSpace2::init(argc, M); + MyNameSpace1::MyClass<unsigned short, int> Obj; + for (int i = 0; i <= argc * 10; i++) { + Obj.work1(&M[argc], argc * 100000); + Obj.work2(&M[argc * argc], argc * 1000000); + } + MyNameSpace2::print(M, argc); + return 0; +} diff --git a/llvm/test/tools/llvm-readobj/ELF/decompress-zlib-unsupported.test b/llvm/test/tools/llvm-readobj/ELF/decompress-zlib-unsupported.test index f4c73de7ca6c9d73737020b143668dc7ef65b075..083c296b8cc13778871ffdf7c18453e3d41c65d3 100644 --- a/llvm/test/tools/llvm-readobj/ELF/decompress-zlib-unsupported.test +++ b/llvm/test/tools/llvm-readobj/ELF/decompress-zlib-unsupported.test @@ -10,6 +10,7 @@ # CHECK-NEXT: [ 18] x.c. # CHECK-NEXT: [ 1e] . # CHECK-NEXT: [ 20] . +# CHECK-EMPTY: # CHECK-NEXT: Hex dump of section '.b': # CHECK-NEXT: warning: '[[FILE]]': LLVM was not built with LLVM_ENABLE_ZLIB or did not find zlib at build time # CHECK-NEXT: 0x00000000 01000000 00000000 01000000 00000000 ................ diff --git a/llvm/test/tools/llvm-readobj/ELF/decompress-zlib.test b/llvm/test/tools/llvm-readobj/ELF/decompress-zlib.test index ea7a8854eb1a0cad328b6f1395036b4aa24cb158..c1d12a6d560ec8f4e0947fe57c42b0fc359f501b 100644 --- a/llvm/test/tools/llvm-readobj/ELF/decompress-zlib.test +++ b/llvm/test/tools/llvm-readobj/ELF/decompress-zlib.test @@ -28,6 +28,7 @@ # COMPRESSED: String dump of section '.not_null_terminated': # COMPRESSED-NEXT: [ 0] no # COMPRESSED-NEXT: [ 3] null +# COMPRESSED-EMPTY: # COMPRESSED-NEXT: Hex dump of section '.strings': # COMPRESSED-NEXT: 0x00000000 01000000 00000000 16000000 00000000 ................ # COMPRESSED-NEXT: 0x00000010 00000000 00000000 789ccb48 2d4a6548 ........x..H-JeH @@ -39,6 +40,7 @@ # INVALID: String dump of section '.invalid1': # INVALID-NEXT: warning: '[[FILE]]': corrupted compressed section header # INVALID-NEXT: [ 0] . +# INVALID-EMPTY: # INVALID-NEXT: Hex dump of section '.invalid2': # INVALID-NEXT: warning: '[[FILE]]': zlib error: Z_DATA_ERROR # INVALID-NEXT: 0x00000000 01000000 00000000 16000000 00000000 ................ diff --git a/llvm/test/tools/llvm-readobj/ELF/decompress-zstd-unsupported.test b/llvm/test/tools/llvm-readobj/ELF/decompress-zstd-unsupported.test index 65da952687f526d1ad43d75004cdc87923a59059..98c7cb002769ae7f358639f738993f9efac3b67e 100644 --- a/llvm/test/tools/llvm-readobj/ELF/decompress-zstd-unsupported.test +++ b/llvm/test/tools/llvm-readobj/ELF/decompress-zstd-unsupported.test @@ -9,6 +9,7 @@ # CHECK-NEXT: [ 10] . # CHECK-NEXT: [ 18] (./. .. # CHECK-NEXT: [ 21] . +# CHECK-EMPTY: # CHECK-NEXT: Hex dump of section '.b': # CHECK-NEXT: warning: '[[FILE]]': LLVM was not built with LLVM_ENABLE_ZSTD or did not find zstd at build time # CHECK-NEXT: 0x00000000 02000000 00000000 01000000 00000000 ................ diff --git a/llvm/test/tools/llvm-readobj/ELF/hex-dump-multi.s b/llvm/test/tools/llvm-readobj/ELF/hex-dump-multi.s index 33ef534e81e13842ef23ba4af985ff2c6c7b4e26..942bfc4b7fb026ddd4f36ff554b630003a33a301 100644 --- a/llvm/test/tools/llvm-readobj/ELF/hex-dump-multi.s +++ b/llvm/test/tools/llvm-readobj/ELF/hex-dump-multi.s @@ -1,10 +1,12 @@ # REQUIRES: x86-registered-target # RUN: llvm-mc -filetype=obj -triple x86_64 %s -o %t.o -# RUN: llvm-readobj -x .a -x .b %t.o | FileCheck %s +# RUN: llvm-readobj -x .a -x .b %t.o | FileCheck %s --check-prefixes=HEADER,CHECK # RUN: llvm-readelf -x .a -x .b %t.o | FileCheck %s -# CHECK: Hex dump of section '.a': +# HEADER: LoadName: +# CHECK: {{^$}} +# CHECK-NEXT: Hex dump of section '.a': # CHECK-NEXT: 0x00000000 00 # CHECK-EMPTY: # CHECK-NEXT: Hex dump of section '.b': diff --git a/llvm/test/tools/llvm-readobj/ELF/hex-dump.test b/llvm/test/tools/llvm-readobj/ELF/hex-dump.test index 7829944806f34f49eab45ad7ca9065cd2d1b95d9..71212dee5e07a7107f2e1581fe49181df791689d 100644 --- a/llvm/test/tools/llvm-readobj/ELF/hex-dump.test +++ b/llvm/test/tools/llvm-readobj/ELF/hex-dump.test @@ -46,7 +46,8 @@ FileHeader: # RUN: llvm-readelf --hex-dump=.sec %t2.out1 | \ # RUN: FileCheck %s --match-full-lines --strict-whitespace --check-prefix=SPACES1 -# SPACES1:Hex dump of section '.sec': +# SPACES1:{{^$}} +# SPACES1-NEXT:Hex dump of section '.sec': # SPACES1-NEXT:0x00000000 00000000 00000000 00000000 00000000 ................ # SPACES1-NEXT:0x00000010 0000 .. @@ -55,7 +56,8 @@ FileHeader: # RUN: llvm-readelf --hex-dump=.sec %t2.out2 | \ # RUN: FileCheck %s --match-full-lines --strict-whitespace --check-prefix=SPACES2 -# SPACES2:Hex dump of section '.sec': +# SPACES2:{{^$}} +# SPACES2-NEXT:Hex dump of section '.sec': # SPACES2-NEXT:0x00000000 00000000 00000000 00000000 00000000 ................ # SPACES2-NEXT:0x00000010 00000000 00000000 00000000 0000 .............. @@ -64,7 +66,8 @@ FileHeader: # RUN: llvm-readelf --hex-dump=.sec %t2.out3 | \ # RUN: FileCheck %s --match-full-lines --strict-whitespace --check-prefix=SPACES3 -# SPACES3:Hex dump of section '.sec': +# SPACES3:{{^$}} +# SPACES3-NEXT:Hex dump of section '.sec': # SPACES3-NEXT:0x00000000 00000000 00000000 00000000 00000000 ................ # SPACES3-NEXT:0x00000010 00000000 00000000 00000000 ............ diff --git a/llvm/test/tools/llvm-readobj/ELF/machine-specific-section-types.test b/llvm/test/tools/llvm-readobj/ELF/machine-specific-section-types.test index f9524383e80b6dbec626ee451aca6a49c9d7f472..f65793c5bdc62d1c52878f3af7d1a4e38c82f1cd 100644 --- a/llvm/test/tools/llvm-readobj/ELF/machine-specific-section-types.test +++ b/llvm/test/tools/llvm-readobj/ELF/machine-specific-section-types.test @@ -17,6 +17,10 @@ # RUN: llvm-readobj --section-headers %t-aarch64.o | FileCheck %s --check-prefix=AARCH64-LLVM # RUN: llvm-readelf --section-headers %t-aarch64.o | FileCheck %s --check-prefix=AARCH64-GNU +# RUN: yaml2obj %s --docnum=5 -o %t-hexagon.o +# RUN: llvm-readobj --section-headers %t-hexagon.o | FileCheck %s --check-prefix=HEXAGON-LLVM +# RUN: llvm-readelf --section-headers %t-hexagon.o | FileCheck %s --check-prefix=HEXAGON-GNU + # ARM-LLVM: Name: exidx # ARM-LLVM: Type: SHT_ARM_EXIDX # ARM-LLVM: Name: preemptmap @@ -64,6 +68,13 @@ # AARCH64-GNU: .memtag.globals.dynamic AARCH64_MEMTAG_GLOBALS_DYNAMIC # AARCH64-GNU: .memtag.globals.static AARCH64_MEMTAG_GLOBALS_STATIC +# HEXAGON-LLVM: Name: hexagon_ordered +# HEXAGON-LLVM: Type: SHT_HEX_ORDERED +# HEXAGON-LLVM: Name: .hexagon.attributes +# HEXAGON-LLVM: Type: SHT_HEXAGON_ATTRIBUTES + +# HEXAGON-GNU: hexagon_ordered HEX_ORDERED + --- !ELF FileHeader: Class: ELFCLASS64 @@ -122,3 +133,15 @@ Sections: Type: SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC - Name: .memtag.globals.static Type: SHT_AARCH64_MEMTAG_GLOBALS_STATIC + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_HEXAGON +Sections: + - Name: hexagon_ordered + Type: SHT_HEX_ORDERED + - Name: .hexagon.attributes + Type: SHT_HEXAGON_ATTRIBUTES diff --git a/llvm/test/tools/llvm-readobj/ELF/reloc-types-aarch64.test b/llvm/test/tools/llvm-readobj/ELF/reloc-types-aarch64.test index 7291282811048fad225b07130f11750137d302ab..cf95b5170026746305595b9261840f2a4b3b7a38 100644 --- a/llvm/test/tools/llvm-readobj/ELF/reloc-types-aarch64.test +++ b/llvm/test/tools/llvm-readobj/ELF/reloc-types-aarch64.test @@ -119,6 +119,7 @@ # CHECK: Type: R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC (571) # CHECK: Type: R_AARCH64_TLSLD_LDST128_DTPREL_LO12 (572) # CHECK: Type: R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC (573) +# CHECK: Type: R_AARCH64_AUTH_ABS64 (580) # CHECK: Type: R_AARCH64_COPY (1024) # CHECK: Type: R_AARCH64_GLOB_DAT (1025) # CHECK: Type: R_AARCH64_JUMP_SLOT (1026) @@ -128,6 +129,7 @@ # CHECK: Type: R_AARCH64_TLS_TPREL64 (1030) # CHECK: Type: R_AARCH64_TLSDESC (1031) # CHECK: Type: R_AARCH64_IRELATIVE (1032) +# CHECK: Type: R_AARCH64_AUTH_RELATIVE (1041) --- !ELF FileHeader: @@ -254,6 +256,7 @@ Sections: - Type: R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC - Type: R_AARCH64_TLSLD_LDST128_DTPREL_LO12 - Type: R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC + - Type: R_AARCH64_AUTH_ABS64 - Type: R_AARCH64_COPY - Type: R_AARCH64_GLOB_DAT - Type: R_AARCH64_JUMP_SLOT @@ -263,3 +266,4 @@ Sections: - Type: R_AARCH64_TLS_TPREL64 - Type: R_AARCH64_TLSDESC - Type: R_AARCH64_IRELATIVE + - Type: R_AARCH64_AUTH_RELATIVE diff --git a/llvm/test/tools/llvm-readobj/ELF/string-dump-multi.s b/llvm/test/tools/llvm-readobj/ELF/string-dump-multi.s index 29d7ef011005e55a5e479929ef42a2a00b7b2715..36a115bd259a96f535ba3cce43f964aabc1efa83 100644 --- a/llvm/test/tools/llvm-readobj/ELF/string-dump-multi.s +++ b/llvm/test/tools/llvm-readobj/ELF/string-dump-multi.s @@ -1,10 +1,12 @@ # REQUIRES: x86-registered-target # RUN: llvm-mc -filetype=obj -triple x86_64 %s -o %t.o -# RUN: llvm-readobj -p .a -p .b %t.o | FileCheck %s +# RUN: llvm-readobj -p .a -p .b %t.o | FileCheck %s --check-prefixes=HEADER,CHECK # RUN: llvm-readelf -p .a -p .b %t.o | FileCheck %s -# CHECK: String dump of section '.a': +# HEADER: LoadName: +# CHECK: {{^$}} +# CHECK-NEXT: String dump of section '.a': # CHECK-NEXT: [ 0] 0 # CHECK-EMPTY: # CHECK-NEXT: String dump of section '.b': diff --git a/llvm/test/tools/llvm-readobj/ELF/string-dump.test b/llvm/test/tools/llvm-readobj/ELF/string-dump.test index c06b274d25288ddddafbcad8f9c11e82eab4e8fc..1d7a177b32de12e6af2fc7e56082f444cfc1e809 100644 --- a/llvm/test/tools/llvm-readobj/ELF/string-dump.test +++ b/llvm/test/tools/llvm-readobj/ELF/string-dump.test @@ -3,7 +3,7 @@ # RUN: llvm-readobj --string-dump=.strings \ # RUN: --string-dump=.not_null_terminated %t > %t.readobj.out -# RUN: FileCheck %s --input-file=%t.readobj.out +# RUN: FileCheck %s --input-file=%t.readobj.out --check-prefixes=HEADER,CHECK # Also test the different ways --string-dump can be specified, i.e. as a short # flag (-p), with different prefix modes (-p .foo, -p=.foo, -p.foo), and with @@ -23,7 +23,9 @@ # RUN: llvm-readelf -hp1 -p2 %t | cmp %t.readelf.out - # RUN: llvm-readelf -hp 1 -p.not_null_terminated %t | cmp %t.readelf.out - -# CHECK: String dump of section '.strings': +# HEADER: LoadName: +# CHECK: {{^$}} +# CHECK-NEXT: String dump of section '.strings': # CHECK-NEXT: [ 0] here # CHECK-NEXT: [ 5] are # CHECK-NEXT: [ 9] some diff --git a/llvm/test/tools/llvm-reduce/remove-dp-values.ll b/llvm/test/tools/llvm-reduce/remove-dp-values.ll index 40ff9f32e960d0af4bb8e494c7e22c2185846d06..d137b279f4ea01a91b7d458b5f48f4b25c8ffa19 100644 --- a/llvm/test/tools/llvm-reduce/remove-dp-values.ll +++ b/llvm/test/tools/llvm-reduce/remove-dp-values.ll @@ -1,7 +1,7 @@ ; RUN: llvm-reduce --abort-on-invalid-reduction --test FileCheck --test-arg --check-prefixes=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t --try-experimental-debuginfo-iterators ; RUN: FileCheck --check-prefixes=CHECK-FINAL --input-file=%t %s --implicit-check-not=dbg.value -; Test that we can, in RemoveDIs mode / DPValues mode (where variable location +; Test that we can, in RemoveDIs mode / DbgVariableRecords mode (where variable location ; information isn't an instruction), remove one variable location assignment ; but not another. diff --git a/llvm/tools/CMakeLists.txt b/llvm/tools/CMakeLists.txt index c6116ac81d12b20e9c6f5db3e0631b59a6fb1cb0..cde57367934e4beaa63184082b0be03573e8f897 100644 --- a/llvm/tools/CMakeLists.txt +++ b/llvm/tools/CMakeLists.txt @@ -37,12 +37,13 @@ add_llvm_tool_subdirectory(llvm-profdata) # Projects supported via LLVM_EXTERNAL_*_SOURCE_DIR need to be explicitly # specified. -add_llvm_external_project(clang) add_llvm_external_project(lld) -add_llvm_external_project(lldb) add_llvm_external_project(mlir) -# Flang depends on mlir, so place it afterward +# ClangIR and Flang depend on mlir, lldb and Flang depend on clang, sort them +# accordingly so place them afterwards +add_llvm_external_project(clang) add_llvm_external_project(flang) +add_llvm_external_project(lldb) add_llvm_external_project(bolt) # Automatically add remaining sub-directories containing a 'CMakeLists.txt' diff --git a/llvm/tools/dsymutil/CMakeLists.txt b/llvm/tools/dsymutil/CMakeLists.txt index 53f882e90b4e920bd5994aec7cfc1775ecf4a297..efe28bda68ebf1587e95009fc4875a13a48c2701 100644 --- a/llvm/tools/dsymutil/CMakeLists.txt +++ b/llvm/tools/dsymutil/CMakeLists.txt @@ -32,7 +32,6 @@ add_llvm_tool(dsymutil MachOUtils.cpp Reproducer.cpp RelocationMap.cpp - SymbolMap.cpp DEPENDS intrinsics_gen diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp index 5ae5ecd556adb7c64fbbb008408afcb92b58c64a..677dfc44c54a40ebd7267653162b1aec0b182216 100644 --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp @@ -634,25 +634,19 @@ bool DwarfLinkerForBinary::linkImpl( DebugMap DebugMap(Map.getTriple(), Map.getBinaryPath()); - std::function<StringRef(StringRef)> TranslationLambda = [&](StringRef Input) { - assert(Options.Translator); - return Options.Translator(Input); - }; - std::unique_ptr<Linker> GeneralLinker = Linker::createLinker( [&](const Twine &Error, StringRef Context, const DWARFDie *DIE) { reportError(Error, Context, DIE); }, [&](const Twine &Warning, StringRef Context, const DWARFDie *DIE) { reportWarning(Warning, Context, DIE); - }, - Options.Translator ? TranslationLambda : nullptr); + }); std::unique_ptr<classic::DwarfStreamer> Streamer; if (!Options.NoOutput) { if (Expected<std::unique_ptr<classic::DwarfStreamer>> StreamerOrErr = classic::DwarfStreamer::createStreamer( - Map.getTriple(), ObjectType, OutFile, Options.Translator, + Map.getTriple(), ObjectType, OutFile, [&](const Twine &Warning, StringRef Context, const DWARFDie *DIE) { reportWarning(Warning, Context, DIE); @@ -866,8 +860,8 @@ bool DwarfLinkerForBinary::linkImpl( if (Map.getTriple().isOSDarwin() && !Map.getBinaryPath().empty() && ObjectType == Linker::OutputFileType::Object) return MachOUtils::generateDsymCompanion( - Options.VFS, Map, Options.Translator, - *Streamer->getAsmPrinter().OutStreamer, OutFile, RelocationsToApply); + Options.VFS, Map, *Streamer->getAsmPrinter().OutStreamer, OutFile, + RelocationsToApply); Streamer->finish(); return true; diff --git a/llvm/tools/dsymutil/LinkUtils.h b/llvm/tools/dsymutil/LinkUtils.h index fd9d985097d6e26d4c2f9efaa1347b2084212f24..6aa0b847eebd67793d421eee874e156cd3456ca7 100644 --- a/llvm/tools/dsymutil/LinkUtils.h +++ b/llvm/tools/dsymutil/LinkUtils.h @@ -9,8 +9,6 @@ #ifndef LLVM_TOOLS_DSYMUTIL_LINKOPTIONS_H #define LLVM_TOOLS_DSYMUTIL_LINKOPTIONS_H -#include "SymbolMap.h" - #include "llvm/ADT/Twine.h" #include "llvm/Remarks/RemarkFormat.h" #include "llvm/Support/VirtualFileSystem.h" @@ -87,9 +85,6 @@ struct LinkOptions { /// The Resources directory in the .dSYM bundle. std::optional<std::string> ResourceDir; - /// Symbol map translator. - SymbolMapTranslator Translator; - /// Virtual File System. llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = vfs::getRealFileSystem(); diff --git a/llvm/tools/dsymutil/MachOUtils.cpp b/llvm/tools/dsymutil/MachOUtils.cpp index 3efc1aff82374422d5354b5d623ce9da7277e8a8..8e144d640ed01fa26edcd5828d96fb396349014a 100644 --- a/llvm/tools/dsymutil/MachOUtils.cpp +++ b/llvm/tools/dsymutil/MachOUtils.cpp @@ -373,7 +373,7 @@ static unsigned segmentLoadCommandSize(bool Is64Bit, unsigned NumSections) { // \a OutFile and it must be using a MachObjectWriter object to do so. bool generateDsymCompanion( llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, const DebugMap &DM, - SymbolMapTranslator &Translator, MCStreamer &MS, raw_fd_ostream &OutFile, + MCStreamer &MS, raw_fd_ostream &OutFile, const std::vector<MachOUtils::DwarfRelocationApplicationInfo> &RelocationsToApply) { auto &ObjectStreamer = static_cast<MCObjectStreamer &>(MS); @@ -509,12 +509,9 @@ bool generateDsymCompanion( } SmallString<0> NewSymtab; - std::function<StringRef(StringRef)> TranslationLambda = - Translator ? [&](StringRef Input) { return Translator(Input); } - : static_cast<std::function<StringRef(StringRef)>>(nullptr); // Legacy dsymutil puts an empty string at the start of the line table. // thus we set NonRelocatableStringpool(,PutEmptyString=true) - NonRelocatableStringpool NewStrings(TranslationLambda, true); + NonRelocatableStringpool NewStrings(true); unsigned NListSize = Is64Bit ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); unsigned NumSyms = 0; uint64_t NewStringsSize = 0; diff --git a/llvm/tools/dsymutil/MachOUtils.h b/llvm/tools/dsymutil/MachOUtils.h index 059d9fdd788a66d4d97b9434425d025ca756c364..0229647b00f85c111353ba29ff1c634aaf93aea5 100644 --- a/llvm/tools/dsymutil/MachOUtils.h +++ b/llvm/tools/dsymutil/MachOUtils.h @@ -8,8 +8,6 @@ #ifndef LLVM_TOOLS_DSYMUTIL_MACHOUTILS_H #define LLVM_TOOLS_DSYMUTIL_MACHOUTILS_H -#include "SymbolMap.h" - #include "llvm/ADT/StringRef.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/VirtualFileSystem.h" @@ -59,7 +57,7 @@ bool generateUniversalBinary(SmallVectorImpl<ArchAndFile> &ArchFiles, StringRef SDKPath, bool Fat64 = false); bool generateDsymCompanion( llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, const DebugMap &DM, - SymbolMapTranslator &Translator, MCStreamer &MS, raw_fd_ostream &OutFile, + MCStreamer &MS, raw_fd_ostream &OutFile, const std::vector<MachOUtils::DwarfRelocationApplicationInfo> &RelocationsToApply); diff --git a/llvm/tools/dsymutil/Options.td b/llvm/tools/dsymutil/Options.td index a4e4c6c4cdb9c020ebc7e894ba5daf42e26c6d8a..d8cec0cb2c410d8fadd239d9bc3682da27ad3ff1 100644 --- a/llvm/tools/dsymutil/Options.td +++ b/llvm/tools/dsymutil/Options.td @@ -128,12 +128,6 @@ def object_prefix_map: Separate<["--", "-"], "object-prefix-map">, Group<grp_general>; def: Joined<["--", "-"], "object-prefix-map=">, Alias<object_prefix_map>; -def symbolmap: Separate<["--", "-"], "symbol-map">, - MetaVarName<"<bcsymbolmap>">, - HelpText<"Updates the existing dSYMs inplace using symbol map specified.">, - Group<grp_general>; -def: Joined<["--", "-"], "symbol-map=">, Alias<symbolmap>; - def arch: Separate<["--", "-"], "arch">, MetaVarName<"<arch>">, HelpText<"Link DWARF debug information only for specified CPU architecture" diff --git a/llvm/tools/dsymutil/SymbolMap.cpp b/llvm/tools/dsymutil/SymbolMap.cpp deleted file mode 100644 index c55362e5f77563b1217ea32f4aaa718fdff713f9..0000000000000000000000000000000000000000 --- a/llvm/tools/dsymutil/SymbolMap.cpp +++ /dev/null @@ -1,157 +0,0 @@ -//===- tools/dsymutil/SymbolMap.cpp ---------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "SymbolMap.h" -#include "DebugMap.h" -#include "MachOUtils.h" - -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/WithColor.h" - -#ifdef __APPLE__ -#include <CoreFoundation/CoreFoundation.h> -#include <uuid/uuid.h> -#endif - -namespace llvm { -namespace dsymutil { - -StringRef SymbolMapTranslator::operator()(StringRef Input) { - if (!Input.starts_with("__hidden#") && !Input.starts_with("___hidden#")) - return Input; - - StringRef Line = Input.drop_front(sizeof("__hidden#") - 1); - bool MightNeedUnderscore = Line.consume_front("#"); - - std::size_t LineNumber = std::numeric_limits<std::size_t>::max(); - Line.split('_').first.getAsInteger(10, LineNumber); - if (LineNumber >= UnobfuscatedStrings.size()) { - WithColor::warning() << "reference to a unexisting unobfuscated string " - << Input << ": symbol map mismatch?\n" - << Line << '\n'; - return Input; - } - - const std::string &Translation = UnobfuscatedStrings[LineNumber]; - if (!MightNeedUnderscore || !MangleNames) - return Translation; - - // Objective-C symbols for the MachO symbol table start with a \1. Please see - // `MangleContext::mangleObjCMethodName` in clang. - if (Translation[0] == 1) - return StringRef(Translation).drop_front(); - - // We need permanent storage for the string we are about to create. Just - // append it to the vector containing translations. This should only happen - // during MachO symbol table translation, thus there should be no risk on - // exponential growth. - UnobfuscatedStrings.emplace_back("_" + Translation); - return UnobfuscatedStrings.back(); -} - -SymbolMapTranslator SymbolMapLoader::Load(StringRef InputFile, - const DebugMap &Map) const { - if (SymbolMap.empty()) - return {}; - - std::string SymbolMapPath = SymbolMap; - -#if __APPLE__ - // Look through the UUID Map. - if (sys::fs::is_directory(SymbolMapPath) && !Map.getUUID().empty()) { - uuid_string_t UUIDString; - uuid_unparse_upper((const uint8_t *)Map.getUUID().data(), UUIDString); - - SmallString<256> PlistPath( - sys::path::parent_path(sys::path::parent_path(InputFile))); - sys::path::append(PlistPath, StringRef(UUIDString).str() + ".plist"); - - CFStringRef plistFile = CFStringCreateWithCString( - kCFAllocatorDefault, PlistPath.c_str(), kCFStringEncodingUTF8); - CFURLRef fileURL = CFURLCreateWithFileSystemPath( - kCFAllocatorDefault, plistFile, kCFURLPOSIXPathStyle, false); - CFReadStreamRef resourceData = - CFReadStreamCreateWithFile(kCFAllocatorDefault, fileURL); - if (resourceData) { - CFReadStreamOpen(resourceData); - CFDictionaryRef plist = (CFDictionaryRef)CFPropertyListCreateWithStream( - kCFAllocatorDefault, resourceData, 0, kCFPropertyListImmutable, - nullptr, nullptr); - - if (plist) { - if (CFDictionaryContainsKey(plist, CFSTR("DBGOriginalUUID"))) { - CFStringRef OldUUID = (CFStringRef)CFDictionaryGetValue( - plist, CFSTR("DBGOriginalUUID")); - - StringRef UUID(CFStringGetCStringPtr(OldUUID, kCFStringEncodingUTF8)); - SmallString<256> BCSymbolMapPath(SymbolMapPath); - sys::path::append(BCSymbolMapPath, UUID.str() + ".bcsymbolmap"); - SymbolMapPath = std::string(BCSymbolMapPath); - } - CFRelease(plist); - } - CFReadStreamClose(resourceData); - CFRelease(resourceData); - } - CFRelease(fileURL); - CFRelease(plistFile); - } -#endif - - if (sys::fs::is_directory(SymbolMapPath)) { - SymbolMapPath += (Twine("/") + sys::path::filename(InputFile) + "-" + - MachOUtils::getArchName(Map.getTriple().getArchName()) + - ".bcsymbolmap") - .str(); - } - - auto ErrOrMemBuffer = MemoryBuffer::getFile(SymbolMapPath); - if (auto EC = ErrOrMemBuffer.getError()) { - WithColor::warning() << SymbolMapPath << ": " << EC.message() - << ": not unobfuscating.\n"; - return {}; - } - - std::vector<std::string> UnobfuscatedStrings; - auto &MemBuf = **ErrOrMemBuffer; - StringRef Data(MemBuf.getBufferStart(), - MemBuf.getBufferEnd() - MemBuf.getBufferStart()); - StringRef LHS; - std::tie(LHS, Data) = Data.split('\n'); - bool MangleNames = false; - - // Check version string first. - if (!LHS.starts_with("BCSymbolMap Version:")) { - // Version string not present, warns but try to parse it. - WithColor::warning() << SymbolMapPath - << " is missing version string: assuming 1.0.\n"; - UnobfuscatedStrings.emplace_back(LHS); - } else if (LHS.equals("BCSymbolMap Version: 1.0")) { - MangleNames = true; - } else if (LHS.equals("BCSymbolMap Version: 2.0")) { - MangleNames = false; - } else { - StringRef VersionNum; - std::tie(LHS, VersionNum) = LHS.split(':'); - WithColor::warning() << SymbolMapPath - << " has unsupported symbol map version" << VersionNum - << ": not unobfuscating.\n"; - return {}; - } - - while (!Data.empty()) { - std::tie(LHS, Data) = Data.split('\n'); - UnobfuscatedStrings.emplace_back(LHS); - } - - return SymbolMapTranslator(std::move(UnobfuscatedStrings), MangleNames); -} - -} // namespace dsymutil -} // namespace llvm diff --git a/llvm/tools/dsymutil/SymbolMap.h b/llvm/tools/dsymutil/SymbolMap.h deleted file mode 100644 index 977de31a5a17ace277ff4a51784cdc3049d23e3e..0000000000000000000000000000000000000000 --- a/llvm/tools/dsymutil/SymbolMap.h +++ /dev/null @@ -1,53 +0,0 @@ -//=- tools/dsymutil/SymbolMap.h -----------------------------------*- C++ -*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_DSYMUTIL_SYMBOLMAP_H -#define LLVM_TOOLS_DSYMUTIL_SYMBOLMAP_H - -#include "llvm/ADT/StringRef.h" - -#include <string> -#include <vector> - -namespace llvm { -namespace dsymutil { -class DebugMap; - -/// Callable class to unobfuscate strings based on a BCSymbolMap. -class SymbolMapTranslator { -public: - SymbolMapTranslator() : MangleNames(false) {} - - SymbolMapTranslator(std::vector<std::string> UnobfuscatedStrings, - bool MangleNames) - : UnobfuscatedStrings(std::move(UnobfuscatedStrings)), - MangleNames(MangleNames) {} - - StringRef operator()(StringRef Input); - - operator bool() const { return !UnobfuscatedStrings.empty(); } - -private: - std::vector<std::string> UnobfuscatedStrings; - bool MangleNames; -}; - -/// Class to initialize SymbolMapTranslators from a BCSymbolMap. -class SymbolMapLoader { -public: - SymbolMapLoader(std::string SymbolMap) : SymbolMap(std::move(SymbolMap)) {} - - SymbolMapTranslator Load(StringRef InputFile, const DebugMap &Map) const; - -private: - const std::string SymbolMap; -}; -} // namespace dsymutil -} // namespace llvm - -#endif // LLVM_TOOLS_DSYMUTIL_SYMBOLMAP_H diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp index 25e281c415e75a97575303fc7b9ba3780f326c23..bc968b6387b65379134c5633096424dbda344b8a 100644 --- a/llvm/tools/dsymutil/dsymutil.cpp +++ b/llvm/tools/dsymutil/dsymutil.cpp @@ -108,7 +108,6 @@ struct DsymutilOptions { bool Flat = false; bool InputIsYAMLDebugMap = false; bool ForceKeepFunctionForStatic = false; - std::string SymbolMap; std::string OutputFile; std::string Toolchain; std::string ReproducerPath; @@ -341,12 +340,6 @@ static Expected<DsymutilOptions> getOptions(opt::InputArgList &Args) { return DWARFLinkerType.takeError(); } - if (opt::Arg *SymbolMap = Args.getLastArg(OPT_symbolmap)) - Options.SymbolMap = SymbolMap->getValue(); - - if (Args.hasArg(OPT_symbolmap)) - Options.LinkOpts.Update = true; - if (Expected<std::vector<std::string>> InputFiles = getInputs(Args, Options.LinkOpts.Update)) { Options.InputFiles = std::move(*InputFiles); @@ -560,8 +553,7 @@ getOutputFileName(StringRef InputFile, const DsymutilOptions &Options) { return OutputLocation(Options.OutputFile); // When updating, do in place replacement. - if (Options.OutputFile.empty() && - (Options.LinkOpts.Update || !Options.SymbolMap.empty())) + if (Options.OutputFile.empty() && Options.LinkOpts.Update) return OutputLocation(std::string(InputFile)); // When dumping the debug map, just return an empty output location. This @@ -668,8 +660,6 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) { return EXIT_FAILURE; } - SymbolMapLoader SymMapLoader(Options.SymbolMap); - for (auto &InputFile : Options.InputFiles) { // Dump the symbol table for each input file and requested arch if (Options.DumpStab) { @@ -760,9 +750,6 @@ int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) { if (Options.DumpDebugMap) continue; - if (!Options.SymbolMap.empty()) - Options.LinkOpts.Translator = SymMapLoader.Load(InputFile, *Map); - if (Map->begin() == Map->end()) { std::lock_guard<std::mutex> Guard(ErrorHandlerMutex); WithColor::warning() diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp index 81cb2a21daf1f270eab84a7f5827751292090ce0..294b8531b08f1324a2fbc7493c340d311356a429 100644 --- a/llvm/tools/llvm-ar/llvm-ar.cpp +++ b/llvm/tools/llvm-ar/llvm-ar.cpp @@ -82,6 +82,7 @@ static void printArHelp(StringRef ToolName) { =darwin - darwin =bsd - bsd =bigarchive - big archive (AIX OS) + =coff - coff --plugin=<string> - ignored for compatibility -h --help - display this help and exit --output - the directory to extract archive members to @@ -193,7 +194,7 @@ static SmallVector<const char *, 256> PositionalArgs; static bool MRI; namespace { -enum Format { Default, GNU, BSD, DARWIN, BIGARCHIVE, Unknown }; +enum Format { Default, GNU, COFF, BSD, DARWIN, BIGARCHIVE, Unknown }; } static Format FormatType = Default; @@ -1025,14 +1026,21 @@ static void performWriteOperation(ArchiveOperation Operation, Kind = object::Archive::K_GNU; else if (OldArchive) { Kind = OldArchive->kind(); - if (Kind == object::Archive::K_BSD) { - auto InferredKind = object::Archive::K_BSD; + std::optional<object::Archive::Kind> AltKind; + if (Kind == object::Archive::K_BSD) + AltKind = object::Archive::K_DARWIN; + else if (Kind == object::Archive::K_GNU && !OldArchive->hasSymbolTable()) + // If there is no symbol table, we can't tell GNU from COFF format + // from the old archive type. + AltKind = object::Archive::K_COFF; + if (AltKind) { + auto InferredKind = Kind; if (NewMembersP && !NewMembersP->empty()) InferredKind = NewMembersP->front().detectKindFromObject(); else if (!NewMembers.empty()) InferredKind = NewMembers.front().detectKindFromObject(); - if (InferredKind == object::Archive::K_DARWIN) - Kind = object::Archive::K_DARWIN; + if (InferredKind == AltKind) + Kind = *AltKind; } } else if (NewMembersP) Kind = !NewMembersP->empty() ? NewMembersP->front().detectKindFromObject() @@ -1044,6 +1052,9 @@ static void performWriteOperation(ArchiveOperation Operation, case GNU: Kind = object::Archive::K_GNU; break; + case COFF: + Kind = object::Archive::K_COFF; + break; case BSD: if (Thin) fail("only the gnu format has a thin mode"); @@ -1376,6 +1387,7 @@ static int ar_main(int argc, char **argv) { .Case("darwin", DARWIN) .Case("bsd", BSD) .Case("bigarchive", BIGARCHIVE) + .Case("coff", COFF) .Default(Unknown); if (FormatType == Unknown) fail(std::string("Invalid format ") + Match); diff --git a/llvm/tools/llvm-as/llvm-as.cpp b/llvm/tools/llvm-as/llvm-as.cpp index 1c869e1739319ede0748040dca1eec283311bfb9..fd852563838f3727248489bf83909c1cafcdbe7f 100644 --- a/llvm/tools/llvm-as/llvm-as.cpp +++ b/llvm/tools/llvm-as/llvm-as.cpp @@ -67,6 +67,7 @@ static cl::opt<std::string> ClDataLayout("data-layout", cl::desc("data layout string to use"), cl::value_desc("layout-string"), cl::init(""), cl::cat(AsCat)); +extern bool WriteNewDbgInfoFormatToBitcode; static void WriteOutputFile(const Module *M, const ModuleSummaryIndex *Index) { // Infer the output filename if needed. @@ -139,6 +140,12 @@ int main(int argc, char **argv) { Err.print(argv[0], errs()); return 1; } + + // Convert to new debug format if requested. + assert(!M->IsNewDbgInfoFormat && "Unexpectedly in new debug mode"); + if (UseNewDbgInfoFormat && WriteNewDbgInfoFormatToBitcode) + M->convertToNewDbgValues(); + std::unique_ptr<ModuleSummaryIndex> Index = std::move(ModuleAndIndex.Index); if (!DisableVerify) { diff --git a/llvm/tools/llvm-c-test/debuginfo.c b/llvm/tools/llvm-c-test/debuginfo.c index a3e41be12e95d401342ab03f18c1e9037b073deb..9b5c37b05d9027612d30579cc17f1dd949b9ac28 100644 --- a/llvm/tools/llvm-c-test/debuginfo.c +++ b/llvm/tools/llvm-c-test/debuginfo.c @@ -29,9 +29,10 @@ declare_objc_class(LLVMDIBuilderRef DIB, LLVMMetadataRef File) { return Decl; } -int llvm_test_dibuilder(void) { +int llvm_test_dibuilder(bool NewDebugInfoFormat) { const char *Filename = "debuginfo.c"; LLVMModuleRef M = LLVMModuleCreateWithName(Filename); + LLVMSetIsNewDbgInfoFormat(M, NewDebugInfoFormat); LLVMDIBuilderRef DIB = LLVMCreateDIBuilder(M); LLVMMetadataRef File = LLVMDIBuilderCreateFile(DIB, Filename, @@ -135,21 +136,39 @@ int llvm_test_dibuilder(void) { LLVMMetadataRef FooParamVar1 = LLVMDIBuilderCreateParameterVariable(DIB, FunctionMetadata, "a", 1, 1, File, 42, Int64Ty, true, 0); - LLVMDIBuilderInsertDeclareAtEnd(DIB, LLVMConstInt(LLVMInt64Type(), 0, false), - FooParamVar1, FooParamExpression, - FooParamLocation, FooEntryBlock); + + if (LLVMIsNewDbgInfoFormat(M)) + LLVMDIBuilderInsertDeclareAtEnd( + DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar1, + FooParamExpression, FooParamLocation, FooEntryBlock); + else + LLVMDIBuilderInsertDeclareIntrinsicAtEnd( + DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar1, + FooParamExpression, FooParamLocation, FooEntryBlock); LLVMMetadataRef FooParamVar2 = LLVMDIBuilderCreateParameterVariable(DIB, FunctionMetadata, "b", 1, 2, File, 42, Int64Ty, true, 0); - LLVMDIBuilderInsertDeclareAtEnd(DIB, LLVMConstInt(LLVMInt64Type(), 0, false), - FooParamVar2, FooParamExpression, - FooParamLocation, FooEntryBlock); + + if (LLVMIsNewDbgInfoFormat(M)) + LLVMDIBuilderInsertDeclareAtEnd( + DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar2, + FooParamExpression, FooParamLocation, FooEntryBlock); + else + LLVMDIBuilderInsertDeclareIntrinsicAtEnd( + DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar2, + FooParamExpression, FooParamLocation, FooEntryBlock); + LLVMMetadataRef FooParamVar3 = LLVMDIBuilderCreateParameterVariable(DIB, FunctionMetadata, "c", 1, 3, File, 42, VectorTy, true, 0); - LLVMDIBuilderInsertDeclareAtEnd(DIB, LLVMConstInt(LLVMInt64Type(), 0, false), - FooParamVar3, FooParamExpression, - FooParamLocation, FooEntryBlock); + if (LLVMIsNewDbgInfoFormat(M)) + LLVMDIBuilderInsertDeclareAtEnd( + DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar3, + FooParamExpression, FooParamLocation, FooEntryBlock); + else + LLVMDIBuilderInsertDeclareIntrinsicAtEnd( + DIB, LLVMConstInt(LLVMInt64Type(), 0, false), FooParamVar3, + FooParamExpression, FooParamLocation, FooEntryBlock); LLVMSetSubprogram(FooFunction, FunctionMetadata); @@ -166,9 +185,12 @@ int llvm_test_dibuilder(void) { LLVMValueRef FooVal1 = LLVMConstInt(LLVMInt64Type(), 0, false); LLVMMetadataRef FooVarValueExpr = LLVMDIBuilderCreateConstantValueExpression(DIB, 0); - - LLVMDIBuilderInsertDbgValueAtEnd(DIB, FooVal1, FooVar1, FooVarValueExpr, - FooVarsLocation, FooVarBlock); + if (LLVMIsNewDbgInfoFormat(M)) + LLVMDIBuilderInsertDbgValueRecordAtEnd( + DIB, FooVal1, FooVar1, FooVarValueExpr, FooVarsLocation, FooVarBlock); + else + LLVMDIBuilderInsertDbgValueIntrinsicAtEnd( + DIB, FooVal1, FooVar1, FooVarValueExpr, FooVarsLocation, FooVarBlock); LLVMMetadataRef MacroFile = LLVMDIBuilderCreateTempMacroFile(DIB, NULL, 0, File); diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp index bc708e2d472edd4195bd34d171722e9648e05718..347863638849ce900873c2ce5f48b1cd468efca7 100644 --- a/llvm/tools/llvm-c-test/echo.cpp +++ b/llvm/tools/llvm-c-test/echo.cpp @@ -1397,6 +1397,14 @@ FunClone: } LLVMDisposeValueMetadataEntries(AllMetadata); + // Copy any prefix data that may be on the function + if (LLVMHasPrefixData(Cur)) + LLVMSetPrefixData(Fun, clone_constant(LLVMGetPrefixData(Cur), M)); + + // Copy any prologue data that may be on the function + if (LLVMHasPrologueData(Cur)) + LLVMSetPrologueData(Fun, clone_constant(LLVMGetPrologueData(Cur), M)); + FunCloner FC(Cur, Fun); FC.CloneBBs(Cur); diff --git a/llvm/tools/llvm-c-test/llvm-c-test.h b/llvm/tools/llvm-c-test/llvm-c-test.h index 00566660257e0714d9abf017487b011b0c9c269e..c50d3cce86748da2e36e1ac1fdb43940992cf603 100644 --- a/llvm/tools/llvm-c-test/llvm-c-test.h +++ b/llvm/tools/llvm-c-test/llvm-c-test.h @@ -36,7 +36,7 @@ int llvm_calc(void); int llvm_disassemble(void); // debuginfo.c -int llvm_test_dibuilder(void); +int llvm_test_dibuilder(bool NewDebugInfoFormat); int llvm_get_di_tag(void); int llvm_di_type_get_name(void); diff --git a/llvm/tools/llvm-c-test/main.c b/llvm/tools/llvm-c-test/main.c index badbe4b13b6ba566bb0b289f5b57e1505140ec73..c4748d342fba14ef4090d088a168ba53afbcd4ff 100644 --- a/llvm/tools/llvm-c-test/main.c +++ b/llvm/tools/llvm-c-test/main.c @@ -110,7 +110,7 @@ int main(int argc, char **argv) { } else if (argc == 2 && !strcmp(argv[1], "--test-diagnostic-handler")) { return llvm_test_diagnostic_handler(); } else if (argc == 2 && !strcmp(argv[1], "--test-dibuilder")) { - return llvm_test_dibuilder(); + return llvm_test_dibuilder(false) && llvm_test_dibuilder(true); } else { print_usage(); } diff --git a/llvm/tools/llvm-debuginfo-analyzer/README.md b/llvm/tools/llvm-debuginfo-analyzer/README.md new file mode 100644 index 0000000000000000000000000000000000000000..28c4be6f732299a5f66ecd151eb8ed77f44f97e8 --- /dev/null +++ b/llvm/tools/llvm-debuginfo-analyzer/README.md @@ -0,0 +1,170 @@ +# `llvm-debuginfo-analyzer` + +These are the notes collected during the development, review and test. +They describe limitations, known issues and future work. + +### Remove the use of macros in ``LVReader.h`` that describe the ``bumpallocators``. +**[D137933](https://reviews.llvm.org/D137933#inline-1389904)** + +Use a standard (or LLVM) ``map`` with ``typeinfo`` (would need a specialization +to expose equality and hasher) for the allocators and the creation +functions could be a function template. + +### Use a **lit test** instead of a **unit test** for the **logical readers**. +**[D125783](https://reviews.llvm.org/D125783#inline-1324376)** + +As the ``DebugInfoLogicalView`` library is sufficiently exposed via the +``llvm-debuginfo-analyzer`` tool, follow the LLVM general approach and +use ``lit`` tests to validate the **logical readers**. + +Convert the ``unitests``: +``` +llvm-project/llvm/unittests/DebugInfo/LogicalView/CodeViewReaderTest.cpp +llvm-project/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp +``` +into ``lit`` tests: +``` +llvm-project/llvm/test/DebugInfo/LogicalView/CodeViewReader.test +llvm-project/llvm/test/DebugInfo/LogicalView/DWARFReader.test +``` + +### Eliminate calls to ``getInputFileDirectory()`` in the ``unittests``. +**[D125783](https://reviews.llvm.org/D125783#inline-1324359)** + +Rewrite the unittests ``ReaderTest`` and ``CodeViewReaderTest`` to eliminate +the call: +``` + getInputFileDirectory() +``` +as use of that call is discouraged. + +### Fix mismatch between ``%d/%x`` format strings and ``uint64_t`` type. +**[D137400](https://reviews.llvm.org/D137400) / [58758](https://github.com/llvm/llvm-project/issues/58758)** + +Incorrect printing of ``uint64_t`` on ``32-bit`` platforms. +Add the ``PRIx64`` specifier to the printing code (``format()``). + +### Remove ``LVScope::Children`` container. +**[D137933](https://reviews.llvm.org/D137933#inline-1373902)** + +Use a **chaining iterator** over the other containers rather than keep a +separate container ``Children`` that mirrors their contents. + +### Use ``TableGen`` for command line options. +**[D125777](https://reviews.llvm.org/D125777#inline-1291801)** + +The current trend is to use ``TableGen`` for command-line options in tools. +Change command line options to use ``tablegen`` as many other LLVM tools. + +### ``LVDoubleMap`` to return ``optional<ValueType>`` instead of ``null pointer``. +**[D125783](https://reviews.llvm.org/D125783#inline-1294164)** + +The more idiomatic LLVM way to handle this would be to have ``find`` +return ``Optional<ValueType>``. + +### Pass references instead of pointers (**Comparison functions**). +**[D125782](https://reviews.llvm.org/D125782#inline-1293920)** + +In the **comparison functions**, pass references instead of pointers (when +pointers cannot be null). + +### Use ``StringMap`` where possible. +**[D125783](https://reviews.llvm.org/D125783#inline-1294211)** + +LLVM has a ``StringMap`` class that is advertised as more efficient than +``std::map<std::string, ValueType>``. Mainly it does fewer allocations +because the key is not a ``std::string``. + +Replace the use of ``std::map<std::string, ValueType>`` with ``StringMap``. +One specific case is the ``LVSymbolNames`` definitions. + +### Calculate unique offset for CodeView elements. +In order to have the same logical functionality as the DWARF reader, such +as: + +* find scopes contribution to debug info +* sort by its physical location + +The logical elements must have an unique offset (similar like the DWARF +``DIE`` offset). + +### Move ``initializeFileAndStringTables`` to the CodeView Library. +There is some code in the CodeView reader that was extracted/adapted +from ``tools/llvm-readobj/COFFDumper.cpp`` that can be moved to the CodeView +library. + +We had a similar case with code shared with ``llvm-pdbutil`` that was moved +to the PDB library: **[D122226](https://reviews.llvm.org/D122226)** + +### Move ``getSymbolKindName`` and ``formatRegisterId`` to the CodeView Library. +There is some code in the CodeView reader that was extracted/adapted +from ``lib/DebugInfo/CodeView/SymbolDumper.cpp`` that can be used. + +### Use of ``std::unordered_set`` instead of ``std::set``. +**[D125784](https://reviews.llvm.org/D125784#inline-1221421)** + +Replace the ``std::set`` usage for ``DeducedScopes``, ``UnresolvedScopes`` and +``IdentifiedNamespaces`` with ``std::unordered_set`` and get the benefit +of the O(1) while inserting/searching, as the order is not important. + +### Optimize ``LVNamespaceDeduction::find`` funtion. +**[D125784](https://reviews.llvm.org/D125784#inline-1296195)** + +Optimize the ``find`` method to use the proposed code: + +``` + LVStringRefs::iterator Iter = std::find_if(Components.begin(), Components.end(), + [](StringRef Name) { + return IdentifiedNamespaces.find(Name) == IdentifiedNamespaces.end(); + }); + LVStringRefs::size_type FirstNonNamespace = std::distance(Components.begin(), Iter); +``` + +### Move all the printing support to a common module. +Factor out printing functionality from the logical elements into a +common module. + +### Refactor ``LVBinaryReader::processLines``. +**[D125783](https://reviews.llvm.org/D125783#inline-1246155) / +[D137156](https://reviews.llvm.org/D137156)** + +During the traversal of the debug information sections, we created the +logical lines representing the **disassembled instructions** from the **text +section** and the logical lines representing the **line records** from the +**debug line** section. Using the ranges associated with the logical scopes, +we will allocate those logical lines to their logical scopes. + +Consider the case when any of those lines become orphans, causing +incorrect scope parent for disassembly or line records. + +### Add support for ``-ffunction-sections``. +**[D125783](https://reviews.llvm.org/D125783#inline-1295012)** + +Only linked executables are handled. It does not support relocatable +files compiled with ``-ffunction-sections``. + +### Add support for DWARF v5 `.debug_names` section / CodeView public symbols stream. +**[D125783](https://reviews.llvm.org/D125783#inline-1294142)** + +The DWARF and CodeView readers use the public names information to create +the instructions (``LVLineAssembler``). Instead of relying on DWARF section +names (``.debug_pubnames``, ``.debug_names``) and CodeView public symbol stream +(``S_PUB32``), the readers should collect the needed information while processing +the debug information. + +If the object file supports the above section names and stream, use them +to create the public names. + +### Add support for some extra DWARF locations. +The following DWARF debug location operands are not supported: + +* `DW_OP_const_type` +* `DW_OP_entry_value` +* `DW_OP_implicit_value` + +### Add support for additional binary formats. +* Extended COFF (`XCOFF`) + +### Add support for ``JSON`` or ``YAML`` +The logical view uses its own and non-standard free form text when +displaying information on logical elements. diff --git a/llvm/tools/llvm-debuginfo-analyzer/README.txt b/llvm/tools/llvm-debuginfo-analyzer/README.txt deleted file mode 100644 index e6c20db7cd7121b51ca0c7281f5d31e02270d06b..0000000000000000000000000000000000000000 --- a/llvm/tools/llvm-debuginfo-analyzer/README.txt +++ /dev/null @@ -1,224 +0,0 @@ -//===- llvm/tools/llvm-debuginfo-analyzer/README.txt ----------------------===// -// -// 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 notes collected during the development, review and test. -// It describes limitations, know issues and future work. -// -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// Remove the use of macros in 'LVReader.h' that describe the bumpallocators. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D137933#inline-1389904 - -Use a standard (or LLVM) map with typeinfo (would need a specialization -to expose equality and hasher) for the allocators and the creation -functions could be a function template. - -//===----------------------------------------------------------------------===// -// Use a lit test instead of a unit test for the logical readers. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125783#inline-1324376 - -As the DebugInfoLogicalView library is sufficiently exposed via the -llvm-debuginfo-analyzer tool, follow the LLVM general approach and -use LIT tests to validate the logical readers. - -Convert the unitests: - llvm-project/llvm/unittests/DebugInfo/LogicalView/CodeViewReaderTest.cpp - llvm-project/llvm/unittests/DebugInfo/LogicalView/ELFReaderTest.cpp - -into LIT tests: - llvm-project/llvm/test/DebugInfo/LogicalView/CodeViewReader.test - llvm-project/llvm/test/DebugInfo/LogicalView/ELFReader.test - -//===----------------------------------------------------------------------===// -// Eliminate calls to 'getInputFileDirectory()' in the unit tests. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125783#inline-1324359 - -Rewrite the unittests 'LFReaderTest' and 'CodeViewReaderTest'to eliminate -the call: - - getInputFileDirectory() - -as use of that call is discouraged. - -See: Use a lit test instead of a unit test for the logical readers. - -//===----------------------------------------------------------------------===// -// Fix mismatch between %d/%x format strings and uint64_t type. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D137400 -https://github.com/llvm/llvm-project/issues/58758 - -Incorrect printing of uint64_t on 32-bit platforms. -Add the PRIx64 specifier to the printing code (format()). - -//===----------------------------------------------------------------------===// -// Remove 'LVScope::Children' container. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D137933#inline-1373902 - -Use a chaining iterator over the other containers rather than keep a -separate container 'Children' that mirrors their contents. - -//===----------------------------------------------------------------------===// -// Use TableGen for command line options. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125777#inline-1291801 - -The current trend is to use TableGen for command-line options in tools. -Change command line options to use tablegen as many other LLVM tools. - -//===----------------------------------------------------------------------===// -// LVDoubleMap to return optional<ValueType> instead of null pointer. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125783#inline-1294164 - -The more idiomatic LLVM way to handle this would be to have 'find ' -return Optional<ValueType>. - -//===----------------------------------------------------------------------===// -// Pass references instead of pointers (Comparison functions). -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125782#inline-1293920 - -In the comparison functions, pass references instead of pointers (when -pointers cannot be null). - -//===----------------------------------------------------------------------===// -// Use StringMap where possible. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125783#inline-1294211 - -LLVM has a StringMap class that is advertised as more efficient than -std::map<std::string, ValueType>. Mainly it does fewer allocations -because the key is not a std::string. - -Replace the use of std::map<std::string, ValueType> with String Map. -One specific case is the LVSymbolNames definitions. - -//===----------------------------------------------------------------------===// -// Calculate unique offset for CodeView elements. -//===----------------------------------------------------------------------===// -In order to have the same logical functionality as the ELF Reader, such -as: - -- find scopes contribution to debug info -- sort by its physical location - -The logical elements must have an unique offset (similar like the DWARF -DIE offset). - -//===----------------------------------------------------------------------===// -// Move 'initializeFileAndStringTables' to the COFF Library. -//===----------------------------------------------------------------------===// -There is some code in the CodeView reader that was extracted/adapted -from 'tools/llvm-readobj/COFFDumper.cpp' that can be moved to the COFF -library. - -We had a similar case with code shared with llvm-pdbutil that was moved -to the PDB library: https://reviews.llvm.org/D122226 - -//===----------------------------------------------------------------------===// -// Move 'getSymbolKindName'/'formatRegisterId' to the CodeView Library. -//===----------------------------------------------------------------------===// -There is some code in the CodeView reader that was extracted/adapted -from 'lib/DebugInfo/CodeView/SymbolDumper.cpp' that can be used. - -//===----------------------------------------------------------------------===// -// Use of std::unordered_set instead of std::set. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125784#inline-1221421 - -Replace the std::set usage for DeducedScopes, UnresolvedScopes and -IdentifiedNamespaces with std::unordered_set and get the benefit -of the O(1) while inserting/searching, as the order is not important. - -//===----------------------------------------------------------------------===// -// Optimize 'LVNamespaceDeduction::find' funtion. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125784#inline-1296195 - -Optimize the 'find' method to use the proposed code: - - LVStringRefs::iterator Iter = std::find_if(Components.begin(), Components.end(), - [](StringRef Name) { - return IdentifiedNamespaces.find(Name) == IdentifiedNamespaces.end(); - }); - LVStringRefs::size_type FirstNonNamespace = std::distance(Components.begin(), Iter); - -//===----------------------------------------------------------------------===// -// Move all the printing support to a common module. -//===----------------------------------------------------------------------===// -Factor out printing functionality from the logical elements into a -common module. - -//===----------------------------------------------------------------------===// -// Refactor 'LVBinaryReader::processLines'. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125783#inline-1246155 -https://reviews.llvm.org/D137156 - -During the traversal of the debug information sections, we created the -logical lines representing the disassembled instructions from the text -section and the logical lines representing the line records from the -debug line section. Using the ranges associated with the logical scopes, -we will allocate those logical lines to their logical scopes. - -Consider the case when any of those lines become orphans, causing -incorrect scope parent for disassembly or line records. - -//===----------------------------------------------------------------------===// -// Add support for '-ffunction-sections'. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125783#inline-1295012 - -Only linked executables are handled. It does not support relocatable -files compiled with -ffunction-sections. - -//===----------------------------------------------------------------------===// -// Add support for DWARF v5 .debug_names section. -// Add support for CodeView public symbols stream. -//===----------------------------------------------------------------------===// -https://reviews.llvm.org/D125783#inline-1294142 - -The ELF and CodeView readers use the public names information to create -the instructions (LVLineAssembler). Instead of relying on DWARF section -names (.debug_pubnames, .debug_names) and CodeView public symbol stream -(S_PUB32), the readers collects the needed information while processing -the debug information. - -If the object file supports the above section names and stream, use them -to create the public names. - -//===----------------------------------------------------------------------===// -// Add support for some extra DWARF locations. -//===----------------------------------------------------------------------===// -The following DWARF debug location operands are not supported: - -- DW_OP_const_type -- DW_OP_entry_value -- DW_OP_implicit_value - -//===----------------------------------------------------------------------===// -// Add support for additional binary formats. -//===----------------------------------------------------------------------===// -- WebAssembly (Wasm). - https://github.com/llvm/llvm-project/issues/57040#issuecomment-1211336680 - -- Extended COFF (XCOFF) - -//===----------------------------------------------------------------------===// -// Add support for JSON or YAML. -//===----------------------------------------------------------------------===// -The logical view uses its own and non-standard free form text when -displaying information on logical elements. - -//===----------------------------------------------------------------------===// diff --git a/llvm/tools/llvm-dis/llvm-dis.cpp b/llvm/tools/llvm-dis/llvm-dis.cpp index 06fc669390bf1d207c0412bff85958cb6be87e6a..49154dc46c57e8bf8afaf901459d68fc742caa80 100644 --- a/llvm/tools/llvm-dis/llvm-dis.cpp +++ b/llvm/tools/llvm-dis/llvm-dis.cpp @@ -80,6 +80,10 @@ static cl::opt<bool> PrintThinLTOIndexOnly( cl::desc("Only read thinlto index and print the index as LLVM assembly."), cl::init(false), cl::Hidden, cl::cat(DisCategory)); +extern cl::opt<bool> WriteNewDbgInfoFormat; + +extern cl::opt<cl::boolOrDefault> LoadBitcodeIntoNewDbgInfoFormat; + namespace { static void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) { @@ -167,6 +171,10 @@ int main(int argc, char **argv) { cl::HideUnrelatedOptions({&DisCategory, &getColorCategory()}); cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n"); + // Load bitcode into the new debug info format by default. + if (LoadBitcodeIntoNewDbgInfoFormat == cl::boolOrDefault::BOU_UNSET) + LoadBitcodeIntoNewDbgInfoFormat = cl::boolOrDefault::BOU_TRUE; + LLVMContext Context; Context.setDiagnosticHandler( std::make_unique<LLVMDisDiagnosticHandler>(argv[0])); @@ -249,8 +257,14 @@ int main(int argc, char **argv) { // All that llvm-dis does is write the assembly to a file. if (!DontPrint) { - if (M) + if (M) { + bool ChangeDbgFormat = M->IsNewDbgInfoFormat != WriteNewDbgInfoFormat; + if (ChangeDbgFormat) + M->setIsNewDbgInfoFormat(WriteNewDbgInfoFormat); M->print(Out->os(), Annotator.get(), PreserveAssemblyUseListOrder); + if (ChangeDbgFormat) + M->setIsNewDbgInfoFormat(!WriteNewDbgInfoFormat); + } if (Index) Index->print(Out->os()); } diff --git a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp index bd17f3c4a6595e2c48ab5e6dc7e3ccae43a68b89..285dcf75ecd9d380ccc268bcfb0f0624a30424d1 100644 --- a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp +++ b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp @@ -338,9 +338,9 @@ Error linkDebugInfoImpl(object::ObjectFile &File, const Options &Options, Triple TargetTriple = File.makeTriple(); std::unique_ptr<classic::DwarfStreamer> Streamer; if (Expected<std::unique_ptr<classic::DwarfStreamer>> StreamerOrErr = - classic::DwarfStreamer::createStreamer( - TargetTriple, Linker::OutputFileType::Object, OutStream, nullptr, - ReportWarn)) + classic::DwarfStreamer::createStreamer(TargetTriple, + Linker::OutputFileType::Object, + OutStream, ReportWarn)) Streamer = std::move(*StreamerOrErr); else return StreamerOrErr.takeError(); diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp index 17ce0355ef4fd073ac1c2265b23ec7dde50084fc..498308e2edbe1fd541c27221dcff61c7164c2129 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -278,60 +278,20 @@ private: return FD; } - Error createSubProcessAndRunBenchmark( - StringRef CounterName, SmallVectorImpl<int64_t> &CounterValues, - ArrayRef<const char *> ValidationCounters, - SmallVectorImpl<int64_t> &ValidationCounterValues) const { - int PipeFiles[2]; - int PipeSuccessOrErr = socketpair(AF_UNIX, SOCK_DGRAM, 0, PipeFiles); - if (PipeSuccessOrErr != 0) { - return make_error<Failure>( - "Failed to create a pipe for interprocess communication between " - "llvm-exegesis and the benchmarking subprocess: " + - Twine(strerror(errno))); - } - - SubprocessMemory SPMemory; - Error MemoryInitError = SPMemory.initializeSubprocessMemory(getpid()); - if (MemoryInitError) - return MemoryInitError; - - Error AddMemDefError = - SPMemory.addMemoryDefinition(Key.MemoryValues, getpid()); - if (AddMemDefError) - return AddMemDefError; - - long ParentTID = get_threadid(); - pid_t ParentOrChildPID = fork(); - - if (ParentOrChildPID == -1) { - return make_error<Failure>("Failed to create child process: " + - Twine(strerror(errno))); - } - - if (ParentOrChildPID == 0) { - // We are in the child process, close the write end of the pipe. - close(PipeFiles[1]); - // Unregister handlers, signal handling is now handled through ptrace in - // the host process. - sys::unregisterHandlers(); - prepareAndRunBenchmark(PipeFiles[0], Key, ParentTID); - // The child process terminates in the above function, so we should never - // get to this point. - llvm_unreachable("Child process didn't exit when expected."); - } - + Error + runParentProcess(pid_t ChildPID, int WriteFD, StringRef CounterName, + SmallVectorImpl<int64_t> &CounterValues, + ArrayRef<const char *> ValidationCounters, + SmallVectorImpl<int64_t> &ValidationCounterValues) const { const ExegesisTarget &ET = State.getExegesisTarget(); - auto CounterOrError = ET.createCounter( - CounterName, State, ValidationCounters, ParentOrChildPID); + auto CounterOrError = + ET.createCounter(CounterName, State, ValidationCounters, ChildPID); if (!CounterOrError) return CounterOrError.takeError(); pfm::CounterGroup *Counter = CounterOrError.get().get(); - close(PipeFiles[0]); - // Make sure to attach to the process (and wait for the sigstop to be // delivered and for the process to continue) before we write to the counter // file descriptor. Attaching to the process before writing to the socket @@ -339,30 +299,30 @@ private: // attach afterwards, the subprocess might exit before we get to the attach // call due to effects like scheduler contention, introducing transient // failures. - if (ptrace(PTRACE_ATTACH, ParentOrChildPID, NULL, NULL) != 0) + if (ptrace(PTRACE_ATTACH, ChildPID, NULL, NULL) != 0) return make_error<Failure>("Failed to attach to the child process: " + Twine(strerror(errno))); - if (wait(NULL) == -1) { + if (waitpid(ChildPID, NULL, 0) == -1) { return make_error<Failure>( "Failed to wait for child process to stop after attaching: " + Twine(strerror(errno))); } - if (ptrace(PTRACE_CONT, ParentOrChildPID, NULL, NULL) != 0) + if (ptrace(PTRACE_CONT, ChildPID, NULL, NULL) != 0) return make_error<Failure>( "Failed to continue execution of the child process: " + Twine(strerror(errno))); int CounterFileDescriptor = Counter->getFileDescriptor(); Error SendError = - sendFileDescriptorThroughSocket(PipeFiles[1], CounterFileDescriptor); + sendFileDescriptorThroughSocket(WriteFD, CounterFileDescriptor); if (SendError) return SendError; int ChildStatus; - if (wait(&ChildStatus) == -1) { + if (waitpid(ChildPID, &ChildStatus, 0) == -1) { return make_error<Failure>( "Waiting for the child process to complete failed: " + Twine(strerror(errno))); @@ -396,12 +356,25 @@ private: // An error was encountered running the snippet, process it siginfo_t ChildSignalInfo; - if (ptrace(PTRACE_GETSIGINFO, ParentOrChildPID, NULL, &ChildSignalInfo) == - -1) { + if (ptrace(PTRACE_GETSIGINFO, ChildPID, NULL, &ChildSignalInfo) == -1) { return make_error<Failure>("Getting signal info from the child failed: " + Twine(strerror(errno))); } + // Send SIGKILL rather than SIGTERM as the child process has no SIGTERM + // handlers to run, and calling SIGTERM would mean that ptrace will force + // it to block in the signal-delivery-stop for the SIGSEGV/other signals, + // and upon exit. + if (kill(ChildPID, SIGKILL) == -1) + return make_error<Failure>("Failed to kill child benchmarking proces: " + + Twine(strerror(errno))); + + // Wait for the process to exit so that there are no zombie processes left + // around. + if (waitpid(ChildPID, NULL, 0) == -1) + return make_error<Failure>("Failed to wait for process to die: " + + Twine(strerror(errno))); + if (ChildSignalInfo.si_signo == SIGSEGV) return make_error<SnippetSegmentationFault>( reinterpret_cast<intptr_t>(ChildSignalInfo.si_addr)); @@ -409,6 +382,57 @@ private: return make_error<SnippetSignal>(ChildSignalInfo.si_signo); } + Error createSubProcessAndRunBenchmark( + StringRef CounterName, SmallVectorImpl<int64_t> &CounterValues, + ArrayRef<const char *> ValidationCounters, + SmallVectorImpl<int64_t> &ValidationCounterValues) const { + int PipeFiles[2]; + int PipeSuccessOrErr = socketpair(AF_UNIX, SOCK_DGRAM, 0, PipeFiles); + if (PipeSuccessOrErr != 0) { + return make_error<Failure>( + "Failed to create a pipe for interprocess communication between " + "llvm-exegesis and the benchmarking subprocess: " + + Twine(strerror(errno))); + } + + SubprocessMemory SPMemory; + Error MemoryInitError = SPMemory.initializeSubprocessMemory(getpid()); + if (MemoryInitError) + return MemoryInitError; + + Error AddMemDefError = + SPMemory.addMemoryDefinition(Key.MemoryValues, getpid()); + if (AddMemDefError) + return AddMemDefError; + + long ParentTID = SubprocessMemory::getCurrentTID(); + pid_t ParentOrChildPID = fork(); + + if (ParentOrChildPID == -1) { + return make_error<Failure>("Failed to create child process: " + + Twine(strerror(errno))); + } + + if (ParentOrChildPID == 0) { + // We are in the child process, close the write end of the pipe. + close(PipeFiles[1]); + // Unregister handlers, signal handling is now handled through ptrace in + // the host process. + sys::unregisterHandlers(); + runChildSubprocess(PipeFiles[0], Key, ParentTID); + // The child process terminates in the above function, so we should never + // get to this point. + llvm_unreachable("Child process didn't exit when expected."); + } + + // Close the read end of the pipe as we only need to write to the subprocess + // from the parent process. + close(PipeFiles[0]); + return runParentProcess(ParentOrChildPID, PipeFiles[1], CounterName, + CounterValues, ValidationCounters, + ValidationCounterValues); + } + void disableCoreDumps() const { struct rlimit rlim; @@ -416,8 +440,8 @@ private: setrlimit(RLIMIT_CORE, &rlim); } - [[noreturn]] void prepareAndRunBenchmark(int Pipe, const BenchmarkKey &Key, - long ParentTID) const { + [[noreturn]] void runChildSubprocess(int Pipe, const BenchmarkKey &Key, + long ParentTID) const { // Disable core dumps in the child process as otherwise everytime we // encounter an execution failure like a segmentation fault, we will create // a core dump. We report the information directly rather than require the diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp index 28b341c461804fc05fbd62ca91b1a8ca3110590d..0a947f6e206fef6339c2abc10b25f72cf1ecb469 100644 --- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp +++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp @@ -10,7 +10,6 @@ #include "Error.h" #include "llvm/Support/Error.h" #include "llvm/Support/FormatVariadic.h" -#include "llvm/Support/Threading.h" #include <cerrno> #ifdef __linux__ @@ -25,6 +24,13 @@ namespace exegesis { #if defined(__linux__) && !defined(__ANDROID__) +long SubprocessMemory::getCurrentTID() { + // We're using the raw syscall here rather than the gettid() function provided + // by most libcs for compatibility as gettid() was only added to glibc in + // version 2.30. + return syscall(SYS_gettid); +} + Error SubprocessMemory::initializeSubprocessMemory(pid_t ProcessID) { // Add the PID to the shared memory name so that if we're running multiple // processes at the same time, they won't interfere with each other. @@ -32,7 +38,7 @@ Error SubprocessMemory::initializeSubprocessMemory(pid_t ProcessID) { // llvm-lit. Additionally add the TID so that downstream consumers // using multiple threads don't run into conflicts. std::string AuxiliaryMemoryName = - formatv("/{0}auxmem{1}", get_threadid(), ProcessID); + formatv("/{0}auxmem{1}", getCurrentTID(), ProcessID); int AuxiliaryMemoryFD = shm_open(AuxiliaryMemoryName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryFD == -1) @@ -53,10 +59,14 @@ Error SubprocessMemory::addMemoryDefinition( SharedMemoryNames.reserve(MemoryDefinitions.size()); for (auto &[Name, MemVal] : MemoryDefinitions) { std::string SharedMemoryName = - formatv("/{0}t{1}memdef{2}", ProcessPID, get_threadid(), MemVal.Index); + formatv("/{0}t{1}memdef{2}", ProcessPID, getCurrentTID(), MemVal.Index); SharedMemoryNames.push_back(SharedMemoryName); int SharedMemoryFD = shm_open(SharedMemoryName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (SharedMemoryFD == -1) + return make_error<Failure>( + "Failed to create shared memory object for memory definition: " + + Twine(strerror(errno))); if (ftruncate(SharedMemoryFD, MemVal.SizeBytes) != 0) { return make_error<Failure>("Truncating a memory definiton failed: " + Twine(strerror(errno))); @@ -87,14 +97,15 @@ Error SubprocessMemory::addMemoryDefinition( Expected<int> SubprocessMemory::setupAuxiliaryMemoryInSubprocess( std::unordered_map<std::string, MemoryValue> MemoryDefinitions, - pid_t ParentPID, uint64_t ParentTID, int CounterFileDescriptor) { + pid_t ParentPID, long ParentTID, int CounterFileDescriptor) { std::string AuxiliaryMemoryName = formatv("/{0}auxmem{1}", ParentTID, ParentPID); int AuxiliaryMemoryFileDescriptor = shm_open(AuxiliaryMemoryName.c_str(), O_RDWR, S_IRUSR | S_IWUSR); if (AuxiliaryMemoryFileDescriptor == -1) return make_error<Failure>( - "Getting file descriptor for auxiliary memory failed"); + "Getting file descriptor for auxiliary memory failed: " + + Twine(strerror(errno))); // set up memory value file descriptors int *AuxiliaryMemoryMapping = (int *)mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, @@ -139,7 +150,7 @@ Error SubprocessMemory::addMemoryDefinition( Expected<int> SubprocessMemory::setupAuxiliaryMemoryInSubprocess( std::unordered_map<std::string, MemoryValue> MemoryDefinitions, - pid_t ParentPID, uint64_t ParentTID, int CounterFileDescriptor) { + pid_t ParentPID, long ParentTID, int CounterFileDescriptor) { return make_error<Failure>( "setupAuxiliaryMemoryInSubprocess is only supported on Linux"); } diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h index 807046e38ce6d2c85d65ca748f5cf51cfbc6471f..572d1085d9cffa7b7f0805c4ab4903ccb621ea0d 100644 --- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h +++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h @@ -35,6 +35,9 @@ public: static constexpr const size_t AuxiliaryMemoryOffset = 1; static constexpr const size_t AuxiliaryMemorySize = 4096; + // Gets the thread ID for the calling thread. + static long getCurrentTID(); + Error initializeSubprocessMemory(pid_t ProcessID); // The following function sets up memory definitions. It creates shared @@ -54,7 +57,7 @@ public: // section. static Expected<int> setupAuxiliaryMemoryInSubprocess( std::unordered_map<std::string, MemoryValue> MemoryDefinitions, - pid_t ParentPID, uint64_t ParentTID, int CounterFileDescriptor); + pid_t ParentPID, long ParentTID, int CounterFileDescriptor); ~SubprocessMemory(); diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp index 1ae2565e894c694797aa298998af4073a49496bc..06e1c7f3c1bbed42e7898a6d6cab1f22f9b10582 100644 --- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp +++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp @@ -423,10 +423,9 @@ static void runBenchmarkConfigurations( if (Err) { // Errors from executing the snippets are fine. // All other errors are a framework issue and should fail. - if (!Err.isA<SnippetExecutionFailure>()) { - llvm::errs() << "llvm-exegesis error: " << toString(std::move(Err)); - exit(1); - } + if (!Err.isA<SnippetExecutionFailure>()) + ExitOnErr(std::move(Err)); + BenchmarkResult.Error = toString(std::move(Err)); } AllResults.push_back(std::move(BenchmarkResult)); diff --git a/llvm/tools/llvm-link/llvm-link.cpp b/llvm/tools/llvm-link/llvm-link.cpp index 9e7f2c3ebac437be061b393419d97b7ed83631f3..9049cb5e858002af7d74ea19cd7c625c71c2bfb7 100644 --- a/llvm/tools/llvm-link/llvm-link.cpp +++ b/llvm/tools/llvm-link/llvm-link.cpp @@ -136,6 +136,8 @@ static cl::opt<bool> TryUseNewDbgInfoFormat( extern cl::opt<bool> UseNewDbgInfoFormat; +extern cl::opt<cl::boolOrDefault> LoadBitcodeIntoNewDbgInfoFormat; + static ExitOnError ExitOnErr; // Read the specified bitcode file in and return it. This routine searches the @@ -480,6 +482,10 @@ int main(int argc, char **argv) { cl::HideUnrelatedOptions({&LinkCategory, &getColorCategory()}); cl::ParseCommandLineOptions(argc, argv, "llvm linker\n"); + // Load bitcode into the new debug info format by default. + if (LoadBitcodeIntoNewDbgInfoFormat == cl::boolOrDefault::BOU_UNSET) + LoadBitcodeIntoNewDbgInfoFormat = cl::boolOrDefault::BOU_TRUE; + // RemoveDIs debug-info transition: tests may request that we /try/ to use the // new debug-info format. if (TryUseNewDbgInfoFormat) { diff --git a/llvm/tools/llvm-lto/llvm-lto.cpp b/llvm/tools/llvm-lto/llvm-lto.cpp index 7943d6952b828d2baf96fea529e229afd787cd23..3c452b650cee1b5504ce4e4076cffe47e6bc4acc 100644 --- a/llvm/tools/llvm-lto/llvm-lto.cpp +++ b/llvm/tools/llvm-lto/llvm-lto.cpp @@ -270,6 +270,7 @@ static cl::opt<bool> TryUseNewDbgInfoFormat( cl::init(false), cl::Hidden); extern cl::opt<bool> UseNewDbgInfoFormat; +extern cl::opt<cl::boolOrDefault> LoadBitcodeIntoNewDbgInfoFormat; namespace { @@ -943,6 +944,9 @@ int main(int argc, char **argv) { InitLLVM X(argc, argv); cl::HideUnrelatedOptions({<OCategory, &getColorCategory()}); cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n"); + // Load bitcode into the new debug info format by default. + if (LoadBitcodeIntoNewDbgInfoFormat == cl::boolOrDefault::BOU_UNSET) + LoadBitcodeIntoNewDbgInfoFormat = cl::boolOrDefault::BOU_TRUE; // RemoveDIs debug-info transition: tests may request that we /try/ to use the // new debug-info format. diff --git a/llvm/tools/llvm-lto2/llvm-lto2.cpp b/llvm/tools/llvm-lto2/llvm-lto2.cpp index d5de4f6b1a277c35c4b844b31a0e644c9ea6d4bf..f222d02bd7cea7f4340233aae3f838a0e937ff1a 100644 --- a/llvm/tools/llvm-lto2/llvm-lto2.cpp +++ b/llvm/tools/llvm-lto2/llvm-lto2.cpp @@ -193,6 +193,7 @@ static cl::opt<bool> TryUseNewDbgInfoFormat( cl::init(false), cl::Hidden); extern cl::opt<bool> UseNewDbgInfoFormat; +extern cl::opt<cl::boolOrDefault> LoadBitcodeIntoNewDbgInfoFormat; static void check(Error E, std::string Msg) { if (!E) @@ -228,6 +229,9 @@ static int usage() { static int run(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, "Resolution-based LTO test harness"); + // Load bitcode into the new debug info format by default. + if (LoadBitcodeIntoNewDbgInfoFormat == cl::boolOrDefault::BOU_UNSET) + LoadBitcodeIntoNewDbgInfoFormat = cl::boolOrDefault::BOU_TRUE; // RemoveDIs debug-info transition: tests may request that we /try/ to use the // new debug-info format. diff --git a/llvm/tools/llvm-mc/llvm-mc.cpp b/llvm/tools/llvm-mc/llvm-mc.cpp index 8eb53e44045987c2d6050b6ce3eea4ddb5320d5d..807071a7b9a16a93dea20a8a156b0b54c6957ca1 100644 --- a/llvm/tools/llvm-mc/llvm-mc.cpp +++ b/llvm/tools/llvm-mc/llvm-mc.cpp @@ -541,11 +541,6 @@ int main(int argc, char **argv) { std::unique_ptr<MCAsmBackend> MAB( TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions)); auto FOut = std::make_unique<formatted_raw_ostream>(*OS); - // FIXME: Workaround for bug in formatted_raw_ostream. Color escape codes - // are (incorrectly) written directly to the unbuffered raw_ostream wrapped - // by the formatted_raw_ostream. - if (Action == AC_CDisassemble) - FOut->SetUnbuffered(); Str.reset( TheTarget->createAsmStreamer(Ctx, std::move(FOut), /*asmverbose*/ true, /*useDwarfDirectory*/ true, IP, diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp index 6318578b110048cbfe578df62e4cdfc72612be7f..7269c51a08d6b58c7e9df8be5be07140ed7f518b 100644 --- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp +++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp @@ -10,6 +10,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/BinaryFormat/COFF.h" #include "llvm/ObjCopy/CommonConfig.h" #include "llvm/ObjCopy/ConfigManager.h" @@ -528,7 +529,7 @@ static Expected<NewSymbolInfo> parseNewSymbolInfo(StringRef FlagValue) { // ArgValue, loads data from the file, and stores section name and data // into the vector of new sections \p NewSections. static Error loadNewSectionData(StringRef ArgValue, StringRef OptionName, - std::vector<NewSectionInfo> &NewSections) { + SmallVector<NewSectionInfo, 0> &NewSections) { if (!ArgValue.contains('=')) return createStringError(errc::invalid_argument, "bad format for " + OptionName + ": missing '='"); @@ -977,6 +978,15 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr, addSymbolsFromFile(Config.SymbolsToKeep, DC.Alloc, Arg->getValue(), SymbolMatchStyle, ErrorCallback)) return std::move(E); + for (auto *Arg : InputArgs.filtered(OBJCOPY_skip_symbol)) + if (Error E = Config.SymbolsToSkip.addMatcher(NameOrPattern::create( + Arg->getValue(), SymbolMatchStyle, ErrorCallback))) + return std::move(E); + for (auto *Arg : InputArgs.filtered(OBJCOPY_skip_symbols)) + if (Error E = + addSymbolsFromFile(Config.SymbolsToSkip, DC.Alloc, Arg->getValue(), + SymbolMatchStyle, ErrorCallback)) + return std::move(E); for (auto *Arg : InputArgs.filtered(OBJCOPY_add_symbol)) { Expected<NewSymbolInfo> SymInfo = parseNewSymbolInfo(Arg->getValue()); if (!SymInfo) diff --git a/llvm/tools/llvm-objcopy/ObjcopyOpts.td b/llvm/tools/llvm-objcopy/ObjcopyOpts.td index 3c0e5cd475a36b72a74d0689d111f64d90a3d141..be02616e8c68e322a0364c194be5089a9fa93940 100644 --- a/llvm/tools/llvm-objcopy/ObjcopyOpts.td +++ b/llvm/tools/llvm-objcopy/ObjcopyOpts.td @@ -206,6 +206,20 @@ defm keep_symbols "be repeated to read symbols from many files">, MetaVarName<"filename">; +defm skip_symbol : Eq<"skip-symbol", "Do not change parameters of symbol <symbol> " + "when executing other options that can change the symbol's " + "name, binding or visibility">, + MetaVarName<"symbol">; + +defm skip_symbols + : Eq<"skip-symbols", + "Read a list of symbols from <filename> and run as if " + "--skip-symbol=<symbol> is set for each one. <filename> " + "contains one symbol per line and may contain comments beginning with " + "'#'. Leading and trailing whitespace is stripped from each line. May " + "be repeated to read symbols from many files">, + MetaVarName<"filename">; + defm dump_section : Eq<"dump-section", "Dump contents of section named <section> into file <file>">, diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp index 0e6935c0ac5895d013a60526e9ebc1ca059e025d..5e0d69a68d69b430c2acb83bde1c3c500e15df63 100644 --- a/llvm/tools/llvm-objdump/MachODump.cpp +++ b/llvm/tools/llvm-objdump/MachODump.cpp @@ -3661,6 +3661,10 @@ struct class_ro32_t { #define RO_ROOT (1 << 1) #define RO_HAS_CXX_STRUCTORS (1 << 2) +/* Values for method_list{64,32}_t->entsize */ +#define ML_HAS_RELATIVE_PTRS (1 << 31) +#define ML_ENTSIZE_MASK 0xFFFF + struct method_list64_t { uint32_t entsize; uint32_t count; @@ -3685,6 +3689,12 @@ struct method32_t { uint32_t imp; /* IMP (32-bit pointer) */ }; +struct method_relative_t { + int32_t name; /* SEL (32-bit relative) */ + int32_t types; /* const char * (32-bit relative) */ + int32_t imp; /* IMP (32-bit relative) */ +}; + struct protocol_list64_t { uint64_t count; /* uintptr_t (a 64-bit value) */ /* struct protocol64_t * list[0]; These pointers follow inline */ @@ -3986,6 +3996,12 @@ inline void swapStruct(struct method32_t &m) { sys::swapByteOrder(m.imp); } +inline void swapStruct(struct method_relative_t &m) { + sys::swapByteOrder(m.name); + sys::swapByteOrder(m.types); + sys::swapByteOrder(m.imp); +} + inline void swapStruct(struct protocol_list64_t &pl) { sys::swapByteOrder(pl.count); } @@ -4440,6 +4456,88 @@ static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) { print_layout_map(layout_map, left); } +static void print_relative_method_list(uint32_t structSizeAndFlags, + uint32_t structCount, uint64_t p, + struct DisassembleInfo *info, + const char *indent, + uint32_t pointerBits) { + struct method_relative_t m; + const char *r, *name; + uint32_t offset, xoffset, left, i; + SectionRef S, xS; + + assert(((structSizeAndFlags & ML_HAS_RELATIVE_PTRS) != 0) && + "expected structSizeAndFlags to have ML_HAS_RELATIVE_PTRS flag"); + + outs() << indent << "\t\t entsize " + << (structSizeAndFlags & ML_ENTSIZE_MASK) << " (relative) \n"; + outs() << indent << "\t\t count " << structCount << "\n"; + + for (i = 0; i < structCount; i++) { + r = get_pointer_64(p, offset, left, S, info); + memset(&m, '\0', sizeof(struct method_relative_t)); + if (left < sizeof(struct method_relative_t)) { + memcpy(&m, r, left); + outs() << indent << " (method_t extends past the end of the section)\n"; + } else + memcpy(&m, r, sizeof(struct method_relative_t)); + if (info->O->isLittleEndian() != sys::IsLittleEndianHost) + swapStruct(m); + + outs() << indent << "\t\t name " << format("0x%" PRIx32, m.name); + uint64_t relNameRefVA = p + offsetof(struct method_relative_t, name); + uint64_t absNameRefVA = relNameRefVA + m.name; + outs() << " (" << format("0x%" PRIx32, absNameRefVA) << ")"; + + // since this is a relative list, absNameRefVA is the address of the + // __objc_selrefs entry, so a pointer, not the actual name + const char *nameRefPtr = + get_pointer_64(absNameRefVA, xoffset, left, xS, info); + if (nameRefPtr) { + uint32_t pointerSize = pointerBits / CHAR_BIT; + if (left < pointerSize) + outs() << indent << " (nameRefPtr extends past the end of the section)"; + else { + if (pointerSize == 64) { + uint64_t nameOff_64 = *reinterpret_cast<const uint64_t *>(nameRefPtr); + if (info->O->isLittleEndian() != sys::IsLittleEndianHost) + sys::swapByteOrder(nameOff_64); + name = get_pointer_64(nameOff_64, xoffset, left, xS, info); + } else { + uint32_t nameOff_32 = *reinterpret_cast<const uint32_t *>(nameRefPtr); + if (info->O->isLittleEndian() != sys::IsLittleEndianHost) + sys::swapByteOrder(nameOff_32); + name = get_pointer_32(nameOff_32, xoffset, left, xS, info); + } + if (name != nullptr) + outs() << format(" %.*s", left, name); + } + } + outs() << "\n"; + + outs() << indent << "\t\t types " << format("0x%" PRIx32, m.types); + uint64_t relTypesVA = p + offsetof(struct method_relative_t, types); + uint64_t absTypesVA = relTypesVA + m.types; + outs() << " (" << format("0x%" PRIx32, absTypesVA) << ")"; + name = get_pointer_32(absTypesVA, xoffset, left, xS, info); + if (name != nullptr) + outs() << format(" %.*s", left, name); + outs() << "\n"; + + outs() << indent << "\t\t imp " << format("0x%" PRIx32, m.imp); + uint64_t relImpVA = p + offsetof(struct method_relative_t, imp); + uint64_t absImpVA = relImpVA + m.imp; + outs() << " (" << format("0x%" PRIx32, absImpVA) << ")"; + name = GuessSymbolName(absImpVA, info->AddrMap); + if (name != nullptr) + outs() << " " << name; + outs() << "\n"; + + p += sizeof(struct method_relative_t); + offset += sizeof(struct method_relative_t); + } +} + static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info, const char *indent) { struct method_list64_t ml; @@ -4461,10 +4559,17 @@ static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info, memcpy(&ml, r, sizeof(struct method_list64_t)); if (info->O->isLittleEndian() != sys::IsLittleEndianHost) swapStruct(ml); + p += sizeof(struct method_list64_t); + + if ((ml.entsize & ML_HAS_RELATIVE_PTRS) != 0) { + print_relative_method_list(ml.entsize, ml.count, p, info, indent, + /*pointerBits=*/64); + return; + } + outs() << indent << "\t\t entsize " << ml.entsize << "\n"; outs() << indent << "\t\t count " << ml.count << "\n"; - p += sizeof(struct method_list64_t); offset += sizeof(struct method_list64_t); for (i = 0; i < ml.count; i++) { r = get_pointer_64(p, offset, left, S, info); @@ -4552,10 +4657,17 @@ static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info, memcpy(&ml, r, sizeof(struct method_list32_t)); if (info->O->isLittleEndian() != sys::IsLittleEndianHost) swapStruct(ml); + p += sizeof(struct method_list32_t); + + if ((ml.entsize & ML_HAS_RELATIVE_PTRS) != 0) { + print_relative_method_list(ml.entsize, ml.count, p, info, indent, + /*pointerBits=*/32); + return; + } + outs() << indent << "\t\t entsize " << ml.entsize << "\n"; outs() << indent << "\t\t count " << ml.count << "\n"; - p += sizeof(struct method_list32_t); offset += sizeof(struct method_list32_t); for (i = 0; i < ml.count; i++) { r = get_pointer_32(p, offset, left, S, info); diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index 78cf67b1e630bb6bebf3f8acb782fced3d540e29..9b65ea5a99e4d889204098e0a72305fc9af22a6e 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -2115,13 +2115,6 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj, formatted_raw_ostream FOS(outs()); - // FIXME: Workaround for bug in formatted_raw_ostream. Color escape codes - // are (incorrectly) written directly to the unbuffered raw_ostream - // wrapped by the formatted_raw_ostream. - if (DisassemblyColor == ColorOutput::Enable || - DisassemblyColor == ColorOutput::Auto) - FOS.SetUnbuffered(); - std::unordered_map<uint64_t, std::string> AllLabels; std::unordered_map<uint64_t, std::vector<BBAddrMapLabel>> BBAddrMapLabels; if (SymbolizeOperands) { diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp index 3a7bd061d3d23a141a4695015903b232b8a8a54b..0b78564ccea379e852b96b8672aa20999933a50d 100644 --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -300,6 +300,13 @@ cl::opt<bool> DoWritePrevVersion( cl::desc("Write the previous version of indexed format, to enable " "some forward compatibility.")); +cl::opt<memprof::IndexedVersion> MemProfVersionRequested( + "memprof-version", cl::Hidden, cl::sub(MergeSubcommand), + cl::desc("Specify the version of the memprof format to use"), + cl::init(memprof::Version0), + cl::values(clEnumValN(memprof::Version0, "0", "version 0"), + clEnumValN(memprof::Version1, "1", "version 1"))); + // Options specific to overlap subcommand. cl::opt<std::string> BaseFilename(cl::Positional, cl::Required, cl::desc("<base profile file>"), @@ -354,6 +361,9 @@ cl::opt<bool> ShowIndirectCallTargets( "ic-targets", cl::init(false), cl::desc("Show indirect call site target values for shown functions"), cl::sub(ShowSubcommand)); +cl::opt<bool> ShowVTables("show-vtables", cl::init(false), + cl::desc("Show vtable names for shown functions"), + cl::sub(ShowSubcommand)); cl::opt<bool> ShowMemOPSizes( "memop-sizes", cl::init(false), cl::desc("Show the profiled sizes of the memory intrinsic calls " @@ -588,7 +598,8 @@ struct WriterContext { WriterContext(bool IsSparse, std::mutex &ErrLock, SmallSet<instrprof_error, 4> &WriterErrorCodes, uint64_t ReservoirSize = 0, uint64_t MaxTraceLength = 0) - : Writer(IsSparse, ReservoirSize, MaxTraceLength, DoWritePrevVersion), + : Writer(IsSparse, ReservoirSize, MaxTraceLength, DoWritePrevVersion, + MemProfVersionRequested), ErrLock(ErrLock), WriterErrorCodes(WriterErrorCodes) {} }; @@ -731,6 +742,13 @@ static void loadInput(const WeightedFile &Input, SymbolRemapper *Remapper, }); } + const InstrProfSymtab &symtab = Reader->getSymtab(); + const auto &VTableNames = symtab.getVTableNames(); + + for (const auto &kv : VTableNames) { + WC->Writer.addVTableName(kv.getKey()); + } + if (Reader->hasTemporalProfile()) { auto &Traces = Reader->getTemporalProfTraces(Input.Weight); if (!Traces.empty()) @@ -2826,6 +2844,10 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) { OS << " Indirect Call Site Count: " << Func.getNumValueSites(IPVK_IndirectCallTarget) << "\n"; + if (ShowVTables) + OS << " Number of instrumented vtables: " + << Func.getNumValueSites(IPVK_VTableTarget) << "\n"; + uint32_t NumMemOPCalls = Func.getNumValueSites(IPVK_MemOPSize); if (ShowMemOPSizes && NumMemOPCalls > 0) OS << " Number of Memory Intrinsics Calls: " << NumMemOPCalls @@ -2847,6 +2869,13 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) { &(Reader->getSymtab())); } + if (ShowVTables) { + OS << " VTable Results:\n"; + traverseAllValueSites(Func, IPVK_VTableTarget, + VPStats[IPVK_VTableTarget], OS, + &(Reader->getSymtab())); + } + if (ShowMemOPSizes && NumMemOPCalls > 0) { OS << " Memory Intrinsic Size Results:\n"; traverseAllValueSites(Func, IPVK_MemOPSize, VPStats[IPVK_MemOPSize], OS, @@ -2895,6 +2924,11 @@ static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) { VPStats[IPVK_IndirectCallTarget]); } + if (ShownFunctions && ShowVTables) { + OS << "Statistics for vtable profile:\n"; + showValueSitesStats(OS, IPVK_VTableTarget, VPStats[IPVK_VTableTarget]); + } + if (ShownFunctions && ShowMemOPSizes) { OS << "Statistics for memory intrinsic calls sizes profile:\n"; showValueSitesStats(OS, IPVK_MemOPSize, VPStats[IPVK_MemOPSize]); diff --git a/llvm/tools/llvm-profgen/PerfReader.cpp b/llvm/tools/llvm-profgen/PerfReader.cpp index c6fcf7e1196ec8e1a8da70df17f9eb07f6ab9913..878147642aa6e7c5dfdd48cb26a8d1fcbf27f379 100644 --- a/llvm/tools/llvm-profgen/PerfReader.cpp +++ b/llvm/tools/llvm-profgen/PerfReader.cpp @@ -408,9 +408,22 @@ PerfScriptReader::convertPerfDataToTrace(ProfiledBinary *Binary, PerfContent::UnknownContent}; } +static StringRef filename(StringRef Path, bool UseBackSlash) { + llvm::sys::path::Style PathStyle = + UseBackSlash ? llvm::sys::path::Style::windows_backslash + : llvm::sys::path::Style::native; + StringRef FileName = llvm::sys::path::filename(Path, PathStyle); + + // In case this file use \r\n as newline. + if (UseBackSlash && FileName.back() == '\r') + return FileName.drop_back(); + + return FileName; +} + void PerfScriptReader::updateBinaryAddress(const MMapEvent &Event) { // Drop the event which doesn't belong to user-provided binary - StringRef BinaryName = llvm::sys::path::filename(Event.BinaryPath); + StringRef BinaryName = filename(Event.BinaryPath, Binary->isCOFF()); if (Binary->getName() != BinaryName) return; @@ -975,7 +988,7 @@ bool PerfScriptReader::extractMMap2EventForBinary(ProfiledBinary *Binary, << format("0x%" PRIx64 ":", MMap.Address) << " \n"; } - StringRef BinaryName = llvm::sys::path::filename(MMap.BinaryPath); + StringRef BinaryName = filename(MMap.BinaryPath, Binary->isCOFF()); return Binary->getName() == BinaryName; } diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/llvm/tools/llvm-profgen/ProfiledBinary.cpp index f62228627b8f1e2b5c4962a1cd21bdd7195c20fc..1baf35820f97fa7b0ef005df0f16cc94110869d4 100644 --- a/llvm/tools/llvm-profgen/ProfiledBinary.cpp +++ b/llvm/tools/llvm-profgen/ProfiledBinary.cpp @@ -14,6 +14,7 @@ #include "llvm/Demangle/Demangle.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/MC/TargetRegistry.h" +#include "llvm/Object/COFF.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" @@ -211,10 +212,11 @@ void ProfiledBinary::load() { OwningBinary<Binary> OBinary = unwrapOrError(createBinary(Path), Path); Binary &ExeBinary = *OBinary.getBinary(); - auto *Obj = dyn_cast<ELFObjectFileBase>(&ExeBinary); - if (!Obj) - exitWithError("not a valid Elf image", Path); + IsCOFF = isa<COFFObjectFile>(&ExeBinary); + if (!isa<ELFObjectFileBase>(&ExeBinary) && !IsCOFF) + exitWithError("not a valid ELF/COFF image", Path); + auto *Obj = cast<ObjectFile>(&ExeBinary); TheTriple = Obj->makeTriple(); LLVM_DEBUG(dbgs() << "Loading " << Path << "\n"); @@ -236,13 +238,14 @@ void ProfiledBinary::load() { DisassembleFunctionSet.insert(DisassembleFunctions.begin(), DisassembleFunctions.end()); - checkPseudoProbe(Obj); + if (auto *ELFObj = dyn_cast<ELFObjectFileBase>(Obj)) { + checkPseudoProbe(ELFObj); + if (UsePseudoProbes) + populateElfSymbolAddressList(ELFObj); - if (UsePseudoProbes) - populateElfSymbolAddressList(Obj); - - if (ShowDisassemblyOnly) - decodePseudoProbe(Obj); + if (ShowDisassemblyOnly) + decodePseudoProbe(ELFObj); + } // Disassemble the text sections. disassemble(Obj); @@ -335,18 +338,35 @@ void ProfiledBinary::setPreferredTextSegmentAddresses(const ELFFile<ELFT> &Obj, exitWithError("no executable segment found", FileName); } -void ProfiledBinary::setPreferredTextSegmentAddresses( - const ELFObjectFileBase *Obj) { +void ProfiledBinary::setPreferredTextSegmentAddresses(const COFFObjectFile *Obj, + StringRef FileName) { + uint64_t ImageBase = Obj->getImageBase(); + if (!ImageBase) + exitWithError("Not a COFF image", FileName); + + PreferredTextSegmentAddresses.push_back(ImageBase); + FirstLoadableAddress = ImageBase; + + for (SectionRef Section : Obj->sections()) { + const coff_section *Sec = Obj->getCOFFSection(Section); + if (Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE) + TextSegmentOffsets.push_back(Sec->VirtualAddress); + } +} + +void ProfiledBinary::setPreferredTextSegmentAddresses(const ObjectFile *Obj) { if (const auto *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) setPreferredTextSegmentAddresses(ELFObj->getELFFile(), Obj->getFileName()); else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) setPreferredTextSegmentAddresses(ELFObj->getELFFile(), Obj->getFileName()); else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) setPreferredTextSegmentAddresses(ELFObj->getELFFile(), Obj->getFileName()); - else if (const auto *ELFObj = cast<ELF64BEObjectFile>(Obj)) + else if (const auto *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) setPreferredTextSegmentAddresses(ELFObj->getELFFile(), Obj->getFileName()); + else if (const auto *COFFObj = dyn_cast<COFFObjectFile>(Obj)) + setPreferredTextSegmentAddresses(COFFObj, Obj->getFileName()); else - llvm_unreachable("invalid ELF object format"); + llvm_unreachable("invalid object format"); } void ProfiledBinary::checkPseudoProbe(const ELFObjectFileBase *Obj) { @@ -442,7 +462,7 @@ void ProfiledBinary::decodePseudoProbe(const ELFObjectFileBase *Obj) { void ProfiledBinary::decodePseudoProbe() { OwningBinary<Binary> OBinary = unwrapOrError(createBinary(Path), Path); Binary &ExeBinary = *OBinary.getBinary(); - auto *Obj = dyn_cast<ELFObjectFileBase>(&ExeBinary); + auto *Obj = cast<ELFObjectFileBase>(&ExeBinary); decodePseudoProbe(Obj); } @@ -593,7 +613,7 @@ bool ProfiledBinary::dissassembleSymbol(std::size_t SI, ArrayRef<uint8_t> Bytes, return true; } -void ProfiledBinary::setUpDisassembler(const ELFObjectFileBase *Obj) { +void ProfiledBinary::setUpDisassembler(const ObjectFile *Obj) { const Target *TheTarget = getTarget(Obj); std::string TripleName = TheTriple.getTriple(); StringRef FileName = Obj->getFileName(); @@ -635,7 +655,7 @@ void ProfiledBinary::setUpDisassembler(const ELFObjectFileBase *Obj) { IPrinter->setPrintBranchImmAsAddress(true); } -void ProfiledBinary::disassemble(const ELFObjectFileBase *Obj) { +void ProfiledBinary::disassemble(const ObjectFile *Obj) { // Set up disassembler and related components. setUpDisassembler(Obj); @@ -687,7 +707,7 @@ void ProfiledBinary::disassemble(const ELFObjectFileBase *Obj) { << "]:\n\n"; } - if (SectionName == ".plt") + if (isa<ELFObjectFileBase>(Obj) && SectionName == ".plt") continue; // Get the section data. @@ -722,8 +742,7 @@ void ProfiledBinary::disassemble(const ELFObjectFileBase *Obj) { } void ProfiledBinary::checkUseFSDiscriminator( - const ELFObjectFileBase *Obj, - std::map<SectionRef, SectionSymbolsTy> &AllSymbols) { + const ObjectFile *Obj, std::map<SectionRef, SectionSymbolsTy> &AllSymbols) { const char *FSDiscriminatorVar = "__llvm_fs_discriminator__"; for (section_iterator SI = Obj->section_begin(), SE = Obj->section_end(); SI != SE; ++SI) { diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.h b/llvm/tools/llvm-profgen/ProfiledBinary.h index 0fd12f5acd6b48a876b6d92631a50f5d0b1b775b..5d2088ad7691c406f30595d69c2d6966df93ff87 100644 --- a/llvm/tools/llvm-profgen/ProfiledBinary.h +++ b/llvm/tools/llvm-profgen/ProfiledBinary.h @@ -297,22 +297,26 @@ class ProfiledBinary { // Use to avoid redundant warning. bool MissingMMapWarned = false; - void setPreferredTextSegmentAddresses(const ELFObjectFileBase *O); + bool IsCOFF = false; + + void setPreferredTextSegmentAddresses(const ObjectFile *O); template <class ELFT> void setPreferredTextSegmentAddresses(const ELFFile<ELFT> &Obj, StringRef FileName); + void setPreferredTextSegmentAddresses(const COFFObjectFile *Obj, + StringRef FileName); void checkPseudoProbe(const ELFObjectFileBase *Obj); void decodePseudoProbe(const ELFObjectFileBase *Obj); void - checkUseFSDiscriminator(const ELFObjectFileBase *Obj, + checkUseFSDiscriminator(const ObjectFile *Obj, std::map<SectionRef, SectionSymbolsTy> &AllSymbols); // Set up disassembler and related components. - void setUpDisassembler(const ELFObjectFileBase *Obj); + void setUpDisassembler(const ObjectFile *Obj); symbolize::LLVMSymbolizer::Options getSymbolizerOpts() const; // Load debug info of subprograms from DWARF section. @@ -333,7 +337,7 @@ class ProfiledBinary { void warnNoFuncEntry(); /// Dissassemble the text section and build various address maps. - void disassemble(const ELFObjectFileBase *O); + void disassemble(const ObjectFile *O); /// Helper function to dissassemble the symbol and extract info for unwinding bool dissassembleSymbol(std::size_t SI, ArrayRef<uint8_t> Bytes, @@ -362,6 +366,8 @@ public: uint64_t getBaseAddress() const { return BaseAddress; } void setBaseAddress(uint64_t Address) { BaseAddress = Address; } + bool isCOFF() const { return IsCOFF; } + // Canonicalize to use preferred load address as base address. uint64_t canonicalizeVirtualAddress(uint64_t Address) { return Address - BaseAddress + getPreferredBaseAddress(); diff --git a/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h b/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h index 2e89463e68d5190eb8b35289307b84d3ce860ef1..94a44e3afccb4300d95f8dc3984bad0218e737de 100644 --- a/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h +++ b/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h @@ -113,7 +113,7 @@ void PrinterContext<ELFT>::printEHFrameHdr(const Elf_Phdr *EHFramePHdr) const { if (!Content) reportError(Content.takeError(), ObjF.getFileName()); - DataExtractor DE(*Content, ELFT::TargetEndianness == llvm::endianness::little, + DataExtractor DE(*Content, ELFT::Endianness == llvm::endianness::little, ELFT::Is64Bits ? 8 : 4); DictScope D(W, "Header"); @@ -186,10 +186,9 @@ void PrinterContext<ELFT>::printEHFrame(const Elf_Shdr *EHFrameShdr) const { // Construct DWARFDataExtractor to handle relocations ("PC Begin" fields). std::unique_ptr<DWARFContext> DICtx = DWARFContext::create( ObjF, DWARFContext::ProcessDebugRelocations::Process, nullptr); - DWARFDataExtractor DE(DICtx->getDWARFObj(), - DICtx->getDWARFObj().getEHFrameSection(), - ELFT::TargetEndianness == llvm::endianness::little, - ELFT::Is64Bits ? 8 : 4); + DWARFDataExtractor DE( + DICtx->getDWARFObj(), DICtx->getDWARFObj().getEHFrameSection(), + ELFT::Endianness == llvm::endianness::little, ELFT::Is64Bits ? 8 : 4); DWARFDebugFrame EHFrame(Triple::ArchType(ObjF.getArch()), /*IsEH=*/true, /*EHFrameAddress=*/Address); if (Error E = EHFrame.parse(DE)) diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index e78732353cc8776385d93e89e5c2d3c30ecb8e72..4b406ef12aecfea5624e765a38b0c3f41d82295e 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -49,6 +49,7 @@ #include "llvm/Support/Format.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/HexagonAttributeParser.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/MSP430AttributeParser.h" #include "llvm/Support/MSP430Attributes.h" @@ -73,6 +74,7 @@ using namespace llvm; using namespace llvm::object; +using namespace llvm::support; using namespace ELF; #define LLVM_READOBJ_ENUM_CASE(ns, enum) \ @@ -2824,6 +2826,11 @@ template <typename ELFT> void ELFDumper<ELFT>::printLoadName() { template <class ELFT> void ELFDumper<ELFT>::printArchSpecificInfo() { switch (Obj.getHeader().e_machine) { + case EM_HEXAGON: + printAttributes(ELF::SHT_HEXAGON_ATTRIBUTES, + std::make_unique<HexagonAttributeParser>(&W), + llvm::endianness::little); + break; case EM_ARM: if (Obj.isLE()) printAttributes(ELF::SHT_ARM_ATTRIBUTES, @@ -3413,13 +3420,13 @@ template <class ELFT> void ELFDumper<ELFT>::printStackMap() const { return; } - if (Error E = StackMapParser<ELFT::TargetEndianness>::validateHeader( - *ContentOrErr)) { + if (Error E = + StackMapParser<ELFT::Endianness>::validateHeader(*ContentOrErr)) { Warn(std::move(E)); return; } - prettyPrintStackMap(W, StackMapParser<ELFT::TargetEndianness>(*ContentOrErr)); + prettyPrintStackMap(W, StackMapParser<ELFT::Endianness>(*ContentOrErr)); } template <class ELFT> @@ -5139,7 +5146,7 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize, OS << format("<corrupt length: 0x%x>", DataSize); return OS.str(); } - PrData = support::endian::read32<ELFT::TargetEndianness>(Data.data()); + PrData = endian::read32<ELFT::Endianness>(Data.data()); if (PrData == 0) { OS << "<None>"; return OS.str(); @@ -5163,7 +5170,7 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize, OS << format("<corrupt length: 0x%x>", DataSize); return OS.str(); } - PrData = support::endian::read32<ELFT::TargetEndianness>(Data.data()); + PrData = endian::read32<ELFT::Endianness>(Data.data()); if (PrData == 0) { OS << "<None>"; return OS.str(); @@ -5189,7 +5196,7 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize, OS << format("<corrupt length: 0x%x>", DataSize); return OS.str(); } - PrData = support::endian::read32<ELFT::TargetEndianness>(Data.data()); + PrData = endian::read32<ELFT::Endianness>(Data.data()); if (PrData == 0) { OS << "<None>"; return OS.str(); @@ -5368,10 +5375,8 @@ static bool printAArch64Note(raw_ostream &OS, uint32_t NoteType, return false; } - uint64_t Platform = - support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 0); - uint64_t Version = - support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 8); + uint64_t Platform = endian::read64<ELFT::Endianness>(Desc.data() + 0); + uint64_t Version = endian::read64<ELFT::Endianness>(Desc.data() + 8); OS << format("platform 0x%" PRIx64 ", version 0x%" PRIx64, Platform, Version); if (Desc.size() > 16) @@ -5451,16 +5456,14 @@ getFreeBSDNote(uint32_t NoteType, ArrayRef<uint8_t> Desc, bool IsCore) { case ELF::NT_FREEBSD_ABI_TAG: if (Desc.size() != 4) return std::nullopt; - return FreeBSDNote{ - "ABI tag", - utostr(support::endian::read32<ELFT::TargetEndianness>(Desc.data()))}; + return FreeBSDNote{"ABI tag", + utostr(endian::read32<ELFT::Endianness>(Desc.data()))}; case ELF::NT_FREEBSD_ARCH_TAG: return FreeBSDNote{"Arch tag", toStringRef(Desc).str()}; case ELF::NT_FREEBSD_FEATURE_CTL: { if (Desc.size() != 4) return std::nullopt; - unsigned Value = - support::endian::read32<ELFT::TargetEndianness>(Desc.data()); + unsigned Value = endian::read32<ELFT::Endianness>(Desc.data()); std::string FlagsStr; raw_string_ostream OS(FlagsStr); printFlags(Value, ArrayRef(FreeBSDFeatureCtlFlags), OS); @@ -6047,7 +6050,7 @@ template <class ELFT> void GNUELFDumper<ELFT>::printNotes() { } else if (Name == "CORE") { if (Type == ELF::NT_FILE) { DataExtractor DescExtractor( - Descriptor, ELFT::TargetEndianness == llvm::endianness::little, + Descriptor, ELFT::Endianness == llvm::endianness::little, sizeof(Elf_Addr)); if (Expected<CoreNote> NoteOrErr = readCoreNote(DescExtractor)) { printCoreNote<ELFT>(OS, *NoteOrErr); @@ -7708,10 +7711,8 @@ static bool printAarch64NoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc, if (Desc.size() < 16) return false; - uint64_t platform = - support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 0); - uint64_t version = - support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 8); + uint64_t platform = endian::read64<ELFT::Endianness>(Desc.data() + 0); + uint64_t version = endian::read64<ELFT::Endianness>(Desc.data() + 8); W.printNumber("Platform", platform); W.printNumber("Version", version); @@ -7846,7 +7847,7 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() { } else if (Name == "CORE") { if (Type == ELF::NT_FILE) { DataExtractor DescExtractor( - Descriptor, ELFT::TargetEndianness == llvm::endianness::little, + Descriptor, ELFT::Endianness == llvm::endianness::little, sizeof(Elf_Addr)); if (Expected<CoreNote> N = readCoreNote(DescExtractor)) { printCoreNoteLLVMStyle(*N, W); diff --git a/llvm/tools/llvm-readobj/ObjDumper.cpp b/llvm/tools/llvm-readobj/ObjDumper.cpp index 0d3fea71aafd42903d7f36ea4cc8fcda2ab63212..0980d2ad3a852b3d1c71934042d5317ed9634978 100644 --- a/llvm/tools/llvm-readobj/ObjDumper.cpp +++ b/llvm/tools/llvm-readobj/ObjDumper.cpp @@ -160,15 +160,10 @@ void ObjDumper::printSectionsAsString(const object::ObjectFile &Obj, ArrayRef<std::string> Sections, bool Decompress) { SmallString<0> Out; - bool First = true; for (object::SectionRef Section : getSectionRefsByNameOrIndex(Obj, Sections)) { StringRef SectionName = unwrapOrError(Obj.getFileName(), Section.getName()); - - if (!First) - W.startLine() << '\n'; - First = false; - W.startLine() << "String dump of section '" << SectionName << "':\n"; + W.startLine() << "\nString dump of section '" << SectionName << "':\n"; StringRef SectionContent = unwrapOrError(Obj.getFileName(), Section.getContents()); @@ -182,15 +177,10 @@ void ObjDumper::printSectionsAsHex(const object::ObjectFile &Obj, ArrayRef<std::string> Sections, bool Decompress) { SmallString<0> Out; - bool First = true; for (object::SectionRef Section : getSectionRefsByNameOrIndex(Obj, Sections)) { StringRef SectionName = unwrapOrError(Obj.getFileName(), Section.getName()); - - if (!First) - W.startLine() << '\n'; - First = false; - W.startLine() << "Hex dump of section '" << SectionName << "':\n"; + W.startLine() << "\nHex dump of section '" << SectionName << "':\n"; StringRef SectionContent = unwrapOrError(Obj.getFileName(), Section.getContents()); diff --git a/llvm/tools/llvm-reduce/deltas/ReduceDbgRecords.cpp b/llvm/tools/llvm-reduce/deltas/ReduceDbgRecords.cpp index 2f3d4cac9fa015b3ad3c33531c1d284b4c1f624d..25de659109c9f09507f8817f1ac3ae7645e54d37 100644 --- a/llvm/tools/llvm-reduce/deltas/ReduceDbgRecords.cpp +++ b/llvm/tools/llvm-reduce/deltas/ReduceDbgRecords.cpp @@ -7,13 +7,13 @@ //===----------------------------------------------------------------------===// // // This file implements a function which calls the Generic Delta pass in order -// to reduce uninteresting DPValues from defined functions. +// to reduce uninteresting DbgVariableRecords from defined functions. // -// DPValues store variable-location debug-info and are attached to instructions. -// This information used to be represented by intrinsics such as dbg.value, and -// would naturally get reduced by llvm-reduce like any other instruction. As -// DPValues get stored elsewhere, they need to be enumerated and eliminated like -// any other data structure in LLVM. +// DbgVariableRecords store variable-location debug-info and are attached to +// instructions. This information used to be represented by intrinsics such as +// dbg.value, and would naturally get reduced by llvm-reduce like any other +// instruction. As DbgVariableRecords get stored elsewhere, they need to be +// enumerated and eliminated like any other data structure in LLVM. // //===----------------------------------------------------------------------===// diff --git a/llvm/tools/llvm-reduce/deltas/ReduceDbgRecords.h b/llvm/tools/llvm-reduce/deltas/ReduceDbgRecords.h index 6a8f62155ec3e2f81a51b9b67980eb5858ffee7a..07a1e04fceaeecb9b4580dec1b5bccd97c612140 100644 --- a/llvm/tools/llvm-reduce/deltas/ReduceDbgRecords.h +++ b/llvm/tools/llvm-reduce/deltas/ReduceDbgRecords.h @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// // // This file implements a function which calls the Generic Delta pass in order -// to reduce uninteresting DPValues from defined functions. +// to reduce uninteresting DbgVariableRecords from defined functions. // //===----------------------------------------------------------------------===// diff --git a/llvm/tools/llvm-shlib/CMakeLists.txt b/llvm/tools/llvm-shlib/CMakeLists.txt index eba1672faee7fad7bd8719d60ee7b02ce8a055e0..b20ac318e768dbb63702ce16dd8e0e4ed9f04a5c 100644 --- a/llvm/tools/llvm-shlib/CMakeLists.txt +++ b/llvm/tools/llvm-shlib/CMakeLists.txt @@ -33,10 +33,13 @@ if(LLVM_BUILD_LLVM_DYLIB) if (LLVM_LINK_LLVM_DYLIB) set(INSTALL_WITH_TOOLCHAIN INSTALL_WITH_TOOLCHAIN) endif() - add_llvm_library(LLVM SHARED DISABLE_LLVM_LINK_LLVM_DYLIB OUTPUT_NAME LLVM ${INSTALL_WITH_TOOLCHAIN} ${SOURCES}) - # Add symlink for backwards compatibility with old library name - get_target_property(LLVM_DYLIB_SOVERSION LLVM SOVERSION) - llvm_install_library_symlink(LLVM-${LLVM_VERSION_MAJOR}${LLVM_VERSION_SUFFIX} LLVM SHARED COMPONENT LLVM SOVERSION ${LLVM_DYLIB_SOVERSION}) + if (WIN32) + add_llvm_library(LLVM SHARED DISABLE_LLVM_LINK_LLVM_DYLIB SONAME ${INSTALL_WITH_TOOLCHAIN} ${SOURCES}) + else() + add_llvm_library(LLVM SHARED DISABLE_LLVM_LINK_LLVM_DYLIB OUTPUT_NAME LLVM ${INSTALL_WITH_TOOLCHAIN} ${SOURCES}) + # Add symlink for backwards compatibility with old library name + llvm_install_library_symlink(LLVM-${LLVM_VERSION_MAJOR}${LLVM_VERSION_SUFFIX} $<TARGET_FILE_NAME:LLVM> SHARED FULL_DEST COMPONENT LLVM) + endif() list(REMOVE_DUPLICATES LIB_NAMES) if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin") diff --git a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp index 69d9b9a2f784f79133dd854397d0d825301013eb..ec4f5c74498f8559f6635db8202279fe44dd0ba5 100644 --- a/llvm/tools/obj2yaml/dxcontainer2yaml.cpp +++ b/llvm/tools/obj2yaml/dxcontainer2yaml.cpp @@ -99,6 +99,9 @@ dumpDXContainer(MemoryBufferRef Source) { else if (const auto *P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&PSVInfo->getInfo())) NewPart.Info = DXContainerYAML::PSVInfo(P); + else if (const auto *P = + std::get_if<dxbc::PSV::v3::RuntimeInfo>(&PSVInfo->getInfo())) + NewPart.Info = DXContainerYAML::PSVInfo(P, PSVInfo->getStringTable()); NewPart.Info->ResourceStride = PSVInfo->getResourceStride(); for (auto Res : PSVInfo->getResources()) NewPart.Info->Resources.push_back(Res); diff --git a/llvm/tools/spirv-tools/CMakeLists.txt b/llvm/tools/spirv-tools/CMakeLists.txt index f73dcadd9f86ac204bcba7624ae624d79a49f59e..c0d4556de4c62dc9a43d4bad6ca67d2a65675292 100644 --- a/llvm/tools/spirv-tools/CMakeLists.txt +++ b/llvm/tools/spirv-tools/CMakeLists.txt @@ -49,7 +49,7 @@ if (SPIRV_DIS) COMMAND ${CMAKE_COMMAND} -E ${LLVM_LINK_OR_COPY} "${SPIRV_DIS}" "${LLVM_RUNTIME_OUTPUT_INTDIR}/spirv-dis") else () add_custom_target(spirv-dis - COMMAND ${CMAKE_COMMAND} -E ${LLVM_LINK_OR_COPY} "${BINARY_DIR}/tools/spirv-dis" "${LLVM_RUNTIME_OUTPUT_INTDIR}/spirv-dis" + COMMAND ${CMAKE_COMMAND} -E ${LLVM_LINK_OR_COPY} "${BINARY_DIR}/tools/spirv-dis${CMAKE_EXECUTABLE_SUFFIX}" "${LLVM_RUNTIME_OUTPUT_INTDIR}/spirv-dis${CMAKE_EXECUTABLE_SUFFIX}" DEPENDS SPIRVTools ) endif () @@ -59,7 +59,7 @@ if (SPIRV_VAL) COMMAND ${CMAKE_COMMAND} -E ${LLVM_LINK_OR_COPY} "${SPIRV_VAL}" "${LLVM_RUNTIME_OUTPUT_INTDIR}/spirv-val") else () add_custom_target(spirv-val - COMMAND ${CMAKE_COMMAND} -E ${LLVM_LINK_OR_COPY} "${BINARY_DIR}/tools/spirv-val" "${LLVM_RUNTIME_OUTPUT_INTDIR}/spirv-val" + COMMAND ${CMAKE_COMMAND} -E ${LLVM_LINK_OR_COPY} "${BINARY_DIR}/tools/spirv-val${CMAKE_EXECUTABLE_SUFFIX}" "${LLVM_RUNTIME_OUTPUT_INTDIR}/spirv-val${CMAKE_EXECUTABLE_SUFFIX}" DEPENDS SPIRVTools ) endif () diff --git a/llvm/tools/verify-uselistorder/verify-uselistorder.cpp b/llvm/tools/verify-uselistorder/verify-uselistorder.cpp index 9afe6817fefb9f7f6fb7b7e0ab931c3c617844a6..cb07dede1d1374300c10e0e7c0b46606e4b87d0c 100644 --- a/llvm/tools/verify-uselistorder/verify-uselistorder.cpp +++ b/llvm/tools/verify-uselistorder/verify-uselistorder.cpp @@ -68,6 +68,8 @@ static cl::opt<unsigned> cl::desc("Number of times to shuffle and verify use-lists"), cl::init(1), cl::cat(Cat)); +extern cl::opt<cl::boolOrDefault> LoadBitcodeIntoNewDbgInfoFormat; + namespace { struct TempFile { @@ -166,6 +168,10 @@ std::unique_ptr<Module> TempFile::readBitcode(LLVMContext &Context) const { "verify-uselistorder: error: "); return nullptr; } + + // verify-uselistoder currently only supports old-style debug info mode. + // FIXME: Update mapping code for RemoveDIs. + ModuleOr.get()->setIsNewDbgInfoFormat(false); return std::move(ModuleOr.get()); } @@ -175,6 +181,9 @@ std::unique_ptr<Module> TempFile::readAssembly(LLVMContext &Context) const { std::unique_ptr<Module> M = parseAssemblyFile(Filename, Err, Context); if (!M.get()) Err.print("verify-uselistorder", errs()); + // verify-uselistoder currently only supports old-style debug info mode. + // FIXME: Update mapping code for RemoveDIs. + M->setIsNewDbgInfoFormat(false); return M; } @@ -536,11 +545,18 @@ int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, "llvm tool to verify use-list order\n"); + // Do not load bitcode into the new debug info format by default. + if (LoadBitcodeIntoNewDbgInfoFormat == cl::boolOrDefault::BOU_UNSET) + LoadBitcodeIntoNewDbgInfoFormat = cl::boolOrDefault::BOU_FALSE; + LLVMContext Context; SMDiagnostic Err; // Load the input module... std::unique_ptr<Module> M = parseIRFile(InputFilename, Err, Context); + // verify-uselistoder currently only supports old-style debug info mode. + // FIXME: Update mapping code for RemoveDIs. + M->setIsNewDbgInfoFormat(false); if (!M.get()) { Err.print(argv[0], errs()); diff --git a/llvm/unittests/ADT/APIntTest.cpp b/llvm/unittests/ADT/APIntTest.cpp index 11237d2e1602dc0866d0ea53ace5506688dd0a78..d5ef63e38e2790a32b83e866725e07f1f19e74be 100644 --- a/llvm/unittests/ADT/APIntTest.cpp +++ b/llvm/unittests/ADT/APIntTest.cpp @@ -14,6 +14,8 @@ #include "llvm/Support/Alignment.h" #include "gtest/gtest.h" #include <array> +#include <climits> +#include <limits> #include <optional> using namespace llvm; @@ -2839,6 +2841,58 @@ TEST(APIntTest, multiply) { EXPECT_EQ(64U, i96.countr_zero()); } +TEST(APIntOpsTest, Mulh) { + + // Unsigned + + // 32 bits + APInt i32a(32, 0x0001'E235); + APInt i32b(32, 0xF623'55AD); + EXPECT_EQ(0x0001'CFA1, APIntOps::mulhu(i32a, i32b)); + + // 64 bits + APInt i64a(64, 0x1234'5678'90AB'CDEF); + APInt i64b(64, 0xFEDC'BA09'8765'4321); + EXPECT_EQ(0x121F'A000'A372'3A57, APIntOps::mulhu(i64a, i64b)); + + // 128 bits + APInt i128a(128, "1234567890ABCDEF1234567890ABCDEF", 16); + APInt i128b(128, "FEDCBA0987654321FEDCBA0987654321", 16); + APInt i128Res = APIntOps::mulhu(i128a, i128b); + EXPECT_EQ(APInt(128, "121FA000A3723A57E68984312C3A8D7E", 16), i128Res); + + // Signed + + // 32 bits + APInt i32c(32, 0x1234'5678); // +ve + APInt i32d(32, 0x10AB'CDEF); // +ve + APInt i32e(32, 0xFEDC'BA09); // -ve + + EXPECT_EQ(0x012F'7D02, APIntOps::mulhs(i32c, i32d)); + EXPECT_EQ(0xFFEB'4988, APIntOps::mulhs(i32c, i32e)); + EXPECT_EQ(0x0001'4B68, APIntOps::mulhs(i32e, i32e)); + + // 64 bits + APInt i64c(64, 0x1234'5678'90AB'CDEF); // +ve + APInt i64d(64, 0x1234'5678'90FE'DCBA); // +ve + APInt i64e(64, 0xFEDC'BA09'8765'4321); // -ve + + EXPECT_EQ(0x014B'66DC'328E'10C1, APIntOps::mulhs(i64c, i64d)); + EXPECT_EQ(0xFFEB'4988'12C6'6C68, APIntOps::mulhs(i64c, i64e)); + EXPECT_EQ(0x0001'4B68'2174'FA18, APIntOps::mulhs(i64e, i64e)); + + // 128 bits + APInt i128c(128, "1234567890ABCDEF1234567890ABCDEF", 16); // +ve + APInt i128d(128, "1234567890FEDCBA1234567890FEDCBA", 16); // +ve + APInt i128e(128, "FEDCBA0987654321FEDCBA0987654321", 16); // -ve + + i128Res = APIntOps::mulhs(i128c, i128d); + EXPECT_EQ(APInt(128, "14B66DC328E10C1FE303DF9EA0B2529", 16), i128Res); + + i128Res = APIntOps::mulhs(i128c, i128e); + EXPECT_EQ(APInt(128, "FFEB498812C66C68D4552DB89B8EBF8F", 16), i128Res); +} + TEST(APIntTest, RoundingUDiv) { for (uint64_t Ai = 1; Ai <= 255; Ai++) { APInt A(8, Ai); @@ -2911,6 +2965,91 @@ TEST(APIntTest, RoundingSDiv) { } } +TEST(APIntTest, Average) { + APInt A0(32, 0); + APInt A2(32, 2); + APInt A100(32, 100); + APInt A101(32, 101); + APInt A200(32, 200, false); + APInt ApUMax = APInt::getMaxValue(32); + + EXPECT_EQ(APInt(32, 150), APIntOps::avgFloorU(A100, A200)); + EXPECT_EQ(APIntOps::RoundingUDiv(A100 + A200, A2, APInt::Rounding::DOWN), + APIntOps::avgFloorU(A100, A200)); + EXPECT_EQ(APIntOps::RoundingUDiv(A100 + A200, A2, APInt::Rounding::UP), + APIntOps::avgCeilU(A100, A200)); + EXPECT_EQ(APIntOps::RoundingUDiv(A100 + A101, A2, APInt::Rounding::DOWN), + APIntOps::avgFloorU(A100, A101)); + EXPECT_EQ(APIntOps::RoundingUDiv(A100 + A101, A2, APInt::Rounding::UP), + APIntOps::avgCeilU(A100, A101)); + EXPECT_EQ(A0, APIntOps::avgFloorU(A0, A0)); + EXPECT_EQ(A0, APIntOps::avgCeilU(A0, A0)); + EXPECT_EQ(ApUMax, APIntOps::avgFloorU(ApUMax, ApUMax)); + EXPECT_EQ(ApUMax, APIntOps::avgCeilU(ApUMax, ApUMax)); + EXPECT_EQ(APIntOps::RoundingUDiv(ApUMax, A2, APInt::Rounding::DOWN), + APIntOps::avgFloorU(A0, ApUMax)); + EXPECT_EQ(APIntOps::RoundingUDiv(ApUMax, A2, APInt::Rounding::UP), + APIntOps::avgCeilU(A0, ApUMax)); + + APInt Ap100(32, +100); + APInt Ap101(32, +101); + APInt Ap200(32, +200); + APInt Am1(32, -1); + APInt Am100(32, -100); + APInt Am101(32, -101); + APInt Am200(32, -200); + APInt AmSMin = APInt::getSignedMinValue(32); + APInt ApSMax = APInt::getSignedMaxValue(32); + + EXPECT_EQ(APInt(32, +150), APIntOps::avgFloorS(Ap100, Ap200)); + EXPECT_EQ(APIntOps::RoundingSDiv(Ap100 + Ap200, A2, APInt::Rounding::DOWN), + APIntOps::avgFloorS(Ap100, Ap200)); + EXPECT_EQ(APIntOps::RoundingSDiv(Ap100 + Ap200, A2, APInt::Rounding::UP), + APIntOps::avgCeilS(Ap100, Ap200)); + + EXPECT_EQ(APInt(32, -150), APIntOps::avgFloorS(Am100, Am200)); + EXPECT_EQ(APIntOps::RoundingSDiv(Am100 + Am200, A2, APInt::Rounding::DOWN), + APIntOps::avgFloorS(Am100, Am200)); + EXPECT_EQ(APIntOps::RoundingSDiv(Am100 + Am200, A2, APInt::Rounding::UP), + APIntOps::avgCeilS(Am100, Am200)); + + EXPECT_EQ(APInt(32, +100), APIntOps::avgFloorS(Ap100, Ap101)); + EXPECT_EQ(APIntOps::RoundingSDiv(Ap100 + Ap101, A2, APInt::Rounding::DOWN), + APIntOps::avgFloorS(Ap100, Ap101)); + EXPECT_EQ(APInt(32, +101), APIntOps::avgCeilS(Ap100, Ap101)); + EXPECT_EQ(APIntOps::RoundingSDiv(Ap100 + Ap101, A2, APInt::Rounding::UP), + APIntOps::avgCeilS(Ap100, Ap101)); + + EXPECT_EQ(APInt(32, -101), APIntOps::avgFloorS(Am100, Am101)); + EXPECT_EQ(APIntOps::RoundingSDiv(Am100 + Am101, A2, APInt::Rounding::DOWN), + APIntOps::avgFloorS(Am100, Am101)); + EXPECT_EQ(APInt(32, -100), APIntOps::avgCeilS(Am100, Am101)); + EXPECT_EQ(APIntOps::RoundingSDiv(Am100 + Am101, A2, APInt::Rounding::UP), + APIntOps::avgCeilS(Am100, Am101)); + + EXPECT_EQ(AmSMin, APIntOps::avgFloorS(AmSMin, AmSMin)); + EXPECT_EQ(AmSMin, APIntOps::avgCeilS(AmSMin, AmSMin)); + + EXPECT_EQ(APIntOps::RoundingSDiv(AmSMin, A2, APInt::Rounding::DOWN), + APIntOps::avgFloorS(A0, AmSMin)); + EXPECT_EQ(APIntOps::RoundingSDiv(AmSMin, A2, APInt::Rounding::UP), + APIntOps::avgCeilS(A0, AmSMin)); + + EXPECT_EQ(A0, APIntOps::avgFloorS(A0, A0)); + EXPECT_EQ(A0, APIntOps::avgCeilS(A0, A0)); + + EXPECT_EQ(Am1, APIntOps::avgFloorS(AmSMin, ApSMax)); + EXPECT_EQ(A0, APIntOps::avgCeilS(AmSMin, ApSMax)); + + EXPECT_EQ(APIntOps::RoundingSDiv(ApSMax, A2, APInt::Rounding::DOWN), + APIntOps::avgFloorS(A0, ApSMax)); + EXPECT_EQ(APIntOps::RoundingSDiv(ApSMax, A2, APInt::Rounding::UP), + APIntOps::avgCeilS(A0, ApSMax)); + + EXPECT_EQ(ApSMax, APIntOps::avgFloorS(ApSMax, ApSMax)); + EXPECT_EQ(ApSMax, APIntOps::avgCeilS(ApSMax, ApSMax)); +} + TEST(APIntTest, umul_ov) { const std::pair<uint64_t, uint64_t> Overflows[] = { {0x8000000000000000, 2}, @@ -2962,6 +3101,69 @@ TEST(APIntTest, smul_ov) { } } +TEST(APIntTest, sfloordiv_ov) { + // int16 test overflow + { + using IntTy = int16_t; + APInt divisor(8 * sizeof(IntTy), std::numeric_limits<IntTy>::lowest(), + true); + APInt dividend(8 * sizeof(IntTy), IntTy(-1), true); + bool Overflow = false; + (void)divisor.sfloordiv_ov(dividend, Overflow); + EXPECT_TRUE(Overflow); + } + // int32 test overflow + { + using IntTy = int32_t; + APInt divisor(8 * sizeof(IntTy), std::numeric_limits<IntTy>::lowest(), + true); + APInt dividend(8 * sizeof(IntTy), IntTy(-1), true); + bool Overflow = false; + (void)divisor.sfloordiv_ov(dividend, Overflow); + EXPECT_TRUE(Overflow); + } + // int64 test overflow + { + using IntTy = int64_t; + APInt divisor(8 * sizeof(IntTy), std::numeric_limits<IntTy>::lowest(), + true); + APInt dividend(8 * sizeof(IntTy), IntTy(-1), true); + bool Overflow = false; + (void)divisor.sfloordiv_ov(dividend, Overflow); + EXPECT_TRUE(Overflow); + } + // test all of int8 + { + bool Overflow = false; + for (int i = -128; i < 128; ++i) { + for (int j = -128; j < 128; ++j) { + if (j == 0) + continue; + + int8_t a = static_cast<int8_t>(i); + int8_t b = static_cast<int8_t>(j); + + APInt divisor(8, a, true); + APInt dividend(8, b, true); + APInt quotient = divisor.sfloordiv_ov(dividend, Overflow); + + if (i == -128 && j == -1) { + EXPECT_TRUE(Overflow); + continue; + } + + if (((i >= 0 && j > 0) || (i <= 0 && j < 0)) || + (i % j == 0)) // if quotient >= 0 and remain == 0 floordiv + // equivalent to div + EXPECT_EQ(quotient.getSExtValue(), a / b); + else + EXPECT_EQ(quotient.getSExtValue(), a / b - 1); + EXPECT_FALSE(Overflow); + } + } + } +} + TEST(APIntTest, SolveQuadraticEquationWrap) { // Verify that "Solution" is the first non-negative integer that solves // Ax^2 + Bx + C = "0 or overflow", i.e. that it is a correct solution diff --git a/llvm/unittests/CodeGen/AArch64SelectionDAGTest.cpp b/llvm/unittests/CodeGen/AArch64SelectionDAGTest.cpp index e0772684e3a954153db2c5a000a837be57d0e33f..27bcad7c24c4db47555c70de0b1de178dd5fabcc 100644 --- a/llvm/unittests/CodeGen/AArch64SelectionDAGTest.cpp +++ b/llvm/unittests/CodeGen/AArch64SelectionDAGTest.cpp @@ -796,4 +796,52 @@ TEST_F(AArch64SelectionDAGTest, computeKnownBits_extload_knownnegative) { EXPECT_EQ(Known.One, APInt(32, 0xfffffff0)); } +TEST_F(AArch64SelectionDAGTest, + computeKnownBits_AVGFLOORU_AVGFLOORS_AVGCEILU_AVGCEILS) { + SDLoc Loc; + auto Int8VT = EVT::getIntegerVT(Context, 8); + auto Int16VT = EVT::getIntegerVT(Context, 16); + auto Int8Vec8VT = EVT::getVectorVT(Context, Int8VT, 8); + auto Int16Vec8VT = EVT::getVectorVT(Context, Int16VT, 8); + + SDValue UnknownOp0 = DAG->getRegister(0, Int8Vec8VT); + SDValue UnknownOp1 = DAG->getRegister(1, Int8Vec8VT); + + SDValue ZextOp0 = + DAG->getNode(ISD::ZERO_EXTEND, Loc, Int16Vec8VT, UnknownOp0); + SDValue ZextOp1 = + DAG->getNode(ISD::ZERO_EXTEND, Loc, Int16Vec8VT, UnknownOp1); + // ZextOp0 = 00000000???????? + // ZextOp1 = 00000000???????? + // => (for all AVG* instructions) + // Known.Zero = 1111111100000000 (0xFF00) + // Known.One = 0000000000000000 (0x0000) + auto Zeroes = APInt(16, 0xFF00); + auto Ones = APInt(16, 0x0000); + + SDValue AVGFLOORU = + DAG->getNode(ISD::AVGFLOORU, Loc, Int16Vec8VT, ZextOp0, ZextOp1); + KnownBits KnownAVGFLOORU = DAG->computeKnownBits(AVGFLOORU); + EXPECT_EQ(KnownAVGFLOORU.Zero, Zeroes); + EXPECT_EQ(KnownAVGFLOORU.One, Ones); + + SDValue AVGFLOORS = + DAG->getNode(ISD::AVGFLOORU, Loc, Int16Vec8VT, ZextOp0, ZextOp1); + KnownBits KnownAVGFLOORS = DAG->computeKnownBits(AVGFLOORS); + EXPECT_EQ(KnownAVGFLOORS.Zero, Zeroes); + EXPECT_EQ(KnownAVGFLOORS.One, Ones); + + SDValue AVGCEILU = + DAG->getNode(ISD::AVGCEILU, Loc, Int16Vec8VT, ZextOp0, ZextOp1); + KnownBits KnownAVGCEILU = DAG->computeKnownBits(AVGCEILU); + EXPECT_EQ(KnownAVGCEILU.Zero, Zeroes); + EXPECT_EQ(KnownAVGCEILU.One, Ones); + + SDValue AVGCEILS = + DAG->getNode(ISD::AVGCEILS, Loc, Int16Vec8VT, ZextOp0, ZextOp1); + KnownBits KnownAVGCEILS = DAG->computeKnownBits(AVGCEILS); + EXPECT_EQ(KnownAVGCEILS.Zero, Zeroes); + EXPECT_EQ(KnownAVGCEILS.One, Ones); +} + } // end namespace llvm diff --git a/llvm/unittests/CodeGen/GlobalISel/CSETest.cpp b/llvm/unittests/CodeGen/GlobalISel/CSETest.cpp index 116099eff14aa9cbcd7584e9aa11b8a2de1cbfc0..822707a1f4ed32ffa6fd3a034a255724ce9519be 100644 --- a/llvm/unittests/CodeGen/GlobalISel/CSETest.cpp +++ b/llvm/unittests/CodeGen/GlobalISel/CSETest.cpp @@ -233,4 +233,216 @@ TEST_F(AArch64GISelMITest, TestConstantFoldCTL) { EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; } +TEST_F(AArch64GISelMITest, TestConstantFoldCTT) { + setUp(); + if (!TM) + GTEST_SKIP(); + + LLT s32 = LLT::scalar(32); + + GISelCSEInfo CSEInfo; + CSEInfo.setCSEConfig(std::make_unique<CSEConfigConstantOnly>()); + CSEInfo.analyze(*MF); + B.setCSEInfo(&CSEInfo); + CSEMIRBuilder CSEB(B.getState()); + auto Cst8 = CSEB.buildConstant(s32, 8); + auto *CttzDef = &*CSEB.buildCTTZ(s32, Cst8); + EXPECT_TRUE(CttzDef->getOpcode() == TargetOpcode::G_CONSTANT); + EXPECT_TRUE(CttzDef->getOperand(1).getCImm()->getZExtValue() == 3); + + // Test vector. + auto Cst16 = CSEB.buildConstant(s32, 16); + auto Cst32 = CSEB.buildConstant(s32, 32); + auto Cst64 = CSEB.buildConstant(s32, 64); + LLT VecTy = LLT::fixed_vector(4, s32); + auto BV = CSEB.buildBuildVector(VecTy, {Cst8.getReg(0), Cst16.getReg(0), + Cst32.getReg(0), Cst64.getReg(0)}); + CSEB.buildCTTZ(VecTy, BV); + + auto CheckStr = R"( + ; CHECK: [[CST8:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 + ; CHECK: [[CST3:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK: [[CST16:%[0-9]+]]:_(s32) = G_CONSTANT i32 16 + ; CHECK: [[CST32:%[0-9]+]]:_(s32) = G_CONSTANT i32 32 + ; CHECK: [[CST64:%[0-9]+]]:_(s32) = G_CONSTANT i32 64 + ; CHECK: [[BV1:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[CST8]]:_(s32), [[CST16]]:_(s32), [[CST32]]:_(s32), [[CST64]]:_(s32) + ; CHECK: [[CST27:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 + ; CHECK: [[CST26:%[0-9]+]]:_(s32) = G_CONSTANT i32 5 + ; CHECK: [[CST25:%[0-9]+]]:_(s32) = G_CONSTANT i32 6 + ; CHECK: [[BV2:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[CST3]]:_(s32), [[CST27]]:_(s32), [[CST26]]:_(s32), [[CST25]]:_(s32) + )"; + + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + +TEST_F(AArch64GISelMITest, TestConstantFoldICMP) { + setUp(); + if (!TM) + GTEST_SKIP(); + + LLT s32 = LLT::scalar(32); + LLT s1 = LLT::scalar(1); + + GISelCSEInfo CSEInfo; + CSEInfo.setCSEConfig(std::make_unique<CSEConfigConstantOnly>()); + CSEInfo.analyze(*MF); + B.setCSEInfo(&CSEInfo); + CSEMIRBuilder CSEB(B.getState()); + + auto One = CSEB.buildConstant(s32, 1); + auto Two = CSEB.buildConstant(s32, 2); + auto MinusOne = CSEB.buildConstant(s32, -1); + auto MinusTwo = CSEB.buildConstant(s32, -2); + + // ICMP_EQ + { + auto I = CSEB.buildICmp(CmpInst::Predicate::ICMP_EQ, s1, One, One); + EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT); + EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue()); + } + + // ICMP_NE + { + auto I = CSEB.buildICmp(CmpInst::Predicate::ICMP_NE, s1, One, Two); + EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT); + EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue()); + } + + // ICMP_UGT + { + auto I = CSEB.buildICmp(CmpInst::Predicate::ICMP_UGT, s1, Two, One); + EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT); + EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue()); + } + + // ICMP_UGE + { + auto I = CSEB.buildICmp(CmpInst::Predicate::ICMP_UGE, s1, One, One); + EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT); + EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue()); + } + + // ICMP_ULT + { + auto I = CSEB.buildICmp(CmpInst::Predicate::ICMP_ULT, s1, One, Two); + EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT); + EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue()); + } + + // ICMP_ULE + { + auto I = CSEB.buildICmp(CmpInst::Predicate::ICMP_ULE, s1, Two, Two); + EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT); + EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue()); + } + + // ICMP_SGT + { + auto I = + CSEB.buildICmp(CmpInst::Predicate::ICMP_SGT, s1, MinusOne, MinusTwo); + EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT); + EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue()); + } + + // ICMP_SGE + { + auto I = + CSEB.buildICmp(CmpInst::Predicate::ICMP_SGE, s1, MinusOne, MinusOne); + EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT); + EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue()); + } + + // ICMP_SLT + { + auto I = + CSEB.buildICmp(CmpInst::Predicate::ICMP_SLT, s1, MinusTwo, MinusOne); + EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT); + EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue()); + } + + // ICMP_SLE + { + auto I = + CSEB.buildICmp(CmpInst::Predicate::ICMP_SLE, s1, MinusTwo, MinusOne); + EXPECT_TRUE(I->getOpcode() == TargetOpcode::G_CONSTANT); + EXPECT_TRUE(I->getOperand(1).getCImm()->getZExtValue()); + } + + LLT VecTy = LLT::fixed_vector(2, s32); + LLT DstTy = LLT::fixed_vector(2, s1); + auto Three = CSEB.buildConstant(s32, 3); + auto MinusThree = CSEB.buildConstant(s32, -3); + auto OneOne = CSEB.buildBuildVector(VecTy, {One.getReg(0), One.getReg(0)}); + auto OneTwo = CSEB.buildBuildVector(VecTy, {One.getReg(0), Two.getReg(0)}); + auto TwoThree = + CSEB.buildBuildVector(VecTy, {Two.getReg(0), Three.getReg(0)}); + auto MinusOneOne = + CSEB.buildBuildVector(VecTy, {MinusOne.getReg(0), MinusOne.getReg(0)}); + auto MinusOneTwo = + CSEB.buildBuildVector(VecTy, {MinusOne.getReg(0), MinusTwo.getReg(0)}); + auto MinusTwoThree = + CSEB.buildBuildVector(VecTy, {MinusTwo.getReg(0), MinusThree.getReg(0)}); + + // ICMP_EQ + CSEB.buildICmp(CmpInst::Predicate::ICMP_EQ, DstTy, OneOne, OneOne); + + // ICMP_NE + CSEB.buildICmp(CmpInst::Predicate::ICMP_NE, DstTy, OneOne, OneTwo); + + // ICMP_UGT + CSEB.buildICmp(CmpInst::Predicate::ICMP_UGT, DstTy, TwoThree, OneTwo); + + // ICMP_UGE + CSEB.buildICmp(CmpInst::Predicate::ICMP_UGE, DstTy, OneTwo, OneOne); + + // ICMP_ULT + CSEB.buildICmp(CmpInst::Predicate::ICMP_ULT, DstTy, OneOne, OneTwo); + + // ICMP_ULE + CSEB.buildICmp(CmpInst::Predicate::ICMP_ULE, DstTy, OneTwo, OneOne); + + // ICMP_SGT + CSEB.buildICmp(CmpInst::Predicate::ICMP_SGT, DstTy, MinusOneTwo, + MinusTwoThree); + + // ICMP_SGE + CSEB.buildICmp(CmpInst::Predicate::ICMP_SGE, DstTy, MinusOneTwo, MinusOneOne); + + // ICMP_SLT + CSEB.buildICmp(CmpInst::Predicate::ICMP_SLT, DstTy, MinusTwoThree, + MinusOneTwo); + + // ICMP_SLE + CSEB.buildICmp(CmpInst::Predicate::ICMP_SLE, DstTy, MinusOneTwo, MinusOneOne); + + auto CheckStr = R"( + ; CHECK: [[One:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK: [[Two:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 + ; CHECK: [[MinusOne:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1 + ; CHECK: [[MinusTwo:%[0-9]+]]:_(s32) = G_CONSTANT i32 -2 + ; CHECK: [[True:%[0-9]+]]:_(s1) = G_CONSTANT i1 true + ; CHECK: [[Three:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 + ; CHECK: [[MinusThree:%[0-9]+]]:_(s32) = G_CONSTANT i32 -3 + ; CHECK: {{%[0-9]+}}:_(<2 x s32>) = G_BUILD_VECTOR [[One]]:_(s32), [[One]]:_(s32) + ; CHECK: {{%[0-9]+}}:_(<2 x s32>) = G_BUILD_VECTOR [[One]]:_(s32), [[Two]]:_(s32) + ; CHECK: {{%[0-9]+}}:_(<2 x s32>) = G_BUILD_VECTOR [[Two]]:_(s32), [[Three]]:_(s32) + ; CHECK: {{%[0-9]+}}:_(<2 x s32>) = G_BUILD_VECTOR [[MinusOne]]:_(s32), [[MinusOne]]:_(s32) + ; CHECK: {{%[0-9]+}}:_(<2 x s32>) = G_BUILD_VECTOR [[MinusOne]]:_(s32), [[MinusTwo]]:_(s32) + ; CHECK: {{%[0-9]+}}:_(<2 x s32>) = G_BUILD_VECTOR [[MinusTwo]]:_(s32), [[MinusThree]]:_(s32) + ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[True]]:_(s1), [[True]]:_(s1) + ; CHECK: [[False:%[0-9]+]]:_(s1) = G_CONSTANT i1 false + ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[False]]:_(s1), [[True]]:_(s1) + ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[True]]:_(s1), [[True]]:_(s1) + ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[True]]:_(s1), [[True]]:_(s1) + ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[False]]:_(s1), [[True]]:_(s1) + ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[True]]:_(s1), [[False]]:_(s1) + ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[True]]:_(s1), [[True]]:_(s1) + ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[True]]:_(s1), [[False]]:_(s1) + ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[True]]:_(s1), [[True]]:_(s1) + ; CHECK: {{%[0-9]+}}:_(<2 x s1>) = G_BUILD_VECTOR [[True]]:_(s1), [[True]]:_(s1) + )"; + + EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF; +} + } // namespace diff --git a/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp b/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp index f3659bc695636137822be2a3811cb7fc70c390d1..ef80eed8d18023d8e965cde142da7e70e38791b9 100644 --- a/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp +++ b/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp @@ -1100,6 +1100,25 @@ TEST_F(AMDGPUGISelMITest, TestIsKnownToBeAPowerOfTwo) { EXPECT_TRUE(isKnownToBeAPowerOfTwo(CopyOrPow2, *MRI, &KB)); } +static void AddRangeMetadata(LLVMContext &Context, MachineInstr *Load) { + IntegerType *Int8Ty = Type::getInt8Ty(Context); + + // Value must be in [0, 2) + Metadata *LowAndHigh[] = { + ConstantAsMetadata::get(ConstantInt::get(Int8Ty, 0)), + ConstantAsMetadata::get(ConstantInt::get(Int8Ty, 2))}; + auto NewMDNode = MDNode::get(Context, LowAndHigh); + const MachineMemOperand *OldMMO = *Load->memoperands_begin(); + MachineMemOperand *NewMMO = + Load->getParent()->getParent()->getMachineMemOperand( + OldMMO->getPointerInfo(), OldMMO->getFlags(), OldMMO->getMemoryType(), + OldMMO->getAlign(), OldMMO->getAAInfo(), NewMDNode); + MachineIRBuilder MIB(*Load); + MIB.buildLoadInstr(Load->getOpcode(), Load->getOperand(0), + Load->getOperand(1), *NewMMO); + Load->eraseFromParent(); +} + TEST_F(AArch64GISelMITest, TestMetadata) { StringRef MIRString = " %imp:_(p0) = G_IMPLICIT_DEF\n" " %load:_(s8) = G_LOAD %imp(p0) :: (load (s8))\n" @@ -1120,20 +1139,7 @@ TEST_F(AArch64GISelMITest, TestMetadata) { MachineInstr *And = MRI->getVRegDef(SrcReg); MachineInstr *Ext = MRI->getVRegDef(And->getOperand(1).getReg()); MachineInstr *Load = MRI->getVRegDef(Ext->getOperand(1).getReg()); - IntegerType *Int8Ty = Type::getInt8Ty(Context); - - // Value must be in [0, 2) - Metadata *LowAndHigh[] = { - ConstantAsMetadata::get(ConstantInt::get(Int8Ty, 0)), - ConstantAsMetadata::get(ConstantInt::get(Int8Ty, 2))}; - auto NewMDNode = MDNode::get(Context, LowAndHigh); - const MachineMemOperand *OldMMO = *Load->memoperands_begin(); - MachineMemOperand NewMMO(OldMMO->getPointerInfo(), OldMMO->getFlags(), - OldMMO->getSizeInBits(), OldMMO->getAlign(), - OldMMO->getAAInfo(), NewMDNode); - MachineIRBuilder MIB(*Load); - MIB.buildLoad(Load->getOperand(0), Load->getOperand(1), NewMMO); - Load->eraseFromParent(); + AddRangeMetadata(Context, Load); GISelKnownBits Info(*MF); KnownBits Res = Info.getKnownBits(And->getOperand(1).getReg()); @@ -1148,6 +1154,66 @@ TEST_F(AArch64GISelMITest, TestMetadata) { EXPECT_EQ(Mask.getZExtValue(), Res.Zero.getZExtValue()); } +TEST_F(AArch64GISelMITest, TestMetadataExt) { + StringRef MIRString = " %imp:_(p0) = G_IMPLICIT_DEF\n" + " %load:_(s32) = G_LOAD %imp(p0) :: (load (s8))\n" + " %copy:_(s32) = COPY %load(s32)\n"; + setUp(MIRString); + if (!TM) + GTEST_SKIP(); + + Register CopyReg = Copies[Copies.size() - 1]; + MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg); + Register SrcReg = FinalCopy->getOperand(1).getReg(); + MachineInstr *Load = MRI->getVRegDef(SrcReg); + AddRangeMetadata(Context, Load); + + GISelKnownBits Info(*MF); + KnownBits Res = Info.getKnownBits(SrcReg); + EXPECT_TRUE(Res.One.isZero()); + EXPECT_EQ(Res.Zero.getZExtValue(), 0xfeu); +} + +TEST_F(AArch64GISelMITest, TestMetadataZExt) { + StringRef MIRString = " %imp:_(p0) = G_IMPLICIT_DEF\n" + " %load:_(s32) = G_ZEXTLOAD %imp(p0) :: (load (s8))\n" + " %copy:_(s32) = COPY %load(s32)\n"; + setUp(MIRString); + if (!TM) + GTEST_SKIP(); + + Register CopyReg = Copies[Copies.size() - 1]; + MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg); + Register SrcReg = FinalCopy->getOperand(1).getReg(); + MachineInstr *Load = MRI->getVRegDef(SrcReg); + AddRangeMetadata(Context, Load); + + GISelKnownBits Info(*MF); + KnownBits Res = Info.getKnownBits(SrcReg); + EXPECT_TRUE(Res.One.isZero()); + EXPECT_EQ(Res.Zero.getZExtValue(), 0xfffffffe); +} + +TEST_F(AArch64GISelMITest, TestMetadataSExt) { + StringRef MIRString = " %imp:_(p0) = G_IMPLICIT_DEF\n" + " %load:_(s32) = G_SEXTLOAD %imp(p0) :: (load (s8))\n" + " %copy:_(s32) = COPY %load(s32)\n"; + setUp(MIRString); + if (!TM) + GTEST_SKIP(); + + Register CopyReg = Copies[Copies.size() - 1]; + MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg); + Register SrcReg = FinalCopy->getOperand(1).getReg(); + MachineInstr *Load = MRI->getVRegDef(SrcReg); + AddRangeMetadata(Context, Load); + + GISelKnownBits Info(*MF); + KnownBits Res = Info.getKnownBits(SrcReg); + EXPECT_TRUE(Res.One.isZero()); + EXPECT_EQ(Res.Zero.getZExtValue(), 0xfffffffe); +} + TEST_F(AArch64GISelMITest, TestKnownBitsExt) { StringRef MIRString = " %c1:_(s16) = G_CONSTANT i16 1\n" " %x:_(s16) = G_IMPLICIT_DEF\n" diff --git a/llvm/unittests/CodeGen/GlobalISel/KnownBitsVectorTest.cpp b/llvm/unittests/CodeGen/GlobalISel/KnownBitsVectorTest.cpp index ab180cd1cc27262eabe356255370a34f9cb39fb2..dd6edd35a8468b6c173107dc634fbd3aeb0f811b 100644 --- a/llvm/unittests/CodeGen/GlobalISel/KnownBitsVectorTest.cpp +++ b/llvm/unittests/CodeGen/GlobalISel/KnownBitsVectorTest.cpp @@ -1008,7 +1008,7 @@ TEST_F(AArch64GISelMITest, TestVectorMetadata) { auto *NewMDNode = MDNode::get(Context, LowAndHigh); const MachineMemOperand *OldMMO = *Load->memoperands_begin(); MachineMemOperand NewMMO(OldMMO->getPointerInfo(), OldMMO->getFlags(), - OldMMO->getSizeInBits(), OldMMO->getAlign(), + OldMMO->getMemoryType(), OldMMO->getAlign(), OldMMO->getAAInfo(), NewMDNode); MachineIRBuilder MIB(*Load); MIB.buildLoad(Load->getOperand(0), Load->getOperand(1), NewMMO); diff --git a/llvm/unittests/CodeGen/LowLevelTypeTest.cpp b/llvm/unittests/CodeGen/LowLevelTypeTest.cpp index cb34802a5de27144f2d96d3cc038f9c46e8dcea8..b60d82b529fa3ff9ae1773d218e1e7593251ff3c 100644 --- a/llvm/unittests/CodeGen/LowLevelTypeTest.cpp +++ b/llvm/unittests/CodeGen/LowLevelTypeTest.cpp @@ -18,6 +18,24 @@ using namespace llvm; namespace { +TEST(LowLevelTypeTest, Token) { + LLVMContext C; + DataLayout DL(""); + + const LLT TTy = LLT::token(); + + // Test kind. + EXPECT_TRUE(TTy.isValid()); + EXPECT_TRUE(TTy.isScalar()); + EXPECT_TRUE(TTy.isToken()); + + EXPECT_FALSE(TTy.isPointer()); + EXPECT_FALSE(TTy.isVector()); + + const LLT STy = LLT::scalar(0); + EXPECT_EQ(STy, TTy); +} + TEST(LowLevelTypeTest, Scalar) { LLVMContext C; DataLayout DL(""); @@ -32,6 +50,8 @@ TEST(LowLevelTypeTest, Scalar) { ASSERT_FALSE(Ty.isPointer()); ASSERT_FALSE(Ty.isVector()); + EXPECT_TRUE(S != 0 || Ty.isToken()); + // Test sizes. EXPECT_EQ(S, Ty.getSizeInBits()); EXPECT_EQ(S, Ty.getScalarSizeInBits()); @@ -77,6 +97,7 @@ TEST(LowLevelTypeTest, Vector) { ASSERT_FALSE(VTy.isScalar()); ASSERT_FALSE(VTy.isPointer()); + ASSERT_FALSE(VTy.isToken()); // Test sizes. EXPECT_EQ(S, VTy.getScalarSizeInBits()); @@ -300,6 +321,7 @@ TEST(LowLevelTypeTest, Invalid) { ASSERT_FALSE(Ty.isScalar()); ASSERT_FALSE(Ty.isPointer()); ASSERT_FALSE(Ty.isVector()); + ASSERT_FALSE(Ty.isToken()); } TEST(LowLevelTypeTest, Divide) { diff --git a/llvm/unittests/CodeGen/MFCommon.inc b/llvm/unittests/CodeGen/MFCommon.inc index 7de7eabdd1f6040b4a9d82011ee9b736c6f86daf..1997e8052297577c70c15188a1744f3e117d1528 100644 --- a/llvm/unittests/CodeGen/MFCommon.inc +++ b/llvm/unittests/CodeGen/MFCommon.inc @@ -23,9 +23,10 @@ class BogusRegisterInfo : public TargetRegisterInfo { public: BogusRegisterInfo() : TargetRegisterInfo(nullptr, BogusRegisterClasses, BogusRegisterClasses, - nullptr, nullptr, LaneBitmask(~0u), nullptr, nullptr) { + nullptr, nullptr, nullptr, LaneBitmask(~0u), nullptr, + nullptr) { InitMCRegisterInfo(nullptr, 0, 0, 0, nullptr, 0, nullptr, 0, nullptr, - nullptr, nullptr, nullptr, nullptr, 0, nullptr, nullptr); + nullptr, nullptr, nullptr, nullptr, 0, nullptr); } const MCPhysReg * diff --git a/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp b/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp index 17fc3ce8af267729086dd038ecec22930ccc665f..a7112cfac63de51461bf6f53e30236a60f24276f 100644 --- a/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp +++ b/llvm/unittests/CodeGen/SelectionDAGPatternMatchTest.cpp @@ -130,6 +130,13 @@ TEST_F(SelectionDAGPatternMatchTest, matchBinaryOp) { SDValue Add = DAG->getNode(ISD::ADD, DL, Int32VT, Op0, Op1); SDValue Sub = DAG->getNode(ISD::SUB, DL, Int32VT, Add, Op0); SDValue Mul = DAG->getNode(ISD::MUL, DL, Int32VT, Add, Sub); + SDValue And = DAG->getNode(ISD::AND, DL, Int32VT, Op0, Op1); + SDValue Xor = DAG->getNode(ISD::XOR, DL, Int32VT, Op1, Op0); + SDValue Or = DAG->getNode(ISD::OR, DL, Int32VT, Op0, Op1); + SDValue SMax = DAG->getNode(ISD::SMAX, DL, Int32VT, Op0, Op1); + SDValue SMin = DAG->getNode(ISD::SMIN, DL, Int32VT, Op1, Op0); + SDValue UMax = DAG->getNode(ISD::UMAX, DL, Int32VT, Op0, Op1); + SDValue UMin = DAG->getNode(ISD::UMIN, DL, Int32VT, Op1, Op0); SDValue SFAdd = DAG->getNode(ISD::STRICT_FADD, DL, {Float32VT, MVT::Other}, {DAG->getEntryNode(), Op2, Op2}); @@ -144,6 +151,23 @@ TEST_F(SelectionDAGPatternMatchTest, matchBinaryOp) { EXPECT_TRUE( sd_match(SFAdd, m_ChainedBinOp(ISD::STRICT_FADD, m_SpecificVT(Float32VT), m_SpecificVT(Float32VT)))); + + EXPECT_TRUE(sd_match(And, m_c_BinOp(ISD::AND, m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(And, m_And(m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(Xor, m_c_BinOp(ISD::XOR, m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(Xor, m_Xor(m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(Or, m_c_BinOp(ISD::OR, m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(Or, m_Or(m_Value(), m_Value()))); + + EXPECT_TRUE(sd_match(SMax, m_c_BinOp(ISD::SMAX, m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(SMax, m_SMax(m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(SMin, m_c_BinOp(ISD::SMIN, m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(SMin, m_SMin(m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(UMax, m_c_BinOp(ISD::UMAX, m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(UMax, m_UMax(m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(UMin, m_c_BinOp(ISD::UMIN, m_Value(), m_Value()))); + EXPECT_TRUE(sd_match(UMin, m_UMin(m_Value(), m_Value()))); + SDValue BindVal; EXPECT_TRUE(sd_match(SFAdd, m_ChainedBinOp(ISD::STRICT_FADD, m_Value(BindVal), m_Deferred(BindVal)))); @@ -163,10 +187,20 @@ TEST_F(SelectionDAGPatternMatchTest, matchUnaryOp) { SDValue SExt = DAG->getNode(ISD::SIGN_EXTEND, DL, Int64VT, Op0); SDValue Trunc = DAG->getNode(ISD::TRUNCATE, DL, Int32VT, Op1); + SDValue Sub = DAG->getNode(ISD::SUB, DL, Int32VT, Trunc, Op0); + SDValue Neg = DAG->getNegative(Op0, DL, Int32VT); + SDValue Not = DAG->getNOT(DL, Op0, Int32VT); + using namespace SDPatternMatch; EXPECT_TRUE(sd_match(ZExt, m_UnaryOp(ISD::ZERO_EXTEND, m_Value()))); EXPECT_TRUE(sd_match(SExt, m_SExt(m_Value()))); EXPECT_TRUE(sd_match(Trunc, m_Trunc(m_Specific(Op1)))); + + EXPECT_TRUE(sd_match(Neg, m_Neg(m_Value()))); + EXPECT_TRUE(sd_match(Not, m_Not(m_Value()))); + EXPECT_FALSE(sd_match(ZExt, m_Neg(m_Value()))); + EXPECT_FALSE(sd_match(Sub, m_Neg(m_Value()))); + EXPECT_FALSE(sd_match(Neg, m_Not(m_Value()))); } TEST_F(SelectionDAGPatternMatchTest, matchConstants) { @@ -217,6 +251,38 @@ TEST_F(SelectionDAGPatternMatchTest, patternCombinators) { EXPECT_TRUE(sd_match(Add, m_AllOf(m_Opc(ISD::ADD), m_OneUse()))); } +TEST_F(SelectionDAGPatternMatchTest, optionalResizing) { + SDLoc DL; + auto Int32VT = EVT::getIntegerVT(Context, 32); + auto Int64VT = EVT::getIntegerVT(Context, 64); + + SDValue Op32 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int32VT); + SDValue Op64 = DAG->getCopyFromReg(DAG->getEntryNode(), DL, 1, Int64VT); + SDValue ZExt = DAG->getNode(ISD::ZERO_EXTEND, DL, Int64VT, Op32); + SDValue SExt = DAG->getNode(ISD::SIGN_EXTEND, DL, Int64VT, Op32); + SDValue AExt = DAG->getNode(ISD::ANY_EXTEND, DL, Int64VT, Op32); + SDValue Trunc = DAG->getNode(ISD::TRUNCATE, DL, Int32VT, Op64); + + using namespace SDPatternMatch; + SDValue A; + EXPECT_TRUE(sd_match(Op32, m_ZExtOrSelf(m_Value(A)))); + EXPECT_TRUE(A == Op32); + EXPECT_TRUE(sd_match(ZExt, m_ZExtOrSelf(m_Value(A)))); + EXPECT_TRUE(A == Op32); + EXPECT_TRUE(sd_match(Op64, m_SExtOrSelf(m_Value(A)))); + EXPECT_TRUE(A == Op64); + EXPECT_TRUE(sd_match(SExt, m_SExtOrSelf(m_Value(A)))); + EXPECT_TRUE(A == Op32); + EXPECT_TRUE(sd_match(Op32, m_AExtOrSelf(m_Value(A)))); + EXPECT_TRUE(A == Op32); + EXPECT_TRUE(sd_match(AExt, m_AExtOrSelf(m_Value(A)))); + EXPECT_TRUE(A == Op32); + EXPECT_TRUE(sd_match(Op64, m_TruncOrSelf(m_Value(A)))); + EXPECT_TRUE(A == Op64); + EXPECT_TRUE(sd_match(Trunc, m_TruncOrSelf(m_Value(A)))); + EXPECT_TRUE(A == Op64); +} + TEST_F(SelectionDAGPatternMatchTest, matchNode) { SDLoc DL; auto Int32VT = EVT::getIntegerVT(Context, 32); diff --git a/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp b/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp index c5b9f5cfc0d4acb16281ed1f9f6047d817106c90..ad5e51b7efb83486d447127f65373abcc4cb2fae 100644 --- a/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp @@ -568,12 +568,20 @@ StringRef dwarfgen::Generator::generate() { for (auto &CU : CompileUnits) { // Set the absolute .debug_info offset for this compile unit. CU->setOffset(SecOffset); - // The DIEs contain compile unit relative offsets. - unsigned CUOffset = 11; + // The DIEs contain compile unit relative offsets and the offset depends + // on the Dwarf version. + unsigned CUOffset = 4 + // Length + 2 + // Version + 4 + // Abbreviation offset + 1; // Address size + if (Asm->getDwarfVersion() >= 5) + CUOffset += 1; // DW_UT_compile tag. + CUOffset = CU->getUnitDIE().computeSizeAndOffsets(CUOffset); // Update our absolute .debug_info offset. SecOffset += CUOffset; - CU->setLength(CUOffset - 4); + unsigned CUOffsetUnitLength = 4; + CU->setLength(CUOffset - CUOffsetUnitLength); } Abbreviations.Emit(Asm.get(), TLOF->getDwarfAbbrevSection()); diff --git a/llvm/unittests/DebugInfo/LogicalView/CMakeLists.txt b/llvm/unittests/DebugInfo/LogicalView/CMakeLists.txt index 1b93d77a20bd69a0034f9159cb73d87d69e4d830..1116edb212b057b8974b9b9510b2cfeb85f68139 100644 --- a/llvm/unittests/DebugInfo/LogicalView/CMakeLists.txt +++ b/llvm/unittests/DebugInfo/LogicalView/CMakeLists.txt @@ -12,7 +12,7 @@ add_llvm_unittest_with_input_files(DebugInfoLogicalViewTests CodeViewReaderTest.cpp CommandLineOptionsTest.cpp CompareElementsTest.cpp - ELFReaderTest.cpp + DWARFReaderTest.cpp SelectElementsTest.cpp LocationRangesTest.cpp LogicalElementsTest.cpp diff --git a/llvm/unittests/DebugInfo/LogicalView/ELFReaderTest.cpp b/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp similarity index 99% rename from llvm/unittests/DebugInfo/LogicalView/ELFReaderTest.cpp rename to llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp index bd278befbc642f15e23541815749b4b5112eacb5..a1bd5dee3565660607226c9c740df097588d932e 100644 --- a/llvm/unittests/DebugInfo/LogicalView/ELFReaderTest.cpp +++ b/llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp @@ -1,4 +1,4 @@ -//===- llvm/unittest/DebugInfo/LogicalView/ELFReaderTest.cpp --------------===// +//===- llvm/unittest/DebugInfo/LogicalView/DWARFReaderTest.cpp ------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -323,7 +323,7 @@ void compareElements(SmallString<128> &InputsDir) { checkElementComparison(Reference.get(), Target.get()); } -TEST(LogicalViewTest, ELFReader) { +TEST(LogicalViewTest, DWARFReader) { // Initialize targets and assembly printers/parsers. llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargetMCs(); diff --git a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt index f102ba59e3754256e4f72b2264b5e9ff274ce3ef..8a6a26bba63c26cbd27f6804c1a4a5600f6d7ae9 100644 --- a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt +++ b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt @@ -26,6 +26,7 @@ add_llvm_unittest(OrcJITTests JITTargetMachineBuilderTest.cpp LazyCallThroughAndReexportsTest.cpp LookupAndRecordAddrsTest.cpp + MachOPlatformTest.cpp MapperJITLinkMemoryManagerTest.cpp MemoryMapperTest.cpp ObjectFormatsTest.cpp diff --git a/llvm/unittests/ExecutionEngine/Orc/MachOPlatformTest.cpp b/llvm/unittests/ExecutionEngine/Orc/MachOPlatformTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bf6c1042252d76efb8dabef6bfd4b8e53276b888 --- /dev/null +++ b/llvm/unittests/ExecutionEngine/Orc/MachOPlatformTest.cpp @@ -0,0 +1,56 @@ +//===---------- MachOPlatformTest.cpp - MachPlatform API Tests ------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/ExecutionEngine/Orc/MachOPlatform.h" +#include "llvm/BinaryFormat/MachO.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::orc; + +TEST(MachOPlatformTests, BuildVersionOptsFromTriple) { + + auto darwinOS = MachOPlatform::HeaderOptions::BuildVersionOpts::fromTriple( + Triple("arm64-apple-darwin"), 0, 0); + EXPECT_FALSE(darwinOS); + + auto macOS = MachOPlatform::HeaderOptions::BuildVersionOpts::fromTriple( + Triple("arm64-apple-macosx"), 0, 0); + EXPECT_TRUE(macOS); + EXPECT_EQ(macOS->Platform, MachO::PLATFORM_MACOS); + + auto iOS = MachOPlatform::HeaderOptions::BuildVersionOpts::fromTriple( + Triple("arm64-apple-ios"), 0, 0); + EXPECT_TRUE(iOS); + EXPECT_EQ(iOS->Platform, MachO::PLATFORM_IOS); + + auto iOSSim = MachOPlatform::HeaderOptions::BuildVersionOpts::fromTriple( + Triple("arm64-apple-ios-simulator"), 0, 0); + EXPECT_TRUE(iOSSim); + EXPECT_EQ(iOSSim->Platform, MachO::PLATFORM_IOSSIMULATOR); + + auto tvOS = MachOPlatform::HeaderOptions::BuildVersionOpts::fromTriple( + Triple("arm64-apple-tvos"), 0, 0); + EXPECT_TRUE(tvOS); + EXPECT_EQ(tvOS->Platform, MachO::PLATFORM_TVOS); + + auto tvOSSim = MachOPlatform::HeaderOptions::BuildVersionOpts::fromTriple( + Triple("arm64-apple-tvos-simulator"), 0, 0); + EXPECT_TRUE(tvOSSim); + EXPECT_EQ(tvOSSim->Platform, MachO::PLATFORM_TVOSSIMULATOR); + + auto watchOS = MachOPlatform::HeaderOptions::BuildVersionOpts::fromTriple( + Triple("arm64-apple-watchos"), 0, 0); + EXPECT_TRUE(watchOS); + EXPECT_EQ(watchOS->Platform, MachO::PLATFORM_WATCHOS); + + auto watchOSSim = MachOPlatform::HeaderOptions::BuildVersionOpts::fromTriple( + Triple("arm64-apple-watchos-simulator"), 0, 0); + EXPECT_TRUE(watchOSSim); + EXPECT_EQ(watchOSSim->Platform, MachO::PLATFORM_WATCHOSSIMULATOR); +} diff --git a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp index fdbe8df783b117a4e62d048981578d651d444590..5c415cadcd686c89fbdc9e51b9ff73f2bfb2fc9f 100644 --- a/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp +++ b/llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp @@ -5856,6 +5856,23 @@ TEST_F(OpenMPIRBuilderTest, TargetDataRegion) { EXPECT_TRUE(TargetDataCall->getOperand(2)->getType()->isIntegerTy(32)); EXPECT_TRUE(TargetDataCall->getOperand(8)->getType()->isPointerTy()); + // Check that BodyGenCB is still made when IsTargetDevice is set to true. + OMPBuilder.Config.setIsTargetDevice(true); + bool CheckDevicePassBodyGen = false; + auto BodyTargetCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) { + CheckDevicePassBodyGen = true; + Builder.restoreIP(CodeGenIP); + CallInst *TargetDataCall = + dyn_cast<CallInst>(BB->back().getPrevNode()->getPrevNode()); + // Make sure no begin_mapper call is present for device pass. + EXPECT_EQ(TargetDataCall, nullptr); + return Builder.saveIP(); + }; + Builder.restoreIP(OMPBuilder.createTargetData( + Loc, AllocaIP, Builder.saveIP(), Builder.getInt64(DeviceID), + /* IfCond= */ nullptr, Info, GenMapInfoCB, nullptr, BodyTargetCB)); + EXPECT_TRUE(CheckDevicePassBodyGen); + Builder.CreateRetVoid(); EXPECT_FALSE(verifyModule(*M, &errs())); } diff --git a/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp b/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp index e23c7eaa4930d066ba4b693ec81306685dfd8413..905928819dda807d65e80e2300e8adedbbab4c0a 100644 --- a/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp +++ b/llvm/unittests/IR/BasicBlockDbgInfoTest.cpp @@ -41,7 +41,7 @@ namespace { // position that it already resides at. This is fine -- but gets complicated // with dbg.value intrinsics. By moving an instruction, we can end up changing // nothing but the location of debug-info intrinsics. That has to be modelled -// by DPValues, the dbg.value replacement. +// by DbgVariableRecords, the dbg.value replacement. TEST(BasicBlockDbgInfoTest, InsertAfterSelf) { LLVMContext C; UseNewDbgInfoFormat = true; @@ -90,10 +90,10 @@ TEST(BasicBlockDbgInfoTest, InsertAfterSelf) { // %b = add // %c = add // dbg.value - // Check that this is replicated by DPValues. + // Check that this is replicated by DbgVariableRecords. Inst2->moveAfter(Inst1); - // Inst1 should only have one DPValue on it. + // Inst1 should only have one DbgVariableRecord on it. EXPECT_TRUE(Inst1->hasDbgRecords()); auto Range1 = Inst1->getDbgRecordRange(); EXPECT_EQ(std::distance(Range1.begin(), Range1.end()), 1u); @@ -147,10 +147,10 @@ TEST(BasicBlockDbgInfoTest, MarkerOperations) { // Fetch out our two markers, Instruction *Instr1 = &*BB.begin(); Instruction *Instr2 = Instr1->getNextNode(); - DPMarker *Marker1 = Instr1->DbgMarker; - DPMarker *Marker2 = Instr2->DbgMarker; - // There's no TrailingDPValues marker allocated yet. - DPMarker *EndMarker = nullptr; + DbgMarker *Marker1 = Instr1->DebugMarker; + DbgMarker *Marker2 = Instr2->DebugMarker; + // There's no TrailingDbgRecords marker allocated yet. + DbgMarker *EndMarker = nullptr; // Check that the "getMarker" utilities operate as expected. EXPECT_EQ(BB.getMarker(Instr1->getIterator()), Marker1); @@ -158,83 +158,83 @@ TEST(BasicBlockDbgInfoTest, MarkerOperations) { EXPECT_EQ(BB.getNextMarker(Instr1), Marker2); EXPECT_EQ(BB.getNextMarker(Instr2), EndMarker); // Is nullptr. - // There should be two DPValues, - EXPECT_EQ(Marker1->StoredDPValues.size(), 1u); - EXPECT_EQ(Marker2->StoredDPValues.size(), 1u); + // There should be two DbgVariableRecords, + EXPECT_EQ(Marker1->StoredDbgRecords.size(), 1u); + EXPECT_EQ(Marker2->StoredDbgRecords.size(), 1u); // Unlink them and try to re-insert them through the basic block. - DbgRecord *DPV1 = &*Marker1->StoredDPValues.begin(); - DbgRecord *DPV2 = &*Marker2->StoredDPValues.begin(); - DPV1->removeFromParent(); - DPV2->removeFromParent(); - EXPECT_TRUE(Marker1->StoredDPValues.empty()); - EXPECT_TRUE(Marker2->StoredDPValues.empty()); + DbgRecord *DVR1 = &*Marker1->StoredDbgRecords.begin(); + DbgRecord *DVR2 = &*Marker2->StoredDbgRecords.begin(); + DVR1->removeFromParent(); + DVR2->removeFromParent(); + EXPECT_TRUE(Marker1->StoredDbgRecords.empty()); + EXPECT_TRUE(Marker2->StoredDbgRecords.empty()); // This should appear in Marker1. - BB.insertDbgRecordBefore(DPV1, BB.begin()); - EXPECT_EQ(Marker1->StoredDPValues.size(), 1u); - EXPECT_EQ(DPV1, &*Marker1->StoredDPValues.begin()); + BB.insertDbgRecordBefore(DVR1, BB.begin()); + EXPECT_EQ(Marker1->StoredDbgRecords.size(), 1u); + EXPECT_EQ(DVR1, &*Marker1->StoredDbgRecords.begin()); // This should attach to Marker2. - BB.insertDbgRecordAfter(DPV2, &*BB.begin()); - EXPECT_EQ(Marker2->StoredDPValues.size(), 1u); - EXPECT_EQ(DPV2, &*Marker2->StoredDPValues.begin()); + BB.insertDbgRecordAfter(DVR2, &*BB.begin()); + EXPECT_EQ(Marker2->StoredDbgRecords.size(), 1u); + EXPECT_EQ(DVR2, &*Marker2->StoredDbgRecords.begin()); - // Now, how about removing instructions? That should cause any DPValues to - // "fall down". + // Now, how about removing instructions? That should cause any + // DbgVariableRecords to "fall down". Instr1->removeFromParent(); Marker1 = nullptr; - // DPValues should now be in Marker2. + // DbgVariableRecords should now be in Marker2. EXPECT_EQ(BB.size(), 1u); - EXPECT_EQ(Marker2->StoredDPValues.size(), 2u); + EXPECT_EQ(Marker2->StoredDbgRecords.size(), 2u); // They should also be in the correct order. - SmallVector<DbgRecord *, 2> DPVs; - for (DbgRecord &DPV : Marker2->getDbgRecordRange()) - DPVs.push_back(&DPV); - EXPECT_EQ(DPVs[0], DPV1); - EXPECT_EQ(DPVs[1], DPV2); - - // If we remove the end instruction, the DPValues should fall down into - // the trailing marker. + SmallVector<DbgRecord *, 2> DVRs; + for (DbgRecord &DVR : Marker2->getDbgRecordRange()) + DVRs.push_back(&DVR); + EXPECT_EQ(DVRs[0], DVR1); + EXPECT_EQ(DVRs[1], DVR2); + + // If we remove the end instruction, the DbgVariableRecords should fall down + // into the trailing marker. EXPECT_EQ(BB.getTrailingDbgRecords(), nullptr); Instr2->removeFromParent(); EXPECT_TRUE(BB.empty()); EndMarker = BB.getTrailingDbgRecords(); ASSERT_NE(EndMarker, nullptr); - EXPECT_EQ(EndMarker->StoredDPValues.size(), 2u); + EXPECT_EQ(EndMarker->StoredDbgRecords.size(), 2u); // Again, these should arrive in the correct order. - DPVs.clear(); - for (DbgRecord &DPV : EndMarker->getDbgRecordRange()) - DPVs.push_back(&DPV); - EXPECT_EQ(DPVs[0], DPV1); - EXPECT_EQ(DPVs[1], DPV2); + DVRs.clear(); + for (DbgRecord &DVR : EndMarker->getDbgRecordRange()) + DVRs.push_back(&DVR); + EXPECT_EQ(DVRs[0], DVR1); + EXPECT_EQ(DVRs[1], DVR2); // Inserting a normal instruction at the beginning: shouldn't dislodge the - // DPValues. It's intended to not go at the start. + // DbgVariableRecords. It's intended to not go at the start. Instr1->insertBefore(BB, BB.begin()); - EXPECT_EQ(EndMarker->StoredDPValues.size(), 2u); + EXPECT_EQ(EndMarker->StoredDbgRecords.size(), 2u); Instr1->removeFromParent(); - // Inserting at end(): should dislodge the DPValues, if they were dbg.values - // then they would sit "above" the new instruction. + // Inserting at end(): should dislodge the DbgVariableRecords, if they were + // dbg.values then they would sit "above" the new instruction. Instr1->insertBefore(BB, BB.end()); - EXPECT_EQ(Instr1->DbgMarker->StoredDPValues.size(), 2u); + EXPECT_EQ(Instr1->DebugMarker->StoredDbgRecords.size(), 2u); // We should de-allocate the trailing marker when something is inserted // at end(). EXPECT_EQ(BB.getTrailingDbgRecords(), nullptr); - // Remove Instr1: now the DPValues will fall down again, + // Remove Instr1: now the DbgVariableRecords will fall down again, Instr1->removeFromParent(); EndMarker = BB.getTrailingDbgRecords(); - EXPECT_EQ(EndMarker->StoredDPValues.size(), 2u); + EXPECT_EQ(EndMarker->StoredDbgRecords.size(), 2u); // Inserting a terminator, however it's intended, should dislodge the - // trailing DPValues, as it's the clear intention of the caller that this be - // the final instr in the block, and DPValues aren't allowed to live off the - // end forever. + // trailing DbgVariableRecords, as it's the clear intention of the caller that + // this be the final instr in the block, and DbgVariableRecords aren't allowed + // to live off the end forever. Instr2->insertBefore(BB, BB.begin()); - EXPECT_EQ(Instr2->DbgMarker->StoredDPValues.size(), 2u); + EXPECT_EQ(Instr2->DebugMarker->StoredDbgRecords.size(), 2u); EXPECT_EQ(BB.getTrailingDbgRecords(), nullptr); // Teardown, @@ -297,35 +297,38 @@ TEST(BasicBlockDbgInfoTest, HeadBitOperations) { Instruction *CInst = BInst->getNextNode(); Instruction *DInst = CInst->getNextNode(); // CInst should have debug-info. - ASSERT_TRUE(CInst->DbgMarker); - EXPECT_FALSE(CInst->DbgMarker->StoredDPValues.empty()); + ASSERT_TRUE(CInst->DebugMarker); + EXPECT_FALSE(CInst->DebugMarker->StoredDbgRecords.empty()); - // If we move "c" to the start of the block, just normally, then the DPValues - // should fall down to "d". + // If we move "c" to the start of the block, just normally, then the + // DbgVariableRecords should fall down to "d". CInst->moveBefore(BB, BeginIt2); - EXPECT_TRUE(!CInst->DbgMarker || CInst->DbgMarker->StoredDPValues.empty()); - ASSERT_TRUE(DInst->DbgMarker); - EXPECT_FALSE(DInst->DbgMarker->StoredDPValues.empty()); + EXPECT_TRUE(!CInst->DebugMarker || + CInst->DebugMarker->StoredDbgRecords.empty()); + ASSERT_TRUE(DInst->DebugMarker); + EXPECT_FALSE(DInst->DebugMarker->StoredDbgRecords.empty()); // Wheras if we move D to the start of the block with moveBeforePreserving, - // the DPValues should move with it. + // the DbgVariableRecords should move with it. DInst->moveBeforePreserving(BB, BB.begin()); - EXPECT_FALSE(DInst->DbgMarker->StoredDPValues.empty()); + EXPECT_FALSE(DInst->DebugMarker->StoredDbgRecords.empty()); EXPECT_EQ(&*BB.begin(), DInst); - // Similarly, moveAfterPreserving "D" to "C" should move DPValues with "D". + // Similarly, moveAfterPreserving "D" to "C" should move DbgVariableRecords + // with "D". DInst->moveAfterPreserving(CInst); - EXPECT_FALSE(DInst->DbgMarker->StoredDPValues.empty()); + EXPECT_FALSE(DInst->DebugMarker->StoredDbgRecords.empty()); // (move back to the start...) DInst->moveBeforePreserving(BB, BB.begin()); - // Current order of insts: "D -> C -> B -> Ret". DPValues on "D". + // Current order of insts: "D -> C -> B -> Ret". DbgVariableRecords on "D". // If we move "C" to the beginning of the block, it should go before the - // DPValues. They'll stay on "D". + // DbgVariableRecords. They'll stay on "D". CInst->moveBefore(BB, BB.begin()); - EXPECT_TRUE(!CInst->DbgMarker || CInst->DbgMarker->StoredDPValues.empty()); - EXPECT_FALSE(DInst->DbgMarker->StoredDPValues.empty()); + EXPECT_TRUE(!CInst->DebugMarker || + CInst->DebugMarker->StoredDbgRecords.empty()); + EXPECT_FALSE(DInst->DebugMarker->StoredDbgRecords.empty()); EXPECT_EQ(&*BB.begin(), CInst); EXPECT_EQ(CInst->getNextNode(), DInst); @@ -333,16 +336,17 @@ TEST(BasicBlockDbgInfoTest, HeadBitOperations) { CInst->moveBefore(BInst); EXPECT_EQ(&*BB.begin(), DInst); - // Current order of insts: "D -> C -> B -> Ret". DPValues on "D". + // Current order of insts: "D -> C -> B -> Ret". DbgVariableRecords on "D". // Now move CInst to the position of DInst, but using getIterator instead of // BasicBlock::begin. This signals that we want the "C" instruction to be - // immediately before "D", with any DPValues on "D" now moving to "C". - // It's the equivalent of moving an instruction to the position between a + // immediately before "D", with any DbgVariableRecords on "D" now moving to + // "C". It's the equivalent of moving an instruction to the position between a // run of dbg.values and the next instruction. CInst->moveBefore(BB, DInst->getIterator()); - // CInst gains the DPValues. - EXPECT_TRUE(!DInst->DbgMarker || DInst->DbgMarker->StoredDPValues.empty()); - EXPECT_FALSE(CInst->DbgMarker->StoredDPValues.empty()); + // CInst gains the DbgVariableRecords. + EXPECT_TRUE(!DInst->DebugMarker || + DInst->DebugMarker->StoredDbgRecords.empty()); + EXPECT_FALSE(CInst->DebugMarker->StoredDbgRecords.empty()); EXPECT_EQ(&*BB.begin(), CInst); UseNewDbgInfoFormat = false; @@ -378,8 +382,8 @@ TEST(BasicBlockDbgInfoTest, InstrDbgAccess) { !11 = !DILocation(line: 1, column: 1, scope: !6) )"); - // Check that DPValues can be accessed from Instructions without digging - // into the depths of DPMarkers. + // Check that DbgVariableRecords can be accessed from Instructions without + // digging into the depths of DbgMarkers. BasicBlock &BB = M->getFunction("f")->getEntryBlock(); // Convert the module to "new" form debug-info. M->convertToNewDbgValues(); @@ -388,28 +392,28 @@ TEST(BasicBlockDbgInfoTest, InstrDbgAccess) { Instruction *CInst = BInst->getNextNode(); Instruction *DInst = CInst->getNextNode(); - ASSERT_FALSE(BInst->DbgMarker); - ASSERT_TRUE(CInst->DbgMarker); - ASSERT_EQ(CInst->DbgMarker->StoredDPValues.size(), 1u); - DbgRecord *DPV1 = &*CInst->DbgMarker->StoredDPValues.begin(); - ASSERT_TRUE(DPV1); + ASSERT_FALSE(BInst->DebugMarker); + ASSERT_TRUE(CInst->DebugMarker); + ASSERT_EQ(CInst->DebugMarker->StoredDbgRecords.size(), 1u); + DbgRecord *DVR1 = &*CInst->DebugMarker->StoredDbgRecords.begin(); + ASSERT_TRUE(DVR1); EXPECT_FALSE(BInst->hasDbgRecords()); - // Clone DPValues from one inst to another. Other arguments to clone are - // tested in DPMarker test. + // Clone DbgVariableRecords from one inst to another. Other arguments to clone + // are tested in DbgMarker test. auto Range1 = BInst->cloneDebugInfoFrom(CInst); - EXPECT_EQ(BInst->DbgMarker->StoredDPValues.size(), 1u); - DbgRecord *DPV2 = &*BInst->DbgMarker->StoredDPValues.begin(); + EXPECT_EQ(BInst->DebugMarker->StoredDbgRecords.size(), 1u); + DbgRecord *DVR2 = &*BInst->DebugMarker->StoredDbgRecords.begin(); EXPECT_EQ(std::distance(Range1.begin(), Range1.end()), 1u); - EXPECT_EQ(&*Range1.begin(), DPV2); - EXPECT_NE(DPV1, DPV2); + EXPECT_EQ(&*Range1.begin(), DVR2); + EXPECT_NE(DVR1, DVR2); // We should be able to get a range over exactly the same information. auto Range2 = BInst->getDbgRecordRange(); EXPECT_EQ(Range1.begin(), Range2.begin()); EXPECT_EQ(Range1.end(), Range2.end()); - // We should be able to query if there are DPValues, + // We should be able to query if there are DbgVariableRecords, EXPECT_TRUE(BInst->hasDbgRecords()); EXPECT_TRUE(CInst->hasDbgRecords()); EXPECT_FALSE(DInst->hasDbgRecords()); @@ -417,12 +421,12 @@ TEST(BasicBlockDbgInfoTest, InstrDbgAccess) { // Dropping should be easy, BInst->dropDbgRecords(); EXPECT_FALSE(BInst->hasDbgRecords()); - EXPECT_EQ(BInst->DbgMarker->StoredDPValues.size(), 0u); + EXPECT_EQ(BInst->DebugMarker->StoredDbgRecords.size(), 0u); - // And we should be able to drop individual DPValues. - CInst->dropOneDbgRecord(DPV1); + // And we should be able to drop individual DbgVariableRecords. + CInst->dropOneDbgRecord(DVR1); EXPECT_FALSE(CInst->hasDbgRecords()); - EXPECT_EQ(CInst->DbgMarker->StoredDPValues.size(), 0u); + EXPECT_EQ(CInst->DebugMarker->StoredDbgRecords.size(), 0u); UseNewDbgInfoFormat = false; } @@ -514,7 +518,7 @@ protected: BasicBlock *BBEntry, *BBExit; BasicBlock::iterator Dest, First, Last; Instruction *BInst, *Branch, *CInst; - DPValue *DPVA, *DPVB, *DPVConst; + DbgVariableRecord *DVRA, *DVRB, *DVRConst; void SetUp() override { UseNewDbgInfoFormat = true; @@ -531,26 +535,30 @@ protected: Branch = &*Last; CInst = &*Dest; - DPVA = cast<DPValue>(&*BInst->DbgMarker->StoredDPValues.begin()); - DPVB = cast<DPValue>(&*Branch->DbgMarker->StoredDPValues.begin()); - DPVConst = cast<DPValue>(&*CInst->DbgMarker->StoredDPValues.begin()); + DVRA = + cast<DbgVariableRecord>(&*BInst->DebugMarker->StoredDbgRecords.begin()); + DVRB = cast<DbgVariableRecord>( + &*Branch->DebugMarker->StoredDbgRecords.begin()); + DVRConst = + cast<DbgVariableRecord>(&*CInst->DebugMarker->StoredDbgRecords.begin()); } void TearDown() override { UseNewDbgInfoFormat = false; } - bool InstContainsDPValue(Instruction *I, DPValue *DPV) { + bool InstContainsDbgVariableRecord(Instruction *I, DbgVariableRecord *DVR) { for (DbgRecord &D : I->getDbgRecordRange()) { - if (&D == DPV) { + if (&D == DVR) { // Confirm too that the links between the records are correct. - EXPECT_EQ(DPV->Marker, I->DbgMarker); - EXPECT_EQ(I->DbgMarker->MarkedInstr, I); + EXPECT_EQ(DVR->Marker, I->DebugMarker); + EXPECT_EQ(I->DebugMarker->MarkedInstr, I); return true; } } return false; } - bool CheckDPVOrder(Instruction *I, SmallVector<DPValue *> CheckVals) { + bool CheckDVROrder(Instruction *I, + SmallVector<DbgVariableRecord *> CheckVals) { SmallVector<DbgRecord *> Vals; for (DbgRecord &D : I->getDbgRecordRange()) Vals.push_back(&D); @@ -578,15 +586,15 @@ TEST_F(DbgSpliceTest, DbgSpliceTest0) { /* define i16 @f(i16 %a) !dbg !6 { BBEntry entry: -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -First %b = add i16 %a, 1, !dbg !11 -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -Last br label %exit, !dbg !11 +DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata +!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call +void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), +!dbg !11 Last br label %exit, !dbg !11 BBExit exit: -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata +!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, +!dbg !11 } Splice from First, not including leading dbg.value, to Last, including the @@ -595,15 +603,14 @@ Dest %c = add i16 %b, 1, !dbg !11 define i16 @f(i16 %a) !dbg !6 { BBEntry entry: -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -Last br label %exit, !dbg !11 +DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata +!DIExpression()), !dbg !11 Last br label %exit, !dbg !11 BBExit exit: -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -First %b = add i16 %a, 1, !dbg !11 -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata +!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call +void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), +!dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, !dbg !11 } @@ -613,14 +620,14 @@ Dest %c = add i16 %b, 1, !dbg !11 EXPECT_EQ(CInst->getParent(), BBExit); EXPECT_EQ(Branch->getParent(), BBEntry); - // DPVB: should be on Dest, in exit block. - EXPECT_TRUE(InstContainsDPValue(CInst, DPVB)); + // DVRB: should be on Dest, in exit block. + EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRB)); - // DPVA, should have "fallen" onto the branch, remained in entry block. - EXPECT_TRUE(InstContainsDPValue(Branch, DPVA)); + // DVRA, should have "fallen" onto the branch, remained in entry block. + EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRA)); - // DPVConst should be on the moved %b instruction. - EXPECT_TRUE(InstContainsDPValue(BInst, DPVConst)); + // DVRConst should be on the moved %b instruction. + EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRConst)); } TEST_F(DbgSpliceTest, DbgSpliceTest1) { @@ -631,15 +638,15 @@ TEST_F(DbgSpliceTest, DbgSpliceTest1) { /* define i16 @f(i16 %a) !dbg !6 { BBEntry entry: -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -First %b = add i16 %a, 1, !dbg !11 -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -Last br label %exit, !dbg !11 +DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata +!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call +void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), +!dbg !11 Last br label %exit, !dbg !11 BBExit exit: -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata +!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, +!dbg !11 } Splice from First, not including leading dbg.value, to Last, including the @@ -648,15 +655,15 @@ Dest %c = add i16 %b, 1, !dbg !11 define i16 @f(i16 %a) !dbg !6 { BBEntry entry: -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -Last br label %exit, !dbg !11 +DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata +!DIExpression()), !dbg !11 Last br label %exit, !dbg !11 BBExit exit: First %b = add i16 %a, 1, !dbg !11 -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata +!DIExpression()), !dbg !11 DVRConst call void @llvm.dbg.value(metadata i16 0, +metadata !9, metadata !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, +!dbg !11 ret i16 0, !dbg !11 } @@ -666,17 +673,17 @@ Dest %c = add i16 %b, 1, !dbg !11 EXPECT_EQ(CInst->getParent(), BBExit); EXPECT_EQ(Branch->getParent(), BBEntry); - // DPVB: should be on CInst, in exit block. - EXPECT_TRUE(InstContainsDPValue(CInst, DPVB)); + // DVRB: should be on CInst, in exit block. + EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRB)); - // DPVA, should have "fallen" onto the branch, remained in entry block. - EXPECT_TRUE(InstContainsDPValue(Branch, DPVA)); + // DVRA, should have "fallen" onto the branch, remained in entry block. + EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRA)); - // DPVConst should be behind / after the moved instructions, remain on CInst. - EXPECT_TRUE(InstContainsDPValue(CInst, DPVConst)); + // DVRConst should be behind / after the moved instructions, remain on CInst. + EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRConst)); - // Order of DPVB and DPVConst should be thus: - EXPECT_TRUE(CheckDPVOrder(CInst, {DPVB, DPVConst})); + // Order of DVRB and DVRConst should be thus: + EXPECT_TRUE(CheckDVROrder(CInst, {DVRB, DVRConst})); } TEST_F(DbgSpliceTest, DbgSpliceTest2) { @@ -687,15 +694,15 @@ TEST_F(DbgSpliceTest, DbgSpliceTest2) { /* define i16 @f(i16 %a) !dbg !6 { BBEntry entry: -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -First %b = add i16 %a, 1, !dbg !11 -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -Last br label %exit, !dbg !11 +DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata +!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call +void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), +!dbg !11 Last br label %exit, !dbg !11 BBExit exit: -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata +!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, +!dbg !11 } Splice from head of First, which includes the leading dbg.value, to Last, @@ -707,12 +714,12 @@ BBEntry entry: Last br label %exit, !dbg !11 BBExit exit: -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -First %b = add i16 %a, 1, !dbg !11 -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata +!DIExpression()), !dbg !11 DVRA call void @llvm.dbg.value(metadata i16 %a, +metadata !9, metadata !DIExpression()), !dbg !11 First %b = add i16 %a, 1, +!dbg !11 DVRB call void @llvm.dbg.value(metadata i16 %b, metadata !9, +metadata !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret +i16 0, !dbg !11 } @@ -721,18 +728,18 @@ Dest %c = add i16 %b, 1, !dbg !11 EXPECT_EQ(BInst->getParent(), BBExit); EXPECT_EQ(CInst->getParent(), BBExit); - // DPVB: should be on CInst, in exit block. - EXPECT_TRUE(InstContainsDPValue(CInst, DPVB)); + // DVRB: should be on CInst, in exit block. + EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRB)); - // DPVA, should have transferred with the spliced instructions, remains on + // DVRA, should have transferred with the spliced instructions, remains on // the "b" inst. - EXPECT_TRUE(InstContainsDPValue(BInst, DPVA)); + EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRA)); - // DPVConst should be ahead of the moved instructions, ahead of BInst. - EXPECT_TRUE(InstContainsDPValue(BInst, DPVConst)); + // DVRConst should be ahead of the moved instructions, ahead of BInst. + EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRConst)); - // Order of DPVA and DPVConst should be thus: - EXPECT_TRUE(CheckDPVOrder(BInst, {DPVConst, DPVA})); + // Order of DVRA and DVRConst should be thus: + EXPECT_TRUE(CheckDVROrder(BInst, {DVRConst, DVRA})); } TEST_F(DbgSpliceTest, DbgSpliceTest3) { @@ -743,15 +750,15 @@ TEST_F(DbgSpliceTest, DbgSpliceTest3) { /* define i16 @f(i16 %a) !dbg !6 { BBEntry entry: -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -First %b = add i16 %a, 1, !dbg !11 -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -Last br label %exit, !dbg !11 +DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata +!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call +void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), +!dbg !11 Last br label %exit, !dbg !11 BBExit exit: -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata +!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, +!dbg !11 } Splice from head of First, which includes the leading dbg.value, to Last, @@ -763,12 +770,12 @@ BBEntry entry: Last br label %exit, !dbg !11 BBExit exit: -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -First %b = add i16 %a, 1, !dbg !11 -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata +!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call +void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), +!dbg !11 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, +metadata !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret +i16 0, !dbg !11 } */ @@ -776,18 +783,18 @@ Dest %c = add i16 %b, 1, !dbg !11 EXPECT_EQ(BInst->getParent(), BBExit); EXPECT_EQ(CInst->getParent(), BBExit); - // DPVB: should be on CInst, in exit block. - EXPECT_TRUE(InstContainsDPValue(CInst, DPVB)); + // DVRB: should be on CInst, in exit block. + EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRB)); - // DPVA, should have transferred with the spliced instructions, remains on + // DVRA, should have transferred with the spliced instructions, remains on // the "b" inst. - EXPECT_TRUE(InstContainsDPValue(BInst, DPVA)); + EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRA)); - // DPVConst should be behind the moved instructions, ahead of CInst. - EXPECT_TRUE(InstContainsDPValue(CInst, DPVConst)); + // DVRConst should be behind the moved instructions, ahead of CInst. + EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRConst)); - // Order of DPVB and DPVConst should be thus: - EXPECT_TRUE(CheckDPVOrder(CInst, {DPVB, DPVConst})); + // Order of DVRB and DVRConst should be thus: + EXPECT_TRUE(CheckDVROrder(CInst, {DVRB, DVRConst})); } TEST_F(DbgSpliceTest, DbgSpliceTest4) { @@ -798,15 +805,15 @@ TEST_F(DbgSpliceTest, DbgSpliceTest4) { /* define i16 @f(i16 %a) !dbg !6 { BBEntry entry: -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -First %b = add i16 %a, 1, !dbg !11 -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -Last br label %exit, !dbg !11 +DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata +!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call +void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), +!dbg !11 Last br label %exit, !dbg !11 BBExit exit: -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata +!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, +!dbg !11 } Splice from First, not including the leading dbg.value, to Last, but NOT @@ -815,15 +822,15 @@ Dest %c = add i16 %b, 1, !dbg !11 define i16 @f(i16 %a) !dbg !6 { BBEntry entry: -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -Last br label %exit, !dbg !11 +DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata +!DIExpression()), !dbg !11 DVRB call void @llvm.dbg.value(metadata i16 %b, +metadata !9, metadata !DIExpression()), !dbg !11 Last br label %exit, !dbg +!11 BBExit exit: -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -First %b = add i16 %a, 1, !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata +!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 Dest %c = +add i16 %b, 1, !dbg !11 ret i16 0, !dbg !11 } */ @@ -832,17 +839,17 @@ Dest %c = add i16 %b, 1, !dbg !11 EXPECT_EQ(CInst->getParent(), BBExit); EXPECT_EQ(Branch->getParent(), BBEntry); - // DPVB: should be on Branch as before, remain in entry block. - EXPECT_TRUE(InstContainsDPValue(Branch, DPVB)); + // DVRB: should be on Branch as before, remain in entry block. + EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRB)); - // DPVA, should have remained in entry block, falls onto Branch inst. - EXPECT_TRUE(InstContainsDPValue(Branch, DPVA)); + // DVRA, should have remained in entry block, falls onto Branch inst. + EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRA)); - // DPVConst should be ahead of the moved instructions, BInst. - EXPECT_TRUE(InstContainsDPValue(BInst, DPVConst)); + // DVRConst should be ahead of the moved instructions, BInst. + EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRConst)); - // Order of DPVA and DPVA should be thus: - EXPECT_TRUE(CheckDPVOrder(Branch, {DPVA, DPVB})); + // Order of DVRA and DVRA should be thus: + EXPECT_TRUE(CheckDVROrder(Branch, {DVRA, DVRB})); } TEST_F(DbgSpliceTest, DbgSpliceTest5) { @@ -853,15 +860,15 @@ TEST_F(DbgSpliceTest, DbgSpliceTest5) { /* define i16 @f(i16 %a) !dbg !6 { BBEntry entry: -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -First %b = add i16 %a, 1, !dbg !11 -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -Last br label %exit, !dbg !11 +DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata +!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call +void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), +!dbg !11 Last br label %exit, !dbg !11 BBExit exit: -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata +!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, +!dbg !11 } Splice from First, not including the leading dbg.value, to Last, but NOT @@ -870,15 +877,16 @@ Dest %c = add i16 %b, 1, !dbg !11 define i16 @f(i16 %a) !dbg !6 { BBEntry entry: -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -Last br label %exit, !dbg !11 +DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata +!DIExpression()), !dbg !11 DVRB call void @llvm.dbg.value(metadata i16 %b, +metadata !9, metadata !DIExpression()), !dbg !11 Last br label %exit, !dbg +!11 BBExit exit: First %b = add i16 %a, 1, !dbg !11 -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata +!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, +!dbg !11 } */ @@ -887,17 +895,17 @@ Dest %c = add i16 %b, 1, !dbg !11 EXPECT_EQ(CInst->getParent(), BBExit); EXPECT_EQ(Branch->getParent(), BBEntry); - // DPVB: should be on Branch as before, remain in entry block. - EXPECT_TRUE(InstContainsDPValue(Branch, DPVB)); + // DVRB: should be on Branch as before, remain in entry block. + EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRB)); - // DPVA, should have remained in entry block, falls onto Branch inst. - EXPECT_TRUE(InstContainsDPValue(Branch, DPVA)); + // DVRA, should have remained in entry block, falls onto Branch inst. + EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRA)); - // DPVConst should be behind of the moved instructions, on CInst. - EXPECT_TRUE(InstContainsDPValue(CInst, DPVConst)); + // DVRConst should be behind of the moved instructions, on CInst. + EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRConst)); - // Order of DPVA and DPVB should be thus: - EXPECT_TRUE(CheckDPVOrder(Branch, {DPVA, DPVB})); + // Order of DVRA and DVRB should be thus: + EXPECT_TRUE(CheckDVROrder(Branch, {DVRA, DVRB})); } TEST_F(DbgSpliceTest, DbgSpliceTest6) { @@ -908,15 +916,15 @@ TEST_F(DbgSpliceTest, DbgSpliceTest6) { /* define i16 @f(i16 %a) !dbg !6 { BBEntry entry: -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -First %b = add i16 %a, 1, !dbg !11 -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -Last br label %exit, !dbg !11 +DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata +!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call +void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), +!dbg !11 Last br label %exit, !dbg !11 BBExit exit: -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata +!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, +!dbg !11 } Splice from First, including the leading dbg.value, to Last, but NOT @@ -925,15 +933,14 @@ Dest %c = add i16 %b, 1, !dbg !11 define i16 @f(i16 %a) !dbg !6 { BBEntry entry: -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -Last br label %exit, !dbg !11 +DVRB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata +!DIExpression()), !dbg !11 Last br label %exit, !dbg !11 BBExit exit: -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -First %b = add i16 %a, 1, !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata +!DIExpression()), !dbg !11 DVRA call void @llvm.dbg.value(metadata i16 %a, +metadata !9, metadata !DIExpression()), !dbg !11 First %b = add i16 %a, 1, +!dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, !dbg !11 } */ @@ -942,17 +949,17 @@ Dest %c = add i16 %b, 1, !dbg !11 EXPECT_EQ(CInst->getParent(), BBExit); EXPECT_EQ(Branch->getParent(), BBEntry); - // DPVB: should be on Branch as before, remain in entry block. - EXPECT_TRUE(InstContainsDPValue(Branch, DPVB)); + // DVRB: should be on Branch as before, remain in entry block. + EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRB)); - // DPVA, should have transferred to BBExit, on B inst. - EXPECT_TRUE(InstContainsDPValue(BInst, DPVA)); + // DVRA, should have transferred to BBExit, on B inst. + EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRA)); - // DPVConst should be ahead of the moved instructions, on BInst. - EXPECT_TRUE(InstContainsDPValue(BInst, DPVConst)); + // DVRConst should be ahead of the moved instructions, on BInst. + EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRConst)); - // Order of DPVA and DPVConst should be thus: - EXPECT_TRUE(CheckDPVOrder(BInst, {DPVConst, DPVA})); + // Order of DVRA and DVRConst should be thus: + EXPECT_TRUE(CheckDVROrder(BInst, {DVRConst, DVRA})); } TEST_F(DbgSpliceTest, DbgSpliceTest7) { @@ -963,15 +970,15 @@ TEST_F(DbgSpliceTest, DbgSpliceTest7) { /* define i16 @f(i16 %a) !dbg !6 { BBEntry entry: -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -First %b = add i16 %a, 1, !dbg !11 -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -Last br label %exit, !dbg !11 +DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata +!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call +void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), +!dbg !11 Last br label %exit, !dbg !11 BBExit exit: -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata +!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, +!dbg !11 } Splice from First, including the leading dbg.value, to Last, but NOT @@ -980,15 +987,14 @@ Dest %c = add i16 %b, 1, !dbg !11 define i16 @f(i16 %a) !dbg !6 { BBEntry entry: -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -Last br label %exit, !dbg !11 +DVRB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata +!DIExpression()), !dbg !11 Last br label %exit, !dbg !11 BBExit exit: -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -First %b = add i16 %a, 1, !dbg !11 -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata +!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRConst call +void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), +!dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, !dbg !11 } */ @@ -997,21 +1003,21 @@ Dest %c = add i16 %b, 1, !dbg !11 EXPECT_EQ(CInst->getParent(), BBExit); EXPECT_EQ(Branch->getParent(), BBEntry); - // DPVB: should be on Branch as before, remain in entry block. - EXPECT_TRUE(InstContainsDPValue(Branch, DPVB)); + // DVRB: should be on Branch as before, remain in entry block. + EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRB)); - // DPVA, should have transferred to BBExit, on B inst. - EXPECT_TRUE(InstContainsDPValue(BInst, DPVA)); + // DVRA, should have transferred to BBExit, on B inst. + EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRA)); - // DPVConst should be after of the moved instructions, on CInst. - EXPECT_TRUE(InstContainsDPValue(CInst, DPVConst)); + // DVRConst should be after of the moved instructions, on CInst. + EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRConst)); } // But wait, there's more! What if you splice a range that is empty, but // implicitly contains debug-info? In the dbg.value design for debug-info, -// this would be an explicit range, but in DPValue debug-info, it isn't. -// Check that if we try to do that, with differing head-bit values, that -// DPValues are transferred. +// this would be an explicit range, but in DbgVariableRecord debug-info, it +// isn't. Check that if we try to do that, with differing head-bit values, that +// DbgVariableRecords are transferred. // Test with empty transfers to Dest, with head bit set and not set. TEST_F(DbgSpliceTest, DbgSpliceEmpty0) { @@ -1021,31 +1027,31 @@ TEST_F(DbgSpliceTest, DbgSpliceEmpty0) { /* define i16 @f(i16 %a) !dbg !6 { BBEntry entry: -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -First %b = add i16 %a, 1, !dbg !11 -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -Last br label %exit, !dbg !11 +DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata +!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call +void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), +!dbg !11 Last br label %exit, !dbg !11 BBExit exit: -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata +!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, +!dbg !11 } Splice from BBEntry.getFirstInsertionPt to First -- this implicitly is a - splice of DPVA, but the iterators are pointing at the same instruction. The + splice of DVRA, but the iterators are pointing at the same instruction. The only difference is the setting of the head bit. Becomes; define i16 @f(i16 %a) !dbg !6 { First %b = add i16 %a, 1, !dbg !11 -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -Last br label %exit, !dbg !11 +DVRB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata +!DIExpression()), !dbg !11 Last br label %exit, !dbg !11 BBExit exit: -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata +!DIExpression()), !dbg !11 DVRA call void @llvm.dbg.value(metadata i16 %a, +metadata !9, metadata !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, +!dbg !11 ret i16 0, !dbg !11 } */ @@ -1054,17 +1060,17 @@ Dest %c = add i16 %b, 1, !dbg !11 EXPECT_EQ(CInst->getParent(), BBExit); EXPECT_EQ(Branch->getParent(), BBEntry); - // DPVB: should be on Branch as before, remain in entry block. - EXPECT_TRUE(InstContainsDPValue(Branch, DPVB)); + // DVRB: should be on Branch as before, remain in entry block. + EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRB)); - // DPVA, should have transferred to BBExit, on C inst. - EXPECT_TRUE(InstContainsDPValue(CInst, DPVA)); + // DVRA, should have transferred to BBExit, on C inst. + EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRA)); - // DPVConst should be ahead of the moved DPValue, on CInst. - EXPECT_TRUE(InstContainsDPValue(CInst, DPVConst)); + // DVRConst should be ahead of the moved DbgVariableRecord, on CInst. + EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRConst)); - // Order of DPVA and DPVConst should be thus: - EXPECT_TRUE(CheckDPVOrder(CInst, {DPVConst, DPVA})); + // Order of DVRA and DVRConst should be thus: + EXPECT_TRUE(CheckDVROrder(CInst, {DVRConst, DVRA})); } TEST_F(DbgSpliceTest, DbgSpliceEmpty1) { @@ -1074,32 +1080,32 @@ TEST_F(DbgSpliceTest, DbgSpliceEmpty1) { /* define i16 @f(i16 %a) !dbg !6 { BBEntry entry: -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -First %b = add i16 %a, 1, !dbg !11 -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -Last br label %exit, !dbg !11 +DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata +!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call +void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), +!dbg !11 Last br label %exit, !dbg !11 BBExit exit: -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata +!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, +!dbg !11 } Splice from BBEntry.getFirstInsertionPt to First -- this implicitly is a - splice of DPVA, but the iterators are pointing at the same instruction. The + splice of DVRA, but the iterators are pointing at the same instruction. The only difference is the setting of the head bit. Insert at head of Dest, - i.e. before DPVConst. Becomes; + i.e. before DVRConst. Becomes; define i16 @f(i16 %a) !dbg !6 { First %b = add i16 %a, 1, !dbg !11 -DPVB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11 -Last br label %exit, !dbg !11 +DVRB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata +!DIExpression()), !dbg !11 Last br label %exit, !dbg !11 BBExit exit: -DPVA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11 -DPVConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11 -Dest %c = add i16 %b, 1, !dbg !11 - ret i16 0, !dbg !11 +DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata +!DIExpression()), !dbg !11 DVRConst call void @llvm.dbg.value(metadata i16 0, +metadata !9, metadata !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, +!dbg !11 ret i16 0, !dbg !11 } */ @@ -1108,21 +1114,21 @@ Dest %c = add i16 %b, 1, !dbg !11 EXPECT_EQ(CInst->getParent(), BBExit); EXPECT_EQ(Branch->getParent(), BBEntry); - // DPVB: should be on Branch as before, remain in entry block. - EXPECT_TRUE(InstContainsDPValue(Branch, DPVB)); + // DVRB: should be on Branch as before, remain in entry block. + EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRB)); - // DPVA, should have transferred to BBExit, on C inst. - EXPECT_TRUE(InstContainsDPValue(CInst, DPVA)); + // DVRA, should have transferred to BBExit, on C inst. + EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRA)); - // DPVConst should be ahead of the moved DPValue, on CInst. - EXPECT_TRUE(InstContainsDPValue(CInst, DPVConst)); + // DVRConst should be ahead of the moved DbgVariableRecord, on CInst. + EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRConst)); - // Order of DPVA and DPVConst should be thus: - EXPECT_TRUE(CheckDPVOrder(CInst, {DPVA, DPVConst})); + // Order of DVRA and DVRConst should be thus: + EXPECT_TRUE(CheckDVROrder(CInst, {DVRA, DVRConst})); } -// If we splice new instructions into a block with trailing DPValues, then -// the trailing DPValues should get flushed back out. +// If we splice new instructions into a block with trailing DbgVariableRecords, +// then the trailing DbgVariableRecords should get flushed back out. TEST(BasicBlockDbgInfoTest, DbgSpliceTrailing) { LLVMContext C; UseNewDbgInfoFormat = true; @@ -1159,7 +1165,7 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceTrailing) { BasicBlock &Exit = *Entry.getNextNode(); M->convertToNewDbgValues(); - // Begin by forcing entry block to have dangling DPValue. + // Begin by forcing entry block to have dangling DbgVariableRecord. Entry.getTerminator()->eraseFromParent(); ASSERT_NE(Entry.getTrailingDbgRecords(), nullptr); EXPECT_TRUE(Entry.empty()); @@ -1167,19 +1173,19 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceTrailing) { // Now transfer the entire contents of the exit block into the entry. Entry.splice(Entry.end(), &Exit, Exit.begin(), Exit.end()); - // The trailing DPValue should have been placed at the front of what's been - // spliced in. + // The trailing DbgVariableRecord should have been placed at the front of + // what's been spliced in. Instruction *BInst = &*Entry.begin(); - ASSERT_TRUE(BInst->DbgMarker); - EXPECT_EQ(BInst->DbgMarker->StoredDPValues.size(), 1u); + ASSERT_TRUE(BInst->DebugMarker); + EXPECT_EQ(BInst->DebugMarker->StoredDbgRecords.size(), 1u); UseNewDbgInfoFormat = false; } -// When we remove instructions from the program, adjacent DPValues coalesce -// together into one DPMarker. In "old" dbg.value mode you could re-insert -// the removed instruction back into the middle of a sequence of dbg.values. -// Test that this can be replicated correctly by DPValues +// When we remove instructions from the program, adjacent DbgVariableRecords +// coalesce together into one DbgMarker. In "old" dbg.value mode you could +// re-insert the removed instruction back into the middle of a sequence of +// dbg.values. Test that this can be replicated correctly by DbgVariableRecords TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsert) { LLVMContext C; UseNewDbgInfoFormat = true; @@ -1221,7 +1227,7 @@ TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsert) { Instruction *RetInst = AddInst->getNextNode(); ASSERT_TRUE(isa<ReturnInst>(RetInst)); - // add and sub should both have one DPValue on add and ret. + // add and sub should both have one DbgVariableRecord on add and ret. EXPECT_FALSE(SubInst->hasDbgRecords()); EXPECT_TRUE(AddInst->hasDbgRecords()); EXPECT_TRUE(RetInst->hasDbgRecords()); @@ -1232,20 +1238,21 @@ TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsert) { // The Supported (TM) code sequence for removing then reinserting insts // after another instruction: - std::optional<DPValue::self_iterator> Pos = + std::optional<DbgVariableRecord::self_iterator> Pos = AddInst->getDbgReinsertionPosition(); AddInst->removeFromParent(); // We should have a re-insertion position. ASSERT_TRUE(Pos); - // Both DPValues should now be attached to the ret inst. + // Both DbgVariableRecords should now be attached to the ret inst. auto R3 = RetInst->getDbgRecordRange(); EXPECT_EQ(std::distance(R3.begin(), R3.end()), 2u); // Re-insert and re-insert. AddInst->insertAfter(SubInst); Entry.reinsertInstInDbgRecords(AddInst, Pos); - // We should be back into a position of having one DPValue on add and ret. + // We should be back into a position of having one DbgVariableRecord on add + // and ret. EXPECT_FALSE(SubInst->hasDbgRecords()); EXPECT_TRUE(AddInst->hasDbgRecords()); EXPECT_TRUE(RetInst->hasDbgRecords()); @@ -1257,9 +1264,9 @@ TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsert) { UseNewDbgInfoFormat = false; } -// Test instruction removal and re-insertion, this time with one DPValue that -// should hop up one instruction. -TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsertForOneDPValue) { +// Test instruction removal and re-insertion, this time with one +// DbgVariableRecord that should hop up one instruction. +TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsertForOneDbgVariableRecord) { LLVMContext C; UseNewDbgInfoFormat = true; @@ -1299,7 +1306,7 @@ TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsertForOneDPValue) { Instruction *RetInst = AddInst->getNextNode(); ASSERT_TRUE(isa<ReturnInst>(RetInst)); - // There should be one DPValue. + // There should be one DbgVariableRecord. EXPECT_FALSE(SubInst->hasDbgRecords()); EXPECT_TRUE(AddInst->hasDbgRecords()); EXPECT_FALSE(RetInst->hasDbgRecords()); @@ -1307,13 +1314,13 @@ TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsertForOneDPValue) { EXPECT_EQ(std::distance(R1.begin(), R1.end()), 1u); // The Supported (TM) code sequence for removing then reinserting insts: - std::optional<DPValue::self_iterator> Pos = + std::optional<DbgVariableRecord::self_iterator> Pos = AddInst->getDbgReinsertionPosition(); AddInst->removeFromParent(); - // No re-insertion position as there were no DPValues on the ret. + // No re-insertion position as there were no DbgVariableRecords on the ret. ASSERT_FALSE(Pos); - // The single DPValue should now be attached to the ret inst. + // The single DbgVariableRecord should now be attached to the ret inst. EXPECT_TRUE(RetInst->hasDbgRecords()); auto R2 = RetInst->getDbgRecordRange(); EXPECT_EQ(std::distance(R2.begin(), R2.end()), 1u); @@ -1321,7 +1328,8 @@ TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsertForOneDPValue) { // Re-insert and re-insert. AddInst->insertAfter(SubInst); Entry.reinsertInstInDbgRecords(AddInst, Pos); - // We should be back into a position of having one DPValue on the AddInst. + // We should be back into a position of having one DbgVariableRecord on the + // AddInst. EXPECT_FALSE(SubInst->hasDbgRecords()); EXPECT_TRUE(AddInst->hasDbgRecords()); EXPECT_FALSE(RetInst->hasDbgRecords()); @@ -1374,7 +1382,7 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty1) { BasicBlock &Exit = *Entry.getNextNode(); M->convertToNewDbgValues(); - // Begin by forcing entry block to have dangling DPValue. + // Begin by forcing entry block to have dangling DbgVariableRecord. Entry.getTerminator()->eraseFromParent(); ASSERT_NE(Entry.getTrailingDbgRecords(), nullptr); EXPECT_TRUE(Entry.empty()); @@ -1387,17 +1395,17 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty1) { // should be in the correct order of %a, then 0. Instruction *BInst = &*Entry.begin(); ASSERT_TRUE(BInst->hasDbgRecords()); - EXPECT_EQ(BInst->DbgMarker->StoredDPValues.size(), 2u); - SmallVector<DPValue *, 2> DPValues; - for (DbgRecord &DPV : BInst->getDbgRecordRange()) - DPValues.push_back(cast<DPValue>(&DPV)); + EXPECT_EQ(BInst->DebugMarker->StoredDbgRecords.size(), 2u); + SmallVector<DbgVariableRecord *, 2> DbgVariableRecords; + for (DbgRecord &DVR : BInst->getDbgRecordRange()) + DbgVariableRecords.push_back(cast<DbgVariableRecord>(&DVR)); - EXPECT_EQ(DPValues[0]->getVariableLocationOp(0), F.getArg(0)); - Value *SecondDPVValue = DPValues[1]->getVariableLocationOp(0); - ASSERT_TRUE(isa<ConstantInt>(SecondDPVValue)); - EXPECT_EQ(cast<ConstantInt>(SecondDPVValue)->getZExtValue(), 0ull); + EXPECT_EQ(DbgVariableRecords[0]->getVariableLocationOp(0), F.getArg(0)); + Value *SecondDVRValue = DbgVariableRecords[1]->getVariableLocationOp(0); + ASSERT_TRUE(isa<ConstantInt>(SecondDVRValue)); + EXPECT_EQ(cast<ConstantInt>(SecondDVRValue)->getZExtValue(), 0ull); - // No trailing DPValues in the entry block now. + // No trailing DbgVariableRecords in the entry block now. EXPECT_EQ(Entry.getTrailingDbgRecords(), nullptr); UseNewDbgInfoFormat = false; @@ -1444,31 +1452,31 @@ TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty2) { BasicBlock &Exit = *Entry.getNextNode(); M->convertToNewDbgValues(); - // Begin by forcing entry block to have dangling DPValue. + // Begin by forcing entry block to have dangling DbgVariableRecord. Entry.getTerminator()->eraseFromParent(); ASSERT_NE(Entry.getTrailingDbgRecords(), nullptr); EXPECT_TRUE(Entry.empty()); // Now transfer into the entry block -- fetching the first instruction with // begin and then calling getIterator clears the "head" bit, meaning that the - // range to move will not include any leading DPValues. + // range to move will not include any leading DbgVariableRecords. Entry.splice(Entry.end(), &Exit, Exit.begin()->getIterator(), Exit.end()); // We should now have one dbg.values on the first instruction, %a. Instruction *BInst = &*Entry.begin(); ASSERT_TRUE(BInst->hasDbgRecords()); - EXPECT_EQ(BInst->DbgMarker->StoredDPValues.size(), 1u); - SmallVector<DPValue *, 2> DPValues; - for (DbgRecord &DPV : BInst->getDbgRecordRange()) - DPValues.push_back(cast<DPValue>(&DPV)); + EXPECT_EQ(BInst->DebugMarker->StoredDbgRecords.size(), 1u); + SmallVector<DbgVariableRecord *, 2> DbgVariableRecords; + for (DbgRecord &DVR : BInst->getDbgRecordRange()) + DbgVariableRecords.push_back(cast<DbgVariableRecord>(&DVR)); - EXPECT_EQ(DPValues[0]->getVariableLocationOp(0), F.getArg(0)); - // No trailing DPValues in the entry block now. + EXPECT_EQ(DbgVariableRecords[0]->getVariableLocationOp(0), F.getArg(0)); + // No trailing DbgVariableRecords in the entry block now. EXPECT_EQ(Entry.getTrailingDbgRecords(), nullptr); // We should have nothing left in the exit block... EXPECT_TRUE(Exit.empty()); - // ... except for some dangling DPValues. + // ... except for some dangling DbgVariableRecords. EXPECT_NE(Exit.getTrailingDbgRecords(), nullptr); EXPECT_FALSE(Exit.getTrailingDbgRecords()->empty()); Exit.getTrailingDbgRecords()->eraseFromParent(); diff --git a/llvm/unittests/IR/ConstantRangeTest.cpp b/llvm/unittests/IR/ConstantRangeTest.cpp index 34a162a5514e951b2972dcedd551a37e0a3137af..8ec120d70e99f65b3301f363a27cf0b9ce9944a7 100644 --- a/llvm/unittests/IR/ConstantRangeTest.cpp +++ b/llvm/unittests/IR/ConstantRangeTest.cpp @@ -2479,6 +2479,24 @@ TEST_F(ConstantRangeTest, castOps) { ConstantRange IntToPtr = A.castOp(Instruction::IntToPtr, 64); EXPECT_EQ(64u, IntToPtr.getBitWidth()); EXPECT_TRUE(IntToPtr.isFullSet()); + + ConstantRange UIToFP = A.castOp(Instruction::UIToFP, 16); + EXPECT_EQ(16u, UIToFP.getBitWidth()); + EXPECT_TRUE(UIToFP.isFullSet()); + + ConstantRange UIToFP2 = A.castOp(Instruction::UIToFP, 64); + ConstantRange B(APInt(64, 0), APInt(64, 65536)); + EXPECT_EQ(64u, UIToFP2.getBitWidth()); + EXPECT_EQ(B, UIToFP2); + + ConstantRange SIToFP = A.castOp(Instruction::SIToFP, 16); + EXPECT_EQ(16u, SIToFP.getBitWidth()); + EXPECT_TRUE(SIToFP.isFullSet()); + + ConstantRange SIToFP2 = A.castOp(Instruction::SIToFP, 64); + ConstantRange C(APInt(64, -32768), APInt(64, 32768)); + EXPECT_EQ(64u, SIToFP2.getBitWidth()); + EXPECT_EQ(C, SIToFP2); } TEST_F(ConstantRangeTest, binaryAnd) { diff --git a/llvm/unittests/IR/DebugInfoTest.cpp b/llvm/unittests/IR/DebugInfoTest.cpp index 0b019c26148b5c973aea6089f59da4e092f39c51..d06b979bf4a1c4adf6e6f99b29867c30118a2a4d 100644 --- a/llvm/unittests/IR/DebugInfoTest.cpp +++ b/llvm/unittests/IR/DebugInfoTest.cpp @@ -234,8 +234,8 @@ TEST(DbgVariableIntrinsic, EmptyMDIsKillLocation) { EXPECT_TRUE(DbgDeclare->isKillLocation()); } -// Duplicate of above test, but in DPValue representation. -TEST(MetadataTest, DeleteInstUsedByDPValue) { +// Duplicate of above test, but in DbgVariableRecord representation. +TEST(MetadataTest, DeleteInstUsedByDbgVariableRecord) { LLVMContext C; std::unique_ptr<Module> M = parseIR(C, R"( define i16 @f(i16 %a) !dbg !6 { @@ -267,26 +267,26 @@ TEST(MetadataTest, DeleteInstUsedByDPValue) { Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHI(); M->convertToNewDbgValues(); - // Find the DPValues using %b. + // Find the DbgVariableRecords using %b. SmallVector<DbgValueInst *, 2> DVIs; - SmallVector<DPValue *, 2> DPVs; - findDbgValues(DVIs, &I, &DPVs); - ASSERT_EQ(DPVs.size(), 2u); + SmallVector<DbgVariableRecord *, 2> DVRs; + findDbgValues(DVIs, &I, &DVRs); + ASSERT_EQ(DVRs.size(), 2u); - // Delete %b. The DPValue should now point to undef. + // Delete %b. The DbgVariableRecord should now point to undef. I.eraseFromParent(); - EXPECT_EQ(DPVs[0]->getNumVariableLocationOps(), 1u); - EXPECT_TRUE(isa<UndefValue>(DPVs[0]->getVariableLocationOp(0))); - EXPECT_TRUE(DPVs[0]->isKillLocation()); - EXPECT_EQ(DPVs[1]->getNumVariableLocationOps(), 2u); - EXPECT_TRUE(isa<UndefValue>(DPVs[1]->getVariableLocationOp(1))); - EXPECT_TRUE(DPVs[1]->isKillLocation()); + EXPECT_EQ(DVRs[0]->getNumVariableLocationOps(), 1u); + EXPECT_TRUE(isa<UndefValue>(DVRs[0]->getVariableLocationOp(0))); + EXPECT_TRUE(DVRs[0]->isKillLocation()); + EXPECT_EQ(DVRs[1]->getNumVariableLocationOps(), 2u); + EXPECT_TRUE(isa<UndefValue>(DVRs[1]->getVariableLocationOp(1))); + EXPECT_TRUE(DVRs[1]->isKillLocation()); UseNewDbgInfoFormat = OldDbgValueMode; } // Ensure that the order of dbg.value intrinsics returned by findDbgValues, and -// their corresponding DPValue representation, are consistent. -TEST(MetadataTest, OrderingOfDPValues) { +// their corresponding DbgVariableRecord representation, are consistent. +TEST(MetadataTest, OrderingOfDbgVariableRecords) { LLVMContext C; std::unique_ptr<Module> M = parseIR(C, R"( define i16 @f(i16 %a) !dbg !6 { @@ -319,10 +319,10 @@ TEST(MetadataTest, OrderingOfDPValues) { Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHI(); SmallVector<DbgValueInst *, 2> DVIs; - SmallVector<DPValue *, 2> DPVs; - findDbgValues(DVIs, &I, &DPVs); + SmallVector<DbgVariableRecord *, 2> DVRs; + findDbgValues(DVIs, &I, &DVRs); ASSERT_EQ(DVIs.size(), 2u); - ASSERT_EQ(DPVs.size(), 0u); + ASSERT_EQ(DVRs.size(), 0u); // The correct order of dbg.values is given by their use-list, which becomes // the reverse order of creation. Thus the dbg.values should come out as @@ -332,17 +332,17 @@ TEST(MetadataTest, OrderingOfDPValues) { DILocalVariable *Var1 = DVIs[1]->getVariable(); EXPECT_TRUE(Var1->getName() == "foo"); - // Now try again, but in DPValue form. + // Now try again, but in DbgVariableRecord form. DVIs.clear(); M->convertToNewDbgValues(); - findDbgValues(DVIs, &I, &DPVs); + findDbgValues(DVIs, &I, &DVRs); ASSERT_EQ(DVIs.size(), 0u); - ASSERT_EQ(DPVs.size(), 2u); + ASSERT_EQ(DVRs.size(), 2u); - Var0 = DPVs[0]->getVariable(); + Var0 = DVRs[0]->getVariable(); EXPECT_TRUE(Var0->getName() == "bar"); - Var1 = DPVs[1]->getVariable(); + Var1 = DVRs[1]->getVariable(); EXPECT_TRUE(Var1->getName() == "foo"); M->convertFromNewDbgValues(); @@ -861,9 +861,9 @@ TEST(AssignmentTrackingTest, InstrMethods) { } } -// Test some very straight-forward operations on DPValues -- these are +// Test some very straight-forward operations on DbgVariableRecords -- these are // dbg.values that have been converted to a non-instruction format. -TEST(MetadataTest, ConvertDbgToDPValue) { +TEST(MetadataTest, ConvertDbgToDbgVariableRecord) { LLVMContext C; std::unique_ptr<Module> M = parseIR(C, R"( define i16 @f(i16 %a) !dbg !6 { @@ -900,7 +900,7 @@ TEST(MetadataTest, ConvertDbgToDPValue) { const DIExpression *Expr = nullptr; const DILocation *Loc = nullptr; const Metadata *MLoc = nullptr; - DPValue *DPV1 = nullptr; + DbgVariableRecord *DVR1 = nullptr; { DbgValueInst *DPI = dyn_cast<DbgValueInst>(&I); ASSERT_TRUE(DPI); @@ -909,17 +909,18 @@ TEST(MetadataTest, ConvertDbgToDPValue) { Loc = DPI->getDebugLoc().get(); MLoc = DPI->getRawLocation(); - // Test the creation of a DPValue and it's conversion back to a dbg.value. - DPV1 = new DPValue(DPI); - EXPECT_EQ(DPV1->getVariable(), Var); - EXPECT_EQ(DPV1->getExpression(), Expr); - EXPECT_EQ(DPV1->getDebugLoc().get(), Loc); - EXPECT_EQ(DPV1->getRawLocation(), MLoc); + // Test the creation of a DbgVariableRecord and it's conversion back to a + // dbg.value. + DVR1 = new DbgVariableRecord(DPI); + EXPECT_EQ(DVR1->getVariable(), Var); + EXPECT_EQ(DVR1->getExpression(), Expr); + EXPECT_EQ(DVR1->getDebugLoc().get(), Loc); + EXPECT_EQ(DVR1->getRawLocation(), MLoc); // Erase dbg.value, DPI->eraseFromParent(); - // Re-create from DPV1, inserting at front. - DPV1->createDebugIntrinsic(&*M, + // Re-create from DVR1, inserting at front. + DVR1->createDebugIntrinsic(&*M, &M->getFunction("f")->getEntryBlock().front()); Instruction *NewDPI = &M->getFunction("f")->getEntryBlock().front(); @@ -931,113 +932,116 @@ TEST(MetadataTest, ConvertDbgToDPValue) { EXPECT_EQ(DPI2->getRawLocation(), MLoc); } - // Fetch the second dbg.value, convert it to a DPValue, + // Fetch the second dbg.value, convert it to a DbgVariableRecord, BasicBlock::iterator It = M->getFunction("f")->getEntryBlock().begin(); It = std::next(std::next(It)); DbgValueInst *DPI3 = dyn_cast<DbgValueInst>(It); ASSERT_TRUE(DPI3); - DPValue *DPV2 = new DPValue(DPI3); + DbgVariableRecord *DVR2 = new DbgVariableRecord(DPI3); // These dbg.values are supposed to refer to different values. - EXPECT_NE(DPV1->getRawLocation(), DPV2->getRawLocation()); + EXPECT_NE(DVR1->getRawLocation(), DVR2->getRawLocation()); - // Try manipulating DPValues and markers in the exit block. + // Try manipulating DbgVariableRecords and markers in the exit block. BasicBlock *ExitBlock = &*std::next(M->getFunction("f")->getEntryBlock().getIterator()); Instruction *FirstInst = &ExitBlock->front(); Instruction *RetInst = &*std::next(FirstInst->getIterator()); - // Set-up DPMarkers in this block. + // Set-up DbgMarkers in this block. ExitBlock->IsNewDbgInfoFormat = true; ExitBlock->createMarker(FirstInst); ExitBlock->createMarker(RetInst); - // Insert DPValues into markers, order should come out DPV2, DPV1. - FirstInst->DbgMarker->insertDbgRecord(DPV1, false); - FirstInst->DbgMarker->insertDbgRecord(DPV2, true); + // Insert DbgRecords into markers, order should come out DVR2, DVR1. + FirstInst->DebugMarker->insertDbgRecord(DVR1, false); + FirstInst->DebugMarker->insertDbgRecord(DVR2, true); unsigned int ItCount = 0; - for (DbgRecord &Item : FirstInst->DbgMarker->getDbgRecordRange()) { - EXPECT_TRUE((&Item == DPV2 && ItCount == 0) || - (&Item == DPV1 && ItCount == 1)); - EXPECT_EQ(Item.getMarker(), FirstInst->DbgMarker); + for (DbgRecord &Item : FirstInst->DebugMarker->getDbgRecordRange()) { + EXPECT_TRUE((&Item == DVR2 && ItCount == 0) || + (&Item == DVR1 && ItCount == 1)); + EXPECT_EQ(Item.getMarker(), FirstInst->DebugMarker); ++ItCount; } - // Clone them onto the second marker -- should allocate new DPVs. - RetInst->DbgMarker->cloneDebugInfoFrom(FirstInst->DbgMarker, std::nullopt, false); - EXPECT_EQ(RetInst->DbgMarker->StoredDPValues.size(), 2u); + // Clone them onto the second marker -- should allocate new DVRs. + RetInst->DebugMarker->cloneDebugInfoFrom(FirstInst->DebugMarker, std::nullopt, + false); + EXPECT_EQ(RetInst->DebugMarker->StoredDbgRecords.size(), 2u); ItCount = 0; // Check these things store the same information; but that they're not the same // objects. - for (DPValue &Item : - DPValue::filter(RetInst->DbgMarker->getDbgRecordRange())) { - EXPECT_TRUE((Item.getRawLocation() == DPV2->getRawLocation() && ItCount == 0) || - (Item.getRawLocation() == DPV1->getRawLocation() && ItCount == 1)); - - EXPECT_EQ(Item.getMarker(), RetInst->DbgMarker); - EXPECT_NE(&Item, DPV1); - EXPECT_NE(&Item, DPV2); + for (DbgVariableRecord &Item : + filterDbgVars(RetInst->DebugMarker->getDbgRecordRange())) { + EXPECT_TRUE( + (Item.getRawLocation() == DVR2->getRawLocation() && ItCount == 0) || + (Item.getRawLocation() == DVR1->getRawLocation() && ItCount == 1)); + + EXPECT_EQ(Item.getMarker(), RetInst->DebugMarker); + EXPECT_NE(&Item, DVR1); + EXPECT_NE(&Item, DVR2); ++ItCount; } - RetInst->DbgMarker->dropDbgRecords(); - EXPECT_EQ(RetInst->DbgMarker->StoredDPValues.size(), 0u); - - // Try cloning one single DPValue. - auto DIIt = std::next(FirstInst->DbgMarker->getDbgRecordRange().begin()); - RetInst->DbgMarker->cloneDebugInfoFrom(FirstInst->DbgMarker, DIIt, false); - EXPECT_EQ(RetInst->DbgMarker->StoredDPValues.size(), 1u); - // The second DPValue should have been cloned; it should have the same values - // as DPV1. - EXPECT_EQ(cast<DPValue>(RetInst->DbgMarker->StoredDPValues.begin()) - ->getRawLocation(), - DPV1->getRawLocation()); - // We should be able to drop individual DPValues. - RetInst->DbgMarker->dropOneDbgRecord( - &*RetInst->DbgMarker->StoredDPValues.begin()); - - // "Aborb" a DPMarker: this means pretend that the instruction it's attached + RetInst->DebugMarker->dropDbgRecords(); + EXPECT_EQ(RetInst->DebugMarker->StoredDbgRecords.size(), 0u); + + // Try cloning one single DbgVariableRecord. + auto DIIt = std::next(FirstInst->DebugMarker->getDbgRecordRange().begin()); + RetInst->DebugMarker->cloneDebugInfoFrom(FirstInst->DebugMarker, DIIt, false); + EXPECT_EQ(RetInst->DebugMarker->StoredDbgRecords.size(), 1u); + // The second DbgVariableRecord should have been cloned; it should have the + // same values as DVR1. + EXPECT_EQ( + cast<DbgVariableRecord>(RetInst->DebugMarker->StoredDbgRecords.begin()) + ->getRawLocation(), + DVR1->getRawLocation()); + // We should be able to drop individual DbgRecords. + RetInst->DebugMarker->dropOneDbgRecord( + &*RetInst->DebugMarker->StoredDbgRecords.begin()); + + // "Aborb" a DbgMarker: this means pretend that the instruction it's attached // to is disappearing so it needs to be transferred into "this" marker. - RetInst->DbgMarker->absorbDebugValues(*FirstInst->DbgMarker, true); - EXPECT_EQ(RetInst->DbgMarker->StoredDPValues.size(), 2u); - // Should be the DPV1 and DPV2 objects. + RetInst->DebugMarker->absorbDebugValues(*FirstInst->DebugMarker, true); + EXPECT_EQ(RetInst->DebugMarker->StoredDbgRecords.size(), 2u); + // Should be the DVR1 and DVR2 objects. ItCount = 0; - for (DbgRecord &Item : RetInst->DbgMarker->getDbgRecordRange()) { - EXPECT_TRUE((&Item == DPV2 && ItCount == 0) || - (&Item == DPV1 && ItCount == 1)); - EXPECT_EQ(Item.getMarker(), RetInst->DbgMarker); + for (DbgRecord &Item : RetInst->DebugMarker->getDbgRecordRange()) { + EXPECT_TRUE((&Item == DVR2 && ItCount == 0) || + (&Item == DVR1 && ItCount == 1)); + EXPECT_EQ(Item.getMarker(), RetInst->DebugMarker); ++ItCount; } - // Finally -- there are two DPValues left over. If we remove evrything in the - // basic block, then they should sink down into the "TrailingDPValues" - // container for dangling debug-info. Future facilities will restore them - // back when a terminator is inserted. - FirstInst->DbgMarker->removeMarker(); + // Finally -- there are two DbgVariableRecords left over. If we remove + // evrything in the basic block, then they should sink down into the + // "TrailingDbgRecords" container for dangling debug-info. Future facilities + // will restore them back when a terminator is inserted. + FirstInst->DebugMarker->removeMarker(); FirstInst->eraseFromParent(); - RetInst->DbgMarker->removeMarker(); + RetInst->DebugMarker->removeMarker(); RetInst->eraseFromParent(); - DPMarker *EndMarker = ExitBlock->getTrailingDbgRecords(); + DbgMarker *EndMarker = ExitBlock->getTrailingDbgRecords(); ASSERT_NE(EndMarker, nullptr); - EXPECT_EQ(EndMarker->StoredDPValues.size(), 2u); - // Test again that it's those two DPValues, DPV1 and DPV2. + EXPECT_EQ(EndMarker->StoredDbgRecords.size(), 2u); + // Test again that it's those two DbgVariableRecords, DVR1 and DVR2. ItCount = 0; for (DbgRecord &Item : EndMarker->getDbgRecordRange()) { - EXPECT_TRUE((&Item == DPV2 && ItCount == 0) || - (&Item == DPV1 && ItCount == 1)); + EXPECT_TRUE((&Item == DVR2 && ItCount == 0) || + (&Item == DVR1 && ItCount == 1)); EXPECT_EQ(Item.getMarker(), EndMarker); ++ItCount; } - // Cleanup the trailing DPValue records and marker. + // Cleanup the trailing DbgVariableRecord records and marker. EndMarker->eraseFromParent(); - // The record of those trailing DPValues would dangle and cause an assertion - // failure if it lived until the end of the LLVMContext. + // The record of those trailing DbgVariableRecords would dangle and cause an + // assertion failure if it lived until the end of the LLVMContext. ExitBlock->deleteTrailingDbgRecords(); } -TEST(MetadataTest, DPValueConversionRoutines) { +TEST(MetadataTest, DbgVariableRecordConversionRoutines) { LLVMContext C; // For the purpose of this test, set and un-set the command line option @@ -1074,14 +1078,14 @@ TEST(MetadataTest, DPValueConversionRoutines) { )"); // Check that the conversion routines and utilities between dbg.value - // debug-info format and DPValues works. + // debug-info format and DbgVariableRecords works. Function *F = M->getFunction("f"); BasicBlock *BB1 = &F->getEntryBlock(); // First instruction should be a dbg.value. EXPECT_TRUE(isa<DbgValueInst>(BB1->front())); EXPECT_FALSE(BB1->IsNewDbgInfoFormat); - // Validating the block for DPValues / DPMarkers shouldn't fail -- there's - // no data stored right now. + // Validating the block for DbgVariableRecords / DbgMarkers shouldn't fail -- + // there's no data stored right now. bool BrokenDebugInfo = false; bool Error = verifyModule(*M, &errs(), &BrokenDebugInfo); EXPECT_FALSE(Error); @@ -1104,38 +1108,39 @@ TEST(MetadataTest, DPValueConversionRoutines) { for (auto &I : BB) EXPECT_FALSE(isa<DbgValueInst>(I)); - // There should be a DPMarker on each of the two instructions in the entry - // block, each containing one DPValue. + // There should be a DbgMarker on each of the two instructions in the entry + // block, each containing one DbgVariableRecord. EXPECT_EQ(BB1->size(), 2u); Instruction *FirstInst = &BB1->front(); Instruction *SecondInst = FirstInst->getNextNode(); - ASSERT_TRUE(FirstInst->DbgMarker); - ASSERT_TRUE(SecondInst->DbgMarker); - EXPECT_NE(FirstInst->DbgMarker, SecondInst->DbgMarker); - EXPECT_EQ(FirstInst, FirstInst->DbgMarker->MarkedInstr); - EXPECT_EQ(SecondInst, SecondInst->DbgMarker->MarkedInstr); - - EXPECT_EQ(FirstInst->DbgMarker->StoredDPValues.size(), 1u); - DPValue *DPV1 = - cast<DPValue>(&*FirstInst->DbgMarker->getDbgRecordRange().begin()); - EXPECT_EQ(DPV1->getMarker(), FirstInst->DbgMarker); + ASSERT_TRUE(FirstInst->DebugMarker); + ASSERT_TRUE(SecondInst->DebugMarker); + EXPECT_NE(FirstInst->DebugMarker, SecondInst->DebugMarker); + EXPECT_EQ(FirstInst, FirstInst->DebugMarker->MarkedInstr); + EXPECT_EQ(SecondInst, SecondInst->DebugMarker->MarkedInstr); + + EXPECT_EQ(FirstInst->DebugMarker->StoredDbgRecords.size(), 1u); + DbgVariableRecord *DVR1 = cast<DbgVariableRecord>( + &*FirstInst->DebugMarker->getDbgRecordRange().begin()); + EXPECT_EQ(DVR1->getMarker(), FirstInst->DebugMarker); // Should point at %a, an argument. - EXPECT_TRUE(isa<Argument>(DPV1->getVariableLocationOp(0))); + EXPECT_TRUE(isa<Argument>(DVR1->getVariableLocationOp(0))); - EXPECT_EQ(SecondInst->DbgMarker->StoredDPValues.size(), 1u); - DPValue *DPV2 = - cast<DPValue>(&*SecondInst->DbgMarker->getDbgRecordRange().begin()); - EXPECT_EQ(DPV2->getMarker(), SecondInst->DbgMarker); + EXPECT_EQ(SecondInst->DebugMarker->StoredDbgRecords.size(), 1u); + DbgVariableRecord *DVR2 = cast<DbgVariableRecord>( + &*SecondInst->DebugMarker->getDbgRecordRange().begin()); + EXPECT_EQ(DVR2->getMarker(), SecondInst->DebugMarker); // Should point at FirstInst. - EXPECT_EQ(DPV2->getVariableLocationOp(0), FirstInst); + EXPECT_EQ(DVR2->getVariableLocationOp(0), FirstInst); - // There should be no DPValues / DPMarkers in the second block, but it should - // be marked as being in the new format. + // There should be no DbgVariableRecords / DbgMarkers in the second block, but + // it should be marked as being in the new format. BasicBlock *BB2 = BB1->getNextNode(); EXPECT_TRUE(BB2->IsNewDbgInfoFormat); for (auto &Inst : *BB2) // Either there should be no marker, or it should be empty. - EXPECT_TRUE(!Inst.DbgMarker || Inst.DbgMarker->StoredDPValues.empty()); + EXPECT_TRUE(!Inst.DebugMarker || + Inst.DebugMarker->StoredDbgRecords.empty()); // Validating the first block should continue to not be a problem, Error = verifyModule(*M, &errs(), &BrokenDebugInfo); @@ -1144,17 +1149,17 @@ TEST(MetadataTest, DPValueConversionRoutines) { // But if we were to break something, it should be able to fire. Don't attempt // to comprehensively test the validator, it's a smoke-test rather than a // "proper" verification pass. - DPV1->setMarker(nullptr); + DVR1->setMarker(nullptr); // A marker pointing the wrong way should be an error. Error = verifyModule(*M, &errs(), &BrokenDebugInfo); EXPECT_FALSE(Error); EXPECT_TRUE(BrokenDebugInfo); - DPV1->setMarker(FirstInst->DbgMarker); + DVR1->setMarker(FirstInst->DebugMarker); - DILocalVariable *DLV1 = DPV1->getVariable(); - DIExpression *Expr1 = DPV1->getExpression(); - DILocalVariable *DLV2 = DPV2->getVariable(); - DIExpression *Expr2 = DPV2->getExpression(); + DILocalVariable *DLV1 = DVR1->getVariable(); + DIExpression *Expr1 = DVR1->getExpression(); + DILocalVariable *DLV2 = DVR2->getVariable(); + DIExpression *Expr2 = DVR2->getExpression(); // Convert everything back to the "old" format and ensure it's right. M->convertFromNewDbgValues(); diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp index 139e8832c97b9177379353feb270f8f62b6019ea..2001df090aed53b4480f025ba1986c7bd6a63720 100644 --- a/llvm/unittests/IR/IRBuilderTest.cpp +++ b/llvm/unittests/IR/IRBuilderTest.cpp @@ -57,7 +57,7 @@ TEST_F(IRBuilderTest, Intrinsics) { IRBuilder<> Builder(BB); Value *V; Instruction *I; - CallInst *Call; + Value *Result; IntrinsicInst *II; V = Builder.CreateLoad(GV->getValueType(), GV); @@ -65,78 +65,80 @@ TEST_F(IRBuilderTest, Intrinsics) { I->setHasNoInfs(true); I->setHasNoNaNs(false); - Call = Builder.CreateMinNum(V, V); - II = cast<IntrinsicInst>(Call); + Result = Builder.CreateMinNum(V, V); + II = cast<IntrinsicInst>(Result); EXPECT_EQ(II->getIntrinsicID(), Intrinsic::minnum); - Call = Builder.CreateMaxNum(V, V); - II = cast<IntrinsicInst>(Call); + Result = Builder.CreateMaxNum(V, V); + II = cast<IntrinsicInst>(Result); EXPECT_EQ(II->getIntrinsicID(), Intrinsic::maxnum); - Call = Builder.CreateMinimum(V, V); - II = cast<IntrinsicInst>(Call); + Result = Builder.CreateMinimum(V, V); + II = cast<IntrinsicInst>(Result); EXPECT_EQ(II->getIntrinsicID(), Intrinsic::minimum); - Call = Builder.CreateMaximum(V, V); - II = cast<IntrinsicInst>(Call); + Result = Builder.CreateMaximum(V, V); + II = cast<IntrinsicInst>(Result); EXPECT_EQ(II->getIntrinsicID(), Intrinsic::maximum); - Call = Builder.CreateIntrinsic(Intrinsic::readcyclecounter, {}, {}); - II = cast<IntrinsicInst>(Call); + Result = Builder.CreateIntrinsic(Intrinsic::readcyclecounter, {}, {}); + II = cast<IntrinsicInst>(Result); EXPECT_EQ(II->getIntrinsicID(), Intrinsic::readcyclecounter); - Call = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, V); - II = cast<IntrinsicInst>(Call); + Result = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, V); + II = cast<IntrinsicInst>(Result); EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fabs); EXPECT_FALSE(II->hasNoInfs()); EXPECT_FALSE(II->hasNoNaNs()); - Call = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, V, I); - II = cast<IntrinsicInst>(Call); + Result = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, V, I); + II = cast<IntrinsicInst>(Result); EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fabs); EXPECT_TRUE(II->hasNoInfs()); EXPECT_FALSE(II->hasNoNaNs()); - Call = Builder.CreateBinaryIntrinsic(Intrinsic::pow, V, V); - II = cast<IntrinsicInst>(Call); + Result = Builder.CreateBinaryIntrinsic(Intrinsic::pow, V, V); + II = cast<IntrinsicInst>(Result); EXPECT_EQ(II->getIntrinsicID(), Intrinsic::pow); EXPECT_FALSE(II->hasNoInfs()); EXPECT_FALSE(II->hasNoNaNs()); - Call = Builder.CreateBinaryIntrinsic(Intrinsic::pow, V, V, I); - II = cast<IntrinsicInst>(Call); + Result = Builder.CreateBinaryIntrinsic(Intrinsic::pow, V, V, I); + II = cast<IntrinsicInst>(Result); EXPECT_EQ(II->getIntrinsicID(), Intrinsic::pow); EXPECT_TRUE(II->hasNoInfs()); EXPECT_FALSE(II->hasNoNaNs()); - Call = Builder.CreateIntrinsic(Intrinsic::fma, {V->getType()}, {V, V, V}); - II = cast<IntrinsicInst>(Call); + Result = Builder.CreateIntrinsic(Intrinsic::fma, {V->getType()}, {V, V, V}); + II = cast<IntrinsicInst>(Result); EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fma); EXPECT_FALSE(II->hasNoInfs()); EXPECT_FALSE(II->hasNoNaNs()); - Call = Builder.CreateIntrinsic(Intrinsic::fma, {V->getType()}, {V, V, V}, I); - II = cast<IntrinsicInst>(Call); + Result = + Builder.CreateIntrinsic(Intrinsic::fma, {V->getType()}, {V, V, V}, I); + II = cast<IntrinsicInst>(Result); EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fma); EXPECT_TRUE(II->hasNoInfs()); EXPECT_FALSE(II->hasNoNaNs()); - Call = Builder.CreateIntrinsic(Intrinsic::fma, {V->getType()}, {V, V, V}, I); - II = cast<IntrinsicInst>(Call); + Result = + Builder.CreateIntrinsic(Intrinsic::fma, {V->getType()}, {V, V, V}, I); + II = cast<IntrinsicInst>(Result); EXPECT_EQ(II->getIntrinsicID(), Intrinsic::fma); EXPECT_TRUE(II->hasNoInfs()); EXPECT_FALSE(II->hasNoNaNs()); - Call = Builder.CreateUnaryIntrinsic(Intrinsic::roundeven, V); - II = cast<IntrinsicInst>(Call); + Result = Builder.CreateUnaryIntrinsic(Intrinsic::roundeven, V); + II = cast<IntrinsicInst>(Result); EXPECT_EQ(II->getIntrinsicID(), Intrinsic::roundeven); EXPECT_FALSE(II->hasNoInfs()); EXPECT_FALSE(II->hasNoNaNs()); - Call = Builder.CreateIntrinsic( + Result = Builder.CreateIntrinsic( Intrinsic::set_rounding, {}, {Builder.getInt32(static_cast<uint32_t>(RoundingMode::TowardZero))}); - II = cast<IntrinsicInst>(Call); + II = cast<IntrinsicInst>(Result); EXPECT_EQ(II->getIntrinsicID(), Intrinsic::set_rounding); } @@ -920,7 +922,7 @@ TEST_F(IRBuilderTest, DIBuilder) { DILabel *Label = DIB.createLabel(BarScope, "badger", File, 1, /*AlwaysPreserve*/ false); - { /* dbg.label | DPLabel */ + { /* dbg.label | DbgLabelRecord */ // Insert before I and check order. ExpectOrder(DIB.insertLabel(Label, LabelLoc, I), I->getIterator()); @@ -929,7 +931,7 @@ TEST_F(IRBuilderTest, DIBuilder) { // inserted into the block untill another instruction is added. DbgInstPtr LabelRecord = DIB.insertLabel(Label, LabelLoc, BB); // Specifically do not insert a terminator, to check this works. `I` - // should have absorbed the DPLabel in the new debug info mode. + // should have absorbed the DbgLabelRecord in the new debug info mode. I = Builder.CreateAlloca(Builder.getInt32Ty()); ExpectOrder(LabelRecord, I->getIterator()); } @@ -942,7 +944,7 @@ TEST_F(IRBuilderTest, DIBuilder) { DIB.createAutoVariable(BarSP, "X", File, 2, IntType, true); DILocalVariable *VarY = DIB.createAutoVariable(BarSP, "Y", File, 2, IntType, true); - { /* dbg.value | DPValue::Value */ + { /* dbg.value | DbgVariableRecord::Value */ ExpectOrder(DIB.insertDbgValueIntrinsic(I, VarX, DIB.createExpression(), VarLoc, I), I->getIterator()); @@ -953,7 +955,7 @@ TEST_F(IRBuilderTest, DIBuilder) { ExpectOrder(VarXValue, I->getIterator()); EXPECT_EQ(BB->getTrailingDbgRecords(), nullptr); } - { /* dbg.declare | DPValue::Declare */ + { /* dbg.declare | DbgVariableRecord::Declare */ ExpectOrder(DIB.insertDeclare(I, VarY, DIB.createExpression(), VarLoc, I), I->getIterator()); // Check inserting at end of the block works as with labels. @@ -963,7 +965,7 @@ TEST_F(IRBuilderTest, DIBuilder) { ExpectOrder(VarYDeclare, I->getIterator()); EXPECT_EQ(BB->getTrailingDbgRecords(), nullptr); } - { /* dbg.assign | DPValue::Assign */ + { /* dbg.assign | DbgVariableRecord::Assign */ I = Builder.CreateAlloca(Builder.getInt32Ty()); I->setMetadata(LLVMContext::MD_DIAssignID, DIAssignID::getDistinct(Ctx)); // DbgAssign interface is slightly different - it always inserts after the diff --git a/llvm/unittests/IR/ManglerTest.cpp b/llvm/unittests/IR/ManglerTest.cpp index 8ad95a83b6928c09b7209e8feef2243c631ce173..f2b78a1f9876946630c0d2a01d971ecef6ed1224 100644 --- a/llvm/unittests/IR/ManglerTest.cpp +++ b/llvm/unittests/IR/ManglerTest.cpp @@ -171,7 +171,7 @@ TEST(ManglerTest, GOFF) { "foo"); EXPECT_EQ(mangleFunc("foo", llvm::GlobalValue::PrivateLinkage, llvm::CallingConv::C, Mod, Mang), - "@foo"); + "L#foo"); } } // end anonymous namespace diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp index 767dd1a59d2b9e9310abeead5c0d169d79467b72..4c2e5f77a540381ebcf2ea4a813e1e0183842422 100644 --- a/llvm/unittests/IR/MetadataTest.cpp +++ b/llvm/unittests/IR/MetadataTest.cpp @@ -106,7 +106,7 @@ protected: DIType *getDerivedType() { return DIDerivedType::getDistinct( Context, dwarf::DW_TAG_pointer_type, "", nullptr, 0, nullptr, - getBasicType("basictype"), 1, 2, 0, std::nullopt, DINode::FlagZero); + getBasicType("basictype"), 1, 2, 0, std::nullopt, {}, DINode::FlagZero); } Constant *getConstant() { return ConstantInt::get(Type::getInt32Ty(Context), Counter++); @@ -461,7 +461,7 @@ TEST_F(MDNodeTest, PrintTree) { auto *StructTy = cast<DICompositeType>(getCompositeType()); DIType *PointerTy = DIDerivedType::getDistinct( Context, dwarf::DW_TAG_pointer_type, "", nullptr, 0, nullptr, StructTy, - 1, 2, 0, std::nullopt, DINode::FlagZero); + 1, 2, 0, std::nullopt, {}, DINode::FlagZero); StructTy->replaceElements(MDTuple::get(Context, PointerTy)); auto *Var = DILocalVariable::get(Context, Scope, "foo", File, @@ -1864,13 +1864,17 @@ TEST_F(DIDerivedTypeTest, get) { DIType *BaseType = getBasicType("basic"); MDTuple *ExtraData = getTuple(); unsigned DWARFAddressSpace = 8; + DIDerivedType::PtrAuthData PtrAuthData(1, false, 1234, true, true); + DIDerivedType::PtrAuthData PtrAuthData2(1, false, 1234, true, false); DINode::DIFlags Flags5 = static_cast<DINode::DIFlags>(5); DINode::DIFlags Flags4 = static_cast<DINode::DIFlags>(4); - auto *N = - DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, - 1, Scope, BaseType, 2, 3, 4, DWARFAddressSpace, Flags5, - ExtraData); + auto *N = DIDerivedType::get( + Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, + BaseType, 2, 3, 4, DWARFAddressSpace, std::nullopt, Flags5, ExtraData); + auto *N1 = DIDerivedType::get(Context, dwarf::DW_TAG_LLVM_ptrauth_type, "", + File, 1, Scope, N, 2, 3, 4, DWARFAddressSpace, + PtrAuthData, Flags5, ExtraData); EXPECT_EQ(dwarf::DW_TAG_pointer_type, N->getTag()); EXPECT_EQ("something", N->getName()); EXPECT_EQ(File, N->getFile()); @@ -1881,53 +1885,73 @@ TEST_F(DIDerivedTypeTest, get) { EXPECT_EQ(3u, N->getAlignInBits()); EXPECT_EQ(4u, N->getOffsetInBits()); EXPECT_EQ(DWARFAddressSpace, *N->getDWARFAddressSpace()); + EXPECT_EQ(std::nullopt, N->getPtrAuthData()); + EXPECT_EQ(PtrAuthData, N1->getPtrAuthData()); + EXPECT_NE(PtrAuthData2, N1->getPtrAuthData()); EXPECT_EQ(5u, N->getFlags()); EXPECT_EQ(ExtraData, N->getExtraData()); EXPECT_EQ(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, BaseType, 2, 3, - 4, DWARFAddressSpace, Flags5, ExtraData)); + 4, DWARFAddressSpace, std::nullopt, Flags5, + ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_reference_type, "something", File, 1, Scope, BaseType, 2, 3, - 4, DWARFAddressSpace, Flags5, ExtraData)); + 4, DWARFAddressSpace, std::nullopt, Flags5, + ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "else", - File, 1, Scope, BaseType, 2, 3, - 4, DWARFAddressSpace, Flags5, ExtraData)); + File, 1, Scope, BaseType, 2, 3, 4, + DWARFAddressSpace, std::nullopt, Flags5, + ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", getFile(), 1, Scope, BaseType, 2, - 3, 4, DWARFAddressSpace, Flags5, ExtraData)); + 3, 4, DWARFAddressSpace, std::nullopt, Flags5, + ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 2, Scope, BaseType, 2, 3, - 4, DWARFAddressSpace, Flags5, ExtraData)); + 4, DWARFAddressSpace, std::nullopt, Flags5, + ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, getSubprogram(), - BaseType, 2, 3, 4, DWARFAddressSpace, Flags5, - ExtraData)); + BaseType, 2, 3, 4, DWARFAddressSpace, + std::nullopt, Flags5, ExtraData)); EXPECT_NE(N, DIDerivedType::get( Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, getBasicType("basic2"), 2, 3, 4, DWARFAddressSpace, - Flags5, ExtraData)); + std::nullopt, Flags5, ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, BaseType, 3, 3, - 4, DWARFAddressSpace, Flags5, ExtraData)); + 4, DWARFAddressSpace, std::nullopt, Flags5, + ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, BaseType, 2, 2, - 4, DWARFAddressSpace, Flags5, ExtraData)); + 4, DWARFAddressSpace, std::nullopt, Flags5, + ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, BaseType, 2, 3, - 5, DWARFAddressSpace, Flags5, ExtraData)); + 5, DWARFAddressSpace, std::nullopt, Flags5, + ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, BaseType, 2, 3, - 4, DWARFAddressSpace + 1, Flags5, ExtraData)); + 4, DWARFAddressSpace + 1, std::nullopt, + Flags5, ExtraData)); + EXPECT_NE(N1, + DIDerivedType::get(Context, dwarf::DW_TAG_LLVM_ptrauth_type, "", + File, 1, Scope, N, 2, 3, 4, DWARFAddressSpace, + std::nullopt, Flags5, ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, BaseType, 2, 3, - 4, DWARFAddressSpace, Flags4, ExtraData)); + 4, DWARFAddressSpace, std::nullopt, Flags4, + ExtraData)); EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, BaseType, 2, 3, - 4, DWARFAddressSpace, Flags5, getTuple())); + 4, DWARFAddressSpace, std::nullopt, Flags5, + getTuple())); TempDIDerivedType Temp = N->clone(); EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); + TempDIDerivedType Temp1 = N1->clone(); + EXPECT_EQ(N1, MDNode::replaceWithUniqued(std::move(Temp1))); } TEST_F(DIDerivedTypeTest, getWithLargeValues) { @@ -1937,14 +1961,23 @@ TEST_F(DIDerivedTypeTest, getWithLargeValues) { MDTuple *ExtraData = getTuple(); DINode::DIFlags Flags = static_cast<DINode::DIFlags>(5); - auto *N = DIDerivedType::get( - Context, dwarf::DW_TAG_pointer_type, "something", File, 1, Scope, - BaseType, UINT64_MAX, UINT32_MAX - 1, UINT64_MAX - 2, UINT32_MAX - 3, - Flags, ExtraData); + auto *N = DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", + File, 1, Scope, BaseType, UINT64_MAX, + UINT32_MAX - 1, UINT64_MAX - 2, UINT32_MAX - 3, + std::nullopt, Flags, ExtraData); EXPECT_EQ(UINT64_MAX, N->getSizeInBits()); EXPECT_EQ(UINT32_MAX - 1, N->getAlignInBits()); EXPECT_EQ(UINT64_MAX - 2, N->getOffsetInBits()); EXPECT_EQ(UINT32_MAX - 3, *N->getDWARFAddressSpace()); + + auto *N1 = DIDerivedType::get( + Context, dwarf::DW_TAG_LLVM_ptrauth_type, "", File, 1, Scope, N, + UINT64_MAX, UINT32_MAX - 1, UINT64_MAX - 2, UINT32_MAX - 3, + DIDerivedType::PtrAuthData(7, true, 0xffff, true, false), Flags, + ExtraData); + EXPECT_EQ(7U, N1->getPtrAuthData()->key()); + EXPECT_EQ(true, N1->getPtrAuthData()->isAddressDiscriminated()); + EXPECT_EQ(0xffffU, N1->getPtrAuthData()->extraDiscriminator()); } typedef MetadataTest DICompositeTypeTest; @@ -3560,6 +3593,27 @@ TEST_F(DIExpressionTest, foldConstant) { #undef EXPECT_FOLD_CONST } +TEST_F(DIExpressionTest, appendToStackAssert) { + DIExpression *Expr = DIExpression::get(Context, {}); + + // Verify that the DW_OP_LLVM_convert operands, which have the same values as + // DW_OP_stack_value and DW_OP_LLVM_fragment, do not get interpreted as such + // operations. This previously triggered an assert. + uint64_t FromSize = dwarf::DW_OP_stack_value; + uint64_t ToSize = dwarf::DW_OP_LLVM_fragment; + uint64_t Ops[] = { + dwarf::DW_OP_LLVM_convert, FromSize, dwarf::DW_ATE_signed, + dwarf::DW_OP_LLVM_convert, ToSize, dwarf::DW_ATE_signed, + }; + Expr = DIExpression::appendToStack(Expr, Ops); + + uint64_t Expected[] = { + dwarf::DW_OP_LLVM_convert, FromSize, dwarf::DW_ATE_signed, + dwarf::DW_OP_LLVM_convert, ToSize, dwarf::DW_ATE_signed, + dwarf::DW_OP_stack_value}; + EXPECT_EQ(Expr->getElements(), ArrayRef<uint64_t>(Expected)); +} + typedef MetadataTest DIObjCPropertyTest; TEST_F(DIObjCPropertyTest, get) { @@ -4268,7 +4322,7 @@ TEST_F(MDTupleAllocationTest, Tracking2) { #if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG) && !defined(GTEST_HAS_SEH) typedef MetadataTest MDTupleAllocationDeathTest; TEST_F(MDTupleAllocationDeathTest, ResizeRejected) { - MDTuple *A = MDTuple::get(Context, None); + MDTuple *A = MDTuple::get(Context, std::nullopt); auto *Value1 = getConstantAsMetadata(); EXPECT_DEATH(A->push_back(Value1), "Resizing is not supported for uniqued nodes"); diff --git a/llvm/unittests/IR/PatternMatch.cpp b/llvm/unittests/IR/PatternMatch.cpp index 533a30bfba45dd606b33cdb67159fce15bb528cf..4d0c2e4220fec74491dc5b0289624c45562bdc87 100644 --- a/llvm/unittests/IR/PatternMatch.cpp +++ b/llvm/unittests/IR/PatternMatch.cpp @@ -494,6 +494,45 @@ TEST_F(PatternMatchTest, Unless) { EXPECT_FALSE(m_Unless(m_c_Add(m_Zero(), m_One())).match(X)); } +TEST_F(PatternMatchTest, BitWise) { + Value *Or = IRB.CreateOr(IRB.getInt32(1), IRB.getInt32(0)); + Value *Xor = IRB.CreateXor(IRB.getInt32(1), IRB.getInt32(0)); + Value *And = IRB.CreateXor(IRB.getInt32(1), IRB.getInt32(0)); + Constant *T = IRB.getInt1(true); + Constant *F = IRB.getInt1(false); + Value *Alloca = IRB.CreateAlloca(IRB.getInt1Ty()); + Value *X = IRB.CreateLoad(IRB.getInt1Ty(), Alloca); + Value *Y = IRB.CreateLoad(IRB.getInt1Ty(), Alloca); + Value *LAnd = IRB.CreateSelect(X, Y, F); + Value *LOr = IRB.CreateSelect(X, T, Y); + Value *Add = IRB.CreateAdd(IRB.getInt32(1), IRB.getInt32(0)); + + EXPECT_TRUE(m_BitwiseLogic(m_One(), m_Zero()).match(Or)); + EXPECT_TRUE(m_BitwiseLogic(m_One(), m_Zero()).match(Xor)); + EXPECT_TRUE(m_BitwiseLogic(m_One(), m_Zero()).match(And)); + EXPECT_FALSE(m_BitwiseLogic(m_Value(), m_Value()).match(LAnd)); + EXPECT_FALSE(m_BitwiseLogic(m_Value(), m_Value()).match(LOr)); + EXPECT_FALSE(m_BitwiseLogic(m_Value(), m_Value()).match(Add)); + + EXPECT_FALSE(m_BitwiseLogic(m_Zero(), m_One()).match(Or)); + EXPECT_FALSE(m_BitwiseLogic(m_Zero(), m_One()).match(Xor)); + EXPECT_FALSE(m_BitwiseLogic(m_Zero(), m_One()).match(And)); + + EXPECT_TRUE(m_c_BitwiseLogic(m_One(), m_Zero()).match(Or)); + EXPECT_TRUE(m_c_BitwiseLogic(m_One(), m_Zero()).match(Xor)); + EXPECT_TRUE(m_c_BitwiseLogic(m_One(), m_Zero()).match(And)); + EXPECT_FALSE(m_c_BitwiseLogic(m_Value(), m_Value()).match(LAnd)); + EXPECT_FALSE(m_c_BitwiseLogic(m_Value(), m_Value()).match(LOr)); + EXPECT_FALSE(m_c_BitwiseLogic(m_Value(), m_Value()).match(Add)); + + EXPECT_TRUE(m_c_BitwiseLogic(m_Zero(), m_One()).match(Or)); + EXPECT_TRUE(m_c_BitwiseLogic(m_Zero(), m_One()).match(Xor)); + EXPECT_TRUE(m_c_BitwiseLogic(m_Zero(), m_One()).match(And)); + + EXPECT_FALSE(m_c_BitwiseLogic(m_One(), m_One()).match(Or)); + EXPECT_FALSE(m_c_BitwiseLogic(m_Zero(), m_Zero()).match(Xor)); +} + TEST_F(PatternMatchTest, ZExtSExtSelf) { LLVMContext &Ctx = IRB.getContext(); @@ -909,6 +948,16 @@ TEST_F(PatternMatchTest, OverflowingBinOps) { EXPECT_EQ(L, MatchL); EXPECT_EQ(R, MatchR); MatchL = MatchR = nullptr; + + EXPECT_TRUE( + m_c_NUWAdd(m_Specific(L), m_Specific(R)).match(IRB.CreateNUWAdd(L, R))); + EXPECT_TRUE( + m_c_NUWAdd(m_Specific(R), m_Specific(L)).match(IRB.CreateNUWAdd(L, R))); + EXPECT_FALSE( + m_c_NUWAdd(m_Specific(R), m_ZeroInt()).match(IRB.CreateNUWAdd(L, R))); + EXPECT_FALSE( + m_NUWAdd(m_Specific(R), m_Specific(L)).match(IRB.CreateNUWAdd(L, R))); + EXPECT_TRUE( m_NUWSub(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWSub(L, R))); EXPECT_EQ(L, MatchL); diff --git a/llvm/unittests/IR/ValueTest.cpp b/llvm/unittests/IR/ValueTest.cpp index 97c8fea3c6dbf48438766b617d25c3143cf586a0..246c2fc7fe4063dafbded88bf3c57164defafa00 100644 --- a/llvm/unittests/IR/ValueTest.cpp +++ b/llvm/unittests/IR/ValueTest.cpp @@ -317,9 +317,9 @@ TEST(ValueTest, replaceUsesOutsideBlock) { ASSERT_TRUE(Ret->getOperand(0) == cast<Value>(B)); } -TEST(ValueTest, replaceUsesOutsideBlockDPValue) { +TEST(ValueTest, replaceUsesOutsideBlockDbgVariableRecord) { // Check that Value::replaceUsesOutsideBlock(New, BB) replaces uses outside - // BB, including DPValues. + // BB, including DbgVariableRecords. const auto *IR = R"( define i32 @f() !dbg !6 { entry: @@ -379,14 +379,16 @@ TEST(ValueTest, replaceUsesOutsideBlockDPValue) { EXPECT_TRUE(Branch->hasDbgRecords()); EXPECT_TRUE(Ret->hasDbgRecords()); - DPValue *DPV1 = cast<DPValue>(&*Branch->getDbgRecordRange().begin()); - DPValue *DPV2 = cast<DPValue>(&*Ret->getDbgRecordRange().begin()); + DbgVariableRecord *DVR1 = + cast<DbgVariableRecord>(&*Branch->getDbgRecordRange().begin()); + DbgVariableRecord *DVR2 = + cast<DbgVariableRecord>(&*Ret->getDbgRecordRange().begin()); A->replaceUsesOutsideBlock(B, Entry); // These users are in Entry so shouldn't be changed. - EXPECT_TRUE(DPV1->getVariableLocationOp(0) == cast<Value>(A)); + EXPECT_TRUE(DVR1->getVariableLocationOp(0) == cast<Value>(A)); // These users are outside Entry so should be changed. - EXPECT_TRUE(DPV2->getVariableLocationOp(0) == cast<Value>(B)); + EXPECT_TRUE(DVR2->getVariableLocationOp(0) == cast<Value>(B)); UseNewDbgInfoFormat = OldDbgValueMode; } diff --git a/llvm/unittests/Linker/LinkModulesTest.cpp b/llvm/unittests/Linker/LinkModulesTest.cpp index 182ce73178c1d47b67360de55d411289854750f0..884e20e89c5c2f40e4ddfa0fac7aed6d7e7bd204 100644 --- a/llvm/unittests/Linker/LinkModulesTest.cpp +++ b/llvm/unittests/Linker/LinkModulesTest.cpp @@ -72,7 +72,7 @@ protected: BasicBlock *ExitBB; }; -static void expectNoDiags(const DiagnosticInfo &DI, void *C) { +static void expectNoDiags(const DiagnosticInfo *DI, void *C) { llvm_unreachable("expectNoDiags called!"); } diff --git a/llvm/unittests/ProfileData/InstrProfTest.cpp b/llvm/unittests/ProfileData/InstrProfTest.cpp index cd4552a039b36b034b185c5decae3c5adb5ffbfd..732f8fd792f8ded68cd437e96313655c1501b681 100644 --- a/llvm/unittests/ProfileData/InstrProfTest.cpp +++ b/llvm/unittests/ProfileData/InstrProfTest.cpp @@ -366,7 +366,8 @@ IndexedMemProfRecord makeRecord( const MemInfoBlock &Block = MemInfoBlock()) { llvm::memprof::IndexedMemProfRecord MR; for (const auto &Frames : AllocFrames) - MR.AllocSites.emplace_back(Frames, Block); + MR.AllocSites.emplace_back(Frames, llvm::memprof::hashCallStack(Frames), + Block); for (const auto &Frames : CallSiteFrames) MR.CallSites.push_back(Frames); return MR; @@ -637,32 +638,78 @@ TEST_F(InstrProfTest, test_irpgo_read_deprecated_names) { Succeeded()); } +// callee1 to callee6 are from vtable1 to vtable6 respectively. static const char callee1[] = "callee1"; static const char callee2[] = "callee2"; static const char callee3[] = "callee3"; static const char callee4[] = "callee4"; static const char callee5[] = "callee5"; static const char callee6[] = "callee6"; +// callee7 and callee8 are not from any vtables. +static const char callee7[] = "callee7"; +static const char callee8[] = "callee8"; +// 'callee' is primarily used to create multiple-element vtables. +static const char callee[] = "callee"; +static const uint64_t vtable1[] = {uint64_t(callee), uint64_t(callee1)}; +static const uint64_t vtable2[] = {uint64_t(callee2), uint64_t(callee)}; +static const uint64_t vtable3[] = { + uint64_t(callee), + uint64_t(callee3), +}; +static const uint64_t vtable4[] = {uint64_t(callee4), uint64_t(callee)}; +static const uint64_t vtable5[] = {uint64_t(callee5), uint64_t(callee)}; +static const uint64_t vtable6[] = {uint64_t(callee6), uint64_t(callee)}; + +// Returns the address of callee with a numbered suffix in vtable. +static uint64_t getCalleeAddress(const uint64_t *vtableAddr) { + uint64_t CalleeAddr; + // Callee with a numbered suffix is the 2nd element in vtable1 and vtable3, + // and the 1st element in the rest of vtables. + if (vtableAddr == vtable1 || vtableAddr == vtable3) + CalleeAddr = uint64_t(vtableAddr) + 8; + else + CalleeAddr = uint64_t(vtableAddr); + return CalleeAddr; +} -TEST_P(InstrProfReaderWriterTest, icall_data_read_write) { +TEST_P(InstrProfReaderWriterTest, icall_and_vtable_data_read_write) { NamedInstrProfRecord Record1("caller", 0x1234, {1, 2}); - // 4 value sites. - Record1.reserveSites(IPVK_IndirectCallTarget, 4); - InstrProfValueData VD0[] = { - {(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}, {(uint64_t)callee3, 3}}; - Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr); - // No value profile data at the second site. - Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); - InstrProfValueData VD2[] = {{(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}}; - Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr); - InstrProfValueData VD3[] = {{(uint64_t)callee1, 1}}; - Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); + // 4 indirect call value sites. + { + Record1.reserveSites(IPVK_IndirectCallTarget, 4); + InstrProfValueData VD0[] = { + {(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}, {(uint64_t)callee3, 3}}; + Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr); + // No value profile data at the second site. + Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); + InstrProfValueData VD2[] = {{(uint64_t)callee1, 1}, {(uint64_t)callee2, 2}}; + Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr); + InstrProfValueData VD3[] = {{(uint64_t)callee7, 1}, {(uint64_t)callee8, 2}}; + Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 2, nullptr); + } + + // 2 vtable value sites. + { + InstrProfValueData VD0[] = { + {getCalleeAddress(vtable1), 1}, + {getCalleeAddress(vtable2), 2}, + {getCalleeAddress(vtable3), 3}, + }; + InstrProfValueData VD2[] = { + {getCalleeAddress(vtable1), 1}, + {getCalleeAddress(vtable2), 2}, + }; + Record1.addValueData(IPVK_VTableTarget, 0, VD0, 3, nullptr); + Record1.addValueData(IPVK_VTableTarget, 2, VD2, 2, nullptr); + } Writer.addRecord(std::move(Record1), getProfWeight(), Err); Writer.addRecord({"callee1", 0x1235, {3, 4}}, Err); Writer.addRecord({"callee2", 0x1235, {3, 4}}, Err); Writer.addRecord({"callee3", 0x1235, {3, 4}}, Err); + Writer.addRecord({"callee7", 0x1235, {3, 4}}, Err); + Writer.addRecord({"callee8", 0x1235, {3, 4}}, Err); // Set writer value prof data endianness. Writer.setValueProfDataEndianness(getEndianness()); @@ -675,24 +722,63 @@ TEST_P(InstrProfReaderWriterTest, icall_data_read_write) { Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); ASSERT_THAT_ERROR(R.takeError(), Succeeded()); + + // Test the number of instrumented indirect call sites and the number of + // profiled values at each site. ASSERT_EQ(4U, R->getNumValueSites(IPVK_IndirectCallTarget)); EXPECT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); EXPECT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); EXPECT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); - EXPECT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); + EXPECT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); + + // Test the number of instrumented vtable sites and the number of profiled + // values at each site. + ASSERT_EQ(R->getNumValueSites(IPVK_VTableTarget), 2U); + EXPECT_EQ(R->getNumValueDataForSite(IPVK_VTableTarget, 0), 3U); + EXPECT_EQ(R->getNumValueDataForSite(IPVK_VTableTarget, 1), 2U); + + // First indirect site. + { + uint64_t TotalC; + auto VD = R->getValueForSite(IPVK_IndirectCallTarget, 0, &TotalC); + + EXPECT_EQ(VD[0].Count, 3U * getProfWeight()); + EXPECT_EQ(VD[1].Count, 2U * getProfWeight()); + EXPECT_EQ(VD[2].Count, 1U * getProfWeight()); + EXPECT_EQ(TotalC, 6U * getProfWeight()); + + EXPECT_STREQ((const char *)VD[0].Value, "callee3"); + EXPECT_STREQ((const char *)VD[1].Value, "callee2"); + EXPECT_STREQ((const char *)VD[2].Value, "callee1"); + } - uint64_t TotalC; - std::unique_ptr<InstrProfValueData[]> VD = - R->getValueForSite(IPVK_IndirectCallTarget, 0, &TotalC); + // First vtable site. + { + uint64_t TotalC; + auto VD = R->getValueForSite(IPVK_VTableTarget, 0, &TotalC); + + EXPECT_EQ(VD[0].Count, 3U * getProfWeight()); + EXPECT_EQ(VD[1].Count, 2U * getProfWeight()); + EXPECT_EQ(VD[2].Count, 1U * getProfWeight()); + EXPECT_EQ(TotalC, 6U * getProfWeight()); + + EXPECT_EQ(VD[0].Value, getCalleeAddress(vtable3)); + EXPECT_EQ(VD[1].Value, getCalleeAddress(vtable2)); + EXPECT_EQ(VD[2].Value, getCalleeAddress(vtable1)); + } + + // Second vtable site. + { + uint64_t TotalC; + auto VD = R->getValueForSite(IPVK_VTableTarget, 1, &TotalC); - EXPECT_EQ(3U * getProfWeight(), VD[0].Count); - EXPECT_EQ(2U * getProfWeight(), VD[1].Count); - EXPECT_EQ(1U * getProfWeight(), VD[2].Count); - EXPECT_EQ(6U * getProfWeight(), TotalC); + EXPECT_EQ(VD[0].Count, 2U * getProfWeight()); + EXPECT_EQ(VD[1].Count, 1U * getProfWeight()); + EXPECT_EQ(TotalC, 3U * getProfWeight()); - EXPECT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3")); - EXPECT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2")); - EXPECT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1")); + EXPECT_EQ(VD[0].Value, getCalleeAddress(vtable2)); + EXPECT_EQ(VD[1].Value, getCalleeAddress(vtable1)); + } } INSTANTIATE_TEST_SUITE_P( @@ -800,33 +886,53 @@ TEST_P(MaybeSparseInstrProfTest, annotate_vp_data) { ASSERT_EQ(1U, ValueData[3].Count); } -TEST_P(MaybeSparseInstrProfTest, icall_data_merge) { +TEST_P(MaybeSparseInstrProfTest, icall_and_vtable_data_merge) { static const char caller[] = "caller"; NamedInstrProfRecord Record11(caller, 0x1234, {1, 2}); NamedInstrProfRecord Record12(caller, 0x1234, {1, 2}); - // 5 value sites. - Record11.reserveSites(IPVK_IndirectCallTarget, 5); - InstrProfValueData VD0[] = {{uint64_t(callee1), 1}, - {uint64_t(callee2), 2}, - {uint64_t(callee3), 3}, - {uint64_t(callee4), 4}}; - Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 4, nullptr); + // 5 value sites for indirect calls. + { + Record11.reserveSites(IPVK_IndirectCallTarget, 5); + InstrProfValueData VD0[] = {{uint64_t(callee1), 1}, + {uint64_t(callee2), 2}, + {uint64_t(callee3), 3}, + {uint64_t(callee4), 4}}; + Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 4, nullptr); - // No value profile data at the second site. - Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); + // No value profile data at the second site. + Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr); - InstrProfValueData VD2[] = { - {uint64_t(callee1), 1}, {uint64_t(callee2), 2}, {uint64_t(callee3), 3}}; - Record11.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr); + InstrProfValueData VD2[] = { + {uint64_t(callee1), 1}, {uint64_t(callee2), 2}, {uint64_t(callee3), 3}}; + Record11.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr); - InstrProfValueData VD3[] = {{uint64_t(callee1), 1}}; - Record11.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr); + InstrProfValueData VD3[] = {{uint64_t(callee7), 1}, {uint64_t(callee8), 2}}; + Record11.addValueData(IPVK_IndirectCallTarget, 3, VD3, 2, nullptr); - InstrProfValueData VD4[] = {{uint64_t(callee1), 1}, - {uint64_t(callee2), 2}, - {uint64_t(callee3), 3}}; - Record11.addValueData(IPVK_IndirectCallTarget, 4, VD4, 3, nullptr); + InstrProfValueData VD4[] = { + {uint64_t(callee1), 1}, {uint64_t(callee2), 2}, {uint64_t(callee3), 3}}; + Record11.addValueData(IPVK_IndirectCallTarget, 4, VD4, 3, nullptr); + } + // 3 value sites for vtables. + { + Record11.reserveSites(IPVK_VTableTarget, 3); + InstrProfValueData VD0[] = {{getCalleeAddress(vtable1), 1}, + {getCalleeAddress(vtable2), 2}, + {getCalleeAddress(vtable3), 3}, + {getCalleeAddress(vtable4), 4}}; + Record11.addValueData(IPVK_VTableTarget, 0, VD0, 4, nullptr); + + InstrProfValueData VD2[] = {{getCalleeAddress(vtable1), 1}, + {getCalleeAddress(vtable2), 2}, + {getCalleeAddress(vtable3), 3}}; + Record11.addValueData(IPVK_VTableTarget, 1, VD2, 3, nullptr); + + InstrProfValueData VD4[] = {{getCalleeAddress(vtable1), 1}, + {getCalleeAddress(vtable2), 2}, + {getCalleeAddress(vtable3), 3}}; + Record11.addValueData(IPVK_VTableTarget, 3, VD4, 3, nullptr); + } // A different record for the same caller. Record12.reserveSites(IPVK_IndirectCallTarget, 5); @@ -842,11 +948,28 @@ TEST_P(MaybeSparseInstrProfTest, icall_data_merge) { Record12.addValueData(IPVK_IndirectCallTarget, 3, nullptr, 0, nullptr); - InstrProfValueData VD42[] = {{uint64_t(callee1), 1}, - {uint64_t(callee2), 2}, - {uint64_t(callee3), 3}}; + InstrProfValueData VD42[] = { + {uint64_t(callee1), 1}, {uint64_t(callee2), 2}, {uint64_t(callee3), 3}}; Record12.addValueData(IPVK_IndirectCallTarget, 4, VD42, 3, nullptr); + // 3 value sites for vtables. + { + Record12.reserveSites(IPVK_VTableTarget, 3); + InstrProfValueData VD0[] = {{getCalleeAddress(vtable2), 5}, + {getCalleeAddress(vtable3), 3}}; + Record12.addValueData(IPVK_VTableTarget, 0, VD0, 2, nullptr); + + InstrProfValueData VD2[] = {{getCalleeAddress(vtable2), 1}, + {getCalleeAddress(vtable3), 3}, + {getCalleeAddress(vtable4), 4}}; + Record12.addValueData(IPVK_VTableTarget, 1, VD2, 3, nullptr); + + InstrProfValueData VD4[] = {{getCalleeAddress(vtable1), 1}, + {getCalleeAddress(vtable2), 2}, + {getCalleeAddress(vtable3), 3}}; + Record12.addValueData(IPVK_VTableTarget, 3, VD4, 3, nullptr); + } + Writer.addRecord(std::move(Record11), Err); // Merge profile data. Writer.addRecord(std::move(Record12), Err); @@ -856,53 +979,95 @@ TEST_P(MaybeSparseInstrProfTest, icall_data_merge) { Writer.addRecord({callee3, 0x1235, {3, 4}}, Err); Writer.addRecord({callee3, 0x1235, {3, 4}}, Err); Writer.addRecord({callee4, 0x1235, {3, 5}}, Err); + Writer.addRecord({callee7, 0x1235, {3, 5}}, Err); + Writer.addRecord({callee8, 0x1235, {3, 5}}, Err); auto Profile = Writer.writeBuffer(); readProfile(std::move(Profile)); + // Test the number of instrumented value sites and the number of profiled + // values for each site. Expected<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234); EXPECT_THAT_ERROR(R.takeError(), Succeeded()); + // For indirect calls. ASSERT_EQ(5U, R->getNumValueSites(IPVK_IndirectCallTarget)); ASSERT_EQ(4U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); ASSERT_EQ(0U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); ASSERT_EQ(4U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); - ASSERT_EQ(1U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); + ASSERT_EQ(2U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); ASSERT_EQ(3U, R->getNumValueDataForSite(IPVK_IndirectCallTarget, 4)); + // For vtables. + ASSERT_EQ(R->getNumValueSites(IPVK_VTableTarget), 3U); + ASSERT_EQ(R->getNumValueDataForSite(IPVK_VTableTarget, 0), 4U); + ASSERT_EQ(R->getNumValueDataForSite(IPVK_VTableTarget, 1), 4U); + ASSERT_EQ(R->getNumValueDataForSite(IPVK_VTableTarget, 2), 3U); + + // Test the merged values for indirect calls. + { + auto VD = R->getValueForSite(IPVK_IndirectCallTarget, 0); + EXPECT_STREQ((const char *)VD[0].Value, "callee2"); + EXPECT_EQ(VD[0].Count, 7U); + EXPECT_STREQ((const char *)VD[1].Value, "callee3"); + EXPECT_EQ(VD[1].Count, 6U); + EXPECT_STREQ((const char *)VD[2].Value, "callee4"); + EXPECT_EQ(VD[2].Count, 4U); + EXPECT_STREQ((const char *)VD[3].Value, "callee1"); + EXPECT_EQ(VD[3].Count, 1U); + + auto VD_2(R->getValueForSite(IPVK_IndirectCallTarget, 2)); + EXPECT_STREQ((const char *)VD_2[0].Value, "callee3"); + EXPECT_EQ(VD_2[0].Count, 6U); + EXPECT_STREQ((const char *)VD_2[1].Value, "callee4"); + EXPECT_EQ(VD_2[1].Count, 4U); + EXPECT_STREQ((const char *)VD_2[2].Value, "callee2"); + EXPECT_EQ(VD_2[2].Count, 3U); + EXPECT_STREQ((const char *)VD_2[3].Value, "callee1"); + EXPECT_EQ(VD_2[3].Count, 1U); + + auto VD_3(R->getValueForSite(IPVK_IndirectCallTarget, 3)); + EXPECT_STREQ((const char *)VD_3[0].Value, "callee8"); + EXPECT_EQ(VD_3[0].Count, 2U); + EXPECT_STREQ((const char *)VD_3[1].Value, "callee7"); + EXPECT_EQ(VD_3[1].Count, 1U); + + auto VD_4(R->getValueForSite(IPVK_IndirectCallTarget, 4)); + EXPECT_STREQ((const char *)VD_4[0].Value, "callee3"); + EXPECT_EQ(VD_4[0].Count, 6U); + EXPECT_STREQ((const char *)VD_4[1].Value, "callee2"); + EXPECT_EQ(VD_4[1].Count, 4U); + EXPECT_STREQ((const char *)VD_4[2].Value, "callee1"); + EXPECT_EQ(VD_4[2].Count, 2U); + } - std::unique_ptr<InstrProfValueData[]> VD = - R->getValueForSite(IPVK_IndirectCallTarget, 0); - ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee2")); - ASSERT_EQ(7U, VD[0].Count); - ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee3")); - ASSERT_EQ(6U, VD[1].Count); - ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee4")); - ASSERT_EQ(4U, VD[2].Count); - ASSERT_EQ(StringRef((const char *)VD[3].Value, 7), StringRef("callee1")); - ASSERT_EQ(1U, VD[3].Count); - - std::unique_ptr<InstrProfValueData[]> VD_2( - R->getValueForSite(IPVK_IndirectCallTarget, 2)); - ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee3")); - ASSERT_EQ(6U, VD_2[0].Count); - ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee4")); - ASSERT_EQ(4U, VD_2[1].Count); - ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee2")); - ASSERT_EQ(3U, VD_2[2].Count); - ASSERT_EQ(StringRef((const char *)VD_2[3].Value, 7), StringRef("callee1")); - ASSERT_EQ(1U, VD_2[3].Count); - - std::unique_ptr<InstrProfValueData[]> VD_3( - R->getValueForSite(IPVK_IndirectCallTarget, 3)); - ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee1")); - ASSERT_EQ(1U, VD_3[0].Count); - - std::unique_ptr<InstrProfValueData[]> VD_4( - R->getValueForSite(IPVK_IndirectCallTarget, 4)); - ASSERT_EQ(StringRef((const char *)VD_4[0].Value, 7), StringRef("callee3")); - ASSERT_EQ(6U, VD_4[0].Count); - ASSERT_EQ(StringRef((const char *)VD_4[1].Value, 7), StringRef("callee2")); - ASSERT_EQ(4U, VD_4[1].Count); - ASSERT_EQ(StringRef((const char *)VD_4[2].Value, 7), StringRef("callee1")); - ASSERT_EQ(2U, VD_4[2].Count); + // Test the merged values for vtables + { + auto VD0 = R->getValueForSite(IPVK_VTableTarget, 0); + EXPECT_EQ(VD0[0].Value, getCalleeAddress(vtable2)); + EXPECT_EQ(VD0[0].Count, 7U); + EXPECT_EQ(VD0[1].Value, getCalleeAddress(vtable3)); + EXPECT_EQ(VD0[1].Count, 6U); + EXPECT_EQ(VD0[2].Value, getCalleeAddress(vtable4)); + EXPECT_EQ(VD0[2].Count, 4U); + EXPECT_EQ(VD0[3].Value, getCalleeAddress(vtable1)); + EXPECT_EQ(VD0[3].Count, 1U); + + auto VD1 = R->getValueForSite(IPVK_VTableTarget, 1); + EXPECT_EQ(VD1[0].Value, getCalleeAddress(vtable3)); + EXPECT_EQ(VD1[0].Count, 6U); + EXPECT_EQ(VD1[1].Value, getCalleeAddress(vtable4)); + EXPECT_EQ(VD1[1].Count, 4U); + EXPECT_EQ(VD1[2].Value, getCalleeAddress(vtable2)); + EXPECT_EQ(VD1[2].Count, 3U); + EXPECT_EQ(VD1[3].Value, getCalleeAddress(vtable1)); + EXPECT_EQ(VD1[3].Count, 1U); + + auto VD2 = R->getValueForSite(IPVK_VTableTarget, 2); + EXPECT_EQ(VD2[0].Value, getCalleeAddress(vtable3)); + EXPECT_EQ(VD2[0].Count, 6U); + EXPECT_EQ(VD2[1].Value, getCalleeAddress(vtable2)); + EXPECT_EQ(VD2[1].Count, 4U); + EXPECT_EQ(VD2[2].Value, getCalleeAddress(vtable1)); + EXPECT_EQ(VD2[2].Count, 2U); + } } struct ValueProfileMergeEdgeCaseTest @@ -1026,30 +1191,62 @@ INSTANTIATE_TEST_SUITE_P( EdgeCaseTest, ValueProfileMergeEdgeCaseTest, ::testing::Combine(::testing::Bool(), /* Sparse */ ::testing::Values(IPVK_IndirectCallTarget, - IPVK_MemOPSize) /* ValueKind */ + IPVK_MemOPSize, + IPVK_VTableTarget) /* ValueKind */ )); static void addValueProfData(InstrProfRecord &Record) { - Record.reserveSites(IPVK_IndirectCallTarget, 5); - InstrProfValueData VD0[] = {{uint64_t(callee1), 400}, - {uint64_t(callee2), 1000}, - {uint64_t(callee3), 500}, - {uint64_t(callee4), 300}, - {uint64_t(callee5), 100}}; - Record.addValueData(IPVK_IndirectCallTarget, 0, VD0, 5, nullptr); - InstrProfValueData VD1[] = {{uint64_t(callee5), 800}, - {uint64_t(callee3), 1000}, - {uint64_t(callee2), 2500}, - {uint64_t(callee1), 1300}}; - Record.addValueData(IPVK_IndirectCallTarget, 1, VD1, 4, nullptr); - InstrProfValueData VD2[] = {{uint64_t(callee6), 800}, - {uint64_t(callee3), 1000}, - {uint64_t(callee4), 5500}}; - Record.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr); - InstrProfValueData VD3[] = {{uint64_t(callee2), 1800}, - {uint64_t(callee3), 2000}}; - Record.addValueData(IPVK_IndirectCallTarget, 3, VD3, 2, nullptr); - Record.addValueData(IPVK_IndirectCallTarget, 4, nullptr, 0, nullptr); + // Add test data for indirect calls. + { + Record.reserveSites(IPVK_IndirectCallTarget, 6); + InstrProfValueData VD0[] = {{uint64_t(callee1), 400}, + {uint64_t(callee2), 1000}, + {uint64_t(callee3), 500}, + {uint64_t(callee4), 300}, + {uint64_t(callee5), 100}}; + Record.addValueData(IPVK_IndirectCallTarget, 0, VD0, 5, nullptr); + InstrProfValueData VD1[] = {{uint64_t(callee5), 800}, + {uint64_t(callee3), 1000}, + {uint64_t(callee2), 2500}, + {uint64_t(callee1), 1300}}; + Record.addValueData(IPVK_IndirectCallTarget, 1, VD1, 4, nullptr); + InstrProfValueData VD2[] = {{uint64_t(callee6), 800}, + {uint64_t(callee3), 1000}, + {uint64_t(callee4), 5500}}; + Record.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr); + InstrProfValueData VD3[] = {{uint64_t(callee2), 1800}, + {uint64_t(callee3), 2000}}; + Record.addValueData(IPVK_IndirectCallTarget, 3, VD3, 2, nullptr); + Record.addValueData(IPVK_IndirectCallTarget, 4, nullptr, 0, nullptr); + InstrProfValueData VD5[] = {{uint64_t(callee7), 1234}, + {uint64_t(callee8), 5678}}; + Record.addValueData(IPVK_IndirectCallTarget, 5, VD5, 2, nullptr); + } + + // Add test data for vtables + { + Record.reserveSites(IPVK_VTableTarget, 4); + InstrProfValueData VD0[] = { + {getCalleeAddress(vtable1), 400}, {getCalleeAddress(vtable2), 1000}, + {getCalleeAddress(vtable3), 500}, {getCalleeAddress(vtable4), 300}, + {getCalleeAddress(vtable5), 100}, + }; + InstrProfValueData VD1[] = {{getCalleeAddress(vtable5), 800}, + {getCalleeAddress(vtable3), 1000}, + {getCalleeAddress(vtable2), 2500}, + {getCalleeAddress(vtable1), 1300}}; + InstrProfValueData VD2[] = { + {getCalleeAddress(vtable6), 800}, + {getCalleeAddress(vtable3), 1000}, + {getCalleeAddress(vtable4), 5500}, + }; + InstrProfValueData VD3[] = {{getCalleeAddress(vtable2), 1800}, + {getCalleeAddress(vtable3), 2000}}; + Record.addValueData(IPVK_VTableTarget, 0, VD0, 5, nullptr); + Record.addValueData(IPVK_VTableTarget, 1, VD1, 4, nullptr); + Record.addValueData(IPVK_VTableTarget, 2, VD2, 3, nullptr); + Record.addValueData(IPVK_VTableTarget, 3, VD3, 2, nullptr); + } } TEST(ValueProfileReadWriteTest, value_prof_data_read_write) { @@ -1062,59 +1259,107 @@ TEST(ValueProfileReadWriteTest, value_prof_data_read_write) { VPData->deserializeTo(Record, nullptr); // Now read data from Record and sanity check the data - ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget)); + ASSERT_EQ(6U, Record.getNumValueSites(IPVK_IndirectCallTarget)); ASSERT_EQ(5U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); ASSERT_EQ(4U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 1)); ASSERT_EQ(3U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 2)); ASSERT_EQ(2U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 3)); ASSERT_EQ(0U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 4)); + ASSERT_EQ(2U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 5)); auto Cmp = [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) { return VD1.Count > VD2.Count; }; + std::unique_ptr<InstrProfValueData[]> VD_0( Record.getValueForSite(IPVK_IndirectCallTarget, 0)); llvm::sort(&VD_0[0], &VD_0[5], Cmp); - ASSERT_EQ(StringRef((const char *)VD_0[0].Value, 7), StringRef("callee2")); - ASSERT_EQ(1000U, VD_0[0].Count); - ASSERT_EQ(StringRef((const char *)VD_0[1].Value, 7), StringRef("callee3")); - ASSERT_EQ(500U, VD_0[1].Count); - ASSERT_EQ(StringRef((const char *)VD_0[2].Value, 7), StringRef("callee1")); - ASSERT_EQ(400U, VD_0[2].Count); - ASSERT_EQ(StringRef((const char *)VD_0[3].Value, 7), StringRef("callee4")); - ASSERT_EQ(300U, VD_0[3].Count); - ASSERT_EQ(StringRef((const char *)VD_0[4].Value, 7), StringRef("callee5")); - ASSERT_EQ(100U, VD_0[4].Count); + EXPECT_STREQ((const char *)VD_0[0].Value, "callee2"); + EXPECT_EQ(1000U, VD_0[0].Count); + EXPECT_STREQ((const char *)VD_0[1].Value, "callee3"); + EXPECT_EQ(500U, VD_0[1].Count); + EXPECT_STREQ((const char *)VD_0[2].Value, "callee1"); + EXPECT_EQ(400U, VD_0[2].Count); + EXPECT_STREQ((const char *)VD_0[3].Value, "callee4"); + EXPECT_EQ(300U, VD_0[3].Count); + EXPECT_STREQ((const char *)VD_0[4].Value, "callee5"); + EXPECT_EQ(100U, VD_0[4].Count); std::unique_ptr<InstrProfValueData[]> VD_1( Record.getValueForSite(IPVK_IndirectCallTarget, 1)); llvm::sort(&VD_1[0], &VD_1[4], Cmp); - ASSERT_EQ(StringRef((const char *)VD_1[0].Value, 7), StringRef("callee2")); - ASSERT_EQ(2500U, VD_1[0].Count); - ASSERT_EQ(StringRef((const char *)VD_1[1].Value, 7), StringRef("callee1")); - ASSERT_EQ(1300U, VD_1[1].Count); - ASSERT_EQ(StringRef((const char *)VD_1[2].Value, 7), StringRef("callee3")); - ASSERT_EQ(1000U, VD_1[2].Count); - ASSERT_EQ(StringRef((const char *)VD_1[3].Value, 7), StringRef("callee5")); - ASSERT_EQ(800U, VD_1[3].Count); + EXPECT_STREQ((const char *)VD_1[0].Value, "callee2"); + EXPECT_EQ(VD_1[0].Count, 2500U); + EXPECT_STREQ((const char *)VD_1[1].Value, "callee1"); + EXPECT_EQ(VD_1[1].Count, 1300U); + EXPECT_STREQ((const char *)VD_1[2].Value, "callee3"); + EXPECT_EQ(VD_1[2].Count, 1000U); + EXPECT_STREQ((const char *)VD_1[3].Value, "callee5"); + EXPECT_EQ(VD_1[3].Count, 800U); std::unique_ptr<InstrProfValueData[]> VD_2( Record.getValueForSite(IPVK_IndirectCallTarget, 2)); llvm::sort(&VD_2[0], &VD_2[3], Cmp); - ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee4")); - ASSERT_EQ(5500U, VD_2[0].Count); - ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee3")); - ASSERT_EQ(1000U, VD_2[1].Count); - ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee6")); - ASSERT_EQ(800U, VD_2[2].Count); + EXPECT_STREQ((const char *)VD_2[0].Value, "callee4"); + EXPECT_EQ(VD_2[0].Count, 5500U); + EXPECT_STREQ((const char *)VD_2[1].Value, "callee3"); + EXPECT_EQ(VD_2[1].Count, 1000U); + EXPECT_STREQ((const char *)VD_2[2].Value, "callee6"); + EXPECT_EQ(VD_2[2].Count, 800U); std::unique_ptr<InstrProfValueData[]> VD_3( Record.getValueForSite(IPVK_IndirectCallTarget, 3)); llvm::sort(&VD_3[0], &VD_3[2], Cmp); - ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee3")); - ASSERT_EQ(2000U, VD_3[0].Count); - ASSERT_EQ(StringRef((const char *)VD_3[1].Value, 7), StringRef("callee2")); - ASSERT_EQ(1800U, VD_3[1].Count); + EXPECT_STREQ((const char *)VD_3[0].Value, "callee3"); + EXPECT_EQ(VD_3[0].Count, 2000U); + EXPECT_STREQ((const char *)VD_3[1].Value, "callee2"); + EXPECT_EQ(VD_3[1].Count, 1800U); + + ASSERT_EQ(Record.getNumValueSites(IPVK_VTableTarget), 4U); + ASSERT_EQ(Record.getNumValueDataForSite(IPVK_VTableTarget, 0), 5U); + ASSERT_EQ(Record.getNumValueDataForSite(IPVK_VTableTarget, 1), 4U); + ASSERT_EQ(Record.getNumValueDataForSite(IPVK_VTableTarget, 2), 3U); + ASSERT_EQ(Record.getNumValueDataForSite(IPVK_VTableTarget, 3), 2U); + + auto VD0(Record.getValueForSite(IPVK_VTableTarget, 0)); + llvm::sort(&VD0[0], &VD0[5], Cmp); + EXPECT_EQ(VD0[0].Value, getCalleeAddress(vtable2)); + EXPECT_EQ(VD0[0].Count, 1000U); + EXPECT_EQ(VD0[1].Value, getCalleeAddress(vtable3)); + EXPECT_EQ(VD0[1].Count, 500U); + EXPECT_EQ(VD0[2].Value, getCalleeAddress(vtable1)); + EXPECT_EQ(VD0[2].Count, 400U); + EXPECT_EQ(VD0[3].Value, getCalleeAddress(vtable4)); + EXPECT_EQ(VD0[3].Count, 300U); + EXPECT_EQ(VD0[4].Value, getCalleeAddress(vtable5)); + EXPECT_EQ(VD0[4].Count, 100U); + + auto VD1(Record.getValueForSite(IPVK_VTableTarget, 1)); + llvm::sort(&VD1[0], &VD1[4], Cmp); + EXPECT_EQ(VD1[0].Value, getCalleeAddress(vtable2)); + EXPECT_EQ(VD1[0].Count, 2500U); + EXPECT_EQ(VD1[1].Value, getCalleeAddress(vtable1)); + EXPECT_EQ(VD1[1].Count, 1300U); + EXPECT_EQ(VD1[2].Value, getCalleeAddress(vtable3)); + EXPECT_EQ(VD1[2].Count, 1000U); + EXPECT_EQ(VD1[3].Value, getCalleeAddress(vtable5)); + EXPECT_EQ(VD1[3].Count, 800U); + + auto VD2(Record.getValueForSite(IPVK_VTableTarget, 2)); + llvm::sort(&VD2[0], &VD2[3], Cmp); + EXPECT_EQ(VD2[0].Value, getCalleeAddress(vtable4)); + EXPECT_EQ(VD2[0].Count, 5500U); + EXPECT_EQ(VD2[1].Value, getCalleeAddress(vtable3)); + EXPECT_EQ(VD2[1].Count, 1000U); + EXPECT_EQ(VD2[2].Value, getCalleeAddress(vtable6)); + EXPECT_EQ(VD2[2].Count, 800U); + + auto VD3(Record.getValueForSite(IPVK_VTableTarget, 3)); + llvm::sort(&VD3[0], &VD3[2], Cmp); + EXPECT_EQ(VD3[0].Value, getCalleeAddress(vtable3)); + EXPECT_EQ(VD3[0].Count, 2000U); + EXPECT_EQ(VD3[1].Value, getCalleeAddress(vtable2)); + EXPECT_EQ(VD3[1].Count, 1800U); } TEST(ValueProfileReadWriteTest, symtab_mapping) { @@ -1131,27 +1376,121 @@ TEST(ValueProfileReadWriteTest, symtab_mapping) { Symtab.mapAddress(uint64_t(callee4), 0x4000ULL); // Missing mapping for callee5 + auto getVTableStartAddr = [](const uint64_t *vtable) -> uint64_t { + return uint64_t(vtable); + }; + auto getVTableEndAddr = [](const uint64_t *vtable) -> uint64_t { + return uint64_t(vtable) + 16; + }; + auto getVTableMidAddr = [](const uint64_t *vtable) -> uint64_t { + return uint64_t(vtable) + 8; + }; + // vtable1, vtable2, vtable3, vtable4 get mapped; vtable5, vtable6 are not + // mapped. + Symtab.mapVTableAddress(getVTableStartAddr(vtable1), + getVTableEndAddr(vtable1), MD5Hash("vtable1")); + Symtab.mapVTableAddress(getVTableStartAddr(vtable2), + getVTableEndAddr(vtable2), MD5Hash("vtable2")); + Symtab.mapVTableAddress(getVTableStartAddr(vtable3), + getVTableEndAddr(vtable3), MD5Hash("vtable3")); + Symtab.mapVTableAddress(getVTableStartAddr(vtable4), + getVTableEndAddr(vtable4), MD5Hash("vtable4")); + VPData->deserializeTo(Record, &Symtab); // Now read data from Record and sanity check the data - ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget)); - ASSERT_EQ(5U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0)); + ASSERT_EQ(Record.getNumValueSites(IPVK_IndirectCallTarget), 6U); + ASSERT_EQ(Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0), 5U); + + // Look up the value correpsonding to the middle of a vtable in symtab and + // test that it's the hash of the name. + EXPECT_EQ(Symtab.getVTableHashFromAddress(getVTableMidAddr(vtable1)), + MD5Hash("vtable1")); + EXPECT_EQ(Symtab.getVTableHashFromAddress(getVTableMidAddr(vtable2)), + MD5Hash("vtable2")); + EXPECT_EQ(Symtab.getVTableHashFromAddress(getVTableMidAddr(vtable3)), + MD5Hash("vtable3")); + EXPECT_EQ(Symtab.getVTableHashFromAddress(getVTableMidAddr(vtable4)), + MD5Hash("vtable4")); auto Cmp = [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) { return VD1.Count > VD2.Count; }; - std::unique_ptr<InstrProfValueData[]> VD_0( - Record.getValueForSite(IPVK_IndirectCallTarget, 0)); + auto VD_0(Record.getValueForSite(IPVK_IndirectCallTarget, 0)); llvm::sort(&VD_0[0], &VD_0[5], Cmp); ASSERT_EQ(VD_0[0].Value, 0x2000ULL); - ASSERT_EQ(1000U, VD_0[0].Count); + ASSERT_EQ(VD_0[0].Count, 1000U); ASSERT_EQ(VD_0[1].Value, 0x3000ULL); - ASSERT_EQ(500U, VD_0[1].Count); + ASSERT_EQ(VD_0[1].Count, 500U); ASSERT_EQ(VD_0[2].Value, 0x1000ULL); - ASSERT_EQ(400U, VD_0[2].Count); + ASSERT_EQ(VD_0[2].Count, 400U); // callee5 does not have a mapped value -- default to 0. ASSERT_EQ(VD_0[4].Value, 0ULL); + + // Sanity check the vtable value data + ASSERT_EQ(Record.getNumValueSites(IPVK_VTableTarget), 4U); + + { + // The first vtable site. + auto VD(Record.getValueForSite(IPVK_VTableTarget, 0)); + ASSERT_EQ(Record.getNumValueDataForSite(IPVK_VTableTarget, 0), 5U); + llvm::sort(&VD[0], &VD[5], Cmp); + EXPECT_EQ(VD[0].Count, 1000U); + EXPECT_EQ(VD[0].Value, MD5Hash("vtable2")); + EXPECT_EQ(VD[1].Count, 500U); + EXPECT_EQ(VD[1].Value, MD5Hash("vtable3")); + EXPECT_EQ(VD[2].Value, MD5Hash("vtable1")); + EXPECT_EQ(VD[2].Count, 400U); + EXPECT_EQ(VD[3].Value, MD5Hash("vtable4")); + EXPECT_EQ(VD[3].Count, 300U); + + // vtable5 isn't mapped -- default to 0. + EXPECT_EQ(VD[4].Value, 0U); + EXPECT_EQ(VD[4].Count, 100U); + } + + { + // The second vtable site. + auto VD(Record.getValueForSite(IPVK_VTableTarget, 1)); + ASSERT_EQ(Record.getNumValueDataForSite(IPVK_VTableTarget, 1), 4U); + llvm::sort(&VD[0], &VD[4], Cmp); + EXPECT_EQ(VD[0].Value, MD5Hash("vtable2")); + EXPECT_EQ(VD[0].Count, 2500U); + EXPECT_EQ(VD[1].Value, MD5Hash("vtable1")); + EXPECT_EQ(VD[1].Count, 1300U); + + EXPECT_EQ(VD[2].Value, MD5Hash("vtable3")); + EXPECT_EQ(VD[2].Count, 1000U); + // vtable5 isn't mapped -- default to 0. + EXPECT_EQ(VD[3].Value, 0U); + EXPECT_EQ(VD[3].Count, 800U); + } + + { + // The third vtable site. + auto VD(Record.getValueForSite(IPVK_VTableTarget, 2)); + ASSERT_EQ(Record.getNumValueDataForSite(IPVK_VTableTarget, 2), 3U); + llvm::sort(&VD[0], &VD[3], Cmp); + EXPECT_EQ(VD[0].Count, 5500U); + EXPECT_EQ(VD[0].Value, MD5Hash("vtable4")); + EXPECT_EQ(VD[1].Count, 1000U); + EXPECT_EQ(VD[1].Value, MD5Hash("vtable3")); + // vtable6 isn't mapped -- default to 0. + EXPECT_EQ(VD[2].Value, 0U); + EXPECT_EQ(VD[2].Count, 800U); + } + + { + // The fourth vtable site. + auto VD(Record.getValueForSite(IPVK_VTableTarget, 3)); + ASSERT_EQ(Record.getNumValueDataForSite(IPVK_VTableTarget, 3), 2U); + llvm::sort(&VD[0], &VD[2], Cmp); + EXPECT_EQ(VD[0].Count, 2000U); + EXPECT_EQ(VD[0].Value, MD5Hash("vtable3")); + EXPECT_EQ(VD[1].Count, 1800U); + EXPECT_EQ(VD[1].Value, MD5Hash("vtable2")); + } } TEST_P(MaybeSparseInstrProfTest, get_max_function_count) { @@ -1277,13 +1616,13 @@ TEST(SymtabTest, instr_prof_symtab_module_test) { std::string IRPGOName = getIRPGOFuncName(*F); auto IRPGOFuncName = ProfSymtab.getFuncOrVarName(IndexedInstrProf::ComputeHash(IRPGOName)); - EXPECT_EQ(StringRef(IRPGOName), IRPGOFuncName); - EXPECT_EQ(StringRef(Funcs[I]), getParsedIRPGOName(IRPGOFuncName).second); + EXPECT_EQ(IRPGOName, IRPGOFuncName); + EXPECT_EQ(Funcs[I], getParsedIRPGOName(IRPGOFuncName).second); // Ensure we can still read this old record name. std::string PGOName = getPGOFuncName(*F); auto PGOFuncName = ProfSymtab.getFuncOrVarName(IndexedInstrProf::ComputeHash(PGOName)); - EXPECT_EQ(StringRef(PGOName), PGOFuncName); + EXPECT_EQ(PGOName, PGOFuncName); EXPECT_THAT(PGOFuncName.str(), EndsWith(Funcs[I].str())); } } diff --git a/llvm/unittests/ProfileData/MemProfTest.cpp b/llvm/unittests/ProfileData/MemProfTest.cpp index f5e4a4aff2ed17c7791a1f67be6efb147270e4eb..1cca44e9b03707b6eec907851b0e321e8633ba38 100644 --- a/llvm/unittests/ProfileData/MemProfTest.cpp +++ b/llvm/unittests/ProfileData/MemProfTest.cpp @@ -280,7 +280,8 @@ TEST(MemProf, RecordSerializationRoundTrip) { IndexedMemProfRecord Record; for (const auto &ACS : AllocCallStacks) { // Use the same info block for both allocation sites. - Record.AllocSites.emplace_back(ACS, Info); + Record.AllocSites.emplace_back(ACS, llvm::memprof::hashCallStack(ACS), + Info); } Record.CallSites.assign(CallSites); @@ -376,7 +377,9 @@ TEST(MemProf, BaseMemProfReader) { Block.AllocCount = 1U, Block.TotalAccessDensity = 4, Block.TotalLifetime = 200001; std::array<FrameId, 2> CallStack{F1.hash(), F2.hash()}; - FakeRecord.AllocSites.emplace_back(/*CS=*/CallStack, /*MB=*/Block); + FakeRecord.AllocSites.emplace_back( + /*CS=*/CallStack, /*CSId=*/llvm::memprof::hashCallStack(CallStack), + /*MB=*/Block); ProfData.insert({F1.hash(), FakeRecord}); MemProfReader Reader(FrameIdMap, ProfData); diff --git a/llvm/unittests/Support/FormatVariadicTest.cpp b/llvm/unittests/Support/FormatVariadicTest.cpp index 58c89aad7a85bed654542e34c800397c5689e3b9..a78b25c53d7e43d47833be1a043066b9ea215d71 100644 --- a/llvm/unittests/Support/FormatVariadicTest.cpp +++ b/llvm/unittests/Support/FormatVariadicTest.cpp @@ -20,8 +20,8 @@ struct Format : public FormatAdapter<int> { void format(raw_ostream &OS, StringRef Opt) override { OS << "Format"; } }; -using detail::uses_format_member; -using detail::uses_missing_provider; +using support::detail::uses_format_member; +using support::detail::uses_missing_provider; static_assert(uses_format_member<Format>::value, ""); static_assert(uses_format_member<Format &>::value, ""); diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp index d3177ce7e98371fc003cfc17da4cef40ef5515f9..027d6379af26b0902d800be785c2af53c0f8aea6 100644 --- a/llvm/unittests/Support/KnownBitsTest.cpp +++ b/llvm/unittests/Support/KnownBitsTest.cpp @@ -362,39 +362,14 @@ TEST(KnownBitsTest, BinaryExhaustive) { return Known1 ^ Known2; }, [](const APInt &N1, const APInt &N2) { return N1 ^ N2; }); - - testBinaryOpExhaustive( - [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::umax(Known1, Known2); - }, - [](const APInt &N1, const APInt &N2) { return APIntOps::umax(N1, N2); }); - testBinaryOpExhaustive( - [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::umin(Known1, Known2); - }, - [](const APInt &N1, const APInt &N2) { return APIntOps::umin(N1, N2); }); - testBinaryOpExhaustive( - [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::smax(Known1, Known2); - }, - [](const APInt &N1, const APInt &N2) { return APIntOps::smax(N1, N2); }); - testBinaryOpExhaustive( - [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::smin(Known1, Known2); - }, - [](const APInt &N1, const APInt &N2) { return APIntOps::smin(N1, N2); }); - testBinaryOpExhaustive( - [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::abdu(Known1, Known2); - }, - [](const APInt &N1, const APInt &N2) { return APIntOps::abdu(N1, N2); }, - checkCorrectnessOnlyBinary); - testBinaryOpExhaustive( - [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::abds(Known1, Known2); - }, - [](const APInt &N1, const APInt &N2) { return APIntOps::abds(N1, N2); }, - checkCorrectnessOnlyBinary); + testBinaryOpExhaustive(KnownBits::umax, APIntOps::umax); + testBinaryOpExhaustive(KnownBits::umin, APIntOps::umin); + testBinaryOpExhaustive(KnownBits::smax, APIntOps::smax); + testBinaryOpExhaustive(KnownBits::smin, APIntOps::smin); + testBinaryOpExhaustive(KnownBits::abdu, APIntOps::abdu, + checkCorrectnessOnlyBinary); + testBinaryOpExhaustive(KnownBits::abds, APIntOps::abds, + checkCorrectnessOnlyBinary); testBinaryOpExhaustive( [](const KnownBits &Known1, const KnownBits &Known2) { return KnownBits::udiv(Known1, Known2); @@ -437,9 +412,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { }, checkCorrectnessOnlyBinary); testBinaryOpExhaustive( - [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::urem(Known1, Known2); - }, + KnownBits::urem, [](const APInt &N1, const APInt &N2) -> std::optional<APInt> { if (N2.isZero()) return std::nullopt; @@ -447,9 +420,7 @@ TEST(KnownBitsTest, BinaryExhaustive) { }, checkCorrectnessOnlyBinary); testBinaryOpExhaustive( - [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::srem(Known1, Known2); - }, + KnownBits::srem, [](const APInt &N1, const APInt &N2) -> std::optional<APInt> { if (N2.isZero()) return std::nullopt; @@ -457,33 +428,25 @@ TEST(KnownBitsTest, BinaryExhaustive) { }, checkCorrectnessOnlyBinary); testBinaryOpExhaustive( - [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::sadd_sat(Known1, Known2); - }, + KnownBits::sadd_sat, [](const APInt &N1, const APInt &N2) -> std::optional<APInt> { return N1.sadd_sat(N2); }, checkCorrectnessOnlyBinary); testBinaryOpExhaustive( - [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::uadd_sat(Known1, Known2); - }, + KnownBits::uadd_sat, [](const APInt &N1, const APInt &N2) -> std::optional<APInt> { return N1.uadd_sat(N2); }, checkCorrectnessOnlyBinary); testBinaryOpExhaustive( - [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::ssub_sat(Known1, Known2); - }, + KnownBits::ssub_sat, [](const APInt &N1, const APInt &N2) -> std::optional<APInt> { return N1.ssub_sat(N2); }, checkCorrectnessOnlyBinary); testBinaryOpExhaustive( - [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::usub_sat(Known1, Known2); - }, + KnownBits::usub_sat, [](const APInt &N1, const APInt &N2) -> std::optional<APInt> { return N1.usub_sat(N2); }, @@ -582,7 +545,6 @@ TEST(KnownBitsTest, BinaryExhaustive) { return N1.ashr(N2); }, checkOptimalityBinary, /* RefinePoisonToZero */ true); - testBinaryOpExhaustive( [](const KnownBits &Known1, const KnownBits &Known2) { return KnownBits::mul(Known1, Known2); @@ -590,22 +552,12 @@ TEST(KnownBitsTest, BinaryExhaustive) { [](const APInt &N1, const APInt &N2) { return N1 * N2; }, checkCorrectnessOnlyBinary); testBinaryOpExhaustive( - [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::mulhs(Known1, Known2); - }, - [](const APInt &N1, const APInt &N2) { - unsigned Bits = N1.getBitWidth(); - return (N1.sext(2 * Bits) * N2.sext(2 * Bits)).extractBits(Bits, Bits); - }, + KnownBits::mulhs, + [](const APInt &N1, const APInt &N2) { return APIntOps::mulhs(N1, N2); }, checkCorrectnessOnlyBinary); testBinaryOpExhaustive( - [](const KnownBits &Known1, const KnownBits &Known2) { - return KnownBits::mulhu(Known1, Known2); - }, - [](const APInt &N1, const APInt &N2) { - unsigned Bits = N1.getBitWidth(); - return (N1.zext(2 * Bits) * N2.zext(2 * Bits)).extractBits(Bits, Bits); - }, + KnownBits::mulhu, + [](const APInt &N1, const APInt &N2) { return APIntOps::mulhu(N1, N2); }, checkCorrectnessOnlyBinary); } diff --git a/llvm/unittests/Support/LEB128Test.cpp b/llvm/unittests/Support/LEB128Test.cpp index 21523e5f7a08c73b854870fed8dde990747e9394..08b8c5573ce637062ddbf27825c74e9736778130 100644 --- a/llvm/unittests/Support/LEB128Test.cpp +++ b/llvm/unittests/Support/LEB128Test.cpp @@ -242,6 +242,21 @@ TEST(LEB128Test, DecodeInvalidSLEB128) { #undef EXPECT_INVALID_SLEB128 } +TEST(LEB128Test, DecodeAndInc) { +#define EXPECT_LEB128(FUN, VALUE, SIZE) \ + do { \ + const uint8_t *V = reinterpret_cast<const uint8_t *>(VALUE), *P = V; \ + auto Expected = FUN(P), Actual = FUN##AndInc(P); \ + EXPECT_EQ(Actual, Expected); \ + EXPECT_EQ(P - V, SIZE); \ + } while (0) + EXPECT_LEB128(decodeULEB128, "\x7f", 1); + EXPECT_LEB128(decodeULEB128, "\x80\x01", 2); + EXPECT_LEB128(decodeSLEB128, "\x7f", 1); + EXPECT_LEB128(decodeSLEB128, "\x80\x01", 2); +#undef EXPECT_LEB128 +} + TEST(LEB128Test, SLEB128Size) { // Positive Value Testing Plan: // (1) 128 ^ n - 1 ........ need (n+1) bytes diff --git a/llvm/unittests/Support/RISCVISAInfoTest.cpp b/llvm/unittests/Support/RISCVISAInfoTest.cpp index 82cf4c639b6160859c0622db2f5c4d8b7bc299a6..a331e6a74ceb631f2170cb4b38d019b4402ad12a 100644 --- a/llvm/unittests/Support/RISCVISAInfoTest.cpp +++ b/llvm/unittests/Support/RISCVISAInfoTest.cpp @@ -739,170 +739,173 @@ TEST(RiscvExtensionsHelp, CheckExtensions) { std::string ExpectedOutput = R"(All available -march extensions for RISC-V - Name Version Description - i 2.1 This is a long dummy description - e 2.0 - m 2.0 - a 2.1 - f 2.2 - d 2.2 - c 2.0 - v 1.0 - h 1.0 - zic64b 1.0 - zicbom 1.0 - zicbop 1.0 - zicboz 1.0 - ziccamoa 1.0 - ziccif 1.0 - zicclsm 1.0 - ziccrse 1.0 - zicntr 2.0 - zicond 1.0 - zicsr 2.0 - zifencei 2.0 - zihintntl 1.0 - zihintpause 2.0 - zihpm 2.0 - zmmul 1.0 - za128rs 1.0 - za64rs 1.0 - zacas 1.0 - zawrs 1.0 - zfa 1.0 - zfh 1.0 - zfhmin 1.0 - zfinx 1.0 - zdinx 1.0 - zca 1.0 - zcb 1.0 - zcd 1.0 - zce 1.0 - zcf 1.0 - zcmp 1.0 - zcmt 1.0 - zba 1.0 - zbb 1.0 - zbc 1.0 - zbkb 1.0 - zbkc 1.0 - zbkx 1.0 - zbs 1.0 - zk 1.0 - zkn 1.0 - zknd 1.0 - zkne 1.0 - zknh 1.0 - zkr 1.0 - zks 1.0 - zksed 1.0 - zksh 1.0 - zkt 1.0 - zvbb 1.0 - zvbc 1.0 - zve32f 1.0 - zve32x 1.0 - zve64d 1.0 - zve64f 1.0 - zve64x 1.0 - zvfh 1.0 - zvfhmin 1.0 - zvkb 1.0 - zvkg 1.0 - zvkn 1.0 - zvknc 1.0 - zvkned 1.0 - zvkng 1.0 - zvknha 1.0 - zvknhb 1.0 - zvks 1.0 - zvksc 1.0 - zvksed 1.0 - zvksg 1.0 - zvksh 1.0 - zvkt 1.0 - zvl1024b 1.0 - zvl128b 1.0 - zvl16384b 1.0 - zvl2048b 1.0 - zvl256b 1.0 - zvl32768b 1.0 - zvl32b 1.0 - zvl4096b 1.0 - zvl512b 1.0 - zvl64b 1.0 - zvl65536b 1.0 - zvl8192b 1.0 - zhinx 1.0 - zhinxmin 1.0 - shcounterenw 1.0 - shgatpa 1.0 - shtvala 1.0 - shvsatpa 1.0 - shvstvala 1.0 - shvstvecd 1.0 - smaia 1.0 - smepmp 1.0 - ssaia 1.0 - ssccptr 1.0 - sscofpmf 1.0 - sscounterenw 1.0 - ssstateen 1.0 - ssstrict 1.0 - sstc 1.0 - sstvala 1.0 - sstvecd 1.0 - ssu64xl 1.0 - svade 1.0 - svadu 1.0 - svbare 1.0 - svinval 1.0 - svnapot 1.0 - svpbmt 1.0 - xcvalu 1.0 - xcvbi 1.0 - xcvbitmanip 1.0 - xcvelw 1.0 - xcvmac 1.0 - xcvmem 1.0 - xcvsimd 1.0 - xsfvcp 1.0 - xsfvfnrclipxfqf 1.0 - xsfvfwmaccqqq 1.0 - xsfvqmaccdod 1.0 - xsfvqmaccqoq 1.0 - xtheadba 1.0 - xtheadbb 1.0 - xtheadbs 1.0 - xtheadcmo 1.0 - xtheadcondmov 1.0 - xtheadfmemidx 1.0 - xtheadmac 1.0 - xtheadmemidx 1.0 - xtheadmempair 1.0 - xtheadsync 1.0 - xtheadvdot 1.0 - xventanacondops 1.0 + Name Version Description + i 2.1 This is a long dummy description + e 2.0 + m 2.0 + a 2.1 + f 2.2 + d 2.2 + c 2.0 + v 1.0 + h 1.0 + zic64b 1.0 + zicbom 1.0 + zicbop 1.0 + zicboz 1.0 + ziccamoa 1.0 + ziccif 1.0 + zicclsm 1.0 + ziccrse 1.0 + zicntr 2.0 + zicond 1.0 + zicsr 2.0 + zifencei 2.0 + zihintntl 1.0 + zihintpause 2.0 + zihpm 2.0 + zmmul 1.0 + za128rs 1.0 + za64rs 1.0 + zacas 1.0 + zawrs 1.0 + zfa 1.0 + zfh 1.0 + zfhmin 1.0 + zfinx 1.0 + zdinx 1.0 + zca 1.0 + zcb 1.0 + zcd 1.0 + zce 1.0 + zcf 1.0 + zcmp 1.0 + zcmt 1.0 + zba 1.0 + zbb 1.0 + zbc 1.0 + zbkb 1.0 + zbkc 1.0 + zbkx 1.0 + zbs 1.0 + zk 1.0 + zkn 1.0 + zknd 1.0 + zkne 1.0 + zknh 1.0 + zkr 1.0 + zks 1.0 + zksed 1.0 + zksh 1.0 + zkt 1.0 + zvbb 1.0 + zvbc 1.0 + zve32f 1.0 + zve32x 1.0 + zve64d 1.0 + zve64f 1.0 + zve64x 1.0 + zvfh 1.0 + zvfhmin 1.0 + zvkb 1.0 + zvkg 1.0 + zvkn 1.0 + zvknc 1.0 + zvkned 1.0 + zvkng 1.0 + zvknha 1.0 + zvknhb 1.0 + zvks 1.0 + zvksc 1.0 + zvksed 1.0 + zvksg 1.0 + zvksh 1.0 + zvkt 1.0 + zvl1024b 1.0 + zvl128b 1.0 + zvl16384b 1.0 + zvl2048b 1.0 + zvl256b 1.0 + zvl32768b 1.0 + zvl32b 1.0 + zvl4096b 1.0 + zvl512b 1.0 + zvl64b 1.0 + zvl65536b 1.0 + zvl8192b 1.0 + zhinx 1.0 + zhinxmin 1.0 + shcounterenw 1.0 + shgatpa 1.0 + shtvala 1.0 + shvsatpa 1.0 + shvstvala 1.0 + shvstvecd 1.0 + smaia 1.0 + smepmp 1.0 + ssaia 1.0 + ssccptr 1.0 + sscofpmf 1.0 + sscounterenw 1.0 + ssstateen 1.0 + ssstrict 1.0 + sstc 1.0 + sstvala 1.0 + sstvecd 1.0 + ssu64xl 1.0 + svade 1.0 + svadu 1.0 + svbare 1.0 + svinval 1.0 + svnapot 1.0 + svpbmt 1.0 + xcvalu 1.0 + xcvbi 1.0 + xcvbitmanip 1.0 + xcvelw 1.0 + xcvmac 1.0 + xcvmem 1.0 + xcvsimd 1.0 + xsfcease 1.0 + xsfvcp 1.0 + xsfvfnrclipxfqf 1.0 + xsfvfwmaccqqq 1.0 + xsfvqmaccdod 1.0 + xsfvqmaccqoq 1.0 + xsifivecdiscarddlone 1.0 + xsifivecflushdlone 1.0 + xtheadba 1.0 + xtheadbb 1.0 + xtheadbs 1.0 + xtheadcmo 1.0 + xtheadcondmov 1.0 + xtheadfmemidx 1.0 + xtheadmac 1.0 + xtheadmemidx 1.0 + xtheadmempair 1.0 + xtheadsync 1.0 + xtheadvdot 1.0 + xventanacondops 1.0 Experimental extensions - zicfilp 0.4 This is a long dummy description - zicfiss 0.4 - zimop 0.1 - zaamo 0.2 - zabha 1.0 - zalasr 0.1 - zalrsc 0.2 - zfbfmin 1.0 - zcmop 0.2 - ztso 0.1 - zvfbfmin 1.0 - zvfbfwma 1.0 - smmpm 0.8 - smnpm 0.8 - ssnpm 0.8 - sspm 0.8 - ssqosid 1.0 - supm 0.8 + zicfilp 0.4 This is a long dummy description + zicfiss 0.4 + zimop 0.1 + zaamo 0.2 + zabha 1.0 + zalasr 0.1 + zalrsc 0.2 + zfbfmin 1.0 + zcmop 0.2 + ztso 0.1 + zvfbfmin 1.0 + zvfbfwma 1.0 + smmpm 0.8 + smnpm 0.8 + ssnpm 0.8 + sspm 0.8 + ssqosid 1.0 + supm 0.8 Use -march to specify the target's extension. For example, clang -march=rv32i_v1p0)"; diff --git a/llvm/unittests/Support/ThreadPool.cpp b/llvm/unittests/Support/ThreadPool.cpp index d74c625d122950e7041aa865c2b3c1776f3bc11d..381b4fc2a26b8ed5bdcada897186b3f653fa7def 100644 --- a/llvm/unittests/Support/ThreadPool.cpp +++ b/llvm/unittests/Support/ThreadPool.cpp @@ -126,7 +126,7 @@ using ThreadPoolImpls = ::testing::Types< #endif SingleThreadExecutor>; -TYPED_TEST_SUITE(ThreadPoolTest, ThreadPoolImpls); +TYPED_TEST_SUITE(ThreadPoolTest, ThreadPoolImpls, ); #define CHECK_UNSUPPORTED() \ do { \ diff --git a/llvm/unittests/Support/TimeProfilerTest.cpp b/llvm/unittests/Support/TimeProfilerTest.cpp index 6be716bae6b3fb5af9b64edd347ed28cd1535911..bb820ec99a393ef008c4be692d1a95538e376820 100644 --- a/llvm/unittests/Support/TimeProfilerTest.cpp +++ b/llvm/unittests/Support/TimeProfilerTest.cpp @@ -54,6 +54,17 @@ TEST(TimeProfiler, Begin_End_Smoke) { ASSERT_TRUE(json.find(R"("detail":"detail")") != std::string::npos); } +TEST(TimeProfiler, Async_Begin_End_Smoke) { + setupProfiler(); + + auto *Profiler = timeTraceAsyncProfilerBegin("event", "detail"); + timeTraceProfilerEnd(Profiler); + + std::string json = teardownProfiler(); + ASSERT_TRUE(json.find(R"("name":"event")") != std::string::npos); + ASSERT_TRUE(json.find(R"("detail":"detail")") != std::string::npos); +} + TEST(TimeProfiler, Begin_End_Disabled) { // Nothing should be observable here. The test is really just making sure // we've not got a stray nullptr deref. diff --git a/llvm/unittests/Support/VirtualFileSystemTest.cpp b/llvm/unittests/Support/VirtualFileSystemTest.cpp index d4abbb4345873cfa22873656769338f10ecdd0c1..695b09343257f1e5819b4cb51466552acda88c4b 100644 --- a/llvm/unittests/Support/VirtualFileSystemTest.cpp +++ b/llvm/unittests/Support/VirtualFileSystemTest.cpp @@ -7,9 +7,11 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/VirtualFileSystem.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/Config/llvm-config.h" #include "llvm/Support/Errc.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/SourceMgr.h" @@ -3330,3 +3332,66 @@ TEST(RedirectingFileSystemTest, Used) { EXPECT_TRUE(Redirecting1->hasBeenUsed()); EXPECT_FALSE(Redirecting2->hasBeenUsed()); } + +// Check that paths looked up in the external filesystem are unmodified, except +// potentially to add the working directory. We cannot canonicalize away .. +// in the presence of symlinks in the external filesystem. +TEST(RedirectingFileSystemTest, ExternalPaths) { + struct InterceptorFS : llvm::vfs::ProxyFileSystem { + std::vector<std::string> SeenPaths; + + InterceptorFS(IntrusiveRefCntPtr<FileSystem> UnderlyingFS) + : ProxyFileSystem(UnderlyingFS) {} + + llvm::ErrorOr<llvm::vfs::Status> status(const Twine &Path) override { + SeenPaths.push_back(Path.str()); + return ProxyFileSystem::status(Path); + } + + llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>> + openFileForRead(const Twine &Path) override { + SeenPaths.push_back(Path.str()); + return ProxyFileSystem::openFileForRead(Path); + } + + std::error_code isLocal(const Twine &Path, bool &Result) override { + SeenPaths.push_back(Path.str()); + return ProxyFileSystem::isLocal(Path, Result); + } + + vfs::directory_iterator dir_begin(const Twine &Dir, + std::error_code &EC) override { + SeenPaths.push_back(Dir.str()); + return ProxyFileSystem::dir_begin(Dir, EC); + } + }; + + std::error_code EC; + auto BaseFS = makeIntrusiveRefCnt<DummyFileSystem>(); + BaseFS->setCurrentWorkingDirectory("/cwd"); + auto CheckFS = makeIntrusiveRefCnt<InterceptorFS>(BaseFS); + auto FS = vfs::RedirectingFileSystem::create({}, /*UseExternalNames=*/false, + *CheckFS); + + FS->status("/a/../b"); + FS->openFileForRead("c"); + FS->exists("./d"); + bool IsLocal = false; + FS->isLocal("/e/./../f", IsLocal); + FS->dir_begin(".././g", EC); + + std::vector<std::string> Expected{"/a/../b", "/cwd/c", "/cwd/./d", + "/e/./../f", "/cwd/.././g"}; + + EXPECT_EQ(CheckFS->SeenPaths, Expected); + + CheckFS->SeenPaths.clear(); + FS->setRedirection(vfs::RedirectingFileSystem::RedirectKind::Fallback); + FS->status("/a/../b"); + FS->openFileForRead("c"); + FS->exists("./d"); + FS->isLocal("/e/./../f", IsLocal); + FS->dir_begin(".././g", EC); + + EXPECT_EQ(CheckFS->SeenPaths, Expected); +} diff --git a/llvm/unittests/TableGen/CMakeLists.txt b/llvm/unittests/TableGen/CMakeLists.txt index 7830e021804589b9200998b15f924b407cf74915..57b237306b19cb10b25870755c25aeb636af630e 100644 --- a/llvm/unittests/TableGen/CMakeLists.txt +++ b/llvm/unittests/TableGen/CMakeLists.txt @@ -9,10 +9,10 @@ tablegen(LLVM AutomataTables.inc -gen-searchable-tables) tablegen(LLVM AutomataAutomata.inc -gen-automata) add_public_tablegen_target(AutomataTestTableGen) -add_llvm_unittest(TableGenTests DISABLE_LLVM_LINK_LLVM_DYLIB +add_llvm_unittest(TableGenTests AutomataTest.cpp CodeExpanderTest.cpp ParserEntryPointTest.cpp ) -target_link_libraries(TableGenTests PRIVATE LLVMTableGenGlobalISel LLVMTableGen) +target_link_libraries(TableGenTests PRIVATE LLVMTableGenCommon LLVMTableGen) diff --git a/llvm/unittests/TableGen/CodeExpanderTest.cpp b/llvm/unittests/TableGen/CodeExpanderTest.cpp index 4a9a0e8c114bc005bf7c41409e71c37f0ef55926..1528884ffdf65b7dcffe85d44786e8ffcb64eadc 100644 --- a/llvm/unittests/TableGen/CodeExpanderTest.cpp +++ b/llvm/unittests/TableGen/CodeExpanderTest.cpp @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "GlobalISel/CodeExpander.h" -#include "GlobalISel/CodeExpansions.h" +#include "Common/GlobalISel/CodeExpander.h" +#include "Common/GlobalISel/CodeExpansions.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Error.h" diff --git a/llvm/unittests/Target/AArch64/AddressingModes.cpp b/llvm/unittests/Target/AArch64/AddressingModes.cpp index 284ea7ae9233ed175340039a5122aef6ac3ecb29..0af18d886791a1e6fa6edeeea0adacfdf73df6f1 100644 --- a/llvm/unittests/Target/AArch64/AddressingModes.cpp +++ b/llvm/unittests/Target/AArch64/AddressingModes.cpp @@ -13,11 +13,13 @@ using namespace llvm; namespace { struct AddrMode : public TargetLowering::AddrMode { - constexpr AddrMode(GlobalValue *GV, int64_t Offs, bool HasBase, int64_t S) { + constexpr AddrMode(GlobalValue *GV, int64_t Offs, bool HasBase, int64_t S, + int64_t SOffs = 0) { BaseGV = GV; BaseOffs = Offs; HasBaseReg = HasBase; Scale = S; + ScalableOffset = SOffs; } }; struct TestCase { @@ -153,6 +155,45 @@ const std::initializer_list<TestCase> Tests = { {{nullptr, 4096 + 1, true, 0}, 8, false}, }; + +struct SVETestCase { + AddrMode AM; + unsigned TypeBits; + unsigned NumElts; + bool Result; +}; + +const std::initializer_list<SVETestCase> SVETests = { + // {BaseGV, BaseOffs, HasBaseReg, Scale, SOffs}, EltBits, Count, Result + // Test immediate range -- [-8,7] vector's worth. + // <vscale x 16 x i8>, increment by one vector + {{nullptr, 0, true, 0, 16}, 8, 16, true}, + // <vscale x 4 x i32>, increment by eight vectors + {{nullptr, 0, true, 0, 128}, 32, 4, false}, + // <vscale x 8 x i16>, increment by seven vectors + {{nullptr, 0, true, 0, 112}, 16, 8, true}, + // <vscale x 2 x i64>, decrement by eight vectors + {{nullptr, 0, true, 0, -128}, 64, 2, true}, + // <vscale x 16 x i8>, decrement by nine vectors + {{nullptr, 0, true, 0, -144}, 8, 16, false}, + + // Half the size of a vector register, but allowable with extending + // loads and truncating stores + // <vscale x 8 x i8>, increment by three vectors + {{nullptr, 0, true, 0, 24}, 8, 8, true}, + + // Test invalid types or offsets + // <vscale x 5 x i32>, increment by one vector (base size > 16B) + {{nullptr, 0, true, 0, 20}, 32, 5, false}, + // <vscale x 8 x i16>, increment by half a vector + {{nullptr, 0, true, 0, 8}, 16, 8, false}, + // <vscale x 3 x i8>, increment by 3 vectors (non-power-of-two) + {{nullptr, 0, true, 0, 9}, 8, 3, false}, + + // Scalable and fixed offsets + // <vscale x 16 x i8>, increment by 32 then decrement by vscale x 16 + {{nullptr, 32, true, 0, -16}, 8, 16, false}, +}; } // namespace TEST(AddressingModes, AddressingModes) { @@ -179,4 +220,11 @@ TEST(AddressingModes, AddressingModes) { Type *Typ = Type::getIntNTy(Ctx, Test.TypeBits); ASSERT_EQ(TLI->isLegalAddressingMode(DL, Test.AM, Typ, 0), Test.Result); } + + for (const auto &SVETest : SVETests) { + Type *Ty = VectorType::get(Type::getIntNTy(Ctx, SVETest.TypeBits), + ElementCount::getScalable(SVETest.NumElts)); + ASSERT_EQ(TLI->isLegalAddressingMode(DL, SVETest.AM, Ty, 0), + SVETest.Result); + } } diff --git a/llvm/unittests/Target/AArch64/CMakeLists.txt b/llvm/unittests/Target/AArch64/CMakeLists.txt index dacd919ba1e33b33484550a2552e8ec42ceb8eb9..64ab991ac479a4914ffcfcb99153329da82000cf 100644 --- a/llvm/unittests/Target/AArch64/CMakeLists.txt +++ b/llvm/unittests/Target/AArch64/CMakeLists.txt @@ -29,6 +29,7 @@ add_llvm_target_unittest(AArch64Tests MatrixRegisterAliasing.cpp SMEAttributesTest.cpp AArch64SVESchedPseudoTest.cpp + Immediates.cpp ) set_property(TARGET AArch64Tests PROPERTY FOLDER "Tests/UnitTests/TargetTests") diff --git a/llvm/unittests/Target/AArch64/Immediates.cpp b/llvm/unittests/Target/AArch64/Immediates.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a4551b083b4407cdda8ad9fb14775c88b2ef0fca --- /dev/null +++ b/llvm/unittests/Target/AArch64/Immediates.cpp @@ -0,0 +1,106 @@ +#include "AArch64Subtarget.h" +#include "AArch64TargetMachine.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/MC/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" + +#include "gtest/gtest.h" +#include <initializer_list> +#include <memory> + +using namespace llvm; + +namespace { + +struct TestCase { + int64_t Imm; + bool Result; +}; + +const std::initializer_list<TestCase> Tests = { + // ScalableImm, Result + // No change, easily 'supported' + {0, true}, + + // addvl increments by whole registers, range [-32,31] + // +(16 * vscale), one register's worth + {16, true}, + // -(32 * 16 * vscale) + {-512, true}, + // -(33 * 16 * vscale) + {-528, false}, + // +(31 * 16 * vscale) + {496, true}, + // +(32 * 16 * vscale) + {512, false}, + + // inc[h|w|d] increments by the number of 16/32/64bit elements in a + // register. mult_imm is in the range [1,16] + // +(mult_imm * num_elts * vscale) + // +(1 * 8 * vscale), 16 bit + {8, true}, + // +(15 * 8 * vscale), 16 bit + {120, true}, + // +(1 * 4 * vscale), 32 bit + {4, true}, + // +(7 * 4 * vscale), 32 bit + {28, true}, + // +(1 * 2 * vscale), 64 bit + {2, true}, + // +(13 * 2 * vscale), 64 bit + {26, true}, + // +(17 * 8 * vscale), 16 bit, out of range. + {136, false}, + // +(19 * 2 * vscale), 64 bit, out of range. + {38, false}, + // +(21 * 4 * vscale), 32 bit, out of range. + {84, false}, + + // dec[h|w|d] -- Same as above, but negative. + // -(mult_imm * num_elts * vscale) + // -(1 * 8 * vscale), 16 bit + {-8, true}, + // -(15 * 8 * vscale), 16 bit + {-120, true}, + // -(1 * 4 * vscale), 32 bit + {-4, true}, + // -(7 * 4 * vscale), 32 bit + {-28, true}, + // -(1 * 2 * vscale), 64 bit + {-2, true}, + // -(13 * 2 * vscale), 64 bit + {-26, true}, + // -(17 * 8 * vscale), 16 bit, out of range. + {-136, false}, + // -(19 * 2 * vscale), 64 bit, out of range. + {-38, false}, + // -(21 * 4 * vscale), 32 bit, out of range. + {-84, false}, + + // Invalid; not divisible by the above powers of 2. + {5, false}, +}; +} // namespace + +TEST(Immediates, Immediates) { + LLVMInitializeAArch64TargetInfo(); + LLVMInitializeAArch64Target(); + LLVMInitializeAArch64TargetMC(); + + std::string Error; + auto TT = Triple::normalize("aarch64"); + const Target *T = TargetRegistry::lookupTarget(TT, Error); + + std::unique_ptr<TargetMachine> TM(T->createTargetMachine( + TT, "generic", "+sve2", TargetOptions(), std::nullopt, std::nullopt, + CodeGenOptLevel::Default)); + AArch64Subtarget ST(TM->getTargetTriple(), TM->getTargetCPU(), + TM->getTargetCPU(), TM->getTargetFeatureString(), *TM, + true); + + auto *TLI = ST.getTargetLowering(); + + for (const auto &Test : Tests) { + ASSERT_EQ(TLI->isLegalAddScalableImmediate(Test.Imm), Test.Result); + } +} diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp index 3773f59a3c5af9a9643d5d463d00228f5b78a0b7..2c72a7229b5274bd9b9231b16f2d41a337d8797f 100644 --- a/llvm/unittests/TargetParser/TargetParserTest.cpp +++ b/llvm/unittests/TargetParser/TargetParserTest.cpp @@ -1140,6 +1140,22 @@ INSTANTIATE_TEST_SUITE_P( AArch64::AEK_PERFMON, AArch64::AEK_PREDRES, AArch64::AEK_JSCVT, AArch64::AEK_FCMA}), "9.2-A"), + ARMCPUTestParams<AArch64::ExtensionBitset>( + "cortex-a520ae", "armv9.2-a", "crypto-neon-fp-armv8", + AArch64::ExtensionBitset( + {AArch64::AEK_BF16, AArch64::AEK_I8MM, + AArch64::AEK_SVE, AArch64::AEK_SVE2, + AArch64::AEK_FP16, AArch64::AEK_DOTPROD, + AArch64::AEK_LSE, AArch64::AEK_RDM, + AArch64::AEK_SIMD, AArch64::AEK_RCPC, + AArch64::AEK_RAS, AArch64::AEK_CRC, + AArch64::AEK_FP, AArch64::AEK_SB, + AArch64::AEK_SSBS, AArch64::AEK_MTE, + AArch64::AEK_FP16FML, AArch64::AEK_PAUTH, + AArch64::AEK_SVE2BITPERM, AArch64::AEK_FLAGM, + AArch64::AEK_PERFMON, AArch64::AEK_PREDRES, + AArch64::AEK_JSCVT, AArch64::AEK_FCMA}), + "9.2-A"), ARMCPUTestParams<AArch64::ExtensionBitset>( "cortex-a57", "armv8-a", "crypto-neon-fp-armv8", AArch64::ExtensionBitset({AArch64::AEK_CRC, AArch64::AEK_AES, @@ -1283,6 +1299,23 @@ INSTANTIATE_TEST_SUITE_P( AArch64::AEK_PROFILE, AArch64::AEK_JSCVT, AArch64::AEK_FCMA}), "9.2-A"), + ARMCPUTestParams<AArch64::ExtensionBitset>( + "cortex-a720ae", "armv9.2-a", "crypto-neon-fp-armv8", + AArch64::ExtensionBitset( + {AArch64::AEK_BF16, AArch64::AEK_I8MM, + AArch64::AEK_SVE, AArch64::AEK_SVE2, + AArch64::AEK_FP16, AArch64::AEK_DOTPROD, + AArch64::AEK_LSE, AArch64::AEK_RDM, + AArch64::AEK_SIMD, AArch64::AEK_RCPC, + AArch64::AEK_RAS, AArch64::AEK_CRC, + AArch64::AEK_FP, AArch64::AEK_SB, + AArch64::AEK_SSBS, AArch64::AEK_MTE, + AArch64::AEK_FP16FML, AArch64::AEK_PAUTH, + AArch64::AEK_SVE2BITPERM, AArch64::AEK_FLAGM, + AArch64::AEK_PERFMON, AArch64::AEK_PREDRES, + AArch64::AEK_PROFILE, AArch64::AEK_JSCVT, + AArch64::AEK_FCMA}), + "9.2-A"), ARMCPUTestParams<AArch64::ExtensionBitset>( "neoverse-v1", "armv8.4-a", "crypto-neon-fp-armv8", AArch64::ExtensionBitset( @@ -1717,7 +1750,7 @@ INSTANTIATE_TEST_SUITE_P( ARMCPUTestParams<AArch64::ExtensionBitset>::PrintToStringParamName); // Note: number of CPUs includes aliases. -static constexpr unsigned NumAArch64CPUArchs = 70; +static constexpr unsigned NumAArch64CPUArchs = 72; TEST(TargetParserTest, testAArch64CPUArchList) { SmallVector<StringRef, NumAArch64CPUArchs> List; @@ -2314,13 +2347,6 @@ AArch64ExtensionDependenciesBaseArchTestParams {}, {"aes", "sha2", "sha3", "sm4"}}, - // +sve implies +f32mm if the base architecture is v8.6A+ or v9.1A+, but - // not earlier architectures. - {AArch64::ARMV8_5A, {"sve"}, {"sve"}, {"f32mm"}}, - {AArch64::ARMV9A, {"sve"}, {"sve"}, {"f32mm"}}, - {AArch64::ARMV8_6A, {"sve"}, {"sve", "f32mm"}, {}}, - {AArch64::ARMV9_1A, {"sve"}, {"sve", "f32mm"}, {}}, - // +fp16 implies +fp16fml for v8.4A+, but not v9.0-A+ {AArch64::ARMV8_3A, {"fp16"}, {"fullfp16"}, {"fp16fml"}}, {AArch64::ARMV9A, {"fp16"}, {"fullfp16"}, {"fp16fml"}}, @@ -2487,10 +2513,10 @@ AArch64ExtensionDependenciesBaseCPUTestParams {}}, {"cortex-a520", {}, - {"v9.2a", "bf16", "crc", "dotprod", "f32mm", "flagm", - "fp-armv8", "fullfp16", "fp16fml", "i8mm", "lse", "mte", - "pauth", "perfmon", "predres", "ras", "rcpc", "rdm", - "sb", "neon", "ssbs", "sve", "sve2-bitperm", "sve2"}, + {"v9.2a", "bf16", "crc", "dotprod", "flagm", "fp-armv8", + "fullfp16", "fp16fml", "i8mm", "lse", "mte", "pauth", + "perfmon", "predres", "ras", "rcpc", "rdm", "sb", + "neon", "ssbs", "sve", "sve2-bitperm", "sve2"}, {}}, // Negative modifiers diff --git a/llvm/unittests/Transforms/Utils/CallPromotionUtilsTest.cpp b/llvm/unittests/Transforms/Utils/CallPromotionUtilsTest.cpp index eff8e27d36d64131ac09edd1bd21b250cd02b2b8..0e9641c5846f355effe3fc236e8d262bbea49be0 100644 --- a/llvm/unittests/Transforms/Utils/CallPromotionUtilsTest.cpp +++ b/llvm/unittests/Transforms/Utils/CallPromotionUtilsTest.cpp @@ -37,7 +37,7 @@ define void @f() { entry: %o = alloca %class.Impl %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0 - store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %base + store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %base %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1 store i32 3, i32* %f %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0 @@ -171,7 +171,7 @@ define void @f() { entry: %o = alloca %class.Impl %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0 - store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %base + store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %base %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1 store i32 3, i32* %f %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0 @@ -213,7 +213,7 @@ define void @f() { entry: %o = alloca %class.Impl %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0 - store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %base + store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %base %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1 store i32 3, i32* %f %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0 @@ -256,7 +256,7 @@ entry: %a = alloca %struct.A, align 8 %0 = bitcast %struct.A* %a to i8* %1 = getelementptr %struct.A, %struct.A* %a, i64 0, i32 0 - store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTV1A, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %1, align 8 + store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTV1A, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %1, align 8 %2 = bitcast %struct.A* %a to i8* %3 = bitcast i8* %2 to i8** %vtable.i = load i8*, i8** %3, align 8 @@ -271,7 +271,7 @@ entry: %a = alloca %struct.A, align 8 %0 = bitcast %struct.A* %a to i8* %1 = getelementptr %struct.A, %struct.A* %a, i64 0, i32 0 - store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTV1A, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %1, align 8 + store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTV1A, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %1, align 8 %2 = bitcast %struct.A* %a to i8* %3 = bitcast i8* %2 to i8** %vtable.i = load i8*, i8** %3, align 8 @@ -340,7 +340,7 @@ define %struct1 @f() { entry: %o = alloca %class.Impl %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0 - store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %base + store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %base %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1 store i32 3, i32* %f %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0 diff --git a/llvm/unittests/Transforms/Utils/DebugifyTest.cpp b/llvm/unittests/Transforms/Utils/DebugifyTest.cpp index 89fa1334b427ea68a5e26e3529733f8f6a84e93a..0b00734fc4d752d8ca7ee464da76d5ba849fba4c 100644 --- a/llvm/unittests/Transforms/Utils/DebugifyTest.cpp +++ b/llvm/unittests/Transforms/Utils/DebugifyTest.cpp @@ -60,7 +60,7 @@ struct DebugValueDrop : public FunctionPass { for (Instruction &I : BB) { if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I)) Dbgs.push_back(DVI); - // If there are any non-intrinsic records (DPValues), drop those too. + // If there are any non-intrinsic records (DbgRecords), drop those too. I.dropDbgRecords(); } } diff --git a/llvm/unittests/Transforms/Utils/LocalTest.cpp b/llvm/unittests/Transforms/Utils/LocalTest.cpp index 87a2a2ae470051bb3aa5056d64514dcc71c29d81..a86775a1366b0538088e2df42fad124fa53c20bd 100644 --- a/llvm/unittests/Transforms/Utils/LocalTest.cpp +++ b/llvm/unittests/Transforms/Utils/LocalTest.cpp @@ -1279,11 +1279,11 @@ TEST(Local, ExpressionForConstant) { EXPECT_EQ(Expr, nullptr); } -TEST(Local, ReplaceDPValue) { +TEST(Local, ReplaceDbgVariableRecord) { LLVMContext C; - // Test that RAUW also replaces the operands of DPValue objects, i.e. - // non-instruction stored debugging information. + // Test that RAUW also replaces the operands of DbgVariableRecord objects, + // i.e. non-instruction stored debugging information. std::unique_ptr<Module> M = parseIR(C, R"( declare void @llvm.dbg.value(metadata, metadata, metadata) @@ -1323,24 +1323,23 @@ TEST(Local, ReplaceDPValue) { It = std::next(It); Instruction *RetInst = &*It; - // Convert DVI into a DPValue. - RetInst->DbgMarker = new DPMarker(); - RetInst->DbgMarker->MarkedInstr = RetInst; - DPValue *DPV = new DPValue(DVI); - RetInst->DbgMarker->insertDbgRecord(DPV, false); + // Convert DVI into a DbgVariableRecord. + RetInst->DebugMarker = new DbgMarker(); + RetInst->DebugMarker->MarkedInstr = RetInst; + DbgVariableRecord *DVR = new DbgVariableRecord(DVI); + RetInst->DebugMarker->insertDbgRecord(DVR, false); // ... and erase the dbg.value. DVI->eraseFromParent(); - // DPV should originally refer to %bar, - EXPECT_EQ(DPV->getVariableLocationOp(0), BarInst); + // DVR should originally refer to %bar, + EXPECT_EQ(DVR->getVariableLocationOp(0), BarInst); // Now try to replace the computation of %bar with %foo -- this should cause - // the DPValue's to have it's operand updated beneath it. + // the DbgVariableRecord's to have it's operand updated beneath it. BarInst->replaceAllUsesWith(FooInst); - // Check DPV now points at %foo. - EXPECT_EQ(DPV->getVariableLocationOp(0), FooInst); + // Check DVR now points at %foo. + EXPECT_EQ(DVR->getVariableLocationOp(0), FooInst); // Teardown. - RetInst->DbgMarker->eraseFromParent(); + RetInst->DebugMarker->eraseFromParent(); } - diff --git a/llvm/unittests/Transforms/Vectorize/VPlanHCFGTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanHCFGTest.cpp index be8be7acbe38812354478d582843f9e409ac4cae..777675b623f32a66147f207412b79deeb45ceb28 100644 --- a/llvm/unittests/Transforms/Vectorize/VPlanHCFGTest.cpp +++ b/llvm/unittests/Transforms/Vectorize/VPlanHCFGTest.cpp @@ -96,7 +96,7 @@ TEST_F(VPlanHCFGTest, testBuildHCFGInnerLoop) { #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) // Add an external value to check we do not print the list of external values, // as this is not required with the new printing. - Plan->getVPValueOrAddLiveIn(&*F->arg_begin()); + Plan->getOrAddLiveIn(&*F->arg_begin()); std::string FullDump; raw_string_ostream OS(FullDump); Plan->printDOT(OS); diff --git a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp index 33d5e2759af59098006e68c801fd8da86d17295e..02e7ca341fe22955af1ed9e1f4284919f17a2f71 100644 --- a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp +++ b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp @@ -1036,7 +1036,7 @@ TEST(VPRecipeTest, CastVPWidenMemoryInstructionRecipeToVPUserAndVPDef) { new LoadInst(Int32, UndefValue::get(Int32Ptr), "", false, Align(1)); VPValue Addr; VPValue Mask; - VPWidenMemoryInstructionRecipe Recipe(*Load, &Addr, &Mask, true, false); + VPWidenMemoryInstructionRecipe Recipe(*Load, &Addr, &Mask, true, false, {}); EXPECT_TRUE(isa<VPUser>(&Recipe)); VPRecipeBase *BaseR = &Recipe; EXPECT_TRUE(isa<VPUser>(BaseR)); @@ -1131,7 +1131,7 @@ TEST(VPRecipeTest, MayHaveSideEffectsAndMayReadWriteMemory) { new LoadInst(Int32, UndefValue::get(Int32Ptr), "", false, Align(1)); VPValue Addr; VPValue Mask; - VPWidenMemoryInstructionRecipe Recipe(*Load, &Addr, &Mask, true, false); + VPWidenMemoryInstructionRecipe Recipe(*Load, &Addr, &Mask, true, false, {}); EXPECT_FALSE(Recipe.mayHaveSideEffects()); EXPECT_TRUE(Recipe.mayReadFromMemory()); EXPECT_FALSE(Recipe.mayWriteToMemory()); @@ -1146,7 +1146,7 @@ TEST(VPRecipeTest, MayHaveSideEffectsAndMayReadWriteMemory) { VPValue Mask; VPValue StoredV; VPWidenMemoryInstructionRecipe Recipe(*Store, &Addr, &StoredV, &Mask, false, - false); + false, {}); EXPECT_TRUE(Recipe.mayHaveSideEffects()); EXPECT_FALSE(Recipe.mayReadFromMemory()); EXPECT_TRUE(Recipe.mayWriteToMemory()); @@ -1237,8 +1237,8 @@ TEST(VPRecipeTest, dump) { BinaryOperator::CreateAdd(UndefValue::get(Int32), UndefValue::get(Int32)); AI->setName("a"); SmallVector<VPValue *, 2> Args; - VPValue *ExtVPV1 = Plan.getVPValueOrAddLiveIn(ConstantInt::get(Int32, 1)); - VPValue *ExtVPV2 = Plan.getVPValueOrAddLiveIn(ConstantInt::get(Int32, 2)); + VPValue *ExtVPV1 = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 1)); + VPValue *ExtVPV2 = Plan.getOrAddLiveIn(ConstantInt::get(Int32, 2)); Args.push_back(ExtVPV1); Args.push_back(ExtVPV2); VPWidenRecipe *WidenR = diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp index febd96086df27b1911c8028ee7c85082f7972007..8b82ce899a48ad14bf4831d5398194df51900245 100644 --- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp +++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp @@ -95,12 +95,12 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenInstAlias.h" -#include "CodeGenInstruction.h" -#include "CodeGenRegisters.h" -#include "CodeGenTarget.h" -#include "SubtargetFeatureInfo.h" -#include "Types.h" +#include "Common/CodeGenInstAlias.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenRegisters.h" +#include "Common/CodeGenTarget.h" +#include "Common/SubtargetFeatureInfo.h" +#include "Common/Types.h" #include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" @@ -375,6 +375,10 @@ public: int AsmVariantNo; }; +bool getPreferSmallerInstructions(CodeGenTarget const &Target) { + return Target.getAsmParser()->getValueAsBit("PreferSmallerInstructions"); +} + /// MatchableInfo - Helper class for storing the necessary information for an /// instruction or alias which is capable of being matched. struct MatchableInfo { @@ -502,6 +506,9 @@ struct MatchableInfo { /// matchable came from. Record *const TheDef; + // ResInstSize - The size of the resulting instruction for this matchable. + unsigned ResInstSize; + /// DefRec - This is the definition that it came from. PointerUnion<const CodeGenInstruction *, const CodeGenInstAlias *> DefRec; @@ -543,10 +550,12 @@ struct MatchableInfo { MatchableInfo(const CodeGenInstruction &CGI) : AsmVariantID(0), AsmString(CGI.AsmString), TheDef(CGI.TheDef), - DefRec(&CGI), UseInstAsmMatchConverter(true) {} + ResInstSize(TheDef->getValueAsInt("Size")), DefRec(&CGI), + UseInstAsmMatchConverter(true) {} MatchableInfo(std::unique_ptr<const CodeGenInstAlias> Alias) : AsmVariantID(0), AsmString(Alias->AsmString), TheDef(Alias->TheDef), + ResInstSize(Alias->ResultInst->TheDef->getValueAsInt("Size")), DefRec(Alias.release()), UseInstAsmMatchConverter(TheDef->getValueAsBit( "UseInstAsmMatchConverter")) {} @@ -555,9 +564,9 @@ struct MatchableInfo { // where it was copied while being in an owning state. MatchableInfo(const MatchableInfo &RHS) : AsmVariantID(RHS.AsmVariantID), AsmString(RHS.AsmString), - TheDef(RHS.TheDef), DefRec(RHS.DefRec), ResOperands(RHS.ResOperands), - Mnemonic(RHS.Mnemonic), AsmOperands(RHS.AsmOperands), - RequiredFeatures(RHS.RequiredFeatures), + TheDef(RHS.TheDef), ResInstSize(RHS.ResInstSize), DefRec(RHS.DefRec), + ResOperands(RHS.ResOperands), Mnemonic(RHS.Mnemonic), + AsmOperands(RHS.AsmOperands), RequiredFeatures(RHS.RequiredFeatures), ConversionFnKind(RHS.ConversionFnKind), HasDeprecation(RHS.HasDeprecation), UseInstAsmMatchConverter(RHS.UseInstAsmMatchConverter) { @@ -608,12 +617,18 @@ struct MatchableInfo { void buildInstructionResultOperands(); void buildAliasResultOperands(bool AliasConstraintsAreChecked); - /// operator< - Compare two matchables. - bool operator<(const MatchableInfo &RHS) const { + /// shouldBeMatchedBefore - Compare two matchables for ordering. + bool shouldBeMatchedBefore(const MatchableInfo &RHS, + bool PreferSmallerInstructions) const { // The primary comparator is the instruction mnemonic. if (int Cmp = Mnemonic.compare_insensitive(RHS.Mnemonic)) return Cmp == -1; + // (Optionally) Order by the resultant instuctions size. + // eg. for ARM thumb instructions smaller encodings should be preferred. + if (PreferSmallerInstructions && ResInstSize != RHS.ResInstSize) + return ResInstSize < RHS.ResInstSize; + if (AsmOperands.size() != RHS.AsmOperands.size()) return AsmOperands.size() < RHS.AsmOperands.size(); @@ -652,7 +667,8 @@ struct MatchableInfo { /// couldMatchAmbiguouslyWith - Check whether this matchable could /// ambiguously match the same set of operands as \p RHS (without being a /// strictly superior match). - bool couldMatchAmbiguouslyWith(const MatchableInfo &RHS) const { + bool couldMatchAmbiguouslyWith(const MatchableInfo &RHS, + bool PreferSmallerInstructions) const { // The primary comparator is the instruction mnemonic. if (Mnemonic != RHS.Mnemonic) return false; @@ -661,6 +677,10 @@ struct MatchableInfo { if (AsmVariantID != RHS.AsmVariantID) return false; + // The size of instruction is unambiguous. + if (PreferSmallerInstructions && ResInstSize != RHS.ResInstSize) + return false; + // The number of operands is unambiguous. if (AsmOperands.size() != RHS.AsmOperands.size()) return false; @@ -1986,16 +2006,16 @@ emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, } CvtOS << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n"; CvtOS << " const uint8_t *Converter = ConversionTable[Kind];\n"; - CvtOS << " unsigned OpIdx;\n"; CvtOS << " Inst.setOpcode(Opcode);\n"; CvtOS << " for (const uint8_t *p = Converter; *p; p += 2) {\n"; if (HasOptionalOperands) { // When optional operands are involved, formal and actual operand indices // may differ. Map the former to the latter by subtracting the number of // absent optional operands. - CvtOS << " OpIdx = *(p + 1) - DefaultsOffset[*(p + 1)];\n"; + // FIXME: This is not an operand index in the CVT_Tied case + CvtOS << " unsigned OpIdx = *(p + 1) - DefaultsOffset[*(p + 1)];\n"; } else { - CvtOS << " OpIdx = *(p + 1);\n"; + CvtOS << " unsigned OpIdx = *(p + 1);\n"; } CvtOS << " switch (*p) {\n"; CvtOS << " default: llvm_unreachable(\"invalid conversion entry!\");\n"; @@ -2004,11 +2024,11 @@ emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, << " &>(*Operands[OpIdx]).addRegOperands(Inst, 1);\n"; CvtOS << " break;\n"; CvtOS << " case CVT_Tied: {\n"; - CvtOS << " assert(OpIdx < (size_t)(std::end(TiedAsmOperandTable) -\n"; + CvtOS << " assert(*(p + 1) < (size_t)(std::end(TiedAsmOperandTable) -\n"; CvtOS << " std::begin(TiedAsmOperandTable)) &&\n"; CvtOS << " \"Tied operand not found\");\n"; - CvtOS << " unsigned TiedResOpnd = TiedAsmOperandTable[OpIdx][0];\n"; + CvtOS << " unsigned TiedResOpnd = TiedAsmOperandTable[*(p + 1)][0];\n"; CvtOS << " if (TiedResOpnd != (uint8_t)-1)\n"; CvtOS << " Inst.addOperand(Inst.getOperand(TiedResOpnd));\n"; CvtOS << " break;\n"; @@ -2499,7 +2519,7 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info, raw_ostream &OS) { // Check for register operands, including sub-classes. OS << " if (Operand.isReg()) {\n"; OS << " MatchClassKind OpKind;\n"; - OS << " switch (Operand.getReg()) {\n"; + OS << " switch (Operand.getReg().id()) {\n"; OS << " default: OpKind = InvalidMatchClass; break;\n"; for (const auto &RC : Info.RegisterClasses) OS << " case " << RC.first->getValueAsString("Namespace") @@ -3221,20 +3241,23 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { AsmMatcherInfo Info(AsmParser, Target, Records); Info.buildInfo(); + bool PreferSmallerInstructions = getPreferSmallerInstructions(Target); // Sort the instruction table using the partial order on classes. We use // stable_sort to ensure that ambiguous instructions are still // deterministically ordered. llvm::stable_sort( Info.Matchables, - [](const std::unique_ptr<MatchableInfo> &a, - const std::unique_ptr<MatchableInfo> &b) { return *a < *b; }); + [PreferSmallerInstructions](const std::unique_ptr<MatchableInfo> &A, + const std::unique_ptr<MatchableInfo> &B) { + return A->shouldBeMatchedBefore(*B, PreferSmallerInstructions); + }); #ifdef EXPENSIVE_CHECKS // Verify that the table is sorted and operator < works transitively. for (auto I = Info.Matchables.begin(), E = Info.Matchables.end(); I != E; ++I) { for (auto J = I; J != E; ++J) { - assert(!(**J < **I)); + assert(!(*J)->shouldBeMatchedBefore(**I, PreferSmallerInstructions)); } } #endif @@ -3253,7 +3276,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { const MatchableInfo &A = **I; const MatchableInfo &B = **J; - if (A.couldMatchAmbiguouslyWith(B)) { + if (A.couldMatchAmbiguouslyWith(B, PreferSmallerInstructions)) { errs() << "warning: ambiguous matchables:\n"; A.dump(); errs() << "\nis incomparable with:\n"; @@ -3729,6 +3752,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " } else {\n"; OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"but formal " "operand not required\\n\");\n"; + OS << " if (isSubclass(Formal, OptionalMatchClass)) {\n"; + OS << " OptionalOperandsMask.set(FormalIdx);\n"; + OS << " }\n"; OS << " }\n"; OS << " continue;\n"; } else { diff --git a/llvm/utils/TableGen/AsmWriterEmitter.cpp b/llvm/utils/TableGen/AsmWriterEmitter.cpp index a27061ee585a5963cf46ad358b52ef295f326e5e..16661cd29edc556164fa3073bc9e28e07eaa310f 100644 --- a/llvm/utils/TableGen/AsmWriterEmitter.cpp +++ b/llvm/utils/TableGen/AsmWriterEmitter.cpp @@ -11,13 +11,13 @@ // //===----------------------------------------------------------------------===// -#include "AsmWriterInst.h" -#include "CodeGenInstAlias.h" -#include "CodeGenInstruction.h" -#include "CodeGenRegisters.h" -#include "CodeGenTarget.h" -#include "SequenceToOffsetTable.h" -#include "Types.h" +#include "Basic/SequenceToOffsetTable.h" +#include "Common/AsmWriterInst.h" +#include "Common/CodeGenInstAlias.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenRegisters.h" +#include "Common/CodeGenTarget.h" +#include "Common/Types.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" diff --git a/llvm/utils/TableGen/Basic/CMakeLists.txt b/llvm/utils/TableGen/Basic/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5a899e3b7c8035bd1a77d4bf236a74f54f4ded94 --- /dev/null +++ b/llvm/utils/TableGen/Basic/CMakeLists.txt @@ -0,0 +1,21 @@ +# The basic TableGen library contains as little dependencies as possible. +# In particular, it does not depend on vt_gen -> it does not use ValueTypes. +# +# This library is the only thing included in `llvm-min-tablegen`. + +set(LLVM_LINK_COMPONENTS + Support + TableGen + ) + +add_llvm_library(LLVMTableGenBasic OBJECT EXCLUDE_FROM_ALL + CodeGenIntrinsics.cpp + SDNodeProperties.cpp +) +set_target_properties(LLVMTableGenBasic PROPERTIES FOLDER "Tablegenning") + +# Users may include its headers as "Basic/*.h" +target_include_directories(LLVMTableGenBasic + INTERFACE + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..> + ) diff --git a/llvm/utils/TableGen/CodeGenIntrinsics.cpp b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp similarity index 100% rename from llvm/utils/TableGen/CodeGenIntrinsics.cpp rename to llvm/utils/TableGen/Basic/CodeGenIntrinsics.cpp diff --git a/llvm/utils/TableGen/CodeGenIntrinsics.h b/llvm/utils/TableGen/Basic/CodeGenIntrinsics.h similarity index 100% rename from llvm/utils/TableGen/CodeGenIntrinsics.h rename to llvm/utils/TableGen/Basic/CodeGenIntrinsics.h diff --git a/llvm/utils/TableGen/SDNodeProperties.cpp b/llvm/utils/TableGen/Basic/SDNodeProperties.cpp similarity index 100% rename from llvm/utils/TableGen/SDNodeProperties.cpp rename to llvm/utils/TableGen/Basic/SDNodeProperties.cpp diff --git a/llvm/utils/TableGen/SDNodeProperties.h b/llvm/utils/TableGen/Basic/SDNodeProperties.h similarity index 100% rename from llvm/utils/TableGen/SDNodeProperties.h rename to llvm/utils/TableGen/Basic/SDNodeProperties.h diff --git a/llvm/utils/TableGen/SequenceToOffsetTable.h b/llvm/utils/TableGen/Basic/SequenceToOffsetTable.h similarity index 100% rename from llvm/utils/TableGen/SequenceToOffsetTable.h rename to llvm/utils/TableGen/Basic/SequenceToOffsetTable.h diff --git a/llvm/utils/TableGen/CMakeLists.txt b/llvm/utils/TableGen/CMakeLists.txt index 0100bf345ec29e1df9447f4029e1aa7fbcb54ea4..577aeded4be72c37ab76048457d24281eb77f7f3 100644 --- a/llvm/utils/TableGen/CMakeLists.txt +++ b/llvm/utils/TableGen/CMakeLists.txt @@ -1,26 +1,25 @@ -add_subdirectory(GlobalISel) +# Basic utilities which is the strict minimum needed to build +# llvm-min-tblgen. +add_subdirectory(Basic) +# Common utilities are all of the reusable components and helper +# code needed by the backends. +add_subdirectory(Common) -add_llvm_library(LLVMTableGenCommon STATIC OBJECT EXCLUDE_FROM_ALL +set(LLVM_LINK_COMPONENTS Support) + +# llvm-min-tablegen only contains a subset of backends necessary to +# build llvm/include. It must not depend on TableGenCommon, as +# TableGenCommon depends on this already to generate things such as +# ValueType definitions. +add_tablegen(llvm-min-tblgen LLVM_HEADERS + TableGen.cpp Attributes.cpp - CodeGenIntrinsics.cpp DirectiveEmitter.cpp IntrinsicEmitter.cpp RISCVTargetDefEmitter.cpp - SDNodeProperties.cpp VTEmitter.cpp - PARTIAL_SOURCES_INTENDED - - LINK_COMPONENTS - Support - TableGen - ) -set_target_properties(LLVMTableGenCommon PROPERTIES FOLDER "Tablegenning") + $<TARGET_OBJECTS:obj.LLVMTableGenBasic> -set(LLVM_LINK_COMPONENTS Support) - -add_tablegen(llvm-min-tblgen LLVM_HEADERS - TableGen.cpp - $<TARGET_OBJECTS:obj.LLVMTableGenCommon> PARTIAL_SOURCES_INTENDED ) set_target_properties(llvm-min-tblgen PROPERTIES FOLDER "Tablegenning") @@ -35,63 +34,51 @@ add_tablegen(llvm-tblgen LLVM EXPORT LLVM AsmMatcherEmitter.cpp AsmWriterEmitter.cpp - AsmWriterInst.cpp - CTagsEmitter.cpp + Attributes.cpp CallingConvEmitter.cpp CodeEmitterGen.cpp - CodeGenDAGPatterns.cpp - CodeGenHwModes.cpp - CodeGenInstAlias.cpp - CodeGenInstruction.cpp CodeGenMapTable.cpp - CodeGenRegisters.cpp - CodeGenSchedule.cpp - CodeGenTarget.cpp + CompressInstEmitter.cpp + CTagsEmitter.cpp DAGISelEmitter.cpp DAGISelMatcherEmitter.cpp DAGISelMatcherGen.cpp DAGISelMatcherOpt.cpp - DAGISelMatcher.cpp DecoderEmitter.cpp DFAEmitter.cpp DFAPacketizerEmitter.cpp + DirectiveEmitter.cpp DisassemblerEmitter.cpp DXILEmitter.cpp ExegesisEmitter.cpp FastISelEmitter.cpp GlobalISelCombinerEmitter.cpp GlobalISelEmitter.cpp - GlobalISelMatchTable.cpp - GlobalISelMatchTableExecutorEmitter.cpp - InfoByHwMode.cpp - InstrInfoEmitter.cpp InstrDocsEmitter.cpp - OptEmitter.cpp + InstrInfoEmitter.cpp + IntrinsicEmitter.cpp + MacroFusionPredicatorEmitter.cpp OptParserEmitter.cpp OptRSTEmitter.cpp - PredicateExpander.cpp PseudoLoweringEmitter.cpp - CompressInstEmitter.cpp - MacroFusionPredicatorEmitter.cpp RegisterBankEmitter.cpp RegisterInfoEmitter.cpp + RISCVTargetDefEmitter.cpp SearchableTableEmitter.cpp SubtargetEmitter.cpp - SubtargetFeatureInfo.cpp TableGen.cpp - Types.cpp - VarLenCodeEmitterGen.cpp - X86DisassemblerTables.cpp + VTEmitter.cpp + WebAssemblyDisassemblerEmitter.cpp X86CompressEVEXTablesEmitter.cpp + X86DisassemblerTables.cpp X86FoldTablesEmitter.cpp X86MnemonicTables.cpp X86ModRMFilters.cpp X86RecognizableInstr.cpp - WebAssemblyDisassemblerEmitter.cpp + $<TARGET_OBJECTS:obj.LLVMTableGenBasic> $<TARGET_OBJECTS:obj.LLVMTableGenCommon> DEPENDS intrinsics_gen # via llvm-min-tablegen ) -target_link_libraries(llvm-tblgen PRIVATE LLVMTableGenGlobalISel) set_target_properties(llvm-tblgen PROPERTIES FOLDER "Tablegenning") diff --git a/llvm/utils/TableGen/CallingConvEmitter.cpp b/llvm/utils/TableGen/CallingConvEmitter.cpp index 3c3a2874ce80155fdddfcff735eb7a229fc0d2d1..ec6ef56a66fa0fc1d26564d7e21d8ea5f8e67fbd 100644 --- a/llvm/utils/TableGen/CallingConvEmitter.cpp +++ b/llvm/utils/TableGen/CallingConvEmitter.cpp @@ -11,7 +11,7 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenTarget.h" +#include "Common/CodeGenTarget.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" diff --git a/llvm/utils/TableGen/CodeEmitterGen.cpp b/llvm/utils/TableGen/CodeEmitterGen.cpp index 9194c13ccdcb086214173a06a7fa75342e1420f8..a57885f22d7e3ec522904428df9a9571156b5ca9 100644 --- a/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -22,11 +22,11 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenHwModes.h" -#include "CodeGenInstruction.h" -#include "CodeGenTarget.h" -#include "InfoByHwMode.h" -#include "VarLenCodeEmitterGen.h" +#include "Common/CodeGenHwModes.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenTarget.h" +#include "Common/InfoByHwMode.h" +#include "Common/VarLenCodeEmitterGen.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringExtras.h" diff --git a/llvm/utils/TableGen/CodeGenMapTable.cpp b/llvm/utils/TableGen/CodeGenMapTable.cpp index 03af0b49ba979c198c4194d30cedf210700cc25f..fbf1d47c0327d9057938d42868ea156ec542ac96 100644 --- a/llvm/utils/TableGen/CodeGenMapTable.cpp +++ b/llvm/utils/TableGen/CodeGenMapTable.cpp @@ -75,8 +75,8 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenInstruction.h" -#include "CodeGenTarget.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenTarget.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" using namespace llvm; diff --git a/llvm/utils/TableGen/AsmWriterInst.cpp b/llvm/utils/TableGen/Common/AsmWriterInst.cpp similarity index 100% rename from llvm/utils/TableGen/AsmWriterInst.cpp rename to llvm/utils/TableGen/Common/AsmWriterInst.cpp diff --git a/llvm/utils/TableGen/AsmWriterInst.h b/llvm/utils/TableGen/Common/AsmWriterInst.h similarity index 100% rename from llvm/utils/TableGen/AsmWriterInst.h rename to llvm/utils/TableGen/Common/AsmWriterInst.h diff --git a/llvm/utils/TableGen/Common/CMakeLists.txt b/llvm/utils/TableGen/Common/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c31ed5a1de690c7d693044880d1846e072690b0f --- /dev/null +++ b/llvm/utils/TableGen/Common/CMakeLists.txt @@ -0,0 +1,51 @@ +# The common library is similar to the basic library except it can +# depend on vt_gen. +# +# This library contains the bulk of the supporting code for all +# TableGen backends. It's split off as a separate library to +# allow unit-testing those components. + +set(LLVM_LINK_COMPONENTS + Support + TableGen + ) + +add_llvm_library(LLVMTableGenCommon STATIC OBJECT EXCLUDE_FROM_ALL + GlobalISel/CodeExpander.cpp + GlobalISel/CombinerUtils.cpp + GlobalISel/CXXPredicates.cpp + GlobalISel/GlobalISelMatchTable.cpp + GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp + GlobalISel/MatchDataInfo.cpp + GlobalISel/PatternParser.cpp + GlobalISel/Patterns.cpp + + AsmWriterInst.cpp + CodeGenDAGPatterns.cpp + CodeGenHwModes.cpp + CodeGenInstAlias.cpp + CodeGenInstruction.cpp + CodeGenRegisters.cpp + CodeGenSchedule.cpp + CodeGenTarget.cpp + DAGISelMatcher.cpp + InfoByHwMode.cpp + OptEmitter.cpp + PredicateExpander.cpp + SubtargetFeatureInfo.cpp + Types.cpp + VarLenCodeEmitterGen.cpp + + LINK_LIBS + LLVMTableGenBasic + + DEPENDS + vt_gen + ) +set_target_properties(LLVMTableGenCommon PROPERTIES FOLDER "Tablegenning") + +# Users may include its headers as "Common/*.h" +target_include_directories(LLVMTableGenCommon + PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..> + ) diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp similarity index 100% rename from llvm/utils/TableGen/CodeGenDAGPatterns.cpp rename to llvm/utils/TableGen/Common/CodeGenDAGPatterns.cpp diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.h b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h similarity index 99% rename from llvm/utils/TableGen/CodeGenDAGPatterns.h rename to llvm/utils/TableGen/Common/CodeGenDAGPatterns.h index 823c40c922cbe5b0642b5d44086fa7ebb6f69b04..7fcd39a9e940cc8769d93b46a0155ae70dedb9d3 100644 --- a/llvm/utils/TableGen/CodeGenDAGPatterns.h +++ b/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h @@ -14,9 +14,9 @@ #ifndef LLVM_UTILS_TABLEGEN_CODEGENDAGPATTERNS_H #define LLVM_UTILS_TABLEGEN_CODEGENDAGPATTERNS_H -#include "CodeGenIntrinsics.h" +#include "Basic/CodeGenIntrinsics.h" +#include "Basic/SDNodeProperties.h" #include "CodeGenTarget.h" -#include "SDNodeProperties.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/PointerUnion.h" diff --git a/llvm/utils/TableGen/CodeGenHwModes.cpp b/llvm/utils/TableGen/Common/CodeGenHwModes.cpp similarity index 100% rename from llvm/utils/TableGen/CodeGenHwModes.cpp rename to llvm/utils/TableGen/Common/CodeGenHwModes.cpp diff --git a/llvm/utils/TableGen/CodeGenHwModes.h b/llvm/utils/TableGen/Common/CodeGenHwModes.h similarity index 100% rename from llvm/utils/TableGen/CodeGenHwModes.h rename to llvm/utils/TableGen/Common/CodeGenHwModes.h diff --git a/llvm/utils/TableGen/CodeGenInstAlias.cpp b/llvm/utils/TableGen/Common/CodeGenInstAlias.cpp similarity index 100% rename from llvm/utils/TableGen/CodeGenInstAlias.cpp rename to llvm/utils/TableGen/Common/CodeGenInstAlias.cpp diff --git a/llvm/utils/TableGen/CodeGenInstAlias.h b/llvm/utils/TableGen/Common/CodeGenInstAlias.h similarity index 100% rename from llvm/utils/TableGen/CodeGenInstAlias.h rename to llvm/utils/TableGen/Common/CodeGenInstAlias.h diff --git a/llvm/utils/TableGen/CodeGenInstruction.cpp b/llvm/utils/TableGen/Common/CodeGenInstruction.cpp similarity index 99% rename from llvm/utils/TableGen/CodeGenInstruction.cpp rename to llvm/utils/TableGen/Common/CodeGenInstruction.cpp index b00b95da5fc276eecbc6c3a2a25191966a53f6b5..18a4e7b0f18b23039b28506a485e91368c8f461c 100644 --- a/llvm/utils/TableGen/CodeGenInstruction.cpp +++ b/llvm/utils/TableGen/Common/CodeGenInstruction.cpp @@ -325,7 +325,9 @@ static void ParseConstraint(StringRef CStr, CGIOperandList &Ops, Record *Rec) { // Only other constraint is "TIED_TO" for now. StringRef::size_type pos = CStr.find_first_of('='); - if (pos == StringRef::npos) + if (pos == StringRef::npos || pos == 0 || + CStr.find_first_of(" \t", pos) != (pos + 1) || + CStr.find_last_of(" \t", pos) != (pos - 1)) PrintFatalError(Rec->getLoc(), "Unrecognized constraint '" + CStr + "' in '" + Rec->getName() + "'"); start = CStr.find_first_not_of(" \t"); diff --git a/llvm/utils/TableGen/CodeGenInstruction.h b/llvm/utils/TableGen/Common/CodeGenInstruction.h similarity index 100% rename from llvm/utils/TableGen/CodeGenInstruction.h rename to llvm/utils/TableGen/Common/CodeGenInstruction.h diff --git a/llvm/utils/TableGen/CodeGenRegisters.cpp b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp similarity index 97% rename from llvm/utils/TableGen/CodeGenRegisters.cpp rename to llvm/utils/TableGen/Common/CodeGenRegisters.cpp index 40af0d3077b2dec2345ad678b17e40be5bfd739f..624e8d5d54ba8f1da73d3687da9ab32fde6940cc 100644 --- a/llvm/utils/TableGen/CodeGenRegisters.cpp +++ b/llvm/utils/TableGen/Common/CodeGenRegisters.cpp @@ -47,19 +47,24 @@ using namespace llvm; // CodeGenSubRegIndex //===----------------------------------------------------------------------===// -CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum) +CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum, + const CodeGenHwModes &CGH) : TheDef(R), EnumValue(Enum), AllSuperRegsCovered(true), Artificial(true) { Name = std::string(R->getName()); if (R->getValue("Namespace")) Namespace = std::string(R->getValueAsString("Namespace")); - Size = R->getValueAsInt("Size"); - Offset = R->getValueAsInt("Offset"); + + if (const RecordVal *RV = R->getValue("SubRegRanges")) + if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) + Range = SubRegRangeByHwMode(DI->getDef(), CGH); + if (!Range.hasDefault()) + Range.insertSubRegRangeForMode(DefaultMode, SubRegRange(R)); } CodeGenSubRegIndex::CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum) : TheDef(nullptr), Name(std::string(N)), Namespace(std::string(Nspace)), - Size(-1), Offset(-1), EnumValue(Enum), AllSuperRegsCovered(true), + Range(SubRegRange(-1, -1)), EnumValue(Enum), AllSuperRegsCovered(true), Artificial(true) {} std::string CodeGenSubRegIndex::getQualifiedName() const { @@ -81,7 +86,7 @@ void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) { "ComposedOf must have exactly two entries"); CodeGenSubRegIndex *A = RegBank.getSubRegIdx(Comps[0]); CodeGenSubRegIndex *B = RegBank.getSubRegIdx(Comps[1]); - CodeGenSubRegIndex *X = A->addComposite(B, this); + CodeGenSubRegIndex *X = A->addComposite(B, this, RegBank.getHwModes()); if (X) PrintFatalError(TheDef->getLoc(), "Ambiguous ComposedOf entries"); } @@ -518,7 +523,8 @@ void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) { // Each part of Cand is a sub-register of this. Make the full Cand also // a sub-register with a concatenated sub-register index. - CodeGenSubRegIndex *Concat = RegBank.getConcatSubRegIndex(Parts); + CodeGenSubRegIndex *Concat = + RegBank.getConcatSubRegIndex(Parts, RegBank.getHwModes()); std::pair<CodeGenSubRegIndex *, CodeGenRegister *> NewSubReg = std::pair(Concat, Cand); @@ -542,7 +548,7 @@ void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) { PrintFatalError(TheDef->getLoc(), "No SubRegIndex for " + SubReg.second->getName() + " in " + getName()); - NewIdx->addComposite(SubReg.first, SubIdx); + NewIdx->addComposite(SubReg.first, SubIdx, RegBank.getHwModes()); } } } @@ -1315,7 +1321,7 @@ CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(Record *Def) { CodeGenSubRegIndex *&Idx = Def2SubRegIdx[Def]; if (Idx) return Idx; - SubRegIndices.emplace_back(Def, SubRegIndices.size() + 1); + SubRegIndices.emplace_back(Def, SubRegIndices.size() + 1, getHwModes()); Idx = &SubRegIndices.back(); return Idx; } @@ -1379,12 +1385,13 @@ CodeGenRegBank::getCompositeSubRegIndex(CodeGenSubRegIndex *A, // None exists, synthesize one. std::string Name = A->getName() + "_then_" + B->getName(); Comp = createSubRegIndex(Name, A->getNamespace()); - A->addComposite(B, Comp); + A->addComposite(B, Comp, getHwModes()); return Comp; } CodeGenSubRegIndex *CodeGenRegBank::getConcatSubRegIndex( - const SmallVector<CodeGenSubRegIndex *, 8> &Parts) { + const SmallVector<CodeGenSubRegIndex *, 8> &Parts, + const CodeGenHwModes &CGH) { assert(Parts.size() > 1 && "Need two parts to concatenate"); #ifndef NDEBUG for (CodeGenSubRegIndex *Idx : Parts) { @@ -1399,28 +1406,47 @@ CodeGenSubRegIndex *CodeGenRegBank::getConcatSubRegIndex( // None exists, synthesize one. std::string Name = Parts.front()->getName(); - // Determine whether all parts are contiguous. - bool isContinuous = true; - unsigned Size = Parts.front()->Size; - unsigned LastOffset = Parts.front()->Offset; - unsigned LastSize = Parts.front()->Size; - unsigned UnknownSize = (uint16_t)-1; + const unsigned UnknownSize = (uint16_t)-1; + for (unsigned i = 1, e = Parts.size(); i != e; ++i) { Name += '_'; Name += Parts[i]->getName(); - if (Size == UnknownSize || Parts[i]->Size == UnknownSize) - Size = UnknownSize; - else - Size += Parts[i]->Size; - if (LastSize == UnknownSize || Parts[i]->Offset != (LastOffset + LastSize)) - isContinuous = false; - LastOffset = Parts[i]->Offset; - LastSize = Parts[i]->Size; } + Idx = createSubRegIndex(Name, Parts.front()->getNamespace()); - Idx->Size = Size; - Idx->Offset = isContinuous ? Parts.front()->Offset : -1; Idx->ConcatenationOf.assign(Parts.begin(), Parts.end()); + + unsigned NumModes = CGH.getNumModeIds(); + for (unsigned M = 0; M < NumModes; ++M) { + const CodeGenSubRegIndex *Part = Parts.front(); + + // Determine whether all parts are contiguous. + bool IsContinuous = true; + const SubRegRange &FirstPartRange = Part->Range.get(M); + unsigned Size = FirstPartRange.Size; + unsigned LastOffset = FirstPartRange.Offset; + unsigned LastSize = FirstPartRange.Size; + + for (unsigned i = 1, e = Parts.size(); i != e; ++i) { + Part = Parts[i]; + Name += '_'; + Name += Part->getName(); + + const SubRegRange &PartRange = Part->Range.get(M); + if (Size == UnknownSize || PartRange.Size == UnknownSize) + Size = UnknownSize; + else + Size += PartRange.Size; + if (LastSize == UnknownSize || + PartRange.Offset != (LastOffset + LastSize)) + IsContinuous = false; + LastOffset = PartRange.Offset; + LastSize = PartRange.Size; + } + unsigned Offset = IsContinuous ? FirstPartRange.Offset : -1; + Idx->Range.get(M) = SubRegRange(Size, Offset); + } + return Idx; } @@ -1504,7 +1530,8 @@ void CodeGenRegBank::computeComposites() { assert(Idx3 && "Sub-register doesn't have an index"); // Conflicting composition? Emit a warning but allow it. - if (CodeGenSubRegIndex *Prev = Idx1->addComposite(Idx2, Idx3)) { + if (CodeGenSubRegIndex *Prev = + Idx1->addComposite(Idx2, Idx3, getHwModes())) { // If the composition was not user-defined, always emit a warning. if (!UserDefined.count({Idx1, Idx2}) || agree(compose(Idx1, Idx2), SubRegAction.at(Idx3))) diff --git a/llvm/utils/TableGen/CodeGenRegisters.h b/llvm/utils/TableGen/Common/CodeGenRegisters.h similarity index 96% rename from llvm/utils/TableGen/CodeGenRegisters.h rename to llvm/utils/TableGen/Common/CodeGenRegisters.h index c34f376ea99db3d2810bba72836b2dad45e7ef6b..9058baea2b23e98afd69bca5cd13956988836649 100644 --- a/llvm/utils/TableGen/CodeGenRegisters.h +++ b/llvm/utils/TableGen/Common/CodeGenRegisters.h @@ -68,8 +68,7 @@ class CodeGenSubRegIndex { std::string Namespace; public: - uint16_t Size; - uint16_t Offset; + SubRegRangeByHwMode Range; const unsigned EnumValue; mutable LaneBitmask LaneMask; mutable SmallVector<MaskRolPair, 1> CompositionLaneMaskTransform; @@ -86,7 +85,7 @@ public: // indexes are not used to create new register classes. bool Artificial; - CodeGenSubRegIndex(Record *R, unsigned Enum); + CodeGenSubRegIndex(Record *R, unsigned Enum, const CodeGenHwModes &CGH); CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum); CodeGenSubRegIndex(CodeGenSubRegIndex &) = delete; @@ -108,19 +107,42 @@ public: // Add a composite subreg index: this+A = B. // Return a conflicting composite, or NULL - CodeGenSubRegIndex *addComposite(CodeGenSubRegIndex *A, - CodeGenSubRegIndex *B) { + CodeGenSubRegIndex *addComposite(CodeGenSubRegIndex *A, CodeGenSubRegIndex *B, + const CodeGenHwModes &CGH) { assert(A && B); std::pair<CompMap::iterator, bool> Ins = Composed.insert(std::pair(A, B)); + // Synthetic subreg indices that aren't contiguous (for instance ARM // register tuples) don't have a bit range, so it's OK to let // B->Offset == -1. For the other cases, accumulate the offset and set // the size here. Only do so if there is no offset yet though. - if ((Offset != (uint16_t)-1 && A->Offset != (uint16_t)-1) && - (B->Offset == (uint16_t)-1)) { - B->Offset = Offset + A->Offset; - B->Size = A->Size; + unsigned NumModes = CGH.getNumModeIds(); + // Skip default mode. + for (unsigned M = 0; M < NumModes; ++M) { + // Handle DefaultMode last. + if (M == DefaultMode) + continue; + SubRegRange &Range = this->Range.get(M); + SubRegRange &ARange = A->Range.get(M); + SubRegRange &BRange = B->Range.get(M); + + if (Range.Offset != (uint16_t)-1 && ARange.Offset != (uint16_t)-1 && + BRange.Offset == (uint16_t)-1) { + BRange.Offset = Range.Offset + ARange.Offset; + BRange.Size = ARange.Size; + } + } + + // Now handle default. + SubRegRange &Range = this->Range.get(DefaultMode); + SubRegRange &ARange = A->Range.get(DefaultMode); + SubRegRange &BRange = B->Range.get(DefaultMode); + if (Range.Offset != (uint16_t)-1 && ARange.Offset != (uint16_t)-1 && + BRange.Offset == (uint16_t)-1) { + BRange.Offset = Range.Offset + ARange.Offset; + BRange.Size = ARange.Size; } + return (Ins.second || Ins.first->second == B) ? nullptr : Ins.first->second; } @@ -681,7 +703,8 @@ public: // Find or create a sub-register index representing the concatenation of // non-overlapping sibling indices. CodeGenSubRegIndex * - getConcatSubRegIndex(const SmallVector<CodeGenSubRegIndex *, 8> &); + getConcatSubRegIndex(const SmallVector<CodeGenSubRegIndex *, 8> &, + const CodeGenHwModes &CGH); const std::deque<CodeGenRegister> &getRegisters() const { return Registers; } diff --git a/llvm/utils/TableGen/CodeGenSchedule.cpp b/llvm/utils/TableGen/Common/CodeGenSchedule.cpp similarity index 100% rename from llvm/utils/TableGen/CodeGenSchedule.cpp rename to llvm/utils/TableGen/Common/CodeGenSchedule.cpp diff --git a/llvm/utils/TableGen/CodeGenSchedule.h b/llvm/utils/TableGen/Common/CodeGenSchedule.h similarity index 100% rename from llvm/utils/TableGen/CodeGenSchedule.h rename to llvm/utils/TableGen/Common/CodeGenSchedule.h diff --git a/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/Common/CodeGenTarget.cpp similarity index 100% rename from llvm/utils/TableGen/CodeGenTarget.cpp rename to llvm/utils/TableGen/Common/CodeGenTarget.cpp diff --git a/llvm/utils/TableGen/CodeGenTarget.h b/llvm/utils/TableGen/Common/CodeGenTarget.h similarity index 99% rename from llvm/utils/TableGen/CodeGenTarget.h rename to llvm/utils/TableGen/Common/CodeGenTarget.h index e109c717dc018e8a5dcc239b22f469179ec5c293..df4c22ebb379eeba7c2d3bd673a6d93bdef2ea19 100644 --- a/llvm/utils/TableGen/CodeGenTarget.h +++ b/llvm/utils/TableGen/Common/CodeGenTarget.h @@ -16,10 +16,10 @@ #ifndef LLVM_UTILS_TABLEGEN_CODEGENTARGET_H #define LLVM_UTILS_TABLEGEN_CODEGENTARGET_H +#include "Basic/SDNodeProperties.h" #include "CodeGenHwModes.h" #include "CodeGenInstruction.h" #include "InfoByHwMode.h" -#include "SDNodeProperties.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" diff --git a/llvm/utils/TableGen/DAGISelMatcher.cpp b/llvm/utils/TableGen/Common/DAGISelMatcher.cpp similarity index 100% rename from llvm/utils/TableGen/DAGISelMatcher.cpp rename to llvm/utils/TableGen/Common/DAGISelMatcher.cpp diff --git a/llvm/utils/TableGen/DAGISelMatcher.h b/llvm/utils/TableGen/Common/DAGISelMatcher.h similarity index 100% rename from llvm/utils/TableGen/DAGISelMatcher.h rename to llvm/utils/TableGen/Common/DAGISelMatcher.h diff --git a/llvm/utils/TableGen/GlobalISel/CXXPredicates.cpp b/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.cpp similarity index 100% rename from llvm/utils/TableGen/GlobalISel/CXXPredicates.cpp rename to llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.cpp diff --git a/llvm/utils/TableGen/GlobalISel/CXXPredicates.h b/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.h similarity index 100% rename from llvm/utils/TableGen/GlobalISel/CXXPredicates.h rename to llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.h diff --git a/llvm/utils/TableGen/GlobalISel/CodeExpander.cpp b/llvm/utils/TableGen/Common/GlobalISel/CodeExpander.cpp similarity index 100% rename from llvm/utils/TableGen/GlobalISel/CodeExpander.cpp rename to llvm/utils/TableGen/Common/GlobalISel/CodeExpander.cpp diff --git a/llvm/utils/TableGen/GlobalISel/CodeExpander.h b/llvm/utils/TableGen/Common/GlobalISel/CodeExpander.h similarity index 100% rename from llvm/utils/TableGen/GlobalISel/CodeExpander.h rename to llvm/utils/TableGen/Common/GlobalISel/CodeExpander.h diff --git a/llvm/utils/TableGen/GlobalISel/CodeExpansions.h b/llvm/utils/TableGen/Common/GlobalISel/CodeExpansions.h similarity index 100% rename from llvm/utils/TableGen/GlobalISel/CodeExpansions.h rename to llvm/utils/TableGen/Common/GlobalISel/CodeExpansions.h diff --git a/llvm/utils/TableGen/Common/GlobalISel/CombinerUtils.cpp b/llvm/utils/TableGen/Common/GlobalISel/CombinerUtils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..37e6306050951b6db1189a3eda43f809ff95f244 --- /dev/null +++ b/llvm/utils/TableGen/Common/GlobalISel/CombinerUtils.cpp @@ -0,0 +1,23 @@ +//===- CombinerUtils.cpp --------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CombinerUtils.h" +#include "llvm/ADT/StringSet.h" + +namespace llvm { + +StringRef insertStrRef(StringRef S) { + if (S.empty()) + return {}; + + static StringSet<> Pool; + auto [It, Inserted] = Pool.insert(S); + return It->getKey(); +} + +} // namespace llvm diff --git a/llvm/utils/TableGen/GlobalISel/CombinerUtils.h b/llvm/utils/TableGen/Common/GlobalISel/CombinerUtils.h similarity index 96% rename from llvm/utils/TableGen/GlobalISel/CombinerUtils.h rename to llvm/utils/TableGen/Common/GlobalISel/CombinerUtils.h index 8cb2514a10e8761d5964c8173c97f61395dbf4c0..82a64c63edbde324cf0b8b54a0a812d509c5fc46 100644 --- a/llvm/utils/TableGen/GlobalISel/CombinerUtils.h +++ b/llvm/utils/TableGen/Common/GlobalISel/CombinerUtils.h @@ -65,6 +65,10 @@ inline const DagInit *getDagWithOperatorOfSubClass(const Init &N, return I; return nullptr; } + +/// Copies a StringRef into a static pool to preserve it. +StringRef insertStrRef(StringRef S); + } // namespace llvm #endif diff --git a/llvm/utils/TableGen/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp similarity index 99% rename from llvm/utils/TableGen/GlobalISelMatchTable.cpp rename to llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp index 45fb41b89f2787ba960a81885e17651d4e08383b..19d42b7688dac8f99ff66d0c413b4cb222db52af 100644 --- a/llvm/utils/TableGen/GlobalISelMatchTable.cpp +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp @@ -7,8 +7,8 @@ //===----------------------------------------------------------------------===// #include "GlobalISelMatchTable.h" -#include "CodeGenInstruction.h" -#include "CodeGenRegisters.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenRegisters.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" #include "llvm/Support/LEB128.h" @@ -1077,30 +1077,25 @@ OperandPredicateMatcher::~OperandPredicateMatcher() {} bool OperandPredicateMatcher::isHigherPriorityThan( const OperandPredicateMatcher &B) const { // Generally speaking, an instruction is more important than an Int or a - // LiteralInt because it can cover more nodes but theres an exception to + // LiteralInt because it can cover more nodes but there's an exception to // this. G_CONSTANT's are less important than either of those two because they // are more permissive. - const InstructionOperandMatcher *AOM = - dyn_cast<InstructionOperandMatcher>(this); - const InstructionOperandMatcher *BOM = - dyn_cast<InstructionOperandMatcher>(&B); + const auto *AOM = dyn_cast<InstructionOperandMatcher>(this); + const auto *BOM = dyn_cast<InstructionOperandMatcher>(&B); bool AIsConstantInsn = AOM && AOM->getInsnMatcher().isConstantInstruction(); bool BIsConstantInsn = BOM && BOM->getInsnMatcher().isConstantInstruction(); - if (AOM && BOM) { - // The relative priorities between a G_CONSTANT and any other instruction - // don't actually matter but this code is needed to ensure a strict weak - // ordering. This is particularly important on Windows where the rules will - // be incorrectly sorted without it. - if (AIsConstantInsn != BIsConstantInsn) - return AIsConstantInsn < BIsConstantInsn; - return false; - } + // The relative priorities between a G_CONSTANT and any other instruction + // don't actually matter but this code is needed to ensure a strict weak + // ordering. This is particularly important on Windows where the rules will + // be incorrectly sorted without it. + if (AOM && BOM) + return !AIsConstantInsn && BIsConstantInsn; - if (AOM && AIsConstantInsn && (B.Kind == OPM_Int || B.Kind == OPM_LiteralInt)) + if (AIsConstantInsn && (B.Kind == OPM_Int || B.Kind == OPM_LiteralInt)) return false; - if (BOM && BIsConstantInsn && (Kind == OPM_Int || Kind == OPM_LiteralInt)) + if (BIsConstantInsn && (Kind == OPM_Int || Kind == OPM_LiteralInt)) return true; return Kind < B.Kind; diff --git a/llvm/utils/TableGen/GlobalISelMatchTable.h b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h similarity index 99% rename from llvm/utils/TableGen/GlobalISelMatchTable.h rename to llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h index b1ab7da8db44618edb8d83c7e0a8f3c9f1c60df3..aa86fad763d18002508071622d629c9b5fe72b6b 100644 --- a/llvm/utils/TableGen/GlobalISelMatchTable.h +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h @@ -16,7 +16,7 @@ #ifndef LLVM_UTILS_TABLEGEN_GLOBALISELMATCHTABLE_H #define LLVM_UTILS_TABLEGEN_GLOBALISELMATCHTABLE_H -#include "CodeGenDAGPatterns.h" +#include "Common/CodeGenDAGPatterns.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" diff --git a/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp similarity index 100% rename from llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.cpp rename to llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp diff --git a/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.h b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h similarity index 99% rename from llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.h rename to llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h index 7e952d6df30939d5539652f209e4ce67b6efd992..d2b6a74c75771345148c7b4f3a8fd077ab1d47cf 100644 --- a/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.h +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h @@ -15,7 +15,7 @@ #ifndef LLVM_UTILS_TABLEGEN_GLOBALISELMATCHTABLEEXECUTOREMITTER_H #define LLVM_UTILS_TABLEGEN_GLOBALISELMATCHTABLEEXECUTOREMITTER_H -#include "SubtargetFeatureInfo.h" +#include "Common/SubtargetFeatureInfo.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" diff --git a/llvm/utils/TableGen/GlobalISel/MatchDataInfo.cpp b/llvm/utils/TableGen/Common/GlobalISel/MatchDataInfo.cpp similarity index 100% rename from llvm/utils/TableGen/GlobalISel/MatchDataInfo.cpp rename to llvm/utils/TableGen/Common/GlobalISel/MatchDataInfo.cpp diff --git a/llvm/utils/TableGen/GlobalISel/MatchDataInfo.h b/llvm/utils/TableGen/Common/GlobalISel/MatchDataInfo.h similarity index 100% rename from llvm/utils/TableGen/GlobalISel/MatchDataInfo.h rename to llvm/utils/TableGen/Common/GlobalISel/MatchDataInfo.h diff --git a/llvm/utils/TableGen/Common/GlobalISel/PatternParser.cpp b/llvm/utils/TableGen/Common/GlobalISel/PatternParser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1d6c4c73a26405d93bf58b543e873c927b784964 --- /dev/null +++ b/llvm/utils/TableGen/Common/GlobalISel/PatternParser.cpp @@ -0,0 +1,462 @@ +//===- PatternParser.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 "Common/GlobalISel/PatternParser.h" +#include "Basic/CodeGenIntrinsics.h" +#include "Common/CodeGenTarget.h" +#include "Common/GlobalISel/CombinerUtils.h" +#include "Common/GlobalISel/Patterns.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/SaveAndRestore.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" + +namespace llvm { +namespace gi { +static constexpr StringLiteral MIFlagsEnumClassName = "MIFlagEnum"; + +namespace { +class PrettyStackTraceParse : public PrettyStackTraceEntry { + const Record &Def; + +public: + PrettyStackTraceParse(const Record &Def) : Def(Def) {} + + void print(raw_ostream &OS) const override { + if (Def.isSubClassOf("GICombineRule")) + OS << "Parsing GICombineRule '" << Def.getName() << '\''; + else if (Def.isSubClassOf(PatFrag::ClassName)) + OS << "Parsing " << PatFrag::ClassName << " '" << Def.getName() << '\''; + else + OS << "Parsing '" << Def.getName() << '\''; + OS << '\n'; + } +}; +} // namespace + +bool PatternParser::parsePatternList( + const DagInit &List, + function_ref<bool(std::unique_ptr<Pattern>)> ParseAction, + StringRef Operator, StringRef AnonPatNamePrefix) { + if (List.getOperatorAsDef(DiagLoc)->getName() != Operator) { + PrintError(DiagLoc, "Expected " + Operator + " operator"); + return false; + } + + if (List.getNumArgs() == 0) { + PrintError(DiagLoc, Operator + " pattern list is empty"); + return false; + } + + // The match section consists of a list of matchers and predicates. Parse each + // one and add the equivalent GIMatchDag nodes, predicates, and edges. + for (unsigned I = 0; I < List.getNumArgs(); ++I) { + Init *Arg = List.getArg(I); + std::string Name = List.getArgName(I) + ? List.getArgName(I)->getValue().str() + : ("__" + AnonPatNamePrefix + "_" + Twine(I)).str(); + + if (auto Pat = parseInstructionPattern(*Arg, Name)) { + if (!ParseAction(std::move(Pat))) + return false; + continue; + } + + if (auto Pat = parseWipMatchOpcodeMatcher(*Arg, Name)) { + if (!ParseAction(std::move(Pat))) + return false; + continue; + } + + // Parse arbitrary C++ code + if (const auto *StringI = dyn_cast<StringInit>(Arg)) { + auto CXXPat = std::make_unique<CXXPattern>(*StringI, insertStrRef(Name)); + if (!ParseAction(std::move(CXXPat))) + return false; + continue; + } + + PrintError(DiagLoc, + "Failed to parse pattern: '" + Arg->getAsString() + '\''); + return false; + } + + return true; +} + +static const CodeGenInstruction & +getInstrForIntrinsic(const CodeGenTarget &CGT, const CodeGenIntrinsic *I) { + StringRef Opc; + if (I->isConvergent) { + Opc = I->hasSideEffects ? "G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS" + : "G_INTRINSIC_CONVERGENT"; + } else { + Opc = I->hasSideEffects ? "G_INTRINSIC_W_SIDE_EFFECTS" : "G_INTRINSIC"; + } + + RecordKeeper &RK = I->TheDef->getRecords(); + return CGT.getInstruction(RK.getDef(Opc)); +} + +static const CodeGenIntrinsic *getCodeGenIntrinsic(Record *R) { + // Intrinsics need to have a static lifetime because the match table keeps + // references to CodeGenIntrinsic objects. + static DenseMap<const Record *, std::unique_ptr<CodeGenIntrinsic>> + AllIntrinsics; + + auto &Ptr = AllIntrinsics[R]; + if (!Ptr) + Ptr = std::make_unique<CodeGenIntrinsic>(R, std::vector<Record *>()); + return Ptr.get(); +} + +std::unique_ptr<Pattern> +PatternParser::parseInstructionPattern(const Init &Arg, StringRef Name) { + const DagInit *DagPat = dyn_cast<DagInit>(&Arg); + if (!DagPat) + return nullptr; + + std::unique_ptr<InstructionPattern> Pat; + if (const DagInit *IP = getDagWithOperatorOfSubClass(Arg, "Instruction")) { + auto &Instr = CGT.getInstruction(IP->getOperatorAsDef(DiagLoc)); + Pat = + std::make_unique<CodeGenInstructionPattern>(Instr, insertStrRef(Name)); + } else if (const DagInit *IP = + getDagWithOperatorOfSubClass(Arg, "Intrinsic")) { + Record *TheDef = IP->getOperatorAsDef(DiagLoc); + const CodeGenIntrinsic *Intrin = getCodeGenIntrinsic(TheDef); + const CodeGenInstruction &Instr = getInstrForIntrinsic(CGT, Intrin); + Pat = + std::make_unique<CodeGenInstructionPattern>(Instr, insertStrRef(Name)); + cast<CodeGenInstructionPattern>(*Pat).setIntrinsic(Intrin); + } else if (const DagInit *PFP = + getDagWithOperatorOfSubClass(Arg, PatFrag::ClassName)) { + const Record *Def = PFP->getOperatorAsDef(DiagLoc); + const PatFrag *PF = parsePatFrag(Def); + if (!PF) + return nullptr; // Already diagnosed by parsePatFrag + Pat = std::make_unique<PatFragPattern>(*PF, insertStrRef(Name)); + } else if (const DagInit *BP = + getDagWithOperatorOfSubClass(Arg, BuiltinPattern::ClassName)) { + Pat = std::make_unique<BuiltinPattern>(*BP->getOperatorAsDef(DiagLoc), + insertStrRef(Name)); + } else + return nullptr; + + for (unsigned K = 0; K < DagPat->getNumArgs(); ++K) { + Init *Arg = DagPat->getArg(K); + if (auto *DagArg = getDagWithSpecificOperator(*Arg, "MIFlags")) { + if (!parseInstructionPatternMIFlags(*Pat, DagArg)) + return nullptr; + continue; + } + + if (!parseInstructionPatternOperand(*Pat, Arg, DagPat->getArgName(K))) + return nullptr; + } + + if (!Pat->checkSemantics(DiagLoc)) + return nullptr; + + return std::move(Pat); +} + +std::unique_ptr<Pattern> +PatternParser::parseWipMatchOpcodeMatcher(const Init &Arg, StringRef Name) { + const DagInit *Matcher = getDagWithSpecificOperator(Arg, "wip_match_opcode"); + if (!Matcher) + return nullptr; + + if (Matcher->getNumArgs() == 0) { + PrintError(DiagLoc, "Empty wip_match_opcode"); + return nullptr; + } + + // Each argument is an opcode that can match. + auto Result = std::make_unique<AnyOpcodePattern>(insertStrRef(Name)); + for (const auto &Arg : Matcher->getArgs()) { + Record *OpcodeDef = getDefOfSubClass(*Arg, "Instruction"); + if (OpcodeDef) { + Result->addOpcode(&CGT.getInstruction(OpcodeDef)); + continue; + } + + PrintError(DiagLoc, "Arguments to wip_match_opcode must be instructions"); + return nullptr; + } + + return std::move(Result); +} + +bool PatternParser::parseInstructionPatternOperand(InstructionPattern &IP, + const Init *OpInit, + const StringInit *OpName) { + const auto ParseErr = [&]() { + PrintError(DiagLoc, + "cannot parse operand '" + OpInit->getAsUnquotedString() + "' "); + if (OpName) + PrintNote(DiagLoc, + "operand name is '" + OpName->getAsUnquotedString() + '\''); + return false; + }; + + // untyped immediate, e.g. 0 + if (const auto *IntImm = dyn_cast<IntInit>(OpInit)) { + std::string Name = OpName ? OpName->getAsUnquotedString() : ""; + IP.addOperand(IntImm->getValue(), insertStrRef(Name), PatternType()); + return true; + } + + // typed immediate, e.g. (i32 0) + if (const auto *DagOp = dyn_cast<DagInit>(OpInit)) { + if (DagOp->getNumArgs() != 1) + return ParseErr(); + + const Record *TyDef = DagOp->getOperatorAsDef(DiagLoc); + auto ImmTy = PatternType::get(DiagLoc, TyDef, + "cannot parse immediate '" + + DagOp->getAsUnquotedString() + '\''); + if (!ImmTy) + return false; + + if (!IP.hasAllDefs()) { + PrintError(DiagLoc, "out operand of '" + IP.getInstName() + + "' cannot be an immediate"); + return false; + } + + const auto *Val = dyn_cast<IntInit>(DagOp->getArg(0)); + if (!Val) + return ParseErr(); + + std::string Name = OpName ? OpName->getAsUnquotedString() : ""; + IP.addOperand(Val->getValue(), insertStrRef(Name), *ImmTy); + return true; + } + + // Typed operand e.g. $x/$z in (G_FNEG $x, $z) + if (auto *DefI = dyn_cast<DefInit>(OpInit)) { + if (!OpName) { + PrintError(DiagLoc, "expected an operand name after '" + + OpInit->getAsString() + '\''); + return false; + } + const Record *Def = DefI->getDef(); + auto Ty = PatternType::get(DiagLoc, Def, "cannot parse operand type"); + if (!Ty) + return false; + IP.addOperand(insertStrRef(OpName->getAsUnquotedString()), *Ty); + return true; + } + + // Untyped operand e.g. $x/$z in (G_FNEG $x, $z) + if (isa<UnsetInit>(OpInit)) { + assert(OpName && "Unset w/ no OpName?"); + IP.addOperand(insertStrRef(OpName->getAsUnquotedString()), PatternType()); + return true; + } + + return ParseErr(); +} + +bool PatternParser::parseInstructionPatternMIFlags(InstructionPattern &IP, + const DagInit *Op) { + auto *CGIP = dyn_cast<CodeGenInstructionPattern>(&IP); + if (!CGIP) { + PrintError(DiagLoc, + "matching/writing MIFlags is only allowed on CodeGenInstruction " + "patterns"); + return false; + } + + const auto CheckFlagEnum = [&](const Record *R) { + if (!R->isSubClassOf(MIFlagsEnumClassName)) { + PrintError(DiagLoc, "'" + R->getName() + "' is not a subclass of '" + + MIFlagsEnumClassName + "'"); + return false; + } + + return true; + }; + + if (CGIP->getMIFlagsInfo()) { + PrintError(DiagLoc, "MIFlags can only be present once on an instruction"); + return false; + } + + auto &FI = CGIP->getOrCreateMIFlagsInfo(); + for (unsigned K = 0; K < Op->getNumArgs(); ++K) { + const Init *Arg = Op->getArg(K); + + // Match/set a flag: (MIFlags FmNoNans) + if (const auto *Def = dyn_cast<DefInit>(Arg)) { + const Record *R = Def->getDef(); + if (!CheckFlagEnum(R)) + return false; + + FI.addSetFlag(R); + continue; + } + + // Do not match a flag/unset a flag: (MIFlags (not FmNoNans)) + if (const DagInit *NotDag = getDagWithSpecificOperator(*Arg, "not")) { + for (const Init *NotArg : NotDag->getArgs()) { + const DefInit *DefArg = dyn_cast<DefInit>(NotArg); + if (!DefArg) { + PrintError(DiagLoc, "cannot parse '" + NotArg->getAsUnquotedString() + + "': expected a '" + MIFlagsEnumClassName + + "'"); + return false; + } + + const Record *R = DefArg->getDef(); + if (!CheckFlagEnum(R)) + return false; + + FI.addUnsetFlag(R); + continue; + } + + continue; + } + + // Copy flags from a matched instruction: (MIFlags $mi) + if (isa<UnsetInit>(Arg)) { + FI.addCopyFlag(insertStrRef(Op->getArgName(K)->getAsUnquotedString())); + continue; + } + } + + return true; +} + +std::unique_ptr<PatFrag> PatternParser::parsePatFragImpl(const Record *Def) { + auto StackTrace = PrettyStackTraceParse(*Def); + if (!Def->isSubClassOf(PatFrag::ClassName)) + return nullptr; + + const DagInit *Ins = Def->getValueAsDag("InOperands"); + if (Ins->getOperatorAsDef(Def->getLoc())->getName() != "ins") { + PrintError(Def, "expected 'ins' operator for " + PatFrag::ClassName + + " in operands list"); + return nullptr; + } + + const DagInit *Outs = Def->getValueAsDag("OutOperands"); + if (Outs->getOperatorAsDef(Def->getLoc())->getName() != "outs") { + PrintError(Def, "expected 'outs' operator for " + PatFrag::ClassName + + " out operands list"); + return nullptr; + } + + auto Result = std::make_unique<PatFrag>(*Def); + if (!parsePatFragParamList(*Outs, [&](StringRef Name, unsigned Kind) { + Result->addOutParam(insertStrRef(Name), (PatFrag::ParamKind)Kind); + return true; + })) + return nullptr; + + if (!parsePatFragParamList(*Ins, [&](StringRef Name, unsigned Kind) { + Result->addInParam(insertStrRef(Name), (PatFrag::ParamKind)Kind); + return true; + })) + return nullptr; + + const ListInit *Alts = Def->getValueAsListInit("Alternatives"); + unsigned AltIdx = 0; + for (const Init *Alt : *Alts) { + const auto *PatDag = dyn_cast<DagInit>(Alt); + if (!PatDag) { + PrintError(Def, "expected dag init for PatFrag pattern alternative"); + return nullptr; + } + + PatFrag::Alternative &A = Result->addAlternative(); + const auto AddPat = [&](std::unique_ptr<Pattern> Pat) { + A.Pats.push_back(std::move(Pat)); + return true; + }; + + SaveAndRestore<ArrayRef<SMLoc>> DiagLocSAR(DiagLoc, Def->getLoc()); + if (!parsePatternList( + *PatDag, AddPat, "pattern", + /*AnonPatPrefix*/ + (Def->getName() + "_alt" + Twine(AltIdx++) + "_pattern").str())) + return nullptr; + } + + if (!Result->buildOperandsTables() || !Result->checkSemantics()) + return nullptr; + + return Result; +} + +bool PatternParser::parsePatFragParamList( + const DagInit &OpsList, + function_ref<bool(StringRef, unsigned)> ParseAction) { + for (unsigned K = 0; K < OpsList.getNumArgs(); ++K) { + const StringInit *Name = OpsList.getArgName(K); + const Init *Ty = OpsList.getArg(K); + + if (!Name) { + PrintError(DiagLoc, "all operands must be named'"); + return false; + } + const std::string NameStr = Name->getAsUnquotedString(); + + PatFrag::ParamKind OpKind; + if (isSpecificDef(*Ty, "gi_imm")) + OpKind = PatFrag::PK_Imm; + else if (isSpecificDef(*Ty, "root")) + OpKind = PatFrag::PK_Root; + else if (isa<UnsetInit>(Ty) || + isSpecificDef(*Ty, "gi_mo")) // no type = gi_mo. + OpKind = PatFrag::PK_MachineOperand; + else { + PrintError( + DiagLoc, + '\'' + NameStr + + "' operand type was expected to be 'root', 'gi_imm' or 'gi_mo'"); + return false; + } + + if (!ParseAction(NameStr, (unsigned)OpKind)) + return false; + } + + return true; +} + +const PatFrag *PatternParser::parsePatFrag(const Record *Def) { + // Cache already parsed PatFrags to avoid doing extra work. + static DenseMap<const Record *, std::unique_ptr<PatFrag>> ParsedPatFrags; + + auto It = ParsedPatFrags.find(Def); + if (It != ParsedPatFrags.end()) { + SeenPatFrags.insert(It->second.get()); + return It->second.get(); + } + + std::unique_ptr<PatFrag> NewPatFrag = parsePatFragImpl(Def); + if (!NewPatFrag) { + PrintError(Def, "Could not parse " + PatFrag::ClassName + " '" + + Def->getName() + "'"); + // Put a nullptr in the map so we don't attempt parsing this again. + ParsedPatFrags[Def] = nullptr; + return nullptr; + } + + const auto *Res = NewPatFrag.get(); + ParsedPatFrags[Def] = std::move(NewPatFrag); + SeenPatFrags.insert(Res); + return Res; +} + +} // namespace gi +} // namespace llvm diff --git a/llvm/utils/TableGen/Common/GlobalISel/PatternParser.h b/llvm/utils/TableGen/Common/GlobalISel/PatternParser.h new file mode 100644 index 0000000000000000000000000000000000000000..cd6f524075cdb9bb9339c2d95a3a302a6287b0dd --- /dev/null +++ b/llvm/utils/TableGen/Common/GlobalISel/PatternParser.h @@ -0,0 +1,118 @@ +//===- PatternParser.h ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file Contains tools to parse MIR patterns from TableGen DAG elements. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_UTILS_GLOBALISEL_PATTERNPARSER_H +#define LLVM_UTILS_GLOBALISEL_PATTERNPARSER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLFunctionalExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/SMLoc.h" +#include <memory> + +namespace llvm { +class CodeGenTarget; +class DagInit; +class Init; +class Record; +class StringRef; +class StringInit; + +namespace gi { +class InstructionPattern; +class Pattern; +class PatFrag; + +/// Helper class to parse MIR Pattern lists. +/// +/// e.g., `(match (G_FADD $x, $y, $z), (G_FNEG $y, $z))` +class PatternParser { + const CodeGenTarget &CGT; + ArrayRef<SMLoc> DiagLoc; + + mutable SmallPtrSet<const PatFrag *, 2> SeenPatFrags; + +public: + PatternParser(const CodeGenTarget &CGT, ArrayRef<SMLoc> DiagLoc) + : CGT(CGT), DiagLoc(DiagLoc) {} + + /// Parses a list of patterns such as: + /// (Operator (Pattern1 ...), (Pattern2 ...)) + /// \param List DagInit of the expected pattern list. + /// \param ParseAction Callback to handle a succesfully parsed pattern. + /// \param Operator The name of the operator, e.g. "match" + /// \param AnonPatNamePrefix Prefix for anonymous pattern names. + /// \return true on success, false on failure. + bool + parsePatternList(const DagInit &List, + function_ref<bool(std::unique_ptr<Pattern>)> ParseAction, + StringRef Operator, StringRef AnonPatNamePrefix); + + /// \returns all PatFrags encountered by this PatternParser. + const auto &getSeenPatFrags() const { return SeenPatFrags; } + +private: + /// Parse any InstructionPattern from a TableGen Init. + /// \param Arg Init to parse. + /// \param PatName Name of the pattern that will be parsed. + /// \return the parsed pattern on success, nullptr on failure. + std::unique_ptr<Pattern> parseInstructionPattern(const Init &Arg, + StringRef PatName); + + /// Parse a WipOpcodeMatcher from a TableGen Init. + /// \param Arg Init to parse. + /// \param PatName Name of the pattern that will be parsed. + /// \return the parsed pattern on success, nullptr on failure. + std::unique_ptr<Pattern> parseWipMatchOpcodeMatcher(const Init &Arg, + StringRef PatName); + + /// Parses an Operand of an InstructionPattern from a TableGen Init. + /// \param IP InstructionPattern for which we're parsing. + /// \param OpInit Init to parse. + /// \param OpName Name of the operand to parse. + /// \return true on success, false on failure. + bool parseInstructionPatternOperand(InstructionPattern &IP, + const Init *OpInit, + const StringInit *OpName); + + /// Parses a MIFlag for an InstructionPattern from a TableGen Init. + /// \param IP InstructionPattern for which we're parsing. + /// \param Op Init to parse. + /// \return true on success, false on failure. + bool parseInstructionPatternMIFlags(InstructionPattern &IP, + const DagInit *Op); + + /// (Uncached) PatFrag parsing implementation. + /// \param Def PatFrag def to parsee. + /// \return the parsed PatFrag on success, nullptr on failure. + std::unique_ptr<PatFrag> parsePatFragImpl(const Record *Def); + + /// Parses the in or out parameter list of a PatFrag. + /// \param OpsList Init to parse. + /// \param ParseAction Callback on successful parse, with the name of + /// the parameter and its \ref PatFrag::ParamKind + /// \return true on success, false on failure. + bool + parsePatFragParamList(const DagInit &OpsList, + function_ref<bool(StringRef, unsigned)> ParseAction); + + /// Cached PatFrag parser. This avoids duplicate work by keeping track of + /// already-parsed PatFrags. + /// \param Def PatFrag def to parsee. + /// \return the parsed PatFrag on success, nullptr on failure. + const PatFrag *parsePatFrag(const Record *Def); +}; + +} // namespace gi +} // namespace llvm + +#endif diff --git a/llvm/utils/TableGen/GlobalISel/Patterns.cpp b/llvm/utils/TableGen/Common/GlobalISel/Patterns.cpp similarity index 99% rename from llvm/utils/TableGen/GlobalISel/Patterns.cpp rename to llvm/utils/TableGen/Common/GlobalISel/Patterns.cpp index 758eac2dfebd302391a2b367e5fde156189a45b1..388bf7e9e833449e827debcd6c4c84550fafbd0e 100644 --- a/llvm/utils/TableGen/GlobalISel/Patterns.cpp +++ b/llvm/utils/TableGen/Common/GlobalISel/Patterns.cpp @@ -7,11 +7,11 @@ //===----------------------------------------------------------------------===// #include "Patterns.h" -#include "../CodeGenInstruction.h" -#include "../CodeGenIntrinsics.h" +#include "Basic/CodeGenIntrinsics.h" #include "CXXPredicates.h" #include "CodeExpander.h" #include "CodeExpansions.h" +#include "Common/CodeGenInstruction.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" diff --git a/llvm/utils/TableGen/GlobalISel/Patterns.h b/llvm/utils/TableGen/Common/GlobalISel/Patterns.h similarity index 100% rename from llvm/utils/TableGen/GlobalISel/Patterns.h rename to llvm/utils/TableGen/Common/GlobalISel/Patterns.h diff --git a/llvm/utils/TableGen/InfoByHwMode.cpp b/llvm/utils/TableGen/Common/InfoByHwMode.cpp similarity index 92% rename from llvm/utils/TableGen/InfoByHwMode.cpp rename to llvm/utils/TableGen/Common/InfoByHwMode.cpp index 4a64421c013c5f778ac318c62cf6df1909044054..cacf4ece6671371f494d340beed3407e49c56743 100644 --- a/llvm/utils/TableGen/InfoByHwMode.cpp +++ b/llvm/utils/TableGen/Common/InfoByHwMode.cpp @@ -115,7 +115,7 @@ ValueTypeByHwMode llvm::getValueTypeByHwMode(Record *Rec, return ValueTypeByHwMode(Rec, llvm::getValueType(Rec)); } -RegSizeInfo::RegSizeInfo(Record *R, const CodeGenHwModes &CGH) { +RegSizeInfo::RegSizeInfo(Record *R) { RegSize = R->getValueAsInt("RegSize"); SpillSize = R->getValueAsInt("SpillSize"); SpillAlignment = R->getValueAsInt("SpillAlignment"); @@ -139,7 +139,7 @@ void RegSizeInfo::writeToStream(raw_ostream &OS) const { RegSizeInfoByHwMode::RegSizeInfoByHwMode(Record *R, const CodeGenHwModes &CGH) { const HwModeSelect &MS = CGH.getHwModeSelect(R); for (const HwModeSelect::PairType &P : MS.Items) { - auto I = Map.insert({P.first, RegSizeInfo(P.second, CGH)}); + auto I = Map.insert({P.first, RegSizeInfo(P.second)}); assert(I.second && "Duplicate entry?"); (void)I; } @@ -183,6 +183,20 @@ void RegSizeInfoByHwMode::writeToStream(raw_ostream &OS) const { OS << '}'; } +SubRegRange::SubRegRange(Record *R) { + Size = R->getValueAsInt("Size"); + Offset = R->getValueAsInt("Offset"); +} + +SubRegRangeByHwMode::SubRegRangeByHwMode(Record *R, const CodeGenHwModes &CGH) { + const HwModeSelect &MS = CGH.getHwModeSelect(R); + for (const HwModeSelect::PairType &P : MS.Items) { + auto I = Map.insert({P.first, SubRegRange(P.second)}); + assert(I.second && "Duplicate entry?"); + (void)I; + } +} + EncodingInfoByHwMode::EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH) { const HwModeSelect &MS = CGH.getHwModeSelect(R); diff --git a/llvm/utils/TableGen/InfoByHwMode.h b/llvm/utils/TableGen/Common/InfoByHwMode.h similarity index 92% rename from llvm/utils/TableGen/InfoByHwMode.h rename to llvm/utils/TableGen/Common/InfoByHwMode.h index 001509e5317f95724ceb88d8916451480ffb9ba0..dd0b9830d757e8b8799769e22708ca337a053f90 100644 --- a/llvm/utils/TableGen/InfoByHwMode.h +++ b/llvm/utils/TableGen/Common/InfoByHwMode.h @@ -176,12 +176,14 @@ struct ValueTypeByHwMode : public InfoByHwMode<MVT> { ValueTypeByHwMode getValueTypeByHwMode(Record *Rec, const CodeGenHwModes &CGH); +raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T); + struct RegSizeInfo { unsigned RegSize; unsigned SpillSize; unsigned SpillAlignment; - RegSizeInfo(Record *R, const CodeGenHwModes &CGH); + RegSizeInfo(Record *R); RegSizeInfo() = default; bool operator<(const RegSizeInfo &I) const; bool operator==(const RegSizeInfo &I) const { @@ -213,10 +215,27 @@ struct RegSizeInfoByHwMode : public InfoByHwMode<RegSizeInfo> { } }; -raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T); raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T); raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T); +struct SubRegRange { + uint16_t Size; + uint16_t Offset; + + SubRegRange(Record *R); + SubRegRange(uint16_t Size, uint16_t Offset) : Size(Size), Offset(Offset) {} +}; + +struct SubRegRangeByHwMode : public InfoByHwMode<SubRegRange> { + SubRegRangeByHwMode(Record *R, const CodeGenHwModes &CGH); + SubRegRangeByHwMode(SubRegRange Range) { Map.insert({DefaultMode, Range}); } + SubRegRangeByHwMode() = default; + + void insertSubRegRangeForMode(unsigned Mode, SubRegRange Info) { + Map.insert(std::pair(Mode, Info)); + } +}; + struct EncodingInfoByHwMode : public InfoByHwMode<Record *> { EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH); EncodingInfoByHwMode() = default; diff --git a/llvm/utils/TableGen/OptEmitter.cpp b/llvm/utils/TableGen/Common/OptEmitter.cpp similarity index 100% rename from llvm/utils/TableGen/OptEmitter.cpp rename to llvm/utils/TableGen/Common/OptEmitter.cpp diff --git a/llvm/utils/TableGen/OptEmitter.h b/llvm/utils/TableGen/Common/OptEmitter.h similarity index 100% rename from llvm/utils/TableGen/OptEmitter.h rename to llvm/utils/TableGen/Common/OptEmitter.h diff --git a/llvm/utils/TableGen/PredicateExpander.cpp b/llvm/utils/TableGen/Common/PredicateExpander.cpp similarity index 100% rename from llvm/utils/TableGen/PredicateExpander.cpp rename to llvm/utils/TableGen/Common/PredicateExpander.cpp diff --git a/llvm/utils/TableGen/PredicateExpander.h b/llvm/utils/TableGen/Common/PredicateExpander.h similarity index 100% rename from llvm/utils/TableGen/PredicateExpander.h rename to llvm/utils/TableGen/Common/PredicateExpander.h diff --git a/llvm/utils/TableGen/SubtargetFeatureInfo.cpp b/llvm/utils/TableGen/Common/SubtargetFeatureInfo.cpp similarity index 100% rename from llvm/utils/TableGen/SubtargetFeatureInfo.cpp rename to llvm/utils/TableGen/Common/SubtargetFeatureInfo.cpp diff --git a/llvm/utils/TableGen/SubtargetFeatureInfo.h b/llvm/utils/TableGen/Common/SubtargetFeatureInfo.h similarity index 100% rename from llvm/utils/TableGen/SubtargetFeatureInfo.h rename to llvm/utils/TableGen/Common/SubtargetFeatureInfo.h diff --git a/llvm/utils/TableGen/Types.cpp b/llvm/utils/TableGen/Common/Types.cpp similarity index 100% rename from llvm/utils/TableGen/Types.cpp rename to llvm/utils/TableGen/Common/Types.cpp diff --git a/llvm/utils/TableGen/Types.h b/llvm/utils/TableGen/Common/Types.h similarity index 100% rename from llvm/utils/TableGen/Types.h rename to llvm/utils/TableGen/Common/Types.h diff --git a/llvm/utils/TableGen/VarLenCodeEmitterGen.cpp b/llvm/utils/TableGen/Common/VarLenCodeEmitterGen.cpp similarity index 97% rename from llvm/utils/TableGen/VarLenCodeEmitterGen.cpp rename to llvm/utils/TableGen/Common/VarLenCodeEmitterGen.cpp index bfb7e5c333170c2ae7189c181f7c02fa1e630969..4263d8f41715f30d1a6ef4029502bda8417f8377 100644 --- a/llvm/utils/TableGen/VarLenCodeEmitterGen.cpp +++ b/llvm/utils/TableGen/Common/VarLenCodeEmitterGen.cpp @@ -337,8 +337,8 @@ static void emitInstBits(raw_ostream &IS, raw_ostream &SS, const APInt &Bits, return; } - IS.indent(4) << "{/*NumBits*/" << Bits.getBitWidth() << ", " - << "/*Index*/" << Index << "},"; + IS.indent(4) << "{/*NumBits*/" << Bits.getBitWidth() << ", " << "/*Index*/" + << Index << "},"; SS.indent(4); for (unsigned I = 0; I < Bits.getNumWords(); ++I, ++Index) @@ -371,8 +371,8 @@ void VarLenCodeEmitterGen::emitInstructionBaseValues( if (ModeIt == InstIt->second.end()) ModeIt = InstIt->second.find(Universal); if (ModeIt == InstIt->second.end()) { - IS.indent(4) << "{/*NumBits*/0, /*Index*/0},\t" - << "// " << R->getName() << " no encoding\n"; + IS.indent(4) << "{/*NumBits*/0, /*Index*/0},\t" << "// " << R->getName() + << " no encoding\n"; continue; } const VarLenInst &VLI = ModeIt->second; @@ -492,10 +492,9 @@ std::string VarLenCodeEmitterGen::getInstructionCaseForEncoding( SS << ", /*Pos=*/" << utostr(Offset) << ", Scratch, Fixups, STI);\n"; - SS.indent(I) << "Inst.insertBits(" - << "Scratch.extractBits(" << utostr(NumBits) << ", " - << utostr(LoBit) << ")" - << ", " << Offset << ");\n"; + SS.indent(I) << "Inst.insertBits(" << "Scratch.extractBits(" + << utostr(NumBits) << ", " << utostr(LoBit) << ")" << ", " + << Offset << ");\n"; HighScratchAccess = std::max(HighScratchAccess, NumBits + LoBit); } diff --git a/llvm/utils/TableGen/VarLenCodeEmitterGen.h b/llvm/utils/TableGen/Common/VarLenCodeEmitterGen.h similarity index 100% rename from llvm/utils/TableGen/VarLenCodeEmitterGen.h rename to llvm/utils/TableGen/Common/VarLenCodeEmitterGen.h diff --git a/llvm/utils/TableGen/CompressInstEmitter.cpp b/llvm/utils/TableGen/CompressInstEmitter.cpp index f703fff0ef3e8943d912ad7c2c43137154b5d85f..fcf77934faacfd2b99512032f696ba4f2aa05812 100644 --- a/llvm/utils/TableGen/CompressInstEmitter.cpp +++ b/llvm/utils/TableGen/CompressInstEmitter.cpp @@ -64,9 +64,9 @@ //===----------------------------------------------------------------------===// -#include "CodeGenInstruction.h" -#include "CodeGenRegisters.h" -#include "CodeGenTarget.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenRegisters.h" +#include "Common/CodeGenTarget.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" diff --git a/llvm/utils/TableGen/DAGISelEmitter.cpp b/llvm/utils/TableGen/DAGISelEmitter.cpp index 336cee09b90c36a384ea6b545b63c3246180d561..b43a8e659dd9c5e1470f7ff31c3a58d164c77fcc 100644 --- a/llvm/utils/TableGen/DAGISelEmitter.cpp +++ b/llvm/utils/TableGen/DAGISelEmitter.cpp @@ -10,10 +10,10 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenDAGPatterns.h" -#include "CodeGenInstruction.h" -#include "CodeGenTarget.h" -#include "DAGISelMatcher.h" +#include "Common/CodeGenDAGPatterns.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenTarget.h" +#include "Common/DAGISelMatcher.h" #include "llvm/Support/Debug.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" diff --git a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp index 533b8c423690299cdddd26379678088d75a248ed..dcecac4380ce23eb9e18b5cbe057f3fdd23beb2e 100644 --- a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -10,12 +10,12 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenDAGPatterns.h" -#include "CodeGenInstruction.h" -#include "CodeGenRegisters.h" -#include "CodeGenTarget.h" -#include "DAGISelMatcher.h" -#include "SDNodeProperties.h" +#include "Basic/SDNodeProperties.h" +#include "Common/CodeGenDAGPatterns.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenRegisters.h" +#include "Common/CodeGenTarget.h" +#include "Common/DAGISelMatcher.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/StringMap.h" diff --git a/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/llvm/utils/TableGen/DAGISelMatcherGen.cpp index e8bdabaa0c7e89e295e48995c8b835b4e4469e19..99babdf07316f04dcbdbeabc56d1bf99ef164dde 100644 --- a/llvm/utils/TableGen/DAGISelMatcherGen.cpp +++ b/llvm/utils/TableGen/DAGISelMatcherGen.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenDAGPatterns.h" -#include "CodeGenInstruction.h" -#include "CodeGenRegisters.h" -#include "CodeGenTarget.h" -#include "DAGISelMatcher.h" -#include "InfoByHwMode.h" -#include "SDNodeProperties.h" +#include "Basic/SDNodeProperties.h" +#include "Common/CodeGenDAGPatterns.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenRegisters.h" +#include "Common/CodeGenTarget.h" +#include "Common/DAGISelMatcher.h" +#include "Common/InfoByHwMode.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/TableGen/Error.h" diff --git a/llvm/utils/TableGen/DAGISelMatcherOpt.cpp b/llvm/utils/TableGen/DAGISelMatcherOpt.cpp index 047d285f9914e505da3419113595a052c1f495bf..224102e49d98917525af21324c5aaaba0e78907a 100644 --- a/llvm/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/llvm/utils/TableGen/DAGISelMatcherOpt.cpp @@ -10,9 +10,9 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenDAGPatterns.h" -#include "DAGISelMatcher.h" -#include "SDNodeProperties.h" +#include "Basic/SDNodeProperties.h" +#include "Common/CodeGenDAGPatterns.h" +#include "Common/DAGISelMatcher.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" diff --git a/llvm/utils/TableGen/DFAEmitter.cpp b/llvm/utils/TableGen/DFAEmitter.cpp index ce8cc2a078d7179b60bfde14c1a747dcc91a391c..567184d3d5ee71182d789b5c7dd505ec660aa067 100644 --- a/llvm/utils/TableGen/DFAEmitter.cpp +++ b/llvm/utils/TableGen/DFAEmitter.cpp @@ -21,7 +21,7 @@ //===----------------------------------------------------------------------===// #include "DFAEmitter.h" -#include "SequenceToOffsetTable.h" +#include "Basic/SequenceToOffsetTable.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/UniqueVector.h" diff --git a/llvm/utils/TableGen/DFAPacketizerEmitter.cpp b/llvm/utils/TableGen/DFAPacketizerEmitter.cpp index 26ea1846ffae2f0bb10ca550e7feed713c13d734..3c74df048660e19f3fbe63c696ec0b13d546d76a 100644 --- a/llvm/utils/TableGen/DFAPacketizerEmitter.cpp +++ b/llvm/utils/TableGen/DFAPacketizerEmitter.cpp @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenSchedule.h" -#include "CodeGenTarget.h" +#include "Common/CodeGenSchedule.h" +#include "Common/CodeGenTarget.h" #include "DFAEmitter.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Debug.h" diff --git a/llvm/utils/TableGen/DXILEmitter.cpp b/llvm/utils/TableGen/DXILEmitter.cpp index 59089929837ebba9d734bc3d0b7b905416db34f0..f2504775d557f2fd58d4acef31bec6dfb0bf9029 100644 --- a/llvm/utils/TableGen/DXILEmitter.cpp +++ b/llvm/utils/TableGen/DXILEmitter.cpp @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenTarget.h" -#include "SequenceToOffsetTable.h" +#include "Basic/SequenceToOffsetTable.h" +#include "Common/CodeGenTarget.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" @@ -74,13 +74,13 @@ static ParameterKind getParameterKind(const Record *R) { auto VTRec = R->getValueAsDef("VT"); switch (getValueType(VTRec)) { case MVT::isVoid: - return ParameterKind::VOID; + return ParameterKind::Void; case MVT::f16: - return ParameterKind::HALF; + return ParameterKind::Half; case MVT::f32: - return ParameterKind::FLOAT; + return ParameterKind::Float; case MVT::f64: - return ParameterKind::DOUBLE; + return ParameterKind::Double; case MVT::i1: return ParameterKind::I1; case MVT::i8: @@ -91,11 +91,11 @@ static ParameterKind getParameterKind(const Record *R) { return ParameterKind::I32; case MVT::fAny: case MVT::iAny: - return ParameterKind::OVERLOAD; + return ParameterKind::Overload; case MVT::Other: // Handle DXIL-specific overload types if (R->getValueAsInt("isHalfOrFloat") || R->getValueAsInt("isI16OrI32")) { - return ParameterKind::OVERLOAD; + return ParameterKind::Overload; } LLVM_FALLTHROUGH; default: @@ -119,7 +119,7 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) { // Populate OpTypes with return type and parameter types // Parameter indices of overloaded parameters. - // This vector contains overload parameters in the order order used to + // This vector contains overload parameters in the order used to // resolve an LLVMMatchType in accordance with convention outlined in // the comment before the definition of class LLVMMatchType in // llvm/IR/Intrinsics.td @@ -201,16 +201,16 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) { /// \return std::string string representation of input Kind static std::string getParameterKindStr(ParameterKind Kind) { switch (Kind) { - case ParameterKind::INVALID: - return "INVALID"; - case ParameterKind::VOID: - return "VOID"; - case ParameterKind::HALF: - return "HALF"; - case ParameterKind::FLOAT: - return "FLOAT"; - case ParameterKind::DOUBLE: - return "DOUBLE"; + case ParameterKind::Invalid: + return "Invalid"; + case ParameterKind::Void: + return "Void"; + case ParameterKind::Half: + return "Half"; + case ParameterKind::Float: + return "Float"; + case ParameterKind::Double: + return "Double"; case ParameterKind::I1: return "I1"; case ParameterKind::I8: @@ -221,14 +221,14 @@ static std::string getParameterKindStr(ParameterKind Kind) { return "I32"; case ParameterKind::I64: return "I64"; - case ParameterKind::OVERLOAD: - return "OVERLOAD"; - case ParameterKind::CBUFFER_RET: - return "CBUFFER_RET"; - case ParameterKind::RESOURCE_RET: - return "RESOURCE_RET"; - case ParameterKind::DXIL_HANDLE: - return "DXIL_HANDLE"; + case ParameterKind::Overload: + return "Overload"; + case ParameterKind::CBufferRet: + return "CBufferRet"; + case ParameterKind::ResourceRet: + return "ResourceRet"; + case ParameterKind::DXILHandle: + return "DXILHandle"; } llvm_unreachable("Unknown llvm::dxil::ParameterKind enum"); } @@ -398,10 +398,20 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops, OS << " static const OpCodeProperty OpCodeProps[] = {\n"; for (auto &Op : Ops) { + // Consider Op.OverloadParamIndex as the overload parameter index, by + // default + auto OLParamIdx = Op.OverloadParamIndex; + // If no overload parameter index is set, treat first parameter type as + // overload type - unless the Op has no parameters, in which case treat the + // return type - as overload parameter to emit the appropriate overload kind + // enum. + if (OLParamIdx < 0) { + OLParamIdx = (Op.OpTypes.size() > 1) ? 1 : 0; + } OS << " { dxil::OpCode::" << Op.OpName << ", " << OpStrings.get(Op.OpName) << ", OpCodeClass::" << Op.OpClass << ", " << OpClassStrings.get(Op.OpClass.data()) << ", " - << getOverloadKindStr(Op.OpTypes[0]) << ", " + << getOverloadKindStr(Op.OpTypes[OLParamIdx]) << ", " << emitDXILOperationAttr(Op.OpAttributes) << ", " << Op.OverloadParamIndex << ", " << Op.OpTypes.size() - 1 << ", " << Parameters.get(ParameterMap[Op.OpClass]) << " },\n"; @@ -452,7 +462,7 @@ static void emitDXILOperationTable(std::vector<DXILOperationDesc> &Ops, [](raw_ostream &ParamOS, ParameterKind Kind) { ParamOS << "ParameterKind::" << getParameterKindStr(Kind); }, - "ParameterKind::INVALID"); + "ParameterKind::Invalid"); OS << " };\n\n"; OS << " unsigned Index = Prop.ParameterTableOffset;\n"; OS << " return DXILOpParameterKindTable + Index;\n"; diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp index dd78dc02159b9432d1c9e1a36eabf3fba57ff4db..3bd7f432ff9ad6b35e1f708de301254303f9b4b9 100644 --- a/llvm/utils/TableGen/DecoderEmitter.cpp +++ b/llvm/utils/TableGen/DecoderEmitter.cpp @@ -11,12 +11,12 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenHwModes.h" -#include "CodeGenInstruction.h" -#include "CodeGenTarget.h" -#include "InfoByHwMode.h" +#include "Common/CodeGenHwModes.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenTarget.h" +#include "Common/InfoByHwMode.h" +#include "Common/VarLenCodeEmitterGen.h" #include "TableGenBackends.h" -#include "VarLenCodeEmitterGen.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/CachedHashString.h" @@ -54,10 +54,27 @@ using namespace llvm; extern cl::OptionCategory DisassemblerEmitterCat; -cl::opt<bool> DecoderEmitterSuppressDuplicates( +enum SuppressLevel { + SUPPRESSION_DISABLE, + SUPPRESSION_LEVEL1, + SUPPRESSION_LEVEL2 +}; + +cl::opt<SuppressLevel> DecoderEmitterSuppressDuplicates( "suppress-per-hwmode-duplicates", cl::desc("Suppress duplication of instrs into per-HwMode decoder tables"), - cl::init(false), cl::cat(DisassemblerEmitterCat)); + cl::values( + clEnumValN( + SUPPRESSION_DISABLE, "O0", + "Do not prevent DecoderTable duplications caused by HwModes"), + clEnumValN( + SUPPRESSION_LEVEL1, "O1", + "Remove duplicate DecoderTable entries generated due to HwModes"), + clEnumValN( + SUPPRESSION_LEVEL2, "O2", + "Extract HwModes-specific instructions into new DecoderTables, " + "significantly reducing Table Duplications")), + cl::init(SUPPRESSION_DISABLE), cl::cat(DisassemblerEmitterCat)); namespace { @@ -128,6 +145,7 @@ struct EncodingIDAndOpcode { }; using EncodingIDsVec = std::vector<EncodingIDAndOpcode>; +using NamespacesHwModesMap = std::map<std::string, std::set<StringRef>>; raw_ostream &operator<<(raw_ostream &OS, const EncodingAndInst &Value) { if (Value.EncodingDef != Value.Inst->TheDef) @@ -934,7 +952,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table, unsigned Shift = 0; do { OS << ", " << (unsigned)*I; - Value += (*I & 0x7f) << Shift; + Value += ((uint64_t)(*I & 0x7f)) << Shift; Shift += 7; } while (*I++ >= 128); if (Value > 127) { @@ -947,7 +965,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table, Shift = 0; do { OS << ", " << (unsigned)*I; - Value += (*I & 0x7f) << Shift; + Value += ((uint64_t)(*I & 0x7f)) << Shift; Shift += 7; } while (*I++ >= 128); if (Value > 127) { @@ -2283,10 +2301,8 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, } case MCD::OPC_CheckField: { // Decode the start value. - unsigned Len; - unsigned Start = decodeULEB128(++Ptr, &Len); - Ptr += Len; - Len = *Ptr;)"; + unsigned Start = decodeULEB128AndInc(++Ptr); + unsigned Len = *Ptr;)"; if (IsVarLenInst) OS << "\n makeUp(insn, Start + Len);"; OS << R"( @@ -2311,10 +2327,8 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, break; } case MCD::OPC_CheckPredicate: { - unsigned Len; // Decode the Predicate Index value. - unsigned PIdx = decodeULEB128(++Ptr, &Len); - Ptr += Len; + unsigned PIdx = decodeULEB128AndInc(++Ptr); // NumToSkip is a plain 24-bit integer. unsigned NumToSkip = *Ptr++; NumToSkip |= (*Ptr++) << 8; @@ -2330,18 +2344,15 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, break; } case MCD::OPC_Decode: { - unsigned Len; // Decode the Opcode value. - unsigned Opc = decodeULEB128(++Ptr, &Len); - Ptr += Len; - unsigned DecodeIdx = decodeULEB128(Ptr, &Len); - Ptr += Len; + unsigned Opc = decodeULEB128AndInc(++Ptr); + unsigned DecodeIdx = decodeULEB128AndInc(Ptr); MI.clear(); MI.setOpcode(Opc); bool DecodeComplete;)"; if (IsVarLenInst) { - OS << "\n Len = InstrLenTable[Opc];\n" + OS << "\n unsigned Len = InstrLenTable[Opc];\n" << " makeUp(insn, Len);"; } OS << R"( @@ -2354,12 +2365,9 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, return S; } case MCD::OPC_TryDecode: { - unsigned Len; // Decode the Opcode value. - unsigned Opc = decodeULEB128(++Ptr, &Len); - Ptr += Len; - unsigned DecodeIdx = decodeULEB128(Ptr, &Len); - Ptr += Len; + unsigned Opc = decodeULEB128AndInc(++Ptr); + unsigned DecodeIdx = decodeULEB128AndInc(Ptr); // NumToSkip is a plain 24-bit integer. unsigned NumToSkip = *Ptr++; NumToSkip |= (*Ptr++) << 8; @@ -2391,11 +2399,8 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI, } case MCD::OPC_SoftFail: { // Decode the mask values. - unsigned Len; - uint64_t PositiveMask = decodeULEB128(++Ptr, &Len); - Ptr += Len; - uint64_t NegativeMask = decodeULEB128(Ptr, &Len); - Ptr += Len; + uint64_t PositiveMask = decodeULEB128AndInc(++Ptr); + uint64_t NegativeMask = decodeULEB128AndInc(Ptr); bool Fail = (insn & PositiveMask) != 0 || (~insn & NegativeMask) != 0; if (Fail) S = MCDisassembler::SoftFail; @@ -2430,21 +2435,65 @@ static bool Check(DecodeStatus &Out, DecodeStatus In) { // Collect all HwModes referenced by the target for encoding purposes, // returning a vector of corresponding names. -static void -collectHwModesReferencedForEncodings(const CodeGenHwModes &HWM, - std::vector<StringRef> &Names) { +static void collectHwModesReferencedForEncodings( + const CodeGenHwModes &HWM, std::vector<StringRef> &Names, + NamespacesHwModesMap &NamespacesWithHwModes) { SmallBitVector BV(HWM.getNumModeIds()); for (const auto &MS : HWM.getHwModeSelects()) { for (const HwModeSelect::PairType &P : MS.second.Items) { - if (P.second->isSubClassOf("InstructionEncoding")) + if (P.second->isSubClassOf("InstructionEncoding")) { + std::string DecoderNamespace = + std::string(P.second->getValueAsString("DecoderNamespace")); + if (P.first == DefaultMode) { + NamespacesWithHwModes[DecoderNamespace].insert(""); + } else { + NamespacesWithHwModes[DecoderNamespace].insert( + HWM.getMode(P.first).Name); + } BV.set(P.first); + } } } transform(BV.set_bits(), std::back_inserter(Names), [&HWM](const int &M) { + if (M == DefaultMode) + return StringRef(""); return HWM.getModeName(M, /*IncludeDefault=*/true); }); } +static void +handleHwModesUnrelatedEncodings(const CodeGenInstruction *Instr, + const std::vector<StringRef> &HwModeNames, + NamespacesHwModesMap &NamespacesWithHwModes, + std::vector<EncodingAndInst> &GlobalEncodings) { + const Record *InstDef = Instr->TheDef; + + switch (DecoderEmitterSuppressDuplicates) { + case SUPPRESSION_DISABLE: { + for (StringRef HwModeName : HwModeNames) + GlobalEncodings.emplace_back(InstDef, Instr, HwModeName); + break; + } + case SUPPRESSION_LEVEL1: { + std::string DecoderNamespace = + std::string(InstDef->getValueAsString("DecoderNamespace")); + auto It = NamespacesWithHwModes.find(DecoderNamespace); + if (It != NamespacesWithHwModes.end()) { + for (StringRef HwModeName : It->second) + GlobalEncodings.emplace_back(InstDef, Instr, HwModeName); + } else { + // Only emit the encoding once, as it's DecoderNamespace doesn't + // contain any HwModes. + GlobalEncodings.emplace_back(InstDef, Instr, ""); + } + break; + } + case SUPPRESSION_LEVEL2: + GlobalEncodings.emplace_back(InstDef, Instr, ""); + break; + } +} + // Emits disassembler code for instruction decoding. void DecoderEmitter::run(raw_ostream &o) { formatted_raw_ostream OS(o); @@ -2470,10 +2519,12 @@ namespace llvm { // Parameterize the decoders based on namespace and instruction width. // First, collect all encoding-related HwModes referenced by the target. + // And establish a mapping table between DecoderNamespace and HwMode. // If HwModeNames is empty, add the empty string so we always have one HwMode. const CodeGenHwModes &HWM = Target.getHwModes(); std::vector<StringRef> HwModeNames; - collectHwModesReferencedForEncodings(HWM, HwModeNames); + NamespacesHwModesMap NamespacesWithHwModes; + collectHwModesReferencedForEncodings(HWM, HwModeNames, NamespacesWithHwModes); if (HwModeNames.empty()) HwModeNames.push_back(""); @@ -2484,22 +2535,22 @@ namespace llvm { if (const RecordVal *RV = InstDef->getValue("EncodingInfos")) { if (DefInit *DI = dyn_cast_or_null<DefInit>(RV->getValue())) { EncodingInfoByHwMode EBM(DI->getDef(), HWM); - for (auto &KV : EBM) - NumberedEncodings.emplace_back( - KV.second, NumberedInstruction, - HWM.getModeName(KV.first, /*IncludeDefault=*/true)); + for (auto &[ModeId, Encoding] : EBM) { + // DecoderTables with DefaultMode should not have any suffix. + if (ModeId == DefaultMode) { + NumberedEncodings.emplace_back(Encoding, NumberedInstruction, ""); + } else { + NumberedEncodings.emplace_back(Encoding, NumberedInstruction, + HWM.getMode(ModeId).Name); + } + } continue; } } - // This instruction is encoded the same on all HwModes. Emit it for all - // HwModes by default, otherwise leave it in a single common table. - if (DecoderEmitterSuppressDuplicates) { - NumberedEncodings.emplace_back(InstDef, NumberedInstruction, "AllModes"); - } else { - for (StringRef HwModeName : HwModeNames) - NumberedEncodings.emplace_back(InstDef, NumberedInstruction, - HwModeName); - } + // This instruction is encoded the same on all HwModes. + // According to user needs, provide varying degrees of suppression. + handleHwModesUnrelatedEncodings(NumberedInstruction, HwModeNames, + NamespacesWithHwModes, NumberedEncodings); } for (const auto &NumberedAlias : RK.getAllDerivedDefinitions("AdditionalEncoding")) diff --git a/llvm/utils/TableGen/DisassemblerEmitter.cpp b/llvm/utils/TableGen/DisassemblerEmitter.cpp index 2d653af4d3025ef294478abc99683566ce351d37..d41750075b41f2af85c125112d54f3f49bf21fdf 100644 --- a/llvm/utils/TableGen/DisassemblerEmitter.cpp +++ b/llvm/utils/TableGen/DisassemblerEmitter.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenTarget.h" +#include "Common/CodeGenTarget.h" #include "TableGenBackends.h" #include "WebAssemblyDisassemblerEmitter.h" #include "X86DisassemblerTables.h" diff --git a/llvm/utils/TableGen/FastISelEmitter.cpp b/llvm/utils/TableGen/FastISelEmitter.cpp index f04c6e3b3bf05db7ca5b2e1fc46f2f177be7f0af..acfdc20316b72f9494d27980a4ab5301e15f69fb 100644 --- a/llvm/utils/TableGen/FastISelEmitter.cpp +++ b/llvm/utils/TableGen/FastISelEmitter.cpp @@ -16,11 +16,11 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenDAGPatterns.h" -#include "CodeGenInstruction.h" -#include "CodeGenRegisters.h" -#include "CodeGenTarget.h" -#include "InfoByHwMode.h" +#include "Common/CodeGenDAGPatterns.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenRegisters.h" +#include "Common/CodeGenTarget.h" +#include "Common/InfoByHwMode.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/TableGen/Error.h" diff --git a/llvm/utils/TableGen/GlobalISel/CMakeLists.txt b/llvm/utils/TableGen/GlobalISel/CMakeLists.txt deleted file mode 100644 index 7262c405839934ae8e1c7f6e817fa3525f1abdd2..0000000000000000000000000000000000000000 --- a/llvm/utils/TableGen/GlobalISel/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -set(LLVM_LINK_COMPONENTS - Support - TableGen - ) - -add_llvm_library(LLVMTableGenGlobalISel STATIC DISABLE_LLVM_LINK_LLVM_DYLIB - CodeExpander.cpp - CXXPredicates.cpp - MatchDataInfo.cpp - Patterns.cpp - - DEPENDS - vt_gen - ) - -# Users may include its headers as "GlobalISel/*.h" -target_include_directories(LLVMTableGenGlobalISel - INTERFACE - $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..> - ) diff --git a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp index dee3cb4d71a403667adef7ab7dc8427da7683957..ef9e9ff04f85f729e176bcfebf0a2aca1426e7ff 100644 --- a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp @@ -26,18 +26,19 @@ /// //===----------------------------------------------------------------------===// -#include "CodeGenInstruction.h" -#include "CodeGenIntrinsics.h" -#include "CodeGenTarget.h" -#include "GlobalISel/CXXPredicates.h" -#include "GlobalISel/CodeExpander.h" -#include "GlobalISel/CodeExpansions.h" -#include "GlobalISel/CombinerUtils.h" -#include "GlobalISel/MatchDataInfo.h" -#include "GlobalISel/Patterns.h" -#include "GlobalISelMatchTable.h" -#include "GlobalISelMatchTableExecutorEmitter.h" -#include "SubtargetFeatureInfo.h" +#include "Basic/CodeGenIntrinsics.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenTarget.h" +#include "Common/GlobalISel/CXXPredicates.h" +#include "Common/GlobalISel/CodeExpander.h" +#include "Common/GlobalISel/CodeExpansions.h" +#include "Common/GlobalISel/CombinerUtils.h" +#include "Common/GlobalISel/GlobalISelMatchTable.h" +#include "Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h" +#include "Common/GlobalISel/MatchDataInfo.h" +#include "Common/GlobalISel/PatternParser.h" +#include "Common/GlobalISel/Patterns.h" +#include "Common/SubtargetFeatureInfo.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/EquivalenceClasses.h" #include "llvm/ADT/Hashing.h" @@ -80,7 +81,6 @@ cl::opt<bool> DebugTypeInfer("gicombiner-debug-typeinfer", constexpr StringLiteral CXXApplyPrefix = "GICXXCustomAction_CombineApply"; constexpr StringLiteral CXXPredPrefix = "GICXXPred_MI_Predicate_"; -constexpr StringLiteral MIFlagsEnumClassName = "MIFlagEnum"; //===- CodeExpansions Helpers --------------------------------------------===// @@ -109,17 +109,6 @@ void declareTempRegExpansion(CodeExpansions &CE, unsigned TempRegID, //===- Misc. Helpers -----------------------------------------------------===// -/// Copies a StringRef into a static pool to preserve it. -/// Most Pattern classes use StringRef so we need this. -StringRef insertStrRef(StringRef S) { - if (S.empty()) - return {}; - - static StringSet<> Pool; - auto [It, Inserted] = Pool.insert(S); - return It->getKey(); -} - template <typename Container> auto keys(Container &&C) { return map_range(C, [](auto &Entry) -> auto & { return Entry.first; }); } @@ -639,8 +628,9 @@ public: SubtargetFeatureInfoMap &SubtargetFeatures, Record &RuleDef, unsigned ID, std::vector<RuleMatcher> &OutRMs) - : CGT(CGT), SubtargetFeatures(SubtargetFeatures), RuleDef(RuleDef), - RuleID(ID), OutRMs(OutRMs) {} + : Parser(CGT, RuleDef.getLoc()), CGT(CGT), + SubtargetFeatures(SubtargetFeatures), RuleDef(RuleDef), RuleID(ID), + OutRMs(OutRMs) {} /// Parses all fields in the RuleDef record. bool parseAll(); @@ -718,26 +708,6 @@ private: bool buildRuleOperandsTable(); bool parseDefs(const DagInit &Def); - bool - parsePatternList(const DagInit &List, - function_ref<bool(std::unique_ptr<Pattern>)> ParseAction, - StringRef Operator, ArrayRef<SMLoc> DiagLoc, - StringRef AnonPatNamePrefix) const; - - std::unique_ptr<Pattern> parseInstructionPattern(const Init &Arg, - StringRef PatName) const; - std::unique_ptr<Pattern> parseWipMatchOpcodeMatcher(const Init &Arg, - StringRef PatName) const; - bool parseInstructionPatternOperand(InstructionPattern &IP, - const Init *OpInit, - const StringInit *OpName) const; - bool parseInstructionPatternMIFlags(InstructionPattern &IP, - const DagInit *Op) const; - std::unique_ptr<PatFrag> parsePatFragImpl(const Record *Def) const; - bool parsePatFragParamList( - ArrayRef<SMLoc> DiagLoc, const DagInit &OpsList, - function_ref<bool(StringRef, PatFrag::ParamKind)> ParseAction) const; - const PatFrag *parsePatFrag(const Record *Def) const; bool emitMatchPattern(CodeExpansions &CE, const PatternAlternatives &Alts, const InstructionPattern &IP); @@ -781,6 +751,7 @@ private: DenseSet<const Pattern *> &SeenPats, OperandDefLookupFn LookupOperandDef, OperandMapperFnRef OperandMapper = [](const auto &O) { return O; }); + PatternParser Parser; const CodeGenTarget &CGT; SubtargetFeatureInfoMap &SubtargetFeatures; Record &RuleDef; @@ -808,9 +779,6 @@ private: SmallVector<MatchDataInfo, 2> MatchDatas; SmallVector<PatternAlternatives, 1> PermutationsToEmit; - - // print()/debug-only members. - mutable SmallPtrSet<const PatFrag *, 2> SeenPatFrags; }; bool CombineRuleBuilder::parseAll() { @@ -819,16 +787,16 @@ bool CombineRuleBuilder::parseAll() { if (!parseDefs(*RuleDef.getValueAsDag("Defs"))) return false; - if (!parsePatternList( + if (!Parser.parsePatternList( *RuleDef.getValueAsDag("Match"), [this](auto Pat) { return addMatchPattern(std::move(Pat)); }, "match", - RuleDef.getLoc(), (RuleDef.getName() + "_match").str())) + (RuleDef.getName() + "_match").str())) return false; - if (!parsePatternList( + if (!Parser.parsePatternList( *RuleDef.getValueAsDag("Apply"), [this](auto Pat) { return addApplyPattern(std::move(Pat)); }, "apply", - RuleDef.getLoc(), (RuleDef.getName() + "_apply").str())) + (RuleDef.getName() + "_apply").str())) return false; if (!buildRuleOperandsTable() || !typecheckPatterns() || !findRoots() || @@ -884,9 +852,10 @@ void CombineRuleBuilder::print(raw_ostream &OS) const { OS << " )\n"; } - if (!SeenPatFrags.empty()) { + const auto &SeenPFs = Parser.getSeenPatFrags(); + if (!SeenPFs.empty()) { OS << " (PatFrags\n"; - for (const auto *PF : SeenPatFrags) { + for (const auto *PF : Parser.getSeenPatFrags()) { PF->print(OS, /*Indent=*/" "); OS << '\n'; } @@ -1500,426 +1469,6 @@ bool CombineRuleBuilder::parseDefs(const DagInit &Def) { return true; } -bool CombineRuleBuilder::parsePatternList( - const DagInit &List, - function_ref<bool(std::unique_ptr<Pattern>)> ParseAction, - StringRef Operator, ArrayRef<SMLoc> DiagLoc, - StringRef AnonPatNamePrefix) const { - if (List.getOperatorAsDef(RuleDef.getLoc())->getName() != Operator) { - ::PrintError(DiagLoc, "Expected " + Operator + " operator"); - return false; - } - - if (List.getNumArgs() == 0) { - ::PrintError(DiagLoc, Operator + " pattern list is empty"); - return false; - } - - // The match section consists of a list of matchers and predicates. Parse each - // one and add the equivalent GIMatchDag nodes, predicates, and edges. - for (unsigned I = 0; I < List.getNumArgs(); ++I) { - Init *Arg = List.getArg(I); - std::string Name = List.getArgName(I) - ? List.getArgName(I)->getValue().str() - : ("__" + AnonPatNamePrefix + "_" + Twine(I)).str(); - - if (auto Pat = parseInstructionPattern(*Arg, Name)) { - if (!ParseAction(std::move(Pat))) - return false; - continue; - } - - if (auto Pat = parseWipMatchOpcodeMatcher(*Arg, Name)) { - if (!ParseAction(std::move(Pat))) - return false; - continue; - } - - // Parse arbitrary C++ code - if (const auto *StringI = dyn_cast<StringInit>(Arg)) { - auto CXXPat = std::make_unique<CXXPattern>(*StringI, insertStrRef(Name)); - if (!ParseAction(std::move(CXXPat))) - return false; - continue; - } - - ::PrintError(DiagLoc, - "Failed to parse pattern: '" + Arg->getAsString() + "'"); - return false; - } - - return true; -} - -static const CodeGenInstruction & -getInstrForIntrinsic(const CodeGenTarget &CGT, const CodeGenIntrinsic *I) { - StringRef Opc; - if (I->isConvergent) { - Opc = I->hasSideEffects ? "G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS" - : "G_INTRINSIC_CONVERGENT"; - } else { - Opc = I->hasSideEffects ? "G_INTRINSIC_W_SIDE_EFFECTS" : "G_INTRINSIC"; - } - - RecordKeeper &RK = I->TheDef->getRecords(); - return CGT.getInstruction(RK.getDef(Opc)); -} - -static const CodeGenIntrinsic *getCodeGenIntrinsic(Record *R) { - // Intrinsics need to have a static lifetime because the match table keeps - // references to CodeGenIntrinsic objects. - static DenseMap<const Record *, std::unique_ptr<CodeGenIntrinsic>> - AllIntrinsics; - - auto &Ptr = AllIntrinsics[R]; - if (!Ptr) - Ptr = std::make_unique<CodeGenIntrinsic>(R, std::vector<Record *>()); - return Ptr.get(); -} - -std::unique_ptr<Pattern> -CombineRuleBuilder::parseInstructionPattern(const Init &Arg, - StringRef Name) const { - const DagInit *DagPat = dyn_cast<DagInit>(&Arg); - if (!DagPat) - return nullptr; - - std::unique_ptr<InstructionPattern> Pat; - if (const DagInit *IP = getDagWithOperatorOfSubClass(Arg, "Instruction")) { - auto &Instr = CGT.getInstruction(IP->getOperatorAsDef(RuleDef.getLoc())); - Pat = - std::make_unique<CodeGenInstructionPattern>(Instr, insertStrRef(Name)); - } else if (const DagInit *IP = - getDagWithOperatorOfSubClass(Arg, "Intrinsic")) { - Record *TheDef = IP->getOperatorAsDef(RuleDef.getLoc()); - const CodeGenIntrinsic *Intrin = getCodeGenIntrinsic(TheDef); - const CodeGenInstruction &Instr = getInstrForIntrinsic(CGT, Intrin); - Pat = - std::make_unique<CodeGenInstructionPattern>(Instr, insertStrRef(Name)); - cast<CodeGenInstructionPattern>(*Pat).setIntrinsic(Intrin); - } else if (const DagInit *PFP = - getDagWithOperatorOfSubClass(Arg, PatFrag::ClassName)) { - const Record *Def = PFP->getOperatorAsDef(RuleDef.getLoc()); - const PatFrag *PF = parsePatFrag(Def); - if (!PF) - return nullptr; // Already diagnosed by parsePatFrag - Pat = std::make_unique<PatFragPattern>(*PF, insertStrRef(Name)); - } else if (const DagInit *BP = - getDagWithOperatorOfSubClass(Arg, BuiltinPattern::ClassName)) { - Pat = std::make_unique<BuiltinPattern>( - *BP->getOperatorAsDef(RuleDef.getLoc()), insertStrRef(Name)); - } else - return nullptr; - - for (unsigned K = 0; K < DagPat->getNumArgs(); ++K) { - Init *Arg = DagPat->getArg(K); - if (auto *DagArg = getDagWithSpecificOperator(*Arg, "MIFlags")) { - if (!parseInstructionPatternMIFlags(*Pat, DagArg)) - return nullptr; - continue; - } - - if (!parseInstructionPatternOperand(*Pat, Arg, DagPat->getArgName(K))) - return nullptr; - } - - if (!Pat->checkSemantics(RuleDef.getLoc())) - return nullptr; - - return std::move(Pat); -} - -std::unique_ptr<Pattern> -CombineRuleBuilder::parseWipMatchOpcodeMatcher(const Init &Arg, - StringRef Name) const { - const DagInit *Matcher = getDagWithSpecificOperator(Arg, "wip_match_opcode"); - if (!Matcher) - return nullptr; - - if (Matcher->getNumArgs() == 0) { - PrintError("Empty wip_match_opcode"); - return nullptr; - } - - // Each argument is an opcode that can match. - auto Result = std::make_unique<AnyOpcodePattern>(insertStrRef(Name)); - for (const auto &Arg : Matcher->getArgs()) { - Record *OpcodeDef = getDefOfSubClass(*Arg, "Instruction"); - if (OpcodeDef) { - Result->addOpcode(&CGT.getInstruction(OpcodeDef)); - continue; - } - - PrintError("Arguments to wip_match_opcode must be instructions"); - return nullptr; - } - - return std::move(Result); -} - -bool CombineRuleBuilder::parseInstructionPatternOperand( - InstructionPattern &IP, const Init *OpInit, - const StringInit *OpName) const { - const auto ParseErr = [&]() { - PrintError("cannot parse operand '" + OpInit->getAsUnquotedString() + "' "); - if (OpName) - PrintNote("operand name is '" + OpName->getAsUnquotedString() + "'"); - return false; - }; - - // untyped immediate, e.g. 0 - if (const auto *IntImm = dyn_cast<IntInit>(OpInit)) { - std::string Name = OpName ? OpName->getAsUnquotedString() : ""; - IP.addOperand(IntImm->getValue(), insertStrRef(Name), PatternType()); - return true; - } - - // typed immediate, e.g. (i32 0) - if (const auto *DagOp = dyn_cast<DagInit>(OpInit)) { - if (DagOp->getNumArgs() != 1) - return ParseErr(); - - const Record *TyDef = DagOp->getOperatorAsDef(RuleDef.getLoc()); - auto ImmTy = PatternType::get(RuleDef.getLoc(), TyDef, - "cannot parse immediate '" + - DagOp->getAsUnquotedString() + "'"); - if (!ImmTy) - return false; - - if (!IP.hasAllDefs()) { - PrintError("out operand of '" + IP.getInstName() + - "' cannot be an immediate"); - return false; - } - - const auto *Val = dyn_cast<IntInit>(DagOp->getArg(0)); - if (!Val) - return ParseErr(); - - std::string Name = OpName ? OpName->getAsUnquotedString() : ""; - IP.addOperand(Val->getValue(), insertStrRef(Name), *ImmTy); - return true; - } - - // Typed operand e.g. $x/$z in (G_FNEG $x, $z) - if (auto *DefI = dyn_cast<DefInit>(OpInit)) { - if (!OpName) { - PrintError("expected an operand name after '" + OpInit->getAsString() + - "'"); - return false; - } - const Record *Def = DefI->getDef(); - auto Ty = - PatternType::get(RuleDef.getLoc(), Def, "cannot parse operand type"); - if (!Ty) - return false; - IP.addOperand(insertStrRef(OpName->getAsUnquotedString()), *Ty); - return true; - } - - // Untyped operand e.g. $x/$z in (G_FNEG $x, $z) - if (isa<UnsetInit>(OpInit)) { - assert(OpName && "Unset w/ no OpName?"); - IP.addOperand(insertStrRef(OpName->getAsUnquotedString()), PatternType()); - return true; - } - - return ParseErr(); -} - -bool CombineRuleBuilder::parseInstructionPatternMIFlags( - InstructionPattern &IP, const DagInit *Op) const { - auto *CGIP = dyn_cast<CodeGenInstructionPattern>(&IP); - if (!CGIP) { - PrintError("matching/writing MIFlags is only allowed on CodeGenInstruction " - "patterns"); - return false; - } - - const auto CheckFlagEnum = [&](const Record *R) { - if (!R->isSubClassOf(MIFlagsEnumClassName)) { - PrintError("'" + R->getName() + "' is not a subclass of '" + - MIFlagsEnumClassName + "'"); - return false; - } - - return true; - }; - - if (CGIP->getMIFlagsInfo()) { - PrintError("MIFlags can only be present once on an instruction"); - return false; - } - - auto &FI = CGIP->getOrCreateMIFlagsInfo(); - for (unsigned K = 0; K < Op->getNumArgs(); ++K) { - const Init *Arg = Op->getArg(K); - - // Match/set a flag: (MIFlags FmNoNans) - if (const auto *Def = dyn_cast<DefInit>(Arg)) { - const Record *R = Def->getDef(); - if (!CheckFlagEnum(R)) - return false; - - FI.addSetFlag(R); - continue; - } - - // Do not match a flag/unset a flag: (MIFlags (not FmNoNans)) - if (const DagInit *NotDag = getDagWithSpecificOperator(*Arg, "not")) { - for (const Init *NotArg : NotDag->getArgs()) { - const DefInit *DefArg = dyn_cast<DefInit>(NotArg); - if (!DefArg) { - PrintError("cannot parse '" + NotArg->getAsUnquotedString() + - "': expected a '" + MIFlagsEnumClassName + "'"); - return false; - } - - const Record *R = DefArg->getDef(); - if (!CheckFlagEnum(R)) - return false; - - FI.addUnsetFlag(R); - continue; - } - - continue; - } - - // Copy flags from a matched instruction: (MIFlags $mi) - if (isa<UnsetInit>(Arg)) { - FI.addCopyFlag(insertStrRef(Op->getArgName(K)->getAsUnquotedString())); - continue; - } - } - - return true; -} - -std::unique_ptr<PatFrag> -CombineRuleBuilder::parsePatFragImpl(const Record *Def) const { - auto StackTrace = PrettyStackTraceParse(*Def); - if (!Def->isSubClassOf(PatFrag::ClassName)) - return nullptr; - - const DagInit *Ins = Def->getValueAsDag("InOperands"); - if (Ins->getOperatorAsDef(Def->getLoc())->getName() != "ins") { - ::PrintError(Def, "expected 'ins' operator for " + PatFrag::ClassName + - " in operands list"); - return nullptr; - } - - const DagInit *Outs = Def->getValueAsDag("OutOperands"); - if (Outs->getOperatorAsDef(Def->getLoc())->getName() != "outs") { - ::PrintError(Def, "expected 'outs' operator for " + PatFrag::ClassName + - " out operands list"); - return nullptr; - } - - auto Result = std::make_unique<PatFrag>(*Def); - if (!parsePatFragParamList(Def->getLoc(), *Outs, - [&](StringRef Name, PatFrag::ParamKind Kind) { - Result->addOutParam(insertStrRef(Name), Kind); - return true; - })) - return nullptr; - - if (!parsePatFragParamList(Def->getLoc(), *Ins, - [&](StringRef Name, PatFrag::ParamKind Kind) { - Result->addInParam(insertStrRef(Name), Kind); - return true; - })) - return nullptr; - - const ListInit *Alts = Def->getValueAsListInit("Alternatives"); - unsigned AltIdx = 0; - for (const Init *Alt : *Alts) { - const auto *PatDag = dyn_cast<DagInit>(Alt); - if (!PatDag) { - ::PrintError(Def, "expected dag init for PatFrag pattern alternative"); - return nullptr; - } - - PatFrag::Alternative &A = Result->addAlternative(); - const auto AddPat = [&](std::unique_ptr<Pattern> Pat) { - A.Pats.push_back(std::move(Pat)); - return true; - }; - - if (!parsePatternList( - *PatDag, AddPat, "pattern", Def->getLoc(), - /*AnonPatPrefix*/ - (Def->getName() + "_alt" + Twine(AltIdx++) + "_pattern").str())) - return nullptr; - } - - if (!Result->buildOperandsTables() || !Result->checkSemantics()) - return nullptr; - - return Result; -} - -bool CombineRuleBuilder::parsePatFragParamList( - ArrayRef<SMLoc> DiagLoc, const DagInit &OpsList, - function_ref<bool(StringRef, PatFrag::ParamKind)> ParseAction) const { - for (unsigned K = 0; K < OpsList.getNumArgs(); ++K) { - const StringInit *Name = OpsList.getArgName(K); - const Init *Ty = OpsList.getArg(K); - - if (!Name) { - ::PrintError(DiagLoc, "all operands must be named'"); - return false; - } - const std::string NameStr = Name->getAsUnquotedString(); - - PatFrag::ParamKind OpKind; - if (isSpecificDef(*Ty, "gi_imm")) - OpKind = PatFrag::PK_Imm; - else if (isSpecificDef(*Ty, "root")) - OpKind = PatFrag::PK_Root; - else if (isa<UnsetInit>(Ty) || - isSpecificDef(*Ty, "gi_mo")) // no type = gi_mo. - OpKind = PatFrag::PK_MachineOperand; - else { - ::PrintError( - DiagLoc, - "'" + NameStr + - "' operand type was expected to be 'root', 'gi_imm' or 'gi_mo'"); - return false; - } - - if (!ParseAction(NameStr, OpKind)) - return false; - } - - return true; -} - -const PatFrag *CombineRuleBuilder::parsePatFrag(const Record *Def) const { - // Cache already parsed PatFrags to avoid doing extra work. - static DenseMap<const Record *, std::unique_ptr<PatFrag>> ParsedPatFrags; - - auto It = ParsedPatFrags.find(Def); - if (It != ParsedPatFrags.end()) { - SeenPatFrags.insert(It->second.get()); - return It->second.get(); - } - - std::unique_ptr<PatFrag> NewPatFrag = parsePatFragImpl(Def); - if (!NewPatFrag) { - ::PrintError(Def, "Could not parse " + PatFrag::ClassName + " '" + - Def->getName() + "'"); - // Put a nullptr in the map so we don't attempt parsing this again. - ParsedPatFrags[Def] = nullptr; - return nullptr; - } - - const auto *Res = NewPatFrag.get(); - ParsedPatFrags[Def] = std::move(NewPatFrag); - SeenPatFrags.insert(Res); - return Res; -} - bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE, const PatternAlternatives &Alts, const InstructionPattern &IP) { @@ -2910,6 +2459,7 @@ void GICombinerEmitter::emitRunCustomAction(raw_ostream &OS) { OS << " switch(ApplyID) {\n"; for (const auto &Apply : ApplyCode) { OS << " case " << Apply->getEnumNameWithPrefix(CXXApplyPrefix) << ":{\n" + << " Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]);\n" << " " << join(split(Apply->Code, '\n'), "\n ") << '\n' << " return;\n"; OS << " }\n"; @@ -2956,8 +2506,8 @@ GICombinerEmitter::buildMatchTable(MutableArrayRef<RuleMatcher> Rules) { const Matcher *B) { auto *L = static_cast<const RuleMatcher *>(A); auto *R = static_cast<const RuleMatcher *>(B); - return std::tuple(OpcodeOrder[L->getOpcode()], L->getNumOperands()) < - std::tuple(OpcodeOrder[R->getOpcode()], R->getNumOperands()); + return std::make_tuple(OpcodeOrder[L->getOpcode()], L->getNumOperands()) < + std::make_tuple(OpcodeOrder[R->getOpcode()], R->getNumOperands()); }); for (Matcher *Rule : InputRules) diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index e86057422cd78e9255287df047ef16ebbbad23e0..25e302ce1ca46f5a36a1f5cceb7fcfba81901a48 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -30,15 +30,15 @@ /// //===----------------------------------------------------------------------===// -#include "CodeGenDAGPatterns.h" -#include "CodeGenInstruction.h" -#include "CodeGenIntrinsics.h" -#include "CodeGenRegisters.h" -#include "CodeGenTarget.h" -#include "GlobalISelMatchTable.h" -#include "GlobalISelMatchTableExecutorEmitter.h" -#include "InfoByHwMode.h" -#include "SubtargetFeatureInfo.h" +#include "Basic/CodeGenIntrinsics.h" +#include "Common/CodeGenDAGPatterns.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenRegisters.h" +#include "Common/CodeGenTarget.h" +#include "Common/GlobalISel/GlobalISelMatchTable.h" +#include "Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h" +#include "Common/InfoByHwMode.h" +#include "Common/SubtargetFeatureInfo.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGenTypes/LowLevelType.h" #include "llvm/CodeGenTypes/MachineValueType.h" diff --git a/llvm/utils/TableGen/InstrDocsEmitter.cpp b/llvm/utils/TableGen/InstrDocsEmitter.cpp index efabf6bb7ba69fa8ddb4bfd4fe0aa3518542fe62..f948540e18dbd878c27753800b537f9fa1da9c0d 100644 --- a/llvm/utils/TableGen/InstrDocsEmitter.cpp +++ b/llvm/utils/TableGen/InstrDocsEmitter.cpp @@ -18,9 +18,9 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenDAGPatterns.h" -#include "CodeGenInstruction.h" -#include "CodeGenTarget.h" +#include "Common/CodeGenDAGPatterns.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenTarget.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" #include <string> diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp index 2d08447429d95ef76d07516e3cd5bbfbf37d480e..36f8fa1465393835b3f22b1d341db0a82ced14a2 100644 --- a/llvm/utils/TableGen/InstrInfoEmitter.cpp +++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp @@ -11,15 +11,15 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenDAGPatterns.h" -#include "CodeGenInstruction.h" -#include "CodeGenSchedule.h" -#include "CodeGenTarget.h" -#include "PredicateExpander.h" -#include "SequenceToOffsetTable.h" -#include "SubtargetFeatureInfo.h" +#include "Basic/SequenceToOffsetTable.h" +#include "Common/CodeGenDAGPatterns.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenSchedule.h" +#include "Common/CodeGenTarget.h" +#include "Common/PredicateExpander.h" +#include "Common/SubtargetFeatureInfo.h" +#include "Common/Types.h" #include "TableGenBackends.h" -#include "Types.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" diff --git a/llvm/utils/TableGen/IntrinsicEmitter.cpp b/llvm/utils/TableGen/IntrinsicEmitter.cpp index 50a34eac7ca35ace1bf0a3fda74b2a92a1c9bb9e..a7e99fa4c05068c64a65fe62161b91ed9a81c8cd 100644 --- a/llvm/utils/TableGen/IntrinsicEmitter.cpp +++ b/llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -10,8 +10,8 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenIntrinsics.h" -#include "SequenceToOffsetTable.h" +#include "Basic/CodeGenIntrinsics.h" +#include "Basic/SequenceToOffsetTable.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" diff --git a/llvm/utils/TableGen/MacroFusionPredicatorEmitter.cpp b/llvm/utils/TableGen/MacroFusionPredicatorEmitter.cpp index 7f494e532b1f441fab34432ea99b58dd9bd325de..63b827a35177e3643d47339574c0be1e15120c41 100644 --- a/llvm/utils/TableGen/MacroFusionPredicatorEmitter.cpp +++ b/llvm/utils/TableGen/MacroFusionPredicatorEmitter.cpp @@ -38,14 +38,12 @@ // //===---------------------------------------------------------------------===// -#include "CodeGenTarget.h" -#include "PredicateExpander.h" -#include "llvm/ADT/SmallVector.h" +#include "Common/CodeGenTarget.h" +#include "Common/PredicateExpander.h" #include "llvm/Support/Debug.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" -#include <set> #include <vector> using namespace llvm; @@ -61,14 +59,14 @@ class MacroFusionPredicatorEmitter { raw_ostream &OS); void emitMacroFusionImpl(std::vector<Record *> Fusions, PredicateExpander &PE, raw_ostream &OS); - void emitPredicates(std::vector<Record *> &FirstPredicate, + void emitPredicates(std::vector<Record *> &FirstPredicate, bool IsCommutable, PredicateExpander &PE, raw_ostream &OS); - void emitFirstPredicate(Record *SecondPredicate, PredicateExpander &PE, - raw_ostream &OS); - void emitSecondPredicate(Record *SecondPredicate, PredicateExpander &PE, - raw_ostream &OS); - void emitBothPredicate(Record *Predicates, PredicateExpander &PE, - raw_ostream &OS); + void emitFirstPredicate(Record *SecondPredicate, bool IsCommutable, + PredicateExpander &PE, raw_ostream &OS); + void emitSecondPredicate(Record *SecondPredicate, bool IsCommutable, + PredicateExpander &PE, raw_ostream &OS); + void emitBothPredicate(Record *Predicates, bool IsCommutable, + PredicateExpander &PE, raw_ostream &OS); public: MacroFusionPredicatorEmitter(RecordKeeper &R) : Records(R), Target(R) {} @@ -103,15 +101,17 @@ void MacroFusionPredicatorEmitter::emitMacroFusionImpl( for (Record *Fusion : Fusions) { std::vector<Record *> Predicates = Fusion->getValueAsListOfDefs("Predicates"); + bool IsCommutable = Fusion->getValueAsBit("IsCommutable"); OS << "bool is" << Fusion->getName() << "(\n"; OS.indent(4) << "const TargetInstrInfo &TII,\n"; OS.indent(4) << "const TargetSubtargetInfo &STI,\n"; OS.indent(4) << "const MachineInstr *FirstMI,\n"; OS.indent(4) << "const MachineInstr &SecondMI) {\n"; - OS.indent(2) << "auto &MRI = SecondMI.getMF()->getRegInfo();\n"; + OS.indent(2) + << "[[maybe_unused]] auto &MRI = SecondMI.getMF()->getRegInfo();\n"; - emitPredicates(Predicates, PE, OS); + emitPredicates(Predicates, IsCommutable, PE, OS); OS.indent(2) << "return true;\n"; OS << "}\n"; @@ -122,15 +122,16 @@ void MacroFusionPredicatorEmitter::emitMacroFusionImpl( } void MacroFusionPredicatorEmitter::emitPredicates( - std::vector<Record *> &Predicates, PredicateExpander &PE, raw_ostream &OS) { + std::vector<Record *> &Predicates, bool IsCommutable, PredicateExpander &PE, + raw_ostream &OS) { for (Record *Predicate : Predicates) { Record *Target = Predicate->getValueAsDef("Target"); if (Target->getName() == "first_fusion_target") - emitFirstPredicate(Predicate, PE, OS); + emitFirstPredicate(Predicate, IsCommutable, PE, OS); else if (Target->getName() == "second_fusion_target") - emitSecondPredicate(Predicate, PE, OS); + emitSecondPredicate(Predicate, IsCommutable, PE, OS); else if (Target->getName() == "both_fusion_target") - emitBothPredicate(Predicate, PE, OS); + emitBothPredicate(Predicate, IsCommutable, PE, OS); else PrintFatalError(Target->getLoc(), "Unsupported 'FusionTarget': " + Target->getName()); @@ -138,6 +139,7 @@ void MacroFusionPredicatorEmitter::emitPredicates( } void MacroFusionPredicatorEmitter::emitFirstPredicate(Record *Predicate, + bool IsCommutable, PredicateExpander &PE, raw_ostream &OS) { if (Predicate->isSubClassOf("WildcardPred")) { @@ -170,6 +172,7 @@ void MacroFusionPredicatorEmitter::emitFirstPredicate(Record *Predicate, } void MacroFusionPredicatorEmitter::emitSecondPredicate(Record *Predicate, + bool IsCommutable, PredicateExpander &PE, raw_ostream &OS) { if (Predicate->isSubClassOf("FusionPredicateWithMCInstPredicate")) { @@ -182,6 +185,36 @@ void MacroFusionPredicatorEmitter::emitSecondPredicate(Record *Predicate, OS << ")\n"; OS.indent(4) << " return false;\n"; OS.indent(2) << "}\n"; + } else if (Predicate->isSubClassOf("SameReg")) { + int FirstOpIdx = Predicate->getValueAsInt("FirstOpIdx"); + int SecondOpIdx = Predicate->getValueAsInt("SecondOpIdx"); + + OS.indent(2) << "if (!SecondMI.getOperand(" << FirstOpIdx + << ").getReg().isVirtual()) {\n"; + OS.indent(4) << "if (SecondMI.getOperand(" << FirstOpIdx + << ").getReg() != SecondMI.getOperand(" << SecondOpIdx + << ").getReg())"; + + if (IsCommutable) { + OS << " {\n"; + OS.indent(6) << "if (!SecondMI.getDesc().isCommutable())\n"; + OS.indent(6) << " return false;\n"; + + OS.indent(6) + << "unsigned SrcOpIdx1 = " << SecondOpIdx + << ", SrcOpIdx2 = TargetInstrInfo::CommuteAnyOperandIndex;\n"; + OS.indent(6) + << "if (TII.findCommutedOpIndices(SecondMI, SrcOpIdx1, SrcOpIdx2))\n"; + OS.indent(6) + << " if (SecondMI.getOperand(" << FirstOpIdx + << ").getReg() != SecondMI.getOperand(SrcOpIdx2).getReg())\n"; + OS.indent(6) << " return false;\n"; + OS.indent(4) << "}\n"; + } else { + OS << "\n"; + OS.indent(4) << " return false;\n"; + } + OS.indent(2) << "}\n"; } else { PrintFatalError(Predicate->getLoc(), "Unsupported predicate for second instruction: " + @@ -190,13 +223,14 @@ void MacroFusionPredicatorEmitter::emitSecondPredicate(Record *Predicate, } void MacroFusionPredicatorEmitter::emitBothPredicate(Record *Predicate, + bool IsCommutable, PredicateExpander &PE, raw_ostream &OS) { if (Predicate->isSubClassOf("FusionPredicateWithCode")) OS << Predicate->getValueAsString("Predicate"); else if (Predicate->isSubClassOf("BothFusionPredicateWithMCInstPredicate")) { - emitFirstPredicate(Predicate, PE, OS); - emitSecondPredicate(Predicate, PE, OS); + emitFirstPredicate(Predicate, IsCommutable, PE, OS); + emitSecondPredicate(Predicate, IsCommutable, PE, OS); } else if (Predicate->isSubClassOf("TieReg")) { int FirstOpIdx = Predicate->getValueAsInt("FirstOpIdx"); int SecondOpIdx = Predicate->getValueAsInt("SecondOpIdx"); @@ -206,8 +240,28 @@ void MacroFusionPredicatorEmitter::emitBothPredicate(Record *Predicate, << ").isReg() &&\n"; OS.indent(2) << " FirstMI->getOperand(" << FirstOpIdx << ").getReg() == SecondMI.getOperand(" << SecondOpIdx - << ").getReg()))\n"; - OS.indent(2) << " return false;\n"; + << ").getReg()))"; + + if (IsCommutable) { + OS << " {\n"; + OS.indent(4) << "if (!SecondMI.getDesc().isCommutable())\n"; + OS.indent(4) << " return false;\n"; + + OS.indent(4) + << "unsigned SrcOpIdx1 = " << SecondOpIdx + << ", SrcOpIdx2 = TargetInstrInfo::CommuteAnyOperandIndex;\n"; + OS.indent(4) + << "if (TII.findCommutedOpIndices(SecondMI, SrcOpIdx1, SrcOpIdx2))\n"; + OS.indent(4) + << " if (FirstMI->getOperand(" << FirstOpIdx + << ").getReg() != SecondMI.getOperand(SrcOpIdx2).getReg())\n"; + OS.indent(4) << " return false;\n"; + OS.indent(2) << "}"; + } else { + OS << "\n"; + OS.indent(2) << " return false;"; + } + OS << "\n"; } else PrintFatalError(Predicate->getLoc(), "Unsupported predicate for both instruction: " + diff --git a/llvm/utils/TableGen/OptParserEmitter.cpp b/llvm/utils/TableGen/OptParserEmitter.cpp index c25f6c59cab383362e155a35304ee7d946661e91..6334af53f88f6a01cd8e0e060bd12dc300d7c16d 100644 --- a/llvm/utils/TableGen/OptParserEmitter.cpp +++ b/llvm/utils/TableGen/OptParserEmitter.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "OptEmitter.h" +#include "Common/OptEmitter.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" diff --git a/llvm/utils/TableGen/OptRSTEmitter.cpp b/llvm/utils/TableGen/OptRSTEmitter.cpp index 5a7f079dc1681cb4a06588bea2b0ea83f7bde188..75b7cbdf298879ecb5bee223b9605978fdb90304 100644 --- a/llvm/utils/TableGen/OptRSTEmitter.cpp +++ b/llvm/utils/TableGen/OptRSTEmitter.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "OptEmitter.h" +#include "Common/OptEmitter.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/TableGen/Record.h" diff --git a/llvm/utils/TableGen/PseudoLoweringEmitter.cpp b/llvm/utils/TableGen/PseudoLoweringEmitter.cpp index 7f692f29192d9a405618a9b647a3ee88febc3600..01cfd4a1d982903fb3a907df42280edcc75420af 100644 --- a/llvm/utils/TableGen/PseudoLoweringEmitter.cpp +++ b/llvm/utils/TableGen/PseudoLoweringEmitter.cpp @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenInstruction.h" -#include "CodeGenTarget.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenTarget.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" diff --git a/llvm/utils/TableGen/RegisterBankEmitter.cpp b/llvm/utils/TableGen/RegisterBankEmitter.cpp index 8b59411c5bc3c08e1a5c2bf0911b53f19d4ccd1b..5546e727af3847acd4cddd266e20038f14aeb5e8 100644 --- a/llvm/utils/TableGen/RegisterBankEmitter.cpp +++ b/llvm/utils/TableGen/RegisterBankEmitter.cpp @@ -11,9 +11,9 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenRegisters.h" -#include "CodeGenTarget.h" -#include "InfoByHwMode.h" +#include "Common/CodeGenRegisters.h" +#include "Common/CodeGenTarget.h" +#include "Common/InfoByHwMode.h" #include "llvm/ADT/BitVector.h" #include "llvm/Support/Debug.h" #include "llvm/TableGen/Error.h" diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp index d074e31c624588b41a2ce9f183816bf47316984e..ee8830edeedbbe5aed6409a46d4937c1a6c14106 100644 --- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp +++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp @@ -12,12 +12,12 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenHwModes.h" -#include "CodeGenRegisters.h" -#include "CodeGenTarget.h" -#include "InfoByHwMode.h" -#include "SequenceToOffsetTable.h" -#include "Types.h" +#include "Basic/SequenceToOffsetTable.h" +#include "Common/CodeGenHwModes.h" +#include "Common/CodeGenRegisters.h" +#include "Common/CodeGenTarget.h" +#include "Common/InfoByHwMode.h" +#include "Common/Types.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" @@ -955,16 +955,6 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, SubRegIdxSeqs.emit(OS, printSubRegIndex); OS << "};\n\n"; - // Emit the table of sub-register index sizes. - OS << "extern const MCRegisterInfo::SubRegCoveredBits " << TargetName - << "SubRegIdxRanges[] = {\n"; - OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n"; - for (const auto &Idx : SubRegIndices) { - OS << " { " << Idx.Offset << ", " << Idx.Size << " },\t// " - << Idx.getName() << "\n"; - } - OS << "};\n\n"; - // Emit the string table. RegStrings.layout(); RegStrings.emitStringLiteralDef(OS, Twine("extern const char ") + TargetName + @@ -1101,8 +1091,7 @@ void RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, << TargetName << "LaneMaskLists, " << TargetName << "RegStrings, " << TargetName << "RegClassStrings, " << TargetName << "SubRegIdxLists, " << (std::distance(SubRegIndices.begin(), SubRegIndices.end()) + 1) << ",\n" - << TargetName << "SubRegIdxRanges, " << TargetName - << "RegEncodingTable);\n\n"; + << TargetName << "RegEncodingTable);\n\n"; EmitRegMapping(OS, Regs, false); @@ -1253,6 +1242,19 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << "\" };\n\n"; + // Emit the table of sub-register index sizes. + OS << "static const TargetRegisterInfo::SubRegCoveredBits " + "SubRegIdxRangeTable[] = {\n"; + for (unsigned M = 0; M < NumModes; ++M) { + OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n"; + for (const auto &Idx : SubRegIndices) { + const SubRegRange &Range = Idx.Range.get(M); + OS << " { " << Range.Offset << ", " << Range.Size << " },\t// " + << Idx.getName() << "\n"; + } + } + OS << "};\n\n"; + // Emit SubRegIndex lane masks, including 0. OS << "\nstatic const LaneBitmask SubRegIndexLaneMaskTable[] = {\n " "LaneBitmask::getAll(),\n"; @@ -1634,8 +1636,6 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "extern const char " << TargetName << "RegClassStrings[];\n"; OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n"; OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n"; - OS << "extern const MCRegisterInfo::SubRegCoveredBits " << TargetName - << "SubRegIdxRanges[];\n"; OS << "extern const uint16_t " << TargetName << "RegEncodingTable[];\n"; EmitRegMappingTables(OS, Regs, true); @@ -1646,7 +1646,8 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, " unsigned PC, unsigned HwMode)\n" << " : TargetRegisterInfo(&" << TargetName << "RegInfoDesc" << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() << ",\n" - << " SubRegIndexNameTable, SubRegIndexLaneMaskTable,\n" + << " SubRegIndexNameTable, SubRegIdxRangeTable, " + "SubRegIndexLaneMaskTable,\n" << " "; printMask(OS, RegBank.CoveringLanes); OS << ", RegClassInfos, VTLists, HwMode) {\n" @@ -1661,7 +1662,6 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << " " << TargetName << "RegClassStrings,\n" << " " << TargetName << "SubRegIdxLists,\n" << " " << SubRegIndicesSize + 1 << ",\n" - << " " << TargetName << "SubRegIdxRanges,\n" << " " << TargetName << "RegEncodingTable);\n\n"; EmitRegMapping(OS, Regs, true); @@ -1867,7 +1867,13 @@ void RegisterInfoEmitter::debugDump(raw_ostream &OS) { OS << "SubRegIndex " << SRI.getName() << ":\n"; OS << "\tLaneMask: " << PrintLaneMask(SRI.LaneMask) << '\n'; OS << "\tAllSuperRegsCovered: " << SRI.AllSuperRegsCovered << '\n'; - OS << "\tOffset, Size: " << SRI.Offset << ", " << SRI.Size << '\n'; + OS << "\tOffset: {"; + for (unsigned M = 0; M != NumModes; ++M) + OS << ' ' << getModeName(M) << ':' << SRI.Range.get(M).Offset; + OS << " }\n\tSize: {"; + for (unsigned M = 0; M != NumModes; ++M) + OS << ' ' << getModeName(M) << ':' << SRI.Range.get(M).Size; + OS << " }\n"; } for (const CodeGenRegister &R : RegBank.getRegisters()) { diff --git a/llvm/utils/TableGen/SearchableTableEmitter.cpp b/llvm/utils/TableGen/SearchableTableEmitter.cpp index 51f18f360ed3110c0435e11edbd772b7d4f9ced9..48ee23db957defb94caadd4ac7a9472a1a58d2cb 100644 --- a/llvm/utils/TableGen/SearchableTableEmitter.cpp +++ b/llvm/utils/TableGen/SearchableTableEmitter.cpp @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenIntrinsics.h" -#include "CodeGenTarget.h" +#include "Basic/CodeGenIntrinsics.h" +#include "Common/CodeGenTarget.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp index d350d7de139f6e7e729f9c0a6d2206b39040a7d8..2e2c57b802ee54c49bc789d72f26eb4949fbbeac 100644 --- a/llvm/utils/TableGen/SubtargetEmitter.cpp +++ b/llvm/utils/TableGen/SubtargetEmitter.cpp @@ -10,10 +10,10 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenHwModes.h" -#include "CodeGenSchedule.h" -#include "CodeGenTarget.h" -#include "PredicateExpander.h" +#include "Common/CodeGenHwModes.h" +#include "Common/CodeGenSchedule.h" +#include "Common/CodeGenTarget.h" +#include "Common/PredicateExpander.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringExtras.h" diff --git a/llvm/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp b/llvm/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp index 928129f24fcb493c92a805b1584a5d7a6ca4ae11..e9436ab16e448ab3ba6193bddc4d0a839525fb79 100644 --- a/llvm/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp +++ b/llvm/utils/TableGen/WebAssemblyDisassemblerEmitter.cpp @@ -14,7 +14,7 @@ //===----------------------------------------------------------------------===// #include "WebAssemblyDisassemblerEmitter.h" -#include "CodeGenInstruction.h" +#include "Common/CodeGenInstruction.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Record.h" diff --git a/llvm/utils/TableGen/X86CompressEVEXTablesEmitter.cpp b/llvm/utils/TableGen/X86CompressEVEXTablesEmitter.cpp index 0a9abbfe186ed6f9eab3d88db15b9bb1a0554a8a..c721502a395f097d5d13ecad740ccadff4b1b8a6 100644 --- a/llvm/utils/TableGen/X86CompressEVEXTablesEmitter.cpp +++ b/llvm/utils/TableGen/X86CompressEVEXTablesEmitter.cpp @@ -11,8 +11,8 @@ /// //===----------------------------------------------------------------------===// -#include "CodeGenInstruction.h" -#include "CodeGenTarget.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenTarget.h" #include "X86RecognizableInstr.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" diff --git a/llvm/utils/TableGen/X86FoldTablesEmitter.cpp b/llvm/utils/TableGen/X86FoldTablesEmitter.cpp index 1319042e48d060ca360ce516a70cd6ee30979649..5871e678b16ebde93b39860378b7864f20494926 100644 --- a/llvm/utils/TableGen/X86FoldTablesEmitter.cpp +++ b/llvm/utils/TableGen/X86FoldTablesEmitter.cpp @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenInstruction.h" -#include "CodeGenTarget.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenTarget.h" #include "X86RecognizableInstr.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/FormattedStream.h" diff --git a/llvm/utils/TableGen/X86ManualFoldTables.def b/llvm/utils/TableGen/X86ManualFoldTables.def index 8e6cb4a7bd879832cb5c9c6419728a5447e17123..2ebd92883c07192ea85009dd063518b77a24c80c 100644 --- a/llvm/utils/TableGen/X86ManualFoldTables.def +++ b/llvm/utils/TableGen/X86ManualFoldTables.def @@ -227,6 +227,13 @@ NOFOLD(MMX_MOVQ64rr_REV) NOFOLD(INSERTPSrr) NOFOLD(VINSERTPSZrr) NOFOLD(VINSERTPSrr) +// Memory faults are suppressed for CFCMOV with memory operand. +NOFOLD(CFCMOV16rr_REV) +NOFOLD(CFCMOV32rr_REV) +NOFOLD(CFCMOV64rr_REV) +NOFOLD(CFCMOV16rr_ND) +NOFOLD(CFCMOV32rr_ND) +NOFOLD(CFCMOV64rr_ND) #undef NOFOLD #ifndef ENTRY diff --git a/llvm/utils/TableGen/X86MnemonicTables.cpp b/llvm/utils/TableGen/X86MnemonicTables.cpp index aeafee15746235d79e018b55a50285f948436285..d9ceed40f7c70deea0ddba97d04aab45df45cbcb 100644 --- a/llvm/utils/TableGen/X86MnemonicTables.cpp +++ b/llvm/utils/TableGen/X86MnemonicTables.cpp @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenInstruction.h" -#include "CodeGenTarget.h" +#include "Common/CodeGenInstruction.h" +#include "Common/CodeGenTarget.h" #include "X86RecognizableInstr.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" diff --git a/llvm/utils/TableGen/X86RecognizableInstr.cpp b/llvm/utils/TableGen/X86RecognizableInstr.cpp index 39006a40daeb6ac7763c10101d336a9de1d846f0..a2bc037b690c6f878c1856631a0a89d5f395d40b 100644 --- a/llvm/utils/TableGen/X86RecognizableInstr.cpp +++ b/llvm/utils/TableGen/X86RecognizableInstr.cpp @@ -540,6 +540,13 @@ void RecognizableInstr::emitInstructionSpecifier() { HANDLE_OPERAND(relocation) HANDLE_OPERAND(opcodeModifier) break; + case X86Local::MRMDestRegCC: + assert(numPhysicalOperands == 3 && + "Unexpected number of operands for MRMDestRegCC"); + HANDLE_OPERAND(rmRegister) + HANDLE_OPERAND(roRegister) + HANDLE_OPERAND(opcodeModifier) + break; case X86Local::MRMDestReg: // Operand 1 is a register operand in the R/M field. // - In AVX512 there may be a mask operand here - @@ -566,6 +573,13 @@ void RecognizableInstr::emitInstructionSpecifier() { HANDLE_OPTIONAL(immediate) HANDLE_OPTIONAL(immediate) break; + case X86Local::MRMDestMemCC: + assert(numPhysicalOperands == 3 && + "Unexpected number of operands for MRMDestMemCC"); + HANDLE_OPERAND(memory) + HANDLE_OPERAND(roRegister) + HANDLE_OPERAND(opcodeModifier) + break; case X86Local::MRMDestMem4VOp3CC: // Operand 1 is a register operand in the Reg/Opcode field. // Operand 2 is a register operand in the R/M field. @@ -650,8 +664,10 @@ void RecognizableInstr::emitInstructionSpecifier() { HANDLE_OPTIONAL(immediate) break; case X86Local::MRMSrcRegCC: - assert(numPhysicalOperands == 3 && + assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && "Unexpected number of operands for MRMSrcRegCC"); + if (IsND) + HANDLE_OPERAND(vvvvRegister) HANDLE_OPERAND(roRegister) HANDLE_OPERAND(rmRegister) HANDLE_OPERAND(opcodeModifier) @@ -700,8 +716,10 @@ void RecognizableInstr::emitInstructionSpecifier() { HANDLE_OPTIONAL(immediate) break; case X86Local::MRMSrcMemCC: - assert(numPhysicalOperands == 3 && + assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && "Unexpected number of operands for MRMSrcMemCC"); + if (IsND) + HANDLE_OPERAND(vvvvRegister) HANDLE_OPERAND(roRegister) HANDLE_OPERAND(memory) HANDLE_OPERAND(opcodeModifier) @@ -871,6 +889,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { filter = std::make_unique<DumbFilter>(); break; case X86Local::MRMDestReg: + case X86Local::MRMDestRegCC: case X86Local::MRMSrcReg: case X86Local::MRMSrcReg4VOp3: case X86Local::MRMSrcRegOp4: @@ -880,6 +899,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { filter = std::make_unique<ModFilter>(true); break; case X86Local::MRMDestMem: + case X86Local::MRMDestMemCC: case X86Local::MRMDestMem4VOp3CC: case X86Local::MRMDestMemFSIB: case X86Local::MRMSrcMem: @@ -950,6 +970,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { if (Form == X86Local::AddRegFrm || Form == X86Local::MRMSrcRegCC || Form == X86Local::MRMSrcMemCC || Form == X86Local::MRMXrCC || Form == X86Local::MRMXmCC || Form == X86Local::AddCCFrm || + Form == X86Local::MRMDestRegCC || Form == X86Local::MRMDestMemCC || Form == X86Local::MRMDestMem4VOp3CC) { uint8_t Count = Form == X86Local::AddRegFrm ? 8 : 16; assert(((opcodeToSet % Count) == 0) && "ADDREG_FRM opcode not aligned"); diff --git a/llvm/utils/TableGen/X86RecognizableInstr.h b/llvm/utils/TableGen/X86RecognizableInstr.h index ad319b3f28b72337dc831c9c37463c39ffdf55ca..12fb41750cb3f380a73e1cd7cc71a630ced5b8b2 100644 --- a/llvm/utils/TableGen/X86RecognizableInstr.h +++ b/llvm/utils/TableGen/X86RecognizableInstr.h @@ -16,7 +16,7 @@ #ifndef LLVM_UTILS_TABLEGEN_X86RECOGNIZABLEINSTR_H #define LLVM_UTILS_TABLEGEN_X86RECOGNIZABLEINSTR_H -#include "CodeGenInstruction.h" +#include "Common/CodeGenInstruction.h" #include "llvm/Support/X86DisassemblerDecoderCommon.h" #include <cstdint> #include <string> @@ -106,6 +106,8 @@ enum { RawFrmImm16 = 8, AddCCFrm = 9, PrefixByte = 10, + MRMDestRegCC = 18, + MRMDestMemCC = 19, MRMDestMem4VOp3CC = 20, MRMr0 = 21, MRMSrcMemFSIB = 22, diff --git a/llvm/utils/bisect-skip-count b/llvm/utils/bisect-skip-count index efdd2c937e1529656bee809f75053ef0228316a1..1a64eba381dc8aff1ddb9af8f3bb0d9f56a75716 100755 --- a/llvm/utils/bisect-skip-count +++ b/llvm/utils/bisect-skip-count @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # This script is used to bisect skip and count arguments for --debug-counter. # It is similar to bisect, except it understands how to increase skip and decrease count # diff --git a/llvm/utils/git/code-format-helper.py b/llvm/utils/git/code-format-helper.py index 1113bf02570b94fbffc23a377ee365ba26084ece..f1207026704e887f188b17e63ab92693d0d6d1b9 100755 --- a/llvm/utils/git/code-format-helper.py +++ b/llvm/utils/git/code-format-helper.py @@ -44,6 +44,7 @@ class FormatArgs: token: str = None verbose: bool = True issue_number: int = 0 + write_comment_to_file: bool = False def __init__(self, args: argparse.Namespace = None) -> None: if not args is None: @@ -53,12 +54,14 @@ class FormatArgs: self.token = args.token self.changed_files = args.changed_files self.issue_number = args.issue_number + self.write_comment_to_file = args.write_comment_to_file class FormatHelper: COMMENT_TAG = "<!--LLVM CODE FORMAT COMMENT: {fmt}-->" name: str friendly_name: str + comment: dict = None @property def comment_tag(self) -> str: @@ -119,6 +122,14 @@ View the diff from {self.name} here. comment_text = self.comment_tag + "\n\n" + comment_text existing_comment = self.find_comment(pr) + + if args.write_comment_to_file: + if create_new or existing_comment: + self.comment = {"body": comment_text} + if existing_comment: + self.comment["id"] = existing_comment.id + return + if existing_comment: existing_comment.edit(comment_text) elif create_new: @@ -310,6 +321,8 @@ def hook_main(): if fmt.has_tool(): if not fmt.run(args.changed_files, args): failed_fmts.append(fmt.name) + if fmt.comment: + comments.append(fmt.comment) else: print(f"Couldn't find {fmt.name}, can't check " + fmt.friendly_name.lower()) @@ -350,6 +363,11 @@ if __name__ == "__main__": type=str, help="Comma separated list of files that has been changed", ) + parser.add_argument( + "--write-comment-to-file", + action="store_true", + help="Don't post comments on the PR, instead write the comments and metadata a file called 'comment'", + ) args = FormatArgs(parser.parse_args()) @@ -358,9 +376,18 @@ if __name__ == "__main__": changed_files = args.changed_files.split(",") failed_formatters = [] + comments = [] for fmt in ALL_FORMATTERS: if not fmt.run(changed_files, args): failed_formatters.append(fmt.name) + if fmt.comment: + comments.append(fmt.comment) + + if len(comments): + with open("comments", "w") as f: + import json + + json.dump(comments, f) if len(failed_formatters) > 0: print(f"error: some formatters failed: {' '.join(failed_formatters)}") diff --git a/llvm/utils/git/github-automation.py b/llvm/utils/git/github-automation.py index b21f14eca4450ac48b370a3b58e987567a54a475..1b5141e42594b16c1f64f77677141d6dd4d1c729 100755 --- a/llvm/utils/git/github-automation.py +++ b/llvm/utils/git/github-automation.py @@ -24,18 +24,19 @@ Hi! This issue may be a good introductory issue for people new to working on LLVM. If you would like to work on this issue, your first steps are: -1. In the comments of the issue, request for it to be assigned to you. -2. Fix the issue locally. -3. [Run the test suite](https://llvm.org/docs/TestingGuide.html#unit-and-regression-tests) locally. Remember that the subdirectories under `test/` create fine-grained testing targets, so you can e.g. use `make check-clang-ast` to only run Clang's AST tests. -4. Create a Git commit. -5. Run [`git clang-format HEAD~1`](https://clang.llvm.org/docs/ClangFormat.html#git-integration) to format your changes. -6. Open a [pull request](https://github.com/llvm/llvm-project/pulls) to the [upstream repository](https://github.com/llvm/llvm-project) on GitHub. Detailed instructions can be found [in GitHub's documentation](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request). +1. Check that no other contributor has already been assigned to this issue. If you believe that no one is actually working on it despite an assignment, ping the person. After one week without a response, the assignee may be changed. +1. In the comments of this issue, request for it to be assigned to you, or just create a [pull request](https://github.com/llvm/llvm-project/pulls) after following the steps below. [Mention](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) this issue in the description of the pull request. +1. Fix the issue locally. +1. [Run the test suite](https://llvm.org/docs/TestingGuide.html#unit-and-regression-tests) locally. Remember that the subdirectories under `test/` create fine-grained testing targets, so you can e.g. use `make check-clang-ast` to only run Clang's AST tests. +1. Create a Git commit. +1. Run [`git clang-format HEAD~1`](https://clang.llvm.org/docs/ClangFormat.html#git-integration) to format your changes. +1. Open a [pull request](https://github.com/llvm/llvm-project/pulls) to the [upstream repository](https://github.com/llvm/llvm-project) on GitHub. Detailed instructions can be found [in GitHub's documentation](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request). [Mention](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) this issue in the description of the pull request. If you have any further questions about this issue, don't hesitate to ask via a comment in the thread below. """ -def _get_curent_team(team_name, teams) -> Optional[github.Team.Team]: +def _get_current_team(team_name, teams) -> Optional[github.Team.Team]: for team in teams: if team_name == team.name.lower(): return team @@ -69,7 +70,7 @@ class IssueSubscriber: self._team_name = "issue-subscribers-{}".format(label_name).lower() def run(self) -> bool: - team = _get_curent_team(self.team_name, self.org.get_teams()) + team = _get_current_team(self.team_name, self.org.get_teams()) if not team: print(f"couldn't find team named {self.team_name}") return False @@ -124,7 +125,7 @@ class PRSubscriber: def run(self) -> bool: patch = None - team = _get_curent_team(self.team_name, self.org.get_teams()) + team = _get_current_team(self.team_name, self.org.get_teams()) if not team: print(f"couldn't find team named {self.team_name}") return False @@ -200,7 +201,7 @@ Author: {self.pr.user.name} ({self.pr.user.login}) ) return True - def _get_curent_team(self) -> Optional[github.Team.Team]: + def _get_current_team(self) -> Optional[github.Team.Team]: for team in self.org.get_teams(): if self.team_name == team.name.lower(): return team @@ -280,7 +281,7 @@ class PRBuildbotInformation: @{self.author} Congratulations on having your first Pull Request (PR) merged into the LLVM Project! Your changes will be combined with recent changes from other authors, then tested -by our [build bots](https://lab.llvm.org/buildbot/). If there is a problem with a build, you may recieve a report in an email or a comment on this PR. +by our [build bots](https://lab.llvm.org/buildbot/). If there is a problem with a build, you may receive a report in an email or a comment on this PR. Please check whether problems have been caused by your change specifically, as the builds can include changes from many authors. It is not uncommon for your @@ -638,7 +639,7 @@ class ReleaseWorkflow: parser = argparse.ArgumentParser() parser.add_argument( - "--token", type=str, required=True, help="GitHub authentiation token" + "--token", type=str, required=True, help="GitHub authentication token" ) parser.add_argument( "--repo", @@ -668,7 +669,7 @@ release_workflow_parser.add_argument( "--llvm-project-dir", type=str, default=".", - help="directory containing the llvm-project checout", + help="directory containing the llvm-project checkout", ) release_workflow_parser.add_argument( "--issue-number", type=int, required=True, help="The issue number to update" diff --git a/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/bugprone/BUILD.gn b/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/bugprone/BUILD.gn index 3b41f9b4007f34c9970ff01c37ab52a9e2dfc889..cd90c7752e1642fa0ce6c790f6066747065081de 100644 --- a/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/bugprone/BUILD.gn +++ b/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/bugprone/BUILD.gn @@ -81,6 +81,7 @@ static_library("bugprone") { "SuspiciousReallocUsageCheck.cpp", "SuspiciousSemicolonCheck.cpp", "SuspiciousStringCompareCheck.cpp", + "SuspiciousStringviewDataUsageCheck.cpp", "SwappedArgumentsCheck.cpp", "SwitchMissingDefaultCaseCheck.cpp", "TerminatingContinueCheck.cpp", diff --git a/llvm/utils/gn/secondary/clang/include/clang/Basic/BUILD.gn b/llvm/utils/gn/secondary/clang/include/clang/Basic/BUILD.gn index d484ff9cddd91c4ac62dfed983e812a12432cc63..b18b109dcff56d11956ba4e1e4d284d379c5f50b 100644 --- a/llvm/utils/gn/secondary/clang/include/clang/Basic/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/include/clang/Basic/BUILD.gn @@ -25,6 +25,7 @@ diag_groups = [ "CrossTU", "Driver", "Frontend", + "InstallAPI", "Lex", "Parse", "Refactoring", diff --git a/llvm/utils/gn/secondary/clang/lib/Analysis/FlowSensitive/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/Analysis/FlowSensitive/BUILD.gn index e69567c2d9c652aa42e88ce054e3ea9d42d5d430..04f20211b3c7107f940b449303e9975279bd68bf 100644 --- a/llvm/utils/gn/secondary/clang/lib/Analysis/FlowSensitive/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/lib/Analysis/FlowSensitive/BUILD.gn @@ -23,8 +23,8 @@ static_library("FlowSensitive") { target_gen_dir, ] sources = [ + "AdornedCFG.cpp", "Arena.cpp", - "ControlFlowContext.cpp", "DataflowAnalysisContext.cpp", "DataflowEnvironment.cpp", "DebugSupport.cpp", diff --git a/llvm/utils/gn/secondary/clang/lib/Headers/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/Headers/BUILD.gn index 7c00aaffdc1b91c4be6c4ed22b69d84815af9c79..25fcdc4d0015126511f1caaa88fa3569341dd2ae 100644 --- a/llvm/utils/gn/secondary/clang/lib/Headers/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/lib/Headers/BUILD.gn @@ -205,6 +205,7 @@ copy("Headers") { "ia32intrin.h", "immintrin.h", "intrin.h", + "intrin0.h", "inttypes.h", "invpcidintrin.h", "iso646.h", @@ -256,6 +257,7 @@ copy("Headers") { "ppc_wrappers/xmmintrin.h", "prfchiintrin.h", "prfchwintrin.h", + "ptrauth.h", "ptwriteintrin.h", "raointintrin.h", "rdpruintrin.h", @@ -309,6 +311,7 @@ copy("Headers") { "xsaveoptintrin.h", "xsavesintrin.h", "xtestintrin.h", + "yvals_core.h", ] outputs = [ "$clang_resource_dir/include/{{source_target_relative}}" ] } diff --git a/llvm/utils/gn/secondary/clang/lib/InstallAPI/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/InstallAPI/BUILD.gn index 5e533bf23ec4753574be67780de3368b9bf3d324..2f43a915b2a6641b733cdfd1033eb80cf2f14d8c 100644 --- a/llvm/utils/gn/secondary/clang/lib/InstallAPI/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/lib/InstallAPI/BUILD.gn @@ -3,10 +3,12 @@ static_library("InstallAPI") { configs += [ "//llvm/utils/gn/build:clang_code" ] deps = [ "//clang/lib/AST", + "//llvm/lib/Demangle", "//llvm/lib/Support", "//llvm/lib/TextAPI", ] sources = [ + "DylibVerifier.cpp", "FileList.cpp", "Frontend.cpp", "HeaderFile.cpp", diff --git a/llvm/utils/gn/secondary/clang/tools/clang-installapi/BUILD.gn b/llvm/utils/gn/secondary/clang/tools/clang-installapi/BUILD.gn index 4f6895181f552af29385893035845c15468259ac..89f0107686f91d4e0cbce1f5d83b7e14cca2e6ee 100644 --- a/llvm/utils/gn/secondary/clang/tools/clang-installapi/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/tools/clang-installapi/BUILD.gn @@ -1,8 +1,15 @@ +import("//llvm/utils/TableGen/tablegen.gni") import("//llvm/utils/gn/build/driver_executable.gni") +tablegen("InstallAPIOpts") { + visibility = [ ":clang-installapi" ] + args = [ "-gen-opt-parser-defs" ] +} + driver_executable("clang-installapi") { configs += [ "//llvm/utils/gn/build:clang_code" ] deps = [ + ":InstallAPIOpts", "//clang/lib/Driver", "//clang/lib/Frontend", "//clang/lib/InstallAPI", @@ -10,6 +17,7 @@ driver_executable("clang-installapi") { "//llvm/lib/Support", "//llvm/lib/TargetParser", "//llvm/lib/TextAPI", + "//llvm/lib/TextAPI/BinaryReader", ] sources = [ "ClangInstallAPI.cpp", diff --git a/llvm/utils/gn/secondary/clang/unittests/Interpreter/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/Interpreter/BUILD.gn index c2999a67f58a9b177a140f35f89159cd6a1c7235..103954e5756d34d63a832f8e62e10aee9596902a 100644 --- a/llvm/utils/gn/secondary/clang/unittests/Interpreter/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/unittests/Interpreter/BUILD.gn @@ -8,6 +8,7 @@ unittest("ClangReplInterpreterTests") { "//clang/lib/Frontend", "//clang/lib/Interpreter", "//llvm/lib/IR", + "//llvm/lib/Target:TargetsToBuild", "//llvm/lib/TargetParser", "//llvm/lib/Testing/Support", ] diff --git a/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn index 01c2b6ced3366f3462adcc27f61aae9deff0f1cf..adaf6c476dfeccf97f8205e8ded4d808b69a566b 100644 --- a/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/unittests/StaticAnalyzer/BUILD.gn @@ -19,6 +19,8 @@ unittest("StaticAnalysisTests") { "CallEventTest.cpp", "ConflictingEvalCallsTest.cpp", "FalsePositiveRefutationBRVisitorTest.cpp", + "IsCLibraryFunctionTest.cpp", + "MemRegionDescriptiveNameTest.cpp", "NoStateChangeFuncVisitorTest.cpp", "ParamRegionTest.cpp", "RangeSetTest.cpp", diff --git a/llvm/utils/gn/secondary/compiler-rt/lib/scudo/standalone/BUILD.gn b/llvm/utils/gn/secondary/compiler-rt/lib/scudo/standalone/BUILD.gn index 02a9595e2654beb36a9bf93c3f64847e4e4f3962..c8347f6336d73f003695696e2c964b326574497d 100644 --- a/llvm/utils/gn/secondary/compiler-rt/lib/scudo/standalone/BUILD.gn +++ b/llvm/utils/gn/secondary/compiler-rt/lib/scudo/standalone/BUILD.gn @@ -12,6 +12,7 @@ source_set("sources") { sources = [ "allocator_common.h", "allocator_config.h", + "allocator_config_wrapper.h", "atomic_helpers.h", "bytemap.h", "checksum.cpp", diff --git a/llvm/utils/gn/secondary/compiler-rt/lib/scudo/standalone/tests/BUILD.gn b/llvm/utils/gn/secondary/compiler-rt/lib/scudo/standalone/tests/BUILD.gn index f69f1c413b47da0e41e8c6db3bde54c5010f5622..2ddc3abe47f742fdd7fa522d617163336b72752f 100644 --- a/llvm/utils/gn/secondary/compiler-rt/lib/scudo/standalone/tests/BUILD.gn +++ b/llvm/utils/gn/secondary/compiler-rt/lib/scudo/standalone/tests/BUILD.gn @@ -8,6 +8,7 @@ unittest("ScudoUnitTest") { cflags = test_cflags deps = [ "//compiler-rt/lib/scudo/standalone:sources" ] sources = [ + "allocator_config_test.cpp", "atomic_test.cpp", "bytemap_test.cpp", "checksum_test.cpp", diff --git a/llvm/utils/gn/secondary/compiler-rt/test/BUILD.gn b/llvm/utils/gn/secondary/compiler-rt/test/BUILD.gn index efb324713cfeaf979056bdf3c3efe1c7942ccf43..d533e79e6374df2e20391b3000acfcaf8534a5c5 100644 --- a/llvm/utils/gn/secondary/compiler-rt/test/BUILD.gn +++ b/llvm/utils/gn/secondary/compiler-rt/test/BUILD.gn @@ -65,6 +65,7 @@ write_cmake_config("lit_common_configured") { "SANITIZER_USE_STATIC_CXX_ABI_PYBOOL=False", "SANITIZER_USE_STATIC_LLVM_UNWINDER_PYBOOL=False", "COMPILER_RT_HAS_AARCH64_SME_PYBOOL=False", + "COMPILER_RT_DARWIN_LINKER_VERSION=", "COMPILER_RT_HAS_LLD_PYBOOL=True", "COMPILER_RT_HAS_GWP_ASAN_PYBOOL=False", "HAVE_RPC_XDR_H=0", diff --git a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn index f3d7b1bceb4d518ce5bd4b3617ce5fc2491e6da9..8a2ab18bf953a8c6d3d6431046fccf965337e68c 100644 --- a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn +++ b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn @@ -287,6 +287,7 @@ if (current_toolchain == default_toolchain) { "__algorithm/shift_right.h", "__algorithm/shuffle.h", "__algorithm/sift_down.h", + "__algorithm/simd_utils.h", "__algorithm/sort.h", "__algorithm/sort_heap.h", "__algorithm/stable_partition.h", @@ -499,22 +500,27 @@ if (current_toolchain == default_toolchain) { "__fwd/array.h", "__fwd/bit_reference.h", "__fwd/complex.h", + "__fwd/deque.h", "__fwd/format.h", "__fwd/fstream.h", "__fwd/functional.h", "__fwd/ios.h", "__fwd/istream.h", "__fwd/mdspan.h", + "__fwd/memory.h", "__fwd/memory_resource.h", "__fwd/ostream.h", "__fwd/pair.h", + "__fwd/queue.h", "__fwd/span.h", "__fwd/sstream.h", + "__fwd/stack.h", "__fwd/streambuf.h", "__fwd/string.h", "__fwd/string_view.h", "__fwd/subrange.h", "__fwd/tuple.h", + "__fwd/vector.h", "__hash_table", "__ios/fpos.h", "__iterator/access.h", @@ -824,10 +830,7 @@ if (current_toolchain == default_toolchain) { "__type_traits/is_constant_evaluated.h", "__type_traits/is_constructible.h", "__type_traits/is_convertible.h", - "__type_traits/is_copy_assignable.h", - "__type_traits/is_copy_constructible.h", "__type_traits/is_core_convertible.h", - "__type_traits/is_default_constructible.h", "__type_traits/is_destructible.h", "__type_traits/is_empty.h", "__type_traits/is_enum.h", @@ -843,17 +846,10 @@ if (current_toolchain == default_toolchain) { "__type_traits/is_member_function_pointer.h", "__type_traits/is_member_object_pointer.h", "__type_traits/is_member_pointer.h", - "__type_traits/is_move_assignable.h", - "__type_traits/is_move_constructible.h", "__type_traits/is_nothrow_assignable.h", "__type_traits/is_nothrow_constructible.h", "__type_traits/is_nothrow_convertible.h", - "__type_traits/is_nothrow_copy_assignable.h", - "__type_traits/is_nothrow_copy_constructible.h", - "__type_traits/is_nothrow_default_constructible.h", "__type_traits/is_nothrow_destructible.h", - "__type_traits/is_nothrow_move_assignable.h", - "__type_traits/is_nothrow_move_constructible.h", "__type_traits/is_null_pointer.h", "__type_traits/is_object.h", "__type_traits/is_pod.h", @@ -874,14 +870,9 @@ if (current_toolchain == default_toolchain) { "__type_traits/is_trivial.h", "__type_traits/is_trivially_assignable.h", "__type_traits/is_trivially_constructible.h", - "__type_traits/is_trivially_copy_assignable.h", - "__type_traits/is_trivially_copy_constructible.h", "__type_traits/is_trivially_copyable.h", - "__type_traits/is_trivially_default_constructible.h", "__type_traits/is_trivially_destructible.h", "__type_traits/is_trivially_lexicographically_comparable.h", - "__type_traits/is_trivially_move_assignable.h", - "__type_traits/is_trivially_move_constructible.h", "__type_traits/is_trivially_relocatable.h", "__type_traits/is_unbounded_array.h", "__type_traits/is_union.h", diff --git a/llvm/utils/gn/secondary/lldb/source/Host/BUILD.gn b/llvm/utils/gn/secondary/lldb/source/Host/BUILD.gn index 39c3efaa040a54c072310aa04d1bdef08aa954e7..7c9edfb016d7aa0cb4d5cd2a147ef3d52f9db6a2 100644 --- a/llvm/utils/gn/secondary/lldb/source/Host/BUILD.gn +++ b/llvm/utils/gn/secondary/lldb/source/Host/BUILD.gn @@ -16,6 +16,7 @@ static_library("Host") { ] public_deps = [ "//llvm/utils/gn/build/libs/xml" ] sources = [ + "common/Alarm.cpp", "common/File.cpp", "common/FileAction.cpp", "common/FileCache.cpp", diff --git a/llvm/utils/gn/secondary/lldb/source/Plugins/Language/CPlusPlus/BUILD.gn b/llvm/utils/gn/secondary/lldb/source/Plugins/Language/CPlusPlus/BUILD.gn index 6c667b280aa765d36ef989b8e124e47da8956d65..9d57f2f0877e3e71fc22c11dd8305b93e093cb44 100644 --- a/llvm/utils/gn/secondary/lldb/source/Plugins/Language/CPlusPlus/BUILD.gn +++ b/llvm/utils/gn/secondary/lldb/source/Plugins/Language/CPlusPlus/BUILD.gn @@ -34,6 +34,7 @@ static_library("CPlusPlus") { "LibCxxMap.cpp", "LibCxxQueue.cpp", "LibCxxRangesRefView.cpp", + "LibCxxSliceArray.cpp", "LibCxxSpan.cpp", "LibCxxTuple.cpp", "LibCxxUnorderedMap.cpp", diff --git a/llvm/utils/gn/secondary/llvm/lib/DebugInfo/LogicalView/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/DebugInfo/LogicalView/BUILD.gn index 763fdf21a1c81ed61dd38bc3f6023aeb67f5fcc1..12b9540cc6d98e7dca7d67421e3cf40b90054cd5 100644 --- a/llvm/utils/gn/secondary/llvm/lib/DebugInfo/LogicalView/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/DebugInfo/LogicalView/BUILD.gn @@ -29,6 +29,6 @@ static_library("LogicalView") { "Readers/LVBinaryReader.cpp", "Readers/LVCodeViewReader.cpp", "Readers/LVCodeViewVisitor.cpp", - "Readers/LVELFReader.cpp", + "Readers/LVDWARFReader.cpp", ] } diff --git a/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn index 6caad81edec53f062172966424a37ecd415d412d..ba0f6d8c0f8cff88b392b58aa9765c85d27772ea 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn @@ -3,6 +3,7 @@ static_library("Support") { deps = [ "BLAKE3", "//llvm/include/llvm/Config:config", + "//llvm/include/llvm/Support:write_vcsrevision", "//llvm/lib/Demangle", "//llvm/utils/gn/build/libs/pthread", "//llvm/utils/gn/build/libs/terminfo", @@ -89,6 +90,8 @@ static_library("Support") { "GlobPattern.cpp", "GraphWriter.cpp", "Hashing.cpp", + "HexagonAttributeParser.cpp", + "HexagonAttributes.cpp", "InitLLVM.cpp", "InstructionCost.cpp", "IntEqClasses.cpp", diff --git a/llvm/utils/gn/secondary/llvm/lib/Target/AMDGPU/MCTargetDesc/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Target/AMDGPU/MCTargetDesc/BUILD.gn index 3d8e3e66d26db1d522c62a059f19e056db663c46..5ba91fcec83a0d78c699d03fccd7f2ae7d0dc14a 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Target/AMDGPU/MCTargetDesc/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Target/AMDGPU/MCTargetDesc/BUILD.gn @@ -103,6 +103,8 @@ static_library("MCTargetDesc") { "AMDGPUInstPrinter.cpp", "AMDGPUMCAsmInfo.cpp", "AMDGPUMCCodeEmitter.cpp", + "AMDGPUMCExpr.cpp", + "AMDGPUMCKernelDescriptor.cpp", "AMDGPUMCTargetDesc.cpp", "AMDGPUTargetStreamer.cpp", "R600InstPrinter.cpp", diff --git a/llvm/utils/gn/secondary/llvm/lib/Transforms/IPO/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Transforms/IPO/BUILD.gn index 2003e86e90b96de3c5a5f8a3d5db19cb3f91cb74..0d134c7bdffb704df8de8f182e98186685563626 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Transforms/IPO/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Transforms/IPO/BUILD.gn @@ -57,6 +57,7 @@ static_library("IPO") { "SCCP.cpp", "SampleContextTracker.cpp", "SampleProfile.cpp", + "SampleProfileMatcher.cpp", "SampleProfileProbe.cpp", "StripDeadPrototypes.cpp", "StripSymbols.cpp", diff --git a/llvm/utils/gn/secondary/llvm/tools/dsymutil/BUILD.gn b/llvm/utils/gn/secondary/llvm/tools/dsymutil/BUILD.gn index d22d0433656e51ab7ebe5c2d37dcabd0415655c9..5710e07b07cf7bd1ee2fd6463e239c1db8c33888 100644 --- a/llvm/utils/gn/secondary/llvm/tools/dsymutil/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/tools/dsymutil/BUILD.gn @@ -31,7 +31,6 @@ driver_executable("dsymutil") { "MachOUtils.cpp", "RelocationMap.cpp", "Reproducer.cpp", - "SymbolMap.cpp", "dsymutil.cpp", ] if (host_os == "mac") { diff --git a/llvm/utils/gn/secondary/llvm/unittests/DebugInfo/LogicalView/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/DebugInfo/LogicalView/BUILD.gn index 9cbddd8af9a8f8ad9b243f387d645cd8521ddf6b..d87bac64e7b34967b53418422a64c0b3c012e4b0 100644 --- a/llvm/utils/gn/secondary/llvm/unittests/DebugInfo/LogicalView/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/unittests/DebugInfo/LogicalView/BUILD.gn @@ -14,7 +14,7 @@ unittest("DebugInfoLogicalViewTests") { "CodeViewReaderTest.cpp", "CommandLineOptionsTest.cpp", "CompareElementsTest.cpp", - "ELFReaderTest.cpp", + "DWARFReaderTest.cpp", "LocationRangesTest.cpp", "LogicalElementsTest.cpp", "SelectElementsTest.cpp", diff --git a/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn index be1efff15f5aa0187905d455b57b6445f516f889..3e05b9b1f8c3f797c45110d46749dca910dec658 100644 --- a/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn @@ -24,6 +24,7 @@ unittest("OrcJITTests") { "JITTargetMachineBuilderTest.cpp", "LazyCallThroughAndReexportsTest.cpp", "LookupAndRecordAddrsTest.cpp", + "MachOPlatformTest.cpp", "MapperJITLinkMemoryManagerTest.cpp", "MemoryMapperTest.cpp", "ObjectFormatsTest.cpp", diff --git a/llvm/utils/gn/secondary/llvm/unittests/TableGen/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/TableGen/BUILD.gn index ce04c967c2484e9e8eb4bc5ce801cec360a58854..a08001d0b319cea6e5d9772db8d2ce6ce1066dad 100644 --- a/llvm/utils/gn/secondary/llvm/unittests/TableGen/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/unittests/TableGen/BUILD.gn @@ -19,7 +19,7 @@ unittest("TableGenTests") { ":AutomataTables", "//llvm/lib/Support", "//llvm/lib/TableGen", - "//llvm/utils/TableGen/GlobalISel", + "//llvm/utils/TableGen/Common", ] include_dirs = [ "//llvm/utils/TableGen" ] sources = [ diff --git a/llvm/utils/gn/secondary/llvm/unittests/Target/AArch64/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/Target/AArch64/BUILD.gn index 8fde227c4517969661667c773abd660e863768ed..cddec7aee574543eedf850125ab24034ef2158e9 100644 --- a/llvm/utils/gn/secondary/llvm/unittests/Target/AArch64/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/unittests/Target/AArch64/BUILD.gn @@ -20,6 +20,7 @@ unittest("AArch64Tests") { "AArch64SVESchedPseudoTest.cpp", "AddressingModes.cpp", "DecomposeStackOffsetTest.cpp", + "Immediates.cpp", "InstSizes.cpp", "MatrixRegisterAliasing.cpp", "SMEAttributesTest.cpp", diff --git a/llvm/utils/gn/secondary/llvm/utils/TableGen/BUILD.gn b/llvm/utils/gn/secondary/llvm/utils/TableGen/BUILD.gn index 58335000950d46a24eec6e32eb7db069e31f8a40..53a9d8d01519a7f0555d5e4a008f2e5439e255cc 100644 --- a/llvm/utils/gn/secondary/llvm/utils/TableGen/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/utils/TableGen/BUILD.gn @@ -1,51 +1,45 @@ source_set("llvm-min-tblgen-sources") { sources = [ "Attributes.cpp", - "CodeGenIntrinsics.cpp", "DirectiveEmitter.cpp", "IntrinsicEmitter.cpp", "RISCVTargetDefEmitter.cpp", - "SDNodeProperties.cpp", "TableGen.cpp", "VTEmitter.cpp", ] - deps = [ "//llvm/lib/Support" ] + deps = [ + "Basic", + "//llvm/lib/Support", + ] } executable("llvm-min-tblgen") { deps = [ ":llvm-min-tblgen-sources", - "//llvm/lib/TableGen", + "Basic", ] } executable("llvm-tblgen") { deps = [ ":llvm-min-tblgen-sources", + "Basic", + "Common", "//llvm/include/llvm/Config:llvm-config", "//llvm/lib/CodeGenTypes", "//llvm/lib/Support", "//llvm/lib/TableGen", - "//llvm/utils/TableGen/GlobalISel", ] + include_dirs = [ "." ] sources = [ "AsmMatcherEmitter.cpp", "AsmWriterEmitter.cpp", - "AsmWriterInst.cpp", "CTagsEmitter.cpp", "CallingConvEmitter.cpp", "CodeEmitterGen.cpp", - "CodeGenDAGPatterns.cpp", - "CodeGenHwModes.cpp", - "CodeGenInstAlias.cpp", - "CodeGenInstruction.cpp", "CodeGenMapTable.cpp", - "CodeGenRegisters.cpp", - "CodeGenSchedule.cpp", - "CodeGenTarget.cpp", "CompressInstEmitter.cpp", "DAGISelEmitter.cpp", - "DAGISelMatcher.cpp", "DAGISelMatcherEmitter.cpp", "DAGISelMatcherGen.cpp", "DAGISelMatcherOpt.cpp", @@ -58,24 +52,16 @@ executable("llvm-tblgen") { "FastISelEmitter.cpp", "GlobalISelCombinerEmitter.cpp", "GlobalISelEmitter.cpp", - "GlobalISelMatchTable.cpp", - "GlobalISelMatchTableExecutorEmitter.cpp", - "InfoByHwMode.cpp", "InstrDocsEmitter.cpp", "InstrInfoEmitter.cpp", "MacroFusionPredicatorEmitter.cpp", - "OptEmitter.cpp", "OptParserEmitter.cpp", "OptRSTEmitter.cpp", - "PredicateExpander.cpp", "PseudoLoweringEmitter.cpp", "RegisterBankEmitter.cpp", "RegisterInfoEmitter.cpp", "SearchableTableEmitter.cpp", "SubtargetEmitter.cpp", - "SubtargetFeatureInfo.cpp", - "Types.cpp", - "VarLenCodeEmitterGen.cpp", "WebAssemblyDisassemblerEmitter.cpp", "X86CompressEVEXTablesEmitter.cpp", "X86DisassemblerTables.cpp", diff --git a/llvm/utils/gn/secondary/llvm/utils/TableGen/Basic/BUILD.gn b/llvm/utils/gn/secondary/llvm/utils/TableGen/Basic/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..2ebe393fa0fd9d531ff7d6641c574b67445ba1b5 --- /dev/null +++ b/llvm/utils/gn/secondary/llvm/utils/TableGen/Basic/BUILD.gn @@ -0,0 +1,10 @@ +static_library("Basic") { + deps = [ + "//llvm/lib/Support", + "//llvm/lib/TableGen", + ] + sources = [ + "CodeGenIntrinsics.cpp", + "SDNodeProperties.cpp", + ] +} diff --git a/llvm/utils/gn/secondary/llvm/utils/TableGen/Common/BUILD.gn b/llvm/utils/gn/secondary/llvm/utils/TableGen/Common/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..daa3278d56d7c13dc8e156b4a7bc5c334ab574be --- /dev/null +++ b/llvm/utils/gn/secondary/llvm/utils/TableGen/Common/BUILD.gn @@ -0,0 +1,34 @@ +static_library("Common") { + deps = [ + "//llvm/include/llvm/CodeGen:GenVT", + "//llvm/lib/CodeGenTypes", + "//llvm/lib/Support", + "//llvm/lib/TableGen", + ] + include_dirs = [ ".." ] + sources = [ + "AsmWriterInst.cpp", + "CodeGenDAGPatterns.cpp", + "CodeGenHwModes.cpp", + "CodeGenInstAlias.cpp", + "CodeGenInstruction.cpp", + "CodeGenRegisters.cpp", + "CodeGenSchedule.cpp", + "CodeGenTarget.cpp", + "DAGISelMatcher.cpp", + "GlobalISel/CXXPredicates.cpp", + "GlobalISel/CodeExpander.cpp", + "GlobalISel/CombinerUtils.cpp", + "GlobalISel/GlobalISelMatchTable.cpp", + "GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp", + "GlobalISel/MatchDataInfo.cpp", + "GlobalISel/PatternParser.cpp", + "GlobalISel/Patterns.cpp", + "InfoByHwMode.cpp", + "OptEmitter.cpp", + "PredicateExpander.cpp", + "SubtargetFeatureInfo.cpp", + "Types.cpp", + "VarLenCodeEmitterGen.cpp", + ] +} diff --git a/llvm/utils/gn/secondary/llvm/utils/TableGen/GlobalISel/BUILD.gn b/llvm/utils/gn/secondary/llvm/utils/TableGen/GlobalISel/BUILD.gn deleted file mode 100644 index 8b0ca856151704693149e2064d789accd64d8513..0000000000000000000000000000000000000000 --- a/llvm/utils/gn/secondary/llvm/utils/TableGen/GlobalISel/BUILD.gn +++ /dev/null @@ -1,13 +0,0 @@ -static_library("GlobalISel") { - deps = [ - "//llvm/include/llvm/CodeGen:GenVT", - "//llvm/lib/CodeGenTypes", - "//llvm/lib/Support", - ] - sources = [ - "CXXPredicates.cpp", - "CodeExpander.cpp", - "MatchDataInfo.cpp", - "Patterns.cpp", - ] -} diff --git a/llvm/utils/release/export.sh b/llvm/utils/release/export.sh index 9fd906c49ea6e514696e34c30e6783965a04d26e..66bef82586a34853a3e5a18c32fbfaa42c79a555 100755 --- a/llvm/utils/release/export.sh +++ b/llvm/utils/release/export.sh @@ -84,7 +84,7 @@ export_sources() { # Determine the release by fetching the version from LLVM's CMakeLists.txt # in the specified git ref. if [ -n "$snapshot" ]; then - release=$(git -C $llvm_src_dir show $snapshot:llvm/CMakeLists.txt | grep -ioP 'set\(\s*LLVM_VERSION_(MAJOR|MINOR|PATCH)\s\K[0-9]+' | paste -sd '.') + release=$(git -C $llvm_src_dir show $snapshot:cmake/Modules/LLVMVersion.cmake | grep -ioP 'set\(\s*LLVM_VERSION_(MAJOR|MINOR|PATCH)\s\K[0-9]+' | paste -sd '.') fi tag="llvmorg-$release" diff --git a/mlir/docs/DataLayout.md b/mlir/docs/DataLayout.md index b9dde30519d6edaa33eef7325756acffa769b0c0..21430c44ca95fb7aac64a49ccaf8a8f7c32df93c 100644 --- a/mlir/docs/DataLayout.md +++ b/mlir/docs/DataLayout.md @@ -77,6 +77,7 @@ public: llvm::TypeSize getTypeSizeInBits(Type type) const; uint64_t getTypeABIAlignment(Type type) const; uint64_t getTypePreferredAlignment(Type type) const; + std::optional<uint64_t> getTypeIndexBitwidth(Type type) const; }; ``` @@ -267,7 +268,8 @@ module attributes { dlti.dl_spec = #dlti.dl_spec< >} {} ``` -specifies that `index` has 32 bits. All other layout properties of `index` match +specifies that `index` has 32 bits and index computations should be performed +using 32-bit precision as well. All other layout properties of `index` match those of the integer type with the same bitwidth defined above. In absence of the corresponding entry, `index` is assumed to be a 64-bit @@ -287,7 +289,7 @@ The default data layout assumes 8-bit bytes. ### DLTI Dialect -The [DLTI](Dialects/DLTI.md) dialect provides the attributes implementing +The [DLTI](../Dialects/DLTIDialect/) dialect provides the attributes implementing `DataLayoutSpecInterface` and `DataLayoutEntryInterface`, as well as a dialect attribute that can be used to attach the specification to a given operation. The verifier of this attribute triggers those of the specification and checks the diff --git a/mlir/docs/Tutorials/transform/Ch2.md b/mlir/docs/Tutorials/transform/Ch2.md index 1aaefd2f2c30755916d7313d3ede629813e06fa3..6a6cefd8785aa4d7e6db8c3e6c78350e100b97e4 100644 --- a/mlir/docs/Tutorials/transform/Ch2.md +++ b/mlir/docs/Tutorials/transform/Ch2.md @@ -62,7 +62,7 @@ The operations themselves can be defined using ODS, exactly in the same way as r #define MY_EXTENSION include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/IR/OpBase.td" include "mlir/Interfaces/SideEffectInterfaces.td" @@ -124,7 +124,7 @@ This will generate two files, `MyExtension.h.inc` and `MyExtension.cpp.inc`, tha ```c++ // In MyExtension.h. #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #define GET_OP_CLASSES #include "MyExtension.h.inc" diff --git a/mlir/examples/transform/Ch2/include/MyExtension.h b/mlir/examples/transform/Ch2/include/MyExtension.h index 03a24a190e15e411559f2a623090ea5478e6701c..5ab70a505aee454113c6e81daf5f626a262cd340 100644 --- a/mlir/examples/transform/Ch2/include/MyExtension.h +++ b/mlir/examples/transform/Ch2/include/MyExtension.h @@ -13,7 +13,7 @@ #include "mlir/Bytecode/BytecodeOpInterface.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #define GET_OP_CLASSES #include "MyExtension.h.inc" diff --git a/mlir/examples/transform/Ch2/include/MyExtension.td b/mlir/examples/transform/Ch2/include/MyExtension.td index 4824b83e6c1843df3b2afdb51b1c7cb42942ef60..1abd95237055670b1257dbf3cdfed30a3fc47924 100644 --- a/mlir/examples/transform/Ch2/include/MyExtension.td +++ b/mlir/examples/transform/Ch2/include/MyExtension.td @@ -15,7 +15,7 @@ #define MY_EXTENSION include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/IR/OpBase.td" include "mlir/Interfaces/SideEffectInterfaces.td" diff --git a/mlir/examples/transform/Ch2/lib/MyExtension.cpp b/mlir/examples/transform/Ch2/lib/MyExtension.cpp index 031c52c307382e87c6c4472a6165f086297a4813..b2955a905b883cfe22e3dfcf2ae20a894c829842 100644 --- a/mlir/examples/transform/Ch2/lib/MyExtension.cpp +++ b/mlir/examples/transform/Ch2/lib/MyExtension.cpp @@ -15,8 +15,8 @@ #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/SCF/IR/SCF.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformTypes.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/DialectRegistry.h" #include "mlir/IR/Operation.h" #include "mlir/Interfaces/SideEffectInterfaces.h" diff --git a/mlir/examples/transform/Ch3/include/MyExtension.h b/mlir/examples/transform/Ch3/include/MyExtension.h index 223638eee1c0365df582e6f7ec853c6ad63cf398..086850403e1c5ba362dbf625b603fc42f6235e71 100644 --- a/mlir/examples/transform/Ch3/include/MyExtension.h +++ b/mlir/examples/transform/Ch3/include/MyExtension.h @@ -13,13 +13,16 @@ #include "mlir/Bytecode/BytecodeOpInterface.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" namespace mlir { class CallOpInterface; namespace func { class CallOp; } // namespace func +namespace transform { +class OperationType; +} // namespace transform } // namespace mlir #define GET_TYPEDEF_CLASSES diff --git a/mlir/examples/transform/Ch3/include/MyExtension.td b/mlir/examples/transform/Ch3/include/MyExtension.td index f444df18d69e8b57cfdf9439cce1e97dfe0be896..5a78186d75c7b4f59398560eb951cf0c63e3765b 100644 --- a/mlir/examples/transform/Ch3/include/MyExtension.td +++ b/mlir/examples/transform/Ch3/include/MyExtension.td @@ -16,7 +16,7 @@ include "MyExtensionTypes.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Dialect/Transform/IR/TransformTypes.td" include "mlir/IR/OpBase.td" include "mlir/Interfaces/SideEffectInterfaces.td" diff --git a/mlir/examples/transform/Ch3/include/MyExtensionTypes.td b/mlir/examples/transform/Ch3/include/MyExtensionTypes.td index 7d745935d47830bb593d616898dc7d1fec8cdefa..8c4b8a9c782b9132bd2ade56e2c8cabb06b22dbb 100644 --- a/mlir/examples/transform/Ch3/include/MyExtensionTypes.td +++ b/mlir/examples/transform/Ch3/include/MyExtensionTypes.td @@ -16,7 +16,7 @@ include "mlir/IR/AttrTypeBase.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" // Transform dialect allows additional types to be defined and injected. def CallOpInterfaceHandle diff --git a/mlir/examples/transform/Ch3/lib/MyExtension.cpp b/mlir/examples/transform/Ch3/lib/MyExtension.cpp index dc0a8a0ab30336e95bdcb1282d4fe31be223a4ee..2e4388d4cc2281656532862c5541dc7ec2e193f6 100644 --- a/mlir/examples/transform/Ch3/lib/MyExtension.cpp +++ b/mlir/examples/transform/Ch3/lib/MyExtension.cpp @@ -15,6 +15,7 @@ #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/SCF/IR/SCF.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" +#include "mlir/Dialect/Transform/IR/TransformTypes.h" #include "mlir/IR/DialectImplementation.h" #include "mlir/Interfaces/CallInterfaces.h" #include "llvm/ADT/TypeSwitch.h" diff --git a/mlir/examples/transform/Ch4/include/MyExtension.h b/mlir/examples/transform/Ch4/include/MyExtension.h index 13e5b3c04b02f11c1c3c9ce51cd6873d8a5bb85e..620ec8f398a5a73e9c6778fa6aba43f287327f73 100644 --- a/mlir/examples/transform/Ch4/include/MyExtension.h +++ b/mlir/examples/transform/Ch4/include/MyExtension.h @@ -13,8 +13,8 @@ #include "mlir/Bytecode/BytecodeOpInterface.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformOps.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" namespace mlir { class CallOpInterface; diff --git a/mlir/examples/transform/Ch4/include/MyExtension.td b/mlir/examples/transform/Ch4/include/MyExtension.td index ae58dc37db43fc4e1f21bb2409d29638cd2a463d..660680334178d9b15cc28aa95b2393ec54658f36 100644 --- a/mlir/examples/transform/Ch4/include/MyExtension.td +++ b/mlir/examples/transform/Ch4/include/MyExtension.td @@ -14,9 +14,9 @@ #ifndef MY_EXTENSION #define MY_EXTENSION -include "mlir/Dialect/Transform/IR/MatchInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/IR/OpBase.td" include "mlir/Interfaces/SideEffectInterfaces.td" diff --git a/mlir/include/mlir-c/Dialect/LLVM.h b/mlir/include/mlir-c/Dialect/LLVM.h index d823afb659c8dbd0aa8e8bcfa0989e1c1b53498b..4f1d646f5bc831014edfc40fec6413071919966e 100644 --- a/mlir/include/mlir-c/Dialect/LLVM.h +++ b/mlir/include/mlir-c/Dialect/LLVM.h @@ -229,16 +229,16 @@ MLIR_CAPI_EXPORTED MlirAttribute mlirLLVMDIBasicTypeAttrGet( /// Creates a LLVM DICompositeType attribute. MLIR_CAPI_EXPORTED MlirAttribute mlirLLVMDICompositeTypeAttrGet( - MlirContext ctx, unsigned int tag, MlirAttribute name, MlirAttribute file, - uint32_t line, MlirAttribute scope, MlirAttribute baseType, int64_t flags, - uint64_t sizeInBits, uint64_t alignInBits, intptr_t nElements, - MlirAttribute const *elements); + MlirContext ctx, unsigned int tag, MlirAttribute recId, MlirAttribute name, + MlirAttribute file, uint32_t line, MlirAttribute scope, + MlirAttribute baseType, int64_t flags, uint64_t sizeInBits, + uint64_t alignInBits, intptr_t nElements, MlirAttribute const *elements); /// Creates a LLVM DIDerivedType attribute. MLIR_CAPI_EXPORTED MlirAttribute mlirLLVMDIDerivedTypeAttrGet( MlirContext ctx, unsigned int tag, MlirAttribute name, MlirAttribute baseType, uint64_t sizeInBits, uint32_t alignInBits, - uint64_t offsetInBits); + uint64_t offsetInBits, MlirAttribute extraData); /// Gets the base type from a LLVM DIDerivedType attribute. MLIR_CAPI_EXPORTED MlirAttribute diff --git a/mlir/include/mlir/Analysis/Presburger/Matrix.h b/mlir/include/mlir/Analysis/Presburger/Matrix.h index 4484ebc747e61ce2e625c877b4ad42394ea51de3..c20a7bcecd52dc2882c6e01fcd2b2038dc2c3276 100644 --- a/mlir/include/mlir/Analysis/Presburger/Matrix.h +++ b/mlir/include/mlir/Analysis/Presburger/Matrix.h @@ -244,6 +244,9 @@ protected: SmallVector<T, 16> data; }; +extern template class Matrix<MPInt>; +extern template class Matrix<Fraction>; + // An inherited class for integer matrices, with no new data attributes. // This is only used for the matrix-related methods which apply only // to integers (hermite normal form computation and row normalisation). diff --git a/mlir/include/mlir/Conversion/ArithCommon/AttrToLLVMConverter.h b/mlir/include/mlir/Conversion/ArithCommon/AttrToLLVMConverter.h index 32d7979c32dfb2c2811301b69d44fedbce55e9e1..0891e2ba7be760dfe20ceec74bccd833e62e1b26 100644 --- a/mlir/include/mlir/Conversion/ArithCommon/AttrToLLVMConverter.h +++ b/mlir/include/mlir/Conversion/ArithCommon/AttrToLLVMConverter.h @@ -36,6 +36,20 @@ convertArithOverflowFlagsToLLVM(arith::IntegerOverflowFlags arithFlags); LLVM::IntegerOverflowFlagsAttr convertArithOverflowAttrToLLVM(arith::IntegerOverflowFlagsAttr flagsAttr); +/// Creates an LLVM rounding mode enum value from a given arithmetic rounding +/// mode enum value. +LLVM::RoundingMode +convertArithRoundingModeToLLVM(arith::RoundingMode roundingMode); + +/// Creates an LLVM rounding mode attribute from a given arithmetic rounding +/// mode attribute. +LLVM::RoundingModeAttr +convertArithRoundingModeAttrToLLVM(arith::RoundingModeAttr roundingModeAttr); + +/// Returns an attribute for the default LLVM FP exception behavior. +LLVM::FPExceptionBehaviorAttr +getLLVMDefaultFPExceptionBehavior(MLIRContext &context); + // Attribute converter that populates a NamedAttrList by removing the fastmath // attribute from the source operation attributes, and replacing it with an // equivalent LLVM fastmath attribute. @@ -89,6 +103,40 @@ public: private: NamedAttrList convertedAttr; }; + +template <typename SourceOp, typename TargetOp> +class AttrConverterConstrainedFPToLLVM { + static_assert(TargetOp::template hasTrait< + LLVM::FPExceptionBehaviorOpInterface::Trait>(), + "Target constrained FP operations must implement " + "LLVM::FPExceptionBehaviorOpInterface"); + +public: + AttrConverterConstrainedFPToLLVM(SourceOp srcOp) { + // Copy the source attributes. + convertedAttr = NamedAttrList{srcOp->getAttrs()}; + + if constexpr (TargetOp::template hasTrait< + LLVM::RoundingModeOpInterface::Trait>()) { + // Get the name of the rounding mode attribute. + StringRef arithAttrName = srcOp.getRoundingModeAttrName(); + // Remove the source attribute. + auto arithAttr = + cast<arith::RoundingModeAttr>(convertedAttr.erase(arithAttrName)); + // Set the target attribute. + convertedAttr.set(TargetOp::getRoundingModeAttrName(), + convertArithRoundingModeAttrToLLVM(arithAttr)); + } + convertedAttr.set(TargetOp::getFPExceptionBehaviorAttrName(), + getLLVMDefaultFPExceptionBehavior(*srcOp->getContext())); + } + + ArrayRef<NamedAttribute> getAttrs() const { return convertedAttr.getAttrs(); } + +private: + NamedAttrList convertedAttr; +}; + } // namespace arith } // namespace mlir diff --git a/mlir/include/mlir/Conversion/MemRefToEmitC/MemRefToEmitC.h b/mlir/include/mlir/Conversion/MemRefToEmitC/MemRefToEmitC.h new file mode 100644 index 0000000000000000000000000000000000000000..734ffdba520c9ff5ce991b02d61bb96ae6ad2acc --- /dev/null +++ b/mlir/include/mlir/Conversion/MemRefToEmitC/MemRefToEmitC.h @@ -0,0 +1,21 @@ +//===- MemRefToEmitC.h - Convert MemRef to EmitC --------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef MLIR_CONVERSION_MEMREFTOEMITC_MEMREFTOEMITC_H +#define MLIR_CONVERSION_MEMREFTOEMITC_MEMREFTOEMITC_H + +namespace mlir { +class RewritePatternSet; +class TypeConverter; + +void populateMemRefToEmitCTypeConversion(TypeConverter &typeConverter); + +void populateMemRefToEmitCConversionPatterns(RewritePatternSet &patterns, + TypeConverter &converter); +} // namespace mlir + +#endif // MLIR_CONVERSION_MEMREFTOEMITC_MEMREFTOEMITC_H diff --git a/mlir/include/mlir/Conversion/MemRefToEmitC/MemRefToEmitCPass.h b/mlir/include/mlir/Conversion/MemRefToEmitC/MemRefToEmitCPass.h new file mode 100644 index 0000000000000000000000000000000000000000..4a63014c19ad0e0bb0eaf69517c1accb9e30e36f --- /dev/null +++ b/mlir/include/mlir/Conversion/MemRefToEmitC/MemRefToEmitCPass.h @@ -0,0 +1,20 @@ +//===- MemRefToEmitCPass.h - A Pass to convert MemRef to EmitC ------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef MLIR_CONVERSION_MEMREFTOEMITC_MEMREFTOEMITCPASS_H +#define MLIR_CONVERSION_MEMREFTOEMITC_MEMREFTOEMITCPASS_H + +#include <memory> + +namespace mlir { +class Pass; + +#define GEN_PASS_DECL_CONVERTMEMREFTOEMITC +#include "mlir/Conversion/Passes.h.inc" +} // namespace mlir + +#endif // MLIR_CONVERSION_MEMREFTOEMITC_MEMREFTOEMITCPASS_H diff --git a/mlir/include/mlir/Conversion/Passes.h b/mlir/include/mlir/Conversion/Passes.h index f2aa4fb535402d66481685deb5d9a31065b4a81c..2179ae18ac074bedd7d7ed1f2985f4f71e358719 100644 --- a/mlir/include/mlir/Conversion/Passes.h +++ b/mlir/include/mlir/Conversion/Passes.h @@ -45,6 +45,7 @@ #include "mlir/Conversion/MathToLLVM/MathToLLVM.h" #include "mlir/Conversion/MathToLibm/MathToLibm.h" #include "mlir/Conversion/MathToSPIRV/MathToSPIRVPass.h" +#include "mlir/Conversion/MemRefToEmitC/MemRefToEmitCPass.h" #include "mlir/Conversion/MemRefToLLVM/MemRefToLLVM.h" #include "mlir/Conversion/MemRefToSPIRV/MemRefToSPIRVPass.h" #include "mlir/Conversion/NVGPUToNVVM/NVGPUToNVVM.h" diff --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td index bd81cc6d5323bfa674d2af4bf3ed730a9e1433f6..d094ee3b36ab956a89b024c0ac9be88b819e4b0c 100644 --- a/mlir/include/mlir/Conversion/Passes.td +++ b/mlir/include/mlir/Conversion/Passes.td @@ -172,10 +172,6 @@ def ConvertArithToSPIRV : Pass<"convert-arith-to-spirv"> { "bool", /*default=*/"true", "Emulate narrower scalar types with 32-bit ones if not supported by " "the target">, - Option<"enableFastMath", "enable-fast-math", - "bool", /*default=*/"false", - "Enable fast math mode (assuming no NaN and infinity for floating " - "point values) when performing conversion"> ]; } @@ -753,6 +749,15 @@ def ConvertMathToFuncs : Pass<"convert-math-to-funcs", "ModuleOp"> { ]; } +//===----------------------------------------------------------------------===// +// MemRefToEmitC +//===----------------------------------------------------------------------===// + +def ConvertMemRefToEmitC : Pass<"convert-memref-to-emitc"> { + let summary = "Convert MemRef dialect to EmitC dialect"; + let dependentDialects = ["emitc::EmitCDialect"]; +} + //===----------------------------------------------------------------------===// // MemRefToLLVM //===----------------------------------------------------------------------===// diff --git a/mlir/include/mlir/Dialect/AMDGPU/TransformOps/AMDGPUTransformOps.h b/mlir/include/mlir/Dialect/AMDGPU/TransformOps/AMDGPUTransformOps.h index 4fb4ab08a0da34a489328bd2e300948e3c453815..dcf934c71dd1fcae4a1cf5f7e9f853506e1fe6ed 100644 --- a/mlir/include/mlir/Dialect/AMDGPU/TransformOps/AMDGPUTransformOps.h +++ b/mlir/include/mlir/Dialect/AMDGPU/TransformOps/AMDGPUTransformOps.h @@ -12,7 +12,7 @@ #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/Transform/IR/TransformAttrs.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/RegionKindInterface.h" diff --git a/mlir/include/mlir/Dialect/AMDGPU/TransformOps/AMDGPUTransformOps.td b/mlir/include/mlir/Dialect/AMDGPU/TransformOps/AMDGPUTransformOps.td index 0eb67050608630fa265c35cefa3e4130ea5a1581..8aaa87511a2be6620c9b0b88f120e94cb59eea67 100644 --- a/mlir/include/mlir/Dialect/AMDGPU/TransformOps/AMDGPUTransformOps.td +++ b/mlir/include/mlir/Dialect/AMDGPU/TransformOps/AMDGPUTransformOps.td @@ -11,7 +11,7 @@ include "mlir/Dialect/Transform/IR/TransformAttrs.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Dialect/Transform/IR/TransformTypes.td" include "mlir/Interfaces/SideEffectInterfaces.td" diff --git a/mlir/include/mlir/Dialect/Affine/Analysis/LoopAnalysis.h b/mlir/include/mlir/Dialect/Affine/Analysis/LoopAnalysis.h index 1f64b57cac57822a97f02bdbd78abda24fd5d6a0..7b92b930fb5f57ab7cccea047930560657f8114f 100644 --- a/mlir/include/mlir/Dialect/Affine/Analysis/LoopAnalysis.h +++ b/mlir/include/mlir/Dialect/Affine/Analysis/LoopAnalysis.h @@ -48,6 +48,11 @@ std::optional<uint64_t> getConstantTripCount(AffineForOp forOp); /// this method is thus able to determine non-trivial divisors. uint64_t getLargestDivisorOfTripCount(AffineForOp forOp); +/// Checks if an affine read or write operation depends on `forOp`'s IV, i.e., +/// if the memory access is invariant on `forOp`. +template <typename LoadOrStoreOp> +bool isInvariantAccess(LoadOrStoreOp memOp, AffineForOp forOp); + /// Given an induction variable `iv` of type AffineForOp and `indices` of type /// IndexType, returns the set of `indices` that are independent of `iv`. /// diff --git a/mlir/include/mlir/Dialect/Affine/IR/AffineValueMap.h b/mlir/include/mlir/Dialect/Affine/IR/AffineValueMap.h index 8439930a87467cc23b981fa0b6bf3af3ceb7788d..7ad0e4a1e5ea041dd983103d821c88e033878a97 100644 --- a/mlir/include/mlir/Dialect/Affine/IR/AffineValueMap.h +++ b/mlir/include/mlir/Dialect/Affine/IR/AffineValueMap.h @@ -44,6 +44,11 @@ public: // Resets this AffineValueMap with 'map', 'operands', and 'results'. void reset(AffineMap map, ValueRange operands, ValueRange results = {}); + /// Composes all incoming affine.apply ops and then simplifies and + /// canonicalizes the map and operands. This can change the number of + /// operands, but the result count remains the same. + void composeSimplifyAndCanonicalize(); + /// Return the value map that is the difference of value maps 'a' and 'b', /// represented as an affine map and its operands. The output map + operands /// are canonicalized and simplified. diff --git a/mlir/include/mlir/Dialect/Affine/TransformOps/AffineTransformOps.h b/mlir/include/mlir/Dialect/Affine/TransformOps/AffineTransformOps.h index f52f04ada036f5f83a52a030cb31006a6d303646..1001cb52b518b84d6f7145b8511292064011dc65 100644 --- a/mlir/include/mlir/Dialect/Affine/TransformOps/AffineTransformOps.h +++ b/mlir/include/mlir/Dialect/Affine/TransformOps/AffineTransformOps.h @@ -10,8 +10,8 @@ #define MLIR_DIALECT_AFFINE_TRANSFORMOPS_AFFINETRANSFORMOPS_H #include "mlir/Bytecode/BytecodeOpInterface.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformTypes.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpImplementation.h" namespace mlir { diff --git a/mlir/include/mlir/Dialect/Affine/TransformOps/AffineTransformOps.td b/mlir/include/mlir/Dialect/Affine/TransformOps/AffineTransformOps.td index b74e4af6eedd0e3a0d84dab4e006320f3cd39088..70b127fd063caf047a37e700f82cc8d0b6bdc0e3 100644 --- a/mlir/include/mlir/Dialect/Affine/TransformOps/AffineTransformOps.td +++ b/mlir/include/mlir/Dialect/Affine/TransformOps/AffineTransformOps.td @@ -10,7 +10,7 @@ #define AFFINE_TRANSFORM_OPS include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Dialect/Transform/IR/TransformTypes.td" include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/IR/OpBase.td" diff --git a/mlir/include/mlir/Dialect/Arith/IR/Arith.h b/mlir/include/mlir/Dialect/Arith/IR/Arith.h index 971c78f4a86a75aa7f491315b9d54af017d65da9..00cdb13feb29bb63004716ba5ddc61ee9cabd880 100644 --- a/mlir/include/mlir/Dialect/Arith/IR/Arith.h +++ b/mlir/include/mlir/Dialect/Arith/IR/Arith.h @@ -53,6 +53,7 @@ namespace arith { class ConstantIntOp : public arith::ConstantOp { public: using arith::ConstantOp::ConstantOp; + static ::mlir::TypeID resolveTypeID() { return TypeID::get<ConstantOp>(); } /// Build a constant int op that produces an integer of the specified width. static void build(OpBuilder &builder, OperationState &result, int64_t value, @@ -74,6 +75,7 @@ public: class ConstantFloatOp : public arith::ConstantOp { public: using arith::ConstantOp::ConstantOp; + static ::mlir::TypeID resolveTypeID() { return TypeID::get<ConstantOp>(); } /// Build a constant float op that produces a float of the specified type. static void build(OpBuilder &builder, OperationState &result, @@ -90,7 +92,7 @@ public: class ConstantIndexOp : public arith::ConstantOp { public: using arith::ConstantOp::ConstantOp; - + static ::mlir::TypeID resolveTypeID() { return TypeID::get<ConstantOp>(); } /// Build a constant int op that produces an index. static void build(OpBuilder &builder, OperationState &result, int64_t value); diff --git a/mlir/include/mlir/Dialect/Arith/IR/ArithBase.td b/mlir/include/mlir/Dialect/Arith/IR/ArithBase.td index c8a42c43c880b095b74a9db253e03eac5f80b5c9..19a2ade2e95a0e6955497a049471aa7df34c1ef8 100644 --- a/mlir/include/mlir/Dialect/Arith/IR/ArithBase.td +++ b/mlir/include/mlir/Dialect/Arith/IR/ArithBase.td @@ -156,4 +156,29 @@ def Arith_IntegerOverflowAttr : let assemblyFormat = "`<` $value `>`"; } +//===----------------------------------------------------------------------===// +// Arith_RoundingMode +//===----------------------------------------------------------------------===// + +// These correspond to LLVM's values defined in: +// llvm/include/llvm/ADT/FloatingPointMode.h + +def Arith_RToNearestTiesToEven // Round to nearest, ties to even + : I32EnumAttrCase<"to_nearest_even", 0>; +def Arith_RDownward // Round toward -inf + : I32EnumAttrCase<"downward", 1>; +def Arith_RUpward // Round toward +inf + : I32EnumAttrCase<"upward", 2>; +def Arith_RTowardZero // Round toward 0 + : I32EnumAttrCase<"toward_zero", 3>; +def Arith_RToNearestTiesAwayFromZero // Round to nearest, ties away from zero + : I32EnumAttrCase<"to_nearest_away", 4>; + +def Arith_RoundingModeAttr : I32EnumAttr< + "RoundingMode", "Floating point rounding mode", + [Arith_RToNearestTiesToEven, Arith_RDownward, Arith_RUpward, + Arith_RTowardZero, Arith_RToNearestTiesAwayFromZero]> { + let cppNamespace = "::mlir::arith"; +} + #endif // ARITH_BASE diff --git a/mlir/include/mlir/Dialect/Arith/IR/ArithOps.td b/mlir/include/mlir/Dialect/Arith/IR/ArithOps.td index c9df50d0395d1f731a22ffbc257d827cf9c0bac5..ead19c69a0831c3dcf5e7f0f825684f92495d991 100644 --- a/mlir/include/mlir/Dialect/Arith/IR/ArithOps.td +++ b/mlir/include/mlir/Dialect/Arith/IR/ArithOps.td @@ -1227,17 +1227,32 @@ def Arith_TruncIOp : Arith_IToICastOp<"trunci"> { // TruncFOp //===----------------------------------------------------------------------===// -def Arith_TruncFOp : Arith_FToFCastOp<"truncf"> { +def Arith_TruncFOp : + Arith_Op<"truncf", + [Pure, SameOperandsAndResultShape, + DeclareOpInterfaceMethods<ArithRoundingModeInterface>, + DeclareOpInterfaceMethods<CastOpInterface>]>, + Arguments<(ins FloatLike:$in, + OptionalAttr<Arith_RoundingModeAttr>:$roundingmode)>, + Results<(outs FloatLike:$out)> { let summary = "cast from floating-point to narrower floating-point"; let description = [{ Truncate a floating-point value to a smaller floating-point-typed value. The destination type must be strictly narrower than the source type. - If the value cannot be exactly represented, it is rounded using the default - rounding mode. When operating on vectors, casts elementwise. + If the value cannot be exactly represented, it is rounded using the + provided rounding mode or the default one if no rounding mode is provided. + When operating on vectors, casts elementwise. }]; + let builders = [ + OpBuilder<(ins "Type":$out, "Value":$in), [{ + $_state.addOperands(in); + $_state.addTypes(out); + }]> + ]; let hasFolder = 1; let hasVerifier = 1; + let assemblyFormat = "$in ($roundingmode^)? attr-dict `:` type($in) `to` type($out)"; } //===----------------------------------------------------------------------===// diff --git a/mlir/include/mlir/Dialect/Arith/IR/ArithOpsInterfaces.td b/mlir/include/mlir/Dialect/Arith/IR/ArithOpsInterfaces.td index 73a5d9c32ef2057739da8b971fa964691fa1e57c..82d6c9ad6b03da75d992aafa62a871000c5414fb 100644 --- a/mlir/include/mlir/Dialect/Arith/IR/ArithOpsInterfaces.td +++ b/mlir/include/mlir/Dialect/Arith/IR/ArithOpsInterfaces.td @@ -106,4 +106,37 @@ def ArithIntegerOverflowFlagsInterface : OpInterface<"ArithIntegerOverflowFlagsI ]; } +def ArithRoundingModeInterface : OpInterface<"ArithRoundingModeInterface"> { + let description = [{ + Access to op rounding mode. + }]; + + let cppNamespace = "::mlir::arith"; + + let methods = [ + InterfaceMethod< + /*desc=*/ "Returns a RoundingModeAttr attribute for the operation", + /*returnType=*/ "RoundingModeAttr", + /*methodName=*/ "getRoundingModeAttr", + /*args=*/ (ins), + /*methodBody=*/ [{}], + /*defaultImpl=*/ [{ + auto op = cast<ConcreteOp>(this->getOperation()); + return op.getRoundingmodeAttr(); + }] + >, + StaticInterfaceMethod< + /*desc=*/ [{Returns the name of the RoundingModeAttr attribute for + the operation}], + /*returnType=*/ "StringRef", + /*methodName=*/ "getRoundingModeAttrName", + /*args=*/ (ins), + /*methodBody=*/ [{}], + /*defaultImpl=*/ [{ + return "roundingmode"; + }] + > + ]; +} + #endif // ARITH_OPS_INTERFACES diff --git a/mlir/include/mlir/Dialect/Arith/Transforms/BufferViewFlowOpInterfaceImpl.h b/mlir/include/mlir/Dialect/Arith/Transforms/BufferViewFlowOpInterfaceImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..a2b3a9bb655b8747fdbc7574c366259ed7e4d69a --- /dev/null +++ b/mlir/include/mlir/Dialect/Arith/Transforms/BufferViewFlowOpInterfaceImpl.h @@ -0,0 +1,20 @@ +//===- BufferViewFlowOpInterfaceImpl.h - Buffer View Analysis ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DIALECT_ARITH_TRANSFORMS_BUFFERVIEWFLOWOPINTERFACEIMPL_H +#define MLIR_DIALECT_ARITH_TRANSFORMS_BUFFERVIEWFLOWOPINTERFACEIMPL_H + +namespace mlir { +class DialectRegistry; + +namespace arith { +void registerBufferViewFlowOpInterfaceExternalModels(DialectRegistry ®istry); +} // namespace arith +} // namespace mlir + +#endif // MLIR_DIALECT_ARITH_TRANSFORMS_BUFFERVIEWFLOWOPINTERFACEIMPL_H diff --git a/mlir/include/mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.h b/mlir/include/mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.h new file mode 100644 index 0000000000000000000000000000000000000000..84e67fe72b623b16bc30d07663b0684d23e5bccb --- /dev/null +++ b/mlir/include/mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.h @@ -0,0 +1,27 @@ +//===- BufferViewFlowOpInterface.h - Buffer View Flow Analysis --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DIALECT_BUFFERIZATION_IR_BUFFERVIEWFLOWOPINTERFACE_H_ +#define MLIR_DIALECT_BUFFERIZATION_IR_BUFFERVIEWFLOWOPINTERFACE_H_ + +#include "mlir/IR/OpDefinition.h" +#include "mlir/Support/LLVM.h" + +namespace mlir { +class ValueRange; + +namespace bufferization { + +using RegisterDependenciesFn = std::function<void(ValueRange, ValueRange)>; + +} // namespace bufferization +} // namespace mlir + +#include "mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.h.inc" + +#endif // MLIR_DIALECT_BUFFERIZATION_IR_BUFFERVIEWFLOWOPINTERFACE_H_ diff --git a/mlir/include/mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.td b/mlir/include/mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.td new file mode 100644 index 0000000000000000000000000000000000000000..58885d742266476530e3589f322681e90b560034 --- /dev/null +++ b/mlir/include/mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.td @@ -0,0 +1,73 @@ +//===-- BufferViewFlowOpInterface.td - Buffer View Flow ----*- tablegen -*-===// +// +// 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 BUFFER_VIEW_FLOW_OP_INTERFACE +#define BUFFER_VIEW_FLOW_OP_INTERFACE + +include "mlir/IR/OpBase.td" + +def BufferViewFlowOpInterface : + OpInterface<"BufferViewFlowOpInterface"> { + let description = [{ + An op interface for the buffer view flow analysis. This interface describes + buffer dependencies between operands and op results/region entry block + arguments. + }]; + let cppNamespace = "::mlir::bufferization"; + let methods = [ + InterfaceMethod< + /*desc=*/[{ + Populate buffer dependencies between operands and op results/region + entry block arguments. + + Implementations should register dependencies between an operand ("X") + and an op result/region entry block argument ("Y") if Y may depend + on X. Y depends on X if Y and X are the same buffer or if Y is a + subview of X. + + Example: + ``` + %r = arith.select %c, %m1, %m2 : memref<5xf32> + ``` + In the above example, %0 may depend on %m1 or %m2 and a correct + interface implementation should call: + - "registerDependenciesFn(%m1, %r)". + - "registerDependenciesFn(%m2, %r)" + }], + /*retType=*/"void", + /*methodName=*/"populateDependencies", + /*args=*/(ins + "::mlir::bufferization::RegisterDependenciesFn" + :$registerDependenciesFn) + >, + InterfaceMethod< + /*desc=*/[{ + Return "true" if the given value may be a terminal buffer. A buffer + value is "terminal" if it cannot be traced back any further in the + buffer view flow analysis. + + Examples: A buffer could be terminal because: + - it is a newly allocated buffer (e.g., "memref.alloc"), + - or: because there is not enough compile-time information available + to make a definite decision (e.g., "memref.realloc" may reallocate + but we do not know for sure; another example are call ops where we + would have to analyze the body of the callee). + + Implementations can assume that the given SSA value is an OpResult of + this operation or a region entry block argument of this operation. + }], + /*retType=*/"bool", + /*methodName=*/"mayBeTerminalBuffer", + /*args=*/(ins "Value":$value), + /*methodBody=*/"", + /*defaultImplementation=*/"return false;" + >, + ]; +} + +#endif // BUFFER_VIEW_FLOW_OP_INTERFACE diff --git a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h index d8cfeee2466360a6cb26dc331187a9ad13968af9..2d8add82383bef61702c9009dbf064d0c0ef50da 100644 --- a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h +++ b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h @@ -142,11 +142,21 @@ public: /// This function adds an ALLOW entry. void allowDialect(StringRef dialectNamespace) { Entry::FilterFn filterFn = [=](Operation *op) { - return op->getDialect()->getNamespace() == dialectNamespace; + return op->getName().getDialectNamespace() == dialectNamespace; }; entries.push_back(Entry{filterFn, Entry::FilterType::ALLOW}); } + /// Deny the given dialect. + /// + /// This function adds a DENY entry. + void denyDialect(StringRef dialectNamespace) { + Entry::FilterFn filterFn = [=](Operation *op) { + return op->getDialect()->getNamespace() == dialectNamespace; + }; + entries.push_back(Entry{filterFn, Entry::FilterType::DENY}); + } + /// Allow the given ops. /// /// This function adds one or multiple ALLOW entries. @@ -356,10 +366,6 @@ struct BufferizationOptions { DefaultMemorySpaceFn defaultMemorySpaceFn = [](TensorType t) -> std::optional<Attribute> { return Attribute(); }; - /// Seed for the analysis fuzzer. If set to `0`, the fuzzer is deactivated. - /// Should be used only with `testAnalysisOnly = true`. - unsigned analysisFuzzerSeed = 0; - /// If set to `true`, the analysis is skipped. A buffer is copied before every /// write. This flag cannot be used together with `testAnalysisOnly = true`. bool copyBeforeWrite = false; diff --git a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizationOps.td b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizationOps.td index 9dc6afcaab31c86b48b34b6663d12f818efd1b7b..4f609ddff9a4138dc32d32fbda7d14463b0d6933 100644 --- a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizationOps.td +++ b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizationOps.td @@ -10,6 +10,7 @@ #define BUFFERIZATION_OPS include "mlir/Dialect/Bufferization/IR/AllocationOpInterface.td" +include "mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.td" include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.td" include "mlir/Dialect/Bufferization/IR/BufferizationBase.td" include "mlir/Interfaces/DestinationStyleOpInterface.td" diff --git a/mlir/include/mlir/Dialect/Bufferization/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/Bufferization/IR/CMakeLists.txt index 31a553f9a32f55449d11a0123e9a8d94c8b8e93d..13a5bc370a4fce492ca474aa28cb22ebf983f2ef 100644 --- a/mlir/include/mlir/Dialect/Bufferization/IR/CMakeLists.txt +++ b/mlir/include/mlir/Dialect/Bufferization/IR/CMakeLists.txt @@ -3,6 +3,7 @@ add_mlir_doc(BufferizationOps BufferizationOps Dialects/ -gen-dialect-doc) add_mlir_interface(AllocationOpInterface) add_mlir_interface(BufferDeallocationOpInterface) add_mlir_interface(BufferizableOpInterface) +add_mlir_interface(BufferViewFlowOpInterface) set(LLVM_TARGET_DEFINITIONS BufferizationEnums.td) mlir_tablegen(BufferizationEnums.h.inc -gen-enum-decls) diff --git a/mlir/include/mlir/Dialect/Bufferization/TransformOps/BufferizationTransformOps.h b/mlir/include/mlir/Dialect/Bufferization/TransformOps/BufferizationTransformOps.h index 75ce4b484165b285d0b90a10aff6f1acaf89083b..1dbe29b444134f5db56f0daf8974403cc5feed49 100644 --- a/mlir/include/mlir/Dialect/Bufferization/TransformOps/BufferizationTransformOps.h +++ b/mlir/include/mlir/Dialect/Bufferization/TransformOps/BufferizationTransformOps.h @@ -11,8 +11,8 @@ #include "mlir/Bytecode/BytecodeOpInterface.h" #include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformTypes.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpImplementation.h" namespace mlir { diff --git a/mlir/include/mlir/Dialect/Bufferization/TransformOps/BufferizationTransformOps.td b/mlir/include/mlir/Dialect/Bufferization/TransformOps/BufferizationTransformOps.td index 9b588eb610e51b8c40a28733369bc28ae3ad59a5..5ace9c390e146e2f2b5e2640a90ff59e469de6e3 100644 --- a/mlir/include/mlir/Dialect/Bufferization/TransformOps/BufferizationTransformOps.td +++ b/mlir/include/mlir/Dialect/Bufferization/TransformOps/BufferizationTransformOps.td @@ -11,7 +11,7 @@ include "mlir/Dialect/Bufferization/IR/BufferizationEnums.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Dialect/Transform/IR/TransformTypes.td" include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/IR/OpBase.td" diff --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/BufferViewFlowAnalysis.h b/mlir/include/mlir/Dialect/Bufferization/Transforms/BufferViewFlowAnalysis.h index 24825db69f90c505ff83f561bc47e1f1132334c6..4015231c845daf9bb474f062d25c2ef30b1e6a1c 100644 --- a/mlir/include/mlir/Dialect/Bufferization/Transforms/BufferViewFlowAnalysis.h +++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/BufferViewFlowAnalysis.h @@ -53,6 +53,7 @@ public: /// /// Results in resolve(B) returning {B, C} ValueSetT resolve(Value value) const; + ValueSetT resolveReverse(Value value) const; /// Removes the given values from all alias sets. void remove(const SetVector<Value> &aliasValues); @@ -63,6 +64,9 @@ public: /// results have to be changed. void rename(Value from, Value to); + /// Returns "true" if the given value may be a terminal. + bool mayBeTerminalBuffer(Value value) const; + private: /// This function constructs a mapping from values to its immediate /// dependencies. @@ -70,6 +74,44 @@ private: /// Maps values to all immediate dependencies this value can have. ValueMapT dependencies; + ValueMapT reverseDependencies; + + /// A set of all SSA values that may be terminal buffers. + DenseSet<Value> terminals; +}; + +/// An is-same-buffer analysis that checks if two SSA values belong to the same +/// buffer allocation or not. +class BufferOriginAnalysis { +public: + BufferOriginAnalysis(Operation *op); + + /// Return "true" if `v1` and `v2` originate from the same buffer allocation. + /// Return "false" if `v1` and `v2` originate from different allocations. + /// Return "nullopt" if we do not know for sure. + /// + /// Example 1: isSameAllocation(%0, %1) == true + /// ``` + /// %0 = memref.alloc() + /// %1 = memref.subview %0 + /// ``` + /// + /// Example 2: isSameAllocation(%0, %1) == false + /// ``` + /// %0 = memref.alloc() + /// %1 = memref.alloc() + /// ``` + /// + /// Example 3: isSameAllocation(%0, %2) == nullopt + /// ``` + /// %0 = memref.alloc() + /// %1 = memref.alloc() + /// %2 = arith.select %c, %0, %1 + /// ``` + std::optional<bool> isSameAllocation(Value v1, Value v2); + +private: + BufferViewFlowAnalysis analysis; }; } // namespace mlir diff --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/OneShotAnalysis.h b/mlir/include/mlir/Dialect/Bufferization/Transforms/OneShotAnalysis.h index a29af853eb21ba664c8e15bb90432059628949ec..d50a3042aeeacf083457fb840e5e0396fc6642bc 100644 --- a/mlir/include/mlir/Dialect/Bufferization/Transforms/OneShotAnalysis.h +++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/OneShotAnalysis.h @@ -24,7 +24,12 @@ class OneShotAnalysisState; /// Options for analysis-enabled bufferization. struct OneShotBufferizationOptions : public BufferizationOptions { - enum class AnalysisHeuristic { BottomUp, TopDown }; + enum class AnalysisHeuristic { + BottomUp, + TopDown, + BottomUpFromTerminators, + Fuzzer + }; OneShotBufferizationOptions() = default; @@ -42,6 +47,11 @@ struct OneShotBufferizationOptions : public BufferizationOptions { /// Specify the functions that should not be analyzed. copyBeforeWrite will be /// set to true when bufferizing them. llvm::ArrayRef<std::string> noAnalysisFuncFilter; + + /// Seed for the analysis fuzzer. Used only if the heuristic is set to + /// `AnalysisHeuristic::Fuzzer`. The fuzzer should be used only with + /// `testAnalysisOnly = true`. + unsigned analysisFuzzerSeed = 0; }; /// State for analysis-enabled bufferization. This class keeps track of alias diff --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h index 809f03407258a8a2018454d234c7bc3cd8ddfb19..a729bc99b987cd405746f2a950763b178281cfd1 100644 --- a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h +++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h @@ -148,7 +148,7 @@ std::unique_ptr<Pass> createBufferLoopHoistingPass(); // Options struct for BufferResultsToOutParams pass. // Note: defined only here, not in tablegen. -struct BufferResultsToOutParamsOptions { +struct BufferResultsToOutParamsOpts { /// Memcpy function: Generate a memcpy between two memrefs. using MemCpyFn = std::function<LogicalResult(OpBuilder &, Location, Value, Value)>; @@ -162,17 +162,21 @@ struct BufferResultsToOutParamsOptions { /// Memcpy function; used to create a copy between two memrefs. /// If this is empty, memref.copy is used. std::optional<MemCpyFn> memCpyFn; + + /// If true, the pass adds a "bufferize.result" attribute to each output + /// parameter. + bool addResultAttribute = false; }; /// Creates a pass that converts memref function results to out-params. std::unique_ptr<Pass> createBufferResultsToOutParamsPass( - const BufferResultsToOutParamsOptions &options = {}); + const BufferResultsToOutParamsOpts &options = {}); /// Replace buffers that are returned from a function with an out parameter. /// Also update all call sites. LogicalResult promoteBufferResultsToOutParams(ModuleOp module, - const BufferResultsToOutParamsOptions &options); + const BufferResultsToOutParamsOpts &options); /// Creates a pass that drops memref function results that are equivalent to a /// function argument. diff --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td index e01f36b8daa18d6a01b65ffac3a7eeb84be76e38..1303dc2c9ae10f74710d8dc8faf94a4fc39cf417 100644 --- a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td +++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td @@ -316,6 +316,11 @@ def BufferResultsToOutParams : Pass<"buffer-results-to-out-params", "ModuleOp"> buffers for results need to be allocated in the caller. This currently only works for static shaped memrefs. }]; + let options = [ + Option<"addResultAttribute", "add-result-attr", "bool", + /*default=*/"false", + "Add the attribute 'bufferize.result' to all output parameters.">, + ]; let constructor = "mlir::bufferization::createBufferResultsToOutParamsPass()"; let dependentDialects = ["memref::MemRefDialect"]; } @@ -454,6 +459,24 @@ def OneShotBufferize : Pass<"one-shot-bufferize", "ModuleOp"> { argument is read/written and which returned values are aliasing/equivalent. For debugging purposes, such information can be printed with `test-analysis-only`. + + The order in which ops are analyzed is important. The analysis is greedy and + ops that are analyzed earlier are more likely to bufferize in-place. The + heuristic can be set with `analysis-heuristic`. At the moment, the following + heuristics are available: + + * `bottom-up` (default): Analyze ops from bottom to top. + * `top-down`: Analyze ops from top to bottom. + * `fuzzer`: Randomize the ordering of ops with `analysis-fuzzer-seed`. + * `bottom-up-from-terminators`: Traverse the reverse use-def chains of + tensor IR, starting from region branch terminators (bottom-up). Nested + regions are traversed before enclosing regions. Analyze the traversed ops + first, then analyze the remaining ops bottom-up. This heuristic is useful + for bufferizing loop constructs. One-Shot Bufferize currently supports + only such IR where yielded tensor values bufferize to equivalent region + iter_args, and first analyzing all ops on the path from the "yielding" op + to the beginning of the loop body makes it more likely for the region + iter_args and yielded values to bufferize to equivalent buffers. }]; let options = [ Option<"allowReturnAllocsFromLoops", "allow-return-allocs-from-loops", diff --git a/mlir/include/mlir/Dialect/Complex/IR/ComplexOps.td b/mlir/include/mlir/Dialect/Complex/IR/ComplexOps.td index e19d714cadf8a9496ac45741b34a85ee624aaf4d..d660292478b1909ef9687e3b5ff4ccb62580793b 100644 --- a/mlir/include/mlir/Dialect/Complex/IR/ComplexOps.td +++ b/mlir/include/mlir/Dialect/Complex/IR/ComplexOps.td @@ -225,6 +225,8 @@ def DivOp : ComplexArithmeticOp<"div"> { %a = complex.div %b, %c : complex<f32> ``` }]; + + let hasFolder = 1; } //===----------------------------------------------------------------------===// diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h index 1f0df3cb336b1243a4ee33b6ebd69661637d97ff..725a1bcb4e6cb11c5101be1460e0c3e5819d70a6 100644 --- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h +++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h @@ -30,6 +30,10 @@ namespace mlir { namespace emitc { void buildTerminatedBody(OpBuilder &builder, Location loc); +/// Determines whether \p type is a valid integer type in EmitC. +bool isSupportedIntegerType(mlir::Type type); +/// Determines whether \p type is a valid floating-point type in EmitC. +bool isSupportedFloatType(mlir::Type type); } // namespace emitc } // namespace mlir diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td index ec842f76628c080aa596c4931d756c2666b1b278..d746222ff37a4b4da906fa49949831971f8616c8 100644 --- a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td +++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td @@ -51,8 +51,8 @@ class EmitC_BinaryOp<string mnemonic, list<Trait> traits = []> : def CExpression : NativeOpTrait<"emitc::CExpression">; // Types only used in binary arithmetic operations. -def IntegerIndexOrOpaqueType : AnyTypeOf<[AnyInteger, Index, EmitC_OpaqueType]>; -def FloatIntegerIndexOrOpaqueType : AnyTypeOf<[AnyFloat, IntegerIndexOrOpaqueType]>; +def IntegerIndexOrOpaqueType : AnyTypeOf<[EmitCIntegerType, Index, EmitC_OpaqueType]>; +def FloatIntegerIndexOrOpaqueType : AnyTypeOf<[EmitCFloatType, IntegerIndexOrOpaqueType]>; def EmitC_AddOp : EmitC_BinaryOp<"add", [CExpression]> { let summary = "Addition operation"; @@ -1155,4 +1155,36 @@ def EmitC_IfOp : EmitC_Op<"if", let hasCustomAssemblyFormat = 1; } +def EmitC_SubscriptOp : EmitC_Op<"subscript", + [TypesMatchWith<"result type matches element type of 'array'", + "array", "result", + "::llvm::cast<ArrayType>($_self).getElementType()">]> { + let summary = "Array subscript operation"; + let description = [{ + With the `subscript` operation the subscript operator `[]` can be applied + to variables or arguments of array type. + + Example: + + ```mlir + %i = index.constant 1 + %j = index.constant 7 + %0 = emitc.subscript %arg0[%i, %j] : <4x8xf32>, index, index + ``` + }]; + let arguments = (ins Arg<EmitC_ArrayType, "the reference to load from">:$array, + Variadic<IntegerIndexOrOpaqueType>:$indices); + let results = (outs AnyType:$result); + + let builders = [ + OpBuilder<(ins "Value":$array, "ValueRange":$indices), [{ + build($_builder, $_state, cast<ArrayType>(array.getType()).getElementType(), array, indices); + }]> + ]; + + let hasVerifier = 1; + let assemblyFormat = "$array `[` $indices `]` attr-dict `:` type($array) `,` type($indices)"; +} + + #endif // MLIR_DIALECT_EMITC_IR_EMITC diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td index 1ff41022eba8c93677e81a85b89a7b40e3afd019..bce5807230ce4999bbaf837a4704c4384f47e7a0 100644 --- a/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td +++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td @@ -22,6 +22,12 @@ include "mlir/IR/BuiltinTypeInterfaces.td" // EmitC type definitions //===----------------------------------------------------------------------===// +def EmitCIntegerType : Type<CPred<"emitc::isSupportedIntegerType($_self)">, + "integer type supported by EmitC">; + +def EmitCFloatType : Type<CPred<"emitc::isSupportedFloatType($_self)">, + "floating-point type supported by EmitC">; + class EmitC_Type<string name, string typeMnemonic, list<Trait> traits = []> : TypeDef<EmitC_Dialect, name, traits> { let mnemonic = typeMnemonic; @@ -39,7 +45,7 @@ def EmitC_ArrayType : EmitC_Type<"Array", "array", [ShapedTypeInterface]> { // Array emitted as `int32_t[10]` !emitc.array<10xi32> // Array emitted as `float[10][20]` - !emitc.ptr<10x20xf32> + !emitc.array<10x20xf32> ``` }]; diff --git a/mlir/include/mlir/Dialect/Func/TransformOps/FuncTransformOps.h b/mlir/include/mlir/Dialect/Func/TransformOps/FuncTransformOps.h index 8d0b97da95d49252355103e49d02a7ccf766858c..37f0ea0f28552240de3d2eefed9e0d6dbae3d8a0 100644 --- a/mlir/include/mlir/Dialect/Func/TransformOps/FuncTransformOps.h +++ b/mlir/include/mlir/Dialect/Func/TransformOps/FuncTransformOps.h @@ -10,7 +10,7 @@ #define MLIR_DIALECT_FUNC_TRANSFORMOPS_FUNCTRANSFORMOPS_H #include "mlir/Bytecode/BytecodeOpInterface.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpImplementation.h" #define GET_OP_CLASSES diff --git a/mlir/include/mlir/Dialect/Func/TransformOps/FuncTransformOps.td b/mlir/include/mlir/Dialect/Func/TransformOps/FuncTransformOps.td index c36fdd1505562089e88b154b127d9c243dbf41d8..306fbf881de61dbe80ff5a4f6144e18de5a7f051 100644 --- a/mlir/include/mlir/Dialect/Func/TransformOps/FuncTransformOps.td +++ b/mlir/include/mlir/Dialect/Func/TransformOps/FuncTransformOps.td @@ -10,7 +10,7 @@ #define FUNC_TRANSFORM_OPS include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Dialect/Transform/IR/TransformTypes.td" include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/IR/RegionKindInterface.td" diff --git a/mlir/include/mlir/Dialect/GPU/TransformOps/GPUTransformOps.h b/mlir/include/mlir/Dialect/GPU/TransformOps/GPUTransformOps.h index d6612c7c0b7ff40c2ffa67df0265bfccb985a767..4b5f684525046b8b0656b97516ae55849d8d3851 100644 --- a/mlir/include/mlir/Dialect/GPU/TransformOps/GPUTransformOps.h +++ b/mlir/include/mlir/Dialect/GPU/TransformOps/GPUTransformOps.h @@ -10,7 +10,7 @@ #define MLIR_DIALECT_GPU_TRANSFORMOPS_GPUTRANSFORMOPS_H #include "mlir/Dialect/SCF/IR/SCF.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/PatternMatch.h" diff --git a/mlir/include/mlir/Dialect/GPU/TransformOps/GPUTransformOps.td b/mlir/include/mlir/Dialect/GPU/TransformOps/GPUTransformOps.td index 616a82b08a6148323c01bd0ad8ce40302c87d029..80b4547c32c101d6828f4c553c925502f60433fc 100644 --- a/mlir/include/mlir/Dialect/GPU/TransformOps/GPUTransformOps.td +++ b/mlir/include/mlir/Dialect/GPU/TransformOps/GPUTransformOps.td @@ -10,7 +10,7 @@ #define GPU_TRANSFORM_OPS include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/IR/OpBase.td" diff --git a/mlir/include/mlir/Dialect/GPU/TransformOps/Utils.h b/mlir/include/mlir/Dialect/GPU/TransformOps/Utils.h index c65f522e01876975eec28a1568940d7366d7183c..52fc6f4d5c71b3183258afb3622729aa1585b4b9 100644 --- a/mlir/include/mlir/Dialect/GPU/TransformOps/Utils.h +++ b/mlir/include/mlir/Dialect/GPU/TransformOps/Utils.h @@ -11,7 +11,7 @@ #include "mlir/Dialect/GPU/IR/GPUDialect.h" #include "mlir/Dialect/SCF/IR/DeviceMappingInterface.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/PatternMatch.h" diff --git a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt index 862abf00d034505e71faac7d13796ff1f67681df..759de745440c211e05d1184f53dfda533564676a 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt +++ b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt @@ -29,6 +29,8 @@ add_mlir_doc(LLVMIntrinsicOps LLVMIntrinsicOps Dialects/ -gen-op-doc) set(LLVM_TARGET_DEFINITIONS LLVMInterfaces.td) mlir_tablegen(LLVMInterfaces.h.inc -gen-op-interface-decls) mlir_tablegen(LLVMInterfaces.cpp.inc -gen-op-interface-defs) +mlir_tablegen(LLVMAttrInterfaces.h.inc -gen-attr-interface-decls) +mlir_tablegen(LLVMAttrInterfaces.cpp.inc -gen-attr-interface-defs) mlir_tablegen(LLVMTypeInterfaces.h.inc -gen-type-interface-decls) mlir_tablegen(LLVMTypeInterfaces.cpp.inc -gen-type-interface-defs) add_public_tablegen_target(MLIRLLVMInterfacesIncGen) diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td index a831b076fb864f155c832a1bf7170450ce3fc391..91bd3702f93b9798829ac2b2698cfe66708c42ea 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td @@ -10,6 +10,7 @@ #define LLVMIR_ATTRDEFS include "mlir/Dialect/LLVMIR/LLVMDialect.td" +include "mlir/Dialect/LLVMIR/LLVMInterfaces.td" include "mlir/IR/AttrTypeBase.td" include "mlir/IR/CommonAttrConstraints.td" @@ -238,7 +239,7 @@ def LoopAnnotationAttr : LLVM_Attr<"LoopAnnotation", "loop_annotation"> { //===----------------------------------------------------------------------===// class LLVM_DIParameter<string summary, string default, string parseName, - string printName = parseName> + string errorCase, string printName = parseName> : AttrOrTypeParameter<"unsigned", "debug info " # summary> { let parser = [{ [&]() -> FailureOr<unsigned> { SMLoc tagLoc = $_parser.getCurrentLocation(); @@ -246,33 +247,35 @@ class LLVM_DIParameter<string summary, string default, string parseName, if ($_parser.parseKeyword(&name)) return failure(); - if (unsigned tag = llvm::dwarf::get}] # parseName # [{(name)) - return tag; - return $_parser.emitError(tagLoc) - << "invalid debug info }] # summary # [{ name: " << name; + unsigned tag = llvm::dwarf::get}] # parseName # [{(name); + if (tag == }] # errorCase # [{) + return $_parser.emitError(tagLoc) + << "invalid debug info }] # summary # [{ name: " << name; + return tag; }() }]; let printer = "$_printer << llvm::dwarf::" # printName # "String($_self)"; let defaultValue = default; } def LLVM_DICallingConventionParameter : LLVM_DIParameter< - "calling convention", /*default=*/"0", "CallingConvention", "Convention" + "calling convention", /*default=*/"0", "CallingConvention", /*errorCase=*/"0", + "Convention" >; def LLVM_DIEncodingParameter : LLVM_DIParameter< - "encoding", /*default=*/"0", "AttributeEncoding" + "encoding", /*default=*/"0", "AttributeEncoding", /*errorCase=*/"0" >; def LLVM_DILanguageParameter : LLVM_DIParameter< - "language", /*default=*/"", "Language" + "language", /*default=*/"", "Language", /*errorCase=*/"0" >; def LLVM_DITagParameter : LLVM_DIParameter< - "tag", /*default=*/"", "Tag" + "tag", /*default=*/"", "Tag", /*errorCase=*/"llvm::dwarf::DW_TAG_invalid" >; def LLVM_DIOperationEncodingParameter : LLVM_DIParameter< - "operation encoding", /*default=*/"", "OperationEncoding" + "operation encoding", /*default=*/"", "OperationEncoding", /*errorCase=*/"0" >; //===----------------------------------------------------------------------===// @@ -357,9 +360,11 @@ def LLVM_DICompileUnitAttr : LLVM_Attr<"DICompileUnit", "di_compile_unit", //===----------------------------------------------------------------------===// def LLVM_DICompositeTypeAttr : LLVM_Attr<"DICompositeType", "di_composite_type", - /*traits=*/[], "DITypeAttr"> { + [LLVM_DIRecursiveTypeAttrInterface], + "DITypeAttr"> { let parameters = (ins LLVM_DITagParameter:$tag, + OptionalParameter<"DistinctAttr">:$recId, OptionalParameter<"StringAttr">:$name, OptionalParameter<"DIFileAttr">:$file, OptionalParameter<"uint32_t">:$line, @@ -371,6 +376,21 @@ def LLVM_DICompositeTypeAttr : LLVM_Attr<"DICompositeType", "di_composite_type", OptionalArrayRefParameter<"DINodeAttr">:$elements ); let assemblyFormat = "`<` struct(params) `>`"; + let extraClassDeclaration = [{ + /// Requirements of DIRecursiveTypeAttrInterface. + /// @{ + + /// Get whether this attr describes a recursive self reference. + bool isRecSelf() { return getTag() == 0; } + + /// Get a copy of this type attr but with the recursive ID set to `recId`. + DIRecursiveTypeAttrInterface withRecId(DistinctAttr recId); + + /// Build a rec-self instance using the provided `recId`. + static DIRecursiveTypeAttrInterface getRecSelf(DistinctAttr recId); + + /// @} + }]; } //===----------------------------------------------------------------------===// @@ -385,7 +405,8 @@ def LLVM_DIDerivedTypeAttr : LLVM_Attr<"DIDerivedType", "di_derived_type", OptionalParameter<"DITypeAttr">:$baseType, OptionalParameter<"uint64_t">:$sizeInBits, OptionalParameter<"uint32_t">:$alignInBits, - OptionalParameter<"uint64_t">:$offsetInBits + OptionalParameter<"uint64_t">:$offsetInBits, + OptionalParameter<"DINodeAttr">:$extraData ); let assemblyFormat = "`<` struct(params) `>`"; } @@ -525,7 +546,7 @@ def LLVM_DISubprogramAttr : LLVM_Attr<"DISubprogram", "di_subprogram", "DIFileAttr":$file, OptionalParameter<"unsigned">:$line, OptionalParameter<"unsigned">:$scopeLine, - "DISubprogramFlags":$subprogramFlags, + OptionalParameter<"DISubprogramFlags">:$subprogramFlags, OptionalParameter<"DISubroutineTypeAttr">:$type ); let builders = [ diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h index c370bfa2b733d65f3387a1c5ea24350951b11ce7..091a817caf3d6e0f76922d6ac801e042720b6d8b 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h @@ -84,6 +84,8 @@ using linkage::Linkage; } // namespace LLVM } // namespace mlir +#include "mlir/Dialect/LLVMIR/LLVMAttrInterfaces.h.inc" + #define GET_ATTRDEF_CLASSES #include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.h.inc" diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h index 06df4a601b7a3f7bf0cccd066c140b531862cd94..9341a5a11cd629020326e87f2b25bffd23b717e2 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h @@ -30,7 +30,6 @@ #include "mlir/Interfaces/InferTypeOpInterface.h" #include "mlir/Interfaces/SideEffectInterfaces.h" #include "mlir/Support/ThreadLocalCache.h" -#include "mlir/Transforms/Mem2Reg.h" #include "llvm/ADT/PointerEmbeddedInt.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/LLVMContext.h" diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td index a7b269eb41ee2e3660f8b5a77d93c54d7568572e..04d797031245e306a824f2de934dbaec9df87e46 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td @@ -705,4 +705,61 @@ def FramePointerKindEnum : LLVM_EnumAttr< let cppNamespace = "::mlir::LLVM::framePointerKind"; } +//===----------------------------------------------------------------------===// +// RoundingMode +//===----------------------------------------------------------------------===// + +// These values must match llvm::RoundingMode ones. +// See llvm/include/llvm/ADT/FloatingPointMode.h. +def RoundTowardZero + : LLVM_EnumAttrCase<"TowardZero", "towardzero", "TowardZero", 0>; +def RoundNearestTiesToEven + : LLVM_EnumAttrCase<"NearestTiesToEven", "tonearest", "NearestTiesToEven", 1>; +def RoundTowardPositive + : LLVM_EnumAttrCase<"TowardPositive", "upward", "TowardPositive", 2>; +def RoundTowardNegative + : LLVM_EnumAttrCase<"TowardNegative", "downward", "TowardNegative", 3>; +def RoundNearestTiesToAway + : LLVM_EnumAttrCase<"NearestTiesToAway", "tonearestaway", "NearestTiesToAway", 4>; +def RoundDynamic + : LLVM_EnumAttrCase<"Dynamic", "dynamic", "Dynamic", 7>; +// Needed as llvm::RoundingMode defines this. +def RoundInvalid + : LLVM_EnumAttrCase<"Invalid", "invalid", "Invalid", -1>; + +// RoundingModeAttr should not be used in operations definitions. +// Use ValidRoundingModeAttr instead. +def RoundingModeAttr : LLVM_EnumAttr< + "RoundingMode", + "::llvm::RoundingMode", + "LLVM Rounding Mode", + [RoundTowardZero, RoundNearestTiesToEven, RoundTowardPositive, + RoundTowardNegative, RoundNearestTiesToAway, RoundDynamic, RoundInvalid]> { + let cppNamespace = "::mlir::LLVM"; +} + +def ValidRoundingModeAttr : ConfinedAttr<RoundingModeAttr, [IntMinValue<0>]>; + +//===----------------------------------------------------------------------===// +// FPExceptionBehavior +//===----------------------------------------------------------------------===// + +// These values must match llvm::fp::ExceptionBehavior ones. +// See llvm/include/llvm/IR/FPEnv.h. +def FPExceptionBehaviorIgnore + : LLVM_EnumAttrCase<"Ignore", "ignore", "ebIgnore", 0>; +def FPExceptionBehaviorMayTrap + : LLVM_EnumAttrCase<"MayTrap", "maytrap", "ebMayTrap", 1>; +def FPExceptionBehaviorStrict + : LLVM_EnumAttrCase<"Strict", "strict", "ebStrict", 2>; + +def FPExceptionBehaviorAttr : LLVM_EnumAttr< + "FPExceptionBehavior", + "::llvm::fp::ExceptionBehavior", + "LLVM Exception Behavior", + [FPExceptionBehaviorIgnore, FPExceptionBehaviorMayTrap, + FPExceptionBehaviorStrict]> { + let cppNamespace = "::mlir::LLVM"; +} + #endif // LLVMIR_ENUMS diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td index 3b2a132a881e4edcec2146e3d7b22d0918e8ba75..cee752aeb269b7221f2ff20c03c626c8c8e02f37 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines op and type interfaces for the LLVM dialect in MLIR. +// This file defines interfaces for the LLVM dialect in MLIR. // //===----------------------------------------------------------------------===// @@ -290,6 +290,73 @@ def GetResultPtrElementType : OpInterface<"GetResultPtrElementType"> { ]; } +def FPExceptionBehaviorOpInterface : OpInterface<"FPExceptionBehaviorOpInterface"> { + let description = [{ + An interface for operations receiving an exception behavior attribute + controlling FP exception behavior. + }]; + + let cppNamespace = "::mlir::LLVM"; + + let methods = [ + InterfaceMethod< + /*desc=*/ "Returns a FPExceptionBehavior attribute for the operation", + /*returnType=*/ "FPExceptionBehaviorAttr", + /*methodName=*/ "getFPExceptionBehaviorAttr", + /*args=*/ (ins), + /*methodBody=*/ [{}], + /*defaultImpl=*/ [{ + auto op = cast<ConcreteOp>(this->getOperation()); + return op.getFpExceptionBehaviorAttr(); + }] + >, + StaticInterfaceMethod< + /*desc=*/ [{Returns the name of the FPExceptionBehaviorAttr + attribute for the operation}], + /*returnType=*/ "StringRef", + /*methodName=*/ "getFPExceptionBehaviorAttrName", + /*args=*/ (ins), + /*methodBody=*/ [{}], + /*defaultImpl=*/ [{ + return "fpExceptionBehavior"; + }] + > + ]; +} + +def RoundingModeOpInterface : OpInterface<"RoundingModeOpInterface"> { + let description = [{ + An interface for operations receiving a rounding mode attribute + controlling FP rounding mode. + }]; + + let cppNamespace = "::mlir::LLVM"; + + let methods = [ + InterfaceMethod< + /*desc=*/ "Returns a RoundingMode attribute for the operation", + /*returnType=*/ "RoundingModeAttr", + /*methodName=*/ "getRoundingModeAttr", + /*args=*/ (ins), + /*methodBody=*/ [{}], + /*defaultImpl=*/ [{ + auto op = cast<ConcreteOp>(this->getOperation()); + return op.getRoundingmodeAttr(); + }] + >, + StaticInterfaceMethod< + /*desc=*/ [{Returns the name of the RoundingModeAttr attribute + for the operation}], + /*returnType=*/ "StringRef", + /*methodName=*/ "getRoundingModeAttrName", + /*args=*/ (ins), + /*methodBody=*/ [{}], + /*defaultImpl=*/ [{ + return "roundingmode"; + }] + >, + ]; +} //===----------------------------------------------------------------------===// // LLVM dialect type interfaces. @@ -319,4 +386,58 @@ def LLVM_PointerElementTypeInterface ]; } +//===----------------------------------------------------------------------===// +// LLVM dialect attr interfaces. +//===----------------------------------------------------------------------===// + +def LLVM_DIRecursiveTypeAttrInterface + : AttrInterface<"DIRecursiveTypeAttrInterface"> { + let description = [{ + This attribute represents a DITypeAttr that is recursive. Only DITypeAttrs + that translate to LLVM DITypes that support mutation should implement this + interface. + + There are two modes for conforming attributes: + + 1. "rec-decl": + - This attr is a recursive declaration identified by a recId. + + 2. "rec-self": + - This attr is considered a recursive self reference. + - This attr itself is a placeholder type that should be conceptually + replaced with the closest parent attr of the same type with the same + recId. + + For example, to represent a linked list struct: + + #rec_self = di_composite_type<recId = 0> + #ptr = di_derived_type<baseType: #rec_self, ...> + #field = di_derived_type<name = "next", baseType: #ptr, ...> + #rec = di_composite_type<recId = 0, name = "Node", elements: #field, ...> + #var = di_local_variable<type = #rec, ...> + + Note that a rec-self without an outer rec-decl with the same recId is + conceptually the same as an "unbound" variable. The context needs to provide + meaning to the rec-self. + }]; + let cppNamespace = "::mlir::LLVM"; + let methods = [ + InterfaceMethod<[{ + Get whether this attr describes a recursive self reference. + }], "bool", "isRecSelf", (ins)>, + InterfaceMethod<[{ + Get the recursive ID used for matching "rec-decl" with "rec-self". + If this attr instance is not recursive, return a null attribute. + }], "DistinctAttr", "getRecId", (ins)>, + InterfaceMethod<[{ + Get a copy of this type attr but with the recursive ID set to `recId`. + }], "DIRecursiveTypeAttrInterface", "withRecId", + (ins "DistinctAttr":$recId)>, + StaticInterfaceMethod<[{ + Build a rec-self instance using the provided `recId`. + }], "DIRecursiveTypeAttrInterface", "getRecSelf", + (ins "DistinctAttr":$recId)> + ]; +} + #endif // LLVMIR_INTERFACES diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td index b88f1186a44b49b02dcaabc0d248bff749ad33b8..28526f1a1560ce9346baae8456752716e4b909cc 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td @@ -311,6 +311,91 @@ def LLVM_InvariantEndOp : LLVM_ZeroResultIntrOp<"invariant.end", [2], "qualified(type($ptr))"; } +// Constrained Floating-Point Intrinsics. + +class LLVM_ConstrainedIntr<string mnem, int numArgs, + bit overloadedResult, list<int> overloadedOperands, + bit hasRoundingMode> + : LLVM_OneResultIntrOp<"experimental.constrained." # mnem, + /*overloadedResults=*/ + !cond(!gt(overloadedResult, 0) : [0], + true : []), + overloadedOperands, + /*traits=*/[Pure, DeclareOpInterfaceMethods<FPExceptionBehaviorOpInterface>] + # !cond( + !gt(hasRoundingMode, 0) : [DeclareOpInterfaceMethods<RoundingModeOpInterface>], + true : []), + /*requiresFastmath=*/0, + /*immArgPositions=*/[], + /*immArgAttrNames=*/[]> { + dag regularArgs = !dag(ins, !listsplat(LLVM_Type, numArgs), !foreach(i, !range(numArgs), "arg_" #i)); + dag attrArgs = !con(!cond(!gt(hasRoundingMode, 0) : (ins ValidRoundingModeAttr:$roundingmode), + true : (ins)), + (ins FPExceptionBehaviorAttr:$fpExceptionBehavior)); + let arguments = !con(regularArgs, attrArgs); + let llvmBuilder = [{ + SmallVector<llvm::Value *> args = + moduleTranslation.lookupValues(opInst.getOperands()); + SmallVector<llvm::Type *> overloadedTypes; }] # + !cond(!gt(overloadedResult, 0) : [{ + // Take into account overloaded result type. + overloadedTypes.push_back($_resultType); }], + // No overloaded result type. + true : "") # [{ + llvm::transform(ArrayRef<unsigned>}] # overloadedOperandsCpp # [{, + std::back_inserter(overloadedTypes), + [&args](unsigned index) { return args[index]->getType(); }); + llvm::Module *module = builder.GetInsertBlock()->getModule(); + llvm::Function *callee = + llvm::Intrinsic::getDeclaration(module, + llvm::Intrinsic::experimental_constrained_}] # + mnem # [{, overloadedTypes); }] # + !cond(!gt(hasRoundingMode, 0) : [{ + // Get rounding mode using interface. + llvm::RoundingMode rounding = + moduleTranslation.translateRoundingMode($roundingmode); }], + true : [{ + // No rounding mode. + std::optional<llvm::RoundingMode> rounding; }]) # [{ + llvm::fp::ExceptionBehavior except = + moduleTranslation.translateFPExceptionBehavior($fpExceptionBehavior); + $res = builder.CreateConstrainedFPCall(callee, args, "", rounding, except); + }]; + let mlirBuilder = [{ + SmallVector<Value> mlirOperands; + SmallVector<NamedAttribute> mlirAttrs; + if (failed(moduleImport.convertIntrinsicArguments( + llvmOperands.take_front( }] # numArgs # [{), + {}, {}, mlirOperands, mlirAttrs))) { + return failure(); + } + + FPExceptionBehaviorAttr fpExceptionBehaviorAttr = + $_fpExceptionBehavior_attr($fpExceptionBehavior); + mlirAttrs.push_back( + $_builder.getNamedAttr( + $_qualCppClassName::getFPExceptionBehaviorAttrName(), + fpExceptionBehaviorAttr)); }] # + !cond(!gt(hasRoundingMode, 0) : [{ + RoundingModeAttr roundingModeAttr = $_roundingMode_attr($roundingmode); + mlirAttrs.push_back( + $_builder.getNamedAttr($_qualCppClassName::getRoundingModeAttrName(), + roundingModeAttr)); + }], true : "") # [{ + $res = $_builder.create<$_qualCppClassName>($_location, + $_resultType, mlirOperands, mlirAttrs); + }]; +} + +def LLVM_ConstrainedFPTruncIntr + : LLVM_ConstrainedIntr<"fptrunc", /*numArgs=*/1, + /*overloadedResult=*/1, /*overloadedOperands=*/[0], + /*hasRoundingMode=*/1> { + let assemblyFormat = [{ + $arg_0 $roundingmode $fpExceptionBehavior attr-dict `:` type($arg_0) `to` type(results) + }]; +} + // Intrinsics with multiple returns. class LLVM_ArithWithOverflowOp<string mnem> @@ -526,19 +611,19 @@ def LLVM_DbgLabelOp : LLVM_IntrOp<"dbg.label", [], [], [], 0> { // Variadic function intrinsics. // -def LLVM_VaStartOp : LLVM_ZeroResultIntrOp<"vastart">, +def LLVM_VaStartOp : LLVM_ZeroResultIntrOp<"vastart", [0]>, Arguments<(ins LLVM_AnyPointer:$arg_list)> { let assemblyFormat = "$arg_list attr-dict `:` qualified(type($arg_list))"; let summary = "Initializes `arg_list` for subsequent variadic argument extractions."; } -def LLVM_VaCopyOp : LLVM_ZeroResultIntrOp<"vacopy">, +def LLVM_VaCopyOp : LLVM_ZeroResultIntrOp<"vacopy", [0]>, Arguments<(ins LLVM_AnyPointer:$dest_list, LLVM_AnyPointer:$src_list)> { let assemblyFormat = "$src_list `to` $dest_list attr-dict `:` type(operands)"; let summary = "Copies the current argument position from `src_list` to `dest_list`."; } -def LLVM_VaEndOp : LLVM_ZeroResultIntrOp<"vaend">, +def LLVM_VaEndOp : LLVM_ZeroResultIntrOp<"vaend", [0]>, Arguments<(ins LLVM_AnyPointer:$arg_list)> { let assemblyFormat = "$arg_list attr-dict `:` qualified(type($arg_list))"; let summary = "Destroys `arg_list`, which has been initialized by `intr.vastart` or `intr.vacopy`."; diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td index b6aa73dad22970d09b970b65205eae992f71cded..7b9a9cf017c53796dd9785ec3d7ce6948c76ed87 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOpBase.td @@ -170,6 +170,10 @@ class LLVM_OpBase<Dialect dialect, string mnemonic, list<Trait> traits = []> : // - $_float_attr - substituted by a call to a float attribute matcher; // - $_var_attr - substituted by a call to a variable attribute matcher; // - $_label_attr - substituted by a call to a label attribute matcher; + // - $_roundingMode_attr - substituted by a call to a rounding mode + // attribute matcher; + // - $_fpExceptionBehavior_attr - substituted by a call to a FP exception + // behavior attribute matcher; // - $_resultType - substituted with the MLIR result type; // - $_location - substituted with the MLIR location; // - $_builder - substituted with the MLIR builder; diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td index b523374f6c06b586fad6bc3050cb50ab6735e1d3..f8f9264b3889be37e735db96c69a73db502741e9 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -323,7 +323,8 @@ def LLVM_GEPOp : LLVM_Op<"getelementptr", [Pure, } def LLVM_LoadOp : LLVM_MemAccessOpBase<"load", - [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, + [DeclareOpInterfaceMethods<DestructurableAccessorOpInterface>, + DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, DeclareOpInterfaceMethods<PromotableMemOpInterface>, DeclareOpInterfaceMethods<SafeMemorySlotAccessOpInterface>]> { dag args = (ins LLVM_AnyPointer:$addr, @@ -402,7 +403,8 @@ def LLVM_LoadOp : LLVM_MemAccessOpBase<"load", } def LLVM_StoreOp : LLVM_MemAccessOpBase<"store", - [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, + [DeclareOpInterfaceMethods<DestructurableAccessorOpInterface>, + DeclareOpInterfaceMethods<MemoryEffectsOpInterface>, DeclareOpInterfaceMethods<PromotableMemOpInterface>, DeclareOpInterfaceMethods<SafeMemorySlotAccessOpInterface>]> { dag args = (ins LLVM_LoadableType:$value, diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.td index 96cdbf01b4bd91fe70d1f22c9cf60d8e9dde0910..b7176aa93ff1f782c859478a3eb34fa6d4a4b1fe 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.td @@ -123,7 +123,7 @@ def LLVMFunctionType : LLVMType<"LLVMFunction", "func"> { def LLVMPointerType : LLVMType<"LLVMPointer", "ptr", [ DeclareTypeInterfaceMethods<DataLayoutTypeInterface, [ - "areCompatible", "verifyEntries"]>]> { + "getIndexBitwidth", "areCompatible", "verifyEntries"]>]> { let summary = "LLVM pointer type"; let description = [{ The `!llvm.ptr` type is an LLVM pointer type. This type typically represents diff --git a/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td index 8ec8e16f75c94bb779af0ac68f38e2f060bac7a4..728e92c9dc8dcf841919611f8e1d300a4a9b0f42 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td @@ -409,6 +409,33 @@ def NVVM_BarrierOp : NVVM_Op<"barrier", [AttrSizedOperandSegments]> { let assemblyFormat = "(`id` `=` $barrierId^)? (`number_of_threads` `=` $numberOfThreads^)? attr-dict"; } +def NVVM_BarrierArriveOp : NVVM_PTXBuilder_Op<"barrier.arrive"> +{ + let arguments = (ins Optional<I32>:$barrierId, I32:$numberOfThreads); + + let description = [{ + Thread that executes this op announces their arrival at the barrier with + given id and continue their execution. + + The default barrier id is 0 that is similar to `nvvm.barrier` Op. When + `barrierId` is not present, the default barrier id is used. + + [For more information, see PTX ISA] + (https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-bar) + }]; + + let assemblyFormat = "(`id` `=` $barrierId^)? `number_of_threads` `=` $numberOfThreads attr-dict"; + + let extraClassDefinition = [{ + std::string $cppClass::getPtx() { + std::string ptx = "bar.arrive "; + if (getBarrierId()) { ptx += "%0, %1'"; } + else { ptx += "0, %0;"; } + return ptx; + } + }]; +} + def NVVM_ClusterArriveOp : NVVM_Op<"cluster.arrive"> { let arguments = (ins OptionalAttr<UnitAttr>:$aligned); diff --git a/mlir/include/mlir/Dialect/LLVMIR/ROCDLOps.td b/mlir/include/mlir/Dialect/LLVMIR/ROCDLOps.td index abb38a3df8068ceeb43f62c4931942959f971eb6..1dabf5d7979b70751ccfb2ca0634ed5cafb98079 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/ROCDLOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/ROCDLOps.td @@ -162,10 +162,18 @@ def ROCDL_BallotOp : ROCDL_Op<"ballot">, Results<(outs LLVM_Type:$res)>, Arguments<(ins I1:$pred)> { + let summary = "Vote across thread group"; + + let description = [{ + Ballot provides a bit mask containing the 1-bit predicate value from each lane. + The nth bit of the result contains the 1 bit contributed by the nth warp lane. + }]; + string llvmBuilder = [{ $res = createIntrinsicCall(builder, - llvm::Intrinsic::amdgcn_ballot, {$pred}, {llvm::Type::getInt32Ty(moduleTranslation.getLLVMContext())}); + llvm::Intrinsic::amdgcn_ballot, {$pred}, {$_resultType}); }]; + let assemblyFormat = "$pred attr-dict `:` type($res)"; } diff --git a/mlir/include/mlir/Dialect/LLVMIR/Transforms/TypeConsistency.h b/mlir/include/mlir/Dialect/LLVMIR/Transforms/TypeConsistency.h index b32ac56d7079c60388f28e8a3566a10338c5c28b..cacb241bfd7a10b93c435837aa9cbca7c01304ec 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/Transforms/TypeConsistency.h +++ b/mlir/include/mlir/Dialect/LLVMIR/Transforms/TypeConsistency.h @@ -29,18 +29,6 @@ namespace LLVM { /// interpret pointee types as consistently as possible. std::unique_ptr<Pass> createTypeConsistencyPass(); -/// Transforms uses of pointers to a whole struct to uses of pointers to the -/// first element of a struct. This is achieved by inserting a GEP to the first -/// element when possible. -template <class User> -class AddFieldGetterToStructDirectUse : public OpRewritePattern<User> { -public: - using OpRewritePattern<User>::OpRewritePattern; - - LogicalResult matchAndRewrite(User user, - PatternRewriter &rewriter) const override; -}; - /// Canonicalizes GEPs of which the base type and the pointer's type hint do not /// match. This is done by replacing the original GEP into a GEP with the type /// hint as a base type when an element of the hinted type aligns with the diff --git a/mlir/include/mlir/Dialect/Linalg/IR/LinalgStructuredOps.td b/mlir/include/mlir/Dialect/Linalg/IR/LinalgStructuredOps.td index 92d844eefb72071147f7945bce35af587d449712..5ee363ed325727b22a7dfe054001766497b6e4b8 100644 --- a/mlir/include/mlir/Dialect/Linalg/IR/LinalgStructuredOps.td +++ b/mlir/include/mlir/Dialect/Linalg/IR/LinalgStructuredOps.td @@ -391,7 +391,6 @@ def ReduceOp : LinalgStructuredBase_Op<"reduce", [ def TransposeOp : LinalgStructuredBase_Op<"transpose", [ DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>, - SameVariadicOperandSize, SingleBlockImplicitTerminator<"YieldOp">]> { let summary = "Transpose operator"; let description = [{ @@ -470,7 +469,6 @@ def TransposeOp : LinalgStructuredBase_Op<"transpose", [ def BroadcastOp : LinalgStructuredBase_Op<"broadcast", [ DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>, - SameVariadicOperandSize, SingleBlockImplicitTerminator<"YieldOp">]> { let summary = "Static broadcast operator"; let description = [{ diff --git a/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgMatchOps.h b/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgMatchOps.h index d6bbcf88b79f495c08b773061c7b4d053dd598f1..fdebcb031b113c20f67485abf749d42e6384a096 100644 --- a/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgMatchOps.h +++ b/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgMatchOps.h @@ -10,8 +10,8 @@ #define MLIR_DIALECT_LINALG_TRANSFORMOPS_LINALGMATCHOPS_H #include "mlir/Dialect/Linalg/IR/Linalg.h" -#include "mlir/Dialect/Transform/IR/MatchInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformAttrs.h" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.h" namespace mlir { namespace transform { diff --git a/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgMatchOps.td b/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgMatchOps.td index dfeb8ae5d5ddbcb46311c3ab1c1bd977edcef676..cdc29d053e5a4b613e9b9fd92eff55bdc7c7bec6 100644 --- a/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgMatchOps.td +++ b/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgMatchOps.td @@ -10,7 +10,7 @@ #define LINALG_MATCH_OPS include "mlir/Dialect/Linalg/TransformOps/LinalgTransformEnums.td" -include "mlir/Dialect/Transform/IR/MatchInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.td" include "mlir/Dialect/Transform/IR/TransformAttrs.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" include "mlir/Dialect/Transform/IR/TransformTypes.td" diff --git a/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.h b/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.h index 12923663b3fb6ce6b8f9aab774aae226f40216de..3af642752724c4b190e5293ad0bd0170c6f4010f 100644 --- a/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.h +++ b/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.h @@ -14,7 +14,7 @@ #include "mlir/Dialect/Linalg/IR/Linalg.h" #include "mlir/Dialect/Transform/IR/TransformAttrs.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Dialect/Utils/StructuredOpsUtils.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/RegionKindInterface.h" @@ -38,6 +38,9 @@ class UnPackOp; } // namespace tensor namespace transform { +class AnyOpType; +class AnyValueType; +class OperationType; class TransformHandleTypeInterface; // Types needed for builders. struct TileSizesSpec {}; diff --git a/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.td b/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.td index bdeab55091b9f363893fa9843147037677278dc0..c260fe3f7a46a5d3dd3438011c8bd314d8090022 100644 --- a/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.td +++ b/mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.td @@ -12,7 +12,7 @@ include "mlir/Dialect/Linalg/TransformOps/LinalgTransformEnums.td" include "mlir/Dialect/Transform/IR/TransformAttrs.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Dialect/Transform/IR/TransformTypes.td" include "mlir/Dialect/SCF/IR/DeviceMappingInterface.td" include "mlir/Interfaces/SideEffectInterfaces.td" @@ -1918,7 +1918,9 @@ def TileUsingForallOp : It is the user's responsibility to ensure that `num_threads/tile_sizes` is a valid tiling specification (i.e. that only tiles parallel dimensions, - e.g. in the Linalg case). + e.g. in the Linalg case). If the dimension is not parallelizable, a warning + is issued to notify the user that the generated code is not safe to + parallelize. If non-empty, the `mapping` is added as an attribute to the resulting `scf.forall`. diff --git a/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h b/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h index c64ecb79c5ca514da5a662c1bc7800559f823f5a..feb3b3f03cf53877ee3e525d93cfd8a7193c7ac9 100644 --- a/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h +++ b/mlir/include/mlir/Dialect/Linalg/Transforms/Transforms.h @@ -460,7 +460,8 @@ LogicalResult promoteSubviewsPrecondition(Operation *op, LogicalResult vectorizeOpPrecondition(Operation *op, ArrayRef<int64_t> inputVectorSizes = {}, ArrayRef<bool> inputScalableVecDims = {}, - bool vectorizeNDExtract = false); + bool vectorizeNDExtract = false, + bool flatten1DDepthwiseConv = false); //===----------------------------------------------------------------------===// // Transformations exposed as functional-style API calls. diff --git a/mlir/include/mlir/Dialect/Math/Transforms/Passes.h b/mlir/include/mlir/Dialect/Math/Transforms/Passes.h index 11b2c7a7afa2f779bca1ae766f9497f3e4849013..e2c513047c77a52002fde554b2813b6febb9dbd7 100644 --- a/mlir/include/mlir/Dialect/Math/Transforms/Passes.h +++ b/mlir/include/mlir/Dialect/Math/Transforms/Passes.h @@ -36,6 +36,7 @@ void populateExpandFloorFPattern(RewritePatternSet &patterns); void populateExpandCeilFPattern(RewritePatternSet &patterns); void populateExpandExp2FPattern(RewritePatternSet &patterns); void populateExpandPowFPattern(RewritePatternSet &patterns); +void populateExpandFPowIPattern(RewritePatternSet &patterns); void populateExpandRoundFPattern(RewritePatternSet &patterns); void populateExpandRoundEvenPattern(RewritePatternSet &patterns); void populateMathAlgebraicSimplificationPatterns(RewritePatternSet &patterns); diff --git a/mlir/include/mlir/Dialect/MemRef/TransformOps/MemRefTransformOps.h b/mlir/include/mlir/Dialect/MemRef/TransformOps/MemRefTransformOps.h index ee7c6968314887ce3c3a7766ec9326b13864df69..a87767acdd3b8f153bfa0c6a08d041cd5a43397b 100644 --- a/mlir/include/mlir/Dialect/MemRef/TransformOps/MemRefTransformOps.h +++ b/mlir/include/mlir/Dialect/MemRef/TransformOps/MemRefTransformOps.h @@ -10,13 +10,16 @@ #define MLIR_DIALECT_MEMREF_TRANSFORMOPS_MEMREFTRANSFORMOPS_H #include "mlir/Bytecode/BytecodeOpInterface.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpImplementation.h" namespace mlir { namespace memref { class AllocOp; } // namespace memref +namespace transform { +class OperationType; +} // namespace transform } // namespace mlir #define GET_OP_CLASSES diff --git a/mlir/include/mlir/Dialect/MemRef/TransformOps/MemRefTransformOps.td b/mlir/include/mlir/Dialect/MemRef/TransformOps/MemRefTransformOps.td index 29383a3825be8834353ea52293ebc10de4f24a11..2d060f3c2da6477f864385b312ffb13aada4125f 100644 --- a/mlir/include/mlir/Dialect/MemRef/TransformOps/MemRefTransformOps.td +++ b/mlir/include/mlir/Dialect/MemRef/TransformOps/MemRefTransformOps.td @@ -10,7 +10,7 @@ #define MEMREF_TRANSFORM_OPS include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Dialect/Transform/IR/TransformTypes.td" include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/IR/OpBase.td" diff --git a/mlir/include/mlir/Dialect/MemRef/Transforms/BufferViewFlowOpInterfaceImpl.h b/mlir/include/mlir/Dialect/MemRef/Transforms/BufferViewFlowOpInterfaceImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..714518a21e975db827426148cd1b80e900bfd1bb --- /dev/null +++ b/mlir/include/mlir/Dialect/MemRef/Transforms/BufferViewFlowOpInterfaceImpl.h @@ -0,0 +1,20 @@ +//===- BufferViewFlowOpInterfaceImpl.h - Buffer View Analysis ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DIALECT_MEMREF_TRANSFORMS_BUFFERVIEWFLOWOPINTERFACEIMPL_H +#define MLIR_DIALECT_MEMREF_TRANSFORMS_BUFFERVIEWFLOWOPINTERFACEIMPL_H + +namespace mlir { +class DialectRegistry; + +namespace memref { +void registerBufferViewFlowOpInterfaceExternalModels(DialectRegistry ®istry); +} // namespace memref +} // namespace mlir + +#endif // MLIR_DIALECT_MEMREF_TRANSFORMS_BUFFERVIEWFLOWOPINTERFACEIMPL_H diff --git a/mlir/include/mlir/Dialect/NVGPU/TransformOps/NVGPUTransformOps.h b/mlir/include/mlir/Dialect/NVGPU/TransformOps/NVGPUTransformOps.h index 1c30cc4a57d8800d0dc5ceeb8b5cd2ea25a41ee3..5179adeb09dbe90be35c314399395beca5787dce 100644 --- a/mlir/include/mlir/Dialect/NVGPU/TransformOps/NVGPUTransformOps.h +++ b/mlir/include/mlir/Dialect/NVGPU/TransformOps/NVGPUTransformOps.h @@ -11,7 +11,7 @@ #include "mlir/Dialect/Transform/IR/TransformAttrs.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/RegionKindInterface.h" diff --git a/mlir/include/mlir/Dialect/NVGPU/TransformOps/NVGPUTransformOps.td b/mlir/include/mlir/Dialect/NVGPU/TransformOps/NVGPUTransformOps.td index bce84cb3fdea08eb86ffcf76dd026e302fbedae5..0225562baa58cfeffbdb99825750c338fff6a105 100644 --- a/mlir/include/mlir/Dialect/NVGPU/TransformOps/NVGPUTransformOps.td +++ b/mlir/include/mlir/Dialect/NVGPU/TransformOps/NVGPUTransformOps.td @@ -11,7 +11,7 @@ include "mlir/Dialect/Transform/IR/TransformAttrs.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Dialect/Transform/IR/TransformTypes.td" include "mlir/Interfaces/SideEffectInterfaces.td" diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td index 39ff49f0ccf5413d6503fadda98917758df56790..f33942b3c7c02d9b7f91a082f7764a2fab9c4c51 100644 --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -268,6 +268,9 @@ def ParallelOp : OpenMP_Op<"parallel", [ The optional $proc_bind_val attribute controls the thread affinity for the execution of the parallel region. + + The optional byref attribute controls whether reduction arguments are passed by + reference or by value. }]; let arguments = (ins Optional<I1>:$if_expr_var, @@ -278,7 +281,8 @@ def ParallelOp : OpenMP_Op<"parallel", [ OptionalAttr<SymbolRefArrayAttr>:$reductions, OptionalAttr<ProcBindKindAttr>:$proc_bind_val, Variadic<AnyType>:$private_vars, - OptionalAttr<SymbolRefArrayAttr>:$privatizers); + OptionalAttr<SymbolRefArrayAttr>:$privatizers, + UnitAttr:$byref); let regions = (region AnyRegion:$region); @@ -299,6 +303,7 @@ def ParallelOp : OpenMP_Op<"parallel", [ $allocators_vars, type($allocators_vars) ) `)` | `proc_bind` `(` custom<ClauseAttr>($proc_bind_val) `)` + | `byref` $byref ) custom<ParallelRegion>($region, $reduction_vars, type($reduction_vars), $reductions, $private_vars, type($private_vars), $privatizers) attr-dict @@ -510,7 +515,7 @@ def SingleOp : OpenMP_Op<"single", [AttrSizedOperandSegments]> { // 2.9.2 Workshare Loop Construct //===----------------------------------------------------------------------===// -def WsLoopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments, +def WsloopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments, AllTypesMatch<["lowerBound", "upperBound", "step"]>, RecursiveMemoryEffects, ReductionClauseInterface]> { let summary = "worksharing-loop construct"; @@ -570,6 +575,9 @@ def WsLoopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments, The optional `order` attribute specifies which order the iterations of the associate loops are executed in. Currently the only option for this attribute is "concurrent". + + The optional `byref` attribute indicates that reduction arguments should be + passed by reference. }]; let arguments = (ins Variadic<IntLikeType>:$lowerBound, @@ -584,6 +592,7 @@ def WsLoopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments, OptionalAttr<ScheduleModifierAttr>:$schedule_modifier, UnitAttr:$simd_modifier, UnitAttr:$nowait, + UnitAttr:$byref, ConfinedAttr<OptionalAttr<I64Attr>, [IntMinValue<0>]>:$ordered_val, OptionalAttr<OrderKindAttr>:$order_val, UnitAttr:$inclusive); @@ -613,11 +622,12 @@ def WsLoopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments, $schedule_val, $schedule_modifier, $simd_modifier, $schedule_chunk_var, type($schedule_chunk_var)) `)` |`nowait` $nowait + |`byref` $byref |`ordered` `(` $ordered_val `)` |`order` `(` custom<ClauseAttr>($order_val) `)` - ) custom<WsLoop>($region, $lowerBound, $upperBound, $step, - type($step), $reduction_vars, type($reduction_vars), $reductions, - $inclusive) attr-dict + ) custom<Wsloop>($region, $lowerBound, $upperBound, $step, type($step), + $reduction_vars, type($reduction_vars), $reductions, + $inclusive) attr-dict }]; let hasVerifier = 1; } @@ -714,7 +724,7 @@ def SimdLoopOp : OpenMP_Op<"simdloop", [AttrSizedOperandSegments, def YieldOp : OpenMP_Op<"yield", [Pure, ReturnLike, Terminator, - ParentOneOf<["WsLoopOp", "ReductionDeclareOp", + ParentOneOf<["WsloopOp", "DeclareReductionOp", "AtomicUpdateOp", "SimdLoopOp", "PrivateClauseOp"]>]> { let summary = "loop yield and termination operation"; let description = [{ @@ -904,7 +914,7 @@ def TaskOp : OpenMP_Op<"task", [AttrSizedOperandSegments, let hasVerifier = 1; } -def TaskLoopOp : OpenMP_Op<"taskloop", [AttrSizedOperandSegments, +def TaskloopOp : OpenMP_Op<"taskloop", [AttrSizedOperandSegments, AutomaticAllocationScope, RecursiveMemoryEffects, AllTypesMatch<["lowerBound", "upperBound", "step"]>, ReductionClauseInterface]> { @@ -1062,7 +1072,7 @@ def TaskLoopOp : OpenMP_Op<"taskloop", [AttrSizedOperandSegments, let hasVerifier = 1; } -def TaskGroupOp : OpenMP_Op<"taskgroup", [AttrSizedOperandSegments, +def TaskgroupOp : OpenMP_Op<"taskgroup", [AttrSizedOperandSegments, ReductionClauseInterface, AutomaticAllocationScope]> { let summary = "taskgroup construct"; @@ -1181,24 +1191,24 @@ def VariableCaptureKindAttr : EnumAttr<OpenMP_Dialect, VariableCaptureKind, let assemblyFormat = "`(` $value `)`"; } -def DataBoundsType : OpenMP_Type<"DataBounds", "data_bounds_ty"> { - let summary = "Type for representing omp data clause bounds information"; +def MapBoundsType : OpenMP_Type<"MapBounds", "map_bounds_ty"> { + let summary = "Type for representing omp map clause bounds information"; } -def DataBoundsOp : OpenMP_Op<"bounds", +def MapBoundsOp : OpenMP_Op<"map.bounds", [AttrSizedOperandSegments, NoMemoryEffect]> { let summary = "Represents normalized bounds information for map clauses."; let description = [{ This operation is a variation on the OpenACC dialects DataBoundsOp. Within the OpenMP dialect it stores the bounds/range of data to be mapped to a - device specified by map clauses on target directives. Within, - the OpenMP dialect the DataBoundsOp is associated with MapInfoOp, + device specified by map clauses on target directives. Within + the OpenMP dialect, the MapBoundsOp is associated with MapInfoOp, helping to store bounds information for the mapped variable. It is used to support OpenMP array sectioning, Fortran pointer and allocatable mapping and pointer/allocatable member of derived types. - In all cases the DataBoundsOp holds information on the section of + In all cases the MapBoundsOp holds information on the section of data to be mapped. Such as the upper bound and lower bound of the section of data to be mapped. This information is currently utilised by the LLVM-IR lowering to help generate instructions to @@ -1217,7 +1227,7 @@ def DataBoundsOp : OpenMP_Op<"bounds", ``` => ```mlir - omp.bounds lower_bound(1) upper_bound(9) extent(9) start_idx(0) + omp.map.bounds lower_bound(1) upper_bound(9) extent(9) start_idx(0) ``` Fortran: @@ -1227,7 +1237,7 @@ def DataBoundsOp : OpenMP_Op<"bounds", ``` => ```mlir - omp.bounds lower_bound(1) upper_bound(9) extent(9) start_idx(1) + omp.map.bounds lower_bound(1) upper_bound(9) extent(9) start_idx(1) ``` For Fortran pointers and allocatables (as well as those that are @@ -1247,7 +1257,7 @@ def DataBoundsOp : OpenMP_Op<"bounds", ``` => ```mlir - omp.bounds lower_bound(0) upper_bound(9) extent(10) start_idx(1) + omp.map.bounds lower_bound(0) upper_bound(9) extent(10) start_idx(1) ``` This operation records the bounds information in a normalized fashion @@ -1266,7 +1276,7 @@ def DataBoundsOp : OpenMP_Op<"bounds", Optional<IntLikeType>:$stride, DefaultValuedAttr<BoolAttr, "false">:$stride_in_bytes, Optional<IntLikeType>:$start_idx); - let results = (outs DataBoundsType:$result); + let results = (outs MapBoundsType:$result); let assemblyFormat = [{ oilist( @@ -1293,12 +1303,12 @@ def DataBoundsOp : OpenMP_Op<"bounds", let hasVerifier = 1; } -def MapInfoOp : OpenMP_Op<"map_info", [AttrSizedOperandSegments]> { +def MapInfoOp : OpenMP_Op<"map.info", [AttrSizedOperandSegments]> { let arguments = (ins OpenMP_PointerLikeType:$var_ptr, TypeAttr:$var_type, Optional<OpenMP_PointerLikeType>:$var_ptr_ptr, Variadic<OpenMP_PointerLikeType>:$members, - Variadic<DataBoundsType>:$bounds, /* rank-0 to rank-{n-1} */ + Variadic<MapBoundsType>:$bounds, /* rank-0 to rank-{n-1} */ OptionalAttr<UI64Attr>:$map_type, OptionalAttr<VariableCaptureKindAttr>:$map_capture_type, OptionalAttr<StrAttr>:$name); @@ -1328,7 +1338,7 @@ def MapInfoOp : OpenMP_Op<"map_info", [AttrSizedOperandSegments]> { ``` => ```mlir - omp.map_info var_ptr(%index_ssa) map_type(to) map_capture_type(ByRef) + omp.map.info var_ptr(%index_ssa) map_type(to) map_capture_type(ByRef) name(index) ``` @@ -1337,10 +1347,10 @@ def MapInfoOp : OpenMP_Op<"map_info", [AttrSizedOperandSegments]> { - `var_type`: The type of the variable to copy. - `var_ptr_ptr`: Used when the variable copied is a member of a class, structure or derived type and refers to the originating struct. - - `members`: Used to indicate mapped child members for the current MapInfoOp, - represented as other MapInfoOp's, utilised in cases where a parent structure - type and members of the structure type are being mapped at the same time. - For example: map(to: parent, parent->member, parent->member2[:10]) + - `members`: Used to indicate mapped child members for the current MapInfoOp, + represented as other MapInfoOp's, utilised in cases where a parent structure + type and members of the structure type are being mapped at the same time. + For example: map(to: parent, parent->member, parent->member2[:10]) - `bounds`: Used when copying slices of array's, pointers or pointer members of objects (e.g. derived types or classes), indicates the bounds to be copied of the variable. When it's an array slice it is in rank order where rank 0 @@ -1381,8 +1391,8 @@ def MapInfoOp : OpenMP_Op<"map_info", [AttrSizedOperandSegments]> { // 2.14.2 target data Construct //===---------------------------------------------------------------------===// -def Target_DataOp: OpenMP_Op<"target_data", [AttrSizedOperandSegments, - MapClauseOwningOpInterface]>{ +def TargetDataOp: OpenMP_Op<"target_data", [AttrSizedOperandSegments, + MapClauseOwningOpInterface]>{ let summary = "target data construct"; let description = [{ Map variables to a device data environment for the extent of the region. @@ -1438,8 +1448,8 @@ def Target_DataOp: OpenMP_Op<"target_data", [AttrSizedOperandSegments, // 2.14.3 target enter data Construct //===---------------------------------------------------------------------===// -def Target_EnterDataOp: OpenMP_Op<"target_enter_data", - [AttrSizedOperandSegments, +def TargetEnterDataOp: OpenMP_Op<"target_enter_data", + [AttrSizedOperandSegments, MapClauseOwningOpInterface]>{ let summary = "target enter data construct"; let description = [{ @@ -1492,7 +1502,7 @@ def Target_EnterDataOp: OpenMP_Op<"target_enter_data", // 2.14.4 target exit data Construct //===---------------------------------------------------------------------===// -def Target_ExitDataOp: OpenMP_Op<"target_exit_data", +def TargetExitDataOp: OpenMP_Op<"target_exit_data", [AttrSizedOperandSegments, MapClauseOwningOpInterface]>{ let summary = "target exit data construct"; @@ -1543,13 +1553,12 @@ def Target_ExitDataOp: OpenMP_Op<"target_exit_data", } //===---------------------------------------------------------------------===// -// 2.14.6 target update data Construct +// 2.14.6 target update Construct //===---------------------------------------------------------------------===// -def Target_UpdateDataOp: OpenMP_Op<"target_update_data", - [AttrSizedOperandSegments, - MapClauseOwningOpInterface]>{ - let summary = "target update data construct"; +def TargetUpdateOp: OpenMP_Op<"target_update", [AttrSizedOperandSegments, + MapClauseOwningOpInterface]>{ + let summary = "target update construct"; let description = [{ The target update directive makes the corresponding list items in the device data environment consistent with their original list items, according to the @@ -1603,7 +1612,7 @@ def Target_UpdateDataOp: OpenMP_Op<"target_update_data", // 2.14.5 target construct //===----------------------------------------------------------------------===// -def TargetOp : OpenMP_Op<"target",[IsolatedFromAbove, MapClauseOwningOpInterface, +def TargetOp : OpenMP_Op<"target", [IsolatedFromAbove, MapClauseOwningOpInterface, OutlineableOpenMPOpInterface, AttrSizedOperandSegments]> { let summary = "target construct"; let description = [{ @@ -1772,7 +1781,7 @@ def OrderedOp : OpenMP_Op<"ordered"> { let hasVerifier = 1; } -def OrderedRegionOp : OpenMP_Op<"ordered_region"> { +def OrderedRegionOp : OpenMP_Op<"ordered.region"> { let summary = "ordered construct with region"; let description = [{ The ordered construct with region specifies a structured block in a @@ -2103,7 +2112,7 @@ def CancelOp : OpenMP_Op<"cancel"> { //===----------------------------------------------------------------------===// // 2.18.2 Cancellation Point Construct //===----------------------------------------------------------------------===// -def CancellationPointOp : OpenMP_Op<"cancellationpoint"> { +def CancellationPointOp : OpenMP_Op<"cancellation_point"> { let summary = "cancellation point directive"; let description = [{ The cancellation point construct introduces a user-defined cancellation @@ -2121,7 +2130,7 @@ def CancellationPointOp : OpenMP_Op<"cancellationpoint"> { // 2.19.5.7 declare reduction Directive //===----------------------------------------------------------------------===// -def ReductionDeclareOp : OpenMP_Op<"reduction.declare", [Symbol, +def DeclareReductionOp : OpenMP_Op<"declare_reduction", [Symbol, IsolatedFromAbove]> { let summary = "declares a reduction kind"; diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td index ed086d36424c1f210d021e3de32b5d6f8ae0ceb7..2e37384ce3eb710f6dae0e6ec14570ccfffe5619 100644 --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td @@ -34,8 +34,8 @@ def OutlineableOpenMPOpInterface : OpInterface<"OutlineableOpenMPOpInterface"> { def MapClauseOwningOpInterface : OpInterface<"MapClauseOwningOpInterface"> { let description = [{ OpenMP operations which own a list of omp::MapInfoOp's implement this interface - to allow generic access to deal with map operands to more easily manipulate - this class of operations. + to allow generic access to deal with map operands to more easily manipulate + this class of operations. }]; let cppNamespace = "::mlir::omp"; @@ -45,7 +45,7 @@ def MapClauseOwningOpInterface : OpInterface<"MapClauseOwningOpInterface"> { (ins), [{ return $_op.getMapOperands(); }]>, - InterfaceMethod<"Get mutable map operands", "::mlir::MutableOperandRange", + InterfaceMethod<"Get mutable map operands", "::mlir::MutableOperandRange", "getMapOperandsMutable", (ins), [{ return $_op.getMapOperandsMutable(); diff --git a/mlir/include/mlir/Dialect/SCF/TransformOps/SCFTransformOps.h b/mlir/include/mlir/Dialect/SCF/TransformOps/SCFTransformOps.h index d14d63e56dc764f6e9ff341e63e95a8e13738dc5..65ccd43b56c8d39d94dd1b33fedce3cfc3c4fe02 100644 --- a/mlir/include/mlir/Dialect/SCF/TransformOps/SCFTransformOps.h +++ b/mlir/include/mlir/Dialect/SCF/TransformOps/SCFTransformOps.h @@ -10,8 +10,8 @@ #define MLIR_DIALECT_SCF_TRANSFORMOPS_SCFTRANSFORMOPS_H #include "mlir/Bytecode/BytecodeOpInterface.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformTypes.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpImplementation.h" #include "mlir/Interfaces/LoopLikeInterface.h" diff --git a/mlir/include/mlir/Dialect/SCF/TransformOps/SCFTransformOps.td b/mlir/include/mlir/Dialect/SCF/TransformOps/SCFTransformOps.td index cef73689c072b8c67819ceea6a9e78e49538d01a..5eefe2664d0a1b1ea072b8dd8f7bc401c9890a4c 100644 --- a/mlir/include/mlir/Dialect/SCF/TransformOps/SCFTransformOps.td +++ b/mlir/include/mlir/Dialect/SCF/TransformOps/SCFTransformOps.td @@ -10,7 +10,7 @@ #define SCF_TRANSFORM_OPS include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Dialect/Transform/IR/TransformTypes.td" include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/IR/OpBase.td" @@ -333,23 +333,24 @@ def TakeAssumedBranchOp : Op<Transform_Dialect, "scf.take_assumed_branch", [ }]; } -def LoopFuseSibling : Op<Transform_Dialect, "loop.fuse_sibling", +def LoopFuseSiblingOp : Op<Transform_Dialect, "loop.fuse_sibling", [FunctionalStyleTransformOpTrait, MemoryEffectsOpInterface, DeclareOpInterfaceMethods<TransformOpInterface>]> { let summary = "Fuse a loop into another loop, assuming the fusion is legal."; let description = [{ Fuses the `target` loop into the `source` loop assuming they are - independent of each other. It is the responsibility of the user to ensure - that the given two loops are independent of each other, this operation will - not performa any legality checks and will simply fuse the two given loops. + independent of each other. In the fused loop, the arguments, body and + results of `target` are placed _before_ those of `source`. - Currently, the only fusion supported is when both `target` and `source` - are `scf.forall` operations. For `scf.forall` fusion, the bounds and the - mapping must match, otherwise a silencable failure is produced. + For fusion of two `scf.for` loops, the bounds and step size must match. For + fusion of two `scf.forall` loops, the bounds and the mapping must match. + Otherwise a silencable failure is produced. - The input handles `target` and `source` must map to exactly one operation, - a definite failure is produced otherwise. + The `target` and `source` handles must refer to exactly one operation, + otherwise a definite failure is produced. It is the responsibility of the + user to ensure that the `target` and `source` loops are independent of each + other -- this op will only perform rudimentary legality checks. #### Return modes @@ -362,10 +363,6 @@ def LoopFuseSibling : Op<Transform_Dialect, "loop.fuse_sibling", let results = (outs TransformHandleTypeInterface:$fused_loop); let assemblyFormat = "$target `into` $source attr-dict " " `:` functional-type(operands, results)"; - - let builders = [ - OpBuilder<(ins "Value":$loop, "Value":$fused_loop)> - ]; } #endif // SCF_TRANSFORM_OPS diff --git a/mlir/include/mlir/Dialect/SCF/Utils/Utils.h b/mlir/include/mlir/Dialect/SCF/Utils/Utils.h index 9bdd6eb833876f09a63bfa367e8614d938b0b9f0..883d11bcc4df06aa66c1ccf7edaea9697c0bc76e 100644 --- a/mlir/include/mlir/Dialect/SCF/Utils/Utils.h +++ b/mlir/include/mlir/Dialect/SCF/Utils/Utils.h @@ -162,6 +162,16 @@ scf::ForallOp fuseIndependentSiblingForallLoops(scf::ForallOp target, scf::ForallOp source, RewriterBase &rewriter); +/// Given two scf.for loops, `target` and `source`, fuses `target` into +/// `source`. Assumes that the given loops are siblings and are independent of +/// each other. +/// +/// This function does not perform any legality checks and simply fuses the +/// loops. The caller is responsible for ensuring that the loops are legal to +/// fuse. +scf::ForOp fuseIndependentSiblingForLoops(scf::ForOp target, scf::ForOp source, + RewriterBase &rewriter); + } // namespace mlir #endif // MLIR_DIALECT_SCF_UTILS_UTILS_H_ diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVLogicalOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVLogicalOps.td index e48a56f0625d3f1ca6c46b41f6f0a37f74afb8c5..61c5a7a6394f8aa1311f6a45232e38ab4cfb49e0 100644 --- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVLogicalOps.td +++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVLogicalOps.td @@ -659,6 +659,8 @@ def SPIRV_SGreaterThanOp : SPIRV_LogicalBinaryOp<"SGreaterThan", ``` }]; + + let hasFolder = 1; } // ----- @@ -688,6 +690,8 @@ def SPIRV_SGreaterThanEqualOp : SPIRV_LogicalBinaryOp<"SGreaterThanEqual", %5 = spirv.SGreaterThanEqual %2, %3 : vector<4xi32> ``` }]; + + let hasFolder = 1; } // ----- @@ -716,6 +720,8 @@ def SPIRV_SLessThanOp : SPIRV_LogicalBinaryOp<"SLessThan", ``` }]; + + let hasFolder = 1; } // ----- @@ -745,6 +751,8 @@ def SPIRV_SLessThanEqualOp : SPIRV_LogicalBinaryOp<"SLessThanEqual", %5 = spirv.SLessThanEqual %2, %3 : vector<4xi32> ``` }]; + + let hasFolder = 1; } // ----- @@ -800,6 +808,8 @@ def SPIRV_SelectOp : SPIRV_Op<"Select", // These ops require dynamic availability specification based on operand and // result types. bit autogenAvailability = 0; + + let hasFolder = 1; } // ----- @@ -828,6 +838,8 @@ def SPIRV_UGreaterThanOp : SPIRV_LogicalBinaryOp<"UGreaterThan", %5 = spirv.UGreaterThan %2, %3 : vector<4xi32> ``` }]; + + let hasFolder = 1; } // ----- @@ -857,6 +869,8 @@ def SPIRV_UGreaterThanEqualOp : SPIRV_LogicalBinaryOp<"UGreaterThanEqual", %5 = spirv.UGreaterThanEqual %2, %3 : vector<4xi32> ``` }]; + + let hasFolder = 1; } // ----- @@ -884,6 +898,8 @@ def SPIRV_ULessThanOp : SPIRV_LogicalBinaryOp<"ULessThan", %5 = spirv.ULessThan %2, %3 : vector<4xi32> ``` }]; + + let hasFolder = 1; } // ----- @@ -947,6 +963,8 @@ def SPIRV_ULessThanEqualOp : SPIRV_LogicalBinaryOp<"ULessThanEqual", %5 = spirv.ULessThanEqual %2, %3 : vector<4xi32> ``` }]; + + let hasFolder = 1; } #endif // MLIR_DIALECT_SPIRV_IR_LOGICAL_OPS diff --git a/mlir/include/mlir/Dialect/SPIRV/Transforms/SPIRVConversion.h b/mlir/include/mlir/Dialect/SPIRV/Transforms/SPIRVConversion.h index 933d62e35fce8cd7f9cc0bf88db6344f225b706d..09eecafc0c8a5136257a3e33e10b8ff6ccf7b3e1 100644 --- a/mlir/include/mlir/Dialect/SPIRV/Transforms/SPIRVConversion.h +++ b/mlir/include/mlir/Dialect/SPIRV/Transforms/SPIRVConversion.h @@ -55,11 +55,6 @@ struct SPIRVConversionOptions { /// values will be packed into one 32-bit value to be memory efficient. bool emulateLT32BitScalarTypes{true}; - /// Whether to enable fast math mode during conversion. If true, various - /// patterns would assume no NaN/infinity numbers as inputs, and thus there - /// will be no special guards emitted to check and handle such cases. - bool enableFastMathMode{false}; - /// Use 64-bit integers when converting index types. bool use64bitIndex{false}; }; diff --git a/mlir/include/mlir/Dialect/SPIRV/Transforms/SPIRVWebGPUTransforms.h b/mlir/include/mlir/Dialect/SPIRV/Transforms/SPIRVWebGPUTransforms.h index ac4d38e0c5b1ebec076664b711b329724ae94753..d0fc85ccc9de494f125325e0a4ea827f6e38447b 100644 --- a/mlir/include/mlir/Dialect/SPIRV/Transforms/SPIRVWebGPUTransforms.h +++ b/mlir/include/mlir/Dialect/SPIRV/Transforms/SPIRVWebGPUTransforms.h @@ -18,12 +18,18 @@ namespace mlir { namespace spirv { -/// Appends to a pattern list additional patterns to expand extended -/// multiplication ops into regular arithmetic ops. Extended multiplication ops -/// are not supported by the WebGPU Shading Language (WGSL). +/// Appends patterns to expand extended multiplication and adition ops into +/// regular arithmetic ops. Extended arithmetic ops are not supported by the +/// WebGPU Shading Language (WGSL). void populateSPIRVExpandExtendedMultiplicationPatterns( RewritePatternSet &patterns); +/// Appends patterns to expand non-finite arithmetic ops `IsNan` and `IsInf`. +/// These are not supported by the WebGPU Shading Language (WGSL). We follow +/// fast math assumptions and assume that all floating point values are finite. +void populateSPIRVExpandNonFiniteArithmeticPatterns( + RewritePatternSet &patterns); + } // namespace spirv } // namespace mlir diff --git a/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorOps.td b/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorOps.td index 0498576fcffc511bb5b896662ade48120ab0318b..5df8a176459b7c7f5570f902e59bf021ef06802e 100644 --- a/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorOps.td +++ b/mlir/include/mlir/Dialect/SparseTensor/IR/SparseTensorOps.td @@ -1278,8 +1278,10 @@ def SparseTensor_SelectOp : SparseTensor_Op<"select", [Pure, SameOperandsAndResu let hasVerifier = 1; } -def SparseTensor_YieldOp : SparseTensor_Op<"yield", [Pure, Terminator]>, - Arguments<(ins Optional<AnyType>:$result)> { +def SparseTensor_YieldOp : SparseTensor_Op<"yield", [Pure, Terminator, + ParentOneOf<["BinaryOp", "UnaryOp", "ReduceOp", "SelectOp", + "ForeachOp"]>]>, + Arguments<(ins Variadic<AnyType>:$results)> { let summary = "Yield from sparse_tensor set-like operations"; let description = [{ Yields a value from within a `binary`, `unary`, `reduce`, @@ -1302,14 +1304,27 @@ def SparseTensor_YieldOp : SparseTensor_Op<"yield", [Pure, Terminator]>, let builders = [ OpBuilder<(ins), [{ - build($_builder, $_state, Value()); + build($_builder, $_state, ValueRange()); + }]>, + OpBuilder<(ins "Value":$yieldVal), + [{ + build($_builder, $_state, ValueRange(yieldVal)); }]> ]; + let extraClassDeclaration = [{ + Value getSingleResult() { + assert(hasSingleResult()); + return getResults().front(); + } + bool hasSingleResult() { + return getResults().size() == 1; + } + }]; + let assemblyFormat = [{ - $result attr-dict `:` type($result) + $results attr-dict `:` type($results) }]; - let hasVerifier = 1; } def SparseTensor_ForeachOp : SparseTensor_Op<"foreach", @@ -1419,7 +1434,7 @@ def SparseTensor_ForeachOp : SparseTensor_Op<"foreach", } //===----------------------------------------------------------------------===// -// Sparse Tensor Debugging Operations. +// Sparse Tensor Debugging and Test-Only Operations. //===----------------------------------------------------------------------===// def SparseTensor_PrintOp : SparseTensor_Op<"print">, @@ -1440,4 +1455,25 @@ def SparseTensor_PrintOp : SparseTensor_Op<"print">, let assemblyFormat = "$tensor attr-dict `:` type($tensor)"; } +def SparseTensor_HasRuntimeLibraryOp + : SparseTensor_Op<"has_runtime_library", []>, Results<(outs I1:$result)> { + string summary = "Indicates whether running in runtime/codegen mode"; + string description = [{ + Returns a boolean value that indicates whether the sparsifier runs in + runtime library mode or not. For testing only! This operation is useful + for writing test cases that require different code depending on + runtime/codegen mode. + + Example: + + ```mlir + %has_runtime = sparse_tensor.has_runtime_library + scf.if %has_runtime { + ... + } + ``` + }]; + let assemblyFormat = "attr-dict"; +} + #endif // SPARSETENSOR_OPS diff --git a/mlir/include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.h b/mlir/include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.h index 1c52e4881dc88b58a2e22ceebc0a20b7ff4cfe77..8c31249090528fc7f167fe554834f345d86c5cdc 100644 --- a/mlir/include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.h +++ b/mlir/include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.h @@ -9,10 +9,10 @@ #ifndef MLIR_DIALECT_SPARSETENSOR_TRANSFORMOPS_SPARSETENSORTRANSFORMOPS_H #define MLIR_DIALECT_SPARSETENSOR_TRANSFORMOPS_SPARSETENSORTRANSFORMOPS_H -#include "mlir/Dialect/Transform/IR/MatchInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformAttrs.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/RegionKindInterface.h" diff --git a/mlir/include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.td b/mlir/include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.td index 9f0436e701b8bbe70029c8aa41f843cbdd844296..e340228795cdef166625268e5354ae0db127e84e 100644 --- a/mlir/include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.td +++ b/mlir/include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.td @@ -11,7 +11,7 @@ #ifndef SPARSETENSOR_TRANSFORM_OPS #define SPARSETENSOR_TRANSFORM_OPS -include "mlir/Dialect/Transform/IR/MatchInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.td" include "mlir/Dialect/Transform/IR/TransformAttrs.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" include "mlir/Dialect/Transform/IR/TransformTypes.td" diff --git a/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td b/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td index 670202fe4372e64adbe292e57f93cfb65483aa61..cf7f3e89079c1c851471348f80b686e57dd4638c 100644 --- a/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td +++ b/mlir/include/mlir/Dialect/Tensor/IR/TensorOps.td @@ -1364,7 +1364,7 @@ def Tensor_PadOp : Tensor_Op<"pad", [ unsigned count = staticAttrs.size(); for (unsigned idx = 0; idx < count; ++idx) { if (ShapedType::isDynamic(staticAttrs[idx])) - res.push_back(values[numDynamic++]); + res.push_back(getAsOpFoldResult(values[numDynamic++])); else res.push_back(builder.getI64IntegerAttr(staticAttrs[idx])); } diff --git a/mlir/include/mlir/Dialect/Tensor/TransformOps/TensorTransformOps.h b/mlir/include/mlir/Dialect/Tensor/TransformOps/TensorTransformOps.h index 0e5fda6041faaadb89af82e0deef71ba53ec4b0f..4fb777df340960a8a273cd3e8bf03f4d957436aa 100644 --- a/mlir/include/mlir/Dialect/Tensor/TransformOps/TensorTransformOps.h +++ b/mlir/include/mlir/Dialect/Tensor/TransformOps/TensorTransformOps.h @@ -9,8 +9,8 @@ #ifndef MLIR_DIALECT_TENSOR_TRANSFORMOPS_TENSORTRANSFORMOPS_H #define MLIR_DIALECT_TENSOR_TRANSFORMOPS_TENSORTRANSFORMOPS_H -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformTypes.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/PatternMatch.h" diff --git a/mlir/include/mlir/Dialect/Tensor/TransformOps/TensorTransformOps.td b/mlir/include/mlir/Dialect/Tensor/TransformOps/TensorTransformOps.td index 39e1d7fa3494a399334b70ddc3fe63886dc46b0c..fea5afa0b7bb39531c18764d3ef660d0819390f1 100644 --- a/mlir/include/mlir/Dialect/Tensor/TransformOps/TensorTransformOps.td +++ b/mlir/include/mlir/Dialect/Tensor/TransformOps/TensorTransformOps.td @@ -10,7 +10,7 @@ #define TENSOR_TRANSFORM_OPS include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Dialect/Transform/IR/TransformTypes.td" include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/IR/OpBase.td" diff --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td b/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td index 0ecded75c5d8bc4487765b0b7d9ba959a374ebb7..306e4a439520885e1f9e62127a3cecd6df62377d 100644 --- a/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td +++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td @@ -1942,7 +1942,7 @@ def Tosa_ConstOp : Tosa_Op<"const", [ConstantLike, Pure, ); let results = (outs - TensorOf<[AnyTypeOf<[Tosa_AnyNumber_Plus_F64, Tosa_Int4]>]>:$output + TensorOf<[AnyTypeOf<[Tosa_AnyNumber_Plus_F64]>]>:$output ); let hasFolder = 1; diff --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td b/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td index 5a4d6ff464f19e84cfc0d9d1a83c6e4832d841e9..cff3de0a69af957b4620ee66d05a36b116246460 100644 --- a/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td +++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td @@ -38,29 +38,17 @@ class Tosa_QuantizedType<string n, list<int> params, bit signed> // Used to express accumulator results or compare results. //===----------------------------------------------------------------------===// -def Tosa_UInt8 : UI<8>; -def Tosa_UInt16 : UI<16>; - def Tosa_Int4 : I<4>; def Tosa_Int8 : I<8>; -def Tosa_Int16 : I<16>; def Tosa_Int32 : I<32>; -def Tosa_Int48 : I<48>; def Tosa_Int64 : I<64>; -def Tosa_SignedInt : AnyTypeOf<[Tosa_Int8, - Tosa_Int16, - Tosa_Int32, - Tosa_Int48, - Tosa_Int64]>; - -def Tosa_Bool : I<1>; - -// No unsigned unquantized int types. -def Tosa_Int : AnyTypeOf<[Tosa_Bool, - Tosa_UInt8, - Tosa_UInt16, - Tosa_SignedInt]>; +// The TOSA dialect allows more types than the TOSA standard to allow for +// experimentation. For historical reasons, signless is used in the place of +// signed. +// The TosaValidation pass can be used to check for standard conformance. +def Tosa_Int : AnyTypeOf<[AnyUnsignedInteger, + AnySignlessInteger]>; def Tosa_Int32Or64 : AnyTypeOf<[Tosa_Int32, Tosa_Int64]>; @@ -172,9 +160,6 @@ class Tosa_TypeLike<list<Type> types, string description = ""> : TypeConstraint< def Tosa_IntLike : Tosa_TypeLike<[Tosa_Int], "signless-integer-like">; def Tosa_Int8Like : Tosa_TypeLike<[Tosa_Int8], "signless-integer-8-bit-like">; -def Tosa_Int16Like : Tosa_TypeLike<[Tosa_Int16], "signless-integer-16-bit-like">; -def Tosa_Int32Like : Tosa_TypeLike<[Tosa_Int32], "signless-integer-32-bit-like">; -def Tosa_Int64Like : Tosa_TypeLike<[Tosa_Int64], "signless-integer-64-bit-like">; //===----------------------------------------------------------------------===// // Attribute predicates and classes. diff --git a/mlir/include/mlir/Dialect/Transform/CMakeLists.txt b/mlir/include/mlir/Dialect/Transform/CMakeLists.txt index ef44ab891cc5c92495252de345684d851a7eed05..0cd71ec6919d9ebc93a6797646ec61a48910f3d5 100644 --- a/mlir/include/mlir/Dialect/Transform/CMakeLists.txt +++ b/mlir/include/mlir/Dialect/Transform/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(DebugExtension) +add_subdirectory(Interfaces) add_subdirectory(IR) add_subdirectory(LoopExtension) add_subdirectory(PDLExtension) diff --git a/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.h b/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.h index d660393a71e0a449fb305b110d3145f94424052a..ea541c9515b8328e7ea65575f578df69bdf7f6a6 100644 --- a/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.h +++ b/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.h @@ -10,9 +10,9 @@ #define MLIR_DIALECT_TRANSFORM_DEBUGEXTENSION_DEBUGEXTENSIONOPS_H #include "mlir/Bytecode/BytecodeOpInterface.h" -#include "mlir/Dialect/Transform/IR/MatchInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpDefinition.h" #include "mlir/IR/OpImplementation.h" #include "mlir/Interfaces/SideEffectInterfaces.h" diff --git a/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.td b/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.td index 16e2a39044b4964fb90261841a1a4e6f52262e4e..0275f241fda35f3c60d3abbfa479f172f792b93e 100644 --- a/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.td +++ b/mlir/include/mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.td @@ -16,8 +16,8 @@ include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/IR/OpBase.td" -include "mlir/Dialect/Transform/IR/MatchInterfaces.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" def DebugEmitRemarkAtOp : TransformDialectOp<"debug.emit_remark_at", diff --git a/mlir/include/mlir/Dialect/Transform/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/Transform/IR/CMakeLists.txt index 2b8a887257cae0ab19b5aa7374ec51f0ce700306..df5af7ae710dae2ef1107d1e62d825b8c1da26c4 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/CMakeLists.txt +++ b/mlir/include/mlir/Dialect/Transform/IR/CMakeLists.txt @@ -24,17 +24,3 @@ add_dependencies(mlir-headers MLIRTransformDialectEnumIncGen) add_mlir_dialect(TransformOps transform) add_mlir_doc(TransformOps TransformOps Dialects/ -gen-op-doc -dialect=transform) -# Contrary to what the name claims, this only produces the _op_ interface. -add_mlir_interface(TransformInterfaces) -add_mlir_doc(TransformInterfaces TransformOpInterfaces Dialects/ -gen-op-interface-docs) - -add_mlir_interface(MatchInterfaces) -add_dependencies(MLIRMatchInterfacesIncGen MLIRTransformInterfacesIncGen) -add_mlir_doc(TransformInterfaces MatchOpInterfaces Dialects/ -gen-op-interface-docs) - -set(LLVM_TARGET_DEFINITIONS TransformInterfaces.td) -mlir_tablegen(TransformTypeInterfaces.h.inc -gen-type-interface-decls) -mlir_tablegen(TransformTypeInterfaces.cpp.inc -gen-type-interface-defs) -add_public_tablegen_target(MLIRTransformDialectTypeInterfacesIncGen) -add_dependencies(mlir-headers MLIRTransformDialectTypeInterfacesIncGen) -add_mlir_doc(TransformInterfaces TransformTypeInterfaces Dialects/ -gen-type-interface-docs) diff --git a/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.h b/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.h index db27f2c6fc49b75adb9ece2a58335f141861156b..128eacdbe6ab7a7da612e0e4e5967d41222dd49f 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.h +++ b/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.h @@ -252,21 +252,21 @@ private: template <typename OpTy> void TransformDialect::addOperationIfNotRegistered() { - StringRef name = OpTy::getOperationName(); std::optional<RegisteredOperationName> opName = - RegisteredOperationName::lookup(name, getContext()); + RegisteredOperationName::lookup(TypeID::get<OpTy>(), getContext()); if (!opName) { addOperations<OpTy>(); #ifndef NDEBUG + StringRef name = OpTy::getOperationName(); detail::checkImplementsTransformOpInterface(name, getContext()); #endif // NDEBUG return; } - if (opName->getTypeID() == TypeID::get<OpTy>()) + if (LLVM_LIKELY(opName->getTypeID() == TypeID::get<OpTy>())) return; - reportDuplicateOpRegistration(name); + reportDuplicateOpRegistration(OpTy::getOperationName()); } template <typename Type> diff --git a/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.td b/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.td index 33c2e7ce0e6d62a6ef52fe912134cf153bb15355..d03049e186f94d7e0c54f7c1348341b963e8d8b9 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.td +++ b/mlir/include/mlir/Dialect/Transform/IR/TransformDialect.td @@ -23,7 +23,7 @@ def Transform_Dialect : Dialect { /// Symbol name for the default entry point "named sequence". constexpr const static ::llvm::StringLiteral kTransformEntryPointSymbolName = "__transform_main"; - + /// Name of the attribute attachable to the symbol table operation /// containing named sequences. This is used to trigger verification. constexpr const static ::llvm::StringLiteral @@ -34,12 +34,6 @@ def Transform_Dialect : Dialect { constexpr const static ::llvm::StringLiteral kTargetTagAttrName = "transform.target_tag"; - /// Name of the attribute attachable to an operation, indicating that - /// TrackingListener failures should be silenced. - constexpr const static ::llvm::StringLiteral - kSilenceTrackingFailuresAttrName = - "transform.silence_tracking_failures"; - /// Names of the attributes indicating whether an argument of an external /// transform dialect symbol is consumed or only read. constexpr const static ::llvm::StringLiteral kArgConsumedAttrName = diff --git a/mlir/include/mlir/Dialect/Transform/IR/TransformOps.h b/mlir/include/mlir/Dialect/Transform/IR/TransformOps.h index 1f46e34171b8ddcd185084e3adfe6b50cbb4a482..88185a07966d755485bf4b64ade27f37967fbfe5 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/TransformOps.h +++ b/mlir/include/mlir/Dialect/Transform/IR/TransformOps.h @@ -10,11 +10,11 @@ #define MLIR_DIALECT_TRANSFORM_IR_TRANSFORMOPS_H #include "mlir/Bytecode/BytecodeOpInterface.h" -#include "mlir/Dialect/Transform/IR/MatchInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformAttrs.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformTypes.h" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpDefinition.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/PatternMatch.h" diff --git a/mlir/include/mlir/Dialect/Transform/IR/TransformOps.td b/mlir/include/mlir/Dialect/Transform/IR/TransformOps.td index 1766e4bb875f327cf375d127080ba55c9f050107..21c9595860d4c5d85ddaf2758a6efe12f9dee9a5 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/TransformOps.td +++ b/mlir/include/mlir/Dialect/Transform/IR/TransformOps.td @@ -18,10 +18,10 @@ include "mlir/Interfaces/FunctionInterfaces.td" include "mlir/IR/OpAsmInterface.td" include "mlir/IR/RegionKindInterface.td" include "mlir/IR/SymbolInterfaces.td" -include "mlir/Dialect/Transform/IR/MatchInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.td" include "mlir/Dialect/Transform/IR/TransformAttrs.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" def AlternativesOp : TransformDialectOp<"alternatives", [DeclareOpInterfaceMethods<RegionBranchOpInterface, @@ -1098,15 +1098,28 @@ def PrintOp : TransformDialectOp<"print", MatchOpInterface]> { let summary = "Dump each payload op"; let description = [{ - This op dumps each payload op that is associated with the `target` operand - to stderr. It also prints the `name` string attribute. If no target is + Prints each payload op that is associated with the `target` operand to + `stdout`. It also prints the `name` string attribute. If no target is specified, the top-level op is dumped. This op is useful for printf-style debugging. + + Supported printing flag attributes: + * `assume_verified` -- skips verification when the unit attribute is + specified. This improves performace but may lead to crashes and + unexpected behavior when the printed payload op is invalid. + * `use_local_scope` -- prints in local scope when the unit attribute is + specified. This improves performance but may not be identical to + printing within the full module. + * `skip_regions` -- does not print regions of operations when the unit + attribute is specified. }]; let arguments = (ins Optional<TransformHandleTypeInterface>:$target, - OptionalAttr<StrAttr>:$name); + OptionalAttr<StrAttr>:$name, + OptionalAttr<UnitAttr>:$assume_verified, + OptionalAttr<UnitAttr>:$use_local_scope, + OptionalAttr<UnitAttr>:$skip_regions); let results = (outs); let builders = [ diff --git a/mlir/include/mlir/Dialect/Transform/IR/TransformTypes.h b/mlir/include/mlir/Dialect/Transform/IR/TransformTypes.h index bf0fc208829a7b208790495c333e52fb55c0026a..a0d54253c80d73fd2c898e8ade4c531147d3bc8b 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/TransformTypes.h +++ b/mlir/include/mlir/Dialect/Transform/IR/TransformTypes.h @@ -9,6 +9,7 @@ #ifndef MLIR_DIALECT_TRANSFORM_IR_TRANSFORMTYPES_H #define MLIR_DIALECT_TRANSFORM_IR_TRANSFORMTYPES_H +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Dialect/Transform/Utils/DiagnosedSilenceableFailure.h" #include "mlir/IR/Types.h" #include "mlir/Support/LLVM.h" @@ -19,7 +20,6 @@ class Operation; class Type; } // namespace mlir -#include "mlir/Dialect/Transform/IR/TransformTypeInterfaces.h.inc" #define GET_TYPEDEF_CLASSES #include "mlir/Dialect/Transform/IR/TransformTypes.h.inc" diff --git a/mlir/include/mlir/Dialect/Transform/IR/TransformTypes.td b/mlir/include/mlir/Dialect/Transform/IR/TransformTypes.td index 44dfce913d15a2a8cc0e09cdbe2a0b169f3bb8a2..2d9a26e165b672f2275cfb8b417ac66168826f26 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/TransformTypes.td +++ b/mlir/include/mlir/Dialect/Transform/IR/TransformTypes.td @@ -10,7 +10,7 @@ #define MLIR_DIALECT_TRANSFORM_IR_TRANSFORMTYPES include "mlir/IR/AttrTypeBase.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" def Transform_AffineMapParamType : TypeDef<Transform_Dialect, "AffineMapParam", diff --git a/mlir/include/mlir/Dialect/Transform/Interfaces/CMakeLists.txt b/mlir/include/mlir/Dialect/Transform/Interfaces/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..14ce5b82b8112358fb3ca2859cc744fe16f4b103 --- /dev/null +++ b/mlir/include/mlir/Dialect/Transform/Interfaces/CMakeLists.txt @@ -0,0 +1,17 @@ +# Contrary to what the name claims, this only produces the _op_ interface. The +# type interface is produced manually below. +add_mlir_interface(TransformInterfaces) +add_mlir_doc(TransformInterfaces TransformOpInterfaces Dialects/ -gen-op-interface-docs) + +set(LLVM_TARGET_DEFINITIONS TransformInterfaces.td) +mlir_tablegen(TransformTypeInterfaces.h.inc -gen-type-interface-decls) +mlir_tablegen(TransformTypeInterfaces.cpp.inc -gen-type-interface-defs) +add_public_tablegen_target(MLIRTransformDialectTypeInterfacesIncGen) +add_dependencies(mlir-headers MLIRTransformDialectTypeInterfacesIncGen) +add_mlir_doc(TransformInterfaces TransformTypeInterfaces Dialects/ -gen-type-interface-docs) + +add_mlir_interface(MatchInterfaces) +add_dependencies(MLIRMatchInterfacesIncGen MLIRTransformInterfacesIncGen) +add_dependencies(mlir-headers MLIRMatchInterfacesIncGen) +add_mlir_doc(MatchInterfaces MatchOpInterfaces Dialects/ -gen-op-interface-docs) + diff --git a/mlir/include/mlir/Dialect/Transform/IR/MatchInterfaces.h b/mlir/include/mlir/Dialect/Transform/Interfaces/MatchInterfaces.h similarity index 98% rename from mlir/include/mlir/Dialect/Transform/IR/MatchInterfaces.h rename to mlir/include/mlir/Dialect/Transform/Interfaces/MatchInterfaces.h index 36aeb4583029c9691aed72081eaf4840b7edf467..ad3e375c326fee8adb6a2f3623b481027c64c927 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/MatchInterfaces.h +++ b/mlir/include/mlir/Dialect/Transform/Interfaces/MatchInterfaces.h @@ -12,7 +12,7 @@ #include <optional> #include <type_traits> -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpDefinition.h" #include "llvm/ADT/STLExtras.h" @@ -218,6 +218,6 @@ expandTargetSpecification(Location loc, bool isAll, bool isInverted, } // namespace transform } // namespace mlir -#include "mlir/Dialect/Transform/IR/MatchInterfaces.h.inc" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.h.inc" #endif // MLIR_DIALECT_TRANSFORM_IR_MATCHINTERFACES_H diff --git a/mlir/include/mlir/Dialect/Transform/IR/MatchInterfaces.td b/mlir/include/mlir/Dialect/Transform/Interfaces/MatchInterfaces.td similarity index 97% rename from mlir/include/mlir/Dialect/Transform/IR/MatchInterfaces.td rename to mlir/include/mlir/Dialect/Transform/Interfaces/MatchInterfaces.td index be92e4d91b42b32357e4c92094212c7935d37231..56d2ac64859976ded6823d080fb4735bc2198c53 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/MatchInterfaces.td +++ b/mlir/include/mlir/Dialect/Transform/Interfaces/MatchInterfaces.td @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// include "mlir/IR/OpBase.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" def MatchOpInterface : OpInterface<"MatchOpInterface", [TransformOpInterface]> { diff --git a/mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.h b/mlir/include/mlir/Dialect/Transform/Interfaces/TransformInterfaces.h similarity index 99% rename from mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.h rename to mlir/include/mlir/Dialect/Transform/Interfaces/TransformInterfaces.h index 32724ff4b98e8e6c360de1d548061fc444a4b818..59cc2f22c93813dca8bc92c3289b5569d5f90f22 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.h +++ b/mlir/include/mlir/Dialect/Transform/Interfaces/TransformInterfaces.h @@ -6,10 +6,9 @@ // //===----------------------------------------------------------------------===// -#ifndef MLIR_DIALECT_TRANSFORM_IR_TRANSFORMINTERFACES_H -#define MLIR_DIALECT_TRANSFORM_IR_TRANSFORMINTERFACES_H +#ifndef MLIR_DIALECT_TRANSFORM_INTERFACES_TRANSFORMINTERFACES_H +#define MLIR_DIALECT_TRANSFORM_INTERFACES_TRANSFORMINTERFACES_H -#include "mlir/Dialect/Transform/IR/TransformTypes.h" #include "mlir/Dialect/Transform/Utils/DiagnosedSilenceableFailure.h" #include "mlir/Dialect/Transform/Utils/RaggedArray.h" #include "mlir/IR/OpDefinition.h" @@ -18,6 +17,8 @@ #include "mlir/Support/LogicalResult.h" #include "mlir/Transforms/DialectConversion.h" +#include "mlir/Dialect/Transform/Interfaces/TransformTypeInterfaces.h.inc" + namespace mlir { namespace transform { @@ -74,7 +75,7 @@ getConsumedHandleOpOperands(transform::TransformOpInterface transformOp); } // namespace transform } // namespace mlir -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h.inc" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h.inc" namespace mlir { namespace transform { @@ -1591,4 +1592,4 @@ mlir::transform::TransformEachOpTrait<OpTy>::verifyTrait(Operation *op) { return success(); } -#endif // DIALECT_TRANSFORM_IR_TRANSFORMINTERFACES_H +#endif // DIALECT_TRANSFORM_INTERFACES_TRANSFORMINTERFACES_H diff --git a/mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.td b/mlir/include/mlir/Dialect/Transform/Interfaces/TransformInterfaces.td similarity index 98% rename from mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.td rename to mlir/include/mlir/Dialect/Transform/Interfaces/TransformInterfaces.td index 8f7b8f1999e0c595d3149fc381439ddc0e5aa217..c5c4c61bc2fe5cde7a8bfea65d52c1d43d1c9a76 100644 --- a/mlir/include/mlir/Dialect/Transform/IR/TransformInterfaces.td +++ b/mlir/include/mlir/Dialect/Transform/Interfaces/TransformInterfaces.td @@ -241,6 +241,14 @@ def FindPayloadReplacementOpInterface /*arguments=*/(ins) >, ]; + + let extraSharedClassDeclaration = [{ + /// Name of the attribute attachable to an operation, indicating that + /// TrackingListener failures should be silenced. + constexpr const static ::llvm::StringLiteral + kSilenceTrackingFailuresAttrName = + "transform.silence_tracking_failures"; + }]; } def PatternDescriptorOpInterface : OpInterface<"PatternDescriptorOpInterface"> { diff --git a/mlir/include/mlir/Dialect/Transform/LoopExtension/LoopExtensionOps.h b/mlir/include/mlir/Dialect/Transform/LoopExtension/LoopExtensionOps.h index 68cc0699d081a0df35a7582da512f3ea29507d8b..f3f696bb0b9c6980cb5211182a3eda8a5503a81b 100644 --- a/mlir/include/mlir/Dialect/Transform/LoopExtension/LoopExtensionOps.h +++ b/mlir/include/mlir/Dialect/Transform/LoopExtension/LoopExtensionOps.h @@ -11,7 +11,7 @@ #include "mlir/Bytecode/BytecodeOpInterface.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpDefinition.h" #include "mlir/IR/OpImplementation.h" #include "mlir/Interfaces/LoopLikeInterface.h" diff --git a/mlir/include/mlir/Dialect/Transform/LoopExtension/LoopExtensionOps.td b/mlir/include/mlir/Dialect/Transform/LoopExtension/LoopExtensionOps.td index 78a8c6ad489a9af1fe0f566b407f9ff5e4901546..885b55811e62ce304ef4b03223da9974342dfd33 100644 --- a/mlir/include/mlir/Dialect/Transform/LoopExtension/LoopExtensionOps.td +++ b/mlir/include/mlir/Dialect/Transform/LoopExtension/LoopExtensionOps.td @@ -10,7 +10,7 @@ #define MLIR_DIALECT_TRANSFORM_LOOPEXTENSION_LOOPEXTENSIONOPS include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Interfaces/SideEffectInterfaces.td" def HoistLoopInvariantSubsetsOp diff --git a/mlir/include/mlir/Dialect/Transform/PDLExtension/PDLExtensionOps.h b/mlir/include/mlir/Dialect/Transform/PDLExtension/PDLExtensionOps.h index 5172bcf204e5f09856fb3113545d9f4ba15f694d..7f52e00ec30b642845cb9afafb33312c0fdd0714 100644 --- a/mlir/include/mlir/Dialect/Transform/PDLExtension/PDLExtensionOps.h +++ b/mlir/include/mlir/Dialect/Transform/PDLExtension/PDLExtensionOps.h @@ -11,7 +11,7 @@ #include "mlir/Bytecode/BytecodeOpInterface.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpDefinition.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/SymbolTable.h" diff --git a/mlir/include/mlir/Dialect/Transform/PDLExtension/PDLExtensionOps.td b/mlir/include/mlir/Dialect/Transform/PDLExtension/PDLExtensionOps.td index 206a799690aa59c0991469900756a0c04d6a178d..4c4d230d2ae4bf2909f4024d2c8b6ca0b2e39a6b 100644 --- a/mlir/include/mlir/Dialect/Transform/PDLExtension/PDLExtensionOps.td +++ b/mlir/include/mlir/Dialect/Transform/PDLExtension/PDLExtensionOps.td @@ -10,7 +10,7 @@ #define MLIR_DIALECT_TRANSFORM_PDLEXTENSION_PDLEXTENSIONOPS include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/IR/OpAsmInterface.td" include "mlir/IR/SymbolInterfaces.td" diff --git a/mlir/include/mlir/Dialect/Transform/Transforms/TransformInterpreterPassBase.h b/mlir/include/mlir/Dialect/Transform/Transforms/TransformInterpreterPassBase.h index 16ef0bc6a7392001e39267a9f10c96946f85eb8c..3a4b391fd7f4ae617ada95404bf5344f5d3a9e70 100644 --- a/mlir/include/mlir/Dialect/Transform/Transforms/TransformInterpreterPassBase.h +++ b/mlir/include/mlir/Dialect/Transform/Transforms/TransformInterpreterPassBase.h @@ -14,7 +14,7 @@ #ifndef MLIR_DIALECT_TRANSFORM_TRANSFORMS_TRANSFORMINTERPRETERPASSBASE_H #define MLIR_DIALECT_TRANSFORM_TRANSFORMS_TRANSFORMINTERPRETERPASSBASE_H -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Pass/Pass.h" #include "mlir/Support/LLVM.h" #include <memory> diff --git a/mlir/include/mlir/Dialect/Transform/Transforms/TransformInterpreterUtils.h b/mlir/include/mlir/Dialect/Transform/Transforms/TransformInterpreterUtils.h index 738e0c533c6b518115b2f592a27668940490477d..4c16d40d368e0ff983ce4d17d73323843a1f7d98 100644 --- a/mlir/include/mlir/Dialect/Transform/Transforms/TransformInterpreterUtils.h +++ b/mlir/include/mlir/Dialect/Transform/Transforms/TransformInterpreterUtils.h @@ -10,7 +10,7 @@ #define MLIR_DIALECT_TRANSFORM_TRANSFORMS_TRANSFORMINTERPRETERUTILS_H #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Pass/Pass.h" #include "mlir/Support/LLVM.h" #include <memory> diff --git a/mlir/include/mlir/Dialect/Utils/StaticValueUtils.h b/mlir/include/mlir/Dialect/Utils/StaticValueUtils.h index 1dc0398494dccf3d19dbc9673df3a5e1bbd3c6cd..20f019666a2e6a917cc5b359fdc7fc6d6a3d86b9 100644 --- a/mlir/include/mlir/Dialect/Utils/StaticValueUtils.h +++ b/mlir/include/mlir/Dialect/Utils/StaticValueUtils.h @@ -15,6 +15,7 @@ #ifndef MLIR_DIALECT_UTILS_STATICVALUEUTILS_H #define MLIR_DIALECT_UTILS_STATICVALUEUTILS_H +#include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/OpDefinition.h" #include "mlir/Support/LLVM.h" diff --git a/mlir/include/mlir/Dialect/Vector/IR/ScalableValueBoundsConstraintSet.h b/mlir/include/mlir/Dialect/Vector/IR/ScalableValueBoundsConstraintSet.h new file mode 100644 index 0000000000000000000000000000000000000000..31e19ff1ad39f7f1b9bd9edb83ff7612de3158e6 --- /dev/null +++ b/mlir/include/mlir/Dialect/Vector/IR/ScalableValueBoundsConstraintSet.h @@ -0,0 +1,104 @@ +//===- ScalableValueBoundsConstraintSet.h - Scalable Value Bounds ---------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DIALECT_VECTOR_IR_SCALABLEVALUEBOUNDSCONSTRAINTSET_H +#define MLIR_DIALECT_VECTOR_IR_SCALABLEVALUEBOUNDSCONSTRAINTSET_H + +#include "mlir/Analysis/Presburger/IntegerRelation.h" +#include "mlir/Dialect/Vector/IR/VectorOps.h" +#include "mlir/Interfaces/ValueBoundsOpInterface.h" + +namespace mlir::vector { + +namespace detail { + +/// Parent class for the value bounds RTTIExtends. Uses protected inheritance to +/// hide all ValueBoundsConstraintSet methods by default (as some do not use the +/// ScalableValueBoundsConstraintSet, so may produce unexpected results). +struct ValueBoundsConstraintSet : protected ::mlir::ValueBoundsConstraintSet { + using ::mlir::ValueBoundsConstraintSet::ValueBoundsConstraintSet; +}; +} // namespace detail + +/// A version of `ValueBoundsConstraintSet` that can solve for scalable bounds. +struct ScalableValueBoundsConstraintSet + : public llvm::RTTIExtends<ScalableValueBoundsConstraintSet, + detail::ValueBoundsConstraintSet> { + ScalableValueBoundsConstraintSet(MLIRContext *context, unsigned vscaleMin, + unsigned vscaleMax) + : RTTIExtends(context), vscaleMin(vscaleMin), vscaleMax(vscaleMax){}; + + using RTTIExtends::bound; + using RTTIExtends::StopConditionFn; + + /// A thin wrapper over an `AffineMap` which can represent a constant bound, + /// or a scalable bound (in terms of vscale). The `AffineMap` will always + /// take at most one parameter, vscale, and returns a single result, which is + /// the bound of value. + struct ConstantOrScalableBound { + AffineMap map; + + struct BoundSize { + int64_t baseSize{0}; + bool scalable{false}; + }; + + /// Get the (possibly) scalable size of the bound, returns failure if + /// the bound cannot be represented as a single quantity. + FailureOr<BoundSize> getSize() const; + }; + + /// Computes a (possibly) scalable bound for a given value. This is + /// similar to `ValueBoundsConstraintSet::computeConstantBound()`, but + /// uses knowledge of the range of vscale to compute either a constant + /// bound, an expression in terms of vscale, or failure if no bound can + /// be computed. + /// + /// The resulting `AffineMap` will always take at most one parameter, + /// vscale, and return a single result, which is the bound of `value`. + /// + /// Note: `vscaleMin` must be `<=` to `vscaleMax`. If `vscaleMin` == + /// `vscaleMax`, the resulting bound (if found), will be constant. + static FailureOr<ConstantOrScalableBound> + computeScalableBound(Value value, std::optional<int64_t> dim, + unsigned vscaleMin, unsigned vscaleMax, + presburger::BoundType boundType, bool closedUB = true, + StopConditionFn stopCondition = nullptr); + + /// Get the value of vscale. Returns `nullptr` vscale as not been encountered. + Value getVscaleValue() const { return vscale; } + + /// Sets the value of vscale. Asserts if vscale has already been set. + void setVscale(vector::VectorScaleOp vscaleOp) { + assert(!vscale && "expected vscale to be unset"); + vscale = vscaleOp.getResult(); + } + + /// The minimum possible value of vscale. + unsigned getVscaleMin() const { return vscaleMin; } + + /// The maximum possible value of vscale. + unsigned getVscaleMax() const { return vscaleMax; } + + static char ID; + +private: + const unsigned vscaleMin; + const unsigned vscaleMax; + + // This will be set when the first `vector.vscale` operation is found within + // the `ValueBoundsOpInterface` implementation then reused from there on. + Value vscale = nullptr; +}; + +using ConstantOrScalableBound = + ScalableValueBoundsConstraintSet::ConstantOrScalableBound; + +} // namespace mlir::vector + +#endif // MLIR_DIALECT_VECTOR_IR_SCALABLEVALUEBOUNDSCONSTRAINTSET_H diff --git a/mlir/include/mlir/Dialect/Vector/IR/ValueBoundsOpInterfaceImpl.h b/mlir/include/mlir/Dialect/Vector/IR/ValueBoundsOpInterfaceImpl.h new file mode 100644 index 0000000000000000000000000000000000000000..4794bc9016c6f949190bea39386a8c3f24b5f2fb --- /dev/null +++ b/mlir/include/mlir/Dialect/Vector/IR/ValueBoundsOpInterfaceImpl.h @@ -0,0 +1,20 @@ +//===- ValueBoundsOpInterfaceImpl.h - Impl. of ValueBoundsOpInterface -----===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DIALECT_VECTOR_IR_VALUEBOUNDSOPINTERFACEIMPL_H +#define MLIR_DIALECT_VECTOR_IR_VALUEBOUNDSOPINTERFACEIMPL_H + +namespace mlir { +class DialectRegistry; + +namespace vector { +void registerValueBoundsOpInterfaceExternalModels(DialectRegistry ®istry); +} // namespace vector +} // namespace mlir + +#endif // MLIR_DIALECT_VECTOR_IR_VALUEBOUNDSOPINTERFACEIMPL_H diff --git a/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.h b/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.h index 1fa9057a068213dd1693987f599e3ef7185a7da9..c43a8a0b02c67e20ff9bf4c59a69e751dfd32a9a 100644 --- a/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.h +++ b/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.h @@ -9,7 +9,7 @@ #ifndef MLIR_DIALECT_VECTOR_TRANSFORMOPS_VECTORTRANSFORMOPS_H #define MLIR_DIALECT_VECTOR_TRANSFORMOPS_VECTORTRANSFORMOPS_H -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Dialect/Vector/Transforms/VectorRewritePatterns.h" #include "mlir/Dialect/Vector/Transforms/VectorTransforms.h" #include "mlir/IR/OpImplementation.h" diff --git a/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td b/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td index 83df5fe27d7a4a70f61f056a00434ce971666ee1..f6371f39c394443303e4d496ad55c2063f1fcb32 100644 --- a/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td +++ b/mlir/include/mlir/Dialect/Vector/TransformOps/VectorTransformOps.td @@ -10,7 +10,7 @@ #define VECTOR_TRANSFORM_OPS include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Dialect/Vector/Transforms/VectorTransformsBase.td" include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/IR/OpBase.td" diff --git a/mlir/include/mlir/Dialect/Vector/Transforms/VectorTransforms.h b/mlir/include/mlir/Dialect/Vector/Transforms/VectorTransforms.h index 08d3bb157a0e396105b2117d126ca4bca2588ff1..1f7d6411cd5a468265ed6319dcbc0401d2fc4d60 100644 --- a/mlir/include/mlir/Dialect/Vector/Transforms/VectorTransforms.h +++ b/mlir/include/mlir/Dialect/Vector/Transforms/VectorTransforms.h @@ -110,8 +110,10 @@ void transferOpflowOpt(RewriterBase &rewriter, Operation *rootOp); /// Cast away the leading unit dim, if exists, for the given contract op. /// Return success if the transformation applies; return failure otherwise. -LogicalResult castAwayContractionLeadingOneDim(vector::ContractionOp contractOp, - RewriterBase &rewriter); +FailureOr<Value> +castAwayContractionLeadingOneDim(vector::ContractionOp contractOp, + MaskingOpInterface maskingOp, + RewriterBase &rewriter); } // namespace vector } // namespace mlir diff --git a/mlir/include/mlir/Dialect/Vector/Utils/VectorUtils.h b/mlir/include/mlir/Dialect/Vector/Utils/VectorUtils.h index f6b03a0f2c8007fb170d316bf91b5e17a8c241a8..f88fbdf9e627659c30b8d00e140da224c6d73ea8 100644 --- a/mlir/include/mlir/Dialect/Vector/Utils/VectorUtils.h +++ b/mlir/include/mlir/Dialect/Vector/Utils/VectorUtils.h @@ -9,12 +9,15 @@ #ifndef MLIR_DIALECT_VECTOR_UTILS_VECTORUTILS_H_ #define MLIR_DIALECT_VECTOR_UTILS_VECTORUTILS_H_ +#include "mlir/Dialect/MemRef/IR/MemRef.h" +#include "mlir/Dialect/Tensor/IR/Tensor.h" #include "mlir/Dialect/Utils/IndexingUtils.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/Support/LLVM.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/TypeSwitch.h" namespace mlir { @@ -98,6 +101,85 @@ bool isContiguousSlice(MemRefType memrefType, VectorType vectorType); std::optional<StaticTileOffsetRange> createUnrollIterator(VectorType vType, int64_t targetRank = 1); +/// A wrapper for getMixedSizes for vector.transfer_read and +/// vector.transfer_write Ops (for source and destination, respectively). +/// +/// Tensor and MemRef types implement their own, very similar version of +/// getMixedSizes. This method will call the appropriate version (depending on +/// `hasTensorSemantics`). It will also automatically extract the operand for +/// which to call it on (source for "read" and destination for "write" ops). +SmallVector<OpFoldResult> getMixedSizesXfer(bool hasTensorSemantics, + Operation *xfer, + RewriterBase &rewriter); + +/// A pattern for ops that implement `MaskableOpInterface` and that _might_ be +/// masked (i.e. inside `vector.mask` Op region). In particular: +/// 1. Matches `SourceOp` operation, Op. +/// 2.1. If Op is masked, retrieves the masking Op, maskOp, and updates the +/// insertion point to avoid inserting new ops into the `vector.mask` Op +/// region (which only allows one Op). +/// 2.2 If Op is not masked, this step is skipped. +/// 3. Invokes `matchAndRewriteMaskableOp` on Op and optionally maskOp if +/// found in step 2.1. +/// +/// This wrapper frees patterns from re-implementing the logic to update the +/// insertion point when a maskable Op is masked. Such patterns are still +/// responsible for providing an updated ("rewritten") version of: +/// a. the source Op when mask _is not_ present, +/// b. the source Op and the masking Op when mask _is_ present. +/// To use this pattern, implement `matchAndRewriteMaskableOp`. Note that +/// the return value will depend on the case above. +template <class SourceOp> +struct MaskableOpRewritePattern : OpRewritePattern<SourceOp> { + using OpRewritePattern<SourceOp>::OpRewritePattern; + +private: + LogicalResult matchAndRewrite(SourceOp sourceOp, + PatternRewriter &rewriter) const final { + auto maskableOp = dyn_cast<MaskableOpInterface>(sourceOp.getOperation()); + if (!maskableOp) + return failure(); + + Operation *rootOp = sourceOp; + + // If this Op is masked, update the insertion point to avoid inserting into + // the vector.mask Op region. + OpBuilder::InsertionGuard guard(rewriter); + MaskingOpInterface maskOp; + if (maskableOp.isMasked()) { + maskOp = maskableOp.getMaskingOp(); + rewriter.setInsertionPoint(maskOp); + rootOp = maskOp; + } + + FailureOr<Value> newOp = + matchAndRewriteMaskableOp(sourceOp, maskOp, rewriter); + if (failed(newOp)) + return failure(); + + rewriter.replaceOp(rootOp, *newOp); + return success(); + } + +public: + // Matches `sourceOp` that can potentially be masked with `maskingOp`. If the + // latter is present, returns a replacement for `maskingOp`. Otherwise, + // returns a replacement for `sourceOp`. + virtual FailureOr<Value> + matchAndRewriteMaskableOp(SourceOp sourceOp, MaskingOpInterface maskingOp, + PatternRewriter &rewriter) const = 0; +}; + +/// Returns true if the input Vector type can be linearized. +/// +/// Linearization is meant in the sense of flattening vectors, e.g.: +/// * vector<NxMxKxi32> -> vector<N*M*Kxi32> +/// In this sense, Vectors that are either: +/// * already linearized, or +/// * contain more than 1 scalable dimensions, +/// are not linearizable. +bool isLinearizableVector(VectorType type); + } // namespace vector /// Constructs a permutation map of invariant memref indices to vector diff --git a/mlir/include/mlir/Dialect/XeGPU/IR/XeGPU.h b/mlir/include/mlir/Dialect/XeGPU/IR/XeGPU.h index 7aaa4ecc7ee77a5c9a10cba19e1513c363c9bf65..87aabdc015fea5d6b9bdde486e2f540c46a7d574 100644 --- a/mlir/include/mlir/Dialect/XeGPU/IR/XeGPU.h +++ b/mlir/include/mlir/Dialect/XeGPU/IR/XeGPU.h @@ -9,7 +9,12 @@ #ifndef MLIR_DIALECT_XEGPU_IR_XEGPU_H #define MLIR_DIALECT_XEGPU_IR_XEGPU_H -#include <mlir/IR/Dialect.h> +#include "mlir/Bytecode/BytecodeOpInterface.h" +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/IR/Dialect.h" +#include "mlir/Interfaces/ShapedOpInterfaces.h" +#include "mlir/Interfaces/SideEffectInterfaces.h" +#include "mlir/Interfaces/ViewLikeInterface.h" namespace mlir { namespace xegpu { diff --git a/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUAttrs.td b/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUAttrs.td index bb325c272e3324aa2998f9e71422fe3ffbd95a03..cd38549f1ccf4324dbb41a28414953881a2cde48 100644 --- a/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUAttrs.td +++ b/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUAttrs.td @@ -10,6 +10,7 @@ #define MLIR_DIALECT_XEGPU_IR_XEGPUATTRS_TD include "mlir/Dialect/XeGPU/IR/XeGPUDialect.td" +include "mlir/IR/EnumAttr.td" class XeGPUAttr<string name, string attrMnemonic, list<Trait> traits = [], string baseCppClass = "::mlir::Attribute"> @@ -17,4 +18,64 @@ class XeGPUAttr<string name, string attrMnemonic, list<Trait> traits = [], let mnemonic = attrMnemonic; } +def XeGPU_TensorDescAttr: XeGPUAttr<"TensorDesc", "tdesc_attr"> { + let parameters = (ins + OptionalParameter<"MemoryScopeAttr">: $memory_scope, + OptionalParameter<"IntegerAttr", "1">: $array_length, + OptionalParameter<"BoolAttr", "true">: $boundary_check + ); + + let builders = [ + AttrBuilder<(ins + CArg<"xegpu::MemoryScope", "xegpu::MemoryScope::Global">:$memory_scope, + CArg<"int", "1">:$array_length, + CArg<"bool", "true">: $boundary_check + )> + ]; + + let assemblyFormat = "`<` struct(params) `>`"; +} + +//===----------------------------------------------------------------------===// +// XeGPU Memory Scope Enums. +//===----------------------------------------------------------------------===// +def XeGPU_MemoryScopeGlobal: I32EnumAttrCase<"Global", 0, "global">; +def XeGPU_MemoryScopeShared: I32EnumAttrCase<"SLM", 1, "slm">; +def XeGPU_MemoryScope: I32EnumAttr<"MemoryScope", + "The address space of the memory the tensor descritor is created for", + [XeGPU_MemoryScopeGlobal, XeGPU_MemoryScopeShared]> { + let genSpecializedAttr = 0; + let cppNamespace = "::mlir::xegpu"; +} + +def XeGPU_MemoryScopeAttr: + EnumAttr<XeGPU_Dialect, XeGPU_MemoryScope, "memory_scope"> { + let assemblyFormat = "$value"; +} + +//===----------------------------------------------------------------------===// +// XeGPU Cache Enums. +//===----------------------------------------------------------------------===// +def XeGPU_CachePolicyCached: I32EnumAttrCase<"CACHED", 0, "cached">; // valid for read and write +def XeGPU_CachePolicyUncached: I32EnumAttrCase<"UNCACHED", 1, "uncached">; // valid for read and write +def XeGPU_CachePolicyStreaming: I32EnumAttrCase<"STREAMING", 2, "streaming">; // valid for read only +def XeGPU_CachePolicyInvalid: I32EnumAttrCase<"READ_INVALIDATE", 3, "read_invalidate">; // valid for read only +def XeGPU_CachePolicyWriteBack: I32EnumAttrCase<"WRITE_BACK", 4, "write_back">; // valid for write only +def XeGPU_CachePolicyWriteThrough: I32EnumAttrCase<"WRITE_THROUGH", 5, "write_through">; // valid for write only + +def XeGPU_CachePolicyEnums : I32EnumAttr<"CachePolicy", "Cache policy", + [XeGPU_CachePolicyCached, XeGPU_CachePolicyUncached, + XeGPU_CachePolicyStreaming, XeGPU_CachePolicyInvalid, + XeGPU_CachePolicyWriteBack, XeGPU_CachePolicyWriteThrough]> { + let genSpecializedAttr = 0; + let cppNamespace = "::mlir::xegpu"; +} + +def XeGPU_CacheHintAttr + : EnumAttr<XeGPU_Dialect, XeGPU_CachePolicyEnums, "cache_hint"> { + let assemblyFormat = "`<` $value `>`"; +} + + + #endif // MLIR_DIALECT_XEGPU_IR_XEGPUATTRS_TD diff --git a/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUDialect.td b/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUDialect.td index 3851275ad30a0a9b0c143cd5ec66ef7ceded10b7..c2f09319c790e0a7183c5561b50b135071c25ee0 100644 --- a/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUDialect.td +++ b/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUDialect.td @@ -23,8 +23,8 @@ def XeGPU_Dialect : Dialect { the lower-level GPU compiler. }]; - // let useDefaultTypePrinterParser = true; - // let useDefaultAttributePrinterParser = true; + let useDefaultTypePrinterParser = true; + let useDefaultAttributePrinterParser = true; } #endif // MLIR_DIALECT_XEGPU_IR_XEGPUDIALECT_TD diff --git a/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUOps.td b/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUOps.td index 5825ef9195b03ff4ed6d15028f303b4da80c4511..93c56ad05b432ca4bba6bef10f15bbc38df0bbf7 100644 --- a/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUOps.td +++ b/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUOps.td @@ -9,10 +9,13 @@ #ifndef MLIR_DIALECT_XEGPU_IR_XEGPUOPS_TD #define MLIR_DIALECT_XEGPU_IR_XEGPUOPS_TD +include "mlir/IR/AttrTypeBase.td" include "mlir/Dialect/XeGPU/IR/XeGPUAttrs.td" include "mlir/Dialect/XeGPU/IR/XeGPUDialect.td" include "mlir/Dialect/XeGPU/IR/XeGPUTypes.td" - +include "mlir/Interfaces/ShapedOpInterfaces.td" +include "mlir/Interfaces/SideEffectInterfaces.td" +include "mlir/Interfaces/ViewLikeInterface.td" // Base class for dialect operations. This operation inherits from the base // `Op` class in OpBase.td, and provides: @@ -20,7 +23,305 @@ include "mlir/Dialect/XeGPU/IR/XeGPUTypes.td" // * The mnemonic for the operation, or the name without the dialect prefix. // * A list of traits for the operation. class XeGPU_Op<string mnemonic, list<Trait> traits = []>: - Op<XeGPU_Dialect, mnemonic, traits>; + Op<XeGPU_Dialect, mnemonic, traits> { + + code extraBaseClassDeclaration = [{ + void printProperties(::mlir::MLIRContext *ctx, + ::mlir::OpAsmPrinter &p, const Properties &prop) { + Attribute propAttr = getPropertiesAsAttr(ctx, prop); + if (propAttr) + p << "<" << propAttr << ">"; + } + + static ::mlir::ParseResult parseProperties(::mlir::OpAsmParser &parser, + ::mlir::OperationState &result) { + if (mlir::succeeded(parser.parseLess())) { + if (parser.parseAttribute(result.propertiesAttr) || parser.parseGreater()) + return failure(); + } + return success(); + } + + }]; +} + + +def XeGPU_CreateNdDescOp: XeGPU_Op<"create_nd_tdesc", [Pure, ViewLikeOpInterface, + AttrSizedOperandSegments, OffsetSizeAndStrideOpInterface]> { + + let summary = "Create nd-tensor descriptor operation"; + let description = [{ + The "create_nd_tdesc" operation creates a TensorDescType which represents + a sub-view of a 2D memory region (It can be extended to support n-D memory + region if needed in future). Elements in the subview continuous in each + dimention. It encodes the following important information for supporting + Intel hardware features: + + * source: an object representing (starting address/pointer of) a 2D memory region. + It can be either a 2D memref object, or simply a pointer represented by uint64_t type. + for the later case, the shape and layout information of the 2D memory region should + be explicitly passed via `dynamic_shape` and `dynamic_strides` parameters. + * offsets: two index values represents offsets from the "source" at the each dimension + at which the subview of the target memory will be created. It is encoded via two + variables, including "dynamic_offsets" and "static_offsets", such that it can + accept various forms, such as, operands (e.g., [%c0, %c]) and attributes (e.g., [2, 4])). + * shape: the shape information of the memory region pointed by the "source". It is + typically encoded via the MemRefType of the source, e.g., memref<4096x4096xf16>. + But if "source" is simply a pointer represented as uint64_t type, or a memref + type without shape information e.g., memref<?x?xf16>, the shape information has + to be explicitly passed via the "dynamic_shape" argument. Currently "dynamic_shape" + only accepts operands(e.g., [%c4096, %c4096]), not attributes(e.g., [4096, 4096]). + * strides: the strides of the memory region pointed by the "source". Similar to shape, + it is typically encoded via the MemRefType of the source too. But if "source" is + simply a pointer represented as uint64_t type, or a memref type without shape + information e.g., memref<?x?xf16>, the strides information has to be explicitly + passed via the "dynamic_strides" argument. And it currently only accepts operands two. + + Example 1 (suppose the tensor shape inferred by the compiler is 8x16): + %0 = memref.alloc() : memref<1024x1024xf32> + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %1 = xegpu.create_nd_tdesc %0[%c0, %c0]: memref<1024x1024xf32> -> TensorDesc<8x16xf32> + + Example 2 (suppose the tensor shape inferred by the compiler is 8x16): + %0 = memref.alloc(%h, %w) : memref<?x?xf32> + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %1 = xegpu.create_nd_tdesc %0[%c0, %c0], [%h, %w], [%w, %c1]: memref<?x?xf32> -> TensorDesc<8x16xf32> + + Example 3 (suppose the tensor shape inferred by the compiler is 8x16): + %0 = ... : ui64 + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %1 = xegpu.create_nd_tdesc %0[%c0, %c0], [%h, %w], [%w, %c1]: ui64 -> TensorDesc<8x16xf32> + }]; + + let arguments = (ins + XeGPU_BaseAddrType: $source, + Variadic<Index>: $offsets, + Variadic<Index>: $shape, + Variadic<Index>: $strides, + DenseI64ArrayAttr: $const_offsets, + OptionalAttr<DenseI64ArrayAttr>: $const_shape, + OptionalAttr<DenseI64ArrayAttr>: $const_strides + ); + let results = (outs XeGPU_TensorDesc: $TensorDesc); + + let assemblyFormat = [{ + $source `` + custom<DynamicIndexList>($offsets, $const_offsets) + (`,` custom<DynamicIndexList>($shape, $const_shape)^ + `,` custom<DynamicIndexList>($strides, $const_strides))? + attr-dict `:` type($source) `->` qualified(type($TensorDesc)) + }]; + + let hasVerifier = 1; + + let builders = [ + OpBuilder<(ins "Type": $tdesc, "TypedValue<MemRefType>": $source, + "llvm::ArrayRef<OpFoldResult>": $offsets)>, + + OpBuilder<(ins "Type": $tdesc, "TypedValue<IntegerType> ": $source, + "llvm::ArrayRef<OpFoldResult>": $offsets, + "llvm::ArrayRef<OpFoldResult>": $shape, + "llvm::ArrayRef<OpFoldResult>": $strides)> + ]; + + let extraClassDeclaration = extraBaseClassDeclaration # [{ + /// Returns the type of the source memref operand. + Type getSourceType() { + return getSource().getType(); + } + + /// Returns the type of the result TensorDesc. + xegpu::TensorDescType getType() { + return getTensorDesc().getType(); + } + + /// Return the element type of the TensorDesc + Type getElementType() { + return getType().getElementType(); + } + + /// Return the shape of the TensorDesc + llvm::ArrayRef<int64_t> getTensorDescShape() { + return getType().getShape(); + } + + /// wrapper for matching with OffsetSizeAndStrideOpInterface + OperandRange getSizes() { + return getShape(); + } + + ArrayRef<int64_t> getStaticOffsets(){ + return getConstOffsets(); + } + + /// wrapper for matching with OffsetSizeAndStrideOpInterface + /// If source is IntegerType or `const_shape` is filled, + /// it will return `const_shape`, such that mixes of `shape` + /// and `const_shape` will be used to represent the shape of + /// source operand. They overide static shape from source memref type. + ArrayRef<int64_t> getStaticSizes() { + auto attr = getConstShapeAttr(); + if (getSourceType().isa<IntegerType>() || attr) + return attr; + + auto memrefType = getSourceType().dyn_cast<MemRefType>(); + assert(memrefType && "Incorrect use of getStaticSizes"); + return memrefType.getShape(); + } + + /// wrapper for matching with OffsetSizeAndStrideOpInterface + /// If source is IntegerType or `const_strides` is filled, it + /// will return `const_strides`, such that mixes of `strides` + /// and `const_strides` will be used to represent the strides of + /// source operand. They overide static strides from source memref type. + ArrayRef<int64_t> getStaticStrides() { + auto attr = getConstStridesAttr(); + if (getSourceType().isa<IntegerType>() || attr) + return attr; + + auto memrefType = getSourceType().dyn_cast<MemRefType>(); + assert(memrefType && "Incorrect use of getStaticStrides"); + auto [strides, offset] = getStridesAndOffset(memrefType); + // reuse the storage of ConstStridesAttr since strides from + // memref is not persistant + setConstStrides(strides); + attr = getConstStridesAttr(); + return attr; + } + + /// Return the expected rank of each of the`static_offsets`, + /// `static_shape` and `static_strides` attributes. + std::array<unsigned, 3> getArrayAttrMaxRanks() { + unsigned rank; + if (auto ty = getSourceType().dyn_cast<MemRefType>()) { + rank = ty.getRank(); + } else { + rank = (unsigned)getMixedOffsets().size(); + } + return {rank, rank, rank}; + } + + /// Return the number of leading operands before the `offsets`, + /// `shape` and `strides` operands. + static unsigned getOffsetSizeAndStrideStartOperandIndex() { return 1; } + + mlir::Value getViewSource() { return getSource(); } + }]; +} + +def XeGPU_PrefetchNdOp : XeGPU_Op<"prefetch_nd", []> { + let summary = "prefetches a nD block to cache"; + let description = [{ + It issues an instruction to prefetch the data from memory to each + level of the cache based on their cache policy. + + Example: + ``` + xegpu.prefetch_nd %tdesc {l1_hint = #xegpu.cache_hint<cached>, + l2_hint = #xegpu.cache_hint<cached>, + l3_hint = #xegpu.cache_hint<cached>} + : !xegpu.tensor_desc<8x16xf16> + ``` + + }]; + + let arguments = (ins XeGPU_TensorDesc: $TensorDesc, + OptionalAttr<XeGPU_CacheHintAttr>: $l1_hint, + OptionalAttr<XeGPU_CacheHintAttr>: $l2_hint, + OptionalAttr<XeGPU_CacheHintAttr>: $l3_hint); + + let extraClassDeclaration = extraBaseClassDeclaration; + + let assemblyFormat = "$TensorDesc prop-dict attr-dict `:` qualified(type($TensorDesc))"; +} + + +def XeGPU_LoadNdOp : XeGPU_Op<"load_nd"> { + let summary = "loads a n-D block from memory (represented by TensorDesc)" + "to registers (represented by vector)"; + let description = [{ + LoadNdOp essentially mimics the hardware block read instruction to read + a block of data from memory to register. It takes a set of optional cache + hints for each level of cache, L1, L2 and L3. If hardware does not have a + correspoding cache, Corresponding cache hint attribute will be masked. + vnni transform is an hardware feature for Intel GPU, which is used to + do data packing during the load for B operand of matrix operation, if + the bit width of the data type is less then 32 bits, e.g., fp16. And + transpose is another Intel hardware feature, which will do transpose + operation when loading the data if the bit width of the data type is + fp32 or fp64. It implies that vnni and transpose cannot exit at the + same time. + + Example: + ``` + xegpu.load_nd %1 {transpose = [1, 0], + l1_hint = #xegpu.cache_hint<cached>, + l2_hint = #xegpu.cache_hint<uncached>, + l3_hint = #xegpu.cache_hint<streaming>} + : !xegpu.tensor_desc<8x16xf32> -> vector<16x8xf32> + ``` + + + }]; + + let arguments = (ins XeGPU_TensorDesc: $TensorDesc, + OptionalAttr<I64Attr>: $vnni_axis, + OptionalAttr<DenseI64ArrayAttr>: $transpose, + OptionalAttr<XeGPU_CacheHintAttr>: $l1_hint, + OptionalAttr<XeGPU_CacheHintAttr>: $l2_hint, + OptionalAttr<XeGPU_CacheHintAttr>: $l3_hint); + + let results = (outs XeGPU_ValueType: $value); + + let extraClassDeclaration = extraBaseClassDeclaration # [{ + VectorType getType() { + return llvm::dyn_cast<VectorType>(getValue().getType()); + } + + xegpu::TensorDescType getTensorDescType() { + return getTensorDesc().getType(); + } + }]; + + let assemblyFormat = "$TensorDesc prop-dict attr-dict `:` qualified(type($TensorDesc)) `->` type($value)"; + let hasVerifier = 1; +} + +def XeGPU_StoreNdOp : XeGPU_Op<"store_nd", []> { + let summary = "stores a n-D block register region back to memory, currently only supports 2D"; + + let description = [{ + StoreNdOp essentially mimics the hardware block write instruction io + write a block of data from register into the memory region as described + by the TensorDesc. It takes a set of optional cache hints for each level + of cache, L1, L2 and L3. If hardware does not have a correspoding cache, + Corresponding cache hint attribute will be masked. + + Example: + ``` + xegpu.store_nd %3, %2 {l1_hint = #xegpu.cache_hint<uncached>, + l2_hint = #xegpu.cache_hint<write_back>, + l3_hint = #xegpu.cache_hint<write_through>} + : vector<8x16xf16>, !xegpu.tensor_desc<8x16xf16> + ``` + + + }]; + + let arguments = (ins XeGPU_ValueType: $value, + XeGPU_TensorDesc: $TensorDesc, + OptionalAttr<XeGPU_CacheHintAttr>: $l1_hint, + OptionalAttr<XeGPU_CacheHintAttr>: $l2_hint, + OptionalAttr<XeGPU_CacheHintAttr>: $l3_hint); + + let extraClassDeclaration = extraBaseClassDeclaration; + let assemblyFormat = [{$value `,` $TensorDesc prop-dict attr-dict + `:` type($value) `,` qualified(type($TensorDesc))}]; + let hasVerifier = 1; +} #endif // MLIR_DIALECT_XEGPU_IR_XEGPUOPS_TD diff --git a/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUTypes.td b/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUTypes.td index 1d75bb4e2906fe671fbbefa2cff93394e585e66e..19ac1693712dd83066de2f064c3cb1d492a3faed 100644 --- a/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUTypes.td +++ b/mlir/include/mlir/Dialect/XeGPU/IR/XeGPUTypes.td @@ -9,9 +9,9 @@ #ifndef MLIR_DIALECT_XEGPU_IR_XEGPUTYPES_TD #define MLIR_DIALECT_XEGPU_IR_XEGPUTYPES_TD -include "mlir/IR/BuiltinTypes.td" include "mlir/Dialect/XeGPU/IR/XeGPUAttrs.td" include "mlir/Dialect/XeGPU/IR/XeGPUDialect.td" +include "mlir/IR/BuiltinTypes.td" def XeGPU_IntType: AnyTypeOf<[I1, I8, I16, I32, I64, SI1, SI8, SI16, SI32, SI64, UI1, UI8, UI16, UI32, UI64]>; def XeGPU_FloatType: AnyTypeOf<[F16, F32, F64, BF16, TF32]>; @@ -30,4 +30,106 @@ class XeGPUTypeDef<string name, string typeMnemonic, list<Trait> traits = [], let mnemonic = typeMnemonic; } +def XeGPU_TensorDesc: XeGPUTypeDef<"TensorDesc", "tensor_desc", + [ShapedTypeInterface], "::mlir::TensorType"> { + let summary = "TensorDesc describing regions of interested data."; + let description = [{ + TensorDesc is a type designed to describe regions of the interested data as well as some + features that are unique to Intel hardware. Different with the builtin tensor type in MLIR, + it essentially only contains the meta data, and doesn't hold the data by itself. It is designed + to mainly support 2D block load/store and DPAS (matrix multiplication instruction) on Intel GPU. + It encodes the following information: + + * shape: the sizes/shape of the intereted data block, e.g., 8x16 means 8 rows + and each row contains 16 contiguous data element. The rows could be + either contiguous or not, depends on whether the encoding attribute + is set or not. + * element_type: the data type of the data element, e.g., f16, f32. + + Similar to the builtin tensor, it also provides an optinal attribute to encoding + the following information via the TensorDescAttr object: + * memory_scope (xegpu::MemoryScope): [optional] where the data is located, + global memory or shared memory. It is default to Global. + * array_length (int): [optional] The number of contiguous blocks with size as `shape`, + that will be loaded by block load at a time. It is default to 1. + * boundary_check (bool): [optional] indicates whether the operation detects the boundary + and pads with zero for out-of-boundary access. It is default to do boundary check. + + + Syntax: + + ``` + TensorDesc-type ::= `tensor_desc` `<` dim-list element-type (attr-list)? `>` + element-type ::= float-type | integer-type | index-type + dim-list := (static-dim-list `x`)? + static-dim-list ::= decimal-literal `x` decimal-literal + attr-list = (, memory_scope = value)? (, arr_len = value)? (, boundary_check = value)? + ``` + + Examples: + + ```mlir + // A block TensorDesc with 8x16 i32 elements + xegpu.tensor_desc<8x16xi32> + + // A block TensorDesc with 8x16 f32 elements + xegpu.tensor_desc<8x16xf32> + + // A TensorDesc with 8x16 f32 elements for a memory region in shared memory space. + xegpu.tensor_desc<8x16xf32, #xegpu.tdesc_attr<memory_scope = slm>> + ``` + }]; + + let parameters = (ins ArrayRefParameter<"int64_t">: $shape, + "mlir::Type": $elementType, + OptionalParameter<"mlir::Attribute">: $encoding); + + let extraClassDeclaration = [{ + using TensorType::clone; + using mlir::ShapedType::Trait<TensorDescType>::getElementTypeBitWidth; + using mlir::ShapedType::Trait<TensorDescType>::getRank; + using mlir::ShapedType::Trait<TensorDescType>::getNumElements; + using mlir::ShapedType::Trait<TensorDescType>::isDynamicDim; + using mlir::ShapedType::Trait<TensorDescType>::hasStaticShape; + using mlir::ShapedType::Trait<TensorDescType>::getNumDynamicDims; + using mlir::ShapedType::Trait<TensorDescType>::getDimSize; + using mlir::ShapedType::Trait<TensorDescType>::getDynamicDimIndex; + + TensorDescType clone(::mlir::Type elementType) { + return llvm::cast<TensorDescType>(cloneWith(getShape(), elementType)); + } + + TensorDescAttr getEncodingAsTensorDescAttr() const { + return llvm::dyn_cast_if_present<TensorDescAttr>(getEncoding()); + } + + xegpu::MemoryScope getMemoryScope() const { + auto attr = getEncodingAsTensorDescAttr(); + if (attr && attr.getMemoryScope()) + return attr.getMemoryScope().getValue(); + // return default value + return MemoryScope::Global; + } + + int getArrayLength() { + auto attr = getEncodingAsTensorDescAttr(); + if (attr && attr.getArrayLength()) + return attr.getArrayLength().getInt(); + // return default value + return 1; + } + + bool getBoundaryCheck() { + auto attr = getEncodingAsTensorDescAttr(); + if (attr && attr.getBoundaryCheck()) + return attr.getBoundaryCheck().getValue(); + // return default value + return true; + } + }]; + + let hasCustomAssemblyFormat = true; + +} + #endif // MLIR_DIALECT_XEGPU_IR_XEGPUTYPES_TD diff --git a/mlir/include/mlir/ExecutionEngine/SparseTensor/File.h b/mlir/include/mlir/ExecutionEngine/SparseTensor/File.h index f927b82628b1a62b2b148af865093cae49d75066..714e664dd0f4eb0db0bb0db8e7ee29cd8f0c452b 100644 --- a/mlir/include/mlir/ExecutionEngine/SparseTensor/File.h +++ b/mlir/include/mlir/ExecutionEngine/SparseTensor/File.h @@ -206,7 +206,7 @@ public: auto *lvlCOO = readCOO<V>(map, lvlSizes); auto *tensor = SparseTensorStorage<P, I, V>::newFromCOO( dimRank, getDimSizes(), lvlRank, lvlSizes, lvlTypes, dim2lvl, lvl2dim, - *lvlCOO); + lvlCOO); delete lvlCOO; return tensor; } diff --git a/mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h b/mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h index 468782ebef4e3418ac52866e95b8557711debd15..80e3fec22694fbfdb0064770aa6cbe8c35172ffc 100644 --- a/mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h +++ b/mlir/include/mlir/ExecutionEngine/SparseTensor/Storage.h @@ -143,6 +143,12 @@ public: MLIR_SPARSETENSOR_FOREVERY_FIXED_O(DECL_GETCOORDINATES) #undef DECL_GETCOORDINATES + /// Gets coordinates-overhead storage buffer for the given level. +#define DECL_GETCOORDINATESBUFFER(INAME, C) \ + virtual void getCoordinatesBuffer(std::vector<C> **, uint64_t); + MLIR_SPARSETENSOR_FOREVERY_FIXED_O(DECL_GETCOORDINATESBUFFER) +#undef DECL_GETCOORDINATESBUFFER + /// Gets primary storage. #define DECL_GETVALUES(VNAME, V) virtual void getValues(std::vector<V> **); MLIR_SPARSETENSOR_FOREVERY_V(DECL_GETVALUES) @@ -197,37 +203,22 @@ class SparseTensorStorage final : public SparseTensorStorageBase { const uint64_t *lvl2dim) : SparseTensorStorageBase(dimRank, dimSizes, lvlRank, lvlSizes, lvlTypes, dim2lvl, lvl2dim), - positions(lvlRank), coordinates(lvlRank), lvlCursor(lvlRank), coo() {} + positions(lvlRank), coordinates(lvlRank), lvlCursor(lvlRank) {} public: /// Constructs a sparse tensor with the given encoding, and allocates - /// overhead storage according to some simple heuristics. When the - /// `bool` argument is true and `lvlTypes` are all dense, then this - /// ctor will also initialize the values array with zeros. That - /// argument should be true when an empty tensor is intended; whereas - /// it should usually be false when the ctor will be followed up by - /// some other form of initialization. - SparseTensorStorage(uint64_t dimRank, const uint64_t *dimSizes, - uint64_t lvlRank, const uint64_t *lvlSizes, - const LevelType *lvlTypes, const uint64_t *dim2lvl, - const uint64_t *lvl2dim, SparseTensorCOO<V> *lvlCOO, - bool initializeValuesIfAllDense); - - /// Constructs a sparse tensor with the given encoding, and initializes - /// the contents from the COO. This ctor performs the same heuristic - /// overhead-storage allocation as the ctor above. + /// overhead storage according to some simple heuristics. When lvlCOO + /// is set, the sparse tensor initializes with the contents from that + /// data structure. Otherwise, an empty sparse tensor results. SparseTensorStorage(uint64_t dimRank, const uint64_t *dimSizes, uint64_t lvlRank, const uint64_t *lvlSizes, const LevelType *lvlTypes, const uint64_t *dim2lvl, - const uint64_t *lvl2dim, SparseTensorCOO<V> &lvlCOO); + const uint64_t *lvl2dim, SparseTensorCOO<V> *lvlCOO); /// Constructs a sparse tensor with the given encoding, and initializes - /// the contents from the level buffers. This ctor allocates exactly - /// the required amount of overhead storage, not using any heuristics. - /// It assumes that the data provided by `lvlBufs` can be directly used to - /// interpret the result sparse tensor and performs *NO* integrity test on the - /// input data. It also assume that the trailing COO coordinate buffer is - /// passed in as a single AoS memory. + /// the contents from the level buffers. The constructor assumes that the + /// data provided by `lvlBufs` can be directly used to interpret the result + /// sparse tensor and performs no integrity test on the input data. SparseTensorStorage(uint64_t dimRank, const uint64_t *dimSizes, uint64_t lvlRank, const uint64_t *lvlSizes, const LevelType *lvlTypes, const uint64_t *dim2lvl, @@ -244,16 +235,14 @@ public: newFromCOO(uint64_t dimRank, const uint64_t *dimSizes, uint64_t lvlRank, const uint64_t *lvlSizes, const LevelType *lvlTypes, const uint64_t *dim2lvl, const uint64_t *lvl2dim, - SparseTensorCOO<V> &lvlCOO); + SparseTensorCOO<V> *lvlCOO); - /// Allocates a new sparse tensor and initialize it with the data stored level - /// buffers directly. + /// Allocates a new sparse tensor and initialize it from the given buffers. static SparseTensorStorage<P, C, V> * - packFromLvlBuffers(uint64_t dimRank, const uint64_t *dimSizes, - uint64_t lvlRank, const uint64_t *lvlSizes, - const LevelType *lvlTypes, const uint64_t *dim2lvl, - const uint64_t *lvl2dim, uint64_t srcRank, - const intptr_t *buffers); + newFromBuffers(uint64_t dimRank, const uint64_t *dimSizes, uint64_t lvlRank, + const uint64_t *lvlSizes, const LevelType *lvlTypes, + const uint64_t *dim2lvl, const uint64_t *lvl2dim, + uint64_t srcRank, const intptr_t *buffers); ~SparseTensorStorage() final = default; @@ -268,6 +257,31 @@ public: assert(lvl < getLvlRank()); *out = &coordinates[lvl]; } + void getCoordinatesBuffer(std::vector<C> **out, uint64_t lvl) final { + assert(out && "Received nullptr for out parameter"); + assert(lvl < getLvlRank()); + // Note that the sparse tensor support library always stores COO in SoA + // format, even when AoS is requested. This is never an issue, since all + // actual code/library generation requests "views" into the coordinate + // storage for the individual levels, which is trivially provided for + // both AoS and SoA (as well as all the other storage formats). The only + // exception is when the buffer version of coordinate storage is requested + // (currently only for printing). In that case, we do the following + // potentially expensive transformation to provide that view. If this + // operation becomes more common beyond debugging, we should consider + // implementing proper AoS in the support library as well. + uint64_t lvlRank = getLvlRank(); + uint64_t nnz = values.size(); + crdBuffer.clear(); + crdBuffer.reserve(nnz * (lvlRank - lvl)); + for (uint64_t i = 0; i < nnz; i++) { + for (uint64_t l = lvl; l < lvlRank; l++) { + assert(i < coordinates[l].size()); + crdBuffer.push_back(coordinates[l][i]); + } + } + *out = &crdBuffer; + } void getValues(std::vector<V> **out) final { assert(out && "Received nullptr for out parameter"); *out = &values; @@ -337,16 +351,6 @@ public: } } - /// Allocates a new COO object and initializes it with the contents. - /// Callers must make sure to delete the COO when they're done with it. - SparseTensorCOO<V> *toCOO() { - std::vector<uint64_t> dimCoords(getDimRank()); - coo = new SparseTensorCOO<V>(getDimSizes(), values.size()); - toCOO(0, 0, dimCoords); - assert(coo->getElements().size() == values.size()); - return coo; - } - /// Sort the unordered tensor in place, the method assumes that it is /// an unordered COO tensor. void sortInPlace() { @@ -556,58 +560,14 @@ private: return -1u; } - // Performs forall on level entries and inserts into dim COO. - void toCOO(uint64_t parentPos, uint64_t l, std::vector<uint64_t> &dimCoords) { - if (l == getLvlRank()) { - map.pushbackward(lvlCursor.data(), dimCoords.data()); - assert(coo); - assert(parentPos < values.size()); - coo->add(dimCoords, values[parentPos]); - return; - } - if (isCompressedLvl(l)) { - const std::vector<P> &positionsL = positions[l]; - assert(parentPos + 1 < positionsL.size()); - const uint64_t pstart = static_cast<uint64_t>(positionsL[parentPos]); - const uint64_t pstop = static_cast<uint64_t>(positionsL[parentPos + 1]); - const std::vector<C> &coordinatesL = coordinates[l]; - assert(pstop <= coordinatesL.size()); - for (uint64_t pos = pstart; pos < pstop; pos++) { - lvlCursor[l] = static_cast<uint64_t>(coordinatesL[pos]); - toCOO(pos, l + 1, dimCoords); - } - } else if (isLooseCompressedLvl(l)) { - const std::vector<P> &positionsL = positions[l]; - assert(2 * parentPos + 1 < positionsL.size()); - const uint64_t pstart = static_cast<uint64_t>(positionsL[2 * parentPos]); - const uint64_t pstop = - static_cast<uint64_t>(positionsL[2 * parentPos + 1]); - const std::vector<C> &coordinatesL = coordinates[l]; - assert(pstop <= coordinatesL.size()); - for (uint64_t pos = pstart; pos < pstop; pos++) { - lvlCursor[l] = static_cast<uint64_t>(coordinatesL[pos]); - toCOO(pos, l + 1, dimCoords); - } - } else if (isSingletonLvl(l) || isNOutOfMLvl(l)) { - assert(parentPos < coordinates[l].size()); - lvlCursor[l] = static_cast<uint64_t>(coordinates[l][parentPos]); - toCOO(parentPos, l + 1, dimCoords); - } else { // Dense level. - assert(isDenseLvl(l)); - const uint64_t sz = getLvlSizes()[l]; - const uint64_t pstart = parentPos * sz; - for (uint64_t c = 0; c < sz; c++) { - lvlCursor[l] = c; - toCOO(pstart + c, l + 1, dimCoords); - } - } - } - + // Sparse tensor storage components. std::vector<std::vector<P>> positions; std::vector<std::vector<C>> coordinates; std::vector<V> values; + + // Auxiliary data structures. std::vector<uint64_t> lvlCursor; - SparseTensorCOO<V> *coo; + std::vector<C> crdBuffer; // just for AoS view }; //===----------------------------------------------------------------------===// @@ -621,9 +581,9 @@ SparseTensorStorage<P, C, V> *SparseTensorStorage<P, C, V>::newEmpty( uint64_t dimRank, const uint64_t *dimSizes, uint64_t lvlRank, const uint64_t *lvlSizes, const LevelType *lvlTypes, const uint64_t *dim2lvl, const uint64_t *lvl2dim) { + SparseTensorCOO<V> *noLvlCOO = nullptr; return new SparseTensorStorage<P, C, V>(dimRank, dimSizes, lvlRank, lvlSizes, - lvlTypes, dim2lvl, lvl2dim, nullptr, - true); + lvlTypes, dim2lvl, lvl2dim, noLvlCOO); } template <typename P, typename C, typename V> @@ -631,13 +591,14 @@ SparseTensorStorage<P, C, V> *SparseTensorStorage<P, C, V>::newFromCOO( uint64_t dimRank, const uint64_t *dimSizes, uint64_t lvlRank, const uint64_t *lvlSizes, const LevelType *lvlTypes, const uint64_t *dim2lvl, const uint64_t *lvl2dim, - SparseTensorCOO<V> &lvlCOO) { + SparseTensorCOO<V> *lvlCOO) { + assert(lvlCOO); return new SparseTensorStorage<P, C, V>(dimRank, dimSizes, lvlRank, lvlSizes, lvlTypes, dim2lvl, lvl2dim, lvlCOO); } template <typename P, typename C, typename V> -SparseTensorStorage<P, C, V> *SparseTensorStorage<P, C, V>::packFromLvlBuffers( +SparseTensorStorage<P, C, V> *SparseTensorStorage<P, C, V>::newFromBuffers( uint64_t dimRank, const uint64_t *dimSizes, uint64_t lvlRank, const uint64_t *lvlSizes, const LevelType *lvlTypes, const uint64_t *dim2lvl, const uint64_t *lvl2dim, uint64_t srcRank, @@ -657,11 +618,9 @@ SparseTensorStorage<P, C, V>::SparseTensorStorage( uint64_t dimRank, const uint64_t *dimSizes, uint64_t lvlRank, const uint64_t *lvlSizes, const LevelType *lvlTypes, const uint64_t *dim2lvl, const uint64_t *lvl2dim, - SparseTensorCOO<V> *lvlCOO, bool initializeValuesIfAllDense) + SparseTensorCOO<V> *lvlCOO) : SparseTensorStorage(dimRank, dimSizes, lvlRank, lvlSizes, lvlTypes, dim2lvl, lvl2dim) { - assert(!lvlCOO || lvlRank == lvlCOO->getRank()); - coo = lvlCOO; // Provide hints on capacity of positions and coordinates. // TODO: needs much fine-tuning based on actual sparsity; currently // we reserve position/coordinate space based on all previous dense @@ -692,27 +651,20 @@ SparseTensorStorage<P, C, V>::SparseTensorStorage( sz = detail::checkedMul(sz, lvlSizes[l]); } } - if (allDense && initializeValuesIfAllDense) + if (lvlCOO) { + /* New from COO: ensure it is sorted. */ + assert(lvlCOO->getRank() == lvlRank); + lvlCOO->sort(); + // Now actually insert the `elements`. + const auto &elements = lvlCOO->getElements(); + const uint64_t nse = elements.size(); + assert(values.size() == 0); + values.reserve(nse); + fromCOO(elements, 0, nse, 0); + } else if (allDense) { + /* New empty (all dense) */ values.resize(sz, 0); -} - -template <typename P, typename C, typename V> -SparseTensorStorage<P, C, V>::SparseTensorStorage( // NOLINT - uint64_t dimRank, const uint64_t *dimSizes, uint64_t lvlRank, - const uint64_t *lvlSizes, const LevelType *lvlTypes, - const uint64_t *dim2lvl, const uint64_t *lvl2dim, - SparseTensorCOO<V> &lvlCOO) - : SparseTensorStorage(dimRank, dimSizes, lvlRank, lvlSizes, lvlTypes, - dim2lvl, lvl2dim, nullptr, false) { - // Ensure lvlCOO is sorted. - assert(lvlRank == lvlCOO.getRank()); - lvlCOO.sort(); - // Now actually insert the `elements`. - const auto &elements = lvlCOO.getElements(); - const uint64_t nse = elements.size(); - assert(values.size() == 0); - values.reserve(nse); - fromCOO(elements, 0, nse, 0); + } } template <typename P, typename C, typename V> diff --git a/mlir/include/mlir/ExecutionEngine/SparseTensorRuntime.h b/mlir/include/mlir/ExecutionEngine/SparseTensorRuntime.h index d916186c835c2ea2e872f5d7db8725737b10a900..396f76fd8f921afa1b1cb0fcb600a67c11241315 100644 --- a/mlir/include/mlir/ExecutionEngine/SparseTensorRuntime.h +++ b/mlir/include/mlir/ExecutionEngine/SparseTensorRuntime.h @@ -77,6 +77,14 @@ MLIR_SPARSETENSOR_FOREVERY_O(DECL_SPARSEPOSITIONS) MLIR_SPARSETENSOR_FOREVERY_O(DECL_SPARSECOORDINATES) #undef DECL_SPARSECOORDINATES +/// Tensor-storage method to obtain direct access to the coordinates array +/// buffer for the given level (provides an AoS view into the library). +#define DECL_SPARSECOORDINATES(CNAME, C) \ + MLIR_CRUNNERUTILS_EXPORT void _mlir_ciface_sparseCoordinatesBuffer##CNAME( \ + StridedMemRefType<C, 1> *out, void *tensor, index_type lvl); +MLIR_SPARSETENSOR_FOREVERY_O(DECL_SPARSECOORDINATES) +#undef DECL_SPARSECOORDINATES + /// Tensor-storage method to insert elements in lexicographical /// level-coordinate order. #define DECL_LEXINSERT(VNAME, V) \ diff --git a/mlir/include/mlir/IR/Builders.h b/mlir/include/mlir/IR/Builders.h index 43b6d2b38416904ec64d027b08d4614070a2ad01..3beade017d1ab9f17ae861d481586c216ed176ca 100644 --- a/mlir/include/mlir/IR/Builders.h +++ b/mlir/include/mlir/IR/Builders.h @@ -490,7 +490,7 @@ private: template <typename OpT> RegisteredOperationName getCheckRegisteredInfo(MLIRContext *ctx) { std::optional<RegisteredOperationName> opName = - RegisteredOperationName::lookup(OpT::getOperationName(), ctx); + RegisteredOperationName::lookup(TypeID::get<OpT>(), ctx); if (LLVM_UNLIKELY(!opName)) { llvm::report_fatal_error( "Building op `" + OpT::getOperationName() + diff --git a/mlir/include/mlir/IR/Dialect.h b/mlir/include/mlir/IR/Dialect.h index 6c8a170a03c72d38a9e08e47d4dcf819aa1ae0a8..f7c1f4df16fc48e014d9a281b111a7a1c1b26530 100644 --- a/mlir/include/mlir/IR/Dialect.h +++ b/mlir/include/mlir/IR/Dialect.h @@ -210,7 +210,7 @@ public: /// registration. The promised interface type can be an interface of any type /// not just a dialect interface, i.e. it may also be an /// AttributeInterface/OpInterface/TypeInterface/etc. - template <typename ConcreteT, typename InterfaceT> + template <typename InterfaceT, typename ConcreteT> void declarePromisedInterface() { unresolvedPromisedInterfaces.insert( {TypeID::get<ConcreteT>(), InterfaceT::getInterfaceID()}); @@ -221,7 +221,7 @@ public: // declarePromisedInterfaces<FunctionOpInterface, MyFuncType1, MyFuncType2>() template <typename InterfaceT, typename... ConcreteT> void declarePromisedInterfaces() { - (declarePromisedInterface<ConcreteT, InterfaceT>(), ...); + (declarePromisedInterface<InterfaceT, ConcreteT>(), ...); } /// Checks if the given interface, which is attempting to be used, is a diff --git a/mlir/include/mlir/IR/OpDefinition.h b/mlir/include/mlir/IR/OpDefinition.h index bd68c27445744e36045d388263dc18e0cb5eb9f3..c177ae3594d11f9b738801dbf371a904439708c7 100644 --- a/mlir/include/mlir/IR/OpDefinition.h +++ b/mlir/include/mlir/IR/OpDefinition.h @@ -1729,8 +1729,7 @@ public: template <typename... Models> static void attachInterface(MLIRContext &context) { std::optional<RegisteredOperationName> info = - RegisteredOperationName::lookup(ConcreteType::getOperationName(), - &context); + RegisteredOperationName::lookup(TypeID::get<ConcreteType>(), &context); if (!info) llvm::report_fatal_error( "Attempting to attach an interface to an unregistered operation " + diff --git a/mlir/include/mlir/IR/OperationSupport.h b/mlir/include/mlir/IR/OperationSupport.h index f2aa6cee840308e77c0901293d11823f1d426eb1..90e63ff8fcb38f09cbd9426038b5670abbf48e60 100644 --- a/mlir/include/mlir/IR/OperationSupport.h +++ b/mlir/include/mlir/IR/OperationSupport.h @@ -676,6 +676,11 @@ public: static std::optional<RegisteredOperationName> lookup(StringRef name, MLIRContext *ctx); + /// Lookup the registered operation information for the given operation. + /// Returns std::nullopt if the operation isn't registered. + static std::optional<RegisteredOperationName> lookup(TypeID typeID, + MLIRContext *ctx); + /// Register a new operation in a Dialect object. /// This constructor is used by Dialect objects when they register the list /// of operations they contain. diff --git a/mlir/include/mlir/IR/OwningOpRef.h b/mlir/include/mlir/IR/OwningOpRef.h index eb4bf2dc67e3e7e583054fd0ee2f9d334f6d7bd8..0c35eae8de096412e448bf94d7bf814b0eb5c891 100644 --- a/mlir/include/mlir/IR/OwningOpRef.h +++ b/mlir/include/mlir/IR/OwningOpRef.h @@ -13,6 +13,7 @@ #ifndef MLIR_IR_OWNINGOPREF_H #define MLIR_IR_OWNINGOPREF_H +#include <type_traits> #include <utility> namespace mlir { diff --git a/mlir/include/mlir/IR/PatternMatch.h b/mlir/include/mlir/IR/PatternMatch.h index ef53a0b82866fcd86bc683173529a73b8be33e44..15b1c38929485e5be6e8e09209c2ef9452579840 100644 --- a/mlir/include/mlir/IR/PatternMatch.h +++ b/mlir/include/mlir/IR/PatternMatch.h @@ -409,9 +409,9 @@ public: /// Notify the listener that the specified operation was modified in-place. virtual void notifyOperationModified(Operation *op) {} - /// Notify the listener that the specified operation is about to be replaced - /// with another operation. This is called before the uses of the old - /// operation have been changed. + /// Notify the listener that all uses of the specified operation's results + /// are about to be replaced with the results of another operation. This is + /// called before the uses of the old operation have been changed. /// /// By default, this function calls the "operation replaced with values" /// notification. @@ -420,9 +420,10 @@ public: notifyOperationReplaced(op, replacement->getResults()); } - /// Notify the listener that the specified operation is about to be replaced - /// with the a range of values, potentially produced by other operations. - /// This is called before the uses of the operation have been changed. + /// Notify the listener that all uses of the specified operation's results + /// are about to be replaced with the a range of values, potentially + /// produced by other operations. This is called before the uses of the + /// operation have been changed. virtual void notifyOperationReplaced(Operation *op, ValueRange replacement) {} @@ -634,11 +635,13 @@ public: /// Find uses of `from` and replace them with `to`. Also notify the listener /// about every in-place op modification (for every use that was replaced). void replaceAllUsesWith(Value from, Value to) { - return replaceAllUsesWith(from.getImpl(), to); + for (OpOperand &operand : llvm::make_early_inc_range(from.getUses())) { + Operation *op = operand.getOwner(); + modifyOpInPlace(op, [&]() { operand.set(to); }); + } } - template <typename OperandType, typename ValueT> - void replaceAllUsesWith(IRObjectWithUseList<OperandType> *from, ValueT &&to) { - for (OperandType &operand : llvm::make_early_inc_range(from->getUses())) { + void replaceAllUsesWith(Block *from, Block *to) { + for (BlockOperand &operand : llvm::make_early_inc_range(from->getUses())) { Operation *op = operand.getOwner(); modifyOpInPlace(op, [&]() { operand.set(to); }); } @@ -648,12 +651,16 @@ public: for (auto it : llvm::zip(from, to)) replaceAllUsesWith(std::get<0>(it), std::get<1>(it)); } - // Note: This function cannot be called `replaceAllUsesWith` because the - // overload resolution, when called with an op that can be implicitly - // converted to a Value, would be ambiguous. - void replaceAllOpUsesWith(Operation *from, ValueRange to) { - replaceAllUsesWith(from->getResults(), to); - } + + /// Find uses of `from` and replace them with `to`. Also notify the listener + /// about every in-place op modification (for every use that was replaced) + /// and that the `from` operation is about to be replaced. + /// + /// Note: This function cannot be called `replaceAllUsesWith` because the + /// overload resolution, when called with an op that can be implicitly + /// converted to a Value, would be ambiguous. + void replaceAllOpUsesWith(Operation *from, ValueRange to); + void replaceAllOpUsesWith(Operation *from, Operation *to); /// Find uses of `from` and replace them with `to` if the `functor` returns /// true. Also notify the listener about every in-place op modification (for @@ -736,6 +743,8 @@ protected: : OpBuilder(ctx, listener) {} explicit RewriterBase(const OpBuilder &otherBuilder) : OpBuilder(otherBuilder) {} + explicit RewriterBase(Operation *op, OpBuilder::Listener *listener = nullptr) + : OpBuilder(op, listener) {} virtual ~RewriterBase(); private: @@ -756,6 +765,8 @@ public: explicit IRRewriter(MLIRContext *ctx, OpBuilder::Listener *listener = nullptr) : RewriterBase(ctx, listener) {} explicit IRRewriter(const OpBuilder &builder) : RewriterBase(builder) {} + explicit IRRewriter(Operation *op, OpBuilder::Listener *listener = nullptr) + : RewriterBase(op, listener) {} }; //===----------------------------------------------------------------------===// diff --git a/mlir/include/mlir/IR/TensorEncoding.td b/mlir/include/mlir/IR/TensorEncoding.td index 3991520d72a5fe474b4ff0b03eb9774a0238f5e1..4907dcbb5de9648799cd3d4efad13b854717be91 100644 --- a/mlir/include/mlir/IR/TensorEncoding.td +++ b/mlir/include/mlir/IR/TensorEncoding.td @@ -34,8 +34,8 @@ def VerifiableTensorEncoding : AttrInterface<"VerifiableTensorEncoding"> { /*retTy=*/"::mlir::LogicalResult", /*methodName=*/"verifyEncoding", /*args=*/(ins - "ArrayRef<int64_t>":$shape, - "Type":$elementType, + "::mlir::ArrayRef<int64_t>":$shape, + "::mlir::Type":$elementType, "::llvm::function_ref<::mlir::InFlightDiagnostic()>":$emitError) >, ]; diff --git a/mlir/include/mlir/InitAllDialects.h b/mlir/include/mlir/InitAllDialects.h index 21775e11e07149b47a5da7689b06bee07de95616..c558dc53cc7face3159e62c2f35a44ca7a29f6b5 100644 --- a/mlir/include/mlir/InitAllDialects.h +++ b/mlir/include/mlir/InitAllDialects.h @@ -21,6 +21,7 @@ #include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/Arith/IR/ValueBoundsOpInterfaceImpl.h" #include "mlir/Dialect/Arith/Transforms/BufferDeallocationOpInterfaceImpl.h" +#include "mlir/Dialect/Arith/Transforms/BufferViewFlowOpInterfaceImpl.h" #include "mlir/Dialect/Arith/Transforms/BufferizableOpInterfaceImpl.h" #include "mlir/Dialect/ArmNeon/ArmNeonDialect.h" #include "mlir/Dialect/ArmSME/IR/ArmSME.h" @@ -52,6 +53,7 @@ #include "mlir/Dialect/MemRef/IR/MemRefMemorySlot.h" #include "mlir/Dialect/MemRef/IR/ValueBoundsOpInterfaceImpl.h" #include "mlir/Dialect/MemRef/Transforms/AllocationOpInterfaceImpl.h" +#include "mlir/Dialect/MemRef/Transforms/BufferViewFlowOpInterfaceImpl.h" #include "mlir/Dialect/MemRef/Transforms/RuntimeOpVerification.h" #include "mlir/Dialect/Mesh/IR/MeshDialect.h" #include "mlir/Dialect/NVGPU/IR/NVGPUDialect.h" @@ -82,6 +84,7 @@ #include "mlir/Dialect/Transform/IR/TransformDialect.h" #include "mlir/Dialect/Transform/PDLExtension/PDLExtension.h" #include "mlir/Dialect/UB/IR/UBOps.h" +#include "mlir/Dialect/Vector/IR/ValueBoundsOpInterfaceImpl.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" #include "mlir/Dialect/Vector/Transforms/BufferizableOpInterfaceImpl.h" #include "mlir/Dialect/Vector/Transforms/SubsetOpInterfaceImpl.h" @@ -147,6 +150,7 @@ inline void registerAllDialects(DialectRegistry ®istry) { affine::registerValueBoundsOpInterfaceExternalModels(registry); arith::registerBufferDeallocationOpInterfaceExternalModels(registry); arith::registerBufferizableOpInterfaceExternalModels(registry); + arith::registerBufferViewFlowOpInterfaceExternalModels(registry); arith::registerValueBoundsOpInterfaceExternalModels(registry); bufferization::func_ext::registerBufferizableOpInterfaceExternalModels( registry); @@ -156,6 +160,7 @@ inline void registerAllDialects(DialectRegistry ®istry) { gpu::registerBufferDeallocationOpInterfaceExternalModels(registry); linalg::registerAllDialectInterfaceImplementations(registry); memref::registerAllocationOpInterfaceExternalModels(registry); + memref::registerBufferViewFlowOpInterfaceExternalModels(registry); memref::registerRuntimeVerifiableOpInterfaceExternalModels(registry); memref::registerValueBoundsOpInterfaceExternalModels(registry); memref::registerMemorySlotExternalModels(registry); @@ -174,6 +179,7 @@ inline void registerAllDialects(DialectRegistry ®istry) { tosa::registerShardingInterfaceExternalModels(registry); vector::registerBufferizableOpInterfaceExternalModels(registry); vector::registerSubsetOpInterfaceExternalModels(registry); + vector::registerValueBoundsOpInterfaceExternalModels(registry); NVVM::registerNVVMTargetInterfaceExternalModels(registry); ROCDL::registerROCDLTargetInterfaceExternalModels(registry); spirv::registerSPIRVTargetInterfaceExternalModels(registry); diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h index 4a21f76dfc5d1c930a537db728710ef82cffc4ea..046354677e6a00b8102d3cd29c3ccfd10618b044 100644 --- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h +++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.h @@ -57,6 +57,13 @@ uint64_t getDefaultPreferredAlignment(Type type, const DataLayout &dataLayout, ArrayRef<DataLayoutEntryInterface> params); +/// Default handler for the index bitwidth request. Computes the result for +/// the built-in index type and dispatches to the DataLayoutTypeInterface for +/// other types. +std::optional<uint64_t> +getDefaultIndexBitwidth(Type type, const DataLayout &dataLayout, + ArrayRef<DataLayoutEntryInterface> params); + /// Default handler for alloca memory space request. Dispatches to the /// DataLayoutInterface if specified, otherwise returns the default. Attribute getDefaultAllocaMemorySpace(DataLayoutEntryInterface entry); @@ -180,6 +187,11 @@ public: /// Returns the preferred of the given type in the current scope. uint64_t getTypePreferredAlignment(Type t) const; + /// Returns the bitwidth that should be used when performing index + /// computations for the given pointer-like type in the current scope. If the + /// type is not a pointer-like type, it returns std::nullopt. + std::optional<uint64_t> getTypeIndexBitwidth(Type t) const; + /// Returns the memory space used for AllocaOps. Attribute getAllocaMemorySpace() const; @@ -216,6 +228,7 @@ private: mutable DenseMap<Type, llvm::TypeSize> bitsizes; mutable DenseMap<Type, uint64_t> abiAlignments; mutable DenseMap<Type, uint64_t> preferredAlignments; + mutable DenseMap<Type, std::optional<uint64_t>> indexBitwidths; /// Cache for alloca, global, and program memory spaces. mutable std::optional<Attribute> allocaMemorySpace; diff --git a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td index a8def967fffcfabbc6223e90cb198149f9514eee..0ee7a116d1142160b414a2011070841a2499e7d8 100644 --- a/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td +++ b/mlir/include/mlir/Interfaces/DataLayoutInterfaces.td @@ -280,6 +280,22 @@ def DataLayoutOpInterface : OpInterface<"DataLayoutOpInterface"> { params); }] >, + StaticInterfaceMethod< + /*description=*/"Returns the bitwidth that should be used when " + "performing index computations for the type computed " + "using the relevant entries. The data layout object can " + "be used for recursive queries.", + /*retTy=*/"std::optional<uint64_t>", + /*methodName=*/"getIndexBitwidth", + /*args=*/(ins "::mlir::Type":$type, + "const ::mlir::DataLayout &":$dataLayout, + "::mlir::DataLayoutEntryListRef":$params), + /*methodBody=*/"", + /*defaultImplementation=*/[{ + return ::mlir::detail::getDefaultIndexBitwidth(type, dataLayout, + params); + }] + >, StaticInterfaceMethod< /*description=*/"Returns the memory space used by the ABI computed " "using the relevant entries. The data layout object " @@ -400,6 +416,18 @@ def DataLayoutTypeInterface : TypeInterface<"DataLayoutTypeInterface"> { /*args=*/(ins "const ::mlir::DataLayout &":$dataLayout, "::mlir::DataLayoutEntryListRef":$params) >, + InterfaceMethod< + /*description=*/"Returns the bitwidth that should be used when " + "performing index computations for the given " + "pointer-like type. If the type is not a pointer-like " + "type, returns std::nullopt.", + /*retTy=*/"std::optional<uint64_t>", + /*methodName=*/"getIndexBitwidth", + /*args=*/(ins "const ::mlir::DataLayout &":$dataLayout, + "::mlir::DataLayoutEntryListRef":$params), + /*methodBody=*/"", + /*defaultImplementation=*/[{ return std::nullopt; }] + >, InterfaceMethod< /*desc=*/"Returns true if the two lists of entries are compatible, that " "is, that `newLayout` spec entries can be nested in an op with " diff --git a/mlir/include/mlir/Interfaces/MemorySlotInterfaces.h b/mlir/include/mlir/Interfaces/MemorySlotInterfaces.h index 56e5e96aecd13cc80e96a764b1effbae87fed355..aaa261be6553f33824303382bb08f1e89d72d7b1 100644 --- a/mlir/include/mlir/Interfaces/MemorySlotInterfaces.h +++ b/mlir/include/mlir/Interfaces/MemorySlotInterfaces.h @@ -26,8 +26,7 @@ struct MemorySlot { /// Memory slot attached with information about its destructuring procedure. struct DestructurableMemorySlot : public MemorySlot { - /// Maps an index within the memory slot to the type of the pointer that - /// will be generated to access the element directly. + /// Maps an index within the memory slot to the corresponding subelement type. DenseMap<Attribute, Type> elementPtrs; }; diff --git a/mlir/include/mlir/Interfaces/MemorySlotInterfaces.td b/mlir/include/mlir/Interfaces/MemorySlotInterfaces.td index 9ffa709cc5bfd49c2493d2ad2f737183bcfd00b4..e10e2d4e104c3ea330e5c5bc4e83b2116609f678 100644 --- a/mlir/include/mlir/Interfaces/MemorySlotInterfaces.td +++ b/mlir/include/mlir/Interfaces/MemorySlotInterfaces.td @@ -83,11 +83,10 @@ def PromotableAllocationOpInterface def PromotableMemOpInterface : OpInterface<"PromotableMemOpInterface"> { let description = [{ Describes an operation that can load from memory slots and/or store - to memory slots. Loads and stores must be of whole values of the same - type as the slot itself. + to memory slots. - For a memory operation on a slot to be valid, it must operate on the slot - pointer *only as a pointer to an element of the type of the slot*. + For a memory operation on a slot to be valid, it must strictly operate + within the bounds of the slot. If the same operation does both loads and stores on the same slot, the load must semantically happen first. @@ -142,7 +141,8 @@ def PromotableMemOpInterface : OpInterface<"PromotableMemOpInterface"> { }], "bool", "canUsesBeRemoved", (ins "const ::mlir::MemorySlot &":$slot, "const ::llvm::SmallPtrSetImpl<::mlir::OpOperand *> &":$blockingUses, - "::llvm::SmallVectorImpl<::mlir::OpOperand *> &":$newBlockingUses) + "::llvm::SmallVectorImpl<::mlir::OpOperand *> &":$newBlockingUses, + "const ::mlir::DataLayout &":$datalayout) >, InterfaceMethod<[{ Transforms IR to ensure that the current operation does not use the @@ -197,7 +197,8 @@ def PromotableOpInterface : OpInterface<"PromotableOpInterface"> { No IR mutation is allowed in this method. }], "bool", "canUsesBeRemoved", (ins "const ::llvm::SmallPtrSetImpl<::mlir::OpOperand *> &":$blockingUses, - "::llvm::SmallVectorImpl<::mlir::OpOperand *> &":$newBlockingUses) + "::llvm::SmallVectorImpl<::mlir::OpOperand *> &":$newBlockingUses, + "const ::mlir::DataLayout &":$datalayout) >, InterfaceMethod<[{ Transforms IR to ensure that the current operation does not use the @@ -285,29 +286,28 @@ def DestructurableAllocationOpInterface def SafeMemorySlotAccessOpInterface : OpInterface<"SafeMemorySlotAccessOpInterface"> { let description = [{ - Describes operations using memory slots in a type-safe manner. + Describes operations using memory slots in a safe manner. }]; let cppNamespace = "::mlir"; let methods = [ InterfaceMethod<[{ Returns whether all accesses in this operation to the provided slot are - done in a type-safe manner. To be type-safe, the access must only load - the value in this type as the type of the slot, and without assuming any - context around the slot. For example, a type-safe load must not load - outside the bounds of the slot. + done in a safe manner. To be safe, the access most only access the slot + inside the bounds that its type implies. - If the type-safety of the accesses depends on the type-safety of the - accesses to further memory slots, the result of this method will be - conditioned to the type-safety of the accesses to the slots added by - this method to `mustBeSafelyUsed`. + If the safety of the accesses depends on the safety of the accesses to + further memory slots, the result of this method will be conditioned to + the safety of the accesses to the slots added by this method to + `mustBeSafelyUsed`. No IR mutation is allowed in this method. }], "::mlir::LogicalResult", "ensureOnlySafeAccesses", (ins "const ::mlir::MemorySlot &":$slot, - "::mlir::SmallVectorImpl<::mlir::MemorySlot> &":$mustBeSafelyUsed) + "::mlir::SmallVectorImpl<::mlir::MemorySlot> &":$mustBeSafelyUsed, + "const ::mlir::DataLayout &":$dataLayout) > ]; } @@ -323,13 +323,12 @@ def DestructurableAccessorOpInterface InterfaceMethod<[{ For a given destructurable memory slot, returns whether this operation can rewire its uses of the slot to use the slots generated after - destructuring. This may involve creating new operations, and usually - amounts to checking if the pointer types match. + destructuring. This may involve creating new operations. This method must also register the indices it will access within the `usedIndices` set. If the accessor generates new slots mapping to subelements, they must be registered in `mustBeSafelyUsed` to ensure - they are used in a locally type-safe manner. + they are used in a safe manner. No IR mutation is allowed in this method. }], @@ -337,7 +336,8 @@ def DestructurableAccessorOpInterface "canRewire", (ins "const ::mlir::DestructurableMemorySlot &":$slot, "::llvm::SmallPtrSetImpl<::mlir::Attribute> &":$usedIndices, - "::mlir::SmallVectorImpl<::mlir::MemorySlot> &":$mustBeSafelyUsed) + "::mlir::SmallVectorImpl<::mlir::MemorySlot> &":$mustBeSafelyUsed, + "const ::mlir::DataLayout &":$dataLayout) >, InterfaceMethod<[{ Rewires the use of a slot to the generated subslots, without deleting @@ -351,7 +351,8 @@ def DestructurableAccessorOpInterface "rewire", (ins "const ::mlir::DestructurableMemorySlot &":$slot, "::llvm::DenseMap<::mlir::Attribute, ::mlir::MemorySlot> &":$subslots, - "::mlir::RewriterBase &":$rewriter) + "::mlir::RewriterBase &":$rewriter, + "const ::mlir::DataLayout &":$dataLayout) > ]; } diff --git a/mlir/include/mlir/Interfaces/ValueBoundsOpInterface.h b/mlir/include/mlir/Interfaces/ValueBoundsOpInterface.h index 28dadfb9ecf86885c6400073c4f0c984400376e6..bdfd689c7ac4f3b43f6e6cd152096aa7ec61d549 100644 --- a/mlir/include/mlir/Interfaces/ValueBoundsOpInterface.h +++ b/mlir/include/mlir/Interfaces/ValueBoundsOpInterface.h @@ -15,6 +15,7 @@ #include "mlir/IR/Value.h" #include "mlir/Interfaces/DestinationStyleOpInterface.h" #include "llvm/ADT/SetVector.h" +#include "llvm/Support/ExtensibleRTTI.h" #include <queue> @@ -63,7 +64,8 @@ using ValueDimList = SmallVector<std::pair<Value, std::optional<int64_t>>>; /// /// Note: Any modification of existing IR invalides the data stored in this /// class. Adding new operations is allowed. -class ValueBoundsConstraintSet { +class ValueBoundsConstraintSet + : public llvm::RTTIExtends<ValueBoundsConstraintSet, llvm::RTTIRoot> { protected: /// Helper class that builds a bound for a shaped value dimension or /// index-typed value. @@ -107,6 +109,8 @@ protected: }; public: + static char ID; + /// The stop condition when traversing the backward slice of a shaped value/ /// index-type value. The traversal continues until the stop condition /// evaluates to "true" for a value. @@ -255,6 +259,10 @@ public: /// Return an expression that represents a constant. AffineExpr getExpr(int64_t constant); + /// Debugging only: Dump the constraint set and the column-to-value/dim + /// mapping to llvm::errs. + void dump() const; + protected: /// Dimension identifier to indicate a value is index-typed. This is used for /// internal data structures/API only. @@ -265,6 +273,16 @@ protected: ValueBoundsConstraintSet(MLIRContext *ctx); + /// Populates the constraint set for a value/map without actually computing + /// the bound. Returns the position for the value/map (via the return value + /// and `posOut` output parameter). + int64_t populateConstraintsSet(Value value, + std::optional<int64_t> dim = std::nullopt, + StopConditionFn stopCondition = nullptr); + int64_t populateConstraintsSet(AffineMap map, ValueDimList mapOperands, + StopConditionFn stopCondition = nullptr, + int64_t *posOut = nullptr); + /// Iteratively process all elements on the worklist until an index-typed /// value or shaped value meets `stopCondition`. Such values are not processed /// any further. diff --git a/mlir/include/mlir/Pass/Pass.h b/mlir/include/mlir/Pass/Pass.h index 070e0cad38787ca91543e35eff43144ce6b6c029..0f50f3064f17802670bc13539aa7a1939d3fd430 100644 --- a/mlir/include/mlir/Pass/Pass.h +++ b/mlir/include/mlir/Pass/Pass.h @@ -114,7 +114,9 @@ public: /// Derived classes may override this method to hook into the point at which /// options are initialized, but should generally always invoke this base /// class variant. - virtual LogicalResult initializeOptions(StringRef options); + virtual LogicalResult + initializeOptions(StringRef options, + function_ref<LogicalResult(const Twine &)> errorHandler); /// Prints out the pass in the textual representation of pipelines. If this is /// an adaptor pass, print its pass managers. diff --git a/mlir/include/mlir/Pass/PassOptions.h b/mlir/include/mlir/Pass/PassOptions.h index 6717a3585d12a5586f172b9650426d984a5e28eb..3a5e3224133e6f2ff32e63597f83ef74833b8500 100644 --- a/mlir/include/mlir/Pass/PassOptions.h +++ b/mlir/include/mlir/Pass/PassOptions.h @@ -293,7 +293,8 @@ public: /// Parse options out as key=value pairs that can then be handed off to the /// `llvm::cl` command line passing infrastructure. Everything is space /// separated. - LogicalResult parseFromString(StringRef options); + LogicalResult parseFromString(StringRef options, + raw_ostream &errorStream = llvm::errs()); /// Print the options held by this struct in a form that can be parsed via /// 'parseFromString'. diff --git a/mlir/include/mlir/Support/ToolUtilities.h b/mlir/include/mlir/Support/ToolUtilities.h index d2c89409c0653b2e8ab731b85fb12347be1bfaab..511cb118bb2467a351f9c4d94f667f13b7202232 100644 --- a/mlir/include/mlir/Support/ToolUtilities.h +++ b/mlir/include/mlir/Support/ToolUtilities.h @@ -15,6 +15,8 @@ #include "mlir/Support/LLVM.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" + #include <memory> namespace llvm { @@ -27,20 +29,24 @@ struct LogicalResult; using ChunkBufferHandler = function_ref<LogicalResult( std::unique_ptr<llvm::MemoryBuffer> chunkBuffer, raw_ostream &os)>; -/// Splits the specified buffer on a marker (`// -----`), processes each chunk -/// independently according to the normal `processChunkBuffer` logic, and writes -/// all results to `os`. +extern inline const char *const kDefaultSplitMarker = "// -----"; + +/// Splits the specified buffer on a marker (`// -----` by default), processes +/// each chunk independently according to the normal `processChunkBuffer` logic, +/// and writes all results to `os`. /// /// This is used to allow a large number of small independent tests to be put -/// into a single file. `enableSplitting` can be used to toggle if splitting -/// should be enabled, e.g. to allow for merging split and non-split code paths. -/// When `insertMarkerInOutput` is true, split markers (`//-----`) are placed -/// between each of the processed output chunks. +/// into a single file. The input split marker is configurable. If it is empty, +/// merging is disabled, which allows for merging split and non-split code +/// paths. Output split markers (`//-----` by default) followed by a new line +/// character, respectively, are placed between each of the processed output +/// chunks. (The new line character is inserted even if the split marker is +/// empty.) LogicalResult splitAndProcessBuffer(std::unique_ptr<llvm::MemoryBuffer> originalBuffer, ChunkBufferHandler processChunkBuffer, raw_ostream &os, - bool enableSplitting = true, - bool insertMarkerInOutput = false); + llvm::StringRef inputSplitMarker = kDefaultSplitMarker, + llvm::StringRef outputSplitMarker = ""); } // namespace mlir #endif // MLIR_SUPPORT_TOOLUTILITIES_H diff --git a/mlir/include/mlir/TableGen/Format.h b/mlir/include/mlir/TableGen/Format.h index 79d3d26a9d68d6988b2194a9e056559058935a5c..e92f6c64eab561703e6ae66185fec311b90f9b1b 100644 --- a/mlir/include/mlir/TableGen/Format.h +++ b/mlir/include/mlir/TableGen/Format.h @@ -133,14 +133,15 @@ protected: // std::vector<Base*>. struct CreateAdapters { template <typename... Ts> - std::vector<llvm::detail::format_adapter *> operator()(Ts &...items) { - return std::vector<llvm::detail::format_adapter *>{&items...}; + std::vector<llvm::support::detail::format_adapter *> + operator()(Ts &...items) { + return std::vector<llvm::support::detail::format_adapter *>{&items...}; } }; StringRef fmt; const FmtContext *context; - std::vector<llvm::detail::format_adapter *> adapters; + std::vector<llvm::support::detail::format_adapter *> adapters; std::vector<FmtReplacement> replacements; public: @@ -205,8 +206,8 @@ public: class FmtStrVecObject : public FmtObjectBase { public: - using StrFormatAdapter = - decltype(llvm::detail::build_format_adapter(std::declval<std::string>())); + using StrFormatAdapter = decltype(llvm::support::detail::build_format_adapter( + std::declval<std::string>())); FmtStrVecObject(StringRef fmt, const FmtContext *ctx, ArrayRef<std::string> params); @@ -259,14 +260,15 @@ private: /// in C++ code generation. template <typename... Ts> inline auto tgfmt(StringRef fmt, const FmtContext *ctx, Ts &&...vals) - -> FmtObject<decltype(std::make_tuple( - llvm::detail::build_format_adapter(std::forward<Ts>(vals))...))> { + -> FmtObject< + decltype(std::make_tuple(llvm::support::detail::build_format_adapter( + std::forward<Ts>(vals))...))> { using ParamTuple = decltype(std::make_tuple( - llvm::detail::build_format_adapter(std::forward<Ts>(vals))...)); + llvm::support::detail::build_format_adapter(std::forward<Ts>(vals))...)); return FmtObject<ParamTuple>( fmt, ctx, - std::make_tuple( - llvm::detail::build_format_adapter(std::forward<Ts>(vals))...)); + std::make_tuple(llvm::support::detail::build_format_adapter( + std::forward<Ts>(vals))...)); } inline FmtStrVecObject tgfmt(StringRef fmt, const FmtContext *ctx, diff --git a/mlir/include/mlir/Target/Cpp/CppEmitter.h b/mlir/include/mlir/Target/Cpp/CppEmitter.h index 30d3fff9fca88bd3d9d012e5750908ddc8fc9608..d3c081061faa034d03a2454df11b12884c95e427 100644 --- a/mlir/include/mlir/Target/Cpp/CppEmitter.h +++ b/mlir/include/mlir/Target/Cpp/CppEmitter.h @@ -13,13 +13,11 @@ #ifndef MLIR_TARGET_CPP_CPPEMITTER_H #define MLIR_TARGET_CPP_CPPEMITTER_H -#include "mlir/IR/BuiltinTypes.h" -#include "mlir/IR/Value.h" -#include "llvm/ADT/ScopedHashTable.h" -#include "llvm/Support/raw_ostream.h" -#include <stack> +#include "mlir/Support/LLVM.h" namespace mlir { +struct LogicalResult; +class Operation; namespace emitc { /// Translates the given operation to C++ code. The operation or operations in diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h index b49d2f539453e6a4488ed33f9a759cba8619ebd1..b551eb937cfe8d393dff87e41abf15ad28383867 100644 --- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h @@ -152,6 +152,14 @@ public: /// Converts `value` to a label attribute. Asserts if the matching fails. DILabelAttr matchLabelAttr(llvm::Value *value); + /// Converts `value` to a FP exception behavior attribute. Asserts if the + /// matching fails. + FPExceptionBehaviorAttr matchFPExceptionBehaviorAttr(llvm::Value *value); + + /// Converts `value` to a rounding mode attribute. Asserts if the matching + /// fails. + RoundingModeAttr matchRoundingModeAttr(llvm::Value *value); + /// Converts `value` to an array of alias scopes or returns failure if the /// conversion fails. FailureOr<SmallVector<AliasScopeAttr>> diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h index fb4392eb223c7f6ee6d21840246b8dd0913013a8..310a43e0de96b30820e4456479c251cb8f1ace95 100644 --- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h @@ -201,6 +201,13 @@ public: /// Translates the given LLVM debug info metadata. llvm::Metadata *translateDebugInfo(LLVM::DINodeAttr attr); + /// Translates the given LLVM rounding mode metadata. + llvm::RoundingMode translateRoundingMode(LLVM::RoundingMode rounding); + + /// Translates the given LLVM FP exception behavior metadata. + llvm::fp::ExceptionBehavior + translateFPExceptionBehavior(LLVM::FPExceptionBehavior exceptionBehavior); + /// Translates the contents of the given block to LLVM IR using this /// translator. The LLVM IR basic block corresponding to the given block is /// expected to exist in the mapping of this translator. Uses `builder` to diff --git a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h index 6e90fad1618d21be4980e7d92f05adb43aacba9b..4f7f83cdb47376466ccef48c88aa6b6a7cdee2fb 100644 --- a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h +++ b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h @@ -15,6 +15,7 @@ #include "mlir/Debug/CLOptionsSetup.h" #include "mlir/Support/LogicalResult.h" +#include "mlir/Support/ToolUtilities.h" #include "llvm/ADT/StringRef.h" #include <cstdlib> @@ -136,13 +137,23 @@ public: } bool shouldShowDialects() const { return showDialectsFlag; } - /// Set whether to split the input file based on the `// -----` marker into - /// pieces and process each chunk independently. - MlirOptMainConfig &splitInputFile(bool split = true) { - splitInputFileFlag = split; + /// Set the marker on which to split the input into chunks and process each + /// chunk independently. Input is not split if empty. + MlirOptMainConfig & + splitInputFile(std::string splitMarker = kDefaultSplitMarker) { + splitInputFileFlag = std::move(splitMarker); + return *this; + } + StringRef inputSplitMarker() const { return splitInputFileFlag; } + + /// Set whether to merge the output chunks into one file using the given + /// marker. + MlirOptMainConfig & + outputSplitMarker(std::string splitMarker = kDefaultSplitMarker) { + outputSplitMarkerFlag = std::move(splitMarker); return *this; } - bool shouldSplitInputFile() const { return splitInputFileFlag; } + StringRef outputSplitMarker() const { return outputSplitMarkerFlag; } /// Disable implicit addition of a top-level module op during parsing. MlirOptMainConfig &useExplicitModule(bool useExplicitModule) { @@ -215,9 +226,12 @@ protected: /// Show the registered dialects before trying to load the input file. bool showDialectsFlag = false; - /// Split the input file based on the `// -----` marker into pieces and - /// process each chunk independently. - bool splitInputFileFlag = false; + /// Split the input file based on the given marker into chunks and process + /// each chunk independently. Input is not split if empty. + std::string splitInputFileFlag = ""; + + /// Merge output chunks into one file using the given marker. + std::string outputSplitMarkerFlag = ""; /// Use an explicit top-level module op during parsing. bool useExplicitModuleFlag = false; diff --git a/mlir/include/mlir/Transforms/Inliner.h b/mlir/include/mlir/Transforms/Inliner.h index 1fe61fb4bbe7d9482b5be5a5f64d02764e2a44fb..073b83f6f844c537f10b349e11ad1079eb6da582 100644 --- a/mlir/include/mlir/Transforms/Inliner.h +++ b/mlir/include/mlir/Transforms/Inliner.h @@ -69,19 +69,6 @@ private: /// of inlining decisions from the leafs to the roots of the callgraph. class Inliner { public: - using RunPipelineHelperTy = std::function<LogicalResult( - Pass &pass, OpPassManager &pipeline, Operation *op)>; - - Inliner(Operation *op, CallGraph &cg, Pass &pass, AnalysisManager am, - RunPipelineHelperTy runPipelineHelper, const InlinerConfig &config) - : op(op), cg(cg), pass(pass), am(am), - runPipelineHelper(std::move(runPipelineHelper)), config(config) {} - Inliner(Inliner &) = delete; - void operator=(const Inliner &) = delete; - - /// Perform inlining on a OpTrait::SymbolTable operation. - LogicalResult doInlining(); - /// This struct represents a resolved call to a given callgraph node. Given /// that the call does not actually contain a direct reference to the /// Region(CallGraphNode) that it is dispatching to, we need to resolve them @@ -94,7 +81,29 @@ public: CallGraphNode *sourceNode, *targetNode; }; -protected: + using RunPipelineHelperTy = std::function<LogicalResult( + Pass &pass, OpPassManager &pipeline, Operation *op)>; + + /// Type of the callback answering if it is profitable + /// to inline a callable operation at a call site. + /// It might be the case that the ResolvedCall does not provide + /// enough context to make the profitability decision, so + /// this hook's interface might need to be extended in future. + using ProfitabilityCallbackTy = std::function<bool(const ResolvedCall &)>; + + Inliner(Operation *op, CallGraph &cg, Pass &pass, AnalysisManager am, + RunPipelineHelperTy runPipelineHelper, const InlinerConfig &config, + ProfitabilityCallbackTy isProfitableToInline) + : op(op), cg(cg), pass(pass), am(am), + runPipelineHelper(std::move(runPipelineHelper)), config(config), + isProfitableToInline(std::move(isProfitableToInline)) {} + Inliner(Inliner &) = delete; + void operator=(const Inliner &) = delete; + + /// Perform inlining on a OpTrait::SymbolTable operation. + LogicalResult doInlining(); + +private: /// An OpTrait::SymbolTable operation to run the inlining on. Operation *op; /// A CallGraph analysis for the given operation. @@ -108,12 +117,12 @@ protected: const RunPipelineHelperTy runPipelineHelper; /// The inliner configuration parameters. const InlinerConfig &config; + /// Returns true, if it is profitable to inline the callable operation + /// at the call site. + ProfitabilityCallbackTy isProfitableToInline; -private: /// Forward declaration of the class providing the actual implementation. class Impl; - -public: }; } // namespace mlir diff --git a/mlir/include/mlir/Transforms/Mem2Reg.h b/mlir/include/mlir/Transforms/Mem2Reg.h index 89244feb21754e9fe27723621ff49595fa8b5e3a..ed10644e26a519fc165a4396a603b98b054f061b 100644 --- a/mlir/include/mlir/Transforms/Mem2Reg.h +++ b/mlir/include/mlir/Transforms/Mem2Reg.h @@ -9,8 +9,6 @@ #ifndef MLIR_TRANSFORMS_MEM2REG_H #define MLIR_TRANSFORMS_MEM2REG_H -#include "mlir/IR/Dominance.h" -#include "mlir/IR/OpDefinition.h" #include "mlir/IR/PatternMatch.h" #include "mlir/Interfaces/MemorySlotInterfaces.h" #include "llvm/ADT/Statistic.h" @@ -25,29 +23,11 @@ struct Mem2RegStatistics { llvm::Statistic *newBlockArgumentAmount = nullptr; }; -/// Pattern applying mem2reg to the regions of the operations on which it -/// matches. -class Mem2RegPattern - : public OpInterfaceRewritePattern<PromotableAllocationOpInterface> { -public: - using OpInterfaceRewritePattern::OpInterfaceRewritePattern; - - Mem2RegPattern(MLIRContext *context, Mem2RegStatistics statistics = {}, - PatternBenefit benefit = 1) - : OpInterfaceRewritePattern(context, benefit), statistics(statistics) {} - - LogicalResult matchAndRewrite(PromotableAllocationOpInterface allocator, - PatternRewriter &rewriter) const override; - -private: - Mem2RegStatistics statistics; -}; - /// Attempts to promote the memory slots of the provided allocators. Succeeds if /// at least one memory slot was promoted. LogicalResult tryToPromoteMemorySlots(ArrayRef<PromotableAllocationOpInterface> allocators, - RewriterBase &rewriter, + RewriterBase &rewriter, const DataLayout &dataLayout, Mem2RegStatistics statistics = {}); } // namespace mlir diff --git a/mlir/include/mlir/Transforms/Passes.h b/mlir/include/mlir/Transforms/Passes.h index 11f5b23e62c663b74a3d531f74a8eac0c4f89a38..58bd61b2ae8b88aa0f95360802c5e2d514419fa6 100644 --- a/mlir/include/mlir/Transforms/Passes.h +++ b/mlir/include/mlir/Transforms/Passes.h @@ -43,6 +43,7 @@ class GreedyRewriteConfig; #define GEN_PASS_DECL_SYMBOLDCE #define GEN_PASS_DECL_SYMBOLPRIVATIZE #define GEN_PASS_DECL_TOPOLOGICALSORT +#define GEN_PASS_DECL_COMPOSITEFIXEDPOINTPASS #include "mlir/Transforms/Passes.h.inc" /// Creates an instance of the Canonicalizer pass, configured with default @@ -130,6 +131,12 @@ createSymbolPrivatizePass(ArrayRef<std::string> excludeSymbols = {}); /// their producers. std::unique_ptr<Pass> createTopologicalSortPass(); +/// Create composite pass, which runs provided set of passes until fixed point +/// or maximum number of iterations reached. +std::unique_ptr<Pass> createCompositeFixedPointPass( + std::string name, llvm::function_ref<void(OpPassManager &)> populateFunc, + int maxIterations = 10); + //===----------------------------------------------------------------------===// // Registration //===----------------------------------------------------------------------===// diff --git a/mlir/include/mlir/Transforms/Passes.td b/mlir/include/mlir/Transforms/Passes.td index b8fdf7a580476eec1c38752763306885deaa5268..1b40a87c63f27e03108d5a6855cb6e7e79028282 100644 --- a/mlir/include/mlir/Transforms/Passes.td +++ b/mlir/include/mlir/Transforms/Passes.td @@ -278,6 +278,13 @@ def Inliner : Pass<"inline"> { Option<"maxInliningIterations", "max-iterations", "unsigned", /*default=*/"4", "Maximum number of iterations when inlining within an SCC">, + Option<"inliningThreshold", "inlining-threshold", "unsigned", + /*default=*/"-1U", + "If the ratio between the number of the operations " + "in the callee and the number of the operations " + "in the caller exceeds this value (in percentage), " + "then the callee is not inlined even if it is legal " + "to inline it">, ]; } @@ -545,4 +552,21 @@ def TopologicalSort : Pass<"topological-sort"> { let constructor = "mlir::createTopologicalSortPass()"; } +def CompositeFixedPointPass : Pass<"composite-fixed-point-pass"> { + let summary = "Composite fixed point pass"; + let description = [{ + Composite pass runs provided set of passes until fixed point or maximum + number of iterations reached. + }]; + + let options = [ + Option<"name", "name", "std::string", /*default=*/"\"CompositeFixedPointPass\"", + "Composite pass display name">, + Option<"pipelineStr", "pipeline", "std::string", /*default=*/"", + "Composite pass inner pipeline">, + Option<"maxIter", "max-iterations", "int", /*default=*/"10", + "Maximum number of iterations if inner pipeline">, + ]; +} + #endif // MLIR_TRANSFORMS_PASSES diff --git a/mlir/include/mlir/Transforms/SROA.h b/mlir/include/mlir/Transforms/SROA.h index 0b3e72400c2873355a82f61b7c5ab670cea434d6..d09a7989edeab2d24a1c4128560e65cdf30b620c 100644 --- a/mlir/include/mlir/Transforms/SROA.h +++ b/mlir/include/mlir/Transforms/SROA.h @@ -9,11 +9,9 @@ #ifndef MLIR_TRANSFORMS_SROA_H #define MLIR_TRANSFORMS_SROA_H -#include "mlir/IR/PatternMatch.h" #include "mlir/Interfaces/MemorySlotInterfaces.h" #include "mlir/Support/LogicalResult.h" #include "llvm/ADT/Statistic.h" -#include <variant> namespace mlir { @@ -29,29 +27,12 @@ struct SROAStatistics { llvm::Statistic *maxSubelementAmount = nullptr; }; -/// Pattern applying SROA to the regions of the operations on which it -/// matches. -class SROAPattern - : public OpInterfaceRewritePattern<DestructurableAllocationOpInterface> { -public: - using OpInterfaceRewritePattern::OpInterfaceRewritePattern; - - SROAPattern(MLIRContext *context, SROAStatistics statistics = {}, - PatternBenefit benefit = 1) - : OpInterfaceRewritePattern(context, benefit), statistics(statistics) {} - - LogicalResult matchAndRewrite(DestructurableAllocationOpInterface allocator, - PatternRewriter &rewriter) const override; - -private: - SROAStatistics statistics; -}; - /// Attempts to destructure the slots of destructurable allocators. Returns /// failure if no slot was destructured. LogicalResult tryToDestructureMemorySlots( ArrayRef<DestructurableAllocationOpInterface> allocators, - RewriterBase &rewriter, SROAStatistics statistics = {}); + RewriterBase &rewriter, const DataLayout &dataLayout, + SROAStatistics statistics = {}); } // namespace mlir diff --git a/mlir/lib/CAPI/Dialect/LLVM.cpp b/mlir/lib/CAPI/Dialect/LLVM.cpp index 2d938ce5f4834cc2897d7bf5c8f41c8527e24a1a..71f2b73dd73bca1066475df3ba3a2e9fdd9c8e54 100644 --- a/mlir/lib/CAPI/Dialect/LLVM.cpp +++ b/mlir/lib/CAPI/Dialect/LLVM.cpp @@ -152,32 +152,31 @@ MlirAttribute mlirLLVMDIBasicTypeAttrGet(MlirContext ctx, unsigned int tag, } MlirAttribute mlirLLVMDICompositeTypeAttrGet( - MlirContext ctx, unsigned int tag, MlirAttribute name, MlirAttribute file, - uint32_t line, MlirAttribute scope, MlirAttribute baseType, int64_t flags, - uint64_t sizeInBits, uint64_t alignInBits, intptr_t nElements, - MlirAttribute const *elements) { + MlirContext ctx, unsigned int tag, MlirAttribute recId, MlirAttribute name, + MlirAttribute file, uint32_t line, MlirAttribute scope, + MlirAttribute baseType, int64_t flags, uint64_t sizeInBits, + uint64_t alignInBits, intptr_t nElements, MlirAttribute const *elements) { SmallVector<Attribute> elementsStorage; elementsStorage.reserve(nElements); return wrap(DICompositeTypeAttr::get( - unwrap(ctx), tag, cast<StringAttr>(unwrap(name)), - cast<DIFileAttr>(unwrap(file)), line, cast<DIScopeAttr>(unwrap(scope)), - cast<DITypeAttr>(unwrap(baseType)), DIFlags(flags), sizeInBits, - alignInBits, + unwrap(ctx), tag, cast<DistinctAttr>(unwrap(recId)), + cast<StringAttr>(unwrap(name)), cast<DIFileAttr>(unwrap(file)), line, + cast<DIScopeAttr>(unwrap(scope)), cast<DITypeAttr>(unwrap(baseType)), + DIFlags(flags), sizeInBits, alignInBits, llvm::map_to_vector(unwrapList(nElements, elements, elementsStorage), [](Attribute a) { return a.cast<DINodeAttr>(); }))); } -MlirAttribute mlirLLVMDIDerivedTypeAttrGet(MlirContext ctx, unsigned int tag, - MlirAttribute name, - MlirAttribute baseType, - uint64_t sizeInBits, - uint32_t alignInBits, - uint64_t offsetInBits) { - return wrap(DIDerivedTypeAttr::get(unwrap(ctx), tag, - cast<StringAttr>(unwrap(name)), - cast<DITypeAttr>(unwrap(baseType)), - sizeInBits, alignInBits, offsetInBits)); +MlirAttribute +mlirLLVMDIDerivedTypeAttrGet(MlirContext ctx, unsigned int tag, + MlirAttribute name, MlirAttribute baseType, + uint64_t sizeInBits, uint32_t alignInBits, + uint64_t offsetInBits, MlirAttribute extraData) { + return wrap(DIDerivedTypeAttr::get( + unwrap(ctx), tag, cast<StringAttr>(unwrap(name)), + cast<DITypeAttr>(unwrap(baseType)), sizeInBits, alignInBits, offsetInBits, + cast<DINodeAttr>(unwrap(extraData)))); } MlirAttribute diff --git a/mlir/lib/CAPI/Dialect/TransformInterpreter.cpp b/mlir/lib/CAPI/Dialect/TransformInterpreter.cpp index 6a2cfb235fcfd443d63bcc20491567dc9b19f95c..eb6951dc5584d64ca7b26384f4dea954e9cc4e77 100644 --- a/mlir/lib/CAPI/Dialect/TransformInterpreter.cpp +++ b/mlir/lib/CAPI/Dialect/TransformInterpreter.cpp @@ -15,7 +15,7 @@ #include "mlir/CAPI/IR.h" #include "mlir/CAPI/Support.h" #include "mlir/CAPI/Wrap.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Dialect/Transform/Transforms/TransformInterpreterUtils.h" using namespace mlir; diff --git a/mlir/lib/Conversion/ArithCommon/AttrToLLVMConverter.cpp b/mlir/lib/Conversion/ArithCommon/AttrToLLVMConverter.cpp index dab064a3a954ec534ec6e27abea1f6402eeba5ac..f12eba98480d33b5e6e2efaf3bfd5577b683b4f1 100644 --- a/mlir/lib/Conversion/ArithCommon/AttrToLLVMConverter.cpp +++ b/mlir/lib/Conversion/ArithCommon/AttrToLLVMConverter.cpp @@ -55,3 +55,34 @@ LLVM::IntegerOverflowFlagsAttr mlir::arith::convertArithOverflowAttrToLLVM( return LLVM::IntegerOverflowFlagsAttr::get( flagsAttr.getContext(), convertArithOverflowFlagsToLLVM(arithFlags)); } + +LLVM::RoundingMode +mlir::arith::convertArithRoundingModeToLLVM(arith::RoundingMode roundingMode) { + switch (roundingMode) { + case arith::RoundingMode::downward: + return LLVM::RoundingMode::TowardNegative; + case arith::RoundingMode::to_nearest_away: + return LLVM::RoundingMode::NearestTiesToAway; + case arith::RoundingMode::to_nearest_even: + return LLVM::RoundingMode::NearestTiesToEven; + case arith::RoundingMode::toward_zero: + return LLVM::RoundingMode::TowardZero; + case arith::RoundingMode::upward: + return LLVM::RoundingMode::TowardPositive; + } + llvm_unreachable("Unhandled rounding mode"); +} + +LLVM::RoundingModeAttr mlir::arith::convertArithRoundingModeAttrToLLVM( + arith::RoundingModeAttr roundingModeAttr) { + assert(roundingModeAttr && "Expecting valid attribute"); + return LLVM::RoundingModeAttr::get( + roundingModeAttr.getContext(), + convertArithRoundingModeToLLVM(roundingModeAttr.getValue())); +} + +LLVM::FPExceptionBehaviorAttr +mlir::arith::getLLVMDefaultFPExceptionBehavior(MLIRContext &context) { + return LLVM::FPExceptionBehaviorAttr::get(&context, + LLVM::FPExceptionBehavior::Ignore); +} diff --git a/mlir/lib/Conversion/ArithToAMDGPU/ArithToAMDGPU.cpp b/mlir/lib/Conversion/ArithToAMDGPU/ArithToAMDGPU.cpp index b51a13ae362e92b477378ba7cbb1557920ccab38..0113a3df0b8e3d2af821b3afbcd1c74919a1930d 100644 --- a/mlir/lib/Conversion/ArithToAMDGPU/ArithToAMDGPU.cpp +++ b/mlir/lib/Conversion/ArithToAMDGPU/ArithToAMDGPU.cpp @@ -175,6 +175,9 @@ static Value clampInput(PatternRewriter &rewriter, Location loc, } LogicalResult TruncFToFloat8RewritePattern::match(arith::TruncFOp op) const { + // Only supporting default rounding mode as of now. + if (op.getRoundingmodeAttr()) + return failure(); Type outType = op.getOut().getType(); if (auto outVecType = outType.dyn_cast<VectorType>()) { if (outVecType.isScalable()) diff --git a/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp b/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp index 3532785c31b9396e1eee5fbd76cd7f3396160bf1..db493c1294ba2dd51abe84211d29cbd6713debf2 100644 --- a/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp +++ b/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp @@ -55,6 +55,55 @@ public: } }; +template <typename ArithOp, typename EmitCOp> +class IntegerOpConversion final : public OpConversionPattern<ArithOp> { +public: + using OpConversionPattern<ArithOp>::OpConversionPattern; + + LogicalResult + matchAndRewrite(ArithOp op, typename ArithOp::Adaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + + Type type = this->getTypeConverter()->convertType(op.getType()); + if (!isa_and_nonnull<IntegerType, IndexType>(type)) { + return rewriter.notifyMatchFailure(op, "expected integer type"); + } + + if (type.isInteger(1)) { + // arith expects wrap-around arithmethic, which doesn't happen on `bool`. + return rewriter.notifyMatchFailure(op, "i1 type is not implemented"); + } + + Value lhs = adaptor.getLhs(); + Value rhs = adaptor.getRhs(); + Type arithmeticType = type; + if ((type.isSignlessInteger() || type.isSignedInteger()) && + !bitEnumContainsAll(op.getOverflowFlags(), + arith::IntegerOverflowFlags::nsw)) { + // If the C type is signed and the op doesn't guarantee "No Signed Wrap", + // we compute in unsigned integers to avoid UB. + arithmeticType = rewriter.getIntegerType(type.getIntOrFloatBitWidth(), + /*isSigned=*/false); + } + if (arithmeticType != type) { + lhs = rewriter.template create<emitc::CastOp>(op.getLoc(), arithmeticType, + lhs); + rhs = rewriter.template create<emitc::CastOp>(op.getLoc(), arithmeticType, + rhs); + } + + Value result = rewriter.template create<EmitCOp>(op.getLoc(), + arithmeticType, lhs, rhs); + + if (arithmeticType != type) { + result = + rewriter.template create<emitc::CastOp>(op.getLoc(), type, result); + } + rewriter.replaceOp(op, result); + return success(); + } +}; + class SelectOpConversion : public OpConversionPattern<arith::SelectOp> { public: using OpConversionPattern<arith::SelectOp>::OpConversionPattern; @@ -96,6 +145,9 @@ void mlir::populateArithToEmitCPatterns(TypeConverter &typeConverter, ArithOpConversion<arith::DivFOp, emitc::DivOp>, ArithOpConversion<arith::MulFOp, emitc::MulOp>, ArithOpConversion<arith::SubFOp, emitc::SubOp>, + IntegerOpConversion<arith::AddIOp, emitc::AddOp>, + IntegerOpConversion<arith::MulIOp, emitc::MulOp>, + IntegerOpConversion<arith::SubIOp, emitc::SubOp>, SelectOpConversion >(typeConverter, ctx); // clang-format on diff --git a/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp b/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp index 1f01f4a75c5b3ef9217afae9d9a29fd8eeced990..d882f1184f45704c25c5b802a3433afa5f2ea6b5 100644 --- a/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp +++ b/mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp @@ -28,6 +28,31 @@ using namespace mlir; namespace { +/// Operations whose conversion will depend on whether they are passed a +/// rounding mode attribute or not. +/// +/// `SourceOp` is the source operation; `TargetOp`, the operation it will lower +/// to; `AttrConvert` is the attribute conversion to convert the rounding mode +/// attribute. +template <typename SourceOp, typename TargetOp, bool Constrained, + template <typename, typename> typename AttrConvert = + AttrConvertPassThrough> +struct ConstrainedVectorConvertToLLVMPattern + : public VectorConvertToLLVMPattern<SourceOp, TargetOp, AttrConvert> { + using VectorConvertToLLVMPattern<SourceOp, TargetOp, + AttrConvert>::VectorConvertToLLVMPattern; + + LogicalResult + matchAndRewrite(SourceOp op, typename SourceOp::Adaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + if (Constrained != static_cast<bool>(op.getRoundingModeAttr())) + return failure(); + return VectorConvertToLLVMPattern<SourceOp, TargetOp, + AttrConvert>::matchAndRewrite(op, adaptor, + rewriter); + } +}; + //===----------------------------------------------------------------------===// // Straightforward Op Lowerings //===----------------------------------------------------------------------===// @@ -112,7 +137,11 @@ using SubIOpLowering = VectorConvertToLLVMPattern<arith::SubIOp, LLVM::SubOp, arith::AttrConvertOverflowToLLVM>; using TruncFOpLowering = - VectorConvertToLLVMPattern<arith::TruncFOp, LLVM::FPTruncOp>; + ConstrainedVectorConvertToLLVMPattern<arith::TruncFOp, LLVM::FPTruncOp, + false>; +using ConstrainedTruncFOpLowering = ConstrainedVectorConvertToLLVMPattern< + arith::TruncFOp, LLVM::ConstrainedFPTruncIntr, true, + arith::AttrConverterConstrainedFPToLLVM>; using TruncIOpLowering = VectorConvertToLLVMPattern<arith::TruncIOp, LLVM::TruncOp>; using UIToFPOpLowering = @@ -537,6 +566,7 @@ void mlir::arith::populateArithToLLVMConversionPatterns( SubFOpLowering, SubIOpLowering, TruncFOpLowering, + ConstrainedTruncFOpLowering, TruncIOpLowering, UIToFPOpLowering, XOrIOpLowering diff --git a/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp b/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp index edf81bd7a8f3963e9abcf078852ce3d421d2b926..806981728561c1104d92a4887885a9c71cad27d8 100644 --- a/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp +++ b/mlir/lib/Conversion/ArithToSPIRV/ArithToSPIRV.cpp @@ -805,6 +805,15 @@ struct TypeCastingOpPattern final : public OpConversionPattern<Op> { } else { rewriter.template replaceOpWithNewOp<SPIRVOp>(op, dstType, adaptor.getOperands()); + if (auto roundingModeOp = + dyn_cast<arith::ArithRoundingModeInterface>(*op)) { + if (arith::RoundingModeAttr roundingMode = + roundingModeOp.getRoundingModeAttr()) { + // TODO: Perform rounding mode attribute conversion and attach to new + // operation when defined in the dialect. + return failure(); + } + } } return success(); } @@ -992,10 +1001,9 @@ public: return failure(); Location loc = op.getLoc(); - auto *converter = getTypeConverter<SPIRVTypeConverter>(); Value replace; - if (converter->getOptions().enableFastMathMode) { + if (bitEnumContainsAll(op.getFastmath(), arith::FastMathFlags::nnan)) { if (op.getPredicate() == arith::CmpFPredicate::ORD) { // Ordered comparsion checks if neither operand is NaN. replace = spirv::ConstantOp::getOne(op.getType(), loc, rewriter); @@ -1122,7 +1130,7 @@ public: Value spirvOp = rewriter.create<SPIRVOp>(loc, dstType, adaptor.getOperands()); - if (converter->getOptions().enableFastMathMode) { + if (bitEnumContainsAll(op.getFastmath(), arith::FastMathFlags::nnan)) { rewriter.replaceOp(op, spirvOp); return success(); } @@ -1177,7 +1185,7 @@ public: rewriter.create<SPIRVOp>(loc, dstType, adaptor.getOperands()); if (!shouldInsertNanGuards<SPIRVOp>() || - converter->getOptions().enableFastMathMode) { + bitEnumContainsAll(op.getFastmath(), arith::FastMathFlags::nnan)) { rewriter.replaceOp(op, spirvOp); return success(); } @@ -1286,7 +1294,6 @@ struct ConvertArithToSPIRVPass SPIRVConversionOptions options; options.emulateLT32BitScalarTypes = this->emulateLT32BitScalarTypes; - options.enableFastMathMode = this->enableFastMath; SPIRVTypeConverter typeConverter(targetAttr, options); // Use UnrealizedConversionCast as the bridge so that we don't need to pull diff --git a/mlir/lib/Conversion/CMakeLists.txt b/mlir/lib/Conversion/CMakeLists.txt index 8219cf98575f3c59be38d76383c3178c381e86ea..41ab7046b91ce3ce937f3aba027d903f995be17c 100644 --- a/mlir/lib/Conversion/CMakeLists.txt +++ b/mlir/lib/Conversion/CMakeLists.txt @@ -35,6 +35,7 @@ add_subdirectory(MathToFuncs) add_subdirectory(MathToLibm) add_subdirectory(MathToLLVM) add_subdirectory(MathToSPIRV) +add_subdirectory(MemRefToEmitC) add_subdirectory(MemRefToLLVM) add_subdirectory(MemRefToSPIRV) add_subdirectory(NVGPUToNVVM) diff --git a/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp b/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp index 12a5e202685885a0d488d29d60455dc899a31a58..17f64f1b65b7c4ce70fb1977963567bc3b5159a4 100644 --- a/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp +++ b/mlir/lib/Conversion/ComplexToStandard/ComplexToStandard.cpp @@ -196,6 +196,7 @@ struct TrigonometricOpConversion : public OpConversionPattern<TrigonometricOp> { auto loc = op.getLoc(); auto type = cast<ComplexType>(adaptor.getComplex().getType()); auto elementType = cast<FloatType>(type.getElementType()); + arith::FastMathFlagsAttr fmf = op.getFastMathFlagsAttr(); Value real = rewriter.create<complex::ReOp>(loc, elementType, adaptor.getComplex()); @@ -207,14 +208,14 @@ struct TrigonometricOpConversion : public OpConversionPattern<TrigonometricOp> { // implementation in the subclass to combine them. Value half = rewriter.create<arith::ConstantOp>( loc, elementType, rewriter.getFloatAttr(elementType, 0.5)); - Value exp = rewriter.create<math::ExpOp>(loc, imag); - Value scaledExp = rewriter.create<arith::MulFOp>(loc, half, exp); - Value reciprocalExp = rewriter.create<arith::DivFOp>(loc, half, exp); - Value sin = rewriter.create<math::SinOp>(loc, real); - Value cos = rewriter.create<math::CosOp>(loc, real); + Value exp = rewriter.create<math::ExpOp>(loc, imag, fmf); + Value scaledExp = rewriter.create<arith::MulFOp>(loc, half, exp, fmf); + Value reciprocalExp = rewriter.create<arith::DivFOp>(loc, half, exp, fmf); + Value sin = rewriter.create<math::SinOp>(loc, real, fmf); + Value cos = rewriter.create<math::CosOp>(loc, real, fmf); auto resultPair = - combine(loc, scaledExp, reciprocalExp, sin, cos, rewriter); + combine(loc, scaledExp, reciprocalExp, sin, cos, rewriter, fmf); rewriter.replaceOpWithNewOp<complex::CreateOp>(op, type, resultPair.first, resultPair.second); @@ -223,15 +224,17 @@ struct TrigonometricOpConversion : public OpConversionPattern<TrigonometricOp> { virtual std::pair<Value, Value> combine(Location loc, Value scaledExp, Value reciprocalExp, Value sin, - Value cos, ConversionPatternRewriter &rewriter) const = 0; + Value cos, ConversionPatternRewriter &rewriter, + arith::FastMathFlagsAttr fmf) const = 0; }; struct CosOpConversion : public TrigonometricOpConversion<complex::CosOp> { using TrigonometricOpConversion<complex::CosOp>::TrigonometricOpConversion; - std::pair<Value, Value> - combine(Location loc, Value scaledExp, Value reciprocalExp, Value sin, - Value cos, ConversionPatternRewriter &rewriter) const override { + std::pair<Value, Value> combine(Location loc, Value scaledExp, + Value reciprocalExp, Value sin, Value cos, + ConversionPatternRewriter &rewriter, + arith::FastMathFlagsAttr fmf) const override { // Complex cosine is defined as; // cos(x + iy) = 0.5 * (exp(i(x + iy)) + exp(-i(x + iy))) // Plugging in: @@ -241,10 +244,12 @@ struct CosOpConversion : public TrigonometricOpConversion<complex::CosOp> { // We get: // Re(cos(x + iy)) = (0.5/t + 0.5*t) * cos x // Im(cos(x + iy)) = (0.5/t - 0.5*t) * sin x - Value sum = rewriter.create<arith::AddFOp>(loc, reciprocalExp, scaledExp); - Value resultReal = rewriter.create<arith::MulFOp>(loc, sum, cos); - Value diff = rewriter.create<arith::SubFOp>(loc, reciprocalExp, scaledExp); - Value resultImag = rewriter.create<arith::MulFOp>(loc, diff, sin); + Value sum = + rewriter.create<arith::AddFOp>(loc, reciprocalExp, scaledExp, fmf); + Value resultReal = rewriter.create<arith::MulFOp>(loc, sum, cos, fmf); + Value diff = + rewriter.create<arith::SubFOp>(loc, reciprocalExp, scaledExp, fmf); + Value resultImag = rewriter.create<arith::MulFOp>(loc, diff, sin, fmf); return {resultReal, resultImag}; } }; @@ -813,9 +818,10 @@ struct NegOpConversion : public OpConversionPattern<complex::NegOp> { struct SinOpConversion : public TrigonometricOpConversion<complex::SinOp> { using TrigonometricOpConversion<complex::SinOp>::TrigonometricOpConversion; - std::pair<Value, Value> - combine(Location loc, Value scaledExp, Value reciprocalExp, Value sin, - Value cos, ConversionPatternRewriter &rewriter) const override { + std::pair<Value, Value> combine(Location loc, Value scaledExp, + Value reciprocalExp, Value sin, Value cos, + ConversionPatternRewriter &rewriter, + arith::FastMathFlagsAttr fmf) const override { // Complex sine is defined as; // sin(x + iy) = -0.5i * (exp(i(x + iy)) - exp(-i(x + iy))) // Plugging in: @@ -825,10 +831,12 @@ struct SinOpConversion : public TrigonometricOpConversion<complex::SinOp> { // We get: // Re(sin(x + iy)) = (0.5*t + 0.5/t) * sin x // Im(cos(x + iy)) = (0.5*t - 0.5/t) * cos x - Value sum = rewriter.create<arith::AddFOp>(loc, scaledExp, reciprocalExp); - Value resultReal = rewriter.create<arith::MulFOp>(loc, sum, sin); - Value diff = rewriter.create<arith::SubFOp>(loc, scaledExp, reciprocalExp); - Value resultImag = rewriter.create<arith::MulFOp>(loc, diff, cos); + Value sum = + rewriter.create<arith::AddFOp>(loc, scaledExp, reciprocalExp, fmf); + Value resultReal = rewriter.create<arith::MulFOp>(loc, sum, sin, fmf); + Value diff = + rewriter.create<arith::SubFOp>(loc, scaledExp, reciprocalExp, fmf); + Value resultImag = rewriter.create<arith::MulFOp>(loc, diff, cos, fmf); return {resultReal, resultImag}; } }; @@ -845,6 +853,7 @@ struct SqrtOpConversion : public OpConversionPattern<complex::SqrtOp> { auto type = cast<ComplexType>(op.getType()); Type elementType = type.getElementType(); Value arg = adaptor.getComplex(); + arith::FastMathFlagsAttr fmf = op.getFastMathFlagsAttr(); Value zero = b.create<arith::ConstantOp>(elementType, b.getZeroAttr(elementType)); @@ -852,14 +861,14 @@ struct SqrtOpConversion : public OpConversionPattern<complex::SqrtOp> { Value real = b.create<complex::ReOp>(elementType, adaptor.getComplex()); Value imag = b.create<complex::ImOp>(elementType, adaptor.getComplex()); - Value absLhs = b.create<math::AbsFOp>(real); - Value absArg = b.create<complex::AbsOp>(elementType, arg); - Value addAbs = b.create<arith::AddFOp>(absLhs, absArg); + Value absLhs = b.create<math::AbsFOp>(real, fmf); + Value absArg = b.create<complex::AbsOp>(elementType, arg, fmf); + Value addAbs = b.create<arith::AddFOp>(absLhs, absArg, fmf); Value half = b.create<arith::ConstantOp>(elementType, b.getFloatAttr(elementType, 0.5)); - Value halfAddAbs = b.create<arith::MulFOp>(addAbs, half); - Value sqrtAddAbs = b.create<math::SqrtOp>(halfAddAbs); + Value halfAddAbs = b.create<arith::MulFOp>(addAbs, half, fmf); + Value sqrtAddAbs = b.create<math::SqrtOp>(halfAddAbs, fmf); Value realIsNegative = b.create<arith::CmpFOp>(arith::CmpFPredicate::OLT, real, zero); @@ -869,7 +878,7 @@ struct SqrtOpConversion : public OpConversionPattern<complex::SqrtOp> { Value resultReal = sqrtAddAbs; Value imagDivTwoResultReal = b.create<arith::DivFOp>( - imag, b.create<arith::AddFOp>(resultReal, resultReal)); + imag, b.create<arith::AddFOp>(resultReal, resultReal, fmf), fmf); Value negativeResultReal = b.create<arith::NegFOp>(resultReal); @@ -882,7 +891,7 @@ struct SqrtOpConversion : public OpConversionPattern<complex::SqrtOp> { resultReal = b.create<arith::SelectOp>( realIsNegative, b.create<arith::DivFOp>( - imag, b.create<arith::AddFOp>(resultImag, resultImag)), + imag, b.create<arith::AddFOp>(resultImag, resultImag, fmf), fmf), resultReal); Value realIsZero = diff --git a/mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp b/mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp index 73d418cb8413276cc6a45415f6d1c628e070d94e..993c09b03c0fde197939b8e07f4245e5ff7b62c5 100644 --- a/mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp +++ b/mlir/lib/Conversion/GPUCommon/GPUOpsLowering.cpp @@ -545,8 +545,7 @@ LogicalResult impl::scalarizeVectorOp(Operation *op, ValueRange operands, ConversionPatternRewriter &rewriter, const LLVMTypeConverter &converter) { TypeRange operandTypes(operands); - if (llvm::none_of(operandTypes, - [](Type type) { return isa<VectorType>(type); })) { + if (llvm::none_of(operandTypes, llvm::IsaPred<VectorType>)) { return rewriter.notifyMatchFailure(op, "expected vector operand"); } if (op->getNumRegions() != 0 || op->getNumSuccessors() != 0) diff --git a/mlir/lib/Conversion/GPUToNVVM/LowerGpuOpsToNVVMOps.cpp b/mlir/lib/Conversion/GPUToNVVM/LowerGpuOpsToNVVMOps.cpp index d6a5d8cd74d5f20a3989e9e97c1701a53a6a03e7..b95fba20a00cbe509d7a562e04f57232eb2926e9 100644 --- a/mlir/lib/Conversion/GPUToNVVM/LowerGpuOpsToNVVMOps.cpp +++ b/mlir/lib/Conversion/GPUToNVVM/LowerGpuOpsToNVVMOps.cpp @@ -155,8 +155,6 @@ struct GPUShuffleOpLowering : public ConvertOpToLLVMPattern<gpu::ShuffleOp> { auto valueTy = adaptor.getValue().getType(); auto int32Type = IntegerType::get(rewriter.getContext(), 32); auto predTy = IntegerType::get(rewriter.getContext(), 1); - auto resultTy = LLVM::LLVMStructType::getLiteral(rewriter.getContext(), - {valueTy, predTy}); Value one = rewriter.create<LLVM::ConstantOp>(loc, int32Type, 1); Value minusOne = rewriter.create<LLVM::ConstantOp>(loc, int32Type, -1); @@ -176,14 +174,25 @@ struct GPUShuffleOpLowering : public ConvertOpToLLVMPattern<gpu::ShuffleOp> { rewriter.create<LLVM::SubOp>(loc, int32Type, adaptor.getWidth(), one); } - auto returnValueAndIsValidAttr = rewriter.getUnitAttr(); + bool predIsUsed = !op->getResult(1).use_empty(); + UnitAttr returnValueAndIsValidAttr = nullptr; + Type resultTy = valueTy; + if (predIsUsed) { + returnValueAndIsValidAttr = rewriter.getUnitAttr(); + resultTy = LLVM::LLVMStructType::getLiteral(rewriter.getContext(), + {valueTy, predTy}); + } Value shfl = rewriter.create<NVVM::ShflOp>( loc, resultTy, activeMask, adaptor.getValue(), adaptor.getOffset(), maskAndClamp, convertShflKind(op.getMode()), returnValueAndIsValidAttr); - Value shflValue = rewriter.create<LLVM::ExtractValueOp>(loc, shfl, 0); - Value isActiveSrcLane = rewriter.create<LLVM::ExtractValueOp>(loc, shfl, 1); - - rewriter.replaceOp(op, {shflValue, isActiveSrcLane}); + if (predIsUsed) { + Value shflValue = rewriter.create<LLVM::ExtractValueOp>(loc, shfl, 0); + Value isActiveSrcLane = + rewriter.create<LLVM::ExtractValueOp>(loc, shfl, 1); + rewriter.replaceOp(op, {shflValue, isActiveSrcLane}); + } else { + rewriter.replaceOp(op, {shfl, nullptr}); + } return success(); } }; diff --git a/mlir/lib/Conversion/LinalgToStandard/CMakeLists.txt b/mlir/lib/Conversion/LinalgToStandard/CMakeLists.txt index 0c8816b65d194eb27c97c32bc56bca411a396174..cbe85789b29a371b72646702d71cb9242f5539c4 100644 --- a/mlir/lib/Conversion/LinalgToStandard/CMakeLists.txt +++ b/mlir/lib/Conversion/LinalgToStandard/CMakeLists.txt @@ -14,6 +14,7 @@ add_mlir_conversion_library(MLIRLinalgToStandard MLIRFuncDialect MLIRIR MLIRLinalgDialect + MLIRLinalgTransforms MLIRMemRefDialect MLIRPass MLIRSCFDialect diff --git a/mlir/lib/Conversion/MemRefToEmitC/CMakeLists.txt b/mlir/lib/Conversion/MemRefToEmitC/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..8a72e747d024ae686549339abde7602001fcde6d --- /dev/null +++ b/mlir/lib/Conversion/MemRefToEmitC/CMakeLists.txt @@ -0,0 +1,18 @@ +add_mlir_conversion_library(MLIRMemRefToEmitC + MemRefToEmitC.cpp + MemRefToEmitCPass.cpp + + ADDITIONAL_HEADER_DIRS + ${MLIR_MAIN_INCLUDE_DIR}/mlir/Conversion/MemRefToEmitC + + DEPENDS + MLIRConversionPassIncGen + + LINK_COMPONENTS + Core + + LINK_LIBS PUBLIC + MLIREmitCDialect + MLIRMemRefDialect + MLIRTransforms + ) diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0e3b6469212640aa89094cebf1bff561c28b2a69 --- /dev/null +++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp @@ -0,0 +1,114 @@ +//===- MemRefToEmitC.cpp - MemRef to EmitC conversion ---------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements patterns to convert memref ops into emitc ops. +// +//===----------------------------------------------------------------------===// + +#include "mlir/Conversion/MemRefToEmitC/MemRefToEmitC.h" + +#include "mlir/Dialect/EmitC/IR/EmitC.h" +#include "mlir/Dialect/MemRef/IR/MemRef.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/PatternMatch.h" +#include "mlir/Transforms/DialectConversion.h" + +using namespace mlir; + +namespace { +struct ConvertAlloca final : public OpConversionPattern<memref::AllocaOp> { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(memref::AllocaOp op, OpAdaptor operands, + ConversionPatternRewriter &rewriter) const override { + + if (!op.getType().hasStaticShape()) { + return rewriter.notifyMatchFailure( + op.getLoc(), "cannot transform alloca with dynamic shape"); + } + + if (op.getAlignment().value_or(1) > 1) { + // TODO: Allow alignment if it is not more than the natural alignment + // of the C array. + return rewriter.notifyMatchFailure( + op.getLoc(), "cannot transform alloca with alignment requirement"); + } + + auto resultTy = getTypeConverter()->convertType(op.getType()); + if (!resultTy) { + return rewriter.notifyMatchFailure(op.getLoc(), "cannot convert type"); + } + auto noInit = emitc::OpaqueAttr::get(getContext(), ""); + rewriter.replaceOpWithNewOp<emitc::VariableOp>(op, resultTy, noInit); + return success(); + } +}; + +struct ConvertLoad final : public OpConversionPattern<memref::LoadOp> { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(memref::LoadOp op, OpAdaptor operands, + ConversionPatternRewriter &rewriter) const override { + + auto resultTy = getTypeConverter()->convertType(op.getType()); + if (!resultTy) { + return rewriter.notifyMatchFailure(op.getLoc(), "cannot convert type"); + } + + auto subscript = rewriter.create<emitc::SubscriptOp>( + op.getLoc(), operands.getMemref(), operands.getIndices()); + + auto noInit = emitc::OpaqueAttr::get(getContext(), ""); + auto var = + rewriter.create<emitc::VariableOp>(op.getLoc(), resultTy, noInit); + + rewriter.create<emitc::AssignOp>(op.getLoc(), var, subscript); + rewriter.replaceOp(op, var); + return success(); + } +}; + +struct ConvertStore final : public OpConversionPattern<memref::StoreOp> { + using OpConversionPattern::OpConversionPattern; + + LogicalResult + matchAndRewrite(memref::StoreOp op, OpAdaptor operands, + ConversionPatternRewriter &rewriter) const override { + + auto subscript = rewriter.create<emitc::SubscriptOp>( + op.getLoc(), operands.getMemref(), operands.getIndices()); + rewriter.replaceOpWithNewOp<emitc::AssignOp>(op, subscript, + operands.getValue()); + return success(); + } +}; +} // namespace + +void mlir::populateMemRefToEmitCTypeConversion(TypeConverter &typeConverter) { + typeConverter.addConversion( + [&](MemRefType memRefType) -> std::optional<Type> { + if (!memRefType.hasStaticShape() || + !memRefType.getLayout().isIdentity() || memRefType.getRank() == 0) { + return {}; + } + Type convertedElementType = + typeConverter.convertType(memRefType.getElementType()); + if (!convertedElementType) + return {}; + return emitc::ArrayType::get(memRefType.getShape(), + convertedElementType); + }); +} + +void mlir::populateMemRefToEmitCConversionPatterns(RewritePatternSet &patterns, + TypeConverter &converter) { + patterns.add<ConvertAlloca, ConvertLoad, ConvertStore>(converter, + patterns.getContext()); +} diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4e5d1912d15729333f8f5a9908ada6655e5ae6fd --- /dev/null +++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp @@ -0,0 +1,55 @@ +//===- MemRefToEmitC.cpp - MemRef to EmitC conversion ---------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements a pass to convert memref ops into emitc ops. +// +//===----------------------------------------------------------------------===// + +#include "mlir/Conversion/MemRefToEmitC/MemRefToEmitCPass.h" + +#include "mlir/Conversion/MemRefToEmitC/MemRefToEmitC.h" +#include "mlir/Dialect/EmitC/IR/EmitC.h" +#include "mlir/Dialect/MemRef/IR/MemRef.h" +#include "mlir/Pass/Pass.h" +#include "mlir/Transforms/DialectConversion.h" + +namespace mlir { +#define GEN_PASS_DEF_CONVERTMEMREFTOEMITC +#include "mlir/Conversion/Passes.h.inc" +} // namespace mlir + +using namespace mlir; + +namespace { +struct ConvertMemRefToEmitCPass + : public impl::ConvertMemRefToEmitCBase<ConvertMemRefToEmitCPass> { + void runOnOperation() override { + TypeConverter converter; + + // Fallback for other types. + converter.addConversion([](Type type) -> std::optional<Type> { + if (isa<MemRefType>(type)) + return {}; + return type; + }); + + populateMemRefToEmitCTypeConversion(converter); + + RewritePatternSet patterns(&getContext()); + populateMemRefToEmitCConversionPatterns(patterns, converter); + + ConversionTarget target(getContext()); + target.addIllegalDialect<memref::MemRefDialect>(); + target.addLegalDialect<emitc::EmitCDialect>(); + + if (failed(applyPartialConversion(getOperation(), target, + std::move(patterns)))) + return signalPassFailure(); + } +}; +} // namespace diff --git a/mlir/lib/Conversion/MemRefToLLVM/CMakeLists.txt b/mlir/lib/Conversion/MemRefToLLVM/CMakeLists.txt index 1400618c93e850bc37e4a7aa1bcce77b24bb1c5d..f0d95f5ada290e0729f29014097a7997afdc224d 100644 --- a/mlir/lib/Conversion/MemRefToLLVM/CMakeLists.txt +++ b/mlir/lib/Conversion/MemRefToLLVM/CMakeLists.txt @@ -14,6 +14,7 @@ add_mlir_conversion_library(MLIRMemRefToLLVM LINK_LIBS PUBLIC MLIRAnalysis MLIRDataLayoutInterfaces + MLIRFuncDialect MLIRLLVMCommonConversion MLIRMemRefDialect MLIRMemRefUtils diff --git a/mlir/lib/Conversion/MemRefToSPIRV/MapMemRefStorageClassPass.cpp b/mlir/lib/Conversion/MemRefToSPIRV/MapMemRefStorageClassPass.cpp index 76dab8ee4ac3369ceb46782e9650d661ecd7bde5..4cbc3dfdae223cecd26896ce7d73d6b13dcbcb5f 100644 --- a/mlir/lib/Conversion/MemRefToSPIRV/MapMemRefStorageClassPass.cpp +++ b/mlir/lib/Conversion/MemRefToSPIRV/MapMemRefStorageClassPass.cpp @@ -272,14 +272,16 @@ public: const spirv::MemorySpaceToStorageClassMap &memorySpaceMap) : memorySpaceMap(memorySpaceMap) {} - LogicalResult initializeOptions(StringRef options) override { - if (failed(Pass::initializeOptions(options))) + LogicalResult initializeOptions( + StringRef options, + function_ref<LogicalResult(const Twine &)> errorHandler) override { + if (failed(Pass::initializeOptions(options, errorHandler))) return failure(); if (clientAPI == "opencl") memorySpaceMap = spirv::mapMemorySpaceToOpenCLStorageClass; else if (clientAPI != "vulkan") - return failure(); + return errorHandler(llvm::Twine("Invalid clienAPI: ") + clientAPI); return success(); } diff --git a/mlir/lib/Conversion/MemRefToSPIRV/MemRefToSPIRV.cpp b/mlir/lib/Conversion/MemRefToSPIRV/MemRefToSPIRV.cpp index 0acb2142f3f68a48734617719f84a412f3661793..81b9f55cac80f77d1ba676a95f74fa79d5ece027 100644 --- a/mlir/lib/Conversion/MemRefToSPIRV/MemRefToSPIRV.cpp +++ b/mlir/lib/Conversion/MemRefToSPIRV/MemRefToSPIRV.cpp @@ -50,11 +50,12 @@ static Value getOffsetForBitwidth(Location loc, Value srcIdx, int sourceBits, assert(targetBits % sourceBits == 0); Type type = srcIdx.getType(); IntegerAttr idxAttr = builder.getIntegerAttr(type, targetBits / sourceBits); - auto idx = builder.create<spirv::ConstantOp>(loc, type, idxAttr); + auto idx = builder.createOrFold<spirv::ConstantOp>(loc, type, idxAttr); IntegerAttr srcBitsAttr = builder.getIntegerAttr(type, sourceBits); - auto srcBitsValue = builder.create<spirv::ConstantOp>(loc, type, srcBitsAttr); - auto m = builder.create<spirv::UModOp>(loc, srcIdx, idx); - return builder.create<spirv::IMulOp>(loc, type, m, srcBitsValue); + auto srcBitsValue = + builder.createOrFold<spirv::ConstantOp>(loc, type, srcBitsAttr); + auto m = builder.createOrFold<spirv::UModOp>(loc, srcIdx, idx); + return builder.createOrFold<spirv::IMulOp>(loc, type, m, srcBitsValue); } /// Returns an adjusted spirv::AccessChainOp. Based on the @@ -74,11 +75,11 @@ adjustAccessChainForBitwidth(const SPIRVTypeConverter &typeConverter, Value lastDim = op->getOperand(op.getNumOperands() - 1); Type type = lastDim.getType(); IntegerAttr attr = builder.getIntegerAttr(type, targetBits / sourceBits); - auto idx = builder.create<spirv::ConstantOp>(loc, type, attr); + auto idx = builder.createOrFold<spirv::ConstantOp>(loc, type, attr); auto indices = llvm::to_vector<4>(op.getIndices()); // There are two elements if this is a 1-D tensor. assert(indices.size() == 2); - indices.back() = builder.create<spirv::SDivOp>(loc, lastDim, idx); + indices.back() = builder.createOrFold<spirv::SDivOp>(loc, lastDim, idx); Type t = typeConverter.convertType(op.getComponentPtr().getType()); return builder.create<spirv::AccessChainOp>(loc, t, op.getBasePtr(), indices); } @@ -91,7 +92,8 @@ static Value castBoolToIntN(Location loc, Value srcBool, Type dstType, return srcBool; Value zero = spirv::ConstantOp::getZero(dstType, loc, builder); Value one = spirv::ConstantOp::getOne(dstType, loc, builder); - return builder.create<spirv::SelectOp>(loc, dstType, srcBool, one, zero); + return builder.createOrFold<spirv::SelectOp>(loc, dstType, srcBool, one, + zero); } /// Returns the `targetBits`-bit value shifted by the given `offset`, and cast @@ -111,10 +113,10 @@ static Value shiftValue(Location loc, Value value, Value offset, Value mask, loc, builder.getIntegerType(targetBits), value); } - value = builder.create<spirv::BitwiseAndOp>(loc, value, mask); + value = builder.createOrFold<spirv::BitwiseAndOp>(loc, value, mask); } - return builder.create<spirv::ShiftLeftLogicalOp>(loc, value.getType(), value, - offset); + return builder.createOrFold<spirv::ShiftLeftLogicalOp>(loc, value.getType(), + value, offset); } /// Returns true if the allocations of memref `type` generated from `allocOp` @@ -165,7 +167,7 @@ static Value castIntNToBool(Location loc, Value srcInt, OpBuilder &builder) { return srcInt; auto one = spirv::ConstantOp::getOne(srcInt.getType(), loc, builder); - return builder.create<spirv::IEqualOp>(loc, srcInt, one); + return builder.createOrFold<spirv::IEqualOp>(loc, srcInt, one); } //===----------------------------------------------------------------------===// @@ -597,13 +599,14 @@ IntLoadOpPattern::matchAndRewrite(memref::LoadOp loadOp, OpAdaptor adaptor, // ____XXXX________ -> ____________XXXX Value lastDim = accessChainOp->getOperand(accessChainOp.getNumOperands() - 1); Value offset = getOffsetForBitwidth(loc, lastDim, srcBits, dstBits, rewriter); - Value result = rewriter.create<spirv::ShiftRightArithmeticOp>( + Value result = rewriter.createOrFold<spirv::ShiftRightArithmeticOp>( loc, spvLoadOp.getType(), spvLoadOp, offset); // Apply the mask to extract corresponding bits. - Value mask = rewriter.create<spirv::ConstantOp>( + Value mask = rewriter.createOrFold<spirv::ConstantOp>( loc, dstType, rewriter.getIntegerAttr(dstType, (1 << srcBits) - 1)); - result = rewriter.create<spirv::BitwiseAndOp>(loc, dstType, result, mask); + result = + rewriter.createOrFold<spirv::BitwiseAndOp>(loc, dstType, result, mask); // Apply sign extension on the loading value unconditionally. The signedness // semantic is carried in the operator itself, we relies other pattern to @@ -611,11 +614,11 @@ IntLoadOpPattern::matchAndRewrite(memref::LoadOp loadOp, OpAdaptor adaptor, IntegerAttr shiftValueAttr = rewriter.getIntegerAttr(dstType, dstBits - srcBits); Value shiftValue = - rewriter.create<spirv::ConstantOp>(loc, dstType, shiftValueAttr); - result = rewriter.create<spirv::ShiftLeftLogicalOp>(loc, dstType, result, - shiftValue); - result = rewriter.create<spirv::ShiftRightArithmeticOp>(loc, dstType, result, - shiftValue); + rewriter.createOrFold<spirv::ConstantOp>(loc, dstType, shiftValueAttr); + result = rewriter.createOrFold<spirv::ShiftLeftLogicalOp>(loc, dstType, + result, shiftValue); + result = rewriter.createOrFold<spirv::ShiftRightArithmeticOp>( + loc, dstType, result, shiftValue); rewriter.replaceOp(loadOp, result); @@ -744,11 +747,12 @@ IntStoreOpPattern::matchAndRewrite(memref::StoreOp storeOp, OpAdaptor adaptor, // Create a mask to clear the destination. E.g., if it is the second i8 in // i32, 0xFFFF00FF is created. - Value mask = rewriter.create<spirv::ConstantOp>( + Value mask = rewriter.createOrFold<spirv::ConstantOp>( loc, dstType, rewriter.getIntegerAttr(dstType, (1 << srcBits) - 1)); - Value clearBitsMask = - rewriter.create<spirv::ShiftLeftLogicalOp>(loc, dstType, mask, offset); - clearBitsMask = rewriter.create<spirv::NotOp>(loc, dstType, clearBitsMask); + Value clearBitsMask = rewriter.createOrFold<spirv::ShiftLeftLogicalOp>( + loc, dstType, mask, offset); + clearBitsMask = + rewriter.createOrFold<spirv::NotOp>(loc, dstType, clearBitsMask); Value storeVal = shiftValue(loc, adaptor.getValue(), offset, mask, rewriter); Value adjustedPtr = adjustAccessChainForBitwidth(typeConverter, accessChainOp, @@ -910,7 +914,7 @@ LogicalResult ReinterpretCastPattern::matchAndRewrite( int64_t attrVal = cast<IntegerAttr>(offset.get<Attribute>()).getInt(); Attribute attr = rewriter.getIntegerAttr(intType, attrVal); - return rewriter.create<spirv::ConstantOp>(loc, intType, attr); + return rewriter.createOrFold<spirv::ConstantOp>(loc, intType, attr); }(); rewriter.replaceOpWithNewOp<spirv::InBoundsPtrAccessChainOp>( diff --git a/mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp b/mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp index fa54d01cfe2384794da873268319b468a9b0edb0..b9ada0fa0f979d66abbe1ba3474f87ece1a72c5f 100644 --- a/mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp +++ b/mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp @@ -239,21 +239,23 @@ void mlir::configureOpenMPToLLVMConversionLegality( ConversionTarget &target, LLVMTypeConverter &typeConverter) { target.addDynamicallyLegalOp< mlir::omp::AtomicReadOp, mlir::omp::AtomicWriteOp, mlir::omp::FlushOp, - mlir::omp::ThreadprivateOp, mlir::omp::YieldOp, mlir::omp::EnterDataOp, - mlir::omp::ExitDataOp, mlir::omp::UpdateDataOp, mlir::omp::DataBoundsOp, - mlir::omp::MapInfoOp>([&](Operation *op) { - return typeConverter.isLegal(op->getOperandTypes()) && - typeConverter.isLegal(op->getResultTypes()); - }); + mlir::omp::ThreadprivateOp, mlir::omp::YieldOp, + mlir::omp::TargetEnterDataOp, mlir::omp::TargetExitDataOp, + mlir::omp::TargetUpdateOp, mlir::omp::MapBoundsOp, mlir::omp::MapInfoOp>( + [&](Operation *op) { + return typeConverter.isLegal(op->getOperandTypes()) && + typeConverter.isLegal(op->getResultTypes()); + }); target.addDynamicallyLegalOp<mlir::omp::ReductionOp>([&](Operation *op) { return typeConverter.isLegal(op->getOperandTypes()); }); target.addDynamicallyLegalOp< mlir::omp::AtomicUpdateOp, mlir::omp::CriticalOp, mlir::omp::TargetOp, - mlir::omp::DataOp, mlir::omp::OrderedRegionOp, mlir::omp::ParallelOp, - mlir::omp::WsLoopOp, mlir::omp::SimdLoopOp, mlir::omp::MasterOp, - mlir::omp::SectionOp, mlir::omp::SectionsOp, mlir::omp::SingleOp, - mlir::omp::TaskGroupOp, mlir::omp::TaskOp, mlir::omp::ReductionDeclareOp, + mlir::omp::TargetDataOp, mlir::omp::OrderedRegionOp, + mlir::omp::ParallelOp, mlir::omp::WsloopOp, mlir::omp::SimdLoopOp, + mlir::omp::MasterOp, mlir::omp::SectionOp, mlir::omp::SectionsOp, + mlir::omp::SingleOp, mlir::omp::TaskgroupOp, mlir::omp::TaskOp, + mlir::omp::DeclareReductionOp, mlir::omp::PrivateClauseOp>([&](Operation *op) { return std::all_of(op->getRegions().begin(), op->getRegions().end(), [&](Region ®ion) { @@ -270,28 +272,28 @@ void mlir::populateOpenMPToLLVMConversionPatterns(LLVMTypeConverter &converter, // bounds information for map clauses and the operation and type are // discarded on lowering to LLVM-IR from the OpenMP dialect. converter.addConversion( - [&](omp::DataBoundsType type) -> Type { return type; }); + [&](omp::MapBoundsType type) -> Type { return type; }); patterns.add< AtomicReadOpConversion, MapInfoOpConversion, ReductionOpConversion, - MultiRegionOpConversion<omp::ReductionDeclareOp>, + MultiRegionOpConversion<omp::DeclareReductionOp>, MultiRegionOpConversion<omp::PrivateClauseOp>, RegionOpConversion<omp::CriticalOp>, RegionOpConversion<omp::MasterOp>, ReductionOpConversion, RegionOpConversion<omp::OrderedRegionOp>, - RegionOpConversion<omp::ParallelOp>, RegionOpConversion<omp::WsLoopOp>, + RegionOpConversion<omp::ParallelOp>, RegionOpConversion<omp::WsloopOp>, RegionOpConversion<omp::SectionsOp>, RegionOpConversion<omp::SectionOp>, RegionOpConversion<omp::SimdLoopOp>, RegionOpConversion<omp::SingleOp>, - RegionOpConversion<omp::TaskGroupOp>, RegionOpConversion<omp::TaskOp>, - RegionOpConversion<omp::DataOp>, RegionOpConversion<omp::TargetOp>, + RegionOpConversion<omp::TaskgroupOp>, RegionOpConversion<omp::TaskOp>, + RegionOpConversion<omp::TargetDataOp>, RegionOpConversion<omp::TargetOp>, RegionLessOpWithVarOperandsConversion<omp::AtomicWriteOp>, RegionOpWithVarOperandsConversion<omp::AtomicUpdateOp>, RegionLessOpWithVarOperandsConversion<omp::FlushOp>, RegionLessOpWithVarOperandsConversion<omp::ThreadprivateOp>, RegionLessOpConversion<omp::YieldOp>, - RegionLessOpConversion<omp::EnterDataOp>, - RegionLessOpConversion<omp::ExitDataOp>, - RegionLessOpConversion<omp::UpdateDataOp>, - RegionLessOpWithVarOperandsConversion<omp::DataBoundsOp>>(converter); + RegionLessOpConversion<omp::TargetEnterDataOp>, + RegionLessOpConversion<omp::TargetExitDataOp>, + RegionLessOpConversion<omp::TargetUpdateOp>, + RegionLessOpWithVarOperandsConversion<omp::MapBoundsOp>>(converter); } namespace { diff --git a/mlir/lib/Conversion/SCFToOpenMP/SCFToOpenMP.cpp b/mlir/lib/Conversion/SCFToOpenMP/SCFToOpenMP.cpp index 464a647564acedfddb977d91bf231d4fa5da7920..7f91367ad427a29c1abed1ea4870f9052a442bbf 100644 --- a/mlir/lib/Conversion/SCFToOpenMP/SCFToOpenMP.cpp +++ b/mlir/lib/Conversion/SCFToOpenMP/SCFToOpenMP.cpp @@ -183,12 +183,12 @@ static Attribute minMaxValueForUnsignedInt(Type type, bool min) { /// symbol table. The declaration has a constant initializer with the neutral /// value `initValue`, and the `reductionIndex`-th reduction combiner carried /// over from `reduce`. -static omp::ReductionDeclareOp +static omp::DeclareReductionOp createDecl(PatternRewriter &builder, SymbolTable &symbolTable, scf::ReduceOp reduce, int64_t reductionIndex, Attribute initValue) { OpBuilder::InsertionGuard guard(builder); Type type = reduce.getOperands()[reductionIndex].getType(); - auto decl = builder.create<omp::ReductionDeclareOp>(reduce.getLoc(), + auto decl = builder.create<omp::DeclareReductionOp>(reduce.getLoc(), "__scf_reduction", type); symbolTable.insert(decl); @@ -215,9 +215,9 @@ createDecl(PatternRewriter &builder, SymbolTable &symbolTable, /// Adds an atomic reduction combiner to the given OpenMP reduction declaration /// using llvm.atomicrmw of the given kind. -static omp::ReductionDeclareOp addAtomicRMW(OpBuilder &builder, +static omp::DeclareReductionOp addAtomicRMW(OpBuilder &builder, LLVM::AtomicBinOp atomicKind, - omp::ReductionDeclareOp decl, + omp::DeclareReductionOp decl, scf::ReduceOp reduce, int64_t reductionIndex) { OpBuilder::InsertionGuard guard(builder); @@ -241,7 +241,7 @@ static omp::ReductionDeclareOp addAtomicRMW(OpBuilder &builder, /// reduction and returns it. Recognizes common reductions in order to identify /// the neutral value, necessary for the OpenMP declaration. If the reduction /// cannot be recognized, returns null. -static omp::ReductionDeclareOp declareReduction(PatternRewriter &builder, +static omp::DeclareReductionOp declareReduction(PatternRewriter &builder, scf::ReduceOp reduce, int64_t reductionIndex) { Operation *container = SymbolTable::getNearestSymbolTable(reduce); @@ -262,35 +262,35 @@ static omp::ReductionDeclareOp declareReduction(PatternRewriter &builder, Type type = reduce.getOperands()[reductionIndex].getType(); Block &reduction = reduce.getReductions()[reductionIndex].front(); if (matchSimpleReduction<arith::AddFOp, LLVM::FAddOp>(reduction)) { - omp::ReductionDeclareOp decl = + omp::DeclareReductionOp decl = createDecl(builder, symbolTable, reduce, reductionIndex, builder.getFloatAttr(type, 0.0)); return addAtomicRMW(builder, LLVM::AtomicBinOp::fadd, decl, reduce, reductionIndex); } if (matchSimpleReduction<arith::AddIOp, LLVM::AddOp>(reduction)) { - omp::ReductionDeclareOp decl = + omp::DeclareReductionOp decl = createDecl(builder, symbolTable, reduce, reductionIndex, builder.getIntegerAttr(type, 0)); return addAtomicRMW(builder, LLVM::AtomicBinOp::add, decl, reduce, reductionIndex); } if (matchSimpleReduction<arith::OrIOp, LLVM::OrOp>(reduction)) { - omp::ReductionDeclareOp decl = + omp::DeclareReductionOp decl = createDecl(builder, symbolTable, reduce, reductionIndex, builder.getIntegerAttr(type, 0)); return addAtomicRMW(builder, LLVM::AtomicBinOp::_or, decl, reduce, reductionIndex); } if (matchSimpleReduction<arith::XOrIOp, LLVM::XOrOp>(reduction)) { - omp::ReductionDeclareOp decl = + omp::DeclareReductionOp decl = createDecl(builder, symbolTable, reduce, reductionIndex, builder.getIntegerAttr(type, 0)); return addAtomicRMW(builder, LLVM::AtomicBinOp::_xor, decl, reduce, reductionIndex); } if (matchSimpleReduction<arith::AndIOp, LLVM::AndOp>(reduction)) { - omp::ReductionDeclareOp decl = createDecl( + omp::DeclareReductionOp decl = createDecl( builder, symbolTable, reduce, reductionIndex, builder.getIntegerAttr( type, llvm::APInt::getAllOnes(type.getIntOrFloatBitWidth()))); @@ -327,7 +327,7 @@ static omp::ReductionDeclareOp declareReduction(PatternRewriter &builder, matchSelectReduction<LLVM::ICmpOp, LLVM::SelectOp>( reduction, {LLVM::ICmpPredicate::slt, LLVM::ICmpPredicate::sle}, {LLVM::ICmpPredicate::sgt, LLVM::ICmpPredicate::sge}, isMin)) { - omp::ReductionDeclareOp decl = + omp::DeclareReductionOp decl = createDecl(builder, symbolTable, reduce, reductionIndex, minMaxValueForSignedInt(type, !isMin)); return addAtomicRMW(builder, @@ -340,7 +340,7 @@ static omp::ReductionDeclareOp declareReduction(PatternRewriter &builder, matchSelectReduction<LLVM::ICmpOp, LLVM::SelectOp>( reduction, {LLVM::ICmpPredicate::ugt, LLVM::ICmpPredicate::ule}, {LLVM::ICmpPredicate::ugt, LLVM::ICmpPredicate::uge}, isMin)) { - omp::ReductionDeclareOp decl = + omp::DeclareReductionOp decl = createDecl(builder, symbolTable, reduce, reductionIndex, minMaxValueForUnsignedInt(type, !isMin)); return addAtomicRMW( @@ -367,10 +367,10 @@ struct ParallelOpLowering : public OpRewritePattern<scf::ParallelOp> { // TODO: consider checking it here is already a compatible reduction // declaration and use it instead of redeclaring. SmallVector<Attribute> reductionDeclSymbols; - SmallVector<omp::ReductionDeclareOp> ompReductionDecls; + SmallVector<omp::DeclareReductionOp> ompReductionDecls; auto reduce = cast<scf::ReduceOp>(parallelOp.getBody()->getTerminator()); for (int64_t i = 0, e = parallelOp.getNumReductions(); i < e; ++i) { - omp::ReductionDeclareOp decl = declareReduction(rewriter, reduce, i); + omp::DeclareReductionOp decl = declareReduction(rewriter, reduce, i); ompReductionDecls.push_back(decl); if (!decl) return failure(); @@ -461,7 +461,7 @@ struct ParallelOpLowering : public OpRewritePattern<scf::ParallelOp> { // Replace the loop. { OpBuilder::InsertionGuard allocaGuard(rewriter); - auto loop = rewriter.create<omp::WsLoopOp>( + auto loop = rewriter.create<omp::WsloopOp>( parallelOp.getLoc(), parallelOp.getLowerBound(), parallelOp.getUpperBound(), parallelOp.getStep()); rewriter.create<omp::TerminatorOp>(loc); diff --git a/mlir/lib/Conversion/TosaToTensor/TosaToTensor.cpp b/mlir/lib/Conversion/TosaToTensor/TosaToTensor.cpp index 505d85f211111c63b70813fdb1e67be278f94466..cd6da355824691fbc4da3936028d51af975f97a7 100644 --- a/mlir/lib/Conversion/TosaToTensor/TosaToTensor.cpp +++ b/mlir/lib/Conversion/TosaToTensor/TosaToTensor.cpp @@ -19,24 +19,99 @@ #include "mlir/IR/PatternMatch.h" #include "mlir/Transforms/DialectConversion.h" +#include <numeric> + using namespace mlir; using namespace tosa; -static bool findIntermediateShape(ArrayRef<int64_t> lhsShape, - ArrayRef<int64_t> rhsShape, - SmallVector<int64_t> &intermediateShape, - bool isDynamic) { - if (isDynamic) { - // TODO (natashaknk): Make dynamic intermediate shape not always be rank-1 - intermediateShape = {ShapedType::kDynamic}; - return true; - } +namespace { - if (lhsShape.empty() || rhsShape.empty()) { - intermediateShape = {}; - return true; - } +// Infer the type to which the input of a 'tosa.reshape' op must be cast when +// lowered. +TensorType inferReshapeInputType(TypedValue<TensorType> input, + ArrayRef<int64_t> newShape) { + // No need to cast input for non-empty target shape + if (!newShape.empty()) + return input.getType(); + + // The input type must be cast into a tensor with the same rank and all static + // dimensions set to 1. This prevents the generation of a tensor.collapse_shape + // op that converts a dynamically shaped tensor into a 0D tensor. While such + // construct is not incorrect on its own, bufferization cannot properly handle + // it at the moment, so we avoid it. + SmallVector<int64_t> shape(input.getType().getRank(), 1); + return input.getType().clone(shape); +} + +// Infer the result type of 'tensor.expand_shape' in the collapse-expand +// pair emitted for a 'tosa.reshape' op. +TensorType inferReshapeExpandedType(TensorType inputType, + ArrayRef<int64_t> newShape) { + // Special case for 0D output tensor. Note: Watch out when using Type::clone() + // with just '{}', as it will invoke the incorrect overload. + if (newShape.empty()) + return inputType.clone(ArrayRef<int64_t>{}); + + // Check if the input is static, and if so, get its total size + bool inputIsStatic = inputType.hasStaticShape(); + int64_t totalSize = inputIsStatic ? inputType.getNumElements() : -1; + + // Compute result shape + bool resultIsStatic = true; + auto resultShape = llvm::map_to_vector(newShape, [&](int64_t size) -> int64_t { + // If this is not a placeholder, do not change it + if (size >= 0) + return size; + + // If we do not know the total size of the tensor, keep this dimension + // dynamic in the result shape. + if (!inputIsStatic) { + resultIsStatic = false; + return ShapedType::kDynamic; + } + // Calculate the product of all elements in 'newShape' except for the -1 + // placeholder, which we discard by negating the result. + int64_t totalSizeNoPlaceholder = -std::accumulate( + newShape.begin(), newShape.end(), 1, std::multiplies<int64_t>()); + + // If there is a 0 component in 'newShape', resolve the placeholder as 0. + if (totalSizeNoPlaceholder == 0) + return 0; + + // Resolve the placeholder as the quotient between the total tensor size and + // the product of all other sizes. + return totalSize / totalSizeNoPlaceholder; + }); + + // A syntactic restriction in 'tensor.expand_shape' forbids a dynamically + // shaped input from being reshaped into a statically shaped result. We may + // simply turn the first result dimension dynamic to address this. + if (!inputIsStatic && resultIsStatic) + resultShape[0] = ShapedType::kDynamic; + + // The 'tensor.expand_shape' op also forbids a statically shaped input from + // being reshaped into a dynamically shaped result, but the placeholder + // inference algorithm above guarantees that this will never be the case. + assert(!inputIsStatic || resultIsStatic); + + // Create result type + return inputType.clone(resultShape); +} + +// Infer the result type of 'tensor.collapse_shape' in the collapse-expand +// pair emitted for a 'tosa.reshape' op. +TensorType inferReshapeCollapsedType(TensorType lhsType, TensorType rhsType) { + auto lhsShape = lhsType.getShape(); + auto rhsShape = rhsType.getShape(); + + if (lhsShape.empty() || rhsShape.empty()) + return lhsType.clone(ArrayRef<int64_t>{}); + + if (ShapedType::isDynamicShape(lhsShape) || ShapedType::isDynamicShape(rhsShape)) + return lhsType.clone({ShapedType::kDynamic}); + + SmallVector<int64_t> intermediateShape; unsigned currLhsDim = 0, currRhsDim = 0; while (currLhsDim < lhsShape.size() && currRhsDim < rhsShape.size()) { int64_t rhsSize = rhsShape[currRhsDim]; @@ -62,174 +137,113 @@ static bool findIntermediateShape(ArrayRef<int64_t> lhsShape, currLhsDim++; } - // If the iterators didn't reach the end and their leftover dimensions are not - // equal to 1 an intermediate shape was not found. - while (currLhsDim < lhsShape.size()) { - if (lhsShape[currLhsDim++] != 1) { - return false; - } + // Static shapes are guaranteed to be compatible by the op verifier, so all + // leftover dimensions should be 1. + for (; currLhsDim < lhsShape.size(); currLhsDim++) { + assert(lhsShape[currLhsDim] == 1); } - - while (currRhsDim < rhsShape.size()) { - if (rhsShape[currRhsDim++] != 1) { - return false; - } + for (; currRhsDim < rhsShape.size(); currRhsDim++) { + assert(rhsShape[currRhsDim] == 1); } - - return true; + + return lhsType.clone(intermediateShape); } -static bool createReassociationMapsForCollapse( - PatternRewriter &rewriter, ArrayRef<int64_t> srcShape, - ArrayRef<int64_t> dstShape, - SmallVector<ReassociationExprs, 4> &reassociationMap, bool isDynamic) { +SmallVector<ReassociationExprs> +createReassociationMapForCollapse(OpBuilder &builder, Type srcType, Type dstType) { + auto srcShape = cast<TensorType>(srcType).getShape(); + auto dstShape = cast<TensorType>(dstType).getShape(); - // If the shape is dynamic, create a map for collapsing into one dimension. - if (isDynamic) { - SmallVector<AffineExpr, 2> exprs; - for (int i = 0, s = srcShape.size(); i < s; ++i) - exprs.push_back(rewriter.getAffineDimExpr(i)); - reassociationMap = {exprs}; - return true; - } + if (srcShape.empty() || dstShape.empty()) + return {}; - if (dstShape.empty()) { - reassociationMap = {}; - return true; + if (ShapedType::isDynamicShape(srcShape) || ShapedType::isDynamicShape(dstShape)) { + assert(dstShape.size() == 1); + SmallVector<AffineExpr, 2> exprs; + for (auto i : llvm::seq<int64_t>(srcShape.size())) + exprs.push_back(builder.getAffineDimExpr(i)); + return {exprs}; } - reassociationMap.resize(dstShape.size()); + SmallVector<ReassociationExprs> reassociationMap(dstShape.size()); unsigned currSrcDim = 0, currDstDim = 0; while (currSrcDim < srcShape.size() && currDstDim < dstShape.size()) { int64_t dstSize = dstShape[currDstDim]; int64_t srcSize = srcShape[currSrcDim]; while (srcSize < dstSize && currSrcDim < srcShape.size()) { reassociationMap[currDstDim].push_back( - rewriter.getAffineDimExpr(currSrcDim++)); + builder.getAffineDimExpr(currSrcDim++)); srcSize *= srcShape[currSrcDim]; } if (srcSize == dstSize) { reassociationMap[currDstDim].push_back( - rewriter.getAffineDimExpr(currSrcDim++)); + builder.getAffineDimExpr(currSrcDim++)); // If the next dim in collapsedShape is not 1, treat subsequent dims in // expandedShape which are 1 to be collapsed. if (currDstDim == dstShape.size() - 1 || dstShape[currDstDim + 1] != 1) { while (currSrcDim < srcShape.size() && srcShape[currSrcDim] == 1) { reassociationMap[currDstDim].push_back( - rewriter.getAffineDimExpr(currSrcDim++)); + builder.getAffineDimExpr(currSrcDim++)); } } } currDstDim++; } - // If both iterators didn't reach the end, we have leftover dimentions which - // implies that we have a mismatch in shape. - return currSrcDim == srcShape.size() && currDstDim == dstShape.size(); + // If the source and target shapes are compatible, both iterators must have + // reached the end. This condition is guaranteed by the op verifier for + // static shapes. + assert(currSrcDim == srcShape.size() && currDstDim == dstShape.size()); + return reassociationMap; } -namespace { -Value createCollapse(ConversionPatternRewriter &rewriter, Location loc, - ShapedType resultTy, Value operand) { - ShapedType operandTy = cast<ShapedType>(operand.getType()); - if (resultTy == operandTy) - return operand; - - bool isDynamic = !operandTy.hasStaticShape(); - - if (isDynamic && resultTy.getRank() != 1) { - (void)rewriter.notifyMatchFailure( - loc, "Cannot collapse dynamic dims to more than one dimension"); - return {}; - } - - SmallVector<ReassociationExprs, 4> reassociationMap; - if (!createReassociationMapsForCollapse(rewriter, operandTy.getShape(), - resultTy.getShape(), - reassociationMap, isDynamic)) { - (void)rewriter.notifyMatchFailure( - loc, "tosa.reshape Attempting to collapse into an incompatible shape"); - return {}; - } - - SmallVector<int64_t> intermediateShape; - if (!findIntermediateShape(operandTy.getShape(), resultTy.getShape(), - intermediateShape, isDynamic)) { - (void)rewriter.notifyMatchFailure( - loc, "tosa.reshape Cannot collapse into given shape"); - return {}; - } - return rewriter.create<tensor::CollapseShapeOp>(loc, resultTy, operand, - reassociationMap); +// Create a tensor.collapse_shape op that reshapes the input into the given +// result type. +Value createCollapse(OpBuilder &builder, Location loc, TensorType resultType, + Value input) { + auto reassociationMap = + createReassociationMapForCollapse(builder, input.getType(), resultType); + return builder.createOrFold<tensor::CollapseShapeOp>(loc, resultType, input, + reassociationMap); } -Value createExpand(ConversionPatternRewriter &rewriter, Location loc, - ShapedType resultTy, Value operand) { - ShapedType operandTy = cast<ShapedType>(operand.getType()); - if (resultTy == operandTy) - return operand; - - bool isDynamic = !operandTy.hasStaticShape(); - - if (isDynamic && operandTy.getRank() != 1) { - (void)rewriter.notifyMatchFailure( - loc, "Cannot expand dynamic dims from more than one dimension"); - return {}; - } - - SmallVector<ReassociationExprs, 4> reassociationMap; - if (!createReassociationMapsForCollapse(rewriter, resultTy.getShape(), - operandTy.getShape(), - reassociationMap, isDynamic)) { - (void)rewriter.notifyMatchFailure( - loc, "tosa.reshape Attempting to expand into an incompatible shape"); - return {}; - } - - SmallVector<int64_t> intermediateShape; - if (!findIntermediateShape(operandTy.getShape(), resultTy.getShape(), - intermediateShape, isDynamic) || - intermediateShape != operandTy.getShape()) { - (void)rewriter.notifyMatchFailure( - loc, "tosa.reshape Cannot expand into given shape"); - return {}; - } - return rewriter.create<tensor::ExpandShapeOp>(loc, resultTy, operand, - reassociationMap); +// Create a tensor.expand_shape op that reshapes the input into the given result +// type. +Value createExpand(OpBuilder &builder, Location loc, TensorType resultType, + Value input) { + auto reassociationMap = + createReassociationMapForCollapse(builder, resultType, input.getType()); + return builder.createOrFold<tensor::ExpandShapeOp>(loc, resultType, input, + reassociationMap); } -class ReshapeConverterCollapseExpand - : public OpConversionPattern<tosa::ReshapeOp> { +class ReshapeConverter : public OpConversionPattern<tosa::ReshapeOp> { public: using OpConversionPattern<tosa::ReshapeOp>::OpConversionPattern; LogicalResult matchAndRewrite(tosa::ReshapeOp reshape, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const final { - ShapedType operandTy = cast<ShapedType>(adaptor.getInput1().getType()); - ShapedType resultTy = cast<ShapedType>(reshape.getType()); - bool isDynamic = !operandTy.hasStaticShape(); - - SmallVector<int64_t> intermediateShape; - if (!findIntermediateShape(resultTy.getShape(), operandTy.getShape(), - intermediateShape, isDynamic)) { - return rewriter.notifyMatchFailure( - reshape, "tosa.reshape Cannot identify an intermediate shape between " - "the given two shapes"); - } - auto intermediateTy = RankedTensorType::get( - intermediateShape, reshape.getType().getElementType()); - - Value collapse = createCollapse(rewriter, reshape.getLoc(), intermediateTy, - adaptor.getInput1()); - if (!collapse) - return failure(); - - Value expand = createExpand(rewriter, reshape.getLoc(), resultTy, collapse); - if (!expand) - return failure(); - - rewriter.replaceOp(reshape, expand); + auto loc = reshape.getLoc(); + auto resultType = reshape.getResult().getType(); + auto input = reshape.getInput1(); + auto newShape = reshape.getNewShape(); + + // Infer all intermediate types + auto inputType = inferReshapeInputType(input, newShape); + auto expandedType = inferReshapeExpandedType(inputType, newShape); + auto collapsedType = inferReshapeCollapsedType(inputType, expandedType); + + // Cast input if needed + auto castInput = rewriter.createOrFold<tensor::CastOp>(loc, inputType, input); + + // Emit collaspe-expand pair + auto collapsed = createCollapse(rewriter, loc, collapsedType, castInput); + auto expanded = createExpand(rewriter, loc, expandedType, collapsed); + + // Cast to final result type if needed + auto result = rewriter.createOrFold<tensor::CastOp>(loc, resultType, expanded); + rewriter.replaceOp(reshape, result); return success(); } }; @@ -416,8 +430,10 @@ struct ConcatConverter : public OpConversionPattern<tosa::ConcatOp> { void mlir::tosa::populateTosaToTensorConversionPatterns( RewritePatternSet *patterns) { - patterns->add<SliceConverter, PadConverter, ConcatConverter>( - patterns->getContext()); - - patterns->add<ReshapeConverterCollapseExpand>(patterns->getContext()); + patterns->add< + ConcatConverter, + PadConverter, + ReshapeConverter, + SliceConverter + >(patterns->getContext()); } diff --git a/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp b/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp index 85fb8a539912f776e0eb8f3bbfb9cbdab36a2197..399c0450824ee5e790af32440e3bb4e1b6d65270 100644 --- a/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp +++ b/mlir/lib/Conversion/VectorToGPU/VectorToGPU.cpp @@ -202,9 +202,7 @@ template <typename ExtOpTy> static bool integerExtendSupportsMMAMatrixType(ExtOpTy extOp) { if (!isa<vector::TransferReadOp>(extOp.getOperand().getDefiningOp())) return false; - return llvm::all_of(extOp->getUsers(), [](Operation *user) { - return isa<vector::ContractionOp>(user); - }); + return llvm::all_of(extOp->getUsers(), llvm::IsaPred<vector::ContractionOp>); } static bool fpExtendSupportsMMAMatrixType(arith::ExtFOp extOp) { return true; } @@ -345,15 +343,13 @@ getSliceContract(Operation *op, static SetVector<Operation *> getOpToConvert(mlir::Operation *op, bool useNvGpu) { auto hasVectorDest = [](Operation *op) { - return llvm::any_of(op->getResultTypes(), - [](Type t) { return isa<VectorType>(t); }); + return llvm::any_of(op->getResultTypes(), llvm::IsaPred<VectorType>); }; BackwardSliceOptions backwardSliceOptions; backwardSliceOptions.filter = hasVectorDest; auto hasVectorSrc = [](Operation *op) { - return llvm::any_of(op->getOperandTypes(), - [](Type t) { return isa<VectorType>(t); }); + return llvm::any_of(op->getOperandTypes(), llvm::IsaPred<VectorType>); }; ForwardSliceOptions forwardSliceOptions; forwardSliceOptions.filter = hasVectorSrc; diff --git a/mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp b/mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp index 1ba0bc8b6bfbe5e86ed992da7029783e8b597bc6..69b3d41e17c2d409891935aa7e1c343b0fc252b8 100644 --- a/mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp +++ b/mlir/lib/Dialect/Affine/Analysis/AffineAnalysis.cpp @@ -17,7 +17,6 @@ #include "mlir/Dialect/Affine/Analysis/Utils.h" #include "mlir/Dialect/Affine/IR/AffineOps.h" #include "mlir/Dialect/Affine/IR/AffineValueMap.h" -#include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/IR/AffineExprVisitor.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/IntegerSet.h" @@ -137,8 +136,7 @@ static bool isLocallyDefined(Value v, Operation *enclosingOp) { bool mlir::affine::isLoopMemoryParallel(AffineForOp forOp) { // Any memref-typed iteration arguments are treated as serializing. - if (llvm::any_of(forOp.getResultTypes(), - [](Type type) { return isa<BaseMemRefType>(type); })) + if (llvm::any_of(forOp.getResultTypes(), llvm::IsaPred<BaseMemRefType>)) return false; // Collect all load and store ops in loop nest rooted at 'forOp'. diff --git a/mlir/lib/Dialect/Affine/Analysis/LoopAnalysis.cpp b/mlir/lib/Dialect/Affine/Analysis/LoopAnalysis.cpp index fc0515ba95f4fe9eb4af5229915ed7b137384a58..1c28d6b00b3c81146d46636c5a05f73cede345a1 100644 --- a/mlir/lib/Dialect/Affine/Analysis/LoopAnalysis.cpp +++ b/mlir/lib/Dialect/Affine/Analysis/LoopAnalysis.cpp @@ -145,45 +145,36 @@ uint64_t mlir::affine::getLargestDivisorOfTripCount(AffineForOp forOp) { return *gcd; } -/// Given an induction variable `iv` of type AffineForOp and an access `index` -/// of type index, returns `true` if `index` is independent of `iv` and -/// false otherwise. The determination supports composition with at most one -/// AffineApplyOp. The 'at most one AffineApplyOp' comes from the fact that -/// the composition of AffineApplyOp needs to be canonicalized by construction -/// to avoid writing code that composes arbitrary numbers of AffineApplyOps -/// everywhere. To achieve this, at the very least, the compose-affine-apply -/// pass must have been run. +/// Given an affine.for `iv` and an access `index` of type index, returns `true` +/// if `index` is independent of `iv` and false otherwise. /// -/// Prerequisites: -/// 1. `iv` and `index` of the proper type; -/// 2. at most one reachable AffineApplyOp from index; -/// -/// Returns false in cases with more than one AffineApplyOp, this is -/// conservative. +/// Prerequisites: `iv` and `index` of the proper type; static bool isAccessIndexInvariant(Value iv, Value index) { - assert(isAffineForInductionVar(iv) && "iv must be a AffineForOp"); - assert(isa<IndexType>(index.getType()) && "index must be of IndexType"); - SmallVector<Operation *, 4> affineApplyOps; - getReachableAffineApplyOps({index}, affineApplyOps); - - if (affineApplyOps.empty()) { - // Pointer equality test because of Value pointer semantics. - return index != iv; - } - - if (affineApplyOps.size() > 1) { - affineApplyOps[0]->emitRemark( - "CompositionAffineMapsPass must have been run: there should be at most " - "one AffineApplyOp, returning false conservatively."); - return false; - } + assert(isAffineForInductionVar(iv) && "iv must be an affine.for iv"); + assert(isa<IndexType>(index.getType()) && "index must be of 'index' type"); + auto map = AffineMap::getMultiDimIdentityMap(/*numDims=*/1, iv.getContext()); + SmallVector<Value> operands = {index}; + AffineValueMap avm(map, operands); + avm.composeSimplifyAndCanonicalize(); + return !avm.isFunctionOf(0, iv); +} - auto composeOp = cast<AffineApplyOp>(affineApplyOps[0]); - // We need yet another level of indirection because the `dim` index of the - // access may not correspond to the `dim` index of composeOp. - return !composeOp.getAffineValueMap().isFunctionOf(0, iv); +// Pre-requisite: Loop bounds should be in canonical form. +template <typename LoadOrStoreOp> +bool mlir::affine::isInvariantAccess(LoadOrStoreOp memOp, AffineForOp forOp) { + AffineValueMap avm(memOp.getAffineMap(), memOp.getMapOperands()); + avm.composeSimplifyAndCanonicalize(); + return !llvm::is_contained(avm.getOperands(), forOp.getInductionVar()); } +// Explicitly instantiate the template so that the compiler knows we need them. +template bool mlir::affine::isInvariantAccess(AffineReadOpInterface, + AffineForOp); +template bool mlir::affine::isInvariantAccess(AffineWriteOpInterface, + AffineForOp); +template bool mlir::affine::isInvariantAccess(AffineLoadOp, AffineForOp); +template bool mlir::affine::isInvariantAccess(AffineStoreOp, AffineForOp); + DenseSet<Value> mlir::affine::getInvariantAccesses(Value iv, ArrayRef<Value> indices) { DenseSet<Value> res; diff --git a/mlir/lib/Dialect/Affine/IR/AffineOps.cpp b/mlir/lib/Dialect/Affine/IR/AffineOps.cpp index 8a070d256398701557e0add14a1c70eed1793bb6..c591e5056480ca0800e74aa2ee01266c87e03d62 100644 --- a/mlir/lib/Dialect/Affine/IR/AffineOps.cpp +++ b/mlir/lib/Dialect/Affine/IR/AffineOps.cpp @@ -17,6 +17,7 @@ #include "mlir/IR/OpDefinition.h" #include "mlir/IR/PatternMatch.h" #include "mlir/Interfaces/ShapedOpInterfaces.h" +#include "mlir/Interfaces/ValueBoundsOpInterface.h" #include "mlir/Support/MathExtras.h" #include "mlir/Transforms/InliningUtils.h" #include "llvm/ADT/ScopeExit.h" @@ -220,6 +221,8 @@ void AffineDialect::initialize() { #include "mlir/Dialect/Affine/IR/AffineOps.cpp.inc" >(); addInterfaces<AffineInlinerInterface>(); + declarePromisedInterfaces<ValueBoundsOpInterface, AffineApplyOp, AffineMaxOp, + AffineMinOp>(); } /// Materialize a single constant operation from a given attribute value with diff --git a/mlir/lib/Dialect/Affine/IR/AffineValueMap.cpp b/mlir/lib/Dialect/Affine/IR/AffineValueMap.cpp index 2800237fd05ac6d2c91733705acaee4154c6d4e6..6a52849186872e013a4ddfcb3d5ff3316d3a09d6 100644 --- a/mlir/lib/Dialect/Affine/IR/AffineValueMap.cpp +++ b/mlir/lib/Dialect/Affine/IR/AffineValueMap.cpp @@ -24,6 +24,15 @@ void AffineValueMap::reset(AffineMap map, ValueRange operands, this->results.assign(results.begin(), results.end()); } +void AffineValueMap::composeSimplifyAndCanonicalize() { + AffineMap sMap = getAffineMap(); + fullyComposeAffineMapAndOperands(&sMap, &operands); + // Full composition also canonicalizes and simplifies before returning. We + // need to canonicalize once more to drop unused operands. + canonicalizeMapAndOperands(&sMap, &operands); + this->map.reset(sMap); +} + void AffineValueMap::difference(const AffineValueMap &a, const AffineValueMap &b, AffineValueMap *res) { assert(a.getNumResults() == b.getNumResults() && "invalid inputs"); diff --git a/mlir/lib/Dialect/Affine/TransformOps/AffineTransformOps.cpp b/mlir/lib/Dialect/Affine/TransformOps/AffineTransformOps.cpp index 0b4570c65c515492c84421b4a79df9e79c0a4b94..e8bfd4421f5ca4cfd753867d2651c96404927af8 100644 --- a/mlir/lib/Dialect/Affine/TransformOps/AffineTransformOps.cpp +++ b/mlir/lib/Dialect/Affine/TransformOps/AffineTransformOps.cpp @@ -13,7 +13,7 @@ #include "mlir/Dialect/Affine/IR/AffineValueMap.h" #include "mlir/Dialect/Affine/LoopUtils.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" using namespace mlir; diff --git a/mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp b/mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp index 46c7871f40232fea514c4a2dd50d835ccc0f32f1..71e9648a5e00fab42cc4bac2a39ec7268a2ad86c 100644 --- a/mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp +++ b/mlir/lib/Dialect/Affine/Transforms/SuperVectorize.cpp @@ -609,9 +609,8 @@ makePattern(const DenseSet<Operation *> ¶llelLoops, int vectorRank, } static NestedPattern &vectorTransferPattern() { - static auto pattern = affine::matcher::Op([](Operation &op) { - return isa<vector::TransferReadOp, vector::TransferWriteOp>(op); - }); + static auto pattern = affine::matcher::Op( + llvm::IsaPred<vector::TransferReadOp, vector::TransferWriteOp>); return pattern; } diff --git a/mlir/lib/Dialect/Affine/Utils/LoopFusionUtils.cpp b/mlir/lib/Dialect/Affine/Utils/LoopFusionUtils.cpp index fb45528ad5e7d18cac1a6fa31344a0ce8daf23f0..84ae4b52dcf4e8f1ab2e19fa3133705a704f1c24 100644 --- a/mlir/lib/Dialect/Affine/Utils/LoopFusionUtils.cpp +++ b/mlir/lib/Dialect/Affine/Utils/LoopFusionUtils.cpp @@ -211,8 +211,7 @@ static unsigned getMaxLoopDepth(ArrayRef<Operation *> srcOps, unsigned loopDepth = getInnermostCommonLoopDepth(targetDstOps); // Return common loop depth for loads if there are no store ops. - if (all_of(targetDstOps, - [&](Operation *op) { return isa<AffineReadOpInterface>(op); })) + if (all_of(targetDstOps, llvm::IsaPred<AffineReadOpInterface>)) return loopDepth; // Check dependences on all pairs of ops in 'targetDstOps' and store the diff --git a/mlir/lib/Dialect/Affine/Utils/Utils.cpp b/mlir/lib/Dialect/Affine/Utils/Utils.cpp index 3dc5539cde3d989fb88a0b02c98d9d229a0ad175..8b8ed2578ca5cc8b18c4ccf1445a4d8206000368 100644 --- a/mlir/lib/Dialect/Affine/Utils/Utils.cpp +++ b/mlir/lib/Dialect/Affine/Utils/Utils.cpp @@ -1792,8 +1792,7 @@ MemRefType mlir::affine::normalizeMemRefType(MemRefType memrefType) { MLIRContext *context = memrefType.getContext(); for (unsigned d = 0; d < newRank; ++d) { // Check if this dimension is dynamic. - if (bool isDynDim = - isNormalizedMemRefDynamicDim(d, layoutMap, memrefTypeDynDims)) { + if (isNormalizedMemRefDynamicDim(d, layoutMap, memrefTypeDynDims)) { newShape[d] = ShapedType::kDynamic; continue; } diff --git a/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td b/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td index 11c4a29718e1d964dd8b001a5468a03e8caa4a16..caca2ff81964f736cf5dc293a7c02a600c9d6061 100644 --- a/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td +++ b/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td @@ -253,9 +253,6 @@ def CmpIExtUI : // SelectOp //===----------------------------------------------------------------------===// -def GetScalarOrVectorTrueAttribute : - NativeCodeCall<"cast<TypedAttr>(getBoolAttribute($0.getType(), true))">; - // select(not(pred), a, b) => select(pred, b, a) def SelectNotCond : Pat<(SelectOp (Arith_XOrIOp $pred, (ConstantLikeMatcher APIntAttr:$ones)), $a, $b), @@ -272,31 +269,12 @@ def RedundantSelectFalse : Pat<(SelectOp $pred, $a, (SelectOp $pred, $b, $c)), (SelectOp $pred, $a, $c)>; -// select(predA, select(predB, x, y), y) => select(and(predA, predB), x, y) -def SelectAndCond : - Pat<(SelectOp $predA, (SelectOp $predB, $x, $y), $y), - (SelectOp (Arith_AndIOp $predA, $predB), $x, $y)>; - -// select(predA, select(predB, y, x), y) => select(and(predA, not(predB)), x, y) -def SelectAndNotCond : - Pat<(SelectOp $predA, (SelectOp $predB, $y, $x), $y), - (SelectOp (Arith_AndIOp $predA, - (Arith_XOrIOp $predB, - (Arith_ConstantOp (GetScalarOrVectorTrueAttribute $predB)))), - $x, $y)>; - -// select(predA, x, select(predB, x, y)) => select(or(predA, predB), x, y) -def SelectOrCond : - Pat<(SelectOp $predA, $x, (SelectOp $predB, $x, $y)), - (SelectOp (Arith_OrIOp $predA, $predB), $x, $y)>; - -// select(predA, x, select(predB, y, x)) => select(or(predA, not(predB)), x, y) -def SelectOrNotCond : - Pat<(SelectOp $predA, $x, (SelectOp $predB, $y, $x)), - (SelectOp (Arith_OrIOp $predA, - (Arith_XOrIOp $predB, - (Arith_ConstantOp (GetScalarOrVectorTrueAttribute $predB)))), - $x, $y)>; +// select(pred, false, true) => not(pred) +def SelectI1ToNot : + Pat<(SelectOp $pred, + (ConstantLikeMatcher ConstantAttr<I1Attr, "0">), + (ConstantLikeMatcher ConstantAttr<I1Attr, "1">)), + (Arith_XOrIOp $pred, (Arith_ConstantOp ConstantAttr<I1Attr, "1">))>; //===----------------------------------------------------------------------===// // IndexCastOp diff --git a/mlir/lib/Dialect/Arith/IR/ArithDialect.cpp b/mlir/lib/Dialect/Arith/IR/ArithDialect.cpp index 745c5706a838cec18b54e47581632329da27aa3c..042acf61009000116d3c41cade1063f334164b5f 100644 --- a/mlir/lib/Dialect/Arith/IR/ArithDialect.cpp +++ b/mlir/lib/Dialect/Arith/IR/ArithDialect.cpp @@ -8,9 +8,12 @@ #include "mlir/Conversion/ConvertToLLVM/ToLLVMInterface.h" #include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h" +#include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h" #include "mlir/Dialect/UB/IR/UBOps.h" #include "mlir/IR/Builders.h" #include "mlir/IR/DialectImplementation.h" +#include "mlir/Interfaces/ValueBoundsOpInterface.h" #include "mlir/Transforms/InliningUtils.h" #include "llvm/ADT/TypeSwitch.h" @@ -45,7 +48,13 @@ void arith::ArithDialect::initialize() { #include "mlir/Dialect/Arith/IR/ArithOpsAttributes.cpp.inc" >(); addInterfaces<ArithInlinerInterface>(); - declarePromisedInterface<ArithDialect, ConvertToLLVMPatternInterface>(); + declarePromisedInterface<ConvertToLLVMPatternInterface, ArithDialect>(); + declarePromisedInterface<bufferization::BufferDeallocationOpInterface, + SelectOp>(); + declarePromisedInterfaces<bufferization::BufferizableOpInterface, ConstantOp, + IndexCastOp, SelectOp>(); + declarePromisedInterfaces<ValueBoundsOpInterface, AddIOp, ConstantOp, SubIOp, + MulIOp>(); } /// Materialize an integer or floating point constant. diff --git a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp index 0f71c19c23b654853f98d2f7b99ba7fe762ea031..ce0602c853e3c32f24903c8041c959f29e16f480 100644 --- a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp +++ b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp @@ -91,6 +91,29 @@ arith::CmpIPredicate arith::invertPredicate(arith::CmpIPredicate pred) { llvm_unreachable("unknown cmpi predicate kind"); } +/// Equivalent to +/// convertRoundingModeToLLVM(convertArithRoundingModeToLLVM(roundingMode)). +/// +/// Not possible to implement as chain of calls as this would introduce a +/// circular dependency with MLIRArithAttrToLLVMConversion and make arith depend +/// on the LLVM dialect and on translation to LLVM. +static llvm::RoundingMode +convertArithRoundingModeToLLVMIR(RoundingMode roundingMode) { + switch (roundingMode) { + case RoundingMode::downward: + return llvm::RoundingMode::TowardNegative; + case RoundingMode::to_nearest_away: + return llvm::RoundingMode::NearestTiesToAway; + case RoundingMode::to_nearest_even: + return llvm::RoundingMode::NearestTiesToEven; + case RoundingMode::toward_zero: + return llvm::RoundingMode::TowardZero; + case RoundingMode::upward: + return llvm::RoundingMode::TowardPositive; + } + llvm_unreachable("Unhandled rounding mode"); +} + static arith::CmpIPredicateAttr invertPredicate(arith::CmpIPredicateAttr pred) { return arith::CmpIPredicateAttr::get(pred.getContext(), invertPredicate(pred.getValue())); @@ -434,9 +457,7 @@ arith::MulSIExtendedOp::fold(FoldAdaptor adaptor, // Invoke the constant fold helper again to calculate the 'high' result. Attribute highAttr = constFoldBinaryOp<IntegerAttr>( adaptor.getOperands(), [](const APInt &a, const APInt &b) { - unsigned bitWidth = a.getBitWidth(); - APInt fullProduct = a.sext(bitWidth * 2) * b.sext(bitWidth * 2); - return fullProduct.extractBits(bitWidth, bitWidth); + return llvm::APIntOps::mulhs(a, b); }); assert(highAttr && "Unexpected constant-folding failure"); @@ -491,9 +512,7 @@ arith::MulUIExtendedOp::fold(FoldAdaptor adaptor, // Invoke the constant fold helper again to calculate the 'high' result. Attribute highAttr = constFoldBinaryOp<IntegerAttr>( adaptor.getOperands(), [](const APInt &a, const APInt &b) { - unsigned bitWidth = a.getBitWidth(); - APInt fullProduct = a.zext(bitWidth * 2) * b.zext(bitWidth * 2); - return fullProduct.extractBits(bitWidth, bitWidth); + return llvm::APIntOps::mulhu(a, b); }); assert(highAttr && "Unexpected constant-folding failure"); @@ -689,43 +708,17 @@ OpFoldResult arith::FloorDivSIOp::fold(FoldAdaptor adaptor) { return getLhs(); // Don't fold if it would overflow or if it requires a division by zero. - bool overflowOrDiv0 = false; + bool overflowOrDiv = false; auto result = constFoldBinaryOp<IntegerAttr>( adaptor.getOperands(), [&](APInt a, const APInt &b) { - if (overflowOrDiv0 || !b) { - overflowOrDiv0 = true; + if (b.isZero()) { + overflowOrDiv = true; return a; } - if (!a) - return a; - // After this point we know that neither a or b are zero. - unsigned bits = a.getBitWidth(); - APInt zero = APInt::getZero(bits); - bool aGtZero = a.sgt(zero); - bool bGtZero = b.sgt(zero); - if (aGtZero && bGtZero) { - // Both positive, return a / b. - return a.sdiv_ov(b, overflowOrDiv0); - } - if (!aGtZero && !bGtZero) { - // Both negative, return -a / -b. - APInt posA = zero.ssub_ov(a, overflowOrDiv0); - APInt posB = zero.ssub_ov(b, overflowOrDiv0); - return posA.sdiv_ov(posB, overflowOrDiv0); - } - if (!aGtZero && bGtZero) { - // A is negative, b is positive, return - ceil(-a, b). - APInt posA = zero.ssub_ov(a, overflowOrDiv0); - APInt ceil = signedCeilNonnegInputs(posA, b, overflowOrDiv0); - return zero.ssub_ov(ceil, overflowOrDiv0); - } - // A is positive, b is negative, return - ceil(a, -b). - APInt posB = zero.ssub_ov(b, overflowOrDiv0); - APInt ceil = signedCeilNonnegInputs(a, posB, overflowOrDiv0); - return zero.ssub_ov(ceil, overflowOrDiv0); + return a.sfloordiv_ov(b, overflowOrDiv); }); - return overflowOrDiv0 ? Attribute() : result; + return overflowOrDiv ? Attribute() : result; } //===----------------------------------------------------------------------===// @@ -969,7 +962,6 @@ OpFoldResult arith::MaxNumFOp::fold(FoldAdaptor adaptor) { [](const APFloat &a, const APFloat &b) { return llvm::maximum(a, b); }); } - //===----------------------------------------------------------------------===// // MaxSIOp //===----------------------------------------------------------------------===// @@ -1260,13 +1252,12 @@ static bool checkWidthChangeCast(TypeRange inputs, TypeRange outputs) { } /// Attempts to convert `sourceValue` to an APFloat value with -/// `targetSemantics`, without any information loss or rounding. -static FailureOr<APFloat> -convertFloatValue(APFloat sourceValue, - const llvm::fltSemantics &targetSemantics) { +/// `targetSemantics` and `roundingMode`, without any information loss. +static FailureOr<APFloat> convertFloatValue( + APFloat sourceValue, const llvm::fltSemantics &targetSemantics, + llvm::RoundingMode roundingMode = llvm::RoundingMode::NearestTiesToEven) { bool losesInfo = false; - auto status = sourceValue.convert( - targetSemantics, llvm::RoundingMode::NearestTiesToEven, &losesInfo); + auto status = sourceValue.convert(targetSemantics, roundingMode, &losesInfo); if (losesInfo || status != APFloat::opOK) return failure(); @@ -1418,15 +1409,19 @@ LogicalResult arith::TruncIOp::verify() { //===----------------------------------------------------------------------===// /// Perform safe const propagation for truncf, i.e., only propagate if FP value -/// can be represented without precision loss or rounding. This is because the -/// semantics of `arith.truncf` do not assume a specific rounding mode. +/// can be represented without precision loss. OpFoldResult arith::TruncFOp::fold(FoldAdaptor adaptor) { auto resElemType = cast<FloatType>(getElementTypeOrSelf(getType())); const llvm::fltSemantics &targetSemantics = resElemType.getFloatSemantics(); return constFoldCastOp<FloatAttr, FloatAttr>( adaptor.getOperands(), getType(), - [&targetSemantics](const APFloat &a, bool &castStatus) { - FailureOr<APFloat> result = convertFloatValue(a, targetSemantics); + [this, &targetSemantics](const APFloat &a, bool &castStatus) { + RoundingMode roundingMode = + getRoundingmode().value_or(RoundingMode::to_nearest_even); + llvm::RoundingMode llvmRoundingMode = + convertArithRoundingModeToLLVMIR(roundingMode); + FailureOr<APFloat> result = + convertFloatValue(a, targetSemantics, llvmRoundingMode); if (failed(result)) { castStatus = false; return a; @@ -2173,35 +2168,6 @@ void arith::CmpFOp::getCanonicalizationPatterns(RewritePatternSet &patterns, // SelectOp //===----------------------------------------------------------------------===// -// Transforms a select of a boolean to arithmetic operations -// -// arith.select %arg, %x, %y : i1 -// -// becomes -// -// and(%arg, %x) or and(!%arg, %y) -struct SelectI1Simplify : public OpRewritePattern<arith::SelectOp> { - using OpRewritePattern<arith::SelectOp>::OpRewritePattern; - - LogicalResult matchAndRewrite(arith::SelectOp op, - PatternRewriter &rewriter) const override { - if (!op.getType().isInteger(1)) - return failure(); - - Value falseConstant = - rewriter.create<arith::ConstantIntOp>(op.getLoc(), true, 1); - Value notCondition = rewriter.create<arith::XOrIOp>( - op.getLoc(), op.getCondition(), falseConstant); - - Value trueVal = rewriter.create<arith::AndIOp>( - op.getLoc(), op.getCondition(), op.getTrueValue()); - Value falseVal = rewriter.create<arith::AndIOp>(op.getLoc(), notCondition, - op.getFalseValue()); - rewriter.replaceOpWithNewOp<arith::OrIOp>(op, trueVal, falseVal); - return success(); - } -}; - // select %arg, %c1, %c0 => extui %arg struct SelectToExtUI : public OpRewritePattern<arith::SelectOp> { using OpRewritePattern<arith::SelectOp>::OpRewritePattern; @@ -2238,9 +2204,8 @@ struct SelectToExtUI : public OpRewritePattern<arith::SelectOp> { void arith::SelectOp::getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) { - results.add<RedundantSelectFalse, RedundantSelectTrue, SelectI1Simplify, - SelectAndCond, SelectAndNotCond, SelectOrCond, SelectOrNotCond, - SelectNotCond, SelectToExtUI>(context); + results.add<RedundantSelectFalse, RedundantSelectTrue, SelectNotCond, + SelectI1ToNot, SelectToExtUI>(context); } OpFoldResult arith::SelectOp::fold(FoldAdaptor adaptor) { diff --git a/mlir/lib/Dialect/Arith/Transforms/BufferViewFlowOpInterfaceImpl.cpp b/mlir/lib/Dialect/Arith/Transforms/BufferViewFlowOpInterfaceImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9df9df86b64fb58a75a48c31c60b7307f58cb21f --- /dev/null +++ b/mlir/lib/Dialect/Arith/Transforms/BufferViewFlowOpInterfaceImpl.cpp @@ -0,0 +1,44 @@ +//===- BufferViewFlowOpInterfaceImpl.cpp - Buffer View Flow Analysis ------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "mlir/Dialect/Arith/Transforms/BufferViewFlowOpInterfaceImpl.h" + +#include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.h" + +using namespace mlir; +using namespace mlir::bufferization; + +namespace mlir { +namespace arith { +namespace { + +struct SelectOpInterface + : public BufferViewFlowOpInterface::ExternalModel<SelectOpInterface, + SelectOp> { + void + populateDependencies(Operation *op, + RegisterDependenciesFn registerDependenciesFn) const { + auto selectOp = cast<SelectOp>(op); + + // Either one of the true/false value may be selected at runtime. + registerDependenciesFn(selectOp.getTrueValue(), selectOp.getResult()); + registerDependenciesFn(selectOp.getFalseValue(), selectOp.getResult()); + } +}; + +} // namespace +} // namespace arith +} // namespace mlir + +void arith::registerBufferViewFlowOpInterfaceExternalModels( + DialectRegistry ®istry) { + registry.addExtension(+[](MLIRContext *ctx, arith::ArithDialect *dialect) { + SelectOp::attachInterface<SelectOpInterface>(*ctx); + }); +} diff --git a/mlir/lib/Dialect/Arith/Transforms/CMakeLists.txt b/mlir/lib/Dialect/Arith/Transforms/CMakeLists.txt index 02240601bcd35a113c7d662ff3639c8856e62ae6..12659eaba1fa5effa966ef267dd44daffcb2ed93 100644 --- a/mlir/lib/Dialect/Arith/Transforms/CMakeLists.txt +++ b/mlir/lib/Dialect/Arith/Transforms/CMakeLists.txt @@ -2,6 +2,7 @@ add_mlir_dialect_library(MLIRArithTransforms BufferDeallocationOpInterfaceImpl.cpp BufferizableOpInterfaceImpl.cpp Bufferize.cpp + BufferViewFlowOpInterfaceImpl.cpp EmulateUnsupportedFloats.cpp EmulateWideInt.cpp EmulateNarrowType.cpp diff --git a/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp b/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp index 7f246daf99ff3cc9d6b677a670eb95fae321c50e..dd04a5996558945abdc1d20b0b8d1a8557225de9 100644 --- a/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp +++ b/mlir/lib/Dialect/Arith/Transforms/ExpandOps.cpp @@ -110,9 +110,13 @@ struct CeilDivSIOpConverter : public OpRewritePattern<arith::CeilDivSIOp> { } }; -/// Expands FloorDivSIOp (n, m) into -/// 1) x = (m<0) ? 1 : -1 -/// 2) return (n*m<0) ? - ((-n+x) / m) -1 : n / m +/// Expands FloorDivSIOp (x, y) into +/// z = x / y +/// if (z * y != x && (x < 0) != (y < 0)) { +/// return z - 1; +/// } else { +/// return z; +/// } struct FloorDivSIOpConverter : public OpRewritePattern<arith::FloorDivSIOp> { using OpRewritePattern::OpRewritePattern; LogicalResult matchAndRewrite(arith::FloorDivSIOp op, @@ -121,41 +125,29 @@ struct FloorDivSIOpConverter : public OpRewritePattern<arith::FloorDivSIOp> { Type type = op.getType(); Value a = op.getLhs(); Value b = op.getRhs(); - Value plusOne = createConst(loc, type, 1, rewriter); + + Value quotient = rewriter.create<arith::DivSIOp>(loc, a, b); + Value product = rewriter.create<arith::MulIOp>(loc, quotient, b); + Value notEqualDivisor = rewriter.create<arith::CmpIOp>( + loc, arith::CmpIPredicate::ne, a, product); Value zero = createConst(loc, type, 0, rewriter); - Value minusOne = createConst(loc, type, -1, rewriter); - // Compute x = (b<0) ? 1 : -1. - Value compare = - rewriter.create<arith::CmpIOp>(loc, arith::CmpIPredicate::slt, b, zero); - Value x = rewriter.create<arith::SelectOp>(loc, compare, plusOne, minusOne); - // Compute negative res: -1 - ((x-a)/b). - Value xMinusA = rewriter.create<arith::SubIOp>(loc, x, a); - Value xMinusADivB = rewriter.create<arith::DivSIOp>(loc, xMinusA, b); - Value negRes = rewriter.create<arith::SubIOp>(loc, minusOne, xMinusADivB); - // Compute positive res: a/b. - Value posRes = rewriter.create<arith::DivSIOp>(loc, a, b); - // Result is (a*b<0) ? negative result : positive result. - // Note, we want to avoid using a*b because of possible overflow. - // The case that matters are a>0, a==0, a<0, b>0 and b<0. We do - // not particuliarly care if a*b<0 is true or false when b is zero - // as this will result in an illegal divide. So `a*b<0` can be reformulated - // as `(a>0 && b<0) || (a>0 && b<0)' or `(a>0 && b<0) || (a>0 && b<=0)'. - // We pick the first expression here. + Value aNeg = rewriter.create<arith::CmpIOp>(loc, arith::CmpIPredicate::slt, a, zero); - Value aPos = - rewriter.create<arith::CmpIOp>(loc, arith::CmpIPredicate::sgt, a, zero); Value bNeg = rewriter.create<arith::CmpIOp>(loc, arith::CmpIPredicate::slt, b, zero); - Value bPos = - rewriter.create<arith::CmpIOp>(loc, arith::CmpIPredicate::sgt, b, zero); - Value firstTerm = rewriter.create<arith::AndIOp>(loc, aNeg, bPos); - Value secondTerm = rewriter.create<arith::AndIOp>(loc, aPos, bNeg); - Value compareRes = - rewriter.create<arith::OrIOp>(loc, firstTerm, secondTerm); - // Perform substitution and return success. - rewriter.replaceOpWithNewOp<arith::SelectOp>(op, compareRes, negRes, - posRes); + + Value signOpposite = rewriter.create<arith::CmpIOp>( + loc, arith::CmpIPredicate::ne, aNeg, bNeg); + Value cond = + rewriter.create<arith::AndIOp>(loc, notEqualDivisor, signOpposite); + + Value minusOne = createConst(loc, type, -1, rewriter); + Value quotientMinusOne = + rewriter.create<arith::AddIOp>(loc, quotient, minusOne); + + rewriter.replaceOpWithNewOp<arith::SelectOp>(op, cond, quotientMinusOne, + quotient); return success(); } }; @@ -261,6 +253,11 @@ struct BFloat16TruncFOpConverter : public OpRewritePattern<arith::TruncFOp> { return rewriter.notifyMatchFailure(op, "not a trunc of f32 to bf16."); } + if (op.getRoundingmodeAttr()) { + return rewriter.notifyMatchFailure( + op, "only applicable to default rounding mode."); + } + Type i16Ty = b.getI16Type(); Type i32Ty = b.getI32Type(); Type f32Ty = b.getF32Type(); diff --git a/mlir/lib/Dialect/Arith/Transforms/UnsignedWhenEquivalent.cpp b/mlir/lib/Dialect/Arith/Transforms/UnsignedWhenEquivalent.cpp index 53f2008324f054ce3c5ee812939228da45ba3cd9..4edce84bafd4160fe0a7a4d6d358229b3b374686 100644 --- a/mlir/lib/Dialect/Arith/Transforms/UnsignedWhenEquivalent.cpp +++ b/mlir/lib/Dialect/Arith/Transforms/UnsignedWhenEquivalent.cpp @@ -125,12 +125,11 @@ struct ArithUnsignedWhenEquivalentPass ConversionTarget target(*ctx); target.addLegalDialect<ArithDialect>(); - target - .addDynamicallyLegalOp<DivSIOp, CeilDivSIOp, CeilDivUIOp, FloorDivSIOp, - RemSIOp, MinSIOp, MaxSIOp, ExtSIOp>( - [&solver](Operation *op) -> std::optional<bool> { - return failed(staticallyNonNegative(solver, op)); - }); + target.addDynamicallyLegalOp<DivSIOp, CeilDivSIOp, FloorDivSIOp, RemSIOp, + MinSIOp, MaxSIOp, ExtSIOp>( + [&solver](Operation *op) -> std::optional<bool> { + return failed(staticallyNonNegative(solver, op)); + }); target.addDynamicallyLegalOp<CmpIOp>( [&solver](CmpIOp op) -> std::optional<bool> { return failed(isCmpIConvertable(solver, op)); diff --git a/mlir/lib/Dialect/ArmNeon/Transforms/LowerContractionToSMMLAPattern.cpp b/mlir/lib/Dialect/ArmNeon/Transforms/LowerContractionToSMMLAPattern.cpp index 47c84708f3c38bf0a617c0dfe4d7a944cb6b0409..1f48d27aa27b170d3d13b51a7f929eb478feea35 100644 --- a/mlir/lib/Dialect/ArmNeon/Transforms/LowerContractionToSMMLAPattern.cpp +++ b/mlir/lib/Dialect/ArmNeon/Transforms/LowerContractionToSMMLAPattern.cpp @@ -16,7 +16,9 @@ #include "mlir/Dialect/ArmNeon/Transforms.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" +#include "mlir/Dialect/Utils/IndexingUtils.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" +#include "mlir/IR/AffineMap.h" #include "mlir/IR/PatternMatch.h" #include "mlir/Support/LogicalResult.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" @@ -36,8 +38,10 @@ static Type matchContainerType(Type element, Type container) { return element; } -/// Lowering from a single vector::contractOp directly to the arm neon smmla -/// intrinsic. The shapes of the contract and intrinsic must match. +/// Lowering from a vector::contractOp arm neon smmla intrinsic. This will tile +/// any vector.contract into multiple smmla instructions with unrolling so long +/// as [2,2,8] is a divisor of its shape. If no unrolling is necessary, a single +/// smmla instruction is emitted. class LowerContractionToSMMLAPattern : public OpRewritePattern<vector::ContractionOp> { public: @@ -45,10 +49,6 @@ public: LogicalResult matchAndRewrite(vector::ContractionOp op, PatternRewriter &rewriter) const override { Location loc = op.getLoc(); - Value lhs = op.getLhs(); - Value rhs = op.getRhs(); - Value res = op.getAcc(); - // Check index maps that represent M N K in contract. auto indexingMaps = op.getIndexingMapsArray(); if (llvm::any_of(indexingMaps, [](mlir::AffineMap affineMap) { @@ -57,7 +57,6 @@ public: })) { return failure(); } - // Check iterator types for contract. auto iteratorTypes = op.getIteratorTypesArray(); if (iteratorTypes.size() != 3 || @@ -66,22 +65,24 @@ public: iteratorTypes[2] != vector::IteratorType::reduction) { return failure(); } - - // Check the tile size by mapping the dimensions of the contract. + // Infer tile sizes from operands; Note: RHS is not transposed. mlir::VectorType lhsType = op.getLhsType(); mlir::VectorType rhsType = op.getRhsType(); auto dimM = lhsType.getDimSize(0); auto dimN = rhsType.getDimSize(0); auto dimK = lhsType.getDimSize(1); - if (rhsType.getDimSize(1) != dimK || dimM != 2 || dimN != 2 || dimK != 8) { + + // Unrolling patterns can handle any [2, 2, 8] shaped multiple of inputs for + // tiling. + if (dimM % 2 != 0 || dimN % 2 != 0 || dimK % 8 != 0) { return failure(); } // Check two extsi inputs Rhs Lhs for contract. arith::ExtSIOp origLhsExtOp = - dyn_cast_or_null<arith::ExtSIOp>(lhs.getDefiningOp()); + dyn_cast_or_null<arith::ExtSIOp>(op.getLhs().getDefiningOp()); arith::ExtSIOp origRhsExtOp = - dyn_cast_or_null<arith::ExtSIOp>(rhs.getDefiningOp()); + dyn_cast_or_null<arith::ExtSIOp>(op.getRhs().getDefiningOp()); if (!origLhsExtOp || !origRhsExtOp) { return failure(); } @@ -113,26 +114,73 @@ public: return failure(); } - // Collapse to 1D vectors required by smmla intrinsic - auto collapsedInputType = VectorType::get( - {16}, extsiLhs.getType().cast<ShapedType>().getElementType()); - auto collapsedOutputType = - VectorType::get({4}, res.getType().cast<ShapedType>().getElementType()); - auto collapsedLhs = rewriter.createOrFold<vector::ShapeCastOp>( - extsiLhs.getLoc(), collapsedInputType, extsiLhs); - auto collapsedRhs = rewriter.createOrFold<vector::ShapeCastOp>( - extsiRhs.getLoc(), collapsedInputType, extsiRhs); - auto collapsedRes = rewriter.createOrFold<vector::ShapeCastOp>( - res.getLoc(), collapsedOutputType, res); - - // Replace the contract with a neon op - auto smmlaOp = rewriter.createOrFold<arm_neon::SmmlaOp>( - op.getLoc(), collapsedRes.getType(), collapsedRes, collapsedLhs, - collapsedRhs); - - // Reshape output back to 2D - rewriter.replaceOpWithNewOp<vector::ShapeCastOp>(op, op.getResultType(), - smmlaOp); + // Initial accumulator for the final result. This is the un-tiled result if + // tiling is done. + Value result = rewriter.create<arith::ConstantOp>( + loc, op.getResultType(), rewriter.getZeroAttr(op.getResultType())); + + SmallVector<int64_t> unrolledSize = *op.getShapeForUnroll(); + SmallVector<int64_t> smmlaShape{2, 2, 8}; + SmallVector<int64_t> loopOrder{0, 1, 2}; + for (SmallVector<int64_t> offsets : + StaticTileOffsetRange(unrolledSize, smmlaShape, loopOrder)) { + + // Helper to compute the new shape of each operand and extract the slice. + auto extractOperand = [&](Value operand, AffineMap permutationMap, + ArrayRef<int64_t> operandOffsets) { + SmallVector<int64_t> operandShape = + applyPermutationMap(permutationMap, ArrayRef<int64_t>(smmlaShape)); + SmallVector<int64_t> operandStrides(operandOffsets.size(), 1); + return rewriter.createOrFold<vector::ExtractStridedSliceOp>( + loc, operand, operandOffsets, operandShape, operandStrides); + }; + + // Extract tiled lhs, rhs, and acc + AffineMap lhsPermutationMap = op.getIndexingMapsArray()[0]; + SmallVector<int64_t> lhsOffsets = + applyPermutationMap(lhsPermutationMap, ArrayRef<int64_t>(offsets)); + Value tiledLhs = extractOperand(extsiLhs, lhsPermutationMap, lhsOffsets); + AffineMap rhsPermutationMap = op.getIndexingMapsArray()[1]; + SmallVector<int64_t> rhsOffsets = + applyPermutationMap(rhsPermutationMap, ArrayRef<int64_t>(offsets)); + Value tiledRhs = extractOperand(extsiRhs, rhsPermutationMap, rhsOffsets); + AffineMap accPermutationMap = op.getIndexingMapsArray()[2]; + SmallVector<int64_t> accOffsets = + applyPermutationMap(accPermutationMap, ArrayRef<int64_t>(offsets)); + Value tiledAcc = + extractOperand(op.getAcc(), accPermutationMap, accOffsets); + + // Collapse tiled operands to 1D vectors required by smmla intrinsic + auto collapsedInputType = VectorType::get( + tiledLhs.getType().cast<ShapedType>().getNumElements(), + tiledLhs.getType().cast<ShapedType>().getElementType()); + auto collapsedOutputType = VectorType::get( + {4}, tiledAcc.getType().cast<ShapedType>().getElementType()); + auto collapsedLhs = rewriter.createOrFold<vector::ShapeCastOp>( + tiledLhs.getLoc(), collapsedInputType, tiledLhs); + auto collapsedRhs = rewriter.createOrFold<vector::ShapeCastOp>( + tiledRhs.getLoc(), collapsedInputType, tiledRhs); + auto collapsedRes = rewriter.createOrFold<vector::ShapeCastOp>( + tiledAcc.getLoc(), collapsedOutputType, tiledAcc); + + // Insert contract op + auto smmlaOp = rewriter.createOrFold<arm_neon::SmmlaOp>( + op.getLoc(), collapsedRes.getType(), collapsedRes, collapsedLhs, + collapsedRhs); + + // Reshape output back to 2D + Value tiledRes = rewriter.createOrFold<vector::ShapeCastOp>( + smmlaOp.getLoc(), tiledAcc.getType(), smmlaOp); + + // Insert the tiled result back into the non tiled result of the + // contract op. + SmallVector<int64_t> strides( + tiledRes.getType().cast<ShapedType>().getRank(), 1); + result = rewriter.createOrFold<vector::InsertStridedSliceOp>( + loc, tiledRes, result, accOffsets, strides); + } + + rewriter.replaceOp(op, result); return success(); } }; diff --git a/mlir/lib/Dialect/Bufferization/IR/BufferViewFlowOpInterface.cpp b/mlir/lib/Dialect/Bufferization/IR/BufferViewFlowOpInterface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ea726a4bfc3fb933b632ad03be1911d7e91c5f92 --- /dev/null +++ b/mlir/lib/Dialect/Bufferization/IR/BufferViewFlowOpInterface.cpp @@ -0,0 +1,18 @@ +//===- BufferViewFlowOpInterface.cpp - Buffer View Flow Analysis ----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.h" +#include "mlir/Dialect/Bufferization/IR/Bufferization.h" + +namespace mlir { +namespace bufferization { + +#include "mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.cpp.inc" + +} // namespace bufferization +} // namespace mlir diff --git a/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp b/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp index 8f0f6d1fcc84903dc8119ad667fd65b4ebcc7b50..55c9299c58effd0ba050ac752d1dcab3fe1b9dc8 100644 --- a/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp +++ b/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp @@ -344,11 +344,11 @@ bool BufferizationOptions::isOpAllowed(Operation *op) const { BufferizableOpInterface BufferizationOptions::dynCastBufferizableOp(Operation *op) const { + if (!isOpAllowed(op)) + return nullptr; auto bufferizableOp = dyn_cast<BufferizableOpInterface>(op); if (!bufferizableOp) return nullptr; - if (!isOpAllowed(op)) - return nullptr; return bufferizableOp; } diff --git a/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp b/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp index 34a0c594a5a5a34592e1480782c68a596bd2cf79..a656c812a59feba782759efae7600e41580342ca 100644 --- a/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp +++ b/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp @@ -252,16 +252,6 @@ LogicalResult AllocTensorOp::verify() { << getType().getNumDynamicDims() << " dynamic sizes"; if (getCopy() && getCopy().getType() != getType()) return emitError("expected that `copy` and return type match"); - - // For sparse tensor allocation, we require that none of its - // uses escapes the function boundary directly. - if (sparse_tensor::getSparseTensorEncoding(getType())) { - for (auto &use : getOperation()->getUses()) - if (isa<func::ReturnOp, func::CallOp, func::CallIndirectOp>( - use.getOwner())) - return emitError("sparse tensor allocation should not escape function"); - } - return success(); } @@ -343,6 +333,9 @@ struct FoldDimOfAllocTensorOp : public OpRewritePattern<tensor::DimOp> { auto allocTensorOp = dimOp.getSource().getDefiningOp<AllocTensorOp>(); if (!allocTensorOp || !maybeConstantIndex) return failure(); + if (*maybeConstantIndex < 0 || + *maybeConstantIndex >= allocTensorOp.getType().getRank()) + return failure(); if (!allocTensorOp.getType().isDynamicDim(*maybeConstantIndex)) return failure(); rewriter.replaceOp( diff --git a/mlir/lib/Dialect/Bufferization/IR/CMakeLists.txt b/mlir/lib/Dialect/Bufferization/IR/CMakeLists.txt index 9895db9d93ce0bbf084cfeb0320539e24d195cea..63dcc1eb233e9280c20f08fe58c82245c8351903 100644 --- a/mlir/lib/Dialect/Bufferization/IR/CMakeLists.txt +++ b/mlir/lib/Dialect/Bufferization/IR/CMakeLists.txt @@ -4,6 +4,7 @@ add_mlir_dialect_library(MLIRBufferizationDialect BufferDeallocationOpInterface.cpp BufferizationOps.cpp BufferizationDialect.cpp + BufferViewFlowOpInterface.cpp UnstructuredControlFlow.cpp ADDITIONAL_HEADER_DIRS diff --git a/mlir/lib/Dialect/Bufferization/Transforms/BufferDeallocationSimplification.cpp b/mlir/lib/Dialect/Bufferization/Transforms/BufferDeallocationSimplification.cpp index e30779868b47539bdbabf93464eb3f00e6a12152..954485cfede3dac7aa3dce3879a9c9870d5f5fcf 100644 --- a/mlir/lib/Dialect/Bufferization/Transforms/BufferDeallocationSimplification.cpp +++ b/mlir/lib/Dialect/Bufferization/Transforms/BufferDeallocationSimplification.cpp @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#include "mlir/Analysis/AliasAnalysis.h" #include "mlir/Dialect/Bufferization/IR/Bufferization.h" +#include "mlir/Dialect/Bufferization/Transforms/BufferViewFlowAnalysis.h" #include "mlir/Dialect/Bufferization/Transforms/Passes.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" @@ -34,6 +34,14 @@ using namespace mlir::bufferization; // Helpers //===----------------------------------------------------------------------===// +/// Given a memref value, return the "base" value by skipping over all +/// ViewLikeOpInterface ops (if any) in the reverse use-def chain. +static Value getViewBase(Value value) { + while (auto viewLikeOp = value.getDefiningOp<ViewLikeOpInterface>()) + value = viewLikeOp.getViewSource(); + return value; +} + static LogicalResult updateDeallocIfChanged(DeallocOp deallocOp, ValueRange memrefs, ValueRange conditions, @@ -49,14 +57,6 @@ static LogicalResult updateDeallocIfChanged(DeallocOp deallocOp, return success(); } -/// Given a memref value, return the "base" value by skipping over all -/// ViewLikeOpInterface ops (if any) in the reverse use-def chain. -static Value getViewBase(Value value) { - while (auto viewLikeOp = value.getDefiningOp<ViewLikeOpInterface>()) - value = viewLikeOp.getViewSource(); - return value; -} - /// Return "true" if the given values are guaranteed to be different (and /// non-aliasing) allocations based on the fact that one value is the result /// of an allocation and the other value is a block argument of a parent block. @@ -80,12 +80,14 @@ static bool distinctAllocAndBlockArgument(Value v1, Value v2) { /// Checks if `memref` may potentially alias a MemRef in `otherList`. It is /// often a requirement of optimization patterns that there cannot be any /// aliasing memref in order to perform the desired simplification. -static bool potentiallyAliasesMemref(AliasAnalysis &analysis, +static bool potentiallyAliasesMemref(BufferOriginAnalysis &analysis, ValueRange otherList, Value memref) { for (auto other : otherList) { if (distinctAllocAndBlockArgument(other, memref)) continue; - if (!analysis.alias(other, memref).isNo()) + std::optional<bool> analysisResult = + analysis.isSameAllocation(other, memref); + if (!analysisResult.has_value() || analysisResult == true) return true; } return false; @@ -129,8 +131,8 @@ namespace { struct RemoveDeallocMemrefsContainedInRetained : public OpRewritePattern<DeallocOp> { RemoveDeallocMemrefsContainedInRetained(MLIRContext *context, - AliasAnalysis &aliasAnalysis) - : OpRewritePattern<DeallocOp>(context), aliasAnalysis(aliasAnalysis) {} + BufferOriginAnalysis &analysis) + : OpRewritePattern<DeallocOp>(context), analysis(analysis) {} /// The passed 'memref' must not have a may-alias relation to any retained /// memref, and at least one must-alias relation. If there is no must-aliasing @@ -147,10 +149,11 @@ struct RemoveDeallocMemrefsContainedInRetained // deallocated in some situations and can thus not be dropped). bool atLeastOneMustAlias = false; for (Value retained : deallocOp.getRetained()) { - AliasResult analysisResult = aliasAnalysis.alias(retained, memref); - if (analysisResult.isMay()) + std::optional<bool> analysisResult = + analysis.isSameAllocation(retained, memref); + if (!analysisResult.has_value()) return failure(); - if (analysisResult.isMust() || analysisResult.isPartial()) + if (analysisResult == true) atLeastOneMustAlias = true; } if (!atLeastOneMustAlias) @@ -161,8 +164,9 @@ struct RemoveDeallocMemrefsContainedInRetained // we can remove that operand later on. for (auto [i, retained] : llvm::enumerate(deallocOp.getRetained())) { Value updatedCondition = deallocOp.getUpdatedConditions()[i]; - AliasResult analysisResult = aliasAnalysis.alias(retained, memref); - if (analysisResult.isMust() || analysisResult.isPartial()) { + std::optional<bool> analysisResult = + analysis.isSameAllocation(retained, memref); + if (analysisResult == true) { auto disjunction = rewriter.create<arith::OrIOp>( deallocOp.getLoc(), updatedCondition, cond); rewriter.replaceAllUsesExcept(updatedCondition, disjunction.getResult(), @@ -206,7 +210,7 @@ struct RemoveDeallocMemrefsContainedInRetained } private: - AliasAnalysis &aliasAnalysis; + BufferOriginAnalysis &analysis; }; /// Remove memrefs from the `retained` list which are guaranteed to not alias @@ -228,15 +232,15 @@ private: struct RemoveRetainedMemrefsGuaranteedToNotAlias : public OpRewritePattern<DeallocOp> { RemoveRetainedMemrefsGuaranteedToNotAlias(MLIRContext *context, - AliasAnalysis &aliasAnalysis) - : OpRewritePattern<DeallocOp>(context), aliasAnalysis(aliasAnalysis) {} + BufferOriginAnalysis &analysis) + : OpRewritePattern<DeallocOp>(context), analysis(analysis) {} LogicalResult matchAndRewrite(DeallocOp deallocOp, PatternRewriter &rewriter) const override { SmallVector<Value> newRetainedMemrefs, replacements; for (auto retainedMemref : deallocOp.getRetained()) { - if (potentiallyAliasesMemref(aliasAnalysis, deallocOp.getMemrefs(), + if (potentiallyAliasesMemref(analysis, deallocOp.getMemrefs(), retainedMemref)) { newRetainedMemrefs.push_back(retainedMemref); replacements.push_back({}); @@ -264,7 +268,7 @@ struct RemoveRetainedMemrefsGuaranteedToNotAlias } private: - AliasAnalysis &aliasAnalysis; + BufferOriginAnalysis &analysis; }; /// Split off memrefs to separate dealloc operations to reduce the number of @@ -297,8 +301,8 @@ private: struct SplitDeallocWhenNotAliasingAnyOther : public OpRewritePattern<DeallocOp> { SplitDeallocWhenNotAliasingAnyOther(MLIRContext *context, - AliasAnalysis &aliasAnalysis) - : OpRewritePattern<DeallocOp>(context), aliasAnalysis(aliasAnalysis) {} + BufferOriginAnalysis &analysis) + : OpRewritePattern<DeallocOp>(context), analysis(analysis) {} LogicalResult matchAndRewrite(DeallocOp deallocOp, PatternRewriter &rewriter) const override { @@ -314,7 +318,7 @@ struct SplitDeallocWhenNotAliasingAnyOther SmallVector<Value> otherMemrefs(deallocOp.getMemrefs()); otherMemrefs.erase(otherMemrefs.begin() + i); // Check if `memref` can split off into a separate bufferization.dealloc. - if (potentiallyAliasesMemref(aliasAnalysis, otherMemrefs, memref)) { + if (potentiallyAliasesMemref(analysis, otherMemrefs, memref)) { // `memref` alias with other memrefs, do not split off. remainingMemrefs.push_back(memref); remainingConditions.push_back(cond); @@ -352,7 +356,7 @@ struct SplitDeallocWhenNotAliasingAnyOther } private: - AliasAnalysis &aliasAnalysis; + BufferOriginAnalysis &analysis; }; /// Check for every retained memref if a must-aliasing memref exists in the @@ -381,8 +385,8 @@ private: struct RetainedMemrefAliasingAlwaysDeallocatedMemref : public OpRewritePattern<DeallocOp> { RetainedMemrefAliasingAlwaysDeallocatedMemref(MLIRContext *context, - AliasAnalysis &aliasAnalysis) - : OpRewritePattern<DeallocOp>(context), aliasAnalysis(aliasAnalysis) {} + BufferOriginAnalysis &analysis) + : OpRewritePattern<DeallocOp>(context), analysis(analysis) {} LogicalResult matchAndRewrite(DeallocOp deallocOp, PatternRewriter &rewriter) const override { @@ -396,8 +400,9 @@ struct RetainedMemrefAliasingAlwaysDeallocatedMemref if (!matchPattern(cond, m_One())) continue; - AliasResult analysisResult = aliasAnalysis.alias(retained, memref); - if (analysisResult.isMust() || analysisResult.isPartial()) { + std::optional<bool> analysisResult = + analysis.isSameAllocation(retained, memref); + if (analysisResult == true) { rewriter.replaceAllUsesWith(res, cond); aliasesWithConstTrueMemref[i] = true; canDropMemref = true; @@ -411,10 +416,9 @@ struct RetainedMemrefAliasingAlwaysDeallocatedMemref if (!extractOp) continue; - AliasResult extractAnalysisResult = - aliasAnalysis.alias(retained, extractOp.getOperand()); - if (extractAnalysisResult.isMust() || - extractAnalysisResult.isPartial()) { + std::optional<bool> extractAnalysisResult = + analysis.isSameAllocation(retained, extractOp.getOperand()); + if (extractAnalysisResult == true) { rewriter.replaceAllUsesWith(res, cond); aliasesWithConstTrueMemref[i] = true; canDropMemref = true; @@ -434,7 +438,7 @@ struct RetainedMemrefAliasingAlwaysDeallocatedMemref } private: - AliasAnalysis &aliasAnalysis; + BufferOriginAnalysis &analysis; }; } // namespace @@ -452,13 +456,13 @@ struct BufferDeallocationSimplificationPass : public bufferization::impl::BufferDeallocationSimplificationBase< BufferDeallocationSimplificationPass> { void runOnOperation() override { - AliasAnalysis &aliasAnalysis = getAnalysis<AliasAnalysis>(); + BufferOriginAnalysis analysis(getOperation()); RewritePatternSet patterns(&getContext()); patterns.add<RemoveDeallocMemrefsContainedInRetained, RemoveRetainedMemrefsGuaranteedToNotAlias, SplitDeallocWhenNotAliasingAnyOther, RetainedMemrefAliasingAlwaysDeallocatedMemref>(&getContext(), - aliasAnalysis); + analysis); populateDeallocOpCanonicalizationPatterns(patterns, &getContext()); if (failed( diff --git a/mlir/lib/Dialect/Bufferization/Transforms/BufferResultsToOutParams.cpp b/mlir/lib/Dialect/Bufferization/Transforms/BufferResultsToOutParams.cpp index 930f035339c1d310afff553f4466c13b09c2773e..a2222e169c4d64a7f7b663101989b3e4dd92d106 100644 --- a/mlir/lib/Dialect/Bufferization/Transforms/BufferResultsToOutParams.cpp +++ b/mlir/lib/Dialect/Bufferization/Transforms/BufferResultsToOutParams.cpp @@ -21,7 +21,7 @@ namespace bufferization { } // namespace mlir using namespace mlir; -using MemCpyFn = bufferization::BufferResultsToOutParamsOptions::MemCpyFn; +using MemCpyFn = bufferization::BufferResultsToOutParamsOpts::MemCpyFn; /// Return `true` if the given MemRef type has a fully dynamic layout. static bool hasFullyDynamicLayoutMap(MemRefType type) { @@ -45,9 +45,12 @@ static bool hasStaticIdentityLayout(MemRefType type) { // Updates the func op and entry block. // // Any args appended to the entry block are added to `appendedEntryArgs`. +// If `addResultAttribute` is true, adds the unit attribute `bufferize.result` +// to each newly created function argument. static LogicalResult updateFuncOp(func::FuncOp func, - SmallVectorImpl<BlockArgument> &appendedEntryArgs) { + SmallVectorImpl<BlockArgument> &appendedEntryArgs, + bool addResultAttribute) { auto functionType = func.getFunctionType(); // Collect information about the results will become appended arguments. @@ -80,6 +83,10 @@ updateFuncOp(func::FuncOp func, for (int i = 0, e = erasedResultTypes.size(); i < e; ++i, ++erasedIndicesIt) { func.setArgAttrs(functionType.getNumInputs() + i, func.getResultAttrs(*erasedIndicesIt)); + if (addResultAttribute) + func.setArgAttr(functionType.getNumInputs() + i, + StringAttr::get(func.getContext(), "bufferize.result"), + UnitAttr::get(func.getContext())); } // Erase the results. @@ -127,7 +134,7 @@ static LogicalResult updateReturnOps(func::FuncOp func, // temporary buffers for newly introduced out params. static LogicalResult updateCalls(ModuleOp module, - const bufferization::BufferResultsToOutParamsOptions &options) { + const bufferization::BufferResultsToOutParamsOpts &options) { bool didFail = false; SymbolTable symtab(module); module.walk([&](func::CallOp op) { @@ -189,12 +196,13 @@ updateCalls(ModuleOp module, LogicalResult mlir::bufferization::promoteBufferResultsToOutParams( ModuleOp module, - const bufferization::BufferResultsToOutParamsOptions &options) { + const bufferization::BufferResultsToOutParamsOpts &options) { for (auto func : module.getOps<func::FuncOp>()) { if (!options.filterFn(&func)) continue; SmallVector<BlockArgument, 6> appendedEntryArgs; - if (failed(updateFuncOp(func, appendedEntryArgs))) + if (failed( + updateFuncOp(func, appendedEntryArgs, options.addResultAttribute))) return failure(); if (func.isExternal()) continue; @@ -218,21 +226,25 @@ struct BufferResultsToOutParamsPass : bufferization::impl::BufferResultsToOutParamsBase< BufferResultsToOutParamsPass> { explicit BufferResultsToOutParamsPass( - const bufferization::BufferResultsToOutParamsOptions &options) + const bufferization::BufferResultsToOutParamsOpts &options) : options(options) {} void runOnOperation() override { + // Convert from pass options in tablegen to BufferResultsToOutParamsOpts. + if (addResultAttribute) + options.addResultAttribute = true; + if (failed(bufferization::promoteBufferResultsToOutParams(getOperation(), options))) return signalPassFailure(); } private: - bufferization::BufferResultsToOutParamsOptions options; + bufferization::BufferResultsToOutParamsOpts options; }; } // namespace std::unique_ptr<Pass> mlir::bufferization::createBufferResultsToOutParamsPass( - const bufferization::BufferResultsToOutParamsOptions &options) { + const bufferization::BufferResultsToOutParamsOpts &options) { return std::make_unique<BufferResultsToOutParamsPass>(options); } diff --git a/mlir/lib/Dialect/Bufferization/Transforms/BufferViewFlowAnalysis.cpp b/mlir/lib/Dialect/Bufferization/Transforms/BufferViewFlowAnalysis.cpp index 88ef1b639fc5ceba3640fe2a5efdacdd65f301c0..72f47b8b468ea63338b75848ba5a31e47d0e4ef7 100644 --- a/mlir/lib/Dialect/Bufferization/Transforms/BufferViewFlowAnalysis.cpp +++ b/mlir/lib/Dialect/Bufferization/Transforms/BufferViewFlowAnalysis.cpp @@ -8,29 +8,34 @@ #include "mlir/Dialect/Bufferization/Transforms/BufferViewFlowAnalysis.h" +#include "mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.h" +#include "mlir/Interfaces/CallInterfaces.h" #include "mlir/Interfaces/ControlFlowInterfaces.h" +#include "mlir/Interfaces/FunctionInterfaces.h" #include "mlir/Interfaces/ViewLikeInterface.h" #include "llvm/ADT/SetOperations.h" #include "llvm/ADT/SetVector.h" using namespace mlir; +using namespace mlir::bufferization; + +//===----------------------------------------------------------------------===// +// BufferViewFlowAnalysis +//===----------------------------------------------------------------------===// /// Constructs a new alias analysis using the op provided. BufferViewFlowAnalysis::BufferViewFlowAnalysis(Operation *op) { build(op); } -/// Find all immediate and indirect dependent buffers this value could -/// potentially have. Note that the resulting set will also contain the value -/// provided as it is a dependent alias of itself. -BufferViewFlowAnalysis::ValueSetT -BufferViewFlowAnalysis::resolve(Value rootValue) const { - ValueSetT result; +static BufferViewFlowAnalysis::ValueSetT +resolveValues(const BufferViewFlowAnalysis::ValueMapT &map, Value value) { + BufferViewFlowAnalysis::ValueSetT result; SmallVector<Value, 8> queue; - queue.push_back(rootValue); + queue.push_back(value); while (!queue.empty()) { Value currentValue = queue.pop_back_val(); if (result.insert(currentValue).second) { - auto it = dependencies.find(currentValue); - if (it != dependencies.end()) { + auto it = map.find(currentValue); + if (it != map.end()) { for (Value aliasValue : it->second) queue.push_back(aliasValue); } @@ -39,6 +44,19 @@ BufferViewFlowAnalysis::resolve(Value rootValue) const { return result; } +/// Find all immediate and indirect dependent buffers this value could +/// potentially have. Note that the resulting set will also contain the value +/// provided as it is a dependent alias of itself. +BufferViewFlowAnalysis::ValueSetT +BufferViewFlowAnalysis::resolve(Value rootValue) const { + return resolveValues(dependencies, rootValue); +} + +BufferViewFlowAnalysis::ValueSetT +BufferViewFlowAnalysis::resolveReverse(Value rootValue) const { + return resolveValues(reverseDependencies, rootValue); +} + /// Removes the given values from all alias sets. void BufferViewFlowAnalysis::remove(const SetVector<Value> &aliasValues) { for (auto &entry : dependencies) @@ -65,18 +83,46 @@ void BufferViewFlowAnalysis::rename(Value from, Value to) { void BufferViewFlowAnalysis::build(Operation *op) { // Registers all dependencies of the given values. auto registerDependencies = [&](ValueRange values, ValueRange dependencies) { - for (auto [value, dep] : llvm::zip(values, dependencies)) + for (auto [value, dep] : llvm::zip_equal(values, dependencies)) { this->dependencies[value].insert(dep); + this->reverseDependencies[dep].insert(value); + } + }; + + // Mark all buffer results and buffer region entry block arguments of the + // given op as terminals. + auto populateTerminalValues = [&](Operation *op) { + for (Value v : op->getResults()) + if (isa<BaseMemRefType>(v.getType())) + this->terminals.insert(v); + for (Region &r : op->getRegions()) + for (BlockArgument v : r.getArguments()) + if (isa<BaseMemRefType>(v.getType())) + this->terminals.insert(v); }; op->walk([&](Operation *op) { - // TODO: We should have an op interface instead of a hard-coded list of - // interfaces/ops. + // Query BufferViewFlowOpInterface. If the op does not implement that + // interface, try to infer the dependencies from other interfaces that the + // op may implement. + if (auto bufferViewFlowOp = dyn_cast<BufferViewFlowOpInterface>(op)) { + bufferViewFlowOp.populateDependencies(registerDependencies); + for (Value v : op->getResults()) + if (isa<BaseMemRefType>(v.getType()) && + bufferViewFlowOp.mayBeTerminalBuffer(v)) + this->terminals.insert(v); + for (Region &r : op->getRegions()) + for (BlockArgument v : r.getArguments()) + if (isa<BaseMemRefType>(v.getType()) && + bufferViewFlowOp.mayBeTerminalBuffer(v)) + this->terminals.insert(v); + return WalkResult::advance(); + } // Add additional dependencies created by view changes to the alias list. if (auto viewInterface = dyn_cast<ViewLikeOpInterface>(op)) { - dependencies[viewInterface.getViewSource()].insert( - viewInterface->getResult(0)); + registerDependencies(viewInterface.getViewSource(), + viewInterface->getResult(0)); return WalkResult::advance(); } @@ -131,16 +177,154 @@ void BufferViewFlowAnalysis::build(Operation *op) { return WalkResult::advance(); } - // Unknown op: Assume that all operands alias with all results. - for (Value operand : op->getOperands()) { - if (!isa<BaseMemRefType>(operand.getType())) - continue; - for (Value result : op->getResults()) { - if (!isa<BaseMemRefType>(result.getType())) - continue; - registerDependencies({operand}, {result}); - } + // Region terminators are handled together with RegionBranchOpInterface. + if (isa<RegionBranchTerminatorOpInterface>(op)) + return WalkResult::advance(); + + if (isa<CallOpInterface>(op)) { + // This is an intra-function analysis. We have no information about other + // functions. Conservatively assume that each operand may alias with each + // result. Also mark the results are terminals because the function could + // return newly allocated buffers. + populateTerminalValues(op); + for (Value operand : op->getOperands()) + for (Value result : op->getResults()) + registerDependencies({operand}, {result}); + return WalkResult::advance(); } + + // We have no information about unknown ops. + populateTerminalValues(op); + return WalkResult::advance(); }); } + +bool BufferViewFlowAnalysis::mayBeTerminalBuffer(Value value) const { + assert(isa<BaseMemRefType>(value.getType()) && "expected memref"); + return terminals.contains(value); +} + +//===----------------------------------------------------------------------===// +// BufferOriginAnalysis +//===----------------------------------------------------------------------===// + +/// Return "true" if the given value is the result of a memory allocation. +static bool hasAllocateSideEffect(Value v) { + Operation *op = v.getDefiningOp(); + if (!op) + return false; + return hasEffect<MemoryEffects::Allocate>(op, v); +} + +/// Return "true" if the given value is a function block argument. +static bool isFunctionArgument(Value v) { + auto bbArg = dyn_cast<BlockArgument>(v); + if (!bbArg) + return false; + Block *b = bbArg.getOwner(); + auto funcOp = dyn_cast<FunctionOpInterface>(b->getParentOp()); + if (!funcOp) + return false; + return bbArg.getOwner() == &funcOp.getFunctionBody().front(); +} + +/// Given a memref value, return the "base" value by skipping over all +/// ViewLikeOpInterface ops (if any) in the reverse use-def chain. +static Value getViewBase(Value value) { + while (auto viewLikeOp = value.getDefiningOp<ViewLikeOpInterface>()) + value = viewLikeOp.getViewSource(); + return value; +} + +BufferOriginAnalysis::BufferOriginAnalysis(Operation *op) : analysis(op) {} + +std::optional<bool> BufferOriginAnalysis::isSameAllocation(Value v1, Value v2) { + assert(isa<BaseMemRefType>(v1.getType()) && "expected buffer"); + assert(isa<BaseMemRefType>(v2.getType()) && "expected buffer"); + + // Skip over all view-like ops. + v1 = getViewBase(v1); + v2 = getViewBase(v2); + + // Fast path: If both buffers are the same SSA value, we can be sure that + // they originate from the same allocation. + if (v1 == v2) + return true; + + // Compute the SSA values from which the buffers `v1` and `v2` originate. + SmallPtrSet<Value, 16> origin1 = analysis.resolveReverse(v1); + SmallPtrSet<Value, 16> origin2 = analysis.resolveReverse(v2); + + // Originating buffers are "terminal" if they could not be traced back any + // further by the `BufferViewFlowAnalysis`. Examples of terminal buffers: + // - function block arguments + // - values defined by allocation ops such as "memref.alloc" + // - values defined by ops that are unknown to the buffer view flow analysis + // - values that are marked as "terminal" in the `BufferViewFlowOpInterface` + SmallPtrSet<Value, 16> terminal1, terminal2; + + // While gathering terminal buffers, keep track of whether all terminal + // buffers are newly allocated buffer or function entry arguments. + bool allAllocs1 = true, allAllocs2 = true; + bool allAllocsOrFuncEntryArgs1 = true, allAllocsOrFuncEntryArgs2 = true; + + // Helper function that gathers terminal buffers among `origin`. + auto gatherTerminalBuffers = [this](const SmallPtrSet<Value, 16> &origin, + SmallPtrSet<Value, 16> &terminal, + bool &allAllocs, + bool &allAllocsOrFuncEntryArgs) { + for (Value v : origin) { + if (isa<BaseMemRefType>(v.getType()) && analysis.mayBeTerminalBuffer(v)) { + terminal.insert(v); + allAllocs &= hasAllocateSideEffect(v); + allAllocsOrFuncEntryArgs &= + isFunctionArgument(v) || hasAllocateSideEffect(v); + } + } + assert(!terminal.empty() && "expected non-empty terminal set"); + }; + + // Gather terminal buffers for `v1` and `v2`. + gatherTerminalBuffers(origin1, terminal1, allAllocs1, + allAllocsOrFuncEntryArgs1); + gatherTerminalBuffers(origin2, terminal2, allAllocs2, + allAllocsOrFuncEntryArgs2); + + // If both `v1` and `v2` have a single matching terminal buffer, they are + // guaranteed to originate from the same buffer allocation. + if (llvm::hasSingleElement(terminal1) && llvm::hasSingleElement(terminal2) && + *terminal1.begin() == *terminal2.begin()) + return true; + + // At least one of the two values has multiple terminals. + + // Check if there is overlap between the terminal buffers of `v1` and `v2`. + bool distinctTerminalSets = true; + for (Value v : terminal1) + distinctTerminalSets &= !terminal2.contains(v); + // If there is overlap between the terminal buffers of `v1` and `v2`, we + // cannot make an accurate decision without further analysis. + if (!distinctTerminalSets) + return std::nullopt; + + // If `v1` originates from only allocs, and `v2` is guaranteed to originate + // from different allocations (that is guaranteed if `v2` originates from + // only distinct allocs or function entry arguments), we can be sure that + // `v1` and `v2` originate from different allocations. The same argument can + // be made when swapping `v1` and `v2`. + bool isolatedAlloc1 = allAllocs1 && (allAllocs2 || allAllocsOrFuncEntryArgs2); + bool isolatedAlloc2 = (allAllocs1 || allAllocsOrFuncEntryArgs1) && allAllocs2; + if (isolatedAlloc1 || isolatedAlloc2) + return false; + + // Otherwise: We do not know whether `v1` and `v2` originate from the same + // allocation or not. + // TODO: Function arguments are currently handled conservatively. We assume + // that they could be the same allocation. + // TODO: Terminals other than allocations and function arguments are + // currently handled conservatively. We assume that they could be the same + // allocation. E.g., we currently return "nullopt" for values that originate + // from different "memref.get_global" ops (with different symbols). + return std::nullopt; +} diff --git a/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp b/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp index 6a0ad66549965af4dcc301d06a17f9265ebd2e7f..32f4e6a0fe890179aa6a7718bcfe1eb825cec618 100644 --- a/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp +++ b/mlir/lib/Dialect/Bufferization/Transforms/Bufferize.cpp @@ -182,6 +182,11 @@ parseHeuristicOption(const std::string &s) { return OneShotBufferizationOptions::AnalysisHeuristic::BottomUp; if (s == "top-down") return OneShotBufferizationOptions::AnalysisHeuristic::TopDown; + if (s == "bottom-up-from-terminators") + return OneShotBufferizationOptions::AnalysisHeuristic:: + BottomUpFromTerminators; + if (s == "fuzzer") + return OneShotBufferizationOptions::AnalysisHeuristic::Fuzzer; llvm_unreachable("invalid analysisheuristic option"); } @@ -453,7 +458,7 @@ LogicalResult bufferization::bufferizeOp(Operation *op, // canonicalize away (or canonicalize to more precise layouts). SmallVector<Operation *> worklist; op->walk<WalkOrder::PostOrder>([&](Operation *op) { - if (hasTensorSemantics(op)) + if (options.isOpAllowed(op) && hasTensorSemantics(op)) worklist.push_back(op); }); @@ -472,8 +477,6 @@ LogicalResult bufferization::bufferizeOp(Operation *op, auto bufferizableOp = options.dynCastBufferizableOp(nextOp); if (!bufferizableOp) continue; - if (!options.isOpAllowed(nextOp)) - continue; // Skip ops that no longer have tensor semantics. if (!hasTensorSemantics(nextOp)) continue; diff --git a/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp index 4cdbbf35dc876bc899d2f1500da3075cfba5fe83..053ea7935260a2191bced9a2655b237c565590aa 100644 --- a/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp +++ b/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp @@ -326,7 +326,7 @@ struct FuncOpInterface static bool supportsUnstructuredControlFlow() { return true; } bool hasTensorSemantics(Operation *op) const { - auto isaTensor = [](Type type) { return isa<TensorType>(type); }; + auto isaTensor = llvm::IsaPred<TensorType>; // A function has tensor semantics if it has tensor arguments/results. auto funcOp = cast<FuncOp>(op); diff --git a/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp b/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp index fba9cd87306381d990c84414ad864be806e00f12..531016130d1d8e183f135dbcf6cdee3e2041cb3b 100644 --- a/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp +++ b/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp @@ -51,6 +51,7 @@ #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/IR/AsmState.h" #include "mlir/IR/Dominance.h" +#include "mlir/IR/Iterators.h" #include "mlir/IR/Operation.h" #include "mlir/IR/TypeUtilities.h" #include "mlir/Interfaces/ControlFlowInterfaces.h" @@ -1094,41 +1095,104 @@ static void equivalenceAnalysis(Operation *op, OneShotAnalysisState &state) { equivalenceAnalysis(ops, state); } -LogicalResult OneShotAnalysisState::analyzeOp(Operation *op, - const DominanceInfo &domInfo) { - // Collect ops so we can build our own reverse traversal. - SmallVector<Operation *> ops; - op->walk([&](Operation *op) { - // No tensors => no buffers. - if (!hasTensorSemantics(op)) +/// "Bottom-up from terminators" heuristic. +static SmallVector<Operation *> +bottomUpFromTerminatorsHeuristic(Operation *op, + const OneShotAnalysisState &state) { + SetVector<Operation *> traversedOps; + + // Find region terminators. + op->walk<WalkOrder::PostOrder>([&](RegionBranchTerminatorOpInterface term) { + if (!traversedOps.insert(term)) return; - ops.push_back(op); + // Follow the reverse SSA use-def chain from each yielded value as long as + // we stay within the same region. + SmallVector<OpResult> worklist; + for (Value v : term->getOperands()) { + if (!isa<TensorType>(v.getType())) + continue; + auto opResult = dyn_cast<OpResult>(v); + if (!opResult) + continue; + worklist.push_back(opResult); + } + while (!worklist.empty()) { + OpResult opResult = worklist.pop_back_val(); + Operation *defOp = opResult.getDefiningOp(); + if (!traversedOps.insert(defOp)) + continue; + if (!term->getParentRegion()->findAncestorOpInRegion(*defOp)) + continue; + AliasingOpOperandList aliases = state.getAliasingOpOperands(opResult); + for (auto alias : aliases) { + Value v = alias.opOperand->get(); + if (!isa<TensorType>(v.getType())) + continue; + auto opResult = dyn_cast<OpResult>(v); + if (!opResult) + continue; + worklist.push_back(opResult); + } + } }); - if (getOptions().analysisFuzzerSeed) { - // This is a fuzzer. For testing purposes only. Randomize the order in which - // operations are analyzed. The bufferization quality is likely worse, but - // we want to make sure that no assertions are triggered anywhere. - std::mt19937 g(getOptions().analysisFuzzerSeed); - llvm::shuffle(ops.begin(), ops.end(), g); - } + // Analyze traversed ops, then all remaining ops. + SmallVector<Operation *> result(traversedOps.begin(), traversedOps.end()); + op->walk<WalkOrder::PostOrder, ReverseIterator>([&](Operation *op) { + if (!traversedOps.contains(op) && hasTensorSemantics(op)) + result.push_back(op); + }); + return result; +} +LogicalResult OneShotAnalysisState::analyzeOp(Operation *op, + const DominanceInfo &domInfo) { OneShotBufferizationOptions::AnalysisHeuristic heuristic = getOptions().analysisHeuristic; - if (heuristic == OneShotBufferizationOptions::AnalysisHeuristic::BottomUp) { - // Default: Walk ops in reverse for better interference analysis. - for (Operation *op : reverse(ops)) - if (failed(analyzeSingleOp(op, domInfo))) - return failure(); - } else if (heuristic == - OneShotBufferizationOptions::AnalysisHeuristic::TopDown) { - for (Operation *op : ops) - if (failed(analyzeSingleOp(op, domInfo))) - return failure(); + + SmallVector<Operation *> orderedOps; + if (heuristic == + OneShotBufferizationOptions::AnalysisHeuristic::BottomUpFromTerminators) { + orderedOps = bottomUpFromTerminatorsHeuristic(op, *this); } else { - llvm_unreachable("unsupported heuristic"); + op->walk([&](Operation *op) { + // No tensors => no buffers. + if (!hasTensorSemantics(op)) + return; + orderedOps.push_back(op); + }); + switch (heuristic) { + case OneShotBufferizationOptions::AnalysisHeuristic::BottomUp: { + // Default: Walk ops in reverse for better interference analysis. + std::reverse(orderedOps.begin(), orderedOps.end()); + break; + } + case OneShotBufferizationOptions::AnalysisHeuristic::TopDown: { + // Ops are already sorted top-down in `orderedOps`. + break; + } + case OneShotBufferizationOptions::AnalysisHeuristic::Fuzzer: { + assert(getOptions().analysisFuzzerSeed && + "expected that fuzzer seed it set"); + // This is a fuzzer. For testing purposes only. Randomize the order in + // which operations are analyzed. The bufferization quality is likely + // worse, but we want to make sure that no assertions are triggered + // anywhere. + std::mt19937 g(getOptions().analysisFuzzerSeed); + llvm::shuffle(orderedOps.begin(), orderedOps.end(), g); + break; + } + default: { + llvm_unreachable("unsupported heuristic"); + } + } } + // Analyze ops in the computed order. + for (Operation *op : orderedOps) + if (failed(analyzeSingleOp(op, domInfo))) + return failure(); + equivalenceAnalysis(op, *this); return success(); } diff --git a/mlir/lib/Dialect/Bufferization/Transforms/OneShotModuleBufferize.cpp b/mlir/lib/Dialect/Bufferization/Transforms/OneShotModuleBufferize.cpp index 33feea0b956ca010aea0cfcf042d13c8cd38a08d..0a4072605c265ffc4cec1b5d7de80f094744b60a 100644 --- a/mlir/lib/Dialect/Bufferization/Transforms/OneShotModuleBufferize.cpp +++ b/mlir/lib/Dialect/Bufferization/Transforms/OneShotModuleBufferize.cpp @@ -67,6 +67,7 @@ #include "mlir/Dialect/Bufferization/Transforms/Transforms.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" +#include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/Operation.h" using namespace mlir; @@ -277,9 +278,10 @@ static void equivalenceAnalysis(func::FuncOp funcOp, /// Return "true" if the given function signature has tensor semantics. static bool hasTensorSignature(func::FuncOp funcOp) { - auto isaTensor = [](Type t) { return isa<TensorType>(t); }; - return llvm::any_of(funcOp.getFunctionType().getInputs(), isaTensor) || - llvm::any_of(funcOp.getFunctionType().getResults(), isaTensor); + return llvm::any_of(funcOp.getFunctionType().getInputs(), + llvm::IsaPred<TensorType>) || + llvm::any_of(funcOp.getFunctionType().getResults(), + llvm::IsaPred<TensorType>); } /// Store all functions of the `moduleOp` in `orderedFuncOps`, sorted by diff --git a/mlir/lib/Dialect/Complex/IR/ComplexDialect.cpp b/mlir/lib/Dialect/Complex/IR/ComplexDialect.cpp index ca57171af156f9ee23b45f3a09f05ed191352185..0bdcf434e062feff62a7becb99e3788ae0dd9861 100644 --- a/mlir/lib/Dialect/Complex/IR/ComplexDialect.cpp +++ b/mlir/lib/Dialect/Complex/IR/ComplexDialect.cpp @@ -40,7 +40,7 @@ void complex::ComplexDialect::initialize() { #define GET_ATTRDEF_LIST #include "mlir/Dialect/Complex/IR/ComplexAttributes.cpp.inc" >(); - declarePromisedInterface<ComplexDialect, ConvertToLLVMPatternInterface>(); + declarePromisedInterface<ConvertToLLVMPatternInterface, ComplexDialect>(); addInterfaces<ComplexInlinerInterface>(); } diff --git a/mlir/lib/Dialect/Complex/IR/ComplexOps.cpp b/mlir/lib/Dialect/Complex/IR/ComplexOps.cpp index 5529dccaf1de6fb8dba1cbf5a465fbec066823fb..1c81433bc3e9451ff4bf821d0dd1734367546606 100644 --- a/mlir/lib/Dialect/Complex/IR/ComplexOps.cpp +++ b/mlir/lib/Dialect/Complex/IR/ComplexOps.cpp @@ -369,6 +369,32 @@ OpFoldResult MulOp::fold(FoldAdaptor adaptor) { return {}; } +//===----------------------------------------------------------------------===// +// DivOp +//===----------------------------------------------------------------------===// + +OpFoldResult DivOp::fold(FoldAdaptor adaptor) { + auto rhs = adaptor.getRhs(); + if (!rhs) + return {}; + + ArrayAttr arrayAttr = rhs.dyn_cast<ArrayAttr>(); + if (!arrayAttr || arrayAttr.size() != 2) + return {}; + + APFloat real = cast<FloatAttr>(arrayAttr[0]).getValue(); + APFloat imag = cast<FloatAttr>(arrayAttr[1]).getValue(); + + if (!imag.isZero()) + return {}; + + // complex.div(a, complex.constant<1.0, 0.0>) -> a + if (real == APFloat(real.getSemantics(), 1)) + return getLhs(); + + return {}; +} + //===----------------------------------------------------------------------===// // TableGen'd op method definitions //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/ControlFlow/IR/ControlFlowOps.cpp b/mlir/lib/Dialect/ControlFlow/IR/ControlFlowOps.cpp index d242d75bd51fa7b1d2770a3cff342fe10865e9f9..5d11f8f6cc458ba4d41a0f316d7ba4a9945b6db2 100644 --- a/mlir/lib/Dialect/ControlFlow/IR/ControlFlowOps.cpp +++ b/mlir/lib/Dialect/ControlFlow/IR/ControlFlowOps.cpp @@ -10,6 +10,8 @@ #include "mlir/Conversion/ConvertToLLVM/ToLLVMInterface.h" #include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h" +#include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h" #include "mlir/IR/AffineExpr.h" #include "mlir/IR/AffineMap.h" #include "mlir/IR/Builders.h" @@ -68,7 +70,11 @@ void ControlFlowDialect::initialize() { #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.cpp.inc" >(); addInterfaces<ControlFlowInlinerInterface>(); - declarePromisedInterface<ControlFlowDialect, ConvertToLLVMPatternInterface>(); + declarePromisedInterface<ConvertToLLVMPatternInterface, ControlFlowDialect>(); + declarePromisedInterfaces<bufferization::BufferizableOpInterface, BranchOp, + CondBranchOp>(); + declarePromisedInterface<bufferization::BufferDeallocationOpInterface, + CondBranchOp>(); } //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp index 9426bbbe2370f06815e7fb26958059b0301dbdaf..f4a9dc3ca509c8d0535d52a56bb210f777722d2d 100644 --- a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp +++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp @@ -54,6 +54,35 @@ void mlir::emitc::buildTerminatedBody(OpBuilder &builder, Location loc) { builder.create<emitc::YieldOp>(loc); } +bool mlir::emitc::isSupportedIntegerType(Type type) { + if (auto intType = llvm::dyn_cast<IntegerType>(type)) { + switch (intType.getWidth()) { + case 1: + case 8: + case 16: + case 32: + case 64: + return true; + default: + return false; + } + } + return false; +} + +bool mlir::emitc::isSupportedFloatType(Type type) { + if (auto floatType = llvm::dyn_cast<FloatType>(type)) { + switch (floatType.getWidth()) { + case 32: + case 64: + return true; + default: + return false; + } + } + return false; +} + /// Check that the type of the initial value is compatible with the operations /// result type. static LogicalResult verifyInitializationAttribute(Operation *op, @@ -132,9 +161,10 @@ LogicalResult ApplyOp::verify() { LogicalResult emitc::AssignOp::verify() { Value variable = getVar(); Operation *variableDef = variable.getDefiningOp(); - if (!variableDef || !llvm::isa<emitc::VariableOp>(variableDef)) + if (!variableDef || + !llvm::isa<emitc::VariableOp, emitc::SubscriptOp>(variableDef)) return emitOpError() << "requires first operand (" << variable - << ") to be a Variable"; + << ") to be a Variable or subscript"; Value value = getValue(); if (variable.getType() != value.getType()) @@ -194,8 +224,7 @@ LogicalResult emitc::CallOpaqueOp::verify() { } } - if (llvm::any_of(getResultTypes(), - [](Type type) { return isa<ArrayType>(type); })) { + if (llvm::any_of(getResultTypes(), llvm::IsaPred<ArrayType>)) { return emitOpError() << "cannot return array type"; } @@ -746,6 +775,20 @@ LogicalResult emitc::YieldOp::verify() { return success(); } +//===----------------------------------------------------------------------===// +// SubscriptOp +//===----------------------------------------------------------------------===// + +LogicalResult emitc::SubscriptOp::verify() { + if (getIndices().size() != (size_t)getArray().getType().getRank()) { + return emitOpError() << "requires number of indices (" + << getIndices().size() + << ") to match the rank of the array type (" + << getArray().getType().getRank() << ")"; + } + return success(); +} + //===----------------------------------------------------------------------===// // TableGen'd op method definitions //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/EmitC/Transforms/FormExpressions.cpp b/mlir/lib/Dialect/EmitC/Transforms/FormExpressions.cpp index 5b03f81b305fd5ec3a6a4f8e0495a88f38178576..e7c431f39e3f08439bbf502b1786437623090a26 100644 --- a/mlir/lib/Dialect/EmitC/Transforms/FormExpressions.cpp +++ b/mlir/lib/Dialect/EmitC/Transforms/FormExpressions.cpp @@ -36,7 +36,8 @@ struct FormExpressionsPass // Wrap each C operator op with an expression op. OpBuilder builder(context); auto matchFun = [&](Operation *op) { - if (op->hasTrait<OpTrait::emitc::CExpression>()) + if (op->hasTrait<OpTrait::emitc::CExpression>() && + !op->getParentOfType<emitc::ExpressionOp>()) createExpression(op, builder); }; rootOp->walk(matchFun); diff --git a/mlir/lib/Dialect/Func/IR/FuncOps.cpp b/mlir/lib/Dialect/Func/IR/FuncOps.cpp index d18ec279e85c04864c0d851b3c500faaf3b745ef..95589e8989e27a8eb0063912503dc03439b9ed24 100644 --- a/mlir/lib/Dialect/Func/IR/FuncOps.cpp +++ b/mlir/lib/Dialect/Func/IR/FuncOps.cpp @@ -9,6 +9,7 @@ #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Conversion/ConvertToLLVM/ToLLVMInterface.h" +#include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/IRMapping.h" @@ -41,8 +42,10 @@ void FuncDialect::initialize() { #define GET_OP_LIST #include "mlir/Dialect/Func/IR/FuncOps.cpp.inc" >(); - declarePromisedInterface<FuncDialect, DialectInlinerInterface>(); - declarePromisedInterface<FuncDialect, ConvertToLLVMPatternInterface>(); + declarePromisedInterface<DialectInlinerInterface, FuncDialect>(); + declarePromisedInterface<ConvertToLLVMPatternInterface, FuncDialect>(); + declarePromisedInterfaces<bufferization::BufferizableOpInterface, CallOp, + FuncOp, ReturnOp>(); } /// Materialize a single constant operation from a given attribute value with diff --git a/mlir/lib/Dialect/Func/TransformOps/FuncTransformOps.cpp b/mlir/lib/Dialect/Func/TransformOps/FuncTransformOps.cpp index 9e79b086c0be841de2d1a498ff1dc87e922de442..1e262736226f737099a80b723b0b33982c42af9e 100644 --- a/mlir/lib/Dialect/Func/TransformOps/FuncTransformOps.cpp +++ b/mlir/lib/Dialect/Func/TransformOps/FuncTransformOps.cpp @@ -13,8 +13,8 @@ #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformOps.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Transforms/DialectConversion.h" using namespace mlir; diff --git a/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp b/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp index 33ce5c159db4f9de06782a6bfa44e5d4a2ce7856..f1b9ca5c5002083bcf972377dfb6c3e6e3649708 100644 --- a/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp +++ b/mlir/lib/Dialect/GPU/IR/GPUDialect.cpp @@ -13,6 +13,7 @@ #include "mlir/Dialect/GPU/IR/GPUDialect.h" #include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/IR/Attributes.h" #include "mlir/IR/Builders.h" @@ -215,6 +216,8 @@ void GPUDialect::initialize() { #include "mlir/Dialect/GPU/IR/GPUOpsAttributes.cpp.inc" >(); addInterfaces<GPUInlinerInterface>(); + declarePromisedInterface<bufferization::BufferDeallocationOpInterface, + TerminatorOp>(); } static std::string getSparseHandleKeyword(SparseHandleKind kind) { diff --git a/mlir/lib/Dialect/GPU/TransformOps/GPUTransformOps.cpp b/mlir/lib/Dialect/GPU/TransformOps/GPUTransformOps.cpp index ada985b5979e2d594cc983b8d9e33a4b551ce3a5..b584f63f16e0aae9458bf3dfb6a5b1dcfff56a31 100644 --- a/mlir/lib/Dialect/GPU/TransformOps/GPUTransformOps.cpp +++ b/mlir/lib/Dialect/GPU/TransformOps/GPUTransformOps.cpp @@ -22,7 +22,7 @@ #include "mlir/Dialect/SCF/IR/DeviceMappingInterface.h" #include "mlir/Dialect/SCF/IR/SCF.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Dialect/Utils/IndexingUtils.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" #include "mlir/Dialect/Vector/Transforms/VectorTransforms.h" @@ -296,22 +296,14 @@ checkMappingAttributeTypes(std::optional<TransformOpInterface> transformOp, "scf.forall op requires a mapping attribute"); } - bool hasBlockMapping = - llvm::any_of(forallOp.getMapping().value(), [](Attribute attr) { - return isa<GPUBlockMappingAttr>(attr); - }); - bool hasWarpgroupMapping = - llvm::any_of(forallOp.getMapping().value(), [](Attribute attr) { - return isa<GPUWarpgroupMappingAttr>(attr); - }); - bool hasWarpMapping = - llvm::any_of(forallOp.getMapping().value(), [](Attribute attr) { - return isa<GPUWarpMappingAttr>(attr); - }); - bool hasThreadMapping = - llvm::any_of(forallOp.getMapping().value(), [](Attribute attr) { - return isa<GPUThreadMappingAttr>(attr); - }); + bool hasBlockMapping = llvm::any_of(forallOp.getMapping().value(), + llvm::IsaPred<GPUBlockMappingAttr>); + bool hasWarpgroupMapping = llvm::any_of( + forallOp.getMapping().value(), llvm::IsaPred<GPUWarpgroupMappingAttr>); + bool hasWarpMapping = llvm::any_of(forallOp.getMapping().value(), + llvm::IsaPred<GPUWarpMappingAttr>); + bool hasThreadMapping = llvm::any_of(forallOp.getMapping().value(), + llvm::IsaPred<GPUThreadMappingAttr>); int64_t countMappingTypes = 0; countMappingTypes += hasBlockMapping ? 1 : 0; countMappingTypes += hasWarpgroupMapping ? 1 : 0; diff --git a/mlir/lib/Dialect/GPU/TransformOps/Utils.cpp b/mlir/lib/Dialect/GPU/TransformOps/Utils.cpp index cc3be7da11e0f5e0604f0d8472e1931b4f4e0128..e8ecbe16c3f06fd20515af648d36a58ea3eb1885 100644 --- a/mlir/lib/Dialect/GPU/TransformOps/Utils.cpp +++ b/mlir/lib/Dialect/GPU/TransformOps/Utils.cpp @@ -17,7 +17,7 @@ #include "mlir/Dialect/SCF/IR/DeviceMappingInterface.h" #include "mlir/Dialect/SCF/IR/SCF.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Dialect/Utils/IndexingUtils.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" #include "mlir/IR/AffineExpr.h" diff --git a/mlir/lib/Dialect/GPU/Transforms/AsyncRegionRewriter.cpp b/mlir/lib/Dialect/GPU/Transforms/AsyncRegionRewriter.cpp index 40903f199afdddd268cb1acaa7cb7a2e5bc589e1..b2fa3a99c53fc37bd27a10b87a7a312caf7ae726 100644 --- a/mlir/lib/Dialect/GPU/Transforms/AsyncRegionRewriter.cpp +++ b/mlir/lib/Dialect/GPU/Transforms/AsyncRegionRewriter.cpp @@ -232,9 +232,8 @@ private: // control flow code. static bool areAllUsersExecuteOrAwait(Value token) { return !token.use_empty() && - llvm::all_of(token.getUsers(), [](Operation *user) { - return isa<async::ExecuteOp, async::AwaitOp>(user); - }); + llvm::all_of(token.getUsers(), + llvm::IsaPred<async::ExecuteOp, async::AwaitOp>); } // Add the `asyncToken` as dependency as needed after `op`. diff --git a/mlir/lib/Dialect/Index/IR/IndexDialect.cpp b/mlir/lib/Dialect/Index/IR/IndexDialect.cpp index d631afa63b9a2a8a6639e65fcfa2ba74b0f81b58..183d0e33b2523bf8ebbba54ca669c0a70c78a426 100644 --- a/mlir/lib/Dialect/Index/IR/IndexDialect.cpp +++ b/mlir/lib/Dialect/Index/IR/IndexDialect.cpp @@ -19,7 +19,7 @@ using namespace mlir::index; void IndexDialect::initialize() { registerAttributes(); registerOperations(); - declarePromisedInterface<IndexDialect, ConvertToLLVMPatternInterface>(); + declarePromisedInterface<ConvertToLLVMPatternInterface, IndexDialect>(); } //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp index 645a45dd96befbe4a504ec62d24064ae3e13edd4..a44e83313c9c1f999aa0a8c6a15c57f9d6a524b9 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp @@ -35,6 +35,7 @@ static LogicalResult parseExpressionArg(AsmParser &parser, uint64_t opcode, static void printExpressionArg(AsmPrinter &printer, uint64_t opcode, ArrayRef<uint64_t> args); +#include "mlir/Dialect/LLVMIR/LLVMAttrInterfaces.cpp.inc" #include "mlir/Dialect/LLVMIR/LLVMOpsEnums.cpp.inc" #define GET_ATTRDEF_CLASSES #include "mlir/Dialect/LLVMIR/LLVMOpsAttrDefs.cpp.inc" @@ -185,6 +186,24 @@ void printExpressionArg(AsmPrinter &printer, uint64_t opcode, }); } +//===----------------------------------------------------------------------===// +// DICompositeTypeAttr +//===----------------------------------------------------------------------===// + +DIRecursiveTypeAttrInterface +DICompositeTypeAttr::withRecId(DistinctAttr recId) { + return DICompositeTypeAttr::get(getContext(), getTag(), recId, getName(), + getFile(), getLine(), getScope(), + getBaseType(), getFlags(), getSizeInBits(), + getAlignInBits(), getElements()); +} + +DIRecursiveTypeAttrInterface +DICompositeTypeAttr::getRecSelf(DistinctAttr recId) { + return DICompositeTypeAttr::get(recId.getContext(), 0, recId, {}, {}, 0, {}, + {}, DIFlags(), 0, 0, {}); +} + //===----------------------------------------------------------------------===// // TargetFeaturesAttr //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp index 3ba6ac6ccc8142a8a55b9340305d630f53b219a8..e5c19a916392e18720b0163e15a7f13e41e67b74 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -2786,10 +2786,8 @@ LogicalResult LLVM::BitcastOp::verify() { if (!resultType) return success(); - auto isVector = [](Type type) { - return llvm::isa<VectorType, LLVMScalableVectorType, LLVMFixedVectorType>( - type); - }; + auto isVector = + llvm::IsaPred<VectorType, LLVMScalableVectorType, LLVMFixedVectorType>; // Due to bitcast requiring both operands to be of the same size, it is not // possible for only one of the two to be a pointer of vectors. diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp index bf24194d03ddb21e9cb63ecea51ba04930955cc3..06c1fdd2eb2d95833a35039f4ff2113cb6dfda03 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp @@ -13,15 +13,15 @@ #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/LLVMIR/LLVMTypes.h" -#include "mlir/IR/IRMapping.h" #include "mlir/IR/Matchers.h" #include "mlir/IR/PatternMatch.h" -#include "mlir/IR/ValueRange.h" #include "mlir/Interfaces/DataLayoutInterfaces.h" #include "mlir/Interfaces/MemorySlotInterfaces.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/TypeSwitch.h" +#define DEBUG_TYPE "sroa" + using namespace mlir; //===----------------------------------------------------------------------===// @@ -71,12 +71,8 @@ SmallVector<DestructurableMemorySlot> LLVM::AllocaOp::getDestructurableSlots() { if (!destructuredType) return {}; - DenseMap<Attribute, Type> allocaTypeMap; - for (Attribute index : llvm::make_first_range(destructuredType.value())) - allocaTypeMap.insert({index, LLVM::LLVMPointerType::get(getContext())}); - - return { - DestructurableMemorySlot{{getResult(), getElemType()}, {allocaTypeMap}}}; + return {DestructurableMemorySlot{{getResult(), getElemType()}, + *destructuredType}}; } DenseMap<Attribute, MemorySlot> @@ -132,7 +128,8 @@ Value LLVM::StoreOp::getStored(const MemorySlot &slot, RewriterBase &rewriter) { bool LLVM::LoadOp::canUsesBeRemoved( const MemorySlot &slot, const SmallPtrSetImpl<OpOperand *> &blockingUses, - SmallVectorImpl<OpOperand *> &newBlockingUses) { + SmallVectorImpl<OpOperand *> &newBlockingUses, + const DataLayout &dataLayout) { if (blockingUses.size() != 1) return false; Value blockingUse = (*blockingUses.begin())->get(); @@ -155,7 +152,8 @@ DeletionKind LLVM::LoadOp::removeBlockingUses( bool LLVM::StoreOp::canUsesBeRemoved( const MemorySlot &slot, const SmallPtrSetImpl<OpOperand *> &blockingUses, - SmallVectorImpl<OpOperand *> &newBlockingUses) { + SmallVectorImpl<OpOperand *> &newBlockingUses, + const DataLayout &dataLayout) { if (blockingUses.size() != 1) return false; Value blockingUse = (*blockingUses.begin())->get(); @@ -180,15 +178,111 @@ DeletionKind LLVM::StoreOp::removeBlockingUses( return DeletionKind::Delete; } +/// Checks if `slot` can be accessed through the provided access type. +static bool isValidAccessType(const MemorySlot &slot, Type accessType, + const DataLayout &dataLayout) { + return dataLayout.getTypeSize(accessType) <= + dataLayout.getTypeSize(slot.elemType); +} + LogicalResult LLVM::LoadOp::ensureOnlySafeAccesses( - const MemorySlot &slot, SmallVectorImpl<MemorySlot> &mustBeSafelyUsed) { - return success(getAddr() != slot.ptr || getType() == slot.elemType); + const MemorySlot &slot, SmallVectorImpl<MemorySlot> &mustBeSafelyUsed, + const DataLayout &dataLayout) { + return success(getAddr() != slot.ptr || + isValidAccessType(slot, getType(), dataLayout)); } LogicalResult LLVM::StoreOp::ensureOnlySafeAccesses( - const MemorySlot &slot, SmallVectorImpl<MemorySlot> &mustBeSafelyUsed) { + const MemorySlot &slot, SmallVectorImpl<MemorySlot> &mustBeSafelyUsed, + const DataLayout &dataLayout) { return success(getAddr() != slot.ptr || - getValue().getType() == slot.elemType); + isValidAccessType(slot, getValue().getType(), dataLayout)); +} + +/// Returns the subslot's type at the requested index. +static Type getTypeAtIndex(const DestructurableMemorySlot &slot, + Attribute index) { + auto subelementIndexMap = + slot.elemType.cast<DestructurableTypeInterface>().getSubelementIndexMap(); + if (!subelementIndexMap) + return {}; + assert(!subelementIndexMap->empty()); + + // Note: Returns a null-type when no entry was found. + return subelementIndexMap->lookup(index); +} + +bool LLVM::LoadOp::canRewire(const DestructurableMemorySlot &slot, + SmallPtrSetImpl<Attribute> &usedIndices, + SmallVectorImpl<MemorySlot> &mustBeSafelyUsed, + const DataLayout &dataLayout) { + if (getVolatile_()) + return false; + + // A load always accesses the first element of the destructured slot. + auto index = IntegerAttr::get(IntegerType::get(getContext(), 32), 0); + Type subslotType = getTypeAtIndex(slot, index); + if (!subslotType) + return false; + + // The access can only be replaced when the subslot is read within its bounds. + if (dataLayout.getTypeSize(getType()) > dataLayout.getTypeSize(subslotType)) + return false; + + usedIndices.insert(index); + return true; +} + +DeletionKind LLVM::LoadOp::rewire(const DestructurableMemorySlot &slot, + DenseMap<Attribute, MemorySlot> &subslots, + RewriterBase &rewriter, + const DataLayout &dataLayout) { + auto index = IntegerAttr::get(IntegerType::get(getContext(), 32), 0); + auto it = subslots.find(index); + assert(it != subslots.end()); + + rewriter.modifyOpInPlace( + *this, [&]() { getAddrMutable().set(it->getSecond().ptr); }); + return DeletionKind::Keep; +} + +bool LLVM::StoreOp::canRewire(const DestructurableMemorySlot &slot, + SmallPtrSetImpl<Attribute> &usedIndices, + SmallVectorImpl<MemorySlot> &mustBeSafelyUsed, + const DataLayout &dataLayout) { + if (getVolatile_()) + return false; + + // Storing the pointer to memory cannot be dealt with. + if (getValue() == slot.ptr) + return false; + + // A store always accesses the first element of the destructured slot. + auto index = IntegerAttr::get(IntegerType::get(getContext(), 32), 0); + Type subslotType = getTypeAtIndex(slot, index); + if (!subslotType) + return false; + + // The access can only be replaced when the subslot is read within its bounds. + if (dataLayout.getTypeSize(getValue().getType()) > + dataLayout.getTypeSize(subslotType)) + return false; + + usedIndices.insert(index); + return true; +} + +DeletionKind LLVM::StoreOp::rewire(const DestructurableMemorySlot &slot, + DenseMap<Attribute, MemorySlot> &subslots, + RewriterBase &rewriter, + const DataLayout &dataLayout) { + auto index = IntegerAttr::get(IntegerType::get(getContext(), 32), 0); + auto it = subslots.find(index); + assert(it != subslots.end()); + + rewriter.modifyOpInPlace( + *this, [&]() { getAddrMutable().set(it->getSecond().ptr); }); + return DeletionKind::Keep; } //===----------------------------------------------------------------------===// @@ -206,7 +300,8 @@ static bool forwardToUsers(Operation *op, bool LLVM::BitcastOp::canUsesBeRemoved( const SmallPtrSetImpl<OpOperand *> &blockingUses, - SmallVectorImpl<OpOperand *> &newBlockingUses) { + SmallVectorImpl<OpOperand *> &newBlockingUses, + const DataLayout &dataLayout) { return forwardToUsers(*this, newBlockingUses); } @@ -217,7 +312,8 @@ DeletionKind LLVM::BitcastOp::removeBlockingUses( bool LLVM::AddrSpaceCastOp::canUsesBeRemoved( const SmallPtrSetImpl<OpOperand *> &blockingUses, - SmallVectorImpl<OpOperand *> &newBlockingUses) { + SmallVectorImpl<OpOperand *> &newBlockingUses, + const DataLayout &dataLayout) { return forwardToUsers(*this, newBlockingUses); } @@ -228,7 +324,8 @@ DeletionKind LLVM::AddrSpaceCastOp::removeBlockingUses( bool LLVM::LifetimeStartOp::canUsesBeRemoved( const SmallPtrSetImpl<OpOperand *> &blockingUses, - SmallVectorImpl<OpOperand *> &newBlockingUses) { + SmallVectorImpl<OpOperand *> &newBlockingUses, + const DataLayout &dataLayout) { return true; } @@ -239,7 +336,8 @@ DeletionKind LLVM::LifetimeStartOp::removeBlockingUses( bool LLVM::LifetimeEndOp::canUsesBeRemoved( const SmallPtrSetImpl<OpOperand *> &blockingUses, - SmallVectorImpl<OpOperand *> &newBlockingUses) { + SmallVectorImpl<OpOperand *> &newBlockingUses, + const DataLayout &dataLayout) { return true; } @@ -250,7 +348,8 @@ DeletionKind LLVM::LifetimeEndOp::removeBlockingUses( bool LLVM::InvariantStartOp::canUsesBeRemoved( const SmallPtrSetImpl<OpOperand *> &blockingUses, - SmallVectorImpl<OpOperand *> &newBlockingUses) { + SmallVectorImpl<OpOperand *> &newBlockingUses, + const DataLayout &dataLayout) { return true; } @@ -261,7 +360,8 @@ DeletionKind LLVM::InvariantStartOp::removeBlockingUses( bool LLVM::InvariantEndOp::canUsesBeRemoved( const SmallPtrSetImpl<OpOperand *> &blockingUses, - SmallVectorImpl<OpOperand *> &newBlockingUses) { + SmallVectorImpl<OpOperand *> &newBlockingUses, + const DataLayout &dataLayout) { return true; } @@ -272,7 +372,8 @@ DeletionKind LLVM::InvariantEndOp::removeBlockingUses( bool LLVM::DbgDeclareOp::canUsesBeRemoved( const SmallPtrSetImpl<OpOperand *> &blockingUses, - SmallVectorImpl<OpOperand *> &newBlockingUses) { + SmallVectorImpl<OpOperand *> &newBlockingUses, + const DataLayout &dataLayout) { return true; } @@ -283,7 +384,8 @@ DeletionKind LLVM::DbgDeclareOp::removeBlockingUses( bool LLVM::DbgValueOp::canUsesBeRemoved( const SmallPtrSetImpl<OpOperand *> &blockingUses, - SmallVectorImpl<OpOperand *> &newBlockingUses) { + SmallVectorImpl<OpOperand *> &newBlockingUses, + const DataLayout &dataLayout) { // There is only one operand that we can remove the use of. if (blockingUses.size() != 1) return false; @@ -318,7 +420,8 @@ static bool hasAllZeroIndices(LLVM::GEPOp gepOp) { bool LLVM::GEPOp::canUsesBeRemoved( const SmallPtrSetImpl<OpOperand *> &blockingUses, - SmallVectorImpl<OpOperand *> &newBlockingUses) { + SmallVectorImpl<OpOperand *> &newBlockingUses, + const DataLayout &dataLayout) { // GEP can be removed as long as it is a no-op and its users can be removed. if (!hasAllZeroIndices(*this)) return false; @@ -330,85 +433,214 @@ DeletionKind LLVM::GEPOp::removeBlockingUses( return DeletionKind::Delete; } -static bool isFirstIndexZero(LLVM::GEPOp gep) { - IntegerAttr index = - llvm::dyn_cast_if_present<IntegerAttr>(gep.getIndices()[0]); - return index && index.getInt() == 0; +/// Returns the amount of bytes the provided GEP elements will offset the +/// pointer by. Returns nullopt if no constant offset could be computed. +static std::optional<uint64_t> gepToByteOffset(const DataLayout &dataLayout, + LLVM::GEPOp gep) { + // Collects all indices. + SmallVector<uint64_t> indices; + for (auto index : gep.getIndices()) { + auto constIndex = dyn_cast<IntegerAttr>(index); + if (!constIndex) + return {}; + int64_t gepIndex = constIndex.getInt(); + // Negative indices are not supported. + if (gepIndex < 0) + return {}; + indices.push_back(gepIndex); + } + + Type currentType = gep.getElemType(); + uint64_t offset = indices[0] * dataLayout.getTypeSize(currentType); + + for (uint64_t index : llvm::drop_begin(indices)) { + bool shouldCancel = + TypeSwitch<Type, bool>(currentType) + .Case([&](LLVM::LLVMArrayType arrayType) { + offset += + index * dataLayout.getTypeSize(arrayType.getElementType()); + currentType = arrayType.getElementType(); + return false; + }) + .Case([&](LLVM::LLVMStructType structType) { + ArrayRef<Type> body = structType.getBody(); + assert(index < body.size() && "expected valid struct indexing"); + for (uint32_t i : llvm::seq(index)) { + if (!structType.isPacked()) + offset = llvm::alignTo( + offset, dataLayout.getTypeABIAlignment(body[i])); + offset += dataLayout.getTypeSize(body[i]); + } + + // Align for the current type as well. + if (!structType.isPacked()) + offset = llvm::alignTo( + offset, dataLayout.getTypeABIAlignment(body[index])); + currentType = body[index]; + return false; + }) + .Default([&](Type type) { + LLVM_DEBUG(llvm::dbgs() + << "[sroa] Unsupported type for offset computations" + << type << "\n"); + return true; + }); + + if (shouldCancel) + return std::nullopt; + } + + return offset; +} + +namespace { +/// A struct that stores both the index into the aggregate type of the slot as +/// well as the corresponding byte offset in memory. +struct SubslotAccessInfo { + /// The parent slot's index that the access falls into. + uint32_t index; + /// The offset into the subslot of the access. + uint64_t subslotOffset; +}; +} // namespace + +/// Computes subslot access information for an access into `slot` with the given +/// offset. +/// Returns nullopt when the offset is out-of-bounds or when the access is into +/// the padding of `slot`. +static std::optional<SubslotAccessInfo> +getSubslotAccessInfo(const DestructurableMemorySlot &slot, + const DataLayout &dataLayout, LLVM::GEPOp gep) { + std::optional<uint64_t> offset = gepToByteOffset(dataLayout, gep); + if (!offset) + return {}; + + // Helper to check that a constant index is in the bounds of the GEP index + // representation. LLVM dialects's GEP arguments have a limited bitwidth, thus + // this additional check is necessary. + auto isOutOfBoundsGEPIndex = [](uint64_t index) { + return index >= (1 << LLVM::kGEPConstantBitWidth); + }; + + Type type = slot.elemType; + if (*offset >= dataLayout.getTypeSize(type)) + return {}; + return TypeSwitch<Type, std::optional<SubslotAccessInfo>>(type) + .Case([&](LLVM::LLVMArrayType arrayType) + -> std::optional<SubslotAccessInfo> { + // Find which element of the array contains the offset. + uint64_t elemSize = dataLayout.getTypeSize(arrayType.getElementType()); + uint64_t index = *offset / elemSize; + if (isOutOfBoundsGEPIndex(index)) + return {}; + return SubslotAccessInfo{static_cast<uint32_t>(index), + *offset - (index * elemSize)}; + }) + .Case([&](LLVM::LLVMStructType structType) + -> std::optional<SubslotAccessInfo> { + uint64_t distanceToStart = 0; + // Walk over the elements of the struct to find in which of + // them the offset is. + for (auto [index, elem] : llvm::enumerate(structType.getBody())) { + uint64_t elemSize = dataLayout.getTypeSize(elem); + if (!structType.isPacked()) { + distanceToStart = llvm::alignTo( + distanceToStart, dataLayout.getTypeABIAlignment(elem)); + // If the offset is in padding, cancel the rewrite. + if (offset < distanceToStart) + return {}; + } + + if (offset < distanceToStart + elemSize) { + if (isOutOfBoundsGEPIndex(index)) + return {}; + // The offset is within this element, stop iterating the + // struct and return the index. + return SubslotAccessInfo{static_cast<uint32_t>(index), + *offset - distanceToStart}; + } + + // The offset is not within this element, continue walking + // over the struct. + distanceToStart += elemSize; + } + + return {}; + }); +} + +/// Constructs a byte array type of the given size. +static LLVM::LLVMArrayType getByteArrayType(MLIRContext *context, + unsigned size) { + auto byteType = IntegerType::get(context, 8); + return LLVM::LLVMArrayType::get(context, byteType, size); } LogicalResult LLVM::GEPOp::ensureOnlySafeAccesses( - const MemorySlot &slot, SmallVectorImpl<MemorySlot> &mustBeSafelyUsed) { + const MemorySlot &slot, SmallVectorImpl<MemorySlot> &mustBeSafelyUsed, + const DataLayout &dataLayout) { if (getBase() != slot.ptr) return success(); - if (slot.elemType != getElemType()) - return failure(); - if (!isFirstIndexZero(*this)) + std::optional<uint64_t> gepOffset = gepToByteOffset(dataLayout, *this); + if (!gepOffset) return failure(); - Type reachedType = getResultPtrElementType(); - if (!reachedType) + uint64_t slotSize = dataLayout.getTypeSize(slot.elemType); + // Check that the access is strictly inside the slot. + if (*gepOffset >= slotSize) return failure(); - mustBeSafelyUsed.emplace_back<MemorySlot>({getResult(), reachedType}); + // Every access that remains in bounds of the remaining slot is considered + // legal. + mustBeSafelyUsed.emplace_back<MemorySlot>( + {getRes(), getByteArrayType(getContext(), slotSize - *gepOffset)}); return success(); } bool LLVM::GEPOp::canRewire(const DestructurableMemorySlot &slot, SmallPtrSetImpl<Attribute> &usedIndices, - SmallVectorImpl<MemorySlot> &mustBeSafelyUsed) { - auto basePtrType = llvm::dyn_cast<LLVM::LLVMPointerType>(getBase().getType()); - if (!basePtrType) + SmallVectorImpl<MemorySlot> &mustBeSafelyUsed, + const DataLayout &dataLayout) { + if (!isa<LLVM::LLVMPointerType>(getBase().getType())) return false; - if (getBase() != slot.ptr || slot.elemType != getElemType()) - return false; - if (!isFirstIndexZero(*this)) - return false; - Type reachedType = getResultPtrElementType(); - if (!reachedType || getIndices().size() < 2) - return false; - auto firstLevelIndex = dyn_cast<IntegerAttr>(getIndices()[1]); - if (!firstLevelIndex) + if (getBase() != slot.ptr) return false; - assert(slot.elementPtrs.contains(firstLevelIndex)); - if (!llvm::isa<LLVM::LLVMPointerType>(slot.elementPtrs.at(firstLevelIndex))) + std::optional<SubslotAccessInfo> accessInfo = + getSubslotAccessInfo(slot, dataLayout, *this); + if (!accessInfo) return false; - mustBeSafelyUsed.emplace_back<MemorySlot>({getResult(), reachedType}); - usedIndices.insert(firstLevelIndex); + auto indexAttr = + IntegerAttr::get(IntegerType::get(getContext(), 32), accessInfo->index); + assert(slot.elementPtrs.contains(indexAttr)); + usedIndices.insert(indexAttr); + + // The remainder of the subslot should be accesses in-bounds. Thus, we create + // a dummy slot with the size of the remainder. + Type subslotType = slot.elementPtrs.lookup(indexAttr); + uint64_t slotSize = dataLayout.getTypeSize(subslotType); + LLVM::LLVMArrayType remainingSlotType = + getByteArrayType(getContext(), slotSize - accessInfo->subslotOffset); + mustBeSafelyUsed.emplace_back<MemorySlot>({getRes(), remainingSlotType}); + return true; } DeletionKind LLVM::GEPOp::rewire(const DestructurableMemorySlot &slot, DenseMap<Attribute, MemorySlot> &subslots, - RewriterBase &rewriter) { - IntegerAttr firstLevelIndex = - llvm::dyn_cast_if_present<IntegerAttr>(getIndices()[1]); - const MemorySlot &newSlot = subslots.at(firstLevelIndex); - - ArrayRef<int32_t> remainingIndices = getRawConstantIndices().slice(2); - - // If the GEP would become trivial after this transformation, eliminate it. - // A GEP should only be eliminated if it has no indices (except the first - // pointer index), as simplifying GEPs with all-zero indices would eliminate - // structure information useful for further destruction. - if (remainingIndices.empty()) { - rewriter.replaceAllUsesWith(getResult(), newSlot.ptr); - return DeletionKind::Delete; - } - - rewriter.modifyOpInPlace(*this, [&]() { - // Rewire the indices by popping off the second index. - // Start with a single zero, then add the indices beyond the second. - SmallVector<int32_t> newIndices(1); - newIndices.append(remainingIndices.begin(), remainingIndices.end()); - setRawConstantIndices(newIndices); - - // Rewire the pointed type. - setElemType(newSlot.elemType); - - // Rewire the pointer. - getBaseMutable().assign(newSlot.ptr); - }); - - return DeletionKind::Keep; + RewriterBase &rewriter, + const DataLayout &dataLayout) { + std::optional<SubslotAccessInfo> accessInfo = + getSubslotAccessInfo(slot, dataLayout, *this); + assert(accessInfo && "expected access info to be checked before"); + auto indexAttr = + IntegerAttr::get(IntegerType::get(getContext(), 32), accessInfo->index); + const MemorySlot &newSlot = subslots.at(indexAttr); + + auto byteType = IntegerType::get(rewriter.getContext(), 8); + auto newPtr = rewriter.createOrFold<LLVM::GEPOp>( + getLoc(), getResult().getType(), byteType, newSlot.ptr, + ArrayRef<GEPArg>(accessInfo->subslotOffset), getInbounds()); + rewriter.replaceAllUsesWith(getResult(), newPtr); + return DeletionKind::Delete; } //===----------------------------------------------------------------------===// @@ -447,7 +679,7 @@ std::optional<uint64_t> getStaticMemIntrLen(LLVM::MemcpyInlineOp op) { /// of the bounds of the given slot, on a best-effort basis. template <class MemIntr> static bool definitelyWritesOnlyWithinSlot(MemIntr op, const MemorySlot &slot, - DataLayout &dataLayout) { + const DataLayout &dataLayout) { if (!isa<LLVM::LLVMPointerType>(slot.ptr.getType()) || op.getDst() != slot.ptr) return false; @@ -512,7 +744,8 @@ Value LLVM::MemsetOp::getStored(const MemorySlot &slot, bool LLVM::MemsetOp::canUsesBeRemoved( const MemorySlot &slot, const SmallPtrSetImpl<OpOperand *> &blockingUses, - SmallVectorImpl<OpOperand *> &newBlockingUses) { + SmallVectorImpl<OpOperand *> &newBlockingUses, + const DataLayout &dataLayout) { // TODO: Support non-integer types. bool canConvertType = TypeSwitch<Type, bool>(slot.elemType) @@ -526,8 +759,7 @@ bool LLVM::MemsetOp::canUsesBeRemoved( if (getIsVolatile()) return false; - DataLayout layout = DataLayout::closest(*this); - return getStaticMemIntrLen(*this) == layout.getTypeSize(slot.elemType); + return getStaticMemIntrLen(*this) == dataLayout.getTypeSize(slot.elemType); } DeletionKind LLVM::MemsetOp::removeBlockingUses( @@ -537,14 +769,15 @@ DeletionKind LLVM::MemsetOp::removeBlockingUses( } LogicalResult LLVM::MemsetOp::ensureOnlySafeAccesses( - const MemorySlot &slot, SmallVectorImpl<MemorySlot> &mustBeSafelyUsed) { - DataLayout dataLayout = DataLayout::closest(*this); + const MemorySlot &slot, SmallVectorImpl<MemorySlot> &mustBeSafelyUsed, + const DataLayout &dataLayout) { return success(definitelyWritesOnlyWithinSlot(*this, slot, dataLayout)); } bool LLVM::MemsetOp::canRewire(const DestructurableMemorySlot &slot, SmallPtrSetImpl<Attribute> &usedIndices, - SmallVectorImpl<MemorySlot> &mustBeSafelyUsed) { + SmallVectorImpl<MemorySlot> &mustBeSafelyUsed, + const DataLayout &dataLayout) { if (&slot.elemType.getDialect() != getOperation()->getDialect()) return false; @@ -558,13 +791,13 @@ bool LLVM::MemsetOp::canRewire(const DestructurableMemorySlot &slot, if (!areAllIndicesI32(slot)) return false; - DataLayout dataLayout = DataLayout::closest(*this); return definitelyWritesOnlyWithinSlot(*this, slot, dataLayout); } DeletionKind LLVM::MemsetOp::rewire(const DestructurableMemorySlot &slot, DenseMap<Attribute, MemorySlot> &subslots, - RewriterBase &rewriter) { + RewriterBase &rewriter, + const DataLayout &dataLayout) { std::optional<DenseMap<Attribute, Type>> types = slot.elemType.cast<DestructurableTypeInterface>().getSubelementIndexMap(); @@ -579,7 +812,6 @@ DeletionKind LLVM::MemsetOp::rewire(const DestructurableMemorySlot &slot, packed = structType.isPacked(); Type i32 = IntegerType::get(getContext(), 32); - DataLayout dataLayout = DataLayout::closest(*this); uint64_t memsetLen = memsetLenAttr.getValue().getZExtValue(); uint64_t covered = 0; for (size_t i = 0; i < types->size(); i++) { @@ -642,7 +874,8 @@ template <class MemcpyLike> static bool memcpyCanUsesBeRemoved(MemcpyLike op, const MemorySlot &slot, const SmallPtrSetImpl<OpOperand *> &blockingUses, - SmallVectorImpl<OpOperand *> &newBlockingUses) { + SmallVectorImpl<OpOperand *> &newBlockingUses, + const DataLayout &dataLayout) { // If source and destination are the same, memcpy behavior is undefined and // memmove is a no-op. Because there is no memory change happening here, // simplifying such operations is left to canonicalization. @@ -652,8 +885,7 @@ memcpyCanUsesBeRemoved(MemcpyLike op, const MemorySlot &slot, if (op.getIsVolatile()) return false; - DataLayout layout = DataLayout::closest(op); - return getStaticMemIntrLen(op) == layout.getTypeSize(slot.elemType); + return getStaticMemIntrLen(op) == dataLayout.getTypeSize(slot.elemType); } template <class MemcpyLike> @@ -681,7 +913,8 @@ memcpyEnsureOnlySafeAccesses(MemcpyLike op, const MemorySlot &slot, template <class MemcpyLike> static bool memcpyCanRewire(MemcpyLike op, const DestructurableMemorySlot &slot, SmallPtrSetImpl<Attribute> &usedIndices, - SmallVectorImpl<MemorySlot> &mustBeSafelyUsed) { + SmallVectorImpl<MemorySlot> &mustBeSafelyUsed, + const DataLayout &dataLayout) { if (op.getIsVolatile()) return false; @@ -693,7 +926,6 @@ static bool memcpyCanRewire(MemcpyLike op, const DestructurableMemorySlot &slot, return false; // Only full copies are supported. - DataLayout dataLayout = DataLayout::closest(op); if (getStaticMemIntrLen(op) != dataLayout.getTypeSize(slot.elemType)) return false; @@ -733,15 +965,13 @@ void createMemcpyLikeToReplace(RewriterBase &rewriter, const DataLayout &layout, /// Rewires a memcpy-like operation. Only copies to or from the full slot are /// supported. template <class MemcpyLike> -static DeletionKind memcpyRewire(MemcpyLike op, - const DestructurableMemorySlot &slot, - DenseMap<Attribute, MemorySlot> &subslots, - RewriterBase &rewriter) { +static DeletionKind +memcpyRewire(MemcpyLike op, const DestructurableMemorySlot &slot, + DenseMap<Attribute, MemorySlot> &subslots, RewriterBase &rewriter, + const DataLayout &dataLayout) { if (subslots.empty()) return DeletionKind::Delete; - DataLayout layout = DataLayout::closest(op); - assert((slot.ptr == op.getDst()) != (slot.ptr == op.getSrc())); bool isDst = slot.ptr == op.getDst(); @@ -772,7 +1002,7 @@ static DeletionKind memcpyRewire(MemcpyLike op, isDst ? op.getSrc() : op.getDst(), gepIndices); // Then create a new memcpy out of this source pointer. - createMemcpyLikeToReplace(rewriter, layout, op, + createMemcpyLikeToReplace(rewriter, dataLayout, op, isDst ? subslot.ptr : subslotPtrInOther, isDst ? subslotPtrInOther : subslot.ptr, subslot.elemType, op.getIsVolatile()); @@ -798,8 +1028,10 @@ Value LLVM::MemcpyOp::getStored(const MemorySlot &slot, bool LLVM::MemcpyOp::canUsesBeRemoved( const MemorySlot &slot, const SmallPtrSetImpl<OpOperand *> &blockingUses, - SmallVectorImpl<OpOperand *> &newBlockingUses) { - return memcpyCanUsesBeRemoved(*this, slot, blockingUses, newBlockingUses); + SmallVectorImpl<OpOperand *> &newBlockingUses, + const DataLayout &dataLayout) { + return memcpyCanUsesBeRemoved(*this, slot, blockingUses, newBlockingUses, + dataLayout); } DeletionKind LLVM::MemcpyOp::removeBlockingUses( @@ -810,20 +1042,24 @@ DeletionKind LLVM::MemcpyOp::removeBlockingUses( } LogicalResult LLVM::MemcpyOp::ensureOnlySafeAccesses( - const MemorySlot &slot, SmallVectorImpl<MemorySlot> &mustBeSafelyUsed) { + const MemorySlot &slot, SmallVectorImpl<MemorySlot> &mustBeSafelyUsed, + const DataLayout &dataLayout) { return memcpyEnsureOnlySafeAccesses(*this, slot, mustBeSafelyUsed); } bool LLVM::MemcpyOp::canRewire(const DestructurableMemorySlot &slot, SmallPtrSetImpl<Attribute> &usedIndices, - SmallVectorImpl<MemorySlot> &mustBeSafelyUsed) { - return memcpyCanRewire(*this, slot, usedIndices, mustBeSafelyUsed); + SmallVectorImpl<MemorySlot> &mustBeSafelyUsed, + const DataLayout &dataLayout) { + return memcpyCanRewire(*this, slot, usedIndices, mustBeSafelyUsed, + dataLayout); } DeletionKind LLVM::MemcpyOp::rewire(const DestructurableMemorySlot &slot, DenseMap<Attribute, MemorySlot> &subslots, - RewriterBase &rewriter) { - return memcpyRewire(*this, slot, subslots, rewriter); + RewriterBase &rewriter, + const DataLayout &dataLayout) { + return memcpyRewire(*this, slot, subslots, rewriter, dataLayout); } bool LLVM::MemcpyInlineOp::loadsFrom(const MemorySlot &slot) { @@ -841,8 +1077,10 @@ Value LLVM::MemcpyInlineOp::getStored(const MemorySlot &slot, bool LLVM::MemcpyInlineOp::canUsesBeRemoved( const MemorySlot &slot, const SmallPtrSetImpl<OpOperand *> &blockingUses, - SmallVectorImpl<OpOperand *> &newBlockingUses) { - return memcpyCanUsesBeRemoved(*this, slot, blockingUses, newBlockingUses); + SmallVectorImpl<OpOperand *> &newBlockingUses, + const DataLayout &dataLayout) { + return memcpyCanUsesBeRemoved(*this, slot, blockingUses, newBlockingUses, + dataLayout); } DeletionKind LLVM::MemcpyInlineOp::removeBlockingUses( @@ -853,22 +1091,26 @@ DeletionKind LLVM::MemcpyInlineOp::removeBlockingUses( } LogicalResult LLVM::MemcpyInlineOp::ensureOnlySafeAccesses( - const MemorySlot &slot, SmallVectorImpl<MemorySlot> &mustBeSafelyUsed) { + const MemorySlot &slot, SmallVectorImpl<MemorySlot> &mustBeSafelyUsed, + const DataLayout &dataLayout) { return memcpyEnsureOnlySafeAccesses(*this, slot, mustBeSafelyUsed); } bool LLVM::MemcpyInlineOp::canRewire( const DestructurableMemorySlot &slot, SmallPtrSetImpl<Attribute> &usedIndices, - SmallVectorImpl<MemorySlot> &mustBeSafelyUsed) { - return memcpyCanRewire(*this, slot, usedIndices, mustBeSafelyUsed); + SmallVectorImpl<MemorySlot> &mustBeSafelyUsed, + const DataLayout &dataLayout) { + return memcpyCanRewire(*this, slot, usedIndices, mustBeSafelyUsed, + dataLayout); } DeletionKind LLVM::MemcpyInlineOp::rewire(const DestructurableMemorySlot &slot, DenseMap<Attribute, MemorySlot> &subslots, - RewriterBase &rewriter) { - return memcpyRewire(*this, slot, subslots, rewriter); + RewriterBase &rewriter, + const DataLayout &dataLayout) { + return memcpyRewire(*this, slot, subslots, rewriter, dataLayout); } bool LLVM::MemmoveOp::loadsFrom(const MemorySlot &slot) { @@ -886,8 +1128,10 @@ Value LLVM::MemmoveOp::getStored(const MemorySlot &slot, bool LLVM::MemmoveOp::canUsesBeRemoved( const MemorySlot &slot, const SmallPtrSetImpl<OpOperand *> &blockingUses, - SmallVectorImpl<OpOperand *> &newBlockingUses) { - return memcpyCanUsesBeRemoved(*this, slot, blockingUses, newBlockingUses); + SmallVectorImpl<OpOperand *> &newBlockingUses, + const DataLayout &dataLayout) { + return memcpyCanUsesBeRemoved(*this, slot, blockingUses, newBlockingUses, + dataLayout); } DeletionKind LLVM::MemmoveOp::removeBlockingUses( @@ -898,20 +1142,24 @@ DeletionKind LLVM::MemmoveOp::removeBlockingUses( } LogicalResult LLVM::MemmoveOp::ensureOnlySafeAccesses( - const MemorySlot &slot, SmallVectorImpl<MemorySlot> &mustBeSafelyUsed) { + const MemorySlot &slot, SmallVectorImpl<MemorySlot> &mustBeSafelyUsed, + const DataLayout &dataLayout) { return memcpyEnsureOnlySafeAccesses(*this, slot, mustBeSafelyUsed); } bool LLVM::MemmoveOp::canRewire(const DestructurableMemorySlot &slot, SmallPtrSetImpl<Attribute> &usedIndices, - SmallVectorImpl<MemorySlot> &mustBeSafelyUsed) { - return memcpyCanRewire(*this, slot, usedIndices, mustBeSafelyUsed); + SmallVectorImpl<MemorySlot> &mustBeSafelyUsed, + const DataLayout &dataLayout) { + return memcpyCanRewire(*this, slot, usedIndices, mustBeSafelyUsed, + dataLayout); } DeletionKind LLVM::MemmoveOp::rewire(const DestructurableMemorySlot &slot, DenseMap<Attribute, MemorySlot> &subslots, - RewriterBase &rewriter) { - return memcpyRewire(*this, slot, subslots, rewriter); + RewriterBase &rewriter, + const DataLayout &dataLayout) { + return memcpyRewire(*this, slot, subslots, rewriter, dataLayout); } //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp index 443e245887ea8e5bb762915968bbf8514ab332f5..630187f220a4ba8ac9ab3bbff3af5a3f11bf1e16 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp @@ -287,15 +287,22 @@ getPointerDataLayoutEntry(DataLayoutEntryListRef params, LLVMPointerType type, } } if (currentEntry) { - return *extractPointerSpecValue(currentEntry, pos) / - (pos == PtrDLEntryPos::Size ? 1 : kBitsInByte); + std::optional<uint64_t> value = extractPointerSpecValue(currentEntry, pos); + // If the optional `PtrDLEntryPos::Index` entry is not available, use the + // pointer size as the index bitwidth. + if (!value && pos == PtrDLEntryPos::Index) + value = extractPointerSpecValue(currentEntry, PtrDLEntryPos::Size); + bool isSizeOrIndex = + pos == PtrDLEntryPos::Size || pos == PtrDLEntryPos::Index; + return *value / (isSizeOrIndex ? 1 : kBitsInByte); } // If not found, and this is the pointer to the default memory space, assume // 64-bit pointers. if (type.getAddressSpace() == 0) { - return pos == PtrDLEntryPos::Size ? kDefaultPointerSizeBits - : kDefaultPointerAlignment; + bool isSizeOrIndex = + pos == PtrDLEntryPos::Size || pos == PtrDLEntryPos::Index; + return isSizeOrIndex ? kDefaultPointerSizeBits : kDefaultPointerAlignment; } return std::nullopt; @@ -332,6 +339,16 @@ LLVMPointerType::getPreferredAlignment(const DataLayout &dataLayout, return dataLayout.getTypePreferredAlignment(get(getContext())); } +std::optional<uint64_t> +LLVMPointerType::getIndexBitwidth(const DataLayout &dataLayout, + DataLayoutEntryListRef params) const { + if (std::optional<uint64_t> indexBitwidth = + getPointerDataLayoutEntry(params, *this, PtrDLEntryPos::Index)) + return *indexBitwidth; + + return dataLayout.getTypeIndexBitwidth(get(getContext())); +} + bool LLVMPointerType::areCompatible(DataLayoutEntryListRef oldLayout, DataLayoutEntryListRef newLayout) const { for (DataLayoutEntryInterface newEntry : newLayout) { diff --git a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp index 4780ec09b81b9bb89ad6ee80741fd146fe5dc5ff..94197e473ce012741b53c796ca7d43030a05a7cc 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp @@ -214,8 +214,7 @@ void MmaOp::print(OpAsmPrinter &p) { p.printOptionalAttrDict(this->getOperation()->getAttrs(), ignoreAttrNames); // Print the types of the operands and result. - p << " : " - << "("; + p << " : " << "("; llvm::interleaveComma(SmallVector<Type, 3>{frags[0].regs[0].getType(), frags[1].regs[0].getType(), frags[2].regs[0].getType()}, @@ -956,9 +955,7 @@ std::string NVVM::WgmmaMmaAsyncOp::getPtx() { ss << "},"; // Need to map read/write registers correctly. regCnt = (regCnt * 2); - ss << " $" << (regCnt) << "," - << " $" << (regCnt + 1) << "," - << " p"; + ss << " $" << (regCnt) << "," << " $" << (regCnt + 1) << "," << " p"; if (getTypeD() != WGMMATypes::s32) { ss << ", $" << (regCnt + 3) << ", $" << (regCnt + 4); } @@ -1047,8 +1044,8 @@ void NVVMDialect::initialize() { // Support unknown operations because not all NVVM operations are // registered. allowUnknownOperations(); - declarePromisedInterface<NVVMDialect, ConvertToLLVMPatternInterface>(); - declarePromisedInterface<NVVMTargetAttr, gpu::TargetAttrInterface>(); + declarePromisedInterface<ConvertToLLVMPatternInterface, NVVMDialect>(); + declarePromisedInterface<gpu::TargetAttrInterface, NVVMTargetAttr>(); } LogicalResult NVVMDialect::verifyOperationAttribute(Operation *op, diff --git a/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp index 0f2e75cd7e8bc70b40e22d528033e0e2641ca2e8..65b770ae3261067e4ecec5d9178c8303539ddec1 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/ROCDLDialect.cpp @@ -247,7 +247,7 @@ void ROCDLDialect::initialize() { // Support unknown operations because not all ROCDL operations are registered. allowUnknownOperations(); - declarePromisedInterface<ROCDLTargetAttr, gpu::TargetAttrInterface>(); + declarePromisedInterface<gpu::TargetAttrInterface, ROCDLTargetAttr>(); } LogicalResult ROCDLDialect::verifyOperationAttribute(Operation *op, diff --git a/mlir/lib/Dialect/LLVMIR/Transforms/TypeConsistency.cpp b/mlir/lib/Dialect/LLVMIR/Transforms/TypeConsistency.cpp index b25c831bc7172a3cabdb5abf1ccbe7397cc19314..3d700fe94e3b9c9ecd16ff1213720dda3f955bbd 100644 --- a/mlir/lib/Dialect/LLVMIR/Transforms/TypeConsistency.cpp +++ b/mlir/lib/Dialect/LLVMIR/Transforms/TypeConsistency.cpp @@ -49,104 +49,6 @@ static bool areBitcastCompatible(DataLayout &layout, Type lhs, Type rhs) { layout.getTypeSize(lhs) == layout.getTypeSize(rhs)); } -//===----------------------------------------------------------------------===// -// AddFieldGetterToStructDirectUse -//===----------------------------------------------------------------------===// - -/// Gets the type of the first subelement of `type` if `type` is destructurable, -/// nullptr otherwise. -static Type getFirstSubelementType(Type type) { - auto destructurable = dyn_cast<DestructurableTypeInterface>(type); - if (!destructurable) - return nullptr; - - Type subelementType = destructurable.getTypeAtIndex( - IntegerAttr::get(IntegerType::get(type.getContext(), 32), 0)); - if (subelementType) - return subelementType; - - return nullptr; -} - -/// Extracts a pointer to the first field of an `elemType` from the address -/// pointer of the provided MemOp, and rewires the MemOp so it uses that pointer -/// instead. -template <class MemOp> -static void insertFieldIndirection(MemOp op, PatternRewriter &rewriter, - Type elemType) { - PatternRewriter::InsertionGuard guard(rewriter); - - rewriter.setInsertionPointAfterValue(op.getAddr()); - SmallVector<GEPArg> firstTypeIndices{0, 0}; - - Value properPtr = rewriter.create<GEPOp>( - op->getLoc(), LLVM::LLVMPointerType::get(op.getContext()), elemType, - op.getAddr(), firstTypeIndices); - - rewriter.modifyOpInPlace(op, - [&]() { op.getAddrMutable().assign(properPtr); }); -} - -template <> -LogicalResult AddFieldGetterToStructDirectUse<LoadOp>::matchAndRewrite( - LoadOp load, PatternRewriter &rewriter) const { - PatternRewriter::InsertionGuard guard(rewriter); - - Type inconsistentElementType = - isElementTypeInconsistent(load.getAddr(), load.getType()); - if (!inconsistentElementType) - return failure(); - Type firstType = getFirstSubelementType(inconsistentElementType); - if (!firstType) - return failure(); - DataLayout layout = DataLayout::closest(load); - if (!areBitcastCompatible(layout, firstType, load.getResult().getType())) - return failure(); - - insertFieldIndirection<LoadOp>(load, rewriter, inconsistentElementType); - - // If the load does not use the first type but a type that can be casted from - // it, add a bitcast and change the load type. - if (firstType != load.getResult().getType()) { - rewriter.setInsertionPointAfterValue(load.getResult()); - BitcastOp bitcast = rewriter.create<BitcastOp>( - load->getLoc(), load.getResult().getType(), load.getResult()); - rewriter.modifyOpInPlace(load, - [&]() { load.getResult().setType(firstType); }); - rewriter.replaceAllUsesExcept(load.getResult(), bitcast.getResult(), - bitcast); - } - - return success(); -} - -template <> -LogicalResult AddFieldGetterToStructDirectUse<StoreOp>::matchAndRewrite( - StoreOp store, PatternRewriter &rewriter) const { - PatternRewriter::InsertionGuard guard(rewriter); - - Type inconsistentElementType = - isElementTypeInconsistent(store.getAddr(), store.getValue().getType()); - if (!inconsistentElementType) - return failure(); - Type firstType = getFirstSubelementType(inconsistentElementType); - if (!firstType) - return failure(); - - DataLayout layout = DataLayout::closest(store); - // Check that the first field has the right type or can at least be bitcast - // to the right type. - if (!areBitcastCompatible(layout, firstType, store.getValue().getType())) - return failure(); - - insertFieldIndirection<StoreOp>(store, rewriter, inconsistentElementType); - - rewriter.modifyOpInPlace( - store, [&]() { store.getValueMutable().assign(store.getValue()); }); - - return success(); -} - //===----------------------------------------------------------------------===// // CanonicalizeAlignedGep //===----------------------------------------------------------------------===// @@ -684,9 +586,6 @@ struct LLVMTypeConsistencyPass : public LLVM::impl::LLVMTypeConsistencyBase<LLVMTypeConsistencyPass> { void runOnOperation() override { RewritePatternSet rewritePatterns(&getContext()); - rewritePatterns.add<AddFieldGetterToStructDirectUse<LoadOp>>(&getContext()); - rewritePatterns.add<AddFieldGetterToStructDirectUse<StoreOp>>( - &getContext()); rewritePatterns.add<CanonicalizeAlignedGep>(&getContext()); rewritePatterns.add<SplitStores>(&getContext(), maxVectorSplitSize); rewritePatterns.add<BitcastStores>(&getContext()); diff --git a/mlir/lib/Dialect/Linalg/IR/LinalgDialect.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgDialect.cpp index 027058d4de6328a98f647a6b97ed8e5166c756d5..9e50c355c504173f960727435a3d3d1734242dc5 100644 --- a/mlir/lib/Dialect/Linalg/IR/LinalgDialect.cpp +++ b/mlir/lib/Dialect/Linalg/IR/LinalgDialect.cpp @@ -21,7 +21,10 @@ #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/Dialect.h" #include "mlir/IR/DialectImplementation.h" +#include "mlir/Interfaces/DestinationStyleOpInterface.h" #include "mlir/Interfaces/FunctionInterfaces.h" +#include "mlir/Interfaces/SubsetOpInterface.h" +#include "mlir/Interfaces/ValueBoundsOpInterface.h" #include "mlir/Parser/Parser.h" #include "mlir/Support/LLVM.h" #include "mlir/Transforms/InliningUtils.h" @@ -120,9 +123,26 @@ void mlir::linalg::LinalgDialect::initialize() { addInterfaces<LinalgInlinerInterface>(); - declarePromisedInterface<GenericOp, mesh::ShardingInterface>(); + declarePromisedInterface<mesh::ShardingInterface, GenericOp>(); declarePromisedInterfaces<mesh::ShardingInterface, #define GET_OP_LIST +#include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.cpp.inc" + >(); + declarePromisedInterface<SubsetOpInterface, CopyOp>(); + declarePromisedInterface<SubsetInsertionOpInterface, CopyOp>(); + declarePromisedInterface<ValueBoundsOpInterface, IndexOp>(); + declarePromisedInterface<TilingInterface, linalg::GenericOp>(); + declarePromisedInterface<PartialReductionOpInterface, linalg::GenericOp>(); + declarePromisedInterfaces<TilingInterface, +#define GET_OP_LIST +#include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.cpp.inc" + >(); + declarePromisedInterfaces<PartialReductionOpInterface, +#define GET_OP_LIST +#include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.cpp.inc" + >(); + declarePromisedInterfaces<bufferization::BufferizableOpInterface, +#define GET_OP_LIST #include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.cpp.inc" >(); } diff --git a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp index 6954eee93efd14e591449e34c8ea125740698db7..2d7219fef87c64bd716fae670a81ff8200560086 100644 --- a/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp +++ b/mlir/lib/Dialect/Linalg/IR/LinalgOps.cpp @@ -28,6 +28,7 @@ #include "mlir/IR/AffineExprVisitor.h" #include "mlir/IR/AffineMap.h" #include "mlir/IR/BuiltinAttributes.h" +#include "mlir/IR/BuiltinTypeInterfaces.h" #include "mlir/IR/Matchers.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/OperationSupport.h" @@ -119,8 +120,7 @@ static void fillStructuredOpRegion(OpBuilder &opBuilder, Region ®ion, TypeRange inputTypes, TypeRange outputTypes, ArrayRef<NamedAttribute> attrs, RegionBuilderFn regionBuilder) { - assert(llvm::all_of(outputTypes, - [](Type t) { return llvm::isa<ShapedType>(t); })); + assert(llvm::all_of(outputTypes, llvm::IsaPred<ShapedType>)); SmallVector<Type, 8> argTypes; SmallVector<Location, 8> argLocs; @@ -162,7 +162,7 @@ static void buildStructuredOp(OpBuilder &b, OperationState &state, resultTensorTypes.value_or(TypeRange()); if (!resultTensorTypes) copy_if(outputs.getTypes(), std::back_inserter(derivedResultTypes), - [](Type type) { return llvm::isa<RankedTensorType>(type); }); + llvm::IsaPred<RankedTensorType>); state.addOperands(inputs); state.addOperands(outputs); diff --git a/mlir/lib/Dialect/Linalg/TransformOps/LinalgMatchOps.cpp b/mlir/lib/Dialect/Linalg/TransformOps/LinalgMatchOps.cpp index fb18886c16b16d561b5e5a83fa1e24a769bfcb19..3e85559e1ec0c697fc4d63c821d2510c10b5d92c 100644 --- a/mlir/lib/Dialect/Linalg/TransformOps/LinalgMatchOps.cpp +++ b/mlir/lib/Dialect/Linalg/TransformOps/LinalgMatchOps.cpp @@ -12,7 +12,8 @@ #include "mlir/Dialect/Linalg/IR/LinalgInterfaces.h" #include "mlir/Dialect/Linalg/TransformOps/Syntax.h" #include "mlir/Dialect/Linalg/Utils/Utils.h" -#include "mlir/Dialect/Transform/IR/MatchInterfaces.h" +#include "mlir/Dialect/Transform/IR/TransformTypes.h" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/Interfaces/FunctionImplementation.h" #include "llvm/Support/Debug.h" diff --git a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp index ae28049f02e391c6196a8e3b4e327e556c5f1d56..88819cd964354b10761a206af425563e4e9263ed 100644 --- a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp +++ b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp @@ -25,9 +25,9 @@ #include "mlir/Dialect/Tensor/IR/Tensor.h" #include "mlir/Dialect/Tensor/Utils/Utils.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformOps.h" #include "mlir/Dialect/Transform/IR/TransformTypes.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Dialect/Transform/Utils/Utils.h" #include "mlir/Dialect/Utils/IndexingUtils.h" #include "mlir/Dialect/Utils/StaticValueUtils.h" @@ -3269,17 +3269,24 @@ DiagnosedSilenceableFailure transform::FlattenElementwiseLinalgOp::applyToOne( transform::ApplyToEachResultList &results, transform::TransformState &state) { rewriter.setInsertionPoint(target); - if (target.getNumLoops() <= 1) + if (!isElementwise(target)) + return mlir::emitSilenceableFailure(target->getLoc()) + << "only elementwise flattening is supported"; + + // If rank <= 1, do nothing + if (target.getNumLoops() <= 1) { + results.push_back(target); return DiagnosedSilenceableFailure::success(); + } + + // Attempt to flatten all dims to one. ReassociationIndices reassociation(target.getNumLoops()); std::iota(reassociation.begin(), reassociation.end(), 0); auto maybeFlattened = - (isElementwise(target)) - ? collapseOpIterationDims(target, reassociation, rewriter) - : FailureOr<CollapseResult>(rewriter.notifyMatchFailure( - target, "only elementwise flattening is supported")); + collapseOpIterationDims(target, reassociation, rewriter); if (failed(maybeFlattened)) - return emitDefaultSilenceableFailure(target); + return mlir::emitSilenceableFailure(target->getLoc()) + << "attempted to flatten, but failed"; results.push_back(maybeFlattened->collapsedOp); rewriter.replaceOp(target, maybeFlattened->results); return DiagnosedSilenceableFailure::success(); diff --git a/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp b/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp index 5ceb85e7d9903b0e7ad5b2aa011ca7dee6eb4f86..7fd88dec71d4911579424608046669aecae37d3f 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/DataLayoutPropagation.cpp @@ -17,6 +17,7 @@ #include "mlir/Dialect/Utils/IndexingUtils.h" #include "mlir/IR/Dominance.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" +#include "llvm/ADT/TypeSwitch.h" #include "llvm/Support/Debug.h" #include <optional> @@ -552,6 +553,305 @@ private: ControlPropagationFn controlFn; }; +/// Project dimsPos to the inner-most non-unit dim pos with reassocIndices. +/// +/// For example, given dimsPos [0, 2], reassocIndices [[0, 1], [2, 3]], and +/// targetShape [16, 16, 32, 1], it returns [1, 2]. Because for pos 0, the +/// inner-most projected dim in pos [0, 1] is 1. And for pos 2, the inner-most +/// non-unit projected dims in pos [2, 3] is 2. +/// +/// If all candidates in a reassociation are unit dims, it chooses the +/// inner-most dim pos. +static SmallVector<int64_t> +projectToInnerMostNonUnitDimsPos(ArrayRef<int64_t> dimsPos, + ArrayRef<ReassociationIndices> reassocIndices, + ArrayRef<int64_t> targetShape) { + SmallVector<int64_t> projectedDimsPos; + for (auto pos : dimsPos) { + // In the case all dims are unit, this will return the inner-most one. + int64_t projectedPos = reassocIndices[pos].back(); + for (auto i : llvm::reverse(reassocIndices[pos])) { + int64_t dim = targetShape[i]; + if (dim > 1 || ShapedType::isDynamic(dim)) { + projectedPos = i; + break; + } + } + projectedDimsPos.push_back(projectedPos); + } + return projectedDimsPos; +} + +/// Check if all dims in dimsPos are divisible by the corresponding tile sizes. +static bool isDimsDivisibleByTileSizes(ArrayRef<int64_t> dimsPos, + ArrayRef<int64_t> shape, + ArrayRef<int64_t> tileSizes) { + for (auto [pos, tileSize] : llvm::zip_equal(dimsPos, tileSizes)) { + int64_t dim = shape[pos]; + if (ShapedType::isDynamic(dim) || (dim % tileSize) != 0) + return false; + } + return true; +} + +/// Permutate the reassociation indices and reindex them in the sequence order. +/// Returns the next dim pos in the sequence. +/// +/// For example, given reassocIndices [[0, 1], [2]] and permutation [1, 0], it +/// applies the permutation to get [[2], [0, 1]] and reindexes the indices into +/// [[0], [1, 2]]. +static int64_t applyPermutationAndReindexReassoc( + SmallVector<ReassociationIndices> &reassocIndices, + ArrayRef<int64_t> permutation) { + applyPermutationToVector<ReassociationIndices>(reassocIndices, permutation); + int64_t nextPos = 0; + for (ReassociationIndices &indices : reassocIndices) { + for (auto &index : indices) { + index = nextPos; + nextPos += 1; + } + } + return nextPos; +} + +/// Bubble up pack op through collapse shape op when the packed dims can be +/// projected to the dims before collapsing. This is possible when the inner +/// tile sizes can divide the projected dims. +/// +/// For example: +/// +/// %collapsed = tensor.collapse_shape %in [[0, 1], 2] +/// : tensor<?x16x4xf32> into tensor<?x4xf32> +/// %pack = tensor.pack %collapsed outer_dims_perm = [0, 1] +/// inner_dims_pos = [0, 1] inner_tiles = [8, 1] into %empty +/// : tensor<?x4xf32> -> tensor<?x4x8x1xf32> +/// +/// can be transformed into: +/// +/// %pack = tensor.pack %in outer_dims_perm = [1, 2] +/// inner_dims_pos = [1, 2] inner_tiles = [8, 1] into %empty +/// : tensor<?x16x4xf32> -> tensor<?x2x4x8x1xf32> +/// %collapsed = tensor.collapse_shape %pack [[0, 1], 2, 3, 4] +/// : tensor<?x2x4x8x1xf32> into tensor<?x4x8x1> +static LogicalResult +bubbleUpPackOpThroughCollapseShape(tensor::CollapseShapeOp collapseOp, + tensor::PackOp packOp, + PatternRewriter &rewriter) { + SmallVector<int64_t> innerTileSizes = packOp.getStaticTiles(); + ArrayRef<int64_t> innerDimsPos = packOp.getInnerDimsPos(); + ArrayRef<int64_t> outerDimsPerm = packOp.getOuterDimsPerm(); + + ArrayRef<int64_t> srcShape = collapseOp.getSrcType().getShape(); + SmallVector<ReassociationIndices> reassocIndices = + collapseOp.getReassociationIndices(); + // Project inner tile pos to the dim pos before collapsing. For example, if + // dims [x, y] is collapsed into [z], packing on dim z can be projected back + // to pack on dim y. + // + // Project to inner-most non-unit dims to increase the chance that they can be + // divided by the inner tile sizes. This is correct because for [..., x, 1], + // packing on dim 1 is equivalent to packing on dim x. + SmallVector<int64_t> projectedInnerDimsPos = + projectToInnerMostNonUnitDimsPos(innerDimsPos, reassocIndices, srcShape); + + if (!isDimsDivisibleByTileSizes(projectedInnerDimsPos, srcShape, + innerTileSizes)) { + return failure(); + } + // Expand the outer dims permutation with the associated source dims for the + // new permutation after bubbling. This is because moving a collapsed dim is + // equivalent to moving the associated source dims together. + SmallVector<int64_t> newOuterDimsPerm; + for (auto outerPos : outerDimsPerm) { + newOuterDimsPerm.insert(newOuterDimsPerm.end(), + reassocIndices[outerPos].begin(), + reassocIndices[outerPos].end()); + } + + auto emptyOp = tensor::PackOp::createDestinationTensor( + rewriter, packOp.getLoc(), collapseOp.getSrc(), packOp.getMixedTiles(), + projectedInnerDimsPos, newOuterDimsPerm); + auto newPackOp = rewriter.create<tensor::PackOp>( + packOp.getLoc(), collapseOp.getSrc(), emptyOp, projectedInnerDimsPos, + packOp.getMixedTiles(), packOp.getPaddingValue(), newOuterDimsPerm); + + SmallVector<ReassociationIndices> newReassocIndices = reassocIndices; + // First apply the permutation on the reassociations of the outer dims. + // For example given the permutation [1, 0], the reassociations [[0, 1], [2]] + // -> [[0], [1, 2]] + int64_t nextPos = + applyPermutationAndReindexReassoc(newReassocIndices, outerDimsPerm); + // Then add direct mapping for the inner tile dims. + for (size_t i = 0; i < innerDimsPos.size(); ++i) { + newReassocIndices.push_back({nextPos}); + nextPos += 1; + } + + auto newCollapseOp = rewriter.create<tensor::CollapseShapeOp>( + collapseOp.getLoc(), packOp.getType(), newPackOp, newReassocIndices); + rewriter.replaceOp(packOp, newCollapseOp); + + return success(); +} + +class BubbleUpPackOpThroughReshapeOp final + : public OpRewritePattern<tensor::PackOp> { +public: + BubbleUpPackOpThroughReshapeOp(MLIRContext *context, ControlPropagationFn fun) + : OpRewritePattern<tensor::PackOp>(context), controlFn(std::move(fun)) {} + + LogicalResult matchAndRewrite(tensor::PackOp packOp, + PatternRewriter &rewriter) const override { + Operation *srcOp = packOp.getSource().getDefiningOp(); + // Currently only support when the pack op is the only user. + if (!srcOp || !(srcOp->getNumResults() == 1) || + !srcOp->getResult(0).hasOneUse()) { + return failure(); + } + // Currently only support static inner tile sizes. + if (llvm::any_of(packOp.getStaticTiles(), [](int64_t size) { + return ShapedType::isDynamic(size); + })) { + return failure(); + } + + // User controlled propagation function. + if (!controlFn(srcOp)) + return failure(); + + return TypeSwitch<Operation *, LogicalResult>(srcOp) + .Case([&](tensor::CollapseShapeOp op) { + return bubbleUpPackOpThroughCollapseShape(op, packOp, rewriter); + }) + .Default([](Operation *) { return failure(); }); + } + +private: + ControlPropagationFn controlFn; +}; + +/// Push down unpack op through expand shape op when the packed dims can be +/// projected to the dims after expanding. This is possible when the inner tile +/// sizes can divide the projected dims. +/// +/// For example: +/// +/// %unpack = tensor.unpack %in outer_dims_perm = [0, 1] +/// inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %empty +/// : tensor<?x32x8x8xf32> -> tensor<?x256xf32> +/// %expanded = tensor.expand_shape %unpack [[0, 1], [2]] +/// : tensor<?x256xf32> into tensor<?x256x256xf32> +/// +/// can be transformed into: +/// +/// %expanded = tensor.expand_shape %ain [[0, 1], [2], [3], [4]] +/// : tensor<?x32x8x8xf32> into tensor<?x32x32x8x8xf32> +/// %unpack = tensor.unpack %expanded outer_dims_perm = [0, 1, 2] +/// inner_dims_pos = [1, 2] inner_tiles = [8, 8] into %empty +/// : tensor<?x32x32x8x8xf32> -> tensor<?x256x256xf32> +static LogicalResult +pushDownUnPackOpThroughExpandShape(tensor::UnPackOp unPackOp, + tensor::ExpandShapeOp expandOp, + PatternRewriter &rewriter) { + SmallVector<int64_t> innerTileSizes = unPackOp.getStaticTiles(); + ArrayRef<int64_t> innerDimsPos = unPackOp.getInnerDimsPos(); + ArrayRef<int64_t> outerDimsPerm = unPackOp.getOuterDimsPerm(); + + ArrayRef<int64_t> dstShape = expandOp.getType().getShape(); + SmallVector<ReassociationIndices> reassocIndices = + expandOp.getReassociationIndices(); + // Project inner tile pos to the dim pos after expanding. For example, if dims + // [z] is expanded into [x, y], unpacking on dim z can be projected to unpack + // on dim y. + // + // Project to inner-most non-unit dims to increase the chance that they can be + // divided by the inner tile sizes. This is correct because for [..., x, 1], + // unpacking on dim 1 is equivalent to unpacking on dim x. + SmallVector<int64_t> projectedInnerDimsPos = + projectToInnerMostNonUnitDimsPos(innerDimsPos, reassocIndices, dstShape); + + if (!isDimsDivisibleByTileSizes(projectedInnerDimsPos, dstShape, + innerTileSizes)) { + return failure(); + } + // Expand the outer dims permutation with the associated expanded dims for the + // new permutation after pushing. This is because moving a source dim is + // equivalent to moving the associated expanded dims together. + SmallVector<int64_t> newOuterDimsPerm; + for (auto outerPos : outerDimsPerm) { + newOuterDimsPerm.insert(newOuterDimsPerm.end(), + reassocIndices[outerPos].begin(), + reassocIndices[outerPos].end()); + } + + SmallVector<ReassociationIndices> newReassocIndices = reassocIndices; + // First apply the permutation on the reassociations of the outer dims. + // For example given the permutation [1, 0], the reassociations [[0, 1], [2]] + // -> [[0], [1, 2]] + int64_t nextPos = + applyPermutationAndReindexReassoc(newReassocIndices, outerDimsPerm); + // Then add direct mapping for the inner tile dims. + for (size_t i = 0; i < innerDimsPos.size(); ++i) { + newReassocIndices.push_back({nextPos}); + nextPos += 1; + } + + RankedTensorType newExpandType = + tensor::PackOp::inferPackedType(expandOp.getType(), innerTileSizes, + projectedInnerDimsPos, newOuterDimsPerm); + auto newExpandOp = rewriter.create<tensor::ExpandShapeOp>( + expandOp.getLoc(), newExpandType, unPackOp.getSource(), + newReassocIndices); + + auto emptyOp = tensor::UnPackOp::createDestinationTensor( + rewriter, unPackOp.getLoc(), newExpandOp, unPackOp.getMixedTiles(), + projectedInnerDimsPos, newOuterDimsPerm); + auto newUnPackOp = rewriter.create<tensor::UnPackOp>( + unPackOp.getLoc(), newExpandOp.getResult(), emptyOp, + projectedInnerDimsPos, unPackOp.getMixedTiles(), newOuterDimsPerm); + rewriter.replaceOp(expandOp, newUnPackOp); + + return success(); +} + +class PushDownUnPackOpThroughReshapeOp final + : public OpRewritePattern<tensor::UnPackOp> { +public: + PushDownUnPackOpThroughReshapeOp(MLIRContext *context, + ControlPropagationFn fun) + : OpRewritePattern<tensor::UnPackOp>(context), controlFn(std::move(fun)) { + } + + LogicalResult matchAndRewrite(tensor::UnPackOp unPackOp, + PatternRewriter &rewriter) const override { + Value result = unPackOp.getResult(); + // Currently only support unpack op with the single user. + if (!result.hasOneUse()) { + return failure(); + } + // Currently only support static inner tile sizes. + if (llvm::any_of(unPackOp.getStaticTiles(), [](int64_t size) { + return ShapedType::isDynamic(size); + })) { + return failure(); + } + + Operation *consumerOp = *result.user_begin(); + // User controlled propagation function. + if (!controlFn(consumerOp)) + return failure(); + + return TypeSwitch<Operation *, LogicalResult>(consumerOp) + .Case([&](tensor::ExpandShapeOp op) { + return pushDownUnPackOpThroughExpandShape(unPackOp, op, rewriter); + }) + .Default([](Operation *) { return failure(); }); + } + +private: + ControlPropagationFn controlFn; +}; + // TODO: Relax this restriction. We should unpack a generic op also // in the presence of multiple unpack ops as producers. /// Return the unpacked operand, if present, for the current generic op. @@ -774,6 +1074,7 @@ void mlir::linalg::populateDataLayoutPropagationPatterns( const ControlPropagationFn &controlPackUnPackPropagation) { patterns .insert<BubbleUpPackOpThroughGenericOpPattern, BubbleUpPackThroughPadOp, - PushDownUnPackOpThroughGenericOp, PushDownUnPackThroughPadOp>( + BubbleUpPackOpThroughReshapeOp, PushDownUnPackOpThroughGenericOp, + PushDownUnPackThroughPadOp, PushDownUnPackOpThroughReshapeOp>( patterns.getContext(), controlPackUnPackPropagation); } diff --git a/mlir/lib/Dialect/Linalg/Transforms/ElementwiseToLinalg.cpp b/mlir/lib/Dialect/Linalg/Transforms/ElementwiseToLinalg.cpp index 5508aaf9d8753711ce0f0089122d19302a3af441..28d6752fc2d3880f86268deacce3e94899949702 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/ElementwiseToLinalg.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/ElementwiseToLinalg.cpp @@ -27,8 +27,7 @@ static bool isElementwiseMappableOpOnRankedTensors(Operation *op) { // TODO: The conversion pattern can be made to work for `any_of` here, but // it's more complex as it requires tracking which operands are scalars. - return llvm::all_of(op->getOperandTypes(), - [](Type type) { return isa<RankedTensorType>(type); }); + return llvm::all_of(op->getOperandTypes(), llvm::IsaPred<RankedTensorType>); } /// Given `op` assumed `isElementwiseMappableOpOnRankedTensors`, iterate over diff --git a/mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp b/mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp index 30aed850bed81ece9742a745dd19e4186d78196d..462f692615faadf61b1d6699ec84fe8191abcde5 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/Tiling.cpp @@ -304,6 +304,28 @@ static void calculateTileOffsetsAndSizes( } } +/// Returns a vector of bools representing if, for each axis, `op` can be tiled +/// without incurring in a race condition and thus it is thread-safe to do the +/// tiling. This is checked by iterating over numThreads and ensuring that the +/// corresponding iterator type is "parallel". If it is not, then we know that +/// such dimension is unsafe to tile. +SmallVector<bool> safeToTileToForall(mlir::MLIRContext *ctx, LinalgOp linalgOp, + ArrayRef<OpFoldResult> numThreads) { + auto iterators = linalgOp.getIteratorTypesArray(); + SmallVector<bool> safeToTile(numThreads.size(), true); + + for (unsigned i = 0, e = numThreads.size(); i != e; i++) { + if (auto attr = llvm::dyn_cast_if_present<Attribute>(numThreads[i])) { + if (cast<IntegerAttr>(attr).getValue().getSExtValue() > 1) { + safeToTile[i] = iterators[i] == utils::IteratorType::parallel; + } + } else { + safeToTile[i] = iterators[i] == utils::IteratorType::parallel; + } + } + return safeToTile; +} + /// Rewrite a TilingInterface `op` to a tiled `scf.forall`. The /// tiling is specified by the number of tiles/threads `numThreads` and the /// optional nominal tile size `nominalTileSizes`. If `nominalTilSizes` is @@ -314,8 +336,10 @@ static void calculateTileOffsetsAndSizes( /// size of data. /// It is the user's responsibility to ensure that `numThreads` is a valid /// tiling specification (i.e. that only tiles parallel dimensions, e.g. in the -/// Linalg case). If `omitTileOffsetBoundsCheck` is true, then the function will -/// assume that `tileSize[i] * (numThread[i] -1) <= dimSize[i]` holds. +/// Linalg case). If the dimension is not parallelizable, a warning is issued to +/// notify the user that the generated code is not safe to parallelize. If +/// `omitTileOffsetBoundsCheck` is true, then the function will assume that +/// `tileSize[i] * (numThread[i] -1) <= dimSize[i]` holds. static FailureOr<ForallTilingResult> tileToForallOpImpl( RewriterBase &b, TilingInterface op, ArrayRef<OpFoldResult> numThreads, std::optional<ArrayRef<OpFoldResult>> nominalTileSizes, @@ -344,6 +368,16 @@ static FailureOr<ForallTilingResult> tileToForallOpImpl( return getValueOrCreateConstantIndexOp(b, loc, ofr); })); + LinalgOp linalgOp = dyn_cast<LinalgOp>(op.getOperation()); + if (linalgOp) { + // Check if tiling is thread safe and print a warning if not. + SmallVector<bool> tilingSafety = + safeToTileToForall(b.getContext(), linalgOp, numThreads); + for (size_t i = 0; i < tilingSafety.size(); i++) + if (!tilingSafety[i]) + op.emitWarning() << "tiling is not thread safe at axis #" << i; + } + // 1. Create the ForallOp. We don't use the lambda body-builder // version because we require the use of RewriterBase in the body, so we // manually move the insertion point to the body below. diff --git a/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp b/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp index 1e703dacfd0c758712b20943fb0ff1727b63d846..25785653a716752f6dfe322ce9e8f9ef03c83a2b 100644 --- a/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp +++ b/mlir/lib/Dialect/Linalg/Transforms/Vectorization.cpp @@ -24,6 +24,7 @@ #include "mlir/Dialect/Utils/StructuredOpsUtils.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" #include "mlir/Dialect/Vector/Interfaces/MaskableOpInterface.h" +#include "mlir/Dialect/Vector/Utils/VectorUtils.h" #include "mlir/IR/AffineExpr.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinTypeInterfaces.h" @@ -54,6 +55,8 @@ using namespace mlir::linalg; /// Try to vectorize `convOp` as a convolution. static FailureOr<Operation *> vectorizeConvolution(RewriterBase &rewriter, LinalgOp convOp, + ArrayRef<int64_t> inputVecSizes = {}, + ArrayRef<bool> inputVecScalableFlags = {}, bool flatten1DDepthwiseConv = false); /// Return the unique instance of OpType in `block` if it is indeed unique. @@ -1712,7 +1715,40 @@ static LogicalResult reductionPreconditions(LinalgOp op) { return success(); } -static LogicalResult vectorizeDynamicLinalgOpPrecondition(linalg::LinalgOp op) { +static LogicalResult +vectorizeDynamicConvOpPrecondition(linalg::LinalgOp conv, + bool flatten1DDepthwiseConv) { + if (flatten1DDepthwiseConv) { + LDBG("Vectorization of flattened convs with dynamic shapes is not " + "supported\n"); + return failure(); + } + + if (!isa<linalg::DepthwiseConv1DNwcWcOp>(conv)) { + LDBG("Not a 1D depth-wise WC conv, dynamic shapes are not supported\n"); + return failure(); + } + + // Support dynamic shapes in 1D depthwise convolution, but only in the + // _channel_ dimension. + Value lhs = conv.getDpsInputOperand(0)->get(); + ArrayRef<int64_t> lhsShape = cast<ShapedType>(lhs.getType()).getShape(); + auto shapeWithoutCh = lhsShape.drop_back(1); + if (ShapedType::isDynamicShape(shapeWithoutCh)) { + LDBG("Dynamically-shaped op vectorization precondition failed: only " + "channel dim can be dynamic\n"); + return failure(); + } + + return success(); +} + +static LogicalResult +vectorizeDynamicLinalgOpPrecondition(linalg::LinalgOp op, + bool flatten1DDepthwiseConv) { + if (isa<ConvolutionOpInterface>(op.getOperation())) + return vectorizeDynamicConvOpPrecondition(op, flatten1DDepthwiseConv); + // TODO: Masking only supports dynamic element-wise ops, linalg.generic ops, // linalg.copy ops and ops that implement ContractionOpInterface for now. if (!isElementwise(op) && @@ -1778,10 +1814,9 @@ vectorizeUnPackOpPrecondition(tensor::UnPackOp unpackOp, return success(); } -static LogicalResult -vectorizeLinalgOpPrecondition(LinalgOp linalgOp, - ArrayRef<int64_t> inputVectorSizes, - bool vectorizeNDExtract) { +static LogicalResult vectorizeLinalgOpPrecondition( + LinalgOp linalgOp, ArrayRef<int64_t> inputVectorSizes, + bool vectorizeNDExtract, bool flatten1DDepthwiseConv) { // tensor with dimension of 0 cannot be vectorized. if (llvm::is_contained(linalgOp.getStaticShape(), 0)) return failure(); @@ -1791,8 +1826,8 @@ vectorizeLinalgOpPrecondition(LinalgOp linalgOp, inputVectorSizes))) return failure(); - if (linalgOp.hasDynamicShape() && - failed(vectorizeDynamicLinalgOpPrecondition(linalgOp))) { + if (linalgOp.hasDynamicShape() && failed(vectorizeDynamicLinalgOpPrecondition( + linalgOp, flatten1DDepthwiseConv))) { LDBG("Dynamically-shaped op failed vectorization pre-conditions\n"); return failure(); } @@ -1911,14 +1946,17 @@ vectorizeScalableVectorPrecondition(Operation *op, if (!isScalable) return success(); - // Only element-wise ops supported in the presence of scalable dims. + // Only element-wise and 1d depthwise conv ops supported in the presence of + // scalable dims. auto linalgOp = dyn_cast<LinalgOp>(op); - return success(linalgOp && isElementwise(linalgOp)); + return success(linalgOp && (isElementwise(linalgOp) || + isa<linalg::DepthwiseConv1DNwcWcOp>(op))); } LogicalResult mlir::linalg::vectorizeOpPrecondition( Operation *op, ArrayRef<int64_t> inputVectorSizes, - ArrayRef<bool> inputScalableVecDims, bool vectorizeNDExtract) { + ArrayRef<bool> inputScalableVecDims, bool vectorizeNDExtract, + bool flatten1DDepthwiseConv) { if (failed(vectorizeScalableVectorPrecondition(op, inputVectorSizes, inputScalableVecDims))) return failure(); @@ -1926,7 +1964,8 @@ LogicalResult mlir::linalg::vectorizeOpPrecondition( return TypeSwitch<Operation *, LogicalResult>(op) .Case<linalg::LinalgOp>([&](auto linalgOp) { return vectorizeLinalgOpPrecondition(linalgOp, inputVectorSizes, - vectorizeNDExtract); + vectorizeNDExtract, + flatten1DDepthwiseConv); }) .Case<tensor::PadOp>([&](auto padOp) { return vectorizePadOpPrecondition(padOp, inputVectorSizes); @@ -1975,7 +2014,8 @@ LogicalResult mlir::linalg::vectorize(RewriterBase &rewriter, Operation *op, LLVM_DEBUG(llvm::dbgs() << "\n"); if (failed(vectorizeOpPrecondition(op, inputVectorSizes, inputScalableVecDims, - vectorizeNDExtract))) { + vectorizeNDExtract, + flatten1DDepthwiseConv))) { LDBG("Vectorization pre-conditions failed\n"); return failure(); } @@ -1999,7 +2039,8 @@ LogicalResult mlir::linalg::vectorize(RewriterBase &rewriter, Operation *op, // inference. if (isa<ConvolutionOpInterface>(linalgOp.getOperation())) { FailureOr<Operation *> convOr = vectorizeConvolution( - rewriter, linalgOp, flatten1DDepthwiseConv); + rewriter, linalgOp, inputVectorSizes, inputScalableVecDims, + flatten1DDepthwiseConv); if (succeeded(convOr)) { llvm::append_range(results, (*convOr)->getResults()); return success(); @@ -3131,13 +3172,30 @@ struct Conv1DGenerator /// kw is always unrolled. /// TODO: w (resp. kw) is unrolled when the strideW ( resp. dilationW) is /// > 1. - FailureOr<Operation *> depthwiseConv(bool flatten) { + FailureOr<Operation *> depthwiseConv(uint64_t channelDimVecSize, + bool channelDimScalableFlag, + bool flatten) { if (!valid) return rewriter.notifyMatchFailure(op, "unvectorizable depthwise conv"); + bool scalableChDim = false; + bool useMasking = false; int64_t nSize, wSize, cSize, kwSize; // kernel{kw, c} bindShapeDims(rhsShapedType, kwSize, cSize); + if (ShapedType::isDynamic(cSize)) { + assert(channelDimVecSize != 0 && "Channel dim vec size must be > 0"); + cSize = channelDimVecSize; + // Scalable vectors are only used when both conditions are met: + // 1. channel dim is dynamic + // 2. channelDimScalableFlag is set + scalableChDim = channelDimScalableFlag; + useMasking = true; + } + + assert(!(useMasking && flatten) && + "Unsupported flattened conv with dynamic shapes"); + // out{n, w, c} bindShapeDims(resShapedType, nSize, wSize); @@ -3158,20 +3216,51 @@ struct Conv1DGenerator // (i.e. 16 convolved with 3 (@stride 1 dilation 1) -> 14) ((wSize - 1) * strideW + 1) + ((kwSize - 1) * dilationW + 1) - 1, cSize}, - lhsEltType); - VectorType rhsType = VectorType::get({kwSize, cSize}, rhsEltType); - VectorType resType = VectorType::get({nSize, wSize, cSize}, resEltType); + lhsEltType, /*scalableDims=*/{false, false, scalableChDim}); + VectorType rhsType = + VectorType::get({kwSize, cSize}, rhsEltType, + /*scalableDims=*/{false, scalableChDim}); + VectorType resType = + VectorType::get({nSize, wSize, cSize}, resEltType, + /*scalableDims=*/{false, false, scalableChDim}); + + // Masks the input xfer Op along the channel dim, iff the corresponding + // scalable flag is set. + auto maybeMaskXferOp = [&](ArrayRef<int64_t> maskShape, + ArrayRef<bool> scalableDims, + Operation *opToMask) { + if (!useMasking) + return opToMask; + auto maskType = + VectorType::get(maskShape, rewriter.getI1Type(), scalableDims); + + SmallVector<OpFoldResult> mixedDims = vector::getMixedSizesXfer( + cast<LinalgOp>(op).hasPureTensorSemantics(), opToMask, rewriter); + + Value maskOp = + rewriter.create<vector::CreateMaskOp>(loc, maskType, mixedDims); + + return mlir::vector::maskOperation(rewriter, opToMask, maskOp); + }; // Read lhs slice of size {n, w * strideW + kw * dilationW, c} @ [0, 0, // 0]. Value lhs = rewriter.create<vector::TransferReadOp>( loc, lhsType, lhsShaped, ValueRange{zero, zero, zero}); + auto maybeMaskedLhs = maybeMaskXferOp( + lhsType.getShape(), lhsType.getScalableDims(), lhs.getDefiningOp()); + // Read rhs slice of size {kw, c} @ [0, 0]. Value rhs = rewriter.create<vector::TransferReadOp>(loc, rhsType, rhsShaped, ValueRange{zero, zero}); + auto maybeMaskedRhs = maybeMaskXferOp( + rhsType.getShape(), rhsType.getScalableDims(), rhs.getDefiningOp()); + // Read res slice of size {n, w, c} @ [0, 0, 0]. Value res = rewriter.create<vector::TransferReadOp>( loc, resType, resShaped, ValueRange{zero, zero, zero}); + auto maybeMaskedRes = maybeMaskXferOp( + resType.getShape(), resType.getScalableDims(), res.getDefiningOp()); //===------------------------------------------------------------------===// // Begin vector-only rewrite part @@ -3186,7 +3275,7 @@ struct Conv1DGenerator for (int64_t kw = 0; kw < kwSize; ++kw) { for (int64_t w = 0; w < wSize; w += wSizeStep) { lhsVals.push_back(rewriter.create<vector::ExtractStridedSliceOp>( - loc, lhs, + loc, maybeMaskedLhs->getResult(0), /*offsets=*/ArrayRef<int64_t>{0, w * strideW + kw * dilationW, 0}, inOutSliceSizes, inOutStrides)); } @@ -3194,12 +3283,13 @@ struct Conv1DGenerator // Extract rhs slice of size {c} @ [kw]. for (int64_t kw = 0; kw < kwSize; ++kw) { rhsVals.push_back(rewriter.create<vector::ExtractOp>( - loc, rhs, /*offsets=*/ArrayRef<int64_t>{kw})); + loc, maybeMaskedRhs->getResult(0), + /*offsets=*/ArrayRef<int64_t>{kw})); } // Extract res slice: {n, wSizeStep, c} @ [0, w, 0]. for (int64_t w = 0; w < wSize; w += wSizeStep) { resVals.push_back(rewriter.create<vector::ExtractStridedSliceOp>( - loc, res, + loc, maybeMaskedRes->getResult(0), /*offsets=*/ArrayRef<int64_t>{0, w, 0}, inOutSliceSizes, inOutStrides)); } @@ -3208,10 +3298,15 @@ struct Conv1DGenerator return kw * (wSize / wSizeStep) + w; }; + // Note - the scalable flags are ignored as flattening combined with + // scalable vectorization is not supported. auto inOutFlattenSliceSizes = SmallVector<int64_t>{nSize, wSizeStep * cSize}; - auto lhsCastType = VectorType::get(inOutFlattenSliceSizes, lhsEltType); - auto resCastType = VectorType::get(inOutFlattenSliceSizes, resEltType); + auto lhsTypeAfterFlattening = + VectorType::get(inOutFlattenSliceSizes, lhsEltType); + auto resTypeAfterFlattening = + VectorType::get(inOutFlattenSliceSizes, resEltType); + // Compute contraction: O{n, w, c} += I{n, sw * w + dw * kw, c} * F{c} for (int64_t kw = 0; kw < kwSize; ++kw) { for (int64_t w = 0; w < wSize; w += wSizeStep) { @@ -3221,9 +3316,9 @@ struct Conv1DGenerator // Flatten the input and output vectors (collapse the channel // dimension) lhsVal = rewriter.create<vector::ShapeCastOp>( - loc, lhsCastType, lhsVals[linearIndex(kw, w)]); - resVal = rewriter.create<vector::ShapeCastOp>(loc, resCastType, - resVals[w]); + loc, lhsTypeAfterFlattening, lhsVals[linearIndex(kw, w)]); + resVal = rewriter.create<vector::ShapeCastOp>( + loc, resTypeAfterFlattening, resVals[w]); } resVals[w] = depthwiseConv1dSliceAsMulAcc(rewriter, loc, lhsVal, rhsVals[kw], resVal, flatten); @@ -3248,8 +3343,8 @@ struct Conv1DGenerator // Write back res slice: {n, wSizeStep, c} @ [0, w, 0]. // This does not depend on kw. for (int64_t w = 0; w < wSize; w += wSizeStep) { - res = rewriter.create<vector::InsertStridedSliceOp>( - loc, resVals[w], res, + maybeMaskedRes = rewriter.create<vector::InsertStridedSliceOp>( + loc, resVals[w], maybeMaskedRes->getResult(0), /*offsets=*/ArrayRef<int64_t>{0, w, 0}, /*strides=*/ArrayRef<int64_t>{1, 1, 1}); } @@ -3258,10 +3353,11 @@ struct Conv1DGenerator //===------------------------------------------------------------------===// // Write back res slice of size {n, w, c} @ [0, 0, 0]. - return rewriter - .create<vector::TransferWriteOp>(loc, res, resShaped, - ValueRange{zero, zero, zero}) - .getOperation(); + Operation *resOut = rewriter.create<vector::TransferWriteOp>( + loc, maybeMaskedRes->getResult(0), resShaped, + ValueRange{zero, zero, zero}); + return maybeMaskXferOp(resType.getShape(), resType.getScalableDims(), + resOut); } /// Lower: @@ -3278,6 +3374,10 @@ struct Conv1DGenerator lhs = promote(rewriter, loc, lhs, resTy); if (flatten) { + // NOTE: This following logic won't work for scalable vectors. For this + // reason, "flattening" is not supported when shapes are dynamic (this + // should be captured by one of the pre-conditions). + // There are two options for handling the filter: // * shape_cast(broadcast(filter)) // * broadcast(shuffle(filter)) @@ -3399,7 +3499,9 @@ struct Conv1DGenerator /// Entry point that transposes into the common form: /// {{n, strideW * w + dilationW * kw, c}, {kw, c}, {n, w, c}} - FailureOr<Operation *> generateDilatedConv(bool flatten = false) { + FailureOr<Operation *> generateDilatedConv(uint64_t vecChDimSize = 0, + bool vecChDimScalableFlag = false, + bool flatten = false) { AffineExpr n, w, c, kw; bindDims(ctx, n, w, c, kw); if (!iters({Par(), Par(), Par(), Red()})) @@ -3410,7 +3512,7 @@ struct Conv1DGenerator if (layout({/*lhsIndex*/ {n, strideW * w + dilationW * kw, c}, /*rhsIndex*/ {kw, c}, /*resIndex*/ {n, w, c}})) - return depthwiseConv(flatten); + return depthwiseConv(vecChDimSize, vecChDimScalableFlag, flatten); return rewriter.notifyMatchFailure(op, "not a depthwise::Nwc layout"); } @@ -3435,15 +3537,14 @@ private: // Otherwise, check for one or zero `ext` predecessor. The `ext` operands // must be block arguments or extension of block arguments. bool setOperKind(Operation *reduceOp) { - int numBlockArguments = llvm::count_if( - reduceOp->getOperands(), [](Value v) { return isa<BlockArgument>(v); }); + int numBlockArguments = + llvm::count_if(reduceOp->getOperands(), llvm::IsaPred<BlockArgument>); switch (numBlockArguments) { case 1: { // Will be convolution if feeder is a MulOp. // Otherwise, if it can be pooling. - auto feedValIt = llvm::find_if(reduceOp->getOperands(), [](Value v) { - return !isa<BlockArgument>(v); - }); + auto feedValIt = llvm::find_if_not(reduceOp->getOperands(), + llvm::IsaPred<BlockArgument>); Operation *feedOp = (*feedValIt).getDefiningOp(); if (isCastOfBlockArgument(feedOp)) { oper = Pool; @@ -3475,9 +3576,9 @@ private: /// Helper function to vectorize a LinalgOp with convolution semantics. // TODO: extend the generic vectorization to support windows and drop this. -static FailureOr<Operation *> -vectorizeConvolution(RewriterBase &rewriter, LinalgOp op, - bool flatten1DDepthwiseConv) { +static FailureOr<Operation *> vectorizeConvolution( + RewriterBase &rewriter, LinalgOp op, ArrayRef<int64_t> inputVecSizes, + ArrayRef<bool> inputScalableVecDims, bool flatten1DDepthwiseConv) { // The ConvolutionOpInterface gives us guarantees of existence for // strides/dilations. However, we do not need to rely on those, we can // simply use them if present, otherwise use the default and let the generic @@ -3502,7 +3603,28 @@ vectorizeConvolution(RewriterBase &rewriter, LinalgOp op, res = e.generateNcwPooling(); if (succeeded(res)) return res; - return e.generateDilatedConv(flatten1DDepthwiseConv); + + // Only depthwise 1D NWC convs are left - these can be vectorized using masks + // and scalable vectors. Note that ATM the only dim that can be dynamic (i.e. + // masked/scalable) is the channel dim (i.e. the trailing dim). + uint64_t vecChDimSize = ShapedType::kDynamic; + bool vecChDimScalableFlag = false; + if (!inputVecSizes.empty()) { + // Only use the input vector size corresponding to the channel dim. Other + // vector dims will be inferred from the Ops. + assert((isa<linalg::DepthwiseConv1DNwcWcOp>(*op) || + isa<linalg::DepthwiseConv1DNcwCwOp>(*op)) && + "Not a 1D depthwise conv!"); + size_t chDimIdx = + TypeSwitch<Operation *, size_t>(op) + .Case<linalg::DepthwiseConv1DNwcWcOp>([](auto conv) { return 2; }) + .Case<linalg::DepthwiseConv1DNcwCwOp>([](auto conv) { return 1; }); + + vecChDimSize = inputVecSizes[chDimIdx]; + vecChDimScalableFlag = inputScalableVecDims[chDimIdx]; + } + return e.generateDilatedConv(vecChDimSize, vecChDimScalableFlag, + flatten1DDepthwiseConv); } struct VectorizeConvolution : public OpInterfaceRewritePattern<LinalgOp> { diff --git a/mlir/lib/Dialect/MLProgram/IR/CMakeLists.txt b/mlir/lib/Dialect/MLProgram/IR/CMakeLists.txt index 90c9c9aa787503341b78b10276636d43705082cf..725bb5fd9da9ede54707acba2f68a887a7fe4e0d 100644 --- a/mlir/lib/Dialect/MLProgram/IR/CMakeLists.txt +++ b/mlir/lib/Dialect/MLProgram/IR/CMakeLists.txt @@ -15,5 +15,6 @@ add_mlir_dialect_library(MLIRMLProgramDialect MLIRControlFlowInterfaces MLIRFunctionInterfaces MLIRInferTypeOpInterface + MLIRTransforms MLIRIR ) diff --git a/mlir/lib/Dialect/MLProgram/IR/MLProgramDialect.cpp b/mlir/lib/Dialect/MLProgram/IR/MLProgramDialect.cpp index 1a8fe208d4099e61cfa7c278665355e755f0d9cc..bda1032ed988471cd8ac0fc45b2bad077341a16f 100644 --- a/mlir/lib/Dialect/MLProgram/IR/MLProgramDialect.cpp +++ b/mlir/lib/Dialect/MLProgram/IR/MLProgramDialect.cpp @@ -8,6 +8,7 @@ #include "mlir/Dialect/MLProgram/IR/MLProgram.h" #include "mlir/IR/DialectImplementation.h" +#include "mlir/Transforms/InliningUtils.h" #include "llvm/ADT/TypeSwitch.h" using namespace mlir; @@ -24,6 +25,18 @@ using namespace mlir::ml_program; #include "mlir/Dialect/MLProgram/IR/MLProgramTypes.cpp.inc" namespace { + +struct MLProgramInlinerInterface : public DialectInlinerInterface { + using DialectInlinerInterface::DialectInlinerInterface; + + bool isLegalToInline(Operation *, Region *, bool, + IRMapping &) const override { + // We have no specific opinion on whether ops defined in this dialect should + // be inlined. + return true; + } +}; + struct MLProgramOpAsmDialectInterface : public OpAsmDialectInterface { using OpAsmDialectInterface::OpAsmDialectInterface; @@ -53,5 +66,5 @@ void ml_program::MLProgramDialect::initialize() { #include "mlir/Dialect/MLProgram/IR/MLProgramOps.cpp.inc" >(); - addInterfaces<MLProgramOpAsmDialectInterface>(); + addInterfaces<MLProgramInlinerInterface, MLProgramOpAsmDialectInterface>(); } diff --git a/mlir/lib/Dialect/Math/IR/MathDialect.cpp b/mlir/lib/Dialect/Math/IR/MathDialect.cpp index a71b24cb1b97372e2db946fac334864f261519c5..285b5ca594050011e827458b64724c9e707675bb 100644 --- a/mlir/lib/Dialect/Math/IR/MathDialect.cpp +++ b/mlir/lib/Dialect/Math/IR/MathDialect.cpp @@ -35,5 +35,5 @@ void mlir::math::MathDialect::initialize() { #include "mlir/Dialect/Math/IR/MathOps.cpp.inc" >(); addInterfaces<MathInlinerInterface>(); - declarePromisedInterface<MathDialect, ConvertToLLVMPatternInterface>(); + declarePromisedInterface<ConvertToLLVMPatternInterface, MathDialect>(); } diff --git a/mlir/lib/Dialect/Math/Transforms/ExpandPatterns.cpp b/mlir/lib/Dialect/Math/Transforms/ExpandPatterns.cpp index 989a3e5536ec66fc014d16adbd3a7c6541ed90c0..0b8546251350fa0da9ec2bb6d69ca7f79595bfb5 100644 --- a/mlir/lib/Dialect/Math/Transforms/ExpandPatterns.cpp +++ b/mlir/lib/Dialect/Math/Transforms/ExpandPatterns.cpp @@ -1,4 +1,4 @@ -//===- ExpandTanh.cpp - Code to perform expanding tanh op -----------------===// +//===- ExpandPatterns.cpp - Code to expand various math operations. -------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// // -// This file implements expansion of tanh op. +// This file implements expansion of various math operations. // //===----------------------------------------------------------------------===// @@ -23,9 +23,14 @@ using namespace mlir; /// Create a float constant. -static Value createFloatConst(Location loc, Type type, double value, +static Value createFloatConst(Location loc, Type type, APFloat value, OpBuilder &b) { - auto attr = b.getFloatAttr(getElementTypeOrSelf(type), value); + bool losesInfo = false; + auto eltType = getElementTypeOrSelf(type); + // Convert double to the given `FloatType` with round-to-nearest-ties-to-even. + value.convert(cast<FloatType>(eltType).getFloatSemantics(), + APFloat::rmNearestTiesToEven, &losesInfo); + auto attr = b.getFloatAttr(eltType, value); if (auto shapedTy = dyn_cast<ShapedType>(type)) { return b.create<arith::ConstantOp>(loc, DenseElementsAttr::get(shapedTy, attr)); @@ -34,7 +39,12 @@ static Value createFloatConst(Location loc, Type type, double value, return b.create<arith::ConstantOp>(loc, attr); } -/// Create a float constant. +static Value createFloatConst(Location loc, Type type, double value, + OpBuilder &b) { + return createFloatConst(loc, type, APFloat(value), b); +} + +/// Create an integer constant. static Value createIntConst(Location loc, Type type, int64_t value, OpBuilder &b) { auto attr = b.getIntegerAttr(getElementTypeOrSelf(type), value); @@ -91,34 +101,42 @@ static LogicalResult convertCoshOp(math::CoshOp op, PatternRewriter &rewriter) { } /// Expands tanh op into -/// 1) 1-exp^{-2x} / 1+exp^{-2x}, if x => 0 -/// 2) exp^{2x}-1 / exp^{2x}+1 , if x < 0 +/// 1-exp^{-2x} / 1+exp^{-2x} +/// To avoid overflow we exploit the reflection symmetry `tanh(-x) = -tanh(x)`. +/// We compute a "signs" value which is -1 if input is negative and +1 if input +/// is positive. Then multiply the input by this value, guaranteeing that the +/// result is positive, which also guarantees `exp^{-2x * sign(x)}` is in (0, +/// 1]. Expand the computation on the input `x * sign(x)`, then multiply the +/// result by `sign(x)` to retain sign of the real result. static LogicalResult convertTanhOp(math::TanhOp op, PatternRewriter &rewriter) { auto floatType = op.getOperand().getType(); Location loc = op.getLoc(); + Value zero = createFloatConst(loc, floatType, 0.0, rewriter); Value one = createFloatConst(loc, floatType, 1.0, rewriter); - Value two = createFloatConst(loc, floatType, 2.0, rewriter); - Value doubledX = rewriter.create<arith::MulFOp>(loc, op.getOperand(), two); - - // Case 1: tanh(x) = 1-exp^{-2x} / 1+exp^{-2x} - Value negDoubledX = rewriter.create<arith::NegFOp>(loc, doubledX); + Value negTwo = createFloatConst(loc, floatType, -2.0, rewriter); + + // Compute sign(x) = cast<float_type>(x < 0) * (-2) + 1 + Value isNegative = rewriter.create<arith::CmpFOp>( + loc, arith::CmpFPredicate::OLT, op.getOperand(), zero); + Value isNegativeFloat = + rewriter.create<arith::UIToFPOp>(loc, floatType, isNegative); + Value isNegativeTimesNegTwo = + rewriter.create<arith::MulFOp>(loc, isNegativeFloat, negTwo); + Value sign = rewriter.create<arith::AddFOp>(loc, isNegativeTimesNegTwo, one); + + // Normalize input to positive value: y = sign(x) * x + Value positiveX = rewriter.create<arith::MulFOp>(loc, sign, op.getOperand()); + + // Decompose on normalized input + Value negDoubledX = rewriter.create<arith::MulFOp>(loc, negTwo, positiveX); Value exp2x = rewriter.create<math::ExpOp>(loc, negDoubledX); Value dividend = rewriter.create<arith::SubFOp>(loc, one, exp2x); Value divisor = rewriter.create<arith::AddFOp>(loc, one, exp2x); Value positiveRes = rewriter.create<arith::DivFOp>(loc, dividend, divisor); - // Case 2: tanh(x) = exp^{2x}-1 / exp^{2x}+1 - exp2x = rewriter.create<math::ExpOp>(loc, doubledX); - dividend = rewriter.create<arith::SubFOp>(loc, exp2x, one); - divisor = rewriter.create<arith::AddFOp>(loc, exp2x, one); - Value negativeRes = rewriter.create<arith::DivFOp>(loc, dividend, divisor); + // Multiply result by sign(x) to retain signs from negative inputs + rewriter.replaceOpWithNewOp<arith::MulFOp>(op, sign, positiveRes); - // tanh(x) = x >= 0 ? positiveRes : negativeRes - Value zero = createFloatConst(loc, floatType, 0.0, rewriter); - Value cmpRes = rewriter.create<arith::CmpFOp>(loc, arith::CmpFPredicate::OGE, - op.getOperand(), zero); - rewriter.replaceOpWithNewOp<arith::SelectOp>(op, cmpRes, positiveRes, - negativeRes); return success(); } @@ -194,6 +212,69 @@ static LogicalResult convertCeilOp(math::CeilOp op, PatternRewriter &rewriter) { rewriter.replaceOp(op, ret); return success(); } + +// Convert `math.fpowi` to a series of `arith.mulf` operations. +// If the power is negative, we divide one by the result. +// If both the base and power are zero, the result is 1. +static LogicalResult convertFPowICstOp(math::FPowIOp op, + PatternRewriter &rewriter) { + ImplicitLocOpBuilder b(op->getLoc(), rewriter); + Value base = op.getOperand(0); + Value power = op.getOperand(1); + Type baseType = base.getType(); + + Attribute cstAttr; + if (!matchPattern(power, m_Constant(&cstAttr))) + return failure(); + + APInt value; + if (!matchPattern(cstAttr, m_ConstantInt(&value))) + return failure(); + + int64_t powerInt = value.getSExtValue(); + bool isNegative = powerInt < 0; + int64_t absPower = std::abs(powerInt); + Value one = createFloatConst(op->getLoc(), baseType, 1.00, rewriter); + Value res = createFloatConst(op->getLoc(), baseType, 1.00, rewriter); + + while (absPower > 0) { + if (absPower & 1) + res = b.create<arith::MulFOp>(baseType, base, res); + absPower >>= 1; + base = b.create<arith::MulFOp>(baseType, base, base); + } + + // Make sure not to introduce UB in case of negative power. + if (isNegative) { + auto &sem = dyn_cast<mlir::FloatType>(getElementTypeOrSelf(baseType)) + .getFloatSemantics(); + Value zero = + createFloatConst(op->getLoc(), baseType, + APFloat::getZero(sem, /*Negative=*/false), rewriter); + Value negZero = + createFloatConst(op->getLoc(), baseType, + APFloat::getZero(sem, /*Negative=*/true), rewriter); + Value posInfinity = + createFloatConst(op->getLoc(), baseType, + APFloat::getInf(sem, /*Negative=*/false), rewriter); + Value negInfinity = + createFloatConst(op->getLoc(), baseType, + APFloat::getInf(sem, /*Negative=*/true), rewriter); + Value zeroEqCheck = + b.create<arith::CmpFOp>(arith::CmpFPredicate::OEQ, res, zero); + Value negZeroEqCheck = + b.create<arith::CmpFOp>(arith::CmpFPredicate::OEQ, res, negZero); + res = b.create<arith::DivFOp>(baseType, one, res); + res = + b.create<arith::SelectOp>(op->getLoc(), zeroEqCheck, posInfinity, res); + res = b.create<arith::SelectOp>(op->getLoc(), negZeroEqCheck, negInfinity, + res); + } + + rewriter.replaceOp(op, res); + return success(); +} + // Converts Powf(float a, float b) (meaning a^b) to exp^(b * ln(a)) static LogicalResult convertPowfOp(math::PowFOp op, PatternRewriter &rewriter) { ImplicitLocOpBuilder b(op->getLoc(), rewriter); @@ -509,6 +590,10 @@ void mlir::populateExpandPowFPattern(RewritePatternSet &patterns) { patterns.add(convertPowfOp); } +void mlir::populateExpandFPowIPattern(RewritePatternSet &patterns) { + patterns.add(convertFPowICstOp); +} + void mlir::populateExpandRoundFPattern(RewritePatternSet &patterns) { patterns.add(convertRoundOp); } diff --git a/mlir/lib/Dialect/Math/Transforms/PolynomialApproximation.cpp b/mlir/lib/Dialect/Math/Transforms/PolynomialApproximation.cpp index 962cb28b7c2ab9f408c2e8428b395dbac3582775..428c1c37c4e8b5e027d4dfee1c54079f9736019c 100644 --- a/mlir/lib/Dialect/Math/Transforms/PolynomialApproximation.cpp +++ b/mlir/lib/Dialect/Math/Transforms/PolynomialApproximation.cpp @@ -39,14 +39,24 @@ using namespace mlir; using namespace mlir::math; using namespace mlir::vector; +// Helper to encapsulate a vector's shape (including scalable dims). +struct VectorShape { + ArrayRef<int64_t> sizes; + ArrayRef<bool> scalableFlags; + + bool empty() const { return sizes.empty(); } +}; + // Returns vector shape if the type is a vector. Returns an empty shape if it is // not a vector. -static ArrayRef<int64_t> vectorShape(Type type) { +static VectorShape vectorShape(Type type) { auto vectorType = dyn_cast<VectorType>(type); - return vectorType ? vectorType.getShape() : ArrayRef<int64_t>(); + return vectorType + ? VectorShape{vectorType.getShape(), vectorType.getScalableDims()} + : VectorShape{}; } -static ArrayRef<int64_t> vectorShape(Value value) { +static VectorShape vectorShape(Value value) { return vectorShape(value.getType()); } @@ -55,14 +65,16 @@ static ArrayRef<int64_t> vectorShape(Value value) { //----------------------------------------------------------------------------// // Broadcasts scalar type into vector type (iff shape is non-scalar). -static Type broadcast(Type type, ArrayRef<int64_t> shape) { +static Type broadcast(Type type, VectorShape shape) { assert(!isa<VectorType>(type) && "must be scalar type"); - return !shape.empty() ? VectorType::get(shape, type) : type; + return !shape.empty() + ? VectorType::get(shape.sizes, type, shape.scalableFlags) + : type; } // Broadcasts scalar value into vector (iff shape is non-scalar). static Value broadcast(ImplicitLocOpBuilder &builder, Value value, - ArrayRef<int64_t> shape) { + VectorShape shape) { assert(!isa<VectorType>(value.getType()) && "must be scalar value"); auto type = broadcast(value.getType(), shape); return !shape.empty() ? builder.create<BroadcastOp>(type, value) : value; @@ -215,7 +227,7 @@ static Value clamp(ImplicitLocOpBuilder &builder, Value value, Value lowerBound, static std::pair<Value, Value> frexp(ImplicitLocOpBuilder &builder, Value arg, bool isPositive = false) { assert(getElementTypeOrSelf(arg).isF32() && "arg must be f32 type"); - ArrayRef<int64_t> shape = vectorShape(arg); + VectorShape shape = vectorShape(arg); auto bcast = [&](Value value) -> Value { return broadcast(builder, value, shape); @@ -255,7 +267,7 @@ static std::pair<Value, Value> frexp(ImplicitLocOpBuilder &builder, Value arg, // Computes exp2 for an i32 argument. static Value exp2I32(ImplicitLocOpBuilder &builder, Value arg) { assert(getElementTypeOrSelf(arg).isInteger(32) && "arg must be i32 type"); - ArrayRef<int64_t> shape = vectorShape(arg); + VectorShape shape = vectorShape(arg); auto bcast = [&](Value value) -> Value { return broadcast(builder, value, shape); @@ -281,7 +293,7 @@ Value makePolynomialCalculation(ImplicitLocOpBuilder &builder, Type elementType = getElementTypeOrSelf(x); assert((elementType.isF32() || elementType.isF16()) && "x must be f32 or f16 type"); - ArrayRef<int64_t> shape = vectorShape(x); + VectorShape shape = vectorShape(x); if (coeffs.empty()) return broadcast(builder, floatCst(builder, 0.0f, elementType), shape); @@ -379,7 +391,7 @@ AtanApproximation::matchAndRewrite(math::AtanOp op, if (!getElementTypeOrSelf(operand).isF32()) return rewriter.notifyMatchFailure(op, "unsupported operand type"); - ArrayRef<int64_t> shape = vectorShape(op.getOperand()); + VectorShape shape = vectorShape(op.getOperand()); ImplicitLocOpBuilder builder(op->getLoc(), rewriter); Value abs = builder.create<math::AbsFOp>(operand); @@ -478,7 +490,7 @@ Atan2Approximation::matchAndRewrite(math::Atan2Op op, return rewriter.notifyMatchFailure(op, "unsupported operand type"); ImplicitLocOpBuilder builder(op->getLoc(), rewriter); - ArrayRef<int64_t> shape = vectorShape(op.getResult()); + VectorShape shape = vectorShape(op.getResult()); // Compute atan in the valid range. auto div = builder.create<arith::DivFOp>(y, x); @@ -544,7 +556,7 @@ TanhApproximation::matchAndRewrite(math::TanhOp op, if (!getElementTypeOrSelf(op.getOperand()).isF32()) return rewriter.notifyMatchFailure(op, "unsupported operand type"); - ArrayRef<int64_t> shape = vectorShape(op.getOperand()); + VectorShape shape = vectorShape(op.getOperand()); ImplicitLocOpBuilder builder(op->getLoc(), rewriter); auto bcast = [&](Value value) -> Value { @@ -632,7 +644,7 @@ LogApproximationBase<Op>::logMatchAndRewrite(Op op, PatternRewriter &rewriter, if (!getElementTypeOrSelf(op.getOperand()).isF32()) return rewriter.notifyMatchFailure(op, "unsupported operand type"); - ArrayRef<int64_t> shape = vectorShape(op.getOperand()); + VectorShape shape = vectorShape(op.getOperand()); ImplicitLocOpBuilder builder(op->getLoc(), rewriter); auto bcast = [&](Value value) -> Value { @@ -779,7 +791,7 @@ Log1pApproximation::matchAndRewrite(math::Log1pOp op, if (!getElementTypeOrSelf(op.getOperand()).isF32()) return rewriter.notifyMatchFailure(op, "unsupported operand type"); - ArrayRef<int64_t> shape = vectorShape(op.getOperand()); + VectorShape shape = vectorShape(op.getOperand()); ImplicitLocOpBuilder builder(op->getLoc(), rewriter); auto bcast = [&](Value value) -> Value { @@ -829,7 +841,7 @@ ErfPolynomialApproximation::matchAndRewrite(math::ErfOp op, if (!(elementType.isF32() || elementType.isF16())) return rewriter.notifyMatchFailure(op, "only f32 and f16 type is supported."); - ArrayRef<int64_t> shape = vectorShape(operand); + VectorShape shape = vectorShape(operand); ImplicitLocOpBuilder builder(op->getLoc(), rewriter); auto bcast = [&](Value value) -> Value { @@ -938,9 +950,8 @@ ErfPolynomialApproximation::matchAndRewrite(math::ErfOp op, namespace { -Value clampWithNormals(ImplicitLocOpBuilder &builder, - const llvm::ArrayRef<int64_t> shape, Value value, - float lowerBound, float upperBound) { +Value clampWithNormals(ImplicitLocOpBuilder &builder, const VectorShape shape, + Value value, float lowerBound, float upperBound) { assert(!std::isnan(lowerBound)); assert(!std::isnan(upperBound)); @@ -1131,7 +1142,7 @@ ExpM1Approximation::matchAndRewrite(math::ExpM1Op op, if (!getElementTypeOrSelf(op.getOperand()).isF32()) return rewriter.notifyMatchFailure(op, "unsupported operand type"); - ArrayRef<int64_t> shape = vectorShape(op.getOperand()); + VectorShape shape = vectorShape(op.getOperand()); ImplicitLocOpBuilder builder(op->getLoc(), rewriter); auto bcast = [&](Value value) -> Value { @@ -1201,7 +1212,7 @@ LogicalResult SinAndCosApproximation<isSine, OpTy>::matchAndRewrite( if (!getElementTypeOrSelf(op.getOperand()).isF32()) return rewriter.notifyMatchFailure(op, "unsupported operand type"); - ArrayRef<int64_t> shape = vectorShape(op.getOperand()); + VectorShape shape = vectorShape(op.getOperand()); ImplicitLocOpBuilder builder(op->getLoc(), rewriter); auto bcast = [&](Value value) -> Value { @@ -1328,7 +1339,7 @@ CbrtApproximation::matchAndRewrite(math::CbrtOp op, return rewriter.notifyMatchFailure(op, "unsupported operand type"); ImplicitLocOpBuilder b(op->getLoc(), rewriter); - ArrayRef<int64_t> shape = vectorShape(operand); + VectorShape shape = vectorShape(operand); Type floatTy = getElementTypeOrSelf(operand.getType()); Type intTy = b.getIntegerType(floatTy.getIntOrFloatBitWidth()); @@ -1417,10 +1428,10 @@ RsqrtApproximation::matchAndRewrite(math::RsqrtOp op, if (!getElementTypeOrSelf(op.getOperand()).isF32()) return rewriter.notifyMatchFailure(op, "unsupported operand type"); - ArrayRef<int64_t> shape = vectorShape(op.getOperand()); + VectorShape shape = vectorShape(op.getOperand()); // Only support already-vectorized rsqrt's. - if (shape.empty() || shape.back() % 8 != 0) + if (shape.empty() || shape.sizes.back() % 8 != 0) return rewriter.notifyMatchFailure(op, "unsupported operand type"); ImplicitLocOpBuilder builder(op->getLoc(), rewriter); diff --git a/mlir/lib/Dialect/MemRef/IR/MemRefDialect.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefDialect.cpp index d71669a274b8fc2c2fba097f96aca4b9ddbad49c..3a8bd12ba25863795cdd547a8a47561dc59cbe1d 100644 --- a/mlir/lib/Dialect/MemRef/IR/MemRefDialect.cpp +++ b/mlir/lib/Dialect/MemRef/IR/MemRefDialect.cpp @@ -8,8 +8,13 @@ #include "mlir/Conversion/ConvertToLLVM/ToLLVMInterface.h" #include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/Bufferization/IR/AllocationOpInterface.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/Interfaces/MemorySlotInterfaces.h" +#include "mlir/Interfaces/RuntimeVerifiableOpInterface.h" #include "mlir/Interfaces/SideEffectInterfaces.h" +#include "mlir/Interfaces/ValueBoundsOpInterface.h" #include "mlir/Transforms/InliningUtils.h" #include <optional> @@ -42,7 +47,14 @@ void mlir::memref::MemRefDialect::initialize() { #include "mlir/Dialect/MemRef/IR/MemRefOps.cpp.inc" >(); addInterfaces<MemRefInlinerInterface>(); - declarePromisedInterface<MemRefDialect, ConvertToLLVMPatternInterface>(); + declarePromisedInterface<ConvertToLLVMPatternInterface, MemRefDialect>(); + declarePromisedInterfaces<bufferization::AllocationOpInterface, AllocOp, + AllocaOp, ReallocOp>(); + declarePromisedInterfaces<RuntimeVerifiableOpInterface, CastOp, ExpandShapeOp, + LoadOp, ReinterpretCastOp, StoreOp, SubViewOp>(); + declarePromisedInterfaces<ValueBoundsOpInterface, AllocOp, AllocaOp, CastOp, + DimOp, GetGlobalOp, RankOp, SubViewOp>(); + declarePromisedInterface<DestructurableTypeInterface, MemRefType>(); } /// Finds the unique dealloc operation (if one exists) for `allocValue`. diff --git a/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp index 561b8619032cce7e21c764de29e74def77411489..6c5250d527ade808da50bf4932c267bae315ccff 100644 --- a/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp +++ b/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp @@ -120,11 +120,8 @@ memref::AllocaOp::getDestructurableSlots() { if (!destructuredType) return {}; - DenseMap<Attribute, Type> indexMap; - for (auto const &[index, type] : *destructuredType) - indexMap.insert({index, MemRefType::get({}, type)}); - - return {DestructurableMemorySlot{{getMemref(), memrefType}, indexMap}}; + return { + DestructurableMemorySlot{{getMemref(), memrefType}, *destructuredType}}; } DenseMap<Attribute, MemorySlot> @@ -170,7 +167,8 @@ Value memref::LoadOp::getStored(const MemorySlot &slot, bool memref::LoadOp::canUsesBeRemoved( const MemorySlot &slot, const SmallPtrSetImpl<OpOperand *> &blockingUses, - SmallVectorImpl<OpOperand *> &newBlockingUses) { + SmallVectorImpl<OpOperand *> &newBlockingUses, + const DataLayout &dataLayout) { if (blockingUses.size() != 1) return false; Value blockingUse = (*blockingUses.begin())->get(); @@ -210,7 +208,8 @@ static Attribute getAttributeIndexFromIndexOperands(MLIRContext *ctx, bool memref::LoadOp::canRewire(const DestructurableMemorySlot &slot, SmallPtrSetImpl<Attribute> &usedIndices, - SmallVectorImpl<MemorySlot> &mustBeSafelyUsed) { + SmallVectorImpl<MemorySlot> &mustBeSafelyUsed, + const DataLayout &dataLayout) { if (slot.ptr != getMemRef()) return false; Attribute index = getAttributeIndexFromIndexOperands( @@ -223,7 +222,8 @@ bool memref::LoadOp::canRewire(const DestructurableMemorySlot &slot, DeletionKind memref::LoadOp::rewire(const DestructurableMemorySlot &slot, DenseMap<Attribute, MemorySlot> &subslots, - RewriterBase &rewriter) { + RewriterBase &rewriter, + const DataLayout &dataLayout) { Attribute index = getAttributeIndexFromIndexOperands( getContext(), getIndices(), getMemRefType()); const MemorySlot &memorySlot = subslots.at(index); @@ -247,7 +247,8 @@ Value memref::StoreOp::getStored(const MemorySlot &slot, bool memref::StoreOp::canUsesBeRemoved( const MemorySlot &slot, const SmallPtrSetImpl<OpOperand *> &blockingUses, - SmallVectorImpl<OpOperand *> &newBlockingUses) { + SmallVectorImpl<OpOperand *> &newBlockingUses, + const DataLayout &dataLayout) { if (blockingUses.size() != 1) return false; Value blockingUse = (*blockingUses.begin())->get(); @@ -263,7 +264,8 @@ DeletionKind memref::StoreOp::removeBlockingUses( bool memref::StoreOp::canRewire(const DestructurableMemorySlot &slot, SmallPtrSetImpl<Attribute> &usedIndices, - SmallVectorImpl<MemorySlot> &mustBeSafelyUsed) { + SmallVectorImpl<MemorySlot> &mustBeSafelyUsed, + const DataLayout &dataLayout) { if (slot.ptr != getMemRef() || getValue() == slot.ptr) return false; Attribute index = getAttributeIndexFromIndexOperands( @@ -276,7 +278,8 @@ bool memref::StoreOp::canRewire(const DestructurableMemorySlot &slot, DeletionKind memref::StoreOp::rewire(const DestructurableMemorySlot &slot, DenseMap<Attribute, MemorySlot> &subslots, - RewriterBase &rewriter) { + RewriterBase &rewriter, + const DataLayout &dataLayout) { Attribute index = getAttributeIndexFromIndexOperands( getContext(), getIndices(), getMemRefType()); const MemorySlot &memorySlot = subslots.at(index); diff --git a/mlir/lib/Dialect/MemRef/TransformOps/MemRefTransformOps.cpp b/mlir/lib/Dialect/MemRef/TransformOps/MemRefTransformOps.cpp index 8932d616418277273170a01ebb5f1d876c652c9f..b3481ce1c56bbd40e0543bd9601b7bccffaa64cb 100644 --- a/mlir/lib/Dialect/MemRef/TransformOps/MemRefTransformOps.cpp +++ b/mlir/lib/Dialect/MemRef/TransformOps/MemRefTransformOps.cpp @@ -19,7 +19,8 @@ #include "mlir/Dialect/NVGPU/IR/NVGPUDialect.h" #include "mlir/Dialect/SCF/IR/SCF.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/IR/TransformTypes.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" #include "mlir/Dialect/Vector/Transforms/VectorTransforms.h" #include "mlir/Interfaces/LoopLikeInterface.h" diff --git a/mlir/lib/Dialect/MemRef/Transforms/BufferViewFlowOpInterfaceImpl.cpp b/mlir/lib/Dialect/MemRef/Transforms/BufferViewFlowOpInterfaceImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bbb269bd00161b1669ff092aeee2218496562173 --- /dev/null +++ b/mlir/lib/Dialect/MemRef/Transforms/BufferViewFlowOpInterfaceImpl.cpp @@ -0,0 +1,48 @@ +//===- BufferViewFlowOpInterfaceImpl.cpp - Buffer View Flow Analysis ------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "mlir/Dialect/MemRef/Transforms/BufferViewFlowOpInterfaceImpl.h" + +#include "mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.h" +#include "mlir/Dialect/MemRef/IR/MemRef.h" + +using namespace mlir; +using namespace mlir::bufferization; + +namespace mlir { +namespace memref { +namespace { + +struct ReallocOpInterface + : public BufferViewFlowOpInterface::ExternalModel<ReallocOpInterface, + ReallocOp> { + void + populateDependencies(Operation *op, + RegisterDependenciesFn registerDependenciesFn) const { + auto reallocOp = cast<ReallocOp>(op); + // memref.realloc may return the source operand. + registerDependenciesFn(reallocOp.getSource(), reallocOp.getResult()); + } + + bool mayBeTerminalBuffer(Operation *op, Value value) const { + // The return value of memref.realloc is a terminal buffer because the op + // may return a newly allocated buffer. + return true; + } +}; + +} // namespace +} // namespace memref +} // namespace mlir + +void memref::registerBufferViewFlowOpInterfaceExternalModels( + DialectRegistry ®istry) { + registry.addExtension(+[](MLIRContext *ctx, memref::MemRefDialect *dialect) { + ReallocOp::attachInterface<ReallocOpInterface>(*ctx); + }); +} diff --git a/mlir/lib/Dialect/MemRef/Transforms/CMakeLists.txt b/mlir/lib/Dialect/MemRef/Transforms/CMakeLists.txt index 08b7eab726eb7e813b352c556124cb19add4dbe4..f150ac7ac2d634af24776f3792de54967d90404e 100644 --- a/mlir/lib/Dialect/MemRef/Transforms/CMakeLists.txt +++ b/mlir/lib/Dialect/MemRef/Transforms/CMakeLists.txt @@ -1,5 +1,6 @@ add_mlir_dialect_library(MLIRMemRefTransforms AllocationOpInterfaceImpl.cpp + BufferViewFlowOpInterfaceImpl.cpp ComposeSubView.cpp ExpandOps.cpp ExpandRealloc.cpp @@ -27,6 +28,7 @@ add_mlir_dialect_library(MLIRMemRefTransforms MLIRArithDialect MLIRArithTransforms MLIRBufferizationDialect + MLIRBufferizationTransforms MLIRDialectUtils MLIRFuncDialect MLIRGPUDialect diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp index c09a3403f9a3e3cae72040eeac5fd56484c4ecf7..9ba96e4be7d1fc2b9ecbed6598b07b9c49615285 100644 --- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp +++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp @@ -457,7 +457,7 @@ static ParseResult parseRegions(OpAsmParser &parser, OperationState &state, } static bool isComputeOperation(Operation *op) { - return isa<acc::ParallelOp>(op) || isa<acc::LoopOp>(op); + return isa<acc::ParallelOp, acc::LoopOp>(op); } namespace { diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp index 8a6980e2c6a2d962fc52bb1b2b64d8fbf31ed089..bf5875071e0dc4e74feb68cf8617d64d629c6775 100644 --- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp +++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp @@ -592,7 +592,7 @@ static LogicalResult verifyReductionVarList(Operation *op, Type varType = accum.getType(); auto symbolRef = llvm::cast<SymbolRefAttr>(std::get<1>(args)); auto decl = - SymbolTable::lookupNearestSymbolFrom<ReductionDeclareOp>(op, symbolRef); + SymbolTable::lookupNearestSymbolFrom<DeclareReductionOp>(op, symbolRef); if (!decl) return op->emitOpError() << "expected symbol reference " << symbolRef << " to point to a reduction declaration"; @@ -1112,18 +1112,18 @@ static LogicalResult verifyMapClause(Operation *op, OperandRange mapOperands) { bool implicit = mapTypeToBitFlag( mapTypeBits, llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT); - if ((isa<DataOp>(op) || isa<TargetOp>(op)) && del) + if ((isa<TargetDataOp>(op) || isa<TargetOp>(op)) && del) return emitError(op->getLoc(), "to, from, tofrom and alloc map types are permitted"); - if (isa<EnterDataOp>(op) && (from || del)) + if (isa<TargetEnterDataOp>(op) && (from || del)) return emitError(op->getLoc(), "to and alloc map types are permitted"); - if (isa<ExitDataOp>(op) && to) + if (isa<TargetExitDataOp>(op) && to) return emitError(op->getLoc(), "from, release and delete map types are permitted"); - if (isa<UpdateDataOp>(op)) { + if (isa<TargetUpdateOp>(op)) { if (del) { return emitError(op->getLoc(), "at least one of to or from map types must be " @@ -1161,7 +1161,7 @@ static LogicalResult verifyMapClause(Operation *op, OperandRange mapOperands) { return success(); } -LogicalResult DataOp::verify() { +LogicalResult TargetDataOp::verify() { if (getMapOperands().empty() && getUseDevicePtr().empty() && getUseDeviceAddr().empty()) { return ::emitError(this->getLoc(), "At least one of map, useDevicePtr, or " @@ -1170,21 +1170,21 @@ LogicalResult DataOp::verify() { return verifyMapClause(*this, getMapOperands()); } -LogicalResult EnterDataOp::verify() { +LogicalResult TargetEnterDataOp::verify() { LogicalResult verifyDependVars = verifyDependVarList(*this, getDepends(), getDependVars()); return failed(verifyDependVars) ? verifyDependVars : verifyMapClause(*this, getMapOperands()); } -LogicalResult ExitDataOp::verify() { +LogicalResult TargetExitDataOp::verify() { LogicalResult verifyDependVars = verifyDependVarList(*this, getDepends(), getDependVars()); return failed(verifyDependVars) ? verifyDependVars : verifyMapClause(*this, getMapOperands()); } -LogicalResult UpdateDataOp::verify() { +LogicalResult TargetUpdateOp::verify() { LogicalResult verifyDependVars = verifyDependVarList(*this, getDepends(), getDependVars()); return failed(verifyDependVars) ? verifyDependVars @@ -1209,7 +1209,7 @@ void ParallelOp::build(OpBuilder &builder, OperationState &state, /*allocate_vars=*/ValueRange(), /*allocators_vars=*/ValueRange(), /*reduction_vars=*/ValueRange(), /*reductions=*/nullptr, /*proc_bind_val=*/nullptr, /*private_vars=*/ValueRange(), - /*privatizers=*/nullptr); + /*privatizers=*/nullptr, /*byref=*/false); state.addAttributes(attributes); } @@ -1345,14 +1345,14 @@ LogicalResult SingleOp::verify() { } //===----------------------------------------------------------------------===// -// WsLoopOp +// WsloopOp //===----------------------------------------------------------------------===// /// loop-control ::= `(` ssa-id-list `)` `:` type `=` loop-bounds /// loop-bounds := `(` ssa-id-list `)` to `(` ssa-id-list `)` inclusive? steps /// steps := `step` `(`ssa-id-list`)` ParseResult -parseWsLoop(OpAsmParser &parser, Region ®ion, +parseWsloop(OpAsmParser &parser, Region ®ion, SmallVectorImpl<OpAsmParser::UnresolvedOperand> &lowerBound, SmallVectorImpl<OpAsmParser::UnresolvedOperand> &upperBound, SmallVectorImpl<OpAsmParser::UnresolvedOperand> &steps, @@ -1405,7 +1405,7 @@ parseWsLoop(OpAsmParser &parser, Region ®ion, return parser.parseRegion(region, regionArgs); } -void printWsLoop(OpAsmPrinter &p, Operation *op, Region ®ion, +void printWsloop(OpAsmPrinter &p, Operation *op, Region ®ion, ValueRange lowerBound, ValueRange upperBound, ValueRange steps, TypeRange loopVarTypes, ValueRange reductionOperands, TypeRange reductionTypes, ArrayAttr reductionSymbols, @@ -1531,14 +1531,14 @@ static ParseResult parseAtomicReductionRegion(OpAsmParser &parser, } static void printAtomicReductionRegion(OpAsmPrinter &printer, - ReductionDeclareOp op, Region ®ion) { + DeclareReductionOp op, Region ®ion) { if (region.empty()) return; printer << "atomic "; printer.printRegion(region); } -LogicalResult ReductionDeclareOp::verifyRegions() { +LogicalResult DeclareReductionOp::verifyRegions() { if (getInitializerRegion().empty()) return emitOpError() << "expects non-empty initializer region"; Block &initializerEntryBlock = getInitializerRegion().front(); @@ -1617,17 +1617,17 @@ LogicalResult TaskOp::verify() { } //===----------------------------------------------------------------------===// -// TaskGroupOp +// TaskgroupOp //===----------------------------------------------------------------------===// -LogicalResult TaskGroupOp::verify() { +LogicalResult TaskgroupOp::verify() { return verifyReductionVarList(*this, getTaskReductions(), getTaskReductionVars()); } //===----------------------------------------------------------------------===// -// TaskLoopOp +// TaskloopOp //===----------------------------------------------------------------------===// -SmallVector<Value> TaskLoopOp::getAllReductionVars() { +SmallVector<Value> TaskloopOp::getAllReductionVars() { SmallVector<Value> allReductionNvars(getInReductionVars().begin(), getInReductionVars().end()); allReductionNvars.insert(allReductionNvars.end(), getReductionVars().begin(), @@ -1635,7 +1635,7 @@ SmallVector<Value> TaskLoopOp::getAllReductionVars() { return allReductionNvars; } -LogicalResult TaskLoopOp::verify() { +LogicalResult TaskloopOp::verify() { if (getAllocateVars().size() != getAllocatorsVars().size()) return emitError( "expected equal sizes for allocate and allocator variables"); @@ -1663,10 +1663,10 @@ LogicalResult TaskLoopOp::verify() { } //===----------------------------------------------------------------------===// -// WsLoopOp +// WsloopOp //===----------------------------------------------------------------------===// -void WsLoopOp::build(OpBuilder &builder, OperationState &state, +void WsloopOp::build(OpBuilder &builder, OperationState &state, ValueRange lowerBound, ValueRange upperBound, ValueRange step, ArrayRef<NamedAttribute> attributes) { build(builder, state, lowerBound, upperBound, step, @@ -1674,12 +1674,13 @@ void WsLoopOp::build(OpBuilder &builder, OperationState &state, /*linear_step_vars=*/ValueRange(), /*reduction_vars=*/ValueRange(), /*reductions=*/nullptr, /*schedule_val=*/nullptr, /*schedule_chunk_var=*/nullptr, /*schedule_modifier=*/nullptr, - /*simd_modifier=*/false, /*nowait=*/false, /*ordered_val=*/nullptr, + /*simd_modifier=*/false, /*nowait=*/false, /*byref=*/false, + /*ordered_val=*/nullptr, /*order_val=*/nullptr, /*inclusive=*/false); state.addAttributes(attributes); } -LogicalResult WsLoopOp::verify() { +LogicalResult WsloopOp::verify() { return verifyReductionVarList(*this, getReductions(), getReductionVars()); } @@ -1710,7 +1711,7 @@ LogicalResult CriticalOp::verifySymbolUses(SymbolTableCollection &symbolTable) { //===----------------------------------------------------------------------===// LogicalResult OrderedOp::verify() { - auto container = (*this)->getParentOfType<WsLoopOp>(); + auto container = (*this)->getParentOfType<WsloopOp>(); if (!container || !container.getOrderedValAttr() || container.getOrderedValAttr().getInt() == 0) return emitOpError() << "ordered depend directive must be closely " @@ -1730,7 +1731,7 @@ LogicalResult OrderedRegionOp::verify() { if (getSimd()) return failure(); - if (auto container = (*this)->getParentOfType<WsLoopOp>()) { + if (auto container = (*this)->getParentOfType<WsloopOp>()) { if (!container.getOrderedValAttr() || container.getOrderedValAttr().getInt() != 0) return emitOpError() << "ordered region must be closely nested inside " @@ -1873,15 +1874,15 @@ LogicalResult CancelOp::verify() { << "inside a parallel region"; } if (cct == ClauseCancellationConstructType::Loop) { - if (!isa<WsLoopOp>(parentOp)) { + if (!isa<WsloopOp>(parentOp)) { return emitOpError() << "cancel loop must appear " << "inside a worksharing-loop region"; } - if (cast<WsLoopOp>(parentOp).getNowaitAttr()) { + if (cast<WsloopOp>(parentOp).getNowaitAttr()) { return emitError() << "A worksharing construct that is canceled " << "must not have a nowait clause"; } - if (cast<WsLoopOp>(parentOp).getOrderedValAttr()) { + if (cast<WsloopOp>(parentOp).getOrderedValAttr()) { return emitError() << "A worksharing construct that is canceled " << "must not have an ordered clause"; } @@ -1919,7 +1920,7 @@ LogicalResult CancellationPointOp::verify() { << "inside a parallel region"; } if ((cct == ClauseCancellationConstructType::Loop) && - !isa<WsLoopOp>(parentOp)) { + !isa<WsloopOp>(parentOp)) { return emitOpError() << "cancellation point loop must appear " << "inside a worksharing-loop region"; } @@ -1933,10 +1934,10 @@ LogicalResult CancellationPointOp::verify() { } //===----------------------------------------------------------------------===// -// DataBoundsOp +// MapBoundsOp //===----------------------------------------------------------------------===// -LogicalResult DataBoundsOp::verify() { +LogicalResult MapBoundsOp::verify() { auto extent = getExtent(); auto upperbound = getUpperBound(); if (!extent && !upperbound) diff --git a/mlir/lib/Dialect/SCF/IR/SCF.cpp b/mlir/lib/Dialect/SCF/IR/SCF.cpp index 233e702dbb22928747c7504683379dedd64155a8..7a1aafc9f1c2f95e6819f4cc37f65d2ba3806ec2 100644 --- a/mlir/lib/Dialect/SCF/IR/SCF.cpp +++ b/mlir/lib/Dialect/SCF/IR/SCF.cpp @@ -9,6 +9,8 @@ #include "mlir/Dialect/SCF/IR/SCF.h" #include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/Arith/Utils/Utils.h" +#include "mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h" +#include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h" #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/Dialect/SCF/IR/DeviceMappingInterface.h" @@ -18,6 +20,7 @@ #include "mlir/IR/Matchers.h" #include "mlir/IR/PatternMatch.h" #include "mlir/Interfaces/FunctionInterfaces.h" +#include "mlir/Interfaces/ValueBoundsOpInterface.h" #include "mlir/Support/MathExtras.h" #include "mlir/Transforms/InliningUtils.h" #include "llvm/ADT/MapVector.h" @@ -71,6 +74,12 @@ void SCFDialect::initialize() { #include "mlir/Dialect/SCF/IR/SCFOps.cpp.inc" >(); addInterfaces<SCFInlinerInterface>(); + declarePromisedInterfaces<bufferization::BufferDeallocationOpInterface, + InParallelOp, ReduceReturnOp>(); + declarePromisedInterfaces<bufferization::BufferizableOpInterface, ConditionOp, + ExecuteRegionOp, ForOp, IfOp, IndexSwitchOp, + ForallOp, InParallelOp, WhileOp, YieldOp>(); + declarePromisedInterface<ValueBoundsOpInterface, ForOp>(); } /// Default callback for IfOp builders. Inserts a yield without arguments. @@ -3875,6 +3884,95 @@ struct WhileRemoveDuplicatedResults : public OpRewritePattern<WhileOp> { return success(); } }; + +/// If both ranges contain same values return mappping indices from args2 to +/// args1. Otherwise return std::nullopt. +static std::optional<SmallVector<unsigned>> getArgsMapping(ValueRange args1, + ValueRange args2) { + if (args1.size() != args2.size()) + return std::nullopt; + + SmallVector<unsigned> ret(args1.size()); + for (auto &&[i, arg1] : llvm::enumerate(args1)) { + auto it = llvm::find(args2, arg1); + if (it == args2.end()) + return std::nullopt; + + ret[std::distance(args2.begin(), it)] = static_cast<unsigned>(i); + } + + return ret; +} + +static bool hasDuplicates(ValueRange args) { + llvm::SmallDenseSet<Value> set; + for (Value arg : args) { + if (set.contains(arg)) + return true; + + set.insert(arg); + } + return false; +} + +/// If `before` block args are directly forwarded to `scf.condition`, rearrange +/// `scf.condition` args into same order as block args. Update `after` block +/// args and op result values accordingly. +/// Needed to simplify `scf.while` -> `scf.for` uplifting. +struct WhileOpAlignBeforeArgs : public OpRewritePattern<WhileOp> { + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(WhileOp loop, + PatternRewriter &rewriter) const override { + auto oldBefore = loop.getBeforeBody(); + ConditionOp oldTerm = loop.getConditionOp(); + ValueRange beforeArgs = oldBefore->getArguments(); + ValueRange termArgs = oldTerm.getArgs(); + if (beforeArgs == termArgs) + return failure(); + + if (hasDuplicates(termArgs)) + return failure(); + + auto mapping = getArgsMapping(beforeArgs, termArgs); + if (!mapping) + return failure(); + + { + OpBuilder::InsertionGuard g(rewriter); + rewriter.setInsertionPoint(oldTerm); + rewriter.replaceOpWithNewOp<ConditionOp>(oldTerm, oldTerm.getCondition(), + beforeArgs); + } + + auto oldAfter = loop.getAfterBody(); + + SmallVector<Type> newResultTypes(beforeArgs.size()); + for (auto &&[i, j] : llvm::enumerate(*mapping)) + newResultTypes[j] = loop.getResult(i).getType(); + + auto newLoop = rewriter.create<WhileOp>( + loop.getLoc(), newResultTypes, loop.getInits(), + /*beforeBuilder=*/nullptr, /*afterBuilder=*/nullptr); + auto newBefore = newLoop.getBeforeBody(); + auto newAfter = newLoop.getAfterBody(); + + SmallVector<Value> newResults(beforeArgs.size()); + SmallVector<Value> newAfterArgs(beforeArgs.size()); + for (auto &&[i, j] : llvm::enumerate(*mapping)) { + newResults[i] = newLoop.getResult(j); + newAfterArgs[i] = newAfter->getArgument(j); + } + + rewriter.inlineBlockBefore(oldBefore, newBefore, newBefore->begin(), + newBefore->getArguments()); + rewriter.inlineBlockBefore(oldAfter, newAfter, newAfter->begin(), + newAfterArgs); + + rewriter.replaceOp(loop, newResults); + return success(); + } +}; } // namespace void WhileOp::getCanonicalizationPatterns(RewritePatternSet &results, @@ -3882,7 +3980,7 @@ void WhileOp::getCanonicalizationPatterns(RewritePatternSet &results, results.add<RemoveLoopInvariantArgsFromBeforeBlock, RemoveLoopInvariantValueYielded, WhileConditionTruth, WhileCmpCond, WhileUnusedResult, WhileRemoveDuplicatedResults, - WhileRemoveUnusedArgs>(context); + WhileRemoveUnusedArgs, WhileOpAlignBeforeArgs>(context); } //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/SCF/TransformOps/SCFTransformOps.cpp b/mlir/lib/Dialect/SCF/TransformOps/SCFTransformOps.cpp index bc2fe5772af9d6d2712cdaed0cd0ae2543dd2f79..c09184148208036adf60d6dd6fd451c6287f5d87 100644 --- a/mlir/lib/Dialect/SCF/TransformOps/SCFTransformOps.cpp +++ b/mlir/lib/Dialect/SCF/TransformOps/SCFTransformOps.cpp @@ -17,8 +17,8 @@ #include "mlir/Dialect/SCF/Transforms/Transforms.h" #include "mlir/Dialect/SCF/Utils/Utils.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformOps.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Dialect/Utils/StaticValueUtils.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" #include "mlir/IR/BuiltinAttributes.h" @@ -384,7 +384,7 @@ void transform::TakeAssumedBranchOp::getEffects( } //===----------------------------------------------------------------------===// -// LoopFuseSibling +// LoopFuseSiblingOp //===----------------------------------------------------------------------===// /// Check if `target` and `source` are siblings, in the context that `target` @@ -408,7 +408,7 @@ static DiagnosedSilenceableFailure isOpSibling(Operation *target, // Check if fusion will violate dominance. DominanceInfo domInfo(source); if (target->isBeforeInBlock(source)) { - // Since, `target` is before `source`, all users of results of `target` + // Since `target` is before `source`, all users of results of `target` // need to be dominated by `source`. for (Operation *user : target->getUsers()) { if (!domInfo.properlyDominates(source, user, /*enclosingOpOk=*/false)) { @@ -424,9 +424,8 @@ static DiagnosedSilenceableFailure isOpSibling(Operation *target, // Check if operands of `target` are dominated by `source`. for (Value operand : target->getOperands()) { Operation *operandOp = operand.getDefiningOp(); - // If operand does not have a defining operation, it is a block arguement, - // which will always dominate `source`, since `target` and `source` are in - // the same block and the operand dominated `source` before. + // Operands without defining operations are block arguments. When `target` + // and `source` occur in the same block, these operands dominate `source`. if (!operandOp) continue; @@ -441,8 +440,11 @@ static DiagnosedSilenceableFailure isOpSibling(Operation *target, bool failed = false; OpOperand *failedValue = nullptr; visitUsedValuesDefinedAbove(target->getRegions(), [&](OpOperand *operand) { - if (!domInfo.properlyDominates(operand->getOwner(), source, - /*enclosingOpOk=*/false)) { + Operation *operandOp = operand->get().getDefiningOp(); + if (operandOp && !domInfo.properlyDominates(operandOp, source, + /*enclosingOpOk=*/false)) { + // `operand` is not an argument of an enclosing block and the defining + // op of `operand` is outside `target` but does not dominate `source`. failed = true; failedValue = operand; } @@ -457,12 +459,11 @@ static DiagnosedSilenceableFailure isOpSibling(Operation *target, return DiagnosedSilenceableFailure::success(); } -/// Check if `target` can be fused into `source`. +/// Check if `target` scf.forall can be fused into `source` scf.forall. /// -/// This is a simple check that just checks if both loops have same -/// bounds, steps and mapping. This check does not ensure that the side effects -/// of `target` are independent of `source` or vice-versa. It is the -/// responsibility of the caller to ensure that. +/// This simply checks if both loops have the same bounds, steps and mapping. +/// No attempt is made at checking that the side effects of `target` and +/// `source` are independent of each other. static bool isForallWithIdenticalConfiguration(Operation *target, Operation *source) { auto targetOp = dyn_cast<scf::ForallOp>(target); @@ -476,21 +477,27 @@ static bool isForallWithIdenticalConfiguration(Operation *target, targetOp.getMapping() == sourceOp.getMapping(); } -/// Fuse `target` into `source` assuming they are siblings and indepndent. -/// TODO: Add fusion for more operations. Currently, we handle only scf.forall. -static Operation *fuseSiblings(Operation *target, Operation *source, - RewriterBase &rewriter) { - auto targetOp = dyn_cast<scf::ForallOp>(target); - auto sourceOp = dyn_cast<scf::ForallOp>(source); +/// Check if `target` scf.for can be fused into `source` scf.for. +/// +/// This simply checks if both loops have the same bounds and steps. No attempt +/// is made at checking that the side effects of `target` and `source` are +/// independent of each other. +static bool isForWithIdenticalConfiguration(Operation *target, + Operation *source) { + auto targetOp = dyn_cast<scf::ForOp>(target); + auto sourceOp = dyn_cast<scf::ForOp>(source); if (!targetOp || !sourceOp) - return nullptr; - return fuseIndependentSiblingForallLoops(targetOp, sourceOp, rewriter); + return false; + + return targetOp.getLowerBound() == sourceOp.getLowerBound() && + targetOp.getUpperBound() == sourceOp.getUpperBound() && + targetOp.getStep() == sourceOp.getStep(); } DiagnosedSilenceableFailure -transform::LoopFuseSibling::apply(transform::TransformRewriter &rewriter, - transform::TransformResults &results, - transform::TransformState &state) { +transform::LoopFuseSiblingOp::apply(transform::TransformRewriter &rewriter, + transform::TransformResults &results, + transform::TransformState &state) { auto targetOps = state.getPayloadOps(getTarget()); auto sourceOps = state.getPayloadOps(getSource()); @@ -510,13 +517,18 @@ transform::LoopFuseSibling::apply(transform::TransformRewriter &rewriter, if (!diag.succeeded()) return diag; - // Check if the target can be fused into source. - if (!isForallWithIdenticalConfiguration(target, source)) { + Operation *fusedLoop; + /// TODO: Support fusion for loop-like ops besides scf.for and scf.forall. + if (isForWithIdenticalConfiguration(target, source)) { + fusedLoop = fuseIndependentSiblingForLoops( + cast<scf::ForOp>(target), cast<scf::ForOp>(source), rewriter); + } else if (isForallWithIdenticalConfiguration(target, source)) { + fusedLoop = fuseIndependentSiblingForallLoops( + cast<scf::ForallOp>(target), cast<scf::ForallOp>(source), rewriter); + } else return emitSilenceableFailure(target->getLoc()) << "operations cannot be fused"; - } - Operation *fusedLoop = fuseSiblings(target, source, rewriter); assert(fusedLoop && "failed to fuse operations"); results.set(cast<OpResult>(getFusedLoop()), {fusedLoop}); diff --git a/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp b/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp index a5bff0a892c3dffe7d9429c3e5aeaa5393314aad..a30e349d49136c29c10ba46a6316772d487e3b14 100644 --- a/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp +++ b/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp @@ -220,7 +220,7 @@ LogicalResult mlir::scf::peelForLoopFirstIteration(RewriterBase &b, ForOp forOp, auto stepInt = getConstantIntValue(forOp.getStep()); // Peeling is not needed if there is one or less iteration. - if (lbInt && ubInt && stepInt && (*ubInt - *lbInt) / *stepInt <= 1) + if (lbInt && ubInt && stepInt && ceil(float(*ubInt - *lbInt) / *stepInt) <= 1) return failure(); AffineExpr lbSymbol, stepSymbol; diff --git a/mlir/lib/Dialect/SCF/Utils/Utils.cpp b/mlir/lib/Dialect/SCF/Utils/Utils.cpp index 502d7e197a6f6bb5bfeeeb4e2eb30f84f9868ff1..914aeb4fa79fda289f9da6306637c33d2edf1a4a 100644 --- a/mlir/lib/Dialect/SCF/Utils/Utils.cpp +++ b/mlir/lib/Dialect/SCF/Utils/Utils.cpp @@ -910,61 +910,98 @@ scf::ForallOp mlir::fuseIndependentSiblingForallLoops(scf::ForallOp target, unsigned numTargetOuts = target.getNumResults(); unsigned numSourceOuts = source.getNumResults(); - OperandRange targetOuts = target.getOutputs(); - OperandRange sourceOuts = source.getOutputs(); - // Create fused shared_outs. SmallVector<Value> fusedOuts; - fusedOuts.reserve(numTargetOuts + numSourceOuts); - fusedOuts.append(targetOuts.begin(), targetOuts.end()); - fusedOuts.append(sourceOuts.begin(), sourceOuts.end()); + llvm::append_range(fusedOuts, target.getOutputs()); + llvm::append_range(fusedOuts, source.getOutputs()); - // Create a new scf::forall op after the source loop. + // Create a new scf.forall op after the source loop. rewriter.setInsertionPointAfter(source); scf::ForallOp fusedLoop = rewriter.create<scf::ForallOp>( source.getLoc(), source.getMixedLowerBound(), source.getMixedUpperBound(), source.getMixedStep(), fusedOuts, source.getMapping()); // Map control operands. - IRMapping fusedMapping; - fusedMapping.map(target.getInductionVars(), fusedLoop.getInductionVars()); - fusedMapping.map(source.getInductionVars(), fusedLoop.getInductionVars()); + IRMapping mapping; + mapping.map(target.getInductionVars(), fusedLoop.getInductionVars()); + mapping.map(source.getInductionVars(), fusedLoop.getInductionVars()); // Map shared outs. - fusedMapping.map(target.getRegionIterArgs(), - fusedLoop.getRegionIterArgs().slice(0, numTargetOuts)); - fusedMapping.map( - source.getRegionIterArgs(), - fusedLoop.getRegionIterArgs().slice(numTargetOuts, numSourceOuts)); + mapping.map(target.getRegionIterArgs(), + fusedLoop.getRegionIterArgs().take_front(numTargetOuts)); + mapping.map(source.getRegionIterArgs(), + fusedLoop.getRegionIterArgs().take_back(numSourceOuts)); // Append everything except the terminator into the fused operation. rewriter.setInsertionPointToStart(fusedLoop.getBody()); for (Operation &op : target.getBody()->without_terminator()) - rewriter.clone(op, fusedMapping); + rewriter.clone(op, mapping); for (Operation &op : source.getBody()->without_terminator()) - rewriter.clone(op, fusedMapping); + rewriter.clone(op, mapping); // Fuse the old terminator in_parallel ops into the new one. scf::InParallelOp targetTerm = target.getTerminator(); scf::InParallelOp sourceTerm = source.getTerminator(); scf::InParallelOp fusedTerm = fusedLoop.getTerminator(); - rewriter.setInsertionPointToStart(fusedTerm.getBody()); for (Operation &op : targetTerm.getYieldingOps()) - rewriter.clone(op, fusedMapping); + rewriter.clone(op, mapping); for (Operation &op : sourceTerm.getYieldingOps()) - rewriter.clone(op, fusedMapping); - - // Replace all uses of the old loops with the fused loop. - rewriter.replaceAllUsesWith(target.getResults(), - fusedLoop.getResults().slice(0, numTargetOuts)); - rewriter.replaceAllUsesWith( - source.getResults(), - fusedLoop.getResults().slice(numTargetOuts, numSourceOuts)); - - // Erase the old loops. - rewriter.eraseOp(target); - rewriter.eraseOp(source); + rewriter.clone(op, mapping); + + // Replace old loops by substituting their uses by results of the fused loop. + rewriter.replaceOp(target, fusedLoop.getResults().take_front(numTargetOuts)); + rewriter.replaceOp(source, fusedLoop.getResults().take_back(numSourceOuts)); + + return fusedLoop; +} + +scf::ForOp mlir::fuseIndependentSiblingForLoops(scf::ForOp target, + scf::ForOp source, + RewriterBase &rewriter) { + unsigned numTargetOuts = target.getNumResults(); + unsigned numSourceOuts = source.getNumResults(); + + // Create fused init_args, with target's init_args before source's init_args. + SmallVector<Value> fusedInitArgs; + llvm::append_range(fusedInitArgs, target.getInitArgs()); + llvm::append_range(fusedInitArgs, source.getInitArgs()); + + // Create a new scf.for op after the source loop (with scf.yield terminator + // (without arguments) only in case its init_args is empty). + rewriter.setInsertionPointAfter(source); + scf::ForOp fusedLoop = rewriter.create<scf::ForOp>( + source.getLoc(), source.getLowerBound(), source.getUpperBound(), + source.getStep(), fusedInitArgs); + + // Map original induction variables and operands to those of the fused loop. + IRMapping mapping; + mapping.map(target.getInductionVar(), fusedLoop.getInductionVar()); + mapping.map(target.getRegionIterArgs(), + fusedLoop.getRegionIterArgs().take_front(numTargetOuts)); + mapping.map(source.getInductionVar(), fusedLoop.getInductionVar()); + mapping.map(source.getRegionIterArgs(), + fusedLoop.getRegionIterArgs().take_back(numSourceOuts)); + + // Merge target's body into the new (fused) for loop and then source's body. + rewriter.setInsertionPointToStart(fusedLoop.getBody()); + for (Operation &op : target.getBody()->without_terminator()) + rewriter.clone(op, mapping); + for (Operation &op : source.getBody()->without_terminator()) + rewriter.clone(op, mapping); + + // Build fused yield results by appropriately mapping original yield operands. + SmallVector<Value> yieldResults; + for (Value operand : target.getBody()->getTerminator()->getOperands()) + yieldResults.push_back(mapping.lookupOrDefault(operand)); + for (Value operand : source.getBody()->getTerminator()->getOperands()) + yieldResults.push_back(mapping.lookupOrDefault(operand)); + if (!yieldResults.empty()) + rewriter.create<scf::YieldOp>(source.getLoc(), yieldResults); + + // Replace old loops by substituting their uses by results of the fused loop. + rewriter.replaceOp(target, fusedLoop.getResults().take_front(numTargetOuts)); + rewriter.replaceOp(source, fusedLoop.getResults().take_back(numSourceOuts)); return fusedLoop; } diff --git a/mlir/lib/Dialect/SPIRV/IR/CMakeLists.txt b/mlir/lib/Dialect/SPIRV/IR/CMakeLists.txt index 2b5cedafae1e85b91569c739647e3d63cce6f5cc..b185264211474fcb6dade5f3a60fdbf1709b945a 100644 --- a/mlir/lib/Dialect/SPIRV/IR/CMakeLists.txt +++ b/mlir/lib/Dialect/SPIRV/IR/CMakeLists.txt @@ -27,6 +27,7 @@ add_mlir_dialect_library(MLIRSPIRVDialect ${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/SPIRV DEPENDS + MLIRGPUDialect MLIRSPIRVAttributeIncGen MLIRSPIRVAttrUtilsGen MLIRSPIRVAvailabilityIncGen diff --git a/mlir/lib/Dialect/SPIRV/IR/CooperativeMatrixOps.cpp b/mlir/lib/Dialect/SPIRV/IR/CooperativeMatrixOps.cpp index d532d466334a56c76bc67d9d3680742897df8df8..2ff3efdc96a7f8b22f1c5779f38a78936cc58deb 100644 --- a/mlir/lib/Dialect/SPIRV/IR/CooperativeMatrixOps.cpp +++ b/mlir/lib/Dialect/SPIRV/IR/CooperativeMatrixOps.cpp @@ -125,8 +125,7 @@ LogicalResult KHRCooperativeMatrixMulAddOp::verify() { if (getMatrixOperands()) { Type elementTypes[] = {typeA.getElementType(), typeB.getElementType(), typeC.getElementType()}; - if (!llvm::all_of(elementTypes, - [](Type ty) { return isa<IntegerType>(ty); })) { + if (!llvm::all_of(elementTypes, llvm::IsaPred<IntegerType>)) { return emitOpError("Matrix Operands require all matrix element types to " "be Integer Types"); } diff --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp b/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp index 4c62289a1e94580f5a2ea14a78c50a6e45ed9428..b1acfd1a2abedb07bb2eef680be9e03da460d6d3 100644 --- a/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp +++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVCanonicalization.cpp @@ -250,14 +250,11 @@ struct MulExtendedFold final : OpRewritePattern<MulOp> { auto highBits = constFoldBinaryOp<IntegerAttr>( {lhsAttr, rhsAttr}, [](const APInt &a, const APInt &b) { - unsigned bitWidth = a.getBitWidth(); - APInt c; if (IsSigned) { - c = a.sext(bitWidth * 2) * b.sext(bitWidth * 2); + return llvm::APIntOps::mulhs(a, b); } else { - c = a.zext(bitWidth * 2) * b.zext(bitWidth * 2); + return llvm::APIntOps::mulhu(a, b); } - return c.extractBits(bitWidth, bitWidth); // Extract high result }); if (!highBits) @@ -797,6 +794,49 @@ OpFoldResult spirv::LogicalOrOp::fold(FoldAdaptor adaptor) { return Attribute(); } +//===----------------------------------------------------------------------===// +// spirv.SelectOp +//===----------------------------------------------------------------------===// + +OpFoldResult spirv::SelectOp::fold(FoldAdaptor adaptor) { + // spirv.Select _ x x -> x + Value trueVals = getTrueValue(); + Value falseVals = getFalseValue(); + if (trueVals == falseVals) + return trueVals; + + ArrayRef<Attribute> operands = adaptor.getOperands(); + + // spirv.Select true x y -> x + // spirv.Select false x y -> y + if (auto boolAttr = getScalarOrSplatBoolAttr(operands[0])) + return *boolAttr ? trueVals : falseVals; + + // Check that all the operands are constant + if (!operands[0] || !operands[1] || !operands[2]) + return Attribute(); + + // Note: getScalarOrSplatBoolAttr will always return a boolAttr if we are in + // the scalar case. Hence, we are only required to consider the case of + // DenseElementsAttr in foldSelectOp. + auto condAttrs = dyn_cast<DenseElementsAttr>(operands[0]); + auto trueAttrs = dyn_cast<DenseElementsAttr>(operands[1]); + auto falseAttrs = dyn_cast<DenseElementsAttr>(operands[2]); + if (!condAttrs || !trueAttrs || !falseAttrs) + return Attribute(); + + auto elementResults = llvm::to_vector<4>(trueAttrs.getValues<Attribute>()); + auto iters = llvm::zip_equal(elementResults, condAttrs.getValues<BoolAttr>(), + falseAttrs.getValues<Attribute>()); + for (auto [result, cond, falseRes] : iters) { + if (!cond.getValue()) + result = falseRes; + } + + auto resultType = trueAttrs.getType(); + return DenseElementsAttr::get(cast<ShapedType>(resultType), elementResults); +} + //===----------------------------------------------------------------------===// // spirv.IEqualOp //===----------------------------------------------------------------------===// @@ -837,6 +877,172 @@ OpFoldResult spirv::INotEqualOp::fold(spirv::INotEqualOp::FoldAdaptor adaptor) { }); } +//===----------------------------------------------------------------------===// +// spirv.SGreaterThan +//===----------------------------------------------------------------------===// + +OpFoldResult +spirv::SGreaterThanOp::fold(spirv::SGreaterThanOp::FoldAdaptor adaptor) { + // x == x -> false + if (getOperand1() == getOperand2()) { + auto falseAttr = BoolAttr::get(getContext(), false); + if (isa<IntegerType>(getType())) + return falseAttr; + if (auto vecTy = dyn_cast<VectorType>(getType())) + return SplatElementsAttr::get(vecTy, falseAttr); + } + + return constFoldBinaryOp<IntegerAttr>( + adaptor.getOperands(), getType(), [](const APInt &a, const APInt &b) { + return a.sgt(b) ? APInt::getAllOnes(1) : APInt::getZero(1); + }); +} + +//===----------------------------------------------------------------------===// +// spirv.SGreaterThanEqual +//===----------------------------------------------------------------------===// + +OpFoldResult spirv::SGreaterThanEqualOp::fold( + spirv::SGreaterThanEqualOp::FoldAdaptor adaptor) { + // x == x -> true + if (getOperand1() == getOperand2()) { + auto trueAttr = BoolAttr::get(getContext(), true); + if (isa<IntegerType>(getType())) + return trueAttr; + if (auto vecTy = dyn_cast<VectorType>(getType())) + return SplatElementsAttr::get(vecTy, trueAttr); + } + + return constFoldBinaryOp<IntegerAttr>( + adaptor.getOperands(), getType(), [](const APInt &a, const APInt &b) { + return a.sge(b) ? APInt::getAllOnes(1) : APInt::getZero(1); + }); +} + +//===----------------------------------------------------------------------===// +// spirv.UGreaterThan +//===----------------------------------------------------------------------===// + +OpFoldResult +spirv::UGreaterThanOp::fold(spirv::UGreaterThanOp::FoldAdaptor adaptor) { + // x == x -> false + if (getOperand1() == getOperand2()) { + auto falseAttr = BoolAttr::get(getContext(), false); + if (isa<IntegerType>(getType())) + return falseAttr; + if (auto vecTy = dyn_cast<VectorType>(getType())) + return SplatElementsAttr::get(vecTy, falseAttr); + } + + return constFoldBinaryOp<IntegerAttr>( + adaptor.getOperands(), getType(), [](const APInt &a, const APInt &b) { + return a.ugt(b) ? APInt::getAllOnes(1) : APInt::getZero(1); + }); +} + +//===----------------------------------------------------------------------===// +// spirv.UGreaterThanEqual +//===----------------------------------------------------------------------===// + +OpFoldResult spirv::UGreaterThanEqualOp::fold( + spirv::UGreaterThanEqualOp::FoldAdaptor adaptor) { + // x == x -> true + if (getOperand1() == getOperand2()) { + auto trueAttr = BoolAttr::get(getContext(), true); + if (isa<IntegerType>(getType())) + return trueAttr; + if (auto vecTy = dyn_cast<VectorType>(getType())) + return SplatElementsAttr::get(vecTy, trueAttr); + } + + return constFoldBinaryOp<IntegerAttr>( + adaptor.getOperands(), getType(), [](const APInt &a, const APInt &b) { + return a.uge(b) ? APInt::getAllOnes(1) : APInt::getZero(1); + }); +} + +//===----------------------------------------------------------------------===// +// spirv.SLessThan +//===----------------------------------------------------------------------===// + +OpFoldResult spirv::SLessThanOp::fold(spirv::SLessThanOp::FoldAdaptor adaptor) { + // x == x -> false + if (getOperand1() == getOperand2()) { + auto falseAttr = BoolAttr::get(getContext(), false); + if (isa<IntegerType>(getType())) + return falseAttr; + if (auto vecTy = dyn_cast<VectorType>(getType())) + return SplatElementsAttr::get(vecTy, falseAttr); + } + + return constFoldBinaryOp<IntegerAttr>( + adaptor.getOperands(), getType(), [](const APInt &a, const APInt &b) { + return a.slt(b) ? APInt::getAllOnes(1) : APInt::getZero(1); + }); +} + +//===----------------------------------------------------------------------===// +// spirv.SLessThanEqual +//===----------------------------------------------------------------------===// + +OpFoldResult +spirv::SLessThanEqualOp::fold(spirv::SLessThanEqualOp::FoldAdaptor adaptor) { + // x == x -> true + if (getOperand1() == getOperand2()) { + auto trueAttr = BoolAttr::get(getContext(), true); + if (isa<IntegerType>(getType())) + return trueAttr; + if (auto vecTy = dyn_cast<VectorType>(getType())) + return SplatElementsAttr::get(vecTy, trueAttr); + } + + return constFoldBinaryOp<IntegerAttr>( + adaptor.getOperands(), getType(), [](const APInt &a, const APInt &b) { + return a.sle(b) ? APInt::getAllOnes(1) : APInt::getZero(1); + }); +} + +//===----------------------------------------------------------------------===// +// spirv.ULessThan +//===----------------------------------------------------------------------===// + +OpFoldResult spirv::ULessThanOp::fold(spirv::ULessThanOp::FoldAdaptor adaptor) { + // x == x -> false + if (getOperand1() == getOperand2()) { + auto falseAttr = BoolAttr::get(getContext(), false); + if (isa<IntegerType>(getType())) + return falseAttr; + if (auto vecTy = dyn_cast<VectorType>(getType())) + return SplatElementsAttr::get(vecTy, falseAttr); + } + + return constFoldBinaryOp<IntegerAttr>( + adaptor.getOperands(), getType(), [](const APInt &a, const APInt &b) { + return a.ult(b) ? APInt::getAllOnes(1) : APInt::getZero(1); + }); +} + +//===----------------------------------------------------------------------===// +// spirv.ULessThanEqual +//===----------------------------------------------------------------------===// + +OpFoldResult +spirv::ULessThanEqualOp::fold(spirv::ULessThanEqualOp::FoldAdaptor adaptor) { + // x == x -> true + if (getOperand1() == getOperand2()) { + auto trueAttr = BoolAttr::get(getContext(), true); + if (isa<IntegerType>(getType())) + return trueAttr; + if (auto vecTy = dyn_cast<VectorType>(getType())) + return SplatElementsAttr::get(vecTy, trueAttr); + } + + return constFoldBinaryOp<IntegerAttr>( + adaptor.getOperands(), getType(), [](const APInt &a, const APInt &b) { + return a.ule(b) ? APInt::getAllOnes(1) : APInt::getZero(1); + }); +} + //===----------------------------------------------------------------------===// // spirv.ShiftLeftLogical //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVDialect.cpp b/mlir/lib/Dialect/SPIRV/IR/SPIRVDialect.cpp index e914f46bdef6435fad71d2b0e3ed4081bd2d065a..72488d6e5d0b09859c48aad050885692fc9a3b8c 100644 --- a/mlir/lib/Dialect/SPIRV/IR/SPIRVDialect.cpp +++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVDialect.cpp @@ -135,7 +135,7 @@ void SPIRVDialect::initialize() { // Allow unknown operations because SPIR-V is extensible. allowUnknownOperations(); - declarePromisedInterface<TargetEnvAttr, gpu::TargetAttrInterface>(); + declarePromisedInterface<gpu::TargetAttrInterface, TargetEnvAttr>(); } std::string SPIRVDialect::getAttributeName(Decoration decoration) { diff --git a/mlir/lib/Dialect/SPIRV/Transforms/SPIRVConversion.cpp b/mlir/lib/Dialect/SPIRV/Transforms/SPIRVConversion.cpp index 2b79c8022b8e85b4d63dfef199c8b49ce98a0564..4072608dc8f8736214e2ec948960f85c700929fa 100644 --- a/mlir/lib/Dialect/SPIRV/Transforms/SPIRVConversion.cpp +++ b/mlir/lib/Dialect/SPIRV/Transforms/SPIRVConversion.cpp @@ -991,15 +991,16 @@ Value mlir::spirv::linearizeIndex(ValueRange indices, ArrayRef<int64_t> strides, // broken down into progressive small steps so we can have intermediate steps // using other dialects. At the moment SPIR-V is the final sink. - Value linearizedIndex = builder.create<spirv::ConstantOp>( + Value linearizedIndex = builder.createOrFold<spirv::ConstantOp>( loc, integerType, IntegerAttr::get(integerType, offset)); for (const auto &index : llvm::enumerate(indices)) { - Value strideVal = builder.create<spirv::ConstantOp>( + Value strideVal = builder.createOrFold<spirv::ConstantOp>( loc, integerType, IntegerAttr::get(integerType, strides[index.index()])); - Value update = builder.create<spirv::IMulOp>(loc, strideVal, index.value()); + Value update = + builder.createOrFold<spirv::IMulOp>(loc, index.value(), strideVal); linearizedIndex = - builder.create<spirv::IAddOp>(loc, linearizedIndex, update); + builder.createOrFold<spirv::IAddOp>(loc, update, linearizedIndex); } return linearizedIndex; } diff --git a/mlir/lib/Dialect/SPIRV/Transforms/SPIRVWebGPUTransforms.cpp b/mlir/lib/Dialect/SPIRV/Transforms/SPIRVWebGPUTransforms.cpp index 21de1c9e867c04ed4250424ae06ccfbd77446858..5d4dd5b3a1e01344e0a4cb72a38668b40b1af071 100644 --- a/mlir/lib/Dialect/SPIRV/Transforms/SPIRVWebGPUTransforms.cpp +++ b/mlir/lib/Dialect/SPIRV/Transforms/SPIRVWebGPUTransforms.cpp @@ -39,7 +39,7 @@ namespace { //===----------------------------------------------------------------------===// // Helpers //===----------------------------------------------------------------------===// -Attribute getScalarOrSplatAttr(Type type, int64_t value) { +static Attribute getScalarOrSplatAttr(Type type, int64_t value) { APInt sizedValue(getElementTypeOrSelf(type).getIntOrFloatBitWidth(), value); if (auto intTy = dyn_cast<IntegerType>(type)) return IntegerAttr::get(intTy, sizedValue); @@ -47,9 +47,9 @@ Attribute getScalarOrSplatAttr(Type type, int64_t value) { return SplatElementsAttr::get(cast<ShapedType>(type), sizedValue); } -Value lowerExtendedMultiplication(Operation *mulOp, PatternRewriter &rewriter, - Value lhs, Value rhs, - bool signExtendArguments) { +static Value lowerExtendedMultiplication(Operation *mulOp, + PatternRewriter &rewriter, Value lhs, + Value rhs, bool signExtendArguments) { Location loc = mulOp->getLoc(); Type argTy = lhs.getType(); // Emulate 64-bit multiplication by splitting each input element of type i32 @@ -203,15 +203,39 @@ struct ExpandAddCarryPattern final : OpRewritePattern<IAddCarryOp> { } }; +struct ExpandIsInfPattern final : OpRewritePattern<IsInfOp> { + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(IsInfOp op, + PatternRewriter &rewriter) const override { + // We assume values to be finite and turn `IsInf` info `false`. + rewriter.replaceOpWithNewOp<spirv::ConstantOp>( + op, op.getType(), getScalarOrSplatAttr(op.getType(), 0)); + return success(); + } +}; + +struct ExpandIsNanPattern final : OpRewritePattern<IsNanOp> { + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(IsNanOp op, + PatternRewriter &rewriter) const override { + // We assume values to be finite and turn `IsNan` info `false`. + rewriter.replaceOpWithNewOp<spirv::ConstantOp>( + op, op.getType(), getScalarOrSplatAttr(op.getType(), 0)); + return success(); + } +}; + //===----------------------------------------------------------------------===// // Passes //===----------------------------------------------------------------------===// -class WebGPUPreparePass - : public impl::SPIRVWebGPUPreparePassBase<WebGPUPreparePass> { -public: +struct WebGPUPreparePass final + : impl::SPIRVWebGPUPreparePassBase<WebGPUPreparePass> { void runOnOperation() override { RewritePatternSet patterns(&getContext()); populateSPIRVExpandExtendedMultiplicationPatterns(patterns); + populateSPIRVExpandNonFiniteArithmeticPatterns(patterns); if (failed( applyPatternsAndFoldGreedily(getOperation(), std::move(patterns)))) @@ -227,12 +251,16 @@ void populateSPIRVExpandExtendedMultiplicationPatterns( RewritePatternSet &patterns) { // WGSL currently does not support extended multiplication ops, see: // https://github.com/gpuweb/gpuweb/issues/1565. - patterns.add< - // clang-format off - ExpandSMulExtendedPattern, - ExpandUMulExtendedPattern, - ExpandAddCarryPattern - >(patterns.getContext()); + patterns.add<ExpandSMulExtendedPattern, ExpandUMulExtendedPattern, + ExpandAddCarryPattern>(patterns.getContext()); } + +void populateSPIRVExpandNonFiniteArithmeticPatterns( + RewritePatternSet &patterns) { + // WGSL currently does not support `isInf` and `isNan`, see: + // https://github.com/gpuweb/gpuweb/pull/2311. + patterns.add<ExpandIsInfPattern, ExpandIsNanPattern>(patterns.getContext()); +} + } // namespace spirv } // namespace mlir diff --git a/mlir/lib/Dialect/Shape/IR/Shape.cpp b/mlir/lib/Dialect/Shape/IR/Shape.cpp index d9ee39a4e8dd321b03336dae2a173af612febd7c..58c3f4c334577cd36c92bdff891e70d4ae0306aa 100644 --- a/mlir/lib/Dialect/Shape/IR/Shape.cpp +++ b/mlir/lib/Dialect/Shape/IR/Shape.cpp @@ -11,6 +11,7 @@ #include "mlir/Dialect/Shape/IR/Shape.h" #include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h" #include "mlir/Dialect/CommonFolders.h" #include "mlir/Dialect/Tensor/IR/Tensor.h" #include "mlir/Dialect/Traits.h" @@ -64,9 +65,8 @@ LogicalResult shape::getShapeVec(Value input, } static bool isErrorPropagationPossible(TypeRange operandTypes) { - return llvm::any_of(operandTypes, [](Type ty) { - return llvm::isa<SizeType, ShapeType, ValueShapeType>(ty); - }); + return llvm::any_of(operandTypes, + llvm::IsaPred<SizeType, ShapeType, ValueShapeType>); } static LogicalResult verifySizeOrIndexOp(Operation *op) { @@ -143,6 +143,8 @@ void ShapeDialect::initialize() { // still evolving it makes it simple to start with an unregistered ops and // try different variants before actually defining the op. allowUnknownOperations(); + declarePromisedInterfaces<bufferization::BufferizableOpInterface, AssumingOp, + AssumingYieldOp>(); } Operation *ShapeDialect::materializeConstant(OpBuilder &builder, diff --git a/mlir/lib/Dialect/SparseTensor/IR/SparseTensorDialect.cpp b/mlir/lib/Dialect/SparseTensor/IR/SparseTensorDialect.cpp index 7750efdd9add0f4a412a2f0a1fa5f34346a6293b..e4d93c5623b9c48ff88cb79575005b1d7225025b 100644 --- a/mlir/lib/Dialect/SparseTensor/IR/SparseTensorDialect.cpp +++ b/mlir/lib/Dialect/SparseTensor/IR/SparseTensorDialect.cpp @@ -16,6 +16,7 @@ #include "mlir/Dialect/SparseTensor/IR/SparseTensorType.h" #include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h" #include "mlir/Dialect/Utils/StaticValueUtils.h" #include "mlir/IR/Builders.h" #include "mlir/IR/DialectImplementation.h" @@ -1590,7 +1591,8 @@ static LogicalResult verifyNumBlockArgs(T *op, Region ®ion, if (!yield) return op->emitError() << regionName << " region must end with sparse_tensor.yield"; - if (!yield.getResult() || yield.getResult().getType() != outputType) + if (!yield.hasSingleResult() || + yield.getSingleResult().getType() != outputType) return op->emitError() << regionName << " region yield type mismatch"; return success(); @@ -1653,7 +1655,8 @@ LogicalResult UnaryOp::verify() { // Absent branch can only yield invariant values. Block *absentBlock = &absent.front(); Block *parent = getOperation()->getBlock(); - Value absentVal = cast<YieldOp>(absentBlock->getTerminator()).getResult(); + Value absentVal = + cast<YieldOp>(absentBlock->getTerminator()).getSingleResult(); if (auto arg = dyn_cast<BlockArgument>(absentVal)) { if (arg.getOwner() == parent) return emitError("absent region cannot yield linalg argument"); @@ -1906,18 +1909,6 @@ LogicalResult SortOp::verify() { return success(); } -LogicalResult YieldOp::verify() { - // Check for compatible parent. - auto *parentOp = (*this)->getParentOp(); - if (isa<BinaryOp>(parentOp) || isa<UnaryOp>(parentOp) || - isa<ReduceOp>(parentOp) || isa<SelectOp>(parentOp) || - isa<ForeachOp>(parentOp)) - return success(); - - return emitOpError("expected parent op to be sparse_tensor unary, binary, " - "reduce, select or foreach"); -} - /// Materialize a single constant operation from a given attribute value with /// the desired resultant type. Operation *SparseTensorDialect::materializeConstant(OpBuilder &builder, @@ -1956,6 +1947,10 @@ void SparseTensorDialect::initialize() { #define GET_OP_LIST #include "mlir/Dialect/SparseTensor/IR/SparseTensorOps.cpp.inc" >(); + declarePromisedInterfaces< + bufferization::BufferizableOpInterface, ConcatenateOp, ConvertOp, LoadOp, + NewOp, NumberOfEntriesOp, AssembleOp, DisassembleOp, + ToCoordinatesBufferOp, ToCoordinatesOp, ToPositionsOp, ToValuesOp>(); } #define GET_OP_CLASSES diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/BufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/BufferizableOpInterfaceImpl.cpp index a942a721e218fe76219040c62e7ec08aed2bd85b..7734d1d258453c8dcff23135de87362f1ecf8e39 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/BufferizableOpInterfaceImpl.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/BufferizableOpInterfaceImpl.cpp @@ -187,6 +187,35 @@ struct DisassembleOpInterface } }; +struct ForeachOpInterface : public SparseBufferizableOpInterfaceExternalModel< + ForeachOpInterface, sparse_tensor::ForeachOp> { + bool bufferizesToMemoryRead(Operation *op, OpOperand &opOperand, + const AnalysisState &state) const { + return true; + } + + bool bufferizesToMemoryWrite(Operation *op, OpOperand &opOperand, + const AnalysisState &state) const { + return false; + } + + AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand, + const AnalysisState &state) const { + return {}; + } + + LogicalResult verifyAnalysis(Operation *op, + const AnalysisState &state) const { + // A more complex analysis (similar to scf.for) is needed if the op returns + // a tensor. That tensor would have to be bufferized (not implemented yet). + for (OpResult result : op->getResults()) { + if (isa<TensorType>(result.getType())) + return op->emitOpError("tensor results are not supported yet"); + } + return success(); + } +}; + struct NumberOfEntriesOpInterface : public SparseBufferizableOpInterfaceExternalModel< NumberOfEntriesOpInterface, sparse_tensor::NumberOfEntriesOp> { @@ -307,6 +336,7 @@ void mlir::sparse_tensor::registerBufferizableOpInterfaceExternalModels( NumberOfEntriesOpInterface>(*ctx); sparse_tensor::AssembleOp::attachInterface<AssembleOpInterface>(*ctx); sparse_tensor::DisassembleOp::attachInterface<DisassembleOpInterface>(*ctx); + sparse_tensor::ForeachOp::attachInterface<ForeachOpInterface>(*ctx); sparse_tensor::ToCoordinatesBufferOp::attachInterface< ToCoordinatesBufferOpInterface>(*ctx); sparse_tensor::ToCoordinatesOp::attachInterface<ToCoordinatesOpInterface>( diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseReinterpretMap.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseReinterpretMap.cpp index f93b59de29e57be67d46339c46bc606cb97afec4..9c0fc60877d8a3cb4f93d678dfb4601d7d10a77b 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseReinterpretMap.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseReinterpretMap.cpp @@ -573,6 +573,12 @@ private: rewriter.modifyOpInPlace(linalgOp, [&]() { linalgOp->setOperand(t->getOperandNumber(), dst); }); + + // Release the transposed form afterwards. + // TODO: CSE when used in more than one following op? + rewriter.setInsertionPointAfter(linalgOp); + rewriter.create<bufferization::DeallocTensorOp>(dst.getLoc(), dst); + return success(); } // Cannot be resolved with a single conversion. @@ -758,9 +764,10 @@ struct ForeachOpDemapper if (numInitArgs != 0) { rewriter.setInsertionPointToEnd(body); auto yield = llvm::cast<YieldOp>(body->getTerminator()); - if (auto stt = tryGetSparseTensorType(yield.getResult()); + if (auto stt = tryGetSparseTensorType(yield.getSingleResult()); stt && !stt->isIdentity()) { - Value y = genDemap(rewriter, stt->getEncoding(), yield.getResult()); + Value y = + genDemap(rewriter, stt->getEncoding(), yield.getSingleResult()); rewriter.create<YieldOp>(loc, y); rewriter.eraseOp(yield); } diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp index 7ff2fc25328a6c2b58cc4fb36322a81902bb1428..5679f277e148660063d6b70a0be38892ec9de0b7 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp @@ -1561,6 +1561,19 @@ struct SparseNewConverter : public OpConversionPattern<NewOp> { } }; +struct SparseHasRuntimeLibraryConverter + : public OpConversionPattern<HasRuntimeLibraryOp> { + using OpConversionPattern::OpConversionPattern; + LogicalResult + matchAndRewrite(HasRuntimeLibraryOp op, OpAdaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + auto i1Type = rewriter.getI1Type(); + rewriter.replaceOpWithNewOp<arith::ConstantOp>( + op, i1Type, rewriter.getIntegerAttr(i1Type, 0)); + return success(); + } +}; + } // namespace //===----------------------------------------------------------------------===// @@ -1572,21 +1585,21 @@ struct SparseNewConverter : public OpConversionPattern<NewOp> { void mlir::populateSparseTensorCodegenPatterns( TypeConverter &typeConverter, RewritePatternSet &patterns, bool createSparseDeallocs, bool enableBufferInitialization) { - patterns.add<SparseAssembleOpConverter, SparseDisassembleOpConverter, - SparseReturnConverter, SparseCallConverter, SparseLvlOpConverter, - SparseCastConverter, SparseExtractSliceConverter, - SparseTensorLoadConverter, SparseExpandConverter, - SparseCompressConverter, SparseInsertConverter, - SparseReorderCOOConverter, SparseReMapConverter, - SparseSliceGetterOpConverter<ToSliceOffsetOp, - StorageSpecifierKind::DimOffset>, - SparseSliceGetterOpConverter<ToSliceStrideOp, - StorageSpecifierKind::DimStride>, - SparseToPositionsConverter, SparseToCoordinatesConverter, - SparseToCoordinatesBufferConverter, SparseToValuesConverter, - SparseConvertConverter, SparseNewConverter, - SparseNumberOfEntriesConverter>(typeConverter, - patterns.getContext()); + patterns.add< + SparseAssembleOpConverter, SparseDisassembleOpConverter, + SparseReturnConverter, SparseCallConverter, SparseLvlOpConverter, + SparseCastConverter, SparseExtractSliceConverter, + SparseTensorLoadConverter, SparseExpandConverter, SparseCompressConverter, + SparseInsertConverter, SparseReorderCOOConverter, SparseReMapConverter, + SparseSliceGetterOpConverter<ToSliceOffsetOp, + StorageSpecifierKind::DimOffset>, + SparseSliceGetterOpConverter<ToSliceStrideOp, + StorageSpecifierKind::DimStride>, + SparseToPositionsConverter, SparseToCoordinatesConverter, + SparseToCoordinatesBufferConverter, SparseToValuesConverter, + SparseConvertConverter, SparseNewConverter, + SparseNumberOfEntriesConverter, SparseHasRuntimeLibraryConverter>( + typeConverter, patterns.getContext()); patterns.add<SparseTensorDeallocConverter>( typeConverter, patterns.getContext(), createSparseDeallocs); patterns.add<SparseTensorAllocConverter, SparseTensorEmptyConverter>( diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorConversion.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorConversion.cpp index 0937c10f257283b1b2a799935f573813bbcbec1e..c52fa3751e6b4a06a1020fe038b17aebb920b340 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorConversion.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorConversion.cpp @@ -275,7 +275,7 @@ static Value genPositionsCall(OpBuilder &builder, Location loc, .getResult(0); } -/// Generates a call to obtain the coordindates array. +/// Generates a call to obtain the coordinates array. static Value genCoordinatesCall(OpBuilder &builder, Location loc, SparseTensorType stt, Value ptr, Level l) { Type crdTp = stt.getCrdType(); @@ -287,6 +287,20 @@ static Value genCoordinatesCall(OpBuilder &builder, Location loc, .getResult(0); } +/// Generates a call to obtain the coordinates array (AoS view). +static Value genCoordinatesBufferCall(OpBuilder &builder, Location loc, + SparseTensorType stt, Value ptr, + Level l) { + Type crdTp = stt.getCrdType(); + auto resTp = MemRefType::get({ShapedType::kDynamic}, crdTp); + Value lvl = constantIndex(builder, loc, l); + SmallString<25> name{"sparseCoordinatesBuffer", + overheadTypeFunctionSuffix(crdTp)}; + return createFuncCall(builder, loc, name, resTp, {ptr, lvl}, + EmitCInterface::On) + .getResult(0); +} + //===----------------------------------------------------------------------===// // Conversion rules. //===----------------------------------------------------------------------===// @@ -518,13 +532,35 @@ public: LogicalResult matchAndRewrite(ToCoordinatesOp op, OpAdaptor adaptor, ConversionPatternRewriter &rewriter) const override { + const Location loc = op.getLoc(); + auto stt = getSparseTensorType(op.getTensor()); + auto crds = genCoordinatesCall(rewriter, loc, stt, adaptor.getTensor(), + op.getLevel()); + // Cast the MemRef type to the type expected by the users, though these + // two types should be compatible at runtime. + if (op.getType() != crds.getType()) + crds = rewriter.create<memref::CastOp>(loc, op.getType(), crds); + rewriter.replaceOp(op, crds); + return success(); + } +}; + +/// Sparse conversion rule for coordinate accesses (AoS style). +class SparseToCoordinatesBufferConverter + : public OpConversionPattern<ToCoordinatesBufferOp> { +public: + using OpConversionPattern::OpConversionPattern; + LogicalResult + matchAndRewrite(ToCoordinatesBufferOp op, OpAdaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + const Location loc = op.getLoc(); auto stt = getSparseTensorType(op.getTensor()); - auto crds = genCoordinatesCall(rewriter, op.getLoc(), stt, - adaptor.getTensor(), op.getLevel()); + auto crds = genCoordinatesBufferCall( + rewriter, loc, stt, adaptor.getTensor(), stt.getAoSCOOStart()); // Cast the MemRef type to the type expected by the users, though these // two types should be compatible at runtime. if (op.getType() != crds.getType()) - crds = rewriter.create<memref::CastOp>(op.getLoc(), op.getType(), crds); + crds = rewriter.create<memref::CastOp>(loc, op.getType(), crds); rewriter.replaceOp(op, crds); return success(); } @@ -840,6 +876,19 @@ public: } }; +struct SparseHasRuntimeLibraryConverter + : public OpConversionPattern<HasRuntimeLibraryOp> { + using OpConversionPattern::OpConversionPattern; + LogicalResult + matchAndRewrite(HasRuntimeLibraryOp op, OpAdaptor adaptor, + ConversionPatternRewriter &rewriter) const override { + auto i1Type = rewriter.getI1Type(); + rewriter.replaceOpWithNewOp<arith::ConstantOp>( + op, i1Type, rewriter.getIntegerAttr(i1Type, 1)); + return success(); + } +}; + } // namespace //===----------------------------------------------------------------------===// @@ -865,9 +914,10 @@ void mlir::populateSparseTensorConversionPatterns(TypeConverter &typeConverter, SparseTensorAllocConverter, SparseTensorEmptyConverter, SparseTensorDeallocConverter, SparseTensorReorderCOOConverter, SparseTensorToPositionsConverter, SparseTensorToCoordinatesConverter, - SparseTensorToValuesConverter, SparseNumberOfEntriesConverter, - SparseTensorLoadConverter, SparseTensorInsertConverter, - SparseTensorExpandConverter, SparseTensorCompressConverter, - SparseTensorAssembleConverter, SparseTensorDisassembleConverter>( + SparseToCoordinatesBufferConverter, SparseTensorToValuesConverter, + SparseNumberOfEntriesConverter, SparseTensorLoadConverter, + SparseTensorInsertConverter, SparseTensorExpandConverter, + SparseTensorCompressConverter, SparseTensorAssembleConverter, + SparseTensorDisassembleConverter, SparseHasRuntimeLibraryConverter>( typeConverter, patterns.getContext()); } diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp index 17f70d0796ccfc3c949f84af4283bc3ea7ea1502..b117c1694e45b8d9ee7617422d7899374023ac96 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp @@ -648,7 +648,9 @@ public: loc, lvl, vector::PrintPunctuation::NoPunctuation); rewriter.create<vector::PrintOp>(loc, rewriter.getStringAttr("] : ")); Value crd = nullptr; - // TODO: eliminates ToCoordinateBufferOp! + // For COO AoS storage, we want to print a single, linear view of + // the full coordinate storage at this level. For any other storage, + // we show the coordinate storage for every indivual level. if (stt.getAoSCOOStart() == l) crd = rewriter.create<ToCoordinatesBufferOp>(loc, tensor); else diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/StageSparseOperations.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/StageSparseOperations.cpp index 5b4395cc31a46bddf4658fefeb1d9b03ecdaeddb..c370d104e09858543028163ef10a647fcc5a49a0 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/StageSparseOperations.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/StageSparseOperations.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "mlir/Dialect/Bufferization/IR/Bufferization.h" +#include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/SparseTensor/IR/SparseTensor.h" #include "mlir/Dialect/SparseTensor/IR/SparseTensorType.h" #include "mlir/Dialect/SparseTensor/Transforms/Passes.h" @@ -16,6 +17,37 @@ using namespace mlir::sparse_tensor; namespace { +struct GuardSparseAlloc + : public OpRewritePattern<bufferization::AllocTensorOp> { + using OpRewritePattern<bufferization::AllocTensorOp>::OpRewritePattern; + + LogicalResult matchAndRewrite(bufferization::AllocTensorOp op, + PatternRewriter &rewriter) const override { + // Only rewrite sparse allocations. + if (!getSparseTensorEncoding(op.getResult().getType())) + return failure(); + + // Only rewrite sparse allocations that escape the method + // without any chance of a finalizing operation in between. + // Here we assume that sparse tensor setup never crosses + // method boundaries. The current rewriting only repairs + // the most obvious allocate-call/return cases. + if (!llvm::all_of(op->getUses(), [](OpOperand &use) { + return isa<func::ReturnOp, func::CallOp, func::CallIndirectOp>( + use.getOwner()); + })) + return failure(); + + // Guard escaping empty sparse tensor allocations with a finalizing + // operation that leaves the underlying storage in a proper state + // before the tensor escapes across the method boundary. + rewriter.setInsertionPointAfter(op); + auto load = rewriter.create<LoadOp>(op.getLoc(), op.getResult(), true); + rewriter.replaceAllUsesExcept(op, load, load); + return success(); + } +}; + template <typename StageWithSortOp> struct StageUnorderedSparseOps : public OpRewritePattern<StageWithSortOp> { using OpRewritePattern<StageWithSortOp>::OpRewritePattern; @@ -37,6 +69,6 @@ struct StageUnorderedSparseOps : public OpRewritePattern<StageWithSortOp> { } // namespace void mlir::populateStageSparseOperationsPatterns(RewritePatternSet &patterns) { - patterns.add<StageUnorderedSparseOps<ConvertOp>, + patterns.add<GuardSparseAlloc, StageUnorderedSparseOps<ConvertOp>, StageUnorderedSparseOps<ConcatenateOp>>(patterns.getContext()); } diff --git a/mlir/lib/Dialect/SparseTensor/Utils/Merger.cpp b/mlir/lib/Dialect/SparseTensor/Utils/Merger.cpp index 72b722c69ae34bb7595f1b84fa88c79b36e269fb..9c0aed3c18eff28f98d5167cdff04c0311ac1d48 100644 --- a/mlir/lib/Dialect/SparseTensor/Utils/Merger.cpp +++ b/mlir/lib/Dialect/SparseTensor/Utils/Merger.cpp @@ -1031,7 +1031,7 @@ LatSetId Merger::buildLattices(ExprId e, LoopId i) { // invariant on the right. Block &absentBlock = absentRegion.front(); YieldOp absentYield = cast<YieldOp>(absentBlock.getTerminator()); - const Value absentVal = absentYield.getResult(); + const Value absentVal = absentYield.getSingleResult(); const ExprId rhs = addInvariantExp(absentVal); return disjSet(e, child0, buildLattices(rhs, i), unop); } @@ -1500,7 +1500,7 @@ static Value insertYieldOp(RewriterBase &rewriter, Location loc, Region ®ion, // Merge cloned block and return yield value. Operation *placeholder = rewriter.create<arith::ConstantIndexOp>(loc, 0); rewriter.inlineBlockBefore(&tmpRegion.front(), placeholder, vals); - Value val = clonedYield.getResult(); + Value val = clonedYield.getSingleResult(); rewriter.eraseOp(clonedYield); rewriter.eraseOp(placeholder); return val; diff --git a/mlir/lib/Dialect/Tensor/IR/TensorDialect.cpp b/mlir/lib/Dialect/Tensor/IR/TensorDialect.cpp index 62032ff301bece2f2e155e9ddae0eeda26bc2ce5..002077753b132417ad20ba21931485c621b0230a 100644 --- a/mlir/lib/Dialect/Tensor/IR/TensorDialect.cpp +++ b/mlir/lib/Dialect/Tensor/IR/TensorDialect.cpp @@ -8,8 +8,11 @@ #include "mlir/Dialect/Affine/IR/AffineOps.h" #include "mlir/Dialect/Arith/IR/Arith.h" +#include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h" #include "mlir/Dialect/Complex/IR/Complex.h" #include "mlir/Dialect/Tensor/IR/Tensor.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" +#include "mlir/Interfaces/SubsetOpInterface.h" #include "mlir/Transforms/InliningUtils.h" using namespace mlir; @@ -45,4 +48,22 @@ void TensorDialect::initialize() { #include "mlir/Dialect/Tensor/IR/TensorOps.cpp.inc" >(); addInterfaces<TensorInlinerInterface>(); + declarePromisedInterfaces< + bufferization::BufferizableOpInterface, CastOp, CollapseShapeOp, DimOp, + EmptyOp, ExpandShapeOp, ExtractSliceOp, ExtractOp, FromElementsOp, + GenerateOp, InsertOp, InsertSliceOp, PadOp, ParallelInsertSliceOp, RankOp, + ReshapeOp, SplatOp>(); + declarePromisedInterfaces<transform::FindPayloadReplacementOpInterface, + CollapseShapeOp, ExpandShapeOp, ExtractSliceOp, + InsertSliceOp, ReshapeOp>(); + declarePromisedInterfaces<ReifyRankedShapedTypeOpInterface, ExpandShapeOp, + CollapseShapeOp, PadOp>(); + declarePromisedInterfaces<SubsetOpInterface, ExtractSliceOp, InsertSliceOp, + ParallelInsertSliceOp>(); + declarePromisedInterfaces<SubsetInsertionOpInterface, InsertSliceOp, + ParallelInsertSliceOp>(); + declarePromisedInterface<SubsetExtractionOpInterface, ExtractSliceOp>(); + declarePromisedInterfaces<TilingInterface, PadOp, PackOp, UnPackOp>(); + declarePromisedInterfaces<ValueBoundsOpInterface, CastOp, DimOp, EmptyOp, + ExtractSliceOp, PadOp, RankOp>(); } diff --git a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp index dc8843aa4e1e13dc7f980f61d290c440a2da7c57..0ce40e813712098fbd33df164a1737fed0c50baa 100644 --- a/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp +++ b/mlir/lib/Dialect/Tensor/IR/TensorOps.cpp @@ -276,6 +276,10 @@ bool mlir::tensor::preservesStaticInformation(Type source, Type target) { if (sourceType.getRank() != targetType.getRank()) return false; + // Requires same encoding. + if (sourceType.getEncoding() != targetType.getEncoding()) + return false; + // If cast is towards more static sizes along any dimension, don't fold. for (auto t : llvm::zip(sourceType.getShape(), targetType.getShape())) { if (!ShapedType::isDynamic(std::get<0>(t)) && @@ -1064,10 +1068,13 @@ void EmptyOp::getCanonicalizationPatterns(RewritePatternSet &results, /// Try to remove a tensor operation if it would only reshape a constant. /// Removes the op and replaces the constant with a new constant of the result -/// shape. -static OpFoldResult reshapeConstantSource(DenseElementsAttr source, - TensorType result) { - if (source && source.isSplat() && result.hasStaticShape()) +/// shape. When an optional cst attribute is passed, it is reshaped only if the +/// splat value matches the value in the attribute. +static OpFoldResult +reshapeConstantSource(DenseElementsAttr source, TensorType result, + std::optional<Attribute> cst = std::nullopt) { + if (source && source.isSplat() && result.hasStaticShape() && + (!cst.has_value() || source.getSplatValue<Attribute>() == cst.value())) return source.resizeSplat(result); return {}; @@ -4139,9 +4146,12 @@ bool PackOp::isLikePad() { } OpFoldResult PackOp::fold(FoldAdaptor adaptor) { + std::optional<Attribute> paddingValue; + if (auto pad = adaptor.getPaddingValue()) + paddingValue = pad; if (OpFoldResult reshapedSource = reshapeConstantSource( llvm::dyn_cast_if_present<DenseElementsAttr>(adaptor.getSource()), - getResult().getType())) + getDestType(), paddingValue)) return reshapedSource; return {}; } diff --git a/mlir/lib/Dialect/Tensor/TransformOps/TensorTransformOps.cpp b/mlir/lib/Dialect/Tensor/TransformOps/TensorTransformOps.cpp index 38f1824a3634a3542cede13d892084f1afaaee8c..5c6a32ce9a68d60edd812c1395d9341db710b91d 100644 --- a/mlir/lib/Dialect/Tensor/TransformOps/TensorTransformOps.cpp +++ b/mlir/lib/Dialect/Tensor/TransformOps/TensorTransformOps.cpp @@ -14,7 +14,7 @@ #include "mlir/Dialect/Tensor/Transforms/Transforms.h" #include "mlir/Dialect/Tensor/Utils/Utils.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/Builders.h" #include "mlir/Transforms/DialectConversion.h" diff --git a/mlir/lib/Dialect/Tensor/Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp b/mlir/lib/Dialect/Tensor/Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp index 5257310f5b005b9c715fd64b65aad3faece28b99..ff003e486d21c87c665462deafd1b7c8c7a947b9 100644 --- a/mlir/lib/Dialect/Tensor/Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp +++ b/mlir/lib/Dialect/Tensor/Transforms/MergeConsecutiveInsertExtractSlicePatterns.cpp @@ -78,12 +78,12 @@ struct MergeConsecutiveInsertSlice : public OpRewritePattern<OpTy> { } }; -/// Drop redundant rank expansion. I.e., rank expansions that are directly -/// followed by rank reductions. E.g.: +/// Drop redundant rank expansion of insert_slice that are directly followed +/// by extract_slice. E.g.: /// %0 = tensor.insert_slice ... : tensor<5x10xf32> into tensor<1x1x5x10xf32> /// %1 = tensor.extract_slice %0[0, 0, 2, 3] [1, 1, 2, 2] [1, 1, 1, 1] /// : tensor<1x1x5x10xf32> to tensor<2x2xf32> -struct DropRedundantInsertSliceRankExpansion +struct DropRedundantRankExpansionOnExtractSliceOfInsertSlice : public OpRewritePattern<ExtractSliceOp> { using OpRewritePattern::OpRewritePattern; @@ -134,6 +134,97 @@ struct DropRedundantInsertSliceRankExpansion return success(); } }; + +/// Drop redundant rank expansion of insert_slice that direclty follows +/// extract_slice. +/// +/// This can be done when the insert_slice op purely expands ranks (adds unit +/// dims) and the extrace_slice drops corresponding unit dims. For example: +/// +/// %extracted_slice = tensor.extract_slice %in[0, 0] [1, 8] [1, 1] +/// : tensor<2x8xf32> to tensor<8xf32> +/// %inserted_slice = tensor.insert_slice %extracted_slice +/// into %dest[0, 0] [1, 8] [1, 1] +/// : tensor<8xf32> into tensor<1x8xf32> +/// +/// can be folded into: +/// +/// %extracted_slice = tensor.extract_slice %in[0, 0] [1, 8] [1, 1] +/// : tensor<2x8xf32> to tensor<1x8xf32> +struct DropRedundantRankExpansionOnInsertSliceOfExtractSlice final + : public OpRewritePattern<tensor::InsertSliceOp> { + using OpRewritePattern<tensor::InsertSliceOp>::OpRewritePattern; + + LogicalResult matchAndRewrite(tensor::InsertSliceOp insertSliceOp, + PatternRewriter &rewriter) const override { + auto extractSliceOp = + insertSliceOp.getSource().getDefiningOp<tensor::ExtractSliceOp>(); + if (!extractSliceOp) { + return rewriter.notifyMatchFailure(insertSliceOp, + "source is not extract_slice"); + } + + // Can't fold if the extract_slice op has other users. + if (!extractSliceOp->hasOneUse()) { + return rewriter.notifyMatchFailure(insertSliceOp, + "source has multi-uses"); + } + + // Check if the insert_slice op purely expands ranks (add unit dims). + if (!isCastLikeInsertSliceOp(insertSliceOp)) { + return rewriter.notifyMatchFailure(insertSliceOp, + "insert_slice is not cast-like"); + } + + llvm::SmallBitVector extractDroppedDims = extractSliceOp.getDroppedDims(); + llvm::SmallBitVector insertDroppedDims = insertSliceOp.getDroppedDims(); + // Can't fold if the insert_slice op expands to more dims. + if (extractDroppedDims.size() < insertDroppedDims.size()) { + return rewriter.notifyMatchFailure(insertSliceOp, + "insert_slice expands more dims"); + } + + // Try to match the extract dropped dims to the insert dropped dims. This is + // done by scanning the dims of extract_slice and find the left-most one can + // match the dim of insert_slice. If a match is found, advance the dim of + // insert_slice to match the next one. + unsigned insertDimPos = 0; + for (unsigned extractDimPos = 0; extractDimPos < extractDroppedDims.size(); + ++extractDimPos) { + // Matched all dims. + if (insertDimPos == insertDroppedDims.size()) + break; + + bool isExtractDropped = extractDroppedDims[extractDimPos]; + bool isInsertDropped = insertDroppedDims[insertDimPos]; + // Match if both sides drop/keep the dim. Advance and match the next dim + // of insert_slice. + if (isExtractDropped == isInsertDropped) { + insertDimPos += 1; + } else if (!isExtractDropped && isInsertDropped) { + // Not enough extract dropped dims to match the insert dropped dims. + return rewriter.notifyMatchFailure(insertSliceOp, + "insert_slice drops more unit dims"); + } + // If the dim is dropped by extract_slice and not by insert_slice, look + // the next dim of extract_slice to see if it can match the current dim of + // insert_slice. + } + // Can't match some insert dims. + if (insertDimPos != insertDroppedDims.size()) { + return rewriter.notifyMatchFailure(insertSliceOp, + "insert_slice has unmatched dims"); + } + + rewriter.replaceOpWithNewOp<tensor::ExtractSliceOp>( + insertSliceOp, insertSliceOp.getType(), extractSliceOp.getSource(), + extractSliceOp.getMixedOffsets(), extractSliceOp.getMixedSizes(), + extractSliceOp.getMixedStrides()); + rewriter.eraseOp(extractSliceOp); + + return success(); + } +}; } // namespace void mlir::tensor::populateMergeConsecutiveInsertExtractSlicePatterns( @@ -146,5 +237,7 @@ void mlir::tensor::populateMergeConsecutiveInsertExtractSlicePatterns( void mlir::tensor::populateDropRedundantInsertSliceRankExpansionPatterns( RewritePatternSet &patterns) { - patterns.add<DropRedundantInsertSliceRankExpansion>(patterns.getContext()); + patterns.add<DropRedundantRankExpansionOnExtractSliceOfInsertSlice, + DropRedundantRankExpansionOnInsertSliceOfExtractSlice>( + patterns.getContext()); } diff --git a/mlir/lib/Dialect/Tensor/Transforms/PackAndUnpackPatterns.cpp b/mlir/lib/Dialect/Tensor/Transforms/PackAndUnpackPatterns.cpp index 55fd387496690a21697f7055726af6b11d2a744b..666ac56c6cd5cd87be606a96c619222de7ea23c3 100644 --- a/mlir/lib/Dialect/Tensor/Transforms/PackAndUnpackPatterns.cpp +++ b/mlir/lib/Dialect/Tensor/Transforms/PackAndUnpackPatterns.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/Tensor/Transforms/Transforms.h" #include "mlir/Dialect/Utils/IndexingUtils.h" #include "mlir/IR/PatternMatch.h" -#include "llvm/Support/Debug.h" namespace mlir { namespace tensor { @@ -224,6 +223,33 @@ struct FoldUnpackWithExtractSliceOp : public OpRewritePattern<ExtractSliceOp> { } }; +// Applies 'permutation' on 'inVec' and stores the result in resVec. +// 'inVec' may be empty, in that case it's one-to-one mapping with permutation. +// `rank` sets the boundary for permutation i.e., the permutation dim can't be +// greater than the rank specified. If it's so then return false. +// For e.g., permutation {1, 0, 3, 2} with rank 2 is allowed since the values in +// permutation[:rank] doesn't exceed rank, whereas, permutation {1, 3, 0, 2} is +// not allowed since `3` exceeds the value of the rank in the given range. +static bool checkAndPermute(ArrayRef<int64_t> permutation, + ArrayRef<int64_t> inVec, + SmallVectorImpl<int64_t> &resVec, int64_t rank) { + + for (unsigned int i = 0; i < rank; ++i) { + int64_t remappedPosition = permutation[i]; + + if (!inVec.empty()) { + if (remappedPosition >= rank) { + return false; + } + remappedPosition = inVec[remappedPosition]; + } + + resVec.push_back(remappedPosition); + } + + return true; +} + /// Fold 'pack' -> 'transpose' into 'pack' since 'pack' already has transpose /// semantics. struct FoldProducerPackWithConsumerLinalgTransposeOp @@ -246,24 +272,12 @@ struct FoldProducerPackWithConsumerLinalgTransposeOp SmallVector<OpFoldResult> newMixedInnerTilesVec; int64_t srcRank = packOp.getSourceRank(); - // Process transpose operation for non-tiled outer dimensions - for (unsigned int i = 0; i < srcRank; ++i) { - int64_t remappedPosition = transposePerm[i]; - - // If tensor.pack has outer_dims_perm attribute, then consider it during - // index remapping. - if (!outerDimsPerm.empty()) { - if (transposePerm[i] >= srcRank) { - return rewriter.notifyMatchFailure( - transposeOp, - "Cannot fold in tensor.pack if a tile dimension was transposed " - "with a non-tile dimension in linalg.transpose."); - } - remappedPosition = outerDimsPerm[remappedPosition]; - } - - newOuterDimsPermVec.push_back(remappedPosition); - } + if (!checkAndPermute(transposePerm, outerDimsPerm, newOuterDimsPermVec, + srcRank)) + return rewriter.notifyMatchFailure( + transposeOp, + "Cannot fold in tensor.pack if a tile dimension was transposed " + "with a non-tile dimension in linalg.transpose."); // Process transpose operation for tiled inner dimensions for (unsigned int i = srcRank; i < transposePerm.size(); ++i) { @@ -323,12 +337,103 @@ struct FoldConsumerPackWithProducerLinalgTransposeOp return success(); } }; + +/// Fold 'unpack' -> 'transpose' into 'unpack' since 'unpack' already has +/// transpose semantics. +struct FoldProducerUnPackWithConsumerLinalgTransposeOp + : public OpRewritePattern<linalg::TransposeOp> { + using OpRewritePattern<linalg::TransposeOp>::OpRewritePattern; + + LogicalResult matchAndRewrite(linalg::TransposeOp transposeOp, + PatternRewriter &rewriter) const override { + auto unPackOp = transposeOp.getOperand(0).getDefiningOp<UnPackOp>(); + + if (!unPackOp) + return failure(); + + auto transposePermutation = transposeOp.getPermutation(); + auto outerDimsPerm = unPackOp.getOuterDimsPerm(); + auto innerDimsPos = unPackOp.getInnerDimsPos(); + SmallVector<int64_t> newInnerDimsPosVec; + SmallVector<int64_t> newOuterDimsPermVec = + llvm::to_vector(transposePermutation); + + if (!outerDimsPerm.empty()) + applyPermutationToVector(newOuterDimsPermVec, outerDimsPerm); + + // Can't use applyPermutationToVector for newInnerDimsPosVec since input and + // permutation rank won't necessarily be equal in all cases. + for (auto dim : innerDimsPos) + newInnerDimsPosVec.push_back(transposePermutation[dim]); + + Value output = unPackOp.createDestinationTensor( + rewriter, transposeOp.getLoc(), unPackOp.getSource(), + unPackOp.getMixedTiles(), newInnerDimsPosVec, newOuterDimsPermVec); + + rewriter.replaceOpWithNewOp<UnPackOp>( + transposeOp, unPackOp.getSource(), output, newInnerDimsPosVec, + unPackOp.getMixedTiles(), newOuterDimsPermVec); + + return success(); + } +}; + +/// Fold 'transpose' -> 'unpack' into 'unpack' since 'unpack' already has +/// transpose semantics. +struct FoldConsumerUnPackWithProducerLinalgTransposeOp + : public OpRewritePattern<UnPackOp> { + using OpRewritePattern<UnPackOp>::OpRewritePattern; + + LogicalResult matchAndRewrite(UnPackOp unPackOp, + PatternRewriter &rewriter) const override { + auto transposeOp = + unPackOp.getSource().getDefiningOp<linalg::TransposeOp>(); + + if (!transposeOp) + return failure(); + + auto transposePermutation = transposeOp.getPermutation(); + auto outerDimsPerm = unPackOp.getOuterDimsPerm(); + auto innerDimsPos = unPackOp.getInnerDimsPos(); + int64_t destRank = unPackOp.getSourceRank() - innerDimsPos.size(); + auto mixedInnerTilesVec = unPackOp.getMixedTiles(); + SmallVector<int64_t> newOuterDimsPermVec; + SmallVector<int64_t> newInnerDimsPosVec; + SmallVector<OpFoldResult> newMixedInnerTilesVec; + + if (!checkAndPermute(transposePermutation, outerDimsPerm, + newOuterDimsPermVec, destRank)) + return rewriter.notifyMatchFailure( + unPackOp, + "Cannot fold in tensor.unpack if a tile dimension was transposed " + "with a non-tile dimension in linalg.transpose."); + + // Process transpose operation for tiled inner dimensions + for (unsigned int i = destRank; i < transposePermutation.size(); ++i) { + int64_t remappedPosition = transposePermutation[i] - destRank; + newMixedInnerTilesVec.push_back(mixedInnerTilesVec[remappedPosition]); + newInnerDimsPosVec.push_back(innerDimsPos[remappedPosition]); + } + + Value output = unPackOp.createDestinationTensor( + rewriter, unPackOp.getLoc(), transposeOp.getOperand(0), + newMixedInnerTilesVec, newInnerDimsPosVec, newOuterDimsPermVec); + + rewriter.replaceOpWithNewOp<UnPackOp>( + unPackOp, transposeOp.getOperand(0), output, newInnerDimsPosVec, + newMixedInnerTilesVec, newOuterDimsPermVec); + + return success(); + } +}; } // namespace void populateFoldIntoPackAndUnpackPatterns(RewritePatternSet &patterns) { patterns.insert<FoldUnpackWithExtractSliceOp, FoldPadWithPackOp, FoldProducerPackWithConsumerLinalgTransposeOp, - FoldConsumerPackWithProducerLinalgTransposeOp>( + FoldConsumerPackWithProducerLinalgTransposeOp, + FoldConsumerUnPackWithProducerLinalgTransposeOp, + FoldProducerUnPackWithConsumerLinalgTransposeOp>( patterns.getContext()); } diff --git a/mlir/lib/Dialect/Tensor/Utils/Utils.cpp b/mlir/lib/Dialect/Tensor/Utils/Utils.cpp index 186f85d2ce20a62b873aca31aab1fc83bea347eb..2dd91e2f7a17003e2700435e6eadd655a604d1c3 100644 --- a/mlir/lib/Dialect/Tensor/Utils/Utils.cpp +++ b/mlir/lib/Dialect/Tensor/Utils/Utils.cpp @@ -142,11 +142,15 @@ mlir::tensor::getUnPackInverseSrcPerm(UnPackOp unpackOp, bool mlir::tensor::isCastLikeInsertSliceOp(InsertSliceOp op) { llvm::SmallBitVector droppedDims = op.getDroppedDims(); int64_t srcDim = 0; + RankedTensorType resultType = op.getDestType(); // Source dims and destination dims (apart from dropped dims) must have the // same size. - for (int64_t resultDim = 0; resultDim < op.getDestType().getRank(); - ++resultDim) { + for (int64_t resultDim = 0; resultDim < resultType.getRank(); ++resultDim) { if (droppedDims.test(resultDim)) { + // InsertSlice may expand unit dimensions that result from inserting a + // size-1 slice into a non-size-1 result dimension. + if (resultType.getDimSize(resultDim) != 1) + return false; continue; } FailureOr<bool> equalDimSize = ValueBoundsConstraintSet::areEqual( diff --git a/mlir/lib/Dialect/Tosa/CMakeLists.txt b/mlir/lib/Dialect/Tosa/CMakeLists.txt index ba5343dcd7ac6c17f8e9c5be20ae0a55fa3e352c..1911405c63cd5820999fbfff267537090c804199 100644 --- a/mlir/lib/Dialect/Tosa/CMakeLists.txt +++ b/mlir/lib/Dialect/Tosa/CMakeLists.txt @@ -12,6 +12,7 @@ add_mlir_dialect_library(MLIRTosaDialect MLIRTosaDialectBytecodeIncGen MLIRTosaOpsIncGen MLIRTosaInterfacesIncGen + MLIRShardingInterfaceIncGen LINK_LIBS PUBLIC MLIRIR diff --git a/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp b/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp index 4c50aaecfe9488f79b04d077a1a61623c47a116e..d23c9fe824c94af5b95abc142976268c5cbd1fea 100644 --- a/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp +++ b/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp @@ -795,7 +795,10 @@ OpFoldResult ReshapeOp::fold(FoldAdaptor adaptor) { if (!inputTy || !outputTy) return {}; - if (inputTy == outputTy) + // Fold when the input and output types are the same. This is only safe when + // there is at most 1 dynamic dimension. For 2 or more dynamic dimensions, + // there may still be a productive reshape. + if (inputTy == outputTy && inputTy.getNumDynamicDims() < 2) return getInput1(); // reshape(reshape(x)) -> reshape(x) diff --git a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp index 62d07859e32f6ecff4b6827423889f5813b66563..6e6e843507381225023e30375a069693039666f5 100644 --- a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp +++ b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "mlir/Dialect/Tosa/IR/TosaOps.h" +#include "mlir/Dialect/Mesh/Interfaces/ShardingInterface.h" #include "mlir/Dialect/Quant/QuantOps.h" #include "mlir/Dialect/Tensor/IR/Tensor.h" #include "mlir/Dialect/Tosa/Utils/QuantUtils.h" @@ -136,6 +137,14 @@ void TosaDialect::initialize() { #include "mlir/Dialect/Tosa/IR/TosaAttributes.cpp.inc" >(); addInterfaces<TosaDialectBytecodeInterface, TosaInlinerInterface>(); + declarePromisedInterfaces< + mesh::ShardingInterface, ClampOp, SigmoidOp, TanhOp, AddOp, + ArithmeticRightShiftOp, BitwiseAndOp, BitwiseOrOp, BitwiseXorOp, DivOp, + LogicalAndOp, LogicalLeftShiftOp, LogicalRightShiftOp, LogicalOrOp, + LogicalXorOp, MaximumOp, MinimumOp, MulOp, PowOp, SubOp, AbsOp, + BitwiseNotOp, CeilOp, ClzOp, ExpOp, FloorOp, LogOp, LogicalNotOp, + NegateOp, ReciprocalOp, RsqrtOp, SelectOp, EqualOp, GreaterOp, + GreaterEqualOp, MatMulOp>(); } Operation *TosaDialect::materializeConstant(OpBuilder &builder, Attribute value, @@ -961,6 +970,11 @@ mlir::LogicalResult tosa::ReshapeOp::verify() { << " elements into " << outputElementsNum; } } + + int missingDims = llvm::count(getNewShape(), -1); + if (missingDims > 1) + return emitOpError() << "At most one target dimension can be -1"; + return mlir::success(); } diff --git a/mlir/lib/Dialect/Tosa/Transforms/TosaFolders.cpp b/mlir/lib/Dialect/Tosa/Transforms/TosaFolders.cpp index 050f8ca3f32aeda867caf888bb3b691e0afcfa98..6575b39fd45a1f8f1d62aadb590e7e5dd370ddb6 100644 --- a/mlir/lib/Dialect/Tosa/Transforms/TosaFolders.cpp +++ b/mlir/lib/Dialect/Tosa/Transforms/TosaFolders.cpp @@ -132,14 +132,17 @@ bool constantUnaryOpShouldBeFolded(TosaOp unaryOp, DenseElementsAttr values) { return inputOp.hasOneUse(); } -template <typename BaseType> -DenseElementsAttr transposeType(ElementsAttr attr, ShapedType inputType, +template <typename RangeType> +DenseElementsAttr transposeType(const RangeType &data, ShapedType inputType, ShapedType outputType, llvm::ArrayRef<int64_t> permValues) { + using ElementType = std::decay_t<decltype(*std::begin(data))>; + + assert(inputType.getElementType() == outputType.getElementType()); + if (inputType.getNumElements() == 0) - return DenseElementsAttr::get(outputType, llvm::ArrayRef<BaseType>{}); + return DenseElementsAttr::get(outputType, llvm::ArrayRef<ElementType>{}); - auto attrValues = attr.getValues<BaseType>(); auto inputShape = inputType.getShape(); // The inverted permutation map and strides of the output are used to compute @@ -148,10 +151,11 @@ DenseElementsAttr transposeType(ElementsAttr attr, ShapedType inputType, auto outputStrides = computeStrides(outputType.getShape()); auto invertedPermValues = invertPermutationVector(permValues); - auto initialValue = *std::begin(attrValues); - SmallVector<BaseType> outputValues(inputType.getNumElements(), initialValue); + auto initialValue = *std::begin(data); + SmallVector<ElementType> outputValues(inputType.getNumElements(), + initialValue); - for (const auto &it : llvm::enumerate(attrValues)) { + for (const auto &it : llvm::enumerate(data)) { auto srcLinearIndex = it.index(); uint64_t dstLinearIndex = 0; @@ -170,7 +174,7 @@ DenseElementsAttr transposeType(ElementsAttr attr, ShapedType inputType, } return DenseElementsAttr::get(outputType, - llvm::ArrayRef<BaseType>(outputValues)); + llvm::ArrayRef<ElementType>(outputValues)); } // A type specialized transposition of an ElementsAttr. @@ -180,32 +184,28 @@ DenseElementsAttr transposeType(ElementsAttr attr, ShapedType inputType, DenseElementsAttr transpose(ElementsAttr attr, ShapedType inputType, ShapedType outputType, llvm::ArrayRef<int64_t> permValues) { - auto baseType = inputType.getElementType(); - - // Handle possible integer types - if (auto intType = dyn_cast<IntegerType>(baseType)) { - switch (intType.getWidth()) { - case 1: - return transposeType<bool>(attr, inputType, outputType, permValues); - case 8: - return transposeType<int8_t>(attr, inputType, outputType, permValues); - case 16: - return transposeType<int16_t>(attr, inputType, outputType, permValues); - case 32: - return transposeType<int32_t>(attr, inputType, outputType, permValues); - case 64: - return transposeType<int64_t>(attr, inputType, outputType, permValues); - default: - return transposeType<APInt>(attr, inputType, outputType, permValues); - } - } + if (auto data = attr.tryGetValues<bool>()) + return transposeType(*data, inputType, outputType, permValues); - // Handle possible float types - if (baseType.isF32()) { - return transposeType<float>(attr, inputType, outputType, permValues); - } + if (auto data = attr.tryGetValues<int8_t>()) + return transposeType(*data, inputType, outputType, permValues); + + if (auto data = attr.tryGetValues<int16_t>()) + return transposeType(*data, inputType, outputType, permValues); + + if (auto data = attr.tryGetValues<int32_t>()) + return transposeType(*data, inputType, outputType, permValues); - return transposeType<APFloat>(attr, inputType, outputType, permValues); + if (auto data = attr.tryGetValues<int64_t>()) + return transposeType(*data, inputType, outputType, permValues); + + if (auto data = attr.tryGetValues<float>()) + return transposeType(*data, inputType, outputType, permValues); + + if (auto data = attr.tryGetValues<APFloat>()) + return transposeType(*data, inputType, outputType, permValues); + + return nullptr; } struct TosaFoldConstantTranspose : public OpRewritePattern<tosa::TransposeOp> { @@ -228,14 +228,19 @@ struct TosaFoldConstantTranspose : public OpRewritePattern<tosa::TransposeOp> { DenseIntElementsAttr permAttr; if (!matchPattern(op.getPerms(), m_Constant(&permAttr))) return failure(); - auto permValues = llvm::to_vector<6>(llvm::map_range( + auto permValues = llvm::map_to_vector( // TOSA allows both 32- and 64-bit integer tensors here. permAttr.getValues<APInt>(), - [](const APInt &val) { return val.getSExtValue(); })); + [](const APInt &val) { return val.getSExtValue(); }); auto inputType = cast<ShapedType>(op.getInput1().getType()); auto resultAttr = transpose(inputValues, inputType, outputType, permValues); + if (!resultAttr) { + return rewriter.notifyMatchFailure( + op, "unsupported attribute or element type"); + } + rewriter.replaceOpWithNewOp<tosa::ConstOp>(op, outputType, resultAttr); return success(); } diff --git a/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp b/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp index 967775281ad91f7c872831817e03370b2a0911ce..74ef6381f3d70148c750704e76d9ee5141a00224 100644 --- a/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp +++ b/mlir/lib/Dialect/Tosa/Transforms/TosaValidation.cpp @@ -410,6 +410,8 @@ private: bool CheckVariable(Operation *op); bool CheckVariableReadOrWrite(Operation *op); + bool isValidElementType(Type type); + SmallVector<std::function<LogicalResult(Operation *)>> constCheckers; TosaLevel tosaLevel; DenseMap<StringAttr, mlir::Type> variablesMap; @@ -503,15 +505,58 @@ LogicalResult TosaValidation::applyVariableCheck(Operation *op) { return success(); } +bool TosaValidation::isValidElementType(Type type) { + if ((profile == TosaProfileEnum::BaseInference) && isa<FloatType>(type)) { + return false; + } + if (type.isF64()) { + return false; + } + if (auto intTy = dyn_cast<IntegerType>(type)) { + if (intTy.isUnsigned()) { + switch (intTy.getWidth()) { + case 8: + case 16: + return true; + default: + return false; + } + } else { + // Signless - treated as signed. + switch (intTy.getWidth()) { + case 1: + case 4: + case 8: + case 16: + case 32: + case 48: + case 64: + return true; + default: + return false; + } + } + return false; + } + return true; +} + void TosaValidation::runOnOperation() { configLevelAndProfile(); getOperation().walk([&](Operation *op) { for (Value operand : op->getOperands()) { - if ((profile == TosaProfileEnum::BaseInference) && - isa<FloatType>(getElementTypeOrSelf(operand))) { + auto elementTy = getElementTypeOrSelf(operand); + if (!isValidElementType(elementTy)) { + op->emitOpError() << "is not profile-aligned: element type " + << elementTy << " is not legal"; return signalPassFailure(); } - if (getElementTypeOrSelf(operand).isF64()) { + } + for (Type resultTy : op->getResultTypes()) { + auto elementTy = getElementTypeOrSelf(resultTy); + if (!isValidElementType(elementTy)) { + op->emitOpError() << "is not profile-aligned: element type " + << elementTy << " is not legal"; return signalPassFailure(); } } diff --git a/mlir/lib/Dialect/Traits.cpp b/mlir/lib/Dialect/Traits.cpp index d4e0f8a3137053c4c639ef8e8f7ac0ae4a446398..2efc157ce79617b8fbe216f8f4af2b79b23a6d35 100644 --- a/mlir/lib/Dialect/Traits.cpp +++ b/mlir/lib/Dialect/Traits.cpp @@ -188,9 +188,8 @@ Type OpTrait::util::getBroadcastedType(Type type1, Type type2, /// Returns a tuple corresponding to whether range has tensor or vector type. template <typename iterator_range> static std::tuple<bool, bool> hasTensorOrVectorType(iterator_range types) { - return std::make_tuple( - llvm::any_of(types, [](Type t) { return isa<TensorType>(t); }), - llvm::any_of(types, [](Type t) { return isa<VectorType>(t); })); + return {llvm::any_of(types, llvm::IsaPred<TensorType>), + llvm::any_of(types, llvm::IsaPred<VectorType>)}; } static bool isCompatibleInferredReturnShape(ArrayRef<int64_t> inferred, @@ -202,7 +201,7 @@ static bool isCompatibleInferredReturnShape(ArrayRef<int64_t> inferred, }; if (inferred.size() != existing.size()) return false; - for (auto [inferredDim, existingDim] : llvm::zip(inferred, existing)) + for (auto [inferredDim, existingDim] : llvm::zip_equal(inferred, existing)) if (!isCompatible(inferredDim, existingDim)) return false; return true; @@ -238,8 +237,8 @@ LogicalResult OpTrait::impl::verifyCompatibleOperandBroadcast(Operation *op) { std::get<1>(resultsHasTensorVectorType))) return op->emitError("cannot broadcast vector with tensor"); - auto rankedOperands = make_filter_range( - op->getOperandTypes(), [](Type t) { return isa<RankedTensorType>(t); }); + auto rankedOperands = + make_filter_range(op->getOperandTypes(), llvm::IsaPred<RankedTensorType>); // If all operands are unranked, then all result shapes are possible. if (rankedOperands.empty()) @@ -257,8 +256,8 @@ LogicalResult OpTrait::impl::verifyCompatibleOperandBroadcast(Operation *op) { return op->emitOpError("operands don't have broadcast-compatible shapes"); } - auto rankedResults = make_filter_range( - op->getResultTypes(), [](Type t) { return isa<RankedTensorType>(t); }); + auto rankedResults = + make_filter_range(op->getResultTypes(), llvm::IsaPred<RankedTensorType>); // If all of the results are unranked then no further verification. if (rankedResults.empty()) diff --git a/mlir/lib/Dialect/Transform/CMakeLists.txt b/mlir/lib/Dialect/Transform/CMakeLists.txt index ed05194b72990be1a0928021f390173c06e70838..64115dcc29d639d2a2b14d6420899fcb73e43d43 100644 --- a/mlir/lib/Dialect/Transform/CMakeLists.txt +++ b/mlir/lib/Dialect/Transform/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(DebugExtension) +add_subdirectory(Interfaces) add_subdirectory(IR) add_subdirectory(LoopExtension) add_subdirectory(PDLExtension) diff --git a/mlir/lib/Dialect/Transform/IR/CMakeLists.txt b/mlir/lib/Dialect/Transform/IR/CMakeLists.txt index 34083b2fd7aab373fc2be4d33cd51de166d1d90e..5b4989f328e6909d7d9145d3ff8c4b49b3afc182 100644 --- a/mlir/lib/Dialect/Transform/IR/CMakeLists.txt +++ b/mlir/lib/Dialect/Transform/IR/CMakeLists.txt @@ -1,17 +1,10 @@ add_mlir_dialect_library(MLIRTransformDialect - MatchInterfaces.cpp TransformAttrs.cpp TransformDialect.cpp - TransformInterfaces.cpp TransformOps.cpp TransformTypes.cpp Utils.cpp - DEPENDS - MLIRMatchInterfacesIncGen - MLIRTransformDialectIncGen - MLIRTransformInterfacesIncGen - LINK_LIBS PUBLIC MLIRCastInterfaces MLIRFunctionInterfaces @@ -24,5 +17,6 @@ add_mlir_dialect_library(MLIRTransformDialect MLIRRewrite MLIRSideEffectInterfaces MLIRTransforms + MLIRTransformDialectInterfaces MLIRTransformDialectUtils ) diff --git a/mlir/lib/Dialect/Transform/IR/TransformDialect.cpp b/mlir/lib/Dialect/Transform/IR/TransformDialect.cpp index fb355bc97192682f8910748fd98131cf2bab1fa6..e628430ff861eda3c3aa2b2740967e2b0388cfbc 100644 --- a/mlir/lib/Dialect/Transform/IR/TransformDialect.cpp +++ b/mlir/lib/Dialect/Transform/IR/TransformDialect.cpp @@ -8,10 +8,10 @@ #include "mlir/Dialect/Transform/IR/TransformDialect.h" #include "mlir/Analysis/CallGraph.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformOps.h" #include "mlir/Dialect/Transform/IR/TransformTypes.h" #include "mlir/Dialect/Transform/IR/Utils.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/DialectImplementation.h" #include "llvm/ADT/SCCIterator.h" @@ -178,7 +178,8 @@ LogicalResult transform::TransformDialect::verifyOperationAttribute( } return success(); } - if (attribute.getName().getValue() == kSilenceTrackingFailuresAttrName) { + if (attribute.getName().getValue() == + FindPayloadReplacementOpInterface::kSilenceTrackingFailuresAttrName) { if (!llvm::isa<UnitAttr>(attribute.getValue())) { return op->emitError() << attribute.getName() << " must be a unit attribute"; diff --git a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp index ca80899ab0734183705be8d1f4fd8b9b2256d606..dc19022219e5b240fd01f4c7b7760c7aee6117d9 100644 --- a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp +++ b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp @@ -11,14 +11,15 @@ #include "mlir/Conversion/ConvertToLLVM/ToLLVMInterface.h" #include "mlir/Conversion/LLVMCommon/ConversionTarget.h" #include "mlir/Conversion/LLVMCommon/TypeConverter.h" -#include "mlir/Dialect/Transform/IR/MatchInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformAttrs.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformTypes.h" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/Diagnostics.h" #include "mlir/IR/Dominance.h" +#include "mlir/IR/OperationSupport.h" #include "mlir/IR/PatternMatch.h" #include "mlir/IR/Verifier.h" #include "mlir/Interfaces/CallInterfaces.h" @@ -819,7 +820,7 @@ bool transform::CastOp::areCastCompatible(TypeRange inputs, TypeRange outputs) { assert(outputs.size() == 1 && "expected one output"); return llvm::all_of( std::initializer_list<Type>{inputs.front(), outputs.front()}, - [](Type ty) { return isa<transform::TransformHandleTypeInterface>(ty); }); + llvm::IsaPred<transform::TransformHandleTypeInterface>); } //===----------------------------------------------------------------------===// @@ -1020,6 +1021,8 @@ transform::ForeachMatchOp::apply(transform::TransformRewriter &rewriter, matchActionPairs.emplace_back(matcherSymbol, actionSymbol); } + DiagnosedSilenceableFailure overallDiag = + DiagnosedSilenceableFailure::success(); for (Operation *root : state.getPayloadOps(getRoot())) { WalkResult walkResult = root->walk([&](Operation *op) { // If getRestrictRoot is not present, skip over the root op itself so we @@ -1058,8 +1061,19 @@ transform::ForeachMatchOp::apply(transform::TransformRewriter &rewriter, action.getFunctionBody().front().without_terminator()) { DiagnosedSilenceableFailure result = state.applyTransform(cast<TransformOpInterface>(transform)); - if (failed(result.checkAndReport())) + if (result.isDefiniteFailure()) return WalkResult::interrupt(); + if (result.isSilenceableFailure()) { + if (overallDiag.succeeded()) { + overallDiag = emitSilenceableError() << "actions failed"; + } + overallDiag.attachNote(action->getLoc()) + << "failed action: " << result.getMessage(); + overallDiag.attachNote(op->getLoc()) + << "when applied to this matching payload"; + (void)result.silence(); + continue; + } } break; } @@ -1075,7 +1089,7 @@ transform::ForeachMatchOp::apply(transform::TransformRewriter &rewriter, // by actions, are invalidated. results.set(llvm::cast<OpResult>(getUpdated()), state.getPayloadOps(getRoot())); - return DiagnosedSilenceableFailure::success(); + return overallDiag; } void transform::ForeachMatchOp::getEffects( @@ -2614,21 +2628,37 @@ transform::PrintOp::apply(transform::TransformRewriter &rewriter, if (getName().has_value()) llvm::outs() << *getName() << " "; + OpPrintingFlags printFlags; + if (getAssumeVerified().value_or(false)) + printFlags.assumeVerified(); + if (getUseLocalScope().value_or(false)) + printFlags.useLocalScope(); + if (getSkipRegions().value_or(false)) + printFlags.skipRegions(); + if (!getTarget()) { - llvm::outs() << "top-level ]]]\n" << *state.getTopLevel() << "\n"; + llvm::outs() << "top-level ]]]\n"; + state.getTopLevel()->print(llvm::outs(), printFlags); + llvm::outs() << "\n"; return DiagnosedSilenceableFailure::success(); } llvm::outs() << "]]]\n"; - for (Operation *target : state.getPayloadOps(getTarget())) - llvm::outs() << *target << "\n"; + for (Operation *target : state.getPayloadOps(getTarget())) { + target->print(llvm::outs(), printFlags); + llvm::outs() << "\n"; + } return DiagnosedSilenceableFailure::success(); } void transform::PrintOp::getEffects( SmallVectorImpl<MemoryEffects::EffectInstance> &effects) { - onlyReadsHandle(getTarget(), effects); + // We don't really care about mutability here, but `getTarget` now + // unconditionally casts to a specific type before verification could run + // here. + if (!getTargetMutable().empty()) + onlyReadsHandle(getTargetMutable()[0].get(), effects); onlyReadsPayload(effects); // There is no resource for stderr file descriptor, so just declare print diff --git a/mlir/lib/Dialect/Transform/IR/TransformTypes.cpp b/mlir/lib/Dialect/Transform/IR/TransformTypes.cpp index 5f70235c2352af3230d2d6b59c89098eae70a1a8..8d9f105d1c5dbae55916994d4b61b3888a4e43da 100644 --- a/mlir/lib/Dialect/Transform/IR/TransformTypes.cpp +++ b/mlir/lib/Dialect/Transform/IR/TransformTypes.cpp @@ -8,7 +8,7 @@ #include "mlir/Dialect/Transform/IR/TransformTypes.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/DialectImplementation.h" @@ -19,8 +19,6 @@ using namespace mlir; -#include "mlir/Dialect/Transform/IR/TransformTypeInterfaces.cpp.inc" - // These are automatically generated by ODS but are not used as the Transform // dialect uses a different dispatch mechanism to support dialect extensions. LLVM_ATTRIBUTE_UNUSED static OptionalParseResult diff --git a/mlir/lib/Dialect/Transform/Interfaces/CMakeLists.txt b/mlir/lib/Dialect/Transform/Interfaces/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc9cbfdc9a5bf347ad6b5d56ced445379427e2af --- /dev/null +++ b/mlir/lib/Dialect/Transform/Interfaces/CMakeLists.txt @@ -0,0 +1,17 @@ +add_mlir_library(MLIRTransformDialectInterfaces + MatchInterfaces.cpp + TransformInterfaces.cpp + + DEPENDS + MLIRMatchInterfacesIncGen + MLIRTransformInterfacesIncGen + + LINK_LIBS PUBLIC + MLIRCastInterfaces + MLIRIR + MLIRRewrite + MLIRSideEffectInterfaces + MLIRTransforms + MLIRTransformDialectUtils +) + diff --git a/mlir/lib/Dialect/Transform/IR/MatchInterfaces.cpp b/mlir/lib/Dialect/Transform/Interfaces/MatchInterfaces.cpp similarity index 97% rename from mlir/lib/Dialect/Transform/IR/MatchInterfaces.cpp rename to mlir/lib/Dialect/Transform/Interfaces/MatchInterfaces.cpp index b9b6dabc26216e1ac3dd3b41862b13472aa17585..4151d0ea5bee05b0fa64cf42b5298b2d74b906f8 100644 --- a/mlir/lib/Dialect/Transform/IR/MatchInterfaces.cpp +++ b/mlir/lib/Dialect/Transform/Interfaces/MatchInterfaces.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "mlir/Dialect/Transform/IR/MatchInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.h" using namespace mlir; @@ -149,4 +149,4 @@ DiagnosedSilenceableFailure transform::expandTargetSpecification( // Generated interface implementation. //===----------------------------------------------------------------------===// -#include "mlir/Dialect/Transform/IR/MatchInterfaces.cpp.inc" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.cpp.inc" diff --git a/mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp b/mlir/lib/Dialect/Transform/Interfaces/TransformInterfaces.cpp similarity index 98% rename from mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp rename to mlir/lib/Dialect/Transform/Interfaces/TransformInterfaces.cpp index 71a9d61198e3fb4d5f518a5a95f5cb5779a05eee..48f3954b6cf69f4e33dd81adde98adb62228aa5d 100644 --- a/mlir/lib/Dialect/Transform/IR/TransformInterfaces.cpp +++ b/mlir/lib/Dialect/Transform/Interfaces/TransformInterfaces.cpp @@ -6,10 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" -#include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformTypes.h" #include "mlir/IR/Diagnostics.h" #include "mlir/IR/Operation.h" #include "mlir/IR/PatternMatch.h" @@ -951,8 +949,8 @@ transform::TransformState::applyTransform(TransformOpInterface transform) { DiagnosedSilenceableFailure trackingFailure = trackingListener.checkAndResetError(); if (!transform->hasTrait<ReportTrackingListenerFailuresOpTrait>() || - transform->hasAttr( - transform::TransformDialect::kSilenceTrackingFailuresAttrName)) { + transform->hasAttr(FindPayloadReplacementOpInterface:: + kSilenceTrackingFailuresAttrName)) { // Only report failures for ReportTrackingListenerFailuresOpTrait ops. Also // do not report failures if the above mentioned attribute is set. if (trackingFailure.isSilenceableFailure()) @@ -1278,14 +1276,11 @@ void transform::TrackingListener::notifyMatchFailure( } void transform::TrackingListener::notifyOperationErased(Operation *op) { - // TODO: Walk can be removed when D144193 has landed. - op->walk([&](Operation *op) { - // Remove mappings for result values. - for (OpResult value : op->getResults()) - (void)replacePayloadValue(value, nullptr); - // Remove mapping for op. - (void)replacePayloadOp(op, nullptr); - }); + // Remove mappings for result values. + for (OpResult value : op->getResults()) + (void)replacePayloadValue(value, nullptr); + // Remove mapping for op. + (void)replacePayloadOp(op, nullptr); } void transform::TrackingListener::notifyOperationReplaced( @@ -1652,23 +1647,7 @@ LogicalResult transform::detail::mapPossibleTopLevelTransformOpBlockArguments( << " were provided to the interpreter"; } - // Top-level transforms can be used for matching. If no concrete operation - // type is specified, the block argument is mapped to the top-level op. - // Otherwise, it is mapped to all ops of the specified type within the - // top-level op (including the top-level op itself). Once an op is added as - // a target, its descendants are not explored any further. - BlockArgument bbArg = region.front().getArgument(0); - if (auto bbArgType = dyn_cast<transform::OperationType>(bbArg.getType())) { - state.getTopLevel()->walk<WalkOrder::PreOrder>([&](Operation *op) { - if (op->getName().getStringRef() == bbArgType.getOperationName()) { - targets.push_back(op); - return WalkResult::skip(); - } - return WalkResult::advance(); - }); - } else { - targets.push_back(state.getTopLevel()); - } + targets.push_back(state.getTopLevel()); for (unsigned i = 0, e = state.getNumTopLevelMappings(); i < e; ++i) extraMappings.push_back(llvm::to_vector(state.getTopLevelMapping(i))); @@ -2006,4 +1985,5 @@ LogicalResult transform::applyTransforms( // Generated interface implementation. //===----------------------------------------------------------------------===// -#include "mlir/Dialect/Transform/IR/TransformInterfaces.cpp.inc" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.cpp.inc" +#include "mlir/Dialect/Transform/Interfaces/TransformTypeInterfaces.cpp.inc" diff --git a/mlir/lib/Dialect/Transform/Transforms/CheckUses.cpp b/mlir/lib/Dialect/Transform/Transforms/CheckUses.cpp index 45fa644f42ec3f9a3a3564e058535e6bc9b9d331..561d3d5b05af6467a0f092a2709581aa2e9a7ae3 100644 --- a/mlir/lib/Dialect/Transform/Transforms/CheckUses.cpp +++ b/mlir/lib/Dialect/Transform/Transforms/CheckUses.cpp @@ -13,7 +13,7 @@ #include "mlir/Dialect/Transform/Transforms/Passes.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Interfaces/SideEffectInterfaces.h" #include "mlir/Pass/Pass.h" #include "llvm/ADT/SetOperations.h" diff --git a/mlir/lib/Dialect/Transform/Transforms/InferEffects.cpp b/mlir/lib/Dialect/Transform/Transforms/InferEffects.cpp index 281c1b9f8fdb79ca5903f63279110a7c7ab4299e..20db09ca9e8d599d1995a317fa1aaefcedc8443b 100644 --- a/mlir/lib/Dialect/Transform/Transforms/InferEffects.cpp +++ b/mlir/lib/Dialect/Transform/Transforms/InferEffects.cpp @@ -9,7 +9,7 @@ #include "mlir/Dialect/Transform/IR/TransformDialect.h" #include "mlir/Dialect/Transform/Transforms/Passes.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/Visitors.h" #include "mlir/Interfaces/FunctionInterfaces.h" #include "mlir/Interfaces/SideEffectInterfaces.h" diff --git a/mlir/lib/Dialect/Transform/Transforms/InterpreterPass.cpp b/mlir/lib/Dialect/Transform/Transforms/InterpreterPass.cpp index 7adf223f3440a59f122db7f5e7ec3b40b8a4691c..19906f15ae85f6eacffa9f135117893badcc54ab 100644 --- a/mlir/lib/Dialect/Transform/Transforms/InterpreterPass.cpp +++ b/mlir/lib/Dialect/Transform/Transforms/InterpreterPass.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Dialect/Transform/Transforms/Passes.h" #include "mlir/Dialect/Transform/Transforms/TransformInterpreterUtils.h" diff --git a/mlir/lib/Dialect/Transform/Transforms/TransformInterpreterPassBase.cpp b/mlir/lib/Dialect/Transform/Transforms/TransformInterpreterPassBase.cpp index a2f9e502e7235faa5f63c1136b39c8fb23a2787f..efb9359e19951b751d14ece1d2edee991b0faa14 100644 --- a/mlir/lib/Dialect/Transform/Transforms/TransformInterpreterPassBase.cpp +++ b/mlir/lib/Dialect/Transform/Transforms/TransformInterpreterPassBase.cpp @@ -13,9 +13,9 @@ #include "mlir/Dialect/Transform/Transforms/TransformInterpreterPassBase.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformOps.h" #include "mlir/Dialect/Transform/IR/Utils.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Dialect/Transform/Transforms/TransformInterpreterUtils.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/Verifier.h" diff --git a/mlir/lib/Dialect/Transform/Transforms/TransformInterpreterUtils.cpp b/mlir/lib/Dialect/Transform/Transforms/TransformInterpreterUtils.cpp index 8a9cd7c52d82c9212d92420e00dcf2021ff0bfd4..232c9c96dd09fc4112d4227b43387a4a1bf7488f 100644 --- a/mlir/lib/Dialect/Transform/Transforms/TransformInterpreterUtils.cpp +++ b/mlir/lib/Dialect/Transform/Transforms/TransformInterpreterUtils.cpp @@ -12,9 +12,9 @@ #include "mlir/Dialect/Transform/Transforms/TransformInterpreterUtils.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformOps.h" #include "mlir/Dialect/Transform/IR/Utils.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/Verifier.h" #include "mlir/IR/Visitors.h" diff --git a/mlir/lib/Dialect/UB/IR/UBOps.cpp b/mlir/lib/Dialect/UB/IR/UBOps.cpp index 3a2010cdcb5c7cea8b59cde70ba193022052a540..5b2cfe7bf426425ada7807e0813cfc7552d1e1ca 100644 --- a/mlir/lib/Dialect/UB/IR/UBOps.cpp +++ b/mlir/lib/Dialect/UB/IR/UBOps.cpp @@ -46,7 +46,7 @@ void UBDialect::initialize() { #include "mlir/Dialect/UB/IR/UBOpsAttributes.cpp.inc" >(); addInterfaces<UBInlinerInterface>(); - declarePromisedInterface<UBDialect, ConvertToLLVMPatternInterface>(); + declarePromisedInterface<ConvertToLLVMPatternInterface, UBDialect>(); } Operation *UBDialect::materializeConstant(OpBuilder &builder, Attribute value, diff --git a/mlir/lib/Dialect/Utils/CMakeLists.txt b/mlir/lib/Dialect/Utils/CMakeLists.txt index 7d40caebe1e0536a775ac1cd4a298c335e6beb1f..a0096e5f299d59baa7f283ce628db3dd3483f443 100644 --- a/mlir/lib/Dialect/Utils/CMakeLists.txt +++ b/mlir/lib/Dialect/Utils/CMakeLists.txt @@ -4,7 +4,9 @@ add_mlir_library(MLIRDialectUtils StructuredOpsUtils.cpp StaticValueUtils.cpp + DEPENDS + MLIRDialectUtilsIncGen + LINK_LIBS PUBLIC - MLIRArithUtils MLIRIR ) diff --git a/mlir/lib/Dialect/Utils/StaticValueUtils.cpp b/mlir/lib/Dialect/Utils/StaticValueUtils.cpp index 0c8a88da789e269509946235d67f287cdc35a852..1e8197e1094424087c5d48a73fe40881d146e6b5 100644 --- a/mlir/lib/Dialect/Utils/StaticValueUtils.cpp +++ b/mlir/lib/Dialect/Utils/StaticValueUtils.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "mlir/Dialect/Utils/StaticValueUtils.h" -#include "mlir/Dialect/Arith/Utils/Utils.h" #include "mlir/IR/Matchers.h" #include "mlir/Support/LLVM.h" #include "mlir/Support/MathExtras.h" @@ -18,13 +17,10 @@ namespace mlir { bool isZeroIndex(OpFoldResult v) { if (!v) return false; - if (auto attr = llvm::dyn_cast_if_present<Attribute>(v)) { - IntegerAttr intAttr = dyn_cast<IntegerAttr>(attr); - return intAttr && intAttr.getValue().isZero(); - } - if (auto cst = v.get<Value>().getDefiningOp<arith::ConstantIndexOp>()) - return cst.value() == 0; - return false; + std::optional<int64_t> constint = getConstantIntValue(v); + if (!constint) + return false; + return *constint == 0; } std::tuple<SmallVector<OpFoldResult>, SmallVector<OpFoldResult>, diff --git a/mlir/lib/Dialect/Vector/IR/CMakeLists.txt b/mlir/lib/Dialect/Vector/IR/CMakeLists.txt index 70f3fa8c297d4bc0d0fb809a06675e246330b9f6..204462ffd047c6496391f50958c98443f68f0616 100644 --- a/mlir/lib/Dialect/Vector/IR/CMakeLists.txt +++ b/mlir/lib/Dialect/Vector/IR/CMakeLists.txt @@ -1,5 +1,7 @@ add_mlir_dialect_library(MLIRVectorDialect VectorOps.cpp + ValueBoundsOpInterfaceImpl.cpp + ScalableValueBoundsConstraintSet.cpp ADDITIONAL_HEADER_DIRS ${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/Vector/IR diff --git a/mlir/lib/Dialect/Vector/IR/ScalableValueBoundsConstraintSet.cpp b/mlir/lib/Dialect/Vector/IR/ScalableValueBoundsConstraintSet.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6d7e3bc70f59de908bffb1d8032abab7b29f91f3 --- /dev/null +++ b/mlir/lib/Dialect/Vector/IR/ScalableValueBoundsConstraintSet.cpp @@ -0,0 +1,103 @@ +//===- ScalableValueBoundsConstraintSet.cpp - Scalable Value Bounds -------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "mlir/Dialect/Vector/IR/ScalableValueBoundsConstraintSet.h" + +#include "mlir/Dialect/Vector/IR/VectorOps.h" + +namespace mlir::vector { + +FailureOr<ConstantOrScalableBound::BoundSize> +ConstantOrScalableBound::getSize() const { + if (map.isSingleConstant()) + return BoundSize{map.getSingleConstantResult(), /*scalable=*/false}; + if (map.getNumResults() != 1 || map.getNumInputs() != 1) + return failure(); + auto binop = dyn_cast<AffineBinaryOpExpr>(map.getResult(0)); + if (!binop || binop.getKind() != AffineExprKind::Mul) + return failure(); + auto matchConstant = [&](AffineExpr expr, int64_t &constant) -> bool { + if (auto cst = dyn_cast<AffineConstantExpr>(expr)) { + constant = cst.getValue(); + return true; + } + return false; + }; + // Match `s0 * cst` or `cst * s0`: + int64_t cst = 0; + auto lhs = binop.getLHS(); + auto rhs = binop.getRHS(); + if ((matchConstant(lhs, cst) && isa<AffineSymbolExpr>(rhs)) || + (matchConstant(rhs, cst) && isa<AffineSymbolExpr>(lhs))) { + return BoundSize{cst, /*scalable=*/true}; + } + return failure(); +} + +char ScalableValueBoundsConstraintSet::ID = 0; + +FailureOr<ConstantOrScalableBound> +ScalableValueBoundsConstraintSet::computeScalableBound( + Value value, std::optional<int64_t> dim, unsigned vscaleMin, + unsigned vscaleMax, presburger::BoundType boundType, bool closedUB, + StopConditionFn stopCondition) { + using namespace presburger; + + assert(vscaleMin <= vscaleMax); + ScalableValueBoundsConstraintSet scalableCstr(value.getContext(), vscaleMin, + vscaleMax); + + int64_t pos = scalableCstr.populateConstraintsSet(value, dim, stopCondition); + + // Project out all variables apart from vscale. + // This should result in constraints in terms of vscale only. + scalableCstr.projectOut( + [&](ValueDim p) { return p.first != scalableCstr.getVscaleValue(); }); + + assert(scalableCstr.cstr.getNumDimAndSymbolVars() == + scalableCstr.positionToValueDim.size() && + "inconsistent mapping state"); + + // Check that the only symbols left are vscale. + for (int64_t i = 0; i < scalableCstr.cstr.getNumDimAndSymbolVars(); ++i) { + if (i == pos) + continue; + if (scalableCstr.positionToValueDim[i] != + ValueDim(scalableCstr.getVscaleValue(), + ValueBoundsConstraintSet::kIndexValue)) { + return failure(); + } + } + + SmallVector<AffineMap, 1> lowerBound(1), upperBound(1); + scalableCstr.cstr.getSliceBounds(pos, 1, value.getContext(), &lowerBound, + &upperBound, closedUB); + + auto invalidBound = [](auto &bound) { + return !bound[0] || bound[0].getNumResults() != 1; + }; + + AffineMap bound = [&] { + if (boundType == BoundType::EQ && !invalidBound(lowerBound) && + lowerBound[0] == lowerBound[0]) { + return lowerBound[0]; + } else if (boundType == BoundType::LB && !invalidBound(lowerBound)) { + return lowerBound[0]; + } else if (boundType == BoundType::UB && !invalidBound(upperBound)) { + return upperBound[0]; + } + return AffineMap{}; + }(); + + if (!bound) + return failure(); + + return ConstantOrScalableBound{bound}; +} + +} // namespace mlir::vector diff --git a/mlir/lib/Dialect/Vector/IR/ValueBoundsOpInterfaceImpl.cpp b/mlir/lib/Dialect/Vector/IR/ValueBoundsOpInterfaceImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca95072d9bb0f274575c28c5f3bdd77887a3318c --- /dev/null +++ b/mlir/lib/Dialect/Vector/IR/ValueBoundsOpInterfaceImpl.cpp @@ -0,0 +1,51 @@ +//===- ValueBoundsOpInterfaceImpl.cpp - Impl. of ValueBoundsOpInterface ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "mlir/Dialect/Vector/IR/ValueBoundsOpInterfaceImpl.h" + +#include "mlir/Dialect/Vector/IR/ScalableValueBoundsConstraintSet.h" +#include "mlir/Dialect/Vector/IR/VectorOps.h" +#include "mlir/Interfaces/ValueBoundsOpInterface.h" + +using namespace mlir; + +namespace mlir::vector { +namespace { + +struct VectorScaleOpInterface + : public ValueBoundsOpInterface::ExternalModel<VectorScaleOpInterface, + VectorScaleOp> { + void populateBoundsForIndexValue(Operation *op, Value value, + ValueBoundsConstraintSet &cstr) const { + auto *scalableCstr = dyn_cast<ScalableValueBoundsConstraintSet>(&cstr); + if (!scalableCstr) + return; + auto vscaleOp = cast<VectorScaleOp>(op); + assert(value == vscaleOp.getResult() && "invalid value"); + if (auto vscale = scalableCstr->getVscaleValue()) { + // All copies of vscale are equivalent. + scalableCstr->bound(value) == cstr.getExpr(vscale); + } else { + // We know vscale is confined to [vscaleMin, vscaleMax]. + scalableCstr->bound(value) >= scalableCstr->getVscaleMin(); + scalableCstr->bound(value) <= scalableCstr->getVscaleMax(); + scalableCstr->setVscale(vscaleOp); + } + } +}; + +} // namespace +} // namespace mlir::vector + +void mlir::vector::registerValueBoundsOpInterfaceExternalModels( + DialectRegistry ®istry) { + registry.addExtension(+[](MLIRContext *ctx, vector::VectorDialect *dialect) { + vector::VectorScaleOp::attachInterface<vector::VectorScaleOpInterface>( + *ctx); + }); +} diff --git a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp index 75f6220ad8f3fae0332e9d8c49c425b7c81a30ad..3e6425879cc67fb8577143b76fb4b903bd62b43c 100644 --- a/mlir/lib/Dialect/Vector/IR/VectorOps.cpp +++ b/mlir/lib/Dialect/Vector/IR/VectorOps.cpp @@ -16,6 +16,7 @@ #include "mlir/Dialect/Affine/IR/ValueBoundsOpInterfaceImpl.h" #include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/Arith/Utils/Utils.h" +#include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/Dialect/Tensor/IR/Tensor.h" #include "mlir/Dialect/Utils/IndexingUtils.h" @@ -31,6 +32,7 @@ #include "mlir/IR/OpImplementation.h" #include "mlir/IR/PatternMatch.h" #include "mlir/IR/TypeUtilities.h" +#include "mlir/Interfaces/SubsetOpInterface.h" #include "mlir/Interfaces/ValueBoundsOpInterface.h" #include "mlir/Support/LLVM.h" #include "mlir/Transforms/InliningUtils.h" @@ -374,6 +376,14 @@ void VectorDialect::initialize() { >(); addInterfaces<VectorInlinerInterface>(); + + declarePromisedInterfaces<bufferization::BufferizableOpInterface, + TransferReadOp, TransferWriteOp, GatherOp, MaskOp, + YieldOp>(); + declarePromisedInterfaces<SubsetOpInterface, TransferReadOp, + TransferWriteOp>(); + declarePromisedInterface<SubsetExtractionOpInterface, TransferReadOp>(); + declarePromisedInterface<SubsetInsertionOpInterface, TransferWriteOp>(); } /// Materialize a single constant operation from a given attribute value with @@ -888,13 +898,12 @@ static LogicalResult verifyOutputShape( AffineMap resMap = op.getIndexingMapsArray()[2]; auto extentsMap = AffineMap::get(/*dimCount=*/extents.size(), - /*symCount=*/0, extents, ctx); + /*symbolCount=*/0, extents, ctx); // Compose the resMap with the extentsMap, which is a constant map. AffineMap expectedMap = simplifyAffineMap(resMap.compose(extentsMap)); - assert( - llvm::all_of(expectedMap.getResults(), - [](AffineExpr e) { return isa<AffineConstantExpr>(e); }) && - "expected constant extent along all dimensions."); + assert(llvm::all_of(expectedMap.getResults(), + llvm::IsaPred<AffineConstantExpr>) && + "expected constant extent along all dimensions."); // Extract the expected shape and build the type. auto expectedShape = llvm::to_vector<4>( llvm::map_range(expectedMap.getResults(), [](AffineExpr e) { @@ -6054,7 +6063,7 @@ LogicalResult MaskOp::fold(FoldAdaptor adaptor, maskableOp->dropAllUses(); maskableOp->moveBefore(getOperation()); - results.push_back(maskableOp->getResult(0)); + llvm::append_range(results, maskableOp->getResults()); return success(); } diff --git a/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp b/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp index 6c2cfd8833dddc002f303a23ab838b669de7c14f..885644864c0f71e066bf25d20af599eaaa8b078b 100644 --- a/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp +++ b/mlir/lib/Dialect/Vector/TransformOps/VectorTransformOps.cpp @@ -13,8 +13,8 @@ #include "mlir/Conversion/VectorToSCF/VectorToSCF.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformOps.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Dialect/Vector/IR/VectorOps.h" #include "mlir/Dialect/Vector/Transforms/LoweringPatterns.h" #include "mlir/Dialect/Vector/Transforms/VectorRewritePatterns.h" diff --git a/mlir/lib/Dialect/Vector/Transforms/LowerVectorContract.cpp b/mlir/lib/Dialect/Vector/Transforms/LowerVectorContract.cpp index 0eaf9f71a37d215f9cd04a20a53a1feefe483d4e..ba1c96805ff83154938ca8214748cf6da265ac7b 100644 --- a/mlir/lib/Dialect/Vector/Transforms/LowerVectorContract.cpp +++ b/mlir/lib/Dialect/Vector/Transforms/LowerVectorContract.cpp @@ -41,7 +41,6 @@ using namespace mlir::vector; //===----------------------------------------------------------------------===// // Helper functions //===----------------------------------------------------------------------===// - // Helper to find an index in an affine map. static std::optional<int64_t> getResultIndex(AffineMap map, int64_t index) { for (int64_t i = 0, e = map.getNumResults(); i < e; ++i) { @@ -226,9 +225,9 @@ namespace { /// This only kicks in when VectorTransformsOptions is set to OuterProduct and /// the vector.contract op is a row-major matrix multiply. class ContractionOpToMatmulOpLowering - : public OpRewritePattern<vector::ContractionOp> { + : public vector::MaskableOpRewritePattern<vector::ContractionOp> { public: - using OpRewritePattern::OpRewritePattern; + using MaskableOpRewritePattern::MaskableOpRewritePattern; using FilterConstraintType = std::function<LogicalResult(vector::ContractionOp op)>; @@ -241,12 +240,13 @@ public: vector::VectorTransformsOptions vectorTransformOptions, MLIRContext *context, PatternBenefit benefit = 1, FilterConstraintType constraint = defaultFilter) - : OpRewritePattern<vector::ContractionOp>(context, benefit), + : MaskableOpRewritePattern<vector::ContractionOp>(context, benefit), vectorTransformOptions(vectorTransformOptions), filter(std::move(constraint)) {} - LogicalResult matchAndRewrite(vector::ContractionOp op, - PatternRewriter &rewriter) const override; + FailureOr<Value> + matchAndRewriteMaskableOp(vector::ContractionOp op, MaskingOpInterface maskOp, + PatternRewriter &rewriter) const override; private: /// Options to control the vector patterns. @@ -270,9 +270,9 @@ private: /// This only kicks in when VectorTransformsOptions is set to OuterProduct and /// the vector.contract op is a row-major matrix multiply. class ContractionOpToOuterProductOpLowering - : public OpRewritePattern<vector::ContractionOp> { + : public MaskableOpRewritePattern<vector::ContractionOp> { public: - using OpRewritePattern::OpRewritePattern; + using MaskableOpRewritePattern::MaskableOpRewritePattern; using FilterConstraintType = std::function<LogicalResult(vector::ContractionOp op)>; @@ -285,12 +285,13 @@ public: vector::VectorTransformsOptions vectorTransformOptions, MLIRContext *context, PatternBenefit benefit = 1, FilterConstraintType constraint = defaultFilter) - : OpRewritePattern<vector::ContractionOp>(context, benefit), + : MaskableOpRewritePattern<vector::ContractionOp>(context, benefit), vectorTransformOptions(vectorTransformOptions), filter(std::move(constraint)) {} - LogicalResult matchAndRewrite(vector::ContractionOp op, - PatternRewriter &rewriter) const override; + FailureOr<Value> + matchAndRewriteMaskableOp(vector::ContractionOp op, MaskingOpInterface maskOp, + PatternRewriter &rewriter) const override; private: /// Options to control the vector patterns. @@ -317,9 +318,9 @@ private: /// This only kicks in when VectorTransformsOptions is set to Dot and /// the vector.contract op is a row-major matmul or matvec. class ContractionOpToDotLowering - : public OpRewritePattern<vector::ContractionOp> { + : public MaskableOpRewritePattern<vector::ContractionOp> { public: - using OpRewritePattern::OpRewritePattern; + using MaskableOpRewritePattern::MaskableOpRewritePattern; using FilterConstraintType = std::function<LogicalResult(vector::ContractionOp op)>; @@ -332,11 +333,12 @@ public: vector::VectorTransformsOptions vectorTransformOptions, MLIRContext *context, PatternBenefit benefit = 1, const FilterConstraintType &constraint = defaultFilter) - : OpRewritePattern<vector::ContractionOp>(context, benefit), + : MaskableOpRewritePattern<vector::ContractionOp>(context, benefit), vectorTransformOptions(vectorTransformOptions), filter(defaultFilter) {} - LogicalResult matchAndRewrite(vector::ContractionOp op, - PatternRewriter &rewriter) const override; + FailureOr<Value> + matchAndRewriteMaskableOp(vector::ContractionOp op, MaskingOpInterface maskOp, + PatternRewriter &rewriter) const override; private: /// Options to control the vector patterns. @@ -358,9 +360,10 @@ private: /// /// This only kicks in when either VectorTransformsOptions is set /// to Dot or when other contraction patterns fail. -class ContractionOpLowering : public OpRewritePattern<vector::ContractionOp> { +class ContractionOpLowering + : public MaskableOpRewritePattern<vector::ContractionOp> { public: - using OpRewritePattern::OpRewritePattern; + using MaskableOpRewritePattern::MaskableOpRewritePattern; using FilterConstraintType = std::function<LogicalResult(vector::ContractionOp op)>; @@ -371,12 +374,13 @@ public: ContractionOpLowering(vector::VectorTransformsOptions vectorTransformOptions, MLIRContext *context, PatternBenefit benefit = 1, FilterConstraintType constraint = defaultFilter) - : OpRewritePattern<vector::ContractionOp>(context, benefit), + : MaskableOpRewritePattern<vector::ContractionOp>(context, benefit), vectorTransformOptions(vectorTransformOptions), filter(std::move(constraint)) {} - LogicalResult matchAndRewrite(vector::ContractionOp op, - PatternRewriter &rewriter) const override; + FailureOr<Value> + matchAndRewriteMaskableOp(vector::ContractionOp op, MaskingOpInterface maskOp, + PatternRewriter &rewriter) const override; private: /// Options to control the vector patterns. @@ -634,8 +638,10 @@ private: /// /// This only kicks in when VectorTransformsOptions is set to OuterProduct but /// otherwise supports any layout permutation of the matrix-multiply. -LogicalResult ContractionOpToOuterProductOpLowering::matchAndRewrite( - vector::ContractionOp op, PatternRewriter &rewriter) const { +FailureOr<Value> +ContractionOpToOuterProductOpLowering::matchAndRewriteMaskableOp( + vector::ContractionOp op, MaskingOpInterface maskOp, + PatternRewriter &rewriter) const { if (vectorTransformOptions.vectorContractLowering != vector::VectorContractLowering::OuterProduct) return failure(); @@ -643,43 +649,25 @@ LogicalResult ContractionOpToOuterProductOpLowering::matchAndRewrite( if (failed(filter(op))) return failure(); - // Vector mask setup. - OpBuilder::InsertionGuard guard(rewriter); - auto maskableOp = cast<vector::MaskableOpInterface>(op.getOperation()); - Operation *rootOp; - if (maskableOp.isMasked()) { - rewriter.setInsertionPoint(maskableOp.getMaskingOp()); - rootOp = maskableOp.getMaskingOp(); - } else { - rootOp = op; - } - UnrolledOuterProductGenerator e(rewriter, op); FailureOr<Value> matmatRes = e.matmat(); if (succeeded(matmatRes)) { - rewriter.replaceOp(rootOp, *matmatRes); - return success(); + return matmatRes; } FailureOr<Value> matvecRes = e.matvec(); if (succeeded(matvecRes)) { - rewriter.replaceOp(rootOp, *matvecRes); - return success(); - } - FailureOr<Value> tmatvecRes = e.tmatvec(); - if (succeeded(tmatvecRes)) { - rewriter.replaceOp(rootOp, *tmatvecRes); - return success(); + return matvecRes; } - return failure(); + FailureOr<Value> tmatvecRes = e.tmatvec(); + return tmatvecRes; } -LogicalResult -ContractionOpToDotLowering::matchAndRewrite(vector::ContractionOp op, - PatternRewriter &rewriter) const { +FailureOr<Value> ContractionOpToDotLowering::matchAndRewriteMaskableOp( + vector::ContractionOp op, MaskingOpInterface maskOp, + PatternRewriter &rewriter) const { // TODO: Support vector.mask. - auto maskableOp = cast<MaskableOpInterface>(op.getOperation()); - if (maskableOp.isMasked()) + if (maskOp) return failure(); if (failed(filter(op))) @@ -788,15 +776,14 @@ ContractionOpToDotLowering::matchAndRewrite(vector::ContractionOp op, } if (auto acc = op.getAcc()) res = createAdd(op.getLoc(), res, acc, isInt, rewriter); - rewriter.replaceOp(op, res); - return success(); + return res; } /// Lower vector.contract with all size one reduction dimensions to /// elementwise ops when possible. struct ContractOpToElementwise - : public OpRewritePattern<vector::ContractionOp> { - using OpRewritePattern::OpRewritePattern; + : public MaskableOpRewritePattern<vector::ContractionOp> { + using MaskableOpRewritePattern::MaskableOpRewritePattern; using FilterConstraintType = std::function<LogicalResult(vector::ContractionOp op)>; static LogicalResult defaultFilter(vector::ContractionOp op) { @@ -806,14 +793,15 @@ struct ContractOpToElementwise vector::VectorTransformsOptions vectorTransformOptions, MLIRContext *context, PatternBenefit benefit = 1, const FilterConstraintType &constraint = defaultFilter) - : OpRewritePattern<vector::ContractionOp>(context, benefit), + : MaskableOpRewritePattern<vector::ContractionOp>(context, benefit), vectorTransformOptions(vectorTransformOptions), filter(defaultFilter) {} - LogicalResult matchAndRewrite(vector::ContractionOp contractOp, - PatternRewriter &rewriter) const override { + FailureOr<Value> + matchAndRewriteMaskableOp(vector::ContractionOp contractOp, + MaskingOpInterface maskOp, + PatternRewriter &rewriter) const override { // TODO: Support vector.mask. - auto maskableOp = cast<MaskableOpInterface>(contractOp.getOperation()); - if (maskableOp.isMasked()) + if (maskOp) return failure(); if (failed(filter(contractOp))) @@ -903,8 +891,10 @@ struct ContractOpToElementwise std::optional<Value> result = createContractArithOp(loc, newLhs, newRhs, contractOp.getAcc(), contractOp.getKind(), rewriter, isInt); - rewriter.replaceOp(contractOp, {*result}); - return success(); + if (result) + return *result; + + return failure(); } private: @@ -930,9 +920,9 @@ private: // TODO: break down into transpose/reshape/cast ops // when they become available to avoid code dup // TODO: investigate lowering order impact on performance -LogicalResult -ContractionOpLowering::matchAndRewrite(vector::ContractionOp op, - PatternRewriter &rewriter) const { +FailureOr<Value> ContractionOpLowering::matchAndRewriteMaskableOp( + vector::ContractionOp op, MaskingOpInterface maskOp, + PatternRewriter &rewriter) const { if (failed(filter(op))) return failure(); @@ -951,29 +941,36 @@ ContractionOpLowering::matchAndRewrite(vector::ContractionOp op, // TODO: implement benefits, cost models. MLIRContext *ctx = op.getContext(); + ContractionOpToMatmulOpLowering pat1(vectorTransformOptions, ctx); - if (succeeded(pat1.matchAndRewrite(op, rewriter))) - return success(); + FailureOr<Value> newVal1 = + pat1.matchAndRewriteMaskableOp(op, maskOp, rewriter); + if (!failed(newVal1)) + return newVal1; + ContractionOpToOuterProductOpLowering pat2(vectorTransformOptions, ctx); - if (succeeded(pat2.matchAndRewrite(op, rewriter))) - return success(); + FailureOr<Value> newVal2 = + pat2.matchAndRewriteMaskableOp(op, maskOp, rewriter); + if (!failed(newVal2)) + return newVal2; + ContractionOpToDotLowering pat3(vectorTransformOptions, ctx); - if (succeeded(pat3.matchAndRewrite(op, rewriter))) - return success(); + FailureOr<Value> newVal3 = + pat3.matchAndRewriteMaskableOp(op, maskOp, rewriter); + if (!failed(newVal3)) + return newVal3; + ContractOpToElementwise pat4(vectorTransformOptions, ctx); - if (succeeded(pat4.matchAndRewrite(op, rewriter))) - return success(); + FailureOr<Value> newVal4 = + pat4.matchAndRewriteMaskableOp(op, maskOp, rewriter); + if (!failed(newVal4)) + return newVal4; // Vector mask setup. - OpBuilder::InsertionGuard guard(rewriter); - Operation *rootOp = op; - Value mask; - if (op.isMasked()) { - rewriter.setInsertionPoint(op.getMaskingOp()); - rootOp = op.getMaskingOp(); - mask = op.getMaskingOp().getMask(); - } + Value mask; + if (maskOp) + mask = maskOp.getMask(); // Find first batch dimension in LHS/RHS, and lower when found. std::vector<std::pair<int64_t, int64_t>> batchDimMap = op.getBatchDimMap(); if (!batchDimMap.empty()) { @@ -982,8 +979,7 @@ ContractionOpLowering::matchAndRewrite(vector::ContractionOp op, auto newOp = lowerParallel(rewriter, op, lhsIndex, rhsIndex, mask); if (failed(newOp)) return failure(); - rewriter.replaceOp(rootOp, *newOp); - return success(); + return newOp; } // Collect contracting dimensions. @@ -1003,8 +999,7 @@ ContractionOpLowering::matchAndRewrite(vector::ContractionOp op, auto newOp = lowerParallel(rewriter, op, lhsIndex, /*rhsIndex=*/-1, mask); if (failed(newOp)) return failure(); - rewriter.replaceOp(rootOp, *newOp); - return success(); + return newOp; } } @@ -1015,8 +1010,7 @@ ContractionOpLowering::matchAndRewrite(vector::ContractionOp op, auto newOp = lowerParallel(rewriter, op, /*lhsIndex=*/-1, rhsIndex, mask); if (failed(newOp)) return failure(); - rewriter.replaceOp(rootOp, *newOp); - return success(); + return newOp; } } @@ -1025,8 +1019,7 @@ ContractionOpLowering::matchAndRewrite(vector::ContractionOp op, auto newOp = lowerReduction(rewriter, op, mask); if (failed(newOp)) return failure(); - rewriter.replaceOp(rootOp, *newOp); - return success(); + return newOp; } return failure(); @@ -1291,12 +1284,11 @@ public: /// This only kicks in when VectorTransformsOptions is set to `Matmul`. /// vector.transpose operations are inserted if the vector.contract op is not a /// row-major matrix multiply. -LogicalResult -ContractionOpToMatmulOpLowering::matchAndRewrite(vector::ContractionOp op, - PatternRewriter &rew) const { +FailureOr<Value> ContractionOpToMatmulOpLowering::matchAndRewriteMaskableOp( + vector::ContractionOp op, MaskingOpInterface maskOp, + PatternRewriter &rew) const { // TODO: Support vector.mask. - auto maskableOp = cast<MaskableOpInterface>(op.getOperation()); - if (maskableOp.isMasked()) + if (maskOp) return failure(); if (vectorTransformOptions.vectorContractLowering != @@ -1379,8 +1371,7 @@ ContractionOpToMatmulOpLowering::matchAndRewrite(vector::ContractionOp op, : static_cast<Value>( rew.create<arith::AddFOp>(loc, op.getAcc(), mul)); - rew.replaceOp(op, res); - return success(); + return res; } } // namespace diff --git a/mlir/lib/Dialect/Vector/Transforms/LowerVectorTransfer.cpp b/mlir/lib/Dialect/Vector/Transforms/LowerVectorTransfer.cpp index 4a5e8fcfb6edaf53e1d2d5878b67f342692b157e..0693aa596cb28f99042b9ce262f3d89a68e00390 100644 --- a/mlir/lib/Dialect/Vector/Transforms/LowerVectorTransfer.cpp +++ b/mlir/lib/Dialect/Vector/Transforms/LowerVectorTransfer.cpp @@ -41,8 +41,12 @@ static Value extendVectorRank(OpBuilder &builder, Location loc, Value vec, SmallVector<int64_t> newShape(addedRank, 1); newShape.append(originalVecType.getShape().begin(), originalVecType.getShape().end()); - VectorType newVecType = - VectorType::get(newShape, originalVecType.getElementType()); + + SmallVector<bool> newScalableDims(addedRank, false); + newScalableDims.append(originalVecType.getScalableDims().begin(), + originalVecType.getScalableDims().end()); + VectorType newVecType = VectorType::get( + newShape, originalVecType.getElementType(), newScalableDims); return builder.create<vector::BroadcastOp>(loc, newVecType, vec); } diff --git a/mlir/lib/Dialect/Vector/Transforms/VectorDistribute.cpp b/mlir/lib/Dialect/Vector/Transforms/VectorDistribute.cpp index b3ab4a916121e3a82a4863ffb77d14aac3457226..a67e03e85f714538a1f9720d30b7046f842f95bf 100644 --- a/mlir/lib/Dialect/Vector/Transforms/VectorDistribute.cpp +++ b/mlir/lib/Dialect/Vector/Transforms/VectorDistribute.cpp @@ -598,9 +598,8 @@ struct WarpOpTransferWrite : public OpRewritePattern<WarpExecuteOnLane0Op> { } // Do not process warp ops that contain only TransferWriteOps. - if (llvm::all_of(warpOp.getOps(), [](Operation &op) { - return isa<vector::TransferWriteOp, vector::YieldOp>(&op); - })) + if (llvm::all_of(warpOp.getOps(), + llvm::IsaPred<vector::TransferWriteOp, vector::YieldOp>)) return failure(); SmallVector<Value> yieldValues = {writeOp.getVector()}; @@ -746,8 +745,8 @@ struct WarpOpConstant : public OpRewritePattern<WarpExecuteOnLane0Op> { using OpRewritePattern<WarpExecuteOnLane0Op>::OpRewritePattern; LogicalResult matchAndRewrite(WarpExecuteOnLane0Op warpOp, PatternRewriter &rewriter) const override { - OpOperand *yieldOperand = getWarpResult( - warpOp, [](Operation *op) { return isa<arith::ConstantOp>(op); }); + OpOperand *yieldOperand = + getWarpResult(warpOp, llvm::IsaPred<arith::ConstantOp>); if (!yieldOperand) return failure(); auto constantOp = yieldOperand->get().getDefiningOp<arith::ConstantOp>(); @@ -1060,8 +1059,8 @@ struct WarpOpBroadcast : public OpRewritePattern<WarpExecuteOnLane0Op> { using OpRewritePattern<WarpExecuteOnLane0Op>::OpRewritePattern; LogicalResult matchAndRewrite(WarpExecuteOnLane0Op warpOp, PatternRewriter &rewriter) const override { - OpOperand *operand = getWarpResult( - warpOp, [](Operation *op) { return isa<vector::BroadcastOp>(op); }); + OpOperand *operand = + getWarpResult(warpOp, llvm::IsaPred<vector::BroadcastOp>); if (!operand) return failure(); unsigned int operandNumber = operand->getOperandNumber(); @@ -1097,8 +1096,8 @@ struct WarpOpShapeCast : public OpRewritePattern<WarpExecuteOnLane0Op> { using OpRewritePattern<WarpExecuteOnLane0Op>::OpRewritePattern; LogicalResult matchAndRewrite(WarpExecuteOnLane0Op warpOp, PatternRewriter &rewriter) const override { - OpOperand *operand = getWarpResult( - warpOp, [](Operation *op) { return isa<vector::ShapeCastOp>(op); }); + OpOperand *operand = + getWarpResult(warpOp, llvm::IsaPred<vector::ShapeCastOp>); if (!operand) return failure(); @@ -1156,8 +1155,8 @@ struct WarpOpCreateMask : public OpRewritePattern<WarpExecuteOnLane0Op> { using OpRewritePattern::OpRewritePattern; LogicalResult matchAndRewrite(WarpExecuteOnLane0Op warpOp, PatternRewriter &rewriter) const override { - OpOperand *yieldOperand = getWarpResult( - warpOp, [](Operation *op) { return isa<vector::CreateMaskOp>(op); }); + OpOperand *yieldOperand = + getWarpResult(warpOp, llvm::IsaPred<vector::CreateMaskOp>); if (!yieldOperand) return failure(); @@ -1222,8 +1221,8 @@ struct WarpOpExtract : public OpRewritePattern<WarpExecuteOnLane0Op> { using OpRewritePattern<WarpExecuteOnLane0Op>::OpRewritePattern; LogicalResult matchAndRewrite(WarpExecuteOnLane0Op warpOp, PatternRewriter &rewriter) const override { - OpOperand *operand = getWarpResult( - warpOp, [](Operation *op) { return isa<vector::ExtractOp>(op); }); + OpOperand *operand = + getWarpResult(warpOp, llvm::IsaPred<vector::ExtractOp>); if (!operand) return failure(); unsigned int operandNumber = operand->getOperandNumber(); @@ -1325,9 +1324,8 @@ struct WarpOpExtractElement : public OpRewritePattern<WarpExecuteOnLane0Op> { warpShuffleFromIdxFn(std::move(fn)) {} LogicalResult matchAndRewrite(WarpExecuteOnLane0Op warpOp, PatternRewriter &rewriter) const override { - OpOperand *operand = getWarpResult(warpOp, [](Operation *op) { - return isa<vector::ExtractElementOp>(op); - }); + OpOperand *operand = + getWarpResult(warpOp, llvm::IsaPred<vector::ExtractElementOp>); if (!operand) return failure(); unsigned int operandNumber = operand->getOperandNumber(); @@ -1422,8 +1420,8 @@ struct WarpOpInsertElement : public OpRewritePattern<WarpExecuteOnLane0Op> { LogicalResult matchAndRewrite(WarpExecuteOnLane0Op warpOp, PatternRewriter &rewriter) const override { - OpOperand *operand = getWarpResult( - warpOp, [](Operation *op) { return isa<vector::InsertElementOp>(op); }); + OpOperand *operand = + getWarpResult(warpOp, llvm::IsaPred<vector::InsertElementOp>); if (!operand) return failure(); unsigned int operandNumber = operand->getOperandNumber(); @@ -1503,8 +1501,7 @@ struct WarpOpInsert : public OpRewritePattern<WarpExecuteOnLane0Op> { LogicalResult matchAndRewrite(WarpExecuteOnLane0Op warpOp, PatternRewriter &rewriter) const override { - OpOperand *operand = getWarpResult( - warpOp, [](Operation *op) { return isa<vector::InsertOp>(op); }); + OpOperand *operand = getWarpResult(warpOp, llvm::IsaPred<vector::InsertOp>); if (!operand) return failure(); unsigned int operandNumber = operand->getOperandNumber(); @@ -1808,8 +1805,8 @@ struct WarpOpReduction : public OpRewritePattern<WarpExecuteOnLane0Op> { LogicalResult matchAndRewrite(WarpExecuteOnLane0Op warpOp, PatternRewriter &rewriter) const override { - OpOperand *yieldOperand = getWarpResult( - warpOp, [](Operation *op) { return isa<vector::ReductionOp>(op); }); + OpOperand *yieldOperand = + getWarpResult(warpOp, llvm::IsaPred<vector::ReductionOp>); if (!yieldOperand) return failure(); diff --git a/mlir/lib/Dialect/Vector/Transforms/VectorDropLeadUnitDim.cpp b/mlir/lib/Dialect/Vector/Transforms/VectorDropLeadUnitDim.cpp index 74382b027c2f48a4be5eca491cdbc583c8989470..593c1e53557ad896f0f7b49ef58c4287f6bb1553 100644 --- a/mlir/lib/Dialect/Vector/Transforms/VectorDropLeadUnitDim.cpp +++ b/mlir/lib/Dialect/Vector/Transforms/VectorDropLeadUnitDim.cpp @@ -329,12 +329,10 @@ struct CastAwayTransferWriteLeadingOneDim } // namespace -LogicalResult +FailureOr<Value> mlir::vector::castAwayContractionLeadingOneDim(vector::ContractionOp contractOp, + MaskingOpInterface maskingOp, RewriterBase &rewriter) { - // TODO(#78787): Not supported masked op yet. - if (cast<MaskableOpInterface>(contractOp.getOperation()).isMasked()) - return failure(); VectorType oldAccType = dyn_cast<VectorType>(contractOp.getAccType()); if (oldAccType == nullptr) return failure(); @@ -368,6 +366,7 @@ mlir::vector::castAwayContractionLeadingOneDim(vector::ContractionOp contractOp, SmallVector<Value> operands = {contractOp.getLhs(), contractOp.getRhs(), contractOp.getAcc()}; SmallVector<Value> newOperands; + auto loc = contractOp.getLoc(); for (const auto &it : llvm::enumerate(oldIndexingMaps)) { // Check if the dim to be dropped exists as a leading dim in the operand @@ -405,7 +404,7 @@ mlir::vector::castAwayContractionLeadingOneDim(vector::ContractionOp contractOp, map = AffineMap::get(map.getNumDims(), 0, transposeResults, contractOp.getContext()); operands[it.index()] = rewriter.create<vector::TransposeOp>( - contractOp.getLoc(), operands[it.index()], perm); + loc, operands[it.index()], perm); } } // We have taken care to have the dim to be dropped be @@ -429,18 +428,29 @@ mlir::vector::castAwayContractionLeadingOneDim(vector::ContractionOp contractOp, // Extract if its a valid extraction, otherwise use the operand // without extraction. newOperands.push_back( - validExtract ? rewriter.create<vector::ExtractOp>(contractOp.getLoc(), - operands[it.index()], - splatZero(dropDim)) + validExtract ? rewriter.create<vector::ExtractOp>( + loc, operands[it.index()], splatZero(dropDim)) : operands[it.index()]); } - auto newContractOp = rewriter.create<vector::ContractionOp>( - contractOp.getLoc(), newOperands[0], newOperands[1], newOperands[2], + + // Depending on whether this vector.contract is masked, the replacing Op + // should either be a new vector.contract Op or vector.mask Op. + Operation *newOp = rewriter.create<vector::ContractionOp>( + loc, newOperands[0], newOperands[1], newOperands[2], rewriter.getAffineMapArrayAttr(newIndexingMaps), rewriter.getArrayAttr(newIteratorTypes), contractOp.getKind()); - rewriter.replaceOpWithNewOp<vector::BroadcastOp>( - contractOp, contractOp->getResultTypes()[0], newContractOp); - return success(); + + if (maskingOp) { + auto newMask = rewriter.create<vector::ExtractOp>(loc, maskingOp.getMask(), + splatZero(dropDim)); + + newOp = mlir::vector::maskOperation(rewriter, newOp, newMask); + } + + return rewriter + .create<vector::BroadcastOp>(loc, contractOp->getResultTypes()[0], + newOp->getResults()[0]) + .getResult(); } namespace { @@ -450,12 +460,14 @@ namespace { /// 1 dimensions. Also performs tranpose of lhs and rhs operands if required /// prior to extract. struct CastAwayContractionLeadingOneDim - : public OpRewritePattern<vector::ContractionOp> { - using OpRewritePattern::OpRewritePattern; - - LogicalResult matchAndRewrite(vector::ContractionOp contractOp, - PatternRewriter &rewriter) const override { - return castAwayContractionLeadingOneDim(contractOp, rewriter); + : public MaskableOpRewritePattern<vector::ContractionOp> { + using MaskableOpRewritePattern::MaskableOpRewritePattern; + + FailureOr<Value> + matchAndRewriteMaskableOp(vector::ContractionOp contractOp, + MaskingOpInterface maskingOp, + PatternRewriter &rewriter) const override { + return castAwayContractionLeadingOneDim(contractOp, maskingOp, rewriter); } }; diff --git a/mlir/lib/Dialect/Vector/Transforms/VectorLinearize.cpp b/mlir/lib/Dialect/Vector/Transforms/VectorLinearize.cpp index 7ca03537049812dcacfbb656d6f109344eecfdcc..4fa5b8a4865b4f1ae36f64e50d4316e6e47dee30 100644 --- a/mlir/lib/Dialect/Vector/Transforms/VectorLinearize.cpp +++ b/mlir/lib/Dialect/Vector/Transforms/VectorLinearize.cpp @@ -22,9 +22,9 @@ using namespace mlir; static bool isLessThanTargetBitWidth(Operation *op, unsigned targetBitWidth) { auto resultTypes = op->getResultTypes(); for (auto resType : resultTypes) { - VectorType vecType = cast<VectorType>(resType); + VectorType vecType = dyn_cast<VectorType>(resType); // Reject index since getElementTypeBitWidth will abort for Index types. - if (vecType.getElementType().isIndex()) + if (!vecType || vecType.getElementType().isIndex()) return false; unsigned trailingVecDimBitWidth = vecType.getShape().back() * vecType.getElementTypeBitWidth(); @@ -49,6 +49,12 @@ struct LinearizeConstant final : OpConversionPattern<arith::ConstantOp> { Location loc = constOp.getLoc(); auto resType = getTypeConverter()->convertType<VectorType>(constOp.getType()); + + if (resType.isScalable() && !isa<SplatElementsAttr>(constOp.getValue())) + return rewriter.notifyMatchFailure( + loc, + "Cannot linearize a constant scalable vector that's not a splat"); + if (!resType) return rewriter.notifyMatchFailure(loc, "can't convert return type"); if (!isLessThanTargetBitWidth(constOp, targetVectorBitWidth)) @@ -104,11 +110,11 @@ void mlir::vector::populateVectorLinearizeTypeConversionsAndLegality( ConversionTarget &target, unsigned targetBitWidth) { typeConverter.addConversion([](VectorType type) -> std::optional<Type> { - // Ignore scalable vectors for now. - if (type.getRank() <= 1 || type.isScalable()) + if (!isLinearizableVector(type)) return type; - return VectorType::get(type.getNumElements(), type.getElementType()); + return VectorType::get(type.getNumElements(), type.getElementType(), + type.isScalable()); }); auto materializeCast = [](OpBuilder &builder, Type type, ValueRange inputs, diff --git a/mlir/lib/Dialect/Vector/Transforms/VectorTransforms.cpp b/mlir/lib/Dialect/Vector/Transforms/VectorTransforms.cpp index 6f6b6dcdad2006db128bb93b2fc1e0c797009e90..69c497264fd1ed6e8bdf108055a462d863e683ee 100644 --- a/mlir/lib/Dialect/Vector/Transforms/VectorTransforms.cpp +++ b/mlir/lib/Dialect/Vector/Transforms/VectorTransforms.cpp @@ -1643,10 +1643,12 @@ struct DropUnitDimFromElementwiseOps final if (!resultVectorType) return failure(); - // Check the pre-conditions. For `Elementwise` Ops all operands are - // guaranteed to have identical shapes and it suffices to only check the - // first one. - auto sourceVectorType = cast<VectorType>(op->getOperands()[0].getType()); + // Check the operand pre-conditions. For `Elementwise` ops all operands are + // guaranteed to have identical shapes (with some exceptions such as + // `arith.select`) and it suffices to only check one of them. + auto sourceVectorType = dyn_cast<VectorType>(op->getOperand(0).getType()); + if (!sourceVectorType) + return failure(); if (sourceVectorType.getRank() < 2) return failure(); diff --git a/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp b/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp index d613672608c3ad8095cf7137371ea0649bde5309..ebc6f5cbcaa9eded3a004ba8e62005ace7af1767 100644 --- a/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp +++ b/mlir/lib/Dialect/Vector/Utils/VectorUtils.cpp @@ -300,3 +300,25 @@ vector::createUnrollIterator(VectorType vType, int64_t targetRank) { shapeToUnroll = shapeToUnroll.slice(0, firstScalableDim); return StaticTileOffsetRange(shapeToUnroll, /*unrollStep=*/1); } + +SmallVector<OpFoldResult> vector::getMixedSizesXfer(bool hasTensorSemantics, + Operation *xfer, + RewriterBase &rewriter) { + auto loc = xfer->getLoc(); + + Value base = TypeSwitch<Operation *, Value>(xfer) + .Case<vector::TransferReadOp>( + [&](auto readOp) { return readOp.getSource(); }) + .Case<vector::TransferWriteOp>( + [&](auto writeOp) { return writeOp.getOperand(1); }); + + SmallVector<OpFoldResult> mixedSourceDims = + hasTensorSemantics ? tensor::getMixedSizes(rewriter, loc, base) + : memref::getMixedSizes(rewriter, loc, base); + return mixedSourceDims; +} + +bool vector::isLinearizableVector(VectorType type) { + auto numScalableDims = llvm::count(type.getScalableDims(), true); + return (type.getRank() > 1) && (numScalableDims <= 1); +} diff --git a/mlir/lib/Dialect/XeGPU/IR/CMakeLists.txt b/mlir/lib/Dialect/XeGPU/IR/CMakeLists.txt index 2e99f39ed86d2e6ac70a260d2f32a43a986285e5..617c89a84ee077104a799b00070fe51921f387bc 100644 --- a/mlir/lib/Dialect/XeGPU/IR/CMakeLists.txt +++ b/mlir/lib/Dialect/XeGPU/IR/CMakeLists.txt @@ -11,5 +11,7 @@ add_mlir_dialect_library(MLIRXeGPUDialect MLIRXeGPUEnumsIncGen LINK_LIBS PUBLIC + MLIRDialectUtils MLIRIR + MLIRViewLikeInterface ) diff --git a/mlir/lib/Dialect/XeGPU/IR/XeGPUDialect.cpp b/mlir/lib/Dialect/XeGPU/IR/XeGPUDialect.cpp index 4f839ee773476b42c26f6cb0122710c0231e9623..0b3f4b9c9dbeae06a083bc6e55f11ff836b6c280 100644 --- a/mlir/lib/Dialect/XeGPU/IR/XeGPUDialect.cpp +++ b/mlir/lib/Dialect/XeGPU/IR/XeGPUDialect.cpp @@ -6,7 +6,10 @@ // //===----------------------------------------------------------------------===// -#include <mlir/Dialect/XeGPU/IR/XeGPU.h> +#include "mlir/Dialect/XeGPU/IR/XeGPU.h" +#include "mlir/IR/Builders.h" +#include "mlir/IR/DialectImplementation.h" +#include "llvm/ADT/TypeSwitch.h" namespace mlir { namespace xegpu { @@ -26,8 +29,72 @@ void XeGPUDialect::initialize() { >(); } -// this file is for position occupation, -// we will add functions in following PRs. +//===----------------------------------------------------------------------===// +// XeGPU_TensorDescAttr +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// XeGPU_TensorDescType +//===----------------------------------------------------------------------===// +mlir::Type TensorDescType::parse(::mlir::AsmParser &parser) { + llvm::SmallVector<int64_t> shape; + mlir::Type elementType; + mlir::FailureOr<mlir::Attribute> encoding; + + // Parse literal '<' + if (parser.parseLess()) + return {}; + + auto shapeLoc = parser.getCurrentLocation(); + if (mlir::failed(parser.parseDimensionList(shape))) { + parser.emitError(shapeLoc, "failed to parse parameter 'shape'"); + return {}; + } + + auto elemTypeLoc = parser.getCurrentLocation(); + if (mlir::failed(parser.parseType(elementType))) { + parser.emitError(elemTypeLoc, "failed to parse parameter 'elementType'"); + return {}; + } + + // parse optional attributes + if (mlir::succeeded(parser.parseOptionalComma())) { + encoding = mlir::FieldParser<mlir::Attribute>::parse(parser); + if (mlir::failed(encoding)) { + parser.emitError( + parser.getCurrentLocation(), + "Failed to parse the attribute field for TensorDescType.\n"); + return {}; + } + } + + // Parse literal '>' + if (parser.parseGreater()) + return {}; + + return TensorDescType::get(parser.getContext(), shape, elementType, + encoding.value_or(mlir::Attribute())); +} + +void TensorDescType::print(::mlir::AsmPrinter &printer) const { + printer << "<"; + + auto shape = getShape(); + for (int64_t dim : shape) { + if (mlir::ShapedType::isDynamic(dim)) + printer << '?'; + else + printer << dim; + printer << 'x'; + } + + printer << getElementType(); + + if (auto encoding = getEncoding()) + printer << ", " << encoding; + + printer << ">"; +} } // namespace xegpu } // namespace mlir diff --git a/mlir/lib/Dialect/XeGPU/IR/XeGPUOps.cpp b/mlir/lib/Dialect/XeGPU/IR/XeGPUOps.cpp index 0e89ac4df6ef287005c48a625f733fac9f955799..02106f221f3233f622c9c883ca43489334845e73 100644 --- a/mlir/lib/Dialect/XeGPU/IR/XeGPUOps.cpp +++ b/mlir/lib/Dialect/XeGPU/IR/XeGPUOps.cpp @@ -6,14 +6,196 @@ // //===----------------------------------------------------------------------===// -#include <mlir/Dialect/XeGPU/IR/XeGPU.h> +#include "mlir/Dialect/Utils/StaticValueUtils.h" +#include "mlir/Dialect/XeGPU/IR/XeGPU.h" +#include "mlir/IR/Builders.h" #define DEBUG_TYPE "xegpu" namespace mlir { namespace xegpu { -// this file is for position occupation, -// we will add functions in following PRs. + +static void transpose(llvm::ArrayRef<int64_t> trans, + std::vector<int64_t> &shape) { + std::vector<int64_t> old = shape; + for (size_t i = 0; i < trans.size(); i++) + shape[i] = old[trans[i]]; +} + +template <typename T> +static std::string makeString(T array, bool breakline = false) { + std::string buf; + buf.clear(); + llvm::raw_string_ostream os(buf); + os << "["; + for (size_t i = 1; i < array.size(); i++) { + os << array[i - 1] << ", "; + if (breakline) + os << "\n\t\t"; + } + os << array.back() << "]"; + os.flush(); + return buf; +} + +//===----------------------------------------------------------------------===// +// XeGPU_CreateNdDescOp +//===----------------------------------------------------------------------===// +void CreateNdDescOp::build(OpBuilder &builder, OperationState &state, + Type tdesc, TypedValue<MemRefType> source, + llvm::ArrayRef<OpFoldResult> offsets) { + [[maybe_unused]] auto ty = source.getType(); + assert(ty.hasStaticShape() && offsets.size() == (size_t)ty.getRank()); + + llvm::SmallVector<int64_t> staticOffsets; + llvm::SmallVector<Value> dynamicOffsets; + dispatchIndexOpFoldResults(offsets, dynamicOffsets, staticOffsets); + + build(builder, state, tdesc, source, dynamicOffsets /* dynamic offsets */, + ValueRange({}) /* empty dynamic shape */, + ValueRange({}) /* empty dynamic strides */, + staticOffsets /* const offsets */, {} /* empty const shape*/, + {} /* empty const strides*/); +} + +void CreateNdDescOp::build(OpBuilder &builder, OperationState &state, + Type tdesc, TypedValue<IntegerType> source, + llvm::ArrayRef<OpFoldResult> offsets, + llvm::ArrayRef<OpFoldResult> shape, + llvm::ArrayRef<OpFoldResult> strides) { + assert(shape.size() && offsets.size() && strides.size() && + shape.size() == strides.size() && shape.size() == offsets.size()); + + llvm::SmallVector<int64_t> staticOffsets; + llvm::SmallVector<int64_t> staticShape; + llvm::SmallVector<int64_t> staticStrides; + llvm::SmallVector<Value> dynamicOffsets; + llvm::SmallVector<Value> dynamicShape; + llvm::SmallVector<Value> dynamicStrides; + + dispatchIndexOpFoldResults(offsets, dynamicOffsets, staticOffsets); + dispatchIndexOpFoldResults(shape, dynamicShape, staticShape); + dispatchIndexOpFoldResults(strides, dynamicStrides, staticOffsets); + + auto staticOffsetsAttr = builder.getDenseI64ArrayAttr(staticOffsets); + auto staticShapeAttr = builder.getDenseI64ArrayAttr(staticShape); + auto staticStridesAttr = builder.getDenseI64ArrayAttr(staticStrides); + + build(builder, state, tdesc, source, dynamicOffsets, dynamicShape, + dynamicStrides, staticOffsetsAttr, staticShapeAttr, staticStridesAttr); +} + +LogicalResult CreateNdDescOp::verify() { + auto rank = (int64_t)getMixedOffsets().size(); + bool invalidRank = (rank != 2); + bool invalidElemTy = false; + + // check source type matches the rank if it is a memref. + // It also should have the same ElementType as TensorDesc. + auto memrefTy = getSourceType().dyn_cast<MemRefType>(); + if (memrefTy) { + invalidRank |= (memrefTy.getRank() != rank); + invalidElemTy |= memrefTy.getElementType() != getElementType(); + } + + // check result type matches the rank + invalidRank = (getType().getRank() != rank); + + // mismatches among shape, strides, and offsets are + // already handeled by OffsetSizeAndStrideOpInterface. + // So they are not check here. + if (invalidRank) + return emitOpError( + "Expecting the rank of shape, strides, offsets, " + "source memref type (if source is a memref) and TensorDesc " + "should match with each other. They currenlty are 2D."); + + if (invalidElemTy) + return emitOpError("TensorDesc should have the same element " + "type with the source if it is a memref.\n"); + + return success(); +} + +//===----------------------------------------------------------------------===// +// XeGPU_LoadNdOp +//===----------------------------------------------------------------------===// +LogicalResult LoadNdOp::verify() { + auto tdescTy = getTensorDescType(); + auto valueTy = getType(); + + if (tdescTy.getRank() != 2) + return emitOpError( + "The TensorDesc for LoadNdOp should be a 2D TensorDesc."); + + if (!valueTy) + return emitOpError("Invalid result, it should be a VectorType.\n"); + + auto tdescElemTy = tdescTy.getElementType(); + auto valueElemTy = valueTy.getElementType(); + + if (tdescElemTy != valueElemTy) + return emitOpError( + "Value should have the same element type as TensorDesc."); + + auto array_len = tdescTy.getArrayLength(); + auto tdescShape = tdescTy.getShape().vec(); + auto valueShape = valueTy.getShape().vec(); + + if (getTranspose()) { + auto trans = getTranspose().value(); + if (tdescShape.size() >= trans.size()) + transpose(trans, tdescShape); + else + emitWarning("Invalid transpose attr. It is ignored."); + } + + if (getVnniAxis()) { + auto axis = getVnniAxis().value(); + auto vnni_factor = valueShape.back(); + tdescShape[axis] /= vnni_factor; + tdescShape.push_back(vnni_factor); + } + + if (array_len > 1) { + auto it = tdescShape.begin(); + tdescShape.insert(it, array_len); + } + + if (tdescShape != valueShape) + return emitOpError() << "Result shape doesn't match TensorDesc shape." + << "The expected shape is " << makeString(tdescShape) + << ". But the given shape is " + << makeString(valueShape) << ".\n"; + return success(); +} + +//===----------------------------------------------------------------------===// +// XeGPU_StoreNdOp +//===----------------------------------------------------------------------===// +LogicalResult StoreNdOp::verify() { + auto dstTy = getTensorDesc().getType(); // Tile + auto valTy = getValue().getType().cast<VectorType>(); // Vector + + if (dstTy.getRank() != 2) + return emitOpError("Expecting a 2D TensorDesc shape.\n"); + + if (!valTy) + return emitOpError("Exepcting a VectorType result.\n"); + + auto dstElemTy = dstTy.getElementType(); + auto valElemTy = valTy.getElementType(); + + if (dstElemTy != valElemTy) { + return emitOpError() << "The element type of the value should " + "match the elementtype of the TensorDesc.\n"; + } + + if (dstTy.getShape() != valTy.getShape()) + return emitOpError() + << "The result shape should match the TensorDesc shape.\n"; + return success(); +} } // namespace xegpu } // namespace mlir diff --git a/mlir/lib/ExecutionEngine/CMakeLists.txt b/mlir/lib/ExecutionEngine/CMakeLists.txt index b7e448d5417ea91cdeace60e99c2a4045a75de30..a091944b9ee7df912c4e60fec482548269ee6b81 100644 --- a/mlir/lib/ExecutionEngine/CMakeLists.txt +++ b/mlir/lib/ExecutionEngine/CMakeLists.txt @@ -97,6 +97,29 @@ add_mlir_library(MLIRExecutionEngine MLIRTargetLLVMIRExport ) +if(LLVM_BUILD_LLVM_DYLIB) + # Build a shared library for the execution engine. Some downstream projects + # use this library to build their own CPU runners while preserving dynamic + # linkage. + add_mlir_library(MLIRExecutionEngineShared + ExecutionEngine.cpp + SHARED + + EXCLUDE_FROM_LIBMLIR + + ADDITIONAL_HEADER_DIRS + ${MLIR_MAIN_INCLUDE_DIR}/mlir/ExecutionEngine + + # Ensures that all necessary dependencies are resolved. + DEPENDS + MLIRExecutionEngine + + LINK_LIBS PUBLIC + LLVM + MLIR + ) +endif() + get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS) add_mlir_library(MLIRJitRunner JitRunner.cpp diff --git a/mlir/lib/ExecutionEngine/CRunnerUtils.cpp b/mlir/lib/ExecutionEngine/CRunnerUtils.cpp index 48e4b8cd88b58e688b19c41a72da5280b8b06e51..41c619566b55df65d8dfdc7dfab14bc2d6608ea4 100644 --- a/mlir/lib/ExecutionEngine/CRunnerUtils.cpp +++ b/mlir/lib/ExecutionEngine/CRunnerUtils.cpp @@ -51,8 +51,20 @@ void stdSort(uint64_t n, V *p) { // details of our vectors. Also useful for direct LLVM IR output. extern "C" void printI64(int64_t i) { fprintf(stdout, "%" PRId64, i); } extern "C" void printU64(uint64_t u) { fprintf(stdout, "%" PRIu64, u); } -extern "C" void printF32(float f) { fprintf(stdout, "%g", f); } -extern "C" void printF64(double d) { fprintf(stdout, "%lg", d); } +extern "C" void printF32(float f) { + if (std::isnan(f) && std::signbit(f)) { + fprintf(stdout, "-nan"); + } else { + fprintf(stdout, "%g", f); + } +} +extern "C" void printF64(double d) { + if (std::isnan(d) && std::signbit(d)) { + fprintf(stdout, "-nan"); + } else { + fprintf(stdout, "%lg", d); + } +} extern "C" void printString(char const *s) { fputs(s, stdout); } extern "C" void printOpen() { fputs("( ", stdout); } extern "C" void printClose() { fputs(" )", stdout); } diff --git a/mlir/lib/ExecutionEngine/CudaRuntimeWrappers.cpp b/mlir/lib/ExecutionEngine/CudaRuntimeWrappers.cpp index b9a3429e37b885819693f9b1fa39bd70e5518120..09dc30365e37c000317b65f16e6a00216ff3749c 100644 --- a/mlir/lib/ExecutionEngine/CudaRuntimeWrappers.cpp +++ b/mlir/lib/ExecutionEngine/CudaRuntimeWrappers.cpp @@ -28,6 +28,7 @@ #endif // MLIR_ENABLE_CUDA_CUSPARSE #ifdef _WIN32 +#include <malloc.h> #define MLIR_CUDA_WRAPPERS_EXPORT __declspec(dllexport) #else #define MLIR_CUDA_WRAPPERS_EXPORT __attribute__((visibility("default"))) @@ -287,7 +288,11 @@ extern "C" MLIR_CUDA_WRAPPERS_EXPORT void mgpuMemHostRegisterMemRef(int64_t rank, StridedMemRefType<char, 1> *descriptor, int64_t elementSizeBytes) { // Only densely packed tensors are currently supported. +#ifdef _WIN32 + int64_t *denseStrides = (int64_t *)_alloca(rank * sizeof(int64_t)); +#else int64_t *denseStrides = (int64_t *)alloca(rank * sizeof(int64_t)); +#endif // _WIN32 int64_t *sizes = descriptor->sizes; for (int64_t i = rank - 1, runningStride = 1; i >= 0; i--) { denseStrides[i] = runningStride; @@ -423,24 +428,27 @@ extern "C" MLIR_CUDA_WRAPPERS_EXPORT void mgpuTensorMapEncodeTiled( elementStrides[4], interleave, swizzle, l2Promotion, oobFill); } -namespace { - -template <int rank> -void mgpuGetMemRefDataAndShape(void *raw_descriptor, char **addr, - uint64_t *globalDim) { +template <int Rank> +void mgpuGetMemRefDataAndShape(void *rawDescriptor, char **addr, + uint64_t *globalDim, uint64_t *globalStrides, + const CUtensorMapDataType tensorDataType) { auto descriptor = - reinterpret_cast<StridedMemRefType<char, rank> *>(raw_descriptor); + reinterpret_cast<StridedMemRefType<char, Rank> *>(rawDescriptor); *addr = descriptor->data; - for (int i = 0; i < rank; ++i) { - globalDim[i] = static_cast<uint64_t>(descriptor->sizes[rank - i - 1]); + for (int i = 0; i < Rank; ++i) { + globalDim[i] = static_cast<uint64_t>(descriptor->sizes[Rank - i - 1]); + } + static constexpr int elementSizeInBytes[] = {1, 2, 4, 4, 8, 8, 2, + 4, 8, 2, 4, 4, 4}; + for (int i = 0; i < Rank - 1; ++i) { + globalStrides[i] = static_cast<uint64_t>( + descriptor->strides[Rank - i - 2] * elementSizeInBytes[tensorDataType]); } } -} // namespace - extern "C" MLIR_CUDA_WRAPPERS_EXPORT void *mgpuTensorMapEncodeTiledMemref( int64_t tensorRank, // Dimensionality of tensor - void *ranked_descriptor, // Ranked MemRef descriptor + void *rankedDescriptor, // Ranked MemRef descriptor const CUtensorMapDataType tensorDataType, // Stride size (in bytes) CUtensorMapInterleave interleave, // Type of interleaved layout CUtensorMapSwizzle swizzle, // Bank swizzling pattern @@ -457,38 +465,36 @@ extern "C" MLIR_CUDA_WRAPPERS_EXPORT void *mgpuTensorMapEncodeTiledMemref( char *globalAddress = nullptr; switch (tensorRank) { case 1: - mgpuGetMemRefDataAndShape<1>(ranked_descriptor, &globalAddress, globalDim); + mgpuGetMemRefDataAndShape<1>(rankedDescriptor, &globalAddress, globalDim, + globalStrides, tensorDataType); break; case 2: - mgpuGetMemRefDataAndShape<2>(ranked_descriptor, &globalAddress, globalDim); + mgpuGetMemRefDataAndShape<2>(rankedDescriptor, &globalAddress, globalDim, + globalStrides, tensorDataType); break; case 3: - mgpuGetMemRefDataAndShape<3>(ranked_descriptor, &globalAddress, globalDim); + mgpuGetMemRefDataAndShape<3>(rankedDescriptor, &globalAddress, globalDim, + globalStrides, tensorDataType); break; case 4: - mgpuGetMemRefDataAndShape<4>(ranked_descriptor, &globalAddress, globalDim); + mgpuGetMemRefDataAndShape<4>(rankedDescriptor, &globalAddress, globalDim, + globalStrides, tensorDataType); break; case 5: - mgpuGetMemRefDataAndShape<5>(ranked_descriptor, &globalAddress, globalDim); + mgpuGetMemRefDataAndShape<5>(rankedDescriptor, &globalAddress, globalDim, + globalStrides, tensorDataType); break; default: fprintf( stderr, "'mgpuTensorMapEncodeTiledMemref' failed with 'rank is too high'\n"); - return NULL; + return nullptr; } - static const int elementSizeInBytes[] = {1, 2, 4, 4, 8, 8, 2, - 4, 8, 2, 4, 4, 4}; for (int64_t r = 0; r < tensorRank; ++r) { - elementStrides[r] = uint32_t(1); boxDim[r] = static_cast<uint32_t>(inputBoxDims[tensorRank - r - 1]); } - globalStrides[0] = globalDim[0] * elementSizeInBytes[tensorDataType]; - for (int r = 1; r < tensorRank - 1; r++) - globalStrides[r] = globalStrides[r - 1] * globalDim[r]; - ScopedContext scopedContext; mgpuTensorMapEncodeTiled(&tensorMap, tensorDataType, tensorRank32, globalAddress, globalDim, globalStrides, boxDim, diff --git a/mlir/lib/ExecutionEngine/Float16bits.cpp b/mlir/lib/ExecutionEngine/Float16bits.cpp index 841610e3c161dcec4809fc15518e148ae730d335..e5b4f18dd644b815872dad2d7828e06c3d1d0c64 100644 --- a/mlir/lib/ExecutionEngine/Float16bits.cpp +++ b/mlir/lib/ExecutionEngine/Float16bits.cpp @@ -165,7 +165,7 @@ bool operator==(const bf16 &f1, const bf16 &f2) { return f1.bits == f2.bits; } #endif #endif -#if defined(__x86_64__) +#if defined(__x86_64__) || defined(_M_X64) // On x86 bfloat16 is passed in SSE registers. Since both float and __bf16 // are passed in the same register we can use the wider type and careful casting // to conform to x86_64 psABI. This only works with the assumption that we're diff --git a/mlir/lib/ExecutionEngine/SparseTensor/Storage.cpp b/mlir/lib/ExecutionEngine/SparseTensor/Storage.cpp index aaa42a7e3a31bfd9c8de78216a8d0f76d1afa4f0..acb2d1bb5bed627f60fb3f8f6352254ae0249279 100644 --- a/mlir/lib/ExecutionEngine/SparseTensor/Storage.cpp +++ b/mlir/lib/ExecutionEngine/SparseTensor/Storage.cpp @@ -68,6 +68,14 @@ MLIR_SPARSETENSOR_FOREVERY_FIXED_O(IMPL_GETPOSITIONS) MLIR_SPARSETENSOR_FOREVERY_FIXED_O(IMPL_GETCOORDINATES) #undef IMPL_GETCOORDINATES +#define IMPL_GETCOORDINATESBUFFER(CNAME, C) \ + void SparseTensorStorageBase::getCoordinatesBuffer(std::vector<C> **, \ + uint64_t) { \ + FATAL_PIV("getCoordinatesBuffer" #CNAME); \ + } +MLIR_SPARSETENSOR_FOREVERY_FIXED_O(IMPL_GETCOORDINATESBUFFER) +#undef IMPL_GETCOORDINATESBUFFER + #define IMPL_GETVALUES(VNAME, V) \ void SparseTensorStorageBase::getValues(std::vector<V> **) { \ FATAL_PIV("getValues" #VNAME); \ diff --git a/mlir/lib/ExecutionEngine/SparseTensorRuntime.cpp b/mlir/lib/ExecutionEngine/SparseTensorRuntime.cpp index 731abcbbf1f39e77f45370659bf37ad82bd562da..f160b0f40fb0a357e35af95afc6b3e87f3c30a01 100644 --- a/mlir/lib/ExecutionEngine/SparseTensorRuntime.cpp +++ b/mlir/lib/ExecutionEngine/SparseTensorRuntime.cpp @@ -127,7 +127,7 @@ extern "C" { case Action::kPack: { \ assert(ptr && "Received nullptr for SparseTensorStorage object"); \ intptr_t *buffers = static_cast<intptr_t *>(ptr); \ - return SparseTensorStorage<P, C, V>::packFromLvlBuffers( \ + return SparseTensorStorage<P, C, V>::newFromBuffers( \ dimRank, dimSizes, lvlRank, lvlSizes, lvlTypes, dim2lvl, lvl2dim, \ dimRank, buffers); \ } \ @@ -311,6 +311,7 @@ MLIR_SPARSETENSOR_FOREVERY_V(IMPL_SPARSEVALUES) assert(v); \ aliasIntoMemref(v->size(), v->data(), *ref); \ } + #define IMPL_SPARSEPOSITIONS(PNAME, P) \ IMPL_GETOVERHEAD(sparsePositions##PNAME, P, getPositions) MLIR_SPARSETENSOR_FOREVERY_O(IMPL_SPARSEPOSITIONS) @@ -320,6 +321,12 @@ MLIR_SPARSETENSOR_FOREVERY_O(IMPL_SPARSEPOSITIONS) IMPL_GETOVERHEAD(sparseCoordinates##CNAME, C, getCoordinates) MLIR_SPARSETENSOR_FOREVERY_O(IMPL_SPARSECOORDINATES) #undef IMPL_SPARSECOORDINATES + +#define IMPL_SPARSECOORDINATESBUFFER(CNAME, C) \ + IMPL_GETOVERHEAD(sparseCoordinatesBuffer##CNAME, C, getCoordinatesBuffer) +MLIR_SPARSETENSOR_FOREVERY_O(IMPL_SPARSECOORDINATESBUFFER) +#undef IMPL_SPARSECOORDINATESBUFFER + #undef IMPL_GETOVERHEAD #define IMPL_LEXINSERT(VNAME, V) \ diff --git a/mlir/lib/IR/AffineExpr.cpp b/mlir/lib/IR/AffineExpr.cpp index 56a2d850ad3b67ef7a4b3d7c52a2d5873c4fa2ed..94562d0f15a24ac57afd5f0f7ebb391a02e37bcc 100644 --- a/mlir/lib/IR/AffineExpr.cpp +++ b/mlir/lib/IR/AffineExpr.cpp @@ -774,7 +774,8 @@ static AffineExpr simplifyMul(AffineExpr lhs, AffineExpr rhs) { return getAffineConstantExpr(lhsConst.getValue() * rhsConst.getValue(), lhs.getContext()); - assert(lhs.isSymbolicOrConstant() || rhs.isSymbolicOrConstant()); + if (!lhs.isSymbolicOrConstant() && !rhs.isSymbolicOrConstant()) + return nullptr; // Canonicalize the mul expression so that the constant/symbolic term is the // RHS. If both the lhs and rhs are symbolic, swap them if the lhs is a diff --git a/mlir/lib/IR/AffineMap.cpp b/mlir/lib/IR/AffineMap.cpp index 00a0f05b63330316c178f746ee63c6ed19ab571a..6cdc2682753fc7ac4900c60eb9a3040f91245bf4 100644 --- a/mlir/lib/IR/AffineMap.cpp +++ b/mlir/lib/IR/AffineMap.cpp @@ -359,9 +359,7 @@ bool AffineMap::isSingleConstant() const { } bool AffineMap::isConstant() const { - return llvm::all_of(getResults(), [](AffineExpr expr) { - return isa<AffineConstantExpr>(expr); - }); + return llvm::all_of(getResults(), llvm::IsaPred<AffineConstantExpr>); } int64_t AffineMap::getSingleConstantResult() const { diff --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp index e1e6d14231d9f1503d406b4f4404e5f3abfbf358..214b354c5347e93b0c09e67980e252f871a0d0fc 100644 --- a/mlir/lib/IR/MLIRContext.cpp +++ b/mlir/lib/IR/MLIRContext.cpp @@ -183,7 +183,8 @@ public: llvm::StringMap<std::unique_ptr<OperationName::Impl>> operations; /// A vector of operation info specifically for registered operations. - llvm::StringMap<RegisteredOperationName> registeredOperations; + llvm::DenseMap<TypeID, RegisteredOperationName> registeredOperations; + llvm::StringMap<RegisteredOperationName> registeredOperationsByName; /// This is a sorted container of registered operations for a deterministic /// and efficient `getRegisteredOperations` implementation. @@ -780,8 +781,8 @@ OperationName::OperationName(StringRef name, MLIRContext *context) { // Check the registered info map first. In the overwhelmingly common case, // the entry will be in here and it also removes the need to acquire any // locks. - auto registeredIt = ctxImpl.registeredOperations.find(name); - if (LLVM_LIKELY(registeredIt != ctxImpl.registeredOperations.end())) { + auto registeredIt = ctxImpl.registeredOperationsByName.find(name); + if (LLVM_LIKELY(registeredIt != ctxImpl.registeredOperationsByName.end())) { impl = registeredIt->second.impl; return; } @@ -909,10 +910,19 @@ OperationName::UnregisteredOpModel::hashProperties(OpaqueProperties prop) { //===----------------------------------------------------------------------===// std::optional<RegisteredOperationName> -RegisteredOperationName::lookup(StringRef name, MLIRContext *ctx) { +RegisteredOperationName::lookup(TypeID typeID, MLIRContext *ctx) { auto &impl = ctx->getImpl(); - auto it = impl.registeredOperations.find(name); + auto it = impl.registeredOperations.find(typeID); if (it != impl.registeredOperations.end()) + return it->second; + return std::nullopt; +} + +std::optional<RegisteredOperationName> +RegisteredOperationName::lookup(StringRef name, MLIRContext *ctx) { + auto &impl = ctx->getImpl(); + auto it = impl.registeredOperationsByName.find(name); + if (it != impl.registeredOperationsByName.end()) return it->getValue(); return std::nullopt; } @@ -945,11 +955,16 @@ void RegisteredOperationName::insert( // Update the registered info for this operation. auto emplaced = ctxImpl.registeredOperations.try_emplace( - name, RegisteredOperationName(impl)); + impl->getTypeID(), RegisteredOperationName(impl)); assert(emplaced.second && "operation name registration must be successful"); + auto emplacedByName = ctxImpl.registeredOperationsByName.try_emplace( + name, RegisteredOperationName(impl)); + (void)emplacedByName; + assert(emplacedByName.second && + "operation name registration must be successful"); // Add emplaced operation name to the sorted operations container. - RegisteredOperationName &value = emplaced.first->getValue(); + RegisteredOperationName &value = emplaced.first->second; ctxImpl.sortedRegisteredOperations.insert( llvm::upper_bound(ctxImpl.sortedRegisteredOperations, value, [](auto &lhs, auto &rhs) { diff --git a/mlir/lib/IR/Operation.cpp b/mlir/lib/IR/Operation.cpp index d6d59837d48ac8df9bbdba1cc40810fe2d0e81f8..ca5ff9f72e3e292fa50b5d74aa97113b59c2b9cb 100644 --- a/mlir/lib/IR/Operation.cpp +++ b/mlir/lib/IR/Operation.cpp @@ -1288,9 +1288,7 @@ LogicalResult OpTrait::impl::verifyNoRegionArguments(Operation *op) { } LogicalResult OpTrait::impl::verifyElementwise(Operation *op) { - auto isMappableType = [](Type type) { - return llvm::isa<VectorType, TensorType>(type); - }; + auto isMappableType = llvm::IsaPred<VectorType, TensorType>; auto resultMappableTypes = llvm::to_vector<1>( llvm::make_filter_range(op->getResultTypes(), isMappableType)); auto operandMappableTypes = llvm::to_vector<2>( diff --git a/mlir/lib/IR/PatternMatch.cpp b/mlir/lib/IR/PatternMatch.cpp index 4079ccc7567256dc8d24c59b579b6cf8f330f799..5944a0ea46a14376d32f15fc3aedc38282ca3ce4 100644 --- a/mlir/lib/IR/PatternMatch.cpp +++ b/mlir/lib/IR/PatternMatch.cpp @@ -110,6 +110,22 @@ RewriterBase::~RewriterBase() { // Out of line to provide a vtable anchor for the class. } +void RewriterBase::replaceAllOpUsesWith(Operation *from, ValueRange to) { + // Notify the listener that we're about to replace this op. + if (auto *rewriteListener = dyn_cast_if_present<Listener>(listener)) + rewriteListener->notifyOperationReplaced(from, to); + + replaceAllUsesWith(from->getResults(), to); +} + +void RewriterBase::replaceAllOpUsesWith(Operation *from, Operation *to) { + // Notify the listener that we're about to replace this op. + if (auto *rewriteListener = dyn_cast_if_present<Listener>(listener)) + rewriteListener->notifyOperationReplaced(from, to); + + replaceAllUsesWith(from->getResults(), to->getResults()); +} + /// This method replaces the results of the operation with the specified list of /// values. The number of provided values must match the number of results of /// the operation. The replaced op is erased. @@ -117,10 +133,6 @@ void RewriterBase::replaceOp(Operation *op, ValueRange newValues) { assert(op->getNumResults() == newValues.size() && "incorrect # of replacement values"); - // Notify the listener that we're about to replace this op. - if (auto *rewriteListener = dyn_cast_if_present<Listener>(listener)) - rewriteListener->notifyOperationReplaced(op, newValues); - // Replace all result uses. Also notifies the listener of modifications. replaceAllOpUsesWith(op, newValues); @@ -136,10 +148,6 @@ void RewriterBase::replaceOp(Operation *op, Operation *newOp) { assert(op->getNumResults() == newOp->getNumResults() && "ops have different number of results"); - // Notify the listener that we're about to replace this op. - if (auto *rewriteListener = dyn_cast_if_present<Listener>(listener)) - rewriteListener->notifyOperationReplaced(op, newOp); - // Replace all result uses. Also notifies the listener of modifications. replaceAllOpUsesWith(op, newOp->getResults()); diff --git a/mlir/lib/Interfaces/CMakeLists.txt b/mlir/lib/Interfaces/CMakeLists.txt index e7c76e70ed6b5d70e9103ed7f6fbeab05bce905b..d3b7bf65ad3e7394e9693fa22b2e327afb65d771 100644 --- a/mlir/lib/Interfaces/CMakeLists.txt +++ b/mlir/lib/Interfaces/CMakeLists.txt @@ -101,7 +101,20 @@ add_mlir_library(MLIRSubsetOpInterface MLIRValueBoundsOpInterface ) -add_mlir_interface_library(TilingInterface) +add_mlir_library(MLIRTilingInterface + TilingInterface.cpp + + ADDITIONAL_HEADER_DIRS + ${MLIR_MAIN_INCLUDE_DIR}/mlir/Interfaces + + DEPENDS + MLIRTilingInterfaceIncGen + MLIRDialectUtils + + LINK_LIBS PUBLIC + MLIRIR +) + add_mlir_interface_library(VectorInterfaces) add_mlir_interface_library(ViewLikeInterface) diff --git a/mlir/lib/Interfaces/DataLayoutInterfaces.cpp b/mlir/lib/Interfaces/DataLayoutInterfaces.cpp index 65c41f44192a9074f4efcdc81355b88d6e1ee29c..b5b7d78cfeff768e02828462152dc7946baf020b 100644 --- a/mlir/lib/Interfaces/DataLayoutInterfaces.cpp +++ b/mlir/lib/Interfaces/DataLayoutInterfaces.cpp @@ -218,7 +218,23 @@ uint64_t mlir::detail::getDefaultPreferredAlignment( reportMissingDataLayout(type); } -// Returns the memory space used for allocal operations if specified in the +std::optional<uint64_t> mlir::detail::getDefaultIndexBitwidth( + Type type, const DataLayout &dataLayout, + ArrayRef<DataLayoutEntryInterface> params) { + if (isa<IndexType>(type)) + return getIndexBitwidth(params); + + if (auto typeInterface = dyn_cast<DataLayoutTypeInterface>(type)) + if (std::optional<uint64_t> indexBitwidth = + typeInterface.getIndexBitwidth(dataLayout, params)) + return *indexBitwidth; + + // Return std::nullopt for all other types, which are assumed to be non + // pointer-like types. + return std::nullopt; +} + +// Returns the memory space used for alloca operations if specified in the // given entry. If the entry is empty the default memory space represented by // an empty attribute is returned. Attribute @@ -520,6 +536,18 @@ uint64_t mlir::DataLayout::getTypePreferredAlignment(Type t) const { }); } +std::optional<uint64_t> mlir::DataLayout::getTypeIndexBitwidth(Type t) const { + checkValid(); + return cachedLookup<std::optional<uint64_t>>(t, indexBitwidths, [&](Type ty) { + DataLayoutEntryList list; + if (originalLayout) + list = originalLayout.getSpecForType(ty.getTypeID()); + if (auto iface = dyn_cast_or_null<DataLayoutOpInterface>(scope)) + return iface.getIndexBitwidth(ty, *this, list); + return detail::getDefaultIndexBitwidth(ty, *this, list); + }); +} + mlir::Attribute mlir::DataLayout::getAllocaMemorySpace() const { checkValid(); if (allocaMemorySpace) diff --git a/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp b/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp index 85abc2df8947979628feec509df6f060bd7dae6b..99598f2e89d989944e4e5ed87f82edaff1ccfc3c 100644 --- a/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp +++ b/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp @@ -70,6 +70,8 @@ static std::optional<int64_t> getConstantIntValue(OpFoldResult ofr) { ValueBoundsConstraintSet::ValueBoundsConstraintSet(MLIRContext *ctx) : builder(ctx) {} +char ValueBoundsConstraintSet::ID = 0; + #ifndef NDEBUG static void assertValidValueDim(Value value, std::optional<int64_t> dim) { if (value.getType().isIndex()) { @@ -471,55 +473,87 @@ FailureOr<int64_t> ValueBoundsConstraintSet::computeConstantBound( closedUB); } +FailureOr<int64_t> ValueBoundsConstraintSet::computeConstantBound( + presburger::BoundType type, AffineMap map, ArrayRef<Value> operands, + StopConditionFn stopCondition, bool closedUB) { + ValueDimList valueDims; + for (Value v : operands) { + assert(v.getType().isIndex() && "expected index type"); + valueDims.emplace_back(v, std::nullopt); + } + return computeConstantBound(type, map, valueDims, stopCondition, closedUB); +} + FailureOr<int64_t> ValueBoundsConstraintSet::computeConstantBound( presburger::BoundType type, AffineMap map, ValueDimList operands, StopConditionFn stopCondition, bool closedUB) { assert(map.getNumResults() == 1 && "expected affine map with one result"); ValueBoundsConstraintSet cstr(map.getContext()); - int64_t pos = cstr.insert(/*isSymbol=*/false); + + int64_t pos = 0; + if (stopCondition) { + cstr.populateConstraintsSet(map, operands, stopCondition, &pos); + } else { + // No stop condition specified: Keep adding constraints until a bound could + // be computed. + cstr.populateConstraintsSet( + map, operands, + [&](Value v, std::optional<int64_t> dim) { + return cstr.cstr.getConstantBound64(type, pos).has_value(); + }, + &pos); + } + // Compute constant bound for `valueDim`. + int64_t ubAdjustment = closedUB ? 0 : 1; + if (auto bound = cstr.cstr.getConstantBound64(type, pos)) + return type == BoundType::UB ? *bound + ubAdjustment : *bound; + return failure(); +} + +int64_t ValueBoundsConstraintSet::populateConstraintsSet( + Value value, std::optional<int64_t> dim, StopConditionFn stopCondition) { +#ifndef NDEBUG + assertValidValueDim(value, dim); +#endif // NDEBUG + + AffineMap map = + AffineMap::get(/*dimCount=*/1, /*symbolCount=*/0, + Builder(value.getContext()).getAffineDimExpr(0)); + return populateConstraintsSet(map, {{value, dim}}, stopCondition); +} + +int64_t ValueBoundsConstraintSet::populateConstraintsSet( + AffineMap map, ValueDimList operands, StopConditionFn stopCondition, + int64_t *posOut) { + assert(map.getNumResults() == 1 && "expected affine map with one result"); + int64_t pos = insert(/*isSymbol=*/false); + if (posOut) + *posOut = pos; // Add map and operands to the constraint set. Dimensions are converted to // symbols. All operands are added to the worklist. auto mapper = [&](std::pair<Value, std::optional<int64_t>> v) { - return cstr.getExpr(v.first, v.second); + return getExpr(v.first, v.second); }; SmallVector<AffineExpr> dimReplacements = llvm::to_vector( llvm::map_range(ArrayRef(operands).take_front(map.getNumDims()), mapper)); SmallVector<AffineExpr> symReplacements = llvm::to_vector( llvm::map_range(ArrayRef(operands).drop_front(map.getNumDims()), mapper)); - cstr.addBound( + addBound( presburger::BoundType::EQ, pos, map.getResult(0).replaceDimsAndSymbols(dimReplacements, symReplacements)); // Process the backward slice of `operands` (i.e., reverse use-def chain) // until `stopCondition` is met. if (stopCondition) { - cstr.processWorklist(stopCondition); + processWorklist(stopCondition); } else { - // No stop condition specified: Keep adding constraints until a bound could - // be computed. - cstr.processWorklist( - /*stopCondition=*/[&](Value v, std::optional<int64_t> dim) { - return cstr.cstr.getConstantBound64(type, pos).has_value(); - }); + // No stop condition specified: Keep adding constraints until the worklist + // is empty. + processWorklist([](Value v, std::optional<int64_t> dim) { return false; }); } - // Compute constant bound for `valueDim`. - int64_t ubAdjustment = closedUB ? 0 : 1; - if (auto bound = cstr.cstr.getConstantBound64(type, pos)) - return type == BoundType::UB ? *bound + ubAdjustment : *bound; - return failure(); -} - -FailureOr<int64_t> ValueBoundsConstraintSet::computeConstantBound( - presburger::BoundType type, AffineMap map, ArrayRef<Value> operands, - StopConditionFn stopCondition, bool closedUB) { - ValueDimList valueDims; - for (Value v : operands) { - assert(v.getType().isIndex() && "expected index type"); - valueDims.emplace_back(v, std::nullopt); - } - return computeConstantBound(type, map, valueDims, stopCondition, closedUB); + return pos; } FailureOr<int64_t> @@ -681,6 +715,35 @@ ValueBoundsConstraintSet::areEquivalentSlices(MLIRContext *ctx, return true; } +void ValueBoundsConstraintSet::dump() const { + llvm::errs() << "==========\nColumns:\n"; + llvm::errs() << "(column\tdim\tvalue)\n"; + for (auto [index, valueDim] : llvm::enumerate(positionToValueDim)) { + llvm::errs() << " " << index << "\t"; + if (valueDim) { + if (valueDim->second == kIndexValue) { + llvm::errs() << "n/a\t"; + } else { + llvm::errs() << valueDim->second << "\t"; + } + llvm::errs() << getOwnerOfValue(valueDim->first)->getName() << " "; + if (OpResult result = dyn_cast<OpResult>(valueDim->first)) { + llvm::errs() << "(result " << result.getResultNumber() << ")"; + } else { + llvm::errs() << "(bbarg " + << cast<BlockArgument>(valueDim->first).getArgNumber() + << ")"; + } + llvm::errs() << "\n"; + } else { + llvm::errs() << "n/a\tn/a\n"; + } + } + llvm::errs() << "\nConstraint set:\n"; + cstr.dump(); + llvm::errs() << "==========\n"; +} + ValueBoundsConstraintSet::BoundBuilder & ValueBoundsConstraintSet::BoundBuilder::operator[](int64_t dim) { assert(!this->dim.has_value() && "dim was already set"); diff --git a/mlir/lib/Interfaces/ViewLikeInterface.cpp b/mlir/lib/Interfaces/ViewLikeInterface.cpp index 7c5905010eb413703af09d8394f57802315849eb..6d1ff03756ace92ba559729fd89465a4b37f51dc 100644 --- a/mlir/lib/Interfaces/ViewLikeInterface.cpp +++ b/mlir/lib/Interfaces/ViewLikeInterface.cpp @@ -27,7 +27,7 @@ LogicalResult mlir::verifyListOfOperandsOrIntegers(Operation *op, return op->emitError("expected ") << numElements << " " << name << " values, got " << staticVals.size(); unsigned expectedNumDynamicEntries = - llvm::count_if(staticVals, [&](int64_t staticVal) { + llvm::count_if(staticVals, [](int64_t staticVal) { return ShapedType::isDynamic(staticVal); }); if (values.size() != expectedNumDynamicEntries) diff --git a/mlir/lib/Pass/Pass.cpp b/mlir/lib/Pass/Pass.cpp index 3fb05e53866607509ac8a8e59f5a29a1e0c95aa5..57a6c20141d2c1d30e3c93adc5977e199cdcc554 100644 --- a/mlir/lib/Pass/Pass.cpp +++ b/mlir/lib/Pass/Pass.cpp @@ -60,8 +60,16 @@ Operation *PassExecutionAction::getOp() const { void Pass::anchor() {} /// Attempt to initialize the options of this pass from the given string. -LogicalResult Pass::initializeOptions(StringRef options) { - return passOptions.parseFromString(options); +LogicalResult Pass::initializeOptions( + StringRef options, + function_ref<LogicalResult(const Twine &)> errorHandler) { + std::string errStr; + llvm::raw_string_ostream os(errStr); + if (failed(passOptions.parseFromString(options, os))) { + os.flush(); + return errorHandler(errStr); + } + return success(); } /// Copy the option values from 'other', which is another instance of this diff --git a/mlir/lib/Pass/PassRegistry.cpp b/mlir/lib/Pass/PassRegistry.cpp index b0c314369190a407ab6bd3af41df395b9a454885..f8149673a4093944d992e186b78ce1b4043207f1 100644 --- a/mlir/lib/Pass/PassRegistry.cpp +++ b/mlir/lib/Pass/PassRegistry.cpp @@ -40,7 +40,7 @@ buildDefaultRegistryFn(const PassAllocatorFunction &allocator) { return [=](OpPassManager &pm, StringRef options, function_ref<LogicalResult(const Twine &)> errorHandler) { std::unique_ptr<Pass> pass = allocator(); - LogicalResult result = pass->initializeOptions(options); + LogicalResult result = pass->initializeOptions(options, errorHandler); std::optional<StringRef> pmOpName = pm.getOpName(); std::optional<StringRef> passOpName = pass->getOpName(); @@ -280,7 +280,8 @@ parseNextArg(StringRef options) { llvm_unreachable("unexpected control flow in pass option parsing"); } -LogicalResult detail::PassOptions::parseFromString(StringRef options) { +LogicalResult detail::PassOptions::parseFromString(StringRef options, + raw_ostream &errorStream) { // NOTE: `options` is modified in place to always refer to the unprocessed // part of the string. while (!options.empty()) { @@ -291,7 +292,7 @@ LogicalResult detail::PassOptions::parseFromString(StringRef options) { auto it = OptionsMap.find(key); if (it == OptionsMap.end()) { - llvm::errs() << "<Pass-Options-Parser>: no such option " << key << "\n"; + errorStream << "<Pass-Options-Parser>: no such option " << key << "\n"; return failure(); } if (llvm::cl::ProvidePositionalOption(it->second, value, 0)) diff --git a/mlir/lib/Support/ToolUtilities.cpp b/mlir/lib/Support/ToolUtilities.cpp index ee0214f3d8ac04d93082e5289c075c1445c7c973..f05b4f5c643d50880f4eae44af258801a544b0a0 100644 --- a/mlir/lib/Support/ToolUtilities.cpp +++ b/mlir/lib/Support/ToolUtilities.cpp @@ -21,22 +21,20 @@ using namespace mlir; LogicalResult mlir::splitAndProcessBuffer(std::unique_ptr<llvm::MemoryBuffer> originalBuffer, ChunkBufferHandler processChunkBuffer, - raw_ostream &os, bool enableSplitting, - bool insertMarkerInOutput) { + raw_ostream &os, llvm::StringRef inputSplitMarker, + llvm::StringRef outputSplitMarker) { // If splitting is disabled, we process the full input buffer. - if (!enableSplitting) + if (inputSplitMarker.empty()) return processChunkBuffer(std::move(originalBuffer), os); - const char splitMarkerConst[] = "// -----"; - StringRef splitMarker(splitMarkerConst); - const int splitMarkerLen = splitMarker.size(); + const int inputSplitMarkerLen = inputSplitMarker.size(); auto *origMemBuffer = originalBuffer.get(); SmallVector<StringRef, 8> rawSourceBuffers; const int checkLen = 2; // Split dropping the last checkLen chars to enable flagging near misses. origMemBuffer->getBuffer().split(rawSourceBuffers, - splitMarker.drop_back(checkLen)); + inputSplitMarker.drop_back(checkLen)); if (rawSourceBuffers.empty()) return success(); @@ -58,8 +56,9 @@ mlir::splitAndProcessBuffer(std::unique_ptr<llvm::MemoryBuffer> originalBuffer, } // Check that suffix is as expected and doesn't have any dash post. - bool expectedSuffix = buffer.starts_with(splitMarker.take_back(checkLen)) && - buffer.size() > checkLen && buffer[checkLen] != '0'; + bool expectedSuffix = + buffer.starts_with(inputSplitMarker.take_back(checkLen)) && + buffer.size() > checkLen && buffer[checkLen] != '0'; if (expectedSuffix) { sourceBuffers.push_back(prev); prev = buffer.drop_front(checkLen); @@ -69,8 +68,8 @@ mlir::splitAndProcessBuffer(std::unique_ptr<llvm::MemoryBuffer> originalBuffer, fileSourceMgr.PrintMessage(llvm::errs(), splitLoc, llvm::SourceMgr::DK_Warning, "near miss with file split marker"); - prev = StringRef(prev.data(), - prev.size() + splitMarkerLen - checkLen + buffer.size()); + prev = StringRef(prev.data(), prev.size() + inputSplitMarkerLen - + checkLen + buffer.size()); } } if (!prev.empty()) @@ -89,7 +88,7 @@ mlir::splitAndProcessBuffer(std::unique_ptr<llvm::MemoryBuffer> originalBuffer, hadFailure = true; }; llvm::interleave(sourceBuffers, os, interleaveFn, - insertMarkerInOutput ? "\n// -----\n" : ""); + (llvm::Twine(outputSplitMarker) + "\n").str()); // If any fails, then return a failure of the tool. return failure(hadFailure); diff --git a/mlir/lib/TableGen/Class.cpp b/mlir/lib/TableGen/Class.cpp index 9092adcc627c0831c21891b39292616552dff664..fedf64fd96b0d478ba5d46df80df208112282ab6 100644 --- a/mlir/lib/TableGen/Class.cpp +++ b/mlir/lib/TableGen/Class.cpp @@ -369,9 +369,7 @@ void Class::finalize() { Visibility Class::getLastVisibilityDecl() const { auto reverseDecls = llvm::reverse(declarations); - auto it = llvm::find_if(reverseDecls, [](auto &decl) { - return isa<VisibilityDeclaration>(decl); - }); + auto it = llvm::find_if(reverseDecls, llvm::IsaPred<VisibilityDeclaration>); return it == reverseDecls.end() ? (isStruct ? Visibility::Public : Visibility::Private) : cast<VisibilityDeclaration>(**it).getVisibility(); diff --git a/mlir/lib/TableGen/Format.cpp b/mlir/lib/TableGen/Format.cpp index 03f888b139f8e499362ad99d6fd56aa8c4ca17d7..65f4ad56dd158e41aaf48190ba62612fac2d46ea 100644 --- a/mlir/lib/TableGen/Format.cpp +++ b/mlir/lib/TableGen/Format.cpp @@ -203,7 +203,8 @@ FmtStrVecObject::FmtStrVecObject(StringRef fmt, const FmtContext *ctx, : FmtObjectBase(fmt, ctx, params.size()) { parameters.reserve(params.size()); for (std::string p : params) - parameters.push_back(llvm::detail::build_format_adapter(std::move(p))); + parameters.push_back( + llvm::support::detail::build_format_adapter(std::move(p))); adapters.reserve(parameters.size()); for (auto &p : parameters) diff --git a/mlir/lib/Target/Cpp/CMakeLists.txt b/mlir/lib/Target/Cpp/CMakeLists.txt index d8f372cf162453800dccd45e308028318483c3a9..578cb2f22767aa4e0e591f7e6bba49b0b92904cb 100644 --- a/mlir/lib/Target/Cpp/CMakeLists.txt +++ b/mlir/lib/Target/Cpp/CMakeLists.txt @@ -10,8 +10,6 @@ add_mlir_translation_library(MLIRTargetCpp MLIREmitCDialect MLIRFuncDialect MLIRIR - MLIRMathDialect - MLIRSCFDialect MLIRSupport MLIRTranslateLib ) diff --git a/mlir/lib/Target/Cpp/TranslateRegistration.cpp b/mlir/lib/Target/Cpp/TranslateRegistration.cpp index 4104b177d7d9afbd82f9ff05eb0e0182bde56d88..1aa98834a73f49f0d9738c61ff0fd12dddc261cf 100644 --- a/mlir/lib/Target/Cpp/TranslateRegistration.cpp +++ b/mlir/lib/Target/Cpp/TranslateRegistration.cpp @@ -9,8 +9,6 @@ #include "mlir/Dialect/ControlFlow/IR/ControlFlow.h" #include "mlir/Dialect/EmitC/IR/EmitC.h" #include "mlir/Dialect/Func/IR/FuncOps.h" -#include "mlir/Dialect/Math/IR/Math.h" -#include "mlir/Dialect/SCF/IR/SCF.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/IR/Dialect.h" #include "mlir/Target/Cpp/CppEmitter.h" @@ -42,9 +40,7 @@ void registerToCppTranslation() { // clang-format off registry.insert<cf::ControlFlowDialect, emitc::EmitCDialect, - func::FuncDialect, - math::MathDialect, - scf::SCFDialect>(); + func::FuncDialect>(); // clang-format on }); } diff --git a/mlir/lib/Target/Cpp/TranslateToCpp.cpp b/mlir/lib/Target/Cpp/TranslateToCpp.cpp index 7cbb1e9265e174948911128bbf0e0c868dd4efc5..0b07b4b06dfc71fa2ac90393a05a3d4557b66441 100644 --- a/mlir/lib/Target/Cpp/TranslateToCpp.cpp +++ b/mlir/lib/Target/Cpp/TranslateToCpp.cpp @@ -18,11 +18,13 @@ #include "mlir/Support/LLVM.h" #include "mlir/Target/Cpp/CppEmitter.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/ScopedHashTable.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/TypeSwitch.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FormatVariadic.h" +#include <stack> #include <utility> #define DEBUG_TYPE "translate-to-cpp" @@ -172,6 +174,9 @@ struct CppEmitter { /// Return the existing or a new name for a Value. StringRef getOrCreateName(Value val); + // Returns the textual representation of a subscript operation. + std::string getSubscriptName(emitc::SubscriptOp op); + /// Return the existing or a new label of a Block. StringRef getOrCreateName(Block &block); @@ -341,8 +346,7 @@ static LogicalResult printOperation(CppEmitter &emitter, static LogicalResult printOperation(CppEmitter &emitter, emitc::AssignOp assignOp) { - auto variableOp = cast<emitc::VariableOp>(assignOp.getVar().getDefiningOp()); - OpResult result = variableOp->getResult(0); + OpResult result = assignOp.getVar().getDefiningOp()->getResult(0); if (failed(emitter.emitVariableAssignment(result))) return failure(); @@ -350,6 +354,13 @@ static LogicalResult printOperation(CppEmitter &emitter, return emitter.emitOperand(assignOp.getValue()); } +static LogicalResult printOperation(CppEmitter &emitter, + emitc::SubscriptOp subscriptOp) { + // Add name to cache so that `hasValueInScope` works. + emitter.getOrCreateName(subscriptOp.getResult()); + return success(); +} + static LogicalResult printBinaryOperation(CppEmitter &emitter, Operation *operation, StringRef binaryOperator) { @@ -989,8 +1000,7 @@ static LogicalResult printOperation(CppEmitter &emitter, "with multiple blocks needs variables declared at top"); } - if (llvm::any_of(functionOp.getResultTypes(), - [](Type type) { return isa<ArrayType>(type); })) { + if (llvm::any_of(functionOp.getResultTypes(), llvm::IsaPred<ArrayType>)) { return functionOp.emitOpError() << "cannot emit array type as result type"; } @@ -1091,12 +1101,28 @@ CppEmitter::CppEmitter(raw_ostream &os, bool declareVariablesAtTop) labelInScopeCount.push(0); } +std::string CppEmitter::getSubscriptName(emitc::SubscriptOp op) { + std::string out; + llvm::raw_string_ostream ss(out); + ss << getOrCreateName(op.getArray()); + for (auto index : op.getIndices()) { + ss << "[" << getOrCreateName(index) << "]"; + } + return out; +} + /// Return the existing or a new name for a Value. StringRef CppEmitter::getOrCreateName(Value val) { if (auto literal = dyn_cast_if_present<emitc::LiteralOp>(val.getDefiningOp())) return literal.getValue(); - if (!valueMapper.count(val)) - valueMapper.insert(val, formatv("v{0}", ++valueInScopeCount.top())); + if (!valueMapper.count(val)) { + if (auto subscript = + dyn_cast_if_present<emitc::SubscriptOp>(val.getDefiningOp())) { + valueMapper.insert(val, getSubscriptName(subscript)); + } else { + valueMapper.insert(val, formatv("v{0}", ++valueInScopeCount.top())); + } + } return *valueMapper.begin(val); } @@ -1144,17 +1170,16 @@ LogicalResult CppEmitter::emitAttribute(Location loc, Attribute attr) { SmallString<128> strValue; // Use default values of toString except don't truncate zeros. val.toString(strValue, 0, 0, false); + os << strValue; switch (llvm::APFloatBase::SemanticsToEnum(val.getSemantics())) { case llvm::APFloatBase::S_IEEEsingle: - os << "(float)"; + os << "f"; break; case llvm::APFloatBase::S_IEEEdouble: - os << "(double)"; break; default: - break; + llvm_unreachable("unsupported floating point type"); }; - os << strValue; } else if (val.isNaN()) { os << "NAN"; } else if (val.isInfinity()) { @@ -1166,10 +1191,18 @@ LogicalResult CppEmitter::emitAttribute(Location loc, Attribute attr) { // Print floating point attributes. if (auto fAttr = dyn_cast<FloatAttr>(attr)) { + if (!isa<Float32Type, Float64Type>(fAttr.getType())) { + return emitError(loc, + "expected floating point attribute to be f32 or f64"); + } printFloat(fAttr.getValue()); return success(); } if (auto dense = dyn_cast<DenseFPElementsAttr>(attr)) { + if (!isa<Float32Type, Float64Type>(dense.getElementType())) { + return emitError(loc, + "expected floating point attribute to be f32 or f64"); + } os << '{'; interleaveComma(dense, os, [&](const APFloat &val) { printFloat(val); }); os << '}'; @@ -1336,6 +1369,8 @@ LogicalResult CppEmitter::emitVariableAssignment(OpResult result) { LogicalResult CppEmitter::emitVariableDeclaration(OpResult result, bool trailingSemicolon) { + if (isa<emitc::SubscriptOp>(result.getDefiningOp())) + return success(); if (hasValueInScope(result)) { return result.getDefiningOp()->emitError( "result variable for the operation already declared"); @@ -1411,7 +1446,7 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) { emitc::DivOp, emitc::ExpressionOp, emitc::ForOp, emitc::FuncOp, emitc::IfOp, emitc::IncludeOp, emitc::LogicalAndOp, emitc::LogicalNotOp, emitc::LogicalOrOp, emitc::MulOp, - emitc::RemOp, emitc::ReturnOp, emitc::SubOp, + emitc::RemOp, emitc::ReturnOp, emitc::SubOp, emitc::SubscriptOp, emitc::UnaryMinusOp, emitc::UnaryPlusOp, emitc::VariableOp, emitc::VerbatimOp>( [&](auto op) { return printOperation(*this, op); }) @@ -1426,7 +1461,7 @@ LogicalResult CppEmitter::emitOperation(Operation &op, bool trailingSemicolon) { if (failed(status)) return failure(); - if (isa<emitc::LiteralOp>(op)) + if (isa<emitc::LiteralOp, emitc::SubscriptOp>(op)) return success(); if (getEmittedExpression() || @@ -1540,7 +1575,7 @@ LogicalResult CppEmitter::emitTypes(Location loc, ArrayRef<Type> types) { } LogicalResult CppEmitter::emitTupleType(Location loc, ArrayRef<Type> types) { - if (llvm::any_of(types, [](Type type) { return isa<ArrayType>(type); })) { + if (llvm::any_of(types, llvm::IsaPred<ArrayType>)) { return emitError(loc, "cannot emit tuple of array type"); } os << "std::tuple<"; diff --git a/mlir/lib/Target/LLVMIR/DebugImporter.cpp b/mlir/lib/Target/LLVMIR/DebugImporter.cpp index c631617f973544e84ae840c3cf5fd750a5451be6..779ad26fc847e690f82187cea5a10a25be8943ed 100644 --- a/mlir/lib/Target/LLVMIR/DebugImporter.cpp +++ b/mlir/lib/Target/LLVMIR/DebugImporter.cpp @@ -13,6 +13,7 @@ #include "mlir/IR/Location.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" +#include "llvm/ADT/TypeSwitch.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DebugInfoMetadata.h" @@ -51,10 +52,9 @@ DICompileUnitAttr DebugImporter::translateImpl(llvm::DICompileUnit *node) { std::optional<DIEmissionKind> emissionKind = symbolizeDIEmissionKind(node->getEmissionKind()); return DICompileUnitAttr::get( - context, DistinctAttr::create(UnitAttr::get(context)), - node->getSourceLanguage(), translate(node->getFile()), - getStringAttrOrNull(node->getRawProducer()), node->isOptimized(), - emissionKind.value()); + context, getOrCreateDistinctID(node), node->getSourceLanguage(), + translate(node->getFile()), getStringAttrOrNull(node->getRawProducer()), + node->isOptimized(), emissionKind.value()); } DICompositeTypeAttr DebugImporter::translateImpl(llvm::DICompositeType *node) { @@ -64,11 +64,7 @@ DICompositeTypeAttr DebugImporter::translateImpl(llvm::DICompositeType *node) { assert(element && "expected a non-null element type"); elements.push_back(translate(element)); } - // Drop the elements parameter if a cyclic dependency is detected. We - // currently cannot model these cycles and thus drop the parameter if - // required. A cyclic dependency is detected if one of the element nodes - // translates to a nullptr since the node is already on the translation stack. - // TODO: Support debug metadata with cyclic dependencies. + // Drop the elements parameter if any of the elements are invalid. if (llvm::is_contained(elements, nullptr)) elements.clear(); DITypeAttr baseType = translate(node->getBaseType()); @@ -77,21 +73,24 @@ DICompositeTypeAttr DebugImporter::translateImpl(llvm::DICompositeType *node) { if (node->getTag() == llvm::dwarf::DW_TAG_array_type && !baseType) return nullptr; return DICompositeTypeAttr::get( - context, node->getTag(), getStringAttrOrNull(node->getRawName()), - translate(node->getFile()), node->getLine(), translate(node->getScope()), - baseType, flags.value_or(DIFlags::Zero), node->getSizeInBits(), + context, node->getTag(), /*recId=*/{}, + getStringAttrOrNull(node->getRawName()), translate(node->getFile()), + node->getLine(), translate(node->getScope()), baseType, + flags.value_or(DIFlags::Zero), node->getSizeInBits(), node->getAlignInBits(), elements); } DIDerivedTypeAttr DebugImporter::translateImpl(llvm::DIDerivedType *node) { - // Return nullptr if the base type is a cyclic dependency. + // Return nullptr if the base type is invalid. DITypeAttr baseType = translate(node->getBaseType()); if (node->getBaseType() && !baseType) return nullptr; + DINodeAttr extraData = + translate(dyn_cast_or_null<llvm::DINode>(node->getExtraData())); return DIDerivedTypeAttr::get( context, node->getTag(), getStringAttrOrNull(node->getRawName()), baseType, node->getSizeInBits(), node->getAlignInBits(), - node->getOffsetInBits()); + node->getOffsetInBits(), extraData); } DIFileAttr DebugImporter::translateImpl(llvm::DIFile *node) { @@ -179,13 +178,14 @@ DISubprogramAttr DebugImporter::translateImpl(llvm::DISubprogram *node) { // Only definitions require a distinct identifier. mlir::DistinctAttr id; if (node->isDistinct()) - id = DistinctAttr::create(UnitAttr::get(context)); - std::optional<DISubprogramFlags> subprogramFlags = - symbolizeDISubprogramFlags(node->getSubprogram()->getSPFlags()); - // Return nullptr if the scope or type is a cyclic dependency. + id = getOrCreateDistinctID(node); + // Return nullptr if the scope or type is invalid. DIScopeAttr scope = translate(node->getScope()); if (node->getScope() && !scope) return nullptr; + std::optional<DISubprogramFlags> subprogramFlags = + symbolizeDISubprogramFlags(node->getSubprogram()->getSPFlags()); + assert(subprogramFlags && "expected valid subprogram flags"); DISubroutineTypeAttr type = translate(node->getType()); if (node->getType() && !type) return nullptr; @@ -193,8 +193,7 @@ DISubprogramAttr DebugImporter::translateImpl(llvm::DISubprogram *node) { getStringAttrOrNull(node->getRawName()), getStringAttrOrNull(node->getRawLinkageName()), translate(node->getFile()), node->getLine(), - node->getScopeLine(), subprogramFlags.value(), - type); + node->getScopeLine(), *subprogramFlags, type); } DISubrangeAttr DebugImporter::translateImpl(llvm::DISubrange *node) { @@ -229,7 +228,7 @@ DebugImporter::translateImpl(llvm::DISubroutineType *node) { } types.push_back(translate(type)); } - // Return nullptr if any of the types is a cyclic dependency. + // Return nullptr if any of the types is invalid. if (llvm::is_contained(types, nullptr)) return nullptr; return DISubroutineTypeAttr::get(context, node->getCC(), types); @@ -247,12 +246,42 @@ DINodeAttr DebugImporter::translate(llvm::DINode *node) { if (DINodeAttr attr = nodeToAttr.lookup(node)) return attr; - // Return nullptr if a cyclic dependency is detected since the same node is - // being traversed twice. This check avoids infinite recursion if the debug - // metadata contains cycles. - if (!translationStack.insert(node)) - return nullptr; - auto guard = llvm::make_scope_exit([&]() { translationStack.pop_back(); }); + // If the node type is capable of being recursive, check if it's seen before. + auto recSelfCtor = getRecSelfConstructor(node); + if (recSelfCtor) { + // If a cyclic dependency is detected since the same node is being traversed + // twice, emit a recursive self type, and mark the duplicate node on the + // translationStack so it can emit a recursive decl type. + auto [iter, inserted] = translationStack.try_emplace(node, nullptr); + if (!inserted) { + // The original node may have already been assigned a recursive ID from + // a different self-reference. Use that if possible. + DistinctAttr recId = iter->second; + if (!recId) { + recId = DistinctAttr::create(UnitAttr::get(context)); + iter->second = recId; + } + unboundRecursiveSelfRefs.back().insert(recId); + return cast<DINodeAttr>(recSelfCtor(recId)); + } + } + + unboundRecursiveSelfRefs.emplace_back(); + + auto guard = llvm::make_scope_exit([&]() { + if (recSelfCtor) + translationStack.pop_back(); + + // Copy unboundRecursiveSelfRefs down to the previous level. + if (unboundRecursiveSelfRefs.size() == 1) + assert(unboundRecursiveSelfRefs.back().empty() && + "internal error: unbound recursive self reference at top level."); + else + unboundRecursiveSelfRefs[unboundRecursiveSelfRefs.size() - 2].insert( + unboundRecursiveSelfRefs.back().begin(), + unboundRecursiveSelfRefs.back().end()); + unboundRecursiveSelfRefs.pop_back(); + }); // Convert the debug metadata if possible. auto translateNode = [this](llvm::DINode *node) -> DINodeAttr { @@ -289,7 +318,19 @@ DINodeAttr DebugImporter::translate(llvm::DINode *node) { return nullptr; }; if (DINodeAttr attr = translateNode(node)) { - nodeToAttr.insert({node, attr}); + // If this node was marked as recursive, set its recId. + if (auto recType = dyn_cast<DIRecursiveTypeAttrInterface>(attr)) { + if (DistinctAttr recId = translationStack.lookup(node)) { + attr = cast<DINodeAttr>(recType.withRecId(recId)); + // Remove the unbound recursive ID from the set of unbound self + // references in the translation stack. + unboundRecursiveSelfRefs.back().erase(recId); + } + } + + // Only cache fully self-contained nodes. + if (unboundRecursiveSelfRefs.back().empty()) + nodeToAttr.try_emplace(node, attr); return attr; } return nullptr; @@ -346,3 +387,20 @@ StringAttr DebugImporter::getStringAttrOrNull(llvm::MDString *stringNode) { return StringAttr(); return StringAttr::get(context, stringNode->getString()); } + +DistinctAttr DebugImporter::getOrCreateDistinctID(llvm::DINode *node) { + DistinctAttr &id = nodeToDistinctAttr[node]; + if (!id) + id = DistinctAttr::create(UnitAttr::get(context)); + return id; +} + +function_ref<DIRecursiveTypeAttrInterface(DistinctAttr)> +DebugImporter::getRecSelfConstructor(llvm::DINode *node) { + using CtorType = function_ref<DIRecursiveTypeAttrInterface(DistinctAttr)>; + return TypeSwitch<llvm::DINode *, CtorType>(node) + .Case([&](llvm::DICompositeType *concreteNode) { + return CtorType(DICompositeTypeAttr::getRecSelf); + }) + .Default(CtorType()); +} diff --git a/mlir/lib/Target/LLVMIR/DebugImporter.h b/mlir/lib/Target/LLVMIR/DebugImporter.h index 7d4a371284b68b87728f9a07bc2426dce2d61b57..bcf628fc4234fbeae3a2ca1c7f62c37e3d3c5f22 100644 --- a/mlir/lib/Target/LLVMIR/DebugImporter.h +++ b/mlir/lib/Target/LLVMIR/DebugImporter.h @@ -82,12 +82,28 @@ private: /// null attribute otherwise. StringAttr getStringAttrOrNull(llvm::MDString *stringNode); + /// Get the DistinctAttr used to represent `node` if one was already created + /// for it, or create a new one if not. + DistinctAttr getOrCreateDistinctID(llvm::DINode *node); + + /// Get the `getRecSelf` constructor for the translated type of `node` if its + /// translated DITypeAttr supports recursion. Otherwise, returns nullptr. + function_ref<DIRecursiveTypeAttrInterface(DistinctAttr)> + getRecSelfConstructor(llvm::DINode *node); + /// A mapping between LLVM debug metadata and the corresponding attribute. DenseMap<llvm::DINode *, DINodeAttr> nodeToAttr; + /// A mapping between distinct LLVM debug metadata nodes and the corresponding + /// distinct id attribute. + DenseMap<llvm::DINode *, DistinctAttr> nodeToDistinctAttr; /// A stack that stores the metadata nodes that are being traversed. The stack /// is used to detect cyclic dependencies during the metadata translation. - SetVector<llvm::DINode *> translationStack; + /// A node is pushed with a null value. If it is ever seen twice, it is given + /// a recursive id attribute, indicating that it is a recursive node. + llvm::MapVector<llvm::DINode *, DistinctAttr> translationStack; + /// All the unbound recursive self references in the translation stack. + SmallVector<DenseSet<DistinctAttr>> unboundRecursiveSelfRefs; MLIRContext *context; ModuleOp mlirModule; diff --git a/mlir/lib/Target/LLVMIR/DebugTranslation.cpp b/mlir/lib/Target/LLVMIR/DebugTranslation.cpp index 16918aab549788f833bd22075df3e38168570381..642359a23756aff72be5b3a5843fd3faa21b7163 100644 --- a/mlir/lib/Target/LLVMIR/DebugTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/DebugTranslation.cpp @@ -116,12 +116,20 @@ static DINodeT *getDistinctOrUnique(bool isDistinct, Ts &&...args) { return DINodeT::get(std::forward<Ts>(args)...); } +llvm::TempDICompositeType +DebugTranslation::translateTemporaryImpl(DICompositeTypeAttr attr) { + return llvm::DICompositeType::getTemporary( + llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()), nullptr, + attr.getLine(), nullptr, nullptr, attr.getSizeInBits(), + attr.getAlignInBits(), + /*OffsetInBits=*/0, + /*Flags=*/static_cast<llvm::DINode::DIFlags>(attr.getFlags()), + /*Elements=*/nullptr, /*RuntimeLang=*/0, + /*VTableHolder=*/nullptr); +} + llvm::DICompositeType * DebugTranslation::translateImpl(DICompositeTypeAttr attr) { - SmallVector<llvm::Metadata *> elements; - for (auto member : attr.getElements()) - elements.push_back(translate(member)); - // TODO: Use distinct attributes to model this, once they have landed. // Depending on the tag, composite types must be distinct. bool isDistinct = false; @@ -133,6 +141,10 @@ DebugTranslation::translateImpl(DICompositeTypeAttr attr) { isDistinct = true; } + SmallVector<llvm::Metadata *> elements; + for (DINodeAttr member : attr.getElements()) + elements.push_back(translate(member)); + return getDistinctOrUnique<llvm::DICompositeType>( isDistinct, llvmCtx, attr.getTag(), getMDStringOrNull(attr.getName()), translate(attr.getFile()), attr.getLine(), translate(attr.getScope()), @@ -150,7 +162,8 @@ llvm::DIDerivedType *DebugTranslation::translateImpl(DIDerivedTypeAttr attr) { /*File=*/nullptr, /*Line=*/0, /*Scope=*/nullptr, translate(attr.getBaseType()), attr.getSizeInBits(), attr.getAlignInBits(), attr.getOffsetInBits(), - /*DWARFAddressSpace=*/std::nullopt, /*Flags=*/llvm::DINode::FlagZero); + /*DWARFAddressSpace=*/std::nullopt, /*PtrAuthData=*/std::nullopt, + /*Flags=*/llvm::DINode::FlagZero, translate(attr.getExtraData())); } llvm::DIFile *DebugTranslation::translateImpl(DIFileAttr attr) { @@ -200,22 +213,76 @@ DebugTranslation::translateImpl(DIGlobalVariableAttr attr) { attr.getIsDefined(), nullptr, nullptr, attr.getAlignInBits(), nullptr); } +llvm::DIType * +DebugTranslation::translateRecursive(DIRecursiveTypeAttrInterface attr) { + DistinctAttr recursiveId = attr.getRecId(); + if (attr.isRecSelf()) { + auto *iter = recursiveTypeMap.find(recursiveId); + assert(iter != recursiveTypeMap.end() && "unbound DI recursive self type"); + return iter->second; + } + + auto setRecursivePlaceholder = [&](llvm::DIType *placeholder) { + [[maybe_unused]] auto [iter, inserted] = + recursiveTypeMap.try_emplace(recursiveId, placeholder); + (void)iter; + (void)inserted; + assert(inserted && "illegal reuse of recursive id"); + }; + + llvm::DIType *result = + TypeSwitch<DIRecursiveTypeAttrInterface, llvm::DIType *>(attr) + .Case<DICompositeTypeAttr>([&](auto attr) { + auto temporary = translateTemporaryImpl(attr); + setRecursivePlaceholder(temporary.get()); + // Must call `translateImpl` directly instead of `translate` to + // avoid handling the recursive interface again. + auto *concrete = translateImpl(attr); + temporary->replaceAllUsesWith(concrete); + return concrete; + }); + + assert(recursiveTypeMap.back().first == recursiveId && + "internal inconsistency: unexpected recursive translation stack"); + recursiveTypeMap.pop_back(); + + return result; +} + llvm::DIScope *DebugTranslation::translateImpl(DIScopeAttr attr) { return cast<llvm::DIScope>(translate(DINodeAttr(attr))); } llvm::DISubprogram *DebugTranslation::translateImpl(DISubprogramAttr attr) { + if (auto iter = distinctAttrToNode.find(attr.getId()); + iter != distinctAttrToNode.end()) + return cast<llvm::DISubprogram>(iter->second); + + llvm::DIScope *scope = translate(attr.getScope()); + llvm::DIFile *file = translate(attr.getFile()); + llvm::DIType *type = translate(attr.getType()); + llvm::DICompileUnit *compileUnit = translate(attr.getCompileUnit()); + + // Check again after recursive calls in case this distinct node recurses back + // to itself. + if (auto iter = distinctAttrToNode.find(attr.getId()); + iter != distinctAttrToNode.end()) + return cast<llvm::DISubprogram>(iter->second); + bool isDefinition = static_cast<bool>(attr.getSubprogramFlags() & LLVM::DISubprogramFlags::Definition); - return getDistinctOrUnique<llvm::DISubprogram>( - isDefinition, llvmCtx, translate(attr.getScope()), - getMDStringOrNull(attr.getName()), - getMDStringOrNull(attr.getLinkageName()), translate(attr.getFile()), - attr.getLine(), translate(attr.getType()), attr.getScopeLine(), + llvm::DISubprogram *node = getDistinctOrUnique<llvm::DISubprogram>( + isDefinition, llvmCtx, scope, getMDStringOrNull(attr.getName()), + getMDStringOrNull(attr.getLinkageName()), file, attr.getLine(), type, + attr.getScopeLine(), /*ContainingType=*/nullptr, /*VirtualIndex=*/0, /*ThisAdjustment=*/0, llvm::DINode::FlagZero, static_cast<llvm::DISubprogram::DISPFlags>(attr.getSubprogramFlags()), - translate(attr.getCompileUnit())); + compileUnit); + + if (attr.getId()) + distinctAttrToNode.try_emplace(attr.getId(), node); + return node; } llvm::DIModule *DebugTranslation::translateImpl(DIModuleAttr attr) { @@ -268,15 +335,23 @@ llvm::DINode *DebugTranslation::translate(DINodeAttr attr) { if (llvm::DINode *node = attrToNode.lookup(attr)) return node; - llvm::DINode *node = - TypeSwitch<DINodeAttr, llvm::DINode *>(attr) - .Case<DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr, - DIDerivedTypeAttr, DIFileAttr, DIGlobalVariableAttr, - DILabelAttr, DILexicalBlockAttr, DILexicalBlockFileAttr, - DILocalVariableAttr, DIModuleAttr, DINamespaceAttr, - DINullTypeAttr, DISubprogramAttr, DISubrangeAttr, - DISubroutineTypeAttr>( - [&](auto attr) { return translateImpl(attr); }); + llvm::DINode *node = nullptr; + // Recursive types go through a dedicated handler. All other types are + // dispatched directly to their specific handlers. + if (auto recTypeAttr = dyn_cast<DIRecursiveTypeAttrInterface>(attr)) + if (recTypeAttr.getRecId()) + node = translateRecursive(recTypeAttr); + + if (!node) + node = TypeSwitch<DINodeAttr, llvm::DINode *>(attr) + .Case<DIBasicTypeAttr, DICompileUnitAttr, DICompositeTypeAttr, + DIDerivedTypeAttr, DIFileAttr, DIGlobalVariableAttr, + DILabelAttr, DILexicalBlockAttr, DILexicalBlockFileAttr, + DILocalVariableAttr, DIModuleAttr, DINamespaceAttr, + DINullTypeAttr, DISubprogramAttr, DISubrangeAttr, + DISubroutineTypeAttr>( + [&](auto attr) { return translateImpl(attr); }); + attrToNode.insert({attr, node}); return node; } diff --git a/mlir/lib/Target/LLVMIR/DebugTranslation.h b/mlir/lib/Target/LLVMIR/DebugTranslation.h index 627c68468449837c25127f8e0f3e60b05303fedd..c7a5228cbf5e920ba8c48bbec5b3ad2fe223e59d 100644 --- a/mlir/lib/Target/LLVMIR/DebugTranslation.h +++ b/mlir/lib/Target/LLVMIR/DebugTranslation.h @@ -88,6 +88,17 @@ private: llvm::DISubroutineType *translateImpl(DISubroutineTypeAttr attr); llvm::DIType *translateImpl(DITypeAttr attr); + /// Attributes that support self recursion need to implement an additional + /// method to hook into `translateRecursive`. + /// - `<temp llvm type> translateTemporaryImpl(<mlir type>)`: + /// Create a temporary translation of the DI attr without recursively + /// translating any nested DI attrs. + llvm::DIType *translateRecursive(DIRecursiveTypeAttrInterface attr); + + /// Translate the given attribute to a temporary llvm debug metadata of the + /// corresponding type. + llvm::TempDICompositeType translateTemporaryImpl(DICompositeTypeAttr attr); + /// Constructs a string metadata node from the string attribute. Returns /// nullptr if `stringAttr` is null or contains and empty string. llvm::MDString *getMDStringOrNull(StringAttr stringAttr); @@ -102,6 +113,14 @@ private: /// metadata. DenseMap<Attribute, llvm::DINode *> attrToNode; + /// A mapping between recursive ID and the translated DIType. + llvm::MapVector<DistinctAttr, llvm::DIType *> recursiveTypeMap; + + /// A mapping between a distinct ID and the translated LLVM metadata node. + /// This helps identify attrs that should translate into the same LLVM debug + /// node. + DenseMap<DistinctAttr, llvm::DINode *> distinctAttrToNode; + /// A mapping between filename and llvm debug file. /// TODO: Change this to DenseMap<Identifier, ...> when we can /// access the Identifier filename in FileLineColLoc. diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp index bef227f2c583ed511d7c9d135519fe946d88b38e..646d0ed73084adff1eddc6bf8e52b68ddb5b36bd 100644 --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -331,10 +331,10 @@ convertOmpCritical(Operation &opInst, llvm::IRBuilderBase &builder, /// Returns a reduction declaration that corresponds to the given reduction /// operation in the given container. Currently only supports reductions inside -/// WsLoopOp and ParallelOp but can be easily extended as long as the given +/// WsloopOp and ParallelOp but can be easily extended as long as the given /// construct implements getNumReductionVars. template <typename T> -static std::optional<omp::ReductionDeclareOp> +static std::optional<omp::DeclareReductionOp> findReductionDeclInContainer(T container, omp::ReductionOp reduction) { for (unsigned i = 0, e = container.getNumReductionVars(); i < e; ++i) { if (container.getReductionVars()[i] != reduction.getAccumulator()) @@ -343,7 +343,7 @@ findReductionDeclInContainer(T container, omp::ReductionOp reduction) { SymbolRefAttr reductionSymbol = cast<SymbolRefAttr>((*container.getReductions())[i]); auto declareOp = - SymbolTable::lookupNearestSymbolFrom<omp::ReductionDeclareOp>( + SymbolTable::lookupNearestSymbolFrom<omp::DeclareReductionOp>( container, reductionSymbol); return declareOp; } @@ -352,16 +352,16 @@ findReductionDeclInContainer(T container, omp::ReductionOp reduction) { /// Searches for a reduction in a provided region and the regions /// it is nested in -static omp::ReductionDeclareOp findReductionDecl(Operation &containerOp, +static omp::DeclareReductionOp findReductionDecl(Operation &containerOp, omp::ReductionOp reduction) { - std::optional<omp::ReductionDeclareOp> declareOp = std::nullopt; + std::optional<omp::DeclareReductionOp> declareOp = std::nullopt; Operation *container = &containerOp; while (!declareOp.has_value() && container) { // Check if current container is supported for reductions searches if (auto par = dyn_cast<omp::ParallelOp>(*container)) { declareOp = findReductionDeclInContainer(par, reduction); - } else if (auto loop = dyn_cast<omp::WsLoopOp>(*container)) { + } else if (auto loop = dyn_cast<omp::WsloopOp>(*container)) { declareOp = findReductionDeclInContainer(loop, reduction); } else { break; @@ -381,7 +381,7 @@ static omp::ReductionDeclareOp findReductionDecl(Operation &containerOp, template <typename T> static void collectReductionDecls(T loop, - SmallVectorImpl<omp::ReductionDeclareOp> &reductions) { + SmallVectorImpl<omp::DeclareReductionOp> &reductions) { std::optional<ArrayAttr> attr = loop.getReductions(); if (!attr) return; @@ -389,7 +389,7 @@ collectReductionDecls(T loop, reductions.reserve(reductions.size() + loop.getNumReductionVars()); for (auto symbolRef : attr->getAsRange<SymbolRefAttr>()) { reductions.push_back( - SymbolTable::lookupNearestSymbolFrom<omp::ReductionDeclareOp>( + SymbolTable::lookupNearestSymbolFrom<omp::DeclareReductionOp>( loop, symbolRef)); } } @@ -466,7 +466,7 @@ using OwningAtomicReductionGen = /// reduction declaration. The generator uses `builder` but ignores its /// insertion point. static OwningReductionGen -makeReductionGen(omp::ReductionDeclareOp decl, llvm::IRBuilderBase &builder, +makeReductionGen(omp::DeclareReductionOp decl, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) { // The lambda is mutable because we need access to non-const methods of decl // (which aren't actually mutating it), and we must capture decl by-value to @@ -496,7 +496,7 @@ makeReductionGen(omp::ReductionDeclareOp decl, llvm::IRBuilderBase &builder, /// insertion point. Returns null if there is no atomic region available in the /// reduction declaration. static OwningAtomicReductionGen -makeAtomicReductionGen(omp::ReductionDeclareOp decl, +makeAtomicReductionGen(omp::DeclareReductionOp decl, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) { if (decl.getAtomicReductionRegion().empty()) @@ -783,7 +783,7 @@ convertOmpTaskOp(omp::TaskOp taskOp, llvm::IRBuilderBase &builder, /// Converts an OpenMP taskgroup construct into LLVM IR using OpenMPIRBuilder. static LogicalResult -convertOmpTaskgroupOp(omp::TaskGroupOp tgOp, llvm::IRBuilderBase &builder, +convertOmpTaskgroupOp(omp::TaskgroupOp tgOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) { using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy; LogicalResult bodyGenStatus = success(); @@ -805,12 +805,12 @@ convertOmpTaskgroupOp(omp::TaskGroupOp tgOp, llvm::IRBuilderBase &builder, /// Allocate space for privatized reduction variables. template <typename T> static void -allocReductionVars(T loop, llvm::IRBuilderBase &builder, - LLVM::ModuleTranslation &moduleTranslation, - llvm::OpenMPIRBuilder::InsertPointTy &allocaIP, - SmallVector<omp::ReductionDeclareOp> &reductionDecls, - SmallVector<llvm::Value *> &privateReductionVariables, - DenseMap<Value, llvm::Value *> &reductionVariableMap) { +allocByValReductionVars(T loop, llvm::IRBuilderBase &builder, + LLVM::ModuleTranslation &moduleTranslation, + llvm::OpenMPIRBuilder::InsertPointTy &allocaIP, + SmallVector<omp::DeclareReductionOp> &reductionDecls, + SmallVector<llvm::Value *> &privateReductionVariables, + DenseMap<Value, llvm::Value *> &reductionVariableMap) { llvm::IRBuilderBase::InsertPointGuard guard(builder); builder.restoreIP(allocaIP); auto args = @@ -830,7 +830,7 @@ template <typename T> static void collectReductionInfo( T loop, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, - SmallVector<omp::ReductionDeclareOp> &reductionDecls, + SmallVector<omp::DeclareReductionOp> &reductionDecls, SmallVector<OwningReductionGen> &owningReductionGens, SmallVector<OwningAtomicReductionGen> &owningAtomicReductionGens, const SmallVector<llvm::Value *> &privateReductionVariables, @@ -860,9 +860,10 @@ static void collectReductionInfo( /// Converts an OpenMP workshare loop into LLVM IR using OpenMPIRBuilder. static LogicalResult -convertOmpWsLoop(Operation &opInst, llvm::IRBuilderBase &builder, +convertOmpWsloop(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) { - auto loop = cast<omp::WsLoopOp>(opInst); + auto loop = cast<omp::WsloopOp>(opInst); + const bool isByRef = loop.getByref(); // TODO: this should be in the op verifier instead. if (loop.getLowerBound().empty()) return failure(); @@ -881,25 +882,24 @@ convertOmpWsLoop(Operation &opInst, llvm::IRBuilderBase &builder, chunk = builder.CreateSExtOrTrunc(chunkVar, ivType); } - SmallVector<omp::ReductionDeclareOp> reductionDecls; + SmallVector<omp::DeclareReductionOp> reductionDecls; collectReductionDecls(loop, reductionDecls); llvm::OpenMPIRBuilder::InsertPointTy allocaIP = findAllocaInsertPoint(builder, moduleTranslation); SmallVector<llvm::Value *> privateReductionVariables; DenseMap<Value, llvm::Value *> reductionVariableMap; - allocReductionVars(loop, builder, moduleTranslation, allocaIP, reductionDecls, - privateReductionVariables, reductionVariableMap); - - // Store the mapping between reduction variables and their private copies on - // ModuleTranslation stack. It can be then recovered when translating - // omp.reduce operations in a separate call. - LLVM::ModuleTranslation::SaveStack<OpenMPVarMappingStackFrame> mappingGuard( - moduleTranslation, reductionVariableMap); + if (!isByRef) { + allocByValReductionVars(loop, builder, moduleTranslation, allocaIP, + reductionDecls, privateReductionVariables, + reductionVariableMap); + } // Before the loop, store the initial values of reductions into reduction // variables. Although this could be done after allocas, we don't want to mess // up with the alloca insertion point. + MutableArrayRef<BlockArgument> reductionArgs = + loop.getRegion().getArguments().take_back(loop.getNumReductionVars()); for (unsigned i = 0; i < loop.getNumReductionVars(); ++i) { SmallVector<llvm::Value *> phis; if (failed(inlineConvertOmpRegions(reductionDecls[i].getInitializerRegion(), @@ -908,9 +908,31 @@ convertOmpWsLoop(Operation &opInst, llvm::IRBuilderBase &builder, return failure(); assert(phis.size() == 1 && "expected one value to be yielded from the " "reduction neutral element declaration region"); - builder.CreateStore(phis[0], privateReductionVariables[i]); + if (isByRef) { + // Allocate reduction variable (which is a pointer to the real reduction + // variable allocated in the inlined region) + llvm::Value *var = builder.CreateAlloca( + moduleTranslation.convertType(reductionDecls[i].getType())); + // Store the result of the inlined region to the allocated reduction var + // ptr + builder.CreateStore(phis[0], var); + + privateReductionVariables.push_back(var); + moduleTranslation.mapValue(reductionArgs[i], phis[0]); + reductionVariableMap.try_emplace(loop.getReductionVars()[i], phis[0]); + } else { + // for by-ref case the store is inside of the reduction region + builder.CreateStore(phis[0], privateReductionVariables[i]); + // the rest was handled in allocByValReductionVars + } } + // Store the mapping between reduction variables and their private copies on + // ModuleTranslation stack. It can be then recovered when translating + // omp.reduce operations in a separate call. + LLVM::ModuleTranslation::SaveStack<OpenMPVarMappingStackFrame> mappingGuard( + moduleTranslation, reductionVariableMap); + // Set up the source location value for OpenMP runtime. llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder); @@ -940,9 +962,9 @@ convertOmpWsLoop(Operation &opInst, llvm::IRBuilderBase &builder, }; // Delegate actual loop construction to the OpenMP IRBuilder. - // TODO: this currently assumes WsLoop is semantically similar to SCF loop, + // TODO: this currently assumes Wsloop is semantically similar to SCF loop, // i.e. it has a positive step, uses signed integer semantics. Reconsider - // this code when WsLoop clearly supports more cases. + // this code when Wsloop clearly supports more cases. llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder(); for (unsigned i = 0, e = loop.getNumLoops(); i < e; ++i) { llvm::Value *lowerBound = @@ -1014,7 +1036,7 @@ convertOmpWsLoop(Operation &opInst, llvm::IRBuilderBase &builder, builder.SetInsertPoint(tempTerminator); llvm::OpenMPIRBuilder::InsertPointTy contInsertPoint = ompBuilder->createReductions(builder.saveIP(), allocaIP, reductionInfos, - loop.getNowait()); + loop.getNowait(), isByRef); if (!contInsertPoint.getBlock()) return loop->emitOpError() << "failed to convert reductions"; auto nextInsertionPoint = @@ -1068,6 +1090,7 @@ convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) { using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy; OmpParallelOpConversionManager raii(opInst); + const bool isByRef = opInst.getByref(); // TODO: support error propagation in OpenMPIRBuilder and use it instead of // relying on captured variables. @@ -1076,24 +1099,23 @@ convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder, auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP) { // Collect reduction declarations - SmallVector<omp::ReductionDeclareOp> reductionDecls; + SmallVector<omp::DeclareReductionOp> reductionDecls; collectReductionDecls(opInst, reductionDecls); // Allocate reduction vars SmallVector<llvm::Value *> privateReductionVariables; DenseMap<Value, llvm::Value *> reductionVariableMap; - allocReductionVars(opInst, builder, moduleTranslation, allocaIP, - reductionDecls, privateReductionVariables, - reductionVariableMap); - - // Store the mapping between reduction variables and their private copies on - // ModuleTranslation stack. It can be then recovered when translating - // omp.reduce operations in a separate call. - LLVM::ModuleTranslation::SaveStack<OpenMPVarMappingStackFrame> mappingGuard( - moduleTranslation, reductionVariableMap); + if (!isByRef) { + allocByValReductionVars(opInst, builder, moduleTranslation, allocaIP, + reductionDecls, privateReductionVariables, + reductionVariableMap); + } // Initialize reduction vars builder.restoreIP(allocaIP); + MutableArrayRef<BlockArgument> reductionArgs = + opInst.getRegion().getArguments().take_back( + opInst.getNumReductionVars()); for (unsigned i = 0; i < opInst.getNumReductionVars(); ++i) { SmallVector<llvm::Value *> phis; if (failed(inlineConvertOmpRegions( @@ -1104,9 +1126,32 @@ convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder, "expected one value to be yielded from the " "reduction neutral element declaration region"); builder.restoreIP(allocaIP); - builder.CreateStore(phis[0], privateReductionVariables[i]); + + if (isByRef) { + // Allocate reduction variable (which is a pointer to the real reduciton + // variable allocated in the inlined region) + llvm::Value *var = builder.CreateAlloca( + moduleTranslation.convertType(reductionDecls[i].getType())); + // Store the result of the inlined region to the allocated reduction var + // ptr + builder.CreateStore(phis[0], var); + + privateReductionVariables.push_back(var); + moduleTranslation.mapValue(reductionArgs[i], phis[0]); + reductionVariableMap.try_emplace(opInst.getReductionVars()[i], phis[0]); + } else { + // for by-ref case the store is inside of the reduction init region + builder.CreateStore(phis[0], privateReductionVariables[i]); + // the rest is done in allocByValReductionVars + } } + // Store the mapping between reduction variables and their private copies on + // ModuleTranslation stack. It can be then recovered when translating + // omp.reduce operations in a separate call. + LLVM::ModuleTranslation::SaveStack<OpenMPVarMappingStackFrame> mappingGuard( + moduleTranslation, reductionVariableMap); + // Save the alloca insertion point on ModuleTranslation stack for use in // nested regions. LLVM::ModuleTranslation::SaveStack<OpenMPAllocaStackFrame> frame( @@ -1137,7 +1182,7 @@ convertOmpParallel(omp::ParallelOp opInst, llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::InsertPointTy contInsertPoint = ompBuilder->createReductions(builder.saveIP(), allocaIP, - reductionInfos, false); + reductionInfos, false, isByRef); if (!contInsertPoint.getBlock()) { bodyGenStatus = opInst->emitOpError() << "failed to convert reductions"; return; @@ -1608,16 +1653,16 @@ convertOmpAtomicCapture(omp::AtomicCaptureOp atomicCaptureOp, /// Converts an OpenMP reduction operation using OpenMPIRBuilder. Expects the /// mapping between reduction variables and their private equivalents to have /// been stored on the ModuleTranslation stack. Currently only supports -/// reduction within WsLoopOp and ParallelOp, but can be easily extended. +/// reduction within WsloopOp and ParallelOp, but can be easily extended. static LogicalResult convertOmpReductionOp(omp::ReductionOp reductionOp, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) { // Find the declaration that corresponds to the reduction op. - omp::ReductionDeclareOp declaration; + omp::DeclareReductionOp declaration; Operation *reductionParent = reductionOp->getParentOp(); if (dyn_cast<omp::ParallelOp>(reductionParent) || - dyn_cast<omp::WsLoopOp>(reductionParent)) { + dyn_cast<omp::WsloopOp>(reductionParent)) { declaration = findReductionDecl(*reductionParent, reductionOp); } else { llvm_unreachable("Unhandled reduction container"); @@ -1742,6 +1787,20 @@ getDeclareTargetRefPtrSuffix(LLVM::GlobalOp globalOp, return suffix; } +static bool isDeclareTargetLink(mlir::Value value) { + if (auto addressOfOp = + llvm::dyn_cast_if_present<LLVM::AddressOfOp>(value.getDefiningOp())) { + auto modOp = addressOfOp->getParentOfType<mlir::ModuleOp>(); + Operation *gOp = modOp.lookupSymbol(addressOfOp.getGlobalName()); + if (auto declareTargetGlobal = + llvm::dyn_cast<mlir::omp::DeclareTargetInterface>(gOp)) + if (declareTargetGlobal.getDeclareTargetCaptureClause() == + mlir::omp::DeclareTargetCaptureClause::link) + return true; + } + return false; +} + // Returns the reference pointer generated by the lowering of the declare target // operation in cases where the link clause is used or the to clause is used in // USM mode. @@ -1849,7 +1908,7 @@ llvm::Value *getSizeInBytes(DataLayout &dl, const mlir::Type &type, if (!memberClause.getBounds().empty()) { llvm::Value *elementCount = builder.getInt64(1); for (auto bounds : memberClause.getBounds()) { - if (auto boundOp = mlir::dyn_cast_if_present<mlir::omp::DataBoundsOp>( + if (auto boundOp = mlir::dyn_cast_if_present<mlir::omp::MapBoundsOp>( bounds.getDefiningOp())) { // The below calculation for the size to be mapped calculated from the // map_info's bounds is: (elemCount * [UB - LB] + 1), later we @@ -1937,6 +1996,99 @@ void collectMapDataFromMapOperands(MapInfoData &mapData, } } +/// This function calculates the array/pointer offset for map data provided +/// with bounds operations, e.g. when provided something like the following: +/// +/// Fortran +/// map(tofrom: array(2:5, 3:2)) +/// or +/// C++ +/// map(tofrom: array[1:4][2:3]) +/// We must calculate the initial pointer offset to pass across, this function +/// performs this using bounds. +/// +/// NOTE: which while specified in row-major order it currently needs to be +/// flipped for Fortran's column order array allocation and access (as +/// opposed to C++'s row-major, hence the backwards processing where order is +/// important). This is likely important to keep in mind for the future when +/// we incorporate a C++ frontend, both frontends will need to agree on the +/// ordering of generated bounds operations (one may have to flip them) to +/// make the below lowering frontend agnostic. The offload size +/// calcualtion may also have to be adjusted for C++. +std::vector<llvm::Value *> +calculateBoundsOffset(LLVM::ModuleTranslation &moduleTranslation, + llvm::IRBuilderBase &builder, bool isArrayTy, + mlir::OperandRange bounds) { + std::vector<llvm::Value *> idx; + // There's no bounds to calculate an offset from, we can safely + // ignore and return no indices. + if (bounds.empty()) + return idx; + + // If we have an array type, then we have its type so can treat it as a + // normal GEP instruction where the bounds operations are simply indexes + // into the array. We currently do reverse order of the bounds, which + // I believe leans more towards Fortran's column-major in memory. + if (isArrayTy) { + idx.push_back(builder.getInt64(0)); + for (int i = bounds.size() - 1; i >= 0; --i) { + if (auto boundOp = mlir::dyn_cast_if_present<mlir::omp::MapBoundsOp>( + bounds[i].getDefiningOp())) { + idx.push_back(moduleTranslation.lookupValue(boundOp.getLowerBound())); + } + } + } else { + // If we do not have an array type, but we have bounds, then we're dealing + // with a pointer that's being treated like an array and we have the + // underlying type e.g. an i32, or f64 etc, e.g. a fortran descriptor base + // address (pointer pointing to the actual data) so we must caclulate the + // offset using a single index which the following two loops attempts to + // compute. + + // Calculates the size offset we need to make per row e.g. first row or + // column only needs to be offset by one, but the next would have to be + // the previous row/column offset multiplied by the extent of current row. + // + // For example ([1][10][100]): + // + // - First row/column we move by 1 for each index increment + // - Second row/column we move by 1 (first row/column) * 10 (extent/size of + // current) for 10 for each index increment + // - Third row/column we would move by 10 (second row/column) * + // (extent/size of current) 100 for 1000 for each index increment + std::vector<llvm::Value *> dimensionIndexSizeOffset{builder.getInt64(1)}; + for (size_t i = 1; i < bounds.size(); ++i) { + if (auto boundOp = mlir::dyn_cast_if_present<mlir::omp::MapBoundsOp>( + bounds[i].getDefiningOp())) { + dimensionIndexSizeOffset.push_back(builder.CreateMul( + moduleTranslation.lookupValue(boundOp.getExtent()), + dimensionIndexSizeOffset[i - 1])); + } + } + + // Now that we have calculated how much we move by per index, we must + // multiply each lower bound offset in indexes by the size offset we + // have calculated in the previous and accumulate the results to get + // our final resulting offset. + for (int i = bounds.size() - 1; i >= 0; --i) { + if (auto boundOp = mlir::dyn_cast_if_present<mlir::omp::MapBoundsOp>( + bounds[i].getDefiningOp())) { + if (idx.empty()) + idx.emplace_back(builder.CreateMul( + moduleTranslation.lookupValue(boundOp.getLowerBound()), + dimensionIndexSizeOffset[i])); + else + idx.back() = builder.CreateAdd( + idx.back(), builder.CreateMul(moduleTranslation.lookupValue( + boundOp.getLowerBound()), + dimensionIndexSizeOffset[i])); + } + } + } + + return idx; +} + // This creates two insertions into the MapInfosTy data structure for the // "parent" of a set of members, (usually a container e.g. // class/structure/derived type) when subsequent members have also been @@ -2012,6 +2164,27 @@ static llvm::omp::OpenMPOffloadMappingFlags mapParentWithMembers( return memberOfFlag; } +// The intent is to verify if the mapped data being passed is a +// pointer -> pointee that requires special handling in certain cases, +// e.g. applying the OMP_MAP_PTR_AND_OBJ map type. +// +// There may be a better way to verify this, but unfortunately with +// opaque pointers we lose the ability to easily check if something is +// a pointer whilst maintaining access to the underlying type. +static bool checkIfPointerMap(mlir::omp::MapInfoOp mapOp) { + // If we have a varPtrPtr field assigned then the underlying type is a pointer + if (mapOp.getVarPtrPtr()) + return true; + + // If the map data is declare target with a link clause, then it's represented + // as a pointer when we lower it to LLVM-IR even if at the MLIR level it has + // no relation to pointers. + if (isDeclareTargetLink(mapOp.getVarPtr())) + return true; + + return false; +} + // This function is intended to add explicit mappings of members static void processMapMembersWithParent( LLVM::ModuleTranslation &moduleTranslation, llvm::IRBuilderBase &builder, @@ -2038,8 +2211,11 @@ static void processMapMembersWithParent( auto mapFlag = llvm::omp::OpenMPOffloadMappingFlags(memberClause.getMapType().value()); mapFlag &= ~llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM; + mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF; ompBuilder.setCorrectMemberOfFlag(mapFlag, memberOfFlag); - mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ; + if (checkIfPointerMap(memberClause)) + mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ; + combinedInfo.Types.emplace_back(mapFlag); combinedInfo.DevicePointers.emplace_back( llvm::OpenMPIRBuilder::DeviceInfoTy::None); @@ -2047,55 +2223,7 @@ static void processMapMembersWithParent( LLVM::createMappingInformation(memberClause.getLoc(), ompBuilder)); combinedInfo.BasePointers.emplace_back(mapData.BasePointers[memberDataIdx]); - - std::vector<llvm::Value *> idx{builder.getInt64(0)}; - llvm::Value *offsetAddress = nullptr; - if (!memberClause.getBounds().empty()) { - if (mapData.BaseType[memberDataIdx]->isArrayTy()) { - for (int i = memberClause.getBounds().size() - 1; i >= 0; --i) { - if (auto boundOp = mlir::dyn_cast_if_present<mlir::omp::DataBoundsOp>( - memberClause.getBounds()[i].getDefiningOp())) { - idx.push_back( - moduleTranslation.lookupValue(boundOp.getLowerBound())); - } - } - } else { - std::vector<llvm::Value *> dimensionIndexSizeOffset{ - builder.getInt64(1)}; - for (size_t i = 1; i < memberClause.getBounds().size(); ++i) { - if (auto boundOp = mlir::dyn_cast_if_present<mlir::omp::DataBoundsOp>( - memberClause.getBounds()[i].getDefiningOp())) { - dimensionIndexSizeOffset.push_back(builder.CreateMul( - moduleTranslation.lookupValue(boundOp.getExtent()), - dimensionIndexSizeOffset[i - 1])); - } - } - - for (int i = memberClause.getBounds().size() - 1; i >= 0; --i) { - if (auto boundOp = mlir::dyn_cast_if_present<mlir::omp::DataBoundsOp>( - memberClause.getBounds()[i].getDefiningOp())) { - if (!offsetAddress) - offsetAddress = builder.CreateMul( - moduleTranslation.lookupValue(boundOp.getLowerBound()), - dimensionIndexSizeOffset[i]); - else - offsetAddress = builder.CreateAdd( - offsetAddress, - builder.CreateMul( - moduleTranslation.lookupValue(boundOp.getLowerBound()), - dimensionIndexSizeOffset[i])); - } - } - } - } - - llvm::Value *memberIdx = - builder.CreateLoad(builder.getPtrTy(), mapData.Pointers[memberDataIdx]); - memberIdx = builder.CreateInBoundsGEP( - mapData.BaseType[memberDataIdx], memberIdx, - offsetAddress ? std::vector<llvm::Value *>{offsetAddress} : idx, - "member_idx"); - combinedInfo.Pointers.emplace_back(memberIdx); + combinedInfo.Pointers.emplace_back(mapData.Pointers[memberDataIdx]); combinedInfo.Sizes.emplace_back(mapData.Sizes[memberDataIdx]); } } @@ -2113,6 +2241,76 @@ static void processMapWithMembersOf( memberOfParentFlag); } +// This is a variation on Clang's GenerateOpenMPCapturedVars, which +// generates different operation (e.g. load/store) combinations for +// arguments to the kernel, based on map capture kinds which are then +// utilised in the combinedInfo in place of the original Map value. +static void +createAlteredByCaptureMap(MapInfoData &mapData, + LLVM::ModuleTranslation &moduleTranslation, + llvm::IRBuilderBase &builder) { + for (size_t i = 0; i < mapData.MapClause.size(); ++i) { + // if it's declare target, skip it, it's handled seperately. + if (!mapData.IsDeclareTarget[i]) { + auto mapOp = + mlir::dyn_cast_if_present<mlir::omp::MapInfoOp>(mapData.MapClause[i]); + mlir::omp::VariableCaptureKind captureKind = + mapOp.getMapCaptureType().value_or( + mlir::omp::VariableCaptureKind::ByRef); + bool isPtrTy = checkIfPointerMap(mapOp); + + // Currently handles array sectioning lowerbound case, but more + // logic may be required in the future. Clang invokes EmitLValue, + // which has specialised logic for special Clang types such as user + // defines, so it is possible we will have to extend this for + // structures or other complex types. As the general idea is that this + // function mimics some of the logic from Clang that we require for + // kernel argument passing from host -> device. + switch (captureKind) { + case mlir::omp::VariableCaptureKind::ByRef: { + llvm::Value *newV = mapData.Pointers[i]; + std::vector<llvm::Value *> offsetIdx = calculateBoundsOffset( + moduleTranslation, builder, mapData.BaseType[i]->isArrayTy(), + mapOp.getBounds()); + if (isPtrTy) + newV = builder.CreateLoad(builder.getPtrTy(), newV); + + if (!offsetIdx.empty()) + newV = builder.CreateInBoundsGEP(mapData.BaseType[i], newV, offsetIdx, + "array_offset"); + mapData.Pointers[i] = newV; + } break; + case mlir::omp::VariableCaptureKind::ByCopy: { + llvm::Type *type = mapData.BaseType[i]; + llvm::Value *newV; + if (mapData.Pointers[i]->getType()->isPointerTy()) + newV = builder.CreateLoad(type, mapData.Pointers[i]); + else + newV = mapData.Pointers[i]; + + if (!isPtrTy) { + auto curInsert = builder.saveIP(); + builder.restoreIP(findAllocaInsertPoint(builder, moduleTranslation)); + auto *memTempAlloc = + builder.CreateAlloca(builder.getPtrTy(), nullptr, ".casted"); + builder.restoreIP(curInsert); + + builder.CreateStore(newV, memTempAlloc); + newV = builder.CreateLoad(builder.getPtrTy(), memTempAlloc); + } + + mapData.Pointers[i] = newV; + mapData.BasePointers[i] = newV; + } break; + case mlir::omp::VariableCaptureKind::This: + case mlir::omp::VariableCaptureKind::VLAType: + mapData.MapClause[i]->emitOpError("Unhandled capture kind"); + break; + } + } + } +} + // Generate all map related information and fill the combinedInfo. static void genMapInfos(llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation, @@ -2122,6 +2320,20 @@ static void genMapInfos(llvm::IRBuilderBase &builder, const SmallVector<Value> &devPtrOperands = {}, const SmallVector<Value> &devAddrOperands = {}, bool isTargetParams = false) { + // We wish to modify some of the methods in which arguments are + // passed based on their capture type by the target region, this can + // involve generating new loads and stores, which changes the + // MLIR value to LLVM value mapping, however, we only wish to do this + // locally for the current function/target and also avoid altering + // ModuleTranslation, so we remap the base pointer or pointer stored + // in the map infos corresponding MapInfoData, which is later accessed + // by genMapInfos and createTarget to help generate the kernel and + // kernel arg structure. It primarily becomes relevant in cases like + // bycopy, or byref range'd arrays. In the default case, we simply + // pass thee pointer byref as both basePointer and pointer. + if (!moduleTranslation.getOpenMPBuilder()->Config.isTargetDevice()) + createAlteredByCaptureMap(mapData, moduleTranslation, builder); + llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder(); auto fail = [&combinedInfo]() -> void { @@ -2155,19 +2367,20 @@ static void genMapInfos(llvm::IRBuilderBase &builder, continue; } - // Declare Target Mappings are excluded from being marked as - // OMP_MAP_TARGET_PARAM as they are not passed as parameters, they're - // marked with OMP_MAP_PTR_AND_OBJ instead. auto mapFlag = mapData.Types[i]; - if (mapData.IsDeclareTarget[i]) + bool isPtrTy = checkIfPointerMap(mapInfoOp); + if (isPtrTy) mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ; - else if (isTargetParams) + + // Declare Target Mappings are excluded from being marked as + // OMP_MAP_TARGET_PARAM as they are not passed as parameters. + if (isTargetParams && !mapData.IsDeclareTarget[i]) mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM; if (auto mapInfoOp = dyn_cast<mlir::omp::MapInfoOp>(mapData.MapClause[i])) if (mapInfoOp.getMapCaptureType().value() == mlir::omp::VariableCaptureKind::ByCopy && - !mapInfoOp.getVarType().isa<LLVM::LLVMPointerType>()) + !isPtrTy) mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_LITERAL; combinedInfo.BasePointers.emplace_back(mapData.BasePointers[i]); @@ -2234,7 +2447,7 @@ convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder, LogicalResult result = llvm::TypeSwitch<Operation *, LogicalResult>(op) - .Case([&](omp::DataOp dataOp) { + .Case([&](omp::TargetDataOp dataOp) { if (auto ifExprVar = dataOp.getIfExpr()) ifCond = moduleTranslation.lookupValue(ifExprVar); @@ -2249,7 +2462,7 @@ convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder, useDevAddrOperands = dataOp.getUseDeviceAddr(); return success(); }) - .Case([&](omp::EnterDataOp enterDataOp) { + .Case([&](omp::TargetEnterDataOp enterDataOp) { if (enterDataOp.getNowait()) return (LogicalResult)(enterDataOp.emitError( "`nowait` is not supported yet")); @@ -2266,7 +2479,7 @@ convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder, mapOperands = enterDataOp.getMapOperands(); return success(); }) - .Case([&](omp::ExitDataOp exitDataOp) { + .Case([&](omp::TargetExitDataOp exitDataOp) { if (exitDataOp.getNowait()) return (LogicalResult)(exitDataOp.emitError( "`nowait` is not supported yet")); @@ -2284,7 +2497,7 @@ convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder, mapOperands = exitDataOp.getMapOperands(); return success(); }) - .Case([&](omp::UpdateDataOp updateDataOp) { + .Case([&](omp::TargetUpdateOp updateDataOp) { if (updateDataOp.getNowait()) return (LogicalResult)(updateDataOp.emitError( "`nowait` is not supported yet")); @@ -2321,7 +2534,7 @@ convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder, auto genMapInfoCB = [&](InsertPointTy codeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & { builder.restoreIP(codeGenIP); - if (auto dataOp = dyn_cast<omp::DataOp>(op)) { + if (auto dataOp = dyn_cast<omp::TargetDataOp>(op)) { genMapInfos(builder, moduleTranslation, DL, combinedInfo, mapData, useDevPtrOperands, useDevAddrOperands); } else { @@ -2336,8 +2549,9 @@ convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder, using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy; LogicalResult bodyGenStatus = success(); auto bodyGenCB = [&](InsertPointTy codeGenIP, BodyGenTy bodyGenType) { - assert(isa<omp::DataOp>(op) && "BodyGen requested for non DataOp"); - Region ®ion = cast<omp::DataOp>(op).getRegion(); + assert(isa<omp::TargetDataOp>(op) && + "BodyGen requested for non TargetDataOp"); + Region ®ion = cast<omp::TargetDataOp>(op).getRegion(); switch (bodyGenType) { case BodyGenTy::Priv: // Check if any device ptr/addr info is available @@ -2382,7 +2596,7 @@ convertOmpTargetData(Operation *op, llvm::IRBuilderBase &builder, llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder); llvm::OpenMPIRBuilder::InsertPointTy allocaIP = findAllocaInsertPoint(builder, moduleTranslation); - if (isa<omp::DataOp>(op)) { + if (isa<omp::TargetDataOp>(op)) { builder.restoreIP(ompBuilder->createTargetData( ompLoc, allocaIP, builder.saveIP(), builder.getInt64(deviceID), ifCond, info, genMapInfoCB, nullptr, bodyGenCB)); @@ -2616,86 +2830,6 @@ createDeviceArgumentAccessor(MapInfoData &mapData, llvm::Argument &arg, return builder.saveIP(); } -// This is a variation on Clang's GenerateOpenMPCapturedVars, which -// generates different operation (e.g. load/store) combinations for -// arguments to the kernel, based on map capture kinds which are then -// utilised in the combinedInfo in place of the original Map value. -static void -createAlteredByCaptureMap(MapInfoData &mapData, - LLVM::ModuleTranslation &moduleTranslation, - llvm::IRBuilderBase &builder) { - for (size_t i = 0; i < mapData.MapClause.size(); ++i) { - // if it's declare target, skip it, it's handled seperately. - if (!mapData.IsDeclareTarget[i]) { - mlir::omp::VariableCaptureKind captureKind = - mlir::omp::VariableCaptureKind::ByRef; - - if (auto mapOp = mlir::dyn_cast_if_present<mlir::omp::MapInfoOp>( - mapData.MapClause[i])) { - captureKind = mapOp.getMapCaptureType().value_or( - mlir::omp::VariableCaptureKind::ByRef); - } - - switch (captureKind) { - case mlir::omp::VariableCaptureKind::ByRef: { - // Currently handles array sectioning lowerbound case, but more - // logic may be required in the future. Clang invokes EmitLValue, - // which has specialised logic for special Clang types such as user - // defines, so it is possible we will have to extend this for - // structures or other complex types. As the general idea is that this - // function mimics some of the logic from Clang that we require for - // kernel argument passing from host -> device. - if (auto mapOp = mlir::dyn_cast_if_present<mlir::omp::MapInfoOp>( - mapData.MapClause[i])) { - if (!mapOp.getBounds().empty() && mapData.BaseType[i]->isArrayTy()) { - - std::vector<llvm::Value *> idx = - std::vector<llvm::Value *>{builder.getInt64(0)}; - for (int i = mapOp.getBounds().size() - 1; i >= 0; --i) { - if (auto boundOp = - mlir::dyn_cast_if_present<mlir::omp::DataBoundsOp>( - mapOp.getBounds()[i].getDefiningOp())) { - idx.push_back( - moduleTranslation.lookupValue(boundOp.getLowerBound())); - } - } - - mapData.Pointers[i] = builder.CreateInBoundsGEP( - mapData.BaseType[i], mapData.Pointers[i], idx); - } - } - } break; - case mlir::omp::VariableCaptureKind::ByCopy: { - llvm::Type *type = mapData.BaseType[i]; - llvm::Value *newV; - if (mapData.Pointers[i]->getType()->isPointerTy()) - newV = builder.CreateLoad(type, mapData.Pointers[i]); - else - newV = mapData.Pointers[i]; - - if (!type->isPointerTy()) { - auto curInsert = builder.saveIP(); - builder.restoreIP(findAllocaInsertPoint(builder, moduleTranslation)); - auto *memTempAlloc = - builder.CreateAlloca(builder.getPtrTy(), nullptr, ".casted"); - builder.restoreIP(curInsert); - - builder.CreateStore(newV, memTempAlloc); - newV = builder.CreateLoad(builder.getPtrTy(), memTempAlloc); - } - - mapData.Pointers[i] = newV; - mapData.BasePointers[i] = newV; - } break; - case mlir::omp::VariableCaptureKind::This: - case mlir::omp::VariableCaptureKind::VLAType: - mapData.MapClause[i]->emitOpError("Unhandled capture kind"); - break; - } - } - } -} - static LogicalResult convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) { @@ -2764,20 +2898,6 @@ convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder, collectMapDataFromMapOperands(mapData, mapOperands, moduleTranslation, dl, builder); - // We wish to modify some of the methods in which kernel arguments are - // passed based on their capture type by the target region, this can - // involve generating new loads and stores, which changes the - // MLIR value to LLVM value mapping, however, we only wish to do this - // locally for the current function/target and also avoid altering - // ModuleTranslation, so we remap the base pointer or pointer stored - // in the map infos corresponding MapInfoData, which is later accessed - // by genMapInfos and createTarget to help generate the kernel and - // kernel arg structure. It primarily becomes relevant in cases like - // bycopy, or byref range'd arrays. In the default case, we simply - // pass thee pointer byref as both basePointer and pointer. - if (!moduleTranslation.getOpenMPBuilder()->Config.isTargetDevice()) - createAlteredByCaptureMap(mapData, moduleTranslation, builder); - llvm::OpenMPIRBuilder::MapInfosTy combinedInfos; auto genMapInfoCB = [&](llvm::OpenMPIRBuilder::InsertPointTy codeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & { @@ -3087,8 +3207,8 @@ LogicalResult OpenMPDialectLLVMIRTranslationInterface::convertOperation( .Case([&](omp::OrderedOp) { return convertOmpOrdered(*op, builder, moduleTranslation); }) - .Case([&](omp::WsLoopOp) { - return convertOmpWsLoop(*op, builder, moduleTranslation); + .Case([&](omp::WsloopOp) { + return convertOmpWsloop(*op, builder, moduleTranslation); }) .Case([&](omp::SimdLoopOp) { return convertOmpSimdLoop(*op, builder, moduleTranslation); @@ -3117,14 +3237,14 @@ LogicalResult OpenMPDialectLLVMIRTranslationInterface::convertOperation( .Case([&](omp::TaskOp op) { return convertOmpTaskOp(op, builder, moduleTranslation); }) - .Case([&](omp::TaskGroupOp op) { + .Case([&](omp::TaskgroupOp op) { return convertOmpTaskgroupOp(op, builder, moduleTranslation); }) - .Case<omp::YieldOp, omp::TerminatorOp, omp::ReductionDeclareOp, + .Case<omp::YieldOp, omp::TerminatorOp, omp::DeclareReductionOp, omp::CriticalDeclareOp>([](auto op) { // `yield` and `terminator` can be just omitted. The block structure // was created in the region that handles their parent operation. - // `reduction.declare` will be used by reductions and is not + // `declare_reduction` will be used by reductions and is not // converted directly, skip it. // `critical.declare` is only used to declare names of critical // sections which will be used by `critical` ops and hence can be @@ -3135,18 +3255,18 @@ LogicalResult OpenMPDialectLLVMIRTranslationInterface::convertOperation( .Case([&](omp::ThreadprivateOp) { return convertOmpThreadprivate(*op, builder, moduleTranslation); }) - .Case<omp::DataOp, omp::EnterDataOp, omp::ExitDataOp, omp::UpdateDataOp>( - [&](auto op) { - return convertOmpTargetData(op, builder, moduleTranslation); - }) + .Case<omp::TargetDataOp, omp::TargetEnterDataOp, omp::TargetExitDataOp, + omp::TargetUpdateOp>([&](auto op) { + return convertOmpTargetData(op, builder, moduleTranslation); + }) .Case([&](omp::TargetOp) { return convertOmpTarget(*op, builder, moduleTranslation); }) - .Case<omp::MapInfoOp, omp::DataBoundsOp, omp::PrivateClauseOp>( + .Case<omp::MapInfoOp, omp::MapBoundsOp, omp::PrivateClauseOp>( [&](auto op) { // No-op, should be handled by relevant owning operations e.g. - // TargetOp, EnterDataOp, ExitDataOp, DataOp etc. and then - // discarded + // TargetOp, TargetEnterDataOp, TargetExitDataOp, TargetDataOp etc. + // and then discarded return success(); }) .Default([&](Operation *inst) { diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp index d63ea12ecd49b189550d3ad3fa22ad652f09e7b3..6e70d52fa760b69258bec9456e34c718ddbbaa66 100644 --- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp @@ -1290,6 +1290,27 @@ DILabelAttr ModuleImport::matchLabelAttr(llvm::Value *value) { return debugImporter->translate(node); } +FPExceptionBehaviorAttr +ModuleImport::matchFPExceptionBehaviorAttr(llvm::Value *value) { + auto *metadata = cast<llvm::MetadataAsValue>(value); + auto *mdstr = cast<llvm::MDString>(metadata->getMetadata()); + std::optional<llvm::fp::ExceptionBehavior> optLLVM = + llvm::convertStrToExceptionBehavior(mdstr->getString()); + assert(optLLVM && "Expecting FP exception behavior"); + return builder.getAttr<FPExceptionBehaviorAttr>( + convertFPExceptionBehaviorFromLLVM(*optLLVM)); +} + +RoundingModeAttr ModuleImport::matchRoundingModeAttr(llvm::Value *value) { + auto *metadata = cast<llvm::MetadataAsValue>(value); + auto *mdstr = cast<llvm::MDString>(metadata->getMetadata()); + std::optional<llvm::RoundingMode> optLLVM = + llvm::convertStrToRoundingMode(mdstr->getString()); + assert(optLLVM && "Expecting rounding mode"); + return builder.getAttr<RoundingModeAttr>( + convertRoundingModeFromLLVM(*optLLVM)); +} + FailureOr<SmallVector<AliasScopeAttr>> ModuleImport::matchAliasScopeAttrs(llvm::Value *value) { auto *nodeAsVal = cast<llvm::MetadataAsValue>(value); diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp index c00628a420a000a9ba3f96d200314912d081304d..669b95a9c6a5be178f1637c74d62e1b526d779b4 100644 --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -274,16 +274,15 @@ translateDataLayout(DataLayoutSpecInterface attribute, layoutStream << ":" << preferred; return success(); }) - .Case([&](LLVMPointerType ptrType) { - layoutStream << "p" << ptrType.getAddressSpace() << ":"; + .Case([&](LLVMPointerType type) { + layoutStream << "p" << type.getAddressSpace() << ":"; uint64_t size = dataLayout.getTypeSizeInBits(type); uint64_t abi = dataLayout.getTypeABIAlignment(type) * 8u; uint64_t preferred = dataLayout.getTypePreferredAlignment(type) * 8u; - layoutStream << size << ":" << abi << ":" << preferred; - if (std::optional<uint64_t> index = extractPointerSpecValue( - entry.getValue(), PtrDLEntryPos::Index)) - layoutStream << ":" << *index; + uint64_t index = *dataLayout.getTypeIndexBitwidth(type); + layoutStream << size << ":" << abi << ":" << preferred << ":" + << index; return success(); }) .Default([loc](Type type) { @@ -716,6 +715,8 @@ void ModuleTranslation::forgetMapping(Region ®ion) { branchMapping.erase(&op); if (isa<LLVM::GlobalOp>(op)) globalsMapping.erase(&op); + if (isa<LLVM::CallOp>(op)) + callMapping.erase(&op); llvm::append_range( toProcess, llvm::map_range(op.getRegions(), [](Region &r) { return &r; })); @@ -1720,6 +1721,16 @@ llvm::Metadata *ModuleTranslation::translateDebugInfo(LLVM::DINodeAttr attr) { return debugTranslation->translate(attr); } +llvm::RoundingMode +ModuleTranslation::translateRoundingMode(LLVM::RoundingMode rounding) { + return convertRoundingModeToLLVM(rounding); +} + +llvm::fp::ExceptionBehavior ModuleTranslation::translateFPExceptionBehavior( + LLVM::FPExceptionBehavior exceptionBehavior) { + return convertFPExceptionBehaviorToLLVM(exceptionBehavior); +} + llvm::NamedMDNode * ModuleTranslation::getOrInsertNamedModuleMetadata(StringRef name) { return llvmModule->getOrInsertNamedMetadata(name); diff --git a/mlir/lib/Target/SPIRV/Serialization/Serializer.cpp b/mlir/lib/Target/SPIRV/Serialization/Serializer.cpp index 4a4e878d8af915d87e9f8c1dbc2b8a90568ccb05..9a74ac115e95552db28a6758dcfa2ca0b577c350 100644 --- a/mlir/lib/Target/SPIRV/Serialization/Serializer.cpp +++ b/mlir/lib/Target/SPIRV/Serialization/Serializer.cpp @@ -1031,9 +1031,9 @@ Serializer::processBlock(Block *block, bool omitLabel, // into multiple basic blocks. If that's the case, we need to emit the merge // right now and then create new blocks for further serialization of the ops // in this block. - if (emitMerge && llvm::any_of(block->getOperations(), [](Operation &op) { - return isa<spirv::LoopOp, spirv::SelectionOp>(op); - })) { + if (emitMerge && + llvm::any_of(block->getOperations(), + llvm::IsaPred<spirv::LoopOp, spirv::SelectionOp>)) { if (failed(emitMerge())) return failure(); emitMerge = nullptr; @@ -1045,7 +1045,7 @@ Serializer::processBlock(Block *block, bool omitLabel, } // Process each op in this block except the terminator. - for (auto &op : llvm::make_range(block->begin(), std::prev(block->end()))) { + for (Operation &op : llvm::drop_end(*block)) { if (failed(processOperation(&op))) return failure(); } diff --git a/mlir/lib/Tools/lsp-server-support/Transport.cpp b/mlir/lib/Tools/lsp-server-support/Transport.cpp index df675cf78210be8f6b4d82f0bd0a678b25b3990d..64dea35614c070a72ec256b1829aae620d57d706 100644 --- a/mlir/lib/Tools/lsp-server-support/Transport.cpp +++ b/mlir/lib/Tools/lsp-server-support/Transport.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "mlir/Tools/lsp-server-support/Transport.h" +#include "mlir/Support/ToolUtilities.h" #include "mlir/Tools/lsp-server-support/Logging.h" #include "mlir/Tools/lsp-server-support/Protocol.h" #include "llvm/ADT/SmallString.h" @@ -347,7 +348,7 @@ LogicalResult JSONTransport::readDelimitedMessage(std::string &json) { StringRef lineRef = line.str().trim(); if (lineRef.starts_with("//")) { // Found a delimiter for the message. - if (lineRef == "// -----") + if (lineRef == kDefaultSplitMarker) break; continue; } diff --git a/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp b/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp index de657a3df9ef7b49e4e65ba8801abaccbf16448c..ed75b4a90536eb1276ec545f01b21c230341ad80 100644 --- a/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp +++ b/mlir/lib/Tools/mlir-lsp-server/MLIRServer.cpp @@ -15,6 +15,7 @@ #include "mlir/IR/Operation.h" #include "mlir/Interfaces/FunctionInterfaces.h" #include "mlir/Parser/Parser.h" +#include "mlir/Support/ToolUtilities.h" #include "mlir/Tools/lsp-server-support/Logging.h" #include "mlir/Tools/lsp-server-support/SourceMgrUtils.h" #include "llvm/ADT/StringExtras.h" @@ -1052,11 +1053,8 @@ MLIRTextFile::MLIRTextFile(const lsp::URIForFile &uri, StringRef fileContents, context.allowUnregisteredDialects(); // Split the file into separate MLIR documents. - // TODO: Find a way to share the split file marker with other tools. We don't - // want to use `splitAndProcessBuffer` here, but we do want to make sure this - // marker doesn't go out of sync. SmallVector<StringRef, 8> subContents; - StringRef(contents).split(subContents, "// -----"); + StringRef(contents).split(subContents, kDefaultSplitMarker); chunks.emplace_back(std::make_unique<MLIRTextFileChunk>( context, /*lineOffset=*/0, uri, subContents.front(), diagnostics)); diff --git a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp index b62557153b416771ea85e00a62e786e5617b575a..44c5e9826f3b7921035fa5ff9d3b565fa27af09a 100644 --- a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp +++ b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp @@ -31,6 +31,7 @@ #include "mlir/Pass/Pass.h" #include "mlir/Pass/PassManager.h" #include "mlir/Support/FileUtilities.h" +#include "mlir/Support/LogicalResult.h" #include "mlir/Support/Timing.h" #include "mlir/Support/ToolUtilities.h" #include "mlir/Tools/ParseUtilities.h" @@ -127,11 +128,21 @@ struct MlirOptMainConfigCLOptions : public MlirOptMainConfig { cl::desc("Print the list of registered dialects and exit"), cl::location(showDialectsFlag), cl::init(false)); - static cl::opt<bool, /*ExternalStorage=*/true> splitInputFile( - "split-input-file", - cl::desc("Split the input file into pieces and process each " - "chunk independently"), - cl::location(splitInputFileFlag), cl::init(false)); + static cl::opt<std::string, /*ExternalStorage=*/true> splitInputFile{ + "split-input-file", llvm::cl::ValueOptional, + cl::callback([&](const std::string &str) { + // Implicit value: use default marker if flag was used without value. + if (str.empty()) + splitInputFile.setValue(kDefaultSplitMarker); + }), + cl::desc("Split the input file into chunks using the given or " + "default marker and process each chunk independently"), + cl::location(splitInputFileFlag), cl::init("")}; + + static cl::opt<std::string, /*ExternalStorage=*/true> outputSplitMarker( + "output-split-marker", + cl::desc("Split marker to use for merging the ouput"), + cl::location(outputSplitMarkerFlag), cl::init(kDefaultSplitMarker)); static cl::opt<bool, /*ExternalStorage=*/true> verifyDiagnostics( "verify-diagnostics", @@ -503,15 +514,19 @@ mlir::registerAndParseCLIOptions(int argc, char **argv, return std::make_pair(inputFilename.getValue(), outputFilename.getValue()); } +static LogicalResult printRegisteredDialects(DialectRegistry ®istry) { + llvm::outs() << "Available Dialects: "; + interleave(registry.getDialectNames(), llvm::outs(), ","); + llvm::outs() << "\n"; + return success(); +} + LogicalResult mlir::MlirOptMain(llvm::raw_ostream &outputStream, std::unique_ptr<llvm::MemoryBuffer> buffer, DialectRegistry ®istry, const MlirOptMainConfig &config) { - if (config.shouldShowDialects()) { - llvm::outs() << "Available Dialects: "; - interleave(registry.getDialectNames(), llvm::outs(), ","); - llvm::outs() << "\n"; - } + if (config.shouldShowDialects()) + return printRegisteredDialects(registry); // The split-input-file mode is a very specific mode that slices the file // up into small pieces and checks each independently. @@ -533,8 +548,8 @@ LogicalResult mlir::MlirOptMain(llvm::raw_ostream &outputStream, threadPool); }; return splitAndProcessBuffer(std::move(buffer), chunkFn, outputStream, - config.shouldSplitInputFile(), - /*insertMarkerInOutput=*/true); + config.inputSplitMarker(), + config.outputSplitMarker()); } LogicalResult mlir::MlirOptMain(int argc, char **argv, @@ -546,6 +561,9 @@ LogicalResult mlir::MlirOptMain(int argc, char **argv, MlirOptMainConfig config = MlirOptMainConfig::createFromCLOptions(); + if (config.shouldShowDialects()) + return printRegisteredDialects(registry); + // When reading from stdin and the input is a tty, it is often a user mistake // and the process "appears to be stuck". Print a message to let the user know // about it! diff --git a/mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.cpp b/mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.cpp index a5c6c2bb2c6a0cf4f47d2ecb35ffbf80907a189e..d282ee8f61d8fe8c9f9881a2f55c6ecfead7f827 100644 --- a/mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.cpp +++ b/mlir/lib/Tools/mlir-pdll-lsp-server/PDLLServer.cpp @@ -10,6 +10,7 @@ #include "Protocol.h" #include "mlir/IR/BuiltinOps.h" +#include "mlir/Support/ToolUtilities.h" #include "mlir/Tools/PDLL/AST/Context.h" #include "mlir/Tools/PDLL/AST/Nodes.h" #include "mlir/Tools/PDLL/AST/Types.h" @@ -1621,7 +1622,8 @@ PDLTextFile::getPDLLViewOutput(lsp::PDLLViewOutputKind kind) { [&](PDLTextFileChunk &chunk) { chunk.document.getPDLLViewOutput(outputOS, kind); }, - [&] { outputOS << "\n// -----\n\n"; }); + [&] { outputOS << "\n" + << kDefaultSplitMarker << "\n\n"; }); } return result; } @@ -1632,11 +1634,8 @@ void PDLTextFile::initialize(const lsp::URIForFile &uri, int64_t newVersion, chunks.clear(); // Split the file into separate PDL documents. - // TODO: Find a way to share the split file marker with other tools. We don't - // want to use `splitAndProcessBuffer` here, but we do want to make sure this - // marker doesn't go out of sync. SmallVector<StringRef, 8> subContents; - StringRef(contents).split(subContents, "// -----"); + StringRef(contents).split(subContents, kDefaultSplitMarker); chunks.emplace_back(std::make_unique<PDLTextFileChunk>( /*lineOffset=*/0, uri, subContents.front(), extraIncludeDirs, diagnostics)); diff --git a/mlir/lib/Tools/mlir-translate/MlirTranslateMain.cpp b/mlir/lib/Tools/mlir-translate/MlirTranslateMain.cpp index 92adb8d6ac97c6025fd5b26c7c48e17206816e7d..bd9928950ecc769c72009ae15c13de7420409de3 100644 --- a/mlir/lib/Tools/mlir-translate/MlirTranslateMain.cpp +++ b/mlir/lib/Tools/mlir-translate/MlirTranslateMain.cpp @@ -62,11 +62,16 @@ LogicalResult mlir::mlirTranslateMain(int argc, char **argv, llvm::cl::desc("Allow operation with no registered dialects (discouraged: testing only!)"), llvm::cl::init(false)); - static llvm::cl::opt<bool> splitInputFile( - "split-input-file", - llvm::cl::desc("Split the input file into pieces and " - "process each chunk independently"), - llvm::cl::init(false)); + static llvm::cl::opt<std::string> inputSplitMarker{ + "split-input-file", llvm::cl::ValueOptional, + llvm::cl::callback([&](const std::string &str) { + // Implicit value: use default marker if flag was used without value. + if (str.empty()) + inputSplitMarker.setValue(kDefaultSplitMarker); + }), + llvm::cl::desc("Split the input file into chunks using the given or " + "default marker and process each chunk independently"), + llvm::cl::init("")}; static llvm::cl::opt<bool> verifyDiagnostics( "verify-diagnostics", @@ -80,6 +85,11 @@ LogicalResult mlir::mlirTranslateMain(int argc, char **argv, "(discouraged: testing only!)"), llvm::cl::init(false)); + static llvm::cl::opt<std::string> outputSplitMarker( + "output-split-marker", + llvm::cl::desc("Split marker to use for merging the ouput"), + llvm::cl::init("")); + llvm::InitLLVM y(argc, argv); // Add flags for all the registered translations. @@ -176,7 +186,8 @@ LogicalResult mlir::mlirTranslateMain(int argc, char **argv, }; if (failed(splitAndProcessBuffer(std::move(input), processBuffer, - output->os(), splitInputFile))) + output->os(), inputSplitMarker, + outputSplitMarker))) return failure(); output->keep(); diff --git a/mlir/lib/Transforms/CMakeLists.txt b/mlir/lib/Transforms/CMakeLists.txt index 6c32ecf8a2a2f1417a8dd5da16738d79bfb04b43..90c0298fb5e46a23b315cf3e88f1bf5298ad7203 100644 --- a/mlir/lib/Transforms/CMakeLists.txt +++ b/mlir/lib/Transforms/CMakeLists.txt @@ -2,6 +2,7 @@ add_subdirectory(Utils) add_mlir_library(MLIRTransforms Canonicalizer.cpp + CompositePass.cpp ControlFlowSink.cpp CSE.cpp GenerateRuntimeVerification.cpp diff --git a/mlir/lib/Transforms/CompositePass.cpp b/mlir/lib/Transforms/CompositePass.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b388a28da6424f80ae10934f74a7a2b3fe8d8545 --- /dev/null +++ b/mlir/lib/Transforms/CompositePass.cpp @@ -0,0 +1,105 @@ +//===- CompositePass.cpp - Composite pass code ----------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// CompositePass allows to run set of passes until fixed point is reached. +// +//===----------------------------------------------------------------------===// + +#include "mlir/Transforms/Passes.h" + +#include "mlir/Pass/Pass.h" +#include "mlir/Pass/PassManager.h" + +namespace mlir { +#define GEN_PASS_DEF_COMPOSITEFIXEDPOINTPASS +#include "mlir/Transforms/Passes.h.inc" +} // namespace mlir + +using namespace mlir; + +namespace { +struct CompositeFixedPointPass final + : public impl::CompositeFixedPointPassBase<CompositeFixedPointPass> { + using CompositeFixedPointPassBase::CompositeFixedPointPassBase; + + CompositeFixedPointPass( + std::string name_, llvm::function_ref<void(OpPassManager &)> populateFunc, + int maxIterations) { + name = std::move(name_); + maxIter = maxIterations; + populateFunc(dynamicPM); + + llvm::raw_string_ostream os(pipelineStr); + dynamicPM.printAsTextualPipeline(os); + } + + LogicalResult initializeOptions( + StringRef options, + function_ref<LogicalResult(const Twine &)> errorHandler) override { + if (failed(CompositeFixedPointPassBase::initializeOptions(options, + errorHandler))) + return failure(); + + if (failed(parsePassPipeline(pipelineStr, dynamicPM))) + return errorHandler("Failed to parse composite pass pipeline"); + + return success(); + } + + LogicalResult initialize(MLIRContext *context) override { + if (maxIter <= 0) + return emitError(UnknownLoc::get(context)) + << "Invalid maxIterations value: " << maxIter << "\n"; + + return success(); + } + + void getDependentDialects(DialectRegistry ®istry) const override { + dynamicPM.getDependentDialects(registry); + } + + void runOnOperation() override { + auto op = getOperation(); + OperationFingerPrint fp(op); + + int currentIter = 0; + int maxIterVal = maxIter; + while (true) { + if (failed(runPipeline(dynamicPM, op))) + return signalPassFailure(); + + if (currentIter++ >= maxIterVal) { + op->emitWarning("Composite pass \"" + llvm::Twine(name) + + "\"+ didn't converge in " + llvm::Twine(maxIterVal) + + " iterations"); + break; + } + + OperationFingerPrint newFp(op); + if (newFp == fp) + break; + + fp = newFp; + } + } + +protected: + llvm::StringRef getName() const override { return name; } + +private: + OpPassManager dynamicPM; +}; +} // namespace + +std::unique_ptr<Pass> mlir::createCompositeFixedPointPass( + std::string name, llvm::function_ref<void(OpPassManager &)> populateFunc, + int maxIterations) { + + return std::make_unique<CompositeFixedPointPass>(std::move(name), + populateFunc, maxIterations); +} diff --git a/mlir/lib/Transforms/InlinerPass.cpp b/mlir/lib/Transforms/InlinerPass.cpp index c058e8050cd199393d2bf70664fd706442a1aafd..04b2f9e419187792713ee604e447fc818c9bb058 100644 --- a/mlir/lib/Transforms/InlinerPass.cpp +++ b/mlir/lib/Transforms/InlinerPass.cpp @@ -24,6 +24,8 @@ namespace mlir { #include "mlir/Transforms/Passes.h.inc" } // namespace mlir +#define DEBUG_TYPE "inliner-pass" + using namespace mlir; /// This function implements the inliner optimization pipeline. @@ -62,7 +64,9 @@ private: /// Derived classes may override this method to hook into the point at which /// options are initialized, but should generally always invoke this base /// class variant. - LogicalResult initializeOptions(StringRef options) override; + LogicalResult initializeOptions( + StringRef options, + function_ref<LogicalResult(const Twine &)> errorHandler) override; /// Inliner configuration parameters created from the pass options. InlinerConfig config; @@ -88,6 +92,39 @@ InlinerPass::InlinerPass(std::function<void(OpPassManager &)> defaultPipeline, config.setOpPipelines(std::move(opPipelines)); } +// Return true if the inlining ratio does not exceed the threshold. +static bool isProfitableToInline(const Inliner::ResolvedCall &resolvedCall, + unsigned inliningThreshold) { + // Return early, ratio <= 0U will always be false. + if (inliningThreshold == 0U) + return false; + // Return early, ratio <= -1U will always be true. + if (inliningThreshold == -1U) + return true; + + Region *callerRegion = resolvedCall.sourceNode->getCallableRegion(); + Region *calleeRegion = resolvedCall.targetNode->getCallableRegion(); + + assert(calleeRegion && callerRegion && "unexpected external node"); + + auto countOps = [](Region *region) { + unsigned count = 0; + region->walk([&](Operation *) { ++count; }); + return count; + }; + + unsigned callerOps = countOps(callerRegion); + + // Always inline empty callees (if it is possible at all). + if (callerOps == 0) + return true; + + unsigned ratio = countOps(calleeRegion) * 100 / callerOps; + LLVM_DEBUG(llvm::dbgs() << "Callee / caller operation ratio (max: " + << inliningThreshold << "%): " << ratio << "%\n"); + return ratio <= inliningThreshold; +} + void InlinerPass::runOnOperation() { CallGraph &cg = getAnalysis<CallGraph>(); @@ -100,9 +137,14 @@ void InlinerPass::runOnOperation() { return signalPassFailure(); } + // By default, assume that any inlining is profitable. + auto profitabilityCb = [=](const Inliner::ResolvedCall &call) { + return isProfitableToInline(call, inliningThreshold); + }; + // Get an instance of the inliner. Inliner inliner(op, cg, *this, getAnalysisManager(), runPipelineHelper, - config); + config, profitabilityCb); // Run the inlining. if (failed(inliner.doInlining())) @@ -110,8 +152,10 @@ void InlinerPass::runOnOperation() { return; } -LogicalResult InlinerPass::initializeOptions(StringRef options) { - if (failed(Pass::initializeOptions(options))) +LogicalResult InlinerPass::initializeOptions( + StringRef options, + function_ref<LogicalResult(const Twine &)> errorHandler) { + if (failed(Pass::initializeOptions(options, errorHandler))) return failure(); // Initialize the pipeline builder for operations without the dedicated diff --git a/mlir/lib/Transforms/Mem2Reg.cpp b/mlir/lib/Transforms/Mem2Reg.cpp index f3a973d9994083cab7ccf75528294f829869f1f9..80e3b79016329778833a7946d987f97330ea8d02 100644 --- a/mlir/lib/Transforms/Mem2Reg.cpp +++ b/mlir/lib/Transforms/Mem2Reg.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "mlir/Transforms/Mem2Reg.h" +#include "mlir/Analysis/DataLayoutAnalysis.h" #include "mlir/Analysis/SliceAnalysis.h" #include "mlir/IR/Builders.h" #include "mlir/IR/Dominance.h" @@ -14,10 +15,8 @@ #include "mlir/IR/Value.h" #include "mlir/Interfaces/ControlFlowInterfaces.h" #include "mlir/Interfaces/MemorySlotInterfaces.h" -#include "mlir/Transforms/GreedyPatternRewriteDriver.h" #include "mlir/Transforms/Passes.h" #include "mlir/Transforms/RegionUtils.h" -#include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Casting.h" #include "llvm/Support/GenericIteratedDominanceFrontier.h" @@ -119,8 +118,9 @@ struct MemorySlotPromotionInfo { /// promotion. This does not mutate IR. class MemorySlotPromotionAnalyzer { public: - MemorySlotPromotionAnalyzer(MemorySlot slot, DominanceInfo &dominance) - : slot(slot), dominance(dominance) {} + MemorySlotPromotionAnalyzer(MemorySlot slot, DominanceInfo &dominance, + const DataLayout &dataLayout) + : slot(slot), dominance(dominance), dataLayout(dataLayout) {} /// Computes the information for slot promotion if promotion is possible, /// returns nothing otherwise. @@ -155,6 +155,7 @@ private: MemorySlot slot; DominanceInfo &dominance; + const DataLayout &dataLayout; }; /// The MemorySlotPromoter handles the state of promoting a memory slot. It @@ -269,10 +270,12 @@ LogicalResult MemorySlotPromotionAnalyzer::computeBlockingUses( // If the operation decides it cannot deal with removing the blocking uses, // promotion must fail. if (auto promotable = dyn_cast<PromotableOpInterface>(user)) { - if (!promotable.canUsesBeRemoved(blockingUses, newBlockingUses)) + if (!promotable.canUsesBeRemoved(blockingUses, newBlockingUses, + dataLayout)) return failure(); } else if (auto promotable = dyn_cast<PromotableMemOpInterface>(user)) { - if (!promotable.canUsesBeRemoved(slot, blockingUses, newBlockingUses)) + if (!promotable.canUsesBeRemoved(slot, blockingUses, newBlockingUses, + dataLayout)) return failure(); } else { // An operation that has blocking uses must be promoted. If it is not @@ -612,7 +615,8 @@ void MemorySlotPromoter::promoteSlot() { LogicalResult mlir::tryToPromoteMemorySlots( ArrayRef<PromotableAllocationOpInterface> allocators, - RewriterBase &rewriter, Mem2RegStatistics statistics) { + RewriterBase &rewriter, const DataLayout &dataLayout, + Mem2RegStatistics statistics) { bool promotedAny = false; for (PromotableAllocationOpInterface allocator : allocators) { @@ -621,7 +625,7 @@ LogicalResult mlir::tryToPromoteMemorySlots( continue; DominanceInfo dominance; - MemorySlotPromotionAnalyzer analyzer(slot, dominance); + MemorySlotPromotionAnalyzer analyzer(slot, dominance, dataLayout); std::optional<MemorySlotPromotionInfo> info = analyzer.computeInfo(); if (info) { MemorySlotPromoter(slot, allocator, rewriter, dominance, @@ -635,13 +639,6 @@ LogicalResult mlir::tryToPromoteMemorySlots( return success(promotedAny); } -LogicalResult -Mem2RegPattern::matchAndRewrite(PromotableAllocationOpInterface allocator, - PatternRewriter &rewriter) const { - hasBoundedRewriteRecursion(); - return tryToPromoteMemorySlots({allocator}, rewriter, statistics); -} - namespace { struct Mem2Reg : impl::Mem2RegBase<Mem2Reg> { @@ -650,17 +647,40 @@ struct Mem2Reg : impl::Mem2RegBase<Mem2Reg> { void runOnOperation() override { Operation *scopeOp = getOperation(); - Mem2RegStatistics statictics{&promotedAmount, &newBlockArgumentAmount}; + Mem2RegStatistics statistics{&promotedAmount, &newBlockArgumentAmount}; + + bool changed = false; + + for (Region ®ion : scopeOp->getRegions()) { + if (region.getBlocks().empty()) + continue; + + OpBuilder builder(®ion.front(), region.front().begin()); + IRRewriter rewriter(builder); + + // Promoting a slot can allow for further promotion of other slots, + // promotion is tried until no promotion succeeds. + while (true) { + SmallVector<PromotableAllocationOpInterface> allocators; + // Build a list of allocators to attempt to promote the slots of. + region.walk([&](PromotableAllocationOpInterface allocator) { + allocators.emplace_back(allocator); + }); - GreedyRewriteConfig config; - config.enableRegionSimplification = enableRegionSimplification; + auto &dataLayoutAnalysis = getAnalysis<DataLayoutAnalysis>(); + const DataLayout &dataLayout = dataLayoutAnalysis.getAtOrAbove(scopeOp); - RewritePatternSet rewritePatterns(&getContext()); - rewritePatterns.add<Mem2RegPattern>(&getContext(), statictics); - FrozenRewritePatternSet frozen(std::move(rewritePatterns)); + // Attempt promoting until no promotion succeeds. + if (failed(tryToPromoteMemorySlots(allocators, rewriter, dataLayout, + statistics))) + break; - if (failed(applyPatternsAndFoldGreedily(scopeOp, frozen, config))) - signalPassFailure(); + changed = true; + getAnalysisManager().invalidate({}); + } + } + if (!changed) + markAllAnalysesPreserved(); } }; diff --git a/mlir/lib/Transforms/SROA.cpp b/mlir/lib/Transforms/SROA.cpp index 3ceda51e1c894c735afdd5a42b82a2a3486a5ada..f24cbb7b1725ccf26efb9cf14c35b8ad45c47ddb 100644 --- a/mlir/lib/Transforms/SROA.cpp +++ b/mlir/lib/Transforms/SROA.cpp @@ -7,9 +7,9 @@ //===----------------------------------------------------------------------===// #include "mlir/Transforms/SROA.h" +#include "mlir/Analysis/DataLayoutAnalysis.h" #include "mlir/Analysis/SliceAnalysis.h" #include "mlir/Interfaces/MemorySlotInterfaces.h" -#include "mlir/Transforms/GreedyPatternRewriteDriver.h" #include "mlir/Transforms/Passes.h" namespace mlir { @@ -43,7 +43,8 @@ struct MemorySlotDestructuringInfo { /// nothing if the slot cannot be destructured or if there is no useful work to /// be done. static std::optional<MemorySlotDestructuringInfo> -computeDestructuringInfo(DestructurableMemorySlot &slot) { +computeDestructuringInfo(DestructurableMemorySlot &slot, + const DataLayout &dataLayout) { assert(isa<DestructurableTypeInterface>(slot.elemType)); if (slot.ptr.use_empty()) @@ -63,7 +64,8 @@ computeDestructuringInfo(DestructurableMemorySlot &slot) { for (OpOperand &use : slot.ptr.getUses()) { if (auto accessor = dyn_cast<DestructurableAccessorOpInterface>(use.getOwner())) { - if (accessor.canRewire(slot, info.usedIndices, usedSafelyWorklist)) { + if (accessor.canRewire(slot, info.usedIndices, usedSafelyWorklist, + dataLayout)) { info.accessors.push_back(accessor); continue; } @@ -83,8 +85,8 @@ computeDestructuringInfo(DestructurableMemorySlot &slot) { Operation *subslotUser = subslotUse.getOwner(); if (auto memOp = dyn_cast<SafeMemorySlotAccessOpInterface>(subslotUser)) - if (succeeded(memOp.ensureOnlySafeAccesses(mustBeUsedSafely, - usedSafelyWorklist))) + if (succeeded(memOp.ensureOnlySafeAccesses( + mustBeUsedSafely, usedSafelyWorklist, dataLayout))) continue; // If it cannot be shown that the operation uses the slot safely, maybe it @@ -111,7 +113,7 @@ computeDestructuringInfo(DestructurableMemorySlot &slot) { SmallVector<OpOperand *> newBlockingUses; // If the operation decides it cannot deal with removing the blocking uses, // destructuring must fail. - if (!promotable.canUsesBeRemoved(blockingUses, newBlockingUses)) + if (!promotable.canUsesBeRemoved(blockingUses, newBlockingUses, dataLayout)) return {}; // Then, register any new blocking uses for coming operations. @@ -133,6 +135,7 @@ computeDestructuringInfo(DestructurableMemorySlot &slot) { static void destructureSlot(DestructurableMemorySlot &slot, DestructurableAllocationOpInterface allocator, RewriterBase &rewriter, + const DataLayout &dataLayout, MemorySlotDestructuringInfo &info, const SROAStatistics &statistics) { RewriterBase::InsertionGuard guard(rewriter); @@ -159,7 +162,8 @@ static void destructureSlot(DestructurableMemorySlot &slot, for (Operation *toRewire : llvm::reverse(usersToRewire)) { rewriter.setInsertionPointAfter(toRewire); if (auto accessor = dyn_cast<DestructurableAccessorOpInterface>(toRewire)) { - if (accessor.rewire(slot, subslots, rewriter) == DeletionKind::Delete) + if (accessor.rewire(slot, subslots, rewriter, dataLayout) == + DeletionKind::Delete) toErase.push_back(accessor); continue; } @@ -187,17 +191,18 @@ static void destructureSlot(DestructurableMemorySlot &slot, LogicalResult mlir::tryToDestructureMemorySlots( ArrayRef<DestructurableAllocationOpInterface> allocators, - RewriterBase &rewriter, SROAStatistics statistics) { + RewriterBase &rewriter, const DataLayout &dataLayout, + SROAStatistics statistics) { bool destructuredAny = false; for (DestructurableAllocationOpInterface allocator : allocators) { for (DestructurableMemorySlot slot : allocator.getDestructurableSlots()) { std::optional<MemorySlotDestructuringInfo> info = - computeDestructuringInfo(slot); + computeDestructuringInfo(slot, dataLayout); if (!info) continue; - destructureSlot(slot, allocator, rewriter, *info, statistics); + destructureSlot(slot, allocator, rewriter, dataLayout, *info, statistics); destructuredAny = true; } } @@ -205,13 +210,6 @@ LogicalResult mlir::tryToDestructureMemorySlots( return success(destructuredAny); } -LogicalResult -SROAPattern::matchAndRewrite(DestructurableAllocationOpInterface allocator, - PatternRewriter &rewriter) const { - hasBoundedRewriteRecursion(); - return tryToDestructureMemorySlots({allocator}, rewriter, statistics); -} - namespace { struct SROA : public impl::SROABase<SROA> { @@ -223,12 +221,37 @@ struct SROA : public impl::SROABase<SROA> { SROAStatistics statistics{&destructuredAmount, &slotsWithMemoryBenefit, &maxSubelementAmount}; - RewritePatternSet rewritePatterns(&getContext()); - rewritePatterns.add<SROAPattern>(&getContext(), statistics); - FrozenRewritePatternSet frozen(std::move(rewritePatterns)); + auto &dataLayoutAnalysis = getAnalysis<DataLayoutAnalysis>(); + const DataLayout &dataLayout = dataLayoutAnalysis.getAtOrAbove(scopeOp); + bool changed = false; + + for (Region ®ion : scopeOp->getRegions()) { + if (region.getBlocks().empty()) + continue; - if (failed(applyPatternsAndFoldGreedily(scopeOp, frozen))) - signalPassFailure(); + OpBuilder builder(®ion.front(), region.front().begin()); + IRRewriter rewriter(builder); + + // Destructuring a slot can allow for further destructuring of other + // slots, destructuring is tried until no destructuring succeeds. + while (true) { + SmallVector<DestructurableAllocationOpInterface> allocators; + // Build a list of allocators to attempt to destructure the slots of. + // TODO: Update list on the fly to avoid repeated visiting of the same + // allocators. + region.walk([&](DestructurableAllocationOpInterface allocator) { + allocators.emplace_back(allocator); + }); + + if (failed(tryToDestructureMemorySlots(allocators, rewriter, dataLayout, + statistics))) + break; + + changed = true; + } + } + if (!changed) + markAllAnalysesPreserved(); } }; diff --git a/mlir/lib/Transforms/Utils/DialectConversion.cpp b/mlir/lib/Transforms/Utils/DialectConversion.cpp index 2ec0b964b304f6a4550b25e0c174c339496b53c4..8671c1008902a0b2b71460ceaa69f217d21891b1 100644 --- a/mlir/lib/Transforms/Utils/DialectConversion.cpp +++ b/mlir/lib/Transforms/Utils/DialectConversion.cpp @@ -2825,9 +2825,9 @@ static void computeNecessaryMaterializations( } // Check to see if this is an argument materialization. - auto isBlockArg = [](Value v) { return isa<BlockArgument>(v); }; - if (llvm::any_of(op->getOperands(), isBlockArg) || - llvm::any_of(inverseMapping[op->getResult(0)], isBlockArg)) { + if (llvm::any_of(op->getOperands(), llvm::IsaPred<BlockArgument>) || + llvm::any_of(inverseMapping[op->getResult(0)], + llvm::IsaPred<BlockArgument>)) { mat->setMaterializationKind(MaterializationKind::Argument); } diff --git a/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp b/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp index 6cb5635e68c922d177a5ffcae96c3a0eace440ca..bbecbdb85669359e0a74325655f6f7044338b939 100644 --- a/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp +++ b/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp @@ -377,7 +377,7 @@ private: /// be re-added to the worklist. This function should be called when an /// operation is modified or removed, as it may trigger further /// simplifications. - void addOperandsToWorklist(ValueRange operands); + void addOperandsToWorklist(Operation *op); /// Notify the driver that the given block was inserted. void notifyBlockInserted(Block *block, Region *previous, @@ -688,17 +688,36 @@ void GreedyPatternRewriteDriver::notifyOperationModified(Operation *op) { addToWorklist(op); } -void GreedyPatternRewriteDriver::addOperandsToWorklist(ValueRange operands) { - for (Value operand : operands) { - // If the use count of this operand is now < 2, we re-add the defining - // operation to the worklist. - // TODO: This is based on the fact that zero use operations - // may be deleted, and that single use values often have more - // canonicalization opportunities. - if (!operand || (!operand.use_empty() && !operand.hasOneUse())) +void GreedyPatternRewriteDriver::addOperandsToWorklist(Operation *op) { + for (Value operand : op->getOperands()) { + // If this operand currently has at most 2 users, add its defining op to the + // worklist. Indeed, after the op is deleted, then the operand will have at + // most 1 user left. If it has 0 users left, it can be deleted too, + // and if it has 1 user left, there may be further canonicalization + // opportunities. + if (!operand) continue; - if (auto *defOp = operand.getDefiningOp()) - addToWorklist(defOp); + + auto *defOp = operand.getDefiningOp(); + if (!defOp) + continue; + + Operation *otherUser = nullptr; + bool hasMoreThanTwoUses = false; + for (auto user : operand.getUsers()) { + if (user == op || user == otherUser) + continue; + if (!otherUser) { + otherUser = user; + continue; + } + hasMoreThanTwoUses = true; + break; + } + if (hasMoreThanTwoUses) + continue; + + addToWorklist(defOp); } } @@ -722,7 +741,7 @@ void GreedyPatternRewriteDriver::notifyOperationErased(Operation *op) { if (config.listener) config.listener->notifyOperationErased(op); - addOperandsToWorklist(op->getOperands()); + addOperandsToWorklist(op); worklist.remove(op); if (config.strictMode != GreedyRewriteStrictness::AnyOp) diff --git a/mlir/lib/Transforms/Utils/Inliner.cpp b/mlir/lib/Transforms/Utils/Inliner.cpp index f227cedb269d81bcfa2c041397f543c215051791..8acfc96d2b611b2a91f87b8dbd7a0d3cc3ab2ba5 100644 --- a/mlir/lib/Transforms/Utils/Inliner.cpp +++ b/mlir/lib/Transforms/Utils/Inliner.cpp @@ -741,6 +741,9 @@ bool Inliner::Impl::shouldInline(ResolvedCall &resolvedCall) { if (calleeHasMultipleBlocks && !callerRegionSupportsMultipleBlocks()) return false; + if (!inliner.isProfitableToInline(resolvedCall)) + return false; + // Otherwise, inline. return true; } diff --git a/mlir/lib/Transforms/Utils/OneToNTypeConversion.cpp b/mlir/lib/Transforms/Utils/OneToNTypeConversion.cpp index 7cb957d5ec29ea8b9870ab0e9666765b845d7575..fef9d8eb0fef74f2ef978bf5c6460318d62c5fc3 100644 --- a/mlir/lib/Transforms/Utils/OneToNTypeConversion.cpp +++ b/mlir/lib/Transforms/Utils/OneToNTypeConversion.cpp @@ -392,8 +392,7 @@ applyPartialOneToNConversion(Operation *op, OneToNTypeConverter &typeConverter, // Argument materialization. assert(castKind == getCastKindName(CastKind::Argument) && "unexpected value of cast kind attribute"); - assert(llvm::all_of(operands, - [&](Value v) { return isa<BlockArgument>(v); })); + assert(llvm::all_of(operands, llvm::IsaPred<BlockArgument>)); maybeResult = typeConverter.materializeArgumentConversion( rewriter, castOp->getLoc(), resultTypes.front(), castOp.getOperands()); diff --git a/mlir/python/CMakeLists.txt b/mlir/python/CMakeLists.txt index 563d035f1552676782ef993cc0f91d539210b4af..c27ee688a04087f7a06d521fe75ccb8d43598345 100644 --- a/mlir/python/CMakeLists.txt +++ b/mlir/python/CMakeLists.txt @@ -108,6 +108,15 @@ declare_mlir_dialect_python_bindings( dialects/complex.py DIALECT_NAME complex) +declare_mlir_dialect_python_bindings( + ADD_TO_PARENT MLIRPythonSources.Dialects + ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mlir" + TD_FILE dialects/IndexOps.td + SOURCES + dialects/index.py + DIALECT_NAME index + GEN_ENUM_BINDINGS) + declare_mlir_dialect_python_bindings( ADD_TO_PARENT MLIRPythonSources.Dialects ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mlir" diff --git a/mlir/python/mlir/dialects/IndexOps.td b/mlir/python/mlir/dialects/IndexOps.td new file mode 100644 index 0000000000000000000000000000000000000000..13b1d782c8536c35352aad730a2dc88540458d3d --- /dev/null +++ b/mlir/python/mlir/dialects/IndexOps.td @@ -0,0 +1,14 @@ +//===-- IndexOps.td - Entry point for Index bindings -----*- tablegen -*---===// +// +// 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 PYTHON_BINDINGS_INDEX_OPS +#define PYTHON_BINDINGS_INDEX_OPS + +include "mlir/Dialect/Index/IR/IndexOps.td" + +#endif diff --git a/mlir/python/mlir/dialects/index.py b/mlir/python/mlir/dialects/index.py new file mode 100644 index 0000000000000000000000000000000000000000..73708c7d71a8c835a5d9d7d85de8332a6b6230f6 --- /dev/null +++ b/mlir/python/mlir/dialects/index.py @@ -0,0 +1,6 @@ +# 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 + +from ._index_ops_gen import * +from ._index_enum_gen import * diff --git a/mlir/python/requirements.txt b/mlir/python/requirements.txt index a596f8747ebe7688d72493207aa79ec1c8961a9f..acd6dbb25edaf518ea091c36b83115bef5729849 100644 --- a/mlir/python/requirements.txt +++ b/mlir/python/requirements.txt @@ -1,4 +1,3 @@ numpy>=1.19.5, <=1.26 pybind11>=2.9.0, <=2.10.3 -PyYAML>=5.3.1, <=6.0.1 -dataclasses>=0.6, <=0.8 \ No newline at end of file +PyYAML>=5.3.1, <=6.0.1 \ No newline at end of file diff --git a/mlir/test/CAPI/llvm.c b/mlir/test/CAPI/llvm.c index 2fd98b29f487c8fad863b915290bd8e69b3d7e5e..9c3c7da46c4cd83e77fe03d37d23cd7b8f72e578 100644 --- a/mlir/test/CAPI/llvm.c +++ b/mlir/test/CAPI/llvm.c @@ -297,11 +297,11 @@ static void testDebugInfoAttributes(MlirContext ctx) { 1, 0, 8, di_type)); // CHECK: #llvm.di_derived_type<{{.*}}> mlirAttributeDump( - mlirLLVMDIDerivedTypeAttrGet(ctx, 0, bar, di_type, 64, 8, 0)); + mlirLLVMDIDerivedTypeAttrGet(ctx, 0, bar, di_type, 64, 8, 0, di_type)); // CHECK: #llvm.di_composite_type<{{.*}}> mlirAttributeDump(mlirLLVMDICompositeTypeAttrGet( - ctx, 0, foo, file, 1, compile_unit, di_type, 0, 64, 8, 1, &di_type)); + ctx, 0, id, foo, file, 1, compile_unit, di_type, 0, 64, 8, 1, &di_type)); MlirAttribute subroutine_type = mlirLLVMDISubroutineTypeAttrGet(ctx, 0x0, 1, &di_type); diff --git a/mlir/test/Conversion/ArithToEmitC/arith-to-emitc-failed.mlir b/mlir/test/Conversion/ArithToEmitC/arith-to-emitc-failed.mlir new file mode 100644 index 0000000000000000000000000000000000000000..30abd81f3d44707dc38a346160610348659eff6a --- /dev/null +++ b/mlir/test/Conversion/ArithToEmitC/arith-to-emitc-failed.mlir @@ -0,0 +1,15 @@ +// RUN: mlir-opt -convert-arith-to-emitc %s -split-input-file -verify-diagnostics + +func.func @bool(%arg0: i1, %arg1: i1) { + // expected-error@+1 {{failed to legalize operation 'arith.addi'}} + %0 = arith.addi %arg0, %arg1 : i1 + return +} + +// ----- + +func.func @vector(%arg0: vector<4xi32>, %arg1: vector<4xi32>) { + // expected-error@+1 {{failed to legalize operation 'arith.addi'}} + %0 = arith.addi %arg0, %arg1 : vector<4xi32> + return +} diff --git a/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir b/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir index 022530ef4db84b36cc1f932dd31e0d0c049d44ab..76ba518577ab8e5688c4c34f2ce3673dc22d2ca9 100644 --- a/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir +++ b/mlir/test/Conversion/ArithToEmitC/arith-to-emitc.mlir @@ -37,6 +37,57 @@ func.func @arith_ops(%arg0: f32, %arg1: f32) { // ----- +// CHECK-LABEL: arith_integer_ops +func.func @arith_integer_ops(%arg0: i32, %arg1: i32) { + // CHECK: %[[C1:[^ ]*]] = emitc.cast %arg0 : i32 to ui32 + // CHECK: %[[C2:[^ ]*]] = emitc.cast %arg1 : i32 to ui32 + // CHECK: %[[ADD:[^ ]*]] = emitc.add %[[C1]], %[[C2]] : (ui32, ui32) -> ui32 + // CHECK: %[[C3:[^ ]*]] = emitc.cast %[[ADD]] : ui32 to i32 + %0 = arith.addi %arg0, %arg1 : i32 + // CHECK: %[[C1:[^ ]*]] = emitc.cast %arg0 : i32 to ui32 + // CHECK: %[[C2:[^ ]*]] = emitc.cast %arg1 : i32 to ui32 + // CHECK: %[[SUB:[^ ]*]] = emitc.sub %[[C1]], %[[C2]] : (ui32, ui32) -> ui32 + // CHECK: %[[C3:[^ ]*]] = emitc.cast %[[SUB]] : ui32 to i32 + %1 = arith.subi %arg0, %arg1 : i32 + // CHECK: %[[C1:[^ ]*]] = emitc.cast %arg0 : i32 to ui32 + // CHECK: %[[C2:[^ ]*]] = emitc.cast %arg1 : i32 to ui32 + // CHECK: %[[MUL:[^ ]*]] = emitc.mul %[[C1]], %[[C2]] : (ui32, ui32) -> ui32 + // CHECK: %[[C3:[^ ]*]] = emitc.cast %[[MUL]] : ui32 to i32 + %2 = arith.muli %arg0, %arg1 : i32 + + return +} + +// ----- + +// CHECK-LABEL: arith_integer_ops_signed_nsw +func.func @arith_integer_ops_signed_nsw(%arg0: i32, %arg1: i32) { + // CHECK: emitc.add %arg0, %arg1 : (i32, i32) -> i32 + %0 = arith.addi %arg0, %arg1 overflow<nsw> : i32 + // CHECK: emitc.sub %arg0, %arg1 : (i32, i32) -> i32 + %1 = arith.subi %arg0, %arg1 overflow<nsw> : i32 + // CHECK: emitc.mul %arg0, %arg1 : (i32, i32) -> i32 + %2 = arith.muli %arg0, %arg1 overflow<nsw> : i32 + + return +} + +// ----- + +// CHECK-LABEL: arith_index +func.func @arith_index(%arg0: index, %arg1: index) { + // CHECK: emitc.add %arg0, %arg1 : (index, index) -> index + %0 = arith.addi %arg0, %arg1 : index + // CHECK: emitc.sub %arg0, %arg1 : (index, index) -> index + %1 = arith.subi %arg0, %arg1 : index + // CHECK: emitc.mul %arg0, %arg1 : (index, index) -> index + %2 = arith.muli %arg0, %arg1 : index + + return +} + +// ----- + func.func @arith_select(%arg0: i1, %arg1: tensor<8xi32>, %arg2: tensor<8xi32>) -> () { // CHECK: [[V0:[^ ]*]] = emitc.conditional %arg0, %arg1, %arg2 : tensor<8xi32> %0 = arith.select %arg0, %arg1, %arg2 : i1, tensor<8xi32> diff --git a/mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir b/mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir index 29268eef47e853478a9972edd7e2c21fb46a2d08..56ae930e6d6273d561260eefea6c8b04ccfd5237 100644 --- a/mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir +++ b/mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir @@ -289,6 +289,21 @@ func.func @fptrunc_vector(%arg0 : vector<2xf32>, %arg1 : vector<2xf64>) { return } +// CHECK-LABEL: experimental_constrained_fptrunc +func.func @experimental_constrained_fptrunc(%arg0 : f64) { +// CHECK-NEXT: = llvm.intr.experimental.constrained.fptrunc {{.*}} tonearest ignore : f64 to f32 + %0 = arith.truncf %arg0 to_nearest_even : f64 to f32 +// CHECK-NEXT: = llvm.intr.experimental.constrained.fptrunc {{.*}} downward ignore : f64 to f32 + %1 = arith.truncf %arg0 downward : f64 to f32 +// CHECK-NEXT: = llvm.intr.experimental.constrained.fptrunc {{.*}} upward ignore : f64 to f32 + %2 = arith.truncf %arg0 upward : f64 to f32 +// CHECK-NEXT: = llvm.intr.experimental.constrained.fptrunc {{.*}} towardzero ignore : f64 to f32 + %3 = arith.truncf %arg0 toward_zero : f64 to f32 +// CHECK-NEXT: = llvm.intr.experimental.constrained.fptrunc {{.*}} tonearestaway ignore : f64 to f32 + %4 = arith.truncf %arg0 to_nearest_away : f64 to f32 + return +} + // Check sign and zero extension and truncation of integers. // CHECK-LABEL: @integer_extension_and_truncation func.func @integer_extension_and_truncation(%arg0 : i3) { diff --git a/mlir/test/Conversion/ArithToSPIRV/fast-math.mlir b/mlir/test/Conversion/ArithToSPIRV/fast-math.mlir index dbf0361c2ab35bb9c13b26a809128c33795a0a7b..9bbe28fb127a7868c5529fac944d02f9ed3e724c 100644 --- a/mlir/test/Conversion/ArithToSPIRV/fast-math.mlir +++ b/mlir/test/Conversion/ArithToSPIRV/fast-math.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-opt -split-input-file -convert-arith-to-spirv=enable-fast-math -verify-diagnostics %s | FileCheck %s +// RUN: mlir-opt -split-input-file -convert-arith-to-spirv -verify-diagnostics %s | FileCheck %s module attributes { spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [], []>, #spirv.resource_limits<>> @@ -8,7 +8,7 @@ module attributes { // CHECK-SAME: %[[LHS:.+]]: f32, %[[RHS:.+]]: f32 func.func @cmpf_ordered(%arg0 : f32, %arg1 : f32) -> i1 { // CHECK: %[[T:.+]] = spirv.Constant true - %0 = arith.cmpf ord, %arg0, %arg1 : f32 + %0 = arith.cmpf ord, %arg0, %arg1 fastmath<fast> : f32 // CHECK: return %[[T]] return %0: i1 } @@ -17,7 +17,7 @@ func.func @cmpf_ordered(%arg0 : f32, %arg1 : f32) -> i1 { // CHECK-SAME: %[[LHS:.+]]: vector<4xf32>, %[[RHS:.+]]: vector<4xf32> func.func @cmpf_unordered(%arg0 : vector<4xf32>, %arg1 : vector<4xf32>) -> vector<4xi1> { // CHECK: %[[F:.+]] = spirv.Constant dense<false> - %0 = arith.cmpf uno, %arg0, %arg1 : vector<4xf32> + %0 = arith.cmpf uno, %arg0, %arg1 fastmath<nnan> : vector<4xf32> // CHECK: return %[[F]] return %0: vector<4xi1> } @@ -34,7 +34,7 @@ module attributes { // CHECK-SAME: %[[LHS:.+]]: f32, %[[RHS:.+]]: f32 func.func @minimumf(%arg0 : f32, %arg1 : f32) -> f32 { // CHECK: %[[F:.+]] = spirv.GL.FMin %[[LHS]], %[[RHS]] - %0 = arith.minimumf %arg0, %arg1 : f32 + %0 = arith.minimumf %arg0, %arg1 fastmath<fast> : f32 // CHECK: return %[[F]] return %0: f32 } @@ -43,7 +43,7 @@ func.func @minimumf(%arg0 : f32, %arg1 : f32) -> f32 { // CHECK-SAME: %[[LHS:.+]]: vector<4xf32>, %[[RHS:.+]]: vector<4xf32> func.func @maximumf(%arg0 : vector<4xf32>, %arg1 : vector<4xf32>) -> vector<4xf32> { // CHECK: %[[F:.+]] = spirv.GL.FMax %[[LHS]], %[[RHS]] - %0 = arith.maximumf %arg0, %arg1 : vector<4xf32> + %0 = arith.maximumf %arg0, %arg1 fastmath<fast> : vector<4xf32> // CHECK: return %[[F]] return %0: vector<4xf32> } @@ -52,7 +52,7 @@ func.func @maximumf(%arg0 : vector<4xf32>, %arg1 : vector<4xf32>) -> vector<4xf3 // CHECK-SAME: %[[LHS:.+]]: f32, %[[RHS:.+]]: f32 func.func @minnumf(%arg0 : f32, %arg1 : f32) -> f32 { // CHECK: %[[F:.+]] = spirv.GL.FMin %[[LHS]], %[[RHS]] - %0 = arith.minnumf %arg0, %arg1 : f32 + %0 = arith.minnumf %arg0, %arg1 fastmath<fast> : f32 // CHECK: return %[[F]] return %0: f32 } @@ -61,7 +61,7 @@ func.func @minnumf(%arg0 : f32, %arg1 : f32) -> f32 { // CHECK-SAME: %[[LHS:.+]]: vector<4xf32>, %[[RHS:.+]]: vector<4xf32> func.func @maxnumf(%arg0 : vector<4xf32>, %arg1 : vector<4xf32>) -> vector<4xf32> { // CHECK: %[[F:.+]] = spirv.GL.FMax %[[LHS]], %[[RHS]] - %0 = arith.maxnumf %arg0, %arg1 : vector<4xf32> + %0 = arith.maxnumf %arg0, %arg1 fastmath<fast> : vector<4xf32> // CHECK: return %[[F]] return %0: vector<4xf32> } diff --git a/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir b/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir index c80ba48cf8c1a3379bb46317bdcac8c5d20b2f39..bac94aae6b746ce19d3675b69f5392d9ee6d3491 100644 --- a/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir +++ b/mlir/test/Conversion/ComplexToStandard/convert-to-standard.mlir @@ -708,11 +708,60 @@ func.func @complex_tanh(%arg: complex<f32>) -> complex<f32> { // ----- // CHECK-LABEL: func @complex_sqrt +// CHECK-SAME: %[[ARG:.*]]: complex<f32> func.func @complex_sqrt(%arg: complex<f32>) -> complex<f32> { %sqrt = complex.sqrt %arg : complex<f32> return %sqrt : complex<f32> } +// CHECK: %[[CST:.*]] = arith.constant 0.000000e+00 : f32 +// CHECK: %[[VAR0:.*]] = complex.re %[[ARG]] : complex<f32> +// CHECK: %[[VAR1:.*]] = complex.im %[[ARG]] : complex<f32> +// CHECK: %[[VAR2:.*]] = math.absf %[[VAR0]] : f32 +// CHECK: %[[CST0:.*]] = arith.constant 0.000000e+00 : f32 +// CHECK: %[[CST1:.*]] = arith.constant 1.000000e+00 : f32 +// CHECK: %[[VAR3:.*]] = complex.re %[[ARG]] : complex<f32> +// CHECK: %[[VAR4:.*]] = complex.im %[[ARG]] : complex<f32> +// CHECK: %[[VAR5:.*]] = arith.cmpf oeq, %[[VAR3]], %[[CST0]] : f32 +// CHECK: %[[VAR6:.*]] = arith.cmpf oeq, %[[VAR4]], %[[CST0]] : f32 +// CHECK: %[[VAR7:.*]] = arith.divf %[[VAR4]], %[[VAR3]] : f32 +// CHECK: %[[VAR8:.*]] = arith.mulf %[[VAR7]], %[[VAR7]] : f32 +// CHECK: %[[VAR9:.*]] = arith.addf %[[VAR8]], %[[CST1]] : f32 +// CHECK: %[[VAR10:.*]] = math.sqrt %[[VAR9]] : f32 +// CHECK: %[[VAR11:.*]] = math.absf %[[VAR3]] : f32 +// CHECK: %[[VAR12:.*]] = arith.mulf %[[VAR10]], %[[VAR11]] : f32 +// CHECK: %[[VAR13:.*]] = arith.divf %[[VAR3]], %[[VAR4]] : f32 +// CHECK: %[[VAR14:.*]] = arith.mulf %[[VAR13]], %[[VAR13]] : f32 +// CHECK: %[[VAR15:.*]] = arith.addf %[[VAR14]], %[[CST1]] : f32 +// CHECK: %[[VAR16:.*]] = math.sqrt %[[VAR15]] : f32 +// CHECK: %[[VAR17:.*]] = math.absf %[[VAR4]] : f32 +// CHECK: %[[VAR18:.*]] = arith.mulf %[[VAR16]], %[[VAR17]] : f32 +// CHECK: %[[VAR19:.*]] = arith.cmpf ogt, %[[VAR3]], %[[VAR4]] : f32 +// CHECK: %[[VAR20:.*]] = arith.select %[[VAR19]], %[[VAR12]], %[[VAR18]] : f32 +// CHECK: %[[VAR21:.*]] = arith.select %[[VAR6]], %[[VAR11]], %[[VAR20]] : f32 +// CHECK: %[[VAR22:.*]] = arith.select %[[VAR5]], %[[VAR17]], %[[VAR21]] : f32 +// CHECK: %[[VAR23:.*]] = arith.addf %[[VAR2]], %[[VAR22]] : f32 +// CHECK: %[[CST2:.*]] = arith.constant 5.000000e-01 : f32 +// CHECK: %[[VAR24:.*]] = arith.mulf %[[VAR23]], %[[CST2]] : f32 +// CHECK: %[[VAR25:.*]] = math.sqrt %[[VAR24]] : f32 +// CHECK: %[[VAR26:.*]] = arith.cmpf olt, %[[VAR0]], %cst : f32 +// CHECK: %[[VAR27:.*]] = arith.cmpf olt, %[[VAR1]], %cst : f32 +// CHECK: %[[VAR28:.*]] = arith.addf %[[VAR25]], %[[VAR25]] : f32 +// CHECK: %[[VAR29:.*]] = arith.divf %[[VAR1]], %[[VAR28]] : f32 +// CHECK: %[[VAR30:.*]] = arith.negf %[[VAR25]] : f32 +// CHECK: %[[VAR31:.*]] = arith.select %[[VAR27]], %[[VAR30]], %[[VAR25]] : f32 +// CHECK: %[[VAR32:.*]] = arith.select %[[VAR26]], %[[VAR31]], %[[VAR29]] : f32 +// CHECK: %[[VAR33:.*]] = arith.addf %[[VAR32]], %[[VAR32]] : f32 +// CHECK: %[[VAR34:.*]] = arith.divf %[[VAR1]], %[[VAR33]] : f32 +// CHECK: %[[VAR35:.*]] = arith.select %[[VAR26]], %[[VAR34]], %[[VAR25]] : f32 +// CHECK: %[[VAR36:.*]] = arith.cmpf oeq, %[[VAR0]], %cst : f32 +// CHECK: %[[VAR37:.*]] = arith.cmpf oeq, %[[VAR1]], %cst : f32 +// CHECK: %[[VAR38:.*]] = arith.andi %[[VAR36]], %[[VAR37]] : i1 +// CHECK: %[[VAR39:.*]] = arith.select %[[VAR38]], %cst, %[[VAR35]] : f32 +// CHECK: %[[VAR40:.*]] = arith.select %[[VAR38]], %cst, %[[VAR32]] : f32 +// CHECK: %[[VAR41:.*]] = complex.create %[[VAR39]], %[[VAR40]] : complex<f32> +// CHECK: return %[[VAR41]] : complex<f32> + // ----- // CHECK-LABEL: func @complex_conj @@ -1254,42 +1303,42 @@ func.func @complex_atan2_with_fmf(%lhs: complex<f32>, // CHECK: %[[CST_6:.*]] = arith.constant 0.000000e+00 : f32 // CHECK: %[[VAR187:.*]] = complex.re %[[VAR186]] : complex<f32> // CHECK: %[[VAR188:.*]] = complex.im %[[VAR186]] : complex<f32> -// CHECK: %[[VAR189:.*]] = math.absf %[[VAR187]] : f32 +// CHECK: %[[VAR189:.*]] = math.absf %[[VAR187]] fastmath<nnan,contract> : f32 // CHECK: %[[CST_7:.*]] = arith.constant 0.000000e+00 : f32 // CHECK: %[[CST_8:.*]] = arith.constant 1.000000e+00 : f32 // CHECK: %[[VAR190:.*]] = complex.re %[[VAR186]] : complex<f32> // CHECK: %[[VAR191:.*]] = complex.im %[[VAR186]] : complex<f32> // CHECK: %[[VAR192:.*]] = arith.cmpf oeq, %[[VAR190]], %[[CST_7]] : f32 // CHECK: %[[VAR193:.*]] = arith.cmpf oeq, %[[VAR191]], %[[CST_7]] : f32 -// CHECK: %[[VAR194:.*]] = arith.divf %[[VAR191]], %[[VAR190]] : f32 -// CHECK: %[[VAR195:.*]] = arith.mulf %[[VAR194]], %[[VAR194]] : f32 -// CHECK: %[[VAR196:.*]] = arith.addf %[[VAR195]], %[[CST_8]] : f32 -// CHECK: %[[VAR197:.*]] = math.sqrt %[[VAR196]] : f32 -// CHECK: %[[VAR198:.*]] = math.absf %[[VAR190]] : f32 -// CHECK: %[[VAR199:.*]] = arith.mulf %[[VAR197]], %[[VAR198]] : f32 -// CHECK: %[[VAR200:.*]] = arith.divf %[[VAR190]], %[[VAR191]] : f32 -// CHECK: %[[VAR201:.*]] = arith.mulf %[[VAR200]], %[[VAR200]] : f32 -// CHECK: %[[VAR202:.*]] = arith.addf %[[VAR201]], %[[CST_8]] : f32 -// CHECK: %[[VAR203:.*]] = math.sqrt %[[VAR202]] : f32 -// CHECK: %[[VAR204:.*]] = math.absf %[[VAR191]] : f32 -// CHECK: %[[VAR205:.*]] = arith.mulf %[[VAR203]], %[[VAR204]] : f32 +// CHECK: %[[VAR194:.*]] = arith.divf %[[VAR191]], %[[VAR190]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR195:.*]] = arith.mulf %[[VAR194]], %[[VAR194]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR196:.*]] = arith.addf %[[VAR195]], %[[CST_8]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR197:.*]] = math.sqrt %[[VAR196]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR198:.*]] = math.absf %[[VAR190]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR199:.*]] = arith.mulf %[[VAR197]], %[[VAR198]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR200:.*]] = arith.divf %[[VAR190]], %[[VAR191]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR201:.*]] = arith.mulf %[[VAR200]], %[[VAR200]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR202:.*]] = arith.addf %[[VAR201]], %[[CST_8]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR203:.*]] = math.sqrt %[[VAR202]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR204:.*]] = math.absf %[[VAR191]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR205:.*]] = arith.mulf %[[VAR203]], %[[VAR204]] fastmath<nnan,contract> : f32 // CHECK: %[[VAR206:.*]] = arith.cmpf ogt, %[[VAR190]], %[[VAR191]] : f32 // CHECK: %[[VAR207:.*]] = arith.select %[[VAR206]], %[[VAR199]], %[[VAR205]] : f32 // CHECK: %[[VAR208:.*]] = arith.select %[[VAR193]], %[[VAR198]], %[[VAR207]] : f32 // CHECK: %[[VAR209:.*]] = arith.select %[[VAR192]], %[[VAR204]], %[[VAR208]] : f32 -// CHECK: %[[VAR210:.*]] = arith.addf %[[VAR189]], %[[VAR209]] : f32 +// CHECK: %[[VAR210:.*]] = arith.addf %[[VAR189]], %[[VAR209]] fastmath<nnan,contract> : f32 // CHECK: %[[CST_9:.*]] = arith.constant 5.000000e-01 : f32 -// CHECK: %[[VAR211:.*]] = arith.mulf %[[VAR210]], %[[CST_9]] : f32 -// CHECK: %[[VAR212:.*]] = math.sqrt %[[VAR211]] : f32 +// CHECK: %[[VAR211:.*]] = arith.mulf %[[VAR210]], %[[CST_9]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR212:.*]] = math.sqrt %[[VAR211]] fastmath<nnan,contract> : f32 // CHECK: %[[VAR213:.*]] = arith.cmpf olt, %[[VAR187]], %[[CST_6]] : f32 // CHECK: %[[VAR214:.*]] = arith.cmpf olt, %[[VAR188]], %[[CST_6]] : f32 -// CHECK: %[[VAR215:.*]] = arith.addf %[[VAR212]], %[[VAR212]] : f32 -// CHECK: %[[VAR216:.*]] = arith.divf %[[VAR188]], %[[VAR215]] : f32 +// CHECK: %[[VAR215:.*]] = arith.addf %[[VAR212]], %[[VAR212]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR216:.*]] = arith.divf %[[VAR188]], %[[VAR215]] fastmath<nnan,contract> : f32 // CHECK: %[[VAR217:.*]] = arith.negf %[[VAR212]] : f32 // CHECK: %[[VAR218:.*]] = arith.select %[[VAR214]], %[[VAR217]], %[[VAR212]] : f32 // CHECK: %[[VAR219:.*]] = arith.select %[[VAR213]], %[[VAR218]], %[[VAR216]] : f32 -// CHECK: %[[VAR220:.*]] = arith.addf %[[VAR219]], %[[VAR219]] : f32 -// CHECK: %[[VAR221:.*]] = arith.divf %[[VAR188]], %[[VAR220]] : f32 +// CHECK: %[[VAR220:.*]] = arith.addf %[[VAR219]], %[[VAR219]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR221:.*]] = arith.divf %[[VAR188]], %[[VAR220]] fastmath<nnan,contract> : f32 // CHECK: %[[VAR222:.*]] = arith.select %[[VAR213]], %[[VAR221]], %[[VAR212]] : f32 // CHECK: %[[VAR223:.*]] = arith.cmpf oeq, %[[VAR187]], %[[CST_6]] : f32 // CHECK: %[[VAR224:.*]] = arith.cmpf oeq, %[[VAR188]], %[[CST_6]] : f32 @@ -1728,3 +1777,106 @@ func.func @complex_div_with_fmf(%lhs: complex<f32>, %rhs: complex<f32>) -> compl // CHECK: %[[RESULT_IMAG_WITH_SPECIAL_CASES:.*]] = arith.select %[[RESULT_IS_NAN]], %[[RESULT_IMAG_SPECIAL_CASE_1]], %[[RESULT_IMAG]] : f32 // CHECK: %[[RESULT:.*]] = complex.create %[[RESULT_REAL_WITH_SPECIAL_CASES]], %[[RESULT_IMAG_WITH_SPECIAL_CASES]] : complex<f32> // CHECK: return %[[RESULT]] : complex<f32> + +// ----- + +// CHECK-LABEL: func @complex_sqrt_with_fmf +// CHECK-SAME: %[[ARG:.*]]: complex<f32> +func.func @complex_sqrt_with_fmf(%arg: complex<f32>) -> complex<f32> { + %sqrt = complex.sqrt %arg fastmath<nnan,contract> : complex<f32> + return %sqrt : complex<f32> +} + +// CHECK: %[[CST:.*]] = arith.constant 0.000000e+00 : f32 +// CHECK: %[[VAR0:.*]] = complex.re %[[ARG]] : complex<f32> +// CHECK: %[[VAR1:.*]] = complex.im %[[ARG]] : complex<f32> +// CHECK: %[[VAR2:.*]] = math.absf %[[VAR0]] fastmath<nnan,contract> : f32 +// CHECK: %[[CST0:.*]] = arith.constant 0.000000e+00 : f32 +// CHECK: %[[CST1:.*]] = arith.constant 1.000000e+00 : f32 +// CHECK: %[[VAR3:.*]] = complex.re %[[ARG]] : complex<f32> +// CHECK: %[[VAR4:.*]] = complex.im %[[ARG]] : complex<f32> +// CHECK: %[[VAR5:.*]] = arith.cmpf oeq, %[[VAR3]], %[[CST0]] : f32 +// CHECK: %[[VAR6:.*]] = arith.cmpf oeq, %[[VAR4]], %[[CST0]] : f32 +// CHECK: %[[VAR7:.*]] = arith.divf %[[VAR4]], %[[VAR3]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR8:.*]] = arith.mulf %[[VAR7]], %[[VAR7]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR9:.*]] = arith.addf %[[VAR8]], %[[CST1]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR10:.*]] = math.sqrt %[[VAR9]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR11:.*]] = math.absf %[[VAR3]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR12:.*]] = arith.mulf %[[VAR10]], %[[VAR11]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR13:.*]] = arith.divf %[[VAR3]], %[[VAR4]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR14:.*]] = arith.mulf %[[VAR13]], %[[VAR13]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR15:.*]] = arith.addf %[[VAR14]], %[[CST1]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR16:.*]] = math.sqrt %[[VAR15]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR17:.*]] = math.absf %[[VAR4]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR18:.*]] = arith.mulf %[[VAR16]], %[[VAR17]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR19:.*]] = arith.cmpf ogt, %[[VAR3]], %[[VAR4]] : f32 +// CHECK: %[[VAR20:.*]] = arith.select %[[VAR19]], %[[VAR12]], %[[VAR18]] : f32 +// CHECK: %[[VAR21:.*]] = arith.select %[[VAR6]], %[[VAR11]], %[[VAR20]] : f32 +// CHECK: %[[VAR22:.*]] = arith.select %[[VAR5]], %[[VAR17]], %[[VAR21]] : f32 +// CHECK: %[[VAR23:.*]] = arith.addf %[[VAR2]], %[[VAR22]] fastmath<nnan,contract> : f32 +// CHECK: %[[CST2:.*]] = arith.constant 5.000000e-01 : f32 +// CHECK: %[[VAR24:.*]] = arith.mulf %[[VAR23]], %[[CST2]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR25:.*]] = math.sqrt %[[VAR24]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR26:.*]] = arith.cmpf olt, %[[VAR0]], %cst : f32 +// CHECK: %[[VAR27:.*]] = arith.cmpf olt, %[[VAR1]], %cst : f32 +// CHECK: %[[VAR28:.*]] = arith.addf %[[VAR25]], %[[VAR25]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR29:.*]] = arith.divf %[[VAR1]], %[[VAR28]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR30:.*]] = arith.negf %[[VAR25]] : f32 +// CHECK: %[[VAR31:.*]] = arith.select %[[VAR27]], %[[VAR30]], %[[VAR25]] : f32 +// CHECK: %[[VAR32:.*]] = arith.select %[[VAR26]], %[[VAR31]], %[[VAR29]] : f32 +// CHECK: %[[VAR33:.*]] = arith.addf %[[VAR32]], %[[VAR32]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR34:.*]] = arith.divf %[[VAR1]], %[[VAR33]] fastmath<nnan,contract> : f32 +// CHECK: %[[VAR35:.*]] = arith.select %[[VAR26]], %[[VAR34]], %[[VAR25]] : f32 +// CHECK: %[[VAR36:.*]] = arith.cmpf oeq, %[[VAR0]], %cst : f32 +// CHECK: %[[VAR37:.*]] = arith.cmpf oeq, %[[VAR1]], %cst : f32 +// CHECK: %[[VAR38:.*]] = arith.andi %[[VAR36]], %[[VAR37]] : i1 +// CHECK: %[[VAR39:.*]] = arith.select %[[VAR38]], %cst, %[[VAR35]] : f32 +// CHECK: %[[VAR40:.*]] = arith.select %[[VAR38]], %cst, %[[VAR32]] : f32 +// CHECK: %[[VAR41:.*]] = complex.create %[[VAR39]], %[[VAR40]] : complex<f32> +// CHECK: return %[[VAR41]] : complex<f32> + +// ----- + +// CHECK-LABEL: func @complex_cos_with_fmf +// CHECK-SAME: %[[ARG:.*]]: complex<f32> +func.func @complex_cos_with_fmf(%arg: complex<f32>) -> complex<f32> { + %cos = complex.cos %arg fastmath<nnan,contract> : complex<f32> + return %cos : complex<f32> +} +// CHECK-DAG: %[[REAL:.*]] = complex.re %[[ARG]] +// CHECK-DAG: %[[IMAG:.*]] = complex.im %[[ARG]] +// CHECK-DAG: %[[HALF:.*]] = arith.constant 5.000000e-01 : f32 +// CHECK-DAG: %[[EXP:.*]] = math.exp %[[IMAG]] fastmath<nnan,contract> : f32 +// CHECK-DAG: %[[HALF_EXP:.*]] = arith.mulf %[[HALF]], %[[EXP]] fastmath<nnan,contract> +// CHECK-DAG: %[[HALF_REXP:.*]] = arith.divf %[[HALF]], %[[EXP]] fastmath<nnan,contract> +// CHECK-DAG: %[[SIN:.*]] = math.sin %[[REAL]] fastmath<nnan,contract> : f32 +// CHECK-DAG: %[[COS:.*]] = math.cos %[[REAL]] fastmath<nnan,contract> : f32 +// CHECK-DAG: %[[EXP_SUM:.*]] = arith.addf %[[HALF_REXP]], %[[HALF_EXP]] fastmath<nnan,contract> +// CHECK-DAG: %[[RESULT_REAL:.*]] = arith.mulf %[[EXP_SUM]], %[[COS]] fastmath<nnan,contract> +// CHECK-DAG: %[[EXP_DIFF:.*]] = arith.subf %[[HALF_REXP]], %[[HALF_EXP]] fastmath<nnan,contract> +// CHECK-DAG: %[[RESULT_IMAG:.*]] = arith.mulf %[[EXP_DIFF]], %[[SIN]] fastmath<nnan,contract> +// CHECK-DAG: %[[RESULT:.*]] = complex.create %[[RESULT_REAL]], %[[RESULT_IMAG]] : complex<f32> +// CHECK: return %[[RESULT]] + +// ----- + +// CHECK-LABEL: func @complex_sin_with_fmf +// CHECK-SAME: %[[ARG:.*]]: complex<f32> +func.func @complex_sin_with_fmf(%arg: complex<f32>) -> complex<f32> { + %cos = complex.sin %arg fastmath<nnan,contract> : complex<f32> + return %cos : complex<f32> +} +// CHECK-DAG: %[[REAL:.*]] = complex.re %[[ARG]] +// CHECK-DAG: %[[IMAG:.*]] = complex.im %[[ARG]] +// CHECK-DAG: %[[HALF:.*]] = arith.constant 5.000000e-01 : f32 +// CHECK-DAG: %[[EXP:.*]] = math.exp %[[IMAG]] fastmath<nnan,contract> : f32 +// CHECK-DAG: %[[HALF_EXP:.*]] = arith.mulf %[[HALF]], %[[EXP]] fastmath<nnan,contract> +// CHECK-DAG: %[[HALF_REXP:.*]] = arith.divf %[[HALF]], %[[EXP]] fastmath<nnan,contract> +// CHECK-DAG: %[[SIN:.*]] = math.sin %[[REAL]] fastmath<nnan,contract> : f32 +// CHECK-DAG: %[[COS:.*]] = math.cos %[[REAL]] fastmath<nnan,contract> : f32 +// CHECK-DAG: %[[EXP_SUM:.*]] = arith.addf %[[HALF_EXP]], %[[HALF_REXP]] fastmath<nnan,contract> +// CHECK-DAG: %[[RESULT_REAL:.*]] = arith.mulf %[[EXP_SUM]], %[[SIN]] fastmath<nnan,contract> +// CHECK-DAG: %[[EXP_DIFF:.*]] = arith.subf %[[HALF_EXP]], %[[HALF_REXP]] fastmath<nnan,contract> +// CHECK-DAG: %[[RESULT_IMAG:.*]] = arith.mulf %[[EXP_DIFF]], %[[COS]] fastmath<nnan,contract> +// CHECK-DAG: %[[RESULT:.*]] = complex.create %[[RESULT_REAL]], %[[RESULT_IMAG]] : complex<f32> +// CHECK: return %[[RESULT]] diff --git a/mlir/test/Conversion/GPUToNVVM/gpu-to-nvvm.mlir b/mlir/test/Conversion/GPUToNVVM/gpu-to-nvvm.mlir index dd3b6c2080aa21bf7f5022e2b04e2c23053229d5..8877ee083286b4d80b98d2ac94d865d77d82d1b6 100644 --- a/mlir/test/Conversion/GPUToNVVM/gpu-to-nvvm.mlir +++ b/mlir/test/Conversion/GPUToNVVM/gpu-to-nvvm.mlir @@ -112,7 +112,7 @@ gpu.module @test_module_3 { gpu.module @test_module_4 { // CHECK-LABEL: func @gpu_shuffle() - func.func @gpu_shuffle() -> (f32, f32, f32, f32) { + func.func @gpu_shuffle() -> (f32, f32, f32, f32, i1, i1, i1, i1) { // CHECK: %[[#VALUE:]] = llvm.mlir.constant(1.000000e+00 : f32) : f32 %arg0 = arith.constant 1.0 : f32 // CHECK: %[[#OFFSET:]] = llvm.mlir.constant(4 : i32) : i32 @@ -143,11 +143,41 @@ gpu.module @test_module_4 { // CHECK: nvvm.shfl.sync idx {{.*}} {return_value_and_is_valid} : f32 -> !llvm.struct<(f32, i1)> %shfli, %predi = gpu.shuffle idx %arg0, %arg1, %arg2 : f32 - func.return %shfl, %shflu, %shfld, %shfli : f32, f32,f32, f32 + func.return %shfl, %shflu, %shfld, %shfli, %pred, %predu, %predd, %predi + : f32, f32,f32, f32, i1, i1, i1, i1 } -} + // CHECK-LABEL: func @gpu_shuffle_unused_pred() + func.func @gpu_shuffle_unused_pred() -> (f32, f32, f32, f32) { + // CHECK: %[[#VALUE:]] = llvm.mlir.constant(1.000000e+00 : f32) : f32 + %arg0 = arith.constant 1.0 : f32 + // CHECK: %[[#OFFSET:]] = llvm.mlir.constant(4 : i32) : i32 + %arg1 = arith.constant 4 : i32 + // CHECK: %[[#WIDTH:]] = llvm.mlir.constant(23 : i32) : i32 + %arg2 = arith.constant 23 : i32 + // CHECK: %[[#ONE:]] = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[#MINUS_ONE:]] = llvm.mlir.constant(-1 : i32) : i32 + // CHECK: %[[#THIRTY_TWO:]] = llvm.mlir.constant(32 : i32) : i32 + // CHECK: %[[#NUM_LANES:]] = llvm.sub %[[#THIRTY_TWO]], %[[#WIDTH]] : i32 + // CHECK: %[[#MASK:]] = llvm.lshr %[[#MINUS_ONE]], %[[#NUM_LANES]] : i32 + // CHECK: %[[#CLAMP:]] = llvm.sub %[[#WIDTH]], %[[#ONE]] : i32 + // CHECK: %[[#SHFL:]] = nvvm.shfl.sync bfly %[[#MASK]], %[[#VALUE]], %[[#OFFSET]], %[[#CLAMP]] : f32 -> f32 + %shfl, %pred = gpu.shuffle xor %arg0, %arg1, %arg2 : f32 + // CHECK: %[[#ONE:]] = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[#MINUS_ONE:]] = llvm.mlir.constant(-1 : i32) : i32 + // CHECK: %[[#THIRTY_TWO:]] = llvm.mlir.constant(32 : i32) : i32 + // CHECK: %[[#NUM_LANES:]] = llvm.sub %[[#THIRTY_TWO]], %[[#WIDTH]] : i32 + // CHECK: %[[#MASK:]] = llvm.lshr %[[#MINUS_ONE]], %[[#NUM_LANES]] : i32 + // CHECK: %[[#SHFL:]] = nvvm.shfl.sync up %[[#MASK]], %[[#VALUE]], %[[#OFFSET]], %[[#NUM_LANES]] : f32 -> f32 + %shflu, %predu = gpu.shuffle up %arg0, %arg1, %arg2 : f32 + // CHECK: nvvm.shfl.sync down {{.*}} : f32 -> f32 + %shfld, %predd = gpu.shuffle down %arg0, %arg1, %arg2 : f32 + // CHECK: nvvm.shfl.sync idx {{.*}} : f32 -> f32 + %shfli, %predi = gpu.shuffle idx %arg0, %arg1, %arg2 : f32 + func.return %shfl, %shflu, %shfld, %shfli : f32, f32,f32, f32 + } +} gpu.module @test_module_5 { // CHECK-LABEL: func @gpu_sync() diff --git a/mlir/test/Conversion/GPUToSPIRV/load-store.mlir b/mlir/test/Conversion/GPUToSPIRV/load-store.mlir index fa12da8ef9d4eca308385a8a2bfdb854b0f54fa8..4339799ccd5eaf1b8dab84a99bcd0df838734eaa 100644 --- a/mlir/test/Conversion/GPUToSPIRV/load-store.mlir +++ b/mlir/test/Conversion/GPUToSPIRV/load-store.mlir @@ -60,13 +60,9 @@ module attributes { // CHECK: %[[INDEX2:.*]] = spirv.IAdd %[[ARG4]], %[[LOCALINVOCATIONIDX]] %13 = arith.addi %arg4, %3 : index // CHECK: %[[ZERO:.*]] = spirv.Constant 0 : i32 - // CHECK: %[[OFFSET1_0:.*]] = spirv.Constant 0 : i32 // CHECK: %[[STRIDE1_1:.*]] = spirv.Constant 4 : i32 - // CHECK: %[[UPDATE1_1:.*]] = spirv.IMul %[[STRIDE1_1]], %[[INDEX1]] : i32 - // CHECK: %[[OFFSET1_1:.*]] = spirv.IAdd %[[OFFSET1_0]], %[[UPDATE1_1]] : i32 - // CHECK: %[[STRIDE1_2:.*]] = spirv.Constant 1 : i32 - // CHECK: %[[UPDATE1_2:.*]] = spirv.IMul %[[STRIDE1_2]], %[[INDEX2]] : i32 - // CHECK: %[[OFFSET1_2:.*]] = spirv.IAdd %[[OFFSET1_1]], %[[UPDATE1_2]] : i32 + // CHECK: %[[UPDATE1_1:.*]] = spirv.IMul %[[INDEX1]], %[[STRIDE1_1]] : i32 + // CHECK: %[[OFFSET1_2:.*]] = spirv.IAdd %[[INDEX2]], %[[UPDATE1_1]] : i32 // CHECK: %[[PTR1:.*]] = spirv.AccessChain %[[ARG0]]{{\[}}%[[ZERO]], %[[OFFSET1_2]]{{\]}} // CHECK-NEXT: %[[VAL1:.*]] = spirv.Load "StorageBuffer" %[[PTR1]] %14 = memref.load %arg0[%12, %13] : memref<12x4xf32, #spirv.storage_class<StorageBuffer>> diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-failed.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-failed.mlir new file mode 100644 index 0000000000000000000000000000000000000000..390190d341e5ae264bc35f21f7373e3ba5826b86 --- /dev/null +++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-failed.mlir @@ -0,0 +1,40 @@ +// RUN: mlir-opt -convert-memref-to-emitc %s -split-input-file -verify-diagnostics + +func.func @memref_op(%arg0 : memref<2x4xf32>) { + // expected-error@+1 {{failed to legalize operation 'memref.copy'}} + memref.copy %arg0, %arg0 : memref<2x4xf32> to memref<2x4xf32> + return +} + +// ----- + +func.func @alloca_with_dynamic_shape() { + %0 = index.constant 1 + // expected-error@+1 {{failed to legalize operation 'memref.alloca'}} + %1 = memref.alloca(%0) : memref<4x?xf32> + return +} + +// ----- + +func.func @alloca_with_alignment() { + // expected-error@+1 {{failed to legalize operation 'memref.alloca'}} + %0 = memref.alloca() {alignment = 64 : i64}: memref<4xf32> + return +} + +// ----- + +func.func @non_identity_layout() { + // expected-error@+1 {{failed to legalize operation 'memref.alloca'}} + %0 = memref.alloca() : memref<4x3xf32, affine_map<(d0, d1) -> (d1, d0)>> + return +} + +// ----- + +func.func @zero_rank() { + // expected-error@+1 {{failed to legalize operation 'memref.alloca'}} + %0 = memref.alloca() : memref<f32> + return +} diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir new file mode 100644 index 0000000000000000000000000000000000000000..9793b2d6d7832f0e7cc43ab9e39005085578772b --- /dev/null +++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir @@ -0,0 +1,28 @@ +// RUN: mlir-opt -convert-memref-to-emitc %s -split-input-file | FileCheck %s + +// CHECK-LABEL: memref_store +// CHECK-SAME: %[[v:.*]]: f32, %[[i:.*]]: index, %[[j:.*]]: index +func.func @memref_store(%v : f32, %i: index, %j: index) { + // CHECK: %[[ALLOCA:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.array<4x8xf32> + %0 = memref.alloca() : memref<4x8xf32> + + // CHECK: %[[SUBSCRIPT:.*]] = emitc.subscript %[[ALLOCA]][%[[i]], %[[j]]] : <4x8xf32> + // CHECK: emitc.assign %[[v]] : f32 to %[[SUBSCRIPT:.*]] : f32 + memref.store %v, %0[%i, %j] : memref<4x8xf32> + return +} +// ----- + +// CHECK-LABEL: memref_load +// CHECK-SAME: %[[i:.*]]: index, %[[j:.*]]: index +func.func @memref_load(%i: index, %j: index) -> f32 { + // CHECK: %[[ALLOCA:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.array<4x8xf32> + %0 = memref.alloca() : memref<4x8xf32> + + // CHECK: %[[LOAD:.*]] = emitc.subscript %[[ALLOCA]][%[[i]], %[[j]]] : <4x8xf32> + // CHECK: %[[VAR:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> f32 + // CHECK: emitc.assign %[[LOAD]] : f32 to %[[VAR]] : f32 + %1 = memref.load %0[%i, %j] : memref<4x8xf32> + // CHECK: return %[[VAR]] : f32 + return %1 : f32 +} diff --git a/mlir/test/Conversion/MemRefToSPIRV/bitwidth-emulation.mlir b/mlir/test/Conversion/MemRefToSPIRV/bitwidth-emulation.mlir index 470c8531e2e0fb63669346bdab7e6934e24130a9..52ed14e8cce233b743beff51515bde19935f7056 100644 --- a/mlir/test/Conversion/MemRefToSPIRV/bitwidth-emulation.mlir +++ b/mlir/test/Conversion/MemRefToSPIRV/bitwidth-emulation.mlir @@ -12,16 +12,10 @@ module attributes { // CHECK-LABEL: @load_i1 func.func @load_i1(%arg0: memref<i1, #spirv.storage_class<StorageBuffer>>) -> i1 { // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32 - // CHECK: %[[FOUR:.+]] = spirv.Constant 4 : i32 - // CHECK: %[[QUOTIENT:.+]] = spirv.SDiv %[[ZERO]], %[[FOUR]] : i32 - // CHECK: %[[PTR:.+]] = spirv.AccessChain %{{.+}}[%[[ZERO]], %[[QUOTIENT]]] + // CHECK: %[[PTR:.+]] = spirv.AccessChain %{{.+}}[%[[ZERO]], %[[ZERO]]] // CHECK: %[[LOAD:.+]] = spirv.Load "StorageBuffer" %[[PTR]] - // CHECK: %[[EIGHT:.+]] = spirv.Constant 8 : i32 - // CHECK: %[[IDX:.+]] = spirv.UMod %[[ZERO]], %[[FOUR]] : i32 - // CHECK: %[[BITS:.+]] = spirv.IMul %[[IDX]], %[[EIGHT]] : i32 - // CHECK: %[[VALUE:.+]] = spirv.ShiftRightArithmetic %[[LOAD]], %[[BITS]] : i32, i32 // CHECK: %[[MASK:.+]] = spirv.Constant 255 : i32 - // CHECK: %[[T1:.+]] = spirv.BitwiseAnd %[[VALUE]], %[[MASK]] : i32 + // CHECK: %[[T1:.+]] = spirv.BitwiseAnd %[[LOAD]], %[[MASK]] : i32 // CHECK: %[[T2:.+]] = spirv.Constant 24 : i32 // CHECK: %[[T3:.+]] = spirv.ShiftLeftLogical %[[T1]], %[[T2]] : i32, i32 // CHECK: %[[T4:.+]] = spirv.ShiftRightArithmetic %[[T3]], %[[T2]] : i32, i32 @@ -37,32 +31,20 @@ func.func @load_i1(%arg0: memref<i1, #spirv.storage_class<StorageBuffer>>) -> i1 // INDEX64-LABEL: @load_i8 func.func @load_i8(%arg0: memref<i8, #spirv.storage_class<StorageBuffer>>) -> i8 { // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32 - // CHECK: %[[FOUR:.+]] = spirv.Constant 4 : i32 - // CHECK: %[[QUOTIENT:.+]] = spirv.SDiv %[[ZERO]], %[[FOUR]] : i32 - // CHECK: %[[PTR:.+]] = spirv.AccessChain %{{.+}}[%[[ZERO]], %[[QUOTIENT]]] + // CHECK: %[[PTR:.+]] = spirv.AccessChain %{{.+}}[%[[ZERO]], %[[ZERO]]] // CHECK: %[[LOAD:.+]] = spirv.Load "StorageBuffer" %[[PTR]] - // CHECK: %[[EIGHT:.+]] = spirv.Constant 8 : i32 - // CHECK: %[[IDX:.+]] = spirv.UMod %[[ZERO]], %[[FOUR]] : i32 - // CHECK: %[[BITS:.+]] = spirv.IMul %[[IDX]], %[[EIGHT]] : i32 - // CHECK: %[[VALUE:.+]] = spirv.ShiftRightArithmetic %[[LOAD]], %[[BITS]] : i32, i32 // CHECK: %[[MASK:.+]] = spirv.Constant 255 : i32 - // CHECK: %[[T1:.+]] = spirv.BitwiseAnd %[[VALUE]], %[[MASK]] : i32 + // CHECK: %[[T1:.+]] = spirv.BitwiseAnd %[[LOAD]], %[[MASK]] : i32 // CHECK: %[[T2:.+]] = spirv.Constant 24 : i32 // CHECK: %[[T3:.+]] = spirv.ShiftLeftLogical %[[T1]], %[[T2]] : i32, i32 // CHECK: %[[SR:.+]] = spirv.ShiftRightArithmetic %[[T3]], %[[T2]] : i32, i32 // CHECK: builtin.unrealized_conversion_cast %[[SR]] // INDEX64: %[[ZERO:.+]] = spirv.Constant 0 : i64 - // INDEX64: %[[FOUR:.+]] = spirv.Constant 4 : i64 - // INDEX64: %[[QUOTIENT:.+]] = spirv.SDiv %[[ZERO]], %[[FOUR]] : i64 - // INDEX64: %[[PTR:.+]] = spirv.AccessChain %{{.+}}[%[[ZERO]], %[[QUOTIENT]]] : {{.+}}, i64, i64 + // INDEX64: %[[PTR:.+]] = spirv.AccessChain %{{.+}}[%[[ZERO]], %[[ZERO]]] : {{.+}}, i64, i64 // INDEX64: %[[LOAD:.+]] = spirv.Load "StorageBuffer" %[[PTR]] : i32 - // INDEX64: %[[EIGHT:.+]] = spirv.Constant 8 : i64 - // INDEX64: %[[IDX:.+]] = spirv.UMod %[[ZERO]], %[[FOUR]] : i64 - // INDEX64: %[[BITS:.+]] = spirv.IMul %[[IDX]], %[[EIGHT]] : i64 - // INDEX64: %[[VALUE:.+]] = spirv.ShiftRightArithmetic %[[LOAD]], %[[BITS]] : i32, i64 // INDEX64: %[[MASK:.+]] = spirv.Constant 255 : i32 - // INDEX64: %[[T1:.+]] = spirv.BitwiseAnd %[[VALUE]], %[[MASK]] : i32 + // INDEX64: %[[T1:.+]] = spirv.BitwiseAnd %[[LOAD]], %[[MASK]] : i32 // INDEX64: %[[T2:.+]] = spirv.Constant 24 : i32 // INDEX64: %[[T3:.+]] = spirv.ShiftLeftLogical %[[T1]], %[[T2]] : i32, i32 // INDEX64: %[[SR:.+]] = spirv.ShiftRightArithmetic %[[T3]], %[[T2]] : i32, i32 @@ -76,15 +58,12 @@ func.func @load_i8(%arg0: memref<i8, #spirv.storage_class<StorageBuffer>>) -> i8 func.func @load_i16(%arg0: memref<10xi16, #spirv.storage_class<StorageBuffer>>, %index : index) -> i16 { // CHECK: %[[ARG1_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG1]] : index to i32 // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32 - // CHECK: %[[ONE:.+]] = spirv.Constant 1 : i32 - // CHECK: %[[UPDATE:.+]] = spirv.IMul %[[ONE]], %[[ARG1_CAST]] : i32 - // CHECK: %[[FLAT_IDX:.+]] = spirv.IAdd %[[ZERO]], %[[UPDATE]] : i32 // CHECK: %[[TWO:.+]] = spirv.Constant 2 : i32 - // CHECK: %[[QUOTIENT:.+]] = spirv.SDiv %[[FLAT_IDX]], %[[TWO]] : i32 + // CHECK: %[[QUOTIENT:.+]] = spirv.SDiv %[[ARG1_CAST]], %[[TWO]] : i32 // CHECK: %[[PTR:.+]] = spirv.AccessChain %{{.+}}[%[[ZERO]], %[[QUOTIENT]]] // CHECK: %[[LOAD:.+]] = spirv.Load "StorageBuffer" %[[PTR]] // CHECK: %[[SIXTEEN:.+]] = spirv.Constant 16 : i32 - // CHECK: %[[IDX:.+]] = spirv.UMod %[[FLAT_IDX]], %[[TWO]] : i32 + // CHECK: %[[IDX:.+]] = spirv.UMod %[[ARG1_CAST]], %[[TWO]] : i32 // CHECK: %[[BITS:.+]] = spirv.IMul %[[IDX]], %[[SIXTEEN]] : i32 // CHECK: %[[VALUE:.+]] = spirv.ShiftRightArithmetic %[[LOAD]], %[[BITS]] : i32, i32 // CHECK: %[[MASK:.+]] = spirv.Constant 65535 : i32 @@ -110,20 +89,12 @@ func.func @load_f32(%arg0: memref<f32, #spirv.storage_class<StorageBuffer>>) { func.func @store_i1(%arg0: memref<i1, #spirv.storage_class<StorageBuffer>>, %value: i1) { // CHECK: %[[ARG0_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG0]] // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32 - // CHECK: %[[FOUR:.+]] = spirv.Constant 4 : i32 - // CHECK: %[[EIGHT:.+]] = spirv.Constant 8 : i32 - // CHECK: %[[IDX:.+]] = spirv.UMod %[[ZERO]], %[[FOUR]] : i32 - // CHECK: %[[OFFSET:.+]] = spirv.IMul %[[IDX]], %[[EIGHT]] : i32 - // CHECK: %[[MASK1:.+]] = spirv.Constant 255 : i32 - // CHECK: %[[TMP1:.+]] = spirv.ShiftLeftLogical %[[MASK1]], %[[OFFSET]] : i32, i32 - // CHECK: %[[MASK:.+]] = spirv.Not %[[TMP1]] : i32 + // CHECK: %[[MASK:.+]] = spirv.Constant -256 : i32 // CHECK: %[[ONE:.+]] = spirv.Constant 1 : i32 // CHECK: %[[CASTED_ARG1:.+]] = spirv.Select %[[ARG1]], %[[ONE]], %[[ZERO]] : i1, i32 - // CHECK: %[[STORE_VAL:.+]] = spirv.ShiftLeftLogical %[[CASTED_ARG1]], %[[OFFSET]] : i32, i32 - // CHECK: %[[ACCESS_IDX:.+]] = spirv.SDiv %[[ZERO]], %[[FOUR]] : i32 - // CHECK: %[[PTR:.+]] = spirv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ACCESS_IDX]]] + // CHECK: %[[PTR:.+]] = spirv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ZERO]]] // CHECK: spirv.AtomicAnd <Device> <AcquireRelease> %[[PTR]], %[[MASK]] - // CHECK: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[STORE_VAL]] + // CHECK: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[CASTED_ARG1]] memref.store %value, %arg0[] : memref<i1, #spirv.storage_class<StorageBuffer>> return } @@ -136,36 +107,22 @@ func.func @store_i8(%arg0: memref<i8, #spirv.storage_class<StorageBuffer>>, %val // CHECK-DAG: %[[ARG1_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG1]] : i8 to i32 // CHECK-DAG: %[[ARG0_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG0]] // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32 - // CHECK: %[[FOUR:.+]] = spirv.Constant 4 : i32 - // CHECK: %[[EIGHT:.+]] = spirv.Constant 8 : i32 - // CHECK: %[[IDX:.+]] = spirv.UMod %[[ZERO]], %[[FOUR]] : i32 - // CHECK: %[[OFFSET:.+]] = spirv.IMul %[[IDX]], %[[EIGHT]] : i32 // CHECK: %[[MASK1:.+]] = spirv.Constant 255 : i32 - // CHECK: %[[TMP1:.+]] = spirv.ShiftLeftLogical %[[MASK1]], %[[OFFSET]] : i32, i32 - // CHECK: %[[MASK:.+]] = spirv.Not %[[TMP1]] : i32 + // CHECK: %[[MASK2:.+]] = spirv.Constant -256 : i32 // CHECK: %[[CLAMPED_VAL:.+]] = spirv.BitwiseAnd %[[ARG1_CAST]], %[[MASK1]] : i32 - // CHECK: %[[STORE_VAL:.+]] = spirv.ShiftLeftLogical %[[CLAMPED_VAL]], %[[OFFSET]] : i32, i32 - // CHECK: %[[ACCESS_IDX:.+]] = spirv.SDiv %[[ZERO]], %[[FOUR]] : i32 - // CHECK: %[[PTR:.+]] = spirv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ACCESS_IDX]]] - // CHECK: spirv.AtomicAnd <Device> <AcquireRelease> %[[PTR]], %[[MASK]] - // CHECK: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[STORE_VAL]] + // CHECK: %[[PTR:.+]] = spirv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ZERO]]] + // CHECK: spirv.AtomicAnd <Device> <AcquireRelease> %[[PTR]], %[[MASK2]] + // CHECK: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[CLAMPED_VAL]] // INDEX64-DAG: %[[ARG1_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG1]] : i8 to i32 // INDEX64-DAG: %[[ARG0_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG0]] // INDEX64: %[[ZERO:.+]] = spirv.Constant 0 : i64 - // INDEX64: %[[FOUR:.+]] = spirv.Constant 4 : i64 - // INDEX64: %[[EIGHT:.+]] = spirv.Constant 8 : i64 - // INDEX64: %[[IDX:.+]] = spirv.UMod %[[ZERO]], %[[FOUR]] : i64 - // INDEX64: %[[OFFSET:.+]] = spirv.IMul %[[IDX]], %[[EIGHT]] : i64 // INDEX64: %[[MASK1:.+]] = spirv.Constant 255 : i32 - // INDEX64: %[[TMP1:.+]] = spirv.ShiftLeftLogical %[[MASK1]], %[[OFFSET]] : i32, i64 - // INDEX64: %[[MASK:.+]] = spirv.Not %[[TMP1]] : i32 + // INDEX64: %[[MASK2:.+]] = spirv.Constant -256 : i32 // INDEX64: %[[CLAMPED_VAL:.+]] = spirv.BitwiseAnd %[[ARG1_CAST]], %[[MASK1]] : i32 - // INDEX64: %[[STORE_VAL:.+]] = spirv.ShiftLeftLogical %[[CLAMPED_VAL]], %[[OFFSET]] : i32, i64 - // INDEX64: %[[ACCESS_IDX:.+]] = spirv.SDiv %[[ZERO]], %[[FOUR]] : i64 - // INDEX64: %[[PTR:.+]] = spirv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ACCESS_IDX]]] : {{.+}}, i64, i64 - // INDEX64: spirv.AtomicAnd <Device> <AcquireRelease> %[[PTR]], %[[MASK]] - // INDEX64: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[STORE_VAL]] + // INDEX64: %[[PTR:.+]] = spirv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ZERO]]] : {{.+}}, i64, i64 + // INDEX64: spirv.AtomicAnd <Device> <AcquireRelease> %[[PTR]], %[[MASK2]] + // INDEX64: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[CLAMPED_VAL]] memref.store %value, %arg0[] : memref<i8, #spirv.storage_class<StorageBuffer>> return } @@ -177,19 +134,16 @@ func.func @store_i16(%arg0: memref<10xi16, #spirv.storage_class<StorageBuffer>>, // CHECK-DAG: %[[ARG0_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG0]] // CHECK-DAG: %[[ARG1_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG1]] : index to i32 // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32 - // CHECK: %[[ONE:.+]] = spirv.Constant 1 : i32 - // CHECK: %[[UPDATE:.+]] = spirv.IMul %[[ONE]], %[[ARG1_CAST]] : i32 - // CHECK: %[[FLAT_IDX:.+]] = spirv.IAdd %[[ZERO]], %[[UPDATE]] : i32 // CHECK: %[[TWO:.+]] = spirv.Constant 2 : i32 // CHECK: %[[SIXTEEN:.+]] = spirv.Constant 16 : i32 - // CHECK: %[[IDX:.+]] = spirv.UMod %[[FLAT_IDX]], %[[TWO]] : i32 + // CHECK: %[[IDX:.+]] = spirv.UMod %[[ARG1_CAST]], %[[TWO]] : i32 // CHECK: %[[OFFSET:.+]] = spirv.IMul %[[IDX]], %[[SIXTEEN]] : i32 // CHECK: %[[MASK1:.+]] = spirv.Constant 65535 : i32 // CHECK: %[[TMP1:.+]] = spirv.ShiftLeftLogical %[[MASK1]], %[[OFFSET]] : i32, i32 // CHECK: %[[MASK:.+]] = spirv.Not %[[TMP1]] : i32 // CHECK: %[[CLAMPED_VAL:.+]] = spirv.BitwiseAnd %[[ARG2_CAST]], %[[MASK1]] : i32 // CHECK: %[[STORE_VAL:.+]] = spirv.ShiftLeftLogical %[[CLAMPED_VAL]], %[[OFFSET]] : i32, i32 - // CHECK: %[[ACCESS_IDX:.+]] = spirv.SDiv %[[FLAT_IDX]], %[[TWO]] : i32 + // CHECK: %[[ACCESS_IDX:.+]] = spirv.SDiv %[[ARG1_CAST]], %[[TWO]] : i32 // CHECK: %[[PTR:.+]] = spirv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ACCESS_IDX]]] // CHECK: spirv.AtomicAnd <Device> <AcquireRelease> %[[PTR]], %[[MASK]] // CHECK: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[STORE_VAL]] @@ -222,15 +176,12 @@ module attributes { func.func @load_i4(%arg0: memref<?xi4, #spirv.storage_class<StorageBuffer>>, %i: index) -> i4 { // CHECK: %[[INDEX:.+]] = builtin.unrealized_conversion_cast %{{.+}} : index to i32 // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32 - // CHECK: %[[ONE:.+]] = spirv.Constant 1 : i32 - // CHECK: %[[MUL:.+]] = spirv.IMul %[[ONE]], %[[INDEX]] : i32 - // CHECK: %[[OFFSET:.+]] = spirv.IAdd %[[ZERO]], %[[MUL]] : i32 // CHECK: %[[EIGHT:.+]] = spirv.Constant 8 : i32 - // CHECK: %[[QUOTIENT:.+]] = spirv.SDiv %[[OFFSET]], %[[EIGHT]] : i32 + // CHECK: %[[QUOTIENT:.+]] = spirv.SDiv %[[INDEX]], %[[EIGHT]] : i32 // CHECK: %[[PTR:.+]] = spirv.AccessChain %{{.+}}[%[[ZERO]], %[[QUOTIENT]]] // CHECK: %[[LOAD:.+]] = spirv.Load "StorageBuffer" %[[PTR]] : i32 // CHECK: %[[FOUR:.+]] = spirv.Constant 4 : i32 - // CHECK: %[[IDX:.+]] = spirv.UMod %[[OFFSET]], %[[EIGHT]] : i32 + // CHECK: %[[IDX:.+]] = spirv.UMod %[[INDEX]], %[[EIGHT]] : i32 // CHECK: %[[BITS:.+]] = spirv.IMul %[[IDX]], %[[FOUR]] : i32 // CHECK: %[[VALUE:.+]] = spirv.ShiftRightArithmetic %[[LOAD]], %[[BITS]] : i32, i32 // CHECK: %[[MASK:.+]] = spirv.Constant 15 : i32 @@ -248,19 +199,16 @@ func.func @store_i4(%arg0: memref<?xi4, #spirv.storage_class<StorageBuffer>>, %v // CHECK: %[[VAL:.+]] = builtin.unrealized_conversion_cast %{{.+}} : i4 to i32 // CHECK: %[[INDEX:.+]] = builtin.unrealized_conversion_cast %{{.+}} : index to i32 // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32 - // CHECK: %[[ONE:.+]] = spirv.Constant 1 : i32 - // CHECK: %[[MUL:.+]] = spirv.IMul %[[ONE]], %[[INDEX]] : i32 - // CHECK: %[[OFFSET:.+]] = spirv.IAdd %[[ZERO]], %[[MUL]] : i32 // CHECK: %[[EIGHT:.+]] = spirv.Constant 8 : i32 - // CHECK: %[[FOUR:.+]] = spirv.Constant [[OFFSET]] : i32 - // CHECK: %[[IDX:.+]] = spirv.UMod %[[OFFSET]], %[[EIGHT]] : i32 + // CHECK: %[[FOUR:.+]] = spirv.Constant 4 : i32 + // CHECK: %[[IDX:.+]] = spirv.UMod %[[INDEX]], %[[EIGHT]] : i32 // CHECK: %[[BITS:.+]] = spirv.IMul %[[IDX]], %[[FOUR]] : i32 // CHECK: %[[MASK1:.+]] = spirv.Constant 15 : i32 // CHECK: %[[SL:.+]] = spirv.ShiftLeftLogical %[[MASK1]], %[[BITS]] : i32, i32 // CHECK: %[[MASK2:.+]] = spirv.Not %[[SL]] : i32 // CHECK: %[[CLAMPED_VAL:.+]] = spirv.BitwiseAnd %[[VAL]], %[[MASK1]] : i32 // CHECK: %[[STORE_VAL:.+]] = spirv.ShiftLeftLogical %[[CLAMPED_VAL]], %[[BITS]] : i32, i32 - // CHECK: %[[ACCESS_INDEX:.+]] = spirv.SDiv %[[OFFSET]], %[[EIGHT]] : i32 + // CHECK: %[[ACCESS_INDEX:.+]] = spirv.SDiv %[[INDEX]], %[[EIGHT]] : i32 // CHECK: %[[PTR:.+]] = spirv.AccessChain %{{.+}}[%[[ZERO]], %[[ACCESS_INDEX]]] // CHECK: spirv.AtomicAnd <Device> <AcquireRelease> %[[PTR]], %[[MASK2]] // CHECK: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[STORE_VAL]] @@ -283,16 +231,10 @@ module attributes { // INDEX64-LABEL: @load_i8 func.func @load_i8(%arg0: memref<i8, #spirv.storage_class<StorageBuffer>>) -> i8 { // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32 - // CHECK: %[[FOUR:.+]] = spirv.Constant 4 : i32 - // CHECK: %[[QUOTIENT:.+]] = spirv.SDiv %[[ZERO]], %[[FOUR]] : i32 - // CHECK: %[[PTR:.+]] = spirv.AccessChain %{{.+}}[%[[ZERO]], %[[QUOTIENT]]] + // CHECK: %[[PTR:.+]] = spirv.AccessChain %{{.+}}[%[[ZERO]], %[[ZERO]]] // CHECK: %[[LOAD:.+]] = spirv.Load "StorageBuffer" %[[PTR]] - // CHECK: %[[EIGHT:.+]] = spirv.Constant 8 : i32 - // CHECK: %[[IDX:.+]] = spirv.UMod %[[ZERO]], %[[FOUR]] : i32 - // CHECK: %[[BITS:.+]] = spirv.IMul %[[IDX]], %[[EIGHT]] : i32 - // CHECK: %[[VALUE:.+]] = spirv.ShiftRightArithmetic %[[LOAD]], %[[BITS]] : i32, i32 // CHECK: %[[MASK:.+]] = spirv.Constant 255 : i32 - // CHECK: %[[T1:.+]] = spirv.BitwiseAnd %[[VALUE]], %[[MASK]] : i32 + // CHECK: %[[T1:.+]] = spirv.BitwiseAnd %[[LOAD]], %[[MASK]] : i32 // CHECK: %[[T2:.+]] = spirv.Constant 24 : i32 // CHECK: %[[T3:.+]] = spirv.ShiftLeftLogical %[[T1]], %[[T2]] : i32, i32 // CHECK: %[[SR:.+]] = spirv.ShiftRightArithmetic %[[T3]], %[[T2]] : i32, i32 @@ -300,16 +242,10 @@ func.func @load_i8(%arg0: memref<i8, #spirv.storage_class<StorageBuffer>>) -> i8 // CHECK: return %[[CAST]] : i8 // INDEX64: %[[ZERO:.+]] = spirv.Constant 0 : i64 - // INDEX64: %[[FOUR:.+]] = spirv.Constant 4 : i64 - // INDEX64: %[[QUOTIENT:.+]] = spirv.SDiv %[[ZERO]], %[[FOUR]] : i64 - // INDEX64: %[[PTR:.+]] = spirv.AccessChain %{{.+}}[%[[ZERO]], %[[QUOTIENT]]] : {{.+}}, i64, i64 + // INDEX64: %[[PTR:.+]] = spirv.AccessChain %{{.+}}[%[[ZERO]], %[[ZERO]]] : {{.+}}, i64, i64 // INDEX64: %[[LOAD:.+]] = spirv.Load "StorageBuffer" %[[PTR]] : i32 - // INDEX64: %[[EIGHT:.+]] = spirv.Constant 8 : i64 - // INDEX64: %[[IDX:.+]] = spirv.UMod %[[ZERO]], %[[FOUR]] : i64 - // INDEX64: %[[BITS:.+]] = spirv.IMul %[[IDX]], %[[EIGHT]] : i64 - // INDEX64: %[[VALUE:.+]] = spirv.ShiftRightArithmetic %[[LOAD]], %[[BITS]] : i32, i64 // INDEX64: %[[MASK:.+]] = spirv.Constant 255 : i32 - // INDEX64: %[[T1:.+]] = spirv.BitwiseAnd %[[VALUE]], %[[MASK]] : i32 + // INDEX64: %[[T1:.+]] = spirv.BitwiseAnd %[[LOAD]], %[[MASK]] : i32 // INDEX64: %[[T2:.+]] = spirv.Constant 24 : i32 // INDEX64: %[[T3:.+]] = spirv.ShiftLeftLogical %[[T1]], %[[T2]] : i32, i32 // INDEX64: %[[SR:.+]] = spirv.ShiftRightArithmetic %[[T3]], %[[T2]] : i32, i32 @@ -326,37 +262,19 @@ func.func @load_i8(%arg0: memref<i8, #spirv.storage_class<StorageBuffer>>) -> i8 func.func @store_i8(%arg0: memref<i8, #spirv.storage_class<StorageBuffer>>, %value: i8) { // CHECK-DAG: %[[ARG0_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG0]] // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32 - // CHECK: %[[FOUR:.+]] = spirv.Constant 4 : i32 - // CHECK: %[[EIGHT:.+]] = spirv.Constant 8 : i32 - // CHECK: %[[IDX:.+]] = spirv.UMod %[[ZERO]], %[[FOUR]] : i32 - // CHECK: %[[OFFSET:.+]] = spirv.IMul %[[IDX]], %[[EIGHT]] : i32 - // CHECK: %[[MASK1:.+]] = spirv.Constant 255 : i32 - // CHECK: %[[TMP1:.+]] = spirv.ShiftLeftLogical %[[MASK1]], %[[OFFSET]] : i32, i32 - // CHECK: %[[MASK:.+]] = spirv.Not %[[TMP1]] : i32 + // CHECK: %[[MASK1:.+]] = spirv.Constant -256 : i32 // CHECK: %[[ARG1_CAST:.+]] = spirv.UConvert %[[ARG1]] : i8 to i32 - // CHECK: %[[CLAMPED_VAL:.+]] = spirv.BitwiseAnd %[[ARG1_CAST]], %[[MASK1]] : i32 - // CHECK: %[[STORE_VAL:.+]] = spirv.ShiftLeftLogical %[[CLAMPED_VAL]], %[[OFFSET]] : i32, i32 - // CHECK: %[[ACCESS_IDX:.+]] = spirv.SDiv %[[ZERO]], %[[FOUR]] : i32 - // CHECK: %[[PTR:.+]] = spirv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ACCESS_IDX]]] - // CHECK: spirv.AtomicAnd <Device> <AcquireRelease> %[[PTR]], %[[MASK]] - // CHECK: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[STORE_VAL]] + // CHECK: %[[PTR:.+]] = spirv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ZERO]]] + // CHECK: spirv.AtomicAnd <Device> <AcquireRelease> %[[PTR]], %[[MASK1]] + // CHECK: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[ARG1_CAST]] // INDEX64-DAG: %[[ARG0_CAST:.+]] = builtin.unrealized_conversion_cast %[[ARG0]] // INDEX64: %[[ZERO:.+]] = spirv.Constant 0 : i64 - // INDEX64: %[[FOUR:.+]] = spirv.Constant 4 : i64 - // INDEX64: %[[EIGHT:.+]] = spirv.Constant 8 : i64 - // INDEX64: %[[IDX:.+]] = spirv.UMod %[[ZERO]], %[[FOUR]] : i64 - // INDEX64: %[[OFFSET:.+]] = spirv.IMul %[[IDX]], %[[EIGHT]] : i64 - // INDEX64: %[[MASK1:.+]] = spirv.Constant 255 : i32 - // INDEX64: %[[TMP1:.+]] = spirv.ShiftLeftLogical %[[MASK1]], %[[OFFSET]] : i32, i64 - // INDEX64: %[[MASK:.+]] = spirv.Not %[[TMP1]] : i32 + // INDEX64: %[[MASK1:.+]] = spirv.Constant -256 : i32 // INDEX64: %[[ARG1_CAST:.+]] = spirv.UConvert %[[ARG1]] : i8 to i32 - // INDEX64: %[[CLAMPED_VAL:.+]] = spirv.BitwiseAnd %[[ARG1_CAST]], %[[MASK1]] : i32 - // INDEX64: %[[STORE_VAL:.+]] = spirv.ShiftLeftLogical %[[CLAMPED_VAL]], %[[OFFSET]] : i32, i64 - // INDEX64: %[[ACCESS_IDX:.+]] = spirv.SDiv %[[ZERO]], %[[FOUR]] : i64 - // INDEX64: %[[PTR:.+]] = spirv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ACCESS_IDX]]] : {{.+}}, i64, i64 - // INDEX64: spirv.AtomicAnd <Device> <AcquireRelease> %[[PTR]], %[[MASK]] - // INDEX64: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[STORE_VAL]] + // INDEX64: %[[PTR:.+]] = spirv.AccessChain %[[ARG0_CAST]][%[[ZERO]], %[[ZERO]]] : {{.+}}, i64, i64 + // INDEX64: spirv.AtomicAnd <Device> <AcquireRelease> %[[PTR]], %[[MASK1]] + // INDEX64: spirv.AtomicOr <Device> <AcquireRelease> %[[PTR]], %[[ARG1_CAST]] memref.store %value, %arg0[] : memref<i8, #spirv.storage_class<StorageBuffer>> return } diff --git a/mlir/test/Conversion/MemRefToSPIRV/memref-to-spirv.mlir b/mlir/test/Conversion/MemRefToSPIRV/memref-to-spirv.mlir index feb6d4e924015f8be2b411bb57e9fb694378947e..10c03a270005f1fe4da87dd8249e4055c5f83515 100644 --- a/mlir/test/Conversion/MemRefToSPIRV/memref-to-spirv.mlir +++ b/mlir/test/Conversion/MemRefToSPIRV/memref-to-spirv.mlir @@ -70,11 +70,8 @@ func.func @load_store_unknown_dim(%i: index, %source: memref<?xi32, #spirv.stora func.func @load_i1(%src: memref<4xi1, #spirv.storage_class<StorageBuffer>>, %i : index) -> i1 { // CHECK-DAG: %[[SRC_CAST:.+]] = builtin.unrealized_conversion_cast %[[SRC]] : memref<4xi1, #spirv.storage_class<StorageBuffer>> to !spirv.ptr<!spirv.struct<(!spirv.array<4 x i8, stride=1> [0])>, StorageBuffer> // CHECK-DAG: %[[IDX_CAST:.+]] = builtin.unrealized_conversion_cast %[[IDX]] - // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32 - // CHECK: %[[ONE:.+]] = spirv.Constant 1 : i32 - // CHECK: %[[MUL:.+]] = spirv.IMul %[[ONE]], %[[IDX_CAST]] : i32 - // CHECK: %[[ADD:.+]] = spirv.IAdd %[[ZERO]], %[[MUL]] : i32 - // CHECK: %[[ADDR:.+]] = spirv.AccessChain %[[SRC_CAST]][%[[ZERO]], %[[ADD]]] + // CHECK: %[[ZERO:.*]] = spirv.Constant 0 : i32 + // CHECK: %[[ADDR:.+]] = spirv.AccessChain %[[SRC_CAST]][%[[ZERO]], %[[IDX_CAST]]] // CHECK: %[[VAL:.+]] = spirv.Load "StorageBuffer" %[[ADDR]] : i8 // CHECK: %[[ONE_I8:.+]] = spirv.Constant 1 : i8 // CHECK: %[[BOOL:.+]] = spirv.IEqual %[[VAL]], %[[ONE_I8]] : i8 @@ -90,15 +87,10 @@ func.func @store_i1(%dst: memref<4xi1, #spirv.storage_class<StorageBuffer>>, %i: %true = arith.constant true // CHECK-DAG: %[[DST_CAST:.+]] = builtin.unrealized_conversion_cast %[[DST]] : memref<4xi1, #spirv.storage_class<StorageBuffer>> to !spirv.ptr<!spirv.struct<(!spirv.array<4 x i8, stride=1> [0])>, StorageBuffer> // CHECK-DAG: %[[IDX_CAST:.+]] = builtin.unrealized_conversion_cast %[[IDX]] - // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32 - // CHECK: %[[ONE:.+]] = spirv.Constant 1 : i32 - // CHECK: %[[MUL:.+]] = spirv.IMul %[[ONE]], %[[IDX_CAST]] : i32 - // CHECK: %[[ADD:.+]] = spirv.IAdd %[[ZERO]], %[[MUL]] : i32 - // CHECK: %[[ADDR:.+]] = spirv.AccessChain %[[DST_CAST]][%[[ZERO]], %[[ADD]]] - // CHECK: %[[ZERO_I8:.+]] = spirv.Constant 0 : i8 + // CHECK: %[[ZERO:.*]] = spirv.Constant 0 : i32 + // CHECK: %[[ADDR:.+]] = spirv.AccessChain %[[DST_CAST]][%[[ZERO]], %[[IDX_CAST]]] // CHECK: %[[ONE_I8:.+]] = spirv.Constant 1 : i8 - // CHECK: %[[RES:.+]] = spirv.Select %{{.+}}, %[[ONE_I8]], %[[ZERO_I8]] : i1, i8 - // CHECK: spirv.Store "StorageBuffer" %[[ADDR]], %[[RES]] : i8 + // CHECK: spirv.Store "StorageBuffer" %[[ADDR]], %[[ONE_I8]] : i8 memref.store %true, %dst[%i]: memref<4xi1, #spirv.storage_class<StorageBuffer>> return } @@ -234,11 +226,7 @@ func.func @load_store_unknown_dim(%i: index, %source: memref<?xi32, #spirv.stora func.func @load_i1(%src: memref<4xi1, #spirv.storage_class<CrossWorkgroup>>, %i : index) -> i1 { // CHECK-DAG: %[[SRC_CAST:.+]] = builtin.unrealized_conversion_cast %[[SRC]] : memref<4xi1, #spirv.storage_class<CrossWorkgroup>> to !spirv.ptr<!spirv.array<4 x i8>, CrossWorkgroup> // CHECK-DAG: %[[IDX_CAST:.+]] = builtin.unrealized_conversion_cast %[[IDX]] - // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32 - // CHECK: %[[ONE:.+]] = spirv.Constant 1 : i32 - // CHECK: %[[MUL:.+]] = spirv.IMul %[[ONE]], %[[IDX_CAST]] : i32 - // CHECK: %[[ADD:.+]] = spirv.IAdd %[[ZERO]], %[[MUL]] : i32 - // CHECK: %[[ADDR:.+]] = spirv.AccessChain %[[SRC_CAST]][%[[ADD]]] + // CHECK: %[[ADDR:.+]] = spirv.AccessChain %[[SRC_CAST]][%[[IDX_CAST]]] // CHECK: %[[VAL:.+]] = spirv.Load "CrossWorkgroup" %[[ADDR]] : i8 // CHECK: %[[ONE_I8:.+]] = spirv.Constant 1 : i8 // CHECK: %[[BOOL:.+]] = spirv.IEqual %[[VAL]], %[[ONE_I8]] : i8 @@ -254,15 +242,9 @@ func.func @store_i1(%dst: memref<4xi1, #spirv.storage_class<CrossWorkgroup>>, %i %true = arith.constant true // CHECK-DAG: %[[DST_CAST:.+]] = builtin.unrealized_conversion_cast %[[DST]] : memref<4xi1, #spirv.storage_class<CrossWorkgroup>> to !spirv.ptr<!spirv.array<4 x i8>, CrossWorkgroup> // CHECK-DAG: %[[IDX_CAST:.+]] = builtin.unrealized_conversion_cast %[[IDX]] - // CHECK: %[[ZERO:.+]] = spirv.Constant 0 : i32 - // CHECK: %[[ONE:.+]] = spirv.Constant 1 : i32 - // CHECK: %[[MUL:.+]] = spirv.IMul %[[ONE]], %[[IDX_CAST]] : i32 - // CHECK: %[[ADD:.+]] = spirv.IAdd %[[ZERO]], %[[MUL]] : i32 - // CHECK: %[[ADDR:.+]] = spirv.AccessChain %[[DST_CAST]][%[[ADD]]] - // CHECK: %[[ZERO_I8:.+]] = spirv.Constant 0 : i8 + // CHECK: %[[ADDR:.+]] = spirv.AccessChain %[[DST_CAST]][%[[IDX_CAST]]] // CHECK: %[[ONE_I8:.+]] = spirv.Constant 1 : i8 - // CHECK: %[[RES:.+]] = spirv.Select %{{.+}}, %[[ONE_I8]], %[[ZERO_I8]] : i1, i8 - // CHECK: spirv.Store "CrossWorkgroup" %[[ADDR]], %[[RES]] : i8 + // CHECK: spirv.Store "CrossWorkgroup" %[[ADDR]], %[[ONE_I8]] : i8 memref.store %true, %dst[%i]: memref<4xi1, #spirv.storage_class<CrossWorkgroup>> return } diff --git a/mlir/test/Conversion/NVVMToLLVM/nvvm-to-llvm.mlir b/mlir/test/Conversion/NVVMToLLVM/nvvm-to-llvm.mlir index 0ac7331e1f69872daafd7aa2130dd0b7a13dfa46..8920bf86d89b1d4046f1bfb7b3b413d983c2fa65 100644 --- a/mlir/test/Conversion/NVVMToLLVM/nvvm-to-llvm.mlir +++ b/mlir/test/Conversion/NVVMToLLVM/nvvm-to-llvm.mlir @@ -680,3 +680,15 @@ func.func @fence_proxy() { nvvm.fence.proxy { kind = #nvvm.proxy_kind<async.shared>, space = #nvvm.shared_space<cluster>} func.return } + +// ----- + +// CHECK-LABEL: @llvm_nvvm_barrier_arrive +// CHECK-SAME: (%[[barId:.*]]: i32, %[[numberOfThreads:.*]]: i32) +llvm.func @llvm_nvvm_barrier_arrive(%barID : i32, %numberOfThreads : i32) { + // CHECK: llvm.inline_asm has_side_effects asm_dialect = att "bar.arrive 0, $0;", "r" %[[numberOfThreads]] : (i32) -> () + nvvm.barrier.arrive number_of_threads = %numberOfThreads + // CHECK: llvm.inline_asm has_side_effects asm_dialect = att "bar.arrive $0, $1'", "r,r" %[[barId]], %[[numberOfThreads]] : (i32, i32) -> () + nvvm.barrier.arrive id = %barID number_of_threads = %numberOfThreads + llvm.return +} diff --git a/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir b/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir index 6cbc0c8f4be9a2400328ff4256a71db9d2513971..dc5d6969ca78964040435f0975801b457aa91345 100644 --- a/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir +++ b/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir @@ -193,25 +193,25 @@ func.func @task_depend(%arg0: !llvm.ptr) { // CHECK-LABEL: @_QPomp_target_data // CHECK: (%[[ARG0:.*]]: !llvm.ptr, %[[ARG1:.*]]: !llvm.ptr, %[[ARG2:.*]]: !llvm.ptr, %[[ARG3:.*]]: !llvm.ptr) -// CHECK: %[[MAP0:.*]] = omp.map_info var_ptr(%[[ARG0]] : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""} -// CHECK: %[[MAP1:.*]] = omp.map_info var_ptr(%[[ARG1]] : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""} -// CHECK: %[[MAP2:.*]] = omp.map_info var_ptr(%[[ARG2]] : !llvm.ptr, i32) map_clauses(always, exit_release_or_enter_alloc) capture(ByRef) -> !llvm.ptr {name = ""} +// CHECK: %[[MAP0:.*]] = omp.map.info var_ptr(%[[ARG0]] : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""} +// CHECK: %[[MAP1:.*]] = omp.map.info var_ptr(%[[ARG1]] : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""} +// CHECK: %[[MAP2:.*]] = omp.map.info var_ptr(%[[ARG2]] : !llvm.ptr, i32) map_clauses(always, exit_release_or_enter_alloc) capture(ByRef) -> !llvm.ptr {name = ""} // CHECK: omp.target_enter_data map_entries(%[[MAP0]], %[[MAP1]], %[[MAP2]] : !llvm.ptr, !llvm.ptr, !llvm.ptr) -// CHECK: %[[MAP3:.*]] = omp.map_info var_ptr(%[[ARG0]] : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""} -// CHECK: %[[MAP4:.*]] = omp.map_info var_ptr(%[[ARG1]] : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""} -// CHECK: %[[MAP5:.*]] = omp.map_info var_ptr(%[[ARG2]] : !llvm.ptr, i32) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> !llvm.ptr {name = ""} -// CHECK: %[[MAP6:.*]] = omp.map_info var_ptr(%[[ARG3]] : !llvm.ptr, i32) map_clauses(always, delete) capture(ByRef) -> !llvm.ptr {name = ""} +// CHECK: %[[MAP3:.*]] = omp.map.info var_ptr(%[[ARG0]] : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""} +// CHECK: %[[MAP4:.*]] = omp.map.info var_ptr(%[[ARG1]] : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""} +// CHECK: %[[MAP5:.*]] = omp.map.info var_ptr(%[[ARG2]] : !llvm.ptr, i32) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> !llvm.ptr {name = ""} +// CHECK: %[[MAP6:.*]] = omp.map.info var_ptr(%[[ARG3]] : !llvm.ptr, i32) map_clauses(always, delete) capture(ByRef) -> !llvm.ptr {name = ""} // CHECK: omp.target_exit_data map_entries(%[[MAP3]], %[[MAP4]], %[[MAP5]], %[[MAP6]] : !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) llvm.func @_QPomp_target_data(%a : !llvm.ptr, %b : !llvm.ptr, %c : !llvm.ptr, %d : !llvm.ptr) { - %0 = omp.map_info var_ptr(%a : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""} - %1 = omp.map_info var_ptr(%b : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""} - %2 = omp.map_info var_ptr(%c : !llvm.ptr, i32) map_clauses(always, exit_release_or_enter_alloc) capture(ByRef) -> !llvm.ptr {name = ""} + %0 = omp.map.info var_ptr(%a : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""} + %1 = omp.map.info var_ptr(%b : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""} + %2 = omp.map.info var_ptr(%c : !llvm.ptr, i32) map_clauses(always, exit_release_or_enter_alloc) capture(ByRef) -> !llvm.ptr {name = ""} omp.target_enter_data map_entries(%0, %1, %2 : !llvm.ptr, !llvm.ptr, !llvm.ptr) {} - %3 = omp.map_info var_ptr(%a : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""} - %4 = omp.map_info var_ptr(%b : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""} - %5 = omp.map_info var_ptr(%c : !llvm.ptr, i32) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> !llvm.ptr {name = ""} - %6 = omp.map_info var_ptr(%d : !llvm.ptr, i32) map_clauses(always, delete) capture(ByRef) -> !llvm.ptr {name = ""} + %3 = omp.map.info var_ptr(%a : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""} + %4 = omp.map.info var_ptr(%b : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""} + %5 = omp.map.info var_ptr(%c : !llvm.ptr, i32) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> !llvm.ptr {name = ""} + %6 = omp.map.info var_ptr(%d : !llvm.ptr, i32) map_clauses(always, delete) capture(ByRef) -> !llvm.ptr {name = ""} omp.target_exit_data map_entries(%3, %4, %5, %6 : !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) {} llvm.return } @@ -220,7 +220,7 @@ llvm.func @_QPomp_target_data(%a : !llvm.ptr, %b : !llvm.ptr, %c : !llvm.ptr, %d // CHECK-LABEL: @_QPomp_target_data_region // CHECK: (%[[ARG0:.*]]: !llvm.ptr, %[[ARG1:.*]]: !llvm.ptr) { -// CHECK: %[[MAP_0:.*]] = omp.map_info var_ptr(%[[ARG0]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} +// CHECK: %[[MAP_0:.*]] = omp.map.info var_ptr(%[[ARG0]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} // CHECK: omp.target_data map_entries(%[[MAP_0]] : !llvm.ptr) { // CHECK: %[[VAL_1:.*]] = llvm.mlir.constant(10 : i32) : i32 // CHECK: llvm.store %[[VAL_1]], %[[ARG1]] : i32, !llvm.ptr @@ -229,7 +229,7 @@ llvm.func @_QPomp_target_data(%a : !llvm.ptr, %b : !llvm.ptr, %c : !llvm.ptr, %d // CHECK: llvm.return llvm.func @_QPomp_target_data_region(%a : !llvm.ptr, %i : !llvm.ptr) { - %1 = omp.map_info var_ptr(%a : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %1 = omp.map.info var_ptr(%a : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} omp.target_data map_entries(%1 : !llvm.ptr) { %2 = llvm.mlir.constant(10 : i32) : i32 llvm.store %2, %i : i32, !llvm.ptr @@ -244,8 +244,8 @@ llvm.func @_QPomp_target_data_region(%a : !llvm.ptr, %i : !llvm.ptr) { // CHECK: %[[ARG_0:.*]]: !llvm.ptr, // CHECK: %[[ARG_1:.*]]: !llvm.ptr) { // CHECK: %[[VAL_0:.*]] = llvm.mlir.constant(64 : i32) : i32 -// CHECK: %[[MAP1:.*]] = omp.map_info var_ptr(%[[ARG_0]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} -// CHECK: %[[MAP2:.*]] = omp.map_info var_ptr(%[[ARG_1]] : !llvm.ptr, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !llvm.ptr {name = ""} +// CHECK: %[[MAP1:.*]] = omp.map.info var_ptr(%[[ARG_0]] : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} +// CHECK: %[[MAP2:.*]] = omp.map.info var_ptr(%[[ARG_1]] : !llvm.ptr, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !llvm.ptr {name = ""} // CHECK: omp.target thread_limit(%[[VAL_0]] : i32) map_entries(%[[MAP1]] -> %[[BB_ARG0:.*]], %[[MAP2]] -> %[[BB_ARG1:.*]] : !llvm.ptr, !llvm.ptr) { // CHECK: ^bb0(%[[BB_ARG0]]: !llvm.ptr, %[[BB_ARG1]]: !llvm.ptr): // CHECK: %[[VAL_1:.*]] = llvm.mlir.constant(10 : i32) : i32 @@ -257,8 +257,8 @@ llvm.func @_QPomp_target_data_region(%a : !llvm.ptr, %i : !llvm.ptr) { llvm.func @_QPomp_target(%a : !llvm.ptr, %i : !llvm.ptr) { %0 = llvm.mlir.constant(64 : i32) : i32 - %1 = omp.map_info var_ptr(%a : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} - %3 = omp.map_info var_ptr(%i : !llvm.ptr, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !llvm.ptr {name = ""} + %1 = omp.map.info var_ptr(%a : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %3 = omp.map.info var_ptr(%i : !llvm.ptr, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !llvm.ptr {name = ""} omp.target thread_limit(%0 : i32) map_entries(%1 -> %arg0, %3 -> %arg1 : !llvm.ptr, !llvm.ptr) { ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr): %2 = llvm.mlir.constant(10 : i32) : i32 @@ -304,7 +304,7 @@ llvm.func @_QPsb() { // ----- -// CHECK: omp.reduction.declare @eqv_reduction : i32 init +// CHECK: omp.declare_reduction @eqv_reduction : i32 init // CHECK: ^bb0(%{{.*}}: i32): // CHECK: %[[TRUE:.*]] = llvm.mlir.constant(true) : i1 // CHECK: %[[TRUE_EXT:.*]] = llvm.zext %[[TRUE]] : i1 to i32 @@ -329,7 +329,7 @@ llvm.func @_QPsb() { // CHECK: omp.terminator // CHECK: llvm.return -omp.reduction.declare @eqv_reduction : i32 init { +omp.declare_reduction @eqv_reduction : i32 init { ^bb0(%arg0: i32): %0 = llvm.mlir.constant(true) : i1 %1 = llvm.zext %0 : i1 to i32 @@ -420,8 +420,8 @@ llvm.func @sub_() { %1 = llvm.mlir.constant(1 : index) : i64 %2 = llvm.mlir.constant(1 : i64) : i64 %3 = llvm.alloca %2 x i32 {bindc_name = "i", in_type = i32, operandSegmentSizes = array<i32: 0, 0>, uniq_name = "_QFsubEi"} : (i64) -> !llvm.ptr -// CHECK: omp.ordered_region - omp.ordered_region { +// CHECK: omp.ordered.region + omp.ordered.region { %4 = llvm.trunc %1 : i64 to i32 llvm.br ^bb1(%4, %1 : i32, i64) ^bb1(%5: i32, %6: i64): // 2 preds: ^bb0, ^bb2 @@ -451,14 +451,14 @@ llvm.func @sub_() { // CHECK: %[[C_02:.*]] = llvm.mlir.constant(1 : index) : i64 // CHECK: %[[C_03:.*]] = llvm.mlir.constant(1 : index) : i64 // CHECK: %[[C_04:.*]] = llvm.mlir.constant(1 : index) : i64 -// CHECK: %[[BOUNDS0:.*]] = omp.bounds lower_bound(%[[C_02]] : i64) upper_bound(%[[C_01]] : i64) stride(%[[C_04]] : i64) start_idx(%[[C_04]] : i64) -// CHECK: %[[MAP0:.*]] = omp.map_info var_ptr(%[[ARG_1]] : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS0]]) -> !llvm.ptr {name = ""} +// CHECK: %[[BOUNDS0:.*]] = omp.map.bounds lower_bound(%[[C_02]] : i64) upper_bound(%[[C_01]] : i64) stride(%[[C_04]] : i64) start_idx(%[[C_04]] : i64) +// CHECK: %[[MAP0:.*]] = omp.map.info var_ptr(%[[ARG_1]] : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS0]]) -> !llvm.ptr {name = ""} // CHECK: %[[C_11:.*]] = llvm.mlir.constant(4 : index) : i64 // CHECK: %[[C_12:.*]] = llvm.mlir.constant(1 : index) : i64 // CHECK: %[[C_13:.*]] = llvm.mlir.constant(1 : index) : i64 // CHECK: %[[C_14:.*]] = llvm.mlir.constant(1 : index) : i64 -// CHECK: %[[BOUNDS1:.*]] = omp.bounds lower_bound(%[[C_12]] : i64) upper_bound(%[[C_11]] : i64) stride(%[[C_14]] : i64) start_idx(%[[C_14]] : i64) -// CHECK: %[[MAP1:.*]] = omp.map_info var_ptr(%[[ARG_2]] : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS1]]) -> !llvm.ptr {name = ""} +// CHECK: %[[BOUNDS1:.*]] = omp.map.bounds lower_bound(%[[C_12]] : i64) upper_bound(%[[C_11]] : i64) stride(%[[C_14]] : i64) start_idx(%[[C_14]] : i64) +// CHECK: %[[MAP1:.*]] = omp.map.info var_ptr(%[[ARG_2]] : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS1]]) -> !llvm.ptr {name = ""} // CHECK: omp.target map_entries(%[[MAP0]] -> %[[BB_ARG0:.*]], %[[MAP1]] -> %[[BB_ARG1:.*]] : !llvm.ptr, !llvm.ptr) { // CHECK: ^bb0(%[[BB_ARG0]]: !llvm.ptr, %[[BB_ARG1]]: !llvm.ptr): // CHECK: omp.terminator @@ -471,14 +471,14 @@ llvm.func @_QPtarget_map_with_bounds(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: %1 = llvm.mlir.constant(1 : index) : i64 %2 = llvm.mlir.constant(1 : index) : i64 %3 = llvm.mlir.constant(1 : index) : i64 - %4 = omp.bounds lower_bound(%1 : i64) upper_bound(%0 : i64) stride(%3 : i64) start_idx(%3 : i64) - %5 = omp.map_info var_ptr(%arg1 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%4) -> !llvm.ptr {name = ""} + %4 = omp.map.bounds lower_bound(%1 : i64) upper_bound(%0 : i64) stride(%3 : i64) start_idx(%3 : i64) + %5 = omp.map.info var_ptr(%arg1 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%4) -> !llvm.ptr {name = ""} %6 = llvm.mlir.constant(4 : index) : i64 %7 = llvm.mlir.constant(1 : index) : i64 %8 = llvm.mlir.constant(1 : index) : i64 %9 = llvm.mlir.constant(1 : index) : i64 - %10 = omp.bounds lower_bound(%7 : i64) upper_bound(%6 : i64) stride(%9 : i64) start_idx(%9 : i64) - %11 = omp.map_info var_ptr(%arg2 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%10) -> !llvm.ptr {name = ""} + %10 = omp.map.bounds lower_bound(%7 : i64) upper_bound(%6 : i64) stride(%9 : i64) start_idx(%9 : i64) + %11 = omp.map.info var_ptr(%arg2 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%10) -> !llvm.ptr {name = ""} omp.target map_entries(%5 -> %arg3, %11 -> %arg4: !llvm.ptr, !llvm.ptr) { ^bb0(%arg3: !llvm.ptr, %arg4: !llvm.ptr): omp.terminator diff --git a/mlir/test/Conversion/SCFToOpenMP/reductions.mlir b/mlir/test/Conversion/SCFToOpenMP/reductions.mlir index a6704644873f0952b47a6a164576fa5f8c73706b..3b6c145d62f1a865ac56c56024bedf945c21c6f4 100644 --- a/mlir/test/Conversion/SCFToOpenMP/reductions.mlir +++ b/mlir/test/Conversion/SCFToOpenMP/reductions.mlir @@ -1,6 +1,6 @@ // RUN: mlir-opt -convert-scf-to-openmp -split-input-file %s | FileCheck %s -// CHECK: omp.reduction.declare @[[$REDF:.*]] : f32 +// CHECK: omp.declare_reduction @[[$REDF:.*]] : f32 // CHECK: init // CHECK: %[[INIT:.*]] = llvm.mlir.constant(0.000000e+00 : f32) @@ -51,7 +51,7 @@ func.func @reduction1(%arg0 : index, %arg1 : index, %arg2 : index, // ----- // Only check the declaration here, the rest is same as above. -// CHECK: omp.reduction.declare @{{.*}} : f32 +// CHECK: omp.declare_reduction @{{.*}} : f32 // CHECK: init // CHECK: %[[INIT:.*]] = llvm.mlir.constant(1.000000e+00 : f32) @@ -87,7 +87,7 @@ func.func @reduction2(%arg0 : index, %arg1 : index, %arg2 : index, // Mostly, the same check as above, except for the types, // the name of the op and the init value. -// CHECK: omp.reduction.declare @[[$REDI:.*]] : i32 +// CHECK: omp.declare_reduction @[[$REDI:.*]] : i32 // CHECK: init // CHECK: %[[INIT:.*]] = llvm.mlir.constant(1 : i32) @@ -126,7 +126,7 @@ func.func @reduction_muli(%arg0 : index, %arg1 : index, %arg2 : index, // ----- // Only check the declaration here, the rest is same as above. -// CHECK: omp.reduction.declare @{{.*}} : f32 +// CHECK: omp.declare_reduction @{{.*}} : f32 // CHECK: init // CHECK: %[[INIT:.*]] = llvm.mlir.constant(-3.4 @@ -160,7 +160,7 @@ func.func @reduction3(%arg0 : index, %arg1 : index, %arg2 : index, // ----- -// CHECK: omp.reduction.declare @[[$REDF1:.*]] : f32 +// CHECK: omp.declare_reduction @[[$REDF1:.*]] : f32 // CHECK: init // CHECK: %[[INIT:.*]] = llvm.mlir.constant(-3.4 @@ -174,7 +174,7 @@ func.func @reduction3(%arg0 : index, %arg1 : index, %arg2 : index, // CHECK-NOT: atomic -// CHECK: omp.reduction.declare @[[$REDF2:.*]] : i64 +// CHECK: omp.declare_reduction @[[$REDF2:.*]] : i64 // CHECK: init // CHECK: %[[INIT:.*]] = llvm.mlir.constant diff --git a/mlir/test/Conversion/SCFToSPIRV/for.mlir b/mlir/test/Conversion/SCFToSPIRV/for.mlir index 02558463b8662d4aa5b56ed134a471cc3040bc3a..81661ec7a3a0603a446ac3bc234d216e9c33a137 100644 --- a/mlir/test/Conversion/SCFToSPIRV/for.mlir +++ b/mlir/test/Conversion/SCFToSPIRV/for.mlir @@ -19,17 +19,9 @@ func.func @loop_kernel(%arg2 : memref<10xf32, #spirv.storage_class<StorageBuffer // CHECK: spirv.BranchConditional %[[CMP]], ^[[BODY:.*]], ^[[MERGE:.*]] // CHECK: ^[[BODY]]: // CHECK: %[[ZERO1:.*]] = spirv.Constant 0 : i32 - // CHECK: %[[OFFSET1:.*]] = spirv.Constant 0 : i32 - // CHECK: %[[STRIDE1:.*]] = spirv.Constant 1 : i32 - // CHECK: %[[UPDATE1:.*]] = spirv.IMul %[[STRIDE1]], %[[INDVAR]] : i32 - // CHECK: %[[INDEX1:.*]] = spirv.IAdd %[[OFFSET1]], %[[UPDATE1]] : i32 - // CHECK: spirv.AccessChain {{%.*}}{{\[}}%[[ZERO1]], %[[INDEX1]]{{\]}} + // CHECK: spirv.AccessChain {{%.*}}{{\[}}%[[ZERO1]], %[[INDVAR]]{{\]}} // CHECK: %[[ZERO2:.*]] = spirv.Constant 0 : i32 - // CHECK: %[[OFFSET2:.*]] = spirv.Constant 0 : i32 - // CHECK: %[[STRIDE2:.*]] = spirv.Constant 1 : i32 - // CHECK: %[[UPDATE2:.*]] = spirv.IMul %[[STRIDE2]], %[[INDVAR]] : i32 - // CHECK: %[[INDEX2:.*]] = spirv.IAdd %[[OFFSET2]], %[[UPDATE2]] : i32 - // CHECK: spirv.AccessChain {{%.*}}[%[[ZERO2]], %[[INDEX2]]] + // CHECK: spirv.AccessChain {{%.*}}[%[[ZERO2]], %[[INDVAR]]] // CHECK: %[[INCREMENT:.*]] = spirv.IAdd %[[INDVAR]], %[[STEP]] : i32 // CHECK: spirv.Branch ^[[HEADER]](%[[INCREMENT]] : i32) // CHECK: ^[[MERGE]] diff --git a/mlir/test/Conversion/SPIRVToLLVM/misc-ops-to-llvm.mlir b/mlir/test/Conversion/SPIRVToLLVM/misc-ops-to-llvm.mlir index 9fe1e532dfc77c61577264b7428c9e61d294b693..31da59dcdc726088bd4750fe4db898aa8b1ced43 100644 --- a/mlir/test/Conversion/SPIRVToLLVM/misc-ops-to-llvm.mlir +++ b/mlir/test/Conversion/SPIRVToLLVM/misc-ops-to-llvm.mlir @@ -43,18 +43,18 @@ spirv.func @composite_insert_vector(%arg0: vector<3xf32>, %arg1: f32) "None" { //===----------------------------------------------------------------------===// // CHECK-LABEL: @select_scalar -spirv.func @select_scalar(%arg0: i1, %arg1: vector<3xi32>, %arg2: f32) "None" { +spirv.func @select_scalar(%arg0: i1, %arg1: vector<3xi32>, %arg2: vector<3xi32>, %arg3: f32, %arg4: f32) "None" { // CHECK: llvm.select %{{.*}}, %{{.*}}, %{{.*}} : i1, vector<3xi32> - %0 = spirv.Select %arg0, %arg1, %arg1 : i1, vector<3xi32> + %0 = spirv.Select %arg0, %arg1, %arg2 : i1, vector<3xi32> // CHECK: llvm.select %{{.*}}, %{{.*}}, %{{.*}} : i1, f32 - %1 = spirv.Select %arg0, %arg2, %arg2 : i1, f32 + %1 = spirv.Select %arg0, %arg3, %arg4 : i1, f32 spirv.Return } // CHECK-LABEL: @select_vector -spirv.func @select_vector(%arg0: vector<2xi1>, %arg1: vector<2xi32>) "None" { +spirv.func @select_vector(%arg0: vector<2xi1>, %arg1: vector<2xi32>, %arg2: vector<2xi32>) "None" { // CHECK: llvm.select %{{.*}}, %{{.*}}, %{{.*}} : vector<2xi1>, vector<2xi32> - %0 = spirv.Select %arg0, %arg1, %arg1 : vector<2xi1>, vector<2xi32> + %0 = spirv.Select %arg0, %arg1, %arg2 : vector<2xi1>, vector<2xi32> spirv.Return } diff --git a/mlir/test/Conversion/TensorToLinalg/tensor-ops-to-linalg.mlir b/mlir/test/Conversion/TensorToLinalg/tensor-ops-to-linalg.mlir index 238c0c51312a6b6777d61004b91b8beb6249d2f2..a0a676edceb745a4b1e7a30965dcc0d49e5f613f 100644 --- a/mlir/test/Conversion/TensorToLinalg/tensor-ops-to-linalg.mlir +++ b/mlir/test/Conversion/TensorToLinalg/tensor-ops-to-linalg.mlir @@ -22,7 +22,6 @@ func.func @generalize_pad_tensor_static_shape(%arg0: tensor<1x28x28x1xf32>) -> t // CHECK-LABEL: func @generalize_pad_tensor_dynamic_shape( // CHECK-SAME: %[[IN:.*]]: tensor<4x?x2x?xf32>, // CHECK-SAME: %[[OFFSET:.*]]: index) -> tensor<4x?x?x?xf32> { -// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index // CHECK-DAG: %[[CST:.*]] = arith.constant 0.000000e+00 : f32 // CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index // CHECK: %[[DIM1:.*]] = tensor.dim %[[IN]], %[[C1]] : tensor<4x?x2x?xf32> @@ -33,7 +32,7 @@ func.func @generalize_pad_tensor_static_shape(%arg0: tensor<1x28x28x1xf32>) -> t // CHECK: %[[OUT_DIM3:.*]] = arith.addi %[[DIM3]], %[[OFFSET]] : index // CHECK: %[[INIT:.*]] = tensor.empty(%[[DIM1]], %[[OUT_DIM2]], %[[OUT_DIM3]]) : tensor<4x?x?x?xf32> // CHECK: %[[FILL:.*]] = linalg.fill ins(%[[CST]] : f32) outs(%[[INIT]] : tensor<4x?x?x?xf32>) -> tensor<4x?x?x?xf32> -// CHECK: %[[PADDED:.*]] = tensor.insert_slice %[[IN]] into %[[FILL]]{{\[}}%[[C0]], %[[C0]], %[[OFFSET]], %[[C0]]] [4, %[[DIM1]], 2, %[[DIM3]]] [1, 1, 1, 1] : tensor<4x?x2x?xf32> into tensor<4x?x?x?xf32> +// CHECK: %[[PADDED:.*]] = tensor.insert_slice %[[IN]] into %[[FILL]][0, 0, %[[OFFSET]], 0] [4, %[[DIM1]], 2, %[[DIM3]]] [1, 1, 1, 1] : tensor<4x?x2x?xf32> into tensor<4x?x?x?xf32> // CHECK: return %[[PADDED]] : tensor<4x?x?x?xf32> // CHECK: } func.func @generalize_pad_tensor_dynamic_shape(%arg0: tensor<4x?x2x?xf32>, %arg1: index) -> tensor<4x?x?x?xf32> { diff --git a/mlir/test/Conversion/TensorToSPIRV/tensor-ops-to-spirv.mlir b/mlir/test/Conversion/TensorToSPIRV/tensor-ops-to-spirv.mlir index 19de613bf5b073630375ff24c9989ef1dab0c36d..32d0fbea65b164ab7b137a4a4ba17e7e560e0d8a 100644 --- a/mlir/test/Conversion/TensorToSPIRV/tensor-ops-to-spirv.mlir +++ b/mlir/test/Conversion/TensorToSPIRV/tensor-ops-to-spirv.mlir @@ -14,14 +14,12 @@ func.func @tensor_extract_constant(%a : index, %b: index, %c: index) -> i32 { // CHECK: spirv.Store "Function" %[[VAR]], %[[CST]] : !spirv.array<12 x i32> // CHECK: %[[C0:.+]] = spirv.Constant 0 : i32 // CHECK: %[[C6:.+]] = spirv.Constant 6 : i32 - // CHECK: %[[MUL0:.+]] = spirv.IMul %[[C6]], %[[A]] : i32 - // CHECK: %[[ADD0:.+]] = spirv.IAdd %[[C0]], %[[MUL0]] : i32 + // CHECK: %[[MUL0:.+]] = spirv.IMul %[[A]], %[[C6]] : i32 // CHECK: %[[C3:.+]] = spirv.Constant 3 : i32 - // CHECK: %[[MUL1:.+]] = spirv.IMul %[[C3]], %[[B]] : i32 - // CHECK: %[[ADD1:.+]] = spirv.IAdd %[[ADD0]], %[[MUL1]] : i32 + // CHECK: %[[MUL1:.+]] = spirv.IMul %[[B]], %[[C3]] : i32 + // CHECK: %[[ADD1:.+]] = spirv.IAdd %[[MUL1]], %[[MUL0]] : i32 // CHECK: %[[C1:.+]] = spirv.Constant 1 : i32 - // CHECK: %[[MUL2:.+]] = spirv.IMul %[[C1]], %[[C]] : i32 - // CHECK: %[[ADD2:.+]] = spirv.IAdd %[[ADD1]], %[[MUL2]] : i32 + // CHECK: %[[ADD2:.+]] = spirv.IAdd %[[C]], %[[ADD1]] : i32 // CHECK: %[[AC:.+]] = spirv.AccessChain %[[VAR]][%[[ADD2]]] // CHECK: %[[VAL:.+]] = spirv.Load "Function" %[[AC]] : i32 %extract = tensor.extract %cst[%a, %b, %c] : tensor<2x2x3xi32> diff --git a/mlir/test/Conversion/TosaToTensor/tosa-to-tensor.mlir b/mlir/test/Conversion/TosaToTensor/tosa-to-tensor.mlir index daaa68a7260b71e1070eef8e197769bb168362f8..a8a3c42e1684227418101af0a881ea0e445a1466 100644 --- a/mlir/test/Conversion/TosaToTensor/tosa-to-tensor.mlir +++ b/mlir/test/Conversion/TosaToTensor/tosa-to-tensor.mlir @@ -1,95 +1,363 @@ // RUN: mlir-opt --split-input-file --tosa-to-tensor %s -o -| FileCheck %s -// CHECK-LABEL: @test_reshape_downrank -// CHECK-SAME: (%[[ARG0:[0-9a-zA-Z_]*]] -func.func @test_reshape_downrank(%arg0: tensor<2x3xf32>) -> tensor<6xf32> { - // CHECK: [[RESHAPE:%.+]] = tensor.collapse_shape %[[ARG0]] {{\[}}[0, 1]] - %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 6>} : (tensor<2x3xf32>) -> tensor<6xf32> - // CHECK: return [[RESHAPE]] - return %0 : tensor<6xf32> +// ----- + +// CHECK-LABEL: test_reshape_0d_same_s2s_explicit +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<f32> +// CHECK: return %[[ARG_0]] : tensor<f32> +func.func @test_reshape_0d_same_s2s_explicit(%arg0: tensor<f32>) -> tensor<f32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64>} : (tensor<f32>) -> tensor<f32> + return %0 : tensor<f32> } // ----- -// CHECK-LABEL: @test_reshape_downrank_dyn -// CHECK-SAME: (%[[ARG0:[0-9a-zA-Z_]*]] -func.func @test_reshape_downrank_dyn(%arg0: tensor<2x?xf32>) -> tensor<?xf32> { - // CHECK: [[RESHAPE:%.+]] = tensor.collapse_shape %[[ARG0]] {{\[}}[0, 1]] - %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: -1>} : (tensor<2x?xf32>) -> tensor<?xf32> - // CHECK: return [[RESHAPE]] +// CHECK-LABEL: test_reshape_0d_up_s2d_auto +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<f32> +// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] : tensor<f32> into tensor<1xf32> +// CHECK: %[[VAL_1:.*]] = tensor.cast %[[VAL_0]] : tensor<1xf32> to tensor<?xf32> +// CHECK: return %[[VAL_1]] : tensor<?xf32> +func.func @test_reshape_0d_up_s2d_auto(%arg0: tensor<f32>) -> tensor<?xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: -1>} : (tensor<f32>) -> tensor<?xf32> return %0 : tensor<?xf32> } // ----- -// CHECK-LABEL: @test_reshape_uprank -// CHECK-SAME: (%[[ARG0:[0-9a-zA-Z_]*]] -func.func @test_reshape_uprank(%arg0: tensor<6xf32>) -> tensor<2x3xf32> { - // CHECK: [[RESHAPE:%.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1]] - %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 2, 3>} : (tensor<6xf32>) -> tensor<2x3xf32> - // CHECK: return [[RESHAPE]] - return %0 : tensor<2x3xf32> +// CHECK-LABEL: test_reshape_0d_up_s2d_explicit +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<f32> +// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] : tensor<f32> into tensor<1xf32> +// CHECK: %[[VAL_1:.*]] = tensor.cast %[[VAL_0]] : tensor<1xf32> to tensor<?xf32> +// CHECK: return %[[VAL_1]] : tensor<?xf32> +func.func @test_reshape_0d_up_s2d_explicit(%arg0: tensor<f32>) -> tensor<?xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 1>} : (tensor<f32>) -> tensor<?xf32> + return %0 : tensor<?xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_0d_up_s2s_auto +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<f32> +// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] : tensor<f32> into tensor<1xf32> +// CHECK: return %[[VAL_0]] : tensor<1xf32> +func.func @test_reshape_0d_up_s2s_auto(%arg0: tensor<f32>) -> tensor<1xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: -1>} : (tensor<f32>) -> tensor<1xf32> + return %0 : tensor<1xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_0d_up_s2s_explicit +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<f32> +// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] [] : tensor<f32> into tensor<1xf32> +// CHECK: return %[[VAL_0]] : tensor<1xf32> +func.func @test_reshape_0d_up_s2s_explicit(%arg0: tensor<f32>) -> tensor<1xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 1>} : (tensor<f32>) -> tensor<1xf32> + return %0 : tensor<1xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_1d_down_d2s_explicit +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<?xf32> +// CHECK: %[[VAL_0:.*]] = tensor.cast %[[ARG_0]] : tensor<?xf32> to tensor<1xf32> +// CHECK: %[[VAL_1:.*]] = tensor.collapse_shape %[[VAL_0]] [] : tensor<1xf32> into tensor<f32> +// CHECK: return %[[VAL_1]] : tensor<f32> +func.func @test_reshape_1d_down_d2s_explicit(%arg0: tensor<?xf32>) -> tensor<f32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64>} : (tensor<?xf32>) -> tensor<f32> + return %0 : tensor<f32> +} + +// ----- + +// CHECK-LABEL: test_reshape_1d_down_s2s_explicit +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<1xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] [] : tensor<1xf32> into tensor<f32> +// CHECK: return %[[VAL_0]] : tensor<f32> +func.func @test_reshape_1d_down_s2s_explicit(%arg0: tensor<1xf32>) -> tensor<f32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64>} : (tensor<1xf32>) -> tensor<f32> + return %0 : tensor<f32> } // ----- -// CHECK-LABEL: @test_reshape_uprank_dyn -// CHECK-SAME: (%[[ARG0:[0-9a-zA-Z_]*]] -func.func @test_reshape_uprank_dyn(%arg0: tensor<?xf32>) -> tensor<2x?xf32> { - // CHECK: [[RESHAPE:%.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1]] +// CHECK-LABEL: test_reshape_1d_up_d2d_auto +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<?xf32> +// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor<?xf32> into tensor<2x?xf32> +// CHECK: return %[[VAL_0]] : tensor<2x?xf32> +func.func @test_reshape_1d_up_d2d_auto(%arg0: tensor<?xf32>) -> tensor<2x?xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 2, -1>} : (tensor<?xf32>) -> tensor<2x?xf32> - // CHECK: return [[RESHAPE]] return %0 : tensor<2x?xf32> } // ----- -// CHECK-LABEL: @test_reshape_samerank -// CHECK-SAME: (%[[ARG0:.*]]: tensor<3x2xf32>) -func.func @test_reshape_samerank(%arg0: tensor<3x2xf32>) -> tensor<2x3xf32> { - // CHECK-NEXT: %[[RESHAPE1:.*]] = tensor.collapse_shape %[[ARG0]] {{\[}}[0, 1]] - // CHECK-NEXT: %[[RESHAPE2:.*]] = tensor.expand_shape %[[RESHAPE1]] {{\[}}[0, 1]] - %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 2, 3>} : (tensor<3x2xf32>) -> tensor<2x3xf32> - // CHECK-NEXT: return %[[RESHAPE2]] +// CHECK-LABEL: test_reshape_1d_up_s2s_explicit +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<6xf32> +// CHECK: %[[VAL_0:.*]] = tensor.expand_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor<6xf32> into tensor<2x3xf32> +// CHECK: return %[[VAL_0]] : tensor<2x3xf32> +func.func @test_reshape_1d_up_s2s_explicit(%arg0: tensor<6xf32>) -> tensor<2x3xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 2, 3>} : (tensor<6xf32>) -> tensor<2x3xf32> return %0 : tensor<2x3xf32> } // ----- -// CHECK-LABEL: @test_reshape_samerank_dyn -// CHECK-SAME: (%[[ARG0:.*]]: tensor<?x2xf32>) -func.func @test_reshape_samerank_dyn(%arg0: tensor<?x2xf32>) -> tensor<2x?xf32> { - // CHECK-NEXT: %[[RESHAPE1:.*]] = tensor.collapse_shape %[[ARG0]] {{\[}}[0, 1]] - // CHECK-NEXT: %[[RESHAPE2:.*]] = tensor.expand_shape %[[RESHAPE1]] {{\[}}[0, 1]] +// CHECK-LABEL: test_reshape_2d_down_d2d_auto +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<2x?xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor<2x?xf32> into tensor<?xf32> +// CHECK: return %[[VAL_0]] : tensor<?xf32> +func.func @test_reshape_2d_down_d2d_auto(%arg0: tensor<2x?xf32>) -> tensor<?xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: -1>} : (tensor<2x?xf32>) -> tensor<?xf32> + return %0 : tensor<?xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_2d_down_s2s_explicit +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<2x3xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor<2x3xf32> into tensor<6xf32> +// CHECK: return %[[VAL_0]] : tensor<6xf32> +func.func @test_reshape_2d_down_s2s_explicit(%arg0: tensor<2x3xf32>) -> tensor<6xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 6>} : (tensor<2x3xf32>) -> tensor<6xf32> + return %0 : tensor<6xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_2d_same_d2d_auto +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<?x2xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor<?x2xf32> into tensor<?xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] : tensor<?xf32> into tensor<2x?xf32> +// CHECK: return %[[VAL_1]] : tensor<2x?xf32> +func.func @test_reshape_2d_same_d2d_auto(%arg0: tensor<?x2xf32>) -> tensor<2x?xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 2, -1>} : (tensor<?x2xf32>) -> tensor<2x?xf32> - // CHECK-NEXT: return %[[RESHAPE2]] return %0 : tensor<2x?xf32> } // ----- -// CHECK-LABEL: @test_reshape_downrank_6D -// CHECK-SAME: (%[[ARG0:[0-9a-zA-Z_]*]]: -func.func @test_reshape_downrank_6D(%arg0: tensor<1x2x3x5x7x11xf32>) -> tensor<6x5x77xf32> { - // CHECK: tensor.collapse_shape %[[ARG0]] {{\[}}[0, 1, 2], [3], [4, 5]] - %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 6, 5, 77>} : (tensor<1x2x3x5x7x11xf32>) -> tensor<6x5x77xf32> - return %0 : tensor<6x5x77xf32> +// CHECK-LABEL: test_reshape_2d_same_s2d_auto +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<2x4xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor<2x4xf32> into tensor<8xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] : tensor<8xf32> into tensor<4x2xf32> +// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<4x2xf32> to tensor<?x2xf32> +// CHECK: return %[[VAL_2]] : tensor<?x2xf32> +func.func @test_reshape_2d_same_s2d_auto(%arg0: tensor<2x4xf32>) -> tensor<?x2xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: -1, 2>} : (tensor<2x4xf32>) -> tensor<?x2xf32> + return %0 : tensor<?x2xf32> } // ----- -// CHECK-LABEL: @test_reshape_downrank_6D_dyn -// CHECK-SAME: (%[[ARG0:[0-9a-zA-Z_]*]]: -func.func @test_reshape_downrank_6D_dyn(%arg0: tensor<1x2x?x5x7x11xf32>) -> tensor<?x5x77xf32> { - // CHECK: tensor.collapse_shape %[[ARG0]] {{\[}}[0, 1, 2, 3, 4, 5]] - // CHECK: tensor.expand_shape %{{.*}} {{\[}}[0, 1, 2]] +// CHECK-LABEL: test_reshape_2d_same_s2d_explicit +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<2x4xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor<2x4xf32> into tensor<8xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] : tensor<8xf32> into tensor<4x2xf32> +// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<4x2xf32> to tensor<?x2xf32> +// CHECK: return %[[VAL_2]] : tensor<?x2xf32> +func.func @test_reshape_2d_same_s2d_explicit(%arg0: tensor<2x4xf32>) -> tensor<?x2xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 4, 2>} : (tensor<2x4xf32>) -> tensor<?x2xf32> + return %0 : tensor<?x2xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_2d_same_s2s_explicit +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<3x2xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1]] : tensor<3x2xf32> into tensor<6xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1]] : tensor<6xf32> into tensor<2x3xf32> +// CHECK: return %[[VAL_1]] : tensor<2x3xf32> +func.func @test_reshape_2d_same_s2s_explicit(%arg0: tensor<3x2xf32>) -> tensor<2x3xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 2, 3>} : (tensor<3x2xf32>) -> tensor<2x3xf32> + return %0 : tensor<2x3xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_3d_same_d2d_auto_empty +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<3x2x?xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor<3x2x?xf32> into tensor<?xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor<?xf32> into tensor<0x3x?xf32> +// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<0x3x?xf32> to tensor<?x?x?xf32> +// CHECK: return %[[VAL_2]] : tensor<?x?x?xf32> +func.func @test_reshape_3d_same_d2d_auto_empty(%arg0: tensor<3x2x?xf32>) -> tensor<?x?x?xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 0, 3, -1>} : (tensor<3x2x?xf32>) -> tensor<?x?x?xf32> + return %0 : tensor<?x?x?xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_3d_same_d2d_auto +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<2x?x?xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor<2x?x?xf32> into tensor<?xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor<?xf32> into tensor<2x?x4xf32> +// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<2x?x4xf32> to tensor<?x?x?xf32> +// CHECK: return %[[VAL_2]] : tensor<?x?x?xf32> +func.func @test_reshape_3d_same_d2d_auto(%arg0: tensor<2x?x?xf32>) -> tensor<?x?x?xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 2, -1, 4>} : (tensor<2x?x?xf32>) -> tensor<?x?x?xf32> + return %0 : tensor<?x?x?xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_3d_same_d2d_auto_identity +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<?x3x4xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor<?x3x4xf32> into tensor<?xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor<?xf32> into tensor<2x3x?xf32> +// CHECK: return %[[VAL_1]] : tensor<2x3x?xf32> +func.func @test_reshape_3d_same_d2d_auto_identity(%arg0: tensor<?x3x4xf32>) -> tensor<2x3x?xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 2, 3, -1>} : (tensor<?x3x4xf32>) -> tensor<2x3x?xf32> + return %0 : tensor<2x3x?xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_3d_same_d2d_explicit_empty +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<3x2x?xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor<3x2x?xf32> into tensor<?xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor<?xf32> into tensor<?x3x2xf32> +// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<?x3x2xf32> to tensor<?x?x?xf32> +// CHECK: return %[[VAL_2]] : tensor<?x?x?xf32> +func.func @test_reshape_3d_same_d2d_explicit_empty(%arg0: tensor<3x2x?xf32>) -> tensor<?x?x?xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 0, 3, 2>} : (tensor<3x2x?xf32>) -> tensor<?x?x?xf32> + return %0 : tensor<?x?x?xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_3d_same_d2d_explicit +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<?x?x?xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor<?x?x?xf32> into tensor<?xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor<?xf32> into tensor<?x3x4xf32> +// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<?x3x4xf32> to tensor<?x?x?xf32> +// CHECK: return %[[VAL_2]] : tensor<?x?x?xf32> +func.func @test_reshape_3d_same_d2d_explicit(%arg0: tensor<?x?x?xf32>) -> tensor<?x?x?xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 2, 3, 4>} : (tensor<?x?x?xf32>) -> tensor<?x?x?xf32> + return %0 : tensor<?x?x?xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_3d_same_d2d_explicit_identity +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<?x3x4xf32> +// CHECK: %[[VAL_0:.*]] = tensor.cast %[[ARG_0]] : tensor<?x3x4xf32> to tensor<2x3x?xf32> +// CHECK: return %[[VAL_0]] : tensor<2x3x?xf32> +func.func @test_reshape_3d_same_d2d_explicit_identity(%arg0: tensor<?x3x4xf32>) -> tensor<2x3x?xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 2, 3, 4>} : (tensor<?x3x4xf32>) -> tensor<2x3x?xf32> + return %0 : tensor<2x3x?xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_3d_same_d2s_auto +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<?x?x?xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor<?x?x?xf32> into tensor<?xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor<?xf32> into tensor<2x?x4xf32> +// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<2x?x4xf32> to tensor<2x3x4xf32> +// CHECK: return %[[VAL_2]] : tensor<2x3x4xf32> +func.func @test_reshape_3d_same_d2s_auto(%arg0: tensor<?x?x?xf32>) -> tensor<2x3x4xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 2, -1, 4>} : (tensor<?x?x?xf32>) -> tensor<2x3x4xf32> + return %0 : tensor<2x3x4xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_3d_same_d2s_explicit +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<?x?x?xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor<?x?x?xf32> into tensor<?xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor<?xf32> into tensor<?x3x4xf32> +// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<?x3x4xf32> to tensor<2x3x4xf32> +// CHECK: return %[[VAL_2]] : tensor<2x3x4xf32> +func.func @test_reshape_3d_same_d2s_explicit(%arg0: tensor<?x?x?xf32>) -> tensor<2x3x4xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 2, 3, 4>} : (tensor<?x?x?xf32>) -> tensor<2x3x4xf32> + return %0 : tensor<2x3x4xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_3d_same_s2s_explicit_identity +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<2x3x4xf32> +// CHECK: return %[[ARG_0]] : tensor<2x3x4xf32> +func.func @test_reshape_3d_same_s2s_explicit_identity(%arg0: tensor<2x3x4xf32>) -> tensor<2x3x4xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 2, 3, 4>} : (tensor<2x3x4xf32>) -> tensor<2x3x4xf32> + return %0 : tensor<2x3x4xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_3d_up_d2s_explicit +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<?x?x?xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2]] : tensor<?x?x?xf32> into tensor<?xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2, 3]] : tensor<?xf32> into tensor<?x3x2x1xf32> +// CHECK: %[[VAL_2:.*]] = tensor.cast %[[VAL_1]] : tensor<?x3x2x1xf32> to tensor<1x3x2x1xf32> +// CHECK: return %[[VAL_2]] : tensor<1x3x2x1xf32> +func.func @test_reshape_3d_up_d2s_explicit(%input: tensor<?x?x?xf32>) -> tensor<1x3x2x1xf32> { + %0 = tosa.reshape %input {new_shape = array<i64: 1, 3, 2, 1>} : (tensor<?x?x?xf32>) -> tensor<1x3x2x1xf32> + return %0 : tensor<1x3x2x1xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_4d_down_d2s_explicit +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<?x?x?x?xf32> +// CHECK: %[[VAL_0:.*]] = tensor.cast %[[ARG_0]] : tensor<?x?x?x?xf32> to tensor<1x1x1x1xf32> +// CHECK: %[[VAL_1:.*]] = tensor.collapse_shape %[[VAL_0]] [] : tensor<1x1x1x1xf32> into tensor<f32> +// CHECK: return %[[VAL_1]] : tensor<f32> +func.func @test_reshape_4d_down_d2s_explicit(%arg0: tensor<?x?x?x?xf32>) -> tensor<f32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64>} : (tensor<?x?x?x?xf32>) -> tensor<f32> + return %0 : tensor<f32> +} + +// ----- + +// CHECK-LABEL: test_reshape_5d_down_d2d_auto +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<?x?x?x2x3xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2, 3, 4]] : tensor<?x?x?x2x3xf32> into tensor<?xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor<?xf32> into tensor<?x2x3xf32> +// CHECK: return %[[VAL_1]] : tensor<?x2x3xf32> +func.func @test_reshape_5d_down_d2d_auto(%arg0: tensor<?x?x?x2x3xf32>) -> tensor<?x2x3xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: -1, 2, 3>} : (tensor<?x?x?x2x3xf32>) -> tensor<?x2x3xf32> + return %0 : tensor<?x2x3xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_6d_down_d2d_auto +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<1x2x?x5x7x11xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2, 3, 4, 5]] : tensor<1x2x?x5x7x11xf32> into tensor<?xf32> +// CHECK: %[[VAL_1:.*]] = tensor.expand_shape %[[VAL_0]] {{\[\[}}0, 1, 2]] : tensor<?xf32> into tensor<?x5x77xf32> +// CHECK: return %[[VAL_1]] : tensor<?x5x77xf32> +func.func @test_reshape_6d_down_d2d_auto(%arg0: tensor<1x2x?x5x7x11xf32>) -> tensor<?x5x77xf32> { %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: -1, 5, 77>} : (tensor<1x2x?x5x7x11xf32>) -> tensor<?x5x77xf32> return %0 : tensor<?x5x77xf32> } // ----- -// CHECK-LABLE: func @slice +// CHECK-LABEL: test_reshape_6d_down_s2s_auto +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<1x2x3x5x7x11xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2], [3], [4, 5]] : tensor<1x2x3x5x7x11xf32> into tensor<6x5x77xf32> +// CHECK: return %[[VAL_0]] : tensor<6x5x77xf32> +func.func @test_reshape_6d_down_s2s_auto(%arg0: tensor<1x2x3x5x7x11xf32>) -> tensor<6x5x77xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 6, 5, -1>} : (tensor<1x2x3x5x7x11xf32>) -> tensor<6x5x77xf32> + return %0 : tensor<6x5x77xf32> +} + +// ----- + +// CHECK-LABEL: test_reshape_6d_down_s2s_explicit +// CHECK-SAME: %[[ARG_0:[a-zA-Z0-9_]+]]: tensor<1x2x3x5x7x11xf32> +// CHECK: %[[VAL_0:.*]] = tensor.collapse_shape %[[ARG_0]] {{\[\[}}0, 1, 2], [3], [4, 5]] : tensor<1x2x3x5x7x11xf32> into tensor<6x5x77xf32> +// CHECK: return %[[VAL_0]] : tensor<6x5x77xf32> +func.func @test_reshape_6d_down_s2s_explicit(%arg0: tensor<1x2x3x5x7x11xf32>) -> tensor<6x5x77xf32> { + %0 = "tosa.reshape"(%arg0) {new_shape = array<i64: 6, 5, 77>} : (tensor<1x2x3x5x7x11xf32>) -> tensor<6x5x77xf32> + return %0 : tensor<6x5x77xf32> +} + +// ----- + +// CHECK-LABEL: func @slice func.func @slice(%arg0: tensor<6xf32>) ->() { // CHECK: [[SLICE:%.+]] = tensor.extract_slice %arg0[2] [1] [1] %0 = "tosa.slice"(%arg0) {start = array<i64: 2>, size = array<i64: 1>} : (tensor<6xf32>) -> (tensor<1xf32>) diff --git a/mlir/test/Conversion/VectorToSPIRV/vector-to-spirv.mlir b/mlir/test/Conversion/VectorToSPIRV/vector-to-spirv.mlir index c9984091d5acc6ac18cd1545a9432d801802a090..cddc4ee385357de5c2474ad630a45a0cfc4e6f5a 100644 --- a/mlir/test/Conversion/VectorToSPIRV/vector-to-spirv.mlir +++ b/mlir/test/Conversion/VectorToSPIRV/vector-to-spirv.mlir @@ -720,9 +720,7 @@ module attributes { // CHECK: %[[CST1:.+]] = spirv.Constant 0 : i32 // CHECK: %[[CST2:.+]] = spirv.Constant 0 : i32 // CHECK: %[[CST3:.+]] = spirv.Constant 1 : i32 -// CHECK: %[[S2:.+]] = spirv.IMul %[[CST3]], %[[S1]] : i32 -// CHECK: %[[S3:.+]] = spirv.IAdd %[[CST2]], %[[S2]] : i32 -// CHECK: %[[S4:.+]] = spirv.AccessChain %[[S0]][%[[CST1]], %[[S3]]] : !spirv.ptr<!spirv.struct<(!spirv.array<4 x f32, stride=4> [0])>, StorageBuffer>, i32, i32 +// CHECK: %[[S4:.+]] = spirv.AccessChain %[[S0]][%[[CST1]], %[[S1]]] : !spirv.ptr<!spirv.struct<(!spirv.array<4 x f32, stride=4> [0])>, StorageBuffer>, i32, i32 // CHECK: %[[S5:.+]] = spirv.Bitcast %[[S4]] : !spirv.ptr<f32, StorageBuffer> to !spirv.ptr<vector<4xf32>, StorageBuffer> // CHECK: %[[R0:.+]] = spirv.Load "StorageBuffer" %[[S5]] : vector<4xf32> // CHECK: return %[[R0]] : vector<4xf32> @@ -743,11 +741,9 @@ func.func @vector_load(%arg0 : memref<4xf32, #spirv.storage_class<StorageBuffer> // CHECK: %[[CST0_1:.+]] = spirv.Constant 0 : i32 // CHECK: %[[CST0_2:.+]] = spirv.Constant 0 : i32 // CHECK: %[[CST4:.+]] = spirv.Constant 4 : i32 -// CHECK: %[[S3:.+]] = spirv.IMul %[[CST4]], %[[S1]] : i32 -// CHECK: %[[S4:.+]] = spirv.IAdd %[[CST0_2]], %[[S3]] : i32 +// CHECK: %[[S3:.+]] = spirv.IMul %[[S1]], %[[CST4]] : i32 // CHECK: %[[CST1:.+]] = spirv.Constant 1 : i32 -// CHECK: %[[S5:.+]] = spirv.IMul %[[CST1]], %[[S2]] : i32 -// CHECK: %[[S6:.+]] = spirv.IAdd %[[S4]], %[[S5]] : i32 +// CHECK: %[[S6:.+]] = spirv.IAdd %[[S2]], %[[S3]] : i32 // CHECK: %[[S7:.+]] = spirv.AccessChain %[[S0]][%[[CST0_1]], %[[S6]]] : !spirv.ptr<!spirv.struct<(!spirv.array<16 x f32, stride=4> [0])>, StorageBuffer>, i32, i32 // CHECK: %[[S8:.+]] = spirv.Bitcast %[[S7]] : !spirv.ptr<f32, StorageBuffer> to !spirv.ptr<vector<4xf32>, StorageBuffer> // CHECK: %[[R0:.+]] = spirv.Load "StorageBuffer" %[[S8]] : vector<4xf32> @@ -768,9 +764,7 @@ func.func @vector_load_2d(%arg0 : memref<4x4xf32, #spirv.storage_class<StorageBu // CHECK: %[[CST1:.+]] = spirv.Constant 0 : i32 // CHECK: %[[CST2:.+]] = spirv.Constant 0 : i32 // CHECK: %[[CST3:.+]] = spirv.Constant 1 : i32 -// CHECK: %[[S2:.+]] = spirv.IMul %[[CST3]], %[[S1]] : i32 -// CHECK: %[[S3:.+]] = spirv.IAdd %[[CST2]], %[[S2]] : i32 -// CHECK: %[[S4:.+]] = spirv.AccessChain %[[S0]][%[[CST1]], %[[S3]]] : !spirv.ptr<!spirv.struct<(!spirv.array<4 x f32, stride=4> [0])>, StorageBuffer>, i32, i32 +// CHECK: %[[S4:.+]] = spirv.AccessChain %[[S0]][%[[CST1]], %[[S1]]] : !spirv.ptr<!spirv.struct<(!spirv.array<4 x f32, stride=4> [0])>, StorageBuffer>, i32, i32 // CHECK: %[[S5:.+]] = spirv.Bitcast %[[S4]] : !spirv.ptr<f32, StorageBuffer> to !spirv.ptr<vector<4xf32>, StorageBuffer> // CHECK: spirv.Store "StorageBuffer" %[[S5]], %[[ARG1]] : vector<4xf32> func.func @vector_store(%arg0 : memref<4xf32, #spirv.storage_class<StorageBuffer>>, %arg1 : vector<4xf32>) { @@ -790,11 +784,9 @@ func.func @vector_store(%arg0 : memref<4xf32, #spirv.storage_class<StorageBuffer // CHECK: %[[CST0_1:.+]] = spirv.Constant 0 : i32 // CHECK: %[[CST0_2:.+]] = spirv.Constant 0 : i32 // CHECK: %[[CST4:.+]] = spirv.Constant 4 : i32 -// CHECK: %[[S3:.+]] = spirv.IMul %[[CST4]], %[[S1]] : i32 -// CHECK: %[[S4:.+]] = spirv.IAdd %[[CST0_2]], %[[S3]] : i32 +// CHECK: %[[S3:.+]] = spirv.IMul %[[S1]], %[[CST4]] : i32 // CHECK: %[[CST1:.+]] = spirv.Constant 1 : i32 -// CHECK: %[[S5:.+]] = spirv.IMul %[[CST1]], %[[S2]] : i32 -// CHECK: %[[S6:.+]] = spirv.IAdd %[[S4]], %[[S5]] : i32 +// CHECK: %[[S6:.+]] = spirv.IAdd %[[S2]], %[[S3]] : i32 // CHECK: %[[S7:.+]] = spirv.AccessChain %[[S0]][%[[CST0_1]], %[[S6]]] : !spirv.ptr<!spirv.struct<(!spirv.array<16 x f32, stride=4> [0])>, StorageBuffer>, i32, i32 // CHECK: %[[S8:.+]] = spirv.Bitcast %[[S7]] : !spirv.ptr<f32, StorageBuffer> to !spirv.ptr<vector<4xf32>, StorageBuffer> // CHECK: spirv.Store "StorageBuffer" %[[S8]], %[[ARG1]] : vector<4xf32> diff --git a/mlir/test/Dialect/Affine/access-analysis.mlir b/mlir/test/Dialect/Affine/access-analysis.mlir index 68310b9323535ade16a24bbe433195c2ae1d0153..789de646a8f9e2aab7bf27ea12470cb30abfa30b 100644 --- a/mlir/test/Dialect/Affine/access-analysis.mlir +++ b/mlir/test/Dialect/Affine/access-analysis.mlir @@ -1,13 +1,14 @@ // RUN: mlir-opt %s -split-input-file -test-affine-access-analysis -verify-diagnostics | FileCheck %s -// CHECK-LABEL: func @loop_1d -func.func @loop_1d(%A : memref<?x?xf32>, %B : memref<?x?x?xf32>) { +// CHECK-LABEL: func @loop_simple +func.func @loop_simple(%A : memref<?x?xf32>, %B : memref<?x?x?xf32>) { %c0 = arith.constant 0 : index %M = memref.dim %A, %c0 : memref<?x?xf32> affine.for %i = 0 to %M { affine.for %j = 0 to %M { affine.load %A[%c0, %i] : memref<?x?xf32> // expected-remark@above {{contiguous along loop 0}} + // expected-remark@above {{invariant along loop 1}} affine.load %A[%c0, 8 * %i + %j] : memref<?x?xf32> // expected-remark@above {{contiguous along loop 1}} // Note/FIXME: access stride isn't being checked. @@ -15,6 +16,7 @@ func.func @loop_1d(%A : memref<?x?xf32>, %B : memref<?x?x?xf32>) { // These are all non-contiguous along both loops. Nothing is emitted. affine.load %A[%i, %c0] : memref<?x?xf32> + // expected-remark@above {{invariant along loop 1}} // Note/FIXME: access stride isn't being checked. affine.load %A[%i, 8 * %j] : memref<?x?xf32> // expected-remark@above {{contiguous along loop 1}} @@ -27,6 +29,22 @@ func.func @loop_1d(%A : memref<?x?xf32>, %B : memref<?x?x?xf32>) { // ----- +// CHECK-LABEL: func @loop_unsimplified +func.func @loop_unsimplified(%A : memref<100xf32>) { + affine.for %i = 0 to 100 { + affine.load %A[2 * %i - %i - %i] : memref<100xf32> + // expected-remark@above {{invariant along loop 0}} + + %m = affine.apply affine_map<(d0) -> (-2 * d0)>(%i) + %n = affine.apply affine_map<(d0) -> (2 * d0)>(%i) + affine.load %A[(%m + %n) floordiv 2] : memref<100xf32> + // expected-remark@above {{invariant along loop 0}} + } + return +} + +// ----- + #map = affine_map<(d0) -> (d0 * 16)> #map1 = affine_map<(d0) -> (d0 * 16 + 16)> #map2 = affine_map<(d0) -> (d0)> @@ -41,11 +59,19 @@ func.func @tiled(%arg0: memref<*xf32>) { %alloc_0 = memref.alloc() : memref<1x16x1x16xf32> affine.for %arg4 = #map(%arg1) to #map1(%arg1) { affine.for %arg5 = #map(%arg3) to #map1(%arg3) { + // TODO: here and below, the access isn't really invariant + // along tile-space IVs where the intra-tile IVs' bounds + // depend on them. %0 = affine.load %cast[%arg4] : memref<64xf32> // expected-remark@above {{contiguous along loop 3}} + // expected-remark@above {{invariant along loop 0}} + // expected-remark@above {{invariant along loop 1}} + // expected-remark@above {{invariant along loop 2}} + // expected-remark@above {{invariant along loop 4}} affine.store %0, %alloc_0[0, %arg1 * -16 + %arg4, 0, %arg3 * -16 + %arg5] : memref<1x16x1x16xf32> // expected-remark@above {{contiguous along loop 4}} // expected-remark@above {{contiguous along loop 2}} + // expected-remark@above {{invariant along loop 1}} } } affine.for %arg4 = #map(%arg1) to #map1(%arg1) { @@ -56,6 +82,9 @@ func.func @tiled(%arg0: memref<*xf32>) { // expected-remark@above {{contiguous along loop 2}} affine.store %0, %alloc[0, %arg5, %arg6, %arg4] : memref<1x224x224x64xf32> // expected-remark@above {{contiguous along loop 3}} + // expected-remark@above {{invariant along loop 0}} + // expected-remark@above {{invariant along loop 1}} + // expected-remark@above {{invariant along loop 2}} } } } diff --git a/mlir/test/Dialect/Arith/canonicalize.mlir b/mlir/test/Dialect/Arith/canonicalize.mlir index cb98a10048a309461b4c33425691f1e319e9ddac..79a318565e98f9db15b1576703d4d9fca73f7b38 100644 --- a/mlir/test/Dialect/Arith/canonicalize.mlir +++ b/mlir/test/Dialect/Arith/canonicalize.mlir @@ -116,18 +116,6 @@ func.func @selToNot(%arg0: i1) -> i1 { return %res : i1 } -// CHECK-LABEL: @selToArith -// CHECK-NEXT: %[[trueval:.+]] = arith.constant true -// CHECK-NEXT: %[[notcmp:.+]] = arith.xori %arg0, %[[trueval]] : i1 -// CHECK-NEXT: %[[condtrue:.+]] = arith.andi %arg0, %arg1 : i1 -// CHECK-NEXT: %[[condfalse:.+]] = arith.andi %[[notcmp]], %arg2 : i1 -// CHECK-NEXT: %[[res:.+]] = arith.ori %[[condtrue]], %[[condfalse]] : i1 -// CHECK: return %[[res]] -func.func @selToArith(%arg0: i1, %arg1 : i1, %arg2 : i1) -> i1 { - %res = arith.select %arg0, %arg1, %arg2 : i1 - return %res : i1 -} - // CHECK-LABEL: @redundantSelectTrue // CHECK-NEXT: %[[res:.+]] = arith.select %arg0, %arg1, %arg3 // CHECK-NEXT: return %[[res]] @@ -160,74 +148,6 @@ func.func @selNotCond(%arg0: i1, %arg1 : i32, %arg2 : i32, %arg3 : i32, %arg4 : return %res1, %res2 : i32, i32 } -// CHECK-LABEL: @selAndCond -// CHECK-NEXT: %[[and:.+]] = arith.andi %arg1, %arg0 -// CHECK-NEXT: %[[res:.+]] = arith.select %[[and]], %arg2, %arg3 -// CHECK-NEXT: return %[[res]] -func.func @selAndCond(%arg0: i1, %arg1: i1, %arg2 : i32, %arg3 : i32) -> i32 { - %sel = arith.select %arg0, %arg2, %arg3 : i32 - %res = arith.select %arg1, %sel, %arg3 : i32 - return %res : i32 -} - -// CHECK-LABEL: @selAndNotCond -// CHECK-NEXT: %[[one:.+]] = arith.constant true -// CHECK-NEXT: %[[not:.+]] = arith.xori %arg0, %[[one]] -// CHECK-NEXT: %[[and:.+]] = arith.andi %arg1, %[[not]] -// CHECK-NEXT: %[[res:.+]] = arith.select %[[and]], %arg3, %arg2 -// CHECK-NEXT: return %[[res]] -func.func @selAndNotCond(%arg0: i1, %arg1: i1, %arg2 : i32, %arg3 : i32) -> i32 { - %sel = arith.select %arg0, %arg2, %arg3 : i32 - %res = arith.select %arg1, %sel, %arg2 : i32 - return %res : i32 -} - -// CHECK-LABEL: @selAndNotCondVec -// CHECK-NEXT: %[[one:.+]] = arith.constant dense<true> : vector<4xi1> -// CHECK-NEXT: %[[not:.+]] = arith.xori %arg0, %[[one]] -// CHECK-NEXT: %[[and:.+]] = arith.andi %arg1, %[[not]] -// CHECK-NEXT: %[[res:.+]] = arith.select %[[and]], %arg3, %arg2 -// CHECK-NEXT: return %[[res]] -func.func @selAndNotCondVec(%arg0: vector<4xi1>, %arg1: vector<4xi1>, %arg2 : vector<4xi32>, %arg3 : vector<4xi32>) -> vector<4xi32> { - %sel = arith.select %arg0, %arg2, %arg3 : vector<4xi1>, vector<4xi32> - %res = arith.select %arg1, %sel, %arg2 : vector<4xi1>, vector<4xi32> - return %res : vector<4xi32> -} - -// CHECK-LABEL: @selOrCond -// CHECK-NEXT: %[[or:.+]] = arith.ori %arg1, %arg0 -// CHECK-NEXT: %[[res:.+]] = arith.select %[[or]], %arg2, %arg3 -// CHECK-NEXT: return %[[res]] -func.func @selOrCond(%arg0: i1, %arg1: i1, %arg2 : i32, %arg3 : i32) -> i32 { - %sel = arith.select %arg0, %arg2, %arg3 : i32 - %res = arith.select %arg1, %arg2, %sel : i32 - return %res : i32 -} - -// CHECK-LABEL: @selOrNotCond -// CHECK-NEXT: %[[one:.+]] = arith.constant true -// CHECK-NEXT: %[[not:.+]] = arith.xori %arg0, %[[one]] -// CHECK-NEXT: %[[or:.+]] = arith.ori %arg1, %[[not]] -// CHECK-NEXT: %[[res:.+]] = arith.select %[[or]], %arg3, %arg2 -// CHECK-NEXT: return %[[res]] -func.func @selOrNotCond(%arg0: i1, %arg1: i1, %arg2 : i32, %arg3 : i32) -> i32 { - %sel = arith.select %arg0, %arg2, %arg3 : i32 - %res = arith.select %arg1, %arg3, %sel : i32 - return %res : i32 -} - -// CHECK-LABEL: @selOrNotCondVec -// CHECK-NEXT: %[[one:.+]] = arith.constant dense<true> : vector<4xi1> -// CHECK-NEXT: %[[not:.+]] = arith.xori %arg0, %[[one]] -// CHECK-NEXT: %[[or:.+]] = arith.ori %arg1, %[[not]] -// CHECK-NEXT: %[[res:.+]] = arith.select %[[or]], %arg3, %arg2 -// CHECK-NEXT: return %[[res]] -func.func @selOrNotCondVec(%arg0: vector<4xi1>, %arg1: vector<4xi1>, %arg2 : vector<4xi32>, %arg3 : vector<4xi32>) -> vector<4xi32> { - %sel = arith.select %arg0, %arg2, %arg3 : vector<4xi1>, vector<4xi32> - %res = arith.select %arg1, %arg3, %sel : vector<4xi1>, vector<4xi32> - return %res : vector<4xi32> -} - // Test case: Folding of comparisons with equal operands. // CHECK-LABEL: @cmpi_equal_operands // CHECK-DAG: %[[T:.*]] = arith.constant true @@ -837,6 +757,51 @@ func.func @truncFPConstant() -> bf16 { return %0 : bf16 } +// CHECK-LABEL: @truncFPToNearestEvenConstant +// CHECK: %[[cres:.+]] = arith.constant 1.000000e+00 : bf16 +// CHECK: return %[[cres]] +func.func @truncFPToNearestEvenConstant() -> bf16 { + %cst = arith.constant 1.000000e+00 : f32 + %0 = arith.truncf %cst to_nearest_even : f32 to bf16 + return %0 : bf16 +} + +// CHECK-LABEL: @truncFPDownwardConstant +// CHECK: %[[cres:.+]] = arith.constant 1.000000e+00 : bf16 +// CHECK: return %[[cres]] +func.func @truncFPDownwardConstant() -> bf16 { + %cst = arith.constant 1.000000e+00 : f32 + %0 = arith.truncf %cst downward : f32 to bf16 + return %0 : bf16 +} + +// CHECK-LABEL: @truncFPUpwardConstant +// CHECK: %[[cres:.+]] = arith.constant 1.000000e+00 : bf16 +// CHECK: return %[[cres]] +func.func @truncFPUpwardConstant() -> bf16 { + %cst = arith.constant 1.000000e+00 : f32 + %0 = arith.truncf %cst upward : f32 to bf16 + return %0 : bf16 +} + +// CHECK-LABEL: @truncFPTowardZeroConstant +// CHECK: %[[cres:.+]] = arith.constant 1.000000e+00 : bf16 +// CHECK: return %[[cres]] +func.func @truncFPTowardZeroConstant() -> bf16 { + %cst = arith.constant 1.000000e+00 : f32 + %0 = arith.truncf %cst toward_zero : f32 to bf16 + return %0 : bf16 +} + +// CHECK-LABEL: @truncFPToNearestAwayConstant +// CHECK: %[[cres:.+]] = arith.constant 1.000000e+00 : bf16 +// CHECK: return %[[cres]] +func.func @truncFPToNearestAwayConstant() -> bf16 { + %cst = arith.constant 1.000000e+00 : f32 + %0 = arith.truncf %cst to_nearest_away : f32 to bf16 + return %0 : bf16 +} + // CHECK-LABEL: @truncFPVectorConstant // CHECK: %[[cres:.+]] = arith.constant dense<[0.000000e+00, 1.000000e+00]> : vector<2xbf16> // CHECK: return %[[cres]] diff --git a/mlir/test/Dialect/Arith/expand-ops.mlir b/mlir/test/Dialect/Arith/expand-ops.mlir index 91f652e5a270e3d3e772498dc9c10f8cf9abfed6..6bed93e4c969db400fb2d5722362f08d4a907286 100644 --- a/mlir/test/Dialect/Arith/expand-ops.mlir +++ b/mlir/test/Dialect/Arith/expand-ops.mlir @@ -66,23 +66,17 @@ func.func @ceildivi_index(%arg0: index, %arg1: index) -> (index) { func.func @floordivi(%arg0: i32, %arg1: i32) -> (i32) { %res = arith.floordivsi %arg0, %arg1 : i32 return %res : i32 -// CHECK: [[ONE:%.+]] = arith.constant 1 : i32 -// CHECK: [[ZERO:%.+]] = arith.constant 0 : i32 -// CHECK: [[MIN1:%.+]] = arith.constant -1 : i32 -// CHECK: [[CMP1:%.+]] = arith.cmpi slt, [[ARG1]], [[ZERO]] : i32 -// CHECK: [[X:%.+]] = arith.select [[CMP1]], [[ONE]], [[MIN1]] : i32 -// CHECK: [[TRUE1:%.+]] = arith.subi [[X]], [[ARG0]] : i32 -// CHECK: [[TRUE2:%.+]] = arith.divsi [[TRUE1]], [[ARG1]] : i32 -// CHECK: [[TRUE3:%.+]] = arith.subi [[MIN1]], [[TRUE2]] : i32 -// CHECK: [[FALSE:%.+]] = arith.divsi [[ARG0]], [[ARG1]] : i32 -// CHECK: [[NNEG:%.+]] = arith.cmpi slt, [[ARG0]], [[ZERO]] : i32 -// CHECK: [[NPOS:%.+]] = arith.cmpi sgt, [[ARG0]], [[ZERO]] : i32 -// CHECK: [[MNEG:%.+]] = arith.cmpi slt, [[ARG1]], [[ZERO]] : i32 -// CHECK: [[MPOS:%.+]] = arith.cmpi sgt, [[ARG1]], [[ZERO]] : i32 -// CHECK: [[TERM1:%.+]] = arith.andi [[NNEG]], [[MPOS]] : i1 -// CHECK: [[TERM2:%.+]] = arith.andi [[NPOS]], [[MNEG]] : i1 -// CHECK: [[CMP2:%.+]] = arith.ori [[TERM1]], [[TERM2]] : i1 -// CHECK: [[RES:%.+]] = arith.select [[CMP2]], [[TRUE3]], [[FALSE]] : i32 +// CHECK: %[[QUOTIENT:.*]] = arith.divsi %arg0, %arg1 : i32 +// CHECK: %[[PRODUCT:.*]] = arith.muli %[[QUOTIENT]], %arg1 : i32 +// CHECK: %[[NOT_EQ_PRODUCT:.*]] = arith.cmpi ne, %arg0, %[[PRODUCT]] : i32 +// CHECK-DAG: %[[ZERO:.*]] = arith.constant 0 : i32 +// CHECK: %[[NEG_DIVISOR:.*]] = arith.cmpi slt, %arg0, %[[ZERO]] : i32 +// CHECK: %[[NEG_DIVIDEND:.*]] = arith.cmpi slt, %arg1, %[[ZERO]] : i32 +// CHECK: %[[OPPOSITE_SIGN:.*]] = arith.cmpi ne, %[[NEG_DIVISOR]], %[[NEG_DIVIDEND]] : i1 +// CHECK: %[[CONDITION:.*]] = arith.andi %[[NOT_EQ_PRODUCT]], %[[OPPOSITE_SIGN]] : i1 +// CHECK-DAG: %[[NEG_ONE:.*]] = arith.constant -1 : i32 +// CHECK: %[[MINUS_ONE:.*]] = arith.addi %[[QUOTIENT]], %[[NEG_ONE]] : i32 +// CHECK: %[[RES:.*]] = arith.select %[[CONDITION]], %[[MINUS_ONE]], %[[QUOTIENT]] : i32 } // ----- @@ -93,23 +87,17 @@ func.func @floordivi(%arg0: i32, %arg1: i32) -> (i32) { func.func @floordivi_index(%arg0: index, %arg1: index) -> (index) { %res = arith.floordivsi %arg0, %arg1 : index return %res : index -// CHECK: [[ONE:%.+]] = arith.constant 1 : index -// CHECK: [[ZERO:%.+]] = arith.constant 0 : index -// CHECK: [[MIN1:%.+]] = arith.constant -1 : index -// CHECK: [[CMP1:%.+]] = arith.cmpi slt, [[ARG1]], [[ZERO]] : index -// CHECK: [[X:%.+]] = arith.select [[CMP1]], [[ONE]], [[MIN1]] : index -// CHECK: [[TRUE1:%.+]] = arith.subi [[X]], [[ARG0]] : index -// CHECK: [[TRUE2:%.+]] = arith.divsi [[TRUE1]], [[ARG1]] : index -// CHECK: [[TRUE3:%.+]] = arith.subi [[MIN1]], [[TRUE2]] : index -// CHECK: [[FALSE:%.+]] = arith.divsi [[ARG0]], [[ARG1]] : index -// CHECK: [[NNEG:%.+]] = arith.cmpi slt, [[ARG0]], [[ZERO]] : index -// CHECK: [[NPOS:%.+]] = arith.cmpi sgt, [[ARG0]], [[ZERO]] : index -// CHECK: [[MNEG:%.+]] = arith.cmpi slt, [[ARG1]], [[ZERO]] : index -// CHECK: [[MPOS:%.+]] = arith.cmpi sgt, [[ARG1]], [[ZERO]] : index -// CHECK: [[TERM1:%.+]] = arith.andi [[NNEG]], [[MPOS]] : i1 -// CHECK: [[TERM2:%.+]] = arith.andi [[NPOS]], [[MNEG]] : i1 -// CHECK: [[CMP2:%.+]] = arith.ori [[TERM1]], [[TERM2]] : i1 -// CHECK: [[RES:%.+]] = arith.select [[CMP2]], [[TRUE3]], [[FALSE]] : index +// CHECK: %[[QUOTIENT:.*]] = arith.divsi %arg0, %arg1 : index +// CHECK: %[[PRODUCT:.*]] = arith.muli %[[QUOTIENT]], %arg1 : index +// CHECK: %[[NOT_EQ_PRODUCT:.*]] = arith.cmpi ne, %arg0, %[[PRODUCT]] : index +// CHECK-DAG: %[[ZERO:.*]] = arith.constant 0 : index +// CHECK: %[[NEG_DIVISOR:.*]] = arith.cmpi slt, %arg0, %[[ZERO]] : index +// CHECK: %[[NEG_DIVIDEND:.*]] = arith.cmpi slt, %arg1, %[[ZERO]] : index +// CHECK: %[[OPPOSITE_SIGN:.*]] = arith.cmpi ne, %[[NEG_DIVISOR]], %[[NEG_DIVIDEND]] : i1 +// CHECK: %[[CONDITION:.*]] = arith.andi %[[NOT_EQ_PRODUCT]], %[[OPPOSITE_SIGN]] : i1 +// CHECK: %[[NEG_ONE:.*]] = arith.constant -1 : index +// CHECK-DAG: %[[MINUS_ONE:.*]] = arith.addi %[[QUOTIENT]], %[[NEG_ONE]] : index +// CHECK: %[[RES:.*]] = arith.select %[[CONDITION]], %[[MINUS_ONE]], %[[QUOTIENT]] : index } // ----- @@ -121,23 +109,17 @@ func.func @floordivi_index(%arg0: index, %arg1: index) -> (index) { func.func @floordivi_vec(%arg0: vector<4xi32>, %arg1: vector<4xi32>) -> (vector<4xi32>) { %res = arith.floordivsi %arg0, %arg1 : vector<4xi32> return %res : vector<4xi32> -// CHECK: %[[VAL_2:.*]] = arith.constant dense<1> : vector<4xi32> -// CHECK: %[[VAL_3:.*]] = arith.constant dense<0> : vector<4xi32> -// CHECK: %[[VAL_4:.*]] = arith.constant dense<-1> : vector<4xi32> -// CHECK: %[[VAL_5:.*]] = arith.cmpi slt, %[[VAL_1]], %[[VAL_3]] : vector<4xi32> -// CHECK: %[[VAL_6:.*]] = arith.select %[[VAL_5]], %[[VAL_2]], %[[VAL_4]] : vector<4xi1>, vector<4xi32> -// CHECK: %[[VAL_7:.*]] = arith.subi %[[VAL_6]], %[[VAL_0]] : vector<4xi32> -// CHECK: %[[VAL_8:.*]] = arith.divsi %[[VAL_7]], %[[VAL_1]] : vector<4xi32> -// CHECK: %[[VAL_9:.*]] = arith.subi %[[VAL_4]], %[[VAL_8]] : vector<4xi32> -// CHECK: %[[VAL_10:.*]] = arith.divsi %[[VAL_0]], %[[VAL_1]] : vector<4xi32> -// CHECK: %[[VAL_11:.*]] = arith.cmpi slt, %[[VAL_0]], %[[VAL_3]] : vector<4xi32> -// CHECK: %[[VAL_12:.*]] = arith.cmpi sgt, %[[VAL_0]], %[[VAL_3]] : vector<4xi32> -// CHECK: %[[VAL_13:.*]] = arith.cmpi slt, %[[VAL_1]], %[[VAL_3]] : vector<4xi32> -// CHECK: %[[VAL_14:.*]] = arith.cmpi sgt, %[[VAL_1]], %[[VAL_3]] : vector<4xi32> -// CHECK: %[[VAL_15:.*]] = arith.andi %[[VAL_11]], %[[VAL_14]] : vector<4xi1> -// CHECK: %[[VAL_16:.*]] = arith.andi %[[VAL_12]], %[[VAL_13]] : vector<4xi1> -// CHECK: %[[VAL_17:.*]] = arith.ori %[[VAL_15]], %[[VAL_16]] : vector<4xi1> -// CHECK: %[[VAL_18:.*]] = arith.select %[[VAL_17]], %[[VAL_9]], %[[VAL_10]] : vector<4xi1>, vector<4xi32> +// CHECK: %[[QUOTIENT:.*]] = arith.divsi %arg0, %arg1 : vector<4xi32> +// CHECK: %[[PRODUCT:.*]] = arith.muli %[[QUOTIENT]], %arg1 : vector<4xi32> +// CHECK: %[[NOT_EQ_PRODUCT:.*]] = arith.cmpi ne, %arg0, %[[PRODUCT]] : vector<4xi32> +// CHECK-DAG: %[[ZERO:.*]] = arith.constant dense<0> : vector<4xi32> +// CHECK: %[[NEG_DIVISOR:.*]] = arith.cmpi slt, %arg0, %[[ZERO]] : vector<4xi32> +// CHECK: %[[NEG_DIVIDEND:.*]] = arith.cmpi slt, %arg1, %[[ZERO]] : vector<4xi32> +// CHECK: %[[OPPOSITE_SIGN:.*]] = arith.cmpi ne, %[[NEG_DIVISOR]], %[[NEG_DIVIDEND]] : vector<4xi1> +// CHECK: %[[CONDITION:.*]] = arith.andi %[[NOT_EQ_PRODUCT]], %[[OPPOSITE_SIGN]] : vector<4xi1> +// CHECK-DAG: %[[NEG_ONE:.*]] = arith.constant dense<-1> : vector<4xi32> +// CHECK: %[[MINUS_ONE:.*]] = arith.addi %[[QUOTIENT]], %[[NEG_ONE]] : vector<4xi32> +// CHECK: %[[RES:.*]] = arith.select %[[CONDITION]], %[[MINUS_ONE]], %[[QUOTIENT]] : vector<4xi1>, vector<4xi32> } // ----- diff --git a/mlir/test/Dialect/Arith/one-shot-bufferize.mlir b/mlir/test/Dialect/Arith/one-shot-bufferize.mlir index 174bf2fc8e4bc75bc39128b75be392a816f67e43..f6bdca7f4d9e56173729458992a60b06acdea922 100644 --- a/mlir/test/Dialect/Arith/one-shot-bufferize.mlir +++ b/mlir/test/Dialect/Arith/one-shot-bufferize.mlir @@ -1,9 +1,9 @@ // RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries" -split-input-file | FileCheck %s // Run fuzzer with different seeds. -// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-fuzzer-seed=23 bufferize-function-boundaries" -split-input-file -o /dev/null -// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-fuzzer-seed=59 bufferize-function-boundaries" -split-input-file -o /dev/null -// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-fuzzer-seed=91 bufferize-function-boundaries" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=23 bufferize-function-boundaries" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=59 bufferize-function-boundaries" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=91 bufferize-function-boundaries" -split-input-file -o /dev/null // Test bufferization using memref types that have no layout map. // RUN: mlir-opt %s -one-shot-bufferize="unknown-type-conversion=identity-layout-map function-boundary-type-conversion=identity-layout-map bufferize-function-boundaries" -split-input-file -o /dev/null diff --git a/mlir/test/Dialect/Arith/ops.mlir b/mlir/test/Dialect/Arith/ops.mlir index e499573e324b5fca1a23e7f87ffb1e5ba51610dd..f684e02344a517e28e7195e84aa3d81bf0816410 100644 --- a/mlir/test/Dialect/Arith/ops.mlir +++ b/mlir/test/Dialect/Arith/ops.mlir @@ -703,6 +703,16 @@ func.func @test_truncf_scalable_vector(%arg0 : vector<[8]xf32>) -> vector<[8]xbf return %0 : vector<[8]xbf16> } +// CHECK-LABEL: test_truncf_rounding_mode +func.func @test_truncf_rounding_mode(%arg0 : f64) -> (f32, f32, f32, f32, f32) { + %0 = arith.truncf %arg0 to_nearest_even : f64 to f32 + %1 = arith.truncf %arg0 downward : f64 to f32 + %2 = arith.truncf %arg0 upward : f64 to f32 + %3 = arith.truncf %arg0 toward_zero : f64 to f32 + %4 = arith.truncf %arg0 to_nearest_away : f64 to f32 + return %0, %1, %2, %3, %4 : f32, f32, f32, f32, f32 +} + // CHECK-LABEL: test_uitofp func.func @test_uitofp(%arg0 : i32) -> f32 { %0 = arith.uitofp %arg0 : i32 to f32 diff --git a/mlir/test/Dialect/ArmNeon/lower-to-arm-neon.mlir b/mlir/test/Dialect/ArmNeon/lower-to-arm-neon.mlir index cba7b00ba77a82082ccffebf8a175488f5679b07..e2be87453bf6f256ff5a14d6dbfa3c9af73aa1b3 100644 --- a/mlir/test/Dialect/ArmNeon/lower-to-arm-neon.mlir +++ b/mlir/test/Dialect/ArmNeon/lower-to-arm-neon.mlir @@ -40,3 +40,97 @@ func.func @test_lower_vector_arm_neon_without_extsi(%lhs: vector<2x8xi32>, %rhs: %res = vector.contract {indexing_maps = [affine_map<(d0, d1, d2) -> (d0, d2)>, affine_map<(d0, d1, d2) -> (d1, d2)>, affine_map<(d0, d1, d2) -> (d0, d1)>], iterator_types = ["parallel", "parallel", "reduction"], kind = #vector.kind<add>} %lhs, %rhs, %acc : vector<2x8xi32>, vector<2x8xi32> into vector<2x2xi32> return %res : vector<2x2xi32> } + +// ----- + +// CHECK-LABEL: test_lower_vector_arm_neon_unroll +// CHECK-SAME: %[[VAL_0:.*]]: vector<4x8xi8>, %[[VAL_1:.*]]: vector<4x8xi8>, %[[VAL_2:.*]]: vector<4x4xi32> +// CHECK-DAG: %[[VAL_3:.*]] = arith.constant dense<0> : vector<4x4xi32> +// CHECK-DAG: %[[VAL_4:.*]] = vector.extract_strided_slice %[[VAL_0]] {offsets = [0, 0], sizes = [2, 8], strides = [1, 1]} : vector<4x8xi8> to vector<2x8xi8> +// CHECK-DAG: %[[VAL_5:.*]] = vector.extract_strided_slice %[[VAL_1]] {offsets = [0, 0], sizes = [2, 8], strides = [1, 1]} : vector<4x8xi8> to vector<2x8xi8> +// CHECK-DAG: %[[VAL_6:.*]] = vector.extract_strided_slice %[[VAL_2]] {offsets = [0, 0], sizes = [2, 2], strides = [1, 1]} : vector<4x4xi32> to vector<2x2xi32> +// CHECK-DAG: %[[VAL_7:.*]] = vector.shape_cast %[[VAL_4]] : vector<2x8xi8> to vector<16xi8> +// CHECK-DAG: %[[VAL_8:.*]] = vector.shape_cast %[[VAL_5]] : vector<2x8xi8> to vector<16xi8> +// CHECK-DAG: %[[VAL_9:.*]] = vector.shape_cast %[[VAL_6]] : vector<2x2xi32> to vector<4xi32> +// CHECK-DAG: %[[VAL_10:.*]] = arm_neon.intr.smmla %[[VAL_9]], %[[VAL_7]], %[[VAL_8]] : vector<16xi8> to vector<4xi32> +// CHECK-DAG: %[[VAL_11:.*]] = vector.shape_cast %[[VAL_10]] : vector<4xi32> to vector<2x2xi32> +// CHECK-DAG: %[[VAL_12:.*]] = vector.insert_strided_slice %[[VAL_11]], %[[VAL_3]] {offsets = [0, 0], strides = [1, 1]} : vector<2x2xi32> into vector<4x4xi32> +// CHECK-DAG: %[[VAL_13:.*]] = vector.extract_strided_slice %[[VAL_0]] {offsets = [0, 0], sizes = [2, 8], strides = [1, 1]} : vector<4x8xi8> to vector<2x8xi8> +// CHECK-DAG: %[[VAL_14:.*]] = vector.extract_strided_slice %[[VAL_1]] {offsets = [2, 0], sizes = [2, 8], strides = [1, 1]} : vector<4x8xi8> to vector<2x8xi8> +// CHECK-DAG: %[[VAL_15:.*]] = vector.extract_strided_slice %[[VAL_2]] {offsets = [0, 2], sizes = [2, 2], strides = [1, 1]} : vector<4x4xi32> to vector<2x2xi32> +// CHECK-DAG: %[[VAL_16:.*]] = vector.shape_cast %[[VAL_13]] : vector<2x8xi8> to vector<16xi8> +// CHECK-DAG: %[[VAL_17:.*]] = vector.shape_cast %[[VAL_14]] : vector<2x8xi8> to vector<16xi8> +// CHECK-DAG: %[[VAL_18:.*]] = vector.shape_cast %[[VAL_15]] : vector<2x2xi32> to vector<4xi32> +// CHECK-DAG: %[[VAL_19:.*]] = arm_neon.intr.smmla %[[VAL_18]], %[[VAL_16]], %[[VAL_17]] : vector<16xi8> to vector<4xi32> +// CHECK-DAG: %[[VAL_20:.*]] = vector.shape_cast %[[VAL_19]] : vector<4xi32> to vector<2x2xi32> +// CHECK-DAG: %[[VAL_21:.*]] = vector.insert_strided_slice %[[VAL_20]], %[[VAL_12]] {offsets = [0, 2], strides = [1, 1]} : vector<2x2xi32> into vector<4x4xi32> +// CHECK-DAG: %[[VAL_22:.*]] = vector.extract_strided_slice %[[VAL_0]] {offsets = [2, 0], sizes = [2, 8], strides = [1, 1]} : vector<4x8xi8> to vector<2x8xi8> +// CHECK-DAG: %[[VAL_23:.*]] = vector.extract_strided_slice %[[VAL_1]] {offsets = [0, 0], sizes = [2, 8], strides = [1, 1]} : vector<4x8xi8> to vector<2x8xi8> +// CHECK-DAG: %[[VAL_24:.*]] = vector.extract_strided_slice %[[VAL_2]] {offsets = [2, 0], sizes = [2, 2], strides = [1, 1]} : vector<4x4xi32> to vector<2x2xi32> +// CHECK-DAG: %[[VAL_25:.*]] = vector.shape_cast %[[VAL_22]] : vector<2x8xi8> to vector<16xi8> +// CHECK-DAG: %[[VAL_26:.*]] = vector.shape_cast %[[VAL_23]] : vector<2x8xi8> to vector<16xi8> +// CHECK-DAG: %[[VAL_27:.*]] = vector.shape_cast %[[VAL_24]] : vector<2x2xi32> to vector<4xi32> +// CHECK-DAG: %[[VAL_28:.*]] = arm_neon.intr.smmla %[[VAL_27]], %[[VAL_25]], %[[VAL_26]] : vector<16xi8> to vector<4xi32> +// CHECK-DAG: %[[VAL_29:.*]] = vector.shape_cast %[[VAL_28]] : vector<4xi32> to vector<2x2xi32> +// CHECK-DAG: %[[VAL_30:.*]] = vector.insert_strided_slice %[[VAL_29]], %[[VAL_21]] {offsets = [2, 0], strides = [1, 1]} : vector<2x2xi32> into vector<4x4xi32> +// CHECK-DAG: %[[VAL_31:.*]] = vector.extract_strided_slice %[[VAL_0]] {offsets = [2, 0], sizes = [2, 8], strides = [1, 1]} : vector<4x8xi8> to vector<2x8xi8> +// CHECK-DAG: %[[VAL_32:.*]] = vector.extract_strided_slice %[[VAL_1]] {offsets = [2, 0], sizes = [2, 8], strides = [1, 1]} : vector<4x8xi8> to vector<2x8xi8> +// CHECK-DAG: %[[VAL_33:.*]] = vector.extract_strided_slice %[[VAL_2]] {offsets = [2, 2], sizes = [2, 2], strides = [1, 1]} : vector<4x4xi32> to vector<2x2xi32> +// CHECK-DAG: %[[VAL_34:.*]] = vector.shape_cast %[[VAL_31]] : vector<2x8xi8> to vector<16xi8> +// CHECK-DAG: %[[VAL_35:.*]] = vector.shape_cast %[[VAL_32]] : vector<2x8xi8> to vector<16xi8> +// CHECK-DAG: %[[VAL_36:.*]] = vector.shape_cast %[[VAL_33]] : vector<2x2xi32> to vector<4xi32> +// CHECK-DAG: %[[VAL_37:.*]] = arm_neon.intr.smmla %[[VAL_36]], %[[VAL_34]], %[[VAL_35]] : vector<16xi8> to vector<4xi32> +// CHECK-DAG: %[[VAL_38:.*]] = vector.shape_cast %[[VAL_37]] : vector<4xi32> to vector<2x2xi32> +// CHECK-DAG: %[[VAL_39:.*]] = vector.insert_strided_slice %[[VAL_38]], %[[VAL_30]] {offsets = [2, 2], strides = [1, 1]} : vector<2x2xi32> into vector<4x4xi32> +// CHECK-DAG: return %[[VAL_39]] : vector<4x4xi32> +// CHECK-DAG: } +func.func @test_lower_vector_arm_neon_unroll(%lhs: vector<4x8xi8>, %rhs: vector<4x8xi8>, %acc : vector<4x4xi32>) -> vector<4x4xi32> { + %lhs_extsi = arith.extsi %lhs : vector<4x8xi8> to vector<4x8xi32> + %rhs_extsi = arith.extsi %rhs : vector<4x8xi8> to vector<4x8xi32> + %res = vector.contract {indexing_maps = [affine_map<(d0, d1, d2) -> (d0, d2)>, affine_map<(d0, d1, d2) -> (d1, d2)>, affine_map<(d0, d1, d2) -> (d0, d1)>], iterator_types = ["parallel", "parallel", "reduction"], kind = #vector.kind<add>} %lhs_extsi, %rhs_extsi, %acc : vector<4x8xi32>, vector<4x8xi32> into vector<4x4xi32> + return %res : vector<4x4xi32> +} + +// ----- + +// CHECK-LABEL: func.func @test_lower_vector_arm_neon_mixed_unroll( +// CHECK-SAME: %[[VAL_0:.*]]: vector<4x8xi8>, +// CHECK-SAME: %[[VAL_1:.*]]: vector<2x8xi4>, +// CHECK-SAME: %[[VAL_2:.*]]: vector<4x2xi32>) -> vector<4x2xi32> { +// CHECK-DAG: %[[VAL_3:.*]] = arith.constant dense<0> : vector<4x2xi32> +// CHECK-DAG: %[[VAL_4:.*]] = arith.extsi %[[VAL_1]] : vector<2x8xi4> to vector<2x8xi8> +// CHECK-DAG: %[[VAL_5:.*]] = vector.extract_strided_slice %[[VAL_0]] {offsets = [0, 0], sizes = [2, 8], strides = [1, 1]} : vector<4x8xi8> to vector<2x8xi8> +// CHECK-DAG: %[[VAL_6:.*]] = vector.extract_strided_slice %[[VAL_2]] {offsets = [0, 0], sizes = [2, 2], strides = [1, 1]} : vector<4x2xi32> to vector<2x2xi32> +// CHECK-DAG: %[[VAL_7:.*]] = vector.shape_cast %[[VAL_5]] : vector<2x8xi8> to vector<16xi8> +// CHECK-DAG: %[[VAL_8:.*]] = vector.shape_cast %[[VAL_4]] : vector<2x8xi8> to vector<16xi8> +// CHECK-DAG: %[[VAL_9:.*]] = vector.shape_cast %[[VAL_6]] : vector<2x2xi32> to vector<4xi32> +// CHECK-DAG: %[[VAL_10:.*]] = arm_neon.intr.smmla %[[VAL_9]], %[[VAL_7]], %[[VAL_8]] : vector<16xi8> to vector<4xi32> +// CHECK-DAG: %[[VAL_11:.*]] = vector.shape_cast %[[VAL_10]] : vector<4xi32> to vector<2x2xi32> +// CHECK-DAG: %[[VAL_12:.*]] = vector.insert_strided_slice %[[VAL_11]], %[[VAL_3]] {offsets = [0, 0], strides = [1, 1]} : vector<2x2xi32> into vector<4x2xi32> +// CHECK-DAG: %[[VAL_13:.*]] = vector.extract_strided_slice %[[VAL_0]] {offsets = [2, 0], sizes = [2, 8], strides = [1, 1]} : vector<4x8xi8> to vector<2x8xi8> +// CHECK-DAG: %[[VAL_14:.*]] = vector.extract_strided_slice %[[VAL_2]] {offsets = [2, 0], sizes = [2, 2], strides = [1, 1]} : vector<4x2xi32> to vector<2x2xi32> +// CHECK-DAG: %[[VAL_15:.*]] = vector.shape_cast %[[VAL_13]] : vector<2x8xi8> to vector<16xi8> +// CHECK-DAG: %[[VAL_16:.*]] = vector.shape_cast %[[VAL_4]] : vector<2x8xi8> to vector<16xi8> +// CHECK-DAG: %[[VAL_17:.*]] = vector.shape_cast %[[VAL_14]] : vector<2x2xi32> to vector<4xi32> +// CHECK-DAG: %[[VAL_18:.*]] = arm_neon.intr.smmla %[[VAL_17]], %[[VAL_15]], %[[VAL_16]] : vector<16xi8> to vector<4xi32> +// CHECK-DAG: %[[VAL_19:.*]] = vector.shape_cast %[[VAL_18]] : vector<4xi32> to vector<2x2xi32> +// CHECK-DAG: %[[VAL_20:.*]] = vector.insert_strided_slice %[[VAL_19]], %[[VAL_12]] {offsets = [2, 0], strides = [1, 1]} : vector<2x2xi32> into vector<4x2xi32> +// CHECK-DAG: return %[[VAL_20]] : vector<4x2xi32> +// CHECK-DAG: } +func.func @test_lower_vector_arm_neon_mixed_unroll(%lhs: vector<4x8xi8>, %rhs: vector<2x8xi4>, %acc : vector<4x2xi32>) -> vector<4x2xi32> { + %lhs_extsi = arith.extsi %lhs : vector<4x8xi8> to vector<4x8xi32> + %rhs_extsi = arith.extsi %rhs : vector<2x8xi4> to vector<2x8xi32> + %res = vector.contract {indexing_maps = [affine_map<(d0, d1, d2) -> (d0, d2)>, affine_map<(d0, d1, d2) -> (d1, d2)>, affine_map<(d0, d1, d2) -> (d0, d1)>], iterator_types = ["parallel", "parallel", "reduction"], kind = #vector.kind<add>} %lhs_extsi, %rhs_extsi, %acc : vector<4x8xi32>, vector<2x8xi32> into vector<4x2xi32> + return %res : vector<4x2xi32> +} + +// ----- + +// CHECK-LABEL: func.func @test_lower_vector_arm_neon_unroll_incompatible_shape( +// CHECK-DAG: %[[result:.*]] = vector.contract +func.func @test_lower_vector_arm_neon_unroll_incompatible_shape(%lhs: vector<4x12xi8>, %rhs: vector<4x12xi8>, %acc : vector<4x4xi32>) -> vector<4x4xi32> { + %lhs_extsi = arith.extsi %lhs : vector<4x12xi8> to vector<4x12xi32> + %rhs_extsi = arith.extsi %rhs : vector<4x12xi8> to vector<4x12xi32> + %res = vector.contract {indexing_maps = [affine_map<(d0, d1, d2) -> (d0, d2)>, affine_map<(d0, d1, d2) -> (d1, d2)>, affine_map<(d0, d1, d2) -> (d0, d1)>], iterator_types = ["parallel", "parallel", "reduction"], kind = #vector.kind<add>} %lhs_extsi, %rhs_extsi, %acc : vector<4x12xi32>, vector<4x12xi32> into vector<4x4xi32> + return %res : vector<4x4xi32> +} diff --git a/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-loops.mlir b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-loops.mlir new file mode 100644 index 0000000000000000000000000000000000000000..53b28c3aab6fd8814236deaebd178d54bc61c2f3 --- /dev/null +++ b/mlir/test/Dialect/Bufferization/Transforms/OwnershipBasedBufferDeallocation/dealloc-loops.mlir @@ -0,0 +1,86 @@ +// RUN: mlir-opt %s -expand-realloc="emit-deallocs=false" -ownership-based-buffer-deallocation="private-function-dynamic-ownership=true" -canonicalize -buffer-deallocation-simplification | FileCheck %s + +// A function that reallocates two buffer inside of a loop. The simplification +// pass should be able to figure out that the iter_args are always originating +// from different allocations. IR like this one appears in the sparse compiler. + +// CHECK-LABEL: func private @loop_with_realloc( +func.func private @loop_with_realloc(%lb: index, %ub: index, %step: index, %c: i1, %s1: index, %s2: index) -> (memref<?xf32>, memref<?xf32>) { + // CHECK-DAG: %[[false:.*]] = arith.constant false + // CHECK-DAG: %[[true:.*]] = arith.constant true + + // CHECK: %[[m0:.*]] = memref.alloc + %m0 = memref.alloc(%s1) : memref<?xf32> + // CHECK: %[[m1:.*]] = memref.alloc + %m1 = memref.alloc(%s1) : memref<?xf32> + + // CHECK: %[[r:.*]]:4 = scf.for {{.*}} iter_args(%[[arg0:.*]] = %[[m0]], %[[arg1:.*]] = %[[m1]], %[[o0:.*]] = %[[false]], %[[o1:.*]] = %[[false]]) + %r0, %r1 = scf.for %iv = %lb to %ub step %step iter_args(%arg0 = %m0, %arg1 = %m1) -> (memref<?xf32>, memref<?xf32>) { + // CHECK: %[[m2:.*]]:2 = scf.if %{{.*}} -> (memref<?xf32>, i1) { + // CHECK-NEXT: memref.alloc + // CHECK-NEXT: memref.subview + // CHECK-NEXT: memref.copy + // CHECK-NEXT: scf.yield %{{.*}}, %[[true]] + // CHECK-NEXT: } else { + // CHECK-NEXT: memref.reinterpret_cast + // CHECK-NEXT: scf.yield %{{.*}}, %[[false]] + // CHECK-NEXT: } + %m2 = memref.realloc %arg0(%s2) : memref<?xf32> to memref<?xf32> + // CHECK: %[[m3:.*]]:2 = scf.if %{{.*}} -> (memref<?xf32>, i1) { + // CHECK-NEXT: memref.alloc + // CHECK-NEXT: memref.subview + // CHECK-NEXT: memref.copy + // CHECK-NEXT: scf.yield %{{.*}}, %[[true]] + // CHECK-NEXT: } else { + // CHECK-NEXT: memref.reinterpret_cast + // CHECK-NEXT: scf.yield %{{.*}}, %[[false]] + // CHECK-NEXT: } + %m3 = memref.realloc %arg1(%s2) : memref<?xf32> to memref<?xf32> + + // CHECK: %[[base0:.*]], %{{.*}}, %{{.*}}, %{{.*}} = memref.extract_strided_metadata %[[arg0]] + // CHECK: %[[base1:.*]], %{{.*}}, %{{.*}}, %{{.*}} = memref.extract_strided_metadata %[[arg1]] + // CHECK: %[[d0:.*]] = bufferization.dealloc (%[[base0]] : memref<f32>) if (%[[o0]]) retain (%[[m2]]#0 : memref<?xf32>) + // CHECK: %[[d1:.*]] = bufferization.dealloc (%[[base1]] : memref<f32>) if (%[[o1]]) retain (%[[m3]]#0 : memref<?xf32>) + // CHECK-DAG: %[[o2:.*]] = arith.ori %[[d0]], %[[m2]]#1 + // CHECK-DAG: %[[o3:.*]] = arith.ori %[[d1]], %[[m3]]#1 + // CHECK: scf.yield %[[m2]]#0, %[[m3]]#0, %[[o2]], %[[o3]] + scf.yield %m2, %m3 : memref<?xf32>, memref<?xf32> + } + + // CHECK: %[[d2:.*]] = bufferization.dealloc (%[[m0]] : memref<?xf32>) if (%[[true]]) retain (%[[r]]#0 : memref<?xf32>) + // CHECK: %[[d3:.*]] = bufferization.dealloc (%[[m1]] : memref<?xf32>) if (%[[true]]) retain (%[[r]]#1 : memref<?xf32>) + // CHECK-DAG: %[[or0:.*]] = arith.ori %[[d2]], %[[r]]#2 + // CHECK-DAG: %[[or1:.*]] = arith.ori %[[d3]], %[[r]]#3 + // CHECK: return %[[r]]#0, %[[r]]#1, %[[or0]], %[[or1]] + return %r0, %r1 : memref<?xf32>, memref<?xf32> +} + +// ----- + +// The yielded values of the loop are swapped. Therefore, the +// bufferization.dealloc before the func.return can now longer be split, +// because %r0 could originate from either %m0 and %m1 (same for %r1). + +// CHECK-LABEL: func private @swapping_loop_with_realloc( +func.func private @swapping_loop_with_realloc(%lb: index, %ub: index, %step: index, %c: i1, %s1: index, %s2: index) -> (memref<?xf32>, memref<?xf32>) { + // CHECK-DAG: %[[false:.*]] = arith.constant false + // CHECK-DAG: %[[true:.*]] = arith.constant true + + // CHECK: %[[m0:.*]] = memref.alloc + %m0 = memref.alloc(%s1) : memref<?xf32> + // CHECK: %[[m1:.*]] = memref.alloc + %m1 = memref.alloc(%s1) : memref<?xf32> + + // CHECK: %[[r:.*]]:4 = scf.for {{.*}} iter_args(%[[arg0:.*]] = %[[m0]], %[[arg1:.*]] = %[[m1]], %[[o0:.*]] = %[[false]], %[[o1:.*]] = %[[false]]) + %r0, %r1 = scf.for %iv = %lb to %ub step %step iter_args(%arg0 = %m0, %arg1 = %m1) -> (memref<?xf32>, memref<?xf32>) { + %m2 = memref.realloc %arg0(%s2) : memref<?xf32> to memref<?xf32> + %m3 = memref.realloc %arg1(%s2) : memref<?xf32> to memref<?xf32> + scf.yield %m3, %m2 : memref<?xf32>, memref<?xf32> + } + + // CHECK: %[[base0:.*]], %{{.*}}, %{{.*}}, %{{.*}} = memref.extract_strided_metadata %[[r]]#0 + // CHECK: %[[base1:.*]], %{{.*}}, %{{.*}}, %{{.*}} = memref.extract_strided_metadata %[[r]]#1 + // CHECK: %[[d:.*]]:2 = bufferization.dealloc (%[[m0]], %[[m1]], %[[base0]], %[[base1]] : {{.*}}) if (%[[true]], %[[true]], %[[r]]#2, %[[r]]#3) retain (%[[r]]#0, %[[r]]#1 : {{.*}}) + // CHECK: return %[[r]]#0, %[[r]]#1, %[[d]]#0, %[[d]]#1 + return %r0, %r1 : memref<?xf32>, memref<?xf32> +} diff --git a/mlir/test/Dialect/Bufferization/Transforms/buffer-deallocation-simplification.mlir b/mlir/test/Dialect/Bufferization/Transforms/buffer-deallocation-simplification.mlir index eee69acbe821b3703c04178097c956b77a423fba..b40a17cf800bf309d805bc4581e4e01327a84c56 100644 --- a/mlir/test/Dialect/Bufferization/Transforms/buffer-deallocation-simplification.mlir +++ b/mlir/test/Dialect/Bufferization/Transforms/buffer-deallocation-simplification.mlir @@ -92,15 +92,13 @@ func.func @dealloc_split_when_no_other_aliasing(%arg0: i1, %arg1: memref<2xi32>, // CHECK-NEXT: [[ALLOC0:%.+]] = memref.alloc( // CHECK-NEXT: [[ALLOC1:%.+]] = memref.alloc( // CHECK-NEXT: [[V0:%.+]] = arith.select{{.*}}[[ALLOC0]], [[ALLOC1]] : -// COM: there is only one value in the retained list because the -// COM: RemoveRetainedMemrefsGuaranteedToNotAlias pattern also applies here and -// COM: removes %arg1 from the list. In the second dealloc, this does not apply -// COM: because function arguments are assumed potentially alias (even if the -// COM: types don't exactly match). +// COM: there is only one value in the retained lists because the +// COM: RemoveRetainedMemrefsGuaranteedToNotAlias pattern also applies here: +// COM: - %alloc is guaranteed to not alias with %arg1. +// COM: - %arg2 is guaranteed to not alias with %0. // CHECK-NEXT: [[V1:%.+]] = bufferization.dealloc ([[ALLOC0]] : memref<2xi32>) if ([[ARG0]]) retain ([[V0]] : memref<2xi32>) -// CHECK-NEXT: [[V2:%.+]]:2 = bufferization.dealloc ([[ARG2]] : memref<2xi32>) if ([[ARG3]]) retain ([[ARG1]], [[V0]] : memref<2xi32>, memref<2xi32>) -// CHECK-NEXT: [[V3:%.+]] = arith.ori [[V1]], [[V2]]#1 -// CHECK-NEXT: return [[V2]]#0, [[V3]] : +// CHECK-NEXT: [[V2:%.+]] = bufferization.dealloc ([[ARG2]] : memref<2xi32>) if ([[ARG3]]) retain ([[ARG1]] : memref<2xi32>) +// CHECK-NEXT: return [[V2]], [[V1]] : // ----- diff --git a/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-allow-return-allocs.mlir b/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-allow-return-allocs.mlir index e4375950d3363774098631b77ce20af73e0040ad..8f0170b17381a4c6a766f61498085ecae7c20532 100644 --- a/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-allow-return-allocs.mlir +++ b/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-allow-return-allocs.mlir @@ -1,9 +1,9 @@ // RUN: mlir-opt %s -one-shot-bufferize="allow-unknown-ops" -canonicalize -split-input-file | FileCheck %s // Run fuzzer with different seeds. -// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-fuzzer-seed=23" -split-input-file -o /dev/null -// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-fuzzer-seed=59" -split-input-file -o /dev/null -// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-fuzzer-seed=91" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=23" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=59" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=91" -split-input-file -o /dev/null // CHECK-LABEL: func @buffer_not_deallocated( // CHECK-SAME: %[[t:.*]]: tensor<?xf32> diff --git a/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis-bottom-up-from-terminators.mlir b/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis-bottom-up-from-terminators.mlir new file mode 100644 index 0000000000000000000000000000000000000000..1b75edc4c157fc61d204656fd446cf36e7270044 --- /dev/null +++ b/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis-bottom-up-from-terminators.mlir @@ -0,0 +1,36 @@ +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-heuristic=bottom-up-from-terminators" -split-input-file | FileCheck %s + +// CHECK-LABEL: func @simple_test( +func.func @simple_test(%lb: index, %ub: index, %step: index, %f1: f32, %f2: f32) -> (tensor<5xf32>, tensor<5xf32>) { + %c0 = arith.constant 0 : index + %p = arith.constant 0.0 : f32 + + // Make sure that ops that feed into region terminators bufferize in-place + // (if possible). + // Note: This test case fails to bufferize with a "top-down" or "bottom-up" + // heuristic. + + %0 = tensor.empty() : tensor<5xf32> + %1 = scf.for %iv = %lb to %ub step %step iter_args(%t = %0) -> (tensor<5xf32>) { + // CHECK: linalg.fill {__inplace_operands_attr__ = ["none", "false"]} + %2 = linalg.fill ins(%f1 : f32) outs(%t : tensor<5xf32>) -> tensor<5xf32> + // CHECK: linalg.fill {__inplace_operands_attr__ = ["none", "true"]} + %3 = linalg.fill ins(%f2 : f32) outs(%t : tensor<5xf32>) -> tensor<5xf32> + %4 = vector.transfer_read %2[%c0], %p : tensor<5xf32>, vector<5xf32> + vector.print %4 : vector<5xf32> + scf.yield %3 : tensor<5xf32> + } + + %5 = tensor.empty() : tensor<5xf32> + %6 = scf.for %iv = %lb to %ub step %step iter_args(%t = %0) -> (tensor<5xf32>) { + // CHECK: linalg.fill {__inplace_operands_attr__ = ["none", "true"]} + %7 = linalg.fill ins(%f1 : f32) outs(%t : tensor<5xf32>) -> tensor<5xf32> + // CHECK: linalg.fill {__inplace_operands_attr__ = ["none", "false"]} + %8 = linalg.fill ins(%f2 : f32) outs(%t : tensor<5xf32>) -> tensor<5xf32> + %9 = vector.transfer_read %8[%c0], %p : tensor<5xf32>, vector<5xf32> + vector.print %9 : vector<5xf32> + scf.yield %7 : tensor<5xf32> + } + + return %1, %6 : tensor<5xf32>, tensor<5xf32> +} diff --git a/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-partial.mlir b/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-partial.mlir index 2c5f2083f58908336091f100bd5459d7c0fe8b95..9380c81ce235cdeca8dcd9ae916b5be6e9ebcf95 100644 --- a/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-partial.mlir +++ b/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-partial.mlir @@ -4,9 +4,9 @@ // RUN: mlir-opt %s -allow-unregistered-dialect -one-shot-bufferize="allow-unknown-ops unknown-type-conversion=identity-layout-map" -split-input-file | FileCheck %s --check-prefix=CHECK-NO-LAYOUT-MAP // Run fuzzer with different seeds. -// RUN: mlir-opt %s -allow-unregistered-dialect -one-shot-bufferize="test-analysis-only analysis-fuzzer-seed=23" -split-input-file -o /dev/null -// RUN: mlir-opt %s -allow-unregistered-dialect -one-shot-bufferize="test-analysis-only analysis-fuzzer-seed=59" -split-input-file -o /dev/null -// RUN: mlir-opt %s -allow-unregistered-dialect -one-shot-bufferize="test-analysis-only analysis-fuzzer-seed=91" -split-input-file -o /dev/null +// RUN: mlir-opt %s -allow-unregistered-dialect -one-shot-bufferize="test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=23" -split-input-file -o /dev/null +// RUN: mlir-opt %s -allow-unregistered-dialect -one-shot-bufferize="test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=59" -split-input-file -o /dev/null +// RUN: mlir-opt %s -allow-unregistered-dialect -one-shot-bufferize="test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=91" -split-input-file -o /dev/null // RUN: mlir-opt %s -allow-unregistered-dialect -one-shot-bufferize="dialect-filter=tensor,bufferization allow-unknown-ops" -canonicalize -split-input-file | FileCheck %s --check-prefix=CHECK-TENSOR // RUN: mlir-opt %s -allow-unregistered-dialect -one-shot-bufferize="dialect-filter=scf,bufferization allow-unknown-ops" -canonicalize -split-input-file | FileCheck %s --check-prefix=CHECK-SCF diff --git a/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize.mlir b/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize.mlir index 611b67e198c00006e66637a50d578f0fc56f4204..0ed3a9f077ce0e9304b786f7c3669d307eef1a38 100644 --- a/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize.mlir +++ b/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize.mlir @@ -1,9 +1,9 @@ // RUN: mlir-opt %s -one-shot-bufferize="allow-unknown-ops" -verify-diagnostics -split-input-file | FileCheck %s // Run fuzzer with different seeds. -// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-fuzzer-seed=23" -verify-diagnostics -split-input-file -o /dev/null -// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-fuzzer-seed=59" -verify-diagnostics -split-input-file -o /dev/null -// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-fuzzer-seed=91" -verify-diagnostics -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=23" -verify-diagnostics -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=59" -verify-diagnostics -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=91" -verify-diagnostics -split-input-file -o /dev/null // Run with top-down analysis. // RUN: mlir-opt %s -one-shot-bufferize="allow-unknown-ops analysis-heuristic=top-down" -verify-diagnostics -split-input-file | FileCheck %s --check-prefix=CHECK-TOP-DOWN-ANALYSIS diff --git a/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-allow-return-allocs.mlir b/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-allow-return-allocs.mlir index 9319ac61d928eb800b607e7da80b8a9578d5aabc..c58b153d438caf4e650255840c1ef2474bbbc708 100644 --- a/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-allow-return-allocs.mlir +++ b/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-allow-return-allocs.mlir @@ -2,9 +2,9 @@ // RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1 " -split-input-file | FileCheck %s --check-prefix=NO-DROP // Run fuzzer with different seeds. -// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1 test-analysis-only analysis-fuzzer-seed=23" -split-input-file -o /dev/null -// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1 test-analysis-only analysis-fuzzer-seed=59" -split-input-file -o /dev/null -// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1 test-analysis-only analysis-fuzzer-seed=91" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1 test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=23" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1 test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=59" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1 test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=91" -split-input-file -o /dev/null // Test bufferization using memref types that have no layout map. // RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1 unknown-type-conversion=identity-layout-map function-boundary-type-conversion=identity-layout-map" -split-input-file -o /dev/null diff --git a/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-analysis.mlir b/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-analysis.mlir index 6e7b113aa35c0b1bebce8867e078adefd4db8081..42d9cc00d3ff5ae198ca6b94e30913abc360a54f 100644 --- a/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-analysis.mlir +++ b/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize-analysis.mlir @@ -1,9 +1,14 @@ // RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries test-analysis-only" -split-input-file | FileCheck %s // Run fuzzer with different seeds. -// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries test-analysis-only analysis-fuzzer-seed=23" -split-input-file -o /dev/null -// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries test-analysis-only analysis-fuzzer-seed=59" -split-input-file -o /dev/null -// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries test-analysis-only analysis-fuzzer-seed=91" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=23" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=59" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=91" -split-input-file -o /dev/null + +// Try different heuristics. Not checking the result, just make sure that we do +// not crash. +// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries test-analysis-only analysis-heuristic=bottom-up-from-terminators" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries test-analysis-only analysis-heuristic=top-down" -split-input-file -o /dev/null // TODO: Extract op-specific test cases and move them to their respective // dialects. diff --git a/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir b/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir index 39f4835b28ffeb2183b0bbacbc917a7ea56d5d95..429c9e4dea9e93e77c8e47552a6fa5ca4e9f6067 100644 --- a/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir +++ b/mlir/test/Dialect/Bufferization/Transforms/one-shot-module-bufferize.mlir @@ -2,9 +2,9 @@ // RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1" -canonicalize -drop-equivalent-buffer-results -split-input-file | FileCheck %s // Run fuzzer with different seeds. -// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1 test-analysis-only analysis-fuzzer-seed=23" -split-input-file -o /dev/null -// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1 test-analysis-only analysis-fuzzer-seed=59" -split-input-file -o /dev/null -// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1 test-analysis-only analysis-fuzzer-seed=91" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1 test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=23" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1 test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=59" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1 test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=91" -split-input-file -o /dev/null // Test bufferization using memref types that have no layout map. // RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries=1 unknown-type-conversion=identity-layout-map function-boundary-type-conversion=identity-layout-map" -split-input-file | FileCheck %s --check-prefix=CHECK-NO-LAYOUT-MAP diff --git a/mlir/test/Dialect/Bufferization/invalid.mlir b/mlir/test/Dialect/Bufferization/invalid.mlir index 83f8ef78615432da1b48fdfb5c71349b7068019a..4ebdb0a8f0490e3a2944e8e7bcb1abcf978dabf9 100644 --- a/mlir/test/Dialect/Bufferization/invalid.mlir +++ b/mlir/test/Dialect/Bufferization/invalid.mlir @@ -26,29 +26,6 @@ func.func @alloc_tensor_copy_and_dims(%t: tensor<?xf32>, %sz: index) { // ----- -#DCSR = #sparse_tensor.encoding<{ map = (d0, d1) -> (d0 : compressed, d1 : compressed) }> - -func.func @sparse_alloc_direct_return() -> tensor<20x40xf32, #DCSR> { - // expected-error @+1{{sparse tensor allocation should not escape function}} - %0 = bufferization.alloc_tensor() : tensor<20x40xf32, #DCSR> - return %0 : tensor<20x40xf32, #DCSR> -} - -// ----- - -#DCSR = #sparse_tensor.encoding<{ map = (d0, d1) -> (d0 : compressed, d1 : compressed) }> - -func.func private @foo(tensor<20x40xf32, #DCSR>) -> () - -func.func @sparse_alloc_call() { - // expected-error @+1{{sparse tensor allocation should not escape function}} - %0 = bufferization.alloc_tensor() : tensor<20x40xf32, #DCSR> - call @foo(%0) : (tensor<20x40xf32, #DCSR>) -> () - return -} - -// ----- - // expected-error @+1{{invalid value for 'bufferization.access'}} func.func private @invalid_buffer_access_type(tensor<*xf32> {bufferization.access = "foo"}) diff --git a/mlir/test/Dialect/Complex/canonicalize.mlir b/mlir/test/Dialect/Complex/canonicalize.mlir index 64c3f313dda959c9f7496490d3e89ca6f867f828..16fa0fdf56a1b402ba501843220a6d88055fe351 100644 --- a/mlir/test/Dialect/Complex/canonicalize.mlir +++ b/mlir/test/Dialect/Complex/canonicalize.mlir @@ -281,3 +281,59 @@ func.func @double_reverse_bitcast(%arg0 : complex<f32>) -> f64 { // CHECK: return %[[R0]] : f64 func.return %1 : f64 } + + +// CHECK-LABEL: func @div_one_f16 +// CHECK-SAME: (%[[ARG0:.*]]: f16, %[[ARG1:.*]]: f16) -> complex<f16> +func.func @div_one_f16(%arg0: f16, %arg1: f16) -> complex<f16> { + %create = complex.create %arg0, %arg1: complex<f16> + %one = complex.constant [1.0 : f16, 0.0 : f16] : complex<f16> + %div = complex.div %create, %one : complex<f16> + // CHECK: %[[CREATE:.*]] = complex.create %[[ARG0]], %[[ARG1]] : complex<f16> + // CHECK-NEXT: return %[[CREATE]] + return %div : complex<f16> +} + +// CHECK-LABEL: func @div_one_f32 +// CHECK-SAME: (%[[ARG0:.*]]: f32, %[[ARG1:.*]]: f32) -> complex<f32> +func.func @div_one_f32(%arg0: f32, %arg1: f32) -> complex<f32> { + %create = complex.create %arg0, %arg1: complex<f32> + %one = complex.constant [1.0 : f32, 0.0 : f32] : complex<f32> + %div = complex.div %create, %one : complex<f32> + // CHECK: %[[CREATE:.*]] = complex.create %[[ARG0]], %[[ARG1]] : complex<f32> + // CHECK-NEXT: return %[[CREATE]] + return %div : complex<f32> +} + +// CHECK-LABEL: func @div_one_f64 +// CHECK-SAME: (%[[ARG0:.*]]: f64, %[[ARG1:.*]]: f64) -> complex<f64> +func.func @div_one_f64(%arg0: f64, %arg1: f64) -> complex<f64> { + %create = complex.create %arg0, %arg1: complex<f64> + %one = complex.constant [1.0 : f64, 0.0 : f64] : complex<f64> + %div = complex.div %create, %one : complex<f64> + // CHECK: %[[CREATE:.*]] = complex.create %[[ARG0]], %[[ARG1]] : complex<f64> + // CHECK-NEXT: return %[[CREATE]] + return %div : complex<f64> +} + +// CHECK-LABEL: func @div_one_f80 +// CHECK-SAME: (%[[ARG0:.*]]: f80, %[[ARG1:.*]]: f80) -> complex<f80> +func.func @div_one_f80(%arg0: f80, %arg1: f80) -> complex<f80> { + %create = complex.create %arg0, %arg1: complex<f80> + %one = complex.constant [1.0 : f80, 0.0 : f80] : complex<f80> + %div = complex.div %create, %one : complex<f80> + // CHECK: %[[CREATE:.*]] = complex.create %[[ARG0]], %[[ARG1]] : complex<f80> + // CHECK-NEXT: return %[[CREATE]] + return %div : complex<f80> +} + +// CHECK-LABEL: func @div_one_f128 +// CHECK-SAME: (%[[ARG0:.*]]: f128, %[[ARG1:.*]]: f128) -> complex<f128> +func.func @div_one_f128(%arg0: f128, %arg1: f128) -> complex<f128> { + %create = complex.create %arg0, %arg1: complex<f128> + %one = complex.constant [1.0 : f128, 0.0 : f128] : complex<f128> + %div = complex.div %create, %one : complex<f128> + // CHECK: %[[CREATE:.*]] = complex.create %[[ARG0]], %[[ARG1]] : complex<f128> + // CHECK-NEXT: return %[[CREATE]] + return %div : complex<f128> +} diff --git a/mlir/test/Dialect/EmitC/invalid_ops.mlir b/mlir/test/Dialect/EmitC/invalid_ops.mlir index 58b3a11ed93e15fc36677166e520f271bc8afda9..22423cf61b5556e74cac3d719b6d7d40c49f4760 100644 --- a/mlir/test/Dialect/EmitC/invalid_ops.mlir +++ b/mlir/test/Dialect/EmitC/invalid_ops.mlir @@ -170,7 +170,7 @@ func.func @add_float_pointer(%arg0: f32, %arg1: !emitc.ptr<f32>) { // ----- func.func @div_tensor(%arg0: tensor<i32>, %arg1: tensor<i32>) { - // expected-error @+1 {{'emitc.div' op operand #0 must be floating-point or integer or index or EmitC opaque type, but got 'tensor<i32>'}} + // expected-error @+1 {{'emitc.div' op operand #0 must be floating-point type supported by EmitC or integer type supported by EmitC or index or EmitC opaque type, but got 'tensor<i32>'}} %1 = "emitc.div" (%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32> return } @@ -178,7 +178,7 @@ func.func @div_tensor(%arg0: tensor<i32>, %arg1: tensor<i32>) { // ----- func.func @mul_tensor(%arg0: tensor<i32>, %arg1: tensor<i32>) { - // expected-error @+1 {{'emitc.mul' op operand #0 must be floating-point or integer or index or EmitC opaque type, but got 'tensor<i32>'}} + // expected-error @+1 {{'emitc.mul' op operand #0 must be floating-point type supported by EmitC or integer type supported by EmitC or index or EmitC opaque type, but got 'tensor<i32>'}} %1 = "emitc.mul" (%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32> return } @@ -186,7 +186,7 @@ func.func @mul_tensor(%arg0: tensor<i32>, %arg1: tensor<i32>) { // ----- func.func @rem_tensor(%arg0: tensor<i32>, %arg1: tensor<i32>) { - // expected-error @+1 {{'emitc.rem' op operand #0 must be integer or index or EmitC opaque type, but got 'tensor<i32>'}} + // expected-error @+1 {{'emitc.rem' op operand #0 must be integer type supported by EmitC or index or EmitC opaque type, but got 'tensor<i32>'}} %1 = "emitc.rem" (%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32> return } @@ -194,7 +194,7 @@ func.func @rem_tensor(%arg0: tensor<i32>, %arg1: tensor<i32>) { // ----- func.func @rem_float(%arg0: f32, %arg1: f32) { - // expected-error @+1 {{'emitc.rem' op operand #0 must be integer or index or EmitC opaque type, but got 'f32'}} + // expected-error @+1 {{'emitc.rem' op operand #0 must be integer type supported by EmitC or index or EmitC opaque type, but got 'f32'}} %1 = "emitc.rem" (%arg0, %arg1) : (f32, f32) -> f32 return } @@ -235,7 +235,7 @@ func.func @test_misplaced_yield() { // ----- func.func @test_assign_to_non_variable(%arg1: f32, %arg2: f32) { - // expected-error @+1 {{'emitc.assign' op requires first operand (<block argument> of type 'f32' at index: 1) to be a Variable}} + // expected-error @+1 {{'emitc.assign' op requires first operand (<block argument> of type 'f32' at index: 1) to be a Variable or subscript}} emitc.assign %arg1 : f32 to %arg2 : f32 return } @@ -387,3 +387,11 @@ func.func @logical_or_resulterror(%arg0: i32, %arg1: i32) { %0 = "emitc.logical_or"(%arg0, %arg1) : (i32, i32) -> i32 return } + +// ----- + +func.func @test_subscript_indices_mismatch(%arg0: !emitc.array<4x8xf32>, %arg2: index) { + // expected-error @+1 {{'emitc.subscript' op requires number of indices (1) to match the rank of the array type (2)}} + %0 = emitc.subscript %arg0[%arg2] : <4x8xf32>, index + return +} diff --git a/mlir/test/Dialect/EmitC/invalid_types.mlir b/mlir/test/Dialect/EmitC/invalid_types.mlir index 079371b39b9d1ee21e8cfa340fc0c306433fa3ea..f9d517bf689b95a953b1e702365b3e1904685efa 100644 --- a/mlir/test/Dialect/EmitC/invalid_types.mlir +++ b/mlir/test/Dialect/EmitC/invalid_types.mlir @@ -81,3 +81,19 @@ func.func @illegal_array_with_tensor_element_type( %arg0: !emitc.array<4xtensor<4xi32>> ) { } + +// ----- + +func.func @illegal_integer_type(%arg0: i11, %arg1: i11) -> i11 { + // expected-error @+1 {{'emitc.mul' op operand #0 must be floating-point type supported by EmitC or integer type supported by EmitC or index or EmitC opaque type, but got 'i11'}} + %mul = "emitc.mul" (%arg0, %arg1) : (i11, i11) -> i11 + return +} + +// ----- + +func.func @illegal_float_type(%arg0: f80, %arg1: f80) { + // expected-error @+1 {{'emitc.mul' op operand #0 must be floating-point type supported by EmitC or integer type supported by EmitC or index or EmitC opaque type, but got 'f80'}} + %mul = "emitc.mul" (%arg0, %arg1) : (f80, f80) -> f80 + return +} diff --git a/mlir/test/Dialect/EmitC/transforms.mlir b/mlir/test/Dialect/EmitC/transforms.mlir index ad167fa455a1a5b3b3a391cba9e16c7b843434cd..8ac606a2c8c0a17806d26a31535c8b4655798999 100644 --- a/mlir/test/Dialect/EmitC/transforms.mlir +++ b/mlir/test/Dialect/EmitC/transforms.mlir @@ -107,3 +107,20 @@ func.func @expression_with_address_taken(%arg0: i32, %arg1: i32, %arg2: !emitc.p %d = emitc.cmp lt, %c, %arg2 :(!emitc.ptr<i32>, !emitc.ptr<i32>) -> i1 return %d : i1 } + +// CHECK-LABEL: func.func @no_nested_expression( +// CHECK-SAME: %[[VAL_0:.*]]: i32, %[[VAL_1:.*]]: i32) -> i1 { +// CHECK: %[[VAL_2:.*]] = emitc.expression : i1 { +// CHECK: %[[VAL_3:.*]] = emitc.cmp lt, %[[VAL_0]], %[[VAL_1]] : (i32, i32) -> i1 +// CHECK: emitc.yield %[[VAL_3]] : i1 +// CHECK: } +// CHECK: return %[[VAL_2]] : i1 +// CHECK: } + +func.func @no_nested_expression(%arg0: i32, %arg1: i32) -> i1 { + %a = emitc.expression : i1 { + %b = emitc.cmp lt, %arg0, %arg1 :(i32, i32) -> i1 + emitc.yield %b : i1 + } + return %a : i1 +} diff --git a/mlir/test/Dialect/LLVMIR/debuginfo.mlir b/mlir/test/Dialect/LLVMIR/debuginfo.mlir index cef2ced391d676cd23c1fb58c0ab9849dfe27394..94bb2bb0622920159861480b8d14faa31e93df7d 100644 --- a/mlir/test/Dialect/LLVMIR/debuginfo.mlir +++ b/mlir/test/Dialect/LLVMIR/debuginfo.mlir @@ -24,10 +24,11 @@ sizeInBits = 32, encoding = DW_ATE_signed > -// CHECK-DAG: #[[PTR0:.*]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type, baseType = #[[INT0]], sizeInBits = 64, alignInBits = 32, offsetInBits = 4> +// CHECK-DAG: #[[PTR0:.*]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type, baseType = #[[INT0]], sizeInBits = 64, alignInBits = 32, offsetInBits = 4, extraData = #[[INT1]]> #ptr0 = #llvm.di_derived_type< tag = DW_TAG_pointer_type, baseType = #int0, - sizeInBits = 64, alignInBits = 32, offsetInBits = 4 + sizeInBits = 64, alignInBits = 32, offsetInBits = 4, + extraData = #int1 > // CHECK-DAG: #[[PTR1:.*]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type, name = "ptr1"> @@ -95,11 +96,10 @@ file = #file, line = 3, scopeLine = 3, subprogramFlags = "Definition|Optimized", type = #spType0 > -// CHECK-DAG: #[[SP1:.*]] = #llvm.di_subprogram<compileUnit = #[[CU]], scope = #[[COMP2]], name = "value", file = #[[FILE]], subprogramFlags = Definition, type = #[[SPTYPE1]]> +// CHECK-DAG: #[[SP1:.*]] = #llvm.di_subprogram<scope = #[[COMP2]], file = #[[FILE]], type = #[[SPTYPE1]]> #sp1 = #llvm.di_subprogram< - // Omit the optional linkageName parameter. - compileUnit = #cu, scope = #comp2, name = "value", - file = #file, subprogramFlags = "Definition", type = #spType1 + // Omit the optional parameters. + scope = #comp2, file = #file, type = #spType1 > // CHECK-DAG: #[[MODULE:.*]] = #llvm.di_module<file = #[[FILE]], scope = #[[FILE]], name = "module", configMacros = "bar", includePath = "/", apinotes = "/", line = 42, isDecl = true> @@ -111,7 +111,6 @@ // CHECK-DAG: #[[SP2:.*]] = #llvm.di_subprogram<compileUnit = #[[CU]], scope = #[[MODULE]], name = "value", file = #[[FILE]], subprogramFlags = Definition, type = #[[SPTYPE2]]> #sp2 = #llvm.di_subprogram< - // Omit the optional linkageName parameter. compileUnit = #cu, scope = #module, name = "value", file = #file, subprogramFlags = "Definition", type = #spType2 > diff --git a/mlir/test/Dialect/LLVMIR/layout.mlir b/mlir/test/Dialect/LLVMIR/layout.mlir index 2868e1740f861c9a16d1f432bf1523a59575d46b..a78fb771242e009050672f4242767f81f52ce1a2 100644 --- a/mlir/test/Dialect/LLVMIR/layout.mlir +++ b/mlir/test/Dialect/LLVMIR/layout.mlir @@ -7,6 +7,7 @@ module { // CHECK: alloca_memory_space = 0 // CHECK: bitsize = 64 // CHECK: global_memory_space = 0 + // CHECK: index = 64 // CHECK: preferred = 8 // CHECK: program_memory_space = 0 // CHECK: size = 8 @@ -16,6 +17,7 @@ module { // CHECK: alloca_memory_space = 0 // CHECK: bitsize = 64 // CHECK: global_memory_space = 0 + // CHECK: index = 64 // CHECK: preferred = 8 // CHECK: program_memory_space = 0 // CHECK: size = 8 @@ -25,6 +27,7 @@ module { // CHECK: alloca_memory_space = 0 // CHECK: bitsize = 64 // CHECK: global_memory_space = 0 + // CHECK: index = 64 // CHECK: preferred = 8 // CHECK: program_memory_space = 0 // CHECK: size = 8 @@ -39,7 +42,7 @@ module { module attributes { dlti.dl_spec = #dlti.dl_spec< #dlti.dl_entry<!llvm.ptr, dense<[32, 32, 64]> : vector<3xi64>>, #dlti.dl_entry<!llvm.ptr<5>, dense<[64, 64, 64]> : vector<3xi64>>, - #dlti.dl_entry<!llvm.ptr<4>, dense<[32, 64, 64]> : vector<3xi64>>, + #dlti.dl_entry<!llvm.ptr<4>, dense<[32, 64, 64, 24]> : vector<4xi64>>, #dlti.dl_entry<"dlti.alloca_memory_space", 5 : ui64>, #dlti.dl_entry<"dlti.global_memory_space", 2 : ui64>, #dlti.dl_entry<"dlti.program_memory_space", 3 : ui64>, @@ -51,6 +54,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec< // CHECK: alloca_memory_space = 5 // CHECK: bitsize = 32 // CHECK: global_memory_space = 2 + // CHECK: index = 32 // CHECK: preferred = 8 // CHECK: program_memory_space = 3 // CHECK: size = 4 @@ -60,6 +64,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec< // CHECK: alloca_memory_space = 5 // CHECK: bitsize = 32 // CHECK: global_memory_space = 2 + // CHECK: index = 32 // CHECK: preferred = 8 // CHECK: program_memory_space = 3 // CHECK: size = 4 @@ -69,24 +74,17 @@ module attributes { dlti.dl_spec = #dlti.dl_spec< // CHECK: alloca_memory_space = 5 // CHECK: bitsize = 64 // CHECK: global_memory_space = 2 + // CHECK: index = 64 // CHECK: preferred = 8 // CHECK: program_memory_space = 3 // CHECK: size = 8 // CHECK: stack_alignment = 128 "test.data_layout_query"() : () -> !llvm.ptr<5> - // CHECK: alignment = 4 - // CHECK: alloca_memory_space = 5 - // CHECK: bitsize = 32 - // CHECK: global_memory_space = 2 - // CHECK: preferred = 8 - // CHECK: program_memory_space = 3 - // CHECK: size = 4 - // CHECK: stack_alignment = 128 - "test.data_layout_query"() : () -> !llvm.ptr<3> // CHECK: alignment = 8 // CHECK: alloca_memory_space = 5 // CHECK: bitsize = 32 // CHECK: global_memory_space = 2 + // CHECK: index = 24 // CHECK: preferred = 8 // CHECK: program_memory_space = 3 // CHECK: size = 4 @@ -134,6 +132,7 @@ module { // simple case // CHECK: alignment = 4 // CHECK: bitsize = 32 + // CHECK: index = 0 // CHECK: preferred = 4 // CHECK: size = 4 "test.data_layout_query"() : () -> !llvm.struct<(i32)> @@ -141,6 +140,7 @@ module { // padding inbetween // CHECK: alignment = 8 // CHECK: bitsize = 128 + // CHECK: index = 0 // CHECK: preferred = 8 // CHECK: size = 16 "test.data_layout_query"() : () -> !llvm.struct<(i32, f64)> @@ -148,6 +148,7 @@ module { // padding at end of struct // CHECK: alignment = 8 // CHECK: bitsize = 128 + // CHECK: index = 0 // CHECK: preferred = 8 // CHECK: size = 16 "test.data_layout_query"() : () -> !llvm.struct<(f64, i32)> @@ -155,6 +156,7 @@ module { // packed // CHECK: alignment = 1 // CHECK: bitsize = 96 + // CHECK: index = 0 // CHECK: preferred = 8 // CHECK: size = 12 "test.data_layout_query"() : () -> !llvm.struct<packed (f64, i32)> @@ -162,6 +164,7 @@ module { // empty // CHECK: alignment = 1 // CHECK: bitsize = 0 + // CHECK: index = 0 // CHECK: preferred = 1 // CHECK: size = 0 "test.data_layout_query"() : () -> !llvm.struct<()> @@ -179,6 +182,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec< // Strict alignment is applied // CHECK: alignment = 4 // CHECK: bitsize = 16 + // CHECK: index = 0 // CHECK: preferred = 4 // CHECK: size = 2 "test.data_layout_query"() : () -> !llvm.struct<(i16)> @@ -186,6 +190,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec< // No impact on structs that have stricter requirements // CHECK: alignment = 8 // CHECK: bitsize = 128 + // CHECK: index = 0 // CHECK: preferred = 8 // CHECK: size = 16 "test.data_layout_query"() : () -> !llvm.struct<(i32, f64)> @@ -193,6 +198,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec< // Only the preferred alignment of structs is affected // CHECK: alignment = 1 // CHECK: bitsize = 32 + // CHECK: index = 0 // CHECK: preferred = 4 // CHECK: size = 4 "test.data_layout_query"() : () -> !llvm.struct<packed (i16, i16)> @@ -200,6 +206,7 @@ module attributes { dlti.dl_spec = #dlti.dl_spec< // empty // CHECK: alignment = 4 // CHECK: bitsize = 0 + // CHECK: index = 0 // CHECK: preferred = 4 // CHECK: size = 0 "test.data_layout_query"() : () -> !llvm.struct<()> @@ -265,6 +272,7 @@ module { // simple case // CHECK: alignment = 4 // CHECK: bitsize = 64 + // CHECK: index = 0 // CHECK: preferred = 4 // CHECK: size = 8 "test.data_layout_query"() : () -> !llvm.array<2 x i32> @@ -272,6 +280,7 @@ module { // size 0 // CHECK: alignment = 8 // CHECK: bitsize = 0 + // CHECK: index = 0 // CHECK: preferred = 8 // CHECK: size = 0 "test.data_layout_query"() : () -> !llvm.array<0 x f64> @@ -279,6 +288,7 @@ module { // alignment info matches element type // CHECK: alignment = 4 // CHECK: bitsize = 64 + // CHECK: index = 0 // CHECK: preferred = 8 // CHECK: size = 8 "test.data_layout_query"() : () -> !llvm.array<1 x i64> diff --git a/mlir/test/Dialect/LLVMIR/mem2reg-intrinsics.mlir b/mlir/test/Dialect/LLVMIR/mem2reg-intrinsics.mlir index ce6338fb3488379c181c744021675557102f80e1..4fc80a87f20df5706308241a9728bb8d2d8359b0 100644 --- a/mlir/test/Dialect/LLVMIR/mem2reg-intrinsics.mlir +++ b/mlir/test/Dialect/LLVMIR/mem2reg-intrinsics.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-opt %s --pass-pipeline="builtin.module(llvm.func(mem2reg{region-simplify=false}))" --split-input-file | FileCheck %s +// RUN: mlir-opt %s --pass-pipeline="builtin.module(llvm.func(mem2reg))" --split-input-file | FileCheck %s // CHECK-LABEL: llvm.func @basic_memset // CHECK-SAME: (%[[MEMSET_VALUE:.*]]: i8) @@ -6,13 +6,13 @@ llvm.func @basic_memset(%memset_value: i8) -> i32 { %0 = llvm.mlir.constant(1 : i32) : i32 %1 = llvm.alloca %0 x i32 {alignment = 4 : i64} : (i32) -> !llvm.ptr %memset_len = llvm.mlir.constant(4 : i32) : i32 - // CHECK-DAG: %[[C8:.*]] = llvm.mlir.constant(8 : i32) : i32 - // CHECK-DAG: %[[C16:.*]] = llvm.mlir.constant(16 : i32) : i32 "llvm.intr.memset"(%1, %memset_value, %memset_len) <{isVolatile = false}> : (!llvm.ptr, i8, i32) -> () // CHECK-NOT: "llvm.intr.memset" // CHECK: %[[VALUE_8:.*]] = llvm.zext %[[MEMSET_VALUE]] : i8 to i32 + // CHECK: %[[C8:.*]] = llvm.mlir.constant(8 : i32) : i32 // CHECK: %[[SHIFTED_8:.*]] = llvm.shl %[[VALUE_8]], %[[C8]] // CHECK: %[[VALUE_16:.*]] = llvm.or %[[VALUE_8]], %[[SHIFTED_8]] + // CHECK: %[[C16:.*]] = llvm.mlir.constant(16 : i32) : i32 // CHECK: %[[SHIFTED_16:.*]] = llvm.shl %[[VALUE_16]], %[[C16]] // CHECK: %[[VALUE_32:.*]] = llvm.or %[[VALUE_16]], %[[SHIFTED_16]] // CHECK-NOT: "llvm.intr.memset" @@ -31,7 +31,14 @@ llvm.func @basic_memset_constant() -> i32 { %memset_len = llvm.mlir.constant(4 : i32) : i32 "llvm.intr.memset"(%1, %memset_value, %memset_len) <{isVolatile = false}> : (!llvm.ptr, i8, i32) -> () %2 = llvm.load %1 {alignment = 4 : i64} : !llvm.ptr -> i32 - // CHECK: %[[RES:.*]] = llvm.mlir.constant(707406378 : i32) : i32 + // CHECK: %[[C42:.*]] = llvm.mlir.constant(42 : i8) : i8 + // CHECK: %[[VALUE_42:.*]] = llvm.zext %[[C42]] : i8 to i32 + // CHECK: %[[C8:.*]] = llvm.mlir.constant(8 : i32) : i32 + // CHECK: %[[SHIFTED_42:.*]] = llvm.shl %[[VALUE_42]], %[[C8]] : i32 + // CHECK: %[[OR0:.*]] = llvm.or %[[VALUE_42]], %[[SHIFTED_42]] : i32 + // CHECK: %[[C16:.*]] = llvm.mlir.constant(16 : i32) : i32 + // CHECK: %[[SHIFTED:.*]] = llvm.shl %[[OR0]], %[[C16]] : i32 + // CHECK: %[[RES:..*]] = llvm.or %[[OR0]], %[[SHIFTED]] : i32 // CHECK: llvm.return %[[RES]] : i32 llvm.return %2 : i32 } @@ -44,16 +51,16 @@ llvm.func @exotic_target_memset(%memset_value: i8) -> i40 { %0 = llvm.mlir.constant(1 : i32) : i32 %1 = llvm.alloca %0 x i40 {alignment = 4 : i64} : (i32) -> !llvm.ptr %memset_len = llvm.mlir.constant(5 : i32) : i32 - // CHECK-DAG: %[[C8:.*]] = llvm.mlir.constant(8 : i40) : i40 - // CHECK-DAG: %[[C16:.*]] = llvm.mlir.constant(16 : i40) : i40 - // CHECK-DAG: %[[C32:.*]] = llvm.mlir.constant(32 : i40) : i40 "llvm.intr.memset"(%1, %memset_value, %memset_len) <{isVolatile = false}> : (!llvm.ptr, i8, i32) -> () // CHECK-NOT: "llvm.intr.memset" // CHECK: %[[VALUE_8:.*]] = llvm.zext %[[MEMSET_VALUE]] : i8 to i40 + // CHECK: %[[C8:.*]] = llvm.mlir.constant(8 : i40) : i40 // CHECK: %[[SHIFTED_8:.*]] = llvm.shl %[[VALUE_8]], %[[C8]] // CHECK: %[[VALUE_16:.*]] = llvm.or %[[VALUE_8]], %[[SHIFTED_8]] + // CHECK: %[[C16:.*]] = llvm.mlir.constant(16 : i40) : i40 // CHECK: %[[SHIFTED_16:.*]] = llvm.shl %[[VALUE_16]], %[[C16]] // CHECK: %[[VALUE_32:.*]] = llvm.or %[[VALUE_16]], %[[SHIFTED_16]] + // CHECK: %[[C32:.*]] = llvm.mlir.constant(32 : i40) : i40 // CHECK: %[[SHIFTED_COMPL:.*]] = llvm.shl %[[VALUE_32]], %[[C32]] // CHECK: %[[VALUE_COMPL:.*]] = llvm.or %[[VALUE_32]], %[[SHIFTED_COMPL]] // CHECK-NOT: "llvm.intr.memset" @@ -64,21 +71,6 @@ llvm.func @exotic_target_memset(%memset_value: i8) -> i40 { // ----- -// CHECK-LABEL: llvm.func @exotic_target_memset_constant -llvm.func @exotic_target_memset_constant() -> i40 { - %0 = llvm.mlir.constant(1 : i32) : i32 - %1 = llvm.alloca %0 x i40 {alignment = 4 : i64} : (i32) -> !llvm.ptr - %memset_value = llvm.mlir.constant(42 : i8) : i8 - %memset_len = llvm.mlir.constant(5 : i32) : i32 - "llvm.intr.memset"(%1, %memset_value, %memset_len) <{isVolatile = false}> : (!llvm.ptr, i8, i32) -> () - %2 = llvm.load %1 {alignment = 4 : i64} : !llvm.ptr -> i40 - // CHECK: %[[RES:.*]] = llvm.mlir.constant(181096032810 : i40) : i40 - // CHECK: llvm.return %[[RES]] : i40 - llvm.return %2 : i40 -} - -// ----- - // CHECK-LABEL: llvm.func @no_volatile_memset llvm.func @no_volatile_memset() -> i32 { // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32 @@ -195,7 +187,7 @@ llvm.func @basic_memcpy_dest(%destination: !llvm.ptr) -> i32 { // CHECK-LABEL: llvm.func @double_memcpy llvm.func @double_memcpy() -> i32 { %0 = llvm.mlir.constant(1 : i32) : i32 - // CHECK-NEXT: %[[DATA:.*]] = llvm.mlir.constant(42 : i32) : i32 + // CHECK: %[[DATA:.*]] = llvm.mlir.constant(42 : i32) : i32 %data = llvm.mlir.constant(42 : i32) : i32 %is_volatile = llvm.mlir.constant(false) : i1 %memcpy_len = llvm.mlir.constant(4 : i32) : i32 @@ -206,7 +198,7 @@ llvm.func @double_memcpy() -> i32 { "llvm.intr.memcpy"(%2, %1, %memcpy_len) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> () %res = llvm.load %2 : !llvm.ptr -> i32 - // CHECK-NEXT: llvm.return %[[DATA]] : i32 + // CHECK: llvm.return %[[DATA]] : i32 llvm.return %res : i32 } diff --git a/mlir/test/Dialect/LLVMIR/nvvm.mlir b/mlir/test/Dialect/LLVMIR/nvvm.mlir index f35393c5e957484f922cb3c22f8a86de1c05035b..de2904d15b647b4f68e48a272c9bf6ddcc1811df 100644 --- a/mlir/test/Dialect/LLVMIR/nvvm.mlir +++ b/mlir/test/Dialect/LLVMIR/nvvm.mlir @@ -55,6 +55,16 @@ llvm.func @llvm_nvvm_barrier(%barId : i32, %numberOfThreads : i32) { llvm.return } +// CHECK-LABEL: @llvm_nvvm_barrier_arrive +// CHECK-SAME: (%[[barId:.*]]: i32, %[[numberOfThreads:.*]]: i32) +llvm.func @llvm_nvvm_barrier_arrive(%barId : i32, %numberOfThreads : i32) { + // CHECK: nvvm.barrier.arrive number_of_threads = %[[numberOfThreads]] + nvvm.barrier.arrive number_of_threads = %numberOfThreads + // CHECK: nvvm.barrier.arrive id = %[[barId]] number_of_threads = %[[numberOfThreads]] + nvvm.barrier.arrive id = %barId number_of_threads = %numberOfThreads + llvm.return +} + // CHECK-LABEL: @llvm_nvvm_cluster_arrive func.func @llvm_nvvm_cluster_arrive() { // CHECK: nvvm.cluster.arrive diff --git a/mlir/test/Dialect/LLVMIR/roundtrip.mlir b/mlir/test/Dialect/LLVMIR/roundtrip.mlir index b157cf0014184250df14e52028d489629db050a4..31acf2b95e4638bafb612f208d3cfc6cc38715b4 100644 --- a/mlir/test/Dialect/LLVMIR/roundtrip.mlir +++ b/mlir/test/Dialect/LLVMIR/roundtrip.mlir @@ -647,3 +647,18 @@ llvm.func @experimental_noalias_scope_decl() { llvm.intr.experimental.noalias.scope.decl #alias_scope llvm.return } + +// CHECK-LABEL: @experimental_constrained_fptrunc +llvm.func @experimental_constrained_fptrunc(%in: f64) { + // CHECK: llvm.intr.experimental.constrained.fptrunc %{{.*}} towardzero ignore : f64 to f32 + %0 = llvm.intr.experimental.constrained.fptrunc %in towardzero ignore : f64 to f32 + // CHECK: llvm.intr.experimental.constrained.fptrunc %{{.*}} tonearest maytrap : f64 to f32 + %1 = llvm.intr.experimental.constrained.fptrunc %in tonearest maytrap : f64 to f32 + // CHECK: llvm.intr.experimental.constrained.fptrunc %{{.*}} upward strict : f64 to f32 + %2 = llvm.intr.experimental.constrained.fptrunc %in upward strict : f64 to f32 + // CHECK: llvm.intr.experimental.constrained.fptrunc %{{.*}} downward ignore : f64 to f32 + %3 = llvm.intr.experimental.constrained.fptrunc %in downward ignore : f64 to f32 + // CHECK: llvm.intr.experimental.constrained.fptrunc %{{.*}} tonearestaway ignore : f64 to f32 + %4 = llvm.intr.experimental.constrained.fptrunc %in tonearestaway ignore : f64 to f32 + llvm.return +} diff --git a/mlir/test/Dialect/LLVMIR/sroa-intrinsics.mlir b/mlir/test/Dialect/LLVMIR/sroa-intrinsics.mlir index c2e3458134ba4b6312b7e79d074cc22454885bc0..ba73025814cc0548513d10b2d56d870b09603933 100644 --- a/mlir/test/Dialect/LLVMIR/sroa-intrinsics.mlir +++ b/mlir/test/Dialect/LLVMIR/sroa-intrinsics.mlir @@ -146,12 +146,10 @@ llvm.func @invalid_indirect_memset() -> i32 { // CHECK-LABEL: llvm.func @memset_double_use llvm.func @memset_double_use() -> i32 { - // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32 - // CHECK-DAG: %[[ALLOCA_INT:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32 - // CHECK-DAG: %[[ALLOCA_FLOAT:.*]] = llvm.alloca %[[ALLOCA_LEN]] x f32 - // CHECK-DAG: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8 - // After SROA, only one i32 will be actually used, so only 4 bytes will be set. - // CHECK-DAG: %[[MEMSET_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 + // CHECK: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA_FLOAT:.*]] = llvm.alloca %[[ALLOCA_LEN]] x f32 + // CHECK: %[[ALLOCA_INT:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32 + // CHECK: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8 %0 = llvm.mlir.constant(1 : i32) : i32 %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, f32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr %memset_value = llvm.mlir.constant(42 : i8) : i8 @@ -159,8 +157,11 @@ llvm.func @memset_double_use() -> i32 { %memset_len = llvm.mlir.constant(8 : i32) : i32 // We expect two generated memset, one for each field. // CHECK-NOT: "llvm.intr.memset" - // CHECK-DAG: "llvm.intr.memset"(%[[ALLOCA_INT]], %[[MEMSET_VALUE]], %[[MEMSET_LEN]]) <{isVolatile = false}> - // CHECK-DAG: "llvm.intr.memset"(%[[ALLOCA_FLOAT]], %[[MEMSET_VALUE]], %[[MEMSET_LEN]]) <{isVolatile = false}> + // After SROA, only one i32 will be actually used, so only 4 bytes will be set. + // CHECK: %[[MEMSET_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 + // CHECK: "llvm.intr.memset"(%[[ALLOCA_INT]], %[[MEMSET_VALUE]], %[[MEMSET_LEN]]) <{isVolatile = false}> + // CHECK: %[[MEMSET_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 + // CHECK: "llvm.intr.memset"(%[[ALLOCA_FLOAT]], %[[MEMSET_VALUE]], %[[MEMSET_LEN]]) <{isVolatile = false}> // CHECK-NOT: "llvm.intr.memset" "llvm.intr.memset"(%1, %memset_value, %memset_len) <{isVolatile = false}> : (!llvm.ptr, i8, i32) -> () %2 = llvm.getelementptr %1[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, f32)> @@ -208,13 +209,10 @@ llvm.func @memset_considers_alignment() -> i32 { // CHECK-LABEL: llvm.func @memset_considers_packing llvm.func @memset_considers_packing() -> i32 { - // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32 - // CHECK-DAG: %[[ALLOCA_INT:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32 - // CHECK-DAG: %[[ALLOCA_FLOAT:.*]] = llvm.alloca %[[ALLOCA_LEN]] x f32 - // CHECK-DAG: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8 - // After SROA, only 32-bit values will be actually used, so only 4 bytes will be set. - // CHECK-DAG: %[[MEMSET_LEN_WHOLE:.*]] = llvm.mlir.constant(4 : i32) : i32 - // CHECK-DAG: %[[MEMSET_LEN_PARTIAL:.*]] = llvm.mlir.constant(3 : i32) : i32 + // CHECK: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA_FLOAT:.*]] = llvm.alloca %[[ALLOCA_LEN]] x f32 + // CHECK: %[[ALLOCA_INT:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32 + // CHECK: %[[MEMSET_VALUE:.*]] = llvm.mlir.constant(42 : i8) : i8 %0 = llvm.mlir.constant(1 : i32) : i32 %1 = llvm.alloca %0 x !llvm.struct<"foo", packed (i8, i32, f32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr %memset_value = llvm.mlir.constant(42 : i8) : i8 @@ -222,7 +220,10 @@ llvm.func @memset_considers_packing() -> i32 { %memset_len = llvm.mlir.constant(8 : i32) : i32 // Now all fields are touched by the memset. // CHECK-NOT: "llvm.intr.memset" + // After SROA, only 32-bit values will be actually used, so only 4 bytes will be set. + // CHECK: %[[MEMSET_LEN_WHOLE:.*]] = llvm.mlir.constant(4 : i32) : i32 // CHECK: "llvm.intr.memset"(%[[ALLOCA_INT]], %[[MEMSET_VALUE]], %[[MEMSET_LEN_WHOLE]]) <{isVolatile = false}> + // CHECK: %[[MEMSET_LEN_PARTIAL:.*]] = llvm.mlir.constant(3 : i32) : i32 // CHECK: "llvm.intr.memset"(%[[ALLOCA_FLOAT]], %[[MEMSET_VALUE]], %[[MEMSET_LEN_PARTIAL]]) <{isVolatile = false}> // CHECK-NOT: "llvm.intr.memset" "llvm.intr.memset"(%1, %memset_value, %memset_len) <{isVolatile = false}> : (!llvm.ptr, i8, i32) -> () @@ -241,14 +242,14 @@ llvm.func @memset_considers_packing() -> i32 { // CHECK-LABEL: llvm.func @memcpy_dest // CHECK-SAME: (%[[OTHER_ARRAY:.*]]: !llvm.ptr) llvm.func @memcpy_dest(%other_array: !llvm.ptr) -> i32 { - // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32 - // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32 - // After SROA, only one i32 will be actually used, so only 4 bytes will be set. - // CHECK-DAG: %[[MEMCPY_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 + // CHECK: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32 %0 = llvm.mlir.constant(1 : i32) : i32 %1 = llvm.alloca %0 x !llvm.array<10 x i32> : (i32) -> !llvm.ptr %memcpy_len = llvm.mlir.constant(40 : i32) : i32 // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32> + // After SROA, only one i32 will be actually used, so only 4 bytes will be set. + // CHECK: %[[MEMCPY_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 // CHECK: "llvm.intr.memcpy"(%[[ALLOCA]], %[[SLOT_IN_OTHER]], %[[MEMCPY_LEN]]) <{isVolatile = false}> "llvm.intr.memcpy"(%1, %other_array, %memcpy_len) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> () %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32> @@ -261,9 +262,8 @@ llvm.func @memcpy_dest(%other_array: !llvm.ptr) -> i32 { // CHECK-LABEL: llvm.func @memcpy_src // CHECK-SAME: (%[[OTHER_ARRAY:.*]]: !llvm.ptr) llvm.func @memcpy_src(%other_array: !llvm.ptr) -> i32 { - // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32 // After SROA, only one i32 will be actually used, so only 4 bytes will be set. - // CHECK-DAG: %[[MEMCPY_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 // CHECK-COUNT-4: = llvm.alloca %[[ALLOCA_LEN]] x i32 %0 = llvm.mlir.constant(1 : i32) : i32 %1 = llvm.alloca %0 x !llvm.array<4 x i32> : (i32) -> !llvm.ptr @@ -271,14 +271,18 @@ llvm.func @memcpy_src(%other_array: !llvm.ptr) -> i32 { // Unfortunately because of FileCheck limitations it is not possible to check which slot gets read from. // We can only check that the amount of operations and allocated slots is correct, which should be sufficient // as unused slots are not generated. - // CHECK-DAG: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32> - // CHECK-DAG: "llvm.intr.memcpy"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMCPY_LEN]]) <{isVolatile = false}> - // CHECK-DAG: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32> - // CHECK-DAG: "llvm.intr.memcpy"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMCPY_LEN]]) <{isVolatile = false}> - // CHECK-DAG: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32> - // CHECK-DAG: "llvm.intr.memcpy"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMCPY_LEN]]) <{isVolatile = false}> - // CHECK-DAG: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32> - // CHECK-DAG: "llvm.intr.memcpy"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMCPY_LEN]]) <{isVolatile = false}> + // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32> + // CHECK: %[[MEMCPY_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 + // CHECK: "llvm.intr.memcpy"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMCPY_LEN]]) <{isVolatile = false}> + // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32> + // CHECK: %[[MEMCPY_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 + // CHECK: "llvm.intr.memcpy"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMCPY_LEN]]) <{isVolatile = false}> + // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32> + // CHECK: %[[MEMCPY_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 + // CHECK: "llvm.intr.memcpy"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMCPY_LEN]]) <{isVolatile = false}> + // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32> + // CHECK: %[[MEMCPY_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 + // CHECK: "llvm.intr.memcpy"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMCPY_LEN]]) <{isVolatile = false}> "llvm.intr.memcpy"(%other_array, %1, %memcpy_len) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> () %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32> %3 = llvm.load %2 : !llvm.ptr -> i32 @@ -289,14 +293,19 @@ llvm.func @memcpy_src(%other_array: !llvm.ptr) -> i32 { // CHECK-LABEL: llvm.func @memcpy_double llvm.func @memcpy_double() -> i32 { - // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32 - // CHECK-DAG: %[[MEMCPY_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 + // CHECK: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32 %0 = llvm.mlir.constant(1 : i32) : i32 - // CHECK-COUNT-2: = llvm.alloca %[[ALLOCA_LEN]] x i32 + // CHECK: = llvm.alloca %[[ALLOCA_LEN]] x i32 + // TODO: This should also disappear as a GEP with all zero indices should be + // ignored. + // CHECK: = llvm.alloca %[[ALLOCA_LEN]] x !llvm.array<1 x i32> %1 = llvm.alloca %0 x !llvm.array<1 x i32> : (i32) -> !llvm.ptr %2 = llvm.alloca %0 x !llvm.array<1 x i32> : (i32) -> !llvm.ptr + // Match the dead constant, to avoid collision with the newly created one. + // CHECK: llvm.mlir.constant %memcpy_len = llvm.mlir.constant(4 : i32) : i32 // CHECK-NOT: "llvm.intr.memcpy" + // CHECK: %[[MEMCPY_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 // CHECK: "llvm.intr.memcpy"(%{{.*}}, %{{.*}}, %[[MEMCPY_LEN]]) <{isVolatile = false}> // CHECK-NOT: "llvm.intr.memcpy" "llvm.intr.memcpy"(%1, %2, %memcpy_len) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> () @@ -346,14 +355,14 @@ llvm.func @memcpy_no_volatile(%other_array: !llvm.ptr) -> i32 { // CHECK-LABEL: llvm.func @memmove_dest // CHECK-SAME: (%[[OTHER_ARRAY:.*]]: !llvm.ptr) llvm.func @memmove_dest(%other_array: !llvm.ptr) -> i32 { - // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32 - // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32 - // After SROA, only one i32 will be actually used, so only 4 bytes will be set. - // CHECK-DAG: %[[MEMMOVE_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 + // CHECK: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_LEN]] x i32 %0 = llvm.mlir.constant(1 : i32) : i32 %1 = llvm.alloca %0 x !llvm.array<10 x i32> : (i32) -> !llvm.ptr %memmove_len = llvm.mlir.constant(40 : i32) : i32 // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32> + // After SROA, only one i32 will be actually used, so only 4 bytes will be set. + // CHECK: %[[MEMMOVE_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 // CHECK: "llvm.intr.memmove"(%[[ALLOCA]], %[[SLOT_IN_OTHER]], %[[MEMMOVE_LEN]]) <{isVolatile = false}> "llvm.intr.memmove"(%1, %other_array, %memmove_len) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> () %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32> @@ -366,9 +375,7 @@ llvm.func @memmove_dest(%other_array: !llvm.ptr) -> i32 { // CHECK-LABEL: llvm.func @memmove_src // CHECK-SAME: (%[[OTHER_ARRAY:.*]]: !llvm.ptr) llvm.func @memmove_src(%other_array: !llvm.ptr) -> i32 { - // CHECK-DAG: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32 - // After SROA, only one i32 will be actually used, so only 4 bytes will be set. - // CHECK-DAG: %[[MEMMOVE_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 + // CHECK: %[[ALLOCA_LEN:.*]] = llvm.mlir.constant(1 : i32) : i32 // CHECK-COUNT-4: = llvm.alloca %[[ALLOCA_LEN]] x i32 %0 = llvm.mlir.constant(1 : i32) : i32 %1 = llvm.alloca %0 x !llvm.array<4 x i32> : (i32) -> !llvm.ptr @@ -376,14 +383,18 @@ llvm.func @memmove_src(%other_array: !llvm.ptr) -> i32 { // Unfortunately because of FileCheck limitations it is not possible to check which slot gets read from. // We can only check that the amount of operations and allocated slots is correct, which should be sufficient // as unused slots are not generated. - // CHECK-DAG: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32> - // CHECK-DAG: "llvm.intr.memmove"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMMOVE_LEN]]) <{isVolatile = false}> - // CHECK-DAG: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32> - // CHECK-DAG: "llvm.intr.memmove"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMMOVE_LEN]]) <{isVolatile = false}> - // CHECK-DAG: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32> - // CHECK-DAG: "llvm.intr.memmove"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMMOVE_LEN]]) <{isVolatile = false}> - // CHECK-DAG: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32> - // CHECK-DAG: "llvm.intr.memmove"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMMOVE_LEN]]) <{isVolatile = false}> + // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32> + // CHECK: %[[MEMMOVE_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 + // CHECK: "llvm.intr.memmove"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMMOVE_LEN]]) <{isVolatile = false}> + // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32> + // CHECK: %[[MEMMOVE_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 + // CHECK: "llvm.intr.memmove"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMMOVE_LEN]]) <{isVolatile = false}> + // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32> + // CHECK: %[[MEMMOVE_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 + // CHECK: "llvm.intr.memmove"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMMOVE_LEN]]) <{isVolatile = false}> + // CHECK: %[[SLOT_IN_OTHER:.*]] = llvm.getelementptr %[[OTHER_ARRAY]][0, 3] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32> + // CHECK: %[[MEMMOVE_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 + // CHECK: "llvm.intr.memmove"(%[[SLOT_IN_OTHER]], %{{.*}}, %[[MEMMOVE_LEN]]) <{isVolatile = false}> "llvm.intr.memmove"(%other_array, %1, %memmove_len) <{isVolatile = false}> : (!llvm.ptr, !llvm.ptr, i32) -> () %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i32> %3 = llvm.load %2 : !llvm.ptr -> i32 diff --git a/mlir/test/Dialect/LLVMIR/sroa.mlir b/mlir/test/Dialect/LLVMIR/sroa.mlir index f56ea53ac029e709bc089a17dc2f2ea19db32a59..fe1531d988a4f52d234e2fda941bac52cf94b625 100644 --- a/mlir/test/Dialect/LLVMIR/sroa.mlir +++ b/mlir/test/Dialect/LLVMIR/sroa.mlir @@ -82,6 +82,27 @@ llvm.func @multi_level_indirect() -> i32 { // ----- +// This verifies that a nested GEP's users are checked properly. In this case +// the load goes over the bounds of the memory slot and thus should block the +// splitting of the alloca. + +// CHECK-LABEL: llvm.func @nested_access_over_slot_bound +llvm.func @nested_access_over_slot_bound() -> i64 { + %0 = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<(i32, struct<( + %1 = llvm.alloca %0 x !llvm.struct<(i32, struct<(array<10 x i32>)>, i32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr + // CHECK: %[[GEP0:.*]] = llvm.getelementptr inbounds %[[ALLOCA]] + %2 = llvm.getelementptr inbounds %1[0, 1, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i32, struct<(array<10 x i32>)>, i32)> + // CHECK: %[[GEP1:.*]] = llvm.getelementptr inbounds %[[GEP0]] + %3 = llvm.getelementptr inbounds %2[0, 9] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<10 x i32> + // CHECK: %[[RES:.*]] = llvm.load %[[GEP1]] + %4 = llvm.load %3 : !llvm.ptr -> i64 + // CHECK: llvm.return %[[RES]] : i64 + llvm.return %4 : i64 +} + +// ----- + // CHECK-LABEL: llvm.func @resolve_alias // CHECK-SAME: (%[[ARG:.*]]: i32) llvm.func @resolve_alias(%arg: i32) -> i32 { @@ -197,3 +218,233 @@ llvm.func @no_dynamic_indexing(%arg: i32) -> i32 { // CHECK: llvm.return %[[RES]] : i32 llvm.return %3 : i32 } + +// ----- + +// CHECK-LABEL: llvm.func @no_nested_dynamic_indexing +// CHECK-SAME: (%[[ARG:.*]]: i32) +llvm.func @no_nested_dynamic_indexing(%arg: i32) -> i32 { + // CHECK: %[[SIZE:.*]] = llvm.mlir.constant(1 : i32) + %0 = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[SIZE]] x !llvm.struct<(array<10 x i32>, i32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr + %1 = llvm.alloca %0 x !llvm.struct<(array<10 x i32>, i32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr + // CHECK-NOT: = llvm.alloca + // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0, %[[ARG]]] + %2 = llvm.getelementptr %1[0, 0, %arg] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<(array<10 x i32>, i32)> + // CHECK: %[[RES:.*]] = llvm.load %[[GEP]] + %3 = llvm.load %2 : !llvm.ptr -> i32 + // CHECK: llvm.return %[[RES]] : i32 + llvm.return %3 : i32 +} + +// ----- + +// CHECK-LABEL: llvm.func @store_first_field +llvm.func @store_first_field(%arg: i32) { + %0 = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i32 + %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32, i32)> : (i32) -> !llvm.ptr + // CHECK-NEXT: llvm.store %{{.*}}, %[[ALLOCA]] : i32 + llvm.store %arg, %1 : i32, !llvm.ptr + llvm.return +} + +// ----- + +// CHECK-LABEL: llvm.func @store_first_field_different_type +// CHECK-SAME: (%[[ARG:.*]]: f32) +llvm.func @store_first_field_different_type(%arg: f32) { + %0 = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i32 + %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32, i32)> : (i32) -> !llvm.ptr + // CHECK-NEXT: llvm.store %[[ARG]], %[[ALLOCA]] : f32 + llvm.store %arg, %1 : f32, !llvm.ptr + llvm.return +} + +// ----- + +// CHECK-LABEL: llvm.func @store_sub_field +// CHECK-SAME: (%[[ARG:.*]]: f32) +llvm.func @store_sub_field(%arg: f32) { + %0 = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i64 + %1 = llvm.alloca %0 x !llvm.struct<"foo", (i64, i32)> : (i32) -> !llvm.ptr + // CHECK-NEXT: llvm.store %[[ARG]], %[[ALLOCA]] : f32 + llvm.store %arg, %1 : f32, !llvm.ptr + llvm.return +} + +// ----- + +// CHECK-LABEL: llvm.func @load_first_field +llvm.func @load_first_field() -> i32 { + %0 = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i32 + %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32, i32)> : (i32) -> !llvm.ptr + // CHECK-NEXT: %[[RES:.*]] = llvm.load %[[ALLOCA]] : !llvm.ptr -> i32 + %2 = llvm.load %1 : !llvm.ptr -> i32 + // CHECK: llvm.return %[[RES]] : i32 + llvm.return %2 : i32 +} + +// ----- + +// CHECK-LABEL: llvm.func @load_first_field_different_type +llvm.func @load_first_field_different_type() -> f32 { + %0 = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i32 + %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32, i32)> : (i32) -> !llvm.ptr + // CHECK-NEXT: %[[RES:.*]] = llvm.load %[[ALLOCA]] : !llvm.ptr -> f32 + %2 = llvm.load %1 : !llvm.ptr -> f32 + // CHECK: llvm.return %[[RES]] : f32 + llvm.return %2 : f32 +} + +// ----- + +// CHECK-LABEL: llvm.func @load_sub_field +llvm.func @load_sub_field() -> i32 { + %0 = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i64 : (i32) -> !llvm.ptr + %1 = llvm.alloca %0 x !llvm.struct<(i64, i32)> : (i32) -> !llvm.ptr + // CHECK-NEXT: %[[RES:.*]] = llvm.load %[[ALLOCA]] + %res = llvm.load %1 : !llvm.ptr -> i32 + // CHECK: llvm.return %[[RES]] : i32 + llvm.return %res : i32 +} + +// ----- + +// CHECK-LABEL: llvm.func @vector_store_type_mismatch +// CHECK-SAME: %[[ARG:.*]]: vector<4xi32> +llvm.func @vector_store_type_mismatch(%arg: vector<4xi32>) { + %0 = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x vector<4xf32> + %1 = llvm.alloca %0 x !llvm.struct<"foo", (vector<4xf32>)> : (i32) -> !llvm.ptr + // CHECK-NEXT: llvm.store %[[ARG]], %[[ALLOCA]] + llvm.store %arg, %1 : vector<4xi32>, !llvm.ptr + llvm.return +} + +// ----- + +// CHECK-LABEL: llvm.func @store_to_memory +// CHECK-SAME: %[[ARG:.*]]: !llvm.ptr +llvm.func @store_to_memory(%arg: !llvm.ptr) { + %0 = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct< + %1 = llvm.alloca %0 x !llvm.struct<"foo", (vector<4xf32>)> : (i32) -> !llvm.ptr + // CHECK-NEXT: llvm.store %[[ALLOCA]], %[[ARG]] + llvm.store %1, %arg : !llvm.ptr, !llvm.ptr + llvm.return +} + +// ----- + +// CHECK-LABEL: llvm.func @type_mismatch_array_access +// CHECK-SAME: %[[ARG:.*]]: i32 +llvm.func @type_mismatch_array_access(%arg: i32) { + %0 = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i32 + %1 = llvm.alloca %0 x !llvm.struct<(i32, i32, i32)> : (i32) -> !llvm.ptr + %2 = llvm.getelementptr %1[8] : (!llvm.ptr) -> !llvm.ptr, i8 + // CHECK-NEXT: llvm.store %[[ARG]], %[[ALLOCA]] + llvm.store %arg, %2 : i32, !llvm.ptr + llvm.return +} + +// ----- + +// CHECK-LABEL: llvm.func @type_mismatch_struct_access +// CHECK-SAME: %[[ARG:.*]]: i32 +llvm.func @type_mismatch_struct_access(%arg: i32) { + %0 = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i32 + %1 = llvm.alloca %0 x !llvm.struct<(i32, i32, i32)> : (i32) -> !llvm.ptr + %2 = llvm.getelementptr %1[0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i32, i32)> + // CHECK-NEXT: llvm.store %[[ARG]], %[[ALLOCA]] + llvm.store %arg, %2 : i32, !llvm.ptr + llvm.return +} + +// ----- + +// CHECK-LABEL: llvm.func @index_in_final_padding +llvm.func @index_in_final_padding(%arg: i32) { + %0 = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (i32, i8)> + %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i8)> : (i32) -> !llvm.ptr + // CHECK: = llvm.getelementptr %[[ALLOCA]][7] : (!llvm.ptr) -> !llvm.ptr, i8 + %2 = llvm.getelementptr %1[7] : (!llvm.ptr) -> !llvm.ptr, i8 + llvm.store %arg, %2 : i32, !llvm.ptr + llvm.return +} + +// ----- + +// CHECK-LABEL: llvm.func @index_out_of_bounds +llvm.func @index_out_of_bounds(%arg: i32) { + %0 = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (i32, i32)> + %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32)> : (i32) -> !llvm.ptr + // CHECK: = llvm.getelementptr %[[ALLOCA]][9] : (!llvm.ptr) -> !llvm.ptr, i8 + %2 = llvm.getelementptr %1[9] : (!llvm.ptr) -> !llvm.ptr, i8 + llvm.store %arg, %2 : i32, !llvm.ptr + llvm.return +} + +// ----- + +// CHECK-LABEL: llvm.func @index_in_padding +llvm.func @index_in_padding(%arg: i16) { + %0 = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (i16, i32)> + %1 = llvm.alloca %0 x !llvm.struct<"foo", (i16, i32)> : (i32) -> !llvm.ptr + // CHECK: = llvm.getelementptr %[[ALLOCA]][2] : (!llvm.ptr) -> !llvm.ptr, i8 + %2 = llvm.getelementptr %1[2] : (!llvm.ptr) -> !llvm.ptr, i8 + llvm.store %arg, %2 : i16, !llvm.ptr + llvm.return +} + +// ----- + +// CHECK-LABEL: llvm.func @index_not_in_padding_because_packed +// CHECK-SAME: %[[ARG:.*]]: i16 +llvm.func @index_not_in_padding_because_packed(%arg: i16) { + %0 = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i32 + %1 = llvm.alloca %0 x !llvm.struct<"foo", packed (i16, i32)> : (i32) -> !llvm.ptr + %2 = llvm.getelementptr %1[2] : (!llvm.ptr) -> !llvm.ptr, i8 + // CHECK-NEXT: llvm.store %[[ARG]], %[[ALLOCA]] + llvm.store %arg, %2 : i16, !llvm.ptr + llvm.return +} + +// ----- + +// CHECK-LABEL: llvm.func @no_crash_on_negative_gep_index +// CHECK-SAME: %[[ARG:.*]]: f16 +llvm.func @no_crash_on_negative_gep_index(%arg: f16) { + %0 = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (i32, i32, i32)> + %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32, i32)> : (i32) -> !llvm.ptr + // CHECK: llvm.getelementptr %[[ALLOCA]][-1] : (!llvm.ptr) -> !llvm.ptr, f32 + %2 = llvm.getelementptr %1[-1] : (!llvm.ptr) -> !llvm.ptr, f32 + llvm.store %arg, %2 : f16, !llvm.ptr + llvm.return +} + +// ----- + +// CHECK-LABEL: llvm.func @out_of_bound_gep_array_access +// CHECK-SAME: %[[ARG:.*]]: i32 +llvm.func @out_of_bound_gep_array_access(%arg: i32) { + %0 = llvm.mlir.constant(1 : i32) : i32 + // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x i32 + %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32)> : (i32) -> !llvm.ptr + %2 = llvm.getelementptr %1[0, 4] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<4 x i8> + // CHECK-NEXT: llvm.store %[[ARG]], %[[ALLOCA]] + llvm.store %arg, %2 : i32, !llvm.ptr + llvm.return +} diff --git a/mlir/test/Dialect/LLVMIR/type-consistency.mlir b/mlir/test/Dialect/LLVMIR/type-consistency.mlir index 021151b929d8e2227bd0e9321d3b0e275df8c847..a6176142f1746334031cf1abe75871a0882b8091 100644 --- a/mlir/test/Dialect/LLVMIR/type-consistency.mlir +++ b/mlir/test/Dialect/LLVMIR/type-consistency.mlir @@ -26,63 +26,6 @@ llvm.func @same_address_keep_inbounds(%arg: i32) { // ----- -// CHECK-LABEL: llvm.func @struct_store_instead_of_first_field -llvm.func @struct_store_instead_of_first_field(%arg: i32) { - %0 = llvm.mlir.constant(1 : i32) : i32 - // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (i32, i32, i32)> - %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32, i32)> : (i32) -> !llvm.ptr - // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, i32, i32)> - // CHECK: llvm.store %{{.*}}, %[[GEP]] : i32 - llvm.store %arg, %1 : i32, !llvm.ptr - llvm.return -} - -// ----- - -// CHECK-LABEL: llvm.func @struct_store_instead_of_first_field_same_size -// CHECK-SAME: (%[[ARG:.*]]: f32) -llvm.func @struct_store_instead_of_first_field_same_size(%arg: f32) { - %0 = llvm.mlir.constant(1 : i32) : i32 - // CHECK-DAG: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (i32, i32, i32)> - %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32, i32)> : (i32) -> !llvm.ptr - // CHECK-DAG: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, i32, i32)> - // CHECK-DAG: %[[BITCAST:.*]] = llvm.bitcast %[[ARG]] : f32 to i32 - // CHECK: llvm.store %[[BITCAST]], %[[GEP]] : i32 - llvm.store %arg, %1 : f32, !llvm.ptr - llvm.return -} - -// ----- - -// CHECK-LABEL: llvm.func @struct_load_instead_of_first_field -llvm.func @struct_load_instead_of_first_field() -> i32 { - %0 = llvm.mlir.constant(1 : i32) : i32 - // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (i32, i32, i32)> - %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32, i32)> : (i32) -> !llvm.ptr - // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, i32, i32)> - // CHECK: %[[RES:.*]] = llvm.load %[[GEP]] : !llvm.ptr -> i32 - %2 = llvm.load %1 : !llvm.ptr -> i32 - // CHECK: llvm.return %[[RES]] : i32 - llvm.return %2 : i32 -} - -// ----- - -// CHECK-LABEL: llvm.func @struct_load_instead_of_first_field_same_size -llvm.func @struct_load_instead_of_first_field_same_size() -> f32 { - %0 = llvm.mlir.constant(1 : i32) : i32 - // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (i32, i32, i32)> - %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32, i32)> : (i32) -> !llvm.ptr - // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, i32, i32)> - // CHECK: %[[LOADED:.*]] = llvm.load %[[GEP]] : !llvm.ptr -> i32 - // CHECK: %[[RES:.*]] = llvm.bitcast %[[LOADED]] : i32 to f32 - %2 = llvm.load %1 : !llvm.ptr -> f32 - // CHECK: llvm.return %[[RES]] : f32 - llvm.return %2 : f32 -} - -// ----- - // CHECK-LABEL: llvm.func @index_in_final_padding llvm.func @index_in_final_padding(%arg: i32) { %0 = llvm.mlir.constant(1 : i32) : i32 @@ -135,22 +78,6 @@ llvm.func @index_not_in_padding_because_packed(%arg: i16) { // ----- -// CHECK-LABEL: llvm.func @index_to_struct -// CHECK-SAME: (%[[ARG:.*]]: i32) -llvm.func @index_to_struct(%arg: i32) { - %0 = llvm.mlir.constant(1 : i32) : i32 - // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (i32, struct<"bar", (i32, i32)>)> - %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, struct<"bar", (i32, i32)>)> : (i32) -> !llvm.ptr - // CHECK: %[[GEP0:.*]] = llvm.getelementptr %[[ALLOCA]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, struct<"bar", (i32, i32)>)> - // CHECK: %[[GEP1:.*]] = llvm.getelementptr %[[GEP0]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"bar", (i32, i32)> - %7 = llvm.getelementptr %1[4] : (!llvm.ptr) -> !llvm.ptr, i8 - // CHECK: llvm.store %[[ARG]], %[[GEP1]] - llvm.store %arg, %7 : i32, !llvm.ptr - llvm.return -} - -// ----- - // CHECK-LABEL: llvm.func @no_crash_on_negative_gep_index llvm.func @no_crash_on_negative_gep_index() { %0 = llvm.mlir.constant(1.000000e+00 : f16) : f16 @@ -175,10 +102,9 @@ llvm.func @coalesced_store_ints(%arg: i64) { // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (i32, i32)> %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32)> : (i32) -> !llvm.ptr - // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, i32)> // CHECK: %[[SHR:.*]] = llvm.lshr %[[ARG]], %[[CST0]] // CHECK: %[[TRUNC:.*]] = llvm.trunc %[[SHR]] : i64 to i32 - // CHECK: llvm.store %[[TRUNC]], %[[GEP]] + // CHECK: llvm.store %[[TRUNC]], %[[ALLOCA]] // CHECK: %[[SHR:.*]] = llvm.lshr %[[ARG]], %[[CST32]] : i64 // CHECK: %[[TRUNC:.*]] = llvm.trunc %[[SHR]] : i64 to i32 // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, i32)> @@ -225,11 +151,9 @@ llvm.func @coalesced_store_floats(%arg: i64) { // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (f32, f32)> %1 = llvm.alloca %0 x !llvm.struct<"foo", (f32, f32)> : (i32) -> !llvm.ptr - // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (f32, f32)> // CHECK: %[[SHR:.*]] = llvm.lshr %[[ARG]], %[[CST0]] // CHECK: %[[TRUNC:.*]] = llvm.trunc %[[SHR]] : i64 to i32 - // CHECK: %[[BIT_CAST:.*]] = llvm.bitcast %[[TRUNC]] : i32 to f32 - // CHECK: llvm.store %[[BIT_CAST]], %[[GEP]] + // CHECK: llvm.store %[[TRUNC]], %[[ALLOCA]] // CHECK: %[[SHR:.*]] = llvm.lshr %[[ARG]], %[[CST32]] : i64 // CHECK: %[[TRUNC:.*]] = llvm.trunc %[[SHR]] : i64 to i32 // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (f32, f32)> @@ -298,10 +222,9 @@ llvm.func @coalesced_store_packed_struct(%arg: i64) { // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", packed (i16, i32, i16)> %1 = llvm.alloca %0 x !llvm.struct<"foo", packed (i16, i32, i16)> : (i32) -> !llvm.ptr - // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", packed (i16, i32, i16)> // CHECK: %[[SHR:.*]] = llvm.lshr %[[ARG]], %[[CST0]] // CHECK: %[[TRUNC:.*]] = llvm.trunc %[[SHR]] : i64 to i16 - // CHECK: llvm.store %[[TRUNC]], %[[GEP]] + // CHECK: llvm.store %[[TRUNC]], %[[ALLOCA]] // CHECK: %[[SHR:.*]] = llvm.lshr %[[ARG]], %[[CST16]] // CHECK: %[[TRUNC:.*]] = llvm.trunc %[[SHR]] : i64 to i32 // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", packed (i16, i32, i16)> @@ -328,9 +251,8 @@ llvm.func @vector_write_split(%arg: vector<4xi32>) { // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (i32, i32, i32, i32)> %1 = llvm.alloca %0 x !llvm.struct<"foo", (i32, i32, i32, i32)> : (i32) -> !llvm.ptr - // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, i32, i32, i32)> // CHECK: %[[EXTRACT:.*]] = llvm.extractelement %[[ARG]][%[[CST0]] : i32] : vector<4xi32> - // CHECK: llvm.store %[[EXTRACT]], %[[GEP]] : i32, !llvm.ptr + // CHECK: llvm.store %[[EXTRACT]], %[[ALLOCA]] : i32, !llvm.ptr // CHECK: %[[EXTRACT:.*]] = llvm.extractelement %[[ARG]][%[[CST1]] : i32] : vector<4xi32> // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i32, i32, i32, i32)> @@ -405,36 +327,6 @@ llvm.func @vector_write_split_struct(%arg: vector<2xi64>) { // ----- -// CHECK-LABEL: llvm.func @type_consistent_vector_store -// CHECK-SAME: %[[ARG:.*]]: vector<4xi32> -llvm.func @type_consistent_vector_store(%arg: vector<4xi32>) { - %0 = llvm.mlir.constant(1 : i32) : i32 - // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (vector<4xi32>)> - %1 = llvm.alloca %0 x !llvm.struct<"foo", (vector<4xi32>)> : (i32) -> !llvm.ptr - // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (vector<4xi32>)> - // CHECK: llvm.store %[[ARG]], %[[GEP]] - llvm.store %arg, %1 : vector<4xi32>, !llvm.ptr - llvm.return -} - -// ----- - -// CHECK-LABEL: llvm.func @type_consistent_vector_store_other_type -// CHECK-SAME: %[[ARG:.*]]: vector<4xi32> -llvm.func @type_consistent_vector_store_other_type(%arg: vector<4xi32>) { - %0 = llvm.mlir.constant(1 : i32) : i32 - // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (vector<4xf32>)> - %1 = llvm.alloca %0 x !llvm.struct<"foo", (vector<4xf32>)> : (i32) -> !llvm.ptr - // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (vector<4xf32>)> - // CHECK: %[[BIT_CAST:.*]] = llvm.bitcast %[[ARG]] : vector<4xi32> to vector<4xf32> - // CHECK: llvm.store %[[BIT_CAST]], %[[GEP]] - llvm.store %arg, %1 : vector<4xi32>, !llvm.ptr - // CHECK-NOT: llvm.store %[[ARG]], %[[ALLOCA]] - llvm.return -} - -// ----- - // CHECK-LABEL: llvm.func @bitcast_insertion // CHECK-SAME: %[[ARG:.*]]: i32 llvm.func @bitcast_insertion(%arg: i32) { @@ -478,10 +370,9 @@ llvm.func @coalesced_store_ints_subaggregate(%arg: i64) { %3 = llvm.getelementptr %1[0, 1, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i64, struct<(i32, i32)>)> // CHECK: %[[TOP_GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i64, struct<(i32, i32)>)> - // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[TOP_GEP]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i32, i32)> // CHECK: %[[SHR:.*]] = llvm.lshr %[[ARG]], %[[CST0]] // CHECK: %[[TRUNC:.*]] = llvm.trunc %[[SHR]] : i64 to i32 - // CHECK: llvm.store %[[TRUNC]], %[[GEP]] + // CHECK: llvm.store %[[TRUNC]], %[[TOP_GEP]] // CHECK: %[[SHR:.*]] = llvm.lshr %[[ARG]], %[[CST32]] : i64 // CHECK: %[[TRUNC:.*]] = llvm.trunc %[[SHR]] : i64 to i32 // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[TOP_GEP]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i32, i32)> @@ -520,10 +411,9 @@ llvm.func @overlapping_int_aggregate_store(%arg: i64) { // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (i16, struct<(i16, i16, i16)>)> %1 = llvm.alloca %0 x !llvm.struct<"foo", (i16, struct<(i16, i16, i16)>)> : (i32) -> !llvm.ptr - // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i16, struct<(i16, i16, i16)>)> // CHECK: %[[SHR:.*]] = llvm.lshr %[[ARG]], %[[CST0]] // CHECK: %[[TRUNC:.*]] = llvm.trunc %[[SHR]] : i64 to i16 - // CHECK: llvm.store %[[TRUNC]], %[[GEP]] + // CHECK: llvm.store %[[TRUNC]], %[[ALLOCA]] // CHECK: %[[SHR:.*]] = llvm.lshr %[[ARG]], %[[CST16]] : i64 // CHECK: [[TRUNC:.*]] = llvm.trunc %[[SHR]] : i64 to i48 @@ -531,8 +421,7 @@ llvm.func @overlapping_int_aggregate_store(%arg: i64) { // Normal integer splitting of [[TRUNC]] follows: - // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[TOP_GEP]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i16, i16, i16)> - // CHECK: llvm.store %{{.*}}, %[[GEP]] + // CHECK: llvm.store %{{.*}}, %[[TOP_GEP]] // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[TOP_GEP]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i16, i16, i16)> // CHECK: llvm.store %{{.*}}, %[[GEP]] // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[TOP_GEP]][0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i16, i16, i16)> @@ -557,14 +446,12 @@ llvm.func @overlapping_vector_aggregate_store(%arg: vector<4 x i16>) { // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (i16, struct<(i16, i16, i16)>)> %1 = llvm.alloca %0 x !llvm.struct<"foo", (i16, struct<(i16, i16, i16)>)> : (i32) -> !llvm.ptr - // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i16, struct<(i16, i16, i16)>)> // CHECK: %[[EXTRACT:.*]] = llvm.extractelement %[[ARG]][%[[CST0]] : i32] - // CHECK: llvm.store %[[EXTRACT]], %[[GEP]] + // CHECK: llvm.store %[[EXTRACT]], %[[ALLOCA]] // CHECK: %[[EXTRACT:.*]] = llvm.extractelement %[[ARG]][%[[CST1]] : i32] // CHECK: %[[GEP0:.*]] = llvm.getelementptr %[[ALLOCA]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i16, struct<(i16, i16, i16)>)> - // CHECK: %[[GEP1:.*]] = llvm.getelementptr %[[GEP0]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i16, i16, i16)> - // CHECK: llvm.store %[[EXTRACT]], %[[GEP1]] + // CHECK: llvm.store %[[EXTRACT]], %[[GEP0]] // CHECK: %[[EXTRACT:.*]] = llvm.extractelement %[[ARG]][%[[CST2]] : i32] // CHECK: %[[GEP0:.*]] = llvm.getelementptr %[[ALLOCA]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i16, struct<(i16, i16, i16)>)> @@ -593,10 +480,9 @@ llvm.func @partially_overlapping_aggregate_store(%arg: i64) { // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.struct<"foo", (i16, struct<(i16, i16, i16, i16)>)> %1 = llvm.alloca %0 x !llvm.struct<"foo", (i16, struct<(i16, i16, i16, i16)>)> : (i32) -> !llvm.ptr - // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<"foo", (i16, struct<(i16, i16, i16, i16)>)> // CHECK: %[[SHR:.*]] = llvm.lshr %[[ARG]], %[[CST0]] // CHECK: %[[TRUNC:.*]] = llvm.trunc %[[SHR]] : i64 to i16 - // CHECK: llvm.store %[[TRUNC]], %[[GEP]] + // CHECK: llvm.store %[[TRUNC]], %[[ALLOCA]] // CHECK: %[[SHR:.*]] = llvm.lshr %[[ARG]], %[[CST16]] : i64 // CHECK: [[TRUNC:.*]] = llvm.trunc %[[SHR]] : i64 to i48 @@ -604,8 +490,7 @@ llvm.func @partially_overlapping_aggregate_store(%arg: i64) { // Normal integer splitting of [[TRUNC]] follows: - // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[TOP_GEP]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i16, i16, i16, i16)> - // CHECK: llvm.store %{{.*}}, %[[GEP]] + // CHECK: llvm.store %{{.*}}, %[[TOP_GEP]] // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[TOP_GEP]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i16, i16, i16, i16)> // CHECK: llvm.store %{{.*}}, %[[GEP]] // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[TOP_GEP]][0, 2] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(i16, i16, i16, i16)> @@ -651,10 +536,9 @@ llvm.func @coalesced_store_ints_array(%arg: i64) { // CHECK: %[[ALLOCA:.*]] = llvm.alloca %{{.*}} x !llvm.array<2 x i32> %1 = llvm.alloca %0 x !llvm.array<2 x i32> : (i32) -> !llvm.ptr - // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<2 x i32> // CHECK: %[[SHR:.*]] = llvm.lshr %[[ARG]], %[[CST0]] // CHECK: %[[TRUNC:.*]] = llvm.trunc %[[SHR]] : i64 to i32 - // CHECK: llvm.store %[[TRUNC]], %[[GEP]] + // CHECK: llvm.store %[[TRUNC]], %[[ALLOCA]] // CHECK: %[[SHR:.*]] = llvm.lshr %[[ARG]], %[[CST32]] : i64 // CHECK: %[[TRUNC:.*]] = llvm.trunc %[[SHR]] : i64 to i32 // CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 1] : (!llvm.ptr) -> !llvm.ptr, !llvm.array<2 x i32> diff --git a/mlir/test/Dialect/Linalg/data-layout-propagation.mlir b/mlir/test/Dialect/Linalg/data-layout-propagation.mlir index e036695a2ac9fd2eff1531ef35cd4221e0562682..79d61ab757e32722aaaf0fbe689d00f3532eee86 100644 --- a/mlir/test/Dialect/Linalg/data-layout-propagation.mlir +++ b/mlir/test/Dialect/Linalg/data-layout-propagation.mlir @@ -905,3 +905,163 @@ func.func @unpack_different_destination_shape(%arg0: tensor<1x1x1080x1920x16xi32 // CHECK-SAME: inner_dims_pos = [0] inner_tiles = [16] // CHECK-SAME: into %[[UNPACK_NEW_DEST]] // CHECK: return %[[UNPACK]] : tensor<16x540x960xi32> + +// ----- + +func.func @bubble_up_pack_through_collapse(%1: tensor<?x16x4xf32>, %dim : index) -> tensor<?x4x8x1xf32> { + %collapsed = tensor.collapse_shape %1 [[0, 1], [2]] : tensor<?x16x4xf32> into tensor<?x4xf32> + %2 = tensor.empty(%dim) : tensor<?x4x8x1xf32> + %pack = tensor.pack %collapsed outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [8, 1] into %2 : tensor<?x4xf32> -> tensor<?x4x8x1xf32> + func.return %pack : tensor<?x4x8x1xf32> +} +// CHECK-LABEL: func.func @bubble_up_pack_through_collapse +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]] +// CHECK: %[[C0:.+]] = arith.constant 0 : index +// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor<?x16x4xf32> +// CHECK: %[[EMPTY:.+]] = tensor.empty(%[[DIM]]) : tensor<?x2x4x8x1xf32> +// CHECK: %[[PACK:.+]] = tensor.pack %[[ARG0]] outer_dims_perm = [0, 1, 2] inner_dims_pos = [1, 2] inner_tiles = [8, 1] into %[[EMPTY]] : tensor<?x16x4xf32> -> tensor<?x2x4x8x1xf32> +// CHECK: %[[COLLAPSED:.+]] = tensor.collapse_shape %[[PACK]] {{\[}}[0, 1], [2], [3], [4]] : tensor<?x2x4x8x1xf32> into tensor<?x4x8x1xf32> +// CHECK: return %[[COLLAPSED]] : tensor<?x4x8x1xf32> + +// ----- + +func.func @bubble_up_permuted_pack_through_collapse(%1: tensor<4x192x16x256xf32>) -> tensor<4x32x3072x8x1xf32> { + %collapsed = tensor.collapse_shape %1 [[0], [1, 2], [3]] : tensor<4x192x16x256xf32> into tensor<4x3072x256xf32> + %2 = tensor.empty() : tensor<4x32x3072x8x1xf32> + %pack = tensor.pack %collapsed outer_dims_perm = [0, 2, 1] inner_dims_pos = [2, 1] inner_tiles = [8, 1] into %2 : tensor<4x3072x256xf32> -> tensor<4x32x3072x8x1xf32> + func.return %pack : tensor<4x32x3072x8x1xf32> +} +// CHECK-LABEL: func.func @bubble_up_permuted_pack_through_collapse +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<4x32x192x16x8x1xf32> +// CHECK: %[[PACK:.+]] = tensor.pack %[[ARG0]] outer_dims_perm = [0, 3, 1, 2] inner_dims_pos = [3, 2] inner_tiles = [8, 1] into %[[EMPTY]] : tensor<4x192x16x256xf32> -> tensor<4x32x192x16x8x1xf32> +// CHECK: %[[COLLAPSED:.+]] = tensor.collapse_shape %pack {{\[}}[0], [1], [2, 3], [4], [5]] : tensor<4x32x192x16x8x1xf32> into tensor<4x32x3072x8x1xf32> +// CHECK: return %[[COLLAPSED]] : tensor<4x32x3072x8x1xf32> + +// ----- + +func.func @bubble_up_pack_through_unit_collapse(%1: tensor<1x64x1x4xf32>) -> tensor<8x4x8x1xf32> { + %collapsed = tensor.collapse_shape %1 [[0, 1, 2], [3]] : tensor<1x64x1x4xf32> into tensor<64x4xf32> + %2 = tensor.empty() : tensor<8x4x8x1xf32> + %pack = tensor.pack %collapsed outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [8, 1] into %2 : tensor<64x4xf32> -> tensor<8x4x8x1xf32> + func.return %pack : tensor<8x4x8x1xf32> +} +// CHECK-LABEL: func.func @bubble_up_pack_through_unit_collapse +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<1x8x1x4x8x1xf32> +// CHECK: %[[PACK:.+]] = tensor.pack %[[ARG0]] outer_dims_perm = [0, 1, 2, 3] inner_dims_pos = [1, 3] inner_tiles = [8, 1] into %[[EMPTY]] : tensor<1x64x1x4xf32> -> tensor<1x8x1x4x8x1xf32> +// CHECK: %[[COLLAPSED:.+]] = tensor.collapse_shape %[[PACK]] {{\[}}[0, 1, 2], [3], [4], [5]] : tensor<1x8x1x4x8x1xf32> into tensor<8x4x8x1xf32> +// CHECK: return %[[COLLAPSED]] : tensor<8x4x8x1xf32> + +// ----- + +func.func @bubble_up_pack_through_collapse_on_outer_dims(%1: tensor<?x16x4xf32>, %dim : index) -> tensor<?x1x4xf32> { + %collapsed = tensor.collapse_shape %1 [[0, 1], [2]] : tensor<?x16x4xf32> into tensor<?x4xf32> + %2 = tensor.empty(%dim) : tensor<?x1x4xf32> + %pack = tensor.pack %collapsed outer_dims_perm = [0, 1] inner_dims_pos = [1] inner_tiles = [4] into %2 : tensor<?x4xf32> -> tensor<?x1x4xf32> + func.return %pack : tensor<?x1x4xf32> +} +// CHECK-LABEL: func.func @bubble_up_pack_through_collapse_on_outer_dims +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]] +// CHECK: %[[C0:.+]] = arith.constant 0 : index +// CHECK: %[[DIM:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor<?x16x4xf32> +// CHECK: %[[EMPTY:.+]] = tensor.empty(%[[DIM]]) : tensor<?x16x1x4xf32> +// CHECK: %[[PACK:.+]] = tensor.pack %[[ARG0]] outer_dims_perm = [0, 1, 2] inner_dims_pos = [2] inner_tiles = [4] into %[[EMPTY]] : tensor<?x16x4xf32> -> tensor<?x16x1x4xf32> +// CHECK: %[[COLLAPSED:.+]] = tensor.collapse_shape %[[PACK]] {{\[}}[0, 1], [2], [3]] : tensor<?x16x1x4xf32> into tensor<?x1x4xf32> +// CHECK: return %[[COLLAPSED]] : tensor<?x1x4xf32> + +// ----- + +func.func @no_bubble_up_pack_through_non_divisible_collapse(%1: tensor<3072x64x4xf32>) -> tensor<384x32x8x8xf32> { + %collapsed = tensor.collapse_shape %1 [[0], [1, 2]] : tensor<3072x64x4xf32> into tensor<3072x256xf32> + %2 = tensor.empty() : tensor<384x32x8x8xf32> + %pack = tensor.pack %collapsed outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %2 : tensor<3072x256xf32> -> tensor<384x32x8x8xf32> + func.return %pack : tensor<384x32x8x8xf32> +} +// CHECK-LABEL: func.func @no_bubble_up_pack_through_non_divisible_collapse +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK: %[[COLLAPSED:.+]] = tensor.collapse_shape %[[ARG0]] {{\[}}[0], [1, 2]] : tensor<3072x64x4xf32> into tensor<3072x256xf32> +// CHECK: %[[PACK:.+]] = tensor.pack %[[COLLAPSED]] +// CHECK: return %[[PACK]] : tensor<384x32x8x8xf32> + +// ----- + +func.func @push_down_unpack_through_expand(%5: tensor<?x32x8x8xf32>, %dim: index) -> tensor<?x256x256xf32> { + %6 = tensor.empty(%dim) : tensor<?x256xf32> + %unpack = tensor.unpack %5 outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %6 : tensor<?x32x8x8xf32> -> tensor<?x256xf32> + %expanded = tensor.expand_shape %unpack [[0, 1], [2]] : tensor<?x256xf32> into tensor<?x256x256xf32> + func.return %expanded : tensor<?x256x256xf32> +} +// CHECK-LABEL: func.func @push_down_unpack_through_expand +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]] +// CHECK: %[[C0:.+]] = arith.constant 0 : index +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2], [3], [4]] : tensor<?x32x8x8xf32> into tensor<?x32x32x8x8xf32> +// CHECK: %[[DIM:.+]] = tensor.dim %[[EXPANDED]], %[[C0]] : tensor<?x32x32x8x8xf32> +// CHECK: %[[EMPTY:.+]] = tensor.empty(%[[DIM]]) : tensor<?x256x256xf32> +// CHECK: %[[UNPACK:.+]] = tensor.unpack %[[EXPANDED:.+]] outer_dims_perm = [0, 1, 2] inner_dims_pos = [1, 2] inner_tiles = [8, 8] into %[[EMPTY]] : tensor<?x32x32x8x8xf32> -> tensor<?x256x256xf32> +// CHECK: return %[[UNPACK]] : tensor<?x256x256xf32> + +// ----- + +func.func @push_down_permuted_unpack_through_expand(%5: tensor<4x32x384x8x8xf32>) -> tensor<4x12x256x256xf32> { + %6 = tensor.empty() : tensor<4x3072x256xf32> + %unpack = tensor.unpack %5 outer_dims_perm = [0, 2, 1] inner_dims_pos = [2, 1] inner_tiles = [8, 8] into %6 : tensor<4x32x384x8x8xf32> -> tensor<4x3072x256xf32> + %expanded = tensor.expand_shape %unpack [[0], [1, 2], [3]] : tensor<4x3072x256xf32> into tensor<4x12x256x256xf32> + func.return %expanded : tensor<4x12x256x256xf32> +} +// CHECK-LABEL: @push_down_permuted_unpack_through_expand +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0], [1], [2, 3], [4], [5]] : tensor<4x32x384x8x8xf32> into tensor<4x32x12x32x8x8xf32> +// CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<4x12x256x256xf32> +// CHECK: %[[UNPACK:.+]] = tensor.unpack %[[EXPANDED]] outer_dims_perm = [0, 3, 1, 2] inner_dims_pos = [3, 2] inner_tiles = [8, 8] into %[[EMPTY]] : tensor<4x32x12x32x8x8xf32> -> tensor<4x12x256x256xf32> +// CHECK: return %[[UNPACK]] : tensor<4x12x256x256xf32> + +// ----- + +func.func @push_down_unpack_through_unit_expand(%5: tensor<6x32x8x8xf32>) -> tensor<3x16x1x256xf32> { + %6 = tensor.empty() : tensor<48x256xf32> + %unpack = tensor.unpack %5 outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %6 : tensor<6x32x8x8xf32> -> tensor<48x256xf32> + %expanded = tensor.expand_shape %unpack [[0, 1, 2], [3]] : tensor<48x256xf32> into tensor<3x16x1x256xf32> + func.return %expanded : tensor<3x16x1x256xf32> +} +// CHECK-LABEL: func.func @push_down_unpack_through_unit_expand +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1, 2], [3], [4], [5]] : tensor<6x32x8x8xf32> into tensor<3x2x1x32x8x8xf32> +// CHECK: %[[EMPTY:.+]] = tensor.empty() : tensor<3x16x1x256xf32> +// CHECK: %[[UNPACK:.+]] = tensor.unpack %[[EXPANDED]] outer_dims_perm = [0, 1, 2, 3] inner_dims_pos = [1, 3] inner_tiles = [8, 8] into %[[EMPTY]] : tensor<3x2x1x32x8x8xf32> -> tensor<3x16x1x256xf32> +// CHECK: return %[[UNPACK]] : tensor<3x16x1x256xf32> + +// ----- + +func.func @push_down_unpack_through_expand_on_outer_dims(%5: tensor<?x32x8xf32>, %dim: index) -> tensor<?x256x256xf32> { + %6 = tensor.empty(%dim) : tensor<?x256xf32> + %unpack = tensor.unpack %5 outer_dims_perm = [0, 1] inner_dims_pos = [1] inner_tiles = [8] into %6 : tensor<?x32x8xf32> -> tensor<?x256xf32> + %expanded = tensor.expand_shape %unpack [[0, 1], [2]] : tensor<?x256xf32> into tensor<?x256x256xf32> + func.return %expanded : tensor<?x256x256xf32> +} +// CHECK-LABEL: func.func @push_down_unpack_through_expand_on_outer_dims +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]] +// CHECK: %[[C0:.+]] = arith.constant 0 : index +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[ARG0]] {{\[}}[0, 1], [2], [3]] : tensor<?x32x8xf32> into tensor<?x256x32x8xf32> +// CHECK: %[[DIM:.+]] = tensor.dim %[[EXPANDED]], %[[C0]] : tensor<?x256x32x8xf32> +// CHECK: %[[EMPTY:.+]] = tensor.empty(%[[DIM]]) : tensor<?x256x256xf32> +// CHECK: %[[UNPACK:.+]] = tensor.unpack %[[EXPANDED:.+]] outer_dims_perm = [0, 1, 2] inner_dims_pos = [2] inner_tiles = [8] into %[[EMPTY]] : tensor<?x256x32x8xf32> -> tensor<?x256x256xf32> +// CHECK: return %[[UNPACK]] : tensor<?x256x256xf32> + +// ----- + +func.func @no_push_down_unpack_through_non_divisible_expand(%5: tensor<384x32x8x8xf32>) -> tensor<256x12x256xf32> { + %6 = tensor.empty() : tensor<3072x256xf32> + %unpack = tensor.unpack %5 outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %6 : tensor<384x32x8x8xf32> -> tensor<3072x256xf32> + %expanded = tensor.expand_shape %unpack [[0, 1], [2]] : tensor<3072x256xf32> into tensor<256x12x256xf32> + func.return %expanded : tensor<256x12x256xf32> +} +// CHECK-LABEL: func.func @no_push_down_unpack_through_non_divisible_expand +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] +// CHECK: %[[UNPACK:.+]] = tensor.unpack %[[ARG0]] +// CHECK: %[[EXPANDED:.+]] = tensor.expand_shape %[[UNPACK]] {{\[}}[0, 1], [2]] : tensor<3072x256xf32> into tensor<256x12x256xf32> +// CHECK: return %[[EXPANDED]] : tensor<256x12x256xf32> diff --git a/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir b/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir index f2c490b832076fb132b1132ca188b0eadc6b0a3d..c140b6abcc37a2c123e4b39cb135a609bfbd9666 100644 --- a/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir +++ b/mlir/test/Dialect/Linalg/drop-unit-extent-dims.mlir @@ -1033,3 +1033,23 @@ func.func @do_not_drop_non_constant_padding(%arg0: tensor<1x1x3x1x1xf32>, %pad: // CHECK-SLICES-LABEL: func @do_not_drop_non_constant_padding // CHECK-SLICES: tensor.pad %{{.*}} low[0, 1, 0, %c0, 0] high[0, 0, 0, %c0, 2] // CHECK-SLICES: } : tensor<1x1x3x1x1xf32> to tensor<1x2x3x1x3xf32> + +// ----- + +func.func @drop_known_unit_constant_low_high(%arg0: tensor<1x383x128xf32>) -> tensor<1x384x128xf32> { + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %cst = arith.constant 0.000000e+00 : f32 + %padded = tensor.pad %arg0 low[%c0, %c1, %c0] high[%c0, %c0, %c0] { + ^bb0(%arg1: index, %arg2: index, %arg3: index): + tensor.yield %cst : f32 + } : tensor<1x383x128xf32> to tensor<1x384x128xf32> + return %padded : tensor<1x384x128xf32> +} +// CHECK-LABEL: func @drop_known_unit_constant_low_high +// CHECK: %[[COLLAPSE:.+]] = tensor.collapse_shape +// CHECK-SAME: {{\[}}[0, 1], [2]] : tensor<1x383x128xf32> into tensor<383x128xf32> +// CHECK: %[[PADDED:.+]] = tensor.pad %[[COLLAPSE]] low[1, 0] high[0, 0] +// CHECK: } : tensor<383x128xf32> to tensor<384x128xf32> +// CHECK: tensor.expand_shape %[[PADDED]] +// CHECK-SAME: {{\[}}[0, 1], [2]] : tensor<384x128xf32> into tensor<1x384x128xf32> diff --git a/mlir/test/Dialect/Linalg/flatten-elementwise.mlir b/mlir/test/Dialect/Linalg/flatten-elementwise.mlir index 858c133dd536caebd0a24572e6149c79769808ab..5a27fe76b134113add71f942524316eaa97d6160 100644 --- a/mlir/test/Dialect/Linalg/flatten-elementwise.mlir +++ b/mlir/test/Dialect/Linalg/flatten-elementwise.mlir @@ -67,6 +67,27 @@ module attributes {transform.with_named_sequence} { // ----- +// CHECK-LABEL: func.func @map_already_flat( +// CHECK-SAME: %[[ARG0:[a-zA-Z0-9_]*]]: memref<32xf32> +// CHECK-SAME: %[[ARG1:[a-zA-Z0-9_]*]]: memref<32xf32> +// CHECK-SAME: %[[ARG2:[a-zA-Z0-9_]*]]: memref<32xf32> +// CHECK-NEXT: linalg.map { arith.addf } ins(%[[ARG0]], %[[ARG1]] : memref<32xf32>, memref<32xf32>) outs(%[[ARG2]] : memref<32xf32>) +func.func @map_already_flat(%arg0: memref<32xf32>, %arg1: memref<32xf32>, %arg2: memref<32xf32>) { + linalg.map {arith.addf} ins(%arg0, %arg1: memref<32xf32>, memref<32xf32>) outs(%arg2: memref<32xf32>) + return +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match interface{LinalgOp} in %arg1 : (!transform.any_op) -> !transform.any_op + %flattened = transform.structured.flatten_elementwise %0 + : (!transform.any_op) -> !transform.any_op + transform.yield + } +} + +// ----- + // CHECK: #[[$MAP0:.*]] = affine_map<(d0) -> (d0)> // CHECK-LABEL: func.func @generic // CHECK-SAME: %[[ARG0:[a-zA-Z0-9_]*]]: memref<32x7xf32> diff --git a/mlir/test/Dialect/Linalg/flatten-unsupported.mlir b/mlir/test/Dialect/Linalg/flatten-unsupported.mlir new file mode 100644 index 0000000000000000000000000000000000000000..499db4cfb3294d7f7da6d47946eb6e32375f0510 --- /dev/null +++ b/mlir/test/Dialect/Linalg/flatten-unsupported.mlir @@ -0,0 +1,33 @@ +// RUN: mlir-opt %s -transform-interpreter -split-input-file -verify-diagnostics + +func.func @non_elementwise(%arg0: memref<2x3xf32>, %arg1: memref<3x4xf32>, %arg2: memref<2x4xf32>) { + // expected-error @below {{only elementwise flattening is supported}} + linalg.matmul ins(%arg0, %arg1 : memref<2x3xf32>, memref<3x4xf32>) outs(%arg2: memref<2x4xf32>) + return +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match interface{LinalgOp} in %arg1 : (!transform.any_op) -> !transform.any_op + %flattened = transform.structured.flatten_elementwise %0 + : (!transform.any_op) -> !transform.any_op + transform.yield + } +} + +// ----- + +func.func @unsupported_memref(%arg0: memref<32x7xf32, strided<[7, 2]>>, %arg1: memref<32x7xf32, strided<[7, 2]>>, %arg2: memref<32x7xf32, strided<[7, 2]>>) { + // expected-error @below {{attempted to flatten, but failed}} + linalg.map {arith.addf} ins(%arg0, %arg1: memref<32x7xf32, strided<[7, 2]>>, memref<32x7xf32, strided<[7, 2]>>) outs(%arg2: memref<32x7xf32, strided<[7, 2]>>) + return +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match interface{LinalgOp} in %arg1 : (!transform.any_op) -> !transform.any_op + %flattened = transform.structured.flatten_elementwise %0 + : (!transform.any_op) -> !transform.any_op + transform.yield + } +} diff --git a/mlir/test/Dialect/Linalg/generalize-pad-tensor.mlir b/mlir/test/Dialect/Linalg/generalize-pad-tensor.mlir index ac0eb48fb379408e0596b551ce1a8a889506c64f..2beab31b613d544fc3d9e6f1281755d06ca90686 100644 --- a/mlir/test/Dialect/Linalg/generalize-pad-tensor.mlir +++ b/mlir/test/Dialect/Linalg/generalize-pad-tensor.mlir @@ -19,7 +19,6 @@ func.func @generalize_pad_tensor_static_shape(%arg0: tensor<1x28x28x1xf32>) -> t // CHECK-LABEL: func @generalize_pad_tensor_dynamic_shape( // CHECK-SAME: %[[IN:.*]]: tensor<4x?x2x?xf32>, // CHECK-SAME: %[[OFFSET:.*]]: index) -> tensor<4x?x?x?xf32> { -// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index // CHECK-DAG: %[[CST:.*]] = arith.constant 0.000000e+00 : f32 // CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index // CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index @@ -32,7 +31,7 @@ func.func @generalize_pad_tensor_static_shape(%arg0: tensor<1x28x28x1xf32>) -> t // CHECK: %[[FILL:.*]] = linalg.fill ins(%[[CST]] : f32) outs(%[[INIT]] : tensor<4x?x?x?xf32>) -> tensor<4x?x?x?xf32> // CHECK: %[[DIM1_1:.*]] = tensor.dim %[[IN]], %[[C1]] : tensor<4x?x2x?xf32> // CHECK: %[[DIM3_1:.*]] = tensor.dim %[[IN]], %[[C3]] : tensor<4x?x2x?xf32> -// CHECK: %[[PADDED:.*]] = tensor.insert_slice %[[IN]] into %[[FILL]]{{\[}}%[[C0]], %[[C0]], %[[OFFSET]], %[[C0]]] [4, %[[DIM1_1]], 2, %[[DIM3_1]]] [1, 1, 1, 1] : tensor<4x?x2x?xf32> into tensor<4x?x?x?xf32> +// CHECK: %[[PADDED:.*]] = tensor.insert_slice %[[IN]] into %[[FILL]][0, 0, %[[OFFSET]], 0] [4, %[[DIM1_1]], 2, %[[DIM3_1]]] [1, 1, 1, 1] : tensor<4x?x2x?xf32> into tensor<4x?x?x?xf32> // CHECK: return %[[PADDED]] : tensor<4x?x?x?xf32> // CHECK: } func.func @generalize_pad_tensor_dynamic_shape(%arg0: tensor<4x?x2x?xf32>, %arg1: index) -> tensor<4x?x?x?xf32> { diff --git a/mlir/test/Dialect/Linalg/one-shot-bufferize.mlir b/mlir/test/Dialect/Linalg/one-shot-bufferize.mlir index c69701b65e2064394de64319f5085670186a7310..9616a3e32a06486bfb05efecfe544ffea72b0eee 100644 --- a/mlir/test/Dialect/Linalg/one-shot-bufferize.mlir +++ b/mlir/test/Dialect/Linalg/one-shot-bufferize.mlir @@ -1,9 +1,9 @@ // RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries" -canonicalize -buffer-loop-hoisting -drop-equivalent-buffer-results -split-input-file | FileCheck %s // Run fuzzer with different seeds. -// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-fuzzer-seed=23 bufferize-function-boundaries" -split-input-file -o /dev/null -// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-fuzzer-seed=59 bufferize-function-boundaries" -split-input-file -o /dev/null -// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-fuzzer-seed=91 bufferize-function-boundaries" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=23 bufferize-function-boundaries" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=59 bufferize-function-boundaries" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=91 bufferize-function-boundaries" -split-input-file -o /dev/null // Test bufferization using memref types that have no layout map. // RUN: mlir-opt %s -one-shot-bufferize="unknown-type-conversion=identity-layout-map function-boundary-type-conversion=identity-layout-map bufferize-function-boundaries" -drop-equivalent-buffer-results -split-input-file | FileCheck %s --check-prefix=CHECK-NO-LAYOUT-MAP diff --git a/mlir/test/Dialect/Linalg/tile-to-forall.mlir b/mlir/test/Dialect/Linalg/tile-to-forall.mlir index abd807b3e4d3e19eb7dafbf480294ff76a8ab898..12e2dea5530b59c7526679816dcec4c217ee411c 100644 --- a/mlir/test/Dialect/Linalg/tile-to-forall.mlir +++ b/mlir/test/Dialect/Linalg/tile-to-forall.mlir @@ -586,3 +586,144 @@ module attributes {transform.with_named_sequence} { transform.yield } } + +// ----- + +#map = affine_map<(d0, d1) -> (d0, d1)> +#map1 = affine_map<(d0, d1) -> (d0)> + +func.func @tile_thread_safety1(%arg0: tensor<100x300xf32>, %arg1: tensor<100xf32>) -> tensor<100xf32> { + // expected-warning@below {{tiling is not thread safe at axis #1}} + %0 = linalg.generic {indexing_maps = [#map, #map1], iterator_types = ["parallel", "reduction"]} ins(%arg0 : tensor<100x300xf32>) outs(%arg1 : tensor<100xf32>) { + ^bb0(%in: f32, %out: f32): + %1 = arith.addf %in, %out : f32 + linalg.yield %1 : f32 + } -> tensor<100xf32> + return %0 : tensor<100xf32> +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["linalg.generic"]} in %arg0 : (!transform.any_op) -> !transform.any_op + %forall, %tiled_generic = transform.structured.tile_using_forall %0 num_threads [4, 2] + : (!transform.any_op) -> (!transform.any_op, !transform.any_op) + transform.yield + } +} + +// ----- + +#map = affine_map<(d0, d1, d2) -> (d0, d1, d2)> +#map1 = affine_map<(d0, d1, d2) -> (d1, d2)> + +func.func @tile_thread_safety2(%arg0: tensor<100x300x8xf32>, %arg1: tensor<300x8xf32>) -> tensor<300x8xf32> { + // expected-warning@below {{tiling is not thread safe at axis #0}} + %0 = linalg.generic {indexing_maps = [#map, #map1], iterator_types = ["reduction", "parallel", "parallel"]} ins(%arg0 : tensor<100x300x8xf32>) outs(%arg1 : tensor<300x8xf32>) { + ^bb0(%in: f32, %out: f32): + %1 = arith.addf %in, %out : f32 + linalg.yield %1 : f32 + } -> tensor<300x8xf32> + return %0 : tensor<300x8xf32> +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["linalg.generic"]} in %arg0 : (!transform.any_op) -> !transform.any_op + %forall, %tiled_generic = transform.structured.tile_using_forall %0 num_threads [8] + : (!transform.any_op) -> (!transform.any_op, !transform.any_op) + transform.yield + } +} + +// ----- + +#map = affine_map<(d0, d1, d2) -> (d0, d1, d2)> +#map1 = affine_map<(d0, d1, d2) -> (d0, d2)> + +func.func @tile_thread_safety3(%arg0: tensor<100x300x8xf32>, %arg1: tensor<100x8xf32>) -> tensor<100x8xf32> { + // expected-warning@below {{tiling is not thread safe at axis #1}} + %0 = linalg.generic {indexing_maps = [#map, #map1], iterator_types = ["parallel", "reduction", "parallel"]} ins(%arg0 : tensor<100x300x8xf32>) outs(%arg1 : tensor<100x8xf32>) { + ^bb0(%in: f32, %out: f32): + %1 = arith.addf %in, %out : f32 + linalg.yield %1 : f32 + } -> tensor<100x8xf32> + return %0 : tensor<100x8xf32> +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["linalg.generic"]} in %arg0 : (!transform.any_op) -> !transform.any_op + %forall, %tiled_generic = transform.structured.tile_using_forall %0 num_threads [8, 4, 2] + : (!transform.any_op) -> (!transform.any_op, !transform.any_op) + transform.yield + } +} + +// ----- + +#map = affine_map<(d0, d1, d2) -> (d0, d1, d2)> +#map1 = affine_map<(d0, d1, d2) -> (d0, d2)> +#map2 = affine_map<(d0, d1, d2) -> (d2)> + +func.func @tile_thread_safety4(%arg0: tensor<100x300x8xf32>, %arg1: tensor<100x8xf32>, %arg2 : tensor<8xf32>) -> (tensor<100x8xf32>, tensor<8xf32>) { + // expected-warning@+2 {{tiling is not thread safe at axis #0}} + // expected-warning@below {{tiling is not thread safe at axis #1}} + %0:2 = linalg.generic {indexing_maps = [#map, #map1, #map2], iterator_types = ["reduction", "reduction", "parallel"]} ins(%arg0 : tensor<100x300x8xf32>) outs(%arg1, %arg2 : tensor<100x8xf32>, tensor<8xf32>) { + ^bb0(%in: f32, %out1: f32, %out2: f32): + %1 = arith.addf %in, %out1 : f32 + %2 = arith.addf %in, %out2 : f32 + linalg.yield %1, %2 : f32, f32 + } -> (tensor<100x8xf32>, tensor<8xf32>) + return %0#0, %0#1 : tensor<100x8xf32>, tensor<8xf32> +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["linalg.generic"]} in %arg0 : (!transform.any_op) -> !transform.any_op + %forall, %tiled_generic = transform.structured.tile_using_forall %0 num_threads [8, 4, 2] + : (!transform.any_op) -> (!transform.any_op, !transform.any_op) + transform.yield + } +} + +// ----- + +#map = affine_map<(d0, d1) -> (d0, d1)> +#map1 = affine_map<(d0, d1) -> (d0)> + +func.func @tile_thread_safety5(%arg0: tensor<100x300xf32>, %arg1: tensor<100xf32>) -> tensor<100xf32> { + // expected-warning@below {{tiling is not thread safe at axis #1}} + %0 = linalg.generic {indexing_maps = [#map, #map1], iterator_types = ["parallel", "reduction"]} ins(%arg0 : tensor<100x300xf32>) outs(%arg1 : tensor<100xf32>) { + ^bb0(%in: f32, %out: f32): + %1 = arith.addf %in, %out : f32 + linalg.yield %1 : f32 + } -> tensor<100xf32> + return %0 : tensor<100xf32> +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["linalg.generic"]} in %arg0 : (!transform.any_op) -> !transform.any_op + %forall, %tiled_generic = transform.structured.tile_using_forall %0 tile_sizes [10, 1] + : (!transform.any_op) -> (!transform.any_op, !transform.any_op) + transform.yield + } +} + +// ----- + +func.func @tile_thread_safety6(%A: tensor<?x?xf32>, %B: tensor<?x?xf32>, %C: tensor<?x?xf32>) -> tensor<?x?xf32> { + // expected-warning@below {{tiling is not thread safe at axis #2}} + %0 = linalg.matmul ins(%A, %B : tensor<?x?xf32>, tensor<?x?xf32>) + outs(%C : tensor<?x?xf32>) -> (tensor<?x?xf32>) + return %0 : tensor<?x?xf32> +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["linalg.matmul"]} in %arg0 : (!transform.any_op) -> !transform.any_op + %forall, %tiled_generic = transform.structured.tile_using_forall %0 num_threads [2, 0, 8] + : (!transform.any_op) -> (!transform.any_op, !transform.any_op) + transform.yield + } +} diff --git a/mlir/test/Dialect/Linalg/transform-op-matmul-to-outerproduct.mlir b/mlir/test/Dialect/Linalg/transform-op-matmul-to-outerproduct.mlir index ee66073a9a4193573d8155c07b3fb3560bcb95e1..a1a0c413da0c1c13b08fd036823b3566fd2c0b56 100644 --- a/mlir/test/Dialect/Linalg/transform-op-matmul-to-outerproduct.mlir +++ b/mlir/test/Dialect/Linalg/transform-op-matmul-to-outerproduct.mlir @@ -1,38 +1,51 @@ // RUN: mlir-opt %s -transform-interpreter | FileCheck %s -func.func @outerproduct_matmul(%A: memref<3x3xf32>, %B: memref<3x3xf32>, %C: memref<3x3xf32>) { - linalg.matmul ins(%A, %B: memref<3x3xf32>, memref<3x3xf32>) +func.func @matmul_to_outerproduct(%A: memref<3x4xf32>, %B: memref<4x3xf32>, %C: memref<3x3xf32>) { + linalg.matmul ins(%A, %B: memref<3x4xf32>, memref<4x3xf32>) outs(%C: memref<3x3xf32>) return } -// CHECK-LABEL: func.func @outerproduct_matmul( -// CHECK-SAME: %[[VAL_0:.*]]: memref<3x3xf32>, %[[VAL_1:.*]]: memref<3x3xf32>, %[[VAL_2:.*]]: memref<3x3xf32>) { -// CHECK: %[[VAL_3:.*]] = arith.constant 0 : index -// CHECK: %[[VAL_4:.*]] = arith.constant 0.000000e+00 : f32 -// CHECK: %[[VAL_5:.*]] = vector.transfer_read %[[VAL_0]]{{\[}}%[[VAL_3]], %[[VAL_3]]], %[[VAL_4]] {in_bounds = [true, true]} : memref<3x3xf32>, vector<3x3xf32> -// CHECK: %[[VAL_6:.*]] = vector.transfer_read %[[VAL_1]]{{\[}}%[[VAL_3]], %[[VAL_3]]], %[[VAL_4]] {in_bounds = [true, true]} : memref<3x3xf32>, vector<3x3xf32> -// CHECK: %[[VAL_7:.*]] = vector.transfer_read %[[VAL_2]]{{\[}}%[[VAL_3]], %[[VAL_3]]], %[[VAL_4]] {in_bounds = [true, true]} : memref<3x3xf32>, vector<3x3xf32> -// CHECK: %[[VAL_8:.*]] = vector.transpose %[[VAL_5]], [1, 0] : vector<3x3xf32> to vector<3x3xf32> -// CHECK: %[[VAL_9:.*]] = vector.extract %[[VAL_8]][0] : vector<3xf32> from vector<3x3xf32> -// CHECK: %[[VAL_10:.*]] = vector.extract %[[VAL_6]][0] : vector<3xf32> from vector<3x3xf32> -// CHECK: %[[VAL_11:.*]] = vector.outerproduct %[[VAL_9]], %[[VAL_10]], %[[VAL_7]] {kind = #vector.kind<add>} : vector<3xf32>, vector<3xf32> -// CHECK: %[[VAL_12:.*]] = vector.extract %[[VAL_8]][1] : vector<3xf32> from vector<3x3xf32> -// CHECK: %[[VAL_13:.*]] = vector.extract %[[VAL_6]][1] : vector<3xf32> from vector<3x3xf32> -// CHECK: %[[VAL_14:.*]] = vector.outerproduct %[[VAL_12]], %[[VAL_13]], %[[VAL_11]] {kind = #vector.kind<add>} : vector<3xf32>, vector<3xf32> -// CHECK: %[[VAL_15:.*]] = vector.extract %[[VAL_8]][2] : vector<3xf32> from vector<3x3xf32> -// CHECK: %[[VAL_16:.*]] = vector.extract %[[VAL_6]][2] : vector<3xf32> from vector<3x3xf32> -// CHECK: %[[VAL_17:.*]] = vector.outerproduct %[[VAL_15]], %[[VAL_16]], %[[VAL_14]] {kind = #vector.kind<add>} : vector<3xf32>, vector<3xf32> -// CHECK: vector.transfer_write %[[VAL_17]], %[[VAL_2]]{{\[}}%[[VAL_3]], %[[VAL_3]]] {in_bounds = [true, true]} : vector<3x3xf32>, memref<3x3xf32> -// CHECK: return -// CHECK: } +// CHECK-LABEL: func.func @matmul_to_outerproduct( +// CHECK-SAME: %[[A:.*]]: memref<3x4xf32>, +// CHECK-SAME: %[[B:.*]]: memref<4x3xf32>, +// CHECK-SAME: %[[C:.*]]: memref<3x3xf32>) { +// CHECK: %[[VEC_A:.*]] = vector.transfer_read %[[A]] +// CHECK: %[[VEC_B:.*]] = vector.transfer_read %[[B]] +// CHECK: %[[VEC_C:.*]] = vector.transfer_read %[[C]] +// CHECK: %[[VEC_A_T:.*]] = vector.transpose %[[VEC_A]], [1, 0] : vector<3x4xf32> to vector<4x3xf32> +// CHECK: %[[A0:.*]] = vector.extract %[[VEC_A_T]][0] : vector<3xf32> from vector<4x3xf32> +// CHECK: %[[B0:.*]] = vector.extract %[[VEC_B]][0] : vector<3xf32> from vector<4x3xf32> +// CHECK: %[[OP_0:.*]] = vector.outerproduct %[[A0]], %[[B0]], %[[VEC_C]] +// CHECK: %[[A1:.*]] = vector.extract %[[VEC_A_T]][1] : vector<3xf32> from vector<4x3xf32> +// CHECK: %[[B1:.*]] = vector.extract %[[VEC_B]][1] : vector<3xf32> from vector<4x3xf32> +// CHECK: %[[OP_1:.*]] = vector.outerproduct %[[A1]], %[[B1]], %[[OP_0]] +// CHECK: %[[A_2:.*]] = vector.extract %[[VEC_A_T]][2] : vector<3xf32> from vector<4x3xf32> +// CHECK: %[[B_2:.*]] = vector.extract %[[VEC_B]][2] : vector<3xf32> from vector<4x3xf32> +// CHECK: %[[OP_2:.*]] = vector.outerproduct %[[A_2]], %[[B_2]], %[[OP_1]] +// CHECK: %[[A_3:.*]] = vector.extract %[[VEC_A_T]][3] : vector<3xf32> from vector<4x3xf32> +// CHECK: %[[B_3:.*]] = vector.extract %[[VEC_B]][3] : vector<3xf32> from vector<4x3xf32> +// CHECK: %[[RES:.*]] = vector.outerproduct %[[A_3]], %[[B_3]], %[[OP_2]] +// CHECK: vector.transfer_write %[[RES]], %[[C]]{{.*}} : vector<3x3xf32>, memref<3x3xf32> module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { - %0 = transform.structured.match ops{["linalg.matmul"]} in %arg1 : (!transform.any_op) -> !transform.any_op - %1 = transform.get_parent_op %0 {isolated_from_above} : (!transform.any_op) -> !transform.any_op - %2 = transform.structured.vectorize_children_and_apply_patterns %1 : (!transform.any_op) -> !transform.any_op - transform.apply_patterns to %2 { + transform.named_sequence @__transform_main(%module: !transform.any_op {transform.readonly}) { + %func = transform.structured.match ops{["func.func"]} in %module : (!transform.any_op) -> !transform.any_op + + // Vectorize: linalg.matmul -> vector.multi_reduction + %matmul = transform.structured.match ops{["linalg.matmul"]} in %func : (!transform.any_op) -> !transform.any_op + transform.structured.vectorize %matmul : !transform.any_op + + // vector.multi_reduction --> vector.contract + transform.apply_patterns to %func { + transform.apply_patterns.vector.reduction_to_contract + // Reduce the rank of xfer ops. This transform vector.contract to be more + // more matmul-like and to enable the lowering to outer product Ops. + transform.apply_patterns.vector.transfer_permutation_patterns + } : !transform.any_op + + // vector.contract --> vector.outerproduct + transform.apply_patterns to %func { transform.apply_patterns.vector.lower_contraction lowering_strategy = "outerproduct" } : !transform.any_op transform.yield diff --git a/mlir/test/Dialect/Linalg/vectorization-unsupported.mlir b/mlir/test/Dialect/Linalg/vectorization-unsupported.mlir index a1a52397386c970c7b54921ce3a2ab672c028bf1..9127eac5da9510916866976517255790e3825611 100644 --- a/mlir/test/Dialect/Linalg/vectorization-unsupported.mlir +++ b/mlir/test/Dialect/Linalg/vectorization-unsupported.mlir @@ -19,10 +19,49 @@ module attributes {transform.with_named_sequence} { // ----- -func.func @depthwise_conv1d_nwc_wc_dyn_ch_dim(%input: memref<3x5x?xf32>, %filter: memref<2x?xf32>, %output: memref<3x2x?xf32>) { +// Masked vectorisation of 1D depthwise CW convs is not yet supported + +func.func @depthwise_conv1d_ncw_cw(%input: memref<3x?x4xf32>, %filter: memref<?x1xf32>, %output: memref<3x?x4xf32>) { + // expected-error @+1 {{Attempted to vectorize, but failed}} + linalg.depthwise_conv_1d_ncw_cw + {dilations = dense<2> : tensor<1xi64>, strides = dense<1> : tensor<1xi64>} + ins(%input, %filter : memref<3x?x4xf32>, memref<?x1xf32>) + outs(%output : memref<3x?x4xf32>) + return +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["linalg.depthwise_conv_1d_ncw_cw"]} in %arg1 : (!transform.any_op) -> !transform.any_op + transform.structured.vectorize %0 vector_sizes [3, 4, 5, 1] : !transform.any_op + transform.yield + } +} + +// ----- + +func.func @depthwise_conv1d_nwc_wc_dyn_w_dim(%input: memref<3x?x4xf32>, %filter: memref<?x4xf32>, %output: memref<3x?x4xf32>) { // expected-error @+1 {{Attempted to vectorize, but failed}} linalg.depthwise_conv_1d_nwc_wc {dilations = dense<2> : tensor<1xi64>, strides = dense<1> : tensor<1xi64>} + ins(%input, %filter : memref<3x?x4xf32>, memref<?x4xf32>) + outs(%output : memref<3x?x4xf32>) + return +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["linalg.depthwise_conv_1d_nwc_wc"]} in %arg1 : (!transform.any_op) -> !transform.any_op + transform.structured.vectorize %0 vector_sizes [3, 2, 4, 2] : !transform.any_op + transform.yield + } +} + +// ----- + +func.func @depthwise_conv1d_nwc_wc_dyn_ch_dim(%input: memref<3x5x?xf32>, %filter: memref<2x?xf32>, %output: memref<3x2x?xf32>) { + // expected-error @+1 {{Attempted to vectorize, but failed}} + linalg.depthwise_conv_1d_nwc_wc ins(%input, %filter : memref<3x5x?xf32>, memref<2x?xf32>) outs(%output : memref<3x2x?xf32>) return @@ -41,7 +80,6 @@ module attributes {transform.with_named_sequence} { func.func @depthwise_conv1d_nwc_wc_dyn_w_dim(%input: memref<3x?x3xf32>, %filter: memref<2x3xf32>, %output: memref<3x?x3xf32>) { // expected-error @+1 {{Attempted to vectorize, but failed}} linalg.depthwise_conv_1d_nwc_wc - {dilations = dense<2> : tensor<1xi64>, strides = dense<1> : tensor<1xi64>} ins(%input, %filter : memref<3x?x3xf32>, memref<2x3xf32>) outs(%output : memref<3x?x3xf32>) return diff --git a/mlir/test/Dialect/Linalg/vectorize-conv-masked-and-scalable.mlir b/mlir/test/Dialect/Linalg/vectorize-conv-masked-and-scalable.mlir new file mode 100644 index 0000000000000000000000000000000000000000..84b556d80887c06d755e54f9067ba1003338e2d2 --- /dev/null +++ b/mlir/test/Dialect/Linalg/vectorize-conv-masked-and-scalable.mlir @@ -0,0 +1,185 @@ +// RUN: mlir-opt -split-input-file -transform-interpreter -cse %s | FileCheck %s + +func.func @depthwise_conv1d_nwc_wc_1x8x3xi8_tensor(%input: tensor<1x8x?xi8>, + %filter: tensor<1x?xi8>, + %output: tensor<1x8x?xi8>) -> (tensor<1x8x?xi8>) { + %res = linalg.depthwise_conv_1d_nwc_wc + {dilations = dense<1> : vector<1xi64>, + strides = dense<1> : vector<1xi64>} + ins(%input, %filter : tensor<1x8x?xi8>, tensor<1x?xi8>) + outs(%output : tensor<1x8x?xi8>) -> tensor<1x8x?xi8> + return %res : tensor<1x8x?xi8> +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["linalg.depthwise_conv_1d_nwc_wc"]} in %arg0 : (!transform.any_op) -> !transform.any_op + transform.structured.vectorize %0 vector_sizes [1, 8, 4, 1] : !transform.any_op + transform.yield + } +} + +// CHECK-LABEL: func.func @depthwise_conv1d_nwc_wc_1x8x3xi8_tensor( +// CHECK-SAME: %[[INPUT:.*]]: tensor<1x8x?xi8>, +// CHECK-SAME: %[[FILTER:.*]]: tensor<1x?xi8>, +// CHECK-SAME: %[[OUTPUT:.*]]: tensor<1x8x?xi8>) -> tensor<1x8x?xi8> { + +// CHECK: %[[C1:.*]] = arith.constant 1 : index +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[PAD:.*]] = arith.constant 0 : i8 + +/// Create a mask for the input tensor +// CHECK: %[[C2:.*]] = arith.constant 2 : index +// CHECK: %[[CH_DIM_IN:.*]] = tensor.dim %[[INPUT]], %[[C2]] : tensor<1x8x?xi8> +// CHECK: %[[C8:.*]] = arith.constant 8 : index +// CHECK: %[[MASK_IN:.*]] = vector.create_mask %[[C1]], %[[C8]], %[[CH_DIM_IN]] : vector<1x8x4xi1> +/// Read the input tensor +// CHECK: %[[VEC_IN:.*]] = vector.mask %[[MASK_IN]] { vector.transfer_read %[[INPUT]]{{\[}}%[[C0]], %[[C0]], %[[C0]]], %[[PAD]] : tensor<1x8x?xi8>, vector<1x8x4xi8> } : vector<1x8x4xi1> -> vector<1x8x4xi8> + +/// Create a mask for the filter tensor +// CHECK: %[[CH_DIM_FLT:.*]] = tensor.dim %[[FILTER]], %[[C1]] : tensor<1x?xi8> +// CHECK: %[[MASK_FLT:.*]] = vector.create_mask %[[C1]], %[[CH_DIM_FLT]] : vector<1x4xi1> +/// Read the filter tensor +// CHECK: %[[VEC_FLT:.*]] = vector.mask %[[MASK_FLT]] { vector.transfer_read %[[FILTER]]{{\[}}%[[C0]], %[[C0]]], %[[PAD]] : tensor<1x?xi8>, vector<1x4xi8> } : vector<1x4xi1> -> vector<1x4xi8> + +/// Create a mask for the output tensor +// CHECK: %[[CH_DIM_OUT:.*]] = tensor.dim %[[OUTPUT]], %[[C2]] : tensor<1x8x?xi8> +// CHECK: %[[MASK_OUT:.*]] = vector.create_mask %[[C1]], %[[C8]], %[[CH_DIM_OUT]] : vector<1x8x4xi1> +// CHECK: %[[VEC_OUT:.*]] = vector.mask %[[MASK_OUT]] { vector.transfer_read %[[OUTPUT]]{{\[}}%[[C0]], %[[C0]], %[[C0]]], %[[PAD]] : tensor<1x8x?xi8>, vector<1x8x4xi8> } : vector<1x8x4xi1> -> vector<1x8x4xi8> + +/// Convolution +// CHECK: %[[IN_1:.*]] = vector.extract_strided_slice %[[VEC_IN]] {offsets = [0, 0, 0], sizes = [1, 8, 4], strides = [1, 1, 1]} : vector<1x8x4xi8> to vector<1x8x4xi8> +// CHECK: %[[FLT_1:.*]] = vector.extract %[[VEC_FLT]][0] : vector<4xi8> from vector<1x4xi8> +// CHECK: %[[OUT_1:.*]] = vector.extract_strided_slice %[[VEC_OUT]] {offsets = [0, 0, 0], sizes = [1, 8, 4], strides = [1, 1, 1]} : vector<1x8x4xi8> to vector<1x8x4xi8> +// CHECK: %[[FLT_1_B:.*]] = vector.broadcast %[[FLT_1]] : vector<4xi8> to vector<1x8x4xi8> +// CHECK: %[[MULI:.*]] = arith.muli %[[IN_1]], %[[FLT_1_B]] : vector<1x8x4xi8> +// CHECK: %[[ADDI:.*]] = arith.addi %[[MULI]], %[[OUT_1]] : vector<1x8x4xi8> +// CHECK: %[[OUT_INS:.*]] = vector.insert_strided_slice %[[ADDI]], %[[VEC_OUT]] {offsets = [0, 0, 0], strides = [1, 1, 1]} : vector<1x8x4xi8> into vector<1x8x4xi8> +// CHECK: %[[OUT:.*]] = vector.mask %[[MASK_OUT]] { vector.transfer_write %[[OUT_INS]], %[[OUTPUT]]{{\[}}%[[C0]], %[[C0]], %[[C0]]] : vector<1x8x4xi8>, tensor<1x8x?xi8> } : vector<1x8x4xi1> -> tensor<1x8x?xi8> +// CHECK: return %[[OUT]] : tensor<1x8x?xi8> + +// ----- + +func.func @depthwise_conv1d_nwc_wc_1x8x3xi8_tensor_scalable( + %input: tensor<1x8x?xi8>, + %filter: tensor<1x?xi8>, + %output: tensor<1x8x?xi8>) -> (tensor<1x8x?xi8>) { + %res = linalg.depthwise_conv_1d_nwc_wc + {dilations = dense<1> : vector<1xi64>, + strides = dense<1> : vector<1xi64>} + ins(%input, %filter : tensor<1x8x?xi8>, tensor<1x?xi8>) + outs(%output : tensor<1x8x?xi8>) -> tensor<1x8x?xi8> + return %res : tensor<1x8x?xi8> +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["linalg.depthwise_conv_1d_nwc_wc"]} in %arg0 : (!transform.any_op) -> !transform.any_op + transform.structured.vectorize %0 vector_sizes [1, 8, [4], 1] : !transform.any_op + transform.yield + } +} + +// CHECK-LABEL: func.func @depthwise_conv1d_nwc_wc_1x8x3xi8_tensor_scalable( +// CHECK-SAME: %[[INPUT:.*]]: tensor<1x8x?xi8>, +// CHECK-SAME: %[[FILTER:.*]]: tensor<1x?xi8>, +// CHECK-SAME: %[[OUTPUT:.*]]: tensor<1x8x?xi8>) -> tensor<1x8x?xi8> { + +// CHECK: %[[C1:.*]] = arith.constant 1 : index +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[PAD:.*]] = arith.constant 0 : i8 + +/// Create a mask for the input tensor +// CHECK: %[[C2:.*]] = arith.constant 2 : index +// CHECK: %[[CH_DIM_IN:.*]] = tensor.dim %[[INPUT]], %[[C2]] : tensor<1x8x?xi8> +// CHECK: %[[C8:.*]] = arith.constant 8 : index +// CHECK: %[[MASK_IN:.*]] = vector.create_mask %[[C1]], %[[C8]], %[[CH_DIM_IN]] : vector<1x8x[4]xi1> +/// Read the input tensor +// CHECK: %[[VEC_IN:.*]] = vector.mask %[[MASK_IN]] { vector.transfer_read %[[INPUT]]{{\[}}%[[C0]], %[[C0]], %[[C0]]], %[[PAD]] : tensor<1x8x?xi8>, vector<1x8x[4]xi8> } : vector<1x8x[4]xi1> -> vector<1x8x[4]xi8> + +/// Create a mask for the filter tensor +// CHECK: %[[CH_DIM_FLT:.*]] = tensor.dim %[[FILTER]], %[[C1]] : tensor<1x?xi8> +// CHECK: %[[MASK_FLT:.*]] = vector.create_mask %[[C1]], %[[CH_DIM_FLT]] : vector<1x[4]xi1> +/// Read the filter tensor +// CHECK: %[[VEC_FLT:.*]] = vector.mask %[[MASK_FLT]] { vector.transfer_read %[[FILTER]]{{\[}}%[[C0]], %[[C0]]], %[[PAD]] : tensor<1x?xi8>, vector<1x[4]xi8> } : vector<1x[4]xi1> -> vector<1x[4]xi8> + +/// Create a mask for the output tensor +// CHECK: %[[CH_DIM_OUT:.*]] = tensor.dim %[[OUTPUT]], %[[C2]] : tensor<1x8x?xi8> +// CHECK: %[[MASK_OUT:.*]] = vector.create_mask %[[C1]], %[[C8]], %[[CH_DIM_OUT]] : vector<1x8x[4]xi1> +/// Read the output tensor +// CHECK: %[[VEC_OUT:.*]] = vector.mask %[[MASK_OUT]] { vector.transfer_read %[[OUTPUT]]{{\[}}%[[C0]], %[[C0]], %[[C0]]], %[[PAD]] : tensor<1x8x?xi8>, vector<1x8x[4]xi8> } : vector<1x8x[4]xi1> -> vector<1x8x[4]xi8> + +/// Convolution +// CHECK: %[[IN_1:.*]] = vector.extract_strided_slice %[[VEC_IN]] {offsets = [0, 0, 0], sizes = [1, 8, 4], strides = [1, 1, 1]} : vector<1x8x[4]xi8> to vector<1x8x[4]xi8> +// CHECK: %[[FLT_1:.*]] = vector.extract %[[VEC_FLT]][0] : vector<[4]xi8> from vector<1x[4]xi8> +// CHECK: %[[OUT_1:.*]] = vector.extract_strided_slice %[[VEC_OUT]] {offsets = [0, 0, 0], sizes = [1, 8, 4], strides = [1, 1, 1]} : vector<1x8x[4]xi8> to vector<1x8x[4]xi8> +// CHECK: %[[FLT_1_B:.*]] = vector.broadcast %[[FLT_1]] : vector<[4]xi8> to vector<1x8x[4]xi8> +// CHECK: %[[MULI:.*]] = arith.muli %[[IN_1]], %[[FLT_1_B]] : vector<1x8x[4]xi8> +// CHECK: %[[ADDI:.*]] = arith.addi %[[MULI]], %[[OUT_1]] : vector<1x8x[4]xi8> +// CHECK: %[[OUT_INS:.*]] = vector.insert_strided_slice %[[ADDI]], %[[VEC_OUT]] {offsets = [0, 0, 0], strides = [1, 1, 1]} : vector<1x8x[4]xi8> into vector<1x8x[4]xi8> +// CHECK: %[[OUT:.*]] = vector.mask %[[MASK_OUT]] { vector.transfer_write %[[OUT_INS]], %[[OUTPUT]]{{\[}}%[[C0]], %[[C0]], %[[C0]]] : vector<1x8x[4]xi8>, tensor<1x8x?xi8> } : vector<1x8x[4]xi1> -> tensor<1x8x?xi8> +// CHECK: return %[[OUT]] : tensor<1x8x?xi8> + +// ----- + +func.func @depthwise_conv1d_nwc_wc_3x5x4xf32_memref_dilation_2( + %input: memref<3x5x?xf32>, + %filter: memref<2x?xf32>, + %output: memref<3x2x?xf32>) { + linalg.depthwise_conv_1d_nwc_wc + {dilations = dense<2> : tensor<1xi64>, strides = dense<1> : tensor<1xi64>} + ins(%input, %filter : memref<3x5x?xf32>, memref<2x?xf32>) + outs(%output : memref<3x2x?xf32>) + return +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["linalg.depthwise_conv_1d_nwc_wc"]} in %arg0 : (!transform.any_op) -> !transform.any_op + transform.structured.vectorize %0 vector_sizes [3, 2, [4], 2] : !transform.any_op + transform.yield + } +} + +// CHECK-LABEL: func.func @depthwise_conv1d_nwc_wc_3x5x4xf32_memref_dilation_2( +// CHECK-SAME: %[[INPUT:.*]]: memref<3x5x?xf32>, +// CHECK-SAME: %[[FILTER:.*]]: memref<2x?xf32>, +// CHECK-SAME: %[[OUTPUT:.*]]: memref<3x2x?xf32>) { + +// CHECK: %[[C1:.*]] = arith.constant 1 : index +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[PAD:.*]] = arith.constant 0.000000e+00 : f32 +// CHECK: %[[C2:.*]] = arith.constant 2 : index + +/// Create a mask for the input tensor +// CHECK: %[[CH_DIM_IN:.*]] = memref.dim %[[INPUT]], %[[C2]] : memref<3x5x?xf32> +// CHECK: %[[C3:.*]] = arith.constant 3 : index +// CHECK: %[[C5:.*]] = arith.constant 5 : index +// CHECK: %[[MASK_IN:.*]] = vector.create_mask %[[C3]], %[[C5]], %[[CH_DIM_IN]] : vector<3x4x[4]xi1> +/// Read the input tensor +// CHECK: %[[VEC_IN:.*]] = vector.mask %[[MASK_IN]] { vector.transfer_read %[[INPUT]]{{\[}}%[[C0]], %[[C0]], %[[C0]]], %[[PAD]] : memref<3x5x?xf32>, vector<3x4x[4]xf32> } : vector<3x4x[4]xi1> -> vector<3x4x[4]xf32> + +/// Create a mask for the filter tensor +// CHECK: %[[CH_DIM_FLT:.*]] = memref.dim %[[FILTER]], %[[C1]] : memref<2x?xf32> +// CHECK: %[[MASK_FLT:.*]] = vector.create_mask %[[C2]], %[[CH_DIM_FLT]] : vector<2x[4]xi1> +/// Read the filter tensor +// CHECK: %[[VEC_FLT:.*]] = vector.mask %[[MASK_FLT]] { vector.transfer_read %[[FILTER]]{{\[}}%[[C0]], %[[C0]]], %[[PAD]] : memref<2x?xf32>, vector<2x[4]xf32> } : vector<2x[4]xi1> -> vector<2x[4]xf32> + +/// Create a mask for the output tensor +// CHECK: %[[CH_DIM_OUT:.*]] = memref.dim %[[OUTPUT]], %[[C2]] : memref<3x2x?xf32> +// CHECK: %[[MASK_OUT:.*]] = vector.create_mask %[[C3]], %[[C2]], %[[CH_DIM_OUT]] : vector<3x2x[4]xi1> +/// Read the output tensor +// CHECK: %[[VEC_OUT:.*]] = vector.mask %[[MASK_OUT]] { vector.transfer_read %[[OUTPUT]]{{\[}}%[[C0]], %[[C0]], %[[C0]]], %[[PAD]] : memref<3x2x?xf32>, vector<3x2x[4]xf32> } : vector<3x2x[4]xi1> -> vector<3x2x[4]xf32> + +/// Convolution +// CHECK: %[[IN_1:.*]] = vector.extract_strided_slice %[[VEC_IN]] {offsets = [0, 0, 0], sizes = [3, 2, 4], strides = [1, 1, 1]} : vector<3x4x[4]xf32> to vector<3x2x[4]xf32> +// CHECK: %[[IN_2:.*]] = vector.extract_strided_slice %[[VEC_IN]] {offsets = [0, 2, 0], sizes = [3, 2, 4], strides = [1, 1, 1]} : vector<3x4x[4]xf32> to vector<3x2x[4]xf32> +// CHECK: %[[FLT_1:.*]] = vector.extract %[[VEC_FLT]][0] : vector<[4]xf32> from vector<2x[4]xf32> +// CHECK: %[[FLT_2:.*]] = vector.extract %[[VEC_FLT]][1] : vector<[4]xf32> from vector<2x[4]xf32> +// CHECK: %[[OUT_1:.*]] = vector.extract_strided_slice %[[VEC_OUT]] {offsets = [0, 0, 0], sizes = [3, 2, 4], strides = [1, 1, 1]} : vector<3x2x[4]xf32> to vector<3x2x[4]xf32> +// CHECK: %[[FLT_1_B:.*]] = vector.broadcast %[[FLT_1]] : vector<[4]xf32> to vector<3x2x[4]xf32> +// CHECK: %[[FMA_1:.*]] = vector.fma %[[IN_1]], %[[FLT_1_B]], %[[OUT_1]] : vector<3x2x[4]xf32> +// CHECK: %[[FLT_2_B:.*]] = vector.broadcast %[[FLT_2]] : vector<[4]xf32> to vector<3x2x[4]xf32> +// CHECK: %[[FMA_2:.*]] = vector.fma %[[IN_2]], %[[FLT_2_B]], %[[FMA_1]] : vector<3x2x[4]xf32> +// CHECK: %[[OUT_INS:.*]] = vector.insert_strided_slice %[[FMA_2]], %[[VEC_OUT]] {offsets = [0, 0, 0], strides = [1, 1, 1]} : vector<3x2x[4]xf32> into vector<3x2x[4]xf32> +// CHECK: vector.mask %[[MASK_OUT]] { vector.transfer_write %[[OUT_INS]], %[[OUTPUT]]{{\[}}%[[C0]], %[[C0]], %[[C0]]] : vector<3x2x[4]xf32>, memref<3x2x?xf32> } : vector<3x2x[4]xi1> diff --git a/mlir/test/Dialect/MLProgram/inlining.mlir b/mlir/test/Dialect/MLProgram/inlining.mlir new file mode 100644 index 0000000000000000000000000000000000000000..ac3677e1b9288217e5632378f35c6928d4d69dee --- /dev/null +++ b/mlir/test/Dialect/MLProgram/inlining.mlir @@ -0,0 +1,19 @@ +// RUN: mlir-opt %s -inline | FileCheck %s + +// Verifies that regions with operations from the ml_program dialect can +// be inlined. + +ml_program.global private @global(dense<4> : tensor<4xi32>) : tensor<4xi32> + +// CHECK: @inline_into +func.func @inline_into() -> tensor<4xi32> { + // CHECK-NOT: @inline_from + // CHECK: ml_program.global_load_const + %0 = call @inline_from() : () -> tensor<4xi32> + return %0 : tensor<4xi32> +} + +func.func @inline_from() -> tensor<4xi32> { + %0 = ml_program.global_load_const @global : tensor<4xi32> + return %0 : tensor<4xi32> +} diff --git a/mlir/test/Dialect/Math/expand-math.mlir b/mlir/test/Dialect/Math/expand-math.mlir index 6ee65b085dad1b6d8f7236c51f3f2cbb4a43a680..bfcff27bd64eb003bcb31767b913d2ca327b49a1 100644 --- a/mlir/test/Dialect/Math/expand-math.mlir +++ b/mlir/test/Dialect/Math/expand-math.mlir @@ -7,19 +7,18 @@ func.func @tanh(%arg: f32) -> f32 { } // CHECK-DAG: %[[ZERO:.+]] = arith.constant 0.000000e+00 : f32 // CHECK-DAG: %[[ONE:.+]] = arith.constant 1.000000e+00 : f32 -// CHECK-DAG: %[[TWO:.+]] = arith.constant 2.000000e+00 : f32 -// CHECK: %[[DOUBLEDX:.+]] = arith.mulf %arg0, %[[TWO]] : f32 -// CHECK: %[[NEGDOUBLEDX:.+]] = arith.negf %[[DOUBLEDX]] : f32 +// CHECK-DAG: %[[TWO:.+]] = arith.constant -2.000000e+00 : f32 +// CHECK: %[[VAL0:.+]] = arith.cmpf olt, %arg0, %[[ZERO]] : f32 +// CHECK: %[[VAL1:.+]] = arith.uitofp %[[VAL0]] : i1 to f32 +// CHECK: %[[VAL2:.+]] = arith.mulf %[[VAL1]], %[[TWO]] : f32 +// CHECK: %[[SIGN:.+]] = arith.addf %[[VAL2]], %[[ONE]] : f32 +// CHECK: %[[POSX:.+]] = arith.mulf %[[SIGN]], %arg0 : f32 +// CHECK: %[[NEGDOUBLEDX:.+]] = arith.mulf %[[POSX]], %[[TWO]] : f32 // CHECK: %[[EXP1:.+]] = math.exp %[[NEGDOUBLEDX]] : f32 // CHECK: %[[DIVIDEND1:.+]] = arith.subf %[[ONE]], %[[EXP1]] : f32 // CHECK: %[[DIVISOR1:.+]] = arith.addf %[[EXP1]], %[[ONE]] : f32 -// CHECK: %[[RES1:.+]] = arith.divf %[[DIVIDEND1]], %[[DIVISOR1]] : f32 -// CHECK: %[[EXP2:.+]] = math.exp %[[DOUBLEDX]] : f32 -// CHECK: %[[DIVIDEND2:.+]] = arith.subf %[[EXP2]], %[[ONE]] : f32 -// CHECK: %[[DIVISOR2:.+]] = arith.addf %[[EXP2]], %[[ONE]] : f32 -// CHECK: %[[RES2:.+]] = arith.divf %[[DIVIDEND2]], %[[DIVISOR2]] : f32 -// CHECK: %[[COND:.+]] = arith.cmpf oge, %arg0, %[[ZERO]] : f32 -// CHECK: %[[RESULT:.+]] = arith.select %[[COND]], %[[RES1]], %[[RES2]] : f32 +// CHECK: %[[POSRES:.+]] = arith.divf %[[DIVIDEND1]], %[[DIVISOR1]] : f32 +// CHECK: %[[RESULT:.+]] = arith.mulf %[[SIGN]], %[[POSRES]] : f32 // CHECK: return %[[RESULT]] // ----- @@ -512,3 +511,102 @@ func.func @roundeven16(%arg: f16) -> f16 { // CHECK: %[[COPYSIGN:.*]] = math.copysign %[[RESULT]], %[[VAL_0]] : f16 // CHECK: return %[[COPYSIGN]] : f16 + +// ----- + +// CHECK-LABEL: func.func @math_fpowi_neg_odd_power +func.func @math_fpowi_neg_odd_power(%0 : tensor<8xf32>) -> tensor<8xf32> { + %1 = arith.constant dense<-3> : tensor<8xi64> + %2 = math.fpowi %0, %1 : tensor<8xf32>, tensor<8xi64> + return %2 : tensor<8xf32> +} +// CHECK-SAME: (%[[ARG0:.*]]: tensor<8xf32>) -> tensor<8xf32> { +// CHECK-DAG: %[[CST1:.*]] = arith.constant dense<1.000000e+00> : tensor<8xf32> +// CHECK-DAG: %[[CST0:.*]] = arith.constant dense<0.000000e+00> : tensor<8xf32> +// CHECK-DAG: %[[CSTNEG0:.*]] = arith.constant dense<-0.000000e+00> : tensor<8xf32> +// CHECK-DAG: %[[CSTINF:.*]] = arith.constant dense<0x7F800000> : tensor<8xf32> +// CHECK-DAG: %[[CSTNEGINF:.*]] = arith.constant dense<0xFF800000> : tensor<8xf32> +// CHECK: %[[SQ:.*]] = arith.mulf %[[ARG0]], %[[ARG0]] : tensor<8xf32> +// CHECK: %[[CUBE:.*]] = arith.mulf %[[SQ]], %[[ARG0]] : tensor<8xf32> +// CHECK: %[[CMP0:.*]] = arith.cmpf oeq, %[[CUBE]], %[[CST0]] : tensor<8xf32> +// CHECK: %[[CMPNEG0:.*]] = arith.cmpf oeq, %[[CUBE]], %[[CSTNEG0]] : tensor<8xf32> +// CHECK: %[[INV:.*]] = arith.divf %[[CST1]], %[[CUBE]] : tensor<8xf32> +// CHECK: %[[UB1:.*]] = arith.select %[[CMP0]], %[[CSTINF]], %[[INV]] : tensor<8xi1>, tensor<8xf32> +// CHECK: %[[UB2:.*]] = arith.select %[[CMPNEG0]], %[[CSTNEGINF]], %[[UB1]] : tensor<8xi1>, tensor<8xf32> +// CHECK: return %[[UB2]] : tensor<8xf32> + +// ----- + +// CHECK-LABEL: func.func @math_fpowi_neg_even_power +func.func @math_fpowi_neg_even_power(%0 : tensor<8xf32>) -> tensor<8xf32> { + %1 = arith.constant dense<-4> : tensor<8xi64> + %2 = math.fpowi %0, %1 : tensor<8xf32>, tensor<8xi64> + return %2 : tensor<8xf32> +} +// CHECK-SAME: (%[[ARG0:.*]]: tensor<8xf32>) -> tensor<8xf32> { +// CHECK-DAG: %[[CST1:.*]] = arith.constant dense<1.000000e+00> : tensor<8xf32> +// CHECK-DAG: %[[CST0:.*]] = arith.constant dense<0.000000e+00> : tensor<8xf32> +// CHECK-DAG: %[[CSTNEG0:.*]] = arith.constant dense<-0.000000e+00> : tensor<8xf32> +// CHECK-DAG: %[[CSTINF:.*]] = arith.constant dense<0x7F800000> : tensor<8xf32> +// CHECK-DAG: %[[CSTNEGINF:.*]] = arith.constant dense<0xFF800000> : tensor<8xf32> +// CHECK: %[[SQ:.*]] = arith.mulf %[[ARG0]], %[[ARG0]] : tensor<8xf32> +// CHECK: %[[PW4:.*]] = arith.mulf %[[SQ]], %[[SQ]] : tensor<8xf32> +// CHECK: %[[CMP0:.*]] = arith.cmpf oeq, %[[PW4]], %[[CST0]] : tensor<8xf32> +// CHECK: %[[CMPNEG0:.*]] = arith.cmpf oeq, %[[PW4]], %[[CSTNEG0]] : tensor<8xf32> +// CHECK: %[[INV:.*]] = arith.divf %[[CST1]], %[[PW4]] : tensor<8xf32> +// CHECK: %[[UB1:.*]] = arith.select %[[CMP0]], %[[CSTINF]], %[[INV]] : tensor<8xi1>, tensor<8xf32> +// CHECK: %[[UB2:.*]] = arith.select %[[CMPNEG0]], %[[CSTNEGINF]], %[[UB1]] : tensor<8xi1>, tensor<8xf32> +// CHECK: return %[[UB2]] : tensor<8xf32> + +// ----- + +// CHECK-LABEL: func.func @math_fpowi_pos_odd_power +func.func @math_fpowi_pos_odd_power(%0 : tensor<8xf32>) -> tensor<8xf32> { + %1 = arith.constant dense<5> : tensor<8xi64> + %2 = math.fpowi %0, %1 : tensor<8xf32>, tensor<8xi64> + return %2 : tensor<8xf32> +} +// CHECK-SAME: (%[[ARG0:.*]]: tensor<8xf32>) -> tensor<8xf32> { +// CHECK: %[[SQ:.*]] = arith.mulf %[[ARG0]], %[[ARG0]] : tensor<8xf32> +// CHECK: %[[PW4:.*]] = arith.mulf %[[SQ]], %[[SQ]] : tensor<8xf32> +// CHECK: %[[PW5:.*]] = arith.mulf %[[PW4]], %[[ARG0]] : tensor<8xf32> +// CHECK: return %[[PW5]] : tensor<8xf32> + +// ----- + +// CHECK-LABEL: func.func @math_fpowi_pos_even_power +func.func @math_fpowi_pos_even_power(%0 : tensor<8xf32>) -> tensor<8xf32> { + %1 = arith.constant dense<4> : tensor<8xi64> + %2 = math.fpowi %0, %1 : tensor<8xf32>, tensor<8xi64> + return %2 : tensor<8xf32> +} +// CHECK-SAME: (%[[ARG0:.*]]: tensor<8xf32>) -> tensor<8xf32> { +// CHECK: %[[SQ:.*]] = arith.mulf %[[ARG0]], %[[ARG0]] : tensor<8xf32> +// CHECK: %[[PW4:.*]] = arith.mulf %[[SQ]], %[[SQ]] : tensor<8xf32> +// CHECK: return %[[PW4]] : tensor<8xf32> + +// ----- + +// CHECK-LABEL: func.func @math_fpowi_even_scalar +func.func @math_fpowi_even_scalar(%0 : f32) -> f32 { + %pow = arith.constant 2 : i64 + %2 = math.fpowi %0, %pow : f32, i64 + return %2 : f32 +} +// CHECK-SAME: (%[[ARG0:.*]]: f32) -> f32 { +// CHECK: %[[SQ:.*]] = arith.mulf %[[ARG0]], %[[ARG0]] : f32 +// CHECK: return %[[SQ]] : f32 + +// ----- + +// CHECK-LABEL: func.func @math_fpowi_scalar_zero +func.func @math_fpowi_scalar_zero(%0 : f32) -> f32 { + %pow = arith.constant 0 : i64 + %2 = math.fpowi %0, %pow : f32, i64 + return %2 : f32 +} +// CHECK-SAME: (%[[ARG0:.*]]: f32) -> f32 { +// CHECK: %[[RET:.*]] = arith.constant 1.000000e+00 : f32 +// CHECK: return %[[RET]] : f32 + +// ----- diff --git a/mlir/test/Dialect/Math/polynomial-approximation.mlir b/mlir/test/Dialect/Math/polynomial-approximation.mlir index 834a7dc0af66d636df64c33c832a3a1c723552c6..93ecd67f14dd3d85a189cef6186cb36de818d367 100644 --- a/mlir/test/Dialect/Math/polynomial-approximation.mlir +++ b/mlir/test/Dialect/Math/polynomial-approximation.mlir @@ -94,6 +94,20 @@ func.func @erf_vector(%arg0: vector<8xf32>) -> vector<8xf32> { return %0 : vector<8xf32> } +// CHECK-LABEL: func @erf_scalable_vector( +// CHECK-SAME: %[[arg0:.*]]: vector<[8]xf32>) -> vector<[8]xf32> { +// CHECK: %[[zero:.*]] = arith.constant dense<0.000000e+00> : vector<[8]xf32> +// CHECK-NOT: erf +// CHECK-NOT: vector<8xf32> +// CHECK-COUNT-20: select {{.*}} : vector<[8]xi1>, vector<[8]xf32> +// CHECK: %[[res:.*]] = arith.select {{.*}} : vector<[8]xi1>, vector<[8]xf32> +// CHECK: return %[[res]] : vector<[8]xf32> +// CHECK: } +func.func @erf_scalable_vector(%arg0: vector<[8]xf32>) -> vector<[8]xf32> { + %0 = math.erf %arg0 : vector<[8]xf32> + return %0 : vector<[8]xf32> +} + // CHECK-LABEL: func @exp_scalar( // CHECK-SAME: %[[VAL_0:.*]]: f32) -> f32 { // CHECK-DAG: %[[VAL_1:.*]] = arith.constant 5.000000e-01 : f32 @@ -151,6 +165,17 @@ func.func @exp_vector(%arg0: vector<8xf32>) -> vector<8xf32> { return %0 : vector<8xf32> } +// CHECK-LABEL: func @exp_scalable_vector +// CHECK-NOT: math.exp +// CHECK-NOT: vector<8xf32> +// CHECK-COUNT-46: vector<[8]x{{(i32)|(f32)}}> +// CHECK-NOT: vector<8xf32> +// CHECK-NOT: math.exp +func.func @exp_scalable_vector(%arg0: vector<[8]xf32>) -> vector<[8]xf32> { + %0 = math.exp %arg0 : vector<[8]xf32> + return %0 : vector<[8]xf32> +} + // CHECK-LABEL: func @expm1_scalar( // CHECK-SAME: %[[X:.*]]: f32) -> f32 { // CHECK-DAG: %[[VAL_1:.*]] = arith.constant 1.000000e+00 : f32 @@ -277,6 +302,22 @@ func.func @expm1_vector(%arg0: vector<8x8xf32>) -> vector<8x8xf32> { return %0 : vector<8x8xf32> } +// CHECK-LABEL: func @expm1_scalable_vector( +// CHECK-SAME: %{{.*}}: vector<8x[8]xf32>) -> vector<8x[8]xf32> { +// CHECK-NOT: vector<8x8xf32> +// CHECK-NOT: exp +// CHECK-NOT: log +// CHECK-NOT: expm1 +// CHECK-COUNT-127: vector<8x[8]x{{(i32)|(f32)|(i1)}}> +// CHECK-NOT: vector<8x8xf32> +// CHECK-NOT: exp +// CHECK-NOT: log +// CHECK-NOT: expm1 +func.func @expm1_scalable_vector(%arg0: vector<8x[8]xf32>) -> vector<8x[8]xf32> { + %0 = math.expm1 %arg0 : vector<8x[8]xf32> + return %0 : vector<8x[8]xf32> +} + // CHECK-LABEL: func @log_scalar( // CHECK-SAME: %[[X:.*]]: f32) -> f32 { // CHECK-DAG: %[[VAL_1:.*]] = arith.constant 0.000000e+00 : f32 @@ -357,6 +398,18 @@ func.func @log_vector(%arg0: vector<8xf32>) -> vector<8xf32> { return %0 : vector<8xf32> } +// CHECK-LABEL: func @log_scalable_vector( +// CHECK-SAME: %{{.*}}: vector<[8]xf32>) -> vector<[8]xf32> { +// CHECK: %[[CST_LN2:.*]] = arith.constant dense<0.693147182> : vector<[8]xf32> +// CHECK-COUNT-5: select {{.*}} : vector<[8]xi1>, vector<[8]xf32> +// CHECK: %[[VAL_71:.*]] = arith.select {{.*}} : vector<[8]xi1>, vector<[8]xf32> +// CHECK: return %[[VAL_71]] : vector<[8]xf32> +// CHECK: } +func.func @log_scalable_vector(%arg0: vector<[8]xf32>) -> vector<[8]xf32> { + %0 = math.log %arg0 : vector<[8]xf32> + return %0 : vector<[8]xf32> +} + // CHECK-LABEL: func @log2_scalar( // CHECK-SAME: %[[VAL_0:.*]]: f32) -> f32 { // CHECK: %[[CST_LOG2E:.*]] = arith.constant 1.44269502 : f32 @@ -381,6 +434,18 @@ func.func @log2_vector(%arg0: vector<8xf32>) -> vector<8xf32> { return %0 : vector<8xf32> } +// CHECK-LABEL: func @log2_scalable_vector( +// CHECK-SAME: %{{.*}}: vector<[8]xf32>) -> vector<[8]xf32> { +// CHECK: %[[CST_LOG2E:.*]] = arith.constant dense<1.44269502> : vector<[8]xf32> +// CHECK-COUNT-5: select {{.*}} : vector<[8]xi1>, vector<[8]xf32> +// CHECK: %[[VAL_71:.*]] = arith.select {{.*}} : vector<[8]xi1>, vector<[8]xf32> +// CHECK: return %[[VAL_71]] : vector<[8]xf32> +// CHECK: } +func.func @log2_scalable_vector(%arg0: vector<[8]xf32>) -> vector<[8]xf32> { + %0 = math.log2 %arg0 : vector<[8]xf32> + return %0 : vector<[8]xf32> +} + // CHECK-LABEL: func @log1p_scalar( // CHECK-SAME: %[[X:.*]]: f32) -> f32 { // CHECK: %[[CST_ONE:.*]] = arith.constant 1.000000e+00 : f32 @@ -414,6 +479,17 @@ func.func @log1p_vector(%arg0: vector<8xf32>) -> vector<8xf32> { return %0 : vector<8xf32> } +// CHECK-LABEL: func @log1p_scalable_vector( +// CHECK-SAME: %[[VAL_0:.*]]: vector<[8]xf32>) -> vector<[8]xf32> { +// CHECK: %[[CST_ONE:.*]] = arith.constant dense<1.000000e+00> : vector<[8]xf32> +// CHECK-COUNT-6: select {{.*}} : vector<[8]xi1>, vector<[8]xf32> +// CHECK: %[[VAL_79:.*]] = arith.select {{.*}} : vector<[8]xi1>, vector<[8]xf32> +// CHECK: return %[[VAL_79]] : vector<[8]xf32> +// CHECK: } +func.func @log1p_scalable_vector(%arg0: vector<[8]xf32>) -> vector<[8]xf32> { + %0 = math.log1p %arg0 : vector<[8]xf32> + return %0 : vector<[8]xf32> +} // CHECK-LABEL: func @tanh_scalar( // CHECK-SAME: %[[VAL_0:.*]]: f32) -> f32 { @@ -470,6 +546,19 @@ func.func @tanh_vector(%arg0: vector<8xf32>) -> vector<8xf32> { return %0 : vector<8xf32> } +// CHECK-LABEL: func @tanh_scalable_vector( +// CHECK-SAME: %[[VAL_0:.*]]: vector<[8]xf32>) -> vector<[8]xf32> { +// CHECK: %[[VAL_1:.*]] = arith.constant dense<-7.99881172> : vector<[8]xf32> +// CHECK-NOT: tanh +// CHECK-COUNT-2: select {{.*}} : vector<[8]xi1>, vector<[8]xf32> +// CHECK: %[[VAL_33:.*]] = arith.select {{.*}} : vector<[8]xi1>, vector<[8]xf32> +// CHECK: return %[[VAL_33]] : vector<[8]xf32> +// CHECK: } +func.func @tanh_scalable_vector(%arg0: vector<[8]xf32>) -> vector<[8]xf32> { + %0 = math.tanh %arg0 : vector<[8]xf32> + return %0 : vector<[8]xf32> +} + // We only approximate rsqrt for vectors and when the AVX2 option is enabled. // CHECK-LABEL: func @rsqrt_scalar // AVX2-LABEL: func @rsqrt_scalar diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir index d9261b89e24e3ac304c61f40c0f0ce006287f365..a00383cf44057c3cf311f95364c55bb1054439c4 100644 --- a/mlir/test/Dialect/OpenMP/invalid.mlir +++ b/mlir/test/Dialect/OpenMP/invalid.mlir @@ -338,7 +338,7 @@ func.func @omp_simdloop_pretty_simdlen_safelen(%lb : index, %ub : index, %step : // ----- // expected-error @below {{op expects initializer region with one argument of the reduction type}} -omp.reduction.declare @add_f32 : f64 +omp.declare_reduction @add_f32 : f64 init { ^bb0(%arg: f32): %0 = arith.constant 0.0 : f32 @@ -353,7 +353,7 @@ combiner { // ----- // expected-error @below {{expects initializer region to yield a value of the reduction type}} -omp.reduction.declare @add_f32 : f32 +omp.declare_reduction @add_f32 : f32 init { ^bb0(%arg: f32): %0 = arith.constant 0.0 : f64 @@ -368,7 +368,7 @@ combiner { // ----- // expected-error @below {{expects reduction region with two arguments of the reduction type}} -omp.reduction.declare @add_f32 : f32 +omp.declare_reduction @add_f32 : f32 init { ^bb0(%arg: f32): %0 = arith.constant 0.0 : f32 @@ -383,7 +383,7 @@ combiner { // ----- // expected-error @below {{expects reduction region to yield a value of the reduction type}} -omp.reduction.declare @add_f32 : f32 +omp.declare_reduction @add_f32 : f32 init { ^bb0(%arg: f32): %0 = arith.constant 0.0 : f32 @@ -399,7 +399,7 @@ combiner { // ----- // expected-error @below {{expects atomic reduction region with two arguments of the same type}} -omp.reduction.declare @add_f32 : f32 +omp.declare_reduction @add_f32 : f32 init { ^bb0(%arg: f32): %0 = arith.constant 0.0 : f32 @@ -418,7 +418,7 @@ atomic { // ----- // expected-error @below {{expects atomic reduction region arguments to be accumulators containing the reduction type}} -omp.reduction.declare @add_f32 : f32 +omp.declare_reduction @add_f32 : f32 init { ^bb0(%arg: f32): %0 = arith.constant 0.0 : f32 @@ -453,7 +453,7 @@ func.func @foo(%lb : index, %ub : index, %step : index) { // ----- -omp.reduction.declare @add_f32 : f32 +omp.declare_reduction @add_f32 : f32 init { ^bb0(%arg: f32): %0 = arith.constant 0.0 : f32 @@ -481,7 +481,7 @@ func.func @foo(%lb : index, %ub : index, %step : index) { // ----- -omp.reduction.declare @add_f32 : f32 +omp.declare_reduction @add_f32 : f32 init { ^bb0(%arg: f32): %0 = arith.constant 0.0 : f32 @@ -543,7 +543,7 @@ func.func @omp_ordered1(%arg1 : i32, %arg2 : i32, %arg3 : i32) -> () { omp.wsloop ordered(1) for (%0) : i32 = (%arg1) to (%arg2) step (%arg3) { // expected-error @below {{ordered region must be closely nested inside a worksharing-loop region with an ordered clause without parameter present}} - omp.ordered_region { + omp.ordered.region { omp.terminator } omp.yield @@ -556,7 +556,7 @@ func.func @omp_ordered1(%arg1 : i32, %arg2 : i32, %arg3 : i32) -> () { func.func @omp_ordered2(%arg1 : i32, %arg2 : i32, %arg3 : i32) -> () { omp.wsloop for (%0) : i32 = (%arg1) to (%arg2) step (%arg3) { // expected-error @below {{ordered region must be closely nested inside a worksharing-loop region with an ordered clause without parameter present}} - omp.ordered_region { + omp.ordered.region { omp.terminator } omp.yield @@ -1339,7 +1339,7 @@ func.func @omp_task(%ptr: !llvm.ptr) { // ----- -omp.reduction.declare @add_f32 : f32 +omp.declare_reduction @add_f32 : f32 init { ^bb0(%arg: f32): %0 = arith.constant 0.0 : f32 @@ -1363,7 +1363,7 @@ func.func @omp_task(%ptr: !llvm.ptr) { // ----- -omp.reduction.declare @add_i32 : i32 +omp.declare_reduction @add_i32 : i32 init { ^bb0(%arg: i32): %0 = arith.constant 0 : i32 @@ -1474,7 +1474,7 @@ func.func @omp_cancel5() -> () { func.func @omp_cancellationpoint() { omp.sections { // expected-error @below {{cancellation point parallel must appear inside a parallel region}} - omp.cancellationpoint cancellation_construct_type(parallel) + omp.cancellation_point cancellation_construct_type(parallel) // CHECK: omp.terminator omp.terminator } @@ -1486,7 +1486,7 @@ func.func @omp_cancellationpoint() { func.func @omp_cancellationpoint1() { omp.parallel { // expected-error @below {{cancellation point sections must appear inside a sections region}} - omp.cancellationpoint cancellation_construct_type(sections) + omp.cancellation_point cancellation_construct_type(sections) // CHECK: omp.terminator omp.terminator } @@ -1498,7 +1498,7 @@ func.func @omp_cancellationpoint1() { func.func @omp_cancellationpoint2() { omp.sections { // expected-error @below {{cancellation point loop must appear inside a worksharing-loop region}} - omp.cancellationpoint cancellation_construct_type(loop) + omp.cancellation_point cancellation_construct_type(loop) // CHECK: omp.terminator omp.terminator } @@ -1571,7 +1571,7 @@ func.func @taskloop(%lb: i32, %ub: i32, %step: i32) { // ----- -omp.reduction.declare @add_f32 : f32 +omp.declare_reduction @add_f32 : f32 init { ^bb0(%arg: f32): %0 = arith.constant 0.0 : f32 @@ -1596,7 +1596,7 @@ func.func @taskloop(%lb: i32, %ub: i32, %step: i32) { // ----- -omp.reduction.declare @add_f32 : f32 +omp.declare_reduction @add_f32 : f32 init { ^bb0(%arg: f32): %0 = arith.constant 0.0 : f32 @@ -1642,7 +1642,7 @@ func.func @omp_threadprivate() { // ----- func.func @omp_target(%map1: memref<?xi32>) { - %mapv = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(delete) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(delete) capture(ByRef) -> memref<?xi32> {name = ""} // expected-error @below {{to, from, tofrom and alloc map types are permitted}} omp.target map_entries(%mapv -> %arg0: memref<?xi32>) { ^bb0(%arg0: memref<?xi32>): @@ -1653,7 +1653,7 @@ func.func @omp_target(%map1: memref<?xi32>) { // ----- func.func @omp_target_data(%map1: memref<?xi32>) { - %mapv = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(delete) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(delete) capture(ByRef) -> memref<?xi32> {name = ""} // expected-error @below {{to, from, tofrom and alloc map types are permitted}} omp.target_data map_entries(%mapv : memref<?xi32>){} return @@ -1670,7 +1670,7 @@ func.func @omp_target_data() { // ----- func.func @omp_target_enter_data(%map1: memref<?xi32>) { - %mapv = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32> {name = ""} // expected-error @below {{to and alloc map types are permitted}} omp.target_enter_data map_entries(%mapv : memref<?xi32>){} return @@ -1679,7 +1679,7 @@ func.func @omp_target_enter_data(%map1: memref<?xi32>) { // ----- func.func @omp_target_enter_data_depend(%a: memref<?xi32>) { - %0 = omp.map_info var_ptr(%a: memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> + %0 = omp.map.info var_ptr(%a: memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> // expected-error @below {{op expected as many depend values as depend variables}} omp.target_enter_data map_entries(%0: memref<?xi32> ) {operandSegmentSizes = array<i32: 0, 0, 1, 0>} return @@ -1688,7 +1688,7 @@ func.func @omp_target_enter_data_depend(%a: memref<?xi32>) { // ----- func.func @omp_target_exit_data(%map1: memref<?xi32>) { - %mapv = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> {name = ""} // expected-error @below {{from, release and delete map types are permitted}} omp.target_exit_data map_entries(%mapv : memref<?xi32>){} return @@ -1697,7 +1697,7 @@ func.func @omp_target_exit_data(%map1: memref<?xi32>) { // ----- func.func @omp_target_exit_data_depend(%a: memref<?xi32>) { - %0 = omp.map_info var_ptr(%a: memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32> + %0 = omp.map.info var_ptr(%a: memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32> // expected-error @below {{op expected as many depend values as depend variables}} omp.target_exit_data map_entries(%0: memref<?xi32> ) {operandSegmentSizes = array<i32: 0, 0, 1, 0>} return @@ -1706,71 +1706,71 @@ func.func @omp_target_exit_data_depend(%a: memref<?xi32>) { // ----- func.func @omp_target_update_invalid_motion_type(%map1 : memref<?xi32>) { - %mapv = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""} // expected-error @below {{at least one of to or from map types must be specified, other map types are not permitted}} - omp.target_update_data motion_entries(%mapv : memref<?xi32>) + omp.target_update motion_entries(%mapv : memref<?xi32>) return } // ----- func.func @omp_target_update_invalid_motion_type_2(%map1 : memref<?xi32>) { - %mapv = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(delete) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(delete) capture(ByRef) -> memref<?xi32> {name = ""} // expected-error @below {{at least one of to or from map types must be specified, other map types are not permitted}} - omp.target_update_data motion_entries(%mapv : memref<?xi32>) + omp.target_update motion_entries(%mapv : memref<?xi32>) return } // ----- func.func @omp_target_update_invalid_motion_modifier(%map1 : memref<?xi32>) { - %mapv = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(always, to) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(always, to) capture(ByRef) -> memref<?xi32> {name = ""} // expected-error @below {{present, mapper and iterator map type modifiers are permitted}} - omp.target_update_data motion_entries(%mapv : memref<?xi32>) + omp.target_update motion_entries(%mapv : memref<?xi32>) return } // ----- func.func @omp_target_update_invalid_motion_modifier_2(%map1 : memref<?xi32>) { - %mapv = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(close, to) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(close, to) capture(ByRef) -> memref<?xi32> {name = ""} // expected-error @below {{present, mapper and iterator map type modifiers are permitted}} - omp.target_update_data motion_entries(%mapv : memref<?xi32>) + omp.target_update motion_entries(%mapv : memref<?xi32>) return } // ----- func.func @omp_target_update_invalid_motion_modifier_3(%map1 : memref<?xi32>) { - %mapv = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(implicit, to) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(implicit, to) capture(ByRef) -> memref<?xi32> {name = ""} // expected-error @below {{present, mapper and iterator map type modifiers are permitted}} - omp.target_update_data motion_entries(%mapv : memref<?xi32>) + omp.target_update motion_entries(%mapv : memref<?xi32>) return } // ----- func.func @omp_target_update_invalid_motion_modifier_4(%map1 : memref<?xi32>) { - %mapv = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(implicit, tofrom) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(implicit, tofrom) capture(ByRef) -> memref<?xi32> {name = ""} // expected-error @below {{either to or from map types can be specified, not both}} - omp.target_update_data motion_entries(%mapv : memref<?xi32>) + omp.target_update motion_entries(%mapv : memref<?xi32>) return } // ----- func.func @omp_target_update_invalid_motion_modifier_5(%map1 : memref<?xi32>) { - %mapv = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> {name = ""} - %mapv2 = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv2 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32> {name = ""} // expected-error @below {{either to or from map types can be specified, not both}} - omp.target_update_data motion_entries(%mapv, %mapv2 : memref<?xi32>, memref<?xi32>) + omp.target_update motion_entries(%mapv, %mapv2 : memref<?xi32>, memref<?xi32>) return } llvm.mlir.global internal @_QFsubEx() : i32 @@ -1778,9 +1778,9 @@ llvm.mlir.global internal @_QFsubEx() : i32 // ----- func.func @omp_target_update_data_depend(%a: memref<?xi32>) { - %0 = omp.map_info var_ptr(%a: memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> + %0 = omp.map.info var_ptr(%a: memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> // expected-error @below {{op expected as many depend values as depend variables}} - omp.target_update_data motion_entries(%0: memref<?xi32> ) {operandSegmentSizes = array<i32: 0, 0, 1, 0>} + omp.target_update motion_entries(%0: memref<?xi32> ) {operandSegmentSizes = array<i32: 0, 0, 1, 0>} return } diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir index 211ff0ff9272ec4fd871a5e5191826f1f30ffa02..30ce77423005ac91c7780aa1d301c4e634b03d4c 100644 --- a/mlir/test/Dialect/OpenMP/ops.mlir +++ b/mlir/test/Dialect/OpenMP/ops.mlir @@ -520,20 +520,20 @@ func.func @omp_target(%if_cond : i1, %device : si32, %num_threads : i32, %map1: }) {nowait, operandSegmentSizes = array<i32: 1,1,1,0,0>} : ( i1, si32, i32 ) -> () // Test with optional map clause. - // CHECK: %[[MAP_A:.*]] = omp.map_info var_ptr(%[[VAL_1:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""} - // CHECK: %[[MAP_B:.*]] = omp.map_info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""} + // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_1:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""} + // CHECK: %[[MAP_B:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""} // CHECK: omp.target map_entries(%[[MAP_A]] -> {{.*}}, %[[MAP_B]] -> {{.*}} : memref<?xi32>, memref<?xi32>) { - %mapv1 = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""} - %mapv2 = omp.map_info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv1 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv2 = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""} omp.target map_entries(%mapv1 -> %arg0, %mapv2 -> %arg1 : memref<?xi32>, memref<?xi32>) { ^bb0(%arg0: memref<?xi32>, %arg1: memref<?xi32>): omp.terminator } - // CHECK: %[[MAP_C:.*]] = omp.map_info var_ptr(%[[VAL_1:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> {name = ""} - // CHECK: %[[MAP_D:.*]] = omp.map_info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(always, from) capture(ByRef) -> memref<?xi32> {name = ""} + // CHECK: %[[MAP_C:.*]] = omp.map.info var_ptr(%[[VAL_1:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> {name = ""} + // CHECK: %[[MAP_D:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(always, from) capture(ByRef) -> memref<?xi32> {name = ""} // CHECK: omp.target map_entries(%[[MAP_C]] -> {{.*}}, %[[MAP_D]] -> {{.*}} : memref<?xi32>, memref<?xi32>) { - %mapv3 = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> {name = ""} - %mapv4 = omp.map_info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(always, from) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv3 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv4 = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(always, from) capture(ByRef) -> memref<?xi32> {name = ""} omp.target map_entries(%mapv3 -> %arg0, %mapv4 -> %arg1 : memref<?xi32>, memref<?xi32>) { ^bb0(%arg0: memref<?xi32>, %arg1: memref<?xi32>): omp.terminator @@ -546,31 +546,31 @@ func.func @omp_target(%if_cond : i1, %device : si32, %num_threads : i32, %map1: // CHECK-LABEL: omp_target_data func.func @omp_target_data (%if_cond : i1, %device : si32, %device_ptr: memref<i32>, %device_addr: memref<?xi32>, %map1: memref<?xi32>, %map2: memref<?xi32>) -> () { - // CHECK: %[[MAP_A:.*]] = omp.map_info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(always, from) capture(ByRef) -> memref<?xi32> {name = ""} + // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(always, from) capture(ByRef) -> memref<?xi32> {name = ""} // CHECK: omp.target_data if(%[[VAL_0:.*]] : i1) device(%[[VAL_1:.*]] : si32) map_entries(%[[MAP_A]] : memref<?xi32>) - %mapv1 = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(always, from) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv1 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(always, from) capture(ByRef) -> memref<?xi32> {name = ""} omp.target_data if(%if_cond : i1) device(%device : si32) map_entries(%mapv1 : memref<?xi32>){} - // CHECK: %[[MAP_A:.*]] = omp.map_info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(close, present, to) capture(ByRef) -> memref<?xi32> {name = ""} + // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(close, present, to) capture(ByRef) -> memref<?xi32> {name = ""} // CHECK: omp.target_data map_entries(%[[MAP_A]] : memref<?xi32>) use_device_ptr(%[[VAL_3:.*]] : memref<i32>) use_device_addr(%[[VAL_4:.*]] : memref<?xi32>) - %mapv2 = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(close, present, to) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv2 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(close, present, to) capture(ByRef) -> memref<?xi32> {name = ""} omp.target_data map_entries(%mapv2 : memref<?xi32>) use_device_ptr(%device_ptr : memref<i32>) use_device_addr(%device_addr : memref<?xi32>) {} - // CHECK: %[[MAP_A:.*]] = omp.map_info var_ptr(%[[VAL_1:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""} - // CHECK: %[[MAP_B:.*]] = omp.map_info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""} + // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_1:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""} + // CHECK: %[[MAP_B:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""} // CHECK: omp.target_data map_entries(%[[MAP_A]], %[[MAP_B]] : memref<?xi32>, memref<?xi32>) - %mapv3 = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""} - %mapv4 = omp.map_info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv3 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv4 = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""} omp.target_data map_entries(%mapv3, %mapv4 : memref<?xi32>, memref<?xi32>) {} - // CHECK: %[[MAP_A:.*]] = omp.map_info var_ptr(%[[VAL_3:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""} + // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_3:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""} // CHECK: omp.target_enter_data if(%[[VAL_0:.*]] : i1) device(%[[VAL_1:.*]] : si32) nowait map_entries(%[[MAP_A]] : memref<?xi32>) - %mapv5 = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv5 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""} omp.target_enter_data if(%if_cond : i1) device(%device : si32) nowait map_entries(%mapv5 : memref<?xi32>) - // CHECK: %[[MAP_A:.*]] = omp.map_info var_ptr(%[[VAL_3:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""} + // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_3:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""} // CHECK: omp.target_exit_data if(%[[VAL_0:.*]] : i1) device(%[[VAL_1:.*]] : si32) nowait map_entries(%[[MAP_A]] : memref<?xi32>) - %mapv6 = omp.map_info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv6 = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""} omp.target_exit_data if(%if_cond : i1) device(%device : si32) nowait map_entries(%mapv6 : memref<?xi32>) return @@ -591,7 +591,7 @@ func.func @omp_target_pretty(%if_cond : i1, %device : si32, %num_threads : i32) return } -// CHECK: omp.reduction.declare +// CHECK: omp.declare_reduction // CHECK-LABEL: @add_f32 // CHECK: : f32 // CHECK: init @@ -603,7 +603,7 @@ func.func @omp_target_pretty(%if_cond : i1, %device : si32, %num_threads : i32) // CHECK: atomic // CHECK: ^{{.+}}(%{{.+}}: !llvm.ptr, %{{.+}}: !llvm.ptr): // CHECK: omp.yield -omp.reduction.declare @add_f32 : f32 +omp.declare_reduction @add_f32 : f32 init { ^bb0(%arg: f32): %0 = arith.constant 0.0 : f32 @@ -773,9 +773,9 @@ func.func @sections_reduction() { return } -// CHECK: omp.reduction.declare +// CHECK: omp.declare_reduction // CHECK-LABEL: @add2_f32 -omp.reduction.declare @add2_f32 : f32 +omp.declare_reduction @add2_f32 : f32 // CHECK: init init { ^bb0(%arg: f32): @@ -904,15 +904,15 @@ func.func @omp_critical() -> () { func.func @omp_ordered(%arg1 : i32, %arg2 : i32, %arg3 : i32, %vec0 : i64, %vec1 : i64, %vec2 : i64, %vec3 : i64) -> () { - // CHECK: omp.ordered_region - omp.ordered_region { + // CHECK: omp.ordered.region + omp.ordered.region { // CHECK: omp.terminator omp.terminator } omp.wsloop ordered(0) for (%0) : i32 = (%arg1) to (%arg2) step (%arg3) { - omp.ordered_region { + omp.ordered.region { omp.terminator } omp.yield @@ -1815,8 +1815,8 @@ func.func @omp_cancel_sections() -> () { func.func @omp_cancellationpoint_parallel() -> () { omp.parallel { - // CHECK: omp.cancellationpoint cancellation_construct_type(parallel) - omp.cancellationpoint cancellation_construct_type(parallel) + // CHECK: omp.cancellation_point cancellation_construct_type(parallel) + omp.cancellation_point cancellation_construct_type(parallel) // CHECK: omp.cancel cancellation_construct_type(parallel) omp.cancel cancellation_construct_type(parallel) omp.terminator @@ -1827,8 +1827,8 @@ func.func @omp_cancellationpoint_parallel() -> () { func.func @omp_cancellationpoint_wsloop(%lb : index, %ub : index, %step : index) { omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) { - // CHECK: omp.cancellationpoint cancellation_construct_type(loop) - omp.cancellationpoint cancellation_construct_type(loop) + // CHECK: omp.cancellation_point cancellation_construct_type(loop) + omp.cancellation_point cancellation_construct_type(loop) // CHECK: omp.cancel cancellation_construct_type(loop) omp.cancel cancellation_construct_type(loop) // CHECK: omp.terminator @@ -1840,8 +1840,8 @@ func.func @omp_cancellationpoint_wsloop(%lb : index, %ub : index, %step : index) func.func @omp_cancellationpoint_sections() -> () { omp.sections { omp.section { - // CHECK: omp.cancellationpoint cancellation_construct_type(sections) - omp.cancellationpoint cancellation_construct_type(sections) + // CHECK: omp.cancellation_point cancellation_construct_type(sections) + omp.cancellation_point cancellation_construct_type(sections) // CHECK: omp.cancel cancellation_construct_type(sections) omp.cancel cancellation_construct_type(sections) omp.terminator @@ -2088,7 +2088,7 @@ func.func @opaque_pointers_atomic_rwu(%v: !llvm.ptr, %x: !llvm.ptr) { // CHECK-LABEL: @opaque_pointers_reduction // CHECK: atomic { // CHECK-NEXT: ^{{[[:alnum:]]+}}(%{{.*}}: !llvm.ptr, %{{.*}}: !llvm.ptr): -omp.reduction.declare @opaque_pointers_reduction : f32 +omp.declare_reduction @opaque_pointers_reduction : f32 init { ^bb0(%arg: f32): %0 = arith.constant 0.0 : f32 @@ -2113,27 +2113,27 @@ func.func @omp_targets_with_map_bounds(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> () // CHECK: %[[C_01:.*]] = llvm.mlir.constant(1 : index) : i64 // CHECK: %[[C_02:.*]] = llvm.mlir.constant(1 : index) : i64 // CHECK: %[[C_03:.*]] = llvm.mlir.constant(1 : index) : i64 - // CHECK: %[[BOUNDS0:.*]] = omp.bounds lower_bound(%[[C_01]] : i64) upper_bound(%[[C_00]] : i64) stride(%[[C_02]] : i64) start_idx(%[[C_03]] : i64) - // CHECK: %[[MAP0:.*]] = omp.map_info var_ptr(%[[ARG0]] : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS0]]) -> !llvm.ptr {name = ""} + // CHECK: %[[BOUNDS0:.*]] = omp.map.bounds lower_bound(%[[C_01]] : i64) upper_bound(%[[C_00]] : i64) stride(%[[C_02]] : i64) start_idx(%[[C_03]] : i64) + // CHECK: %[[MAP0:.*]] = omp.map.info var_ptr(%[[ARG0]] : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS0]]) -> !llvm.ptr {name = ""} %0 = llvm.mlir.constant(4 : index) : i64 %1 = llvm.mlir.constant(1 : index) : i64 %2 = llvm.mlir.constant(1 : index) : i64 %3 = llvm.mlir.constant(1 : index) : i64 - %4 = omp.bounds lower_bound(%1 : i64) upper_bound(%0 : i64) stride(%2 : i64) start_idx(%3 : i64) + %4 = omp.map.bounds lower_bound(%1 : i64) upper_bound(%0 : i64) stride(%2 : i64) start_idx(%3 : i64) - %mapv1 = omp.map_info var_ptr(%arg0 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%4) -> !llvm.ptr {name = ""} + %mapv1 = omp.map.info var_ptr(%arg0 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%4) -> !llvm.ptr {name = ""} // CHECK: %[[C_10:.*]] = llvm.mlir.constant(9 : index) : i64 // CHECK: %[[C_11:.*]] = llvm.mlir.constant(1 : index) : i64 // CHECK: %[[C_12:.*]] = llvm.mlir.constant(2 : index) : i64 // CHECK: %[[C_13:.*]] = llvm.mlir.constant(2 : index) : i64 - // CHECK: %[[BOUNDS1:.*]] = omp.bounds lower_bound(%[[C_11]] : i64) upper_bound(%[[C_10]] : i64) stride(%[[C_12]] : i64) start_idx(%[[C_13]] : i64) - // CHECK: %[[MAP1:.*]] = omp.map_info var_ptr(%[[ARG1]] : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByCopy) bounds(%[[BOUNDS1]]) -> !llvm.ptr {name = ""} + // CHECK: %[[BOUNDS1:.*]] = omp.map.bounds lower_bound(%[[C_11]] : i64) upper_bound(%[[C_10]] : i64) stride(%[[C_12]] : i64) start_idx(%[[C_13]] : i64) + // CHECK: %[[MAP1:.*]] = omp.map.info var_ptr(%[[ARG1]] : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByCopy) bounds(%[[BOUNDS1]]) -> !llvm.ptr {name = ""} %6 = llvm.mlir.constant(9 : index) : i64 %7 = llvm.mlir.constant(1 : index) : i64 %8 = llvm.mlir.constant(2 : index) : i64 %9 = llvm.mlir.constant(2 : index) : i64 - %10 = omp.bounds lower_bound(%7 : i64) upper_bound(%6 : i64) stride(%8 : i64) start_idx(%9 : i64) - %mapv2 = omp.map_info var_ptr(%arg1 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByCopy) bounds(%10) -> !llvm.ptr {name = ""} + %10 = omp.map.bounds lower_bound(%7 : i64) upper_bound(%6 : i64) stride(%8 : i64) start_idx(%9 : i64) + %mapv2 = omp.map.info var_ptr(%arg1 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByCopy) bounds(%10) -> !llvm.ptr {name = ""} // CHECK: omp.target map_entries(%[[MAP0]] -> {{.*}}, %[[MAP1]] -> {{.*}} : !llvm.ptr, !llvm.ptr) omp.target map_entries(%mapv1 -> %arg2, %mapv2 -> %arg3 : !llvm.ptr, !llvm.ptr) { @@ -2144,14 +2144,14 @@ func.func @omp_targets_with_map_bounds(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> () // CHECK: omp.target_data map_entries(%[[MAP0]], %[[MAP1]] : !llvm.ptr, !llvm.ptr) omp.target_data map_entries(%mapv1, %mapv2 : !llvm.ptr, !llvm.ptr){} - // CHECK: %[[MAP2:.*]] = omp.map_info var_ptr(%[[ARG0]] : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(VLAType) bounds(%[[BOUNDS0]]) -> !llvm.ptr {name = ""} + // CHECK: %[[MAP2:.*]] = omp.map.info var_ptr(%[[ARG0]] : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(VLAType) bounds(%[[BOUNDS0]]) -> !llvm.ptr {name = ""} // CHECK: omp.target_enter_data map_entries(%[[MAP2]] : !llvm.ptr) - %mapv3 = omp.map_info var_ptr(%arg0 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(VLAType) bounds(%4) -> !llvm.ptr {name = ""} + %mapv3 = omp.map.info var_ptr(%arg0 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(VLAType) bounds(%4) -> !llvm.ptr {name = ""} omp.target_enter_data map_entries(%mapv3 : !llvm.ptr){} - // CHECK: %[[MAP3:.*]] = omp.map_info var_ptr(%[[ARG1]] : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(This) bounds(%[[BOUNDS1]]) -> !llvm.ptr {name = ""} + // CHECK: %[[MAP3:.*]] = omp.map.info var_ptr(%[[ARG1]] : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(This) bounds(%[[BOUNDS1]]) -> !llvm.ptr {name = ""} // CHECK: omp.target_exit_data map_entries(%[[MAP3]] : !llvm.ptr) - %mapv4 = omp.map_info var_ptr(%arg1 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(This) bounds(%10) -> !llvm.ptr {name = ""} + %mapv4 = omp.map.info var_ptr(%arg1 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(This) bounds(%10) -> !llvm.ptr {name = ""} omp.target_exit_data map_entries(%mapv4 : !llvm.ptr){} return @@ -2159,22 +2159,22 @@ func.func @omp_targets_with_map_bounds(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> () // CHECK-LABEL: omp_target_update_data func.func @omp_target_update_data (%if_cond : i1, %device : si32, %map1: memref<?xi32>, %map2: memref<?xi32>) -> () { - %mapv_from = omp.map_info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv_from = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32> {name = ""} - %mapv_to = omp.map_info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(present, to) capture(ByRef) -> memref<?xi32> {name = ""} + %mapv_to = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(present, to) capture(ByRef) -> memref<?xi32> {name = ""} - // CHECK: omp.target_update_data if(%[[VAL_0:.*]] : i1) device(%[[VAL_1:.*]] : si32) nowait motion_entries(%{{.*}}, %{{.*}} : memref<?xi32>, memref<?xi32>) - omp.target_update_data if(%if_cond : i1) device(%device : si32) nowait motion_entries(%mapv_from , %mapv_to : memref<?xi32>, memref<?xi32>) + // CHECK: omp.target_update if(%[[VAL_0:.*]] : i1) device(%[[VAL_1:.*]] : si32) nowait motion_entries(%{{.*}}, %{{.*}} : memref<?xi32>, memref<?xi32>) + omp.target_update if(%if_cond : i1) device(%device : si32) nowait motion_entries(%mapv_from , %mapv_to : memref<?xi32>, memref<?xi32>) return } // CHECK-LABEL: omp_targets_is_allocatable // CHECK-SAME: (%[[ARG0:.*]]: !llvm.ptr, %[[ARG1:.*]]: !llvm.ptr) func.func @omp_targets_is_allocatable(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> () { - // CHECK: %[[MAP0:.*]] = omp.map_info var_ptr(%[[ARG0]] : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} - %mapv1 = omp.map_info var_ptr(%arg0 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} - // CHECK: %[[MAP1:.*]] = omp.map_info var_ptr(%[[ARG1]] : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) map_clauses(tofrom) capture(ByRef) members(%[[MAP0]] : !llvm.ptr) -> !llvm.ptr {name = ""} - %mapv2 = omp.map_info var_ptr(%arg1 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) map_clauses(tofrom) capture(ByRef) members(%mapv1 : !llvm.ptr) -> !llvm.ptr {name = ""} + // CHECK: %[[MAP0:.*]] = omp.map.info var_ptr(%[[ARG0]] : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %mapv1 = omp.map.info var_ptr(%arg0 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + // CHECK: %[[MAP1:.*]] = omp.map.info var_ptr(%[[ARG1]] : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) map_clauses(tofrom) capture(ByRef) members(%[[MAP0]] : !llvm.ptr) -> !llvm.ptr {name = ""} + %mapv2 = omp.map.info var_ptr(%arg1 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) map_clauses(tofrom) capture(ByRef) members(%mapv1 : !llvm.ptr) -> !llvm.ptr {name = ""} // CHECK: omp.target map_entries(%[[MAP0]] -> {{.*}}, %[[MAP1]] -> {{.*}} : !llvm.ptr, !llvm.ptr) omp.target map_entries(%mapv1 -> %arg2, %mapv2 -> %arg3 : !llvm.ptr, !llvm.ptr) { ^bb0(%arg2: !llvm.ptr, %arg3 : !llvm.ptr): @@ -2186,12 +2186,12 @@ func.func @omp_targets_is_allocatable(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> () // CHECK-LABEL: func @omp_target_enter_update_exit_data_depend // CHECK-SAME:([[ARG0:%.*]]: memref<?xi32>, [[ARG1:%.*]]: memref<?xi32>, [[ARG2:%.*]]: memref<?xi32>) { func.func @omp_target_enter_update_exit_data_depend(%a: memref<?xi32>, %b: memref<?xi32>, %c: memref<?xi32>) { -// CHECK-NEXT: [[MAP0:%.*]] = omp.map_info -// CHECK-NEXT: [[MAP1:%.*]] = omp.map_info -// CHECK-NEXT: [[MAP2:%.*]] = omp.map_info - %map_a = omp.map_info var_ptr(%a: memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> - %map_b = omp.map_info var_ptr(%b: memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32> - %map_c = omp.map_info var_ptr(%c: memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> +// CHECK-NEXT: [[MAP0:%.*]] = omp.map.info +// CHECK-NEXT: [[MAP1:%.*]] = omp.map.info +// CHECK-NEXT: [[MAP2:%.*]] = omp.map.info + %map_a = omp.map.info var_ptr(%a: memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> + %map_b = omp.map.info var_ptr(%b: memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32> + %map_c = omp.map.info var_ptr(%c: memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> // Do some work on the host that writes to 'a' omp.task depend(taskdependout -> %a : memref<?xi32>) { @@ -2217,11 +2217,11 @@ func.func @omp_target_enter_update_exit_data_depend(%a: memref<?xi32>, %b: memre } // Copy the updated 'a' onto the target - // CHECK: omp.target_update_data nowait motion_entries([[MAP0]] : memref<?xi32>) depend(taskdependin -> [[ARG0]] : memref<?xi32>) - omp.target_update_data motion_entries(%map_a : memref<?xi32>) depend(taskdependin -> %a : memref<?xi32>) nowait + // CHECK: omp.target_update nowait motion_entries([[MAP0]] : memref<?xi32>) depend(taskdependin -> [[ARG0]] : memref<?xi32>) + omp.target_update motion_entries(%map_a : memref<?xi32>) depend(taskdependin -> %a : memref<?xi32>) nowait // Compute 'c' on the target and copy it back - %map_c_from = omp.map_info var_ptr(%c: memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32> + %map_c_from = omp.map.info var_ptr(%c: memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32> omp.target map_entries(%map_a -> %arg0, %map_c_from -> %arg1 : memref<?xi32>, memref<?xi32>) depend(taskdependout -> %c : memref<?xi32>) { ^bb0(%arg0 : memref<?xi32>, %arg1 : memref<?xi32>) : "test.foobar"() : ()->() diff --git a/mlir/test/Dialect/SCF/canonicalize.mlir b/mlir/test/Dialect/SCF/canonicalize.mlir index 52e0fdfa36d6cd4e6a482b2c42eb45f6817ac05b..b4c9ed4db94e0e890d83679b8d3c4a285af7e15d 100644 --- a/mlir/test/Dialect/SCF/canonicalize.mlir +++ b/mlir/test/Dialect/SCF/canonicalize.mlir @@ -1198,6 +1198,35 @@ func.func @while_unused_arg2(%val0: i32) -> i32 { // CHECK: return %[[RES]] : i32 +// ----- + +// CHECK-LABEL: func @test_align_args +// CHECK: %[[RES:.*]]:3 = scf.while (%[[ARG0:.*]] = %{{.*}}, %[[ARG1:.*]] = %{{.*}}, %[[ARG2:.*]] = %{{.*}}) : (f32, i32, i64) -> (f32, i32, i64) { +// CHECK: scf.condition(%{{.*}}) %[[ARG0]], %[[ARG1]], %[[ARG2]] : f32, i32, i64 +// CHECK: ^bb0(%[[ARG3:.*]]: f32, %[[ARG4:.*]]: i32, %[[ARG5:.*]]: i64): +// CHECK: %[[R1:.*]] = "test.test"(%[[ARG5]]) : (i64) -> f32 +// CHECK: %[[R2:.*]] = "test.test"(%[[ARG3]]) : (f32) -> i32 +// CHECK: %[[R3:.*]] = "test.test"(%[[ARG4]]) : (i32) -> i64 +// CHECK: scf.yield %[[R1]], %[[R2]], %[[R3]] : f32, i32, i64 +// CHECK: return %[[RES]]#2, %[[RES]]#0, %[[RES]]#1 +func.func @test_align_args() -> (i64, f32, i32) { + %0 = "test.test"() : () -> (f32) + %1 = "test.test"() : () -> (i32) + %2 = "test.test"() : () -> (i64) + %3:3 = scf.while (%arg0 = %0, %arg1 = %1, %arg2 = %2) : (f32, i32, i64) -> (i64, f32, i32) { + %cond = "test.test"() : () -> (i1) + scf.condition(%cond) %arg2, %arg0, %arg1 : i64, f32, i32 + } do { + ^bb0(%arg3: i64, %arg4: f32, %arg5: i32): + %4 = "test.test"(%arg3) : (i64) -> (f32) + %5 = "test.test"(%arg4) : (f32) -> (i32) + %6 = "test.test"(%arg5) : (i32) -> (i64) + scf.yield %4, %5, %6 : f32, i32, i64 + } + return %3#0, %3#1, %3#2 : i64, f32, i32 +} + + // ----- // CHECK-LABEL: @combineIfs diff --git a/mlir/test/Dialect/SCF/for-loop-peeling-front.mlir b/mlir/test/Dialect/SCF/for-loop-peeling-front.mlir index 65141ff7623ff2932a38a7c64ccbc62a683a7989..fe3b3e686a3e4a75bb13f454d3fa9327e0bc4410 100644 --- a/mlir/test/Dialect/SCF/for-loop-peeling-front.mlir +++ b/mlir/test/Dialect/SCF/for-loop-peeling-front.mlir @@ -13,11 +13,11 @@ // CHECK: %[[INIT:.*]] = arith.addi %[[ACC]], %[[CAST]] : i32 // CHECK: scf.yield %[[INIT]] // CHECK: } -// CHECK: %[[RESULT:.*]] = scf.for %[[IV:.*]] = %[[C4]] to %[[C17]] -// CHECK-SAME: step %[[C4]] iter_args(%[[ACC:.*]] = %[[FIRST]]) -> (i32) { -// CHECK: %[[MIN2:.*]] = affine.min #[[MAP]](%[[C17]], %[[IV]])[%[[C4]]] +// CHECK: %[[RESULT:.*]] = scf.for %[[IV2:.*]] = %[[C4]] to %[[C17]] +// CHECK-SAME: step %[[C4]] iter_args(%[[ACC2:.*]] = %[[FIRST]]) -> (i32) { +// CHECK: %[[MIN2:.*]] = affine.min #[[MAP]](%[[C17]], %[[IV2]])[%[[C4]]] // CHECK: %[[CAST2:.*]] = arith.index_cast %[[MIN2]] : index to i32 -// CHECK: %[[ADD:.*]] = arith.addi %[[ACC]], %[[CAST2]] : i32 +// CHECK: %[[ADD:.*]] = arith.addi %[[ACC2]], %[[CAST2]] : i32 // CHECK: scf.yield %[[ADD]] // CHECK: } // CHECK: return %[[RESULT]] @@ -110,6 +110,45 @@ func.func @fully_dynamic_bounds(%lb : index, %ub: index, %step: index) -> i32 { // ----- +// CHECK-DAG: #[[MAP:.*]] = affine_map<(d0, d1)[s0] -> (4, d0 - d1)> +// CHECK: func @two_iteration_example( +// CHECK-DAG: %[[C0_I32:.*]] = arith.constant 0 : i32 +// CHECK-DAG: %[[C2:.*]] = arith.constant 2 : index +// CHECK-DAG: %[[C4:.*]] = arith.constant 4 : index +// CHECK-DAG: %[[C8:.*]] = arith.constant 8 : index +// CHECK-DAG: %[[C6:.*]] = arith.constant 6 : index +// CHECK: %[[FIRST:.*]] = scf.for %[[IV:.*]] = %[[C2]] to %[[C6]] +// CHECK-SAME: step %[[C4]] iter_args(%[[ACC:.*]] = %[[C0_I32]]) -> (i32) { +// CHECK: %[[MIN:.*]] = affine.min #[[MAP]](%[[C6]], %[[IV]])[%[[C4]]] +// CHECK: %[[CAST:.*]] = arith.index_cast %[[MIN]] : index to i32 +// CHECK: %[[INIT:.*]] = arith.addi %[[ACC]], %[[CAST]] : i32 +// CHECK: scf.yield %[[INIT]] +// CHECK: } +// CHECK: %[[RESULT:.*]] = scf.for %[[IV2:.*]] = %[[C6]] to %[[C8]] +// CHECK-SAME: step %[[C4]] iter_args(%[[ACC2:.*]] = %[[FIRST]]) -> (i32) { +// CHECK: %[[MIN2:.*]] = affine.min #[[MAP]](%[[C8]], %[[IV2]])[%[[C4]]] +// CHECK: %[[CAST2:.*]] = arith.index_cast %[[MIN2]] : index to i32 +// CHECK: %[[ADD:.*]] = arith.addi %[[ACC2]], %[[CAST2]] : i32 +// CHECK: scf.yield %[[ADD]] +// CHECK: } +// CHECK: return %[[RESULT]] +#map = affine_map<(d0, d1)[s0] -> (s0, d0 - d1)> +func.func @two_iteration_example() -> i32 { + %c0_i32 = arith.constant 0 : i32 + %lb = arith.constant 2 : index + %step = arith.constant 4 : index + %ub = arith.constant 8 : index + %r = scf.for %iv = %lb to %ub step %step iter_args(%arg = %c0_i32) -> i32 { + %s = affine.min #map(%ub, %iv)[%step] + %casted = arith.index_cast %s : index to i32 + %0 = arith.addi %arg, %casted : i32 + scf.yield %0 : i32 + } + return %r : i32 +} + +// ----- + // CHECK-DAG: #[[MAP:.*]] = affine_map<(d0, d1)[s0] -> (4, d0 - d1)> // CHECK: func @no_peeling_front( // CHECK-DAG: %[[C0_I32:.*]] = arith.constant 0 : i32 diff --git a/mlir/test/Dialect/SCF/one-shot-bufferize-analysis.mlir b/mlir/test/Dialect/SCF/one-shot-bufferize-analysis.mlir index 7d23498f32e16ddfeb4f7b0a10a4d1afab388723..4d82021e86f5bb234404210e548af55ac45b3285 100644 --- a/mlir/test/Dialect/SCF/one-shot-bufferize-analysis.mlir +++ b/mlir/test/Dialect/SCF/one-shot-bufferize-analysis.mlir @@ -1,9 +1,9 @@ // RUN: mlir-opt %s -one-shot-bufferize="allow-return-allocs-from-loops bufferize-function-boundaries test-analysis-only" -split-input-file | FileCheck %s // Run fuzzer with different seeds. -// RUN: mlir-opt %s -one-shot-bufferize="allow-return-allocs-from-loops bufferize-function-boundaries test-analysis-only analysis-fuzzer-seed=23" -split-input-file -o /dev/null -// RUN: mlir-opt %s -one-shot-bufferize="allow-return-allocs-from-loops bufferize-function-boundaries test-analysis-only analysis-fuzzer-seed=59" -split-input-file -o /dev/null -// RUN: mlir-opt %s -one-shot-bufferize="allow-return-allocs-from-loops bufferize-function-boundaries test-analysis-only analysis-fuzzer-seed=91" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="allow-return-allocs-from-loops bufferize-function-boundaries test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=23" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="allow-return-allocs-from-loops bufferize-function-boundaries test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=59" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="allow-return-allocs-from-loops bufferize-function-boundaries test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=91" -split-input-file -o /dev/null // CHECK-LABEL: func @scf_for_yield_only func.func @scf_for_yield_only( diff --git a/mlir/test/Dialect/SCF/one-shot-bufferize.mlir b/mlir/test/Dialect/SCF/one-shot-bufferize.mlir index 24da8d84b18e26036275409cf62cd4b3626286bc..485fdd9b0e59323bcc2a468054db05bf7bf3786a 100644 --- a/mlir/test/Dialect/SCF/one-shot-bufferize.mlir +++ b/mlir/test/Dialect/SCF/one-shot-bufferize.mlir @@ -1,9 +1,9 @@ // RUN: mlir-opt %s -allow-unregistered-dialect -one-shot-bufferize="allow-return-allocs-from-loops bufferize-function-boundaries" -cse -canonicalize -drop-equivalent-buffer-results -split-input-file | FileCheck %s // Run fuzzer with different seeds. -// RUN: mlir-opt %s -allow-unregistered-dialect -one-shot-bufferize="allow-return-allocs-from-loops test-analysis-only analysis-fuzzer-seed=23 bufferize-function-boundaries" -split-input-file -o /dev/null -// RUN: mlir-opt %s -allow-unregistered-dialect -one-shot-bufferize="allow-return-allocs-from-loops test-analysis-only analysis-fuzzer-seed=59 bufferize-function-boundaries" -split-input-file -o /dev/null -// RUN: mlir-opt %s -allow-unregistered-dialect -one-shot-bufferize="allow-return-allocs-from-loops test-analysis-only analysis-fuzzer-seed=91 bufferize-function-boundaries" -split-input-file -o /dev/null +// RUN: mlir-opt %s -allow-unregistered-dialect -one-shot-bufferize="allow-return-allocs-from-loops analysis-heuristic=fuzzer test-analysis-only analysis-fuzzer-seed=23 bufferize-function-boundaries" -split-input-file -o /dev/null +// RUN: mlir-opt %s -allow-unregistered-dialect -one-shot-bufferize="allow-return-allocs-from-loops analysis-heuristic=fuzzer test-analysis-only analysis-fuzzer-seed=59 bufferize-function-boundaries" -split-input-file -o /dev/null +// RUN: mlir-opt %s -allow-unregistered-dialect -one-shot-bufferize="allow-return-allocs-from-loops analysis-heuristic=fuzzer test-analysis-only analysis-fuzzer-seed=91 bufferize-function-boundaries" -split-input-file -o /dev/null // Test bufferization using memref types that have no layout map. // RUN: mlir-opt %s -allow-unregistered-dialect -one-shot-bufferize="allow-return-allocs-from-loops unknown-type-conversion=identity-layout-map function-boundary-type-conversion=identity-layout-map bufferize-function-boundaries" -split-input-file -o /dev/null diff --git a/mlir/test/Dialect/SCF/transform-loop-fuse-sibling.mlir b/mlir/test/Dialect/SCF/transform-loop-fuse-sibling.mlir index faaa2db3aa57dee6f8993dad63302a0b1506c56f..0f51b1cdbe0cf18d245ebe056ad5599a70d0442b 100644 --- a/mlir/test/Dialect/SCF/transform-loop-fuse-sibling.mlir +++ b/mlir/test/Dialect/SCF/transform-loop-fuse-sibling.mlir @@ -1,14 +1,113 @@ // RUN: mlir-opt %s -transform-interpreter --cse --canonicalize -split-input-file -verify-diagnostics | FileCheck %s +// RUN: mlir-opt %s -transform-interpreter -split-input-file -verify-diagnostics | FileCheck %s --check-prefix CHECK-NOCLEANUP -func.func @test(%A : tensor<128x128xf32>, %B1 : tensor<128x128xf32>, %B2 : tensor<128x128xf32>) -> (tensor<128x128xf32>, tensor<128x128xf32>) { +// CHECK: func.func @fuse_1st_for_into_2nd([[A:%.*]]: {{.*}}, [[B:%.*]]: {{.*}} +func.func @fuse_1st_for_into_2nd(%A: tensor<128xf32>, %B: tensor<128xf32>) -> (tensor<128xf32>, tensor<128xf32>) { + // CHECK-DAG: [[C0:%.*]] = arith.constant 0 : index + // CHECK-DAG: [[C16:%.*]] = arith.constant 16 : index + // CHECK-DAG: [[C128:%.*]] = arith.constant 128 : index + // CHECK-DAG: [[ZERO:%.*]] = arith.constant 0.000000e+00 : f32 + %c0 = arith.constant 0 : index + %c16 = arith.constant 16 : index + %c128 = arith.constant 128 : index + %cst = arith.constant 0.000000e+00 : f32 + // CHECK: [[R0:%.*]]:2 = scf.for [[IV:%.*]] = [[C0]] to [[C128]] step [[C16]] iter_args([[IA:%.*]] = [[A]], [[IB:%.*]] = [[B]]) {{.*}} + %1 = scf.for %arg3 = %c0 to %c128 step %c16 iter_args(%arg4 = %A) -> (tensor<128xf32>) { + // CHECK-DAG: [[ASLICE:%.*]] = vector.transfer_read [[A]][[[IV]]], [[ZERO]] + // CHECK-DAG: [[SLICE0:%.*]] = vector.transfer_read [[IA]][[[IV]]], [[ZERO]] + // CHECK: [[OUT1:%.*]] = arith.addf [[SLICE0]], [[ASLICE]] + // CHECK-NEXT: [[WRT0:%.*]] = vector.transfer_write [[OUT1]], [[IA]][[[IV]]] + %2 = vector.transfer_read %A[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %3 = vector.transfer_read %arg4[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %5 = arith.addf %3, %2 : vector<16xf32> + %6 = vector.transfer_write %5, %arg4[%arg3] {in_bounds = [true]} : vector<16xf32>, tensor<128xf32> + scf.yield %6 : tensor<128xf32> + } + %dup1 = scf.for %arg3 = %c0 to %c128 step %c16 iter_args(%arg4 = %B) -> (tensor<128xf32>) { + // CHECK-DAG: [[SLICE1:%.*]] = vector.transfer_read [[IB]][[[IV]]], [[ZERO]] + // CHECK: [[OUT2:%.*]] = arith.addf [[SLICE1]], [[ASLICE]] + // CHECK-NEXT: [[WRT1:%.*]] = vector.transfer_write [[OUT2]], [[IB]][[[IV]]] + %dup2 = vector.transfer_read %A[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %dup3 = vector.transfer_read %arg4[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %dup5 = arith.addf %dup3, %dup2 : vector<16xf32> + %dup6 = vector.transfer_write %dup5, %arg4[%arg3] {in_bounds = [true]} : vector<16xf32>, tensor<128xf32> + // CHECK: scf.yield [[WRT0]], [[WRT1]] : {{.*}} + scf.yield %dup6 : tensor<128xf32> + } + return %1, %dup1 : tensor<128xf32>, tensor<128xf32> +} +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["scf.for"]} in %arg0 : (!transform.any_op) -> !transform.any_op + %for:2 = transform.split_handle %0 : (!transform.any_op) -> (!transform.any_op, !transform.any_op) + %fused = transform.loop.fuse_sibling %for#0 into %for#1 : (!transform.any_op,!transform.any_op) -> !transform.any_op + transform.yield + } +} + +// ----- + +// CHECK: func.func @fuse_2nd_for_into_1st([[A:%.*]]: {{.*}}, [[B:%.*]]: {{.*}} +func.func @fuse_2nd_for_into_1st(%A: tensor<128xf32>, %B: tensor<128xf32>) -> (tensor<128xf32>, tensor<128xf32>) { + // CHECK-DAG: [[C0:%.*]] = arith.constant 0 : index + // CHECK-DAG: [[C16:%.*]] = arith.constant 16 : index + // CHECK-DAG: [[C128:%.*]] = arith.constant 128 : index + // CHECK-DAG: [[ZERO:%.*]] = arith.constant 0.000000e+00 : f32 + %c0 = arith.constant 0 : index + %c16 = arith.constant 16 : index + %c128 = arith.constant 128 : index + %cst = arith.constant 0.000000e+00 : f32 + // CHECK: [[R0:%.*]]:2 = scf.for [[IV:%.*]] = [[C0]] to [[C128]] step [[C16]] iter_args([[IB:%.*]] = [[B]], [[IA:%.*]] = [[A]]) {{.*}} + %1 = scf.for %arg3 = %c0 to %c128 step %c16 iter_args(%arg4 = %A) -> (tensor<128xf32>) { + // CHECK-DAG: [[ASLICE:%.*]] = vector.transfer_read [[A]][[[IV]]], [[ZERO]] + // CHECK-DAG: [[SLICE0:%.*]] = vector.transfer_read [[IB]][[[IV]]], [[ZERO]] + // CHECK: [[OUT1:%.*]] = arith.addf [[SLICE0]], [[ASLICE]] + // CHECK-NEXT: [[WRT0:%.*]] = vector.transfer_write [[OUT1]], [[IB]][[[IV]]] + %2 = vector.transfer_read %A[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %3 = vector.transfer_read %arg4[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %5 = arith.addf %3, %2 : vector<16xf32> + %6 = vector.transfer_write %5, %arg4[%arg3] {in_bounds = [true]} : vector<16xf32>, tensor<128xf32> + scf.yield %6 : tensor<128xf32> + } + %dup1 = scf.for %arg3 = %c0 to %c128 step %c16 iter_args(%arg4 = %B) -> (tensor<128xf32>) { + // CHECK-DAG: [[SLICE1:%.*]] = vector.transfer_read [[IA]][[[IV]]], [[ZERO]] + // CHECK: [[OUT2:%.*]] = arith.addf [[SLICE1]], [[ASLICE]] + // CHECK-NEXT: [[WRT1:%.*]] = vector.transfer_write [[OUT2]], [[IA]][[[IV]]] + %dup2 = vector.transfer_read %A[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + // NB: the dominance check used to fail on the following line, + // however the defining op for the value of %arg3 occurs above the source loop and hence is safe + // and %arg4 is a block argument of the scope of the loops and hence is safe + %dup3 = vector.transfer_read %arg4[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %dup5 = arith.addf %dup3, %dup2 : vector<16xf32> + %dup6 = vector.transfer_write %dup5, %arg4[%arg3] {in_bounds = [true]} : vector<16xf32>, tensor<128xf32> + // CHECK: scf.yield [[WRT0]], [[WRT1]] : {{.*}} + scf.yield %dup6 : tensor<128xf32> + } + return %1, %dup1 : tensor<128xf32>, tensor<128xf32> +} +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["scf.for"]} in %arg0 : (!transform.any_op) -> !transform.any_op + %for:2 = transform.split_handle %0 : (!transform.any_op) -> (!transform.any_op, !transform.any_op) + %fused = transform.loop.fuse_sibling %for#1 into %for#0 : (!transform.any_op,!transform.any_op) -> !transform.any_op + transform.yield + } +} + +// ----- + +// CHECK: func.func @matmul_fuse_1st_forall_into_2nd([[A1:%.*]]: {{.*}}, [[A2:%.*]]: {{.*}}, [[B:%.*]]: {{.*}} +func.func @matmul_fuse_1st_forall_into_2nd(%A1 : tensor<128x128xf32>, %A2 : tensor<128x128xf32>, %B : tensor<128x128xf32>) -> (tensor<128x128xf32>, tensor<128x128xf32>) { %zero = arith.constant 0.0 : f32 %out_alloc = tensor.empty() : tensor<128x128xf32> %out = linalg.fill ins(%zero : f32) outs(%out_alloc : tensor<128x128xf32>) -> tensor<128x128xf32> // CHECK: scf.forall ([[I:%.*]]) in (4) shared_outs([[S1:%.*]] = [[IN1:%.*]], [[S2:%.*]] = [[IN2:%.*]]) -> (tensor<128x128xf32>, tensor<128x128xf32>) { // CHECK: [[T:%.*]] = affine.apply + // CHECK: tensor.extract_slice [[A2]][[[T]], 0] [32, 128] [1, 1] // CHECK: tensor.extract_slice [[S1]][[[T]], 0] [32, 128] [1, 1] // CHECK: [[OUT1:%.*]] = linalg.matmul + // CHECK: tensor.extract_slice [[A1]][[[T]], 0] [32, 128] [1, 1] // CHECK: tensor.extract_slice [[S2]][[[T]], 0] [32, 128] [1, 1] // CHECK: [[OUT2:%.*]] = linalg.matmul // CHECK: scf.forall.in_parallel { @@ -16,12 +115,11 @@ func.func @test(%A : tensor<128x128xf32>, %B1 : tensor<128x128xf32>, %B2 : tenso // CHECK: tensor.parallel_insert_slice [[OUT2]] into [[S2]][[[T]], 0] [32, 128] [1, 1] // CHECK: } // CHECK: } - %out1 = linalg.matmul ins(%A, %B1 : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> - %out2 = linalg.matmul ins(%A, %B2 : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> + %out1 = linalg.matmul ins(%A1, %B : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> + %out2 = linalg.matmul ins(%A2, %B : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> func.return %out1, %out2 : tensor<128x128xf32>, tensor<128x128xf32> } - module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%variant_op : !transform.any_op {transform.readonly}) { %matched = transform.structured.match ops{["linalg.matmul"]} in %variant_op : (!transform.any_op) -> (!transform.any_op) @@ -31,25 +129,37 @@ module attributes {transform.with_named_sequence} { %tiled_mm1, %loop1 = transform.structured.tile_using_forall %mm1 tile_sizes [32] : (!transform.any_op) -> (!transform.any_op, !transform.any_op) %tiled_mm2, %loop2 = transform.structured.tile_using_forall %mm2 tile_sizes [32] : (!transform.any_op) -> (!transform.any_op, !transform.any_op) - %fused_loop = transform.loop.fuse_sibling %loop1 into %loop2 : (!transform.any_op, !transform.any_op) -> !transform.any_op + %fused_loop = transform.loop.fuse_sibling %loop2 into %loop1 : (!transform.any_op, !transform.any_op) -> !transform.any_op transform.yield } } // ----- -func.func @test(%A : tensor<128x128xf32>, %B1 : tensor<128x128xf32>, %B2 : tensor<128x128xf32>) -> (tensor<128x128xf32>, tensor<128x128xf32>) { +// CHECK: func.func @matmul_fuse_2nd_forall_into_1st([[A1:%.*]]: {{.*}}, [[A2:%.*]]: {{.*}}, [[B:%.*]]: {{.*}} +func.func @matmul_fuse_2nd_forall_into_1st(%A1 : tensor<128x128xf32>, %A2 : tensor<128x128xf32>, %B : tensor<128x128xf32>) -> (tensor<128x128xf32>, tensor<128x128xf32>) { %zero = arith.constant 0.0 : f32 %out_alloc = tensor.empty() : tensor<128x128xf32> %out = linalg.fill ins(%zero : f32) outs(%out_alloc : tensor<128x128xf32>) -> tensor<128x128xf32> - // expected-error @below {{user of results of target should be properly dominated by source}} - %out1 = linalg.matmul ins(%A, %B1 : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> - %out2 = linalg.matmul ins(%A, %out1 : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> + // CHECK: scf.forall ([[I:%.*]]) in (4) shared_outs([[S1:%.*]] = [[IN1:%.*]], [[S2:%.*]] = [[IN2:%.*]]) -> (tensor<128x128xf32>, tensor<128x128xf32>) { + // CHECK: [[T:%.*]] = affine.apply + // CHECK: tensor.extract_slice [[A1]][[[T]], 0] [32, 128] [1, 1] + // CHECK: tensor.extract_slice [[S1]][[[T]], 0] [32, 128] [1, 1] + // CHECK: [[OUT1:%.*]] = linalg.matmul + // CHECK: tensor.extract_slice [[A2]][[[T]], 0] [32, 128] [1, 1] + // CHECK: tensor.extract_slice [[S2]][[[T]], 0] [32, 128] [1, 1] + // CHECK: [[OUT2:%.*]] = linalg.matmul + // CHECK: scf.forall.in_parallel { + // CHECK: tensor.parallel_insert_slice [[OUT1]] into [[S1]][[[T]], 0] [32, 128] [1, 1] + // CHECK: tensor.parallel_insert_slice [[OUT2]] into [[S2]][[[T]], 0] [32, 128] [1, 1] + // CHECK: } + // CHECK: } + %out1 = linalg.matmul ins(%A1, %B : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> + %out2 = linalg.matmul ins(%A2, %B : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> func.return %out1, %out2 : tensor<128x128xf32>, tensor<128x128xf32> } - module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%variant_op : !transform.any_op {transform.readonly}) { %matched = transform.structured.match ops{["linalg.matmul"]} in %variant_op : (!transform.any_op) -> (!transform.any_op) @@ -66,18 +176,84 @@ module attributes {transform.with_named_sequence} { // ----- -func.func @test(%A : tensor<128x128xf32>, %B1 : tensor<128x128xf32>, %B2 : tensor<128x128xf32>) -> (tensor<128x128xf32>, tensor<128x128xf32>) { +// CHECK-NOCLEANUP: func.func @fuse_no_iter_args([[A:%.*]]: {{.*}}, [[B:%.*]]: {{.*}} +func.func @fuse_no_iter_args(%A: tensor<128xf32>, %B: tensor<128xf32>) { + // CHECK-NOCLEANUP: [[C0:%.*]] = arith.constant 0 : index + // CHECK-NOCLEANUP: [[C16:%.*]] = arith.constant 16 : index + // CHECK-NOCLEANUP: [[C128:%.*]] = arith.constant 128 : index + // CHECK-NOCLEANUP: [[ZERO:%.*]] = arith.constant 0.000000e+00 : f32 + %c0 = arith.constant 0 : index + %c16 = arith.constant 16 : index + %c128 = arith.constant 128 : index + %cst = arith.constant 0.000000e+00 : f32 + // CHECK-NOCLEANUP: scf.for [[IV:%.*]] = [[C0]] to [[C128]] step [[C16]] {{.*}} + scf.for %arg0 = %c0 to %c128 step %c16 { + // CHECK-NOCLEANUP: [[ASLICE:%.*]] = vector.transfer_read [[A]][[[IV]]], [[ZERO]] + %2 = vector.transfer_read %A[%arg0], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + scf.yield + } + scf.for %arg0 = %c0 to %c128 step %c16 { + // CHECK-NOCLEANUP: [[BSLICE:%.*]] = vector.transfer_read [[B]][[[IV]]], [[ZERO]] + %dup2 = vector.transfer_read %B[%arg0], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + scf.yield + } + return +} +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["scf.for"]} in %arg0 : (!transform.any_op) -> !transform.any_op + %for:2 = transform.split_handle %0 : (!transform.any_op) -> (!transform.any_op, !transform.any_op) + %fused = transform.loop.fuse_sibling %for#0 into %for#1 : (!transform.any_op,!transform.any_op) -> !transform.any_op + transform.yield + } +} + +// ----- + +func.func @source_for_uses_result_of_target_for_err(%A: tensor<128xf32>, %B: tensor<128xf32>) -> (tensor<128xf32>, tensor<128xf32>) { + %c0 = arith.constant 0 : index + %c16 = arith.constant 16 : index + %c128 = arith.constant 128 : index + %cst = arith.constant 0.000000e+00 : f32 + // expected-error @below {{user of results of target should be properly dominated by source}} + %1 = scf.for %arg3 = %c0 to %c128 step %c16 iter_args(%arg4 = %A) -> (tensor<128xf32>) { + %2 = vector.transfer_read %A[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %3 = vector.transfer_read %arg4[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %5 = arith.addf %3, %2 : vector<16xf32> + %6 = vector.transfer_write %5, %arg4[%arg3] {in_bounds = [true]} : vector<16xf32>, tensor<128xf32> + scf.yield %6 : tensor<128xf32> + } + %dup1 = scf.for %arg3 = %c0 to %c128 step %c16 iter_args(%arg4 = %1) -> (tensor<128xf32>) { + %dup2 = vector.transfer_read %A[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %dup3 = vector.transfer_read %arg4[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %dup5 = arith.addf %dup3, %dup2 : vector<16xf32> + %dup6 = vector.transfer_write %dup5, %arg4[%arg3] {in_bounds = [true]} : vector<16xf32>, tensor<128xf32> + scf.yield %dup6 : tensor<128xf32> + } + return %1, %dup1 : tensor<128xf32>, tensor<128xf32> +} +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["scf.for"]} in %arg0 : (!transform.any_op) -> !transform.any_op + %for:2 = transform.split_handle %0 : (!transform.any_op) -> (!transform.any_op, !transform.any_op) + %fused = transform.loop.fuse_sibling %for#0 into %for#1 : (!transform.any_op,!transform.any_op) -> !transform.any_op + transform.yield + } +} + +// ----- + +func.func @source_forall_uses_result_of_target_forall_err(%A : tensor<128x128xf32>, %B1 : tensor<128x128xf32>, %B2 : tensor<128x128xf32>) -> (tensor<128x128xf32>, tensor<128x128xf32>) { %zero = arith.constant 0.0 : f32 %out_alloc = tensor.empty() : tensor<128x128xf32> %out = linalg.fill ins(%zero : f32) outs(%out_alloc : tensor<128x128xf32>) -> tensor<128x128xf32> + // expected-error @below {{user of results of target should be properly dominated by source}} %out1 = linalg.matmul ins(%A, %B1 : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> - // expected-error @below {{values used inside regions of target should be properly dominated by source}} %out2 = linalg.matmul ins(%A, %out1 : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> func.return %out1, %out2 : tensor<128x128xf32>, tensor<128x128xf32> } - module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%variant_op : !transform.any_op {transform.readonly}) { %matched = transform.structured.match ops{["linalg.matmul"]} in %variant_op : (!transform.any_op) -> (!transform.any_op) @@ -87,25 +263,58 @@ module attributes {transform.with_named_sequence} { %tiled_mm1, %loop1 = transform.structured.tile_using_forall %mm1 tile_sizes [32] : (!transform.any_op) -> (!transform.any_op, !transform.any_op) %tiled_mm2, %loop2 = transform.structured.tile_using_forall %mm2 tile_sizes [32] : (!transform.any_op) -> (!transform.any_op, !transform.any_op) - %fused_loop = transform.loop.fuse_sibling %loop2 into %loop1 : (!transform.any_op, !transform.any_op) -> !transform.any_op + %fused_loop = transform.loop.fuse_sibling %loop1 into %loop2 : (!transform.any_op, !transform.any_op) -> !transform.any_op transform.yield } } // ----- -func.func @test(%A : tensor<128x128xf32>, %B1 : tensor<128x128xf32>, %B2 : tensor<128x128xf32>) -> (tensor<128x128xf32>, tensor<128x128xf32>) { - %zero = arith.constant 0.0 : f32 - %out_alloc = tensor.empty() : tensor<128x128xf32> - %out = linalg.fill ins(%zero : f32) outs(%out_alloc : tensor<128x128xf32>) -> tensor<128x128xf32> +func.func @target_for_region_uses_result_of_source_for_err(%A: tensor<128xf32>, %B: tensor<128xf32>) -> (tensor<128xf32>, tensor<128xf32>) { + %c0 = arith.constant 0 : index + %c16 = arith.constant 16 : index + %c128 = arith.constant 128 : index + %cst = arith.constant 0.000000e+00 : f32 + %1 = scf.for %arg3 = %c0 to %c128 step %c16 iter_args(%arg4 = %A) -> (tensor<128xf32>) { + %2 = vector.transfer_read %A[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %3 = vector.transfer_read %arg4[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %5 = arith.addf %3, %2 : vector<16xf32> + %6 = vector.transfer_write %5, %arg4[%arg3] {in_bounds = [true]} : vector<16xf32>, tensor<128xf32> + scf.yield %6 : tensor<128xf32> + } + %dup1 = scf.for %arg3 = %c0 to %c128 step %c16 iter_args(%arg4 = %B) -> (tensor<128xf32>) { + // expected-error @below {{values used inside regions of target should be properly dominated by source}} + %dup2 = vector.transfer_read %1[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %dup3 = vector.transfer_read %arg4[%arg3], %cst {in_bounds = [true]} : tensor<128xf32>, vector<16xf32> + %dup5 = arith.addf %dup3, %dup2 : vector<16xf32> + %dup6 = vector.transfer_write %dup5, %arg4[%arg3] {in_bounds = [true]} : vector<16xf32>, tensor<128xf32> + scf.yield %dup6 : tensor<128xf32> + } + return %1, %dup1 : tensor<128xf32>, tensor<128xf32> +} +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["scf.for"]} in %arg0 : (!transform.any_op) -> !transform.any_op + %for:2 = transform.split_handle %0 : (!transform.any_op) -> (!transform.any_op, !transform.any_op) + %fused = transform.loop.fuse_sibling %for#1 into %for#0 : (!transform.any_op,!transform.any_op) -> !transform.any_op + transform.yield + } +} - %out1 = linalg.matmul ins(%A, %B1 : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out : tensor<128x128xf32>) -> tensor<128x128xf32> +// ----- + +func.func @target_forall_depends_on_value_not_dominated_by_source_forall_err(%A1 : tensor<128x128xf32>, %A2 : tensor<128x128xf32>, %B : tensor<128x128xf32>) -> (tensor<128x128xf32>, tensor<128x128xf32>) { + %zero = arith.constant 0.0 : f32 + %buf1_alloc = tensor.empty() : tensor<128x128xf32> + %buf1 = linalg.fill ins(%zero : f32) outs(%buf1_alloc : tensor<128x128xf32>) -> tensor<128x128xf32> + %out1 = linalg.matmul ins(%A1, %B : tensor<128x128xf32>, tensor<128x128xf32>) outs(%buf1 : tensor<128x128xf32>) -> tensor<128x128xf32> + %out_alloc2 = tensor.empty() : tensor<128x128xf32> + %buf2 = linalg.fill ins(%zero : f32) outs(%buf1_alloc : tensor<128x128xf32>) -> tensor<128x128xf32> // expected-error @below {{operands of target should be properly dominated by source}} - %out2 = linalg.matmul ins(%A, %B2 : tensor<128x128xf32>, tensor<128x128xf32>) outs(%out1 : tensor<128x128xf32>) -> tensor<128x128xf32> + %out2 = linalg.matmul ins(%A2, %B : tensor<128x128xf32>, tensor<128x128xf32>) outs(%buf2 : tensor<128x128xf32>) -> tensor<128x128xf32> func.return %out1, %out2 : tensor<128x128xf32>, tensor<128x128xf32> } - module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%variant_op : !transform.any_op {transform.readonly}) { %matched = transform.structured.match ops{["linalg.matmul"]} in %variant_op : (!transform.any_op) -> (!transform.any_op) diff --git a/mlir/test/Dialect/SPIRV/Transforms/canonicalize.mlir b/mlir/test/Dialect/SPIRV/Transforms/canonicalize.mlir index 1cb69891a70ed6e16faec2788b507c10b8ca3521..977d31a6bfe542aa2c22fe48b4ca26dc720b2c2d 100644 --- a/mlir/test/Dialect/SPIRV/Transforms/canonicalize.mlir +++ b/mlir/test/Dialect/SPIRV/Transforms/canonicalize.mlir @@ -1346,6 +1346,52 @@ func.func @convert_logical_or_true_false_vector(%arg: vector<3xi1>) -> (vector<3 // ----- +//===----------------------------------------------------------------------===// +// spirv.Select +//===----------------------------------------------------------------------===// + +// CHECK-LABEL: @convert_select_scalar +// CHECK-SAME: %[[ARG1:.+]]: i32, %[[ARG2:.+]]: i32 +func.func @convert_select_scalar(%arg1: i32, %arg2: i32) -> (i32, i32) { + %true = spirv.Constant true + %false = spirv.Constant false + %0 = spirv.Select %true, %arg1, %arg2 : i1, i32 + %1 = spirv.Select %false, %arg1, %arg2 : i1, i32 + + // CHECK: return %[[ARG1]], %[[ARG2]] + return %0, %1 : i32, i32 +} + +// CHECK-LABEL: @convert_select_vector +// CHECK-SAME: %[[ARG1:.+]]: vector<3xi32>, %[[ARG2:.+]]: vector<3xi32> +func.func @convert_select_vector(%arg1: vector<3xi32>, %arg2: vector<3xi32>) -> (vector<3xi32>, vector<3xi32>) { + %true = spirv.Constant dense<true> : vector<3xi1> + %false = spirv.Constant dense<false> : vector<3xi1> + %0 = spirv.Select %true, %arg1, %arg2 : vector<3xi1>, vector<3xi32> + %1 = spirv.Select %false, %arg1, %arg2 : vector<3xi1>, vector<3xi32> + + // CHECK: return %[[ARG1]], %[[ARG2]] + return %0, %1: vector<3xi32>, vector<3xi32> +} + +// CHECK-LABEL: @convert_select_vector_extra +// CHECK-SAME: %[[CONDITIONS:.+]]: vector<2xi1>, %[[ARG1:.+]]: vector<2xi32> +func.func @convert_select_vector_extra(%conditions: vector<2xi1>, %arg1: vector<2xi32>) -> (vector<2xi32>, vector<2xi32>) { + %true_false = spirv.Constant dense<[true, false]> : vector<2xi1> + %cvec_1 = spirv.Constant dense<[42, -132]> : vector<2xi32> + %cvec_2 = spirv.Constant dense<[0, 42]> : vector<2xi32> + + // CHECK: %[[RES:.+]] = spirv.Constant dense<42> + %0 = spirv.Select %true_false, %cvec_1, %cvec_2: vector<2xi1>, vector<2xi32> + + %1 = spirv.Select %conditions, %arg1, %arg1 : vector<2xi1>, vector<2xi32> + + // CHECK: return %[[RES]], %[[ARG1]] + return %0, %1: vector<2xi32>, vector<2xi32> +} + +// ----- + //===----------------------------------------------------------------------===// // spirv.IEqual //===----------------------------------------------------------------------===// @@ -1432,6 +1478,358 @@ func.func @const_fold_vector_inotequal() -> vector<3xi1> { // ----- +//===----------------------------------------------------------------------===// +// spirv.SGreaterThan +//===----------------------------------------------------------------------===// + +// CHECK-LABEL: @sgt_same +func.func @sgt_same(%arg0 : i32, %arg1 : vector<3xi32>) -> (i1, vector<3xi1>) { + // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false + // CHECK-DAG: %[[CVFALSE:.*]] = spirv.Constant dense<false> + %0 = spirv.SGreaterThan %arg0, %arg0 : i32 + %1 = spirv.SGreaterThan %arg1, %arg1 : vector<3xi32> + + // CHECK: return %[[CFALSE]], %[[CVFALSE]] + return %0, %1 : i1, vector<3xi1> +} + +// CHECK-LABEL: @const_fold_scalar_sgt +func.func @const_fold_scalar_sgt() -> (i1, i1) { + %c4 = spirv.Constant 4 : i32 + %c5 = spirv.Constant 5 : i32 + %c6 = spirv.Constant 6 : i32 + + // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true + // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false + %0 = spirv.SGreaterThan %c5, %c6 : i32 + %1 = spirv.SGreaterThan %c5, %c4 : i32 + + // CHECK: return %[[CFALSE]], %[[CTRUE]] + return %0, %1 : i1, i1 +} + +// CHECK-LABEL: @const_fold_vector_sgt +func.func @const_fold_vector_sgt() -> vector<3xi1> { + %cv0 = spirv.Constant dense<[-1, -4, 3]> : vector<3xi32> + %cv1 = spirv.Constant dense<[-1, -3, 2]> : vector<3xi32> + + // CHECK: %[[RET:.*]] = spirv.Constant dense<[false, false, true]> + %0 = spirv.SGreaterThan %cv0, %cv1 : vector<3xi32> + + // CHECK: return %[[RET]] + return %0 : vector<3xi1> +} + +// ----- + +//===----------------------------------------------------------------------===// +// spirv.SGreaterThanEqual +//===----------------------------------------------------------------------===// + +// CHECK-LABEL: @sge_same +func.func @sge_same(%arg0 : i32, %arg1 : vector<3xi32>) -> (i1, vector<3xi1>) { + // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true + // CHECK-DAG: %[[CVTRUE:.*]] = spirv.Constant dense<true> + %0 = spirv.SGreaterThanEqual %arg0, %arg0 : i32 + %1 = spirv.SGreaterThanEqual %arg1, %arg1 : vector<3xi32> + + // CHECK: return %[[CTRUE]], %[[CVTRUE]] + return %0, %1 : i1, vector<3xi1> +} + +// CHECK-LABEL: @const_fold_scalar_sge +func.func @const_fold_scalar_sge() -> (i1, i1) { + %c4 = spirv.Constant 4 : i32 + %c5 = spirv.Constant 5 : i32 + %c6 = spirv.Constant 6 : i32 + + // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true + // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false + %0 = spirv.SGreaterThanEqual %c5, %c6 : i32 + %1 = spirv.SGreaterThanEqual %c5, %c4 : i32 + + // CHECK: return %[[CFALSE]], %[[CTRUE]] + return %0, %1 : i1, i1 +} + +// CHECK-LABEL: @const_fold_vector_sge +func.func @const_fold_vector_sge() -> vector<3xi1> { + %cv0 = spirv.Constant dense<[-1, -4, 3]> : vector<3xi32> + %cv1 = spirv.Constant dense<[-1, -3, 2]> : vector<3xi32> + + // CHECK: %[[RET:.*]] = spirv.Constant dense<[true, false, true]> + %0 = spirv.SGreaterThanEqual %cv0, %cv1 : vector<3xi32> + + // CHECK: return %[[RET]] + return %0 : vector<3xi1> +} + +// ----- + +//===----------------------------------------------------------------------===// +// spirv.UGreaterThan +//===----------------------------------------------------------------------===// + +// CHECK-LABEL: @ugt_same +func.func @ugt_same(%arg0 : i32, %arg1 : vector<3xi32>) -> (i1, vector<3xi1>) { + // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false + // CHECK-DAG: %[[CVFALSE:.*]] = spirv.Constant dense<false> + %0 = spirv.UGreaterThan %arg0, %arg0 : i32 + %1 = spirv.UGreaterThan %arg1, %arg1 : vector<3xi32> + + // CHECK: return %[[CFALSE]], %[[CVFALSE]] + return %0, %1 : i1, vector<3xi1> +} + +// CHECK-LABEL: @const_fold_scalar_ugt +func.func @const_fold_scalar_ugt() -> (i1, i1) { + %c4 = spirv.Constant 4 : i32 + %c5 = spirv.Constant 5 : i32 + %cn6 = spirv.Constant -6 : i32 + + // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true + // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false + %0 = spirv.UGreaterThan %c5, %cn6 : i32 + %1 = spirv.UGreaterThan %c5, %c4 : i32 + + // CHECK: return %[[CFALSE]], %[[CTRUE]] + return %0, %1 : i1, i1 +} + +// CHECK-LABEL: @const_fold_vector_ugt +func.func @const_fold_vector_ugt() -> vector<3xi1> { + %cv0 = spirv.Constant dense<[-1, -4, 3]> : vector<3xi32> + %cv1 = spirv.Constant dense<[-1, -3, 2]> : vector<3xi32> + + // CHECK: %[[RET:.*]] = spirv.Constant dense<[false, false, true]> + %0 = spirv.UGreaterThan %cv0, %cv1 : vector<3xi32> + + // CHECK: return %[[RET]] + return %0 : vector<3xi1> +} + +// ----- + +//===----------------------------------------------------------------------===// +// spirv.UGreaterThanEqual +//===----------------------------------------------------------------------===// + +// CHECK-LABEL: @uge_same +func.func @uge_same(%arg0 : i32, %arg1 : vector<3xi32>) -> (i1, vector<3xi1>) { + // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true + // CHECK-DAG: %[[CVTRUE:.*]] = spirv.Constant dense<true> + %0 = spirv.UGreaterThanEqual %arg0, %arg0 : i32 + %1 = spirv.UGreaterThanEqual %arg1, %arg1 : vector<3xi32> + + // CHECK: return %[[CTRUE]], %[[CVTRUE]] + return %0, %1 : i1, vector<3xi1> +} + +// CHECK-LABEL: @const_fold_scalar_uge +func.func @const_fold_scalar_uge() -> (i1, i1) { + %c4 = spirv.Constant 4 : i32 + %c5 = spirv.Constant 5 : i32 + %cn6 = spirv.Constant -6 : i32 + + // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true + // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false + %0 = spirv.UGreaterThanEqual %c5, %cn6 : i32 + %1 = spirv.UGreaterThanEqual %c5, %c4 : i32 + + // CHECK: return %[[CFALSE]], %[[CTRUE]] + return %0, %1 : i1, i1 +} + +// CHECK-LABEL: @const_fold_vector_uge +func.func @const_fold_vector_uge() -> vector<3xi1> { + %cv0 = spirv.Constant dense<[-1, -4, 3]> : vector<3xi32> + %cv1 = spirv.Constant dense<[-1, -3, 2]> : vector<3xi32> + + // CHECK: %[[RET:.*]] = spirv.Constant dense<[true, false, true]> + %0 = spirv.UGreaterThanEqual %cv0, %cv1 : vector<3xi32> + + // CHECK: return %[[RET]] + return %0 : vector<3xi1> +} + +// ----- + +//===----------------------------------------------------------------------===// +// spirv.SLessThan +//===----------------------------------------------------------------------===// + +// CHECK-LABEL: @slt_same +func.func @slt_same(%arg0 : i32, %arg1 : vector<3xi32>) -> (i1, vector<3xi1>) { + // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false + // CHECK-DAG: %[[CVFALSE:.*]] = spirv.Constant dense<false> + %0 = spirv.SLessThan %arg0, %arg0 : i32 + %1 = spirv.SLessThan %arg1, %arg1 : vector<3xi32> + + // CHECK: return %[[CFALSE]], %[[CVFALSE]] + return %0, %1 : i1, vector<3xi1> +} + +// CHECK-LABEL: @const_fold_scalar_slt +func.func @const_fold_scalar_slt() -> (i1, i1) { + %c4 = spirv.Constant 4 : i32 + %c5 = spirv.Constant 5 : i32 + %c6 = spirv.Constant 6 : i32 + + // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true + // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false + %0 = spirv.SLessThan %c5, %c6 : i32 + %1 = spirv.SLessThan %c5, %c4 : i32 + + // CHECK: return %[[CTRUE]], %[[CFALSE]] + return %0, %1 : i1, i1 +} + +// CHECK-LABEL: @const_fold_vector_slt +func.func @const_fold_vector_slt() -> vector<3xi1> { + %cv0 = spirv.Constant dense<[-1, -4, 3]> : vector<3xi32> + %cv1 = spirv.Constant dense<[-1, -3, 2]> : vector<3xi32> + + // CHECK: %[[RET:.*]] = spirv.Constant dense<[false, true, false]> + %0 = spirv.SLessThan %cv0, %cv1 : vector<3xi32> + + // CHECK: return %[[RET]] + return %0 : vector<3xi1> +} + +// ----- + +//===----------------------------------------------------------------------===// +// spirv.SLessThanEqual +//===----------------------------------------------------------------------===// + +// CHECK-LABEL: @sle_same +func.func @sle_same(%arg0 : i32, %arg1 : vector<3xi32>) -> (i1, vector<3xi1>) { + // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true + // CHECK-DAG: %[[CVTRUE:.*]] = spirv.Constant dense<true> + %0 = spirv.SLessThanEqual %arg0, %arg0 : i32 + %1 = spirv.SLessThanEqual %arg1, %arg1 : vector<3xi32> + + // CHECK: return %[[CTRUE]], %[[CVTRUE]] + return %0, %1 : i1, vector<3xi1> +} + +// CHECK-LABEL: @const_fold_scalar_sle +func.func @const_fold_scalar_sle() -> (i1, i1) { + %c4 = spirv.Constant 4 : i32 + %c5 = spirv.Constant 5 : i32 + %c6 = spirv.Constant 6 : i32 + + // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true + // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false + %0 = spirv.SLessThanEqual %c5, %c6 : i32 + %1 = spirv.SLessThanEqual %c5, %c4 : i32 + + // CHECK: return %[[CTRUE]], %[[CFALSE]] + return %0, %1 : i1, i1 +} + +// CHECK-LABEL: @const_fold_vector_sle +func.func @const_fold_vector_sle() -> vector<3xi1> { + %cv0 = spirv.Constant dense<[-1, -4, 3]> : vector<3xi32> + %cv1 = spirv.Constant dense<[-1, -3, 2]> : vector<3xi32> + + // CHECK: %[[RET:.*]] = spirv.Constant dense<[true, true, false]> + %0 = spirv.SLessThanEqual %cv0, %cv1 : vector<3xi32> + + // CHECK: return %[[RET]] + return %0 : vector<3xi1> +} + +// ----- + +//===----------------------------------------------------------------------===// +// spirv.ULessThan +//===----------------------------------------------------------------------===// + +// CHECK-LABEL: @ult_same +func.func @ult_same(%arg0 : i32, %arg1 : vector<3xi32>) -> (i1, vector<3xi1>) { + // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false + // CHECK-DAG: %[[CVFALSE:.*]] = spirv.Constant dense<false> + %0 = spirv.ULessThan %arg0, %arg0 : i32 + %1 = spirv.ULessThan %arg1, %arg1 : vector<3xi32> + + // CHECK: return %[[CFALSE]], %[[CVFALSE]] + return %0, %1 : i1, vector<3xi1> +} + +// CHECK-LABEL: @const_fold_scalar_ult +func.func @const_fold_scalar_ult() -> (i1, i1) { + %c4 = spirv.Constant 4 : i32 + %c5 = spirv.Constant 5 : i32 + %cn6 = spirv.Constant -6 : i32 + + // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true + // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false + %0 = spirv.ULessThan %c5, %cn6 : i32 + %1 = spirv.ULessThan %c5, %c4 : i32 + + // CHECK: return %[[CTRUE]], %[[CFALSE]] + return %0, %1 : i1, i1 +} + +// CHECK-LABEL: @const_fold_vector_ult +func.func @const_fold_vector_ult() -> vector<3xi1> { + %cv0 = spirv.Constant dense<[-1, -4, 3]> : vector<3xi32> + %cv1 = spirv.Constant dense<[-1, -3, 2]> : vector<3xi32> + + // CHECK: %[[RET:.*]] = spirv.Constant dense<[false, true, false]> + %0 = spirv.ULessThan %cv0, %cv1 : vector<3xi32> + + // CHECK: return %[[RET]] + return %0 : vector<3xi1> +} + +// ----- + +//===----------------------------------------------------------------------===// +// spirv.ULessThanEqual +//===----------------------------------------------------------------------===// + +// CHECK-LABEL: @ule_same +func.func @ule_same(%arg0 : i32, %arg1 : vector<3xi32>) -> (i1, vector<3xi1>) { + // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true + // CHECK-DAG: %[[CVTRUE:.*]] = spirv.Constant dense<true> + %0 = spirv.ULessThanEqual %arg0, %arg0 : i32 + %1 = spirv.ULessThanEqual %arg1, %arg1 : vector<3xi32> + + // CHECK: return %[[CTRUE]], %[[CVTRUE]] + return %0, %1 : i1, vector<3xi1> +} + +// CHECK-LABEL: @const_fold_scalar_ule +func.func @const_fold_scalar_ule() -> (i1, i1) { + %c4 = spirv.Constant 4 : i32 + %c5 = spirv.Constant 5 : i32 + %cn6 = spirv.Constant -6 : i32 + + // CHECK-DAG: %[[CTRUE:.*]] = spirv.Constant true + // CHECK-DAG: %[[CFALSE:.*]] = spirv.Constant false + %0 = spirv.ULessThanEqual %c5, %cn6 : i32 + %1 = spirv.ULessThanEqual %c5, %c4 : i32 + + // CHECK: return %[[CTRUE]], %[[CFALSE]] + return %0, %1 : i1, i1 +} + +// CHECK-LABEL: @const_fold_vector_ule +func.func @const_fold_vector_ule() -> vector<3xi1> { + %cv0 = spirv.Constant dense<[-1, -4, 3]> : vector<3xi32> + %cv1 = spirv.Constant dense<[-1, -3, 2]> : vector<3xi32> + + // CHECK: %[[RET:.*]] = spirv.Constant dense<[true, true, false]> + %0 = spirv.ULessThanEqual %cv0, %cv1 : vector<3xi32> + + // CHECK: return %[[RET]] + return %0 : vector<3xi1> +} + +// ----- + //===----------------------------------------------------------------------===// // spirv.LeftShiftLogical //===----------------------------------------------------------------------===// diff --git a/mlir/test/Dialect/SPIRV/Transforms/webgpu-prepare.mlir b/mlir/test/Dialect/SPIRV/Transforms/webgpu-prepare.mlir index 1ec4e5e4f9664b89dd4b7188aabeb536b46b06c6..45f188da3815cf6b31cacb32305bf805761204f6 100644 --- a/mlir/test/Dialect/SPIRV/Transforms/webgpu-prepare.mlir +++ b/mlir/test/Dialect/SPIRV/Transforms/webgpu-prepare.mlir @@ -182,4 +182,36 @@ spirv.func @iaddcarry_i16(%a : i16, %b : i16) -> !spirv.struct<(i16, i16)> "None spirv.ReturnValue %0 : !spirv.struct<(i16, i16)> } +// CHECK-LABEL: func @is_inf_f32 +// CHECK-NEXT: [[FALSE:%.+]] = spirv.Constant false +// CHECK-NEXT: spirv.ReturnValue [[FALSE]] : i1 +spirv.func @is_inf_f32(%a : f32) -> i1 "None" { + %0 = spirv.IsInf %a : f32 + spirv.ReturnValue %0 : i1 +} + +// CHECK-LABEL: func @is_inf_4xf32 +// CHECK-NEXT: [[FALSE:%.+]] = spirv.Constant dense<false> : vector<4xi1> +// CHECK-NEXT: spirv.ReturnValue [[FALSE]] : vector<4xi1> +spirv.func @is_inf_4xf32(%a : vector<4xf32>) -> vector<4xi1> "None" { + %0 = spirv.IsInf %a : vector<4xf32> + spirv.ReturnValue %0 : vector<4xi1> +} + +// CHECK-LABEL: func @is_nan_f32 +// CHECK-NEXT: [[FALSE:%.+]] = spirv.Constant false +// CHECK-NEXT: spirv.ReturnValue [[FALSE]] : i1 +spirv.func @is_nan_f32(%a : f32) -> i1 "None" { + %0 = spirv.IsNan %a : f32 + spirv.ReturnValue %0 : i1 +} + +// CHECK-LABEL: func @is_nan_4xf32 +// CHECK-NEXT: [[FALSE:%.+]] = spirv.Constant dense<false> : vector<4xi1> +// CHECK-NEXT: spirv.ReturnValue [[FALSE]] : vector<4xi1> +spirv.func @is_nan_4xf32(%a : vector<4xf32>) -> vector<4xi1> "None" { + %0 = spirv.IsNan %a : vector<4xf32> + spirv.ReturnValue %0 : vector<4xi1> +} + } // end module diff --git a/mlir/test/Dialect/SparseTensor/invalid.mlir b/mlir/test/Dialect/SparseTensor/invalid.mlir index 48f28ef390ed5354c1ee9dac62656faf8c7e9740..18851f29d8eaa36e541457d84fe99ce3021cbc8e 100644 --- a/mlir/test/Dialect/SparseTensor/invalid.mlir +++ b/mlir/test/Dialect/SparseTensor/invalid.mlir @@ -868,16 +868,6 @@ func.func @sparse_sort_coo_no_perm(%arg0: index, %arg1: memref<?xindex>) -> (mem // ----- -#CSR = #sparse_tensor.encoding<{map = (d0, d1) -> (d0 : dense, d1 : compressed)}> - -func.func @sparse_alloc_escapes(%arg0: index) -> tensor<10x?xf64, #CSR> { - // expected-error@+1 {{sparse tensor allocation should not escape function}} - %0 = bufferization.alloc_tensor(%arg0) : tensor<10x?xf64, #CSR> - return %0: tensor<10x?xf64, #CSR> -} - -// ----- - #UnorderedCOO = #sparse_tensor.encoding<{map = (d0, d1) -> (d0 : compressed(nonunique, nonordered), d1 : singleton(nonordered))}> #OrderedCOOPerm = #sparse_tensor.encoding<{map = (d0, d1) -> (d1 : compressed(nonunique), d0 : singleton)}> diff --git a/mlir/test/Dialect/SparseTensor/no_fold_into_consumer.mlir b/mlir/test/Dialect/SparseTensor/no_fold_into_consumer.mlir new file mode 100644 index 0000000000000000000000000000000000000000..bbc7f397e793fe129971fbca16be83b2784ae66c --- /dev/null +++ b/mlir/test/Dialect/SparseTensor/no_fold_into_consumer.mlir @@ -0,0 +1,47 @@ +// RUN: mlir-opt %s --canonicalize --pre-sparsification-rewrite | FileCheck %s + +#map = affine_map<(d0, d1, d2) -> (d0, d1, d2)> + +#sparse = #sparse_tensor.encoding<{ + map = (d0, d1, d2) -> + (d0 : compressed(nonunique), + d1 : singleton(nonunique, soa), + d2 : singleton(soa)), + posWidth = 64, + crdWidth = 64 +}> + + +module { + // + // This IR should not end up in an infinite loop trying to fold + // the linalg producer into the tensor cast consumer (even though + // static sizes can fold, the different encodings cannot). The + // cast was sloppy to begin with (but it has been observed by + // external sources) and can be easily repaired by the sparsifier. + // + // CHECK-LABEL: func @avoid_fold + // CHECK: arith.constant + // CHECK: tensor.empty() + // CHECK: linalg.generic + // CHECK: sparse_tensor.convert + // CHECK: return + // + func.func @avoid_fold(%0: tensor<10x20x30xf64, #sparse>) -> tensor<10x20x30xf64, #sparse> { + %1 = tensor.empty() : tensor<10x20x30xf64> + %2 = linalg.generic { indexing_maps = [#map, #map], + iterator_types = ["parallel", "parallel", "parallel"] + } + ins (%0 : tensor<10x20x30xf64, #sparse>) + outs(%1 : tensor<10x20x30xf64>) { + ^bb0(%in: f64, %out: f64): + %cst = arith.constant 0.000000e+00 : f64 + %4 = arith.cmpf ugt, %in, %cst : f64 + %5 = arith.select %4, %in, %cst : f64 + linalg.yield %5 : f64 + } -> tensor<10x20x30xf64> + %cast = tensor.cast %2 : tensor<10x20x30xf64> to tensor<10x20x30xf64, #sparse> + return %cast : tensor<10x20x30xf64, #sparse> + } +} + diff --git a/mlir/test/Dialect/SparseTensor/roundtrip.mlir b/mlir/test/Dialect/SparseTensor/roundtrip.mlir index e9e458e805ba47150f3bb26beeb712a048820c97..a47a3d5119f96d4c2bfd34e127e0a3ed659611b9 100644 --- a/mlir/test/Dialect/SparseTensor/roundtrip.mlir +++ b/mlir/test/Dialect/SparseTensor/roundtrip.mlir @@ -728,3 +728,13 @@ func.func @sparse_print(%arg0: tensor<10x10xf64, #CSR>) { sparse_tensor.print %arg0 : tensor<10x10xf64, #CSR> return } + +// ----- + +// CHECK-LABEL: func.func @sparse_has_runtime() -> i1 +// CHECK: %[[H:.*]] = sparse_tensor.has_runtime_library +// CHECK: return %[[H]] : i1 +func.func @sparse_has_runtime() -> i1 { + %has_runtime = sparse_tensor.has_runtime_library + return %has_runtime : i1 +} diff --git a/mlir/test/Dialect/Tensor/canonicalize.mlir b/mlir/test/Dialect/Tensor/canonicalize.mlir index e5374f031be5530949be0d876f6dd575c22e7b28..ac365c9d297e889931516d5c6eae1dd0362934a4 100644 --- a/mlir/test/Dialect/Tensor/canonicalize.mlir +++ b/mlir/test/Dialect/Tensor/canonicalize.mlir @@ -830,6 +830,39 @@ func.func @fold_pack_constant_splat(%dest : tensor<8x16x8x32xf32>) -> tensor<8x1 // ----- +// CHECK-LABEL: func @fold_padding_value_pack_constant_splat +// CHECK-NOT: tensor.pack +// CHECK: arith.constant dense<1.000000e-01> : tensor<8x16x8x32xf32> +func.func @fold_padding_value_pack_constant_splat(%dest : tensor<8x16x8x32xf32>) -> tensor<8x16x8x32xf32> { + %pad = arith.constant 1.000000e-01 : f32 + %cst = arith.constant dense<1.000000e-01> : tensor<63x127xf32> + %0 = tensor.pack %cst + padding_value(%pad : f32) + outer_dims_perm = [1, 0] inner_dims_pos = [0, 1] + inner_tiles = [8, 32] into %dest : tensor<63x127xf32> -> tensor<8x16x8x32xf32> + return %0 : tensor<8x16x8x32xf32> +} + + +// ----- + +// CHECK-LABEL: func @nofold_padding_value_pack_constant_splat +// CHECK: arith.constant dense<1.000000e-01> : tensor<63x127xf32> +// CHECK: tensor.pack +func.func @nofold_padding_value_pack_constant_splat(%dest : tensor<8x16x8x32xf32>) -> tensor<8x16x8x32xf32> { + %pad = arith.constant 0.0 : f32 + %cst = arith.constant dense<1.000000e-01> : tensor<63x127xf32> + %0 = tensor.pack %cst + padding_value(%pad : f32) + outer_dims_perm = [1, 0] + inner_dims_pos = [0, 1] + inner_tiles = [8, 32] + into %dest : tensor<63x127xf32> -> tensor<8x16x8x32xf32> + return %0 : tensor<8x16x8x32xf32> +} + +// ----- + func.func @fold_padding_value_pack(%arg0: tensor<1200x500000xf32>) -> tensor<31250x1200x16x1xf32> { %cst = arith.constant 0.000000e+00 : f32 %0 = tensor.empty() : tensor<31250x1200x16x1xf32> @@ -2367,3 +2400,26 @@ func.func @dim_of_reshape_undominated(%arg0: tensor<*xf32>, %arg1: tensor<?xinde %dim = tensor.dim %reshape, %0 : tensor<*xf32> return %dim : index } + +// ----- + +// Test case: This test fails to fold because the index of tensor.dim is out_of_bounds +// CHECK-LABEL: func @dim_out_of_bounds( +// CHECK: %[[IDX:.*]] = index.constant 28 +// CHECK-NEXT: bufferization.alloc_tensor +// CHECK-NEXT: %[[DIM:.*]] = tensor.dim %{{.*}}, %[[IDX]] +// CHECK-NEXT: memref.alloc +// CHECK-NEXT: memref.cast +// CHECK-NEXT: affine.vector_load %{{.*}}[{{.*}}, {{.*}}, symbol(%[[DIM]])] +// CHECK-NEXT: return +func.func @dim_out_of_bounds() -> vector<7xi32> { + %c1 = arith.constant 1 : index + %idx28 = index.constant 28 + %c29 = arith.constant 29 : index + %3 = bufferization.alloc_tensor(%c29) : tensor<?xi16> + %dim = tensor.dim %3, %idx28 : tensor<?xi16> + %alloc_21 = memref.alloc(%c29) : memref<?x26x2xi32> + %16 = affine.vector_load %alloc_21[%c1, %c1, %dim] : memref<?x26x2xi32>, vector<7xi32> + return %16 : vector<7xi32> +} + diff --git a/mlir/test/Dialect/Tensor/decompose-concat.mlir b/mlir/test/Dialect/Tensor/decompose-concat.mlir index 159347b4f7aa283412a89abde3c487d69929b6a5..c0f23b8eddbd52ac4695648aeca74c62892d853e 100644 --- a/mlir/test/Dialect/Tensor/decompose-concat.mlir +++ b/mlir/test/Dialect/Tensor/decompose-concat.mlir @@ -73,7 +73,8 @@ func.func @decompose_dynamic_into_static_concat_dim(%arg0 : tensor<1x?x?xf32>, // CHECK: return %[[CONCAT]] : tensor<1x?x128xf32> module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root: !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.tensor.decompose_concat } : !transform.op<"func.func"> diff --git a/mlir/test/Dialect/Tensor/drop-redundant-insert-slice-rank-expansion.mlir b/mlir/test/Dialect/Tensor/drop-redundant-insert-slice-rank-expansion.mlir index e337fdd932142415910f2771b875283db51d4226..88e55062f47702693885071964b7ae0c8b140e08 100644 --- a/mlir/test/Dialect/Tensor/drop-redundant-insert-slice-rank-expansion.mlir +++ b/mlir/test/Dialect/Tensor/drop-redundant-insert-slice-rank-expansion.mlir @@ -9,3 +9,68 @@ func.func @test_drop_rank_expansion(%src: tensor<128x480xf32>, %dest: tensor<1x1 %extracted_slice = tensor.extract_slice %inserted_slice[0, 0, 0, 0] [1, 1, 123, 456] [1, 1, 1, 1] : tensor<1x1x128x480xf32> to tensor<123x456xf32> return %extracted_slice : tensor<123x456xf32> } + +// ----- + +func.func @fold_casting_insert_slice_of_extract_slice(%in : tensor<?x8x2x8xf32>, %dest : tensor<8x1x8xf32>) -> tensor<8x1x8xf32> { + %extracted_slice = tensor.extract_slice %in[0, 0, 0, 0] [1, 8, 1, 8] [1, 1, 1, 1] : tensor<?x8x2x8xf32> to tensor<8x8xf32> + %inserted_slice = tensor.insert_slice %extracted_slice into %dest[0, 0, 0] [8, 1, 8] [1, 1, 1] : tensor<8x8xf32> into tensor<8x1x8xf32> + return %inserted_slice : tensor<8x1x8xf32> +} +// CHECK-LABEL: func.func @fold_casting_insert_slice_of_extract_slice( +// CHECK-SAME: %[[ARG0:.*]]: tensor<?x8x2x8xf32> +// CHECK: %[[EXTRACTED_SLICE:.*]] = tensor.extract_slice %[[ARG0]][0, 0, 0, 0] [1, 8, 1, 8] [1, 1, 1, 1] +// CHECK-SAME: : tensor<?x8x2x8xf32> to tensor<8x1x8xf32> +// CHECK: return %[[EXTRACTED_SLICE]] : tensor<8x1x8xf32> + +// ----- + +func.func @fold_casting_insert_slice_of_strided_extract_slice(%in : tensor<?x8x2x8xf32>, %dest : tensor<1x4x8xf32>) -> tensor<1x4x8xf32> { + %extracted_slice = tensor.extract_slice %in[0, 0, 0, 0] [1, 4, 1, 8] [1, 2, 1, 1] : tensor<?x8x2x8xf32> to tensor<4x8xf32> + %inserted_slice = tensor.insert_slice %extracted_slice into %dest[0, 0, 0] [1, 4, 8] [1, 1, 1] : tensor<4x8xf32> into tensor<1x4x8xf32> + return %inserted_slice : tensor<1x4x8xf32> +} +// CHECK-LABEL: func.func @fold_casting_insert_slice_of_strided_extract_slice( +// CHECK-SAME: %[[ARG0:.*]]: tensor<?x8x2x8xf32> +// CHECK: %[[EXTRACTED_SLICE:.*]] = tensor.extract_slice %[[ARG0]][0, 0, 0, 0] [1, 4, 1, 8] [1, 2, 1, 1] +// CHECK-SAME: : tensor<?x8x2x8xf32> to tensor<1x4x8xf32> +// CHECK: return %[[EXTRACTED_SLICE]] : tensor<1x4x8xf32> + +// ----- + +func.func @no_fold_more_unit_dims_insert_slice_of_extract_slice(%in : tensor<?x8x8xf32>, %dest : tensor<1x1x8x8xf32>) -> tensor<1x1x8x8xf32> { + %extracted_slice = tensor.extract_slice %in[0, 0, 0] [1, 8, 8] [1, 1, 1] : tensor<?x8x8xf32> to tensor<8x8xf32> + %inserted_slice = tensor.insert_slice %extracted_slice into %dest[0, 0, 0, 0] [1, 1, 8, 8] [1, 1, 1, 1] : tensor<8x8xf32> into tensor<1x1x8x8xf32> + return %inserted_slice : tensor<1x1x8x8xf32> +} +// CHECK-LABEL: func.func @no_fold_more_unit_dims_insert_slice_of_extract_slice( +// CHECK-SAME: %[[ARG0:.*]]: tensor<?x8x8xf32> +// CHECK: %[[EXTRACTED_SLICE:.*]] = tensor.extract_slice %[[ARG0]] +// CHECK: %[[INSERTED_SLICE:.*]] = tensor.insert_slice %[[EXTRACTED_SLICE]] +// CHECK: return %[[INSERTED_SLICE]] : tensor<1x1x8x8xf32> + +// ----- + +func.func @no_fold_strided_insert_slice_of_extract_slice(%in : tensor<?x8x2x8xf32>, %dest : tensor<1x4x4xf32>) -> tensor<1x4x4xf32> { + %extracted_slice = tensor.extract_slice %in[0, 0, 0, 0] [1, 8, 1, 8] [1, 1, 1, 1] : tensor<?x8x2x8xf32> to tensor<8x8xf32> + %inserted_slice = tensor.insert_slice %extracted_slice into %dest[0, 0, 0] [1, 8, 8] [1, 2, 2] : tensor<8x8xf32> into tensor<1x4x4xf32> + return %inserted_slice : tensor<1x4x4xf32> +} +// CHECK-LABEL: func.func @no_fold_strided_insert_slice_of_extract_slice( +// CHECK-SAME: %[[ARG0:.*]]: tensor<?x8x2x8xf32> +// CHECK: %[[EXTRACTED_SLICE:.*]] = tensor.extract_slice %[[ARG0]] +// CHECK: %[[INSERTED_SLICE:.*]] = tensor.insert_slice %[[EXTRACTED_SLICE]] +// CHECK: return %[[INSERTED_SLICE]] : tensor<1x4x4xf32> + +// ----- + +func.func @no_fold_non_casting_insert_slice_of_extract_slice(%in : tensor<1x1x1x8x8xf32>, %dest : tensor<2x8x8xf32>) -> tensor<2x8x8xf32> { + %extracted_slice = tensor.extract_slice %in[0, 0, 0, 0, 0] [1, 1, 1, 8, 8] [1, 1, 1, 1, 1] : tensor<1x1x1x8x8xf32> to tensor<8x8xf32> + %inserted_slice = tensor.insert_slice %extracted_slice into %dest[0, 0, 0] [1, 8, 8] [1, 1, 1] : tensor<8x8xf32> into tensor<2x8x8xf32> + return %inserted_slice : tensor<2x8x8xf32> +} +// CHECK-LABEL: func.func @no_fold_non_casting_insert_slice_of_extract_slice( +// CHECK-SAME: %[[ARG0:.*]]: tensor<1x1x1x8x8xf32> +// CHECK: %[[EXTRACTED_SLICE:.*]] = tensor.extract_slice %[[ARG0]] +// CHECK: %[[INSERTED_SLICE:.*]] = tensor.insert_slice %[[EXTRACTED_SLICE]] +// CHECK: return %[[INSERTED_SLICE]] : tensor<2x8x8xf32> diff --git a/mlir/test/Dialect/Tensor/fold-empty-op.mlir b/mlir/test/Dialect/Tensor/fold-empty-op.mlir index 057e105f3b572c34ff2508a26e1159a9e0d66c9b..15f841f2128edb792194c93cc37d38d5534fb0df 100644 --- a/mlir/test/Dialect/Tensor/fold-empty-op.mlir +++ b/mlir/test/Dialect/Tensor/fold-empty-op.mlir @@ -1,7 +1,8 @@ // RUN: mlir-opt -split-input-file -transform-interpreter %s | FileCheck %s module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.tensor.fold_tensor_empty } : !transform.op<"func.func"> @@ -67,7 +68,8 @@ func.func @rank_reducing_empty_tensor_extract(%sz : index, %idx : index) -> tens // ----- module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.tensor.fold_tensor_empty {fold_single_use_only = true} diff --git a/mlir/test/Dialect/Tensor/fold-into-pack-and-unpack.mlir b/mlir/test/Dialect/Tensor/fold-into-pack-and-unpack.mlir index 682107dbebbfae8b880d0b270eb98c7896498e8b..aa860e33cf3517b6eb7434118d17117ece5625a0 100644 --- a/mlir/test/Dialect/Tensor/fold-into-pack-and-unpack.mlir +++ b/mlir/test/Dialect/Tensor/fold-into-pack-and-unpack.mlir @@ -290,22 +290,21 @@ func.func @tensor_pack_linalg_transpose_fold_dynamic_outer_and_tile_dims(%arg0: %return_value = tensor.cast %transposed : tensor<12x4x56x9x32x8x2xf32> to tensor<?x?x56x9x32x8x2xf32> return %return_value : tensor<?x?x56x9x32x8x2xf32> } -// CHECK: #[[map:.+]] = affine_map<()[s0] -> (s0 ceildiv 8)> -// CHECK: #[[map1:.+]] = affine_map<()[s0] -> (s0 ceildiv 2)> -// CHECK: module { -// CHECK: func.func @tensor_pack_linalg_transpose_fold_dynamic_outer_and_tile_dims( -// CHECK-SAME: %[[ARG0:.+]]: tensor<56x?x?x128xf32>) -// CHECK-DAG: %[[c1:.+]] = arith.constant 1 : index -// CHECK-DAG: %[[c2:.+]] = arith.constant 2 : index -// CHECK: %[[dim:.+]] = tensor.dim %[[ARG0]], %[[c1]] : tensor<56x?x?x128xf32> -// CHECK: %[[dim_0:.+]] = tensor.dim %[[ARG0]], %[[c2]] : tensor<56x?x?x128xf32> -// CHECK: %[[mapped_dim1:.+]] = affine.apply #[[map:.+]]()[%[[dim]]] -// CHECK: %[[mapped_dim2:.+]] = affine.apply #[[map1:.+]]()[%[[dim_0]]] -// CHECK: %[[INIT:.+]] = tensor.empty(%[[mapped_dim2]], %[[mapped_dim1]]) : tensor<?x4x56x?x32x8x2xf32> -// CHECK: %[[PACK:.+]] = tensor.pack %[[ARG0]] outer_dims_perm = [2, 3, 0, 1] inner_dims_pos = [3, 1, 2] inner_tiles = [32, 8, 2] into %[[INIT]] : tensor<56x?x?x128xf32> -> tensor<?x4x56x?x32x8x2xf32> -// CHECK: %[[CAST:.+]] = tensor.cast %[[PACK]] : tensor<?x4x56x?x32x8x2xf32> to tensor<?x?x56x9x32x8x2xf32> -// CHECK: return %[[CAST]] : tensor<?x?x56x9x32x8x2xf32> -// CHECK: } +// CHECK-DAG: #[[$MAP0:.+]] = affine_map<()[s0] -> (s0 ceildiv 8)> +// CHECK-DAG: #[[$MAP1:.+]] = affine_map<()[s0] -> (s0 ceildiv 2)> +// CHECK-LABEL: func.func @tensor_pack_linalg_transpose_fold_dynamic_outer_and_tile_dims( +// CHECK-SAME: %[[ARG0:.+]]: tensor<56x?x?x128xf32>) +// CHECK-DAG: %[[c1:.+]] = arith.constant 1 : index +// CHECK-DAG: %[[c2:.+]] = arith.constant 2 : index +// CHECK: %[[dim:.+]] = tensor.dim %[[ARG0]], %[[c1]] : tensor<56x?x?x128xf32> +// CHECK: %[[dim_0:.+]] = tensor.dim %[[ARG0]], %[[c2]] : tensor<56x?x?x128xf32> +// CHECK: %[[mapped_dim1:.+]] = affine.apply #[[$MAP0]]()[%[[dim]]] +// CHECK: %[[mapped_dim2:.+]] = affine.apply #[[$MAP1]]()[%[[dim_0]]] +// CHECK: %[[INIT:.+]] = tensor.empty(%[[mapped_dim2]], %[[mapped_dim1]]) : tensor<?x4x56x?x32x8x2xf32> +// CHECK: %[[PACK:.+]] = tensor.pack %[[ARG0]] outer_dims_perm = [2, 3, 0, 1] inner_dims_pos = [3, 1, 2] inner_tiles = [32, 8, 2] into %[[INIT]] : tensor<56x?x?x128xf32> -> tensor<?x4x56x?x32x8x2xf32> +// CHECK: %[[CAST:.+]] = tensor.cast %[[PACK]] : tensor<?x4x56x?x32x8x2xf32> to tensor<?x?x56x9x32x8x2xf32> +// CHECK: return %[[CAST]] : tensor<?x?x56x9x32x8x2xf32> +// CHECK: } // ----- @@ -323,7 +322,7 @@ func.func @tensor_pack_linalg_transpose_fold_dynamic_outer_dims_tile_dims_tile_s return %transposed : tensor<?x?x?x?x?x?x?xf32> } -// CHECK: #[[map:.+]] = affine_map<()[s0, s1] -> (s0 ceildiv s1)> +// CHECK: #[[$MAP:.+]] = affine_map<()[s0, s1] -> (s0 ceildiv s1)> // CHECK: module { // CHECK: func.func @tensor_pack_linalg_transpose_fold_dynamic_outer_dims_tile_dims_tile_sizes( // CHECK-SAME: %[[ARG0:.+]]: tensor<?x?x?x?xf32>, @@ -338,9 +337,9 @@ func.func @tensor_pack_linalg_transpose_fold_dynamic_outer_dims_tile_dims_tile_s // CHECK: %[[dim_0:.+]] = tensor.dim %[[ARG0]], %[[c1]] : tensor<?x?x?x?xf32> // CHECK: %[[dim_1:.+]] = tensor.dim %[[ARG0]], %[[c2]] : tensor<?x?x?x?xf32> // CHECK: %[[dim_2:.+]] = tensor.dim %[[ARG0]], %[[c3]] : tensor<?x?x?x?xf32> -// CHECK: %[[mapped_dim0:.+]] = affine.apply #[[map:.+]]()[%[[dim_2]], %[[ARG3]]] -// CHECK: %[[mapped_dim1:.+]] = affine.apply #[[map:.+]]()[%[[dim_0]], %[[ARG1]]] -// CHECK: %[[mapped_dim2:.+]] = affine.apply #[[map:.+]]()[%[[dim_1]], %[[ARG2]]] +// CHECK: %[[mapped_dim0:.+]] = affine.apply #[[$MAP]]()[%[[dim_2]], %[[ARG3]]] +// CHECK: %[[mapped_dim1:.+]] = affine.apply #[[$MAP]]()[%[[dim_0]], %[[ARG1]]] +// CHECK: %[[mapped_dim2:.+]] = affine.apply #[[$MAP]]()[%[[dim_1]], %[[ARG2]]] // CHECK: %[[INIT:.+]] = tensor.empty(%[[mapped_dim2]], %[[mapped_dim1]], %[[mapped_dim0]], %[[dim]], %[[ARG3]], %[[ARG1]], %[[ARG2]]) : tensor<?x?x?x?x?x?x?xf32> // CHECK: %[[PACK:.+]] = tensor.pack %[[ARG0]] outer_dims_perm = [2, 1, 3, 0] inner_dims_pos = [3, 1, 2] inner_tiles = [%[[ARG3]], %[[ARG1]], %[[ARG2]]] into %[[INIT]] : tensor<?x?x?x?xf32> -> tensor<?x?x?x?x?x?x?xf32> // CHECK: return %[[PACK]] : tensor<?x?x?x?x?x?x?xf32> @@ -465,7 +464,7 @@ func.func @linalg_transpose_tensor_pack_fold_dynamic_outer_dims_tile_dims_tile_s into %pack_dest : tensor<?x?x?x?xf32> -> tensor<?x?x?x?x?x?x?xf32> return %pack : tensor<?x?x?x?x?x?x?xf32> } -// CHECK: #[[map:.+]] = affine_map<()[s0, s1] -> (s0 ceildiv s1)> +// CHECK: #[[$MAP:.+]] = affine_map<()[s0, s1] -> (s0 ceildiv s1)> //CHECK-LABEL: func.func @linalg_transpose_tensor_pack_fold_dynamic_outer_dims_tile_dims_tile_sizes( // CHECK-SAME: %[[ARG0:.+]]: tensor<?x?x?x?xf32>, %[[ARG1:.+]]: tensor<?x?x?x?xf32>, // CHECK-SAME: %[[ARG2:.+]]: tensor<?x?x?x?x?x?x?xf32>, %[[ARG3:.+]]: index, %[[ARG4:.+]]: index, %[[ARG5:.+]]: index) -> tensor<?x?x?x?x?x?x?xf32> { @@ -477,9 +476,9 @@ func.func @linalg_transpose_tensor_pack_fold_dynamic_outer_dims_tile_dims_tile_s // CHECK: %[[DIM0:.+]] = tensor.dim %[[ARG0]], %[[C1]] : tensor<?x?x?x?xf32> // CHECK: %[[DIM1:.+]] = tensor.dim %[[ARG0]], %[[C2]] : tensor<?x?x?x?xf32> // CHECK: %[[DIM2:.+]] = tensor.dim %[[ARG0]], %[[C3]] : tensor<?x?x?x?xf32> -// CHECK: %[[VAL0:.+]] = affine.apply #[[map:.+]]()[%[[DIM2]], %[[ARG3]]] -// CHECK: %[[VAL1:.+]] = affine.apply #[[map:.+]]()[%[[DIM0]], %[[ARG4]]] -// CHECK: %[[VAL2:.+]] = affine.apply #[[map:.+]]()[%[[DIM]], %[[ARG5]]] +// CHECK: %[[VAL0:.+]] = affine.apply #[[$MAP]]()[%[[DIM2]], %[[ARG3]]] +// CHECK: %[[VAL1:.+]] = affine.apply #[[$MAP]]()[%[[DIM0]], %[[ARG4]]] +// CHECK: %[[VAL2:.+]] = affine.apply #[[$MAP]]()[%[[DIM]], %[[ARG5]]] // CHECK: %[[VAL3:.+]] = tensor.empty(%[[VAL1]], %[[DIM1]], %[[VAL2]], %[[VAL0]], %[[ARG3]], %[[ARG4]], %[[ARG5]]) : tensor<?x?x?x?x?x?x?xf32> // CHECK: %[[PACK:.+]] = tensor.pack %[[ARG0]] outer_dims_perm = [1, 2, 0, 3] inner_dims_pos = [3, 1, 0] inner_tiles = [%[[ARG3]], %[[ARG4]], %[[ARG5]]] into %[[VAL3]] : tensor<?x?x?x?xf32> -> tensor<?x?x?x?x?x?x?xf32> // CHECK: return %[[PACK]] : tensor<?x?x?x?x?x?x?xf32> @@ -506,13 +505,13 @@ func.func @linalg_transpose_tensor_pack_multiple_tiles(%arg0: tensor<?x32x128xbf into %2 : tensor<32x128x?xbf16> -> tensor<32x?x64x16x2xbf16> return %pack : tensor<32x?x64x16x2xbf16> } -// CHECK: #[[map:.+]] = affine_map<()[s0] -> (s0 ceildiv 16)> +// CHECK: #[[$MAP:.+]] = affine_map<()[s0] -> (s0 ceildiv 16)> //CHECK-LABEL: func.func @linalg_transpose_tensor_pack_multiple_tiles( // CHECK-SAME: %[[ARG0:.+]]: tensor<?x32x128xbf16>) -> tensor<32x?x64x16x2xbf16> { // CHECK-DAG: %[[C0:.+]] = arith.constant 0 : index // CHECK-DAG: %[[CST:.+]] = arith.constant 0.000000e+00 : bf16 // CHECK: %[[DIM:.+]] = tensor.dim %[[ARG0]], %[[C0]] : tensor<?x32x128xbf16> -// CHECK: %[[VAL0:.+]] = affine.apply #[[map:.+]]()[%[[DIM]]] +// CHECK: %[[VAL0:.+]] = affine.apply #[[$MAP]]()[%[[DIM]]] // CHECK: %[[VAL1:.+]] = tensor.empty(%[[VAL0]]) : tensor<32x?x64x16x2xbf16> // CHECK: %[[PACK:.+]] = tensor.pack %[[ARG0]] // CHECK-SAME: padding_value(%[[CST]] : bf16) @@ -522,3 +521,91 @@ func.func @linalg_transpose_tensor_pack_multiple_tiles(%arg0: tensor<?x32x128xbf // CHECK-SAME: into %[[VAL1]] : tensor<?x32x128xbf16> -> tensor<32x?x64x16x2xbf16> // CHECK: return %[[PACK]] : tensor<32x?x64x16x2xbf16> // CHECK: } + +// ----- + +func.func @linalg_transpose_tensor_unpack_fold(%arg0: tensor<1x1x4x16xi32>) -> tensor<16x4xi32> { + %0 = tensor.empty() : tensor<1x1x16x4xi32> + %transposed = linalg.transpose ins(%arg0 : tensor<1x1x4x16xi32>) + outs(%0 : tensor<1x1x16x4xi32>) + permutation = [1, 0, 3, 2] + %1 = tensor.empty() : tensor<16x4xi32> + %unpack = tensor.unpack %transposed + outer_dims_perm = [0, 1] + inner_dims_pos = [0, 1] + inner_tiles = [16, 4] into + %1 : tensor<1x1x16x4xi32> -> tensor<16x4xi32> + return %unpack : tensor<16x4xi32> +} +//CHECK-LABEL: func.func @linalg_transpose_tensor_unpack_fold( +// CHECK-SAME: %[[ARG0:.+]]: tensor<1x1x4x16xi32>) -> tensor<16x4xi32> { +// CHECK: %[[OUT:.+]] = tensor.empty() : tensor<16x4xi32> +// CHECK: %[[UNPACK:.+]] = tensor.unpack %[[ARG0]] +// CHECK-SAME: outer_dims_perm = [1, 0] +// CHECK-SAME: inner_dims_pos = [1, 0] +// CHECK-SAME: inner_tiles = [4, 16] +// CHEKC-SAME: into %[[OUT]] : tensor<1x1x4x16xi32> -> tensor<16x4xi32> +// CHECK: return %[[UNPACK]] : tensor<16x4xi32> +// CHECK: } + +// ----- + +func.func @linalg_transpose_tensor_unpack_fold_dynamic_outer_dims_tile_dims_tile_sizes(%arg0: tensor<?x?x?x?xf32>, %transpose_dest: tensor<?x?x?x?xf32>, %unpack_dest: tensor<?x?xf32>, %tile_p : index, %tile_q : index) -> tensor<?x?xf32> { + %transposed = linalg.transpose + ins(%arg0 : tensor<?x?x?x?xf32>) + outs(%transpose_dest : tensor<?x?x?x?xf32>) + permutation = [1, 0, 3, 2] + + %unpack = tensor.unpack %transposed + outer_dims_perm = [1, 0] + inner_dims_pos = [0, 1] + inner_tiles = [%tile_p, %tile_q] + into %unpack_dest : tensor<?x?x?x?xf32> -> tensor<?x?xf32> + return %unpack : tensor<?x?xf32> +} +// CHECK: #[[$MAP:.+]] = affine_map<()[s0, s1] -> (s0 * s1)> +// CHECK-LABEL: func.func @linalg_transpose_tensor_unpack_fold_dynamic_outer_dims_tile_dims_tile_sizes( +// CHECK-SAME: %[[ARG0:.+]]: tensor<?x?x?x?xf32>, %[[ARG1:.+]]: tensor<?x?x?x?xf32>, %[[ARG2:.+]]: tensor<?x?xf32>, +// CHECK-SAME: %[[IDX1:.+]]: index, %[[IDX2:.+]]: index) -> tensor<?x?xf32> { +// CHECK-DAG: %[[CST1:.+]] = arith.constant 1 : index +// CHECK-DAG: %[[CST0:.+]] = arith.constant 0 : index +// CHECK-DAG: %[[DIM0:.+]] = tensor.dim %[[ARG0]], %[[CST0]] : tensor<?x?x?x?xf32> +// CHECK-DAG: %[[DIM1:.+]] = tensor.dim %[[ARG0]], %[[CST1]] : tensor<?x?x?x?xf32> +// CHECK-DAG: %[[AMAP0:.+]] = affine.apply #[[$MAP]]()[%[[DIM1]], %[[IDX2]]] +// CHECK-DAG: %[[AMAP1:.+]] = affine.apply #[[$MAP]]()[%[[DIM0]], %[[IDX1]]] +// CHECK: %[[OUT:.+]] = tensor.empty(%[[AMAP1]], %[[AMAP0]]) : tensor<?x?xf32> +// CHECK: %[[UNPACK:.+]] = tensor.unpack %[[ARG0]] +// CHECK-SAME: outer_dims_perm = [0, 1] +// CHECK-SAME: inner_dims_pos = [1, 0] +// CHECK-SAME: inner_tiles = [%[[IDX2]], %[[IDX1]]] +// CHECK-SAME: into %[[OUT]] : tensor<?x?x?x?xf32> -> tensor<?x?xf32> +// CHECK: return %[[UNPACK]] : tensor<?x?xf32> +// CHECK: } + +// ----- + +func.func @tensor_unpack_linalg_transpose_fold(%arg0: tensor<56x57x1x64xf32>) -> tensor<3648x56xf32> { + %0 = tensor.empty() : tensor<56x3648xf32> + %pack = tensor.unpack %arg0 + outer_dims_perm = [0, 1] + inner_dims_pos = [0, 1] + inner_tiles = [1, 64] + into %0 : tensor<56x57x1x64xf32> -> tensor<56x3648xf32> + + %1 = tensor.empty() : tensor<3648x56xf32> + %transposed = linalg.transpose + ins(%pack : tensor<56x3648xf32>) + outs(%1 : tensor<3648x56xf32>) + permutation = [1,0] + return %transposed : tensor<3648x56xf32> +} +// CHECK-LABEL: func.func @tensor_unpack_linalg_transpose_fold( +// CHECK-SAME: %[[ARG0:.+]]: tensor<56x57x1x64xf32>) -> tensor<3648x56xf32> { +// CHECK: %[[OUT:.+]] = tensor.empty() : tensor<3648x56xf32> +// CHECK: %[[UNPACK:.+]] = tensor.unpack %[[ARG0]] +// CHECK-SAME: outer_dims_perm = [1, 0] +// CHECK-SAME: inner_dims_pos = [1, 0] +// CHECK-SAME: inner_tiles = [1, 64] +// CHECK-SAME: into %[[OUT:.+]] : tensor<56x57x1x64xf32> -> tensor<3648x56xf32> +// CHECK: return %[[UNPACK]] : tensor<3648x56xf32> +// CHECK: } diff --git a/mlir/test/Dialect/Tensor/fold-tensor-subset-ops-into-vector-transfers.mlir b/mlir/test/Dialect/Tensor/fold-tensor-subset-ops-into-vector-transfers.mlir index 505abc8f35335952075c7c047c6ec6b0805345f2..6213db3956f9a1e47b55d5429e940aeaf9e9d190 100644 --- a/mlir/test/Dialect/Tensor/fold-tensor-subset-ops-into-vector-transfers.mlir +++ b/mlir/test/Dialect/Tensor/fold-tensor-subset-ops-into-vector-transfers.mlir @@ -1,7 +1,8 @@ // RUN: mlir-opt -split-input-file -transform-interpreter %s | FileCheck %s module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.tensor.fold_tensor_subset_ops_into_vector_transfers } : !transform.op<"func.func"> diff --git a/mlir/test/Dialect/Tensor/one-shot-bufferize.mlir b/mlir/test/Dialect/Tensor/one-shot-bufferize.mlir index 38c3bb8af8107d8617f6fd6367bdf59f7d8113cf..e2169fe1404c82e60be71a1f5b24199d3b08bdac 100644 --- a/mlir/test/Dialect/Tensor/one-shot-bufferize.mlir +++ b/mlir/test/Dialect/Tensor/one-shot-bufferize.mlir @@ -1,9 +1,9 @@ // RUN: mlir-opt %s -one-shot-bufferize="bufferize-function-boundaries" -drop-equivalent-buffer-results -split-input-file | FileCheck %s // Run fuzzer with different seeds. -// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-fuzzer-seed=23 bufferize-function-boundaries" -split-input-file -o /dev/null -// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-fuzzer-seed=59 bufferize-function-boundaries" -split-input-file -o /dev/null -// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-fuzzer-seed=91 bufferize-function-boundaries" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=23 bufferize-function-boundaries" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=59 bufferize-function-boundaries" -split-input-file -o /dev/null +// RUN: mlir-opt %s -one-shot-bufferize="test-analysis-only analysis-heuristic=fuzzer analysis-fuzzer-seed=91 bufferize-function-boundaries" -split-input-file -o /dev/null // Test bufferization using memref types that have no layout map. // RUN: mlir-opt %s -one-shot-bufferize="unknown-type-conversion=identity-layout-map bufferize-function-boundaries" -split-input-file -o /dev/null diff --git a/mlir/test/Dialect/Tensor/rewrite-as-constant.mlir b/mlir/test/Dialect/Tensor/rewrite-as-constant.mlir index d68a6bd25286d71294bd1ba781056414ff8f465e..1a1cf9e407d805d6b07d5de02adda024b3bb794a 100644 --- a/mlir/test/Dialect/Tensor/rewrite-as-constant.mlir +++ b/mlir/test/Dialect/Tensor/rewrite-as-constant.mlir @@ -1,7 +1,8 @@ // RUN: mlir-opt -split-input-file -transform-interpreter %s | FileCheck %s module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.tensor.rewrite_as_constant } : !transform.op<"func.func"> diff --git a/mlir/test/Dialect/Tosa/canonicalize.mlir b/mlir/test/Dialect/Tosa/canonicalize.mlir index e7ede2e0ccef9a88e8c4994a87a9f8dfa0374f2e..6eac759a083645c4414d9ca2c263b4ca08e072d7 100644 --- a/mlir/test/Dialect/Tosa/canonicalize.mlir +++ b/mlir/test/Dialect/Tosa/canonicalize.mlir @@ -365,6 +365,14 @@ func.func @reshape_canonicalize(%arg0: tensor<?x10xf32>) -> tensor<?x10xf32> { return %0 : tensor<?x10xf32> } +// CHECK-LABEL: @reshape_canonicalize_dyn_nofold +func.func @reshape_canonicalize_dyn_nofold(%arg0: tensor<?x?x10xf32>) -> tensor<?x?x10xf32> { + // CHECK: %[[VAR0:.+]] = tosa.reshape %arg0 {new_shape = array<i64: -1, 2, 10>} : (tensor<?x?x10xf32>) -> tensor<?x?x10xf32> + // CHECK: return %[[VAR0]] : tensor<?x?x10xf32> + %0 = tosa.reshape %arg0 {new_shape = array<i64: -1, 2, 10>} : (tensor<?x?x10xf32>) -> tensor<?x?x10xf32> + return %0 : tensor<?x?x10xf32> +} + // CHECK-LABEL: @reshape_canonicalize_double func.func @reshape_canonicalize_double(%arg0: tensor<?x10xf32>) -> tensor<?x5xf32> { // CHECK: %[[VAL_1:.*]] = tosa.reshape %arg0 {new_shape = array<i64: -1, 5>} diff --git a/mlir/test/Dialect/Tosa/constant-op-fold.mlir b/mlir/test/Dialect/Tosa/constant-op-fold.mlir index 27ca3ae3c21be68ae426da221933848ae275dac3..de752f31fcbaa1ed2346997580187d2c2fc16588 100644 --- a/mlir/test/Dialect/Tosa/constant-op-fold.mlir +++ b/mlir/test/Dialect/Tosa/constant-op-fold.mlir @@ -112,6 +112,23 @@ func.func @transpose_nofold_quantized_types() -> tensor<1x1x2x2x!quant.uniform<i return %0: tensor<1x1x2x2x!quant.uniform<i8<-127:127>:f32:3, {1.000000e-01,1.000000e-01}>> } +// CHECK-LABEL: @transpose_nofold_dense_resource +func.func @transpose_nofold_dense_resource() -> tensor<2x2xf32> { + %0 = "tosa.const"() <{value = dense_resource<resource> : tensor<2x2xf32>}> : () -> tensor<2x2xf32> + %1 = "tosa.const"() <{value = dense<[1, 0]> : tensor<2xi32>}> : () -> tensor<2xi32> + + // CHECK: tosa.transpose + %2 = tosa.transpose %0, %1 : (tensor<2x2xf32>, tensor<2xi32>) -> tensor<2x2xf32> + return %2 : tensor<2x2xf32> +} +{-# + dialect_resources: { + builtin: { + resource: "0x08000000010000000000000002000000000000000300000000000000" + } + } +#-} + // ----- // CHECK-LABEL: @fold_add_zero_rhs_f32 diff --git a/mlir/test/Dialect/Tosa/level_check.mlir b/mlir/test/Dialect/Tosa/level_check.mlir index 35ecbcc799e3dfb309f3ec46e85315bca443e3e8..d8dd878051f18d546873d93791e3a4bd464389b1 100644 --- a/mlir/test/Dialect/Tosa/level_check.mlir +++ b/mlir/test/Dialect/Tosa/level_check.mlir @@ -115,6 +115,22 @@ func.func @test_const(%arg0 : tensor<1x1xi32>) -> tensor<1x1x1x1x1x1x1xi32> { // ----- +func.func @test_const_i2(%arg0 : tensor<1xi2>) { + // expected-error@+1 {{'tosa.const' op is not profile-aligned: element type 'i2' is not legal}} + %0 = "tosa.const"() {value = dense<0> : tensor<1xi2>} : () -> tensor<1xi2> + return +} + +// ----- + +func.func @test_const_ui32(%arg0 : tensor<1xui32>) { + // expected-error@+1 {{'tosa.const' op is not profile-aligned: element type 'ui32' is not legal}} + %0 = "tosa.const"() {value = dense<0> : tensor<1xui32>} : () -> tensor<1xui32> + return +} + +// ----- + func.func @test_avgpool2d_kernel_y(%arg0: tensor<1x32x32x8xf32>) -> tensor<1x32x32x8xf32> { // expected-error@+1 {{'tosa.avg_pool2d' op failed level check: kernel <= MAX_KERNEL}} %0 = "tosa.avg_pool2d"(%arg0) {kernel = array<i64: 8193, 1>, pad = array<i64: 4, 4, 4, 4>, stride = array<i64: 1, 1>, acc_type = f32} : diff --git a/mlir/test/Dialect/Transform/foreach-match.mlir b/mlir/test/Dialect/Transform/foreach-match.mlir new file mode 100644 index 0000000000000000000000000000000000000000..206625ae0746beb101e697cd00f50fb919a2f055 --- /dev/null +++ b/mlir/test/Dialect/Transform/foreach-match.mlir @@ -0,0 +1,80 @@ +// RUN: mlir-opt %s --transform-interpreter --split-input-file --verify-diagnostics + +// Silenceable diagnostics suppressed. +module attributes { transform.with_named_sequence } { + func.func @test_loop_peeling_not_beneficial() { + %lb = arith.constant 0 : index + %ub = arith.constant 40 : index + %step = arith.constant 5 : index + scf.for %i = %lb to %ub step %step { + arith.addi %i, %i : index + } + return + } + + transform.named_sequence @peel(%arg0: !transform.op<"scf.for"> {transform.consumed}) { + transform.loop.peel %arg0 : (!transform.op<"scf.for">) -> (!transform.any_op, !transform.any_op) + transform.yield + } + transform.named_sequence @match_for(%arg0: !transform.any_op {transform.readonly}) -> !transform.any_op { + transform.match.operation_name %arg0 ["scf.for"] : !transform.any_op + transform.yield %arg0 : !transform.any_op + } + transform.named_sequence @__transform_main(%root: !transform.any_op) { + transform.sequence %root : !transform.any_op failures(suppress) { + ^bb0(%arg0: !transform.any_op): + transform.foreach_match in %arg0 + @match_for -> @peel + : (!transform.any_op) -> !transform.any_op + transform.yield + } + transform.yield + } +} + +// ----- + +// Silenceable diagnostics propagated. +module attributes { transform.with_named_sequence } { + func.func @test_loop_peeling_not_beneficial() { + %lb = arith.constant 0 : index + %ub = arith.constant 40 : index + %step = arith.constant 5 : index + // expected-note @below {{when applied to this matching payload}} + scf.for %i = %lb to %ub step %step { + arith.addi %i, %i : index + } + return + } + + // expected-note @below {{failed to peel the last iteration}} + transform.named_sequence @peel(%arg0: !transform.op<"scf.for"> {transform.consumed}) { + transform.loop.peel %arg0 : (!transform.op<"scf.for">) -> (!transform.any_op, !transform.any_op) + transform.yield + } + transform.named_sequence @match_for(%arg0: !transform.any_op {transform.readonly}) -> !transform.any_op { + transform.match.operation_name %arg0 ["scf.for"] : !transform.any_op + transform.yield %arg0 : !transform.any_op + } + transform.named_sequence @main_suppress(%root: !transform.any_op) { + transform.sequence %root : !transform.any_op failures(suppress) { + ^bb0(%arg0: !transform.any_op): + transform.foreach_match in %arg0 + @match_for -> @peel + : (!transform.any_op) -> !transform.any_op + transform.yield + } + transform.yield + } + transform.named_sequence @__transform_main(%root: !transform.any_op) { + transform.sequence %root : !transform.any_op failures(propagate) { + ^bb0(%arg0: !transform.any_op): + // expected-error @below {{actions failed}} + transform.foreach_match in %arg0 + @match_for -> @peel + : (!transform.any_op) -> !transform.any_op + transform.yield + } + transform.yield + } +} diff --git a/mlir/test/Dialect/Transform/ops-invalid.mlir b/mlir/test/Dialect/Transform/ops-invalid.mlir index 73a5f36af92952fab6396b3546043b557bb913bc..cc04e65420c5b7edfbd1a4706bf771198c0c4e8f 100644 --- a/mlir/test/Dialect/Transform/ops-invalid.mlir +++ b/mlir/test/Dialect/Transform/ops-invalid.mlir @@ -771,3 +771,14 @@ module attributes { transform.with_named_sequence } { transform.yield %arg0 : !transform.any_op } } + +// ----- + +module attributes { transform.with_named_sequence } { + transform.named_sequence @match_matmul(%entry: !transform.any_op) -> () { + %c3 = transform.param.constant 1 : i64 -> !transform.param<i64> + // expected-error @below {{op operand #0 must be TransformHandleTypeInterface instance}} + transform.print %c3 : !transform.param<i64> + transform.yield + } +} diff --git a/mlir/test/Dialect/Transform/ops.mlir b/mlir/test/Dialect/Transform/ops.mlir index a718d6a9e9fd90f8445d41d34dd34322517f9351..ecef7e181e903954081f3981d9cb95276e5f70ae 100644 --- a/mlir/test/Dialect/Transform/ops.mlir +++ b/mlir/test/Dialect/Transform/ops.mlir @@ -86,16 +86,18 @@ transform.sequence failures(propagate) { } // CHECK: transform.sequence -// CHECK: print -// CHECK: print -// CHECK: print -// CHECK: print +// CHECK-COUNT-9: print transform.sequence failures(propagate) { ^bb0(%arg0: !transform.any_op): transform.print %arg0 : !transform.any_op transform.print transform.print %arg0 {name = "test"} : !transform.any_op transform.print {name = "test"} + transform.print {name = "test", assume_verified} + transform.print %arg0 {assume_verified} : !transform.any_op + transform.print %arg0 {use_local_scope} : !transform.any_op + transform.print %arg0 {skip_regions} : !transform.any_op + transform.print %arg0 {assume_verified, use_local_scope, skip_regions} : !transform.any_op } // CHECK: transform.sequence diff --git a/mlir/test/Dialect/Transform/test-interpreter-printing.mlir b/mlir/test/Dialect/Transform/test-interpreter-printing.mlir new file mode 100644 index 0000000000000000000000000000000000000000..a54c83d2b249eb473934da1c51e256771613175e --- /dev/null +++ b/mlir/test/Dialect/Transform/test-interpreter-printing.mlir @@ -0,0 +1,56 @@ +// RUN: mlir-opt %s --transform-interpreter --allow-unregistered-dialect --verify-diagnostics | FileCheck %s + +// RUN: mlir-opt %s --transform-interpreter --allow-unregistered-dialect --verify-diagnostics \ +// RUN: --mlir-print-debuginfo | FileCheck %s --check-prefix=CHECK-LOC + +func.func @nested_ops() { + "test.qux"() ({ + // expected-error @below{{fail_to_verify is set}} + "test.baz"() ({ + "test.bar"() : () -> () + }) : () -> () + }) : () -> () +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op) { + // CHECK-LABEL{LITERAL}: [[[ IR printer: START top-level ]]] + // CHECK-NEXT: module { + // CHECK-LOC-LABEL{LITERAL}: [[[ IR printer: START top-level ]]] + // CHECK-LOC-NEXT: #{{.+}} = loc( + // CHECK-LOC-NEXT: module { + transform.print {name = "START"} + + // CHECK{LITERAL}: [[[ IR printer: Local scope top-level ]]] + // CHECK-NEXT: module { + // CHECK-LOC{LITERAL}: [[[ IR printer: Local scope top-level ]]] + // CHECK-LOC-NEXT: module { + transform.print {name = "Local scope", use_local_scope} + + %baz = transform.structured.match ops{["test.baz"]} in %arg0 : (!transform.any_op) -> !transform.any_op + + // CHECK{LITERAL}: [[[ IR printer: ]]] + // CHECK-NEXT: "test.baz"() ({ + // CHECK-NEXT: "test.bar"() : () -> () + // CHECK-NEXT: }) : () -> () + transform.print %baz : !transform.any_op + + // CHECK{LITERAL}: [[[ IR printer: Baz ]]] + // CHECK-NEXT: "test.baz"() ({ + transform.print %baz {name = "Baz"} : !transform.any_op + + // CHECK{LITERAL}: [[[ IR printer: No region ]]] + // CHECK-NEXT: "test.baz"() ({...}) : () -> () + transform.print %baz {name = "No region", skip_regions} : !transform.any_op + + // CHECK{LITERAL}: [[[ IR printer: No verify ]]] + // CHECK-NEXT: "test.baz"() ({ + // CHECK-NEXT: transform.test_dummy_payload_op {fail_to_verify} : () -> () + transform.test_produce_invalid_ir %baz : !transform.any_op + transform.print %baz {name = "No verify", assume_verified} : !transform.any_op + + // CHECK-LABEL{LITERAL}: [[[ IR printer: END top-level ]]] + transform.print {name = "END"} + transform.yield + } +} diff --git a/mlir/test/Dialect/Transform/test-pass-application.mlir b/mlir/test/Dialect/Transform/test-pass-application.mlir index 7cb5387b937d45c191a686fb535afb2a24fe46a2..460ac3947f5c8227848c939677330da90255b01c 100644 --- a/mlir/test/Dialect/Transform/test-pass-application.mlir +++ b/mlir/test/Dialect/Transform/test-pass-application.mlir @@ -78,6 +78,7 @@ module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%arg1: !transform.any_op) { %1 = transform.structured.match ops{["func.func"]} in %arg1 : (!transform.any_op) -> !transform.any_op // expected-error @below {{failed to add pass or pass pipeline to pipeline: canonicalize}} + // expected-error @below {{<Pass-Options-Parser>: no such option invalid-option}} transform.apply_registered_pass "canonicalize" to %1 {options = "invalid-option=1"} : (!transform.any_op) -> !transform.any_op transform.yield } diff --git a/mlir/test/Dialect/Vector/canonicalize.mlir b/mlir/test/Dialect/Vector/canonicalize.mlir index 4c73a6271786e6012d5303422cde1ff2c02985a4..627ac54cf145bfe0e3761e8f74c8170ff7706aa3 100644 --- a/mlir/test/Dialect/Vector/canonicalize.mlir +++ b/mlir/test/Dialect/Vector/canonicalize.mlir @@ -2483,6 +2483,18 @@ func.func @all_true_vector_mask(%a : vector<3x4xf32>) -> vector<3x4xf32> { // ----- +// CHECK-LABEL: func @all_true_vector_mask_no_result( +func.func @all_true_vector_mask_no_result(%a : vector<3x4xf32>, %m : memref<3x4xf32>) { +// CHECK-NOT: vector.mask +// CHECK: vector.transfer_write + %c0 = arith.constant 0 : index + %all_true = vector.constant_mask [3, 4] : vector<3x4xi1> + vector.mask %all_true { vector.transfer_write %a, %m[%c0, %c0] : vector<3x4xf32>, memref<3x4xf32> } : vector<3x4xi1> + return +} + +// ----- + // CHECK-LABEL: func.func @fold_shape_cast_with_mask( // CHECK-SAME: %[[VAL_0:.*]]: tensor<1x?xf32>) -> vector<1x4xi1> { func.func @fold_shape_cast_with_mask(%arg0: tensor<1x?xf32>) -> vector<1x4xi1> { diff --git a/mlir/test/Dialect/Vector/linearize.mlir b/mlir/test/Dialect/Vector/linearize.mlir index 2cbf9bec7a41364ac72355fea20da8b2b69a6041..f0e9b3a05c066ebc8a2da9db4d69e618fd28e367 100644 --- a/mlir/test/Dialect/Vector/linearize.mlir +++ b/mlir/test/Dialect/Vector/linearize.mlir @@ -1,92 +1,156 @@ -// RUN: mlir-opt %s -split-input-file -test-vector-linearize | FileCheck %s -// RUN: mlir-opt %s -split-input-file -test-vector-linearize=target-vector-bitwidth=128 | FileCheck %s --check-prefix=CHECK128 -// RUN: mlir-opt %s -split-input-file -test-vector-linearize=target-vector-bitwidth=0 | FileCheck %s --check-prefix=CHECK0 - -// CHECK-LABEL: test_linearize -// CHECK128-LABEL: test_linearize -// CHECK0-LABEL: test_linearize -// CHECK-SAME: (%[[ORIG_ARG:.*]]: vector<2x2xf32>) -// CHECK128-SAME: (%[[ORIG_ARG:.*]]: vector<2x2xf32>) -// CHECK: %[[ARG:.*]] = vector.shape_cast %[[ORIG_ARG]] : vector<2x2xf32> to vector<4xf32> -// CHECK128: %[[ARG:.*]] = vector.shape_cast %[[ORIG_ARG]] : vector<2x2xf32> to vector<4xf32> +// RUN: mlir-opt %s -split-input-file -test-vector-linearize -verify-diagnostics | FileCheck %s --check-prefixes=ALL,DEFAULT +// RUN: mlir-opt %s -split-input-file -test-vector-linearize=target-vector-bitwidth=128 -verify-diagnostics | FileCheck %s --check-prefixes=ALL,BW-128 +// RUN: mlir-opt %s -split-input-file -test-vector-linearize=target-vector-bitwidth=0 | FileCheck %s --check-prefixes=ALL,BW-0 + +// ALL-LABEL: test_linearize +// ALL-SAME: (%[[ORIG_ARG:.*]]: vector<2x2xf32>) func.func @test_linearize(%arg0: vector<2x2xf32>) -> vector<2x2xf32> { -// CHECK: %[[C1:.*]] = arith.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00]> : vector<4xf32> -// CHECK128: %[[C1:.*]] = arith.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00]> : vector<4xf32> -// CHECK0: %[[C1:.*]] = arith.constant dense<{{.*}}> : vector<2x2xf32> + // DEFAULT: %[[ARG:.*]] = vector.shape_cast %[[ORIG_ARG]] : vector<2x2xf32> to vector<4xf32> + // DEFAULT: %[[CST:.*]] = arith.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00]> : vector<4xf32> + // DEFAULT: %[[RES:.*]] = vector.shape_cast %[[CST]] : vector<4xf32> to vector<2x2xf32> + + // BW-128: %[[ARG:.*]] = vector.shape_cast %[[ORIG_ARG]] : vector<2x2xf32> to vector<4xf32> + // BW-128: %[[CST:.*]] = arith.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00]> : vector<4xf32> + // BW-128: %[[RES:.*]] = vector.shape_cast %[[CST]] : vector<4xf32> to vector<2x2xf32> + // BW-0: %[[RES:.*]] = arith.constant dense<{{.*}}> : vector<2x2xf32> %0 = arith.constant dense<[[1.0, 2.0], [3.0, 4.0]]> : vector<2x2xf32> -// CHECK: %[[RES:.*]] = vector.shape_cast %[[C1]] : vector<4xf32> to vector<2x2xf32> -// CHECK128: %[[RES:.*]] = vector.shape_cast %[[C1]] : vector<4xf32> to vector<2x2xf32> -// Arith and math ops are handled in generic way, check some of them -// CHECK: %{{.*}} = math.sin %[[ARG]] : vector<4xf32> -// CHECK128: %{{.*}} = math.sin %[[ARG]] : vector<4xf32> -// CHECK0: %{{.*}} = math.sin %{{.*}} : vector<2x2xf32> + + // DEFAULT: %{{.*}} = math.sin %[[ARG]] : vector<4xf32> + // BW-128: %{{.*}} = math.sin %[[ARG]] : vector<4xf32> + // BW-0: %{{.*}} = math.sin %{{.*}} : vector<2x2xf32> %1 = math.sin %arg0 : vector<2x2xf32> -// CHECK: %{{.*}} = arith.addf %[[ARG]], %[[C1]] : vector<4xf32> -// CHECK128: %{{.*}} = arith.addf %[[ARG]], %[[C1]] : vector<4xf32> -// CHECK0: %{{.*}} = arith.addf %{{.*}} : vector<2x2xf32> + // DEFAULT: %{{.*}} = arith.addf %[[ARG]], %[[CST]] : vector<4xf32> + // BW-128: %{{.*}} = arith.addf %[[ARG]], %[[CST]] : vector<4xf32> + // BW-0: %{{.*}} = arith.addf %{{.*}} : vector<2x2xf32> %2 = arith.addf %arg0, %0 : vector<2x2xf32> -// CHECK: return %[[RES]] : vector<2x2xf32> -// CHECK128: return %[[RES]] : vector<2x2xf32> + // ALL: return %[[RES]] : vector<2x2xf32> return %0 : vector<2x2xf32> } -// CHECK-LABEL: test_partial_linearize -// CHECK128-LABEL: test_partial_linearize -// CHECK0-LABEL: test_partial_linearize -// CHECK-SAME: (%[[ORIG_ARG:.*]]: vector<2x2xf32>, %[[ORIG_ARG2:.*]]: vector<4x4xf32>) -// CHECK128-SAME: (%[[ORIG_ARG:.*]]: vector<2x2xf32>, %[[ORIG_ARG2:.*]]: vector<4x4xf32>) -// CHECK0-SAME: (%[[ORIG_ARG:.*]]: vector<2x2xf32>, %[[ORIG_ARG2:.*]]: vector<4x4xf32>) -// CHECK: %[[ARG:.*]] = vector.shape_cast %[[ORIG_ARG]] : vector<2x2xf32> to vector<4xf32> -// CHECK128: %[[ARG:.*]] = vector.shape_cast %[[ORIG_ARG]] : vector<2x2xf32> to vector<4xf32> -// CHECK: %[[ARG2:.*]] = vector.shape_cast %[[ORIG_ARG2]] : vector<4x4xf32> to vector<16xf32> +// ----- + +// ALL-LABEL: test_partial_linearize +// ALL-SAME: (%[[ORIG_ARG:.*]]: vector<2x2xf32>, %[[ORIG_ARG2:.*]]: vector<4x4xf32>) func.func @test_partial_linearize(%arg0: vector<2x2xf32>, %arg1: vector<4x4xf32>) -> vector<2x2xf32> { -// CHECK: %[[C1:.*]] = arith.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00]> : vector<4xf32> -// CHECK128: %[[C1:.*]] = arith.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00]> : vector<4xf32> -// CHECK0: %[[C1:.*]] = arith.constant dense<{{.*}}> : vector<2x2xf32> + // DEFAULT: %[[ARG:.*]] = vector.shape_cast %[[ORIG_ARG]] : vector<2x2xf32> to vector<4xf32> + // DEFAULT: %[[ARG2:.*]] = vector.shape_cast %[[ORIG_ARG2]] : vector<4x4xf32> to vector<16xf32> + // DEFAULT: %[[CST:.*]] = arith.constant dense<{{.*}}> : vector<4xf32> + // DEFAULT: %[[RES:.*]] = vector.shape_cast %[[CST]] : vector<4xf32> to vector<2x2xf32> + // BW-128: %[[ARG:.*]] = vector.shape_cast %[[ORIG_ARG]] : vector<2x2xf32> to vector<4xf32> + // BW-128: %[[CST:.*]] = arith.constant dense<{{.*}}> : vector<4xf32> + // BW-128: %[[RES:.*]] = vector.shape_cast %[[CST]] : vector<4xf32> to vector<2x2xf32> + + // BW-0: %[[RES:.*]] = arith.constant dense<{{.*}}> : vector<2x2xf32> %0 = arith.constant dense<[[1.0, 2.0], [3.0, 4.0]]> : vector<2x2xf32> -// CHECK: %[[RES:.*]] = vector.shape_cast %[[C1]] : vector<4xf32> to vector<2x2xf32> -// CHECK128: %[[RES:.*]] = vector.shape_cast %[[C1]] : vector<4xf32> to vector<2x2xf32> - // CHECK: %[[C2:.*]] = arith.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 1.000000e+00, 2.000000e+00, 5.000000e+00, 6.000000e+00]> : vector<16xf32> - // CHECK128: %[[C2:.*]] = arith.constant dense<{{.*}}> : vector<4x4xf32> - // CHECK0: %[[C2:.*]] = arith.constant dense<{{.*}}> : vector<4x4xf32> + // DEFAULT: %[[C2:.*]] = arith.constant dense<{{.*}}> : vector<16xf32> + // BW-128: %[[C2:.*]] = arith.constant dense<{{.*}}> : vector<4x4xf32> + // BW-0: %[[C2:.*]] = arith.constant dense<{{.*}}> : vector<4x4xf32> %5 = arith.constant dense<[[1.0, 2.0, 3.0, 4.0], [1.0, 2.0,3.0, 4.0], [1.0, 2.0, 3.0, 4.0], [1.0, 2.0, 5.0, 6.0]]> : vector<4x4xf32> -// Arith and math ops are handled in generic way, check some of them -// CHECK: %[[SIN:.*]] = math.sin %[[ARG]] : vector<4xf32> -// CHECK128: %[[SIN:.*]] = math.sin %[[ARG]] : vector<4xf32> -// CHECK0: %[[SIN:.*]] = math.sin %[[ORIG_ARG]] : vector<2x2xf32> + + // Arith and math ops are handled in generic way, check some of them + // DEFAULT: %[[SIN:.*]] = math.sin %[[ARG]] : vector<4xf32> + // BW-128: %[[SIN:.*]] = math.sin %[[ARG]] : vector<4xf32> + // BW-0: %[[SIN:.*]] = math.sin %[[ORIG_ARG]] : vector<2x2xf32> %1 = math.sin %arg0 : vector<2x2xf32> - // CHECK: %[[SIN1:.*]] = math.sin %[[ARG2]] : vector<16xf32> -// CHECK128: %[[SIN1:.*]] = math.sin %[[ORIG_ARG2]] : vector<4x4xf32> -// CHECK0: %[[SIN1:.*]] = math.sin %[[ORIG_ARG2]] : vector<4x4xf32> + // DEFAULT: %[[SIN1:.*]] = math.sin %[[ARG2]] : vector<16xf32> + // BW-128: %[[SIN1:.*]] = math.sin %[[ORIG_ARG2]] : vector<4x4xf32> + // BW-0: %[[SIN1:.*]] = math.sin %[[ORIG_ARG2]] : vector<4x4xf32> %6 = math.sin %arg1 : vector<4x4xf32> -// CHECK: %{{.*}} = arith.addf %[[ARG]], %[[C1]] : vector<4xf32> -// CHECK128: %{{.*}} = arith.addf %[[ARG]], %[[C1]] : vector<4xf32> -// CHECK0: %{{.*}} = arith.addf %{{.*}} : vector<2x2xf32> + // DEFAULT: %{{.*}} = arith.addf %[[ARG]], %[[CST]] : vector<4xf32> + // BW-128: %{{.*}} = arith.addf %[[ARG]], %[[CST]] : vector<4xf32> + // BW-0: %{{.*}} = arith.addf %{{.*}} : vector<2x2xf32> %2 = arith.addf %arg0, %0 : vector<2x2xf32> - // CHECK: %[[ADD2:.*]] = arith.addf %[[ARG2]], %[[C2]] : vector<16xf32> - // CHECK128: %[[ADD2:.*]] = arith.addf %[[ORIG_ARG2]], %[[C2]] : vector<4x4xf32> - // CHECK0: %[[ADD2:.*]] = arith.addf %[[ORIG_ARG2]], %[[C2]] : vector<4x4xf32> + // DEFAULT: %[[ADD2:.*]] = arith.addf %[[ARG2]], %[[C2]] : vector<16xf32> + // BW-128: %[[ADD2:.*]] = arith.addf %[[ORIG_ARG2]], %[[C2]] : vector<4x4xf32> + // BW-0: %[[ADD2:.*]] = arith.addf %[[ORIG_ARG2]], %[[C2]] : vector<4x4xf32> %7 = arith.addf %arg1, %5 : vector<4x4xf32> -// CHECK: return %[[RES]] : vector<2x2xf32> -// CHECK128: return %[[RES]] : vector<2x2xf32> + + // ALL: return %[[RES]] : vector<2x2xf32> return %0 : vector<2x2xf32> } -// CHECK-LABEL: test_index_no_linearize -// CHECK128-LABEL: test_index_no_linearize -// CHECK0-LABEL: test_index_no_linearize +// ----- + +// ALL-LABEL: test_index_no_linearize func.func @test_index_no_linearize(%arg0: vector<2x2xindex>, %arg1: vector<2x2xindex>) -> vector<2x2xindex> { - // CHECK: %[[ADD:.*]] = arith.addi {{.*}} : vector<2x2xindex> - // CHECK128: %[[ADD:.*]] = arith.addi {{.*}} : vector<2x2xindex> - // CHECK0: %[[ADD:.*]] = arith.addi {{.*}} : vector<2x2xindex> + // ALL: %[[ADD:.*]] = arith.addi {{.*}} : vector<2x2xindex> %0 = arith.addi %arg0, %arg1 : vector<2x2xindex> return %0 : vector<2x2xindex> } + +// ----- + +// vectorizable operation (arith.mulf) with tensor result types. + +// ALL-LABEL: test_tensor_no_linearize +func.func @test_tensor_no_linearize(%arg0: tensor<2x2xf32>, %arg1: tensor<2x2xf32>) -> (tensor<2x2xf32>, tensor<2x2xf32>) { + // ALL: %[[MULF:.*]] = arith.mulf %arg0, %arg1 : tensor<2x2xf32> + %0 = arith.mulf %arg0, %arg1 : tensor<2x2xf32> + + return %0, %arg0 : tensor<2x2xf32>, tensor<2x2xf32> +} + +// ----- + +// ALL-LABEL: func.func @test_scalable_linearize( +// ALL-SAME: %[[ARG_0:.*]]: vector<2x[2]xf32>) -> vector<2x[2]xf32> { +func.func @test_scalable_linearize(%arg0: vector<2x[2]xf32>) -> vector<2x[2]xf32> { + // DEFAULT: %[[SC:.*]] = vector.shape_cast %[[ARG_0]] : vector<2x[2]xf32> to vector<[4]xf32> + // DEFAULT: %[[CST:.*]] = arith.constant dense<3.000000e+00> : vector<[4]xf32> + // BW-128: %[[SC:.*]] = vector.shape_cast %[[ARG_0]] : vector<2x[2]xf32> to vector<[4]xf32> + // BW-128: %[[CST:.*]] = arith.constant dense<3.000000e+00> : vector<[4]xf32> + // BW-0: %[[CST:.*]] = arith.constant dense<3.000000e+00> : vector<2x[2]xf32> + %0 = arith.constant dense<[[3., 3.], [3., 3.]]> : vector<2x[2]xf32> + + // DEFAULT: %[[SIN:.*]] = math.sin %[[SC]] : vector<[4]xf32> + // BW-128: %[[SIN:.*]] = math.sin %[[SC]] : vector<[4]xf32> + // BW-0: %[[SIN:.*]] = math.sin %[[ARG_0]] : vector<2x[2]xf32> + %1 = math.sin %arg0 : vector<2x[2]xf32> + + // DEFAULT: %[[ADDF:.*]] = arith.addf %[[SIN]], %[[CST]] : vector<[4]xf32> + // BW-128: %[[ADDF:.*]] = arith.addf %[[SIN]], %[[CST]] : vector<[4]xf32> + // BW-0: %[[RES:.*]] = arith.addf %[[CST]], %[[SIN]] : vector<2x[2]xf32> + %2 = arith.addf %0, %1 : vector<2x[2]xf32> + + // DEFAULT: %[[RES:.*]] = vector.shape_cast %[[ADDF]] : vector<[4]xf32> to vector<2x[2]xf32> + // BW-128: %[[RES:.*]] = vector.shape_cast %[[ADDF]] : vector<[4]xf32> to vector<2x[2]xf32> + // ALL: return %[[RES]] : vector<2x[2]xf32> + return %2 : vector<2x[2]xf32> +} + +// ----- + +// ALL-LABEL: func.func @test_scalable_no_linearize( +// ALL-SAME: %[[VAL_0:.*]]: vector<[2]x[2]xf32>) -> vector<[2]x[2]xf32> { +func.func @test_scalable_no_linearize(%arg0: vector<[2]x[2]xf32>) -> vector<[2]x[2]xf32> { + // ALL: %[[CST:.*]] = arith.constant dense<2.000000e+00> : vector<[2]x[2]xf32> + %0 = arith.constant dense<[[2., 2.], [2., 2.]]> : vector<[2]x[2]xf32> + + // ALL: %[[SIN:.*]] = math.sin %[[VAL_0]] : vector<[2]x[2]xf32> + %1 = math.sin %arg0 : vector<[2]x[2]xf32> + + // ALL: %[[RES:.*]] = arith.addf %[[CST]], %[[SIN]] : vector<[2]x[2]xf32> + %2 = arith.addf %0, %1 : vector<[2]x[2]xf32> + + // ALL: return %[[RES]] : vector<[2]x[2]xf32> + return %2 : vector<[2]x[2]xf32> +} + +// ----- + +func.func @test_scalable_no_linearize(%arg0: vector<2x[2]xf32>) -> vector<2x[2]xf32> { + // expected-error@+1 {{failed to legalize operation 'arith.constant' that was explicitly marked illegal}} + %0 = arith.constant dense<[[1., 1.], [3., 3.]]> : vector<2x[2]xf32> + %1 = math.sin %arg0 : vector<2x[2]xf32> + %2 = arith.addf %0, %1 : vector<2x[2]xf32> + + return %2 : vector<2x[2]xf32> +} diff --git a/mlir/test/Dialect/Vector/test-scalable-bounds.mlir b/mlir/test/Dialect/Vector/test-scalable-bounds.mlir new file mode 100644 index 0000000000000000000000000000000000000000..245a6f5c13ac3d3ea717b2319cc750d9fc61dd76 --- /dev/null +++ b/mlir/test/Dialect/Vector/test-scalable-bounds.mlir @@ -0,0 +1,161 @@ +// RUN: mlir-opt %s -test-affine-reify-value-bounds -cse -verify-diagnostics \ +// RUN: -verify-diagnostics -split-input-file | FileCheck %s + +#map_dim_i = affine_map<(d0)[s0] -> (-d0 + 32400, s0)> +#map_dim_j = affine_map<(d0)[s0] -> (-d0 + 16, s0)> + +// Here the upper bound for min_i is 4 x vscale, as we know 4 x vscale is +// always less than 32400. The bound for min_j is 16, as 16 is always less +// 4 x vscale_max (vscale_max is the UB for vscale). + +// CHECK: #[[$SCALABLE_BOUND_MAP_0:.*]] = affine_map<()[s0] -> (s0 * 4)> + +// CHECK-LABEL: @fixed_size_loop_nest +// CHECK-DAG: %[[VSCALE:.*]] = vector.vscale +// CHECK-DAG: %[[UB_i:.*]] = affine.apply #[[$SCALABLE_BOUND_MAP_0]]()[%[[VSCALE]]] +// CHECK-DAG: %[[UB_j:.*]] = arith.constant 16 : index +// CHECK: "test.some_use"(%[[UB_i]], %[[UB_j]]) : (index, index) -> () +func.func @fixed_size_loop_nest() { + %c16 = arith.constant 16 : index + %c32400 = arith.constant 32400 : index + %c4 = arith.constant 4 : index + %c0 = arith.constant 0 : index + %vscale = vector.vscale + %c4_vscale = arith.muli %vscale, %c4 : index + scf.for %i = %c0 to %c32400 step %c4_vscale { + %min_i = affine.min #map_dim_i(%i)[%c4_vscale] + scf.for %j = %c0 to %c16 step %c4_vscale { + %min_j = affine.min #map_dim_j(%j)[%c4_vscale] + %bound_i = "test.reify_scalable_bound"(%min_i) {type = "UB", vscale_min = 1, vscale_max = 16} : (index) -> index + %bound_j = "test.reify_scalable_bound"(%min_j) {type = "UB", vscale_min = 1, vscale_max = 16} : (index) -> index + "test.some_use"(%bound_i, %bound_j) : (index, index) -> () + } + } + return +} + +// ----- + +#map_dynamic_dim = affine_map<(d0)[s0, s1] -> (-d0 + s1, s0)> + +// Here upper bounds for both min_i and min_j are both (conservatively) +// 4 x vscale, as we know that is always the largest value they could take. As +// if `dim < 4 x vscale` then 4 x vscale is an overestimate, and if +// `dim > 4 x vscale` then the min will be clamped to 4 x vscale. + +// CHECK: #[[$SCALABLE_BOUND_MAP_1:.*]] = affine_map<()[s0] -> (s0 * 4)> + +// CHECK-LABEL: @dynamic_size_loop_nest +// CHECK: %[[VSCALE:.*]] = vector.vscale +// CHECK: %[[UB_ij:.*]] = affine.apply #[[$SCALABLE_BOUND_MAP_1]]()[%[[VSCALE]]] +// CHECK: "test.some_use"(%[[UB_ij]], %[[UB_ij]]) : (index, index) -> () +func.func @dynamic_size_loop_nest(%dim0: index, %dim1: index) { + %c4 = arith.constant 4 : index + %c0 = arith.constant 0 : index + %vscale = vector.vscale + %c4_vscale = arith.muli %vscale, %c4 : index + scf.for %i = %c0 to %dim0 step %c4_vscale { + %min_i = affine.min #map_dynamic_dim(%i)[%c4_vscale, %dim0] + scf.for %j = %c0 to %dim1 step %c4_vscale { + %min_j = affine.min #map_dynamic_dim(%j)[%c4_vscale, %dim1] + %bound_i = "test.reify_scalable_bound"(%min_i) {type = "UB", vscale_min = 1, vscale_max = 16} : (index) -> index + %bound_j = "test.reify_scalable_bound"(%min_j) {type = "UB", vscale_min = 1, vscale_max = 16} : (index) -> index + "test.some_use"(%bound_i, %bound_j) : (index, index) -> () + } + } + return +} + +// ----- + +// Here the bound is just a value + a constant. + +// CHECK: #[[$SCALABLE_BOUND_MAP_2:.*]] = affine_map<()[s0] -> (s0 + 8)> + +// CHECK-LABEL: @add_to_vscale +// CHECK: %[[VSCALE:.*]] = vector.vscale +// CHECK: %[[SCALABLE_BOUND:.*]] = affine.apply #[[$SCALABLE_BOUND_MAP_2]]()[%[[VSCALE]]] +// CHECK: "test.some_use"(%[[SCALABLE_BOUND]]) : (index) -> () +func.func @add_to_vscale() { + %vscale = vector.vscale + %c8 = arith.constant 8 : index + %vscale_plus_c8 = arith.addi %vscale, %c8 : index + %bound = "test.reify_scalable_bound"(%vscale_plus_c8) {type = "EQ", vscale_min = 1, vscale_max = 16} : (index) -> index + "test.some_use"(%bound) : (index) -> () + return +} + +// ----- + +// Here we know vscale is always 2 so we get a constant bound. + +// CHECK-LABEL: @vscale_fixed_size +// CHECK: %[[C2:.*]] = arith.constant 2 : index +// CHECK: "test.some_use"(%[[C2]]) : (index) -> () +func.func @vscale_fixed_size() { + %vscale = vector.vscale + %bound = "test.reify_scalable_bound"(%vscale) {type = "EQ", vscale_min = 2, vscale_max = 2} : (index) -> index + "test.some_use"(%bound) : (index) -> () + return +} + +// ----- + +// Here we don't know the upper bound (%a is underspecified) + +func.func @unknown_bound(%a: index) { + %vscale = vector.vscale + %vscale_plus_a = arith.muli %vscale, %a : index + // expected-error @below{{could not reify bound}} + %bound = "test.reify_scalable_bound"(%vscale_plus_a) {type = "UB", vscale_min = 1, vscale_max = 16} : (index) -> index + "test.some_use"(%bound) : (index) -> () + return +} + +// ----- + +// Here we have two vscale values (that have not been CSE'd), but they should +// still be treated as equivalent. + +// CHECK: #[[$SCALABLE_BOUND_MAP_3:.*]] = affine_map<()[s0] -> (s0 * 6)> + +// CHECK-LABEL: @duplicate_vscale_values +// CHECK: %[[VSCALE:.*]] = vector.vscale +// CHECK: %[[SCALABLE_BOUND:.*]] = affine.apply #[[$SCALABLE_BOUND_MAP_3]]()[%[[VSCALE]]] +// CHECK: "test.some_use"(%[[SCALABLE_BOUND]]) : (index) -> () +func.func @duplicate_vscale_values() { + %c4 = arith.constant 4 : index + %vscale_0 = vector.vscale + + %c2 = arith.constant 2 : index + %vscale_1 = vector.vscale + + %c4_vscale = arith.muli %vscale_0, %c4 : index + %c2_vscale = arith.muli %vscale_1, %c2 : index + %add = arith.addi %c2_vscale, %c4_vscale : index + + %bound = "test.reify_scalable_bound"(%add) {type = "EQ", vscale_min = 1, vscale_max = 16} : (index) -> index + "test.some_use"(%bound) : (index) -> () + return +} + +// ----- + +// Test some non-scalable code to ensure that works too: + +#map_dim_i = affine_map<(d0)[s0] -> (-d0 + 1024, s0)> + +// CHECK-LABEL: @non_scalable_code +// CHECK: %[[C4:.*]] = arith.constant 4 : index +// CHECK: "test.some_use"(%[[C4]]) : (index) -> () +func.func @non_scalable_code() { + %c1024 = arith.constant 1024 : index + %c4 = arith.constant 4 : index + %c0 = arith.constant 0 : index + scf.for %i = %c0 to %c1024 step %c4 { + %min_i = affine.min #map_dim_i(%i)[%c4] + %bound_i = "test.reify_scalable_bound"(%min_i) {type = "UB", vscale_min = 1, vscale_max = 16} : (index) -> index + "test.some_use"(%bound_i) : (index) -> () + } + return +} diff --git a/mlir/test/Dialect/Vector/vector-contract-to-outerproduct-matvec-transforms.mlir b/mlir/test/Dialect/Vector/vector-contract-to-outerproduct-matvec-transforms.mlir index 412e95bede3a7cfa6abb7ecb00fb3453e921fe5e..0b3636e3b196b9a567f7c07530441671746ce3a0 100644 --- a/mlir/test/Dialect/Vector/vector-contract-to-outerproduct-matvec-transforms.mlir +++ b/mlir/test/Dialect/Vector/vector-contract-to-outerproduct-matvec-transforms.mlir @@ -657,7 +657,8 @@ func.func @masked_extract_contract2_scalable_reduction_dim(%arg0: vector<[2]x[3] // TD sequence // ============================================================================ module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.lower_contraction lowering_strategy = "outerproduct" } : !transform.op<"func.func"> diff --git a/mlir/test/Dialect/Vector/vector-dropleadunitdim-transforms.mlir b/mlir/test/Dialect/Vector/vector-dropleadunitdim-transforms.mlir index af6e636245b04e79c18379c2668dc9e2fda543c9..3a120a56056cad8d727d24202a2399d19f05226f 100644 --- a/mlir/test/Dialect/Vector/vector-dropleadunitdim-transforms.mlir +++ b/mlir/test/Dialect/Vector/vector-dropleadunitdim-transforms.mlir @@ -30,6 +30,80 @@ func.func @cast_away_contraction_leading_one_dims(%arg0: vector<1x16x8xf32>, %ar } // ----- +// CHECK: #[[$MAP_0:.+]] = affine_map<(d0, d1, d2) -> (d0, d2)> +// CHECK: #[[$MAP_1:.+]] = affine_map<(d0, d1, d2) -> (d2, d1)> +// CHECK: #[[$MAP_2:.+]] = affine_map<(d0, d1, d2) -> (d0, d1)> + +// CHECK-LABEL: func.func @cast_away_contraction_leading_one_dim_under_const_mask +// CHECK: %[[MASK:.*]] = vector.constant_mask [15, 15, 8] : vector<16x16x8xi1> +// CHECK: %[[R0:.*]] = vector.extract %{{.*}}[0] : vector<16x8xf32> from vector<1x16x8xf32> +// CHECK: %[[R1:.*]] = vector.extract %{{.*}}[0] : vector<8x16xf32> from vector<1x8x16xf32> +// CHECK: %[[R2:.*]] = vector.extract %{{.*}}[0] : vector<16x16xf32> from vector<1x16x16xf32> +// CHECK: %[[CONTRACT:.*]] = vector.mask %[[MASK]] { +// CHECK-SAME: vector.contract {indexing_maps = [#[[$MAP_0]], #[[$MAP_1]], #[[$MAP_2]]], iterator_types = ["parallel", "parallel", "reduction"], kind = #vector.kind<add>} +// CHECK-SAME: %[[R0]], %[[R1]], %[[R2]] : vector<16x8xf32>, vector<8x16xf32> into vector<16x16xf32> +// CHECK-SAME: } : vector<16x16x8xi1> -> vector<16x16xf32> +// CHECK: %[[RES:.*]] = vector.broadcast %[[CONTRACT]] : vector<16x16xf32> to vector<1x16x16xf32> +// CHECK: return %[[RES]] : vector<1x16x16xf32> + +#contraction_accesses0 = [ + affine_map<(l, i, j, k) -> (l, i, k)>, + affine_map<(l, i, j, k) -> (l, k, j)>, + affine_map<(l, i, j, k) -> (l, i, j)> +] +#contraction_trait0 = { + indexing_maps = #contraction_accesses0, + iterator_types = ["parallel", "parallel", "parallel", "reduction"] +} + +func.func @cast_away_contraction_leading_one_dim_under_const_mask(%arg0: vector<1x16x8xf32>, %arg1: vector<1x8x16xf32>, %arg2: vector<1x16x16xf32>) -> vector<1x16x16xf32> { + %mask = vector.constant_mask [1, 15, 15, 8] : vector<1x16x16x8xi1> + %0 = vector.mask %mask { + vector.contract #contraction_trait0 %arg0, %arg1, %arg2 : vector<1x16x8xf32>, vector<1x8x16xf32> into vector<1x16x16xf32> + } : vector<1x16x16x8xi1> -> vector<1x16x16xf32> + return %0 : vector<1x16x16xf32> +} + +// ----- +// CHECK-DAG: #[[$MAP0:.+]] = affine_map<(d0, d1, d2) -> (d0, d2)> +// CHECK-DAG: #[[$MAP1:.+]] = affine_map<(d0, d1, d2) -> (d2, d1)> +// CHECK-DAG: #[[$MAP2:.+]] = affine_map<(d0, d1, d2) -> (d0, d1)> + +// CHECK-LABEL: func.func @cast_away_contraction_leading_one_dim_under_mask +// CHECK: %[[R0:.*]] = vector.extract %{{.*}} : vector<16x8xf32> from vector<1x16x8xf32> +// CHECK: %[[R1:.*]] = vector.extract %{{.*}} : vector<8x16xf32> from vector<1x8x16xf32> +// CHECK: %[[R2:.*]] = vector.extract %{{.*}} : vector<16x16xf32> from vector<1x16x16xf32> +// CHECK: %[[M:.*]] = vector.extract %{{.*}} : vector<16x16x8xi1> from vector<1x16x16x8xi1> +// CHECK: %[[CONTRACT:.*]] = vector.mask %[[M]] { +// CHECK-SAME: vector.contract {indexing_maps = [#[[$MAP0]], #[[$MAP1]], #[[$MAP2]]], iterator_types = ["parallel", "parallel", "reduction"], kind = #vector.kind<add>} +// CHECK-SAME: %[[R0]], %[[R1]], %[[R2]] : vector<16x8xf32>, vector<8x16xf32> into vector<16x16xf32> +// CHECK-SAME: } : vector<16x16x8xi1> -> vector<16x16xf32> +// CHECK-NEXT: %[[RES:.*]] = vector.broadcast %[[CONTRACT]] : vector<16x16xf32> to vector<1x16x16xf32> +// CHECK-NEXT: return %[[RES]] : vector<1x16x16xf32> + +#contraction_accesses0 = [ + affine_map<(l, i, j, k) -> (l, i, k)>, + affine_map<(l, i, j, k) -> (l, k, j)>, + affine_map<(l, i, j, k) -> (l, i, j)> +] +#contraction_trait0 = { + indexing_maps = #contraction_accesses0, + iterator_types = ["parallel", "parallel", "parallel", "reduction"] +} + +func.func @cast_away_contraction_leading_one_dim_under_mask( + %arg0: vector<1x16x8xf32>, + %arg1: vector<1x8x16xf32>, + %arg2: vector<1x16x16xf32>, + %mask: vector<1x16x16x8xi1>) -> vector<1x16x16xf32> { + %0 = vector.mask %mask { + vector.contract #contraction_trait0 %arg0, %arg1, %arg2 : vector<1x16x8xf32>, vector<1x8x16xf32> into vector<1x16x16xf32> + } : vector<1x16x16x8xi1> -> vector<1x16x16xf32> + return %0: vector<1x16x16xf32> +} + +// ----- + // CHECK-DAG: #[[$map0:.*]] = affine_map<(d0, d1) -> (d1)> // CHECK-DAG: #[[$map1:.*]] = affine_map<(d0, d1) -> (d1, d0)> // CHECK-DAG: #[[$map2:.*]] = affine_map<(d0, d1) -> (d0)> @@ -164,36 +238,6 @@ func.func @cast_away_contraction_leading_one_dims_nonleadingunitdim_rank4_acctra return %0: vector<1x1x2x16xf32> } -// ----- - -// CHECK-DAG: #[[MAP0:.*]] = affine_map<(d0, d1, d2, d3) -> (d0, d1, d3)> -// CHECK-DAG: #[[MAP1:.*]] = affine_map<(d0, d1, d2, d3) -> (d0, d3, d2)> -// CHECK-DAG: #[[MAP2:.*]] = affine_map<(d0, d1, d2, d3) -> (d0, d1, d2)> - -// CHECK-LABEL: not_insert_cast_for_contraction_under_mask -// CHECK: %[[MASK:.+]] = vector.constant_mask -// CHECK: %[[CASTED_MASK:.+]] = vector.broadcast %[[MASK]] -// CHECK: %[[RET:.+]] = vector.mask %[[CASTED_MASK]] { -// CHECK-SAME: vector.contract {{.*}} : vector<1x16x8xf32>, vector<1x8x16xf32> into vector<1x16x16xf32> } -// CHECK: return %[[RET]] : vector<1x16x16xf32> - -#contraction_accesses0 = [ - affine_map<(l, i, j, k) -> (l, i, k)>, - affine_map<(l, i, j, k) -> (l, k, j)>, - affine_map<(l, i, j, k) -> (l, i, j)> -] -#contraction_trait0 = { - indexing_maps = #contraction_accesses0, - iterator_types = ["parallel", "parallel", "parallel", "reduction"] -} - -func.func @not_insert_cast_for_contraction_under_mask(%arg0: vector<1x16x8xf32>, %arg1: vector<1x8x16xf32>, %arg2: vector<1x16x16xf32>) -> vector<1x16x16xf32> { - %mask = vector.constant_mask [1, 15, 15, 8] : vector<1x16x16x8xi1> - %0 = vector.mask %mask { - vector.contract #contraction_trait0 %arg0, %arg1, %arg2 : vector<1x16x8xf32>, vector<1x8x16xf32> into vector<1x16x16xf32> - } : vector<1x16x16x8xi1> -> vector<1x16x16xf32> - return %0 : vector<1x16x16xf32> -} // ----- // CHECK-LABEL: func @cast_away_extract_strided_slice_leading_one_dims @@ -428,6 +472,8 @@ func.func @cast_away_elementwise_leading_one_dims( return %0, %1, %2, %3: vector<1x1x8xf32>, vector<1x4xi1>, vector<1x4xf32>, vector<1x4xf32> } +// ----- + // CHECK-LABEL: func @cast_away_insert_leading_one_dims_scalar // CHECK-SAME: (%[[S:.+]]: f32, %[[V:.+]]: vector<1x1x4xf32>) // CHECK: %[[EXTRACT:.+]] = vector.extract %[[V]][0, 0] : vector<4xf32> from vector<1x1x4xf32> @@ -439,6 +485,8 @@ func.func @cast_away_insert_leading_one_dims_scalar(%s: f32, %v: vector<1x1x4xf3 return %0: vector<1x1x4xf32> } +// ----- + // CHECK-LABEL: func.func @cast_away_insert_leading_one_dims_scalar_scalable( // CHECK-SAME: %[[S:.*]]: f32, // CHECK-SAME: %[[V:.*]]: vector<1x1x[4]xf32>) -> vector<1x1x[4]xf32> { @@ -451,6 +499,8 @@ func.func @cast_away_insert_leading_one_dims_scalar_scalable(%s: f32, %v: vector return %0: vector<1x1x[4]xf32> } +// ----- + // CHECK-LABEL: func.func @cast_away_insert_leading_one_dims_scalar_skip_scalable_dim( // CHECK-SAME: %[[S:.*]]: f32, // CHECK-SAME: %[[V:.*]]: vector<1x[1]x4xf32>) -> vector<1x[1]x4xf32> { @@ -463,6 +513,8 @@ func.func @cast_away_insert_leading_one_dims_scalar_skip_scalable_dim(%s: f32, % return %0: vector<1x[1]x4xf32> } +// ----- + // CHECK-LABEL: func @cast_away_insert_leading_one_dims_rank1 // CHECK-SAME: (%[[S:.+]]: vector<4xf32>, %[[V:.+]]: vector<1x1x4xf32>) // CHECK: %[[BCAST:.+]] = vector.broadcast %[[S]] : vector<4xf32> to vector<1x1x4xf32> @@ -472,6 +524,8 @@ func.func @cast_away_insert_leading_one_dims_rank1(%s: vector<4xf32>, %v: vector return %0: vector<1x1x4xf32> } +// ----- + // CHECK-LABEL: func.func @cast_away_insert_leading_one_dims_rank1_scalable( // CHECK-SAME: %[[S:.*]]: vector<[4]xf32>, // CHECK-SAME: %[[V:.*]]: vector<1x1x[4]xf32>) -> vector<1x1x[4]xf32> { @@ -482,6 +536,8 @@ func.func @cast_away_insert_leading_one_dims_rank1_scalable(%s: vector<[4]xf32>, return %0: vector<1x1x[4]xf32> } +// ----- + // CHECK-LABEL: func @cast_away_insert_leading_one_dims_rank2 // CHECK-SAME: (%[[S:.+]]: vector<1x4xf32>, %[[V:.+]]: vector<1x1x4xf32>) // CHECK: %[[EXTRACT:.+]] = vector.extract %[[S]][0] : vector<4xf32> from vector<1x4xf32> @@ -492,6 +548,8 @@ func.func @cast_away_insert_leading_one_dims_rank2(%s: vector<1x4xf32>, %v: vect return %0: vector<1x1x4xf32> } +// ----- + // CHECK-LABEL: func.func @cast_away_insert_leading_one_dims_rank2_scalable( // CHECK-SAME: %[[S:.*]]: vector<1x[4]xf32>, // CHECK-SAME: %[[V:.*]]: vector<1x1x[4]xf32>) -> vector<1x1x[4]xf32> { @@ -503,6 +561,8 @@ func.func @cast_away_insert_leading_one_dims_rank2_scalable(%s: vector<1x[4]xf32 return %0: vector<1x1x[4]xf32> } +// ----- + // CHECK-LABEL: func @cast_away_insert_leading_one_dims_rank2_one_dest // CHECK-SAME: (%[[S:.+]]: vector<1x4xf32>, %[[V:.+]]: vector<1x2x1x4xf32>) // CHECK: %[[EXTRACTS:.+]] = vector.extract %[[S]][0] : vector<4xf32> from vector<1x4xf32> @@ -515,6 +575,8 @@ func.func @cast_away_insert_leading_one_dims_rank2_one_dest(%s: vector<1x4xf32>, return %0: vector<1x2x1x4xf32> } +// ----- + // CHECK-LABEL: func.func @cast_away_insert_leading_one_dims_rank2_one_dest_scalable( // CHECK-SAME: %[[S:.*]]: vector<1x[4]xf32>, // CHECK-SAME: %[[V:.*]]: vector<1x2x1x[4]xf32>) -> vector<1x2x1x[4]xf32> { @@ -528,6 +590,8 @@ func.func @cast_away_insert_leading_one_dims_rank2_one_dest_scalable(%s: vector< return %0: vector<1x2x1x[4]xf32> } +// ----- + // CHECK-LABEL: func @cast_away_insert_leading_one_dims_non_one_dest // CHECK-SAME: (%[[S:.+]]: vector<1x4xf32>, %[[V:.+]]: vector<8x1x4xf32>) // CHECK: %[[EXTRACT:.+]] = vector.extract %[[S]][0] : vector<4xf32> from vector<1x4xf32> @@ -538,6 +602,8 @@ func.func @cast_away_insert_leading_one_dims_non_one_dest(%s: vector<1x4xf32>, % return %0: vector<8x1x4xf32> } +// ----- + // CHECK-LABEL: func.func @cast_away_insert_leading_one_dims_non_one_dest_scalable( // CHECK-SAME: %[[S:.*]]: vector<1x[4]xf32>, // CHECK-SAME: %[[V:.*]]: vector<8x1x[4]xf32>) -> vector<8x1x[4]xf32> { @@ -549,6 +615,8 @@ func.func @cast_away_insert_leading_one_dims_non_one_dest_scalable(%s: vector<1x return %0: vector<8x1x[4]xf32> } +// ----- + // CHECK-LABEL: func @cast_away_insert_leading_one_dims_one_two_dest // CHECK-SAME: (%[[S:.+]]: vector<1x8xi1>, %[[V:.+]]: vector<1x1x8x1x8xi1>) // CHECK: %[[EXTRACTS:.+]] = vector.extract %[[S]][0] : vector<8xi1> from vector<1x8xi1> @@ -561,6 +629,8 @@ func.func @cast_away_insert_leading_one_dims_one_two_dest(%s: vector<1x8xi1>, %v return %0: vector<1x1x8x1x8xi1> } +// ----- + // CHECK-LABEL: func.func @cast_away_insert_leading_one_dims_one_two_dest_scalable( // CHECK-SAME: %[[S:.*]]: vector<1x[8]xi1>, // CHECK-SAME: %[[V:.*]]: vector<1x1x8x1x[8]xi1>) -> vector<1x1x8x1x[8]xi1> { @@ -574,6 +644,8 @@ func.func @cast_away_insert_leading_one_dims_one_two_dest_scalable(%s: vector<1x return %0: vector<1x1x8x1x[8]xi1> } +// ----- + // CHECK-LABEL: func.func @cast_away_constant_mask() -> vector<1x1x8x2x1xi1> { // CHECK: %[[MASK:.*]] = vector.constant_mask [6, 1, 1] : vector<8x2x1xi1> // CHECK: %[[BCAST:.*]] = vector.broadcast %[[MASK]] : vector<8x2x1xi1> to vector<1x1x8x2x1xi1> @@ -582,3 +654,13 @@ func.func @cast_away_constant_mask() -> vector<1x1x8x2x1xi1> { %0 = vector.constant_mask [1, 1, 6, 1, 1] : vector<1x1x8x2x1xi1> return %0: vector<1x1x8x2x1xi1> } + +// ----- + +// CHECK-LABEL: func.func @drop_unit_dims_scalar_cond_select( +// CHECK: arith.select {{.*}} : vector<16xi1> +func.func @drop_unit_dims_scalar_cond_select(%cond: i1, %arg0: vector<1x16xi1>, %arg1: vector<1x16xi1>) -> vector<1x16xi1> { + %sel = arith.select %cond, %arg0, %arg1 : vector<1x16xi1> + return %sel : vector<1x16xi1> +} + diff --git a/mlir/test/Dialect/Vector/vector-materialize-mask.mlir b/mlir/test/Dialect/Vector/vector-materialize-mask.mlir index c47d91bb6ed921dfeb091292731383c7fae4952d..a3fd6339492c4e2d1fd0baaf4d63c2252bffaa00 100644 --- a/mlir/test/Dialect/Vector/vector-materialize-mask.mlir +++ b/mlir/test/Dialect/Vector/vector-materialize-mask.mlir @@ -8,7 +8,8 @@ func.func @select_single_i1_vector(%cond : i1) -> vector<1xi1> { } module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.materialize_masks } : !transform.op<"func.func"> diff --git a/mlir/test/Dialect/Vector/vector-multi-reduction-lowering.mlir b/mlir/test/Dialect/Vector/vector-multi-reduction-lowering.mlir index 6e06ba1bb14b6e6d5c7f2bc4994cb74b83a46bd1..22808aa7d6acc352d35afdd7470715869056f43e 100644 --- a/mlir/test/Dialect/Vector/vector-multi-reduction-lowering.mlir +++ b/mlir/test/Dialect/Vector/vector-multi-reduction-lowering.mlir @@ -282,7 +282,8 @@ func.func private @scalable_dims(%A : vector<8x[4]x2xf32>, %B: vector<8x[4]xf32> // CHECK: return %[[VAL_163]] : vector<8x[4]xf32> module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.lower_multi_reduction lowering_strategy = "innerreduction" } : !transform.op<"func.func"> diff --git a/mlir/test/Dialect/Vector/vector-multi-reduction-outer-lowering.mlir b/mlir/test/Dialect/Vector/vector-multi-reduction-outer-lowering.mlir index 308baa97af9a41dc1fbf8249a41a3ce2870fafab..33adb554564753326f1dab5da9fdc0bfe3b8e2d2 100644 --- a/mlir/test/Dialect/Vector/vector-multi-reduction-outer-lowering.mlir +++ b/mlir/test/Dialect/Vector/vector-multi-reduction-outer-lowering.mlir @@ -189,7 +189,8 @@ func.func @vector_multi_reduction_to_scalar(%arg0: vector<2x3xf32>, %acc: f32) - // CHECK: return %{{.+}} module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.lower_multi_reduction lowering_strategy = "innerparallel" } : !transform.op<"func.func"> diff --git a/mlir/test/Dialect/Vector/vector-transfer-drop-unit-dims-patterns.mlir b/mlir/test/Dialect/Vector/vector-transfer-drop-unit-dims-patterns.mlir index d65708068862f46d02bab3b03aaa4bc2d9c88e17..e9d12b044e2c7e8973d181eea607e27d1657ded7 100644 --- a/mlir/test/Dialect/Vector/vector-transfer-drop-unit-dims-patterns.mlir +++ b/mlir/test/Dialect/Vector/vector-transfer-drop-unit-dims-patterns.mlir @@ -239,7 +239,8 @@ func.func @masked_transfer_read_dynamic_rank_reducing_scalable_unit_dim( // CHECK: vector.transfer_read {{.*}} vector<[16]x[1]xi8> module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.rank_reducing_subview_patterns } : !transform.op<"func.func"> diff --git a/mlir/test/Dialect/Vector/vector-transfer-full-partial-split-copy-transform.mlir b/mlir/test/Dialect/Vector/vector-transfer-full-partial-split-copy-transform.mlir index bcb8e1a10c8493ad3a889f9fe8c9a98c2852e6ea..483147c6f6a402fa35a7bb753139210ad7816247 100644 --- a/mlir/test/Dialect/Vector/vector-transfer-full-partial-split-copy-transform.mlir +++ b/mlir/test/Dialect/Vector/vector-transfer-full-partial-split-copy-transform.mlir @@ -63,7 +63,7 @@ func.func @split_vector_transfer_read_strided_2d( %c0 = arith.constant 0 : index %f0 = arith.constant 0.0 : f32 - + // CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index // CHECK-DAG: %[[c4:.*]] = arith.constant 4 : index // CHECK-DAG: %[[c7:.*]] = arith.constant 7 : index @@ -107,7 +107,8 @@ func.func @split_vector_transfer_read_strided_2d( } module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.split_transfer_full_partial split_transfer_strategy = "linalg-copy" } : !transform.op<"func.func"> @@ -170,7 +171,8 @@ func.func @split_vector_transfer_write_2d(%V: vector<4x8xf32>, %A: memref<?x8xf3 // CHECK: } module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.split_transfer_full_partial split_transfer_strategy = "linalg-copy" } : !transform.op<"func.func"> @@ -240,7 +242,8 @@ func.func @split_vector_transfer_write_strided_2d( // CHECK: } module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.split_transfer_full_partial split_transfer_strategy = "linalg-copy" } : !transform.op<"func.func"> diff --git a/mlir/test/Dialect/Vector/vector-transfer-full-partial-split.mlir b/mlir/test/Dialect/Vector/vector-transfer-full-partial-split.mlir index 644de885bbaa9d57e399886d4070869a1683ad69..a9c7bf8e8b3279455747e3de3001ffa6192b85af 100644 --- a/mlir/test/Dialect/Vector/vector-transfer-full-partial-split.mlir +++ b/mlir/test/Dialect/Vector/vector-transfer-full-partial-split.mlir @@ -133,7 +133,8 @@ func.func @split_vector_transfer_read_mem_space(%A: memref<?x8xf32, 3>, %i: inde } module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.split_transfer_full_partial split_transfer_strategy = "vector-transfer" } : !transform.op<"func.func"> @@ -193,7 +194,8 @@ func.func @split_vector_transfer_write_2d(%V: vector<4x8xf32>, %A: memref<?x8xf3 module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.split_transfer_full_partial split_transfer_strategy = "vector-transfer" } : !transform.op<"func.func"> @@ -257,7 +259,8 @@ func.func @split_vector_transfer_write_strided_2d( // CHECK: } module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.split_transfer_full_partial split_transfer_strategy = "vector-transfer" } : !transform.op<"func.func"> @@ -292,7 +295,8 @@ func.func @split_vector_transfer_write_mem_space(%V: vector<4x8xf32>, %A: memref module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.split_transfer_full_partial split_transfer_strategy = "vector-transfer" } : !transform.op<"func.func"> @@ -337,7 +341,8 @@ func.func @transfer_read_within_scf_for(%A : memref<?x?xf32>, %lb : index, %ub : } module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.split_transfer_full_partial split_transfer_strategy = "vector-transfer" } : !transform.op<"func.func"> diff --git a/mlir/test/Dialect/Vector/vector-transfer-permutation-lowering.mlir b/mlir/test/Dialect/Vector/vector-transfer-permutation-lowering.mlir index 13e07f59a72a7756ae3d910604ef8d9e487ad361..31bd19c0be8e836d65e6653af4b18a3c88cbd159 100644 --- a/mlir/test/Dialect/Vector/vector-transfer-permutation-lowering.mlir +++ b/mlir/test/Dialect/Vector/vector-transfer-permutation-lowering.mlir @@ -41,6 +41,24 @@ func.func @permutation_with_mask_scalable(%2: memref<?x?xf32>, %dim_1: index, %d return %1 : vector<8x[4]x2xf32> } +// CHECK: func.func @permutation_with_mask_transfer_write_scalable( +// CHECK-SAME: %[[ARG_0:.*]]: vector<4x[8]xi16>, +// CHECK-SAME: %[[ARG_1:.*]]: memref<1x4x?x1x1x1x1xi16>, +// CHECK-SAME: %[[MASK:.*]]: vector<4x[8]xi1>) { +// CHECK: %[[C0:.*]] = arith.constant 0 : index +// CHECK: %[[BCAST_1:.*]] = vector.broadcast %[[ARG_0]] : vector<4x[8]xi16> to vector<1x1x1x1x4x[8]xi16> +// CHECK: %[[BCAST_2:.*]] = vector.broadcast %[[MASK]] : vector<4x[8]xi1> to vector<1x1x1x1x4x[8]xi1> +// CHECK: %[[TRANSPOSE_1:.*]] = vector.transpose %[[BCAST_2]], [4, 5, 0, 1, 2, 3] : vector<1x1x1x1x4x[8]xi1> to vector<4x[8]x1x1x1x1xi1> +// CHECK: %[[TRANSPOSE_2:.*]] = vector.transpose %[[BCAST_1]], [4, 5, 0, 1, 2, 3] : vector<1x1x1x1x4x[8]xi16> to vector<4x[8]x1x1x1x1xi16> +// CHECK: vector.transfer_write %[[TRANSPOSE_2]], %[[ARG_1]]{{\[}}%[[C0]], %[[C0]], %[[C0]], %[[C0]], %[[C0]], %[[C0]], %[[C0]]], %[[TRANSPOSE_1]] {in_bounds = [true, true, true, true, true, true]} : vector<4x[8]x1x1x1x1xi16>, memref<1x4x?x1x1x1x1xi16> +// CHECK: return +func.func @permutation_with_mask_transfer_write_scalable(%arg0: vector<4x[8]xi16>, %arg1: memref<1x4x?x1x1x1x1xi16>, %mask: vector<4x[8]xi1>){ + %c0 = arith.constant 0 : index + vector.transfer_write %arg0, %arg1[%c0, %c0, %c0, %c0, %c0, %c0, %c0], %mask {in_bounds = [true, true], permutation_map = affine_map<(d0, d1, d2, d3, d4, d5, d6) -> (d1, d2)> +} : vector<4x[8]xi16>, memref<1x4x?x1x1x1x1xi16> + + return +} module attributes {transform.with_named_sequence} { transform.named_sequence @__transform_main(%module_op: !transform.any_op {transform.readonly}) { %f = transform.structured.match ops{["func.func"]} in %module_op diff --git a/mlir/test/Dialect/Vector/vector-transfer-to-vector-load-store.mlir b/mlir/test/Dialect/Vector/vector-transfer-to-vector-load-store.mlir index 7aaaff70e5242e3c73c84a12313d4b30845f1d71..2f2bdcaab5b3ee0efb396eb6c82e72c85401d763 100644 --- a/mlir/test/Dialect/Vector/vector-transfer-to-vector-load-store.mlir +++ b/mlir/test/Dialect/Vector/vector-transfer-to-vector-load-store.mlir @@ -239,7 +239,8 @@ func.func @transfer_broadcasting_complex(%mem : memref<10x20x30x8x8xf32>, %i : i module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.lower_transfer max_transfer_rank = 99 transform.apply_patterns.vector.transfer_permutation_patterns @@ -363,7 +364,8 @@ func.func @transfer_write_broadcast_unit_dim( } module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.lower_transfer max_transfer_rank = 99 transform.apply_patterns.vector.transfer_permutation_patterns @@ -391,7 +393,8 @@ func.func @transfer_2D_masked(%mem : memref<?x?xf32>, %mask : vector<2x4xi1>) -> } module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.lower_transfer max_transfer_rank = 2 } : !transform.op<"func.func"> diff --git a/mlir/test/Dialect/Vector/vector-transpose-lowering.mlir b/mlir/test/Dialect/Vector/vector-transpose-lowering.mlir index 97b698edeb0598bc0f155abcd8bbeb77662a9129..628a8ce509599411c7f6fa455d12e1f9b2b43ed9 100644 --- a/mlir/test/Dialect/Vector/vector-transpose-lowering.mlir +++ b/mlir/test/Dialect/Vector/vector-transpose-lowering.mlir @@ -86,7 +86,8 @@ func.func @transpose23_scalable(%arg0: vector<2x[3]xf32>) -> vector<[3]x2xf32> { } module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.lower_transpose lowering_strategy = "eltwise" } : !transform.op<"func.func"> @@ -111,7 +112,8 @@ func.func @transpose(%arg0: vector<2x4xf32>) -> vector<4x2xf32> { module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.lower_transpose lowering_strategy = "shuffle_1d" } : !transform.op<"func.func"> @@ -132,7 +134,8 @@ func.func @transpose(%arg0: vector<2x4xf32>) -> vector<4x2xf32> { module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.lower_transpose lowering_strategy = "flat_transpose" } : !transform.op<"func.func"> @@ -621,7 +624,8 @@ func.func @transpose210_1x8x8xf32(%arg0: vector<1x8x8xf32>) -> vector<8x8x1xf32> } module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.lower_transpose avx2_lowering_strategy = true } : !transform.op<"func.func"> @@ -701,7 +705,8 @@ func.func @transpose_shuffle16x16xf32(%arg0: vector<16x16xf32>) -> vector<16x16x } module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.lower_transpose lowering_strategy = "shuffle_16x16" } : !transform.op<"func.func"> @@ -782,7 +787,8 @@ func.func @transpose021_shuffle16x16xf32(%arg0: vector<1x16x16xf32>) -> vector<1 } module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.lower_transpose lowering_strategy = "shuffle_16x16" } : !transform.op<"func.func"> @@ -842,7 +848,8 @@ func.func @transpose10_nx4xnx1xf32(%arg0: vector<4x[1]xf32>) -> vector<[1]x4xf32 } module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.lower_transpose } : !transform.op<"func.func"> @@ -863,7 +870,8 @@ func.func @transpose_nx8x2xf32(%arg0: vector<[8]x2xf32>) -> vector<2x[8]xf32> { } module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.lower_transpose lowering_strategy = "shuffle_1d" } : !transform.op<"func.func"> diff --git a/mlir/test/Dialect/XeGPU/XeGPUOps.mlir b/mlir/test/Dialect/XeGPU/XeGPUOps.mlir new file mode 100644 index 0000000000000000000000000000000000000000..039346adbb851c6774ad538b01649f776af16a2e --- /dev/null +++ b/mlir/test/Dialect/XeGPU/XeGPUOps.mlir @@ -0,0 +1,62 @@ +// RUN: mlir-opt %s | FileCheck %s +// Verify the printed output can be parsed. +// RUN: mlir-opt %s | mlir-opt | FileCheck %s +// Verify the generic form can be parsed. +// RUN: mlir-opt -mlir-print-op-generic %s | mlir-opt | FileCheck %s + +// CHECK-LABEL: gpu.module @test { +gpu.module @test { +// CHECK: gpu.func @test_create_nd_tdesc_vc_1(%[[arg0:.*]]: memref<24x32xf32>) { +gpu.func @test_create_nd_tdesc_vc_1(%src: memref<24x32xf32>) { + // CHECK: %[[REG:.*]] = xegpu.create_nd_tdesc %arg0[0, 0] : memref<24x32xf32> -> !xegpu.tensor_desc<8x16xf32> + %1 = xegpu.create_nd_tdesc %src[0, 0] : memref<24x32xf32> -> !xegpu.tensor_desc<8x16xf32> + gpu.return +} + +// CHECK: gpu.func @test_create_nd_tdesc_vc_2(%[[arg0:.*]]: ui64, %[[arg1:.*]]: index, %[[arg2:.*]]: index, %[[arg3:.*]]: index, %[[arg4:.*]]: index) { +gpu.func @test_create_nd_tdesc_vc_2(%src: ui64, %w : index, %h : index, %x : index, %y : index) { + //CHECK: %[[C:.*]] = arith.constant 1 : index + %c1 = arith.constant 1 : index + // CHECK: %[[REG:.*]] = xegpu.create_nd_tdesc %[[arg0]][%[[arg3]], %[[arg4]]], [%[[arg2]], %[[arg1]]], [%[[arg1]], %[[C]]] : ui64 -> !xegpu.tensor_desc<8x16xf32> + %1 = xegpu.create_nd_tdesc %src[%x, %y], [%h, %w], [%w, %c1] : ui64 -> !xegpu.tensor_desc<8x16xf32> + gpu.return +} + +// CHECK: gpu.func @test_create_nd_tdesc_vc_3(%[[arg0:.*]]: memref<24x32xf32>) { +gpu.func @test_create_nd_tdesc_vc_3(%src: memref<24x32xf32>) { + // CHECK: %[[REG:.*]] = xegpu.create_nd_tdesc %[[arg0]][0, 0] : memref<24x32xf32> -> !xegpu.tensor_desc<24x16xf32, #xegpu.tdesc_attr<array_length = 2 : i64> + %1 = xegpu.create_nd_tdesc %src[0, 0] : memref<24x32xf32> -> !xegpu.tensor_desc<24x16xf32, #xegpu.tdesc_attr<array_length = 2>> + gpu.return +} + +// CHECK: gpu.func @test_prefetch_nd_vc(%[[arg0:.*]]: memref<24x32xf16>) { +gpu.func @test_prefetch_nd_vc(%src: memref<24x32xf16>) { + // CHECK: %[[R0:.*]] = xegpu.create_nd_tdesc %[[arg0]][0, 0] : memref<24x32xf16> -> !xegpu.tensor_desc<8x16xf16> + %1 = xegpu.create_nd_tdesc %src[0, 0] : memref<24x32xf16> -> !xegpu.tensor_desc<8x16xf16> + // CHECK: xegpu.prefetch_nd %[[R0]] <{l1_hint = #xegpu.cache_hint<cached>, l2_hint = #xegpu.cache_hint<uncached>}> : !xegpu.tensor_desc<8x16xf16> + xegpu.prefetch_nd %1 <{l1_hint = #xegpu.cache_hint<cached>, l2_hint = #xegpu.cache_hint<uncached>}>: !xegpu.tensor_desc<8x16xf16> + gpu.return +} + +// CHECK: func @test_load_nd_vc(%[[arg0:.*]]: memref<8x16xf16>) { +gpu.func @test_load_nd_vc(%src: memref<8x16xf16>) { + // CHECK: %[[R0:.*]] = xegpu.create_nd_tdesc %arg0[0, 0] : memref<8x16xf16> -> !xegpu.tensor_desc<8x16xf16> + %1 = xegpu.create_nd_tdesc %src[0, 0] : memref<8x16xf16> -> !xegpu.tensor_desc<8x16xf16> + // CHECK: %[[R1:.*]] = xegpu.load_nd %[[R0]] <{l1_hint = #xegpu.cache_hint<cached>, l2_hint = #xegpu.cache_hint<uncached>, vnni_axis = 0 : i64}> : !xegpu.tensor_desc<8x16xf16> -> vector<4x16x2xf16> + %2 = xegpu.load_nd %1 <{vnni_axis = 0, l1_hint = #xegpu.cache_hint<cached>, l2_hint = #xegpu.cache_hint<uncached>}> + : !xegpu.tensor_desc<8x16xf16> -> vector<4x16x2xf16> + gpu.return +} + +// CHECK: func @test_store_nd_vc(%[[arg0:.*]]: memref<24x32xf16>) { +gpu.func @test_store_nd_vc(%dst: memref<24x32xf16>) { + // CHECK: %[[C:.*]] = arith.constant dense<1.000000e+00> : vector<24x32xf16> + %1 = arith.constant dense<1.0>: vector<24x32xf16> + // CHECK: %[[R0:.*]] = xegpu.create_nd_tdesc %[[arg0]][0, 0] : memref<24x32xf16> -> !xegpu.tensor_desc<24x32xf16> + %2 = xegpu.create_nd_tdesc %dst[0, 0] : memref<24x32xf16> -> !xegpu.tensor_desc<24x32xf16> + // CHECK: xegpu.store_nd %[[C]], %[[R0]] <{l1_hint = #xegpu.cache_hint<write_back>, l2_hint = #xegpu.cache_hint<uncached>}> : vector<24x32xf16>, !xegpu.tensor_desc<24x32xf16> + xegpu.store_nd %1, %2 <{l1_hint = #xegpu.cache_hint<write_back>, l2_hint = #xegpu.cache_hint<uncached>}>: vector<24x32xf16>, !xegpu.tensor_desc<24x32xf16> + gpu.return +} + +} \ No newline at end of file diff --git a/mlir/test/IR/custom-print-parse.mlir b/mlir/test/IR/custom-print-parse.mlir index b157fd1b1ea3386156798ebb33ffaa50ef095e0e..0eadc2e4295601b546abdfa5595e3b708bf15b3d 100644 --- a/mlir/test/IR/custom-print-parse.mlir +++ b/mlir/test/IR/custom-print-parse.mlir @@ -14,4 +14,9 @@ module @dimension_list { test.custom_dimension_list_attr dimension_list = ? // CHECK: test.custom_dimension_list_attr dimension_list = ?x? test.custom_dimension_list_attr dimension_list = ?x? + + // CHECK: test.optional_custom_attr + test.optional_custom_attr bar + // CHECK: test.optional_custom_attr foo false + test.optional_custom_attr foo false } diff --git a/mlir/test/IR/greedy-pattern-rewriter-driver.mlir b/mlir/test/IR/greedy-pattern-rewrite-driver-bottom-up.mlir similarity index 100% rename from mlir/test/IR/greedy-pattern-rewriter-driver.mlir rename to mlir/test/IR/greedy-pattern-rewrite-driver-bottom-up.mlir diff --git a/mlir/test/IR/greedy-pattern-rewrite-driver-top-down.mlir b/mlir/test/IR/greedy-pattern-rewrite-driver-top-down.mlir new file mode 100644 index 0000000000000000000000000000000000000000..a362d6f99b9478f2c7f12a31caa9b7f0cba246c6 --- /dev/null +++ b/mlir/test/IR/greedy-pattern-rewrite-driver-top-down.mlir @@ -0,0 +1,58 @@ +// RUN: mlir-opt %s -test-patterns="max-iterations=1 top-down=true" \ +// RUN: --split-input-file | FileCheck %s + +// Tests for https://github.com/llvm/llvm-project/issues/86765. Ensure +// that operands of a dead op are added to the worklist even if the same value +// appears multiple times as an operand. + +// 2 uses of the same operand + +// CHECK: func.func @f(%arg0: i1) { +// CHECK-NEXT: return +// CHECK-NEXT: } +func.func @f(%arg0: i1) { + %0 = arith.constant 0 : i32 + %if = scf.if %arg0 -> (i32) { + scf.yield %0 : i32 + } else { + scf.yield %0 : i32 + } + %dead_leaf = arith.addi %if, %if : i32 + return +} + +// ----- + +// 3 uses of the same operand + +// CHECK: func.func @f() { +// CHECK-NEXT: return +// CHECK-NEXT: } +func.func @f() { + %0 = arith.constant 0 : i1 + %if = scf.if %0 -> (i1) { + scf.yield %0 : i1 + } else { + scf.yield %0 : i1 + } + %dead_leaf = arith.select %if, %if, %if : i1 + return +} + +// ----- + +// 2 uses of the same operand, op has 3 operands + +// CHECK: func.func @f() { +// CHECK-NEXT: return +// CHECK-NEXT: } +func.func @f() { + %0 = arith.constant 0 : i1 + %if = scf.if %0 -> (i1) { + scf.yield %0 : i1 + } else { + scf.yield %0 : i1 + } + %dead_leaf = arith.select %0, %if, %if : i1 + return +} diff --git a/mlir/test/IR/invalid-custom-print-parse.mlir b/mlir/test/IR/invalid-custom-print-parse.mlir index 456b16c91bc04b73587360ebe08b9c3f606c0a4e..00da145e35e0bd89e721c6b21ddd9df4c1e22b57 100644 --- a/mlir/test/IR/invalid-custom-print-parse.mlir +++ b/mlir/test/IR/invalid-custom-print-parse.mlir @@ -14,3 +14,8 @@ test.custom_dimension_list_attr dimension_list = -1 // expected-error@+2 {{expected ']'}} // expected-error@+1 {{custom op 'test.custom_dimension_list_attr' Failed parsing dimension list.}} test.custom_dimension_list_attr dimension_list = [2x3] + +// ----- + +// expected-error @below {{expected attribute value}} +test.optional_custom_attr foo diff --git a/mlir/test/Integration/Dialect/Complex/CPU/correctness.mlir b/mlir/test/Integration/Dialect/Complex/CPU/correctness.mlir index a42ed6968d370045ddcc29b06c21b509bf112412..441f7500538f7edfa5204a9ba87d537f8917e86b 100644 --- a/mlir/test/Integration/Dialect/Complex/CPU/correctness.mlir +++ b/mlir/test/Integration/Dialect/Complex/CPU/correctness.mlir @@ -9,9 +9,6 @@ // RUN: -shared-libs=%mlir_c_runner_utils |\ // RUN: FileCheck %s -// XFAIL: target=aarch64{{.*}} -// See: https://github.com/llvm/llvm-project/issues/58531 - func.func @test_unary(%input: tensor<?xcomplex<f32>>, %func: (complex<f32>) -> complex<f32>) { %c0 = arith.constant 0 : index @@ -189,8 +186,9 @@ func.func @entry() { // CHECK-NEXT: 0 // CHECK-NEXT: 0 (0.0, 0.0), (-1.0, 0.0), - // CHECK-NEXT: -nan - // CHECK-NEXT: -nan + // Ignoring the sign of nan as that can't be tested in platform agnostic manner. See: #58531 + // CHECK-NEXT: nan + // CHECK-NEXT: nan (1.0, 1.0), (1.0, 1.0) // CHECK-NEXT: 0.273 // CHECK-NEXT: 0.583 diff --git a/mlir/test/Integration/Dialect/Linalg/CPU/ArmSVE/1d-depthwise-conv.mlir b/mlir/test/Integration/Dialect/Linalg/CPU/ArmSVE/1d-depthwise-conv.mlir new file mode 100644 index 0000000000000000000000000000000000000000..56dce1c654017029b474dc77f9d1b2b33899c2fe --- /dev/null +++ b/mlir/test/Integration/Dialect/Linalg/CPU/ArmSVE/1d-depthwise-conv.mlir @@ -0,0 +1,60 @@ +// DEFINE: %{compile} = mlir-opt %s \ +// DEFINE: -transform-interpreter -test-transform-dialect-erase-schedule \ +// DEFINE: -one-shot-bufferize="bufferize-function-boundaries" -lower-vector-mask -buffer-deallocation-pipeline -cse -canonicalize -convert-vector-to-scf -arm-sve-legalize-vector-storage \ +// DEFINE: -convert-vector-to-llvm="enable-arm-sve" -test-lower-to-llvm -o %t +// DEFINE: %{entry_point} = conv +// DEFINE: %{run} = %mcr_aarch64_cmd %t -e %{entry_point} -entry-point-result=void --march=aarch64 --mattr="+sve"\ +// DEFINE: -shared-libs=%mlir_runner_utils,%mlir_c_runner_utils + +// RUN: rm -f %t && %{compile} && %{run} | FileCheck %s + +func.func @conv() { + // Define input/output tensors + %input_init = tensor.empty() : tensor<1x8x6xi32> + %output_init = tensor.empty() : tensor<1x7x6xi32> + + %five = arith.constant 5 : i32 + %zero = arith.constant 0 : i32 + %input = linalg.fill ins(%five : i32) outs(%input_init : tensor<1x8x6xi32>) -> tensor<1x8x6xi32> + %output = linalg.fill ins(%zero : i32) outs(%output_init : tensor<1x7x6xi32>) -> tensor<1x7x6xi32> + + // Define the filter tensor + %filter = arith.constant dense<[ + [ 1, 2, 3, 4, 5, 6], + [ 11, 12, 13, 14, 15, 16] + ]> : tensor<2x6xi32> + + // static sizes -> dynamic sizes + %input_dyn = tensor.cast %input_init : tensor<1x8x6xi32> to tensor<1x8x?xi32> + %output_dyn = tensor.cast %output : tensor<1x7x6xi32> to tensor<1x7x?xi32> + %filter_dyn = tensor.cast %filter : tensor<2x6xi32> to tensor<2x?xi32> + + // Run the convolution + %res = linalg.depthwise_conv_1d_nwc_wc + ins(%input_dyn, %filter_dyn : tensor<1x8x?xi32>, tensor<2x?xi32>) + outs(%output_dyn : tensor<1x7x?xi32>) -> tensor<1x7x?xi32> + + // Print the results + // CHECK: SVE: START OF TEST OUTPUT + vector.print str "SVE: START OF TEST OUTPUT\n" + + // CHECK-NEXT: Unranked Memref base@ = {{.*}} rank = 3 offset = 0 sizes = [1, 7, 6] strides = [42, 6, 1] data = + // CHECK-COUNT-7: [60, 70, 80, 90, 100, 110] + %xf = tensor.cast %res : tensor<1x7x?xi32> to tensor<*xi32> + call @printMemrefI32(%xf) : (tensor<*xi32>) -> () + + // CHECK-NEXT: SVE: END OF TEST OUTPUT + vector.print str "SVE: END OF TEST OUTPUT\n" + + return +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) { + %0 = transform.structured.match ops{["linalg.depthwise_conv_1d_nwc_wc"]} in %arg0 : (!transform.any_op) -> !transform.any_op + transform.structured.vectorize %0 vector_sizes [1, 7, [8], 2] : !transform.any_op + transform.yield + } +} + +func.func private @printMemrefI32(%ptr : tensor<*xi32>) diff --git a/mlir/test/Integration/Dialect/Linalg/CPU/ArmSVE/fill-1d.mlir b/mlir/test/Integration/Dialect/Linalg/CPU/ArmSVE/fill-1d.mlir index a5b2ad1605cd100e3a08199a9409fd7cfe0536fa..44b555c8c3ad5e5186518d7015ee1c67a8ffd718 100644 --- a/mlir/test/Integration/Dialect/Linalg/CPU/ArmSVE/fill-1d.mlir +++ b/mlir/test/Integration/Dialect/Linalg/CPU/ArmSVE/fill-1d.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-opt %s -transform-interpreter -test-transform-dialect-erase-schedule -lower-vector-mask -one-shot-bufferize -test-lower-to-llvm | \ +// RUN: mlir-opt %s -transform-interpreter -test-transform-dialect-erase-schedule -lower-vector-mask -one-shot-bufferize -buffer-deallocation-pipeline -test-lower-to-llvm | \ // RUN: %mcr_aarch64_cmd -e=entry -entry-point-result=void --march=aarch64 --mattr="+sve" -shared-libs=%mlir_runner_utils,%mlir_c_runner_utils | \ // RUN: FileCheck %s diff --git a/mlir/test/Integration/Dialect/Linalg/CPU/ArmSVE/matmul.mlir b/mlir/test/Integration/Dialect/Linalg/CPU/ArmSVE/matmul.mlir index 51a0c8f7c945aab378d4b2699b7633f62a355856..68e474fe5cefeb597d1fb04bc047414db62f94a0 100644 --- a/mlir/test/Integration/Dialect/Linalg/CPU/ArmSVE/matmul.mlir +++ b/mlir/test/Integration/Dialect/Linalg/CPU/ArmSVE/matmul.mlir @@ -1,6 +1,6 @@ // DEFINE: %{compile} = mlir-opt %s \ // DEFINE: -transform-interpreter -test-transform-dialect-erase-schedule \ -// DEFINE: -one-shot-bufferize -func-bufferize -cse -canonicalize -convert-vector-to-scf -arm-sve-legalize-vector-storage \ +// DEFINE: -one-shot-bufferize="bufferize-function-boundaries" -buffer-deallocation-pipeline -cse -canonicalize -convert-vector-to-scf -arm-sve-legalize-vector-storage \ // DEFINE: -convert-vector-to-llvm="enable-arm-sve" -test-lower-to-llvm -o %t // DEFINE: %{entry_point} = matmul_f32 // DEFINE: %{run} = %mcr_aarch64_cmd %t -e %{entry_point} -entry-point-result=void --march=aarch64 --mattr="+sve"\ diff --git a/mlir/test/Integration/Dialect/Linalg/CPU/mmt4d.mlir b/mlir/test/Integration/Dialect/Linalg/CPU/mmt4d.mlir index 8ee4e1fb48fef1358391d29864aff054b27ac8fc..92c7039c849601bdff474f2210c0a708497fa6d3 100644 --- a/mlir/test/Integration/Dialect/Linalg/CPU/mmt4d.mlir +++ b/mlir/test/Integration/Dialect/Linalg/CPU/mmt4d.mlir @@ -1,6 +1,6 @@ // DEFINE: %{compile} = mlir-opt %s \ // DEFINE: -transform-interpreter -test-transform-dialect-erase-schedule \ -// DEFINE: -one-shot-bufferize -func-bufferize -cse -canonicalize -convert-vector-to-scf -test-lower-to-llvm -o %t +// DEFINE: -one-shot-bufferize="bufferize-function-boundaries" -buffer-deallocation-pipeline -cse -canonicalize -convert-vector-to-scf -test-lower-to-llvm -o %t // DEFINE: %{entry_point} = mmt4d // DEFINE: %{run} = mlir-cpu-runner %t -e %{entry_point} -entry-point-result=void \ // DEFINE: -shared-libs=%mlir_runner_utils,%mlir_c_runner_utils diff --git a/mlir/test/Integration/Dialect/Linalg/CPU/pack-unpack-mmt4d.mlir b/mlir/test/Integration/Dialect/Linalg/CPU/pack-unpack-mmt4d.mlir new file mode 100644 index 0000000000000000000000000000000000000000..5680882dccb1ee7e026e084c4f0b9439ca8d302c --- /dev/null +++ b/mlir/test/Integration/Dialect/Linalg/CPU/pack-unpack-mmt4d.mlir @@ -0,0 +1,173 @@ +// DEFINE: %{compile} = mlir-opt %s \ +// DEFINE: -transform-interpreter -test-transform-dialect-erase-schedule \ +// DEFINE: -one-shot-bufferize="bufferize-function-boundaries" \ +// DEFINE: -buffer-deallocation-pipeline="private-function-dynamic-ownership" \ +// DEFINE: -cse -canonicalize -test-lower-to-llvm +// DEFINE: %{entry_point} = main +// DEFINE: %{run} = mlir-cpu-runner -e %{entry_point} -entry-point-result=void \ +// DEFINE: -shared-libs=%mlir_runner_utils,%mlir_c_runner_utils + +// RUN: %{compile} | %{run} | FileCheck %s + +/// End-to-end test for computing matrix-multiplication using linalg.mmt4d. In +/// particular, demonstrates how the following MLIR sequence (implemented in @mmt4d): +/// +/// A_pack = tensor.pack A +/// B_pack = tensor.pack B +/// C_pack = tensor.pack C +/// out_pack = linalg.mmt4d(A_pack, B_pack, C_pack) +/// +/// is equivalent to: +/// +/// linalg.matmul(A, B, C) +/// +/// (implemented in @matmul). + +func.func @main() { + // Allocate and initialise the inputs + %A_alloc = tensor.empty() : tensor<7x16xi32> + %B_alloc = tensor.empty() : tensor<16x13xi32> + + %three = arith.constant 3 : i32 + %four = arith.constant 4 : i32 + %A = linalg.fill ins(%three : i32) outs(%A_alloc : tensor<7x16xi32>) -> tensor<7x16xi32> + %B = linalg.fill ins(%four : i32) outs(%B_alloc : tensor<16x13xi32>) -> tensor<16x13xi32> + %C = arith.constant dense<[ + [ 1, 8, 15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85], + [ 2, 9, 16, 23, 30, 37, 44, 51, 58, 65, 72, 79, 86], + [ 3, 10, 17, 24, 31, 38, 45, 52, 59, 66, 73, 80, 87], + [ 4, 11, 18, 25, 32, 39, 46, 53, 60, 67, 74, 81, 88], + [ 5, 12, 19, 26, 33, 40, 47, 54, 61, 68, 75, 82, 89], + [ 6, 13, 20, 27, 34, 41, 48, 55, 62, 69, 76, 83, 90], + [ 7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91] + ]> : tensor<7x13xi32> + + // Matrix multiplication via linalg.mmt4d + // CHECK: Unranked Memref + // CHECK: [193, 200, 207, 214, 221, 228, 235, 242, 249, 256, 263, 270, 277] + // CHECK: [194, 201, 208, 215, 222, 229, 236, 243, 250, 257, 264, 271, 278] + // CHECK: [195, 202, 209, 216, 223, 230, 237, 244, 251, 258, 265, 272, 279] + // CHECK: [196, 203, 210, 217, 224, 231, 238, 245, 252, 259, 266, 273, 280] + // CHECK: [197, 204, 211, 218, 225, 232, 239, 246, 253, 260, 267, 274, 281] + // CHECK: [198, 205, 212, 219, 226, 233, 240, 247, 254, 261, 268, 275, 282] + // CHECK: [199, 206, 213, 220, 227, 234, 241, 248, 255, 262, 269, 276, 283] + %C_mmt4d = func.call @mmt4d(%A, %B, %C) : (tensor<7x16xi32>, tensor<16x13xi32>, tensor<7x13xi32>) -> tensor<7x13xi32> + %xf = tensor.cast %C_mmt4d : tensor<7x13xi32> to tensor<*xi32> + call @printMemrefI32(%xf) : (tensor<*xi32>) -> () + + // Matrix multiplication with linalg.matmul + // CHECK: Unranked Memref + // CHECK: [193, 200, 207, 214, 221, 228, 235, 242, 249, 256, 263, 270, 277] + // CHECK: [194, 201, 208, 215, 222, 229, 236, 243, 250, 257, 264, 271, 278] + // CHECK: [195, 202, 209, 216, 223, 230, 237, 244, 251, 258, 265, 272, 279] + // CHECK: [196, 203, 210, 217, 224, 231, 238, 245, 252, 259, 266, 273, 280] + // CHECK: [197, 204, 211, 218, 225, 232, 239, 246, 253, 260, 267, 274, 281] + // CHECK: [198, 205, 212, 219, 226, 233, 240, 247, 254, 261, 268, 275, 282] + // CHECK: [199, 206, 213, 220, 227, 234, 241, 248, 255, 262, 269, 276, 283] + %C_matmul = func.call @matmul(%A, %B, %C) : (tensor<7x16xi32>, tensor<16x13xi32>, tensor<7x13xi32>) -> tensor<7x13xi32> + %xf_2 = tensor.cast %C_matmul : tensor<7x13xi32> to tensor<*xi32> + call @printMemrefI32(%xf_2) : (tensor<*xi32>) -> () + + return +} + +func.func private @matmul(%A: tensor<7x16xi32>, %B: tensor<16x13xi32>, %C: tensor<7x13xi32>) -> tensor<7x13xi32> { + %C_matmul = linalg.matmul ins(%A, %B: tensor<7x16xi32>, tensor<16x13xi32>) + outs(%C: tensor<7x13xi32>) -> tensor<7x13xi32> + + return %C_matmul : tensor<7x13xi32> +} + +func.func private @mmt4d(%A: tensor<7x16xi32>, %B: tensor<16x13xi32>, %C: tensor<7x13xi32>) -> tensor<7x13xi32> { + %zero = arith.constant 0 : i32 + + %A_pack_empty = tensor.empty() : tensor<2x16x8x1xi32> + %B_pack_empty = tensor.empty() : tensor<2x16x8x1xi32> + %C_pack_empty = tensor.empty() : tensor<2x2x8x8xi32> + + // Pack matrices + %A_pack = tensor.pack %A padding_value(%zero : i32) inner_dims_pos = [0, 1] inner_tiles = [8, 1] into %A_pack_empty : tensor<7x16xi32> -> tensor<2x16x8x1xi32> + %B_pack = tensor.pack %B padding_value(%zero : i32) outer_dims_perm = [1, 0] inner_dims_pos = [1, 0] inner_tiles = [8, 1] into %B_pack_empty : tensor<16x13xi32> -> tensor<2x16x8x1xi32> + %C_pack = tensor.pack %C padding_value(%zero : i32) outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %C_pack_empty : tensor<7x13xi32> -> tensor<2x2x8x8xi32> + + // MMT4D + %mmt4d = linalg.mmt4d ins(%A_pack, %B_pack : tensor<2x16x8x1xi32>, tensor<2x16x8x1xi32>) outs(%C_pack : tensor<2x2x8x8xi32>) -> tensor<2x2x8x8xi32> + + // Unpack output + %C_out_empty = tensor.empty() : tensor<7x13xi32> + %C_out_unpack = tensor.unpack %mmt4d outer_dims_perm = [0, 1] inner_dims_pos = [0, 1] inner_tiles = [8, 8] into %C_out_empty : tensor<2x2x8x8xi32> -> tensor<7x13xi32> + + return %C_out_unpack : tensor<7x13xi32> +} + +module @transforms attributes { transform.with_named_sequence } { + transform.named_sequence @__transform_main(%module: !transform.any_op {transform.readonly}) { + %mmt4d = transform.collect_matching @match_mmt4d in %module : (!transform.any_op) -> (!transform.any_op) + %func = transform.get_parent_op %mmt4d {isolated_from_above} : (!transform.any_op) -> !transform.op<"func.func"> + + // Step 1: Tile + // Tile parallel dims + %tiled_linalg_op_p, %loops:4 = transform.structured.tile_using_for %mmt4d[1, 1, 0, 8, 8, 0] + : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op, !transform.any_op, !transform.any_op) + // Tile reduction dims + %tiled_linalg_op_r, %loops2:2 = transform.structured.tile_using_for %tiled_linalg_op_p[0, 0, 1, 0, 0, 1] + : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op) + + // Step 2: Vectorize + transform.structured.vectorize %tiled_linalg_op_r : !transform.any_op + + // Step 3: Simplify + // vector.multi_reduction --> vector.contract + // Generates a 6-dim vector.contract with the dim matching the original MMT4D Op + // and with the following split into parallel and reduction dims: + // * parallel, parallel, reduction, parallel, parallel, reduction + transform.apply_patterns to %func { + transform.apply_patterns.vector.reduction_to_contract + // Reduce the rank of xfer ops. This transforms vector.contract to be + // more matmul-like and to enable the lowering to outer product Ops. + transform.apply_patterns.vector.transfer_permutation_patterns + } : !transform.op<"func.func"> + + // Hoisting and LICM - not strictly required + %func_h = transform.structured.hoist_redundant_vector_transfers %func + : (!transform.op<"func.func">) -> !transform.op<"func.func"> + %all_loops = transform.structured.match interface{LoopLikeInterface} in %func_h + : (!transform.op<"func.func">) -> !transform.any_op + transform.apply_licm to %all_loops : !transform.any_op + transform.loop.hoist_loop_invariant_subsets %all_loops : !transform.any_op + + // Simplify the 6-dim vector.contract into a 3-dim matmul-like + // vector.contract with the following split into parallel and reduction + // dims: + // * parallel, parallel, reduction + transform.apply_patterns to %func_h { + transform.apply_patterns.vector.reduction_to_contract + transform.apply_patterns.vector.cast_away_vector_leading_one_dim + transform.apply_patterns.canonicalization + } : !transform.op<"func.func"> + + // Step 4. Lower tensor.pack + %pack = transform.structured.match ops{["tensor.pack"]} in %func_h + : (!transform.op<"func.func">) -> !transform.op<"tensor.pack"> + transform.structured.lower_pack %pack : (!transform.op<"tensor.pack">) + -> (!transform.op<"tensor.pad">, !transform.op<"tensor.expand_shape">, !transform.op<"linalg.transpose">) + + // Step 5. Lower tensor.unpack + %unpack = transform.structured.match ops{["tensor.unpack"]} in %func_h + : (!transform.op<"func.func">) -> !transform.op<"tensor.unpack"> + transform.structured.lower_unpack %unpack : (!transform.op<"tensor.unpack">) + -> (!transform.op<"tensor.empty">, + !transform.op<"linalg.transpose">, + !transform.op<"tensor.collapse_shape">, + !transform.op<"tensor.extract_slice">) + transform.yield + } + + transform.named_sequence @match_mmt4d( + %entry: !transform.any_op {transform.readonly}) -> !transform.any_op { + transform.match.operation_name %entry ["linalg.mmt4d"] : !transform.any_op + transform.yield %entry : !transform.any_op + } +} + +func.func private @printMemrefI32(%ptr : tensor<*xi32>) diff --git a/mlir/test/Integration/Dialect/Linalg/CPU/test-matmul-masked-vec.mlir b/mlir/test/Integration/Dialect/Linalg/CPU/test-matmul-masked-vec.mlir index 0378d638df61abe3336f521833a386f555fd850a..a70d794506c483722036e6a16e5c11a6ecb82fbd 100644 --- a/mlir/test/Integration/Dialect/Linalg/CPU/test-matmul-masked-vec.mlir +++ b/mlir/test/Integration/Dialect/Linalg/CPU/test-matmul-masked-vec.mlir @@ -1,4 +1,4 @@ -// RUN: mlir-opt %s -transform-interpreter -test-transform-dialect-erase-schedule -one-shot-bufferize -func-bufferize -lower-vector-mask --test-lower-to-llvm | \ +// RUN: mlir-opt %s -transform-interpreter -test-transform-dialect-erase-schedule -one-shot-bufferize="bufferize-function-boundaries" -buffer-deallocation-pipeline -lower-vector-mask --test-lower-to-llvm | \ // RUN: mlir-cpu-runner -e main -entry-point-result=void --shared-libs=%mlir_c_runner_utils,%mlir_runner_utils | \ // RUN: FileCheck %s diff --git a/mlir/test/Integration/Dialect/Memref/reinterpret-cast-runtime-verification.mlir b/mlir/test/Integration/Dialect/Memref/reinterpret-cast-runtime-verification.mlir index 3700291540547872205706ae1b94f7b1bc5f546b..2239ba50b6626787420b6ac44bf1af2a6ba2d1ab 100644 --- a/mlir/test/Integration/Dialect/Memref/reinterpret-cast-runtime-verification.mlir +++ b/mlir/test/Integration/Dialect/Memref/reinterpret-cast-runtime-verification.mlir @@ -34,7 +34,8 @@ func.func @main() { %5 = arith.constant 5 : index %alloca_1 = memref.alloca() : memref<1xf32> - %alloc_4 = memref.alloc(%4) : memref<?xf32> + %alloca_4 = memref.alloca() : memref<4xf32> + %alloca_4_dyn = memref.cast %alloca_4 : memref<4xf32> to memref<?xf32> // Offset is out-of-bounds // CHECK: ERROR: Runtime op verification failed @@ -55,20 +56,20 @@ func.func @main() { // CHECK-NEXT: "memref.reinterpret_cast"(%{{.*}}) // CHECK-NEXT: ^ result of reinterpret_cast is out-of-bounds of the base memref // CHECK-NEXT: Location: loc({{.*}}) - func.call @reinterpret_cast_fully_dynamic(%alloc_4, %0, %5, %1) : (memref<?xf32>, index, index, index) -> () + func.call @reinterpret_cast_fully_dynamic(%alloca_4_dyn, %0, %5, %1) : (memref<?xf32>, index, index, index) -> () // Stride is out-of-bounds // CHECK: ERROR: Runtime op verification failed // CHECK-NEXT: "memref.reinterpret_cast"(%{{.*}}) // CHECK-NEXT: ^ result of reinterpret_cast is out-of-bounds of the base memref // CHECK-NEXT: Location: loc({{.*}}) - func.call @reinterpret_cast_fully_dynamic(%alloc_4, %0, %4, %4) : (memref<?xf32>, index, index, index) -> () + func.call @reinterpret_cast_fully_dynamic(%alloca_4_dyn, %0, %4, %4) : (memref<?xf32>, index, index, index) -> () // CHECK-NOT: ERROR: Runtime op verification failed func.call @reinterpret_cast(%alloca_1, %0) : (memref<1xf32>, index) -> () // CHECK-NOT: ERROR: Runtime op verification failed - func.call @reinterpret_cast_fully_dynamic(%alloc_4, %0, %4, %1) : (memref<?xf32>, index, index, index) -> () + func.call @reinterpret_cast_fully_dynamic(%alloca_4_dyn, %0, %4, %1) : (memref<?xf32>, index, index, index) -> () return } diff --git a/mlir/test/Integration/Dialect/Memref/subview-runtime-verification.mlir b/mlir/test/Integration/Dialect/Memref/subview-runtime-verification.mlir index 48987ce216f1a3a031d5af582f7fd9858bbe5ab1..3ccf8b1be6d7bf4a687f64353ce7de9a8ad25f58 100644 --- a/mlir/test/Integration/Dialect/Memref/subview-runtime-verification.mlir +++ b/mlir/test/Integration/Dialect/Memref/subview-runtime-verification.mlir @@ -38,14 +38,15 @@ func.func @main() { %5 = arith.constant 5 : index %alloca = memref.alloca() : memref<1xf32> - %alloc = memref.alloc(%4) : memref<?x4xf32> + %alloca_4 = memref.alloca() : memref<4x4xf32> + %alloca_4_dyn = memref.cast %alloca_4 : memref<4x4xf32> to memref<?x4xf32> // Offset is out-of-bounds // CHECK: ERROR: Runtime op verification failed // CHECK-NEXT: "memref.subview" // CHECK-NEXT: ^ subview is out-of-bounds of the base memref // CHECK-NEXT: Location: loc({{.*}}) - func.call @subview_dynamic_rank_reduce(%alloc, %5, %5, %1) : (memref<?x4xf32>, index, index, index) -> () + func.call @subview_dynamic_rank_reduce(%alloca_4_dyn, %5, %5, %1) : (memref<?x4xf32>, index, index, index) -> () // Offset is out-of-bounds // CHECK: ERROR: Runtime op verification failed @@ -66,23 +67,23 @@ func.func @main() { // CHECK-NEXT: "memref.subview" // CHECK-NEXT: ^ subview is out-of-bounds of the base memref // CHECK-NEXT: Location: loc({{.*}}) - func.call @subview_dynamic(%alloc, %0, %5, %1) : (memref<?x4xf32>, index, index, index) -> () + func.call @subview_dynamic(%alloca_4_dyn, %0, %5, %1) : (memref<?x4xf32>, index, index, index) -> () // Stride is out-of-bounds // CHECK: ERROR: Runtime op verification failed // CHECK-NEXT: "memref.subview" // CHECK-NEXT: ^ subview is out-of-bounds of the base memref // CHECK-NEXT: Location: loc({{.*}}) - func.call @subview_dynamic(%alloc, %0, %4, %4) : (memref<?x4xf32>, index, index, index) -> () + func.call @subview_dynamic(%alloca_4_dyn, %0, %4, %4) : (memref<?x4xf32>, index, index, index) -> () // CHECK-NOT: ERROR: Runtime op verification failed func.call @subview(%alloca, %0) : (memref<1xf32>, index) -> () // CHECK-NOT: ERROR: Runtime op verification failed - func.call @subview_dynamic(%alloc, %0, %4, %1) : (memref<?x4xf32>, index, index, index) -> () + func.call @subview_dynamic(%alloca_4_dyn, %0, %4, %1) : (memref<?x4xf32>, index, index, index) -> () // CHECK-NOT: ERROR: Runtime op verification failed - func.call @subview_dynamic_rank_reduce(%alloc, %0, %1, %0) : (memref<?x4xf32>, index, index, index) -> () + func.call @subview_dynamic_rank_reduce(%alloca_4_dyn, %0, %1, %0) : (memref<?x4xf32>, index, index, index) -> () return diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/dual_sparse_conv_2d.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/dual_sparse_conv_2d.mlir index 350b5b41dafc008c9c7b54aca755205938084e77..c645ca6567209c162ddc0fef8704fb20eae3d323 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/dual_sparse_conv_2d.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/dual_sparse_conv_2d.mlir @@ -222,6 +222,7 @@ module { bufferization.dealloc_tensor %sparse_filter_CD : tensor<3x3xi32, #CDR> bufferization.dealloc_tensor %sparse_filter_CSC : tensor<3x3xi32, #CSC> + bufferization.dealloc_tensor %0 : tensor<6x6xi32> bufferization.dealloc_tensor %2 : tensor<6x6xi32, #DCSR> bufferization.dealloc_tensor %3 : tensor<6x6xi32, #CSR> bufferization.dealloc_tensor %4 : tensor<6x6xi32, #CDR> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/reshape_dot.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/reshape_dot.mlir index ebf9f4392d859b09a57753639d2aad5c3ce2321c..f7975e0738fa81e3d33bb868ebc9f76fefd59e53 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/reshape_dot.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/reshape_dot.mlir @@ -35,8 +35,8 @@ #COO_3D = #sparse_tensor.encoding<{ map = (d0, d1, d2) -> (d0 : compressed(nonunique), d1 : singleton(nonunique), d2 : singleton), posWidth = 32, crdWidth = 32 }> module { - func.func private @printMemref3dF32(%ptr : tensor<?x?x?xf32>) attributes { llvm.emit_c_interface } - func.func private @printMemref2dF32(%ptr : tensor<?x?xf32>) attributes { llvm.emit_c_interface } + func.func private @printMemref3dF32(%ptr : tensor<?x?x?xf32> {bufferization.access = "read"}) attributes { llvm.emit_c_interface } + func.func private @printMemref2dF32(%ptr : tensor<?x?xf32> {bufferization.access = "read"}) attributes { llvm.emit_c_interface } func.func @test_sparse_rhs(%arg0: tensor<5x6xf32>, %arg1: tensor<6x2x3xf32, #COO_3D>) -> tensor<?x?x?xf32> { %collapsed = tensor.collapse_shape %arg1 [[0], [1, 2]] : tensor<6x2x3xf32, #COO_3D> into tensor<6x6xf32, #COO_2D> @@ -46,6 +46,11 @@ module { %2 = linalg.matmul ins(%arg0, %collapsed : tensor<5x6xf32>, tensor<6x6xf32, #COO_2D>) outs(%1 : tensor<5x6xf32>) -> tensor<5x6xf32> %expanded = tensor.expand_shape %2 [[0], [1, 2]] : tensor<5x6xf32> into tensor<5x2x3xf32> %ret1 = tensor.cast %expanded : tensor<5x2x3xf32> to tensor<?x?x?xf32> + + // Note: tensor.collapse_shape is a metadata-only operation on dense tensors + // but requires reallocation on sparse tensors. + bufferization.dealloc_tensor %collapsed : tensor<6x6xf32, #COO_2D> + return %ret1 : tensor<?x?x?xf32> } @@ -57,6 +62,11 @@ module { %2 = linalg.matmul ins(%arg0, %collapsed : tensor<5x6xf32, #COO_2D>, tensor<6x6xf32, #COO_2D>) outs(%1 : tensor<5x6xf32>) -> tensor<5x6xf32> %expanded = tensor.expand_shape %2 [[0], [1, 2]] : tensor<5x6xf32> into tensor<5x2x3xf32> %ret1 = tensor.cast %expanded : tensor<5x2x3xf32> to tensor<?x?x?xf32> + + // Note: tensor.collapse_shape is a metadata-only operation on dense tensors + // but requires reallocation on sparse tensors. + bufferization.dealloc_tensor %collapsed : tensor<6x6xf32, #COO_2D> + return %ret1 : tensor<?x?x?xf32> } @@ -80,6 +90,11 @@ module { %2 = linalg.matmul ins(%arg0, %collapsed : tensor<5x6xf32, #COO_2D>, tensor<6x6xf32, #COO_2D>) outs(%1 : tensor<5x6xf32>) -> tensor<5x6xf32> %expanded = tensor.expand_shape %2 [[0], [1, 2]] : tensor<5x6xf32> into tensor<5x2x3xf32> %ret1 = tensor.cast %expanded : tensor<5x2x3xf32> to tensor<?x?x?xf32> + + // Note: tensor.collapse_shape is a metadata-only operation on dense tensors + // but requires reallocation on sparse tensors. + bufferization.dealloc_tensor %collapsed : tensor<6x6xf32, #COO_2D> + return %ret1 : tensor<?x?x?xf32> } @@ -192,6 +207,7 @@ module { bufferization.dealloc_tensor %so1 : tensor<?x?x?xf32> bufferization.dealloc_tensor %so2 : tensor<?x?x?xf32> bufferization.dealloc_tensor %so3 : tensor<?x?x?xf32> + return } } diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_block_matmul.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_block_matmul.mlir index 464de9c8a2c3a6e08fdec826b722d9cfdfe4ea3a..efef01155cc784edb6dd73f64df01952193c1f67 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_block_matmul.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_block_matmul.mlir @@ -161,6 +161,14 @@ module { call @dump_dense_f64(%s24) : (tensor<4x4xf64>) -> () call @dump_dense_f64(%scsr) : (tensor<4x4xf64>) -> () + bufferization.dealloc_tensor %a : tensor<4x8xf64, #BSR> + bufferization.dealloc_tensor %b : tensor<4x8xf64, #NV_24> + bufferization.dealloc_tensor %c : tensor<4x8xf64, #CSR> + bufferization.dealloc_tensor %d : tensor<4x4xf64> + bufferization.dealloc_tensor %s : tensor<4x4xf64> + bufferization.dealloc_tensor %s24 : tensor<4x4xf64> + bufferization.dealloc_tensor %scsr : tensor<4x4xf64> + return } } diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d.mlir index f8fb8fdf53e35642f67d77c4483e9b22c112e110..55d4caeb7eb30e6fdb0e0fc6f4a723e5c3b2e937 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conv_2d.mlir @@ -273,11 +273,14 @@ module { bufferization.dealloc_tensor %sparse_input_CSC : tensor<8x8xi32, #CSC> bufferization.dealloc_tensor %sparse_input_CD : tensor<8x8xi32, #CDR> + bufferization.dealloc_tensor %0 : tensor<6x6xi32> bufferization.dealloc_tensor %1 : tensor<6x6xi32, #DCSR> bufferization.dealloc_tensor %2 : tensor<6x6xi32, #DCSR> bufferization.dealloc_tensor %3 : tensor<6x6xi32, #CSR> bufferization.dealloc_tensor %4 : tensor<6x6xi32, #CDR> bufferization.dealloc_tensor %5 : tensor<6x6xi32, #CSC> + bufferization.dealloc_tensor %6 : tensor<6x6xi32> + return } } diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion.mlir index f13c1c66df6dce9ebf7faf24386b46aedc8cff9e..8024c128189597af2677325baf2f90615cdecfff 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -46,28 +46,10 @@ // Integration test that tests conversions between sparse tensors. // module { - // - // Output utilities. - // - func.func @dumpf64(%arg0: memref<?xf64>) { - %c0 = arith.constant 0 : index - %d0 = arith.constant -1.0 : f64 - %0 = vector.transfer_read %arg0[%c0], %d0: memref<?xf64>, vector<24xf64> - vector.print %0 : vector<24xf64> - return - } - func.func @dumpidx(%arg0: memref<?xindex>) { - %c0 = arith.constant 0 : index - %d0 = arith.constant 0 : index - %0 = vector.transfer_read %arg0[%c0], %d0: memref<?xindex>, vector<25xindex> - vector.print %0 : vector<25xindex> - return - } - // // Main driver. // - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c2 = arith.constant 2 : index @@ -110,195 +92,176 @@ module { %i = sparse_tensor.convert %3 : tensor<2x3x4xf64, #Tensor3> to tensor<2x3x4xf64, #Tensor3> // - // Check number_of_entries. + // Verify the outputs. // - // CHECK-COUNT-12: 24 - %nv1 = sparse_tensor.number_of_entries %1 : tensor<2x3x4xf64, #Tensor1> - %nv2 = sparse_tensor.number_of_entries %2 : tensor<2x3x4xf64, #Tensor2> - %nv3 = sparse_tensor.number_of_entries %3 : tensor<2x3x4xf64, #Tensor3> - %nav = sparse_tensor.number_of_entries %a : tensor<2x3x4xf64, #Tensor1> - %nbv = sparse_tensor.number_of_entries %b : tensor<2x3x4xf64, #Tensor1> - %ncv = sparse_tensor.number_of_entries %c : tensor<2x3x4xf64, #Tensor1> - %ndv = sparse_tensor.number_of_entries %d : tensor<2x3x4xf64, #Tensor2> - %nev = sparse_tensor.number_of_entries %e : tensor<2x3x4xf64, #Tensor2> - %nfv = sparse_tensor.number_of_entries %f : tensor<2x3x4xf64, #Tensor2> - %ngv = sparse_tensor.number_of_entries %g : tensor<2x3x4xf64, #Tensor3> - %nhv = sparse_tensor.number_of_entries %h : tensor<2x3x4xf64, #Tensor3> - %niv = sparse_tensor.number_of_entries %i : tensor<2x3x4xf64, #Tensor3> - vector.print %nv1 : index - vector.print %nv2 : index - vector.print %nv3 : index - vector.print %nav : index - vector.print %nbv : index - vector.print %ncv : index - vector.print %ndv : index - vector.print %nev : index - vector.print %nfv : index - vector.print %ngv : index - vector.print %nhv : index - vector.print %niv : index - + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 2, 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 2 + // CHECK-NEXT: crd[0] : ( 0, 1 + // CHECK-NEXT: pos[1] : ( 0, 3, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 0, 1, 2 + // CHECK-NEXT: pos[2] : ( 0, 4, 8, 12, 16, 20, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 + // CHECK-NEXT: ---- // - // Check values. + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4, 2 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 4, 8, 12 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: pos[2] : ( 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9, 21, 10, 22, 11, 23, 12, 24 + // CHECK-NEXT: ---- // - // CHECK: ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 ) - // CHECK-NEXT: ( 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9, 21, 10, 22, 11, 23, 12, 24 ) - // CHECK-NEXT: ( 1, 5, 9, 13, 17, 21, 2, 6, 10, 14, 18, 22, 3, 7, 11, 15, 19, 23, 4, 8, 12, 16, 20, 24 ) - // CHECK-NEXT: ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 ) - // CHECK-NEXT: ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 ) - // CHECK-NEXT: ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 ) - // CHECK-NEXT: ( 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9, 21, 10, 22, 11, 23, 12, 24 ) - // CHECK-NEXT: ( 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9, 21, 10, 22, 11, 23, 12, 24 ) - // CHECK-NEXT: ( 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9, 21, 10, 22, 11, 23, 12, 24 ) - // CHECK-NEXT: ( 1, 5, 9, 13, 17, 21, 2, 6, 10, 14, 18, 22, 3, 7, 11, 15, 19, 23, 4, 8, 12, 16, 20, 24 ) - // CHECK-NEXT: ( 1, 5, 9, 13, 17, 21, 2, 6, 10, 14, 18, 22, 3, 7, 11, 15, 19, 23, 4, 8, 12, 16, 20, 24 ) - // CHECK-NEXT: ( 1, 5, 9, 13, 17, 21, 2, 6, 10, 14, 18, 22, 3, 7, 11, 15, 19, 23, 4, 8, 12, 16, 20, 24 ) + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 4, 2, 3 ) + // CHECK-NEXT: pos[0] : ( 0, 4 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6, 8 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: pos[2] : ( 0, 3, 6, 9, 12, 15, 18, 21, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2 + // CHECK-NEXT: values : ( 1, 5, 9, 13, 17, 21, 2, 6, 10, 14, 18, 22, 3, 7, 11, 15, 19, 23, 4, 8, 12, 16, 20, 24 + // CHECK-NEXT: ---- // - %v1 = sparse_tensor.values %1 : tensor<2x3x4xf64, #Tensor1> to memref<?xf64> - %v2 = sparse_tensor.values %2 : tensor<2x3x4xf64, #Tensor2> to memref<?xf64> - %v3 = sparse_tensor.values %3 : tensor<2x3x4xf64, #Tensor3> to memref<?xf64> - %av = sparse_tensor.values %a : tensor<2x3x4xf64, #Tensor1> to memref<?xf64> - %bv = sparse_tensor.values %b : tensor<2x3x4xf64, #Tensor1> to memref<?xf64> - %cv = sparse_tensor.values %c : tensor<2x3x4xf64, #Tensor1> to memref<?xf64> - %dv = sparse_tensor.values %d : tensor<2x3x4xf64, #Tensor2> to memref<?xf64> - %ev = sparse_tensor.values %e : tensor<2x3x4xf64, #Tensor2> to memref<?xf64> - %fv = sparse_tensor.values %f : tensor<2x3x4xf64, #Tensor2> to memref<?xf64> - %gv = sparse_tensor.values %g : tensor<2x3x4xf64, #Tensor3> to memref<?xf64> - %hv = sparse_tensor.values %h : tensor<2x3x4xf64, #Tensor3> to memref<?xf64> - %iv = sparse_tensor.values %i : tensor<2x3x4xf64, #Tensor3> to memref<?xf64> - - call @dumpf64(%v1) : (memref<?xf64>) -> () - call @dumpf64(%v2) : (memref<?xf64>) -> () - call @dumpf64(%v3) : (memref<?xf64>) -> () - call @dumpf64(%av) : (memref<?xf64>) -> () - call @dumpf64(%bv) : (memref<?xf64>) -> () - call @dumpf64(%cv) : (memref<?xf64>) -> () - call @dumpf64(%dv) : (memref<?xf64>) -> () - call @dumpf64(%ev) : (memref<?xf64>) -> () - call @dumpf64(%fv) : (memref<?xf64>) -> () - call @dumpf64(%gv) : (memref<?xf64>) -> () - call @dumpf64(%hv) : (memref<?xf64>) -> () - call @dumpf64(%iv) : (memref<?xf64>) -> () - + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 2, 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 2 + // CHECK-NEXT: crd[0] : ( 0, 1 + // CHECK-NEXT: pos[1] : ( 0, 3, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 0, 1, 2 + // CHECK-NEXT: pos[2] : ( 0, 4, 8, 12, 16, 20, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 + // CHECK-NEXT: ---- // - // Check coordinates. + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 2, 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 2 + // CHECK-NEXT: crd[0] : ( 0, 1 + // CHECK-NEXT: pos[1] : ( 0, 3, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 0, 1, 2 + // CHECK-NEXT: pos[2] : ( 0, 4, 8, 12, 16, 20, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 + // CHECK-NEXT: ---- // - // CHECK-NEXT: ( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) - // CHECK-NEXT: ( 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0 ) + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 2, 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 2 + // CHECK-NEXT: crd[0] : ( 0, 1 + // CHECK-NEXT: pos[1] : ( 0, 3, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 0, 1, 2 + // CHECK-NEXT: pos[2] : ( 0, 4, 8, 12, 16, 20, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 + // CHECK-NEXT: ---- // - %v10 = sparse_tensor.coordinates %1 { level = 0 : index } : tensor<2x3x4xf64, #Tensor1> to memref<?xindex> - %v11 = sparse_tensor.coordinates %1 { level = 1 : index } : tensor<2x3x4xf64, #Tensor1> to memref<?xindex> - %v12 = sparse_tensor.coordinates %1 { level = 2 : index } : tensor<2x3x4xf64, #Tensor1> to memref<?xindex> - %v20 = sparse_tensor.coordinates %2 { level = 0 : index } : tensor<2x3x4xf64, #Tensor2> to memref<?xindex> - %v21 = sparse_tensor.coordinates %2 { level = 1 : index } : tensor<2x3x4xf64, #Tensor2> to memref<?xindex> - %v22 = sparse_tensor.coordinates %2 { level = 2 : index } : tensor<2x3x4xf64, #Tensor2> to memref<?xindex> - %v30 = sparse_tensor.coordinates %3 { level = 0 : index } : tensor<2x3x4xf64, #Tensor3> to memref<?xindex> - %v31 = sparse_tensor.coordinates %3 { level = 1 : index } : tensor<2x3x4xf64, #Tensor3> to memref<?xindex> - %v32 = sparse_tensor.coordinates %3 { level = 2 : index } : tensor<2x3x4xf64, #Tensor3> to memref<?xindex> - - %a10 = sparse_tensor.coordinates %a { level = 0 : index } : tensor<2x3x4xf64, #Tensor1> to memref<?xindex> - %a11 = sparse_tensor.coordinates %a { level = 1 : index } : tensor<2x3x4xf64, #Tensor1> to memref<?xindex> - %a12 = sparse_tensor.coordinates %a { level = 2 : index } : tensor<2x3x4xf64, #Tensor1> to memref<?xindex> - %b10 = sparse_tensor.coordinates %b { level = 0 : index } : tensor<2x3x4xf64, #Tensor1> to memref<?xindex> - %b11 = sparse_tensor.coordinates %b { level = 1 : index } : tensor<2x3x4xf64, #Tensor1> to memref<?xindex> - %b12 = sparse_tensor.coordinates %b { level = 2 : index } : tensor<2x3x4xf64, #Tensor1> to memref<?xindex> - %c10 = sparse_tensor.coordinates %c { level = 0 : index } : tensor<2x3x4xf64, #Tensor1> to memref<?xindex> - %c11 = sparse_tensor.coordinates %c { level = 1 : index } : tensor<2x3x4xf64, #Tensor1> to memref<?xindex> - %c12 = sparse_tensor.coordinates %c { level = 2 : index } : tensor<2x3x4xf64, #Tensor1> to memref<?xindex> - - %d20 = sparse_tensor.coordinates %d { level = 0 : index } : tensor<2x3x4xf64, #Tensor2> to memref<?xindex> - %d21 = sparse_tensor.coordinates %d { level = 1 : index } : tensor<2x3x4xf64, #Tensor2> to memref<?xindex> - %d22 = sparse_tensor.coordinates %d { level = 2 : index } : tensor<2x3x4xf64, #Tensor2> to memref<?xindex> - %e20 = sparse_tensor.coordinates %e { level = 0 : index } : tensor<2x3x4xf64, #Tensor2> to memref<?xindex> - %e21 = sparse_tensor.coordinates %e { level = 1 : index } : tensor<2x3x4xf64, #Tensor2> to memref<?xindex> - %e22 = sparse_tensor.coordinates %e { level = 2 : index } : tensor<2x3x4xf64, #Tensor2> to memref<?xindex> - %f20 = sparse_tensor.coordinates %f { level = 0 : index } : tensor<2x3x4xf64, #Tensor2> to memref<?xindex> - %f21 = sparse_tensor.coordinates %f { level = 1 : index } : tensor<2x3x4xf64, #Tensor2> to memref<?xindex> - %f22 = sparse_tensor.coordinates %f { level = 2 : index } : tensor<2x3x4xf64, #Tensor2> to memref<?xindex> - - %g30 = sparse_tensor.coordinates %g { level = 0 : index } : tensor<2x3x4xf64, #Tensor3> to memref<?xindex> - %g31 = sparse_tensor.coordinates %g { level = 1 : index } : tensor<2x3x4xf64, #Tensor3> to memref<?xindex> - %g32 = sparse_tensor.coordinates %g { level = 2 : index } : tensor<2x3x4xf64, #Tensor3> to memref<?xindex> - %h30 = sparse_tensor.coordinates %h { level = 0 : index } : tensor<2x3x4xf64, #Tensor3> to memref<?xindex> - %h31 = sparse_tensor.coordinates %h { level = 1 : index } : tensor<2x3x4xf64, #Tensor3> to memref<?xindex> - %h32 = sparse_tensor.coordinates %h { level = 2 : index } : tensor<2x3x4xf64, #Tensor3> to memref<?xindex> - %i30 = sparse_tensor.coordinates %i { level = 0 : index } : tensor<2x3x4xf64, #Tensor3> to memref<?xindex> - %i31 = sparse_tensor.coordinates %i { level = 1 : index } : tensor<2x3x4xf64, #Tensor3> to memref<?xindex> - %i32 = sparse_tensor.coordinates %i { level = 2 : index } : tensor<2x3x4xf64, #Tensor3> to memref<?xindex> - - call @dumpidx(%v10) : (memref<?xindex>) -> () - call @dumpidx(%v11) : (memref<?xindex>) -> () - call @dumpidx(%v12) : (memref<?xindex>) -> () - call @dumpidx(%v20) : (memref<?xindex>) -> () - call @dumpidx(%v21) : (memref<?xindex>) -> () - call @dumpidx(%v22) : (memref<?xindex>) -> () - call @dumpidx(%v30) : (memref<?xindex>) -> () - call @dumpidx(%v31) : (memref<?xindex>) -> () - call @dumpidx(%v32) : (memref<?xindex>) -> () - - call @dumpidx(%a10) : (memref<?xindex>) -> () - call @dumpidx(%a11) : (memref<?xindex>) -> () - call @dumpidx(%a12) : (memref<?xindex>) -> () - call @dumpidx(%b10) : (memref<?xindex>) -> () - call @dumpidx(%b11) : (memref<?xindex>) -> () - call @dumpidx(%b12) : (memref<?xindex>) -> () - call @dumpidx(%c10) : (memref<?xindex>) -> () - call @dumpidx(%c11) : (memref<?xindex>) -> () - call @dumpidx(%c12) : (memref<?xindex>) -> () - - call @dumpidx(%d20) : (memref<?xindex>) -> () - call @dumpidx(%d21) : (memref<?xindex>) -> () - call @dumpidx(%d22) : (memref<?xindex>) -> () - call @dumpidx(%e20) : (memref<?xindex>) -> () - call @dumpidx(%e21) : (memref<?xindex>) -> () - call @dumpidx(%e22) : (memref<?xindex>) -> () - call @dumpidx(%f20) : (memref<?xindex>) -> () - call @dumpidx(%f21) : (memref<?xindex>) -> () - call @dumpidx(%f22) : (memref<?xindex>) -> () - - call @dumpidx(%g30) : (memref<?xindex>) -> () - call @dumpidx(%g31) : (memref<?xindex>) -> () - call @dumpidx(%g32) : (memref<?xindex>) -> () - call @dumpidx(%h30) : (memref<?xindex>) -> () - call @dumpidx(%h31) : (memref<?xindex>) -> () - call @dumpidx(%h32) : (memref<?xindex>) -> () - call @dumpidx(%i30) : (memref<?xindex>) -> () - call @dumpidx(%i31) : (memref<?xindex>) -> () - call @dumpidx(%i32) : (memref<?xindex>) -> () + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4, 2 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 4, 8, 12 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: pos[2] : ( 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9, 21, 10, 22, 11, 23, 12, 24 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4, 2 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 4, 8, 12 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: pos[2] : ( 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9, 21, 10, 22, 11, 23, 12, 24 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4, 2 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 4, 8, 12 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: pos[2] : ( 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1, 13, 2, 14, 3, 15, 4, 16, 5, 17, 6, 18, 7, 19, 8, 20, 9, 21, 10, 22, 11, 23, 12, 24 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 4, 2, 3 ) + // CHECK-NEXT: pos[0] : ( 0, 4 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6, 8 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: pos[2] : ( 0, 3, 6, 9, 12, 15, 18, 21, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2 + // CHECK-NEXT: values : ( 1, 5, 9, 13, 17, 21, 2, 6, 10, 14, 18, 22, 3, 7, 11, 15, 19, 23, 4, 8, 12, 16, 20, 24 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 4, 2, 3 ) + // CHECK-NEXT: pos[0] : ( 0, 4 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6, 8 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: pos[2] : ( 0, 3, 6, 9, 12, 15, 18, 21, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2 + // CHECK-NEXT: values : ( 1, 5, 9, 13, 17, 21, 2, 6, 10, 14, 18, 22, 3, 7, 11, 15, 19, 23, 4, 8, 12, 16, 20, 24 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 24 + // CHECK-NEXT: dim = ( 2, 3, 4 ) + // CHECK-NEXT: lvl = ( 4, 2, 3 ) + // CHECK-NEXT: pos[0] : ( 0, 4 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6, 8 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: pos[2] : ( 0, 3, 6, 9, 12, 15, 18, 21, 24 + // CHECK-NEXT: crd[2] : ( 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2 + // CHECK-NEXT: values : ( 1, 5, 9, 13, 17, 21, 2, 6, 10, 14, 18, 22, 3, 7, 11, 15, 19, 23, 4, 8, 12, 16, 20, 24 + // CHECK-NEXT: ---- + // + sparse_tensor.print %1 : tensor<2x3x4xf64, #Tensor1> + sparse_tensor.print %2 : tensor<2x3x4xf64, #Tensor2> + sparse_tensor.print %3 : tensor<2x3x4xf64, #Tensor3> + sparse_tensor.print %a : tensor<2x3x4xf64, #Tensor1> + sparse_tensor.print %b : tensor<2x3x4xf64, #Tensor1> + sparse_tensor.print %c : tensor<2x3x4xf64, #Tensor1> + sparse_tensor.print %d : tensor<2x3x4xf64, #Tensor2> + sparse_tensor.print %e : tensor<2x3x4xf64, #Tensor2> + sparse_tensor.print %f : tensor<2x3x4xf64, #Tensor2> + sparse_tensor.print %g : tensor<2x3x4xf64, #Tensor3> + sparse_tensor.print %h : tensor<2x3x4xf64, #Tensor3> + sparse_tensor.print %i : tensor<2x3x4xf64, #Tensor3> // Release the resources. bufferization.dealloc_tensor %1 : tensor<2x3x4xf64, #Tensor1> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_block.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_block.mlir index 809414ba977d2b364b8a6ee466b206eac754922a..ff22283f43a793b08a9fbbcc12e91e13a694a44a 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_block.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_block.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -52,21 +52,10 @@ // Integration test that tests conversions between sparse tensors. // module { - // - // Output utilities. - // - func.func @dumpf64(%arg0: memref<?xf64>) { - %c0 = arith.constant 0 : index - %d0 = arith.constant -1.0 : f64 - %0 = vector.transfer_read %arg0[%c0], %d0: memref<?xf64>, vector<8xf64> - vector.print %0 : vector<8xf64> - return - } - // // Main driver. // - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c2 = arith.constant 2 : index @@ -88,20 +77,47 @@ module { %3 = sparse_tensor.convert %1 : tensor<2x4xf64, #BSR> to tensor<2x4xf64, #CSR> %4 = sparse_tensor.convert %1 : tensor<2x4xf64, #BSR> to tensor<2x4xf64, #CSC> - %v1 = sparse_tensor.values %1 : tensor<2x4xf64, #BSR> to memref<?xf64> - %v2 = sparse_tensor.values %2 : tensor<2x4xf64, #BSR> to memref<?xf64> - %v3 = sparse_tensor.values %3 : tensor<2x4xf64, #CSR> to memref<?xf64> - %v4 = sparse_tensor.values %4 : tensor<2x4xf64, #CSC> to memref<?xf64> - - - // CHECK: ( 1, 2, 5, 6, 3, 4, 7, 8 ) - // CHECK-NEXT: ( 1, 2, 5, 6, 3, 4, 7, 8 ) - // CHECK-NEXT: ( 1, 2, 3, 4, 5, 6, 7, 8 ) - // CHECK-NEXT: ( 1, 5, 2, 6, 3, 7, 4, 8 ) - call @dumpf64(%v1) : (memref<?xf64>) -> () - call @dumpf64(%v2) : (memref<?xf64>) -> () - call @dumpf64(%v3) : (memref<?xf64>) -> () - call @dumpf64(%v4) : (memref<?xf64>) -> () + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 8 + // CHECK-NEXT: dim = ( 2, 4 ) + // CHECK-NEXT: lvl = ( 1, 2, 2, 2 ) + // CHECK-NEXT: pos[1] : ( 0, 2 + // CHECK-NEXT: crd[1] : ( 0, 1 + // CHECK-NEXT: values : ( 1, 2, 5, 6, 3, 4, 7, 8 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 8 + // CHECK-NEXT: dim = ( 2, 4 ) + // CHECK-NEXT: lvl = ( 1, 2, 2, 2 ) + // CHECK-NEXT: pos[1] : ( 0, 2 + // CHECK-NEXT: crd[1] : ( 0, 1 + // CHECK-NEXT: values : ( 1, 2, 5, 6, 3, 4, 7, 8 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 8 + // CHECK-NEXT: dim = ( 2, 4 ) + // CHECK-NEXT: lvl = ( 2, 4 ) + // CHECK-NEXT: pos[1] : ( 0, 4, 8 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7, 8 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 8 + // CHECK-NEXT: dim = ( 2, 4 ) + // CHECK-NEXT: lvl = ( 4, 2 ) + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6, 8 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1, 5, 2, 6, 3, 7, 4, 8 + // CHECK-NEXT: ---- + // + sparse_tensor.print %1 : tensor<2x4xf64, #BSR> + sparse_tensor.print %2 : tensor<2x4xf64, #BSR> + sparse_tensor.print %3 : tensor<2x4xf64, #CSR> + sparse_tensor.print %4 : tensor<2x4xf64, #CSC> // TODO: Fix memory leaks. bufferization.dealloc_tensor %1 : tensor<2x4xf64, #BSR> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_dyn.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_dyn.mlir index f658457fa67356dfe5e708e9a99666f3577d68d2..11baf65e635091760b11e6bcd58d8e5626ba2d82 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_dyn.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_dyn.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -44,19 +44,7 @@ // may change (the actual underlying sizes obviously never change). // module { - - func.func private @printMemref1dF64(%ptr : memref<?xf64>) attributes { llvm.emit_c_interface } - - // - // Helper method to print values array. The transfer actually - // reads more than required to verify size of buffer as well. - // - func.func @dump(%arg0: memref<?xf64>) { - call @printMemref1dF64(%arg0) : (memref<?xf64>) -> () - return - } - - func.func @entry() { + func.func @main() { %t1 = arith.constant sparse< [ [0,0], [0,1], [0,63], [1,0], [1,1], [31,0], [31,63] ], [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 ]> : tensor<32x64xf64> @@ -72,45 +60,81 @@ module { %5 = sparse_tensor.convert %3 : tensor<?x?xf64, #DCSR> to tensor<?x?xf64, #DCSC> %6 = sparse_tensor.convert %4 : tensor<?x?xf64, #DCSC> to tensor<?x?xf64, #DCSR> -// - // Check number_of_entries. // - // CHECK-COUNT-6: 7 - %n1 = sparse_tensor.number_of_entries %1 : tensor<?x?xf64, #DCSR> - %n2 = sparse_tensor.number_of_entries %2 : tensor<?x?xf64, #DCSC> - %n3 = sparse_tensor.number_of_entries %3 : tensor<?x?xf64, #DCSR> - %n4 = sparse_tensor.number_of_entries %4 : tensor<?x?xf64, #DCSC> - %n5 = sparse_tensor.number_of_entries %5 : tensor<?x?xf64, #DCSC> - %n6 = sparse_tensor.number_of_entries %6 : tensor<?x?xf64, #DCSR> - vector.print %n1 : index - vector.print %n2 : index - vector.print %n3 : index - vector.print %n4 : index - vector.print %n5 : index - vector.print %n6 : index - + // Verify the outputs. + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 32, 64 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 31 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 63, 0, 1, 0, 63 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 64, 32 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 63 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 31, 0, 1, 0, 31 + // CHECK-NEXT: values : ( 1, 4, 6, 2, 5, 3, 7 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 32, 64 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 31 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 63, 0, 1, 0, 63 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 64, 32 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 63 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 31, 0, 1, 0, 31 + // CHECK-NEXT: values : ( 1, 4, 6, 2, 5, 3, 7 + // CHECK-NEXT: ---- // - // All proper row-/column-wise? + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 64, 32 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 63 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 31, 0, 1, 0, 31 + // CHECK-NEXT: values : ( 1, 4, 6, 2, 5, 3, 7 + // CHECK-NEXT: ---- // - // CHECK: [1, 2, 3, 4, 5, 6, 7 - // CHECK: [1, 4, 6, 2, 5, 3, 7 - // CHECK: [1, 2, 3, 4, 5, 6, 7 - // CHECK: [1, 4, 6, 2, 5, 3, 7 - // CHECK: [1, 4, 6, 2, 5, 3, 7 - // CHECK: [1, 2, 3, 4, 5, 6, 7 + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 32, 64 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 31 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 63, 0, 1, 0, 63 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: ---- // - %m1 = sparse_tensor.values %1 : tensor<?x?xf64, #DCSR> to memref<?xf64> - %m2 = sparse_tensor.values %2 : tensor<?x?xf64, #DCSC> to memref<?xf64> - %m3 = sparse_tensor.values %3 : tensor<?x?xf64, #DCSR> to memref<?xf64> - %m4 = sparse_tensor.values %4 : tensor<?x?xf64, #DCSC> to memref<?xf64> - %m5 = sparse_tensor.values %5 : tensor<?x?xf64, #DCSC> to memref<?xf64> - %m6 = sparse_tensor.values %6 : tensor<?x?xf64, #DCSR> to memref<?xf64> - call @dump(%m1) : (memref<?xf64>) -> () - call @dump(%m2) : (memref<?xf64>) -> () - call @dump(%m3) : (memref<?xf64>) -> () - call @dump(%m4) : (memref<?xf64>) -> () - call @dump(%m5) : (memref<?xf64>) -> () - call @dump(%m6) : (memref<?xf64>) -> () + sparse_tensor.print %1 : tensor<?x?xf64, #DCSR> + sparse_tensor.print %2 : tensor<?x?xf64, #DCSC> + sparse_tensor.print %3 : tensor<?x?xf64, #DCSR> + sparse_tensor.print %4 : tensor<?x?xf64, #DCSC> + sparse_tensor.print %5 : tensor<?x?xf64, #DCSC> + sparse_tensor.print %6 : tensor<?x?xf64, #DCSR> // Release the resources. bufferization.dealloc_tensor %1 : tensor<?x?xf64, #DCSR> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_element.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_element.mlir index 81f68366be28c6625195870cc1a8c9589a2e5e9c..a2ec6df392aaa397c8261604a853b62170a20905 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_element.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_element.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -55,7 +55,7 @@ module { // // The first test suite (for non-singleton LevelTypes). // - func.func @entry() { + func.func @main() { // // Initialize a 3-dim dense tensor. // diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_ptr.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_ptr.mlir index 3ebe3be757d2d0f5dc636ca68559cf5644f405cb..6005aa6cfeaed6b33db260b5a45619c72b812915 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_ptr.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_ptr.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -54,41 +54,7 @@ // in addition to layout. // module { - - // - // Helper method to print values and indices arrays. The transfer actually - // reads more than required to verify size of buffer as well. - // - func.func @dumpf64(%arg0: memref<?xf64>) { - %c = arith.constant 0 : index - %d = arith.constant 0.0 : f64 - %0 = vector.transfer_read %arg0[%c], %d: memref<?xf64>, vector<8xf64> - vector.print %0 : vector<8xf64> - return - } - func.func @dumpi08(%arg0: memref<?xi8>) { - %c = arith.constant 0 : index - %d = arith.constant 0 : i8 - %0 = vector.transfer_read %arg0[%c], %d: memref<?xi8>, vector<8xi8> - vector.print %0 : vector<8xi8> - return - } - func.func @dumpi32(%arg0: memref<?xi32>) { - %c = arith.constant 0 : index - %d = arith.constant 0 : i32 - %0 = vector.transfer_read %arg0[%c], %d: memref<?xi32>, vector<8xi32> - vector.print %0 : vector<8xi32> - return - } - func.func @dumpi64(%arg0: memref<?xi64>) { - %c = arith.constant 0 : index - %d = arith.constant 0 : i64 - %0 = vector.transfer_read %arg0[%c], %d: memref<?xi64>, vector<8xi64> - vector.print %0 : vector<8xi64> - return - } - - func.func @entry() { + func.func @main() { %c1 = arith.constant 1 : index %t1 = arith.constant sparse< [ [0,0], [0,1], [0,63], [1,0], [1,1], [31,0], [31,63] ], @@ -106,50 +72,78 @@ module { %6 = sparse_tensor.convert %3 : tensor<32x64xf64, #CSC> to tensor<32x64xf64, #DCSR> // - // All proper row-/column-wise? + // Verify the outputs. // - // CHECK: ( 1, 2, 3, 4, 5, 6, 7, 0 ) - // CHECK-NEXT: ( 1, 4, 6, 2, 5, 3, 7, 0 ) - // CHECK-NEXT: ( 1, 4, 6, 2, 5, 3, 7, 0 ) - // CHECK-NEXT: ( 1, 4, 6, 2, 5, 3, 7, 0 ) - // CHECK-NEXT: ( 1, 2, 3, 4, 5, 6, 7, 0 ) - // CHECK-NEXT: ( 1, 2, 3, 4, 5, 6, 7, 0 ) + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 32, 64 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 31 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 63, 0, 1, 0, 63 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: ---- // - %m1 = sparse_tensor.values %1 : tensor<32x64xf64, #DCSR> to memref<?xf64> - %m2 = sparse_tensor.values %2 : tensor<32x64xf64, #DCSC> to memref<?xf64> - %m3 = sparse_tensor.values %3 : tensor<32x64xf64, #CSC> to memref<?xf64> - %m4 = sparse_tensor.values %4 : tensor<32x64xf64, #DCSC> to memref<?xf64> - %m5 = sparse_tensor.values %5 : tensor<32x64xf64, #DCSR> to memref<?xf64> - %m6 = sparse_tensor.values %6 : tensor<32x64xf64, #DCSR> to memref<?xf64> - call @dumpf64(%m1) : (memref<?xf64>) -> () - call @dumpf64(%m2) : (memref<?xf64>) -> () - call @dumpf64(%m3) : (memref<?xf64>) -> () - call @dumpf64(%m4) : (memref<?xf64>) -> () - call @dumpf64(%m5) : (memref<?xf64>) -> () - call @dumpf64(%m6) : (memref<?xf64>) -> () - + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 64, 32 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 63 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 31, 0, 1, 0, 31 + // CHECK-NEXT: values : ( 1, 4, 6, 2, 5, 3, 7 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 64, 32 ) + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 31, 0, 1, 0, 31 + // CHECK-NEXT: values : ( 1, 4, 6, 2, 5, 3, 7 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 64, 32 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 63 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 31, 0, 1, 0, 31 + // CHECK-NEXT: values : ( 1, 4, 6, 2, 5, 3, 7 + // CHECK-NEXT: ---- // - // Sanity check on indices. + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 32, 64 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 31 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 63, 0, 1, 0, 63 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: ---- // - // CHECK-NEXT: ( 0, 1, 63, 0, 1, 0, 63, 0 ) - // CHECK-NEXT: ( 0, 1, 31, 0, 1, 0, 31, 0 ) - // CHECK-NEXT: ( 0, 1, 31, 0, 1, 0, 31, 0 ) - // CHECK-NEXT: ( 0, 1, 31, 0, 1, 0, 31, 0 ) - // CHECK-NEXT: ( 0, 1, 63, 0, 1, 0, 63, 0 ) - // CHECK-NEXT: ( 0, 1, 63, 0, 1, 0, 63, 0 ) + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 7 + // CHECK-NEXT: dim = ( 32, 64 ) + // CHECK-NEXT: lvl = ( 32, 64 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 31 + // CHECK-NEXT: pos[1] : ( 0, 3, 5, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 63, 0, 1, 0, 63 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: ---- // - %i1 = sparse_tensor.coordinates %1 { level = 1 : index } : tensor<32x64xf64, #DCSR> to memref<?xi8> - %i2 = sparse_tensor.coordinates %2 { level = 1 : index } : tensor<32x64xf64, #DCSC> to memref<?xi64> - %i3 = sparse_tensor.coordinates %3 { level = 1 : index } : tensor<32x64xf64, #CSC> to memref<?xi32> - %i4 = sparse_tensor.coordinates %4 { level = 1 : index } : tensor<32x64xf64, #DCSC> to memref<?xi64> - %i5 = sparse_tensor.coordinates %5 { level = 1 : index } : tensor<32x64xf64, #DCSR> to memref<?xi8> - %i6 = sparse_tensor.coordinates %6 { level = 1 : index } : tensor<32x64xf64, #DCSR> to memref<?xi8> - call @dumpi08(%i1) : (memref<?xi8>) -> () - call @dumpi64(%i2) : (memref<?xi64>) -> () - call @dumpi32(%i3) : (memref<?xi32>) -> () - call @dumpi64(%i4) : (memref<?xi64>) -> () - call @dumpi08(%i5) : (memref<?xi08>) -> () - call @dumpi08(%i6) : (memref<?xi08>) -> () + sparse_tensor.print %1 : tensor<32x64xf64, #DCSR> + sparse_tensor.print %2 : tensor<32x64xf64, #DCSC> + sparse_tensor.print %3 : tensor<32x64xf64, #CSC> + sparse_tensor.print %4 : tensor<32x64xf64, #DCSC> + sparse_tensor.print %5 : tensor<32x64xf64, #DCSR> + sparse_tensor.print %6 : tensor<32x64xf64, #DCSR> // Release the resources. bufferization.dealloc_tensor %1 : tensor<32x64xf64, #DCSR> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_sparse2dense.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_sparse2dense.mlir index 1655d6a03a6202a1010f0e2346d506928e8431ee..e145c4542a7bfc2b989841c80ce1906a35509fb6 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_sparse2dense.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_sparse2dense.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -107,7 +107,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { // // Initialize a 3-dim dense tensor. // @@ -233,6 +233,19 @@ module { // bufferization.dealloc_tensor %s2pp4 : tensor<2x?x?xf64, #Tensor4> // bufferization.dealloc_tensor %s2pp5 : tensor<2x?x?xf64, #Tensor5> // bufferization.dealloc_tensor %s2pp6 : tensor<2x?x?xf64, #Tensor6> + + bufferization.dealloc_tensor %d2341 : tensor<2x3x4xf64> + bufferization.dealloc_tensor %d2342 : tensor<2x3x4xf64> + bufferization.dealloc_tensor %d2343 : tensor<2x3x4xf64> + bufferization.dealloc_tensor %d2344 : tensor<2x3x4xf64> + bufferization.dealloc_tensor %d2345 : tensor<2x3x4xf64> + bufferization.dealloc_tensor %d2346 : tensor<2x3x4xf64> + bufferization.dealloc_tensor %dp344 : tensor<?x3x4xf64> + bufferization.dealloc_tensor %d2p45 : tensor<2x?x4xf64> + bufferization.dealloc_tensor %d23p6 : tensor<2x3x?xf64> + bufferization.dealloc_tensor %dp3p4 : tensor<?x3x?xf64> + bufferization.dealloc_tensor %dpp45 : tensor<?x?x4xf64> + return } } diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_sparse2sparse.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_sparse2sparse.mlir index 2ace317554a070e12f505854f4c475ac966db65e..12f8e34500d818ab25585c3c3ded6a8d9b184feb 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_sparse2sparse.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_conversion_sparse2sparse.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -114,12 +114,14 @@ module { call @dump(%d31) : (tensor<2x3x4xf64>) -> () // - // Release sparse tensors. + // Release the resources. // bufferization.dealloc_tensor %t13 : tensor<2x3x4xf64, #Tensor3> bufferization.dealloc_tensor %t31 : tensor<2x3x4xf64, #Tensor1> bufferization.dealloc_tensor %s1 : tensor<2x3x4xf64, #Tensor1> bufferization.dealloc_tensor %s3 : tensor<2x3x4xf64, #Tensor3> + bufferization.dealloc_tensor %d13 : tensor<2x3x4xf64> + bufferization.dealloc_tensor %d31 : tensor<2x3x4xf64> return } @@ -167,12 +169,14 @@ module { call @dump(%d31) : (tensor<2x3x4xf64>) -> () // - // Release sparse tensors. + // Release the resources. // bufferization.dealloc_tensor %t13 : tensor<2x3x4xf64, #SingletonTensor3> bufferization.dealloc_tensor %t31 : tensor<2x3x4xf64, #SingletonTensor1> bufferization.dealloc_tensor %s1 : tensor<2x3x4xf64, #SingletonTensor1> bufferization.dealloc_tensor %s3 : tensor<2x3x4xf64, #SingletonTensor3> + bufferization.dealloc_tensor %d13 : tensor<2x3x4xf64> + bufferization.dealloc_tensor %d31 : tensor<2x3x4xf64> return } @@ -180,7 +184,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { call @testNonSingleton() : () -> () call @testSingleton() : () -> () return diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_coo_test.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_coo_test.mlir index 16252c1005ebbb3ce1af429e04ac62871ace10b4..16813e0aa707b8c97bc369aae2c14a9860badcaf 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_coo_test.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_coo_test.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -93,17 +93,17 @@ module { func.func @add_coo_coo_out_coo(%arga: tensor<8x8xf32, #SortedCOO>, %argb: tensor<8x8xf32, #SortedCOOSoA>) - -> tensor<8x8xf32, #SortedCOO> { - %init = tensor.empty() : tensor<8x8xf32, #SortedCOO> + -> tensor<8x8xf32, #SortedCOOSoA> { + %init = tensor.empty() : tensor<8x8xf32, #SortedCOOSoA> %0 = linalg.generic #trait ins(%arga, %argb: tensor<8x8xf32, #SortedCOO>, tensor<8x8xf32, #SortedCOOSoA>) - outs(%init: tensor<8x8xf32, #SortedCOO>) { + outs(%init: tensor<8x8xf32, #SortedCOOSoA>) { ^bb(%a: f32, %b: f32, %x: f32): %0 = arith.addf %a, %b : f32 linalg.yield %0 : f32 - } -> tensor<8x8xf32, #SortedCOO> - return %0 : tensor<8x8xf32, #SortedCOO> + } -> tensor<8x8xf32, #SortedCOOSoA> + return %0 : tensor<8x8xf32, #SortedCOOSoA> } @@ -126,7 +126,7 @@ module { return %0 : tensor<8x8xf32> } - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c8 = arith.constant 8 : index @@ -171,8 +171,9 @@ module { -> tensor<8x8xf32> %COO_RET = call @add_coo_coo_out_coo(%COO_A, %COO_B) : (tensor<8x8xf32, #SortedCOO>, tensor<8x8xf32, #SortedCOOSoA>) - -> tensor<8x8xf32, #SortedCOO> - %C4 = sparse_tensor.convert %COO_RET : tensor<8x8xf32, #SortedCOO> to tensor<8x8xf32> + -> tensor<8x8xf32, #SortedCOOSoA> + %C4 = sparse_tensor.convert %COO_RET : tensor<8x8xf32, #SortedCOOSoA> to tensor<8x8xf32> + // // Verify computed matrix C. // @@ -201,6 +202,32 @@ module { vector.print %v4 : vector<8xf32> } + // + // Ensure that COO-SoA output has the same values. + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 64 + // CHECK-NEXT: dim = ( 8, 8 ) + // CHECK-NEXT: lvl = ( 8, 8 ) + // CHECK-NEXT: pos[0] : ( 0, 64 + // CHECK-NEXT: crd[0] : ( 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + // CHECK-SAME: 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + // CHECK-SAME: 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, + // CHECK-SAME: 7, 7, 7, 7 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, + // CHECK-SAME: 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, + // CHECK-SAME: 4, 5, 6, 7 + // CHECK-NEXT: values : ( 8.8, 4.8, 6.8, 4.8, 8.8, 6.1, 14.8, 16.8, 4.4, 4.4, 4.4, 8.4, + // CHECK-SAME: 8.4, 12.4, 16.4, 16.4, 8.8, 4.8, 6.8, 8.8, 8.8, 12.8, 14.8, + // CHECK-SAME: 15.8, 4.3, 5.3, 6.3, 8.3, 8.3, 12.3, 14.3, 16.3, 4.5, 4.5, + // CHECK-SAME: 6.5, 8.5, 8.5, 12.5, 14.5, 16.5, 9.9, 4.9, 6.9, 8.9, 8.9, + // CHECK-SAME: 12.9, 15.9, 16.9, 12.1, 6.1, 5.1, 9.1, 9.1, 13.1, 15.1, 17.1, + // CHECK-SAME: 15.4, 5.4, 7.4, 5.4, 11.4, 10.4, 11.4, 9.4 + // CHECK-NEXT: ---- + // + sparse_tensor.print %COO_RET : tensor<8x8xf32, #SortedCOOSoA> + // Release resources. bufferization.dealloc_tensor %C1 : tensor<8x8xf32> bufferization.dealloc_tensor %C2 : tensor<8x8xf32> @@ -209,7 +236,7 @@ module { bufferization.dealloc_tensor %CSR_A : tensor<8x8xf32, #CSR> bufferization.dealloc_tensor %COO_A : tensor<8x8xf32, #SortedCOO> bufferization.dealloc_tensor %COO_B : tensor<8x8xf32, #SortedCOOSoA> - bufferization.dealloc_tensor %COO_RET : tensor<8x8xf32, #SortedCOO> + bufferization.dealloc_tensor %COO_RET : tensor<8x8xf32, #SortedCOOSoA> return diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_dilated_conv_2d_nhwc_hwcf.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_dilated_conv_2d_nhwc_hwcf.mlir index b4d40ae084015a1f6525d30cff4104e13f508af9..40738a9f7d7f1939ce694a734a2fd49136fd1a15 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_dilated_conv_2d_nhwc_hwcf.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_dilated_conv_2d_nhwc_hwcf.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -78,7 +78,7 @@ func.func @conv_2d_nhwc_hwcf_dual_CDCC(%arg0: tensor<?x?x?x?xf32, #CDCC>, %arg1: } -func.func @entry() { +func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c3 = arith.constant 3 : index diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_dot.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_dot.mlir index f7ba4daa245892ea7268a78e5affa48c379971bd..5451f2d957ad35f825c0f4e6b352bd16e141b25a 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_dot.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_dot.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -49,7 +49,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { // Setup two sparse vectors. %d1 = arith.constant sparse< [ [0], [1], [22], [23], [1022] ], [1.0, 2.0, 3.0, 4.0, 5.0] @@ -60,6 +60,30 @@ module { %s1 = sparse_tensor.convert %d1 : tensor<1024xf32> to tensor<1024xf32, #SparseVector> %s2 = sparse_tensor.convert %d2 : tensor<1024xf32> to tensor<1024xf32, #SparseVector> + // + // Verify the inputs. + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 5 + // CHECK-NEXT: dim = ( 1024 ) + // CHECK-NEXT: lvl = ( 1024 ) + // CHECK-NEXT: pos[0] : ( 0, 5 + // CHECK-NEXT: crd[0] : ( 0, 1, 22, 23, 1022 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 3 + // CHECK-NEXT: dim = ( 1024 ) + // CHECK-NEXT: lvl = ( 1024 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 22, 1022, 1023 + // CHECK-NEXT: values : ( 6, 7, 8 + // CHECK-NEXT: ---- + // + sparse_tensor.print %s1 : tensor<1024xf32, #SparseVector> + sparse_tensor.print %s2 : tensor<1024xf32, #SparseVector> + // Call the kernel and verify the output. // // CHECK: 53 @@ -73,16 +97,6 @@ module { %1 = tensor.extract %0[] : tensor<f32> vector.print %1 : f32 - // Print number of entries in the sparse vectors. - // - // CHECK: 5 - // CHECK: 3 - // - %noe1 = sparse_tensor.number_of_entries %s1 : tensor<1024xf32, #SparseVector> - %noe2 = sparse_tensor.number_of_entries %s2 : tensor<1024xf32, #SparseVector> - vector.print %noe1 : index - vector.print %noe2 : index - // Release the resources. bufferization.dealloc_tensor %0 : tensor<f32> bufferization.dealloc_tensor %s1 : tensor<1024xf32, #SparseVector> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_empty.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_empty.mlir new file mode 100755 index 0000000000000000000000000000000000000000..bcd71f7bd674bdf5ac108753be8df3d09afdabc0 --- /dev/null +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_empty.mlir @@ -0,0 +1,144 @@ +//-------------------------------------------------------------------------------------------------- +// WHEN CREATING A NEW TEST, PLEASE JUST COPY & PASTE WITHOUT EDITS. +// +// Set-up that's shared across all tests in this directory. In principle, this +// config could be moved to lit.local.cfg. However, there are downstream users that +// do not use these LIT config files. Hence why this is kept inline. +// +// DEFINE: %{sparsifier_opts} = enable-runtime-library=true +// DEFINE: %{sparsifier_opts_sve} = enable-arm-sve=true %{sparsifier_opts} +// DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" +// DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" +// DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils +// DEFINE: %{run_opts} = -e main -entry-point-result=void +// DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} +// DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} +// +// DEFINE: %{env} = +//-------------------------------------------------------------------------------------------------- + +// RUN: %{compile} | %{run} | FileCheck %s +// +// Do the same run, but now with direct IR generation. +// REDEFINE: %{sparsifier_opts} = enable-runtime-library=false enable-buffer-initialization=true +// RUN: %{compile} | %{run} | FileCheck %s +// +// Do the same run, but now with direct IR generation and vectorization. +// REDEFINE: %{sparsifier_opts} = enable-runtime-library=false enable-buffer-initialization=true vl=2 reassociate-fp-reductions=true enable-index-optimizations=true +// RUN: %{compile} | %{run} | FileCheck %s +// +// Do the same run, but now with direct IR generation and VLA vectorization. +// RUN: %if mlir_arm_sve_tests %{ %{compile_sve} | %{run_sve} | FileCheck %s %} + + +#map = affine_map<(d0) -> (d0)> + +#SV = #sparse_tensor.encoding<{ + map = (d0) -> (d0 : compressed) +}> + +module { + + // This directly yields an empty sparse vector. + func.func @empty() -> tensor<10xf32, #SV> { + %0 = tensor.empty() : tensor<10xf32, #SV> + return %0 : tensor<10xf32, #SV> + } + + // This also directly yields an empty sparse vector. + func.func @empty_alloc() -> tensor<10xf32, #SV> { + %0 = bufferization.alloc_tensor() : tensor<10xf32, #SV> + return %0 : tensor<10xf32, #SV> + } + + // This yields a hidden empty sparse vector (all zeros). + func.func @zeros() -> tensor<10xf32, #SV> { + %cst = arith.constant 0.0 : f32 + %0 = bufferization.alloc_tensor() : tensor<10xf32, #SV> + %1 = linalg.generic { + indexing_maps = [#map], + iterator_types = ["parallel"]} + outs(%0 : tensor<10xf32, #SV>) { + ^bb0(%out: f32): + linalg.yield %cst : f32 + } -> tensor<10xf32, #SV> + return %1 : tensor<10xf32, #SV> + } + + // This yields a filled sparse vector (all ones). + func.func @ones() -> tensor<10xf32, #SV> { + %cst = arith.constant 1.0 : f32 + %0 = bufferization.alloc_tensor() : tensor<10xf32, #SV> + %1 = linalg.generic { + indexing_maps = [#map], + iterator_types = ["parallel"]} + outs(%0 : tensor<10xf32, #SV>) { + ^bb0(%out: f32): + linalg.yield %cst : f32 + } -> tensor<10xf32, #SV> + return %1 : tensor<10xf32, #SV> + } + + // + // Main driver. + // + func.func @main() { + + %0 = call @empty() : () -> tensor<10xf32, #SV> + %1 = call @empty_alloc() : () -> tensor<10xf32, #SV> + %2 = call @zeros() : () -> tensor<10xf32, #SV> + %3 = call @ones() : () -> tensor<10xf32, #SV> + + // + // Verify the output. In particular, make sure that + // all empty sparse vector data structures are properly + // finalized with a pair (0,0) for positions. + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 0 + // CHECK-NEXT: dim = ( 10 ) + // CHECK-NEXT: lvl = ( 10 ) + // CHECK-NEXT: pos[0] : ( 0, 0, + // CHECK-NEXT: crd[0] : ( + // CHECK-NEXT: values : ( + // CHECK-NEXT: ---- + // + // CHECK-NEXT: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 0 + // CHECK-NEXT: dim = ( 10 ) + // CHECK-NEXT: lvl = ( 10 ) + // CHECK-NEXT: pos[0] : ( 0, 0, + // CHECK-NEXT: crd[0] : ( + // CHECK-NEXT: values : ( + // CHECK-NEXT: ---- + // + // CHECK-NEXT: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 0 + // CHECK-NEXT: dim = ( 10 ) + // CHECK-NEXT: lvl = ( 10 ) + // CHECK-NEXT: pos[0] : ( 0, 0, + // CHECK-NEXT: crd[0] : ( + // CHECK-NEXT: values : ( + // CHECK-NEXT: ---- + // + // CHECK-NEXT: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 10 + // CHECK-NEXT: dim = ( 10 ) + // CHECK-NEXT: lvl = ( 10 ) + // CHECK-NEXT: pos[0] : ( 0, 10, + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + // CHECK-NEXT: values : ( 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + // CHECK-NEXT: ---- + // + sparse_tensor.print %0 : tensor<10xf32, #SV> + sparse_tensor.print %1 : tensor<10xf32, #SV> + sparse_tensor.print %2 : tensor<10xf32, #SV> + sparse_tensor.print %3 : tensor<10xf32, #SV> + + bufferization.dealloc_tensor %0 : tensor<10xf32, #SV> + bufferization.dealloc_tensor %1 : tensor<10xf32, #SV> + bufferization.dealloc_tensor %2 : tensor<10xf32, #SV> + bufferization.dealloc_tensor %3 : tensor<10xf32, #SV> + return + } +} diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_expand.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_expand.mlir index 93a7ea51ec9c4dbeb3b680504567167eb2aefae0..451195b2185b7631e82ee7c97a9fb2a156bd358d 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_expand.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_expand.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -35,8 +35,6 @@ }> module { - func.func private @printMemrefF64(%ptr : tensor<*xf64>) - // // Column-wise storage forces the ijk loop to permute into jki // so that access pattern expansion (workspace) needs to be @@ -54,7 +52,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %d1 = arith.constant -1.0 : f64 @@ -83,24 +81,26 @@ module { : (tensor<8x2xf64, #CSC>, tensor<2x4xf64, #CSC>) -> tensor<8x4xf64, #CSC> - // CHECK: {{\[}}[32.53, 35.73, 38.93, 42.13], - // CHECK-NEXT: [34.56, 37.96, 41.36, 44.76], - // CHECK-NEXT: [36.59, 40.19, 43.79, 47.39], - // CHECK-NEXT: [38.62, 42.42, 46.22, 50.02], - // CHECK-NEXT: [40.65, 44.65, 48.65, 52.65], - // CHECK-NEXT: [42.68, 46.88, 51.08, 55.28], - // CHECK-NEXT: [44.71, 49.11, 53.51, 57.91], - // CHECK-NEXT: [46.74, 51.34, 55.94, 60.54]] // - %xc = sparse_tensor.convert %x3 : tensor<8x4xf64, #CSC> to tensor<8x4xf64> - %xu = tensor.cast %xc : tensor<8x4xf64> to tensor<*xf64> - call @printMemrefF64(%xu) : (tensor<*xf64>) -> () + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 32 + // CHECK-NEXT: dim = ( 8, 4 ) + // CHECK-NEXT: lvl = ( 4, 8 ) + // CHECK-NEXT: pos[1] : ( 0, 8, 16, 24, 32 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, + // CHECK-SAME: 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: values : ( 32.53, 34.56, 36.59, 38.62, 40.65, 42.68, 44.71, 46.74, + // CHECK-SAME: 35.73, 37.96, 40.19, 42.42, 44.65, 46.88, 49.11, 51.34, + // CHECK-SAME: 38.93, 41.36, 43.79, 46.22, 48.65, 51.08, 53.51, 55.94, + // CHECK-SAME: 42.13, 44.76, 47.39, 50.02, 52.65, 55.28, 57.91, 60.54 + // CHECK-NEXT: ---- + // + sparse_tensor.print %x3 : tensor<8x4xf64, #CSC> // Release the resources. bufferization.dealloc_tensor %x1 : tensor<8x2xf64, #CSC> bufferization.dealloc_tensor %x2 : tensor<2x4xf64, #CSC> bufferization.dealloc_tensor %x3 : tensor<8x4xf64, #CSC> - bufferization.dealloc_tensor %xc : tensor<8x4xf64> return } diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_expand_shape.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_expand_shape.mlir index c784375e0f3eaf176cf5bccbaee98ddd6d37665e..6679a81c74088bc58b9c6783c42ac779c3e9d66c 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_expand_shape.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_expand_shape.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -115,7 +115,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %df = arith.constant -1.0 : f64 @@ -147,60 +147,111 @@ module { %expand11 = call @expand_sparse2sparse_dyn(%sdm) : (tensor<?x?xf64, #SparseMatrix>) -> tensor<?x2x?xf64, #Sparse3dTensor> // - // Verify results of expand + // Verify results of expand with dense output. // // CHECK: ( ( 1, 0, 3, 0 ), ( 5, 0, 7, 0 ), ( 9, 0, 11, 0 ) ) // CHECK-NEXT: ( ( 1, 0, 3, 0 ), ( 5, 0, 7, 0 ), ( 9, 0, 11, 0 ) ) - // CHECK-NEXT: ( 1, 3, 5, 7, 9, - // CHECK-NEXT: ( 1, 3, 5, 7, 9, // CHECK-NEXT: ( ( ( 1.1, 1.2 ), ( 1.3, 1.4 ) ), ( ( 2.1, 2.2 ), ( 2.3, 2.4 ) ), ( ( 3.1, 3.2 ), ( 3.3, 3.4 ) ) ) // CHECK-NEXT: ( ( ( 1.1, 1.2 ), ( 1.3, 1.4 ) ), ( ( 2.1, 2.2 ), ( 2.3, 2.4 ) ), ( ( 3.1, 3.2 ), ( 3.3, 3.4 ) ) ) - // CHECK-NEXT: ( 1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4 ) - // CHECK-NEXT: ( 1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4 ) // CHECK-NEXT: ( ( ( 1.1, 1.2 ), ( 1.3, 1.4 ) ), ( ( 2.1, 2.2 ), ( 2.3, 2.4 ) ), ( ( 3.1, 3.2 ), ( 3.3, 3.4 ) ) ) // CHECK-NEXT: ( ( ( 1.1, 1.2 ), ( 1.3, 1.4 ) ), ( ( 2.1, 2.2 ), ( 2.3, 2.4 ) ), ( ( 3.1, 3.2 ), ( 3.3, 3.4 ) ) ) - // CHECK-NEXT: 12 - // CHECK-NEXT: ( 1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4 ) - // CHECK-NEXT: 12 - // CHECK-NEXT: ( 1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4 ) // - %m0 = vector.transfer_read %expand0[%c0, %c0], %df: tensor<3x4xf64>, vector<3x4xf64> vector.print %m0 : vector<3x4xf64> %m1 = vector.transfer_read %expand1[%c0, %c0], %df: tensor<3x4xf64>, vector<3x4xf64> vector.print %m1 : vector<3x4xf64> - %a2 = sparse_tensor.values %expand2 : tensor<3x4xf64, #SparseMatrix> to memref<?xf64> - %m2 = vector.transfer_read %a2[%c0], %df: memref<?xf64>, vector<12xf64> - vector.print %m2 : vector<12xf64> - %a3 = sparse_tensor.values %expand3 : tensor<3x4xf64, #SparseMatrix> to memref<?xf64> - %m3 = vector.transfer_read %a3[%c0], %df: memref<?xf64>, vector<12xf64> - vector.print %m3 : vector<12xf64> - %m4 = vector.transfer_read %expand4[%c0, %c0, %c0], %df: tensor<3x2x2xf64>, vector<3x2x2xf64> vector.print %m4 : vector<3x2x2xf64> %m5 = vector.transfer_read %expand5[%c0, %c0, %c0], %df: tensor<3x2x2xf64>, vector<3x2x2xf64> vector.print %m5 : vector<3x2x2xf64> - %a6 = sparse_tensor.values %expand6 : tensor<3x2x2xf64, #Sparse3dTensor> to memref<?xf64> - %m6 = vector.transfer_read %a6[%c0], %df: memref<?xf64>, vector<12xf64> - vector.print %m6 : vector<12xf64> - %a7 = sparse_tensor.values %expand7 : tensor<3x2x2xf64, #Sparse3dTensor> to memref<?xf64> - %m7 = vector.transfer_read %a7[%c0], %df: memref<?xf64>, vector<12xf64> - vector.print %m7 : vector<12xf64> - %m8 = vector.transfer_read %expand8[%c0, %c0, %c0], %df: tensor<?x2x?xf64>, vector<3x2x2xf64> vector.print %m8 : vector<3x2x2xf64> %m9 = vector.transfer_read %expand9[%c0, %c0, %c0], %df: tensor<?x2x?xf64>, vector<3x2x2xf64> vector.print %m9 : vector<3x2x2xf64> - %n10 = sparse_tensor.number_of_entries %expand10 : tensor<?x2x?xf64, #Sparse3dTensor> - vector.print %n10 : index - %a10 = sparse_tensor.values %expand10 : tensor<?x2x?xf64, #Sparse3dTensor> to memref<?xf64> - %m10 = vector.transfer_read %a10[%c0], %df: memref<?xf64>, vector<12xf64> - vector.print %m10 : vector<12xf64> - %n11 = sparse_tensor.number_of_entries %expand11 : tensor<?x2x?xf64, #Sparse3dTensor> - vector.print %n11 : index - %a11 = sparse_tensor.values %expand11 : tensor<?x2x?xf64, #Sparse3dTensor> to memref<?xf64> - %m11 = vector.transfer_read %a11[%c0], %df: memref<?xf64>, vector<12xf64> - vector.print %m11 : vector<12xf64> + + // + // Verify results of expand with sparse output. + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 6 + // CHECK-NEXT: dim = ( 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6 + // CHECK-NEXT: crd[1] : ( 0, 2, 0, 2, 0, 2 + // CHECK-NEXT: values : ( 1, 3, 5, 7, 9, 11 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 6 + // CHECK-NEXT: dim = ( 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6 + // CHECK-NEXT: crd[1] : ( 0, 2, 0, 2, 0, 2 + // CHECK-NEXT: values : ( 1, 3, 5, 7, 9, 11 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 12 + // CHECK-NEXT: dim = ( 3, 2, 2 ) + // CHECK-NEXT: lvl = ( 3, 2, 2 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: pos[2] : ( 0, 2, 4, 6, 8, 10, 12 + // CHECK-NEXT: crd[2] : ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 12 + // CHECK-NEXT: dim = ( 3, 2, 2 ) + // CHECK-NEXT: lvl = ( 3, 2, 2 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: pos[2] : ( 0, 2, 4, 6, 8, 10, 12 + // CHECK-NEXT: crd[2] : ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 12 + // CHECK-NEXT: dim = ( 3, 2, 2 ) + // CHECK-NEXT: lvl = ( 3, 2, 2 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: pos[2] : ( 0, 2, 4, 6, 8, 10, 12 + // CHECK-NEXT: crd[2] : ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 12 + // CHECK-NEXT: dim = ( 3, 2, 2 ) + // CHECK-NEXT: lvl = ( 3, 2, 2 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 2, 4, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: pos[2] : ( 0, 2, 4, 6, 8, 10, 12 + // CHECK-NEXT: crd[2] : ( 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 + // CHECK-NEXT: values : ( 1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4 + // CHECK-NEXT: ---- + // + sparse_tensor.print %expand2 : tensor<3x4xf64, #SparseMatrix> + sparse_tensor.print %expand3 : tensor<3x4xf64, #SparseMatrix> + sparse_tensor.print %expand6 : tensor<3x2x2xf64, #Sparse3dTensor> + sparse_tensor.print %expand7 : tensor<3x2x2xf64, #Sparse3dTensor> + sparse_tensor.print %expand10 : tensor<?x2x?xf64, #Sparse3dTensor> + sparse_tensor.print %expand11 : tensor<?x2x?xf64, #Sparse3dTensor> // Release sparse resources. diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_filter_conv2d.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_filter_conv2d.mlir index 7478b604ff67154ad1a511cf87779443367cd81d..37ff2e3ffd3f46026e60aba2967321f54bca9b96 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_filter_conv2d.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_filter_conv2d.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -53,7 +53,7 @@ module { return %0 : tensor<6x6xi32, #DCSR> } - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %i0 = arith.constant 0 : i32 @@ -100,25 +100,27 @@ module { vector.print %v : vector<6x6xi32> // - // Should be the same as dense output - // CHECK: ( ( 0, 0, -1, -6, -1, 6 ), - // CHECK-SAME: ( -1, 0, 1, 0, 1, 0 ), - // CHECK-SAME: ( 0, -1, 1, 0, 0, 0 ), - // CHECK-SAME: ( -1, 0, 0, 0, 0, 0 ), - // CHECK-SAME: ( 0, 0, 3, 6, -3, -6 ), - // CHECK-SAME: ( 2, -1, 3, 0, -3, 0 ) ) + // Should be the same as dense output. // - %sparse_ret = sparse_tensor.convert %1 - : tensor<6x6xi32, #DCSR> to tensor<6x6xi32> - %v1 = vector.transfer_read %sparse_ret[%c0, %c0], %i0 - : tensor<6x6xi32>, vector<6x6xi32> - vector.print %v1 : vector<6x6xi32> + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 36 + // CHECK-NEXT: dim = ( 6, 6 ) + // CHECK-NEXT: lvl = ( 6, 6 ) + // CHECK-NEXT: pos[0] : ( 0, 6 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: pos[1] : ( 0, 6, 12, 18, 24, 30, 36 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, + // CHECK-SAME: 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5 + // CHECK-NEXT: values : ( 0, 0, -1, -6, -1, 6, -1, 0, 1, 0, 1, 0, 0, -1, 1, + // CHECK-SAME: 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 3, 6, -3, -6, 2, -1, 3, 0, -3, 0 + // CHECK-NEXT: ---- + // + sparse_tensor.print %1 : tensor<6x6xi32, #DCSR> // Release the resources. bufferization.dealloc_tensor %sparse_filter : tensor<3x3xi32, #DCSR> bufferization.dealloc_tensor %0 : tensor<6x6xi32> bufferization.dealloc_tensor %1 : tensor<6x6xi32, #DCSR> - bufferization.dealloc_tensor %sparse_ret : tensor<6x6xi32> return } diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_flatten.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_flatten.mlir index 55ecac8dbc18749a25ec53b9fecdb047db66c516..8a5712d3fa1b1090e8f9f4bb553a49623c055567 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_flatten.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_flatten.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -82,7 +82,7 @@ module { // // Main driver that reads tensor from file and calls the sparse kernel. // - func.func @entry() { + func.func @main() { %d0 = arith.constant 0.0 : f64 %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_foreach_slices.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_foreach_slices.mlir index 46b83be21dcf30103dbb5f99593fb4378a0fc166..aef3a947e4f0baba6957c21b26ff6b8be2a5da31 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_foreach_slices.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_foreach_slices.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -100,7 +100,7 @@ module { return } - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c2 = arith.constant 2 : index diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir index c1547033062d37fbaade2b81764a1add6c00f21c..63a6d3acd737e2f71410c31eedf77b7d015914b4 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_generate.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -39,7 +39,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %f0 = arith.constant 0.0 : f64 @@ -80,7 +80,8 @@ module { %sv = sparse_tensor.convert %output : tensor<?xf64> to tensor<?xf64, #SparseVector> %n0 = sparse_tensor.number_of_entries %sv : tensor<?xf64, #SparseVector> - // Print the number of non-zeros for verification. + // Print the number of non-zeros for verification + // as shuffle may generate different numbers. // // CHECK: 5 vector.print %n0 : index diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_index.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_index.mlir index 70a63ae7bc9270fbdf770029bc559ef9d66ab74b..3ce45e5fd971f2b7551ef33559be43499ea021eb 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_index.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_index.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -160,7 +160,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %du = arith.constant -1 : i64 %df = arith.constant -1.0 : f32 @@ -208,63 +208,112 @@ module { // // Verify result. // - // CHECK: 2 - // CHECK-NEXT: 8 - // CHECK-NEXT: 8 - // CHECK-NEXT: 8 - // CHECK-NEXT: 2 - // CHECK-NEXT: 12 - // CHECK-NEXT: 12 - // CHECK-NEXT: 12 - // CHECK-NEXT: ( 20, 80 ) - // CHECK-NEXT: ( 0, 1, 12, 3, 24, 5, 6, 7 ) - // CHECK-NEXT: ( 0, 2, 8, 24, 64, 160, 384, 896 ) - // CHECK-NEXT: ( 1, 3, 6, 11, 20, 37, 70, 135 ) - // CHECK-NEXT: ( 10, 120 ) - // CHECK-NEXT: ( 0, 1, 2, 3, 1, 12, 3, 4, 2, 3, 4, 25 ) - // CHECK-NEXT: ( 0, 0, 0, 0, 0, 2, 2, 3, 0, 2, 12, 24 ) - // CHECK-NEXT: ( 1, 2, 3, 4, 2, 4, 4, 5, 3, 4, 7, 9 ) + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 2 + // CHECK-NEXT: dim = ( 8 ) + // CHECK-NEXT: lvl = ( 8 ) + // CHECK-NEXT: pos[0] : ( 0, 2 + // CHECK-NEXT: crd[0] : ( 2, 4 + // CHECK-NEXT: values : ( 20, 80 + // CHECK-NEXT: ---- // - %n0 = sparse_tensor.number_of_entries %0 : tensor<8xi64, #SparseVector> - %n1 = sparse_tensor.number_of_entries %1 : tensor<8xi64, #SparseVector> - %n2 = sparse_tensor.number_of_entries %2 : tensor<8xi64, #SparseVector> - %n3 = sparse_tensor.number_of_entries %3 : tensor<8xi64, #SparseVector> - %n4 = sparse_tensor.number_of_entries %4 : tensor<3x4xi64, #SparseMatrix> - %n5 = sparse_tensor.number_of_entries %5 : tensor<3x4xi64, #SparseMatrix> - %n6 = sparse_tensor.number_of_entries %6 : tensor<3x4xi64, #SparseMatrix> - %n7 = sparse_tensor.number_of_entries %7 : tensor<3x4xi64, #SparseMatrix> - %8 = sparse_tensor.values %0 : tensor<8xi64, #SparseVector> to memref<?xi64> - %9 = sparse_tensor.values %1 : tensor<8xi64, #SparseVector> to memref<?xi64> - %10 = sparse_tensor.values %2 : tensor<8xi64, #SparseVector> to memref<?xi64> - %11 = sparse_tensor.values %3 : tensor<8xi64, #SparseVector> to memref<?xi64> - %12 = sparse_tensor.values %4 : tensor<3x4xi64, #SparseMatrix> to memref<?xi64> - %13 = sparse_tensor.values %5 : tensor<3x4xi64, #SparseMatrix> to memref<?xi64> - %14 = sparse_tensor.values %6 : tensor<3x4xi64, #SparseMatrix> to memref<?xi64> - %15 = sparse_tensor.values %7 : tensor<3x4xi64, #SparseMatrix> to memref<?xi64> - %16 = vector.transfer_read %8[%c0], %du: memref<?xi64>, vector<2xi64> - %17 = vector.transfer_read %9[%c0], %du: memref<?xi64>, vector<8xi64> - %18 = vector.transfer_read %10[%c0], %du: memref<?xi64>, vector<8xi64> - %19 = vector.transfer_read %11[%c0], %du: memref<?xi64>, vector<8xi64> - %20 = vector.transfer_read %12[%c0], %du: memref<?xi64>, vector<2xi64> - %21 = vector.transfer_read %13[%c0], %du: memref<?xi64>, vector<12xi64> - %22 = vector.transfer_read %14[%c0], %du: memref<?xi64>, vector<12xi64> - %23 = vector.transfer_read %15[%c0], %du: memref<?xi64>, vector<12xi64> - vector.print %n0 : index - vector.print %n1 : index - vector.print %n2 : index - vector.print %n3 : index - vector.print %n4 : index - vector.print %n5 : index - vector.print %n6 : index - vector.print %n7 : index - vector.print %16 : vector<2xi64> - vector.print %17 : vector<8xi64> - vector.print %18 : vector<8xi64> - vector.print %19 : vector<8xi64> - vector.print %20 : vector<2xi64> - vector.print %21 : vector<12xi64> - vector.print %22 : vector<12xi64> - vector.print %23 : vector<12xi64> + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 8 + // CHECK-NEXT: dim = ( 8 ) + // CHECK-NEXT: lvl = ( 8 ) + // CHECK-NEXT: pos[0] : ( 0, 8 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: values : ( 0, 1, 12, 3, 24, 5, 6, 7 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 8 + // CHECK-NEXT: dim = ( 8 ) + // CHECK-NEXT: lvl = ( 8 ) + // CHECK-NEXT: pos[0] : ( 0, 8 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: values : ( 0, 2, 8, 24, 64, 160, 384, 896 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 8 + // CHECK-NEXT: dim = ( 8 ) + // CHECK-NEXT: lvl = ( 8 ) + // CHECK-NEXT: pos[0] : ( 0, 8 + // CHECK-NEXT: crd[0] : ( 0, 1, 2, 3, 4, 5, 6, 7 + // CHECK-NEXT: values : ( 1, 3, 6, 11, 20, 37, 70, 135 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 2 + // CHECK-NEXT: dim = ( 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 2 + // CHECK-NEXT: crd[0] : ( 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 1, 2 + // CHECK-NEXT: crd[1] : ( 1, 3 + // CHECK-NEXT: values : ( 10, 120 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 12 + // CHECK-NEXT: dim = ( 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 4, 8, 12 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: values : ( 0, 1, 2, 3, 1, 12, 3, 4, 2, 3, 4, 25 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 12 + // CHECK-NEXT: dim = ( 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 4, 8, 12 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: values : ( 0, 0, 0, 0, 0, 2, 2, 3, 0, 2, 12, 24 + // CHECK-NEXT: ---- + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 12 + // CHECK-NEXT: dim = ( 3, 4 ) + // CHECK-NEXT: lvl = ( 3, 4 ) + // CHECK-NEXT: pos[0] : ( 0, 3 + // CHECK-NEXT: crd[0] : ( 0, 1, 2 + // CHECK-NEXT: pos[1] : ( 0, 4, 8, 12 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 + // CHECK-NEXT: values : ( 1, 2, 3, 4, 2, 4, 4, 5, 3, 4, 7, 9 + // CHECK-NEXT: ---- + // + sparse_tensor.print %0 : tensor<8xi64, #SparseVector> + sparse_tensor.print %1 : tensor<8xi64, #SparseVector> + sparse_tensor.print %2 : tensor<8xi64, #SparseVector> + sparse_tensor.print %3 : tensor<8xi64, #SparseVector> + sparse_tensor.print %4 : tensor<3x4xi64, #SparseMatrix> + sparse_tensor.print %5 : tensor<3x4xi64, #SparseMatrix> + sparse_tensor.print %6 : tensor<3x4xi64, #SparseMatrix> + sparse_tensor.print %7 : tensor<3x4xi64, #SparseMatrix> + + // + // Call the f32 kernel, verify the result. + // + // CHECK: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 6 + // CHECK-NEXT: dim = ( 2, 3 ) + // CHECK-NEXT: lvl = ( 2, 3 ) + // CHECK-NEXT: pos[0] : ( 0, 2 + // CHECK-NEXT: crd[0] : ( 0, 1 + // CHECK-NEXT: pos[1] : ( 0, 3, 6 + // CHECK-NEXT: crd[1] : ( 0, 1, 2, 0, 1, 2 + // CHECK-NEXT: values : ( 0, 10, 0, 1, 1, 42 + // CHECK-NEXT: ---- + // + %100 = call @add_outer_2d(%sf32) : (tensor<2x3xf32, #SparseMatrix>) + -> tensor<2x3xf32, #SparseMatrix> + sparse_tensor.print %100 : tensor<2x3xf32, #SparseMatrix> // Release resources. bufferization.dealloc_tensor %sv : tensor<8xi64, #SparseVector> @@ -279,17 +328,6 @@ module { bufferization.dealloc_tensor %5 : tensor<3x4xi64, #SparseMatrix> bufferization.dealloc_tensor %6 : tensor<3x4xi64, #SparseMatrix> bufferization.dealloc_tensor %7 : tensor<3x4xi64, #SparseMatrix> - - // - // Call the f32 kernel, verify the result, release the resources. - // - // CHECK-NEXT: ( 0, 10, 0, 1, 1, 42 ) - // - %100 = call @add_outer_2d(%sf32) : (tensor<2x3xf32, #SparseMatrix>) - -> tensor<2x3xf32, #SparseMatrix> - %101 = sparse_tensor.values %100 : tensor<2x3xf32, #SparseMatrix> to memref<?xf32> - %102 = vector.transfer_read %101[%c0], %df: memref<?xf32>, vector<6xf32> - vector.print %102 : vector<6xf32> bufferization.dealloc_tensor %sf32 : tensor<2x3xf32, #SparseMatrix> bufferization.dealloc_tensor %100 : tensor<2x3xf32, #SparseMatrix> diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_index_dense.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_index_dense.mlir index 4bb1f3d12871f3547abb8c9d0a55b20441a928d2..fc7b82fdecea343a835bdc8b10824cb5e7030ea8 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_index_dense.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_index_dense.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -138,7 +138,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %du = arith.constant -1 : i64 diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_3d.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_3d.mlir index 364a188cf37c4c2fefeae9f345c35c1125141676..db6612402357e578414845dbc2e800170c798e12 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_3d.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_insert_3d.mlir @@ -10,7 +10,7 @@ // DEFINE: %{compile} = mlir-opt %s --sparsifier="%{sparsifier_opts}" // DEFINE: %{compile_sve} = mlir-opt %s --sparsifier="%{sparsifier_opts_sve}" // DEFINE: %{run_libs} = -shared-libs=%mlir_c_runner_utils,%mlir_runner_utils -// DEFINE: %{run_opts} = -e entry -entry-point-result=void +// DEFINE: %{run_opts} = -e main -entry-point-result=void // DEFINE: %{run} = mlir-cpu-runner %{run_opts} %{run_libs} // DEFINE: %{run_sve} = %mcr_aarch64_cmd --march=aarch64 --mattr="+sve" %{run_opts} %{run_libs} // @@ -48,7 +48,7 @@ module { // // Main driver. // - func.func @entry() { + func.func @main() { %c0 = arith.constant 0 : index %c1 = arith.constant 1 : index %c2 = arith.constant 2 : index diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_pack.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_pack.mlir index 7cde6b93d3250c3db6e1cf29e1dd083e96925d20..7ecccad212cdbe2da3d616fb21a460feb470be2f 100644 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_pack.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_pack.mlir @@ -279,6 +279,30 @@ module { %si = tensor.extract %li[] : tensor<i64> vector.print %si : i64 + // TODO: This check is no longer needed once the codegen path uses the + // buffer deallocation pass. "dealloc_tensor" turn into a no-op in the + // codegen path. + %has_runtime = sparse_tensor.has_runtime_library + scf.if %has_runtime { + // sparse_tensor.assemble copies buffers when running with the runtime + // library. Deallocations are not needed when running in codegen mode. + bufferization.dealloc_tensor %s4 : tensor<10x10xf64, #SortedCOO> + bufferization.dealloc_tensor %s5 : tensor<10x10xf64, #SortedCOOI32> + bufferization.dealloc_tensor %csr : tensor<2x2xf64, #CSR> + bufferization.dealloc_tensor %bs : tensor<2x10x10xf64, #BCOO> + } + + bufferization.dealloc_tensor %li : tensor<i64> + bufferization.dealloc_tensor %od : tensor<3xf64> + bufferization.dealloc_tensor %op : tensor<2xi32> + bufferization.dealloc_tensor %oi : tensor<3x2xi32> + bufferization.dealloc_tensor %d_csr : tensor<4xf64> + bufferization.dealloc_tensor %p_csr : tensor<3xi32> + bufferization.dealloc_tensor %i_csr : tensor<3xi32> + bufferization.dealloc_tensor %bod : tensor<6xf64> + bufferization.dealloc_tensor %bop : tensor<4xindex> + bufferization.dealloc_tensor %boi : tensor<6x2xindex> + return } } diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_pack_d.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_pack_d.mlir index aa1bd04fde87dc7fb849ca5441de59f088623758..20ae7e86285cce530a839b85f5d8a3adbca56d55 100755 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_pack_d.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_pack_d.mlir @@ -140,10 +140,18 @@ module { sparse_tensor.print %s1 : tensor<4x3x2xf32, #BatchedCSR> sparse_tensor.print %s2 : tensor<4x3x2xf32, #CSRDense> - // FIXME: doing this explicitly crashes runtime - // bufferization.dealloc_tensor %s0 : tensor<4x3x2xf32, #CCC> - // bufferization.dealloc_tensor %s1 : tensor<4x3x2xf32, #BatchedCSR> - // bufferization.dealloc_tensor %s2 : tensor<4x3x2xf32, #CSRDense> + // TODO: This check is no longer needed once the codegen path uses the + // buffer deallocation pass. "dealloc_tensor" turn into a no-op in the + // codegen path. + %has_runtime = sparse_tensor.has_runtime_library + scf.if %has_runtime { + // sparse_tensor.assemble copies buffers when running with the runtime + // library. Deallocations are not needed when running in codegen mode. + bufferization.dealloc_tensor %s0 : tensor<4x3x2xf32, #CCC> + bufferization.dealloc_tensor %s1 : tensor<4x3x2xf32, #BatchedCSR> + bufferization.dealloc_tensor %s2 : tensor<4x3x2xf32, #CSRDense> + } + return } } diff --git a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_print.mlir b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_print.mlir index 98d76ba350cbd9edeb3778c8663f79e52017489e..7758ca77dce9ea20d87ab29ce311819a38e7beb2 100755 --- a/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_print.mlir +++ b/mlir/test/Integration/Dialect/SparseTensor/CPU/sparse_print.mlir @@ -120,6 +120,14 @@ ) }> +#COOAoS = #sparse_tensor.encoding<{ + map = (d0, d1) -> (d0 : compressed(nonunique), d1 : singleton) +}> + +#COOSoA = #sparse_tensor.encoding<{ + map = (d0, d1) -> (d0 : compressed(nonunique), d1 : singleton(soa)) +}> + module { // @@ -161,6 +169,8 @@ module { %h = sparse_tensor.convert %x : tensor<4x8xi32> to tensor<4x8xi32, #BSCC> %i = sparse_tensor.convert %x : tensor<4x8xi32> to tensor<4x8xi32, #BSR0> %j = sparse_tensor.convert %x : tensor<4x8xi32> to tensor<4x8xi32, #BSC0> + %AoS = sparse_tensor.convert %x : tensor<4x8xi32> to tensor<4x8xi32, #COOAoS> + %SoA = sparse_tensor.convert %x : tensor<4x8xi32> to tensor<4x8xi32, #COOSoA> // CHECK-NEXT: ---- Sparse Tensor ---- // CHECK-NEXT: nse = 5 @@ -274,19 +284,42 @@ module { // CHECK-NEXT: ---- sparse_tensor.print %j : tensor<4x8xi32, #BSC0> + // CHECK-NEXT: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 5 + // CHECK-NEXT: dim = ( 4, 8 ) + // CHECK-NEXT: lvl = ( 4, 8 ) + // CHECK-NEXT: pos[0] : ( 0, 5, + // CHECK-NEXT: crd[0] : ( 0, 0, 0, 2, 3, 2, 3, 3, 3, 5, + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, + // CHECK-NEXT: ---- + sparse_tensor.print %AoS : tensor<4x8xi32, #COOAoS> + + // CHECK-NEXT: ---- Sparse Tensor ---- + // CHECK-NEXT: nse = 5 + // CHECK-NEXT: dim = ( 4, 8 ) + // CHECK-NEXT: lvl = ( 4, 8 ) + // CHECK-NEXT: pos[0] : ( 0, 5, + // CHECK-NEXT: crd[0] : ( 0, 0, 3, 3, 3, + // CHECK-NEXT: crd[1] : ( 0, 2, 2, 3, 5, + // CHECK-NEXT: values : ( 1, 2, 3, 4, 5, + // CHECK-NEXT: ---- + sparse_tensor.print %SoA : tensor<4x8xi32, #COOSoA> + // Release the resources. - bufferization.dealloc_tensor %XO : tensor<4x8xi32, #AllDense> - bufferization.dealloc_tensor %XT : tensor<4x8xi32, #AllDenseT> - bufferization.dealloc_tensor %a : tensor<4x8xi32, #CSR> - bufferization.dealloc_tensor %b : tensor<4x8xi32, #DCSR> - bufferization.dealloc_tensor %c : tensor<4x8xi32, #CSC> - bufferization.dealloc_tensor %d : tensor<4x8xi32, #DCSC> - bufferization.dealloc_tensor %e : tensor<4x8xi32, #BSR> - bufferization.dealloc_tensor %f : tensor<4x8xi32, #BSRC> - bufferization.dealloc_tensor %g : tensor<4x8xi32, #BSC> - bufferization.dealloc_tensor %h : tensor<4x8xi32, #BSCC> - bufferization.dealloc_tensor %i : tensor<4x8xi32, #BSR0> - bufferization.dealloc_tensor %j : tensor<4x8xi32, #BSC0> + bufferization.dealloc_tensor %XO : tensor<4x8xi32, #AllDense> + bufferization.dealloc_tensor %XT : tensor<4x8xi32, #AllDenseT> + bufferization.dealloc_tensor %a : tensor<4x8xi32, #CSR> + bufferization.dealloc_tensor %b : tensor<4x8xi32, #DCSR> + bufferization.dealloc_tensor %c : tensor<4x8xi32, #CSC> + bufferization.dealloc_tensor %d : tensor<4x8xi32, #DCSC> + bufferization.dealloc_tensor %e : tensor<4x8xi32, #BSR> + bufferization.dealloc_tensor %f : tensor<4x8xi32, #BSRC> + bufferization.dealloc_tensor %g : tensor<4x8xi32, #BSC> + bufferization.dealloc_tensor %h : tensor<4x8xi32, #BSCC> + bufferization.dealloc_tensor %i : tensor<4x8xi32, #BSR0> + bufferization.dealloc_tensor %j : tensor<4x8xi32, #BSC0> + bufferization.dealloc_tensor %AoS : tensor<4x8xi32, #COOAoS> + bufferization.dealloc_tensor %SoA : tensor<4x8xi32, #COOSoA> return } diff --git a/mlir/test/Integration/Dialect/Standard/CPU/test-ceil-floor-pos-neg.mlir b/mlir/test/Integration/Dialect/Standard/CPU/test-ceil-floor-pos-neg.mlir index 39fbb67512c6f00b627cfbd5eaa1b171e3f93f74..a7013eacc9849907e0f87883dc75356dd0dfd1d0 100644 --- a/mlir/test/Integration/Dialect/Standard/CPU/test-ceil-floor-pos-neg.mlir +++ b/mlir/test/Integration/Dialect/Standard/CPU/test-ceil-floor-pos-neg.mlir @@ -2,6 +2,10 @@ // RUN: mlir-cpu-runner -e entry -entry-point-result=void \ // RUN: -shared-libs=%mlir_c_runner_utils | \ // RUN: FileCheck %s +// RUN: mlir-opt %s -pass-pipeline="builtin.module(func.func(convert-vector-to-scf,lower-affine,convert-scf-to-cf,memref-expand,arith-expand),convert-vector-to-llvm,finalize-memref-to-llvm,convert-func-to-llvm,reconcile-unrealized-casts)" | \ +// RUN: mlir-cpu-runner -e main -entry-point-result=void \ +// RUN: -shared-libs=%mlir_c_runner_utils | \ +// RUN: FileCheck %s --check-prefix=SCHECK func.func @transfer_read_2d(%A : memref<40xi32>, %base1: index) { %i42 = arith.constant -42: i32 @@ -101,3 +105,29 @@ func.func @entry() { // CHECK:( 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2, -2, -2, -2 ) // CHECK:( 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4 ) // CHECK:( 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ) + +// ----- + +func.func @non_inline_function() -> (i64, i64, i64, i64, i64, i64) { + %MIN_INT_MINUS_ONE = arith.constant -9223372036854775807 : i64 + %NEG_ONE = arith.constant -1 : i64 + %MIN_INT = arith.constant -9223372036854775808 : i64 + %ONE = arith.constant 1 : i64 + %MAX_INT = arith.constant 9223372036854775807 : i64 + return %MIN_INT_MINUS_ONE, %NEG_ONE, %MIN_INT, %ONE, %MAX_INT, %NEG_ONE : i64, i64, i64, i64, i64, i64 +} + +func.func @main() { + %0:6 = call @non_inline_function() : () -> (i64, i64, i64, i64, i64, i64) + %1 = arith.floordivsi %0#0, %0#1 : i64 + %2 = arith.floordivsi %0#2, %0#3 : i64 + %3 = arith.floordivsi %0#4, %0#5 : i64 + vector.print %1 : i64 + vector.print %2 : i64 + vector.print %3 : i64 + return +} + +// SCHECK: 9223372036854775807 +// SCHECK: -9223372036854775808 +// SCHECK: -9223372036854775807 diff --git a/mlir/test/Integration/Dialect/Tosa/CPU/test-fully-connected.mlir b/mlir/test/Integration/Dialect/Tosa/CPU/test-fully-connected.mlir index bf178c826574e4d85ee76541647d403b0c589ca1..258b1b4f2fab4567582f53ac4d44861ea8f22039 100644 --- a/mlir/test/Integration/Dialect/Tosa/CPU/test-fully-connected.mlir +++ b/mlir/test/Integration/Dialect/Tosa/CPU/test-fully-connected.mlir @@ -1,5 +1,5 @@ // RUN: mlir-opt %s -pass-pipeline="builtin.module(func.func(tosa-to-linalg-named,tosa-to-linalg,tosa-to-arith))" | \ -// RUN: mlir-opt -one-shot-bufferize -func-bufferize -test-lower-to-llvm | \ +// RUN: mlir-opt -one-shot-bufferize="bufferize-function-boundaries" -buffer-deallocation-pipeline -test-lower-to-llvm | \ // RUN: mlir-cpu-runner -O3 -e main -entry-point-result=void \ // RUN: -shared-libs=%mlir_runner_utils \ // RUN: | FileCheck %s diff --git a/mlir/test/Integration/Dialect/Vector/CPU/test-shuffle16x16.mlir b/mlir/test/Integration/Dialect/Vector/CPU/test-shuffle16x16.mlir index 396417bd9b4485ea18e91a5be1a47f082e941818..f7f0a7267cd078808f3017817264f38e21600a48 100644 --- a/mlir/test/Integration/Dialect/Vector/CPU/test-shuffle16x16.mlir +++ b/mlir/test/Integration/Dialect/Vector/CPU/test-shuffle16x16.mlir @@ -30,7 +30,8 @@ func.func @entry() { } module attributes {transform.with_named_sequence} { - transform.named_sequence @__transform_main(%func_op: !transform.op<"func.func"> {transform.readonly}) { + transform.named_sequence @__transform_main(%root : !transform.any_op {transform.readonly}) { + %func_op = transform.structured.match ops{["func.func"]} in %root : (!transform.any_op) -> !transform.op<"func.func"> transform.apply_patterns to %func_op { transform.apply_patterns.vector.lower_transpose lowering_strategy = "shuffle_16x16" } : !transform.op<"func.func"> diff --git a/mlir/test/Integration/GPU/CUDA/sm90/tma_load_128x128_stride_noswizzle.mlir b/mlir/test/Integration/GPU/CUDA/sm90/tma_load_128x128_stride_noswizzle.mlir new file mode 100644 index 0000000000000000000000000000000000000000..4d415394482029a29d583b8ca9c50f62af170b6c --- /dev/null +++ b/mlir/test/Integration/GPU/CUDA/sm90/tma_load_128x128_stride_noswizzle.mlir @@ -0,0 +1,148 @@ +// RUN: mlir-opt %s \ +// RUN: -gpu-lower-to-nvvm-pipeline="cubin-chip=sm_90 cubin-features=+ptx80 opt-level=3" \ +// RUN: | mlir-cpu-runner \ +// RUN: --shared-libs=%mlir_cuda_runtime \ +// RUN: --shared-libs=%mlir_runner_utils \ +// RUN: --shared-libs=%mlir_c_runner_utils \ +// RUN: --entry-point-result=void \ +// RUN: | FileCheck %s + +// CHECK: Correct Results :8192 +// CHECK: Incorrect Results :0 + +module { + func.func @main() { + %c10000000 = arith.constant 10000000 : index + %false = arith.constant false + %c32768 = arith.constant 32768 : index + %c31_i32 = arith.constant 31 : i32 + %c-1_i32 = arith.constant -1 : i32 + %c5_i32 = arith.constant 5 : i32 + %c0_i32 = arith.constant 0 : i32 + %c0 = arith.constant 0 : index + %c8 = arith.constant 8 : index + %c64 = arith.constant 64 : index + %c2 = arith.constant 2 : index + %c32768_i32 = arith.constant 32768 : i32 + %c128 = arith.constant 128 : index + %c1 = arith.constant 1 : index + %0 = llvm.mlir.constant(1 : i64) : i64 + %1 = llvm.mlir.constant(128 : i64) : i64 + %2 = llvm.mlir.constant(0 : i64) : i64 + %f0 = arith.constant 0.0 : f16 + %f123 = arith.constant 1.123 : f16 + + %srcMemref_host = memref.alloc() : memref<128x128xf16> + %dstMemref_host = memref.alloc() : memref<128x128xf16> + scf.for %arg0 = %c0 to %c128 step %c1 { + scf.for %arg1 = %c0 to %c64 step %c1 { + %d1 = arith.index_cast %arg0 : index to i32 + %d2 = arith.index_cast %arg1 : index to i32 + %d3 = arith.sitofp %d1 : i32 to f16 + %d4 = arith.sitofp %d2 : i32 to f16 + %d5 = arith.addf %d3, %f123 : f16 + %d6 = arith.constant 3.12 : f16 + %d7 = arith.mulf %d5, %d6 : f16 + %d8 = arith.addf %d7, %d5 : f16 + %d9 = arith.constant 0.178 : f16 + %d10 = arith.divf %d9, %d8 : f16 + memref.store %d10, %srcMemref_host[%arg0, %arg1] : memref<128x128xf16> + memref.store %f0, %dstMemref_host[%arg0, %arg1] : memref<128x128xf16> + } + } + + %s1 = gpu.wait async + %srcMemref, %s2 = gpu.alloc async [%s1] () : memref<128x128xf16> + %dstMemref, %s3 = gpu.alloc async [%s2] () : memref<128x128xf16> + %s4 = gpu.memcpy async [%s3] %srcMemref, %srcMemref_host : memref<128x128xf16>, memref<128x128xf16> + %s5 = gpu.memcpy async [%s4] %dstMemref, %dstMemref_host : memref<128x128xf16>, memref<128x128xf16> + + %expand_shape = memref.expand_shape %srcMemref [[0, 1], [2, 3]] : memref<128x128xf16> into memref<2x64x2x64xf16> + %transpose = memref.transpose %expand_shape (d0, d1, d2, d3) -> (d0, d2, d1, d3) : memref<2x64x2x64xf16> to memref<2x2x64x64xf16, strided<[8192, 64, 128, 1]>> + %cast = memref.cast %transpose : memref<2x2x64x64xf16, strided<[8192, 64, 128, 1]>> to memref<*xf16> + %24 = nvgpu.tma.create.descriptor %cast box[%c2, %c2, %c64, %c64] : memref<*xf16> -> <tensor = memref<2x2x64x64xf16, 3>, swizzle = none, l2promo = none, oob = zero, interleave = none> + + gpu.launch + blocks(%arg2, %arg3, %arg4) in (%arg8 = %c1, %arg9 = %c1, %arg10 = %c1) + threads(%arg5, %arg6, %arg7) in (%arg11 = %c128, %arg12 = %c1, %arg13 = %c1) + dynamic_shared_memory_size %c32768_i32 + { + %26 = gpu.dynamic_shared_memory : memref<?xi8, #gpu.address_space<workgroup>> + %view = memref.view %26[%c0][] : memref<?xi8, #gpu.address_space<workgroup>> to memref<2x2x64x64xf16, #gpu.address_space<workgroup>> + %27 = nvgpu.mbarrier.create -> <memorySpace = #gpu.address_space<workgroup>> + %thread_id_x = gpu.thread_id x + %28 = arith.index_cast %thread_id_x : index to i32 + %29 = arith.shrui %28, %c5_i32 : i32 + %30 = nvvm.shfl.sync idx %c-1_i32, %29, %c0_i32, %c31_i32 : i32 -> i32 + %31 = arith.cmpi eq, %30, %c0_i32 : i32 + %32 = nvvm.elect.sync -> i1 + %33 = arith.andi %31, %32 : i1 + scf.if %33 { + nvgpu.mbarrier.init %27[%c0], %c1 : <memorySpace = #gpu.address_space<workgroup>> + } + %34 = nvvm.shfl.sync idx %c-1_i32, %29, %c0_i32, %c31_i32 : i32 -> i32 + %35 = arith.cmpi eq, %34, %c0_i32 : i32 + %36 = nvvm.elect.sync -> i1 + %37 = arith.andi %35, %36 : i1 + scf.if %37 { + nvgpu.mbarrier.arrive.expect_tx %27[%c0], %c32768 : <memorySpace = #gpu.address_space<workgroup>> + nvgpu.tma.async.load %24[%c0, %c0, %c0, %c0], %27[%c0] to %view : <tensor = memref<2x2x64x64xf16, 3>, swizzle = none, l2promo = none, oob = zero, interleave = none>, <memorySpace = #gpu.address_space<workgroup>> -> memref<2x2x64x64xf16, #gpu.address_space<workgroup>> + } + nvgpu.mbarrier.try_wait.parity %27[%c0], %false, %c10000000 : <memorySpace = #gpu.address_space<workgroup>> + scf.for %arg14 = %c0 to %c2 step %c1 { + scf.for %arg15 = %c0 to %c2 step %c1 { + %38 = arith.muli %arg14, %c64 : index + %39 = arith.muli %arg15, %c64 : index + %subview = memref.subview %view[%arg14, %arg15, 0, 0] [1, 1, 64, 64] [1, 1, 1, 1] : memref<2x2x64x64xf16, #gpu.address_space<workgroup>> to memref<64x64xf16, strided<[64, 1], offset: ?>, #gpu.address_space<workgroup>> + %subview_0 = memref.subview %dstMemref[%38, %39] [64, 64] [1, 1] : memref<128x128xf16> to memref<64x64xf16, strided<[128, 1], offset: ?>> + %block_dim_x = gpu.block_dim x + %thread_id_y = gpu.thread_id y + %40 = arith.muli %thread_id_y, %block_dim_x : index + %41 = arith.addi %thread_id_x, %40 : index + %block_dim_y = gpu.block_dim y + %42 = arith.muli %block_dim_x, %block_dim_y : index + %thread_id_z = gpu.thread_id z + %43 = arith.muli %thread_id_z, %42 : index + %44 = arith.addi %41, %43 : index + %45 = arith.cmpi eq, %44, %c0 : index + scf.if %45 { + scf.for %arg16 = %c0 to %c64 step %c1 { + scf.for %arg17 = %c0 to %c64 step %c1 { + %46 = memref.load %subview[%arg16, %arg17] : memref<64x64xf16, strided<[64, 1], offset: ?>, #gpu.address_space<workgroup>> + memref.store %46, %subview_0[%arg16, %arg17] : memref<64x64xf16, strided<[128, 1], offset: ?>> + } + } + } + gpu.barrier + } + } + gpu.terminator + } + + %s6 = gpu.memcpy async [%s5] %dstMemref_host, %dstMemref : memref<128x128xf16>, memref<128x128xf16> + gpu.wait [%s6] + + %errorCount, %correctCount = scf.for %arg0 = %c0 to %c128 step %c1 iter_args(%ec1 = %c0, %cc1 = %c0) -> (index,index) { + %ec2, %cc2 = scf.for %arg1 = %c0 to %c64 step %c1 iter_args(%ec2 = %ec1, %cc2 = %cc1) -> (index, index) { + %v1 = memref.load %dstMemref_host[%arg0, %arg1] : memref<128x128xf16> + %v2 = memref.load %srcMemref_host[%arg0, %arg1] : memref<128x128xf16> + %p = arith.cmpf one, %v1, %v2 : f16 + %ec3, %cc3 = scf.if %p -> (index, index) { + %ec3 = arith.addi %ec2, %c1 : index + scf.yield %ec3, %cc2 : index, index + } else { + %cc3 = arith.addi %cc2, %c1 : index + scf.yield %ec2, %cc3 : index, index + } + scf.yield %ec3, %cc3 : index,index + } + scf.yield %ec2, %cc2 : index,index + } + + vector.print str "Correct Results :" + vector.print %correctCount : index + vector.print str "Incorrect Results :" + vector.print %errorCount : index + return + } +} diff --git a/mlir/test/Interfaces/DataLayoutInterfaces/module.mlir b/mlir/test/Interfaces/DataLayoutInterfaces/module.mlir index 096e7ceb3cbcef066fa8da89adf7230abe5e72f1..97286ce758069c097281da68ee1eee4bac9bdc92 100644 --- a/mlir/test/Interfaces/DataLayoutInterfaces/module.mlir +++ b/mlir/test/Interfaces/DataLayoutInterfaces/module.mlir @@ -2,11 +2,13 @@ module attributes { dlti.dl_spec = #dlti.dl_spec< #dlti.dl_entry<!test.test_type_with_layout<10>, ["size", 12]>, - #dlti.dl_entry<!test.test_type_with_layout<20>, ["alignment", 32]>>} { + #dlti.dl_entry<!test.test_type_with_layout<20>, ["alignment", 32]>, + #dlti.dl_entry<!test.test_type_with_layout<30>, ["index", 7]>>} { // CHECK-LABEL: @module_level_layout func.func @module_level_layout() { // CHECK: alignment = 32 // CHECK: bitsize = 12 + // CHECK: index = 7 // CHECK: preferred = 1 // CHECK: size = 2 "test.data_layout_query"() : () -> !test.test_type_with_layout<10> diff --git a/mlir/test/Interfaces/DataLayoutInterfaces/query.mlir b/mlir/test/Interfaces/DataLayoutInterfaces/query.mlir index 9f9240ac6f8cea8125dbe6f731ce2b7a2b9dc296..d3bc91339d164bdf270b357a0b4bc67a7bea4cb1 100644 --- a/mlir/test/Interfaces/DataLayoutInterfaces/query.mlir +++ b/mlir/test/Interfaces/DataLayoutInterfaces/query.mlir @@ -4,24 +4,34 @@ func.func @no_layout_builtin() { // CHECK: alignment = 4 // CHECK: bitsize = 32 + // CHECK: index = 0 // CHECK: preferred = 4 // CHECK: size = 4 "test.data_layout_query"() : () -> i32 // CHECK: alignment = 8 // CHECK: bitsize = 64 + // CHECK: index = 0 // CHECK: preferred = 8 // CHECK: size = 8 "test.data_layout_query"() : () -> f64 // CHECK: alignment = 4 // CHECK: bitsize = 64 + // CHECK: index = 0 // CHECK: preferred = 4 // CHECK: size = 8 "test.data_layout_query"() : () -> complex<f32> // CHECK: alignment = 1 // CHECK: bitsize = 14 + // CHECK: index = 0 // CHECK: preferred = 1 // CHECK: size = 2 "test.data_layout_query"() : () -> complex<i6> + // CHECK: alignment = 4 + // CHECK: bitsize = 64 + // CHECK: index = 64 + // CHECK: preferred = 8 + // CHECK: size = 8 + "test.data_layout_query"() : () -> index return } @@ -30,6 +40,7 @@ func.func @no_layout_builtin() { func.func @no_layout_custom() { // CHECK: alignment = 1 // CHECK: bitsize = 1 + // CHECK: index = 1 // CHECK: preferred = 1 // CHECK: size = 1 "test.data_layout_query"() : () -> !test.test_type_with_layout<10> @@ -41,6 +52,7 @@ func.func @layout_op_no_layout() { "test.op_with_data_layout"() ({ // CHECK: alignment = 1 // CHECK: bitsize = 1 + // CHECK: index = 1 // CHECK: preferred = 1 // CHECK: size = 1 "test.data_layout_query"() : () -> !test.test_type_with_layout<1000> @@ -54,13 +66,15 @@ func.func @layout_op() { "test.op_with_data_layout"() ({ // CHECK: alignment = 20 // CHECK: bitsize = 10 + // CHECK: index = 30 // CHECK: preferred = 1 // CHECK: size = 2 "test.data_layout_query"() : () -> !test.test_type_with_layout<10> "test.maybe_terminator"() : () -> () }) { dlti.dl_spec = #dlti.dl_spec< #dlti.dl_entry<!test.test_type_with_layout<10>, ["size", 10]>, - #dlti.dl_entry<!test.test_type_with_layout<20>, ["alignment", 20]> + #dlti.dl_entry<!test.test_type_with_layout<20>, ["alignment", 20]>, + #dlti.dl_entry<!test.test_type_with_layout<30>, ["index", 30]> >} : () -> () return } @@ -72,13 +86,15 @@ func.func @nested_inner_only() { "test.op_with_data_layout"() ({ // CHECK: alignment = 20 // CHECK: bitsize = 10 + // CHECK: index = 30 // CHECK: preferred = 1 // CHECK: size = 2 "test.data_layout_query"() : () -> !test.test_type_with_layout<10> "test.maybe_terminator"() : () -> () }) { dlti.dl_spec = #dlti.dl_spec< #dlti.dl_entry<!test.test_type_with_layout<10>, ["size", 10]>, - #dlti.dl_entry<!test.test_type_with_layout<20>, ["alignment", 20]> + #dlti.dl_entry<!test.test_type_with_layout<20>, ["alignment", 20]>, + #dlti.dl_entry<!test.test_type_with_layout<30>, ["index", 30]> >} : () -> () "test.maybe_terminator"() : () -> () }) : () -> () @@ -92,6 +108,7 @@ func.func @nested_outer_only() { "test.op_with_data_layout"() ({ // CHECK: alignment = 20 // CHECK: bitsize = 10 + // CHECK: index = 30 // CHECK: preferred = 1 // CHECK: size = 2 "test.data_layout_query"() : () -> !test.test_type_with_layout<10> @@ -100,7 +117,8 @@ func.func @nested_outer_only() { "test.maybe_terminator"() : () -> () }) { dlti.dl_spec = #dlti.dl_spec< #dlti.dl_entry<!test.test_type_with_layout<10>, ["size", 10]>, - #dlti.dl_entry<!test.test_type_with_layout<20>, ["alignment", 20]> + #dlti.dl_entry<!test.test_type_with_layout<20>, ["alignment", 20]>, + #dlti.dl_entry<!test.test_type_with_layout<30>, ["index", 30]> >} : () -> () return } @@ -112,6 +130,7 @@ func.func @nested_middle_only() { "test.op_with_data_layout"() ({ // CHECK: alignment = 20 // CHECK: bitsize = 10 + // CHECK: index = 30 // CHECK: preferred = 1 // CHECK: size = 2 "test.data_layout_query"() : () -> !test.test_type_with_layout<10> @@ -120,7 +139,8 @@ func.func @nested_middle_only() { "test.maybe_terminator"() : () -> () }) { dlti.dl_spec = #dlti.dl_spec< #dlti.dl_entry<!test.test_type_with_layout<10>, ["size", 10]>, - #dlti.dl_entry<!test.test_type_with_layout<20>, ["alignment", 20]> + #dlti.dl_entry<!test.test_type_with_layout<20>, ["alignment", 20]>, + #dlti.dl_entry<!test.test_type_with_layout<30>, ["index", 30]> >} : () -> () "test.maybe_terminator"() : () -> () }) : () -> () @@ -134,6 +154,7 @@ func.func @nested_combine_with_missing() { "test.op_with_data_layout"() ({ // CHECK: alignment = 20 // CHECK: bitsize = 10 + // CHECK: index = 21 // CHECK: preferred = 30 // CHECK: size = 2 "test.data_layout_query"() : () -> !test.test_type_with_layout<10> @@ -146,13 +167,15 @@ func.func @nested_combine_with_missing() { >} : () -> () // CHECK: alignment = 1 // CHECK: bitsize = 42 + // CHECK: index = 21 // CHECK: preferred = 30 // CHECK: size = 6 "test.data_layout_query"() : () -> !test.test_type_with_layout<10> "test.maybe_terminator"() : () -> () }) { dlti.dl_spec = #dlti.dl_spec< #dlti.dl_entry<!test.test_type_with_layout<10>, ["size", 42]>, - #dlti.dl_entry<!test.test_type_with_layout<30>, ["preferred", 30]> + #dlti.dl_entry<!test.test_type_with_layout<30>, ["preferred", 30]>, + #dlti.dl_entry<!test.test_type_with_layout<40>, ["index", 21]> >}: () -> () return } @@ -164,6 +187,7 @@ func.func @nested_combine_all() { "test.op_with_data_layout"() ({ // CHECK: alignment = 20 // CHECK: bitsize = 3 + // CHECK: index = 40 // CHECK: preferred = 30 // CHECK: size = 1 "test.data_layout_query"() : () -> !test.test_type_with_layout<10> @@ -174,16 +198,19 @@ func.func @nested_combine_all() { >} : () -> () // CHECK: alignment = 20 // CHECK: bitsize = 10 + // CHECK: index = 40 // CHECK: preferred = 30 // CHECK: size = 2 "test.data_layout_query"() : () -> !test.test_type_with_layout<10> "test.maybe_terminator"() : () -> () }) { dlti.dl_spec = #dlti.dl_spec< #dlti.dl_entry<!test.test_type_with_layout<10>, ["size", 10]>, - #dlti.dl_entry<!test.test_type_with_layout<20>, ["alignment", 20]> + #dlti.dl_entry<!test.test_type_with_layout<20>, ["alignment", 20]>, + #dlti.dl_entry<!test.test_type_with_layout<40>, ["index", 40]> >} : () -> () // CHECK: alignment = 1 // CHECK: bitsize = 42 + // CHECK: index = 1 // CHECK: preferred = 30 // CHECK: size = 6 "test.data_layout_query"() : () -> !test.test_type_with_layout<10> @@ -200,18 +227,22 @@ func.func @integers() { "test.op_with_data_layout"() ({ // CHECK: alignment = 8 // CHECK: bitsize = 32 + // CHECK: index = 0 // CHECK: preferred = 8 "test.data_layout_query"() : () -> i32 // CHECK: alignment = 16 // CHECK: bitsize = 56 + // CHECK: index = 0 // CHECK: preferred = 16 "test.data_layout_query"() : () -> i56 // CHECK: alignment = 16 // CHECK: bitsize = 64 + // CHECK: index = 0 // CHECK: preferred = 16 "test.data_layout_query"() : () -> i64 // CHECK: alignment = 16 // CHECK: bitsize = 128 + // CHECK: index = 0 // CHECK: preferred = 16 "test.data_layout_query"() : () -> i128 "test.maybe_terminator"() : () -> () @@ -222,18 +253,22 @@ func.func @integers() { "test.op_with_data_layout"() ({ // CHECK: alignment = 8 // CHECK: bitsize = 32 + // CHECK: index = 0 // CHECK: preferred = 16 "test.data_layout_query"() : () -> i32 // CHECK: alignment = 16 // CHECK: bitsize = 56 + // CHECK: index = 0 // CHECK: preferred = 32 "test.data_layout_query"() : () -> i56 // CHECK: alignment = 16 // CHECK: bitsize = 64 + // CHECK: index = 0 // CHECK: preferred = 32 "test.data_layout_query"() : () -> i64 // CHECK: alignment = 16 // CHECK: bitsize = 128 + // CHECK: index = 0 // CHECK: preferred = 32 "test.data_layout_query"() : () -> i128 "test.maybe_terminator"() : () -> () @@ -248,10 +283,12 @@ func.func @floats() { "test.op_with_data_layout"() ({ // CHECK: alignment = 8 // CHECK: bitsize = 32 + // CHECK: index = 0 // CHECK: preferred = 8 "test.data_layout_query"() : () -> f32 // CHECK: alignment = 16 // CHECK: bitsize = 80 + // CHECK: index = 0 // CHECK: preferred = 16 "test.data_layout_query"() : () -> f80 "test.maybe_terminator"() : () -> () @@ -262,10 +299,12 @@ func.func @floats() { "test.op_with_data_layout"() ({ // CHECK: alignment = 8 // CHECK: bitsize = 32 + // CHECK: index = 0 // CHECK: preferred = 16 "test.data_layout_query"() : () -> f32 // CHECK: alignment = 16 // CHECK: bitsize = 80 + // CHECK: index = 0 // CHECK: preferred = 32 "test.data_layout_query"() : () -> f80 "test.maybe_terminator"() : () -> () diff --git a/mlir/test/Interfaces/DataLayoutInterfaces/types.mlir b/mlir/test/Interfaces/DataLayoutInterfaces/types.mlir index 55bb1d2eac911cd93110b324684673340cd65fa2..82ae02cf92adff5c1ed649c134d9ba5db6ab2aa8 100644 --- a/mlir/test/Interfaces/DataLayoutInterfaces/types.mlir +++ b/mlir/test/Interfaces/DataLayoutInterfaces/types.mlir @@ -40,6 +40,7 @@ module @index attributes { dlti.dl_spec = #dlti.dl_spec< #dlti.dl_entry<index, 32>>} { func.func @query() { // CHECK: bitsize = 32 + // CHECK: index = 32 "test.data_layout_query"() : () -> index return } diff --git a/mlir/test/Target/Cpp/common-cpp.mlir b/mlir/test/Target/Cpp/common-cpp.mlir index a87b33a10844d31875068ba82cd4fbf2a2a4808e..0e24bdd19993f093c95685ea24920029eb421644 100644 --- a/mlir/test/Target/Cpp/common-cpp.mlir +++ b/mlir/test/Target/Cpp/common-cpp.mlir @@ -36,7 +36,7 @@ func.func @test_multiple_return() -> (i32, i32) { // CHECK: test_float func.func @test_float() { - // CHECK: foo::constant({(float)0.0e+00, (float)1.000000000e+00}) + // CHECK: foo::constant({0.0e+00f, 1.000000000e+00f}) %0 = emitc.call_opaque "foo::constant"() {args = [dense<[0.000000e+00, 1.000000e+00]> : tensor<2xf32>]} : () -> f32 return } diff --git a/mlir/test/Target/Cpp/const.mlir b/mlir/test/Target/Cpp/const.mlir index 524d564b3b943e5f8a41d977358f0b95287a748d..3658455d669438a7f78b5a005bf3aa8c5097b325 100644 --- a/mlir/test/Target/Cpp/const.mlir +++ b/mlir/test/Target/Cpp/const.mlir @@ -10,6 +10,7 @@ func.func @emitc_constant() { %c5 = "emitc.constant"(){value = #emitc.opaque<"CHAR_MIN">} : () -> !emitc.opaque<"char"> %c6 = "emitc.constant"(){value = 2 : index} : () -> index %c7 = "emitc.constant"(){value = 2.0 : f32} : () -> f32 + %f64 = "emitc.constant"(){value = 4.0 : f64} : () -> f64 %c8 = "emitc.constant"(){value = dense<0> : tensor<i32>} : () -> tensor<i32> %c9 = "emitc.constant"(){value = dense<[0, 1]> : tensor<2xindex>} : () -> tensor<2xindex> %c10 = "emitc.constant"(){value = dense<[[0.0, 1.0], [2.0, 3.0]]> : tensor<2x2xf32>} : () -> tensor<2x2xf32> @@ -23,10 +24,11 @@ func.func @emitc_constant() { // CPP-DEFAULT-NEXT: uint8_t [[V4:[^ ]*]] = 255; // CPP-DEFAULT-NEXT: char [[V5:[^ ]*]] = CHAR_MIN; // CPP-DEFAULT-NEXT: size_t [[V6:[^ ]*]] = 2; -// CPP-DEFAULT-NEXT: float [[V7:[^ ]*]] = (float)2.000000000e+00; +// CPP-DEFAULT-NEXT: float [[V7:[^ ]*]] = 2.000000000e+00f; +// CPP-DEFAULT-NEXT: double [[F64:[^ ]*]] = 4.00000000000000000e+00; // CPP-DEFAULT-NEXT: Tensor<int32_t> [[V8:[^ ]*]] = {0}; // CPP-DEFAULT-NEXT: Tensor<size_t, 2> [[V9:[^ ]*]] = {0, 1}; -// CPP-DEFAULT-NEXT: Tensor<float, 2, 2> [[V10:[^ ]*]] = {(float)0.0e+00, (float)1.000000000e+00, (float)2.000000000e+00, (float)3.000000000e+00}; +// CPP-DEFAULT-NEXT: Tensor<float, 2, 2> [[V10:[^ ]*]] = {0.0e+00f, 1.000000000e+00f, 2.000000000e+00f, 3.000000000e+00f}; // CPP-DECLTOP: void emitc_constant() { // CPP-DECLTOP-NEXT: int32_t [[V0:[^ ]*]]; @@ -37,6 +39,7 @@ func.func @emitc_constant() { // CPP-DECLTOP-NEXT: char [[V5:[^ ]*]]; // CPP-DECLTOP-NEXT: size_t [[V6:[^ ]*]]; // CPP-DECLTOP-NEXT: float [[V7:[^ ]*]]; +// CPP-DECLTOP-NEXT: double [[F64:[^ ]*]]; // CPP-DECLTOP-NEXT: Tensor<int32_t> [[V8:[^ ]*]]; // CPP-DECLTOP-NEXT: Tensor<size_t, 2> [[V9:[^ ]*]]; // CPP-DECLTOP-NEXT: Tensor<float, 2, 2> [[V10:[^ ]*]]; @@ -47,7 +50,8 @@ func.func @emitc_constant() { // CPP-DECLTOP-NEXT: [[V4]] = 255; // CPP-DECLTOP-NEXT: [[V5]] = CHAR_MIN; // CPP-DECLTOP-NEXT: [[V6]] = 2; -// CPP-DECLTOP-NEXT: [[V7]] = (float)2.000000000e+00; +// CPP-DECLTOP-NEXT: [[V7]] = 2.000000000e+00f; +// CPP-DECLTOP-NEXT: [[F64]] = 4.00000000000000000e+00; // CPP-DECLTOP-NEXT: [[V8]] = {0}; // CPP-DECLTOP-NEXT: [[V9]] = {0, 1}; -// CPP-DECLTOP-NEXT: [[V10]] = {(float)0.0e+00, (float)1.000000000e+00, (float)2.000000000e+00, (float)3.000000000e+00}; +// CPP-DECLTOP-NEXT: [[V10]] = {0.0e+00f, 1.000000000e+00f, 2.000000000e+00f, 3.000000000e+00f}; diff --git a/mlir/test/Target/Cpp/for.mlir b/mlir/test/Target/Cpp/for.mlir index 5225f3ddaff259fbdfb153b50f8baf807d70a5c7..60988bcb4655621992a38783fee68275c347b102 100644 --- a/mlir/test/Target/Cpp/for.mlir +++ b/mlir/test/Target/Cpp/for.mlir @@ -63,7 +63,7 @@ func.func @test_for_yield() { // CPP-DEFAULT-NEXT: size_t [[STOP:[^ ]*]] = 10; // CPP-DEFAULT-NEXT: size_t [[STEP:[^ ]*]] = 1; // CPP-DEFAULT-NEXT: int32_t [[S0:[^ ]*]] = 0; -// CPP-DEFAULT-NEXT: float [[P0:[^ ]*]] = (float)1.000000000e+00; +// CPP-DEFAULT-NEXT: float [[P0:[^ ]*]] = 1.000000000e+00f; // CPP-DEFAULT-NEXT: int32_t [[SE:[^ ]*]]; // CPP-DEFAULT-NEXT: float [[PE:[^ ]*]]; // CPP-DEFAULT-NEXT: int32_t [[SI:[^ ]*]]; @@ -96,7 +96,7 @@ func.func @test_for_yield() { // CPP-DECLTOP-NEXT: [[STOP]] = 10; // CPP-DECLTOP-NEXT: [[STEP]] = 1; // CPP-DECLTOP-NEXT: [[S0]] = 0; -// CPP-DECLTOP-NEXT: [[P0]] = (float)1.000000000e+00; +// CPP-DECLTOP-NEXT: [[P0]] = 1.000000000e+00f; // CPP-DECLTOP-NEXT: ; // CPP-DECLTOP-NEXT: ; // CPP-DECLTOP-NEXT: ; diff --git a/mlir/test/Target/Cpp/invalid.mlir b/mlir/test/Target/Cpp/invalid.mlir index 552c04a9b07f7d1d3fab852210cedb34a634c744..513371a09cde1d2f0af7b2bfa2d9151b36e934c9 100644 --- a/mlir/test/Target/Cpp/invalid.mlir +++ b/mlir/test/Target/Cpp/invalid.mlir @@ -10,10 +10,10 @@ func.func @multiple_blocks() { // ----- -func.func @unsupported_std_op(%arg0: f64) -> f64 { - // expected-error@+1 {{'math.absf' op unable to find printer for op}} - %0 = math.absf %arg0 : f64 - return %0 : f64 +func.func @unsupported_op(%arg0: i1) { + // expected-error@+1 {{'cf.assert' op unable to find printer for op}} + cf.assert %arg0, "assertion foo" + return } // ----- diff --git a/mlir/test/Target/Cpp/stdops.mlir b/mlir/test/Target/Cpp/stdops.mlir index cc6bdbe37698477f529bee9f3cc8ba9fcf4c57f0..589e5f2e96affddd83b41cfebac2ab8cd93f9c4d 100644 --- a/mlir/test/Target/Cpp/stdops.mlir +++ b/mlir/test/Target/Cpp/stdops.mlir @@ -60,14 +60,14 @@ func.func @two_results() -> (i32, f32) { } // CPP-DEFAULT: std::tuple<int32_t, float> two_results() { // CPP-DEFAULT: int32_t [[V0:[^ ]*]] = 0; -// CPP-DEFAULT: float [[V1:[^ ]*]] = (float)1.000000000e+00; +// CPP-DEFAULT: float [[V1:[^ ]*]] = 1.000000000e+00f; // CPP-DEFAULT: return std::make_tuple([[V0]], [[V1]]); // CPP-DECLTOP: std::tuple<int32_t, float> two_results() { // CPP-DECLTOP: int32_t [[V0:[^ ]*]]; // CPP-DECLTOP: float [[V1:[^ ]*]]; // CPP-DECLTOP: [[V0]] = 0; -// CPP-DECLTOP: [[V1]] = (float)1.000000000e+00; +// CPP-DECLTOP: [[V1]] = 1.000000000e+00f; // CPP-DECLTOP: return std::make_tuple([[V0]], [[V1]]); diff --git a/mlir/test/Target/Cpp/subscript.mlir b/mlir/test/Target/Cpp/subscript.mlir new file mode 100644 index 0000000000000000000000000000000000000000..a6c82df9111a7925d1b195dbd4ae91d9c42f039d --- /dev/null +++ b/mlir/test/Target/Cpp/subscript.mlir @@ -0,0 +1,32 @@ +// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s +// RUN: mlir-translate -mlir-to-cpp -declare-variables-at-top %s | FileCheck %s + +func.func @load_store(%arg0: !emitc.array<4x8xf32>, %arg1: !emitc.array<3x5xf32>, %arg2: index, %arg3: index) { + %0 = emitc.subscript %arg0[%arg2, %arg3] : <4x8xf32>, index, index + %1 = emitc.subscript %arg1[%arg2, %arg3] : <3x5xf32>, index, index + emitc.assign %0 : f32 to %1 : f32 + return +} +// CHECK: void load_store(float [[ARR1:[^ ]*]][4][8], float [[ARR2:[^ ]*]][3][5], +// CHECK-SAME: size_t [[I:[^ ]*]], size_t [[J:[^ ]*]]) +// CHECK-NEXT: [[ARR2]][[[I]]][[[J]]] = [[ARR1]][[[I]]][[[J]]]; + +emitc.func @func1(%arg0 : f32) { + emitc.return +} + +emitc.func @call_arg(%arg0: !emitc.array<4x8xf32>, %i: i32, %j: i16, + %k: i8) { + %0 = emitc.subscript %arg0[%i, %j] : <4x8xf32>, i32, i16 + %1 = emitc.subscript %arg0[%j, %k] : <4x8xf32>, i16, i8 + + emitc.call @func1 (%0) : (f32) -> () + emitc.call_opaque "func2" (%1) : (f32) -> () + emitc.call_opaque "func3" (%0, %1) { args = [1 : index, 0 : index] } : (f32, f32) -> () + emitc.return +} +// CHECK: void call_arg(float [[ARR1:[^ ]*]][4][8], int32_t [[I:[^ ]*]], +// CHECK-SAME: int16_t [[J:[^ ]*]], int8_t [[K:[^ ]*]]) +// CHECK-NEXT: func1([[ARR1]][[[I]]][[[J]]]); +// CHECK-NEXT: func2([[ARR1]][[[J]]][[[K]]]); +// CHECK-NEXT: func3([[ARR1]][[[J]]][[[K]]], [[ARR1]][[[I]]][[[J]]]); diff --git a/mlir/test/Target/LLVMIR/Import/basic.ll b/mlir/test/Target/LLVMIR/Import/basic.ll index a059425d978067f46c014ea6e77343a008862246..448b0ebe25746cfd140707660846849f9a329de2 100644 --- a/mlir/test/Target/LLVMIR/Import/basic.ll +++ b/mlir/test/Target/LLVMIR/Import/basic.ll @@ -72,26 +72,26 @@ define i32 @useFreezeOp(i32 %x) { ; Varadic function definition %struct.va_list = type { ptr } -declare void @llvm.va_start(ptr) -declare void @llvm.va_copy(ptr, ptr) -declare void @llvm.va_end(ptr) +declare void @llvm.va_start.p0(ptr) +declare void @llvm.va_copy.p0(ptr, ptr) +declare void @llvm.va_end.p0(ptr) ; CHECK-LABEL: llvm.func @variadic_function define void @variadic_function(i32 %X, ...) { ; CHECK: %[[ALLOCA0:.+]] = llvm.alloca %{{.*}} x !llvm.struct<"struct.va_list", (ptr)> {{.*}} : (i32) -> !llvm.ptr %ap = alloca %struct.va_list ; CHECK: llvm.intr.vastart %[[ALLOCA0]] - call void @llvm.va_start(ptr %ap) + call void @llvm.va_start.p0(ptr %ap) ; CHECK: %[[ALLOCA1:.+]] = llvm.alloca %{{.*}} x !llvm.ptr {{.*}} : (i32) -> !llvm.ptr %aq = alloca ptr ; CHECK: llvm.intr.vacopy %[[ALLOCA0]] to %[[ALLOCA1]] - call void @llvm.va_copy(ptr %aq, ptr %ap) + call void @llvm.va_copy.p0(ptr %aq, ptr %ap) ; CHECK: llvm.intr.vaend %[[ALLOCA1]] - call void @llvm.va_end(ptr %aq) + call void @llvm.va_end.p0(ptr %aq) ; CHECK: llvm.intr.vaend %[[ALLOCA0]] - call void @llvm.va_end(ptr %ap) + call void @llvm.va_end.p0(ptr %ap) ; CHECK: llvm.return ret void } diff --git a/mlir/test/Target/LLVMIR/Import/debug-info.ll b/mlir/test/Target/LLVMIR/Import/debug-info.ll index 9ef6580bcf2408e1f7828dad0e3741f27e8a498b..959a5a1cd97176fd36833f952bb6e86b040111ab 100644 --- a/mlir/test/Target/LLVMIR/Import/debug-info.ll +++ b/mlir/test/Target/LLVMIR/Import/debug-info.ll @@ -136,7 +136,7 @@ define void @basic_type() !dbg !3 { ; CHECK: #[[INT:.+]] = #llvm.di_basic_type<tag = DW_TAG_base_type, name = "int"> ; CHECK: #[[PTR1:.+]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type, baseType = #[[INT]]> -; CHECK: #[[PTR2:.+]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type, name = "mypointer", baseType = #[[INT]], sizeInBits = 64, alignInBits = 32, offsetInBits = 4> +; CHECK: #[[PTR2:.+]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type, name = "mypointer", baseType = #[[INT]], sizeInBits = 64, alignInBits = 32, offsetInBits = 4, extraData = #[[INT]]> ; CHECK: #llvm.di_subroutine_type<types = #[[PTR1]], #[[PTR2]]> define void @derived_type() !dbg !3 { @@ -153,7 +153,7 @@ define void @derived_type() !dbg !3 { !5 = !{!7, !8} !6 = !DIBasicType(name: "int") !7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6) -!8 = !DIDerivedType(name: "mypointer", tag: DW_TAG_pointer_type, baseType: !6, size: 64, align: 32, offset: 4) +!8 = !DIDerivedType(name: "mypointer", tag: DW_TAG_pointer_type, baseType: !6, size: 64, align: 32, offset: 4, extraData: !6) ; // ----- @@ -296,12 +296,17 @@ define void @class_method() { ret void, !dbg !9 } -; Verify the elements parameter is dropped due to the cyclic dependencies. -; CHECK: #[[COMP:.+]] = #llvm.di_composite_type<tag = DW_TAG_class_type, name = "class_name", file = #{{.*}}, line = 42, flags = "TypePassByReference|NonTrivial"> -; CHECK: #[[COMP_PTR:.+]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type, baseType = #[[COMP]], sizeInBits = 64> +; Verify the cyclic composite type is identified, even though conversion begins from the subprogram type. +; CHECK: #[[COMP_SELF:.+]] = #llvm.di_composite_type<tag = DW_TAG_null, recId = [[REC_ID:.+]]> +; CHECK: #[[COMP_PTR:.+]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type, baseType = #[[COMP_SELF]], sizeInBits = 64> ; CHECK: #[[SP_TYPE:.+]] = #llvm.di_subroutine_type<types = #{{.*}}, #[[COMP_PTR]]> -; CHECK: #[[SP:.+]] = #llvm.di_subprogram<id = distinct[{{.*}}]<>, compileUnit = #{{.*}}, scope = #[[COMP]], name = "class_method", file = #{{.*}}, subprogramFlags = Definition, type = #[[SP_TYPE]]> -; CHECK: #[[LOC]] = loc(fused<#[[SP]]> +; CHECK: #[[SP_INNER:.+]] = #llvm.di_subprogram<id = [[SP_ID:.+]], compileUnit = #{{.*}}, scope = #[[COMP_SELF]], name = "class_method", file = #{{.*}}, subprogramFlags = Definition, type = #[[SP_TYPE]]> +; CHECK: #[[COMP:.+]] = #llvm.di_composite_type<tag = DW_TAG_class_type, recId = [[REC_ID]], name = "class_name", file = #{{.*}}, line = 42, flags = "TypePassByReference|NonTrivial", elements = #[[SP_INNER]]> + +; CHECK: #[[COMP_PTR_OUTER:.+]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type, baseType = #[[COMP]], sizeInBits = 64> +; CHECK: #[[SP_TYPE_OUTER:.+]] = #llvm.di_subroutine_type<types = #{{.*}}, #[[COMP_PTR_OUTER]]> +; CHECK: #[[SP_OUTER:.+]] = #llvm.di_subprogram<id = [[SP_ID]], compileUnit = #{{.*}}, scope = #[[COMP]], name = "class_method", file = #{{.*}}, subprogramFlags = Definition, type = #[[SP_TYPE_OUTER]]> +; CHECK: #[[LOC]] = loc(fused<#[[SP_OUTER]]> !llvm.dbg.cu = !{!1} !llvm.module.flags = !{!0} @@ -318,15 +323,18 @@ define void @class_method() { ; // ----- -; Verify the elements parameter is dropped due to the cyclic dependencies. -; CHECK: #[[$COMP:.+]] = #llvm.di_composite_type<tag = DW_TAG_class_type, name = "class_field", file = #{{.*}}, line = 42, flags = "TypePassByReference|NonTrivial"> -; CHECK: #[[$COMP_PTR:.+]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type, baseType = #[[$COMP]]> -; CHECK: #[[$VAR0:.+]] = #llvm.di_local_variable<scope = #{{.*}}, name = "class_field", file = #{{.*}}, type = #[[$COMP_PTR]]> +; Verify the cyclic composite type is handled correctly. +; CHECK: #[[COMP_SELF:.+]] = #llvm.di_composite_type<tag = DW_TAG_null, recId = [[REC_ID:.+]]> +; CHECK: #[[COMP_PTR_INNER:.+]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type, baseType = #[[COMP_SELF]]> +; CHECK: #[[FIELD:.+]] = #llvm.di_derived_type<tag = DW_TAG_member, name = "call_field", baseType = #[[COMP_PTR_INNER]]> +; CHECK: #[[COMP:.+]] = #llvm.di_composite_type<tag = DW_TAG_class_type, recId = [[REC_ID]], name = "class_field", file = #{{.*}}, line = 42, flags = "TypePassByReference|NonTrivial", elements = #[[FIELD]]> +; CHECK: #[[COMP_PTR_OUTER:.+]] = #llvm.di_derived_type<tag = DW_TAG_pointer_type, baseType = #[[COMP]]> +; CHECK: #[[VAR0:.+]] = #llvm.di_local_variable<scope = #{{.*}}, name = "class_field", file = #{{.*}}, type = #[[COMP_PTR_OUTER]]> -; CHECK-LABEL: @class_field +; CHECK: @class_field ; CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]] define void @class_field(ptr %arg1) { - ; CHECK: llvm.intr.dbg.value #[[$VAR0]] = %[[ARG0]] : !llvm.ptr + ; CHECK: llvm.intr.dbg.value #[[VAR0]] = %[[ARG0]] : !llvm.ptr call void @llvm.dbg.value(metadata ptr %arg1, metadata !7, metadata !DIExpression()), !dbg !9 ret void } @@ -563,35 +571,6 @@ define void @func_in_module(ptr %arg) !dbg !8 { ; // ----- -; Verifies that array types that have an unimportable base type are removed to -; avoid producing invalid IR. -; CHECK: #[[DI_LOCAL_VAR:.+]] = #llvm.di_local_variable< -; CHECK-NOT: type = - -; CHECK-LABEL: @array_with_cyclic_base_type -define i32 @array_with_cyclic_base_type(ptr %0) !dbg !3 { - call void @llvm.dbg.value(metadata ptr %0, metadata !4, metadata !DIExpression()), !dbg !7 - ret i32 0 -} - -; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none) -declare void @llvm.dbg.value(metadata, metadata, metadata) - - -!llvm.module.flags = !{!0} -!llvm.dbg.cu = !{!1} - -!0 = !{i32 2, !"Debug Info Version", i32 3} -!1 = distinct !DICompileUnit(language: DW_LANG_C, file: !2) -!2 = !DIFile(filename: "debug-info.ll", directory: "/") -!3 = distinct !DISubprogram(name: "func", scope: !2, file: !2, line: 46, scopeLine: 48, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !1) -!4 = !DILocalVariable(name: "op", arg: 5, scope: !3, file: !2, line: 47, type: !5) -!5 = !DICompositeType(tag: DW_TAG_array_type, size: 42, baseType: !6) -!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5) -!7 = !DILocation(line: 0, scope: !3) - -; // ----- - ; Verifies that import compile units respect the distinctness of the input. ; CHECK-LABEL: @distinct_cu_func0 define void @distinct_cu_func0() !dbg !4 { @@ -622,8 +601,9 @@ declare !dbg !1 void @declaration() ; CHECK: #di_subprogram = #llvm.di_subprogram< ; CHECK-NOT: id = distinct +; CHECK-NOT: subprogramFlags = !llvm.module.flags = !{!0} !0 = !{i32 2, !"Debug Info Version", i32 3} -!1 = !DISubprogram(name: "declaration", scope: !2, file: !2, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized) +!1 = !DISubprogram(name: "declaration", scope: !2, file: !2, flags: DIFlagPrototyped, spFlags: 0) !2 = !DIFile(filename: "debug-info.ll", directory: "/") diff --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll index 9a4e939d106516fdb4984537edb16d2e081c729c..3f4efab70e1c02e55919d60720b76203abe3097c 100644 --- a/mlir/test/Target/LLVMIR/Import/import-failure.ll +++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll @@ -85,38 +85,6 @@ define void @unsupported_argument(i64 %arg1) { ; // ----- -; Check that debug intrinsics that depend on cyclic metadata are dropped. - -declare void @llvm.dbg.value(metadata, metadata, metadata) - -; CHECK: import-failure.ll -; CHECK-SAME: warning: dropped instruction: call void @llvm.dbg.label(metadata !{{.*}}) -; CHECK: import-failure.ll -; CHECK-SAME: warning: dropped intrinsic: call void @llvm.dbg.value(metadata i64 %{{.*}}, metadata !3, metadata !DIExpression()) -define void @cylic_metadata(i64 %arg1) { - call void @llvm.dbg.value(metadata i64 %arg1, metadata !10, metadata !DIExpression()), !dbg !14 - call void @llvm.dbg.label(metadata !13), !dbg !14 - ret void -} - -!llvm.dbg.cu = !{!1} -!llvm.module.flags = !{!0} -!0 = !{i32 2, !"Debug Info Version", i32 3} -!1 = distinct !DICompileUnit(language: DW_LANG_C, file: !2) -!2 = !DIFile(filename: "import-failure.ll", directory: "/") -!3 = !DICompositeType(tag: DW_TAG_array_type, size: 42, baseType: !4) -!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !3) -!5 = distinct !DISubprogram(name: "class_method", scope: !2, file: !2, type: !6, spFlags: DISPFlagDefinition, unit: !1) -!6 = !DISubroutineType(types: !7) -!7 = !{!3} -!10 = !DILocalVariable(scope: !5, name: "arg1", file: !2, line: 1, arg: 1, align: 64); -!11 = !DILexicalBlock(scope: !5) -!12 = !DILexicalBlockFile(scope: !11, discriminator: 0) -!13 = !DILabel(scope: !12, name: "label", file: !2, line: 42) -!14 = !DILocation(line: 1, column: 2, scope: !5) - -; // ----- - ; global_dtors with non-null data fields cannot be represented in MLIR. ; CHECK: <unknown> ; CHECK-SAME: error: unhandled global variable: @llvm.global_dtors diff --git a/mlir/test/Target/LLVMIR/Import/intrinsic.ll b/mlir/test/Target/LLVMIR/Import/intrinsic.ll index 1ec9005458c50b7aead51ba1a4473c736dd12e7e..0cefb4f8983aa6c3778a2205bc5d315fc4b4b0f2 100644 --- a/mlir/test/Target/LLVMIR/Import/intrinsic.ll +++ b/mlir/test/Target/LLVMIR/Import/intrinsic.ll @@ -599,11 +599,11 @@ define void @ushl_sat_test(i32 %0, i32 %1, <8 x i32> %2, <8 x i32> %3) { ; CHECK-LABEL: llvm.func @va_intrinsics_test define void @va_intrinsics_test(ptr %0, ptr %1) { ; CHECK: llvm.intr.vastart %{{.*}} - call void @llvm.va_start(ptr %0) + call void @llvm.va_start.p0(ptr %0) ; CHECK: llvm.intr.vacopy %{{.*}} to %{{.*}} - call void @llvm.va_copy(ptr %1, ptr %0) + call void @llvm.va_copy.p0(ptr %1, ptr %0) ; CHECK: llvm.intr.vaend %{{.*}} - call void @llvm.va_end(ptr %0) + call void @llvm.va_end.p0(ptr %0) ret void } @@ -894,6 +894,23 @@ define float @ssa_copy(float %0) { ret float %2 } +; CHECK-LABEL: experimental_constrained_fptrunc +define void @experimental_constrained_fptrunc(double %s, <4 x double> %v) { + ; CHECK: llvm.intr.experimental.constrained.fptrunc %{{.*}} towardzero ignore : f64 to f32 + %1 = call float @llvm.experimental.constrained.fptrunc.f32.f64(double %s, metadata !"round.towardzero", metadata !"fpexcept.ignore") + ; CHECK: llvm.intr.experimental.constrained.fptrunc %{{.*}} tonearest maytrap : f64 to f32 + %2 = call float @llvm.experimental.constrained.fptrunc.f32.f64(double %s, metadata !"round.tonearest", metadata !"fpexcept.maytrap") + ; CHECK: llvm.intr.experimental.constrained.fptrunc %{{.*}} upward strict : f64 to f32 + %3 = call float @llvm.experimental.constrained.fptrunc.f32.f64(double %s, metadata !"round.upward", metadata !"fpexcept.strict") + ; CHECK: llvm.intr.experimental.constrained.fptrunc %{{.*}} downward ignore : f64 to f32 + %4 = call float @llvm.experimental.constrained.fptrunc.f32.f64(double %s, metadata !"round.downward", metadata !"fpexcept.ignore") + ; CHECK: llvm.intr.experimental.constrained.fptrunc %{{.*}} tonearestaway ignore : f64 to f32 + %5 = call float @llvm.experimental.constrained.fptrunc.f32.f64(double %s, metadata !"round.tonearestaway", metadata !"fpexcept.ignore") + ; CHECK: llvm.intr.experimental.constrained.fptrunc %{{.*}} tonearestaway ignore : vector<4xf64> to vector<4xf16> + %6 = call <4 x half> @llvm.experimental.constrained.fptrunc.v4f16.v4f64(<4 x double> %v, metadata !"round.tonearestaway", metadata !"fpexcept.ignore") + ret void +} + declare float @llvm.fmuladd.f32(float, float, float) declare <8 x float> @llvm.fmuladd.v8f32(<8 x float>, <8 x float>, <8 x float>) declare float @llvm.fma.f32(float, float, float) @@ -1059,9 +1076,9 @@ declare ptr @llvm.stacksave.p0() declare ptr addrspace(1) @llvm.stacksave.p1() declare void @llvm.stackrestore.p0(ptr) declare void @llvm.stackrestore.p1(ptr addrspace(1)) -declare void @llvm.va_start(ptr) -declare void @llvm.va_copy(ptr, ptr) -declare void @llvm.va_end(ptr) +declare void @llvm.va_start.p0(ptr) +declare void @llvm.va_copy.p0(ptr, ptr) +declare void @llvm.va_end.p0(ptr) declare <8 x i32> @llvm.vp.add.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) declare <8 x i32> @llvm.vp.sub.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) declare <8 x i32> @llvm.vp.mul.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) @@ -1120,3 +1137,5 @@ declare void @llvm.assume(i1) declare float @llvm.ssa.copy.f32(float returned) declare <vscale x 4 x float> @llvm.vector.insert.nxv4f32.v4f32(<vscale x 4 x float>, <4 x float>, i64) declare <4 x float> @llvm.vector.extract.v4f32.nxv4f32(<vscale x 4 x float>, i64) +declare <4 x half> @llvm.experimental.constrained.fptrunc.v4f16.v4f64(<4 x double>, metadata, metadata) +declare float @llvm.experimental.constrained.fptrunc.f32.f64(double, metadata, metadata) diff --git a/mlir/test/Target/LLVMIR/data-layout.mlir b/mlir/test/Target/LLVMIR/data-layout.mlir index e61972a0dd9764663137f4d27b7b472f71c4f592..881d6727e2a17a1146e41cd87b71604b50b7ad02 100644 --- a/mlir/test/Target/LLVMIR/data-layout.mlir +++ b/mlir/test/Target/LLVMIR/data-layout.mlir @@ -6,7 +6,7 @@ // CHECK: S128- // CHECK: i64:64:128 // CHECK: f80:128:256 -// CHECK: p0:32:64:128 +// CHECK: p0:32:64:128:32 // CHECK: p1:32:32:32:16 module attributes {dlti.dl_spec = #dlti.dl_spec< #dlti.dl_entry<"dlti.endianness", "big">, diff --git a/mlir/test/Target/LLVMIR/llvmir-debug.mlir b/mlir/test/Target/LLVMIR/llvmir-debug.mlir index cfd5239515c9c02b5a3e0bbeb1d8302219b4db35..785a525caab8c287d03a404582e646f76f8cb8be 100644 --- a/mlir/test/Target/LLVMIR/llvmir-debug.mlir +++ b/mlir/test/Target/LLVMIR/llvmir-debug.mlir @@ -28,7 +28,8 @@ llvm.func @func_no_debug() { > #ptr = #llvm.di_derived_type< tag = DW_TAG_pointer_type, baseType = #si32, - sizeInBits = 64, alignInBits = 32, offsetInBits = 8 + sizeInBits = 64, alignInBits = 32, offsetInBits = 8, + extraData = #si32 > #named = #llvm.di_derived_type< // Specify the name parameter. @@ -135,7 +136,7 @@ llvm.func @empty_types() { // CHECK: ![[FUNC_TYPE]] = !DISubroutineType(cc: DW_CC_normal, types: ![[FUNC_ARGS:.*]]) // CHECK: ![[FUNC_ARGS]] = !{null, ![[ARG_TYPE:.*]], ![[PTR_TYPE:.*]], ![[NAMED_TYPE:.*]], ![[COMPOSITE_TYPE:.*]], ![[VECTOR_TYPE:.*]]} // CHECK: ![[ARG_TYPE]] = !DIBasicType(name: "si64") -// CHECK: ![[PTR_TYPE]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[BASE_TYPE:.*]], size: 64, align: 32, offset: 8) +// CHECK: ![[PTR_TYPE]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[BASE_TYPE:.*]], size: 64, align: 32, offset: 8, extraData: ![[BASE_TYPE]]) // CHECK: ![[BASE_TYPE]] = !DIBasicType(name: "si32", size: 32, encoding: DW_ATE_signed) // CHECK: ![[NAMED_TYPE]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "named", baseType: ![[BASE_TYPE:.*]]) // CHECK: ![[COMPOSITE_TYPE]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "composite", file: ![[CU_FILE_LOC]], line: 42, size: 64, align: 32, elements: ![[COMPOSITE_ELEMENTS:.*]]) @@ -171,14 +172,14 @@ llvm.func @empty_types() { #di_file = #llvm.di_file<"foo.mlir" in "/test/"> #di_subprogram = #llvm.di_subprogram< - scope = #di_file, name = "func_decl_with_subprogram", file = #di_file, subprogramFlags = "Optimized" + scope = #di_file, name = "func_decl_with_subprogram", file = #di_file > // CHECK-LABEL: declare !dbg // CHECK-SAME: ![[SUBPROGRAM:.*]] i32 @func_decl_with_subprogram( llvm.func @func_decl_with_subprogram() -> (i32) loc(fused<#di_subprogram>["foo.mlir":2:1]) -// CHECK: ![[SUBPROGRAM]] = !DISubprogram(name: "func_decl_with_subprogram", scope: ![[FILE:.*]], file: ![[FILE]], spFlags: DISPFlagOptimized) +// CHECK: ![[SUBPROGRAM]] = !DISubprogram(name: "func_decl_with_subprogram", scope: ![[FILE:.*]], file: ![[FILE]], spFlags: 0) // CHECK: ![[FILE]] = !DIFile(filename: "foo.mlir", directory: "/test/") // ----- @@ -342,3 +343,83 @@ llvm.func @func_line_tables() { llvm.func @func_debug_directives() { llvm.return } loc(fused<#di_subprogram_2>["foo2.mlir":0:0]) + +// ----- + +// Ensure recursive types with multiple external references work. + +// Common base nodes. +#di_file = #llvm.di_file<"test.mlir" in "/"> +#di_null_type = #llvm.di_null_type +#di_compile_unit = #llvm.di_compile_unit<id = distinct[1]<>, sourceLanguage = DW_LANG_C, file = #di_file, isOptimized = false, emissionKind = None> + +// Recursive type itself. +#di_struct_self = #llvm.di_composite_type<tag = DW_TAG_null, recId = distinct[0]<>> +#di_ptr_inner = #llvm.di_derived_type<tag = DW_TAG_pointer_type, baseType = #di_struct_self, sizeInBits = 64> +#di_subroutine_inner = #llvm.di_subroutine_type<types = #di_null_type, #di_ptr_inner> +#di_subprogram_inner = #llvm.di_subprogram< + id = distinct[2]<>, + compileUnit = #di_compile_unit, + scope = #di_struct_self, + name = "class_method", + file = #di_file, + subprogramFlags = Definition, + type = #di_subroutine_inner> +#di_struct = #llvm.di_composite_type< + tag = DW_TAG_class_type, + recId = distinct[0]<>, + name = "class_name", + file = #di_file, + line = 42, + flags = "TypePassByReference|NonTrivial", + elements = #di_subprogram_inner> + +// Outer types referencing the entire recursive type. +#di_ptr_outer = #llvm.di_derived_type<tag = DW_TAG_pointer_type, baseType = #di_struct, sizeInBits = 64> +#di_subroutine_outer = #llvm.di_subroutine_type<types = #di_null_type, #di_ptr_outer> +#di_subprogram_outer = #llvm.di_subprogram< + id = distinct[2]<>, + compileUnit = #di_compile_unit, + scope = #di_struct, + name = "class_method", + file = #di_file, + subprogramFlags = Definition, + type = #di_subroutine_outer> + +#loc3 = loc(fused<#di_subprogram_outer>["test.mlir":1:1]) + +// CHECK: @class_method +// CHECK: ret void, !dbg ![[LOC:.*]] + +// CHECK: ![[CU:.*]] = distinct !DICompileUnit( +// CHECK: ![[SP:.*]] = distinct !DISubprogram(name: "class_method", scope: ![[STRUCT:.*]], file: !{{.*}}, type: ![[SUBROUTINE:.*]], spFlags: DISPFlagDefinition, unit: ![[CU]]) +// CHECK: ![[STRUCT]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "class_name", {{.*}}, elements: ![[ELEMS:.*]]) +// CHECK: ![[ELEMS]] = !{![[SP]]} +// CHECK: ![[SUBROUTINE]] = !DISubroutineType(types: ![[SUBROUTINE_ELEMS:.*]]) +// CHECK: ![[SUBROUTINE_ELEMS]] = !{null, ![[PTR:.*]]} +// CHECK: ![[PTR]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[STRUCT]], size: 64) +// CHECK: ![[LOC]] = !DILocation(line: 1, column: 1, scope: ![[SP]]) + +llvm.func @class_method() { + llvm.return loc(#loc3) +} loc(#loc3) + +// ----- + +// Ensures composite types with a recursive scope work. + +#di_composite_type_self = #llvm.di_composite_type<tag = DW_TAG_null, recId = distinct[0]<>> +#di_file = #llvm.di_file<"test.mlir" in "/"> +#di_subroutine_type = #llvm.di_subroutine_type<types = #di_composite_type_self> +#di_subprogram = #llvm.di_subprogram<scope = #di_file, file = #di_file, subprogramFlags = Optimized, type = #di_subroutine_type> +#di_composite_type = #llvm.di_composite_type<tag = DW_TAG_class_type, recId = distinct[0]<>, scope = #di_subprogram> +#di_global_variable = #llvm.di_global_variable<file = #di_file, line = 1, type = #di_composite_type> +#di_global_variable_expression = #llvm.di_global_variable_expression<var = #di_global_variable> + +llvm.mlir.global @global_variable() {dbg_expr = #di_global_variable_expression} : !llvm.struct<()> + +// CHECK: distinct !DIGlobalVariable({{.*}}type: ![[COMP:[0-9]+]], +// CHECK: ![[COMP]] = distinct !DICompositeType({{.*}}scope: ![[SCOPE:[0-9]+]], +// CHECK: ![[SCOPE]] = !DISubprogram({{.*}}type: ![[SUBROUTINE:[0-9]+]], +// CHECK: ![[SUBROUTINE]] = !DISubroutineType(types: ![[SR_TYPES:[0-9]+]]) +// CHECK: ![[SR_TYPES]] = !{![[COMP]]} diff --git a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir index fc2e0fd201a73876a23b3481de8f546537687014..0013522582a727971776849f9c453baebd62cd5a 100644 --- a/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir +++ b/mlir/test/Target/LLVMIR/llvmir-intrinsics.mlir @@ -964,6 +964,35 @@ llvm.func @ssa_copy(%arg: f32) -> f32 { llvm.return %0 : f32 } +// CHECK-LABEL: @experimental_constrained_fptrunc +llvm.func @experimental_constrained_fptrunc(%s: f64, %v: vector<4xf32>) { + // CHECK: call float @llvm.experimental.constrained.fptrunc.f32.f64( + // CHECK: metadata !"round.towardzero" + // CHECK: metadata !"fpexcept.ignore" + %0 = llvm.intr.experimental.constrained.fptrunc %s towardzero ignore : f64 to f32 + // CHECK: call float @llvm.experimental.constrained.fptrunc.f32.f64( + // CHECK: metadata !"round.tonearest" + // CHECK: metadata !"fpexcept.maytrap" + %1 = llvm.intr.experimental.constrained.fptrunc %s tonearest maytrap : f64 to f32 + // CHECK: call float @llvm.experimental.constrained.fptrunc.f32.f64( + // CHECK: metadata !"round.upward" + // CHECK: metadata !"fpexcept.strict" + %2 = llvm.intr.experimental.constrained.fptrunc %s upward strict : f64 to f32 + // CHECK: call float @llvm.experimental.constrained.fptrunc.f32.f64( + // CHECK: metadata !"round.downward" + // CHECK: metadata !"fpexcept.ignore" + %3 = llvm.intr.experimental.constrained.fptrunc %s downward ignore : f64 to f32 + // CHECK: call float @llvm.experimental.constrained.fptrunc.f32.f64( + // CHECK: metadata !"round.tonearestaway" + // CHECK: metadata !"fpexcept.ignore" + %4 = llvm.intr.experimental.constrained.fptrunc %s tonearestaway ignore : f64 to f32 + // CHECK: call <4 x half> @llvm.experimental.constrained.fptrunc.v4f16.v4f32( + // CHECK: metadata !"round.upward" + // CHECK: metadata !"fpexcept.strict" + %5 = llvm.intr.experimental.constrained.fptrunc %v upward strict : vector<4xf32> to vector<4xf16> + llvm.return +} + // Check that intrinsics are declared with appropriate types. // CHECK-DAG: declare float @llvm.fma.f32(float, float, float) // CHECK-DAG: declare <8 x float> @llvm.fma.v8f32(<8 x float>, <8 x float>, <8 x float>) #0 @@ -1126,3 +1155,5 @@ llvm.func @ssa_copy(%arg: f32) -> f32 { // CHECK-DAG: declare ptr addrspace(1) @llvm.stacksave.p1() // CHECK-DAG: declare void @llvm.stackrestore.p0(ptr) // CHECK-DAG: declare void @llvm.stackrestore.p1(ptr addrspace(1)) +// CHECK-DAG: declare float @llvm.experimental.constrained.fptrunc.f32.f64(double, metadata, metadata) +// CHECK-DAG: declare <4 x half> @llvm.experimental.constrained.fptrunc.v4f16.v4f32(<4 x float>, metadata, metadata) diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir index c38c7ea587d25b787c500b90affcb3e14f1a27ae..97f37939551d837323fab4f61e70c45a8a9badf2 100644 --- a/mlir/test/Target/LLVMIR/llvmir.mlir +++ b/mlir/test/Target/LLVMIR/llvmir.mlir @@ -2251,14 +2251,14 @@ llvm.func @vararg_function(%arg0: i32, ...) { %1 = llvm.mlir.constant(1 : i32) : i32 // CHECK: %[[ALLOCA0:.+]] = alloca %struct.va_list, align 8 %2 = llvm.alloca %1 x !llvm.struct<"struct.va_list", (ptr)> {alignment = 8 : i64} : (i32) -> !llvm.ptr - // CHECK: call void @llvm.va_start(ptr %[[ALLOCA0]]) + // CHECK: call void @llvm.va_start.p0(ptr %[[ALLOCA0]]) llvm.intr.vastart %2 : !llvm.ptr // CHECK: %[[ALLOCA1:.+]] = alloca ptr, align 8 %4 = llvm.alloca %0 x !llvm.ptr {alignment = 8 : i64} : (i32) -> !llvm.ptr - // CHECK: call void @llvm.va_copy(ptr %[[ALLOCA1]], ptr %[[ALLOCA0]]) + // CHECK: call void @llvm.va_copy.p0(ptr %[[ALLOCA1]], ptr %[[ALLOCA0]]) llvm.intr.vacopy %2 to %4 : !llvm.ptr, !llvm.ptr - // CHECK: call void @llvm.va_end(ptr %[[ALLOCA1]]) - // CHECK: call void @llvm.va_end(ptr %[[ALLOCA0]]) + // CHECK: call void @llvm.va_end.p0(ptr %[[ALLOCA1]]) + // CHECK: call void @llvm.va_end.p0(ptr %[[ALLOCA0]]) llvm.intr.vaend %4 : !llvm.ptr llvm.intr.vaend %2 : !llvm.ptr // CHECK: ret void diff --git a/mlir/test/Target/LLVMIR/omptarget-array-sectioning-host.mlir b/mlir/test/Target/LLVMIR/omptarget-array-sectioning-host.mlir index 307d8a02ce61dafbfa5d92d083fc723dbe29e3ad..08ccbf04014a9b3b21070dcc3a7a44e64e93f119 100644 --- a/mlir/test/Target/LLVMIR/omptarget-array-sectioning-host.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-array-sectioning-host.mlir @@ -14,10 +14,10 @@ module attributes {omp.is_target_device = false} { %2 = llvm.mlir.constant(1 : index) : i64 %3 = llvm.mlir.constant(0 : index) : i64 %4 = llvm.mlir.constant(2 : index) : i64 - %5 = omp.bounds lower_bound(%3 : i64) upper_bound(%4 : i64) stride(%2 : i64) start_idx(%2 : i64) - %6 = omp.bounds lower_bound(%2 : i64) upper_bound(%2 : i64) stride(%2 : i64) start_idx(%2 : i64) - %7 = omp.map_info var_ptr(%0 : !llvm.ptr, !llvm.array<3 x array<3 x array<3 x i32>>>) map_clauses(tofrom) capture(ByRef) bounds(%5, %5, %6) -> !llvm.ptr {name = "inarray(1:3,1:3,2:2)"} - %8 = omp.map_info var_ptr(%1 : !llvm.ptr, !llvm.array<3 x array<3 x array<3 x i32>>>) map_clauses(tofrom) capture(ByRef) bounds(%5, %5, %5) -> !llvm.ptr {name = "outarray(1:3,1:3,1:3)"} + %5 = omp.map.bounds lower_bound(%3 : i64) upper_bound(%4 : i64) stride(%2 : i64) start_idx(%2 : i64) + %6 = omp.map.bounds lower_bound(%2 : i64) upper_bound(%2 : i64) stride(%2 : i64) start_idx(%2 : i64) + %7 = omp.map.info var_ptr(%0 : !llvm.ptr, !llvm.array<3 x array<3 x array<3 x i32>>>) map_clauses(tofrom) capture(ByRef) bounds(%5, %5, %6) -> !llvm.ptr {name = "inarray(1:3,1:3,2:2)"} + %8 = omp.map.info var_ptr(%1 : !llvm.ptr, !llvm.array<3 x array<3 x array<3 x i32>>>) map_clauses(tofrom) capture(ByRef) bounds(%5, %5, %5) -> !llvm.ptr {name = "outarray(1:3,1:3,1:3)"} omp.target map_entries(%7 -> %arg0, %8 -> %arg1 : !llvm.ptr, !llvm.ptr) { ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr): %9 = llvm.mlir.constant(0 : i64) : i64 diff --git a/mlir/test/Target/LLVMIR/omptarget-byref-bycopy-generation-device.mlir b/mlir/test/Target/LLVMIR/omptarget-byref-bycopy-generation-device.mlir index 875d04f584ca96fafb11bd750db00a18f13c0fad..5931da7582fd78cb960c615dff02c6ed8049de88 100644 --- a/mlir/test/Target/LLVMIR/omptarget-byref-bycopy-generation-device.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-byref-bycopy-generation-device.mlir @@ -4,8 +4,8 @@ module attributes {omp.is_target_device = true} { llvm.func @_QQmain() attributes {fir.bindc_name = "main"} { %0 = llvm.mlir.addressof @_QFEi : !llvm.ptr %1 = llvm.mlir.addressof @_QFEsp : !llvm.ptr - %2 = omp.map_info var_ptr(%1 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = "sp"} - %3 = omp.map_info var_ptr(%0 : !llvm.ptr, i32) map_clauses(to) capture(ByCopy) -> !llvm.ptr {name = "i"} + %2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = "sp"} + %3 = omp.map.info var_ptr(%0 : !llvm.ptr, i32) map_clauses(to) capture(ByCopy) -> !llvm.ptr {name = "i"} omp.target map_entries(%2 -> %arg0, %3 -> %arg1 : !llvm.ptr, !llvm.ptr) { ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr): %4 = llvm.load %arg1 : !llvm.ptr -> i32 diff --git a/mlir/test/Target/LLVMIR/omptarget-byref-bycopy-generation-host.mlir b/mlir/test/Target/LLVMIR/omptarget-byref-bycopy-generation-host.mlir index c8fb4e232f06f5092cb40f546f683ac8dbf3346f..8635ea49567067f1fdbae062f7ea9da38250026d 100644 --- a/mlir/test/Target/LLVMIR/omptarget-byref-bycopy-generation-host.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-byref-bycopy-generation-host.mlir @@ -4,8 +4,8 @@ module attributes {omp.is_target_device = false} { llvm.func @_QQmain() attributes {fir.bindc_name = "main"} { %0 = llvm.mlir.addressof @_QFEi : !llvm.ptr %1 = llvm.mlir.addressof @_QFEsp : !llvm.ptr - %2 = omp.map_info var_ptr(%1 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = "sp"} - %3 = omp.map_info var_ptr(%0 : !llvm.ptr, i32) map_clauses(to) capture(ByCopy) -> !llvm.ptr {name = "i"} + %2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = "sp"} + %3 = omp.map.info var_ptr(%0 : !llvm.ptr, i32) map_clauses(to) capture(ByCopy) -> !llvm.ptr {name = "i"} omp.target map_entries(%2 -> %arg0, %3 -> %arg1 : !llvm.ptr, !llvm.ptr) { ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr): %4 = llvm.load %arg1 : !llvm.ptr -> i32 diff --git a/mlir/test/Target/LLVMIR/omptarget-constant-alloca-raise.mlir b/mlir/test/Target/LLVMIR/omptarget-constant-alloca-raise.mlir index be521fbe1f01a6dd36c29a222c76a7f695fff737..7a785301eb16b6bd00decdcc4ef23f779ecb4a53 100644 --- a/mlir/test/Target/LLVMIR/omptarget-constant-alloca-raise.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-constant-alloca-raise.mlir @@ -14,7 +14,7 @@ module attributes {omp.is_target_device = true} { llvm.func @_QQmain() attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>} { %1 = llvm.mlir.constant(1 : i64) : i64 %2 = llvm.alloca %1 x !llvm.struct<(ptr)> : (i64) -> !llvm.ptr - %3 = omp.map_info var_ptr(%2 : !llvm.ptr, !llvm.struct<(ptr)>) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr + %3 = omp.map.info var_ptr(%2 : !llvm.ptr, !llvm.struct<(ptr)>) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr omp.target map_entries(%3 -> %arg0 : !llvm.ptr) { ^bb0(%arg0: !llvm.ptr): %4 = llvm.mlir.constant(1 : i32) : i32 diff --git a/mlir/test/Target/LLVMIR/omptarget-constant-indexing-device-region.mlir b/mlir/test/Target/LLVMIR/omptarget-constant-indexing-device-region.mlir index 5c0ac79271a693806d081e59184ed5434eec60a3..be8145dc9075ecfe367fb563e7cd6d3f08551288 100644 --- a/mlir/test/Target/LLVMIR/omptarget-constant-indexing-device-region.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-constant-indexing-device-region.mlir @@ -7,8 +7,8 @@ module attributes {omp.is_target_device = true} { %2 = llvm.mlir.constant(1 : index) : i64 %3 = llvm.mlir.constant(0 : index) : i64 %4 = llvm.mlir.constant(9 : index) : i64 - %5 = omp.bounds lower_bound(%3 : i64) upper_bound(%4 : i64) extent(%1 : i64) stride(%2 : i64) start_idx(%2 : i64) - %6 = omp.map_info var_ptr(%0 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%5) -> !llvm.ptr {name = "sp"} + %5 = omp.map.bounds lower_bound(%3 : i64) upper_bound(%4 : i64) extent(%1 : i64) stride(%2 : i64) start_idx(%2 : i64) + %6 = omp.map.info var_ptr(%0 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%5) -> !llvm.ptr {name = "sp"} omp.target map_entries(%6 -> %arg0 : !llvm.ptr) { ^bb0(%arg0: !llvm.ptr): %7 = llvm.mlir.constant(20 : i32) : i32 diff --git a/mlir/test/Target/LLVMIR/omptarget-declare-target-llvm-device.mlir b/mlir/test/Target/LLVMIR/omptarget-declare-target-llvm-device.mlir index cf08761981fb3a8fb303d8ddca9f842bc2597d8b..bb32000cc9457f0b13b9fb187f67779a762d0a85 100644 --- a/mlir/test/Target/LLVMIR/omptarget-declare-target-llvm-device.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-declare-target-llvm-device.mlir @@ -21,7 +21,7 @@ module attributes {omp.is_target_device = true} { // CHECK-DAG: %[[V:.*]] = load ptr, ptr @_QMtest_0Esp_decl_tgt_ref_ptr, align 8 // CHECK-DAG: store i32 1, ptr %[[V]], align 4 // CHECK-DAG: br label %omp.region.cont - %map = omp.map_info var_ptr(%0 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %map = omp.map.info var_ptr(%0 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} omp.target map_entries(%map -> %arg0 : !llvm.ptr) { ^bb0(%arg0: !llvm.ptr): %1 = llvm.mlir.constant(1 : i32) : i32 diff --git a/mlir/test/Target/LLVMIR/omptarget-fortran-allocatable-types-host.mlir b/mlir/test/Target/LLVMIR/omptarget-fortran-allocatable-types-host.mlir index 831cd05871c4e4fccc67670a9e7037c242383274..7cb22dbb10b18c9ce0d7873af9482c80d7c5b0fc 100644 --- a/mlir/test/Target/LLVMIR/omptarget-fortran-allocatable-types-host.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-fortran-allocatable-types-host.mlir @@ -3,7 +3,7 @@ // This test checks the offload sizes, map types and base pointers and pointers // provided to the OpenMP kernel argument structure are correct when lowering // to LLVM-IR from MLIR when the fortran allocatables flag is switched on and -// a fortran allocatable descriptor type is provided alongside the omp.map_info, +// a fortran allocatable descriptor type is provided alongside the omp.map.info, // the test utilises mapping of array sections, full arrays and individual // allocated scalars. @@ -24,10 +24,10 @@ module attributes {omp.is_target_device = false} { %12 = llvm.getelementptr %3[0, 7, %7, 2] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> %13 = llvm.load %12 : !llvm.ptr -> i64 %14 = llvm.sub %11, %2 : i64 - %15 = omp.bounds lower_bound(%7 : i64) upper_bound(%14 : i64) extent(%11 : i64) stride(%13 : i64) start_idx(%9 : i64) {stride_in_bytes = true} + %15 = omp.map.bounds lower_bound(%7 : i64) upper_bound(%14 : i64) extent(%11 : i64) stride(%13 : i64) start_idx(%9 : i64) {stride_in_bytes = true} %16 = llvm.getelementptr %3[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> - %17 = omp.map_info var_ptr(%16 : !llvm.ptr, f32) map_clauses(tofrom) capture(ByRef) bounds(%15) -> !llvm.ptr {name = "full_arr"} - %18 = omp.map_info var_ptr(%3 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>) map_clauses(tofrom) capture(ByRef) members(%17 : !llvm.ptr) -> !llvm.ptr {name = "full_arr"} + %17 = omp.map.info var_ptr(%3 : !llvm.ptr, f32) var_ptr_ptr(%16 : !llvm.ptr) map_clauses(tofrom) capture(ByRef) bounds(%15) -> !llvm.ptr {name = "full_arr"} + %18 = omp.map.info var_ptr(%3 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>) map_clauses(tofrom) capture(ByRef) members(%17 : !llvm.ptr) -> !llvm.ptr {name = "full_arr"} %19 = llvm.getelementptr %6[0, 7, %7, 0] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> %20 = llvm.load %19 : !llvm.ptr -> i64 %21 = llvm.getelementptr %6[0, 7, %7, 1] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> @@ -36,13 +36,13 @@ module attributes {omp.is_target_device = false} { %24 = llvm.load %23 : !llvm.ptr -> i64 %25 = llvm.sub %1, %20 : i64 %26 = llvm.sub %0, %20 : i64 - %27 = omp.bounds lower_bound(%25 : i64) upper_bound(%26 : i64) extent(%22 : i64) stride(%24 : i64) start_idx(%20 : i64) {stride_in_bytes = true} + %27 = omp.map.bounds lower_bound(%25 : i64) upper_bound(%26 : i64) extent(%22 : i64) stride(%24 : i64) start_idx(%20 : i64) {stride_in_bytes = true} %28 = llvm.getelementptr %6[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> - %29 = omp.map_info var_ptr(%6 : !llvm.ptr, i32) var_ptr_ptr(%28 : !llvm.ptr) map_clauses(tofrom) capture(ByRef) bounds(%27) -> !llvm.ptr {name = "sect_arr(2:5)"} - %30 = omp.map_info var_ptr(%6 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>) map_clauses(tofrom) capture(ByRef) members(%29 : !llvm.ptr) -> !llvm.ptr {name = "sect_arr(2:5)"} + %29 = omp.map.info var_ptr(%6 : !llvm.ptr, i32) var_ptr_ptr(%28 : !llvm.ptr) map_clauses(tofrom) capture(ByRef) bounds(%27) -> !llvm.ptr {name = "sect_arr(2:5)"} + %30 = omp.map.info var_ptr(%6 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)>) map_clauses(tofrom) capture(ByRef) members(%29 : !llvm.ptr) -> !llvm.ptr {name = "sect_arr(2:5)"} %31 = llvm.getelementptr %5[0, 0] : (!llvm.ptr) -> !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)> - %32 = omp.map_info var_ptr(%5 : !llvm.ptr, f32) var_ptr_ptr(%31 : !llvm.ptr) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = "scalar"} - %33 = omp.map_info var_ptr(%5 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) map_clauses(tofrom) capture(ByRef) members(%32 : !llvm.ptr) -> !llvm.ptr {name = "scalar"} + %32 = omp.map.info var_ptr(%5 : !llvm.ptr, f32) var_ptr_ptr(%31 : !llvm.ptr) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = "scalar"} + %33 = omp.map.info var_ptr(%5 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) map_clauses(tofrom) capture(ByRef) members(%32 : !llvm.ptr) -> !llvm.ptr {name = "scalar"} omp.target map_entries(%17 -> %arg0, %18 -> %arg1, %29 -> %arg2, %30 -> %arg3, %32 -> %arg4, %33 -> %arg5 : !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) { ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr, %arg3: !llvm.ptr, %arg4: !llvm.ptr, %arg5: !llvm.ptr): omp.terminator @@ -81,20 +81,19 @@ module attributes {omp.is_target_device = false} { // CHECK: %[[ARR_SECT_SIZE2:.*]] = add i64 %[[ARR_SECT_SIZE3]], 1 // CHECK: %[[ARR_SECT_SIZE1:.*]] = mul i64 1, %[[ARR_SECT_SIZE2]] // CHECK: %[[ARR_SECT_SIZE:.*]] = mul i64 %[[ARR_SECT_SIZE1]], 4 -// CHECK: %[[FULL_ARR_DESC_SIZE:.*]] = sdiv exact i64 sub (i64 ptrtoint (ptr getelementptr inbounds ({ ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr @_QFEfull_arr, i32 1) to i64), i64 ptrtoint (ptr @_QFEfull_arr to i64)), ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) // CHECK: %[[LFULL_ARR:.*]] = load ptr, ptr @_QFEfull_arr, align 8 // CHECK: %[[FULL_ARR_PTR:.*]] = getelementptr inbounds float, ptr %[[LFULL_ARR]], i64 0 -// CHECK: %[[ARR_SECT_DESC_SIZE:.*]] = sdiv exact i64 sub (i64 ptrtoint (ptr getelementptr inbounds ({ ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr @_QFEsect_arr, i32 1) to i64), i64 ptrtoint (ptr @_QFEsect_arr to i64)), ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) // CHECK: %[[ARR_SECT_OFFSET1:.*]] = mul i64 %[[ARR_SECT_OFFSET2]], 1 // CHECK: %[[LARR_SECT:.*]] = load ptr, ptr @_QFEsect_arr, align 8 // CHECK: %[[ARR_SECT_PTR:.*]] = getelementptr inbounds i32, ptr %[[LARR_SECT]], i64 %[[ARR_SECT_OFFSET1]] +// CHECK: %[[SCALAR_PTR_LOAD:.*]] = load ptr, ptr %[[SCALAR_BASE]], align 8 +// CHECK: %[[FULL_ARR_DESC_SIZE:.*]] = sdiv exact i64 sub (i64 ptrtoint (ptr getelementptr inbounds ({ ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr @_QFEfull_arr, i32 1) to i64), i64 ptrtoint (ptr @_QFEfull_arr to i64)), ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) +// CHECK: %[[ARR_SECT_DESC_SIZE:.*]] = sdiv exact i64 sub (i64 ptrtoint (ptr getelementptr inbounds ({ ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr @_QFEsect_arr, i32 1) to i64), i64 ptrtoint (ptr @_QFEsect_arr to i64)), ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) // CHECK: %[[SCALAR_DESC_SZ4:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8 }, ptr %[[SCALAR_ALLOCA]], i32 1 // CHECK: %[[SCALAR_DESC_SZ3:.*]] = ptrtoint ptr %[[SCALAR_DESC_SZ4]] to i64 // CHECK: %[[SCALAR_DESC_SZ2:.*]] = ptrtoint ptr %[[SCALAR_ALLOCA]] to i64 // CHECK: %[[SCALAR_DESC_SZ1:.*]] = sub i64 %[[SCALAR_DESC_SZ3]], %[[SCALAR_DESC_SZ2]] // CHECK: %[[SCALAR_DESC_SZ:.*]] = sdiv exact i64 %[[SCALAR_DESC_SZ1]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64) -// CHECK: %[[SCALAR_PTR_LOAD:.*]] = load ptr, ptr %[[SCALAR_BASE]], align 8 -// CHECK: %[[SCALAR_PTR:.*]] = getelementptr inbounds float, ptr %[[SCALAR_PTR_LOAD]], i64 0 // CHECK: %[[OFFLOADBASEPTRS:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 // CHECK: store ptr @_QFEfull_arr, ptr %[[OFFLOADBASEPTRS]], align 8 @@ -145,4 +144,4 @@ module attributes {omp.is_target_device = false} { // CHECK: %[[OFFLOADBASEPTRS:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_baseptrs, i32 0, i32 8 // CHECK: store ptr %[[SCALAR_BASE]], ptr %[[OFFLOADBASEPTRS]], align 8 // CHECK: %[[OFFLOADPTRS:.*]] = getelementptr inbounds [9 x ptr], ptr %.offload_ptrs, i32 0, i32 8 -// CHECK: store ptr %[[SCALAR_PTR]], ptr %[[OFFLOADPTRS]], align 8 +// CHECK: store ptr %[[SCALAR_PTR_LOAD]], ptr %[[OFFLOADPTRS]], align 8 diff --git a/mlir/test/Target/LLVMIR/omptarget-llvm.mlir b/mlir/test/Target/LLVMIR/omptarget-llvm.mlir index b089d47f795df355046878367f1d29b19067d043..2f629675442d0c75cc6e1f9ca59ad610857be249 100644 --- a/mlir/test/Target/LLVMIR/omptarget-llvm.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-llvm.mlir @@ -3,7 +3,7 @@ llvm.func @_QPopenmp_target_data() { %0 = llvm.mlir.constant(1 : i64) : i64 %1 = llvm.alloca %0 x i32 {bindc_name = "i", in_type = i32, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFopenmp_target_dataEi"} : (i64) -> !llvm.ptr - %2 = omp.map_info var_ptr(%1 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} omp.target_data map_entries(%2 : !llvm.ptr) { %3 = llvm.mlir.constant(99 : i32) : i32 llvm.store %3, %1 : i32, !llvm.ptr @@ -43,8 +43,8 @@ llvm.func @_QPopenmp_target_data_region(%0 : !llvm.ptr) { %2 = llvm.mlir.constant(0 : index) : i64 %3 = llvm.mlir.constant(1024 : index) : i64 %4 = llvm.mlir.constant(1 : index) : i64 - %5 = omp.bounds lower_bound(%2 : i64) upper_bound(%1 : i64) extent(%3 : i64) stride(%4 : i64) start_idx(%4 : i64) - %6 = omp.map_info var_ptr(%0 : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(from) capture(ByRef) bounds(%5) -> !llvm.ptr {name = ""} + %5 = omp.map.bounds lower_bound(%2 : i64) upper_bound(%1 : i64) extent(%3 : i64) stride(%4 : i64) start_idx(%4 : i64) + %6 = omp.map.info var_ptr(%0 : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(from) capture(ByRef) bounds(%5) -> !llvm.ptr {name = ""} omp.target_data map_entries(%6 : !llvm.ptr) { %7 = llvm.mlir.constant(99 : i32) : i32 %8 = llvm.mlir.constant(1 : i64) : i64 @@ -66,16 +66,17 @@ llvm.func @_QPopenmp_target_data_region(%0 : !llvm.ptr) { // CHECK: %[[VAL_2:.*]] = alloca [1 x ptr], align 8 // CHECK: br label %[[VAL_3:.*]] // CHECK: entry: ; preds = %[[VAL_4:.*]] +// CHECK: %[[ARR_OFFSET:.*]] = getelementptr inbounds [1024 x i32], ptr %[[ARR_DATA:.*]], i64 0, i64 0 // CHECK: %[[VAL_5:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0 -// CHECK: store ptr %[[VAL_6:.*]], ptr %[[VAL_5]], align 8 +// CHECK: store ptr %[[ARR_DATA]], ptr %[[VAL_5]], align 8 // CHECK: %[[VAL_7:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0 -// CHECK: store ptr %[[VAL_6]], ptr %[[VAL_7]], align 8 +// CHECK: store ptr %[[ARR_OFFSET]], ptr %[[VAL_7]], align 8 // CHECK: %[[VAL_8:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_2]], i64 0, i64 0 // CHECK: store ptr null, ptr %[[VAL_8]], align 8 // CHECK: %[[VAL_9:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0 // CHECK: %[[VAL_10:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0 // CHECK: call void @__tgt_target_data_begin_mapper(ptr @2, i64 -1, i32 1, ptr %[[VAL_9]], ptr %[[VAL_10]], ptr @.offload_sizes, ptr @.offload_maptypes, ptr @.offload_mapnames, ptr null) -// CHECK: %[[VAL_11:.*]] = getelementptr [1024 x i32], ptr %[[VAL_6]], i32 0, i64 0 +// CHECK: %[[VAL_11:.*]] = getelementptr [1024 x i32], ptr %[[ARR_DATA]], i32 0, i64 0 // CHECK: store i32 99, ptr %[[VAL_11]], align 4 // CHECK: %[[VAL_12:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_0]], i32 0, i32 0 // CHECK: %[[VAL_13:.*]] = getelementptr inbounds [1 x ptr], ptr %[[VAL_1]], i32 0, i32 0 @@ -101,14 +102,14 @@ llvm.func @_QPomp_target_enter_exit(%1 : !llvm.ptr, %3 : !llvm.ptr) { %15 = llvm.mlir.constant(0 : index) : i64 %16 = llvm.mlir.constant(1024 : index) : i64 %17 = llvm.mlir.constant(1 : index) : i64 - %18 = omp.bounds lower_bound(%15 : i64) upper_bound(%14 : i64) extent(%16 : i64) stride(%17 : i64) start_idx(%17 : i64) - %map1 = omp.map_info var_ptr(%1 : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(to) capture(ByRef) bounds(%18) -> !llvm.ptr {name = ""} + %18 = omp.map.bounds lower_bound(%15 : i64) upper_bound(%14 : i64) extent(%16 : i64) stride(%17 : i64) start_idx(%17 : i64) + %map1 = omp.map.info var_ptr(%1 : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(to) capture(ByRef) bounds(%18) -> !llvm.ptr {name = ""} %19 = llvm.mlir.constant(511 : index) : i64 %20 = llvm.mlir.constant(0 : index) : i64 %21 = llvm.mlir.constant(512 : index) : i64 %22 = llvm.mlir.constant(1 : index) : i64 - %23 = omp.bounds lower_bound(%20 : i64) upper_bound(%19 : i64) extent(%21 : i64) stride(%22 : i64) start_idx(%22 : i64) - %map2 = omp.map_info var_ptr(%3 : !llvm.ptr, !llvm.array<512 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%23) -> !llvm.ptr {name = ""} + %23 = omp.map.bounds lower_bound(%20 : i64) upper_bound(%19 : i64) extent(%21 : i64) stride(%22 : i64) start_idx(%22 : i64) + %map2 = omp.map.info var_ptr(%3 : !llvm.ptr, !llvm.array<512 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%23) -> !llvm.ptr {name = ""} omp.target_enter_data if(%12 : i1) device(%13 : i32) map_entries(%map1, %map2 : !llvm.ptr, !llvm.ptr) %24 = llvm.load %7 : !llvm.ptr -> i32 %25 = llvm.mlir.constant(10 : i32) : i32 @@ -118,14 +119,14 @@ llvm.func @_QPomp_target_enter_exit(%1 : !llvm.ptr, %3 : !llvm.ptr) { %29 = llvm.mlir.constant(0 : index) : i64 %30 = llvm.mlir.constant(1024 : index) : i64 %31 = llvm.mlir.constant(1 : index) : i64 - %32 = omp.bounds lower_bound(%29 : i64) upper_bound(%28 : i64) extent(%30 : i64) stride(%31 : i64) start_idx(%31 : i64) - %map3 = omp.map_info var_ptr(%1 : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(from) capture(ByRef) bounds(%32) -> !llvm.ptr {name = ""} + %32 = omp.map.bounds lower_bound(%29 : i64) upper_bound(%28 : i64) extent(%30 : i64) stride(%31 : i64) start_idx(%31 : i64) + %map3 = omp.map.info var_ptr(%1 : !llvm.ptr, !llvm.array<1024 x i32>) map_clauses(from) capture(ByRef) bounds(%32) -> !llvm.ptr {name = ""} %33 = llvm.mlir.constant(511 : index) : i64 %34 = llvm.mlir.constant(0 : index) : i64 %35 = llvm.mlir.constant(512 : index) : i64 %36 = llvm.mlir.constant(1 : index) : i64 - %37 = omp.bounds lower_bound(%34 : i64) upper_bound(%33 : i64) extent(%35 : i64) stride(%36 : i64) start_idx(%36 : i64) - %map4 = omp.map_info var_ptr(%3 : !llvm.ptr, !llvm.array<512 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%37) -> !llvm.ptr {name = ""} + %37 = omp.map.bounds lower_bound(%34 : i64) upper_bound(%33 : i64) extent(%35 : i64) stride(%36 : i64) start_idx(%36 : i64) + %map4 = omp.map.info var_ptr(%3 : !llvm.ptr, !llvm.array<512 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) bounds(%37) -> !llvm.ptr {name = ""} omp.target_exit_data if(%26 : i1) device(%27 : i32) map_entries(%map3, %map4 : !llvm.ptr, !llvm.ptr) llvm.return } @@ -153,16 +154,18 @@ llvm.func @_QPomp_target_enter_exit(%1 : !llvm.ptr, %3 : !llvm.ptr) { // CHECK: entry: ; preds = %[[VAL_12:.*]] // CHECK: br i1 %[[VAL_9]], label %[[VAL_13:.*]], label %[[VAL_14:.*]] // CHECK: omp_if.then: ; preds = %[[VAL_11]] +// CHECK: %[[ARR_OFFSET1:.*]] = getelementptr inbounds [1024 x i32], ptr %[[VAL_16:.*]], i64 0, i64 0 +// CHECK: %[[ARR_OFFSET2:.*]] = getelementptr inbounds [512 x i32], ptr %[[VAL_20:.*]], i64 0, i64 0 // CHECK: %[[VAL_15:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_3]], i32 0, i32 0 // CHECK: store ptr %[[VAL_16:.*]], ptr %[[VAL_15]], align 8 // CHECK: %[[VAL_17:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_4]], i32 0, i32 0 -// CHECK: store ptr %[[VAL_16]], ptr %[[VAL_17]], align 8 +// CHECK: store ptr %[[ARR_OFFSET1]], ptr %[[VAL_17]], align 8 // CHECK: %[[VAL_18:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_5]], i64 0, i64 0 // CHECK: store ptr null, ptr %[[VAL_18]], align 8 // CHECK: %[[VAL_19:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_3]], i32 0, i32 1 // CHECK: store ptr %[[VAL_20:.*]], ptr %[[VAL_19]], align 8 // CHECK: %[[VAL_21:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_4]], i32 0, i32 1 -// CHECK: store ptr %[[VAL_20]], ptr %[[VAL_21]], align 8 +// CHECK: store ptr %[[ARR_OFFSET2]], ptr %[[VAL_21]], align 8 // CHECK: %[[VAL_22:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_5]], i64 0, i64 1 // CHECK: store ptr null, ptr %[[VAL_22]], align 8 // CHECK: %[[VAL_23:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_3]], i32 0, i32 0 @@ -176,26 +179,28 @@ llvm.func @_QPomp_target_enter_exit(%1 : !llvm.ptr, %3 : !llvm.ptr) { // CHECK: %[[VAL_27:.*]] = icmp sgt i32 %[[VAL_26]], 10 // CHECK: %[[VAL_28:.*]] = load i32, ptr %[[VAL_6]], align 4 // CHECK: br i1 %[[VAL_27]], label %[[VAL_29:.*]], label %[[VAL_30:.*]] -// CHECK: omp_if.then1: ; preds = %[[VAL_25]] +// CHECK: omp_if.then2: ; preds = %[[VAL_25]] +// CHECK: %[[ARR_OFFSET3:.*]] = getelementptr inbounds [1024 x i32], ptr %[[VAL_16]], i64 0, i64 0 +// CHECK: %[[ARR_OFFSET4:.*]] = getelementptr inbounds [512 x i32], ptr %[[VAL_20]], i64 0, i64 0 // CHECK: %[[VAL_31:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0 // CHECK: store ptr %[[VAL_16]], ptr %[[VAL_31]], align 8 // CHECK: %[[VAL_32:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0 -// CHECK: store ptr %[[VAL_16]], ptr %[[VAL_32]], align 8 +// CHECK: store ptr %[[ARR_OFFSET3]], ptr %[[VAL_32]], align 8 // CHECK: %[[VAL_33:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_2]], i64 0, i64 0 // CHECK: store ptr null, ptr %[[VAL_33]], align 8 // CHECK: %[[VAL_34:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 1 // CHECK: store ptr %[[VAL_20]], ptr %[[VAL_34]], align 8 // CHECK: %[[VAL_35:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 1 -// CHECK: store ptr %[[VAL_20]], ptr %[[VAL_35]], align 8 +// CHECK: store ptr %[[ARR_OFFSET4]], ptr %[[VAL_35]], align 8 // CHECK: %[[VAL_36:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_2]], i64 0, i64 1 // CHECK: store ptr null, ptr %[[VAL_36]], align 8 // CHECK: %[[VAL_37:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_0]], i32 0, i32 0 // CHECK: %[[VAL_38:.*]] = getelementptr inbounds [2 x ptr], ptr %[[VAL_1]], i32 0, i32 0 // CHECK: call void @__tgt_target_data_end_mapper(ptr @3, i64 -1, i32 2, ptr %[[VAL_37]], ptr %[[VAL_38]], ptr @.offload_sizes.1, ptr @.offload_maptypes.2, ptr @.offload_mapnames.3, ptr null) // CHECK: br label %[[VAL_39:.*]] -// CHECK: omp_if.else5: ; preds = %[[VAL_25]] +// CHECK: omp_if.else8: ; preds = %[[VAL_25]] // CHECK: br label %[[VAL_39]] -// CHECK: omp_if.end6: ; preds = %[[VAL_30]], %[[VAL_29]] +// CHECK: omp_if.end9: ; preds = %[[VAL_30]], %[[VAL_29]] // CHECK: ret void // ----- @@ -203,7 +208,7 @@ llvm.func @_QPomp_target_enter_exit(%1 : !llvm.ptr, %3 : !llvm.ptr) { llvm.func @_QPopenmp_target_use_dev_ptr() { %0 = llvm.mlir.constant(1 : i64) : i64 %a = llvm.alloca %0 x !llvm.ptr : (i64) -> !llvm.ptr - %map1 = omp.map_info var_ptr(%a : !llvm.ptr, !llvm.ptr) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""} + %map1 = omp.map.info var_ptr(%a : !llvm.ptr, !llvm.ptr) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""} omp.target_data map_entries(%map1 : !llvm.ptr) use_device_ptr(%a : !llvm.ptr) { ^bb0(%arg0: !llvm.ptr): %1 = llvm.mlir.constant(10 : i32) : i32 @@ -247,7 +252,7 @@ llvm.func @_QPopenmp_target_use_dev_ptr() { llvm.func @_QPopenmp_target_use_dev_addr() { %0 = llvm.mlir.constant(1 : i64) : i64 %a = llvm.alloca %0 x !llvm.ptr : (i64) -> !llvm.ptr - %map = omp.map_info var_ptr(%a : !llvm.ptr, !llvm.ptr) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""} + %map = omp.map.info var_ptr(%a : !llvm.ptr, !llvm.ptr) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""} omp.target_data map_entries(%map : !llvm.ptr) use_device_addr(%a : !llvm.ptr) { ^bb0(%arg0: !llvm.ptr): %1 = llvm.mlir.constant(10 : i32) : i32 @@ -289,7 +294,7 @@ llvm.func @_QPopenmp_target_use_dev_addr() { llvm.func @_QPopenmp_target_use_dev_addr_no_ptr() { %0 = llvm.mlir.constant(1 : i64) : i64 %a = llvm.alloca %0 x i32 : (i64) -> !llvm.ptr - %map = omp.map_info var_ptr(%a : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %map = omp.map.info var_ptr(%a : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} omp.target_data map_entries(%map : !llvm.ptr) use_device_addr(%a : !llvm.ptr) { ^bb0(%arg0: !llvm.ptr): %1 = llvm.mlir.constant(10 : i32) : i32 @@ -331,7 +336,7 @@ llvm.func @_QPopenmp_target_use_dev_addr_nomap() { %a = llvm.alloca %0 x !llvm.ptr : (i64) -> !llvm.ptr %1 = llvm.mlir.constant(1 : i64) : i64 %b = llvm.alloca %0 x !llvm.ptr : (i64) -> !llvm.ptr - %map = omp.map_info var_ptr(%b : !llvm.ptr, !llvm.ptr) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""} + %map = omp.map.info var_ptr(%b : !llvm.ptr, !llvm.ptr) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""} omp.target_data map_entries(%map : !llvm.ptr) use_device_addr(%a : !llvm.ptr) { ^bb0(%arg0: !llvm.ptr): %2 = llvm.mlir.constant(10 : i32) : i32 @@ -387,8 +392,8 @@ llvm.func @_QPopenmp_target_use_dev_both() { %a = llvm.alloca %0 x !llvm.ptr : (i64) -> !llvm.ptr %1 = llvm.mlir.constant(1 : i64) : i64 %b = llvm.alloca %0 x !llvm.ptr : (i64) -> !llvm.ptr - %map = omp.map_info var_ptr(%a : !llvm.ptr, !llvm.ptr) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} - %map1 = omp.map_info var_ptr(%b : !llvm.ptr, !llvm.ptr) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %map = omp.map.info var_ptr(%a : !llvm.ptr, !llvm.ptr) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %map1 = omp.map.info var_ptr(%b : !llvm.ptr, !llvm.ptr) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} omp.target_data map_entries(%map, %map1 : !llvm.ptr, !llvm.ptr) use_device_ptr(%a : !llvm.ptr) use_device_addr(%b : !llvm.ptr) { ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr): %2 = llvm.mlir.constant(10 : i32) : i32 @@ -445,14 +450,14 @@ llvm.func @_QPopenmp_target_use_dev_both() { llvm.func @_QPopenmp_target_data_update() { %0 = llvm.mlir.constant(1 : i64) : i64 %1 = llvm.alloca %0 x i32 {bindc_name = "i", in_type = i32, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFopenmp_target_dataEi"} : (i64) -> !llvm.ptr - %2 = omp.map_info var_ptr(%1 : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""} + %2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""} omp.target_data map_entries(%2 : !llvm.ptr) { %3 = llvm.mlir.constant(99 : i32) : i32 llvm.store %3, %1 : i32, !llvm.ptr omp.terminator } - omp.target_update_data motion_entries(%2 : !llvm.ptr) + omp.target_update motion_entries(%2 : !llvm.ptr) llvm.return } diff --git a/mlir/test/Target/LLVMIR/omptarget-nowait-llvm.mlir b/mlir/test/Target/LLVMIR/omptarget-nowait-llvm.mlir index 50c2f0702e63e89f6230c81525983010605cf764..f0d88f5c13536fa3382e39c89166b7d5288dc061 100644 --- a/mlir/test/Target/LLVMIR/omptarget-nowait-llvm.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-nowait-llvm.mlir @@ -3,10 +3,10 @@ llvm.func @_QPopenmp_target_data_update() { %0 = llvm.mlir.constant(1 : i64) : i64 %1 = llvm.alloca %0 x i32 {bindc_name = "i", in_type = i32, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFopenmp_target_dataEi"} : (i64) -> !llvm.ptr - %2 = omp.map_info var_ptr(%1 : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""} + %2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""} // CHECK: error: `nowait` is not supported yet - omp.target_update_data motion_entries(%2 : !llvm.ptr) nowait + omp.target_update motion_entries(%2 : !llvm.ptr) nowait llvm.return } @@ -16,7 +16,7 @@ llvm.func @_QPopenmp_target_data_update() { llvm.func @_QPopenmp_target_data_enter() { %0 = llvm.mlir.constant(1 : i64) : i64 %1 = llvm.alloca %0 x i32 {bindc_name = "i", in_type = i32, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFopenmp_target_dataEi"} : (i64) -> !llvm.ptr - %2 = omp.map_info var_ptr(%1 : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""} + %2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""} // CHECK: error: `nowait` is not supported yet omp.target_enter_data map_entries(%2 : !llvm.ptr) nowait @@ -30,7 +30,7 @@ llvm.func @_QPopenmp_target_data_enter() { llvm.func @_QPopenmp_target_data_exit() { %0 = llvm.mlir.constant(1 : i64) : i64 %1 = llvm.alloca %0 x i32 {bindc_name = "i", in_type = i32, operand_segment_sizes = array<i32: 0, 0>, uniq_name = "_QFopenmp_target_dataEi"} : (i64) -> !llvm.ptr - %2 = omp.map_info var_ptr(%1 : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""} + %2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""} // CHECK: error: `nowait` is not supported yet omp.target_exit_data map_entries(%2 : !llvm.ptr) nowait diff --git a/mlir/test/Target/LLVMIR/omptarget-parallel-llvm.mlir b/mlir/test/Target/LLVMIR/omptarget-parallel-llvm.mlir index 6c148944e034c75c3320d4cc24b151f2ee1391e1..f22bc12d6b94c2945e4a4e86b680e839c880d4a2 100644 --- a/mlir/test/Target/LLVMIR/omptarget-parallel-llvm.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-parallel-llvm.mlir @@ -5,7 +5,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memory_space", 5 : ui32>>, llvm.data_layout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9", llvm.target_triple = "amdgcn-amd-amdhsa", omp.is_gpu = true, omp.is_target_device = true} { llvm.func @_QQmain_omp_outline_1(%arg0: !llvm.ptr) attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>} { - %0 = omp.map_info var_ptr(%arg0 : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = "d"} + %0 = omp.map.info var_ptr(%arg0 : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = "d"} omp.target map_entries(%0 -> %arg2 : !llvm.ptr) { ^bb0(%arg2: !llvm.ptr): omp.parallel { @@ -19,7 +19,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo } llvm.func @_test_num_threads(%arg0: !llvm.ptr) attributes {omp.declare_target = #omp.declaretarget<device_type = (host), capture_clause = (to)>} { - %0 = omp.map_info var_ptr(%arg0 : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = "d"} + %0 = omp.map.info var_ptr(%arg0 : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = "d"} omp.target map_entries(%0 -> %arg2 : !llvm.ptr) { ^bb0(%arg2: !llvm.ptr): %1 = llvm.mlir.constant(156 : i32) : i32 @@ -36,8 +36,8 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo llvm.func @parallel_if(%arg0: !llvm.ptr {fir.bindc_name = "ifcond"}) { %0 = llvm.mlir.constant(1 : i64) : i64 %1 = llvm.alloca %0 x i32 {bindc_name = "d"} : (i64) -> !llvm.ptr - %2 = omp.map_info var_ptr(%1 : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = "d"} - %3 = omp.map_info var_ptr(%arg0 : !llvm.ptr, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !llvm.ptr {name = "ifcond"} + %2 = omp.map.info var_ptr(%1 : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = "d"} + %3 = omp.map.info var_ptr(%arg0 : !llvm.ptr, i32) map_clauses(implicit, exit_release_or_enter_alloc) capture(ByCopy) -> !llvm.ptr {name = "ifcond"} omp.target map_entries(%2 -> %arg1, %3 -> %arg2 : !llvm.ptr, !llvm.ptr) { ^bb0(%arg1: !llvm.ptr, %arg2: !llvm.ptr): %4 = llvm.mlir.constant(10 : i32) : i32 diff --git a/mlir/test/Target/LLVMIR/omptarget-region-device-llvm.mlir b/mlir/test/Target/LLVMIR/omptarget-region-device-llvm.mlir index f537eb5c3f572b41d79c87407acc298fe08dc4cf..ca8a2e6a5b98c8e01e010b64a77b0179b8cc478f 100644 --- a/mlir/test/Target/LLVMIR/omptarget-region-device-llvm.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-region-device-llvm.mlir @@ -12,9 +12,9 @@ module attributes {omp.is_target_device = true} { %7 = llvm.alloca %6 x i32 {bindc_name = "c", in_type = i32, operandSegmentSizes = array<i32: 0, 0>, uniq_name = "_QFomp_target_regionEc"} : (i64) -> !llvm.ptr llvm.store %1, %3 : i32, !llvm.ptr llvm.store %0, %5 : i32, !llvm.ptr - %map1 = omp.map_info var_ptr(%3 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} - %map2 = omp.map_info var_ptr(%5 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} - %map3 = omp.map_info var_ptr(%7 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %map1 = omp.map.info var_ptr(%3 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %map2 = omp.map.info var_ptr(%5 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %map3 = omp.map.info var_ptr(%7 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} omp.target map_entries(%map1 -> %arg0, %map2 -> %arg1, %map3 -> %arg2 : !llvm.ptr, !llvm.ptr, !llvm.ptr) { ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr): %8 = llvm.load %arg0 : !llvm.ptr -> i32 diff --git a/mlir/test/Target/LLVMIR/omptarget-region-llvm.mlir b/mlir/test/Target/LLVMIR/omptarget-region-llvm.mlir index b861dd7a7d315fca0236d245c1ee900448f1fe36..a32ee3e184e26bd474f385b7406c16000c3186e0 100644 --- a/mlir/test/Target/LLVMIR/omptarget-region-llvm.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-region-llvm.mlir @@ -12,9 +12,9 @@ module attributes {omp.is_target_device = false} { %7 = llvm.alloca %6 x i32 {bindc_name = "c", in_type = i32, operandSegmentSizes = array<i32: 0, 0>, uniq_name = "_QFomp_target_regionEc"} : (i64) -> !llvm.ptr llvm.store %1, %3 : i32, !llvm.ptr llvm.store %0, %5 : i32, !llvm.ptr - %map1 = omp.map_info var_ptr(%3 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} - %map2 = omp.map_info var_ptr(%5 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} - %map3 = omp.map_info var_ptr(%7 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %map1 = omp.map.info var_ptr(%3 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %map2 = omp.map.info var_ptr(%5 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %map3 = omp.map.info var_ptr(%7 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} omp.target map_entries(%map1 -> %arg0, %map2 -> %arg1, %map3 -> %arg2 : !llvm.ptr, !llvm.ptr, !llvm.ptr) { ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr): %8 = llvm.load %arg0 : !llvm.ptr -> i32 diff --git a/mlir/test/Target/LLVMIR/omptarget-region-parallel-llvm.mlir b/mlir/test/Target/LLVMIR/omptarget-region-parallel-llvm.mlir index c80ea1f0a47be75cd82a0c234f57566a914ef7c2..4072150a8eab83ed92b6051f61d72e8a32aec8cd 100644 --- a/mlir/test/Target/LLVMIR/omptarget-region-parallel-llvm.mlir +++ b/mlir/test/Target/LLVMIR/omptarget-region-parallel-llvm.mlir @@ -12,9 +12,9 @@ module attributes {omp.is_target_device = false} { %7 = llvm.alloca %6 x i32 {bindc_name = "c", in_type = i32, operandSegmentSizes = array<i32: 0, 0>, uniq_name = "_QFomp_target_regionEc"} : (i64) -> !llvm.ptr llvm.store %1, %3 : i32, !llvm.ptr llvm.store %0, %5 : i32, !llvm.ptr - %map1 = omp.map_info var_ptr(%3 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} - %map2 = omp.map_info var_ptr(%5 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} - %map3 = omp.map_info var_ptr(%7 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %map1 = omp.map.info var_ptr(%3 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %map2 = omp.map.info var_ptr(%5 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} + %map3 = omp.map.info var_ptr(%7 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""} omp.target map_entries( %map1 -> %arg0, %map2 -> %arg1, %map3 -> %arg2 : !llvm.ptr, !llvm.ptr, !llvm.ptr) { ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr): omp.parallel { diff --git a/mlir/test/Target/LLVMIR/openmp-llvm.mlir b/mlir/test/Target/LLVMIR/openmp-llvm.mlir index 12bd108ba86cb60a9f28592fff43dd3a5abcea19..4cb99c1f1a285be6518922b8fb51b851f6bf0b78 100644 --- a/mlir/test/Target/LLVMIR/openmp-llvm.mlir +++ b/mlir/test/Target/LLVMIR/openmp-llvm.mlir @@ -1191,7 +1191,7 @@ llvm.func @omp_ordered(%arg0 : i32, %arg1 : i32, %arg2 : i32, %arg3 : i64, // CHECK: [[OMP_THREAD:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]]) // CHECK-NEXT: call void @__kmpc_ordered(ptr @[[GLOB1]], i32 [[OMP_THREAD]]) - omp.ordered_region { + omp.ordered.region { omp.terminator // CHECK: call void @__kmpc_end_ordered(ptr @[[GLOB1]], i32 [[OMP_THREAD]]) } @@ -1199,7 +1199,7 @@ llvm.func @omp_ordered(%arg0 : i32, %arg1 : i32, %arg2 : i32, %arg3 : i64, omp.wsloop ordered(0) for (%arg7) : i32 = (%arg0) to (%arg1) step (%arg2) { // CHECK: call void @__kmpc_ordered(ptr @[[GLOB3:[0-9]+]], i32 [[OMP_THREAD2:%.*]]) - omp.ordered_region { + omp.ordered.region { omp.terminator // CHECK: call void @__kmpc_end_ordered(ptr @[[GLOB3]], i32 [[OMP_THREAD2]]) } diff --git a/mlir/test/Target/LLVMIR/openmp-reduction-byref.mlir b/mlir/test/Target/LLVMIR/openmp-reduction-byref.mlir new file mode 100644 index 0000000000000000000000000000000000000000..e720969e82c112454428b3484d2d1d64b562c63b --- /dev/null +++ b/mlir/test/Target/LLVMIR/openmp-reduction-byref.mlir @@ -0,0 +1,66 @@ +// RUN: mlir-translate -mlir-to-llvmir -split-input-file %s | FileCheck %s + + omp.declare_reduction @add_reduction_i_32 : !llvm.ptr init { + ^bb0(%arg0: !llvm.ptr): + %0 = llvm.mlir.constant(0 : i32) : i32 + %1 = llvm.mlir.constant(1 : i64) : i64 + %2 = llvm.alloca %1 x i32 : (i64) -> !llvm.ptr + llvm.store %0, %2 : i32, !llvm.ptr + omp.yield(%2 : !llvm.ptr) + } combiner { + ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr): + %0 = llvm.load %arg0 : !llvm.ptr -> i32 + %1 = llvm.load %arg1 : !llvm.ptr -> i32 + %2 = llvm.add %0, %1 : i32 + llvm.store %2, %arg0 : i32, !llvm.ptr + omp.yield(%arg0 : !llvm.ptr) + } + + // CHECK-LABEL: @main + llvm.func @main() { + %0 = llvm.mlir.constant(-1 : i32) : i32 + %1 = llvm.mlir.addressof @i : !llvm.ptr + omp.parallel byref reduction(@add_reduction_i_32 %1 -> %arg0 : !llvm.ptr) { + llvm.store %0, %arg0 : i32, !llvm.ptr + omp.terminator + } + llvm.return + } + llvm.mlir.global internal @i() {addr_space = 0 : i32} : i32 { + %0 = llvm.mlir.constant(0 : i32) : i32 + llvm.return %0 : i32 + } + +// CHECK: %{{.+}} = +// Call to the outlined function. +// CHECK: call void {{.*}} @__kmpc_fork_call +// CHECK-SAME: @[[OUTLINED:[A-Za-z_.][A-Za-z0-9_.]*]] + +// Outlined function. +// CHECK: define internal void @[[OUTLINED]] + +// Private reduction variable and its initialization. +// CHECK: %tid.addr.local = alloca i32 +// CHECK: %[[PRIVATE:.+]] = alloca i32 +// CHECK: store i32 0, ptr %[[PRIVATE]] +// CHECK: store ptr %[[PRIVATE]], ptr %[[PRIV_PTR:.+]], + +// Call to the reduction function. +// CHECK: call i32 @__kmpc_reduce +// CHECK-SAME: @[[REDFUNC:[A-Za-z_.][A-Za-z0-9_.]*]] + + +// Non-atomic reduction: +// CHECK: %[[PRIV_VAL_PTR:.+]] = load ptr, ptr %[[PRIV_PTR]] +// CHECK: %[[LOAD:.+]] = load i32, ptr @i +// CHECK: %[[PRIV_VAL:.+]] = load i32, ptr %[[PRIV_VAL_PTR]] +// CHECK: %[[SUM:.+]] = add i32 %[[LOAD]], %[[PRIV_VAL]] +// CHECK: store i32 %[[SUM]], ptr @i +// CHECK: call void @__kmpc_end_reduce +// CHECK: br label %[[FINALIZE:.+]] + +// CHECK: [[FINALIZE]]: + +// Reduction function. +// CHECK: define internal void @[[REDFUNC]] +// CHECK: add i32 diff --git a/mlir/test/Target/LLVMIR/openmp-reduction-call.mlir b/mlir/test/Target/LLVMIR/openmp-reduction-call.mlir new file mode 100644 index 0000000000000000000000000000000000000000..da240f4a6fff37f4766ad79d0861ee6a6dd85d71 --- /dev/null +++ b/mlir/test/Target/LLVMIR/openmp-reduction-call.mlir @@ -0,0 +1,37 @@ +// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s + +// Test that we don't crash when there is a call operation in the combiner + +omp.declare_reduction @add_f32 : f32 +init { +^bb0(%arg: f32): + %0 = llvm.mlir.constant(0.0 : f32) : f32 + omp.yield (%0 : f32) +} +combiner { +^bb1(%arg0: f32, %arg1: f32): +// test this call here: + llvm.call @test_call() : () -> () + %1 = llvm.fadd %arg0, %arg1 : f32 + omp.yield (%1 : f32) +} + +llvm.func @simple_reduction(%lb : i64, %ub : i64, %step : i64) { + %c1 = llvm.mlir.constant(1 : i32) : i32 + %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr + omp.parallel reduction(@add_f32 %0 -> %prv : !llvm.ptr) { + %1 = llvm.mlir.constant(2.0 : f32) : f32 + %2 = llvm.load %prv : !llvm.ptr -> f32 + %3 = llvm.fadd %1, %2 : f32 + llvm.store %3, %prv : f32, !llvm.ptr + omp.terminator + } + llvm.return +} + +llvm.func @test_call() -> () + +// Call to the troublesome function will have been inlined twice: once into +// main and once into the outlined function +// CHECK: call void @test_call() +// CHECK: call void @test_call() diff --git a/mlir/test/Target/LLVMIR/openmp-reduction.mlir b/mlir/test/Target/LLVMIR/openmp-reduction.mlir index 8c3c9cd1aa26b8fbafffdc73d188fbf4d3cac888..39b64d71a2274b0510594e1596fde4d3d552a314 100644 --- a/mlir/test/Target/LLVMIR/openmp-reduction.mlir +++ b/mlir/test/Target/LLVMIR/openmp-reduction.mlir @@ -3,7 +3,7 @@ // Only check the overall shape of the code and the presence of relevant // runtime calls. Actual IR checking is done at the OpenMPIRBuilder level. -omp.reduction.declare @add_f32 : f32 +omp.declare_reduction @add_f32 : f32 init { ^bb0(%arg: f32): %0 = llvm.mlir.constant(0.0 : f32) : f32 @@ -78,7 +78,7 @@ llvm.func @simple_reduction(%lb : i64, %ub : i64, %step : i64) { // ----- -omp.reduction.declare @add_f32 : f32 +omp.declare_reduction @add_f32 : f32 init { ^bb0(%arg: f32): %0 = llvm.mlir.constant(0.0 : f32) : f32 @@ -170,7 +170,7 @@ llvm.func @reuse_declaration(%lb : i64, %ub : i64, %step : i64) { // ----- -omp.reduction.declare @add_f32 : f32 +omp.declare_reduction @add_f32 : f32 init { ^bb0(%arg: f32): %0 = llvm.mlir.constant(0.0 : f32) : f32 @@ -255,7 +255,7 @@ llvm.func @missing_omp_reduction(%lb : i64, %ub : i64, %step : i64) { // ----- -omp.reduction.declare @add_f32 : f32 +omp.declare_reduction @add_f32 : f32 init { ^bb0(%arg: f32): %0 = llvm.mlir.constant(0.0 : f32) : f32 @@ -338,7 +338,7 @@ llvm.func @double_reference(%lb : i64, %ub : i64, %step : i64) { // ----- -omp.reduction.declare @add_f32 : f32 +omp.declare_reduction @add_f32 : f32 init { ^bb0(%arg: f32): %0 = llvm.mlir.constant(0.0 : f32) : f32 @@ -356,7 +356,7 @@ atomic { omp.yield } -omp.reduction.declare @mul_f32 : f32 +omp.declare_reduction @mul_f32 : f32 init { ^bb0(%arg: f32): %0 = llvm.mlir.constant(1.0 : f32) : f32 @@ -435,7 +435,7 @@ llvm.func @no_atomic(%lb : i64, %ub : i64, %step : i64) { // ----- -omp.reduction.declare @add_f32 : f32 +omp.declare_reduction @add_f32 : f32 init { ^bb0(%arg: f32): %0 = llvm.mlir.constant(0.0 : f32) : f32 @@ -504,7 +504,7 @@ llvm.func @simple_reduction_parallel() { // ----- -omp.reduction.declare @add_i32 : i32 +omp.declare_reduction @add_i32 : i32 init { ^bb0(%arg: i32): %0 = llvm.mlir.constant(0 : i32) : i32 diff --git a/mlir/test/Target/LLVMIR/rocdl.mlir b/mlir/test/Target/LLVMIR/rocdl.mlir index 93550f5c7bd5a4fbdeda68c8a3f0d3c0a7251669..ce6b56d48437a0c6338ef886557e256b8c934d35 100644 --- a/mlir/test/Target/LLVMIR/rocdl.mlir +++ b/mlir/test/Target/LLVMIR/rocdl.mlir @@ -88,13 +88,20 @@ llvm.func @rocdl.bpermute(%src : i32) -> i32 { llvm.return %0 : i32 } -llvm.func @rocdl.ballot(%pred : i1) -> i32 { - // CHECK-LABEL: rocdl.ballot +llvm.func @rocdl.ballot32(%pred : i1) -> i32 { + // CHECK-LABEL: rocdl.ballot32 // CHECK: call i32 @llvm.amdgcn.ballot %0 = rocdl.ballot %pred : i32 llvm.return %0 : i32 } +llvm.func @rocdl.ballot64(%pred : i1) -> i64 { + // CHECK-LABEL: rocdl.ballot64 + // CHECK: call i64 @llvm.amdgcn.ballot + %0 = rocdl.ballot %pred : i64 + llvm.return %0 : i64 +} + llvm.func @rocdl.waitcnt() { // CHECK-LABEL: rocdl.waitcnt // CHECK-NEXT: call void @llvm.amdgcn.s.waitcnt(i32 0) diff --git a/mlir/test/Transforms/buffer-results-to-out-params-add-result-attr.mlir b/mlir/test/Transforms/buffer-results-to-out-params-add-result-attr.mlir new file mode 100644 index 0000000000000000000000000000000000000000..f4a95c73e295331c7c31a4ee4081aa517db9c46b --- /dev/null +++ b/mlir/test/Transforms/buffer-results-to-out-params-add-result-attr.mlir @@ -0,0 +1,17 @@ +// RUN: mlir-opt -p 'builtin.module(buffer-results-to-out-params{add-result-attr})' -split-input-file -verify-diagnostics %s | FileCheck %s + +// CHECK-LABEL: @basic({{.*}}: memref<f32> {bufferize.result}) +func.func @basic() -> (memref<f32>) { + %0 = "test.source"() : () -> (memref<f32>) + return %0 : memref<f32> +} + +// ----- + +// CHECK-LABEL: multiple_results +// CHECK-SAME: memref<1xf32> {bufferize.result} +// CHECK-SAME: memref<2xf32> {bufferize.result} +func.func @multiple_results() -> (memref<1xf32>, memref<2xf32>) { + %0, %1 = "test.source"() : () -> (memref<1xf32>, memref<2xf32>) + return %0, %1 : memref<1xf32>, memref<2xf32> +} diff --git a/mlir/test/Transforms/canonicalize.mlir b/mlir/test/Transforms/canonicalize.mlir index 2cf86b50d432f6a7a860adf4958ed15638216d33..d2c2c12d3238929f21ed2134f5081e29c191625d 100644 --- a/mlir/test/Transforms/canonicalize.mlir +++ b/mlir/test/Transforms/canonicalize.mlir @@ -989,6 +989,15 @@ func.func @tensor_arith.floordivsi_by_one(%arg0: tensor<4x5xi32>) -> tensor<4x5x return %res : tensor<4x5xi32> } +// CHECK-LABEL: func @arith.floordivsi_by_one_overflow +func.func @arith.floordivsi_by_one_overflow() -> i64 { + %neg_one = arith.constant -1 : i64 + %min_int = arith.constant -9223372036854775808 : i64 + // CHECK: arith.floordivsi + %poision = arith.floordivsi %min_int, %neg_one : i64 + return %poision : i64 +} + // ----- // CHECK-LABEL: func @arith.ceildivsi_by_one diff --git a/mlir/test/Transforms/composite-pass.mlir b/mlir/test/Transforms/composite-pass.mlir new file mode 100644 index 0000000000000000000000000000000000000000..829470c2c9aa6445520032e450e0c9166ce7545d --- /dev/null +++ b/mlir/test/Transforms/composite-pass.mlir @@ -0,0 +1,26 @@ +// RUN: mlir-opt %s --log-actions-to=- --test-composite-fixed-point-pass -split-input-file | FileCheck %s +// RUN: mlir-opt %s --log-actions-to=- --composite-fixed-point-pass='name=TestCompositePass pipeline=any(canonicalize,cse)' -split-input-file | FileCheck %s + +// CHECK-LABEL: running `TestCompositePass` +// CHECK: running `Canonicalizer` +// CHECK: running `CSE` +// CHECK-NOT: running `Canonicalizer` +// CHECK-NOT: running `CSE` +func.func @test() { + return +} + +// ----- + +// CHECK-LABEL: running `TestCompositePass` +// CHECK: running `Canonicalizer` +// CHECK: running `CSE` +// CHECK: running `Canonicalizer` +// CHECK: running `CSE` +// CHECK-NOT: running `Canonicalizer` +// CHECK-NOT: running `CSE` +func.func @test() { +// this constant will be canonicalized away, causing another pass iteration + %0 = arith.constant 1.5 : f32 + return +} diff --git a/mlir/test/Transforms/inlining-dump-default-pipeline.mlir b/mlir/test/Transforms/inlining-dump-default-pipeline.mlir index e2c31867a8e0451db315afb9e6b81964f9b3a7f8..4f8638054206e87a22c31686f4d226e009ba9394 100644 --- a/mlir/test/Transforms/inlining-dump-default-pipeline.mlir +++ b/mlir/test/Transforms/inlining-dump-default-pipeline.mlir @@ -1,2 +1,2 @@ // RUN: mlir-opt %s -pass-pipeline="builtin.module(inline)" -dump-pass-pipeline 2>&1 | FileCheck %s -// CHECK: builtin.module(inline{default-pipeline=canonicalize max-iterations=4 }) +// CHECK: builtin.module(inline{default-pipeline=canonicalize inlining-threshold=4294967295 max-iterations=4 }) diff --git a/mlir/test/Transforms/inlining-threshold.mlir b/mlir/test/Transforms/inlining-threshold.mlir new file mode 100644 index 0000000000000000000000000000000000000000..649408aab577ac85be3a4404aac806eb1e25052d --- /dev/null +++ b/mlir/test/Transforms/inlining-threshold.mlir @@ -0,0 +1,18 @@ +// RUN: mlir-opt %s -inline='default-pipeline= inlining-threshold=100' | FileCheck %s + +// Check that inlining does not happen when the threshold is exceeded. +func.func @callee1(%arg : i32) -> i32 { + %v1 = arith.addi %arg, %arg : i32 + %v2 = arith.addi %v1, %arg : i32 + %v3 = arith.addi %v2, %arg : i32 + return %v3 : i32 +} + +// CHECK-LABEL: func @caller1 +func.func @caller1(%arg0 : i32) -> i32 { + // CHECK-NEXT: call @callee1 + // CHECK-NEXT: return + + %0 = call @callee1(%arg0) : (i32) -> i32 + return %0 : i32 +} diff --git a/mlir/test/lib/Dialect/Affine/TestAccessAnalysis.cpp b/mlir/test/lib/Dialect/Affine/TestAccessAnalysis.cpp index b38046299d504a92399f148cd22e55f5057888a9..751302550092d71ab0ebf18c6f212c1494a497f6 100644 --- a/mlir/test/lib/Dialect/Affine/TestAccessAnalysis.cpp +++ b/mlir/test/lib/Dialect/Affine/TestAccessAnalysis.cpp @@ -59,18 +59,25 @@ void TestAccessAnalysis::runOnOperation() { enclosingOps.clear(); getAffineForIVs(*memOp, &enclosingOps); for (unsigned d = 0, e = enclosingOps.size(); d < e; d++) { + AffineForOp loop = enclosingOps[d]; int memRefDim; - bool isContiguous; + bool isContiguous, isInvariant; if (auto read = dyn_cast<AffineReadOpInterface>(memOp)) { - isContiguous = isContiguousAccess(enclosingOps[d].getInductionVar(), - read, &memRefDim); + isContiguous = + isContiguousAccess(loop.getInductionVar(), read, &memRefDim); + isInvariant = isInvariantAccess(read, loop); } else { - isContiguous = isContiguousAccess(enclosingOps[d].getInductionVar(), - cast<AffineWriteOpInterface>(memOp), - &memRefDim); + auto write = cast<AffineWriteOpInterface>(memOp); + isContiguous = + isContiguousAccess(loop.getInductionVar(), write, &memRefDim); + isInvariant = isInvariantAccess(write, loop); } + // Check for contiguity for the innermost memref dimension to avoid + // emitting too many diagnostics. if (isContiguous && memRefDim == 0) memOp->emitRemark("contiguous along loop ") << d << '\n'; + if (isInvariant) + memOp->emitRemark("invariant along loop ") << d << '\n'; } } } diff --git a/mlir/test/lib/Dialect/Affine/TestReifyValueBounds.cpp b/mlir/test/lib/Dialect/Affine/TestReifyValueBounds.cpp index 39671a930f2e213822de2c651bca092d3995072f..5e160b720db627e7d78ed62a9dae70624c0433b1 100644 --- a/mlir/test/lib/Dialect/Affine/TestReifyValueBounds.cpp +++ b/mlir/test/lib/Dialect/Affine/TestReifyValueBounds.cpp @@ -13,6 +13,7 @@ #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/Dialect/Tensor/IR/Tensor.h" +#include "mlir/Dialect/Vector/IR/ScalableValueBoundsConstraintSet.h" #include "mlir/IR/PatternMatch.h" #include "mlir/Interfaces/ValueBoundsOpInterface.h" #include "mlir/Pass/Pass.h" @@ -75,7 +76,8 @@ static LogicalResult testReifyValueBounds(func::FuncOp funcOp, WalkResult result = funcOp.walk([&](Operation *op) { // Look for test.reify_bound ops. if (op->getName().getStringRef() == "test.reify_bound" || - op->getName().getStringRef() == "test.reify_constant_bound") { + op->getName().getStringRef() == "test.reify_constant_bound" || + op->getName().getStringRef() == "test.reify_scalable_bound") { if (op->getNumOperands() != 1 || op->getNumResults() != 1 || !op->getResultTypes()[0].isIndex()) { op->emitOpError("invalid op"); @@ -110,6 +112,9 @@ static LogicalResult testReifyValueBounds(func::FuncOp funcOp, bool constant = op->getName().getStringRef() == "test.reify_constant_bound"; + bool scalable = !constant && op->getName().getStringRef() == + "test.reify_scalable_bound"; + // Prepare stop condition. By default, reify in terms of the op's // operands. No stop condition is used when a constant was requested. std::function<bool(Value, std::optional<int64_t>)> stopCondition = @@ -137,6 +142,37 @@ static LogicalResult testReifyValueBounds(func::FuncOp funcOp, if (succeeded(reifiedConst)) reified = FailureOr<OpFoldResult>(rewriter.getIndexAttr(*reifiedConst)); + } else if (scalable) { + unsigned vscaleMin = 0; + unsigned vscaleMax = 0; + if (auto attr = "vscale_min"; op->hasAttrOfType<IntegerAttr>(attr)) { + vscaleMin = unsigned(op->getAttrOfType<IntegerAttr>(attr).getInt()); + } else { + op->emitOpError("expected `vscale_min` to be provided"); + return WalkResult::skip(); + } + if (auto attr = "vscale_max"; op->hasAttrOfType<IntegerAttr>(attr)) { + vscaleMax = unsigned(op->getAttrOfType<IntegerAttr>(attr).getInt()); + } else { + op->emitOpError("expected `vscale_max` to be provided"); + return WalkResult::skip(); + } + + auto loc = op->getLoc(); + auto reifiedScalable = + vector::ScalableValueBoundsConstraintSet::computeScalableBound( + value, dim, vscaleMin, vscaleMax, *boundType); + if (succeeded(reifiedScalable)) { + SmallVector<std::pair<Value, std::optional<int64_t>>, 1> + vscaleOperand; + if (reifiedScalable->map.getNumInputs() == 1) { + // The only possible input to the bound is vscale. + vscaleOperand.push_back(std::make_pair( + rewriter.create<vector::VectorScaleOp>(loc), std::nullopt)); + } + reified = affine::materializeComputedBound( + rewriter, loc, reifiedScalable->map, vscaleOperand); + } } else { if (dim) { if (useArithOps) { diff --git a/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp b/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp index 740562e7783024960d5e058579acf0940eb03379..3da48ffa403ed66ecc88d86c46609a6117f23e45 100644 --- a/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp +++ b/mlir/test/lib/Dialect/DLTI/TestDataLayoutQuery.cpp @@ -36,19 +36,21 @@ struct TestDataLayoutQuery return; const DataLayout &layout = layouts.getAbove(op); - unsigned size = layout.getTypeSize(op.getType()); - unsigned bitsize = layout.getTypeSizeInBits(op.getType()); - unsigned alignment = layout.getTypeABIAlignment(op.getType()); - unsigned preferred = layout.getTypePreferredAlignment(op.getType()); + llvm::TypeSize size = layout.getTypeSize(op.getType()); + llvm::TypeSize bitsize = layout.getTypeSizeInBits(op.getType()); + uint64_t alignment = layout.getTypeABIAlignment(op.getType()); + uint64_t preferred = layout.getTypePreferredAlignment(op.getType()); + uint64_t index = layout.getTypeIndexBitwidth(op.getType()).value_or(0); Attribute allocaMemorySpace = layout.getAllocaMemorySpace(); Attribute programMemorySpace = layout.getProgramMemorySpace(); Attribute globalMemorySpace = layout.getGlobalMemorySpace(); - unsigned stackAlignment = layout.getStackAlignment(); + uint64_t stackAlignment = layout.getStackAlignment(); op->setAttrs( {builder.getNamedAttr("size", builder.getIndexAttr(size)), builder.getNamedAttr("bitsize", builder.getIndexAttr(bitsize)), builder.getNamedAttr("alignment", builder.getIndexAttr(alignment)), builder.getNamedAttr("preferred", builder.getIndexAttr(preferred)), + builder.getNamedAttr("index", builder.getIndexAttr(index)), builder.getNamedAttr("alloca_memory_space", allocaMemorySpace == Attribute() ? builder.getUI32IntegerAttr(0) diff --git a/mlir/test/lib/Dialect/Math/TestExpandMath.cpp b/mlir/test/lib/Dialect/Math/TestExpandMath.cpp index 7ce8b5a7cfe9b3fe4d79106d2ad92bb4c21d9ebb..97600ad1ebe7a31a9071cad7a95853216c755973 100644 --- a/mlir/test/lib/Dialect/Math/TestExpandMath.cpp +++ b/mlir/test/lib/Dialect/Math/TestExpandMath.cpp @@ -46,6 +46,7 @@ void TestExpandMathPass::runOnOperation() { populateExpandFloorFPattern(patterns); populateExpandCeilFPattern(patterns); populateExpandPowFPattern(patterns); + populateExpandFPowIPattern(patterns); populateExpandRoundFPattern(patterns); populateExpandRoundEvenPattern(patterns); (void)applyPatternsAndFoldGreedily(getOperation(), std::move(patterns)); diff --git a/mlir/test/lib/Dialect/Tensor/TestTensorTransforms.cpp b/mlir/test/lib/Dialect/Tensor/TestTensorTransforms.cpp index b907f77e9108253bb9089e8863aeae78dcdd044d..ae4f77f5873e2b3c31bf55ad601a0a10d0e46bc8 100644 --- a/mlir/test/lib/Dialect/Tensor/TestTensorTransforms.cpp +++ b/mlir/test/lib/Dialect/Tensor/TestTensorTransforms.cpp @@ -16,8 +16,8 @@ #include "mlir/Dialect/Tensor/IR/Tensor.h" #include "mlir/Dialect/Tensor/Transforms/TransformUtils.h" #include "mlir/Dialect/Tensor/Transforms/Transforms.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformOps.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Pass/Pass.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" diff --git a/mlir/test/lib/Dialect/Test/TestDialect.cpp b/mlir/test/lib/Dialect/Test/TestDialect.cpp index 1ee52fc08d77f62b451c40a07ada7f60548a3dc3..380c74a47e509a5f898f67ee0e61afb0f52311a9 100644 --- a/mlir/test/lib/Dialect/Test/TestDialect.cpp +++ b/mlir/test/lib/Dialect/Test/TestDialect.cpp @@ -499,6 +499,23 @@ void AffineScopeOp::print(OpAsmPrinter &p) { p.printRegion(getRegion(), /*printEntryBlockArgs=*/false); } +//===----------------------------------------------------------------------===// +// Test OptionalCustomAttrOp +//===----------------------------------------------------------------------===// + +static OptionalParseResult parseOptionalCustomParser(AsmParser &p, + IntegerAttr &result) { + if (succeeded(p.parseOptionalKeyword("foo"))) + return p.parseAttribute(result); + return {}; +} + +static void printOptionalCustomParser(AsmPrinter &p, Operation *, + IntegerAttr result) { + p << "foo "; + p.printAttribute(result); +} + //===----------------------------------------------------------------------===// // Test removing op with inner ops. //===----------------------------------------------------------------------===// diff --git a/mlir/test/lib/Dialect/Test/TestOps.td b/mlir/test/lib/Dialect/Test/TestOps.td index dfd2f21a5ea2498718c29a974546c58c6ac2768b..e6c3601d08dad0c31b4c8465cec0f29a4599f0c3 100644 --- a/mlir/test/lib/Dialect/Test/TestOps.td +++ b/mlir/test/lib/Dialect/Test/TestOps.td @@ -2048,6 +2048,17 @@ def CustomDimensionListAttrOp : TEST_Op<"custom_dimension_list_attr"> { }]; } +def OptionalCustomAttrOp : TEST_Op<"optional_custom_attr"> { + let description = [{ + Test using a custom directive as the optional group anchor and the first + element to parse. It is expected to return an `OptionalParseResult`. + }]; + let arguments = (ins OptionalAttr<I1Attr>:$attr); + let assemblyFormat = [{ + attr-dict (custom<OptionalCustomParser>($attr)^) : (`bar`)? + }]; +} + //===----------------------------------------------------------------------===// // Test OpAsmInterface. diff --git a/mlir/test/lib/Dialect/Test/TestPatterns.cpp b/mlir/test/lib/Dialect/Test/TestPatterns.cpp index 2da184bc3d85baae0c0d80c509f163ed183cc68d..76dc825fe4451557f27e7b6aea55d7d2897d59bb 100644 --- a/mlir/test/lib/Dialect/Test/TestPatterns.cpp +++ b/mlir/test/lib/Dialect/Test/TestPatterns.cpp @@ -489,7 +489,10 @@ private: OperationName("test.new_op", op->getContext()).getIdentifier(), op->getOperands(), op->getResultTypes()); } - rewriter.replaceOp(op, newOp->getResults()); + // "replaceOp" could be used instead of "replaceAllOpUsesWith"+"eraseOp". + // A "notifyOperationReplaced" callback is triggered in either case. + rewriter.replaceAllOpUsesWith(op, newOp->getResults()); + rewriter.eraseOp(op); return success(); } }; diff --git a/mlir/test/lib/Dialect/Test/TestTypeDefs.td b/mlir/test/lib/Dialect/Test/TestTypeDefs.td index 1957845c842f20803e1dcf8331ccc4cc5c7353e7..492642b711e09e8ad2d97ad6e306418d8bddee3d 100644 --- a/mlir/test/lib/Dialect/Test/TestTypeDefs.td +++ b/mlir/test/lib/Dialect/Test/TestTypeDefs.td @@ -148,7 +148,8 @@ def TestType : Test_Type<"Test", [ } def TestTypeWithLayoutType : Test_Type<"TestTypeWithLayout", [ - DeclareTypeInterfaceMethods<DataLayoutTypeInterface, ["areCompatible"]> + DeclareTypeInterfaceMethods<DataLayoutTypeInterface, ["getIndexBitwidth", + "areCompatible"]> ]> { let mnemonic = "test_type_with_layout"; let parameters = (ins "unsigned":$key); diff --git a/mlir/test/lib/Dialect/Test/TestTypes.cpp b/mlir/test/lib/Dialect/Test/TestTypes.cpp index 2f4c9b689069b8936f483478433975b35dd82a90..7a195eb25a3ba1ae611c99d836573d06ede71064 100644 --- a/mlir/test/lib/Dialect/Test/TestTypes.cpp +++ b/mlir/test/lib/Dialect/Test/TestTypes.cpp @@ -276,6 +276,12 @@ uint64_t TestTypeWithLayoutType::getPreferredAlignment( return extractKind(params, "preferred"); } +std::optional<uint64_t> +TestTypeWithLayoutType::getIndexBitwidth(const DataLayout &dataLayout, + DataLayoutEntryListRef params) const { + return extractKind(params, "index"); +} + bool TestTypeWithLayoutType::areCompatible( DataLayoutEntryListRef oldLayout, DataLayoutEntryListRef newLayout) const { unsigned old = extractKind(oldLayout, "alignment"); @@ -297,7 +303,7 @@ TestTypeWithLayoutType::verifyEntries(DataLayoutEntryListRef params, (void)kind; assert(kind && (kind.getValue() == "size" || kind.getValue() == "alignment" || - kind.getValue() == "preferred") && + kind.getValue() == "preferred" || kind.getValue() == "index") && "unexpected kind"); assert(llvm::isa<IntegerAttr>(array.getValue().back())); } diff --git a/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.cpp b/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.cpp index b9424e06bf0318fc2793cbe60114ce94f030ef7c..2b39668035bc09a4a2ab056181a071671132d04e 100644 --- a/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.cpp +++ b/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.cpp @@ -15,8 +15,8 @@ #include "TestTransformStateExtension.h" #include "mlir/Dialect/PDL/IR/PDL.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformOps.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Dialect/Transform/PDLExtension/PDLExtensionOps.h" #include "mlir/IR/OpImplementation.h" #include "mlir/IR/PatternMatch.h" diff --git a/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.h b/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.h index 95950e4c5af1fe08fc192af69929cd634493f339..60dc959b005010023618c056903cfde2845580ee 100644 --- a/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.h +++ b/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.h @@ -16,9 +16,9 @@ #include "mlir/Bytecode/BytecodeOpInterface.h" #include "mlir/Dialect/PDL/IR/PDLTypes.h" -#include "mlir/Dialect/Transform/IR/MatchInterfaces.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformTypes.h" +#include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/IR/OpImplementation.h" namespace mlir { diff --git a/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.td b/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.td index c00cc560e83e9b6e24bbfc5a84b5ea3da21b185b..4f2cf34f7d3347208ca8c093ec9fc1e0f59d405c 100644 --- a/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.td +++ b/mlir/test/lib/Dialect/Transform/TestTransformDialectExtension.td @@ -17,9 +17,9 @@ include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/IR/AttrTypeBase.td" include "mlir/IR/OpBase.td" -include "mlir/Dialect/Transform/IR/MatchInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/MatchInterfaces.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Dialect/PDL/IR/PDLTypes.td" def TestTransformTestDialectHandleType diff --git a/mlir/test/lib/Dialect/Transform/TestTransformDialectInterpreter.cpp b/mlir/test/lib/Dialect/Transform/TestTransformDialectInterpreter.cpp index 7d77499585648e051b024c4a2588477d58eb08e1..e936ac5b852bd8e31a730f4a6d633f104689bbc1 100644 --- a/mlir/test/lib/Dialect/Transform/TestTransformDialectInterpreter.cpp +++ b/mlir/test/lib/Dialect/Transform/TestTransformDialectInterpreter.cpp @@ -13,8 +13,8 @@ #include "TestTransformDialectExtension.h" #include "mlir/Dialect/Transform/DebugExtension/DebugExtensionOps.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" #include "mlir/Dialect/Transform/IR/TransformOps.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Dialect/Transform/Transforms/TransformInterpreterPassBase.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinOps.h" diff --git a/mlir/test/lib/Dialect/Transform/TestTransformStateExtension.h b/mlir/test/lib/Dialect/Transform/TestTransformStateExtension.h index 752b3a78141ea60c7995153840742dc2685311a2..0bfa6bed015c0f36e0926f7b57c8d893a20586bf 100644 --- a/mlir/test/lib/Dialect/Transform/TestTransformStateExtension.h +++ b/mlir/test/lib/Dialect/Transform/TestTransformStateExtension.h @@ -14,7 +14,7 @@ #ifndef MLIR_TEST_LIB_DIALECT_TRANSFORM_TESTTRANSFORMSTATEEXTENSION_H #define MLIR_TEST_LIB_DIALECT_TRANSFORM_TESTTRANSFORMSTATEEXTENSION_H -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" using namespace mlir; diff --git a/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp b/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp index f14fb18706d1b759b63b95e527417ae217c91105..00622599910567aa5dbf0c3c24c5bcd3fe156c74 100644 --- a/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp +++ b/mlir/test/lib/Dialect/Vector/TestVectorTransforms.cpp @@ -489,7 +489,9 @@ struct TestFlattenVectorTransferPatterns Option<unsigned> targetVectorBitwidth{ *this, "target-vector-bitwidth", llvm::cl::desc( - "Minimum vector bitwidth to enable the flattening transformation"), + "Minimum vector bitwidth to enable the flattening transformation. " + "For scalable vectors this is the base size, i.e. the size " + "corresponding to vscale=1."), llvm::cl::init(std::numeric_limits<unsigned>::max())}; void runOnOperation() override { diff --git a/mlir/test/lib/Interfaces/TilingInterface/TestTilingInterfaceTransformOps.cpp b/mlir/test/lib/Interfaces/TilingInterface/TestTilingInterfaceTransformOps.cpp index b6a0ad84eee011d80b9055a00e8e4c1cb9276bda..335db1a61f476ef1c2bda5b467d5c02c45630be8 100644 --- a/mlir/test/lib/Interfaces/TilingInterface/TestTilingInterfaceTransformOps.cpp +++ b/mlir/test/lib/Interfaces/TilingInterface/TestTilingInterfaceTransformOps.cpp @@ -16,7 +16,7 @@ #include "mlir/Dialect/SCF/Transforms/TileUsingInterface.h" #include "mlir/Dialect/Transform/IR/TransformAttrs.h" #include "mlir/Dialect/Transform/IR/TransformDialect.h" -#include "mlir/Dialect/Transform/IR/TransformInterfaces.h" +#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h" #include "mlir/Dialect/Utils/StaticValueUtils.h" #include "mlir/IR/Dominance.h" #include "mlir/IR/OpImplementation.h" diff --git a/mlir/test/lib/Interfaces/TilingInterface/TestTilingInterfaceTransformOps.td b/mlir/test/lib/Interfaces/TilingInterface/TestTilingInterfaceTransformOps.td index f6e577a5c17a683cb48061ab73583b3fe8cf40fe..ef42375e5286d8609a65ca2645c56419ffedf32b 100644 --- a/mlir/test/lib/Interfaces/TilingInterface/TestTilingInterfaceTransformOps.td +++ b/mlir/test/lib/Interfaces/TilingInterface/TestTilingInterfaceTransformOps.td @@ -11,7 +11,7 @@ include "mlir/Dialect/SCF/IR/DeviceMappingInterface.td" include "mlir/Dialect/Transform/IR/TransformDialect.td" -include "mlir/Dialect/Transform/IR/TransformInterfaces.td" +include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.td" include "mlir/Dialect/Transform/IR/TransformTypes.td" include "mlir/Interfaces/SideEffectInterfaces.td" include "mlir/IR/OpBase.td" diff --git a/mlir/test/lib/Transforms/CMakeLists.txt b/mlir/test/lib/Transforms/CMakeLists.txt index 2a3a8608db544242e966a411f2a5c438e1f06b4b..a849b7ebd29e2304b666420febe66291b6cf72ee 100644 --- a/mlir/test/lib/Transforms/CMakeLists.txt +++ b/mlir/test/lib/Transforms/CMakeLists.txt @@ -20,6 +20,7 @@ endif() # Exclude tests from libMLIR.so add_mlir_library(MLIRTestTransforms TestCommutativityUtils.cpp + TestCompositePass.cpp TestConstantFold.cpp TestControlFlowSink.cpp TestInlining.cpp diff --git a/mlir/test/lib/Transforms/TestCompositePass.cpp b/mlir/test/lib/Transforms/TestCompositePass.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c0d93cc0d64ec1e3dee805fd182fcac10d005c7 --- /dev/null +++ b/mlir/test/lib/Transforms/TestCompositePass.cpp @@ -0,0 +1,38 @@ +//===------ TestCompositePass.cpp --- composite test pass -----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements a pass to test the composite pass utility. +// +//===----------------------------------------------------------------------===// + +#include "mlir/Pass/Pass.h" +#include "mlir/Pass/PassManager.h" +#include "mlir/Pass/PassRegistry.h" +#include "mlir/Transforms/Passes.h" + +namespace mlir { +namespace test { +void registerTestCompositePass() { + registerPassPipeline( + "test-composite-fixed-point-pass", "Test composite pass", + [](OpPassManager &pm, StringRef optionsStr, + function_ref<LogicalResult(const Twine &)> errorHandler) { + if (!optionsStr.empty()) + return failure(); + + pm.addPass(createCompositeFixedPointPass( + "TestCompositePass", [](OpPassManager &p) { + p.addPass(createCanonicalizerPass()); + p.addPass(createCSEPass()); + })); + return success(); + }, + [](function_ref<void(const detail::PassOptions &)>) {}); +} +} // namespace test +} // namespace mlir diff --git a/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir b/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir index 541a201c94c58666104e3c36210d1e68f36f5d77..340ef30bf59c29e81a7ccb16aa22b9cdbc6ca962 100644 --- a/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir +++ b/mlir/test/mlir-cpu-runner/test-expand-math-approx.mlir @@ -190,6 +190,12 @@ func.func @func_powff64(%a : f64, %b : f64) { return } +func.func @func_powff32(%a : f32, %b : f32) { + %r = math.powf %a, %b : f32 + vector.print %r : f32 + return +} + func.func @powf() { // CHECK-NEXT: 16 %a = arith.constant 4.0 : f64 @@ -230,7 +236,17 @@ func.func @powf() { %j = arith.constant 29385.0 : f64 %j_p = arith.constant 23598.0 : f64 call @func_powff64(%j, %j_p) : (f64, f64) -> () - return + + // CHECK-NEXT: -nan + %k = arith.constant 1.0 : f64 + %k_p = arith.constant 0xfff0000001000000 : f64 + call @func_powff64(%k, %k_p) : (f64, f64) -> () + + // CHECK-NEXT: -nan + %l = arith.constant 1.0 : f32 + %l_p = arith.constant 0xffffffff : f32 + call @func_powff32(%l, %l_p) : (f32, f32) -> () + return } // -------------------------------------------------------------------------- // @@ -683,6 +699,24 @@ func.func @cosh() { return } +// -------------------------------------------------------------------------- // +// Tanh. +// -------------------------------------------------------------------------- // + +func.func @tanh_8xf32(%a : vector<8xf32>) { + %r = math.tanh %a : vector<8xf32> + vector.print %r : vector<8xf32> + return +} + +func.func @tanh() { + // CHECK: -1, -0.761594, -0.291313, 0, 0.291313, 0.761594, 1, 1 + %v3 = arith.constant dense<[0xff800000, -1.0, -0.3, 0.0, 0.3, 1.0, 10.0, 0x7f800000]> : vector<8xf32> + call @tanh_8xf32(%v3) : (vector<8xf32>) -> () + + return +} + func.func @main() { call @exp2f() : () -> () call @roundf() : () -> () @@ -690,5 +724,6 @@ func.func @main() { call @roundeven() : () -> () call @sinh() : () -> () call @cosh() : () -> () + call @tanh() : () -> () return } diff --git a/mlir/test/mlir-opt/nearmiss.mlir b/mlir/test/mlir-opt/nearmiss.mlir deleted file mode 100644 index 2f695517eca06873c8a35b1bbc2678aabb97a4d6..0000000000000000000000000000000000000000 --- a/mlir/test/mlir-opt/nearmiss.mlir +++ /dev/null @@ -1,22 +0,0 @@ -// RUN: mlir-opt --split-input-file --verify-diagnostics %s 2> %t && FileCheck --input-file %t %s -// RUN: cat %t - -func.func @main() {return} - -// ----- - -// expected-note @+1 {{see existing symbol definition here}} -func.func @foo() { return } -// CHECK: warning: near miss with file split marker -// CHECK: ---- -// ---- - -// expected-error @+1 {{redefinition of symbol named 'foo'}} -func.func @foo() { return } -// CHECK: warning: near miss with file split marker -// CHECK: ---- -// ---- -func.func @bar2() {return } - -// No error flagged at the end for a near miss. -// ---- diff --git a/mlir/test/mlir-opt/split-markers.mlir b/mlir/test/mlir-opt/split-markers.mlir new file mode 100644 index 0000000000000000000000000000000000000000..f372654bcc8d3fc1e7b427795236f50c1013a10f --- /dev/null +++ b/mlir/test/mlir-opt/split-markers.mlir @@ -0,0 +1,43 @@ +// Check near-miss mechanics: +// RUN: mlir-opt --split-input-file --verify-diagnostics %s 2> %t \ +// RUN: && FileCheck --input-file %t --check-prefix=CHECK-DEFAULT %s +// RUN: cat %t + +// Check that (1) custom input splitter and (2) custom output splitters work. +// RUN: mlir-opt %s -split-input-file="// CHECK-DEFAULT: ""----" \ +// RUN: -output-split-marker="// ---- next split ----" \ +// RUN: | FileCheck --check-prefix=CHECK-CUSTOM %s + +// Check that (3) the input is not split if `-split-input-file` is not given. +// RUN: mlir-opt %s 2> %t \ +// RUN: || FileCheck --input-file %t --check-prefix=CHECK-NOSPLIT %s +// RUN: cat %t + +func.func @main() {return} + +// ----- + +// expected-note @+1 {{see existing symbol definition here}} +func.func @foo() { return } +// CHECK-DEFAULT: warning: near miss with file split marker +// CHECK-DEFAULT: ---- +// ---- + +// CHECK-NOSPLIT: error: redefinition of symbol named 'main' +func.func @main() {return} + +// expected-error @+1 {{redefinition of symbol named 'foo'}} +func.func @foo() { return } +// CHECK-DEFAULT: warning: near miss with file split marker +// CHECK-DEFAULT: ---- +// ---- +func.func @bar2() {return } + +// No error flagged at the end for a near miss. +// ---- + +// CHECK-CUSTOM: module +// CHECK-CUSTOM: ---- next split ---- +// CHECK-CUSTOM: module +// CHECK-CUSTOM: ---- next split ---- +// CHECK-CUSTOM: module diff --git a/mlir/test/mlir-pdll/split-markers.pdll b/mlir/test/mlir-pdll/split-markers.pdll new file mode 100644 index 0000000000000000000000000000000000000000..2b314538004fa1f362ee8004385350ed49d4b07a --- /dev/null +++ b/mlir/test/mlir-pdll/split-markers.pdll @@ -0,0 +1,48 @@ +// Check that (1) the default input split marker used if no custom marker is +// specified and (2) the output file is merged using the default marker. +// RUN: mlir-pdll %s -split-input-file \ +// RUN: | FileCheck -check-prefix=CHECK-DEFAULT %s + +// Check that the custom (3) input and (output) split markers are used if +// provided. +// RUN: mlir-pdll %s \ +// RUN: -split-input-file="// ""=====" -output-split-marker "// #####" \ +// RUN: | FileCheck -check-prefix=CHECK-CUSTOM %s + +// Check that (5) the input is not split if `-split-input-file` is not given. +// RUN: mlir-pdll %s \ +// RUN: | FileCheck -check-prefix=CHECK-NOSPLIT %s + +// CHECK-DEFAULT: Module +// CHECK-DEFAULT-NEXT: PatternDecl +// CHECK-DEFAULT-NOT: PatternDecl +// CHECK-DEFAULT: //{{ }}----- +// CHECK-DEFAULT-NEXT: Module +// CHECK-DEFAULT-NEXT: PatternDecl +// CHECK-DEFAULT: PatternDecl + +// CHECK-CUSTOM: Module +// CHECK-CUSTOM-NEXT: PatternDecl +// CHECK-CUSTOM: PatternDecl +// CHECK-CUSTOM: // ##### +// CHECK-CUSTOM-NEXT: Module +// CHECK-CUSTOM-NEXT: PatternDecl +// CHECK-CUSTOM-NOT: PatternDecl + +// CHECK-NOSPLIT: Module +// CHECK-NOSPLIT-NEXT: PatternDecl +// CHECK-NOSPLIT-NOT: Module +// CHECK-NOSPLIT: PatternDecl +// CHECK-NOSPLIT-NOT: Module +// CHECK-NOSPLIT: PatternDecl +// CHECK-NOSPLIT-NOT: Module + +Pattern => erase op<test.op>; + +// ----- + +Pattern => erase op<test.op2>; + +// ===== + +Pattern => erase op<test.op3>; diff --git a/mlir/test/mlir-tblgen/attr-or-type-format.td b/mlir/test/mlir-tblgen/attr-or-type-format.td index b9041e45f856ad602188c45ec9a0e46f73c92b9b..2884c4ed6a9081bf50ceb5b451494865293580e6 100644 --- a/mlir/test/mlir-tblgen/attr-or-type-format.td +++ b/mlir/test/mlir-tblgen/attr-or-type-format.td @@ -648,7 +648,7 @@ def TypeN : TestType<"TestP"> { // TYPE-LABEL: TestQType::parse // TYPE: if (auto result = [&]() -> ::mlir::OptionalParseResult { // TYPE: auto odsCustomResult = parseAB(odsParser -// TYPE: if (!odsCustomResult) return {}; +// TYPE: if (!odsCustomResult.has_value()) return {}; // TYPE: if (::mlir::failed(*odsCustomResult)) return ::mlir::failure(); // TYPE: return ::mlir::success(); // TYPE: }(); result.has_value() && ::mlir::failed(*result)) { diff --git a/mlir/test/mlir-tblgen/op-format.td b/mlir/test/mlir-tblgen/op-format.td index 3250589605f348901df446a380a70ad0927acf98..4a19ffb3dfcc6880a6c313ab69d48c19b1d1a22f 100644 --- a/mlir/test/mlir-tblgen/op-format.td +++ b/mlir/test/mlir-tblgen/op-format.td @@ -93,14 +93,14 @@ def OptionalGroupC : TestFormat_Op<[{ }]>, Arguments<(ins DefaultValuedStrAttr<StrAttr, "default">:$a)>; // CHECK-LABEL: OptionalGroupD::parse -// CHECK: if (auto result = [&]() -> ::mlir::OptionalParseResult { +// CHECK: if (auto optResult = [&]() -> ::mlir::OptionalParseResult { // CHECK: auto odsResult = parseCustom(parser, aOperand, bOperand); -// CHECK: if (!odsResult) return {}; +// CHECK: if (!odsResult.has_value()) return {}; // CHECK: if (::mlir::failed(*odsResult)) return ::mlir::failure(); // CHECK: return ::mlir::success(); -// CHECK: }(); result.has_value() && ::mlir::failed(*result)) { +// CHECK: }(); optResult.has_value() && ::mlir::failed(*optResult)) { // CHECK: return ::mlir::failure(); -// CHECK: } else if (result.has_value()) { +// CHECK: } else if (optResult.has_value()) { // CHECK-LABEL: OptionalGroupD::print // CHECK-NEXT: if (((getA()) || (getB()))) { diff --git a/mlir/test/mlir-translate/split-markers.mlir b/mlir/test/mlir-translate/split-markers.mlir new file mode 100644 index 0000000000000000000000000000000000000000..ed576bcd852360043577be48036693335197a167 --- /dev/null +++ b/mlir/test/mlir-translate/split-markers.mlir @@ -0,0 +1,35 @@ +// Check that (1) the output split marker is inserted and (2) the input file is +// split using the default split marker. +// RUN: mlir-translate %s -split-input-file -mlir-to-llvmir \ +// RUN: -output-split-marker="; -----" \ +// RUN: | FileCheck -check-prefix=CHECK-OUTPUT %s + +// With the second command, check that (3) the input split marker is used and +// (4) the output split marker is empty if not specified. +// RUN: mlir-translate %s -split-input-file="// ""-----" -mlir-to-llvmir \ +// RUN: -output-split-marker="; -----" \ +// RUN: | mlir-translate -split-input-file -import-llvm \ +// RUN: -split-input-file="; -----" \ +// RUN: | FileCheck -check-prefix=CHECK-ROUNDTRIP %s + +// Check that (5) the input is not split if `-split-input-file` is not given. +// RUN: mlir-translate %s -mlir-to-llvmir \ +// RUN: | FileCheck -check-prefix=CHECK-NOSPLIT %s + +// CHECK-OUTPUT: ModuleID +// CHECK-OUTPUT: ; ----- +// CHECK-OUTPUT-NEXT: ModuleID + +// CHECK-ROUNDTRIP: module {{.*}} { +// CHECK-ROUNDTRIP-NEXT: } +// CHECK-ROUNDTRIP-EMPTY: +// CHECK-ROUNDTRIP: module + +// CHECK-NOSPLIT: ModuleID +// CHECK-NOSPLIT-NOT: ModuleID + +module {} + +// ----- + +module {} diff --git a/mlir/test/python/dialects/index_dialect.py b/mlir/test/python/dialects/index_dialect.py new file mode 100644 index 0000000000000000000000000000000000000000..9db883469792c5c9f58e8650d0c1e9230d0ed654 --- /dev/null +++ b/mlir/test/python/dialects/index_dialect.py @@ -0,0 +1,235 @@ +# RUN: %PYTHON %s | FileCheck %s + +from mlir.ir import * +from mlir.dialects import index, arith + + +def run(f): + print("\nTEST:", f.__name__) + with Context() as ctx, Location.unknown(): + module = Module.create() + with InsertionPoint(module.body): + f(ctx) + print(module) + + +# CHECK-LABEL: TEST: testConstantOp +@run +def testConstantOp(ctx): + a = index.ConstantOp(value=42) + # CHECK: %{{.*}} = index.constant 42 + + +# CHECK-LABEL: TEST: testBoolConstantOp +@run +def testBoolConstantOp(ctx): + a = index.BoolConstantOp(value=True) + # CHECK: %{{.*}} = index.bool.constant true + + +# CHECK-LABEL: TEST: testAndOp +@run +def testAndOp(ctx): + a = index.ConstantOp(value=42) + r = index.AndOp(a, a) + # CHECK: %{{.*}} = index.and %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testOrOp +@run +def testOrOp(ctx): + a = index.ConstantOp(value=42) + r = index.OrOp(a, a) + # CHECK: %{{.*}} = index.or %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testXOrOp +@run +def testXOrOp(ctx): + a = index.ConstantOp(value=42) + r = index.XOrOp(a, a) + # CHECK: %{{.*}} = index.xor %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testCastSOp +@run +def testCastSOp(ctx): + a = index.ConstantOp(value=42) + b = arith.ConstantOp(value=23, result=IntegerType.get_signless(64)) + c = index.CastSOp(input=a, output=IntegerType.get_signless(32)) + d = index.CastSOp(input=b, output=IndexType.get()) + # CHECK: %{{.*}} = index.casts %{{.*}} : index to i32 + # CHECK: %{{.*}} = index.casts %{{.*}} : i64 to index + + +# CHECK-LABEL: TEST: testCastUOp +@run +def testCastUOp(ctx): + a = index.ConstantOp(value=42) + b = arith.ConstantOp(value=23, result=IntegerType.get_signless(64)) + c = index.CastUOp(input=a, output=IntegerType.get_signless(32)) + d = index.CastUOp(input=b, output=IndexType.get()) + # CHECK: %{{.*}} = index.castu %{{.*}} : index to i32 + # CHECK: %{{.*}} = index.castu %{{.*}} : i64 to index + + +# CHECK-LABEL: TEST: testCeilDivSOp +@run +def testCeilDivSOp(ctx): + a = index.ConstantOp(value=42) + r = index.CeilDivSOp(a, a) + # CHECK: %{{.*}} = index.ceildivs %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testCeilDivUOp +@run +def testCeilDivUOp(ctx): + a = index.ConstantOp(value=42) + r = index.CeilDivUOp(a, a) + # CHECK: %{{.*}} = index.ceildivu %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testCmpOp +@run +def testCmpOp(ctx): + a = index.ConstantOp(value=42) + b = index.ConstantOp(value=23) + pred = AttrBuilder.get("IndexCmpPredicateAttr")("slt", context=ctx) + r = index.CmpOp(pred, lhs=a, rhs=b) + # CHECK: %{{.*}} = index.cmp slt(%{{.*}}, %{{.*}}) + + +# CHECK-LABEL: TEST: testAddOp +@run +def testAddOp(ctx): + a = index.ConstantOp(value=42) + r = index.AddOp(a, a) + # CHECK: %{{.*}} = index.add %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testSubOp +@run +def testSubOp(ctx): + a = index.ConstantOp(value=42) + r = index.SubOp(a, a) + # CHECK: %{{.*}} = index.sub %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testMulOp +@run +def testMulOp(ctx): + a = index.ConstantOp(value=42) + r = index.MulOp(a, a) + # CHECK: %{{.*}} = index.mul %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testDivSOp +@run +def testDivSOp(ctx): + a = index.ConstantOp(value=42) + r = index.DivSOp(a, a) + # CHECK: %{{.*}} = index.divs %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testDivUOp +@run +def testDivUOp(ctx): + a = index.ConstantOp(value=42) + r = index.DivUOp(a, a) + # CHECK: %{{.*}} = index.divu %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testFloorDivSOp +@run +def testFloorDivSOp(ctx): + a = index.ConstantOp(value=42) + r = index.FloorDivSOp(a, a) + # CHECK: %{{.*}} = index.floordivs %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testMaxSOp +@run +def testMaxSOp(ctx): + a = index.ConstantOp(value=42) + b = index.ConstantOp(value=23) + r = index.MaxSOp(a, b) + # CHECK: %{{.*}} = index.maxs %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testMaxUOp +@run +def testMaxUOp(ctx): + a = index.ConstantOp(value=42) + b = index.ConstantOp(value=23) + r = index.MaxUOp(a, b) + # CHECK: %{{.*}} = index.maxu %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testMinSOp +@run +def testMinSOp(ctx): + a = index.ConstantOp(value=42) + b = index.ConstantOp(value=23) + r = index.MinSOp(a, b) + # CHECK: %{{.*}} = index.mins %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testMinUOp +@run +def testMinUOp(ctx): + a = index.ConstantOp(value=42) + b = index.ConstantOp(value=23) + r = index.MinUOp(a, b) + # CHECK: %{{.*}} = index.minu %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testRemSOp +@run +def testRemSOp(ctx): + a = index.ConstantOp(value=42) + b = index.ConstantOp(value=23) + r = index.RemSOp(a, b) + # CHECK: %{{.*}} = index.rems %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testRemUOp +@run +def testRemUOp(ctx): + a = index.ConstantOp(value=42) + b = index.ConstantOp(value=23) + r = index.RemUOp(a, b) + # CHECK: %{{.*}} = index.remu %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testShlOp +@run +def testShlOp(ctx): + a = index.ConstantOp(value=42) + b = index.ConstantOp(value=3) + r = index.ShlOp(a, b) + # CHECK: %{{.*}} = index.shl %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testShrSOp +@run +def testShrSOp(ctx): + a = index.ConstantOp(value=42) + b = index.ConstantOp(value=3) + r = index.ShrSOp(a, b) + # CHECK: %{{.*}} = index.shrs %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testShrUOp +@run +def testShrUOp(ctx): + a = index.ConstantOp(value=42) + b = index.ConstantOp(value=3) + r = index.ShrUOp(a, b) + # CHECK: %{{.*}} = index.shru %{{.*}}, %{{.*}} + + +# CHECK-LABEL: TEST: testSizeOfOp +@run +def testSizeOfOp(ctx): + r = index.SizeOfOp() + # CHECK: %{{.*}} = index.sizeof diff --git a/mlir/tools/mlir-opt/mlir-opt.cpp b/mlir/tools/mlir-opt/mlir-opt.cpp index 82b3881792bf3f338251f821a801b651ba5c3f58..6ce9f3041d6f48eb39c3212fde32c1bc0d0fab0a 100644 --- a/mlir/tools/mlir-opt/mlir-opt.cpp +++ b/mlir/tools/mlir-opt/mlir-opt.cpp @@ -68,6 +68,7 @@ void registerTosaTestQuantUtilAPIPass(); void registerVectorizerTestPass(); namespace test { +void registerTestCompositePass(); void registerCommutativityUtils(); void registerConvertCallOpPass(); void registerInliner(); @@ -195,6 +196,7 @@ void registerTestPasses() { registerVectorizerTestPass(); registerTosaTestQuantUtilAPIPass(); + mlir::test::registerTestCompositePass(); mlir::test::registerCommutativityUtils(); mlir::test::registerConvertCallOpPass(); mlir::test::registerInliner(); diff --git a/mlir/tools/mlir-pdll/mlir-pdll.cpp b/mlir/tools/mlir-pdll/mlir-pdll.cpp index 43e4aa50642403bd38b28167d6ee2f52c4b72331..c6ad6c361e99467c4aa1ceac19ffdb5f39d0f2d4 100644 --- a/mlir/tools/mlir-pdll/mlir-pdll.cpp +++ b/mlir/tools/mlir-pdll/mlir-pdll.cpp @@ -136,11 +136,20 @@ int main(int argc, char **argv) { llvm::cl::desc( "Print out the parsed ODS information from the input file"), llvm::cl::init(false)); - llvm::cl::opt<bool> splitInputFile( - "split-input-file", - llvm::cl::desc("Split the input file into pieces and process each " - "chunk independently"), - llvm::cl::init(false)); + llvm::cl::opt<std::string> inputSplitMarker{ + "split-input-file", llvm::cl::ValueOptional, + llvm::cl::callback([&](const std::string &str) { + // Implicit value: use default marker if flag was used without value. + if (str.empty()) + inputSplitMarker.setValue(kDefaultSplitMarker); + }), + llvm::cl::desc("Split the input file into chunks using the given or " + "default marker and process each chunk independently"), + llvm::cl::init("")}; + llvm::cl::opt<std::string> outputSplitMarker( + "output-split-marker", + llvm::cl::desc("Split marker to use for merging the ouput"), + llvm::cl::init(kDefaultSplitMarker)); llvm::cl::opt<enum OutputType> outputType( "x", llvm::cl::init(OutputType::AST), llvm::cl::desc("The type of output desired"), @@ -187,7 +196,7 @@ int main(int argc, char **argv) { dumpODS, includedFiles); }; if (failed(splitAndProcessBuffer(std::move(inputFile), processFn, outputStrOS, - splitInputFile))) + inputSplitMarker, outputSplitMarker))) return 1; // Write the output. diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp index f8e0c83da3c8a66f2a580fae7a74cfdabaf21fe0..6098808c646f765ef69cd5182a5286833c5d5fde 100644 --- a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp +++ b/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp @@ -622,7 +622,7 @@ void DefFormat::genCustomParser(CustomDirective *el, FmtContext &ctx, } os.unindent() << ");\n"; if (isOptional) { - os << "if (!odsCustomResult) return {};\n"; + os << "if (!odsCustomResult.has_value()) return {};\n"; os << "if (::mlir::failed(*odsCustomResult)) return ::mlir::failure();\n"; } else { os << "if (::mlir::failed(odsCustomResult)) return {};\n"; diff --git a/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp b/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp index 23bc9b00dc902da872d2abdf3cfcdc1a55b1d689..2c7acec3b1b8538a1abf039c2be3c3623f34594d 100644 --- a/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp +++ b/mlir/tools/mlir-tblgen/LLVMIRConversionGen.cpp @@ -272,6 +272,10 @@ static LogicalResult emitOneMLIRBuilder(const Record &record, raw_ostream &os, bs << "moduleImport.matchLocalVariableAttr"; } else if (name == "_label_attr") { bs << "moduleImport.matchLabelAttr"; + } else if (name == "_fpExceptionBehavior_attr") { + bs << "moduleImport.matchFPExceptionBehaviorAttr"; + } else if (name == "_roundingMode_attr") { + bs << "moduleImport.matchRoundingModeAttr"; } else if (name == "_resultType") { bs << "moduleImport.convertType(inst->getType())"; } else if (name == "_location") { diff --git a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp index 0d81912afb615880839dbbafdc67406960352539..3a697520dfad57b1e237a260426f845335576eae 100644 --- a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp +++ b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp @@ -3057,7 +3057,7 @@ void OpEmitter::genCodeForAddingArgAndRegionForBuilder( body << llvm::formatv( "static_cast<int32_t>(std::accumulate({0}.begin(), {0}.end(), 0, " "[](int32_t curSum, ::mlir::ValueRange range) {{ return curSum + " - "range.size(); }))", + "static_cast<int32_t>(range.size()); }))", operandName); } else { body << "static_cast<int32_t>(" << getArgumentName(op, i) << ".size())"; diff --git a/mlir/tools/mlir-tblgen/OpFormatGen.cpp b/mlir/tools/mlir-tblgen/OpFormatGen.cpp index eb8c0aba1d33b675a954d8f42491ffb22ffa2a36..1ffac059f19815dbe97b1a04b1b7b46653d8be88 100644 --- a/mlir/tools/mlir-tblgen/OpFormatGen.cpp +++ b/mlir/tools/mlir-tblgen/OpFormatGen.cpp @@ -1025,7 +1025,7 @@ static void genCustomDirectiveParser(CustomDirective *dir, MethodBody &body, body << ");\n"; if (isOptional) { - body << " if (!odsResult) return {};\n" + body << " if (!odsResult.has_value()) return {};\n" << " if (::mlir::failed(*odsResult)) return ::mlir::failure();\n"; } else { body << " if (odsResult) return ::mlir::failure();\n"; @@ -1285,13 +1285,13 @@ void OperationFormat::genElementParser(FormatElement *element, MethodBody &body, region->name); } } else if (auto *custom = dyn_cast<CustomDirective>(firstElement)) { - body << " if (auto result = [&]() -> ::mlir::OptionalParseResult {\n"; + body << " if (auto optResult = [&]() -> ::mlir::OptionalParseResult {\n"; genCustomDirectiveParser(custom, body, useProperties, opCppClassName, /*isOptional=*/true); body << " return ::mlir::success();\n" - << " }(); result.has_value() && ::mlir::failed(*result)) {\n" + << " }(); optResult.has_value() && ::mlir::failed(*optResult)) {\n" << " return ::mlir::failure();\n" - << " } else if (result.has_value()) {\n"; + << " } else if (optResult.has_value()) {\n"; } genElementParsers(firstElement, thenElements.drop_front(), diff --git a/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp b/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp index 9672a02cc08f68c48f1aee3c17e089aa462f81e8..2a7406f42f34b5b0b1efd7968847e3858e2b1d54 100644 --- a/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp +++ b/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp @@ -533,7 +533,7 @@ void InterfaceGenerator::emitInterfaceDecl(const Interface &interface) { << "struct " << interfaceTraitsName << " {\n"; emitConceptDecl(interface); emitModelDecl(interface); - os << "};"; + os << "};\n"; // Emit the derived trait for the interface. os << "template <typename " << valueTemplate << ">\n"; diff --git a/mlir/unittests/IR/AffineExprTest.cpp b/mlir/unittests/IR/AffineExprTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff154eb29807c3b7d82c2b9050cbaff20a0644e7 --- /dev/null +++ b/mlir/unittests/IR/AffineExprTest.cpp @@ -0,0 +1,32 @@ +//===- AffineExprTest.cpp - unit tests for affine expression API ----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "mlir/IR/AffineExpr.h" +#include "mlir/IR/Builders.h" +#include "gtest/gtest.h" + +using namespace mlir; + +// Test creating AffineExprs using the overloaded binary operators. +TEST(AffineExprTest, constructFromBinaryOperators) { + MLIRContext ctx; + OpBuilder b(&ctx); + + auto d0 = b.getAffineDimExpr(0); + auto d1 = b.getAffineDimExpr(1); + + auto sum = d0 + d1; + auto difference = d0 - d1; + auto product = d0 * d1; + auto remainder = d0 % d1; + + ASSERT_EQ(sum.getKind(), AffineExprKind::Add); + ASSERT_EQ(difference.getKind(), AffineExprKind::Add); + ASSERT_EQ(product.getKind(), AffineExprKind::Mul); + ASSERT_EQ(remainder.getKind(), AffineExprKind::Mod); +} diff --git a/mlir/unittests/IR/CMakeLists.txt b/mlir/unittests/IR/CMakeLists.txt index e7e9c3b565169320b6ab3d4711f8044d3571e2ab..71f8f449756ec01d00718e693bff08f2079014fc 100644 --- a/mlir/unittests/IR/CMakeLists.txt +++ b/mlir/unittests/IR/CMakeLists.txt @@ -1,5 +1,6 @@ add_mlir_unittest(MLIRIRTests AdaptorTest.cpp + AffineExprTest.cpp AffineMapTest.cpp AttributeTest.cpp DialectTest.cpp diff --git a/mlir/unittests/IR/InterfaceAttachmentTest.cpp b/mlir/unittests/IR/InterfaceAttachmentTest.cpp index 16de34c45ec6e08b17c4f4e41852bf2603162e06..58049a9969e3ab28db2e3ccbedc3e0925146938f 100644 --- a/mlir/unittests/IR/InterfaceAttachmentTest.cpp +++ b/mlir/unittests/IR/InterfaceAttachmentTest.cpp @@ -431,8 +431,8 @@ TEST(InterfaceAttachmentTest, PromisedInterfaces) { attr.hasPromiseOrImplementsInterface<TestExternalAttrInterface>()); // Add a promise `TestExternalAttrInterface`. - testDialect->declarePromisedInterface<test::SimpleAAttr, - TestExternalAttrInterface>(); + testDialect->declarePromisedInterface<TestExternalAttrInterface, + test::SimpleAAttr>(); EXPECT_TRUE( attr.hasPromiseOrImplementsInterface<TestExternalAttrInterface>()); diff --git a/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp b/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp index 794e19710fadca4cdd613ae7a3abcbf5a63cb6dd..d6b8d7392f3237214cf246648cb9f227dd8ab4e0 100644 --- a/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp +++ b/mlir/unittests/Interfaces/DataLayoutInterfacesTest.cpp @@ -345,6 +345,8 @@ TEST(DataLayout, NullSpec) { EXPECT_EQ(layout.getTypeABIAlignment(Float16Type::get(&ctx)), 16u); EXPECT_EQ(layout.getTypePreferredAlignment(IntegerType::get(&ctx, 42)), 128u); EXPECT_EQ(layout.getTypePreferredAlignment(Float16Type::get(&ctx)), 32u); + EXPECT_EQ(layout.getTypeIndexBitwidth(Float16Type::get(&ctx)), std::nullopt); + EXPECT_EQ(layout.getTypeIndexBitwidth(IndexType::get(&ctx)), 64u); EXPECT_EQ(layout.getAllocaMemorySpace(), Attribute()); EXPECT_EQ(layout.getProgramMemorySpace(), Attribute()); @@ -373,6 +375,8 @@ TEST(DataLayout, EmptySpec) { EXPECT_EQ(layout.getTypeABIAlignment(Float16Type::get(&ctx)), 16u); EXPECT_EQ(layout.getTypePreferredAlignment(IntegerType::get(&ctx, 42)), 128u); EXPECT_EQ(layout.getTypePreferredAlignment(Float16Type::get(&ctx)), 32u); + EXPECT_EQ(layout.getTypeIndexBitwidth(Float16Type::get(&ctx)), std::nullopt); + EXPECT_EQ(layout.getTypeIndexBitwidth(IndexType::get(&ctx)), 64u); EXPECT_EQ(layout.getAllocaMemorySpace(), Attribute()); EXPECT_EQ(layout.getProgramMemorySpace(), Attribute()); @@ -385,6 +389,7 @@ TEST(DataLayout, SpecWithEntries) { "dltest.op_with_layout"() { dltest.layout = #dltest.spec< #dlti.dl_entry<i42, 5>, #dlti.dl_entry<i16, 6>, + #dlti.dl_entry<index, 42>, #dlti.dl_entry<"dltest.alloca_memory_space", 5 : i32>, #dlti.dl_entry<"dltest.program_memory_space", 3 : i32>, #dlti.dl_entry<"dltest.global_memory_space", 2 : i32>, @@ -408,6 +413,8 @@ TEST(DataLayout, SpecWithEntries) { EXPECT_EQ(layout.getTypeABIAlignment(Float16Type::get(&ctx)), 8u); EXPECT_EQ(layout.getTypePreferredAlignment(IntegerType::get(&ctx, 42)), 16u); EXPECT_EQ(layout.getTypePreferredAlignment(Float16Type::get(&ctx)), 16u); + EXPECT_EQ(layout.getTypeIndexBitwidth(Float16Type::get(&ctx)), std::nullopt); + EXPECT_EQ(layout.getTypeIndexBitwidth(IndexType::get(&ctx)), 42u); EXPECT_EQ(layout.getTypeSize(IntegerType::get(&ctx, 32)), 32u); EXPECT_EQ(layout.getTypeSize(Float32Type::get(&ctx)), 32u); diff --git a/openmp/README.rst b/openmp/README.rst index 0e4916f44c68287ab31822731bcabc5922a2ed3c..2dfc8630858b80aad3e357ec4cbf9429373ea04f 100644 --- a/openmp/README.rst +++ b/openmp/README.rst @@ -141,7 +141,7 @@ Options for all Libraries Options for ``libomp`` ---------------------- -**LIBOMP_ARCH** = ``aarch64|arm|i386|loongarch64|mic|mips|mips64|ppc64|ppc64le|x86_64|riscv64|s390x`` +**LIBOMP_ARCH** = ``aarch64|aarch64_32|arm|i386|loongarch64|mic|mips|mips64|ppc64|ppc64le|x86_64|riscv64|s390x`` The default value for this option is chosen based on probing the compiler for architecture macros (e.g., is ``__x86_64__`` predefined by compiler?). diff --git a/openmp/docs/SupportAndFAQ.rst b/openmp/docs/SupportAndFAQ.rst index afc532cd73eef4244641c1c934580f02088a7934..9e6974dfbb13d2f32b2dbb62f4d8dc06667f8c52 100644 --- a/openmp/docs/SupportAndFAQ.rst +++ b/openmp/docs/SupportAndFAQ.rst @@ -279,11 +279,12 @@ Q: How to build an OpenMP offload capable compiler with an outdated host compile Enabling the OpenMP runtime will perform a two-stage build for you. If your host compiler is different from your system-wide compiler, you may need -to set the CMake variable `GCC_INSTALL_PREFIX` so clang will be able to find the -correct GCC toolchain in the second stage of the build. +to set ``CMAKE_{C,CXX}_FLAGS`` like +``--gcc-install-dir=/usr/lib/gcc/x86_64-linux-gnu/12`` so that clang will be +able to find the correct GCC toolchain in the second stage of the build. For example, if your system-wide GCC installation is too old to build LLVM and -you would like to use a newer GCC, set the CMake variable `GCC_INSTALL_PREFIX` +you would like to use a newer GCC, set ``--gcc-install-dir=`` to inform clang of the GCC installation you would like to use in the second stage. Q: How can I include OpenMP offloading support in my CMake project? diff --git a/openmp/libomptarget/CMakeLists.txt b/openmp/libomptarget/CMakeLists.txt index a74eff0c0bebf3bc2b31b9f1d6269b4289aad046..531198fae01699b72b5bf08cc71e2297022fad70 100644 --- a/openmp/libomptarget/CMakeLists.txt +++ b/openmp/libomptarget/CMakeLists.txt @@ -56,6 +56,8 @@ set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} x86_64-pc-linux-gnu-L set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} nvptx64-nvidia-cuda") set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} nvptx64-nvidia-cuda-LTO") set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} nvptx64-nvidia-cuda-JIT-LTO") +set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} s390x-ibm-linux-gnu") +set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} s390x-ibm-linux-gnu-LTO") # Once the plugins for the different targets are validated, they will be added to # the list of supported targets in the current system. @@ -143,8 +145,7 @@ add_subdirectory(DeviceRTL) add_subdirectory(tools) # Build target agnostic offloading library. -set(LIBOMPTARGET_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) -add_subdirectory(${LIBOMPTARGET_SRC_DIR}) +add_subdirectory(src) # Add tests. add_subdirectory(test) diff --git a/openmp/libomptarget/DeviceRTL/src/Debug.cpp b/openmp/libomptarget/DeviceRTL/src/Debug.cpp index aecc33c0497a7cb2c60775b4eb313018720bdc08..31cd54e3de35ce4fb1a1e827a9e9ca8a50b2351e 100644 --- a/openmp/libomptarget/DeviceRTL/src/Debug.cpp +++ b/openmp/libomptarget/DeviceRTL/src/Debug.cpp @@ -33,10 +33,10 @@ void __assert_fail(const char *expr, const char *file, unsigned line, void __assert_fail_internal(const char *expr, const char *msg, const char *file, unsigned line, const char *function) { if (msg) { - PRINTF("%s:%u: %s: Assertion %s (`%s') failed.\n", file, line, function, + PRINTF("%s:%u: %s: Assertion %s (`%s`) failed.\n", file, line, function, msg, expr); } else { - PRINTF("%s:%u: %s: Assertion `%s' failed.\n", file, line, function, expr); + PRINTF("%s:%u: %s: Assertion `%s` failed.\n", file, line, function, expr); } __builtin_trap(); } diff --git a/openmp/libomptarget/include/OpenMP/Mapping.h b/openmp/libomptarget/include/OpenMP/Mapping.h index 4bd676fc658a7d9106874ecabca4bb7a5184aaae..b9f5c1658293141bcdad8d879170dae4464a19dd 100644 --- a/openmp/libomptarget/include/OpenMP/Mapping.h +++ b/openmp/libomptarget/include/OpenMP/Mapping.h @@ -424,7 +424,8 @@ typedef int (*TargetDataFuncPtrTy)(ident_t *, DeviceTy &, int32_t, void **, map_var_info_t *, void **, AsyncInfoTy &, bool); -void dumpTargetPointerMappings(const ident_t *Loc, DeviceTy &Device); +void dumpTargetPointerMappings(const ident_t *Loc, DeviceTy &Device, + bool toStdOut = false); int targetDataBegin(ident_t *Loc, DeviceTy &Device, int32_t ArgNum, void **ArgsBase, void **Args, int64_t *ArgSizes, diff --git a/openmp/libomptarget/include/PluginManager.h b/openmp/libomptarget/include/PluginManager.h index 77684285ddf15e5daeaffd031ca4bfd7705379cd..eece7525e25e72a86b24f5a90c6b641244c58da2 100644 --- a/openmp/libomptarget/include/PluginManager.h +++ b/openmp/libomptarget/include/PluginManager.h @@ -45,24 +45,6 @@ struct PluginAdaptorTy { static llvm::Expected<std::unique_ptr<PluginAdaptorTy>> create(const std::string &Name); - /// Initialize as many devices as possible for this plugin adaptor. Devices - /// that fail to initialize are ignored. - void initDevices(PluginManager &PM); - - bool isUsed() const { return DeviceOffset >= 0; } - - /// Return the number of devices visible to the underlying plugin. - int32_t getNumberOfPluginDevices() const { return NumberOfPluginDevices; } - - /// Return the number of devices successfully initialized and visible to the - /// user. - int32_t getNumberOfUserDevices() const { return NumberOfUserDevices; } - - /// RTL index, index is the number of devices of other RTLs that were - /// registered before, i.e. the OpenMP index of the first device to be - /// registered with this RTL. - int32_t DeviceOffset = -1; - /// Name of the shared object file representing the plugin. std::string Name; @@ -76,16 +58,6 @@ struct PluginAdaptorTy { #include "Shared/PluginAPI.inc" #undef PLUGIN_API_HANDLE - llvm::DenseSet<const __tgt_device_image *> UsedImages; - -private: - /// Number of devices the underling plugins sees. - int32_t NumberOfPluginDevices = -1; - - /// Number of devices exposed to the user. This can be less than the number of - /// devices for the plugin if some failed to initialize. - int32_t NumberOfUserDevices = 0; - /// Create a plugin adaptor for filename \p Name with a dynamic library \p DL. PluginAdaptorTy(const std::string &Name, std::unique_ptr<llvm::sys::DynamicLibrary> DL); @@ -120,6 +92,11 @@ struct PluginManager { std::make_unique<DeviceImageTy>(TgtBinDesc, TgtDeviceImage)); } + /// Initialize as many devices as possible for this plugin adaptor. Devices + /// that fail to initialize are ignored. Returns the offset the devices were + /// registered at. + void initDevices(PluginAdaptorTy &RTL); + /// Return the device presented to the user as device \p DeviceNo if it is /// initialized and ready. Otherwise return an error explaining the problem. llvm::Expected<DeviceTy &> getDevice(uint32_t DeviceNo); @@ -169,12 +146,7 @@ struct PluginManager { return Devices.getExclusiveAccessor(); } - int getNumUsedPlugins() const { - int NCI = 0; - for (auto &P : PluginAdaptors) - NCI += P->isUsed(); - return NCI; - } + int getNumUsedPlugins() const { return DeviceOffsets.size(); } // Initialize all plugins. void initAllPlugins(); @@ -195,6 +167,15 @@ private: // List of all plugin adaptors, in use or not. llvm::SmallVector<std::unique_ptr<PluginAdaptorTy>> PluginAdaptors; + // Mapping of plugin adaptors to offsets in the device table. + llvm::DenseMap<const PluginAdaptorTy *, int32_t> DeviceOffsets; + + // Mapping of plugin adaptors to the number of used devices. + llvm::DenseMap<const PluginAdaptorTy *, int32_t> DeviceUsed; + + // Set of all device images currently in use. + llvm::DenseSet<const __tgt_device_image *> UsedImages; + /// Executable images and information extracted from the input images passed /// to the runtime. llvm::SmallVector<std::unique_ptr<DeviceImageTy>> DeviceImages; diff --git a/openmp/libomptarget/include/Shared/Debug.h b/openmp/libomptarget/include/Shared/Debug.h index a39626d15386b0d9351003153ef0dd51268ae654..7c3db8dbf119f6217b5c010a41fcf2201d066b67 100644 --- a/openmp/libomptarget/include/Shared/Debug.h +++ b/openmp/libomptarget/include/Shared/Debug.h @@ -136,10 +136,12 @@ inline uint32_t getDebugLevel() { } while (0) /// Print a generic information string used if LIBOMPTARGET_INFO=1 -#define INFO_MESSAGE(_num, ...) \ +#define INFO_MESSAGE(_num, ...) INFO_MESSAGE_TO(stderr, _num, __VA_ARGS__) + +#define INFO_MESSAGE_TO(_stdDst, _num, ...) \ do { \ - fprintf(stderr, GETNAME(TARGET_NAME) " device %d info: ", (int)_num); \ - fprintf(stderr, __VA_ARGS__); \ + fprintf(_stdDst, GETNAME(TARGET_NAME) " device %d info: ", (int)_num); \ + fprintf(_stdDst, __VA_ARGS__); \ } while (0) // Debugging messages @@ -187,4 +189,13 @@ inline uint32_t getDebugLevel() { } \ } while (false) +#define DUMP_INFO(toStdOut, _flags, _id, ...) \ + do { \ + if (toStdOut) { \ + INFO_MESSAGE_TO(stdout, _id, __VA_ARGS__); \ + } else { \ + INFO(_flags, _id, __VA_ARGS__); \ + } \ + } while (false) + #endif // OMPTARGET_SHARED_DEBUG_H diff --git a/openmp/libomptarget/include/omptarget.h b/openmp/libomptarget/include/omptarget.h index 8e0ccf191839da91325c6ba529d3c242316c8c53..323dee41630f2f9e66afa645801d402fdb6e309c 100644 --- a/openmp/libomptarget/include/omptarget.h +++ b/openmp/libomptarget/include/omptarget.h @@ -273,6 +273,7 @@ struct __tgt_target_non_contig { extern "C" { #endif +void ompx_dump_mapping_tables(void); int omp_get_num_devices(void); int omp_get_device_num(void); int omp_get_initial_device(void); diff --git a/openmp/libomptarget/plugins-nextgen/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/CMakeLists.txt index 3ca02368253ef8ba307e4211bd6b72f978e1742d..dbd82ac945171e6d81de871818e1cd898b1839a3 100644 --- a/openmp/libomptarget/plugins-nextgen/CMakeLists.txt +++ b/openmp/libomptarget/plugins-nextgen/CMakeLists.txt @@ -10,104 +10,68 @@ # ##===----------------------------------------------------------------------===## +# Common interface to handle creating a plugin library. +set(common_dir ${CMAKE_CURRENT_SOURCE_DIR}/common) add_subdirectory(common) - -# void build_generic_elf64(string tmachine, string tmachine_name, string tmachine_libname, string elf_machine_id); -# - build a plugin for an ELF based generic 64-bit target based on libffi. -# - tmachine: name of the machine processor as used in the cmake build system. -# - tmachine_name: name of the machine to be printed with the debug messages. -# - tmachine_libname: machine name to be appended to the plugin library name. -macro(build_generic_elf64 tmachine tmachine_name tmachine_libname tmachine_triple elf_machine_id) -if(CMAKE_SYSTEM_PROCESSOR MATCHES "${tmachine}$") - # Define macro to be used as prefix of the runtime messages for this target. - add_definitions("-DTARGET_NAME=${tmachine_name}") - - # Define debug prefix. TODO: This should be automatized in the Debug.h but - # it requires changing the original plugins. - add_definitions(-DDEBUG_PREFIX="TARGET ${tmachine_name} RTL") - - # Define the macro with the ELF e_machine for this target. - add_definitions("-DTARGET_ELF_ID=${elf_machine_id}") - - # Define target triple - add_definitions("-DLIBOMPTARGET_NEXTGEN_GENERIC_PLUGIN_TRIPLE=${tmachine}") - - add_llvm_library("omptarget.rtl.${tmachine_libname}" - SHARED - - ${CMAKE_CURRENT_SOURCE_DIR}/../generic-elf-64bit/src/rtl.cpp - - ADDITIONAL_HEADER_DIRS - ${LIBOMPTARGET_INCLUDE_DIR} - - LINK_LIBS - PRIVATE - PluginCommon - ${OPENMP_PTHREAD_LIB} +function(add_target_library target_name lib_name) + add_llvm_library(${target_name} SHARED + LINK_COMPONENTS + ${LLVM_TARGETS_TO_BUILD} + AggressiveInstCombine + Analysis + BinaryFormat + BitReader + BitWriter + CodeGen + Core + Extensions + InstCombine + Instrumentation + IPO + IRReader + Linker + MC + Object + Passes + Remarks + ScalarOpts + Support + Target + TargetParser + TransformUtils + Vectorize NO_INSTALL_RPATH BUILDTREE_ONLY ) - if(LIBOMPTARGET_DEP_LIBFFI_FOUND) - libomptarget_say("Building ${tmachine_libname} plugin linked with libffi") - if(FFI_STATIC_LIBRARIES) - target_link_libraries( - "omptarget.rtl.${tmachine_libname}" PRIVATE FFI::ffi_static) - else() - target_link_libraries( - "omptarget.rtl.${tmachine_libname}" PRIVATE FFI::ffi) - endif() - else() - libomptarget_say("Building ${tmachine_libname} plugin for dlopened libffi") - target_sources("omptarget.rtl.${tmachine_libname}" PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/../generic-elf-64bit/dynamic_ffi/ffi.cpp) - target_include_directories("omptarget.rtl.${tmachine_libname}" PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/../generic-elf-64bit/dynamic_ffi) - endif() + llvm_update_compile_flags(${target_name}) + target_link_libraries(${target_name} PRIVATE + PluginCommon ${OPENMP_PTHREAD_LIB}) - if(OMPT_TARGET_DEFAULT AND LIBOMPTARGET_OMPT_SUPPORT) - target_link_libraries("omptarget.rtl.${tmachine_libname}" PRIVATE OMPT) - endif() + target_compile_definitions(${target_name} PRIVATE TARGET_NAME=${lib_name}) + target_compile_definitions(${target_name} PRIVATE + DEBUG_PREFIX="TARGET ${lib_name} RTL") - if(LIBOMP_HAVE_VERSION_SCRIPT_FLAG) - target_link_libraries("omptarget.rtl.${tmachine_libname}" PRIVATE - "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports") + if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + # On FreeBSD, the 'environ' symbol is undefined at link time, but resolved by + # the dynamic linker at runtime. Therefore, allow the symbol to be undefined + # when creating a shared library. + target_link_libraries(${target_name} PRIVATE "-Wl,--allow-shlib-undefined") + else() + target_link_libraries(${target_name} PRIVATE "-Wl,-z,defs") endif() - # Install plugin under the lib destination folder. - install(TARGETS "omptarget.rtl.${tmachine_libname}" - LIBRARY DESTINATION "${OPENMP_INSTALL_LIBDIR}") - set_target_properties("omptarget.rtl.${tmachine_libname}" PROPERTIES - INSTALL_RPATH "$ORIGIN" BUILD_RPATH "$ORIGIN:${CMAKE_CURRENT_BINARY_DIR}/.." - POSITION_INDEPENDENT_CODE ON - CXX_VISIBILITY_PRESET protected) - - target_include_directories("omptarget.rtl.${tmachine_libname}" PRIVATE - ${LIBOMPTARGET_INCLUDE_DIR}) - - if(LIBOMPTARGET_DEP_LIBFFI_FOUND) - list(APPEND LIBOMPTARGET_TESTED_PLUGINS "omptarget.rtl.${tmachine_libname}") - set(LIBOMPTARGET_TESTED_PLUGINS - "${LIBOMPTARGET_TESTED_PLUGINS}" PARENT_SCOPE) - set(LIBOMPTARGET_SYSTEM_TARGETS - "${LIBOMPTARGET_SYSTEM_TARGETS} ${tmachine_triple} - ${tmachine_triple}-LTO" PARENT_SCOPE) - else() - libomptarget_say("Not generating ${tmachine_name} tests. LibFFI not found.") + if(LIBOMP_HAVE_VERSION_SCRIPT_FLAG) + target_link_libraries(${target_name} PRIVATE + "-Wl,--version-script=${common_dir}/../exports") endif() -else() - libomptarget_say("Not building ${tmachine_name} NextGen offloading plugin: machine not found in the system.") -endif() -endmacro() + set_target_properties(${target_name} PROPERTIES CXX_VISIBILITY_PRESET protected) +endfunction() -add_subdirectory(aarch64) add_subdirectory(amdgpu) add_subdirectory(cuda) -add_subdirectory(ppc64) -add_subdirectory(ppc64le) -add_subdirectory(x86_64) -add_subdirectory(s390x) +add_subdirectory(host) # Make sure the parent scope can see the plugins that will be created. set(LIBOMPTARGET_SYSTEM_TARGETS "${LIBOMPTARGET_SYSTEM_TARGETS}" PARENT_SCOPE) diff --git a/openmp/libomptarget/plugins-nextgen/aarch64/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/aarch64/CMakeLists.txt deleted file mode 100644 index 2c2b753590e205cd1e5d68d1ff89233eb10dbb1c..0000000000000000000000000000000000000000 --- a/openmp/libomptarget/plugins-nextgen/aarch64/CMakeLists.txt +++ /dev/null @@ -1,17 +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 -# -##===----------------------------------------------------------------------===## -# -# Build a plugin for an aarch64 machine if available. -# -##===----------------------------------------------------------------------===## - -if(CMAKE_SYSTEM_NAME MATCHES "Linux") - build_generic_elf64("aarch64" "aarch64" "aarch64" "aarch64-unknown-linux-gnu" "183") -else() - libomptarget_say("Not building aarch64 NextGen offloading plugin: machine not found in the system.") -endif() diff --git a/openmp/libomptarget/plugins-nextgen/amdgpu/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/amdgpu/CMakeLists.txt index 8fbfe4d9b13f73a3dc443a1c07c57969744c443d..40df77102c78fb2c335bb0fce487da267966f2d5 100644 --- a/openmp/libomptarget/plugins-nextgen/amdgpu/CMakeLists.txt +++ b/openmp/libomptarget/plugins-nextgen/amdgpu/CMakeLists.txt @@ -27,76 +27,23 @@ if(NOT (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64)|(ppc64le)|(aarch64)$" AND CMAKE return() endif() -################################################################################ -# Define the suffix for the runtime messaging dumps. -add_definitions(-DTARGET_NAME=AMDGPU) - -# Define debug prefix. TODO: This should be automatized in the Debug.h but it -# requires changing the original plugins. -add_definitions(-DDEBUG_PREFIX="TARGET AMDGPU RTL") +# Create the library and add the default arguments. +add_target_library(omptarget.rtl.amdgpu AMDGPU) -set(LIBOMPTARGET_DLOPEN_LIBHSA OFF) -option(LIBOMPTARGET_FORCE_DLOPEN_LIBHSA "Build with dlopened libhsa" ${LIBOMPTARGET_DLOPEN_LIBHSA}) - -if (${hsa-runtime64_FOUND} AND NOT LIBOMPTARGET_FORCE_DLOPEN_LIBHSA) - libomptarget_say("Building AMDGPU NextGen plugin linked against libhsa") - set(LIBOMPTARGET_EXTRA_SOURCE) - set(LIBOMPTARGET_DEP_LIBRARIES hsa-runtime64::hsa-runtime64) -else() - libomptarget_say("Building AMDGPU NextGen plugin for dlopened libhsa") - include_directories(dynamic_hsa) - set(LIBOMPTARGET_EXTRA_SOURCE dynamic_hsa/hsa.cpp) - set(LIBOMPTARGET_DEP_LIBRARIES) -endif() +target_sources(omptarget.rtl.amdgpu PRIVATE src/rtl.cpp) +target_include_directories(omptarget.rtl.amdgpu PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/utils) -if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - # On FreeBSD, the 'environ' symbol is undefined at link time, but resolved by - # the dynamic linker at runtime. Therefore, allow the symbol to be undefined - # when creating a shared library. - set(LDFLAGS_UNDEFINED "-Wl,--allow-shlib-undefined") +option(LIBOMPTARGET_FORCE_DLOPEN_LIBHSA "Build with dlopened libhsa" OFF) +if(hsa-runtime64_FOUND AND NOT LIBOMPTARGET_FORCE_DLOPEN_LIBHSA) + libomptarget_say("Building AMDGPU plugin linked against libhsa") + target_link_libraries(omptarget.rtl.amdgpu PRIVATE hsa-runtime64::hsa-runtime64) else() - set(LDFLAGS_UNDEFINED "-Wl,-z,defs") + libomptarget_say("Building AMDGPU plugin for dlopened libhsa") + target_include_directories(omptarget.rtl.amdgpu PRIVATE dynamic_hsa) + target_sources(omptarget.rtl.amdgpu PRIVATE dynamic_hsa/hsa.cpp) endif() -add_llvm_library(omptarget.rtl.amdgpu SHARED - src/rtl.cpp - ${LIBOMPTARGET_EXTRA_SOURCE} - - ADDITIONAL_HEADER_DIRS - ${LIBOMPTARGET_INCLUDE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/utils - - LINK_COMPONENTS - Support - Object - - LINK_LIBS - PRIVATE - PluginCommon - ${LIBOMPTARGET_DEP_LIBRARIES} - ${OPENMP_PTHREAD_LIB} - ${LDFLAGS_UNDEFINED} - - NO_INSTALL_RPATH - BUILDTREE_ONLY -) - -if ((OMPT_TARGET_DEFAULT) AND (LIBOMPTARGET_OMPT_SUPPORT)) - target_link_libraries(omptarget.rtl.amdgpu PRIVATE OMPT) -endif() - -if (LIBOMP_HAVE_VERSION_SCRIPT_FLAG) - target_link_libraries(omptarget.rtl.amdgpu PRIVATE - "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports") -endif() - -target_include_directories( - omptarget.rtl.amdgpu - PRIVATE - ${LIBOMPTARGET_INCLUDE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/utils -) - # Configure testing for the AMDGPU plugin. We will build tests if we could a # functional AMD GPU on the system, or if manually specifies by the user. option(LIBOMPTARGET_FORCE_AMDGPU_TESTS "Build AMDGPU libomptarget tests" OFF) @@ -114,5 +61,4 @@ endif() # Install plugin under the lib destination folder. install(TARGETS omptarget.rtl.amdgpu LIBRARY DESTINATION "${OPENMP_INSTALL_LIBDIR}") set_target_properties(omptarget.rtl.amdgpu PROPERTIES - INSTALL_RPATH "$ORIGIN" BUILD_RPATH "$ORIGIN:${CMAKE_CURRENT_BINARY_DIR}/.." - CXX_VISIBILITY_PRESET protected) + INSTALL_RPATH "$ORIGIN" BUILD_RPATH "$ORIGIN:${CMAKE_CURRENT_BINARY_DIR}/..") diff --git a/openmp/libomptarget/plugins-nextgen/amdgpu/src/rtl.cpp b/openmp/libomptarget/plugins-nextgen/amdgpu/src/rtl.cpp index fce7454bf2800d4a7748b9c6663efcdf7cf23cb4..a0fdde951b74a776a853649248e27c267b0433a5 100644 --- a/openmp/libomptarget/plugins-nextgen/amdgpu/src/rtl.cpp +++ b/openmp/libomptarget/plugins-nextgen/amdgpu/src/rtl.cpp @@ -371,7 +371,8 @@ private: struct AMDGPUMemoryManagerTy : public DeviceAllocatorTy { /// Create an empty memory manager. - AMDGPUMemoryManagerTy() : MemoryPool(nullptr), MemoryManager(nullptr) {} + AMDGPUMemoryManagerTy(AMDGPUPluginTy &Plugin) + : Plugin(Plugin), MemoryPool(nullptr), MemoryManager(nullptr) {} /// Initialize the memory manager from a memory pool. Error init(AMDGPUMemoryPoolTy &MemoryPool) { @@ -429,6 +430,9 @@ private: return OFFLOAD_SUCCESS; } + /// The underlying plugin that owns this memory manager. + AMDGPUPluginTy &Plugin; + /// The memory pool used to allocate memory. AMDGPUMemoryPoolTy *MemoryPool; @@ -1744,9 +1748,10 @@ protected: /// HSA host agent. We aggregate all its resources into the same instance. struct AMDHostDeviceTy : public AMDGenericDeviceTy { /// Create a host device from an array of host agents. - AMDHostDeviceTy(const llvm::SmallVector<hsa_agent_t> &HostAgents) - : AMDGenericDeviceTy(), Agents(HostAgents), ArgsMemoryManager(), - PinnedMemoryManager() { + AMDHostDeviceTy(AMDGPUPluginTy &Plugin, + const llvm::SmallVector<hsa_agent_t> &HostAgents) + : AMDGenericDeviceTy(), Agents(HostAgents), ArgsMemoryManager(Plugin), + PinnedMemoryManager(Plugin) { assert(HostAgents.size() && "No host agent found"); } @@ -1840,9 +1845,10 @@ private: /// generic device class. struct AMDGPUDeviceTy : public GenericDeviceTy, AMDGenericDeviceTy { // Create an AMDGPU device with a device id and default AMDGPU grid values. - AMDGPUDeviceTy(int32_t DeviceId, int32_t NumDevices, + AMDGPUDeviceTy(GenericPluginTy &Plugin, int32_t DeviceId, int32_t NumDevices, AMDHostDeviceTy &HostDevice, hsa_agent_t Agent) - : GenericDeviceTy(DeviceId, NumDevices, {0}), AMDGenericDeviceTy(), + : GenericDeviceTy(Plugin, DeviceId, NumDevices, {0}), + AMDGenericDeviceTy(), OMPX_NumQueues("LIBOMPTARGET_AMDGPU_NUM_HSA_QUEUES", 4), OMPX_QueueSize("LIBOMPTARGET_AMDGPU_HSA_QUEUE_SIZE", 512), OMPX_DefaultTeamsPerCU("LIBOMPTARGET_AMDGPU_TEAMS_PER_CU", 4), @@ -2088,7 +2094,7 @@ struct AMDGPUDeviceTy : public GenericDeviceTy, AMDGenericDeviceTy { /// Allocate and construct an AMDGPU kernel. Expected<GenericKernelTy &> constructKernel(const char *Name) override { // Allocate and construct the AMDGPU kernel. - AMDGPUKernelTy *AMDGPUKernel = Plugin::get().allocate<AMDGPUKernelTy>(); + AMDGPUKernelTy *AMDGPUKernel = Plugin.allocate<AMDGPUKernelTy>(); if (!AMDGPUKernel) return Plugin::error("Failed to allocate memory for AMDGPU kernel"); @@ -2138,8 +2144,7 @@ struct AMDGPUDeviceTy : public GenericDeviceTy, AMDGenericDeviceTy { Expected<DeviceImageTy *> loadBinaryImpl(const __tgt_device_image *TgtImage, int32_t ImageId) override { // Allocate and initialize the image object. - AMDGPUDeviceImageTy *AMDImage = - Plugin::get().allocate<AMDGPUDeviceImageTy>(); + AMDGPUDeviceImageTy *AMDImage = Plugin.allocate<AMDGPUDeviceImageTy>(); new (AMDImage) AMDGPUDeviceImageTy(ImageId, *this, TgtImage); // Load the HSA executable. @@ -2397,6 +2402,27 @@ struct AMDGPUDeviceTy : public GenericDeviceTy, AMDGenericDeviceTy { AsyncInfoWrapperTy &AsyncInfoWrapper) override { AMDGPUDeviceTy &DstDevice = static_cast<AMDGPUDeviceTy &>(DstGenericDevice); + // For large transfers use synchronous behavior. + if (Size >= OMPX_MaxAsyncCopyBytes) { + if (AsyncInfoWrapper.hasQueue()) + if (auto Err = synchronize(AsyncInfoWrapper)) + return Err; + + AMDGPUSignalTy Signal; + if (auto Err = Signal.init()) + return Err; + + if (auto Err = utils::asyncMemCopy( + useMultipleSdmaEngines(), DstPtr, DstDevice.getAgent(), SrcPtr, + getAgent(), (uint64_t)Size, 0, nullptr, Signal.get())) + return Err; + + if (auto Err = Signal.wait(getStreamBusyWaitMicroseconds())) + return Err; + + return Signal.deinit(); + } + AMDGPUStreamTy *Stream = nullptr; if (auto Err = getStream(AsyncInfoWrapper, Stream)) return Err; @@ -2697,7 +2723,7 @@ struct AMDGPUDeviceTy : public GenericDeviceTy, AMDGenericDeviceTy { } Error setDeviceHeapSize(uint64_t Value) override { for (DeviceImageTy *Image : LoadedImages) - if (auto Err = setupDeviceMemoryPool(Plugin::get(), *Image, Value)) + if (auto Err = setupDeviceMemoryPool(Plugin, *Image, Value)) return Err; DeviceMemoryPoolSize = Value; return Plugin::success(); @@ -2737,7 +2763,7 @@ struct AMDGPUDeviceTy : public GenericDeviceTy, AMDGenericDeviceTy { return utils::iterateAgentMemoryPools( Agent, [&](hsa_amd_memory_pool_t HSAMemoryPool) { AMDGPUMemoryPoolTy *MemoryPool = - Plugin::get().allocate<AMDGPUMemoryPoolTy>(); + Plugin.allocate<AMDGPUMemoryPoolTy>(); new (MemoryPool) AMDGPUMemoryPoolTy(HSAMemoryPool); AllMemoryPools.push_back(MemoryPool); return HSA_STATUS_SUCCESS; @@ -3090,7 +3116,7 @@ struct AMDGPUPluginTy final : public GenericPluginTy { // Initialize the host device using host agents. HostDevice = allocate<AMDHostDeviceTy>(); - new (HostDevice) AMDHostDeviceTy(HostAgents); + new (HostDevice) AMDHostDeviceTy(*this, HostAgents); // Setup the memory pools of available for the host. if (auto Err = HostDevice->init()) @@ -3115,6 +3141,18 @@ struct AMDGPUPluginTy final : public GenericPluginTy { return Plugin::check(Status, "Error in hsa_shut_down: %s"); } + /// Creates an AMDGPU device. + GenericDeviceTy *createDevice(GenericPluginTy &Plugin, int32_t DeviceId, + int32_t NumDevices) override { + return new AMDGPUDeviceTy(Plugin, DeviceId, NumDevices, getHostDevice(), + getKernelAgent(DeviceId)); + } + + /// Creates an AMDGPU global handler. + GenericGlobalHandlerTy *createGlobalHandler() override { + return new AMDGPUGlobalHandlerTy(); + } + Triple::ArchType getTripleArch() const override { return Triple::amdgcn; } /// Get the ELF code for recognizing the compatible image binary. @@ -3237,7 +3275,9 @@ Error AMDGPUKernelTy::launchImpl(GenericDeviceTy &GenericDevice, // 56 bytes per allocation. uint32_t AllArgsSize = KernelArgsSize + ImplicitArgsSize; - AMDHostDeviceTy &HostDevice = Plugin::get<AMDGPUPluginTy>().getHostDevice(); + AMDGPUPluginTy &AMDGPUPlugin = + static_cast<AMDGPUPluginTy &>(GenericDevice.Plugin); + AMDHostDeviceTy &HostDevice = AMDGPUPlugin.getHostDevice(); AMDGPUMemoryManagerTy &ArgsMemoryManager = HostDevice.getArgsMemoryManager(); void *AllArgs = nullptr; @@ -3347,20 +3387,10 @@ Error AMDGPUKernelTy::printLaunchInfoDetails(GenericDeviceTy &GenericDevice, return Plugin::success(); } -GenericPluginTy *Plugin::createPlugin() { return new AMDGPUPluginTy(); } - -GenericDeviceTy *Plugin::createDevice(int32_t DeviceId, int32_t NumDevices) { - AMDGPUPluginTy &Plugin = get<AMDGPUPluginTy &>(); - return new AMDGPUDeviceTy(DeviceId, NumDevices, Plugin.getHostDevice(), - Plugin.getKernelAgent(DeviceId)); -} - -GenericGlobalHandlerTy *Plugin::createGlobalHandler() { - return new AMDGPUGlobalHandlerTy(); -} +GenericPluginTy *PluginTy::createPlugin() { return new AMDGPUPluginTy(); } template <typename... ArgsTy> -Error Plugin::check(int32_t Code, const char *ErrFmt, ArgsTy... Args) { +static Error Plugin::check(int32_t Code, const char *ErrFmt, ArgsTy... Args) { hsa_status_t ResultCode = static_cast<hsa_status_t>(Code); if (ResultCode == HSA_STATUS_SUCCESS || ResultCode == HSA_STATUS_INFO_BREAK) return Error::success(); @@ -3384,7 +3414,7 @@ void *AMDGPUMemoryManagerTy::allocate(size_t Size, void *HstPtr, } assert(Ptr && "Invalid pointer"); - auto &KernelAgents = Plugin::get<AMDGPUPluginTy>().getKernelAgents(); + auto &KernelAgents = Plugin.getKernelAgents(); // Allow all kernel agents to access the allocation. if (auto Err = MemoryPool->enableAccess(Ptr, Size, KernelAgents)) { @@ -3427,7 +3457,8 @@ void *AMDGPUDeviceTy::allocate(size_t Size, void *, TargetAllocTy Kind) { } if (Alloc) { - auto &KernelAgents = Plugin::get<AMDGPUPluginTy>().getKernelAgents(); + auto &KernelAgents = + static_cast<AMDGPUPluginTy &>(Plugin).getKernelAgents(); // Inherently necessary for host or shared allocations // Also enabled for device memory to allow device to device memcpy diff --git a/openmp/libomptarget/plugins-nextgen/common/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/common/CMakeLists.txt index 085d443071650ebbccfa6529d760a4793bf1d63d..a7350e662a7c9a887444b34c65e292fe4520e1ba 100644 --- a/openmp/libomptarget/plugins-nextgen/common/CMakeLists.txt +++ b/openmp/libomptarget/plugins-nextgen/common/CMakeLists.txt @@ -19,6 +19,7 @@ add_library(PluginCommon OBJECT src/RPC.cpp src/Utils/ELF.cpp ) +add_dependencies(PluginCommon intrinsics_gen) # Only enable JIT for those targets that LLVM can support. string(TOUPPER "${LLVM_TARGETS_TO_BUILD}" TargetsSupported) @@ -26,45 +27,6 @@ foreach(Target ${TargetsSupported}) target_compile_definitions(PluginCommon PRIVATE "LIBOMPTARGET_JIT_${Target}") endforeach() -# This is required when using LLVM libraries. -llvm_update_compile_flags(PluginCommon) - -if (LLVM_LINK_LLVM_DYLIB) - set(llvm_libs LLVM) -else() - llvm_map_components_to_libnames(llvm_libs - ${LLVM_TARGETS_TO_BUILD} - AggressiveInstCombine - Analysis - BinaryFormat - BitReader - BitWriter - CodeGen - Core - Extensions - InstCombine - Instrumentation - IPO - IRReader - Linker - MC - Object - Passes - Remarks - ScalarOpts - Support - Target - TargetParser - TransformUtils - Vectorize - ) -endif() - -target_link_libraries(PluginCommon - PUBLIC - ${llvm_libs} -) - # Include the RPC server from the `libc` project if availible. if(TARGET llvmlibc_rpc_server AND ${LIBOMPTARGET_GPU_LIBC_SUPPORT}) target_link_libraries(PluginCommon PRIVATE llvmlibc_rpc_server) @@ -82,8 +44,10 @@ elseif(${LIBOMPTARGET_GPU_LIBC_SUPPORT}) endif() endif() -if ((OMPT_TARGET_DEFAULT) AND (LIBOMPTARGET_OMPT_SUPPORT)) - target_link_libraries(PluginCommon PUBLIC OMPT) +# If we have OMPT enabled include it in the list of sources. +if (OMPT_TARGET_DEFAULT AND LIBOMPTARGET_OMPT_SUPPORT) + target_sources(PluginCommon PRIVATE OMPT/OmptCallback.cpp) + target_include_directories(PluginCommon PRIVATE OMPT) endif() # Define the TARGET_NAME and DEBUG_PREFIX. @@ -95,16 +59,12 @@ target_compile_definitions(PluginCommon PRIVATE target_compile_options(PluginCommon PUBLIC ${offload_compile_flags}) target_link_options(PluginCommon PUBLIC ${offload_link_flags}) -target_include_directories(PluginCommon - PRIVATE - ${LIBOMPTARGET_INCLUDE_DIR} - PUBLIC +target_include_directories(PluginCommon PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include + ${LIBOMPTARGET_LLVM_INCLUDE_DIRS} + ${LIBOMPTARGET_INCLUDE_DIR} ) set_target_properties(PluginCommon PROPERTIES POSITION_INDEPENDENT_CODE ON CXX_VISIBILITY_PRESET protected) - -add_subdirectory(OMPT) - diff --git a/openmp/libomptarget/plugins-nextgen/common/OMPT/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/common/OMPT/CMakeLists.txt deleted file mode 100644 index be4c743665b3e978e57ff19288941ef7bf2c4dcd..0000000000000000000000000000000000000000 --- a/openmp/libomptarget/plugins-nextgen/common/OMPT/CMakeLists.txt +++ /dev/null @@ -1,70 +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 -# -##===----------------------------------------------------------------------===## -# -# Aggregation of parts which can be used by OpenMP tools -# -##===----------------------------------------------------------------------===## - -# NOTE: Don't try to build `OMPT` using `add_llvm_library` because we -# don't want to export `OMPT` while `add_llvm_library` requires that. -add_library(OMPT OBJECT - OmptCallback.cpp) - -# This is required when using LLVM libraries. -llvm_update_compile_flags(OMPT) - -if (LLVM_LINK_LLVM_DYLIB) - set(llvm_libs LLVM) -else() - llvm_map_components_to_libnames(llvm_libs - ${LLVM_TARGETS_TO_BUILD} - AggressiveInstCombine - Analysis - BinaryFormat - BitReader - BitWriter - CodeGen - Core - Extensions - InstCombine - Instrumentation - IPO - IRReader - Linker - MC - Object - Passes - Remarks - ScalarOpts - Support - Target - TargetParser - TransformUtils - Vectorize - ) -endif() - -target_link_libraries(OMPT - PUBLIC - ${llvm_libs} -) - -# Define the TARGET_NAME and DEBUG_PREFIX. -target_compile_definitions(OMPT PRIVATE - TARGET_NAME="OMPT" - DEBUG_PREFIX="OMPT" -) - -target_include_directories(OMPT - INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} - PRIVATE ${LIBOMPTARGET_INCLUDE_DIR} -) - -set_target_properties(OMPT PROPERTIES - POSITION_INDEPENDENT_CODE ON - CXX_VISIBILITY_PRESET protected) diff --git a/openmp/libomptarget/plugins-nextgen/common/include/GlobalHandler.h b/openmp/libomptarget/plugins-nextgen/common/include/GlobalHandler.h index 5c767995126b771608b2c0470db91bc4c3a09ce3..829b4b72911935961eae5e49d052cbb4434dedac 100644 --- a/openmp/libomptarget/plugins-nextgen/common/include/GlobalHandler.h +++ b/openmp/libomptarget/plugins-nextgen/common/include/GlobalHandler.h @@ -104,7 +104,7 @@ public: virtual ~GenericGlobalHandlerTy() {} /// Helper function for getting an ELF from a device image. - Expected<ELF64LEObjectFile> getELFObjectFile(DeviceImageTy &Image); + Expected<std::unique_ptr<ObjectFile>> getELFObjectFile(DeviceImageTy &Image); /// Returns whether the symbol named \p SymName is present in the given \p /// Image. diff --git a/openmp/libomptarget/plugins-nextgen/common/include/PluginInterface.h b/openmp/libomptarget/plugins-nextgen/common/include/PluginInterface.h index 9645ab2a67262583c8a8a10aa1adcb28421954df..79e8464bfda5c15fed7fcdae2fc0c9e8f08c7581 100644 --- a/openmp/libomptarget/plugins-nextgen/common/include/PluginInterface.h +++ b/openmp/libomptarget/plugins-nextgen/common/include/PluginInterface.h @@ -289,7 +289,7 @@ struct GenericKernelTy { /// Return a device pointer to a new kernel launch environment. Expected<KernelLaunchEnvironmentTy *> - getKernelLaunchEnvironment(GenericDeviceTy &GenericDevice, + getKernelLaunchEnvironment(GenericDeviceTy &GenericDevice, uint32_t Version, AsyncInfoWrapperTy &AsyncInfo) const; /// Indicate whether an execution mode is valid. @@ -610,7 +610,7 @@ public: struct GenericDeviceTy : public DeviceAllocatorTy { /// Construct a device with its device id within the plugin, the number of /// devices in the plugin and the grid values for that kind of device. - GenericDeviceTy(int32_t DeviceId, int32_t NumDevices, + GenericDeviceTy(GenericPluginTy &Plugin, int32_t DeviceId, int32_t NumDevices, const llvm::omp::GV &GridValues); /// Get the device identifier within the corresponding plugin. Notice that @@ -860,6 +860,9 @@ struct GenericDeviceTy : public DeviceAllocatorTy { /// Allocate and construct a kernel object. virtual Expected<GenericKernelTy &> constructKernel(const char *Name) = 0; + /// Reference to the underlying plugin that created this device. + GenericPluginTy &Plugin; + private: /// Get and set the stack size and heap size for the device. If not used, the /// plugin can implement the setters as no-op and setting the output @@ -976,6 +979,14 @@ struct GenericPluginTy { Error deinit(); virtual Error deinitImpl() = 0; + /// Create a new device for the underlying plugin. + virtual GenericDeviceTy *createDevice(GenericPluginTy &Plugin, + int32_t DeviceID, + int32_t NumDevices) = 0; + + /// Create a new global handler for the underlying plugin. + virtual GenericGlobalHandlerTy *createGlobalHandler() = 0; + /// Get the reference to the device with a certain device id. GenericDeviceTy &getDevice(int32_t DeviceId) { assert(isValidDeviceId(DeviceId) && "Invalid device id"); @@ -1054,6 +1065,132 @@ protected: return (DeviceId >= 0 && DeviceId < getNumDevices()); } +public: + // TODO: This plugin interface needs to be cleaned up. + + /// Returns non-zero if the provided \p Image can be executed by the runtime. + int32_t is_valid_binary(__tgt_device_image *Image); + + /// Initialize the device inside of the plugin. + int32_t init_device(int32_t DeviceId); + + /// Return the number of devices this plugin can support. + int32_t number_of_devices(); + + /// Initializes the OpenMP register requires information. + int64_t init_requires(int64_t RequiresFlags); + + /// Returns non-zero if the data can be exchanged between the two devices. + int32_t is_data_exchangable(int32_t SrcDeviceId, int32_t DstDeviceId); + + /// Initializes the record and replay mechanism inside the plugin. + int32_t initialize_record_replay(int32_t DeviceId, int64_t MemorySize, + void *VAddr, bool isRecord, bool SaveOutput, + uint64_t &ReqPtrArgOffset); + + /// Loads the associated binary into the plugin and returns a handle to it. + int32_t load_binary(int32_t DeviceId, __tgt_device_image *TgtImage, + __tgt_device_binary *Binary); + + /// Allocates memory that is accessively to the given device. + void *data_alloc(int32_t DeviceId, int64_t Size, void *HostPtr, int32_t Kind); + + /// Deallocates memory on the given device. + int32_t data_delete(int32_t DeviceId, void *TgtPtr, int32_t Kind); + + /// Locks / pins host memory using the plugin runtime. + int32_t data_lock(int32_t DeviceId, void *Ptr, int64_t Size, + void **LockedPtr); + + /// Unlocks / unpins host memory using the plugin runtime. + int32_t data_unlock(int32_t DeviceId, void *Ptr); + + /// Notify the runtime about a new mapping that has been created outside. + int32_t data_notify_mapped(int32_t DeviceId, void *HstPtr, int64_t Size); + + /// Notify t he runtime about a mapping that has been deleted. + int32_t data_notify_unmapped(int32_t DeviceId, void *HstPtr); + + /// Copy data to the given device. + int32_t data_submit(int32_t DeviceId, void *TgtPtr, void *HstPtr, + int64_t Size); + + /// Copy data to the given device asynchronously. + int32_t data_submit_async(int32_t DeviceId, void *TgtPtr, void *HstPtr, + int64_t Size, __tgt_async_info *AsyncInfoPtr); + + /// Copy data from the given device. + int32_t data_retrieve(int32_t DeviceId, void *HstPtr, void *TgtPtr, + int64_t Size); + + /// Copy data from the given device asynchornously. + int32_t data_retrieve_async(int32_t DeviceId, void *HstPtr, void *TgtPtr, + int64_t Size, __tgt_async_info *AsyncInfoPtr); + + /// Exchange memory addresses between two devices. + int32_t data_exchange(int32_t SrcDeviceId, void *SrcPtr, int32_t DstDeviceId, + void *DstPtr, int64_t Size); + + /// Exchange memory addresses between two devices asynchronously. + int32_t data_exchange_async(int32_t SrcDeviceId, void *SrcPtr, + int DstDeviceId, void *DstPtr, int64_t Size, + __tgt_async_info *AsyncInfo); + + /// Begin executing a kernel on the given device. + int32_t launch_kernel(int32_t DeviceId, void *TgtEntryPtr, void **TgtArgs, + ptrdiff_t *TgtOffsets, KernelArgsTy *KernelArgs, + __tgt_async_info *AsyncInfoPtr); + + /// Synchronize an asyncrhonous queue with the plugin runtime. + int32_t synchronize(int32_t DeviceId, __tgt_async_info *AsyncInfoPtr); + + /// Query the current state of an asynchronous queue. + int32_t query_async(int32_t DeviceId, __tgt_async_info *AsyncInfoPtr); + + /// Prints information about the given devices supported by the plugin. + void print_device_info(int32_t DeviceId); + + /// Creates an event in the given plugin if supported. + int32_t create_event(int32_t DeviceId, void **EventPtr); + + /// Records an event that has occurred. + int32_t record_event(int32_t DeviceId, void *EventPtr, + __tgt_async_info *AsyncInfoPtr); + + /// Wait until an event has occurred. + int32_t wait_event(int32_t DeviceId, void *EventPtr, + __tgt_async_info *AsyncInfoPtr); + + /// Syncrhonize execution until an event is done. + int32_t sync_event(int32_t DeviceId, void *EventPtr); + + /// Remove the event from the plugin. + int32_t destroy_event(int32_t DeviceId, void *EventPtr); + + /// Remove the event from the plugin. + void set_info_flag(uint32_t NewInfoLevel); + + /// Creates an asynchronous queue for the given plugin. + int32_t init_async_info(int32_t DeviceId, __tgt_async_info **AsyncInfoPtr); + + /// Creates device information to be used for diagnostics. + int32_t init_device_info(int32_t DeviceId, __tgt_device_info *DeviceInfo, + const char **ErrStr); + + /// Sets the offset into the devices for use by OMPT. + int32_t set_device_offset(int32_t DeviceIdOffset); + + /// Returns if the plugin can support auotmatic copy. + int32_t use_auto_zero_copy(int32_t DeviceId); + + /// Look up a global symbol in the given binary. + int32_t get_global(__tgt_device_binary Binary, uint64_t Size, + const char *Name, void **DevicePtr); + + /// Look up a kernel function in the given binary. + int32_t get_function(__tgt_device_binary Binary, const char *Name, + void **KernelPtr); + private: /// Number of devices available for the plugin. int32_t NumDevices = 0; @@ -1085,29 +1222,53 @@ private: RPCServerTy *RPCServer; }; +namespace Plugin { +/// Create a success error. This is the same as calling Error::success(), but +/// it is recommended to use this one for consistency with Plugin::error() and +/// Plugin::check(). +static Error success() { return Error::success(); } + +/// Create a string error. +template <typename... ArgsTy> +static Error error(const char *ErrFmt, ArgsTy... Args) { + return createStringError(inconvertibleErrorCode(), ErrFmt, Args...); +} + +/// Check the plugin-specific error code and return an error or success +/// accordingly. In case of an error, create a string error with the error +/// description. The ErrFmt should follow the format: +/// "Error in <function name>[<optional info>]: %s" +/// The last format specifier "%s" is mandatory and will be used to place the +/// error code's description. Notice this function should be only called from +/// the plugin-specific code. +/// TODO: Refactor this, must be defined individually by each plugin. +template <typename... ArgsTy> +static Error check(int32_t ErrorCode, const char *ErrFmt, ArgsTy... Args); +} // namespace Plugin + /// Class for simplifying the getter operation of the plugin. Anywhere on the /// code, the current plugin can be retrieved by Plugin::get(). The class also /// declares functions to create plugin-specific object instances. The check(), /// createPlugin(), createDevice() and createGlobalHandler() functions should be /// defined by each plugin implementation. -class Plugin { +class PluginTy { // Reference to the plugin instance. static GenericPluginTy *SpecificPlugin; - Plugin() { + PluginTy() { if (auto Err = init()) REPORT("Failed to initialize plugin: %s\n", toString(std::move(Err)).data()); } - ~Plugin() { + ~PluginTy() { if (auto Err = deinit()) REPORT("Failed to deinitialize plugin: %s\n", toString(std::move(Err)).data()); } - Plugin(const Plugin &) = delete; - void operator=(const Plugin &) = delete; + PluginTy(const PluginTy &) = delete; + void operator=(const PluginTy &) = delete; /// Create and intialize the plugin instance. static Error init() { @@ -1158,7 +1319,7 @@ public: // This static variable will initialize the underlying plugin instance in // case there was no previous explicit initialization. The initialization is // thread safe. - static Plugin Plugin; + static PluginTy Plugin; assert(SpecificPlugin && "Plugin is not active"); return *SpecificPlugin; @@ -1170,35 +1331,8 @@ public: /// Indicate whether the plugin is active. static bool isActive() { return SpecificPlugin != nullptr; } - /// Create a success error. This is the same as calling Error::success(), but - /// it is recommended to use this one for consistency with Plugin::error() and - /// Plugin::check(). - static Error success() { return Error::success(); } - - /// Create a string error. - template <typename... ArgsTy> - static Error error(const char *ErrFmt, ArgsTy... Args) { - return createStringError(inconvertibleErrorCode(), ErrFmt, Args...); - } - - /// Check the plugin-specific error code and return an error or success - /// accordingly. In case of an error, create a string error with the error - /// description. The ErrFmt should follow the format: - /// "Error in <function name>[<optional info>]: %s" - /// The last format specifier "%s" is mandatory and will be used to place the - /// error code's description. Notice this function should be only called from - /// the plugin-specific code. - template <typename... ArgsTy> - static Error check(int32_t ErrorCode, const char *ErrFmt, ArgsTy... Args); - /// Create a plugin instance. static GenericPluginTy *createPlugin(); - - /// Create a plugin-specific device. - static GenericDeviceTy *createDevice(int32_t DeviceId, int32_t NumDevices); - - /// Create a plugin-specific global handler. - static GenericGlobalHandlerTy *createGlobalHandler(); }; /// Auxiliary interface class for GenericDeviceResourceManagerTy. This class @@ -1393,7 +1527,7 @@ protected: }; /// A static check on whether or not we support RPC in libomptarget. -const bool libomptargetSupportsRPC(); +bool libomptargetSupportsRPC(); } // namespace plugin } // namespace target diff --git a/openmp/libomptarget/plugins-nextgen/common/include/RPC.h b/openmp/libomptarget/plugins-nextgen/common/include/RPC.h index 2e39b3f299c8881d935d0f63319b1d4093d9095a..01bf539bcb3f32d50a02dd4250c8df5c6fd7f44b 100644 --- a/openmp/libomptarget/plugins-nextgen/common/include/RPC.h +++ b/openmp/libomptarget/plugins-nextgen/common/include/RPC.h @@ -16,12 +16,14 @@ #ifndef OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_COMMON_RPC_H #define OPENMP_LIBOMPTARGET_PLUGINS_NEXTGEN_COMMON_RPC_H +#include "llvm/ADT/DenseMap.h" #include "llvm/Support/Error.h" #include <cstdint> namespace llvm::omp::target { namespace plugin { +struct GenericPluginTy; struct GenericDeviceTy; class GenericGlobalHandlerTy; class DeviceImageTy; @@ -32,7 +34,8 @@ class DeviceImageTy; /// these routines will perform no action. struct RPCServerTy { public: - RPCServerTy(uint32_t NumDevices); + /// Initializes the handles to the number of devices we may need to service. + RPCServerTy(plugin::GenericPluginTy &Plugin); /// Check if this device image is using an RPC server. This checks for the /// precense of an externally visible symbol in the device image that will @@ -56,7 +59,9 @@ public: /// memory associated with the k llvm::Error deinitDevice(plugin::GenericDeviceTy &Device); - ~RPCServerTy(); +private: + /// Array from this device's identifier to its attached devices. + llvm::SmallVector<uintptr_t> Handles; }; } // namespace llvm::omp::target diff --git a/openmp/libomptarget/plugins-nextgen/common/include/Utils/ELF.h b/openmp/libomptarget/plugins-nextgen/common/include/Utils/ELF.h index 140a6b6b84aa1278cd811da2555ea7cb0efe2288..88c83d39b68ceba06141615989726c76caa97ff9 100644 --- a/openmp/libomptarget/plugins-nextgen/common/include/Utils/ELF.h +++ b/openmp/libomptarget/plugins-nextgen/common/include/Utils/ELF.h @@ -28,17 +28,15 @@ bool isELF(llvm::StringRef Buffer); llvm::Expected<bool> checkMachine(llvm::StringRef Object, uint16_t EMachine); /// Returns a pointer to the given \p Symbol inside of an ELF object. -llvm::Expected<const void *> getSymbolAddress( - const llvm::object::ELFObjectFile<llvm::object::ELF64LE> &ELFObj, - const llvm::object::ELF64LE::Sym &Symbol); +llvm::Expected<const void *> +getSymbolAddress(const llvm::object::ELFSymbolRef &Symbol); /// Returns the symbol associated with the \p Name in the \p ELFObj. It will /// first search for the hash sections to identify symbols from the hash table. /// If that fails it will fall back to a linear search in the case of an /// executable file without a hash table. -llvm::Expected<const typename llvm::object::ELF64LE::Sym *> -getSymbol(const llvm::object::ELFObjectFile<llvm::object::ELF64LE> &ELFObj, - llvm::StringRef Name); +llvm::Expected<std::optional<llvm::object::ELFSymbolRef>> +getSymbol(const llvm::object::ObjectFile &ELFObj, llvm::StringRef Name); } // namespace elf } // namespace utils diff --git a/openmp/libomptarget/plugins-nextgen/common/src/GlobalHandler.cpp b/openmp/libomptarget/plugins-nextgen/common/src/GlobalHandler.cpp index d398f60c55bd137fc2ecb52c60a6fe134cebfe0d..ba0aa47f8e51c3e4feaf5aae9521966306e50e11 100644 --- a/openmp/libomptarget/plugins-nextgen/common/src/GlobalHandler.cpp +++ b/openmp/libomptarget/plugins-nextgen/common/src/GlobalHandler.cpp @@ -25,14 +25,12 @@ using namespace omp; using namespace target; using namespace plugin; -Expected<ELF64LEObjectFile> +Expected<std::unique_ptr<ObjectFile>> GenericGlobalHandlerTy::getELFObjectFile(DeviceImageTy &Image) { assert(utils::elf::isELF(Image.getMemoryBuffer().getBuffer()) && "Input is not an ELF file"); - Expected<ELF64LEObjectFile> ElfOrErr = - ELF64LEObjectFile::create(Image.getMemoryBuffer()); - return ElfOrErr; + return ELFObjectFileBase::createELFObjectFile(Image.getMemoryBuffer()); } Error GenericGlobalHandlerTy::moveGlobalBetweenDeviceAndHost( @@ -91,13 +89,13 @@ bool GenericGlobalHandlerTy::isSymbolInImage(GenericDeviceTy &Device, } // Search the ELF symbol using the symbol name. - auto SymOrErr = utils::elf::getSymbol(*ELFObjOrErr, SymName); + auto SymOrErr = utils::elf::getSymbol(**ELFObjOrErr, SymName); if (!SymOrErr) { consumeError(SymOrErr.takeError()); return false; } - return *SymOrErr; + return SymOrErr->has_value(); } Error GenericGlobalHandlerTy::getGlobalMetadataFromImage( @@ -110,17 +108,17 @@ Error GenericGlobalHandlerTy::getGlobalMetadataFromImage( return ELFObj.takeError(); // Search the ELF symbol using the symbol name. - auto SymOrErr = utils::elf::getSymbol(*ELFObj, ImageGlobal.getName()); + auto SymOrErr = utils::elf::getSymbol(**ELFObj, ImageGlobal.getName()); if (!SymOrErr) return Plugin::error("Failed ELF lookup of global '%s': %s", ImageGlobal.getName().data(), toString(SymOrErr.takeError()).data()); - if (!*SymOrErr) + if (!SymOrErr->has_value()) return Plugin::error("Failed to find global symbol '%s' in the ELF image", ImageGlobal.getName().data()); - auto AddrOrErr = utils::elf::getSymbolAddress(*ELFObj, **SymOrErr); + auto AddrOrErr = utils::elf::getSymbolAddress(**SymOrErr); // Get the section to which the symbol belongs. if (!AddrOrErr) return Plugin::error("Failed to get ELF symbol from global '%s': %s", @@ -129,7 +127,7 @@ Error GenericGlobalHandlerTy::getGlobalMetadataFromImage( // Setup the global symbol's address and size. ImageGlobal.setPtr(const_cast<void *>(*AddrOrErr)); - ImageGlobal.setSize((*SymOrErr)->st_size); + ImageGlobal.setSize((*SymOrErr)->getSize()); return Plugin::success(); } diff --git a/openmp/libomptarget/plugins-nextgen/common/src/PluginInterface.cpp b/openmp/libomptarget/plugins-nextgen/common/src/PluginInterface.cpp index 8c8c52de0c210c2e229440ec10df0d19b6eded67..b5f3c45c835fdbca086634cc8a6b494b95fd4730 100644 --- a/openmp/libomptarget/plugins-nextgen/common/src/PluginInterface.cpp +++ b/openmp/libomptarget/plugins-nextgen/common/src/PluginInterface.cpp @@ -39,7 +39,7 @@ using namespace omp; using namespace target; using namespace plugin; -GenericPluginTy *Plugin::SpecificPlugin = nullptr; +GenericPluginTy *PluginTy::SpecificPlugin = nullptr; // TODO: Fix any thread safety issues for multi-threaded kernel recording. struct RecordReplayTy { @@ -438,7 +438,7 @@ Error GenericKernelTy::init(GenericDeviceTy &GenericDevice, // Retrieve kernel environment object for the kernel. GlobalTy KernelEnv(std::string(Name) + "_kernel_environment", sizeof(KernelEnvironment), &KernelEnvironment); - GenericGlobalHandlerTy &GHandler = Plugin::get().getGlobalHandler(); + GenericGlobalHandlerTy &GHandler = GenericDevice.Plugin.getGlobalHandler(); if (auto Err = GHandler.readGlobalFromImage(GenericDevice, *ImagePtr, KernelEnv)) { [[maybe_unused]] std::string ErrStr = toString(std::move(Err)); @@ -468,11 +468,13 @@ Error GenericKernelTy::init(GenericDeviceTy &GenericDevice, Expected<KernelLaunchEnvironmentTy *> GenericKernelTy::getKernelLaunchEnvironment( - GenericDeviceTy &GenericDevice, + GenericDeviceTy &GenericDevice, uint32_t Version, AsyncInfoWrapperTy &AsyncInfoWrapper) const { // Ctor/Dtor have no arguments, replaying uses the original kernel launch - // environment. - if (isCtorOrDtor() || RecordReplay.isReplaying()) + // environment. Older versions of the compiler do not generate a kernel + // launch environment. + if (isCtorOrDtor() || RecordReplay.isReplaying() || + Version < OMP_KERNEL_ARG_MIN_VERSION_WITH_DYN_PTR) return nullptr; if (!KernelEnvironment.Configuration.ReductionDataSize || @@ -544,8 +546,8 @@ Error GenericKernelTy::launch(GenericDeviceTy &GenericDevice, void **ArgPtrs, llvm::SmallVector<void *, 16> Args; llvm::SmallVector<void *, 16> Ptrs; - auto KernelLaunchEnvOrErr = - getKernelLaunchEnvironment(GenericDevice, AsyncInfoWrapper); + auto KernelLaunchEnvOrErr = getKernelLaunchEnvironment( + GenericDevice, KernelArgs.Version, AsyncInfoWrapper); if (!KernelLaunchEnvOrErr) return KernelLaunchEnvOrErr.takeError(); @@ -586,6 +588,9 @@ void *GenericKernelTy::prepareArgs( uint32_t KLEOffset = !!KernelLaunchEnvironment; NumArgs += KLEOffset; + if (NumArgs == 0) + return nullptr; + Args.resize(NumArgs); Ptrs.resize(NumArgs); @@ -705,9 +710,10 @@ uint64_t GenericKernelTy::getNumBlocks(GenericDeviceTy &GenericDevice, return std::min(PreferredNumBlocks, GenericDevice.getBlockLimit()); } -GenericDeviceTy::GenericDeviceTy(int32_t DeviceId, int32_t NumDevices, +GenericDeviceTy::GenericDeviceTy(GenericPluginTy &Plugin, int32_t DeviceId, + int32_t NumDevices, const llvm::omp::GV &OMPGridValues) - : MemoryManager(nullptr), OMP_TeamLimit("OMP_TEAM_LIMIT"), + : Plugin(Plugin), MemoryManager(nullptr), OMP_TeamLimit("OMP_TEAM_LIMIT"), OMP_NumTeams("OMP_NUM_TEAMS"), OMP_TeamsThreadLimit("OMP_TEAMS_THREAD_LIMIT"), OMPX_DebugKind("LIBOMPTARGET_DEVICE_RTL_DEBUG"), @@ -1483,10 +1489,10 @@ Error GenericPluginTy::init() { assert(Devices.size() == 0 && "Plugin already initialized"); Devices.resize(NumDevices, nullptr); - GlobalHandler = Plugin::createGlobalHandler(); + GlobalHandler = createGlobalHandler(); assert(GlobalHandler && "Invalid global handler"); - RPCServer = new RPCServerTy(NumDevices); + RPCServer = new RPCServerTy(*this); assert(RPCServer && "Invalid RPC server"); return Plugin::success(); @@ -1517,7 +1523,7 @@ Error GenericPluginTy::initDevice(int32_t DeviceId) { assert(!Devices[DeviceId] && "Device already initialized"); // Create the device and save the reference. - GenericDeviceTy *Device = Plugin::createDevice(DeviceId, NumDevices); + GenericDeviceTy *Device = createDevice(*this, DeviceId, NumDevices); assert(Device && "Invalid device"); // Save the device reference into the list. @@ -1560,36 +1566,7 @@ Expected<bool> GenericPluginTy::checkELFImage(StringRef Image) const { return isELFCompatible(Image); } -const bool llvm::omp::target::plugin::libomptargetSupportsRPC() { -#ifdef LIBOMPTARGET_RPC_SUPPORT - return true; -#else - return false; -#endif -} - -/// Exposed library API function, basically wrappers around the GenericDeviceTy -/// functionality with the same name. All non-async functions are redirected -/// to the async versions right away with a NULL AsyncInfoPtr. -#ifdef __cplusplus -extern "C" { -#endif - -int32_t __tgt_rtl_init_plugin() { - auto Err = Plugin::initIfNeeded(); - if (Err) { - [[maybe_unused]] std::string ErrStr = toString(std::move(Err)); - DP("Failed to init plugin: %s", ErrStr.c_str()); - return OFFLOAD_FAIL; - } - - return OFFLOAD_SUCCESS; -} - -int32_t __tgt_rtl_is_valid_binary(__tgt_device_image *Image) { - if (!Plugin::isActive()) - return false; - +int32_t GenericPluginTy::is_valid_binary(__tgt_device_image *Image) { StringRef Buffer(reinterpret_cast<const char *>(Image->ImageStart), target::getPtrDiff(Image->ImageEnd, Image->ImageStart)); @@ -1604,13 +1581,13 @@ int32_t __tgt_rtl_is_valid_binary(__tgt_device_image *Image) { case file_magic::elf_executable: case file_magic::elf_shared_object: case file_magic::elf_core: { - auto MatchOrErr = Plugin::get().checkELFImage(Buffer); + auto MatchOrErr = checkELFImage(Buffer); if (Error Err = MatchOrErr.takeError()) return HandleError(std::move(Err)); return *MatchOrErr; } case file_magic::bitcode: { - auto MatchOrErr = Plugin::get().getJIT().checkBitcodeImage(Buffer); + auto MatchOrErr = getJIT().checkBitcodeImage(Buffer); if (Error Err = MatchOrErr.takeError()) return HandleError(std::move(Err)); return *MatchOrErr; @@ -1620,8 +1597,8 @@ int32_t __tgt_rtl_is_valid_binary(__tgt_device_image *Image) { } } -int32_t __tgt_rtl_init_device(int32_t DeviceId) { - auto Err = Plugin::get().initDevice(DeviceId); +int32_t GenericPluginTy::init_device(int32_t DeviceId) { + auto Err = initDevice(DeviceId); if (Err) { REPORT("Failure to initialize device %d: %s\n", DeviceId, toString(std::move(Err)).data()); @@ -1631,24 +1608,24 @@ int32_t __tgt_rtl_init_device(int32_t DeviceId) { return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_number_of_devices() { return Plugin::get().getNumDevices(); } +int32_t GenericPluginTy::number_of_devices() { return getNumDevices(); } -int64_t __tgt_rtl_init_requires(int64_t RequiresFlags) { - Plugin::get().setRequiresFlag(RequiresFlags); +int64_t GenericPluginTy::init_requires(int64_t RequiresFlags) { + setRequiresFlag(RequiresFlags); return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_is_data_exchangable(int32_t SrcDeviceId, - int32_t DstDeviceId) { - return Plugin::get().isDataExchangable(SrcDeviceId, DstDeviceId); +int32_t GenericPluginTy::is_data_exchangable(int32_t SrcDeviceId, + int32_t DstDeviceId) { + return isDataExchangable(SrcDeviceId, DstDeviceId); } -int32_t __tgt_rtl_initialize_record_replay(int32_t DeviceId, int64_t MemorySize, - void *VAddr, bool isRecord, - bool SaveOutput, - uint64_t &ReqPtrArgOffset) { - GenericPluginTy &Plugin = Plugin::get(); - GenericDeviceTy &Device = Plugin.getDevice(DeviceId); +int32_t GenericPluginTy::initialize_record_replay(int32_t DeviceId, + int64_t MemorySize, + void *VAddr, bool isRecord, + bool SaveOutput, + uint64_t &ReqPtrArgOffset) { + GenericDeviceTy &Device = getDevice(DeviceId); RecordReplayTy::RRStatusTy Status = isRecord ? RecordReplayTy::RRStatusTy::RRRecording : RecordReplayTy::RRStatusTy::RRReplaying; @@ -1667,12 +1644,12 @@ int32_t __tgt_rtl_initialize_record_replay(int32_t DeviceId, int64_t MemorySize, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_load_binary(int32_t DeviceId, __tgt_device_image *TgtImage, - __tgt_device_binary *Binary) { - GenericPluginTy &Plugin = Plugin::get(); - GenericDeviceTy &Device = Plugin.getDevice(DeviceId); +int32_t GenericPluginTy::load_binary(int32_t DeviceId, + __tgt_device_image *TgtImage, + __tgt_device_binary *Binary) { + GenericDeviceTy &Device = getDevice(DeviceId); - auto ImageOrErr = Device.loadBinary(Plugin, TgtImage); + auto ImageOrErr = Device.loadBinary(*this, TgtImage); if (!ImageOrErr) { auto Err = ImageOrErr.takeError(); REPORT("Failure to load binary image %p on device %d: %s\n", TgtImage, @@ -1688,10 +1665,10 @@ int32_t __tgt_rtl_load_binary(int32_t DeviceId, __tgt_device_image *TgtImage, return OFFLOAD_SUCCESS; } -void *__tgt_rtl_data_alloc(int32_t DeviceId, int64_t Size, void *HostPtr, - int32_t Kind) { - auto AllocOrErr = Plugin::get().getDevice(DeviceId).dataAlloc( - Size, HostPtr, (TargetAllocTy)Kind); +void *GenericPluginTy::data_alloc(int32_t DeviceId, int64_t Size, void *HostPtr, + int32_t Kind) { + auto AllocOrErr = + getDevice(DeviceId).dataAlloc(Size, HostPtr, (TargetAllocTy)Kind); if (!AllocOrErr) { auto Err = AllocOrErr.takeError(); REPORT("Failure to allocate device memory: %s\n", @@ -1703,9 +1680,10 @@ void *__tgt_rtl_data_alloc(int32_t DeviceId, int64_t Size, void *HostPtr, return *AllocOrErr; } -int32_t __tgt_rtl_data_delete(int32_t DeviceId, void *TgtPtr, int32_t Kind) { +int32_t GenericPluginTy::data_delete(int32_t DeviceId, void *TgtPtr, + int32_t Kind) { auto Err = - Plugin::get().getDevice(DeviceId).dataDelete(TgtPtr, (TargetAllocTy)Kind); + getDevice(DeviceId).dataDelete(TgtPtr, static_cast<TargetAllocTy>(Kind)); if (Err) { REPORT("Failure to deallocate device pointer %p: %s\n", TgtPtr, toString(std::move(Err)).data()); @@ -1715,9 +1693,9 @@ int32_t __tgt_rtl_data_delete(int32_t DeviceId, void *TgtPtr, int32_t Kind) { return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_data_lock(int32_t DeviceId, void *Ptr, int64_t Size, - void **LockedPtr) { - auto LockedPtrOrErr = Plugin::get().getDevice(DeviceId).dataLock(Ptr, Size); +int32_t GenericPluginTy::data_lock(int32_t DeviceId, void *Ptr, int64_t Size, + void **LockedPtr) { + auto LockedPtrOrErr = getDevice(DeviceId).dataLock(Ptr, Size); if (!LockedPtrOrErr) { auto Err = LockedPtrOrErr.takeError(); REPORT("Failure to lock memory %p: %s\n", Ptr, @@ -1734,8 +1712,8 @@ int32_t __tgt_rtl_data_lock(int32_t DeviceId, void *Ptr, int64_t Size, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_data_unlock(int32_t DeviceId, void *Ptr) { - auto Err = Plugin::get().getDevice(DeviceId).dataUnlock(Ptr); +int32_t GenericPluginTy::data_unlock(int32_t DeviceId, void *Ptr) { + auto Err = getDevice(DeviceId).dataUnlock(Ptr); if (Err) { REPORT("Failure to unlock memory %p: %s\n", Ptr, toString(std::move(Err)).data()); @@ -1745,9 +1723,9 @@ int32_t __tgt_rtl_data_unlock(int32_t DeviceId, void *Ptr) { return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_data_notify_mapped(int32_t DeviceId, void *HstPtr, - int64_t Size) { - auto Err = Plugin::get().getDevice(DeviceId).notifyDataMapped(HstPtr, Size); +int32_t GenericPluginTy::data_notify_mapped(int32_t DeviceId, void *HstPtr, + int64_t Size) { + auto Err = getDevice(DeviceId).notifyDataMapped(HstPtr, Size); if (Err) { REPORT("Failure to notify data mapped %p: %s\n", HstPtr, toString(std::move(Err)).data()); @@ -1757,8 +1735,8 @@ int32_t __tgt_rtl_data_notify_mapped(int32_t DeviceId, void *HstPtr, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_data_notify_unmapped(int32_t DeviceId, void *HstPtr) { - auto Err = Plugin::get().getDevice(DeviceId).notifyDataUnmapped(HstPtr); +int32_t GenericPluginTy::data_notify_unmapped(int32_t DeviceId, void *HstPtr) { + auto Err = getDevice(DeviceId).notifyDataUnmapped(HstPtr); if (Err) { REPORT("Failure to notify data unmapped %p: %s\n", HstPtr, toString(std::move(Err)).data()); @@ -1768,17 +1746,16 @@ int32_t __tgt_rtl_data_notify_unmapped(int32_t DeviceId, void *HstPtr) { return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_data_submit(int32_t DeviceId, void *TgtPtr, void *HstPtr, - int64_t Size) { - return __tgt_rtl_data_submit_async(DeviceId, TgtPtr, HstPtr, Size, - /*AsyncInfoPtr=*/nullptr); +int32_t GenericPluginTy::data_submit(int32_t DeviceId, void *TgtPtr, + void *HstPtr, int64_t Size) { + return data_submit_async(DeviceId, TgtPtr, HstPtr, Size, + /*AsyncInfoPtr=*/nullptr); } -int32_t __tgt_rtl_data_submit_async(int32_t DeviceId, void *TgtPtr, - void *HstPtr, int64_t Size, - __tgt_async_info *AsyncInfoPtr) { - auto Err = Plugin::get().getDevice(DeviceId).dataSubmit(TgtPtr, HstPtr, Size, - AsyncInfoPtr); +int32_t GenericPluginTy::data_submit_async(int32_t DeviceId, void *TgtPtr, + void *HstPtr, int64_t Size, + __tgt_async_info *AsyncInfoPtr) { + auto Err = getDevice(DeviceId).dataSubmit(TgtPtr, HstPtr, Size, AsyncInfoPtr); if (Err) { REPORT("Failure to copy data from host to device. Pointers: host " "= " DPxMOD ", device = " DPxMOD ", size = %" PRId64 ": %s\n", @@ -1790,17 +1767,17 @@ int32_t __tgt_rtl_data_submit_async(int32_t DeviceId, void *TgtPtr, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_data_retrieve(int32_t DeviceId, void *HstPtr, void *TgtPtr, - int64_t Size) { - return __tgt_rtl_data_retrieve_async(DeviceId, HstPtr, TgtPtr, Size, - /*AsyncInfoPtr=*/nullptr); +int32_t GenericPluginTy::data_retrieve(int32_t DeviceId, void *HstPtr, + void *TgtPtr, int64_t Size) { + return data_retrieve_async(DeviceId, HstPtr, TgtPtr, Size, + /*AsyncInfoPtr=*/nullptr); } -int32_t __tgt_rtl_data_retrieve_async(int32_t DeviceId, void *HstPtr, - void *TgtPtr, int64_t Size, - __tgt_async_info *AsyncInfoPtr) { - auto Err = Plugin::get().getDevice(DeviceId).dataRetrieve(HstPtr, TgtPtr, - Size, AsyncInfoPtr); +int32_t GenericPluginTy::data_retrieve_async(int32_t DeviceId, void *HstPtr, + void *TgtPtr, int64_t Size, + __tgt_async_info *AsyncInfoPtr) { + auto Err = + getDevice(DeviceId).dataRetrieve(HstPtr, TgtPtr, Size, AsyncInfoPtr); if (Err) { REPORT("Faliure to copy data from device to host. Pointers: host " "= " DPxMOD ", device = " DPxMOD ", size = %" PRId64 ": %s\n", @@ -1812,20 +1789,19 @@ int32_t __tgt_rtl_data_retrieve_async(int32_t DeviceId, void *HstPtr, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_data_exchange(int32_t SrcDeviceId, void *SrcPtr, - int32_t DstDeviceId, void *DstPtr, - int64_t Size) { - return __tgt_rtl_data_exchange_async(SrcDeviceId, SrcPtr, DstDeviceId, DstPtr, - Size, - /*AsyncInfoPtr=*/nullptr); +int32_t GenericPluginTy::data_exchange(int32_t SrcDeviceId, void *SrcPtr, + int32_t DstDeviceId, void *DstPtr, + int64_t Size) { + return data_exchange_async(SrcDeviceId, SrcPtr, DstDeviceId, DstPtr, Size, + /*AsyncInfoPtr=*/nullptr); } -int32_t __tgt_rtl_data_exchange_async(int32_t SrcDeviceId, void *SrcPtr, - int DstDeviceId, void *DstPtr, - int64_t Size, - __tgt_async_info *AsyncInfo) { - GenericDeviceTy &SrcDevice = Plugin::get().getDevice(SrcDeviceId); - GenericDeviceTy &DstDevice = Plugin::get().getDevice(DstDeviceId); +int32_t GenericPluginTy::data_exchange_async(int32_t SrcDeviceId, void *SrcPtr, + int DstDeviceId, void *DstPtr, + int64_t Size, + __tgt_async_info *AsyncInfo) { + GenericDeviceTy &SrcDevice = getDevice(SrcDeviceId); + GenericDeviceTy &DstDevice = getDevice(DstDeviceId); auto Err = SrcDevice.dataExchange(SrcPtr, DstDevice, DstPtr, Size, AsyncInfo); if (Err) { REPORT("Failure to copy data from device (%d) to device (%d). Pointers: " @@ -1838,12 +1814,12 @@ int32_t __tgt_rtl_data_exchange_async(int32_t SrcDeviceId, void *SrcPtr, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_launch_kernel(int32_t DeviceId, void *TgtEntryPtr, - void **TgtArgs, ptrdiff_t *TgtOffsets, - KernelArgsTy *KernelArgs, - __tgt_async_info *AsyncInfoPtr) { - auto Err = Plugin::get().getDevice(DeviceId).launchKernel( - TgtEntryPtr, TgtArgs, TgtOffsets, *KernelArgs, AsyncInfoPtr); +int32_t GenericPluginTy::launch_kernel(int32_t DeviceId, void *TgtEntryPtr, + void **TgtArgs, ptrdiff_t *TgtOffsets, + KernelArgsTy *KernelArgs, + __tgt_async_info *AsyncInfoPtr) { + auto Err = getDevice(DeviceId).launchKernel(TgtEntryPtr, TgtArgs, TgtOffsets, + *KernelArgs, AsyncInfoPtr); if (Err) { REPORT("Failure to run target region " DPxMOD " in device %d: %s\n", DPxPTR(TgtEntryPtr), DeviceId, toString(std::move(Err)).data()); @@ -1853,9 +1829,9 @@ int32_t __tgt_rtl_launch_kernel(int32_t DeviceId, void *TgtEntryPtr, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_synchronize(int32_t DeviceId, - __tgt_async_info *AsyncInfoPtr) { - auto Err = Plugin::get().getDevice(DeviceId).synchronize(AsyncInfoPtr); +int32_t GenericPluginTy::synchronize(int32_t DeviceId, + __tgt_async_info *AsyncInfoPtr) { + auto Err = getDevice(DeviceId).synchronize(AsyncInfoPtr); if (Err) { REPORT("Failure to synchronize stream %p: %s\n", AsyncInfoPtr->Queue, toString(std::move(Err)).data()); @@ -1865,9 +1841,9 @@ int32_t __tgt_rtl_synchronize(int32_t DeviceId, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_query_async(int32_t DeviceId, - __tgt_async_info *AsyncInfoPtr) { - auto Err = Plugin::get().getDevice(DeviceId).queryAsync(AsyncInfoPtr); +int32_t GenericPluginTy::query_async(int32_t DeviceId, + __tgt_async_info *AsyncInfoPtr) { + auto Err = getDevice(DeviceId).queryAsync(AsyncInfoPtr); if (Err) { REPORT("Failure to query stream %p: %s\n", AsyncInfoPtr->Queue, toString(std::move(Err)).data()); @@ -1877,14 +1853,14 @@ int32_t __tgt_rtl_query_async(int32_t DeviceId, return OFFLOAD_SUCCESS; } -void __tgt_rtl_print_device_info(int32_t DeviceId) { - if (auto Err = Plugin::get().getDevice(DeviceId).printInfo()) +void GenericPluginTy::print_device_info(int32_t DeviceId) { + if (auto Err = getDevice(DeviceId).printInfo()) REPORT("Failure to print device %d info: %s\n", DeviceId, toString(std::move(Err)).data()); } -int32_t __tgt_rtl_create_event(int32_t DeviceId, void **EventPtr) { - auto Err = Plugin::get().getDevice(DeviceId).createEvent(EventPtr); +int32_t GenericPluginTy::create_event(int32_t DeviceId, void **EventPtr) { + auto Err = getDevice(DeviceId).createEvent(EventPtr); if (Err) { REPORT("Failure to create event: %s\n", toString(std::move(Err)).data()); return OFFLOAD_FAIL; @@ -1893,10 +1869,9 @@ int32_t __tgt_rtl_create_event(int32_t DeviceId, void **EventPtr) { return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_record_event(int32_t DeviceId, void *EventPtr, - __tgt_async_info *AsyncInfoPtr) { - auto Err = - Plugin::get().getDevice(DeviceId).recordEvent(EventPtr, AsyncInfoPtr); +int32_t GenericPluginTy::record_event(int32_t DeviceId, void *EventPtr, + __tgt_async_info *AsyncInfoPtr) { + auto Err = getDevice(DeviceId).recordEvent(EventPtr, AsyncInfoPtr); if (Err) { REPORT("Failure to record event %p: %s\n", EventPtr, toString(std::move(Err)).data()); @@ -1906,10 +1881,9 @@ int32_t __tgt_rtl_record_event(int32_t DeviceId, void *EventPtr, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_wait_event(int32_t DeviceId, void *EventPtr, - __tgt_async_info *AsyncInfoPtr) { - auto Err = - Plugin::get().getDevice(DeviceId).waitEvent(EventPtr, AsyncInfoPtr); +int32_t GenericPluginTy::wait_event(int32_t DeviceId, void *EventPtr, + __tgt_async_info *AsyncInfoPtr) { + auto Err = getDevice(DeviceId).waitEvent(EventPtr, AsyncInfoPtr); if (Err) { REPORT("Failure to wait event %p: %s\n", EventPtr, toString(std::move(Err)).data()); @@ -1919,8 +1893,8 @@ int32_t __tgt_rtl_wait_event(int32_t DeviceId, void *EventPtr, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_sync_event(int32_t DeviceId, void *EventPtr) { - auto Err = Plugin::get().getDevice(DeviceId).syncEvent(EventPtr); +int32_t GenericPluginTy::sync_event(int32_t DeviceId, void *EventPtr) { + auto Err = getDevice(DeviceId).syncEvent(EventPtr); if (Err) { REPORT("Failure to synchronize event %p: %s\n", EventPtr, toString(std::move(Err)).data()); @@ -1930,8 +1904,8 @@ int32_t __tgt_rtl_sync_event(int32_t DeviceId, void *EventPtr) { return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_destroy_event(int32_t DeviceId, void *EventPtr) { - auto Err = Plugin::get().getDevice(DeviceId).destroyEvent(EventPtr); +int32_t GenericPluginTy::destroy_event(int32_t DeviceId, void *EventPtr) { + auto Err = getDevice(DeviceId).destroyEvent(EventPtr); if (Err) { REPORT("Failure to destroy event %p: %s\n", EventPtr, toString(std::move(Err)).data()); @@ -1941,16 +1915,16 @@ int32_t __tgt_rtl_destroy_event(int32_t DeviceId, void *EventPtr) { return OFFLOAD_SUCCESS; } -void __tgt_rtl_set_info_flag(uint32_t NewInfoLevel) { +void GenericPluginTy::set_info_flag(uint32_t NewInfoLevel) { std::atomic<uint32_t> &InfoLevel = getInfoLevelInternal(); InfoLevel.store(NewInfoLevel); } -int32_t __tgt_rtl_init_async_info(int32_t DeviceId, - __tgt_async_info **AsyncInfoPtr) { +int32_t GenericPluginTy::init_async_info(int32_t DeviceId, + __tgt_async_info **AsyncInfoPtr) { assert(AsyncInfoPtr && "Invalid async info"); - auto Err = Plugin::get().getDevice(DeviceId).initAsyncInfo(AsyncInfoPtr); + auto Err = getDevice(DeviceId).initAsyncInfo(AsyncInfoPtr); if (Err) { REPORT("Failure to initialize async info at " DPxMOD " on device %d: %s\n", DPxPTR(*AsyncInfoPtr), DeviceId, toString(std::move(Err)).data()); @@ -1960,12 +1934,12 @@ int32_t __tgt_rtl_init_async_info(int32_t DeviceId, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_init_device_info(int32_t DeviceId, - __tgt_device_info *DeviceInfo, - const char **ErrStr) { +int32_t GenericPluginTy::init_device_info(int32_t DeviceId, + __tgt_device_info *DeviceInfo, + const char **ErrStr) { *ErrStr = ""; - auto Err = Plugin::get().getDevice(DeviceId).initDeviceInfo(DeviceInfo); + auto Err = getDevice(DeviceId).initDeviceInfo(DeviceInfo); if (Err) { REPORT("Failure to initialize device info at " DPxMOD " on device %d: %s\n", DPxPTR(DeviceInfo), DeviceId, toString(std::move(Err)).data()); @@ -1975,31 +1949,30 @@ int32_t __tgt_rtl_init_device_info(int32_t DeviceId, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_set_device_offset(int32_t DeviceIdOffset) { - Plugin::get().setDeviceIdStartIndex(DeviceIdOffset); +int32_t GenericPluginTy::set_device_offset(int32_t DeviceIdOffset) { + setDeviceIdStartIndex(DeviceIdOffset); return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_use_auto_zero_copy(int32_t DeviceId) { +int32_t GenericPluginTy::use_auto_zero_copy(int32_t DeviceId) { // Automatic zero-copy only applies to programs that did // not request unified_shared_memory and are deployed on an // APU with XNACK enabled. - if (Plugin::get().getRequiresFlags() & OMP_REQ_UNIFIED_SHARED_MEMORY) + if (getRequiresFlags() & OMP_REQ_UNIFIED_SHARED_MEMORY) return false; - return Plugin::get().getDevice(DeviceId).useAutoZeroCopy(); + return getDevice(DeviceId).useAutoZeroCopy(); } -int32_t __tgt_rtl_get_global(__tgt_device_binary Binary, uint64_t Size, - const char *Name, void **DevicePtr) { +int32_t GenericPluginTy::get_global(__tgt_device_binary Binary, uint64_t Size, + const char *Name, void **DevicePtr) { assert(Binary.handle && "Invalid device binary handle"); DeviceImageTy &Image = *reinterpret_cast<DeviceImageTy *>(Binary.handle); - GenericPluginTy &Plugin = Plugin::get(); GenericDeviceTy &Device = Image.getDevice(); GlobalTy DeviceGlobal(Name, Size); - GenericGlobalHandlerTy &GHandler = Plugin.getGlobalHandler(); + GenericGlobalHandlerTy &GHandler = getGlobalHandler(); if (auto Err = GHandler.getGlobalMetadataFromDevice(Device, Image, DeviceGlobal)) { REPORT("Failure to look up global address: %s\n", @@ -2017,8 +1990,8 @@ int32_t __tgt_rtl_get_global(__tgt_device_binary Binary, uint64_t Size, return OFFLOAD_SUCCESS; } -int32_t __tgt_rtl_get_function(__tgt_device_binary Binary, const char *Name, - void **KernelPtr) { +int32_t GenericPluginTy::get_function(__tgt_device_binary Binary, + const char *Name, void **KernelPtr) { assert(Binary.handle && "Invalid device binary handle"); DeviceImageTy &Image = *reinterpret_cast<DeviceImageTy *>(Binary.handle); @@ -2041,6 +2014,212 @@ int32_t __tgt_rtl_get_function(__tgt_device_binary Binary, const char *Name, return OFFLOAD_SUCCESS; } +bool llvm::omp::target::plugin::libomptargetSupportsRPC() { +#ifdef LIBOMPTARGET_RPC_SUPPORT + return true; +#else + return false; +#endif +} + +/// Exposed library API function, basically wrappers around the GenericDeviceTy +/// functionality with the same name. All non-async functions are redirected +/// to the async versions right away with a NULL AsyncInfoPtr. +#ifdef __cplusplus +extern "C" { +#endif + +int32_t __tgt_rtl_init_plugin() { + auto Err = PluginTy::initIfNeeded(); + if (Err) { + [[maybe_unused]] std::string ErrStr = toString(std::move(Err)); + DP("Failed to init plugin: %s", ErrStr.c_str()); + return OFFLOAD_FAIL; + } + + return OFFLOAD_SUCCESS; +} + +int32_t __tgt_rtl_is_valid_binary(__tgt_device_image *Image) { + if (!PluginTy::isActive()) + return false; + + return PluginTy::get().is_valid_binary(Image); +} + +int32_t __tgt_rtl_init_device(int32_t DeviceId) { + return PluginTy::get().init_device(DeviceId); +} + +int32_t __tgt_rtl_number_of_devices() { + return PluginTy::get().number_of_devices(); +} + +int64_t __tgt_rtl_init_requires(int64_t RequiresFlags) { + return PluginTy::get().init_requires(RequiresFlags); +} + +int32_t __tgt_rtl_is_data_exchangable(int32_t SrcDeviceId, + int32_t DstDeviceId) { + return PluginTy::get().is_data_exchangable(SrcDeviceId, DstDeviceId); +} + +int32_t __tgt_rtl_initialize_record_replay(int32_t DeviceId, int64_t MemorySize, + void *VAddr, bool isRecord, + bool SaveOutput, + uint64_t &ReqPtrArgOffset) { + return PluginTy::get().initialize_record_replay( + DeviceId, MemorySize, VAddr, isRecord, SaveOutput, ReqPtrArgOffset); +} + +int32_t __tgt_rtl_load_binary(int32_t DeviceId, __tgt_device_image *TgtImage, + __tgt_device_binary *Binary) { + return PluginTy::get().load_binary(DeviceId, TgtImage, Binary); +} + +void *__tgt_rtl_data_alloc(int32_t DeviceId, int64_t Size, void *HostPtr, + int32_t Kind) { + return PluginTy::get().data_alloc(DeviceId, Size, HostPtr, Kind); +} + +int32_t __tgt_rtl_data_delete(int32_t DeviceId, void *TgtPtr, int32_t Kind) { + return PluginTy::get().data_delete(DeviceId, TgtPtr, Kind); +} + +int32_t __tgt_rtl_data_lock(int32_t DeviceId, void *Ptr, int64_t Size, + void **LockedPtr) { + return PluginTy::get().data_lock(DeviceId, Ptr, Size, LockedPtr); +} + +int32_t __tgt_rtl_data_unlock(int32_t DeviceId, void *Ptr) { + return PluginTy::get().data_unlock(DeviceId, Ptr); +} + +int32_t __tgt_rtl_data_notify_mapped(int32_t DeviceId, void *HstPtr, + int64_t Size) { + return PluginTy::get().data_notify_mapped(DeviceId, HstPtr, Size); +} + +int32_t __tgt_rtl_data_notify_unmapped(int32_t DeviceId, void *HstPtr) { + return PluginTy::get().data_notify_unmapped(DeviceId, HstPtr); +} + +int32_t __tgt_rtl_data_submit(int32_t DeviceId, void *TgtPtr, void *HstPtr, + int64_t Size) { + return PluginTy::get().data_submit(DeviceId, TgtPtr, HstPtr, Size); +} + +int32_t __tgt_rtl_data_submit_async(int32_t DeviceId, void *TgtPtr, + void *HstPtr, int64_t Size, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().data_submit_async(DeviceId, TgtPtr, HstPtr, Size, + AsyncInfoPtr); +} + +int32_t __tgt_rtl_data_retrieve(int32_t DeviceId, void *HstPtr, void *TgtPtr, + int64_t Size) { + return PluginTy::get().data_retrieve(DeviceId, HstPtr, TgtPtr, Size); +} + +int32_t __tgt_rtl_data_retrieve_async(int32_t DeviceId, void *HstPtr, + void *TgtPtr, int64_t Size, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().data_retrieve_async(DeviceId, HstPtr, TgtPtr, Size, + AsyncInfoPtr); +} + +int32_t __tgt_rtl_data_exchange(int32_t SrcDeviceId, void *SrcPtr, + int32_t DstDeviceId, void *DstPtr, + int64_t Size) { + return PluginTy::get().data_exchange(SrcDeviceId, SrcPtr, DstDeviceId, DstPtr, + Size); +} + +int32_t __tgt_rtl_data_exchange_async(int32_t SrcDeviceId, void *SrcPtr, + int DstDeviceId, void *DstPtr, + int64_t Size, + __tgt_async_info *AsyncInfo) { + return PluginTy::get().data_exchange_async(SrcDeviceId, SrcPtr, DstDeviceId, + DstPtr, Size, AsyncInfo); +} + +int32_t __tgt_rtl_launch_kernel(int32_t DeviceId, void *TgtEntryPtr, + void **TgtArgs, ptrdiff_t *TgtOffsets, + KernelArgsTy *KernelArgs, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().launch_kernel(DeviceId, TgtEntryPtr, TgtArgs, + TgtOffsets, KernelArgs, AsyncInfoPtr); +} + +int32_t __tgt_rtl_synchronize(int32_t DeviceId, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().synchronize(DeviceId, AsyncInfoPtr); +} + +int32_t __tgt_rtl_query_async(int32_t DeviceId, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().query_async(DeviceId, AsyncInfoPtr); +} + +void __tgt_rtl_print_device_info(int32_t DeviceId) { + PluginTy::get().print_device_info(DeviceId); +} + +int32_t __tgt_rtl_create_event(int32_t DeviceId, void **EventPtr) { + return PluginTy::get().create_event(DeviceId, EventPtr); +} + +int32_t __tgt_rtl_record_event(int32_t DeviceId, void *EventPtr, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().record_event(DeviceId, EventPtr, AsyncInfoPtr); +} + +int32_t __tgt_rtl_wait_event(int32_t DeviceId, void *EventPtr, + __tgt_async_info *AsyncInfoPtr) { + return PluginTy::get().wait_event(DeviceId, EventPtr, AsyncInfoPtr); +} + +int32_t __tgt_rtl_sync_event(int32_t DeviceId, void *EventPtr) { + return PluginTy::get().sync_event(DeviceId, EventPtr); +} + +int32_t __tgt_rtl_destroy_event(int32_t DeviceId, void *EventPtr) { + return PluginTy::get().destroy_event(DeviceId, EventPtr); +} + +void __tgt_rtl_set_info_flag(uint32_t NewInfoLevel) { + return PluginTy::get().set_info_flag(NewInfoLevel); +} + +int32_t __tgt_rtl_init_async_info(int32_t DeviceId, + __tgt_async_info **AsyncInfoPtr) { + return PluginTy::get().init_async_info(DeviceId, AsyncInfoPtr); +} + +int32_t __tgt_rtl_init_device_info(int32_t DeviceId, + __tgt_device_info *DeviceInfo, + const char **ErrStr) { + return PluginTy::get().init_device_info(DeviceId, DeviceInfo, ErrStr); +} + +int32_t __tgt_rtl_set_device_offset(int32_t DeviceIdOffset) { + return PluginTy::get().set_device_offset(DeviceIdOffset); +} + +int32_t __tgt_rtl_use_auto_zero_copy(int32_t DeviceId) { + return PluginTy::get().use_auto_zero_copy(DeviceId); +} + +int32_t __tgt_rtl_get_global(__tgt_device_binary Binary, uint64_t Size, + const char *Name, void **DevicePtr) { + return PluginTy::get().get_global(Binary, Size, Name, DevicePtr); +} + +int32_t __tgt_rtl_get_function(__tgt_device_binary Binary, const char *Name, + void **KernelPtr) { + return PluginTy::get().get_function(Binary, Name, KernelPtr); +} + #ifdef __cplusplus } #endif diff --git a/openmp/libomptarget/plugins-nextgen/common/src/RPC.cpp b/openmp/libomptarget/plugins-nextgen/common/src/RPC.cpp index f46b27701b5b91f215dd7dbc1d3f9d8e89f9abc4..faa2cbd4f02fe154cf5a8c376940ba86150e10d8 100644 --- a/openmp/libomptarget/plugins-nextgen/common/src/RPC.cpp +++ b/openmp/libomptarget/plugins-nextgen/common/src/RPC.cpp @@ -21,13 +21,8 @@ using namespace llvm; using namespace omp; using namespace target; -RPCServerTy::RPCServerTy(uint32_t NumDevices) { -#ifdef LIBOMPTARGET_RPC_SUPPORT - // If this fails then something is catastrophically wrong, just exit. - if (rpc_status_t Err = rpc_init(NumDevices)) - FATAL_MESSAGE(1, "Error initializing the RPC server: %d\n", Err); -#endif -} +RPCServerTy::RPCServerTy(plugin::GenericPluginTy &Plugin) + : Handles(Plugin.getNumDevices()) {} llvm::Expected<bool> RPCServerTy::isDeviceUsingRPC(plugin::GenericDeviceTy &Device, @@ -44,7 +39,6 @@ Error RPCServerTy::initDevice(plugin::GenericDeviceTy &Device, plugin::GenericGlobalHandlerTy &Handler, plugin::DeviceImageTy &Image) { #ifdef LIBOMPTARGET_RPC_SUPPORT - uint32_t DeviceId = Device.getDeviceId(); auto Alloc = [](uint64_t Size, void *Data) { plugin::GenericDeviceTy &Device = *reinterpret_cast<plugin::GenericDeviceTy *>(Data); @@ -52,10 +46,12 @@ Error RPCServerTy::initDevice(plugin::GenericDeviceTy &Device, }; uint64_t NumPorts = std::min(Device.requestedRPCPortCount(), RPC_MAXIMUM_PORT_COUNT); - if (rpc_status_t Err = rpc_server_init(DeviceId, NumPorts, + rpc_device_t RPCDevice; + if (rpc_status_t Err = rpc_server_init(&RPCDevice, NumPorts, Device.getWarpSize(), Alloc, &Device)) return plugin::Plugin::error( - "Failed to initialize RPC server for device %d: %d", DeviceId, Err); + "Failed to initialize RPC server for device %d: %d", + Device.getDeviceId(), Err); // Register a custom opcode handler to perform plugin specific allocation. auto MallocHandler = [](rpc_port_t Port, void *Data) { @@ -70,10 +66,10 @@ Error RPCServerTy::initDevice(plugin::GenericDeviceTy &Device, Data); }; if (rpc_status_t Err = - rpc_register_callback(DeviceId, RPC_MALLOC, MallocHandler, &Device)) + rpc_register_callback(RPCDevice, RPC_MALLOC, MallocHandler, &Device)) return plugin::Plugin::error( - "Failed to register RPC malloc handler for device %d: %d\n", DeviceId, - Err); + "Failed to register RPC malloc handler for device %d: %d\n", + Device.getDeviceId(), Err); // Register a custom opcode handler to perform plugin specific deallocation. auto FreeHandler = [](rpc_port_t Port, void *Data) { @@ -88,10 +84,10 @@ Error RPCServerTy::initDevice(plugin::GenericDeviceTy &Device, Data); }; if (rpc_status_t Err = - rpc_register_callback(DeviceId, RPC_FREE, FreeHandler, &Device)) + rpc_register_callback(RPCDevice, RPC_FREE, FreeHandler, &Device)) return plugin::Plugin::error( - "Failed to register RPC free handler for device %d: %d\n", DeviceId, - Err); + "Failed to register RPC free handler for device %d: %d\n", + Device.getDeviceId(), Err); // Get the address of the RPC client from the device. void *ClientPtr; @@ -104,17 +100,19 @@ Error RPCServerTy::initDevice(plugin::GenericDeviceTy &Device, sizeof(void *), nullptr)) return Err; - const void *ClientBuffer = rpc_get_client_buffer(DeviceId); + const void *ClientBuffer = rpc_get_client_buffer(RPCDevice); if (auto Err = Device.dataSubmit(ClientPtr, ClientBuffer, rpc_get_client_size(), nullptr)) return Err; + Handles[Device.getDeviceId()] = RPCDevice.handle; #endif return Error::success(); } Error RPCServerTy::runServer(plugin::GenericDeviceTy &Device) { #ifdef LIBOMPTARGET_RPC_SUPPORT - if (rpc_status_t Err = rpc_handle_server(Device.getDeviceId())) + rpc_device_t RPCDevice{Handles[Device.getDeviceId()]}; + if (rpc_status_t Err = rpc_handle_server(RPCDevice)) return plugin::Plugin::error( "Error while running RPC server on device %d: %d", Device.getDeviceId(), Err); @@ -124,22 +122,16 @@ Error RPCServerTy::runServer(plugin::GenericDeviceTy &Device) { Error RPCServerTy::deinitDevice(plugin::GenericDeviceTy &Device) { #ifdef LIBOMPTARGET_RPC_SUPPORT + rpc_device_t RPCDevice{Handles[Device.getDeviceId()]}; auto Dealloc = [](void *Ptr, void *Data) { plugin::GenericDeviceTy &Device = *reinterpret_cast<plugin::GenericDeviceTy *>(Data); Device.free(Ptr, TARGET_ALLOC_HOST); }; - if (rpc_status_t Err = - rpc_server_shutdown(Device.getDeviceId(), Dealloc, &Device)) + if (rpc_status_t Err = rpc_server_shutdown(RPCDevice, Dealloc, &Device)) return plugin::Plugin::error( "Failed to shut down RPC server for device %d: %d", Device.getDeviceId(), Err); #endif return Error::success(); } - -RPCServerTy::~RPCServerTy() { -#ifdef LIBOMPTARGET_RPC_SUPPORT - rpc_shutdown(); -#endif -} diff --git a/openmp/libomptarget/plugins-nextgen/common/src/Utils/ELF.cpp b/openmp/libomptarget/plugins-nextgen/common/src/Utils/ELF.cpp index c84c3bad5def0a5ac0795b3aa19caa9dbcea7346..2ae97f0f2589252a1a157ac89ac996f26358e74a 100644 --- a/openmp/libomptarget/plugins-nextgen/common/src/Utils/ELF.cpp +++ b/openmp/libomptarget/plugins-nextgen/common/src/Utils/ELF.cpp @@ -36,18 +36,10 @@ bool utils::elf::isELF(StringRef Buffer) { } } -Expected<bool> utils::elf::checkMachine(StringRef Object, uint16_t EMachine) { - assert(isELF(Object) && "Input is not an ELF!"); - - Expected<ELF64LEObjectFile> ElfOrErr = - ELF64LEObjectFile::create(MemoryBufferRef(Object, /*Identifier=*/""), - /*InitContent=*/false); - if (!ElfOrErr) - return ElfOrErr.takeError(); - - const auto Header = ElfOrErr->getELFFile().getHeader(); - if (Header.e_ident[EI_CLASS] != ELFCLASS64) - return createError("Only 64-bit ELF files are supported"); +template <class ELFT> +static Expected<bool> +checkMachineImpl(const object::ELFObjectFile<ELFT> &ELFObj, uint16_t EMachine) { + const auto Header = ELFObj.getELFFile().getHeader(); if (Header.e_type != ET_EXEC && Header.e_type != ET_DYN) return createError("Only executable ELF files are supported"); @@ -71,6 +63,25 @@ Expected<bool> utils::elf::checkMachine(StringRef Object, uint16_t EMachine) { return Header.e_machine == EMachine; } +Expected<bool> utils::elf::checkMachine(StringRef Object, uint16_t EMachine) { + assert(isELF(Object) && "Input is not an ELF!"); + + Expected<std::unique_ptr<ObjectFile>> ElfOrErr = + ObjectFile::createELFObjectFile( + MemoryBufferRef(Object, /*Identifier=*/""), + /*InitContent=*/false); + if (!ElfOrErr) + return ElfOrErr.takeError(); + + if (const ELF64LEObjectFile *ELFObj = + dyn_cast<ELF64LEObjectFile>(&**ElfOrErr)) + return checkMachineImpl(*ELFObj, EMachine); + if (const ELF64BEObjectFile *ELFObj = + dyn_cast<ELF64BEObjectFile>(&**ElfOrErr)) + return checkMachineImpl(*ELFObj, EMachine); + return createError("Only 64-bit ELF files are supported"); +} + template <class ELFT> static Expected<const typename ELFT::Sym *> getSymbolFromGnuHashTable(StringRef Name, const typename ELFT::GnuHash &HashTab, @@ -138,9 +149,10 @@ getSymbolFromSysVHashTable(StringRef Name, const typename ELFT::Hash &HashTab, } template <class ELFT> -static Expected<const typename ELFT::Sym *> -getHashTableSymbol(const ELFFile<ELFT> &Elf, const typename ELFT::Shdr &Sec, - StringRef Name) { +static Expected<std::optional<ELFSymbolRef>> +getHashTableSymbol(const ELFObjectFile<ELFT> &ELFObj, + const typename ELFT::Shdr &Sec, StringRef Name) { + const ELFFile<ELFT> &Elf = ELFObj.getELFFile(); if (Sec.sh_type != ELF::SHT_HASH && Sec.sh_type != ELF::SHT_GNU_HASH) return createError( "invalid sh_type for hash table, expected SHT_HASH or SHT_GNU_HASH"); @@ -179,7 +191,12 @@ getHashTableSymbol(const ELFFile<ELFT> &Elf, const typename ELFT::Shdr &Sec, sizeof(typename ELFT::Word) * HashTab->nbuckets + sizeof(typename ELFT::Word) * (SymTab.size() - HashTab->symndx)) return createError("section has invalid sh_size: " + Twine(Sec.sh_size)); - return getSymbolFromGnuHashTable<ELFT>(Name, *HashTab, SymTab, StrTab); + auto Sym = getSymbolFromGnuHashTable<ELFT>(Name, *HashTab, SymTab, StrTab); + if (!Sym) + return Sym.takeError(); + if (!*Sym) + return std::nullopt; + return ELFObj.toSymbolRef(*SymTabOrErr, *Sym - &SymTab[0]); } // If this is a Sys-V hash table we verify its size and search the symbol @@ -197,16 +214,22 @@ getHashTableSymbol(const ELFFile<ELFT> &Elf, const typename ELFT::Shdr &Sec, sizeof(typename ELFT::Word) * HashTab->nchain) return createError("section has invalid sh_size: " + Twine(Sec.sh_size)); - return getSymbolFromSysVHashTable<ELFT>(Name, *HashTab, SymTab, StrTab); + auto Sym = getSymbolFromSysVHashTable<ELFT>(Name, *HashTab, SymTab, StrTab); + if (!Sym) + return Sym.takeError(); + if (!*Sym) + return std::nullopt; + return ELFObj.toSymbolRef(*SymTabOrErr, *Sym - &SymTab[0]); } - return nullptr; + return std::nullopt; } template <class ELFT> -static Expected<const typename ELFT::Sym *> -getSymTableSymbol(const ELFFile<ELFT> &Elf, const typename ELFT::Shdr &Sec, - StringRef Name) { +static Expected<std::optional<ELFSymbolRef>> +getSymTableSymbol(const ELFObjectFile<ELFT> &ELFObj, + const typename ELFT::Shdr &Sec, StringRef Name) { + const ELFFile<ELFT> &Elf = ELFObj.getELFFile(); if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM) return createError( "invalid sh_type for hash table, expected SHT_SYMTAB or SHT_DYNSYM"); @@ -226,13 +249,14 @@ getSymTableSymbol(const ELFFile<ELFT> &Elf, const typename ELFT::Shdr &Sec, for (const typename ELFT::Sym &Sym : SymTab) if (StrTab.drop_front(Sym.st_name).data() == Name) - return &Sym; + return ELFObj.toSymbolRef(&Sec, &Sym - &SymTab[0]); - return nullptr; + return std::nullopt; } -Expected<const typename ELF64LE::Sym *> -utils::elf::getSymbol(const ELFObjectFile<ELF64LE> &ELFObj, StringRef Name) { +template <class ELFT> +static Expected<std::optional<ELFSymbolRef>> +getSymbolImpl(const ELFObjectFile<ELFT> &ELFObj, StringRef Name) { // First try to look up the symbol via the hash table. for (ELFSectionRef Sec : ELFObj.sections()) { if (Sec.getType() != SHT_HASH && Sec.getType() != SHT_GNU_HASH) @@ -241,8 +265,7 @@ utils::elf::getSymbol(const ELFObjectFile<ELF64LE> &ELFObj, StringRef Name) { auto HashTabOrErr = ELFObj.getELFFile().getSection(Sec.getIndex()); if (!HashTabOrErr) return HashTabOrErr.takeError(); - return getHashTableSymbol<ELF64LE>(ELFObj.getELFFile(), **HashTabOrErr, - Name); + return getHashTableSymbol<ELFT>(ELFObj, **HashTabOrErr, Name); } // If this is an executable file check the entire standard symbol table. @@ -253,16 +276,31 @@ utils::elf::getSymbol(const ELFObjectFile<ELF64LE> &ELFObj, StringRef Name) { auto SymTabOrErr = ELFObj.getELFFile().getSection(Sec.getIndex()); if (!SymTabOrErr) return SymTabOrErr.takeError(); - return getSymTableSymbol<ELF64LE>(ELFObj.getELFFile(), **SymTabOrErr, Name); + return getSymTableSymbol<ELFT>(ELFObj, **SymTabOrErr, Name); } - return nullptr; + return std::nullopt; } -Expected<const void *> utils::elf::getSymbolAddress( - const object::ELFObjectFile<object::ELF64LE> &ELFObj, - const object::ELF64LE::Sym &Symbol) { - const ELFFile<ELF64LE> &ELFFile = ELFObj.getELFFile(); +Expected<std::optional<ELFSymbolRef>> +utils::elf::getSymbol(const ObjectFile &Obj, StringRef Name) { + if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(&Obj)) + return getSymbolImpl(*ELFObj, Name); + if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(&Obj)) + return getSymbolImpl(*ELFObj, Name); + return createError("Only 64-bit ELF files are supported"); +} + +template <class ELFT> +static Expected<const void *> +getSymbolAddressImpl(const ELFObjectFile<ELFT> &ELFObj, + const ELFSymbolRef &SymRef) { + const ELFFile<ELFT> &ELFFile = ELFObj.getELFFile(); + + auto SymOrErr = ELFObj.getSymbol(SymRef.getRawDataRefImpl()); + if (!SymOrErr) + return SymOrErr.takeError(); + const auto &Symbol = **SymOrErr; auto SecOrErr = ELFFile.getSection(Symbol.st_shndx); if (!SecOrErr) @@ -283,3 +321,13 @@ Expected<const void *> utils::elf::getSymbolAddress( return ELFFile.base() + Offset; } + +Expected<const void *> +utils::elf::getSymbolAddress(const ELFSymbolRef &SymRef) { + const ObjectFile *Obj = SymRef.getObject(); + if (const ELF64LEObjectFile *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) + return getSymbolAddressImpl(*ELFObj, SymRef); + if (const ELF64BEObjectFile *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) + return getSymbolAddressImpl(*ELFObj, SymRef); + return createError("Only 64-bit ELF files are supported"); +} diff --git a/openmp/libomptarget/plugins-nextgen/cuda/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/cuda/CMakeLists.txt index 2bfb47168a7f3b5e76f914b72b095775e3f3ce92..b3530462aa19ba071e014809d3252f60d43e4663 100644 --- a/openmp/libomptarget/plugins-nextgen/cuda/CMakeLists.txt +++ b/openmp/libomptarget/plugins-nextgen/cuda/CMakeLists.txt @@ -23,34 +23,12 @@ endif() libomptarget_say("Building CUDA NextGen offloading plugin.") -set(LIBOMPTARGET_DLOPEN_LIBCUDA OFF) -option(LIBOMPTARGET_FORCE_DLOPEN_LIBCUDA "Build with dlopened libcuda" ${LIBOMPTARGET_DLOPEN_LIBCUDA}) - -add_llvm_library(omptarget.rtl.cuda SHARED - src/rtl.cpp - - LINK_COMPONENTS - Support - Object - - LINK_LIBS PRIVATE - PluginCommon - ${OPENMP_PTHREAD_LIB} - - NO_INSTALL_RPATH - BUILDTREE_ONLY -) - -if ((OMPT_TARGET_DEFAULT) AND (LIBOMPTARGET_OMPT_SUPPORT)) - target_link_libraries(omptarget.rtl.cuda PRIVATE OMPT) -endif() - -if (LIBOMP_HAVE_VERSION_SCRIPT_FLAG) - target_link_libraries(omptarget.rtl.cuda PRIVATE - "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports,-z,defs") -endif() +# Create the library and add the default arguments. +add_target_library(omptarget.rtl.cuda CUDA) +target_sources(omptarget.rtl.cuda PRIVATE src/rtl.cpp) +option(LIBOMPTARGET_FORCE_DLOPEN_LIBCUDA "Build with dlopened libcuda" OFF) if(LIBOMPTARGET_DEP_CUDA_FOUND AND NOT LIBOMPTARGET_FORCE_DLOPEN_LIBCUDA) libomptarget_say("Building CUDA plugin linked against libcuda") target_link_libraries(omptarget.rtl.cuda PRIVATE CUDA::cuda_driver) @@ -60,13 +38,6 @@ else() target_sources(omptarget.rtl.cuda PRIVATE dynamic_cuda/cuda.cpp) endif() -# Define debug prefix. TODO: This should be automatized in the Debug.h but it -# requires changing the original plugins. -target_compile_definitions(omptarget.rtl.cuda PRIVATE TARGET_NAME="CUDA") -target_compile_definitions(omptarget.rtl.cuda PRIVATE DEBUG_PREFIX="TARGET CUDA RTL") - -target_include_directories(omptarget.rtl.cuda PRIVATE ${LIBOMPTARGET_INCLUDE_DIR}) - # Configure testing for the CUDA plugin. We will build tests if we could a # functional NVIDIA GPU on the system, or if manually specifies by the user. option(LIBOMPTARGET_FORCE_NVIDIA_TESTS "Build NVIDIA libomptarget tests" OFF) @@ -84,5 +55,4 @@ endif() # Install plugin under the lib destination folder. install(TARGETS omptarget.rtl.cuda LIBRARY DESTINATION "${OPENMP_INSTALL_LIBDIR}") set_target_properties(omptarget.rtl.cuda PROPERTIES - INSTALL_RPATH "$ORIGIN" BUILD_RPATH "$ORIGIN:${CMAKE_CURRENT_BINARY_DIR}/.." - CXX_VISIBILITY_PRESET protected) + INSTALL_RPATH "$ORIGIN" BUILD_RPATH "$ORIGIN:${CMAKE_CURRENT_BINARY_DIR}/..") diff --git a/openmp/libomptarget/plugins-nextgen/cuda/src/rtl.cpp b/openmp/libomptarget/plugins-nextgen/cuda/src/rtl.cpp index f85a00cd1cd53045f83c7555c880f6dca82e3e9a..fc74c6aa23fddddf799b4ad362ba4d47ff094fcf 100644 --- a/openmp/libomptarget/plugins-nextgen/cuda/src/rtl.cpp +++ b/openmp/libomptarget/plugins-nextgen/cuda/src/rtl.cpp @@ -255,8 +255,8 @@ private: /// generic device class. struct CUDADeviceTy : public GenericDeviceTy { // Create a CUDA device with a device id and the default CUDA grid values. - CUDADeviceTy(int32_t DeviceId, int32_t NumDevices) - : GenericDeviceTy(DeviceId, NumDevices, NVPTXGridValues), + CUDADeviceTy(GenericPluginTy &Plugin, int32_t DeviceId, int32_t NumDevices) + : GenericDeviceTy(Plugin, DeviceId, NumDevices, NVPTXGridValues), CUDAStreamManager(*this), CUDAEventManager(*this) {} ~CUDADeviceTy() {} @@ -471,7 +471,7 @@ struct CUDADeviceTy : public GenericDeviceTy { /// Allocate and construct a CUDA kernel. Expected<GenericKernelTy &> constructKernel(const char *Name) override { // Allocate and construct the CUDA kernel. - CUDAKernelTy *CUDAKernel = Plugin::get().allocate<CUDAKernelTy>(); + CUDAKernelTy *CUDAKernel = Plugin.allocate<CUDAKernelTy>(); if (!CUDAKernel) return Plugin::error("Failed to allocate memory for CUDA kernel"); @@ -529,7 +529,7 @@ struct CUDADeviceTy : public GenericDeviceTy { return std::move(Err); // Allocate and initialize the image object. - CUDADeviceImageTy *CUDAImage = Plugin::get().allocate<CUDADeviceImageTy>(); + CUDADeviceImageTy *CUDAImage = Plugin.allocate<CUDADeviceImageTy>(); new (CUDAImage) CUDADeviceImageTy(ImageId, *this, TgtImage); // Load the CUDA module. @@ -1166,7 +1166,7 @@ private: // Search for all symbols that contain a constructor or destructor. SmallVector<std::pair<StringRef, uint16_t>> Funcs; - for (ELFSymbolRef Sym : ELFObjOrErr->symbols()) { + for (ELFSymbolRef Sym : (*ELFObjOrErr)->symbols()) { auto NameOrErr = Sym.getName(); if (!NameOrErr) return NameOrErr.takeError(); @@ -1371,6 +1371,17 @@ struct CUDAPluginTy final : public GenericPluginTy { /// Deinitialize the plugin. Error deinitImpl() override { return Plugin::success(); } + /// Creates a CUDA device to use for offloading. + GenericDeviceTy *createDevice(GenericPluginTy &Plugin, int32_t DeviceId, + int32_t NumDevices) override { + return new CUDADeviceTy(Plugin, DeviceId, NumDevices); + } + + /// Creates a CUDA global handler. + GenericGlobalHandlerTy *createGlobalHandler() override { + return new CUDAGlobalHandlerTy(); + } + /// Get the ELF code for recognizing the compatible image binary. uint16_t getMagicElfBits() const override { return ELF::EM_CUDA; } @@ -1484,18 +1495,10 @@ Error CUDADeviceTy::dataExchangeImpl(const void *SrcPtr, return Plugin::check(Res, "Error in cuMemcpyDtoDAsync: %s"); } -GenericPluginTy *Plugin::createPlugin() { return new CUDAPluginTy(); } - -GenericDeviceTy *Plugin::createDevice(int32_t DeviceId, int32_t NumDevices) { - return new CUDADeviceTy(DeviceId, NumDevices); -} - -GenericGlobalHandlerTy *Plugin::createGlobalHandler() { - return new CUDAGlobalHandlerTy(); -} +GenericPluginTy *PluginTy::createPlugin() { return new CUDAPluginTy(); } template <typename... ArgsTy> -Error Plugin::check(int32_t Code, const char *ErrFmt, ArgsTy... Args) { +static Error Plugin::check(int32_t Code, const char *ErrFmt, ArgsTy... Args) { CUresult ResultCode = static_cast<CUresult>(Code); if (ResultCode == CUDA_SUCCESS) return Error::success(); diff --git a/openmp/libomptarget/plugins-nextgen/host/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/host/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ccbf7d033fd663055cae583e558275ab99f7240a --- /dev/null +++ b/openmp/libomptarget/plugins-nextgen/host/CMakeLists.txt @@ -0,0 +1,83 @@ +if(NOT CMAKE_SYSTEM_NAME MATCHES "Linux") + return() +endif() + +set(supported_targets x86_64 aarch64 ppc64 ppc64le s390x) +if(NOT ${CMAKE_SYSTEM_PROCESSOR} IN_LIST supported_targets) + libomptarget_say("Not building ${machine} NextGen offloading plugin") + return() +endif() + +set(machine ${CMAKE_SYSTEM_PROCESSOR}) +if(CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64le$") + set(machine ppc64) +endif() + +# Create the library and add the default arguments. +add_target_library(omptarget.rtl.${machine} ${machine}) + +target_sources(omptarget.rtl.${machine} PRIVATE src/rtl.cpp) + +if(LIBOMPTARGET_DEP_LIBFFI_FOUND) + libomptarget_say("Building ${machine} plugin linked with libffi") + if(FFI_STATIC_LIBRARIES) + target_link_libraries(omptarget.rtl.${machine} PRIVATE FFI::ffi_static) + else() + target_link_libraries(omptarget.rtl.${machine} PRIVATE FFI::ffi) + endif() +else() + libomptarget_say("Building ${machine} plugin for dlopened libffi") + target_sources(omptarget.rtl.${machine} PRIVATE dynamic_ffi/ffi.cpp) + target_include_directories(omptarget.rtl.${machine} PRIVATE dynamic_ffi) +endif() + +# Install plugin under the lib destination folder. +install(TARGETS omptarget.rtl.${machine} + LIBRARY DESTINATION "${OPENMP_INSTALL_LIBDIR}") +set_target_properties(omptarget.rtl.${machine} PROPERTIES + INSTALL_RPATH "$ORIGIN" BUILD_RPATH "$ORIGIN:${CMAKE_CURRENT_BINARY_DIR}/.." + POSITION_INDEPENDENT_CODE ON + CXX_VISIBILITY_PRESET protected) + +target_include_directories(omptarget.rtl.${machine} PRIVATE + ${LIBOMPTARGET_INCLUDE_DIR}) + +if(LIBOMPTARGET_DEP_LIBFFI_FOUND) + list(APPEND LIBOMPTARGET_TESTED_PLUGINS omptarget.rtl.${machine}) + set(LIBOMPTARGET_TESTED_PLUGINS + "${LIBOMPTARGET_TESTED_PLUGINS}" PARENT_SCOPE) +else() + libomptarget_say("Not generating ${tmachine_name} tests. LibFFI not found.") +endif() + +# Define the target specific triples and ELF machine values. +if(CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64le$" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64$") + target_compile_definitions(omptarget.rtl.${machine} PRIVATE TARGET_ELF_ID=EM_PPC64) + target_compile_definitions(omptarget.rtl.${machine} PRIVATE + LIBOMPTARGET_NEXTGEN_GENERIC_PLUGIN_TRIPLE="powerpc64-ibm-linux-gnu") + list(APPEND LIBOMPTARGET_SYSTEM_TARGETS + "powerpc64-ibm-linux-gnu" "powerpc64-ibm-linux-gnu-LTO") + set(LIBOMPTARGET_SYSTEM_TARGETS "${LIBOMPTARGET_SYSTEM_TARGETS}" PARENT_SCOPE) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64$") + target_compile_definitions(omptarget.rtl.${machine} PRIVATE TARGET_ELF_ID=EM_X86_64) + target_compile_definitions(omptarget.rtl.${machine} PRIVATE + LIBOMPTARGET_NEXTGEN_GENERIC_PLUGIN_TRIPLE="x86_64-pc-linux-gnu") + list(APPEND LIBOMPTARGET_SYSTEM_TARGETS + "x86_64-pc-linux-gnu" "x86_64-pc-linux-gnu-LTO") + set(LIBOMPTARGET_SYSTEM_TARGETS "${LIBOMPTARGET_SYSTEM_TARGETS}" PARENT_SCOPE) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64$") + target_compile_definitions(omptarget.rtl.${machine} PRIVATE TARGET_ELF_ID=EM_AARCH64) + target_compile_definitions(omptarget.rtl.${machine} PRIVATE + LIBOMPTARGET_NEXTGEN_GENERIC_PLUGIN_TRIPLE="aarch64-unknown-linux-gnu") + list(APPEND LIBOMPTARGET_SYSTEM_TARGETS + "aarch64-unknown-linux-gnu" "aarch64-unknown-linux-gnu-LTO") + set(LIBOMPTARGET_SYSTEM_TARGETS "${LIBOMPTARGET_SYSTEM_TARGETS}" PARENT_SCOPE) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "s390x$") + target_compile_definitions(omptarget.rtl.${machine} PRIVATE TARGET_ELF_ID=EM_S390) + target_compile_definitions(omptarget.rtl.${machine} PRIVATE + LIBOMPTARGET_NEXTGEN_GENERIC_PLUGIN_TRIPLE="s390x-ibm-linux-gnu") + list(APPEND LIBOMPTARGET_SYSTEM_TARGETS + "s390x-ibm-linux-gnu" "s390x-ibm-linux-gnu-LTO") + set(LIBOMPTARGET_SYSTEM_TARGETS "${LIBOMPTARGET_SYSTEM_TARGETS}" PARENT_SCOPE) +endif() diff --git a/openmp/libomptarget/plugins-nextgen/generic-elf-64bit/dynamic_ffi/ffi.cpp b/openmp/libomptarget/plugins-nextgen/host/dynamic_ffi/ffi.cpp similarity index 78% rename from openmp/libomptarget/plugins-nextgen/generic-elf-64bit/dynamic_ffi/ffi.cpp rename to openmp/libomptarget/plugins-nextgen/host/dynamic_ffi/ffi.cpp index c79daa798581710a67446831055a33d5f7335a58..c586ad1c1969b318b8e5af570b6234df6856afbd 100644 --- a/openmp/libomptarget/plugins-nextgen/generic-elf-64bit/dynamic_ffi/ffi.cpp +++ b/openmp/libomptarget/plugins-nextgen/host/dynamic_ffi/ffi.cpp @@ -11,6 +11,8 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/DynamicLibrary.h" + +#include "Shared/Debug.h" #include <memory> #include "DLWrap.h" @@ -37,15 +39,21 @@ uint32_t ffi_init() { std::string ErrMsg; auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>( llvm::sys::DynamicLibrary::getPermanentLibrary(FFI_PATH, &ErrMsg)); - if (!DynlibHandle->isValid()) + + if (!DynlibHandle->isValid()) { + DP("Unable to load library '%s': %s!\n", FFI_PATH, ErrMsg.c_str()); return DYNAMIC_FFI_FAIL; + } for (size_t I = 0; I < dlwrap::size(); I++) { const char *Sym = dlwrap::symbol(I); void *P = DynlibHandle->getAddressOfSymbol(Sym); - if (P == nullptr) + if (P == nullptr) { + DP("Unable to find '%s' in '%s'!\n", Sym, FFI_PATH); return DYNAMIC_FFI_FAIL; + } + DP("Implementing %s with dlsym(%s) -> %p\n", Sym, Sym, P); *dlwrap::pointer(I) = P; } @@ -53,8 +61,10 @@ uint32_t ffi_init() { #define DYNAMIC_INIT(SYMBOL) \ { \ void *SymbolPtr = DynlibHandle->getAddressOfSymbol(#SYMBOL); \ - if (!SymbolPtr) \ + if (!SymbolPtr) { \ + DP("Unable to find '%s' in '%s'!\n", #SYMBOL, FFI_PATH); \ return DYNAMIC_FFI_FAIL; \ + } \ SYMBOL = *reinterpret_cast<decltype(SYMBOL) *>(SymbolPtr); \ } DYNAMIC_INIT(ffi_type_void); diff --git a/openmp/libomptarget/plugins-nextgen/generic-elf-64bit/dynamic_ffi/ffi.h b/openmp/libomptarget/plugins-nextgen/host/dynamic_ffi/ffi.h similarity index 100% rename from openmp/libomptarget/plugins-nextgen/generic-elf-64bit/dynamic_ffi/ffi.h rename to openmp/libomptarget/plugins-nextgen/host/dynamic_ffi/ffi.h diff --git a/openmp/libomptarget/plugins-nextgen/generic-elf-64bit/src/rtl.cpp b/openmp/libomptarget/plugins-nextgen/host/src/rtl.cpp similarity index 91% rename from openmp/libomptarget/plugins-nextgen/generic-elf-64bit/src/rtl.cpp rename to openmp/libomptarget/plugins-nextgen/host/src/rtl.cpp index 38fc275804faf123e594db82e491086ee6e3cfd2..f0ce24249301af32523ec4655c72aa8f631e77f3 100644 --- a/openmp/libomptarget/plugins-nextgen/generic-elf-64bit/src/rtl.cpp +++ b/openmp/libomptarget/plugins-nextgen/host/src/rtl.cpp @@ -35,7 +35,12 @@ // The ELF ID should be defined at compile-time by the build system. #ifndef TARGET_ELF_ID -#define TARGET_ELF_ID ELF::EM_NONE +#define TARGET_ELF_ID EM_NONE +#endif + +// The target triple should be defined at compile-time by the build system. +#ifndef LIBOMPTARGET_NEXTGEN_GENERIC_PLUGIN_TRIPLE +#define LIBOMPTARGET_NEXTGEN_GENERIC_PLUGIN_TRIPLE "" #endif namespace llvm { @@ -61,7 +66,7 @@ struct GenELF64KernelTy : public GenericKernelTy { GlobalTy Global(getName(), 0); // Get the metadata (address) of the kernel function. - GenericGlobalHandlerTy &GHandler = Plugin::get().getGlobalHandler(); + GenericGlobalHandlerTy &GHandler = Device.Plugin.getGlobalHandler(); if (auto Err = GHandler.getGlobalMetadataFromDevice(Device, Image, Global)) return Err; @@ -127,8 +132,9 @@ private: /// Class implementing the device functionalities for GenELF64. struct GenELF64DeviceTy : public GenericDeviceTy { /// Create the device with a specific id. - GenELF64DeviceTy(int32_t DeviceId, int32_t NumDevices) - : GenericDeviceTy(DeviceId, NumDevices, GenELF64GridValues) {} + GenELF64DeviceTy(GenericPluginTy &Plugin, int32_t DeviceId, + int32_t NumDevices) + : GenericDeviceTy(Plugin, DeviceId, NumDevices, GenELF64GridValues) {} ~GenELF64DeviceTy() {} @@ -144,8 +150,7 @@ struct GenELF64DeviceTy : public GenericDeviceTy { /// Construct the kernel for a specific image on the device. Expected<GenericKernelTy &> constructKernel(const char *Name) override { // Allocate and construct the kernel. - GenELF64KernelTy *GenELF64Kernel = - Plugin::get().allocate<GenELF64KernelTy>(); + GenELF64KernelTy *GenELF64Kernel = Plugin.allocate<GenELF64KernelTy>(); if (!GenELF64Kernel) return Plugin::error("Failed to allocate memory for GenELF64 kernel"); @@ -161,8 +166,7 @@ struct GenELF64DeviceTy : public GenericDeviceTy { Expected<DeviceImageTy *> loadBinaryImpl(const __tgt_device_image *TgtImage, int32_t ImageId) override { // Allocate and initialize the image object. - GenELF64DeviceImageTy *Image = - Plugin::get().allocate<GenELF64DeviceImageTy>(); + GenELF64DeviceImageTy *Image = Plugin.allocate<GenELF64DeviceImageTy>(); new (Image) GenELF64DeviceImageTy(ImageId, *this, TgtImage); // Create a temporary file. @@ -394,8 +398,19 @@ struct GenELF64PluginTy final : public GenericPluginTy { /// Deinitialize the plugin. Error deinitImpl() override { return Plugin::success(); } + /// Creates a generic ELF device. + GenericDeviceTy *createDevice(GenericPluginTy &Plugin, int32_t DeviceId, + int32_t NumDevices) override { + return new GenELF64DeviceTy(Plugin, DeviceId, NumDevices); + } + + /// Creates a generic global handler. + GenericGlobalHandlerTy *createGlobalHandler() override { + return new GenELF64GlobalHandlerTy(); + } + /// Get the ELF code to recognize the compatible binary images. - uint16_t getMagicElfBits() const override { return TARGET_ELF_ID; } + uint16_t getMagicElfBits() const override { return ELF::TARGET_ELF_ID; } /// This plugin does not support exchanging data between two devices. bool isDataExchangable(int32_t SrcDeviceId, int32_t DstDeviceId) override { @@ -406,22 +421,14 @@ struct GenELF64PluginTy final : public GenericPluginTy { Expected<bool> isELFCompatible(StringRef) const override { return true; } Triple::ArchType getTripleArch() const override { - return Triple::LIBOMPTARGET_NEXTGEN_GENERIC_PLUGIN_TRIPLE; + return llvm::Triple(LIBOMPTARGET_NEXTGEN_GENERIC_PLUGIN_TRIPLE).getArch(); } }; -GenericPluginTy *Plugin::createPlugin() { return new GenELF64PluginTy(); } - -GenericDeviceTy *Plugin::createDevice(int32_t DeviceId, int32_t NumDevices) { - return new GenELF64DeviceTy(DeviceId, NumDevices); -} - -GenericGlobalHandlerTy *Plugin::createGlobalHandler() { - return new GenELF64GlobalHandlerTy(); -} +GenericPluginTy *PluginTy::createPlugin() { return new GenELF64PluginTy(); } template <typename... ArgsTy> -Error Plugin::check(int32_t Code, const char *ErrMsg, ArgsTy... Args) { +static Error Plugin::check(int32_t Code, const char *ErrMsg, ArgsTy... Args) { if (Code == 0) return Error::success(); diff --git a/openmp/libomptarget/plugins-nextgen/ppc64/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/ppc64/CMakeLists.txt deleted file mode 100644 index 0cccc9cb82e42c673f08e6014bbc812abd7d4e9d..0000000000000000000000000000000000000000 --- a/openmp/libomptarget/plugins-nextgen/ppc64/CMakeLists.txt +++ /dev/null @@ -1,17 +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 -# -##===----------------------------------------------------------------------===## -# -# Build a plugin for a ppc64 machine if available. -# -##===----------------------------------------------------------------------===## - -if(CMAKE_SYSTEM_NAME MATCHES "Linux") - build_generic_elf64("ppc64" "PPC64" "ppc64" "powerpc64-ibm-linux-gnu" "21") -else() - libomptarget_say("Not building ppc64 NextGen offloading plugin: machine not found in the system.") -endif() diff --git a/openmp/libomptarget/plugins-nextgen/ppc64le/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/ppc64le/CMakeLists.txt deleted file mode 100644 index 9461d79d145dfe49b4843474a6fca384d557a9f1..0000000000000000000000000000000000000000 --- a/openmp/libomptarget/plugins-nextgen/ppc64le/CMakeLists.txt +++ /dev/null @@ -1,17 +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 -# -##===----------------------------------------------------------------------===## -# -# Build a plugin for a ppc64le machine if available. -# -##===----------------------------------------------------------------------===## - -if(CMAKE_SYSTEM_NAME MATCHES "Linux") - build_generic_elf64("ppc64le" "PPC64le" "ppc64" "powerpc64le-ibm-linux-gnu" "21") -else() - libomptarget_say("Not building ppc64le NextGen offloading plugin: machine not found in the system.") -endif() diff --git a/openmp/libomptarget/plugins-nextgen/s390x/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/s390x/CMakeLists.txt deleted file mode 100644 index 1b12a292899980ea99e82d37f0524d17c2254221..0000000000000000000000000000000000000000 --- a/openmp/libomptarget/plugins-nextgen/s390x/CMakeLists.txt +++ /dev/null @@ -1,17 +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 -# -##===----------------------------------------------------------------------===## -# -# Build a plugin for a s390x machine if available. -# -##===----------------------------------------------------------------------===## - -if(CMAKE_SYSTEM_NAME MATCHES "Linux") - build_generic_elf64("SystemZ" "S390X" "s390x" "s390x-ibm-linux-gnu" "22") -else() - libomptarget_say("Not building s390x NextGen offloading plugin: machine not found in the system.") -endif() diff --git a/openmp/libomptarget/plugins-nextgen/x86_64/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/x86_64/CMakeLists.txt deleted file mode 100644 index 129d526a2ae7841954c369868470bd4efbc8b34c..0000000000000000000000000000000000000000 --- a/openmp/libomptarget/plugins-nextgen/x86_64/CMakeLists.txt +++ /dev/null @@ -1,17 +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 -# -##===----------------------------------------------------------------------===## -# -# Build a plugin for a x86_64 machine if available. -# -##===----------------------------------------------------------------------===## - -if(CMAKE_SYSTEM_NAME MATCHES "Linux") - build_generic_elf64("x86_64" "x86_64" "x86_64" "x86_64-pc-linux-gnu" "62") -else() - libomptarget_say("Not building x86_64 NextGen offloading plugin: machine not found in the system.") -endif() diff --git a/openmp/libomptarget/src/CMakeLists.txt b/openmp/libomptarget/src/CMakeLists.txt index 9bc3f3339583d9dcc155a9f6eb74799f2ffd9def..d0971bd4ef079e80209546843a0055c4a7daec70 100644 --- a/openmp/libomptarget/src/CMakeLists.txt +++ b/openmp/libomptarget/src/CMakeLists.txt @@ -73,6 +73,7 @@ if (NOT LIBOMPTARGET_PLUGINS_TO_LOAD) check_plugin_target(cuda) check_plugin_target(aarch64) check_plugin_target(amdgpu) + check_plugin_target(s390x) endif() list(TRANSFORM LIBOMPTARGET_PLUGINS_TO_LOAD PREPEND "\"libomptarget.rtl.") diff --git a/openmp/libomptarget/src/OpenMP/API.cpp b/openmp/libomptarget/src/OpenMP/API.cpp index 85fb08c00a9a74297cb3509125aef168d9aff6ed..c85f9868e37c255c91a14475b5bdf6fb20d11ef1 100644 --- a/openmp/libomptarget/src/OpenMP/API.cpp +++ b/openmp/libomptarget/src/OpenMP/API.cpp @@ -16,6 +16,7 @@ #include "rtl.h" #include "OpenMP/InternalTypes.h" +#include "OpenMP/Mapping.h" #include "OpenMP/OMPT/Interface.h" #include "OpenMP/omp.h" #include "Shared/Profile.h" @@ -27,6 +28,13 @@ #include <cstring> #include <mutex> +EXTERN void ompx_dump_mapping_tables() { + ident_t Loc = {0, 0, 0, 0, ";libomptarget;libomptarget;0;0;;"}; + auto ExclusiveDevicesAccessor = PM->getExclusiveDevicesAccessor(); + for (auto &Device : PM->devices(ExclusiveDevicesAccessor)) + dumpTargetPointerMappings(&Loc, Device, true); +} + #ifdef OMPT_SUPPORT using namespace llvm::omp::target::ompt; #endif diff --git a/openmp/libomptarget/src/OpenMP/Mapping.cpp b/openmp/libomptarget/src/OpenMP/Mapping.cpp index 9c0b219b6f15f126a5482816cacf52a0b2d7f080..c6ff3aa54dd66f695f820bec18673b12168b34be 100644 --- a/openmp/libomptarget/src/OpenMP/Mapping.cpp +++ b/openmp/libomptarget/src/OpenMP/Mapping.cpp @@ -16,28 +16,33 @@ #include "device.h" /// Dump a table of all the host-target pointer pairs on failure -void dumpTargetPointerMappings(const ident_t *Loc, DeviceTy &Device) { +void dumpTargetPointerMappings(const ident_t *Loc, DeviceTy &Device, + bool toStdOut) { MappingInfoTy::HDTTMapAccessorTy HDTTMap = Device.getMappingInfo().HostDataToTargetMap.getExclusiveAccessor(); - if (HDTTMap->empty()) + if (HDTTMap->empty()) { + DUMP_INFO(toStdOut, OMP_INFOTYPE_ALL, Device.DeviceID, + "OpenMP Host-Device pointer mappings table empty\n"); return; + } SourceInfo Kernel(Loc); - INFO(OMP_INFOTYPE_ALL, Device.DeviceID, - "OpenMP Host-Device pointer mappings after block at %s:%d:%d:\n", - Kernel.getFilename(), Kernel.getLine(), Kernel.getColumn()); - INFO(OMP_INFOTYPE_ALL, Device.DeviceID, "%-18s %-18s %s %s %s %s\n", - "Host Ptr", "Target Ptr", "Size (B)", "DynRefCount", "HoldRefCount", - "Declaration"); + DUMP_INFO(toStdOut, OMP_INFOTYPE_ALL, Device.DeviceID, + "OpenMP Host-Device pointer mappings after block at %s:%d:%d:\n", + Kernel.getFilename(), Kernel.getLine(), Kernel.getColumn()); + DUMP_INFO(toStdOut, OMP_INFOTYPE_ALL, Device.DeviceID, + "%-18s %-18s %s %s %s %s\n", "Host Ptr", "Target Ptr", "Size (B)", + "DynRefCount", "HoldRefCount", "Declaration"); for (const auto &It : *HDTTMap) { HostDataToTargetTy &HDTT = *It.HDTT; SourceInfo Info(HDTT.HstPtrName); - INFO(OMP_INFOTYPE_ALL, Device.DeviceID, - DPxMOD " " DPxMOD " %-8" PRIuPTR " %-11s %-12s %s at %s:%d:%d\n", - DPxPTR(HDTT.HstPtrBegin), DPxPTR(HDTT.TgtPtrBegin), - HDTT.HstPtrEnd - HDTT.HstPtrBegin, HDTT.dynRefCountToStr().c_str(), - HDTT.holdRefCountToStr().c_str(), Info.getName(), Info.getFilename(), - Info.getLine(), Info.getColumn()); + DUMP_INFO(toStdOut, OMP_INFOTYPE_ALL, Device.DeviceID, + DPxMOD " " DPxMOD " %-8" PRIuPTR " %-11s %-12s %s at %s:%d:%d\n", + DPxPTR(HDTT.HstPtrBegin), DPxPTR(HDTT.TgtPtrBegin), + HDTT.HstPtrEnd - HDTT.HstPtrBegin, + HDTT.dynRefCountToStr().c_str(), HDTT.holdRefCountToStr().c_str(), + Info.getName(), Info.getFilename(), Info.getLine(), + Info.getColumn()); } } @@ -511,7 +516,8 @@ static void printCopyInfoImpl(int DeviceId, bool H2D, void *SrcPtrBegin, "Copying data from %s to %s, %sPtr=" DPxMOD ", %sPtr=" DPxMOD ", Size=%" PRId64 ", Name=%s\n", H2D ? "host" : "device", H2D ? "device" : "host", H2D ? "Hst" : "Tgt", - DPxPTR(SrcPtrBegin), H2D ? "Tgt" : "Hst", DPxPTR(DstPtrBegin), Size, + DPxPTR(H2D ? SrcPtrBegin : DstPtrBegin), H2D ? "Tgt" : "Hst", + DPxPTR(H2D ? DstPtrBegin : SrcPtrBegin), Size, (HT && HT->HstPtrName) ? getNameFromMapping(HT->HstPtrName).c_str() : "unknown"); } diff --git a/openmp/libomptarget/src/PluginManager.cpp b/openmp/libomptarget/src/PluginManager.cpp index 928913275332c055a5a64b8fdc44dfd4b9b37e6a..792cae3e3dd583d469493c7b8c37da128115df29 100644 --- a/openmp/libomptarget/src/PluginManager.cpp +++ b/openmp/libomptarget/src/PluginManager.cpp @@ -78,7 +78,7 @@ Error PluginAdaptorTy::init() { } // No devices are supported by this RTL? - NumberOfPluginDevices = number_of_devices(); + int32_t NumberOfPluginDevices = number_of_devices(); if (!NumberOfPluginDevices) { return createStringError(inconvertibleErrorCode(), "No devices supported in this RTL\n"); @@ -110,32 +110,33 @@ void PluginManager::init() { DP("RTLs loaded!\n"); } -void PluginAdaptorTy::initDevices(PluginManager &PM) { - if (isUsed()) +void PluginManager::initDevices(PluginAdaptorTy &RTL) { + // If this RTL has already been initialized. + if (PM->DeviceOffsets.contains(&RTL)) return; TIMESCOPE(); // If this RTL is not already in use, initialize it. - assert(getNumberOfPluginDevices() > 0 && + assert(RTL.number_of_devices() > 0 && "Tried to initialize useless plugin adaptor"); // Initialize the device information for the RTL we are about to use. - auto ExclusiveDevicesAccessor = PM.getExclusiveDevicesAccessor(); + auto ExclusiveDevicesAccessor = getExclusiveDevicesAccessor(); // Initialize the index of this RTL and save it in the used RTLs. - DeviceOffset = ExclusiveDevicesAccessor->size(); + int32_t DeviceOffset = ExclusiveDevicesAccessor->size(); - // If possible, set the device identifier offset in the plugin. - if (set_device_offset) - set_device_offset(DeviceOffset); + // Set the device identifier offset in the plugin. + RTL.set_device_offset(DeviceOffset); - int32_t NumPD = getNumberOfPluginDevices(); + int32_t NumberOfUserDevices = 0; + int32_t NumPD = RTL.number_of_devices(); ExclusiveDevicesAccessor->reserve(DeviceOffset + NumPD); // Auto zero-copy is a per-device property. We need to ensure // that all devices are suggesting to use it. bool UseAutoZeroCopy = !(NumPD == 0); for (int32_t PDevI = 0, UserDevId = DeviceOffset; PDevI < NumPD; PDevI++) { - auto Device = std::make_unique<DeviceTy>(this, UserDevId, PDevI); + auto Device = std::make_unique<DeviceTy>(&RTL, UserDevId, PDevI); if (auto Err = Device->init()) { DP("Skip plugin known device %d: %s\n", PDevI, toString(std::move(Err)).c_str()); @@ -153,20 +154,23 @@ void PluginAdaptorTy::initDevices(PluginManager &PM) { // If all devices suggest to use it, change requirment flags to trigger // zero-copy behavior when mapping memory. if (UseAutoZeroCopy) - PM.addRequirements(OMPX_REQ_AUTO_ZERO_COPY); + addRequirements(OMPX_REQ_AUTO_ZERO_COPY); + DeviceOffsets[&RTL] = DeviceOffset; + DeviceUsed[&RTL] = NumberOfUserDevices; DP("Plugin adaptor " DPxMOD " has index %d, exposes %d out of %d devices!\n", - DPxPTR(LibraryHandler.get()), DeviceOffset, NumberOfUserDevices, - NumberOfPluginDevices); + DPxPTR(RTL.LibraryHandler.get()), DeviceOffset, NumberOfUserDevices, + RTL.number_of_devices()); } void PluginManager::initAllPlugins() { for (auto &R : PluginAdaptors) - R->initDevices(*this); + initDevices(*R); } static void registerImageIntoTranslationTable(TranslationTable &TT, - PluginAdaptorTy &RTL, + int32_t DeviceOffset, + int32_t NumberOfUserDevices, __tgt_device_image *Image) { // same size, as when we increase one, we also increase the other. @@ -175,8 +179,7 @@ static void registerImageIntoTranslationTable(TranslationTable &TT, // Resize the Targets Table and Images to accommodate the new targets if // required - unsigned TargetsTableMinimumSize = - RTL.DeviceOffset + RTL.getNumberOfUserDevices(); + unsigned TargetsTableMinimumSize = DeviceOffset + NumberOfUserDevices; if (TT.TargetsTable.size() < TargetsTableMinimumSize) { TT.DeviceTables.resize(TargetsTableMinimumSize, {}); @@ -186,11 +189,11 @@ static void registerImageIntoTranslationTable(TranslationTable &TT, } // Register the image in all devices for this target type. - for (int32_t I = 0; I < RTL.getNumberOfUserDevices(); ++I) { + for (int32_t I = 0; I < NumberOfUserDevices; ++I) { // If we are changing the image we are also invalidating the target table. - if (TT.TargetsImages[RTL.DeviceOffset + I] != Image) { - TT.TargetsImages[RTL.DeviceOffset + I] = Image; - TT.TargetsTable[RTL.DeviceOffset + I] = + if (TT.TargetsImages[DeviceOffset + I] != Image) { + TT.TargetsImages[DeviceOffset + I] = Image; + TT.TargetsTable[DeviceOffset + I] = 0; // lazy initialization of target table. } } @@ -228,7 +231,7 @@ void PluginManager::registerLib(__tgt_bin_desc *Desc) { DP("Image " DPxMOD " is compatible with RTL %s!\n", DPxPTR(Img->ImageStart), R.Name.c_str()); - R.initDevices(*this); + PM->initDevices(R); // Initialize (if necessary) translation table for this library. PM->TrlTblMtx.lock(); @@ -246,8 +249,10 @@ void PluginManager::registerLib(__tgt_bin_desc *Desc) { DP("Registering image " DPxMOD " with RTL %s!\n", DPxPTR(Img->ImageStart), R.Name.c_str()); - registerImageIntoTranslationTable(TransTable, R, Img); - R.UsedImages.insert(Img); + + registerImageIntoTranslationTable(TransTable, PM->DeviceOffsets[&R], + PM->DeviceUsed[&R], Img); + PM->UsedImages.insert(Img); PM->TrlTblMtx.unlock(); FoundRTL = &R; @@ -283,11 +288,11 @@ void PluginManager::unregisterLib(__tgt_bin_desc *Desc) { // Scan the RTLs that have associated images until we find one that supports // the current image. We only need to scan RTLs that are already being used. for (auto &R : PM->pluginAdaptors()) { - if (!R.isUsed()) + if (!DeviceOffsets.contains(&R)) continue; // Ensure that we do not use any unused images associated with this RTL. - if (!R.UsedImages.contains(Img)) + if (!UsedImages.contains(Img)) continue; FoundRTL = &R; diff --git a/openmp/libomptarget/src/device.cpp b/openmp/libomptarget/src/device.cpp index 3345277d91d3a9187809b41ab5472e115fe1d174..44a2facc8d3ddd514ad9c9dbad57b9f2302d7296 100644 --- a/openmp/libomptarget/src/device.cpp +++ b/openmp/libomptarget/src/device.cpp @@ -79,8 +79,7 @@ DeviceTy::~DeviceTy() { llvm::Error DeviceTy::init() { // Make call to init_requires if it exists for this plugin. int32_t Ret = 0; - if (RTL->init_requires) - Ret = RTL->init_requires(PM->getRequirements()); + Ret = RTL->init_requires(PM->getRequirements()); if (Ret != OFFLOAD_SUCCESS) return llvm::createStringError( llvm::inconvertibleErrorCode(), @@ -154,8 +153,6 @@ int32_t DeviceTy::submitData(void *TgtPtrBegin, void *HstPtrBegin, int64_t Size, omp_get_initial_device(), HstPtrBegin, DeviceID, TgtPtrBegin, Size, /*CodePtr=*/OMPT_GET_RETURN_ADDRESS);) - if (!AsyncInfo || !RTL->data_submit_async || !RTL->synchronize) - return RTL->data_submit(RTLDeviceID, TgtPtrBegin, HstPtrBegin, Size); return RTL->data_submit_async(RTLDeviceID, TgtPtrBegin, HstPtrBegin, Size, AsyncInfo); } @@ -176,8 +173,6 @@ int32_t DeviceTy::retrieveData(void *HstPtrBegin, void *TgtPtrBegin, DeviceID, TgtPtrBegin, omp_get_initial_device(), HstPtrBegin, Size, /*CodePtr=*/OMPT_GET_RETURN_ADDRESS);) - if (!RTL->data_retrieve_async || !RTL->synchronize) - return RTL->data_retrieve(RTLDeviceID, HstPtrBegin, TgtPtrBegin, Size); return RTL->data_retrieve_async(RTLDeviceID, HstPtrBegin, TgtPtrBegin, Size, AsyncInfo); } @@ -196,7 +191,7 @@ int32_t DeviceTy::dataExchange(void *SrcPtr, DeviceTy &DstDev, void *DstPtr, RegionInterface.getCallbacks<ompt_target_data_transfer_from_device>(), RTLDeviceID, SrcPtr, DstDev.RTLDeviceID, DstPtr, Size, /*CodePtr=*/OMPT_GET_RETURN_ADDRESS);) - if (!AsyncInfo || !RTL->data_exchange_async || !RTL->synchronize) { + if (!AsyncInfo) { assert(RTL->data_exchange && "RTL->data_exchange is nullptr"); return RTL->data_exchange(RTLDeviceID, SrcPtr, DstDev.RTLDeviceID, DstPtr, Size); @@ -206,9 +201,6 @@ int32_t DeviceTy::dataExchange(void *SrcPtr, DeviceTy &DstDev, void *DstPtr, } int32_t DeviceTy::notifyDataMapped(void *HstPtr, int64_t Size) { - if (!RTL->data_notify_mapped) - return OFFLOAD_SUCCESS; - DP("Notifying about new mapping: HstPtr=" DPxMOD ", Size=%" PRId64 "\n", DPxPTR(HstPtr), Size); @@ -220,9 +212,6 @@ int32_t DeviceTy::notifyDataMapped(void *HstPtr, int64_t Size) { } int32_t DeviceTy::notifyDataUnmapped(void *HstPtr) { - if (!RTL->data_notify_unmapped) - return OFFLOAD_SUCCESS; - DP("Notifying about an unmapping: HstPtr=" DPxMOD "\n", DPxPTR(HstPtr)); if (RTL->data_notify_unmapped(RTLDeviceID, HstPtr)) { @@ -242,70 +231,46 @@ int32_t DeviceTy::launchKernel(void *TgtEntryPtr, void **TgtVarsPtr, // Run region on device bool DeviceTy::printDeviceInfo() { - if (!RTL->print_device_info) - return false; RTL->print_device_info(RTLDeviceID); return true; } // Whether data can be copied to DstDevice directly bool DeviceTy::isDataExchangable(const DeviceTy &DstDevice) { - if (RTL != DstDevice.RTL || !RTL->is_data_exchangable) + if (RTL != DstDevice.RTL) return false; if (RTL->is_data_exchangable(RTLDeviceID, DstDevice.RTLDeviceID)) - return (RTL->data_exchange != nullptr) || - (RTL->data_exchange_async != nullptr); - + return true; return false; } int32_t DeviceTy::synchronize(AsyncInfoTy &AsyncInfo) { - if (RTL->synchronize) - return RTL->synchronize(RTLDeviceID, AsyncInfo); - return OFFLOAD_SUCCESS; + return RTL->synchronize(RTLDeviceID, AsyncInfo); } int32_t DeviceTy::queryAsync(AsyncInfoTy &AsyncInfo) { - if (RTL->query_async) - return RTL->query_async(RTLDeviceID, AsyncInfo); - - return synchronize(AsyncInfo); + return RTL->query_async(RTLDeviceID, AsyncInfo); } int32_t DeviceTy::createEvent(void **Event) { - if (RTL->create_event) - return RTL->create_event(RTLDeviceID, Event); - - return OFFLOAD_SUCCESS; + return RTL->create_event(RTLDeviceID, Event); } int32_t DeviceTy::recordEvent(void *Event, AsyncInfoTy &AsyncInfo) { - if (RTL->record_event) - return RTL->record_event(RTLDeviceID, Event, AsyncInfo); - - return OFFLOAD_SUCCESS; + return RTL->record_event(RTLDeviceID, Event, AsyncInfo); } int32_t DeviceTy::waitEvent(void *Event, AsyncInfoTy &AsyncInfo) { - if (RTL->wait_event) - return RTL->wait_event(RTLDeviceID, Event, AsyncInfo); - - return OFFLOAD_SUCCESS; + return RTL->wait_event(RTLDeviceID, Event, AsyncInfo); } int32_t DeviceTy::syncEvent(void *Event) { - if (RTL->sync_event) - return RTL->sync_event(RTLDeviceID, Event); - - return OFFLOAD_SUCCESS; + return RTL->sync_event(RTLDeviceID, Event); } int32_t DeviceTy::destroyEvent(void *Event) { - if (RTL->create_event) - return RTL->destroy_event(RTLDeviceID, Event); - - return OFFLOAD_SUCCESS; + return RTL->destroy_event(RTLDeviceID, Event); } void DeviceTy::dumpOffloadEntries() { @@ -321,7 +286,5 @@ void DeviceTy::dumpOffloadEntries() { } bool DeviceTy::useAutoZeroCopy() { - if (RTL->use_auto_zero_copy) - return RTL->use_auto_zero_copy(RTLDeviceID); - return false; + return RTL->use_auto_zero_copy(RTLDeviceID); } diff --git a/openmp/libomptarget/src/exports b/openmp/libomptarget/src/exports index d5432a9eed380d1c73fef179ecd86bd7d620879f..f95544ec8329c82f8f3e9dea0141a7af597784e3 100644 --- a/openmp/libomptarget/src/exports +++ b/openmp/libomptarget/src/exports @@ -35,6 +35,7 @@ VERS1.0 { __tgt_push_mapper_component; __kmpc_push_target_tripcount; __kmpc_push_target_tripcount_mapper; + ompx_dump_mapping_tables; omp_get_mapped_ptr; omp_get_num_devices; omp_get_device_num; diff --git a/openmp/libomptarget/src/interface.cpp b/openmp/libomptarget/src/interface.cpp index 8b89bc3ff7124dea236c7ec641ee6131f6b7960c..b562ba8818c39b5c2b318c49c215691b30d3cb8e 100644 --- a/openmp/libomptarget/src/interface.cpp +++ b/openmp/libomptarget/src/interface.cpp @@ -21,6 +21,8 @@ #include "Utils/ExponentialBackoff.h" +#include "llvm/Frontend/OpenMP/OMPConstants.h" + #include <cassert> #include <cstdint> #include <cstdio> @@ -218,11 +220,19 @@ EXTERN void __tgt_target_data_update_nowait_mapper( static KernelArgsTy *upgradeKernelArgs(KernelArgsTy *KernelArgs, KernelArgsTy &LocalKernelArgs, int32_t NumTeams, int32_t ThreadLimit) { - if (KernelArgs->Version > 2) + if (KernelArgs->Version > OMP_KERNEL_ARG_VERSION) DP("Unexpected ABI version: %u\n", KernelArgs->Version); - if (KernelArgs->Version == 1) { - LocalKernelArgs.Version = 2; + uint32_t UpgradedVersion = KernelArgs->Version; + if (KernelArgs->Version < OMP_KERNEL_ARG_VERSION) { + // The upgraded version will be based on the kernel launch environment. + if (KernelArgs->Version < OMP_KERNEL_ARG_MIN_VERSION_WITH_DYN_PTR) + UpgradedVersion = OMP_KERNEL_ARG_MIN_VERSION_WITH_DYN_PTR - 1; + else + UpgradedVersion = OMP_KERNEL_ARG_VERSION; + } + if (UpgradedVersion != KernelArgs->Version) { + LocalKernelArgs.Version = UpgradedVersion; LocalKernelArgs.NumArgs = KernelArgs->NumArgs; LocalKernelArgs.ArgBasePtrs = KernelArgs->ArgBasePtrs; LocalKernelArgs.ArgPtrs = KernelArgs->ArgPtrs; @@ -446,10 +456,8 @@ EXTERN void __tgt_set_info_flag(uint32_t NewInfoLevel) { assert(PM && "Runtime not initialized"); std::atomic<uint32_t> &InfoLevel = getInfoLevelInternal(); InfoLevel.store(NewInfoLevel); - for (auto &R : PM->pluginAdaptors()) { - if (R.set_info_flag) - R.set_info_flag(NewInfoLevel); - } + for (auto &R : PM->pluginAdaptors()) + R.set_info_flag(NewInfoLevel); } EXTERN int __tgt_print_device_info(int64_t DeviceId) { diff --git a/openmp/libomptarget/src/omptarget.cpp b/openmp/libomptarget/src/omptarget.cpp index 3b3e17f0f311e8cd64a6facd17189ea86b921b3a..803e941fe838220409890556d0173a202fad6720 100644 --- a/openmp/libomptarget/src/omptarget.cpp +++ b/openmp/libomptarget/src/omptarget.cpp @@ -30,6 +30,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/bit.h" +#include "llvm/Frontend/OpenMP/OMPConstants.h" #include "llvm/Object/ObjectFile.h" #include <cassert> @@ -480,12 +481,10 @@ void *targetLockExplicit(void *HostPtr, size_t Size, int DeviceNum, FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str()); int32_t Err = 0; - if (!DeviceOrErr->RTL->data_lock) { - Err = DeviceOrErr->RTL->data_lock(DeviceNum, HostPtr, Size, &RC); - if (Err) { - DP("Could not lock ptr %p\n", HostPtr); - return nullptr; - } + Err = DeviceOrErr->RTL->data_lock(DeviceNum, HostPtr, Size, &RC); + if (Err) { + DP("Could not lock ptr %p\n", HostPtr); + return nullptr; } DP("%s returns device ptr " DPxMOD "\n", Name, DPxPTR(RC)); return RC; @@ -498,9 +497,7 @@ void targetUnlockExplicit(void *HostPtr, int DeviceNum, const char *Name) { if (!DeviceOrErr) FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str()); - if (!DeviceOrErr->RTL->data_unlock) - DeviceOrErr->RTL->data_unlock(DeviceNum, HostPtr); - + DeviceOrErr->RTL->data_unlock(DeviceNum, HostPtr); DP("%s returns\n", Name); } @@ -1752,7 +1749,7 @@ int target_replay(ident_t *Loc, DeviceTy &Device, void *HostPtr, Device.submitData(TgtPtr, DeviceMemory, DeviceMemorySize, AsyncInfo); KernelArgsTy KernelArgs = {0}; - KernelArgs.Version = 2; + KernelArgs.Version = OMP_KERNEL_ARG_VERSION; KernelArgs.NumArgs = NumArgs; KernelArgs.Tripcount = LoopTripCount; KernelArgs.NumTeams[0] = NumTeams; diff --git a/openmp/libomptarget/test/api/omp_dynamic_shared_memory.c b/openmp/libomptarget/test/api/omp_dynamic_shared_memory.c index 5095a69a375c94743a91f1bc81a744971e5eb10f..3fe75f24db3e675852f887d3695934ffe3a5a570 100644 --- a/openmp/libomptarget/test/api/omp_dynamic_shared_memory.c +++ b/openmp/libomptarget/test/api/omp_dynamic_shared_memory.c @@ -10,6 +10,8 @@ // UNSUPPORTED: x86_64-pc-linux-gnu-LTO // UNSUPPORTED: aarch64-unknown-linux-gnu // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO #include <omp.h> #include <stdio.h> diff --git a/openmp/libomptarget/test/api/ompx_dump_mapping_tables.cpp b/openmp/libomptarget/test/api/ompx_dump_mapping_tables.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c170c2d7387338b57b82ae0d1948b749eee8d460 --- /dev/null +++ b/openmp/libomptarget/test/api/ompx_dump_mapping_tables.cpp @@ -0,0 +1,35 @@ +// RUN: %libomptarget-compilexx-run-and-check-generic + +#include <cstdio> +#include <omp.h> + +#define N 10 + +int main() { + int *a = new __int32_t[N]; // mapped and released from device 0 + int *b = new __int32_t[2 * N]; // mapped to device 0 + + // clang-format off + // CHECK: Mapping tables after target enter data: + // CHECK-NEXT: omptarget device 0 info: OpenMP Host-Device pointer mappings after block + // CHECK-NEXT: omptarget device 0 info: Host Ptr Target Ptr Size (B) DynRefCount HoldRefCount Declaration + // CHECK-NEXT: omptarget device 0 info: {{(0x[0-9a-f]{16})}} {{(0x[0-9a-f]{16})}} {{[48]}}0 + // CHECK-NEXT: omptarget device 0 info: {{(0x[0-9a-f]{16})}} {{(0x[0-9a-f]{16})}} {{[48]}}0 +#pragma omp target enter data device(0) map(to : a[ : N]) +#pragma omp target enter data device(0) map(to : b[ : 2*N]) + // clang-format on + printf("Mapping tables after target enter data:\n"); + ompx_dump_mapping_tables(); + + // clang-format off + // CHECK: Mapping tables after target exit data for a: + // CHECK-NEXT: omptarget device 0 info: OpenMP Host-Device pointer mappings after block + // CHECK-NEXT: omptarget device 0 info: Host Ptr Target Ptr Size (B) DynRefCount HoldRefCount Declaration + // CHECK-NEXT: omptarget device 0 info: {{(0x[0-9a-f]{16})}} {{(0x[0-9a-f]{16})}} 80 +#pragma omp target exit data device(0) map(release : a[ : N]) + // clang-format on + printf("\nMapping tables after target exit data for a:\n"); + ompx_dump_mapping_tables(); + + return 0; +} diff --git a/openmp/libomptarget/test/jit/empty_kernel_lvl1.c b/openmp/libomptarget/test/jit/empty_kernel_lvl1.c index c908c8ba06509e76e01b2606e73be54a6f955040..a0b8cd448837da6769e68b9dad45febe26efb0e5 100644 --- a/openmp/libomptarget/test/jit/empty_kernel_lvl1.c +++ b/openmp/libomptarget/test/jit/empty_kernel_lvl1.c @@ -32,5 +32,7 @@ // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO #include "empty_kernel.inc" diff --git a/openmp/libomptarget/test/jit/empty_kernel_lvl2.c b/openmp/libomptarget/test/jit/empty_kernel_lvl2.c index 0b88d33292c571e858b062e30939764cf1a0abc0..81a04f55ce43d6ae79ca10cd85e580c767529c2a 100644 --- a/openmp/libomptarget/test/jit/empty_kernel_lvl2.c +++ b/openmp/libomptarget/test/jit/empty_kernel_lvl2.c @@ -92,5 +92,7 @@ // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO #include "empty_kernel.inc" diff --git a/openmp/libomptarget/test/jit/type_punning.c b/openmp/libomptarget/test/jit/type_punning.c index 23aa69bba7b952779618c0d59c38f48b40154aed..10e3d2cef718b8583ab930227de885bb5a6bbc9b 100644 --- a/openmp/libomptarget/test/jit/type_punning.c +++ b/openmp/libomptarget/test/jit/type_punning.c @@ -12,6 +12,8 @@ // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO // Ensure that there is only the kernel function left, not any outlined // parallel regions. diff --git a/openmp/libomptarget/test/mapping/auto_zero_copy.cpp b/openmp/libomptarget/test/mapping/auto_zero_copy.cpp index 6f9d8c2b128c944bfd7b752864bd4452ae417742..46641200bb56e28be63ffc43e2899cfa40c2bb24 100644 --- a/openmp/libomptarget/test/mapping/auto_zero_copy.cpp +++ b/openmp/libomptarget/test/mapping/auto_zero_copy.cpp @@ -13,6 +13,8 @@ // UNSUPPORTED: nvptx64-nvidia-cuda-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO // REQUIRES: unified_shared_memory diff --git a/openmp/libomptarget/test/mapping/auto_zero_copy_globals.cpp b/openmp/libomptarget/test/mapping/auto_zero_copy_globals.cpp index 4a13d270aeebe59b320d6adcf9b7e94aee86428c..55dfb2807ebc78119acaaae154ff10ea440f3810 100644 --- a/openmp/libomptarget/test/mapping/auto_zero_copy_globals.cpp +++ b/openmp/libomptarget/test/mapping/auto_zero_copy_globals.cpp @@ -9,6 +9,8 @@ // UNSUPPORTED: nvptx64-nvidia-cuda-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO // REQUIRES: unified_shared_memory diff --git a/openmp/libomptarget/test/offloading/barrier_fence.c b/openmp/libomptarget/test/offloading/barrier_fence.c index 5d1096478ed9e965c763b0ef99917122162fc0c2..b9a8ca27965a0945196b731c67dd5241b413a0e8 100644 --- a/openmp/libomptarget/test/offloading/barrier_fence.c +++ b/openmp/libomptarget/test/offloading/barrier_fence.c @@ -7,6 +7,8 @@ // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO #include <omp.h> #include <stdio.h> diff --git a/openmp/libomptarget/test/offloading/bug49334.cpp b/openmp/libomptarget/test/offloading/bug49334.cpp index a22d3fe9f665359a5ac9d5a42207bfa434366e71..1f19dab378810d8eefd0a15bd9a0569aede82a24 100644 --- a/openmp/libomptarget/test/offloading/bug49334.cpp +++ b/openmp/libomptarget/test/offloading/bug49334.cpp @@ -9,6 +9,8 @@ // UNSUPPORTED: x86_64-pc-linux-gnu-LTO // UNSUPPORTED: aarch64-unknown-linux-gnu // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO // UNSUPPORTED: amdgcn-amd-amdhsa // UNSUPPORTED: nvptx64-nvidia-cuda // UNSUPPORTED: nvptx64-nvidia-cuda-LTO diff --git a/openmp/libomptarget/test/offloading/d2d_memcpy_sync.c b/openmp/libomptarget/test/offloading/d2d_memcpy_sync.c new file mode 100644 index 0000000000000000000000000000000000000000..6b9b765a74d82313d2080edf0b3e91e357d20bec --- /dev/null +++ b/openmp/libomptarget/test/offloading/d2d_memcpy_sync.c @@ -0,0 +1,72 @@ +// RUN: %libomptarget-compile-generic && \ +// RUN: env LIBOMPTARGET_AMDGPU_MAX_ASYNC_COPY_BYTES=0 %libomptarget-run-generic | \ +// RUN: %fcheck-generic -allow-empty +// REQUIRES: amdgcn-amd-amdhsa + +#include <assert.h> +#include <omp.h> +#include <stdio.h> +#include <stdlib.h> + +const int magic_num = 7; + +int main(int argc, char *argv[]) { + const int N = 128; + const int num_devices = omp_get_num_devices(); + + // No target device, just return + if (num_devices == 0) { + printf("PASS\n"); + return 0; + } + + const int src_device = 0; + int dst_device = num_devices - 1; + + int length = N * sizeof(int); + int *src_ptr = omp_target_alloc(length, src_device); + int *dst_ptr = omp_target_alloc(length, dst_device); + + if (!src_ptr || !dst_ptr) { + printf("FAIL\n"); + return 1; + } + +#pragma omp target teams distribute parallel for device(src_device) \ + is_device_ptr(src_ptr) + for (int i = 0; i < N; ++i) { + src_ptr[i] = magic_num; + } + + if (omp_target_memcpy(dst_ptr, src_ptr, length, 0, 0, dst_device, + src_device)) { + printf("FAIL\n"); + return 1; + } + + int *buffer = malloc(length); + if (!buffer) { + printf("FAIL\n"); + return 1; + } + +#pragma omp target teams distribute parallel for device(dst_device) \ + map(from : buffer[0 : N]) is_device_ptr(dst_ptr) + for (int i = 0; i < N; ++i) { + buffer[i] = dst_ptr[i] + magic_num; + } + + for (int i = 0; i < N; ++i) + assert(buffer[i] == 2 * magic_num); + + printf("PASS\n"); + + // Free host and device memory + free(buffer); + omp_target_free(src_ptr, src_device); + omp_target_free(dst_ptr, dst_device); + + return 0; +} + +// CHECK: PASS diff --git a/openmp/libomptarget/test/offloading/default_thread_limit.c b/openmp/libomptarget/test/offloading/default_thread_limit.c index d32e7df418cbbd041504d579ecbd595c97bee060..4da02bbb152e604020a5c695314c32234ed26882 100644 --- a/openmp/libomptarget/test/offloading/default_thread_limit.c +++ b/openmp/libomptarget/test/offloading/default_thread_limit.c @@ -9,6 +9,8 @@ // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO __attribute__((optnone)) int optnone() { return 1; } diff --git a/openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-array-2.f90 b/openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-array-2.f90 new file mode 100644 index 0000000000000000000000000000000000000000..489c2532a7624c367fe0e7e834f335757f9ce750 --- /dev/null +++ b/openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-array-2.f90 @@ -0,0 +1,39 @@ +! Offloading test checking interaction of an +! enter and exit map of an array of scalars +! REQUIRES: flang, amdgcn-amd-amdhsa +! UNSUPPORTED: nvptx64-nvidia-cuda +! UNSUPPORTED: nvptx64-nvidia-cuda-LTO +! UNSUPPORTED: aarch64-unknown-linux-gnu +! UNSUPPORTED: aarch64-unknown-linux-gnu-LTO +! UNSUPPORTED: x86_64-pc-linux-gnu +! UNSUPPORTED: x86_64-pc-linux-gnu-LTO + +! RUN: %libomptarget-compile-fortran-run-and-check-generic +program main + integer :: array(10) + + do I = 1, 10 + array(I) = I + I + end do + + !$omp target enter data map(to: array) + + ! Shouldn't overwrite data already locked in + ! on target via enter, this will then be + ! overwritten by our exit + do I = 1, 10 + array(I) = 10 + end do + + !$omp target + do i=1,10 + array(i) = array(i) + i + end do + !$omp end target + + !$omp target exit data map(from: array) + + print*, array +end program + +!CHECK: 3 6 9 12 15 18 21 24 27 30 diff --git a/openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-array-bounds.f90 b/openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-array-bounds.f90 new file mode 100644 index 0000000000000000000000000000000000000000..3c8c3507ed728a48e13c113575055a88c11ac930 --- /dev/null +++ b/openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-array-bounds.f90 @@ -0,0 +1,44 @@ +! Offloading test checking interaction of an +! enter and exit map of an array of scalars +! with specified bounds +! REQUIRES: flang, amdgcn-amd-amdhsa +! UNSUPPORTED: nvptx64-nvidia-cuda +! UNSUPPORTED: nvptx64-nvidia-cuda-LTO +! UNSUPPORTED: aarch64-unknown-linux-gnu +! UNSUPPORTED: aarch64-unknown-linux-gnu-LTO +! UNSUPPORTED: x86_64-pc-linux-gnu +! UNSUPPORTED: x86_64-pc-linux-gnu-LTO + +! RUN: %libomptarget-compile-fortran-run-and-check-generic + +program main + integer :: array(10) + + do I = 1, 10 + array(I) = I + I + end do + + !$omp target enter data map(to: array(3:6)) + + ! Shouldn't overwrite data already locked in + ! on target via enter, which will then be + ! overwritten by our exit + do I = 1, 10 + array(I) = 10 + end do + + ! The compiler/runtime is less lenient about read/write out of + ! bounds when using enter and exit, we have to specifically loop + ! over the correctly mapped range + !$omp target + do i=3,6 + array(i) = array(i) + i + end do + !$omp end target + + !$omp target exit data map(from: array(3:6)) + + print *, array +end program + +!CHECK: 10 10 9 12 15 18 10 10 10 10 diff --git a/openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-scalar.f90 b/openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-scalar.f90 new file mode 100644 index 0000000000000000000000000000000000000000..29a0b5ee3e62c131d9c46480d5f58745d7645571 --- /dev/null +++ b/openmp/libomptarget/test/offloading/fortran/target-map-enter-exit-scalar.f90 @@ -0,0 +1,33 @@ +! Offloading test checking interaction of an +! enter and exit map of an scalar +! REQUIRES: flang, amdgcn-amd-amdhsa +! UNSUPPORTED: nvptx64-nvidia-cuda +! UNSUPPORTED: nvptx64-nvidia-cuda-LTO +! UNSUPPORTED: aarch64-unknown-linux-gnu +! UNSUPPORTED: aarch64-unknown-linux-gnu-LTO +! UNSUPPORTED: x86_64-pc-linux-gnu +! UNSUPPORTED: x86_64-pc-linux-gnu-LTO + +! RUN: %libomptarget-compile-fortran-run-and-check-generic +program main + integer :: scalar + scalar = 10 + + !$omp target enter data map(to: scalar) + + !ignored, as we've already attached + scalar = 20 + + !$omp target + scalar = scalar + 50 + !$omp end target + + !$omp target exit data map(from: scalar) + + ! not the answer one may expect, but it is the same + ! answer Clang gives so we are correctly on par with + ! Clang for the moment. + print *, scalar +end program + +!CHECK: 10 diff --git a/openmp/libomptarget/test/offloading/fortran/target-nested-target-data.f90 b/openmp/libomptarget/test/offloading/fortran/target-nested-target-data.f90 new file mode 100644 index 0000000000000000000000000000000000000000..a694f2464546c5e0b0b960e9fd67d0e66d8eaa5c --- /dev/null +++ b/openmp/libomptarget/test/offloading/fortran/target-nested-target-data.f90 @@ -0,0 +1,31 @@ +! Offloading test for target nested inside +! a target data region +! REQUIRES: flang +! UNSUPPORTED: nvptx64-nvidia-cuda-LTO +! UNSUPPORTED: aarch64-unknown-linux-gnu +! UNSUPPORTED: aarch64-unknown-linux-gnu-LTO +! UNSUPPORTED: x86_64-pc-linux-gnu +! UNSUPPORTED: x86_64-pc-linux-gnu-LTO + +! RUN: %libomptarget-compile-fortran-run-and-check-generic +program main + integer :: A(10), B(10), C(10) + + do I = 1, 10 + A(I) = 1 + B(I) = 2 + end do + !$omp target data map(to: A, B) map(alloc: C) + !$omp target map(from: C) + do I = 1, 10 + C(I) = A(I) + B(I) ! assigns 3, A:1 + B:2 + end do + !$omp end target + !$omp target update from(C) ! updates C device -> host + !$omp end target data + + print *, C ! should be all 3's + +end program + +! CHECK: 3 3 3 3 3 3 3 3 3 3 diff --git a/openmp/libomptarget/test/offloading/ompx_bare.c b/openmp/libomptarget/test/offloading/ompx_bare.c index fb3810bd1df1262a5145a1409ad74c86f21025d1..3dabdcd15e0d8d8eb9dea74542665de8fb806e3f 100644 --- a/openmp/libomptarget/test/offloading/ompx_bare.c +++ b/openmp/libomptarget/test/offloading/ompx_bare.c @@ -1,10 +1,13 @@ // RUN: %libomptarget-compile-generic -// RUN: env LIBOMPTARGET_INFO=63 %libomptarget-run-generic 2>&1 | %fcheck-generic +// RUN: env LIBOMPTARGET_INFO=63 %libomptarget-run-generic 2>&1 | \ +// RUN: %fcheck-generic // // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO // UNSUPPORTED: aarch64-unknown-linux-gnu // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO #include <assert.h> #include <ompx.h> diff --git a/openmp/libomptarget/test/offloading/ompx_coords.c b/openmp/libomptarget/test/offloading/ompx_coords.c index 61dad61f46405e369289be09594e480d2b8e78cb..5e4e14b4c6daeb75462b4cd5fe30f86bec334b26 100644 --- a/openmp/libomptarget/test/offloading/ompx_coords.c +++ b/openmp/libomptarget/test/offloading/ompx_coords.c @@ -4,6 +4,8 @@ // UNSUPPORTED: x86_64-pc-linux-gnu-LTO // UNSUPPORTED: aarch64-unknown-linux-gnu // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO #include <omp.h> #include <ompx.h> diff --git a/openmp/libomptarget/test/offloading/ompx_saxpy_mixed.c b/openmp/libomptarget/test/offloading/ompx_saxpy_mixed.c index 440b694e3ac706d110ed0467ab00bf58264cebff..f479be8a484fc96a30926f45bfa3c12091fd3e33 100644 --- a/openmp/libomptarget/test/offloading/ompx_saxpy_mixed.c +++ b/openmp/libomptarget/test/offloading/ompx_saxpy_mixed.c @@ -4,6 +4,8 @@ // UNSUPPORTED: x86_64-pc-linux-gnu-LTO // UNSUPPORTED: aarch64-unknown-linux-gnu // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO #include <math.h> #include <omp.h> diff --git a/openmp/libomptarget/test/offloading/parallel_target_teams_reduction.cpp b/openmp/libomptarget/test/offloading/parallel_target_teams_reduction.cpp index 5303a9463f155161aeb232c35492583353a47d4c..10e1b33f1ce4052691c502f3ef7e45fabd8c8a16 100644 --- a/openmp/libomptarget/test/offloading/parallel_target_teams_reduction.cpp +++ b/openmp/libomptarget/test/offloading/parallel_target_teams_reduction.cpp @@ -6,6 +6,8 @@ // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO #include <iostream> #include <vector> diff --git a/openmp/libomptarget/test/offloading/small_trip_count.c b/openmp/libomptarget/test/offloading/small_trip_count.c index d8bef667607a1cd0764dc20fc6e7425219e53e92..65f094f15746941ccbce0135c98d4c3bd826739c 100644 --- a/openmp/libomptarget/test/offloading/small_trip_count.c +++ b/openmp/libomptarget/test/offloading/small_trip_count.c @@ -9,6 +9,8 @@ // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO #define N 128 diff --git a/openmp/libomptarget/test/offloading/small_trip_count_thread_limit.cpp b/openmp/libomptarget/test/offloading/small_trip_count_thread_limit.cpp index 9796c2dc11663bc8463e6e94136ba53fec6eaffc..b7ae52a62c83bba3804329e09e820e2a8e21eb36 100644 --- a/openmp/libomptarget/test/offloading/small_trip_count_thread_limit.cpp +++ b/openmp/libomptarget/test/offloading/small_trip_count_thread_limit.cpp @@ -7,6 +7,8 @@ // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO int main(int argc, char *argv[]) { constexpr const int block_size = 256; diff --git a/openmp/libomptarget/test/offloading/spmdization.c b/openmp/libomptarget/test/offloading/spmdization.c index 2cf30ff593b991eedb1c9b116970806399da69ff..77913bec8342f95b42b2005f4e1fbea1612e5794 100644 --- a/openmp/libomptarget/test/offloading/spmdization.c +++ b/openmp/libomptarget/test/offloading/spmdization.c @@ -11,6 +11,8 @@ // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO #include <omp.h> #include <stdio.h> diff --git a/openmp/libomptarget/test/offloading/target_critical_region.cpp b/openmp/libomptarget/test/offloading/target_critical_region.cpp index 9a741bef6c591598782e0e896a18c506d0753e76..495632bf76e175072fc89084de5838078b7d4769 100644 --- a/openmp/libomptarget/test/offloading/target_critical_region.cpp +++ b/openmp/libomptarget/test/offloading/target_critical_region.cpp @@ -6,6 +6,8 @@ // UNSUPPORTED: nvptx64-nvidia-cuda-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO // UNSUPPORTED: amdgcn-amd-amdhsa #include <omp.h> diff --git a/openmp/libomptarget/test/offloading/thread_limit.c b/openmp/libomptarget/test/offloading/thread_limit.c index 65275a8f279584a35243642612a8e4752ea2d374..a8cc51b651dc96ea4f1f7c9e48fcccfe5ba2ef9f 100644 --- a/openmp/libomptarget/test/offloading/thread_limit.c +++ b/openmp/libomptarget/test/offloading/thread_limit.c @@ -9,6 +9,8 @@ // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO int main() { int n = 1 << 20; diff --git a/openmp/libomptarget/test/offloading/workshare_chunk.c b/openmp/libomptarget/test/offloading/workshare_chunk.c new file mode 100644 index 0000000000000000000000000000000000000000..a8c60c0097791ae623973d334b9c80a2c4a7ce71 --- /dev/null +++ b/openmp/libomptarget/test/offloading/workshare_chunk.c @@ -0,0 +1,254 @@ +// RUN: %libomptarget-compile-run-and-check-generic +// RUN: %libomptarget-compileopt-run-and-check-generic + +// UNSUPPORTED: aarch64-unknown-linux-gnu +// UNSUPPORTED: aarch64-unknown-linux-gnu-LTO +// UNSUPPORTED: x86_64-pc-linux-gnu +// UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO + +// clang-format off + +#include <omp.h> +#include <stdio.h> + +#define N 100 +#define BLOCK_SHIFT 8 + +void print(int *A, int size) { + for (int i = 0; i < size; ++i) { + printf("B%dT%d ", A[i] >> BLOCK_SHIFT, A[i] % (1 << BLOCK_SHIFT)); + } + printf("\n"); +} + +int main() { + int A[N]; + +#pragma omp target parallel for map(from:A) num_threads(10) schedule(static, 2) + for (int i = 0; i < N; ++i) { + A[i] = (omp_get_team_num() << BLOCK_SHIFT) + omp_get_thread_num(); + } + printf("omp target parallel for thread chunk size %d\n", 2); + print(A, N); + +#pragma omp target teams distribute map(from:A) num_teams(10) \ + dist_schedule(static, 2) + for (int i = 0; i < N; ++i) { + A[i] = (omp_get_team_num() << BLOCK_SHIFT) + omp_get_thread_num(); + } + printf("omp target teams distribute block chunk size %d\n", 2); + print(A, N); + +#pragma omp target teams distribute parallel for map(from:A) \ + num_teams(10) dist_schedule(static, 2) + for (int i = 0; i < N; ++i) { + A[i] = (omp_get_team_num() << BLOCK_SHIFT) + omp_get_thread_num(); + } + printf("omp target teams distribute parallel for block chunk size %d ", 2); + printf("thread chunk size default\n"); + print(A, N); + +#pragma omp target teams distribute parallel for map(from:A) \ + num_teams(10) dist_schedule(static, 2) schedule(static, 3) + for (int i = 0; i < N; ++i) { + A[i] = (omp_get_team_num() << BLOCK_SHIFT) + omp_get_thread_num(); + } + printf("omp target teams distribute parallel for block chunk size %d ", 2); + printf("thread chunk size %d\n", 3); + print(A, N); + +#pragma omp target teams distribute parallel for map(from:A) \ + num_teams(10) dist_schedule(static, 3) schedule(static, 2) + for (int i = 0; i < N; ++i) { + A[i] = (omp_get_team_num() << BLOCK_SHIFT) + omp_get_thread_num(); + } + printf("omp target teams distribute parallel for block chunk size %d ", 3); + printf("thread chunk size %d\n", 2); + print(A, N); + +#pragma omp target teams distribute parallel for map(from:A) \ + num_teams(10) dist_schedule(static, 5) schedule(static, 2) + for (int i = 0; i < N; ++i) { + A[i] = (omp_get_team_num() << BLOCK_SHIFT) + omp_get_thread_num(); + } + printf("omp target teams distribute parallel for block chunk size %d ", 5); + printf("thread chunk size %d\n", 2); + print(A, N); + +#pragma omp target teams distribute parallel for map(from:A) num_teams(10) \ + dist_schedule(static, 49) schedule(static, 2) + for (int i = 0; i < N; ++i) { + A[i] = (omp_get_team_num() << BLOCK_SHIFT) + omp_get_thread_num(); + } + printf("omp target teams distribute parallel for block chunk size %d ", 49); + printf("thread chunk size %d\n", 2); + print(A, N); + +#pragma omp target teams distribute parallel for map(from:A) \ + num_teams(10) num_threads(10) dist_schedule(static, 29) + for (int i = 0; i < N; ++i) { + A[i] = (omp_get_team_num() << BLOCK_SHIFT) + omp_get_thread_num(); + } + printf("omp target teams distribute parallel for block chunk size %d ", 29); + printf("thread chunk size default\n"); + print(A, N); + +#pragma omp target teams distribute parallel for map(from:A) \ + num_teams(10) num_threads(10) dist_schedule(static, 101) + for (int i = 0; i < N; ++i) { + A[i] = (omp_get_team_num() << BLOCK_SHIFT) + omp_get_thread_num(); + } + printf("omp target teams distribute parallel for block chunk size %d ", 101); + printf("thread chunk size default\n"); + print(A, N); + +#pragma omp target teams distribute parallel for map(from:A) \ + num_teams(9) num_threads(10) schedule(static, 101) + for (int i = 0; i < N; ++i) { + A[i] = (omp_get_team_num() << BLOCK_SHIFT) + omp_get_thread_num(); + } + printf("omp target teams distribute parallel for default block chunk size "); + printf("thread chunk size %d\n", 101); + print(A, N); + return 0; +} +//CHECK: omp target parallel for thread chunk size 2 + +//CHECK-NEXT: B0T0 B0T0 B0T1 B0T1 B0T2 B0T2 B0T3 B0T3 B0T4 B0T4 +//CHECK-SAME: B0T5 B0T5 B0T6 B0T6 B0T7 B0T7 B0T8 B0T8 B0T9 B0T9 +//CHECK-SAME: B0T0 B0T0 B0T1 B0T1 B0T2 B0T2 B0T3 B0T3 B0T4 B0T4 +//CHECK-SAME: B0T5 B0T5 B0T6 B0T6 B0T7 B0T7 B0T8 B0T8 B0T9 B0T9 +//CHECK-SAME: B0T0 B0T0 B0T1 B0T1 B0T2 B0T2 B0T3 B0T3 B0T4 B0T4 +//CHECK-SAME: B0T5 B0T5 B0T6 B0T6 B0T7 B0T7 B0T8 B0T8 B0T9 B0T9 +//CHECK-SAME: B0T0 B0T0 B0T1 B0T1 B0T2 B0T2 B0T3 B0T3 B0T4 B0T4 +//CHECK-SAME: B0T5 B0T5 B0T6 B0T6 B0T7 B0T7 B0T8 B0T8 B0T9 B0T9 +//CHECK-SAME: B0T0 B0T0 B0T1 B0T1 B0T2 B0T2 B0T3 B0T3 B0T4 B0T4 +//CHECK-SAME: B0T5 B0T5 B0T6 B0T6 B0T7 B0T7 B0T8 B0T8 B0T9 B0T9 + +//CHECK: omp target teams distribute block chunk size 2 + +//CHECK-NEXT: B0T0 B0T0 B1T0 B1T0 B2T0 B2T0 B3T0 B3T0 B4T0 B4T0 +//CHECK-SAME: B5T0 B5T0 B6T0 B6T0 B7T0 B7T0 B8T0 B8T0 B9T0 B9T0 +//CHECK-SAME: B0T0 B0T0 B1T0 B1T0 B2T0 B2T0 B3T0 B3T0 B4T0 B4T0 +//CHECK-SAME: B5T0 B5T0 B6T0 B6T0 B7T0 B7T0 B8T0 B8T0 B9T0 B9T0 +//CHECK-SAME: B0T0 B0T0 B1T0 B1T0 B2T0 B2T0 B3T0 B3T0 B4T0 B4T0 +//CHECK-SAME: B5T0 B5T0 B6T0 B6T0 B7T0 B7T0 B8T0 B8T0 B9T0 B9T0 +//CHECK-SAME: B0T0 B0T0 B1T0 B1T0 B2T0 B2T0 B3T0 B3T0 B4T0 B4T0 +//CHECK-SAME: B5T0 B5T0 B6T0 B6T0 B7T0 B7T0 B8T0 B8T0 B9T0 B9T0 +//CHECK-SAME: B0T0 B0T0 B1T0 B1T0 B2T0 B2T0 B3T0 B3T0 B4T0 B4T0 +//CHECK-SAME: B5T0 B5T0 B6T0 B6T0 B7T0 B7T0 B8T0 B8T0 B9T0 B9T0 + +//CHECK: omp target teams distribute parallel for +//CHECK-SAME: block chunk size 2 thread chunk size default + +//CHECK-NEXT: B0T0 B0T1 B1T0 B1T1 B2T0 B2T1 B3T0 B3T1 B4T0 B4T1 +//CHECK-SAME: B5T0 B5T1 B6T0 B6T1 B7T0 B7T1 B8T0 B8T1 B9T0 B9T1 +//CHECK-SAME: B0T0 B0T1 B1T0 B1T1 B2T0 B2T1 B3T0 B3T1 B4T0 B4T1 +//CHECK-SAME: B5T0 B5T1 B6T0 B6T1 B7T0 B7T1 B8T0 B8T1 B9T0 B9T1 +//CHECK-SAME: B0T0 B0T1 B1T0 B1T1 B2T0 B2T1 B3T0 B3T1 B4T0 B4T1 +//CHECK-SAME: B5T0 B5T1 B6T0 B6T1 B7T0 B7T1 B8T0 B8T1 B9T0 B9T1 + +//CHECK: omp target teams distribute parallel for +//CHECK-SAME block chunk size 2 thread chunk size 3 + +//CHECK-NEXT: B0T0 B0T0 B1T0 B1T0 B2T0 B2T0 B3T0 B3T0 B4T0 B4T0 +//CHECK-SAME: B5T0 B5T0 B6T0 B6T0 B7T0 B7T0 B8T0 B8T0 B9T0 B9T0 +//CHECK-SAME: B0T0 B0T0 B1T0 B1T0 B2T0 B2T0 B3T0 B3T0 B4T0 B4T0 +//CHECK-SAME: B5T0 B5T0 B6T0 B6T0 B7T0 B7T0 B8T0 B8T0 B9T0 B9T0 +//CHECK-SAME: B0T0 B0T0 B1T0 B1T0 B2T0 B2T0 B3T0 B3T0 B4T0 B4T0 +//CHECK-SAME: B5T0 B5T0 B6T0 B6T0 B7T0 B7T0 B8T0 B8T0 B9T0 B9T0 +//CHECK-SAME: B0T0 B0T0 B1T0 B1T0 B2T0 B2T0 B3T0 B3T0 B4T0 B4T0 +//CHECK-SAME: B5T0 B5T0 B6T0 B6T0 B7T0 B7T0 B8T0 B8T0 B9T0 B9T0 +//CHECK-SAME: B0T0 B0T0 B1T0 B1T0 B2T0 B2T0 B3T0 B3T0 B4T0 B4T0 +//CHECK-SAME: B5T0 B5T0 B6T0 B6T0 B7T0 B7T0 B8T0 B8T0 B9T0 B9T0 + +//CHECK: omp target teams distribute parallel for +//CHECK-SAME: block chunk size 3 thread chunk size 2 + +//CHECK-NEXT: B0T0 B0T0 B0T1 B1T0 B1T0 B1T1 B2T0 B2T0 B2T1 +//CHECK-SAME: B3T0 B3T0 B3T1 B4T0 B4T0 B4T1 +//CHECK-SAME: B5T0 B5T0 B5T1 B6T0 B6T0 B6T1 B7T0 B7T0 B7T1 +//CHECK-SAME: B8T0 B8T0 B8T1 B9T0 B9T0 B9T1 +//CHECK-SAME: B0T0 B0T0 B0T1 B1T0 B1T0 B1T1 B2T0 B2T0 B2T1 +//CHECK-SAME: B3T0 B3T0 B3T1 B4T0 B4T0 B4T1 +//CHECK-SAME: B5T0 B5T0 B5T1 B6T0 B6T0 B6T1 B7T0 B7T0 B7T1 +//CHECK-SAME: B8T0 B8T0 B8T1 B9T0 B9T0 B9T1 +//CHECK-SAME: B0T0 B0T0 B0T1 B1T0 B1T0 B1T1 B2T0 B2T0 B2T1 +//CHECK-SAME: B3T0 B3T0 B3T1 B4T0 B4T0 B4T1 +//CHECK-SAME: B5T0 B5T0 B5T1 B6T0 B6T0 B6T1 B7T0 B7T0 B7T1 +//CHECK-SAME: B8T0 B8T0 B8T1 B9T0 B9T0 B9T1 +//CHECK-SAME: B0T0 B0T0 B0T1 B1T0 B1T0 B1T1 B2T0 B2T0 B2T1 B3T0 + +//CHECK: omp target teams distribute parallel for +//CHECK-SAME: block chunk size 5 thread chunk size 2 + +//CHECK-NEXT: B0T0 B0T0 B0T1 B0T1 B0T2 B1T0 B1T0 B1T1 B1T1 B1T2 +//CHECK-SAME: B2T0 B2T0 B2T1 B2T1 B2T2 B3T0 B3T0 B3T1 B3T1 B3T2 +//CHECK-SAME: B4T0 B4T0 B4T1 B4T1 B4T2 B5T0 B5T0 B5T1 B5T1 B5T2 +//CHECK-SAME: B6T0 B6T0 B6T1 B6T1 B6T2 B7T0 B7T0 B7T1 B7T1 B7T2 +//CHECK-SAME: B8T0 B8T0 B8T1 B8T1 B8T2 B9T0 B9T0 B9T1 B9T1 B9T2 +//CHECK-SAME: B0T0 B0T0 B0T1 B0T1 B0T2 B1T0 B1T0 B1T1 B1T1 B1T2 +//CHECK-SAME: B2T0 B2T0 B2T1 B2T1 B2T2 B3T0 B3T0 B3T1 B3T1 B3T2 +//CHECK-SAME: B4T0 B4T0 B4T1 B4T1 B4T2 B5T0 B5T0 B5T1 B5T1 B5T2 +//CHECK-SAME: B6T0 B6T0 B6T1 B6T1 B6T2 B7T0 B7T0 B7T1 B7T1 B7T2 +//CHECK-SAME: B8T0 B8T0 B8T1 B8T1 B8T2 B9T0 B9T0 B9T1 B9T1 B9T2 + +//CHECK: omp target teams distribute parallel for +//CHECK-SAME: block chunk size 49 thread chunk size 2 + +//CHECK-NEXT: B0T0 B0T0 B0T1 B0T1 B0T2 B0T2 B0T3 B0T3 B0T4 B0T4 B0T5 B0T5 +//CHECK-SAME: B0T6 B0T6 B0T7 B0T7 B0T8 B0T8 B0T9 B0T9 B0T10 B0T10 B0T11 B0T11 +//CHECK-SAME: B0T12 B0T12 B0T13 B0T13 B0T14 B0T14 B0T15 B0T15 B0T16 B0T16 +//CHECK-SAME: B0T17 B0T17 B0T18 B0T18 B0T19 B0T19 B0T20 B0T20 B0T21 B0T21 +//CHECK-SAME: B0T22 B0T22 B0T23 B0T23 B0T24 +//CHECK-SAME: B1T0 B1T0 B1T1 B1T1 B1T2 B1T2 B1T3 B1T3 B1T4 B1T4 B1T5 B1T5 +//CHECK-SAME: B1T6 B1T6 B1T7 B1T7 B1T8 B1T8 B1T9 B1T9 B1T10 B1T10 B1T11 B1T11 +//CHECK-SAME: B1T12 B1T12 B1T13 B1T13 B1T14 B1T14 B1T15 B1T15 B1T16 B1T16 +//CHECK-SAME: B1T17 B1T17 B1T18 B1T18 B1T19 B1T19 B1T20 B1T20 B1T21 B1T21 +//CHECK-SAME: B1T22 B1T22 B1T23 B1T23 B1T24 +//CHECK-SAME: B2T0 B2T0 + +//CHECK: omp target teams distribute parallel for +//CHECK-SAME: block chunk size 29 thread chunk size default + +//CHECK-NEXT: B0T0 B0T1 B0T2 B0T3 B0T4 B0T5 B0T6 B0T7 B0T8 B0T9 +//CHECK-SAME: B0T0 B0T1 B0T2 B0T3 B0T4 B0T5 B0T6 B0T7 B0T8 B0T9 +//CHECK-SAME: B0T0 B0T1 B0T2 B0T3 B0T4 B0T5 B0T6 B0T7 B0T8 +//CHECK-SAME: B1T0 B1T1 B1T2 B1T3 B1T4 B1T5 B1T6 B1T7 B1T8 B1T9 +//CHECK-SAME: B1T0 B1T1 B1T2 B1T3 B1T4 B1T5 B1T6 B1T7 B1T8 B1T9 +//CHECK-SAME: B1T0 B1T1 B1T2 B1T3 B1T4 B1T5 B1T6 B1T7 B1T8 +//CHECK-SAME: B2T0 B2T1 B2T2 B2T3 B2T4 B2T5 B2T6 B2T7 B2T8 B2T9 +//CHECK-SAME: B2T0 B2T1 B2T2 B2T3 B2T4 B2T5 B2T6 B2T7 B2T8 B2T9 +//CHECK-SAME: B2T0 B2T1 B2T2 B2T3 B2T4 B2T5 B2T6 B2T7 B2T8 +//CHECK-SAME: B3T0 B3T1 B3T2 B3T3 B3T4 B3T5 B3T6 B3T7 B3T8 B3T9 +//CHECK-SAME: B3T0 B3T1 B3T2 + +//CHECK: omp target teams distribute parallel for +//CHECK-SAME: block chunk size 101 thread chunk size default + +//CHECK-NEXT: B0T0 B0T1 B0T2 B0T3 B0T4 B0T5 B0T6 B0T7 B0T8 B0T9 +//CHECK-SAME: B0T0 B0T1 B0T2 B0T3 B0T4 B0T5 B0T6 B0T7 B0T8 B0T9 +//CHECK-SAME: B0T0 B0T1 B0T2 B0T3 B0T4 B0T5 B0T6 B0T7 B0T8 B0T9 +//CHECK-SAME: B0T0 B0T1 B0T2 B0T3 B0T4 B0T5 B0T6 B0T7 B0T8 B0T9 +//CHECK-SAME: B0T0 B0T1 B0T2 B0T3 B0T4 B0T5 B0T6 B0T7 B0T8 B0T9 +//CHECK-SAME: B0T0 B0T1 B0T2 B0T3 B0T4 B0T5 B0T6 B0T7 B0T8 B0T9 +//CHECK-SAME: B0T0 B0T1 B0T2 B0T3 B0T4 B0T5 B0T6 B0T7 B0T8 B0T9 +//CHECK-SAME: B0T0 B0T1 B0T2 B0T3 B0T4 B0T5 B0T6 B0T7 B0T8 B0T9 +//CHECK-SAME: B0T0 B0T1 B0T2 B0T3 B0T4 B0T5 B0T6 B0T7 B0T8 B0T9 +//CHECK-SAME: B0T0 B0T1 B0T2 B0T3 B0T4 B0T5 B0T6 B0T7 B0T8 B0T9 + +//CHECK: omp target teams distribute parallel for +//CHECK-SAME: default block chunk size thread chunk size 101 + +//CHECK-NEXT: B0T0 B0T0 B0T0 B0T0 B0T0 B0T0 B0T0 B0T0 B0T0 B0T0 +//CHECK-SAME: B1T0 B1T0 B1T0 B1T0 B1T0 B1T0 B1T0 B1T0 B1T0 B1T0 +//CHECK-SAME: B2T0 B2T0 B2T0 B2T0 B2T0 B2T0 B2T0 B2T0 B2T0 B2T0 +//CHECK-SAME: B3T0 B3T0 B3T0 B3T0 B3T0 B3T0 B3T0 B3T0 B3T0 B3T0 +//CHECK-SAME: B4T0 B4T0 B4T0 B4T0 B4T0 B4T0 B4T0 B4T0 B4T0 B4T0 +//CHECK-SAME: B5T0 B5T0 B5T0 B5T0 B5T0 B5T0 B5T0 B5T0 B5T0 B5T0 +//CHECK-SAME: B6T0 B6T0 B6T0 B6T0 B6T0 B6T0 B6T0 B6T0 B6T0 B6T0 +//CHECK-SAME: B7T0 B7T0 B7T0 B7T0 B7T0 B7T0 B7T0 B7T0 B7T0 B7T0 +//CHECK-SAME: B8T0 B8T0 B8T0 B8T0 B8T0 B8T0 B8T0 B8T0 B8T0 B8T0 +//CHECK-SAME: B0T0 B0T0 B0T0 B0T0 B0T0 B0T0 B0T0 B0T0 B0T0 B0T0 diff --git a/openmp/libomptarget/test/ompt/target_memcpy.c b/openmp/libomptarget/test/ompt/target_memcpy.c index 80a8d6a4b32e59fd215f3f28891aa7ed39bc9130..3224c5ac4c916d166cd5b864936b845c400da298 100644 --- a/openmp/libomptarget/test/ompt/target_memcpy.c +++ b/openmp/libomptarget/test/ompt/target_memcpy.c @@ -4,6 +4,8 @@ // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO /* * Verify that for the target OpenMP APIs, the return address is non-null and diff --git a/openmp/libomptarget/test/ompt/target_memcpy_emi.c b/openmp/libomptarget/test/ompt/target_memcpy_emi.c index 5347f38b87b6ff29ebdaf7f5d62dc4a324ea5635..fd7da13cb05d077a434a3da1a881f76867058f02 100644 --- a/openmp/libomptarget/test/ompt/target_memcpy_emi.c +++ b/openmp/libomptarget/test/ompt/target_memcpy_emi.c @@ -4,6 +4,8 @@ // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO /* * Verify all three data transfer directions: H2D, D2D and D2H diff --git a/openmp/libomptarget/test/ompt/veccopy.c b/openmp/libomptarget/test/ompt/veccopy.c index 80e71fd8a48cb4cf5ae58404d6110361970f6444..bc70f5a0b5b67d362bd7715262322961047c46de 100644 --- a/openmp/libomptarget/test/ompt/veccopy.c +++ b/openmp/libomptarget/test/ompt/veccopy.c @@ -4,6 +4,8 @@ // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO /* * Example OpenMP program that registers non-EMI callbacks diff --git a/openmp/libomptarget/test/ompt/veccopy_data.c b/openmp/libomptarget/test/ompt/veccopy_data.c index cef1de316a7a14854fb4ca64d8e7eadac248a280..264b484b881f10a95e337bdb1a272fc9e5936a31 100644 --- a/openmp/libomptarget/test/ompt/veccopy_data.c +++ b/openmp/libomptarget/test/ompt/veccopy_data.c @@ -4,6 +4,8 @@ // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO /* * Example OpenMP program that registers EMI callbacks. diff --git a/openmp/libomptarget/test/ompt/veccopy_disallow_both.c b/openmp/libomptarget/test/ompt/veccopy_disallow_both.c index 06293e413ba45a9ce922fcae8aa99b18236ca855..a011c21955bb2d054b7de80fa1a1d1252888b5aa 100644 --- a/openmp/libomptarget/test/ompt/veccopy_disallow_both.c +++ b/openmp/libomptarget/test/ompt/veccopy_disallow_both.c @@ -4,6 +4,8 @@ // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO /* * Example OpenMP program that shows that both EMI and non-EMI diff --git a/openmp/libomptarget/test/ompt/veccopy_emi.c b/openmp/libomptarget/test/ompt/veccopy_emi.c index b597d7be6aff668be90740f47abbf22ae3b4dde8..8718a39b4af81259b6410765bd3c82618cd425eb 100644 --- a/openmp/libomptarget/test/ompt/veccopy_emi.c +++ b/openmp/libomptarget/test/ompt/veccopy_emi.c @@ -4,6 +4,8 @@ // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO /* * Example OpenMP program that registers EMI callbacks diff --git a/openmp/libomptarget/test/ompt/veccopy_emi_map.c b/openmp/libomptarget/test/ompt/veccopy_emi_map.c index ce6f6e30d5815f5cd4b6e054504c993c41117459..2accba34034e6474f374813988df6d7995cf2ac4 100644 --- a/openmp/libomptarget/test/ompt/veccopy_emi_map.c +++ b/openmp/libomptarget/test/ompt/veccopy_emi_map.c @@ -4,6 +4,8 @@ // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO /* * Example OpenMP program that shows that map-EMI callbacks are not supported. diff --git a/openmp/libomptarget/test/ompt/veccopy_map.c b/openmp/libomptarget/test/ompt/veccopy_map.c index 83f63a6e6049eb7a36f97e060751de5547272875..56a0dd48f5368335f1a5ee1d5cbab5d64b1bc65e 100644 --- a/openmp/libomptarget/test/ompt/veccopy_map.c +++ b/openmp/libomptarget/test/ompt/veccopy_map.c @@ -4,6 +4,8 @@ // UNSUPPORTED: aarch64-unknown-linux-gnu-LTO // UNSUPPORTED: x86_64-pc-linux-gnu // UNSUPPORTED: x86_64-pc-linux-gnu-LTO +// UNSUPPORTED: s390x-ibm-linux-gnu +// UNSUPPORTED: s390x-ibm-linux-gnu-LTO /* * Example OpenMP program that shows that map callbacks are not supported. diff --git a/openmp/runtime/CMakeLists.txt b/openmp/runtime/CMakeLists.txt index 041b60efac5cee64b5d1ce34d6a13e81a6df9a5d..57ed54bcdc7bbe2b6912f78e742db0b3c34be459 100644 --- a/openmp/runtime/CMakeLists.txt +++ b/openmp/runtime/CMakeLists.txt @@ -30,7 +30,7 @@ if(${OPENMP_STANDALONE_BUILD}) # If adding a new architecture, take a look at cmake/LibompGetArchitecture.cmake libomp_get_architecture(LIBOMP_DETECTED_ARCH) set(LIBOMP_ARCH ${LIBOMP_DETECTED_ARCH} CACHE STRING - "The architecture to build for (x86_64/i386/arm/ppc/ppc64/ppc64le/aarch64/mic/mips/mips64/riscv64/loongarch64/ve/s390x/wasm32).") + "The architecture to build for (x86_64/i386/arm/ppc/ppc64/ppc64le/aarch64/aarch64_32/mic/mips/mips64/riscv64/loongarch64/ve/s390x/wasm32).") # Should assertions be enabled? They are on by default. set(LIBOMP_ENABLE_ASSERTIONS TRUE CACHE BOOL "enable assertions?") @@ -55,6 +55,8 @@ else() # Part of LLVM build set(LIBOMP_ARCH ppc64) elseif(LIBOMP_NATIVE_ARCH MATCHES "powerpc") set(LIBOMP_ARCH ppc) + elseif(LIBOMP_NATIVE_ARCH MATCHES "aarch64_32") + set(LIBOMP_ARCH aarch64_32) elseif(LIBOMP_NATIVE_ARCH MATCHES "aarch64") set(LIBOMP_ARCH aarch64) elseif(LIBOMP_NATIVE_ARCH MATCHES "arm64") @@ -91,7 +93,7 @@ if(LIBOMP_ARCH STREQUAL "aarch64") endif() endif() -libomp_check_variable(LIBOMP_ARCH 32e x86_64 32 i386 arm ppc ppc64 ppc64le aarch64 aarch64_a64fx mic mips mips64 riscv64 loongarch64 ve s390x wasm32) +libomp_check_variable(LIBOMP_ARCH 32e x86_64 32 i386 arm ppc ppc64 ppc64le aarch64 aarch64_32 aarch64_a64fx mic mips mips64 riscv64 loongarch64 ve s390x wasm32) set(LIBOMP_LIB_TYPE normal CACHE STRING "Performance,Profiling,Stubs library (normal/profile/stubs)") @@ -167,6 +169,7 @@ set(IA32 FALSE) set(INTEL64 FALSE) set(ARM FALSE) set(AARCH64 FALSE) +set(AARCH64_32 FALSE) set(AARCH64_A64FX FALSE) set(PPC64BE FALSE) set(PPC64LE FALSE) @@ -196,6 +199,8 @@ elseif("${LIBOMP_ARCH}" STREQUAL "ppc64le") # PPC64LE architecture set(PPC64 TRUE) elseif("${LIBOMP_ARCH}" STREQUAL "aarch64") # AARCH64 architecture set(AARCH64 TRUE) +elseif("${LIBOMP_ARCH}" STREQUAL "aarch64_32") # AARCH64_32 architecture + set(AARCH64_32 TRUE) elseif("${LIBOMP_ARCH}" STREQUAL "aarch64_a64fx") # AARCH64_A64FX architecture set(AARCH64_A64FX TRUE) elseif("${LIBOMP_ARCH}" STREQUAL "mic") # Intel(R) Many Integrated Core Architecture diff --git a/openmp/runtime/cmake/LibompGetArchitecture.cmake b/openmp/runtime/cmake/LibompGetArchitecture.cmake index d7f81870f9ef4b64a704aee17256f224d5f15b81..2d5c6622c9f7dda36d7ebe369c68847c8910833b 100644 --- a/openmp/runtime/cmake/LibompGetArchitecture.cmake +++ b/openmp/runtime/cmake/LibompGetArchitecture.cmake @@ -35,6 +35,8 @@ function(libomp_get_architecture return_arch) #error ARCHITECTURE=arm #elif defined(__arm__) || defined(_M_ARM) || defined(_ARM) #error ARCHITECTURE=arm + #elif defined(__ARM64_ARCH_8_32__) + #error ARCHITECTURE=aarch64_32 #elif defined(__aarch64__) || defined(_M_ARM64) #error ARCHITECTURE=aarch64 #elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) diff --git a/openmp/runtime/cmake/LibompUtils.cmake b/openmp/runtime/cmake/LibompUtils.cmake index 139eabb45c54f74769f03437c29e60c5da72511e..58b93b384a76a01221329c7185be74cf5ffc3c06 100644 --- a/openmp/runtime/cmake/LibompUtils.cmake +++ b/openmp/runtime/cmake/LibompUtils.cmake @@ -101,6 +101,8 @@ function(libomp_get_legal_arch return_arch_string) set(${return_arch_string} "PPC64LE" PARENT_SCOPE) elseif(${AARCH64}) set(${return_arch_string} "AARCH64" PARENT_SCOPE) + elseif(${AARCH64_32}) + set(${return_arch_string} "AARCH64_32" PARENT_SCOPE) elseif(${AARCH64_A64FX}) set(${return_arch_string} "AARCH64_A64FX" PARENT_SCOPE) elseif(${MIPS}) diff --git a/openmp/runtime/cmake/config-ix.cmake b/openmp/runtime/cmake/config-ix.cmake index 76f471a443806ea27ebe9371c8cd826eb5633c9b..337fe2e5996486f6c4b0a9ce79500e6eb1402fca 100644 --- a/openmp/runtime/cmake/config-ix.cmake +++ b/openmp/runtime/cmake/config-ix.cmake @@ -326,6 +326,7 @@ else() (LIBOMP_ARCH STREQUAL i386) OR # (LIBOMP_ARCH STREQUAL arm) OR (LIBOMP_ARCH STREQUAL aarch64) OR + (LIBOMP_ARCH STREQUAL aarch64_32) OR (LIBOMP_ARCH STREQUAL aarch64_a64fx) OR (LIBOMP_ARCH STREQUAL ppc64le) OR (LIBOMP_ARCH STREQUAL ppc64) OR diff --git a/openmp/runtime/src/CMakeLists.txt b/openmp/runtime/src/CMakeLists.txt index ff129feb5b6fa0b4f249e4b77b4d0cba7d30893e..f05bcabb44174265597bf6343a349f6d7d16b4a2 100644 --- a/openmp/runtime/src/CMakeLists.txt +++ b/openmp/runtime/src/CMakeLists.txt @@ -316,9 +316,25 @@ endif() # Building the Fortran module files # One compilation step creates both omp_lib.mod and omp_lib_kinds.mod -if(${LIBOMP_FORTRAN_MODULES}) - configure_file(${LIBOMP_INC_DIR}/omp_lib.h.var omp_lib.h @ONLY) - configure_file(${LIBOMP_INC_DIR}/omp_lib.f90.var omp_lib.f90 @ONLY) +configure_file(${LIBOMP_INC_DIR}/omp_lib.h.var omp_lib.h @ONLY) +configure_file(${LIBOMP_INC_DIR}/omp_lib.F90.var omp_lib.F90 @ONLY) + +set(BUILD_FORTRAN_MODULES False) +if (NOT ${LIBOMP_FORTRAN_MODULES_COMPILER} STREQUAL "") + # If libomp is built as an LLVM runtime and the flang compiler is available, + # compile the Fortran module files. + message(STATUS "configuring openmp to build Fortran module files using ${LIBOMP_FORTRAN_MODULES_COMPILER}") + set(LIBOMP_FORTRAN_SOURCE_FILE omp_lib.F90) + add_custom_target(libomp-mod ALL DEPENDS omp_lib.mod omp_lib_kinds.mod) + add_custom_command( + OUTPUT omp_lib.mod omp_lib_kinds.mod + COMMAND ${LIBOMP_FORTRAN_MODULES_COMPILER} -cpp -fsyntax-only ${LIBOMP_FORTRAN_SOURCE_FILE} + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${LIBOMP_FORTRAN_SOURCE_FILE} + ${CMAKE_CURRENT_BINARY_DIR}/omp_lib.h + ) + set(BUILD_FORTRAN_MODULES True) +elseif(${LIBOMP_FORTRAN_MODULES}) + # The following requests explicit building of the Fortran module files # Workaround for gfortran to build modules with the # omp_sched_monotonic integer parameter if (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") @@ -327,7 +343,7 @@ if(${LIBOMP_FORTRAN_MODULES}) add_custom_target(libomp-mod ALL DEPENDS omp_lib.mod omp_lib_kinds.mod) libomp_get_fflags(LIBOMP_CONFIGURED_FFLAGS) if(CMAKE_Fortran_COMPILER_SUPPORTS_F90) - set(LIBOMP_FORTRAN_SOURCE_FILE omp_lib.f90) + set(LIBOMP_FORTRAN_SOURCE_FILE omp_lib.F90) else() message(FATAL_ERROR "Fortran module build requires Fortran 90 compiler") endif() @@ -339,6 +355,7 @@ if(${LIBOMP_FORTRAN_MODULES}) ${CMAKE_CURRENT_BINARY_DIR}/omp_lib.h ) set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES omp_lib${CMAKE_C_OUTPUT_EXTENSION}) + set(BUILD_FORTRAN_MODULES True) endif() # Move files to exports/ directory if requested @@ -412,11 +429,15 @@ if(${LIBOMP_OMPT_SUPPORT}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/omp-tools.h DESTINATION ${LIBOMP_HEADERS_INSTALL_PATH} RENAME ompt.h) set(LIBOMP_OMP_TOOLS_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE) endif() -if(${LIBOMP_FORTRAN_MODULES}) +if(${BUILD_FORTRAN_MODULES}) + set (destination ${LIBOMP_HEADERS_INSTALL_PATH}) + if (NOT ${LIBOMP_MODULES_INSTALL_PATH} STREQUAL "") + set (destination ${LIBOMP_MODULES_INSTALL_PATH}) + endif() install(FILES ${CMAKE_CURRENT_BINARY_DIR}/omp_lib.h ${CMAKE_CURRENT_BINARY_DIR}/omp_lib.mod ${CMAKE_CURRENT_BINARY_DIR}/omp_lib_kinds.mod - DESTINATION ${LIBOMP_HEADERS_INSTALL_PATH} + DESTINATION ${destination} ) endif() diff --git a/openmp/runtime/src/include/omp.h.var b/openmp/runtime/src/include/omp.h.var index a1488ae9d21c616d8038d8efcf10107c77efa58a..eb3ab7778606a35ae47c743af9ef5bf554b009d3 100644 --- a/openmp/runtime/src/include/omp.h.var +++ b/openmp/runtime/src/include/omp.h.var @@ -156,6 +156,8 @@ /* OpenMP 5.1 interop */ typedef intptr_t omp_intptr_t; + extern void __KAI_KMPC_CONVENTION ompx_dump_mapping_tables(void); + /* 0..omp_get_num_interop_properties()-1 are reserved for implementation-defined properties */ typedef enum omp_interop_property { omp_ipr_fr_id = -1, diff --git a/openmp/runtime/src/include/omp_lib.f90.var b/openmp/runtime/src/include/omp_lib.F90.var similarity index 62% rename from openmp/runtime/src/include/omp_lib.f90.var rename to openmp/runtime/src/include/omp_lib.F90.var index 1ca542db3767ef2bd3c7face937d9e8517e5663c..63a3c93b8d92965f56de923b076ea5a46f1e0d29 100644 --- a/openmp/runtime/src/include/omp_lib.f90.var +++ b/openmp/runtime/src/include/omp_lib.F90.var @@ -14,37 +14,42 @@ use, intrinsic :: iso_c_binding - integer, parameter :: omp_integer_kind = c_int - integer, parameter :: omp_logical_kind = 4 - integer, parameter :: omp_real_kind = c_float - integer, parameter :: kmp_double_kind = c_double - integer, parameter :: omp_lock_kind = c_intptr_t - integer, parameter :: omp_nest_lock_kind = c_intptr_t - integer, parameter :: omp_sched_kind = omp_integer_kind - integer, parameter :: omp_proc_bind_kind = omp_integer_kind - integer, parameter :: kmp_pointer_kind = c_intptr_t - integer, parameter :: kmp_size_t_kind = c_size_t - integer, parameter :: kmp_affinity_mask_kind = c_intptr_t - integer, parameter :: kmp_cancel_kind = omp_integer_kind - integer, parameter :: omp_sync_hint_kind = omp_integer_kind - integer, parameter :: omp_lock_hint_kind = omp_sync_hint_kind - integer, parameter :: omp_control_tool_kind = omp_integer_kind - integer, parameter :: omp_control_tool_result_kind = omp_integer_kind - integer, parameter :: omp_allocator_handle_kind = c_intptr_t - integer, parameter :: omp_memspace_handle_kind = c_intptr_t - integer, parameter :: omp_alloctrait_key_kind = omp_integer_kind - integer, parameter :: omp_alloctrait_val_kind = c_intptr_t - integer, parameter :: omp_interop_kind = c_intptr_t - integer, parameter :: omp_interop_fr_kind = omp_integer_kind + ! Set PRIVATE by default to explicitly only export what is meant + ! to be exported by this MODULE. + private + + integer, parameter, public :: omp_integer_kind = c_int + integer, parameter, public :: omp_logical_kind = 4 + integer, parameter, public :: omp_real_kind = c_float + integer, parameter, public :: kmp_double_kind = c_double + integer, parameter, public :: omp_lock_kind = c_intptr_t + integer, parameter, public :: omp_nest_lock_kind = c_intptr_t + integer, parameter, public :: omp_sched_kind = omp_integer_kind + integer, parameter, public :: omp_proc_bind_kind = omp_integer_kind + integer, parameter, public :: kmp_pointer_kind = c_intptr_t + integer, parameter, public :: kmp_size_t_kind = c_size_t + integer, parameter, public :: kmp_affinity_mask_kind = c_intptr_t + integer, parameter, public :: kmp_cancel_kind = omp_integer_kind + integer, parameter, public :: omp_sync_hint_kind = omp_integer_kind + integer, parameter, public :: omp_lock_hint_kind = omp_sync_hint_kind + integer, parameter, public :: omp_control_tool_kind = omp_integer_kind + integer, parameter, public :: omp_control_tool_result_kind = omp_integer_kind + integer, parameter, public :: omp_allocator_handle_kind = c_intptr_t + integer, parameter, public :: omp_memspace_handle_kind = c_intptr_t + integer, parameter, public :: omp_alloctrait_key_kind = omp_integer_kind + integer, parameter, public :: omp_alloctrait_val_kind = c_intptr_t + integer, parameter, public :: omp_interop_kind = c_intptr_t + integer, parameter, public :: omp_interop_fr_kind = omp_integer_kind type omp_alloctrait integer(kind=omp_alloctrait_key_kind) key integer(kind=omp_alloctrait_val_kind) value end type omp_alloctrait + public :: omp_alloctrait - integer, parameter :: omp_pause_resource_kind = omp_integer_kind - integer, parameter :: omp_depend_kind = c_intptr_t - integer, parameter :: omp_event_handle_kind = c_intptr_t + integer, parameter, public :: omp_pause_resource_kind = omp_integer_kind + integer, parameter, public :: omp_depend_kind = c_intptr_t + integer, parameter, public :: omp_event_handle_kind = c_intptr_t end module omp_lib_kinds @@ -52,119 +57,151 @@ use omp_lib_kinds - integer (kind=omp_integer_kind), parameter :: openmp_version = @LIBOMP_OMP_YEAR_MONTH@ - integer (kind=omp_integer_kind), parameter :: kmp_version_major = @LIBOMP_VERSION_MAJOR@ - integer (kind=omp_integer_kind), parameter :: kmp_version_minor = @LIBOMP_VERSION_MINOR@ - integer (kind=omp_integer_kind), parameter :: kmp_version_build = @LIBOMP_VERSION_BUILD@ + ! Set PRIVATE by default to explicitly only export what is meant + ! to be exported by this MODULE. + private + + ! Re-export definitions in omp_lib_kinds + public :: omp_integer_kind + public :: omp_logical_kind + public :: omp_real_kind + public :: kmp_double_kind + public :: omp_lock_kind + public :: omp_nest_lock_kind + public :: omp_sched_kind + public :: omp_proc_bind_kind + public :: kmp_pointer_kind + public :: kmp_size_t_kind + public :: kmp_affinity_mask_kind + public :: kmp_cancel_kind + public :: omp_sync_hint_kind + public :: omp_lock_hint_kind + public :: omp_control_tool_kind + public :: omp_control_tool_result_kind + public :: omp_allocator_handle_kind + public :: omp_memspace_handle_kind + public :: omp_alloctrait_key_kind + public :: omp_alloctrait_val_kind + public :: omp_interop_kind + public :: omp_interop_fr_kind + public :: omp_alloctrait + public :: omp_pause_resource_kind + public :: omp_depend_kind + public :: omp_event_handle_kind + + integer (kind=omp_integer_kind), parameter, public :: openmp_version = @LIBOMP_OMP_YEAR_MONTH@ + integer (kind=omp_integer_kind), parameter, public :: kmp_version_major = @LIBOMP_VERSION_MAJOR@ + integer (kind=omp_integer_kind), parameter, public :: kmp_version_minor = @LIBOMP_VERSION_MINOR@ + integer (kind=omp_integer_kind), parameter, public :: kmp_version_build = @LIBOMP_VERSION_BUILD@ character(*) kmp_build_date parameter( kmp_build_date = '@LIBOMP_BUILD_DATE@' ) - integer(kind=omp_sched_kind), parameter :: omp_sched_static = 1 - integer(kind=omp_sched_kind), parameter :: omp_sched_dynamic = 2 - integer(kind=omp_sched_kind), parameter :: omp_sched_guided = 3 - integer(kind=omp_sched_kind), parameter :: omp_sched_auto = 4 - integer(kind=omp_sched_kind), parameter :: omp_sched_monotonic = int(Z'80000000', kind=omp_sched_kind) - - integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_false = 0 - integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_true = 1 - integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_master = 2 - integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_close = 3 - integer (kind=omp_proc_bind_kind), parameter :: omp_proc_bind_spread = 4 - - integer (kind=kmp_cancel_kind), parameter :: kmp_cancel_parallel = 1 - integer (kind=kmp_cancel_kind), parameter :: kmp_cancel_loop = 2 - integer (kind=kmp_cancel_kind), parameter :: kmp_cancel_sections = 3 - integer (kind=kmp_cancel_kind), parameter :: kmp_cancel_taskgroup = 4 - - integer (kind=omp_sync_hint_kind), parameter :: omp_sync_hint_none = 0 - integer (kind=omp_sync_hint_kind), parameter :: omp_sync_hint_uncontended = 1 - integer (kind=omp_sync_hint_kind), parameter :: omp_sync_hint_contended = 2 - integer (kind=omp_sync_hint_kind), parameter :: omp_sync_hint_nonspeculative = 4 - integer (kind=omp_sync_hint_kind), parameter :: omp_sync_hint_speculative = 8 - integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_none = omp_sync_hint_none - integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_uncontended = omp_sync_hint_uncontended - integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_contended = omp_sync_hint_contended - integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_nonspeculative = omp_sync_hint_nonspeculative - integer (kind=omp_lock_hint_kind), parameter :: omp_lock_hint_speculative = omp_sync_hint_speculative - integer (kind=omp_lock_hint_kind), parameter :: kmp_lock_hint_hle = 65536 - integer (kind=omp_lock_hint_kind), parameter :: kmp_lock_hint_rtm = 131072 - integer (kind=omp_lock_hint_kind), parameter :: kmp_lock_hint_adaptive = 262144 - - integer (kind=omp_control_tool_kind), parameter :: omp_control_tool_start = 1 - integer (kind=omp_control_tool_kind), parameter :: omp_control_tool_pause = 2 - integer (kind=omp_control_tool_kind), parameter :: omp_control_tool_flush = 3 - integer (kind=omp_control_tool_kind), parameter :: omp_control_tool_end = 4 - - integer (kind=omp_control_tool_result_kind), parameter :: omp_control_tool_notool = -2 - integer (kind=omp_control_tool_result_kind), parameter :: omp_control_tool_nocallback = -1 - integer (kind=omp_control_tool_result_kind), parameter :: omp_control_tool_success = 0 - integer (kind=omp_control_tool_result_kind), parameter :: omp_control_tool_ignored = 1 - - integer (kind=omp_alloctrait_key_kind), parameter :: omp_atk_sync_hint = 1 - integer (kind=omp_alloctrait_key_kind), parameter :: omp_atk_alignment = 2 - integer (kind=omp_alloctrait_key_kind), parameter :: omp_atk_access = 3 - integer (kind=omp_alloctrait_key_kind), parameter :: omp_atk_pool_size = 4 - integer (kind=omp_alloctrait_key_kind), parameter :: omp_atk_fallback = 5 - integer (kind=omp_alloctrait_key_kind), parameter :: omp_atk_fb_data = 6 - integer (kind=omp_alloctrait_key_kind), parameter :: omp_atk_pinned = 7 - integer (kind=omp_alloctrait_key_kind), parameter :: omp_atk_partition = 8 - - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_default = -1 - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_false = 0 - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_true = 1 - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_contended = 3 - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_uncontended = 4 - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_serialized = 5 - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_sequential = omp_atv_serialized - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_private = 6 - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_all = 7 - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_thread = 8 - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_pteam = 9 - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_cgroup = 10 - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_default_mem_fb = 11 - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_null_fb = 12 - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_abort_fb = 13 - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_allocator_fb = 14 - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_environment = 15 - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_nearest = 16 - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_blocked = 17 - integer (kind=omp_alloctrait_val_kind), parameter :: omp_atv_interleaved = 18 - - integer (kind=omp_allocator_handle_kind), parameter :: omp_null_allocator = 0 - integer (kind=omp_allocator_handle_kind), parameter :: omp_default_mem_alloc = 1 - integer (kind=omp_allocator_handle_kind), parameter :: omp_large_cap_mem_alloc = 2 - integer (kind=omp_allocator_handle_kind), parameter :: omp_const_mem_alloc = 3 - integer (kind=omp_allocator_handle_kind), parameter :: omp_high_bw_mem_alloc = 4 - integer (kind=omp_allocator_handle_kind), parameter :: omp_low_lat_mem_alloc = 5 - integer (kind=omp_allocator_handle_kind), parameter :: omp_cgroup_mem_alloc = 6 - integer (kind=omp_allocator_handle_kind), parameter :: omp_pteam_mem_alloc = 7 - integer (kind=omp_allocator_handle_kind), parameter :: omp_thread_mem_alloc = 8 - integer (kind=omp_allocator_handle_kind), parameter :: llvm_omp_target_host_mem_alloc = 100 - integer (kind=omp_allocator_handle_kind), parameter :: llvm_omp_target_shared_mem_alloc = 101 - integer (kind=omp_allocator_handle_kind), parameter :: llvm_omp_target_device_mem_alloc = 102 - - integer (kind=omp_memspace_handle_kind), parameter :: omp_default_mem_space = 0 - integer (kind=omp_memspace_handle_kind), parameter :: omp_large_cap_mem_space = 1 - integer (kind=omp_memspace_handle_kind), parameter :: omp_const_mem_space = 2 - integer (kind=omp_memspace_handle_kind), parameter :: omp_high_bw_mem_space = 3 - integer (kind=omp_memspace_handle_kind), parameter :: omp_low_lat_mem_space = 4 - integer (kind=omp_memspace_handle_kind), parameter :: llvm_omp_target_host_mem_space = 100 - integer (kind=omp_memspace_handle_kind), parameter :: llvm_omp_target_shared_mem_space = 101 - integer (kind=omp_memspace_handle_kind), parameter :: llvm_omp_target_device_mem_space = 102 - - integer (kind=omp_pause_resource_kind), parameter :: omp_pause_resume = 0 - integer (kind=omp_pause_resource_kind), parameter :: omp_pause_soft = 1 - integer (kind=omp_pause_resource_kind), parameter :: omp_pause_hard = 2 - - integer (kind=omp_interop_fr_kind), parameter :: omp_ifr_cuda = 1 - integer (kind=omp_interop_fr_kind), parameter :: omp_ifr_cuda_driver = 2 - integer (kind=omp_interop_fr_kind), parameter :: omp_ifr_opencl = 3 - integer (kind=omp_interop_fr_kind), parameter :: omp_ifr_sycl = 4 - integer (kind=omp_interop_fr_kind), parameter :: omp_ifr_hip = 5 - integer (kind=omp_interop_fr_kind), parameter :: omp_ifr_level_zero = 6 - integer (kind=omp_interop_fr_kind), parameter :: omp_ifr_last = 7 - - integer (kind=omp_interop_kind), parameter :: omp_interop_none = 0 + integer(kind=omp_sched_kind), parameter, public :: omp_sched_static = 1 + integer(kind=omp_sched_kind), parameter, public :: omp_sched_dynamic = 2 + integer(kind=omp_sched_kind), parameter, public :: omp_sched_guided = 3 + integer(kind=omp_sched_kind), parameter, public :: omp_sched_auto = 4 + integer(kind=omp_sched_kind), parameter, public :: omp_sched_monotonic = int(Z'80000000', kind=omp_sched_kind) + + integer (kind=omp_proc_bind_kind), parameter, public :: omp_proc_bind_false = 0 + integer (kind=omp_proc_bind_kind), parameter, public :: omp_proc_bind_true = 1 + integer (kind=omp_proc_bind_kind), parameter, public :: omp_proc_bind_master = 2 + integer (kind=omp_proc_bind_kind), parameter, public :: omp_proc_bind_close = 3 + integer (kind=omp_proc_bind_kind), parameter, public :: omp_proc_bind_spread = 4 + + integer (kind=kmp_cancel_kind), parameter, public :: kmp_cancel_parallel = 1 + integer (kind=kmp_cancel_kind), parameter, public :: kmp_cancel_loop = 2 + integer (kind=kmp_cancel_kind), parameter, public :: kmp_cancel_sections = 3 + integer (kind=kmp_cancel_kind), parameter, public :: kmp_cancel_taskgroup = 4 + + integer (kind=omp_sync_hint_kind), parameter, public :: omp_sync_hint_none = 0 + integer (kind=omp_sync_hint_kind), parameter, public :: omp_sync_hint_uncontended = 1 + integer (kind=omp_sync_hint_kind), parameter, public :: omp_sync_hint_contended = 2 + integer (kind=omp_sync_hint_kind), parameter, public :: omp_sync_hint_nonspeculative = 4 + integer (kind=omp_sync_hint_kind), parameter, public :: omp_sync_hint_speculative = 8 + integer (kind=omp_lock_hint_kind), parameter, public :: omp_lock_hint_none = omp_sync_hint_none + integer (kind=omp_lock_hint_kind), parameter, public :: omp_lock_hint_uncontended = omp_sync_hint_uncontended + integer (kind=omp_lock_hint_kind), parameter, public :: omp_lock_hint_contended = omp_sync_hint_contended + integer (kind=omp_lock_hint_kind), parameter, public :: omp_lock_hint_nonspeculative = omp_sync_hint_nonspeculative + integer (kind=omp_lock_hint_kind), parameter, public :: omp_lock_hint_speculative = omp_sync_hint_speculative + integer (kind=omp_lock_hint_kind), parameter, public :: kmp_lock_hint_hle = 65536 + integer (kind=omp_lock_hint_kind), parameter, public :: kmp_lock_hint_rtm = 131072 + integer (kind=omp_lock_hint_kind), parameter, public :: kmp_lock_hint_adaptive = 262144 + + integer (kind=omp_control_tool_kind), parameter, public :: omp_control_tool_start = 1 + integer (kind=omp_control_tool_kind), parameter, public :: omp_control_tool_pause = 2 + integer (kind=omp_control_tool_kind), parameter, public :: omp_control_tool_flush = 3 + integer (kind=omp_control_tool_kind), parameter, public :: omp_control_tool_end = 4 + + integer (kind=omp_control_tool_result_kind), parameter, public :: omp_control_tool_notool = -2 + integer (kind=omp_control_tool_result_kind), parameter, public :: omp_control_tool_nocallback = -1 + integer (kind=omp_control_tool_result_kind), parameter, public :: omp_control_tool_success = 0 + integer (kind=omp_control_tool_result_kind), parameter, public :: omp_control_tool_ignored = 1 + + integer (kind=omp_alloctrait_key_kind), parameter, public :: omp_atk_sync_hint = 1 + integer (kind=omp_alloctrait_key_kind), parameter, public :: omp_atk_alignment = 2 + integer (kind=omp_alloctrait_key_kind), parameter, public :: omp_atk_access = 3 + integer (kind=omp_alloctrait_key_kind), parameter, public :: omp_atk_pool_size = 4 + integer (kind=omp_alloctrait_key_kind), parameter, public :: omp_atk_fallback = 5 + integer (kind=omp_alloctrait_key_kind), parameter, public :: omp_atk_fb_data = 6 + integer (kind=omp_alloctrait_key_kind), parameter, public :: omp_atk_pinned = 7 + integer (kind=omp_alloctrait_key_kind), parameter, public :: omp_atk_partition = 8 + + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_default = -1 + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_false = 0 + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_true = 1 + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_contended = 3 + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_uncontended = 4 + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_serialized = 5 + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_sequential = omp_atv_serialized + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_private = 6 + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_all = 7 + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_thread = 8 + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_pteam = 9 + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_cgroup = 10 + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_default_mem_fb = 11 + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_null_fb = 12 + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_abort_fb = 13 + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_allocator_fb = 14 + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_environment = 15 + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_nearest = 16 + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_blocked = 17 + integer (kind=omp_alloctrait_val_kind), parameter, public :: omp_atv_interleaved = 18 + + integer (kind=omp_allocator_handle_kind), parameter, public :: omp_null_allocator = 0 + integer (kind=omp_allocator_handle_kind), parameter, public :: omp_default_mem_alloc = 1 + integer (kind=omp_allocator_handle_kind), parameter, public :: omp_large_cap_mem_alloc = 2 + integer (kind=omp_allocator_handle_kind), parameter, public :: omp_const_mem_alloc = 3 + integer (kind=omp_allocator_handle_kind), parameter, public :: omp_high_bw_mem_alloc = 4 + integer (kind=omp_allocator_handle_kind), parameter, public :: omp_low_lat_mem_alloc = 5 + integer (kind=omp_allocator_handle_kind), parameter, public :: omp_cgroup_mem_alloc = 6 + integer (kind=omp_allocator_handle_kind), parameter, public :: omp_pteam_mem_alloc = 7 + integer (kind=omp_allocator_handle_kind), parameter, public :: omp_thread_mem_alloc = 8 + integer (kind=omp_allocator_handle_kind), parameter, public :: llvm_omp_target_host_mem_alloc = 100 + integer (kind=omp_allocator_handle_kind), parameter, public :: llvm_omp_target_shared_mem_alloc = 101 + integer (kind=omp_allocator_handle_kind), parameter, public :: llvm_omp_target_device_mem_alloc = 102 + + integer (kind=omp_memspace_handle_kind), parameter, public :: omp_default_mem_space = 0 + integer (kind=omp_memspace_handle_kind), parameter, public :: omp_large_cap_mem_space = 1 + integer (kind=omp_memspace_handle_kind), parameter, public :: omp_const_mem_space = 2 + integer (kind=omp_memspace_handle_kind), parameter, public :: omp_high_bw_mem_space = 3 + integer (kind=omp_memspace_handle_kind), parameter, public :: omp_low_lat_mem_space = 4 + integer (kind=omp_memspace_handle_kind), parameter, public :: llvm_omp_target_host_mem_space = 100 + integer (kind=omp_memspace_handle_kind), parameter, public :: llvm_omp_target_shared_mem_space = 101 + integer (kind=omp_memspace_handle_kind), parameter, public :: llvm_omp_target_device_mem_space = 102 + + integer (kind=omp_pause_resource_kind), parameter, public :: omp_pause_resume = 0 + integer (kind=omp_pause_resource_kind), parameter, public :: omp_pause_soft = 1 + integer (kind=omp_pause_resource_kind), parameter, public :: omp_pause_hard = 2 + + integer (kind=omp_interop_fr_kind), parameter, public :: omp_ifr_cuda = 1 + integer (kind=omp_interop_fr_kind), parameter, public :: omp_ifr_cuda_driver = 2 + integer (kind=omp_interop_fr_kind), parameter, public :: omp_ifr_opencl = 3 + integer (kind=omp_interop_fr_kind), parameter, public :: omp_ifr_sycl = 4 + integer (kind=omp_interop_fr_kind), parameter, public :: omp_ifr_hip = 5 + integer (kind=omp_interop_fr_kind), parameter, public :: omp_ifr_level_zero = 6 + integer (kind=omp_interop_fr_kind), parameter, public :: omp_ifr_last = 7 + + integer (kind=omp_interop_kind), parameter, public :: omp_interop_none = 0 interface @@ -392,82 +429,102 @@ end subroutine omp_fulfill_event subroutine omp_init_lock(svar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_init_lock !DIR$ ENDIF +#endif use omp_lib_kinds integer (kind=omp_lock_kind) svar end subroutine omp_init_lock subroutine omp_destroy_lock(svar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_destroy_lock !DIR$ ENDIF +#endif use omp_lib_kinds integer (kind=omp_lock_kind) svar end subroutine omp_destroy_lock subroutine omp_set_lock(svar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_set_lock !DIR$ ENDIF +#endif use omp_lib_kinds integer (kind=omp_lock_kind) svar end subroutine omp_set_lock subroutine omp_unset_lock(svar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_unset_lock !DIR$ ENDIF +#endif use omp_lib_kinds integer (kind=omp_lock_kind) svar end subroutine omp_unset_lock function omp_test_lock(svar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_test_lock !DIR$ ENDIF +#endif use omp_lib_kinds logical (kind=omp_logical_kind) omp_test_lock integer (kind=omp_lock_kind) svar end function omp_test_lock subroutine omp_init_nest_lock(nvar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_init_nest_lock !DIR$ ENDIF +#endif use omp_lib_kinds integer (kind=omp_nest_lock_kind) nvar end subroutine omp_init_nest_lock subroutine omp_destroy_nest_lock(nvar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_destroy_nest_lock !DIR$ ENDIF +#endif use omp_lib_kinds integer (kind=omp_nest_lock_kind) nvar end subroutine omp_destroy_nest_lock subroutine omp_set_nest_lock(nvar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_set_nest_lock !DIR$ ENDIF +#endif use omp_lib_kinds integer (kind=omp_nest_lock_kind) nvar end subroutine omp_set_nest_lock subroutine omp_unset_nest_lock(nvar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_unset_nest_lock !DIR$ ENDIF +#endif use omp_lib_kinds integer (kind=omp_nest_lock_kind) nvar end subroutine omp_unset_nest_lock function omp_test_nest_lock(nvar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_test_nest_lock !DIR$ ENDIF +#endif use omp_lib_kinds integer (kind=omp_integer_kind) omp_test_nest_lock integer (kind=omp_nest_lock_kind) nvar @@ -568,20 +625,20 @@ end subroutine omp_display_env function omp_target_alloc(size, device_num) bind(c) - use omp_lib_kinds + use, intrinsic :: iso_c_binding, only: c_ptr, c_size_t, c_int type(c_ptr) omp_target_alloc integer(c_size_t), value :: size integer(c_int), value :: device_num end function omp_target_alloc subroutine omp_target_free(device_ptr, device_num) bind(c) - use omp_lib_kinds + use, intrinsic :: iso_c_binding, only: c_ptr, c_int type(c_ptr), value :: device_ptr integer(c_int), value :: device_num end subroutine omp_target_free function omp_target_is_present(ptr, device_num) bind(c) - use omp_lib_kinds + use, intrinsic :: iso_c_binding, only: c_ptr, c_int integer(c_int) omp_target_is_present type(c_ptr), value :: ptr integer(c_int), value :: device_num @@ -589,7 +646,7 @@ function omp_target_memcpy(dst, src, length, dst_offset, src_offset, & dst_device_num, src_device_num) bind(c) - use omp_lib_kinds + use, intrinsic :: iso_c_binding, only: c_ptr, c_size_t, c_int integer(c_int) omp_target_memcpy type(c_ptr), value :: dst, src integer(c_size_t), value :: length, dst_offset, src_offset @@ -599,7 +656,7 @@ function omp_target_memcpy_rect(dst, src, element_size, num_dims, & volume, dst_offsets, src_offsets, dst_dimensions, & src_dimensions, dst_device_num, src_device_num) bind(c) - use omp_lib_kinds + use, intrinsic :: iso_c_binding, only: c_ptr, c_size_t, c_int integer(c_int) omp_target_memcpy_rect type(c_ptr), value :: dst, src integer(c_size_t), value :: element_size @@ -612,6 +669,7 @@ src_offset, dst_device_num, src_device_num, depobj_count, & depobj_list) bind(c) use omp_lib_kinds + use, intrinsic :: iso_c_binding, only: c_ptr, c_size_t, c_int integer(c_int) omp_target_memcpy_async type(c_ptr), value :: dst, src integer(c_size_t), value :: length, dst_offset, src_offset @@ -625,6 +683,7 @@ src_dimensions, dst_device_num, src_device_num, depobj_count, & depobj_list) bind(c) use omp_lib_kinds + use, intrinsic :: iso_c_binding, only: c_ptr, c_size_t, c_int integer(c_int) omp_target_memcpy_rect_async type(c_ptr), value :: dst, src integer(c_size_t), value :: element_size @@ -646,8 +705,8 @@ function omp_target_memset_async(ptr, val, count, device_num, & depobj_count, depobj_list) bind(c) - use, intrinsic :: iso_c_binding, only : c_ptr, c_int, c_size_t use omp_lib_kinds + use, intrinsic :: iso_c_binding, only : c_ptr, c_int, c_size_t type(c_ptr) :: omp_target_memset_async type(c_ptr), value :: ptr integer(c_int), value :: val @@ -659,7 +718,7 @@ function omp_target_associate_ptr(host_ptr, device_ptr, size, & device_offset, device_num) bind(c) - use omp_lib_kinds + use, intrinsic :: iso_c_binding, only: c_ptr, c_size_t, c_int integer(c_int) omp_target_associate_ptr type(c_ptr), value :: host_ptr, device_ptr integer(c_size_t), value :: size, device_offset @@ -667,21 +726,20 @@ end function omp_target_associate_ptr function omp_get_mapped_ptr(ptr, device_num) bind(c) - use omp_lib_kinds + use, intrinsic :: iso_c_binding, only: c_ptr, c_int type(c_ptr) omp_get_mapped_ptr type(c_ptr), value :: ptr integer(c_int), value :: device_num end function omp_get_mapped_ptr function omp_target_disassociate_ptr(ptr, device_num) bind(c) - use omp_lib_kinds + use, intrinsic :: iso_c_binding, only: c_ptr, c_int integer(c_int) omp_target_disassociate_ptr type(c_ptr), value :: ptr integer(c_int), value :: device_num end function omp_target_disassociate_ptr function omp_target_is_accessible(ptr, size, device_num) bind(c) - use omp_lib_kinds use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t, c_int integer(c_int) omp_target_is_accessible type(c_ptr), value :: ptr @@ -900,4 +958,124 @@ end interface + ! make the above routine definitions public + public :: omp_set_num_threads + public :: omp_set_dynamic + public :: omp_set_nested + public :: omp_get_num_threads + public :: omp_get_max_threads + public :: omp_get_thread_num + public :: omp_get_num_procs + public :: omp_in_parallel + public :: omp_in_final + public :: omp_get_dynamic + public :: omp_get_nested + public :: omp_get_thread_limit + public :: omp_set_max_active_levels + public :: omp_get_max_active_levels + public :: omp_get_level + public :: omp_get_active_level + public :: omp_get_ancestor_thread_num + public :: omp_get_team_size + public :: omp_set_schedule + public :: omp_get_schedule + public :: omp_get_proc_bind + public :: omp_get_num_places + public :: omp_get_place_num_procs + public :: omp_get_place_proc_ids + public :: omp_get_place_num + public :: omp_get_partition_num_places + public :: omp_get_partition_place_nums + public :: omp_get_wtime + public :: omp_get_wtick + public :: omp_get_default_device + public :: omp_set_default_device + public :: omp_get_num_devices + public :: omp_get_num_teams + public :: omp_get_team_num + public :: omp_get_cancellation + public :: omp_is_initial_device + public :: omp_get_initial_device + public :: omp_get_device_num + public :: omp_pause_resource + public :: omp_pause_resource_all + public :: omp_get_supported_active_levels + public :: omp_fulfill_event + public :: omp_init_lock + public :: omp_destroy_lock + public :: omp_set_lock + public :: omp_unset_lock + public :: omp_test_lock + public :: omp_init_nest_lock + public :: omp_destroy_nest_lock + public :: omp_set_nest_lock + public :: omp_unset_nest_lock + public :: omp_test_nest_lock + public :: omp_get_max_task_priority + public :: omp_init_lock_with_hint + public :: omp_init_nest_lock_with_hint + public :: omp_control_tool + public :: omp_init_allocator + public :: omp_destroy_allocator + public :: omp_set_default_allocator + public :: omp_get_default_allocator + public :: omp_set_affinity_format + public :: omp_get_affinity_format + public :: omp_display_affinity + public :: omp_capture_affinity + public :: omp_set_num_teams + public :: omp_get_max_teams + public :: omp_set_teams_thread_limit + public :: omp_get_teams_thread_limit + public :: omp_display_env + public :: omp_target_alloc + public :: omp_target_free + public :: omp_target_is_present + public :: omp_target_memcpy + public :: omp_target_memcpy_rect + public :: omp_target_memcpy_async + public :: omp_target_memcpy_rect_async + public :: omp_target_memset + public :: omp_target_memset_async + public :: omp_target_associate_ptr + public :: omp_get_mapped_ptr + public :: omp_target_disassociate_ptr + public :: omp_target_is_accessible + public :: omp_alloc + public :: omp_aligned_alloc + public :: omp_calloc + public :: omp_aligned_calloc + public :: omp_realloc + public :: omp_free + public :: omp_in_explicit_task + public :: kmp_set_stacksize + public :: kmp_set_stacksize_s + public :: kmp_set_blocktime + public :: kmp_set_library_serial + public :: kmp_set_library_turnaround + public :: kmp_set_library_throughput + public :: kmp_set_library + public :: kmp_set_defaults + public :: kmp_get_stacksize + public :: kmp_get_stacksize_s + public :: kmp_get_blocktime + public :: kmp_get_library + public :: kmp_set_disp_num_buffers + public :: kmp_set_affinity + public :: kmp_get_affinity + public :: kmp_get_affinity_max_proc + public :: kmp_create_affinity_mask + public :: kmp_destroy_affinity_mask + public :: kmp_set_affinity_mask_proc + public :: kmp_unset_affinity_mask_proc + public :: kmp_get_affinity_mask_proc + public :: kmp_malloc + public :: kmp_aligned_malloc + public :: kmp_calloc + public :: kmp_realloc + public :: kmp_free + public :: kmp_set_warnings_on + public :: kmp_set_warnings_off + public :: kmp_get_cancellation_status + end module omp_lib diff --git a/openmp/runtime/src/include/omp_lib.h.var b/openmp/runtime/src/include/omp_lib.h.var index 617f2321676deeffe6b6333bd5f2aabe3d14ef02..a709a2f298f8c8c29ce26aea89311a0761ac219e 100644 --- a/openmp/runtime/src/include/omp_lib.h.var +++ b/openmp/runtime/src/include/omp_lib.h.var @@ -486,82 +486,102 @@ end subroutine omp_fulfill_event subroutine omp_init_lock(svar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_init_lock !DIR$ ENDIF +#endif import integer (kind=omp_lock_kind) svar end subroutine omp_init_lock subroutine omp_destroy_lock(svar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_destroy_lock !DIR$ ENDIF +#endif import integer (kind=omp_lock_kind) svar end subroutine omp_destroy_lock subroutine omp_set_lock(svar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_set_lock !DIR$ ENDIF +#endif import integer (kind=omp_lock_kind) svar end subroutine omp_set_lock subroutine omp_unset_lock(svar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_unset_lock !DIR$ ENDIF +#endif import integer (kind=omp_lock_kind) svar end subroutine omp_unset_lock function omp_test_lock(svar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_test_lock !DIR$ ENDIF +#endif import logical (kind=omp_logical_kind) omp_test_lock integer (kind=omp_lock_kind) svar end function omp_test_lock subroutine omp_init_nest_lock(nvar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_init_nest_lock !DIR$ ENDIF +#endif import integer (kind=omp_nest_lock_kind) nvar end subroutine omp_init_nest_lock subroutine omp_destroy_nest_lock(nvar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_destroy_nest_lock !DIR$ ENDIF +#endif import integer (kind=omp_nest_lock_kind) nvar end subroutine omp_destroy_nest_lock subroutine omp_set_nest_lock(nvar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_set_nest_lock !DIR$ ENDIF +#endif import integer (kind=omp_nest_lock_kind) nvar end subroutine omp_set_nest_lock subroutine omp_unset_nest_lock(nvar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_unset_nest_lock !DIR$ ENDIF +#endif import integer (kind=omp_nest_lock_kind) nvar end subroutine omp_unset_nest_lock function omp_test_nest_lock(nvar) bind(c) +#ifdef __INTEL_COMPILER !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_test_nest_lock !DIR$ ENDIF +#endif import integer (kind=omp_integer_kind) omp_test_nest_lock integer (kind=omp_nest_lock_kind) nvar @@ -990,6 +1010,7 @@ end subroutine kmp_set_warnings_off end interface +#ifdef __INTEL_COMPILER !DIR$ IF DEFINED (__INTEL_OFFLOAD) !DIR$ IF(__INTEL_COMPILER.LT.1900) @@ -1158,3 +1179,4 @@ !$omp declare target(omp_init_nest_lock_with_hint ) !DIR$ ENDIF !DIR$ ENDIF +#endif diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h index 569a1ab9b477c42878b87c20f8af02a549dcd786..18ccf10fe17d0f6e4bf231bd75b387dd5a7235a2 100644 --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -819,6 +819,7 @@ private: typedef KMPAffinity::Mask kmp_affin_mask_t; extern KMPAffinity *__kmp_affinity_dispatch; +#ifndef KMP_OS_AIX class kmp_affinity_raii_t { kmp_affin_mask_t *mask; bool restored; @@ -843,6 +844,7 @@ public: } ~kmp_affinity_raii_t() { restore(); } }; +#endif // !KMP_OS_AIX // Declare local char buffers with this size for printing debug and info // messages, using __kmp_affinity_print_mask(). @@ -1402,19 +1404,9 @@ extern void __kmp_query_cpuid(kmp_cpuinfo_t *p); // subleaf is only needed for cache and topology discovery and can be set to // zero in most cases static inline void __kmp_x86_cpuid(int leaf, int subleaf, struct kmp_cpuid *p) { -#if KMP_ARCH_X86 && (defined(__pic__) || defined(__PIC__)) - // on i386 arch, the ebx reg. is used by pic, thus we need to preserve from - // being trashed beforehand - __asm__ __volatile__("mov %%ebx, %%edi\n" - "cpuid\n" - "xchg %%edi, %%ebx\n" - : "=a"(p->eax), "=b"(p->ebx), "=c"(p->ecx), "=d"(p->edx) - : "a"(leaf), "c"(subleaf)); -#else __asm__ __volatile__("cpuid" : "=a"(p->eax), "=b"(p->ebx), "=c"(p->ecx), "=d"(p->edx) : "a"(leaf), "c"(subleaf)); -#endif } // Load p into FPU control word static inline void __kmp_load_x87_fpu_control_word(const kmp_int16 *p) { @@ -3920,7 +3912,8 @@ extern void __kmp_balanced_affinity(kmp_info_t *th, int team_size); #if KMP_WEIGHTED_ITERATIONS_SUPPORTED extern int __kmp_get_first_osid_with_ecore(void); #endif -#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY +#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY || \ + KMP_OS_AIX extern int kmp_set_thread_affinity_mask_initial(void); #endif static inline void __kmp_assign_root_init_mask() { diff --git a/openmp/runtime/src/kmp_affinity.cpp b/openmp/runtime/src/kmp_affinity.cpp index c3ee4de75a237a3d498cf4c0fddc1ed9b3e5eae1..b574dbbaf54f3d49d14d2d6bbee659b75130c39f 100644 --- a/openmp/runtime/src/kmp_affinity.cpp +++ b/openmp/runtime/src/kmp_affinity.cpp @@ -327,6 +327,9 @@ void kmp_topology_t::_insert_windows_proc_groups() { KMP_CPU_FREE(mask); _insert_layer(KMP_HW_PROC_GROUP, ids); __kmp_free(ids); + + // sort topology after adding proc groups + __kmp_topology->sort_ids(); } #endif @@ -2907,12 +2910,17 @@ static inline const char *__kmp_cpuinfo_get_envvar() { } // Parse /proc/cpuinfo (or an alternate file in the same format) to obtain the -// affinity map. +// affinity map. On AIX, the map is obtained through system SRAD (Scheduler +// Resource Allocation Domain). static bool __kmp_affinity_create_cpuinfo_map(int *line, kmp_i18n_id_t *const msg_id) { + *msg_id = kmp_i18n_null; + +#if KMP_OS_AIX + unsigned num_records = __kmp_xproc; +#else const char *filename = __kmp_cpuinfo_get_filename(); const char *envvar = __kmp_cpuinfo_get_envvar(); - *msg_id = kmp_i18n_null; if (__kmp_affinity.flags.verbose) { KMP_INFORM(AffParseFilename, "KMP_AFFINITY", filename); @@ -2971,6 +2979,7 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line, *msg_id = kmp_i18n_str_CantRewindCpuinfo; return false; } +#endif // KMP_OS_AIX // Allocate the array of records to store the proc info in. The dummy // element at the end makes the logic in filling them out easier to code. @@ -3000,6 +3009,99 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line, INIT_PROC_INFO(threadInfo[i]); } +#if KMP_OS_AIX + int smt_threads; + lpar_info_format1_t cpuinfo; + unsigned num_avail = __kmp_xproc; + + if (__kmp_affinity.flags.verbose) + KMP_INFORM(AffParseFilename, "KMP_AFFINITY", "system info for topology"); + + // Get the number of SMT threads per core. + int retval = + lpar_get_info(LPAR_INFO_FORMAT1, &cpuinfo, sizeof(lpar_info_format1_t)); + if (!retval) + smt_threads = cpuinfo.smt_threads; + else { + CLEANUP_THREAD_INFO; + *msg_id = kmp_i18n_str_UnknownTopology; + return false; + } + + // Allocate a resource set containing available system resourses. + rsethandle_t sys_rset = rs_alloc(RS_SYSTEM); + if (sys_rset == NULL) { + CLEANUP_THREAD_INFO; + *msg_id = kmp_i18n_str_UnknownTopology; + return false; + } + // Allocate a resource set for the SRAD info. + rsethandle_t srad = rs_alloc(RS_EMPTY); + if (srad == NULL) { + rs_free(sys_rset); + CLEANUP_THREAD_INFO; + *msg_id = kmp_i18n_str_UnknownTopology; + return false; + } + + // Get the SRAD system detail level. + int sradsdl = rs_getinfo(NULL, R_SRADSDL, 0); + if (sradsdl < 0) { + rs_free(sys_rset); + rs_free(srad); + CLEANUP_THREAD_INFO; + *msg_id = kmp_i18n_str_UnknownTopology; + return false; + } + // Get the number of RADs at that SRAD SDL. + int num_rads = rs_numrads(sys_rset, sradsdl, 0); + if (num_rads < 0) { + rs_free(sys_rset); + rs_free(srad); + CLEANUP_THREAD_INFO; + *msg_id = kmp_i18n_str_UnknownTopology; + return false; + } + + // Get the maximum number of procs that may be contained in a resource set. + int max_procs = rs_getinfo(NULL, R_MAXPROCS, 0); + if (max_procs < 0) { + rs_free(sys_rset); + rs_free(srad); + CLEANUP_THREAD_INFO; + *msg_id = kmp_i18n_str_UnknownTopology; + return false; + } + + int cur_rad = 0; + int num_set = 0; + for (int srad_idx = 0; cur_rad < num_rads && srad_idx < VMI_MAXRADS; + ++srad_idx) { + // Check if the SRAD is available in the RSET. + if (rs_getrad(sys_rset, srad, sradsdl, srad_idx, 0) < 0) + continue; + + for (int cpu = 0; cpu < max_procs; cpu++) { + // Set the info for the cpu if it is in the SRAD. + if (rs_op(RS_TESTRESOURCE, srad, NULL, R_PROCS, cpu)) { + threadInfo[cpu][osIdIndex] = cpu; + threadInfo[cpu][pkgIdIndex] = cur_rad; + threadInfo[cpu][coreIdIndex] = cpu / smt_threads; + ++num_set; + if (num_set >= num_avail) { + // Done if all available CPUs have been set. + break; + } + } + } + ++cur_rad; + } + rs_free(sys_rset); + rs_free(srad); + + // The topology is already sorted. + +#else // !KMP_OS_AIX unsigned num_avail = 0; *line = 0; #if KMP_ARCH_S390X @@ -3247,6 +3349,8 @@ static bool __kmp_affinity_create_cpuinfo_map(int *line, qsort(threadInfo, num_avail, sizeof(*threadInfo), __kmp_affinity_cmp_ProcCpuInfo_phys_id); +#endif // KMP_OS_AIX + // The table is now sorted by pkgId / coreId / threadId, but we really don't // know the radix of any of the fields. pkgId's may be sparsely assigned among // the chips on a system. Although coreId's are usually assigned @@ -4442,7 +4546,7 @@ static bool __kmp_aux_affinity_initialize_topology(kmp_affinity_t &affinity) { } #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */ -#if KMP_OS_LINUX +#if KMP_OS_LINUX || KMP_OS_AIX if (!success) { int line = 0; success = __kmp_affinity_create_cpuinfo_map(&line, &msg_id); @@ -4838,7 +4942,12 @@ void __kmp_affinity_uninitialize(void) { } if (__kmp_affin_origMask != NULL) { if (KMP_AFFINITY_CAPABLE()) { +#if KMP_OS_AIX + // Uninitialize by unbinding the thread. + bindprocessor(BINDTHREAD, thread_self(), PROCESSOR_CLASS_ANY); +#else __kmp_set_system_affinity(__kmp_affin_origMask, FALSE); +#endif } KMP_CPU_FREE(__kmp_affin_origMask); __kmp_affin_origMask = NULL; @@ -5012,7 +5121,10 @@ void __kmp_affinity_bind_init_mask(int gtid) { __kmp_set_system_affinity(th->th.th_affin_mask, FALSE); } else #endif +#ifndef KMP_OS_AIX + // Do not set the full mask as the init mask on AIX. __kmp_set_system_affinity(th->th.th_affin_mask, TRUE); +#endif } void __kmp_affinity_bind_place(int gtid) { @@ -5125,7 +5237,7 @@ int __kmp_aux_set_affinity(void **mask) { int __kmp_aux_get_affinity(void **mask) { int gtid; int retval; -#if KMP_OS_WINDOWS || KMP_DEBUG +#if KMP_OS_WINDOWS || KMP_OS_AIX || KMP_DEBUG kmp_info_t *th; #endif if (!KMP_AFFINITY_CAPABLE()) { @@ -5133,7 +5245,7 @@ int __kmp_aux_get_affinity(void **mask) { } gtid = __kmp_entry_gtid(); -#if KMP_OS_WINDOWS || KMP_DEBUG +#if KMP_OS_WINDOWS || KMP_OS_AIX || KMP_DEBUG th = __kmp_threads[gtid]; #else (void)gtid; // unused variable @@ -5156,7 +5268,7 @@ int __kmp_aux_get_affinity(void **mask) { } } -#if !KMP_OS_WINDOWS +#if !KMP_OS_WINDOWS && !KMP_OS_AIX retval = __kmp_get_system_affinity((kmp_affin_mask_t *)(*mask), FALSE); KA_TRACE( @@ -5176,7 +5288,7 @@ int __kmp_aux_get_affinity(void **mask) { KMP_CPU_COPY((kmp_affin_mask_t *)(*mask), th->th.th_affin_mask); return 0; -#endif /* KMP_OS_WINDOWS */ +#endif /* !KMP_OS_WINDOWS && !KMP_OS_AIX */ } int __kmp_aux_get_affinity_max_proc() { @@ -5558,7 +5670,8 @@ void __kmp_balanced_affinity(kmp_info_t *th, int nthreads) { } } -#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY +#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY || \ + KMP_OS_AIX // We don't need this entry for Windows because // there is GetProcessAffinityMask() api // @@ -5593,7 +5706,11 @@ extern "C" "set full mask for thread %d\n", gtid)); KMP_DEBUG_ASSERT(__kmp_affin_fullMask != NULL); +#if KMP_OS_AIX + return bindprocessor(BINDTHREAD, thread_self(), PROCESSOR_CLASS_ANY); +#else return __kmp_set_system_affinity(__kmp_affin_fullMask, FALSE); +#endif } #endif diff --git a/openmp/runtime/src/kmp_affinity.h b/openmp/runtime/src/kmp_affinity.h index 1c7db2f59943f8c33cb1e3619b6c7804a7df9720..7efc090f8863d9434261e9545ce120fbcad4795f 100644 --- a/openmp/runtime/src/kmp_affinity.h +++ b/openmp/runtime/src/kmp_affinity.h @@ -191,7 +191,8 @@ public: }; #endif /* KMP_USE_HWLOC */ -#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY +#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY || \ + KMP_OS_AIX #if KMP_OS_LINUX /* On some of the older OS's that we build on, these constants aren't present in <asm/unistd.h> #included from <sys.syscall.h>. They must be the same on @@ -317,6 +318,10 @@ public: #elif KMP_OS_NETBSD #include <pthread.h> #include <sched.h> +#elif KMP_OS_AIX +#include <sys/dr.h> +#include <sys/rset.h> +#define VMI_MAXRADS 64 // Maximum number of RADs allowed by AIX. #endif class KMPNativeAffinity : public KMPAffinity { class Mask : public KMPAffinity::Mask { @@ -404,6 +409,70 @@ class KMPNativeAffinity : public KMPAffinity { ++retval; return retval; } +#if KMP_OS_AIX + // On AIX, we don't have a way to get CPU(s) a thread is bound to. + // This routine is only used to get the full mask. + int get_system_affinity(bool abort_on_error) override { + KMP_ASSERT2(KMP_AFFINITY_CAPABLE(), + "Illegal get affinity operation when not capable"); + + (void)abort_on_error; + + // Set the mask with all CPUs that are available. + for (int i = 0; i < __kmp_xproc; ++i) + KMP_CPU_SET(i, this); + return 0; + } + int set_system_affinity(bool abort_on_error) const override { + KMP_ASSERT2(KMP_AFFINITY_CAPABLE(), + + "Illegal set affinity operation when not capable"); + + int location; + int gtid = __kmp_entry_gtid(); + int tid = thread_self(); + + // Unbind the thread if it was bound to any processors before so that + // we can bind the thread to CPUs specified by the mask not others. + int retval = bindprocessor(BINDTHREAD, tid, PROCESSOR_CLASS_ANY); + + // On AIX, we can only bind to one instead of a set of CPUs with the + // bindprocessor() system call. + KMP_CPU_SET_ITERATE(location, this) { + if (KMP_CPU_ISSET(location, this)) { + retval = bindprocessor(BINDTHREAD, tid, location); + if (retval == -1 && errno == 1) { + rsid_t rsid; + rsethandle_t rsh; + // Put something in rsh to prevent compiler warning + // about uninitalized use + rsh = rs_alloc(RS_EMPTY); + rsid.at_pid = getpid(); + if (RS_DEFAULT_RSET != ra_getrset(R_PROCESS, rsid, 0, rsh)) { + retval = ra_detachrset(R_PROCESS, rsid, 0); + retval = bindprocessor(BINDTHREAD, tid, location); + } + } + if (retval == 0) { + KA_TRACE(10, ("__kmp_set_system_affinity: Done binding " + "T#%d to cpu=%d.\n", + gtid, location)); + continue; + } + int error = errno; + if (abort_on_error) { + __kmp_fatal(KMP_MSG(FunctionError, "bindprocessor()"), + KMP_ERR(error), __kmp_msg_null); + KA_TRACE(10, ("__kmp_set_system_affinity: Error binding " + "T#%d to cpu=%d, errno=%d.\n", + gtid, location, error)); + return error; + } + } + } + return 0; + } +#else // !KMP_OS_AIX int get_system_affinity(bool abort_on_error) override { KMP_ASSERT2(KMP_AFFINITY_CAPABLE(), "Illegal get affinity operation when not capable"); @@ -446,6 +515,7 @@ class KMPNativeAffinity : public KMPAffinity { } return error; } +#endif // KMP_OS_AIX }; void determine_capable(const char *env_var) override { __kmp_affinity_determine_capable(env_var); @@ -475,7 +545,7 @@ class KMPNativeAffinity : public KMPAffinity { api_type get_api_type() const override { return NATIVE_OS; } }; #endif /* KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY \ - */ + || KMP_OS_AIX */ #if KMP_OS_WINDOWS class KMPNativeAffinity : public KMPAffinity { diff --git a/openmp/runtime/src/kmp_collapse.cpp b/openmp/runtime/src/kmp_collapse.cpp index 569d2c1508319daf64a815888ae8bf1d4e2365a5..f1bf04901dc7b711ddf00e4b2ee59e9d0aa7eb11 100644 --- a/openmp/runtime/src/kmp_collapse.cpp +++ b/openmp/runtime/src/kmp_collapse.cpp @@ -1482,8 +1482,8 @@ void kmp_handle_upper_triangle_matrix( original_bounds_nest[0].ub0_u64); kmp_uint64 outer_lb0 = kmp_fix_iv(original_bounds_nest[0].loop_iv_type, original_bounds_nest[0].lb0_u64); - kmp_uint64 inner_ub0 = kmp_fix_iv(original_bounds_nest[1].loop_iv_type, - original_bounds_nest[1].ub0_u64); + [[maybe_unused]] kmp_uint64 inner_ub0 = kmp_fix_iv( + original_bounds_nest[1].loop_iv_type, original_bounds_nest[1].ub0_u64); // calculate the chunk's lower and upper bounds // the total number of iterations in the loop is the sum of the arithmetic // progression from the outer lower to outer upper bound (inclusive since the @@ -1517,16 +1517,11 @@ void kmp_handle_upper_triangle_matrix( kmp_uint64 iter_with_current = iter_before_current + iter_current; // calculate the outer loop lower bound (lbo) which is the max outer iv value // that gives the number of iterations that is equal or just below the total - // number of iterations executed by the previous threads, for less_than - // (1-based) inner loops (inner_ub0 == -1) it will be i.e. - // lbo*(lbo-1)/2<=iter_before_current => lbo^2-lbo-2*iter_before_current<=0 - // for less_than_equal (0-based) inner loops (inner_ub == 0) it will be: - // i.e. lbo*(lbo+1)/2<=iter_before_current => - // lbo^2+lbo-2*iter_before_current<=0 both cases can be handled similarily - // using a parameter to control the equatio sign + // number of iterations executed by the previous threads: + // lbo*(lbo+1)/2<=iter_before_current => + // lbo^2+lbo-2*iter_before_current<=0 kmp_uint64 lower_bound_outer = (kmp_uint64)(sqrt_newton_approx(1 + 8 * iter_before_current) + 1) / 2 - 1; - ; // calculate the inner loop lower bound which is the remaining number of // iterations required to hit the total number of iterations executed by the // previous threads giving the starting point of this thread diff --git a/openmp/runtime/src/kmp_csupport.cpp b/openmp/runtime/src/kmp_csupport.cpp index 878e78b5c7ad2de2d5e15a61c0ea130086bc6869..0268f692ff7fdc6fcf2673a5461e4961a7441c15 100644 --- a/openmp/runtime/src/kmp_csupport.cpp +++ b/openmp/runtime/src/kmp_csupport.cpp @@ -18,6 +18,7 @@ #include "kmp_itt.h" #include "kmp_lock.h" #include "kmp_stats.h" +#include "kmp_utils.h" #include "ompt-specific.h" #define MAX_MESSAGE 512 @@ -4233,7 +4234,7 @@ void __kmpc_doacross_wait(ident_t *loc, int gtid, const kmp_int64 *vec) { up = pr_buf->th_doacross_info[3]; st = pr_buf->th_doacross_info[4]; #if OMPT_SUPPORT && OMPT_OPTIONAL - ompt_dependence_t deps[num_dims]; + SimpleVLA<ompt_dependence_t> deps(num_dims); #endif if (st == 1) { // most common case if (vec[0] < lo || vec[0] > up) { @@ -4345,7 +4346,7 @@ void __kmpc_doacross_post(ident_t *loc, int gtid, const kmp_int64 *vec) { lo = pr_buf->th_doacross_info[2]; st = pr_buf->th_doacross_info[4]; #if OMPT_SUPPORT && OMPT_OPTIONAL - ompt_dependence_t deps[num_dims]; + SimpleVLA<ompt_dependence_t> deps(num_dims); #endif if (st == 1) { // most common case iter_number = vec[0] - lo; diff --git a/openmp/runtime/src/kmp_gsupport.cpp b/openmp/runtime/src/kmp_gsupport.cpp index 4dc8a90f83b4eabef81459211ee5caee61e778e8..86cf16470e14b2c6be4849b75c051c7f4f65e397 100644 --- a/openmp/runtime/src/kmp_gsupport.cpp +++ b/openmp/runtime/src/kmp_gsupport.cpp @@ -358,7 +358,7 @@ void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_ORDERED_END)(void) { // (IA-32 architecture) or 64-bit signed (Intel(R) 64). #if KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS || KMP_ARCH_WASM || \ - KMP_ARCH_PPC + KMP_ARCH_PPC || KMP_ARCH_AARCH64_32 #define KMP_DISPATCH_INIT __kmp_aux_dispatch_init_4 #define KMP_DISPATCH_FINI_CHUNK __kmp_aux_dispatch_fini_chunk_4 #define KMP_DISPATCH_NEXT __kmpc_dispatch_next_4 diff --git a/openmp/runtime/src/kmp_os.h b/openmp/runtime/src/kmp_os.h index 63da9e5fa15d1cc408efc024abe4485fd76a88db..24b40ed32d988a89965d6b40c8f76fe22e65a510 100644 --- a/openmp/runtime/src/kmp_os.h +++ b/openmp/runtime/src/kmp_os.h @@ -76,7 +76,7 @@ #endif #if (KMP_OS_LINUX || KMP_OS_WINDOWS || KMP_OS_FREEBSD || KMP_OS_NETBSD || \ - KMP_OS_DRAGONFLY) && \ + KMP_OS_DRAGONFLY || KMP_OS_AIX) && \ !KMP_OS_WASI #define KMP_AFFINITY_SUPPORTED 1 #if KMP_OS_WINDOWS && KMP_ARCH_X86_64 @@ -179,7 +179,7 @@ typedef unsigned long long kmp_uint64; #endif /* KMP_OS_UNIX */ #if KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS || KMP_ARCH_WASM || \ - KMP_ARCH_PPC + KMP_ARCH_PPC || KMP_ARCH_AARCH64_32 #define KMP_SIZE_T_SPEC KMP_UINT32_SPEC #elif KMP_ARCH_X86_64 || KMP_ARCH_PPC64 || KMP_ARCH_AARCH64 || \ KMP_ARCH_MIPS64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 || \ @@ -1051,7 +1051,7 @@ extern kmp_real64 __kmp_xchg_real64(volatile kmp_real64 *p, kmp_real64 v); #if KMP_ARCH_PPC64 || KMP_ARCH_ARM || KMP_ARCH_AARCH64 || KMP_ARCH_MIPS || \ KMP_ARCH_MIPS64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 || \ - KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_PPC + KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_PPC || KMP_ARCH_AARCH64_32 #if KMP_OS_WINDOWS #undef KMP_MB #define KMP_MB() std::atomic_thread_fence(std::memory_order_seq_cst) diff --git a/openmp/runtime/src/kmp_platform.h b/openmp/runtime/src/kmp_platform.h index c06f46db2d496535491b51337cffe9f3eef8eda5..200fdf697dd0e90689207552b82039e8895a1e22 100644 --- a/openmp/runtime/src/kmp_platform.h +++ b/openmp/runtime/src/kmp_platform.h @@ -105,6 +105,7 @@ #define KMP_ARCH_X86 0 #define KMP_ARCH_X86_64 0 #define KMP_ARCH_AARCH64 0 +#define KMP_ARCH_AARCH64_32 0 #define KMP_ARCH_PPC64_ELFv1 0 #define KMP_ARCH_PPC64_ELFv2 0 #define KMP_ARCH_PPC64_XCOFF 0 @@ -157,6 +158,9 @@ #define KMP_ARCH_PPC_XCOFF 1 #undef KMP_ARCH_PPC #define KMP_ARCH_PPC 1 +#elif defined __ARM64_ARCH_8_32__ +#undef KMP_ARCH_AARCH64_32 +#define KMP_ARCH_AARCH64_32 1 #elif defined __aarch64__ #undef KMP_ARCH_AARCH64 #define KMP_ARCH_AARCH64 1 @@ -244,7 +248,7 @@ /* Specify 32 bit architectures here */ #define KMP_32_BIT_ARCH \ (KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_MIPS || KMP_ARCH_WASM || \ - KMP_ARCH_PPC) + KMP_ARCH_PPC || KMP_ARCH_AARCH64_32) // Platforms which support Intel(R) Many Integrated Core Architecture #define KMP_MIC_SUPPORTED \ @@ -254,7 +258,8 @@ #if (1 != KMP_ARCH_X86 + KMP_ARCH_X86_64 + KMP_ARCH_ARM + KMP_ARCH_PPC64 + \ KMP_ARCH_AARCH64 + KMP_ARCH_MIPS + KMP_ARCH_MIPS64 + \ KMP_ARCH_RISCV64 + KMP_ARCH_LOONGARCH64 + KMP_ARCH_VE + \ - KMP_ARCH_S390X + KMP_ARCH_WASM + KMP_ARCH_PPC) + KMP_ARCH_S390X + KMP_ARCH_WASM + KMP_ARCH_PPC + \ + KMP_ARCH_AARCH64_32) #error Unknown or unsupported architecture #endif diff --git a/openmp/runtime/src/kmp_runtime.cpp b/openmp/runtime/src/kmp_runtime.cpp index a60bdb968371e07f6265c0f9ca21b5d76f1e629e..95acf4dff4cbce113b82c5466bca15ba6dfaa772 100644 --- a/openmp/runtime/src/kmp_runtime.cpp +++ b/openmp/runtime/src/kmp_runtime.cpp @@ -4431,8 +4431,10 @@ kmp_info_t *__kmp_allocate_thread(kmp_root_t *root, kmp_team_t *team, #endif KMP_MB(); - /* first, try to get one from the thread pool */ - if (__kmp_thread_pool) { + /* first, try to get one from the thread pool unless allocating thread is + * the main hidden helper thread. The hidden helper team should always + * allocate new OS threads. */ + if (__kmp_thread_pool && !KMP_HIDDEN_HELPER_TEAM(team)) { new_thr = CCAST(kmp_info_t *, __kmp_thread_pool); __kmp_thread_pool = (volatile kmp_info_t *)new_thr->th.th_next_pool; if (new_thr == __kmp_thread_pool_insert_pt) { @@ -4497,7 +4499,7 @@ kmp_info_t *__kmp_allocate_thread(kmp_root_t *root, kmp_team_t *team, } /* no, well fork a new one */ - KMP_ASSERT(__kmp_nth == __kmp_all_nth); + KMP_ASSERT(KMP_HIDDEN_HELPER_TEAM(team) || __kmp_nth == __kmp_all_nth); KMP_ASSERT(__kmp_all_nth < __kmp_threads_capacity); #if KMP_USE_MONITOR @@ -6752,11 +6754,11 @@ void __kmp_register_library_startup(void) { int fd1 = -1; shm_name = __kmp_str_format("/%s", name); int shm_preexist = 0; - fd1 = shm_open(shm_name, O_CREAT | O_EXCL | O_RDWR, 0666); + fd1 = shm_open(shm_name, O_CREAT | O_EXCL | O_RDWR, 0600); if ((fd1 == -1) && (errno == EEXIST)) { // file didn't open because it already exists. // try opening existing file - fd1 = shm_open(shm_name, O_RDWR, 0666); + fd1 = shm_open(shm_name, O_RDWR, 0600); if (fd1 == -1) { // file didn't open KMP_WARNING(FunctionError, "Can't open SHM"); __kmp_shm_available = false; @@ -6800,11 +6802,11 @@ void __kmp_register_library_startup(void) { int fd1 = -1; temp_reg_status_file_name = __kmp_str_format("/tmp/%s", name); int tmp_preexist = 0; - fd1 = open(temp_reg_status_file_name, O_CREAT | O_EXCL | O_RDWR, 0666); + fd1 = open(temp_reg_status_file_name, O_CREAT | O_EXCL | O_RDWR, 0600); if ((fd1 == -1) && (errno == EEXIST)) { // file didn't open because it already exists. // try opening existing file - fd1 = open(temp_reg_status_file_name, O_RDWR, 0666); + fd1 = open(temp_reg_status_file_name, O_RDWR, 0600); if (fd1 == -1) { // file didn't open if (fd1 == -1) { KMP_WARNING(FunctionError, "Can't open TEMP"); __kmp_tmp_available = false; @@ -6944,7 +6946,7 @@ void __kmp_unregister_library(void) { int fd1; if (__kmp_shm_available) { shm_name = __kmp_str_format("/%s", name); - fd1 = shm_open(shm_name, O_RDONLY, 0666); + fd1 = shm_open(shm_name, O_RDONLY, 0600); if (fd1 != -1) { // File opened successfully char *data1 = (char *)mmap(0, SHM_SIZE, PROT_READ, MAP_SHARED, fd1, 0); if (data1 != MAP_FAILED) { @@ -8924,7 +8926,7 @@ __kmp_determine_reduction_method( // KMP_OS_SOLARIS || KMP_OS_WASI || KMP_OS_AIX #elif KMP_ARCH_X86 || KMP_ARCH_ARM || KMP_ARCH_AARCH || KMP_ARCH_MIPS || \ - KMP_ARCH_WASM || KMP_ARCH_PPC + KMP_ARCH_WASM || KMP_ARCH_PPC || KMP_ARCH_AARCH64_32 #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \ KMP_OS_OPENBSD || KMP_OS_WINDOWS || KMP_OS_HURD || KMP_OS_SOLARIS || \ diff --git a/openmp/runtime/src/kmp_taskdeps.cpp b/openmp/runtime/src/kmp_taskdeps.cpp index f7529481393f9785ec0d20ed2bd152ed78c9bfd2..e575ad8b08a55f600c167e52d9ac3cc50700e456 100644 --- a/openmp/runtime/src/kmp_taskdeps.cpp +++ b/openmp/runtime/src/kmp_taskdeps.cpp @@ -1030,6 +1030,12 @@ void __kmpc_omp_taskwait_deps_51(ident_t *loc_ref, kmp_int32 gtid, __kmp_task_stealing_constraint); } + // Wait until the last __kmp_release_deps is finished before we free the + // current stack frame holding the "node" variable; once its nrefs count + // reaches 1, we're sure nobody else can try to reference it again. + while (node.dn.nrefs > 1) + KMP_YIELD(TRUE); + #if OMPT_SUPPORT __ompt_taskwait_dep_finish(current_task, taskwait_task_data); #endif /* OMPT_SUPPORT */ diff --git a/openmp/runtime/src/kmp_tasking.cpp b/openmp/runtime/src/kmp_tasking.cpp index 155e17ba7ec8740a017e5b0b8500fd2dcc555fa4..6303bb0d63f0f40cbe8f42c3d66e0c3fabef28eb 100644 --- a/openmp/runtime/src/kmp_tasking.cpp +++ b/openmp/runtime/src/kmp_tasking.cpp @@ -3219,7 +3219,7 @@ static kmp_task_t *__kmp_remove_my_task(kmp_info_t *thread, kmp_int32 gtid, // __kmp_steal_task: remove a task from another thread's deque // Assume that calling thread has already checked existence of // task_team thread_data before calling this routine. -static kmp_task_t *__kmp_steal_task(kmp_info_t *victim_thr, kmp_int32 gtid, +static kmp_task_t *__kmp_steal_task(kmp_int32 victim_tid, kmp_int32 gtid, kmp_task_team_t *task_team, std::atomic<kmp_int32> *unfinished_threads, int *thread_finished, @@ -3229,15 +3229,18 @@ static kmp_task_t *__kmp_steal_task(kmp_info_t *victim_thr, kmp_int32 gtid, kmp_taskdata_t *current; kmp_thread_data_t *victim_td, *threads_data; kmp_int32 target; - kmp_int32 victim_tid; + kmp_info_t *victim_thr; KMP_DEBUG_ASSERT(__kmp_tasking_mode != tskm_immediate_exec); threads_data = task_team->tt.tt_threads_data; KMP_DEBUG_ASSERT(threads_data != NULL); // Caller should check this condition + KMP_DEBUG_ASSERT(victim_tid >= 0); + KMP_DEBUG_ASSERT(victim_tid < task_team->tt.tt_nproc); - victim_tid = victim_thr->th.th_info.ds.ds_tid; victim_td = &threads_data[victim_tid]; + victim_thr = victim_td->td.td_thr; + (void)victim_thr; // Use in TRACE messages which aren't always enabled. KA_TRACE(10, ("__kmp_steal_task(enter): T#%d try to steal from T#%d: " "task_team=%p ntasks=%d head=%u tail=%u\n", @@ -3452,9 +3455,9 @@ static inline int __kmp_execute_tasks_template( if (!asleep) { // We have a victim to try to steal from - task = __kmp_steal_task(other_thread, gtid, task_team, - unfinished_threads, thread_finished, - is_constrained); + task = + __kmp_steal_task(victim_tid, gtid, task_team, unfinished_threads, + thread_finished, is_constrained); } if (task != NULL) { // set last stolen to victim if (threads_data[tid].td.td_deque_last_stolen != victim_tid) { diff --git a/openmp/runtime/src/z_Linux_asm.S b/openmp/runtime/src/z_Linux_asm.S index 14987c298fa5f96b9c35b587aafb97586ede6dfc..201949003c014c8531ac1744ff16e08686124611 100644 --- a/openmp/runtime/src/z_Linux_asm.S +++ b/openmp/runtime/src/z_Linux_asm.S @@ -108,7 +108,7 @@ KMP_PREFIX_UNDERSCORE(\proc): # endif // KMP_OS_DARWIN #endif // KMP_ARCH_X86 || KMP_ARCH_x86_64 -#if (KMP_OS_LINUX || KMP_OS_DARWIN || KMP_OS_WINDOWS) && (KMP_ARCH_AARCH64 || KMP_ARCH_ARM) +#if (KMP_OS_LINUX || KMP_OS_DARWIN || KMP_OS_WINDOWS) && (KMP_ARCH_AARCH64 || KMP_ARCH_AARCH64_32 || KMP_ARCH_ARM) # if KMP_OS_DARWIN # define KMP_PREFIX_UNDERSCORE(x) _##x // extra underscore for OS X* symbols @@ -176,7 +176,7 @@ KMP_PREFIX_UNDERSCORE(\proc): .endm # endif // KMP_OS_DARWIN -#endif // (KMP_OS_LINUX || KMP_OS_DARWIN || KMP_OS_WINDOWS) && (KMP_ARCH_AARCH64 || KMP_ARCH_ARM) +#endif // (KMP_OS_LINUX || KMP_OS_DARWIN || KMP_OS_WINDOWS) && (KMP_ARCH_AARCH64 || KMP_ARCH_AARCH64_32 || KMP_ARCH_ARM) .macro COMMON name, size, align_power #if KMP_OS_DARWIN @@ -1236,7 +1236,7 @@ KMP_LABEL(kmp_1_exit): #endif /* KMP_ARCH_X86_64 */ // ' -#if (KMP_OS_LINUX || KMP_OS_DARWIN || KMP_OS_WINDOWS) && KMP_ARCH_AARCH64 +#if (KMP_OS_LINUX || KMP_OS_DARWIN || KMP_OS_WINDOWS) && (KMP_ARCH_AARCH64 || KMP_ARCH_AARCH64_32) //------------------------------------------------------------------------ // int @@ -1360,7 +1360,7 @@ KMP_LABEL(kmp_1): DEBUG_INFO __kmp_invoke_microtask // -- End __kmp_invoke_microtask -#endif /* (KMP_OS_LINUX || KMP_OS_DARWIN || KMP_OS_WINDOWS) && KMP_ARCH_AARCH64 */ +#endif /* (KMP_OS_LINUX || KMP_OS_DARWIN || KMP_OS_WINDOWS) && (KMP_ARCH_AARCH64 || KMP_ARCH_AARCH64_32) */ #if (KMP_OS_LINUX || KMP_OS_DARWIN || KMP_OS_WINDOWS) && KMP_ARCH_ARM @@ -1505,7 +1505,7 @@ KMP_LABEL(kmp_1): DEBUG_INFO __kmp_invoke_microtask // -- End __kmp_invoke_microtask -#endif /* (KMP_OS_LINUX || KMP_OS_DARWIN || KMP_OS_WINDOWS) && KMP_ARCH_AARCH64 */ +#endif /* (KMP_OS_LINUX || KMP_OS_DARWIN || KMP_OS_WINDOWS) && KMP_ARCH_ARM */ #if KMP_ARCH_PPC64 @@ -2405,18 +2405,21 @@ __kmp_invoke_microtask: #endif /* KMP_ARCH_S390X */ -#if KMP_ARCH_ARM || KMP_ARCH_MIPS +#if KMP_ARCH_ARM || KMP_ARCH_MIPS || KMP_ARCH_AARCH64_32 +#ifndef KMP_PREFIX_UNDERSCORE +# define KMP_PREFIX_UNDERSCORE(x) x +#endif .data COMMON .gomp_critical_user_, 32, 3 .data .align 4 - .global __kmp_unnamed_critical_addr -__kmp_unnamed_critical_addr: + .global KMP_PREFIX_UNDERSCORE(__kmp_unnamed_critical_addr) +KMP_PREFIX_UNDERSCORE(__kmp_unnamed_critical_addr): .4byte .gomp_critical_user_ #ifdef __ELF__ - .size __kmp_unnamed_critical_addr,4 + .size KMP_PREFIX_UNDERSCORE(__kmp_unnamed_critical_addr),4 #endif -#endif /* KMP_ARCH_ARM */ +#endif /* KMP_ARCH_ARM || KMP_ARCH_MIPS || KMP_ARCH_AARCH64_32 */ #if KMP_ARCH_PPC64 || KMP_ARCH_AARCH64 || KMP_ARCH_MIPS64 || \ KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 || KMP_ARCH_VE || \ diff --git a/openmp/runtime/src/z_Linux_util.cpp b/openmp/runtime/src/z_Linux_util.cpp index 3f831d6e2a8f9d846cca1959f2a0746ab1bc9647..be47be0dcec2af98e77767aa209da2be85ea6bfe 100644 --- a/openmp/runtime/src/z_Linux_util.cpp +++ b/openmp/runtime/src/z_Linux_util.cpp @@ -125,7 +125,8 @@ static void __kmp_print_cond(char *buffer, kmp_cond_align_t *cond) { } #endif -#if ((KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY) && \ +#if ((KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY || \ + KMP_OS_AIX) && \ KMP_AFFINITY_SUPPORTED) /* Affinity support */ @@ -142,6 +143,29 @@ void __kmp_affinity_bind_thread(int which) { KMP_CPU_FREE_FROM_STACK(mask); } +#if KMP_OS_AIX +void __kmp_affinity_determine_capable(const char *env_var) { + // All versions of AIX support bindprocessor(). + + size_t mask_size = __kmp_xproc / CHAR_BIT; + // Round up to byte boundary. + if (__kmp_xproc % CHAR_BIT) + ++mask_size; + + // Round up to the mask_size_type boundary. + if (mask_size % sizeof(__kmp_affin_mask_size)) + mask_size += sizeof(__kmp_affin_mask_size) - + mask_size % sizeof(__kmp_affin_mask_size); + KMP_AFFINITY_ENABLE(mask_size); + KA_TRACE(10, + ("__kmp_affinity_determine_capable: " + "AIX OS affinity interface bindprocessor functional (mask size = " + "%" KMP_SIZE_T_SPEC ").\n", + __kmp_affin_mask_size)); +} + +#else // !KMP_OS_AIX + /* Determine if we can access affinity functionality on this version of * Linux* OS by checking __NR_sched_{get,set}affinity system calls, and set * __kmp_affin_mask_size to the appropriate value (0 means not capable). */ @@ -271,8 +295,9 @@ void __kmp_affinity_determine_capable(const char *env_var) { KMP_WARNING(AffCantGetMaskSize, env_var); } } - -#endif // KMP_OS_LINUX && KMP_AFFINITY_SUPPORTED +#endif // KMP_OS_AIX +#endif // (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || \ + KMP_OS_DRAGONFLY || KMP_OS_AIX) && KMP_AFFINITY_SUPPORTED #if KMP_USE_FUTEX @@ -501,7 +526,7 @@ static void *__kmp_launch_worker(void *thr) { #endif /* KMP_BLOCK_SIGNALS */ void *exit_val; #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \ - KMP_OS_OPENBSD || KMP_OS_HURD || KMP_OS_SOLARIS + KMP_OS_OPENBSD || KMP_OS_HURD || KMP_OS_SOLARIS || KMP_OS_AIX void *volatile padding = 0; #endif int gtid; @@ -550,7 +575,7 @@ static void *__kmp_launch_worker(void *thr) { #endif /* KMP_BLOCK_SIGNALS */ #if KMP_OS_LINUX || KMP_OS_DRAGONFLY || KMP_OS_FREEBSD || KMP_OS_NETBSD || \ - KMP_OS_OPENBSD || KMP_OS_HURD || KMP_OS_SOLARIS + KMP_OS_OPENBSD || KMP_OS_HURD || KMP_OS_SOLARIS || KMP_OS_AIX if (__kmp_stkoffset > 0 && gtid > 0) { padding = KMP_ALLOCA(gtid * __kmp_stkoffset); (void)padding; @@ -1268,7 +1293,8 @@ static void __kmp_atfork_child(void) { ++__kmp_fork_count; #if KMP_AFFINITY_SUPPORTED -#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY +#if KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_NETBSD || KMP_OS_DRAGONFLY || \ + KMP_OS_AIX // reset the affinity in the child to the initial thread // affinity in the parent kmp_set_thread_affinity_mask_initial(); @@ -1863,21 +1889,8 @@ static int __kmp_get_xproc(void) { #elif KMP_OS_DARWIN - // Bug C77011 High "OpenMP Threads and number of active cores". - - // Find the number of available CPUs. - kern_return_t rc; - host_basic_info_data_t info; - mach_msg_type_number_t num = HOST_BASIC_INFO_COUNT; - rc = host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&info, &num); - if (rc == 0 && num == HOST_BASIC_INFO_COUNT) { - // Cannot use KA_TRACE() here because this code works before trace support - // is initialized. - r = info.avail_cpus; - } else { - KMP_WARNING(CantGetNumAvailCPU); - KMP_INFORM(AssumedNumCPU); - } + size_t len = sizeof(r); + sysctlbyname("hw.logicalcpu", &r, &len, NULL, 0); #else @@ -2325,6 +2338,7 @@ int __kmp_is_address_mapped(void *addr) { found = (int)addr < (__builtin_wasm_memory_size(0) * PAGESIZE); #elif KMP_OS_AIX + (void)rc; // FIXME(AIX): Implement this found = 1; @@ -2608,7 +2622,45 @@ finish: // Clean up and exit. #if !(KMP_ARCH_X86 || KMP_ARCH_X86_64 || KMP_MIC || \ ((KMP_OS_LINUX || KMP_OS_DARWIN) && KMP_ARCH_AARCH64) || \ KMP_ARCH_PPC64 || KMP_ARCH_RISCV64 || KMP_ARCH_LOONGARCH64 || \ - KMP_ARCH_ARM || KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_PPC_XCOFF) + KMP_ARCH_ARM || KMP_ARCH_VE || KMP_ARCH_S390X || KMP_ARCH_PPC_XCOFF || \ + KMP_ARCH_AARCH64_32) + +// Because WebAssembly will use `call_indirect` to invoke the microtask and +// WebAssembly indirect calls check that the called signature is a precise +// match, we need to cast each microtask function pointer back from `void *` to +// its original type. +typedef void (*microtask_t0)(int *, int *); +typedef void (*microtask_t1)(int *, int *, void *); +typedef void (*microtask_t2)(int *, int *, void *, void *); +typedef void (*microtask_t3)(int *, int *, void *, void *, void *); +typedef void (*microtask_t4)(int *, int *, void *, void *, void *, void *); +typedef void (*microtask_t5)(int *, int *, void *, void *, void *, void *, + void *); +typedef void (*microtask_t6)(int *, int *, void *, void *, void *, void *, + void *, void *); +typedef void (*microtask_t7)(int *, int *, void *, void *, void *, void *, + void *, void *, void *); +typedef void (*microtask_t8)(int *, int *, void *, void *, void *, void *, + void *, void *, void *, void *); +typedef void (*microtask_t9)(int *, int *, void *, void *, void *, void *, + void *, void *, void *, void *, void *); +typedef void (*microtask_t10)(int *, int *, void *, void *, void *, void *, + void *, void *, void *, void *, void *, void *); +typedef void (*microtask_t11)(int *, int *, void *, void *, void *, void *, + void *, void *, void *, void *, void *, void *, + void *); +typedef void (*microtask_t12)(int *, int *, void *, void *, void *, void *, + void *, void *, void *, void *, void *, void *, + void *, void *); +typedef void (*microtask_t13)(int *, int *, void *, void *, void *, void *, + void *, void *, void *, void *, void *, void *, + void *, void *, void *); +typedef void (*microtask_t14)(int *, int *, void *, void *, void *, void *, + void *, void *, void *, void *, void *, void *, + void *, void *, void *, void *); +typedef void (*microtask_t15)(int *, int *, void *, void *, void *, void *, + void *, void *, void *, void *, void *, void *, + void *, void *, void *, void *, void *); // we really only need the case with 1 argument, because CLANG always build // a struct of pointers to shared variables referenced in the outlined function @@ -2629,66 +2681,76 @@ int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc, fflush(stderr); exit(-1); case 0: - (*pkfn)(>id, &tid); + (*(microtask_t0)pkfn)(>id, &tid); break; case 1: - (*pkfn)(>id, &tid, p_argv[0]); + (*(microtask_t1)pkfn)(>id, &tid, p_argv[0]); break; case 2: - (*pkfn)(>id, &tid, p_argv[0], p_argv[1]); + (*(microtask_t2)pkfn)(>id, &tid, p_argv[0], p_argv[1]); break; case 3: - (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2]); + (*(microtask_t3)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2]); break; case 4: - (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3]); + (*(microtask_t4)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], + p_argv[3]); break; case 5: - (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4]); + (*(microtask_t5)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], + p_argv[3], p_argv[4]); break; case 6: - (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], - p_argv[5]); + (*(microtask_t6)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], + p_argv[3], p_argv[4], p_argv[5]); break; case 7: - (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], - p_argv[5], p_argv[6]); + (*(microtask_t7)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], + p_argv[3], p_argv[4], p_argv[5], p_argv[6]); break; case 8: - (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], - p_argv[5], p_argv[6], p_argv[7]); + (*(microtask_t8)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], + p_argv[3], p_argv[4], p_argv[5], p_argv[6], + p_argv[7]); break; case 9: - (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], - p_argv[5], p_argv[6], p_argv[7], p_argv[8]); + (*(microtask_t9)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], + p_argv[3], p_argv[4], p_argv[5], p_argv[6], p_argv[7], + p_argv[8]); break; case 10: - (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], - p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9]); + (*(microtask_t10)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], + p_argv[3], p_argv[4], p_argv[5], p_argv[6], + p_argv[7], p_argv[8], p_argv[9]); break; case 11: - (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], - p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10]); + (*(microtask_t11)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], + p_argv[3], p_argv[4], p_argv[5], p_argv[6], + p_argv[7], p_argv[8], p_argv[9], p_argv[10]); break; case 12: - (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], - p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10], - p_argv[11]); + (*(microtask_t12)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], + p_argv[3], p_argv[4], p_argv[5], p_argv[6], + p_argv[7], p_argv[8], p_argv[9], p_argv[10], + p_argv[11]); break; case 13: - (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], - p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10], - p_argv[11], p_argv[12]); + (*(microtask_t13)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], + p_argv[3], p_argv[4], p_argv[5], p_argv[6], + p_argv[7], p_argv[8], p_argv[9], p_argv[10], + p_argv[11], p_argv[12]); break; case 14: - (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], - p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10], - p_argv[11], p_argv[12], p_argv[13]); + (*(microtask_t14)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], + p_argv[3], p_argv[4], p_argv[5], p_argv[6], + p_argv[7], p_argv[8], p_argv[9], p_argv[10], + p_argv[11], p_argv[12], p_argv[13]); break; case 15: - (*pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], p_argv[3], p_argv[4], - p_argv[5], p_argv[6], p_argv[7], p_argv[8], p_argv[9], p_argv[10], - p_argv[11], p_argv[12], p_argv[13], p_argv[14]); + (*(microtask_t15)pkfn)(>id, &tid, p_argv[0], p_argv[1], p_argv[2], + p_argv[3], p_argv[4], p_argv[5], p_argv[6], + p_argv[7], p_argv[8], p_argv[9], p_argv[10], + p_argv[11], p_argv[12], p_argv[13], p_argv[14]); break; } diff --git a/openmp/runtime/test/lit.cfg b/openmp/runtime/test/lit.cfg index 4a457f4cc41f756887d4c74ffeb8d831e725b681..e27e52bb4289b9a34c072ca59f592d7e3fa99b09 100644 --- a/openmp/runtime/test/lit.cfg +++ b/openmp/runtime/test/lit.cfg @@ -129,7 +129,7 @@ if config.operating_system == 'NetBSD': if config.operating_system == 'Darwin': config.available_features.add("darwin") -if config.operating_system in ['Linux', 'Windows']: +if config.operating_system in ['Windows', 'Linux', 'FreeBSD', 'NetBSD', 'DragonFly', 'AIX']: config.available_features.add('affinity') if config.operating_system in ['Linux']: diff --git a/openmp/runtime/test/ompt/callback.h b/openmp/runtime/test/ompt/callback.h index 05b2006a280db58a24970fdc6f2b66b246c91ae0..f07176cc5be664b987d32797b77ebd5d2155bb3b 100644 --- a/openmp/runtime/test/ompt/callback.h +++ b/openmp/runtime/test/ompt/callback.h @@ -186,7 +186,7 @@ ompt_label_##id: #define print_possible_return_addresses(addr) \ printf("%" PRIu64 ": current_address=%p or %p\n", ompt_get_thread_data()->value, \ ((char *)addr) - 8, ((char *)addr) - 12) -#elif KMP_ARCH_AARCH64 +#elif KMP_ARCH_AARCH64 || KMP_ARCH_AARCH64_32 // On AArch64 the NOP instruction is 4 bytes long, can be followed by inserted // store instruction (another 4 bytes long). // FIXME: PR #65696 addded a third possibility (12 byte offset) to make the diff --git a/openmp/runtime/test/tasking/hidden_helper_task/issue-87117.c b/openmp/runtime/test/tasking/hidden_helper_task/issue-87117.c new file mode 100644 index 0000000000000000000000000000000000000000..23080982f49e190d375895557b24b8eaf2166eb9 --- /dev/null +++ b/openmp/runtime/test/tasking/hidden_helper_task/issue-87117.c @@ -0,0 +1,36 @@ +// RUN: %libomp-compile +// RUN: env KMP_HOT_TEAMS_MODE=0 KMP_HOT_TEAMS_MAX_LEVEL=1 %libomp-run +// +// Force the defaults of: +// KMP_HOT_TEAMS_MODE=0 means free extra threads after parallel +// involving non-hot team +// KMP_HOT_TEAMS_MAX_LEVEL=1 means only the initial outer team +// is a hot team. + +#include <stdio.h> +#include <stdlib.h> +#include <omp.h> + +int main() { + int a; + omp_set_max_active_levels(2); +// This nested parallel creates extra threads on the thread pool +#pragma omp parallel num_threads(2) + { +#pragma omp parallel num_threads(2) + { +#pragma omp atomic + a++; + } + } + +// Causes assert if hidden helper thread tries to allocate from thread pool +// instead of creating new OS threads +#pragma omp parallel num_threads(1) + { +#pragma omp target nowait + { a++; } + } + + return EXIT_SUCCESS; +} diff --git a/openmp/runtime/test/tasking/issue-87307.c b/openmp/runtime/test/tasking/issue-87307.c new file mode 100644 index 0000000000000000000000000000000000000000..f889ae20329eb31940fec09d9f1bd5af75490caf --- /dev/null +++ b/openmp/runtime/test/tasking/issue-87307.c @@ -0,0 +1,43 @@ +// RUN: %libomp-compile-and-run +#include <stdio.h> +#include <stdlib.h> +#include <omp.h> + +int a; + +void inc_a() { +#pragma omp task + { +#pragma omp atomic + a++; + } +} + +int main() { + int n; + int nth_outer; + omp_set_max_active_levels(2); + omp_set_dynamic(0); + + for (n = 0; n < 200; ++n) { + a = 0; +#pragma omp parallel num_threads(8) + { + if (omp_get_thread_num() == 0) + nth_outer = omp_get_num_threads(); +#pragma omp parallel num_threads(2) + { + int i; +#pragma omp master + for (i = 0; i < 50; ++i) + inc_a(); + } + } + if (a != nth_outer * 50) { + fprintf(stderr, "error: a (%d) != %d\n", a, nth_outer * 50); + return EXIT_FAILURE; + } + } + + return EXIT_SUCCESS; +} diff --git a/openmp/runtime/test/worksharing/for/collapse_test.inc b/openmp/runtime/test/worksharing/for/collapse_test.inc new file mode 100644 index 0000000000000000000000000000000000000000..de0e7e4e57f30d4cc88f63a8147d231354748c65 --- /dev/null +++ b/openmp/runtime/test/worksharing/for/collapse_test.inc @@ -0,0 +1,201 @@ +#include <omp.h> +#include <malloc.h> +#include <stdio.h> +#include <memory.h> + +#define LOOP_IV_TYPE0 LOOP_TYPES +#define LOOP_TYPE0 LOOP_TYPES +#define LOOP_STYPE0 LOOP_TYPES + +#define LOOP_IV_TYPE1 LOOP_TYPES +#define LOOP_TYPE1 LOOP_TYPES +#define LOOP_STYPE1 LOOP_TYPES + +#define LOOP_IV_TYPE2 LOOP_TYPES +#define LOOP_TYPE2 LOOP_TYPES +#define LOOP_STYPE2 LOOP_TYPES + +#define MAX_THREADS 256 + +#if defined VERBOSE +#define PRINTF printf +#else +#define PRINTF +#endif + +LOOP_TYPE0 iLB, iUB; +LOOP_TYPE1 jA0, jB0; +LOOP_TYPE2 kA0, kB0; + +LOOP_STYPE0 iStep; +LOOP_STYPE1 jA1, jB1, jStep; +LOOP_STYPE2 kA1, kB1, kStep; + +// We can check <=, <, >=, > (!= has different pattern) +// Additional definition of LOOP_LEi, LOOP_LTi, etc. is helpful to build calls +// of the test from main + +#if defined LOOP_LE0 +#define COMPARE0 <= +#elif defined LOOP_LT0 +#define COMPARE0 < +#elif defined LOOP_GE0 +#define COMPARE0 >= +#elif defined LOOP_GT0 +#define COMPARE0 > +#endif + +#if defined LOOP_LE1 +#define COMPARE1 <= +#elif defined LOOP_LT1 +#define COMPARE1 < +#elif defined LOOP_GE1 +#define COMPARE1 >= +#elif defined LOOP_GT1 +#define COMPARE1 > +#endif + +#if defined LOOP_LE2 +#define COMPARE2 <= +#elif defined LOOP_LT2 +#define COMPARE2 < +#elif defined LOOP_GE2 +#define COMPARE2 >= +#elif defined LOOP_GT2 +#define COMPARE2 > +#endif + +typedef struct { + LOOP_IV_TYPE0 i; + LOOP_IV_TYPE1 j; + LOOP_IV_TYPE2 k; +} spaceType; + +spaceType *AllocSpace(unsigned size) { + + spaceType *p = (spaceType *)malloc(size * sizeof(spaceType)); + memset(p, 0, size * sizeof(spaceType)); + return p; +} + +void FreeSpace(spaceType *space) { free(space); } + +// record an iteration +void Set(spaceType *space, unsigned count, unsigned trueCount, LOOP_IV_TYPE0 i, + LOOP_IV_TYPE1 j, LOOP_IV_TYPE0 k) { + if (count > trueCount) { + // number of iterations exceeded + // will be reported with checks + return; + } + space[count - 1].i = i; + space[count - 1].j = j; + space[count - 1].k = k; +} +int test() { + int pass = 1; + LOOP_IV_TYPE0 i; + LOOP_IV_TYPE1 j; + LOOP_IV_TYPE2 k; + + spaceType *openmpSpace; + spaceType *scalarSpace; + + unsigned trueCount = 0; + unsigned openmpCount = 0; + unsigned scalarCount = 0; + unsigned uselessThreadsOpenMP = 0; + unsigned usefulThreadsOpenMP = 0; + unsigned chunkSizesOpenmp[MAX_THREADS] = {0}; + + unsigned num_threads = omp_get_max_threads(); + if (num_threads > MAX_THREADS) + num_threads = MAX_THREADS; + omp_set_num_threads(num_threads); + + // count iterations and allocate space + LOOP { ++trueCount; } + + openmpSpace = AllocSpace(trueCount); + scalarSpace = AllocSpace(trueCount); + + // fill the scalar (compare) space + LOOP { + ++scalarCount; + Set(scalarSpace, scalarCount, trueCount, i, j, k); + } + + // test run body: + // perform and record OpenMP iterations and thread use +#pragma omp parallel num_threads(num_threads) + { +#pragma omp for collapse(3) private(i, j, k) + LOOP { + unsigned count; + unsigned gtid = omp_get_thread_num(); +#pragma omp atomic update + ++chunkSizesOpenmp[gtid]; +#pragma omp atomic capture + count = ++openmpCount; + Set(openmpSpace, count, trueCount, i, j, k); + } + } + + // check for the right number of iterations processed + // (only need to check for less, greater is checked when recording) + if (openmpCount < trueCount) { + PRINTF("OpenMP FAILURE: Openmp processed fewer iterations: %d vs %d\n", + openmpCount, trueCount); + pass = 0; + } else if (openmpCount > trueCount) { + PRINTF("OpenMP FAILURE: Openmp processed more iterations: %d vs %d\n", + openmpCount, trueCount); + pass = 0; + } + + // check openMP for iteration correctnes against scalar + for (unsigned i = 0; i < trueCount; i++) { + unsigned j; + for (j = 0; j < openmpCount; j++) { + if ((scalarSpace[i].i == openmpSpace[j].i) && + (scalarSpace[i].j == openmpSpace[j].j) && + (scalarSpace[i].k == openmpSpace[j].k)) { + break; + } + } + if (j == openmpCount) { + PRINTF("OpenMP FAILURE: (%d %d %d) not processed\n", scalarSpace[i].i, + scalarSpace[i].j, scalarSpace[i].k); + pass = 0; + } + } + + // check for efficient thread use + for (unsigned i = 0; i < num_threads; ++i) { + if (chunkSizesOpenmp[i] == 0) { + ++uselessThreadsOpenMP; + } + } + + // a check to see if at least more than one thread was used (weakish) + if ((uselessThreadsOpenMP == num_threads - 1) && (trueCount > 1)) { + PRINTF("OpenMP FAILURE: threads are not used\n"); + pass = 0; + } + +#if 0 + // a check to see if the load was spread more or less evenly so that + // when there was more work than threads each one got at least something + // (stronger, but may currently fail for a general collapse case) + if ((trueCount >= num_threads) && (uselessThreadsOpenMP > 0)) { + PRINTF("OpenMP FAILURE: %d threads not used with %d iterations\n", + uselessThreadsOpenMP, openmpCount); + pass = 0; + } +#endif + + // clean up space + FreeSpace(openmpSpace); + FreeSpace(scalarSpace); + return pass; +} diff --git a/openmp/runtime/test/worksharing/for/omp_collapse_many_GELTGT_int.c b/openmp/runtime/test/worksharing/for/omp_collapse_many_GELTGT_int.c new file mode 100644 index 0000000000000000000000000000000000000000..77b2d6918d8721a89754010d6ae1dc383254d37a --- /dev/null +++ b/openmp/runtime/test/worksharing/for/omp_collapse_many_GELTGT_int.c @@ -0,0 +1,65 @@ +// RUN: %libomp-compile-and-run + +// Non-rectangular loop collapsing. +// +// Nested loops conform to OpenMP 5.2 standard, +// inner loops bounds may depend on outer loops induction variables. + +#define LOOP_TYPES int +#define COMPARE0 >= +#define COMPARE1 < +#define COMPARE2 > +#define LOOP \ + for (i = iLB; i COMPARE0 iUB; i += iStep) \ + for (j = jA0; j COMPARE1 jB0; j += jStep) \ + for (k = kA0; k COMPARE2 kB0; k += kStep) +#include "collapse_test.inc" + +int main() { + int fail; + + iLB = 3; + iUB = -2; + jA0 = -3; + jA1 = 0; + jB0 = -6; + jB1 = 0; + kA0 = -2; + kA1 = 0; + kB0 = -4; + kB1 = 0; + iStep = -1; + jStep = -1; + kStep = -4; + PRINTF("\nOne off iLB=%d; iUB=%d; jA0=%d; jA1=%d; jB0=%d; jB1=%d; kA0=%d; " + "kA1=%d; kB0=%d; kB1=%d; iStep=%d; jStep=%d; kStep=%d;\n", + iLB, iUB, jA0, jA1, jB0, jB1, kA0, kA1, kB0, kB1, iStep, jStep, kStep); + fail = (test() == 0); + + if (!fail) { + for (iStep = -3; iStep >= -6; iStep -= 2) { + for (jA0 = -6; jA0 <= 6; jA0 += 3) { + for (jB0 = -3; jB0 <= 10; jB0 += 3) { + for (jStep = 1; jStep <= 10; jStep += 2) { + for (kA0 = -2; kA0 <= 4; ++kA0) { + for (kB0 = -4; kB0 <= 2; ++kB0) { + for (kStep = -2; kStep >= -10; kStep -= 4) { + { + PRINTF("\nTrying iLB=%d; iUB=%d; jA0=%d; jA1=%d; jB0=%d; " + "jB1=%d; kA0=%d; kA1=%d; kB0=%d; kB1=%d; iStep=%d; " + "jStep=%d; kStep=%d;\n", + iLB, iUB, jA0, jA1, jB0, jB1, kA0, kA1, kB0, kB1, + iStep, jStep, kStep); + fail = fail || (test() == 0); + } + } + } + } + } + } + } + } + } + + return fail; +} diff --git a/openmp/runtime/test/worksharing/for/omp_collapse_many_GTGEGT_int.c b/openmp/runtime/test/worksharing/for/omp_collapse_many_GTGEGT_int.c new file mode 100644 index 0000000000000000000000000000000000000000..985211172e6283a9bfbabe9136204238b39bfe2d --- /dev/null +++ b/openmp/runtime/test/worksharing/for/omp_collapse_many_GTGEGT_int.c @@ -0,0 +1,71 @@ +// RUN: %libomp-compile-and-run + +// Non-rectangular loop collapsing. +// +// Nested loops conform to OpenMP 5.2 standard, +// inner loops bounds may depend on outer loops induction variables. + +#define LOOP_TYPES int +#define COMPARE0 > +#define COMPARE1 >= +#define COMPARE2 > + +#define DLOOP_GT0 +#define DLOOP_GE1 +#define DLOOP_GT2 + +#define LOOP \ + for (i = iLB; i COMPARE0 iUB; i += iStep) \ + for (j = jA0; j COMPARE1 jB0; j += jStep) \ + for (k = kA0; k COMPARE2 kB0; k += kStep) +#include "collapse_test.inc" + +int main() { + int fail; + + iLB = 3; + iUB = -2; + jA0 = -3; + jA1 = 0; + jB0 = -6; + jB1 = 0; + kA0 = -2; + kA1 = 0; + kB0 = -4; + kB1 = 0; + iStep = -1; + jStep = -1; + kStep = -4; + PRINTF("\nOne off iLB=%d; iUB=%d; jA0=%d; jA1=%d; jB0=%d; jB1=%d; kA0=%d; " + "kA1=%d; kB0=%d; kB1=%d; iStep=%d; jStep=%d; kStep=%d;\n", + iLB, iUB, jA0, jA1, jB0, jB1, kA0, kA1, kB0, kB1, iStep, jStep, kStep); + fail = (test() == 0); + + if (!fail) { + + for (iStep = -3; iStep >= -6; iStep -= 2) { + for (jA0 = -3; jA0 <= 10; jA0 += 3) { + for (jB0 = -6; jB0 <= 6; jB0 += 3) { + for (jStep = -1; jStep >= -10; jStep -= 2) { + for (kA0 = -2; kA0 <= 4; ++kA0) { + for (kB0 = -4; kB0 <= 2; ++kB0) { + for (kStep = -2; kStep >= -10; kStep -= 4) { + { + PRINTF("\nTrying iLB=%d; iUB=%d; jA0=%d; jA1=%d; jB0=%d; " + "jB1=%d; kA0=%d; kA1=%d; kB0=%d; kB1=%d; iStep=%d; " + "jStep=%d; kStep=%d;\n", + iLB, iUB, jA0, jA1, jB0, jB1, kA0, kA1, kB0, kB1, + iStep, jStep, kStep); + fail = fail || (test() == 0); + } + } + } + } + } + } + } + } + } + + return fail; +} diff --git a/openmp/runtime/test/worksharing/for/omp_collapse_many_LTLEGE_int.c b/openmp/runtime/test/worksharing/for/omp_collapse_many_LTLEGE_int.c new file mode 100644 index 0000000000000000000000000000000000000000..47e3b42226c838e9b1673d50e8d4033245d84ef1 --- /dev/null +++ b/openmp/runtime/test/worksharing/for/omp_collapse_many_LTLEGE_int.c @@ -0,0 +1,66 @@ +// RUN: %libomp-compile-and-run + +// Non-rectangular loop collapsing. +// +// Nested loops conform to OpenMP 5.2 standard, +// inner loops bounds may depend on outer loops induction variables. + +#define LOOP_TYPES int +#define COMPARE0 < +#define COMPARE1 <= +#define COMPARE2 >= +#define LOOP \ + for (i = iLB; i COMPARE0 iUB; i += iStep) \ + for (j = jA0; j COMPARE1 jB0; j += jStep) \ + for (k = kA0; k COMPARE2 kB0; k += kStep) +#include "collapse_test.inc" + +int main() { + int fail; + + iLB = -2; + iUB = 3; + jA0 = -3; + jA1 = 0; + jB0 = -6; + jB1 = 0; + kA0 = -2; + kA1 = 0; + kB0 = -4; + kB1 = 0; + iStep = -1; + jStep = -1; + kStep = -4; + PRINTF("\nOne off iLB=%d; iUB=%d; jA0=%d; jA1=%d; jB0=%d; jB1=%d; kA0=%d; " + "kA1=%d; kB0=%d; kB1=%d; iStep=%d; jStep=%d; kStep=%d;\n", + iLB, iUB, jA0, jA1, jB0, jB1, kA0, kA1, kB0, kB1, iStep, jStep, kStep); + fail = (test() == 0); + + if (!fail) { + + for (iStep = 2; iStep <= 6; iStep += 2) { + for (jA0 = -6; jA0 <= 6; jA0 += 3) { + for (jB0 = -3; jB0 <= 10; jB0 += 3) { + for (jStep = 1; jStep <= 10; jStep += 2) { + for (kA0 = -2; kA0 <= 4; ++kA0) { + for (kB0 = -4; kB0 <= 2; ++kB0) { + for (kStep = -2; kStep >= -10; kStep -= 4) { + { + PRINTF("\nTrying iLB=%d; iUB=%d; jA0=%d; jA1=%d; jB0=%d; " + "jB1=%d; kA0=%d; kA1=%d; kB0=%d; kB1=%d; iStep=%d; " + "jStep=%d; kStep=%d;\n", + iLB, iUB, jA0, jA1, jB0, jB1, kA0, kA1, kB0, kB1, + iStep, jStep, kStep); + fail = fail || (test() == 0); + } + } + } + } + } + } + } + } + } + + return fail; +} diff --git a/openmp/runtime/test/worksharing/for/omp_collapse_many_int.c b/openmp/runtime/test/worksharing/for/omp_collapse_many_int.c new file mode 100644 index 0000000000000000000000000000000000000000..4455602df8a23b47e29d30987d6a4b13b45dac19 --- /dev/null +++ b/openmp/runtime/test/worksharing/for/omp_collapse_many_int.c @@ -0,0 +1,73 @@ +// RUN: %libomp-compile-and-run +// XFAIL: true + +// Non-rectangular loop collapsing. +// +// Nested loops conform to OpenMP 5.2 standard, +// inner loops bounds may depend on outer loops induction variables. + +#define LOOP_TYPES int +#define LOOP \ + for (i = iLB; i <= iUB; i += iStep) \ + for (j = i * jA1 + jA0; j <= i * jB1 + jB0; j += jStep) \ + for (k = j * kA1 + kA0; k <= j * kB1 + kB0; k += kStep) +#include "collapse_test.inc" + +int main() { + int fail = 0; + + iLB = -2; + iUB = 3; + jA0 = -7; + jA1 = -1; + jB0 = 13; + jB1 = 3; + kA0 = -20; + kA1 = -2; + kB0 = 111; + kB1 = -1; + iStep = 5; + jStep = 9; + kStep = 10; + PRINTF("\nOne off iLB=%d; iUB=%d; jA0=%d; jA1=%d; jB0=%d; jB1=%d; kA0=%d; " + "kA1=%d; kB0=%d; kB1=%d; iStep=%d; jStep=%d; kStep=%d;\n", + iLB, iUB, jA0, jA1, jB0, jB1, kA0, kA1, kB0, kB1, iStep, jStep, kStep); + fail = fail || (test() == 0); + + if (!fail) { + + // NOTE: if a loop on some level won't execute for all iterations of an + // outer loop, it still should work. Runtime doesn't require lower bounds to + // be <= upper bounds for all possible i, j, k. + + iLB = -2; + iUB = 3; + jA0 = -7; + jB0 = 5; + kA0 = -13; + kB0 = 37; + + for (kA1 = -2; kA1 <= 2; ++kA1) { // <= + for (kB1 = -2; kB1 <= 2; ++kB1) { + for (jA1 = -3; jA1 <= 3; ++jA1) { + for (jB1 = -3; jB1 <= 3; ++jB1) { + for (iStep = 1; iStep <= 3; ++iStep) { + for (jStep = 2; jStep <= 6; jStep += 2) { + for (kStep = 2; kStep <= 8; kStep += 3) { + PRINTF("\nTrying iLB=%d; iUB=%d; jA0=%d; jA1=%d; jB0=%d; " + "jB1=%d; kA0=%d; kA1=%d; kB0=%d; kB1=%d; iStep=%d; " + "jStep=%d; kStep=%d;\n", + iLB, iUB, jA0, jA1, jB0, jB1, kA0, kA1, kB0, kB1, + iStep, jStep, kStep); + fail = fail || (test() == 0); + } + } + } + } + } + } + } + } + + return fail; +} diff --git a/openmp/runtime/test/worksharing/for/omp_collapse_one_int.c b/openmp/runtime/test/worksharing/for/omp_collapse_one_int.c new file mode 100644 index 0000000000000000000000000000000000000000..437d4bff31eb37921e275580f70f6c15f5c89acc --- /dev/null +++ b/openmp/runtime/test/worksharing/for/omp_collapse_one_int.c @@ -0,0 +1,32 @@ +// RUN: %libomp-compile-and-run + +// Non-rectangular loop collapsing. +// +// Nested loops conform to OpenMP 5.2 standard, +// inner loops bounds may depend on outer loops induction variables. + +#define LOOP_TYPES int +#define LOOP \ + for (i = iLB; i <= iUB; i += iStep) \ + for (j = i + jA0; j <= i + jB0; j += jStep) \ + for (k = j + kA0; k <= j + kB0; k += kStep) + +#include "collapse_test.inc" + +int main() { + int fail; + iLB = -2; + iUB = 3; + jA0 = -7; + jB0 = 13; + kA0 = -20; + kB0 = 111; + iStep = 5; + jStep = 9; + kStep = 10; + PRINTF("\nOne off iLB=%d; iUB=%d; jA0=%d; jB0=%d; kA0=%d; kB0=%d; iStep=%d; " + "jStep=%d; kStep=%d;\n", + iLB, iUB, jA0, jB0, kA0, kB0, iStep, jStep, kStep); + fail = (test() == 0); + return fail; +} diff --git a/openmp/runtime/tools/lib/Platform.pm b/openmp/runtime/tools/lib/Platform.pm index 6efd932daef561b628ed452a44ad3e9debad121f..36847d5e8d1099ff1b1bb8d41f00f5d1b7328f99 100644 --- a/openmp/runtime/tools/lib/Platform.pm +++ b/openmp/runtime/tools/lib/Platform.pm @@ -53,6 +53,8 @@ sub canon_arch($) { $arch = "ppc64le"; } elsif ( $arch =~ m{\Appc64} ) { $arch = "ppc64"; + } elsif ( $arch =~ m{\Aaarch64_32} ) { + $arch = "aarch64_32"; } elsif ( $arch =~ m{\Aaarch64} ) { $arch = "aarch64"; } elsif ( $arch =~ m{\Amic} ) { @@ -97,6 +99,7 @@ sub canon_mic_arch($) { "32e" => "Intel(R) 64", "arm" => "ARM", "aarch64" => "AArch64", + "aarch64_32" => "AArch64_32", "loongarch64" => "LoongArch64", "mic" => "Intel(R) Many Integrated Core Architecture", "mips" => "MIPS", @@ -222,6 +225,8 @@ sub target_options() { $_host_arch = "ppc64le"; } elsif ( $hardware_platform eq "ppc64" ) { $_host_arch = "ppc64"; + } elsif ( $hardware_platform eq "aarch64_32" ) { + $_host_arch = "aarch64_32"; } elsif ( $hardware_platform eq "aarch64" ) { $_host_arch = "aarch64"; } elsif ( $hardware_platform eq "mips64" ) { diff --git a/openmp/runtime/tools/lib/Uname.pm b/openmp/runtime/tools/lib/Uname.pm index 9dde444d56a4ece5ebd254fb637c58b28cfada45..447680cc054e32f647556d04f0fc6b69976bde05 100644 --- a/openmp/runtime/tools/lib/Uname.pm +++ b/openmp/runtime/tools/lib/Uname.pm @@ -150,6 +150,8 @@ if ( 0 ) { $values{ hardware_platform } = "ppc64le"; } elsif ( $values{ machine } =~ m{\Appc64\z} ) { $values{ hardware_platform } = "ppc64"; + } elsif ( $values{ machine } =~ m{\Aaarch64_32\z} ) { + $values{ hardware_platform } = "aarch64_32"; } elsif ( $values{ machine } =~ m{\Aaarch64\z} ) { $values{ hardware_platform } = "aarch64"; } elsif ( $values{ machine } =~ m{\Amips64\z} ) { diff --git a/polly/include/polly/Support/PollyDebug.h b/polly/include/polly/Support/PollyDebug.h new file mode 100644 index 0000000000000000000000000000000000000000..5cea68efc24306c8cc254bae0a3409395e0b49ea --- /dev/null +++ b/polly/include/polly/Support/PollyDebug.h @@ -0,0 +1,38 @@ +//===-PollyDebug.h -Provide support for debugging Polly passes-*- 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 +// +//===----------------------------------------------------------------------===// +// +// Functions to aid printing Debug Info of all polly passes. +// +//===----------------------------------------------------------------------===// + +#ifndef POLLY_DEBUG_H +#define POLLY_DEBUG_H + +#include "llvm/Support/Debug.h" + +namespace polly { +using namespace llvm; +bool getPollyDebugFlag(); + +#ifndef NDEBUG +#define POLLY_DEBUG(X) \ + do { \ + if (polly::getPollyDebugFlag()) { \ + X; \ + } else { \ + DEBUG_WITH_TYPE(DEBUG_TYPE, X); \ + } \ + } while (0) +#else +#define POLLY_DEBUG(X) \ + do { \ + } while (false) +#endif + +} // namespace polly +#endif diff --git a/polly/lib/Analysis/DependenceInfo.cpp b/polly/lib/Analysis/DependenceInfo.cpp index 69257c603877ea411edc3beb4ef5e6b8dbbbbe59..9ee004fbac9e53a0b7499143bd1df051974bb604 100644 --- a/polly/lib/Analysis/DependenceInfo.cpp +++ b/polly/lib/Analysis/DependenceInfo.cpp @@ -39,6 +39,7 @@ using namespace polly; using namespace llvm; +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-dependence" static cl::opt<int> OptComputeOut( @@ -300,10 +301,10 @@ static __isl_give isl_union_flow *buildFlow(__isl_keep isl_union_map *Snk, AI = isl_union_access_info_set_kill(AI, isl_union_map_copy(Kill)); AI = isl_union_access_info_set_schedule(AI, isl_schedule_copy(Schedule)); auto Flow = isl_union_access_info_compute_flow(AI); - LLVM_DEBUG(if (!Flow) dbgs() - << "last error: " - << isl_ctx_last_error(isl_schedule_get_ctx(Schedule)) - << '\n';); + POLLY_DEBUG(if (!Flow) dbgs() + << "last error: " + << isl_ctx_last_error(isl_schedule_get_ctx(Schedule)) + << '\n';); return Flow; } @@ -312,18 +313,18 @@ void Dependences::calculateDependences(Scop &S) { isl_schedule *Schedule; isl_union_set *TaggedStmtDomain; - LLVM_DEBUG(dbgs() << "Scop: \n" << S << "\n"); + POLLY_DEBUG(dbgs() << "Scop: \n" << S << "\n"); collectInfo(S, Read, MustWrite, MayWrite, ReductionTagMap, TaggedStmtDomain, Level); bool HasReductions = !isl_union_map_is_empty(ReductionTagMap); - LLVM_DEBUG(dbgs() << "Read: " << Read << '\n'; - dbgs() << "MustWrite: " << MustWrite << '\n'; - dbgs() << "MayWrite: " << MayWrite << '\n'; - dbgs() << "ReductionTagMap: " << ReductionTagMap << '\n'; - dbgs() << "TaggedStmtDomain: " << TaggedStmtDomain << '\n';); + POLLY_DEBUG(dbgs() << "Read: " << Read << '\n'; + dbgs() << "MustWrite: " << MustWrite << '\n'; + dbgs() << "MayWrite: " << MayWrite << '\n'; + dbgs() << "ReductionTagMap: " << ReductionTagMap << '\n'; + dbgs() << "TaggedStmtDomain: " << TaggedStmtDomain << '\n';); Schedule = S.getScheduleTree().release(); @@ -360,10 +361,10 @@ void Dependences::calculateDependences(Scop &S) { Schedule = isl_schedule_pullback_union_pw_multi_aff(Schedule, Tags); } - LLVM_DEBUG(dbgs() << "Read: " << Read << "\n"; - dbgs() << "MustWrite: " << MustWrite << "\n"; - dbgs() << "MayWrite: " << MayWrite << "\n"; - dbgs() << "Schedule: " << Schedule << "\n"); + POLLY_DEBUG(dbgs() << "Read: " << Read << "\n"; + dbgs() << "MustWrite: " << MustWrite << "\n"; + dbgs() << "MayWrite: " << MayWrite << "\n"; + dbgs() << "Schedule: " << Schedule << "\n"); isl_union_map *StrictWAW = nullptr; { @@ -504,7 +505,7 @@ void Dependences::calculateDependences(Scop &S) { isl_union_map_copy(WAW), isl_union_set_copy(TaggedStmtDomain)); STMT_WAR = isl_union_map_intersect_domain(isl_union_map_copy(WAR), TaggedStmtDomain); - LLVM_DEBUG({ + POLLY_DEBUG({ dbgs() << "Wrapped Dependences:\n"; dump(); dbgs() << "\n"; @@ -553,7 +554,7 @@ void Dependences::calculateDependences(Scop &S) { } else TC_RED = isl_union_map_empty(isl_union_map_get_space(RED)); - LLVM_DEBUG({ + POLLY_DEBUG({ dbgs() << "Final Wrapped Dependences:\n"; dump(); dbgs() << "\n"; @@ -603,7 +604,7 @@ void Dependences::calculateDependences(Scop &S) { RED = isl_union_map_zip(RED); TC_RED = isl_union_map_zip(TC_RED); - LLVM_DEBUG({ + POLLY_DEBUG({ dbgs() << "Zipped Dependences:\n"; dump(); dbgs() << "\n"; @@ -615,7 +616,7 @@ void Dependences::calculateDependences(Scop &S) { RED = isl_union_set_unwrap(isl_union_map_domain(RED)); TC_RED = isl_union_set_unwrap(isl_union_map_domain(TC_RED)); - LLVM_DEBUG({ + POLLY_DEBUG({ dbgs() << "Unwrapped Dependences:\n"; dump(); dbgs() << "\n"; @@ -631,7 +632,7 @@ void Dependences::calculateDependences(Scop &S) { RED = isl_union_map_coalesce(RED); TC_RED = isl_union_map_coalesce(TC_RED); - LLVM_DEBUG(dump()); + POLLY_DEBUG(dump()); } bool Dependences::isValidSchedule(Scop &S, isl::schedule NewSched) const { diff --git a/polly/lib/Analysis/PolyhedralInfo.cpp b/polly/lib/Analysis/PolyhedralInfo.cpp index 5c77be0a9a1fa950cb1123c93c44b9ed69d58572..8d8e81a9049dfec93b2ee001e76beb4c88c4443c 100644 --- a/polly/lib/Analysis/PolyhedralInfo.cpp +++ b/polly/lib/Analysis/PolyhedralInfo.cpp @@ -32,6 +32,7 @@ using namespace llvm; using namespace polly; +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polyhedral-info" static cl::opt<bool> CheckParallel("polly-check-parallel", @@ -77,19 +78,19 @@ bool PolyhedralInfo::checkParallel(Loop *L, isl_pw_aff **MinDepDistPtr) const { DI->getDependences(const_cast<Scop *>(S), Dependences::AL_Access); if (!D.hasValidDependences()) return false; - LLVM_DEBUG(dbgs() << "Loop :\t" << L->getHeader()->getName() << ":\n"); + POLLY_DEBUG(dbgs() << "Loop :\t" << L->getHeader()->getName() << ":\n"); isl_union_map *Deps = D.getDependences(Dependences::TYPE_RAW | Dependences::TYPE_WAW | Dependences::TYPE_WAR | Dependences::TYPE_RED) .release(); - LLVM_DEBUG(dbgs() << "Dependences :\t" << stringFromIslObj(Deps, "null") - << "\n"); + POLLY_DEBUG(dbgs() << "Dependences :\t" << stringFromIslObj(Deps, "null") + << "\n"); isl_union_map *Schedule = getScheduleForLoop(S, L); - LLVM_DEBUG(dbgs() << "Schedule: \t" << stringFromIslObj(Schedule, "null") - << "\n"); + POLLY_DEBUG(dbgs() << "Schedule: \t" << stringFromIslObj(Schedule, "null") + << "\n"); IsParallel = D.isParallel(Schedule, Deps, MinDepDistPtr); isl_union_map_free(Schedule); @@ -125,14 +126,14 @@ __isl_give isl_union_map *PolyhedralInfo::getScheduleForLoop(const Scop *S, Loop *L) const { isl_union_map *Schedule = isl_union_map_empty(S->getParamSpace().release()); int CurrDim = S->getRelativeLoopDepth(L); - LLVM_DEBUG(dbgs() << "Relative loop depth:\t" << CurrDim << "\n"); + POLLY_DEBUG(dbgs() << "Relative loop depth:\t" << CurrDim << "\n"); assert(CurrDim >= 0 && "Loop in region should have at least depth one"); for (auto &SS : *S) { if (L->contains(SS.getSurroundingLoop())) { unsigned int MaxDim = SS.getNumIterators(); - LLVM_DEBUG(dbgs() << "Maximum depth of Stmt:\t" << MaxDim << "\n"); + POLLY_DEBUG(dbgs() << "Maximum depth of Stmt:\t" << MaxDim << "\n"); isl_map *ScheduleMap = SS.getSchedule().release(); assert( ScheduleMap && diff --git a/polly/lib/Analysis/PruneUnprofitable.cpp b/polly/lib/Analysis/PruneUnprofitable.cpp index db4a3d73dc33aa34aa91a6f70a4d6bb8426126bd..f8469c03fe55bdaa6e457e8f115be9dc3611da75 100644 --- a/polly/lib/Analysis/PruneUnprofitable.cpp +++ b/polly/lib/Analysis/PruneUnprofitable.cpp @@ -22,6 +22,7 @@ using namespace llvm; using namespace polly; +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-prune-unprofitable" namespace { @@ -57,7 +58,7 @@ static void updateStatistics(Scop &S, bool Pruned) { static bool runPruneUnprofitable(Scop &S) { if (PollyProcessUnprofitable) { - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << "NOTE: -polly-process-unprofitable active, won't prune " "anything\n"); return false; @@ -66,7 +67,7 @@ static bool runPruneUnprofitable(Scop &S) { ScopsProcessed++; if (!S.isProfitable(true)) { - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << "SCoP pruned because it probably cannot be optimized in " "a significant way\n"); S.invalidate(PROFITABLE, DebugLoc()); diff --git a/polly/lib/Analysis/ScopBuilder.cpp b/polly/lib/Analysis/ScopBuilder.cpp index 0edc41d106415c975f9aaf7b2fb13d786247ff06..214e4d360d6bbbe02dbeaff7f2ea66ab94e63819 100644 --- a/polly/lib/Analysis/ScopBuilder.cpp +++ b/polly/lib/Analysis/ScopBuilder.cpp @@ -60,6 +60,7 @@ using namespace llvm; using namespace polly; +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-scops" STATISTIC(ScopFound, "Number of valid Scops"); @@ -2544,9 +2545,9 @@ bool checkCandidatePairAccesses(MemoryAccess *LoadMA, MemoryAccess *StoreMA, isl::map LoadAccs = LoadMA->getAccessRelation(); isl::map StoreAccs = StoreMA->getAccessRelation(); bool Valid = LoadAccs.has_equal_space(StoreAccs); - LLVM_DEBUG(dbgs() << " == The accessed space below is " - << (Valid ? "" : "not ") << "equal!\n"); - LLVM_DEBUG(LoadMA->dump(); StoreMA->dump()); + POLLY_DEBUG(dbgs() << " == The accessed space below is " + << (Valid ? "" : "not ") << "equal!\n"); + POLLY_DEBUG(LoadMA->dump(); StoreMA->dump()); if (Valid) { // Then check if they actually access the same memory. @@ -2560,8 +2561,8 @@ bool checkCandidatePairAccesses(MemoryAccess *LoadMA, MemoryAccess *StoreMA, isl::set InterAccs = isl::manage(RS.copy()).intersect(isl::manage(WS.copy())); Valid = !InterAccs.is_empty(); - LLVM_DEBUG(dbgs() << " == The accessed memory is " << (Valid ? "" : "not ") - << "overlapping!\n"); + POLLY_DEBUG(dbgs() << " == The accessed memory is " << (Valid ? "" : "not ") + << "overlapping!\n"); } if (Valid) { @@ -2571,8 +2572,8 @@ bool checkCandidatePairAccesses(MemoryAccess *LoadMA, MemoryAccess *StoreMA, isl::set AllAccs = AllAccsRel.range(); Valid = !hasIntersectingAccesses(AllAccs, LoadMA, StoreMA, Domain, MemAccs); - LLVM_DEBUG(dbgs() << " == The accessed memory is " << (Valid ? "not " : "") - << "accessed by other instructions!\n"); + POLLY_DEBUG(dbgs() << " == The accessed memory is " << (Valid ? "not " : "") + << "accessed by other instructions!\n"); } return Valid; } @@ -3240,8 +3241,8 @@ bool ScopBuilder::buildAliasChecks() { // we make the assumed context infeasible. scop->invalidate(ALIASING, DebugLoc()); - LLVM_DEBUG(dbgs() << "\n\nNOTE: Run time checks for " << scop->getNameStr() - << " could not be created. This SCoP has been dismissed."); + POLLY_DEBUG(dbgs() << "\n\nNOTE: Run time checks for " << scop->getNameStr() + << " could not be created. This SCoP has been dismissed."); return false; } @@ -3562,7 +3563,7 @@ void ScopBuilder::buildScop(Region &R, AssumptionCache &AC) { DenseMap<BasicBlock *, isl::set> InvalidDomainMap; if (!buildDomains(&R, InvalidDomainMap)) { - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << "Bailing-out because buildDomains encountered problems\n"); return; } @@ -3582,7 +3583,7 @@ void ScopBuilder::buildScop(Region &R, AssumptionCache &AC) { scop->removeStmtNotInDomainMap(); scop->simplifySCoP(false); if (scop->isEmpty()) { - LLVM_DEBUG(dbgs() << "Bailing-out because SCoP is empty\n"); + POLLY_DEBUG(dbgs() << "Bailing-out because SCoP is empty\n"); return; } @@ -3599,7 +3600,8 @@ void ScopBuilder::buildScop(Region &R, AssumptionCache &AC) { // Check early for a feasible runtime context. if (!scop->hasFeasibleRuntimeContext()) { - LLVM_DEBUG(dbgs() << "Bailing-out because of unfeasible context (early)\n"); + POLLY_DEBUG( + dbgs() << "Bailing-out because of unfeasible context (early)\n"); return; } @@ -3607,7 +3609,7 @@ void ScopBuilder::buildScop(Region &R, AssumptionCache &AC) { // only the runtime context could become infeasible. if (!scop->isProfitable(UnprofitableScalarAccs)) { scop->invalidate(PROFITABLE, DebugLoc()); - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << "Bailing-out because SCoP is not considered profitable\n"); return; } @@ -3626,7 +3628,7 @@ void ScopBuilder::buildScop(Region &R, AssumptionCache &AC) { scop->simplifyContexts(); if (!buildAliasChecks()) { - LLVM_DEBUG(dbgs() << "Bailing-out because could not build alias checks\n"); + POLLY_DEBUG(dbgs() << "Bailing-out because could not build alias checks\n"); return; } @@ -3638,7 +3640,7 @@ void ScopBuilder::buildScop(Region &R, AssumptionCache &AC) { // Check late for a feasible runtime context because profitability did not // change. if (!scop->hasFeasibleRuntimeContext()) { - LLVM_DEBUG(dbgs() << "Bailing-out because of unfeasible context (late)\n"); + POLLY_DEBUG(dbgs() << "Bailing-out because of unfeasible context (late)\n"); return; } @@ -3662,12 +3664,12 @@ ScopBuilder::ScopBuilder(Region *R, AssumptionCache &AC, AAResults &AA, buildScop(*R, AC); - LLVM_DEBUG(dbgs() << *scop); + POLLY_DEBUG(dbgs() << *scop); if (!scop->hasFeasibleRuntimeContext()) { InfeasibleScops++; Msg = "SCoP ends here but was dismissed."; - LLVM_DEBUG(dbgs() << "SCoP detected but dismissed\n"); + POLLY_DEBUG(dbgs() << "SCoP detected but dismissed\n"); RecordedAssumptions.clear(); scop.reset(); } else { diff --git a/polly/lib/Analysis/ScopDetection.cpp b/polly/lib/Analysis/ScopDetection.cpp index 938d3f149677ba1dbde4f11a70fb392c7baa00b8..eab7bd83e6a4e7eb38084fde25b8799ecbc61d17 100644 --- a/polly/lib/Analysis/ScopDetection.cpp +++ b/polly/lib/Analysis/ScopDetection.cpp @@ -91,6 +91,7 @@ using namespace llvm; using namespace polly; +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-detect" // This option is set to a very high value, as analyzing such loops increases @@ -406,8 +407,8 @@ inline bool ScopDetection::invalid(DetectionContext &Context, bool Assert, // canUseISLTripCount(). Log.report(RejectReason); - LLVM_DEBUG(dbgs() << RejectReason->getMessage()); - LLVM_DEBUG(dbgs() << "\n"); + POLLY_DEBUG(dbgs() << RejectReason->getMessage()); + POLLY_DEBUG(dbgs() << "\n"); } else { assert(!Assert && "Verification of detected scop failed"); } @@ -704,8 +705,8 @@ bool ScopDetection::isValidCallInst(CallInst &CI, return false; if (isDebugCall(&CI)) { - LLVM_DEBUG(dbgs() << "Allow call to debug function: " - << CalledFunction->getName() << '\n'); + POLLY_DEBUG(dbgs() << "Allow call to debug function: " + << CalledFunction->getName() << '\n'); return true; } @@ -1486,7 +1487,7 @@ Region *ScopDetection::expandRegion(Region &R) { std::unique_ptr<Region> LastValidRegion; auto ExpandedRegion = std::unique_ptr<Region>(R.getExpandedRegion()); - LLVM_DEBUG(dbgs() << "\tExpanding " << R.getNameStr() << "\n"); + POLLY_DEBUG(dbgs() << "\tExpanding " << R.getNameStr() << "\n"); while (ExpandedRegion) { BBPair P = getBBPairForRegion(ExpandedRegion.get()); @@ -1495,7 +1496,8 @@ Region *ScopDetection::expandRegion(Region &R) { /*Verifying=*/false); DetectionContext &Context = *Entry.get(); - LLVM_DEBUG(dbgs() << "\t\tTrying " << ExpandedRegion->getNameStr() << "\n"); + POLLY_DEBUG(dbgs() << "\t\tTrying " << ExpandedRegion->getNameStr() + << "\n"); // Only expand when we did not collect errors. if (!Context.Log.hasErrors()) { @@ -1529,7 +1531,7 @@ Region *ScopDetection::expandRegion(Region &R) { } } - LLVM_DEBUG({ + POLLY_DEBUG({ if (LastValidRegion) dbgs() << "\tto " << LastValidRegion->getNameStr() << "\n"; else @@ -1750,10 +1752,11 @@ bool ScopDetection::isProfitableRegion(DetectionContext &Context) const { bool ScopDetection::isValidRegion(DetectionContext &Context) { Region &CurRegion = Context.CurRegion; - LLVM_DEBUG(dbgs() << "Checking region: " << CurRegion.getNameStr() << "\n\t"); + POLLY_DEBUG(dbgs() << "Checking region: " << CurRegion.getNameStr() + << "\n\t"); if (!PollyAllowFullFunction && CurRegion.isTopLevelRegion()) { - LLVM_DEBUG(dbgs() << "Top level region is invalid\n"); + POLLY_DEBUG(dbgs() << "Top level region is invalid\n"); Context.IsInvalid = true; return false; } @@ -1761,14 +1764,14 @@ bool ScopDetection::isValidRegion(DetectionContext &Context) { DebugLoc DbgLoc; if (CurRegion.getExit() && isa<UnreachableInst>(CurRegion.getExit()->getTerminator())) { - LLVM_DEBUG(dbgs() << "Unreachable in exit\n"); + POLLY_DEBUG(dbgs() << "Unreachable in exit\n"); return invalid<ReportUnreachableInExit>(Context, /*Assert=*/true, CurRegion.getExit(), DbgLoc); } if (!OnlyRegion.empty() && !CurRegion.getEntry()->getName().count(OnlyRegion)) { - LLVM_DEBUG({ + POLLY_DEBUG({ dbgs() << "Region entry does not match -polly-only-region"; dbgs() << "\n"; }); @@ -1802,7 +1805,7 @@ bool ScopDetection::isValidRegion(DetectionContext &Context) { return invalid<ReportIrreducibleRegion>(Context, /*Assert=*/true, &CurRegion, DbgLoc); - LLVM_DEBUG(dbgs() << "OK\n"); + POLLY_DEBUG(dbgs() << "OK\n"); return true; } diff --git a/polly/lib/Analysis/ScopInfo.cpp b/polly/lib/Analysis/ScopInfo.cpp index 3e78cc8937fbf0808474aebb74d2bd5ef18e6b28..fa35fae84aceb24be3015974c4c9b8bf4369628f 100644 --- a/polly/lib/Analysis/ScopInfo.cpp +++ b/polly/lib/Analysis/ScopInfo.cpp @@ -73,6 +73,7 @@ using namespace llvm; using namespace polly; +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-scops" STATISTIC(AssumptionsAliasing, "Number of aliasing assumptions taken."); @@ -2042,7 +2043,7 @@ void Scop::intersectDefinedBehavior(isl::set Set, AssumptionSign Sign) { } void Scop::invalidate(AssumptionKind Kind, DebugLoc Loc, BasicBlock *BB) { - LLVM_DEBUG(dbgs() << "Invalidate SCoP because of reason " << Kind << "\n"); + POLLY_DEBUG(dbgs() << "Invalidate SCoP because of reason " << Kind << "\n"); addAssumption(Kind, isl::set::empty(getParamSpace()), Loc, AS_ASSUMPTION, BB); } diff --git a/polly/lib/CMakeLists.txt b/polly/lib/CMakeLists.txt index 9780f24d5d36a766df1484352358b3d18a14eea6..4557878e515e662c99aba4f9fe943910443a8ca6 100644 --- a/polly/lib/CMakeLists.txt +++ b/polly/lib/CMakeLists.txt @@ -62,6 +62,7 @@ add_llvm_pass_plugin(Polly CodeGen/PerfMonitor.cpp Exchange/JSONExporter.cpp Support/GICHelper.cpp + Support/PollyDebug.cpp Support/SCEVAffinator.cpp Support/SCEVValidator.cpp Support/RegisterPasses.cpp diff --git a/polly/lib/CodeGen/CodeGeneration.cpp b/polly/lib/CodeGen/CodeGeneration.cpp index 3792d995fd990432cecee364bc1f2d37ce252c2c..c4ca3f2e0f0f0ea9581c0d8241f3d74bd9ba8535 100644 --- a/polly/lib/CodeGen/CodeGeneration.cpp +++ b/polly/lib/CodeGen/CodeGeneration.cpp @@ -47,6 +47,7 @@ using namespace llvm; using namespace polly; +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-codegen" static cl::opt<bool> Verify("polly-codegen-verify", @@ -86,7 +87,7 @@ static void verifyGeneratedFunction(Scop &S, Function &F, IslAstInfo &AI) { if (!Verify || !verifyFunction(F, &errs())) return; - LLVM_DEBUG({ + POLLY_DEBUG({ errs() << "== ISL Codegen created an invalid function ==\n\n== The " "SCoP ==\n"; errs() << S; @@ -183,7 +184,7 @@ static bool generateCode(Scop &S, IslAstInfo &AI, LoopInfo &LI, // DependenceInfo or IslAstInfo around. IslAst &Ast = AI.getIslAst(); if (Ast.getSharedIslCtx() != S.getSharedIslCtx()) { - LLVM_DEBUG(dbgs() << "Got an IstAst for a different Scop/isl_ctx\n"); + POLLY_DEBUG(dbgs() << "Got an IstAst for a different Scop/isl_ctx\n"); return false; } diff --git a/polly/lib/CodeGen/IslAst.cpp b/polly/lib/CodeGen/IslAst.cpp index fe2b5d9104d7d0f6354f0857124edeef975ddc1f..142a19d5e069ba2b68716cfbfa0e596cb7eaa4d2 100644 --- a/polly/lib/CodeGen/IslAst.cpp +++ b/polly/lib/CodeGen/IslAst.cpp @@ -52,6 +52,7 @@ #include <cassert> #include <cstdlib> +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-ast" using namespace llvm; @@ -643,14 +644,14 @@ static std::unique_ptr<IslAstInfo> runIslAst( const Dependences &D = GetDeps(Dependences::AL_Statement); if (D.getSharedIslCtx() != Scop.getSharedIslCtx()) { - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << "Got dependence analysis for different SCoP/isl_ctx\n"); return {}; } std::unique_ptr<IslAstInfo> Ast = std::make_unique<IslAstInfo>(Scop, D); - LLVM_DEBUG({ + POLLY_DEBUG({ if (Ast) Ast->print(dbgs()); }); @@ -751,7 +752,7 @@ void IslAstInfo::print(raw_ostream &OS) { P = isl_ast_node_print(RootNode.get(), P, Options); AstStr = isl_printer_get_str(P); - LLVM_DEBUG({ + POLLY_DEBUG({ dbgs() << S.getContextStr() << "\n"; dbgs() << stringFromIslObj(S.getScheduleTree(), "null"); }); diff --git a/polly/lib/CodeGen/IslNodeBuilder.cpp b/polly/lib/CodeGen/IslNodeBuilder.cpp index a226cc2a1b25065f8834f1505d3fbab3fefbc9e2..8b2207ecbf362ce991dfc6fd03a6ba59d4f54392 100644 --- a/polly/lib/CodeGen/IslNodeBuilder.cpp +++ b/polly/lib/CodeGen/IslNodeBuilder.cpp @@ -1212,7 +1212,7 @@ bool IslNodeBuilder::preloadInvariantEquivClass( BasicBlock *EntryBB = &Builder.GetInsertBlock()->getParent()->getEntryBlock(); auto *Alloca = new AllocaInst(AccInstTy, DL.getAllocaAddrSpace(), AccInst->getName() + ".preload.s2a", - &*EntryBB->getFirstInsertionPt()); + EntryBB->getFirstInsertionPt()); Builder.CreateStore(PreloadVal, Alloca); ValueMapT PreloadedPointer; PreloadedPointer[PreloadVal] = AccInst; @@ -1308,10 +1308,11 @@ void IslNodeBuilder::allocateNewArrays(BBPair StartExitBlocks) { auto InstIt = Builder.GetInsertBlock() ->getParent() ->getEntryBlock() - .getTerminator(); + .getTerminator() + ->getIterator(); auto *CreatedArray = new AllocaInst(NewArrayType, DL.getAllocaAddrSpace(), - SAI->getName(), &*InstIt); + SAI->getName(), InstIt); if (PollyTargetFirstLevelCacheLineSize) CreatedArray->setAlignment(Align(PollyTargetFirstLevelCacheLineSize)); SAI->setBasePtr(CreatedArray); diff --git a/polly/lib/CodeGen/LoopGenerators.cpp b/polly/lib/CodeGen/LoopGenerators.cpp index 5c99515c54440565af6ea984b05c7faa1ca03d3f..b4f8bb8948c28248283f07e79f0fb6a6b8af2606 100644 --- a/polly/lib/CodeGen/LoopGenerators.cpp +++ b/polly/lib/CodeGen/LoopGenerators.cpp @@ -225,7 +225,7 @@ ParallelLoopGenerator::storeValuesIntoStruct(SetVector<Value *> &Values) { // in the entry block of the function and use annotations to denote the actual // live span (similar to clang). BasicBlock &EntryBB = Builder.GetInsertBlock()->getParent()->getEntryBlock(); - Instruction *IP = &*EntryBB.getFirstInsertionPt(); + BasicBlock::iterator IP = EntryBB.getFirstInsertionPt(); StructType *Ty = StructType::get(Builder.getContext(), Members); AllocaInst *Struct = new AllocaInst(Ty, DL.getAllocaAddrSpace(), nullptr, "polly.par.userContext", IP); diff --git a/polly/lib/Support/PollyDebug.cpp b/polly/lib/Support/PollyDebug.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9dcd8ed03694ff273791c5cc6ae1cae5fdbc2a97 --- /dev/null +++ b/polly/lib/Support/PollyDebug.cpp @@ -0,0 +1,27 @@ +//===-PollyDebug.cpp -Provide support for debugging Polly passes-*- 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 +// +//===----------------------------------------------------------------------===// +// +// Functions to aid printing Debug Info of all polly passes. +// +//===----------------------------------------------------------------------===// + +#include "polly/Support/PollyDebug.h" +#include "llvm/Support/CommandLine.h" + +using namespace polly; +using namespace llvm; + +bool PollyDebugFlag; +bool polly::getPollyDebugFlag() { return PollyDebugFlag; } + +// -debug - Command line option to enable the DEBUG statements in the passes. +// This flag may only be enabled in debug builds. +static cl::opt<bool, true> + PollyDebug("polly-debug", + cl::desc("Enable debug output for only polly passes."), + cl::Hidden, cl::location(PollyDebugFlag), cl::ZeroOrMore); diff --git a/polly/lib/Support/SCEVValidator.cpp b/polly/lib/Support/SCEVValidator.cpp index e3d9818597ea69bb1a904c52d0af111ae115be8d..5bb82624ed78449b0f50ee9822191f5f096dbf46 100644 --- a/polly/lib/Support/SCEVValidator.cpp +++ b/polly/lib/Support/SCEVValidator.cpp @@ -9,6 +9,7 @@ using namespace llvm; using namespace polly; +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-scev-validator" namespace SCEVType { @@ -136,7 +137,7 @@ public: ValidatorResult visitVScale(const SCEVVScale *VScale) { // We do not support VScale constants. - LLVM_DEBUG(dbgs() << "INVALID: VScale is not supported"); + POLLY_DEBUG(dbgs() << "INVALID: VScale is not supported"); return ValidatorResult(SCEVType::INVALID); } @@ -203,7 +204,7 @@ public: } if ((Op.isIV() || Op.isPARAM()) && !Return.isINT()) { - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << "INVALID: More than one non-int operand in MulExpr\n" << "\tExpr: " << *Expr << "\n" << "\tPrevious expression type: " << Return << "\n" @@ -224,7 +225,7 @@ public: ValidatorResult visitAddRecExpr(const SCEVAddRecExpr *Expr) { if (!Expr->isAffine()) { - LLVM_DEBUG(dbgs() << "INVALID: AddRec is not affine"); + POLLY_DEBUG(dbgs() << "INVALID: AddRec is not affine"); return ValidatorResult(SCEVType::INVALID); } @@ -239,7 +240,7 @@ public: auto *L = Expr->getLoop(); if (R->contains(L) && (!Scope || !L->contains(Scope))) { - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << "INVALID: Loop of AddRec expression boxed in an a " "non-affine subregion or has a non-synthesizable exit " "value."); @@ -253,8 +254,8 @@ public: return Result; } - LLVM_DEBUG(dbgs() << "INVALID: AddRec within scop has non-int" - "recurrence part"); + POLLY_DEBUG(dbgs() << "INVALID: AddRec within scop has non-int" + "recurrence part"); return ValidatorResult(SCEVType::INVALID); } @@ -314,7 +315,7 @@ public: ValidatorResult Op = visit(Expr->getOperand(i)); if (!Op.isConstant()) { - LLVM_DEBUG(dbgs() << "INVALID: UMaxExpr has a non-constant operand"); + POLLY_DEBUG(dbgs() << "INVALID: UMaxExpr has a non-constant operand"); return ValidatorResult(SCEVType::INVALID); } } @@ -329,7 +330,7 @@ public: ValidatorResult Op = visit(Expr->getOperand(i)); if (!Op.isConstant()) { - LLVM_DEBUG(dbgs() << "INVALID: UMinExpr has a non-constant operand"); + POLLY_DEBUG(dbgs() << "INVALID: UMinExpr has a non-constant operand"); return ValidatorResult(SCEVType::INVALID); } } @@ -344,7 +345,7 @@ public: ValidatorResult Op = visit(Expr->getOperand(i)); if (!Op.isConstant()) { - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << "INVALID: SCEVSequentialUMinExpr has a non-constant operand"); return ValidatorResult(SCEVType::INVALID); @@ -356,8 +357,8 @@ public: ValidatorResult visitGenericInst(Instruction *I, const SCEV *S) { if (R->contains(I)) { - LLVM_DEBUG(dbgs() << "INVALID: UnknownExpr references an instruction " - "within the region\n"); + POLLY_DEBUG(dbgs() << "INVALID: UnknownExpr references an instruction " + "within the region\n"); return ValidatorResult(SCEVType::INVALID); } @@ -393,7 +394,7 @@ public: if (LHS.isConstant() && RHS.isConstant()) return ValidatorResult(SCEVType::PARAM, DivExpr); - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << "INVALID: unsigned division of non-constant expressions"); return ValidatorResult(SCEVType::INVALID); } @@ -434,12 +435,13 @@ public: Value *V = Expr->getValue(); if (!Expr->getType()->isIntegerTy() && !Expr->getType()->isPointerTy()) { - LLVM_DEBUG(dbgs() << "INVALID: UnknownExpr is not an integer or pointer"); + POLLY_DEBUG( + dbgs() << "INVALID: UnknownExpr is not an integer or pointer"); return ValidatorResult(SCEVType::INVALID); } if (isa<UndefValue>(V)) { - LLVM_DEBUG(dbgs() << "INVALID: UnknownExpr references an undef value"); + POLLY_DEBUG(dbgs() << "INVALID: UnknownExpr references an undef value"); return ValidatorResult(SCEVType::INVALID); } @@ -601,7 +603,7 @@ bool polly::isAffineExpr(const Region *R, llvm::Loop *Scope, const SCEV *Expr, return false; SCEVValidator Validator(R, Scope, SE, ILS); - LLVM_DEBUG({ + POLLY_DEBUG({ dbgs() << "\n"; dbgs() << "Expr: " << *Expr << "\n"; dbgs() << "Region: " << R->getNameStr() << "\n"; @@ -610,7 +612,7 @@ bool polly::isAffineExpr(const Region *R, llvm::Loop *Scope, const SCEV *Expr, ValidatorResult Result = Validator.visit(Expr); - LLVM_DEBUG({ + POLLY_DEBUG({ if (Result.isValid()) dbgs() << "VALID\n"; dbgs() << "\n"; diff --git a/polly/lib/Support/ScopHelper.cpp b/polly/lib/Support/ScopHelper.cpp index afdb61f25b6c12febb9dd34b1018c1a06c7627d1..24c7011b06de93207c5e1eb5abc62f37c6dd79bd 100644 --- a/polly/lib/Support/ScopHelper.cpp +++ b/polly/lib/Support/ScopHelper.cpp @@ -328,8 +328,9 @@ private: Value *LHS = expandCodeFor(LHSScev, E->getType(), IP); Value *RHS = expandCodeFor(RHSScev, E->getType(), IP); - Inst = BinaryOperator::Create((Instruction::BinaryOps)Inst->getOpcode(), - LHS, RHS, Inst->getName() + Name, IP); + Inst = + BinaryOperator::Create((Instruction::BinaryOps)Inst->getOpcode(), LHS, + RHS, Inst->getName() + Name, IP->getIterator()); return SE.getSCEV(Inst); } diff --git a/polly/lib/Transform/DeLICM.cpp b/polly/lib/Transform/DeLICM.cpp index dae5e79639f7be7af8732e21065408afb2fbc173..8afa63724ade5d4eda5575bc103ddd8fb9de67ce 100644 --- a/polly/lib/Transform/DeLICM.cpp +++ b/polly/lib/Transform/DeLICM.cpp @@ -26,6 +26,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/InitializePasses.h" +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-delicm" using namespace polly; @@ -547,7 +548,7 @@ private: /// @see Knowledge::isConflicting bool isConflicting(const Knowledge &Proposed) { raw_ostream *OS = nullptr; - LLVM_DEBUG(OS = &llvm::dbgs()); + POLLY_DEBUG(OS = &llvm::dbgs()); return Knowledge::isConflicting(Zone, Proposed, OS, 4); } @@ -559,7 +560,7 @@ private: if (SAI->isValueKind()) { auto *MA = S->getValueDef(SAI); if (!MA) { - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << " Reject because value is read-only within the scop\n"); return false; @@ -576,7 +577,7 @@ private: auto UserInst = cast<Instruction>(User); if (!S->contains(UserInst)) { - LLVM_DEBUG(dbgs() << " Reject because value is escaping\n"); + POLLY_DEBUG(dbgs() << " Reject because value is escaping\n"); return false; } } @@ -593,9 +594,9 @@ private: auto PHI = cast<PHINode>(MA->getAccessInstruction()); for (auto Incoming : PHI->blocks()) { if (!S->contains(Incoming)) { - LLVM_DEBUG(dbgs() - << " Reject because at least one incoming block is " - "not in the scop region\n"); + POLLY_DEBUG(dbgs() + << " Reject because at least one incoming block is " + "not in the scop region\n"); return false; } } @@ -603,7 +604,7 @@ private: return true; } - LLVM_DEBUG(dbgs() << " Reject ExitPHI or other non-value\n"); + POLLY_DEBUG(dbgs() << " Reject ExitPHI or other non-value\n"); return false; } @@ -686,12 +687,12 @@ private: // { DomainDef[] -> Element[] } auto DefTarget = TargetElt.apply_domain(DefSched.reverse()); simplify(DefTarget); - LLVM_DEBUG(dbgs() << " Def Mapping: " << DefTarget << '\n'); + POLLY_DEBUG(dbgs() << " Def Mapping: " << DefTarget << '\n'); auto OrigDomain = getDomainFor(DefMA); auto MappedDomain = DefTarget.domain(); if (!OrigDomain.is_subset(MappedDomain)) { - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << " Reject because mapping does not encompass all instances\n"); return false; @@ -704,7 +705,7 @@ private: isl::union_map DefUses; std::tie(DefUses, Lifetime) = computeValueUses(SAI); - LLVM_DEBUG(dbgs() << " Lifetime: " << Lifetime << '\n'); + POLLY_DEBUG(dbgs() << " Lifetime: " << Lifetime << '\n'); /// { [Element[] -> Zone[]] } auto EltZone = Lifetime.apply_domain(DefTarget).wrap(); @@ -858,12 +859,12 @@ private: // { DomainRead[] -> Element[] } auto PHITarget = PHISched.apply_range(TargetElt); simplify(PHITarget); - LLVM_DEBUG(dbgs() << " Mapping: " << PHITarget << '\n'); + POLLY_DEBUG(dbgs() << " Mapping: " << PHITarget << '\n'); auto OrigDomain = getDomainFor(PHIRead); auto MappedDomain = PHITarget.domain(); if (!OrigDomain.is_subset(MappedDomain)) { - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << " Reject because mapping does not encompass all instances\n"); return false; @@ -872,7 +873,7 @@ private: // { DomainRead[] -> DomainWrite[] } auto PerPHIWrites = computePerPHI(SAI); if (PerPHIWrites.is_null()) { - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << " Reject because cannot determine incoming values\n"); return false; } @@ -894,17 +895,17 @@ private: auto ExpandedWritesDom = WritesTarget.domain(); if (!DelicmPartialWrites && !UniverseWritesDom.is_subset(ExpandedWritesDom)) { - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << " Reject because did not find PHI write mapping for " "all instances\n"); if (DelicmOverapproximateWrites) - LLVM_DEBUG(dbgs() << " Relevant Mapping: " - << RelevantWritesTarget << '\n'); - LLVM_DEBUG(dbgs() << " Deduced Mapping: " << WritesTarget - << '\n'); - LLVM_DEBUG(dbgs() << " Missing instances: " - << UniverseWritesDom.subtract(ExpandedWritesDom) - << '\n'); + POLLY_DEBUG(dbgs() << " Relevant Mapping: " + << RelevantWritesTarget << '\n'); + POLLY_DEBUG(dbgs() << " Deduced Mapping: " << WritesTarget + << '\n'); + POLLY_DEBUG(dbgs() << " Missing instances: " + << UniverseWritesDom.subtract(ExpandedWritesDom) + << '\n'); return false; } @@ -916,7 +917,7 @@ private: // { DomainRead[] -> Zone[] } auto Lifetime = betweenScatter(PerPHIWriteScatter, PHISched, false, true); simplify(Lifetime); - LLVM_DEBUG(dbgs() << " Lifetime: " << Lifetime << "\n"); + POLLY_DEBUG(dbgs() << " Lifetime: " << Lifetime << "\n"); // { DomainWrite[] -> Zone[] } auto WriteLifetime = isl::union_map(Lifetime).apply_domain(PerPHIWrites); @@ -1029,7 +1030,7 @@ private: // Use the target store's write location as a suggestion to map scalars to. auto EltTarget = Target.apply_range(TargetAccRel); simplify(EltTarget); - LLVM_DEBUG(dbgs() << " Target mapping is " << EltTarget << '\n'); + POLLY_DEBUG(dbgs() << " Target mapping is " << EltTarget << '\n'); // Stack of elements not yet processed. SmallVector<MemoryAccess *, 16> Worklist; @@ -1067,8 +1068,8 @@ private: if (Closed.count(SAI)) continue; Closed.insert(SAI); - LLVM_DEBUG(dbgs() << "\n Trying to map " << MA << " (SAI: " << SAI - << ")\n"); + POLLY_DEBUG(dbgs() << "\n Trying to map " << MA << " (SAI: " << SAI + << ")\n"); // Skip non-mappable scalars. if (!isMappable(SAI)) @@ -1076,7 +1077,7 @@ private: auto MASize = DL.getTypeAllocSize(MA->getAccessValue()->getType()); if (MASize > StoreSize) { - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << " Reject because storage size is insufficient\n"); continue; } @@ -1212,7 +1213,7 @@ public: "The only reason that these things have not been computed should " "be if the max-operations limit hit"); DeLICMOutOfQuota++; - LLVM_DEBUG(dbgs() << "DeLICM analysis exceeded max_operations\n"); + POLLY_DEBUG(dbgs() << "DeLICM analysis exceeded max_operations\n"); DebugLoc Begin, End; getDebugLocations(getBBPairForRegion(&S->getRegion()), Begin, End); OptimizationRemarkAnalysis R(DEBUG_TYPE, "OutOfQuota", Begin, @@ -1223,7 +1224,7 @@ public: } Zone = OriginalZone = Knowledge({}, EltUnused, EltKnown, EltWritten); - LLVM_DEBUG(dbgs() << "Computed Zone:\n"; OriginalZone.print(dbgs(), 4)); + POLLY_DEBUG(dbgs() << "Computed Zone:\n"; OriginalZone.print(dbgs(), 4)); assert(Zone.isUsable() && OriginalZone.isUsable()); return true; @@ -1245,8 +1246,8 @@ public: continue; if (MA->isMayWrite()) { - LLVM_DEBUG(dbgs() << "Access " << MA - << " pruned because it is a MAY_WRITE\n"); + POLLY_DEBUG(dbgs() << "Access " << MA + << " pruned because it is a MAY_WRITE\n"); OptimizationRemarkMissed R(DEBUG_TYPE, "TargetMayWrite", MA->getAccessInstruction()); R << "Skipped possible mapping target because it is not an " @@ -1256,8 +1257,8 @@ public: } if (Stmt.getNumIterators() == 0) { - LLVM_DEBUG(dbgs() << "Access " << MA - << " pruned because it is not in a loop\n"); + POLLY_DEBUG(dbgs() << "Access " << MA + << " pruned because it is not in a loop\n"); OptimizationRemarkMissed R(DEBUG_TYPE, "WriteNotInLoop", MA->getAccessInstruction()); R << "skipped possible mapping target because it is not in a loop"; @@ -1266,9 +1267,9 @@ public: } if (isScalarAccess(MA)) { - LLVM_DEBUG(dbgs() - << "Access " << MA - << " pruned because it writes only a single element\n"); + POLLY_DEBUG(dbgs() + << "Access " << MA + << " pruned because it writes only a single element\n"); OptimizationRemarkMissed R(DEBUG_TYPE, "ScalarWrite", MA->getAccessInstruction()); R << "skipped possible mapping target because the memory location " @@ -1278,8 +1279,8 @@ public: } if (!isa<StoreInst>(MA->getAccessInstruction())) { - LLVM_DEBUG(dbgs() << "Access " << MA - << " pruned because it is not a StoreInst\n"); + POLLY_DEBUG(dbgs() << "Access " << MA + << " pruned because it is not a StoreInst\n"); OptimizationRemarkMissed R(DEBUG_TYPE, "NotAStore", MA->getAccessInstruction()); R << "skipped possible mapping target because non-store instructions " @@ -1301,9 +1302,9 @@ public: // arguments. isl::union_map AccRel = MA->getLatestAccessRelation(); if (!AccRel.is_single_valued().is_true()) { - LLVM_DEBUG(dbgs() << "Access " << MA - << " is incompatible because it writes multiple " - "elements per instance\n"); + POLLY_DEBUG(dbgs() << "Access " << MA + << " is incompatible because it writes multiple " + "elements per instance\n"); OptimizationRemarkMissed R(DEBUG_TYPE, "NonFunctionalAccRel", MA->getAccessInstruction()); R << "skipped possible mapping target because it writes more than " @@ -1314,7 +1315,7 @@ public: isl::union_set TouchedElts = AccRel.range(); if (!TouchedElts.is_subset(CompatibleElts)) { - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << "Access " << MA << " is incompatible because it touches incompatible elements\n"); @@ -1328,7 +1329,7 @@ public: assert(isCompatibleAccess(MA)); NumberOfCompatibleTargets++; - LLVM_DEBUG(dbgs() << "Analyzing target access " << MA << "\n"); + POLLY_DEBUG(dbgs() << "Analyzing target access " << MA << "\n"); if (collapseScalarsToStore(MA)) Modified = true; } @@ -1361,15 +1362,15 @@ static std::unique_ptr<DeLICMImpl> collapseToUnused(Scop &S, LoopInfo &LI) { std::unique_ptr<DeLICMImpl> Impl = std::make_unique<DeLICMImpl>(&S, &LI); if (!Impl->computeZone()) { - LLVM_DEBUG(dbgs() << "Abort because cannot reliably compute lifetimes\n"); + POLLY_DEBUG(dbgs() << "Abort because cannot reliably compute lifetimes\n"); return Impl; } - LLVM_DEBUG(dbgs() << "Collapsing scalars to unused array elements...\n"); + POLLY_DEBUG(dbgs() << "Collapsing scalars to unused array elements...\n"); Impl->greedyCollapse(); - LLVM_DEBUG(dbgs() << "\nFinal Scop:\n"); - LLVM_DEBUG(dbgs() << S); + POLLY_DEBUG(dbgs() << "\nFinal Scop:\n"); + POLLY_DEBUG(dbgs() << S); return Impl; } diff --git a/polly/lib/Transform/FlattenAlgo.cpp b/polly/lib/Transform/FlattenAlgo.cpp index f8ed332348ab1fa9f77edd1eac51047c3d502953..27a699e5ea59ae3eac5e6cd5460cff63d905b1f7 100644 --- a/polly/lib/Transform/FlattenAlgo.cpp +++ b/polly/lib/Transform/FlattenAlgo.cpp @@ -14,6 +14,7 @@ #include "polly/FlattenAlgo.h" #include "polly/Support/ISLOStream.h" #include "polly/Support/ISLTools.h" +#include "polly/Support/PollyDebug.h" #include "llvm/Support/Debug.h" #define DEBUG_TYPE "polly-flatten-algo" @@ -171,7 +172,7 @@ isl::union_map tryFlattenSequence(isl::union_map Schedule) { // Would cause an infinite loop. if (!isDimBoundedByConstant(ScatterSet, 0)) { - LLVM_DEBUG(dbgs() << "Abort; dimension is not of fixed size\n"); + POLLY_DEBUG(dbgs() << "Abort; dimension is not of fixed size\n"); return {}; } @@ -182,8 +183,8 @@ isl::union_map tryFlattenSequence(isl::union_map Schedule) { auto Counter = isl::pw_aff(isl::local_space(ParamSpace.set_from_params())); while (!ScatterSet.is_empty()) { - LLVM_DEBUG(dbgs() << "Next counter:\n " << Counter << "\n"); - LLVM_DEBUG(dbgs() << "Remaining scatter set:\n " << ScatterSet << "\n"); + POLLY_DEBUG(dbgs() << "Next counter:\n " << Counter << "\n"); + POLLY_DEBUG(dbgs() << "Remaining scatter set:\n " << ScatterSet << "\n"); auto ThisSet = ScatterSet.project_out(isl::dim::set, 1, Dims - 1); auto ThisFirst = ThisSet.lexmin(); auto ScatterFirst = ThisFirst.add_dims(isl::dim::set, Dims - 1); @@ -199,11 +200,11 @@ isl::union_map tryFlattenSequence(isl::union_map Schedule) { auto RemainingSubSchedule = scheduleProjectOut(SubSchedule, 0, 1); auto FirstSubScatter = isl::set(FirstSubSchedule.range()); - LLVM_DEBUG(dbgs() << "Next step in sequence is:\n " << FirstSubScatter - << "\n"); + POLLY_DEBUG(dbgs() << "Next step in sequence is:\n " << FirstSubScatter + << "\n"); if (!isDimBoundedByParameter(FirstSubScatter, 0)) { - LLVM_DEBUG(dbgs() << "Abort; sequence step is not bounded\n"); + POLLY_DEBUG(dbgs() << "Abort; sequence step is not bounded\n"); return {}; } @@ -236,8 +237,8 @@ isl::union_map tryFlattenSequence(isl::union_map Schedule) { Counter = Counter.add(PartLen); } - LLVM_DEBUG(dbgs() << "Sequence-flatten result is:\n " << NewSchedule - << "\n"); + POLLY_DEBUG(dbgs() << "Sequence-flatten result is:\n " << NewSchedule + << "\n"); return NewSchedule; } @@ -266,20 +267,20 @@ isl::union_map tryFlattenLoop(isl::union_map Schedule) { SubExtent = SubExtent.project_out(isl::dim::set, 1, SubDims - 1); if (!isDimBoundedByConstant(SubExtent, 0)) { - LLVM_DEBUG(dbgs() << "Abort; dimension not bounded by constant\n"); + POLLY_DEBUG(dbgs() << "Abort; dimension not bounded by constant\n"); return {}; } auto Min = SubExtent.dim_min(0); - LLVM_DEBUG(dbgs() << "Min bound:\n " << Min << "\n"); + POLLY_DEBUG(dbgs() << "Min bound:\n " << Min << "\n"); auto MinVal = getConstant(Min, false, true); auto Max = SubExtent.dim_max(0); - LLVM_DEBUG(dbgs() << "Max bound:\n " << Max << "\n"); + POLLY_DEBUG(dbgs() << "Max bound:\n " << Max << "\n"); auto MaxVal = getConstant(Max, true, false); if (MinVal.is_null() || MaxVal.is_null() || MinVal.is_nan() || MaxVal.is_nan()) { - LLVM_DEBUG(dbgs() << "Abort; dimension bounds could not be determined\n"); + POLLY_DEBUG(dbgs() << "Abort; dimension bounds could not be determined\n"); return {}; } @@ -297,15 +298,15 @@ isl::union_map tryFlattenLoop(isl::union_map Schedule) { auto IndexMap = isl::union_map::from(Index); auto Result = IndexMap.flat_range_product(RemainingSubSchedule); - LLVM_DEBUG(dbgs() << "Loop-flatten result is:\n " << Result << "\n"); + POLLY_DEBUG(dbgs() << "Loop-flatten result is:\n " << Result << "\n"); return Result; } } // anonymous namespace isl::union_map polly::flattenSchedule(isl::union_map Schedule) { unsigned Dims = getNumScatterDims(Schedule); - LLVM_DEBUG(dbgs() << "Recursive schedule to process:\n " << Schedule - << "\n"); + POLLY_DEBUG(dbgs() << "Recursive schedule to process:\n " << Schedule + << "\n"); // Base case; no dimensions left if (Dims == 0) { @@ -319,20 +320,20 @@ isl::union_map polly::flattenSchedule(isl::union_map Schedule) { // Fixed dimension; no need to preserve variabledness. if (!isVariableDim(Schedule)) { - LLVM_DEBUG(dbgs() << "Fixed dimension; try sequence flattening\n"); + POLLY_DEBUG(dbgs() << "Fixed dimension; try sequence flattening\n"); auto NewScheduleSequence = tryFlattenSequence(Schedule); if (!NewScheduleSequence.is_null()) return NewScheduleSequence; } // Constant stride - LLVM_DEBUG(dbgs() << "Try loop flattening\n"); + POLLY_DEBUG(dbgs() << "Try loop flattening\n"); auto NewScheduleLoop = tryFlattenLoop(Schedule); if (!NewScheduleLoop.is_null()) return NewScheduleLoop; // Try again without loop condition (may blow up the number of pieces!!) - LLVM_DEBUG(dbgs() << "Try sequence flattening again\n"); + POLLY_DEBUG(dbgs() << "Try sequence flattening again\n"); auto NewScheduleSequence = tryFlattenSequence(Schedule); if (!NewScheduleSequence.is_null()) return NewScheduleSequence; diff --git a/polly/lib/Transform/FlattenSchedule.cpp b/polly/lib/Transform/FlattenSchedule.cpp index 87bf642ba0d92ba091993e018d0cac89e8125d04..f514ef359ba07863b9801d41039a8484820c25f5 100644 --- a/polly/lib/Transform/FlattenSchedule.cpp +++ b/polly/lib/Transform/FlattenSchedule.cpp @@ -18,6 +18,7 @@ #include "polly/ScopPass.h" #include "polly/Support/ISLOStream.h" #include "polly/Support/ISLTools.h" +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-flatten-schedule" using namespace polly; @@ -57,23 +58,23 @@ public: // OldSchedule. IslCtx = S.getSharedIslCtx(); - LLVM_DEBUG(dbgs() << "Going to flatten old schedule:\n"); + POLLY_DEBUG(dbgs() << "Going to flatten old schedule:\n"); OldSchedule = S.getSchedule(); - LLVM_DEBUG(printSchedule(dbgs(), OldSchedule, 2)); + POLLY_DEBUG(printSchedule(dbgs(), OldSchedule, 2)); auto Domains = S.getDomains(); auto RestrictedOldSchedule = OldSchedule.intersect_domain(Domains); - LLVM_DEBUG(dbgs() << "Old schedule with domains:\n"); - LLVM_DEBUG(printSchedule(dbgs(), RestrictedOldSchedule, 2)); + POLLY_DEBUG(dbgs() << "Old schedule with domains:\n"); + POLLY_DEBUG(printSchedule(dbgs(), RestrictedOldSchedule, 2)); auto NewSchedule = flattenSchedule(RestrictedOldSchedule); - LLVM_DEBUG(dbgs() << "Flattened new schedule:\n"); - LLVM_DEBUG(printSchedule(dbgs(), NewSchedule, 2)); + POLLY_DEBUG(dbgs() << "Flattened new schedule:\n"); + POLLY_DEBUG(printSchedule(dbgs(), NewSchedule, 2)); NewSchedule = NewSchedule.gist_domain(Domains); - LLVM_DEBUG(dbgs() << "Gisted, flattened new schedule:\n"); - LLVM_DEBUG(printSchedule(dbgs(), NewSchedule, 2)); + POLLY_DEBUG(dbgs() << "Gisted, flattened new schedule:\n"); + POLLY_DEBUG(printSchedule(dbgs(), NewSchedule, 2)); S.setSchedule(NewSchedule); return false; diff --git a/polly/lib/Transform/ForwardOpTree.cpp b/polly/lib/Transform/ForwardOpTree.cpp index 5e6de2e182a526927f1f9d9eff0641f9ce2da655..e9be6c9cdcc271c6fdc5f0921c35ee99f664339c 100644 --- a/polly/lib/Transform/ForwardOpTree.cpp +++ b/polly/lib/Transform/ForwardOpTree.cpp @@ -40,6 +40,7 @@ #include <cassert> #include <memory> +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-optree" using namespace llvm; @@ -171,7 +172,7 @@ struct ForwardingAction { Result.Decision = IsProfitable ? FD_CanForwardProfitably : FD_CanForwardLeaf; Result.Execute = [=]() { - LLVM_DEBUG(dbgs() << " trivially forwarded: " << *Val << "\n"); + POLLY_DEBUG(dbgs() << " trivially forwarded: " << *Val << "\n"); return true; }; return Result; @@ -368,12 +369,12 @@ public: Known = {}; Translator = {}; NormalizeMap = {}; - LLVM_DEBUG(dbgs() << "Known analysis exceeded max_operations\n"); + POLLY_DEBUG(dbgs() << "Known analysis exceeded max_operations\n"); return false; } KnownAnalyzed++; - LLVM_DEBUG(dbgs() << "All known: " << Known << "\n"); + POLLY_DEBUG(dbgs() << "All known: " << Known << "\n"); return true; } @@ -490,7 +491,7 @@ public: // do not add another MemoryAccess. auto ExecAction = [this, TargetStmt, LI, Access]() -> bool { TargetStmt->prependInstruction(LI); - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << " forwarded known load with preexisting MemoryAccess" << Access << "\n"); (void)Access; @@ -528,10 +529,10 @@ public: if (SameVal.is_null()) return ForwardingAction::notApplicable(); - LLVM_DEBUG(dbgs() << " expected values where " << TargetExpectedVal - << "\n"); - LLVM_DEBUG(dbgs() << " candidate elements where " << Candidates - << "\n"); + POLLY_DEBUG(dbgs() << " expected values where " << TargetExpectedVal + << "\n"); + POLLY_DEBUG(dbgs() << " candidate elements where " << Candidates + << "\n"); // { ValInst[] } isl::space ValInstSpace = ExpectedVal.get_space().range(); @@ -568,8 +569,8 @@ public: // { [TargetDomain[] -> Value[]] -> [DefDomain[] -> Value] } LocalTranslator = DefToTarget.reverse().product(ValToVal); - LLVM_DEBUG(dbgs() << " local translator is " << LocalTranslator - << "\n"); + POLLY_DEBUG(dbgs() << " local translator is " << LocalTranslator + << "\n"); if (LocalTranslator.is_null()) return ForwardingAction::notApplicable(); @@ -579,8 +580,8 @@ public: LocalTranslator]() -> bool { TargetStmt->prependInstruction(LI); MemoryAccess *Access = makeReadArrayAccess(TargetStmt, LI, SameVal); - LLVM_DEBUG(dbgs() << " forwarded known load with new MemoryAccess" - << Access << "\n"); + POLLY_DEBUG(dbgs() << " forwarded known load with new MemoryAccess" + << Access << "\n"); (void)Access; if (!LocalTranslator.is_null()) @@ -643,8 +644,8 @@ public: Access = TargetStmt->ensureValueRead(Inst); Access->setNewAccessRelation(SameVal); - LLVM_DEBUG(dbgs() << " forwarded known content of " << *Inst - << " which is " << SameVal << "\n"); + POLLY_DEBUG(dbgs() << " forwarded known content of " << *Inst + << " which is " << SameVal << "\n"); TotalReloads++; NumReloads++; return false; @@ -712,8 +713,8 @@ public: // instruction using them. TargetStmt->prependInstruction(UseInst); - LLVM_DEBUG(dbgs() << " forwarded speculable instruction: " << *UseInst - << "\n"); + POLLY_DEBUG(dbgs() << " forwarded speculable instruction: " << *UseInst + << "\n"); NumInstructionsCopied++; TotalInstructionsCopied++; return true; @@ -765,7 +766,7 @@ public: if (TargetUse.getKind() == VirtualUse::Synthesizable) return ForwardingAction::triviallyForwardable(false, UseVal); - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << " Synthesizable would not be synthesizable anymore: " << *UseVal << "\n"); return ForwardingAction::cannotForward(); @@ -779,8 +780,8 @@ public: auto ExecAction = [this, TargetStmt, UseVal]() { TargetStmt->ensureValueRead(UseVal); - LLVM_DEBUG(dbgs() << " forwarded read-only value " << *UseVal - << "\n"); + POLLY_DEBUG(dbgs() << " forwarded read-only value " << *UseVal + << "\n"); NumReadOnlyCopied++; TotalReadOnlyCopied++; @@ -830,7 +831,8 @@ public: // When no method is found to forward the operand tree, we effectively // cannot handle it. - LLVM_DEBUG(dbgs() << " Cannot forward instruction: " << *Inst << "\n"); + POLLY_DEBUG(dbgs() << " Cannot forward instruction: " << *Inst + << "\n"); return ForwardingAction::cannotForward(); } @@ -945,7 +947,7 @@ public: /// Try to forward an operand tree rooted in @p RA. bool tryForwardTree(MemoryAccess *RA) { assert(RA->isLatestScalarKind()); - LLVM_DEBUG(dbgs() << "Trying to forward operand tree " << RA << "...\n"); + POLLY_DEBUG(dbgs() << "Trying to forward operand tree " << RA << "...\n"); ScopStmt *Stmt = RA->getStatement(); Loop *InLoop = Stmt->getSurroundingLoop(); @@ -1036,22 +1038,22 @@ static std::unique_ptr<ForwardOpTreeImpl> runForwardOpTree(Scop &S, Impl = std::make_unique<ForwardOpTreeImpl>(&S, &LI, MaxOpGuard); if (AnalyzeKnown) { - LLVM_DEBUG(dbgs() << "Prepare forwarders...\n"); + POLLY_DEBUG(dbgs() << "Prepare forwarders...\n"); Impl->computeKnownValues(); } - LLVM_DEBUG(dbgs() << "Forwarding operand trees...\n"); + POLLY_DEBUG(dbgs() << "Forwarding operand trees...\n"); Impl->forwardOperandTrees(); if (MaxOpGuard.hasQuotaExceeded()) { - LLVM_DEBUG(dbgs() << "Not all operations completed because of " - "max_operations exceeded\n"); + POLLY_DEBUG(dbgs() << "Not all operations completed because of " + "max_operations exceeded\n"); KnownOutOfQuota++; } } - LLVM_DEBUG(dbgs() << "\nFinal Scop:\n"); - LLVM_DEBUG(dbgs() << S); + POLLY_DEBUG(dbgs() << "\nFinal Scop:\n"); + POLLY_DEBUG(dbgs() << S); // Update statistics Scop::ScopStatistics ScopStats = S.getStatistics(); diff --git a/polly/lib/Transform/ManualOptimizer.cpp b/polly/lib/Transform/ManualOptimizer.cpp index 264491b7577b34cdbafa88ffd31bc85202ef7c3b..0e330f207fbc489b1af6b0f181737d7397272f07 100644 --- a/polly/lib/Transform/ManualOptimizer.cpp +++ b/polly/lib/Transform/ManualOptimizer.cpp @@ -22,6 +22,7 @@ #include "llvm/Transforms/Utils/LoopUtils.h" #include <optional> +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-opt-manual" using namespace polly; @@ -159,13 +160,13 @@ private: return Result; LLVMContext &Ctx = LoopMD->getContext(); - LLVM_DEBUG(dbgs() << "Dependency violation detected\n"); + POLLY_DEBUG(dbgs() << "Dependency violation detected\n"); DebugLoc TransformLoc = findTransformationDebugLoc(LoopMD, DebugLocAttr); if (IgnoreDepcheck) { - LLVM_DEBUG(dbgs() << "Still accepting transformation due to " - "-polly-pragma-ignore-depcheck\n"); + POLLY_DEBUG(dbgs() << "Still accepting transformation due to " + "-polly-pragma-ignore-depcheck\n"); if (ORE) { ORE->emit( OptimizationRemark(DEBUG_TYPE, RemarkName, TransformLoc, CodeRegion) @@ -177,7 +178,7 @@ private: return Result; } - LLVM_DEBUG(dbgs() << "Rolling back transformation\n"); + POLLY_DEBUG(dbgs() << "Rolling back transformation\n"); if (ORE) { ORE->emit(DiagnosticInfoOptimizationFailure(DEBUG_TYPE, RemarkName, diff --git a/polly/lib/Transform/MatmulOptimizer.cpp b/polly/lib/Transform/MatmulOptimizer.cpp index 05578bd9ed11e5ee930e81f57516cf06e04f1a5c..51ae5a778e4fa3d511ce3e3aebc7ab631e23cb5b 100644 --- a/polly/lib/Transform/MatmulOptimizer.cpp +++ b/polly/lib/Transform/MatmulOptimizer.cpp @@ -42,6 +42,7 @@ #include <string> #include <vector> +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-opt-isl" using namespace llvm; @@ -1825,10 +1826,10 @@ polly::tryOptimizeMatMulPattern(isl::schedule_node Node, const Dependences *D) { TCInfoTy TCI; if (PMBasedTCOpts && isTCPattern(Node, D, TCI)) - LLVM_DEBUG(dbgs() << "The tensor contraction pattern was detected\n"); + POLLY_DEBUG(dbgs() << "The tensor contraction pattern was detected\n"); MatMulInfoTy MMI; if (PMBasedMMMOpts && isMatrMultPattern(Node, D, MMI)) { - LLVM_DEBUG(dbgs() << "The matrix multiplication pattern was detected\n"); + POLLY_DEBUG(dbgs() << "The matrix multiplication pattern was detected\n"); return optimizeMatMulPattern(Node, TTI, MMI); } return {}; diff --git a/polly/lib/Transform/ScheduleOptimizer.cpp b/polly/lib/Transform/ScheduleOptimizer.cpp index 5a0ea3b406754293ec9c2c66871882f8ce708d38..55d51982d90e76d155b07241d320be6c744dea28 100644 --- a/polly/lib/Transform/ScheduleOptimizer.cpp +++ b/polly/lib/Transform/ScheduleOptimizer.cpp @@ -69,6 +69,7 @@ class Loop; class Module; } // namespace llvm +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-opt-isl" static cl::opt<std::string> @@ -730,14 +731,14 @@ static void runIslScheduleOptimizer( // Schedule without optimizations. isl::schedule Schedule = S.getScheduleTree(); walkScheduleTreeForStatistics(S.getScheduleTree(), 0); - LLVM_DEBUG(printSchedule(dbgs(), Schedule, "Original schedule tree")); + POLLY_DEBUG(printSchedule(dbgs(), Schedule, "Original schedule tree")); bool HasUserTransformation = false; if (PragmaBasedOpts) { isl::schedule ManuallyTransformed = applyManualTransformations( &S, Schedule, GetDeps(Dependences::AL_Statement), ORE); if (ManuallyTransformed.is_null()) { - LLVM_DEBUG(dbgs() << "Error during manual optimization\n"); + POLLY_DEBUG(dbgs() << "Error during manual optimization\n"); return; } @@ -745,7 +746,7 @@ static void runIslScheduleOptimizer( // User transformations have precedence over other transformations. HasUserTransformation = true; Schedule = std::move(ManuallyTransformed); - LLVM_DEBUG( + POLLY_DEBUG( printSchedule(dbgs(), Schedule, "After manual transformations")); } } @@ -755,18 +756,18 @@ static void runIslScheduleOptimizer( // TODO: Detect disabled heuristics and no user-directed transformation // metadata earlier in ScopDetection. if (!HasUserTransformation && S.hasDisableHeuristicsHint()) { - LLVM_DEBUG(dbgs() << "Heuristic optimizations disabled by metadata\n"); + POLLY_DEBUG(dbgs() << "Heuristic optimizations disabled by metadata\n"); return; } // Get dependency analysis. const Dependences &D = GetDeps(Dependences::AL_Statement); if (D.getSharedIslCtx() != S.getSharedIslCtx()) { - LLVM_DEBUG(dbgs() << "DependenceInfo for another SCoP/isl_ctx\n"); + POLLY_DEBUG(dbgs() << "DependenceInfo for another SCoP/isl_ctx\n"); return; } if (!D.hasValidDependences()) { - LLVM_DEBUG(dbgs() << "Dependency information not available\n"); + POLLY_DEBUG(dbgs() << "Dependency information not available\n"); return; } @@ -776,9 +777,9 @@ static void runIslScheduleOptimizer( // are added by the rescheduling analyzer. Therefore, disabling the // rescheduler implicitly also disables these optimizations. if (!EnableReschedule) { - LLVM_DEBUG(dbgs() << "Skipping rescheduling due to command line option\n"); + POLLY_DEBUG(dbgs() << "Skipping rescheduling due to command line option\n"); } else if (HasUserTransformation) { - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << "Skipping rescheduling due to manual transformation\n"); } else { // Build input data. @@ -824,10 +825,10 @@ static void runIslScheduleOptimizer( "or 'no'. Falling back to default: 'yes'\n"; } - LLVM_DEBUG(dbgs() << "\n\nCompute schedule from: "); - LLVM_DEBUG(dbgs() << "Domain := " << Domain << ";\n"); - LLVM_DEBUG(dbgs() << "Proximity := " << Proximity << ";\n"); - LLVM_DEBUG(dbgs() << "Validity := " << Validity << ";\n"); + POLLY_DEBUG(dbgs() << "\n\nCompute schedule from: "); + POLLY_DEBUG(dbgs() << "Domain := " << Domain << ";\n"); + POLLY_DEBUG(dbgs() << "Proximity := " << Proximity << ";\n"); + POLLY_DEBUG(dbgs() << "Validity := " << Validity << ";\n"); int IslMaximizeBands; if (MaximizeBandDepth == "yes") { @@ -873,14 +874,14 @@ static void runIslScheduleOptimizer( Schedule = SC.compute_schedule(); if (MaxOpGuard.hasQuotaExceeded()) - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << "Schedule optimizer calculation exceeds ISL quota\n"); } isl_options_set_on_error(Ctx, OnErrorStatus); ScopsRescheduled++; - LLVM_DEBUG(printSchedule(dbgs(), Schedule, "After rescheduling")); + POLLY_DEBUG(printSchedule(dbgs(), Schedule, "After rescheduling")); } walkScheduleTreeForStatistics(Schedule, 1); @@ -908,7 +909,7 @@ static void runIslScheduleOptimizer( if (OAI.PatternOpts || OAI.Postopts || OAI.Prevect) { Schedule = ScheduleTreeOptimizer::optimizeSchedule(Schedule, &OAI); Schedule = hoistExtensionNodes(Schedule); - LLVM_DEBUG(printSchedule(dbgs(), Schedule, "After post-optimizations")); + POLLY_DEBUG(printSchedule(dbgs(), Schedule, "After post-optimizations")); walkScheduleTreeForStatistics(Schedule, 2); } diff --git a/polly/lib/Transform/ScheduleTreeTransform.cpp b/polly/lib/Transform/ScheduleTreeTransform.cpp index e42b3d1c24604bf29929116b9157f43d591adfef..f0684de825d2718979c1897e5bc666fbcdc2e12e 100644 --- a/polly/lib/Transform/ScheduleTreeTransform.cpp +++ b/polly/lib/Transform/ScheduleTreeTransform.cpp @@ -21,6 +21,7 @@ #include "llvm/IR/Metadata.h" #include "llvm/Transforms/Utils/UnrollLoop.h" +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-opt-isl" using namespace polly; @@ -599,7 +600,7 @@ public: if (Nest.size() <= 1) return getBase().visitBand(Band); - LLVM_DEBUG({ + POLLY_DEBUG({ dbgs() << "Found loops to collapse between\n"; dumpIslObj(RootBand, dbgs()); dbgs() << "and\n"; @@ -644,7 +645,7 @@ public: }; static isl::schedule collapseBands(isl::schedule Sched) { - LLVM_DEBUG(dbgs() << "Collapse bands in schedule\n"); + POLLY_DEBUG(dbgs() << "Collapse bands in schedule\n"); BandCollapseRewriter Rewriter; return Rewriter.visit(Sched); } @@ -773,7 +774,7 @@ static isl::schedule tryGreedyFuse(isl::schedule_node_band LHS, if (!canFuseOutermost(LHS, RHS, Deps)) return {}; - LLVM_DEBUG({ + POLLY_DEBUG({ dbgs() << "Found loops for greedy fusion:\n"; dumpIslObj(LHS, dbgs()); dbgs() << "and\n"; @@ -1228,12 +1229,12 @@ isl::schedule polly::applyMaxFission(isl::schedule_node BandToFission) { isl::schedule polly::applyGreedyFusion(isl::schedule Sched, const isl::union_map &Deps) { - LLVM_DEBUG(dbgs() << "Greedy loop fusion\n"); + POLLY_DEBUG(dbgs() << "Greedy loop fusion\n"); GreedyFusionRewriter Rewriter; isl::schedule Result = Rewriter.visit(Sched, Deps); if (!Rewriter.AnyChange) { - LLVM_DEBUG(dbgs() << "Found nothing to fuse\n"); + POLLY_DEBUG(dbgs() << "Found nothing to fuse\n"); return Sched; } diff --git a/polly/lib/Transform/ScopInliner.cpp b/polly/lib/Transform/ScopInliner.cpp index ca61407d2587398567b39dd9029f60e57d94cc01..b78206c1e40bade5d62f99044bf0cb8fdfb7b852 100644 --- a/polly/lib/Transform/ScopInliner.cpp +++ b/polly/lib/Transform/ScopInliner.cpp @@ -21,6 +21,7 @@ #include "llvm/Passes/PassBuilder.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-scop-inliner" using namespace llvm; @@ -60,8 +61,8 @@ public: if (!F) return false; if (F->isDeclaration()) { - LLVM_DEBUG(dbgs() << "Skipping " << F->getName() - << "because it is a declaration.\n"); + POLLY_DEBUG(dbgs() << "Skipping " << F->getName() + << "because it is a declaration.\n"); return false; } @@ -86,8 +87,8 @@ public: bool Changed = false; if (HasScopAsTopLevelRegion) { - LLVM_DEBUG(dbgs() << "Skipping " << F->getName() - << " has scop as top level region"); + POLLY_DEBUG(dbgs() << "Skipping " << F->getName() + << " has scop as top level region"); F->addFnAttr(llvm::Attribute::AlwaysInline); ModulePassManager MPM; @@ -98,8 +99,8 @@ public: if (!PA.areAllPreserved()) Changed = true; } else { - LLVM_DEBUG(dbgs() << F->getName() - << " does NOT have scop as top level region\n"); + POLLY_DEBUG(dbgs() << F->getName() + << " does NOT have scop as top level region\n"); } return Changed; diff --git a/polly/lib/Transform/Simplify.cpp b/polly/lib/Transform/Simplify.cpp index 41a155a41de83d1071b0ff228031c39d5218513b..75e91cd1c031a9f2bb75583185917a651354b422 100644 --- a/polly/lib/Transform/Simplify.cpp +++ b/polly/lib/Transform/Simplify.cpp @@ -22,6 +22,7 @@ #include "llvm/Support/Debug.h" #include <optional> +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-simplify" using namespace llvm; @@ -237,8 +238,8 @@ void SimplifyImpl::removeEmptyDomainStmts() { assert(NumStmtsBefore >= S->getSize()); EmptyDomainsRemoved = NumStmtsBefore - S->getSize(); - LLVM_DEBUG(dbgs() << "Removed " << EmptyDomainsRemoved << " (of " - << NumStmtsBefore << ") statements with empty domains \n"); + POLLY_DEBUG(dbgs() << "Removed " << EmptyDomainsRemoved << " (of " + << NumStmtsBefore << ") statements with empty domains \n"); TotalEmptyDomainsRemoved[CallNo] += EmptyDomainsRemoved; } @@ -280,8 +281,8 @@ void SimplifyImpl::removeOverwrites() { // If all of a write's elements are overwritten, remove it. isl::union_map AccRelUnion = AccRel; if (AccRelUnion.is_subset(WillBeOverwritten)) { - LLVM_DEBUG(dbgs() << "Removing " << MA - << " which will be overwritten anyway\n"); + POLLY_DEBUG(dbgs() << "Removing " << MA + << " which will be overwritten anyway\n"); Stmt.removeSingleMemoryAccess(MA); OverwritesRemoved++; @@ -532,9 +533,9 @@ void SimplifyImpl::removeRedundantWrites() { isl::map AccRelStoredVal = isl::map::from_domain_and_range( AccRelWrapped, makeValueSet(StoredVal)); if (isl::union_map(AccRelStoredVal).is_subset(Known)) { - LLVM_DEBUG(dbgs() << "Cleanup of " << MA << ":\n"); - LLVM_DEBUG(dbgs() << " Scalar: " << *StoredVal << "\n"); - LLVM_DEBUG(dbgs() << " AccRel: " << AccRel << "\n"); + POLLY_DEBUG(dbgs() << "Cleanup of " << MA << ":\n"); + POLLY_DEBUG(dbgs() << " Scalar: " << *StoredVal << "\n"); + POLLY_DEBUG(dbgs() << " AccRel: " << AccRel << "\n"); Stmt.removeSingleMemoryAccess(MA); @@ -576,8 +577,8 @@ void SimplifyImpl::removeUnnecessaryStmts() { S->simplifySCoP(true); assert(NumStmtsBefore >= S->getSize()); StmtsRemoved = NumStmtsBefore - S->getSize(); - LLVM_DEBUG(dbgs() << "Removed " << StmtsRemoved << " (of " << NumStmtsBefore - << ") statements\n"); + POLLY_DEBUG(dbgs() << "Removed " << StmtsRemoved << " (of " << NumStmtsBefore + << ") statements\n"); TotalStmtsRemoved[CallNo] += StmtsRemoved; } @@ -595,7 +596,7 @@ void SimplifyImpl::removeEmptyPartialAccesses() { if (!AccRel.is_empty().is_true()) continue; - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << "Removing " << MA << " because it's a partial access that never occurs\n"); DeferredRemove.push_back(MA); @@ -628,8 +629,8 @@ void SimplifyImpl::markAndSweep(LoopInfo *LI) { for (MemoryAccess *MA : AllMAs) { if (UsedMA.count(MA)) continue; - LLVM_DEBUG(dbgs() << "Removing " << MA - << " because its value is not used\n"); + POLLY_DEBUG(dbgs() << "Removing " << MA + << " because its value is not used\n"); ScopStmt *Stmt = MA->getStatement(); Stmt->removeSingleMemoryAccess(MA); @@ -650,8 +651,8 @@ void SimplifyImpl::markAndSweep(LoopInfo *LI) { for (Instruction *Inst : AllInsts) { auto It = UsedInsts.find({&Stmt, Inst}); if (It == UsedInsts.end()) { - LLVM_DEBUG(dbgs() << "Removing "; Inst->print(dbgs()); - dbgs() << " because it is not used\n"); + POLLY_DEBUG(dbgs() << "Removing "; Inst->print(dbgs()); + dbgs() << " because it is not used\n"); DeadInstructionsRemoved++; TotalDeadInstructionsRemoved[CallNo]++; continue; @@ -708,31 +709,31 @@ void SimplifyImpl::run(Scop &S, LoopInfo *LI) { this->S = &S; ScopsProcessed[CallNo]++; - LLVM_DEBUG(dbgs() << "Removing statements that are never executed...\n"); + POLLY_DEBUG(dbgs() << "Removing statements that are never executed...\n"); removeEmptyDomainStmts(); - LLVM_DEBUG(dbgs() << "Removing partial writes that never happen...\n"); + POLLY_DEBUG(dbgs() << "Removing partial writes that never happen...\n"); removeEmptyPartialAccesses(); - LLVM_DEBUG(dbgs() << "Removing overwrites...\n"); + POLLY_DEBUG(dbgs() << "Removing overwrites...\n"); removeOverwrites(); - LLVM_DEBUG(dbgs() << "Coalesce partial writes...\n"); + POLLY_DEBUG(dbgs() << "Coalesce partial writes...\n"); coalesceWrites(); - LLVM_DEBUG(dbgs() << "Removing redundant writes...\n"); + POLLY_DEBUG(dbgs() << "Removing redundant writes...\n"); removeRedundantWrites(); - LLVM_DEBUG(dbgs() << "Cleanup unused accesses...\n"); + POLLY_DEBUG(dbgs() << "Cleanup unused accesses...\n"); markAndSweep(LI); - LLVM_DEBUG(dbgs() << "Removing statements without side effects...\n"); + POLLY_DEBUG(dbgs() << "Removing statements without side effects...\n"); removeUnnecessaryStmts(); if (isModified()) ScopsModified[CallNo]++; - LLVM_DEBUG(dbgs() << "\nFinal Scop:\n"); - LLVM_DEBUG(dbgs() << S); + POLLY_DEBUG(dbgs() << "\nFinal Scop:\n"); + POLLY_DEBUG(dbgs() << S); auto ScopStats = S.getStatistics(); NumValueWrites[CallNo] += ScopStats.NumValueWrites; diff --git a/polly/lib/Transform/ZoneAlgo.cpp b/polly/lib/Transform/ZoneAlgo.cpp index 4c86891d2cf7de52a22ee2f42f7caeacb7ec8b82..a114a241d87a56d9863ba183ae6557599c575159 100644 --- a/polly/lib/Transform/ZoneAlgo.cpp +++ b/polly/lib/Transform/ZoneAlgo.cpp @@ -156,6 +156,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Support/raw_ostream.h" +#include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-zone" STATISTIC(NumIncompatibleArrays, "Number of not zone-analyzable arrays"); @@ -342,7 +343,7 @@ void ZoneAlgorithm::collectIncompatibleElts(ScopStmt *Stmt, if (MA->isRead()) { // Reject load after store to same location. if (!Stores.is_disjoint(AccRel)) { - LLVM_DEBUG( + POLLY_DEBUG( dbgs() << "Load after store of same element in same statement\n"); OptimizationRemarkMissed R(PassName, "LoadAfterStore", MA->getAccessInstruction()); @@ -362,7 +363,7 @@ void ZoneAlgorithm::collectIncompatibleElts(ScopStmt *Stmt, // In region statements the order is less clear, eg. the load and store // might be in a boxed loop. if (Stmt->isRegionStmt() && !Loads.is_disjoint(AccRel)) { - LLVM_DEBUG(dbgs() << "WRITE in non-affine subregion not supported\n"); + POLLY_DEBUG(dbgs() << "WRITE in non-affine subregion not supported\n"); OptimizationRemarkMissed R(PassName, "StoreInSubregion", MA->getAccessInstruction()); R << "store is in a non-affine subregion"; @@ -373,7 +374,7 @@ void ZoneAlgorithm::collectIncompatibleElts(ScopStmt *Stmt, // Do not allow more than one store to the same location. if (!Stores.is_disjoint(AccRel) && !onlySameValueWrites(Stmt)) { - LLVM_DEBUG(dbgs() << "WRITE after WRITE to same element\n"); + POLLY_DEBUG(dbgs() << "WRITE after WRITE to same element\n"); OptimizationRemarkMissed R(PassName, "StoreAfterStore", MA->getAccessInstruction()); R << "store after store of same element in same statement"; diff --git a/polly/test/Support/pollyDebug.ll b/polly/test/Support/pollyDebug.ll new file mode 100644 index 0000000000000000000000000000000000000000..ada079023b6c3048fecb914b6831939dabb3d4e9 --- /dev/null +++ b/polly/test/Support/pollyDebug.ll @@ -0,0 +1,85 @@ +; Test if "polly-debug" flag enables debug prints from different parts of polly +; RUN: opt %loadNPMPolly -O3 -polly -polly-debug --disable-output < %s 2>&1 | FileCheck %s +; +; REQUIRES: asserts + +; void callee(int n, double A[], int i) { +; for (int j = 0; j < n; j += 1) +; A[i+j] = 42.0; +; } +; +; void caller(int n, double A[]) { +; for (int i = 0; i < n; i += 1) +; callee(n, A, i); +; } + + +%unrelated_type = type { i32 } + +define internal void @callee(i32 %n, ptr noalias nonnull %A, i32 %i) #0 { +entry: + br label %for + +for: + %j = phi i32 [0, %entry], [%j.inc, %inc] + %j.cmp = icmp slt i32 %j, %n + br i1 %j.cmp, label %body, label %exit + + body: + %idx = add i32 %i, %j + %arrayidx = getelementptr inbounds double, ptr %A, i32 %idx + store double 42.0, ptr %arrayidx + br label %inc + +inc: + %j.inc = add nuw nsw i32 %j, 1 + br label %for + +exit: + br label %return + +return: + ret void +} + + +define void @caller(i32 %n, ptr noalias nonnull %A) #0 { +entry: + br label %for + +for: + %i = phi i32 [0, %entry], [%j.inc, %inc] + %i.cmp = icmp slt i32 %i, %n + br i1 %i.cmp, label %body, label %exit + + body: + call void @callee(i32 %n, ptr %A, i32 %i) + br label %inc + +inc: + %j.inc = add nuw nsw i32 %i, 1 + br label %for + +exit: + br label %return + +return: + ret void +} + + +declare void @unrelated_decl() + + +attributes #0 = { noinline } + +!llvm.ident = !{!8} +!8 = !{!"xyxxy"} + +; CHECK: Checking region: entry => <Function Return> +; CHECK: Removing statements that are never executed... +; CHECK: Final Scop: +; CHECK: Forwarding operand trees... +; CHECK: Final Scop: +; CHECK: Collapsing scalars to unused array elements... +; CHECK: Final Scop: diff --git a/utils/bazel/.bazelrc b/utils/bazel/.bazelrc index c06e9b3416263f5fd6b56f4c461d894a7e3009ca..1d7cf4a4df1b11e8e671c9d7a8f861a32c223fb1 100644 --- a/utils/bazel/.bazelrc +++ b/utils/bazel/.bazelrc @@ -30,6 +30,10 @@ build --features=layering_check # See: https://bazel.build/reference/be/functions#exports_files build --incompatible_no_implicit_file_export +# Enable so downstream users can flip this flag globally, this should +# eventually become the default +common --incompatible_disallow_empty_glob + ############################################################################### # Options to select different strategies for linking potential dependent # libraries. The default leaves it disabled. diff --git a/utils/bazel/llvm-project-overlay/bolt/BUILD.bazel b/utils/bazel/llvm-project-overlay/bolt/BUILD.bazel index 043a3b61a75f036f1f5625962f486a2769929388..1c12c8167ba46961ab88dd81fbd03e90cd89b2a0 100644 --- a/utils/bazel/llvm-project-overlay/bolt/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/bolt/BUILD.bazel @@ -221,8 +221,6 @@ cc_library( srcs = glob([ "lib/Target/AArch64/*.cpp", ]), - hdrs = glob([ - ]), includes = ["include"], deps = [ ":Core", diff --git a/utils/bazel/llvm-project-overlay/clang-tools-extra/clang-tidy/defs.bzl b/utils/bazel/llvm-project-overlay/clang-tools-extra/clang-tidy/defs.bzl index 41c03aad871c713d344fe3b2035d7569fdc535fe..387d104a773ab3b06a6a96b3accf1f26d2b5df5f 100644 --- a/utils/bazel/llvm-project-overlay/clang-tools-extra/clang-tidy/defs.bzl +++ b/utils/bazel/llvm-project-overlay/clang-tools-extra/clang-tidy/defs.bzl @@ -16,8 +16,8 @@ _common_library_deps = [ ] def clang_tidy_library(name, **kwargs): - kwargs["srcs"] = kwargs.get("srcs", native.glob([paths.join(name, "*.cpp")])) - kwargs["hdrs"] = kwargs.get("hdrs", native.glob([paths.join(name, "*.h")])) + kwargs["srcs"] = kwargs.get("srcs", native.glob([paths.join(name, "*.cpp")], allow_empty = True)) + kwargs["hdrs"] = kwargs.get("hdrs", native.glob([paths.join(name, "*.h")], allow_empty = True)) kwargs["deps"] = kwargs.get("deps", []) + _common_library_deps cc_library( name = name, diff --git a/utils/bazel/llvm-project-overlay/clang-tools-extra/clangd/BUILD.bazel b/utils/bazel/llvm-project-overlay/clang-tools-extra/clangd/BUILD.bazel new file mode 100644 index 0000000000000000000000000000000000000000..f2aa64b639985018de5a8b3f6f3e638165a5989d --- /dev/null +++ b/utils/bazel/llvm-project-overlay/clang-tools-extra/clangd/BUILD.bazel @@ -0,0 +1,71 @@ +# This file is licensed 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 + +package( + default_visibility = ["//visibility:public"], + features = ["layering_check"], +) + +licenses(["notice"]) + +# TODO: this is a shim to provide Features.inc as needed by Feature.h. +# Replace this with something that parses Features.inc.in. +genrule( + name = "gen_features_inc", + outs = ["Features.inc"], + cmd = "\n".join([ + "echo '// IWYU pragma: private, include \"Feature.h\"' >> $@", + "echo '#define CLANGD_BUILD_XPC 0' >> $@", + "echo '#define CLANGD_ENABLE_REMOTE 1' >> $@", + "echo '#define ENABLE_GRPC_REFLECTION 0' >> $@", + "echo '#define CLANGD_MALLOC_TRIM 0' >> $@", + "echo '#define CLANGD_TIDY_CHECKS 1' >> $@", + "echo '#define CLANGD_DECISION_FOREST 1' >> $@", + ]), +) + +# TODO: Pick up other files for more complete functionality, to match +# clangd/CMakeLists.txt. This might look something like +# glob(["*.cpp", "dir/**/*.cpp", ...]). +cc_library( + name = "ClangDaemon", + srcs = [ + "Feature.cpp", + "Features.inc", + "JSONTransport.cpp", + "Protocol.cpp", + "URI.cpp", + "index/SymbolID.cpp", + "support/Cancellation.cpp", + "support/Context.cpp", + "support/Logger.cpp", + "support/MemoryTree.cpp", + "support/Shutdown.cpp", + "support/ThreadCrashReporter.cpp", + "support/Trace.cpp", + ], + hdrs = [ + "Feature.h", + "LSPBinder.h", + "Protocol.h", + "Transport.h", + "URI.h", + "index/SymbolID.h", + "support/Cancellation.h", + "support/Context.h", + "support/Function.h", + "support/Logger.h", + "support/MemoryTree.h", + "support/Shutdown.h", + "support/ThreadCrashReporter.h", + "support/Trace.h", + ], + includes = ["."], + deps = [ + "//clang:basic", + "//clang:index", + "//llvm:Support", + "//llvm:TargetParser", + ], +) diff --git a/utils/bazel/llvm-project-overlay/clang/BUILD.bazel b/utils/bazel/llvm-project-overlay/clang/BUILD.bazel index d6b124f9d8e4c9103a76373583953582d43be82e..1bf6bee10952bababe23a6b09792a5619a36e622 100644 --- a/utils/bazel/llvm-project-overlay/clang/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/clang/BUILD.bazel @@ -62,6 +62,7 @@ gentbl( "CrossTU", "Driver", "Frontend", + "InstallAPI", "Lex", "Parse", "Refactoring", @@ -613,7 +614,6 @@ cc_library( "include/clang/Basic/Version.inc", ] + glob([ "lib/Basic/*.cpp", - "lib/Basic/*.c", "lib/Basic/*.h", "lib/Basic/Targets/*.cpp", "lib/Basic/Targets/*.h", @@ -1041,7 +1041,6 @@ cc_library( "lib/Analysis/FlowSensitive/Models/*.cpp", "lib/Analysis/FlowSensitive/*.cpp", "lib/Analysis/*.cpp", - "lib/Analysis/*.h", ]) + [ ":analysis_htmllogger_gen", ], @@ -1179,10 +1178,8 @@ gentbl( cc_library( name = "parse", - srcs = [ - ] + glob([ + srcs = glob([ "lib/Parse/*.cpp", - "lib/Parse/*.h", ]), hdrs = [ "include/clang/Parse/AttrParserStringSwitches.inc", @@ -1206,7 +1203,6 @@ cc_library( name = "ast_matchers", srcs = glob([ "lib/ASTMatchers/*.cpp", - "lib/ASTMatchers/*.h", ]), hdrs = glob(["include/clang/ASTMatchers/*.h"]), includes = ["include"], @@ -1240,7 +1236,6 @@ cc_library( name = "rewrite", srcs = glob([ "lib/Rewrite/*.cpp", - "lib/Rewrite/*.h", ]), hdrs = glob(["include/clang/Rewrite/Core/*.h"]), includes = ["include"], @@ -1274,7 +1269,6 @@ cc_library( name = "tooling_core", srcs = glob([ "lib/Tooling/Core/*.cpp", - "lib/Tooling/Core/*.h", ]), hdrs = glob(["include/clang/Tooling/Core/*.h"]), includes = ["include"], @@ -1339,11 +1333,9 @@ cc_library( name = "tooling_refactoring", srcs = glob([ "lib/Tooling/Refactoring/**/*.cpp", - "lib/Tooling/Refactoring/**/*.h", ]), hdrs = glob([ "include/clang/Tooling/Refactoring/**/*.h", - "include/clang/Tooling/Refactoring/**/*.def", ]), deps = [ ":ast", @@ -1592,9 +1584,6 @@ cc_library( srcs = glob( [ "lib/Driver/*.cpp", - "lib/Driver/*.h", - "lib/Driver/Arch/*.cpp", - "lib/Driver/Arch/*.h", "lib/Driver/ToolChains/*.cpp", "lib/Driver/ToolChains/*.h", "lib/Driver/ToolChains/Arch/*.cpp", @@ -1832,9 +1821,6 @@ cc_library( copts = ["$(STACK_FRAME_UNLIMITED)"], data = [":builtin_headers_gen"], includes = ["include"], - textual_hdrs = glob([ - "include/clang/Frontend/*.def", - ]), deps = [ ":apinotes", ":ast", @@ -1871,7 +1857,6 @@ cc_library( name = "frontend_rewrite", srcs = glob([ "lib/Frontend/Rewrite/*.cpp", - "lib/Frontend/Rewrite/*.h", ]), hdrs = glob(["include/clang/Rewrite/Frontend/*.h"]), includes = ["include"], @@ -2068,8 +2053,10 @@ cc_library( ":frontend", ":support", "//llvm:Core", + "//llvm:Demangle", "//llvm:Support", "//llvm:TextAPI", + "//llvm:TextAPIBinaryReader", ], ) @@ -2114,7 +2101,6 @@ cc_library( name = "frontend_tool", srcs = glob([ "lib/FrontendTool/*.cpp", - "lib/FrontendTool/*.h", ]), hdrs = glob(["include/clang/FrontendTool/*.h"]), includes = ["include"], @@ -2318,7 +2304,6 @@ cc_binary( testonly = 1, srcs = glob([ "tools/clang-import-test/*.cpp", - "tools/clang-import-test/*.h", ]), stamp = 0, deps = [ @@ -2348,7 +2333,6 @@ cc_library( name = "clang-driver", srcs = glob([ "tools/driver/*.cpp", - "tools/driver/*.h", ]) + ["clang-driver.cpp"], copts = [ # Disable stack frame size checks in the driver because @@ -2405,6 +2389,7 @@ cc_binary( stamp = 0, deps = [ ":basic", + ":diagnostic_defs_gen", ":frontend", ":lex", ":sema", @@ -2665,7 +2650,6 @@ cc_library( name = "extract_api", srcs = glob([ "lib/ExtractAPI/**/*.cpp", - "lib/ExtractAPI/**/*.h", ]), hdrs = glob(["include/clang/ExtractAPI/**/*.h"]), includes = ["include"], diff --git a/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel b/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel index 9bdd454e1e36412a815ffca56693e40083ed88ea..577e6c033b4e817b91130ce2bdbfd2f09c909791 100644 --- a/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel @@ -19,6 +19,10 @@ cc_library( ], # Will raise error unless supported platforms. }), + target_compatible_with = select({ + "@platforms//os:linux": [], + "//conditions:default": ["@platforms//:incompatible"], + }), ) WIN32_ONLY_FILES = [ diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 5f6c43cd6af7c12ce499c0d32ca2bd87a00b82c4..9dfe4c48184e3eb4e32a47a4de4daea646e00b6a 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -62,7 +62,48 @@ config_setting( flag_values = {":mpfr": "system"}, ) -############################## Support libraries ############################# +################################# Include Files ################################ + +libc_support_library( + name = "llvm_libc_macros_math_macros", + hdrs = ["include/llvm-libc-macros/math-macros.h"], + deps = [":llvm_libc_macros_limits_macros"], + defines = ["__FP_LOGBNAN_MIN"], +) + +libc_support_library( + name = "llvm_libc_macros_limits_macros", + hdrs = ["include/llvm-libc-macros/limits-macros.h"], +) + +libc_support_library( + name = "llvm_libc_macros_float_macros", + hdrs = ["include/llvm-libc-macros/float-macros.h"], +) + +libc_support_library( + name = "llvm_libc_macros_stdint_macros", + hdrs = ["include/llvm-libc-macros/stdint-macros.h"], +) + +libc_support_library( + name = "llvm_libc_macros_stdfix_macros", + hdrs = ["include/llvm-libc-macros/stdfix-macros.h"], + deps = [":llvm_libc_macros_float_macros"], +) + +libc_support_library( + name = "llvm_libc_types_float128", + hdrs = ["include/llvm-libc-types/float128.h"], + deps = [":llvm_libc_macros_float_macros"], +) + +libc_support_library( + name = "llvm_libc_macros_fcntl_macros", + hdrs = ["include/llvm-libc-macros/linux/fcntl-macros.h"], +) + +############################### Support libraries ############################## libc_support_library( name = "__support_macros_properties_architectures", @@ -151,10 +192,20 @@ libc_support_library( ], ) +libc_support_library( + name = "__support_cpp_iterator", + hdrs = ["src/__support/CPP/iterator.h"], + deps = [ + ":__support_cpp_type_traits", + ":__support_macros_attributes", + ], +) + libc_support_library( name = "__support_cpp_array", hdrs = ["src/__support/CPP/array.h"], deps = [ + ":__support_cpp_iterator", ":__support_macros_attributes", ], ) @@ -166,7 +217,6 @@ libc_support_library( ":__support_cpp_limits", ":__support_cpp_type_traits", ":__support_macros_attributes", - ":__support_macros_config", ":__support_macros_sanitizer", ], ) @@ -294,6 +344,7 @@ libc_support_library( "src/__support/CPP/type_traits/is_base_of.h", "src/__support/CPP/type_traits/is_class.h", "src/__support/CPP/type_traits/is_const.h", + "src/__support/CPP/type_traits/is_constant_evaluated.h", "src/__support/CPP/type_traits/is_convertible.h", "src/__support/CPP/type_traits/is_destructible.h", "src/__support/CPP/type_traits/is_enum.h", @@ -332,7 +383,6 @@ libc_support_library( ], deps = [ ":__support_macros_attributes", - ":__support_macros_config", ":__support_macros_properties_types", ":llvm_libc_macros_stdfix_macros", ], @@ -394,6 +444,7 @@ libc_support_library( hdrs = ["src/__support/fixedvector.h"], deps = [ ":__support_cpp_array", + ":__support_cpp_iterator", ], ) @@ -456,10 +507,19 @@ libc_support_library( ], ) +libc_support_library( + name = "__support_sign", + hdrs = ["src/__support/sign.h"], + deps = [ + ":__support_macros_attributes", + ], +) + libc_support_library( name = "__support_uint128", hdrs = ["src/__support/UInt128.h"], deps = [ + ":__support_macros_attributes", ":__support_macros_properties_types", ":__support_uint", ], @@ -528,6 +588,7 @@ libc_support_library( ":__support_cpp_type_traits", ":__support_ctype_utils", ":__support_str_to_num_result", + ":__support_uint128", ":errno", ], ) @@ -563,7 +624,10 @@ libc_support_library( deps = [ ":__support_common", ":__support_cpp_type_traits", + ":__support_fputil_fenv_impl", ":__support_fputil_fp_bits", + ":__support_macros_optimization", + ":__support_uint128", ], ) @@ -595,10 +659,10 @@ libc_support_library( name = "__support_math_extras", hdrs = ["src/__support/math_extras.h"], deps = [ + ":__support_cpp_bit", ":__support_cpp_limits", ":__support_cpp_type_traits", ":__support_macros_attributes", - ":__support_macros_config", ], ) @@ -669,6 +733,7 @@ libc_support_library( ":__support_macros_properties_architectures", ":__support_macros_sanitizer", ":errno", + ":llvm_libc_macros_math_macros", ], ) @@ -691,6 +756,7 @@ libc_support_library( ":__support_macros_attributes", ":__support_macros_properties_types", ":__support_math_extras", + ":__support_sign", ":__support_uint128", ], ) @@ -726,7 +792,10 @@ libc_support_library( libc_support_library( name = "__support_fputil_manipulation_functions", hdrs = ["src/__support/FPUtil/ManipulationFunctions.h"], - textual_hdrs = ["src/__support/FPUtil/x86_64/NextAfterLongDouble.h"], + textual_hdrs = [ + "src/__support/FPUtil/x86_64/NextAfterLongDouble.h", + "src/__support/FPUtil/x86_64/NextUpDownLongDouble.h", + ], deps = [ ":__support_common", ":__support_cpp_bit", @@ -738,6 +807,7 @@ libc_support_library( ":__support_fputil_normal_float", ":__support_macros_optimization", ":__support_uint128", + ":llvm_libc_macros_math_macros", ], ) @@ -751,6 +821,7 @@ libc_support_library( ":__support_fputil_fp_bits", ":__support_fputil_rounding_mode", ":__support_macros_attributes", + ":llvm_libc_macros_math_macros", ], ) @@ -930,10 +1001,7 @@ libc_support_library( libc_support_library( name = "__support_osutil_quick_exit", hdrs = ["src/__support/OSUtil/quick_exit.h"], - textual_hdrs = [ - "src/__support/OSUtil/linux/quick_exit.h", - #TODO: add support for GPU quick_exit (isn't just in a header.) - ], + srcs = ["src/__support/OSUtil/linux/quick_exit.cpp"], deps = [ ":__support_osutil_syscall", ], @@ -979,33 +1047,6 @@ libc_support_library( ], ) -libc_support_library( - name = "llvm_libc_macros_limits_macros", - hdrs = ["include/llvm-libc-macros/limits-macros.h"], -) - -libc_support_library( - name = "llvm_libc_macros_float_macros", - hdrs = ["include/llvm-libc-macros/float-macros.h"], -) - -libc_support_library( - name = "llvm_libc_macros_stdint_macros", - hdrs = ["include/llvm-libc-macros/stdint-macros.h"], -) - -libc_support_library( - name = "llvm_libc_macros_stdfix_macros", - hdrs = ["include/llvm-libc-macros/stdfix-macros.h"], - deps = [":llvm_libc_macros_float_macros"], -) - -libc_support_library( - name = "llvm_libc_types_float128", - hdrs = ["include/llvm-libc-types/float128.h"], - deps = [":llvm_libc_macros_float_macros"], -) - ############################### errno targets ################################ libc_function( @@ -1172,6 +1213,7 @@ libc_support_library( "__support_cpp_type_traits", ":__support_common", ":errno", + ":llvm_libc_macros_math_macros", ], ) @@ -1233,13 +1275,9 @@ libc_support_library( hdrs = ["src/math/generic/inv_trigf_utils.h"], deps = [ ":__support_common", - ":__support_fputil_fenv_impl", ":__support_fputil_fma", - ":__support_fputil_fp_bits", ":__support_fputil_multiply_add", - ":__support_fputil_nearest_integer", ":__support_fputil_polyeval", - ":math_utils", ], ) @@ -2279,7 +2317,6 @@ libc_support_library( ":__support_cpp_cstddef", ":__support_cpp_type_traits", ":__support_macros_attributes", - ":__support_macros_config", ":__support_macros_optimization", ":__support_macros_properties_architectures", ":__support_macros_properties_cpu_features", @@ -3004,6 +3041,7 @@ libc_support_library( deps = [ ":__support_arg_list", ":__support_common", + ":__support_cpp_algorithm", ":__support_cpp_bit", ":__support_cpp_optional", ":__support_cpp_string_view", @@ -3229,6 +3267,18 @@ libc_function( ], ) +libc_function( + name = "rename", + srcs = ["src/stdio/linux/rename.cpp"], + hdrs = ["src/stdio/rename.h"], + deps = [ + ":__support_common", + ":__support_osutil_syscall", + ":errno", + ":llvm_libc_macros_fcntl_macros", + ], +) + ############################### sys/stat targets ############################### libc_function( diff --git a/utils/bazel/llvm-project-overlay/libc/libc_build_rules.bzl b/utils/bazel/llvm-project-overlay/libc/libc_build_rules.bzl index 7d815bc4a2299c6b0194285a80b3519bb19fdb25..be59e18ffd89a9627d43882cb6d69f111983e52c 100644 --- a/utils/bazel/llvm-project-overlay/libc/libc_build_rules.bzl +++ b/utils/bazel/llvm-project-overlay/libc/libc_build_rules.bzl @@ -87,8 +87,17 @@ def libc_function( "-fno-builtin", "-fno-lax-vector-conversions", "-ftrivial-auto-var-init=pattern", + "-fno-omit-frame-pointer", + "-fstack-protector-strong", ] + # x86 targets have -mno-omit-leaf-frame-pointer. + platform_copts = selects.with_or({ + PLATFORM_CPU_X86_64: ["-mno-omit-leaf-frame-pointer"], + "//conditions:default": [], + }) + copts = copts + platform_copts + # We compile the code twice, the first target is suffixed with ".__internal__" and contains the # C++ functions in the "LIBC_NAMESPACE" namespace. This allows us to test the function in the # presence of another libc. diff --git a/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel index 4a94916e1205e0591bc1eba840486b2fe96bdbd2..d2087a3d528f44742f5e97e1ab5f367aac62c48c 100644 --- a/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel @@ -76,6 +76,7 @@ libc_support_library( deps = [ ":LibcUnitTest", ":string_utils", + "//libc:__support_cpp_array", "//libc:__support_cpp_bit", "//libc:__support_cpp_bitset", "//libc:__support_cpp_span", @@ -84,6 +85,7 @@ libc_support_library( "//libc:__support_fputil_fp_bits", "//libc:__support_fputil_fpbits_str", "//libc:__support_fputil_rounding_mode", + "//libc:llvm_libc_macros_math_macros", ], ) diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/__support/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/__support/BUILD.bazel index 6837b9880d5a41de989908d6bda4b533a6db5cbd..4f976122967c4d2dc988b8d079e866aa99371e6f 100644 --- a/utils/bazel/llvm-project-overlay/libc/test/src/__support/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/test/src/__support/BUILD.bazel @@ -64,6 +64,7 @@ libc_test( name = "integer_to_string_test", srcs = ["integer_to_string_test.cpp"], deps = [ + "//libc:__support_cpp_limits", "//libc:__support_cpp_span", "//libc:__support_cpp_string_view", "//libc:__support_integer_literals", @@ -88,6 +89,7 @@ libc_test( "//libc:__support_cpp_optional", "//libc:__support_macros_properties_types", "//libc:__support_uint", + "//libc:llvm_libc_macros_math_macros", ], ) diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/__support/FPUtil/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/__support/FPUtil/BUILD.bazel index 76443fc5d9f85b3f746c35dd8d431b4dfef7a023..18683e42724a546877bb5796fb73e85b2ec72d3d 100644 --- a/utils/bazel/llvm-project-overlay/libc/test/src/__support/FPUtil/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/test/src/__support/FPUtil/BUILD.bazel @@ -17,6 +17,7 @@ libc_test( "//libc:__support_fputil_fp_bits", "//libc:__support_fputil_fpbits_str", "//libc:__support_integer_literals", + "//libc:__support_sign", ], ) diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel index 63e18b83710918ac1abcbaab27a5acf6b4de0bbf..15e367f0aca2dc15707667e1f280550af09d5c24 100644 --- a/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/test/src/math/BUILD.bazel @@ -178,6 +178,7 @@ libc_support_library( deps = [ "//libc:__support_fputil_basic_operations", "//libc:__support_fputil_fp_bits", + "//libc:llvm_libc_macros_math_macros", "//libc/test/UnitTest:LibcUnitTest", "//libc/test/UnitTest:fp_test_helpers", "//libc/utils/MPFRWrapper:mpfr_wrapper", @@ -296,6 +297,7 @@ libc_support_library( "//libc:__support_cpp_limits", "//libc:__support_fputil_fp_bits", "//libc:__support_fputil_manipulation_functions", + "//libc:llvm_libc_macros_math_macros", "//libc/test/UnitTest:LibcUnitTest", ], ) @@ -322,6 +324,7 @@ libc_support_library( "//libc:__support_fputil_basic_operations", "//libc:__support_fputil_fenv_impl", "//libc:__support_fputil_fp_bits", + "//libc:llvm_libc_macros_math_macros", "//libc/test/UnitTest:LibcUnitTest", "//libc/test/UnitTest:fp_test_helpers", ], @@ -349,6 +352,7 @@ libc_support_library( "//libc:__support_cpp_limits", "//libc:__support_fputil_fp_bits", "//libc:__support_fputil_normal_float", + "//libc:llvm_libc_macros_math_macros", "//libc/test/UnitTest:LibcUnitTest", "//libc/test/UnitTest:fp_test_helpers", ], @@ -375,6 +379,7 @@ libc_support_library( deps = [ "//libc:__support_fputil_fenv_impl", "//libc:__support_fputil_fp_bits", + "//libc:llvm_libc_macros_math_macros", "//libc/test/UnitTest:LibcUnitTest", "//libc/test/UnitTest:fp_test_helpers", "//libc/utils/MPFRWrapper:mpfr_wrapper", @@ -411,6 +416,7 @@ libc_support_library( deps = [ "//libc:__support_fputil_fenv_impl", "//libc:__support_fputil_fp_bits", + "//libc:llvm_libc_macros_math_macros", "//libc/test/UnitTest:LibcUnitTest", "//libc/test/UnitTest:fp_test_helpers", "//libc/utils/MPFRWrapper:mpfr_wrapper", @@ -522,6 +528,7 @@ libc_support_library( "//libc:__support_cpp_type_traits", "//libc:__support_fputil_basic_operations", "//libc:__support_fputil_fp_bits", + "//libc:llvm_libc_macros_math_macros", "//libc/test/UnitTest:LibcUnitTest", "//libc/test/UnitTest:fp_test_helpers", ], diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/math/libc_math_test_rules.bzl b/utils/bazel/llvm-project-overlay/libc/test/src/math/libc_math_test_rules.bzl index aba259ba6401a59d36bb28e5da63b0c7ce670cc8..1a5868d242e80aace4bf4ff198d7cec4d72ca0ce 100644 --- a/utils/bazel/llvm-project-overlay/libc/test/src/math/libc_math_test_rules.bzl +++ b/utils/bazel/llvm-project-overlay/libc/test/src/math/libc_math_test_rules.bzl @@ -34,6 +34,7 @@ def math_test(name, hdrs = [], deps = [], **kwargs): "//libc:__support_math_extras", "//libc:__support_uint128", "//libc/test/UnitTest:fp_test_helpers", + "//libc:llvm_libc_macros_math_macros", ] + deps, **kwargs ) diff --git a/utils/bazel/llvm-project-overlay/libc/utils/MPFRWrapper/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/utils/MPFRWrapper/BUILD.bazel index 803010e8b3add5601e82f66dd012262f1aef1d00..5f59d70ecc16d0fa28539ebd86bcd0750302dd58 100644 --- a/utils/bazel/llvm-project-overlay/libc/utils/MPFRWrapper/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/utils/MPFRWrapper/BUILD.bazel @@ -46,6 +46,7 @@ libc_support_library( "//libc:__support_cpp_type_traits", "//libc:__support_fputil_fp_bits", "//libc:__support_fputil_fpbits_str", + "//libc:llvm_libc_macros_math_macros", "//libc/test/UnitTest:LibcUnitTest", "//libc/test/UnitTest:fp_test_helpers", "//libc/utils/MPFRWrapper:mpfr_impl", diff --git a/utils/bazel/llvm-project-overlay/lld/BUILD.bazel b/utils/bazel/llvm-project-overlay/lld/BUILD.bazel index 8fb71fc1f971e56c5d5b741fc744e8e5a3f507e7..5a494a13acea2d953957166ff4084174f959b3cd 100644 --- a/utils/bazel/llvm-project-overlay/lld/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/lld/BUILD.bazel @@ -187,7 +187,6 @@ cc_library( name = "MinGW", srcs = glob([ "MinGW/*.cpp", - "MinGW/*.h", ]), includes = ["MinGW"], deps = [ @@ -296,7 +295,6 @@ cc_binary( name = "lld", srcs = glob([ "tools/lld/*.cpp", - "tools/lld/*.h", ]) + ["lld-driver.cpp"], deps = [ ":COFF", diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel index 4802daa66286effa79b977bdb0918dc9ab419d1e..9cfcb7d3838ed0c0f5dd74f5c334352e7fb150aa 100644 --- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel @@ -4,8 +4,10 @@ load("@bazel_skylib//rules:common_settings.bzl", "string_flag") load("@bazel_skylib//rules:expand_template.bzl", "expand_template") +load("//mlir:tblgen.bzl", "td_library") load(":binary_alias.bzl", "binary_alias") load(":config.bzl", "llvm_config_defines") +load(":driver.bzl", "generate_driver_selects", "generate_driver_tools_def", "llvm_driver_cc_binary", "select_driver_tools") load(":enum_targets_gen.bzl", "enum_targets_gen") load(":targets.bzl", "llvm_targets") load(":tblgen.bzl", "gentbl") @@ -66,7 +68,10 @@ enum_targets_gen( llvm_target_asm_parsers = [ t for t in llvm_targets - if glob(["lib/Target/{}/AsmParser/CMakeLists.txt".format(t)]) + if glob( + ["lib/Target/{}/AsmParser/CMakeLists.txt".format(t)], + allow_empty = True, + ) ] enum_targets_gen( @@ -81,7 +86,10 @@ enum_targets_gen( llvm_target_disassemblers = [ t for t in llvm_targets - if glob(["lib/Target/{}/Disassembler/CMakeLists.txt".format(t)]) + if glob( + ["lib/Target/{}/Disassembler/CMakeLists.txt".format(t)], + allow_empty = True, + ) ] enum_targets_gen( @@ -96,7 +104,10 @@ enum_targets_gen( llvm_target_mcas = [ t for t in llvm_targets - if glob(["lib/Target/{}/MCA/CMakeLists.txt".format(t)]) + if glob( + ["lib/Target/{}/MCA/CMakeLists.txt".format(t)], + allow_empty = True, + ) ] enum_targets_gen( @@ -111,7 +122,10 @@ enum_targets_gen( llvm_target_exegesis = [ t for t in llvm_targets - if glob(["tools/llvm-exegesis/lib/{}/CMakeLists.txt".format(t)]) + if glob( + ["tools/llvm-exegesis/lib/{}/CMakeLists.txt".format(t)], + allow_empty = True, + ) ] enum_targets_gen( @@ -143,6 +157,12 @@ exports_files([ "include/llvm/Config/abi-breaking.h.cmake", ]) +td_library( + name = "OptParserTdFiles", + srcs = ["include/llvm/Option/OptParser.td"], + includes = ["include"], +) + cc_library( name = "config", hdrs = [ @@ -168,7 +188,6 @@ cc_library( name = "Demangle", srcs = glob([ "lib/Demangle/*.cpp", - "lib/Demangle/*.h", ]), hdrs = glob([ "include/llvm/Demangle/*.h", @@ -203,7 +222,6 @@ cc_library( "include/llvm/Option/*.h", ]) + select({ "@platforms//os:windows": glob([ - "lib/Support/Windows/*.h", "lib/Support/Windows/*.inc", ]), "//conditions:default": glob([ @@ -275,6 +293,10 @@ cc_library( "-ldl", "-lm", ], + "@platforms//os:macos": [ + "-pthread", + "-ldl", + ], "//conditions:default": [ "-pthread", "-ldl", @@ -315,7 +337,6 @@ cc_library( name = "LineEditor", srcs = glob([ "lib/LineEditor/*.cpp", - "lib/LineEditor/*.h", ]), hdrs = glob(["include/llvm/LineEditor/*.h"]), copts = llvm_copts, @@ -329,7 +350,6 @@ cc_library( name = "Option", srcs = glob([ "lib/Option/*.cpp", - "lib/Option/*.h", ]), hdrs = glob(["include/llvm/Option/*.h"]), copts = llvm_copts, @@ -376,8 +396,6 @@ cc_library( name = "BinaryFormat", srcs = glob([ "lib/BinaryFormat/*.cpp", - "lib/BinaryFormat/*.def", - "lib/BinaryFormat/*.h", ]), hdrs = glob([ "include/llvm/BinaryFormat/*.h", @@ -409,7 +427,6 @@ cc_library( name = "DebugInfoMSF", srcs = glob([ "lib/DebugInfo/MSF/*.cpp", - "lib/DebugInfo/MSF/*.h", ]), hdrs = glob(["include/llvm/DebugInfo/MSF/*.h"]), copts = llvm_copts, @@ -420,7 +437,6 @@ cc_library( name = "DebugInfoBTF", srcs = glob([ "lib/DebugInfo/BTF/*.cpp", - "lib/DebugInfo/BTF/*.h", ]), hdrs = glob(["include/llvm/DebugInfo/BTF/*.h"]) + [ "include/llvm/DebugInfo/BTF/BTF.def", @@ -437,7 +453,6 @@ cc_library( name = "DebugInfoCodeView", srcs = glob([ "lib/DebugInfo/CodeView/*.cpp", - "lib/DebugInfo/CodeView/*.h", ]), hdrs = glob([ "include/llvm/DebugInfo/CodeView/*.h", @@ -480,9 +495,7 @@ cc_library( name = "DebugInfoPDB", srcs = glob([ "lib/DebugInfo/PDB/*.cpp", - "lib/DebugInfo/PDB/*.h", "lib/DebugInfo/PDB/Native/*.cpp", - "lib/DebugInfo/PDB/Native/*.h", ]), hdrs = glob([ "include/llvm/DebugInfo/PDB/*.h", @@ -523,12 +536,9 @@ cc_library( name = "MC", srcs = glob([ "lib/MC/*.cpp", - "lib/MC/*.h", ]), hdrs = glob([ "include/llvm/MC/*.h", - "include/llvm/MC/*.def", - "include/llvm/MC/*.inc", ]), copts = llvm_copts, deps = [ @@ -545,7 +555,6 @@ cc_library( name = "DebugInfoDWARF", srcs = glob([ "lib/DebugInfo/DWARF/*.cpp", - "lib/DebugInfo/DWARF/*.h", ]), hdrs = glob(["include/llvm/DebugInfo/DWARF/*.h"]), copts = llvm_copts, @@ -563,7 +572,6 @@ cc_library( name = "DebugInfoGSYM", srcs = glob([ "lib/DebugInfo/GSYM/*.cpp", - "lib/DebugInfo/GSYM/*.h", ]), hdrs = glob(["include/llvm/DebugInfo/GSYM/*.h"]), copts = llvm_copts, @@ -580,7 +588,6 @@ cc_library( name = "Symbolize", srcs = glob([ "lib/DebugInfo/Symbolize/*.cpp", - "lib/DebugInfo/Symbolize/*.h", ]), hdrs = glob([ "include/llvm/DebugInfo/Symbolize/*.h", @@ -599,18 +606,44 @@ cc_library( ], ) +# Command line flag to control which tools get included in the llvm driver binary. +# The macro also generates config_setting targets used by select_driver_tools(). +generate_driver_selects(name = "driver-tools") + +generate_driver_tools_def( + name = "gen_llvm_driver_tools_def", + out = "LLVMDriverTools.def", + driver_tools = select_driver_tools(":driver-tools"), +) + +# Workaround inability to put `.def` files into `srcs` with a library +cc_library( + name = "llvm_driver_tools_def_lib", + includes = ["."], + textual_hdrs = ["LLVMDriverTools.def"], +) + +cc_binary( + name = "llvm", + srcs = glob(["tools/llvm-driver/*.cpp"]), + deps = [ + ":Support", + ":llvm_driver_tools_def_lib", + ] + select_driver_tools(":driver-tools"), +) + cc_binary( name = "llvm-min-tblgen", srcs = [ "utils/TableGen/Attributes.cpp", - "utils/TableGen/CodeGenIntrinsics.cpp", - "utils/TableGen/CodeGenIntrinsics.h", + "utils/TableGen/Basic/CodeGenIntrinsics.cpp", + "utils/TableGen/Basic/CodeGenIntrinsics.h", + "utils/TableGen/Basic/SDNodeProperties.cpp", + "utils/TableGen/Basic/SDNodeProperties.h", + "utils/TableGen/Basic/SequenceToOffsetTable.h", "utils/TableGen/DirectiveEmitter.cpp", "utils/TableGen/IntrinsicEmitter.cpp", "utils/TableGen/RISCVTargetDefEmitter.cpp", - "utils/TableGen/SDNodeProperties.cpp", - "utils/TableGen/SDNodeProperties.h", - "utils/TableGen/SequenceToOffsetTable.h", "utils/TableGen/TableGen.cpp", "utils/TableGen/VTEmitter.cpp", ], @@ -626,17 +659,17 @@ cc_binary( cc_library( name = "TableGenGlobalISel", srcs = [ - "utils/TableGen/GlobalISel/CodeExpander.cpp", + "utils/TableGen/Common/GlobalISel/CodeExpander.cpp", ], - hdrs = glob([ + hdrs = [ # We have to include these headers here as well as in the `hdrs` below # to allow the `.cpp` files to use file-relative-inclusion to find # them, even though consumers of this library use inclusion relative to # `utils/TableGen` with the `strip_includes_prefix` of this library. # This mixture appears to be incompatible with header modules. - "utils/TableGen/GlobalISel/CodeExpander.h", - "utils/TableGen/GlobalISel/CodeExpansions.h", - ]), + "utils/TableGen/Common/GlobalISel/CodeExpander.h", + "utils/TableGen/Common/GlobalISel/CodeExpansions.h", + ], copts = llvm_copts, features = ["-header_modules"], strip_include_prefix = "utils/TableGen", @@ -658,20 +691,25 @@ cc_binary( srcs = glob( [ "utils/TableGen/*.cpp", - "utils/TableGen/*.inc", "utils/TableGen/*.h", - "utils/TableGen/GlobalISel/*.cpp", - "utils/TableGen/GlobalISel/*.h", + "utils/TableGen/Basic/*.cpp", + "utils/TableGen/Basic/*.h", + "utils/TableGen/Common/*.cpp", + "utils/TableGen/Common/*.h", + "utils/TableGen/Common/GlobalISel/*.cpp", + "utils/TableGen/Common/GlobalISel/*.h", # Some tablegen sources include headers from MC, so these have to be # listed here. MC uses headers produced by tablegen, so it cannot be a # regular dependency. "include/llvm/MC/*.h", - "include/llvm/TargetParser/SubtargetFeature.h", ], - exclude = ["utils/TableGen/GlobalISel/CodeExpander.cpp"], - ), + exclude = ["utils/TableGen/Common/GlobalISel/CodeExpander.cpp"], + ) + [ + "include/llvm/TargetParser/SubtargetFeature.h", + ], copts = llvm_copts, + includes = ["utils/TableGen"], stamp = 0, deps = [ ":CodeGenTypes", @@ -821,7 +859,6 @@ cc_library( name = "BitstreamReader", srcs = glob([ "lib/Bitstream/Reader/*.cpp", - "lib/Bitstream/Reader/*.h", ]), hdrs = [ "include/llvm/Bitstream/BitCodeEnums.h", @@ -836,9 +873,6 @@ cc_library( cc_library( name = "BitstreamWriter", - srcs = glob([ - "lib/Bitstream/Writer/*.h", - ]), hdrs = [ "include/llvm/Bitstream/BitCodeEnums.h", "include/llvm/Bitstream/BitCodes.h", @@ -956,7 +990,6 @@ cc_library( name = "MCParser", srcs = glob([ "lib/MC/MCParser/*.cpp", - "lib/MC/MCParser/*.h", ]), hdrs = glob(["include/llvm/MC/MCParser/*.h"]), copts = llvm_copts, @@ -1002,11 +1035,10 @@ cc_library( srcs = glob([ "lib/TextAPI/BinaryReader/**/*.cpp", ]), - hdrs = ["include/llvm/TextAPI/DylibReader.h"] + glob( - ["lib/TextAPI/BinaryReader/**/*.h"], - ), + hdrs = ["include/llvm/TextAPI/DylibReader.h"], copts = llvm_copts, deps = [ + ":DebugInfoDWARF", ":Object", ":Support", ":TargetParser", @@ -1067,7 +1099,6 @@ cc_library( name = "ObjectYAML", srcs = glob([ "lib/ObjectYAML/*.cpp", - "lib/ObjectYAML/*.h", ]), hdrs = glob(["include/llvm/ObjectYAML/*.h"]), copts = llvm_copts, @@ -1085,7 +1116,6 @@ cc_library( name = "ProfileData", srcs = glob([ "lib/ProfileData/*.cpp", - "lib/ProfileData/*.h", ]), hdrs = glob([ "include/llvm/ProfileData/*.h", @@ -1109,7 +1139,6 @@ cc_library( name = "Coverage", srcs = glob([ "lib/ProfileData/Coverage/*.cpp", - "lib/ProfileData/Coverage/*.h", ]), hdrs = glob(["include/llvm/ProfileData/Coverage/*.h"]), copts = llvm_copts, @@ -1126,8 +1155,6 @@ cc_library( srcs = glob( [ "lib/Analysis/*.cpp", - "lib/Analysis/*.h", - "lib/Analysis/*.def", ], ), hdrs = glob( @@ -1185,7 +1212,6 @@ cc_library( name = "Target", srcs = glob([ "lib/Target/*.cpp", - "lib/Target/*.h", ]), hdrs = glob([ "include/llvm/Target/*.h", @@ -1221,14 +1247,11 @@ cc_library( name = "TargetParser", srcs = glob([ "lib/TargetParser/*.cpp", - "lib/TargetParser/*.h", ]) + select({ "@platforms//os:windows": glob([ - "lib/TargetParser/Windows/*.h", "lib/TargetParser/Windows/*.inc", ]), "//conditions:default": glob([ - "lib/TargetParser/Unix/*.h", "lib/TargetParser/Unix/*.inc", ]), }), @@ -1252,7 +1275,6 @@ cc_library( name = "DWP", srcs = glob([ "lib/DWP/*.cpp", - "lib/DWP/*.h", ]), hdrs = glob(["include/llvm/DWP/*.h"]), copts = llvm_copts, @@ -1269,7 +1291,6 @@ cc_library( name = "TransformUtils", srcs = glob([ "lib/Transforms/Utils/*.cpp", - "lib/Transforms/Utils/*.h", ]), hdrs = glob(["include/llvm/Transforms/Utils/*.h"]) + [ "include/llvm/Transforms/Utils.h", @@ -1390,7 +1411,6 @@ cc_library( name = "Scalar", srcs = glob([ "lib/Transforms/Scalar/*.cpp", - "lib/Transforms/Scalar/*.h", ]), hdrs = glob(["include/llvm/Transforms/Scalar/*.h"]) + [ "include/llvm/Transforms/Scalar.h", @@ -1432,9 +1452,6 @@ cc_library( cc_library( name = "FrontendDebug", - srcs = glob([ - "lib/Frontend/Debug/*.cpp", - ]), hdrs = glob([ "include/llvm/Frontend/Debug/*.h", ]), @@ -1530,8 +1547,6 @@ cc_library( ]), hdrs = glob([ "include/llvm/Frontend/OpenMP/*.h", - "include/llvm/Frontend/OpenMP/OMP/*.h", - "include/llvm/Frontend/*.h", ]) + [ "include/llvm/Frontend/OpenMP/OMP.h.inc", "include/llvm/Frontend/OpenMP/OMP.inc", @@ -1591,9 +1606,7 @@ cc_library( ]) + [ "include/llvm/Frontend/OpenACC/ACC.inc", ], - hdrs = glob([ - "include/llvm/Frontend/OpenACC/*.h", - ]) + ["include/llvm/Frontend/OpenACC/ACC.h.inc"], + hdrs = ["include/llvm/Frontend/OpenACC/ACC.h.inc"], copts = llvm_copts, deps = [ ":Analysis", @@ -1607,7 +1620,6 @@ cc_library( name = "AsmParser", srcs = glob([ "lib/AsmParser/*.cpp", - "lib/AsmParser/*.h", ]), hdrs = glob(["include/llvm/AsmParser/*.h"]), copts = llvm_copts, @@ -1623,7 +1635,6 @@ cc_library( name = "IRPrinter", srcs = glob([ "lib/IRPrinter/*.cpp", - "lib/IRPrinter/*.h", ]), hdrs = glob([ "include/llvm/IRPrinter/*.h", @@ -1640,7 +1651,6 @@ cc_library( name = "IRReader", srcs = glob([ "lib/IRReader/*.cpp", - "lib/IRReader/*.h", ]), hdrs = glob([ "include/llvm/IRReader/*.h", @@ -1683,7 +1693,6 @@ cc_library( name = "IPO", srcs = glob([ "lib/Transforms/IPO/*.cpp", - "lib/Transforms/IPO/*.h", ]), hdrs = glob([ "include/llvm/Transforms/IPO/*.h", @@ -1721,7 +1730,6 @@ cc_library( name = "CFGuard", srcs = glob([ "lib/Transforms/CFGuard/*.cpp", - "lib/Transforms/CFGuard/*.h", ]), hdrs = ["include/llvm/Transforms/CFGuard.h"], copts = llvm_copts, @@ -1736,7 +1744,6 @@ cc_library( name = "HipStdPar", srcs = glob([ "lib/Transforms/HipStdPar/*.cpp", - "lib/Transforms/HipStdPar/*.h", ]), hdrs = ["include/llvm/Transforms/HipStdPar/HipStdPar.h"], copts = llvm_copts, @@ -1826,7 +1833,6 @@ cc_library( copts = llvm_copts, textual_hdrs = glob([ "include/llvm/CodeGen/**/*.def", - "include/llvm/CodeGen/**/*.inc", ]), deps = [ ":AggressiveInstCombine", @@ -2305,10 +2311,13 @@ gentbl( td_file = "lib/Target/" + target["name"] + "/" + target["short_name"] + ".td", td_srcs = [ ":common_target_td_sources", - ] + glob([ - "lib/Target/" + target["name"] + "/*.td", - "lib/Target/" + target["name"] + "/GISel/*.td", - ]), + ] + glob( + [ + "lib/Target/" + target["name"] + "/*.td", + "lib/Target/" + target["name"] + "/GISel/*.td", + ], + allow_empty = True, + ), deps = target.get("tbl_deps", []), )], [cc_library( @@ -2332,43 +2341,49 @@ gentbl( # a number of targets due to crisscrossing inclusion of headers. [cc_library( name = target["name"] + "UtilsAndDesc", - srcs = glob([ - "lib/Target/" + target["name"] + "/MCTargetDesc/*.cpp", - "lib/Target/" + target["name"] + "/Utils/*.cpp", - - # We have to include these headers here as well as in the `hdrs` - # below to allow the `.cpp` files to use file-relative-inclusion to - # find them, even though consumers of this library use inclusion - # relative to the target with the `strip_includes_prefix` of this - # library. This mixture is likely incompatible with header modules. - "lib/Target/" + target["name"] + "/MCTargetDesc/*.h", - "lib/Target/" + target["name"] + "/Utils/*.h", - ]), - hdrs = glob([ - "lib/Target/" + target["name"] + "/MCTargetDesc/*.h", - "lib/Target/" + target["name"] + "/Utils/*.h", - - # This a bit of a hack to allow us to expose common, internal - # target header files to other libraries within the target via - # target-relative includes. This usage of headers is inherently - # non-modular as there is a mixture of target-relative inclusion - # using this rule and file-relative inclusion using the repeated - # listing of these headers in the `srcs` of subsequent rules. - "lib/Target/" + target["name"] + "/*.h", - - # FIXME: The entries below should be `textual_hdrs` instead of - # `hdrs`, but unfortunately that doesn't work with - # `strip_include_prefix`: - # https://github.com/bazelbuild/bazel/issues/12424 - # - # Once that issue is fixed and released, we can switch this to - # `textual_hdrs` and remove the feature disabling the various Bazel - # features (both current and under-development) that motivated the - # distinction between these two. - "lib/Target/" + target["name"] + "/*.def", - "lib/Target/" + target["name"] + "/*.inc", - "lib/Target/" + target["name"] + "/MCTargetDesc/*.def", - ]), + srcs = glob( + [ + "lib/Target/" + target["name"] + "/MCTargetDesc/*.cpp", + "lib/Target/" + target["name"] + "/Utils/*.cpp", + + # We have to include these headers here as well as in the `hdrs` + # below to allow the `.cpp` files to use file-relative-inclusion to + # find them, even though consumers of this library use inclusion + # relative to the target with the `strip_includes_prefix` of this + # library. This mixture is likely incompatible with header modules. + "lib/Target/" + target["name"] + "/MCTargetDesc/*.h", + "lib/Target/" + target["name"] + "/Utils/*.h", + ], + allow_empty = True, + ), + hdrs = glob( + [ + "lib/Target/" + target["name"] + "/MCTargetDesc/*.h", + "lib/Target/" + target["name"] + "/Utils/*.h", + + # This a bit of a hack to allow us to expose common, internal + # target header files to other libraries within the target via + # target-relative includes. This usage of headers is inherently + # non-modular as there is a mixture of target-relative inclusion + # using this rule and file-relative inclusion using the repeated + # listing of these headers in the `srcs` of subsequent rules. + "lib/Target/" + target["name"] + "/*.h", + + # FIXME: The entries below should be `textual_hdrs` instead of + # `hdrs`, but unfortunately that doesn't work with + # `strip_include_prefix`: + # https://github.com/bazelbuild/bazel/issues/12424 + # + # Once that issue is fixed and released, we can switch this to + # `textual_hdrs` and remove the feature disabling the various Bazel + # features (both current and under-development) that motivated the + # distinction between these two. + "lib/Target/" + target["name"] + "/*.def", + "lib/Target/" + target["name"] + "/*.inc", + "lib/Target/" + target["name"] + "/MCTargetDesc/*.def", + ], + allow_empty = True, + ), copts = llvm_copts, features = [ "-parse_headers", @@ -2392,20 +2407,26 @@ gentbl( )], [cc_library( name = target["name"] + "CodeGen", - srcs = glob([ - "lib/Target/" + target["name"] + "/GISel/*.cpp", - "lib/Target/" + target["name"] + "/GISel/*.h", - "lib/Target/" + target["name"] + "/*.cpp", - "lib/Target/" + target["name"] + "/*.h", - ]), + srcs = glob( + [ + "lib/Target/" + target["name"] + "/GISel/*.cpp", + "lib/Target/" + target["name"] + "/GISel/*.h", + "lib/Target/" + target["name"] + "/*.cpp", + "lib/Target/" + target["name"] + "/*.h", + ], + allow_empty = True, + ), hdrs = ["lib/Target/" + target["name"] + "/" + target["short_name"] + ".h"], copts = llvm_copts, features = ["-layering_check"], strip_include_prefix = "lib/Target/" + target["name"], - textual_hdrs = glob([ - "lib/Target/" + target["name"] + "/*.def", - "lib/Target/" + target["name"] + "/*.inc", - ]), + textual_hdrs = glob( + [ + "lib/Target/" + target["name"] + "/*.def", + "lib/Target/" + target["name"] + "/*.inc", + ], + allow_empty = True, + ), deps = [ ":Analysis", ":BinaryFormat", @@ -2430,10 +2451,13 @@ gentbl( )], [cc_library( name = target["name"] + "AsmParser", - srcs = glob([ - "lib/Target/" + target["name"] + "/AsmParser/*.cpp", - "lib/Target/" + target["name"] + "/AsmParser/*.h", - ]), + srcs = glob( + [ + "lib/Target/" + target["name"] + "/AsmParser/*.cpp", + "lib/Target/" + target["name"] + "/AsmParser/*.h", + ], + allow_empty = True, + ), copts = llvm_copts, deps = [ ":BinaryFormat", @@ -2464,9 +2488,12 @@ gentbl( # `textual_hdrs` and remove the feature disabling the various Bazel # features (both current and under-development) that motivated the # distinction between these two. - hdrs = glob([ - "lib/Target/" + target["name"] + "/Disassembler/*.h", - ]), + hdrs = glob( + [ + "lib/Target/" + target["name"] + "/Disassembler/*.h", + ], + allow_empty = True, + ), features = [ "-parse_headers", "-header_modules", @@ -2475,11 +2502,14 @@ gentbl( )], [cc_library( name = target["name"] + "Disassembler", - srcs = glob([ - "lib/Target/" + target["name"] + "/Disassembler/*.cpp", - "lib/Target/" + target["name"] + "/Disassembler/*.c", - "lib/Target/" + target["name"] + "/Disassembler/*.h", - ]), + srcs = glob( + [ + "lib/Target/" + target["name"] + "/Disassembler/*.cpp", + "lib/Target/" + target["name"] + "/Disassembler/*.c", + "lib/Target/" + target["name"] + "/Disassembler/*.h", + ], + allow_empty = True, + ), copts = llvm_copts, features = ["-layering_check"], deps = [ @@ -2497,11 +2527,14 @@ gentbl( )], [cc_library( name = target["name"] + "TargetMCA", - srcs = glob([ - "lib/Target/" + target["name"] + "/MCA/*.cpp", - "lib/Target/" + target["name"] + "/MCA/*.c", - "lib/Target/" + target["name"] + "/MCA/*.h", - ]), + srcs = glob( + [ + "lib/Target/" + target["name"] + "/MCA/*.cpp", + "lib/Target/" + target["name"] + "/MCA/*.c", + "lib/Target/" + target["name"] + "/MCA/*.h", + ], + allow_empty = True, + ), copts = llvm_copts, features = ["-layering_check"], deps = [ @@ -2559,32 +2592,15 @@ cc_library( textual_hdrs = ["lib/Passes/PassRegistry.def"], ) -cc_library( - name = "MLPolicies", - srcs = glob([ - "lib/Analysis/ML/*.cpp", - "lib/Analysis/ML/*.h", - ]), - hdrs = glob([ - "include/llvm/Analysis/ML/*.h", - ]), - copts = llvm_copts, - deps = [ - ":Analysis", - ":Core", - ":Support", - ], -) - cc_library( name = "Passes", srcs = glob([ "lib/Passes/*.cpp", - "lib/Passes/*.h", ]), hdrs = glob([ "include/llvm/Passes/*.h", "include/llvm/Passes/*.def", + "include/llvm/Passes/*.inc", ]) + ["include/llvm-c/Transforms/PassBuilder.h"], copts = llvm_copts, deps = [ @@ -2600,7 +2616,6 @@ cc_library( ":InstCombine", ":Instrumentation", ":MC", - ":MLPolicies", ":ObjCARC", ":Scalar", ":Support", @@ -2617,7 +2632,6 @@ cc_library( name = "LTO", srcs = glob([ "lib/LTO/*.cpp", - "lib/LTO/*.h", ]), hdrs = glob([ "include/llvm/LTO/*.h", @@ -2657,7 +2671,6 @@ cc_library( name = "ExecutionEngine", srcs = glob([ "lib/ExecutionEngine/*.cpp", - "lib/ExecutionEngine/*.h", "lib/ExecutionEngine/RuntimeDyld/*.cpp", "lib/ExecutionEngine/RuntimeDyld/*.h", "lib/ExecutionEngine/RuntimeDyld/Targets/*.cpp", @@ -2771,11 +2784,9 @@ cc_library( name = "OrcJIT", srcs = glob([ "lib/ExecutionEngine/Orc/*.cpp", - "lib/ExecutionEngine/Orc/*.h", ]), hdrs = glob([ "include/llvm/ExecutionEngine/Orc/*.h", - "include/llvm/ExecutionEngine/Orc/RPC/*.h", ]) + [ "include/llvm-c/LLJIT.h", "include/llvm-c/Orc.h", @@ -2899,7 +2910,6 @@ cc_library( name = "DWARFLinker", srcs = glob([ "lib/DWARFLinker/Classic/*.cpp", - "lib/DWARFLinker/Classic/*.h", ]), hdrs = glob(["include/llvm/DWARFLinker/Classic/*.h"]), copts = llvm_copts, @@ -2920,7 +2930,6 @@ cc_library( name = "DWARFLinkerBase", srcs = glob([ "lib/DWARFLinker/*.cpp", - "lib/DWARFLinker/*.h", ]), hdrs = glob(["include/llvm/DWARFLinker/*.h"]), copts = llvm_copts, @@ -3011,7 +3020,6 @@ cc_library( name = "InterfaceStub", srcs = glob([ "lib/InterfaceStub/*.cpp", - "lib/InterfaceStub/*.h", ]), hdrs = glob([ "include/llvm/InterfaceStub/*.h", @@ -3062,7 +3070,6 @@ cc_library( name = "MCA", srcs = glob([ "lib/MCA/**/*.cpp", - "lib/MCA/**/*.h", ]), hdrs = glob([ "include/llvm/MCA/**/*.h", @@ -3089,7 +3096,6 @@ cc_library( name = "XRay", srcs = glob([ "lib/XRay/*.cpp", - "lib/XRay/*.h", ]), hdrs = glob(["include/llvm/XRay/*.h"]), copts = llvm_copts, @@ -3146,21 +3152,24 @@ cc_library( cc_library( name = "Exegesis", - srcs = glob([ - "tools/llvm-exegesis/lib/*.cpp", - # We have to include these headers here as well as in the `hdrs` below - # to allow the `.cpp` files to use file-relative-inclusion to find - # them, even though consumers of this library use inclusion relative to - # `tools/llvm-exegesis/lib` with the `strip_includes_prefix` of this - # library. This mixture appears to be incompatible with header modules. - "tools/llvm-exegesis/lib/*.h", - ] + [ - "tools/llvm-exegesis/lib/{}/*.cpp".format(t) - for t in llvm_target_exegesis - ] + [ - "tools/llvm-exegesis/lib/{}/*.h".format(t) - for t in llvm_target_exegesis - ]), + srcs = glob( + [ + "tools/llvm-exegesis/lib/*.cpp", + # We have to include these headers here as well as in the `hdrs` below + # to allow the `.cpp` files to use file-relative-inclusion to find + # them, even though consumers of this library use inclusion relative to + # `tools/llvm-exegesis/lib` with the `strip_includes_prefix` of this + # library. This mixture appears to be incompatible with header modules. + "tools/llvm-exegesis/lib/*.h", + ] + [ + "tools/llvm-exegesis/lib/{}/*.cpp".format(t) + for t in llvm_target_exegesis + ] + [ + "tools/llvm-exegesis/lib/{}/*.h".format(t) + for t in llvm_target_exegesis + ], + allow_empty = True, + ), hdrs = glob(["tools/llvm-exegesis/lib/*.h"]), copts = llvm_copts, features = [ @@ -3184,8 +3193,10 @@ cc_library( ":Support", ":Target", ":config", - ":maybe_pfm", - ], + ] + select({ + "@platforms//os:linux": [":maybe_pfm"], + "//conditions:default": [], + }), ) ################################################################################ @@ -3321,23 +3332,10 @@ cc_binary( ], ) -expand_template( - name = "ar_main", - out = "llvm-ar-driver.cpp", - substitutions = { - "@TOOL_NAME@": "llvm_ar", - }, - template = "cmake/modules/llvm-driver-template.cpp.in", -) - -cc_binary( - name = "llvm-ar", - srcs = glob([ - "tools/llvm-ar/*.cpp", - "tools/llvm-ar/*.h", - ]) + ["llvm-ar-driver.cpp"], +cc_library( + name = "llvm-ar-lib", + srcs = glob(["tools/llvm-ar/*.cpp"]), copts = llvm_copts, - stamp = 0, deps = [ ":AllTargetsAsmParsers", ":AllTargetsCodeGens", @@ -3351,6 +3349,12 @@ cc_binary( ], ) +llvm_driver_cc_binary( + name = "llvm-ar", + stamp = 0, + deps = [":llvm-ar-lib"], +) + # We need to run llvm-ar with different basenames to make it run with # different behavior. binary_alias( @@ -3372,7 +3376,6 @@ cc_binary( name = "llvm-as", srcs = glob([ "tools/llvm-as/*.cpp", - "tools/llvm-as/*.h", ]), copts = llvm_copts, stamp = 0, @@ -3389,7 +3392,6 @@ cc_binary( name = "llvm-bcanalyzer", srcs = glob([ "tools/llvm-bcanalyzer/*.cpp", - "tools/llvm-bcanalyzer/*.h", ]), copts = llvm_copts, stamp = 0, @@ -3476,7 +3478,6 @@ cc_binary( name = "llvm-cvtres", srcs = glob([ "tools/llvm-cvtres/*.cpp", - "tools/llvm-cvtres/*.h", ]), copts = llvm_copts, stamp = 0, @@ -3510,7 +3511,6 @@ cc_binary( name = "llvm-cxxmap", srcs = glob([ "tools/llvm-cxxmap/*.cpp", - "tools/llvm-cxxmap/*.h", ]), copts = llvm_copts, stamp = 0, @@ -3545,7 +3545,6 @@ cc_binary( name = "llvm-cxxfilt", srcs = glob([ "tools/llvm-cxxfilt/*.cpp", - "tools/llvm-cxxfilt/*.h", ]) + ["llvm-cxxfilt-driver.cpp"], copts = llvm_copts, stamp = 0, @@ -3578,7 +3577,6 @@ cc_binary( name = "llvm-debuginfod-find", srcs = glob([ "tools/llvm-debuginfod-find/*.cpp", - "tools/llvm-debuginfod-find/*.h", ]), copts = llvm_copts, stamp = 0, @@ -3595,7 +3593,6 @@ cc_binary( name = "llvm-dis", srcs = glob([ "tools/llvm-dis/*.cpp", - "tools/llvm-dis/*.h", ]), copts = llvm_copts, stamp = 0, @@ -3690,7 +3687,6 @@ cc_binary( name = "llvm-dwp", srcs = glob([ "tools/llvm-dwp/*.cpp", - "tools/llvm-dwp/*.h", ]) + ["llvm-dwp-driver.cpp"], copts = llvm_copts, stamp = 0, @@ -3730,7 +3726,6 @@ cc_binary( name = "llvm-extract", srcs = glob([ "tools/llvm-extract/*.cpp", - "tools/llvm-extract/*.h", ]), copts = llvm_copts, stamp = 0, @@ -3772,7 +3767,6 @@ cc_binary( name = "llvm-gsymutil", srcs = glob([ "tools/llvm-gsymutil/*.cpp", - "tools/llvm-gsymutil/*.h", ]) + ["llvm-gsymutil-driver.cpp"], copts = llvm_copts, stamp = 0, @@ -3924,7 +3918,6 @@ cc_binary( name = "llvm-link", srcs = glob([ "tools/llvm-link/*.cpp", - "tools/llvm-link/*.h", ]), copts = llvm_copts, stamp = 0, @@ -3989,7 +3982,6 @@ cc_binary( name = "llvm-lto", srcs = glob([ "tools/llvm-lto/*.cpp", - "tools/llvm-lto/*.h", ]), copts = llvm_copts, stamp = 0, @@ -4012,7 +4004,6 @@ cc_binary( name = "llvm-lto2", srcs = glob([ "tools/llvm-lto2/*.cpp", - "tools/llvm-lto2/*.h", ]), copts = llvm_copts, stamp = 0, @@ -4158,7 +4149,6 @@ cc_binary( name = "llvm-mt", srcs = glob([ "tools/llvm-mt/*.cpp", - "tools/llvm-mt/*.h", ]) + ["llvm-mt-driver.cpp"], copts = llvm_copts, stamp = 0, @@ -4182,23 +4172,10 @@ gentbl( td_srcs = ["include/llvm/Option/OptParser.td"], ) -expand_template( - name = "nm_main", - out = "llvm-nm-driver.cpp", - substitutions = { - "@TOOL_NAME@": "llvm_nm", - }, - template = "cmake/modules/llvm-driver-template.cpp.in", -) - -cc_binary( - name = "llvm-nm", - srcs = glob([ - "tools/llvm-nm/*.cpp", - "tools/llvm-nm/*.h", - ]) + ["llvm-nm-driver.cpp"], +cc_library( + name = "llvm-nm-lib", + srcs = glob(["tools/llvm-nm/*.cpp"]), copts = llvm_copts, - stamp = 0, deps = [ ":AllTargetsAsmParsers", ":AllTargetsCodeGens", @@ -4215,6 +4192,12 @@ cc_binary( ], ) +llvm_driver_cc_binary( + name = "llvm-nm", + stamp = 0, + deps = [":llvm-nm-lib"], +) + gentbl( name = "llvm-objcopy-opts", strip_include_prefix = "tools/llvm-objcopy", @@ -4279,7 +4262,6 @@ cc_binary( name = "llvm-stress", srcs = glob([ "tools/llvm-stress/*.cpp", - "tools/llvm-stress/*.h", ]), copts = llvm_copts, stamp = 0, @@ -4456,7 +4438,6 @@ cc_binary( name = "llvm-profdata", srcs = glob([ "tools/llvm-profdata/*.cpp", - "tools/llvm-profdata/*.h", ]) + ["llvm-profdata-driver.cpp"], copts = llvm_copts, stamp = 0, @@ -4640,7 +4621,6 @@ cc_binary( name = "llvm-rtdyld", srcs = glob([ "tools/llvm-rtdyld/*.cpp", - "tools/llvm-rtdyld/*.h", ]), copts = llvm_copts, stamp = 0, @@ -4669,23 +4649,10 @@ gentbl( td_srcs = ["include/llvm/Option/OptParser.td"], ) -expand_template( - name = "size_main", - out = "llvm-size-driver.cpp", - substitutions = { - "@TOOL_NAME@": "llvm_size", - }, - template = "cmake/modules/llvm-driver-template.cpp.in", -) - -cc_binary( - name = "llvm-size", - srcs = glob([ - "tools/llvm-size/*.cpp", - "tools/llvm-size/*.h", - ]) + ["llvm-size-driver.cpp"], +cc_library( + name = "llvm-size-lib", + srcs = glob(["tools/llvm-size/*.cpp"]), copts = llvm_copts, - stamp = 0, deps = [ ":Object", ":Option", @@ -4694,11 +4661,16 @@ cc_binary( ], ) +llvm_driver_cc_binary( + name = "llvm-size", + stamp = 0, + deps = [":llvm-size-lib"], +) + cc_binary( name = "llvm-split", srcs = glob([ "tools/llvm-split/*.cpp", - "tools/llvm-split/*.h", ]), copts = llvm_copts, stamp = 0, @@ -4728,7 +4700,6 @@ cc_binary( name = "llvm-strings", srcs = glob([ "tools/llvm-strings/*.cpp", - "tools/llvm-strings/*.h", ]), copts = llvm_copts, stamp = 0, @@ -4765,7 +4736,6 @@ cc_binary( name = "llvm-symbolizer", srcs = glob([ "tools/llvm-symbolizer/*.cpp", - "tools/llvm-symbolizer/*.h", ]) + ["llvm-symbolizer-driver.cpp"], copts = llvm_copts, stamp = 0, @@ -4791,7 +4761,6 @@ cc_binary( name = "llvm-undname", srcs = glob([ "tools/llvm-undname/*.cpp", - "tools/llvm-undname/*.h", ]), copts = llvm_copts, stamp = 0, @@ -4805,7 +4774,6 @@ cc_binary( name = "llvm-xray", srcs = glob([ "tools/llvm-xray/*.cpp", - "tools/llvm-xray/*.cc", "tools/llvm-xray/*.h", ]), copts = llvm_copts, @@ -4888,7 +4856,6 @@ cc_binary( name = "sancov", srcs = glob([ "tools/sancov/*.cpp", - "tools/sancov/*.h", ]) + ["sancov-driver.cpp"], copts = llvm_copts, stamp = 0, @@ -4911,7 +4878,6 @@ cc_binary( name = "sanstats", srcs = glob([ "tools/sanstats/*.cpp", - "tools/sanstats/*.h", ]), copts = llvm_copts, stamp = 0, @@ -4926,7 +4892,6 @@ cc_binary( name = "split-file", srcs = glob([ "utils/split-file/*.cpp", - "utils/split-file/*.h", ]), copts = llvm_copts, stamp = 0, @@ -4972,6 +4937,7 @@ py_binary( name = "lit", testonly = True, srcs = ["utils/lit/lit.py"] + glob(["utils/lit/lit/**/*.py"]), + imports = ["utils/lit"], ) py_binary( @@ -5022,7 +4988,6 @@ cc_library( testonly = True, srcs = glob([ "lib/Testing/Support/*.cpp", - "lib/Testing/Support/*.h", ]), hdrs = glob(["include/llvm/Testing/Support/*.h"]), copts = llvm_copts, @@ -5051,7 +5016,6 @@ cc_binary( testonly = True, srcs = glob([ "utils/FileCheck/*.cpp", - "utils/FileCheck/*.h", ]), copts = llvm_copts, stamp = 0, @@ -5097,7 +5061,6 @@ cc_binary( testonly = True, srcs = glob([ "utils/count/*.c", - "utils/count/*.h", ]), stamp = 0, deps = [":Support"], @@ -5108,7 +5071,6 @@ cc_binary( testonly = True, srcs = glob([ "tools/lli/ChildTarget/*.cpp", - "tools/lli/ChildTarget/*.h", ]), copts = llvm_copts, # The tests load code into this binary that expect to see symbols @@ -5175,7 +5137,6 @@ cc_binary( testonly = True, srcs = glob([ "tools/llvm-diff/*.cpp", - "tools/llvm-diff/*.h", ]), copts = llvm_copts, stamp = 0, @@ -5193,7 +5154,6 @@ cc_binary( testonly = True, srcs = glob([ "tools/llvm-isel-fuzzer/*.cpp", - "tools/llvm-isel-fuzzer/*.h", ]), copts = llvm_copts, stamp = 0, @@ -5239,7 +5199,6 @@ cc_binary( testonly = True, srcs = glob([ "utils/not/*.cpp", - "utils/not/*.h", ]), copts = llvm_copts, stamp = 0, @@ -5319,7 +5278,6 @@ cc_binary( testonly = True, srcs = glob([ "tools/llvm-tli-checker/*.cpp", - "tools/llvm-tli-checker/*.h", ]), copts = llvm_copts, stamp = 0, @@ -5366,7 +5324,6 @@ cc_binary( name = "verify-uselistorder", srcs = glob([ "tools/verify-uselistorder/*.cpp", - "tools/verify-uselistorder/*.h", ]), copts = llvm_copts, stamp = 0, @@ -5386,7 +5343,6 @@ cc_binary( testonly = True, srcs = glob([ "tools/yaml2obj/*.cpp", - "tools/yaml2obj/*.h", ]), copts = llvm_copts, stamp = 0, diff --git a/utils/bazel/llvm-project-overlay/llvm/driver.bzl b/utils/bazel/llvm-project-overlay/llvm/driver.bzl new file mode 100644 index 0000000000000000000000000000000000000000..bd0d26d64f481bf6639a1d858f334db3cce8d2ac --- /dev/null +++ b/utils/bazel/llvm-project-overlay/llvm/driver.bzl @@ -0,0 +1,182 @@ +# This file is licensed 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 + +"""Configuration for the llvm-driver tool.""" + +load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") +load("@bazel_skylib//rules:expand_template.bzl", "expand_template") + +# Mapping from every tool to the cc_library that implements the tool's entrypoint. +# TODO: uncomment the remaining targets after splitting them +# into separate library/binary targets. +_TOOLS = { + # "clang-scan-deps": "//clang:clang-scan-deps-lib", + # "clang": "//clang:clang-driver", + # "dsymutil": "//llvm:dsymutil-lib", + # "lld": "//lld:lld-lib", + "llvm-ar": "//llvm:llvm-ar-lib", + # "llvm-cxxfilt": "//llvm:llvm-cxxfilt-lib", + # "llvm-dwp": "//llvm:llvm-dwp-lib", + # "llvm-gsymutil": "//llvm:llvm-gsymutil-lib", + # "llvm-ifs": "//llvm:llvm-ifs-lib", + # "llvm-libtool-darwin": "//llvm:llvm-libtool-darwin-lib", + # "llvm-lipo": "//llvm:llvm-lipo-lib", + # "llvm-ml": "//llvm:llvm-ml-lib", + # "llvm-mt": "//llvm:llvm-mt-lib", + "llvm-nm": "//llvm:llvm-nm-lib", + # "llvm-objcopy": "//llvm:llvm-objcopy-lib", + # "llvm-objdump": "//llvm:llvm-objdump-lib", + # "llvm-profdata": "//llvm:llvm-profdata-lib", + # "llvm-rc": "//llvm:llvm-rc-lib", + # "llvm-readobj": "//llvm:llvm-readobj-lib", + "llvm-size": "//llvm:llvm-size-lib", + # "llvm-symbolizer": "//llvm:llvm-symbolizer-lib", + # "sancov": "//llvm:sancov-lib", +} + +# Tools automatically get their own name as an alias, but there may be additional +# aliases for a given tool. +_EXTRA_ALIASES = { + "clang": ["clang++", "clang-cl", "clang-cpp"], + "lld": ["lld-link", "ld.lld", "ld64.lld", "wasm-ld"], + "llvm-ar": ["ranlib", "lib", "dlltool"], + "llvm-objcopy": ["bitcode-strip", "install-name-tool", "strip"], + "llvm-objdump": ["otool"], + "llvm-rc": ["windres"], + "llvm-readobj": ["readelf"], + "llvm-symbolizer": ["addr2line"], +} + +def _validated_string_list_flag_impl(ctx): + invalid_values = [v for v in ctx.build_setting_value if v not in ctx.attr.values] + if invalid_values: + fail("Tool(s) [{}] are not in the known list of tools: {}".format( + ", ".join(invalid_values), + ", ".join(ctx.attr.values), + )) + return BuildSettingInfo(value = ctx.build_setting_value) + +# Like string_list_flag, but with the validation that string_flag provides. +_validated_string_list_flag = rule( + implementation = _validated_string_list_flag_impl, + build_setting = config.string_list(flag = True), + attrs = { + "values": attr.string_list( + doc = "The list of allowed values for this setting. An error is raised if any other value is given.", + ), + }, + doc = "A string list-typed build setting that can be set on the command line", +) + +def generate_driver_selects(name): + """Generates flags and config settings to configure the tool list. + + By default, all supported tools are included in the "llvm" driver binary. + To build only a subset, specify just the subset you want as the flag. + For example, to produce a binary with just llvm-nm and llvm-size, run: + + $ bazel build \ + --@llvm-project//llvm:driver-tools=llvm-nm,llvm-size \ + @llvm-project//llvm:llvm + + Note: this assumes the flag name is "driver-tools" by being invoked as: + generate_driver_selects(name = "driver-tools") + + Args: + name: the name of the flag that configures which tools are included. + """ + + _validated_string_list_flag( + name = name, + build_setting_default = _TOOLS.keys(), + values = _TOOLS.keys(), + ) + for tool in _TOOLS.keys(): + native.config_setting( + name = "{}-include-{}".format(name, tool), + flag_values = {name: tool}, + ) + +def select_driver_tools(flag): + """Produce a list of tool deps based on generate_driver_selects(). + + Args: + flag: name that was used for generate_driver_selects(). + Returns: + List of tool deps based on generate_driver_selects(). + """ + tools = [] + for tool, target in _TOOLS.items(): + tools += select({ + "{}-include-{}".format(flag, tool): [target], + "//conditions:default": [], + }) + return tools + +def _generate_driver_tools_def_impl(ctx): + # Depending on how the LLVM build files are included, + # it may or may not have the @llvm-project repo prefix. + # Compare just on the name. We could also include the package, + # but the name itself is unique in practice. + label_to_name = {Label(v).name: k for k, v in _TOOLS.items()} + + # Reverse sort by the *main* tool name, but keep aliases together. + # This is consistent with how tools/llvm-driver/CMakeLists.txt does it, + # and this makes sure that more specific tools are checked first. + # For example, "clang-scan-deps" should not match "clang". + tools = [label_to_name[tool.label.name] for tool in ctx.attr.driver_tools] + tool_alias_pairs = [] + for tool_name in reversed(tools): + tool_alias_pairs.append((tool_name, tool_name)) + for extra_alias in _EXTRA_ALIASES.get(tool_name, []): + tool_alias_pairs.append((tool_name, extra_alias)) + + lines = [ + 'LLVM_DRIVER_TOOL("{alias}", {tool})'.format( + tool = tool_name.replace("-", "_"), + alias = alias.removeprefix("llvm-"), + ) + for (tool_name, alias) in tool_alias_pairs + ] + lines.append("#undef LLVM_DRIVER_TOOL") + + ctx.actions.write( + output = ctx.outputs.out, + content = "\n".join(lines), + ) + +generate_driver_tools_def = rule( + implementation = _generate_driver_tools_def_impl, + doc = """Generate a list of LLVM_DRIVER_TOOL macros. +See tools/llvm-driver/CMakeLists.txt for the reference implementation.""", + attrs = { + "driver_tools": attr.label_list( + doc = "List of tools to include in the generated header. Use select_driver_tools() to provide this.", + providers = [CcInfo], + ), + "out": attr.output( + doc = "Name of the generated .def output file.", + mandatory = True, + ), + }, +) + +def llvm_driver_cc_binary( + name, + deps = None, + **kwargs): + """cc_binary wrapper for binaries using the llvm-driver template.""" + expand_template( + name = "_gen_" + name, + out = name + "-driver.cpp", + substitutions = {"@TOOL_NAME@": name.replace("-", "_")}, + template = "//llvm:cmake/modules/llvm-driver-template.cpp.in", + ) + deps = deps or [] + native.cc_binary( + name = name, + srcs = [name + "-driver.cpp"], + deps = deps + ["//llvm:Support"], + **kwargs + ) diff --git a/utils/bazel/llvm-project-overlay/llvm/lit_test.bzl b/utils/bazel/llvm-project-overlay/llvm/lit_test.bzl index ce2a0a00c553a59eb35ec84c72a566c9f7289270..af7ae560768d6ffad3a73d26085715a4178349b5 100644 --- a/utils/bazel/llvm-project-overlay/llvm/lit_test.bzl +++ b/utils/bazel/llvm-project-overlay/llvm/lit_test.bzl @@ -10,6 +10,7 @@ def lit_test( srcs, args = None, data = None, + deps = None, **kwargs): """Runs a single test file with LLVM's lit tool. @@ -27,6 +28,7 @@ def lit_test( args = args or [] data = data or [] + deps = deps or [] native.py_test( name = name, @@ -35,6 +37,7 @@ def lit_test( args = args + ["-v"] + ["$(execpath %s)" % src for src in srcs], data = data + srcs, legacy_create_init = False, + deps = deps + [Label("//llvm:lit")], **kwargs ) diff --git a/utils/bazel/llvm-project-overlay/llvm/unittests/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/unittests/BUILD.bazel index 99b924626c2afc06b328859768fef269161b919e..dd42f84d16dc4bb5042d6d30dbfde648d33226b7 100644 --- a/utils/bazel/llvm-project-overlay/llvm/unittests/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/llvm/unittests/BUILD.bazel @@ -312,6 +312,7 @@ cc_test( "//llvm:AllTargetsAsmParsers", "//llvm:AllTargetsCodeGens", "//llvm:AsmParser", + "//llvm:BinaryFormat", "//llvm:Core", "//llvm:ExecutionEngine", "//llvm:IRReader", @@ -356,10 +357,11 @@ cc_test( [ "IR/*.cpp", "IR/*.h", - "Support/KnownBitsTest.h", ], allow_empty = False, - ), + ) + [ + "Support/KnownBitsTest.h", + ], shard_count = 20, deps = [ "//llvm:Analysis", diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel index 28a69c7ffea1f4d7d27836736ba1700f9af2a7ab..ddd3e69e6ce35f38b8348394b05cb53f87855652 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -325,21 +325,18 @@ cc_library( "lib/IR/*.cpp", "lib/IR/*.h", "lib/IR/PDL/*.cpp", - "lib/Bytecode/Reader/*.h", "lib/Bytecode/Writer/*.h", - "lib/Bytecode/*.h", + "include/mlir/Bytecode/*.h", ]) + [ "include/mlir/IR/PDLPatternMatch.h.inc", - "lib/Bytecode/BytecodeOpInterface.cpp", + "include/mlir/Interfaces/CallInterfaces.h", + "include/mlir/Interfaces/DataLayoutInterfaces.h", + "include/mlir/Interfaces/SideEffectInterfaces.h", ], hdrs = glob([ "include/mlir/IR/*.h", - "include/mlir/Bytecode/*.h", ]) + [ - "include/mlir/Interfaces/CallInterfaces.h", - "include/mlir/Interfaces/DataLayoutInterfaces.h", "include/mlir/Interfaces/FoldInterfaces.h", - "include/mlir/Interfaces/SideEffectInterfaces.h", ], includes = ["include"], deps = [ @@ -354,7 +351,6 @@ cc_library( ":BytecodeOpInterfaceIncGen", ":CallOpInterfacesIncGen", ":DataLayoutInterfacesIncGen", - ":InferTypeOpInterfaceIncGen", ":OpAsmInterfaceIncGen", ":RegionKindInterfaceIncGen", ":SideEffectInterfacesIncGen", @@ -760,6 +756,7 @@ mlir_c_api_cc_library( includes = ["include"], deps = [ ":TransformDialect", + ":TransformDialectInterfaces", ":TransformDialectTransforms", ], ) @@ -1007,6 +1004,7 @@ cc_library( ":CAPIDebugHeaders", ":CAPIIRHeaders", ":MLIRBindingsPythonHeaders", + ":Support", "//llvm:Support", "@local_config_python//:python_headers", "@pybind11", @@ -1459,13 +1457,12 @@ cc_library( ":AffineAnalysis", ":AffineDialect", ":AffineTransformOpsIncGen", - ":AffineTransforms", ":AffineUtils", - ":FuncDialect", + ":BytecodeOpInterface", ":IR", ":TransformDialect", - ":Transforms", - ":VectorDialect", + ":TransformDialectInterfaces", + ":TransformUtils", ], ) @@ -1547,10 +1544,10 @@ cc_library( deps = [ ":AMDGPUIncGen", ":ArithDialect", + ":BytecodeOpInterface", ":GPUDialect", ":IR", ":SideEffectInterfaces", - "//llvm:Core", "//llvm:Support", ], ) @@ -1572,6 +1569,7 @@ cc_library( ":FuncDialect", ":IR", ":TransformDialect", + ":TransformDialectInterfaces", ":VectorDialect", ], ) @@ -1627,7 +1625,6 @@ cc_library( srcs = glob( [ "lib/Dialect/AMDGPU/Transforms/*.cpp", - "lib/Dialect/AMDGPU/Transforms/*.h", ], ), hdrs = glob(["include/mlir/Dialect/AMDGPU/Transforms/*.h"]), @@ -1643,11 +1640,10 @@ cc_library( ":IR", ":MemRefDialect", ":Pass", + ":SideEffectInterfaces", ":Support", ":TransformUtils", - ":Transforms", ":VectorDialect", - "//llvm:Support", ], ) @@ -1657,7 +1653,6 @@ cc_library( hdrs = glob(["include/mlir/Dialect/AMDGPU/Utils/*.h"]), includes = ["include"], deps = [ - ":AMDGPUDialect", ":Support", "//llvm:Support", ], @@ -1765,7 +1760,6 @@ cc_library( name = "TargetCpp", srcs = glob([ "lib/Target/Cpp/*.cpp", - "lib/Target/Cpp/*.h", ]), hdrs = glob(["include/mlir/Target/Cpp/*.h"]), deps = [ @@ -1773,8 +1767,6 @@ cc_library( ":EmitCDialect", ":FuncDialect", ":IR", - ":MathDialect", - ":SCFDialect", ":Support", ":TranslateLib", "//llvm:Support", @@ -1923,11 +1915,10 @@ cc_library( includes = ["include"], deps = [ ":ArmNeonIncGen", + ":BytecodeOpInterface", ":IR", ":SideEffectInterfaces", ":VectorDialect", - "//llvm:Core", - "//llvm:Support", ], ) @@ -1938,17 +1929,14 @@ cc_library( includes = ["include"], deps = [ ":ArithDialect", - ":ArmNeonIncGen", ":ArmNeonDialect", + ":DialectUtils", ":FuncDialect", ":IR", ":LLVMDialect", - ":SideEffectInterfaces", ":Support", + ":TransformUtils", ":VectorDialect", - ":Transforms", - "//llvm:Core", - "//llvm:Support", ], ) @@ -1969,7 +1957,6 @@ cc_library( name = "ArmNeon2dToIntr", srcs = glob([ "lib/Conversion/ArmNeon2dToIntr/*.cpp", - "lib/Conversion/ArmNeon2dToIntr/*.h", ]), hdrs = glob([ "include/mlir/Conversion/ArmNeon2dToIntr/*.h", @@ -1978,14 +1965,9 @@ cc_library( deps = [ ":ArmNeonDialect", ":ConversionPassIncGen", - ":FuncDialect", ":IR", - ":MemRefDialect", - ":OpenACCDialect", ":Pass", - ":SCFDialect", - ":Support", - ":Transforms", + ":TransformUtils", ":VectorDialect", ], ) @@ -2191,13 +2173,13 @@ cc_library( ":ArmSMEIntrinsicOpsIncGen", ":ArmSMEOpInterfacesIncGen", ":ArmSMEOpsIncGen", + ":BytecodeOpInterface", ":IR", ":LLVMDialect", ":MemRefDialect", ":SCFDialect", ":SideEffectInterfaces", ":VectorDialect", - "//llvm:Core", "//llvm:Support", ], ) @@ -2208,7 +2190,6 @@ cc_library( hdrs = glob(["include/mlir/Dialect/ArmSME/Transforms/*.h"]), includes = ["include"], deps = [ - ":ArithDialect", ":ArithUtils", ":ArmSMEDialect", ":ArmSMETransformsPassIncGen", @@ -2221,10 +2202,8 @@ cc_library( ":LLVMDialect", ":MemRefDialect", ":Pass", - ":SCFDialect", ":SCFTransforms", - ":Transforms", - ":VectorDialect", + ":TransformUtils", "//llvm:Support", ], ) @@ -2240,7 +2219,7 @@ cc_library( ":ConversionPassIncGen", ":Pass", ":SCFDialect", - ":Transforms", + ":TransformUtils", ], ) @@ -2259,7 +2238,7 @@ cc_library( ":LLVMDialect", ":MemRefDialect", ":Pass", - ":Transforms", + ":TransformUtils", ":VectorDialect", ], ) @@ -2329,11 +2308,11 @@ cc_library( includes = ["include"], deps = [ ":ArmSVEIncGen", + ":BytecodeOpInterface", ":IR", ":LLVMDialect", ":SideEffectInterfaces", ":VectorDialect", - "//llvm:Core", "//llvm:Support", ], ) @@ -2443,11 +2422,10 @@ cc_library( includes = ["include"], deps = [ ":AMXIncGen", + ":BytecodeOpInterface", ":IR", ":LLVMDialect", ":SideEffectInterfaces", - "//llvm:Core", - "//llvm:Support", ], ) @@ -2458,12 +2436,9 @@ cc_library( includes = ["include"], deps = [ ":AMXDialect", - ":FuncDialect", ":IR", ":LLVMCommonConversion", ":LLVMDialect", - "//llvm:Core", - "//llvm:Support", ], ) @@ -2536,13 +2511,12 @@ cc_library( hdrs = ["include/mlir/Dialect/X86Vector/X86VectorDialect.h"], includes = ["include"], deps = [ + ":BytecodeOpInterface", ":IR", ":InferTypeOpInterface", ":LLVMDialect", ":SideEffectInterfaces", ":X86VectorIncGen", - "//llvm:Core", - "//llvm:Support", ], ) @@ -2553,14 +2527,12 @@ cc_library( includes = ["include"], deps = [ ":ArithDialect", - ":FuncDialect", ":IR", ":LLVMCommonConversion", ":LLVMDialect", ":VectorDialect", ":VectorUtils", ":X86VectorDialect", - "//llvm:Core", "//llvm:Support", ], ) @@ -2734,6 +2706,7 @@ cc_library( ], includes = ["include"], deps = [ + ":BytecodeOpInterface", ":Dialect", ":IR", ":IRDLAttributesIncGen", @@ -2743,6 +2716,7 @@ cc_library( ":IRDLOpsIncGen", ":IRDLTypesIncGen", ":InferTypeOpInterface", + ":SideEffectInterfaces", ":Support", "//llvm:Core", "//llvm:Support", @@ -2841,7 +2815,6 @@ cc_library( name = "SCFTransforms", srcs = glob([ "lib/Dialect/SCF/Transforms/*.cpp", - "lib/Dialect/SCF/Transforms/*.h", ]), hdrs = glob([ "include/mlir/Dialect/SCF/Transforms/*.h", @@ -2854,6 +2827,7 @@ cc_library( ":ArithDialect", ":ArithUtils", ":BufferizationDialect", + ":BufferizationInterfaces", ":BufferizationTransforms", ":DestinationStyleOpInterface", ":DialectUtils", @@ -2870,7 +2844,7 @@ cc_library( ":TensorDialect", ":TensorTransforms", ":TilingInterface", - ":Transforms", + ":TransformUtils", "//llvm:Support", ], ) @@ -2916,6 +2890,7 @@ cc_library( ":AffineUtils", ":ArithDialect", ":ArithUtils", + ":BytecodeOpInterface", ":DialectUtils", ":FuncDialect", ":IR", @@ -2924,10 +2899,9 @@ cc_library( ":SCFTransformOpsIncGen", ":SCFTransforms", ":SCFUtils", - ":SideEffectInterfaces", ":TransformDialect", + ":TransformDialectInterfaces", ":VectorDialect", - "//llvm:Support", ], ) @@ -3127,9 +3101,12 @@ cc_library( includes = ["include"], deps = [ ":ArithDialect", + ":BufferizationInterfaces", + ":BytecodeOpInterface", ":DialectUtils", ":IR", ":InferTypeOpInterface", + ":SideEffectInterfaces", ":SparseTensorAttrDefsIncGen", ":SparseTensorEnums", ":SparseTensorInterfacesIncGen", @@ -3150,13 +3127,11 @@ cc_library( includes = ["include"], deps = [ ":IR", - ":LinalgDialect", ":LinalgTransformOps", ":SparseTensorDialect", ":SparseTensorTransformOpsIncGen", - ":Support", ":TransformDialect", - "//llvm:Support", + ":TransformDialectInterfaces", ], ) @@ -3185,7 +3160,6 @@ cc_library( name = "SparseTensorTransforms", srcs = glob([ "lib/Dialect/SparseTensor/Transforms/*.cpp", - "lib/Dialect/SparseTensor/Transforms/*.h", "lib/Dialect/SparseTensor/Transforms/Utils/*.cpp", "lib/Dialect/SparseTensor/Transforms/Utils/*.h", ]), @@ -3199,6 +3173,7 @@ cc_library( ":ArithDialect", ":ArithUtils", ":BufferizationDialect", + ":BufferizationInterfaces", ":BufferizationTransforms", ":ComplexDialect", ":DialectUtils", @@ -3222,6 +3197,7 @@ cc_library( ":SparseTensorUtils", ":Support", ":TensorDialect", + ":TransformUtils", ":Transforms", ":VectorDialect", "//llvm:Support", @@ -3243,7 +3219,6 @@ cc_library( ":BufferizationTransforms", ":ConversionPasses", ":FuncDialect", - ":FuncTransforms", ":GPUDialect", ":GPUToNVVMTransforms", ":GPUTransforms", @@ -3253,10 +3228,8 @@ cc_library( ":Pass", ":SparseTensorDialect", ":SparseTensorTransforms", - ":TensorTransforms", ":Transforms", ":VectorToLLVM", - ":VectorTransforms", ], ) @@ -3391,10 +3364,12 @@ cc_library( includes = ["include"], deps = [ ":ArithDialect", + ":BytecodeOpInterface", ":DialectUtils", ":IR", ":InferTypeOpInterface", ":MeshIncGen", + ":SideEffectInterfaces", ":Support", ":ViewLikeInterface", "//llvm:Support", @@ -3442,7 +3417,7 @@ cc_library( ":Pass", ":Support", ":TensorDialect", - ":TransformUtils", + ":Transforms", "//llvm:Support", ], ) @@ -3541,12 +3516,12 @@ cc_library( hdrs = ["include/mlir/Dialect/NVGPU/IR/NVGPUDialect.h"], includes = ["include"], deps = [ + ":BytecodeOpInterface", ":GPUDialect", ":IR", ":LLVMDialect", ":NVGPUIncGen", ":SideEffectInterfaces", - "//llvm:Core", "//llvm:Support", ], ) @@ -3566,9 +3541,8 @@ cc_library( ":ArithDialect", ":ArithUtils", ":DialectUtils", - ":GPUCommonTransforms", - ":GPUCompilationAttrInterfacesIncGen", ":GPUDialect", + ":GPUToGPURuntimeTransforms", ":IR", ":LLVMCommonConversion", ":LinalgDialect", @@ -3580,8 +3554,8 @@ cc_library( ":NVVMDialect", ":SCFDialect", ":SCFTransforms", - ":Support", ":TransformDialect", + ":TransformDialectInterfaces", ":VectorDialect", "//llvm:Support", ], @@ -3642,9 +3616,7 @@ cc_library( ]), includes = ["include"], deps = [ - ":AffineDialect", ":ArithDialect", - ":FuncDialect", ":GPUDialect", ":IR", ":MemRefDialect", @@ -3653,9 +3625,7 @@ cc_library( ":Pass", ":SideEffectInterfaces", ":Support", - ":Transforms", ":VectorDialect", - "//llvm:Core", "//llvm:Support", ], ) @@ -3671,6 +3641,8 @@ td_library( deps = [ ":BuiltinDialectTdFiles", ":OpBaseTdFiles", + ":ShapedOpInterfacesTdFiles", + ":ViewLikeInterfaceTdFiles", ], ) @@ -3754,9 +3726,13 @@ cc_library( hdrs = ["include/mlir/Dialect/XeGPU/IR/XeGPU.h"], includes = ["include"], deps = [ + ":BytecodeOpInterface", + ":DialectUtils", ":IR", + ":ShapedOpInterfaces", + ":SideEffectInterfaces", + ":ViewLikeInterface", ":XeGPUIncGen", - "//llvm:Core", "//llvm:Support", ], ) @@ -3817,11 +3793,11 @@ cc_library( name = "Dialect", srcs = glob([ "lib/Dialect/*.cpp", - "lib/Dialect/*.h", - ]), - hdrs = glob([ - "include/mlir/Dialect/*.h", ]), + hdrs = glob( + include = ["include/mlir/Dialect/*.h"], + exclude = ["include/mlir/Dialect/CommonFolders.h"], + ), includes = ["include"], deps = [ ":IR", @@ -3859,14 +3835,12 @@ cc_library( name = "DialectUtils", srcs = glob([ "lib/Dialect/Utils/*.cpp", - "lib/Dialect/Utils/*.h", ]), hdrs = glob([ "include/mlir/Dialect/Utils/*.h", ]), includes = ["include"], deps = [ - ":ArithUtils", ":DialectUtilsIncGen", ":IR", ":Support", @@ -3878,7 +3852,6 @@ cc_library( name = "AffineDialect", srcs = glob([ "lib/Dialect/Affine/IR/*.cpp", - "lib/Dialect/Affine/IR/*.h", ]), hdrs = glob([ "include/mlir/Dialect/Affine/IR/*.h", @@ -3889,12 +3862,11 @@ cc_library( ":AffineOpsIncGen", ":ArithDialect", ":ControlFlowInterfaces", - ":DialectUtils", ":IR", + ":InliningUtils", ":LoopLikeInterface", ":MemRefDialect", ":ShapedOpInterfaces", - ":SideEffectInterfaces", ":Support", ":UBDialect", ":ValueBoundsOpInterface", @@ -3912,7 +3884,7 @@ cc_library( ]), includes = ["include"], deps = [ - ":CallOpInterfaces", + ":BytecodeOpInterface", ":CastInterfaces", ":ControlFlowInterfaces", ":EmitCAttributesIncGen", @@ -3954,6 +3926,8 @@ cc_library( includes = ["include"], deps = [ ":AsyncOpsIncGen", + ":BytecodeOpInterface", + ":CallOpInterfaces", ":ControlFlowInterfaces", ":FunctionInterfaces", ":IR", @@ -3987,9 +3961,6 @@ cc_library( ":SCFToControlFlow", ":Support", ":TransformUtils", - ":Transforms", - ":TransformsPassIncGen", - "//llvm:Core", "//llvm:Support", ], ) @@ -3998,7 +3969,6 @@ cc_library( name = "AffineAnalysis", srcs = glob([ "lib/Dialect/Affine/Analysis/*.cpp", - "lib/Dialect/Affine/Analysis/*.h", ]), hdrs = glob(["include/mlir/Dialect/Affine/Analysis/*.h"]), includes = ["include"], @@ -4006,8 +3976,8 @@ cc_library( ":AffineDialect", ":Analysis", ":ArithDialect", + ":CallOpInterfaces", ":DialectUtils", - ":FuncDialect", ":IR", ":SideEffectInterfaces", ":Support", @@ -4021,7 +3991,6 @@ cc_library( srcs = glob( [ "lib/Dialect/Affine/Utils/*.cpp", - "lib/Dialect/Affine/Utils/*.h", ], ), hdrs = [ @@ -4068,7 +4037,6 @@ cc_library( name = "AffineTransforms", srcs = glob([ "lib/Dialect/Affine/Transforms/*.cpp", - "lib/Dialect/Affine/Transforms/*.h", ]), hdrs = [ "include/mlir/Dialect/Affine/Passes.h", @@ -4089,8 +4057,10 @@ cc_library( ":Pass", ":SCFDialect", ":SCFUtils", + ":SideEffectInterfaces", ":Support", ":TensorDialect", + ":TransformUtils", ":Transforms", ":ValueBoundsOpInterface", ":VectorDialect", @@ -4170,11 +4140,11 @@ cc_library( ":MathToLLVM", ":MathToLibm", ":MathToSPIRV", + ":MemRefToEmitC", ":MemRefToLLVM", ":MemRefToSPIRV", ":NVGPUToNVVM", ":NVVMToLLVM", - ":OpenACCToLLVM", ":OpenACCToSCF", ":OpenMPToLLVM", ":PDLToPDLInterp", @@ -4207,7 +4177,6 @@ cc_library( name = "AsyncToLLVM", srcs = glob([ "lib/Conversion/AsyncToLLVM/*.cpp", - "lib/Conversion/AsyncToLLVM/*.h", ]), hdrs = glob(["include/mlir/Conversion/AsyncToLLVM/*.h"]), includes = ["include"], @@ -4223,8 +4192,7 @@ cc_library( ":LLVMCommonConversion", ":LLVMDialect", ":Pass", - ":Support", - ":Transforms", + ":TransformUtils", "//llvm:Support", ], ) @@ -4233,7 +4201,6 @@ cc_library( name = "AffineToStandard", srcs = glob([ "lib/Conversion/AffineToStandard/*.cpp", - "lib/Conversion/AffineToStandard/*.h", ]), hdrs = glob(["include/mlir/Conversion/AffineToStandard/*.h"]), includes = ["include"], @@ -4241,45 +4208,22 @@ cc_library( ":AffineDialect", ":AffineTransforms", ":AffineUtils", - ":ArithDialect", ":ConversionPassIncGen", - ":FuncDialect", ":IR", ":MemRefDialect", - ":Pass", ":SCFDialect", ":Support", + ":TransformUtils", ":Transforms", ":VectorDialect", ], ) -# SDBM dialect only contains attribute components that can be constructed given -# a dialect object, so whenever it is used it must also be registered. Therefore -# we don't split out the registration library for it. -cc_library( - name = "SDBM", - srcs = glob([ - "lib/Dialect/SDBM/*.cpp", - "lib/Dialect/SDBM/*.h", - ]), - hdrs = glob([ - "include/mlir/Dialect/SDBM/*.h", - ]), - includes = ["include"], - deps = [ - ":IR", - ":Support", - "//llvm:Support", - ], -) - cc_library( name = "SCFDialect", srcs = glob( [ "lib/Dialect/SCF/IR/*.cpp", - "lib/Dialect/SCF/IR/*.h", ], ), hdrs = glob( @@ -4291,20 +4235,20 @@ cc_library( deps = [ ":ArithDialect", ":ArithUtils", + ":BufferizationInterfaces", ":ControlFlowDialect", ":ControlFlowInterfaces", ":DestinationStyleOpInterface", - ":FuncDialect", ":FunctionInterfaces", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":LoopLikeInterface", ":MemRefDialect", ":ParallelCombiningOpInterface", - ":Pass", ":SCFDeviceMappingInterfacesIncGen", ":SCFIncGen", - ":SCFPassIncGen", + ":SideEffectInterfaces", ":Support", ":TensorDialect", ":ValueBoundsOpInterface", @@ -4337,7 +4281,7 @@ cc_library( ":SCFDialect", ":SideEffectInterfaces", ":Support", - ":Transforms", + ":TransformUtils", "//llvm:Support", ], ) @@ -4350,7 +4294,6 @@ cc_library( hdrs = ["include/mlir/Interfaces/Utils/InferIntRangeCommon.h"], includes = ["include"], deps = [ - ":IR", ":InferIntRangeInterface", "//llvm:Support", ], @@ -4368,6 +4311,18 @@ cc_library( ], ) +cc_library( + name = "InliningUtils", + srcs = ["lib/Transforms/Utils/InliningUtils.cpp"], + hdrs = ["include/mlir/Transforms/InliningUtils.h"], + includes = ["include"], + deps = [ + ":CallOpInterfaces", + ":IR", + "//llvm:Support", + ], +) + cc_library( name = "LoopLikeInterface", srcs = ["lib/Interfaces/LoopLikeInterface.cpp"], @@ -4389,7 +4344,6 @@ cc_library( deps = [ ":IR", ":MemorySlotInterfacesIncGen", - "//llvm:Support", ], ) @@ -4401,7 +4355,6 @@ cc_library( deps = [ ":IR", ":ShapedOpInterfacesIncGen", - "//llvm:Support", ], ) @@ -4413,7 +4366,6 @@ cc_library( deps = [ ":IR", ":ParallelCombiningOpInterfaceIncGen", - "//llvm:Support", ], ) @@ -4425,7 +4377,6 @@ cc_library( deps = [ ":IR", ":RuntimeVerifiableOpInterfaceIncGen", - "//llvm:Support", ], ) @@ -4538,13 +4489,17 @@ cc_library( includes = ["include"], deps = [ ":ArithDialect", + ":BufferizationInterfaces", + ":BytecodeOpInterface", + ":CallOpInterfaces", ":CastInterfaces", + ":CommonFolders", ":ControlFlowInterfaces", ":Dialect", - ":FuncDialect", ":FunctionInterfaces", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":MLIRShapeCanonicalizationIncGen", ":ShapeOpsIncGen", ":SideEffectInterfaces", @@ -4572,7 +4527,6 @@ cc_library( name = "ShapeToStandard", srcs = glob([ "lib/Conversion/ShapeToStandard/*.cpp", - "lib/Conversion/ShapeToStandard/*.h", ]), hdrs = ["include/mlir/Conversion/ShapeToStandard/ShapeToStandard.h"], includes = ["include"], @@ -4582,14 +4536,12 @@ cc_library( ":ConversionPassIncGen", ":FuncDialect", ":IR", - ":MemRefDialect", ":Pass", ":SCFDialect", ":ShapeDialect", ":ShapeToStandardGen", - ":Support", ":TensorDialect", - ":Transforms", + ":TransformUtils", "//llvm:Support", ], ) @@ -4612,7 +4564,6 @@ cc_library( name = "ShapeTransforms", srcs = glob([ "lib/Dialect/Shape/Transforms/*.cpp", - "lib/Dialect/Shape/Transforms/*.h", ]), hdrs = [ "include/mlir/Dialect/Shape/Analysis/ShapeMappingAnalysis.h", @@ -4623,6 +4574,7 @@ cc_library( deps = [ ":ArithDialect", ":BufferizationDialect", + ":BufferizationInterfaces", ":BufferizationTransforms", ":FuncDialect", ":IR", @@ -4631,7 +4583,7 @@ cc_library( ":ShapeDialect", ":ShapeTransformsPassIncGen", ":TensorDialect", - ":Transforms", + ":TransformUtils", "//llvm:Support", ], ) @@ -4694,7 +4646,6 @@ cc_library( srcs = glob( [ "lib/Dialect/ControlFlow/IR/*.cpp", - "lib/Dialect/ControlFlow/IR/*.h", ], ), hdrs = glob([ @@ -4703,11 +4654,13 @@ cc_library( includes = ["include"], deps = [ ":ArithDialect", - ":CommonFolders", + ":BufferizationInterfaces", + ":BytecodeOpInterface", ":ControlFlowInterfaces", ":ControlFlowOpsIncGen", ":ConvertToLLVMInterface", ":IR", + ":InliningUtils", ":SideEffectInterfaces", ":Support", "//llvm:Support", @@ -4725,6 +4678,7 @@ cc_library( includes = ["include"], deps = [ ":BufferizationDialect", + ":BufferizationInterfaces", ":BufferizationTransforms", ":ControlFlowDialect", ":IR", @@ -4737,27 +4691,23 @@ cc_library( srcs = glob( [ "lib/Dialect/Func/IR/*.cpp", - "lib/Dialect/Func/IR/*.h", - "lib/Dialect/Func/Utils/*.cpp", ], ), hdrs = glob([ "include/mlir/Dialect/Func/IR/*.h", - "include/mlir/Dialect/Func/Utils/*.h", - ]) + ["include/mlir/Transforms/InliningUtils.h"], + ]), includes = ["include"], deps = [ - ":ArithDialect", + ":BufferizationInterfaces", + ":BytecodeOpInterface", ":CallOpInterfaces", - ":CastInterfaces", - ":CommonFolders", - ":ControlFlowDialect", ":ControlFlowInterfaces", ":ConvertToLLVMInterface", ":FuncIncGen", ":FunctionInterfaces", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":SideEffectInterfaces", ":Support", "//llvm:Support", @@ -4773,7 +4723,7 @@ cc_library( ":ControlFlowDialect", ":FuncDialect", ":IR", - ":InferTypeOpInterface", + ":InliningUtils", ":MeshShardingInterface", ], ) @@ -4819,6 +4769,7 @@ cc_library( ], includes = ["include"], deps = [ + ":BytecodeOpInterface", ":FuncDialect", ":FuncToLLVM", ":FuncTransformOpsIncGen", @@ -4826,6 +4777,7 @@ cc_library( ":LLVMCommonConversion", ":LLVMDialect", ":TransformDialect", + ":TransformDialectInterfaces", ":TransformUtils", ], ) @@ -4890,7 +4842,6 @@ cc_library( name = "FuncTransforms", srcs = glob([ "lib/Dialect/Func/Transforms/*.cpp", - "lib/Dialect/Func/Transforms/*.h", ]), hdrs = glob(["include/mlir/Dialect/Func/Transforms/*.h"]), includes = ["include"], @@ -4902,9 +4853,8 @@ cc_library( ":IR", ":MemRefDialect", ":Pass", - ":SCFDialect", ":Support", - ":Transforms", + ":TransformUtils", "//llvm:Support", ], ) @@ -4922,18 +4872,22 @@ cc_library( includes = ["include"], deps = [ ":AffineDialect", + ":Analysis", ":ArithDialect", ":ArithUtils", + ":BufferizationInterfaces", + ":BytecodeOpInterface", ":ControlFlowInterfaces", - ":DataLayoutInterfaces", ":DestinationStyleOpInterface", ":DialectUtils", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":MaskableOpInterface", ":MaskingOpInterface", ":MemRefDialect", ":SideEffectInterfaces", + ":SubsetOpInterface", ":Support", ":TensorDialect", ":ValueBoundsOpInterface", @@ -4956,23 +4910,18 @@ cc_library( ], includes = ["include"], deps = [ - ":AffineDialect", - ":ArithDialect", - ":AsmParser", ":IR", ":LLVMCommonConversion", ":LLVMDialect", - ":SideEffectInterfaces", ":TransformDialect", + ":TransformDialectInterfaces", ":TransformUtils", ":VectorDialect", - ":VectorEnumsIncGen", ":VectorToLLVM", ":VectorToSCF", ":VectorTransformOpsIncGen", ":VectorTransforms", ":X86VectorTransforms", - "//llvm:Support", ], ) @@ -5023,7 +4972,6 @@ cc_library( srcs = glob( [ "lib/Dialect/Vector/Transforms/*.cpp", - "lib/Dialect/Vector/Transforms/*.h", ], ), hdrs = glob([ @@ -5036,6 +4984,7 @@ cc_library( ":ArithTransforms", ":ArithUtils", ":BufferizationDialect", + ":BufferizationInterfaces", ":BufferizationTransforms", ":DialectUtils", ":FuncDialect", @@ -5049,7 +4998,7 @@ cc_library( ":SubsetOpInterface", ":Support", ":TensorDialect", - ":Transforms", + ":TransformUtils", ":VectorDialect", ":VectorEnumsIncGen", ":VectorInterfaces", @@ -5089,25 +5038,18 @@ cc_library( name = "Support", srcs = glob([ "lib/Support/*.cpp", - "lib/Support/*.h", ]), hdrs = glob(["include/mlir/Support/*.h"]), includes = ["include"], - deps = [ - "//llvm:Support", - "//llvm:TargetParser", - ], + deps = ["//llvm:Support"], ) cc_library( name = "Debug", srcs = glob([ "lib/Debug/*.cpp", - "lib/Debug/*.h", "lib/Debug/BreakpointManagers/*.cpp", - "lib/Debug/BreakpointManagers/*.h", "lib/Debug/Observers/*.cpp", - "lib/Debug/Observers/*.h", ]), hdrs = glob([ "include/mlir/Debug/*.h", @@ -5139,7 +5081,6 @@ cc_library( deps = [ ":Support", "//llvm:Support", - "//llvm:TargetParser", ], ) @@ -5149,8 +5090,6 @@ cc_library( [ "lib/Tools/mlir-lsp-server/*.cpp", "lib/Tools/mlir-lsp-server/*.h", - "lib/Tools/mlir-lsp-server/lsp/*.cpp", - "lib/Tools/mlir-lsp-server/lsp/*.h", ], ), hdrs = glob( @@ -5216,7 +5155,6 @@ cc_library( ":IR", ":Support", "//llvm:Support", - "//llvm:TargetParser", ], ) @@ -5224,16 +5162,12 @@ cc_library( name = "BytecodeReader", srcs = glob([ "lib/Bytecode/Reader/*.cpp", - "lib/Bytecode/Reader/*.h", - "lib/Bytecode/*.h", - ]), - hdrs = glob([ - "include/mlir/Bytecode/*.h", ]), + hdrs = ["include/mlir/Bytecode/BytecodeReader.h"], includes = ["include"], deps = [ ":AsmParser", - ":BytecodeOpInterfaceIncGen", + ":BytecodeOpInterface", ":IR", ":Support", "//llvm:Support", @@ -5245,14 +5179,11 @@ cc_library( srcs = glob([ "lib/Bytecode/Writer/*.cpp", "lib/Bytecode/Writer/*.h", - "lib/Bytecode/*.h", - ]), - hdrs = glob([ - "include/mlir/Bytecode/*.h", ]), + hdrs = ["include/mlir/Bytecode/BytecodeWriter.h"], includes = ["include"], deps = [ - ":BytecodeOpInterfaceIncGen", + ":BytecodeOpInterface", ":IR", ":Support", "//llvm:Support", @@ -5263,7 +5194,6 @@ cc_library( name = "Parser", srcs = glob([ "lib/Parser/*.cpp", - "lib/Parser/*.h", ]), hdrs = glob([ "include/mlir/Parser/*.h", @@ -5273,7 +5203,6 @@ cc_library( ":AsmParser", ":BytecodeReader", ":IR", - ":Support", "//llvm:Support", ], ) @@ -5289,6 +5218,14 @@ gentbl_cc_library( ["-gen-op-interface-defs"], "include/mlir/Dialect/LLVMIR/LLVMInterfaces.cpp.inc", ), + ( + ["-gen-attr-interface-decls"], + "include/mlir/Dialect/LLVMIR/LLVMAttrInterfaces.h.inc", + ), + ( + ["-gen-attr-interface-defs"], + "include/mlir/Dialect/LLVMIR/LLVMAttrInterfaces.cpp.inc", + ), ( ["-gen-type-interface-decls"], "include/mlir/Dialect/LLVMIR/LLVMTypeInterfaces.h.inc", @@ -5337,18 +5274,17 @@ cc_library( "include/mlir/Dialect/LLVMIR/VCIX*.h", "include/mlir/Dialect/LLVMIR/*X86Vector*.h", ], - ) + [ - "include/mlir/Transforms/InliningUtils.h", - "include/mlir/Transforms/Mem2Reg.h", - ], + ), includes = ["include"], deps = [ + ":BytecodeOpInterface", ":CallOpInterfaces", ":ControlFlowInterfaces", ":DataLayoutInterfaces", ":FunctionInterfaces", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":LLVMDialectInterfaceIncGen", ":LLVMIntrinsicOpsIncGen", ":LLVMOpsIncGen", @@ -5386,19 +5322,17 @@ cc_library( name = "LLVMIRTransforms", srcs = glob([ "lib/Dialect/LLVMIR/Transforms/*.cpp", - "lib/Dialect/LLVMIR/Transforms/*.h", ]), hdrs = glob(["include/mlir/Dialect/LLVMIR/Transforms/*.h"]), includes = ["include"], deps = [ ":FuncDialect", - ":GPUDialect", ":IR", ":LLVMDialect", ":LLVMPassIncGen", ":NVVMDialect", ":Pass", - ":Transforms", + ":TransformUtils", "//llvm:BinaryFormat", "//llvm:Support", ], @@ -5539,13 +5473,14 @@ cc_library( srcs = glob( [ "lib/Dialect/GPU/IR/*.cpp", - "lib/Dialect/GPU/IR/*.h", ], ), hdrs = glob(["include/mlir/Dialect/GPU/IR/*.h"]), includes = ["include"], deps = [ ":ArithDialect", + ":BufferizationInterfaces", + ":BytecodeOpInterface", ":ControlFlowInterfaces", ":DLTIDialect", ":FunctionInterfaces", @@ -5555,7 +5490,7 @@ cc_library( ":IR", ":InferIntRangeInterface", ":InferTypeOpInterface", - ":LLVMDialect", + ":InliningUtils", ":MemRefDialect", ":SCFDialect", ":SideEffectInterfaces", @@ -5604,8 +5539,8 @@ cc_library( ":ArithToLLVM", ":FuncDialect", ":FuncToLLVM", - ":GPUCommonTransforms", ":GPUDialect", + ":GPUToGPURuntimeTransforms", ":GPUToNVVMTransforms", ":GPUTransforms", ":IndexToLLVM", @@ -5631,7 +5566,6 @@ cc_library( srcs = glob( [ "lib/Dialect/GPU/Transforms/*.cpp", - "lib/Dialect/GPU/Transforms/*.h", ], ), hdrs = glob(["include/mlir/Dialect/GPU/Transforms/*.h"]), @@ -5643,6 +5577,7 @@ cc_library( ":AsmParser", ":AsyncDialect", ":BufferizationDialect", + ":BufferizationInterfaces", ":ControlFlowDialect", ":DLTIDialect", ":DialectUtils", @@ -5668,6 +5603,7 @@ cc_library( ":SideEffectInterfaces", ":Support", ":ToLLVMIRTranslation", + ":TransformUtils", ":Transforms", ":VCIXToLLVMIRTranslation", ":VectorDialect", @@ -5724,12 +5660,10 @@ cc_library( deps = [ ":AffineDialect", ":ArithDialect", - ":AsmParser", - ":ControlFlowDialect", ":DialectUtils", ":FuncDialect", - ":GPUCommonTransforms", ":GPUDialect", + ":GPUToGPURuntimeTransforms", ":GPUToNVVMTransforms", ":GPUTransformOpsIncGen", ":GPUTransforms", @@ -5737,11 +5671,10 @@ cc_library( ":LLVMCommonConversion", ":MemRefDialect", ":NVVMDialect", - ":Parser", ":SCFDialect", - ":SideEffectInterfaces", ":Support", ":TransformDialect", + ":TransformDialectInterfaces", ":TransformUtils", ":VectorDialect", ":VectorTransforms", @@ -5776,25 +5709,16 @@ td_library( cc_library( name = "GPUCommonTransforms", - srcs = [ - "lib/Conversion/GPUCommon/GPUOpsLowering.cpp", - ], hdrs = [ - "include/mlir/Conversion/GPUCommon/GPUCommonPass.h", "lib/Conversion/GPUCommon/GPUOpsLowering.h", "lib/Conversion/GPUCommon/IndexIntrinsicsOpLowering.h", "lib/Conversion/GPUCommon/OpToFuncCallLowering.h", ], deps = [ - ":ConversionPassIncGen", - ":FuncDialect", ":GPUDialect", - ":GPUTransforms", ":IR", ":LLVMCommonConversion", ":LLVMDialect", - ":Support", - "//llvm:Support", ], ) @@ -5819,14 +5743,12 @@ cc_library( name = "GPUToNVVMTransforms", srcs = glob([ "lib/Conversion/GPUToNVVM/*.cpp", - "lib/Conversion/GPUToNVVM/*.h", ]), hdrs = glob([ "include/mlir/Conversion/GPUToNVVM/*.h", ]), includes = ["include"], deps = [ - ":ArithDialect", ":ArithToLLVM", ":ControlFlowDialect", ":ControlFlowToLLVM", @@ -5835,6 +5757,7 @@ cc_library( ":FuncToLLVM", ":GPUCommonTransforms", ":GPUDialect", + ":GPUToGPURuntimeTransforms", ":GPUToNVVMGen", ":GPUTransforms", ":IR", @@ -5844,10 +5767,8 @@ cc_library( ":MemRefDialect", ":MemRefToLLVM", ":NVVMDialect", - ":Pass", - ":Transforms", + ":TransformUtils", ":VectorToLLVM", - "//llvm:Support", ], ) @@ -5855,7 +5776,6 @@ cc_library( name = "AMDGPUToROCDL", srcs = glob([ "lib/Conversion/AMDGPUToROCDL/*.cpp", - "lib/Conversion/AMDGPUToROCDL/*.h", ]) + ["include/mlir/Conversion/GPUToROCDL/Runtimes.h"], hdrs = glob([ "include/mlir/Conversion/AMDGPUToROCDL/*.h", @@ -5870,8 +5790,6 @@ cc_library( ":LLVMDialect", ":Pass", ":ROCDLDialect", - ":Support", - ":Transforms", "//llvm:Support", ], ) @@ -5880,7 +5798,6 @@ cc_library( name = "NVGPUToNVVM", srcs = glob([ "lib/Conversion/NVGPUToNVVM/*.cpp", - "lib/Conversion/NVGPUToNVVM/*.h", ]), hdrs = glob([ "include/mlir/Conversion/NVGPUToNVVM/*.h", @@ -5889,7 +5806,6 @@ cc_library( deps = [ ":ArithDialect", ":ConversionPassIncGen", - ":GPUCommonTransforms", ":GPUDialect", ":GPUToGPURuntimeTransforms", ":IR", @@ -5908,7 +5824,6 @@ cc_library( name = "VectorToSPIRV", srcs = glob([ "lib/Conversion/VectorToSPIRV/*.cpp", - "lib/Conversion/VectorToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/VectorToSPIRV/*.h", @@ -5922,7 +5837,7 @@ cc_library( ":SPIRVConversion", ":SPIRVDialect", ":Support", - ":Transforms", + ":TransformUtils", ":VectorDialect", "//llvm:Support", ], @@ -5964,6 +5879,7 @@ cc_library( ":FuncToLLVM", ":GPUCommonTransforms", ":GPUDialect", + ":GPUToGPURuntimeTransforms", ":GPUToROCDLTGen", ":GPUTransforms", ":IR", @@ -5974,10 +5890,10 @@ cc_library( ":MemRefToLLVM", ":Pass", ":ROCDLDialect", + ":TransformUtils", ":Transforms", ":VectorDialect", ":VectorToLLVM", - ":VectorToSCF", "//llvm:Support", ], ) @@ -6007,6 +5923,7 @@ cc_library( cc_library( name = "GPUToGPURuntimeTransforms", srcs = [ + "lib/Conversion/GPUCommon/GPUOpsLowering.cpp", "lib/Conversion/GPUCommon/GPUToLLVMConversion.cpp", ], hdrs = ["include/mlir/Conversion/GPUCommon/GPUCommonPass.h"], @@ -6020,6 +5937,7 @@ cc_library( ":ConvertToLLVM", ":ConvertToLLVMInterface", ":FuncToLLVM", + ":GPUCommonTransforms", ":GPUDialect", ":GPUTransforms", ":IR", @@ -6037,7 +5955,6 @@ cc_library( name = "GPUToSPIRV", srcs = glob([ "lib/Conversion/GPUToSPIRV/*.cpp", - "lib/Conversion/GPUToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/GPUToSPIRV/*.h", @@ -6054,14 +5971,11 @@ cc_library( ":GPUDialect", ":IR", ":MemRefToSPIRV", - ":Pass", - ":SCFDialect", ":SCFToSPIRV", ":SPIRVConversion", ":SPIRVDialect", ":Support", - ":Transforms", - ":VectorToSPIRV", + ":TransformUtils", "//llvm:Support", ], ) @@ -6112,7 +6026,7 @@ cc_library( ":SPIRVDialect", ":SPIRVUtils", ":Support", - ":Transforms", + ":TransformUtils", "//llvm:Support", ], ) @@ -6257,6 +6171,7 @@ cc_library( includes = ["include"], deps = [ ":BasicPtxBuilderInterface", + ":BytecodeOpInterface", ":ConvertToLLVMInterface", ":DialectUtils", ":GPUDialect", @@ -6481,13 +6396,10 @@ cc_library( ":ConversionPassIncGen", ":ConvertToLLVMInterface", ":FuncDialect", - ":GPUDialect", ":IR", ":LLVMCommonConversion", ":LLVMDialect", - ":MemRefDialect", ":NVVMDialect", - ":NVVMOpsIncGen", ":Pass", ":Support", "//llvm:Support", @@ -6500,6 +6412,7 @@ cc_library( hdrs = ["include/mlir/Dialect/LLVMIR/ROCDLDialect.h"], includes = ["include"], deps = [ + ":BytecodeOpInterface", ":GPUDialect", ":IR", ":LLVMDialect", @@ -6607,13 +6520,13 @@ cc_library( name = "PDLDialect", srcs = glob([ "lib/Dialect/PDL/IR/*.cpp", - "lib/Dialect/PDL/IR/*.h", ]), hdrs = glob([ "include/mlir/Dialect/PDL/IR/*.h", ]), includes = ["include"], deps = [ + ":BytecodeOpInterface", ":IR", ":InferTypeOpInterface", ":PDLOpsIncGen", @@ -6682,20 +6595,19 @@ cc_library( name = "PDLInterpDialect", srcs = glob([ "lib/Dialect/PDLInterp/IR/*.cpp", - "lib/Dialect/PDLInterp/IR/*.h", ]), hdrs = glob([ "include/mlir/Dialect/PDLInterp/IR/*.h", ]), includes = ["include"], deps = [ + ":BytecodeOpInterface", ":FunctionInterfaces", ":IR", ":InferTypeOpInterface", ":PDLDialect", ":PDLInterpOpsIncGen", ":SideEffectInterfaces", - "//llvm:Support", ], ) @@ -6889,28 +6801,29 @@ cc_library( srcs = glob([ "lib/Dialect/SPIRV/IR/*.cpp", "lib/Dialect/SPIRV/IR/*.h", - ]) + ["include/mlir/Transforms/InliningUtils.h"], + ]), hdrs = glob([ "include/mlir/Dialect/SPIRV/IR/*.h", ]), includes = ["include"], deps = [ + ":BytecodeOpInterface", + ":CallOpInterfaces", ":CommonFolders", ":ControlFlowInterfaces", ":FunctionInterfaces", ":GPUDialect", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":Parser", ":SPIRVAttrUtilsGen", ":SPIRVAttributesIncGen", ":SPIRVAvailabilityIncGen", ":SPIRVCanonicalizationIncGen", ":SPIRVOpsIncGen", - ":SPIRVSerializationGen", ":SideEffectInterfaces", ":Support", - ":Transforms", ":UBDialect", "//llvm:Support", ], @@ -6953,10 +6866,7 @@ cc_library( "include/mlir/Dialect/SPIRV/Utils/*.h", ]), includes = ["include"], - deps = [ - ":SPIRVDialect", - "//llvm:Support", - ], + deps = [":SPIRVDialect"], ) cc_library( @@ -6978,7 +6888,6 @@ cc_library( srcs = glob( [ "lib/Dialect/SPIRV/Transforms/*.cpp", - "lib/Dialect/SPIRV/Transforms/*.h", ], exclude = ["lib/Dialect/SPIRV/Transforms/SPIRVConversion.cpp"], ), @@ -6996,7 +6905,7 @@ cc_library( ":SPIRVPassIncGen", ":SPIRVUtils", ":Support", - ":Transforms", + ":TransformUtils", "//llvm:Support", ], ) @@ -7008,7 +6917,7 @@ cc_library( deps = [ ":IR", ":SPIRVDialect", - ":Transforms", + ":TransformUtils", "//llvm:Support", ], ) @@ -7017,7 +6926,6 @@ cc_library( name = "MathToSPIRV", srcs = glob([ "lib/Conversion/MathToSPIRV/*.cpp", - "lib/Conversion/MathToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/MathToSPIRV/*.h", @@ -7034,8 +6942,7 @@ cc_library( ":SPIRVCommonConversion", ":SPIRVConversion", ":SPIRVDialect", - ":Support", - ":Transforms", + ":TransformUtils", "//llvm:Support", ], ) @@ -7044,7 +6951,6 @@ cc_library( name = "FuncToEmitC", srcs = glob([ "lib/Conversion/FuncToEmitC/*.cpp", - "lib/Conversion/FuncToEmitC/*.h", ]), hdrs = glob([ "include/mlir/Conversion/FuncToEmitC/*.h", @@ -7057,12 +6963,8 @@ cc_library( ":ConversionPassIncGen", ":EmitCDialect", ":FuncDialect", - ":IR", ":Pass", - ":Support", ":TransformUtils", - ":Transforms", - "//llvm:Support", ], ) @@ -7070,7 +6972,6 @@ cc_library( name = "FuncToSPIRV", srcs = glob([ "lib/Conversion/FuncToSPIRV/*.cpp", - "lib/Conversion/FuncToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/FuncToSPIRV/*.h", @@ -7080,20 +6981,16 @@ cc_library( "lib/Conversion/FuncToSPIRV", ], deps = [ - ":ControlFlowToSPIRV", ":ConversionPassIncGen", ":FuncDialect", ":IR", - ":MathToSPIRV", ":Pass", ":SPIRVCommonConversion", ":SPIRVConversion", ":SPIRVDialect", ":SPIRVUtils", ":Support", - ":TensorDialect", - ":Transforms", - ":VectorDialect", + ":TransformUtils", "//llvm:Support", ], ) @@ -7102,7 +6999,6 @@ cc_library( name = "TensorToLinalg", srcs = glob([ "lib/Conversion/TensorToLinalg/*.cpp", - "lib/Conversion/TensorToLinalg/*.h", ]), hdrs = glob([ "include/mlir/Conversion/TensorToLinalg/*.h", @@ -7114,15 +7010,13 @@ cc_library( deps = [ ":ArithDialect", ":ConversionPassIncGen", - ":FuncDialect", ":IR", ":LinalgDialect", ":LinalgTransforms", ":Pass", ":Support", ":TensorDialect", - ":Transforms", - ":VectorDialect", + ":TransformUtils", "//llvm:Support", ], ) @@ -7131,7 +7025,6 @@ cc_library( name = "TensorToSPIRV", srcs = glob([ "lib/Conversion/TensorToSPIRV/*.cpp", - "lib/Conversion/TensorToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/TensorToSPIRV/*.h", @@ -7142,12 +7035,9 @@ cc_library( ], deps = [ ":ArithToSPIRV", - ":ControlFlowToSPIRV", ":ConversionPassIncGen", - ":FuncDialect", ":FuncToSPIRV", ":IR", - ":MathToSPIRV", ":Pass", ":SPIRVCommonConversion", ":SPIRVConversion", @@ -7155,8 +7045,7 @@ cc_library( ":SPIRVUtils", ":Support", ":TensorDialect", - ":Transforms", - ":VectorDialect", + ":TransformUtils", "//llvm:Support", ], ) @@ -7167,11 +7056,8 @@ cc_library( hdrs = ["include/mlir/Target/SPIRV/SPIRVBinaryUtils.h"], includes = ["include"], deps = [ - ":SPIRVAttrUtilsGen", ":SPIRVDialect", - ":SPIRVOpsIncGen", ":Support", - "//llvm:Support", ], ) @@ -7187,13 +7073,10 @@ cc_library( includes = ["include"], deps = [ ":IR", - ":SPIRVAttrUtilsGen", ":SPIRVBinaryUtils", ":SPIRVDialect", - ":SPIRVOpsIncGen", ":SPIRVSerializationGen", ":Support", - ":Transforms", "//llvm:Support", ], ) @@ -7208,13 +7091,10 @@ cc_library( includes = ["include"], deps = [ ":IR", - ":SPIRVAttrUtilsGen", ":SPIRVBinaryUtils", ":SPIRVDialect", - ":SPIRVOpsIncGen", ":SPIRVSerializationGen", ":Support", - ":Transforms", "//llvm:Support", ], ) @@ -7305,7 +7185,6 @@ gentbl_cc_library( cc_library( name = "TensorDialect", srcs = [ - "include/mlir/Transforms/InliningUtils.h", "lib/Dialect/Tensor/IR/TensorDialect.cpp", "lib/Dialect/Tensor/IR/TensorOps.cpp", "lib/Dialect/Tensor/IR/ValueBoundsOpInterfaceImpl.cpp", @@ -7319,6 +7198,8 @@ cc_library( ":AffineDialect", ":ArithDialect", ":ArithUtils", + ":BufferizationInterfaces", + ":BytecodeOpInterface", ":CastInterfaces", ":ComplexDialect", ":ControlFlowInterfaces", @@ -7326,13 +7207,16 @@ cc_library( ":DialectUtils", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":LoopLikeInterface", ":ParallelCombiningOpInterface", ":ShapedOpInterfaces", ":SideEffectInterfaces", + ":SubsetOpInterface", ":Support", ":TensorOpsIncGen", ":TilingInterface", + ":TransformDialectInterfaces", ":ValueBoundsOpInterface", ":ViewLikeInterface", "//llvm:Support", @@ -7351,7 +7235,6 @@ cc_library( ":IR", ":InferTypeOpInterface", ":TensorDialect", - "//llvm:Support", ], ) @@ -7373,7 +7256,6 @@ cc_library( ":TensorUtils", ":TilingInterface", ":ValueBoundsOpInterface", - "//llvm:Support", ], ) @@ -7389,7 +7271,6 @@ cc_library( ":DialectUtils", ":TensorDialect", ":ValueBoundsOpInterface", - "//llvm:Support", ], ) @@ -7414,7 +7295,6 @@ cc_library( srcs = glob( [ "lib/Dialect/Tensor/Transforms/*.cpp", - "lib/Dialect/Tensor/Transforms/*.h", ], ), hdrs = glob(["include/mlir/Dialect/Tensor/Transforms/*.h"]), @@ -7426,6 +7306,7 @@ cc_library( ":ArithDialect", ":ArithUtils", ":BufferizationDialect", + ":BufferizationInterfaces", ":BufferizationTransforms", ":DialectUtils", ":FuncDialect", @@ -7439,7 +7320,7 @@ cc_library( ":TensorPassIncGen", ":TensorUtils", ":TilingInterface", - ":Transforms", + ":TransformUtils", ":ValueBoundsOpInterface", ":VectorDialect", "//llvm:Support", @@ -7490,6 +7371,7 @@ cc_library( ":TensorTransforms", ":TensorUtils", ":TransformDialect", + ":TransformDialectInterfaces", ":TransformUtils", ], ) @@ -7516,30 +7398,38 @@ cc_library( cc_library( name = "TransformUtils", - srcs = glob([ - "lib/Transforms/Utils/*.cpp", - "lib/Transforms/Utils/*.h", - ]), - hdrs = glob( - [ - "include/mlir/Transforms/*.h", - ], - exclude = ["include/mlir/Transforms/Passes.h"], - ), + srcs = glob( + include = ["lib/Transforms/Utils/*.cpp"], + exclude = ["lib/Transforms/Utils/InliningUtils.cpp"], + ) + [ + ], + hdrs = [ + "include/mlir/Transforms/CFGToSCF.h", + "include/mlir/Transforms/CommutativityUtils.h", + "include/mlir/Transforms/ControlFlowSinkUtils.h", + "include/mlir/Transforms/DialectConversion.h", + "include/mlir/Transforms/FoldUtils.h", + "include/mlir/Transforms/GreedyPatternRewriteDriver.h", + "include/mlir/Transforms/Inliner.h", + "include/mlir/Transforms/LoopInvariantCodeMotionUtils.h", + "include/mlir/Transforms/OneToNTypeConversion.h", + "include/mlir/Transforms/RegionUtils.h", + "include/mlir/Transforms/TopologicalSortUtils.h", + ], includes = ["include"], deps = [ ":Analysis", + ":CallOpInterfaces", ":ControlFlowInterfaces", ":FunctionInterfaces", ":IR", + ":InliningUtils", ":LoopLikeInterface", - ":MemorySlotInterfaces", ":Pass", ":Rewrite", ":SideEffectInterfaces", ":SubsetOpInterface", ":Support", - ":TransformsPassIncGen", ":config", "//llvm:Support", ], @@ -7570,7 +7460,6 @@ cc_library( deps = [ ":DerivedAttributeOpInterfaceIncGen", ":IR", - "//llvm:Support", ], ) @@ -7628,7 +7517,6 @@ cc_library( deps = [ ":IR", ":InferIntRangeInterfaceIncGen", - "//llvm:Support", ], ) @@ -7852,24 +7740,32 @@ cc_library( name = "Transforms", srcs = glob([ "lib/Transforms/*.cpp", - "lib/Transforms/*.h", ]), - hdrs = glob(["include/mlir/Transforms/*.h"]), + hdrs = [ + "include/mlir/Transforms/CSE.h", + "include/mlir/Transforms/EndomorphismSimplification.h", + "include/mlir/Transforms/HomomorphismSimplification.h", + "include/mlir/Transforms/LocationSnapshot.h", + "include/mlir/Transforms/Mem2Reg.h", + "include/mlir/Transforms/Passes.h", + "include/mlir/Transforms/SROA.h", + "include/mlir/Transforms/ViewOpGraph.h", + ], includes = ["include"], deps = [ ":Analysis", + ":CallOpInterfaces", ":ControlFlowInterfaces", ":FunctionInterfaces", ":IR", ":LoopLikeInterface", ":MemorySlotInterfaces", ":Pass", - ":Rewrite", ":RuntimeVerifiableOpInterface", + ":SideEffectInterfaces", ":Support", ":TransformUtils", ":TransformsPassIncGen", - ":config", "//llvm:Support", ], ) @@ -7897,7 +7793,6 @@ cc_library( ":ArithDialect", ":ComplexDialect", ":ConversionPassIncGen", - ":FuncDialect", ":FunctionInterfaces", ":GPUDialect", ":GPUTransforms", @@ -7920,16 +7815,12 @@ cc_library( includes = ["include"], deps = [ ":ArithDialect", - ":ControlFlowInterfaces", ":ConversionPassIncGen", ":EmitCDialect", ":IR", - ":Pass", ":SCFDialect", - ":Support", ":TransformUtils", ":Transforms", - "//llvm:Support", ], ) @@ -7937,17 +7828,14 @@ cc_library( name = "SCFToSPIRV", srcs = glob([ "lib/Conversion/SCFToSPIRV/*.cpp", - "lib/Conversion/SCFToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/SCFToSPIRV/*.h", ]), includes = ["include"], deps = [ - ":AffineDialect", ":ArithToSPIRV", ":ConversionPassIncGen", - ":FuncDialect", ":FuncToSPIRV", ":IR", ":IndexToSPIRV", @@ -7956,9 +7844,7 @@ cc_library( ":SCFDialect", ":SPIRVConversion", ":SPIRVDialect", - ":Support", ":TransformUtils", - ":Transforms", "//llvm:Support", ], ) @@ -7975,15 +7861,13 @@ cc_library( ":Analysis", ":ArithDialect", ":ConversionPassIncGen", - ":FuncDialect", ":IR", ":LLVMDialect", ":MemRefDialect", ":OpenMPDialect", ":Pass", ":SCFDialect", - ":Support", - ":Transforms", + ":TransformUtils", ], ) @@ -7998,12 +7882,8 @@ cc_library( ":ArithDialect", ":ControlFlowDialect", ":ConversionPassIncGen", - ":FuncDialect", ":IR", - ":LLVMDialect", - ":Pass", ":SCFDialect", - ":Support", ":TransformUtils", ":Transforms", ], @@ -8017,9 +7897,11 @@ cc_library( hdrs = glob(["include/mlir/Conversion/LLVMCommon/*.h"]), includes = ["include"], deps = [ + ":DataLayoutInterfaces", ":IR", ":LLVMDialect", ":Support", + ":TransformUtils", ":Transforms", "//llvm:Core", "//llvm:Support", @@ -8064,9 +7946,7 @@ cc_library( ":LLVMDialect", ":Pass", ":Rewrite", - ":Support", ":TransformUtils", - "//llvm:Support", ], ) @@ -8123,10 +8003,8 @@ cc_library( ":LLVMDialect", ":Pass", ":SCFDialect", - ":Transforms", + ":TransformUtils", ":UBDialect", - "//llvm:Core", - "//llvm:Support", ], ) @@ -8140,24 +8018,14 @@ cc_library( ], includes = ["include"], deps = [ - ":Analysis", - ":ArithToLLVM", ":ControlFlowDialect", ":ConversionPassIncGen", ":ConvertToLLVMInterface", - ":DataLayoutInterfaces", - ":DialectUtils", ":IR", ":LLVMCommonConversion", ":LLVMDialect", - ":MathDialect", - ":MemRefDialect", - ":Parser", ":Pass", - ":Support", ":TransformUtils", - ":Transforms", - "//llvm:Core", "//llvm:Support", ], ) @@ -8177,11 +8045,33 @@ cc_library( ":SPIRVDialect", ":SPIRVUtils", ":Support", - ":Transforms", + ":TransformUtils", "//llvm:Support", ], ) +cc_library( + name = "MemRefToEmitC", + srcs = glob([ + "lib/Conversion/MemRefToEmitC/*.cpp", + ]), + hdrs = glob([ + "include/mlir/Conversion/MemRefToEmitC/*.h", + ]), + includes = [ + "include", + "lib/Conversion/MemRefToEmitC", + ], + deps = [ + ":ConversionPassIncGen", + ":EmitCDialect", + ":IR", + ":MemRefDialect", + ":Pass", + ":TransformUtils", + ], +) + cc_library( name = "MemRefToLLVM", srcs = glob(["lib/Conversion/MemRefToLLVM/*.cpp"]), @@ -8192,7 +8082,6 @@ cc_library( ":ArithDialect", ":ConversionPassIncGen", ":ConvertToLLVMInterface", - ":DataLayoutInterfaces", ":FuncDialect", ":IR", ":LLVMCommonConversion", @@ -8201,7 +8090,6 @@ cc_library( ":MemRefUtils", ":Pass", ":Support", - ":Transforms", "//llvm:Support", ], ) @@ -8210,7 +8098,6 @@ cc_library( name = "MemRefToSPIRV", srcs = glob([ "lib/Conversion/MemRefToSPIRV/*.cpp", - "lib/Conversion/MemRefToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/MemRefToSPIRV/*.h", @@ -8222,7 +8109,6 @@ cc_library( deps = [ ":ArithDialect", ":ConversionPassIncGen", - ":FuncDialect", ":FunctionInterfaces", ":IR", ":MemRefDialect", @@ -8230,7 +8116,7 @@ cc_library( ":SPIRVConversion", ":SPIRVDialect", ":Support", - ":Transforms", + ":TransformUtils", "//llvm:Support", ], ) @@ -8256,12 +8142,10 @@ cc_library( ":ArithDialect", ":ArithUtils", ":ConversionPassIncGen", - ":ConvertToLLVMInterface", ":IR", - ":LLVMDialect", ":Pass", ":Support", - ":Transforms", + ":TransformUtils", ":VectorDialect", ], ) @@ -8270,7 +8154,6 @@ cc_library( name = "ArithToArmSME", srcs = glob([ "lib/Conversion/ArithToArmSME/*.cpp", - "lib/Conversion/ArithToArmSME/*.h", ]), hdrs = glob([ "include/mlir/Conversion/ArithToArmSME/*.h", @@ -8280,10 +8163,8 @@ cc_library( ":ArithDialect", ":ArmSMEDialect", ":ConversionPassIncGen", - ":IR", ":Pass", - ":Transforms", - "//llvm:Support", + ":TransformUtils", ], ) @@ -8291,7 +8172,6 @@ cc_library( name = "ArithToEmitC", srcs = glob([ "lib/Conversion/ArithToEmitC/*.cpp", - "lib/Conversion/ArithToEmitC/*.h", ]), hdrs = glob([ "include/mlir/Conversion/ArithToEmitC/*.h", @@ -8304,12 +8184,8 @@ cc_library( ":ArithDialect", ":ConversionPassIncGen", ":EmitCDialect", - ":IR", ":Pass", - ":Support", ":TransformUtils", - ":Transforms", - "//llvm:Support", ], ) @@ -8319,7 +8195,6 @@ cc_library( hdrs = glob(["include/mlir/Conversion/ArithToLLVM/*.h"]), includes = ["include"], deps = [ - ":Analysis", ":ArithAttrToLLVMConversion", ":ArithDialect", ":ConversionPassIncGen", @@ -8328,8 +8203,6 @@ cc_library( ":LLVMCommonConversion", ":LLVMDialect", ":Pass", - ":Support", - ":Transforms", ], ) @@ -8341,14 +8214,11 @@ cc_library( deps = [ ":ArithDialect", ":ConversionPassIncGen", - ":FuncToSPIRV", ":IR", ":Pass", ":SPIRVCommonConversion", ":SPIRVConversion", ":SPIRVDialect", - ":Support", - ":Transforms", "//llvm:Support", ], ) @@ -8359,18 +8229,14 @@ cc_library( hdrs = glob(["include/mlir/Conversion/MathToLLVM/*.h"]), includes = ["include"], deps = [ - ":Analysis", ":ArithAttrToLLVMConversion", ":ConversionPassIncGen", ":ConvertToLLVMInterface", - ":DataLayoutInterfaces", ":IR", ":LLVMCommonConversion", ":LLVMDialect", ":MathDialect", ":Pass", - ":Support", - ":Transforms", ], ) @@ -8390,7 +8256,7 @@ cc_library( ":MathDialect", ":Pass", ":SCFDialect", - ":Transforms", + ":TransformUtils", ":VectorDialect", ":VectorUtils", "//llvm:Support", @@ -8414,6 +8280,23 @@ gentbl_cc_library( deps = [":BytecodeOpInterfaceTdFiles"], ) +cc_library( + name = "BytecodeOpInterface", + srcs = ["lib/Bytecode/BytecodeOpInterface.cpp"], + hdrs = [ + "include/mlir/Bytecode/BytecodeImplementation.h", + "include/mlir/Bytecode/BytecodeOpInterface.h", + "include/mlir/Bytecode/Encoding.h", + ], + includes = ["include"], + deps = [ + ":BytecodeOpInterfaceIncGen", + ":IR", + ":Support", + "//llvm:Support", + ], +) + gentbl_cc_library( name = "CallOpInterfacesIncGen", tbl_outs = [ @@ -8468,7 +8351,6 @@ cc_library( deps = [ ":CastInterfacesIncGen", ":IR", - "//llvm:Support", ], ) @@ -8582,9 +8464,7 @@ cc_library( srcs = glob( [ "lib/Analysis/*.cpp", - "lib/Analysis/*.h", "lib/Analysis/*/*.cpp", - "lib/Analysis/*/*.h", ], ), hdrs = glob( @@ -8615,17 +8495,26 @@ cc_library( ], ) +cc_library( + name = "ParseUtilities", + hdrs = ["include/mlir/Tools/ParseUtilities.h"], + includes = ["include"], + deps = [ + ":IR", + ":Parser", + ], +) + cc_library( name = "TranslateLib", srcs = glob([ "lib/Tools/mlir-translate/*.cpp", - ]) + [ - "include/mlir/Tools/ParseUtilities.h", - ], + ]), hdrs = glob(["include/mlir/Tools/mlir-translate/*.h"]), includes = ["include"], deps = [ ":IR", + ":ParseUtilities", ":Parser", ":Support", "//llvm:Support", @@ -8635,6 +8524,7 @@ cc_library( cc_library( name = "ToLLVMIRTranslation", srcs = [ + "lib/Target/LLVMIR/AttrKindDetail.h", "lib/Target/LLVMIR/DebugTranslation.cpp", "lib/Target/LLVMIR/DebugTranslation.h", "lib/Target/LLVMIR/LoopAnnotationTranslation.cpp", @@ -8647,7 +8537,6 @@ cc_library( "include/mlir/Target/LLVMIR/LLVMTranslationInterface.h", "include/mlir/Target/LLVMIR/ModuleTranslation.h", "include/mlir/Target/LLVMIR/TypeToLLVM.h", - "lib/Target/LLVMIR/AttrKindDetail.h", ], includes = ["include"], deps = [ @@ -8813,8 +8702,6 @@ cc_library( deps = [ ":IR", ":ToLLVMIRTranslation", - "//llvm:Core", - "//llvm:Support", ], ) @@ -8890,7 +8777,6 @@ cc_library( ":IR", ":LLVMDialect", ":OpenACCDialect", - ":OpenACCToLLVM", ":OpenMPCommon", ":Support", ":ToLLVMIRTranslation", @@ -8913,6 +8799,7 @@ cc_library( ":OpenMPDialect", ":Support", ":ToLLVMIRTranslation", + ":TransformUtils", ":Transforms", "//llvm:Core", "//llvm:FrontendOpenMP", @@ -8969,9 +8856,11 @@ cc_library( cc_library( name = "FromLLVMIRTranslation", srcs = [ + "lib/Target/LLVMIR/AttrKindDetail.h", "lib/Target/LLVMIR/DataLayoutImporter.cpp", "lib/Target/LLVMIR/DataLayoutImporter.h", "lib/Target/LLVMIR/DebugImporter.cpp", + "lib/Target/LLVMIR/DebugImporter.h", "lib/Target/LLVMIR/LoopAnnotationImporter.cpp", "lib/Target/LLVMIR/LoopAnnotationImporter.h", "lib/Target/LLVMIR/ModuleImport.cpp", @@ -8982,12 +8871,11 @@ cc_library( "include/mlir/Target/LLVMIR/LLVMImportInterface.h", "include/mlir/Target/LLVMIR/ModuleImport.h", "include/mlir/Target/LLVMIR/TypeFromLLVM.h", - "lib/Target/LLVMIR/AttrKindDetail.h", - "lib/Target/LLVMIR/DebugImporter.h", ], includes = ["include"], deps = [ ":DLTIDialect", + ":DataLayoutInterfaces", ":IR", ":LLVMConversionIncGen", ":LLVMDialect", @@ -9081,7 +8969,6 @@ cc_library( includes = ["include"], deps = [ ":IR", - ":Pass", ":Support", "//llvm:Support", ], @@ -9089,18 +8976,15 @@ cc_library( cc_library( name = "MlirOptLib", - srcs = [ - "include/mlir/Tools/ParseUtilities.h", - "lib/Tools/mlir-opt/MlirOptMain.cpp", - ], + srcs = ["lib/Tools/mlir-opt/MlirOptMain.cpp"], hdrs = ["include/mlir/Tools/mlir-opt/MlirOptMain.h"], includes = ["include"], deps = [ - ":BytecodeReader", ":BytecodeWriter", ":Debug", ":IR", ":IRDLDialect", + ":ParseUtilities", ":Parser", ":Pass", ":PluginsLib", @@ -9255,7 +9139,6 @@ cc_library( ":SCFToGPU", ":SCFTransformOps", ":SCFTransforms", - ":SDBM", ":SPIRVDialect", ":SPIRVPassIncGen", ":SPIRVTarget", @@ -9366,7 +9249,6 @@ cc_binary( "//mlir/test:TestTosaDialect", "//mlir/test:TestTransformDialect", "//mlir/test:TestTransforms", - "//mlir/test:TestTypeDialect", "//mlir/test:TestVector", "//mlir/test:TestVectorToSPIRV", ], @@ -9375,10 +9257,7 @@ cc_binary( cc_library( name = "MlirJitRunner", srcs = ["lib/ExecutionEngine/JitRunner.cpp"], - hdrs = [ - "include/mlir/ExecutionEngine/JitRunner.h", - "include/mlir/Tools/ParseUtilities.h", - ], + hdrs = ["include/mlir/ExecutionEngine/JitRunner.h"], includes = ["include"], deps = [ ":AllPassesAndDialects", @@ -9389,6 +9268,7 @@ cc_library( ":LLVMToLLVMIRTranslation", ":OpenACCToLLVMIRTranslation", ":OpenMPToLLVMIRTranslation", + ":ParseUtilities", ":Parser", ":SCFToControlFlow", ":Support", @@ -9522,7 +9402,6 @@ cc_library( deps = [ ":mlir_c_runner_utils", ":mlir_float16_utils", - "//llvm:Support", ], ) @@ -9631,13 +9510,7 @@ cc_library( "manual", # External dependency ], deps = [ - ":FuncDialect", - ":IR", - ":Pass", - ":SPIRVDialect", - ":SideEffectInterfaces", ":Support", - "//llvm:Support", "@vulkan_headers", "@vulkan_sdk//:sdk", ], @@ -9817,7 +9690,6 @@ cc_library( ":AtomicInterfacesIncGen", ":ControlFlowInterfaces", ":IR", - "//llvm:Support", ], ) @@ -9984,7 +9856,6 @@ cc_library( srcs = glob( [ "lib/Dialect/OpenACC/IR/*.cpp", - "lib/Dialect/OpenACC/IR/*.h", ], ), hdrs = glob( @@ -10003,6 +9874,7 @@ cc_library( deps = [ ":AtomicInterfaces", ":AtomicInterfacesIncGen", + ":BytecodeOpInterface", ":ControlFlowInterfaces", ":IR", ":LLVMDialect", @@ -10012,7 +9884,8 @@ cc_library( ":OpenACCOpsInterfacesIncGen", ":OpenACCTypeInterfacesIncGen", ":OpenACCTypesIncGen", - ":Transforms", + ":SideEffectInterfaces", + ":TransformUtils", "//llvm:Support", ], ) @@ -10038,14 +9911,12 @@ cc_library( srcs = glob( [ "lib/Dialect/OpenACC/Transforms/*.cpp", - "lib/Dialect/OpenACC/Transforms/*.h", ], ), hdrs = glob(["include/mlir/Dialect/OpenACC/Transforms/*.h"]), includes = ["include"], deps = [ ":FuncDialect", - ":LLVMIRTransforms", ":OpenACCDialect", ":OpenACCPassIncGen", ":Pass", @@ -10202,7 +10073,6 @@ cc_library( srcs = glob( [ "lib/Dialect/OpenMP/IR/*.cpp", - "lib/Dialect/OpenMP/IR/*.h", ], ), hdrs = glob( @@ -10228,6 +10098,7 @@ cc_library( ":OpenMPInterfacesIncGen", ":OpenMPOpsIncGen", ":OpenMPTypeInterfacesIncGen", + ":SideEffectInterfaces", ":Support", "//llvm:FrontendOpenMP", "//llvm:Support", @@ -10238,7 +10109,6 @@ cc_library( name = "OpenACCToSCF", srcs = glob([ "lib/Conversion/OpenACCToSCF/*.cpp", - "lib/Conversion/OpenACCToSCF/*.h", ]), hdrs = glob([ "include/mlir/Conversion/OpenACCToSCF/*.h", @@ -10247,38 +10117,11 @@ cc_library( deps = [ ":ArithDialect", ":ConversionPassIncGen", - ":FuncDialect", ":IR", ":OpenACCDialect", - ":OpenACCOpsIncGen", - ":OpenACCTypesIncGen", ":Pass", ":SCFDialect", - ":Transforms", - ], -) - -cc_library( - name = "OpenACCToLLVM", - srcs = glob([ - "lib/Conversion/OpenACCToLLVM/*.cpp", - "lib/Conversion/OpenACCToLLVM/*.h", - ]), - hdrs = glob([ - "include/mlir/Conversion/OpenACCToLLVM/*.h", - ]), - includes = ["include"], - deps = [ - ":ConversionPassIncGen", - ":FuncDialect", - ":IR", - ":LLVMCommonConversion", - ":LLVMDialect", - ":OpenACCDialect", - ":Pass", - ":Transforms", - "//llvm:Core", - "//llvm:Support", + ":TransformUtils", ], ) @@ -10286,7 +10129,6 @@ cc_library( name = "OpenMPToLLVM", srcs = glob([ "lib/Conversion/OpenMPToLLVM/*.cpp", - "lib/Conversion/OpenMPToLLVM/*.h", ]), hdrs = glob([ "include/mlir/Conversion/OpenMPToLLVM/*.h", @@ -10296,17 +10138,12 @@ cc_library( ":ArithToLLVM", ":ControlFlowToLLVM", ":ConversionPassIncGen", - ":FuncDialect", ":FuncToLLVM", - ":IR", ":LLVMCommonConversion", ":LLVMDialect", ":MemRefToLLVM", ":OpenMPDialect", ":Pass", - ":Transforms", - "//llvm:Core", - "//llvm:Support", ], ) @@ -10391,16 +10228,13 @@ cc_library( ], includes = ["include"], deps = [ - ":ArithDialect", - ":FuncDialect", + ":BytecodeOpInterface", ":IR", ":InferTypeOpInterface", - ":Pass", ":QuantDialectBytecodeGen", ":QuantOpsIncGen", ":SideEffectInterfaces", ":Support", - ":TransformUtils", "//llvm:Support", ], ) @@ -10496,25 +10330,18 @@ cc_library( name = "IndexToLLVM", srcs = glob([ "lib/Conversion/IndexToLLVM/*.cpp", - "lib/Conversion/IndexToLLVM/*.h", ]), hdrs = glob([ "include/mlir/Conversion/IndexToLLVM/*.h", ]), includes = ["include"], deps = [ - ":Analysis", ":ConversionPassIncGen", ":ConvertToLLVMInterface", - ":IR", ":IndexDialect", ":LLVMCommonConversion", ":LLVMDialect", ":Pass", - ":Support", - ":Transforms", - "//llvm:Core", - "//llvm:Support", ], ) @@ -10522,7 +10349,6 @@ cc_library( name = "IndexToSPIRV", srcs = glob([ "lib/Conversion/IndexToSPIRV/*.cpp", - "lib/Conversion/IndexToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/IndexToSPIRV/*.h", @@ -10530,16 +10356,11 @@ cc_library( includes = ["include"], deps = [ ":ConversionPassIncGen", - ":IR", ":IndexDialect", ":Pass", ":SPIRVCommonConversion", ":SPIRVConversion", ":SPIRVDialect", - ":Support", - ":Transforms", - "//llvm:Core", - "//llvm:Support", ], ) @@ -10549,6 +10370,7 @@ cc_library( hdrs = glob(["include/mlir/Dialect/Index/IR/*.h"]), includes = ["include"], deps = [ + ":BytecodeOpInterface", ":CastInterfaces", ":ConvertToLLVMInterface", ":IR", @@ -10557,6 +10379,7 @@ cc_library( ":InferIntRangeCommon", ":InferIntRangeInterface", ":InferTypeOpInterface", + ":SideEffectInterfaces", "//llvm:Support", ], ) @@ -10841,6 +10664,36 @@ gentbl_cc_library( ], ) +td_library( + name = "BufferViewFlowOpInterfaceTdFiles", + srcs = [ + "include/mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.td", + ], + includes = ["include"], + deps = [ + ":OpBaseTdFiles", + ], +) + +gentbl_cc_library( + name = "BufferViewFlowOpInterfaceIncGen", + tbl_outs = [ + ( + ["-gen-op-interface-decls"], + "include/mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.h.inc", + ), + ( + ["-gen-op-interface-defs"], + "include/mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.cpp.inc", + ), + ], + tblgen = ":mlir-tblgen", + td_file = "include/mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.td", + deps = [ + ":BufferViewFlowOpInterfaceTdFiles", + ], +) + td_library( name = "SubsetOpInterfaceTdFiles", srcs = [ @@ -10880,9 +10733,7 @@ cc_library( ":DestinationStyleOpInterface", ":IR", ":SubsetOpInterfaceIncGen", - ":Support", ":ValueBoundsOpInterface", - "//llvm:Support", ], ) @@ -10913,7 +10764,6 @@ cc_library( name = "LinalgToStandard", srcs = glob([ "lib/Conversion/LinalgToStandard/*.cpp", - "lib/Conversion/LinalgToStandard/*.h", ]), hdrs = glob([ "include/mlir/Conversion/LinalgToStandard/*.h", @@ -10923,17 +10773,13 @@ cc_library( ":AffineDialect", ":ConversionPassIncGen", ":FuncDialect", - ":IR", ":LLVMDialect", ":LinalgDialect", ":LinalgTransforms", ":MemRefDialect", ":Pass", ":SCFDialect", - ":Support", - ":Transforms", - "//llvm:Core", - "//llvm:Support", + ":TransformUtils", ], ) @@ -10947,16 +10793,17 @@ cc_library( ":ArithDialect", ":ArithUtils", ":AsmParser", - ":BufferizationDialect", + ":BufferizationInterfaces", + ":BytecodeOpInterface", ":ComplexDialect", ":ControlFlowInterfaces", ":CopyOpInterface", ":DestinationStyleOpInterface", ":DialectUtils", - ":FuncDialect", ":FunctionInterfaces", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":LinalgEnumsIncGen", ":LinalgInterfacesIncGen", ":LinalgNamedStructuredOpsYamlIncGen", @@ -10964,11 +10811,12 @@ cc_library( ":LinalgStructuredOpsIncGen", ":MathDialect", ":MemRefDialect", + ":MeshShardingInterface", ":Parser", ":SCFDialect", - ":MeshShardingInterface", ":SideEffectInterfaces", ":SparseTensorDialect", + ":SubsetOpInterface", ":Support", ":TensorDialect", ":TilingInterface", @@ -11013,6 +10861,7 @@ cc_library( ":TensorUtils", ":TilingInterface", ":TransformDialect", + ":TransformDialectInterfaces", ":TransformDialectUtils", ":TransformUtils", ":VectorDialect", @@ -11055,7 +10904,6 @@ cc_library( name = "LinalgUtils", srcs = glob([ "lib/Dialect/Linalg/Utils/*.cpp", - "lib/Dialect/Linalg/Utils/*.h", ]), hdrs = glob([ "include/mlir/Dialect/Linalg/Utils/*.h", @@ -11084,7 +10932,6 @@ cc_library( name = "LinalgTransforms", srcs = glob([ "lib/Dialect/Linalg/Transforms/*.cpp", - "lib/Dialect/Linalg/Transforms/*.h", ]), hdrs = [ "include/mlir/Dialect/Linalg/Passes.h", @@ -11099,9 +10946,9 @@ cc_library( ":AffineUtils", ":Analysis", ":ArithDialect", - ":ArithTransforms", ":ArithUtils", ":BufferizationDialect", + ":BufferizationInterfaces", ":BufferizationTransforms", ":ComplexDialect", ":ControlFlowDialect", @@ -11115,18 +10962,16 @@ cc_library( ":LinalgPassIncGen", ":LinalgStructuredOpsIncGen", ":LinalgUtils", - ":LoopLikeInterface", ":MaskableOpInterface", - ":MathDialect", ":MemRefDialect", ":MemRefTransforms", ":MeshDialect", + ":MeshShardingInterface", ":MeshTransforms", ":Pass", ":SCFDialect", ":SCFTransforms", ":SCFUtils", - ":MeshShardingInterface", ":SparseTensorDialect", ":SubsetOpInterface", ":Support", @@ -11136,7 +10981,6 @@ cc_library( ":TensorUtils", ":TilingInterface", ":TransformUtils", - ":Transforms", ":ValueBoundsOpInterface", ":VectorDialect", ":VectorToSCF", @@ -11186,7 +11030,6 @@ cc_library( ":Analysis", ":DestinationStyleOpInterface", ":IR", - ":Support", ":ValueBoundsOpInterfaceIncGen", ":ViewLikeInterface", "//llvm:Support", @@ -11200,7 +11043,6 @@ cc_library( includes = ["include"], deps = [ ":ArithDialect", - ":IR", ":ValueBoundsOpInterface", ], ) @@ -11216,7 +11058,6 @@ cc_library( ":Support", ":TilingInterfaceIncGen", ":ViewLikeInterface", - "//llvm:Support", ], ) @@ -11413,8 +11254,6 @@ cc_library( ":IR", ":MaskableOpInterfaceIncGen", ":MaskingOpInterface", - ":Support", - "//llvm:Support", ], ) @@ -11426,8 +11265,6 @@ cc_library( deps = [ ":IR", ":MaskingOpInterfaceIncGen", - ":Support", - "//llvm:Support", ], ) @@ -11435,7 +11272,6 @@ cc_library( name = "VectorToLLVM", srcs = glob([ "lib/Conversion/VectorToLLVM/*.cpp", - "lib/Conversion/VectorToLLVM/*.h", ]), hdrs = glob([ "include/mlir/Conversion/VectorToLLVM/*.h", @@ -11448,12 +11284,9 @@ cc_library( ":ArithDialect", ":ArithUtils", ":ArmNeonDialect", - ":ArmSMEDialect", - ":ArmSMETransforms", ":ArmSVEDialect", ":ArmSVETransforms", ":ConversionPassIncGen", - ":DialectUtils", ":FuncDialect", ":IR", ":LLVMCommonConversion", @@ -11461,14 +11294,12 @@ cc_library( ":MaskableOpInterface", ":MemRefDialect", ":Pass", - ":Support", ":ToLLVMIRTranslation", - ":Transforms", + ":TransformUtils", ":VectorDialect", ":VectorTransforms", ":X86VectorDialect", ":X86VectorTransforms", - "//llvm:Core", "//llvm:Support", ], ) @@ -11477,7 +11308,6 @@ cc_library( name = "VectorToArmSME", srcs = glob([ "lib/Conversion/VectorToArmSME/*.cpp", - "lib/Conversion/VectorToArmSME/*.h", ]), hdrs = glob([ "include/mlir/Conversion/VectorToArmSME/*.h", @@ -11489,7 +11319,7 @@ cc_library( ":IR", ":MemRefDialect", ":Pass", - ":Transforms", + ":TransformUtils", "//llvm:Support", ], ) @@ -11498,7 +11328,6 @@ cc_library( name = "VectorToGPU", srcs = glob([ "lib/Conversion/VectorToGPU/*.cpp", - "lib/Conversion/VectorToGPU/*.h", ]), hdrs = glob([ "include/mlir/Conversion/VectorToGPU/*.h", @@ -11510,23 +11339,19 @@ cc_library( ":ArithDialect", ":ConversionPassIncGen", ":DialectUtils", - ":FuncDialect", - ":FuncToLLVM", ":GPUDialect", ":IR", - ":LLVMDialect", ":MemRefDialect", ":NVGPUDialect", ":NVGPUUtils", - ":NVVMDialect", ":Pass", ":SCFDialect", ":Support", + ":TransformUtils", ":Transforms", ":VectorDialect", ":VectorTransforms", ":VectorUtils", - "//llvm:Core", "//llvm:Support", ], ) @@ -11535,7 +11360,6 @@ cc_library( name = "VectorToSCF", srcs = glob([ "lib/Conversion/VectorToSCF/*.cpp", - "lib/Conversion/VectorToSCF/*.h", ]), hdrs = glob([ "include/mlir/Conversion/VectorToSCF/*.h", @@ -11543,23 +11367,17 @@ cc_library( includes = ["include"], deps = [ ":AffineDialect", - ":AffineUtils", ":ArithDialect", ":ConversionPassIncGen", - ":FuncDialect", - ":FuncToLLVM", ":IR", - ":LLVMDialect", ":MemRefDialect", ":Pass", ":SCFDialect", - ":Support", ":TensorDialect", + ":TransformUtils", ":Transforms", ":VectorDialect", ":VectorTransforms", - "//llvm:Core", - "//llvm:Support", ], ) @@ -11685,7 +11503,6 @@ cc_library( name = "TosaDialect", srcs = glob([ "lib/Dialect/Tosa/IR/*.cpp", - "lib/Dialect/Tosa/IR/*.h", "lib/Dialect/Tosa/Utils/*.cpp", "lib/Dialect/Tosa/Transforms/*.cpp", ]), @@ -11696,18 +11513,20 @@ cc_library( ]), includes = ["include"], deps = [ - ":Analysis", ":ArithDialect", + ":BytecodeOpInterface", ":Dialect", ":DialectUtils", ":FuncDialect", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":LoopLikeInterface", ":MeshDialect", ":MeshShardingInterface", ":Pass", ":QuantOps", + ":SideEffectInterfaces", ":Support", ":TensorDialect", ":TosaDialectBytecodeGen", @@ -11724,7 +11543,6 @@ cc_library( name = "TosaToArith", srcs = glob([ "lib/Conversion/TosaToArith/*.cpp", - "lib/Conversion/TosaToArith/*.h", ]), hdrs = glob([ "include/mlir/Conversion/TosaToArith/*.h", @@ -11736,11 +11554,10 @@ cc_library( deps = [ ":ArithDialect", ":ConversionPassIncGen", - ":FuncDialect", ":IR", ":Pass", ":TosaDialect", - ":Transforms", + ":TransformUtils", ], ) @@ -11748,7 +11565,6 @@ cc_library( name = "TosaToLinalg", srcs = glob([ "lib/Conversion/TosaToLinalg/*.cpp", - "lib/Conversion/TosaToLinalg/*.h", ]), hdrs = glob([ "include/mlir/Conversion/TosaToLinalg/*.h", @@ -11765,13 +11581,13 @@ cc_library( ":FuncDialect", ":IR", ":LinalgDialect", - ":LinalgUtils", ":MathDialect", ":Pass", ":SCFDialect", ":TensorDialect", ":TensorUtils", ":TosaDialect", + ":TransformUtils", ":Transforms", "//llvm:Support", ], @@ -11781,7 +11597,6 @@ cc_library( name = "TosaToMLProgram", srcs = glob([ "lib/Conversion/TosaToMLProgram/*.cpp", - "lib/Conversion/TosaToMLProgram/*.h", ]), hdrs = glob([ "include/mlir/Conversion/TosaToMLProgram/*.h", @@ -11792,12 +11607,11 @@ cc_library( ], deps = [ ":ConversionPassIncGen", - ":FuncDialect", ":IR", ":MLProgramDialect", ":Pass", ":TosaDialect", - ":Transforms", + ":TransformUtils", ], ) @@ -11805,7 +11619,6 @@ cc_library( name = "TosaToSCF", srcs = glob([ "lib/Conversion/TosaToSCF/*.cpp", - "lib/Conversion/TosaToSCF/*.h", ]), hdrs = glob([ "include/mlir/Conversion/TosaToSCF/*.h", @@ -11822,7 +11635,7 @@ cc_library( ":SCFDialect", ":TensorDialect", ":TosaDialect", - ":Transforms", + ":TransformUtils", ], ) @@ -11830,7 +11643,6 @@ cc_library( name = "TosaToTensor", srcs = glob([ "lib/Conversion/TosaToTensor/*.cpp", - "lib/Conversion/TosaToTensor/*.h", ]), hdrs = glob([ "include/mlir/Conversion/TosaToTensor/*.h", @@ -11843,13 +11655,21 @@ cc_library( ":ArithDialect", ":ArithUtils", ":ConversionPassIncGen", - ":FuncDialect", ":IR", ":Pass", ":TensorDialect", ":TensorUtils", ":TosaDialect", - ":Transforms", + ":TransformUtils", + ], +) + +td_library( + name = "TransformInterfacesTdFiles", + srcs = glob(["include/mlir/Dialect/Transform/Interfaces/*.td"]), + deps = [ + ":OpBaseTdFiles", + ":SideEffectInterfacesTdFiles", ], ) @@ -11862,6 +11682,7 @@ td_library( ":InferTypeOpInterfaceTdFiles", ":OpBaseTdFiles", ":SideEffectInterfacesTdFiles", + ":TransformInterfacesTdFiles", ], ) @@ -11893,17 +11714,17 @@ gentbl_cc_library( [ "-gen-op-interface-decls", ], - "include/mlir/Dialect/Transform/IR/MatchInterfaces.h.inc", + "include/mlir/Dialect/Transform/Interfaces/MatchInterfaces.h.inc", ), ( [ "-gen-op-interface-defs", ], - "include/mlir/Dialect/Transform/IR/MatchInterfaces.cpp.inc", + "include/mlir/Dialect/Transform/Interfaces/MatchInterfaces.cpp.inc", ), ], tblgen = ":mlir-tblgen", - td_file = "include/mlir/Dialect/Transform/IR/MatchInterfaces.td", + td_file = "include/mlir/Dialect/Transform/Interfaces/MatchInterfaces.td", deps = [ ":TransformDialectInterfacesIncGen", ":TransformDialectTdFiles", @@ -11917,29 +11738,29 @@ gentbl_cc_library( [ "-gen-op-interface-decls", ], - "include/mlir/Dialect/Transform/IR/TransformInterfaces.h.inc", + "include/mlir/Dialect/Transform/Interfaces/TransformInterfaces.h.inc", ), ( [ "-gen-op-interface-defs", ], - "include/mlir/Dialect/Transform/IR/TransformInterfaces.cpp.inc", + "include/mlir/Dialect/Transform/Interfaces/TransformInterfaces.cpp.inc", ), ( [ "-gen-type-interface-decls", ], - "include/mlir/Dialect/Transform/IR/TransformTypeInterfaces.h.inc", + "include/mlir/Dialect/Transform/Interfaces/TransformTypeInterfaces.h.inc", ), ( [ "-gen-type-interface-defs", ], - "include/mlir/Dialect/Transform/IR/TransformTypeInterfaces.cpp.inc", + "include/mlir/Dialect/Transform/Interfaces/TransformTypeInterfaces.cpp.inc", ), ], tblgen = ":mlir-tblgen", - td_file = "include/mlir/Dialect/Transform/IR/TransformInterfaces.td", + td_file = "include/mlir/Dialect/Transform/Interfaces/TransformInterfaces.td", deps = [":TransformDialectTdFiles"], ) @@ -12002,6 +11823,25 @@ gentbl_cc_library( deps = [":TransformDialectTdFiles"], ) +cc_library( + name = "TransformDialectInterfaces", + srcs = glob(["lib/Dialect/Transform/Interfaces/*.cpp"]), + hdrs = glob(["include/mlir/Dialect/Transform/Interfaces/*.h"]), + deps = [ + ":CastInterfaces", + ":IR", + ":Rewrite", + ":SideEffectInterfaces", + ":Support", + ":TransformDialectInterfacesIncGen", + ":TransformDialectMatchInterfacesIncGen", + ":TransformDialectUtils", + ":TransformUtils", + ":Transforms", + "//llvm:Support", + ], +) + cc_library( name = "TransformDialect", srcs = glob(["lib/Dialect/Transform/IR/*.cpp"]), @@ -12023,11 +11863,11 @@ cc_library( ":Support", ":TransformDialectEnumsIncGen", ":TransformDialectIncGen", - ":TransformDialectInterfacesIncGen", - ":TransformDialectMatchInterfacesIncGen", + ":TransformDialectInterfaces", ":TransformDialectUtils", ":TransformOpsIncGen", ":TransformTypesIncGen", + ":TransformUtils", ":Transforms", "//llvm:Support", ], @@ -12075,6 +11915,7 @@ cc_library( ":SideEffectInterfaces", ":Support", ":TransformDialect", + ":TransformDialectInterfaces", ":TransformPDLExtensionOpsIncGen", "//llvm:Support", ], @@ -12118,6 +11959,7 @@ cc_library( ":Support", ":TransformDebugExtensionOpsIncGen", ":TransformDialect", + ":TransformDialectInterfaces", "//llvm:Support", ], ) @@ -12162,7 +12004,9 @@ cc_library( ":SideEffectInterfaces", ":Support", ":TransformDialect", + ":TransformDialectInterfaces", ":TransformLoopExtensionOpsIncGen", + ":TransformUtils", ":Transforms", "//llvm:Support", ], @@ -12206,6 +12050,7 @@ cc_library( ":SideEffectInterfaces", ":Support", ":TransformDialect", + ":TransformDialectInterfaces", ":TransformDialectTransformsIncGen", "//llvm:Support", ], @@ -12217,7 +12062,6 @@ cc_library( hdrs = glob(["include/mlir/Dialect/Transform/Utils/*.h"]), includes = ["include"], deps = [ - ":DialectUtils", ":IR", ":Support", ":ViewLikeInterface", @@ -12304,19 +12148,20 @@ cc_library( srcs = glob( [ "lib/Dialect/Complex/IR/*.cpp", - "lib/Dialect/Complex/IR/*.h", ], ), hdrs = ["include/mlir/Dialect/Complex/IR/Complex.h"], includes = ["include"], deps = [ ":ArithDialect", + ":BytecodeOpInterface", ":ComplexAttributesIncGen", ":ComplexBaseIncGen", ":ComplexOpsIncGen", ":ConvertToLLVMInterface", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":SideEffectInterfaces", "//llvm:Support", ], @@ -12326,7 +12171,6 @@ cc_library( name = "ComplexToLLVM", srcs = glob([ "lib/Conversion/ComplexToLLVM/*.cpp", - "lib/Conversion/ComplexToLLVM/*.h", ]), hdrs = glob([ "include/mlir/Conversion/ComplexToLLVM/*.h", @@ -12338,15 +12182,9 @@ cc_library( ":ComplexDialect", ":ConversionPassIncGen", ":ConvertToLLVMInterface", - ":FuncDialect", - ":IR", ":LLVMCommonConversion", ":LLVMDialect", ":Pass", - ":Support", - ":Transforms", - "//llvm:Core", - "//llvm:Support", ], ) @@ -12354,7 +12192,6 @@ cc_library( name = "ComplexToLibm", srcs = glob([ "lib/Conversion/ComplexToLibm/*.cpp", - "lib/Conversion/ComplexToLibm/*.h", ]), hdrs = glob([ "include/mlir/Conversion/ComplexToLibm/*.h", @@ -12363,14 +12200,10 @@ cc_library( deps = [ ":ComplexDialect", ":ConversionPassIncGen", - ":DialectUtils", ":FuncDialect", ":IR", ":Pass", - ":Support", - ":Transforms", - "//llvm:Core", - "//llvm:Support", + ":TransformUtils", ], ) @@ -12378,7 +12211,6 @@ cc_library( name = "ComplexToSPIRV", srcs = glob([ "lib/Conversion/ComplexToSPIRV/*.cpp", - "lib/Conversion/ComplexToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/ComplexToSPIRV/*.h", @@ -12387,14 +12219,10 @@ cc_library( deps = [ ":ComplexDialect", ":ConversionPassIncGen", - ":IR", ":Pass", - ":SPIRVCommonConversion", ":SPIRVConversion", ":SPIRVDialect", - ":Support", - ":Transforms", - "//llvm:Core", + ":TransformUtils", "//llvm:Support", ], ) @@ -12403,7 +12231,6 @@ cc_library( name = "ComplexToStandard", srcs = glob([ "lib/Conversion/ComplexToStandard/*.cpp", - "lib/Conversion/ComplexToStandard/*.h", ]), hdrs = glob([ "include/mlir/Conversion/ComplexToStandard/*.h", @@ -12413,11 +12240,10 @@ cc_library( ":ArithDialect", ":ComplexDialect", ":ConversionPassIncGen", - ":FuncDialect", ":IR", ":MathDialect", ":Pass", - ":Transforms", + ":TransformUtils", ], ) @@ -12562,13 +12388,15 @@ gentbl_cc_library( cc_library( name = "ArithDialect", srcs = [ + "include/mlir/Interfaces/ValueBoundsOpInterface.h", "lib/Dialect/Arith/IR/ArithDialect.cpp", "lib/Dialect/Arith/IR/ArithOps.cpp", "lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp", - ], + ] + glob([ + "include/mlir/Analysis/**/*.h", + ]), hdrs = [ "include/mlir/Dialect/Arith/IR/Arith.h", - "include/mlir/Transforms/InliningUtils.h", ], includes = ["include"], deps = [ @@ -12576,15 +12404,24 @@ cc_library( ":ArithCanonicalizationIncGen", ":ArithOpsIncGen", ":ArithOpsInterfacesIncGen", + ":BufferizationInterfaces", + ":BytecodeOpInterface", + ":CallOpInterfaces", ":CastInterfaces", ":CommonFolders", + ":ControlFlowInterfaces", ":ConvertToLLVMInterface", + ":DestinationStyleOpInterface", ":IR", ":InferIntRangeCommon", ":InferIntRangeInterface", ":InferTypeOpInterface", + ":InliningUtils", + ":Pass", + ":SideEffectInterfaces", ":Support", ":UBDialect", + ":ValueBoundsOpInterfaceIncGen", ":VectorInterfaces", "//llvm:Support", ], @@ -12610,7 +12447,6 @@ cc_library( name = "ArithTransforms", srcs = glob([ "lib/Dialect/Arith/Transforms/*.cpp", - "lib/Dialect/Arith/Transforms/*.h", ]), hdrs = glob([ "include/mlir/Dialect/Arith/Transforms/*.h", @@ -12622,17 +12458,16 @@ cc_library( ":ArithPassIncGen", ":ArithUtils", ":BufferizationDialect", + ":BufferizationInterfaces", ":BufferizationTransforms", ":FuncDialect", ":FuncTransforms", ":IR", - ":InferIntRangeInterface", ":MemRefDialect", ":Pass", ":Support", ":TensorDialect", ":TransformUtils", - ":Transforms", ":ValueBoundsOpInterface", ":VectorDialect", "//llvm:Support", @@ -12731,7 +12566,6 @@ cc_library( srcs = glob( [ "lib/Dialect/Math/IR/*.cpp", - "lib/Dialect/Math/IR/*.h", ], ), hdrs = [ @@ -12740,16 +12574,17 @@ cc_library( includes = ["include"], deps = [ ":ArithDialect", + ":BytecodeOpInterface", ":CommonFolders", ":ConvertToLLVMInterface", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":MathBaseIncGen", ":MathOpsIncGen", ":SideEffectInterfaces", ":UBDialect", ":VectorInterfaces", - "//llvm:Support", ], ) @@ -12757,7 +12592,6 @@ cc_library( name = "MathTransforms", srcs = glob([ "lib/Dialect/Math/Transforms/*.cpp", - "lib/Dialect/Math/Transforms/*.h", ]), hdrs = glob(["include/mlir/Dialect/Math/Transforms/*.h"]), includes = ["include"], @@ -12769,7 +12603,7 @@ cc_library( ":MathPassIncGen", ":Pass", ":SCFDialect", - ":Transforms", + ":TransformUtils", ":VectorDialect", ":VectorUtils", ":X86VectorDialect", @@ -12781,7 +12615,6 @@ cc_library( name = "MathToLibm", srcs = glob([ "lib/Conversion/MathToLibm/*.cpp", - "lib/Conversion/MathToLibm/*.h", ]), hdrs = glob([ "include/mlir/Conversion/MathToLibm/*.h", @@ -12796,12 +12629,8 @@ cc_library( ":LLVMDialect", ":MathDialect", ":Pass", - ":Support", - ":Transforms", + ":TransformUtils", ":VectorDialect", - ":VectorUtils", - "//llvm:Core", - "//llvm:Support", ], ) @@ -12872,7 +12701,6 @@ cc_library( srcs = glob( [ "lib/Dialect/MemRef/IR/*.cpp", - "lib/Dialect/MemRef/IR/*.h", ], ), hdrs = [ @@ -12882,25 +12710,29 @@ cc_library( ], includes = ["include"], deps = [ + ":AllocationOpInterface", ":ArithDialect", ":ArithUtils", + ":BytecodeOpInterface", + ":CallOpInterfaces", ":CastInterfaces", - ":ComplexDialect", ":ControlFlowInterfaces", ":ConvertToLLVMInterface", ":CopyOpInterface", ":DialectUtils", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":MemRefBaseIncGen", ":MemRefOpsIncGen", ":MemorySlotInterfaces", + ":RuntimeVerifiableOpInterface", ":ShapedOpInterfaces", + ":SideEffectInterfaces", ":Support", ":ValueBoundsOpInterface", ":ViewLikeInterface", "//llvm:Support", - "//llvm:TargetParser", ], ) @@ -12944,7 +12776,6 @@ cc_library( srcs = glob( [ "lib/Dialect/MemRef/Transforms/*.cpp", - "lib/Dialect/MemRef/Transforms/*.h", ], ), hdrs = glob(["include/mlir/Dialect/MemRef/Transforms/*.h"]), @@ -12958,6 +12789,7 @@ cc_library( ":ArithTransforms", ":ArithUtils", ":BufferizationDialect", + ":BufferizationInterfaces", ":ControlFlowDialect", ":DialectUtils", ":FuncDialect", @@ -12974,7 +12806,7 @@ cc_library( ":SCFDialect", ":Support", ":TensorDialect", - ":Transforms", + ":TransformUtils", ":ValueBoundsOpInterface", ":VectorDialect", "//llvm:Support", @@ -13020,6 +12852,7 @@ cc_library( ":AffineDialect", ":Analysis", ":ArithDialect", + ":BytecodeOpInterface", ":IR", ":LLVMCommonConversion", ":LoopLikeInterface", @@ -13030,6 +12863,7 @@ cc_library( ":NVGPUDialect", ":SCFDialect", ":TransformDialect", + ":TransformDialectInterfaces", ":TransformUtils", ":VectorDialect", ":VectorTransforms", @@ -13142,14 +12976,16 @@ cc_library( hdrs = glob(["include/mlir/Dialect/MLProgram/IR/*.h"]), includes = ["include"], deps = [ + ":BytecodeOpInterface", + ":CallOpInterfaces", ":ControlFlowInterfaces", ":FunctionInterfaces", ":IR", + ":InliningUtils", ":MLProgramAttributesIncGen", ":MLProgramOpsIncGen", ":MLProgramTypesIncGen", - ":Pass", - ":Support", + ":SideEffectInterfaces", "//llvm:Support", ], ) @@ -13164,7 +13000,7 @@ cc_library( ]), includes = ["include"], deps = [ - ":BufferizationDialect", + ":BufferizationInterfaces", ":FuncDialect", ":IR", ":MLProgramDialect", @@ -13283,14 +13119,12 @@ cc_library( hdrs = glob(["include/mlir/Dialect/MPI/IR/*.h"]), includes = ["include"], deps = [ - ":Dialect", + ":BytecodeOpInterface", ":IR", - ":InferTypeOpInterface", ":MPIAttrsIncGen", ":MPIIncGen", ":MPIOpsIncGen", ":MPITypesIncGen", - ":SideEffectInterfaces", "//llvm:Support", ], ) @@ -13344,6 +13178,7 @@ td_library( includes = ["include"], deps = [ ":AllocationOpInterfaceTdFiles", + ":BufferViewFlowOpInterfaceTdFiles", ":BufferizableOpInterfaceTdFiles", ":CopyOpInterfaceTdFiles", ":DestinationStyleOpInterfaceTdFiles", @@ -13448,17 +13283,17 @@ cc_library( deps = [ ":BufferizationDialect", ":BufferizationEnumsIncGen", + ":BufferizationInterfaces", ":BufferizationTransformOpsIncGen", ":BufferizationTransforms", + ":BytecodeOpInterface", ":FunctionInterfaces", ":IR", ":LinalgDialect", ":MemRefDialect", - ":Parser", - ":SideEffectInterfaces", ":TensorDialect", ":TransformDialect", - "//llvm:Support", + ":TransformDialectInterfaces", ], ) @@ -13481,18 +13316,39 @@ gentbl_cc_library( ], ) +cc_library( + name = "BufferizationInterfaces", + srcs = [ + "include/mlir/Analysis/Liveness.h", + ], + hdrs = [ + "include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h", + "include/mlir/Dialect/Bufferization/IR/BufferViewFlowOpInterface.h", + "include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h", + ], + includes = ["include"], + deps = [ + ":BufferDeallocationOpInterfaceIncGen", + ":BufferViewFlowOpInterfaceIncGen", + ":BufferizableOpInterfaceIncGen", + ":BufferizationEnumsIncGen", + ":IR", + ":Support", + "//llvm:Support", + ], +) + cc_library( name = "BufferizationDialect", srcs = [ "lib/Dialect/Bufferization/IR/BufferDeallocationOpInterface.cpp", + "lib/Dialect/Bufferization/IR/BufferViewFlowOpInterface.cpp", "lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp", "lib/Dialect/Bufferization/IR/BufferizationDialect.cpp", "lib/Dialect/Bufferization/IR/BufferizationOps.cpp", "lib/Dialect/Bufferization/IR/UnstructuredControlFlow.cpp", ], hdrs = [ - "include/mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h", - "include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h", "include/mlir/Dialect/Bufferization/IR/Bufferization.h", "include/mlir/Dialect/Bufferization/IR/DstBufferizableOpInterfaceImpl.h", "include/mlir/Dialect/Bufferization/IR/UnstructuredControlFlow.h", @@ -13501,13 +13357,14 @@ cc_library( deps = [ ":AffineDialect", ":AllocationOpInterface", - ":Analysis", ":ArithDialect", ":BufferDeallocationOpInterfaceIncGen", + ":BufferViewFlowOpInterfaceIncGen", ":BufferizableOpInterfaceIncGen", ":BufferizationBaseIncGen", - ":BufferizationEnumsIncGen", + ":BufferizationInterfaces", ":BufferizationOpsIncGen", + ":BytecodeOpInterface", ":ControlFlowInterfaces", ":CopyOpInterface", ":DestinationStyleOpInterface", @@ -13515,10 +13372,10 @@ cc_library( ":FunctionInterfaces", ":IR", ":InferTypeOpInterface", + ":InliningUtils", ":MemRefDialect", ":SparseTensorDialect", ":SubsetOpInterface", - ":Support", ":TensorDialect", "//llvm:Support", ], @@ -13545,7 +13402,6 @@ cc_library( srcs = glob( [ "lib/Dialect/Bufferization/Transforms/*.cpp", - "lib/Dialect/Bufferization/Transforms/*.h", ], ), hdrs = glob(["include/mlir/Dialect/Bufferization/Transforms/*.h"]), @@ -13555,11 +13411,13 @@ cc_library( ":Analysis", ":ArithDialect", ":BufferizationDialect", - ":BufferizationEnumsIncGen", + ":BufferizationInterfaces", ":BufferizationPassIncGen", + ":CallOpInterfaces", ":ControlFlowDialect", ":ControlFlowInterfaces", ":FuncDialect", + ":FunctionInterfaces", ":IR", ":LoopLikeInterface", ":MemRefDialect", @@ -13570,6 +13428,7 @@ cc_library( ":SubsetOpInterface", ":Support", ":TensorDialect", + ":TransformUtils", ":Transforms", ":ViewLikeInterface", "//llvm:Support", @@ -13596,7 +13455,7 @@ cc_library( ":Pass", ":SCFDialect", ":Support", - ":Transforms", + ":TransformUtils", ], ) @@ -13606,8 +13465,7 @@ cc_library( hdrs = ["include/mlir/Dialect/Bufferization/Pipelines/Passes.h"], includes = ["include"], deps = [ - ":BufferizationDialect", - ":BufferizationToMemRef", + ":BufferizationInterfaces", ":BufferizationTransforms", ":FuncDialect", ":MemRefTransforms", @@ -13700,13 +13558,11 @@ cc_library( cc_library( name = "MlirReduceLib", srcs = ["lib/Tools/mlir-reduce/MlirReduceMain.cpp"], - hdrs = [ - "include/mlir/Tools/ParseUtilities.h", - "include/mlir/Tools/mlir-reduce/MlirReduceMain.h", - ], + hdrs = ["include/mlir/Tools/mlir-reduce/MlirReduceMain.h"], includes = ["include"], deps = [ ":IR", + ":ParseUtilities", ":Parser", ":Pass", ":Reducer", @@ -13736,7 +13592,6 @@ cc_library( srcs = glob( [ "lib/Tools/PDLL/ODS/*.cpp", - "lib/Tools/PDLL/ODS/*.h", ], ), hdrs = glob(["include/mlir/Tools/PDLL/ODS/*.h"]), @@ -13744,7 +13599,6 @@ cc_library( deps = [ ":Support", "//llvm:Support", - "//llvm:TargetParser", ], ) @@ -13761,7 +13615,6 @@ cc_library( deps = [ ":Support", "//llvm:Support", - "//llvm:TargetParser", ], ) @@ -13770,7 +13623,6 @@ cc_library( srcs = glob( [ "lib/Tools/PDLL/CodeGen/*.cpp", - "lib/Tools/PDLL/CodeGen/*.h", ], ), hdrs = glob(["include/mlir/Tools/PDLL/CodeGen/*.h"]), @@ -13912,14 +13764,15 @@ gentbl_cc_library( cc_library( name = "UBDialect", srcs = [ - "include/mlir/Transforms/InliningUtils.h", "lib/Dialect/UB/IR/UBOps.cpp", ], hdrs = ["include/mlir/Dialect/UB/IR/UBOps.h"], includes = ["include"], deps = [ + ":BytecodeOpInterface", ":ConvertToLLVMInterface", ":IR", + ":InliningUtils", ":SideEffectInterfaces", ":UBOpsIncGen", ":UBOpsInterfacesIncGen", @@ -13931,7 +13784,6 @@ cc_library( name = "UBToLLVM", srcs = glob([ "lib/Conversion/UBToLLVM/*.cpp", - "lib/Conversion/UBToLLVM/*.h", ]), hdrs = glob([ "include/mlir/Conversion/UBToLLVM/*.h", @@ -13952,7 +13804,6 @@ cc_library( name = "UBToSPIRV", srcs = glob([ "lib/Conversion/UBToSPIRV/*.cpp", - "lib/Conversion/UBToSPIRV/*.h", ]), hdrs = glob([ "include/mlir/Conversion/UBToSPIRV/*.h", @@ -13964,7 +13815,6 @@ cc_library( ":SPIRVConversion", ":SPIRVDialect", ":UBDialect", - "//llvm:Core", ], ) @@ -13974,6 +13824,7 @@ cc_library( hdrs = ["include/mlir/Dialect/LLVMIR/VCIXDialect.h"], includes = ["include"], deps = [ + ":BytecodeOpInterface", ":GPUDialect", ":IR", ":LLVMDialect", diff --git a/utils/bazel/llvm-project-overlay/mlir/examples/toy/Ch4/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/examples/toy/Ch4/BUILD.bazel index b8c5a59cd14d52ae49992897ffdacde36f45a53d..68639df2aa2ca5d3696bae742c88128466907b13 100644 --- a/utils/bazel/llvm-project-overlay/mlir/examples/toy/Ch4/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/examples/toy/Ch4/BUILD.bazel @@ -101,6 +101,7 @@ cc_binary( "//mlir:CastInterfaces", "//mlir:FunctionInterfaces", "//mlir:IR", + "//mlir:InliningUtils", "//mlir:Parser", "//mlir:Pass", "//mlir:SideEffectInterfaces", diff --git a/utils/bazel/llvm-project-overlay/mlir/examples/toy/Ch5/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/examples/toy/Ch5/BUILD.bazel index ce48e249489d3521c3d587e358dc888bb13cffae..9ce23b5d975474bb73929c8204193872f0920428 100644 --- a/utils/bazel/llvm-project-overlay/mlir/examples/toy/Ch5/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/examples/toy/Ch5/BUILD.bazel @@ -102,11 +102,13 @@ cc_binary( "//mlir:Analysis", "//mlir:ArithDialect", "//mlir:BytecodeReader", + "//mlir:CallOpInterfaces", "//mlir:CastInterfaces", "//mlir:FuncDialect", "//mlir:FuncExtensions", "//mlir:FunctionInterfaces", "//mlir:IR", + "//mlir:InliningUtils", "//mlir:MemRefDialect", "//mlir:Parser", "//mlir:Pass", diff --git a/utils/bazel/llvm-project-overlay/mlir/examples/toy/Ch6/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/examples/toy/Ch6/BUILD.bazel index 286c080656456ea4c149e5a9dc49ae9e331fbab2..86925aa0662c7ea53b301c5caaa51f1332f60de7 100644 --- a/utils/bazel/llvm-project-overlay/mlir/examples/toy/Ch6/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/examples/toy/Ch6/BUILD.bazel @@ -108,6 +108,7 @@ cc_binary( "//mlir:ArithToLLVM", "//mlir:BuiltinToLLVMIRTranslation", "//mlir:BytecodeReader", + "//mlir:CallOpInterfaces", "//mlir:CastInterfaces", "//mlir:ControlFlowToLLVM", "//mlir:ExecutionEngine", @@ -117,6 +118,7 @@ cc_binary( "//mlir:FuncToLLVM", "//mlir:FunctionInterfaces", "//mlir:IR", + "//mlir:InliningUtils", "//mlir:LLVMCommonConversion", "//mlir:LLVMDialect", "//mlir:LLVMIRTransforms", diff --git a/utils/bazel/llvm-project-overlay/mlir/examples/toy/Ch7/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/examples/toy/Ch7/BUILD.bazel index f4037cab03f6a8b1fcfda05d383854ee8fff4cf0..bf9ab79529b8d9dfa9767058284fb21f4be6c859 100644 --- a/utils/bazel/llvm-project-overlay/mlir/examples/toy/Ch7/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/examples/toy/Ch7/BUILD.bazel @@ -108,6 +108,7 @@ cc_binary( "//mlir:ArithToLLVM", "//mlir:BuiltinToLLVMIRTranslation", "//mlir:BytecodeReader", + "//mlir:CallOpInterfaces", "//mlir:CastInterfaces", "//mlir:ControlFlowToLLVM", "//mlir:ExecutionEngine", @@ -117,6 +118,7 @@ cc_binary( "//mlir:FuncToLLVM", "//mlir:FunctionInterfaces", "//mlir:IR", + "//mlir:InliningUtils", "//mlir:LLVMCommonConversion", "//mlir:LLVMDialect", "//mlir:LLVMIRTransforms", diff --git a/utils/bazel/llvm-project-overlay/mlir/python/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/python/BUILD.bazel index 0c3ed22e73601825ee995aa94ea2f30ba4318c4f..d6b0832f4c1a9bb02f7abb7bc928c6e27fc439e8 100644 --- a/utils/bazel/llvm-project-overlay/mlir/python/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/python/BUILD.bazel @@ -492,6 +492,44 @@ filegroup( ], ) +##---------------------------------------------------------------------------## +# Index dialect. +##---------------------------------------------------------------------------## + +gentbl_filegroup( + name = "IndexOpsPyGen", + tbl_outs = [ + ( + [ + "-gen-python-enum-bindings", + "-bind-dialect=index", + ], + "mlir/dialects/_index_enum_gen.py", + ), + ( + [ + "-gen-python-op-bindings", + "-bind-dialect=index", + ], + "mlir/dialects/_index_ops_gen.py", + ), + ], + tblgen = "//mlir:mlir-tblgen", + td_file = "mlir/dialects/IndexOps.td", + deps = [ + "//mlir:IndexOpsTdFiles", + "//mlir:OpBaseTdFiles", + ], +) + +filegroup( + name = "IndexOpsPyFiles", + srcs = [ + "mlir/dialects/index.py", + ":IndexOpsPyGen", + ], +) + ##---------------------------------------------------------------------------## # Math dialect. ##---------------------------------------------------------------------------## diff --git a/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel index 91706af935ac5e805a949a93c7ed088712753615..30130131c46514a0a9110de17dff2565e43b0f55 100644 --- a/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel @@ -94,12 +94,14 @@ cc_library( "//mlir:AffineAnalysis", "//mlir:AffineDialect", "//mlir:Analysis", + "//mlir:CallOpInterfaces", "//mlir:ControlFlowInterfaces", "//mlir:FuncDialect", "//mlir:FunctionInterfaces", "//mlir:IR", "//mlir:MemRefDialect", "//mlir:Pass", + "//mlir:SideEffectInterfaces", "//mlir:Support", ], ) @@ -356,11 +358,13 @@ cc_library( deps = [ ":TestTransformDialectExtensionIncGen", "//llvm:Support", + "//mlir:BytecodeOpInterface", "//mlir:IR", "//mlir:PDLDialect", "//mlir:Pass", "//mlir:TransformDebugExtension", "//mlir:TransformDialect", + "//mlir:TransformDialectInterfaces", "//mlir:TransformDialectTransforms", "//mlir:TransformPDLExtension", ], @@ -385,6 +389,8 @@ cc_library( ":TestTypeDefsIncGen", "//llvm:Support", "//mlir:ArithDialect", + "//mlir:BytecodeOpInterface", + "//mlir:CallOpInterfaces", "//mlir:ControlFlowInterfaces", "//mlir:CopyOpInterface", "//mlir:DLTIDialect", @@ -399,6 +405,7 @@ cc_library( "//mlir:IR", "//mlir:InferIntRangeInterface", "//mlir:InferTypeOpInterface", + "//mlir:InliningUtils", "//mlir:LLVMDialect", "//mlir:LinalgDialect", "//mlir:LoopLikeInterface", @@ -435,6 +442,7 @@ cc_library( "//llvm:Support", "//mlir:Analysis", "//mlir:ArithDialect", + "//mlir:BytecodeOpInterface", "//mlir:BytecodeReader", "//mlir:BytecodeWriter", "//mlir:FuncDialect", @@ -505,6 +513,7 @@ cc_library( "//mlir:TensorTilingInterfaceImpl", "//mlir:TilingInterface", "//mlir:TransformDialect", + "//mlir:TransformDialectInterfaces", "//mlir:Transforms", ], ) @@ -533,6 +542,7 @@ cc_library( "//mlir:Pass", "//mlir:Support", "//mlir:TransformUtils", + "//mlir:Transforms", ], ) @@ -562,6 +572,7 @@ cc_library( "//mlir:ArithDialect", "//mlir:FuncDialect", "//mlir:IR", + "//mlir:InliningUtils", "//mlir:MathDialect", "//mlir:PDLDialect", "//mlir:PDLInterpDialect", @@ -569,8 +580,10 @@ cc_library( "//mlir:Pass", "//mlir:SCFDialect", "//mlir:SPIRVDialect", + "//mlir:SideEffectInterfaces", "//mlir:Support", "//mlir:TransformUtils", + "//mlir:Transforms", ], ) @@ -601,6 +614,7 @@ cc_library( "//mlir:SCFDialect", "//mlir:SCFTransforms", "//mlir:TransformUtils", + "//mlir:Transforms", ], ) @@ -612,6 +626,7 @@ cc_library( "//mlir:FuncDialect", "//mlir:Pass", "//mlir:SPIRVDialect", + "//mlir:TransformUtils", "//mlir:Transforms", "//mlir:VectorDialect", "//mlir:VectorToSPIRV", @@ -639,6 +654,7 @@ cc_library( "//mlir:SCFDialect", "//mlir:Support", "//mlir:TensorDialect", + "//mlir:TransformUtils", "//mlir:Transforms", "//mlir:ValueBoundsOpInterface", "//mlir:VectorDialect", @@ -771,6 +787,7 @@ cc_library( "//mlir:Pass", "//mlir:SCFDialect", "//mlir:TransformUtils", + "//mlir:Transforms", "//mlir:VectorDialect", "//mlir:X86VectorDialect", ], @@ -787,6 +804,7 @@ cc_library( "//mlir:MathDialect", "//mlir:Pass", "//mlir:TransformUtils", + "//mlir:Transforms", "//mlir:VCIXDialect", "//mlir:VectorDialect", ], @@ -805,6 +823,7 @@ cc_library( "//mlir:MemRefDialect", "//mlir:MemRefTransforms", "//mlir:Pass", + "//mlir:TransformUtils", "//mlir:Transforms", "//mlir:VectorDialect", "//mlir:VectorTransforms", @@ -814,7 +833,6 @@ cc_library( cc_library( name = "TestMesh", srcs = glob(["lib/Dialect/Mesh/**/*.cpp"]), - hdrs = glob(["lib/Dialect/Mesh/**/*.h"]), includes = ["lib/Dialect/Test"], deps = [ ":TestDialect", @@ -827,6 +845,7 @@ cc_library( "//mlir:Pass", "//mlir:SPIRVDialect", "//mlir:Support", + "//mlir:TransformUtils", "//mlir:Transforms", ], ) @@ -851,6 +870,7 @@ cc_library( "//mlir:SCFDialect", "//mlir:Support", "//mlir:TransformUtils", + "//mlir:Transforms", ], ) @@ -870,6 +890,7 @@ cc_library( "//mlir:SCFTransforms", "//mlir:SCFUtils", "//mlir:TransformUtils", + "//mlir:Transforms", ], ) @@ -884,6 +905,7 @@ cc_library( "//mlir:LLVMDialect", "//mlir:MathDialect", "//mlir:Pass", + "//mlir:TransformUtils", "//mlir:Transforms", "//mlir:VectorDialect", ], @@ -900,6 +922,7 @@ cc_library( "//mlir:IR", "//mlir:Pass", "//mlir:Support", + "//mlir:TransformUtils", "//mlir:Transforms", ], ) @@ -945,6 +968,7 @@ cc_library( "//mlir:LLVMCommonConversion", "//mlir:LLVMDialect", "//mlir:Pass", + "//mlir:TransformUtils", "//mlir:Transforms", ], ) @@ -995,6 +1019,7 @@ cc_library( "//mlir:IR", "//mlir:Pass", "//mlir:TransformUtils", + "//mlir:Transforms", ], ) @@ -1010,6 +1035,8 @@ cc_library( "//mlir:TensorDialect", "//mlir:TensorTransforms", "//mlir:TransformDialect", + "//mlir:TransformDialectInterfaces", + "//mlir:TransformUtils", "//mlir:Transforms", ], ) @@ -1034,6 +1061,7 @@ cc_library( "//mlir:Support", "//mlir:TensorDialect", "//mlir:TransformUtils", + "//mlir:Transforms", "//mlir:VectorDialect", "//mlir:VectorToSCF", "//mlir:VectorTransforms", @@ -1041,18 +1069,6 @@ cc_library( ], ) -cc_library( - name = "TestTypeDialect", - srcs = glob([ - "lib/Dialect/LLVMIR/*.cpp", - ]), - deps = [ - ":TestDialect", - "//mlir:IR", - "//mlir:LLVMDialect", - ], -) - cc_library( name = "TestTosaDialect", srcs = glob([ @@ -1064,6 +1080,7 @@ cc_library( "//mlir:Pass", "//mlir:TensorDialect", "//mlir:TosaDialect", + "//mlir:TransformUtils", "//mlir:Transforms", ], ) @@ -1120,5 +1137,6 @@ cc_library( "//mlir:Pass", "//mlir:Support", "//mlir:TransformUtils", + "//mlir:Transforms", ], ) diff --git a/utils/bazel/llvm-project-overlay/mlir/unittests/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/unittests/BUILD.bazel index a749a11096c372a4f23d36f8845a1c494944202b..7172beb4de9a62a59d0c995226fecbbc7353bd92 100644 --- a/utils/bazel/llvm-project-overlay/mlir/unittests/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/unittests/BUILD.bazel @@ -16,7 +16,6 @@ cc_test( size = "small", srcs = glob([ "Debug/*.cpp", - "Debug/*.h", ]), deps = [ "//llvm:Support", @@ -35,11 +34,11 @@ cc_test( size = "small", srcs = glob([ "IR/*.cpp", - "IR/*.h", ]), deps = [ "//llvm:Support", "//mlir:BytecodeReader", + "//mlir:CallOpInterfaces", "//mlir:FunctionInterfaces", "//mlir:IR", "//mlir:Parser", @@ -56,13 +55,12 @@ cc_test( size = "small", srcs = glob([ "Interfaces/*.cpp", - "Interfaces/*.h", ]), deps = [ "//llvm:Support", "//llvm:TestingSupport", - "//mlir:BytecodeReader", "//mlir:ArithDialect", + "//mlir:BytecodeReader", "//mlir:ControlFlowInterfaces", "//mlir:DLTIDialect", "//mlir:DataLayoutInterfaces", @@ -81,7 +79,6 @@ cc_test( size = "small", srcs = glob([ "Support/*.cpp", - "Support/*.h", ]), deps = [ "//llvm:Support", @@ -97,7 +94,6 @@ cc_test( size = "small", srcs = glob([ "Pass/*.cpp", - "Pass/*.h", ]), deps = [ "//llvm:Support", @@ -117,7 +113,6 @@ cc_test( size = "small", srcs = glob([ "Rewrite/*.cpp", - "Rewrite/*.h", ]), deps = [ "//mlir:IR", @@ -133,7 +128,6 @@ cc_test( size = "small", srcs = glob([ "Dialect/*.cpp", - "Dialect/*.h", ]), deps = [ "//llvm:Support", @@ -148,7 +142,6 @@ cc_test( size = "small", srcs = glob([ "Dialect/MemRef/*.cpp", - "Dialect/MemRef/*.h", ]), deps = [ "//llvm:TestingSupport", @@ -160,27 +153,11 @@ cc_test( ], ) -cc_test( - name = "quantops_tests", - size = "small", - srcs = glob([ - "Dialect/Quant/*.cpp", - "Dialect/Quant/*.h", - ]), - deps = [ - "//llvm:TestingSupport", - "//mlir:QuantOps", - "//mlir:Transforms", - "//third-party/unittest:gtest_main", - ], -) - cc_test( name = "scf_tests", size = "small", srcs = glob([ "Dialect/SCF/*.cpp", - "Dialect/SCF/*.h", ]), deps = [ "//mlir:ArithDialect", @@ -199,7 +176,6 @@ cc_test( size = "small", srcs = glob([ "Dialect/SparseTensor/*.cpp", - "Dialect/SparseTensor/*.h", ]), deps = [ "//llvm:Support", @@ -217,7 +193,6 @@ cc_test( size = "small", srcs = glob([ "Dialect/SPIRV/*.cpp", - "Dialect/SPIRV/*.h", ]), deps = [ "//llvm:Support", @@ -237,7 +212,6 @@ cc_test( size = "small", srcs = glob([ "Dialect/Transform/*.cpp", - "Dialect/Transform/*.h", ]), deps = [ "//llvm:Support", @@ -263,7 +237,6 @@ cc_test( size = "small", srcs = glob([ "Dialect/Utils/*.cpp", - "Dialect/Utils/*.h", ]), deps = [ "//llvm:Support", @@ -316,7 +289,6 @@ cc_test( size = "small", srcs = glob([ "TableGen/*.cpp", - "TableGen/*.h", ]) + [ "TableGen/EnumsGenTest.cpp.inc", "TableGen/EnumsGenTest.h.inc", @@ -342,7 +314,6 @@ cc_test( size = "small", srcs = glob([ "Transforms/*.cpp", - "Transforms/*.h", ]), deps = [ "//mlir:AffineAnalysis", @@ -362,8 +333,6 @@ cc_test( name = "analysis_tests", size = "small", srcs = glob([ - "Analysis/*.cpp", - "Analysis/*.h", "Analysis/*/*.cpp", "Analysis/*/*.h", ]), @@ -386,9 +355,6 @@ cc_test( size = "small", srcs = glob([ "Bytecode/*.cpp", - "Bytecode/*.h", - "Bytecode/*/*.cpp", - "Bytecode/*/*.h", ]), deps = [ "//llvm:Support", @@ -407,10 +373,7 @@ cc_test( name = "conversion_tests", size = "small", srcs = glob([ - "Conversion/*.cpp", - "Conversion/*.h", "Conversion/*/*.cpp", - "Conversion/*/*.h", ]), deps = [ "//mlir:ArithDialect", diff --git a/utils/bazel/third_party_build/pfm.BUILD b/utils/bazel/third_party_build/pfm.BUILD index fe908d4744dae6e33b41853ff9ff249aab41fc93..dba7464d17df3e2885e827ebbff7d1ad9530e58f 100644 --- a/utils/bazel/third_party_build/pfm.BUILD +++ b/utils/bazel/third_party_build/pfm.BUILD @@ -14,8 +14,12 @@ make_variant( copts = ["-w"], lib_name = "libpfm", lib_source = ":sources", + target_compatible_with = select({ + "@platforms//os:linux": [], + "//conditions:default": ["@platforms//:incompatible"], + }), toolchain = "@rules_foreign_cc//toolchains:preinstalled_autoconf_toolchain", - visibility = ["//visibility:public"], + visibility = ["//visibility:private"], ) alias( @@ -27,5 +31,9 @@ alias( cc_library( name = "pfm_system", linkopts = ["-lpfm"], + target_compatible_with = select({ + "@platforms//os:linux": [], + "//conditions:default": ["@platforms//:incompatible"], + }), visibility = ["//visibility:public"], )